From c7b5ebbddf7bcd3651947760f423e3783bbe6573 Mon Sep 17 00:00:00 2001
From: Marc Fiuczynski <mef@cs.princeton.edu>
Date: Fri, 21 Jan 2005 03:50:53 +0000
Subject: [PATCH] vserver 1.9.3

---
 CREDITS                                       |  156 +-
 Documentation/CodingStyle                     |    4 +-
 Documentation/DMA-API.txt                     |   79 +
 Documentation/DocBook/Makefile                |    4 +-
 Documentation/DocBook/gadget.tmpl             |  245 +-
 Documentation/DocBook/kernel-hacking.tmpl     |    4 +-
 Documentation/DocBook/mousedrivers.tmpl       |    1 -
 Documentation/DocBook/usb.tmpl                |    1 +
 Documentation/IPMI.txt                        |   30 +
 Documentation/cachetlb.txt                    |    4 -
 Documentation/cdrom/cdrom-standard.tex        |   12 +-
 Documentation/crypto/api-intro.txt            |    4 +
 Documentation/devices.txt                     |  120 +-
 Documentation/driver-model/bus.txt            |   74 +-
 Documentation/filesystems/Locking             |   29 +-
 Documentation/filesystems/ext2.txt            |   34 +-
 Documentation/filesystems/ext3.txt            |   72 +-
 Documentation/filesystems/ntfs.txt            |   33 +-
 Documentation/filesystems/proc.txt            |   45 +-
 Documentation/filesystems/tmpfs.txt           |   12 +-
 Documentation/filesystems/vfs.txt             |    2 +-
 Documentation/filesystems/xfs.txt             |   29 +-
 .../firmware_sample_firmware_class.c          |    3 +-
 Documentation/firmware_class/hotplug-script   |    4 +-
 Documentation/i2c/sysfs-interface             |    2 +-
 Documentation/input/joystick-parport.txt      |   13 +-
 Documentation/ioctl-number.txt                |    1 +
 Documentation/kbuild/makefiles.txt            |  145 +-
 Documentation/kernel-parameters.txt           |   85 +-
 Documentation/laptop-mode.txt                 |    2 +-
 Documentation/networking/ip-sysctl.txt        |    5 +
 Documentation/networking/netdevices.txt       |   13 +
 Documentation/pci.txt                         |   11 +-
 Documentation/power/swsusp.txt                |   32 +-
 Documentation/powerpc/hvcs.txt                |   39 +-
 Documentation/powerpc/mpc52xx.txt             |   11 +-
 Documentation/sched-domains.txt               |   27 +-
 Documentation/scsi/ChangeLog.megaraid         |  241 +-
 Documentation/scsi/scsi_mid_low_api.txt       |  252 +-
 .../sound/alsa/ALSA-Configuration.txt         |   31 +-
 .../sound/alsa/DocBook/alsa-driver-api.tmpl   |    1 -
 .../alsa/DocBook/writing-an-alsa-driver.tmpl  |  456 +-
 Documentation/sysctl/kernel.txt               |   22 +-
 Documentation/sysctl/vm.txt                   |    2 +-
 Documentation/usb/sn9c102.txt                 |   55 +-
 Documentation/vm/overcommit-accounting        |    8 +-
 Documentation/vserver/debug.txt               |   77 +-
 Documentation/watchdog/pcwd-watchdog.txt      |    3 +-
 Documentation/x86_64/boot-options.txt         |   24 +-
 MAINTAINERS                                   |  165 +-
 Makefile                                      |  334 +-
 arch/alpha/Kconfig                            |  108 +-
 arch/alpha/Makefile                           |   16 +-
 arch/alpha/boot/Makefile                      |    2 +-
 arch/alpha/defconfig                          |  140 +-
 arch/alpha/kernel/Makefile                    |    4 +-
 arch/alpha/kernel/alpha_ksyms.c               |   59 +-
 arch/alpha/kernel/core_cia.c                  |    4 +-
 arch/alpha/kernel/core_irongate.c             |   20 +-
 arch/alpha/kernel/core_marvel.c               |  227 +-
 arch/alpha/kernel/core_titan.c                |   50 +-
 arch/alpha/kernel/err_titan.c                 |    2 +-
 arch/alpha/kernel/irq.c                       |   44 +-
 arch/alpha/kernel/irq_impl.h                  |   29 -
 arch/alpha/kernel/machvec_impl.h              |  101 +-
 arch/alpha/kernel/osf_sys.c                   |  142 +-
 arch/alpha/kernel/pci-noop.c                  |   75 +-
 arch/alpha/kernel/pci.c                       |   49 +-
 arch/alpha/kernel/pci_iommu.c                 |   39 +
 arch/alpha/kernel/process.c                   |    3 +-
 arch/alpha/kernel/ptrace.c                    |   19 +-
 arch/alpha/kernel/signal.c                    |   41 +-
 arch/alpha/kernel/smp.c                       |   21 +-
 arch/alpha/kernel/srmcons.c                   |   14 +-
 arch/alpha/kernel/sys_alcor.c                 |    6 +-
 arch/alpha/kernel/sys_cabriolet.c             |    5 -
 arch/alpha/kernel/sys_dp264.c                 |   13 +-
 arch/alpha/kernel/sys_eb64p.c                 |    2 -
 arch/alpha/kernel/sys_eiger.c                 |    1 -
 arch/alpha/kernel/sys_jensen.c                |    3 -
 arch/alpha/kernel/sys_marvel.c                |    1 -
 arch/alpha/kernel/sys_miata.c                 |    1 -
 arch/alpha/kernel/sys_mikasa.c                |    2 -
 arch/alpha/kernel/sys_nautilus.c              |    1 -
 arch/alpha/kernel/sys_noritake.c              |    2 -
 arch/alpha/kernel/sys_rawhide.c               |    1 -
 arch/alpha/kernel/sys_ruffian.c               |    1 -
 arch/alpha/kernel/sys_rx164.c                 |    1 -
 arch/alpha/kernel/sys_sable.c                 |    3 -
 arch/alpha/kernel/sys_sio.c                   |    5 -
 arch/alpha/kernel/sys_sx164.c                 |    1 -
 arch/alpha/kernel/sys_takara.c                |    1 -
 arch/alpha/kernel/sys_titan.c                 |   18 +-
 arch/alpha/kernel/sys_wildfire.c              |    1 -
 arch/alpha/kernel/systbls.S                   |    1 +
 arch/alpha/kernel/time.c                      |    6 +-
 arch/alpha/kernel/traps.c                     |    4 +-
 arch/alpha/kernel/vmlinux.lds.S               |    6 +-
 arch/alpha/lib/Makefile                       |    1 -
 arch/alpha/lib/csum_partial_copy.c            |    5 +-
 arch/alpha/mm/fault.c                         |    2 +-
 arch/alpha/mm/numa.c                          |    2 +-
 arch/arm/Kconfig                              |  199 +-
 arch/arm/Makefile                             |   18 +-
 arch/arm/boot/Makefile                        |   10 +
 arch/arm/boot/compressed/Makefile             |   13 +-
 arch/arm/boot/compressed/head-xscale.S        |   31 +-
 arch/arm/boot/compressed/head.S               |   39 +
 arch/arm/boot/compressed/misc.c               |   24 +-
 arch/arm/common/dmabounce.c                   |   34 +-
 arch/arm/common/sa1111.c                      |   17 +-
 arch/arm/configs/ebsa110_defconfig            |    1 -
 arch/arm/configs/iq80321_defconfig            |  433 +-
 arch/arm/configs/ixp4xx_defconfig             |    1 -
 arch/arm/configs/s3c2410_defconfig            |    8 +
 arch/arm/kernel/Makefile                      |    5 +-
 arch/arm/kernel/apm.c                         |  362 +-
 arch/arm/kernel/armksyms.c                    |   93 +-
 arch/arm/kernel/asm-offsets.c                 |   16 +-
 arch/arm/kernel/bios32.c                      |   61 +-
 arch/arm/kernel/calls.S                       |    9 +-
 arch/arm/kernel/debug.S                       |   98 +-
 arch/arm/kernel/ecard.c                       |   82 +-
 arch/arm/kernel/entry-armv.S                  |  220 +-
 arch/arm/kernel/irq.c                         |   19 +-
 arch/arm/kernel/process.c                     |    6 +
 arch/arm/kernel/ptrace.c                      |    7 +-
 arch/arm/kernel/semaphore.c                   |    8 +-
 arch/arm/kernel/setup.c                       |    3 +-
 arch/arm/kernel/signal.c                      |  152 +-
 arch/arm/kernel/sys_arm.c                     |    9 +-
 arch/arm/kernel/time.c                        |   76 +-
 arch/arm/kernel/traps.c                       |    6 +-
 arch/arm/kernel/vmlinux.lds.S                 |    4 +-
 arch/arm/lib/getuser.S                        |   57 +-
 arch/arm/lib/putuser.S                        |   59 +-
 arch/arm/mach-integrator/clock.c              |    9 +-
 arch/arm/mach-integrator/cpu.c                |    8 +-
 arch/arm/mach-integrator/impd1.c              |  191 +
 arch/arm/mach-integrator/integrator_cp.c      |   76 +
 arch/arm/mach-iop3xx/Kconfig                  |   61 +-
 arch/arm/mach-iop3xx/Makefile                 |   21 +-
 arch/arm/mach-iop3xx/arch.c                   |   58 +-
 arch/arm/mach-iop3xx/iop321-irq.c             |    3 +-
 arch/arm/mach-iop3xx/iop321-pci.c             |   64 +-
 arch/arm/mach-iop3xx/iop321-time.c            |   64 +-
 arch/arm/mach-iop3xx/iq80321-pci.c            |   83 +-
 arch/arm/mach-ixp4xx/common.c                 |    2 +-
 arch/arm/mach-lh7a40x/arch-lpd7a40x.c         |   11 +-
 arch/arm/mach-lh7a40x/time.c                  |    8 +-
 arch/arm/mach-omap/Makefile                   |   10 +-
 arch/arm/mach-omap/board-generic.c            |   56 +-
 arch/arm/mach-omap/board-innovator.c          |   58 +-
 arch/arm/mach-omap/board-osk.c                |    4 +-
 arch/arm/mach-omap/board-perseus2.c           |   15 +-
 arch/arm/mach-omap/clocks.c                   |   11 +-
 arch/arm/mach-omap/common.c                   |   53 +-
 arch/arm/mach-omap/common.h                   |    1 -
 arch/arm/mach-omap/dma.c                      |  156 +-
 arch/arm/mach-omap/fpga.c                     |   30 +-
 arch/arm/mach-omap/gpio.c                     |   28 +-
 arch/arm/mach-omap/irq.c                      |   20 +-
 arch/arm/mach-omap/leds.c                     |    9 +-
 arch/arm/mach-omap/leds.h                     |    2 +-
 arch/arm/mach-omap/ocpi.c                     |    4 +-
 arch/arm/mach-pxa/Kconfig                     |    7 +-
 arch/arm/mach-pxa/dma.c                       |    1 +
 arch/arm/mach-pxa/generic.c                   |    8 +
 arch/arm/mach-pxa/idp.c                       |    3 +-
 arch/arm/mach-pxa/irq.c                       |  103 +-
 arch/arm/mach-pxa/leds-lubbock.c              |    1 +
 arch/arm/mach-pxa/leds-mainstone.c            |    1 +
 arch/arm/mach-pxa/lubbock.c                   |    1 +
 arch/arm/mach-pxa/mainstone.c                 |    1 +
 arch/arm/mach-pxa/pm.c                        |   18 +-
 arch/arm/mach-pxa/pxa25x.c                    |    1 +
 arch/arm/mach-pxa/pxa27x.c                    |    1 +
 arch/arm/mach-pxa/sleep.S                     |   43 +-
 arch/arm/mach-pxa/time.c                      |    1 +
 arch/arm/mach-s3c2410/Kconfig                 |   42 +-
 arch/arm/mach-s3c2410/Makefile                |   25 +-
 arch/arm/mach-s3c2410/gpio.c                  |  118 +-
 arch/arm/mach-s3c2410/irq.c                   |  201 +-
 arch/arm/mach-s3c2410/mach-bast.c             |   52 +-
 arch/arm/mach-s3c2410/mach-h1940.c            |   46 +-
 arch/arm/mach-s3c2410/mach-smdk2410.c         |   22 +-
 arch/arm/mach-s3c2410/mach-vr1000.c           |   34 +-
 arch/arm/mach-s3c2410/s3c2410.c               |   78 +-
 arch/arm/mach-s3c2410/s3c2410.h               |   32 +-
 arch/arm/mach-s3c2410/time.c                  |   19 +-
 arch/arm/mach-sa1100/cpu-sa1100.c             |    4 +-
 arch/arm/mach-sa1100/cpu-sa1110.c             |    4 +-
 arch/arm/mach-sa1100/pm.c                     |   19 +-
 arch/arm/mach-versatile/clock.c               |    4 +-
 arch/arm/mach-versatile/core.c                |  211 +-
 arch/arm/mm/Kconfig                           |    6 +-
 arch/arm/mm/Makefile                          |    3 +-
 arch/arm/mm/abort-ev5tj.S                     |    1 -
 arch/arm/mm/cache-v3.S                        |   14 +
 arch/arm/mm/cache-v4.S                        |   14 +
 arch/arm/mm/cache-v4wb.S                      |   14 +
 arch/arm/mm/cache-v4wt.S                      |   14 +
 arch/arm/mm/cache-v6.S                        |   17 +
 arch/arm/mm/consistent.c                      |   30 +-
 arch/arm/mm/copypage-v6.c                     |   92 +-
 arch/arm/mm/fault-armv.c                      |   67 +-
 arch/arm/mm/init.c                            |   13 +-
 arch/arm/mm/proc-arm1020.S                    |   14 +
 arch/arm/mm/proc-arm1020e.S                   |   15 +-
 arch/arm/mm/proc-arm1022.S                    |   16 +-
 arch/arm/mm/proc-arm1026.S                    |   15 +-
 arch/arm/mm/proc-arm920.S                     |   14 +
 arch/arm/mm/proc-arm922.S                     |   14 +
 arch/arm/mm/proc-arm925.S                     |   14 +
 arch/arm/mm/proc-arm926.S                     |   16 +-
 arch/arm/mm/proc-syms.c                       |    8 +-
 arch/arm/mm/proc-v6.S                         |   10 +-
 arch/arm/mm/proc-xscale.S                     |  105 +-
 arch/arm/nwfpe/fpa11_cpdt.c                   |   10 +
 arch/arm/oprofile/op_model_xscale.c           |   29 +-
 arch/arm/tools/mach-types                     |   60 +-
 arch/arm26/Kconfig                            |  117 +-
 arch/arm26/Makefile                           |    4 +-
 arch/arm26/boot/Makefile                      |    4 +-
 arch/arm26/kernel/Makefile                    |    2 +-
 arch/arm26/kernel/armksyms.c                  |   98 +-
 arch/arm26/kernel/irq.c                       |    6 +-
 arch/arm26/kernel/ptrace.c                    |    7 +-
 arch/arm26/kernel/signal.c                    |    4 +-
 arch/arm26/kernel/sys_arm.c                   |    2 +-
 arch/arm26/kernel/time.c                      |   24 +-
 arch/arm26/kernel/vmlinux-arm26-xip.lds.in    |    3 -
 arch/arm26/kernel/vmlinux-arm26.lds.in        |    3 -
 arch/arm26/mm/init.c                          |    6 +-
 arch/cris/Kconfig                             |   56 +-
 arch/cris/Makefile                            |    6 +-
 arch/cris/arch-v10/kernel/debugport.c         |    2 +-
 arch/cris/arch-v10/kernel/process.c           |    2 +-
 arch/cris/arch-v10/kernel/ptrace.c            |   13 +-
 arch/cris/arch-v10/kernel/signal.c            |    8 +-
 arch/cris/arch-v10/mm/init.c                  |    2 +-
 arch/cris/arch-v10/vmlinux.lds.S              |    3 -
 arch/cris/kernel/Makefile                     |    2 +-
 arch/cris/kernel/crisksyms.c                  |    5 +-
 arch/cris/kernel/irq.c                        |    8 +-
 arch/h8300/Kconfig                            |   75 +-
 arch/h8300/kernel/Makefile                    |    2 +-
 arch/h8300/kernel/asm-offsets.c               |    2 +-
 arch/h8300/kernel/h8300_ksyms.c               |   59 +-
 arch/h8300/kernel/ints.c                      |    2 +-
 arch/h8300/kernel/process.c                   |    2 +-
 arch/h8300/kernel/ptrace.c                    |   15 +-
 arch/h8300/kernel/signal.c                    |    8 +-
 arch/h8300/kernel/time.c                      |   23 +-
 arch/h8300/kernel/vmlinux.lds.S               |    3 -
 arch/h8300/lib/checksum.c                     |    1 +
 arch/h8300/platform/h8300h/generic/timer.c    |    4 +-
 arch/h8300/platform/h8s/ints.c                |    2 +-
 arch/i386/Kconfig                             |  194 +-
 arch/i386/Makefile                            |   35 +-
 arch/i386/boot/Makefile                       |    4 +-
 arch/i386/boot/setup.S                        |    2 +-
 arch/i386/boot/video.S                        |   36 +
 arch/i386/kernel/Makefile                     |    6 +-
 arch/i386/kernel/acpi/boot.c                  |   20 +-
 arch/i386/kernel/acpi/sleep.c                 |    5 +-
 arch/i386/kernel/apic.c                       |   89 +-
 arch/i386/kernel/apm.c                        |   45 +-
 arch/i386/kernel/asm-offsets.c                |    1 +
 arch/i386/kernel/cpu/centaur.c                |   27 +-
 arch/i386/kernel/cpu/common.c                 |   23 +-
 arch/i386/kernel/cpu/cpufreq/Kconfig          |   10 +
 arch/i386/kernel/cpu/cpufreq/acpi.c           |  103 +-
 arch/i386/kernel/cpu/cpufreq/gx-suspmod.c     |    1 +
 arch/i386/kernel/cpu/cpufreq/longhaul.c       |  309 +-
 arch/i386/kernel/cpu/cpufreq/longrun.c        |   42 +-
 arch/i386/kernel/cpu/cpufreq/p4-clockmod.c    |    4 +-
 arch/i386/kernel/cpu/cpufreq/powernow-k7.c    |   74 +-
 arch/i386/kernel/cpu/cpufreq/powernow-k8.c    |   16 +-
 arch/i386/kernel/cpu/cpufreq/powernow-k8.h    |    2 +-
 .../kernel/cpu/cpufreq/speedstep-centrino.c   |  250 +-
 arch/i386/kernel/cpu/cpufreq/speedstep-ich.c  |  117 +-
 arch/i386/kernel/cpu/cpufreq/speedstep-smi.c  |    7 +-
 arch/i386/kernel/cpu/intel.c                  |   73 +-
 arch/i386/kernel/cpu/mtrr/mtrr.h              |    1 -
 arch/i386/kernel/cpu/proc.c                   |    4 +-
 arch/i386/kernel/dmi_scan.c                   |   86 +-
 arch/i386/kernel/doublefault.c                |    2 +-
 arch/i386/kernel/entry.S                      |   35 +-
 arch/i386/kernel/head.S                       |    3 -
 arch/i386/kernel/i386_ksyms.c                 |   23 +-
 arch/i386/kernel/i8259.c                      |   72 +-
 arch/i386/kernel/init_task.c                  |    7 +-
 arch/i386/kernel/io_apic.c                    |  184 +-
 arch/i386/kernel/ioport.c                     |   36 +-
 arch/i386/kernel/irq.c                        |   50 +-
 arch/i386/kernel/ldt.c                        |    9 +-
 arch/i386/kernel/microcode.c                  |    1 +
 arch/i386/kernel/nmi.c                        |   76 +-
 arch/i386/kernel/pci-dma.c                    |  111 +-
 arch/i386/kernel/process.c                    |  102 +-
 arch/i386/kernel/ptrace.c                     |   11 +-
 arch/i386/kernel/setup.c                      |   43 +-
 arch/i386/kernel/signal.c                     |   80 +-
 arch/i386/kernel/smp.c                        |   19 +-
 arch/i386/kernel/smpboot.c                    |  277 +-
 arch/i386/kernel/sysenter.c                   |    8 +-
 arch/i386/kernel/time.c                       |   17 +-
 arch/i386/kernel/time_hpet.c                  |   11 +-
 arch/i386/kernel/timers/timer_pit.c           |   44 +
 arch/i386/kernel/timers/timer_tsc.c           |    7 +-
 arch/i386/kernel/traps.c                      |  194 +-
 arch/i386/kernel/vm86.c                       |    4 +-
 arch/i386/kernel/vmlinux.lds.S                |    7 +-
 arch/i386/lib/memcpy.c                        |    6 +-
 arch/i386/lib/mmx.c                           |    2 +-
 arch/i386/lib/usercopy.c                      |    2 +
 arch/i386/mach-es7000/es7000.h                |    9 +-
 arch/i386/mach-es7000/es7000plat.c            |   83 +-
 arch/i386/mach-generic/bigsmp.c               |   28 +-
 arch/i386/mach-voyager/voyager_smp.c          |   32 +-
 arch/i386/math-emu/fpu_proto.h                |    1 -
 arch/i386/mm/Makefile                         |    2 +-
 arch/i386/mm/discontig.c                      |   23 +-
 arch/i386/mm/fault.c                          |   12 +-
 arch/i386/mm/init.c                           |    6 +-
 arch/i386/mm/ioremap.c                        |   22 +-
 arch/i386/mm/mmap.c                           |    4 +-
 arch/i386/mm/pageattr.c                       |    2 +-
 arch/i386/oprofile/op_model_athlon.c          |    4 +-
 arch/i386/oprofile/op_model_p4.c              |   40 +-
 arch/i386/oprofile/op_model_ppro.c            |    4 +-
 arch/i386/pci/common.c                        |    2 +-
 arch/i386/pci/fixup.c                         |  129 +-
 arch/i386/pci/i386.c                          |   10 +-
 arch/i386/pci/mmconfig.c                      |    9 +-
 arch/i386/pci/numa.c                          |    5 +-
 arch/i386/pci/pcbios.c                        |    2 +-
 arch/i386/power/Makefile                      |    1 -
 arch/i386/power/cpu.c                         |    4 +-
 arch/i386/power/swsusp.S                      |   76 +-
 arch/ia64/Kconfig                             |  127 +-
 arch/ia64/Makefile                            |   18 +-
 arch/ia64/configs/generic_defconfig           |   29 +-
 arch/ia64/configs/sn2_defconfig               |   49 +-
 arch/ia64/configs/zx1_defconfig               |  662 +-
 arch/ia64/hp/common/sba_iommu.c               |   86 +-
 arch/ia64/hp/sim/simserial.c                  |    8 +-
 arch/ia64/ia32/binfmt_elf32.c                 |   46 +-
 arch/ia64/ia32/elfcore32.h                    |   14 +-
 arch/ia64/ia32/ia32_entry.S                   |    8 +-
 arch/ia64/ia32/ia32_ldt.c                     |   25 +-
 arch/ia64/ia32/ia32_signal.c                  |  182 +-
 arch/ia64/ia32/ia32_support.c                 |   38 +-
 arch/ia64/ia32/ia32priv.h                     |   19 +-
 arch/ia64/ia32/sys_ia32.c                     |  349 +-
 arch/ia64/kernel/Makefile                     |   12 +-
 arch/ia64/kernel/acpi-ext.c                   |    2 +-
 arch/ia64/kernel/acpi.c                       |   85 +-
 arch/ia64/kernel/asm-offsets.c                |   29 +-
 arch/ia64/kernel/cyclone.c                    |   61 +-
 arch/ia64/kernel/efi.c                        |   14 +-
 arch/ia64/kernel/entry.S                      |    4 +-
 arch/ia64/kernel/fsys.S                       |  365 +-
 arch/ia64/kernel/head.S                       |    3 +-
 arch/ia64/kernel/iosapic.c                    |   73 +-
 arch/ia64/kernel/irq.c                        |   52 +-
 arch/ia64/kernel/irq_ia64.c                   |    7 +-
 arch/ia64/kernel/mca.c                        |   41 +-
 arch/ia64/kernel/minstate.h                   |    6 +-
 arch/ia64/kernel/module.c                     |   20 +-
 arch/ia64/kernel/palinfo.c                    |    4 +-
 arch/ia64/kernel/patch.c                      |   26 +-
 arch/ia64/kernel/perfmon.c                    |   66 +-
 arch/ia64/kernel/process.c                    |   38 +-
 arch/ia64/kernel/ptrace.c                     |  109 +-
 arch/ia64/kernel/sal.c                        |   38 +
 arch/ia64/kernel/salinfo.c                    |   13 +-
 arch/ia64/kernel/setup.c                      |    2 +-
 arch/ia64/kernel/sigframe.h                   |    2 +-
 arch/ia64/kernel/signal.c                     |   92 +-
 arch/ia64/kernel/smp.c                        |    2 +-
 arch/ia64/kernel/smpboot.c                    |   30 +-
 arch/ia64/kernel/sys_ia64.c                   |    4 +-
 arch/ia64/kernel/time.c                       |  221 +-
 arch/ia64/kernel/traps.c                      |   27 +-
 arch/ia64/kernel/unaligned.c                  |   18 +-
 arch/ia64/kernel/unwind.c                     |   45 +-
 arch/ia64/kernel/vmlinux.lds.S                |    7 +-
 arch/ia64/lib/csum_partial_copy.c             |   12 +-
 arch/ia64/lib/io.c                            |   22 +-
 arch/ia64/lib/swiotlb.c                       |  112 +-
 arch/ia64/mm/contig.c                         |   17 +-
 arch/ia64/mm/discontig.c                      |   60 +-
 arch/ia64/mm/extable.c                        |    2 +-
 arch/ia64/mm/fault.c                          |    5 +-
 arch/ia64/mm/init.c                           |   20 +-
 arch/ia64/mm/tlb.c                            |    2 +-
 arch/ia64/oprofile/Kconfig                    |    4 +
 arch/ia64/oprofile/Makefile                   |    1 +
 arch/ia64/oprofile/init.c                     |    9 +-
 arch/ia64/pci/pci.c                           |    9 +-
 arch/ia64/sn/io/hwgfs/interface.c             |    4 +-
 arch/ia64/sn/io/machvec/pci_bus_cvlink.c      |   18 +-
 arch/ia64/sn/kernel/bte.c                     |    7 +-
 arch/ia64/sn/kernel/setup.c                   |    2 +
 arch/ia64/sn/kernel/sn2/Makefile              |    2 +-
 arch/ia64/sn/kernel/sn2/prominfo_proc.c       |  313 +-
 arch/ia64/sn/kernel/sn2/sn_proc_fs.c          |  182 +-
 arch/ia64/sn/kernel/sn2/timer.c               |   49 +-
 arch/m68k/Kconfig                             |   43 +-
 arch/m68k/Makefile                            |    2 +-
 arch/m68k/kernel/Makefile                     |    2 +-
 arch/m68k/kernel/bios32.c                     |    5 -
 arch/m68k/kernel/m68k_ksyms.c                 |   25 +-
 arch/m68k/kernel/process.c                    |    2 +-
 arch/m68k/kernel/ptrace.c                     |    7 +-
 arch/m68k/kernel/signal.c                     |    8 +-
 arch/m68k/kernel/time.c                       |   22 +-
 arch/m68k/kernel/vmlinux-std.lds              |    3 -
 arch/m68k/kernel/vmlinux-sun3.lds             |    3 -
 arch/m68k/q40/q40ints.c                       |    2 +-
 arch/m68knommu/Kconfig                        |   66 +-
 arch/m68knommu/kernel/Makefile                |    2 +-
 arch/m68knommu/kernel/asm-offsets.c           |    2 +-
 arch/m68knommu/kernel/comempci.c              |    2 -
 arch/m68knommu/kernel/m68k_ksyms.c            |   49 +-
 arch/m68knommu/kernel/process.c               |    2 +-
 arch/m68knommu/kernel/ptrace.c                |   13 +-
 arch/m68knommu/kernel/signal.c                |    8 +-
 arch/m68knommu/kernel/time.c                  |   23 +-
 arch/m68knommu/kernel/vmlinux.lds.S           |    3 -
 arch/m68knommu/platform/5307/timers.c         |   13 +-
 arch/mips/Kconfig                             |  146 +-
 arch/mips/Makefile                            |    8 +-
 arch/mips/au1000/common/time.c                |    2 +-
 arch/mips/baget/irq.c                         |    7 +-
 arch/mips/configs/jaguar-atx_defconfig        |    8 +-
 arch/mips/configs/ocelot_c_defconfig          |    2 +-
 arch/mips/configs/tb0226_defconfig            |    1 -
 arch/mips/configs/tb0229_defconfig            |    1 -
 arch/mips/kernel/Makefile                     |    2 +-
 arch/mips/kernel/irixsig.c                    |    4 +-
 arch/mips/kernel/irq.c                        |   45 +-
 arch/mips/kernel/mips_ksyms.c                 |   44 +-
 arch/mips/kernel/signal.c                     |   17 +-
 arch/mips/kernel/signal32.c                   |    8 +-
 arch/mips/kernel/signal_n32.c                 |    4 +-
 arch/mips/kernel/smp.c                        |   23 +-
 arch/mips/kernel/syscall.c                    |    4 +-
 arch/mips/kernel/sysirix.c                    |    4 +-
 arch/mips/kernel/time.c                       |   20 +-
 arch/mips/kernel/vmlinux.lds.S                |    4 +-
 arch/mips/mips-boards/generic/time.c          |    1 -
 arch/mips/mm/fault.c                          |    1 -
 arch/mips/momentum/jaguar_atx/prom.c          |    4 +-
 arch/mips/momentum/ocelot_c/prom.c            |    6 +-
 arch/mips/pci/fixup-atlas.c                   |   10 +-
 arch/mips/pci/fixup-au1000.c                  |    4 -
 arch/mips/pci/fixup-capcella.c                |    4 -
 arch/mips/pci/fixup-cobalt.c                  |   12 +-
 arch/mips/pci/fixup-ddb5074.c                 |    7 +-
 arch/mips/pci/fixup-ddb5477.c                 |   16 +-
 arch/mips/pci/fixup-ip32.c                    |    4 -
 arch/mips/pci/fixup-jaguar.c                  |    4 -
 arch/mips/pci/fixup-lasat.c                   |    4 -
 arch/mips/pci/fixup-malta.c                   |   11 +-
 arch/mips/pci/fixup-mpc30x.c                  |    4 -
 arch/mips/pci/fixup-ocelot-c.c                |    4 -
 arch/mips/pci/fixup-ocelot-g.c                |    4 -
 arch/mips/pci/fixup-sni.c                     |    4 -
 arch/mips/pci/fixup-tb0219.c                  |    4 -
 arch/mips/pci/fixup-tb0226.c                  |    4 -
 arch/mips/pci/fixup-yosemite.c                |    4 -
 arch/mips/pci/pci-ip27.c                      |   21 +-
 arch/mips/pci/pci-sb1250.c                    |    4 -
 arch/mips/pmc-sierra/yosemite/ht.c            |    5 -
 arch/mips/sgi-ip27/ip27-memory.c              |    2 +-
 arch/mips/vr41xx/common/giu.c                 |    7 +-
 arch/mips/vr41xx/common/icu.c                 |  222 +-
 arch/mips/vr41xx/common/serial.c              |    4 +-
 arch/mips/vr41xx/common/vrc4173.c             |   90 +
 arch/parisc/Kconfig                           |   70 +-
 arch/parisc/kernel/Makefile                   |    2 +-
 arch/parisc/kernel/asm-offsets.c              |    4 +-
 arch/parisc/kernel/cache.c                    |    5 +-
 arch/parisc/kernel/hardware.c                 |    2 +-
 arch/parisc/kernel/pci.c                      |    9 -
 arch/parisc/kernel/process.c                  |    2 +-
 arch/parisc/kernel/ptrace.c                   |    7 +-
 arch/parisc/kernel/smp.c                      |   23 +-
 arch/parisc/kernel/time.c                     |   40 +-
 arch/parisc/kernel/vmlinux.lds.S              |    4 +-
 arch/parisc/lib/debuglocks.c                  |    2 +-
 arch/parisc/mm/init.c                         |    2 +-
 arch/ppc/8260_io/fcc_enet.c                   |    4 +-
 arch/ppc/8xx_io/uart.c                        |    2 +-
 arch/ppc/Kconfig                              |  145 +-
 arch/ppc/Makefile                             |   34 +-
 arch/ppc/amiga/config.c                       |    3 -
 arch/ppc/boot/Makefile                        |    4 +-
 arch/ppc/boot/common/misc-common.c            |   30 +-
 arch/ppc/boot/common/ns16550.c                |    6 +-
 arch/ppc/boot/common/serial_stub.c            |    5 -
 arch/ppc/boot/common/util.S                   |   16 +-
 arch/ppc/boot/include/nonstdio.h              |    2 +
 arch/ppc/boot/lib/Makefile                    |    4 +-
 arch/ppc/boot/openfirmware/coffmain.c         |    1 -
 arch/ppc/boot/openfirmware/common.c           |  106 +-
 arch/ppc/boot/openfirmware/misc.S             |    2 +-
 arch/ppc/boot/simple/Makefile                 |    7 +-
 arch/ppc/boot/simple/misc-embedded.c          |    9 +-
 arch/ppc/boot/simple/misc-prep.c              |    1 +
 arch/ppc/boot/simple/misc-spruce.c            |    3 -
 arch/ppc/boot/simple/misc.c                   |   16 +-
 arch/ppc/boot/simple/relocate.S               |    6 +-
 arch/ppc/boot/utils/mkbugboot.c               |   12 +-
 arch/ppc/boot/utils/mktree.c                  |    4 +
 arch/ppc/configs/mvme5100_defconfig           |  448 +-
 arch/ppc/kernel/Makefile                      |    2 +-
 arch/ppc/kernel/align.c                       |  163 +-
 arch/ppc/kernel/asm-offsets.c                 |    7 +
 arch/ppc/kernel/cpu_setup_6xx.S               |   42 +-
 arch/ppc/kernel/cpu_setup_power4.S            |    8 +-
 arch/ppc/kernel/cputable.c                    |  115 +-
 arch/ppc/kernel/dma-mapping.c                 |    4 +-
 arch/ppc/kernel/entry.S                       |    4 +-
 arch/ppc/kernel/head.S                        |   16 +-
 arch/ppc/kernel/head_44x.S                    |  237 +-
 arch/ppc/kernel/head_e500.S                   |  236 +-
 arch/ppc/kernel/idle.c                        |   34 +
 arch/ppc/kernel/idle_6xx.S                    |    6 +-
 arch/ppc/kernel/idle_power4.S                 |    2 +-
 arch/ppc/kernel/irq.c                         |   44 +-
 arch/ppc/kernel/misc.S                        |   33 +-
 arch/ppc/kernel/pci.c                         |   63 +-
 arch/ppc/kernel/ppc_htab.c                    |   33 +-
 arch/ppc/kernel/ppc_ksyms.c                   |    4 +
 arch/ppc/kernel/process.c                     |    7 +-
 arch/ppc/kernel/setup.c                       |    8 +-
 arch/ppc/kernel/signal.c                      |   33 +-
 arch/ppc/kernel/smp.c                         |   10 +-
 arch/ppc/kernel/time.c                        |   43 +-
 arch/ppc/kernel/traps.c                       |   51 +-
 arch/ppc/kernel/vector.S                      |    4 +-
 arch/ppc/kernel/vmlinux.lds.S                 |    4 +-
 arch/ppc/lib/checksum.S                       |   12 +-
 arch/ppc/lib/rheap.c                          |    8 +-
 arch/ppc/math-emu/op-common.h                 |    1 -
 arch/ppc/mm/44x_mmu.c                         |    2 +-
 arch/ppc/mm/4xx_mmu.c                         |    5 +
 arch/ppc/mm/init.c                            |    5 +
 arch/ppc/mm/pgtable.c                         |   13 +
 arch/ppc/platforms/4xx/ebony.c                |  168 +-
 arch/ppc/platforms/4xx/ebony.h                |   18 +-
 arch/ppc/platforms/4xx/ocotea.c               |  271 +-
 arch/ppc/platforms/4xx/ocotea.h               |   15 +-
 arch/ppc/platforms/85xx/mpc8540_ads.c         |    4 -
 arch/ppc/platforms/85xx/mpc85xx_cds_common.c  |    6 +-
 arch/ppc/platforms/85xx/sbc8560.c             |    3 -
 arch/ppc/platforms/Makefile                   |    8 +-
 arch/ppc/platforms/chrp_setup.c               |    9 +-
 arch/ppc/platforms/chrp_smp.c                 |    1 -
 arch/ppc/platforms/est8260.h                  |    3 +
 arch/ppc/platforms/k2.c                       |    4 -
 arch/ppc/platforms/lite5200.c                 |   55 +-
 arch/ppc/platforms/mcpn765.c                  |    6 -
 arch/ppc/platforms/mcpn765.h                  |   50 +-
 arch/ppc/platforms/mpc5200.c                  |   24 +
 arch/ppc/platforms/mvme5100.h                 |   25 +-
 arch/ppc/platforms/pcore.c                    |    4 -
 arch/ppc/platforms/pmac_cpufreq.c             |   12 +-
 arch/ppc/platforms/pmac_feature.c             |    2 +-
 arch/ppc/platforms/pmac_pci.c                 |   23 +-
 arch/ppc/platforms/pmac_setup.c               |    3 -
 arch/ppc/platforms/pmac_smp.c                 |    2 +-
 arch/ppc/platforms/pmac_time.c                |    2 +-
 arch/ppc/platforms/powerpmc250.h              |   18 +-
 arch/ppc/platforms/pplus.c                    |    2 -
 arch/ppc/platforms/pq2ads.h                   |    4 +
 arch/ppc/platforms/prep_pci.c                 |  176 +-
 arch/ppc/platforms/prep_setup.c               |  218 +-
 arch/ppc/platforms/prpmc750.c                 |    4 -
 arch/ppc/platforms/prpmc750.h                 |   26 +-
 arch/ppc/platforms/prpmc800.c                 |    4 -
 arch/ppc/platforms/prpmc800.h                 |   28 +-
 arch/ppc/platforms/residual.c                 |  133 +-
 arch/ppc/platforms/rpx8260.h                  |    7 +
 arch/ppc/platforms/sandpoint.c                |    4 -
 arch/ppc/platforms/sbc82xx.c                  |   58 +-
 arch/ppc/platforms/sbc82xx.h                  |    4 +
 arch/ppc/platforms/spruce.c                   |    5 -
 arch/ppc/platforms/tqm8260.h                  |    4 +
 arch/ppc/platforms/tqm8260_setup.c            |   41 +-
 arch/ppc/syslib/Makefile                      |    4 +-
 arch/ppc/syslib/cpm2_pic.c                    |   25 +-
 arch/ppc/syslib/cpm2_pic.h                    |    8 +-
 arch/ppc/syslib/hawk_common.c                 |   32 +
 arch/ppc/syslib/ibm44x_common.c               |  165 +
 arch/ppc/syslib/ibm44x_common.h               |    8 +-
 arch/ppc/syslib/m8260_pci.h                   |    1 +
 arch/ppc/syslib/m8260_setup.c                 |   84 +-
 arch/ppc/syslib/m8xx_setup.c                  |    6 +
 arch/ppc/syslib/mpc52xx_pic.c                 |   22 +-
 arch/ppc/syslib/mpc52xx_setup.c               |   41 +-
 arch/ppc/syslib/open_pic.c                    |   10 +-
 arch/ppc/syslib/open_pic2.c                   |    2 +-
 arch/ppc/syslib/ppc4xx_pic.c                  |    2 +-
 arch/ppc/syslib/ppc4xx_setup.c                |    4 -
 arch/ppc/syslib/ppc85xx_setup.c               |    4 +-
 arch/ppc/syslib/prom_init.c                   |   24 +-
 arch/ppc/syslib/todc_time.c                   |    8 +-
 arch/ppc64/Kconfig                            |  146 +-
 arch/ppc64/Makefile                           |   19 +-
 arch/ppc64/boot/Makefile                      |   39 +-
 arch/ppc64/boot/main.c                        |  170 +-
 arch/ppc64/boot/zImage.lds                    |   12 +-
 arch/ppc64/configs/g5_defconfig               |  197 +-
 arch/ppc64/configs/iSeries_defconfig          |  109 +-
 arch/ppc64/configs/pSeries_defconfig          |  263 +-
 arch/ppc64/kernel/ItLpQueue.c                 |    2 +-
 arch/ppc64/kernel/Makefile                    |   17 +-
 arch/ppc64/kernel/asm-offsets.c               |   19 +-
 arch/ppc64/kernel/btext.c                     |  231 +-
 arch/ppc64/kernel/eeh.c                       |  321 +-
 arch/ppc64/kernel/entry.S                     |   31 +-
 arch/ppc64/kernel/head.S                      |  264 +-
 arch/ppc64/kernel/hvconsole.c                 |   66 +-
 arch/ppc64/kernel/hvcserver.c                 |   86 +-
 arch/ppc64/kernel/iSeries_htab.c              |    2 +
 arch/ppc64/kernel/iSeries_pci.c               |   45 +-
 arch/ppc64/kernel/iSeries_pci_reset.c         |    3 +-
 arch/ppc64/kernel/iSeries_setup.c             |  178 +-
 arch/ppc64/kernel/iSeries_setup.h             |    4 -
 arch/ppc64/kernel/idle.c                      |  226 +-
 arch/ppc64/kernel/idle_power4.S               |    2 +-
 arch/ppc64/kernel/ioctl32.c                   |    2 -
 arch/ppc64/kernel/iommu.c                     |    2 +-
 arch/ppc64/kernel/irq.c                       |   72 +-
 arch/ppc64/kernel/lmb.c                       |   63 +-
 arch/ppc64/kernel/lparcfg.c                   |  224 +-
 arch/ppc64/kernel/mf_proc.c                   |   30 +-
 arch/ppc64/kernel/misc.S                      |  137 +-
 arch/ppc64/kernel/nvram.c                     |    4 +-
 arch/ppc64/kernel/open_pic.c                  |    5 -
 arch/ppc64/kernel/open_pic_u3.c               |    2 +-
 arch/ppc64/kernel/pSeries_iommu.c             |  200 +-
 arch/ppc64/kernel/pSeries_lpar.c              |  266 +-
 arch/ppc64/kernel/pSeries_pci.c               |  396 +-
 arch/ppc64/kernel/pacaData.c                  |   31 +-
 arch/ppc64/kernel/pci.c                       |  377 +-
 arch/ppc64/kernel/pci.h                       |    4 +-
 arch/ppc64/kernel/pci_dn.c                    |    4 +-
 arch/ppc64/kernel/pci_iommu.c                 |    4 +-
 arch/ppc64/kernel/pmac_feature.c              |   11 +-
 arch/ppc64/kernel/pmac_low_i2c.c              |    2 +-
 arch/ppc64/kernel/pmac_pci.c                  |   26 +-
 arch/ppc64/kernel/pmac_setup.c                |  267 +-
 arch/ppc64/kernel/pmac_smp.c                  |    1 -
 arch/ppc64/kernel/pmac_time.c                 |    2 +-
 arch/ppc64/kernel/ppc_ksyms.c                 |   15 +-
 arch/ppc64/kernel/process.c                   |   29 +-
 arch/ppc64/kernel/prom.c                      | 2439 ++-----
 arch/ppc64/kernel/ras.c                       |    8 +-
 arch/ppc64/kernel/rtas-proc.c                 |    2 +-
 arch/ppc64/kernel/rtas.c                      |  131 +-
 arch/ppc64/kernel/rtasd.c                     |  146 +-
 arch/ppc64/kernel/rtc.c                       |    2 +-
 arch/ppc64/kernel/setup.c                     |  909 ++-
 arch/ppc64/kernel/signal.c                    |   25 +-
 arch/ppc64/kernel/signal32.c                  |   40 +-
 arch/ppc64/kernel/smp.c                       |  380 +-
 arch/ppc64/kernel/sys_ppc32.c                 |   36 +-
 arch/ppc64/kernel/sysfs.c                     |   85 +-
 arch/ppc64/kernel/time.c                      |  103 +-
 arch/ppc64/kernel/traps.c                     |  241 +-
 arch/ppc64/kernel/udbg.c                      |   56 +-
 arch/ppc64/kernel/vector.S                    |    4 +-
 arch/ppc64/kernel/vio.c                       |    4 +
 arch/ppc64/kernel/viopath.c                   |    2 +-
 arch/ppc64/kernel/vmlinux.lds.S               |   12 +-
 arch/ppc64/kernel/xics.c                      |    2 +-
 arch/ppc64/lib/checksum.S                     |   14 +-
 arch/ppc64/lib/locks.c                        |  226 +-
 arch/ppc64/mm/Makefile                        |    4 +-
 arch/ppc64/mm/hash_low.S                      |   16 +-
 arch/ppc64/mm/hash_utils.c                    |   95 +-
 arch/ppc64/mm/hugetlbpage.c                   |  104 +-
 arch/ppc64/mm/imalloc.c                       |   77 +-
 arch/ppc64/mm/init.c                          |  247 +-
 arch/ppc64/mm/mmap.c                          |    9 +-
 arch/ppc64/mm/numa.c                          |  238 +-
 arch/ppc64/mm/slb.c                           |   85 +-
 arch/ppc64/mm/slb_low.S                       |   99 +-
 arch/ppc64/mm/tlb.c                           |    2 +-
 arch/ppc64/oprofile/common.c                  |   21 +-
 arch/ppc64/oprofile/op_impl.h                 |   15 +-
 arch/ppc64/oprofile/op_model_power4.c         |   33 +-
 arch/ppc64/oprofile/op_model_rs64.c           |    6 +-
 arch/ppc64/xmon/xmon.c                        |   42 +-
 arch/s390/Kconfig                             |  187 +-
 arch/s390/Makefile                            |   34 +-
 arch/s390/appldata/appldata_mem.c             |    8 +-
 arch/s390/defconfig                           |   34 +-
 arch/s390/kernel/Makefile                     |    4 +-
 arch/s390/kernel/asm-offsets.c                |    4 +
 arch/s390/kernel/compat_exec.c                |    6 +-
 arch/s390/kernel/compat_linux.c               |    5 +-
 arch/s390/kernel/compat_signal.c              |   45 +-
 arch/s390/kernel/debug.c                      |   13 +-
 arch/s390/kernel/ebcdic.c                     |   12 +-
 arch/s390/kernel/entry.S                      |  103 +-
 arch/s390/kernel/entry64.S                    |  107 +-
 arch/s390/kernel/head.S                       |    6 +-
 arch/s390/kernel/head64.S                     |    6 +-
 arch/s390/kernel/process.c                    |   97 +-
 arch/s390/kernel/profile.c                    |   41 +-
 arch/s390/kernel/s390_ext.c                   |    1 +
 arch/s390/kernel/s390_ksyms.c                 |   21 +-
 arch/s390/kernel/setup.c                      |   51 +-
 arch/s390/kernel/signal.c                     |   25 +-
 arch/s390/kernel/smp.c                        |   30 +-
 arch/s390/kernel/time.c                       |   42 +-
 arch/s390/kernel/traps.c                      |   96 +-
 arch/s390/kernel/vmlinux.lds.S                |    4 +-
 arch/s390/kernel/vtime.c                      |    2 +-
 arch/s390/lib/string.c                        |   34 +-
 arch/s390/mm/Makefile                         |    2 +-
 arch/s390/mm/fault.c                          |    8 +-
 arch/sh/Kconfig                               |  162 +-
 arch/sh/Makefile                              |    4 +-
 arch/sh/boards/mpc1211/pci.c                  |    9 +-
 arch/sh/boards/overdrive/galileo.c            |    8 +-
 arch/sh/boot/compressed/Makefile              |    2 +-
 arch/sh/drivers/pci/fixups-dreamcast.c        |    6 +-
 arch/sh/drivers/pci/pci-sh7751.c              |    9 +-
 arch/sh/drivers/pci/pci-st40.c                |    8 +-
 arch/sh/kernel/Makefile                       |    2 +-
 arch/sh/kernel/irq.c                          |    8 +-
 arch/sh/kernel/kgdb_stub.c                    |    2 +-
 arch/sh/kernel/process.c                      |    2 +-
 arch/sh/kernel/sh_ksyms.c                     |    3 +-
 arch/sh/kernel/signal.c                       |    8 +-
 arch/sh/kernel/smp.c                          |   10 +-
 arch/sh/kernel/time.c                         |   35 +-
 arch/sh/kernel/vmlinux.lds.S                  |    4 +-
 arch/sh/mm/fault-nommu.c                      |    1 -
 arch/sh/mm/fault.c                            |    1 -
 arch/sh/mm/init.c                             |    6 +-
 arch/sh/mm/tlb-sh3.c                          |    1 -
 arch/sh/mm/tlb-sh4.c                          |    1 -
 arch/sh64/Kconfig                             |   50 +-
 arch/sh64/boot/compressed/Makefile            |    6 +-
 arch/sh64/kernel/irq.c                        |    6 +-
 arch/sh64/kernel/pci_sh5.c                    |    7 +-
 arch/sh64/kernel/process.c                    |    4 +-
 arch/sh64/kernel/ptrace.c                     |    7 +-
 arch/sh64/kernel/sh_ksyms.c                   |   29 +-
 arch/sh64/kernel/signal.c                     |    8 +-
 arch/sh64/kernel/time.c                       |   34 +-
 arch/sh64/kernel/vmlinux.lds.S                |    4 +-
 arch/sh64/mm/fault.c                          |    1 -
 arch/sh64/mm/init.c                           |    4 +-
 arch/sh64/mm/tlbmiss.c                        |    1 -
 arch/sparc/Kconfig                            |   80 +-
 arch/sparc/Makefile                           |    2 +-
 arch/sparc/boot/Makefile                      |   42 +-
 arch/sparc/kernel/Makefile                    |    2 +-
 arch/sparc/kernel/entry.S                     |    2 +-
 arch/sparc/kernel/init_task.c                 |    2 +-
 arch/sparc/kernel/irq.c                       |    1 -
 arch/sparc/kernel/pcic.c                      |    4 -
 arch/sparc/kernel/process.c                   |    2 -
 arch/sparc/kernel/ptrace.c                    |    7 +-
 arch/sparc/kernel/setup.c                     |    1 -
 arch/sparc/kernel/signal.c                    |   37 +-
 arch/sparc/kernel/smp.c                       |    1 -
 arch/sparc/kernel/sparc_ksyms.c               |    8 +-
 arch/sparc/kernel/sun4d_smp.c                 |   18 +-
 arch/sparc/kernel/sun4m_smp.c                 |   18 +-
 arch/sparc/kernel/systbls.S                   |    2 +-
 arch/sparc/kernel/time.c                      |   53 +-
 arch/sparc/kernel/vmlinux.lds.S               |    4 +-
 arch/sparc/mm/srmmu.c                         |    2 +-
 arch/sparc/mm/sun4c.c                         |    4 +-
 arch/sparc64/Kconfig                          |  113 +-
 arch/sparc64/Makefile                         |    8 +-
 arch/sparc64/boot/Makefile                    |    2 +-
 arch/sparc64/defconfig                        |   63 +-
 arch/sparc64/kernel/Makefile                  |    3 +-
 arch/sparc64/kernel/auxio.c                   |   11 +-
 arch/sparc64/kernel/binfmt_elf32.c            |    4 +-
 arch/sparc64/kernel/chmc.c                    |    2 +-
 arch/sparc64/kernel/etrap.S                   |  301 +-
 arch/sparc64/kernel/head.S                    |    5 +-
 arch/sparc64/kernel/irq.c                     |   20 +-
 arch/sparc64/kernel/pci.c                     |    8 -
 arch/sparc64/kernel/pci_common.c              |  122 +-
 arch/sparc64/kernel/pci_impl.h                |    1 -
 arch/sparc64/kernel/pci_iommu.c               |   60 +-
 arch/sparc64/kernel/pci_psycho.c              |   28 +-
 arch/sparc64/kernel/pci_sabre.c               |   25 +-
 arch/sparc64/kernel/pci_schizo.c              |   24 +-
 arch/sparc64/kernel/power.c                   |   11 +-
 arch/sparc64/kernel/process.c                 |    2 -
 arch/sparc64/kernel/ptrace.c                  |    7 +-
 arch/sparc64/kernel/setup.c                   |    1 -
 arch/sparc64/kernel/signal.c                  |   37 +-
 arch/sparc64/kernel/signal32.c                |  135 +-
 arch/sparc64/kernel/smp.c                     |   15 +-
 arch/sparc64/kernel/sparc64_ksyms.c           |   40 +-
 arch/sparc64/kernel/sys32.S                   |    2 +-
 arch/sparc64/kernel/sys_sparc32.c             |   38 +-
 arch/sparc64/kernel/systbls.S                 |    4 +-
 arch/sparc64/kernel/time.c                    |  180 +-
 arch/sparc64/kernel/traps.c                   |  141 +-
 arch/sparc64/kernel/ttable.S                  |    2 +-
 arch/sparc64/kernel/vmlinux.lds.S             |    4 +-
 arch/sparc64/lib/Makefile                     |   11 +-
 arch/sparc64/lib/PeeCeeI.c                    |   12 +-
 arch/sparc64/lib/U3copy_from_user.S           |  424 +-
 arch/sparc64/lib/U3copy_to_user.S             |  424 +-
 arch/sparc64/lib/U3memcpy.S                   |  331 +-
 arch/sparc64/lib/atomic.S                     |    9 +-
 arch/sparc64/lib/bitops.S                     |   44 +-
 arch/sparc64/lib/copy_page.S                  |    3 +
 arch/sparc64/lib/debuglocks.c                 |    2 +-
 arch/sparc64/lib/ipcsum.S                     |    6 +-
 arch/sparc64/lib/strlen.S                     |    6 +-
 arch/sparc64/lib/strncmp.S                    |    7 +-
 arch/sparc64/lib/strncpy_from_user.S          |    4 +-
 arch/sparc64/lib/xor.S                        |   28 +-
 arch/sparc64/mm/fault.c                       |   11 +-
 arch/sparc64/mm/init.c                        |   19 +-
 arch/sparc64/solaris/misc.c                   |   69 +-
 arch/um/Kconfig                               |  125 +-
 arch/um/Kconfig_block                         |    5 +
 arch/um/Kconfig_char                          |   56 +-
 arch/um/Kconfig_net                           |   72 +-
 arch/um/Makefile                              |  169 +-
 arch/um/Makefile-i386                         |   42 +-
 arch/um/Makefile-skas                         |    9 +-
 arch/um/Makefile-tt                           |    3 +-
 arch/um/config.release                        |    1 -
 arch/um/defconfig                             |  282 +-
 arch/um/drivers/Makefile                      |   18 +-
 arch/um/drivers/chan_kern.c                   |   67 +-
 arch/um/drivers/chan_user.c                   |  104 +-
 arch/um/drivers/cow.h                         |   16 +-
 arch/um/drivers/cow_user.c                    |   46 +-
 arch/um/drivers/daemon_user.c                 |   26 +-
 arch/um/drivers/fd.c                          |   20 +-
 arch/um/drivers/harddog_user.c                |   62 +-
 arch/um/drivers/hostaudio_kern.c              |  145 +-
 arch/um/drivers/line.c                        |  159 +-
 arch/um/drivers/mcast_user.c                  |   16 +-
 arch/um/drivers/mconsole_kern.c               |  154 +-
 arch/um/drivers/mconsole_user.c               |   25 +-
 arch/um/drivers/mmapper_kern.c                |    5 +-
 arch/um/drivers/net_kern.c                    |  123 +-
 arch/um/drivers/net_user.c                    |   49 +-
 arch/um/drivers/null.c                        |    1 -
 arch/um/drivers/port_kern.c                   |   17 +-
 arch/um/drivers/port_user.c                   |   42 +-
 arch/um/drivers/pty.c                         |   45 +-
 arch/um/drivers/slip_user.c                   |   75 +-
 arch/um/drivers/slirp_user.c                  |   23 +-
 arch/um/drivers/ssl.c                         |   49 +-
 arch/um/drivers/stdio_console.c               |   62 +-
 arch/um/drivers/tty.c                         |   15 +-
 arch/um/drivers/ubd_kern.c                    |  658 +-
 arch/um/drivers/ubd_user.c                    |  498 +-
 arch/um/drivers/xterm.c                       |   37 +-
 arch/um/drivers/xterm_kern.c                  |   12 +-
 arch/um/include/2_5compat.h                   |   14 -
 arch/um/include/irq_kern.h                    |    4 +-
 arch/um/include/irq_user.h                    |    1 +
 arch/um/include/kern_util.h                   |   11 +-
 arch/um/include/line.h                        |    4 +-
 arch/um/include/mconsole.h                    |    6 +-
 arch/um/include/mem.h                         |   15 +-
 arch/um/include/mem_kern.h                    |    2 +-
 arch/um/include/mem_user.h                    |   31 +-
 arch/um/include/os.h                          |   55 +-
 arch/um/include/signal_user.h                 |    2 +
 arch/um/include/skas_ptrace.h                 |    2 +-
 arch/um/include/sysdep-i386/checksum.h        |    4 +-
 arch/um/include/sysdep-i386/frame_user.h      |   28 +-
 arch/um/include/sysdep-i386/sigcontext.h      |    4 +-
 arch/um/include/sysdep-i386/syscalls.h        |   59 +-
 arch/um/include/time_user.h                   |    1 +
 arch/um/include/ubd_user.h                    |    9 +-
 arch/um/include/um_uaccess.h                  |   51 +
 arch/um/include/user.h                        |    3 +
 arch/um/include/user_util.h                   |   13 +-
 arch/um/kernel/Makefile                       |   57 +-
 arch/um/kernel/config.c.in                    |    4 +-
 arch/um/kernel/exec_kern.c                    |    5 +
 arch/um/kernel/frame.c                        |   11 +-
 arch/um/kernel/frame_kern.c                   |    6 +-
 arch/um/kernel/helper.c                       |   62 +-
 arch/um/kernel/init_task.c                    |   17 +-
 arch/um/kernel/initrd_user.c                  |   13 +-
 arch/um/kernel/irq.c                          |  154 +-
 arch/um/kernel/irq_user.c                     |   51 +-
 arch/um/kernel/ksyms.c                        |   60 +-
 arch/um/kernel/mem.c                          |  657 +-
 arch/um/kernel/mem_user.c                     |  224 +-
 arch/um/kernel/physmem.c                      |  130 +-
 arch/um/kernel/process.c                      |  106 +-
 arch/um/kernel/process_kern.c                 |   65 +-
 arch/um/kernel/ptrace.c                       |   25 +-
 arch/um/kernel/reboot.c                       |    2 +
 arch/um/kernel/sigio_kern.c                   |   17 +-
 arch/um/kernel/sigio_user.c                   |  106 +-
 arch/um/kernel/signal_kern.c                  |   79 +-
 arch/um/kernel/signal_user.c                  |   11 +
 arch/um/kernel/skas/Makefile                  |   16 +-
 arch/um/kernel/skas/exec_user.c               |    6 +-
 arch/um/kernel/skas/include/mode.h            |    6 +-
 arch/um/kernel/skas/include/ptrace-skas.h     |   10 +
 arch/um/kernel/skas/include/skas.h            |    4 +-
 arch/um/kernel/skas/include/uaccess.h         |  207 +-
 arch/um/kernel/skas/mem_user.c                |   32 +-
 arch/um/kernel/skas/mmu.c                     |    8 +-
 arch/um/kernel/skas/process.c                 |  192 +-
 arch/um/kernel/skas/process_kern.c            |  115 +-
 arch/um/kernel/skas/sys-i386/Makefile         |    2 -
 arch/um/kernel/skas/sys-i386/sigcontext.c     |   15 +-
 arch/um/kernel/skas/syscall_kern.c            |    2 +-
 arch/um/kernel/skas/syscall_user.c            |    4 +-
 arch/um/kernel/skas/tlb.c                     |    2 +-
 arch/um/kernel/skas/trap_user.c               |    9 +-
 arch/um/kernel/skas/uaccess.c                 |   71 +-
 arch/um/kernel/skas/util/Makefile             |   12 +-
 arch/um/kernel/skas/util/mk_ptregs.c          |    1 +
 arch/um/kernel/smp.c                          |  112 +-
 arch/um/kernel/sys_call_table.c               |  687 +-
 arch/um/kernel/syscall_kern.c                 |   65 +-
 arch/um/kernel/sysrq.c                        |    5 +
 arch/um/kernel/tempfile.c                     |    7 +-
 arch/um/kernel/time.c                         |   41 +-
 arch/um/kernel/time_kern.c                    |   87 +-
 arch/um/kernel/trap_kern.c                    |   51 +-
 arch/um/kernel/trap_user.c                    |   20 +-
 arch/um/kernel/tt/Makefile                    |    6 +-
 arch/um/kernel/tt/exec_kern.c                 |   13 +-
 arch/um/kernel/tt/exec_user.c                 |    9 +-
 arch/um/kernel/tt/include/mode.h              |    2 +
 arch/um/kernel/tt/include/uaccess.h           |   60 +-
 arch/um/kernel/tt/mem.c                       |    2 +-
 arch/um/kernel/tt/mem_user.c                  |    7 +-
 arch/um/kernel/tt/process_kern.c              |  140 +-
 arch/um/kernel/tt/ptproxy/Makefile            |    2 -
 arch/um/kernel/tt/ptproxy/proxy.c             |   29 +-
 arch/um/kernel/tt/ptproxy/sysdep.c            |    1 +
 arch/um/kernel/tt/ptproxy/wait.c              |   12 +-
 arch/um/kernel/tt/sys-i386/Makefile           |    2 -
 arch/um/kernel/tt/syscall_kern.c              |    2 +-
 arch/um/kernel/tt/syscall_user.c              |    4 +-
 arch/um/kernel/tt/tlb.c                       |    1 +
 arch/um/kernel/tt/tracer.c                    |   32 +-
 arch/um/kernel/tt/trap_user.c                 |    9 +-
 arch/um/kernel/tt/uaccess.c                   |   10 +-
 arch/um/kernel/tt/uaccess_user.c              |   24 +-
 arch/um/kernel/tt/unmap.c                     |    3 -
 arch/um/kernel/tty_log.c                      |  136 +-
 arch/um/kernel/uaccess_user.c                 |    4 +-
 arch/um/kernel/um_arch.c                      |   92 +-
 arch/um/kernel/umid.c                         |   87 +-
 arch/um/kernel/user_util.c                    |   65 +-
 arch/um/os-Linux/Makefile                     |    8 +-
 arch/um/os-Linux/drivers/ethertap_kern.c      |    1 -
 arch/um/os-Linux/drivers/ethertap_user.c      |   58 +-
 arch/um/os-Linux/drivers/tuntap_user.c        |   60 +-
 arch/um/os-Linux/file.c                       |  461 +-
 arch/um/os-Linux/process.c                    |   72 +-
 arch/um/os-Linux/tty.c                        |   10 +-
 arch/um/os-Linux/user_syms.c                  |    4 +-
 arch/um/sys-i386/Makefile                     |   30 +-
 arch/um/sys-i386/bugs.c                       |  147 +-
 arch/um/sys-i386/fault.c                      |   16 +-
 arch/um/sys-i386/ldt.c                        |    2 +
 arch/um/sys-i386/ptrace_user.c                |    9 +-
 arch/um/sys-i386/syscalls.c                   |   22 +
 arch/um/sys-i386/util/Makefile                |   19 +-
 arch/um/sys-i386/util/mk_sc.c                 |    1 +
 arch/um/sys-ia64/Makefile                     |   15 +-
 arch/um/sys-ppc/Makefile                      |   11 +-
 arch/um/util/Makefile                         |   27 +-
 arch/um/util/mk_constants_kern.c              |    4 +
 arch/v850/Kconfig                             |   32 +-
 arch/v850/kernel/Makefile                     |    2 +-
 arch/v850/kernel/asm-consts.c                 |    2 +-
 arch/v850/kernel/irq.c                        |    6 +-
 arch/v850/kernel/ptrace.c                     |   17 +-
 arch/v850/kernel/rte_mb_a_pci.c               |    2 -
 arch/v850/kernel/setup.c                      |    4 +-
 arch/v850/kernel/signal.c                     |    8 +-
 arch/v850/kernel/time.c                       |   23 +-
 arch/v850/kernel/v850_ksyms.c                 |   53 +-
 arch/v850/kernel/vmlinux.lds.S                |    3 -
 arch/x86_64/Kconfig                           |  155 +-
 arch/x86_64/Makefile                          |   11 +-
 arch/x86_64/boot/Makefile                     |    2 +-
 arch/x86_64/boot/video.S                      |   86 +-
 arch/x86_64/defconfig                         |   60 +-
 arch/x86_64/ia32/ia32_binfmt.c                |    9 +-
 arch/x86_64/ia32/ia32_ioctl.c                 |   15 -
 arch/x86_64/ia32/ia32_signal.c                |   64 +-
 arch/x86_64/ia32/ia32entry.S                  |   34 +-
 arch/x86_64/ia32/ptrace32.c                   |    6 +-
 arch/x86_64/ia32/sys_ia32.c                   |   51 +-
 arch/x86_64/ia32/syscall32.c                  |   25 +-
 arch/x86_64/kernel/Makefile                   |    3 +-
 arch/x86_64/kernel/aperture.c                 |   23 +-
 arch/x86_64/kernel/apic.c                     |   62 +-
 arch/x86_64/kernel/asm-offsets.c              |    2 +-
 arch/x86_64/kernel/cpufreq/Kconfig            |   54 +
 arch/x86_64/kernel/cpufreq/Makefile           |    8 +-
 arch/x86_64/kernel/early_printk.c             |   19 +-
 arch/x86_64/kernel/entry.S                    |   19 +-
 arch/x86_64/kernel/i8259.c                    |   55 +-
 arch/x86_64/kernel/init_task.c                |    3 +-
 arch/x86_64/kernel/io_apic.c                  |  228 +-
 arch/x86_64/kernel/ioport.c                   |   40 +-
 arch/x86_64/kernel/irq.c                      |   45 +-
 arch/x86_64/kernel/ldt.c                      |   10 +-
 arch/x86_64/kernel/mce.c                      |  132 +-
 arch/x86_64/kernel/msr.c                      |  325 +-
 arch/x86_64/kernel/nmi.c                      |    3 +-
 arch/x86_64/kernel/pci-dma.c                  |   21 +-
 arch/x86_64/kernel/pci-gart.c                 |  290 +-
 arch/x86_64/kernel/pci-nommu.c                |   62 +-
 arch/x86_64/kernel/process.c                  |   85 +-
 arch/x86_64/kernel/ptrace.c                   |   21 +-
 arch/x86_64/kernel/setup.c                    |   65 +-
 arch/x86_64/kernel/setup64.c                  |   39 +-
 arch/x86_64/kernel/signal.c                   |   58 +-
 arch/x86_64/kernel/smp.c                      |   57 +-
 arch/x86_64/kernel/smpboot.c                  |   28 +-
 arch/x86_64/kernel/suspend.c                  |    2 +-
 arch/x86_64/kernel/suspend_asm.S              |   82 +-
 arch/x86_64/kernel/time.c                     |  160 +-
 arch/x86_64/kernel/traps.c                    |   77 +-
 arch/x86_64/kernel/vmlinux.lds.S              |    4 +-
 arch/x86_64/kernel/x8664_ksyms.c              |   92 +-
 arch/x86_64/lib/Makefile                      |    2 +-
 arch/x86_64/lib/bitstr.c                      |    3 +
 arch/x86_64/lib/csum-wrappers.c               |    2 +
 arch/x86_64/lib/memmove.c                     |   16 +-
 arch/x86_64/lib/usercopy.c                    |    2 +
 arch/x86_64/mm/fault.c                        |  100 +-
 arch/x86_64/mm/init.c                         |   22 +-
 arch/x86_64/mm/ioremap.c                      |   12 +-
 arch/x86_64/mm/k8topology.c                   |    4 +-
 arch/x86_64/mm/numa.c                         |   57 +-
 arch/x86_64/pci/Makefile                      |    4 +-
 crypto/Kconfig                                |   14 +-
 crypto/Makefile                               |    1 +
 crypto/aes.c                                  |   14 +-
 crypto/api.c                                  |    6 +-
 crypto/arc4.c                                 |    4 +-
 crypto/blowfish.c                             |    6 +-
 crypto/internal.h                             |    1 -
 crypto/scatterwalk.c                          |    2 +-
 crypto/tcrypt.c                               |   22 +-
 crypto/tcrypt.h                               |  255 +-
 crypto/tea.c                                  |    2 +-
 crypto/twofish.c                              |    4 +-
 drivers/Makefile                              |   12 +-
 drivers/acpi/Kconfig                          |   26 +
 drivers/acpi/Makefile                         |    2 +-
 drivers/acpi/acpi_ksyms.c                     |    2 +
 drivers/acpi/asus_acpi.c                      |  184 +-
 drivers/acpi/blacklist.c                      |   58 +-
 drivers/acpi/bus.c                            |   50 +-
 drivers/acpi/button.c                         |    9 +
 drivers/acpi/debug.c                          |  105 +-
 drivers/acpi/dispatcher/dsmethod.c            |   70 +-
 drivers/acpi/dispatcher/dsmthdat.c            |    8 +-
 drivers/acpi/dispatcher/dsopcode.c            |    7 +-
 drivers/acpi/dispatcher/dsutils.c             |   53 +-
 drivers/acpi/dispatcher/dswload.c             |   22 +
 drivers/acpi/dispatcher/dswstate.c            |   18 +-
 drivers/acpi/ec.c                             |   13 +-
 drivers/acpi/events/evevent.c                 |   12 +-
 drivers/acpi/events/evgpe.c                   |  397 +-
 drivers/acpi/events/evgpeblk.c                |  181 +-
 drivers/acpi/events/evmisc.c                  |   45 +-
 drivers/acpi/events/evregion.c                |  388 +-
 drivers/acpi/events/evrgnini.c                |   12 +-
 drivers/acpi/events/evxface.c                 |  191 +-
 drivers/acpi/events/evxfevnt.c                |  173 +-
 drivers/acpi/events/evxfregn.c                |  203 +-
 drivers/acpi/executer/exconfig.c              |   47 +-
 drivers/acpi/executer/exfldio.c               |  200 +-
 drivers/acpi/executer/exmisc.c                |  149 +-
 drivers/acpi/executer/exmutex.c               |   46 +-
 drivers/acpi/executer/exoparg2.c              |   48 +-
 drivers/acpi/executer/exresolv.c              |    8 +-
 drivers/acpi/executer/exstore.c               |   17 +-
 drivers/acpi/hardware/hwgpe.c                 |  341 +-
 drivers/acpi/hardware/hwregs.c                |  104 +-
 drivers/acpi/hardware/hwsleep.c               |   57 +-
 drivers/acpi/hardware/hwtimer.c               |   28 +-
 drivers/acpi/namespace/nsaccess.c             |    2 +-
 drivers/acpi/namespace/nsalloc.c              |    2 +-
 drivers/acpi/namespace/nseval.c               |   90 +-
 drivers/acpi/namespace/nsinit.c               |   42 +-
 drivers/acpi/namespace/nsparse.c              |    5 +-
 drivers/acpi/namespace/nsxfeval.c             |   52 +-
 drivers/acpi/namespace/nsxfname.c             |    4 +-
 drivers/acpi/numa.c                           |   16 +-
 drivers/acpi/osl.c                            |   74 +-
 drivers/acpi/parser/psopcode.c                |    8 +-
 drivers/acpi/parser/psxface.c                 |   51 +-
 drivers/acpi/pci_link.c                       |   80 +-
 drivers/acpi/power.c                          |   80 +
 drivers/acpi/processor.c                      |   81 +-
 drivers/acpi/resources/rsutils.c              |    7 +-
 drivers/acpi/resources/rsxface.c              |    3 +-
 drivers/acpi/scan.c                           |  193 +-
 drivers/acpi/sleep/Makefile                   |    2 +-
 drivers/acpi/sleep/main.c                     |   36 +-
 drivers/acpi/sleep/proc.c                     |   86 +
 drivers/acpi/sleep/sleep.h                    |    3 +
 drivers/acpi/tables.c                         |    4 +-
 drivers/acpi/tables/tbxfroot.c                |  205 +-
 drivers/acpi/thermal.c                        |   88 +-
 drivers/acpi/utilities/utalloc.c              |   13 +-
 drivers/acpi/utilities/uteval.c               |   18 +-
 drivers/acpi/utilities/utglobal.c             |   88 +-
 drivers/acpi/utilities/utxface.c              |   41 +-
 drivers/atm/Makefile                          |    2 +-
 drivers/atm/ambassador.c                      |    5 +-
 drivers/atm/eni.c                             |   73 +-
 drivers/atm/eni.h                             |   20 +-
 drivers/atm/firestream.c                      |    5 +-
 drivers/atm/firestream.h                      |    2 +-
 drivers/atm/fore200e.h                        |    2 +-
 drivers/atm/he.c                              |   17 +-
 drivers/atm/he.h                              |    2 +-
 drivers/atm/idt77252.c                        |   81 +-
 drivers/atm/idt77252.h                        |    4 +-
 drivers/atm/lanai.c                           |   12 +-
 drivers/atm/nicstar.c                         |    5 +-
 drivers/atm/nicstar.h                         |    2 +-
 drivers/atm/nicstarmac.c                      |    2 +-
 drivers/atm/nicstarmac.h                      |    2 +-
 drivers/base/class.c                          |    9 +-
 drivers/base/firmware_class.c                 |    4 +-
 drivers/base/node.c                           |   13 +-
 drivers/block/DAC960.c                        |   41 +-
 drivers/block/DAC960.h                        |  188 +-
 drivers/block/Kconfig                         |   11 +-
 drivers/block/Makefile                        |    1 +
 drivers/block/amiflop.c                       |   16 +-
 drivers/block/cciss.c                         |   71 +-
 drivers/block/cciss.h                         |    6 +-
 drivers/block/cpqarray.c                      |   14 +-
 drivers/block/cpqarray.h                      |    2 +-
 drivers/block/genhd.c                         |    4 +
 drivers/block/ioctl.c                         |    3 +-
 drivers/block/ll_rw_blk.c                     |  279 +-
 drivers/block/nbd.c                           |   39 +-
 drivers/block/rd.c                            |    9 +-
 drivers/block/scsi_ioctl.c                    |   30 +-
 drivers/block/sx8.c                           |   96 +-
 drivers/block/umem.c                          |   10 +-
 drivers/bluetooth/hci_ldisc.c                 |    8 +-
 drivers/bluetooth/hci_usb.c                   |    2 +-
 drivers/cdrom/cdrom.c                         |  177 +-
 drivers/cdrom/cdu31a.c                        |    6 +-
 drivers/cdrom/mcd.c                           |    7 +-
 drivers/cdrom/viocd.c                         |   63 +-
 drivers/char/Kconfig                          |   53 +-
 drivers/char/Makefile                         |    9 +-
 drivers/char/agp/Kconfig                      |    4 +-
 drivers/char/agp/agp.h                        |    2 +-
 drivers/char/agp/amd-k7-agp.c                 |   31 +-
 drivers/char/agp/amd64-agp.c                  |    8 +-
 drivers/char/agp/ati-agp.c                    |   31 +-
 drivers/char/agp/generic.c                    |   16 +-
 drivers/char/agp/hp-agp.c                     |   16 +-
 drivers/char/agp/intel-agp.c                  |  127 +-
 drivers/char/agp/intel-mch-agp.c              |    8 +-
 drivers/char/agp/nvidia-agp.c                 |   25 +-
 drivers/char/agp/sis-agp.c                    |    4 +
 drivers/char/agp/sworks-agp.c                 |   43 +-
 drivers/char/agp/via-agp.c                    |   33 +-
 drivers/char/amiserial.c                      |   22 +-
 drivers/char/applicom.c                       |   28 +-
 drivers/char/cyclades.c                       |  648 +-
 drivers/char/drm/Kconfig                      |   27 +-
 drivers/char/drm/Makefile                     |    2 +
 drivers/char/drm/drmP.h                       |  233 +-
 drivers/char/drm/drm_agpsupport.h             |    5 +-
 drivers/char/drm/drm_bufs.h                   |  137 +-
 drivers/char/drm/drm_context.h                |   20 +-
 drivers/char/drm/drm_dma.h                    |   53 +-
 drivers/char/drm/drm_drv.h                    |  532 +-
 drivers/char/drm/drm_fops.h                   |   15 +-
 drivers/char/drm/drm_ioctl.h                  |    6 +-
 drivers/char/drm/drm_irq.h                    |   81 +-
 drivers/char/drm/drm_memory.h                 |   38 +-
 drivers/char/drm/drm_memory_debug.h           |    2 +-
 drivers/char/drm/drm_os_linux.h               |   42 +-
 drivers/char/drm/drm_pciids.h                 |    8 +
 drivers/char/drm/drm_scatter.h                |    6 +
 drivers/char/drm/drm_vm.h                     |   44 +-
 drivers/char/drm/ffb.h                        |    4 -
 drivers/char/drm/ffb_context.c                |   30 +-
 drivers/char/drm/ffb_drv.c                    |  214 +-
 drivers/char/drm/ffb_drv.h                    |   10 +
 drivers/char/drm/gamma.h                      |   39 +-
 drivers/char/drm/gamma_context.h              |    4 +-
 drivers/char/drm/gamma_dma.c                  |   78 +-
 drivers/char/drm/gamma_drv.c                  |    1 +
 drivers/char/drm/gamma_drv.h                  |    5 +-
 drivers/char/drm/i810.h                       |   47 -
 drivers/char/drm/i810_dma.c                   |   51 +-
 drivers/char/drm/i810_drv.c                   |   17 +-
 drivers/char/drm/i810_drv.h                   |    1 -
 drivers/char/drm/i830.h                       |   50 -
 drivers/char/drm/i830_dma.c                   |   62 +-
 drivers/char/drm/i830_drv.c                   |   18 +-
 drivers/char/drm/i830_drv.h                   |    5 +-
 drivers/char/drm/i830_irq.c                   |   12 +-
 drivers/char/drm/mga.h                        |   35 -
 drivers/char/drm/mga_dma.c                    |   59 +-
 drivers/char/drm/mga_drv.c                    |   17 +-
 drivers/char/drm/mga_drv.h                    |    6 +
 drivers/char/drm/mga_irq.c                    |    4 +-
 drivers/char/drm/r128.h                       |   45 -
 drivers/char/drm/r128_cce.c                   |   45 +-
 drivers/char/drm/r128_drv.c                   |   18 +-
 drivers/char/drm/r128_drv.h                   |    7 +-
 drivers/char/drm/r128_irq.c                   |    4 +-
 drivers/char/drm/r128_state.c                 |   36 +-
 drivers/char/drm/radeon.h                     |   61 -
 drivers/char/drm/radeon_cp.c                  |   54 +-
 drivers/char/drm/radeon_drv.c                 |   18 +-
 drivers/char/drm/radeon_drv.h                 |    9 +-
 drivers/char/drm/radeon_irq.c                 |    4 +-
 drivers/char/drm/radeon_state.c               |   83 +-
 drivers/char/drm/sis.h                        |   17 -
 drivers/char/drm/sis_drv.c                    |   16 +-
 drivers/char/drm/sis_drv.h                    |    2 -
 drivers/char/drm/sis_mm.c                     |   18 +-
 drivers/char/drm/tdfx.h                       |    2 -
 drivers/char/drm/tdfx_drv.c                   |   20 +-
 drivers/char/ds1620.c                         |    3 +-
 drivers/char/dsp56k.c                         |   14 +-
 drivers/char/ec3104_keyb.c                    |    2 +-
 drivers/char/efirtc.c                         |   19 +-
 drivers/char/epca.c                           |   29 +-
 drivers/char/esp.c                            |   21 +-
 drivers/char/ftape/lowlevel/ftape-calibr.c    |   71 +-
 drivers/char/generic_serial.c                 |   14 +-
 drivers/char/hpet.c                           |   99 +-
 drivers/char/hvc_console.c                    |  754 +-
 drivers/char/hvcs.c                           |  443 +-
 drivers/char/ip2/ip2types.h                   |    3 +
 drivers/char/ip2main.c                        |   17 +-
 drivers/char/ipmi/Kconfig                     |    7 +
 drivers/char/ipmi/Makefile                    |    1 +
 drivers/char/ipmi/ipmi_bt_sm.c                |    2 +-
 drivers/char/ipmi/ipmi_devintf.c              |    2 +-
 drivers/char/ipmi/ipmi_kcs_sm.c               |    2 +-
 drivers/char/ipmi/ipmi_msghandler.c           |   58 +-
 drivers/char/ipmi/ipmi_si_intf.c              |  360 +-
 drivers/char/ipmi/ipmi_si_sm.h                |    3 +
 drivers/char/ipmi/ipmi_smic_sm.c              |    2 +-
 drivers/char/ipmi/ipmi_watchdog.c             |   71 +-
 drivers/char/isicom.c                         |   32 +-
 drivers/char/istallion.c                      |   40 +-
 drivers/char/keyboard.c                       |   33 +-
 drivers/char/mem.c                            |   10 +-
 drivers/char/moxa.c                           |   16 +-
 drivers/char/mxser.c                          |  150 +-
 drivers/char/n_tty.c                          |  382 +-
 drivers/char/nwflash.c                        |   19 +-
 drivers/char/pcmcia/synclink_cs.c             |  637 +-
 drivers/char/pcxx.c                           |   58 +-
 drivers/char/pty.c                            |  171 +-
 drivers/char/random.c                         |  234 +-
 drivers/char/rio/linux_compat.h               |    2 +-
 drivers/char/rio/rio_linux.c                  |    6 +-
 drivers/char/riscom8.c                        |   32 +-
 drivers/char/rocket.c                         |   38 +-
 drivers/char/rocket_int.h                     |    4 -
 drivers/char/selection.c                      |   11 +-
 drivers/char/ser_a2232.c                      |    5 +-
 drivers/char/serial167.c                      |   40 +-
 drivers/char/serial_tx3912.c                  |    5 +-
 drivers/char/sonypi.c                         |    5 +-
 drivers/char/sonypi.h                         |    2 -
 drivers/char/specialix.c                      |   29 +-
 drivers/char/stallion.c                       |   13 +-
 drivers/char/sx.c                             |    5 +-
 drivers/char/synclink.c                       |  647 +-
 drivers/char/synclinkmp.c                     |  783 +-
 drivers/char/tty_io.c                         |  827 ++-
 drivers/char/tty_ioctl.c                      |   63 +-
 drivers/char/viocons.c                        |    5 +-
 drivers/char/vme_scc.c                        |    8 +-
 drivers/char/vt.c                             |   52 +-
 drivers/char/vt_ioctl.c                       |    3 +-
 drivers/char/watchdog/Kconfig                 |    6 +
 drivers/char/watchdog/Makefile                |    1 +
 drivers/char/watchdog/cpu5wdt.c               |    3 +-
 drivers/char/watchdog/ib700wdt.c              |    1 +
 drivers/char/watchdog/indydog.c               |    1 +
 drivers/char/watchdog/ixp4xx_wdt.c            |    1 +
 drivers/char/watchdog/machzwd.c               |    1 +
 drivers/char/watchdog/mixcomwd.c              |    1 +
 drivers/char/watchdog/pcwd.c                  |    3 +-
 drivers/char/watchdog/sa1100_wdt.c            |    5 +
 drivers/char/watchdog/sc1200wdt.c             |    1 +
 drivers/char/watchdog/scx200_wdt.c            |    1 +
 drivers/char/watchdog/wdt285.c                |    1 +
 drivers/char/watchdog/wdt977.c                |    1 +
 drivers/char/watchdog/wdt_pci.c               |    2 +-
 drivers/cpufreq/Kconfig                       |   15 +
 drivers/cpufreq/Makefile                      |    1 +
 drivers/cpufreq/cpufreq.c                     |  172 +-
 drivers/cpufreq/cpufreq_userspace.c           |   27 +
 drivers/cpufreq/proc_intf.c                   |   17 +
 drivers/fc4/soc.h                             |   20 +-
 drivers/fc4/socal.c                           |    4 +-
 drivers/fc4/socal.h                           |    6 +-
 drivers/firmware/Kconfig                      |    5 +-
 drivers/i2c/Makefile                          |    3 +
 drivers/i2c/algos/Kconfig                     |   11 +
 drivers/i2c/algos/Makefile                    |    1 +
 drivers/i2c/algos/i2c-algo-bit.c              |    4 +-
 drivers/i2c/algos/i2c-algo-ite.c              |   14 +-
 drivers/i2c/algos/i2c-algo-pcf.c              |   12 +-
 drivers/i2c/busses/Kconfig                    |   34 +
 drivers/i2c/busses/Makefile                   |    3 +
 drivers/i2c/busses/i2c-ali1563.c              |    2 +-
 drivers/i2c/busses/i2c-ali15x3.c              |    6 +-
 drivers/i2c/busses/i2c-amd756.c               |    2 +-
 drivers/i2c/busses/i2c-amd8111.c              |    2 +-
 drivers/i2c/busses/i2c-elektor.c              |   10 +-
 drivers/i2c/busses/i2c-hydra.c                |    2 +-
 drivers/i2c/busses/i2c-i801.c                 |    6 +-
 drivers/i2c/busses/i2c-i810.c                 |    2 +-
 drivers/i2c/busses/i2c-ibm_iic.c              |    8 +-
 drivers/i2c/busses/i2c-ite.c                  |   24 +-
 drivers/i2c/busses/i2c-keywest.c              |    9 +-
 drivers/i2c/busses/i2c-nforce2.c              |    5 +-
 drivers/i2c/busses/i2c-parport-light.c        |    4 +-
 drivers/i2c/busses/i2c-parport.h              |    2 +-
 drivers/i2c/busses/i2c-piix4.c                |    2 +-
 drivers/i2c/busses/i2c-prosavage.c            |    2 +-
 drivers/i2c/busses/i2c-savage4.c              |    2 +-
 drivers/i2c/busses/i2c-sis5595.c              |    6 +-
 drivers/i2c/busses/i2c-sis630.c               |   17 +-
 drivers/i2c/busses/i2c-sis96x.c               |    2 +-
 drivers/i2c/busses/i2c-via.c                  |    2 +-
 drivers/i2c/busses/i2c-viapro.c               |    8 +-
 drivers/i2c/busses/i2c-voodoo3.c              |    2 +-
 drivers/i2c/busses/scx200_acb.c               |    6 +-
 drivers/i2c/busses/scx200_i2c.c               |   10 +-
 drivers/i2c/chips/Kconfig                     |   27 +-
 drivers/i2c/chips/Makefile                    |    3 +
 drivers/i2c/chips/adm1021.c                   |    2 +-
 drivers/i2c/chips/adm1025.c                   |    2 +-
 drivers/i2c/chips/asb100.c                    |    9 +-
 drivers/i2c/chips/ds1621.c                    |    2 +-
 drivers/i2c/chips/eeprom.c                    |    2 +-
 drivers/i2c/chips/it87.c                      |   60 +-
 drivers/i2c/chips/lm78.c                      |    4 +-
 drivers/i2c/chips/lm83.c                      |   23 +-
 drivers/i2c/chips/lm85.c                      |    9 +-
 drivers/i2c/chips/pcf8591.c                   |    2 +-
 drivers/i2c/chips/rtc8564.c                   |    4 +-
 drivers/i2c/chips/via686a.c                   |    4 +-
 drivers/i2c/chips/w83627hf.c                  |   16 +-
 drivers/i2c/chips/w83781d.c                   |   13 +-
 drivers/ide/Kconfig                           |   12 +-
 drivers/ide/arm/Makefile                      |    1 +
 drivers/ide/arm/icside.c                      |    5 -
 drivers/ide/ide-cd.c                          |   14 +-
 drivers/ide/ide-disk.c                        |  179 +-
 drivers/ide/ide-dma.c                         |   13 +-
 drivers/ide/ide-io.c                          |  267 +-
 drivers/ide/ide-iops.c                        |   26 +-
 drivers/ide/ide-lib.c                         |    4 -
 drivers/ide/ide-probe.c                       |   43 +-
 drivers/ide/ide-proc.c                        |   27 +-
 drivers/ide/ide-tape.c                        |   74 -
 drivers/ide/ide-taskfile.c                    |  202 +-
 drivers/ide/ide.c                             |  218 +-
 drivers/ide/legacy/Makefile                   |    1 -
 drivers/ide/legacy/ide-cs.c                   |    6 -
 drivers/ide/legacy/pdc4030.c                  |  116 +-
 drivers/ide/legacy/qd65xx.h                   |    6 +-
 drivers/ide/pci/aec62xx.c                     |   49 +-
 drivers/ide/pci/aec62xx.h                     |    7 -
 drivers/ide/pci/alim15x3.c                    |    6 +-
 drivers/ide/pci/amd74xx.c                     |    5 +-
 drivers/ide/pci/atiixp.c                      |    2 +-
 drivers/ide/pci/cmd640.c                      |    6 +-
 drivers/ide/pci/cmd64x.c                      |   19 +-
 drivers/ide/pci/cmd64x.h                      |    4 -
 drivers/ide/pci/cs5520.c                      |    7 +-
 drivers/ide/pci/cy82c693.c                    |    2 +-
 drivers/ide/pci/generic.c                     |    2 +-
 drivers/ide/pci/hpt34x.c                      |   70 +-
 drivers/ide/pci/hpt34x.h                      |    2 -
 drivers/ide/pci/hpt366.c                      |   15 +-
 drivers/ide/pci/it8172.c                      |    2 +-
 drivers/ide/pci/ns87415.c                     |    2 +-
 drivers/ide/pci/opti621.c                     |    2 +-
 drivers/ide/pci/pdc202xx_new.c                |    2 +-
 drivers/ide/pci/pdc202xx_old.c                |   13 +-
 drivers/ide/pci/pdc202xx_old.h                |   71 -
 drivers/ide/pci/piix.c                        |   45 +-
 drivers/ide/pci/rz1000.c                      |    2 +-
 drivers/ide/pci/sc1200.c                      |    2 +-
 drivers/ide/pci/serverworks.c                 |    2 +-
 drivers/ide/pci/sgiioc4.c                     |    7 +-
 drivers/ide/pci/siimage.c                     |   52 +-
 drivers/ide/pci/sis5513.c                     |   12 +-
 drivers/ide/pci/sl82c105.c                    |    2 +-
 drivers/ide/pci/slc90e66.c                    |    2 +-
 drivers/ide/pci/triflex.c                     |   64 +-
 drivers/ide/pci/trm290.c                      |    2 +-
 drivers/ide/pci/via82cxxx.c                   |    2 +-
 drivers/ide/ppc/pmac.c                        |   83 +-
 drivers/ieee1394/eth1394.c                    |    4 +-
 drivers/ieee1394/eth1394.h                    |    7 +
 drivers/ieee1394/ohci1394.h                   |    2 +-
 drivers/input/gameport/cs461x.c               |    2 +-
 drivers/input/gameport/emu10k1-gp.c           |    5 +-
 drivers/input/gameport/fm801-gp.c             |    2 +-
 drivers/input/gameport/vortex.c               |    6 +-
 drivers/input/joydev.c                        |    6 +-
 drivers/input/joystick/Kconfig                |    4 +-
 drivers/input/joystick/gamecon.c              |  194 +-
 drivers/input/joystick/grip_mp.c              |    3 +-
 drivers/input/joystick/iforce/iforce-main.c   |    4 +-
 drivers/input/joystick/iforce/iforce-serio.c  |   18 +-
 drivers/input/joystick/iforce/iforce.h        |    2 +-
 drivers/input/joystick/magellan.c             |   24 +-
 drivers/input/joystick/spaceball.c            |   24 +-
 drivers/input/joystick/spaceorb.c             |   24 +-
 drivers/input/joystick/stinger.c              |   24 +-
 drivers/input/joystick/tmdc.c                 |    2 +-
 drivers/input/joystick/twidjoy.c              |   20 +-
 drivers/input/joystick/warrior.c              |   24 +-
 drivers/input/keyboard/atkbd.c                |  285 +-
 drivers/input/keyboard/lkkbd.c                |   24 +-
 drivers/input/keyboard/newtonkbd.c            |   24 +-
 drivers/input/keyboard/sunkbd.c               |   24 +-
 drivers/input/keyboard/xtkbd.c                |   24 +-
 drivers/input/misc/Kconfig                    |    2 +-
 drivers/input/misc/uinput.c                   |    3 +
 drivers/input/mouse/Kconfig                   |    2 -
 drivers/input/mouse/logips2pp.c               |    2 +-
 drivers/input/mouse/pc110pad.c                |    6 +-
 drivers/input/mouse/psmouse-base.c            |  312 +-
 drivers/input/mouse/psmouse.h                 |   40 +-
 drivers/input/mouse/sermouse.c                |   24 +-
 drivers/input/mouse/synaptics.c               |   54 +-
 drivers/input/mouse/vsxxxaa.c                 |   24 +-
 drivers/input/mousedev.c                      |  237 +-
 drivers/input/serio/Kconfig                   |   18 +-
 drivers/input/serio/Makefile                  |    1 +
 drivers/input/serio/ambakmi.c                 |   44 +-
 drivers/input/serio/ct82c710.c                |  104 +-
 drivers/input/serio/gscps2.c                  |   64 +-
 drivers/input/serio/i8042-io.h                |   31 +
 drivers/input/serio/i8042-sparcio.h           |    8 +-
 drivers/input/serio/i8042.c                   |  353 +-
 drivers/input/serio/i8042.h                   |    7 +
 drivers/input/serio/maceps2.c                 |   86 +-
 drivers/input/serio/parkbd.c                  |   48 +-
 drivers/input/serio/pcips2.c                  |   54 +-
 drivers/input/serio/q40kbd.c                  |  117 +-
 drivers/input/serio/rpckbd.c                  |   48 +-
 drivers/input/serio/sa1111ps2.c               |   41 +-
 drivers/input/serio/serio.c                   |  576 +-
 drivers/input/serio/serport.c                 |   49 +-
 drivers/input/touchscreen/gunze.c             |   24 +-
 drivers/input/touchscreen/h3600_ts_input.c    |   24 +-
 drivers/input/tsdev.c                         |  301 +-
 drivers/isdn/act2000/act2000_isa.c            |    5 +-
 drivers/isdn/capi/capi.c                      |   90 +-
 drivers/isdn/capi/capidrv.c                   |    3 +-
 drivers/isdn/hardware/avm/b1.c                |    8 +-
 drivers/isdn/hardware/avm/b1dma.c             |    2 -
 drivers/isdn/hardware/avm/c4.c                |    2 -
 drivers/isdn/hardware/avm/t1isa.c             |    7 +-
 drivers/isdn/hardware/eicon/capifunc.c        |    5 +-
 drivers/isdn/hardware/eicon/capifunc.h        |    4 +-
 drivers/isdn/hardware/eicon/debug.c           |  488 +-
 drivers/isdn/hardware/eicon/debug_if.h        |    6 +
 drivers/isdn/hardware/eicon/debuglib.h        |    6 +-
 drivers/isdn/hardware/eicon/diddfunc.c        |    4 +-
 drivers/isdn/hardware/eicon/diva_didd.c       |   10 +-
 drivers/isdn/hardware/eicon/divamnt.c         |  236 +-
 drivers/isdn/hardware/eicon/divasfunc.c       |   12 +-
 drivers/isdn/hardware/eicon/divasync.h        |   21 +-
 drivers/isdn/hardware/eicon/idifunc.c         |    4 +-
 drivers/isdn/hardware/eicon/io.c              |   50 +-
 drivers/isdn/hardware/eicon/io.h              |   63 +-
 drivers/isdn/hardware/eicon/maintidi.c        |   51 +-
 drivers/isdn/hardware/eicon/maintidi.h        |    4 +-
 drivers/isdn/hardware/eicon/mntfunc.c         |  103 +-
 drivers/isdn/hardware/eicon/pc.h              |   87 +
 drivers/isdn/hardware/eicon/platform.h        |   37 +-
 drivers/isdn/hisax/avm_pci.c                  |  106 +-
 drivers/isdn/hisax/bkm_a4t.c                  |    4 +-
 drivers/isdn/hisax/bkm_a8.c                   |    4 +-
 drivers/isdn/hisax/diva.c                     |    2 +-
 drivers/isdn/hisax/elsa.c                     |    2 +-
 drivers/isdn/hisax/enternow_pci.c             |    2 +-
 drivers/isdn/hisax/gazel.c                    |    2 +-
 drivers/isdn/hisax/hfc_pci.c                  |    4 +-
 drivers/isdn/hisax/niccy.c                    |    2 +-
 drivers/isdn/hisax/nj_s.c                     |    2 +-
 drivers/isdn/hisax/nj_u.c                     |    4 +-
 drivers/isdn/hisax/sedlbauer.c                |    2 +-
 drivers/isdn/hisax/st5481_usb.c               |    3 -
 drivers/isdn/hisax/telespci.c                 |    2 +-
 drivers/isdn/hisax/w6692.c                    |    2 +-
 drivers/isdn/i4l/isdn_net.c                   |    2 +-
 drivers/isdn/i4l/isdn_tty.c                   |   21 +-
 drivers/isdn/tpam/tpam_main.c                 |   47 +-
 drivers/macintosh/adbhid.c                    |  146 +-
 drivers/macintosh/ans-lcd.c                   |    6 +-
 drivers/macintosh/macserial.c                 |   22 +-
 drivers/macintosh/therm_adt746x.c             |   80 +-
 drivers/macintosh/therm_windtunnel.c          |    3 +-
 drivers/macintosh/via-pmu.c                   |   22 +-
 drivers/md/Kconfig                            |   18 +
 drivers/md/Makefile                           |    3 +-
 drivers/md/dm-log.c                           |  110 +-
 drivers/md/dm-log.h                           |    6 +
 drivers/md/dm-raid1.c                         |   29 +-
 drivers/md/dm-stripe.c                        |    9 +-
 drivers/md/dm-table.c                         |   25 +-
 drivers/md/dm.c                               |  142 +-
 drivers/md/dm.h                               |    4 +
 drivers/md/linear.c                           |   25 +-
 drivers/md/md.c                               |  207 +-
 drivers/md/multipath.c                        |   43 +-
 drivers/md/raid0.c                            |   29 +-
 drivers/md/raid1.c                            |  124 +-
 drivers/md/raid5.c                            |   41 +-
 drivers/md/raid6main.c                        |   41 +-
 drivers/media/common/saa7146_i2c.c            |   21 +-
 drivers/media/dvb/b2c2/skystar2.c             |    2 +-
 drivers/media/dvb/bt8xx/bt878.c               |   12 +-
 drivers/media/dvb/dvb-core/dvb_ca_en50221.c   |   27 +-
 drivers/media/dvb/dvb-core/dvb_net.c          |    4 +-
 drivers/media/dvb/frontends/alps_tdlb7.c      |    3 -
 drivers/media/dvb/frontends/dst.c             |    6 +-
 drivers/media/dvb/frontends/sp887x.c          |    2 -
 drivers/media/dvb/frontends/stv0299.c         |   12 +-
 drivers/media/dvb/frontends/tda1004x.c        |    2 -
 drivers/media/dvb/ttpci/Kconfig               |    8 +-
 drivers/media/dvb/ttpci/Makefile              |    2 +-
 drivers/media/dvb/ttusb-dec/ttusb_dec.c       |    2 +-
 drivers/media/radio/miropcm20-rds.c           |    4 +-
 drivers/media/radio/radio-aimslab.c           |    7 +-
 drivers/media/radio/radio-cadet.c             |    6 +-
 drivers/media/radio/radio-maestro.c           |   54 +-
 drivers/media/radio/radio-maxiradio.c         |    9 +-
 drivers/media/radio/radio-sf16fmi.c           |    6 +-
 drivers/media/radio/radio-sf16fmr2.c          |   15 +-
 drivers/media/video/Kconfig                   |    2 +-
 drivers/media/video/adv7175.c                 |   28 +
 drivers/media/video/bttv-cards.c              |   90 +-
 drivers/media/video/bttv-driver.c             |   13 +-
 drivers/media/video/bttv-gpio.c               |   14 +
 drivers/media/video/bttv-i2c.c                |   12 +
 drivers/media/video/bttv-risc.c               |   30 +-
 drivers/media/video/bttv.h                    |    6 +
 drivers/media/video/bttvp.h                   |    1 +
 drivers/media/video/cpia.c                    |   38 +-
 drivers/media/video/dpc7146.c                 |    1 +
 drivers/media/video/meye.c                    |    2 +-
 drivers/media/video/msp3400.c                 |    7 +-
 drivers/media/video/saa7134/saa6752hs.c       |    7 +-
 drivers/media/video/saa7134/saa7134-cards.c   |  132 +-
 drivers/media/video/saa7134/saa7134-core.c    |    7 +-
 drivers/media/video/saa7134/saa7134-i2c.c     |    2 +
 drivers/media/video/saa7134/saa7134-oss.c     |    2 -
 drivers/media/video/saa7134/saa7134-tvaudio.c |    8 +-
 drivers/media/video/saa7134/saa7134-video.c   |   48 +-
 drivers/media/video/saa7134/saa7134.h         |    8 +-
 drivers/media/video/tda7432.c                 |    8 +-
 drivers/media/video/tda9875.c                 |    7 +-
 drivers/media/video/tda9887.c                 |   67 +-
 drivers/media/video/tuner.c                   |   21 +-
 drivers/media/video/tvaudio.c                 |    8 +-
 drivers/media/video/tvmixer.c                 |    8 +-
 drivers/media/video/videodev.c                |    2 +-
 drivers/media/video/zoran_device.c            |    3 +-
 drivers/media/video/zoran_driver.c            |    4 +-
 drivers/message/fusion/Kconfig                |   33 -
 drivers/message/fusion/Makefile               |    3 +-
 drivers/message/fusion/mptbase.c              | 1056 ++-
 drivers/message/fusion/mptbase.h              |  170 +-
 drivers/message/fusion/mptctl.c               |  169 +-
 drivers/message/fusion/mptlan.c               |  154 +-
 drivers/message/fusion/mptscsih.c             | 1831 ++---
 drivers/message/i2o/Makefile                  |    1 +
 drivers/message/i2o/i2o_block.c               | 2321 +++---
 drivers/message/i2o/i2o_config.c              | 1371 ++--
 drivers/message/i2o/i2o_proc.c                | 4032 ++++-------
 drivers/message/i2o/i2o_scsi.c                | 1401 ++--
 drivers/misc/ibmasm/module.c                  |   12 +-
 drivers/mtd/chips/cfi_cmdset_0001.c           |    5 +-
 drivers/mtd/chips/jedec_probe.c               |   44 +-
 drivers/mtd/maps/Kconfig                      |    9 +
 drivers/mtd/maps/Makefile                     |    1 +
 drivers/mtd/maps/amd76xrom.c                  |   15 +-
 drivers/mtd/maps/ceiva.c                      |    4 +-
 drivers/mtd/maps/edb7312.c                    |    8 +-
 drivers/mtd/maps/impa7.c                      |    4 +-
 drivers/mtd/maps/ixp4xx.c                     |   28 +-
 drivers/mtd/maps/lubbock-flash.c              |   10 +-
 drivers/mtd/maps/nettel.c                     |    2 +-
 drivers/mtd/maps/sa1100-flash.c               |    4 +-
 drivers/mtd/maps/tqm8xxl.c                    |    8 +-
 drivers/mtd/maps/uclinux.c                    |    7 +-
 drivers/mtd/nftlmount.c                       |    6 +-
 drivers/net/3c507.c                           |    2 +-
 drivers/net/3c527.c                           |   13 +-
 drivers/net/3c59x.c                           |   90 +-
 drivers/net/8139cp.c                          |    2 +-
 drivers/net/8139too.c                         |   70 +-
 drivers/net/8390.c                            |   46 +-
 drivers/net/8390.h                            |   12 +-
 drivers/net/Kconfig                           |   69 +-
 drivers/net/Makefile                          |    5 +
 drivers/net/acenic.c                          |  156 +-
 drivers/net/acenic.h                          |    2 +-
 drivers/net/amd8111e.c                        |    2 +-
 drivers/net/arcnet/arc-rimi.c                 |   12 +-
 drivers/net/arcnet/arcnet.c                   |    3 +-
 drivers/net/arcnet/com90xx.c                  |    4 +-
 drivers/net/b44.c                             |  199 +-
 drivers/net/b44.h                             |    5 +-
 drivers/net/bonding/bond_alb.c                |    2 +-
 drivers/net/cs89x0.c                          |   29 +-
 drivers/net/cs89x0.h                          |   19 +-
 drivers/net/defxx.c                           |   22 +-
 drivers/net/dl2k.h                            |    2 +-
 drivers/net/e100.c                            |   89 +-
 drivers/net/e1000/e1000.h                     |   24 +-
 drivers/net/e1000/e1000_ethtool.c             |  146 +-
 drivers/net/e1000/e1000_hw.c                  |   16 +-
 drivers/net/e1000/e1000_hw.h                  |    3 +-
 drivers/net/e1000/e1000_main.c                |  526 +-
 drivers/net/e1000/e1000_param.c               |   48 +-
 drivers/net/eepro100.c                        |   17 -
 drivers/net/epic100.c                         |  432 +-
 drivers/net/forcedeth.c                       |   78 +-
 drivers/net/gianfar.c                         |  584 +-
 drivers/net/gianfar.h                         |   46 +-
 drivers/net/gianfar_ethtool.c                 |  221 +-
 drivers/net/gianfar_phy.c                     |  899 +--
 drivers/net/gianfar_phy.h                     |  295 +-
 drivers/net/gt96100eth.c                      |  119 +-
 drivers/net/hamachi.c                         |    2 +-
 drivers/net/hamradio/bpqether.c               |    2 +-
 drivers/net/hamradio/dmascc.c                 |  290 +-
 drivers/net/hamradio/mkiss.c                  |    2 -
 drivers/net/hp100.c                           |   21 +-
 drivers/net/ibm_emac/ibm_emac.h               |   32 +-
 drivers/net/ibm_emac/ibm_emac_core.c          |   74 +-
 drivers/net/ibm_emac/ibm_emac_core.h          |    2 +-
 drivers/net/ibm_emac/ibm_emac_mal.c           |    4 -
 drivers/net/ibmveth.c                         |   28 +-
 drivers/net/ibmveth.h                         |    2 +
 drivers/net/ioc3-eth.c                        |    4 +-
 drivers/net/irda/irda-usb.c                   |    3 -
 drivers/net/irda/irtty-sir.c                  |    7 -
 drivers/net/ixgb/ixgb_main.c                  |  132 +-
 drivers/net/lasi_82596.c                      |    2 -
 drivers/net/loopback.c                        |   13 +
 drivers/net/myri_sbus.c                       |   69 +-
 drivers/net/myri_sbus.h                       |   17 +-
 drivers/net/natsemi.c                         |  282 +-
 drivers/net/ne.c                              |   30 +-
 drivers/net/plip.c                            |    2 +-
 drivers/net/ppp_async.c                       |   18 +-
 drivers/net/ppp_generic.c                     |    1 +
 drivers/net/ppp_synctty.c                     |    2 +
 drivers/net/pppoe.c                           |    4 +-
 drivers/net/r8169.c                           |  669 +-
 drivers/net/rrunner.c                         |   86 +-
 drivers/net/s2io.c                            |    8 +-
 drivers/net/sis900.c                          |    1 +
 drivers/net/sk98lin/h/skdrv2nd.h              |   54 -
 drivers/net/sk98lin/skaddr.c                  |    4 +-
 drivers/net/sk98lin/skge.c                    |  746 +-
 drivers/net/skfp/skfddi.c                     |   20 +-
 drivers/net/slip.c                            |   24 +-
 drivers/net/smc9194.c                         |  255 +-
 drivers/net/smc91x.c                          |   31 +-
 drivers/net/smc91x.h                          |   22 +-
 drivers/net/sunbmac.c                         |   40 +-
 drivers/net/sunbmac.h                         |    8 +-
 drivers/net/sundance.c                        |    2 +-
 drivers/net/sungem.c                          |  246 +-
 drivers/net/sungem.h                          |    7 +-
 drivers/net/sunhme.c                          |   77 +-
 drivers/net/sunhme.h                          |   14 +-
 drivers/net/sunlance.c                        |   64 +-
 drivers/net/sunqe.c                           |   14 +-
 drivers/net/sunqe.h                           |    6 +-
 drivers/net/tg3.c                             |  910 +--
 drivers/net/tg3.h                             |   17 +-
 drivers/net/tokenring/Kconfig                 |    3 +-
 drivers/net/tokenring/ibmtr.c                 |    2 +-
 drivers/net/tokenring/olympic.c               |  117 +-
 drivers/net/tokenring/olympic.h               |    4 +-
 drivers/net/tulip/Kconfig                     |    4 +-
 drivers/net/tulip/de4x5.c                     |   16 +-
 drivers/net/tulip/dmfe.c                      |   30 +-
 drivers/net/typhoon.c                         |   53 +-
 drivers/net/via-rhine.c                       |  739 +-
 drivers/net/via-velocity.c                    |  640 +-
 drivers/net/via-velocity.h                    |   16 +-
 drivers/net/wan/cycx_x25.c                    |    6 +-
 drivers/net/wan/dscc4.c                       |   33 +-
 drivers/net/wan/hd6457x.c                     |    6 +-
 drivers/net/wan/lmc/lmc_debug.c               |    2 +-
 drivers/net/wan/pc300.h                       |   14 +-
 drivers/net/wan/pc300_drv.c                   |  153 +-
 drivers/net/wan/pc300_tty.c                   |   54 +-
 drivers/net/wan/sdla_chdlc.c                  |   20 +-
 drivers/net/wan/sdla_fr.c                     |    4 +-
 drivers/net/wan/sdladrv.c                     |    6 +-
 drivers/net/wan/sdlamain.c                    |    2 +-
 drivers/net/wan/syncppp.c                     |    8 +-
 drivers/net/wireless/airo.c                   |  140 +-
 drivers/net/wireless/airport.c                |   52 +-
 drivers/net/wireless/atmel.c                  |    5 +-
 drivers/net/wireless/hermes.c                 |   12 +-
 drivers/net/wireless/hermes.h                 |  133 +-
 drivers/net/wireless/hermes_rid.h             |   99 +-
 drivers/net/wireless/ieee802_11.h             |    1 -
 drivers/net/wireless/orinoco.c                | 2805 ++++----
 drivers/net/wireless/orinoco.h                |   36 +-
 drivers/net/wireless/orinoco_cs.c             |   70 +-
 drivers/net/wireless/orinoco_pci.c            |   52 +-
 drivers/net/wireless/orinoco_plx.c            |  204 +-
 drivers/net/wireless/orinoco_tmd.c            |   56 +-
 drivers/net/wireless/prism54/isl_38xx.c       |   12 +-
 drivers/net/wireless/prism54/isl_38xx.h       |   14 +-
 drivers/net/wireless/prism54/isl_ioctl.c      |    5 +-
 drivers/net/wireless/prism54/islpci_dev.c     |    8 +-
 drivers/net/wireless/prism54/islpci_dev.h     |    2 +-
 drivers/net/wireless/ray_cs.c                 |  157 +-
 drivers/net/wireless/ray_cs.h                 |    6 +-
 drivers/net/wireless/strip.c                  |   25 +-
 drivers/net/wireless/wavelan.c                |   11 +-
 drivers/oprofile/buffer_sync.c                |  279 +-
 drivers/oprofile/buffer_sync.h                |    3 +
 drivers/oprofile/cpu_buffer.c                 |  101 +-
 drivers/oprofile/cpu_buffer.h                 |   11 +-
 drivers/oprofile/oprofile_stats.c             |   13 +-
 drivers/oprofile/timer_int.c                  |    2 +-
 drivers/parisc/lasi.c                         |    2 +-
 drivers/parisc/superio.c                      |    3 +-
 drivers/parport/parport_pc.c                  |   84 +-
 drivers/pci/Makefile                          |    2 +-
 drivers/pci/hotplug/Kconfig                   |   12 +
 drivers/pci/hotplug/Makefile                  |    1 +
 drivers/pci/hotplug/acpiphp.h                 |   16 +
 drivers/pci/hotplug/acpiphp_core.c            |  127 +-
 drivers/pci/hotplug/acpiphp_glue.c            |   14 -
 drivers/pci/hotplug/cpci_hotplug_core.c       |   18 +-
 drivers/pci/hotplug/cpcihp_zt5550.c           |    4 +-
 drivers/pci/hotplug/cpqphp_core.c             |    4 +-
 drivers/pci/hotplug/ibmphp.h                  |    6 -
 drivers/pci/hotplug/ibmphp_core.c             |    4 +-
 drivers/pci/hotplug/ibmphp_hpc.c              |   20 +-
 drivers/pci/hotplug/pci_hotplug_core.c        |    2 +-
 drivers/pci/hotplug/pciehp_core.c             |    6 +-
 drivers/pci/hotplug/pciehp_hpc.c              |    4 +-
 drivers/pci/hotplug/pcihp_skeleton.c          |    2 +-
 drivers/pci/hotplug/rpaphp_core.c             |   10 +-
 drivers/pci/hotplug/rpaphp_pci.c              |   27 +-
 drivers/pci/hotplug/rpaphp_slot.c             |   12 +-
 drivers/pci/hotplug/shpchp_core.c             |    6 +-
 drivers/pci/hotplug/shpchp_ctrl.c             |    4 +-
 drivers/pci/hotplug/shpchp_hpc.c              |    4 +-
 drivers/pci/pci-driver.c                      |   22 +-
 drivers/pci/pci.c                             |    7 +-
 drivers/pci/pci.ids                           |  572 +-
 drivers/pci/probe.c                           |   13 +-
 drivers/pci/quirks.c                          |  372 +-
 drivers/pci/remove.c                          |   20 +-
 drivers/pci/setup-bus.c                       |    5 +-
 drivers/pcmcia/au1000_generic.c               |   15 +-
 drivers/pcmcia/cardbus.c                      |    2 +-
 drivers/pcmcia/cistpl.c                       |   12 +-
 drivers/pcmcia/cs.c                           |   37 +-
 drivers/pcmcia/ds.c                           |    6 +-
 drivers/pcmcia/hd64465_ss.c                   |   11 +-
 drivers/pcmcia/i82092.c                       |   20 +-
 drivers/pcmcia/i82365.c                       |   17 +-
 drivers/pcmcia/pd6729.c                       |   14 +-
 drivers/pcmcia/pxa2xx_base.c                  |   34 +-
 drivers/pcmcia/pxa2xx_lubbock.c               |   32 +-
 drivers/pcmcia/pxa2xx_mainstone.c             |   24 +
 drivers/pcmcia/rsrc_mgr.c                     |   71 +-
 drivers/pcmcia/sa1100_h3600.c                 |    4 +-
 drivers/pcmcia/soc_common.c                   |   14 +-
 drivers/pcmcia/tcic.c                         |   12 +-
 drivers/pcmcia/yenta_socket.c                 |   10 +-
 drivers/pcmcia/yenta_socket.h                 |    2 +-
 drivers/pnp/interface.c                       |   10 +-
 drivers/pnp/isapnp/core.c                     |    4 +-
 drivers/pnp/pnpbios/bioscalls.c               |   14 +-
 drivers/pnp/pnpbios/core.c                    |    4 +-
 drivers/pnp/pnpbios/proc.c                    |    8 +-
 drivers/pnp/pnpbios/rsparser.c                |    9 +-
 drivers/pnp/system.c                          |    6 +-
 drivers/s390/block/dasd_diag.c                |    7 +-
 drivers/s390/block/dasd_eckd.c                |   20 +-
 drivers/s390/block/dcssblk.c                  |   56 +
 drivers/s390/char/con3215.c                   |   10 +-
 drivers/s390/char/sclp.c                      |   43 +-
 drivers/s390/char/sclp_tty.c                  |    5 +-
 drivers/s390/char/sclp_vt220.c                |    5 +-
 drivers/s390/cio/blacklist.c                  |    4 +-
 drivers/s390/cio/ccwgroup.c                   |   16 +-
 drivers/s390/cio/cio.c                        |   15 +-
 drivers/s390/cio/cmf.c                        |   95 +-
 drivers/s390/cio/css.c                        |    5 +-
 drivers/s390/cio/device.c                     |   26 +-
 drivers/s390/cio/device_fsm.c                 |    1 +
 drivers/s390/cio/device_id.c                  |    4 +-
 drivers/s390/cio/qdio.c                       |    4 +-
 drivers/s390/net/ctctty.c                     |   12 +-
 drivers/s390/net/lcs.c                        |  452 +-
 drivers/s390/net/lcs.h                        |   17 +-
 drivers/s390/net/qeth_main.c                  |   61 +-
 drivers/s390/s390mach.h                       |    4 -
 drivers/s390/scsi/zfcp_aux.c                  |  512 +-
 drivers/s390/scsi/zfcp_def.h                  |  188 +-
 drivers/s390/scsi/zfcp_erp.c                  |  276 +-
 drivers/s390/scsi/zfcp_ext.h                  |   30 +-
 drivers/s390/scsi/zfcp_fsf.c                  |  344 +-
 drivers/s390/scsi/zfcp_fsf.h                  |   11 +-
 drivers/s390/scsi/zfcp_scsi.c                 |   31 +-
 drivers/s390/scsi/zfcp_sysfs_adapter.c        |   45 +-
 drivers/s390/scsi/zfcp_sysfs_driver.c         |    4 +-
 drivers/s390/scsi/zfcp_sysfs_port.c           |   37 +-
 drivers/s390/scsi/zfcp_sysfs_unit.c           |   29 +-
 drivers/sbus/char/aurora.c                    |   13 +-
 drivers/sbus/char/bbc_envctrl.c               |    5 +-
 drivers/sbus/char/bbc_i2c.c                   |    4 +-
 drivers/sbus/char/cpwatchdog.c                |   82 +-
 drivers/sbus/char/display7seg.c               |    2 +-
 drivers/sbus/char/envctrl.c                   |   65 +-
 drivers/sbus/char/flash.c                     |    3 +-
 drivers/sbus/dvma.c                           |   11 -
 drivers/scsi/3w-xxxx.c                        |    6 +-
 drivers/scsi/BusLogic.c                       | 6396 ++++++++---------
 drivers/scsi/BusLogic.h                       | 1468 ++--
 drivers/scsi/Kconfig                          |   27 +-
 drivers/scsi/Makefile                         |    4 +-
 drivers/scsi/NCR5380.c                        |  222 +-
 drivers/scsi/NCR5380.h                        |    3 +-
 drivers/scsi/NCR53C9x.c                       |   16 +-
 drivers/scsi/NCR53c406a.c                     |   11 +-
 drivers/scsi/NCR_Q720.c                       |   21 +-
 drivers/scsi/aacraid/README                   |   14 +-
 drivers/scsi/aacraid/aachba.c                 |   71 +-
 drivers/scsi/aacraid/aacraid.h                |   25 +-
 drivers/scsi/aacraid/commctrl.c               |    2 +-
 drivers/scsi/aacraid/commsup.c                |    2 +-
 drivers/scsi/aacraid/linit.c                  |  179 +-
 drivers/scsi/advansys.c                       |   20 +-
 drivers/scsi/advansys.h                       |   26 -
 drivers/scsi/aha1542.c                        |    4 +-
 drivers/scsi/aha1542.h                        |   10 +-
 drivers/scsi/aic7xxx/Kconfig.aic79xx          |    2 +-
 drivers/scsi/aic7xxx/Kconfig.aic7xxx          |    2 +-
 drivers/scsi/aic7xxx/aic79xx_osm.c            |   41 +-
 drivers/scsi/aic7xxx/aic79xx_pci.c            |    4 +-
 drivers/scsi/aic7xxx/aic7xxx_osm.c            |   12 +-
 drivers/scsi/aic7xxx/aic7xxx_pci.c            |    4 +-
 drivers/scsi/aic7xxx/aicasm/Makefile          |    6 +-
 drivers/scsi/aic7xxx_old.c                    |    9 +-
 drivers/scsi/arm/cumana_1.c                   |    1 +
 drivers/scsi/arm/ecoscsi.c                    |    1 +
 drivers/scsi/arm/eesox.c                      |   30 +-
 drivers/scsi/arm/fas216.c                     |    4 +-
 drivers/scsi/arm/oak.c                        |    1 +
 drivers/scsi/ata_piix.c                       |  174 +-
 drivers/scsi/atp870u.c                        |    6 +-
 drivers/scsi/cpqfcTScontrol.c                 |    1 -
 drivers/scsi/cpqfcTSinit.c                    |   51 +-
 drivers/scsi/dc395x.c                         |   46 +-
 drivers/scsi/dmx3191d.c                       |    3 +-
 drivers/scsi/dtc.c                            |    1 +
 drivers/scsi/eata_pio.c                       |    5 +-
 drivers/scsi/esp.h                            |    4 +-
 drivers/scsi/fd_mcs.c                         |   11 +-
 drivers/scsi/fdomain.c                        |   51 +-
 drivers/scsi/g_NCR5380.c                      |    6 +-
 drivers/scsi/gdth.c                           |  120 +-
 drivers/scsi/gdth.h                           |    2 +-
 drivers/scsi/hosts.c                          |    2 +-
 drivers/scsi/imm.c                            |    2 +-
 drivers/scsi/ipr.c                            |  240 +-
 drivers/scsi/ipr.h                            |   24 +-
 drivers/scsi/ips.c                            |  136 +-
 drivers/scsi/libata-core.c                    | 1201 ++--
 drivers/scsi/libata-scsi.c                    |  426 +-
 drivers/scsi/libata.h                         |    3 +-
 drivers/scsi/mac_scsi.c                       |    1 +
 drivers/scsi/mca_53c9x.c                      |   14 +-
 drivers/scsi/megaraid.c                       |   10 +-
 drivers/scsi/nsp32.c                          |    8 +-
 drivers/scsi/pas16.c                          |    1 +
 drivers/scsi/pcmcia/nsp_cs.c                  |    2 +-
 drivers/scsi/qla1280.c                        | 1024 +--
 drivers/scsi/qla1280.h                        |   57 +-
 drivers/scsi/qla2xxx/ql2100.c                 |    1 +
 drivers/scsi/qla2xxx/ql2200.c                 |    1 +
 drivers/scsi/qla2xxx/ql2300.c                 |    1 +
 drivers/scsi/qla2xxx/ql2322.c                 |    1 +
 drivers/scsi/qla2xxx/ql6312.c                 |    1 +
 drivers/scsi/qla2xxx/ql6322.c                 |    1 +
 drivers/scsi/qla2xxx/qla_init.c               |   14 +-
 drivers/scsi/qla2xxx/qla_iocb.c               |   16 +-
 drivers/scsi/qla2xxx/qla_os.c                 |    7 +-
 drivers/scsi/qla2xxx/qla_version.h            |    4 +-
 drivers/scsi/qlogicpti.c                      |    2 +-
 drivers/scsi/qlogicpti.h                      |    4 +-
 drivers/scsi/sata_nv.c                        |   96 +-
 drivers/scsi/sata_promise.c                   |   87 +-
 drivers/scsi/sata_sil.c                       |   23 +-
 drivers/scsi/sata_sis.c                       |   61 +-
 drivers/scsi/sata_svw.c                       |   78 +-
 drivers/scsi/sata_sx4.c                       |  171 +-
 drivers/scsi/sata_via.c                       |   54 +-
 drivers/scsi/sata_vsc.c                       |   11 +-
 drivers/scsi/scsi.c                           |   17 +-
 drivers/scsi/scsi_error.c                     |   63 +-
 drivers/scsi/scsi_ioctl.c                     |   23 +-
 drivers/scsi/scsi_lib.c                       |   47 +-
 drivers/scsi/scsi_scan.c                      |   25 +-
 drivers/scsi/scsi_syms.c                      |    4 +-
 drivers/scsi/scsi_sysfs.c                     |    8 +-
 drivers/scsi/scsiiom.c                        |  172 +-
 drivers/scsi/sd.c                             |  178 +-
 drivers/scsi/sg.c                             |   43 +-
 drivers/scsi/sr.c                             |   14 +-
 drivers/scsi/sr_ioctl.c                       |    3 +-
 drivers/scsi/sym53c8xx_2/sym_defs.h           |    3 +
 drivers/scsi/sym53c8xx_2/sym_glue.c           |  122 +-
 drivers/scsi/sym53c8xx_2/sym_glue.h           |   42 +-
 drivers/scsi/sym53c8xx_2/sym_hipd.c           |  126 +-
 drivers/scsi/sym53c8xx_2/sym_hipd.h           |   40 +-
 drivers/scsi/sym53c8xx_2/sym_misc.c           |  118 -
 drivers/scsi/sym53c8xx_2/sym_nvram.c          |   16 -
 drivers/scsi/t128.c                           |    1 +
 drivers/scsi/tmscsim.c                        |  615 +-
 drivers/scsi/tmscsim.h                        |    1 -
 drivers/scsi/wd7000.c                         |   47 +-
 drivers/serial/68328serial.c                  |   17 +-
 drivers/serial/68360serial.c                  |   18 +-
 drivers/serial/8250.c                         |  187 +-
 drivers/serial/8250.h                         |   14 +
 drivers/serial/8250_pci.c                     |   60 +-
 drivers/serial/Kconfig                        |   15 +-
 drivers/serial/amba-pl011.c                   |    1 -
 drivers/serial/bast_sio.c                     |   31 +-
 drivers/serial/mcfserial.c                    |   17 +-
 drivers/serial/pxa.c                          |    1 +
 drivers/serial/s3c2410.c                      |    4 +-
 drivers/serial/serial_core.c                  |   29 +-
 drivers/serial/serial_cs.c                    |   45 +-
 drivers/serial/sn_console.c                   |   66 +-
 drivers/serial/sunsab.c                       |   20 +-
 drivers/serial/sunsu.c                        |   89 +-
 drivers/serial/sunzilog.c                     |   79 +-
 drivers/tc/zs.c                               |   49 +-
 drivers/telephony/ixj.c                       |   53 +-
 drivers/telephony/ixj.h                       |    4 +-
 drivers/usb/class/audio.c                     |   12 +-
 drivers/usb/class/bluetty.c                   |   12 +-
 drivers/usb/class/cdc-acm.c                   |   39 +-
 drivers/usb/class/cdc-acm.h                   |    2 +-
 drivers/usb/class/usb-midi.c                  |   26 +-
 drivers/usb/class/usblp.c                     |   14 +-
 drivers/usb/core/Kconfig                      |   37 +
 drivers/usb/core/config.c                     |    7 +-
 drivers/usb/core/devices.c                    |    5 +-
 drivers/usb/core/devio.c                      |   16 +-
 drivers/usb/core/hcd-pci.c                    |    4 +-
 drivers/usb/core/hcd.c                        |   49 +-
 drivers/usb/core/hcd.h                        |    5 +-
 drivers/usb/core/hub.c                        |  702 +-
 drivers/usb/core/hub.h                        |   14 +-
 drivers/usb/core/inode.c                      |   19 +-
 drivers/usb/core/message.c                    |   65 +-
 drivers/usb/core/urb.c                        |   11 +-
 drivers/usb/core/usb.c                        |    2 +
 drivers/usb/core/usb.h                        |    1 +
 drivers/usb/gadget/Kconfig                    |   51 +-
 drivers/usb/gadget/Makefile                   |    4 +-
 drivers/usb/gadget/dummy_hcd.c                |    9 +-
 drivers/usb/gadget/ether.c                    |   19 +-
 drivers/usb/gadget/file_storage.c             |  171 +-
 drivers/usb/gadget/gadget_chips.h             |    6 +
 drivers/usb/gadget/inode.c                    |  145 +-
 drivers/usb/gadget/net2280.c                  |  113 +-
 drivers/usb/gadget/net2280.h                  |   23 +-
 drivers/usb/gadget/pxa2xx_udc.c               |    7 +-
 drivers/usb/gadget/serial.c                   |  293 +-
 drivers/usb/gadget/zero.c                     |   13 +-
 drivers/usb/host/Kconfig                      |    1 +
 drivers/usb/host/ehci-dbg.c                   |   43 +-
 drivers/usb/host/ehci-hcd.c                   |   22 +-
 drivers/usb/host/ehci-hub.c                   |    6 +-
 drivers/usb/host/ehci-mem.c                   |    8 +-
 drivers/usb/host/ehci-q.c                     |   18 +-
 drivers/usb/host/ehci-sched.c                 |   19 +-
 drivers/usb/host/ehci.h                       |   81 +-
 drivers/usb/host/hc_simple.c                  |    5 -
 drivers/usb/host/hc_sl811.c                   |    8 +-
 drivers/usb/host/ohci-dbg.c                   |   18 +-
 drivers/usb/host/ohci-hcd.c                   |    5 +-
 drivers/usb/host/ohci-hub.c                   |   98 +-
 drivers/usb/host/ohci-omap.c                  |  557 +-
 drivers/usb/host/ohci-pci.c                   |    3 +-
 drivers/usb/host/ohci-q.c                     |   36 +-
 drivers/usb/host/ohci.h                       |   35 +-
 drivers/usb/host/uhci-hcd.c                   |   25 +-
 drivers/usb/host/uhci-hcd.h                   |   14 +-
 drivers/usb/host/uhci-hub.c                   |    6 +-
 drivers/usb/image/microtek.c                  |    4 +-
 drivers/usb/input/aiptek.c                    |   20 +-
 drivers/usb/input/ati_remote.c                |    4 +-
 drivers/usb/input/hid-core.c                  |  132 +-
 drivers/usb/input/hiddev.c                    |   35 +-
 drivers/usb/input/kbtab.c                     |   11 +-
 drivers/usb/input/wacom.c                     |   14 +-
 drivers/usb/media/Kconfig                     |   48 +-
 drivers/usb/media/Makefile                    |    4 +-
 drivers/usb/media/dabusb.c                    |    4 +-
 drivers/usb/media/dsbr100.c                   |    2 +-
 drivers/usb/media/ibmcam.c                    |   30 +-
 drivers/usb/media/konicawc.c                  |   20 +-
 drivers/usb/media/ov511.c                     |   75 +-
 drivers/usb/media/se401.c                     |    4 +-
 drivers/usb/media/sn9c102.h                   |    6 +-
 drivers/usb/media/sn9c102_core.c              |   95 +-
 drivers/usb/media/sn9c102_pas106b.c           |   76 +-
 drivers/usb/media/sn9c102_sensor.h            |  133 +-
 drivers/usb/media/sn9c102_tas5110c1b.c        |   47 +-
 drivers/usb/media/sn9c102_tas5130d1b.c        |   56 +-
 drivers/usb/media/stv680.c                    |    7 +-
 drivers/usb/media/ultracam.c                  |   16 +-
 drivers/usb/media/usbvideo.c                  |    2 +-
 drivers/usb/misc/auerswald.c                  |   12 +-
 drivers/usb/misc/legousbtower.c               |   65 +-
 drivers/usb/misc/phidgetservo.c               |   16 +-
 drivers/usb/misc/tiglusb.c                    |    2 +-
 drivers/usb/misc/usbtest.c                    |   31 +-
 drivers/usb/net/catc.c                        |    4 +-
 drivers/usb/net/kaweth.c                      |   10 +-
 drivers/usb/net/pegasus.c                     |   16 +-
 drivers/usb/net/rtl8150.c                     |    6 +-
 drivers/usb/net/usbnet.c                      |   13 +-
 drivers/usb/serial/cyberjack.c                |   34 +-
 drivers/usb/serial/digi_acceleport.c          |   19 +-
 drivers/usb/serial/empeg.c                    |    4 -
 drivers/usb/serial/ftdi_sio.c                 |  122 +-
 drivers/usb/serial/ftdi_sio.h                 |   17 +
 drivers/usb/serial/io_edgeport.c              |   25 +-
 drivers/usb/serial/io_edgeport.h              |    4 +-
 drivers/usb/serial/io_fw_down.h               | 1968 ++---
 drivers/usb/serial/io_fw_down3.h              | 1532 ++--
 drivers/usb/serial/io_tables.h                |   67 +-
 drivers/usb/serial/io_ti.c                    |   23 +-
 drivers/usb/serial/io_usbvend.h               |  377 +-
 drivers/usb/serial/ipaq.c                     |    2 +
 drivers/usb/serial/ipaq.h                     |    1 +
 drivers/usb/serial/ir-usb.c                   |    4 +
 drivers/usb/serial/keyspan_pda.c              |    8 +-
 drivers/usb/serial/mct_u232.c                 |    6 +-
 drivers/usb/serial/pl2303.c                   |    2 +-
 drivers/usb/serial/usb-serial.c               |  137 +-
 drivers/usb/serial/whiteheat.c                |    3 +-
 drivers/usb/storage/datafab.c                 |   25 +-
 drivers/usb/storage/datafab.h                 |    2 +-
 drivers/usb/storage/debug.c                   |    8 +-
 drivers/usb/storage/debug.h                   |    6 +-
 drivers/usb/storage/dpcm.c                    |    6 +-
 drivers/usb/storage/dpcm.h                    |    2 +-
 drivers/usb/storage/freecom.c                 |   24 +-
 drivers/usb/storage/freecom.h                 |    2 +-
 drivers/usb/storage/isd200.c                  |   90 +-
 drivers/usb/storage/isd200.h                  |    2 +-
 drivers/usb/storage/jumpshot.c                |   24 +-
 drivers/usb/storage/jumpshot.h                |    2 +-
 drivers/usb/storage/protocol.c                |   27 +-
 drivers/usb/storage/protocol.h                |   20 +-
 drivers/usb/storage/scsiglue.c                |   47 +-
 drivers/usb/storage/scsiglue.h                |    8 +-
 drivers/usb/storage/sddr09.c                  |   27 +-
 drivers/usb/storage/sddr09.h                  |    2 +-
 drivers/usb/storage/sddr55.c                  |   48 +-
 drivers/usb/storage/sddr55.h                  |    2 +-
 drivers/usb/storage/shuttle_usbat.c           |   42 +-
 drivers/usb/storage/shuttle_usbat.h           |    2 +-
 drivers/usb/storage/transport.c               |   44 +-
 drivers/usb/storage/transport.h               |   19 +-
 drivers/usb/storage/unusual_devs.h            |   33 +-
 drivers/usb/storage/usb.c                     |   30 +-
 drivers/usb/storage/usb.h                     |   13 +-
 drivers/usb/usb-skeleton.c                    |  622 +-
 drivers/video/68328fb.c                       |   25 +-
 drivers/video/Kconfig                         |   56 +-
 drivers/video/Makefile                        |  122 +-
 drivers/video/acornfb.c                       |    9 +-
 drivers/video/amifb.c                         |   19 +-
 drivers/video/asiliantfb.c                    |    7 +-
 drivers/video/aty/aty128fb.c                  |   11 +-
 drivers/video/aty/atyfb_base.c                |   22 +-
 drivers/video/aty/radeon_base.c               |  192 +-
 drivers/video/aty/radeon_monitor.c            |   18 +-
 drivers/video/aty/radeonfb.h                  |    8 +-
 drivers/video/bw2.c                           |   14 +-
 drivers/video/cfbcopyarea.c                   |   13 +-
 drivers/video/cfbfillrect.c                   |   16 +-
 drivers/video/cfbimgblt.c                     |   32 +-
 drivers/video/cg14.c                          |    8 +-
 drivers/video/cg3.c                           |    8 +-
 drivers/video/cg6.c                           |    9 +-
 drivers/video/chipsfb.c                       |    7 +-
 drivers/video/cirrusfb.c                      |   17 +-
 drivers/video/clps711xfb.c                    |    7 +-
 drivers/video/console/Kconfig                 |    6 +-
 drivers/video/console/fbcon.c                 |  501 +-
 drivers/video/console/fbcon.h                 |   21 +-
 drivers/video/controlfb.c                     |    8 +-
 drivers/video/cyber2000fb.c                   |   18 +-
 drivers/video/dnfb.c                          |    8 +
 drivers/video/epson1355fb.c                   | 1012 ++-
 drivers/video/fbmem.c                         |  763 +-
 drivers/video/fbmon.c                         |  113 +-
 drivers/video/ffb.c                           |  155 +-
 drivers/video/fm2fb.c                         |   11 +-
 drivers/video/g364fb.c                        |    6 +-
 drivers/video/gbefb.c                         |   13 +-
 drivers/video/hgafb.c                         |    7 +-
 drivers/video/hitfb.c                         |    8 +-
 drivers/video/hpfb.c                          |    6 +-
 drivers/video/i810/i810_dvt.c                 |   14 +-
 drivers/video/i810/i810_main.c                |   78 +-
 drivers/video/igafb.c                         |    6 +-
 drivers/video/imsttfb.c                       |   15 +-
 drivers/video/kyro/fbdev.c                    |   12 +-
 drivers/video/leo.c                           |    7 +-
 drivers/video/macfb.c                         |   11 +-
 drivers/video/matrox/matroxfb_base.c          |    8 +
 drivers/video/matrox/matroxfb_base.h          |   31 +-
 drivers/video/matrox/matroxfb_crtc2.c         |    3 +
 drivers/video/matrox/matroxfb_crtc2.h         |    2 +-
 drivers/video/matrox/matroxfb_misc.c          |   12 +-
 drivers/video/maxinefb.c                      |    7 +-
 drivers/video/modedb.c                        |  265 +-
 drivers/video/neofb.c                         |  451 +-
 drivers/video/offb.c                          |   33 +-
 drivers/video/p9100.c                         |    8 +-
 drivers/video/platinumfb.c                    |   11 +-
 drivers/video/pm2fb.c                         |   15 +-
 drivers/video/pmag-ba-fb.c                    |    6 +-
 drivers/video/pmagb-b-fb.c                    |    6 +-
 drivers/video/pvr2fb.c                        |   11 +-
 drivers/video/pxafb.c                         |   23 +-
 drivers/video/q40fb.c                         |    6 +-
 drivers/video/radeonfb.c                      |   57 +-
 drivers/video/riva/fbdev.c                    |  491 +-
 drivers/video/riva/nv_driver.c                |    2 +
 drivers/video/riva/riva_hw.c                  |   12 +-
 drivers/video/riva/riva_hw.h                  |    4 +-
 drivers/video/riva/rivafb-i2c.c               |   36 +-
 drivers/video/riva/rivafb.h                   |    7 +-
 drivers/video/sa1100fb.c                      |    6 +-
 drivers/video/sgivwfb.c                       |  135 +-
 drivers/video/sis/sis.h                       |   14 +-
 drivers/video/sis/sis_main.c                  |   58 +-
 drivers/video/sis/sis_main.h                  |    2 +-
 drivers/video/skeletonfb.c                    |   13 +-
 drivers/video/softcursor.c                    |   18 +-
 drivers/video/sstfb.c                         |   11 +-
 drivers/video/stifb.c                         |   15 +-
 drivers/video/tcx.c                           |    8 +-
 drivers/video/tdfxfb.c                        |  156 +-
 drivers/video/tgafb.c                         |   25 +-
 drivers/video/tridentfb.c                     |   24 +-
 drivers/video/tx3912fb.c                      |   13 +-
 drivers/video/valkyriefb.c                    |    8 +-
 drivers/video/vesafb.c                        |   67 +-
 drivers/video/vfb.c                           |   11 +-
 drivers/video/vga16fb.c                       |    9 +-
 drivers/video/vgastate.c                      |   12 +-
 drivers/w1/Kconfig                            |   26 +
 drivers/w1/Makefile                           |    7 +
 drivers/w1/matrox_w1.c                        |    2 +-
 drivers/w1/w1.c                               |  276 +-
 drivers/w1/w1.h                               |   19 +
 drivers/w1/w1_family.c                        |   11 +
 drivers/w1/w1_family.h                        |    2 +-
 drivers/w1/w1_int.c                           |   16 +-
 drivers/w1/w1_io.c                            |   69 +-
 drivers/w1/w1_io.h                            |    3 +
 drivers/w1/w1_netlink.h                       |   15 +-
 drivers/w1/w1_therm.c                         |   87 +-
 drivers/zorro/Makefile                        |    2 +-
 fs/Kconfig                                    |   40 +-
 fs/Makefile                                   |    2 +
 fs/adfs/adfs.h                                |   11 +-
 fs/adfs/dir.c                                 |    3 +-
 fs/adfs/dir_f.c                               |   16 +-
 fs/adfs/dir_fplus.h                           |   28 +-
 fs/adfs/inode.c                               |   11 +-
 fs/adfs/map.c                                 |   10 +-
 fs/adfs/super.c                               |   10 +-
 fs/affs/amigaffs.c                            |   26 +-
 fs/affs/bitmap.c                              |   44 +-
 fs/affs/inode.c                               |   11 +-
 fs/affs/namei.c                               |    2 +-
 fs/affs/super.c                               |    8 +-
 fs/afs/cmservice.c                            |    2 +-
 fs/afs/dir.c                                  |   16 +-
 fs/afs/fsclient.c                             |    6 +-
 fs/afs/inode.c                                |    5 +-
 fs/afs/main.c                                 |    3 +-
 fs/afs/mntpt.c                                |   16 +-
 fs/afs/vlclient.c                             |   17 +-
 fs/afs/vlclient.h                             |    3 -
 fs/afs/vlocation.c                            |    3 +-
 fs/afs/vnode.c                                |    6 +-
 fs/afs/volume.h                               |    1 -
 fs/aio.c                                      |  667 +-
 fs/attr.c                                     |    2 +-
 fs/autofs/root.c                              |   10 +-
 fs/autofs4/autofs_i.h                         |    1 -
 fs/autofs4/expire.c                           |    8 +-
 fs/befs/befs.h                                |    1 -
 fs/befs/debug.c                               |    2 +
 fs/befs/linuxvfs.c                            |   18 +-
 fs/bfs/inode.c                                |    9 +-
 fs/binfmt_aout.c                              |    2 +-
 fs/binfmt_elf.c                               |  144 +-
 fs/bio.c                                      |  151 +-
 fs/buffer.c                                   |   71 +-
 fs/cifs/AUTHORS                               |    5 +-
 fs/cifs/CHANGES                               |    4 +-
 fs/cifs/asn1.c                                |   27 +-
 fs/cifs/cifs_debug.c                          |   16 +-
 fs/cifs/cifsencrypt.c                         |   14 +-
 fs/cifs/cifsfs.c                              |   28 +-
 fs/cifs/cifsfs.h                              |    1 +
 fs/cifs/cifsglob.h                            |   18 +-
 fs/cifs/cifspdu.h                             |  879 +--
 fs/cifs/cifsproto.h                           |    2 +-
 fs/cifs/cifssmb.c                             |  727 +-
 fs/cifs/connect.c                             |  519 +-
 fs/cifs/file.c                                |  131 +-
 fs/cifs/inode.c                               |   45 +-
 fs/cifs/link.c                                |   50 +-
 fs/cifs/misc.c                                |   28 +-
 fs/cifs/netmisc.c                             |   15 +-
 fs/cifs/ntlmssp.h                             |   26 +-
 fs/cifs/transport.c                           |   66 +-
 fs/coda/coda_linux.c                          |    2 +-
 fs/coda/file.c                                |   18 +
 fs/coda/inode.c                               |    2 +-
 fs/coda/psdev.c                               |    2 +-
 fs/coda/upcall.c                              |   10 +-
 fs/compat.c                                   |  142 +-
 fs/compat_ioctl.c                             |   12 +-
 fs/dcache.c                                   |   78 +-
 fs/devpts/inode.c                             |   74 +-
 fs/direct-io.c                                |   75 +-
 fs/dquot.c                                    |    3 +-
 fs/efs/inode.c                                |    4 +-
 fs/efs/super.c                                |   18 +-
 fs/eventpoll.c                                |    6 +-
 fs/exec.c                                     |  126 +-
 fs/exportfs/expfs.c                           |   22 +-
 fs/ext2/acl.h                                 |   12 +-
 fs/ext2/balloc.c                              |    4 +-
 fs/ext2/dir.c                                 |   11 +-
 fs/ext2/ext2.h                                |    7 +-
 fs/ext2/ialloc.c                              |   10 +-
 fs/ext2/inode.c                               |   40 +-
 fs/ext2/ioctl.c                               |    4 +-
 fs/ext2/super.c                               |   81 +-
 fs/ext2/xattr.c                               |    2 +-
 fs/ext2/xattr.h                               |   16 +-
 fs/ext3/acl.h                                 |   12 +-
 fs/ext3/balloc.c                              |    4 +-
 fs/ext3/fsync.c                               |    4 -
 fs/ext3/ialloc.c                              |    7 +-
 fs/ext3/inode.c                               |   69 +-
 fs/ext3/ioctl.c                               |    6 +-
 fs/ext3/namei.c                               |   37 +-
 fs/ext3/super.c                               |  116 +-
 fs/ext3/xattr.c                               |    2 +-
 fs/ext3/xattr.h                               |   16 +-
 fs/fat/cache.c                                |   11 +-
 fs/fat/dir.c                                  |   33 +-
 fs/fat/file.c                                 |    6 -
 fs/fat/inode.c                                |   39 +-
 fs/fat/misc.c                                 |   13 +-
 fs/fcntl.c                                    |   16 +-
 fs/file_table.c                               |   53 +-
 fs/freevxfs/vxfs_extern.h                     |    2 +-
 fs/freevxfs/vxfs_inode.c                      |   11 +-
 fs/freevxfs/vxfs_super.c                      |    2 +-
 fs/fs-writeback.c                             |   33 +-
 fs/hfs/bfind.c                                |    3 +-
 fs/hfs/bitmap.c                               |   35 +-
 fs/hfs/bnode.c                                |   10 +-
 fs/hfs/brec.c                                 |    8 +-
 fs/hfs/btree.c                                |    2 +-
 fs/hfs/btree.h                                |   28 +-
 fs/hfs/catalog.c                              |    2 +-
 fs/hfs/extent.c                               |    6 +-
 fs/hfs/hfs.h                                  |  134 +-
 fs/hfs/hfs_fs.h                               |   15 +-
 fs/hfs/inode.c                                |   26 +-
 fs/hfs/mdb.c                                  |    4 +-
 fs/hfs/part_tbl.c                             |   20 +-
 fs/hfs/super.c                                |    7 +-
 fs/hfsplus/bfind.c                            |    3 +-
 fs/hfsplus/bitmap.c                           |   33 +-
 fs/hfsplus/bnode.c                            |   12 +-
 fs/hfsplus/brec.c                             |    8 +-
 fs/hfsplus/btree.c                            |    2 +-
 fs/hfsplus/catalog.c                          |    8 +-
 fs/hfsplus/extents.c                          |    4 +-
 fs/hfsplus/hfsplus_fs.h                       |    3 +-
 fs/hfsplus/hfsplus_raw.h                      |  172 +-
 fs/hfsplus/inode.c                            |   10 +-
 fs/hfsplus/part_tbl.c                         |   20 +-
 fs/hfsplus/super.c                            |    9 +-
 fs/hfsplus/wrapper.c                          |   10 +-
 fs/hostfs/Makefile                            |    4 +-
 fs/hostfs/hostfs.h                            |   22 +-
 fs/hostfs/hostfs_kern.c                       |  124 +-
 fs/hostfs/hostfs_user.c                       |   62 +-
 fs/hpfs/super.c                               |    2 +-
 fs/hppfs/Makefile                             |    4 +-
 fs/hppfs/hppfs_kern.c                         |   92 +-
 fs/hugetlbfs/inode.c                          |   37 +-
 fs/inode.c                                    |    9 +-
 fs/ioctl.c                                    |    6 +-
 fs/isofs/compress.c                           |    4 +-
 fs/isofs/inode.c                              |    3 +-
 fs/isofs/rock.c                               |   18 +-
 fs/jbd/commit.c                               |   50 +-
 fs/jbd/journal.c                              |   51 +-
 fs/jbd/recovery.c                             |   32 +-
 fs/jbd/revoke.c                               |   13 +-
 fs/jffs2/super.c                              |    7 +-
 fs/jfs/acl.c                                  |   13 +-
 fs/jfs/inode.c                                |   22 +-
 fs/jfs/jfs_dtree.c                            |   65 +-
 fs/jfs/jfs_extent.c                           |   26 +-
 fs/jfs/jfs_imap.c                             |   29 +-
 fs/jfs/jfs_inode.c                            |   14 +-
 fs/jfs/jfs_metapage.c                         |    1 +
 fs/jfs/jfs_mount.c                            |    3 -
 fs/jfs/jfs_txnmgr.c                           |    3 -
 fs/jfs/jfs_xtree.c                            |   61 +-
 fs/jfs/namei.c                                |   39 +-
 fs/jfs/resize.c                               |    5 +-
 fs/jfs/super.c                                |    4 +-
 fs/jfs/xattr.c                                |   51 +-
 fs/libfs.c                                    |   72 +-
 fs/lockd/clntlock.c                           |    4 +-
 fs/lockd/clntproc.c                           |  174 +-
 fs/lockd/host.c                               |   18 +-
 fs/lockd/svc.c                                |    8 +-
 fs/lockd/svc4proc.c                           |    3 +-
 fs/lockd/svclock.c                            |   50 +-
 fs/lockd/svcproc.c                            |    3 +-
 fs/lockd/svcsubs.c                            |   10 +-
 fs/locks.c                                    |  181 +-
 fs/minix/inode.c                              |    7 +-
 fs/minix/itree_common.c                       |    2 +-
 fs/mpage.c                                    |   33 +-
 fs/namei.c                                    |   61 +-
 fs/namespace.c                                |   43 +-
 fs/ncpfs/dir.c                                |   30 +-
 fs/ncpfs/file.c                               |   21 +-
 fs/ncpfs/inode.c                              |   35 +-
 fs/ncpfs/ioctl.c                              |    4 +-
 fs/ncpfs/mmap.c                               |   10 +-
 fs/ncpfs/ncplib_kernel.c                      |  192 +-
 fs/ncpfs/ncplib_kernel.h                      |   42 +-
 fs/ncpfs/sock.c                               |    2 +-
 fs/ncpfs/symlink.c                            |   15 +-
 fs/nfs/Makefile                               |    3 +-
 fs/nfs/dir.c                                  |  144 +-
 fs/nfs/direct.c                               |   47 +-
 fs/nfs/file.c                                 |  151 +-
 fs/nfs/inode.c                                |  389 +-
 fs/nfs/mount_clnt.c                           |    2 -
 fs/nfs/nfs2xdr.c                              |   70 +-
 fs/nfs/nfs3proc.c                             |  111 +-
 fs/nfs/nfs3xdr.c                              |   48 +-
 fs/nfs/nfs4proc.c                             | 1272 +++-
 fs/nfs/nfs4state.c                            |  371 +-
 fs/nfs/nfs4xdr.c                              |  563 +-
 fs/nfs/pagelist.c                             |   62 +-
 fs/nfs/proc.c                                 |   63 +-
 fs/nfs/read.c                                 |   62 +-
 fs/nfs/symlink.c                              |   75 +-
 fs/nfs/write.c                                |  170 +-
 fs/nfsd/Makefile                              |    3 +-
 fs/nfsd/auth.c                                |    2 +-
 fs/nfsd/export.c                              |    5 +
 fs/nfsd/lockd.c                               |   11 +-
 fs/nfsd/nfs3proc.c                            |   12 +-
 fs/nfsd/nfs3xdr.c                             |   10 +-
 fs/nfsd/nfs4proc.c                            |   17 +-
 fs/nfsd/nfs4state.c                           |  148 +-
 fs/nfsd/nfs4xdr.c                             |  127 +-
 fs/nfsd/nfsctl.c                              |   96 +-
 fs/nfsd/nfsfh.c                               |   25 +-
 fs/nfsd/nfsproc.c                             |    1 +
 fs/nfsd/nfssvc.c                              |    2 +
 fs/nfsd/vfs.c                                 |  287 +-
 fs/nls/nls_cp932.c                            |   43 +-
 fs/ntfs/ChangeLog                             |  147 +-
 fs/ntfs/Makefile                              |    4 +-
 fs/ntfs/aops.c                                |  127 +-
 fs/ntfs/attrib.c                              |  904 ++-
 fs/ntfs/attrib.h                              |   36 +-
 fs/ntfs/collate.c                             |   20 +-
 fs/ntfs/collate.h                             |   12 +-
 fs/ntfs/compress.c                            |   38 +-
 fs/ntfs/debug.c                               |   19 +-
 fs/ntfs/debug.h                               |    2 +-
 fs/ntfs/dir.c                                 |  195 +-
 fs/ntfs/endian.h                              |   72 +-
 fs/ntfs/file.c                                |   99 +-
 fs/ntfs/index.c                               |   36 +-
 fs/ntfs/index.h                               |    2 +-
 fs/ntfs/inode.c                               |  492 +-
 fs/ntfs/inode.h                               |   20 +-
 fs/ntfs/layout.h                              |  767 +-
 fs/ntfs/logfile.c                             |    8 +-
 fs/ntfs/logfile.h                             |   76 +-
 fs/ntfs/mft.c                                 |   27 +-
 fs/ntfs/mst.c                                 |   23 +-
 fs/ntfs/namei.c                               |   46 +-
 fs/ntfs/ntfs.h                                |    3 +-
 fs/ntfs/quota.c                               |    2 +-
 fs/ntfs/super.c                               |  380 +-
 fs/ntfs/time.h                                |    6 +-
 fs/ntfs/types.h                               |   26 +-
 fs/ntfs/unistr.c                              |   12 +-
 fs/ntfs/upcase.c                              |    3 +-
 fs/ntfs/volume.h                              |   18 +-
 fs/openpromfs/inode.c                         |   48 +-
 fs/partitions/acorn.c                         |   42 +-
 fs/partitions/amiga.c                         |   42 +-
 fs/partitions/atari.h                         |    4 +-
 fs/partitions/efi.h                           |   36 +-
 fs/partitions/ldm.c                           |   16 +-
 fs/partitions/ldm.h                           |    6 +-
 fs/partitions/mac.h                           |   36 +-
 fs/partitions/msdos.c                         |    3 +
 fs/partitions/osf.c                           |   46 +-
 fs/partitions/sgi.c                           |   32 +-
 fs/partitions/sun.c                           |   33 +-
 fs/proc/array.c                               |   90 +-
 fs/proc/base.c                                |  179 +-
 fs/proc/inode.c                               |    2 +-
 fs/proc/proc_misc.c                           |   99 +-
 fs/proc/proc_tty.c                            |   12 +-
 fs/proc/root.c                                |    5 +-
 fs/proc/task_mmu.c                            |   56 +-
 fs/proc/task_nommu.c                          |    8 +-
 fs/qnx4/inode.c                               |   11 +-
 fs/quota_v1.c                                 |    4 +-
 fs/quota_v2.c                                 |   10 +-
 fs/ramfs/inode.c                              |    8 +-
 fs/reiserfs/file.c                            |   13 +-
 fs/reiserfs/inode.c                           |    5 +-
 fs/reiserfs/ioctl.c                           |    2 +-
 fs/reiserfs/journal.c                         |   94 +-
 fs/reiserfs/super.c                           |   33 +-
 fs/reiserfs/xattr.c                           |   21 +-
 fs/reiserfs/xattr_acl.c                       |   28 +-
 fs/reiserfs/xattr_security.c                  |   10 +-
 fs/reiserfs/xattr_trusted.c                   |   10 +-
 fs/reiserfs/xattr_user.c                      |   10 +-
 fs/romfs/inode.c                              |   33 +-
 fs/select.c                                   |   19 +-
 fs/smbfs/inode.c                              |    2 +-
 fs/smbfs/proc.c                               |   17 +-
 fs/super.c                                    |   26 +-
 fs/sysfs/symlink.c                            |   41 +-
 fs/sysfs/sysfs.h                              |    2 +-
 fs/sysv/balloc.c                              |   31 +-
 fs/sysv/ialloc.c                              |    2 +-
 fs/sysv/inode.c                               |    5 +-
 fs/sysv/itree.c                               |   36 +-
 fs/sysv/super.c                               |   36 +-
 fs/sysv/sysv.h                                |   72 +-
 fs/udf/balloc.c                               |   22 +-
 fs/udf/dir.c                                  |    4 +-
 fs/udf/directory.c                            |   16 +-
 fs/udf/ecma_167.h                             |  294 +-
 fs/udf/fsync.c                                |    4 +-
 fs/udf/inode.c                                |  114 +-
 fs/udf/misc.c                                 |   14 +-
 fs/udf/namei.c                                |   36 +-
 fs/udf/osta_udf.h                             |   86 +-
 fs/udf/partition.c                            |   12 +-
 fs/udf/super.c                                |   59 +-
 fs/udf/truncate.c                             |   14 +-
 fs/udf/udfdecl.h                              |   35 +-
 fs/udf/udfend.h                               |   22 +-
 fs/udf/udftime.c                              |    8 +-
 fs/ufs/balloc.c                               |   33 +-
 fs/ufs/dir.c                                  |   10 +-
 fs/ufs/inode.c                                |   22 +-
 fs/ufs/super.c                                |   24 +-
 fs/ufs/swab.h                                 |   72 +-
 fs/ufs/truncate.c                             |   16 +-
 fs/ufs/util.h                                 |   38 +-
 fs/umsdos/inode.c                             |    6 +-
 fs/vfat/namei.c                               |   40 +-
 fs/xfs/Makefile                               |    3 +-
 fs/xfs/linux-2.6/xfs_aops.c                   |   74 +-
 fs/xfs/linux-2.6/xfs_buf.c                    |   54 +-
 fs/xfs/linux-2.6/xfs_buf.h                    |    2 +-
 fs/xfs/linux-2.6/xfs_file.c                   |   46 +-
 fs/xfs/linux-2.6/xfs_fs_subr.h                |    1 -
 fs/xfs/linux-2.6/xfs_globals.c                |    1 +
 fs/xfs/linux-2.6/xfs_ioctl.c                  |  133 +-
 fs/xfs/linux-2.6/xfs_iops.c                   |   30 +-
 fs/xfs/linux-2.6/xfs_iops.h                   |    2 +-
 fs/xfs/linux-2.6/xfs_linux.h                  |    2 +
 fs/xfs/linux-2.6/xfs_lrw.c                    |  276 +-
 fs/xfs/linux-2.6/xfs_lrw.h                    |    6 +-
 fs/xfs/linux-2.6/xfs_stats.c                  |    4 +-
 fs/xfs/linux-2.6/xfs_super.c                  |  217 +-
 fs/xfs/linux-2.6/xfs_sysctl.c                 |    7 +-
 fs/xfs/linux-2.6/xfs_sysctl.h                 |    2 +
 fs/xfs/linux-2.6/xfs_vfs.c                    |    2 +
 fs/xfs/linux-2.6/xfs_vfs.h                    |   21 +-
 fs/xfs/linux-2.6/xfs_vnode.c                  |   82 +-
 fs/xfs/linux-2.6/xfs_vnode.h                  |   16 +-
 fs/xfs/quota/xfs_dquot.c                      |  108 +-
 fs/xfs/quota/xfs_dquot.h                      |    2 +
 fs/xfs/quota/xfs_qm.c                         |   61 +-
 fs/xfs/quota/xfs_qm.h                         |    8 +-
 fs/xfs/quota/xfs_qm_stats.c                   |    4 +-
 fs/xfs/quota/xfs_qm_syscalls.c                |   40 +-
 fs/xfs/quota/xfs_trans_dquot.c                |   41 +-
 fs/xfs/support/ktrace.c                       |    9 +-
 fs/xfs/support/move.c                         |    8 +-
 fs/xfs/xfs_acl.h                              |    4 +-
 fs/xfs/xfs_alloc.c                            |   20 +-
 fs/xfs/xfs_alloc_btree.c                      |    2 +-
 fs/xfs/xfs_attr.c                             |   33 +-
 fs/xfs/xfs_attr_leaf.h                        |    1 -
 fs/xfs/xfs_bmap.c                             |   75 +-
 fs/xfs/xfs_bmap.h                             |    2 +-
 fs/xfs/xfs_bmap_btree.c                       |    2 +-
 fs/xfs/xfs_bmap_btree.h                       |   11 +-
 fs/xfs/xfs_buf_item.c                         |    2 -
 fs/xfs/xfs_da_btree.c                         |    2 +-
 fs/xfs/xfs_dfrag.c                            |    2 +-
 fs/xfs/xfs_dfrag.h                            |    2 +-
 fs/xfs/xfs_dinode.h                           |   22 +-
 fs/xfs/xfs_dir2_trace.c                       |    2 +-
 fs/xfs/xfs_fs.h                               |   60 +-
 fs/xfs/xfs_fsops.c                            |   20 +-
 fs/xfs/xfs_iget.c                             |    7 +-
 fs/xfs/xfs_inode.c                            |   60 +-
 fs/xfs/xfs_inode.h                            |    1 -
 fs/xfs/xfs_iomap.c                            |  100 +-
 fs/xfs/xfs_iomap.h                            |    5 +-
 fs/xfs/xfs_itable.c                           |   12 +-
 fs/xfs/xfs_itable.h                           |   10 +-
 fs/xfs/xfs_log.c                              |   57 +-
 fs/xfs/xfs_log_priv.h                         |    1 -
 fs/xfs/xfs_log_recover.c                      |   23 +-
 fs/xfs/xfs_mount.c                            |   32 +-
 fs/xfs/xfs_mount.h                            |    2 +-
 fs/xfs/xfs_quota.h                            |   18 +-
 fs/xfs/xfs_rtalloc.c                          |   14 +-
 fs/xfs/xfs_sb.h                               |    6 +-
 fs/xfs/xfs_trans.c                            |    5 +-
 fs/xfs/xfs_trans_item.c                       |    2 +-
 fs/xfs/xfs_types.h                            |    2 +-
 fs/xfs/xfs_vfsops.c                           |  118 +-
 fs/xfs/xfs_vnodeops.c                         |  120 +-
 include/acpi/acconfig.h                       |   25 +-
 include/acpi/acdebug.h                        |    8 +
 include/acpi/acdisasm.h                       |   15 +
 include/acpi/acdispat.h                       |    3 +-
 include/acpi/acevents.h                       |   54 +-
 include/acpi/acexcep.h                        |    8 +-
 include/acpi/acglobal.h                       |   44 +-
 include/acpi/achware.h                        |   36 +-
 include/acpi/acinterp.h                       |   15 +-
 include/acpi/aclocal.h                        |   39 +-
 include/acpi/acmacros.h                       |   23 +-
 include/acpi/acnamesp.h                       |   18 +-
 include/acpi/acobject.h                       |   13 +-
 include/acpi/acparser.h                       |    4 +-
 include/acpi/acpi_bus.h                       |   28 +-
 include/acpi/acpi_drivers.h                   |   58 +-
 include/acpi/acpiosxf.h                       |   19 +-
 include/acpi/acpixf.h                         |   10 +-
 include/acpi/acstruct.h                       |   23 +-
 include/acpi/actbl.h                          |   29 +-
 include/acpi/actypes.h                        |   78 +-
 include/acpi/platform/acenv.h                 |    8 +-
 include/acpi/platform/aclinux.h               |    2 -
 include/asm-alpha/a.out.h                     |    2 +-
 include/asm-alpha/bitops.h                    |    5 +-
 include/asm-alpha/bug.h                       |   12 +-
 include/asm-alpha/cache.h                     |    2 +-
 include/asm-alpha/compiler.h                  |   16 +-
 include/asm-alpha/core_apecs.h                |  224 +-
 include/asm-alpha/core_cia.h                  |  303 +-
 include/asm-alpha/core_irongate.h             |  134 +-
 include/asm-alpha/core_lca.h                  |  223 +-
 include/asm-alpha/core_marvel.h               |  243 +-
 include/asm-alpha/core_mcpcia.h               |  267 +-
 include/asm-alpha/core_polaris.h              |  146 +-
 include/asm-alpha/core_t2.h                   |  110 +-
 include/asm-alpha/core_titan.h                |  146 +-
 include/asm-alpha/core_tsunami.h              |  149 +-
 include/asm-alpha/core_wildfire.h             |  149 +-
 include/asm-alpha/dma-mapping.h               |   64 +-
 include/asm-alpha/hardirq.h                   |   41 -
 include/asm-alpha/io.h                        |  687 +-
 include/asm-alpha/jensen.h                    |   99 +-
 include/asm-alpha/machvec.h                   |   42 +-
 include/asm-alpha/mmu_context.h               |    1 +
 include/asm-alpha/page.h                      |    1 +
 include/asm-alpha/pci.h                       |    4 +-
 include/asm-alpha/pgtable.h                   |    2 +-
 include/asm-alpha/ptrace.h                    |    1 +
 include/asm-alpha/resource.h                  |    2 +-
 include/asm-alpha/semaphore.h                 |   23 +-
 include/asm-alpha/socket.h                    |   16 -
 include/asm-alpha/spinlock.h                  |   27 +-
 include/asm-alpha/sysinfo.h                   |    1 +
 include/asm-alpha/system.h                    |    6 +-
 include/asm-alpha/thread_info.h               |    2 +-
 include/asm-alpha/tlbflush.h                  |    3 +-
 include/asm-alpha/uaccess.h                   |    6 +-
 include/asm-alpha/unistd.h                    |    5 +-
 include/asm-alpha/vga.h                       |   18 +-
 include/asm-arm/apm.h                         |   49 +-
 include/asm-arm/arch-cl7500/uncompress.h      |    2 +-
 include/asm-arm/arch-clps711x/uncompress.h    |    2 +-
 include/asm-arm/arch-ebsa110/param.h          |    2 +-
 include/asm-arm/arch-ebsa110/uncompress.h     |    2 +-
 include/asm-arm/arch-ebsa285/uncompress.h     |    2 +-
 include/asm-arm/arch-epxa10db/uncompress.h    |    2 +-
 include/asm-arm/arch-integrator/uncompress.h  |    2 +-
 include/asm-arm/arch-iop3xx/dma.h             |  103 +-
 include/asm-arm/arch-iop3xx/hardware.h        |   51 +-
 include/asm-arm/arch-iop3xx/iop321-irqs.h     |   26 +-
 include/asm-arm/arch-iop3xx/iop321.h          |   95 +-
 include/asm-arm/arch-iop3xx/iq80321.h         |   32 +-
 include/asm-arm/arch-iop3xx/irqs.h            |   18 +-
 include/asm-arm/arch-iop3xx/memory.h          |   26 +-
 include/asm-arm/arch-iop3xx/param.h           |    2 +-
 include/asm-arm/arch-iop3xx/serial.h          |   53 +-
 include/asm-arm/arch-iop3xx/system.h          |   10 +-
 include/asm-arm/arch-iop3xx/timex.h           |   16 +-
 include/asm-arm/arch-iop3xx/uncompress.h      |   36 +-
 include/asm-arm/arch-iop3xx/vmalloc.h         |    1 +
 include/asm-arm/arch-ixp4xx/io.h              |   14 +-
 include/asm-arm/arch-ixp4xx/uncompress.h      |    2 +-
 include/asm-arm/arch-l7200/param.h            |    2 +-
 include/asm-arm/arch-l7200/uncompress.h       |    2 +-
 include/asm-arm/arch-lh7a40x/uncompress.h     |    2 +-
 include/asm-arm/arch-omap/board-h2.h          |   10 +
 include/asm-arm/arch-omap/board-h3.h          |   84 +-
 include/asm-arm/arch-omap/board-innovator.h   |  119 +-
 include/asm-arm/arch-omap/board-perseus2.h    |   57 +-
 include/asm-arm/arch-omap/board.h             |   51 +-
 include/asm-arm/arch-omap/fpga.h              |  159 +-
 include/asm-arm/arch-omap/hardware.h          |   48 +-
 include/asm-arm/arch-omap/memory.h            |    2 +-
 include/asm-arm/arch-omap/mux.h               |   36 +-
 include/asm-arm/arch-omap/omap1510.h          |   19 +-
 include/asm-arm/arch-omap/omap1610.h          |    9 +
 include/asm-arm/arch-omap/omap5912.h          |    9 +
 include/asm-arm/arch-omap/omap730.h           |    6 -
 include/asm-arm/arch-omap/uncompress.h        |    2 +-
 include/asm-arm/arch-pxa/dma.h                |    2 +-
 include/asm-arm/arch-pxa/hardware.h           |    9 +-
 include/asm-arm/arch-pxa/irqs.h               |   54 +-
 include/asm-arm/arch-pxa/pxa-regs.h           |   56 +-
 include/asm-arm/arch-pxa/serial.h             |    1 +
 include/asm-arm/arch-pxa/system.h             |    1 +
 include/asm-arm/arch-pxa/uncompress.h         |    2 +-
 include/asm-arm/arch-rpc/io.h                 |   38 +-
 include/asm-arm/arch-rpc/uncompress.h         |    6 +-
 include/asm-arm/arch-s3c2410/bast-cpld.h      |   35 +-
 include/asm-arm/arch-s3c2410/bast-irq.h       |    3 +-
 include/asm-arm/arch-s3c2410/dma.h            |  299 +-
 include/asm-arm/arch-s3c2410/hardware.h       |   35 +
 include/asm-arm/arch-s3c2410/param.h          |    2 +-
 include/asm-arm/arch-s3c2410/regs-clock.h     |   58 +-
 include/asm-arm/arch-s3c2410/regs-gpio.h      |   31 +-
 include/asm-arm/arch-s3c2410/regs-timer.h     |    2 +
 include/asm-arm/arch-s3c2410/uncompress.h     |    2 +-
 include/asm-arm/arch-sa1100/uncompress.h      |    2 +-
 include/asm-arm/arch-shark/uncompress.h       |    2 +-
 include/asm-arm/arch-versatile/uncompress.h   |    2 +-
 include/asm-arm/atomic.h                      |   54 +-
 include/asm-arm/bitops.h                      |    2 +-
 include/asm-arm/bug.h                         |   14 +-
 include/asm-arm/cacheflush.h                  |   26 +-
 include/asm-arm/checksum.h                    |    2 +-
 include/asm-arm/elf.h                         |   27 +
 include/asm-arm/fpstate.h                     |   19 +-
 include/asm-arm/hardirq.h                     |   48 +-
 include/asm-arm/hardware.h                    |    9 -
 include/asm-arm/hardware/clock.h              |    8 +-
 include/asm-arm/io.h                          |    2 +
 include/asm-arm/mach/pci.h                    |    8 +-
 include/asm-arm/mach/time.h                   |    7 +-
 include/asm-arm/memory.h                      |   21 +-
 include/asm-arm/page.h                        |    2 +-
 include/asm-arm/param.h                       |   11 +-
 include/asm-arm/ptrace.h                      |    6 +
 include/asm-arm/resource.h                    |    2 +-
 include/asm-arm/semaphore.h                   |   30 +-
 include/asm-arm/socket.h                      |   16 -
 include/asm-arm/system.h                      |   43 +-
 include/asm-arm/thread_info.h                 |   29 +-
 include/asm-arm/uaccess.h                     |    3 +
 include/asm-arm/unistd.h                      |   52 +-
 include/asm-arm26/bug.h                       |   17 +-
 include/asm-arm26/hardirq.h                   |   35 -
 include/asm-arm26/ptrace.h                    |    1 +
 include/asm-arm26/resource.h                  |    2 +-
 include/asm-arm26/semaphore.h                 |   37 +-
 include/asm-arm26/socket.h                    |   16 -
 include/asm-arm26/tlb.h                       |    2 +-
 include/asm-arm26/uaccess.h                   |    3 +
 include/asm-cris/arch-v10/ptrace.h            |    1 +
 include/asm-cris/bug.h                        |   19 +-
 include/asm-cris/hardirq.h                    |   36 -
 include/asm-cris/resource.h                   |    2 +-
 include/asm-cris/semaphore.h                  |   33 +-
 include/asm-cris/socket.h                     |   15 -
 include/asm-cris/uaccess.h                    |    2 +
 include/asm-generic/ide_iops.h                |    8 +-
 include/asm-generic/local.h                   |    2 +-
 include/asm-generic/pgtable.h                 |    8 +
 include/asm-generic/siginfo.h                 |    1 +
 include/asm-generic/vmlinux.lds.h             |   22 +
 include/asm-h8300/bitops.h                    |    2 +
 include/asm-h8300/bug.h                       |   19 +-
 include/asm-h8300/hardirq.h                   |   40 -
 include/asm-h8300/ptrace.h                    |    1 +
 include/asm-h8300/resource.h                  |    2 +-
 include/asm-h8300/semaphore.h                 |   33 +-
 include/asm-h8300/socket.h                    |   16 -
 include/asm-h8300/uaccess.h                   |    2 +
 include/asm-i386/acpi.h                       |   13 +
 include/asm-i386/apic.h                       |   27 +-
 include/asm-i386/bitops.h                     |   12 +-
 include/asm-i386/bug.h                        |   14 +-
 include/asm-i386/checksum.h                   |    7 +-
 include/asm-i386/cpufeature.h                 |   13 +-
 include/asm-i386/desc.h                       |   10 +-
 include/asm-i386/dma-mapping.h                |   13 +-
 include/asm-i386/elf.h                        |    4 +-
 include/asm-i386/fixmap.h                     |   21 +-
 include/asm-i386/hardirq.h                    |   42 +-
 include/asm-i386/hw_irq.h                     |   40 -
 include/asm-i386/io.h                         |   65 +-
 include/asm-i386/linkage.h                    |    4 +
 include/asm-i386/mach-bigsmp/mach_ipi.h       |    2 +-
 include/asm-i386/mach-default/do_timer.h      |    2 +-
 include/asm-i386/mach-default/mach_ipi.h      |    4 +-
 include/asm-i386/mach-es7000/mach_ipi.h       |    2 +-
 include/asm-i386/mach-es7000/mach_mpparse.h   |    3 +-
 include/asm-i386/mach-es7000/mach_mpspec.h    |    2 +-
 include/asm-i386/mach-numaq/mach_ipi.h        |    2 +-
 include/asm-i386/mach-summit/mach_apic.h      |    8 +-
 include/asm-i386/mach-summit/mach_ipi.h       |    2 +-
 include/asm-i386/mach-visws/do_timer.h        |    2 +-
 include/asm-i386/mach-visws/mach_apic.h       |    1 +
 include/asm-i386/mmu_context.h                |   12 +-
 include/asm-i386/mtrr.h                       |    2 -
 include/asm-i386/page.h                       |   25 +-
 include/asm-i386/pgtable-2level.h             |    7 +
 include/asm-i386/pgtable-3level.h             |    8 +
 include/asm-i386/pgtable.h                    |    7 -
 include/asm-i386/processor.h                  |   28 +-
 include/asm-i386/ptrace.h                     |    5 +
 include/asm-i386/resource.h                   |    2 +-
 include/asm-i386/rwlock.h                     |   32 +-
 include/asm-i386/semaphore.h                  |   34 +-
 include/asm-i386/smp.h                        |    1 +
 include/asm-i386/socket.h                     |   16 -
 include/asm-i386/spinlock.h                   |   18 +-
 include/asm-i386/thread_info.h                |    2 +-
 include/asm-i386/timer.h                      |    1 +
 include/asm-i386/timex.h                      |   13 +-
 include/asm-i386/tlbflush.h                   |    2 +-
 include/asm-i386/topology.h                   |    2 +-
 include/asm-i386/uaccess.h                    |   42 +-
 include/asm-i386/unistd.h                     |    3 +-
 include/asm-ia64/acpi.h                       |    4 +-
 include/asm-ia64/bug.h                        |   13 +-
 include/asm-ia64/compat.h                     |    8 +-
 include/asm-ia64/dma-mapping.h                |    2 +-
 include/asm-ia64/elf.h                        |    6 +-
 include/asm-ia64/gcc_intrin.h                 |   24 +-
 include/asm-ia64/hardirq.h                    |   41 +-
 include/asm-ia64/hw_irq.h                     |    2 -
 include/asm-ia64/ia32.h                       |    4 +-
 include/asm-ia64/io.h                         |   85 +-
 include/asm-ia64/iosapic.h                    |   11 +-
 include/asm-ia64/mca.h                        |    7 +
 include/asm-ia64/mca_asm.h                    |    3 -
 include/asm-ia64/mmu_context.h                |   51 +-
 include/asm-ia64/mmzone.h                     |    6 -
 include/asm-ia64/numa.h                       |    2 +-
 include/asm-ia64/page.h                       |   18 +-
 include/asm-ia64/pgtable.h                    |   12 +-
 include/asm-ia64/processor.h                  |   30 +-
 include/asm-ia64/ptrace.h                     |    9 +
 include/asm-ia64/resource.h                   |    2 +-
 include/asm-ia64/sal.h                        |   12 +-
 include/asm-ia64/semaphore.h                  |   30 +-
 include/asm-ia64/siginfo.h                    |    2 +-
 include/asm-ia64/signal.h                     |    4 +-
 include/asm-ia64/smp.h                        |    8 +-
 include/asm-ia64/sn/sn2/shubio.h              |    2 +-
 include/asm-ia64/sn/sn_cpuid.h                |    8 +-
 include/asm-ia64/sn/sn_sal.h                  |  196 +-
 include/asm-ia64/sn/xtalk/xtalk.h             |    2 +-
 include/asm-ia64/sn/xtalk/xwidget.h           |    2 +-
 include/asm-ia64/socket.h                     |   16 -
 include/asm-ia64/spinlock.h                   |    4 +-
 include/asm-ia64/system.h                     |    4 +-
 include/asm-ia64/thread_info.h                |    8 -
 include/asm-ia64/tlb.h                        |    2 +
 include/asm-ia64/tlbflush.h                   |    7 +-
 include/asm-ia64/uaccess.h                    |  120 +-
 include/asm-ia64/unistd.h                     |    4 +-
 include/asm-m68k/bug.h                        |   17 +-
 include/asm-m68k/cacheflush.h                 |   12 +-
 include/asm-m68k/hardirq.h                    |   36 -
 include/asm-m68k/ptrace.h                     |    1 +
 include/asm-m68k/resource.h                   |    2 +-
 include/asm-m68k/semaphore.h                  |   33 +-
 include/asm-m68k/socket.h                     |   16 -
 include/asm-m68k/system.h                     |    2 +-
 include/asm-m68k/uaccess.h                    |    3 +
 include/asm-m68knommu/bug.h                   |   22 +-
 include/asm-m68knommu/hardirq.h               |   46 -
 include/asm-m68knommu/ptrace.h                |    1 +
 include/asm-m68knommu/semaphore.h             |   33 +-
 include/asm-m68knommu/uaccess.h               |    2 +
 include/asm-mips/bug.h                        |   10 +-
 include/asm-mips/dma-mapping.h                |    1 -
 include/asm-mips/hardirq.h                    |   40 -
 include/asm-mips/ptrace.h                     |    1 +
 include/asm-mips/resource.h                   |    2 +-
 include/asm-mips/semaphore.h                  |   36 +-
 include/asm-mips/siginfo.h                    |    2 +-
 include/asm-mips/socket.h                     |   41 +-
 include/asm-mips/uaccess.h                    |    4 +
 include/asm-mips/vr41xx/vrc4173.h             |  106 +
 include/asm-parisc/bug.h                      |   27 +-
 include/asm-parisc/cacheflush.h               |   12 +-
 include/asm-parisc/hardirq.h                  |   42 -
 include/asm-parisc/ptrace.h                   |    1 +
 include/asm-parisc/resource.h                 |    2 +-
 include/asm-parisc/semaphore.h                |   31 +-
 include/asm-parisc/socket.h                   |   14 -
 include/asm-parisc/uaccess.h                  |    2 +
 include/asm-parisc/unistd.h                   |    2 +-
 include/asm-ppc/bug.h                         |    7 +-
 include/asm-ppc/checksum.h                    |    2 +-
 include/asm-ppc/dma-mapping.h                 |    1 -
 include/asm-ppc/fsl_ocp.h                     |    2 +-
 include/asm-ppc/hardirq.h                     |   44 -
 include/asm-ppc/ibm44x.h                      |    4 +-
 include/asm-ppc/ide.h                         |    8 +-
 include/asm-ppc/io.h                          |   74 +-
 include/asm-ppc/mpc52xx.h                     |  374 +-
 include/asm-ppc/mpc52xx_psc.h                 |  162 +-
 include/asm-ppc/mpc8260.h                     |    4 +
 include/asm-ppc/open_pic.h                    |    2 +-
 include/asm-ppc/ppcboot.h                     |   36 +-
 include/asm-ppc/ptrace.h                      |    6 +
 include/asm-ppc/reg_booke.h                   |    6 +-
 include/asm-ppc/residual.h                    |   16 +
 include/asm-ppc/resource.h                    |    2 +-
 include/asm-ppc/semaphore.h                   |   36 +-
 include/asm-ppc/serial.h                      |   12 +-
 include/asm-ppc/socket.h                      |   16 -
 include/asm-ppc/thread_info.h                 |   10 -
 include/asm-ppc/uaccess.h                     |    2 +
 include/asm-ppc64/bitops.h                    |   88 +-
 include/asm-ppc64/btext.h                     |   19 +-
 include/asm-ppc64/bug.h                       |    8 +-
 include/asm-ppc64/checksum.h                  |    4 +-
 include/asm-ppc64/dma-mapping.h               |    1 -
 include/asm-ppc64/eeh.h                       |  152 +-
 include/asm-ppc64/hardirq.h                   |   45 -
 include/asm-ppc64/hvcall.h                    |    8 +-
 include/asm-ppc64/hvconsole.h                 |   18 +-
 include/asm-ppc64/hvcserver.h                 |   25 +-
 include/asm-ppc64/iSeries/iSeries_io.h        |   18 +-
 include/asm-ppc64/io.h                        |  107 +-
 include/asm-ppc64/iommu.h                     |   13 +-
 include/asm-ppc64/lmb.h                       |   10 +-
 include/asm-ppc64/machdep.h                   |    8 +-
 include/asm-ppc64/memory.h                    |   10 -
 include/asm-ppc64/mmu.h                       |  244 +-
 include/asm-ppc64/mmu_context.h               |  218 +-
 include/asm-ppc64/mmzone.h                    |    4 +-
 include/asm-ppc64/naca.h                      |    3 -
 include/asm-ppc64/paca.h                      |   19 +-
 include/asm-ppc64/page.h                      |   26 +-
 include/asm-ppc64/pci-bridge.h                |    9 +-
 include/asm-ppc64/pgalloc.h                   |    1 +
 include/asm-ppc64/pgtable.h                   |   33 +-
 include/asm-ppc64/ppc32.h                     |   30 +-
 include/asm-ppc64/processor.h                 |   58 +-
 include/asm-ppc64/prom.h                      |   71 +-
 include/asm-ppc64/ptrace.h                    |    8 +-
 include/asm-ppc64/resource.h                  |    2 +-
 include/asm-ppc64/rtas.h                      |  143 +-
 include/asm-ppc64/semaphore.h                 |   36 +-
 include/asm-ppc64/smp.h                       |   24 +-
 include/asm-ppc64/socket.h                    |   16 -
 include/asm-ppc64/spinlock.h                  |  278 +-
 include/asm-ppc64/system.h                    |    3 +
 include/asm-ppc64/systemcfg.h                 |   49 +-
 include/asm-ppc64/tlb.h                       |   17 +-
 include/asm-ppc64/uaccess.h                   |    6 +
 include/asm-ppc64/unistd.h                    |    6 +-
 include/asm-s390/bug.h                        |   19 +-
 include/asm-s390/dma-mapping.h                |   13 +-
 include/asm-s390/hardirq.h                    |   43 +-
 include/asm-s390/idals.h                      |    2 +-
 include/asm-s390/irq.h                        |    2 +-
 include/asm-s390/lowcore.h                    |    8 +-
 include/asm-s390/page.h                       |   19 +
 include/asm-s390/pgtable.h                    |   23 +-
 include/asm-s390/processor.h                  |   21 +
 include/asm-s390/ptrace.h                     |    1 +
 include/asm-s390/resource.h                   |    2 +-
 include/asm-s390/socket.h                     |   16 -
 include/asm-s390/thread_info.h                |   38 +-
 include/asm-s390/timer.h                      |    2 -
 include/asm-s390/uaccess.h                    |    6 +
 include/asm-sh/bug.h                          |   17 +-
 include/asm-sh/cacheflush.h                   |   14 +-
 include/asm-sh/dma-mapping.h                  |    1 -
 include/asm-sh/hardirq.h                      |   41 +-
 include/asm-sh/ptrace.h                       |    9 +
 include/asm-sh/resource.h                     |    2 +-
 include/asm-sh/semaphore.h                    |   35 +-
 include/asm-sh/socket.h                       |   16 -
 include/asm-sh/uaccess.h                      |    4 +
 include/asm-sh64/cacheflush.h                 |   14 +-
 include/asm-sh64/dma-mapping.h                |    1 -
 include/asm-sh64/ptrace.h                     |    1 +
 include/asm-sh64/semaphore.h                  |   35 +-
 include/asm-sh64/uaccess.h                    |    3 +
 include/asm-sparc/bug.h                       |   17 +-
 include/asm-sparc/cacheflush.h                |   10 +-
 include/asm-sparc/dma-mapping.h               |    1 -
 include/asm-sparc/hardirq.h                   |   41 -
 include/asm-sparc/ptrace.h                    |    1 +
 include/asm-sparc/resource.h                  |    2 +-
 include/asm-sparc/semaphore.h                 |   36 +-
 include/asm-sparc/sigcontext.h                |   14 -
 include/asm-sparc/socket.h                    |   16 -
 include/asm-sparc/uaccess.h                   |    3 +
 include/asm-sparc/unistd.h                    |   11 +-
 include/asm-sparc/vaddrs.h                    |    4 +-
 include/asm-sparc64/bitops.h                  |   35 +-
 include/asm-sparc64/bug.h                     |   19 +-
 include/asm-sparc64/cacheflush.h              |   11 +-
 include/asm-sparc64/checksum.h                |   37 +-
 include/asm-sparc64/delay.h                   |   69 +-
 include/asm-sparc64/dma.h                     |    2 +-
 include/asm-sparc64/ebus.h                    |    2 +-
 include/asm-sparc64/elf.h                     |    4 +-
 include/asm-sparc64/hardirq.h                 |   41 -
 include/asm-sparc64/ide.h                     |   12 +-
 include/asm-sparc64/io.h                      |  162 +-
 include/asm-sparc64/kdebug.h                  |   49 +-
 include/asm-sparc64/parport.h                 |    6 +-
 include/asm-sparc64/pbm.h                     |    9 +
 include/asm-sparc64/ptrace.h                  |    5 +
 include/asm-sparc64/resource.h                |    2 +-
 include/asm-sparc64/sigcontext.h              |   12 -
 include/asm-sparc64/siginfo.h                 |   54 +-
 include/asm-sparc64/socket.h                  |   16 -
 include/asm-sparc64/spinlock.h                |  180 +-
 include/asm-sparc64/string.h                  |  109 +-
 include/asm-sparc64/tlb.h                     |    2 +
 include/asm-sparc64/ttable.h                  |    6 +
 include/asm-sparc64/uaccess.h                 |   53 +-
 include/asm-sparc64/unistd.h                  |   12 +-
 include/asm-sparc64/vga.h                     |    3 +
 include/asm-um/archparam-i386.h               |   89 +-
 include/asm-um/bug.h                          |   28 +-
 include/asm-um/common.lds.S                   |   52 +-
 include/asm-um/current.h                      |    6 +-
 include/asm-um/dma-mapping.h                  |  122 +-
 include/asm-um/elf.h                          |   13 +
 include/asm-um/fixmap.h                       |    8 +
 include/asm-um/irq.h                          |   18 -
 include/asm-um/mmu_context.h                  |    4 +-
 include/asm-um/page.h                         |   34 +-
 include/asm-um/pgtable.h                      |  109 +-
 include/asm-um/processor-generic.h            |   47 +-
 include/asm-um/processor-i386.h               |   11 +-
 include/asm-um/ptrace-generic.h               |    2 +
 include/asm-um/smp.h                          |    6 +-
 include/asm-um/spinlock.h                     |    4 -
 include/asm-um/system-generic.h               |    9 +-
 include/asm-um/system-i386.h                  |   31 -
 include/asm-um/thread_info.h                  |   16 +-
 include/asm-um/timex.h                        |    2 -
 include/asm-um/uaccess.h                      |    7 +-
 include/asm-um/unistd.h                       |    5 +-
 include/asm-v850/bug.h                        |   12 +-
 include/asm-v850/hardirq.h                    |   40 -
 include/asm-v850/ptrace.h                     |    1 +
 include/asm-v850/resource.h                   |    2 +-
 include/asm-v850/socket.h                     |   16 -
 include/asm-v850/uaccess.h                    |    3 +
 include/asm-x86_64/acpi.h                     |    7 +
 include/asm-x86_64/apic.h                     |   28 +-
 include/asm-x86_64/apicdef.h                  |    2 +-
 include/asm-x86_64/atomic.h                   |  160 +
 include/asm-x86_64/bitops.h                   |  143 +-
 include/asm-x86_64/bug.h                      |   25 +-
 include/asm-x86_64/cpufeature.h               |   15 +-
 include/asm-x86_64/desc.h                     |    4 +-
 include/asm-x86_64/dma-mapping.h              |  134 +-
 include/asm-x86_64/elf.h                      |    7 +
 include/asm-x86_64/hardirq.h                  |   43 +-
 include/asm-x86_64/hw_irq.h                   |   35 +-
 include/asm-x86_64/i387.h                     |   24 +-
 include/asm-x86_64/ia32.h                     |   10 +-
 include/asm-x86_64/ia32_unistd.h              |    3 +-
 include/asm-x86_64/io.h                       |   59 +-
 include/asm-x86_64/mpspec.h                   |    3 +-
 include/asm-x86_64/msi.h                      |    3 +-
 include/asm-x86_64/mtrr.h                     |    2 -
 include/asm-x86_64/pci.h                      |  253 +-
 include/asm-x86_64/processor.h                |   17 +-
 include/asm-x86_64/proto.h                    |    4 +-
 include/asm-x86_64/ptrace.h                   |    1 +
 include/asm-x86_64/resource.h                 |    2 +-
 include/asm-x86_64/semaphore.h                |   35 +-
 include/asm-x86_64/smp.h                      |   14 +-
 include/asm-x86_64/socket.h                   |   16 -
 include/asm-x86_64/spinlock.h                 |    4 +-
 include/asm-x86_64/system.h                   |    8 +-
 include/asm-x86_64/topology.h                 |    9 +-
 include/asm-x86_64/uaccess.h                  |    6 +
 include/asm-x86_64/unistd.h                   |    4 +-
 include/linux/acct.h                          |   23 +-
 include/linux/acpi.h                          |    7 +-
 include/linux/adfs_fs.h                       |   16 +-
 include/linux/adfs_fs_i.h                     |    2 +-
 include/linux/adfs_fs_sb.h                    |    2 +-
 include/linux/affs_fs.h                       |    3 +-
 include/linux/affs_hardblocks.h               |   14 +-
 include/linux/aio.h                           |   28 +-
 include/linux/amigaffs.h                      |  112 +-
 include/linux/arcdevice.h                     |    2 +-
 include/linux/ata.h                           |   31 +-
 include/linux/atalk.h                         |   29 +-
 include/linux/bio.h                           |    3 +
 include/linux/bitmap.h                        |    3 +
 include/linux/blkdev.h                        |   24 +
 include/linux/bootmem.h                       |    3 +
 include/linux/buffer_head.h                   |   26 +-
 include/linux/byteorder/big_endian.h          |  118 +-
 include/linux/byteorder/generic.h             |    8 +-
 include/linux/byteorder/little_endian.h       |  118 +-
 include/linux/capability.h                    |    2 +-
 include/linux/cdrom.h                         |    3 +-
 include/linux/coda.h                          |   10 +-
 include/linux/compat.h                        |   12 +
 include/linux/compat_ioctl.h                  |   24 +-
 include/linux/compiler-gcc+.h                 |    6 +-
 include/linux/compiler-gcc3.h                 |   12 +-
 include/linux/compiler.h                      |    8 +
 include/linux/cpu.h                           |    2 +-
 include/linux/cpufreq.h                       |    7 -
 include/linux/cpumask.h                       |    5 +-
 include/linux/cyclades.h                      |   10 +-
 include/linux/dcache.h                        |    4 +-
 include/linux/delay.h                         |    6 +
 include/linux/device.h                        |    4 +-
 include/linux/dma-mapping.h                   |   30 +
 include/linux/dqblk_xfs.h                     |   63 +-
 include/linux/efs_dir.h                       |    4 +-
 include/linux/efs_fs.h                        |    4 +-
 include/linux/efs_fs_i.h                      |   24 +-
 include/linux/efs_fs_sb.h                     |   52 +-
 include/linux/efs_vh.h                        |   20 +-
 include/linux/elf.h                           |    7 +-
 include/linux/err.h                           |    4 +-
 include/linux/errno.h                         |    1 +
 include/linux/ext2_fs.h                       |  149 +-
 include/linux/ext3_fs.h                       |  146 +-
 include/linux/ext3_fs_i.h                     |    2 +-
 include/linux/fb.h                            |  180 +-
 include/linux/fs.h                            |  124 +-
 include/linux/genhd.h                         |  111 +-
 include/linux/gfp.h                           |    5 +
 include/linux/hdreg.h                         |    5 +-
 include/linux/hiddev.h                        |    8 +-
 include/linux/highmem.h                       |    4 +
 include/linux/highuid.h                       |    8 +-
 include/linux/hpet.h                          |    4 +-
 include/linux/i2c-id.h                        |    4 +
 include/linux/i2c-vid.h                       |    5 +-
 include/linux/i2c.h                           |    4 +-
 include/linux/i2o-dev.h                       |  262 +-
 include/linux/i2o.h                           |  746 +-
 include/linux/ide.h                           |   62 +-
 include/linux/if_bridge.h                     |    2 +-
 include/linux/if_ether.h                      |   14 +-
 include/linux/if_fddi.h                       |   36 +-
 include/linux/if_tr.h                         |    9 +
 include/linux/if_vlan.h                       |   12 +-
 include/linux/inetdevice.h                    |   20 +-
 include/linux/input.h                         |    2 +
 include/linux/interrupt.h                     |    2 +-
 include/linux/ioctl32.h                       |   25 +-
 include/linux/ip6_tunnel.h                    |    2 +
 include/linux/ipmi.h                          |    6 +
 include/linux/ipv6.h                          |   11 +-
 include/linux/isicom.h                        |    1 -
 include/linux/iso_fs.h                        |   12 +-
 include/linux/jbd.h                           |   39 +-
 include/linux/kernel.h                        |    6 +
 include/linux/kmod.h                          |    1 +
 include/linux/kobject.h                       |   11 +-
 include/linux/kref.h                          |   14 +-
 include/linux/libata.h                        |   88 +-
 include/linux/linkage.h                       |    4 +
 include/linux/list.h                          |   42 +-
 include/linux/lockd/bind.h                    |    2 +-
 include/linux/lockd/lockd.h                   |   23 +-
 include/linux/mempolicy.h                     |    3 -
 include/linux/mii.h                           |    3 +-
 include/linux/miscdevice.h                    |    1 +
 include/linux/mm.h                            |  126 +-
 include/linux/mman.h                          |    3 +
 include/linux/mmzone.h                        |   14 +-
 include/linux/moduleparam.h                   |    7 +-
 include/linux/msdos_fs.h                      |   57 +-
 include/linux/mtd/map.h                       |    2 +-
 include/linux/ncp.h                           |   92 +-
 include/linux/ncp_fs.h                        |   10 +-
 include/linux/ncp_fs_i.h                      |    8 +-
 include/linux/ncp_no.h                        |   26 +-
 include/linux/net.h                           |   30 +
 include/linux/netdevice.h                     |    9 +-
 include/linux/netfilter.h                     |    2 +-
 include/linux/netfilter_bridge/ebt_802_3.h    |    9 +
 include/linux/netfilter_ipv4/ip_conntrack.h   |   65 +-
 .../linux/netfilter_ipv4/ip_conntrack_core.h  |   32 +-
 .../linux/netfilter_ipv4/ip_conntrack_ftp.h   |    5 -
 .../linux/netfilter_ipv4/ip_conntrack_irc.h   |    5 -
 .../netfilter_ipv4/ip_conntrack_protocol.h    |   43 +-
 .../linux/netfilter_ipv4/ip_conntrack_tcp.h   |   37 +-
 .../linux/netfilter_ipv4/ip_conntrack_tuple.h |    6 +
 include/linux/netfilter_ipv4/ip_nat.h         |   15 +-
 include/linux/netfilter_ipv4/ip_nat_core.h    |    6 -
 include/linux/netfilter_ipv4/ip_nat_helper.h  |    8 +-
 .../linux/netfilter_ipv4/ip_nat_protocol.h    |   16 +-
 include/linux/netfilter_ipv4/ip_tables.h      |    1 -
 include/linux/netfilter_ipv6.h                |    2 +
 include/linux/netfilter_ipv6/ip6_tables.h     |    4 -
 include/linux/netlink.h                       |    8 +-
 include/linux/nfs.h                           |   17 +
 include/linux/nfs4.h                          |   62 +-
 include/linux/nfs_fs.h                        |  116 +-
 include/linux/nfs_fs_i.h                      |    4 +-
 include/linux/nfs_fs_sb.h                     |    1 +
 include/linux/nfs_mount.h                     |    2 +-
 include/linux/nfs_page.h                      |   37 +-
 include/linux/nfs_xdr.h                       |   76 +-
 include/linux/nfsd/nfsd.h                     |   13 +-
 include/linux/nfsd/state.h                    |    2 +-
 include/linux/nfsd/xdr4.h                     |    6 +-
 include/linux/nls.h                           |   25 +
 include/linux/node.h                          |    1 -
 include/linux/notifier.h                      |    4 +
 include/linux/page-flags.h                    |   10 +-
 include/linux/pagemap.h                       |    1 +
 include/linux/pci.h                           |   24 +-
 include/linux/pci_ids.h                       |   21 +-
 include/linux/percpu.h                        |   26 +-
 include/linux/personality.h                   |   12 +-
 include/linux/pfkeyv2.h                       |    1 +
 include/linux/pid.h                           |   43 +-
 include/linux/pkt_sched.h                     |   20 +
 include/linux/pm.h                            |   11 +-
 include/linux/poll.h                          |    8 +-
 include/linux/prctl.h                         |    2 +
 include/linux/prio_tree.h                     |   12 +
 include/linux/proc_fs.h                       |   11 +-
 include/linux/profile.h                       |   58 +-
 include/linux/ptrace.h                        |    2 +-
 include/linux/quota.h                         |    1 -
 include/linux/quotaio_v2.h                    |   44 +-
 include/linux/raid/md.h                       |    2 -
 include/linux/raid/md_k.h                     |   11 +-
 include/linux/random.h                        |    2 -
 include/linux/rbtree.h                        |    1 +
 include/linux/rcupdate.h                      |  142 +-
 include/linux/reiserfs_fs.h                   |   20 +-
 include/linux/reiserfs_fs_i.h                 |    2 +-
 include/linux/reiserfs_fs_sb.h                |    4 +
 include/linux/resource.h                      |    6 +
 include/linux/rmap.h                          |   18 +-
 include/linux/romfs_fs.h                      |   18 +-
 include/linux/rtnetlink.h                     |  151 +-
 include/linux/sched.h                         |  282 +-
 include/linux/serial_core.h                   |    1 +
 include/linux/serio.h                         |   66 +-
 include/linux/shm.h                           |    2 +
 include/linux/shmem_fs.h                      |   14 +-
 include/linux/signal.h                        |    2 +-
 include/linux/skbuff.h                        |   43 +-
 include/linux/slab.h                          |    7 +-
 include/linux/socket.h                        |    1 -
 include/linux/spinlock.h                      |  244 +-
 include/linux/stddef.h                        |    6 +
 include/linux/sunrpc/auth_gss.h               |    2 -
 include/linux/sunrpc/cache.h                  |    5 +-
 include/linux/sunrpc/gss_asn1.h               |    1 -
 include/linux/sunrpc/sched.h                  |    2 +
 include/linux/sunrpc/svc.h                    |   10 +
 include/linux/suspend.h                       |   20 -
 include/linux/swap.h                          |   22 +-
 include/linux/syscalls.h                      |   10 +-
 include/linux/sysctl.h                        |   18 +-
 include/linux/sysv_fs.h                       |  131 +-
 include/linux/tcp.h                           |   28 +-
 include/linux/time.h                          |   15 +
 include/linux/times.h                         |   20 +
 include/linux/timex.h                         |  121 +-
 include/linux/topology.h                      |    2 +-
 include/linux/tty.h                           |   40 +-
 include/linux/tty_ldisc.h                     |   10 +
 include/linux/types.h                         |   13 +
 include/linux/udf_fs_i.h                      |    2 +-
 include/linux/ufs_fs.h                        |  539 +-
 include/linux/ufs_fs_i.h                      |    4 +-
 include/linux/umem.h                          |   14 +-
 include/linux/usb.h                           |   13 +-
 include/linux/usb_ch9.h                       |    8 +-
 include/linux/usb_gadget.h                    |    6 -
 include/linux/videodev.h                      |    1 +
 include/linux/vs_base.h                       |   50 +-
 include/linux/vs_context.h                    |   24 +-
 include/linux/vs_cvirt.h                      |   67 +-
 include/linux/vs_dlimit.h                     |   17 +-
 include/linux/vs_limit.h                      |   75 +-
 include/linux/vs_memory.h                     |  110 +-
 include/linux/vs_network.h                    |   41 +-
 include/linux/vs_socket.h                     |    8 +-
 include/linux/vserver.h                       |    4 -
 include/linux/vserver/context.h               |   34 +-
 include/linux/vserver/cvirt.h                 |   79 +-
 include/linux/vserver/debug.h                 |   49 +-
 include/linux/vserver/dlimit.h                |   12 +-
 include/linux/vserver/inode.h                 |    8 +-
 include/linux/vserver/legacy.h                |    6 +-
 include/linux/vserver/limit.h                 |   23 +-
 include/linux/vserver/namespace.h             |    7 +-
 include/linux/vserver/network.h               |   18 +-
 include/linux/vserver/sched.h                 |  126 +-
 include/linux/vserver/signal.h                |   10 +-
 include/linux/vserver/switch.h                |   28 +-
 include/linux/vserver/xid.h                   |    4 +-
 include/linux/vt_kern.h                       |    2 +-
 include/linux/wait.h                          |   41 +
 include/linux/workqueue.h                     |    2 +
 include/linux/writeback.h                     |   24 +-
 include/linux/xfrm.h                          |    1 +
 include/math-emu/op-common.h                  |    6 +-
 include/media/id.h                            |    1 -
 include/media/tuner.h                         |   17 +
 include/net/addrconf.h                        |    4 +-
 include/net/af_unix.h                         |    7 +-
 include/net/dn_neigh.h                        |    1 -
 include/net/if_inet6.h                        |    2 +
 include/net/inet_ecn.h                        |   43 +-
 include/net/ip.h                              |    1 +
 include/net/ip6_fib.h                         |    1 +
 include/net/ip6_route.h                       |   12 +
 include/net/ip_fib.h                          |   39 +-
 include/net/ipcomp.h                          |    3 +-
 include/net/ipv6.h                            |    2 +-
 include/net/llc_pdu.h                         |   10 +-
 include/net/neighbour.h                       |  100 +-
 include/net/pkt_act.h                         |   13 +-
 include/net/pkt_sched.h                       |    3 +-
 include/net/route.h                           |    7 +-
 include/net/sctp/sctp.h                       |    1 +
 include/net/sock.h                            |   13 +-
 include/net/tcp.h                             |  246 +-
 include/net/tcp_ecn.h                         |    2 +-
 include/net/xfrm.h                            |  109 +-
 include/pcmcia/ss.h                           |    6 +-
 include/rxrpc/call.h                          |    6 +-
 include/rxrpc/connection.h                    |   12 +-
 include/rxrpc/packet.h                        |   26 +-
 include/rxrpc/peer.h                          |    2 +-
 include/rxrpc/rxrpc.h                         |    9 +-
 include/rxrpc/transport.h                     |    2 -
 include/rxrpc/types.h                         |    2 +
 include/scsi/scsi.h                           |   10 +-
 include/scsi/scsi_device.h                    |   42 +-
 include/scsi/scsi_driver.h                    |    1 +
 include/scsi/scsi_eh.h                        |    1 -
 include/sound/ac97_codec.h                    |   42 +-
 include/sound/asequencer.h                    |    4 +-
 include/sound/asound.h                        |    1 -
 include/sound/control.h                       |    3 +-
 include/sound/core.h                          |   19 +-
 include/sound/cs46xx.h                        |   21 +-
 include/sound/driver.h                        |    2 -
 include/sound/emu10k1.h                       |   27 +-
 include/sound/es1688.h                        |    2 -
 include/sound/info.h                          |    5 +-
 include/sound/initval.h                       |   33 -
 include/sound/memalloc.h                      |   21 +-
 include/sound/pcm.h                           |   58 +-
 include/sound/pcm_oss.h                       |   10 +-
 include/sound/seq_kernel.h                    |    7 +-
 include/sound/soundfont.h                     |    1 +
 include/sound/timer.h                         |    3 +-
 include/sound/trident.h                       |    1 -
 include/sound/version.h                       |    4 +-
 include/sound/vx_core.h                       |    8 +
 include/sound/ymfpci.h                        |    1 -
 include/video/neomagic.h                      |    3 +
 include/video/tdfx.h                          |    1 +
 include/video/vga.h                           |   46 +-
 init/Kconfig                                  |   27 +-
 init/do_mounts_rd.c                           |   20 +-
 init/main.c                                   |  144 +-
 ipc/mqueue.c                                  |    2 +-
 ipc/msg.c                                     |  248 +-
 ipc/sem.c                                     |   98 +-
 ipc/shm.c                                     |   50 +-
 ipc/util.c                                    |  107 +-
 ipc/util.h                                    |   12 +-
 kernel/Makefile                               |    3 +-
 kernel/acct.c                                 |   10 +-
 kernel/audit.c                                |   15 +-
 kernel/auditsc.c                              |    9 +-
 kernel/capability.c                           |    7 +-
 kernel/compat.c                               |  189 +-
 kernel/cpu.c                                  |    7 +-
 kernel/exec_domain.c                          |  121 +-
 kernel/exit.c                                 |  382 +-
 kernel/fork.c                                 |  197 +-
 kernel/kmod.c                                 |    4 +-
 kernel/kthread.c                              |    2 +-
 kernel/module.c                               |   53 +-
 kernel/panic.c                                |    8 +-
 kernel/params.c                               |   10 +
 kernel/pid.c                                  |  107 +-
 kernel/posix-timers.c                         |   24 +-
 kernel/power/Kconfig                          |   42 +-
 kernel/power/Makefile                         |    7 +-
 kernel/power/console.c                        |    3 +
 kernel/power/disk.c                           |   85 +-
 kernel/power/main.c                           |   17 +-
 kernel/power/power.h                          |   19 +-
 kernel/power/process.c                        |    4 +-
 kernel/power/swsusp.c                         | 1386 ++--
 kernel/printk.c                               |   21 +-
 kernel/profile.c                              |  241 +-
 kernel/ptrace.c                               |   63 +-
 kernel/rcupdate.c                             |  311 +-
 kernel/resource.c                             |   22 +-
 kernel/sched.c                                | 1666 +++--
 kernel/signal.c                               |  323 +-
 kernel/softirq.c                              |    7 +-
 kernel/sys.c                                  |  190 +-
 kernel/sysctl.c                               |   57 +-
 kernel/time.c                                 |  102 +-
 kernel/timer.c                                |  159 +-
 kernel/user.c                                 |    4 +-
 kernel/vserver/Kconfig                        |   10 +
 kernel/vserver/context.c                      |  185 +-
 kernel/vserver/cvirt.c                        |   48 +-
 kernel/vserver/dlimit.c                       |   72 +-
 kernel/vserver/helper.c                       |   10 +-
 kernel/vserver/inode.c                        |   14 +-
 kernel/vserver/legacy.c                       |   10 +-
 kernel/vserver/limit.c                        |   16 +-
 kernel/vserver/namespace.c                    |   54 +-
 kernel/vserver/network.c                      |  138 +-
 kernel/vserver/proc.c                         |   89 +-
 kernel/vserver/sched.c                        |   72 +-
 kernel/vserver/signal.c                       |   51 +-
 kernel/vserver/switch.c                       |   16 +-
 kernel/vserver/sysctl.c                       |  152 +-
 kernel/workqueue.c                            |   22 +-
 lib/Makefile                                  |    8 +-
 lib/bitmap.c                                  |   82 +
 lib/idr.c                                     |  168 +-
 lib/kobject.c                                 |   57 +-
 lib/kref.c                                    |   29 +-
 lib/rbtree.c                                  |   13 +
 lib/rwsem.c                                   |    8 +-
 lib/zlib_inflate/Makefile                     |    2 +-
 lib/zlib_inflate/infblock.c                   |    2 +-
 lib/zlib_inflate/inflate.c                    |  143 -
 lib/zlib_inflate/inftrees.c                   |   34 +-
 lib/zlib_inflate/inftrees.h                   |    1 +
 mm/Makefile                                   |    7 +-
 mm/bootmem.c                                  |   25 +-
 mm/filemap.c                                  |  425 +-
 mm/fremap.c                                   |    4 +-
 mm/highmem.c                                  |    6 +-
 mm/hugetlb.c                                  |    6 +-
 mm/memory.c                                   |    9 +-
 mm/mempolicy.c                                |   80 +-
 mm/mempool.c                                  |    1 +
 mm/mlock.c                                    |   65 +-
 mm/mmap.c                                     |  211 +-
 mm/mprotect.c                                 |    2 +
 mm/mremap.c                                   |    9 +-
 mm/nommu.c                                    |    2 +-
 mm/oom_kill.c                                 |   23 +-
 mm/page_alloc.c                               |  358 +-
 mm/prio_tree.c                                |   69 +-
 mm/readahead.c                                |   42 +-
 mm/rmap.c                                     |  289 +-
 mm/shmem.c                                    |  316 +-
 mm/slab.c                                     |  334 +-
 mm/swap_state.c                               |    2 +-
 mm/swapfile.c                                 |   27 +-
 mm/truncate.c                                 |    1 +
 mm/vmalloc.c                                  |   27 +-
 mm/vmscan.c                                   |  115 +-
 net/8021q/vlan.c                              |    2 +-
 net/8021q/vlan_dev.c                          |    6 +-
 net/Kconfig                                   |   13 +
 net/Makefile                                  |    3 +-
 net/appletalk/Makefile                        |    3 +-
 net/appletalk/atalk_proc.c                    |   13 -
 net/appletalk/ddp.c                           |   10 -
 net/appletalk/sysctl_net_atalk.c              |   18 +-
 net/atm/br2684.c                              |    2 +-
 net/atm/clip.c                                |  319 +-
 net/atm/common.h                              |   11 -
 net/atm/ipcommon.h                            |    3 -
 net/atm/lec.h                                 |    1 -
 net/atm/mpoa_proc.c                           |    2 +-
 net/ax25/af_ax25.c                            |    9 +-
 net/ax25/ax25_in.c                            |    1 -
 net/bluetooth/bnep/core.c                     |    2 +-
 net/bluetooth/l2cap.c                         |   19 +-
 net/bridge/br_input.c                         |   62 +-
 net/bridge/br_netfilter.c                     |  447 +-
 net/bridge/br_notify.c                        |    4 +-
 net/bridge/br_private.h                       |    2 +-
 net/bridge/netfilter/ebt_802_3.c              |    2 +-
 net/bridge/netfilter/ebt_among.c              |   61 +-
 net/bridge/netfilter/ebt_arp.c                |   55 +-
 net/bridge/netfilter/ebt_arpreply.c           |   34 +-
 net/bridge/netfilter/ebt_dnat.c               |    3 +-
 net/bridge/netfilter/ebt_ip.c                 |   33 +-
 net/bridge/netfilter/ebt_log.c                |   66 +-
 net/bridge/netfilter/ebt_redirect.c           |    7 +-
 net/bridge/netfilter/ebt_snat.c               |    3 +-
 net/bridge/netfilter/ebt_stp.c                |   22 +-
 net/bridge/netfilter/ebt_vlan.c               |   16 +-
 net/bridge/netfilter/ebtables.c               |    2 +-
 net/compat.c                                  |    6 +-
 net/core/Makefile                             |    2 +-
 net/core/dev.c                                |  145 +-
 net/core/dv.c                                 |    7 +-
 net/core/filter.c                             |   21 +-
 net/core/neighbour.c                          |  886 ++-
 net/core/net-sysfs.c                          |    1 -
 net/core/netfilter.c                          |   14 +-
 net/core/netpoll.c                            |   84 +-
 net/core/pktgen.c                             |  116 +-
 net/core/rtnetlink.c                          |  163 +-
 net/core/skbuff.c                             |    2 +
 net/core/sock.c                               |   21 +
 net/core/utils.c                              |  112 +-
 net/decnet/dn_dev.c                           |  125 +-
 net/decnet/dn_neigh.c                         |  225 +-
 net/decnet/dn_route.c                         |   43 +-
 net/econet/af_econet.c                        |   10 +-
 net/ethernet/eth.c                            |    6 +-
 net/ipv4/Kconfig                              |   40 +-
 net/ipv4/Makefile                             |    4 +-
 net/ipv4/af_inet.c                            |  156 +-
 net/ipv4/ah4.c                                |   17 +-
 net/ipv4/arp.c                                |  249 +-
 net/ipv4/devinet.c                            |  121 +-
 net/ipv4/esp4.c                               |   55 +-
 net/ipv4/fib_frontend.c                       |    4 +-
 net/ipv4/fib_hash.c                           |  844 +--
 net/ipv4/fib_rules.c                          |   25 +-
 net/ipv4/fib_semantics.c                      |  407 +-
 net/ipv4/icmp.c                               |   48 +-
 net/ipv4/igmp.c                               |   92 +-
 net/ipv4/ip_fragment.c                        |   52 +-
 net/ipv4/ip_gre.c                             |   33 +-
 net/ipv4/ip_input.c                           |    3 +-
 net/ipv4/ip_output.c                          |  108 +-
 net/ipv4/ipcomp.c                             |  221 +-
 net/ipv4/ipconfig.c                           |    5 +
 net/ipv4/ipip.c                               |   14 +-
 net/ipv4/ipvs/ip_vs_core.c                    |  118 +-
 net/ipv4/ipvs/ip_vs_proto.c                   |   42 +-
 net/ipv4/ipvs/ip_vs_proto_ah.c                |    9 +-
 net/ipv4/ipvs/ip_vs_proto_esp.c               |    9 +-
 net/ipv4/ipvs/ip_vs_proto_icmp.c              |   35 +-
 net/ipv4/ipvs/ip_vs_proto_tcp.c               |   44 +-
 net/ipv4/ipvs/ip_vs_proto_udp.c               |   42 +-
 net/ipv4/ipvs/ip_vs_sync.c                    |   28 +-
 net/ipv4/ipvs/ip_vs_xmit.c                    |   30 +-
 net/ipv4/netfilter/Kconfig                    |  239 +-
 net/ipv4/netfilter/Makefile                   |   11 +-
 net/ipv4/netfilter/arp_tables.c               |   19 +-
 net/ipv4/netfilter/ip_conntrack_amanda.c      |   17 +-
 net/ipv4/netfilter/ip_conntrack_core.c        |  417 +-
 net/ipv4/netfilter/ip_conntrack_ftp.c         |   46 +-
 net/ipv4/netfilter/ip_conntrack_irc.c         |   47 +-
 .../netfilter/ip_conntrack_proto_generic.c    |   28 +-
 net/ipv4/netfilter/ip_conntrack_proto_icmp.c  |  187 +-
 net/ipv4/netfilter/ip_conntrack_proto_tcp.c   | 1055 ++-
 net/ipv4/netfilter/ip_conntrack_proto_udp.c   |   96 +-
 net/ipv4/netfilter/ip_conntrack_standalone.c  |  486 +-
 net/ipv4/netfilter/ip_conntrack_tftp.c        |   20 +-
 net/ipv4/netfilter/ip_fw_compat_masq.c        |   11 +-
 net/ipv4/netfilter/ip_nat_core.c              |  131 +-
 net/ipv4/netfilter/ip_nat_ftp.c               |   52 +-
 net/ipv4/netfilter/ip_nat_helper.c            |   30 +-
 net/ipv4/netfilter/ip_nat_irc.c               |   45 +-
 net/ipv4/netfilter/ip_nat_proto_icmp.c        |    2 +-
 net/ipv4/netfilter/ip_nat_proto_tcp.c         |    2 +-
 net/ipv4/netfilter/ip_nat_proto_udp.c         |    2 +-
 net/ipv4/netfilter/ip_nat_proto_unknown.c     |    4 +-
 net/ipv4/netfilter/ip_nat_rule.c              |    3 +-
 net/ipv4/netfilter/ip_nat_snmp_basic.c        |    6 +-
 net/ipv4/netfilter/ip_nat_standalone.c        |   27 +-
 net/ipv4/netfilter/ip_nat_tftp.c              |   35 +-
 net/ipv4/netfilter/ip_queue.c                 |    2 +
 net/ipv4/netfilter/ip_tables.c                |   58 +-
 net/ipv4/netfilter/ipchains_core.c            |   44 +-
 net/ipv4/netfilter/ipfwadm_core.c             |   44 +-
 net/ipv4/netfilter/ipt_ECN.c                  |   29 +-
 net/ipv4/netfilter/ipt_LOG.c                  |  170 +-
 net/ipv4/netfilter/ipt_MASQUERADE.c           |    4 +-
 net/ipv4/netfilter/ipt_NOTRACK.c              |    3 +-
 net/ipv4/netfilter/ipt_REJECT.c               |   27 +-
 net/ipv4/netfilter/ipt_ULOG.c                 |   35 +-
 net/ipv4/netfilter/ipt_ah.c                   |   11 +-
 net/ipv4/netfilter/ipt_conntrack.c            |    2 +-
 net/ipv4/netfilter/ipt_ecn.c                  |   17 +-
 net/ipv4/netfilter/ipt_esp.c                  |   11 +-
 net/ipv4/netfilter/ipt_helper.c               |    1 +
 net/ipv4/netfilter/ipt_mac.c                  |    2 +-
 net/ipv4/netfilter/ipt_multiport.c            |   19 +-
 net/ipv4/netfilter/ipt_owner.c                |    2 +-
 net/ipv4/netfilter/ipt_recent.c               |   11 +-
 net/ipv4/netfilter/ipt_state.c                |    4 +-
 net/ipv4/netfilter/ipt_tcpmss.c               |   30 +-
 net/ipv4/netfilter/iptable_filter.c           |    3 +-
 net/ipv4/proc.c                               |    2 +-
 net/ipv4/raw.c                                |  101 +-
 net/ipv4/route.c                              |  164 +-
 net/ipv4/sysctl_net_ipv4.c                    |   12 +-
 net/ipv4/tcp.c                                |   14 +-
 net/ipv4/tcp_diag.c                           |   77 +-
 net/ipv4/tcp_input.c                          |  407 +-
 net/ipv4/tcp_ipv4.c                           |  126 +-
 net/ipv4/tcp_minisocks.c                      |   17 +-
 net/ipv4/tcp_output.c                         |  316 +-
 net/ipv4/tcp_timer.c                          |    8 +-
 net/ipv4/udp.c                                |    9 +-
 net/ipv4/xfrm4_input.c                        |    5 +-
 net/ipv4/xfrm4_output.c                       |    6 +-
 net/ipv4/xfrm4_policy.c                       |   21 +-
 net/ipv4/xfrm4_tunnel.c                       |   14 +-
 net/ipv6/Kconfig                              |   13 +
 net/ipv6/Makefile                             |    3 +-
 net/ipv6/addrconf.c                           |  176 +-
 net/ipv6/af_inet6.c                           |  156 +-
 net/ipv6/ah6.c                                |   29 +-
 net/ipv6/anycast.c                            |   63 +-
 net/ipv6/datagram.c                           |   13 +-
 net/ipv6/esp6.c                               |   52 +-
 net/ipv6/exthdrs.c                            |    3 +
 net/ipv6/exthdrs_core.c                       |   27 +-
 net/ipv6/icmp.c                               |   25 +-
 net/ipv6/ip6_fib.c                            |   29 +-
 net/ipv6/ip6_flowlabel.c                      |    3 +-
 net/ipv6/ip6_input.c                          |    3 +-
 net/ipv6/ip6_output.c                         |   94 +-
 net/ipv6/ip6_tunnel.c                         |   18 +
 net/ipv6/ipcomp6.c                            |  229 +-
 net/ipv6/mcast.c                              |   17 +-
 net/ipv6/ndisc.c                              |   91 +-
 net/ipv6/netfilter/Kconfig                    |    9 +
 net/ipv6/netfilter/Makefile                   |    1 +
 net/ipv6/netfilter/ip6_tables.c               |    1 +
 net/ipv6/netfilter/ip6t_LOG.c                 |    7 +-
 net/ipv6/netfilter/ip6t_eui64.c               |    6 +-
 net/ipv6/netfilter/ip6t_mac.c                 |    2 +-
 net/ipv6/netfilter/ip6t_owner.c               |    2 +-
 net/ipv6/netfilter/ip6table_filter.c          |    3 +-
 net/ipv6/raw.c                                |   60 +-
 net/ipv6/reassembly.c                         |   39 +-
 net/ipv6/route.c                              |  184 +-
 net/ipv6/sit.c                                |   16 +-
 net/ipv6/tcp_ipv6.c                           |   84 +-
 net/ipv6/udp.c                                |   12 +-
 net/ipv6/xfrm6_input.c                        |   21 +-
 net/ipv6/xfrm6_output.c                       |   14 +-
 net/ipv6/xfrm6_policy.c                       |   26 +-
 net/ipv6/xfrm6_tunnel.c                       |   72 +-
 net/ipx/af_ipx.c                              |    2 +
 net/irda/irlan/irlan_common.c                 |    5 +-
 net/irda/irlan/irlan_eth.c                    |   10 +-
 net/irda/irqueue.c                            |    8 +-
 net/key/af_key.c                              |   24 +-
 net/llc/af_llc.c                              |    1 -
 net/llc/llc_input.c                           |    2 +-
 net/llc/llc_output.c                          |    7 +-
 net/netlink/af_netlink.c                      |   38 +-
 net/netrom/af_netrom.c                        |    2 -
 net/packet/af_packet.c                        |   37 +-
 net/rose/af_rose.c                            |    2 -
 net/rxrpc/call.c                              |   65 +-
 net/rxrpc/connection.c                        |   37 +-
 net/rxrpc/main.c                              |    2 +-
 net/rxrpc/peer.c                              |    4 +-
 net/rxrpc/transport.c                         |   12 +-
 net/sched/Kconfig                             |   18 +-
 net/sched/Makefile                            |    5 +-
 net/sched/act_api.c                           |   10 +-
 net/sched/cls_api.c                           |   16 +-
 net/sched/cls_fw.c                            |    2 +-
 net/sched/cls_u32.c                           |    7 +-
 net/sched/estimator.c                         |   10 +-
 net/sched/sch_api.c                           |   46 +-
 net/sched/sch_atm.c                           |    2 +-
 net/sched/sch_cbq.c                           |   21 +-
 net/sched/sch_dsmark.c                        |    2 -
 net/sched/sch_generic.c                       |   73 +-
 net/sched/sch_hfsc.c                          |  315 +-
 net/sched/sch_htb.c                           |    1 -
 net/sched/sch_ingress.c                       |   14 +-
 net/sched/sch_netem.c                         |  810 +--
 net/sched/sch_red.c                           |    8 +-
 net/sched/sch_sfq.c                           |    1 -
 net/sched/sch_teql.c                          |    3 +-
 net/sctp/ipv6.c                               |   24 +-
 net/sctp/protocol.c                           |   36 +-
 net/sctp/socket.c                             |   26 +-
 net/sunrpc/auth_gss/Makefile                  |    4 +
 net/sunrpc/auth_gss/auth_gss.c                |    4 +-
 net/sunrpc/auth_gss/gss_generic_token.c       |    2 +-
 net/sunrpc/auth_gss/gss_krb5_unseal.c         |    2 +-
 net/sunrpc/auth_gss/svcauth_gss.c             |    2 -
 net/sunrpc/cache.c                            |    5 +-
 net/sunrpc/clnt.c                             |   41 +-
 net/sunrpc/sched.c                            |    4 +-
 net/sunrpc/sunrpc_syms.c                      |    1 +
 net/sunrpc/svc.c                              |    9 +-
 net/sunrpc/svcauth.c                          |   62 +-
 net/sunrpc/svcauth_unix.c                     |   32 +-
 net/sunrpc/xprt.c                             |    8 +-
 net/unix/af_unix.c                            |    2 +-
 net/wanrouter/af_wanpipe.c                    |    1 -
 net/x25/af_x25.c                              |    2 -
 net/xfrm/xfrm_export.c                        |    2 -
 net/xfrm/xfrm_policy.c                        |   26 +-
 net/xfrm/xfrm_state.c                         |   36 +-
 net/xfrm/xfrm_user.c                          |   56 +-
 scripts/Makefile                              |   17 +-
 scripts/Makefile.build                        |  121 +-
 scripts/Makefile.clean                        |   44 +-
 scripts/Makefile.lib                          |   52 +-
 scripts/Makefile.modinst                      |    2 +-
 scripts/Makefile.modpost                      |    5 +-
 scripts/basic/Makefile                        |    4 +-
 scripts/basic/fixdep.c                        |   11 +-
 scripts/binoffset.c                           |   12 +-
 scripts/genksyms/Makefile                     |    4 +-
 scripts/genksyms/genksyms.c                   |   15 +
 scripts/kconfig/Makefile                      |    2 +-
 scripts/kconfig/confdata.c                    |   17 +-
 scripts/kconfig/gconf.c                       |    5 +-
 scripts/kconfig/lkc.h                         |    3 -
 scripts/kconfig/mconf.c                       |  161 +-
 scripts/kconfig/menu.c                        |    1 -
 scripts/kconfig/zconf.tab.c_shipped           |    2 +
 scripts/kconfig/zconf.y                       |    2 +
 scripts/lxdialog/Makefile                     |    4 +-
 scripts/lxdialog/menubox.c                    |    9 +
 scripts/mod/Makefile                          |    4 +-
 scripts/mod/modpost.c                         |   36 +-
 scripts/mod/modpost.h                         |    2 +
 scripts/mod/sumversion.c                      |    4 +
 scripts/package/Makefile                      |    6 +-
 scripts/package/builddeb                      |    2 +-
 scripts/package/mkspec                        |   20 +-
 scripts/patch-kernel                          |  113 +-
 scripts/ver_linux                             |    7 +-
 security/Kconfig                              |    4 +-
 security/commoncap.c                          |    9 +-
 security/dummy.c                              |    4 +-
 security/security.c                           |    4 +-
 security/selinux/Kconfig                      |   15 +
 security/selinux/hooks.c                      |  211 +-
 security/selinux/include/avc.h                |    1 -
 security/selinux/selinuxfs.c                  |  266 +-
 security/selinux/ss/avtab.c                   |   12 +-
 security/selinux/ss/avtab.h                   |    2 +
 security/selinux/ss/policydb.h                |    1 -
 security/selinux/ss/services.c                |    1 +
 sound/arm/sa11xx-uda1341.c                    |   19 +-
 sound/core/control.c                          |   51 +-
 sound/core/device.c                           |    4 +-
 sound/core/hwdep.c                            |   40 +-
 sound/core/info.c                             |   63 +-
 sound/core/info_oss.c                         |   12 -
 sound/core/init.c                             |    4 +-
 sound/core/ioctl32/ioctl32.c                  |    2 +-
 sound/core/ioctl32/pcm32.c                    |   55 +-
 sound/core/memalloc.c                         |  412 +-
 sound/core/memory.c                           |   76 +-
 sound/core/oss/mixer_oss.c                    |   53 +-
 sound/core/oss/pcm_oss.c                      |   50 +-
 sound/core/oss/pcm_plugin.c                   |  133 +-
 sound/core/oss/pcm_plugin.h                   |    2 +-
 sound/core/oss/route.c                        |    2 +-
 sound/core/pcm.c                              |   23 +-
 sound/core/pcm_lib.c                          |   78 +-
 sound/core/pcm_memory.c                       |  122 +-
 sound/core/pcm_misc.c                         |  708 +-
 sound/core/pcm_native.c                       |  390 +-
 sound/core/pcm_timer.c                        |   13 +-
 sound/core/rawmidi.c                          |   62 +-
 sound/core/seq/Makefile                       |   58 +-
 sound/core/seq/instr/Makefile                 |   34 +-
 sound/core/seq/instr/ainstr_fm.c              |    2 -
 sound/core/seq/instr/ainstr_gf1.c             |    4 +-
 sound/core/seq/instr/ainstr_iw.c              |    8 +-
 sound/core/seq/instr/ainstr_simple.c          |    2 -
 sound/core/seq/oss/seq_oss.c                  |    9 +-
 sound/core/seq/oss/seq_oss_init.c             |    4 +-
 sound/core/seq/oss/seq_oss_ioctl.c            |   74 +-
 sound/core/seq/oss/seq_oss_midi.c             |    2 +-
 sound/core/seq/oss/seq_oss_readq.c            |   49 +-
 sound/core/seq/oss/seq_oss_readq.h            |    9 +-
 sound/core/seq/oss/seq_oss_rw.c               |  116 +-
 sound/core/seq/oss/seq_oss_synth.c            |    8 +-
 sound/core/seq/oss/seq_oss_timer.c            |    4 +-
 sound/core/seq/oss/seq_oss_writeq.c           |    2 +-
 sound/core/seq/seq.c                          |    3 +-
 sound/core/seq/seq_clientmgr.c                |   80 +-
 sound/core/seq/seq_device.c                   |   14 +-
 sound/core/seq/seq_dummy.c                    |   23 +-
 sound/core/seq/seq_fifo.c                     |    2 +-
 sound/core/seq/seq_instr.c                    |   11 +-
 sound/core/seq/seq_memory.c                   |    6 +-
 sound/core/seq/seq_midi.c                     |    6 +-
 sound/core/seq/seq_midi_emul.c                |    2 -
 sound/core/seq/seq_midi_event.c               |    2 +-
 sound/core/seq/seq_ports.c                    |    4 +-
 sound/core/seq/seq_prioq.c                    |    2 +-
 sound/core/seq/seq_queue.c                    |    2 +-
 sound/core/seq/seq_timer.c                    |    2 +-
 sound/core/seq/seq_virmidi.c                  |   46 +-
 sound/core/sgbuf.c                            |   11 +-
 sound/core/sound.c                            |   42 +-
 sound/core/timer.c                            |   67 +-
 sound/drivers/dummy.c                         |  102 +-
 sound/drivers/mpu401/mpu401.c                 |   21 +-
 sound/drivers/mpu401/mpu401_uart.c            |   22 +-
 sound/drivers/mtpav.c                         |   16 +-
 sound/drivers/opl3/opl3_lib.c                 |   10 +-
 sound/drivers/opl3/opl3_midi.c                |   14 +-
 sound/drivers/opl3/opl3_oss.c                 |   16 +-
 sound/drivers/opl3/opl3_seq.c                 |    9 +-
 sound/drivers/opl3/opl3_synth.c               |    6 +-
 sound/drivers/opl4/Makefile                   |    2 +-
 sound/drivers/opl4/opl4_lib.c                 |   59 +-
 sound/drivers/opl4/opl4_local.h               |    1 -
 sound/drivers/opl4/opl4_mixer.c               |   12 +-
 sound/drivers/opl4/opl4_proc.c                |    8 +-
 sound/drivers/opl4/opl4_seq.c                 |   10 +-
 sound/drivers/opl4/opl4_synth.c               |   35 +-
 sound/drivers/serial-u16550.c                 |   34 +-
 sound/drivers/virmidi.c                       |    9 +-
 sound/drivers/vx/vx_core.c                    |   11 +-
 sound/drivers/vx/vx_hwdep.c                   |    4 +-
 sound/drivers/vx/vx_mixer.c                   |   53 +-
 sound/drivers/vx/vx_pcm.c                     |   37 +-
 sound/drivers/vx/vx_uer.c                     |   15 +-
 sound/i2c/cs8427.c                            |   26 +-
 sound/i2c/i2c.c                               |   10 +-
 sound/i2c/l3/uda1341.c                        |   24 +-
 sound/i2c/other/ak4117.c                      |   10 +-
 sound/i2c/other/ak4xxx-adda.c                 |   12 +-
 sound/i2c/tea6330t.c                          |   14 +-
 sound/isa/Kconfig                             |    8 +
 sound/isa/ad1816a/ad1816a.c                   |   15 +-
 sound/isa/ad1816a/ad1816a_lib.c               |   18 +-
 sound/isa/ad1848/ad1848.c                     |   12 +-
 sound/isa/ad1848/ad1848_lib.c                 |   16 +-
 sound/isa/als100.c                            |   15 +-
 sound/isa/azt2320.c                           |   16 +-
 sound/isa/cmi8330.c                           |   18 +-
 sound/isa/cs423x/cs4231.c                     |   14 +-
 sound/isa/cs423x/cs4231_lib.c                 |   22 +-
 sound/isa/cs423x/cs4236.c                     |   20 +-
 sound/isa/cs423x/cs4236_lib.c                 |   26 +-
 sound/isa/dt019x.c                            |   14 +-
 sound/isa/es1688/es1688.c                     |   11 +-
 sound/isa/es1688/es1688_lib.c                 |   15 +-
 sound/isa/es18xx.c                            |   31 +-
 sound/isa/gus/Makefile                        |    6 +-
 sound/isa/gus/gus_dram.c                      |   10 +-
 sound/isa/gus/gus_instr.c                     |   18 +-
 sound/isa/gus/gus_irq.c                       |    4 +-
 sound/isa/gus/gus_main.c                      |   10 +-
 sound/isa/gus/gus_mem.c                       |    2 +-
 sound/isa/gus/gus_mem_proc.c                  |   12 +-
 sound/isa/gus/gus_mixer.c                     |   10 +-
 sound/isa/gus/gus_pcm.c                       |   38 +-
 sound/isa/gus/gus_synth.c                     |    2 +-
 sound/isa/gus/gus_timer.c                     |    6 +-
 sound/isa/gus/gus_uart.c                      |   12 +-
 sound/isa/gus/gusclassic.c                    |   13 +-
 sound/isa/gus/gusextreme.c                    |   17 +-
 sound/isa/gus/gusmax.c                        |   13 +-
 sound/isa/gus/interwave.c                     |   60 +-
 sound/isa/opl3sa2.c                           |   39 +-
 sound/isa/opti9xx/opti92x-ad1848.c            |   57 +-
 sound/isa/sb/emu8000.c                        |   18 +-
 sound/isa/sb/emu8000_callback.c               |   20 +-
 sound/isa/sb/emu8000_local.h                  |    2 -
 sound/isa/sb/emu8000_patch.c                  |    2 +-
 sound/isa/sb/emu8000_pcm.c                    |    4 +-
 sound/isa/sb/emu8000_synth.c                  |    1 -
 sound/isa/sb/es968.c                          |   13 +-
 sound/isa/sb/sb16.c                           |   21 +-
 sound/isa/sb/sb16_csp.c                       |   17 +-
 sound/isa/sb/sb16_main.c                      |   18 +-
 sound/isa/sb/sb8.c                            |   13 +-
 sound/isa/sb/sb8_main.c                       |    2 -
 sound/isa/sb/sb8_midi.c                       |   16 +-
 sound/isa/sb/sb_common.c                      |    9 +-
 sound/isa/sb/sb_mixer.c                       |    2 -
 sound/isa/sgalaxy.c                           |    9 +-
 sound/isa/sscape.c                            |   24 +-
 sound/isa/wavefront/wavefront.c               |   19 +-
 sound/isa/wavefront/wavefront_fx.c            |   54 +-
 sound/isa/wavefront/wavefront_synth.c         |    6 +
 sound/oss/Kconfig                             |   11 +-
 sound/oss/Makefile                            |    2 +-
 sound/oss/ad1848.c                            |   56 +-
 sound/oss/ad1848.h                            |    8 +-
 sound/oss/ad1889.c                            |   79 +-
 sound/oss/ad1889.h                            |    6 +-
 sound/oss/ali5455.c                           |    1 -
 sound/oss/au1000.c                            |    2 +-
 sound/oss/awe_wave.c                          |    4 +-
 sound/oss/btaudio.c                           |    4 +-
 sound/oss/cmpci.c                             |   83 +-
 sound/oss/cs4232.c                            |   46 +-
 sound/oss/cs4232.h                            |    2 -
 sound/oss/cs46xx.c                            |   13 +-
 sound/oss/dmasound/Kconfig                    |    2 +-
 sound/oss/emu10k1/midi.c                      |    3 +-
 sound/oss/forte.c                             |    1 -
 sound/oss/gus_card.c                          |   24 +-
 sound/oss/gus_wave.c                          |   14 +-
 sound/oss/harmony.c                           |  138 +-
 sound/oss/i810_audio.c                        |   13 +-
 sound/oss/ite8172.c                           |    2 +-
 sound/oss/kahlua.c                            |    4 +
 sound/oss/mad16.c                             |  220 +-
 sound/oss/maui.c                              |   63 +-
 sound/oss/mpu401.c                            |   26 +-
 sound/oss/mpu401.h                            |    2 +-
 sound/oss/msnd.c                              |   28 +-
 sound/oss/msnd.h                              |    9 +-
 sound/oss/msnd_pinnacle.c                     |   42 +-
 sound/oss/nec_vrc5477.c                       |    1 -
 sound/oss/opl3sa.c                            |   59 +-
 sound/oss/opl3sa2.c                           |   59 +-
 sound/oss/pss.c                               |  142 +-
 sound/oss/rme96xx.c                           |    2 +-
 sound/oss/sb_card.c                           |    9 +-
 sound/oss/sb_common.c                         |   24 +-
 sound/oss/sgalaxy.c                           |   42 +-
 sound/oss/sscape.c                            |  215 +-
 sound/oss/swarm_cs4297a.c                     |    2 +-
 sound/oss/trident.c                           |    1 -
 sound/oss/trix.c                              |  221 +-
 sound/oss/v_midi.c                            |    5 +-
 sound/oss/waveartist.c                        |    6 +-
 sound/oss/wavfront.c                          |    6 +-
 sound/oss/wf_midi.c                           |    5 +-
 sound/parisc/harmony.c                        |   75 +-
 sound/pci/Kconfig                             |   14 +-
 sound/pci/Makefile                            |    2 +
 sound/pci/ac97/ac97_codec.c                   |  417 +-
 sound/pci/ac97/ac97_id.h                      |    7 +
 sound/pci/ac97/ac97_local.h                   |   14 +-
 sound/pci/ac97/ac97_patch.c                   |  257 +-
 sound/pci/ac97/ac97_patch.h                   |    1 +
 sound/pci/ac97/ac97_pcm.c                     |    9 +-
 sound/pci/ac97/ac97_proc.c                    |   18 +-
 sound/pci/ac97/ak4531_codec.c                 |   26 +-
 sound/pci/ali5451/ali5451.c                   |   78 +-
 sound/pci/als4000.c                           |   64 +-
 sound/pci/atiixp.c                            |  127 +-
 sound/pci/au88x0/au88x0.c                     |   16 +-
 sound/pci/au88x0/au88x0.h                     |    2 -
 sound/pci/au88x0/au88x0_a3d.c                 |   14 +-
 sound/pci/au88x0/au88x0_core.c                |    2 +-
 sound/pci/au88x0/au88x0_eq.c                  |  160 +-
 sound/pci/au88x0/au88x0_game.c                |    2 +-
 sound/pci/au88x0/au88x0_mixer.c               |   13 +-
 sound/pci/au88x0/au88x0_mpu401.c              |    2 +-
 sound/pci/au88x0/au88x0_pcm.c                 |    7 +-
 sound/pci/au88x0/au88x0_xtalk.c               |    6 +
 sound/pci/au88x0/au88x0_xtalk.h               |    3 +-
 sound/pci/azt3328.c                           |  115 +-
 sound/pci/bt87x.c                             |   96 +-
 sound/pci/cmipci.c                            |  223 +-
 sound/pci/cs4281.c                            |  151 +-
 sound/pci/cs46xx/cs46xx.c                     |    9 +-
 sound/pci/cs46xx/cs46xx_lib.c                 |  346 +-
 sound/pci/cs46xx/cs46xx_lib.h                 |    2 -
 sound/pci/cs46xx/dsp_spos.c                   |   41 +-
 sound/pci/cs46xx/dsp_spos_scb_lib.c           |    2 +-
 sound/pci/emu10k1/emu10k1.c                   |   19 +-
 sound/pci/emu10k1/emu10k1_callback.c          |   16 +-
 sound/pci/emu10k1/emu10k1_main.c              |   57 +-
 sound/pci/emu10k1/emu10k1_patch.c             |    4 +-
 sound/pci/emu10k1/emu10k1_synth.c             |    4 +-
 sound/pci/emu10k1/emufx.c                     |  374 +-
 sound/pci/emu10k1/emumixer.c                  |   21 +-
 sound/pci/emu10k1/emupcm.c                    |  321 +-
 sound/pci/emu10k1/emuproc.c                   |  126 +-
 sound/pci/emu10k1/io.c                        |    4 +-
 sound/pci/emu10k1/irq.c                       |    2 +-
 sound/pci/emu10k1/memory.c                    |   14 +-
 sound/pci/ens1370.c                           |  140 +-
 sound/pci/es1938.c                            |  224 +-
 sound/pci/es1968.c                            |  208 +-
 sound/pci/fm801.c                             |   79 +-
 sound/pci/ice1712/Makefile                    |    2 +-
 sound/pci/ice1712/ak4xxx.c                    |    1 -
 sound/pci/ice1712/aureon.c                    |  307 +-
 sound/pci/ice1712/delta.c                     |    4 +-
 sound/pci/ice1712/ews.c                       |   26 +-
 sound/pci/ice1712/ews.h                       |    4 +-
 sound/pci/ice1712/ice1712.c                   |  125 +-
 sound/pci/ice1712/ice1712.h                   |    6 -
 sound/pci/ice1712/ice1724.c                   |  381 +-
 sound/pci/ice1712/revo.c                      |    4 +-
 sound/pci/intel8x0.c                          |  330 +-
 sound/pci/intel8x0m.c                         |  187 +-
 sound/pci/korg1212/korg1212.c                 |  202 +-
 sound/pci/maestro3.c                          |   97 +-
 sound/pci/mixart/mixart.c                     |  126 +-
 sound/pci/mixart/mixart.h                     |    1 -
 sound/pci/mixart/mixart_core.c                |    4 +-
 sound/pci/mixart/mixart_hwdep.c               |    4 +-
 sound/pci/mixart/mixart_mixer.c               |    2 -
 sound/pci/nm256/nm256.c                       |   97 +-
 sound/pci/rme32.c                             |  844 +--
 sound/pci/rme96.c                             |  375 +-
 sound/pci/rme9652/hdsp.c                      |  481 +-
 sound/pci/rme9652/rme9652.c                   |  311 +-
 sound/pci/sonicvibes.c                        |  130 +-
 sound/pci/trident/trident.c                   |    8 +-
 sound/pci/trident/trident_main.c              |  165 +-
 sound/pci/trident/trident_memory.c            |   14 +-
 sound/pci/trident/trident_synth.c             |   33 +-
 sound/pci/via82xx.c                           |  206 +-
 sound/pci/vx222/vx222.c                       |   42 +-
 sound/pci/vx222/vx222.h                       |    2 +-
 sound/pci/vx222/vx222_ops.c                   |    2 -
 sound/pci/ymfpci/ymfpci.c                     |   10 +-
 sound/pci/ymfpci/ymfpci_main.c                |  186 +-
 sound/pcmcia/pdaudiocf/pdaudiocf.c            |   16 +-
 sound/pcmcia/pdaudiocf/pdaudiocf_core.c       |   12 +-
 sound/pcmcia/pdaudiocf/pdaudiocf_irq.c        |    4 +-
 sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c        |    4 +-
 sound/pcmcia/vx/vx_entry.c                    |   10 +-
 sound/pcmcia/vx/vxp_mixer.c                   |    2 -
 sound/pcmcia/vx/vxp_ops.c                     |    2 -
 sound/pcmcia/vx/vxpocket.c                    |    7 +-
 sound/ppc/Kconfig                             |    5 +-
 sound/ppc/Makefile                            |    2 +-
 sound/ppc/awacs.c                             |   35 +-
 sound/ppc/burgundy.c                          |    6 +-
 sound/ppc/daca.c                              |    6 +-
 sound/ppc/pmac.c                              |   93 +-
 sound/ppc/pmac.h                              |   14 +-
 sound/ppc/powermac.c                          |   24 +-
 sound/ppc/tumbler.c                           |   71 +-
 sound/sparc/amd7930.c                         |   24 +-
 sound/sparc/cs4231.c                          |   49 +-
 sound/synth/emux/emux.c                       |    6 +-
 sound/synth/emux/emux_effect.c                |    2 +-
 sound/synth/emux/emux_hwdep.c                 |    2 +-
 sound/synth/emux/emux_nrpn.c                  |   18 +-
 sound/synth/emux/emux_oss.c                   |   14 +-
 sound/synth/emux/emux_proc.c                  |    2 +-
 sound/synth/emux/emux_seq.c                   |   20 +-
 sound/synth/emux/emux_synth.c                 |   12 +-
 sound/synth/emux/soundfont.c                  |   60 +-
 sound/synth/util_mem.c                        |    2 +-
 sound/usb/Kconfig                             |   10 +
 sound/usb/Makefile                            |    8 +-
 sound/usb/usbaudio.c                          |  108 +-
 sound/usb/usbaudio.h                          |    7 +-
 sound/usb/usbmidi.c                           |   86 +-
 sound/usb/usbmixer.c                          |   62 +-
 sound/usb/usbmixer_maps.c                     |    2 +-
 sound/usb/usbquirks.h                         |   89 +-
 usr/Makefile                                  |    2 +-
 4078 files changed, 121652 insertions(+), 102286 deletions(-)

diff --git a/CREDITS b/CREDITS
index cc0cffd96..22252bdf5 100644
--- a/CREDITS
+++ b/CREDITS
@@ -281,6 +281,11 @@ S: Code 930.5, Goddard Space Flight Center
 S: Greenbelt, Maryland 20771
 S: USA
 
+N: Adam Belay
+E: ambx1@neo.rr.com
+D: Linux Plug and Play Support
+S: USA
+
 N: Daniele Bellucci
 E: bellucda@tiscali.it
 D: Various Janitor work.
@@ -513,6 +518,14 @@ S: 25-29 St Giles
 S: Oxford
 S: United Kingdom
 
+N: Luiz Fernando N. Capitulino
+E: lcapitulino@terra.com.br
+E: lcapitulino@prefeitura.sp.gov.br
+W: http://www.telecentros.sp.gov.br
+D: Little fixes and a lot of janitorial work
+S: E-GOV Telecentros SP
+S: Brazil
+
 N: Remy Card
 E: Remy.Card@masi.ibp.fr
 E: Remy.Card@linux.org
@@ -625,6 +638,14 @@ E: nconway.list@ukaea.org.uk
 D: Assorted sched/mm titbits
 S: Oxfordshire, UK.
 
+N: Kees Cook
+E: kees@outflux.net
+W: http://outflux.net/
+P: 1024D/17063E6D 9FA3 C49C 23C9 D1BC 2E30  1975 1FFF 4BA9 1706 3E6D
+D: Minor updates to SCSI code for the Communications type
+S: (ask for current address)
+S: USA
+
 N: Mark Corner
 E: mcorner@umich.edu
 W: http://www.eecs.umich.edu/~mcorner/
@@ -639,14 +660,6 @@ D: Kernel module SMART utilities
 S: Santa Cruz, California
 S: USA
 
-N: Kees Cook
-E: kees@outflux.net
-W: http://outflux.net/
-P: 1024D/17063E6D 9FA3 C49C 23C9 D1BC 2E30  1975 1FFF 4BA9 1706 3E6D
-D: Minor updates to SCSI code for the Communications type
-S: (ask for current address)
-S: USA
-
 N: Alan Cox
 W: http://www.linux.org.uk/diary/
 D: Linux Networking (0.99.10->2.0.29)
@@ -735,6 +748,12 @@ S: Schimmelsrain 1
 S: D-69231 Rauenberg
 S: Germany
 
+N: Jean Delvare
+E: khali@linux-fr.org
+W: http://khali.linux-fr.org/
+D: Several hardware monitoring drivers
+S: France
+
 N: Peter Denison
 E: peterd@pnd-pc.demon.co.uk
 W: http://www.pnd-pc.demon.co.uk/promise/
@@ -754,7 +773,7 @@ W: http://luxik.cdi.cz/~devik/qos/
 D: HTB qdisc and random networking hacks
 
 N: Alex deVries
-E: adevries@thepuffingroup.com
+E: alex@onefishtwo.ca
 D: Various SGI parts, bits of HAL2 and Newport, PA-RISC Linux.
 S: 41.5 William Street
 S: Ottawa, Ontario
@@ -905,6 +924,10 @@ S: Brevia 1043
 S: S-114 79 Stockholm
 S: Sweden
 
+N: David Engebretsen
+E: engebret@us.ibm.com
+D: Linux port to 64-bit PowerPC architecture
+
 N: Michael Engel
 E: engel@unix-ag.org
 D: DECstation framebuffer drivers
@@ -1049,6 +1072,12 @@ S: R. Tocantins, 89 - Cristo Rei
 S: 80050-430 - Curitiba - Paraná
 S: Brazil
 
+N: Kumar Gala
+E: kumar.gala@freescale.com
+D: Embedded PowerPC 6xx/7xx/74xx/82xx/85xx support
+S: Austin, Texas 78729
+S: USA
+
 N: Nigel Gamble
 E: nigel@nrg.org
 D: Interrupt-driven printer driver
@@ -1060,12 +1089,6 @@ S: USA
 N: Jeff Garzik
 E: jgarzik@pobox.com
 
-N: Kumar Gala
-E: kumar.gala@freescale.com
-D: Embedded PowerPC 6xx/7xx/74xx/82xx/85xx support
-S: Austin, Texas 78729
-S: USA
-
 N: Jacques Gelinas
 E: jacques@solucorp.qc.ca
 D: Author of the Umsdos file system
@@ -1563,10 +1586,37 @@ D: Backport/Forwardport merge monkey.
 D: Various Janitor work.
 S: United Kingdom
 
+N: Martin Josfsson
+E: gandalf@wlug.westbo.se
+P: 1024D/F6B6D3B1 7610 7CED 5C34 4AA6 DBA2  8BE1 5A6D AF95 F6B6 D3B1
+D: netfilter: SAME target
+D: netfilter: helper target
+D: netfilter: various other hacks
+S: Ronneby
+S: Sweden
+
 N: Ani Joshi
 E: ajoshi@shell.unixbox.com
 D: fbdev hacking
 
+N: Jesper Juhl
+E: juhl-lkml@dif.dk
+D: Various small janitor fixes, cleanups etc.
+S: Lemnosvej 1, 3.tv
+S: 2300 Copenhagen S
+S: Denmark
+
+N: Jozsef Kadlecsik
+E: kadlec@blackhole.kfki.hu
+P: 1024D/470DB964 4CB3 1A05 713E 9BF7 FAC5  5809 DD8C B7B1 470D B964
+D: netfilter: TCP window tracking code
+D: netfilter: raw table
+D: netfilter: iprange match
+D: netfilter: new logging interfaces
+D: netfilter: various other hacks
+S: Tata
+S: Hungary
+
 N: Bernhard Kaindl
 E: bkaindl@netway.at
 E: edv@bartelt.via.at
@@ -1818,11 +1868,6 @@ S: Sindlovy Dvory 117
 S: 370 01  Ceske Budejovice
 S: Czech Republic
 
-N: Adam Belay
-E: ambx1@neo.rr.com
-D: Linux Plug and Play Support
-S: USA
-
 N: Bas Laarhoven
 E: sjml@xs4all.nl
 D: Loadable modules and ftape driver
@@ -1954,12 +1999,6 @@ S: 8786 Niwot Road
 S: Niwot, Colorado 80503
 S: USA
 
-N: Pete Popov
-E: pete_popov@yahoo.com
-D: Linux/MIPS AMD/Alchemy Port and mips hacking and debugging
-S: San Jose, CA 95134
-S: USA
-
 N: Robert M. Love
 E: rml@tech9.net
 E: rml@novell.com
@@ -2127,6 +2166,16 @@ D: OV511 driver
 S: (address available on request)
 S: USA
 
+N: Patrick McHardy
+E: kaber@trash.net
+P: 1024D/12155E80 B128 7DE6 FF0A C2B2 48BE  AB4C C9D4 964E 1215 5E80
+D: netfilter: endless number of bugfixes
+D: netfilter: CLASSIFY target
+D: netfilter: addrtype match
+D: tc: HFSC scheduler
+S: Freiburg
+S: Germany
+
 N: Mike McLagan
 E: mike.mclagan@linux.org
 W: http://www.invlogic.com/~mmclagan
@@ -2214,14 +2263,13 @@ S: 7546 JA  Enschede
 S: Netherlands
 
 N: David S. Miller
-E: davem@redhat.com
+E: davem@davemloft.net
 D: Sparc and blue box hacker
 D: Vger Linux mailing list co-maintainer
 D: Linux Emacs elf/qmagic support + other libc/gcc things
 D: Yee bore de yee bore! ;-)
-S: 750 N. Shoreline Blvd.
-S: Apt. #111
-S: Mountain View, California 94043
+S: 575 Harrison St. #103
+S: San Francisco, CA 94105
 S: USA
 
 N: Rick Miller
@@ -2570,6 +2618,7 @@ N: Nicolas Pitre
 E: nico@cam.org
 D: StrongARM SA1100 support integrator & hacker
 D: Xscale PXA architecture
+D: unified SMC 91C9x/91C11x ethernet driver (smc91x)
 S: Montreal, Quebec, Canada
 
 N: Ken Pizzini
@@ -2582,6 +2631,12 @@ P: 1024D/EDBB6147 7B36 0E07 04BC 11DC A7A0  D3F7 7185 9E7A EDBB 6147
 D: sonypi, meye drivers, mct_u232 usb serial hacks
 S: Paris, France
 
+N: Pete Popov
+E: pete_popov@yahoo.com
+D: Linux/MIPS AMD/Alchemy Port and mips hacking and debugging
+S: San Jose, CA 95134
+S: USA
+
 N: Matt Porter
 E: mporter@kernel.crashing.org
 D: Motorola PowerPC PReP support
@@ -2797,7 +2852,7 @@ S: Germany
 
 N: Paul `Rusty' Russell
 E: rusty@rustcorp.com.au
-W: http://www.samba.org/netfilter
+W: http://ozlabs.org/~rusty
 D: Ruggedly handsome.
 D: netfilter, ipchains with Michael Neuling.
 S: 52 Moore St
@@ -2821,7 +2876,6 @@ S: I/3 Walter St
 S: Wellington
 S: New Zealand
 
-
 N: Sampo Saaristo
 E: sambo@cs.tut.fi
 D: Co-author of Multi-Protocol Over ATM (MPOA)
@@ -2838,6 +2892,9 @@ S: Markusstrasse 18
 S: 8006 Zuerich
 S: Switzerland
 
+N: Manuel Estrada Sainz
+D: Firmware loader (request_firmware)
+
 N: Wayne Salamon
 E: wsalamon@tislabs.com
 E: wsalamon@nai.com
@@ -3289,14 +3346,6 @@ S: Chudenicka 8
 S: 10200 Prague 10, Hostivar
 S: Czech Republic
 
-N: James R. Van Zandt
-E: jrv@vanzandt.mv.com
-P: 1024/E298966D F0 37 4F FD E5 7E C5 E6  F1 A0 1E 22 6F 46 DA 0C
-D: Author and maintainer of the Double Talk speech synthesizer driver
-S: 27 Spencer Drive
-S: Nashua, New Hampshire 03062
-S: USA
-
 N: Heikki Vatiainen
 E: hessu@cs.tut.fi
 D: Co-author of Multi-Protocol Over ATM (MPOA), some LANE hacks
@@ -3387,6 +3436,18 @@ S: UC Berkeley
 S: Berkeley, CA 94720-1776
 S: USA
 
+N: Harald Welte
+E: laforge@netfilter.org
+P: 1024D/30F48BFF DBDE 6912 8831 9A53 879B  9190 5DA5 C655 30F4 8BFF
+W: http://gnumonks.org/users/laforge
+D: netfilter: new nat helper infrastructure
+D: netfilter: ULOG, ECN, DSCP target
+D: netfilter: TTL match
+D: netfilter: IPv6 mangle table
+D: netfilter: various other hacks
+S: Berlin
+S: Germany
+
 N: Bill Wendling
 E: wendling@ganymede.isdn.uiuc.edu
 W: http://www.ncsa.uiuc.edu/~wendling/
@@ -3578,6 +3639,14 @@ S: ARCO Tower 1-8-1 Shimomeguro Meguro-ku
 S: Tokyo 153
 S: Japan
 
+N: James R. Van Zandt
+E: jrv@vanzandt.mv.com
+P: 1024/E298966D F0 37 4F FD E5 7E C5 E6  F1 A0 1E 22 6F 46 DA 0C
+D: Author and maintainer of the Double Talk speech synthesizer driver
+S: 27 Spencer Drive
+S: Nashua, New Hampshire 03062
+S: USA
+
 N: Orest Zborowski
 E: orestz@eskimo.com
 D: XFree86 and kernel development
@@ -3619,13 +3688,6 @@ D: MD driver
 D: EISA/sysfs subsystem
 S: France
 
-N: Luiz Fernando N. Capitulino
-E: lcapitulino@terra.com.br
-E: lcapitulino@prefeitura.sp.gov.br
-W: http://www.telecentros.sp.gov.br
-D: Little fixes and a lot of janitorial work
-S: E-GOV Telecentros SP
-S: Brazil
 
 # Don't add your name here, unless you really _are_ after Marc
 # alphabetically. Leonard used to be very proud of being the 
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle
index 7b256c12a..f25b3953f 100644
--- a/Documentation/CodingStyle
+++ b/Documentation/CodingStyle
@@ -356,10 +356,10 @@ Generally, inline functions are preferable to macros resembling functions.
 
 Macros with multiple statements should be enclosed in a do - while block:
 
-#define macrofun(a,b,c) 			\
+#define macrofun(a, b, c) 			\
 	do {					\
 		if (a == 5)			\
-			do_this(b,c);		\
+			do_this(b, c);		\
 	} while (0)
 
 Things to avoid when using macros:
diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index 11caa2d64..8787c4d09 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -444,4 +444,83 @@ dma_alloc_noncoherent(), starting at virtual address vaddr and
 continuing on for size.  Again, you *must* observe the cache line
 boundaries when doing this.
 
+int
+dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+			    dma_addr_t device_addr, size_t size, int
+			    flags)
+
+
+Declare region of memory to be handed out by dma_alloc_coherent when
+it's asked for coherent memory for this device.
+
+bus_addr is the physical address to which the memory is currently
+assigned in the bus responding region (this will be used by the
+platform to perform the mapping)
+
+device_addr is the physical address the device needs to be programmed
+with actually to address this memory (this will be handed out as the
+dma_addr_t in dma_alloc_coherent())
+
+size is the size of the area (must be multiples of PAGE_SIZE).
+
+flags can be or'd together and are
+
+DMA_MEMORY_MAP - request that the memory returned from
+dma_alloc_coherent() be directly writeable.
+
+DMA_MEMORY_IO - request that the memory returned from
+dma_alloc_coherent() be addressable using read/write/memcpy_toio etc.
+
+One or both of these flags must be present
+
+DMA_MEMORY_INCLUDES_CHILDREN - make the declared memory be allocated by
+dma_alloc_coherent of any child devices of this one (for memory residing
+on a bridge).
+
+DMA_MEMORY_EXCLUSIVE - only allocate memory from the declared regions. 
+Do not allow dma_alloc_coherent() to fall back to system memory when
+it's out of memory in the declared region.
+
+The return value will be either DMA_MEMORY_MAP or DMA_MEMORY_IO and
+must correspond to a passed in flag (i.e. no returning DMA_MEMORY_IO
+if only DMA_MEMORY_MAP were passed in) for success or zero for
+failure.
+
+Note, for DMA_MEMORY_IO returns, all subsequent memory returned by
+dma_alloc_coherent() may no longer be accessed directly, but instead
+must be accessed using the correct bus functions.  If your driver
+isn't prepared to handle this contingency, it should not specify
+DMA_MEMORY_IO in the input flags.
+
+As a simplification for the platforms, only *one* such region of
+memory may be declared per device.
+
+For reasons of efficiency, most platforms choose to track the declared
+region only at the granularity of a page.  For smaller allocations,
+you should use the dma_pool() API.
+
+void
+dma_release_declared_memory(struct device *dev)
+
+Remove the memory region previously declared from the system.  This
+API performs *no* in-use checking for this region and will return
+unconditionally having removed all the required structures.  It is the
+drivers job to ensure that no parts of this memory region are
+currently in use.
+
+void *
+dma_mark_declared_memory_occupied(struct device *dev,
+				  dma_addr_t device_addr, size_t size)
+
+This is used to occupy specific regions of the declared space
+(dma_alloc_coherent() will hand out the first free region it finds).
+
+device_addr is the *device* address of the region requested
+
+size is the size (and should be a page sized multiple).
+
+The return value will be either a pointer to the processor virtual
+address of the memory, or an error (via PTR_ERR()) if any part of the
+region is occupied.
+
 
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index bf212c021..9a23eab00 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -185,9 +185,7 @@ clean-files := $(DOCBOOKS) \
 	$(patsubst %.sgml, %.9,    $(DOCBOOKS)) \
 	$(C-procfs-example)
 
-ifneq ($(wildcard $(patsubst %.html,%,$(HTML))),)
-clean-rule := rm -rf $(wildcard $(patsubst %.html,%,$(HTML)))
-endif
+clean-dirs := $(patsubst %.sgml,%,$(DOCBOOKS))
 
 #man put files in man subdir - traverse down
 subdir- := man/
diff --git a/Documentation/DocBook/gadget.tmpl b/Documentation/DocBook/gadget.tmpl
index f07e73a41..0c28a966c 100644
--- a/Documentation/DocBook/gadget.tmpl
+++ b/Documentation/DocBook/gadget.tmpl
@@ -2,8 +2,8 @@
 <book id="USB-Gadget-API">
   <bookinfo>
     <title>USB Gadget API for Linux</title>
-    <date>02 June 2003</date>
-    <edition>02 June 2003</edition>
+    <date>20 August 2004</date>
+    <edition>20 August 2004</edition>
   
     <legalnotice>
        <para>
@@ -34,7 +34,7 @@
        </para>
     </legalnotice>
     <copyright>
-      <year>2003</year>
+      <year>2003-2004</year>
       <holder>David Brownell</holder>
     </copyright>
 
@@ -73,9 +73,13 @@ a number of important problems, including: </para>
 	composite devices,
 	and alternate interface settings.
 	</para></listitem>
+    <listitem><para>USB "On-The-Go" (OTG) support, in conjunction
+	with updates to the Linux-USB host side.
+	</para></listitem>
     <listitem><para>Sharing data structures and API models with the
-	Linux-USB host side API.  This looks forward to USB "On-The-Go"
-	(OTG) and similar more-symmetric frameworks.
+	Linux-USB host side API.  This helps the OTG support, and
+	looks forward to more-symmetric frameworks (where the same
+	I/O model is used by both host and device side drivers).
 	</para></listitem>
     <listitem><para>Minimalist, so it's easier to support new device
 	controller hardware.  I/O processing doesn't imply large
@@ -153,6 +157,7 @@ with the lowest level (which directly handles hardware).
 	the SA-11x0 or PXA-25x UDC (found within many PDAs),
 	and a variety of other products.
 	</para>
+
 	</listitem></varlistentry>
 
     <varlistentry>
@@ -162,10 +167,14 @@ with the lowest level (which directly handles hardware).
 	<para>The lower boundary of this driver implements hardware-neutral
 	USB functions, using calls to the controller driver.
 	Because such hardware varies widely in capabilities and restrictions,
-	the gadget driver is normally configured at compile time
+	and is used in embedded environments where space is at a premium,
+	the gadget driver is often configured at compile time
 	to work with endpoints supported by one particular controller.
 	Gadget drivers may be portable to several different controllers,
 	using conditional compilation.
+	(Recent kernels substantially simplify the work involved in
+	supporting new hardware, by <emphasis>autoconfiguring</emphasis>
+	endpoints automatically for many bulk-oriented drivers.)
 	Gadget driver responsibilities include:
 	</para>
 	<itemizedlist>
@@ -178,8 +187,9 @@ with the lowest level (which directly handles hardware).
 		altsettings, including enabling and configuring endpoints
 		</para></listitem>
 	    <listitem><para>handling life cycle events, such as managing
-		bindings
-	        to hardware, and disconnection from the USB host.
+		bindings to hardware,
+		USB suspend/resume, remote wakeup,
+		and disconnection from the USB host.
 		</para></listitem>
 	    <listitem><para>managing IN and OUT transfers on all currently
 		enabled endpoints
@@ -244,15 +254,38 @@ with the lowest level (which directly handles hardware).
 
 </variablelist>
 
-<para>Over time, reusable utilities should evolve to help make some
-gadget driver tasks simpler.  An example of particular interest
+<para>OTG-capable systems will also need to include a standard Linux-USB
+host side stack,
+with <emphasis>usbcore</emphasis>,
+one or more <emphasis>Host Controller Drivers</emphasis> (HCDs),
+<emphasis>USB Device Drivers</emphasis> to support
+the OTG "Targeted Peripheral List",
+and so forth.
+There will also be an <emphasis>OTG Controller Driver</emphasis>,
+which is visible to gadget and device driver developers only indirectly.
+That helps the host and device side USB controllers implement the
+two new OTG protocols (HNP and SRP).
+Roles switch (host to peripheral, or vice versa) using HNP
+during USB suspend processing, and SRP can be viewed as a
+more battery-friendly kind of device wakeup protocol.
+</para>
+
+<para>Over time, reusable utilities are evolving to help make some
+gadget driver tasks simpler.
+For example, building configuration descriptors from vectors of
+descriptors for the configurations interfaces and endpoints is
+now automated, and many drivers now use autoconfiguration to
+choose hardware endpoints and initialize their descriptors.
+
+A potential example of particular interest
 is code implementing standard USB-IF protocols for
 HID, networking, storage, or audio classes.
 Some developers are interested in KDB or KGDB hooks, to let
 target hardware be remotely debugged.
 Most such USB protocol code doesn't need to be hardware-specific,
 any more than network protocols like X11, HTTP, or NFS are.
-Such interface drivers might be combined, to support composite devices.
+Such gadget-side interface drivers should eventually be combined,
+to implement composite devices.
 </para>
 
 </chapter>
@@ -284,7 +317,7 @@ data types and functions are described here.
 <para>However, docproc does not understand all the C constructs
 that are used, so some relevant information is likely omitted from
 what you are reading.  
-One example of such information is several per-request flags.
+One example of such information is endpoint autoconfiguration.
 You'll have to read the header file, and use example source
 code (such as that for "Gadget Zero"), to fully understand the API.
 </para>
@@ -292,7 +325,7 @@ code (such as that for "Gadget Zero"), to fully understand the API.
 <para>The part of the API implementing some basic
 driver capabilities is specific to the version of the
 Linux kernel that's in use.
-The 2.5 kernel includes a <emphasis>driver model</emphasis>
+The 2.6 kernel includes a <emphasis>driver model</emphasis>
 framework that has no analogue on earlier kernels;
 so those parts of the gadget API are not fully portable.
 (They are implemented on 2.4 kernels, but in a different way.)
@@ -308,17 +341,21 @@ There are significant hardware features, such as device-to-device DMA
 that would be added using hardware-specific APIs.
 </para>
 
-<para>This API expects drivers to use conditional compilation to handle
-endpoint capabilities of different hardware.
-Those tend to have arbitrary restrictions, relating to
+<para>This API allows drivers to use conditional compilation to handle
+endpoint capabilities of different hardware, but doesn't require that.
+Hardware tends to have arbitrary restrictions, relating to
 transfer types, addressing, packet sizes, buffering, and availability.
 As a rule, such differences only matter for "endpoint zero" logic
 that handles device configuration and management.
-The API only supports limited run-time
+The API supports limited run-time
 detection of capabilities, through naming conventions for endpoints.
-Although a gadget driver could scan the endpoints available to it and
-choose to map those capabilities onto driver functionality in some way,
-few drivers will want to reconfigure themselves at run-time.
+Many drivers will be able to at least partially autoconfigure
+themselves.
+In particular, driver init sections will often have endpoint
+autoconfiguration logic that scans the hardware's list of endpoints
+to find ones matching the driver requirements
+(relying on those conventions), to eliminate some of the most
+common reasons for conditional compilation.
 </para>
 
 <para>Like the Linux-USB host side API, this API exposes
@@ -355,10 +392,14 @@ and so on.
 At this point the device is logically in the USB ch9 initial state
 ("attached"), drawing no power and not usable
 (since it does not yet support enumeration).
+Any host should not see the device, since it's not
+activated the data line pullup used by the host to
+detect a device, even if VBUS power is available.
 </para></listitem>
 
 <listitem><para>Register a gadget driver that implements some higher level
-device function.  That will then bind() to a usb_gadget.
+device function.  That will then bind() to a usb_gadget, which
+activates the data line pullup sometime after detecting VBUS.
 </para></listitem>
 
 <listitem><para>The hardware driver can now start enumerating.
@@ -373,6 +414,8 @@ based both on what the bus interface hardware provides and on the
 functionality being implemented.
 That can involve alternate settings or configurations,
 unless the hardware prevents such operation.
+For OTG devices, each configuration descriptor includes
+an OTG descriptor.
 </para></listitem>
 
 <listitem><para>The gadget driver handles the last step of enumeration,
@@ -381,13 +424,18 @@ It enables all endpoints used in that configuration,
 with all interfaces in their default settings.
 That involves using a list of the hardware's endpoints, enabling each
 endpoint according to its descriptor.
+It may also involve using <function>usb_gadget_vbus_draw</function>
+to let more power be drawn from VBUS, as allowed by that configuration.
+For OTG devices, setting a configuration may also involve reporting
+HNP capabilities through a user interface.
 </para></listitem>
 
 <listitem><para>Do real work and perform data transfers, possibly involving
 changes to interface settings or switching to new configurations, until the
 device is disconnect()ed from the host.
 Queue any number of transfer requests to each endpoint.
-The drivers then go back to step 3 (above).
+It may be suspended and resumed several times before being disconnected.
+On disconnect, the drivers go back to step 3 (above).
 </para></listitem>
 
 <listitem><para>When the gadget driver module is being unloaded,
@@ -399,7 +447,9 @@ driver be unloaded.
 
 <para>Drivers will normally be arranged so that just loading the
 gadget driver module (or statically linking it into a Linux kernel)
-allows the peripheral device to be enumerated.
+allows the peripheral device to be enumerated, but some drivers
+will defer enumeration until some higher level component (like
+a user mode daemon) enables it.
 Note that at this lowest level there are no policies about how
 ep0 configuration logic is implemented,
 except that it should obey USB specifications.
@@ -410,6 +460,18 @@ or understanding that composite devices might happen to
 be built by integrating reusable components.
 </para>
 
+<para>Note that the lifecycle above can be slightly different
+for OTG devices.
+Other than providing an additional OTG descriptor in each
+configuration, only the HNP-related differences are particularly
+visible to driver code.
+They involve reporting requirements during the SET_CONFIGURATION
+request, and the option to invoke HNP during some suspend callbacks.
+Also, SRP changes the semantics of
+<function>usb_gadget_wakeup</function>
+slightly.
+</para>
+
 </sect1>
 
 <sect1 id="ch9"><title>USB 2.0 Chapter 9 Types and Constants</title>
@@ -418,9 +480,9 @@ be built by integrating reusable components.
 rely on common USB structures and constants
 defined in the
 <filename>&lt;linux/usb_ch9.h&gt;</filename>
-header file, which is standard in Linux 2.5 kernels.
+header file, which is standard in Linux 2.6 kernels.
 These are the same types and constants used by host
-side drivers.
+side drivers (and usbcore).
 </para>
 
 !Iinclude/linux/usb_ch9.h
@@ -451,26 +513,38 @@ USB peripheral controller drivers.
 
 <para>The core API is sufficient for writing a USB Gadget Driver,
 but some optional utilities are provided to simplify common tasks.
+These utilities include endpoint autoconfiguration.
 </para>
 
 !Edrivers/usb/gadget/usbstring.c
 !Edrivers/usb/gadget/config.c
+<!-- !Edrivers/usb/gadget/epautoconf.c -->
 </sect1>
 
 </chapter>
 
 <chapter id="controllers"><title>Peripheral Controller Drivers</title>
 
-<para>The first hardware supporting this API is the NetChip 2280
+<para>The first hardware supporting this API was the NetChip 2280
 controller, which supports USB 2.0 high speed and is based on PCI.
 This is the <filename>net2280</filename> driver module.
-The driver supports Linux kernel versions 2.4 and 2.5;
+The driver supports Linux kernel versions 2.4 and 2.6;
 contact NetChip Technologies for development boards and product
 information.
 </para> 
 
-<para>For users of Intel's PXA 2xx series processors,
-a <filename>pxa2xx_udc</filename> driver is available.
+<para>Other hardware working in the "gadget" framework includes:
+Intel's PXA 25x and IXP42x series processors
+(<filename>pxa2xx_udc</filename>),
+Toshiba TC86c001 "Goku-S" (<filename>goku_udc</filename>),
+Renesas SH7705/7727 (<filename>sh_udc</filename>),
+MediaQ 11xx (<filename>mq11xx_udc</filename>),
+Hynix HMS30C7202 (<filename>h7202_udc</filename>),
+National 9303/4 (<filename>n9604_udc</filename>),
+Texas Instruments OMAP (<filename>omap_udc</filename>),
+Sharp LH7A40x (<filename>lh7a40x_udc</filename>),
+and more.
+Most of those are full speed controllers.
 </para>
 
 <para>At this writing, there are people at work on drivers in
@@ -526,6 +600,15 @@ subset of CDC Ethernet.
 to avoid creating problems.)
 </para>
 
+<para>Support for Microsoft's <emphasis>RNDIS</emphasis>
+protocol has been contributed by Pengutronix and Auerswald GmbH.
+This is like CDC Ethernet, but it runs on more slightly USB hardware
+(but less than the CDC subset).
+However, its main claim to fame is being able to connect directly to
+recent versions of Windows, using drivers that Microsoft bundles
+and supports, making it much simpler to network with Windows.
+</para>
+
 <para>There is also support for user mode gadget drivers,
 using <emphasis>gadgetfs</emphasis>.
 This provides a <emphasis>User Mode API</emphasis> that presents
@@ -535,6 +618,10 @@ Familiar tools like GDB and pthreads can be used to
 develop and debug user mode drivers, so that once a robust
 controller driver is available many applications for it
 won't require new kernel mode software.
+Linux 2.6 <emphasis>Async I/O (AIO)</emphasis>
+support is available, so that user mode software
+can stream data with only slightly more overhead
+than a kernel driver.
 </para>
 
 <para>There's a USB Mass Storage class driver, which provides
@@ -548,6 +635,16 @@ storage class specification, using transparent SCSI commands
 to access the data from the backing store.
 </para>
 
+<para>There's a "serial line" driver, useful for TTY style
+operation over USB.
+The latest version of that driver supports CDC ACM style
+operation, like a USB modem, and so on most hardware it can
+interoperate easily with MS-Windows.
+One interesting use of that driver is in boot firmware (like a BIOS),
+which can sometimes use that model with very small systems without
+real serial lines.
+</para>
+
 <para>Support for other kinds of gadget is expected to
 be developed and contributed
 over time, as this driver framework evolves.
@@ -555,6 +652,96 @@ over time, as this driver framework evolves.
 
 </chapter>
 
+<chapter id="otg"><title>USB On-The-GO (OTG)</title>
+
+<para>USB OTG support on Linux 2.6 was initially developed
+by Texas Instruments for
+<ulink url="http://www.omap.com">OMAP</ulink> 16xx and 17xx
+series processors.
+Other OTG systems should work in similar ways, but the
+hardware level details could be very different.
+</para> 
+
+<para>Systems need specialized hardware support to implement OTG,
+notably including a special <emphasis>Mini-AB</emphasis> jack
+and associated transciever to support <emphasis>Dual-Role</emphasis>
+operation:
+they can act either as a host, using the standard
+Linux-USB host side driver stack,
+or as a peripheral, using this "gadget" framework.
+To do that, the system software relies on small additions
+to those programming interfaces,
+and on a new internal component (here called an "OTG Controller")
+affecting which driver stack connects to the OTG port.
+In each role, the system can re-use the existing pool of
+hardware-neutral drivers, layered on top of the controller
+driver interfaces (<emphasis>usb_bus</emphasis> or
+<emphasis>usb_gadget</emphasis>).
+Such drivers need at most minor changes, and most of the calls
+added to support OTG can also benefit non-OTG products.
+</para>
+
+<itemizedlist>
+    <listitem><para>Gadget drivers test the <emphasis>is_otg</emphasis>
+	flag, and use it to determine whether or not to include
+	an OTG descriptor in each of their configurations.
+	</para></listitem>
+    <listitem><para>Gadget drivers may need changes to support the
+	two new OTG protocols, exposed in new gadget attributes
+	such as <emphasis>b_hnp_enable</emphasis> flag.
+	HNP support should be reported through a user interface
+	(two LEDs could suffice), and is triggered in some cases
+	when the host suspends the peripheral.
+	SRP support can be user-initiated just like remote wakeup,
+	probably by pressing the same button.
+	</para></listitem>
+    <listitem><para>On the host side, USB device drivers need
+	to be taught to trigger HNP at appropriate moments, using
+	<function>usb_suspend_device()</function>.
+	That also conserves battery power, which is useful even
+	for non-OTG configurations.
+	</para></listitem>
+    <listitem><para>Also on the host side, a driver must support the
+	OTG "Targeted Peripheral List".  That's just a whitelist,
+	used to reject peripherals not supported with a given
+	Linux OTG host.
+	<emphasis>This whitelist is product-specific;
+	each product must modify <filename>otg_whitelist.h</filename>
+	to match its interoperability specification.
+	</emphasis>
+	</para>
+	<para>Non-OTG Linux hosts, like PCs and workstations,
+	normally have some solution for adding drivers, so that
+	peripherals that aren't recognized can eventually be supported.
+	That approach is unreasonable for consumer products that may
+	never have their firmware upgraded, and where it's usually
+	unrealistic to expect traditional PC/workstation/server kinds
+	of support model to work.
+	For example, it's often impractical to change device firmware
+	once the product has been distributed, so driver bugs can't
+	normally be fixed if they're found after shipment.
+	</para></listitem>
+</itemizedlist>
+
+<para>
+Additional changes are needed below those hardware-neutral
+<emphasis>usb_bus</emphasis> and <emphasis>usb_gadget</emphasis>
+driver interfaces; those aren't discussed here in any detail.
+Those affect the hardware-specific code for each USB Host or Peripheral
+controller, and how the HCD initializes (since OTG can be active only
+on a single port).
+They also involve what may be called an <emphasis>OTG Controller
+Driver</emphasis>, managing the OTG transceiver and the OTG state
+machine logic as well as much of the root hub behavior for the
+OTG port.
+The OTG controller driver needs to activate and deactivate USB
+controllers depending on the relevant device role.
+Some related changes were needed inside usbcore, so that it
+can identify OTG-capable devices and respond appropriately
+to HNP or SRP protocols.
+</para> 
+
+</chapter>
 
 </book>
 <!--
diff --git a/Documentation/DocBook/kernel-hacking.tmpl b/Documentation/DocBook/kernel-hacking.tmpl
index 0424c92f5..cd1bc1574 100644
--- a/Documentation/DocBook/kernel-hacking.tmpl
+++ b/Documentation/DocBook/kernel-hacking.tmpl
@@ -145,7 +145,7 @@
     In user context, the <varname>current</varname> pointer (indicating 
     the task we are currently executing) is valid, and
     <function>in_interrupt()</function>
-    (<filename>include/asm/hardirq.h</filename>) is <returnvalue>false
+    (<filename>include/linux/interrupt.h</filename>) is <returnvalue>false
     </returnvalue>.  
    </para>
 
@@ -241,7 +241,7 @@
    <para>
     You can tell you are in a softirq (or bottom half, or tasklet)
     using the <function>in_softirq()</function> macro 
-    (<filename class="headerfile">include/asm/hardirq.h</filename>).
+    (<filename class="headerfile">include/linux/interrupt.h</filename>).
    </para>
    <caution>
     <para>
diff --git a/Documentation/DocBook/mousedrivers.tmpl b/Documentation/DocBook/mousedrivers.tmpl
index 49a902fed..8491969e6 100644
--- a/Documentation/DocBook/mousedrivers.tmpl
+++ b/Documentation/DocBook/mousedrivers.tmpl
@@ -940,7 +940,6 @@ static int close_mouse(struct inode *inode, struct file *file)
         if(--mouse_users)
                 return 0;
         free_irq(OURMOUSE_IRQ, NULL);
-        MOD_DEC_USE_COUNT;
         return 0;
 }
   </programlisting>
diff --git a/Documentation/DocBook/usb.tmpl b/Documentation/DocBook/usb.tmpl
index 52e4fd691..0f0c3a33b 100644
--- a/Documentation/DocBook/usb.tmpl
+++ b/Documentation/DocBook/usb.tmpl
@@ -251,6 +251,7 @@
 !Edrivers/usb/core/message.c
 !Edrivers/usb/core/file.c
 !Edrivers/usb/core/usb.c
+!Edrivers/usb/core/hub.c
     </chapter>
 
     <chapter><title>Host Controller APIs</title>
diff --git a/Documentation/IPMI.txt b/Documentation/IPMI.txt
index 583eb0d58..d6dcb2769 100644
--- a/Documentation/IPMI.txt
+++ b/Documentation/IPMI.txt
@@ -340,6 +340,8 @@ You can change this at module load time (for a module) with:
   modprobe ipmi_si.o type=<type1>,<type2>....
        ports=<port1>,<port2>... addrs=<addr1>,<addr2>...
        irqs=<irq1>,<irq2>... trydefaults=[0|1]
+       regspacings=<sp1>,<sp2>,... regsizes=<size1>,<size2>,...
+       regshifts=<shift1>,<shift2>,...
 
 Each of these except si_trydefaults is a list, the first item for the
 first interface, second item for the second interface, etc.
@@ -361,12 +363,35 @@ si_trydefaults sets whether the standard IPMI interface at 0xca2 and
 any interfaces specified by ACPE are tried.  By default, the driver
 tries it, set this value to zero to turn this off.
 
+The next three parameters have to do with register layout.  The
+registers used by the interfaces may not appear at successive
+locations and they may not be in 8-bit registers.  These parameters
+allow the layout of the data in the registers to be more precisely
+specified.
+
+The regspacings parameter give the number of bytes between successive
+register start addresses.  For instance, if the regspacing is set to 4
+and the start address is 0xca2, then the address for the second
+register would be 0xca6.  This defaults to 1.
+
+The regsizes parameter gives the size of a register, in bytes.  The
+data used by IPMI is 8-bits wide, but it may be inside a larger
+register.  This parameter allows the read and write type to specified.
+It may be 1, 2, 4, or 8.  The default is 1.
+
+Since the register size may be larger than 32 bits, the IPMI data may not
+be in the lower 8 bits.  The regshifts parameter give the amount to shift
+the data to get to the actual IPMI data.
+
 When compiled into the kernel, the addresses can be specified on the
 kernel command line as:
 
   ipmi_si.type=<type1>,<type2>...
        ipmi_si.ports=<port1>,<port2>... ipmi_si.addrs=<addr1>,<addr2>...
        ipmi_si.irqs=<irq1>,<irq2>... ipmi_si.trydefaults=[0|1]
+       ipmi_si.regspacings=<sp1>,<sp2>,...
+       ipmi_si.regsizes=<size1>,<size2>,...
+       ipmi_si.regshifts=<shift1>,<shift2>,...
 
 It works the same as the module parameters of the same names.
 
@@ -496,3 +521,8 @@ start a 120 timer if it is running to make sure the reboot occurs.
 Note that if you use the NMI preaction for the watchdog, you MUST
 NOT use nmi watchdog mode 1.  If you use the NMI watchdog, you
 must use mode 2.
+
+Once you open the watchdog timer, you must write a 'V' character to the
+device to close it, or the timer will not stop.  This is a new semantic
+for the driver, but makes it consistent with the rest of the watchdog
+drivers in Linux.
diff --git a/Documentation/cachetlb.txt b/Documentation/cachetlb.txt
index 26bb2b405..9e2f988a8 100644
--- a/Documentation/cachetlb.txt
+++ b/Documentation/cachetlb.txt
@@ -354,10 +354,6 @@ maps this page at its virtual address.
 	of arbitrary user pages (f.e. for ptrace()) it will use
 	these two routines.
 
-	The page has been kmap()'d, and flush_cache_page() has
-	just been called for the user mapping of this page (if
-	necessary).
-
 	Any necessary cache flushing or other coherency operations
 	that need to occur should happen here.  If the processor's
 	instruction cache does not snoop cpu stores, it is very
diff --git a/Documentation/cdrom/cdrom-standard.tex b/Documentation/cdrom/cdrom-standard.tex
index 0a51967fe..92f94e597 100644
--- a/Documentation/cdrom/cdrom-standard.tex
+++ b/Documentation/cdrom/cdrom-standard.tex
@@ -360,13 +360,11 @@ up the disc, etc. % and device-use count
 
 \subsection{$Void\ release(struct\ cdrom_device_info * cdi)$}
 
-In case of module support, a single call $MOD_DEC_USE_COUNT$ should be
-coded here.  Possibly other device-specific actions should be taken
-such as spinning down the device. However, strategic actions such as
-ejection of the tray, or unlocking the door, should be left over to
-the general routine $cdrom_release()$. Also, the invalidation of the
-allocated buffers in the VFS is taken care of by the routine in
-\cdromc.  This is the only function returning type $void$. 
+
+Device-specific actions should be taken such as spinning down the device.
+However, strategic actions such as ejection of the tray, or unlocking
+the door, should be left over to the general routine $cdrom_release()$.
+This is the only function returning type $void$.
 
 \subsection{$Int\ drive_status(struct\ cdrom_device_info * cdi, int\ slot_nr)$}
 \label{drive status}
diff --git a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt
index 1df474c4e..62778c57f 100644
--- a/Documentation/crypto/api-intro.txt
+++ b/Documentation/crypto/api-intro.txt
@@ -227,6 +227,10 @@ TEA/XTEA algorithm contributors:
 Khazad algorithm contributors:
   Aaron Grothe
 
+Whirlpool algorithm contributors:
+  Aaron Grothe
+  Jean-Luc Cooke
+
 Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>
 
 Please send any credits updates or corrections to:
diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index 954e49636..c46f5961a 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -1,9 +1,9 @@
 
 		       LINUX ALLOCATED DEVICES
 
-	     Maintained by John Cagle <device@lanana.org>
+	     Maintained by Torben Mathiasen <device@lanana.org>
 
-		      Last revised: 15 March 2004
+		      Last revised: 04 August 2004
 
 This list is the Linux Device List, the official registry of allocated
 device numbers and /dev directory nodes for the Linux operating
@@ -410,6 +410,7 @@ Your cooperation is appreciated.
 		199 = /dev/scanners/cuecat :CueCat barcode scanner
 		200 = /dev/net/tun	TAP/TUN network device
 		201 = /dev/button/gulpb	Transmeta GULP-B buttons
+		202 = /dev/emd/ctl	Enhanced Metadisk RAID (EMD) control
 		204 = /dev/video/em8300		EM8300 DVD decoder control
 		205 = /dev/video/em8300_mv	EM8300 DVD decoder video
 		206 = /dev/video/em8300_ma	EM8300 DVD decoder audio
@@ -1682,11 +1683,16 @@ Your cooperation is appreciated.
 		  1 = /dev/dcxx1	Second capture card
 		    ...
 
- 94 block	Inverse NAND Flash Translation Layer
-		  0 = /dev/inftla	First INFTL layer
-		 16 = /dev/inftlb	Second INFTL layer
+ 94 block IBM S/390 DASD block storage
+    		  0 = /dev/dasda First DASD device, major
+    		  1 = /dev/dasda1 First DASD device, block 1
+	    	  2 = /dev/dasda2 First DASD device, block 2
+    		  3 = /dev/dasda3 First DASD device, block 3
+    		  4 = /dev/dasdb Second DASD device, major
+    		  5 = /dev/dasdb1 Second DASD device, block 1
+    		  6 = /dev/dasdb2 Second DASD device, block 2
+    		  7 = /dev/dasdb3 Second DASD device, block 3
 		    ...
-		240 = /dev/inftlp	16th INTFL layer
 
  95 char	IP filter
 		  0 = /dev/ipl		Filter control device/log file
@@ -1695,15 +1701,9 @@ Your cooperation is appreciated.
 		  3 = /dev/ipauth	Authentication control device/log file
 		    ...		
 
- 95 block	IBM S/390 DASD block storage
-		  0 = /dev/dasd0	First DASD device, major
-		  1 = /dev/dasd0a	First DASD device, block 1
-		  2 = /dev/dasd0b	First DASD device, block 2
-		  3 = /dev/dasd0c	First DASD device, block 3
-		  4 = /dev/dasd1	Second DASD device, major
-		  5 = /dev/dasd1a	Second DASD device, block 1
-		  6 = /dev/dasd1b	Second DASD device, block 2
-		  7 = /dev/dasd1c	Second DASD device, block 3
+ 95 block	IBM S/390 VM/ESA minidisk
+		  0 = /dev/msd0		First VM/ESA minidisk
+		  1 = /dev/msd1		Second VM/ESA minidisk
 		    ...
 
  96 char	Parallel port ATAPI tape devices
@@ -1714,10 +1714,11 @@ Your cooperation is appreciated.
 		129 = /dev/npt1		Second p.p. ATAPI tape, no rewind
 		    ...
 
- 96 block	IBM S/390 VM/ESA minidisk
-		  0 = /dev/msd0		First VM/ESA minidisk
-		  1 = /dev/msd1		Second VM/ESA minidisk
+ 96 block Inverse NAND Flash Translation Layer
+		  0 = /dev/inftla First INFTL layer
+		 16 = /dev/inftlb Second INFTL layer
 		    ...
+		240 = /dev/inftlp	16th INTFL layer
 
  97 char	Parallel port generic ATAPI interface
 		  0 = /dev/pg0		First parallel port ATAPI device
@@ -1796,14 +1797,15 @@ Your cooperation is appreciated.
 		partitions is 15.
 
 103 char	Arla network file system
-		  0 = /dev/xfs0		Arla XFS
+		  0 = /dev/nnpfs0	First NNPFS device
+		  1 = /dev/nnpfs1	Second NNPFS device
 
 		Arla is a free clone of the Andrew File System, AFS.
-		Any resemblance with the Swedish milk producer is
-		coincidental.  For more information about the project,
-		write to <arla-drinkers@stacken.kth.se> or subscribe
-		to the arla announce mailing list by sending a mail to
-		<arla-announce-request@stacken.kth.se>.
+		The NNPFS device gives user mode filesystem
+		implementations a kernel presence for caching and easy
+		mounting.  For more information about the project,
+		write to <arla-drinkers@stacken.kth.se> or see
+		http://www.stacken.kth.se/project/arla/
 
 103 block	Audit device
 		  0 = /dev/audit	Audit device
@@ -2060,12 +2062,10 @@ Your cooperation is appreciated.
                 device names.  For example, /dev/hda5 would become
                 /dev/evms/hda5.
 
-118 char	Solidum ???
-		  0 = /dev/solnp0
-		  1 = /dev/solnp1
-		    ...
-		128 = /dev/solnpctl0
-		129 = /dev/solnpctl1
+118 char	IBM Cryptographic Accelerator
+		  0 = /dev/ica	Virtual interface to all IBM Crypto Accelerators
+		  1 = /dev/ica0	IBMCA Device 0
+		  2 = /dev/ica1	IBMCA Device 1
 		    ...
 
 119 char	VMware virtual network control
@@ -2310,6 +2310,11 @@ Your cooperation is appreciated.
 		  1 = /dev/aureal1	Second Aureal Vortex
 		    ...
 
+147 block	Distributed Replicated Block Device (DRBD)
+		  0 = /dev/drbd0	First DRBD device
+		  1 = /dev/drbd1	Second DRBD device
+		    ...
+
 148 char	Technology Concepts serial card
 		  0 = /dev/ttyT0	First TCL port
 		  1 = /dev/ttyT1	Second TCL port
@@ -2346,6 +2351,22 @@ Your cooperation is appreciated.
 		    ...
 		 15 = /dev/spi15	Sixteenth SPI device on the bus
 
+153 block	Enhanced Metadisk RAID (EMD) storage units
+		  0 = /dev/emd/0	First unit
+		  1 = /dev/emd/0p1	Partition 1 on First unit
+		  2 = /dev/emd/0p2	Partition 2 on First unit
+		    ...
+		 15 = /dev/emd/0p15	Partition 15 on First unit
+
+		 16 = /dev/emd/1	Second unit
+		 32 = /dev/emd/2	Third unit
+		    ...
+		240 = /dev/emd/15	Sixteenth unit
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
 154 char	Specialix RIO serial card
 		  0 = /dev/ttySR0	First RIO port
 		    ...
@@ -2371,23 +2392,24 @@ Your cooperation is appreciated.
 		  1 = /dev/gfax1	GammaLink channel 1
 		    ...
 
-159		RESERVED
+159 char	RESERVED
+159 block	RESERVED
 
 160 char	General Purpose Instrument Bus (GPIB)
 		  0 = /dev/gpib0	First GPIB bus
 		  1 = /dev/gpib1	Second GPIB bus
 		    ...
 
-160 block       Promise SX8 8-port SATA Disks on First Controller
-		  0 = /dev/sx8/0     SATA disk 0 whole disk
-		  1 = /dev/sx8/0p1   SATA disk 0 partition 1
+160 block       Carmel 8-port SATA Disks on First Controller
+		  0 = /dev/carmel/0     SATA disk 0 whole disk
+		  1 = /dev/carmel/0p1   SATA disk 0 partition 1
 		    ...
-		 31 = /dev/sx8/0p31  SATA disk 0 partition 31
+		 31 = /dev/carmel/0p31  SATA disk 0 partition 31
 
-		 32 = /dev/sx8/1     SATA disk 1 whole disk
-		 64 = /dev/sx8/2     SATA disk 2 whole disk
+		 32 = /dev/carmel/1     SATA disk 1 whole disk
+		 64 = /dev/carmel/2     SATA disk 2 whole disk
 		    ...
-		224 = /dev/sx8/7     SATA disk 7 whole disk
+		224 = /dev/carmel/7     SATA disk 7 whole disk
 
 		Partitions are handled in the same way as for IDE
 		disks (see major number 3) except that the limit on
@@ -2401,16 +2423,16 @@ Your cooperation is appreciated.
 		 17 = /dev/irlpt1	Second IrLPT device
 		    ...
 
-161 block       Promise SX8 8-port SATA Disks on Second Controller
-		  0 = /dev/sx8/8     SATA disk 8 whole disk
-		  1 = /dev/sx8/8p1   SATA disk 8 partition 1
+161 block       Carmel 8-port SATA Disks on Second Controller
+		  0 = /dev/carmel/8     SATA disk 8 whole disk
+		  1 = /dev/carmel/8p1   SATA disk 8 partition 1
 		    ...
-		 31 = /dev/sx8/8p31  SATA disk 8 partition 31
+		 31 = /dev/carmel/8p31  SATA disk 8 partition 31
 
-		 32 = /dev/sx8/9     SATA disk 9 whole disk
-		 64 = /dev/sx8/10    SATA disk 10 whole disk
+		 32 = /dev/carmel/9     SATA disk 9 whole disk
+		 64 = /dev/carmel/10    SATA disk 10 whole disk
 		    ...
-		224 = /dev/sx8/15    SATA disk 15 whole disk
+		224 = /dev/carmel/15    SATA disk 15 whole disk
 
 		Partitions are handled in the same way as for IDE
 		disks (see major number 3) except that the limit on
@@ -2720,6 +2742,11 @@ Your cooperation is appreciated.
 		    ...
 		 39 = /dev/ttyDB7		DataBooster serial port 7
 		 40 = /dev/ttySG0		SGI Altix console port
+		 41 = /dev/ttySMX0		Motorola i.MX - port 0
+		 42 = /dev/ttySMX1		Motorola i.MX - port 1
+		 43 = /dev/ttySMX2		Motorola i.MX - port 2
+		 44 = /dev/ttyMM0		Marvell MPSC - port 0
+		 45 = /dev/ttyMM1		Marvell MPSC - port 1
 
 205 char	Low-density serial ports (alternate device)
 		  0 = /dev/culu0		Callout device for ttyLU0
@@ -2745,6 +2772,9 @@ Your cooperation is appreciated.
 		    ...
 		 39 = /dev/cudb7		Callout device for ttyDB7
 		 40 = /dev/cusg0		Callout device for ttySG0
+		 41 = /dev/ttySMX0		Callout device for ttySMX0
+		 42 = /dev/ttySMX1		Callout device for ttySMX1
+		 43 = /dev/ttySMX2		Callout device for ttySMX2
 
 206 char	OnStream SC-x0 tape devices
 		  0 = /dev/osst0		First OnStream SCSI tape, mode 0
diff --git a/Documentation/driver-model/bus.txt b/Documentation/driver-model/bus.txt
index 70685dde3..dd62c7b80 100644
--- a/Documentation/driver-model/bus.txt
+++ b/Documentation/driver-model/bus.txt
@@ -5,20 +5,21 @@ Definition
 ~~~~~~~~~~
 
 struct bus_type {
-        char                    * name;
-        rwlock_t                lock;
-        atomic_t                refcount;
+	char			* name;
 
-        struct list_head        node;
-        struct list_head        devices;
-        struct list_head        drivers;
+	struct subsystem	subsys;
+	struct kset		drivers;
+	struct kset		devices;
 
-        struct driver_dir_entry dir;
-        struct driver_dir_entry device_dir;
-        struct driver_dir_entry driver_dir;
+	struct bus_attribute	* bus_attrs;
+	struct device_attribute	* dev_attrs;
+	struct driver_attribute	* drv_attrs;
 
-        int     (*match)        (struct device * dev, struct device_driver * drv);
-	struct device (*add)	(struct device * parent, char * bus_id);
+	int		(*match)(struct device * dev, struct device_driver * drv);
+	int		(*hotplug) (struct device *dev, char **envp, 
+				    int num_envp, char *buffer, int buffer_size);
+	int		(*suspend)(struct device * dev, u32 state);
+	int		(*resume)(struct device * dev);
 };
 
 int bus_register(struct bus_type * bus);
@@ -47,7 +48,7 @@ Registration
 When a bus driver is initialized, it calls bus_register. This
 initializes the rest of the fields in the bus object and inserts it
 into a global list of bus types. Once the bus object is registered, 
-the fields in it (e.g. the rwlock_t) are usable by the bus driver. 
+the fields in it are usable by the bus driver. 
 
 
 Callbacks
@@ -71,40 +72,6 @@ When a driver is registered with the bus, the bus's list of devices is
 iterated over, and the match callback is called for each device that
 does not have a driver associated with it. 
 
-add(): Adding a child device
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The add callback is available to notify the bus about a child device
-at a particular location. 
-
-The parent parameter is the parent device of the child to be added. If
-parent == NULL, the bus should add the device as a child of a default
-parent device or as a child of the root. This policy decision is up to
-the bus driver.
-
-The format of the bus_id field should be consistent with the format of
-the bus_id field of the rest of the devices on the bus. This requires
-the caller to know the format.
-
-On return, the bus driver should return a pointer to the device that
-was created. If the device was not created, the bus driver should
-return an appropriate error code. Refer to include/linux/err.h for
-helper functions to encode errors. Some sample code:
-
-struct device * pci_bus_add(struct device * parent, char * bus_id)
-{
-	...
-	/* the device already exists */
-	return ERR_PTR(-EEXIST);
-	...
-}
-
-The caller can check the return value using IS_ERR():
-
-    struct device * newdev = pci_bus_type.add(parent,bus_id);
-    if (IS_ERR(newdev)) {
-	...
-    }
 
 
 Device and Driver Lists
@@ -118,10 +85,11 @@ necessary.
 
 The LDM core provides helper functions for iterating over each list.
 
-int bus_for_each_dev(struct bus_type * bus, void * data, 
-		     int (*callback)(struct device * dev, void * data));
-int bus_for_each_drv(struct bus_type * bus, void * data,
-		     int (*callback)(struct device_driver * drv, void * data));
+int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data,
+		     int (*fn)(struct device *, void *));
+
+int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, 
+		     void * data, int (*fn)(struct device_driver *, void *));
 
 These helpers iterate over the respective list, and call the callback
 for each device or driver in the list. All list accesses are
@@ -168,9 +136,9 @@ hierarchy:
 Exporting Attributes
 ~~~~~~~~~~~~~~~~~~~~
 struct bus_attribute {
-        struct attribute        attr;
-        ssize_t (*show)(struct bus_type *, char * buf, size_t count, loff_t off);
-        ssize_t (*store)(struct bus_type *, const char * buf, size_t count, loff_t off);
+	struct attribute	attr;
+	ssize_t (*show)(struct bus_type *, char * buf);
+	ssize_t (*store)(struct bus_type *, const char * buf, size_t count);
 };
 
 Bus drivers can export attributes using the BUS_ATTR macro that works
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 1c465edd2..f1c2cee13 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -90,7 +90,7 @@ prototypes:
 	void (*destroy_inode)(struct inode *);
 	void (*read_inode) (struct inode *);
 	void (*dirty_inode) (struct inode *);
-	void (*write_inode) (struct inode *, int);
+	int (*write_inode) (struct inode *, int);
 	void (*put_inode) (struct inode *);
 	void (*drop_inode) (struct inode *);
 	void (*delete_inode) (struct inode *);
@@ -276,21 +276,34 @@ foo_get_block(). It's an overkill, since block bitmaps can be protected by
 internal fs locking and real critical areas are much smaller than the areas
 filesystems protect now.
 
---------------------------- file_lock ------------------------------------
+----------------------- file_lock_operations ------------------------------
 prototypes:
-	void (*fl_notify)(struct file_lock *);	/* unblock callback */
 	void (*fl_insert)(struct file_lock *);	/* lock insertion callback */
 	void (*fl_remove)(struct file_lock *);	/* lock removal callback */
+	void (*fl_copy_lock)(struct file_lock *, struct file_lock *);
+	void (*fl_release_private)(struct file_lock *);
+
 
 locking rules:
-		BKL	may block
-fl_notify:	yes	no
-fl_insert:	yes	no
-fl_remove:	yes	no
+			BKL	may block
+fl_insert:		yes	no
+fl_remove:		yes	no
+fl_copy_lock:		yes	no
+fl_release_private:	yes	yes
+
+----------------------- lock_manager_operations ---------------------------
+prototypes:
+	int (*fl_compare_owner)(struct file_lock *, struct file_lock *);
+	void (*fl_notify)(struct file_lock *);  /* unblock callback */
+
+locking rules:
+			BKL	may block
+fl_compare_owner:	yes	no
+fl_notify:		yes	no
+
 	Currently only NLM provides instances of this class. None of the
 them block. If you have out-of-tree instances - please, show up. Locking
 in that area will change.
-
 --------------------------- buffer_head -----------------------------------
 prototypes:
 	void (*b_end_io)(struct buffer_head *bh, int uptodate);
diff --git a/Documentation/filesystems/ext2.txt b/Documentation/filesystems/ext2.txt
index 02968c532..23a4d98f9 100644
--- a/Documentation/filesystems/ext2.txt
+++ b/Documentation/filesystems/ext2.txt
@@ -17,6 +17,33 @@ Defaults are marked with (*).
 bsddf			(*)	Makes `df' act like BSD.
 minixdf				Makes `df' act like Minix.
 
+barrier=1			This enables/disables barriers. barrier=0 disables it,
+				barrier=1 enables it.
+
+orlov			(*)	This enables the new Orlov block allocator. It's
+				enabled by default.
+
+oldalloc			This disables the Orlov block allocator and
+				enables the old block allocator. Orlov should
+				have better performance, we'd like to get some
+				feedback  if it's the contrary for you.
+
+user_xattr		(*)	Enables POSIX Extended Attributes. It's enabled by
+				default, however you need to confifure its support
+				(CONFIG_EXT2_FS_XATTR). This is neccesary if you want
+				to use POSIX Acces Control Lists support. You can visit
+				http://acl.bestbits.at to know more about POSIX Extended
+				attributes.
+
+nouser_xattr			Disables POSIX Extended Attributes.
+
+acl			(*)	Enables POSIX Access Control Lists support. This is
+				enabled by default, however you need to configure
+				its support (CONFIG_EXT2_FS_POSIX_ACL). If you want
+				to know more about ACLs visit http://acl.bestbits.at
+
+noacl				This option disables POSIX Access Control List support.
+
 check=none, nocheck	(*)	Don't do extra checking of bitmaps on mount
 				(check=normal and check=strict options removed)
 
@@ -336,9 +363,8 @@ and are copied into the filesystem.  If a transaction is incomplete at
 the time of the crash, then there is no guarantee of consistency for
 the blocks in that transaction so they are discarded (which means any
 filesystem changes they represent are also lost).
-
-The ext3 code is currently (Apr 2001) available for 2.2 kernels only,
-and not yet available for 2.4 kernels.
+Check Documentation/filesystems/ext3.txt if you want to read more about
+ext3 and journaling.
 
 References
 ==========
@@ -349,8 +375,6 @@ Design & Implementation	http://e2fsprogs.sourceforge.net/ext2intro.html
 Journaling (ext3)	ftp://ftp.uk.linux.org/pub/linux/sct/fs/jfs/
 Hashed Directories	http://kernelnewbies.org/~phillips/htree/
 Filesystem Resizing	http://ext2resize.sourceforge.net/
-Extended Attributes &
-Access Control Lists	http://acl.bestbits.at/
 Compression (*)		http://www.netspace.net.au/~reiter/e2compr/
 
 Implementations for:
diff --git a/Documentation/filesystems/ext3.txt b/Documentation/filesystems/ext3.txt
index ff220afb1..9ab7f446f 100644
--- a/Documentation/filesystems/ext3.txt
+++ b/Documentation/filesystems/ext3.txt
@@ -22,6 +22,63 @@ journal=inum		When a journal already exists, this option is
 			the inode which will represent the ext3 file
 			system's journal file.
 
+noload			Don't load the journal on mounting.
+
+data=journal		All data are committed into the journal prior
+			to being written into the main file system.
+
+data=ordered	(*)	All data are forced directly out to the main file
+			system prior to its metadata being committed to
+			the journal.
+
+data=writeback		Data ordering is not preserved, data may be
+			written into the main file system after its
+			metadata has been committed to the journal.
+
+commit=nrsec	(*)	Ext3 can be told to sync all its data and metadata
+			every 'nrsec' seconds. The default value is 5 seconds.
+			This means that if you lose your power, you will lose,
+			as much, the latest 5 seconds of work (your filesystem
+			will not be damaged though, thanks to journaling). This
+			default value (or any low value) will hurt performance,
+			but it's good for data-safety. Setting it to 0 will
+			have the same effect than leaving the default 5 sec.
+			Setting it to very large values will improve
+			performance.
+
+barrier=1		This enables/disables barriers. barrier=0 disables it,
+			barrier=1 enables it.
+
+orlov		(*)	This enables the new Orlov block allocator. It's enabled
+			by default.
+
+oldalloc		This disables the Orlov block allocator and enables the
+			old block allocator. Orlov should have better performance,
+			we'd like to get some feedback if it's the contrary for
+			you.
+
+user_xattr	(*)	Enables POSIX Extended Attributes. It's enabled by
+			default, however you need to confifure its support
+			(CONFIG_EXT3_FS_XATTR). This is neccesary if you want
+			to use POSIX Acces Control Lists support. You can visit
+			http://acl.bestbits.at to know more about POSIX Extended
+			attributes.
+
+nouser_xattr		Disables POSIX Extended Attributes.
+
+acl		(*)	Enables POSIX Access Control Lists support. This is
+			enabled by default, however you need to configure
+			its support (CONFIG_EXT3_FS_POSIX_ACL). If you want
+			to know more about ACLs visit http://acl.bestbits.at
+
+noacl			This option disables POSIX Access Control List support.
+
+reservation
+
+noreservation
+
+resize=
+
 bsddf 		(*)	Make 'df' act like BSD.
 minixdf			Make 'df' act like Minix.
 
@@ -30,8 +87,6 @@ nocheck
 
 debug			Extra debugging information is sent to syslog.
 
-noload			Don't load the journal on mounting.
-
 errors=remount-ro(*)	Remount the filesystem read-only on an error.
 errors=continue		Keep going on a filesystem error.
 errors=panic		Panic and halt the machine if an error occurs.
@@ -48,17 +103,6 @@ resuid=n		The user ID which may use the reserved blocks.
 
 sb=n			Use alternate superblock at this location.
 
-data=journal		All data are committed into the journal prior 
-			to being written into the main file system.
-		
-data=ordered	(*)	All data are forced directly out to the main file 
-			system prior to its metadata being committed to 
-			the journal.
-		
-data=writeback  	Data ordering is not preserved, data may be 
-			written into the main file system after its
-			metadata has been committed to the journal.
-
 quota			Quota options are currently silently ignored.
 noquota			(see fs/ext3/super.c, line 594)
 grpquota
@@ -114,7 +158,7 @@ Compatibility
 -------------
 
 Ext2 partitions can be easily convert to ext3, with `tune2fs -j <dev>`.
- Ext3 is fully compatible with Ext2.  Ext3 partitions can easily be
+Ext3 is fully compatible with Ext2.  Ext3 partitions can easily be
 mounted as Ext2.
 
 External Tools
diff --git a/Documentation/filesystems/ntfs.txt b/Documentation/filesystems/ntfs.txt
index 200862dd6..7d600c0f4 100644
--- a/Documentation/filesystems/ntfs.txt
+++ b/Documentation/filesystems/ntfs.txt
@@ -30,7 +30,7 @@ fault-tolerance, encryption or journalling) and very limited, but safe, write
 support.
 
 For fault tolerance and raid support (i.e. volume and stripe sets), you can
-use the kernel's Software RAID / MD driver. See section "Using Software RAID
+use the kernel's Software RAID / MD driver.  See section "Using Software RAID
 with NTFS" for details.
 
 
@@ -64,14 +64,18 @@ Features
 	time find . -type f -exec md5sum "{}" \;
   run three times in sequence with each driver (after a reboot) on a 1.4GiB
   NTFS partition, showed the new driver to be 20% faster in total time elapsed
-  (from 9:43 minutes on average down to 7:53). The time spent in user space
+  (from 9:43 minutes on average down to 7:53).  The time spent in user space
   was unchanged but the time spent in the kernel was decreased by a factor of
   2.5 (from 85 CPU seconds down to 33).
-- The driver does not support short file names in general. For backwards
+- The driver does not support short file names in general.  For backwards
   compatibility, we implement access to files using their short file names if
-  they exist. The driver will not create short file names however, and a rename
-  will discard any existing short file name.
+  they exist.  The driver will not create short file names however, and a
+  rename will discard any existing short file name.
 - The new driver supports exporting of mounted NTFS volumes via NFS.
+- The new driver supports async io (aio).
+- The new driver supports fsync(2), fdatasync(2), and msync(2).
+- The new driver supports readv(2) and writev(2).
+- The new driver supports access time updates (including mtime and ctime).
 
 
 Supported mount options
@@ -273,6 +277,25 @@ ChangeLog
 
 Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
 
+2.1.20:
+	- Fix two stupid bugs introduced in 2.1.18 release.
+2.1.19:
+	- Minor bugfix in handling of the default upcase table.
+	- Many internal cleanups and improvements.  Many thanks to Linus
+	  Torvalds and Al Viro for the help and advice with the sparse
+	  annotations and cleanups.
+2.1.18:
+	- Fix scheduling latencies at mount time.  (Ingo Molnar)
+	- Fix endianness bug in a little traversed portion of the attribute
+	  lookup code.
+2.1.17:
+	- Fix bugs in mount time error code paths.
+2.1.16:
+	- Implement access time updates (including mtime and ctime).
+	- Implement fsync(2), fdatasync(2), and msync(2) system calls.
+	- Enable the readv(2) and writev(2) system calls.
+	- Enable access via the asynchronous io (aio) API by adding support for
+	  the aio_read(3) and aio_write(3) functions.
 2.1.15:
 	- Invalidate quotas when (re)mounting read-write.
 	  NOTE:  This now only leave user space journalling on the side.  (See
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 9d626596d..0dad0f2b0 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -55,7 +55,7 @@ This work is  based on the 2.2.*  kernel version and the  upcoming 2.4.*. I'm
 afraid it's still far from complete, but we  hope it will be useful. As far as
 we know, it is the first 'all-in-one' document about the /proc file system. It
 is focused  on the Intel  x86 hardware,  so if you  are looking for  PPC, ARM,
-SPARC, APX, etc., features, you probably  won't find what you are looking for.
+SPARC, AXP, etc., features, you probably  won't find what you are looking for.
 It also only covers IPv4 networking, not IPv6 nor other protocols - sorry. But
 additions and patches  are welcome and will  be added to this  document if you
 mail them to Bodo.
@@ -169,16 +169,18 @@ information. The  statm  file  contains  more  detailed  information about the
 process memory usage. Its seven fields are explained in Table 1-2.
 
 
-Table 1-2: Contents of the statm files 
+Table 1-2: Contents of the statm files (as of 2.6.8-rc3)
 ..............................................................................
- File     Content                         
- size     total program size              
- resident size of memory portions         
- shared   number of pages that are shared 
- trs      number of pages that are 'code' 
- drs      number of pages of data/stack   
- lrs      number of pages of library      
- dt       number of dirty pages           
+ Field    Content
+ size     total program size (pages)		(same as VmSize in status)
+ resident size of memory portions (pages)	(same as VmRSS in status)
+ shared   number of pages that are shared	(i.e. backed by a file)
+ trs      number of pages that are 'code'	(not including libs; broken,
+							includes data segment)
+ lrs      number of pages of library		(always 0 on 2.6)
+ drs      number of pages of data/stack		(including libs; broken,
+							includes library text)
+ dt       number of dirty pages			(always 0 on 2.6)
 ..............................................................................
 
 1.2 Kernel data
@@ -1109,6 +1111,23 @@ modprobe
 The location  where  the  modprobe  binary  is  located.  The kernel uses this
 program to load modules on demand.
 
+unknown_nmi_panic
+-----------------
+
+The value in this file affects behavior of handling NMI. When the value is
+non-zero, unknown NMI is trapped and then panic occurs. At that time, kernel
+debugging information is displayed on console.
+
+NMI switch that most IA32 servers have fires unknown NMI up, for example.
+If a system hangs up, try pressing the NMI switch.
+
+[NOTE]
+   This function and oprofile share a NMI callback. Therefore this function
+   cannot be enabled when oprofile is activated.
+   And NMI watchdog will be disabled when the value in this file is set to
+   non-zero.
+
+
 2.4 /proc/sys/vm - The virtual memory subsystem
 -----------------------------------------------
 
@@ -1157,6 +1176,12 @@ for writeout by the pdflush daemons.  It is expressed in 100'ths of a second.
 Data which has been dirty in-memory for longer than this interval will be
 written out next time a pdflush daemon wakes up.
 
+legacy_va_layout
+----------------
+
+If non-zero, this sysctl disables the new 32-bit mmap mmap layout - the kernel
+will use the legacy (2.4) layout for all processes.
+
 lower_zone_protection
 ---------------------
 
diff --git a/Documentation/filesystems/tmpfs.txt b/Documentation/filesystems/tmpfs.txt
index 177edbea9..417e3095f 100644
--- a/Documentation/filesystems/tmpfs.txt
+++ b/Documentation/filesystems/tmpfs.txt
@@ -62,13 +62,21 @@ size:      The limit of allocated bytes for this tmpfs instance. The
            since the OOM handler will not be able to free that memory.
 nr_blocks: The same as size, but in blocks of PAGE_CACHE_SIZE.
 nr_inodes: The maximum number of inodes for this instance. The default
-           is half of the number of your physical RAM pages.
+           is half of the number of your physical RAM pages, or (on a
+           a machine with highmem) the number of lowmem RAM pages,
+           whichever is the lower.
 
 These parameters accept a suffix k, m or g for kilo, mega and giga and
 can be changed on remount.  The size parameter also accepts a suffix %
 to limit this tmpfs instance to that percentage of your physical RAM:
 the default, when neither size nor nr_blocks is specified, is size=50%
 
+If both nr_blocks (or size) and nr_inodes are set to 0, neither blocks
+nor inodes will be limited in that instance.  It is generally unwise to
+mount with such options, since it allows any user with write access to
+use up all the memory on the machine; but enhances the scalability of
+that instance in a system with many cpus making intensive use of it.
+
 
 To specify the initial root directory you can use the following mount
 options:
@@ -89,4 +97,4 @@ RAM/SWAP in 10240 inodes and it is only accessible by root.
 Author:
    Christoph Rohland <cr@sap.com>, 1.12.01
 Updated:
-   Hugh Dickins <hugh@veritas.com>, 01 April 2003
+   Hugh Dickins <hugh@veritas.com>, 01 September 2004
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 9557ea184..5be10c915 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -176,7 +176,7 @@ filesystem. As of kernel 2.1.99, the following members are defined:
 
 struct super_operations {
 	void (*read_inode) (struct inode *);
-	void (*write_inode) (struct inode *, int);
+	int (*write_inode) (struct inode *, int);
 	void (*put_inode) (struct inode *);
 	void (*drop_inode) (struct inode *);
 	void (*delete_inode) (struct inode *);
diff --git a/Documentation/filesystems/xfs.txt b/Documentation/filesystems/xfs.txt
index 934254098..c7d5d0c70 100644
--- a/Documentation/filesystems/xfs.txt
+++ b/Documentation/filesystems/xfs.txt
@@ -120,12 +120,18 @@ The following sysctls are available for the XFS filesystem:
 
   fs.xfs.stats_clear		(Min: 0  Default: 0  Max: 1)
 	Setting this to "1" clears accumulated XFS statistics 
-	in /proc/fs/xfs/stat.  It then immediately reset to "0".
-  	
-  fs.xfs.sync_interval		(Min: HZ  Default: 30*HZ  Max: 60*HZ)
-	The interval at which the xfssyncd thread for xfs filesystems
-	flushes metadata out to disk. This thread will flush log
-	activity out, and do some processing on unlinked inodes
+	in /proc/fs/xfs/stat.  It then immediately resets to "0".
+  
+  fs.xfs.xfssyncd_centisecs	(Min: 100  Default: 3000  Max: 720000)
+  	The interval at which the xfssyncd thread flushes metadata
+  	out to disk.  This thread will flush log activity out, and
+  	do some processing on unlinked inodes.
+
+  fs.xfs.xfsbufd_centisecs	(Min: 50  Default: 100	Max: 3000)
+	The interval at which xfsbufd scans the dirty metadata buffers list.
+
+  fs.xfs.age_buffer_centisecs	(Min: 100  Default: 1500  Max: 720000)
+	The age at which xfsbufd flushes dirty metadata buffers to disk.
 
   fs.xfs.error_level		(Min: 0  Default: 3  Max: 11)
 	A volume knob for error reporting when internal errors occur.
@@ -180,14 +186,3 @@ The following sysctls are available for the XFS filesystem:
 	Setting this to "1" will cause the "noatime" flag set 
 	by the chattr(1) command on a directory to be
 	inherited by files in that directory.
-
-  vm.pagebuf.stats_clear	(Min: 0  Default: 0  Max: 1)
-	Setting this to "1" clears accumulated pagebuf statistics 
-	in /proc/fs/pagebuf/stat.  It then immediately reset to "0".
-  	
-  vm.pagebuf.flush_age		(Min: 1*HZ  Default: 15*HZ  Max: 300*HZ)
-	The age at which dirty metadata buffers are flushed to disk
-
-  vm.pagebuf.flush_int		(Min: HZ/2  Default: HZ  Max: 30*HZ)
-	The interval at which the list of dirty metadata buffers is
-	scanned.
diff --git a/Documentation/firmware_class/firmware_sample_firmware_class.c b/Documentation/firmware_class/firmware_sample_firmware_class.c
index 037c0bed9..09eab2f1b 100644
--- a/Documentation/firmware_class/firmware_sample_firmware_class.c
+++ b/Documentation/firmware_class/firmware_sample_firmware_class.c
@@ -14,9 +14,8 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/timer.h>
-#include <asm/hardirq.h>
+#include <linux/firmware.h>
 
-#include "linux/firmware.h"
 
 MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>");
 MODULE_DESCRIPTION("Hackish sample for using firmware class directly");
diff --git a/Documentation/firmware_class/hotplug-script b/Documentation/firmware_class/hotplug-script
index d6608e024..1990130f2 100644
--- a/Documentation/firmware_class/hotplug-script
+++ b/Documentation/firmware_class/hotplug-script
@@ -7,10 +7,10 @@
 HOTPLUG_FW_DIR=/usr/lib/hotplug/firmware/
 
 echo 1 > /sys/$DEVPATH/loading
-cat $HOTPLUG_FW_DIR/$FIRMWARE > /sysfs/$DEVPATH/data
+cat $HOTPLUG_FW_DIR/$FIRMWARE > /sys/$DEVPATH/data
 echo 0 > /sys/$DEVPATH/loading
 
 # To cancel the load in case of error:
 #
-#	echo -1 > /sysfs/$DEVPATH/loading
+#	echo -1 > /sys/$DEVPATH/loading
 #
diff --git a/Documentation/i2c/sysfs-interface b/Documentation/i2c/sysfs-interface
index f651de487..3e74daeb9 100644
--- a/Documentation/i2c/sysfs-interface
+++ b/Documentation/i2c/sysfs-interface
@@ -104,7 +104,7 @@ in[0-8]_input	Voltage input value.
 			in7_*	varies
 			in8_*	varies
 
-in0_ref		CPU core reference voltage.
+cpu[0-1]_vid	CPU core reference voltage.
 		Unit: millivolt
 		Read only.
 		Not always correct.
diff --git a/Documentation/input/joystick-parport.txt b/Documentation/input/joystick-parport.txt
index b8d92c008..88a011c9f 100644
--- a/Documentation/input/joystick-parport.txt
+++ b/Documentation/input/joystick-parport.txt
@@ -335,6 +335,7 @@ controller (compatible with DirectPadPro):
  * Analog PSX Pad (red mode)
  * Analog PSX Pad (green mode)
  * PSX Rumble Pad
+ * PSX DDR Pad
 
 2.4 Sega
 ~~~~~~~~
@@ -452,14 +453,22 @@ uses the following kernel/module command line:
 	  5  | Multisystem 2-button joystick
 	  6  | N64 pad
 	  7  | Sony PSX controller
+	  8  | Sony PSX DDR controller
 
-  The exact type of the PSX controller type is autoprobed, so you must have
-your controller plugged in before initializing.
+  The exact type of the PSX controller type is autoprobed when used so
+hot swapping should work (but is not recomended).
 
   Should you want to use more than one of parallel ports at once, you can use
 gamecon.map2 and gamecon.map3 as additional command line parameters for two
 more parallel ports.
 
+  There are two options specific to PSX driver portion.  gamecon.psx_delay sets
+the command delay when talking to the controllers. The default of 25 should
+work but you can try lowering it for better performace. If your pads don't
+respond try raising it untill they work. Setting the type to 8 allows the
+driver to be used with Dance Dance Revolution or similar games. Arrow keys are
+registered as key presses instead of X and Y axes.
+
 3.2 db9.c
 ~~~~~~~~~
   Apart from making an interface, there is nothing difficult on using the
diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt
index 2be1218a6..bd7a19777 100644
--- a/Documentation/ioctl-number.txt
+++ b/Documentation/ioctl-number.txt
@@ -117,6 +117,7 @@ Code	Seq#	Include File		Comments
 					<mailto:natalia@nikhefk.nikhef.nl>
 'c'	00-7F	linux/comstats.h	conflict!
 'c'	00-7F	linux/coda.h		conflict!
+'d'	00-FF	linux/char/drm/drm/h	conflict!
 'd'	00-1F	linux/devfs_fs.h	conflict!
 'd'	00-DF	linux/video_decoder.h	conflict!
 'd'	F0-FF	linux/digi1.h
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index ec8177616..1075e4de2 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -25,6 +25,7 @@ This document describes the Linux kernel Makefiles.
 	   --- 4.4 Using C++ for host programs
 	   --- 4.5 Controlling compiler options for host programs
 	   --- 4.6 When host programs are actually built
+	   --- 4.7 Using hostprogs-$(CONFIG_FOO)
 
 	=== 5 Kbuild clean infrastructure
 
@@ -36,6 +37,8 @@ This document describes the Linux kernel Makefiles.
 	   --- 6.5 Building non-kbuild targets
 	   --- 6.6 Commands useful for building a boot image
 	   --- 6.7 Custom kbuild commands
+	   --- 6.8 Preprocessing linker scripts
+	   --- 6.9 $(CC) support functions
 
 	=== 7 Kbuild Variables
 	=== 8 Makefile language
@@ -387,7 +390,7 @@ compilation stage.
 Two steps are required in order to use a host executable.
 
 The first step is to tell kbuild that a host program exists. This is
-done utilising the variable host-prog.
+done utilising the variable hostprogs-y.
 
 The second step is to add an explicit dependency to the executable.
 This can be done in two ways. Either add the dependency in a rule, 
@@ -402,7 +405,7 @@ Both possibilities are described in the following.
 	built on the build host.
 
 	Example:
-		host-progs := bin2hex
+		hostprogs-y := bin2hex
 
 	Kbuild assumes in the above example that bin2hex is made from a single
 	c-source file named bin2hex.c located in the same directory as
@@ -418,7 +421,7 @@ Both possibilities are described in the following.
 
 	Example:
 		#scripts/lxdialog/Makefile
-		host-progs    := lxdialog  
+		hostprogs-y   := lxdialog  
 		lxdialog-objs := checklist.o lxdialog.o
 
 	Objects with extension .o are compiled from the corresponding .c
@@ -438,7 +441,7 @@ Both possibilities are described in the following.
 
 	Example:
 		#scripts/kconfig/Makefile
-		host-progs      := conf
+		hostprogs-y     := conf
 		conf-objs       := conf.o libkconfig.so
 		libkconfig-objs := expr.o type.o
   
@@ -457,7 +460,7 @@ Both possibilities are described in the following.
 
 	Example:
 		#scripts/kconfig/Makefile
-		host-progs    := qconf
+		hostprogs-y   := qconf
 		qconf-cxxobjs := qconf.o
 
 	In the example above the executable is composed of the C++ file
@@ -468,7 +471,7 @@ Both possibilities are described in the following.
 
 	Example:
 		#scripts/kconfig/Makefile
-		host-progs    := qconf
+		hostprogs-y   := qconf
 		qconf-cxxobjs := qconf.o
 		qconf-objs    := check.o
 	
@@ -509,7 +512,7 @@ Both possibilities are described in the following.
 
 	Example:
 		#drivers/pci/Makefile
-		host-progs := gen-devlist
+		hostprogs-y := gen-devlist
 		$(obj)/devlist.h: $(src)/pci.ids $(obj)/gen-devlist
 			( cd $(obj); ./gen-devlist ) < $<
 
@@ -524,18 +527,32 @@ Both possibilities are described in the following.
 
 	Example:
 		#scripts/lxdialog/Makefile
-		host-progs    := lxdialog
-		always        := $(host-progs)
+		hostprogs-y   := lxdialog
+		always        := $(hostprogs-y)
 
 	This will tell kbuild to build lxdialog even if not referenced in
 	any rule.
 
+--- 4.7 Using hostprogs-$(CONFIG_FOO)
+
+	A typcal pattern in a Kbuild file lok like this:
+
+	Example:
+		#scripts/Makefile
+		hostprogs-$(CONFIG_KALLSYMS) += kallsyms
+
+	Kbuild knows about both 'y' for built-in and 'm' for module.
+	So if a config symbol evaluate to 'm', kbuild will still build
+	the binary. In other words Kbuild handle hostprogs-m exactly
+	like hostprogs-y. But only hostprogs-y is recommend used
+	when no CONFIG symbol are involved.
+
 === 5 Kbuild clean infrastructure
 
 "make clean" deletes most generated files in the src tree where the kernel
 is compiled. This includes generated files such as host programs.
-Kbuild knows targets listed in $(host-progs), $(always), $(extra-y) and
-$(targets). They are all deleted during "make clean".
+Kbuild knows targets listed in $(hostprogs-y), $(hostprogs-m), $(always),
+$(extra-y) and $(targets). They are all deleted during "make clean".
 Files matching the patterns "*.[oas]", "*.ko", plus some additional files
 generated by kbuild are deleted all over the kernel src tree when
 "make clean" is executed.
@@ -547,8 +564,17 @@ Additional files can be specified in kbuild makefiles by use of $(clean-files).
 		clean-files := devlist.h classlist.h
 
 When executing "make clean", the two files "devlist.h classlist.h" will
-be deleted. Kbuild knows that files specified by $(clean-files) are
-located in the same directory as the makefile.
+be deleted. Kbuild will assume files to be in same relative directory as the
+Makefile except if an absolute path is specified (path starting with '/').
+
+To delete a directory hirachy use:
+	Example:
+		#scripts/package/Makefile
+		clean-dirs := $(objtree)/debian/
+
+This will delete the directory debian, including all subdirectories.
+Kbuild will assume the directories to be in the same relative path as the
+Makefile if no absolute path is specified (path does not start with '/').
 
 Usually kbuild descends down in subdirectories due to "obj-* := dir/",
 but in the architecture makefiles where the kbuild infrastructure
@@ -638,15 +664,6 @@ When kbuild executes the following steps are followed (roughly):
 		#arch/i386/Makefile
 		LDFLAGS_vmlinux := -e stext
 
-    LDFLAGS_BLOB	Options for $(LD) when linking the initramfs blob
-
-	The image used for initramfs is made during the build process.
-	LDFLAGS_BLOB is used to specify additional flags to be used when
-	creating the initramfs_data.o file.
-	Example:
-		#arch/i386/Makefile
-		LDFLAGS_BLOB := --format binary --oformat elf32-i386
-
     OBJCOPYFLAGS	objcopy flags
 
 	When $(call if_changed,objcopy) is used to translate a .o file,
@@ -914,6 +931,90 @@ When kbuild executes the following steps are followed (roughly):
 	will be displayed with "make KBUILD_VERBOSE=0".
 	
 
+--- 6.8 Preprocessing linker scripts
+
+	When the vmlinux image is build the linker script:
+	arch/$(ARCH)/kernel/vmlinux.lds is used.
+	The script is a preprocessed variant of the file vmlinux.lds.S
+	located in the same directory.
+	kbuild knows .lds file and includes a rule *lds.S -> *lds.
+	
+	Example:
+		#arch/i386/kernel/Makefile
+		always := vmlinux.lds
+	
+		#Makefile
+		export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
+		
+	The assigment to $(always) is used to tell kbuild to build the
+	target: vmlinux.lds.
+	The assignment to $(CPPFLAGS_vmlinux.lds) tell kbuild to use the
+	specified options when building the target vmlinux.lds.
+	
+	When building the *.lds target kbuild used the variakles:
+	CPPFLAGS	: Set in top-level Makefile
+	EXTRA_CPPFLAGS	: May be set in the kbuild makefile
+	CPPFLAGS_$(@F)  : Target specific flags.
+	                  Note that the full filename is used in this
+	                  assignment.
+
+	The kbuild infrastructure for *lds file are used in several
+	architecture specific files.
+
+
+--- 6.9 $(CC) support functions
+
+	The kernel may be build with several different versions of
+	$(CC), each supporting a unique set of features and options.
+	kbuild provide basic support to check for valid options for $(CC).
+	$(CC) is useally the gcc compiler, but other alternatives are
+	available.
+
+    cc-option
+	cc-option is used to check if $(CC) support a given option, and not
+	supported to use an optional second option.
+
+	Example:
+		#arch/i386/Makefile
+		cflags-y += $(call cc-option,-march=pentium-mmx,-march=i586)
+
+	In the above example cflags-y will be assigned the option
+	-march=pentium-mmx if supported by $(CC), otherwise -march-i586.
+	The second argument to cc-option is optional, and if omitted
+	cflags-y will be assigned no value if first option is not supported.
+
+   cc-option-yn
+   	cc-option-yn is used to check if gcc supports a given option
+	and return 'y' if supported, otherwise 'n'.
+
+	Example:
+		#arch/ppc/Makefile
+		biarch := $(call cc-option-yn, -m32)
+		aflags-$(biarch) += -a32
+		cflags-$(biarch) += -m32
+	
+	In the above example $(biarch) is set to y if $(CC) supports the -m32
+	option. When $(biarch) equals to y the expanded variables $(aflags-y)
+	and $(cflags-y) will be assigned the values -a32 and -m32.
+
+    cc-version
+	cc-version return a numerical version of the $(CC) compiler version.
+	The format is <major><minor> where both are two digits. So for example
+	gcc 3.41 would return 0341.
+	cc-version is useful when a specific $(CC) version is faulty in one
+	area, for example the -mregparm=3 were broken in some gcc version
+	even though the option was accepted by gcc.
+
+	Example:
+		#arch/i386/Makefile
+		GCC_VERSION := $(call cc-version)
+		cflags-y += $(shell \
+		if [ $(GCC_VERSION) -ge 0300 ] ; then echo "-mregparm=3"; fi ;)
+
+	In the above example -mregparm=3 is only used for gcc version greater
+	than or equal to gcc 3.0.
+	
+
 === 7 Kbuild Variables
 
 The top Makefile exports the following variables:
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 13839bd74..e7ea0b7a6 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -97,9 +97,6 @@ running once the system is up.
 			See header of drivers/scsi/53c7xx.c.
 			See also Documentation/scsi/ncr53c7xx.txt.
 
-	98busmouse.irq=	[HW,MOUSE] PC-9801 Bus Mouse Driver
-			Format: <irq>, default is 13
-
 	acpi=		[HW,ACPI] Advanced Configuration and Power Interface 
 			Format: { force | off | ht | strict }
 			force -- enable ACPI if default was off
@@ -138,6 +135,20 @@ running once the system is up.
 			Recognize and ignore IRQ0/pin2 Interrupt Override.
 			For broken nForce2 BIOS resulting in XT-PIC timer.
 
+	acpi_dbg_layer=	[HW,ACPI]
+			Format: <int>
+			Each bit of the <int> indicates an acpi debug layer,
+			1: enable, 0: disable. It is useful for boot time
+			debugging. After system has booted up, it can be set
+			via /proc/acpi/debug_layer.
+
+	acpi_dbg_level=	[HW,ACPI]
+			Format: <int>
+			Each bit of the <int> indicates an acpi debug level,
+			1: enable, 0: disable. It is useful for boot time
+			debugging. After system has booted up, it can be set
+			via /proc/acpi/debug_level.
+
 	ad1816=		[HW,OSS]
 			Format: <io>,<irq>,<dma>,<dma2>
 			See also Documentation/sound/oss/AD1816.
@@ -189,6 +200,11 @@ running once the system is up.
 			Disable APC CPU standby support. SPARCstation-Fox does
 			not play well with APC CPU idle - disable it if you have
 			APC and your system crashes randomly.
+
+	apic=		[APIC,i386] Change the output verbosity  whilst booting
+			Format: { quiet (default) | verbose | debug }
+			Change the amount of debugging information output
+			when initialising the APIC and IO-APIC components.
  
 	apm=		[APM] Advanced Power Management
 			See header of arch/i386/kernel/apm.c.
@@ -448,6 +464,11 @@ running once the system is up.
 	hd?=		[HW] (E)IDE subsystem
 	hd?lun=		See Documentation/ide.txt.
 
+	highmem=nn[KMG]	[KNL,BOOT] forces the highmem zone to have an exact
+			size of <nn>. This works even on boxes that have no
+			highmem otherwise. This also works to reduce highmem
+			size on bigger boxes.
+
 	hisax=		[HW,ISDN]
 			See Documentation/isdn/README.HiSax.
 
@@ -523,6 +544,18 @@ running once the system is up.
 	isapnp=		[ISAPNP]
 			Format: <RDP>, <reset>, <pci_scan>, <verbosity>
 
+	isolcpus=	[KNL,SMP] Isolate CPUs from the general scheduler.
+			Format: <cpu number>, ..., <cpu number>
+			This option can be used to specify one or more CPUs
+			to isolate from the general SMP balancing and scheduling
+			algorithms. The only way to move a process onto or off
+			an "isolated" CPU is via the CPU affinity syscalls.
+
+			This option is the preferred way to isolate CPUs. The
+			alternative - manually setting the CPU mask of all tasks
+			in the system can cause problems and suboptimal load
+			balancer performance.
+
 	isp16=		[HW,CD]
 			Format: <io>,<irq>,<dma>,<setup>
 
@@ -574,6 +607,20 @@ running once the system is up.
 				so, the driver will manage that printer.
 				See also header of drivers/char/lp.c.
 
+	lpj=n		[KNL]
+			Sets loops_per_jiffy to given constant, thus avoiding
+			time-consuming boot-time autodetection (up to 250 ms per
+			CPU). 0 enables autodetection (default). To determine
+			the correct value for your kernel, boot with normal
+			autodetection and see what value is printed. Note that
+			on SMP systems the preset will be applied to all CPUs,
+			which is likely to cause problems if your CPUs need
+			significantly divergent settings. An incorrect value
+			will cause delays in the kernel to be wrong, leading to
+			unpredictable I/O errors and other breakage. Although
+			unlikely, in the extreme case this might damage your
+			hardware.
+
 	ltpc=		[NET]
 			Format: <io>,<irq>,<dma>
 
@@ -650,6 +697,12 @@ running once the system is up.
 
 	mga=		[HW,DRM]
 
+	mousedev.tap_time=
+			[MOUSE] Maximum time between finger touching and
+			leaving touchpad surface for touch to be considered
+			a tap and be reported as a left button click (for
+			touchpads working in absolute mode only).
+			Format: <msecs>
 	mousedev.xres=	[MOUSE] Horizontal screen resolution, used for devices
 			reporting absolute coordinates, such as tablets
 	mousedev.yres=	[MOUSE] Vertical screen resolution, used for devices
@@ -707,6 +760,9 @@ running once the system is up.
 	noasync		[HW,M68K] Disables async and sync negotiation for
 			all devices.
 
+	nobats		[PPC] Do not use BATs for mapping kernel lowmem
+			on "Classic" PPC cores.
+
 	nocache		[ARM]
  
 	nodisconnect	[HW,SCSI,M68K] Disables SCSI disconnects.
@@ -739,8 +795,13 @@ running once the system is up.
 
 	nolapic		[IA-32,APIC] Do not enable or use the local APIC.
 
+	noltlbs		[PPC] Do not use large page/tlb entries for kernel
+			lowmem mapping on PPC40x.
+
 	nomce		[IA-32] Machine Check Exception
 
+	noresidual	[PPC] Don't use residual data on PReP machines.
+
 	noresume	[SWSUSP] Disables resume and restore original swap space.
  
 	no-scroll	[VGA] Disables scrollback.
@@ -852,6 +913,13 @@ running once the system is up.
 		noacpi			[IA-32] Do not use ACPI for IRQ routing
 					or for PCI scanning.
 
+		firmware		[ARM] Do not re-enumerate the bus but
+					instead just use the configuration
+					from the bootloader. This is currently
+					used on IXP2000 systems where the
+					bus has to be configured a certain way
+					for adjunct CPUs.
+
 	pcmv=		[HW,PCMCIA] BadgePAD 4
 
 	pd.		[PARIDE]
@@ -887,7 +955,10 @@ running once the system is up.
 			Ranges are in pairs (memory base and size).
 
 	profile=	[KNL] Enable kernel profiling via /proc/profile
-			(param: profile step/bucket size as a power of 2)
+			{ schedule | <number> }
+			(param: schedule - profile schedule points}
+			(param: profile step/bucket size as a power of 2 for
+				statistical time based profiling)
 
 	prompt_ramdisk=	[RAM] List of RAM disks to prompt for floppy disk
 			before loading.
@@ -1250,6 +1321,12 @@ running once the system is up.
 			This is actually a boot loader parameter; the value is
 			passed to the kernel using a special protocol.
 
+	vmalloc=nn[KMG]	[KNL,BOOT] forces the vmalloc area to have an exact
+			size of <nn>. This can be used to increase the
+			minimum size (128MB on x86). It can also be used to
+			decrease the size and leave more room for directly
+			mapped kernel RAM.
+
 	vmhalt=		[KNL,S390]
 
 	vmpoff=		[KNL,S390] 
diff --git a/Documentation/laptop-mode.txt b/Documentation/laptop-mode.txt
index 065e59cbb..dc4e810af 100644
--- a/Documentation/laptop-mode.txt
+++ b/Documentation/laptop-mode.txt
@@ -249,7 +249,7 @@ MINIMUM_BATTERY_MINUTES=10
 # playing.
 #READAHEAD=4096
 
-# Shall we remount journaled fs. with appropiate commit interval? (1=yes)
+# Shall we remount journaled fs. with appropriate commit interval? (1=yes)
 #DO_REMOUNTS=1
 
 # And shall we add the "noatime" option to that as well? (1=yes)
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 10304b436..c9ead70d5 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -837,6 +837,11 @@ bridge-nf-call-iptables - BOOLEAN
 	0 : disable this.
 	Default: 1
 
+bridge-nf-call-ip6tables - BOOLEAN
+	1 : pass bridged IPv6 traffic to ip6tables' chains.
+	0 : disable this.
+	Default: 1
+
 bridge-nf-filter-vlan-tagged - BOOLEAN
 	1 : pass bridged vlan-tagged ARP/IP traffic to arptables/iptables.
 	0 : disable this.
diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt
index 8c456edb6..1509f3aff 100644
--- a/Documentation/networking/netdevices.txt
+++ b/Documentation/networking/netdevices.txt
@@ -43,8 +43,21 @@ dev->get_stats:
 
 dev->hard_start_xmit:
 	Synchronization: dev->xmit_lock spinlock.
+	When the driver sets NETIF_F_LLTX in dev->features this will be
+	called without holding xmit_lock. In this case the driver 
+	has to lock by itself when needed. It is recommended to use a try lock
+	for this and return -1 when the spin lock fails. 
+	The locking there should also properly protect against 
+	set_multicast_list
 	Context: BHs disabled
 	Notes: netif_queue_stopped() is guaranteed false
+	Return codes: 
+	o NETDEV_TX_OK everything ok. 
+	o NETDEV_TX_BUSY Cannot transmit packet, try later 
+	  Usually a bug, means queue start/stop flow control is broken in
+	  the driver. Note: the driver must NOT put the skb in its DMA ring.
+	o NETDEV_TX_LOCKED Locking failed, please retry quickly.
+	  Only valid when NETIF_F_LLTX is set.
 
 dev->tx_timeout:
 	Synchronization: dev->xmit_lock spinlock.
diff --git a/Documentation/pci.txt b/Documentation/pci.txt
index 411947638..a1a2bd557 100644
--- a/Documentation/pci.txt
+++ b/Documentation/pci.txt
@@ -25,6 +25,7 @@ on (either the old or the new way), it needs to perform the following steps:
 	Discover resources (addresses and IRQ numbers) provided by the device
 	Allocate these resources
 	Communicate with the device
+	Disable the device
 
 Most of these topics are covered by the following sections, for the rest
 look at <linux/pci.h>, it's hopefully well commented.
@@ -162,8 +163,8 @@ You must eventually (possibly at module unload) decrement the reference
 count on these devices by calling pci_dev_put().
 
 
-3. Enabling devices
-~~~~~~~~~~~~~~~~~~~
+3. Enabling and disabling devices
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Before you do anything with the device you've found, you need to enable
 it by calling pci_enable_device() which enables I/O and memory regions of
 the device, allocates an IRQ if necessary, assigns missing resources if
@@ -180,6 +181,12 @@ and also ensures that the cache line size register is set correctly.
 Make sure to check the return value of pci_set_mwi(), not all architectures
 may support Memory-Write-Invalidate.
 
+   If your driver decides to stop using the device (e.g., there was an
+error while setting it up or the driver module is being unloaded), it
+should call pci_disable_device() to deallocate any IRQ resources, disable
+PCI bus-mastering, etc.  You should not do anything with the device after
+calling pci_disable_device().
+
 4. How to access PCI config space
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    You can use pci_(read|write)_config_(byte|word|dword) to access the config
diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt
index 5cdab4c55..cbbbc9c07 100644
--- a/Documentation/power/swsusp.txt
+++ b/Documentation/power/swsusp.txt
@@ -20,26 +20,6 @@ From kernel/suspend.c:
 You need to append resume=/dev/your_swap_partition to kernel command
 line. Then you suspend by echo 4 > /proc/acpi/sleep.
 
-Pavel's unreliable guide to swsusp mess
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-There are currently two versions of swap suspend in the kernel, the old
-"Pavel's" version in kernel/power/swsusp.c and the new "Patrick's"
-version in kernel/power/pmdisk.c. They provide the same functionality;
-the old version looks ugly but was tested, while the new version looks
-nicer but did not receive so much testing. echo 4 > /proc/acpi/sleep
-calls the old version, echo disk > /sys/power/state calls the new one.
-
-[In the future, when the new version is stable enough, two things can
-happen:
-
-* the new version is moved into swsusp.c, and swsusp is renamed to swap
-  suspend (Pavel prefers this)
-
-* pmdisk is kept as is and swsusp.c is removed from the kernel]
-
-
-
 Article about goals and implementation of Software Suspend for Linux
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Author: G‚ábor Kuti
@@ -75,10 +55,6 @@ hardware!
 About the code
 
 Things to implement
-- SMP support. I've done an SMP support but since I don't have access to a kind
-  of this one I cannot test it. Please SMP people test it.  .. Tested it,
-  doesn't work. Had no time to figure out why. There is some mess with
-  interrupts AFAIK..
 - We should only make a copy of data related to kernel segment, since any
   process data won't be changed.
 - Should make more sanity checks. Or are these enough?
@@ -90,11 +66,6 @@ Not so important ideas for implementing
 - We should not free pages at the beginning so aggressively, most of them
   go there anyway..
 
-Drivers that need support
-- pc_keyb -- perhaps we can wait for vojtech's input patches
-- do IDE cdroms need some kind of support?
-- IDE CD-RW -- how to deal with that?
-
 Sleep states summary (thanx, Ducrot)
 ====================================
 
@@ -109,7 +80,8 @@ and perhaps
 echo 4b > /proc/acpi/sleep      # for suspend to disk via s4bios
 
 
-FAQ:
+Frequently Asked Questions
+==========================
 
 Q: well, suspending a server is IMHO a really stupid thing,
 but... (Diego Zuccato):
diff --git a/Documentation/powerpc/hvcs.txt b/Documentation/powerpc/hvcs.txt
index 111ad15a3..c0a62e116 100644
--- a/Documentation/powerpc/hvcs.txt
+++ b/Documentation/powerpc/hvcs.txt
@@ -10,7 +10,7 @@ NOTE:Eight space tabs are the optimum editor setting for reading this file.
 
 	       Author(s) :  Ryan S. Arnold <rsa@us.ibm.com>
 		       Date Created: March, 02, 2004
-		       Last Changed: July, 07, 2004
+		       Last Changed: August, 24, 2004
 
 ---------------------------------------------------------------------------
 Table of contents:
@@ -243,6 +243,25 @@ node.  If this is not done, the next user to connect to the console will
 continue using the previous user's logged in session which includes
 using the $TERM variable that the previous user supplied.
 
+Hotplug add and remove of vty-server adapters affects which /dev/hvcs* node
+is used to connect to each vty-server adapter.  In order to determine which
+vty-server adapter is associated with which /dev/hvcs* node a special sysfs
+attribute has been added to each vty-server sysfs entry.  This entry is
+called "index" and showing it reveals an integer that refers to the
+/dev/hvcs* entry to use to connect to that device.  For instance cating the
+index attribute of vty-server adapter 30000004 shows the following.
+
+	Pow5:/sys/bus/vio/drivers/hvcs/30000004 # cat index
+	2
+
+This index of '2' means that in order to connect to vty-server adapter
+30000004 the user should interact with /dev/hvcs2.
+
+It should be noted that due to the system hotplug I/O capabilities of a
+system the /dev/hvcs* entry that interacts with a particular vty-server
+adapter is not guarenteed to remain the same across system reboots.  Look
+in the Q & A section for more on this issue.
+
 ---------------------------------------------------------------------------
 6. Disconnection
 
@@ -328,8 +347,8 @@ address that is created by firmware.  An example vty-server sysfs entry
 looks like the following:
 
 	Pow5:/sys/bus/vio/drivers/hvcs/30000004 # ls
-	.   current_vty   devspec  partner_clcs  vterm_state
-	..  detach_state  name     partner_vtys
+	.   current_vty   devspec  name          partner_vtys
+	..  detach_state  index    partner_clcs  vterm_state
 
 Each entry is provided, by default with a "name" attribute.  Reading the
 "name" attribute will reveal the device type as shown in the following
@@ -499,6 +518,20 @@ A: Yes, if you have dlpar and hotplug enabled for your system and it has
 been built into the kernel the hvcs drivers is configured to dynamically
 handle additions of new devices and removals of unused devices.
 
+---------------------------------------------------------------------------
+Q: For some reason /dev/hvcs* doesn't map to the same vty-server adapter
+after a reboot.  What happened?
+
+A: Assignment of vty-server adapters to /dev/hvcs* entries is always done
+in the order that the adapters are exposed.  Due to hotplug capabilities of
+this driver assignment of hotplug added vty-servers may be in a different
+order than how they would be exposed on module load.  Rebooting or
+reloading the module after dynamic addition may result in the /dev/hvcs*
+and vty-server coupling changing if a vty-server adapter was added in a
+slot inbetween two other vty-server adapters.  Refer to the section above
+on how to determine which vty-server goes with which /dev/hvcs* node.
+Hint; look at the sysfs "index" attribute for the vty-server.
+
 ---------------------------------------------------------------------------
 Q: Can I use /dev/hvcs* as a conduit to another partition and use a tty
 device on that partition as the other end of the pipe?
diff --git a/Documentation/powerpc/mpc52xx.txt b/Documentation/powerpc/mpc52xx.txt
index 6efe0a0a5..10dd4ab93 100644
--- a/Documentation/powerpc/mpc52xx.txt
+++ b/Documentation/powerpc/mpc52xx.txt
@@ -1,7 +1,7 @@
 Linux 2.6.x on MPC52xx family
 -----------------------------
 
-For the latest info, go to http://www.246tNt.com/mpc52xx/state.txt
+For the latest info, go to http://www.246tNt.com/mpc52xx/
  
 To compile/use :
 
@@ -37,12 +37,3 @@ Some remarks :
  - Of course, I inspired myself from the 2.4 port. If you think I forgot to
    mention you/your company in the copyright of some code, I'll correct it
    ASAP.
- - The codes wants the MBAR to be set at 0xf0000000 by the bootloader. It's
-   mapped 1:1 with the MMU. If for whatever reason, you want to change this,
-   beware that some code depends on the 0xf0000000 address and other depends
-   on the 1:1 mapping.
- - Most of the code assumes that port multiplexing, frequency selection, ...
-   has already been done. IMHO this should be done as early as possible, in
-   the bootloader. If for whatever reason you can't do it there, do it in the
-   platform setup code (if U-Boot) or in the arch/ppc/boot/simple/... (if
-   DBug)
diff --git a/Documentation/sched-domains.txt b/Documentation/sched-domains.txt
index b5da811fc..a9e990ab9 100644
--- a/Documentation/sched-domains.txt
+++ b/Documentation/sched-domains.txt
@@ -5,12 +5,13 @@ MUST be NULL terminated, and domain structures should be per-CPU as they
 are locklessly updated.
 
 Each scheduling domain spans a number of CPUs (stored in the ->span field).
-A domain's span MUST be a superset of it child's span, and a base domain
-for CPU i MUST span at least i. The top domain for each CPU will generally
-span all CPUs in the system although strictly it doesn't have to, but this
-could lead to a case where some CPUs will never be given tasks to run unless
-the CPUs allowed mask is explicitly set. A sched domain's span means "balance
-process load among these CPUs".
+A domain's span MUST be a superset of it child's span (this restriction could
+be relaxed if the need arises), and a base domain for CPU i MUST span at least
+i. The top domain for each CPU will generally span all CPUs in the system
+although strictly it doesn't have to, but this could lead to a case where some
+CPUs will never be given tasks to run unless the CPUs allowed mask is
+explicitly set. A sched domain's span means "balance process load among these
+CPUs".
 
 Each scheduling domain must have one or more CPU groups (struct sched_group)
 which are organised as a circular one way linked list from the ->groups
@@ -46,6 +47,20 @@ The implementor should read comments in include/linux/sched.h:
 struct sched_domain fields, SD_FLAG_*, SD_*_INIT to get an idea of
 the specifics and what to tune.
 
+For SMT, the architecture must define CONFIG_SCHED_SMT and provide a
+cpumask_t cpu_sibling_map[NR_CPUS], where cpu_sibling_map[i] is the mask of
+all "i"'s siblings as well as "i" itself.
+
+Architectures may retain the regular override the default SD_*_INIT flags
+while using the generic domain builder in kernel/sched.c if they wish to
+retain the traditional SMT->SMP->NUMA topology (or some subset of that). This
+can be done by #define'ing ARCH_HASH_SCHED_TUNE.
+
+Alternatively, the architecture may completely override the generic domain
+builder by #define'ing ARCH_HASH_SCHED_DOMAIN, and exporting your
+arch_init_sched_domains function. This function will attach domains to all
+CPUs using cpu_attach_domain.
+
 Implementors should change the line
 #undef SCHED_DOMAIN_DEBUG
 to
diff --git a/Documentation/scsi/ChangeLog.megaraid b/Documentation/scsi/ChangeLog.megaraid
index 03af4a4cd..431e3983e 100644
--- a/Documentation/scsi/ChangeLog.megaraid
+++ b/Documentation/scsi/ChangeLog.megaraid
@@ -1,42 +1,223 @@
-### Version 2.00.3
-Wed Jan 29 09:13:44 EST 200 - Atul Mukker <atulm@lsil.com>
-i.	Change the handshake in ISR while acknowledging interrupts. Write the
-	valid interrupt pattern 0x10001234 as soon as it is read from the
-	outdoor register. In existing driver and on certain platform, invalid
-	command ids were being returned.
+Release Date	: Mon Sep 27 22:15:07 EDT 2004 - Atul Mukker <atulm@lsil.com>
+Current Version	: 2.20.4.0 (scsi module), 2.20.2.0 (cmm module)
+Older Version	: 2.20.3.1 (scsi module), 2.20.2.0 (cmm module)
 
-	Also, do not wait on status be become 0xFF, since FW can return this
-	status in certain circumstances.
+i.	Fix data corruption. Because of a typo in the driver, the IO packets
+	were wrongly shared by the ioctl path. This causes a whole IO command
+	to be replaced by an incoming ioctl command.
 
-	Initialize the numstatus field of mailbox to 0xFF so that we can wait
-	on this wait in next interrupt. Firmware does not change its value
-	unless there are some status to be posted
+Release Date	: Tue Aug 24 09:43:35 EDT 2004 - Atul Mukker <atulm@lsil.com>
+Current Version	: 2.20.3.1 (scsi module), 2.20.2.0 (cmm module)
+Older Version	: 2.20.3.0 (scsi module), 2.20.2.0 (cmm module)
 
-ii.	Specify the logical drive number while issuing the RESERVATION_STATUS
+i.	Function reordering so that inline functions are defined before they
+	are actually used. It is now mandatory for GCC 3.4.1 (current stable)
 
-iii.	Reduce the default mailbox busy wait time from 300us to 10us. This is
-	done to avaoid a possible deadlock in FW because of longer bust waits.
+	Declare some heavy-weight functions to be non-inlined,
+	megaraid_mbox_build_cmd, megaraid_mbox_runpendq,
+	megaraid_mbox_prepare_pthru, megaraid_mbox_prepare_epthru,
+	megaraid_busywait_mbox
 
-iv.	The max outstanding commands are reduced to 126 because that't the
-	safest value on all FW.
+		- Andrew Morton <akpm@osdl.org>, 08.19.2004
+		linux-scsi mailing list
 
-v.	Number of sectors per IO are reduced to 128 (64kb), becuase FW needs
-	resources in special circumstances like check consistency, rebuilds
-	etc.
+	"Something else to clean up after inclusion: every instance of an
+	inline function is actually rendered as a full function call, because
+	the function is always used before it is defined.  Atul, please
+	re-arrange the code to eliminate the need for most (all) of the
+	function prototypes at the top of each file, and define (not just
+	declare with a prototype) each inline function before its first use"
 
-vi.	max_commands is no longer a module parameter because of iv.
+		- Matt Domsch <Matt_Domsch@dell.com>, 07.27.2004
+		linux-scsi mailing list
 
-### Version: 2.00.2
-i.	Intermediate release with kernel specific code
 
+ii.	Display elapsed time (countdown) while waiting for FW to boot.
 
-### Version: 2.00.1i
-Wed Dec  4 14:34:51 EST 2002 - Atul Mukker <atulm@lsil.com>
-i.	Making the older IO based controllers to work with this driver
+iii.	Module compilation reorder in Makefile so that unresolved symbols do
+	not occur when driver is compiled non-modular.
 
+		Patrick J. LoPresti <patl@users.sourceforge.net>, 8.22.2004
+		linux-scsi mailing list
 
-### Version 2.00.1
-Fri Nov 15 10:59:44 EST 2002 - Atul Mukker <atulm@lsil.com>
-i.	Release host lock before issuing internal command to reset
-	reservations in megaraid_reset() and reacquire after internal command
-	is completed.
+
+Release Date	: Thu Aug 19 09:58:33 EDT 2004 - Atul Mukker <atulm@lsil.com>
+Current Version	: 2.20.3.0 (scsi module), 2.20.2.0 (cmm module)
+Older Version	: 2.20.2.0 (scsi module), 2.20.1.0 (cmm module)
+
+i.	When copying the mailbox packets, copy only first 14 bytes (for 32-bit
+	mailboxes) and only first 22 bytes (for 64-bit mailboxes). This is to
+	avoid getting the stale values for busy bit. We want to set the busy
+	bit just before issuing command to the FW.
+
+ii.	In the reset handling, if the reseted command is not owned by the
+	driver, do not (wrongly) print information for the "attached" driver
+	packet.
+
+iii.	Have extended wait when issuing command in synchronous mode. This is
+	required for the cases where the option ROM is disabled and there is
+	no BIOS to start the controller. The FW starts to boot after receiving
+	the first command from the driver. The current driver has 1 second
+	timeout for the synchronous commands, which is far less than what is
+	actually required. We now wait up to MBOX_RESET_TIME (180 seconds) for
+	FW boot process.
+
+iv.	In megaraid_mbox_product_info, clear the mailbox contents completely
+	before preparing the command for inquiry3. This is to ensure that the
+	FW does not get junk values in the command.
+
+v.	Do away with the redundant LSI_CONFIG_COMPAT redefinition for
+	CONFIG_COMPAT. Replace <asm/ioctl32.h> with <linux/ioctl32.h>
+
+		- James Bottomley <James.Bottomley@SteelEye.com>, 08.17.2004
+		 linux-scsi mailing list
+
+vi.	Add support for 64-bit applications. Current drivers assume only
+	32-bit applications, even on 64-bit platforms. Use the "data" and
+	"buffer" fields of the mimd_t structure, instead of embedded 32-bit
+	addresses in application mailbox and passthru structures.
+
+vii.	Move the function declarations for the management module from
+	megaraid_mm.h to megaraid_mm.c
+
+		- Andrew Morton <akpm@osdl.org>, 08.19.2004
+		linux-scsi mailing list
+
+viii.	Change default values for MEGARAID_NEWGEN, MEGARAID_MM, and
+	MEGARAID_MAILBOX to 'n' in Kconfig.megaraid
+
+		- Andrew Morton <akpm@osdl.org>, 08.19.2004
+		linux-scsi mailing list
+
+ix.	replace udelay with msleep
+
+x.	Typos corrected in comments and whitespace adjustments, explicit
+	grouping of expressions.
+
+
+Release Date	: Fri Jul 23 15:22:07 EDT 2004 - Atul Mukker <atulm@lsil.com>
+Current Version	: 2.20.2.0 (scsi module), 2.20.1.0 (cmm module)
+Older Version	: 2.20.1.0 (scsi module), 2.20.0.0 (cmm module)
+
+i.	Add PCI ids for Acer ROMB 2E solution
+
+ii.	Add PCI ids for I4
+
+iii.	Typo corrected for subsys id for megaraid sata 300-4x
+
+iv.	Remove yield() while mailbox handshake in synchronous commands
+
+
+	"My other main gripe is things like this:
+
+	+	// wait for maximum 1 second for status to post
+	+	for (i = 0; i < 40000; i++) {
+	+		if (mbox->numstatus != 0xFF) break;
+	+		udelay(25); yield();
+	+	}
+
+	which litter the driver.  Use of yield() in drivers is deprecated."
+
+		- James Bottomley <James.Bottomley@SteelEye.com>, 07.14.2004
+		 linux-scsi mailing list
+
+v.	Remove redundant __megaraid_busywait_mbox routine
+
+vi.	Fix bug in the managment module, which causes a system lockup when the
+	IO module is loaded and then unloaded, followed by executing any
+	management utility. The current version of management module does not
+	handle the adapter unregister properly.
+
+	Specifically, it still keeps a reference to the unregistered
+	controllers. To avoid this, the static array adapters has been
+	replaced by a dynamic list, which gets updated every time an adapter
+	is added or removed.
+
+	Also, during unregistration of the IO module, the resources are
+	now released in the exact reverse order of the allocation time
+	sequence.
+
+
+Release Date	: Fri Jun 25 18:58:43 EDT 2004 - Atul Mukker <atulm@lsil.com>
+Current Version	: 2.20.1.0
+Older Version	: megaraid 2.20.0.1
+
+i.	Stale list pointer in adapter causes kernel panic when module
+	megaraid_mbox is unloaded
+
+
+Release Date	: Thu Jun 24 20:37:11 EDT 2004 - Atul Mukker <atulm@lsil.com>
+Current Version	: 2.20.0.1
+Older Version	: megaraid 2.20.0.00
+
+i.	Modules are not 'y' by default, but depend on current definition of
+	SCSI & PCI.
+
+ii.	Redundant structure mraid_driver_t removed.
+
+iii.	Miscellaneous indentation and goto/label fixes.
+		- Christoph Hellwig <hch@infradead.org>, 06.24.2004 linux-scsi
+
+iv.	scsi_host_put(), do just before completing HBA shutdown.
+
+
+
+Release Date	: Mon Jun 21 19:53:54 EDT 2004 - Atul Mukker <atulm@lsil.com>
+Current Version	: 2.20.0.0
+Older Version	: megaraid 2.20.0.rc2 and 2.00.3
+
+i.	Independent module to interact with userland applications and
+	multiplex command to low level RAID module(s).
+
+	"Shared code in a third module, a "library module", is an acceptable
+	solution. modprobe automatically loads dependent modules, so users
+	running "modprobe driver1" or "modprobe driver2" would automatically
+	load the shared library module."
+
+		- Jeff Garzik <jgarzik@pobox.com> 02.25.2004 LKML
+
+	"As Jeff hinted, if your userspace<->driver API is consistent between
+	your new MPT-based RAID controllers and your existing megaraid driver,
+	then perhaps you need a single small helper module (lsiioctl or some
+	better name), loaded by both mptraid and megaraid automatically, which
+	handles registering the /dev/megaraid node dynamically. In this case,
+	both mptraid and megaraid would register with lsiioctl for each
+	adapter discovered, and lsiioctl would essentially be a switch,
+	redirecting userspace tool ioctls to the appropriate driver."
+
+		- Matt Domsch <Matt_Domsch@dell.com> 02.25.2004 LKML
+
+ii.	Remove C99 initializations from pci_device id.
+
+	"pci_id_table_g would be much more readable when not using C99
+	initializers.
+	PCI table doesn't change, there's lots of users that prefer the more
+	readable variant.  And it's really far less and much easier to grok
+	lines without C99 initializers."
+
+		- Christoph Hellwig <hch@infradead.org>, 05.28.2004 linux-scsi
+
+iii.	Many fixes as suggested by Christoph Hellwig <hch@infradead.org> on
+	linux-scsi, 05.28.2004
+
+iv.	We now support up to 32 parallel ioctl commands instead of current 1.
+	There is a conscious effort to let memory allocation not fail for ioctl
+	commands.
+
+v.	Do away with internal memory management. Use pci_pool_(create|alloc)
+	instead.
+
+vi.	Kill tasklet when unloading the driver.
+
+vii.	Do not use "host_lock', driver has fine-grain locks now to protect all
+	data structures.
+
+viii.	Optimize the build scatter-gather list routine. The callers already
+	know the data transfer address and length.
+
+ix.	Better implementation of error handling and recovery. Driver now
+	performs extended errors recovery for instances like scsi cable pull.
+
+x.	Disassociate the management commands with an overlaid scsi command.
+	Driver now treats the management packets as special packets and has a
+	dedicated callback routine.
diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt
index 463dfc72f..e0ea1b9e3 100644
--- a/Documentation/scsi/scsi_mid_low_api.txt
+++ b/Documentation/scsi/scsi_mid_low_api.txt
@@ -35,7 +35,7 @@ ISA or MCA adapters).]
 The SCSI mid level isolates an LLD from other layers such as the SCSI
 upper layer drivers and the block layer.
 
-This version of the document roughly matches linux kernel version 2.6.0-test4.
+This version of the document roughly matches linux kernel version 2.6.8 .
 
 Documentation
 =============
@@ -323,6 +323,16 @@ struct Scsi_Host:
         instance. If the reference count reaches 0 then the given instance
         is freed
 
+The Scsi_device structure has had reference counting infrastructure added.
+This effectively spreads the ownership of struct Scsi_device instances
+across the various SCSI layers which use them. Previously such instances
+were exclusively owned by the mid level. See the access functions declared
+towards the end of include/scsi/scsi_device.h . If an LLD wants to keep
+a copy of a pointer to a Scsi_device instance it should use scsi_device_get()
+to bump its reference count. When it is finished with the pointer it can
+use scsi_device_put() to decrement its reference count (and potentially
+delete it).
+
 ^^ struct Scsi_Host actually has 2 reference counts which are manipulated
 in parallel by these functions.
 
@@ -416,7 +426,7 @@ struct scsi_device * scsi_add_device(struct Scsi_Host *shost,
 /**
  * scsi_add_host - perform sysfs registration and SCSI bus scan.
  * @shost:   pointer to scsi host instance
- * @dev:     pointer to struct device host instance
+ * @dev:     pointer to struct device of type scsi class
  *
  *      Returns 0 on success, negative errno of failure (e.g. -ENOMEM)
  *
@@ -453,7 +463,7 @@ void scsi_add_timer(struct scsi_cmnd *scmd, int timeout,
 
 /**
  * scsi_adjust_queue_depth - change the queue depth on a SCSI device
- * @SDpnt:      pointer to SCSI device to change queue depth on
+ * @sdev:       pointer to SCSI device to change queue depth on
  * @tagged:     0 - no tagged queuing
  *              MSG_SIMPLE_TAG - simple (unordered) tagged queuing
  *              MSG_ORDERED_TAG - ordered tagged queuing
@@ -474,8 +484,8 @@ void scsi_add_timer(struct scsi_cmnd *scmd, int timeout,
  *      Defined in: drivers/scsi/scsi.c [see source code for more notes]
  *
  **/
-void scsi_adjust_queue_depth(struct scsi_device * SDpnt, int tagged, 
-                             int num_tags)
+void scsi_adjust_queue_depth(struct scsi_device * sdev, int tagged, 
+                             int tags)
 
 
 /**
@@ -510,7 +520,7 @@ unsigned char *scsi_bios_ptable(struct block_device *dev)
 /**
  * scsi_block_requests - prevent further commands being queued to given host
  *
- * @SHpnt: pointer to host to block commands on
+ * @shost: pointer to host to block commands on
  *
  *      Returns nothing
  *
@@ -521,7 +531,7 @@ unsigned char *scsi_bios_ptable(struct block_device *dev)
  *
  *      Defined in: drivers/scsi/scsi_lib.c
 **/
-void scsi_block_requests(struct Scsi_Host * SHpnt)
+void scsi_block_requests(struct Scsi_Host * shost)
 
 
 /**
@@ -543,9 +553,10 @@ int scsi_delete_timer(struct scsi_cmnd *scmd)
 
 
 /**
- * scsi_host_alloc - create and register a scsi host adapter instance.
- * @shost_tp:   pointer to scsi host template
- * @xtr_bytes:  extra bytes to allocate in hostdata array (which is the
+ * scsi_host_alloc - create a scsi host adapter instance and perform basic
+ *                   initialization.
+ * @sht:        pointer to scsi host template
+ * @privsize:   extra bytes to allocate in hostdata array (which is the
  *              last member of the returned Scsi_Host instance)
  *
  *      Returns pointer to new Scsi_Host instance or NULL on failure
@@ -555,12 +566,15 @@ int scsi_delete_timer(struct scsi_cmnd *scmd)
  *      Notes: When this call returns to the LLD, the SCSI bus scan on
  *      this host has _not_ yet been done.
  *      The hostdata array (by default zero length) is a per host scratch 
- *      area for the LLD.
+ *      area for the LLD's exclusive use.
  *      Both associated refcounting objects have their refcount set to 1.
+ *      Full registration (in sysfs) and a bus scan are performed later when
+ *      scsi_add_host() is called.
  *
  *      Defined in: drivers/scsi/hosts.c .
  **/
-struct Scsi_Host * scsi_host_alloc(struct scsi_host_template *, int xtr_bytes)
+struct Scsi_Host * scsi_host_alloc(struct scsi_host_template * sht,
+                                   int privsize)
 
 
 /**
@@ -619,8 +633,8 @@ int scsi_partsize(unsigned char *buf, unsigned long capacity,
 
 /**
  * scsi_register - create and register a scsi host adapter instance.
- * @shost_tp:   pointer to scsi host template
- * @xtr_bytes:  extra bytes to allocate in hostdata array (which is the
+ * @sht:        pointer to scsi host template
+ * @privsize:   extra bytes to allocate in hostdata array (which is the
  *              last member of the returned Scsi_Host instance)
  *
  *      Returns pointer to new Scsi_Host instance or NULL on failure
@@ -634,7 +648,8 @@ int scsi_partsize(unsigned char *buf, unsigned long capacity,
  *
  *      Defined in: drivers/scsi/hosts.c .
  **/
-struct Scsi_Host * scsi_register(struct scsi_host_template *, int xtr_bytes)
+struct Scsi_Host * scsi_register(struct scsi_host_template * sht,
+                                 int privsize)
 
 
 /**
@@ -711,15 +726,17 @@ void scsi_set_device(struct Scsi_Host * shost, struct device * dev)
  * scsi_to_pci_dma_dir - convert SCSI subsystem direction flag to PCI
  * @scsi_data_direction: SCSI subsystem direction flag
  *
- *      Returns PCI_DMA_TODEVICE given SCSI_DATA_WRITE,
- *              PCI_DMA_FROMDEVICE given SCSI_DATA_READ
- *              PCI_DMA_BIDIRECTIONAL given SCSI_DATA_UNKNOWN
- *              else returns PCI_DMA_NONE
+ *      Returns DMA_TO_DEVICE given SCSI_DATA_WRITE,
+ *              DMA_FROM_DEVICE given SCSI_DATA_READ
+ *              DMA_BIDIRECTIONAL given SCSI_DATA_UNKNOWN
+ *              else returns DMA_NONE
  *
  *      Might block: no
  *
  *      Notes: The SCSI subsystem now uses the same values for these
  *      constants as the PCI subsystem so this function is a nop.
+ *      The recommendation is not to use this conversion function anymore
+ *      (in the 2.6 kernel series) as it is not needed.
  *
  *      Defined in: drivers/scsi/scsi.h .
  **/
@@ -730,13 +747,15 @@ int scsi_to_pci_dma_dir(unsigned char scsi_data_direction)
  * scsi_to_sbus_dma_dir - convert SCSI subsystem direction flag to SBUS
  * @scsi_data_direction: SCSI subsystem direction flag
  *
- *      Returns SBUS_DMA_TODEVICE given SCSI_DATA_WRITE,
- *              SBUS_DMA_FROMDEVICE given SCSI_DATA_READ
- *              SBUS_DMA_BIDIRECTIONAL given SCSI_DATA_UNKNOWN
- *              else returns SBUS_DMA_NONE
+ *      Returns DMA_TO_DEVICE given SCSI_DATA_WRITE,
+ *              FROM_DEVICE given SCSI_DATA_READ
+ *              DMA_BIDIRECTIONAL given SCSI_DATA_UNKNOWN
+ *              else returns DMA_NONE
  *
  *      Notes: The SCSI subsystem now uses the same values for these
  *      constants as the SBUS subsystem so this function is a nop.
+ *      The recommendation is not to use this conversion function anymore
+ *      (in the 2.6 kernel series) as it is not needed.
  *
  *      Might block: no
  *
@@ -749,7 +768,7 @@ int scsi_to_sbus_dma_dir(unsigned char scsi_data_direction)
  * scsi_track_queue_full - track successive QUEUE_FULL events on given
  *                      device to determine if and when there is a need
  *                      to adjust the queue depth on the device.
- * @SDptr: pointer to SCSI device instance
+ * @sdev:  pointer to SCSI device instance
  * @depth: Current number of outstanding SCSI commands on this device,
  *         not counting the one returned as QUEUE_FULL.
  *
@@ -765,13 +784,13 @@ int scsi_to_sbus_dma_dir(unsigned char scsi_data_direction)
  *
  *      Defined in: drivers/scsi/scsi.c .
  **/
-int scsi_track_queue_full(Scsi_Device *SDptr, int depth)
+int scsi_track_queue_full(Scsi_Device *sdev, int depth)
 
 
 /**
  * scsi_unblock_requests - allow further commands to be queued to given host
  *
- * @SHpnt: pointer to host to unblock commands on
+ * @shost: pointer to host to unblock commands on
  *
  *      Returns nothing
  *
@@ -779,7 +798,7 @@ int scsi_track_queue_full(Scsi_Device *SDptr, int depth)
  *
  *      Defined in: drivers/scsi/scsi_lib.c .
 **/
-void scsi_unblock_requests(struct Scsi_Host * SHpnt)
+void scsi_unblock_requests(struct Scsi_Host * shost)
 
 
 /**
@@ -901,20 +920,20 @@ Details:
  *
  *      Returns:
  *
- *	EH_HANDLED:		I fixed the error, please complete the command
- *	EH_RESET_TIMER:		I need more time, reset the timer and
- *				begin counting again
- *	EH_NOT_HANDLED		Begin normal error recovery
-
+ *      EH_HANDLED:             I fixed the error, please complete the command
+ *      EH_RESET_TIMER:         I need more time, reset the timer and
+ *                              begin counting again
+ *      EH_NOT_HANDLED          Begin normal error recovery
+ *
  *
  *      Locks: None held
  *
  *      Calling context: interrupt
  *
- *	Notes: This is to give the LLD an opportunity to do local recovery.
- *	This recovery is limited to determining if the outstanding command
- *	will ever complete.  You may not abort and restart the command from
- *	this callback.
+ *      Notes: This is to give the LLD an opportunity to do local recovery.
+ *      This recovery is limited to determining if the outstanding command
+ *      will ever complete.  You may not abort and restart the command from
+ *      this callback.
  *
  *      Optionally defined in: LLD
  **/
@@ -1072,10 +1091,6 @@ Details:
  *      mid level does not recognize it, then the LLD that controls
  *      the device receives the ioctl. According to recent Unix standards
  *      unsupported ioctl() 'cmd' numbers should return -ENOTTY.
- *      However the mid level returns -EINVAL for unrecognized 'cmd'
- *      numbers when this function is not supplied by the driver.
- *      Unfortunately some applications expect -EINVAL and react badly
- *      when -ENOTTY is returned; stick with -EINVAL.
  *
  *      Optionally defined in: LLD
  **/
@@ -1110,7 +1125,7 @@ Details:
  *      Optionally defined in: LLD
  **/
     int proc_info(char * buffer, char ** start, off_t offset, 
-                  int length, int hostno, int writeto1_read0)
+                  int length, int host_no, int writeto1_read0)
 
 
 /**
@@ -1120,42 +1135,42 @@ Details:
  *
  *      Returns 0 on success.
  *
- *	If there's a failure, return either:
+ *      If there's a failure, return either:
  *
- *	SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or
- *	SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full
+ *      SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or
+ *      SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full
  *
- *	On both of these returns, the mid-layer will requeue the I/O
+ *      On both of these returns, the mid-layer will requeue the I/O
  *
- *	- if the return is SCSI_MLQUEUE_DEVICE_BUSY, only that particular
- *	device will be paused, and it will be unpaused when a command to
- *	the device returns (or after a brief delay if there are no more
- *	outstanding commands to it).  Commands to other devices continue
- *	to be processed normally.
+ *      - if the return is SCSI_MLQUEUE_DEVICE_BUSY, only that particular
+ *      device will be paused, and it will be unpaused when a command to
+ *      the device returns (or after a brief delay if there are no more
+ *      outstanding commands to it).  Commands to other devices continue
+ *      to be processed normally.
  *
- *	- if the return is SCSI_MLQUEUE_HOST_BUSY, all I/O to the host
- *	is paused and will be unpaused when any command returns from
- *	the host (or after a brief delay if there are no outstanding
- *	commands to the host).
+ *      - if the return is SCSI_MLQUEUE_HOST_BUSY, all I/O to the host
+ *      is paused and will be unpaused when any command returns from
+ *      the host (or after a brief delay if there are no outstanding
+ *      commands to the host).
  *
- *	For compatibility with earlier versions of queuecommand, any
- *	other return value is treated the same as
- *	SCSI_MLQUEUE_HOST_BUSY.
+ *      For compatibility with earlier versions of queuecommand, any
+ *      other return value is treated the same as
+ *      SCSI_MLQUEUE_HOST_BUSY.
  *
- *	Other types of errors that are detected immediately may be
- *	flagged by setting scp->result to an appropriate value,
- *	invoking the 'done' callback, and then returning 0 from this
- *	function. If the command is not performed immediately (and the
- *	LLD is starting (or will start) the given command) then this
- *	function should place 0 in scp->result and return 0.
+ *      Other types of errors that are detected immediately may be
+ *      flagged by setting scp->result to an appropriate value,
+ *      invoking the 'done' callback, and then returning 0 from this
+ *      function. If the command is not performed immediately (and the
+ *      LLD is starting (or will start) the given command) then this
+ *      function should place 0 in scp->result and return 0.
  *
- *	Command ownership.  If the driver returns zero, it owns the
- *	command and must take responsibility for ensuring the 'done'
- *	callback is executed.  Note: the driver may call done before
- *	returning zero, but after it has called done, it may not
- *	return any value other than zero.  If the driver makes a
- *	non-zero return, it must not execute the command's done
- *	callback at any time.
+ *      Command ownership.  If the driver returns zero, it owns the
+ *      command and must take responsibility for ensuring the 'done'
+ *      callback is executed.  Note: the driver may call done before
+ *      returning zero, but after it has called done, it may not
+ *      return any value other than zero.  If the driver makes a
+ *      non-zero return, it must not execute the command's done
+ *      callback at any time.
  *
  *      Locks: struct Scsi_Host::host_lock held on entry (with "irqsave")
  *             and is expected to be held on return.
@@ -1317,7 +1332,12 @@ of interest:
     sg_tablesize - maximum scatter gather elements allowed by host.
                    0 implies scatter gather not supported by host
     max_sectors  - maximum number of sectors (usually 512 bytes) allowed
-                   in a single SCSI command. 0 implies no maximum.
+                   in a single SCSI command. The default value of 0 leads
+                   to a setting of SCSI_DEFAULT_MAX_SECTORS (defined in
+                   scsi_host.h) which is currently set to 1024. So for a
+                   disk the maximum transfer size is 512 KB when max_sectors
+                   is not defined. Note that this size may not be sufficient
+                   for disk firmware uploads.
     cmd_per_lun  - maximum number of commands that can be queued on devices
                    controlled by the host. Overridden by LLD calls to
                    scsi_adjust_queue_depth().
@@ -1328,6 +1348,9 @@ of interest:
                      0=>disallow SCSI command merging
     hostt        - pointer to driver's struct scsi_host_template from which
                    this struct Scsi_Host instance was spawned
+    hostt->proc_name  - name of LLD. This is the driver name that sysfs uses
+    transportt   - pointer to driver's struct scsi_transport_template instance
+                   (if any). FC and SPI transports currently supported.
     sh_list      - a double linked list of pointers to all struct Scsi_Host
                    instances (currently ordered by ascending host_no)
     my_devices   - a double linked list of pointers to struct scsi_device 
@@ -1335,7 +1358,8 @@ of interest:
     hostdata[0]  - area reserved for LLD at end of struct Scsi_Host. Size
                    is set by the second argument (named 'xtr_bytes') to
                    scsi_host_alloc() or scsi_register().
-The structure is defined in include/scsi/scsi_host.h
+
+The scsi_host structure is defined in include/scsi/scsi_host.h
 
 struct scsi_device
 ------------------
@@ -1347,11 +1371,66 @@ The structure is defined in include/scsi/scsi_device.h
 struct scsi_cmnd
 ----------------
 Instances of this structure convey SCSI commands to the LLD and responses
-back to the mid level. The SCSI mid level will ensure that no more SCSI 
-commands become queued against the LLD than are indicated by 
-scsi_adjust_queue_depth() (or struct Scsi_Host::cmd_per_lun). There will 
-be at least one instance of struct scsi_cmnd available for each SCSI device. 
-The structure is defined in include/scsi/scsi_cmnd.h
+back to the mid level. The SCSI mid level will ensure that no more SCSI
+commands become queued against the LLD than are indicated by
+scsi_adjust_queue_depth() (or struct Scsi_Host::cmd_per_lun). There will
+be at least one instance of struct scsi_cmnd available for each SCSI device.
+Members of interest:
+    cmnd         - array containing SCSI command
+    cmnd_len     - length (in bytes) of SCSI command
+    sc_data_direction - direction of data transfer in data phase. See
+                "enum dma_data_direction" in include/linux/dma-mapping.h
+    request_bufflen - number of data bytes to transfer (0 if no data phase)
+    use_sg       - ==0 -> no scatter gather list, hence transfer data
+                          to/from request_buffer
+                 - >0 ->  scatter gather list (actually an array) in
+                          request_buffer with use_sg elements
+    request_buffer - either contains data buffer or scatter gather list
+                     depending on the setting of use_sg. Scatter gather
+                     elements are defined by 'struct scatterlist' found
+                     in include/asm/scatterlist.h .
+    done         - function pointer that should be invoked by LLD when the
+                   SCSI command is completed (successfully or otherwise).
+                   Should only be called by an LLD if the LLD has accepted
+                   the command (i.e. queuecommand() returned or will return
+                   0). The LLD may invoke 'done'  prior to queuecommand()
+                   finishing.
+    result       - should be set by LLD prior to calling 'done'. A value
+                   of 0 implies a successfully completed command (and all
+                   data (if any) has been transferred to or from the SCSI
+                   target device). 'result' is a 32 bit unsigned integer that
+                   can be viewed as 4 related bytes. The SCSI status value is
+                   in the LSB. See include/scsi/scsi.h status_byte(),
+                   msg_byte(), host_byte() and driver_byte() macros and
+                   related constants.
+    sense_buffer - an array (maximum size: SCSI_SENSE_BUFFERSIZE bytes) that
+                   should be written when the SCSI status (LSB of 'result')
+                   is set to CHECK_CONDITION (2). When CHECK_CONDITION is
+                   set, if the top nibble of sense_buffer[0] has the value 7
+                   then the mid level will assume the sense_buffer array
+                   contains a valid SCSI sense buffer; otherwise the mid
+                   level will issue a REQUEST_SENSE SCSI command to
+                   retrieve the sense buffer. The latter strategy is error
+                   prone in the presence of command queuing so the LLD should
+                   always "auto-sense".
+    device       - pointer to scsi_device object that this command is
+                   associated with.
+    resid        - an LLD should set this signed integer to the requested
+                   transfer length (i.e. 'request_bufflen') less the number
+                   of bytes that are actually transferred. 'resid' is
+                   preset to 0 so an LLD can ignore it if it cannot detect
+                   underruns (overruns should be rare). If possible an LLD
+                   should set 'resid' prior to invoking 'done'. The most
+                   interesting case is data transfers from a SCSI target
+                   device device (i.e. READs) that underrun. 
+    underflow    - LLD should place (DID_ERROR << 16) in 'result' if
+                   actual number of bytes transferred is less than this
+                   figure. Not many LLDs implement this check and some that
+                   do just output an error message to the log rather than
+                   report a DID_ERROR. Better for an LLD to implement
+                   'resid'.
+
+The scsi_cmnd structure is defined in include/scsi/scsi_cmnd.h
 
 
 Locks
@@ -1420,15 +1499,16 @@ to support it.
 Credits
 =======
 The following people have contributed to this document:
-        Mike Anderson <andmike@us.ibm.com>
-        James Bottomley <James.Bottomley@steeleye.com> 
-        Patrick Mansfield <patmans@us.ibm.com> 
-        Christoph Hellwig <hch@infradead.org>
-        Doug Ledford <dledford@redhat.com>
-        Andries Brouwer <Andries.Brouwer@cwi.nl>
-        Randy Dunlap <rddunlap@osdl.org>
+        Mike Anderson <andmike at us dot ibm dot com>
+        James Bottomley <James dot Bottomley at steeleye dot com> 
+        Patrick Mansfield <patmans at us dot ibm dot com> 
+        Christoph Hellwig <hch at infradead dot org>
+        Doug Ledford <dledford at redhat dot com>
+        Andries Brouwer <Andries dot Brouwer at cwi dot nl>
+        Randy Dunlap <rddunlap at osdl dot org>
+        Alan Stern <stern at rowland dot harvard dot edu>
 
 
 Douglas Gilbert
-dgilbert@interlog.com
-29th August 2003
+dgilbert at interlog dot com
+25th August 2004
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 10c5bed26..a0c42609f 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -188,6 +188,13 @@ Module parameters
 
     This module supports up to 8 cards and autoprobe.
 
+  Module snd-atiixp-modem
+  -----------------------
+
+    Module for ATI IXP 150/200/250 AC97 modem controllers.
+
+    Module supports up to 8 cards.
+
   Module snd-au8810, snd-au8820, snd-au8830
   -----------------------------------------
 
@@ -516,6 +523,13 @@ Module parameters
 
     Module for ForteMedia FM801 based PCI soundcards.
 
+    tea575x_tuner       - Enable TEA575x tuner
+                          - 1 = MediaForte 256-PCS
+                          - 2 = MediaForte 256-PCPR
+                          - 3 = MediaForte 64-PCR  
+                          - High 16-bits are video (radio) device number + 1
+                          - example: 0x10002 (MediaForte 256-PCPR, device 1)
+
     Module supports up to 8 cards and autoprobe.
     
   Module snd-gusclassic
@@ -613,7 +627,7 @@ Module parameters
     model       - Use the given board model, one of the following:
 		  delta1010, dio2496, delta66, delta44, audiophile, delta410,
 		  delta1010lt, vx442, ewx2496, ews88mt, ews88mt_new, ews88d,
-		  dmx6fire, dsp24, dsp24_71, ez8
+		  dmx6fire, dsp24, dsp24_value, dsp24_71, ez8
     omni	- Omni I/O support for MidiMan M-Audio Delta44/66
     cs8427_timeout - reset timeout for the CS8427 chip (S/PDIF transciever)
                      in msec resolution, default value is 500 (0.5 sec)
@@ -631,7 +645,8 @@ Module parameters
 			* TerraTec Aureon Sky-5.1, Space-7.1
 
     model       - Use the given board model, one of the following:
-		  revo71, amp2000, prodigy71, aureon51, aureon71
+		  revo71, amp2000, prodigy71, aureon51, aureon71,
+		  k8x800
 
     Module supports up to 8 cards and autoprobe.
 
@@ -655,6 +670,8 @@ Module parameters
                      2 = swap headphone and master controls
                      3 = for AD1985, turn on OMS bit and use headphone
                      4 = for ALC65x, turn on the jack sense mode
+    buggy_irq      - Enable workaround for buggy interrupts on some
+                     motherboards (default off)
 
     Module supports autoprobe and multiple bus-master chips (max 8).
 
@@ -1103,6 +1120,16 @@ Module parameters
 
     This module supports up to 8 cards, autoprobe and hotplugging.
 
+  Module snd-usb-usx2y
+  --------------------
+
+    Module for Tascam USB US-122, US-224 and US-428 devices.
+
+    This module supports up to 8 cards, autoprobe and hotplugging.
+
+    Note: you need to load the firmware via usx2yloader utility included
+          in alsa-tools and alsa-firmware packages.
+
   Module snd-via82xx
   ------------------
 
diff --git a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
index 32fdc1545..1f3ae3e32 100644
--- a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
+++ b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
@@ -47,7 +47,6 @@
      </sect1>
      <sect1><title>Memory Management Helpers</title>
 !Esound/core/memory.c
-!Iinclude/sound/sndmagic.h
 !Esound/core/memalloc.c
      </sect1>
   </chapter>
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index fae0c98cf..557786cc0 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -18,8 +18,8 @@
       </affiliation>
      </author>
 
-     <date>Mar. 6, 2004</date>
-     <edition>0.3.1</edition>
+     <date>July 11, 2004</date>
+     <edition>0.3.3</edition>
 
     <abstract>
       <para>
@@ -395,7 +395,6 @@
   #include <linux/pci.h>
   #include <linux/slab.h>
   #include <sound/core.h>
-  #define SNDRV_GET_ID
   #include <sound/initval.h>
 
   // module parameters (see "Module Parameters")
@@ -411,10 +410,6 @@
           // "PCI Resource Managements"
   };
 
-  // this should be go into <sound/sndmagic.h>
-  // (see "Management of Cards and Components")
-  #define mychip_t_magic        0xa15a4501
-
   // chip-specific destructor
   // (see "PCI Resource Managements")
   static int snd_mychip_free(mychip_t *chip)
@@ -426,8 +421,7 @@
   // (see "Management of Cards and Components")
   static int snd_mychip_dev_free(snd_device_t *device)
   {
-          mychip_t *chip = snd_magic_cast(mychip_t,
-                  device->device_data, return -ENXIO);
+          mychip_t *chip = device->device_data;
           return snd_mychip_free(chip);
   }
 
@@ -448,8 +442,8 @@
           // check PCI availability here
           // (see "PCI Resource Managements")
 
-          // allocate a chip-specific data with magic-alloc
-          chip = snd_magic_kcalloc(mychip_t, 0, GFP_KERNEL);
+          // allocate a chip-specific data with zero filled
+          chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
           if (chip == NULL)
                   return -ENOMEM;
 
@@ -744,7 +738,6 @@
   #include <linux/pci.h>
   #include <linux/slab.h>
   #include <sound/core.h>
-  #define SNDRV_GET_ID
   #include <sound/initval.h>
 ]]>
           </programlisting>
@@ -905,13 +898,6 @@
         </informalexample>
       </para>
 
-      <para>
-        You might have objections against such a typedef, but this
-      typedef is necessary if you use a <quote>magic-cast</quote>
-      (explained <link
-      linkend="card-management-chip-what-advantage"><citetitle>later</citetitle></link>). 
-      </para>
-
       <para>
         In general, there are two ways to allocate the chip record.
       </para>
@@ -943,9 +929,8 @@
             </programlisting>
           </informalexample>
 
-          With this method, you don't have to allocate twice. But you
-        cannot use <quote>magic-cast</quote> for this record pointer,
-        instead. 
+          With this method, you don't have to allocate twice.
+          The record is released together with the card instance.
         </para>
       </section>
 
@@ -956,7 +941,7 @@
           After allocating a card instance via
           <function>snd_card_new()</function> (with
           <constant>NULL</constant> on the 4th arg), call
-          <function>snd_magic_kcalloc()</function>. 
+          <function>kcalloc()</function>. 
 
           <informalexample>
             <programlisting>
@@ -965,13 +950,10 @@
   mychip_t *chip;
   card = snd_card_new(index[dev], id[dev], THIS_MODULE, NULL);
   .....
-  chip = snd_magic_kcalloc(mychip_t, 0, GFP_KERNEL);
+  chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 ]]>
             </programlisting>
           </informalexample>
-
-          Once when the record is allocated via snd_magic stuff, you
-        can use <quote>magic-cast</quote> for the void pointer. 
         </para>
 
         <para>
@@ -1002,21 +984,6 @@
           </informalexample>
         </para>
 
-        <para>
-          Also, you need to define a magic-value for <type>mychip_t</type>.
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  #define mychip_t_magic        0xa15a4501
-]]>
-            </programlisting>
-          </informalexample>
-	(the detail will be described in the
-	<link linkend="card-management-chip-what-advantage"><citetitle>
-	next</citetitle></link> subsection).
-	</para>
-
         <para>
           Next, initialize the fields, and register this chip
           record as a low-level device with a specified
@@ -1045,8 +1012,7 @@
 <![CDATA[
   static int snd_mychip_dev_free(snd_device_t *device)
   {
-          mychip_t *chip = snd_magic_cast(mychip_t, device->device_data,
-                                          return -ENXIO);
+          mychip_t *chip = device->device_data;
           return snd_mychip_free(chip);
   }
 ]]>
@@ -1056,126 +1022,6 @@
           where <function>snd_mychip_free()</function> is the real destructor.
         </para>
       </section>
-
-      <section id="card-management-chip-what-advantage">
-        <title>Not a magic but a logic</title>
-
-        <para>Now, you might have a question: What is the advantage of the
-        second method?  Obviously, it looks far more complicated.</para> 
-        <para>
-          As I wrote many times, the second method allows a
-        <quote>magic-cast</quote> for <type>mychip_t</type>. If you
-        have a void pointer (such as
-        pcm-&gt;private_data), the pointer type
-        is unknown at the compile time, and you cannot know even if a
-        wrong pointer type is passed. The compiler would accept
-        it. The magic-cast checks the pointer type at the runtime (and
-        whether it's a null pointer, too). Hence, the cast will be
-        much safer and good for debugging. 
-        </para>
-
-	<para>
-	As you have already seen, allocation with a magic-header can
-	be done via <function>snd_magic_kmalloc()</function> or
-	<function>snd_magic_kcalloc()</function>.
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  mychip_t *chip;
-  chip = snd_magic_kmalloc(mychip_t, 0, GFP_KERNEL);
-  chip = snd_magic_kcalloc(mychip_t, 0, GFP_KERNEL);
-]]>
-            </programlisting>
-          </informalexample>
-
-        The difference of these two functions is whether the area is
-	zero-cleared (<function>kcalloc</function>) or not
-	(<function>kmalloc</function>).
-	</para>
-
-	<para>
-	The first argument of the allocator is the type of the
-	record.  The magic-constant has to be defined for this type
-	beforehand.  In this case, we'll need to define
-	<constant>mychip_t_magic</constant>, for example, as already
-	seen,
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  #define mychip_t_magic        0xa15a4501
-]]>
-            </programlisting>
-          </informalexample>
-
-        The value is arbitrary but should be unique.
-        This is usually defined in
-        <filename>&lt;include/sndmagic.h&gt;</filename> or
-        <filename>&lt;include/amagic.h&gt;</filename> for alsa-driver tree,
-        but you may define it locally in the code at the early
-        development stage, since changing
-        <filename>sndmagic.h</filename> will lead to the recompilation
-        of the whole driver codes.
-        </para>
-
-	<para>
-	The second argument is the extra-data length.  It is usually
-        zero.  The third argument is the flags to be passed to kernel
-        memory allocator, <constant>GFP_XXX</constant>.  Normally,
-        <constant>GFP_KERNEL</constant> is passed.
-	</para>
-
-        <para>
-          For casting a pointer, use
-          <function>snd_magic_cast()</function> macro:
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  mychip_t *chip = snd_magic_cast(mychip_t, source_pointer, action);
-]]>
-            </programlisting>
-          </informalexample>
-
-        where <parameter>source_pointer</parameter> is the pointer to
-        be casted (e.g. pcm-&gt;private_data), and
-        <parameter>action</parameter> is the action to do if the cast
-        fails (e.g. return <constant>-EINVAL</constant>). 
-        </para>
-
-	<para>
-	For releasing the magic-allocated data, you need to call
-        <function>snd_magic_kfree()</function> function instead of
-        <function>kfree()</function>.
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  snd_magic_kfree(chip);
-]]>
-            </programlisting>
-          </informalexample>
-	</para>
-
-	<para>
-	If you call <function>kfree()</function> for the
-	magic-allocated value, it will lead to memory leaks.
-	When the ALSA drivers are compiled with
-	<constant>CONFIG_SND_DEBUG_MEMORY</constant> kernel config (or
-	configured with <option>--with-debug=full</option>), the
-	non-matching free will be checked and you'll see warning
-	messages.
-	</para>
-
-        <para>
-          If you are 100% sure that your code is bug-free, you can
-          compile the driver without
-          <constant>CONFIG_SND_DEBUG_MEMORY</constant> kernel config,
-          so that the magic-allocator and the magic-cast will be
-          replaced to the normal kmalloc and cast.
-        </para>
-      </section>
     </section>
 
     <section id="card-management-registration">
@@ -1238,8 +1084,6 @@
           struct pci_dev *pci;
 
           unsigned long port;
-          struct resource *res_port;
-
           int irq;
   };
 
@@ -1248,16 +1092,13 @@
           // disable hardware here if any
           // (not implemented in this document)
 
-          // release the i/o port
-          if (chip->res_port) {
-                  release_resource(chip->res_port);
-                  kfree_nocheck(chip->res_port);
-          }
           // release the irq
           if (chip->irq >= 0)
                   free_irq(chip->irq, (void *)chip);
+          // release the i/o ports
+          pci_release_regions(chip->pci);
           // release the data
-          snd_magic_kfree(chip);
+          kfree(chip);
           return 0;
   }
 
@@ -1283,7 +1124,7 @@
                   return -ENXIO;
           }
 
-          chip = snd_magic_kcalloc(mychip_t, 0, GFP_KERNEL);
+          chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
           if (chip == NULL)
                   return -ENOMEM;
 
@@ -1293,18 +1134,16 @@
           chip->irq = -1;
 
           // (1) PCI resource allocation
-          chip->port = pci_resource_start(pci, 0);
-          if ((chip->res_port = request_region(chip->port, 8,
-                                                 "My Chip")) == NULL) { 
-                  snd_mychip_free(chip);
-                  printk(KERN_ERR "cannot allocate the port\n");
-                  return -EBUSY;
+          if ((err = pci_request_regions(pci, "My Chip")) < 0) {
+                  kfree(chip);
+                  return err;
           }
+          chip->port = pci_resource_start(pci, 0);
           if (request_irq(pci->irq, snd_mychip_interrupt,
                           SA_INTERRUPT|SA_SHIRQ, "My Chip",
                           (void *)chip)) {
+                  printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
                   snd_mychip_free(chip);
-                  printk(KERN_ERR "cannot grab irq\n");
                   return -EBUSY;
           }
           chip->irq = pci->irq;
@@ -1420,8 +1259,6 @@
           snd_card_t *card;
 
           unsigned long port;
-          struct resource *res_port;
-
           int irq;
   };
 ]]>
@@ -1436,7 +1273,7 @@
       need to initialize this number as -1 before actual allocation,
       since irq 0 is valid. The port address and its resource pointer
       can be initialized as null by
-      <function>snd_magic_kcalloc()</function> automatically, so you
+      <function>kcalloc()</function> automatically, so you
       don't have to take care of resetting them. 
       </para>
 
@@ -1446,14 +1283,11 @@
         <informalexample>
           <programlisting>
 <![CDATA[
-  chip->port = pci_resource_start(pci, 0);
-  if ((chip->res_port = request_region(chip->port, 8,
-                                       "My Chip")) == NULL) { 
-          printk(KERN_ERR "cannot allocate the port 0x%lx\n",
-                 chip->port);
-          snd_mychip_free(chip);
-          return -EBUSY;
+  if ((err = pci_request_regions(pci, "My Chip")) < 0) { 
+          kfree(chip);
+          return err;
   }
+  chip->port = pci_resource_start(pci, 0);
 ]]>
           </programlisting>
         </informalexample>
@@ -1477,8 +1311,8 @@
   if (request_irq(pci->irq, snd_mychip_interrupt,
                   SA_INTERRUPT|SA_SHIRQ, "My Chip",
                   (void *)chip)) {
-          snd_mychip_free(chip);
           printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
+          snd_mychip_free(chip);
           return -EBUSY;
   }
   chip->irq = pci->irq;
@@ -1517,16 +1351,13 @@
   static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
                                           struct pt_regs *regs)
   {
-          mychip_t *chip = snd_magic_cast(mychip_t, dev_id, return);
+          mychip_t *chip = dev_id;
           ....
           return IRQ_HANDLED;
   }
 ]]>
           </programlisting>
         </informalexample>
-
-        Again the magic-cast is used here to get the correct pointer
-      from the second argument. 
       </para>
 
       <para>
@@ -1538,7 +1369,45 @@
 
       <para>
         For releasing the resources, <quote>check-and-release</quote>
-        method is a safer way. For the i/o port, do like this: 
+        method is a safer way. For the interrupt, do like this: 
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  if (chip->irq >= 0)
+          free_irq(chip->irq, (void *)chip);
+]]>
+          </programlisting>
+        </informalexample>
+
+        Since the irq number can start from 0, you should initialize
+        chip-&gt;irq with a negative value (e.g. -1), so that you can
+        check the validity of the irq number as above.
+      </para>
+
+      <para>
+        When you requested I/O ports or memory regions via
+	<function>pci_request_region()</function> or
+	<function>pci_request_regions()</function> like this example,
+	release the resource(s) using the corresponding function,
+	<function>pci_release_region()</function> or
+	<function>pci_release_regions()</function>.
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  pci_release_regions(chip->pci);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+	When you requested manually via <function>request_region()</function>
+	or <function>request_mem_region</function>, you can release it via
+	<function>release_resource()</function>.  Suppose that you keep
+	the resource pointer returned from <function>request_region()</function>
+	in chip-&gt;res_port, the release procedure looks like below:
 
         <informalexample>
           <programlisting>
@@ -1550,10 +1419,8 @@
 ]]>
           </programlisting>
         </informalexample>
-      </para>
 
-      <para>
-        As you can see, the i/o resource pointer is also to be freed
+      As you can see, the resource pointer is also to be freed
       via <function>kfree_nocheck()</function> after
       <function>release_resource()</function> is called. You
       cannot use <function>kfree()</function> here, because on ALSA,
@@ -1567,35 +1434,19 @@
       </para>
 
       <para>
-        For releasing the interrupt, do like this:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  if (chip->irq >= 0)
-          free_irq(chip->irq, (void *)chip);
-]]>
-          </programlisting>
-        </informalexample>
-
         And finally, release the chip-specific record.
 
         <informalexample>
           <programlisting>
 <![CDATA[
-  snd_magic_kfree(chip);
+  kfree(chip);
 ]]>
           </programlisting>
         </informalexample>
       </para>
 
       <para>
-        The chip instance is freed via
-      <function>snd_magic_kfree()</function>. Please use this function
-      for the object allocated by
-      <function>snd_magic_kmalloc()</function>. If you free it with
-      <function>kfree()</function>, it won't work properly and will
-      result in the memory leak. Also, again, remember that you cannot
+      Again, remember that you cannot
       set <parameter>__devexit</parameter> prefix for this destructor. 
       </para>
 
@@ -1629,7 +1480,6 @@
           ....
           unsigned long iobase_phys;
           unsigned long iobase_virt;
-          struct resource *res_iobase;
   };
 ]]>
           </programlisting>
@@ -1640,15 +1490,14 @@
         <informalexample>
           <programlisting>
 <![CDATA[
+  if ((err = pci_request_regions(pci, "My Chip")) < 0) {
+          kfree(chip);
+          return err;
+  }
   chip->iobase_phys = pci_resource_start(pci, 0);
   chip->iobase_virt = (unsigned long)
-                      ioremap_nocache(chip->iobase_phys, 512);
-  if ((chip->res_port = request_mem_region(chip->iobase_phys, 512,
-                                           "My Chip")) == NULL) {
-          printk(KERN_ERR "cannot allocate the memory region\n");
-          snd_mychip_free(chip);
-          return -EBUSY;
-  }
+                      ioremap_nocache(chip->iobase_phys,
+                                      pci_resource_len(pci, 0));
 ]]>
           </programlisting>
         </informalexample>
@@ -1663,10 +1512,8 @@
           ....
           if (chip->iobase_virt)
                   iounmap((void *)chip->iobase_virt);
-          if (chip->res_iobase) {
-                  release_resource(chip->res_iobase);
-                  kfree_nocheck(chip->res_iobase);
-          }
+          ....
+          pci_release_regions(chip->pci);
           ....
   }
 ]]>
@@ -1857,9 +1704,6 @@
   #include <sound/pcm.h>
   ....
 
-  #define chip_t mychip_t
-  ....
-
   /* hardware definition */
   static snd_pcm_hardware_t snd_mychip_playback_hw = {
           .info = (SNDRV_PCM_INFO_MMAP |
@@ -2224,8 +2068,7 @@
 <![CDATA[
   static void mychip_pcm_free(snd_pcm_t *pcm)
   {
-          mychip_t *chip = snd_magic_cast(mychip_t,
-                                    pcm->private_data, return);
+          mychip_t *chip = snd_pcm_chip(pcm);
           // free your own data
           kfree(chip->my_private_pcm_data);
           // do what you like else...
@@ -2653,8 +2496,11 @@ struct _snd_pcm_runtime {
 	done in
 	<link linkend="pcm-interface-operators-open-callback"><citetitle>
 	the open callback</citetitle></link>.
-        Since it's a void pointer, you should use magic-kmalloc and
-	magic-cast for such an object. 
+	Don't mix this with <constant>pcm-&gt;private_data</constant>.
+	The <constant>pcm-&gt;private_data</constant> usually points the
+	chip instance assigned statically at the creation of PCM, while the 
+	<constant>runtime-&gt;private_data</constant> points a dynamic
+	data created at the PCM open callback.
 
           <informalexample>
             <programlisting>
@@ -2663,7 +2509,7 @@ struct _snd_pcm_runtime {
   {
           my_pcm_data_t *data;
           ....
-          data = snd_magic_kmalloc(my_pcm_data_t, 0, GFP_KERNEL);
+          data = kmalloc(sizeof(*data), GFP_KERNEL);
           substream->runtime->private_data = data;
           ....
   }
@@ -2710,8 +2556,6 @@ struct _snd_pcm_runtime {
         <informalexample>
           <programlisting>
 <![CDATA[
-  #define chip_t mychip_t
-
   int xxx() {
           mychip_t *chip = snd_pcm_substream_chip(substream);
           ....
@@ -2719,13 +2563,14 @@ struct _snd_pcm_runtime {
 ]]>
           </programlisting>
         </informalexample>
-      </para>
 
-      <para>
-        It's expanded with a magic-cast, so the cast-error is
-      automatically checked. You should define <type>chip_t</type> at
-      the beginning of the code, since this will be referred in many
-      places of pcm and control interfaces. 
+	The macro reads <constant>substream-&gt;private_data</constant>,
+	which is a copy of <constant>pcm-&gt;private_data</constant>.
+	You can override the former if you need to assign different data
+	records per PCM substream.  For example, cmi8330 driver assigns
+	different private_data for playback and capture directions,
+	because it uses two different codecs (SB- and AD-compatible) for
+	different directions.
       </para>
 
       <section id="pcm-interface-operators-open-callback">
@@ -2803,7 +2648,7 @@ struct _snd_pcm_runtime {
   static int snd_xxx_close(snd_pcm_substream_t *substream)
   {
           ....
-          snd_magic_kfree(substream->runtime->private_data);
+          kfree(substream->runtime->private_data);
           ....
   }
 ]]>
@@ -2887,10 +2732,10 @@ struct _snd_pcm_runtime {
         <para>
           Another note is that this callback is non-atomic
         (schedulable). This is important, because the
-        <structfield>prepare</structfield> callback 
+        <structfield>trigger</structfield> callback 
         is atomic (non-schedulable). That is, mutex or any
-        schedule-related functions are available only in
-        <structfield>hw_params</structfield> callback. 
+        schedule-related functions are not available in
+        <structfield>trigger</structfield> callback.
 	Please see the subsection
 	<link linkend="pcm-interface-atomicity"><citetitle>
 	Atomicity</citetitle></link> for details.
@@ -2956,7 +2801,8 @@ struct _snd_pcm_runtime {
         </para>
 
         <para>
-          As mentioned above, this callback is atomic.
+	Note that this callback became non-atomic since the recent version.
+	You can use schedule-related fucntions safely in this callback now.
         </para>
 
         <para>
@@ -3041,7 +2887,12 @@ struct _snd_pcm_runtime {
         </para>
 
         <para>
-          This callback is also atomic.
+          As mentioned, this callback is atomic.  You cannot call
+	  the function going to sleep.
+	  The trigger callback should be as minimal as possible,
+	  just really triggering the DMA.  The other stuff should be
+	  initialized hw_params and prepare callbacks properly
+	  beforehand.
         </para>
       </section>
 
@@ -3176,7 +3027,7 @@ struct _snd_pcm_runtime {
   static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
                                           struct pt_regs *regs)
   {
-          mychip_t *chip = snd_magic_cast(mychip_t, dev_id, return);
+          mychip_t *chip = dev_id;
           spin_lock(&chip->lock);
           ....
           if (pcm_irq_invoked(chip)) {
@@ -3220,7 +3071,7 @@ struct _snd_pcm_runtime {
   static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id,
                                           struct pt_regs *regs)
   {
-          mychip_t *chip = snd_magic_cast(mychip_t, dev_id, return);
+          mychip_t *chip = dev_id;
           spin_lock(&chip->lock);
           ....
           if (pcm_irq_invoked(chip)) {
@@ -3287,7 +3138,7 @@ struct _snd_pcm_runtime {
       <para>
       As already seen, some pcm callbacks are atomic and some are
       not.  For example, <parameter>hw_params</parameter> callback is
-      non-atomic, while <parameter>prepare</parameter> callback is
+      non-atomic, while <parameter>trigger</parameter> callback is
       atomic.  This means, the latter is called already in a spinlock
       held by the PCM middle layer. Please take this atomicity into
       account when you use a spinlock or a semaphore in the callbacks.
@@ -3298,7 +3149,7 @@ struct _snd_pcm_runtime {
       <function>schedule</function> or go to
       <function>sleep</function>.  The semaphore and mutex do sleep,
       and hence they cannot be used inside the atomic callbacks
-      (e.g. <parameter>prepare</parameter> callback).
+      (e.g. <parameter>trigger</parameter> callback).
       For taking a certain delay in such a callback, please use
       <function>udelay()</function> or <function>mdelay()</function>.
       </para>
@@ -3325,7 +3176,7 @@ struct _snd_pcm_runtime {
   static unsigned int rates[] =
           {4000, 10000, 22050, 44100};
   static snd_pcm_hw_constraint_list_t constraints_rates = {
-          .count = sizeof(rates) / sizeof(rates[0]),
+          .count = ARRAY_SIZE(rates),
           .list = rates,
           .mask = 0,
   };
@@ -3988,8 +3839,7 @@ struct _snd_pcm_runtime {
   static unsigned short snd_mychip_ac97_read(ac97_t *ac97,
                                              unsigned short reg)
   {
-          mychip_t *chip = snd_magic_cast(mychip_t,
-                                   ac97->private_data, return 0);
+          mychip_t *chip = ac97->private_data;
           ....
           // read a register value here from the codec
           return the_register_value;
@@ -3998,26 +3848,26 @@ struct _snd_pcm_runtime {
   static void snd_mychip_ac97_write(ac97_t *ac97,
                                    unsigned short reg, unsigned short val)
   {
-          mychip_t *chip = snd_magic_cast(mychip_t,
-                                   ac97->private_data, return 0);
+          mychip_t *chip = ac97->private_data;
           ....
           // write the given register value to the codec
   }
 
   static int snd_mychip_ac97(mychip_t *chip)
   {
-          ac97_bus_t bus, *pbus;
-          ac97_t ac97;
+          ac97_bus_t *bus;
+          ac97_template_t ac97;
           int err;
+          static ac97_bus_ops_t ops = {
+                  .write = snd_mychip_ac97_write,
+                  .read = snd_mychip_ac97_read,
+          };
 
-          memset(&bus, 0, sizeof(bus));
-          bus.write = snd_mychip_ac97_write;
-          bus.read = snd_mychip_ac97_read;
-          if ((err = snd_ac97_bus(chip->card, &bus, &pbus)) < 0)
+          if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus)) < 0)
                   return err;
           memset(&ac97, 0, sizeof(ac97));
           ac97.private_data = chip;
-          return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
+          return snd_ac97_mixer(bus, &ac97, &chip->ac97);
   }
 
 ]]>
@@ -4030,18 +3880,18 @@ struct _snd_pcm_runtime {
       <title>Constructor</title>
       <para>
         For creating an ac97 instance, first call <function>snd_ac97_bus</function>
-      with <type>ac97_bus_t</type> record including callback functions.
+      with an <type>ac97_bus_ops_t</type> record with callback functions.
 
         <informalexample>
           <programlisting>
 <![CDATA[
-  ac97_bus_t bus, *pbus;
-  int err;
+  ac97_bus_t *bus;
+  static ac97_bus_ops_t ops = {
+        .write = snd_mychip_ac97_write,
+        .read = snd_mychip_ac97_read,
+  };
 
-  memset(&bus, 0, sizeof(bus));
-  bus.write = snd_mychip_ac97_write;
-  bus.read = snd_mychip_ac97_read;
-  snd_ac97_bus(card, &bus, &pbus);
+  snd_ac97_bus(card, 0, &ops, NULL, &pbus);
 ]]>
           </programlisting>
         </informalexample>
@@ -4050,13 +3900,13 @@ struct _snd_pcm_runtime {
       </para>
 
       <para>
-      And then call <function>snd_ac97_mixer()</function> with an <type>ac97_t</type>
+      And then call <function>snd_ac97_mixer()</function> with an <type>ac97_template_t</type>
       record together with the bus pointer created above.
 
         <informalexample>
           <programlisting>
 <![CDATA[
-  ac97_t ac97;
+  ac97_template_t ac97;
   int err;
 
   memset(&ac97, 0, sizeof(ac97));
@@ -4096,8 +3946,7 @@ struct _snd_pcm_runtime {
   static unsigned short snd_mychip_ac97_read(ac97_t *ac97,
                                              unsigned short reg)
   {
-          mychip_t *chip = snd_magic_cast(mychip_t,
-                                   ac97->private_data, return 0);
+          mychip_t *chip = ac97->private_data;
           ....
           return the_register_value;
   }
@@ -4241,7 +4090,7 @@ struct _snd_pcm_runtime {
       <para>
         On some chip, the clock of the codec isn't 48000 but using a
       PCI clock (to save a quartz!). In this case, change the field
-      ac97-&gt;clock to the corresponding
+      bus-&gt;clock to the corresponding
       value. For example, intel8x0 
       and es1968 drivers have the auto-measurement function of the
       clock. 
@@ -4375,7 +4224,7 @@ struct _snd_pcm_runtime {
           <programlisting>
 <![CDATA[
   mpu401_t *mpu;
-  mpu = snd_magic_cast(mpu401_t, rmidi->private_data, );
+  mpu = rmidi->private_data;
 ]]>
           </programlisting>
         </informalexample>
@@ -4546,16 +4395,15 @@ struct _snd_pcm_runtime {
 
       <para>
         You can then pass any pointer value to the
-        <parameter>private_data</parameter>. Again, it should be a
-        magic-allocated record, so that the cast can be checked more
-        safely. If you assign a private data, you should define the
+        <parameter>private_data</parameter>.
+        If you assign a private data, you should define the
         destructor, too. The destructor function is set to
         <structfield>private_free</structfield> field.  
 
         <informalexample>
           <programlisting>
 <![CDATA[
-  mydata_t *p = snd_magic_kmalloc(mydata_t, 0, GFP_KERNEL);
+  mydata_t *p = kmalloc(sizeof(*p), GFP_KERNEL);
   hw->private_data = p;
   hw->private_free = mydata_free;
 ]]>
@@ -4569,9 +4417,8 @@ struct _snd_pcm_runtime {
 <![CDATA[
   static void mydata_free(snd_hwdep_t *hw)
   {
-          mydata_t *p = snd_magic_cast(mydata_csp_t,
-                                       hw->private_data, return);
-          snd_magic_kfree(p);
+          mydata_t *p = hw->private_data;
+          kfree(p);
   }
 ]]>
           </programlisting>
@@ -5097,8 +4944,7 @@ struct _snd_pcm_runtime {
   static void my_proc_read(snd_info_entry_t *entry,
                            snd_info_buffer_t *buffer)
   {
-          chip_t *cm = snd_magic_cast(mychip_t,
-                                  entry->private_data, return);
+          chip_t *chip = entry->private_data;
 
           snd_iprintf(buffer, "This is my chip!\n");
           snd_iprintf(buffer, "Port = %ld\n", chip->port);
@@ -5267,8 +5113,7 @@ struct _snd_pcm_runtime {
   static int mychip_suspend(snd_card_t *card, unsigned int state)
   {
           // (1)
-          mychip_t *chip = snd_magic_cast(mychip_t, card->pm_private_data,
-                                          return -ENXIO);
+          mychip_t *chip = card->pm_private_data;
           // (2)
           snd_pcm_suspend_all(chip->pcm);
           // (3)
@@ -5310,8 +5155,7 @@ struct _snd_pcm_runtime {
   static void mychip_resume(mychip_t *chip)
   {
           // (1)
-          mychip_t *chip = snd_magic_cast(mychip_t, card->pm_private_data,
-                                          return -ENXIO);
+          mychip_t *chip = card->pm_private_data;
           // (2)
           pci_enable_device(chip->pci);
           // (3)
@@ -5428,19 +5272,7 @@ struct _snd_pcm_runtime {
       The module parameters must be declared with the standard
     <function>module_param()()</function>,
     <function>module_param_array()()</function> and
-    <function>MODULE_PARM_DESC()</function> macros. The ALSA provides
-    an additional macro, <function>MODULE_PARM_SYNTAX()</function>,
-    for describing its syntax. The strings will be written to
-    <filename>/lib/modules/XXX/modules.generic_string</filename>
-    file. 
-    </para>
-
-    <para>
-      For convenience, the typical string arguments given to
-    <function>MODULE_PARM_SYNTAX()</function> are defined in
-    <filename>&lt;sound/initval.h&gt;</filename>, such as
-    <constant>SNDRV_ID_DESC</constant> or
-    <constant>SNDRV_ENABLED</constant>.
+    <function>MODULE_PARM_DESC()</function> macros.
     </para>
 
     <para>
@@ -5454,13 +5286,10 @@ struct _snd_pcm_runtime {
   static int boot_devs;
   module_param_array(index, int, boot_devs, 0444);
   MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
-  MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
   module_param_array(id, charp, boot_devs, 0444);
   MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
-  MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
   module_param_array(enable, bool, boot_devs, 0444);
   MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
-  MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 ]]>
         </programlisting>
       </informalexample>
@@ -5479,9 +5308,8 @@ struct _snd_pcm_runtime {
         <programlisting>
 <![CDATA[
   MODULE_DESCRIPTION("My Chip");
-  MODULE_CLASSES("{sound}");
   MODULE_LICENSE("GPL");
-  MODULE_DEVICES("{{Vendor,My Chip Name}}");
+  MODULE_SUPPORTED_DEVICE("{{Vendor,My Chip Name}}");
 ]]>
         </programlisting>
       </informalexample>
@@ -5636,14 +5464,14 @@ struct _snd_pcm_runtime {
   SND_TOPDIR=../..
   endif
 
-  include $(TOPDIR)/toplevel.config
-  include $(TOPDIR)/Makefile.conf
+  include $(SND_TOPDIR)/toplevel.config
+  include $(SND_TOPDIR)/Makefile.conf
 
   snd-xyz-objs := xyz.o abc.o def.o
 
   obj-$(CONFIG_SND_XYZ) += snd-xyz.o
 
-  include $(TOPDIR)/Rules.make
+  include $(SND_TOPDIR)/Rules.make
 ]]>
         </programlisting>
       </example>
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 9a193fc86..351591769 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -23,7 +23,6 @@ show up in /proc/sys/kernel:
 - dentry-state
 - domainname
 - hostname
-- htab-reclaim                [ PPC only ]
 - hotplug
 - java-appletviewer           [ binfmt_java, obsolete ]
 - java-interpreter            [ binfmt_java, obsolete ]
@@ -54,7 +53,6 @@ show up in /proc/sys/kernel:
 - tainted
 - threads-max
 - version
-- zero-paged                  [ PPC only ]
 
 ==============================================================
 
@@ -133,8 +131,8 @@ domainname and hostname, i.e.:
 # echo "darkstar" > /proc/sys/kernel/hostname
 # echo "mydomain" > /proc/sys/kernel/domainname
 has the same effect as
-# hostname "darkstar" > /proc/sys/kernel/hostname
-# domainname "mydomain" > /proc/sys/kernel/domainname
+# hostname "darkstar"
+# domainname "mydomain"
 
 Note, however, that the classic darkstar.frop.org has the
 hostname "darkstar" and DNS (Internet Domain Name Server)
@@ -145,14 +143,6 @@ see the hostname(1) man page.
 
 ==============================================================
 
-htab-reclaim: (PPC only)
-
-Setting this to a non-zero value, the PowerPC htab
-(see Documentation/powerpc/ppc_htab.txt) is pruned
-each time the system hits the idle loop.
- 
-==============================================================
-
 hotplug:
 
 Path for the hotplug policy agent.
@@ -322,11 +312,3 @@ can be ORed together:
       Set by modutils >= 2.4.9 and module-init-tools.
   4 - Unsafe SMP processors: SMP with CPUs not designed for SMP.
 
-==============================================================
-
-zero-paged: (PPC only)
-
-When enabled (non-zero), Linux-PPC will pre-zero pages in
-the idle loop, possibly speeding up get_free_pages. Since
-this only affects what the idle loop is doing, you should
-enable this and see if anything changes.
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index b0349d8aa..57c6fbc84 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -47,7 +47,7 @@ of free memory left when userspace requests more memory.
 When this flag is 1, the kernel pretends there is always enough
 memory until it actually runs out.
 
-When this flag is 2, the kernel uses a "strict overcommit" 
+When this flag is 2, the kernel uses a "never overcommit"
 policy that attempts to prevent any overcommit of memory.  
 
 This feature can be very useful because there are a lot of
diff --git a/Documentation/usb/sn9c102.txt b/Documentation/usb/sn9c102.txt
index 65018c8c9..3999069b9 100644
--- a/Documentation/usb/sn9c102.txt
+++ b/Documentation/usb/sn9c102.txt
@@ -14,10 +14,10 @@ Index
 4.  Module dependencies
 5.  Module loading
 6.  Module parameters
-7.  Device control through "sysfs"
+7.  Optional device control through "sysfs"
 8.  Supported devices
 9.  How to add support for new image sensors
-10. Note for V4L2 developers
+10. Notes for V4L2 application developers
 11. Contact information
 12. Credits
 
@@ -142,23 +142,21 @@ Description:    Debugging information level, from 0 to 3:
                 1 = critical errors
                 2 = significant informations
                 3 = more verbose messages
-                Level 3 is useful for testing only, when just one device
+                Level 3 is useful for testing only, when only one device
                 is used.
 Default:        2
 -------------------------------------------------------------------------------
 
 
-7. Device control through "sysfs"
-=================================
+7. Optional device control through "sysfs"
+==========================================
 It is possible to read and write both the SN9C10[12] and the image sensor
 registers by using the "sysfs" filesystem interface.
 
-Every time a supported device is recognized, read-only files named "redblue"
-and "green" are created in the /sys/class/video4linux/videoX directory. You can
-set the red, blue and green channel's gain by writing the desired value to
-them. The value may range from 0 to 15 for each channel; this means that
-"redblue" accepts 8-bit values, where the low 4 bits are reserved for red and
-the others for blue.
+Every time a supported device is recognized, a read-only file named "green" is
+created in the /sys/class/video4linux/videoX directory. You can set the green
+channel's gain by writing the desired value to it. The value may range from 0
+to 15.
 
 There are other four entries in the directory above for each registered camera:
 "reg", "val", "i2c_reg" and "i2c_val". The first two files control the
@@ -208,7 +206,7 @@ Vendor ID  Product ID
 0xc45      0x6029
 0xc45      0x602a
 0xc45      0x602c
-0xc45      0x8001
+0xc45      0x6030
 
 The list above does NOT imply that all those devices work with this driver: up
 until now only the ones that mount the following image sensors are supported.
@@ -217,6 +215,7 @@ Kernel messages will always tell you whether this is the case:
 Model       Manufacturer
 -----       ------------
 PAS106B     PixArt Imaging Inc.
+PAS202BCB   PixArt Imaging Inc.
 TAS5110C1B  Taiwan Advanced Sensor Corporation
 TAS5130D1B  Taiwan Advanced Sensor Corporation
 
@@ -239,23 +238,31 @@ have created for this purpose, which is present in "sn9c102_sensor.h"
 (documentation is included there). As an example, have a look at the code in
 "sn9c102_pas106b.c", which uses the mentioned interface.
 
-At the moment, not yet supported image sensors are: PAS202B (VGA),
-HV7131[D|E1] (VGA), MI03 (VGA), OV7620 (VGA).
+At the moment, not yet supported image sensors are: HV7131[D|E1] (VGA),
+MI03 (VGA), OV7620 (VGA).
 
 
-10. Note for V4L2 developers
-============================
+10. Notes for V4L2 application developers
+=========================================
 This driver follows the V4L2 API specifications. In particular, it enforces two
 rules:
 
-1) Exactly one I/O method, either "mmap" or "read", is associated with each
+- exactly one I/O method, either "mmap" or "read", is associated with each
 file descriptor. Once it is selected, the application must close and reopen the
-device to switch to the other I/O method.
+device to switch to the other I/O method;
 
-2) Previously mapped buffer memory must always be unmapped before calling any
-of the "VIDIOC_S_CROP", "VIDIOC_TRY_FMT" and "VIDIOC_S_FMT" ioctl's. In case,
-the same number of buffers as before will be allocated again to match the size
-of the new video frames, so you have to map them again before any I/O attempts.
+- previously mapped buffer memory must always be unmapped before calling any
+of the "VIDIOC_S_CROP", "VIDIOC_TRY_FMT" and "VIDIOC_S_FMT" ioctl's. The same
+number of buffers as before will be allocated again to match the size of the
+new video frames, so you have to map them again before any I/O attempts.
+
+Consistently with the hardware limits, this driver also supports image
+downscaling with arbitrary scaling factors from 1, 2 and 4 in both directions.
+However the V4L2 API specifications don't correctly define how the scaling
+factor can be choosen arbitrarily by the "negotiation" of the "source" and
+"target" rectangles. To work around this flaw, we have added the convention
+that, during the negotiation, whenever the "VIDIOC_S_CROP" ioctl is issued, the
+scaling factor is restored to 1.
 
 
 11. Contact information
@@ -273,4 +280,6 @@ I would thank the following persons:
 
 - Stefano Mozzi, who donated 45 EU;
 - Luca Capello for the donation of a webcam;
-- Mizuno Takafumi for the donation of a webcam.
+- Mizuno Takafumi for the donation of a webcam;
+- Carlos Eduardo Medaglia Dyonisio, who added the support for the PAS202BCB
+  image sensor.
diff --git a/Documentation/vm/overcommit-accounting b/Documentation/vm/overcommit-accounting
index e0fd0b8f0..9db560eba 100644
--- a/Documentation/vm/overcommit-accounting
+++ b/Documentation/vm/overcommit-accounting
@@ -1,4 +1,4 @@
-The Linux kernel supports three overcommit handling modes
+The Linux kernel supports the following overcommit handling modes
 
 0	-	Heuristic overcommit handling. Obvious overcommits of
 		address space are refused. Used for a typical system. It
@@ -7,10 +7,10 @@ The Linux kernel supports three overcommit handling modes
 		allocate slighly more memory in this mode. This is the 
 		default.
 
-1	-	No overcommit handling. Appropriate for some scientific
+1	-	Always overcommit. Appropriate for some scientific
 		applications.
 
-2	-	(NEW) strict overcommit. The total address space commit
+2	-	Don't overcommit. The total address space commit
 		for the system is not permitted to exceed swap + a
 		configurable percentage (default is 50) of physical RAM.
 		Depending on the percentage you use, in most situations
@@ -27,7 +27,7 @@ Gotchas
 
 The C language stack growth does an implicit mremap. If you want absolute
 guarantees and run close to the edge you MUST mmap your stack for the 
-largest size you think you will need. For typical stack usage is does
+largest size you think you will need. For typical stack usage this does
 not matter much but it's a corner case if you really really care
 
 In mode 2 the MAP_NORESERVE flag is ignored. 
diff --git a/Documentation/vserver/debug.txt b/Documentation/vserver/debug.txt
index 38be457b8..b949b0525 100644
--- a/Documentation/vserver/debug.txt
+++ b/Documentation/vserver/debug.txt
@@ -1,21 +1,21 @@
 
 debug_switch:
 
- 0   1	
+ 0   1
 
- 1   2	
+ 1   2
 
- 2   4	
+ 2   4
 
- 3   8	
+ 3   8
 
- 4  16	
+ 4  16
 
- 5  32	
+ 5  32
 
- 6  64	
+ 6  64
 
- 7 128	
+ 7 128
 
 
 debug_xid:
@@ -29,10 +29,10 @@ debug_xid:
  1   2	"alloc_vx_info(%d)*"
 	"loc_vx_info(%d)*"
 	"locate_vx_info(%d)"
-		
+
  2   4	"get_vx_info(%p[#%d.%d])"
 	"put_vx_info(%p[#%d.%d])"
-	
+
  3   8	"set_vx_info(%p[#%d.%d.%d])"
 	"clr_vx_info(%p[#%d.%d.%d])"
 	"rcu_free_vx_info(%p): uc=%d"
@@ -44,9 +44,9 @@ debug_xid:
  5  32	"vx_migrate_task(%p,%p[#%d.%d])"
 	"task_get_vx_info(%p)"
 
- 6  64	
+ 6  64	"vx_set_init(%p[#%d],%p[#%d,%d,%d])"
 
- 7 128	
+ 7 128
 
 
 debug_nid:
@@ -59,10 +59,10 @@ debug_nid:
 
  1   2	"alloc_nx_info(%d)*"
 	"loc_nx_info(%d)*"
-		
+
  2   4	"get_nx_info(%p[#%d.%d])"
 	"put_nx_info(%p[#%d.%d])"
-	
+
  3   8	"set_nx_info(%p[#%d.%d.%d])"
 	"clr_nx_info(%p[#%d.%d.%d])"
 	"rcu_free_nx_info(%p): uc=%d"
@@ -75,9 +75,9 @@ debug_nid:
 	"task_get_nx_info(%p)"
 	"create_nx_info()"
 
- 6  64	
+ 6  64
 
- 7 128	
+ 7 128
 
 
 debug_dlim:
@@ -90,11 +90,11 @@ debug_dlim:
 
  2   4	"get_dl_info(%p[#%d.%d])"
 	"put_dl_info(%p[#%d.%d])"
-	
+
  3   8	"rcu_free_dl_info(%p)"
 	"__hash_dl_info: %p[#%d]"
 	"__unhash_dl_info: %p[#%d]"
-	
+
 
  4  16	"ALLOC (%p,#%d)%c inode (%d)"
 	"FREE  (%p,#%d)%c inode"
@@ -112,39 +112,40 @@ debug_dlim:
 debug_cvirt:
 
 
- 0   1	
+ 0   1
 
- 1   2	
+ 1   2
 
  2   4	"vx_map_tgid: %p/%llx: %d -> %d"
 	"vx_rmap_tgid: %p/%llx: %d -> %d"
-	
- 3   8	
 
- 4  16	
+ 3   8
+
+ 4  16
+
+ 5  32
+
+ 6  64
+
+ 7 128
 
- 5  32	
 
- 6  64	
 
- 7 128	
-	
-	
-	
 debug_net:
 
 
- 0   1	
+ 0   1
+
+ 1   2
 
- 1   2	
+ 2   4	"nx_addr_conflict(%p,%p) %d.%d,%d.%d"
 
- 2   4	"tcp_in_list(%p) %p,%p;%lx"
-	
- 3   8	"inet_bind(%p) %p,%p;%lx"
+ 3   8	"inet_bind(%p)* %p,%p;%lx %d.%d.%d.%d"
+	"inet_bind(%p) %d.%d.%d.%d, %d.%d.%d.%d, %d.%d.%d.%d"
 
  4  16	"ip_route_connect(%p) %p,%p;%lx"
 
- 5  32	"tcp_ipv4_addr_conflict(%p,%p) %p,%p;%lx %p,%p;%lx"
+ 5  32	"__addr_in_socket(%p,%d.%d.%d.%d) %p:%d.%d.%d.%d %p;%lx"
 
  6  64	"sk: %p [#%d] (from %d)"
 	"sk,req: %p [#%d] (from %d)"
@@ -162,9 +163,9 @@ debug_limit:
 
  n 2^n	"vx_acc_cres[%5d,%s,%2d]: %5d%s"
 	"vx_cres_avail[%5d,%s,%2d]: %5ld > %5d + %5d"
-	
+
  m 2^m	"vx_acc_page[%5d,%s,%2d]: %5d%s"
 	"vx_acc_pages[%5d,%s,%2d]: %5d += %5d"
 	"vx_pages_avail[%5d,%s,%2d]: %5ld > %5d + %5d"
-	
-	
+
+
diff --git a/Documentation/watchdog/pcwd-watchdog.txt b/Documentation/watchdog/pcwd-watchdog.txt
index a586667aa..12187a33e 100644
--- a/Documentation/watchdog/pcwd-watchdog.txt
+++ b/Documentation/watchdog/pcwd-watchdog.txt
@@ -35,7 +35,8 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
-#include <linux/pcwd.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
 
 int fd;
 
diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt
index d78f8dbf9..7f8570a7b 100644
--- a/Documentation/x86_64/boot-options.txt
+++ b/Documentation/x86_64/boot-options.txt
@@ -136,17 +136,25 @@ PCI
 
 IOMMU
 
-  iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,soft]
+ iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,merge]
+         [,forcesac][,fullflush][,nomerge][,noaperture]
    size  set size of iommu (in bytes)
    noagp don't initialize the AGP driver and use full aperture.
    off   don't use the IOMMU
    leak  turn on simple iommu leak tracing (only when CONFIG_IOMMU_LEAK is on)
    memaper[=order] allocate an own aperture over RAM with size 32MB^order.
    noforce don't force IOMMU usage. Default.
-   force  Force IOMMU
-   soft   Use software bounce buffering for non 32bit IO. Default on Intel
-          machines. 
-
-  swiotlb=pages
-
-  Prereserve that many 4K pages for the software IO bounce buffering.
+   force  Force IOMMU.
+   merge  Do SG merging. Implies force (experimental)
+   nomerge Don't do SG merging.
+   forcesac For SAC mode for masks <40bits  (experimental)
+   fullflush Flush IOMMU on each allocation (default)
+   nofullflush Don't use IOMMU fullflush
+   allowed  overwrite iommu off workarounds for specific chipsets.
+   soft	 Use software bounce buffering (default for Intel machines)
+   noaperture Don't touch the aperture for AGP.
+
+  swiotlb=pages[,force]
+
+  pages  Prereserve that many 128K pages for the software IO bounce buffering.
+  force  Force all IO through the software TLB.
diff --git a/MAINTAINERS b/MAINTAINERS
index c8c25df43..b2b5643bc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -169,7 +169,7 @@ ACI MIXER DRIVER
 P:	Robert Siemer
 M:	Robert.Siemer@gmx.de
 L:	linux-sound@vger.kernel.org
-W:	http://www.uni-karlsruhe.de/~Robert.Siemer/Private/
+W:	http://www.stud.uni-karlsruhe.de/~uh1b/
 S:	Maintained
 
 ACP/MWAVE MODEM
@@ -195,8 +195,14 @@ S:	Maintained
 
 AD1816 SOUND DRIVER
 P:	Thorsten Knabe
-W:	http://www.student.informatik.tu-darmstadt.de/~tek/projects/linux.html
-W:	http://www.tu-darmstadt.de/~tek01/projects/linux.html
+M:	Thorsten Knabe <linux@thorsten-knabe.de>
+W:	http://linux.thorsten-knabe.de
+S:	Maintained
+
+ADM1025 HARDWARE MONITOR DRIVER
+P:	Jean Delvare
+M:	khali@linux-fr.org
+L:	sensors@stimpy.netroedge.com
 S:	Maintained
 
 ADT746X FAN DRIVER
@@ -563,7 +569,7 @@ CRYPTO API
 P:	James Morris
 M:	jmorris@redhat.com
 P:	David S. Miller
-M:	davem@redhat.com
+M:	davem@davemloft.net
 W	http://samba.org/~jamesm/crypto/
 L:	linux-kernel@vger.kernel.org
 S:	Maintained
@@ -621,12 +627,14 @@ DC390/AM53C974 SCSI driver
 P:	Kurt Garloff
 M:	garloff@suse.de
 W:	http://www.garloff.de/kurt/linux/dc390/
+P:	Guennadi Liakhovetski
+M:	g.liakhovetski@gmx.de
 S:	Maintained
 
 DECnet NETWORK LAYER
-P:	Steven Whitehouse
-M:	SteveW@ACM.org
-W:	http://www.sucs.swan.ac.uk/~rohan/DECnet/index.html
+P:	Patrick Caulfield
+M:	patrick@tykepenguin.com
+W:	http://linux-decnet.sourceforge.net
 L:	linux-decnet-user@lists.sourceforge.net
 S:	Maintained
 
@@ -648,8 +656,9 @@ W:	http://sources.redhat.com/dm
 S:	Maintained
 
 DEVICE NUMBER REGISTRY
-P:	John Cagle
+P:	Torben Mathiasen
 M:	device@lanana.org
+W:	http://lanana.org/docs/device-list/index.html
 L:	linux-kernel@vger.kernel.org
 S:	Maintained
 
@@ -762,12 +771,17 @@ M:	saw@saw.sw.com.sg
 S:	Maintained
 
 EMU10K1 SOUND DRIVER
-P:	Rui Sousa	
-M:	rui.p.m.sousa@clix.pt	
+P:	James Courtier-Dutton
+M:	James@superbug.demon.co.uk
 L:	emu10k1-devel@lists.sourceforge.net
 W:	http://sourceforge.net/projects/emu10k1/
 S:	Maintained
 
+EPSON 1355 FRAMEBUFFER DRIVER
+P:	Christopher Hoover
+M:	ch@murgatroid.com, ch@hpl.hp.com
+S:	Maintained
+
 ETHEREXPRESS-16 NETWORK DRIVER
 P:	Philip Blundell
 M:	Philip.Blundell@pobox.com
@@ -822,10 +836,8 @@ M:	viro@math.psu.edu
 S:	Maintained
 
 FIRMWARE LOADER (request_firmware)
-P:	Manuel Estrada Sainz
-M:	ranty@debian.org
 L:	linux-kernel@vger.kernel.org
-S:	Maintained
+S:	Orphan
 
 FPU EMULATOR
 P:	Bill Metzenthen
@@ -905,18 +917,18 @@ L:	linux-hippi@sunsite.dk
 S:	Maintained
 
 HEWLETT-PACKARD FIBRE CHANNEL 64-bit/66MHz PCI non-intelligent HBA
-P:	Chase Maupin
-M:	chase.maupin@hp.com
+P:	Chirag Kantharia
+M:	chirag.kantharia@hp.com
 L:	iss_storagedev@hp.com
 S:	Maintained
  
 HEWLETT-PACKARD SMART2 RAID DRIVER
-P:	Francis Wiran
-M:	francis.wiran@hp.com
+P:	Chirag Kantharia
+M:	chirag.kantharia@hp.com
 L:	iss_storagedev@hp.com
 S:	Maintained
  
-HEWLETT-PACKARD SMART CISS RAID DRIVER 
+HEWLETT-PACKARD SMART CISS RAID DRIVER (cciss)
 P:	Mike Miller
 M:	mike.miller@hp.com
 L:	iss_storagedev@hp.com
@@ -947,6 +959,12 @@ L:	sensors@stimpy.netroedge.com
 W:	http://www.lm-sensors.nu/
 S:	Maintained
 
+I2O
+P:	Markus Lidel
+M:	markus.lidel@shadowconnect.com
+W:	http://i2o.shadowconnect.com/
+S:	Maintained
+
 i386 BOOT CODE
 P:	Riley H. Williams
 M:	Riley@Williams.Name
@@ -1060,6 +1078,19 @@ M:	lethal@chaoticdreams.org
 L:	linux-fbdev-devel@lists.sourceforge.net
 S:	Maintained
 
+INPUT (KEYBOARD, MOUSE, JOYSTICK) DRIVERS
+P:	Vojtech Pavlik
+M:	vojtech@suse.cz
+L:	linux-input@atrey.karlin.mff.cuni.cz
+L:	linux-joystick@atrey.karlin.mff.cuni.cz
+S:	Maintained
+
+INTEL 810/815 FRAMEBUFFER DRIVER
+P:      Antonino Daplas
+M:      adaplas@pol.net
+L:      linux-fbdev-devel@lists.sourceforge.net
+S:      Maintained
+
 INTEL APIC/IOAPIC, LOWLEVEL X86 SMP SUPPORT
 P:	Ingo Molnar
 M:	mingo@redhat.com
@@ -1178,13 +1209,6 @@ L:	jfs-discussion@oss.software.ibm.com
 W:	http://oss.software.ibm.com/jfs/
 S:	Supported
 
-JOYSTICK DRIVER
-P:	Vojtech Pavlik
-M:	vojtech@suse.cz
-L:	linux-joystick@atrey.karlin.mff.cuni.cz
-W:	http://www.suse.cz/development/joystick/
-S:	Maintained
-
 KCONFIG
 P:	Roman Zippel
 M:	zippel@linux-m68k.org
@@ -1266,16 +1290,26 @@ S:	Maintained
 LINUX FOR POWERPC
 P:	Paul Mackerras
 M:	paulus@samba.org
-W:	http://www.fsmlabs.com/linuxppcbk.html
+W:	http://www.penguinppc.org/
+L:	linuxppc-dev@lists.linuxppc.org
 S:	Supported
 
 LINUX FOR POWER MACINTOSH
 P:	Benjamin Herrenschmidt
 M:	benh@kernel.crashing.org
-W:	http://www.linuxppc.org/
+W:	http://www.penguinppc.org/
 L:	linuxppc-dev@lists.linuxppc.org
 S:	Maintained
 
+LINUX FOR POWERPC EMBEDDED MPC52XX
+P:	Sylvain Munaut
+M:	tnt@246tNt.com
+W:	http://www.246tNt.com/mpc52xx/
+W:	http://www.penguinppc.org/
+L:	linuxppc-dev@ozlabs.org
+L:	linuxppc-embedded@ozlabs.org
+S:	Maintained
+
 LINUX FOR POWERPC EMBEDDED PPC4XX
 P:	Matt Porter
 M:	mporter@kernel.crashing.org
@@ -1303,9 +1337,11 @@ M:	acme@conectiva.com.br
 S:	Maintained
 
 LINUX FOR 64BIT POWERPC
-P:	David Engebretsen (stable kernel)
-M:	engebret@us.ibm.com
-P:	Anton Blanchard (development kernel)
+P:	Paul Mackerras
+M:	paulus@samba.org
+M:	paulus@au.ibm.com
+P:	Anton Blanchard
+M:	anton@samba.org
 M:	anton@au.ibm.com
 W:	http://linuxppc64.org
 L:	linuxppc64-dev@lists.linuxppc.org
@@ -1318,6 +1354,18 @@ L:	linux-security-module@wirex.com
 W:	http://lsm.immunix.org
 S:	Supported
 
+LM83 HARDWARE MONITOR DRIVER
+P:	Jean Delvare
+M:	khali@linux-fr.org
+L:	sensors@stimpy.netroedge.com
+S:	Maintained
+
+LM90 HARDWARE MONITOR DRIVER
+P:	Jean Delvare
+M:	khali@linux-fr.org
+L:	sensors@stimpy.netroedge.com
+S:	Maintained
+
 LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP Dynamic Disks)
 P:	Richard Russon (FlatCap)
 M:	ldm@flatcap.org
@@ -1495,7 +1543,7 @@ S:	Maintained
 
 NETWORKING [IPv4/IPv6]
 P:	David S. Miller
-M:	davem@redhat.com
+M:	davem@davemloft.net
 P:	Alexey Kuznetsov
 M:	kuznet@ms2.inr.ac.ru
 P:	Pekka Savola (ipv6)
@@ -1509,6 +1557,14 @@ M:	kaber@coreworks.de
 L:	netdev@oss.sgi.com
 S:	Maintained
 
+IPVS
+P:	Wensong Zhang
+M:	wensong@linux-vs.org
+P:	Julian Anastasov
+M:	ja@ssi.bg
+L:	lvs-users@linuxvirtualserver.org
+S:	Maintained
+
 NFS CLIENT
 P:	Trond Myklebust
 M:	trond.myklebust@fys.uio.no
@@ -1586,6 +1642,8 @@ L:	oprofile-list@lists.sf.net
 S:	Maintained
 
 ORINOCO DRIVER
+P:	Pavel Roskin
+M:	proski@gnu.org
 P:	David Gibson
 M:	hermes@gibson.dropbear.id.au
 W:	http://www.ozlabs.org/people/dgibson/dldwd
@@ -1600,14 +1658,14 @@ P:	David Campbell
 M:	campbell@torque.net
 P:	Andrea Arcangeli
 M:	andrea@e-mind.com
-L:	linux-parport@torque.net
+L:	linux-parport@lists.infradead.org
 W:	http://people.redhat.com/twaugh/parport/
 S:	Maintained
 
 PARIDE DRIVERS FOR PARALLEL PORT IDE DEVICES
 P:	Tim Waugh
 M:	tim@cyberelk.net
-L:	linux-parport@torque.net
+L:	linux-parport@lists.infradead.org
 W:	http://www.torque.net/linux-pp.html
 S:	Maintained
 
@@ -1708,6 +1766,12 @@ M:	promise@pnd-pc.demon.co.uk
 W:	http://www.pnd-pc.demon.co.uk/promise/
 S:	Maintained
 
+PXA2xx SUPPORT
+P:	Nicolas Pitre
+M:	nico@cam.org
+L:	linux-arm-kernel@lists.arm.linux.org.uk
+S:	Maintained
+
 QNX4 FILESYSTEM
 P:	Anders Larsen
 M:	al@alarsen.net
@@ -1784,12 +1848,6 @@ M:	michael@mihu.de
 W:	http://www.mihu.de/linux/saa7146
 S:	Maintained
 
-SA1100 SUPPORT
-P:	Nicolas Pitre
-M:	nico@cam.org
-L:	linux-arm@lists.arm.linux.org.uk
-S:	Maintained
-
 SBPCD CDROM DRIVER
 P:	Eberhard Moenkeberg
 M:	emoenke@gwdg.de
@@ -1895,6 +1953,12 @@ M:	thomas@winischhofer.net
 W:	http://www.winischhofer.net/linuxsisvga.shtml
 S:	Maintained	
 
+SMSC47M1 HARDWARE MONITOR DRIVER
+P:	Jean Delvare
+M:	khali@linux-fr.org
+L:	sensors@stimpy.netroedge.com
+S:	Odd Fixes
+
 SMB FILESYSTEM
 P:	Urban Widmark
 M:	urban@teststation.com
@@ -1902,6 +1966,11 @@ W:	http://samba.org/
 L:	samba@samba.org
 S:	Maintained
 
+SMC91x ETHERNET DRIVER
+P:	Nicolas Pitre
+M:	nico@cam.org
+S:	Maintained
+
 SNA NETWORK LAYER
 P:	Jay Schulist
 M:	jschlst@samba.org
@@ -1945,7 +2014,7 @@ S:	Maintained
 
 UltraSPARC (sparc64):
 P:	David S. Miller
-M:	davem@redhat.com
+M:	davem@davemloft.net
 P:	Eddie C. Dost
 M:	ecd@skynet.be
 P:	Jakub Jelinek
@@ -2165,12 +2234,11 @@ M:	dbrownell@users.sourceforge.net
 L:	linux-usb-devel@lists.sourceforge.net
 S:	Maintained
 
-USB HID/HIDBP/INPUT DRIVERS
+USB HID/HIDBP DRIVERS
 P:	Vojtech Pavlik
 M:	vojtech@suse.cz
 L:	linux-usb-users@lists.sourceforge.net
 L:	linux-usb-devel@lists.sourceforge.net
-W:	http://www.suse.cz/development/input/
 S:	Maintained
 
 USB HUB DRIVER
@@ -2299,6 +2367,13 @@ L:	linux-usb-devel@lists.sourceforge.net
 W:	http://www.connecttech.com
 S:	Supported
 
+USB SN9C10[12] DRIVER
+P:	Luca Risolia
+M:	luca.risolia@studio.unibo.it
+L:	linux-usb-devel@lists.sourceforge.net
+W:	http://go.lamarinapunto.com
+S:	Maintained
+
 USB SUBSYSTEM
 P:	Greg Kroah-Hartman
 M:	greg@kroah.com
@@ -2392,6 +2467,12 @@ M:	johnpol@2ka.mipt.ru
 L:	sensors@stimpy.netroedge.com
 S:	Maintained
 
+W83L785TS HARDWARE MONITOR DRIVER
+P:	Jean Delvare
+M:	khali@linux-fr.org
+L:	sensors@stimpy.netroedge.com
+S:	Odd Fixes
+
 WAN ROUTER & SANGOMA WANPIPE DRIVERS & API (X.25, FRAME RELAY, PPP, CISCO HDLC)
 P:	Nenad Corbic
 M:	ncorbic@sangoma.com
diff --git a/Makefile b/Makefile
index c52759dd3..a11956358 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
-SUBLEVEL = 8
-EXTRAVERSION =
+SUBLEVEL = 9
+EXTRAVERSION = -vs1.9.3
 NAME=Zonked Quokka
 
 # *DOCUMENTATION*
@@ -102,7 +102,7 @@ ifneq ($(KBUILD_OUTPUT),)
 # check that the output directory actually exists
 saved-output := $(KBUILD_OUTPUT)
 KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT) && /bin/pwd)
-$(if $(wildcard $(KBUILD_OUTPUT)),, \
+$(if $(KBUILD_OUTPUT),, \
      $(error output directory "$(saved-output)" does not exist))
 
 .PHONY: $(MAKECMDGOALS)
@@ -141,7 +141,25 @@ VPATH		:= $(srctree)
 
 export srctree objtree VPATH TOPDIR
 
-KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
+nullstring :=
+space      := $(nullstring) # end of line
+
+# Take the contents of any files called localversion* and the config
+# variable CONFIG_LOCALVERSION and append them to KERNELRELEASE. Be
+# careful not to include files twice if building in the source
+# directory. LOCALVERSION from the command line override all of this
+
+ifeq ($(objtree),$(srctree))
+localversion-files := $(wildcard $(srctree)/localversion*)
+else
+localversion-files := $(wildcard $(objtree)/localversion* $(srctree)/localversion*)
+endif
+
+LOCALVERSION = $(subst $(space),, \
+	       $(shell cat /dev/null $(localversion-files)) \
+	       $(subst ",,$(CONFIG_LOCALVERSION)))
+
+KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)$(LOCALVERSION)
 
 # 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
@@ -256,9 +274,32 @@ ifneq ($(findstring s,$(MAKEFLAGS)),)
   quiet=silent_
 endif
 
-check_gcc = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
+export quiet Q KBUILD_VERBOSE
+
+######
+# cc support functions to be used (only) in arch/$(ARCH)/Makefile
+# See documentation in Documentation/kbuild/makefiles.txt
+
+# cc-option
+# Usage: cflags-y += $(call gcc-option, -march=winchip-c6, -march=i586)
+
+cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
+             > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
+
+# For backward compatibility
+check_gcc = $(warning check_gcc is deprecated - use cc-option) \
+            $(call cc-option, $(1),$(2))
+
+# cc-option-yn
+# Usage: flag := $(call gcc-option-yn, -march=winchip-c6)
+cc-option-yn = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
+                > /dev/null 2>&1; then echo "y"; else echo "n"; fi;)
+
+# cc-version
+# Usage gcc-ver := $(call cc-version $(CC))
+cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh \
+              $(if $(1), $(1), $(CC)))
 
-export quiet Q KBUILD_VERBOSE check_gcc
 
 # Look for make include files relative to root of kernel src
 MAKEFLAGS += --include-dir=$(srctree)
@@ -285,6 +326,7 @@ DEPMOD		= /sbin/depmod
 KALLSYMS	= scripts/kallsyms
 PERL		= perl
 CHECK		= sparse
+CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__
 MODFLAGS	= -DMODULE
 CFLAGS_MODULE   = $(MODFLAGS)
 AFLAGS_MODULE   = $(MODFLAGS)
@@ -294,19 +336,23 @@ AFLAGS_KERNEL	=
 
 NOSTDINC_FLAGS  = -nostdinc -iwithprefix include
 
-CPPFLAGS        := -D__KERNEL__ -Iinclude \
-		   $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include)
+# 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)
+
+CPPFLAGS        := -D__KERNEL__ $(LINUXINCLUDE)
 
 CFLAGS 		:= -Wall -Wstrict-prototypes -Wno-trigraphs \
 	  	   -fno-strict-aliasing -fno-common
 AFLAGS		:= -D__ASSEMBLY__
 
-export	VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION KERNELRELEASE ARCH \
-	CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \
+export	VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION LOCALVERSION KERNELRELEASE \
+	ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \
 	CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE \
-	HOSTCXX HOSTCXXFLAGS LDFLAGS_BLOB LDFLAGS_MODULE CHECK
+	HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
 
-export CPPFLAGS NOSTDINC_FLAGS OBJCOPYFLAGS LDFLAGS
+export CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
 export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE 
 export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
 
@@ -428,15 +474,6 @@ else
 include/linux/autoconf.h: ;
 endif
 
-include $(srctree)/arch/$(ARCH)/Makefile
-
-# Default kernel image to build when no specific target is given.
-# KBUILD_IMAGE may be overruled on the commandline or
-# set in the environment
-# Also any assingments in arch/$(ARCH)/Makefiel take precedence over
-# this default value
-export KBUILD_IMAGE ?= vmlinux
-
 # 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
@@ -458,7 +495,16 @@ CFLAGS		+= -g
 endif
 
 # warn about C99 declaration after statement
-CFLAGS += $(call check_gcc,-Wdeclaration-after-statement,)
+CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
+
+include $(srctree)/arch/$(ARCH)/Makefile
+
+# Default kernel image to build when no specific target is given.
+# KBUILD_IMAGE may be overruled on the commandline or
+# set in the environment
+# Also any assingments in arch/$(ARCH)/Makefiel take precedence over
+# this default value
+export KBUILD_IMAGE ?= vmlinux
 
 #
 # INSTALL_PATH specifies where to place the updated kernel and system map
@@ -499,67 +545,93 @@ libs-y		:= $(libs-y1) $(libs-y2)
 
 # Build vmlinux
 # ---------------------------------------------------------------------------
+# vmlinux is build 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
+
+# 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;                     \
+	. $(srctree)/scripts/mkversion > .tmp_version;	\
+	mv -f .tmp_version .version;			\
+	$(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
 
-#	This is a bit tricky: If we need to relink vmlinux, we want
-#	the version number incremented, which means recompile init/version.o
-#	and relink init/init.o. However, we cannot do this during the
-#       normal descending-into-subdirs phase, since at that time
-#       we cannot yet know if we will need to relink vmlinux.
-#	So we descend into init/ inside the rule for vmlinux again.
-head-y += $(HEAD)
-vmlinux-objs := $(head-y) $(init-y) $(core-y) $(libs-y) $(drivers-y) $(net-y)
-
-quiet_cmd_vmlinux__ = LD      $@
-define cmd_vmlinux__
-	$(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) $(head-y) $(init-y) \
-	--start-group \
-	$(core-y) \
-	$(libs-y) \
-	$(drivers-y) \
-	$(net-y) \
-	--end-group \
-	$(filter .tmp_kallsyms%,$^) \
-	-o $@
-endef
+define rule_vmlinux__
+	$(if $(CONFIG_KALLSYMS),,+$(call cmd,vmlinux_version))
 
-#	set -e makes the rule exit immediately on error
+	$(call cmd,vmlinux__)
+	$(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
 
-define rule_vmlinux__
-	+set -e;							\
-	$(if $(filter .tmp_kallsyms%,$^),,				\
-	  echo '  GEN     .version';					\
-	  . $(srctree)/scripts/mkversion > .tmp_version;		\
-	  mv -f .tmp_version .version;					\
-	  $(MAKE) $(build)=init;					\
-	)								\
-	$(if $($(quiet)cmd_vmlinux__),					\
-	  echo '  $($(quiet)cmd_vmlinux__)' &&) 			\
-	$(cmd_vmlinux__);						\
-	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
 
-do_system_map = $(NM) $(1) | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > $(2)
-
-LDFLAGS_vmlinux += -T arch/$(ARCH)/kernel/vmlinux.lds.s
-
-#	Generate section listing all symbols and add it into vmlinux
-#	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
-#	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
+# 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
@@ -569,47 +641,58 @@ endif
 
 kallsyms.o := .tmp_kallsyms$(last_kallsyms).o
 
-define rule_verify_kallsyms
-	@$(call do_system_map, .tmp_vmlinux$(last_kallsyms), .tmp_System.map)
-	@cmp -s System.map .tmp_System.map || \
-		(echo Inconsistent kallsyms data, try setting CONFIG_KALLSYMS_EXTRA_PASS ; rm .tmp_kallsyms* ; false)
+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
+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) $(foreach x,$(CONFIG_KALLSYMS_ALL),--all-symbols) > $@
+      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%
+.tmp_kallsyms%.S: .tmp_vmlinux% $(KALLSYMS)
 	$(call cmd,kallsyms)
 
-.tmp_vmlinux1: $(vmlinux-objs) arch/$(ARCH)/kernel/vmlinux.lds.s FORCE
-	$(call if_changed_rule,vmlinux__)
-
-.tmp_vmlinux2: $(vmlinux-objs) .tmp_kallsyms1.o arch/$(ARCH)/kernel/vmlinux.lds.s FORCE
-	$(call if_changed_rule,vmlinux__)
-
-.tmp_vmlinux3: $(vmlinux-objs) .tmp_kallsyms2.o arch/$(ARCH)/kernel/vmlinux.lds.s FORCE
-	$(call if_changed_rule,vmlinux__)
+# .tmp_vmlinux1 must be complete except kallsyms, so update vmlinux version
+.tmp_vmlinux1: $(vmlinux-lds) $(vmlinux-all) FORCE
+	$(call if_changed_rule,ksym_ld)
 
-endif
+.tmp_vmlinux2: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms1.o FORCE
+	$(call if_changed,vmlinux__)
 
-#	Finally the vmlinux rule
+.tmp_vmlinux3: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms2.o FORCE
+	$(call if_changed,vmlinux__)
 
-define rule_vmlinux
-	$(rule_vmlinux__); \
-	$(call do_system_map, $@, System.map)
-	$(rule_verify_kallsyms)
-endef
+# Needs to visit scripts/ before $(KALLSYMS) can be used.
+$(KALLSYMS): scripts ;
 
-vmlinux: $(vmlinux-objs) $(kallsyms.o) arch/$(ARCH)/kernel/vmlinux.lds.s FORCE
-	$(call if_changed_rule,vmlinux)
+endif # ifdef CONFIG_KALLSYMS
 
-#	The actual objects are generated when descending, 
-#	make sure no implicit rule kicks in
+# vmlinux image - including updated kernel symbols
+vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
+	$(call if_changed_rule,vmlinux__)
 
-$(sort $(vmlinux-objs)) arch/$(ARCH)/kernel/vmlinux.lds.s: $(vmlinux-dirs) ;
+# 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
@@ -632,10 +715,10 @@ $(vmlinux-dirs): prepare-all scripts
 # using a seperate output directory. This allows convinient use
 # of make in output directory
 prepare2:
-	$(Q)if [ ! $(srctree) -ef $(objtree) ]; then       \
-	$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile      \
-	    $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL) \
-	    > $(objtree)/Makefile;                         \
+	$(Q)if /usr/bin/env test ! $(srctree) -ef $(objtree); then \
+	$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile              \
+	    $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)         \
+	    > $(objtree)/Makefile;                                 \
 	fi
 
 # prepare1 is used to check if we are building in a separate output directory,
@@ -667,7 +750,7 @@ prepare-all: prepare0 prepare
 #	Leave this as default for preprocessing vmlinux.lds.S, which is now
 #	done in arch/$(ARCH)/kernel/Makefile
 
-export AFLAGS_vmlinux.lds.o += -P -C -U$(ARCH)
+export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
 
 # Single targets
 # ---------------------------------------------------------------------------
@@ -706,8 +789,8 @@ include/config/MARKER: include/linux/autoconf.h
 # Generate some files
 # ---------------------------------------------------------------------------
 
-#	version.h changes when $(KERNELRELEASE) etc change, as defined in
-#	this Makefile
+# 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
 
@@ -722,7 +805,7 @@ define filechk_version.h
 	)
 endef
 
-include/linux/version.h: Makefile
+include/linux/version.h: $(srctree)/Makefile FORCE
 	$(call filechk,version.h)
 
 # ---------------------------------------------------------------------------
@@ -922,7 +1005,13 @@ help:
 	@echo  '  rpm		  - Build a kernel as an RPM package'
 	@echo  '  tags/TAGS	  - Generate tags file for editors'
 	@echo  '  cscope	  - Generate cscope index'
+	@echo  ''
+	@echo  'Static analysers'
+	@echo  '  buildcheck      - List dangling references to vmlinux discarded sections'
+	@echo  '                    and init sections from non-init sections'
 	@echo  '  checkstack      - Generate a list of stack hogs'
+	@echo  '  namespacecheck  - Name space analysis on compiled kernel'
+	@echo  ''
 	@echo  'Kernel packaging:'
 	@$(MAKE) -f $(package-dir)/Makefile help
 	@echo  ''
@@ -940,7 +1029,8 @@ help:
 
 	@echo  '  make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build'
 	@echo  '  make O=dir [targets] Locate all output files in "dir", including .config'
-	@echo  '  make C=1   [targets] Check all c source with checker tool'
+	@echo  '  make C=1   [targets] Check all c source with $$CHECK (sparse)'
+	@echo  '  make C=2   [targets] Force check of all c source with $$CHECK (sparse)'
 	@echo  ''
 	@echo  'Execute "make" or "make all" to build all targets marked with [*] '
 	@echo  'For further info see the ./README file'
@@ -1081,8 +1171,11 @@ versioncheck:
 		| xargs $(PERL) -w scripts/checkversion.pl
 
 buildcheck:
-	$(PERL) scripts/reference_discarded.pl
-	$(PERL) scripts/reference_init.pl
+	$(PERL) $(srctree)/scripts/reference_discarded.pl
+	$(PERL) $(srctree)/scripts/reference_init.pl
+
+namespacecheck:
+	$(PERL) $(srctree)/scripts/namespace.pl
 
 endif #ifeq ($(config-targets),1)
 endif #ifeq ($(mixed-targets),1)
@@ -1119,13 +1212,22 @@ ifneq ($(cmd_files),)
   include $(cmd_files)
 endif
 
+# Execute command and generate cmd file
+if_changed = $(if $(strip $? \
+		          $(filter-out $(cmd_$(1)),$(cmd_$@))\
+			  $(filter-out $(cmd_$@),$(cmd_$(1)))),\
+	@set -e; \
+	$(if $($(quiet)cmd_$(1)),echo '  $(subst ','\'',$($(quiet)cmd_$(1)))';) \
+	$(cmd_$(1)); \
+	echo 'cmd_$@ := $(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).cmd)
+
+
 # execute the command and also postprocess generated .d dependencies
 # file
-
 if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\
 		          $(filter-out $(cmd_$(1)),$(cmd_$@))\
 			  $(filter-out $(cmd_$@),$(cmd_$(1)))),\
-	@set -e; \
+	$(Q)set -e; \
 	$(if $($(quiet)cmd_$(1)),echo '  $(subst ','\'',$($(quiet)cmd_$(1)))';) \
 	$(cmd_$(1)); \
 	scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \
@@ -1139,7 +1241,7 @@ if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\
 if_changed_rule = $(if $(strip $? \
 		               $(filter-out $(cmd_$(1)),$(cmd_$(@F)))\
 			       $(filter-out $(cmd_$(@F)),$(cmd_$(1)))),\
-	               @$(rule_$(1)))
+	               $(Q)$(rule_$(1)))
 
 # If quiet is set, only print short version of command
 
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index d770bb867..67ac95088 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -32,6 +32,10 @@ config GENERIC_ISA_DMA
 	bool
 	default y
 
+config GENERIC_IOMAP
+	bool
+	default n
+
 source "init/Kconfig"
 
 
@@ -462,11 +466,6 @@ config ALPHA_SRM
 
 	  If unsure, say N.
 
-config EARLY_PRINTK
-	bool
-	depends on ALPHA_GENERIC || ALPHA_SRM
-	default y
-
 config EISA
 	bool
 	depends on ALPHA_GENERIC || ALPHA_JENSEN || ALPHA_ALCOR || ALPHA_MIKASA || ALPHA_SABLE || ALPHA_LYNX || ALPHA_NORITAKE || ALPHA_RAWHIDE
@@ -593,104 +592,7 @@ source "fs/Kconfig"
 
 source "arch/alpha/oprofile/Kconfig"
 
-menu "Kernel hacking"
-
-config ALPHA_LEGACY_START_ADDRESS
-	bool "Legacy kernel start address"
-	depends on ALPHA_GENERIC
-	default n
-	---help---
-	  The 2.4 kernel changed the kernel start address from 0x310000
-	  to 0x810000 to make room for the Wildfire's larger SRM console.
-	  Recent consoles on Titan and Marvel machines also require the
-	  extra room.
-
-	  If you're using aboot 0.7 or later, the bootloader will examine the
-	  ELF headers to determine where to transfer control. Unfortunately,
-	  most older bootloaders -- APB or MILO -- hardcoded the kernel start
-	  address rather than examining the ELF headers, and the result is a
-	  hard lockup.
-
-	  Say Y if you have a broken bootloader.  Say N if you do not, or if
-	  you wish to run on Wildfire, Titan, or Marvel.
-
-config ALPHA_LEGACY_START_ADDRESS
-	bool
-	depends on !ALPHA_GENERIC && !ALPHA_TITAN && !ALPHA_MARVEL && !ALPHA_WILDFIRE
-	default y
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
-config MATHEMU
-	tristate "Kernel FP software completion" if DEBUG_KERNEL && !SMP
-	default y if !DEBUG_KERNEL || SMP
-	help
-	  This option is required for IEEE compliant floating point arithmetic
-	  on the Alpha. The only time you would ever not say Y is to say M in
-	  order to debug the code. Say Y unless you know what you are doing.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SPINLOCK
-	bool "Spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here and build SMP to catch missing spinlock initialization
-	  and certain other kinds of spinlock errors commonly made.  This is
-	  best used in conjunction with the NMI watchdog so that spinlock
-	  deadlocks are also debuggable.
-
-config DEBUG_RWLOCK
-	bool "Read-write spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here then read-write lock processing will count how many
-	  times it has tried to get the lock and issue an error message after
-	  too many attempts.  If you suspect a rwlock problem or a kernel
-	  hacker asks for this option then say Y.  Otherwise say N.
-
-config DEBUG_SEMAPHORE
-	bool "Semaphore debugging"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here then semaphore processing will issue lots of
-	  verbose debugging messages.  If you suspect a semaphore problem or a
-	  kernel hacker asks for this option then say Y.  Otherwise say N.
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  If you don't debug the kernel, you can say N.
-
-endmenu
+source "arch/alpha/Kconfig.debug"
 
 source "kernel/vserver/Kconfig"
 
diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile
index 0337f5f0d..c21132e4f 100644
--- a/arch/alpha/Makefile
+++ b/arch/alpha/Makefile
@@ -11,7 +11,7 @@
 NM := $(NM) -B
 
 LDFLAGS_vmlinux	:= -static -N #-relax
-CHECK		:= $(CHECK) -D__alpha__=1
+CHECKFLAGS	+= -D__alpha__
 cflags-y	:= -pipe -mno-fp-regs -ffixed-8
 
 # Determine if we can use the BWX instructions with GAS.
@@ -22,15 +22,11 @@ $(error The assembler '$(AS)' does not support the BWX instruction)
 endif
 
 # Determine if GCC understands the -mcpu= option.
-have_mcpu := $(shell if $(CC) -mcpu=ev5 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
-
-have_mcpu_pca56 := $(shell if $(CC) -mcpu=pca56 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
-
-have_mcpu_ev6 := $(shell if $(CC) -mcpu=ev6 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
-
-have_mcpu_ev67 := $(shell if $(CC) -mcpu=ev67 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
-
-have_msmall_data := $(shell if $(CC) -msmall-data -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
+have_mcpu        := $(call cc-option-yn, -mcpu=ev5)
+have_mcpu_pca56  := $(call cc-option-yn, -mcpu=pca56)
+have_mcpu_ev6    := $(call cc-option-yn, -mcpu=ev6)
+have_mcpu_ev67   := $(call cc-option-yn, -mcpu=ev67)
+have_msmall_data := $(call cc-option-yn, -msmall-data)
 
 cflags-$(have_msmall_data) += -msmall-data
 
diff --git a/arch/alpha/boot/Makefile b/arch/alpha/boot/Makefile
index e30945095..e1ae14cd2 100644
--- a/arch/alpha/boot/Makefile
+++ b/arch/alpha/boot/Makefile
@@ -8,7 +8,7 @@
 # Copyright (C) 1994 by Linus Torvalds
 #
 
-host-progs	:= tools/mkbb tools/objstrip
+hostprogs-y	:= tools/mkbb tools/objstrip
 targets		:= vmlinux.gz vmlinux \
 		   vmlinux.nh tools/lxboot tools/bootlx tools/bootph \
 		   tools/bootpzh bootloader bootpheader bootpzheader 
diff --git a/arch/alpha/defconfig b/arch/alpha/defconfig
index da929a2ae..6ac8d4a7d 100644
--- a/arch/alpha/defconfig
+++ b/arch/alpha/defconfig
@@ -1,38 +1,48 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2
+# Sat Sep 25 15:38:35 2004
 #
 CONFIG_ALPHA=y
 CONFIG_64BIT=y
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_GENERIC_IOMAP is not set
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
 CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_HOTPLUG is not set
 # CONFIG_IKCONFIG is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_IOSCHED_NOOP=y
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -84,7 +94,6 @@ CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 CONFIG_ALPHA_CORE_AGP=y
 CONFIG_ALPHA_BROKEN_IRQ_MASK=y
-CONFIG_EARLY_PRINTK=y
 CONFIG_EISA=y
 # CONFIG_SMP is not set
 # CONFIG_DISCONTIGMEM is not set
@@ -108,6 +117,8 @@ CONFIG_BINFMT_ELF=y
 #
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_DEBUG_DRIVER is not set
 
 #
@@ -130,7 +141,6 @@ CONFIG_PNP=y
 # Protocols
 #
 CONFIG_ISAPNP=y
-# CONFIG_PNPBIOS is not set
 
 #
 # Block devices
@@ -144,7 +154,7 @@ CONFIG_BLK_DEV_FD=y
 CONFIG_BLK_DEV_LOOP=m
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_CARMEL is not set
+# CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
 
 #
@@ -157,9 +167,9 @@ 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_IDEDISK=y
 CONFIG_IDEDISK_MULTI_MODE=y
-# CONFIG_IDEDISK_STROKE is not set
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -181,7 +191,6 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_ADMA=y
 # CONFIG_BLK_DEV_AEC62XX is not set
 CONFIG_BLK_DEV_ALI15X3=y
 # CONFIG_WDC_ALI15X3 is not set
@@ -203,6 +212,7 @@ CONFIG_BLK_DEV_CY82C693=y
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
 # CONFIG_IDE_CHIPSETS is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -229,7 +239,6 @@ CONFIG_BLK_DEV_SR_VENDOR=y
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 # CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_REPORT_LUNS is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 
@@ -243,6 +252,7 @@ CONFIG_BLK_DEV_SR_VENDOR=y
 # SCSI low-level drivers
 #
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_7000FASST is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AHA1542 is not set
@@ -252,18 +262,16 @@ CONFIG_SCSI_AIC7XXX=m
 CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
 CONFIG_AIC7XXX_RESET_DELAY_MS=5000
 # CONFIG_AIC7XXX_PROBE_EISA_VL is not set
-# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set
 CONFIG_AIC7XXX_DEBUG_MASK=0
 CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_DTC3280 is not set
 # CONFIG_SCSI_EATA is not set
@@ -276,6 +284,7 @@ CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
@@ -320,6 +329,7 @@ CONFIG_SCSI_QLA2XXX=y
 #
 # I2O device support
 #
+# CONFIG_I2O is not set
 
 #
 # Networking support
@@ -342,19 +352,17 @@ CONFIG_IP_MULTICAST=y
 # CONFIG_NET_IPGRE is not set
 # CONFIG_IP_MROUTE is not set
 # CONFIG_ARPD is not set
-CONFIG_INET_ECN=y
 # CONFIG_SYN_COOKIES is not set
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
 
 #
 # IP: Virtual Server Configuration
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -362,6 +370,8 @@ CONFIG_NETFILTER=y
 # IP: Netfilter Configuration
 #
 CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
 CONFIG_IP_NF_FTP=m
 CONFIG_IP_NF_IRC=m
 # CONFIG_IP_NF_TFTP is not set
@@ -386,8 +396,15 @@ CONFIG_IP_NF_IPTABLES=m
 # CONFIG_IP_NF_MATCH_STATE is not set
 # CONFIG_IP_NF_MATCH_CONNTRACK is not set
 # CONFIG_IP_NF_MATCH_OWNER is not set
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_REALM is not set
+# CONFIG_IP_NF_MATCH_SCTP is not set
+# CONFIG_IP_NF_MATCH_COMMENT 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_IP_NF_TARGET_TCPMSS is not set
 CONFIG_IP_NF_NAT=m
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -399,9 +416,7 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_NAT_IRC=m
 CONFIG_IP_NF_NAT_FTP=m
 # CONFIG_IP_NF_MANGLE is not set
-# CONFIG_IP_NF_TARGET_LOG is not set
-# CONFIG_IP_NF_TARGET_ULOG is not set
-# CONFIG_IP_NF_TARGET_TCPMSS is not set
+# CONFIG_IP_NF_RAW is not set
 # CONFIG_IP_NF_ARPTABLES is not set
 CONFIG_IP_NF_COMPAT_IPCHAINS=y
 CONFIG_XFRM=y
@@ -410,10 +425,11 @@ CONFIG_XFRM_USER=m
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
 CONFIG_VLAN_8021Q=m
+# CONFIG_DECNET is not set
 # CONFIG_LLC2 is not set
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
@@ -428,17 +444,18 @@ CONFIG_VLAN_8021Q=m
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
 CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
@@ -446,6 +463,11 @@ CONFIG_DUMMY=m
 # CONFIG_ETHERTAP is not set
 # CONFIG_NET_SB1000 is not set
 
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
 #
 # Ethernet (10 or 100Mbit)
 #
@@ -506,6 +528,7 @@ CONFIG_NET_PCI=y
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_NET_POCKET is not set
 
 #
@@ -518,7 +541,6 @@ CONFIG_NET_PCI=y
 # CONFIG_HAMACHI is not set
 CONFIG_YELLOWFIN=y
 # CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 
@@ -526,45 +548,29 @@ CONFIG_YELLOWFIN=y
 # Ethernet (10000 Mbit)
 #
 # CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
+# CONFIG_S2IO is not set
 
 #
 # Token Ring devices
 #
 # CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
 
 #
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
+# Wireless LAN (non-hamradio)
 #
-# CONFIG_IRDA is not set
+# CONFIG_NET_RADIO is not set
 
 #
-# Bluetooth support
+# Wan interfaces
 #
-# CONFIG_BT is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
 
 #
 # ISDN subsystem
@@ -603,6 +609,7 @@ CONFIG_SERIO_I8042=y
 CONFIG_SERIO_SERPORT=y
 # CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
 
 #
 # Input Device Drivers
@@ -648,7 +655,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
 
 #
 # IPMI
@@ -677,6 +683,11 @@ CONFIG_RTC=y
 #
 # CONFIG_I2C is not set
 
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
 #
 # Misc devices
 #
@@ -728,6 +739,7 @@ CONFIG_EXT2_FS=y
 CONFIG_REISERFS_FS=m
 # CONFIG_REISERFS_CHECK is not set
 # CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
@@ -750,6 +762,8 @@ CONFIG_ISO9660_FS=y
 CONFIG_FAT_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
 #
@@ -757,6 +771,7 @@ CONFIG_VFAT_FS=y
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
 # CONFIG_DEVFS_FS is not set
 # CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
@@ -796,11 +811,11 @@ CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=m
 CONFIG_SUNRPC=m
 # CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
 # CONFIG_AFS_FS is not set
 
 #
@@ -838,6 +853,7 @@ CONFIG_NLS_CODEPAGE_437=y
 # CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
 # CONFIG_NLS_ISO8859_1 is not set
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
@@ -861,15 +877,16 @@ CONFIG_NLS_CODEPAGE_437=y
 #
 # Kernel hacking
 #
-CONFIG_ALPHA_LEGACY_START_ADDRESS=y
 CONFIG_DEBUG_KERNEL=y
-CONFIG_MATHEMU=y
-# CONFIG_DEBUG_SLAB is not set
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_EARLY_PRINTK=y
 # CONFIG_DEBUG_RWLOCK is not set
 # CONFIG_DEBUG_SEMAPHORE is not set
-CONFIG_DEBUG_INFO=y
+CONFIG_ALPHA_LEGACY_START_ADDRESS=y
+CONFIG_MATHEMU=y
 
 #
 # Security options
@@ -887,6 +904,7 @@ CONFIG_CRYPTO_MD5=m
 CONFIG_CRYPTO_SHA1=m
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WHIRLPOOL is not set
 CONFIG_CRYPTO_DES=m
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
@@ -894,11 +912,17 @@ CONFIG_CRYPTO_DES=m
 # CONFIG_CRYPTO_AES is not set
 # CONFIG_CRYPTO_CAST5 is not set
 # CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
 # CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
 # CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
 # CONFIG_CRYPTO_TEST is not set
 
 #
 # Library routines
 #
+# CONFIG_CRC_CCITT is not set
 CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
index 73202af82..ab6fa54b3 100644
--- a/arch/alpha/kernel/Makefile
+++ b/arch/alpha/kernel/Makefile
@@ -2,13 +2,13 @@
 # Makefile for the linux kernel.
 #
 
-extra-y		:= head.o vmlinux.lds.s
+extra-y		:= head.o vmlinux.lds
 EXTRA_AFLAGS	:= $(CFLAGS)
 EXTRA_CFLAGS	:= -Werror -Wno-sign-compare
 
 obj-y    := entry.o traps.o process.o init_task.o osf_sys.o irq.o \
 	    irq_alpha.o signal.o setup.o ptrace.o time.o semaphore.o \
-	    alpha_ksyms.o systbls.o err_common.o
+	    alpha_ksyms.o systbls.o err_common.o io.o
 
 obj-$(CONFIG_VGA_HOSE)	+= console.o
 obj-$(CONFIG_SMP)	+= smp.o
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
index c901914a3..ad654afb8 100644
--- a/arch/alpha/kernel/alpha_ksyms.c
+++ b/arch/alpha/kernel/alpha_ksyms.c
@@ -18,6 +18,7 @@
 #include <linux/tty.h>
 #include <linux/mm.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/io.h>
 #include <asm/console.h>
@@ -67,36 +68,6 @@ EXPORT_SYMBOL(alpha_using_srm);
 #endif /* CONFIG_ALPHA_GENERIC */
 
 /* platform dependent support */
-EXPORT_SYMBOL(_inb);
-EXPORT_SYMBOL(_inw);
-EXPORT_SYMBOL(_inl);
-EXPORT_SYMBOL(_outb);
-EXPORT_SYMBOL(_outw);
-EXPORT_SYMBOL(_outl);
-EXPORT_SYMBOL(_readb);
-EXPORT_SYMBOL(_readw);
-EXPORT_SYMBOL(_readl);
-EXPORT_SYMBOL(_writeb);
-EXPORT_SYMBOL(_writew);
-EXPORT_SYMBOL(_writel);
-EXPORT_SYMBOL(___raw_readb); 
-EXPORT_SYMBOL(___raw_readw); 
-EXPORT_SYMBOL(___raw_readl); 
-EXPORT_SYMBOL(___raw_readq); 
-EXPORT_SYMBOL(___raw_writeb); 
-EXPORT_SYMBOL(___raw_writew); 
-EXPORT_SYMBOL(___raw_writel); 
-EXPORT_SYMBOL(___raw_writeq); 
-EXPORT_SYMBOL(_memcpy_fromio);
-EXPORT_SYMBOL(_memcpy_toio);
-EXPORT_SYMBOL(_memset_c_io);
-EXPORT_SYMBOL(scr_memcpyw);
-EXPORT_SYMBOL(insb);
-EXPORT_SYMBOL(insw);
-EXPORT_SYMBOL(insl);
-EXPORT_SYMBOL(outsb);
-EXPORT_SYMBOL(outsw);
-EXPORT_SYMBOL(outsl);
 EXPORT_SYMBOL(strcat);
 EXPORT_SYMBOL(strcmp);
 EXPORT_SYMBOL(strcpy);
@@ -136,7 +107,9 @@ EXPORT_SYMBOL(pci_dac_dma_supported);
 EXPORT_SYMBOL(pci_dac_page_to_dma);
 EXPORT_SYMBOL(pci_dac_dma_to_page);
 EXPORT_SYMBOL(pci_dac_dma_to_offset);
+EXPORT_SYMBOL(alpha_gendev_to_pci);
 #endif
+EXPORT_SYMBOL(dma_set_mask);
 
 EXPORT_SYMBOL(dump_thread);
 EXPORT_SYMBOL(dump_elf_thread);
@@ -183,8 +156,8 @@ EXPORT_SYMBOL(__min_ipl);
 /*
  * The following are specially called from the uaccess assembly stubs.
  */
-EXPORT_SYMBOL_NOVERS(__copy_user);
-EXPORT_SYMBOL_NOVERS(__do_clear_user);
+EXPORT_SYMBOL(__copy_user);
+EXPORT_SYMBOL(__do_clear_user);
 EXPORT_SYMBOL(__strncpy_from_user);
 EXPORT_SYMBOL(__strnlen_user);
 
@@ -243,17 +216,17 @@ EXPORT_SYMBOL(rtc_lock);
  */
 # undef memcpy
 # undef memset
-EXPORT_SYMBOL_NOVERS(__divl);
-EXPORT_SYMBOL_NOVERS(__divlu);
-EXPORT_SYMBOL_NOVERS(__divq);
-EXPORT_SYMBOL_NOVERS(__divqu);
-EXPORT_SYMBOL_NOVERS(__reml);
-EXPORT_SYMBOL_NOVERS(__remlu);
-EXPORT_SYMBOL_NOVERS(__remq);
-EXPORT_SYMBOL_NOVERS(__remqu);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memchr);
+EXPORT_SYMBOL(__divl);
+EXPORT_SYMBOL(__divlu);
+EXPORT_SYMBOL(__divq);
+EXPORT_SYMBOL(__divqu);
+EXPORT_SYMBOL(__reml);
+EXPORT_SYMBOL(__remlu);
+EXPORT_SYMBOL(__remq);
+EXPORT_SYMBOL(__remqu);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memchr);
 
 EXPORT_SYMBOL(get_wchan);
 
diff --git a/arch/alpha/kernel/core_cia.c b/arch/alpha/kernel/core_cia.c
index f5245ab2f..fd5630643 100644
--- a/arch/alpha/kernel/core_cia.c
+++ b/arch/alpha/kernel/core_cia.c
@@ -282,7 +282,7 @@ void
 cia_pci_tbi_try2(struct pci_controller *hose,
 		 dma_addr_t start, dma_addr_t end)
 {
-	unsigned long bus_addr;
+	void __iomem *bus_addr;
 	int ctrl;
 
 	/* Put the chip into PCI loopback mode.  */
@@ -351,7 +351,7 @@ verify_tb_operation(void)
 	struct pci_iommu_arena *arena = pci_isa_hose->sg_isa;
 	int ctrl, addr0, tag0, pte0, data0;
 	int temp, use_tbia_try2 = 0;
-	unsigned long bus_addr;
+	void __iomem *bus_addr;
 
 	/* pyxis -- tbia is broken */
 	if (pci_isa_hose->dense_io_base)
diff --git a/arch/alpha/kernel/core_irongate.c b/arch/alpha/kernel/core_irongate.c
index 50b7dd3d5..138d497d1 100644
--- a/arch/alpha/kernel/core_irongate.c
+++ b/arch/alpha/kernel/core_irongate.c
@@ -310,7 +310,7 @@ irongate_init_arch(void)
 #define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12) 
 #define GET_GATT(addr) (gatt_pages[GET_PAGE_DIR_IDX(addr)])
 
-unsigned long
+void __iomem *
 irongate_ioremap(unsigned long addr, unsigned long size)
 {
 	struct vm_struct *area;
@@ -320,7 +320,7 @@ irongate_ioremap(unsigned long addr, unsigned long size)
 	unsigned long gart_bus_addr;
 
 	if (!alpha_agpgart_size)
-		return addr + IRONGATE_MEM;
+		return (void __iomem *)(addr + IRONGATE_MEM);
 
 	gart_bus_addr = (unsigned long)IRONGATE0->bar0 &
 			PCI_BASE_ADDRESS_MEM_MASK; 
@@ -339,7 +339,7 @@ irongate_ioremap(unsigned long addr, unsigned long size)
 		/*
 		 * Not found - assume legacy ioremap
 		 */
-		return addr + IRONGATE_MEM;
+		return (void __iomem *)(addr + IRONGATE_MEM);
 	} while(0);
 
 	mmio_regs = (u32 *)(((unsigned long)IRONGATE0->bar1 &
@@ -353,7 +353,7 @@ irongate_ioremap(unsigned long addr, unsigned long size)
 	if (addr & ~PAGE_MASK) {
 		printk("AGP ioremap failed... addr not page aligned (0x%lx)\n",
 		       addr);
-		return addr + IRONGATE_MEM;
+		return (void __iomem *)(addr + IRONGATE_MEM);
 	}
 	last = addr + size - 1;
 	size = PAGE_ALIGN(last) - addr;
@@ -378,7 +378,7 @@ irongate_ioremap(unsigned long addr, unsigned long size)
 	 * Map it
 	 */
 	area = get_vm_area(size, VM_IOREMAP);
-	if (!area) return (unsigned long)NULL;
+	if (!area) return NULL;
 
 	for(baddr = addr, vaddr = (unsigned long)area->addr; 
 	    baddr <= last; 
@@ -391,7 +391,7 @@ irongate_ioremap(unsigned long addr, unsigned long size)
 					     pte, PAGE_SIZE, 0)) {
 			printk("AGP ioremap: FAILED to map...\n");
 			vfree(area->addr);
-			return (unsigned long)NULL;
+			return NULL;
 		}
 	}
 
@@ -402,13 +402,15 @@ irongate_ioremap(unsigned long addr, unsigned long size)
 	printk("irongate_ioremap(0x%lx, 0x%lx) returning 0x%lx\n",
 	       addr, size, vaddr);
 #endif
-	return vaddr;
+	return (void __iomem *)vaddr;
 }
 
 void
-irongate_iounmap(unsigned long addr)
+irongate_iounmap(volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	if (((long)addr >> 41) == -2)
 		return;	/* kseg map, nothing to do */
-	if (addr) return vfree((void *)(PAGE_MASK & addr)); 
+	if (addr)
+		return vfree((void *)(PAGE_MASK & addr)); 
 }
diff --git a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c
index 9bde638e8..bb4fe0498 100644
--- a/arch/alpha/kernel/core_marvel.c
+++ b/arch/alpha/kernel/core_marvel.c
@@ -610,11 +610,84 @@ marvel_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
 	csrs->POx_SG_TBIA.csr;
 }
 
+
+
+/*
+ * RTC Support
+ */
+struct marvel_rtc_access_info {
+	unsigned long function;
+	unsigned long index;
+	unsigned long data;
+};
+
+static void
+__marvel_access_rtc(void *info)
+{
+	struct marvel_rtc_access_info *rtc_access = info;
+
+	register unsigned long __r0 __asm__("$0");
+	register unsigned long __r16 __asm__("$16") = rtc_access->function;
+	register unsigned long __r17 __asm__("$17") = rtc_access->index;
+	register unsigned long __r18 __asm__("$18") = rtc_access->data;
+	
+	__asm__ __volatile__(
+		"call_pal %4 # cserve rtc"
+		: "=r"(__r16), "=r"(__r17), "=r"(__r18), "=r"(__r0)
+		: "i"(PAL_cserve), "0"(__r16), "1"(__r17), "2"(__r18)
+		: "$1", "$22", "$23", "$24", "$25");
+
+	rtc_access->data = __r0;
+}
+
+static u8
+__marvel_rtc_io(u8 b, unsigned long addr, int write)
+{
+	static u8 index = 0;
+
+	struct marvel_rtc_access_info rtc_access;
+	u8 ret = 0;
+
+	switch(addr) {
+	case 0x70:					/* RTC_PORT(0) */
+		if (write) index = b;
+		ret = index;
+		break;
+
+	case 0x71:					/* RTC_PORT(1) */
+		rtc_access.index = index;
+		rtc_access.data = BCD_TO_BIN(b);
+		rtc_access.function = 0x48 + !write;	/* GET/PUT_TOY */
+
+#ifdef CONFIG_SMP
+		if (smp_processor_id() != boot_cpuid)
+			smp_call_function_on_cpu(__marvel_access_rtc,
+						 &rtc_access, 1, 1,
+						 cpumask_of_cpu(boot_cpuid));
+		else
+			__marvel_access_rtc(&rtc_access);
+#else
+		__marvel_access_rtc(&rtc_access);
+#endif
+		ret = BIN_TO_BCD(rtc_access.data);
+		break;
+
+	default:
+		printk(KERN_WARNING "Illegal RTC port %lx\n", addr);
+		break;
+	}
+
+	return ret;
+}
+
 
 /*
  * IO map support.
  */
-unsigned long
+
+#define __marvel_is_mem_vga(a)	(((a) >= 0xa0000) && ((a) <= 0xc0000))
+
+void __iomem *
 marvel_ioremap(unsigned long addr, unsigned long size)
 {
 	struct pci_controller *hose;
@@ -633,8 +706,6 @@ marvel_ioremap(unsigned long addr, unsigned long size)
 	}
 #endif
 
-	if (!marvel_is_ioaddr(addr)) return 0UL;
-
 	/*
 	 * Find the hose.
 	 */
@@ -643,7 +714,7 @@ marvel_ioremap(unsigned long addr, unsigned long size)
 			break; 
 	}
 	if (!hose)
-		return 0UL;
+		return NULL;
 
 	/*
 	 * We have the hose - calculate the bus limits.
@@ -655,15 +726,17 @@ marvel_ioremap(unsigned long addr, unsigned long size)
 	 * Is it direct-mapped?
 	 */
 	if ((baddr >= __direct_map_base) && 
-	    ((baddr + size - 1) < __direct_map_base + __direct_map_size)) 
-		return IDENT_ADDR | (baddr - __direct_map_base);
+	    ((baddr + size - 1) < __direct_map_base + __direct_map_size)) {
+		addr = IDENT_ADDR | (baddr - __direct_map_base);
+		return (void __iomem *) addr;
+	}
 
 	/* 
 	 * Check the scatter-gather arena.
 	 */
 	if (hose->sg_pci &&
 	    baddr >= (unsigned long)hose->sg_pci->dma_base &&
-	    last < (unsigned long)hose->sg_pci->dma_base + hose->sg_pci->size){
+	    last < (unsigned long)hose->sg_pci->dma_base + hose->sg_pci->size) {
 
 		/*
 		 * Adjust the limits (mappings must be page aligned)
@@ -677,7 +750,9 @@ marvel_ioremap(unsigned long addr, unsigned long size)
 		 * Map it.
 		 */
 		area = get_vm_area(size, VM_IOREMAP);
-		if (!area) return (unsigned long)NULL;
+		if (!area)
+			return NULL;
+
 		ptes = hose->sg_pci->ptes;
 		for (vaddr = (unsigned long)area->addr; 
 		    baddr <= last; 
@@ -686,7 +761,7 @@ marvel_ioremap(unsigned long addr, unsigned long size)
 			if (!(pfn & 1)) {
 				printk("ioremap failed... pte not valid...\n");
 				vfree(area->addr);
-				return 0UL;
+				return NULL;
 			}
 			pfn >>= 1;	/* make it a true pfn */
 			
@@ -695,7 +770,7 @@ marvel_ioremap(unsigned long addr, unsigned long size)
 						     PAGE_SIZE, 0)) {
 				printk("FAILED to map...\n");
 				vfree(area->addr);
-				return 0UL;
+				return NULL;
 			}
 		}
 
@@ -703,101 +778,81 @@ marvel_ioremap(unsigned long addr, unsigned long size)
 
 		vaddr = (unsigned long)area->addr + (addr & ~PAGE_MASK);
 
-		return vaddr;
+		return (void __iomem *) vaddr;
 	}
 
-	/*
-	 * Not found - assume legacy ioremap.
-	 */
-	return addr;
+	return NULL;
 }
 
 void
-marvel_iounmap(unsigned long addr)
+marvel_iounmap(volatile void __iomem *xaddr)
 {
-	if (((long)addr >> 41) == -2)
-		return;	/* kseg map, nothing to do */
-	if (addr)
+	unsigned long addr = (unsigned long) xaddr;
+	if (addr >= VMALLOC_START)
 		vfree((void *)(PAGE_MASK & addr)); 
 }
 
-#ifndef CONFIG_ALPHA_GENERIC
-EXPORT_SYMBOL(marvel_ioremap);
-EXPORT_SYMBOL(marvel_iounmap);
-#endif
-
-
-/*
- * RTC Support
- */
-struct marvel_rtc_access_info {
-	unsigned long function;
-	unsigned long index;
-	unsigned long data;
-};
-
-static void
-__marvel_access_rtc(void *info)
+int
+marvel_is_mmio(const volatile void __iomem *xaddr)
 {
-	struct marvel_rtc_access_info *rtc_access = info;
-
-	register unsigned long __r0 __asm__("$0");
-	register unsigned long __r16 __asm__("$16") = rtc_access->function;
-	register unsigned long __r17 __asm__("$17") = rtc_access->index;
-	register unsigned long __r18 __asm__("$18") = rtc_access->data;
-	
-	__asm__ __volatile__(
-		"call_pal %4 # cserve rtc"
-		: "=r"(__r16), "=r"(__r17), "=r"(__r18), "=r"(__r0)
-		: "i"(PAL_cserve), "0"(__r16), "1"(__r17), "2"(__r18)
-		: "$1", "$22", "$23", "$24", "$25");
+	unsigned long addr = (unsigned long) xaddr;
 
-	rtc_access->data = __r0;
+	if (addr >= VMALLOC_START)
+		return 1;
+	else
+		return (addr & 0xFF000000UL) == 0;
 }
 
-u8
-__marvel_rtc_io(int write, u8 b, unsigned long addr)
-{
-	struct marvel_rtc_access_info rtc_access = {0, };
-	static u8 index = 0;
-	u8 ret = 0;
-
-	switch(addr) {
-	case 0x70:					/* RTC_PORT(0) */
-		if (write) index = b;
-		ret = index;
-		break;
+#define __marvel_is_port_vga(a)	\
+  (((a) >= 0x3b0) && ((a) < 0x3e0) && ((a) != 0x3b3) && ((a) != 0x3d3))
+#define __marvel_is_port_kbd(a)	(((a) == 0x60) || ((a) == 0x64))
+#define __marvel_is_port_rtc(a)	(((a) == 0x70) || ((a) == 0x71))
 
-	case 0x71:					/* RTC_PORT(1) */
-		rtc_access.index = index;
-		rtc_access.data = BCD_TO_BIN(b);
-		rtc_access.function = 0x49;		/* GET_TOY */
-		if (write) rtc_access.function = 0x48;	/* PUT_TOY */
-
-#ifdef CONFIG_SMP
-		if (smp_processor_id() != boot_cpuid)
-			smp_call_function_on_cpu(__marvel_access_rtc,
-						 &rtc_access,
-						 1,	/* retry */
-						 1,	/* wait  */
-						 1UL << boot_cpuid);
-		else
-			__marvel_access_rtc(&rtc_access);
-#else
-		__marvel_access_rtc(&rtc_access);
+void __iomem *marvel_ioportmap (unsigned long addr)
+{
+	if (__marvel_is_port_rtc (addr) || __marvel_is_port_kbd(addr))
+		;
+#ifdef CONFIG_VGA_HOSE
+	else if (__marvel_is_port_vga (addr) && pci_vga_hose)
+		addr += pci_vga_hose->io_space->start;
 #endif
-		ret = BIN_TO_BCD(rtc_access.data);
-		
-		break;
+	else
+		return NULL;
+	return (void __iomem *)addr;
+}
 
-	default:
-		printk(KERN_WARNING "Illegal RTC port %lx\n", addr);
-		break;
-	}
+unsigned int
+marvel_ioread8(void __iomem *xaddr)
+{
+	unsigned long addr = (unsigned long) xaddr;
+	if (__marvel_is_port_kbd(addr))
+		return 0;
+	else if (__marvel_is_port_rtc(addr))
+		return __marvel_rtc_io(0, addr, 0);
+	else
+		return __kernel_ldbu(*(vucp)addr);
+}
 
-	return ret;
+void
+marvel_iowrite8(u8 b, void __iomem *xaddr)
+{
+	unsigned long addr = (unsigned long) xaddr;
+	if (__marvel_is_port_kbd(addr))
+		return;
+	else if (__marvel_is_port_rtc(addr)) 
+		__marvel_rtc_io(b, addr, 1);
+	else
+		__kernel_stb(b, *(vucp)addr);
 }
 
+#ifndef CONFIG_ALPHA_GENERIC
+EXPORT_SYMBOL(marvel_ioremap);
+EXPORT_SYMBOL(marvel_iounmap);
+EXPORT_SYMBOL(marvel_is_mmio);
+EXPORT_SYMBOL(marvel_ioportmap);
+EXPORT_SYMBOL(marvel_ioread8);
+EXPORT_SYMBOL(marvel_iowrite8);
+#endif
 
 /*
  * NUMA Support
diff --git a/arch/alpha/kernel/core_titan.c b/arch/alpha/kernel/core_titan.c
index 3ddec9a87..3662fef7d 100644
--- a/arch/alpha/kernel/core_titan.c
+++ b/arch/alpha/kernel/core_titan.c
@@ -461,7 +461,8 @@ titan_kill_arch(int mode)
 /*
  * IO map support.
  */
-unsigned long
+
+void __iomem *
 titan_ioremap(unsigned long addr, unsigned long size)
 {
 	int h = (addr & TITAN_HOSE_MASK) >> TITAN_HOSE_SHIFT;
@@ -487,15 +488,19 @@ titan_ioremap(unsigned long addr, unsigned long size)
 	 * Find the hose.
 	 */
 	for (hose = hose_head; hose; hose = hose->next)
-		if (hose->index == h) break;
-	if (!hose) return (unsigned long)NULL;
+		if (hose->index == h)
+			break;
+	if (!hose)
+		return NULL;
 
 	/*
 	 * Is it direct-mapped?
 	 */
 	if ((baddr >= __direct_map_base) && 
-	    ((baddr + size - 1) < __direct_map_base + __direct_map_size)) 
-		return addr - __direct_map_base + TITAN_MEM_BIAS;
+	    ((baddr + size - 1) < __direct_map_base + __direct_map_size)) {
+		vaddr = addr - __direct_map_base + TITAN_MEM_BIAS;
+		return (void __iomem *) vaddr;
+	}
 
 	/* 
 	 * Check the scatter-gather arena.
@@ -516,7 +521,9 @@ titan_ioremap(unsigned long addr, unsigned long size)
 		 * Map it
 		 */
 		area = get_vm_area(size, VM_IOREMAP);
-		if (!area) return (unsigned long)NULL;
+		if (!area)
+			return NULL;
+
 		ptes = hose->sg_pci->ptes;
 		for (vaddr = (unsigned long)area->addr; 
 		    baddr <= last; 
@@ -525,7 +532,7 @@ titan_ioremap(unsigned long addr, unsigned long size)
 			if (!(pfn & 1)) {
 				printk("ioremap failed... pte not valid...\n");
 				vfree(area->addr);
-				return (unsigned long)NULL;
+				return NULL;
 			}
 			pfn >>= 1;	/* make it a true pfn */
 			
@@ -534,35 +541,42 @@ titan_ioremap(unsigned long addr, unsigned long size)
 						     PAGE_SIZE, 0)) {
 				printk("FAILED to map...\n");
 				vfree(area->addr);
-				return (unsigned long)NULL;
+				return NULL;
 			}
 		}
 
 		flush_tlb_all();
 
 		vaddr = (unsigned long)area->addr + (addr & ~PAGE_MASK);
-		return vaddr;
+		return (void __iomem *) vaddr;
 	}
 
-	/*
-	 * Not found - assume legacy ioremap.
-	 */
-	return addr + TITAN_MEM_BIAS;
-
+	return NULL;
 }
 
 void
-titan_iounmap(unsigned long addr)
+titan_iounmap(volatile void __iomem *xaddr)
 {
-	if (((long)addr >> 41) == -2)
-		return;	/* kseg map, nothing to do */
-	if (addr)
+	unsigned long addr = (unsigned long) xaddr;
+	if (addr >= VMALLOC_START)
 		vfree((void *)(PAGE_MASK & addr)); 
 }
 
+int
+titan_is_mmio(const volatile void __iomem *xaddr)
+{
+	unsigned long addr = (unsigned long) xaddr;
+
+	if (addr >= VMALLOC_START)
+		return 1;
+	else
+		return (addr & 0x100000000UL) == 0;
+}
+
 #ifndef CONFIG_ALPHA_GENERIC
 EXPORT_SYMBOL(titan_ioremap);
 EXPORT_SYMBOL(titan_iounmap);
+EXPORT_SYMBOL(titan_is_mmio);
 #endif
 
 /*
diff --git a/arch/alpha/kernel/err_titan.c b/arch/alpha/kernel/err_titan.c
index 897ea1a15..7e6720d45 100644
--- a/arch/alpha/kernel/err_titan.c
+++ b/arch/alpha/kernel/err_titan.c
@@ -177,7 +177,7 @@ titan_parse_p_perror(int which, int port, u64 perror, int print)
 #define TITAN__PCHIP_PERROR__CMD__S	(52)
 #define TITAN__PCHIP_PERROR__CMD__M	(0x0f)
 #define TITAN__PCHIP_PERROR__ADDR__S	(14)
-#define TITAN__PCHIP_PERROR__ADDR__M	(0x1ffffffff)
+#define TITAN__PCHIP_PERROR__ADDR__M	(0x1fffffffful)
 
 	if (!(perror & TITAN__PCHIP_PERROR__ERRMASK))
 		return MCHK_DISPOSITION_UNKNOWN_ERROR;
diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
index ee987528a..199435fb9 100644
--- a/arch/alpha/kernel/irq.c
+++ b/arch/alpha/kernel/irq.c
@@ -25,6 +25,7 @@
 #include <linux/irq.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/profile.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -83,6 +84,7 @@ handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
 		 struct irqaction *action)
 {
 	int status = 1;	/* Force the "do bottom halves" bit */
+	int ret;
 
 	do {
 		if (!(action->flags & SA_INTERRUPT))
@@ -90,8 +92,9 @@ handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
 		else
 			local_irq_disable();
 
-		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
@@ -288,31 +291,6 @@ irq_affinity_write_proc(struct file *file, const char __user *buffer,
 	return full_count;
 }
 
-static int
-prof_cpu_mask_read_proc(char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
-	if (count - len < 2)
-		return -EINVAL;
-	len += sprintf(page + len, "\n");
-	return len;
-}
-
-static int
-prof_cpu_mask_write_proc(struct file *file, const char __user *buffer,
-			 unsigned long count, void *data)
-{
-	unsigned long full_count = count, err;
-	cpumask_t new_value, *mask = (cpumask_t *)data;
-
-	err = cpumask_parse(buffer, count, new_value);
-	if (err)
-		return err;
-
-	*mask = new_value;
-	return full_count;
-}
 #endif /* CONFIG_SMP */
 
 #define MAX_NAMELEN 10
@@ -350,14 +328,9 @@ register_irq_proc (unsigned int irq)
 #endif
 }
 
-unsigned long prof_cpu_mask = ~0UL;
-
 void
 init_irq_proc (void)
 {
-#ifdef CONFIG_SMP
-	struct proc_dir_entry *entry;
-#endif
 	int i;
 
 	/* create /proc/irq */
@@ -365,12 +338,7 @@ init_irq_proc (void)
 
 #ifdef CONFIG_SMP 
 	/* create /proc/irq/prof_cpu_mask */
-	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
-
-	entry->nlink = 1;
-	entry->data = (void *)&prof_cpu_mask;
-	entry->read_proc = prof_cpu_mask_read_proc;
-	entry->write_proc = prof_cpu_mask_write_proc;
+	create_prof_cpu_mask(root_irq_dir);
 #endif
 
 	/*
diff --git a/arch/alpha/kernel/irq_impl.h b/arch/alpha/kernel/irq_impl.h
index d626a8be9..f201d8ffc 100644
--- a/arch/alpha/kernel/irq_impl.h
+++ b/arch/alpha/kernel/irq_impl.h
@@ -40,32 +40,3 @@ extern struct hw_interrupt_type i8259a_irq_type;
 extern void init_i8259a_irqs(void);
 
 extern void handle_irq(int irq, struct pt_regs * regs);
-
-extern unsigned long prof_cpu_mask;
-
-static inline void
-alpha_do_profile(unsigned long pc)
-{
-	extern char _stext;
-
-	if (!prof_buffer)
-		return;
-
-	/*
-	 * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
-	 * (default is all CPUs.)
-	 */
-	if (!((1<<smp_processor_id()) & prof_cpu_mask))
-		return;
-
-	pc -= (unsigned long) &_stext;
-	pc >>= prof_shift;
-	/*
-	 * Don't ignore out-of-bounds PC values silently,
-	 * put them into the last histogram slot, so if
-	 * present, they will show up as a sharp peak.
-	 */
-	if (pc > prof_len - 1)
-		pc = prof_len - 1;
-	atomic_inc((atomic_t *)&prof_buffer[pc]);
-}
diff --git a/arch/alpha/kernel/machvec_impl.h b/arch/alpha/kernel/machvec_impl.h
index 348597bdb..4959b7a3e 100644
--- a/arch/alpha/kernel/machvec_impl.h
+++ b/arch/alpha/kernel/machvec_impl.h
@@ -44,56 +44,60 @@
 #define DO_DEFAULT_RTC rtc_port: 0x70
 
 #define DO_EV4_MMU							\
-	max_asn:			EV4_MAX_ASN,			\
-	mv_switch_mm:			ev4_switch_mm,			\
-	mv_activate_mm:			ev4_activate_mm,		\
-	mv_flush_tlb_current:		ev4_flush_tlb_current,		\
-	mv_flush_tlb_current_page:	ev4_flush_tlb_current_page
+	.max_asn =			EV4_MAX_ASN,			\
+	.mv_switch_mm =			ev4_switch_mm,			\
+	.mv_activate_mm =		ev4_activate_mm,		\
+	.mv_flush_tlb_current =		ev4_flush_tlb_current,		\
+	.mv_flush_tlb_current_page =	ev4_flush_tlb_current_page
 
 #define DO_EV5_MMU							\
-	max_asn:			EV5_MAX_ASN,			\
-	mv_switch_mm:			ev5_switch_mm,			\
-	mv_activate_mm:			ev5_activate_mm,		\
-	mv_flush_tlb_current:		ev5_flush_tlb_current,		\
-	mv_flush_tlb_current_page:	ev5_flush_tlb_current_page
+	.max_asn =			EV5_MAX_ASN,			\
+	.mv_switch_mm =			ev5_switch_mm,			\
+	.mv_activate_mm =		ev5_activate_mm,		\
+	.mv_flush_tlb_current =		ev5_flush_tlb_current,		\
+	.mv_flush_tlb_current_page =	ev5_flush_tlb_current_page
 
 #define DO_EV6_MMU							\
-	max_asn:			EV6_MAX_ASN,			\
-	mv_switch_mm:			ev5_switch_mm,			\
-	mv_activate_mm:			ev5_activate_mm,		\
-	mv_flush_tlb_current:		ev5_flush_tlb_current,		\
-	mv_flush_tlb_current_page:	ev5_flush_tlb_current_page
+	.max_asn =			EV6_MAX_ASN,			\
+	.mv_switch_mm =			ev5_switch_mm,			\
+	.mv_activate_mm =		ev5_activate_mm,		\
+	.mv_flush_tlb_current =		ev5_flush_tlb_current,		\
+	.mv_flush_tlb_current_page =	ev5_flush_tlb_current_page
 
 #define DO_EV7_MMU							\
-	max_asn:			EV6_MAX_ASN,			\
-	mv_switch_mm:			ev5_switch_mm,			\
-	mv_activate_mm:			ev5_activate_mm,		\
-	mv_flush_tlb_current:		ev5_flush_tlb_current,		\
-	mv_flush_tlb_current_page:	ev5_flush_tlb_current_page
+	.max_asn =			EV6_MAX_ASN,			\
+	.mv_switch_mm =			ev5_switch_mm,			\
+	.mv_activate_mm =		ev5_activate_mm,		\
+	.mv_flush_tlb_current =		ev5_flush_tlb_current,		\
+	.mv_flush_tlb_current_page =	ev5_flush_tlb_current_page
 
 #define IO_LITE(UP,low)							\
-	hae_register:		(unsigned long *) CAT(UP,_HAE_ADDRESS),	\
-	iack_sc:		CAT(UP,_IACK_SC),			\
-	mv_inb:			CAT(low,_inb),				\
-	mv_inw:			CAT(low,_inw),				\
-	mv_inl:			CAT(low,_inl),				\
-	mv_outb:		CAT(low,_outb),				\
-	mv_outw:		CAT(low,_outw),				\
-	mv_outl:		CAT(low,_outl),				\
-	mv_readb:		CAT(low,_readb),			\
-	mv_readw:		CAT(low,_readw),			\
-	mv_readl:		CAT(low,_readl),			\
-	mv_readq:		CAT(low,_readq),			\
-	mv_writeb:		CAT(low,_writeb),			\
-	mv_writew:		CAT(low,_writew),			\
-	mv_writel:		CAT(low,_writel),			\
-	mv_writeq:		CAT(low,_writeq),			\
-	mv_ioremap:		CAT(low,_ioremap),			\
-	mv_iounmap:		CAT(low,_iounmap)			\
+	.hae_register =		(unsigned long *) CAT(UP,_HAE_ADDRESS),	\
+	.iack_sc =		CAT(UP,_IACK_SC),			\
+	.mv_ioread8 =		CAT(low,_ioread8),			\
+	.mv_ioread16 =		CAT(low,_ioread16),			\
+	.mv_ioread32 =		CAT(low,_ioread32),			\
+	.mv_iowrite8 =		CAT(low,_iowrite8),			\
+	.mv_iowrite16 =		CAT(low,_iowrite16),			\
+	.mv_iowrite32 =		CAT(low,_iowrite32),			\
+	.mv_readb =		CAT(low,_readb),			\
+	.mv_readw =		CAT(low,_readw),			\
+	.mv_readl =		CAT(low,_readl),			\
+	.mv_readq =		CAT(low,_readq),			\
+	.mv_writeb =		CAT(low,_writeb),			\
+	.mv_writew =		CAT(low,_writew),			\
+	.mv_writel =		CAT(low,_writel),			\
+	.mv_writeq =		CAT(low,_writeq),			\
+	.mv_ioportmap =		CAT(low,_ioportmap),			\
+	.mv_ioremap =		CAT(low,_ioremap),			\
+	.mv_iounmap =		CAT(low,_iounmap),			\
+	.mv_is_ioaddr =		CAT(low,_is_ioaddr),			\
+	.mv_is_mmio =		CAT(low,_is_mmio)			\
 
 #define IO(UP,low)							\
 	IO_LITE(UP,low),						\
-	pci_ops:		&CAT(low,_pci_ops)
+	.pci_ops =		&CAT(low,_pci_ops),			\
+	.mv_pci_tbi =		CAT(low,_pci_tbi)
 
 #define DO_APECS_IO	IO(APECS,apecs)
 #define DO_CIA_IO	IO(CIA,cia)
@@ -108,23 +112,8 @@
 #define DO_WILDFIRE_IO	IO(WILDFIRE,wildfire)
 
 #define DO_PYXIS_IO	IO_LITE(CIA,cia_bwx), \
-			pci_ops: &CAT(cia,_pci_ops)
-
-#define BUS(which)					\
-	mv_is_ioaddr:	CAT(which,_is_ioaddr),		\
-	mv_pci_tbi:	CAT(which,_pci_tbi)
-
-#define DO_APECS_BUS	BUS(apecs)
-#define DO_CIA_BUS	BUS(cia)
-#define DO_IRONGATE_BUS	BUS(irongate)
-#define DO_LCA_BUS	BUS(lca)
-#define DO_MARVEL_BUS	BUS(marvel)
-#define DO_MCPCIA_BUS	BUS(mcpcia)
-#define DO_POLARIS_BUS	BUS(polaris)
-#define DO_T2_BUS	BUS(t2)
-#define DO_TSUNAMI_BUS	BUS(tsunami)
-#define DO_TITAN_BUS	BUS(titan)
-#define DO_WILDFIRE_BUS	BUS(wildfire)
+			.pci_ops = &cia_pci_ops, \
+			.mv_pci_tbi = cia_pci_tbi
 
 /*
  * In a GENERIC kernel, we have lots of these vectors floating about,
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 4761ed9a4..dcad8d31d 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -91,8 +91,8 @@ osf_set_program_attributes(unsigned long text_start, unsigned long text_len,
  * braindamage (it can't really handle filesystems where the directory
  * offset differences aren't the same as "d_reclen").
  */
-#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
-#define ROUND_UP(x) (((x)+3) & ~3)
+#define NAME_OFFSET	offsetof (struct osf_dirent, d_name)
+#define ROUND_UP(x)	(((x)+3) & ~3)
 
 struct osf_dirent {
 	unsigned int d_ino;
@@ -114,7 +114,7 @@ osf_filldir(void *__buf, const char *name, int namlen, loff_t offset,
 {
 	struct osf_dirent __user *dirent;
 	struct osf_dirent_callback *buf = (struct osf_dirent_callback *) __buf;
-	unsigned int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+	unsigned int reclen = ROUND_UP(NAME_OFFSET + namlen + 1);
 
 	buf->error = -EINVAL;	/* only used if we fail */
 	if (reclen > buf->count)
@@ -723,7 +723,8 @@ osf_setsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes,
 {
 	switch (op) {
 	case SSI_IEEE_FP_CONTROL: {
-		unsigned long swcr, fpcr, fex;
+		unsigned long swcr, fpcr;
+		unsigned int *state;
 
 		/* 
 		 * Alpha Architecture Handbook 4.7.7.3:
@@ -732,22 +733,42 @@ osf_setsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes,
 		 * set in the trap shadow of a software-complete insn.
 		 */
 
-		/* Update softare trap enable bits.  */
 		if (get_user(swcr, (unsigned long __user *)buffer))
 			return -EFAULT;
-		current_thread_info()->ieee_state
-		  = ((current_thread_info()->ieee_state & ~IEEE_SW_MASK)
-		     | (swcr & IEEE_SW_MASK));
+		state = &current_thread_info()->ieee_state;
+
+		/* Update softare trap enable bits.  */
+		*state = (*state & ~IEEE_SW_MASK) | (swcr & IEEE_SW_MASK);
+
+		/* Update the real fpcr.  */
+		fpcr = rdfpcr() & FPCR_DYN_MASK;
+		fpcr |= ieee_swcr_to_fpcr(swcr);
+		wrfpcr(fpcr);
+
+		return 0;
+	}
+
+	case SSI_IEEE_RAISE_EXCEPTION: {
+		unsigned long exc, swcr, fpcr, fex;
+		unsigned int *state;
+
+		if (get_user(exc, (unsigned long __user *)buffer))
+			return -EFAULT;
+		state = &current_thread_info()->ieee_state;
+		exc &= IEEE_STATUS_MASK;
+
+		/* Update softare trap enable bits.  */
+ 		swcr = (*state & IEEE_SW_MASK) | exc;
+		*state |= exc;
 
 		/* Update the real fpcr.  */
 		fpcr = rdfpcr();
-		fpcr &= FPCR_DYN_MASK;
 		fpcr |= ieee_swcr_to_fpcr(swcr);
 		wrfpcr(fpcr);
 
- 		/* If any exceptions are now unmasked, send a signal.  */
-		fex = ((swcr & IEEE_STATUS_MASK)
-		       >> IEEE_STATUS_TO_EXCSUM_SHIFT) & swcr;
+ 		/* If any exceptions set by this call, and are unmasked,
+		   send a signal.  Old exceptions are not signaled.  */
+		fex = (exc >> IEEE_STATUS_TO_EXCSUM_SHIFT) & swcr;
  		if (fex) {
 			siginfo_t info;
 			int si_code = 0;
@@ -765,7 +786,6 @@ osf_setsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes,
 			info.si_addr = NULL;  /* FIXME */
  			send_sig_info(SIGFPE, &info, current);
  		}
-
 		return 0;
 	}
 
@@ -969,7 +989,7 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
 	fd_set_bits fds;
 	char *bits;
 	size_t size;
-	unsigned long timeout;
+	long timeout;
 	int ret;
 
 	timeout = MAX_SCHEDULE_TIMEOUT;
@@ -1033,9 +1053,10 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
 		ret = 0;
 	}
 
-	set_fd_set(n, inp->fds_bits, fds.res_in);
-	set_fd_set(n, outp->fds_bits, fds.res_out);
-	set_fd_set(n, exp->fds_bits, fds.res_ex);
+	if (set_fd_set(n, inp->fds_bits, fds.res_in) ||
+	    set_fd_set(n, outp->fds_bits, fds.res_out) ||
+	    set_fd_set(n, exp->fds_bits, fds.res_ex))
+		ret = -EFAULT;
 
  out:
 	kfree(bits);
@@ -1079,64 +1100,57 @@ osf_getrusage(int who, struct rusage32 __user *ru)
 		r.ru_majflt = current->maj_flt;
 		break;
 	case RUSAGE_CHILDREN:
-		jiffies_to_timeval32(current->cutime, &r.ru_utime);
-		jiffies_to_timeval32(current->cstime, &r.ru_stime);
-		r.ru_minflt = current->cmin_flt;
-		r.ru_majflt = current->cmaj_flt;
-		break;
-	default:
-		jiffies_to_timeval32(current->utime + current->cutime,
-				   &r.ru_utime);
-		jiffies_to_timeval32(current->stime + current->cstime,
-				   &r.ru_stime);
-		r.ru_minflt = current->min_flt + current->cmin_flt;
-		r.ru_majflt = current->maj_flt + current->cmaj_flt;
+		jiffies_to_timeval32(current->signal->cutime, &r.ru_utime);
+		jiffies_to_timeval32(current->signal->cstime, &r.ru_stime);
+		r.ru_minflt = current->signal->cmin_flt;
+		r.ru_majflt = current->signal->cmaj_flt;
 		break;
 	}
 
 	return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
 }
 
-asmlinkage int
-osf_wait4(pid_t pid, int __user *ustatus, int options, struct rusage32 __user *ur)
+asmlinkage long
+osf_wait4(pid_t pid, int __user *ustatus, int options,
+	  struct rusage32 __user *ur)
 {
-	if (!ur) {
+	struct rusage r;
+	long ret, err;
+	mm_segment_t old_fs;
+
+	if (!ur)
 		return sys_wait4(pid, ustatus, options, NULL);
-	} else {
-		struct rusage r;
-		int ret, status;
-		mm_segment_t old_fs = get_fs();
+
+	old_fs = get_fs();
 		
-		set_fs (KERNEL_DS);
-		ret = sys_wait4(pid, &status, options, &r);
-		set_fs (old_fs);
+	set_fs (KERNEL_DS);
+	ret = sys_wait4(pid, ustatus, options, (struct rusage __user *) &r);
+	set_fs (old_fs);
 
-		if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur)))
-			return -EFAULT;
-		__put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec);
-		__put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec);
-		__put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec);
-		__put_user(r.ru_stime.tv_usec, &ur->ru_stime.tv_usec);
-		__put_user(r.ru_maxrss, &ur->ru_maxrss);
-		__put_user(r.ru_ixrss, &ur->ru_ixrss);
-		__put_user(r.ru_idrss, &ur->ru_idrss);
-		__put_user(r.ru_isrss, &ur->ru_isrss);
-		__put_user(r.ru_minflt, &ur->ru_minflt);
-		__put_user(r.ru_majflt, &ur->ru_majflt);
-		__put_user(r.ru_nswap, &ur->ru_nswap);
-		__put_user(r.ru_inblock, &ur->ru_inblock);
-		__put_user(r.ru_oublock, &ur->ru_oublock);
-		__put_user(r.ru_msgsnd, &ur->ru_msgsnd);
-		__put_user(r.ru_msgrcv, &ur->ru_msgrcv);
-		__put_user(r.ru_nsignals, &ur->ru_nsignals);
-		__put_user(r.ru_nvcsw, &ur->ru_nvcsw);
-		if (__put_user(r.ru_nivcsw, &ur->ru_nivcsw))
-			return -EFAULT;
+	if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur)))
+		return -EFAULT;
 
-		if (ustatus && put_user(status, ustatus))
-			return -EFAULT;
-		return ret;
-	}
+	err = 0;
+	err |= __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec);
+	err |= __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec);
+	err |= __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec);
+	err |= __put_user(r.ru_stime.tv_usec, &ur->ru_stime.tv_usec);
+	err |= __put_user(r.ru_maxrss, &ur->ru_maxrss);
+	err |= __put_user(r.ru_ixrss, &ur->ru_ixrss);
+	err |= __put_user(r.ru_idrss, &ur->ru_idrss);
+	err |= __put_user(r.ru_isrss, &ur->ru_isrss);
+	err |= __put_user(r.ru_minflt, &ur->ru_minflt);
+	err |= __put_user(r.ru_majflt, &ur->ru_majflt);
+	err |= __put_user(r.ru_nswap, &ur->ru_nswap);
+	err |= __put_user(r.ru_inblock, &ur->ru_inblock);
+	err |= __put_user(r.ru_oublock, &ur->ru_oublock);
+	err |= __put_user(r.ru_msgsnd, &ur->ru_msgsnd);
+	err |= __put_user(r.ru_msgrcv, &ur->ru_msgrcv);
+	err |= __put_user(r.ru_nsignals, &ur->ru_nsignals);
+	err |= __put_user(r.ru_nvcsw, &ur->ru_nvcsw);
+	err |= __put_user(r.ru_nivcsw, &ur->ru_nivcsw);
+
+	return err ? err : ret;
 }
 
 /*
diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c
index b8a7e3ff8..582a3519f 100644
--- a/arch/alpha/kernel/pci-noop.c
+++ b/arch/alpha/kernel/pci-noop.c
@@ -7,8 +7,10 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
+#include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
+#include <linux/dma-mapping.h>
 
 #include "proto.h"
 
@@ -101,41 +103,112 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
 	else
 		return -ENODEV;
 }
-/* stubs for the routines in pci_iommu.c */
+
+/* Stubs for the routines in pci_iommu.c: */
+
 void *
 pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp)
 {
 	return NULL;
 }
+
 void
 pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu_addr,
 		    dma_addr_t dma_addr)
 {
 }
+
 dma_addr_t
 pci_map_single(struct pci_dev *pdev, void *cpu_addr, size_t size,
 	       int direction)
 {
 	return (dma_addr_t) 0;
 }
+
 void
 pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
 		 int direction)
 {
 }
+
 int
 pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
 	   int direction)
 {
 	return 0;
 }
+
 void
 pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
 	     int direction)
 {
 }
+
 int
 pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask)
 {
 	return 0;
 }
+
+/* Generic DMA mapping functions: */
+
+void *
+dma_alloc_coherent(struct device *dev, size_t size,
+		   dma_addr_t *dma_handle, int gfp)
+{
+	void *ret;
+
+	if (!dev || *dev->dma_mask >= 0xffffffffUL)
+		gfp &= ~GFP_DMA;
+	ret = (void *)__get_free_pages(gfp, get_order(size));
+	if (ret) {
+		memset(ret, 0, size);
+		*dma_handle = virt_to_bus(ret);
+	}
+	return ret;
+}
+
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+int
+dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+	   enum dma_data_direction direction)
+{
+	int i;
+
+	for (i = 0; i < nents; i++ ) {
+		void *va;
+
+		BUG_ON(!sg[i].page);
+		va = page_address(sg[i].page) + sg[i].offset;
+		sg_dma_address(sg + i) = (dma_addr_t)virt_to_bus(va);
+		sg_dma_len(sg + i) = sg[i].length;
+	}
+
+	return nents;
+}
+
+EXPORT_SYMBOL(dma_map_sg);
+
+int
+dma_set_mask(struct device *dev, u64 mask)
+{
+	if (!dev->dma_mask || !dma_supported(dev, mask))
+		return -EIO;
+
+	*dev->dma_mask = mask;
+
+	return 0;
+}
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+	return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
+{
+}
+
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index 1e3abbb5c..b4c64d4fd 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -67,6 +67,7 @@ quirk_isa_bridge(struct pci_dev *dev)
 {
 	dev->class = PCI_CLASS_BRIDGE_ISA << 8;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378, quirk_isa_bridge);
 
 static void __init
 quirk_cypress(struct pci_dev *dev)
@@ -100,6 +101,7 @@ quirk_cypress(struct pci_dev *dev)
 		}
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, quirk_cypress);
 
 /* Called for each device after PCI setup is done. */
 static void __init
@@ -112,17 +114,10 @@ pcibios_fixup_final(struct pci_dev *dev)
 		isa_bridge = dev;
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_final);
 
-struct pci_fixup pcibios_fixups[] __initdata = {
-	{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378,
-	  quirk_isa_bridge },
-	{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693,
-	  quirk_cypress },
-	{ PCI_FIXUP_FINAL,  PCI_ANY_ID,	PCI_ANY_ID,
-	  pcibios_fixup_final },
-	{ 0 }
-};
-
+/* Just declaring that the power-of-ten prefixes are actually the
+   power-of-two ones doesn't make it true :) */
 #define KB			1024
 #define MB			(1024*KB)
 #define GB			(1024*MB)
@@ -536,3 +531,37 @@ sys_pciconfig_iobase(long which, unsigned long bus, unsigned long dfn)
 
 	return -EOPNOTSUPP;
 }
+
+/* Create an __iomem token from a PCI BAR.  Copied from lib/iomap.c with
+   no changes, since we don't want the other things in that object file.  */
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+	unsigned long start = pci_resource_start(dev, bar);
+	unsigned long len = pci_resource_len(dev, bar);
+	unsigned long flags = pci_resource_flags(dev, bar);
+
+	if (!len || !start)
+		return NULL;
+	if (maxlen && len > maxlen)
+		len = maxlen;
+	if (flags & IORESOURCE_IO)
+		return ioport_map(start, len);
+	if (flags & IORESOURCE_MEM) {
+		/* Not checking IORESOURCE_CACHEABLE because alpha does
+		   not distinguish between ioremap and ioremap_nocache.  */
+		return ioremap(start, len);
+	}
+	return NULL;
+}
+
+/* Destroy that token.  Not copied from lib/iomap.c.  */
+
+void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
+{
+	if (__is_mmio(addr))
+		iounmap(addr);
+}
+
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index b47c35679..7cb23f12e 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -930,3 +930,42 @@ pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr)
 {
 	return (dma_addr & ~PAGE_MASK);
 }
+
+
+/* Helper for generic DMA-mapping functions. */
+
+struct pci_dev *
+alpha_gendev_to_pci(struct device *dev)
+{
+	if (dev && dev->bus == &pci_bus_type)
+		return to_pci_dev(dev);
+
+	/* Assume that non-PCI devices asking for DMA are either ISA or EISA,
+	   BUG() otherwise. */
+	BUG_ON(!isa_bridge);
+
+	/* Assume non-busmaster ISA DMA when dma_mask is not set (the ISA
+	   bridge is bus master then). */
+	if (!dev || !dev->dma_mask || !*dev->dma_mask)
+		return isa_bridge;
+
+	/* For EISA bus masters, return isa_bridge (it might have smaller
+	   dma_mask due to wiring limitations). */
+	if (*dev->dma_mask >= isa_bridge->dma_mask)
+		return isa_bridge;
+
+	/* This assumes ISA bus master with dma_mask 0xffffff. */
+	return NULL;
+}
+
+int
+dma_set_mask(struct device *dev, u64 mask)
+{
+	if (!dev->dma_mask ||
+	    !pci_dma_supported(alpha_gendev_to_pci(dev), mask))
+		return -EIO;
+
+	*dev->dma_mask = mask;
+
+	return 0;
+}
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index 6fd854655..4933f3ce5 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -246,8 +246,7 @@ alpha_clone(unsigned long clone_flags, unsigned long usp,
 	if (!usp)
 		usp = rdusp();
 
-	return do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0,
-		       parent_tid, child_tid);
+	return do_fork(clone_flags, usp, regs, 0, parent_tid, child_tid);
 }
 
 int
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index 5d9aae6be..8db4b56b6 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -91,15 +91,15 @@ static int regoff[] = {
 	PT_REG(	   pc)
 };
 
-static long zero;
+static unsigned long zero;
 
 /*
  * Get address of register REGNO in task TASK.
  */
-static long *
+static unsigned long *
 get_reg_addr(struct task_struct * task, unsigned long regno)
 {
-	long *addr;
+	unsigned long *addr;
 
 	if (regno == 30) {
 		addr = &task->thread_info->pcb.usp;
@@ -109,7 +109,7 @@ get_reg_addr(struct task_struct * task, unsigned long regno)
 		zero = 0;
 		addr = &zero;
 	} else {
-		addr = (long *)((long)task->thread_info + regoff[regno]);
+		addr = (void *)task->thread_info + regoff[regno];
 	}
 	return addr;
 }
@@ -117,7 +117,7 @@ get_reg_addr(struct task_struct * task, unsigned long regno)
 /*
  * Get contents of register REGNO in task TASK.
  */
-static long
+static unsigned long
 get_reg(struct task_struct * task, unsigned long regno)
 {
 	/* Special hack for fpcr -- combine hardware and software bits.  */
@@ -135,7 +135,7 @@ get_reg(struct task_struct * task, unsigned long regno)
  * Write contents of register REGNO in task TASK.
  */
 static int
-put_reg(struct task_struct *task, unsigned long regno, long data)
+put_reg(struct task_struct *task, unsigned long regno, unsigned long data)
 {
 	if (regno == 63) {
 		task->thread_info->ieee_state
@@ -168,11 +168,11 @@ int
 ptrace_set_bpt(struct task_struct * child)
 {
 	int displ, i, res, reg_b, nsaved = 0;
-	u32 insn, op_code;
+	unsigned int insn, op_code;
 	unsigned long pc;
 
 	pc  = get_reg(child, REG_PC);
-	res = read_int(child, pc, &insn);
+	res = read_int(child, pc, (int *) &insn);
 	if (res < 0)
 		return res;
 
@@ -203,7 +203,8 @@ ptrace_set_bpt(struct task_struct * child)
 
 	/* install breakpoints: */
 	for (i = 0; i < nsaved; ++i) {
-		res = read_int(child, child->thread_info->bpt_addr[i], &insn);
+		res = read_int(child, child->thread_info->bpt_addr[i],
+			       (int *) &insn);
 		if (res < 0)
 			return res;
 		child->thread_info->bpt_insn[i] = insn;
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index dd1d9195c..94ff1b330 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -145,7 +145,7 @@ sys_rt_sigaction(int sig, const struct sigaction __user *act,
  * Atomically swap in the new signal mask, and wait for a signal.
  */
 asmlinkage int
-do_sigsuspend(old_sigset_t mask, struct pt_regs *reg, struct switch_stack *sw)
+do_sigsuspend(old_sigset_t mask, struct pt_regs *regs, struct switch_stack *sw)
 {
 	sigset_t oldset;
 
@@ -156,17 +156,22 @@ do_sigsuspend(old_sigset_t mask, struct pt_regs *reg, struct switch_stack *sw)
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
+	/* Indicate EINTR on return from any possible signal handler,
+	   which will not come back through here, but via sigreturn.  */
+	regs->r0 = EINTR;
+	regs->r19 = 1;
+
 	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();
-		if (do_signal(&oldset, reg, sw, 0, 0))
+		if (do_signal(&oldset, regs, sw, 0, 0))
 			return -EINTR;
 	}
 }
 
 asmlinkage int
 do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize,
-		 struct pt_regs *reg, struct switch_stack *sw)
+		 struct pt_regs *regs, struct switch_stack *sw)
 {
 	sigset_t oldset, set;
 
@@ -183,10 +188,15 @@ do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize,
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
+	/* Indicate EINTR on return from any possible signal handler,
+	   which will not come back through here, but via sigreturn.  */
+	regs->r0 = EINTR;
+	regs->r19 = 1;
+
 	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();
-		if (do_signal(&oldset, reg, sw, 0, 0))
+		if (do_signal(&oldset, regs, sw, 0, 0))
 			return -EINTR;
 	}
 }
@@ -218,6 +228,12 @@ struct rt_sigframe
 	unsigned int retcode[3];
 };
 
+/* If this changes, userland unwinders that Know Things about our signal
+   frame will break.  Do not undertake lightly.  It also implies an ABI
+   change wrt the size of siginfo_t, which may cause some pain.  */
+extern char compile_time_assert
+        [offsetof(struct rt_sigframe, uc.uc_mcontext) == 176 ? 1 : -1];
+
 #define INSN_MOV_R30_R16	0x47fe0410
 #define INSN_LDI_R0		0x201f0000
 #define INSN_CALLSYS		0x00000083
@@ -469,9 +485,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static void
@@ -533,9 +547,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 
@@ -608,21 +620,20 @@ do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw,
 	siginfo_t info;
 	int signr;
 	unsigned long single_stepping = ptrace_cancel_bpt(current);
+	struct k_sigaction ka;
 
 	if (!oldset)
 		oldset = &current->blocked;
 
 	/* This lets the debugger run, ... */
-	signr = get_signal_to_deliver(&info, regs, NULL);
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	/* ... so re-check the single stepping. */
 	single_stepping |= ptrace_cancel_bpt(current);
 
 	if (signr > 0) {
 		/* Whee!  Actually deliver the signal.  */
-		struct k_sigaction *ka = &current->sighand->action[signr-1];
-
-		if (r0) syscall_restart(r0, r19, regs, ka);
-		handle_signal(signr, ka, &info, oldset, regs, sw);
+		if (r0) syscall_restart(r0, r19, regs, &ka);
+		handle_signal(signr, &ka, &info, oldset, regs, sw);
 		if (single_stepping) 
 			ptrace_set_bpt(current); /* re-set bpt */
 		return 1;
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index 3a4c9d6e2..6d4d09c43 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -25,6 +25,7 @@
 #include <linux/spinlock.h>
 #include <linux/irq.h>
 #include <linux/cache.h>
+#include <linux/profile.h>
 
 #include <asm/hwrpb.h>
 #include <asm/ptrace.h>
@@ -35,7 +36,6 @@
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
 
@@ -411,15 +411,6 @@ secondary_cpu_start(int cpuid, struct task_struct *idle)
 	return 0;
 }
 
-static struct task_struct * __init
-fork_by_hand(void)
-{
-	/* Don't care about the contents of regs since we'll never
-	   reschedule the forked task. */
-	struct pt_regs regs;
-	return copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
-}
-
 /*
  * Bring one cpu online.
  */
@@ -435,15 +426,10 @@ smp_boot_one_cpu(int cpuid)
 	   the other task-y sort of data structures set up like we
 	   wish.  We can't use kernel_thread since we must avoid
 	   rescheduling the child.  */
-	idle = fork_by_hand();
+	idle = fork_idle(cpuid);
 	if (IS_ERR(idle))
 		panic("failed fork for CPU %d", cpuid);
 
-	wake_up_forked_process(idle);
-
-	init_idle(idle, cpuid);
-	unhash_process(idle);
-
 	DBGS(("smp_boot_one_cpu: CPU %d state 0x%lx flags 0x%lx\n",
 	      cpuid, idle->state, idle->flags));
 
@@ -613,8 +599,7 @@ smp_percpu_timer_interrupt(struct pt_regs *regs)
 	struct cpuinfo_alpha *data = &cpu_data[cpu];
 
 	/* Record kernel PC.  */
-	if (!user)
-		alpha_do_profile(regs->pc);
+	profile_tick(CPU_PROFILING, regs);
 
 	if (!--data->prof_counter) {
 		/* We need to make like a normal interrupt -- otherwise
diff --git a/arch/alpha/kernel/srmcons.c b/arch/alpha/kernel/srmcons.c
index 1a9b4c645..49c8c97ed 100644
--- a/arch/alpha/kernel/srmcons.c
+++ b/arch/alpha/kernel/srmcons.c
@@ -91,15 +91,15 @@ srmcons_receive_chars(unsigned long data)
 
 /* called with callback_lock held */
 static int
-srmcons_do_write(struct tty_struct *tty, const unsigned char *buf, int count)
+srmcons_do_write(struct tty_struct *tty, const char *buf, int count)
 {
-	unsigned char *str_cr = "\r";
+	static char str_cr[1] = "\r";
 	long c, remaining = count;
 	srmcons_result result;
-	unsigned char *cur;
+	char *cur;
 	int need_cr;
 
-	for (cur = (unsigned char *)buf; remaining > 0; ) {
+	for (cur = (char *)buf; remaining > 0; ) {
 		need_cr = 0;
 		/* 
 		 * Break it up into reasonable size chunks to allow a chance
@@ -138,7 +138,7 @@ srmcons_write(struct tty_struct *tty, int from_user,
 	unsigned long flags;
 
 	if (from_user) {
-		unsigned char tmp[512];
+		char tmp[512];
 		int ret = 0;
 		size_t c;
 
@@ -146,7 +146,7 @@ srmcons_write(struct tty_struct *tty, int from_user,
 			if (c > sizeof(tmp))
 				c = sizeof(tmp);
 			
-			c -= copy_from_user(tmp, buf, c);
+			c -= copy_from_user(tmp, (const char __user *) buf, c);
 
 			if (!c) { 
 				printk("%s: EFAULT (count %d)\n",
@@ -167,7 +167,7 @@ srmcons_write(struct tty_struct *tty, int from_user,
 	}
 
 	spin_lock_irqsave(&srmcons_callback_lock, flags);
-	srmcons_do_write(tty, buf, count);
+	srmcons_do_write(tty, (const char *) buf, count);
 	spin_unlock_irqrestore(&srmcons_callback_lock, flags);
 
 	return count;
diff --git a/arch/alpha/kernel/sys_alcor.c b/arch/alpha/kernel/sys_alcor.c
index bf2cfa1b0..6852eeedf 100644
--- a/arch/alpha/kernel/sys_alcor.c
+++ b/arch/alpha/kernel/sys_alcor.c
@@ -274,7 +274,6 @@ struct alpha_machine_vector alcor_mv __initmv = {
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_CIA_IO,
-	DO_CIA_BUS,
 	.machine_check		= cia_machine_check,
 	.max_isa_dma_address	= ALPHA_ALCOR_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= EISA_DEFAULT_IO_BASE,
@@ -292,7 +291,7 @@ struct alpha_machine_vector alcor_mv __initmv = {
 	.pci_swizzle		= common_swizzle,
 
 	.sys = { .cia = {
-	    .gru_int_req_bits	= ALCOR_GRU_INT_REQ_BITS
+		.gru_int_req_bits = ALCOR_GRU_INT_REQ_BITS
 	}}
 };
 ALIAS_MV(alcor)
@@ -302,7 +301,6 @@ struct alpha_machine_vector xlt_mv __initmv = {
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_CIA_IO,
-	DO_CIA_BUS,
 	.machine_check		= cia_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= EISA_DEFAULT_IO_BASE,
@@ -320,7 +318,7 @@ struct alpha_machine_vector xlt_mv __initmv = {
 	.pci_swizzle		= common_swizzle,
 
 	.sys = { .cia = {
-	    .gru_int_req_bits	= XLT_GRU_INT_REQ_BITS
+		.gru_int_req_bits = XLT_GRU_INT_REQ_BITS
 	}}
 };
 
diff --git a/arch/alpha/kernel/sys_cabriolet.c b/arch/alpha/kernel/sys_cabriolet.c
index 568feb8b1..c3f9dbc1e 100644
--- a/arch/alpha/kernel/sys_cabriolet.c
+++ b/arch/alpha/kernel/sys_cabriolet.c
@@ -327,7 +327,6 @@ struct alpha_machine_vector cabriolet_mv __initmv = {
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_APECS_IO,
-	DO_APECS_BUS,
 	.machine_check		= apecs_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -354,7 +353,6 @@ struct alpha_machine_vector eb164_mv __initmv = {
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_CIA_IO,
-	DO_CIA_BUS,
 	.machine_check		= cia_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -380,7 +378,6 @@ struct alpha_machine_vector eb66p_mv __initmv = {
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_LCA_IO,
-	DO_LCA_BUS,
 	.machine_check		= lca_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -405,7 +402,6 @@ struct alpha_machine_vector lx164_mv __initmv = {
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_PYXIS_IO,
-	DO_CIA_BUS,
 	.machine_check		= cia_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -432,7 +428,6 @@ struct alpha_machine_vector pc164_mv __initmv = {
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_CIA_IO,
-	DO_CIA_BUS,
 	.machine_check		= cia_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c
index 119501849..10973586f 100644
--- a/arch/alpha/kernel/sys_dp264.c
+++ b/arch/alpha/kernel/sys_dp264.c
@@ -71,10 +71,10 @@ tsunami_update_irq_hw(unsigned long mask)
 	dim1 = &cchip->dim1.csr;
 	dim2 = &cchip->dim2.csr;
 	dim3 = &cchip->dim3.csr;
-	if (cpu_possible(0)) dim0 = &dummy;
-	if (cpu_possible(1)) dim1 = &dummy;
-	if (cpu_possible(2)) dim2 = &dummy;
-	if (cpu_possible(3)) dim3 = &dummy;
+	if (!cpu_possible(0)) dim0 = &dummy;
+	if (!cpu_possible(1)) dim1 = &dummy;
+	if (!cpu_possible(2)) dim2 = &dummy;
+	if (!cpu_possible(3)) dim3 = &dummy;
 
 	*dim0 = mask0;
 	*dim1 = mask1;
@@ -569,7 +569,6 @@ struct alpha_machine_vector dp264_mv __initmv = {
 	DO_EV6_MMU,
 	DO_DEFAULT_RTC,
 	DO_TSUNAMI_IO,
-	DO_TSUNAMI_BUS,
 	.machine_check		= tsunami_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -594,7 +593,6 @@ struct alpha_machine_vector monet_mv __initmv = {
 	DO_EV6_MMU,
 	DO_DEFAULT_RTC,
 	DO_TSUNAMI_IO,
-	DO_TSUNAMI_BUS,
 	.machine_check		= tsunami_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -618,7 +616,6 @@ struct alpha_machine_vector webbrick_mv __initmv = {
 	DO_EV6_MMU,
 	DO_DEFAULT_RTC,
 	DO_TSUNAMI_IO,
-	DO_TSUNAMI_BUS,
 	.machine_check		= tsunami_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -642,7 +639,6 @@ struct alpha_machine_vector clipper_mv __initmv = {
 	DO_EV6_MMU,
 	DO_DEFAULT_RTC,
 	DO_TSUNAMI_IO,
-	DO_TSUNAMI_BUS,
 	.machine_check		= tsunami_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -671,7 +667,6 @@ struct alpha_machine_vector shark_mv __initmv = {
 	DO_EV6_MMU,
 	DO_DEFAULT_RTC,
 	DO_TSUNAMI_IO,
-	DO_TSUNAMI_BUS,
 	.machine_check		= tsunami_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff --git a/arch/alpha/kernel/sys_eb64p.c b/arch/alpha/kernel/sys_eb64p.c
index 035af0b47..32d9c350b 100644
--- a/arch/alpha/kernel/sys_eb64p.c
+++ b/arch/alpha/kernel/sys_eb64p.c
@@ -212,7 +212,6 @@ struct alpha_machine_vector eb64p_mv __initmv = {
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_APECS_IO,
-	DO_APECS_BUS,
 	.machine_check		= apecs_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -238,7 +237,6 @@ struct alpha_machine_vector eb66_mv __initmv = {
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_LCA_IO,
-	DO_LCA_BUS,
 	.machine_check		= lca_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff --git a/arch/alpha/kernel/sys_eiger.c b/arch/alpha/kernel/sys_eiger.c
index c6cbf4780..f98be3e85 100644
--- a/arch/alpha/kernel/sys_eiger.c
+++ b/arch/alpha/kernel/sys_eiger.c
@@ -222,7 +222,6 @@ struct alpha_machine_vector eiger_mv __initmv = {
 	DO_EV6_MMU,
 	DO_DEFAULT_RTC,
 	DO_TSUNAMI_IO,
-	DO_TSUNAMI_BUS,
 	.machine_check		= tsunami_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff --git a/arch/alpha/kernel/sys_jensen.c b/arch/alpha/kernel/sys_jensen.c
index ed6ce2f31..fcabb7c96 100644
--- a/arch/alpha/kernel/sys_jensen.c
+++ b/arch/alpha/kernel/sys_jensen.c
@@ -249,8 +249,6 @@ jensen_machine_check (u64 vector, u64 la, struct pt_regs *regs)
 	printk(KERN_CRIT "Machine check\n");
 }
 
-#define jensen_pci_tbi	((void*)0)
-
 
 /*
  * The System Vector
@@ -260,7 +258,6 @@ struct alpha_machine_vector jensen_mv __initmv = {
 	.vector_name		= "Jensen",
 	DO_EV4_MMU,
 	IO_LITE(JENSEN,jensen),
-	BUS(jensen),
 	.machine_check		= jensen_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.rtc_port		= 0x170,
diff --git a/arch/alpha/kernel/sys_marvel.c b/arch/alpha/kernel/sys_marvel.c
index 561122bea..52873d5fc 100644
--- a/arch/alpha/kernel/sys_marvel.c
+++ b/arch/alpha/kernel/sys_marvel.c
@@ -471,7 +471,6 @@ struct alpha_machine_vector marvel_ev7_mv __initmv = {
 	DO_EV7_MMU,
 	DO_DEFAULT_RTC,
 	DO_MARVEL_IO,
-	DO_MARVEL_BUS,
 	.machine_check		= marvel_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff --git a/arch/alpha/kernel/sys_miata.c b/arch/alpha/kernel/sys_miata.c
index a8cd711e8..61ac56f8e 100644
--- a/arch/alpha/kernel/sys_miata.c
+++ b/arch/alpha/kernel/sys_miata.c
@@ -269,7 +269,6 @@ struct alpha_machine_vector miata_mv __initmv = {
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_PYXIS_IO,
-	DO_CIA_BUS,
 	.machine_check		= cia_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff --git a/arch/alpha/kernel/sys_mikasa.c b/arch/alpha/kernel/sys_mikasa.c
index 57ed49d57..a55c109f5 100644
--- a/arch/alpha/kernel/sys_mikasa.c
+++ b/arch/alpha/kernel/sys_mikasa.c
@@ -221,7 +221,6 @@ struct alpha_machine_vector mikasa_mv __initmv = {
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_APECS_IO,
-	DO_APECS_BUS,
 	.machine_check		= mikasa_apecs_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -246,7 +245,6 @@ struct alpha_machine_vector mikasa_primo_mv __initmv = {
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_CIA_IO,
-	DO_CIA_BUS,
 	.machine_check		= cia_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
index fcf04ed3b..dd3bdedb7 100644
--- a/arch/alpha/kernel/sys_nautilus.c
+++ b/arch/alpha/kernel/sys_nautilus.c
@@ -250,7 +250,6 @@ struct alpha_machine_vector nautilus_mv __initmv = {
 	DO_EV6_MMU,
 	DO_DEFAULT_RTC,
 	DO_IRONGATE_IO,
-	DO_IRONGATE_BUS,
 	.machine_check		= nautilus_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff --git a/arch/alpha/kernel/sys_noritake.c b/arch/alpha/kernel/sys_noritake.c
index e974cdbe6..02363fa79 100644
--- a/arch/alpha/kernel/sys_noritake.c
+++ b/arch/alpha/kernel/sys_noritake.c
@@ -303,7 +303,6 @@ struct alpha_machine_vector noritake_mv __initmv = {
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_APECS_IO,
-	DO_APECS_BUS,
 	.machine_check		= noritake_apecs_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= EISA_DEFAULT_IO_BASE,
@@ -328,7 +327,6 @@ struct alpha_machine_vector noritake_primo_mv __initmv = {
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_CIA_IO,
-	DO_CIA_BUS,
 	.machine_check		= cia_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= EISA_DEFAULT_IO_BASE,
diff --git a/arch/alpha/kernel/sys_rawhide.c b/arch/alpha/kernel/sys_rawhide.c
index 0724393a4..38d32bc3e 100644
--- a/arch/alpha/kernel/sys_rawhide.c
+++ b/arch/alpha/kernel/sys_rawhide.c
@@ -250,7 +250,6 @@ struct alpha_machine_vector rawhide_mv __initmv = {
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_MCPCIA_IO,
-	DO_MCPCIA_BUS,
 	.machine_check		= mcpcia_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff --git a/arch/alpha/kernel/sys_ruffian.c b/arch/alpha/kernel/sys_ruffian.c
index ccabcb1e3..78c30decf 100644
--- a/arch/alpha/kernel/sys_ruffian.c
+++ b/arch/alpha/kernel/sys_ruffian.c
@@ -220,7 +220,6 @@ struct alpha_machine_vector ruffian_mv __initmv = {
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_PYXIS_IO,
-	DO_CIA_BUS,
 	.machine_check		= cia_machine_check,
 	.max_isa_dma_address	= ALPHA_RUFFIAN_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff --git a/arch/alpha/kernel/sys_rx164.c b/arch/alpha/kernel/sys_rx164.c
index 3dcbd2717..dfe16bc12 100644
--- a/arch/alpha/kernel/sys_rx164.c
+++ b/arch/alpha/kernel/sys_rx164.c
@@ -201,7 +201,6 @@ struct alpha_machine_vector rx164_mv __initmv = {
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_POLARIS_IO,
-	DO_POLARIS_BUS,
 	.machine_check		= polaris_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff --git a/arch/alpha/kernel/sys_sable.c b/arch/alpha/kernel/sys_sable.c
index e129e0e80..17423dd8c 100644
--- a/arch/alpha/kernel/sys_sable.c
+++ b/arch/alpha/kernel/sys_sable.c
@@ -566,7 +566,6 @@ struct alpha_machine_vector sable_mv __initmv = {
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_T2_IO,
-	DO_T2_BUS,
 	.machine_check		= t2_machine_check,
 	.max_isa_dma_address	= ALPHA_SABLE_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= EISA_DEFAULT_IO_BASE,
@@ -599,7 +598,6 @@ struct alpha_machine_vector sable_gamma_mv __initmv = {
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_T2_IO,
-	DO_T2_BUS,
 	.machine_check		= t2_machine_check,
 	.max_isa_dma_address	= ALPHA_SABLE_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= EISA_DEFAULT_IO_BASE,
@@ -631,7 +629,6 @@ struct alpha_machine_vector lynx_mv __initmv = {
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_T2_IO,
-	DO_T2_BUS,
 	.machine_check		= t2_machine_check,
 	.max_isa_dma_address	= ALPHA_SABLE_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= EISA_DEFAULT_IO_BASE,
diff --git a/arch/alpha/kernel/sys_sio.c b/arch/alpha/kernel/sys_sio.c
index 177e1275d..47df48a6d 100644
--- a/arch/alpha/kernel/sys_sio.c
+++ b/arch/alpha/kernel/sys_sio.c
@@ -288,7 +288,6 @@ struct alpha_machine_vector alphabook1_mv __initmv = {
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_LCA_IO,
-	DO_LCA_BUS,
 	.machine_check		= lca_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -319,7 +318,6 @@ struct alpha_machine_vector avanti_mv __initmv = {
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_APECS_IO,
-	DO_APECS_BUS,
 	.machine_check		= apecs_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -349,7 +347,6 @@ struct alpha_machine_vector noname_mv __initmv = {
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_LCA_IO,
-	DO_LCA_BUS,
 	.machine_check		= lca_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -388,7 +385,6 @@ struct alpha_machine_vector p2k_mv __initmv = {
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_LCA_IO,
-	DO_LCA_BUS,
 	.machine_check		= lca_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -418,7 +414,6 @@ struct alpha_machine_vector xl_mv __initmv = {
 	DO_EV4_MMU,
 	DO_DEFAULT_RTC,
 	DO_APECS_IO,
-	BUS(apecs),
 	.machine_check		= apecs_machine_check,
 	.max_isa_dma_address	= ALPHA_XL_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff --git a/arch/alpha/kernel/sys_sx164.c b/arch/alpha/kernel/sys_sx164.c
index d8f771a98..3ee73b68e 100644
--- a/arch/alpha/kernel/sys_sx164.c
+++ b/arch/alpha/kernel/sys_sx164.c
@@ -158,7 +158,6 @@ struct alpha_machine_vector sx164_mv __initmv = {
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_PYXIS_IO,
-	DO_CIA_BUS,
 	.machine_check		= cia_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff --git a/arch/alpha/kernel/sys_takara.c b/arch/alpha/kernel/sys_takara.c
index 126c433a6..7955bdfc2 100644
--- a/arch/alpha/kernel/sys_takara.c
+++ b/arch/alpha/kernel/sys_takara.c
@@ -277,7 +277,6 @@ struct alpha_machine_vector takara_mv __initmv = {
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
 	DO_CIA_IO,
-	DO_CIA_BUS,
 	.machine_check		= cia_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff --git a/arch/alpha/kernel/sys_titan.c b/arch/alpha/kernel/sys_titan.c
index 1114bf7ec..4466af674 100644
--- a/arch/alpha/kernel/sys_titan.c
+++ b/arch/alpha/kernel/sys_titan.c
@@ -66,7 +66,7 @@ titan_update_irq_hw(unsigned long mask)
 	register int bcpu = boot_cpuid;
 
 #ifdef CONFIG_SMP
-	register unsigned long cpm = cpu_present_mask;
+	cpumask_t cpm = cpu_present_mask;
 	volatile unsigned long *dim0, *dim1, *dim2, *dim3;
 	unsigned long mask0, mask1, mask2, mask3, dummy;
 
@@ -85,10 +85,10 @@ titan_update_irq_hw(unsigned long mask)
 	dim1 = &cchip->dim1.csr;
 	dim2 = &cchip->dim2.csr;
 	dim3 = &cchip->dim3.csr;
-	if ((cpm & 1) == 0) dim0 = &dummy;
-	if ((cpm & 2) == 0) dim1 = &dummy;
-	if ((cpm & 4) == 0) dim2 = &dummy;
-	if ((cpm & 8) == 0) dim3 = &dummy;
+	if (!cpu_isset(0, cpm)) dim0 = &dummy;
+	if (!cpu_isset(1, cpm)) dim1 = &dummy;
+	if (!cpu_isset(2, cpm)) dim2 = &dummy;
+	if (!cpu_isset(3, cpm)) dim3 = &dummy;
 
 	*dim0 = mask0;
 	*dim1 = mask1;
@@ -145,12 +145,12 @@ titan_end_irq(unsigned int irq)
 }
 
 static void
-titan_cpu_set_irq_affinity(unsigned int irq, unsigned long affinity)
+titan_cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity)
 {
 	int cpu;
 
 	for (cpu = 0; cpu < 4; cpu++) {
-		if (affinity & (1UL << cpu))
+		if (cpu_isset(cpu, affinity))
 			titan_cpu_irq_affinity[cpu] |= 1UL << irq;
 		else
 			titan_cpu_irq_affinity[cpu] &= ~(1UL << irq);
@@ -159,7 +159,7 @@ titan_cpu_set_irq_affinity(unsigned int irq, unsigned long affinity)
 }
 
 static void
-titan_set_irq_affinity(unsigned int irq, unsigned long affinity)
+titan_set_irq_affinity(unsigned int irq, cpumask_t affinity)
 { 
 	spin_lock(&titan_irq_lock);
 	titan_cpu_set_irq_affinity(irq - 16, affinity);
@@ -369,7 +369,6 @@ struct alpha_machine_vector titan_mv __initmv = {
 	DO_EV6_MMU,
 	DO_DEFAULT_RTC,
 	DO_TITAN_IO,
-	DO_TITAN_BUS,
 	.machine_check		= titan_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
@@ -397,7 +396,6 @@ struct alpha_machine_vector privateer_mv __initmv = {
 	DO_EV6_MMU,
 	DO_DEFAULT_RTC,
 	DO_TITAN_IO,
-	DO_TITAN_BUS,
 	.machine_check		= privateer_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff --git a/arch/alpha/kernel/sys_wildfire.c b/arch/alpha/kernel/sys_wildfire.c
index 35b0f4c6f..959e8d7df 100644
--- a/arch/alpha/kernel/sys_wildfire.c
+++ b/arch/alpha/kernel/sys_wildfire.c
@@ -337,7 +337,6 @@ struct alpha_machine_vector wildfire_mv __initmv = {
 	DO_EV6_MMU,
 	DO_DEFAULT_RTC,
 	DO_WILDFIRE_IO,
-	DO_WILDFIRE_BUS,
 	.machine_check		= wildfire_machine_check,
 	.max_isa_dma_address	= ALPHA_MAX_ISA_DMA_ADDRESS,
 	.min_io_address		= DEFAULT_IO_BASE,
diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S
index bf9c1a2b9..a36ae26cb 100644
--- a/arch/alpha/kernel/systbls.S
+++ b/arch/alpha/kernel/systbls.S
@@ -457,6 +457,7 @@ sys_call_table:
 	.quad sys_mq_timedreceive		/* 435 */
 	.quad sys_mq_notify
 	.quad sys_mq_getsetattr
+	.quad sys_waitid
 
 	.size sys_call_table, . - sys_call_table
 	.type sys_call_table, @object
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index 711124368..5ff439b04 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -41,6 +41,7 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/bcd.h>
+#include <linux/profile.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -118,8 +119,7 @@ irqreturn_t timer_interrupt(int irq, void *dev, struct pt_regs * regs)
 
 #ifndef CONFIG_SMP
 	/* Not SMP, do kernel PC profiling here.  */
-	if (!user_mode(regs))
-		alpha_do_profile(regs->pc);
+	profile_tick(CPU_PROFILING, regs);
 #endif
 
 	write_seqlock(&xtime_lock);
@@ -366,7 +366,7 @@ time_init(void)
 		BCD_TO_BIN(year);
 	}
 
-	/* PC-like is standard; used for year < 20 || year >= 70 */
+	/* PC-like is standard; used for year >= 70 */
 	epoch = 1900;
 	if (year < 20)
 		epoch = 2000;
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
index 2248735b8..fd7bd17cc 100644
--- a/arch/alpha/kernel/traps.c
+++ b/arch/alpha/kernel/traps.c
@@ -65,6 +65,8 @@ dik_show_regs(struct pt_regs *regs, unsigned long *r9_15)
 {
 	printk("pc = [<%016lx>]  ra = [<%016lx>]  ps = %04lx    %s\n",
 	       regs->pc, regs->r26, regs->ps, print_tainted());
+	print_symbol("pc is at %s\n", regs->pc);
+	print_symbol("ra is at %s\n", regs->r26 );
 	printk("v0 = %016lx  t0 = %016lx  t1 = %016lx\n",
 	       regs->r0, regs->r1, regs->r2);
 	printk("t2 = %016lx  t3 = %016lx  t4 = %016lx\n",
@@ -109,7 +111,7 @@ dik_show_code(unsigned int *pc)
 	printk("Code:");
 	for (i = -6; i < 2; i++) {
 		unsigned int insn;
-		if (__get_user(insn, pc+i))
+		if (__get_user(insn, (unsigned int __user *)pc + i))
 			break;
 		printk("%c%08x%c", i ? ' ' : '<', insn, i ? ' ' : '>');
 	}
diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S
index d159b8f0d..0922e0785 100644
--- a/arch/alpha/kernel/vmlinux.lds.S
+++ b/arch/alpha/kernel/vmlinux.lds.S
@@ -18,6 +18,7 @@ SECTIONS
   .text : { 
 	*(.text) 
 	SCHED_TEXT
+	LOCK_TEXT
 	*(.fixup)
 	*(.gnu.warning)
   } :kernel
@@ -45,11 +46,6 @@ SECTIONS
   .init.setup : { *(.init.setup) }
   __setup_end = .;
 
-  . = ALIGN(8);
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
-
   . = ALIGN(8);
   __initcall_start = .;
   .initcall.init : {
diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile
index a62309953..21cf624d7 100644
--- a/arch/alpha/lib/Makefile
+++ b/arch/alpha/lib/Makefile
@@ -17,7 +17,6 @@ lib-y =	__divqu.o __remqu.o __divlu.o __remlu.o \
 	$(ev6-y)memset.o \
 	$(ev6-y)memcpy.o \
 	memmove.o \
-	io.o \
 	checksum.o \
 	csum_partial_copy.o \
 	$(ev67-y)strlen.o \
diff --git a/arch/alpha/lib/csum_partial_copy.c b/arch/alpha/lib/csum_partial_copy.c
index 3e0da493b..4af102219 100644
--- a/arch/alpha/lib/csum_partial_copy.c
+++ b/arch/alpha/lib/csum_partial_copy.c
@@ -193,7 +193,8 @@ csum_partial_cfu_dest_aligned(const unsigned long __user *src,
  * This is slightly less fun than the above..
  */
 static inline unsigned long
-csum_partial_cfu_src_aligned(const unsigned long *src, unsigned long *dst,
+csum_partial_cfu_src_aligned(const unsigned long __user *src,
+			     unsigned long *dst,
 			     unsigned long doff,
 			     long len, unsigned long checksum,
 			     unsigned long partial_dest,
@@ -372,7 +373,7 @@ unsigned int
 csum_partial_copy_from_user(const char __user *src, char *dst, int len,
 			    unsigned int sum, int *errp)
 {
-	if (!access_ok(src, len, VERIFY_READ)) {
+	if (!access_ok(VERIFY_READ, src, len)) {
 		*errp = -EFAULT;
 		memset(dst, 0, len);
 		return sum;
diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c
index a0b969ddf..64ace5a9c 100644
--- a/arch/alpha/mm/fault.c
+++ b/arch/alpha/mm/fault.c
@@ -98,7 +98,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
 	   by ignoring such an instruction.  */
 	if (cause == 0) {
 		unsigned int insn;
-		__get_user(insn, (unsigned int *)regs->pc);
+		__get_user(insn, (unsigned int __user *)regs->pc);
 		if ((insn >> 21 & 0x1f) == 0x1f &&
 		    /* ldq ldl ldt lds ldg ldf ldwu ldbu */
 		    (1ul << (insn >> 26) & 0x30f00001400ul)) {
diff --git a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c
index 31a3f6343..a839578e9 100644
--- a/arch/alpha/mm/numa.c
+++ b/arch/alpha/mm/numa.c
@@ -313,7 +313,7 @@ void __init paging_init(void)
 			zones_size[ZONE_DMA] = dma_local_pfn;
 			zones_size[ZONE_NORMAL] = (end_pfn - start_pfn) - dma_local_pfn;
 		}
-		free_area_init_node(nid, NODE_DATA(nid), NULL, zones_size, start_pfn, NULL);
+		free_area_init_node(nid, NODE_DATA(nid), zones_size, start_pfn, NULL);
 	}
 
 	/* Initialize the kernel's ZERO_PGE. */
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index e4435a443..096ea1dd3 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -63,8 +63,11 @@ config GENERIC_BUST_SPINLOCK
 config GENERIC_ISA_DMA
 	bool
 
-source "init/Kconfig"
+config GENERIC_IOMAP
+	bool
+	default y
 
+source "init/Kconfig"
 
 menu "System Type"
 
@@ -108,6 +111,9 @@ config ARCH_IOP3XX
 config ARCH_IXP4XX
 	bool "IXP4xx-based"
 
+config ARCH_IXP2000
+	bool "IXP2400/2800-based"
+
 config ARCH_L7200
 	bool "LinkUp-L7200"
 	help
@@ -158,6 +164,14 @@ config ARCH_VERSATILE_PB
 	help
 	  This enables support for ARM Ltd Versatile PB board.
 
+config ARCH_IMX
+	bool "IMX"
+
+config ARCH_H720X
+	bool "Hynix-HMS720x-based"
+	help
+	  This enables support for systems based on the Hynix HMS720x
+
 endchoice
 
 source "arch/arm/mach-clps711x/Kconfig"
@@ -172,6 +186,8 @@ source "arch/arm/mach-iop3xx/Kconfig"
 
 source "arch/arm/mach-ixp4xx/Kconfig"
 
+source "arch/arm/mach-ixp2000/Kconfig"
+
 source "arch/arm/mach-pxa/Kconfig"
 
 source "arch/arm/mach-sa1100/Kconfig"
@@ -182,6 +198,10 @@ source "arch/arm/mach-s3c2410/Kconfig"
 
 source "arch/arm/mach-lh7a40x/Kconfig"
 
+source "arch/arm/mach-imx/Kconfig"
+
+source "arch/arm/mach-h720x/Kconfig"
+
 # Definitions to make life easier
 config ARCH_ACORN
 	bool
@@ -247,7 +267,6 @@ config XSCALE_PMU
 
 endmenu
 
-
 menu "General setup"
 
 # Select various configuration options depending on the machine type
@@ -264,7 +283,7 @@ config DISCONTIGMEM
 # Now handle the bus types
 config PCI
 	bool "PCI support" if ARCH_INTEGRATOR_AP
-	default y if ARCH_SHARK || FOOTBRIDGE_HOST || ARCH_IOP3XX || ARCH_IXP4XX
+	default y if ARCH_SHARK || FOOTBRIDGE_HOST || ARCH_IOP3XX || ARCH_IXP4XX || ARCH_IXP2000
 	help
 	  Find out whether you have a PCI motherboard. PCI is the name of a
 	  bus system, i.e. the way the CPU talks to the other stuff inside
@@ -294,7 +313,7 @@ config ARM_AMBA
 
 config ISA
 	bool
-	depends on FOOTBRIDGE_HOST || ARCH_SHARK || ARCH_CLPS7500 || ARCH_EBSA110 || ARCH_CDB89712 || ARCH_EDB7211 || ARCH_SA1100
+	depends on FOOTBRIDGE_HOST || ARCH_SHARK || ARCH_CLPS7500 || ARCH_EBSA110 || ARCH_CDB89712 || ARCH_EDB7211 || ARCH_SA1100 || ARCH_MX1ADS
 	default y
 	help
 	  Find out whether you have ISA slots on your motherboard.  ISA is the
@@ -399,7 +418,7 @@ config FPE_NWFPE
 
 config FPE_NWFPE_XP
 	bool "Support extended precision"
-	depends on FPE_NWFPE
+	depends on FPE_NWFPE && !CPU_BIG_ENDIAN
 	help
 	  Say Y to include 80-bit support in the kernel floating-point
 	  emulator.  Otherwise, only 32 and 64-bit support is compiled in.
@@ -425,6 +444,7 @@ config FPE_FASTFPE
 
 config VFP
 	bool "VFP-format floating point maths"
+	depends on CPU_V6 || CPU_ARM926T
 	help
 	  Say Y to include VFP support code in the kernel. This is needed
 	  if your hardware includes a VFP unit.
@@ -552,7 +572,7 @@ config CMDLINE
 
 config LEDS
 	bool "Timer and CPU usage LEDs"
-	depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB
+	depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB || ARCH_IMX
 	help
 	  If you say Y here, the LEDs on your machine will be used
 	  to provide useful information about your current system status.
@@ -565,8 +585,8 @@ config LEDS
 	  system, but the driver will do nothing.
 
 config LEDS_TIMER
-	bool "Timer LED" if LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || MACH_MAINSTONE || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE_PB)
-	depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB
+	bool "Timer LED" if LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || MACH_MAINSTONE || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE_PB || ARCH_IMX)
+	depends on ARCH_NETWINDER || ARCH_EBSA110 || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_CDB89712 || ARCH_P720T || ARCH_OMAP || ARCH_VERSATILE_PB || ARCH_IMX
 	default y if ARCH_EBSA110
 	help
 	  If you say Y here, one of the system LEDs (the green one on the
@@ -581,7 +601,7 @@ config LEDS_TIMER
 
 config LEDS_CPU
 	bool "CPU usage LED"
-	depends on LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE_PB)
+	depends on LEDS && (ARCH_NETWINDER || ARCH_EBSA285 || ARCH_SHARK || ARCH_CO285 || ARCH_SA1100 || ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_PXA_IDP || ARCH_INTEGRATOR || ARCH_P720T || ARCH_VERSATILE_PB || ARCH_IMX)
 	help
 	  If you say Y here, the red LED will be used to give a good real
 	  time indication of CPU usage, by lighting whenever the idle task
@@ -661,165 +681,9 @@ source "drivers/misc/Kconfig"
 
 source "drivers/usb/Kconfig"
 
+source "drivers/mmc/Kconfig"
 
-menu "Kernel hacking"
-
-# RMK wants arm kernels compiled with frame pointers so hardwire this to y.
-# If you know what you are doing and are willing to live without stack
-# traces, you can get a slightly smaller kernel by setting this option to
-# n, but then RMK will have to kill you ;).
-config FRAME_POINTER
-	bool
-	default y
-	help
-	  If you say N here, the resulting kernel will be slightly smaller and
-	  faster. However, when a problem occurs with the kernel, the
-	  information that is reported is severely limited. Most people
-	  should say Y here.
-
-config DEBUG_USER
-	bool "Verbose user fault messages"
-	help
-	  When a user program crashes due to an exception, the kernel can
-	  print a brief message explaining what the problem was. This is
-	  sometimes helpful for debugging but serves no purpose on a
-	  production system. Most people should say N here.
-
-	  In addition, you need to pass user_debug=N on the kernel command
-	  line to enable this feature.  N consists of the sum of:
-
-	      1 - undefined instruction events
-	      2 - system calls
-	      4 - invalid data aborts
-	      8 - SIGSEGV faults
-	     16 - SIGBUS faults
-
-config DEBUG_INFO
-	bool "Include GDB debugging information in kernel binary"
-	help
-	  Say Y here to include source-level debugging information in the
-	  `vmlinux' binary image. This is handy if you want to use gdb or
-	  addr2line to debug the kernel. It has no impact on the in-memory
-	  footprint of the running kernel but it can increase the amount of
-	  time and disk space needed for compilation of the kernel. If in
-	  doubt say N.
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SPINLOCK
-	bool "Spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here and build SMP to catch missing spinlock initialization
-	  and certain other kinds of spinlock errors commonly made.  This is
-	  best used in conjunction with the NMI watchdog so that spinlock
-	  deadlocks are also debuggable.
-
-config DEBUG_WAITQ
-	bool "Wait queue debugging"
-	depends on DEBUG_KERNEL
-
-config DEBUG_BUGVERBOSE
-	bool "Verbose BUG() reporting (adds 70K)"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to make BUG() panics output the file name and line number
-	  of the BUG call as well as the EIP and oops trace.  This aids
-	  debugging but costs about 70-100K of memory.
-
-config DEBUG_ERRORS
-	bool "Verbose kernel error messages"
-	depends on DEBUG_KERNEL
-	help
-	  This option controls verbose debugging information which can be
-	  printed when the kernel detects an internal error. This debugging
-	  information is useful to kernel hackers when tracking down problems,
-	  but mostly meaningless to other people. It's safe to say Y unless
-	  you are concerned with the code size or don't want to see these
-	  messages.
-
-# These options are only for real kernel hackers who want to get their hands dirty. 
-config DEBUG_LL
-	bool "Kernel low-level debugging functions"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to include definitions of printascii, printchar, printhex
-	  in the kernel.  This is helpful if you are debugging code that
-	  executes before the console is initialized.
-
-config DEBUG_ICEDCC
-	bool "Kernel low-level debugging via EmbeddedICE DCC channel"
-	depends on DEBUG_LL
-	help
-	  Say Y here if you want the debug print routines to direct their
-	  output to the EmbeddedICE macrocell's DCC channel using
-	  co-processor 14. This is known to work on the ARM9 style ICE
-	  channel.
-
-	  It does include a timeout to ensure that the system does not
-	  totally freeze when there is nothing connected to read.
-
-config DEBUG_DC21285_PORT
-	bool "Kernel low-level debugging messages via footbridge serial port"
-	depends on DEBUG_LL && FOOTBRIDGE
-	help
-	  Say Y here if you want the debug print routines to direct their
-	  output to the serial port in the DC21285 (Footbridge). Saying N
-	  will cause the debug messages to appear on the first 16550
-	  serial port.
-
-config DEBUG_CLPS711X_UART2
-	bool "Kernel low-level debugging messages via UART2"
-	depends on DEBUG_LL && ARCH_CLPS711X
-	help
-	  Say Y here if you want the debug print routines to direct their
-	  output to the second serial port on these devices.  Saying N will
-	  cause the debug messages to appear on the first serial port.
-
-config DEBUG_S3C2410_PORT
-	depends on DEBUG_LL && ARCH_S3C2410
-	bool "Kernel low-level debugging messages via S3C2410 UART"
-	help
-	  Say Y here if you want debug print routines to go to one of the
-	  S3C2410 internal UARTs. The chosen UART must have been configured
-	  before it is used.
-
-config DEBUG_S3C2410_UART
-	depends on DEBUG_LL && ARCH_S3C2410
-	int "S3C2410 UART to use for low-level debug"
-	default "0"
-	help
-	  Choice for UART for kernel low-level using S3C2410 UARTS,
-	  should be between zero and two. The port must have been
-	  initalised by the boot-loader before use.
-
-endmenu
+source "arch/arm/Kconfig.debug"
 
 source "kernel/vserver/Kconfig"
 
@@ -828,4 +692,3 @@ source "security/Kconfig"
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 8b34b0d8a..a4878a0ae 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -8,8 +8,7 @@
 # Copyright (C) 1995-2001 by Russell King
 
 LDFLAGS_vmlinux	:=-p --no-undefined -X
-LDFLAGS_BLOB	:=--format binary
-AFLAGS_vmlinux.lds.o = -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
+CPPFLAGS_vmlinux.lds = -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
 OBJCOPYFLAGS	:=-O binary -R .note -R .comment -S
 GZFLAGS		:=-9
 #CFLAGS		+=-pipe
@@ -36,8 +35,8 @@ comma = ,
 # Note that GCC does not numerically define an architecture version
 # macro, but instead defines a whole series of macros which makes
 # testing for a specific architecture or later rather impossible.
-arch-$(CONFIG_CPU_32v6)		:=-D__LINUX_ARM_ARCH__=6 $(call check_gcc,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6)
-arch-$(CONFIG_CPU_32v5)		:=-D__LINUX_ARM_ARCH__=5 $(call check_gcc,-march=armv5te,-march=armv4)
+arch-$(CONFIG_CPU_32v6)		:=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6)
+arch-$(CONFIG_CPU_32v5)		:=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4)
 arch-$(CONFIG_CPU_32v4)		:=-D__LINUX_ARM_ARCH__=4 -march=armv4
 arch-$(CONFIG_CPU_32v3)		:=-D__LINUX_ARM_ARCH__=3 -march=armv3
 
@@ -51,14 +50,14 @@ tune-$(CONFIG_CPU_ARM925T)	:=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_ARM926T)	:=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_SA110)	:=-mtune=strongarm110
 tune-$(CONFIG_CPU_SA1100)	:=-mtune=strongarm1100
-tune-$(CONFIG_CPU_XSCALE)	:=$(call check_gcc,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
+tune-$(CONFIG_CPU_XSCALE)	:=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
 tune-$(CONFIG_CPU_V6)		:=-mtune=strongarm
 
 # Need -Uarm for gcc < 3.x
-CFLAGS		+=-mapcs-32 $(arch-y) $(tune-y) $(call check_gcc,-malignment-traps,-mshort-load-bytes) -msoft-float -Wa,-mno-fpu -Uarm
-AFLAGS		+=-mapcs-32 $(arch-y) $(tune-y) -msoft-float -Wa,-mno-fpu
+CFLAGS		+=-mapcs-32 $(arch-y) $(tune-y) $(call cc-option,-malignment-traps,-mshort-load-bytes) -msoft-float -Uarm
+AFLAGS		+=-mapcs-32 $(arch-y) $(tune-y) -msoft-float
 
-CHECK		:= $(CHECK) -D__arm__=1
+CHECKFLAGS	+= -D__arm__
 
 #Default value
 DATAADDR	:= .
@@ -90,10 +89,13 @@ textaddr-$(CONFIG_ARCH_CLPS711X)   := 0xc0028000
 textaddr-$(CONFIG_ARCH_FORTUNET)   := 0xc0008000
  machine-$(CONFIG_ARCH_IOP3XX)	   := iop3xx
  machine-$(CONFIG_ARCH_IXP4XX)	   := ixp4xx
+ machine-$(CONFIG_ARCH_IXP2000)    := ixp2000
  machine-$(CONFIG_ARCH_OMAP)	   := omap
  machine-$(CONFIG_ARCH_S3C2410)	   := s3c2410
  machine-$(CONFIG_ARCH_LH7A40X)	   := lh7a40x
  machine-$(CONFIG_ARCH_VERSATILE_PB) := versatile
+ machine-$(CONFIG_ARCH_IMX)	   := imx
+ machine-$(CONFIG_ARCH_H720X)	   := h720x
 
 ifeq ($(CONFIG_ARCH_EBSA110),y)
 # This is what happens if you forget the IOCS16 line.
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index c247afdd7..cfb4a252a 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -47,10 +47,19 @@ endif
 params_phys-$(CONFIG_ARCH_SA1100)	:= 0xc0000100
 initrd_phys-$(CONFIG_ARCH_SA1100)	:= 0xc0800000
    zreladdr-$(CONFIG_ARCH_PXA)		:= 0xa0008000
+   zreladdr-$(CONFIG_ARCH_MX1ADS)	:= 0x08008000
    zreladdr-$(CONFIG_ARCH_IOP3XX)	:= 0xa0008000
 params_phys-$(CONFIG_ARCH_IOP3XX)	:= 0xa0000100
+initrd_phys-$(CONFIG_ARCH_IOP3XX)   	:= 0xa0800000
+ifeq ($(CONFIG_ARCH_IOP331),y)
+   zreladdr-$(CONFIG_ARCH_IOP3XX)      	:= 0x00008000
+params_phys-$(CONFIG_ARCH_IOP3XX)      	:= 0x00000100
+initrd_phys-$(CONFIG_ARCH_IOP3XX)      	:= 0x00800000
+endif
    zreladdr-$(CONFIG_ARCH_IXP4XX)	:= 0x00008000
 params-phys-$(CONFIG_ARCH_IXP4XX)	:= 0x00000100
+   zreladdr-$(CONFIG_ARCH_IXP2000)	:= 0x00008000
+params-phys-$(CONFIG_ARCH_IXP2000)	:= 0x00000100
    zreladdr-$(CONFIG_ARCH_OMAP)		:= 0x10008000
 params_phys-$(CONFIG_ARCH_OMAP)		:= 0x10000100
 initrd_phys-$(CONFIG_ARCH_OMAP)		:= 0x10800000
@@ -62,6 +71,7 @@ params_phys-$(CONFIG_ARCH_S3C2410)	:= 0x30000100
    zreladdr-$(CONFIG_ARCH_VERSATILE_PB)	:= 0x00008000
 params_phys-$(CONFIG_ARCH_VERSATILE_PB)	:= 0x00000100
 initrd_phys-$(CONFIG_ARCH_VERSATILE_PB)	:= 0x00800000
+   zreladdr-$(CONFIG_ARCH_H720X)	:= 0x40008000
 
 ZRELADDR    := $(zreladdr-y)
 PARAMS_PHYS := $(params_phys-y)
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 951fbf6e8..e9e0c68a3 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -8,11 +8,13 @@ HEAD	= head.o
 OBJS	= misc.o
 FONTC	= drivers/video/console/font_acorn_8x8.c
 
+FONT = $(addprefix ../../../../drivers/video/console/, font_acorn_8x8.o)
+
 #
 # Architecture dependencies
 #
 ifeq ($(CONFIG_ARCH_ACORN),y)
-OBJS		+= ll_char_wr.o font.o
+OBJS		+= ll_char_wr.o $(FONT)
 endif
 
 ifeq ($(CONFIG_ARCH_SHARK),y)
@@ -51,6 +53,10 @@ ifeq ($(CONFIG_DEBUG_ICEDCC),y)
 OBJS            += ice-dcc.o
 endif
 
+ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
+OBJS		+= big-endian.o
+endif
+
 #
 # We now have a PIC decompressor implementation.  Decompressors running
 # from RAM should not define ZTEXTADDR.  Decompressors running directly
@@ -66,7 +72,7 @@ endif
 
 SEDFLAGS	= s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
 
-targets       := vmlinux vmlinux.lds piggy.gz piggy.o font.o \
+targets       := vmlinux vmlinux.lds piggy.gz piggy.o $(FONT) \
 		 head.o misc.o $(OBJS)
 EXTRA_CFLAGS  := -fpic
 EXTRA_AFLAGS  :=
@@ -98,8 +104,7 @@ $(obj)/piggy.gz: $(obj)/../Image FORCE
 
 $(obj)/piggy.o:  $(obj)/piggy.gz FORCE
 
-CFLAGS_font.o := -Dstatic=
-$(obj)/font.o: $(FONTC)
+CFLAGS_font_acorn_8x8.o := -Dstatic=
 
 $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile .config
 	@sed "$(SEDFLAGS)" < $< > $@
diff --git a/arch/arm/boot/compressed/head-xscale.S b/arch/arm/boot/compressed/head-xscale.S
index f9194499e..637e63773 100644
--- a/arch/arm/boot/compressed/head-xscale.S
+++ b/arch/arm/boot/compressed/head-xscale.S
@@ -35,11 +35,19 @@ __XScale_start:
 		mcr	p15, 0, r0, c1, c0, 0
 
 #ifdef	CONFIG_ARCH_IQ80321
-		orr	pc, pc, #PHYS_OFFSET	@ jump to physical memory if we are not there.
-		nop
 		mov	r7, #MACH_TYPE_IQ80321
 #endif
 
+#ifdef  CONFIG_ARCH_IQ31244
+		mov	r7, #(MACH_TYPE_IQ31244 & 0xff)
+		orr	r7, r7, #(MACH_TYPE_IQ31244 & 0xff00)
+#endif
+
+#ifdef  CONFIG_ARCH_IQ80331
+		mov	r7, #(MACH_TYPE_IQ80331 & 0xff)
+		orr	r7, r7, #(MACH_TYPE_IQ80331 & 0xff00)
+#endif
+
 #ifdef CONFIG_ARCH_LUBBOCK
 		mov	r7, #MACH_TYPE_LUBBOCK
 #endif
@@ -48,22 +56,3 @@ __XScale_start:
 		mov	r7, #MACH_TYPE_COTULLA_IDP
 #endif
 
-#ifdef CONFIG_ARCH_IQ80310
-		/*
-		 * Crank the CPU up to 733MHz
-		 */
-		mov	r1, #9
-		mcr	p14, 0, r1, c6, c0, 0
-
-		/*
-		 * Disable ECC error notification
-		 * At some point, we should add an ECC handler to Linux
-		 */
-		mov	r1, #0x1500
-		mov	r0, #0x4
-		str	r0, [r1, #0x34]
-
-		mov	r7, #MACH_TYPE_IQ80310
-#endif
-
-
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index b47032c2d..f560cbf35 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -79,6 +79,14 @@
 		.endm
 		.macro	writeb, rb
 		str	\rb, [r3, #0]
+#elif defined(CONFIG_ARCH_IXP2000)
+		.macro	loadsp, rb
+		mov	\rb, #0xc0000000
+		orr	\rb, \rb, #0x00030000
+		.endm
+		.macro	writeb, rb
+		str	\rb, [r3, #0]
+		.endm
 #elif defined(CONFIG_ARCH_LH7A40X)
 		.macro	loadsp, rb
 		ldr	\rb, =0x80000700	@ UART2 UARTBASE
@@ -100,6 +108,15 @@
 		.macro	writeb, rb
 		strb	\rb, [r3]
 		.endm
+#elif defined(CONFIG_ARCH_IOP331)
+		.macro loadsp, rb
+                mov   	\rb, #0xff000000
+                orr     \rb, \rb, #0x00ff0000
+                orr     \rb, \rb, #0x0000f700   @ location of the UART
+		.endm
+		.macro	writeb, rb
+		str	\rb, [r3, #0]
+		.endm
 #else
 #error no serial architecture defined
 #endif
@@ -332,6 +349,14 @@ LC0:		.word	LC0			@ r1
 LC1:		.word	reloc_end - reloc_start
 		.size	LC0, . - LC0
 
+#ifdef CONFIG_ARCH_RPC
+		.globl	params
+params:		ldr	r0, =params_phys
+		mov	pc, lr
+		.ltorg
+		.align
+#endif
+
 /*
  * Turn on the cache.  We need to setup some page tables so that we
  * can have both the I and D caches on.
@@ -568,6 +593,12 @@ proc_types:
 		b	__armv4_cache_off
 		b	__armv4_cache_flush
 
+		.word	0x00070000		@ ARMv6
+		.word	0x000f0000
+		b	__armv4_cache_on
+		b	__armv4_cache_off
+		b	__armv6_cache_flush
+
 		.word	0			@ unrecognised type
 		.word	0
 		mov	pc, lr
@@ -627,6 +658,14 @@ cache_clean_flush:
 		mov	r3, #16
 		b	call_cache_fn
 
+__armv6_cache_flush:
+		mov	r1, #0
+		mcr	p15, 0, r1, c7, c14, 0	@ clean+invalidate D
+		mcr	p15, 0, r1, c7, c5, 0	@ invalidate I+BTB
+		mcr	p15, 0, r1, c7, c15, 0	@ clean+invalidate unified
+		mcr	p15, 0, r1, c7, c10, 4	@ drain WB
+		mov	pc, lr
+
 __armv4_cache_flush:
 		mov	r2, #64*1024		@ default: 32K dcache size (*2)
 		mov	r11, #32		@ default: 32 byte line size
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c
index ebcac6cfb..23434b567 100644
--- a/arch/arm/boot/compressed/misc.c
+++ b/arch/arm/boot/compressed/misc.c
@@ -23,17 +23,17 @@ unsigned int __machine_arch_type;
 #include <asm/arch/uncompress.h>
 
 #ifdef STANDALONE_DEBUG
-#define puts printf
+#define putstr printf
 #endif
 
 #ifdef CONFIG_DEBUG_ICEDCC
-#define puts icedcc_puts
+#define putstr icedcc_putstr
 #define putc icedcc_putc
 
 extern void idedcc_putc(int ch);
 
 static void
-icedcc_puts(const char *ptr)
+icedcc_putstr(const char *ptr)
 {
 	for (; *ptr != '\0'; ptr++) {
 		icedcc_putc(*ptr);
@@ -191,7 +191,7 @@ static void error(char *m);
 static void gzip_mark(void **);
 static void gzip_release(void **);
 
-static void puts(const char *);
+static void putstr(const char *);
 
 extern int end;
 static ulg free_mem_ptr;
@@ -280,14 +280,14 @@ void flush_window(void)
 	bytes_out += (ulg)outcnt;
 	output_ptr += (ulg)outcnt;
 	outcnt = 0;
-	puts(".");
+	putstr(".");
 }
 
 static void error(char *x)
 {
-	puts("\n\n");
-	puts(x);
-	puts("\n\n -- System halted");
+	putstr("\n\n");
+	putstr(x);
+	putstr("\n\n -- System halted");
 
 	while(1);	/* Halt */
 }
@@ -306,9 +306,9 @@ decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p,
 	arch_decomp_setup();
 
 	makecrc();
-	puts("Uncompressing Linux...");
+	putstr("Uncompressing Linux...");
 	gunzip();
-	puts(" done, booting the kernel.\n");
+	putstr(" done, booting the kernel.\n");
 	return output_ptr;
 }
 #else
@@ -320,9 +320,9 @@ int main()
 	output_data = output_buffer;
 
 	makecrc();
-	puts("Uncompressing Linux...");
+	putstr("Uncompressing Linux...");
 	gunzip();
-	puts("done.\n");
+	putstr("done.\n");
 	return 0;
 }
 #endif
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index c3a87663b..5797b1b10 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -121,9 +121,9 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr,
 	DO_STATS ( device_info->total_allocs++ );
 
 	buf = kmalloc(sizeof(struct safe_buffer), GFP_ATOMIC);
-	if (buf == 0) {
+	if (buf == NULL) {
 		dev_warn(dev, "%s: kmalloc failed\n", __func__);
-		return 0;
+		return NULL;
 	}
 
 	if (size <= device_info->small_buffer_size) {
@@ -137,16 +137,16 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr,
 
 		DO_STATS ( device_info->lbp_allocs++ );
 	} else {
-		pool = 0;
+		pool = NULL;
 		safe = dma_alloc_coherent(dev, size, &safe_dma_addr, GFP_ATOMIC);
 	}
 
-	if (safe == 0) {
+	if (safe == NULL) {
 		dev_warn(device_info->dev,
 			"%s: could not alloc dma memory (size=%d)\n",
 		       __func__, size);
 		kfree(buf);
-		return 0;
+		return NULL;
 	}
 
 #ifdef STATS
@@ -216,27 +216,33 @@ static inline dma_addr_t
 map_single(struct device *dev, void *ptr, size_t size,
 		enum dma_data_direction dir)
 {
-	dma_addr_t dma_addr;
 	struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
+	dma_addr_t dma_addr;
+	int needs_bounce = 0;
 
 	if (device_info)
 		DO_STATS ( device_info->map_op_count++ );
 
+	dma_addr = virt_to_dma(dev, ptr);
+
 	if (dev->dma_mask) {
+		unsigned long mask = *dev->dma_mask;
 		unsigned long limit;
 
-		limit = (*dev->dma_mask + 1) & ~(*dev->dma_mask);
-		if (limit && (size > limit)) {
-			dev_err(dev, "DMA mapping too big "
-				"(requested %#x mask %#Lx)\n",
-				size, *dev->dma_mask);
+		limit = (mask + 1) & ~mask;
+		if (limit && size > limit) {
+			dev_err(dev, "DMA mapping too big (requested %#x "
+				"mask %#Lx)\n", size, *dev->dma_mask);
 			return ~0;
 		}
-	}
 
-	dma_addr = virt_to_dma(dev, ptr);
+		/*
+		 * Figure out if we need to bounce from the DMA mask.
+		 */
+		needs_bounce = (dma_addr | (dma_addr + size - 1)) & ~mask;
+	}
 
-	if (device_info && dma_needs_bounce(dev, dma_addr, size)) {
+	if (device_info && (needs_bounce || dma_needs_bounce(dev, dma_addr, size))) {
 		struct safe_buffer *buf;
 
 		buf = alloc_safe_buffer(device_info, ptr, size, dir);
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 18ba42e69..acc7d1af7 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -35,6 +35,10 @@
 
 #include <asm/hardware/sa1111.h>
 
+#ifdef CONFIG_ARCH_PXA
+#include <asm/arch/pxa-regs.h>
+#endif
+
 extern void __init sa1110_mb_enable(void);
 
 /*
@@ -761,9 +765,6 @@ static void __sa1111_remove(struct sa1111 *sachip)
  */
 int dma_needs_bounce(struct device *dev, dma_addr_t addr, size_t size)
 {
-	unsigned int physaddr = SA1111_DMA_ADDR((unsigned int)addr);
-	u32 dma_mask = *dev->dma_mask;
-
 	/*
 	 * Section 4.6 of the "Intel StrongARM SA-1111 Development Module
 	 * User's Guide" mentions that jumpers R51 and R52 control the
@@ -771,14 +772,8 @@ int dma_needs_bounce(struct device *dev, dma_addr_t addr, size_t size)
 	 * SDRAM bank 1 on Neponset). The default configuration selects
 	 * Assabet, so any address in bank 1 is necessarily invalid.
 	 */
-	if ((machine_is_assabet() || machine_is_pfs168()) &&
-		(addr >= 0xc8000000 || (addr + size) >= 0xc8000000))
-	  	return 1;
-
-	/*
-	 * Check to see if either the start or end are illegal.
-	 */
-	return ((addr & ~dma_mask)) || ((addr + size - 1) & ~dma_mask);
+	return ((machine_is_assabet() || machine_is_pfs168()) &&
+		(addr >= 0xc8000000 || (addr + size) >= 0xc8000000));
 }
 
 struct sa1111_save_data {
diff --git a/arch/arm/configs/ebsa110_defconfig b/arch/arm/configs/ebsa110_defconfig
index 2b1f60fdb..68f4047fc 100644
--- a/arch/arm/configs/ebsa110_defconfig
+++ b/arch/arm/configs/ebsa110_defconfig
@@ -176,7 +176,6 @@ CONFIG_IP_MULTIPLE_TABLES=y
 CONFIG_IP_ROUTE_FWMARK=y
 CONFIG_IP_ROUTE_NAT=y
 # CONFIG_IP_ROUTE_MULTIPATH is not set
-# CONFIG_IP_ROUTE_TOS is not set
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_DHCP is not set
diff --git a/arch/arm/configs/iq80321_defconfig b/arch/arm/configs/iq80321_defconfig
index c9afe2458..f19320b3b 100644
--- a/arch/arm/configs/iq80321_defconfig
+++ b/arch/arm/configs/iq80321_defconfig
@@ -10,27 +10,39 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
 #
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 
 #
 # Loadable module support
 #
 CONFIG_MODULES=y
-# CONFIG_MODULE_UNLOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
 CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 CONFIG_KMOD=y
@@ -38,64 +50,42 @@ CONFIG_KMOD=y
 #
 # System Type
 #
-# CONFIG_ARCH_ADIFCC is not set
 # CONFIG_ARCH_CLPS7500 is not set
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_CO285 is not set
-# CONFIG_ARCH_PXA is not set
 # CONFIG_ARCH_EBSA110 is not set
 # CONFIG_ARCH_CAMELOT is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
 # CONFIG_ARCH_INTEGRATOR is not set
 CONFIG_ARCH_IOP3XX=y
+# CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
 # CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE_PB is not set
 
 #
-# CLPS711X/EP721X Implementations
-#
-
-#
-# Epxa10db
-#
-
-#
-# Footbridge Implementations
+# IOP3xx Implementation Options
 #
 
 #
-# IOP3xx Implementation Options
+# IOP3xx Platform Types
 #
-# CONFIG_ARCH_IQ80310 is not set
 CONFIG_ARCH_IQ80321=y
-# CONFIG_ARCH_IOP310 is not set
+# CONFIG_ARCH_IQ31244 is not set
+# CONFIG_ARCH_IQ80331 is not set
+# CONFIG_ARCH_EP80219 is not set
 CONFIG_ARCH_IOP321=y
+# CONFIG_ARCH_IOP331 is not set
 
 #
 # IOP3xx Chipset Features
 #
-# CONFIG_IOP3XX_AAU is not set
-# CONFIG_IOP3XX_DMA is not set
-# CONFIG_IOP3XX_MU is not set
-# CONFIG_IOP3XX_PMON is not set
-
-#
-# ADIFCC Implementation Options
-#
-
-#
-# ADI Board Types
-#
-
-#
-# Intel PXA250/210 Implementations
-#
-
-#
-# SA11x0 Implementations
-#
 
 #
 # Processor Type
@@ -103,6 +93,9 @@ CONFIG_ARCH_IOP321=y
 CONFIG_CPU_32=y
 CONFIG_CPU_XSCALE=y
 CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_MINICACHE=y
 
 #
 # Processor Features
@@ -119,12 +112,6 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 # CONFIG_PCI_LEGACY_PROC is not set
 CONFIG_PCI_NAMES=y
-# CONFIG_HOTPLUG is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
 
 #
 # At least one math emulation must be selected
@@ -132,11 +119,16 @@ CONFIG_PCI_NAMES=y
 CONFIG_FPE_NWFPE=y
 # CONFIG_FPE_NWFPE_XP is not set
 # CONFIG_FPE_FASTFPE is not set
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
-CONFIG_BINFMT_AOUT=y
+# CONFIG_VFP is not set
 CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
 # CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_PM is not set
 # CONFIG_PREEMPT is not set
 # CONFIG_ARTHUR is not set
@@ -156,6 +148,8 @@ CONFIG_MTD=y
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_REDBOOT_PARTS=y
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
 # CONFIG_MTD_CMDLINE_PARTS is not set
 # CONFIG_MTD_AFS_PARTS is not set
 
@@ -175,13 +169,23 @@ CONFIG_MTD_CFI=y
 # CONFIG_MTD_JEDECPROBE is not set
 CONFIG_MTD_GEN_PROBE=y
 # CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
 CONFIG_MTD_CFI_INTELEXT=y
 # CONFIG_MTD_CFI_AMDSTD is not set
 # CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
@@ -196,6 +200,7 @@ CONFIG_MTD_CFI_INTELEXT=y
 #
 # CONFIG_MTD_PMC551 is not set
 # CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
 # CONFIG_MTD_BLKMTD is not set
 
@@ -214,7 +219,6 @@ CONFIG_MTD_CFI_INTELEXT=y
 #
 # Plug and Play support
 #
-# CONFIG_PNP is not set
 
 #
 # Block devices
@@ -226,6 +230,7 @@ CONFIG_MTD_CFI_INTELEXT=y
 # CONFIG_BLK_DEV_UMEM is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
 # CONFIG_BLK_DEV_INITRD is not set
@@ -243,14 +248,13 @@ CONFIG_NET=y
 #
 # Networking options
 #
-# CONFIG_PACKET is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
 # CONFIG_NETLINK_DEV is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_DHCP is not set
@@ -258,40 +262,26 @@ CONFIG_IP_PNP_BOOTP=y
 # 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_INET_ECN 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
-
-#
-# IP: Netfilter Configuration
-#
-# CONFIG_IP_NF_CONNTRACK is not set
-# CONFIG_IP_NF_QUEUE is not set
-# CONFIG_IP_NF_IPTABLES is not set
-# CONFIG_IP_NF_ARPTABLES is not set
-# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
+# CONFIG_NETFILTER is not set
 
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
 # CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_NET_DIVERT is not set
@@ -303,57 +293,32 @@ CONFIG_IPV6_SCTP__=y
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 
 #
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_SMC91X is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP 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 is not set
-# CONFIG_DGRS is not set
-CONFIG_EEPRO100=y
-# CONFIG_EEPRO100_PIO is not set
-# CONFIG_E100 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO 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_NET_ETHERNET is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -373,96 +338,33 @@ CONFIG_E1000_NAPI=y
 # Ethernet (10000 Mbit)
 #
 # CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
+# CONFIG_S2IO is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Token Ring devices
 #
-# CONFIG_NET_RADIO is not set
+# CONFIG_TR is not set
 
 #
-# Token Ring devices (depends on LLC=y)
+# Wireless LAN (non-hamradio)
 #
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
+# CONFIG_NET_RADIO is not set
 
 #
 # Wan interfaces
 #
 # CONFIG_WAN is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
 #
-CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_BLK_DEV_IDEPCI=y
-# CONFIG_BLK_DEV_GENERIC is not set
-# CONFIG_IDEPCI_SHARE_IRQ is not set
-CONFIG_BLK_DEV_IDEDMA_PCI=y
-# CONFIG_BLK_DEV_IDE_TCQ is not set
-# CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
-# CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_IDEDMA=y
-CONFIG_BLK_DEV_ADMA=y
-# CONFIG_BLK_DEV_AEC62XX is not set
-# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
-CONFIG_BLK_DEV_CMD64X=y
-# CONFIG_BLK_DEV_TRIFLEX is not set
-# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5520 is not set
-# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_OPTI621 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_SLC90E66 is not set
-# CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_VIA82CXXX is not set
-# CONFIG_BLK_DEV_SL82C105 is not set
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDE is not set
 
 #
 # SCSI device support
@@ -470,7 +372,11 @@ CONFIG_IDEDMA_AUTO=y
 # CONFIG_SCSI is not set
 
 #
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
 #
 # CONFIG_IEEE1394 is not set
 
@@ -482,16 +388,24 @@ CONFIG_IDEDMA_AUTO=y
 #
 # ISDN subsystem
 #
-# CONFIG_ISDN_BOOL is not set
+# CONFIG_ISDN is not set
 
 #
 # Input device support
 #
-# CONFIG_INPUT is not set
+CONFIG_INPUT=y
 
 #
 # 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 is not set
+# CONFIG_INPUT_EVBUG is not set
 
 #
 # Input I/O drivers
@@ -499,14 +413,23 @@ CONFIG_IDEDMA_AUTO=y
 # CONFIG_GAMEPORT is not set
 CONFIG_SOUND_GAMEPORT=y
 # CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
 
 #
 # Input Device Drivers
 #
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
 
 #
 # Character devices
 #
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -514,40 +437,17 @@ CONFIG_SOUND_GAMEPORT=y
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
 # Non-8250 serial port support
 #
-# CONFIG_SERIAL_DZ is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# L3 serial bus support
-#
-# CONFIG_L3 is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -569,54 +469,44 @@ CONFIG_UNIX98_PTY_COUNT=256
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_FTAPE is not set
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-CONFIG_VIDEO_DEV=y
 
 #
-# Video For Linux
-#
-# CONFIG_VIDEO_PROC_FS is not set
-
-#
-# Video Adapters
+# I2C support
 #
-# CONFIG_VIDEO_PMS is not set
-# CONFIG_VIDEO_CPIA is not set
-# CONFIG_VIDEO_STRADIS is not set
-# CONFIG_VIDEO_HEXIUM_ORION is not set
-# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+# CONFIG_I2C is not set
 
 #
-# Radio Adapters
+# Multimedia devices
 #
-# CONFIG_RADIO_GEMTEK_PCI is not set
-# CONFIG_RADIO_MAXIRADIO is not set
-# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_VIDEO_DEV is not set
 
 #
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
-# CONFIG_VIDEO_BTCX is not set
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
+CONFIG_XFS_FS=y
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_QUOTA is not set
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 # CONFIG_QUOTA is not set
@@ -632,17 +522,19 @@ CONFIG_EXT2_FS=y
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
 # CONFIG_NTFS_FS is not set
 
 #
 # Pseudo filesystems
 #
 CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
 # CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
 # CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
 #
@@ -651,6 +543,7 @@ CONFIG_RAMFS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
@@ -658,6 +551,10 @@ CONFIG_RAMFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
 # CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -669,19 +566,23 @@ CONFIG_JFFS2_FS_DEBUG=0
 # Network File Systems
 #
 CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+CONFIG_NFS_V3=y
 # CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+# CONFIG_NFSD_TCP is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
 CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
 # CONFIG_AFS_FS is not set
 
 #
@@ -699,46 +600,51 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 
 #
-# Graphics support
+# Native Language Support
 #
-# CONFIG_FB is not set
+# CONFIG_NLS is not set
 
 #
-# Sound
+# Profiling support
 #
-# CONFIG_SOUND is not set
+# CONFIG_PROFILING is not set
 
 #
-# Misc devices
+# Graphics support
+#
+# CONFIG_FB is not set
+
 #
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
 
 #
-# Multimedia Capabilities Port drivers
+# Sound
 #
-# CONFIG_MCP is not set
+# CONFIG_SOUND is not set
 
 #
-# Console Switches
+# Misc devices
 #
-# CONFIG_SWITCHES is not set
 
 #
 # USB support
 #
 # CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
 
 #
-# Bluetooth support
+# USB Gadget Support
 #
-# CONFIG_BT is not set
+# CONFIG_USB_GADGET is not set
 
 #
 # Kernel hacking
@@ -746,14 +652,7 @@ CONFIG_MSDOS_PARTITION=y
 CONFIG_FRAME_POINTER=y
 # CONFIG_DEBUG_USER is not set
 # CONFIG_DEBUG_INFO is not set
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_WAITQ is not set
-CONFIG_DEBUG_BUGVERBOSE=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_KERNEL is not set
 
 #
 # Security options
@@ -768,6 +667,8 @@ CONFIG_DEBUG_LL=y
 #
 # Library routines
 #
-# CONFIG_CRC32 is not set
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/ixp4xx_defconfig b/arch/arm/configs/ixp4xx_defconfig
index 1933c7027..7b821f811 100644
--- a/arch/arm/configs/ixp4xx_defconfig
+++ b/arch/arm/configs/ixp4xx_defconfig
@@ -308,7 +308,6 @@ CONFIG_IP_MULTIPLE_TABLES=y
 CONFIG_IP_ROUTE_FWMARK=y
 CONFIG_IP_ROUTE_NAT=y
 CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_TOS=y
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig
index d9e45878f..9919e7ff0 100644
--- a/arch/arm/configs/s3c2410_defconfig
+++ b/arch/arm/configs/s3c2410_defconfig
@@ -77,6 +77,12 @@ CONFIG_ARCH_H1940=y
 CONFIG_ARCH_SMDK2410=y
 CONFIG_MACH_VR1000=y
 
+#
+# S3C2410 Setup
+#
+CONFIG_S3C2410_DMA=y
+# CONFIG_S3C2410_DMA_DEBUG is not set
+
 #
 # Processor Type
 #
@@ -601,6 +607,8 @@ CONFIG_ROMFS_FS=y
 CONFIG_FAT_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
 #
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 1a85e39d7..936dee40e 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -19,6 +19,9 @@ obj-$(CONFIG_ARTHUR)		+= arthur.o
 obj-$(CONFIG_ISA_DMA)		+= dma-isa.o
 obj-$(CONFIG_PCI)		+= bios32.o
 
+obj-$(CONFIG_IWMMXT)		+= iwmmxt.o
+AFLAGS_iwmmxt.o			:= -Wa,-mcpu=iwmmxt
+
 ifneq ($(CONFIG_ARCH_EBSA110),y)
   obj-y		+= io.o
 endif
@@ -26,7 +29,7 @@ endif
 head-y			:= head.o
 obj-$(CONFIG_DEBUG_LL)	+= debug.o
 
-extra-y := $(head-y) init_task.o vmlinux.lds.s
+extra-y := $(head-y) init_task.o vmlinux.lds
 
 # Spell out some dependencies that aren't automatically figured out
 $(obj)/entry-armv.o: 	$(obj)/entry-header.S include/asm-arm/constants.h
diff --git a/arch/arm/kernel/apm.c b/arch/arm/kernel/apm.c
index a64f78def..70aade05b 100644
--- a/arch/arm/kernel/apm.c
+++ b/arch/arm/kernel/apm.c
@@ -46,7 +46,13 @@
 /*
  * Maximum number of events stored
  */
-#define APM_MAX_EVENTS		20
+#define APM_MAX_EVENTS		16
+
+struct apm_queue {
+	unsigned int		event_head;
+	unsigned int		event_tail;
+	apm_event_t		events[APM_MAX_EVENTS];
+};
 
 /*
  * The per-file APM data
@@ -54,27 +60,25 @@
 struct apm_user {
 	struct list_head	list;
 
-	int			suser: 1;
-	int			writer: 1;
-	int			reader: 1;
-	int			suspend_wait: 1;
-	int			suspend_result;
-
-	int			suspends_pending;
-	int			standbys_pending;
-	unsigned int		suspends_read;
-	unsigned int		standbys_read;
+	unsigned int		suser: 1;
+	unsigned int		writer: 1;
+	unsigned int		reader: 1;
 
-	int			event_head;
-	int			event_tail;
-	apm_event_t		events[APM_MAX_EVENTS];
+	int			suspend_result;
+	unsigned int		suspend_state;
+#define SUSPEND_NONE	0		/* no suspend pending */
+#define SUSPEND_PENDING	1		/* suspend pending read */
+#define SUSPEND_READ	2		/* suspend read, pending ack */
+#define SUSPEND_ACKED	3		/* suspend acked */
+#define SUSPEND_DONE	4		/* suspend completed */
+
+	struct apm_queue	queue;
 };
 
 /*
  * Local variables
  */
 static int suspends_pending;
-static int standbys_pending;
 static int apm_disabled;
 
 static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
@@ -83,14 +87,19 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
 /*
  * This is a list of everyone who has opened /dev/apm_bios
  */
-static spinlock_t user_list_lock = SPIN_LOCK_UNLOCKED;
+static DECLARE_RWSEM(user_list_lock);
 static LIST_HEAD(apm_user_list);
 
 /*
- * The kapmd info.
+ * kapmd info.  kapmd provides us a process context to handle
+ * "APM" events within - specifically necessary if we're going
+ * to be suspending the system.
  */
-static struct task_struct *kapmd;
+static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait);
 static DECLARE_COMPLETION(kapmd_exit);
+static spinlock_t kapmd_queue_lock = SPIN_LOCK_UNLOCKED;
+static struct apm_queue kapmd_queue;
+
 
 static const char driver_version[] = "1.13";	/* no spaces */
 
@@ -102,19 +111,6 @@ static const char driver_version[] = "1.13";	/* no spaces */
  */
 static void __apm_get_power_status(struct apm_power_info *info)
 {
-#if 0 && defined(CONFIG_SA1100_H3600) && defined(CONFIG_TOUCHSCREEN_H3600)
-	extern int h3600_apm_get_power_status(u_char *, u_char *, u_char *,
-					      u_char *, u_short *);
-
-	if (machine_is_h3600()) {
-		int dx;
-		h3600_apm_get_power_status(&info->ac_line_status,
-				&info->battery_status, &info->battery_flag,
-				&info->battery_life, &dx);
-		info->time = dx & 0x7fff;
-		info->units = dx & 0x8000 ? 0 : 1;
-	}
-#endif
 }
 
 /*
@@ -123,65 +119,71 @@ static void __apm_get_power_status(struct apm_power_info *info)
 void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status;
 EXPORT_SYMBOL(apm_get_power_status);
 
-static int queue_empty(struct apm_user *as)
+
+/*
+ * APM event queue management.
+ */
+static inline int queue_empty(struct apm_queue *q)
 {
-	return as->event_head == as->event_tail;
+	return q->event_head == q->event_tail;
 }
 
-static apm_event_t get_queued_event(struct apm_user *as)
+static inline apm_event_t queue_get_event(struct apm_queue *q)
 {
-	as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
-	return as->events[as->event_tail];
+	q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
+	return q->events[q->event_tail];
 }
 
-static void queue_event_one_user(struct apm_user *as, apm_event_t event)
+static void queue_add_event(struct apm_queue *q, apm_event_t event)
 {
-	as->event_head = (as->event_head + 1) % APM_MAX_EVENTS;
-	if (as->event_head == as->event_tail) {
+	q->event_head = (q->event_head + 1) % APM_MAX_EVENTS;
+	if (q->event_head == q->event_tail) {
 		static int notified;
 
 		if (notified++ == 0)
 		    printk(KERN_ERR "apm: an event queue overflowed\n");
-		as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
+		q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
 	}
-	as->events[as->event_head] = event;
-
-	if (!as->suser || !as->writer)
-		return;
-
-	switch (event) {
-	case APM_SYS_SUSPEND:
-	case APM_USER_SUSPEND:
-		as->suspends_pending++;
-		suspends_pending++;
-		break;
+	q->events[q->event_head] = event;
+}
 
-	case APM_SYS_STANDBY:
-	case APM_USER_STANDBY:
-		as->standbys_pending++;
-		standbys_pending++;
-		break;
+static void queue_event_one_user(struct apm_user *as, apm_event_t event)
+{
+	if (as->suser && as->writer) {
+		switch (event) {
+		case APM_SYS_SUSPEND:
+		case APM_USER_SUSPEND:
+			/*
+			 * If this user already has a suspend pending,
+			 * don't queue another one.
+			 */
+			if (as->suspend_state != SUSPEND_NONE)
+				return;
+
+			as->suspend_state = SUSPEND_PENDING;
+			suspends_pending++;
+			break;
+		}
 	}
+	queue_add_event(&as->queue, event);
 }
 
 static void queue_event(apm_event_t event, struct apm_user *sender)
 {
-	struct list_head *l;
-
-	spin_lock(&user_list_lock);
-	list_for_each(l, &apm_user_list) {
-		struct apm_user *as = list_entry(l, struct apm_user, list);
+	struct apm_user *as;
 
+	down_read(&user_list_lock);
+	list_for_each_entry(as, &apm_user_list, list) {
 		if (as != sender && as->reader)
 			queue_event_one_user(as, event);
 	}
-	spin_unlock(&user_list_lock);
+	up_read(&user_list_lock);
 	wake_up_interruptible(&apm_waitqueue);
 }
 
-static int apm_suspend(void)
+static void apm_suspend(void)
 {
-	struct list_head *l;
+	struct apm_user *as;
 	int err = pm_suspend(PM_SUSPEND_MEM);
 
 	/*
@@ -193,52 +195,39 @@ static int apm_suspend(void)
 	/*
 	 * Finally, wake up anyone who is sleeping on the suspend.
 	 */
-	spin_lock(&user_list_lock);
-	list_for_each(l, &apm_user_list) {
-		struct apm_user *as = list_entry(l, struct apm_user, list);
-
+	down_read(&user_list_lock);
+	list_for_each_entry(as, &apm_user_list, list) {
 		as->suspend_result = err;
-		as->suspend_wait = 0;
+		as->suspend_state = SUSPEND_DONE;
 	}
-	spin_unlock(&user_list_lock);
+	up_read(&user_list_lock);
 
-	wake_up_interruptible(&apm_suspend_waitqueue);
-	return err;
+	wake_up(&apm_suspend_waitqueue);
 }
 
 static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
 {
 	struct apm_user *as = fp->private_data;
 	apm_event_t event;
-	int i = count, ret = 0, nonblock = fp->f_flags & O_NONBLOCK;
+	int i = count, ret = 0;
 
 	if (count < sizeof(apm_event_t))
 		return -EINVAL;
 
-	if (queue_empty(as) && nonblock)
+	if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK)
 		return -EAGAIN;
 
-	wait_event_interruptible(apm_waitqueue, !queue_empty(as));
+	wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue));
 
-	while ((i >= sizeof(event)) && !queue_empty(as)) {
-		event = get_queued_event(as);
-		printk("  apm_read: event=%d\n", event);
+	while ((i >= sizeof(event)) && !queue_empty(&as->queue)) {
+		event = queue_get_event(&as->queue);
 
 		ret = -EFAULT;
 		if (copy_to_user(buf, &event, sizeof(event)))
 			break;
 
-		switch (event) {
-		case APM_SYS_SUSPEND:
-		case APM_USER_SUSPEND:
-			as->suspends_read++;
-			break;
-
-		case APM_SYS_STANDBY:
-		case APM_USER_STANDBY:
-			as->standbys_read++;
-			break;
-		}
+		if (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND)
+			as->suspend_state = SUSPEND_READ;
 
 		buf += sizeof(event);
 		i -= sizeof(event);
@@ -252,10 +241,10 @@ static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t
 
 static unsigned int apm_poll(struct file *fp, poll_table * wait)
 {
-	struct apm_user * as = fp->private_data;
+	struct apm_user *as = fp->private_data;
 
 	poll_wait(fp, &apm_waitqueue, wait);
-	return queue_empty(as) ? 0 : POLLIN | POLLRDNORM;
+	return queue_empty(&as->queue) ? 0 : POLLIN | POLLRDNORM;
 }
 
 /*
@@ -272,43 +261,65 @@ static int
 apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
 {
 	struct apm_user *as = filp->private_data;
+	unsigned long flags;
 	int err = -EINVAL;
 
 	if (!as->suser || !as->writer)
 		return -EPERM;
 
 	switch (cmd) {
-	case APM_IOC_STANDBY:
-		break;
-
 	case APM_IOC_SUSPEND:
-		/*
-		 * If we read a suspend command from /dev/apm_bios,
-		 * then the corresponding APM_IOC_SUSPEND ioctl is
-		 * interpreted as an acknowledge.
-		 */
-		if (as->suspends_read > 0) {
-			as->suspends_read--;
-			as->suspends_pending--;
+		as->suspend_result = -EINTR;
+
+		if (as->suspend_state == SUSPEND_READ) {
+			/*
+			 * If we read a suspend command from /dev/apm_bios,
+			 * then the corresponding APM_IOC_SUSPEND ioctl is
+			 * interpreted as an acknowledge.
+			 */
+			as->suspend_state = SUSPEND_ACKED;
 			suspends_pending--;
 		} else {
+			/*
+			 * Otherwise it is a request to suspend the system.
+			 * Queue an event for all readers, and expect an
+			 * acknowledge from all writers who haven't already
+			 * acknowledged.
+			 */
 			queue_event(APM_USER_SUSPEND, as);
 		}
 
 		/*
-		 * If there are outstanding suspend requests for other
-		 * people on /dev/apm_bios, we must sleep for them.
-		 * Last one to bed turns the lights out.
+		 * If there are no further acknowledges required, suspend
+		 * the system.
 		 */
-		if (suspends_pending > 0) {
-			as->suspend_wait = 1;
-			err = wait_event_interruptible(apm_suspend_waitqueue,
-						 as->suspend_wait == 0);
-			if (err == 0)
-				err = as->suspend_result;
-		} else {			
-			err = apm_suspend();
-		}
+		if (suspends_pending == 0)
+			apm_suspend();
+
+		/*
+		 * Wait for the suspend/resume to complete.  If there are
+		 * pending acknowledges, we wait here for them.
+		 *
+		 * Note that 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;
+
+		/*
+		 * Note: do not allow a thread which is acking the suspend
+		 * to escape until the resume is complete.
+		 */
+		if (as->suspend_state == SUSPEND_ACKED)
+			wait_event(apm_suspend_waitqueue,
+					 as->suspend_state == SUSPEND_DONE);
+		else
+			wait_event_interruptible(apm_suspend_waitqueue,
+					 as->suspend_state == SUSPEND_DONE);
+
+		current->flags = flags;
+		err = as->suspend_result;
+		as->suspend_state = SUSPEND_NONE;
 		break;
 	}
 
@@ -320,24 +331,19 @@ static int apm_release(struct inode * inode, struct file * filp)
 	struct apm_user *as = filp->private_data;
 	filp->private_data = NULL;
 
-	spin_lock(&user_list_lock);
+	down_write(&user_list_lock);
 	list_del(&as->list);
-	spin_unlock(&user_list_lock);
+	up_write(&user_list_lock);
 
 	/*
 	 * We are now unhooked from the chain.  As far as new
 	 * events are concerned, we no longer exist.  However, we
-	 * need to balance standbys_pending and suspends_pending,
-	 * which means the possibility of sleeping.
+	 * need to balance suspends_pending, which means the
+	 * possibility of sleeping.
 	 */
-	if (as->standbys_pending > 0) {
-		standbys_pending -= as->standbys_pending;
-//		if (standbys_pending <= 0)
-//			standby();
-	}
-	if (as->suspends_pending > 0) {
-		suspends_pending -= as->suspends_pending;
-		if (suspends_pending <= 0)
+	if (as->suspend_state != SUSPEND_NONE) {
+		suspends_pending -= 1;
+		if (suspends_pending == 0)
 			apm_suspend();
 	}
 
@@ -364,9 +370,9 @@ static int apm_open(struct inode * inode, struct file * filp)
 		as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
 		as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
 
-		spin_lock(&user_list_lock);
+		down_write(&user_list_lock);
 		list_add(&as->list, &apm_user_list);
-		spin_unlock(&user_list_lock);
+		up_write(&user_list_lock);
 
 		filp->private_data = as;
 	}
@@ -438,7 +444,7 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
 	info.ac_line_status = 0xff;
 	info.battery_status = 0xff;
 	info.battery_flag   = 0xff;
-	info.battery_life   = 255;
+	info.battery_life   = -1;
 	info.time	    = -1;
 	info.units	    = -1;
 
@@ -461,34 +467,53 @@ static int apm_get_info(char *buf, char **start, off_t fpos, int length)
 }
 #endif
 
-#if 0
-static int kapmd(void *startup)
+static int kapmd(void *arg)
 {
-	struct task_struct *tsk = current;
+	daemonize("kapmd");
+	current->flags |= PF_NOFREEZE;
 
-	daemonize();
-	strcpy(tsk->comm, "kapmd");
-	kapmd = tsk;
+	do {
+		apm_event_t event;
 
-	spin_lock_irq(&tsk->sigmask_lock);
-	siginitsetinv(&tsk->blocked, sigmask(SIGQUIT));
-	recalc_sigpending(tsk);
-	spin_unlock_irq(&tsk->sigmask_lock);
+		wait_event_interruptible(kapmd_wait,
+				!queue_empty(&kapmd_queue) || !pm_active);
 
-	complete((struct completion *)startup);
+		if (!pm_active)
+			break;
 
-	do {
-		set_task_state(tsk, TASK_INTERRUPTIBLE);
-		schedule();
-	} while (!signal_pending(tsk));
+		spin_lock_irq(&kapmd_queue_lock);
+		event = 0;
+		if (!queue_empty(&kapmd_queue))
+			event = queue_get_event(&kapmd_queue);
+		spin_unlock_irq(&kapmd_queue_lock);
+
+		switch (event) {
+		case 0:
+			break;
+
+		case APM_LOW_BATTERY:
+		case APM_POWER_STATUS_CHANGE:
+			queue_event(event, NULL);
+			break;
+
+		case APM_USER_SUSPEND:
+		case APM_SYS_SUSPEND:
+			queue_event(event, NULL);
+			if (suspends_pending == 0)
+				apm_suspend();
+			break;
+
+		case APM_CRITICAL_SUSPEND:
+			apm_suspend();
+			break;
+		}
+	} while (1);
 
 	complete_and_exit(&kapmd_exit, 0);
 }
-#endif
 
 static int __init apm_init(void)
 {
-//	struct completion startup = COMPLETION_INITIALIZER(startup);
 	int ret;
 
 	if (apm_disabled) {
@@ -501,22 +526,24 @@ static int __init apm_init(void)
 		return -EINVAL;
 	}
 
-//	ret = kernel_thread(kapmd, &startup, CLONE_FS | CLONE_FILES);
-//	if (ret)
-//		return ret;
-//	wait_for_completion(&startup);
-
 	pm_active = 1;
 
+	ret = kernel_thread(kapmd, NULL, CLONE_KERNEL);
+	if (ret < 0) {
+		pm_active = 0;
+		return ret;
+	}
+
 #ifdef CONFIG_PROC_FS
 	create_proc_info_entry("apm", 0, NULL, apm_get_info);
 #endif
 
 	ret = misc_register(&apm_device);
 	if (ret != 0) {
-		pm_active = 0;
 		remove_proc_entry("apm", NULL);
-		send_sig(SIGQUIT, kapmd, 1);
+
+		pm_active = 0;
+		wake_up(&kapmd_wait);
 		wait_for_completion(&kapmd_exit);
 	}
 
@@ -527,9 +554,10 @@ static void __exit apm_exit(void)
 {
 	misc_deregister(&apm_device);
 	remove_proc_entry("apm", NULL);
+
 	pm_active = 0;
-//	send_sig(SIGQUIT, kapmd, 1);
-//	wait_for_completion(&kapmd_exit);
+	wake_up(&kapmd_wait);
+	wait_for_completion(&kapmd_exit);
 }
 
 module_init(apm_init);
@@ -556,3 +584,27 @@ static int __init apm_setup(char *str)
 
 __setup("apm=", apm_setup);
 #endif
+
+/**
+ * apm_queue_event - queue an APM event for kapmd
+ * @event: APM event
+ *
+ * Queue an APM event for kapmd to process and ultimately take the
+ * appropriate action.  Only a subset of events are handled:
+ *   %APM_LOW_BATTERY
+ *   %APM_POWER_STATUS_CHANGE
+ *   %APM_USER_SUSPEND
+ *   %APM_SYS_SUSPEND
+ *   %APM_CRITICAL_SUSPEND
+ */
+void apm_queue_event(apm_event_t event)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&kapmd_queue_lock, flags);
+	queue_add_event(&kapmd_queue, event);
+	spin_unlock_irqrestore(&kapmd_queue_lock, flags);
+
+	wake_up_interruptible(&kapmd_wait);
+}
+EXPORT_SYMBOL(apm_queue_event);
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 43f0c6694..ae9203853 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -57,7 +57,7 @@ EXPORT_SYMBOL_ALIAS(kern_fp_enter,fp_enter);
 EXPORT_SYMBOL_ALIAS(fp_printk,printk);
 EXPORT_SYMBOL_ALIAS(fp_send_sig,send_sig);
 
-EXPORT_SYMBOL_NOVERS(__backtrace);
+EXPORT_SYMBOL(__backtrace);
 
 	/* platform dependent support */
 EXPORT_SYMBOL(udelay);
@@ -69,43 +69,44 @@ EXPORT_SYMBOL(__csum_ipv6_magic);
 
 	/* io */
 #ifndef __raw_readsb
-EXPORT_SYMBOL_NOVERS(__raw_readsb);
+EXPORT_SYMBOL(__raw_readsb);
 #endif
 #ifndef __raw_readsw
-EXPORT_SYMBOL_NOVERS(__raw_readsw);
+EXPORT_SYMBOL(__raw_readsw);
 #endif
 #ifndef __raw_readsl
-EXPORT_SYMBOL_NOVERS(__raw_readsl);
+EXPORT_SYMBOL(__raw_readsl);
 #endif
 #ifndef __raw_writesb
-EXPORT_SYMBOL_NOVERS(__raw_writesb);
+EXPORT_SYMBOL(__raw_writesb);
 #endif
 #ifndef __raw_writesw
-EXPORT_SYMBOL_NOVERS(__raw_writesw);
+EXPORT_SYMBOL(__raw_writesw);
 #endif
 #ifndef __raw_writesl
-EXPORT_SYMBOL_NOVERS(__raw_writesl);
+EXPORT_SYMBOL(__raw_writesl);
 #endif
 
 	/* string / mem functions */
-EXPORT_SYMBOL_NOVERS(strcpy);
-EXPORT_SYMBOL_NOVERS(strncpy);
-EXPORT_SYMBOL_NOVERS(strcat);
-EXPORT_SYMBOL_NOVERS(strncat);
-EXPORT_SYMBOL_NOVERS(strcmp);
-EXPORT_SYMBOL_NOVERS(strncmp);
-EXPORT_SYMBOL_NOVERS(strchr);
-EXPORT_SYMBOL_NOVERS(strlen);
-EXPORT_SYMBOL_NOVERS(strnlen);
-EXPORT_SYMBOL_NOVERS(strpbrk);
-EXPORT_SYMBOL_NOVERS(strrchr);
-EXPORT_SYMBOL_NOVERS(strstr);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memmove);
-EXPORT_SYMBOL_NOVERS(memcmp);
-EXPORT_SYMBOL_NOVERS(memscan);
-EXPORT_SYMBOL_NOVERS(__memzero);
+EXPORT_SYMBOL(strcpy);
+EXPORT_SYMBOL(strncpy);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strncat);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strpbrk);
+EXPORT_SYMBOL(strrchr);
+EXPORT_SYMBOL(strstr);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(memchr);
+EXPORT_SYMBOL(__memzero);
 
 	/* user mem (segment) */
 EXPORT_SYMBOL(__arch_copy_from_user);
@@ -114,30 +115,30 @@ EXPORT_SYMBOL(__arch_clear_user);
 EXPORT_SYMBOL(__arch_strnlen_user);
 EXPORT_SYMBOL(__arch_strncpy_from_user);
 
-EXPORT_SYMBOL_NOVERS(__get_user_1);
-EXPORT_SYMBOL_NOVERS(__get_user_2);
-EXPORT_SYMBOL_NOVERS(__get_user_4);
-EXPORT_SYMBOL_NOVERS(__get_user_8);
+EXPORT_SYMBOL(__get_user_1);
+EXPORT_SYMBOL(__get_user_2);
+EXPORT_SYMBOL(__get_user_4);
+EXPORT_SYMBOL(__get_user_8);
 
-EXPORT_SYMBOL_NOVERS(__put_user_1);
-EXPORT_SYMBOL_NOVERS(__put_user_2);
-EXPORT_SYMBOL_NOVERS(__put_user_4);
-EXPORT_SYMBOL_NOVERS(__put_user_8);
+EXPORT_SYMBOL(__put_user_1);
+EXPORT_SYMBOL(__put_user_2);
+EXPORT_SYMBOL(__put_user_4);
+EXPORT_SYMBOL(__put_user_8);
 
 	/* gcc lib functions */
-EXPORT_SYMBOL_NOVERS(__ashldi3);
-EXPORT_SYMBOL_NOVERS(__ashrdi3);
-EXPORT_SYMBOL_NOVERS(__divsi3);
-EXPORT_SYMBOL_NOVERS(__lshrdi3);
-EXPORT_SYMBOL_NOVERS(__modsi3);
-EXPORT_SYMBOL_NOVERS(__muldi3);
-EXPORT_SYMBOL_NOVERS(__ucmpdi2);
-EXPORT_SYMBOL_NOVERS(__udivdi3);
-EXPORT_SYMBOL_NOVERS(__umoddi3);
-EXPORT_SYMBOL_NOVERS(__udivmoddi4);
-EXPORT_SYMBOL_NOVERS(__udivsi3);
-EXPORT_SYMBOL_NOVERS(__umodsi3);
-EXPORT_SYMBOL_NOVERS(__do_div64);
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__divsi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__modsi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__ucmpdi2);
+EXPORT_SYMBOL(__udivdi3);
+EXPORT_SYMBOL(__umoddi3);
+EXPORT_SYMBOL(__udivmoddi4);
+EXPORT_SYMBOL(__udivsi3);
+EXPORT_SYMBOL(__umodsi3);
+EXPORT_SYMBOL(__do_div64);
 
 	/* bitops */
 EXPORT_SYMBOL(_set_bit_le);
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index c54132421..3f22b6356 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -13,6 +13,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <asm/mach/arch.h>
+#include <asm/thread_info.h>
 
 /*
  * Make sure that the compiler and target are compatible.
@@ -48,10 +49,23 @@ int main(void)
 {
   DEFINE(TSK_ACTIVE_MM,		offsetof(struct task_struct, active_mm));
   BLANK();
+  DEFINE(TI_FLAGS,		offsetof(struct thread_info, flags));
+  DEFINE(TI_PREEMPT,		offsetof(struct thread_info, preempt_count));
+  DEFINE(TI_ADDR_LIMIT,		offsetof(struct thread_info, addr_limit));
+  DEFINE(TI_TASK,		offsetof(struct thread_info, task));
+  DEFINE(TI_EXEC_DOMAIN,	offsetof(struct thread_info, exec_domain));
+  DEFINE(TI_CPU,		offsetof(struct thread_info, cpu));
+  DEFINE(TI_CPU_DOMAIN,		offsetof(struct thread_info, cpu_domain));
+  DEFINE(TI_CPU_SAVE,		offsetof(struct thread_info, cpu_context));
+  DEFINE(TI_USED_CP,		offsetof(struct thread_info, used_cp));
+  DEFINE(TI_FPSTATE,		offsetof(struct thread_info, fpstate));
+  DEFINE(TI_VFPSTATE,		offsetof(struct thread_info, vfpstate));
+  DEFINE(TI_IWMMXT_STATE,	(offsetof(struct thread_info, fpstate)+4)&~7);
+  BLANK();
 #if __LINUX_ARM_ARCH__ >= 6
   DEFINE(MM_CONTEXT_ID,		offsetof(struct mm_struct, context.id));
-#endif
   BLANK();
+#endif
   DEFINE(VMA_VM_MM,		offsetof(struct vm_area_struct, vm_mm));
   DEFINE(VMA_VM_FLAGS,		offsetof(struct vm_area_struct, vm_flags));
   BLANK();
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index 927711c48..ab2985877 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -17,6 +17,7 @@
 #include <asm/mach/pci.h>
 
 static int debug_pci;
+static int use_firmware;
 
 /*
  * We can't use pci_find_device() here since we are
@@ -128,12 +129,14 @@ static void __devinit pci_fixup_83c553(struct pci_dev *dev)
 	pci_write_config_word(dev, 0x44, 0xb000);
 	outb(0x08, 0x4d1);
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, pci_fixup_83c553);
 
 static void __devinit pci_fixup_unassign(struct pci_dev *dev)
 {
 	dev->resource[0].end -= dev->resource[0].start;
 	dev->resource[0].start = 0;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_89C940F, pci_fixup_unassign);
 
 /*
  * Prevent the PCI layer from seeing the resources allocated to this device
@@ -154,6 +157,7 @@ static void __devinit pci_fixup_dec21285(struct pci_dev *dev)
 		}
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, pci_fixup_dec21285);
 
 /*
  * Same as above. The PrPMC800 carrier board for the PrPMC1100 
@@ -178,6 +182,7 @@ static void __devinit pci_fixup_prpmc1100(struct pci_dev *dev)
 		}
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IXP4XX, pci_fixup_prpmc1100);
 
 /*
  * PCI IDE controllers use non-standard I/O port decoding, respect it.
@@ -198,6 +203,7 @@ static void __devinit pci_fixup_ide_bases(struct pci_dev *dev)
 		}
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
 
 /*
  * Put the DEC21142 to sleep
@@ -206,6 +212,7 @@ static void __devinit pci_fixup_dec21142(struct pci_dev *dev)
 {
 	pci_write_config_dword(dev, 0x40, 0x80000000);
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142, pci_fixup_dec21142);
 
 /*
  * The CY82C693 needs some rather major fixups to ensure that it does
@@ -271,38 +278,7 @@ static void __devinit pci_fixup_cy82c693(struct pci_dev *dev)
 		pci_write_config_byte(dev, 0x45, 0x03);
 	}
 }
-
-struct pci_fixup pcibios_fixups[] = {
-	{
-		PCI_FIXUP_HEADER,
-		PCI_VENDOR_ID_CONTAQ,	PCI_DEVICE_ID_CONTAQ_82C693,
-		pci_fixup_cy82c693
-	}, {
-		PCI_FIXUP_HEADER,
-		PCI_VENDOR_ID_DEC,	PCI_DEVICE_ID_DEC_21142,
-		pci_fixup_dec21142
-	}, {
-		PCI_FIXUP_HEADER,
-		PCI_VENDOR_ID_DEC,	PCI_DEVICE_ID_DEC_21285,
-		pci_fixup_dec21285
-	}, {
-		PCI_FIXUP_HEADER,
-		PCI_VENDOR_ID_WINBOND,	PCI_DEVICE_ID_WINBOND_83C553,
-		pci_fixup_83c553
-	}, {
-		PCI_FIXUP_HEADER,
-		PCI_VENDOR_ID_WINBOND2,	PCI_DEVICE_ID_WINBOND2_89C940F,
-		pci_fixup_unassign
-	}, {
-		PCI_FIXUP_HEADER,
-		PCI_ANY_ID,		PCI_ANY_ID,
-		pci_fixup_ide_bases
-	}, {
-		PCI_FIXUP_HEADER,
-		PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_IXP4XX,
-		pci_fixup_prpmc1100
-	}, { 0 }
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, pci_fixup_cy82c693);
 
 void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
 {
@@ -596,15 +572,17 @@ void __init pci_common_init(struct hw_pci *hw)
 	list_for_each_entry(sys, &hw->buses, node) {
 		struct pci_bus *bus = sys->bus;
 
-		/*
-		 * Size the bridge windows.
-		 */
-		pci_bus_size_bridges(bus);
+		if (!use_firmware) {
+			/*
+		 	 * Size the bridge windows.
+		 	 */
+			pci_bus_size_bridges(bus);
 
-		/*
-		 * Assign resources.
-		 */
-		pci_bus_assign_resources(bus);
+			/*
+		 	 * Assign resources.
+		 	 */
+			pci_bus_assign_resources(bus);
+		}
 
 		/*
 		 * Tell drivers about devices found.
@@ -618,6 +596,9 @@ char * __init pcibios_setup(char *str)
 	if (!strcmp(str, "debug")) {
 		debug_pci = 1;
 		return NULL;
+	} else if (!strcmp(str, "firmware")) {
+		use_firmware = 1;
+		return NULL;
 	}
 	return str;
 }
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 3da0b8091..d868099d1 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/arm/kernel/calls.S
  *
- *  Copyright (C) 1995-2003 Russell King
+ *  Copyright (C) 1995-2004 Russell King
  *
  * 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
@@ -288,6 +288,13 @@ __syscall_start:
 		.long	sys_pciconfig_iobase
 		.long	sys_pciconfig_read
 		.long	sys_pciconfig_write
+		.long	sys_mq_open
+/* 275 */	.long	sys_mq_unlink
+		.long	sys_mq_timedsend
+		.long	sys_mq_timedreceive
+		.long	sys_mq_notify
+		.long	sys_mq_getsetattr
+/* 280 */	.long	sys_waitid
 __syscall_end:
 
 		.rept	NR_syscalls - (__syscall_end - __syscall_start) / 4
diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S
index 822dbde5a..7b4e9721f 100644
--- a/arch/arm/kernel/debug.S
+++ b/arch/arm/kernel/debug.S
@@ -411,10 +411,16 @@
 
 		.macro	addruart,rx
 		mov	\rx, #0xfe000000	@ physical
-#ifdef CONFIG_ARCH_IQ80310
-		orr	\rx, \rx, #0x00810000	@ location of the UART
-#elif defined(CONFIG_ARCH_IQ80321)
+#if defined(CONFIG_ARCH_IQ80321) || defined(CONFIG_ARCH_IQ31244)
 		orr	\rx, \rx, #0x00800000	@ location of the UART
+#elif defined(CONFIG_ARCH_IOP331)
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1			@ MMU enabled?
+		moveq	\rx, #0x000fe000	@ Physical Base
+		movne	\rx, #0
+		orr	\rx, \rx, #0xfe000000
+		orr	\rx, \rx, #0x00f00000	@ Virtual Base
+		orr	\rx, \rx, #0x00001700   @ location of the UART
 #else
 #error Unknown IOP3XX implementation
 #endif
@@ -432,7 +438,7 @@
 		.endm
 
 		.macro	waituart,rd,rx
-#ifndef	CONFIG_ARCH_IQ80321
+#if !defined(CONFIG_ARCH_IQ80321) || !defined(CONFIG_ARCH_IQ31244) || !defined(CONFIG_ARCH_IQ80331)
 1001:		ldrb	\rd, [\rx, #0x6]
 		tst	\rd, #0x10
 		beq	1001b
@@ -464,6 +470,36 @@
                 .macro  busyuart,rd,rx
                 .endm
 
+#elif defined(CONFIG_ARCH_IXP2000)
+
+		.macro  addruart,rx
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1			@ MMU enabled?
+		moveq	\rx, #0xc0000000	@ Physical base
+		movne	\rx, #0xfe000000	@ virtual base
+		orrne	\rx, \rx, #0x00f00000
+		orr	\rx, \rx, #0x00030000
+#ifdef	__ARMEB__
+		orr	\rx, \rx, #0x00000003
+#endif
+		.endm 
+		
+		.macro	senduart,rd,rx
+		strb	\rd, [\rx]
+		.endm
+
+		.macro	busyuart,rd,rx
+1002:		ldrb	\rd, [\rx, #0x14]
+		tst	\rd, #0x20       
+		beq	1002b
+		.endm
+
+		.macro	waituart,rd,rx
+		nop
+		nop
+		nop
+		.endm
+
 #elif defined(CONFIG_ARCH_OMAP)
 
 		.macro	addruart,rx
@@ -615,6 +651,60 @@
 		tst	\rd, #1 << 3		@ UARTFLGUBUSY - 1 when busy
 		bne	1001b
 		.endm
+
+#elif defined(CONFIG_ARCH_IMX)
+
+		.macro	addruart,rx
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1			@ MMU enabled?
+		moveq	\rx, #0x00000000	@ physical
+		movne	\rx, #0xe0000000	@ virtual
+		orr	\rx, \rx, #0x00200000
+		orr	\rx, \rx, #0x00006000	@ UART1 offset
+		.endm
+
+		.macro	senduart,rd,rx
+		str	\rd, [\rx, #0x40]	@ TXDATA
+		.endm
+
+		.macro	waituart,rd,rx
+		.endm
+
+		.macro	busyuart,rd,rx
+1002:		ldr	\rd, [\rx, #0x98]	@ SR2
+		tst	\rd, #1 << 3		@ TXDC
+		beq	1002b			@ wait until transmit done
+		.endm
+
+#elif defined(CONFIG_ARCH_H720X)
+
+		.equ    io_virt, IO_BASE
+		.equ    io_phys, IO_START
+
+		.macro  addruart,rx
+		mrc     p15, 0, \rx, c1, c0
+		tst     \rx, #1  	       @ MMU enabled?
+		moveq   \rx, #io_phys	       @ physical base address
+		movne   \rx, #io_virt	       @ virtual address
+		add     \rx, \rx, #0x00020000   @ UART1
+		.endm
+
+		.macro  senduart,rd,rx
+		str     \rd, [\rx, #0x0]        @ UARTDR
+
+		.endm
+
+		.macro  waituart,rd,rx
+1001:		ldr     \rd, [\rx, #0x18]       @ UARTFLG
+		tst     \rd, #1 << 5	       @ UARTFLGUTXFF - 1 when full
+		bne     1001b
+		.endm
+
+		.macro  busyuart,rd,rx
+1001:		ldr     \rd, [\rx, #0x18]       @ UARTFLG
+		tst     \rd, #1 << 3	       @ UARTFLGUBUSY - 1 when busy
+		bne     1001b
+		.endm
 #else
 #error Unknown architecture
 #endif
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index d3dafbf4f..67ac4ec53 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -33,6 +33,7 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
+#include <linux/completion.h>
 #include <linux/reboot.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
@@ -53,18 +54,14 @@
 #define HAVE_EXPMASK
 #endif
 
-enum req {
-	req_readbytes,
-	req_reset
-};
-
 struct ecard_request {
-	enum req	req;
+	void		(*fn)(struct ecard_request *);
 	ecard_t		*ec;
 	unsigned int	address;
 	unsigned int	length;
 	unsigned int	use_loader;
 	void		*buffer;
+	struct completion *complete;
 };
 
 struct expcard_blacklist {
@@ -129,15 +126,14 @@ slot_to_ecard(unsigned int slot)
 #define POD_INT_ADDR(x)	((volatile unsigned char *)\
 			 ((BUS_ADDR((x)) - IO_BASE) + IO_START))
 
-static inline void ecard_task_reset(struct ecard_request *req)
+static void ecard_task_reset(struct ecard_request *req)
 {
 	struct expansion_card *ec = req->ec;
 	if (ec->loader)
 		ecard_loader_reset(POD_INT_ADDR(ec->podaddr), ec->loader);
 }
 
-static void
-ecard_task_readbytes(struct ecard_request *req)
+static void ecard_task_readbytes(struct ecard_request *req)
 {
 	unsigned char *buf = (unsigned char *)req->buffer;
 	volatile unsigned char *base_addr =
@@ -206,26 +202,9 @@ ecard_task_readbytes(struct ecard_request *req)
 
 }
 
-static void ecard_do_request(struct ecard_request *req)
-{
-	switch (req->req) {
-	case req_readbytes:
-		ecard_task_readbytes(req);
-		break;
-
-	case req_reset:
-		ecard_task_reset(req);
-		break;
-	}
-}
-
-#include <linux/completion.h>
-
-static pid_t ecard_pid;
-static wait_queue_head_t ecard_wait;
+static DECLARE_WAIT_QUEUE_HEAD(ecard_wait);
 static struct ecard_request *ecard_req;
-
-static DECLARE_COMPLETION(ecard_completion);
+static DECLARE_MUTEX(ecard_sem);
 
 /*
  * Set up the expansion card daemon's page tables.
@@ -282,8 +261,6 @@ static int ecard_init_mm(void)
 static int
 ecard_task(void * unused)
 {
-	struct task_struct *tsk = current;
-
 	daemonize("kecardd");
 
 	/*
@@ -298,17 +275,13 @@ ecard_task(void * unused)
 	while (1) {
 		struct ecard_request *req;
 
-		do {
-			req = xchg(&ecard_req, NULL);
-
-			if (req == NULL) {
-				sigemptyset(&tsk->pending.signal);
-				interruptible_sleep_on(&ecard_wait);
-			}
-		} while (req == NULL);
+		wait_event_interruptible(ecard_wait, ecard_req != NULL);
 
-		ecard_do_request(req);
-		complete(&ecard_completion);
+		req = xchg(&ecard_req, NULL);
+		if (req != NULL) {
+			req->fn(req);
+			complete(req->complete);
+		}
 	}
 }
 
@@ -318,25 +291,21 @@ ecard_task(void * unused)
  * FIXME: The test here is not sufficient to detect if the
  * kcardd is running.
  */
-static void
-ecard_call(struct ecard_request *req)
+static void ecard_call(struct ecard_request *req)
 {
-	/*
-	 * Make sure we have a context that is able to sleep.
-	 */
-	if (current == &init_task || in_interrupt())
-		BUG();
+	DECLARE_COMPLETION(completion);
 
-	if (ecard_pid <= 0)
-		ecard_pid = kernel_thread(ecard_task, NULL, CLONE_KERNEL);
+	req->complete = &completion;
 
+	down(&ecard_sem);
 	ecard_req = req;
 	wake_up(&ecard_wait);
 
 	/*
 	 * Now wait for kecardd to run.
 	 */
-	wait_for_completion(&ecard_completion);
+	wait_for_completion(&completion);
+	up(&ecard_sem);
 }
 
 /* ======================= Mid-level card control ===================== */
@@ -346,7 +315,7 @@ ecard_readbytes(void *addr, ecard_t *ec, int off, int len, int useld)
 {
 	struct ecard_request req;
 
-	req.req		= req_readbytes;
+	req.fn		= ecard_task_readbytes;
 	req.ec		= ec;
 	req.address	= off;
 	req.length	= len;
@@ -1066,9 +1035,14 @@ nomem:
  */
 static int __init ecard_init(void)
 {
-	int slot, irqhw;
+	int slot, irqhw, ret;
 
-	init_waitqueue_head(&ecard_wait);
+	ret = kernel_thread(ecard_task, NULL, CLONE_KERNEL);
+	if (ret < 0) {
+		printk(KERN_ERR "Ecard: unable to create kernel thread: %d\n",
+		       ret);
+		return ret;
+	}
 
 	printk("Probing expansion cards\n");
 
@@ -1151,7 +1125,7 @@ static void ecard_drv_shutdown(struct device *dev)
 	if (drv->shutdown)
 		drv->shutdown(ec);
 	ecard_release(ec);
-	req.req = req_reset;
+	req.fn = ecard_task_reset;
 	req.ec = ec;
 	ecard_call(&req);
 }
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 7fe5c2d39..5639f1b61 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -562,40 +562,6 @@ ENTRY(soft_irq_mask)
 		.macro	irq_prio_table
 		.endm
 
-#elif defined(CONFIG_ARCH_IOP310)
-
-		.macro	disable_fiq
-		.endm
-
-        	.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-        	mrc p13, 0, \irqstat, c4, c0, 0 @ get INTSRC
-        	mrc p13, 0, \base, c0, c0, 0    @ get INTCTL
-
-        	tst \irqstat, #(1<<29)      @ if INTSRC_BI
-        	tstne   \base, #(1<<3)          @ and INTCTL_BM
-        	movne   \irqnr, #IRQ_XS80200_BCU
-        	bne 1001f
-
-        	tst \irqstat, #(1<<28)      @ if INTSRC_PI
-        	tstne   \base, #(1<<2)          @ and INTCTL_PM
-        	movne   \irqnr, #IRQ_XS80200_PMU
-        	bne 1001f
-
-        	tst \irqstat, #(1<<31)      @ if INTSRC_FI
-        	tstne   \base, #(1<<0)          @ and INTCTL_FM
-        	movne   \irqnr, #IRQ_XS80200_EXTFIQ
-        	bne 1001f
-
-        	tst \irqstat, #(1<<30)      @ if INTSRC_II
-        	tstne   \base, #(1<<1)          @ and INTCTL_IM
-        	movne   \irqnr, #IRQ_XS80200_EXTIRQ
-
-1001:
-  		.endm
-
-  		.macro	irq_prio_table
- 		.endm
-
 #elif defined(CONFIG_ARCH_IOP321)
 		.macro  disable_fiq
 		.endm
@@ -618,6 +584,39 @@ ENTRY(soft_irq_mask)
 		.macro  irq_prio_table
 		.endm
 
+#elif defined(CONFIG_ARCH_IOP331)
+		.macro  disable_fiq
+		.endm
+
+		/*
+		 * Note: only deal with normal interrupts, not FIQ
+		 */
+		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+		mov     \irqnr, #0
+		mrc     p6, 0, \irqstat, c4, c0, 0      @ Read IINTSRC0
+		cmp     \irqstat, #0
+		bne     1002f
+		mrc     p6, 0, \irqstat, c5, c0, 0      @ Read IINTSRC1
+		cmp	\irqstat, #0
+		beq	1001f
+		clz	\irqnr, \irqstat
+/*
+ *		mov	\base, #31
+ *		subs	\irqnr,\base,\irqnr
+ */
+        rsbs    \irqnr,\irqnr,#31   @ recommend by RMK
+		add	\irqnr,\irqnr,#IRQ_IOP331_XINT8
+		b	1001f
+1002:		clz     \irqnr, \irqstat
+		mov     \base, #31
+		subs    \irqnr,\base,\irqnr
+		add     \irqnr,\irqnr,#IRQ_IOP331_DMA0_EOT
+1001:
+		.endm
+
+		.macro  irq_prio_table
+		.endm
+
 #elif defined(CONFIG_ARCH_PXA)
 
 		.macro	disable_fiq
@@ -645,6 +644,60 @@ ENTRY(soft_irq_mask)
 		.macro	irq_prio_table
 		.endm
 
+#elif defined(CONFIG_ARCH_IXP2000)
+
+		.macro  disable_fiq
+		.endm
+
+		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+		
+		mov	\irqnr, #0x0              @clear out irqnr as default
+                mov	\base, #0xfe000000        
+		orr	\base, \base, #0x00ff0000
+		orr	\base, \base, #0x0000a000
+		orr	\base, \base, #0x08
+		ldr	\irqstat, [\base]         @ get interrupts 
+		mov	\tmp, #IXP2000_VALID_IRQ_MASK & 0xff000000
+		orr	\tmp, \tmp, #IXP2000_VALID_IRQ_MASK & 0x00ff0000
+		orr	\tmp, \tmp, #IXP2000_VALID_IRQ_MASK & 0x0000ff00
+		orr	\tmp, \tmp, #IXP2000_VALID_IRQ_MASK & 0x000000ff
+		and	\irqstat, \irqstat, \tmp
+
+		cmp	\irqstat, #0
+		beq	1001f	
+
+		clz     \irqnr, \irqstat
+		mov     \base, #31
+		subs    \irqnr, \base, \irqnr
+		
+		/*
+		 * We handle PCIA and PCIB here so we don't have an
+		 * extra layer of code just to check these two bits.
+		 */
+		cmp	\irqnr, #IRQ_IXP2000_PCI
+		bne	1001f
+
+		mov	\base, #0xfe000000
+		orr	\base, \base, #0x00fd0000
+		orr	\base, \base, #0x0000e100
+		orr	\base, \base, #0x00000058
+		ldr	\irqstat, [\base]
+
+		mov	\tmp, #(1<<26)
+		tst	\irqstat, \tmp
+		movne	\irqnr, #IRQ_IXP2000_PCIA
+		bne	1001f
+
+		mov	\tmp, #(1<<27)
+		tst	\irqstat, \tmp
+		movne	\irqnr, #IRQ_IXP2000_PCIB
+
+1001:
+		.endm 
+		
+		.macro  irq_prio_table
+		.endm
+
 #elif defined (CONFIG_ARCH_IXP4XX)
 
 		.macro	disable_fiq
@@ -884,6 +937,82 @@ ENTRY(soft_irq_mask)
                .macro  irq_prio_table
                .endm
 
+#elif defined(CONFIG_ARCH_IMX)
+
+		.macro	disable_fiq
+		.endm
+#define AITC_NIVECSR   0x40
+		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+		ldr	\irqstat, =IO_ADDRESS(IMX_AITC_BASE)
+		@ Load offset & priority of the highest priority
+		@ interrupt pending.
+		ldr	\irqnr, [\irqstat, #AITC_NIVECSR]
+		@ Shift off the priority leaving the offset or
+		@ "interrupt number"
+		mov	\irqnr, \irqnr, lsr #16
+ 		ldr	\irqstat, =1	@ dummy compare
+		ldr	\base, =0xFFFF		// invalid interrupt
+		cmp	\irqnr, \base
+		bne	1001f
+		ldr	\irqstat, =0
+1001:
+		tst	\irqstat, #1	@ to make the condition code = TRUE
+		.endm
+
+		.macro	irq_prio_table
+		.endm
+
+#elif defined(CONFIG_ARCH_H720X)
+
+		.macro  disable_fiq
+		.endm
+
+		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+#if defined (CONFIG_CPU_H7201) || defined (CONFIG_CPU_H7202)
+		@ we could use the id register on H7202, but this is not
+		@ properly updated when we come back from asm_do_irq
+		@ without a previous return from interrupt
+		@ (see loops below in irq_svc, irq_usr)
+		@ We see unmasked pending ints only, as the masked pending ints
+		@ are not visible here
+
+		mov     \base, #0xf0000000	       @ base register
+		orr     \base, \base, #0x24000	       @ irqbase
+		ldr     \irqstat, [\base, #0x04]        @ get interrupt status
+#if defined (CONFIG_CPU_H7201)
+		ldr	\tmp, =0x001fffff
+#else
+		mvn     \tmp, #0xc0000000
+#endif
+		and     \irqstat, \irqstat, \tmp        @ mask out unused ints
+		mov     \irqnr, #0
+
+		mov     \tmp, #0xff00
+		orr     \tmp, \tmp, #0xff
+		tst     \irqstat, \tmp
+		addeq   \irqnr, \irqnr, #16
+		moveq   \irqstat, \irqstat, lsr #16
+		tst     \irqstat, #255
+		addeq   \irqnr, \irqnr, #8
+		moveq   \irqstat, \irqstat, lsr #8
+		tst     \irqstat, #15
+		addeq   \irqnr, \irqnr, #4
+		moveq   \irqstat, \irqstat, lsr #4
+		tst     \irqstat, #3
+		addeq   \irqnr, \irqnr, #2
+		moveq   \irqstat, \irqstat, lsr #2
+		tst     \irqstat, #1
+		addeq   \irqnr, \irqnr, #1
+		moveq   \irqstat, \irqstat, lsr #1
+		tst     \irqstat, #1		       @ bit 0 should be set
+		.endm
+
+		.macro  irq_prio_table
+		.endm
+
+#else
+#error hynix processor selection missmatch
+#endif
 #else
 #error Unknown architecture
 #endif
@@ -1174,7 +1303,7 @@ __und_usr:	sub	sp, sp, #S_FRAME_SIZE		@ Allocate frame size in one go
  *  r0  - instruction opcode.
  *  r10 - this threads thread_info structure.
  */
-call_fpe:	enable_irq r10				@ Enable interrupts
+call_fpe:
 		tst	r0, #0x08000000			@ only CDP/CPRT/LDC/STC have bit 27
 #if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
 		and	r8, r0, #0x0f000000		@ mask out op-code bits
@@ -1186,6 +1315,14 @@ call_fpe:	enable_irq r10				@ Enable interrupts
 		mov	r7, #1
 		add	r6, r10, #TI_USED_CP
 		strb	r7, [r6, r8, lsr #8]		@ set appropriate used_cp[]
+#ifdef CONFIG_IWMMXT
+		@ Test if we need to give access to iWMMXt coprocessors
+		ldr	r5, [r10, #TI_FLAGS]
+		rsbs	r7, r8, #(1 << 8)		@ CP 0 or 1 only
+		movcss	r7, r5, lsr #(TIF_USING_IWMMXT + 1)
+		bcs	iwmmxt_task_enable
+#endif
+		enable_irq r7
 		add	pc, pc, r8, lsr #6
 		mov	r0, r0
 
@@ -1264,7 +1401,11 @@ ENTRY(ret_from_exception)
 ENTRY(__switch_to)
 		add	ip, r1, #TI_CPU_SAVE
 		ldr	r3, [r2, #TI_CPU_DOMAIN]!
-		stmia	ip, {r4 - sl, fp, sp, lr}	@ Store most regs on stack
+		stmia	ip!, {r4 - sl, fp, sp, lr}	@ Store most regs on stack
+#if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT)
+		mra	r4, r5, acc0
+		stmia   ip, {r4, r5}
+#endif
 		mcr	p15, 0, r3, c3, c0, 0		@ Set domain register
 #ifdef CONFIG_VFP
 		@ Always disable VFP so we can lazily save/restore the old
@@ -1272,6 +1413,13 @@ ENTRY(__switch_to)
 		VFPFMRX	r4, FPEXC
 		bic	r4, r4, #FPEXC_ENABLE
 		VFPFMXR	FPEXC, r4
+#endif
+#if defined(CONFIG_IWMMXT)
+		bl	iwmmxt_task_switch
+#elif defined(CONFIG_CPU_XSCALE)
+		add	r4, r2, #40			@ cpu_context_save->extra
+		ldmib	r4, {r4, r5}
+		mar	acc0, r4, r5
 #endif
 		ldmib	r2, {r4 - sl, fp, sp, pc}	@ Load all regs saved previously
 
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 68636bd7c..9c6501295 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -46,6 +46,7 @@
  */
 #define MAX_IRQ_CNT	100000
 
+static int noirqdebug;
 static volatile unsigned long irq_err_count;
 static spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED;
 static LIST_HEAD(irq_pending);
@@ -235,7 +236,7 @@ report_bad_irq(unsigned int irq, struct pt_regs *regs, struct irqdesc *desc, int
 	static int count = 100;
 	struct irqaction *action;
 
-	if (!count)
+	if (!count || noirqdebug)
 		return;
 
 	count--;
@@ -261,7 +262,7 @@ static int
 __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
 {
 	unsigned int status;
-	int retval = 0;
+	int ret, retval = 0;
 
 	spin_unlock(&irq_controller_lock);
 
@@ -270,8 +271,10 @@ __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
 
 	status = 0;
 	do {
-		status |= action->flags;
-		retval |= action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
+		retval |= ret;
 		action = action->next;
 	} while (action);
 
@@ -861,3 +864,11 @@ void __init init_IRQ(void)
 	init_arch_irq();
 	init_dma();
 }
+
+static int __init noirqdebug_setup(char *str)
+{
+	noirqdebug = 1;
+	return 1;
+}
+
+__setup("noirqdebug", noirqdebug_setup);
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 56498dbf7..1301b0378 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -313,6 +313,9 @@ void flush_thread(void)
 
 	memset(thread->used_cp, 0, sizeof(thread->used_cp));
 	memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
+#if defined(CONFIG_IWMMXT)
+	iwmmxt_task_release(thread);
+#endif
 	fp_init(&thread->fpstate);
 #if defined(CONFIG_VFP)
 	vfp_flush_thread(&thread->vfpstate);
@@ -324,6 +327,9 @@ void release_thread(struct task_struct *dead_task)
 #if defined(CONFIG_VFP)
 	vfp_release_thread(&dead_task->thread_info->vfpstate);
 #endif
+#if defined(CONFIG_IWMMXT)
+	iwmmxt_task_release(dead_task->thread_info);
+#endif
 }
 
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index d99255a8b..465861fcf 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -794,11 +794,8 @@ asmlinkage void syscall_trace(int why, struct pt_regs *regs)
 
 	/* the 0x80 provides a way for the tracing parent to distinguish
 	   between a syscall stop and SIGTRAP delivery */
-	current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-					? 0x80 : 0);
-	current->state = TASK_STOPPED;
-	notify_parent(current, SIGCHLD);
-	schedule();
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+				 ? 0x80 : 0));
 	/*
 	 * this isn't the same as continuing with a signal, but it will do
 	 * for normal use.  strace only continues with a signal if the
diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c
index 9ce72332e..c232d3777 100644
--- a/arch/arm/kernel/semaphore.c
+++ b/arch/arm/kernel/semaphore.c
@@ -214,7 +214,7 @@ __up_wakeup:					\n\
 	ldmfd	sp!, {r0 - r3, pc}		\n\
 	");
 
-EXPORT_SYMBOL_NOVERS(__down_failed);
-EXPORT_SYMBOL_NOVERS(__down_interruptible_failed);
-EXPORT_SYMBOL_NOVERS(__down_trylock_failed);
-EXPORT_SYMBOL_NOVERS(__up_wakeup);
+EXPORT_SYMBOL(__down_failed);
+EXPORT_SYMBOL(__down_interruptible_failed);
+EXPORT_SYMBOL(__down_trylock_failed);
+EXPORT_SYMBOL(__up_wakeup);
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 835010c55..550cb831a 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -57,7 +57,6 @@ extern unsigned int mem_fclk_21285;
 extern void paging_init(struct meminfo *, struct machine_desc *desc);
 extern void convert_to_tag_list(struct tag *tags);
 extern void squash_mem_tags(struct tag *tag);
-extern void bootmem_init(struct meminfo *);
 extern void reboot_setup(char *str);
 extern int root_mountflags;
 extern int _stext, _text, _etext, _edata, _end;
@@ -720,7 +719,6 @@ void __init setup_arch(char **cmdline_p)
 	memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
 	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
 	parse_cmdline(cmdline_p, from);
-	bootmem_init(&meminfo);
 	paging_init(&meminfo, mdesc);
 	request_standard_resources(&meminfo, mdesc);
 
@@ -758,6 +756,7 @@ static const char *hwcap_str[] = {
 	"fpa",
 	"vfp",
 	"edsp",
+	"java",
 	NULL
 };
 
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index d214e8d49..d433d4784 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -145,6 +145,100 @@ struct rt_sigframe
 	unsigned long retcode;
 };
 
+#ifdef CONFIG_IWMMXT
+
+/* iwmmxt_area is 0x98 bytes long, preceeded by 8 bytes of signature */
+#define IWMMXT_STORAGE_SIZE	(0x98 + 8)
+#define IWMMXT_MAGIC0		0x12ef842a
+#define IWMMXT_MAGIC1		0x1c07ca71
+
+static int page_present(struct mm_struct *mm, unsigned long addr, int wr)
+{
+	pgd_t *pgd = pgd_offset(mm, addr);
+	if (pgd_present(*pgd)) {
+		pmd_t *pmd = pmd_offset(pgd, addr);
+		if (pmd_present(*pmd)) {
+			pte_t *pte = pte_offset_map(pmd, addr);
+			return (pte_present(*pte) && (!wr || pte_write(*pte)));
+		}
+	}
+	return 0;
+}
+
+static int
+preserve_iwmmxt_context(void *iwmmxt_save_area)
+{
+	int err = 0;
+
+	/* the iWMMXt context must be 64 bit aligned */
+	long *iwmmxt_storage = (long *)(((long)iwmmxt_save_area + 4) & ~7);
+
+again:
+	__put_user_error(IWMMXT_MAGIC0, iwmmxt_storage+0, err);
+	__put_user_error(IWMMXT_MAGIC1, iwmmxt_storage+1, err);
+	/*
+	 * iwmmxt_task_copy() doesn't check user permissions.
+	 * Let's do a dummy write on the upper boundary to ensure
+	 * access to user mem is OK all way up.
+	 */
+	__put_user_error(0, iwmmxt_storage+IWMMXT_STORAGE_SIZE/4-1, err);
+	if (!err) {
+		/* Let's make sure the user mapping won't disappear under us */
+		struct mm_struct *mm = current->mm;
+		unsigned long addr = (unsigned long)iwmmxt_storage;
+		spin_lock(&mm->page_table_lock);
+		if ( !page_present(mm, addr, 1) ||
+		     !page_present(mm, addr+IWMMXT_STORAGE_SIZE-1, 1) ) {
+			/* our user area has gone before grabbing the lock */
+			spin_unlock(&mm->page_table_lock);
+			goto again;
+		}
+		iwmmxt_task_copy(current_thread_info(), iwmmxt_storage+2);
+		spin_unlock(&mm->page_table_lock);
+		return 0;
+	}
+	return err;
+}
+
+static int
+restore_iwmmxt_context(void *iwmmxt_save_area)
+{
+	int err = 0;
+	long *iwmmxt_storage, magic0, magic1, dummy;
+
+	/* the iWMMXt context is 64 bit aligned */
+	iwmmxt_storage = (long *)(((long)iwmmxt_save_area + 4) & ~7);
+
+	/*
+	 * Validate iWMMXt context signature.
+	 * Also, iwmmxt_task_restore() doesn't check user permissions.
+	 * Let's do a dummy write on the upper boundary to ensure
+	 * access to user mem is OK all way up.
+	 */
+again:
+	__get_user_error(magic0, iwmmxt_storage+0, err);
+	__get_user_error(magic1, iwmmxt_storage+1, err);
+	if (!err && magic0 == IWMMXT_MAGIC0 && magic1 == IWMMXT_MAGIC1 &&
+	    !__get_user(dummy, iwmmxt_storage+IWMMXT_STORAGE_SIZE/4-1)) {
+		/* Let's make sure the user mapping won't disappear under us */
+		struct mm_struct *mm = current->mm;
+		unsigned long addr = (unsigned long)iwmmxt_storage;
+		spin_lock(&mm->page_table_lock);
+		if ( !page_present(mm, addr, 0) ||
+		     !page_present(mm, addr+IWMMXT_STORAGE_SIZE-1, 0) ) {
+			/* our user area has gone before grabbing the lock */
+			spin_unlock(&mm->page_table_lock);
+			goto again;
+		}
+		iwmmxt_task_restore(current_thread_info(), iwmmxt_storage+2);
+		spin_unlock(&mm->page_table_lock);
+		return 0;
+	}
+	return -1;
+}
+
+#endif
+
 static int
 restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
 {
@@ -208,6 +302,11 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
 	if (restore_sigcontext(regs, &frame->sc))
 		goto badframe;
 
+#ifdef CONFIG_IWMMXT
+	if (test_thread_flag(TIF_USING_IWMMXT) && restore_iwmmxt_context(frame+1))
+		goto badframe;
+#endif
+
 	/* Send SIGTRAP if we're single-stepping */
 	if (current->ptrace & PT_SINGLESTEP) {
 		ptrace_cancel_bpt(current);
@@ -256,6 +355,11 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
 	if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT)
 		goto badframe;
 
+#ifdef CONFIG_IWMMXT
+	if (test_thread_flag(TIF_USING_IWMMXT) && restore_iwmmxt_context(frame+1))
+		goto badframe;
+#endif
+
 	/* Send SIGTRAP if we're single-stepping */
 	if (current->ptrace & PT_SINGLESTEP) {
 		ptrace_cancel_bpt(current);
@@ -305,6 +409,12 @@ static inline void __user *
 get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize)
 {
 	unsigned long sp = regs->ARM_sp;
+	void __user *frame;
+
+#ifdef CONFIG_IWMMXT
+	if (test_thread_flag(TIF_USING_IWMMXT))
+		framesize = (framesize + 4 + IWMMXT_STORAGE_SIZE) & ~7;
+#endif
 
 	/*
 	 * This is the X/Open sanctioned signal stack switching.
@@ -315,7 +425,15 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize)
 	/*
 	 * ATPCS B01 mandates 8-byte alignment
 	 */
-	return (void __user *)((sp - framesize) & ~7);
+	frame = (void __user *)((sp - framesize) & ~7);
+
+	/*
+	 * Check that we can actually write to the signal frame.
+	 */
+	if (!access_ok(VERIFY_WRITE, frame, framesize))
+		frame = NULL;
+
+	return frame;
 }
 
 static int
@@ -384,7 +502,7 @@ setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *reg
 	struct sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame));
 	int err = 0;
 
-	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
+	if (!frame)
 		return 1;
 
 	err |= setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]);
@@ -394,6 +512,11 @@ setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *reg
 				      sizeof(frame->extramask));
 	}
 
+#ifdef CONFIG_IWMMXT
+	if (test_thread_flag(TIF_USING_IWMMXT))
+		err |= preserve_iwmmxt_context(frame+1);
+#endif
+
 	if (err == 0)
 		err = setup_return(regs, ka, &frame->retcode, frame, usig);
 
@@ -408,7 +531,7 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
 	stack_t stack;
 	int err = 0;
 
-	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
+	if (!frame)
 		return 1;
 
 	__put_user_error(&frame->info, &frame->pinfo, err);
@@ -428,6 +551,11 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
 				regs, set->sig[0]);
 	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 
+#ifdef CONFIG_IWMMXT
+	if (test_thread_flag(TIF_USING_IWMMXT))
+		err |= preserve_iwmmxt_context(frame+1);
+#endif
+
 	if (err == 0)
 		err = setup_return(regs, ka, &frame->retcode, frame, usig);
 
@@ -454,12 +582,12 @@ static inline void restart_syscall(struct pt_regs *regs)
  * OK, we're invoking a handler
  */	
 static void
-handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
+handle_signal(unsigned long sig, struct k_sigaction *ka,
+	      siginfo_t *info, sigset_t *oldset,
 	      struct pt_regs * regs, int syscall)
 {
 	struct thread_info *thread = current_thread_info();
 	struct task_struct *tsk = current;
-	struct k_sigaction *ka = &tsk->sighand->action[sig-1];
 	int usig = sig;
 	int ret;
 
@@ -514,15 +642,10 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
 		spin_unlock_irq(&tsk->sighand->siglock);
 	}
 
-	if (ret == 0) {
-		if (ka->sa.sa_flags & SA_ONESHOT)
-			ka->sa.sa_handler = SIG_DFL;
+	if (ret == 0)
 		return;
-	}
 
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, tsk);
+	force_sigsegv(sig, tsk);
 }
 
 /*
@@ -536,6 +659,7 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
  */
 static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
 {
+	struct k_sigaction ka;
 	siginfo_t info;
 	int signr;
 
@@ -556,9 +680,9 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
 	if (current->ptrace & PT_SINGLESTEP)
 		ptrace_cancel_bpt(current);
 
-	signr = get_signal_to_deliver(&info, regs, NULL);
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
-		handle_signal(signr, &info, oldset, regs, syscall);
+		handle_signal(signr, &ka, &info, oldset, regs, syscall);
 		if (current->ptrace & PT_SINGLESTEP)
 			ptrace_set_bpt(current);
 		return 1;
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index fb26b3bf9..7cbd18e95 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -217,11 +217,8 @@ asmlinkage int sys_ipc(uint call, int first, int second, int third,
 				return ret;
 			return put_user(raddr, (ulong __user *)third);
 		}
-		case 1:	/* iBCS2 emulator entry point */
-			if (!segment_eq(get_fs(), get_ds()))
-				return -EINVAL;
-			return do_shmat(first, (char __user *) ptr,
-					second, (ulong __user *) third);
+		case 1: /* Of course, we don't support iBCS2! */
+			return -EINVAL;
 		}
 	case SHMDT: 
 		return sys_shmdt ((char __user *)ptr);
@@ -257,7 +254,7 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, struct
 	if (!newsp)
 		newsp = regs->ARM_sp;
 
-	return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL);
+	return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
 }
 
 asmlinkage int sys_vfork(struct pt_regs *regs)
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index efcb44a9e..3043e6de7 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -33,7 +33,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/leds.h>
-
+#include <asm/thread_info.h>
 #include <asm/mach/time.h>
 
 u64 jiffies_64 = INITIAL_JIFFIES;
@@ -52,6 +52,20 @@ EXPORT_SYMBOL(rtc_lock);
 /* change this if you have some constant time drift */
 #define USECS_PER_JIFFY	(1000000/HZ)
 
+#ifdef CONFIG_SMP
+unsigned long profile_pc(struct pt_regs *regs)
+{
+	unsigned long fp, pc = instruction_pointer(regs);
+
+	if (in_lock_functions(pc)) {
+		fp = thread_saved_fp(current);
+		pc = pc_pointer(((unsigned long *)fp)[-1]);
+	}
+
+	return pc;
+}
+EXPORT_SYMBOL(profile_pc);
+#endif
 
 /*
  * hook for setting the RTC's idea of the current time.
@@ -79,31 +93,6 @@ unsigned long long __attribute__((weak)) sched_clock(void)
 	return (unsigned long long)jiffies * (1000000000 / HZ);
 }
 
-/*
- * Handle kernel profile stuff...
- */
-static inline void do_profile(struct pt_regs *regs)
-{
-
-	profile_hook(regs);
-
-	if (!user_mode(regs) &&
-	    prof_buffer &&
-	    current->pid) {
-		unsigned long pc = instruction_pointer(regs);
-		extern int _stext;
-
-		pc -= (unsigned long)&_stext;
-
-		pc >>= prof_shift;
-
-		if (pc >= prof_len)
-			pc = prof_len - 1;
-
-		prof_buffer[pc] += 1;
-	}
-}
-
 static unsigned long next_rtc_update;
 
 /*
@@ -315,9 +304,42 @@ int do_settimeofday(struct timespec *tv)
 
 EXPORT_SYMBOL(do_settimeofday);
 
+/**
+ * save_time_delta - Save the offset between system time and RTC time
+ * @delta: pointer to timespec to store delta
+ * @rtc: pointer to timespec for current RTC time
+ *
+ * Return a delta between the system time and the RTC time, such
+ * that system time can be restored later with restore_time_delta()
+ */
+void save_time_delta(struct timespec *delta, struct timespec *rtc)
+{
+	set_normalized_timespec(delta,
+				xtime.tv_sec - rtc->tv_sec,
+				xtime.tv_nsec - rtc->tv_nsec);
+}
+EXPORT_SYMBOL(save_time_delta);
+
+/**
+ * restore_time_delta - Restore the current system time
+ * @delta: delta returned by save_time_delta()
+ * @rtc: pointer to timespec for current RTC time
+ */
+void restore_time_delta(struct timespec *delta, struct timespec *rtc)
+{
+	struct timespec ts;
+
+	set_normalized_timespec(&ts,
+				delta->tv_sec + rtc->tv_sec,
+				delta->tv_nsec + rtc->tv_nsec);
+
+	do_settimeofday(&ts);
+}
+EXPORT_SYMBOL(restore_time_delta);
+
 void timer_tick(struct pt_regs *regs)
 {
-	do_profile(regs);
+	profile_tick(CPU_PROFILING, regs);
 	do_leds();
 	do_set_rtc();
 	do_timer(regs);
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index e5c7f285b..d0f983705 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -381,7 +381,7 @@ do_cache_op(unsigned long start, unsigned long end, int flags)
 {
 	struct vm_area_struct *vma;
 
-	if (end < start)
+	if (end < start || flags)
 		return;
 
 	vma = find_vma(current->active_mm, start);
@@ -391,7 +391,7 @@ do_cache_op(unsigned long start, unsigned long end, int flags)
 		if (end > vma->vm_end)
 			end = vma->vm_end;
 
-		flush_cache_range(vma, start, end);
+		flush_cache_user_range(vma, start, end);
 	}
 }
 
@@ -562,7 +562,7 @@ asmlinkage void __div0(void)
 	printk("Division by zero in kernel.\n");
 	dump_stack();
 }
-EXPORT_SYMBOL_NOVERS(__div0);
+EXPORT_SYMBOL(__div0);
 
 void abort(void)
 {
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index a5db0ddca..1131500de 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -38,9 +38,6 @@ SECTIONS
 		__early_begin = .;
 			*(__early_param)
 		__early_end = .;
-		__start___param = .;
-			*(__param)
-		__stop___param = .;
 		__initcall_start = .;
 			*(.initcall1.init)
 			*(.initcall2.init)
@@ -74,6 +71,7 @@ SECTIONS
 		_text = .;		/* Text and read-only data	*/
 			*(.text)
 			SCHED_TEXT
+			LOCK_TEXT
 			*(.fixup)
 			*(.gnu.warning)
 			*(.rodata)
diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S
index cf3920459..9478e01d1 100644
--- a/arch/arm/lib/getuser.S
+++ b/arch/arm/lib/getuser.S
@@ -32,59 +32,34 @@
 
 	.global	__get_user_1
 __get_user_1:
-	bic	r1, sp, #0x1f00
-	bic	r1, r1, #0x00ff
-	ldr	r1, [r1, #TI_ADDR_LIMIT]
-	sub	r1, r1, #1
-	cmp	r0, r1
-1:	ldrlsbt	r1, [r0]
-	movls	r0, #0
-	movls	pc, lr
-	b	__get_user_bad
+1:	ldrbt	r1, [r0]
+	mov	r0, #0
+	mov	pc, lr
 
 	.global	__get_user_2
 __get_user_2:
-	bic	r2, sp, #0x1f00
-	bic	r2, r2, #0x00ff
-	ldr	r2, [r2, #TI_ADDR_LIMIT]
-	sub	r2, r2, #2
-	cmp	r0, r2
-2:	ldrlsbt	r1, [r0], #1
-3:	ldrlsbt	r2, [r0]
+2:	ldrbt	r1, [r0], #1
+3:	ldrbt	r2, [r0]
 #ifndef __ARMEB__
-	orrls	r1, r1, r2, lsl #8
+	orr	r1, r1, r2, lsl #8
 #else
-	orrls	r1, r2, r1, lsl #8
+	orr	r1, r2, r1, lsl #8
 #endif
-	movls	r0, #0
-	movls	pc, lr
-	b	__get_user_bad
+	mov	r0, #0
+	mov	pc, lr
 
 	.global	__get_user_4
 __get_user_4:
-	bic	r1, sp, #0x1f00
-	bic	r1, r1, #0x00ff
-	ldr	r1, [r1, #TI_ADDR_LIMIT]
-	sub	r1, r1, #4
-	cmp	r0, r1
-4:	ldrlst	r1, [r0]
-	movls	r0, #0
-	movls	pc, lr
-	b	__get_user_bad
+4:	ldrt	r1, [r0]
+	mov	r0, #0
+	mov	pc, lr
 
 	.global	__get_user_8
 __get_user_8:
-	bic	r2, sp, #0x1f00
-	bic	r2, r2, #0x00ff
-	ldr	r2, [r2, #TI_ADDR_LIMIT]
-	sub	r2, r2, #8
-	cmp	r0, r2
-5:	ldrlst	r1, [r0], #4
-6:	ldrlst	r2, [r0]
-	movls	r0, #0
-	movls	pc, lr
-
-	/* fall through */
+5:	ldrt	r1, [r0], #4
+6:	ldrt	r2, [r0]
+	mov	r0, #0
+	mov	pc, lr
 
 __get_user_bad_8:
 	mov	r2, #0
diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S
index 293de2d2c..b978885a1 100644
--- a/arch/arm/lib/putuser.S
+++ b/arch/arm/lib/putuser.S
@@ -32,60 +32,35 @@
 
 	.global	__put_user_1
 __put_user_1:
-	bic	ip, sp, #0x1f00
-	bic	ip, ip, #0x00ff
-	ldr	ip, [ip, #TI_ADDR_LIMIT]
-	sub	ip, ip, #1
-	cmp	r0, ip
-1:	strlsbt	r1, [r0]
-	movls	r0, #0
-	movls	pc, lr
-	b	__put_user_bad
+1:	strbt	r1, [r0]
+	mov	r0, #0
+	mov	pc, lr
 
 	.global	__put_user_2
 __put_user_2:
-	bic	ip, sp, #0x1f00
-	bic	ip, ip, #0x00ff
-	ldr	ip, [ip, #TI_ADDR_LIMIT]
-	sub	ip, ip, #2
-	cmp	r0, ip
-	movls	ip, r1, lsr #8
+	mov	ip, r1, lsr #8
 #ifndef __ARMEB__
-2:	strlsbt	r1, [r0], #1
-3:	strlsbt	ip, [r0]
+2:	strbt	r1, [r0], #1
+3:	strbt	ip, [r0]
 #else
-2:	strlsbt	ip, [r0], #1
-3:	strlsbt	r1, [r0]
+2:	strbt	ip, [r0], #1
+3:	strbt	r1, [r0]
 #endif
-	movls	r0, #0
-	movls	pc, lr
-	b	__put_user_bad
+	mov	r0, #0
+	mov	pc, lr
 
 	.global	__put_user_4
 __put_user_4:
-	bic	ip, sp, #0x1f00
-	bic	ip, ip, #0x00ff
-	ldr	ip, [ip, #TI_ADDR_LIMIT]
-	sub	ip, ip, #4
-	cmp	r0, ip
-4:	strlst	r1, [r0]
-	movls	r0, #0
-	movls	pc, lr
-	b	__put_user_bad
+4:	strt	r1, [r0]
+	mov	r0, #0
+	mov	pc, lr
 
 	.global	__put_user_8
 __put_user_8:
-	bic	ip, sp, #0x1f00
-	bic	ip, ip, #0x00ff
-	ldr	ip, [ip, #TI_ADDR_LIMIT]
-	sub	ip, ip, #8
-	cmp	r0, ip
-5:	strlst	r1, [r0], #4
-6:	strlst	r2, [r0]
-	movls	r0, #0
-	movls	pc, lr
-
-	/* fall through */
+5:	strt	r1, [r0], #4
+6:	strt	r2, [r0]
+	mov	r0, #0
+	mov	pc, lr
 
 __put_user_bad:
 	mov	r0, #-EFAULT
diff --git a/arch/arm/mach-integrator/clock.c b/arch/arm/mach-integrator/clock.c
index 6af3715ad..56200594d 100644
--- a/arch/arm/mach-integrator/clock.c
+++ b/arch/arm/mach-integrator/clock.c
@@ -76,7 +76,10 @@ EXPORT_SYMBOL(clk_get_rate);
 
 long clk_round_rate(struct clk *clk, unsigned long rate)
 {
-	return rate;
+	struct icst525_vco vco;
+
+	vco = icst525_khz_to_vco(clk->params, rate / 1000);
+	return icst525_khz(clk->params, vco) * 1000;
 }
 EXPORT_SYMBOL(clk_round_rate);
 
@@ -86,8 +89,8 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 	if (clk->setvco) {
 		struct icst525_vco vco;
 
-		vco = icst525_khz_to_vco(clk->params, rate);
-		clk->rate = icst525_khz(clk->params, vco);
+		vco = icst525_khz_to_vco(clk->params, rate / 1000);
+		clk->rate = icst525_khz(clk->params, vco) * 1000;
 
 		printk("Clock %s: setting VCO reg params: S=%d R=%d V=%d\n",
 			clk->name, vco.s, vco.r, vco.v);
diff --git a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c
index e2a07deda..71c58bff3 100644
--- a/arch/arm/mach-integrator/cpu.c
+++ b/arch/arm/mach-integrator/cpu.c
@@ -79,7 +79,7 @@ static int integrator_set_target(struct cpufreq_policy *policy,
 				 unsigned int target_freq,
 				 unsigned int relation)
 {
-	unsigned long cpus_allowed;
+	cpumask_t cpus_allowed;
 	int cpu = policy->cpu;
 	struct icst525_vco vco;
 	struct cpufreq_freqs freqs;
@@ -94,7 +94,7 @@ static int integrator_set_target(struct cpufreq_policy *policy,
 	 * Bind to the specified CPU.  When this call returns,
 	 * we should be running on the right CPU.
 	 */
-	set_cpus_allowed(current, 1 << cpu);
+	set_cpus_allowed(current, cpumask_of_cpu(cpu));
 	BUG_ON(cpu != smp_processor_id());
 
 	/* get current setting */
@@ -154,14 +154,14 @@ static int integrator_set_target(struct cpufreq_policy *policy,
 
 static unsigned int integrator_get(unsigned int cpu)
 {
-	unsigned long cpus_allowed;
+	cpumask_t cpus_allowed;
 	unsigned int current_freq;
 	u_int cm_osc;
 	struct icst525_vco vco;
 
 	cpus_allowed = current->cpus_allowed;
 
-	set_cpus_allowed(current, 1 << cpu);
+	set_cpus_allowed(current, cpumask_of_cpu(cpu));
 	BUG_ON(cpu != smp_processor_id());
 
 	/* detect memory etc. */
diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c
index e776e8a8d..0859557e7 100644
--- a/arch/arm/mach-integrator/impd1.c
+++ b/arch/arm/mach-integrator/impd1.c
@@ -21,6 +21,7 @@
 #include <asm/io.h>
 #include <asm/hardware/icst525.h>
 #include <asm/hardware/amba.h>
+#include <asm/hardware/amba_clcd.h>
 #include <asm/arch/lm.h>
 #include <asm/arch/impd1.h>
 #include <asm/sizes.h>
@@ -87,10 +88,198 @@ void impd1_tweak_control(struct device *dev, u32 mask, u32 val)
 
 EXPORT_SYMBOL(impd1_tweak_control);
 
+/*
+ * CLCD support
+ */
+#define PANEL		PROSPECTOR
+
+#define LTM10C209		1
+#define PROSPECTOR		2
+#define SVGA			3
+#define VGA			4
+
+#if PANEL == VGA
+#define PANELTYPE	vga
+static struct clcd_panel vga = {
+	.mode		= {
+		.name		= "VGA",
+		.refresh	= 60,
+		.xres		= 640,
+		.yres		= 480,
+		.pixclock	= 39721,
+		.left_margin	= 40,
+		.right_margin	= 24,
+		.upper_margin	= 32,
+		.lower_margin	= 11,
+		.hsync_len	= 96,
+		.vsync_len	= 2,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_BCD | TIM2_IPC,
+	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+	.connector	= IMPD1_CTRL_DISP_VGA,
+	.bpp		= 16,
+	.grayscale	= 0,
+};
+
+#elif PANEL == SVGA
+#define PANELTYPE	svga
+static struct clcd_panel svga = {
+	.mode		= {
+		.name		= "SVGA",
+		.refresh	= 0,
+		.xres		= 800,
+		.yres		= 600,
+		.pixclock	= 27778,
+		.left_margin	= 20,
+		.right_margin	= 20,
+		.upper_margin	= 5,
+		.lower_margin	= 5,
+		.hsync_len	= 164,
+		.vsync_len	= 62,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_BCD,
+	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+	.connector	= IMPD1_CTRL_DISP_VGA,
+	.bpp		= 16,
+	.grayscale	= 0,
+};
+
+#elif PANEL == PROSPECTOR
+#define PANELTYPE	prospector
+static struct clcd_panel prospector = {
+	.mode		= {
+		.name		= "PROSPECTOR",
+		.refresh	= 0,
+		.xres		= 640,
+		.yres		= 480,
+		.pixclock	= 40000,
+		.left_margin	= 33,
+		.right_margin	= 64,
+		.upper_margin	= 36,
+		.lower_margin	= 7,
+		.hsync_len	= 64,
+		.vsync_len	= 25,
+		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_BCD,
+	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+	.fixedtimings	= 1,
+	.connector	= IMPD1_CTRL_DISP_LCD,
+	.bpp		= 16,
+	.grayscale	= 0,
+};
+
+#elif PANEL == LTM10C209
+#define PANELTYPE	ltm10c209
+/*
+ * Untested.
+ */
+static struct clcd_panel ltm10c209 = {
+	.mode		= {
+		.name		= "LTM10C209",
+		.refresh	= 0,
+		.xres		= 640,
+		.yres		= 480,
+		.pixclock	= 40000,
+		.left_margin	= 20,
+		.right_margin	= 20,
+		.upper_margin	= 19,
+		.lower_margin	= 19,
+		.hsync_len	= 20,
+		.vsync_len	= 10,
+		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_BCD,
+	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+	.fixedtimings	= 1,
+	.connector	= IMPD1_CTRL_DISP_LCD,
+	.bpp		= 16,
+	.grayscale	= 0,
+};
+#endif
+
+/*
+ * Disable all display connectors on the interface module.
+ */
+static void impd1fb_clcd_disable(struct clcd_fb *fb)
+{
+	impd1_tweak_control(fb->dev->dev.parent, IMPD1_CTRL_DISP_MASK, 0);
+}
+
+/*
+ * Enable the relevant connector on the interface module.
+ */
+static void impd1fb_clcd_enable(struct clcd_fb *fb)
+{
+	impd1_tweak_control(fb->dev->dev.parent, IMPD1_CTRL_DISP_MASK,
+			fb->panel->connector | IMPD1_CTRL_DISP_ENABLE);
+}
+
+static int impd1fb_clcd_setup(struct clcd_fb *fb)
+{
+	unsigned long framebase = fb->dev->res.start + 0x01000000;
+	unsigned long framesize = SZ_1M;
+	int ret = 0;
+
+	fb->panel = &PANELTYPE;
+
+	if (!request_mem_region(framebase, framesize, "clcd framebuffer")) {
+		printk(KERN_ERR "IM-PD1: unable to reserve framebuffer\n");
+		return -EBUSY;
+	}
+
+	fb->fb.screen_base = ioremap(framebase, framesize);
+	if (!fb->fb.screen_base) {
+		printk(KERN_ERR "IM-PD1: unable to map framebuffer\n");
+		ret = -ENOMEM;
+		goto free_buffer;
+	}
+
+	fb->fb.fix.smem_start	= framebase;
+	fb->fb.fix.smem_len	= framesize;
+
+	return 0;
+
+ free_buffer:
+	release_mem_region(framebase, framesize);
+	return ret;
+}
+
+static void impd1fb_clcd_remove(struct clcd_fb *fb)
+{
+	iounmap(fb->fb.screen_base);
+	release_mem_region(fb->fb.fix.smem_start, fb->fb.fix.smem_len);
+}
+
+static struct clcd_board impd1_clcd_data = {
+	.name		= "IM-PD/1",
+	.check		= clcdfb_check,
+	.decode		= clcdfb_decode,
+	.disable	= impd1fb_clcd_disable,
+	.enable		= impd1fb_clcd_enable,
+	.setup		= impd1fb_clcd_setup,
+	.remove		= impd1fb_clcd_remove,
+};
+
 struct impd1_device {
 	unsigned long	offset;
 	unsigned int	irq[2];
 	unsigned int	id;
+	void		*platform_data;
 };
 
 static struct impd1_device impd1_devs[] = {
@@ -133,6 +322,7 @@ static struct impd1_device impd1_devs[] = {
 		.offset	= 0x01000000,
 		.irq	= { 11 },
 		.id	= 0x00041110,
+		.platform_data = &impd1_clcd_data,
 	}
 };
 
@@ -202,6 +392,7 @@ static int impd1_probe(struct lm_device *dev)
 		d->irq[0]	= dev->irq;
 		d->irq[1]	= dev->irq;
 		d->periphid	= idev->id;
+		d->dev.platform_data = idev->platform_data;
 
 		ret = amba_device_register(d, &dev->resource);
 		if (ret) {
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index e56fcb1ea..0f5fc7861 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/device.h>
+#include <linux/dma-mapping.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/sysdev.h>
@@ -23,8 +24,10 @@
 #include <asm/mach-types.h>
 #include <asm/hardware/amba.h>
 #include <asm/hardware/amba_kmi.h>
+#include <asm/hardware/amba_clcd.h>
 #include <asm/hardware/icst525.h>
 
+#include <asm/arch/cm.h>
 #include <asm/arch/lm.h>
 
 #include <asm/mach/arch.h>
@@ -382,10 +385,83 @@ static struct amba_device aaci_device = {
 	.periphid	= 0,
 };
 
+
+/*
+ * CLCD support
+ */
+static struct clcd_panel vga = {
+	.mode		= {
+		.name		= "VGA",
+		.refresh	= 60,
+		.xres		= 640,
+		.yres		= 480,
+		.pixclock	= 39721,
+		.left_margin	= 40,
+		.right_margin	= 24,
+		.upper_margin	= 32,
+		.lower_margin	= 11,
+		.hsync_len	= 96,
+		.vsync_len	= 2,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_BCD | TIM2_IPC,
+	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+	.bpp		= 16,
+	.grayscale	= 0,
+};
+
+/*
+ * Ensure VGA is selected.
+ */
+static void cp_clcd_enable(struct clcd_fb *fb)
+{
+	cm_control(CM_CTRL_LCDMUXSEL_MASK, CM_CTRL_LCDMUXSEL_VGA);
+}
+
+static unsigned long framesize = SZ_1M;
+
+static int cp_clcd_setup(struct clcd_fb *fb)
+{
+	dma_addr_t dma;
+
+	fb->panel = &vga;
+
+	fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
+						    &dma, GFP_KERNEL);
+	if (!fb->fb.screen_base) {
+		printk(KERN_ERR "CLCD: unable to map framebuffer\n");
+		return -ENOMEM;
+	}
+
+	fb->fb.fix.smem_start	= dma;
+	fb->fb.fix.smem_len	= framesize;
+
+	return 0;
+}
+
+static void cp_clcd_remove(struct clcd_fb *fb)
+{
+	dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
+			      fb->fb.screen_base, fb->fb.fix.smem_start);
+}
+
+static struct clcd_board clcd_data = {
+	.name		= "Integrator/CP",
+	.check		= clcdfb_check,
+	.decode		= clcdfb_decode,
+	.enable		= cp_clcd_enable,
+	.setup		= cp_clcd_setup,
+	.remove		= cp_clcd_remove,
+};
+
 static struct amba_device clcd_device = {
 	.dev		= {
 		.bus_id	= "mb:c0",
 		.coherent_dma_mask = ~0,
+		.platform_data = &clcd_data,
 	},
 	.res		= {
 		.start	= INTCP_PA_CLCD_BASE,
diff --git a/arch/arm/mach-iop3xx/Kconfig b/arch/arm/mach-iop3xx/Kconfig
index 6a388e273..019b1bf25 100644
--- a/arch/arm/mach-iop3xx/Kconfig
+++ b/arch/arm/mach-iop3xx/Kconfig
@@ -2,53 +2,48 @@ if ARCH_IOP3XX
 
 menu "IOP3xx Implementation Options"
 
-choice
-	prompt "IOP3xx System Type"
-	default ARCH_IQ80310
-
-config ARCH_IQ80310
-	bool "IQ80310"
-	help
-	  Say Y here if you want to run your kernel on the Intel IQ80310
-	  evaluation kit for the IOP310 chipset.
+comment "IOP3xx Platform Types"
 
 config ARCH_IQ80321
-	bool "IQ80321"
+	bool "Enable support for IQ80321"
+	select ARCH_IOP321
 	help
 	  Say Y here if you want to run your kernel on the Intel IQ80321
 	  evaluation kit for the IOP321 chipset.
-endchoice
 
-# Which IOP variant are we running?
-config ARCH_IOP310
-	bool
-	default ARCH_IQ80310
+config ARCH_IQ31244
+	bool "Enable support for IQ31244"
+	select ARCH_IOP321
 	help
-	  The IQ80310 uses the IOP310 variant.
+	  Say Y here if you want to run your kernel on the Intel IQ31244
+	  evaluation kit for the IOP321 chipset.
+
+config ARCH_IQ80331
+	bool "Enable support for IQ80331"
+	select ARCH_IOP331
+	help
+	  Say Y here if you want to run your kernel on the Intel IQ80331
+	  evaluation kit for the IOP331 chipset.
+
+config ARCH_EP80219
+    bool "Enable support for EP80219"
+    select ARCH_IOP321
+    select ARCH_IQ31244
 
+# Which IOP variant are we running?
 config ARCH_IOP321
 	bool
-	default ARCH_IQ80321
 	help
 	  The IQ80321 uses the IOP321 variant.
+	  The IQ31244 and EP80219 uses the IOP321 variant.
 
-comment "IOP3xx Chipset Features"
-
-config IOP3XX_AAU
-	bool "Support Intel IOP3xx Application Accelerator Unit (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-
-config IOP3XX_DMA
-	bool "Support Intel IOP3xx DMA (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-
-config IOP3XX_MU
-	bool "Support Intel IOP3xx Messaging Unit (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+config ARCH_IOP331
+	bool
+	default ARCH_IQ80331
+	help
+	  The IQ80331 uses the IOP331 variant.
 
-config IOP3XX_PMON
-	bool "Support Intel IOP3xx Performance Monitor (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+comment "IOP3xx Chipset Features"
 
 endmenu
 
diff --git a/arch/arm/mach-iop3xx/Makefile b/arch/arm/mach-iop3xx/Makefile
index a6d1cf98b..dcbffb66d 100644
--- a/arch/arm/mach-iop3xx/Makefile
+++ b/arch/arm/mach-iop3xx/Makefile
@@ -4,27 +4,18 @@
 
 # Object file lists.
 
-obj-y			:= arch.o
+obj-y			:= common.o
 
 obj-m			:=
 obj-n			:=
 obj-			:=
 
-obj-$(CONFIG_ARCH_IOP310)  += xs80200-irq.o iop310-irq.o iop310-pci.o mm.o
+obj-$(CONFIG_ARCH_IOP321)  += iop321-setup.o iop321-irq.o iop321-pci.o iop321-mm.o iop321-time.o
 
-obj-$(CONFIG_ARCH_IQ80310) += iq80310-pci.o iq80310-irq.o
+obj-$(CONFIG_ARCH_IOP331)  += iop331-setup.o iop331-irq.o iop331-pci.o iop331-time.o
 
-obj-$(CONFIG_ARCH_IOP321)  += iop321-irq.o iop321-pci.o mm-321.o iop321-time.o
+obj-$(CONFIG_ARCH_IQ80321) += iq80321-mm.o iq80321-pci.o
 
-obj-$(CONFIG_ARCH_IQ80321) += iq80321-pci.o
+obj-$(CONFIG_ARCH_IQ31244) += iq31244-mm.o iq31244-pci.o
 
-ifeq ($(CONFIG_ARCH_IQ80310),y)
-   ifneq ($(CONFIG_XSCALE_PMU_TIMER),y)
-      obj-y			+= iq80310-time.o
-   endif
-endif
-
-obj-$(CONFIG_IOP3XX_AAU) += aau.o
-obj-$(CONFIG_IOP3XX_DMA) += dma.o
-obj-$(CONFIG_IOP3XX_MU) += message.o
-obj-$(CONFIG_IOP3XX_PMON) += pmon.o
+obj-$(CONFIG_ARCH_IQ80331) += iq80331-mm.o iq80331-pci.o
diff --git a/arch/arm/mach-iop3xx/arch.c b/arch/arm/mach-iop3xx/arch.c
index 3df5e454c..3aca6671f 100644
--- a/arch/arm/mach-iop3xx/arch.c
+++ b/arch/arm/mach-iop3xx/arch.c
@@ -21,56 +21,30 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-#ifdef CONFIG_ARCH_IQ80310
-extern void iq80310_map_io(void);
-extern void iq80310_init_irq(void);
+#ifdef CONFIG_ARCH_IQ80331
+extern void iq80331_map_io(void);
+extern void iop331_init_irq(void);
+extern void iop331_init_time(void);
 #endif
 
-#ifdef CONFIG_ARCH_IQ80321
-extern void iq80321_map_io(void);
-extern void iop321_init_irq(void);
-extern void iop321_init_time(void);
-#endif
-
-#ifdef CONFIG_ARCH_IQ80310
-static void __init
-fixup_iq80310(struct machine_desc *desc, struct tag *tags,
-	      char **cmdline, struct meminfo *mi)
-{
-	system_rev = (*(volatile unsigned int*)0xfe830000) & 0x0f;
-
-	if (system_rev)
-		system_rev = 0xF;
-}
-#endif
-
-#ifdef CONFIG_ARCH_IQ80321
+#ifdef CONFIG_ARCH_IQ80331
 static void __init
-fixup_iop321(struct machine_desc *desc, struct param_struct *params,
+fixup_iop331(struct machine_desc *desc, struct tag *tags,
 	      char **cmdline, struct meminfo *mi)
 {
 }
 #endif
 
-#ifdef CONFIG_ARCH_IQ80310
-MACHINE_START(IQ80310, "Cyclone IQ80310")
-	MAINTAINER("MontaVista Software Inc.")
-	BOOT_MEM(0xa0000000, 0xfe000000, 0xfe000000)
-	FIXUP(fixup_iq80310)
-	MAPIO(iq80310_map_io)
-	INITIRQ(iq80310_init_irq)
+#if defined(CONFIG_ARCH_IQ80331)
+MACHINE_START(IQ80331, "Intel IQ80331")
+	MAINTAINER("Intel Corp.")
+	BOOT_MEM(PHYS_OFFSET, 0xfff01000, 0xfffff000) // virtual, physical
+//	BOOT_MEM(PHYS_OFFSET, IQ80331_UART0_VIRT, IQ80331_UART0_PHYS)
+	MAPIO(iq80331_map_io)
+	INITIRQ(iop331_init_irq)
+	INITTIME(iop331_init_time)
+	BOOT_PARAMS(0x0100)
 MACHINE_END
-
-#elif defined(CONFIG_ARCH_IQ80321)
-MACHINE_START(IQ80321, "Intel IQ80321")
-	MAINTAINER("MontaVista Software, Inc.")
-	BOOT_MEM(PHYS_OFFSET, IQ80321_UART1, 0xfe800000)
-	FIXUP(fixup_iop321)
-	MAPIO(iq80321_map_io)
-	INITIRQ(iop321_init_irq)
-	INITTIME(iop321_init_time)
-MACHINE_END
-
 #else
-#error No machine descriptor defined for this IOP310 implementation
+#error No machine descriptor defined for this IOP3xx implementation
 #endif
diff --git a/arch/arm/mach-iop3xx/iop321-irq.c b/arch/arm/mach-iop3xx/iop321-irq.c
index 472faf582..d42aae6ae 100644
--- a/arch/arm/mach-iop3xx/iop321-irq.c
+++ b/arch/arm/mach-iop3xx/iop321-irq.c
@@ -81,7 +81,8 @@ void __init iop321_init_irq(void)
 
 	intctl_write(0);		// disable all interrupts
 	intstr_write(0);		// treat all as IRQ
-	if(machine_is_iq80321()) 	// all interrupts are inputs to chip
+	if(machine_is_iq80321() ||
+	   machine_is_iq31244()) 	// all interrupts are inputs to chip
 		*IOP321_PCIIRSR = 0x0f;
 
 	for(i = IOP321_IRQ_OFS; i < NR_IOP321_IRQS; i++)
diff --git a/arch/arm/mach-iop3xx/iop321-pci.c b/arch/arm/mach-iop3xx/iop321-pci.c
index 3ae69a1ff..8fdfc3a8f 100644
--- a/arch/arm/mach-iop3xx/iop321-pci.c
+++ b/arch/arm/mach-iop3xx/iop321-pci.c
@@ -44,7 +44,7 @@ static u32 iop321_cfg_address(struct pci_bus *bus, int devfn, int where)
 	u32 addr;
 
 	if (sys->busnr == bus->number)
-		addr = 1 << (PCI_SLOT(devfn) + 16);
+		addr = 1 << (PCI_SLOT(devfn) + 16) | (PCI_SLOT(devfn) << 11);
 	else
 		addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1;
 
@@ -158,6 +158,8 @@ iop321_write_config(struct pci_bus *bus, unsigned int devfn, int where,
 			: "r" (value), "r" (addr),
 			  "r" (IOP321_OCCAR), "r" (IOP321_OCCDR));
 	}
+
+	return PCIBIOS_SUCCESSFUL;
 }
 
 static struct pci_ops iop321_ops = {
@@ -193,53 +195,16 @@ struct pci_bus *iop321_scan_bus(int nr, struct pci_sys_data *sys)
 	return pci_scan_bus(sys->busnr, &iop321_ops, sys);
 }
 
-/*
- * Setup the system data for controller 'nr'.   Return 0 if none found,
- * 1 if found, or negative error.
- */
-int iop321_setup(int nr, struct pci_sys_data *sys)
-{
-	struct resource *res;
-
-	if (nr >= 1)
-		return 0;
-
-	res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL);
-	if (!res)
-		panic("PCI: unable to alloc resources");
-
-	memset(res, 0, sizeof(struct resource) * 2);
-
-	switch (nr) {
-	case 0:
-		res[0].start = IOP321_PCI_IO_BASE + 0x6e000000;
-		res[0].end   = IOP321_PCI_IO_BASE + IOP321_PCI_IO_SIZE-1 + 0x6e000000;
-		res[0].name  = "PCI IO Primary";
-		res[0].flags = IORESOURCE_IO;
-
-		res[1].start = IOP321_PCI_MEM_BASE;
-		res[1].end   = IOP321_PCI_MEM_BASE + IOP321_PCI_MEM_SIZE;
-		res[1].name  = "PCI Memory Primary";
-		res[1].flags = IORESOURCE_MEM;
-		break;
-	}
-
-	request_resource(&ioport_resource, &res[0]);
-	request_resource(&iomem_resource, &res[1]);
-
-	sys->resource[0] = &res[0];
-	sys->resource[1] = &res[1];
-	sys->resource[2] = NULL;
-	sys->io_offset   = 0x6e000000;
-
-	return 1;
-}
-
-
-
-
 void iop321_init(void)
 {
+#if CONFIG_ARCH_EP80219
+    *IOP321_ATUCR = 0x2;
+    *IOP321_OIOWTVR = 0x90000000;
+    *IOP321_IABAR0  = 0x00000004;
+    *IOP321_IABAR2  = 0xa000000c;
+    *IOP321_IALR2   = 0xe0000000;
+#endif
+
 	DBG("PCI:  Intel 80321 PCI init code.\n");
 	DBG("\tATU: IOP321_ATUCMD=0x%04x\n", *IOP321_ATUCMD);
 	DBG("\tATU: IOP321_OMWTVR0=0x%04x, IOP321_OIOWTVR=0x%04x\n",
@@ -251,7 +216,12 @@ void iop321_init(void)
 	DBG("\tATU: IOP321_IABAR2=0x%08x IOP321_IALR2=0x%08x IOP321_IATVR2=%08x\n", *IOP321_IABAR2, *IOP321_IALR2, *IOP321_IATVR2);
 	DBG("\tATU: IOP321_IABAR3=0x%08x IOP321_IALR3=0x%08x IOP321_IATVR3=%08x\n", *IOP321_IABAR3, *IOP321_IALR3, *IOP321_IATVR3);
 
+#if 0
+	hook_fault_code(4, iop321_pci_abort, SIGBUS, "external abort on linefetch");
+	hook_fault_code(6, iop321_pci_abort, SIGBUS, "external abort on linefetch");
+	hook_fault_code(8, iop321_pci_abort, SIGBUS, "external abort on non-linefetch");
+	hook_fault_code(10, iop321_pci_abort, SIGBUS, "external abort on non-linefetch");
+#endif
 	hook_fault_code(16+6, iop321_pci_abort, SIGBUS, "imprecise external abort");
-
 }
 
diff --git a/arch/arm/mach-iop3xx/iop321-time.c b/arch/arm/mach-iop3xx/iop321-time.c
index be36c7069..b2135e18e 100644
--- a/arch/arm/mach-iop3xx/iop321-time.c
+++ b/arch/arm/mach-iop3xx/iop321-time.c
@@ -5,7 +5,7 @@
  *
  * Author: Deepak Saxena <dsaxena@mvista.com>
  *
- * Copyright 2002 MontaVista Software Inc.
+ * Copyright 2002-2003 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
@@ -23,17 +23,25 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
-
+#include <asm/mach-types.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 
+#define IOP321_TIME_SYNC 0
+
+static unsigned long iop321_latch;
+
+static inline unsigned long get_elapsed(void)
+{
+	return iop321_latch - *IOP321_TU_TCR0;
+}
+
 static unsigned long iop321_gettimeoffset(void)
 {
 	unsigned long elapsed, usec;
+	u32 tisr1, tisr2;
 
 	/*
-	 * FIXME: Implement what is described in this comment.
-	 *
 	 * If an interrupt was pending before we read the timer,
 	 * we've already wrapped.  Factor this into the time.
 	 * If an interrupt was pending after we read the timer,
@@ -42,12 +50,19 @@ static unsigned long iop321_gettimeoffset(void)
 	 * be sure its value is after the wrap.
 	 */
 
-	elapsed = *IOP321_TU_TCR0;
+	asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr1));
+	elapsed = get_elapsed();
+	asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr2));
+
+	if(tisr1 & 1)
+		elapsed += iop321_latch;
+	else if (tisr2 & 1)
+		elapsed = iop321_latch + get_elapsed();
 
 	/*
 	 * Now convert them to usec.
 	 */
-	usec = (unsigned long)((LATCH - elapsed) * (tick_nsec / 1000)) / LATCH;
+	usec = (unsigned long)(elapsed * (tick_nsec / 1000)) / iop321_latch;
 
 	return usec;
 }
@@ -56,6 +71,10 @@ static irqreturn_t
 iop321_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	u32 tisr;
+#ifdef IOP321_TIME_SYNC
+	u32 passed;
+#define TM_THRESH (iop321_latch*2)
+#endif
 
 	asm volatile("mrc p6, 0, %0, c6, c1, 0" : "=r" (tisr));
 
@@ -63,7 +82,24 @@ iop321_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
 	asm volatile("mcr p6, 0, %0, c6, c1, 0" : : "r" (tisr));
 
-	timer_tick(regs);
+#ifdef IOP321_TIME_SYNC
+	passed = 0xffffffff - *IOP321_TU_TCR1;
+
+	do
+	{
+		do_timer(regs);
+		if(passed < TM_THRESH)
+			break;
+		if(passed > iop321_latch)
+			passed -= iop321_latch;
+		else
+			passed = 0;
+	} while(1);
+
+	asm volatile("mcr p6, 0, %0, c3, c1, 0" : : "r" (0xffffffff));
+#else
+	do_timer(regs);
+#endif
 
 	return IRQ_HANDLED;
 }
@@ -79,17 +115,27 @@ extern int setup_arm_irq(int, struct irqaction*);
 void __init iop321_init_time(void)
 {
 	u32 timer_ctl;
-	u32 latch = LATCH;
 
+	iop321_latch = (CLOCK_TICK_RATE + HZ / 2) / HZ;
 	gettimeoffset = iop321_gettimeoffset;
 	setup_irq(IRQ_IOP321_TIMER0, &iop321_timer_irq);
 
 	timer_ctl = IOP321_TMR_EN | IOP321_TMR_PRIVILEGED | IOP321_TMR_RELOAD |
 			IOP321_TMR_RATIO_1_1;
 
-	asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (LATCH));
+	asm volatile("mcr p6, 0, %0, c4, c1, 0" : : "r" (iop321_latch));
 
 	asm volatile("mcr p6, 0, %0, c0, c1, 0"	: : "r" (timer_ctl));
+
+#ifdef IOP321_TIME_SYNC
+        /* Setup second timer */
+        /* setup counter */
+        timer_ctl = IOP321_TMR_EN | IOP321_TMR_PRIVILEGED |
+                        IOP321_TMR_RATIO_1_1;
+        asm volatile("mcr p6, 0, %0, c3, c1, 0" : : "r" (0xffffffff));
+        /* setup control */
+        asm volatile("mcr p6, 0, %0, c1, c1, 0" : : "r" (timer_ctl));
+#endif
 }
 
 
diff --git a/arch/arm/mach-iop3xx/iq80321-pci.c b/arch/arm/mach-iop3xx/iq80321-pci.c
index 7dce5dfa6..5d9624863 100644
--- a/arch/arm/mach-iop3xx/iq80321-pci.c
+++ b/arch/arm/mach-iop3xx/iq80321-pci.c
@@ -38,37 +38,79 @@
 
 #define INTE	IRQ_IQ80321_I82544
 
-typedef u8 irq_table[4];
-
-static irq_table pci_irq_table[] = {
-	/*
-	 * PCI IDSEL/INTPIN->INTLINE
-	 * A       B       C       D
-	 */
-	{INTE, INTE, INTE, INTE}, /* Gig-E */
-	{INTD, INTC, INTD, INTA}, /* Unused */
-	{INTC, INTD, INTA, INTB}, /* PCI-X Slot */
-};
-
 static inline int __init
 iq80321_map_irq(struct pci_dev *dev, u8 idsel, u8 pin)
 {
+	static int pci_irq_table[][4] = {
+		/*
+		 * PCI IDSEL/INTPIN->INTLINE
+		 * A       B       C       D
+		 */
+		{INTE, INTE, INTE, INTE}, /* Gig-E */
+		{-1, -1, -1, -1}, 	  /* Unused */
+		{INTC, INTD, INTA, INTB}, /* PCI-X Slot */
+		{-1, -1, -1, -1},
+	};
+
 	BUG_ON(pin < 1 || pin > 4);
 
-	return PCI_IRQ_TABLE_LOOKUP(2, 3);
+//	return PCI_IRQ_TABLE_LOOKUP(4, 7);
+	return pci_irq_table[idsel%4][pin-1];
 }
 
 static int iq80321_setup(int nr, struct pci_sys_data *sys)
 {
-	switch (nr) {
-	case 0:
-		sys->map_irq = iq80321_map_irq;
-		break;
-	default:
+	struct resource *res;
+
+	if(nr != 0)
 		return 0;
-	}
 
-	return iop321_setup(nr, sys);
+	res = kmalloc(sizeof(struct resource) * 2, GFP_KERNEL);
+	if (!res)
+		panic("PCI: unable to alloc resources");
+
+	memset(res, 0, sizeof(struct resource) * 2);
+
+	res[0].start = IQ80321_PCI_IO_BASE + IQ80321_PCI_IO_OFFSET;
+	res[0].end   = IQ80321_PCI_IO_BASE + IQ80321_PCI_IO_SIZE - 1 + IQ80321_PCI_IO_OFFSET;
+	res[0].name  = "IQ80321 PCI I/O Space";
+	res[0].flags = IORESOURCE_IO;
+
+	res[1].start = IQ80321_PCI_MEM_BASE;
+	res[1].end   = IQ80321_PCI_MEM_BASE + IQ80321_PCI_MEM_SIZE;
+	res[1].name  = "IQ80321 PCI Memory Space";
+	res[1].flags = IORESOURCE_MEM;
+
+	request_resource(&ioport_resource, &res[0]);
+	request_resource(&iomem_resource, &res[1]);
+
+	/*
+	 * Since the IQ80321 is a slave card on a PCI backplane,
+	 * it uses BAR1 to reserve a portion of PCI memory space for
+	 * use with the private devices on the secondary bus
+	 * (GigE and PCI-X slot). We read BAR1 and configure
+	 * our outbound translation windows to target that
+	 * address range and assign all devices in that
+	 * address range. W/O this, certain BIOSes will fail
+	 * to boot as the IQ80321 claims addresses that are
+	 * in use by other devices.
+	 *
+	 * Note that the same cannot be done  with I/O space,
+	 * so hopefully the host will stick to the lower 64K for
+	 * PCI I/O and leave us alone.
+	 */
+	sys->mem_offset = IQ80321_PCI_MEM_BASE -
+		(*IOP321_IABAR1 & PCI_BASE_ADDRESS_MEM_MASK);
+
+	sys->resource[0] = &res[0];
+	sys->resource[1] = &res[1];
+	sys->resource[2] = NULL;
+	sys->io_offset   = IQ80321_PCI_IO_OFFSET;
+
+	iop3xx_pcibios_min_io = IQ80321_PCI_IO_BASE;
+	iop3xx_pcibios_min_mem = IQ80321_PCI_MEM_BASE;
+
+	return 1;
 }
 
 static void iq80321_preinit(void)
@@ -82,6 +124,7 @@ static struct hw_pci iq80321_pci __initdata = {
 	.setup		= iq80321_setup,
 	.scan		= iop321_scan_bus,
 	.preinit	= iq80321_preinit,
+	.map_irq	= iq80321_map_irq
 };
 
 static int __init iq80321_pci_init(void)
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index a4edbe0eb..24ffa3238 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -207,7 +207,7 @@ void __init ixp4xx_init_irq(void)
 
 static unsigned volatile last_jiffy_time;
 
-#define CLOCK_TICKS_PER_USEC	(CLOCK_TICK_RATE / USEC_PER_SEC)
+#define CLOCK_TICKS_PER_USEC	((CLOCK_TICK_RATE + USEC_PER_SEC/2) / USEC_PER_SEC)
 
 /* IRQs are disabled before entering here from do_gettimeofday() */
 static unsigned long ixp4xx_gettimeoffset(void)
diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
index 9e0bf6c18..bd82bebce 100644
--- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
+++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
@@ -45,7 +45,6 @@ static struct platform_device smc91x_device = {
 	.resource	= smc91x_resources,
 };
 
-#if 0
 static struct resource lh7a40x_usbclient_resources[] = {
 	[0] = {
 		.start	= USB_PHYS,
@@ -53,8 +52,8 @@ static struct resource lh7a40x_usbclient_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_USB,
-		.end	= IRQ_USB,
+		.start	= IRQ_USBINTR,
+		.end	= IRQ_USBINTR,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -62,7 +61,7 @@ static struct resource lh7a40x_usbclient_resources[] = {
 static u64 lh7a40x_usbclient_dma_mask = 0xffffffffUL;
 
 static struct platform_device lh7a40x_usbclient_device = {
-	.name		= "lh7a40x-udc",
+	.name		= "lh7a40x_udc",
 	.id		= 0,
 	.dev		= {
 		.dma_mask = &lh7a40x_usbclient_dma_mask,
@@ -71,7 +70,6 @@ static struct platform_device lh7a40x_usbclient_device = {
 	.num_resources	= ARRAY_SIZE (lh7a40x_usbclient_resources),
 	.resource	= lh7a40x_usbclient_resources,
 };
-#endif
 
 #if defined (CONFIG_ARCH_LH7A404)
 
@@ -105,8 +103,7 @@ static struct platform_device lh7a404_usbhost_device = {
 
 static struct platform_device *lpd7a40x_devs[] __initdata = {
 	&smc91x_device,
-/*	&lh7a40x_usbclient_device, */
-
+	&lh7a40x_usbclient_device,
 #if defined (CONFIG_ARCH_LH7A404)
 	&lh7a404_usbhost_device,
 #endif
diff --git a/arch/arm/mach-lh7a40x/time.c b/arch/arm/mach-lh7a40x/time.c
index 61ada24c7..f4943cacb 100644
--- a/arch/arm/mach-lh7a40x/time.c
+++ b/arch/arm/mach-lh7a40x/time.c
@@ -22,12 +22,12 @@
 #include <asm/mach/time.h>
 
 #if HZ < 100
-# define TIMER_CONTROL	TIMER_CONTROL1
-# define TIMER_LOAD	TIMER_LOAD1
+# define TIMER_CONTROL	TIMER_CONTROL2
+# define TIMER_LOAD	TIMER_LOAD2
 # define TIMER_CONSTANT	(508469/HZ)
 # define TIMER_MODE	(TIMER_C_ENABLE | TIMER_C_PERIODIC | TIMER_C_508KHZ)
-# define TIMER_EOI	TIMER_EOI1
-# define TIMER_IRQ	IRQ_T1UI
+# define TIMER_EOI	TIMER_EOI2
+# define TIMER_IRQ	IRQ_T2UI
 #else
 # define TIMER_CONTROL	TIMER_CONTROL3
 # define TIMER_LOAD	TIMER_LOAD3
diff --git a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile
index 5fcb1e5c7..b483092dd 100644
--- a/arch/arm/mach-omap/Makefile
+++ b/arch/arm/mach-omap/Makefile
@@ -3,25 +3,29 @@
 #
 
 # Common support
-obj-y := common.o irq.o dma.o clocks.o mux.o bus.o gpio.o time.o
+obj-y := common.o time.o irq.o dma.o clocks.o mux.o gpio.o mcbsp.o
 obj-m :=
 obj-n :=
 obj-  :=
 led-y := leds.o
 
 # Specific board support
+obj-$(CONFIG_MACH_OMAP_H2) += board-h2.o
 obj-$(CONFIG_MACH_OMAP_INNOVATOR) += board-innovator.o
 obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
 obj-$(CONFIG_MACH_OMAP_PERSEUS2) += board-perseus2.o
 obj-$(CONFIG_MACH_OMAP_OSK) += board-osk.o
+obj-$(CONFIG_MACH_OMAP_H3) += board-h3.o
 
-# OCPI interconnect support for 1610 and 5912
+# OCPI interconnect support for 1710, 1610 and 5912
+obj-$(CONFIG_ARCH_OMAP1710) += ocpi.o
 obj-$(CONFIG_ARCH_OMAP1610) += ocpi.o
 obj-$(CONFIG_ARCH_OMAP5912) += ocpi.o
 
 # LEDs support
+led-$(CONFIG_MACH_OMAP_H2) += leds-h2p2-debug.o
 led-$(CONFIG_MACH_OMAP_INNOVATOR) += leds-innovator.o
-led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-perseus2.o
+led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-h2p2-debug.o
 obj-$(CONFIG_LEDS) += $(led-y)
 
 # Power Management
diff --git a/arch/arm/mach-omap/board-generic.c b/arch/arm/mach-omap/board-generic.c
index 447046b24..03da924c7 100644
--- a/arch/arm/mach-omap/board-generic.c
+++ b/arch/arm/mach-omap/board-generic.c
@@ -25,9 +25,13 @@
 #include <asm/arch/clocks.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/mux.h>
+#include <asm/arch/usb.h>
+#include <asm/arch/board.h>
 
 #include "common.h"
 
+extern void __init omap_init_time(void);
+
 static void __init omap_generic_init_irq(void)
 {
 	omap_init_irq();
@@ -36,17 +40,49 @@ static void __init omap_generic_init_irq(void)
 /*
  * Muxes the serial ports on
  */
+#ifdef CONFIG_ARCH_OMAP1510
 static void __init omap_early_serial_init(void)
 {
+#ifdef CONFIG_OMAP_LL_DEBUG_UART1
 	omap_cfg_reg(UART1_TX);
 	omap_cfg_reg(UART1_RTS);
+#endif
 
+#ifdef CONFIG_OMAP_LL_DEBUG_UART2
 	omap_cfg_reg(UART2_TX);
 	omap_cfg_reg(UART2_RTS);
+#endif
 
+#ifdef CONFIG_OMAP_LL_DEBUG_UART1
 	omap_cfg_reg(UART3_TX);
 	omap_cfg_reg(UART3_RX);
+#endif
 }
+#endif
+
+/* assume no Mini-AB port */
+
+#ifdef CONFIG_ARCH_OMAP1510
+static struct omap_usb_config generic1510_usb_config __initdata = {
+	.register_host	= 1,
+	.register_dev	= 1,
+	.hmc_mode	= 16,
+	.pins[0]	= 3,
+};
+#endif
+
+#ifdef CONFIG_ARCH_OMAP1610
+static struct omap_usb_config generic1610_usb_config __initdata = {
+	.register_host	= 1,
+	.register_dev	= 1,
+	.hmc_mode	= 16,
+	.pins[0]	= 6,
+};
+#endif
+
+static struct omap_board_config_kernel generic_config[] = {
+	{ OMAP_TAG_USB,           NULL },
+};
 
 static void __init omap_generic_init(void)
 {
@@ -55,9 +91,19 @@ static void __init omap_generic_init(void)
 	 * You have to mux them off in device drivers later on
 	 * if not needed.
 	 */
+#ifdef CONFIG_ARCH_OMAP1510
 	if (cpu_is_omap1510()) {
 		omap_early_serial_init();
+		generic_config[0].data = &generic1510_usb_config;
 	}
+#endif
+#ifdef CONFIG_ARCH_OMAP1610
+	if (!cpu_is_omap1510()) {
+		generic_config[0].data = &generic1610_usb_config;
+	}
+#endif
+	omap_board_config = generic_config;
+	omap_board_config_size = ARRAY_SIZE(generic_config);
 }
 
 static void __init omap_generic_map_io(void)
@@ -65,18 +111,12 @@ static void __init omap_generic_map_io(void)
 	omap_map_io();
 }
 
-static void __init omap_generic_init_time(void)
-{
-	omap_init_time();
-}
-
-MACHINE_START(OMAP_GENERIC, "Generic OMAP-1510/1610/1710")
+MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
 	MAINTAINER("Tony Lindgren <tony@atomide.com>")
 	BOOT_MEM(0x10000000, 0xfff00000, 0xfef00000)
 	BOOT_PARAMS(0x10000100)
 	MAPIO(omap_generic_map_io)
 	INITIRQ(omap_generic_init_irq)
 	INIT_MACHINE(omap_generic_init)
-	INITTIME(omap_generic_init_time)
+	INITTIME(omap_init_time)
 MACHINE_END
-
diff --git a/arch/arm/mach-omap/board-innovator.c b/arch/arm/mach-omap/board-innovator.c
index 6ef4d8dcf..8fd97e7af 100644
--- a/arch/arm/mach-omap/board-innovator.c
+++ b/arch/arm/mach-omap/board-innovator.c
@@ -29,9 +29,12 @@
 #include <asm/arch/clocks.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/fpga.h>
+#include <asm/arch/usb.h>
 
 #include "common.h"
 
+extern void __init omap_init_time(void);
+
 #ifdef CONFIG_ARCH_OMAP1510
 
 extern int omap_gpio_init(void);
@@ -49,8 +52,8 @@ static struct resource innovator1510_smc91x_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= INT_ETHER,
-		.end	= INT_ETHER,
+		.start	= OMAP1510_INT_ETHER,
+		.end	= OMAP1510_INT_ETHER,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -108,11 +111,43 @@ void innovator_init_irq(void)
 #ifdef CONFIG_ARCH_OMAP1510
 	if (cpu_is_omap1510()) {
 		omap_gpio_init();
-		fpga_init_irq();
+		omap1510_fpga_init_irq();
 	}
 #endif
 }
 
+#ifdef CONFIG_ARCH_OMAP1510
+static struct omap_usb_config innovator1510_usb_config __initdata = {
+	/* has usb host and device, but no Mini-AB port */
+	.register_host	= 1,
+	.register_dev	= 1,
+	/* Assume bad Innovator wiring; Use internal host only with custom cable */
+	.hmc_mode	= 16,
+	.pins[0]	= 2,
+};
+#endif
+
+#ifdef CONFIG_ARCH_OMAP1610
+static struct omap_usb_config h2_usb_config __initdata = {
+	/* usb1 has a Mini-AB port and external isp1301 transceiver */
+	.otg		= 2,
+
+#ifdef	CONFIG_USB_GADGET_OMAP
+	.hmc_mode	= 19,	// 0:host(off) 1:dev|otg 2:disabled
+	// .hmc_mode	= 21,	// 0:host(off) 1:dev(loopback) 2:host(loopback)
+#elif	defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+	/* NONSTANDARD CABLE NEEDED (B-to-Mini-B) */
+	.hmc_mode	= 20,	// 1:dev|otg(off) 1:host 2:disabled
+#endif
+
+	.pins[1]	= 3,
+};
+#endif
+
+static struct omap_board_config_kernel innovator_config[] = {
+	{ OMAP_TAG_USB,         NULL },
+};
+
 static void __init innovator_init(void)
 {
 #ifdef CONFIG_ARCH_OMAP1510
@@ -121,10 +156,21 @@ static void __init innovator_init(void)
 	}
 #endif
 #ifdef CONFIG_ARCH_OMAP1610
-	if (cpu_is_omap1610()) {
+	if (!cpu_is_omap1510()) {
 		platform_add_devices(innovator1610_devices, ARRAY_SIZE(innovator1610_devices));
 	}
 #endif
+
+#ifdef CONFIG_ARCH_OMAP1510
+	if (cpu_is_omap1510())
+		innovator_config[0].data = &innovator1510_usb_config;
+#endif
+#ifdef CONFIG_ARCH_OMAP1610
+	if (cpu_is_omap1610())
+		innovator_config[0].data = &h2_usb_config;
+#endif
+	omap_board_config = innovator_config;
+	omap_board_config_size = ARRAY_SIZE(innovator_config);
 }
 
 static void __init innovator_map_io(void)
@@ -144,7 +190,7 @@ static void __init innovator_map_io(void)
 	}
 #endif
 #ifdef CONFIG_ARCH_OMAP1610
-	if (cpu_is_omap1610()) {
+	if (!cpu_is_omap1510()) {
 		iotable_init(innovator1610_io_desc, ARRAY_SIZE(innovator1610_io_desc));
 	}
 #endif
@@ -156,6 +202,6 @@ MACHINE_START(OMAP_INNOVATOR, "TI-Innovator")
 	BOOT_PARAMS(0x10000100)
 	MAPIO(innovator_map_io)
 	INITIRQ(innovator_init_irq)
-	INITTIME(omap_init_time)
 	INIT_MACHINE(innovator_init)
+	INITTIME(omap_init_time)
 MACHINE_END
diff --git a/arch/arm/mach-omap/board-osk.c b/arch/arm/mach-omap/board-osk.c
index 16ecd6be5..85d9a0ac3 100644
--- a/arch/arm/mach-omap/board-osk.c
+++ b/arch/arm/mach-omap/board-osk.c
@@ -41,6 +41,8 @@
 
 #include "common.h"
 
+extern void __init omap_init_time(void);
+
 static struct map_desc osk5912_io_desc[] __initdata = {
 { OMAP_OSK_ETHR_BASE, OMAP_OSK_ETHR_START, OMAP_OSK_ETHR_SIZE,MT_DEVICE },
 { OMAP_OSK_NOR_FLASH_BASE, OMAP_OSK_NOR_FLASH_START, OMAP_OSK_NOR_FLASH_SIZE,
@@ -94,6 +96,6 @@ MACHINE_START(OMAP_OSK, "TI-OSK")
 	BOOT_PARAMS(0x10000100)
 	MAPIO(osk_map_io)
 	INITIRQ(osk_init_irq)
-	INITTIME(omap_init_time)
 	INIT_MACHINE(osk_init)
+	INITTIME(omap_init_time)
 MACHINE_END
diff --git a/arch/arm/mach-omap/board-perseus2.c b/arch/arm/mach-omap/board-perseus2.c
index 8015d10fc..95833f3b9 100644
--- a/arch/arm/mach-omap/board-perseus2.c
+++ b/arch/arm/mach-omap/board-perseus2.c
@@ -23,9 +23,12 @@
 #include <asm/arch/clocks.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/mux.h>
+#include <asm/arch/fpga.h>
 
 #include "common.h"
 
+extern void __init omap_init_time(void);
+
 void omap_perseus2_init_irq(void)
 {
 	omap_init_irq();
@@ -33,14 +36,14 @@ void omap_perseus2_init_irq(void)
 
 static struct resource smc91x_resources[] = {
 	[0] = {
-		.start	= OMAP730_FPGA_ETHR_START,	/* Physical */
-		.end	= OMAP730_FPGA_ETHR_START + SZ_4K,
+		.start	= H2P2_DBG_FPGA_ETHR_START,	/* Physical */
+		.end	= H2P2_DBG_FPGA_ETHR_START + SZ_4K,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= 0,
+		.start	= INT_730_MPU_EXT_NIRQ,
 		.end	= 0,
-		.flags	= INT_ETHER,
+		.flags	= IORESOURCE_IRQ,
 	},
 };
 
@@ -62,7 +65,7 @@ static void __init omap_perseus2_init(void)
 
 /* Only FPGA needs to be mapped here. All others are done with ioremap */
 static struct map_desc omap_perseus2_io_desc[] __initdata = {
-	{OMAP730_FPGA_BASE, OMAP730_FPGA_START, OMAP730_FPGA_SIZE,
+	{H2P2_DBG_FPGA_BASE, H2P2_DBG_FPGA_START, H2P2_DBG_FPGA_SIZE,
 	 MT_DEVICE},
 };
 
@@ -111,6 +114,6 @@ MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2")
 	BOOT_PARAMS(0x10000100)
 	MAPIO(omap_perseus2_map_io)
 	INITIRQ(omap_perseus2_init_irq)
-	INITTIME(omap_init_time)
 	INIT_MACHINE(omap_perseus2_init)
+	INITTIME(omap_init_time)
 MACHINE_END
diff --git a/arch/arm/mach-omap/clocks.c b/arch/arm/mach-omap/clocks.c
index bda7c6f38..b50785659 100644
--- a/arch/arm/mach-omap/clocks.c
+++ b/arch/arm/mach-omap/clocks.c
@@ -36,6 +36,8 @@
 #include <asm/arch/clocks.h>
 #include <asm/arch/board.h>
 
+extern void start_mputimer1(unsigned long load_val);
+
 /* Input clock in MHz */
 static unsigned int source_clock = 12;
 
@@ -239,7 +241,7 @@ int ck_auto_unclock = 1;
 int ck_debug = 0;
 
 #define CK_MAX_PLL_FREQ		OMAP_CK_MAX_RATE
-static __u8 ck_valid_table[CK_MAX_PLL_FREQ / 8 + 1];
+static __u32 ck_valid_table[CK_MAX_PLL_FREQ / 32 + 1];
 static __u8 ck_lookup_table[CK_MAX_PLL_FREQ];
 
 int
@@ -615,11 +617,11 @@ __ck_make_lookup_table(void)
 int __init
 init_ck(void)
 {
-	const struct omap_clock_info *info;
+	const struct omap_clock_config *info;
 	int crystal_type = 0; /* Default 12 MHz */
 
 	__ck_make_lookup_table();
-	info = omap_get_per_info(OMAP_TAG_CLOCK, struct omap_clock_info);
+	info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
 	if (info != NULL) {
 		if (!cpu_is_omap1510())
 			crystal_type = info->system_clock_type;
@@ -645,7 +647,8 @@ init_ck(void)
 #elif defined(CONFIG_OMAP_ARM_182MHZ) && defined(CONFIG_ARCH_OMAP730)
 	omap_writew(0x250E, ARM_CKCTL);
 	omap_writew(0x2710, DPLL_CTL);
-#elif defined(CONFIG_OMAP_ARM_192MHZ) && (defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912))
+#elif defined(CONFIG_OMAP_ARM_192MHZ) && (defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) \
+					  || defined(CONFIG_ARCH_OMAP1710))
 	omap_writew(0x150f, ARM_CKCTL);
 	if (crystal_type == 2) {
 		source_clock = 13;	/* MHz */
diff --git a/arch/arm/mach-omap/common.c b/arch/arm/mach-omap/common.c
index 43aaa1c6c..17d82a7f3 100644
--- a/arch/arm/mach-omap/common.c
+++ b/arch/arm/mach-omap/common.c
@@ -104,7 +104,7 @@ static struct map_desc omap1510_io_desc[] __initdata = {
 };
 #endif
 
-#ifdef CONFIG_ARCH_OMAP1610
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
 static struct map_desc omap1610_io_desc[] __initdata = {
  { OMAP1610_DSP_BASE,    OMAP1610_DSP_START,    OMAP1610_DSP_SIZE,    MT_DEVICE },
  { OMAP1610_DSPREG_BASE, OMAP1610_DSPREG_START, OMAP1610_DSPREG_SIZE, MT_DEVICE },
@@ -147,8 +147,8 @@ static void __init _omap_map_io(void)
 		iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc));
 	}
 #endif
-#ifdef CONFIG_ARCH_OMAP1610
-	if (cpu_is_omap1610()) {
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
+	if (cpu_is_omap1610() || cpu_is_omap1710()) {
 		iotable_init(omap1610_io_desc, ARRAY_SIZE(omap1610_io_desc));
 	}
 #endif
@@ -181,13 +181,18 @@ void omap_map_io(void)
 extern int omap_bootloader_tag_len;
 extern u8 omap_bootloader_tag[];
 
-const void *__omap_get_per_info(u16 tag, size_t len)
+struct omap_board_config_kernel *omap_board_config;
+int omap_board_config_size = 0;
+
+const void *__omap_get_config(u16 tag, size_t len)
 {
-	struct omap_board_info_entry *info = NULL;
+	struct omap_board_config_entry *info = NULL;
+	struct omap_board_config_kernel *kinfo = NULL;
+	int i;
 
 #ifdef CONFIG_OMAP_BOOT_TAG
 	if (omap_bootloader_tag_len > 4)
-		info = (struct omap_board_info_entry *) omap_bootloader_tag;
+		info = (struct omap_board_config_entry *) omap_bootloader_tag;
 	while (info != NULL) {
 		u8 *next;
 
@@ -198,26 +203,38 @@ const void *__omap_get_per_info(u16 tag, size_t len)
 		if (next >= omap_bootloader_tag + omap_bootloader_tag_len)
 			info = NULL;
 		else
-			info = (struct omap_board_info_entry *) next;
+			info = (struct omap_board_config_entry *) next;
+	}
+	if (info != NULL) {
+		/* Check the length as a lame attempt to check for
+		 * binary inconsistancy. */
+		if (info->len != len) {
+			printk(KERN_ERR "OMAP peripheral config: Length mismatch with tag %x (want %d, got %d)\n",
+			       tag, len, info->len);
+			return NULL;
+		}
+		return info->data;
 	}
 #endif
-	if (info == NULL)
-		return NULL;
-	if (info->len != len) {
-		printk(KERN_ERR "OMAP per_info: Length mismatch with tag %x (want %d, got %d)\n",
-		       tag, len, info->len);
-		return NULL;
+	/* Try to find the config from the board-specific structures
+	 * in the kernel. */
+	for (i = 0; i < omap_board_config_size; i++) {
+		if (omap_board_config[i].tag == tag) {
+			kinfo = &omap_board_config[i];
+			break;
+		}
 	}
-
-	return info->data;
+	if (kinfo == NULL)
+		return NULL;
+	return kinfo->data;
 }
-EXPORT_SYMBOL(__omap_get_per_info);
+EXPORT_SYMBOL(__omap_get_config);
 
 static int __init omap_add_serial_console(void)
 {
-	const struct omap_uart_info *info;
+	const struct omap_uart_config *info;
 
-	info = omap_get_per_info(OMAP_TAG_UART, struct omap_uart_info);
+	info = omap_get_config(OMAP_TAG_UART, struct omap_uart_config);
 	if (info != NULL && info->console_uart) {
 		static char speed[11], *opt = NULL;
 
diff --git a/arch/arm/mach-omap/common.h b/arch/arm/mach-omap/common.h
index 96dcb3c53..1cc559dd2 100644
--- a/arch/arm/mach-omap/common.h
+++ b/arch/arm/mach-omap/common.h
@@ -28,7 +28,6 @@
 #define __ARCH_ARM_MACH_OMAP_COMMON_H
 
 extern void omap_map_io(void);
-extern void omap_init_time(void);
 
 #endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */
 
diff --git a/arch/arm/mach-omap/dma.c b/arch/arm/mach-omap/dma.c
index 385b4d1cc..cfb23d894 100644
--- a/arch/arm/mach-omap/dma.c
+++ b/arch/arm/mach-omap/dma.c
@@ -118,7 +118,7 @@ void omap_set_dma_constant_fill(int lch, u32 color)
 	u16 w;
 
 #ifdef CONFIG_DEBUG_KERNEL
-	if (omap_dma_in_1510_mode) {
+	if (omap_dma_in_1510_mode()) {
 		printk(KERN_ERR "OMAP DMA constant fill not available in 1510 mode.");
 		BUG();
 		return;
@@ -141,7 +141,7 @@ void omap_set_dma_transparent_copy(int lch, u32 color)
 	u16 w;
 
 #ifdef CONFIG_DEBUG_KERNEL
-	if (omap_dma_in_1510_mode) {
+	if (omap_dma_in_1510_mode()) {
 		printk(KERN_ERR "OMAP DMA transparent copy not available in 1510 mode.");
 		BUG();
 	}
@@ -266,46 +266,78 @@ void omap_set_dma_dest_burst_mode(int lch, int burst_mode)
 	omap_writew(w, OMAP_DMA_CSDP(lch));
 }
 
-void omap_start_dma(int lch)
+static inline void init_intr(int lch)
 {
 	u16 w;
 
-	if (!omap_dma_in_1510_mode()) {
-		int next_lch;
-
-		next_lch = dma_chan[lch].next_lch;
-
-		/* Enable the queue, if needed so. */
-		if (next_lch != -1) {
-			/* Clear the STOP_LNK bits */
-			w = omap_readw(OMAP_DMA_CLNK_CTRL(lch));
-			w &= ~(1 << 14);
-			omap_writew(w, OMAP_DMA_CLNK_CTRL(lch));
-			w = omap_readw(OMAP_DMA_CLNK_CTRL(next_lch));
-			w &= ~(1 << 14);
-			omap_writew(w, OMAP_DMA_CLNK_CTRL(next_lch));
-
-			/* And set the ENABLE_LNK bits */
-			omap_writew(next_lch | (1 << 15),
-				    OMAP_DMA_CLNK_CTRL(lch));
-			/* The loop case */
-			if (dma_chan[next_lch].next_lch == lch)
-				omap_writew(lch | (1 << 15),
-					    OMAP_DMA_CLNK_CTRL(next_lch));
-
-			/* Read CSR to make sure it's cleared. */
-			w = omap_readw(OMAP_DMA_CSR(next_lch));
-			/* Enable some nice interrupts. */
-			omap_writew(dma_chan[next_lch].enabled_irqs,
-				    OMAP_DMA_CICR(next_lch));
-			dma_chan[next_lch].flags |= OMAP_DMA_ACTIVE;
-		}
-	}
-
 	/* Read CSR to make sure it's cleared. */
 	w = omap_readw(OMAP_DMA_CSR(lch));
 	/* Enable some nice interrupts. */
 	omap_writew(dma_chan[lch].enabled_irqs, OMAP_DMA_CICR(lch));
+	dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
+}
+
+static inline void enable_lnk(int lch)
+{
+	u16 w;
+
+	/* Clear the STOP_LNK bits */
+	w = omap_readw(OMAP_DMA_CLNK_CTRL(lch));
+	w &= ~(1 << 14);
+	omap_writew(w, OMAP_DMA_CLNK_CTRL(lch));
+
+	/* And set the ENABLE_LNK bits */
+	if (dma_chan[lch].next_lch != -1)
+		omap_writew(dma_chan[lch].next_lch | (1 << 15),
+			    OMAP_DMA_CLNK_CTRL(lch));
+}
+
+static inline void disable_lnk(int lch)
+{
+	u16 w;
+
+	/* Disable interrupts */
+	omap_writew(0, OMAP_DMA_CICR(lch));
+
+	/* Set the STOP_LNK bit */
+	w = omap_readw(OMAP_DMA_CLNK_CTRL(lch));
+	w |= (1 << 14);
+	w = omap_writew(w, OMAP_DMA_CLNK_CTRL(lch));
+
+	dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
+}
+
+void omap_start_dma(int lch)
+{
+	u16 w;
+
+	if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
+		int next_lch, cur_lch;
+		char dma_chan_link_map[OMAP_LOGICAL_DMA_CH_COUNT];
+
+		dma_chan_link_map[lch] = 1;
+		/* Set the link register of the first channel */
+		enable_lnk(lch);
+
+		memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map));
+		cur_lch = dma_chan[lch].next_lch;
+		do {
+			next_lch = dma_chan[cur_lch].next_lch;
+
+                        /* The loop case: we've been here already */
+			if (dma_chan_link_map[cur_lch])
+				break;
+			/* Mark the current channel */
+			dma_chan_link_map[cur_lch] = 1;
+
+			enable_lnk(cur_lch);
+			init_intr(cur_lch);
+
+			cur_lch = next_lch;
+		} while (next_lch != -1);
+	}
+
+	init_intr(lch);
 
 	w = omap_readw(OMAP_DMA_CCR(lch));
 	w |= OMAP_DMA_CCR_EN;
@@ -316,37 +348,34 @@ void omap_start_dma(int lch)
 void omap_stop_dma(int lch)
 {
 	u16 w;
-	int next_lch;
 
-	/* Disable all interrupts on the channel */
-	omap_writew(0, OMAP_DMA_CICR(lch));
+	if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
+		int next_lch, cur_lch = lch;
+		char dma_chan_link_map[OMAP_LOGICAL_DMA_CH_COUNT];
 
-	if (omap_dma_in_1510_mode()) {
-		w = omap_readw(OMAP_DMA_CCR(lch));
-		w &= ~OMAP_DMA_CCR_EN;
-		omap_writew(w, OMAP_DMA_CCR(lch));
-		dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
-		return;
-	}
+		memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map));
+		do {
+			/* The loop case: we've been here already */
+			if (dma_chan_link_map[cur_lch])
+				break;
+			/* Mark the current channel */
+			dma_chan_link_map[cur_lch] = 1;
 
-	next_lch = dma_chan[lch].next_lch;
+			disable_lnk(cur_lch);
 
-	/*
-	 * According to thw HW spec, enabling the STOP_LNK bit
-	 * resets the CCR_EN bit at the same time.
-	 */
-	w = omap_readw(OMAP_DMA_CLNK_CTRL(lch));
-	w |= (1 << 14);
-	w = omap_writew(w, OMAP_DMA_CLNK_CTRL(lch));
-	dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
+			next_lch = dma_chan[cur_lch].next_lch;
+			cur_lch = next_lch;
+		} while (next_lch != -1);
 
-	if (next_lch != -1) {
-		omap_writew(0, OMAP_DMA_CICR(next_lch));
-		w = omap_readw(OMAP_DMA_CLNK_CTRL(next_lch));
-		w |= (1 << 14);
-		w = omap_writew(w, OMAP_DMA_CLNK_CTRL(next_lch));
-		dma_chan[next_lch].flags &= ~OMAP_DMA_ACTIVE;
+		return;
 	}
+	/* Disable all interrupts on the channel */
+	omap_writew(0, OMAP_DMA_CICR(lch));
+
+	w = omap_readw(OMAP_DMA_CCR(lch));
+	w &= ~OMAP_DMA_CCR_EN;
+	omap_writew(w, OMAP_DMA_CCR(lch));
+	dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
 }
 
 void omap_enable_dma_irq(int lch, u16 bits)
@@ -445,7 +474,7 @@ int omap_request_dma(int dev_id, const char *dev_name,
 	chan->data = data;
 	chan->enabled_irqs = OMAP_DMA_TOUT_IRQ | OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;
 
-	if (cpu_is_omap1610() || cpu_is_omap5912()) {
+	if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap730() || cpu_is_omap1710()) {
 		/* If the sync device is set, configure it dynamically. */
 		if (dev_id != 0) {
 			set_gdma_dev(free_ch + 1, dev_id);
@@ -533,7 +562,6 @@ void omap_dma_unlink_lch (int lch_head, int lch_queue)
 	}
 
 	dma_chan[lch_head].next_lch = -1;
-	dma_chan[lch_queue].next_lch = -1;
 }
 
 
@@ -713,7 +741,7 @@ static int __init omap_init_dma(void)
 		printk(KERN_INFO "DMA support for OMAP1510 initialized\n");
 		dma_chan_count = 9;
 		enable_1510_mode = 1;
-	} else if (cpu_is_omap1610() || cpu_is_omap5912()) {
+	} else if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap730() || cpu_is_omap1710()) {
 		printk(KERN_INFO "OMAP DMA hardware version %d\n",
 		       omap_readw(OMAP_DMA_HW_ID));
 		printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n",
@@ -771,6 +799,8 @@ EXPORT_SYMBOL(omap_request_dma);
 EXPORT_SYMBOL(omap_free_dma);
 EXPORT_SYMBOL(omap_start_dma);
 EXPORT_SYMBOL(omap_stop_dma);
+EXPORT_SYMBOL(omap_enable_dma_irq);
+EXPORT_SYMBOL(omap_disable_dma_irq);
 
 EXPORT_SYMBOL(omap_set_dma_transfer_params);
 EXPORT_SYMBOL(omap_set_dma_constant_fill);
diff --git a/arch/arm/mach-omap/fpga.c b/arch/arm/mach-omap/fpga.c
index d9246b1dc..f0ce5c12a 100644
--- a/arch/arm/mach-omap/fpga.c
+++ b/arch/arm/mach-omap/fpga.c
@@ -31,19 +31,9 @@
 #include <asm/arch/fpga.h>
 #include <asm/arch/gpio.h>
 
-unsigned char fpga_read(int reg)
-{
-	return __raw_readb(reg);
-}
-
-void fpga_write(unsigned char val, int reg)
-{
-	__raw_writeb(val, reg);
-}
-
 static void fpga_mask_irq(unsigned int irq)
 {
-	irq -= IH_FPGA_BASE;
+	irq -= OMAP1510_IH_FPGA_BASE;
 
 	if (irq < 8)
 		__raw_writeb((__raw_readb(OMAP1510_FPGA_IMR_LO)
@@ -76,7 +66,7 @@ static void fpga_ack_irq(unsigned int irq)
 
 static void fpga_unmask_irq(unsigned int irq)
 {
-	irq -= IH_FPGA_BASE;
+	irq -= OMAP1510_IH_FPGA_BASE;
 
 	if (irq < 8)
 		__raw_writeb((__raw_readb(OMAP1510_FPGA_IMR_LO) | (1 << irq)),
@@ -114,8 +104,8 @@ void innovator_fpga_IRQ_demux(unsigned int irq, struct irqdesc *desc,
 			break;
 		}
 
-		for (fpga_irq = IH_FPGA_BASE;
-			(fpga_irq < (IH_FPGA_BASE + NR_FPGA_IRQS)) && stat;
+		for (fpga_irq = OMAP1510_IH_FPGA_BASE;
+			(fpga_irq < (OMAP1510_IH_FPGA_BASE + NR_FPGA_IRQS)) && stat;
 			fpga_irq++, stat >>= 1) {
 			if (stat & 1) {
 				d = irq_desc + fpga_irq;
@@ -162,7 +152,7 @@ static struct irqchip omap_fpga_irq = {
  * interrupts at the interrupt controller via disable_irq/enable_irq
  * could pose a problem.
  */
-void fpga_init_irq(void)
+void omap1510_fpga_init_irq(void)
 {
 	int i;
 
@@ -170,9 +160,9 @@ void fpga_init_irq(void)
 	__raw_writeb(0, OMAP1510_FPGA_IMR_HI);
 	__raw_writeb(0, INNOVATOR_FPGA_IMR2);
 
-	for (i = IH_FPGA_BASE; i < (IH_FPGA_BASE + NR_FPGA_IRQS); i++) {
+	for (i = OMAP1510_IH_FPGA_BASE; i < (OMAP1510_IH_FPGA_BASE + NR_FPGA_IRQS); i++) {
 
-		if (i == INT_FPGA_TS) {
+		if (i == OMAP1510_INT_FPGA_TS) {
 			/*
 			 * The touchscreen interrupt is level-sensitive, so
 			 * we'll use the regular mask_ack routine for it.
@@ -201,9 +191,7 @@ void fpga_init_irq(void)
 	omap_request_gpio(13);
 	omap_set_gpio_direction(13, 1);
 	omap_set_gpio_edge_ctrl(13, OMAP_GPIO_RISING_EDGE);
-	set_irq_chained_handler(INT_FPGA, innovator_fpga_IRQ_demux);
+	set_irq_chained_handler(OMAP1510_INT_FPGA, innovator_fpga_IRQ_demux);
 }
 
-EXPORT_SYMBOL(fpga_init_irq);
-EXPORT_SYMBOL(fpga_read);
-EXPORT_SYMBOL(fpga_write);
+EXPORT_SYMBOL(omap1510_fpga_init_irq);
diff --git a/arch/arm/mach-omap/gpio.c b/arch/arm/mach-omap/gpio.c
index 2f052a959..206bee968 100644
--- a/arch/arm/mach-omap/gpio.c
+++ b/arch/arm/mach-omap/gpio.c
@@ -94,7 +94,7 @@ struct gpio_bank {
 #define METHOD_GPIO_1610	2
 #define METHOD_GPIO_730		3
 
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
 static struct gpio_bank gpio_bank_1610[5] = {
 	{ OMAP_MPUIO_BASE,     INT_MPUIO,	    IH_MPUIO_BASE,     METHOD_MPUIO},
 	{ OMAP1610_GPIO1_BASE, INT_GPIO_BANK1,	    IH_GPIO_BASE,      METHOD_GPIO_1610 },
@@ -113,7 +113,7 @@ static struct gpio_bank gpio_bank_1510[2] = {
 
 #ifdef CONFIG_ARCH_OMAP730
 static struct gpio_bank gpio_bank_730[7] = {
-	{ OMAP_MPUIO_BASE,     INT_MPUIO,	    IH_MPUIO_BASE,	METHOD_MPUIO },
+	{ OMAP_MPUIO_BASE,     INT_730_MPUIO,	    IH_MPUIO_BASE,	METHOD_MPUIO },
 	{ OMAP730_GPIO1_BASE,  INT_GPIO_BANK1,	    IH_GPIO_BASE,	METHOD_GPIO_730 },
 	{ OMAP730_GPIO2_BASE,  INT_730_GPIO_BANK2,  IH_GPIO_BASE + 32,	METHOD_GPIO_730 },
 	{ OMAP730_GPIO3_BASE,  INT_730_GPIO_BANK3,  IH_GPIO_BASE + 64,	METHOD_GPIO_730 },
@@ -135,8 +135,8 @@ static inline struct gpio_bank *get_gpio_bank(int gpio)
 		return &gpio_bank[1];
 	}
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
-	if (cpu_is_omap1610() || cpu_is_omap5912()) {
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
+	if (cpu_is_omap1610() || cpu_is_omap1710() || cpu_is_omap5912()) {
 		if (OMAP_GPIO_IS_MPUIO(gpio))
 			return &gpio_bank[0];
 		return &gpio_bank[1 + (gpio >> 4)];
@@ -172,8 +172,8 @@ static inline int gpio_valid(int gpio)
 	if (cpu_is_omap1510() && gpio < 16)
 		return 0;
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
-	if ((cpu_is_omap1610() || cpu_is_omap5912()) && gpio < 64)
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
+	if ((cpu_is_omap1610() || cpu_is_omap1710() || cpu_is_omap5912()) && gpio < 64)
 		return 0;
 #endif
 #ifdef CONFIG_ARCH_OMAP730
@@ -554,7 +554,7 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
 	if (bank->method == METHOD_GPIO_1510)
 		isr_reg = bank->base + OMAP1510_GPIO_INT_STATUS;
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
 	if (bank->method == METHOD_GPIO_1610)
 		isr_reg = bank->base + OMAP1610_GPIO_IRQSTATUS1;
 #endif
@@ -588,7 +588,7 @@ static void gpio_ack_irq(unsigned int irq)
 	if (bank->method == METHOD_GPIO_1510)
 		__raw_writew(1 << (gpio & 0x0f), bank->base + OMAP1510_GPIO_INT_STATUS);
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
 	if (bank->method == METHOD_GPIO_1610)
 		__raw_writew(1 << (gpio & 0x0f), bank->base + OMAP1610_GPIO_IRQSTATUS1);
 #endif
@@ -629,7 +629,7 @@ static void mpuio_mask_irq(unsigned int irq)
 	unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
 	struct gpio_bank *bank = get_gpio_bank(gpio);
 
-	_set_gpio_irqenable(bank, gpio, 0);
+	_set_gpio_irqenable(bank, get_gpio_index(gpio), 0);
 }
 
 static void mpuio_unmask_irq(unsigned int irq)
@@ -637,7 +637,7 @@ static void mpuio_unmask_irq(unsigned int irq)
 	unsigned int gpio = OMAP_MPUIO(irq - IH_MPUIO_BASE);
 	struct gpio_bank *bank = get_gpio_bank(gpio);
 
-	_set_gpio_irqenable(bank, gpio, 1);
+	_set_gpio_irqenable(bank, get_gpio_index(gpio), 1);
 }
 
 static struct irqchip gpio_irq_chip = {
@@ -668,8 +668,8 @@ static int __init _omap_gpio_init(void)
 		gpio_bank = gpio_bank_1510;
 	}
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
-	if (cpu_is_omap1610() || cpu_is_omap5912()) {
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
+	if (cpu_is_omap1610() || cpu_is_omap1710() || cpu_is_omap5912()) {
 		int rev;
 
 		gpio_bank_count = 5;
@@ -702,7 +702,7 @@ static int __init _omap_gpio_init(void)
 			__raw_writew(0x0000, bank->base + OMAP1510_GPIO_INT_STATUS);
 		}
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710) || defined(CONFIG_ARCH_OMAP5912)
 		if (bank->method == METHOD_GPIO_1610) {
 			__raw_writew(0x0000, bank->base + OMAP1610_GPIO_IRQENABLE1);
 			__raw_writew(0xffff, bank->base + OMAP1610_GPIO_IRQSTATUS1);
@@ -731,7 +731,7 @@ static int __init _omap_gpio_init(void)
 
 	/* Enable system clock for GPIO module.
 	 * The CAM_CLK_CTRL *is* really the right place. */
-	if (cpu_is_omap1610())
+	if (cpu_is_omap1610() || cpu_is_omap1710())
 		omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, ULPD_CAM_CLK_CTRL);
 
 	return 0;
diff --git a/arch/arm/mach-omap/irq.c b/arch/arm/mach-omap/irq.c
index 18da117f6..3eec2986b 100644
--- a/arch/arm/mach-omap/irq.c
+++ b/arch/arm/mach-omap/irq.c
@@ -140,7 +140,9 @@ static struct omap_irq_bank omap1510_irq_banks[] = {
 };
 #endif
 
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) \
+				  || defined(CONFIG_ARCH_OMAP1710)
+
 static struct omap_irq_bank omap1610_irq_banks[] = {
 	{ .base_reg = OMAP_IH1_BASE, 		.trigger_map = 0xb3fefe8f },
 	{ .base_reg = OMAP_IH2_BASE, 		.trigger_map = 0xfffff7ff },
@@ -171,8 +173,9 @@ void __init omap_init_irq(void)
 		irq_bank_count = ARRAY_SIZE(omap1510_irq_banks);
 	}
 #endif
-#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912)
-	if (cpu_is_omap1610() || cpu_is_omap5912()) {
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP5912) \
+				  || defined(CONFIG_ARCH_OMAP1710)
+	if (cpu_is_omap1610() || cpu_is_omap5912() || cpu_is_omap1710()) {
 		irq_banks = omap1610_irq_banks;
 		irq_bank_count = ARRAY_SIZE(omap1610_irq_banks);
 	}
@@ -190,6 +193,11 @@ void __init omap_init_irq(void)
 	irq_bank_writel(0x03, 0, IRQ_CONTROL_REG_OFFSET);
 	irq_bank_writel(0x03, 1, IRQ_CONTROL_REG_OFFSET);
 
+	/* Enable interrupts in global mask */
+	if (cpu_is_omap730()) {
+		irq_bank_writel(0x0, 0, IRQ_GMR_REG_OFFSET);
+	}
+
 	/* Install the interrupt handlers for each bank */
 	for (i = 0; i < irq_bank_count; i++) {
 		for (j = i * 32; j < (i + 1) * 32; j++) {
@@ -205,5 +213,9 @@ void __init omap_init_irq(void)
 	}
 
 	/* Unmask level 2 handler */
-	omap_unmask_irq(INT_IH2_IRQ);
+	if (cpu_is_omap730()) {
+		omap_unmask_irq(INT_730_IH2_IRQ);
+	} else {
+		omap_unmask_irq(INT_IH2_IRQ);
+	}
 }
diff --git a/arch/arm/mach-omap/leds.c b/arch/arm/mach-omap/leds.c
index e3f378b4a..b6d0c7203 100644
--- a/arch/arm/mach-omap/leds.c
+++ b/arch/arm/mach-omap/leds.c
@@ -3,6 +3,7 @@
  *
  * OMAP LEDs dispatcher
  */
+#include <linux/kernel.h>
 #include <linux/init.h>
 
 #include <asm/leds.h>
@@ -11,17 +12,17 @@
 #include "leds.h"
 
 static int __init
-omap1510_leds_init(void)
+omap_leds_init(void)
 {
 	if (machine_is_omap_innovator())
 		leds_event = innovator_leds_event;
 
-	else if (machine_is_omap_perseus2()) {
-		leds_event = perseus2_leds_event;
+	else if (machine_is_omap_h2() || machine_is_omap_perseus2()) {
+		leds_event = h2p2_dbg_leds_event;
 	}
 
 	leds_event(led_start);
 	return 0;
 }
 
-__initcall(omap1510_leds_init);
+__initcall(omap_leds_init);
diff --git a/arch/arm/mach-omap/leds.h b/arch/arm/mach-omap/leds.h
index ba2eb59d1..7571e2d63 100644
--- a/arch/arm/mach-omap/leds.h
+++ b/arch/arm/mach-omap/leds.h
@@ -1,2 +1,2 @@
 extern void innovator_leds_event(led_event_t evt);
-extern void perseus2_leds_event(led_event_t evt);
+extern void h2p2_dbg_leds_event(led_event_t evt);
diff --git a/arch/arm/mach-omap/ocpi.c b/arch/arm/mach-omap/ocpi.c
index 944c29418..93c7f4aca 100644
--- a/arch/arm/mach-omap/ocpi.c
+++ b/arch/arm/mach-omap/ocpi.c
@@ -59,8 +59,8 @@ int ocpi_enable(void)
 
 	/* Make sure there's clock for OCPI */
 
-#ifdef CONFIG_ARCH_OMAP1610
-        if (cpu_is_omap1610()) {
+#if defined(CONFIG_ARCH_OMAP1610) || defined(CONFIG_ARCH_OMAP1710)
+        if (cpu_is_omap1610() || cpu_is_omap1710()) {
 		val = omap_readl(OMAP1610_ARM_IDLECT3);
 		val |= EN_OCPI_CK;
 		val &= ~IDLOCPI_ARM;
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index d394f6957..bb28824d8 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -12,7 +12,7 @@ config ARCH_LUBBOCK
 config MACH_MAINSTONE
 	bool "Intel HCDDBBVA0 Development Platform"
 	select PXA27x
-	#select IWMMXT
+	select IWMMXT
 
 config ARCH_PXA_IDP
 	bool "Accelent Xscale IDP"
@@ -32,4 +32,9 @@ config PXA27x
 	help
 	  Select code specific to PXA27x variants
 
+config IWMMXT
+	bool
+	help
+	  Enable support for iWMMXt
+
 endif
diff --git a/arch/arm/mach-pxa/dma.c b/arch/arm/mach-pxa/dma.c
index 3096fa7c5..458112b21 100644
--- a/arch/arm/mach-pxa/dma.c
+++ b/arch/arm/mach-pxa/dma.c
@@ -23,6 +23,7 @@
 #include <asm/hardware.h>
 #include <asm/dma.h>
 
+#include <asm/arch/pxa-regs.h>
 
 static struct dma_channel {
 	char *name;
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
index 80f3535e0..3f4755f70 100644
--- a/arch/arm/mach-pxa/generic.c
+++ b/arch/arm/mach-pxa/generic.c
@@ -30,8 +30,10 @@
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
 
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/udc.h>
 #include <asm/arch/pxafb.h>
+#include <asm/arch/mmc.h>
 
 #include "generic.h"
 
@@ -128,6 +130,12 @@ static struct platform_device pxamci_device = {
 	.resource	= pxamci_resources,
 };
 
+void __init pxa_set_mci_info(struct pxamci_platform_data *info)
+{
+	pxamci_device.dev.platform_data = info;
+}
+EXPORT_SYMBOL(pxa_set_mci_info);
+
 
 static struct pxa2xx_udc_mach_info pxa_udc_info;
 
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index db53cd571..6f8b4873e 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -27,6 +27,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/idp.h>
 
 #include "generic.h"
@@ -100,7 +101,7 @@ static void __init idp_map_io(void)
 	pxa_map_io();
 	iotable_init(idp_io_desc, ARRAY_SIZE(idp_io_desc));
 
-	set_irq_type(IRQ_TO_GPIO_2_80(TOUCH_PANEL_IRQ), TOUCH_PANEL_IRQ_EDGE);
+	set_irq_type(TOUCH_PANEL_IRQ, TOUCH_PANEL_IRQ_EDGE);
 
 	// serial ports 2 & 3
 	pxa_gpio_mode(GPIO42_BTRXD_MD);
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index c771e4376..a676a8657 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -20,39 +20,64 @@
 #include <asm/hardware.h>
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
+#include <asm/arch/pxa-regs.h>
 
 #include "generic.h"
 
 
 /*
- * This is for IRQs known as PXA_IRQ([8...31]).
+ * This is for peripheral IRQs internal to the PXA chip.
  */
 
-static void pxa_mask_irq(unsigned int irq)
+static void pxa_mask_low_irq(unsigned int irq)
 {
 	ICMR &= ~(1 << (irq + PXA_IRQ_SKIP));
 }
 
-static void pxa_unmask_irq(unsigned int irq)
+static void pxa_unmask_low_irq(unsigned int irq)
 {
 	ICMR |= (1 << (irq + PXA_IRQ_SKIP));
 }
 
-static struct irqchip pxa_internal_chip = {
-	.ack		= pxa_mask_irq,
-	.mask		= pxa_mask_irq,
-	.unmask		= pxa_unmask_irq,
+static struct irqchip pxa_internal_chip_low = {
+	.ack		= pxa_mask_low_irq,
+	.mask		= pxa_mask_low_irq,
+	.unmask		= pxa_unmask_low_irq,
 };
 
+#if PXA_INTERNAL_IRQS > 32
+
+/*
+ * This is for the second set of internal IRQs as found on the PXA27x.
+ */
+
+static void pxa_mask_high_irq(unsigned int irq)
+{
+	ICMR2 &= ~(1 << (irq - 32 + PXA_IRQ_SKIP));
+}
+
+static void pxa_unmask_high_irq(unsigned int irq)
+{
+	ICMR2 |= (1 << (irq - 32 + PXA_IRQ_SKIP));
+}
+
+static struct irqchip pxa_internal_chip_high = {
+	.ack		= pxa_mask_high_irq,
+	.mask		= pxa_mask_high_irq,
+	.unmask		= pxa_unmask_high_irq,
+};
+
+#endif
+
 /*
  * PXA GPIO edge detection for IRQs:
  * IRQs are generated on Falling-Edge, Rising-Edge, or both.
  * Use this instead of directly setting GRER/GFER.
  */
 
-static long GPIO_IRQ_rising_edge[3];
-static long GPIO_IRQ_falling_edge[3];
-static long GPIO_IRQ_mask[3];
+static long GPIO_IRQ_rising_edge[4];
+static long GPIO_IRQ_falling_edge[4];
+static long GPIO_IRQ_mask[4];
 
 static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
 {
@@ -106,13 +131,13 @@ static void pxa_ack_low_gpio(unsigned int irq)
 
 static struct irqchip pxa_low_gpio_chip = {
 	.ack		= pxa_ack_low_gpio,
-	.mask		= pxa_mask_irq,
-	.unmask		= pxa_unmask_irq,
+	.mask		= pxa_mask_low_irq,
+	.unmask		= pxa_unmask_low_irq,
 	.type		= pxa_gpio_irq_type,
 };
 
 /*
- * Demux handler for GPIO 2-80 edge detect interrupts
+ * Demux handler for GPIO>=2 edge detect interrupts
  */
 
 static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
@@ -169,6 +194,23 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
 			} while (mask);
 			loop = 1;
 		}
+
+#if PXA_LAST_GPIO >= 96
+		mask = GEDR3;
+		if (mask) {
+			GEDR3 = mask;
+			irq = IRQ_GPIO(96);
+			desc = irq_desc + irq;
+			do {
+				if (mask & 1)
+					desc->handle(irq, desc, regs);
+				irq++;
+				desc++;
+				mask >>= 1;
+			} while (mask);
+			loop = 1;
+		}
+#endif
 	} while (loop);
 }
 
@@ -214,12 +256,25 @@ void __init pxa_init_irq(void)
 	ICLR = 0;
 
 	/* clear all GPIO edge detects */
-	GFER0 = GFER1 = GFER2 = 0;
-	GRER0 = GRER1 = GRER2 = 0;
+	GFER0 = 0;
+	GFER1 = 0;
+	GFER2 = 0;
+	GRER0 = 0;
+	GRER1 = 0;
+	GRER2 = 0;
 	GEDR0 = GEDR0;
 	GEDR1 = GEDR1;
 	GEDR2 = GEDR2;
 
+#ifdef CONFIG_PXA27x
+	/* And similarly for the extra regs on the PXA27x */
+	ICMR2 = 0;
+	ICLR2 = 0;
+	GFER3 = 0;
+	GRER3 = 0;
+	GEDR3 = GEDR3;
+#endif
+
 	/* only unmasked interrupts kick us out of idle */
 	ICCR = 1;
 
@@ -227,10 +282,18 @@ void __init pxa_init_irq(void)
 	GPIO_IRQ_mask[0] = 3;
 
 	for (irq = PXA_IRQ(PXA_IRQ_SKIP); irq <= PXA_IRQ(31); irq++) {
-		set_irq_chip(irq, &pxa_internal_chip);
+		set_irq_chip(irq, &pxa_internal_chip_low);
+		set_irq_handler(irq, do_level_IRQ);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+
+#if PXA_INTERNAL_IRQS > 32
+	for (irq = PXA_IRQ(32); irq < PXA_IRQ(PXA_INTERNAL_IRQS); irq++) {
+		set_irq_chip(irq, &pxa_internal_chip_high);
 		set_irq_handler(irq, do_level_IRQ);
 		set_irq_flags(irq, IRQF_VALID);
 	}
+#endif
 
 	for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
 		set_irq_chip(irq, &pxa_low_gpio_chip);
@@ -238,13 +301,13 @@ void __init pxa_init_irq(void)
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
-	for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(80); irq++) {
+	for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(PXA_LAST_GPIO); irq++) {
 		set_irq_chip(irq, &pxa_muxed_gpio_chip);
 		set_irq_handler(irq, do_edge_IRQ);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
-	/* Install handler for GPIO 2-80 edge detect interrupts */
-	set_irq_chip(IRQ_GPIO_2_80, &pxa_internal_chip);
-	set_irq_chained_handler(IRQ_GPIO_2_80, pxa_gpio_demux_handler);
+	/* Install handler for GPIO>=2 edge detect interrupts */
+	set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low);
+	set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler);
 }
diff --git a/arch/arm/mach-pxa/leds-lubbock.c b/arch/arm/mach-pxa/leds-lubbock.c
index 0e083b34e..05cf56059 100644
--- a/arch/arm/mach-pxa/leds-lubbock.c
+++ b/arch/arm/mach-pxa/leds-lubbock.c
@@ -17,6 +17,7 @@
 #include <asm/hardware.h>
 #include <asm/leds.h>
 #include <asm/system.h>
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/lubbock.h>
 
 #include "leds.h"
diff --git a/arch/arm/mach-pxa/leds-mainstone.c b/arch/arm/mach-pxa/leds-mainstone.c
index 8403f6780..bbd3f87a9 100644
--- a/arch/arm/mach-pxa/leds-mainstone.c
+++ b/arch/arm/mach-pxa/leds-mainstone.c
@@ -17,6 +17,7 @@
 #include <asm/leds.h>
 #include <asm/system.h>
 
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/mainstone.h>
 
 #include "leds.h"
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 28c9677a9..a09d4c11b 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -29,6 +29,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/lubbock.h>
 #include <asm/arch/udc.h>
 #include <asm/arch/pxafb.h>
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 155b5950e..219fd4ecd 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -31,6 +31,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/mainstone.h>
 #include <asm/arch/pxafb.h>
 
diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
index 245e25b08..5e84864a8 100644
--- a/arch/arm/mach-pxa/pm.c
+++ b/arch/arm/mach-pxa/pm.c
@@ -19,7 +19,9 @@
 #include <asm/hardware.h>
 #include <asm/memory.h>
 #include <asm/system.h>
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/lubbock.h>
+#include <asm/mach/time.h>
 
 
 /*
@@ -45,7 +47,7 @@ extern void pxa_cpu_resume(void);
  */
 enum {	SLEEP_SAVE_START = 0,
 
-	SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER,
+	SLEEP_SAVE_OIER,
 	SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3,
 
 	SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2,
@@ -68,17 +70,18 @@ static int pxa_pm_enter(u32 state)
 {
 	unsigned long sleep_save[SLEEP_SAVE_SIZE];
 	unsigned long checksum = 0;
-	unsigned long delta;
+	struct timespec delta, rtc;
 	int i;
 
 	if (state != PM_SUSPEND_MEM)
 		return -EINVAL;
 
 	/* preserve current time */
-	delta = xtime.tv_sec - RCNR;
+	rtc.tv_sec = RCNR;
+	rtc.tv_nsec = 0;
+	save_time_delta(&delta, &rtc);
 
 	/* save vital registers */
-	SAVE(OSCR);
 	SAVE(OSMR0);
 	SAVE(OSMR1);
 	SAVE(OSMR2);
@@ -149,9 +152,11 @@ static int pxa_pm_enter(u32 state)
 	RESTORE(OSMR1);
 	RESTORE(OSMR2);
 	RESTORE(OSMR3);
-	RESTORE(OSCR);
 	RESTORE(OIER);
 
+	/* OSMR0 is the system timer: make sure OSCR is sufficiently behind */
+	OSCR = OSMR0 - LATCH;
+
 	RESTORE(CKEN);
 
 	ICLR = 0;
@@ -159,7 +164,8 @@ static int pxa_pm_enter(u32 state)
 	RESTORE(ICMR);
 
 	/* restore current time */
-	xtime.tv_sec = RCNR + delta;
+	rtc.tv_sec = RCNR;
+	restore_time_delta(&delta, &rtc);
 
 #ifdef DEBUG
 	printk(KERN_DEBUG "*** made it back from resume\n");
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index 41150917f..e887b7175 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -22,6 +22,7 @@
 #include <linux/pm.h>
 
 #include <asm/hardware.h>
+#include <asm/arch/pxa-regs.h>
 
 #include "generic.h"
 
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index b1573c837..e5e97fef8 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -14,6 +14,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <asm/arch/pxa-regs.h>
 #include <linux/init.h>
 #include <linux/pm.h>
 
diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S
index 189263939..be00614f5 100644
--- a/arch/arm/mach-pxa/sleep.S
+++ b/arch/arm/mach-pxa/sleep.S
@@ -16,6 +16,8 @@
 #include <asm/assembler.h>
 #include <asm/hardware.h>
 
+#include <asm/arch/pxa-regs.h>
+
 		.text
 
 /*
@@ -64,6 +66,37 @@ ENTRY(pxa_cpu_suspend)
 	@ prepare pointer to physical address 0 (virtual mapping in generic.c)
 	mov	r2, #UNCACHED_PHYS_0
 
+	@ Intel PXA255 Specification Update notes problems
+	@ about suspending with PXBus operating above 133MHz
+	@ (see Errata 31, GPIO output signals, ... unpredictable in sleep
+	@
+	@ We keep the change-down close to the actual suspend on SDRAM
+	@ as possible to eliminate messing about with the refresh clock
+	@ as the system will restore with the original speed settings
+	@
+	@ Ben Dooks, 13-Sep-2004
+
+	ldr	r6, =CCCR
+	ldr	r8, [r6]		@ keep original value for resume
+
+	@ ensure x1 for run and turbo mode with memory clock
+	bic	r7, r8, #CCCR_M_MASK | CCCR_N_MASK
+	orr	r7, r7, #(1<<5) | (2<<7)
+
+	@ check that the memory frequency is within limits
+	and	r14, r7, #CCCR_L_MASK
+	teq	r14, #1
+	bicne	r7, r7, #CCCR_L_MASK
+	orrne	r7, r7, #1			@@ 99.53MHz
+
+	@ get ready for the change
+	@ note, since we are making turbo=run, do not remove the turbo
+	@ as this may cause non-turbo mode on resume
+	mrc	p14, 0, r0, c6, c0, 0
+	bic	r0, r0, #2			@ clear change bit
+	mcr	p14, 0, r0, c6, c0, 0
+	orr	r0, r0, #2			@ initiate change bit
+
 	@ align execution to a cache line
 	b	1f
 
@@ -74,6 +107,13 @@ ENTRY(pxa_cpu_suspend)
 	@ All needed values are now in registers.
 	@ These last instructions should be in cache
 
+	@ initiate the frequency change...
+	str	r7, [r6]
+	mcr	p14, 0, r0, c6, c0, 0
+
+	@ restore the original cpu speed value for resume
+	str	r8, [r6]
+
 	@ put SDRAM into self-refresh
 	str	r5, [r4]
 
@@ -83,8 +123,7 @@ ENTRY(pxa_cpu_suspend)
 	@ enter sleep mode
 	mcr	p14, 0, r1, c7, c0, 0
 
-20:	nop
-	b	20b				@ loop waiting for sleep
+20:	b	20b				@ loop waiting for sleep
 
 /*
  * cpu_pxa_resume()
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 7e8923563..a49fc0299 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -27,6 +27,7 @@
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
+#include <asm/arch/pxa-regs.h>
 
 
 static inline unsigned long pxa_get_rtc_time(void)
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index 40e78bc44..ee42fe2c2 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -1,9 +1,10 @@
 if ARCH_S3C2410
 
-menu "S3C2410 Implementations"
+menu "S3C24XX Implementations"
 
 config ARCH_BAST
 	bool "Simtec Electronics BAST (EB2410ITX)"
+	select CPU_S3C2410
 	help
 	  Say Y here if you are using the Simtec Electronics EB2410ITX
 	  development board (also known as BAST)
@@ -12,18 +13,22 @@ config ARCH_BAST
 
 config ARCH_H1940
 	bool "IPAQ H1940"
+	select CPU_S3C2410
 	help
 	  Say Y here if you are using the HP IPAQ H1940
+
 	  <http://www.handhelds.org/projects/h1940.html>.
 
 config ARCH_SMDK2410
 	bool "SMDK2410/A9M2410"
+	select CPU_S3C2410
 	help
 	   Say Y here if you are using the SMDK2410 or the derived module A9M2410
            <http://www.fsforth.de>
 
 config MACH_VR1000
 	bool "Thorcom VR1000"
+	select CPU_S3C2410
 	help
 	  Say Y here if you are using the Thorcom VR1000 board.
 
@@ -32,4 +37,39 @@ config MACH_VR1000
 
 endmenu
 
+config CPU_S3C2410
+	bool
+	depends on ARCH_S3C2410
+	help
+	  Support for S3C2410 and S3C2410A family from the S3C24XX line
+	  of Samsung Mobile CPUs.
+
+config CPU_S3C2440
+	bool
+	depends on ARCH_S3C2410
+	help
+	  Support for S3C2440 Samsung Mobile CPU based systems.
+
+comment "S3C2410 Setup"
+
+config S3C2410_DMA
+	bool "S3C2410 DMA support"
+	depends on ARCH_S3C2410
+	help
+	  S3C2410 DMA support. This is needed for drivers like sound which
+	  use the S3C2410's DMA system to move data to and from the
+	  peripheral blocks.
+
+config S3C2410_DMA_DEBUG
+	bool "S3C2410 DMA support debug"
+	depends on ARCH_S3C2410 && S3C2410_DMA
+	help
+	  Enable debugging output for the DMA code. This option sends info
+	  to the kernel log, at priority KERN_DEBUG.
+
+	  Note, it is easy to create and fill the log buffer in a small
+	  amount of time, as well as using an significant percantage of
+	  the CPU time doing so.
+
+
 endif
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index 476c6ca78..5d6d80e91 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -1,19 +1,28 @@
+
 #
 # Makefile for the linux kernel.
 #
 
 # Object file lists.
 
-obj-y			:= s3c2410.o irq.o time.o gpio.o
+obj-y			:= cpu.o irq.o time.o gpio.o clock.o devs.o
 obj-m			:=
 obj-n			:=
 obj-			:=
 
-obj-$(CONFIG_ARCH_BAST)    += mach-bast.o
-obj-$(CONFIG_MACH_H1940)   += mach-h1940.o
-obj-$(CONFIG_ARCH_H1940)   += mach-h1940.o
-obj-$(CONFIG_ARCH_SMDK2410) += mach-smdk2410.o
-obj-$(CONFIG_MACH_VR1000)  += mach-vr1000.o
+# S3C2410 support files
+
+obj-$(CONFIG_CPU_S3C2410)  += s3c2410.o
+obj-$(CONFIG_S3C2410_DMA)  += dma.o
+
+# S3C2440 support
+
+obj-$(CONFIG_CPU_S3C2440)  += s3c2440.o s3c2440-dsc.o
+
+# machine specific support
+
+obj-$(CONFIG_ARCH_BAST)		+= mach-bast.o usb-simtec.o
+obj-$(CONFIG_ARCH_H1940)	+= mach-h1940.o
+obj-$(CONFIG_ARCH_SMDK2410)	+= mach-smdk2410.o
+obj-$(CONFIG_MACH_VR1000)	+= mach-vr1000.o usb-simtec.o
 
-#obj-$(CONFIG_PCI)	+=$(pci-y)
-#obj-$(CONFIG_LEDS)	+=$(leds-y)
diff --git a/arch/arm/mach-s3c2410/gpio.c b/arch/arm/mach-s3c2410/gpio.c
index 450b132af..8996725e9 100644
--- a/arch/arm/mach-s3c2410/gpio.c
+++ b/arch/arm/mach-s3c2410/gpio.c
@@ -19,6 +19,15 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
+ * Changelog
+ *	13-Sep-2004  BJD  Implemented change of MISCCR
+ *	14-Sep-2004  BJD  Added getpin call
+ *	14-Sep-2004  BJD  Fixed bug in setpin() call
+ *	30-Sep-2004  BJD  Fixed cfgpin() mask bug
+ *	01-Oct-2004  BJD  Added getcfg() to get pin configuration
+ *	01-Oct-2004  BJD  Fixed mask bug in pullup() call
+ *	01-Oct-2004  BJD  Added getirq() to turn pin into irqno
+ *	04-Oct-2004  BJD  Added irq filter controls for GPIO
  */
 
 
@@ -36,23 +45,20 @@
 void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
 {
 	unsigned long base = S3C2410_GPIO_BASE(pin);
-	unsigned long shift = 1;
-	unsigned long mask = 3;
+	unsigned long mask;
 	unsigned long con;
 	unsigned long flags;
 
 	if (pin < S3C2410_GPIO_BANKB) {
-		shift = 0;
-		mask  = 1;
+		mask = 1 << S3C2410_GPIO_OFFSET(pin);
+	} else {
+		mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
 	}
 
-	mask <<= S3C2410_GPIO_OFFSET(pin);
-
 	local_irq_save(flags);
 
-	con = __raw_readl(base + 0x00);
-
-	con &= mask << shift;
+	con  = __raw_readl(base + 0x00);
+	con &= ~mask;
 	con |= function;
 
 	__raw_writel(con, base + 0x00);
@@ -60,6 +66,20 @@ void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
 	local_irq_restore(flags);
 }
 
+unsigned int s3c2410_gpio_getcfg(unsigned int pin)
+{
+	unsigned long base = S3C2410_GPIO_BASE(pin);
+	unsigned long mask;
+
+	if (pin < S3C2410_GPIO_BANKB) {
+		mask = 1 << S3C2410_GPIO_OFFSET(pin);
+	} else {
+		mask = 3 << S3C2410_GPIO_OFFSET(pin)*2;
+	}
+
+	return __raw_readl(base) & mask;
+}
+
 void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
 {
 	unsigned long base = S3C2410_GPIO_BASE(pin);
@@ -73,7 +93,7 @@ void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
 	local_irq_save(flags);
 
 	up = __raw_readl(base + 0x08);
-	up &= 1 << offs;
+	up &= ~(1L << offs);
 	up |= to << offs;
 	__raw_writel(up, base + 0x08);
 
@@ -90,9 +110,85 @@ void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
 	local_irq_save(flags);
 
 	dat = __raw_readl(base + 0x04);
-	dat &= 1 << offs;
+	dat &= ~(1 << offs);
 	dat |= to << offs;
 	__raw_writel(dat, base + 0x04);
 
 	local_irq_restore(flags);
 }
+
+unsigned int s3c2410_gpio_getpin(unsigned int pin)
+{
+	unsigned long base = S3C2410_GPIO_BASE(pin);
+	unsigned long offs = S3C2410_GPIO_OFFSET(pin);
+
+	return __raw_readl(base + 0x04) & (1<< offs);
+}
+
+unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
+{
+	unsigned long flags;
+	unsigned long misccr;
+
+	local_irq_save(flags);
+	misccr = __raw_readl(S3C2410_MISCCR);
+	misccr &= ~clear;
+	misccr ^= change;
+	__raw_writel(misccr, S3C2410_MISCCR);
+	local_irq_restore(flags);
+
+	return misccr;
+}
+
+int s3c2410_gpio_getirq(unsigned int pin)
+{
+	if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15_EINT23)
+		return -1;	/* not valid interrupts */
+
+	if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)
+		return -1;	/* not valid pin */
+
+	if (pin < S3C2410_GPF4)
+		return (pin - S3C2410_GPF0) + IRQ_EINT0;
+
+	if (pin < S3C2410_GPG0)
+		return (pin - S3C2410_GPF4) + IRQ_EINT4;
+
+	return (pin - S3C2410_GPG0) + IRQ_EINT8;
+}
+
+int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
+			   unsigned int config)
+{
+	unsigned long reg = S3C2410_EINFLT0;
+	unsigned long flags;
+	unsigned long val;
+
+	if (pin < S3C2410_GPG8 || pin > S3C2410_GPG15)
+		return -1;
+
+	config &= 0xff;
+
+	pin -= S3C2410_GPG8_EINT16;
+	reg += pin & ~3;
+
+	local_irq_save(flags);
+
+	/* update filter width and clock source */
+
+	val = __raw_readl(reg);
+	val &= ~(0xff << ((pin & 3) * 8));
+	val |= config << ((pin & 3) * 8);
+	__raw_writel(val, reg);
+
+	/* update filter enable */
+
+	val = __raw_readl(S3C2410_EXTINT2);
+	val &= ~(1 << ((pin * 4) + 3));
+	val |= on << ((pin * 4) + 3);
+	__raw_writel(val, S3C2410_EXTINT2);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c
index 878b9740d..1951a0323 100644
--- a/arch/arm/mach-s3c2410/irq.c
+++ b/arch/arm/mach-s3c2410/irq.c
@@ -1,7 +1,7 @@
 /* linux/arch/arm/mach-s3c2410/irq.c
  *
- * Copyright (c) 2003 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2003,2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -17,7 +17,23 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- */
+ * Changelog:
+ *
+ *   22-Jul-2004  Ben Dooks <ben@simtec.co.uk>
+ *                Fixed compile warnings
+ *
+ *   22-Jul-2004  Roc Wu <cooloney@yahoo.com.cn>
+ *                Fixed s3c_extirq_type
+ *
+ *   21-Jul-2004  Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
+ *                Addition of ADC/TC demux
+ *
+ *   04-Oct-2004  Klaus Fetscher <k.fetscher@fetron.de>
+ *		  Fix for set_irq_type() on low EINT numbers
+ *
+ *   05-Oct-2004  Ben Dooks <ben@simtec.co.uk>
+ *		  Tidy up KF's patch and sort out new release
+*/
 
 
 #include <linux/init.h>
@@ -34,11 +50,8 @@
 #include <asm/mach/irq.h>
 
 #include <asm/arch/regs-irq.h>
-#include <asm/arch/regs-lcd.h>
+#include <asm/arch/regs-gpio.h>
 
-#if 0
-#include <asm/debug-ll.h>
-#endif
 
 #define irqdbf(x...)
 #define irqdbf2(x...)
@@ -177,12 +190,84 @@ s3c_irqext_unmask(unsigned int irqno)
 	s3c_irq_unmask((irqno <= (IRQ_EINT7 - EXTINT_OFF)) ? IRQ_EINT4t7 : IRQ_EINT8t23);
 }
 
-/* todo - put type handler in here */
-
 static int
 s3c_irqext_type(unsigned int irq, unsigned int type)
 {
-	irqdbf("s3c_irqext_type: called for irq %d, type %d\n", irq, type);
+	unsigned long extint_reg;
+	unsigned long gpcon_reg;
+	unsigned long gpcon_offset, extint_offset;
+	unsigned long newvalue = 0, value;
+
+	if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
+	{
+		gpcon_reg = S3C2410_GPFCON;
+		extint_reg = S3C2410_EXTINT0;
+		gpcon_offset = (irq - IRQ_EINT0) * 2;
+		extint_offset = (irq - IRQ_EINT0) * 4;
+	}
+	else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
+	{
+		gpcon_reg = S3C2410_GPFCON;
+		extint_reg = S3C2410_EXTINT0;
+		gpcon_offset = (irq - (EXTINT_OFF)) * 2;
+		extint_offset = (irq - (EXTINT_OFF)) * 4;
+	}
+	else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
+	{
+		gpcon_reg = S3C2410_GPGCON;
+		extint_reg = S3C2410_EXTINT1;
+		gpcon_offset = (irq - IRQ_EINT8) * 2;
+		extint_offset = (irq - IRQ_EINT8) * 4;
+	}
+	else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
+	{
+		gpcon_reg = S3C2410_GPGCON;
+		extint_reg = S3C2410_EXTINT2;
+		gpcon_offset = (irq - IRQ_EINT8) * 2;
+		extint_offset = (irq - IRQ_EINT16) * 4;
+	} else
+		return -1;
+
+	/* Set the GPIO to external interrupt mode */
+	value = __raw_readl(gpcon_reg);
+	value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset);
+	__raw_writel(value, gpcon_reg);
+
+	/* Set the external interrupt to pointed trigger type */
+	switch (type)
+	{
+		case IRQT_NOEDGE:
+			printk(KERN_WARNING "No edge setting!\n");
+			break;
+
+		case IRQT_RISING:
+			newvalue = S3C2410_EXTINT_RISEEDGE;
+			break;
+
+		case IRQT_FALLING:
+			newvalue = S3C2410_EXTINT_FALLEDGE;
+			break;
+
+		case IRQT_BOTHEDGE:
+			newvalue = S3C2410_EXTINT_BOTHEDGE;
+			break;
+
+		case IRQT_LOW:
+			newvalue = S3C2410_EXTINT_LOWLEV;
+			break;
+
+		case IRQT_HIGH:
+			newvalue = S3C2410_EXTINT_HILEV;
+			break;
+
+		default:
+			printk(KERN_ERR "No such irq type %d", type);
+			return -1;
+	}
+
+	value = __raw_readl(extint_reg);
+	value = (value & ~(7 << extint_offset)) | (newvalue << extint_offset);
+	__raw_writel(value, extint_reg);
 
 	return 0;
 }
@@ -194,6 +279,13 @@ static struct irqchip s3c_irqext_chip = {
 	.type	    = s3c_irqext_type
 };
 
+static struct irqchip s3c_irq_eint0t4 = {
+	.ack	   = s3c_irq_ack,
+	.mask	   = s3c_irq_mask,
+	.unmask	   = s3c_irq_unmask,
+	.type	   = s3c_irqext_type
+};
+
 /* mask values for the parent registers for each of the interrupt types */
 
 #define INTMSK_UART0	 (1UL << (IRQ_UART0 - IRQ_EINT0))
@@ -368,37 +460,37 @@ static struct irqchip s3c_irq_adc = {
 	.ack	    = s3c_irq_adc_ack,
 };
 
-#if 0
-/* LCD (todo) */
-
-static void
-s3c_irq_lcd_mask(unsigned int irqno)
+/* irq demux for adc */
+static void s3c_irq_demux_adc(unsigned int irq,
+			      struct irqdesc *desc,
+			      struct pt_regs *regs)
 {
+	unsigned int subsrc, submsk;
+	unsigned int offset = 9;
+	struct irqdesc *mydesc;
 
-}
-
-static void
-s3c_irq_lcd_unmask(unsigned int irqno)
-{
+	/* read the current pending interrupts, and the mask
+	 * for what it is available */
 
-}
+	subsrc = __raw_readl(S3C2410_SUBSRCPND);
+	submsk = __raw_readl(S3C2410_INTSUBMSK);
 
-static void
-s3c_irq_lcd_ack(unsigned int irqno)
-{
+	subsrc &= ~submsk;
+	subsrc >>= offset;
+	subsrc &= 3;
 
+	if (subsrc != 0) {
+		if (subsrc & 1) {
+			mydesc = irq_desc + IRQ_TC;
+			mydesc->handle( IRQ_TC, mydesc, regs);
+		}
+		if (subsrc & 2) {
+			mydesc = irq_desc + IRQ_ADC;
+			mydesc->handle(IRQ_ADC, mydesc, regs);
+		}
+	}
 }
 
-static struct irqchip s3c_irq_lcd = {
-	.mask	    = s3c_irq_lcd_mask,
-	.unmask	    = s3c_irq_lcd_unmask,
-	.ack	    = s3c_irq_lcd_ack,
-};
-#endif
-
-/* irq demux */
-
-
 static void s3c_irq_demux_uart(unsigned int start,
 			       struct pt_regs *regs)
 {
@@ -466,11 +558,15 @@ s3c_irq_demux_uart2(unsigned int irq,
 	s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs);
 }
 
-
+/* s3c2410_init_irq
+ *
+ * Initialise S3C2410 IRQ system
+*/
 
 void __init s3c2410_init_irq(void)
 {
 	unsigned long pend;
+	unsigned long last;
 	int irqno;
 	int i;
 
@@ -478,48 +574,51 @@ void __init s3c2410_init_irq(void)
 
 	/* first, clear all interrupts pending... */
 
+	last = 0;
 	for (i = 0; i < 4; i++) {
 		pend = __raw_readl(S3C2410_EINTPEND);
-		if (pend == 0)
+
+		if (pend == 0 || pend == last)
 			break;
+
 		__raw_writel(pend, S3C2410_EINTPEND);
 		printk("irq: clearing pending ext status %08x\n", (int)pend);
+		last = pend;
 	}
 
+	last = 0;
 	for (i = 0; i < 4; i++) {
 		pend = __raw_readl(S3C2410_INTPND);
-		if (pend == 0)
+
+		if (pend == 0 || pend == last)
 			break;
+
 		__raw_writel(pend, S3C2410_SRCPND);
 		__raw_writel(pend, S3C2410_INTPND);
 		printk("irq: clearing pending status %08x\n", (int)pend);
+		last = pend;
 	}
 
+	last = 0;
 	for (i = 0; i < 4; i++) {
 		pend = __raw_readl(S3C2410_SUBSRCPND);
 
-		if (pend == 0)
+		if (pend == 0 || pend == last)
 			break;
 
 		printk("irq: clearing subpending status %08x\n", (int)pend);
 		__raw_writel(pend, S3C2410_SUBSRCPND);
+		last = pend;
 	}
 
 	/* register the main interrupts */
 
 	irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
 
-	for (irqno = IRQ_EINT0; irqno < IRQ_ADCPARENT; irqno++) {
+	for (irqno = IRQ_BATT_FLT; irqno <= IRQ_ADCPARENT; irqno++) {
 		/* set all the s3c2410 internal irqs */
 
 		switch (irqno) {
-
-		case IRQ_EINT4t7:
-		case IRQ_EINT8t23:
-			/* these are already dealt with, so should never
-			 * appear */
-			break;
-
 			/* deal with the special IRQs (cascaded) */
 
 		case IRQ_UART0:
@@ -549,12 +648,18 @@ void __init s3c2410_init_irq(void)
 	set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
 	set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
 	set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
-	//set_irq_chained_handler(IRQ_LCD, s3c_irq_demux_);
-	//set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_);
+	set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
 
 
 	/* external interrupts */
 
+	for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
+		irqdbf("registering irq %d (ext int)\n", irqno);
+		set_irq_chip(irqno, &s3c_irq_eint0t4);
+		set_irq_handler(irqno, do_edge_IRQ);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+
 	for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
 		irqdbf("registering irq %d (extended s3c irq)\n", irqno);
 		set_irq_chip(irqno, &s3c_irqext_chip);
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index 2268ab3c7..f75266907 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -1,6 +1,6 @@
 /* linux/arch/arm/mach-s3c2410/mach-bast.c
  *
- * Copyright (c) 2003 Simtec Electronics
+ * Copyright (c) 2003,2004 Simtec Electronics
  *   Ben Dooks <ben@simtec.co.uk>
  *
  * http://www.simtec.co.uk/products/EB2410ITX/
@@ -10,6 +10,9 @@
  * published by the Free Software Foundation.
  *
  * Modifications:
+ *     14-Sep-2004 BJD  USB power control
+ *     20-Aug-2004 BJD  Added s3c2410_board struct
+ *     18-Aug-2004 BJD  Added platform devices from default set
  *     16-May-2003 BJD  Created initial version
  *     16-Aug-2003 BJD  Fixed header files and copyright, added URL
  *     05-Sep-2003 BJD  Moved to v2.6 kernel
@@ -23,6 +26,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/device.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -39,6 +43,9 @@
 #include <asm/arch/regs-serial.h>
 
 #include "s3c2410.h"
+#include "devs.h"
+#include "cpu.h"
+#include "usb-simtec.h"
 
 /* macros for virtual address mods for the io space entries */
 #define VA_C5(item) ((item) + BAST_VAM_CS5)
@@ -154,6 +161,7 @@ static struct s3c2410_uartcfg bast_uartcfgs[] = {
 	[1] = {
 		.hwport	     = 1,
 		.flags	     = 0,
+
 		.clock	     = &bast_serial_clock,
 		.ucon	     = UCON,
 		.ulcon	     = ULCON,
@@ -170,19 +178,51 @@ static struct s3c2410_uartcfg bast_uartcfgs[] = {
 	}
 };
 
+/* NOR Flash on BAST board */
+
+static struct resource bast_nor_resource[] = {
+	[0] = {
+		.start = S3C2410_CS1 + 0x4000000,
+		.end   = S3C2410_CS1 + 0x4000000 + (32*1024*1024) - 1,
+		.flags = IORESOURCE_MEM,
+	}
+};
+
+static struct platform_device bast_device_nor = {
+	.name		= "bast-nor",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(bast_nor_resource),
+	.resource	= bast_nor_resource,
+};
+
+/* Standard BAST devices */
+
+static struct platform_device *bast_devices[] __initdata = {
+	&s3c_device_usb,
+	&s3c_device_lcd,
+	&s3c_device_wdt,
+	&s3c_device_i2c,
+	&s3c_device_iis,
+ 	&s3c_device_rtc,
+	&bast_device_nor
+};
+
+static struct s3c2410_board bast_board __initdata = {
+	.devices       = bast_devices,
+	.devices_count = ARRAY_SIZE(bast_devices)
+};
 
 void __init bast_map_io(void)
 {
-	s3c2410_map_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
-	s3c2410_uartcfgs = bast_uartcfgs;
+	s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
+	s3c2410_init_uarts(bast_uartcfgs, ARRAY_SIZE(bast_uartcfgs));
+	s3c2410_set_board(&bast_board);
+	usb_simtec_init();
 }
 
 void __init bast_init_irq(void)
 {
-	//llprintk("bast_init_irq:\n");
-
 	s3c2410_init_irq();
-
 }
 
 void __init bast_init_time(void)
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index 0a9ba135b..397c546b7 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -1,6 +1,6 @@
-/* linux/arch/arm/mach-s3c2410/mach-ipaq.c
+/* linux/arch/arm/mach-s3c2410/mach-h1940.c
  *
- * Copyright (c) 2003 Simtec Electronics
+ * Copyright (c) 2003,2004 Simtec Electronics
  *   Ben Dooks <ben@simtec.co.uk>
  *
  * http://www.handhelds.org/projects/h1940.html
@@ -16,6 +16,8 @@
  *     06-Jan-2003 BJD  Updates for <arch/map.h>
  *     18-Jan-2003 BJD  Added serial port configuration
  *     17-Feb-2003 BJD  Copied to mach-ipaq.c
+ *     21-Aug-2004 BJD  Added struct s3c2410_board
+ *     04-Sep-2004 BJD  Changed uart init, renamed ipaq_ -> h1940_
 */
 
 #include <linux/kernel.h>
@@ -39,8 +41,10 @@
 #include <asm/arch/regs-serial.h>
 
 #include "s3c2410.h"
+#include "devs.h"
+#include "cpu.h"
 
-static struct map_desc ipaq_iodesc[] __initdata = {
+static struct map_desc h1940_iodesc[] __initdata = {
 	/* nothing here yet */
 };
 
@@ -48,7 +52,7 @@ static struct map_desc ipaq_iodesc[] __initdata = {
 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
 #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
 
-static struct s3c2410_uartcfg ipaq_uartcfgs[] = {
+static struct s3c2410_uartcfg h1940_uartcfgs[] = {
 	[0] = {
 		.hwport	     = 0,
 		.flags	     = 0,
@@ -77,21 +81,35 @@ static struct s3c2410_uartcfg ipaq_uartcfgs[] = {
 };
 
 
-void __init ipaq_map_io(void)
+
+
+static struct platform_device *h1940_devices[] __initdata = {
+	&s3c_device_usb,
+	&s3c_device_lcd,
+	&s3c_device_wdt,
+	&s3c_device_i2c,
+	&s3c_device_iis,
+};
+
+static struct s3c2410_board h1940_board __initdata = {
+	.devices       = h1940_devices,
+	.devices_count = ARRAY_SIZE(h1940_devices)
+};
+
+void __init h1940_map_io(void)
 {
-	s3c2410_map_io(ipaq_iodesc, ARRAY_SIZE(ipaq_iodesc));
-	s3c2410_uartcfgs = ipaq_uartcfgs;
+	s3c24xx_init_io(h1940_iodesc, ARRAY_SIZE(h1940_iodesc));
+	s3c2410_init_uarts(h1940_uartcfgs, ARRAY_SIZE(h1940_uartcfgs));
+	s3c2410_set_board(&h1940_board);
 }
 
-void __init ipaq_init_irq(void)
+void __init h1940_init_irq(void)
 {
-	//llprintk("ipaq_init_irq:\n");
-
 	s3c2410_init_irq();
 
 }
 
-void __init ipaq_init_time(void)
+void __init h1940_init_time(void)
 {
 	s3c2410_init_time();
 }
@@ -100,7 +118,7 @@ MACHINE_START(H1940, "IPAQ-H1940")
      MAINTAINER("Ben Dooks <ben@fluff.org>")
      BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
      BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
-     MAPIO(ipaq_map_io)
-     INITIRQ(ipaq_init_irq)
-     INITTIME(ipaq_init_time)
+     MAPIO(h1940_map_io)
+     INITIRQ(h1940_init_irq)
+     INITTIME(h1940_init_time)
 MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index bfadbd425..9f4286569 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -47,7 +47,8 @@
 #include <asm/arch/regs-serial.h>
 
 #include "s3c2410.h"
-
+#include "devs.h"
+#include "cpu.h"
 
 static struct map_desc smdk2410_iodesc[] __initdata = {
   /* nothing here yet */
@@ -87,11 +88,24 @@ static struct s3c2410_uartcfg smdk2410_uartcfgs[] = {
 	}
 };
 
+static struct platform_device *smdk2410_devices[] __initdata = {
+	&s3c_device_usb,
+	&s3c_device_lcd,
+	&s3c_device_wdt,
+	&s3c_device_i2c,
+	&s3c_device_iis,
+};
+
+static struct s3c2410_board smdk2410_board __initdata = {
+	.devices       = smdk2410_devices,
+	.devices_count = ARRAY_SIZE(smdk2410_devices)
+};
 
 void __init smdk2410_map_io(void)
 {
-	s3c2410_map_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc));
-	s3c2410_uartcfgs = smdk2410_uartcfgs;
+	s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc));
+	s3c2410_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
+	s3c2410_set_board(&smdk2410_board);
 }
 
 void __init smdk2410_init_irq(void)
@@ -113,3 +127,5 @@ MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switc
      INITIRQ(smdk2410_init_irq)
      INITTIME(smdk2410_init_time)
 MACHINE_END
+
+
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index aae341c69..4a07a40cc 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -11,13 +11,10 @@
  * published by the Free Software Foundation.
  *
  * Modifications:
+ *     14-Sep-2004 BJD  USB Power control
+ *     04-Sep-2004 BJD  Added new uart init, and io init
+ *     21-Aug-2004 BJD  Added struct s3c2410_board
  *     06-Aug-2004 BJD  Fixed call to time initialisation
- *     12-Jul-2004 BJD  Renamed machine
- *     16-May-2003 BJD  Created initial version
- *     16-Aug-2003 BJD  Fixed header files and copyright, added URL
- *     05-Sep-2003 BJD  Moved to v2.6 kernel
- *     06-Jan-2003 BJD  Updates for <arch/map.h>
- *     18-Jan-2003 BJD  Added serial port configuration
  *     05-Apr-2004 BJD  Copied to make mach-vr1000.c
 */
 
@@ -44,6 +41,9 @@
 #include <asm/arch/regs-serial.h>
 
 #include "s3c2410.h"
+#include "devs.h"
+#include "cpu.h"
+#include "usb-simtec.h"
 
 /* macros for virtual address mods for the io space entries */
 #define VA_C5(item) ((item) + BAST_VAM_CS5)
@@ -143,19 +143,31 @@ static struct s3c2410_uartcfg vr1000_uartcfgs[] = {
 	}
 };
 
+static struct platform_device *vr1000_devices[] __initdata = {
+	&s3c_device_usb,
+	&s3c_device_lcd,
+	&s3c_device_wdt,
+	&s3c_device_i2c,
+	&s3c_device_iis,
+};
+
+static struct s3c2410_board vr1000_board __initdata = {
+	.devices       = vr1000_devices,
+	.devices_count = ARRAY_SIZE(vr1000_devices)
+};
+
 
 void __init vr1000_map_io(void)
 {
-	s3c2410_map_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc));
-	s3c2410_uartcfgs = vr1000_uartcfgs;
+	s3c24xx_init_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc));
+	s3c2410_init_uarts(vr1000_uartcfgs, ARRAY_SIZE(vr1000_uartcfgs));
+	s3c2410_set_board(&vr1000_board);
+	usb_simtec_init();
 }
 
 void __init vr1000_init_irq(void)
 {
-	//llprintk("vr1000init_irq:\n");
-
 	s3c2410_init_irq();
-
 }
 
 void __init vr1000_init_time(void)
diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c
index bfd843cef..7709e8dde 100644
--- a/arch/arm/mach-s3c2410/s3c2410.c
+++ b/arch/arm/mach-s3c2410/s3c2410.c
@@ -1,6 +1,6 @@
 /* linux/arch/arm/mach-s3c2410/s3c2410.c
  *
- * Copyright (c) 2003 Simtec Electronics
+ * Copyright (c) 2003,2004 Simtec Electronics
  * Ben Dooks <ben@simtec.co.uk>
  *
  * http://www.simtec.co.uk/products/EB2410ITX/
@@ -13,7 +13,8 @@
  *     16-May-2003 BJD  Created initial version
  *     16-Aug-2003 BJD  Fixed header files and copyright, added URL
  *     05-Sep-2003 BJD  Moved to kernel v2.6
- *     18-Jan-2003 BJD  Added serial port configuration
+ *     18-Jan-2004 BJD  Added serial port configuration
+ *     21-Aug-2004 BJD  Added new struct s3c2410_board handler
 */
 
 #include <linux/kernel.h>
@@ -35,6 +36,9 @@
 #include <asm/arch/regs-clock.h>
 #include <asm/arch/regs-serial.h>
 
+#include "s3c2410.h"
+#include "cpu.h"
+
 int s3c2410_clock_tick_rate = 12*1000*1000;  /* current timers at 12MHz */
 
 /* serial port setup */
@@ -47,33 +51,14 @@ unsigned long s3c2410_fclk;
 unsigned long s3c2410_hclk;
 unsigned long s3c2410_pclk;
 
-#ifndef MHZ
-#define MHZ (1000*1000)
-#endif
-
-#define print_mhz(m) ((m) / MHZ), ((m / 1000) % 1000)
-
-#define IODESC_ENT(x) { S3C2410_VA_##x, S3C2410_PA_##x, S3C2410_SZ_##x, MT_DEVICE }
-
 static struct map_desc s3c2410_iodesc[] __initdata = {
-  IODESC_ENT(IRQ),
-  IODESC_ENT(MEMCTRL),
-  IODESC_ENT(USBHOST),
-  IODESC_ENT(DMA),
-  IODESC_ENT(CLKPWR),
-  IODESC_ENT(LCD),
-  IODESC_ENT(NAND),
-  IODESC_ENT(UART),
-  IODESC_ENT(TIMER),
-  IODESC_ENT(USBDEV),
-  IODESC_ENT(WATCHDOG),
-  IODESC_ENT(IIC),
-  IODESC_ENT(IIS),
-  IODESC_ENT(GPIO),
-  IODESC_ENT(RTC),
-  IODESC_ENT(ADC),
-  IODESC_ENT(SPI),
-  IODESC_ENT(SDI)
+	IODESC_ENT(USBHOST),
+	IODESC_ENT(CLKPWR),
+	IODESC_ENT(LCD),
+	IODESC_ENT(UART),
+	IODESC_ENT(TIMER),
+	IODESC_ENT(ADC),
+	IODESC_ENT(WATCHDOG)
 };
 
 static struct resource s3c_uart0_resource[] = {
@@ -146,14 +131,16 @@ static struct platform_device *uart_devices[] __initdata = {
 	&s3c_uart2
 };
 
-void __init s3c2410_map_io(struct map_desc *mach_desc, int size)
+void __init s3c2410_map_io(struct map_desc *mach_desc, int mach_size)
 {
 	unsigned long tmp;
 
 	/* register our io-tables */
 
 	iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc));
-	iotable_init(mach_desc, size);
+	iotable_init(mach_desc, mach_size);
+
+	printk("machine_initted %p,%d\n", mach_desc, mach_size);
 
 	/* now we've got our machine bits initialised, work out what
 	 * clocks we've got */
@@ -175,16 +162,41 @@ void __init s3c2410_map_io(struct map_desc *mach_desc, int size)
 	       print_mhz(s3c2410_pclk));
 }
 
+static struct s3c2410_board *board;
+
+void s3c2410_set_board(struct s3c2410_board *b)
+{
+	board = b;
+}
+
+void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+	s3c2410_uartcfgs = cfg;
+}
 
-static int __init s3c2410_init(void)
+int __init s3c2410_init(void)
 {
 	int ret;
 
 	printk("S3C2410: Initialising architecture\n");
 
 	ret = platform_add_devices(uart_devices, ARRAY_SIZE(uart_devices));
+	if (ret)
+		return ret;
+
+	if (board != NULL) {
+		if (board->devices != NULL) {
+			ret = platform_add_devices(board->devices,
+						   board->devices_count);
+
+			if (ret) {
+				printk(KERN_ERR "s3c2410: failed to add board devices (%d)\n", ret);
+			}
+		}
+
+		/* not adding board devices may not be fatal */
+		ret = 0;
+	}
 
 	return ret;
 }
-
-arch_initcall(s3c2410_init);
diff --git a/arch/arm/mach-s3c2410/s3c2410.h b/arch/arm/mach-s3c2410/s3c2410.h
index 862a7c86d..09742c9bc 100644
--- a/arch/arm/mach-s3c2410/s3c2410.h
+++ b/arch/arm/mach-s3c2410/s3c2410.h
@@ -1,4 +1,19 @@
-
+/* arch/arm/mach-s3c2410/s3c2410.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2410 machine directory
+ *
+ * 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.
+ *
+ * Modifications:
+ *     18-Aug-2004 BJD  Created initial version
+ *     20-Aug-2004 BJD  Added s3c2410_board struct
+ *     04-Sep-2004 BJD  Added s3c2410_init_uarts() call
+*/
 
 extern void s3c2410_map_io(struct map_desc *, int count);
 
@@ -6,3 +21,18 @@ extern void s3c2410_init_irq(void);
 
 extern void s3c2410_init_time(void);
 
+/* the board structure is used at first initialsation time
+ * to get info such as the devices to register for this
+ * board. This is done because platfrom_add_devices() cannot
+ * be called from the map_io entry.
+ *
+*/
+
+struct s3c2410_board {
+	struct platform_device  **devices;
+	unsigned int              devices_count;
+};
+
+extern void s3c2410_set_board(struct s3c2410_board *board);
+
+extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no);
diff --git a/arch/arm/mach-s3c2410/time.c b/arch/arm/mach-s3c2410/time.c
index 62d89d98c..04ba5dfe0 100644
--- a/arch/arm/mach-s3c2410/time.c
+++ b/arch/arm/mach-s3c2410/time.c
@@ -31,14 +31,12 @@
 #include <asm/irq.h>
 #include <asm/arch/map.h>
 #include <asm/arch/regs-timer.h>
+#include <asm/arch/regs-irq.h>
 #include <asm/mach/time.h>
 
 static unsigned long timer_startval;
 static unsigned long timer_ticks_usec;
 
-#ifdef CONFIG_S3C2410_RTC
-extern void s3c2410_rtc_check();
-#endif
 
 /* with an 12MHz clock, we get 12 ticks per-usec
  */
@@ -49,15 +47,30 @@ extern void s3c2410_rtc_check();
  * will have been disabled by do_gettimeoffset()
  * IRQs are disabled before entering here from do_gettimeofday()
  */
+
+#define SRCPND_TIMER4 (1<<(IRQ_TIMER4 - IRQ_EINT0))
+
 static unsigned long s3c2410_gettimeoffset (void)
 {
 	unsigned long tdone;
 	unsigned long usec;
+	unsigned long irqpend;
 
 	/* work out how many ticks have gone since last timer interrupt */
 
 	tdone = timer_startval - __raw_readl(S3C2410_TCNTO(4));
 
+	/* check to see if there is an interrupt pending */
+
+	irqpend = __raw_readl(S3C2410_SRCPND);
+	if (irqpend & SRCPND_TIMER4) {
+		/* re-read the timer, and try and fix up for the missed
+		 * interrupt */
+
+		tdone = timer_startval - __raw_readl(S3C2410_TCNTO(4));
+		tdone += 1<<16;
+	}
+
 	/* currently, tcnt is in 12MHz units, but this may change
 	 * for non-bast machines...
 	 */
diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c
index be5dd86f4..6435b2e48 100644
--- a/arch/arm/mach-sa1100/cpu-sa1100.c
+++ b/arch/arm/mach-sa1100/cpu-sa1100.c
@@ -230,9 +230,7 @@ static int __init sa1100_cpu_init(struct cpufreq_policy *policy)
 }
 
 static struct cpufreq_driver sa1100_driver = {
-	.flags		= CPUFREQ_STICKY |
-			  CPUFREQ_PANIC_OUTOFSYNC | 
-			  CPUFREQ_PANIC_RESUME_OUTOFSYNC,
+	.flags		= CPUFREQ_STICKY,
 	.verify		= sa11x0_verify_speed,
 	.target		= sa1100_target,
 	.get		= sa11x0_getspeed,
diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c
index 62a4dbcce..8d2a89a2e 100644
--- a/arch/arm/mach-sa1100/cpu-sa1110.c
+++ b/arch/arm/mach-sa1100/cpu-sa1110.c
@@ -329,9 +329,7 @@ static int __init sa1110_cpu_init(struct cpufreq_policy *policy)
 }
 
 static struct cpufreq_driver sa1110_driver = {
-	.flags		= CPUFREQ_STICKY |
-			  CPUFREQ_PANIC_OUTOFSYNC | 
-			  CPUFREQ_PANIC_RESUME_OUTOFSYNC,
+	.flags		= CPUFREQ_STICKY,
 	.verify		= sa11x0_verify_speed,
 	.target		= sa1110_target,
 	.get		= sa11x0_getspeed,
diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
index 2532b7f80..7120ec5aa 100644
--- a/arch/arm/mach-sa1100/pm.c
+++ b/arch/arm/mach-sa1100/pm.c
@@ -30,6 +30,7 @@
 #include <asm/hardware.h>
 #include <asm/memory.h>
 #include <asm/system.h>
+#include <asm/mach/time.h>
 
 extern void sa1100_cpu_suspend(void);
 extern void sa1100_cpu_resume(void);
@@ -44,7 +45,7 @@ extern void sa1100_cpu_resume(void);
  */
 enum {	SLEEP_SAVE_SP = 0,
 
-	SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER,
+	SLEEP_SAVE_OIER,
 	SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3,
 
 	SLEEP_SAVE_GPDR, SLEEP_SAVE_GAFR,
@@ -58,18 +59,19 @@ enum {	SLEEP_SAVE_SP = 0,
 
 static int sa11x0_pm_enter(u32 state)
 {
-	unsigned long sleep_save[SLEEP_SAVE_SIZE];
-	unsigned long delta, gpio;
+	unsigned long gpio, sleep_save[SLEEP_SAVE_SIZE];
+	struct timespec delta, rtc;
 
 	if (state != PM_SUSPEND_MEM)
 		return -EINVAL;
 
 	/* preserve current time */
-	delta = xtime.tv_sec - RCNR;
+	rtc.tv_sec = RCNR;
+	rtc.tv_nsec = 0;
+	save_time_delta(&delta, &rtc);
 	gpio = GPLR;
 
 	/* save vital registers */
-	SAVE(OSCR);
 	SAVE(OSMR0);
 	SAVE(OSMR1);
 	SAVE(OSMR2);
@@ -131,11 +133,14 @@ static int sa11x0_pm_enter(u32 state)
 	RESTORE(OSMR1);
 	RESTORE(OSMR2);
 	RESTORE(OSMR3);
-	RESTORE(OSCR);
 	RESTORE(OIER);
 
+	/* OSMR0 is the system timer: make sure OSCR is sufficiently behind */
+	OSCR = OSMR0 - LATCH;
+
 	/* restore current time */
-	xtime.tv_sec = RCNR + delta;
+	rtc.tv_sec = RCNR;
+	restore_time_delta(&delta, &rtc);
 
 	return 0;
 }
diff --git a/arch/arm/mach-versatile/clock.c b/arch/arm/mach-versatile/clock.c
index a13253692..24f12bdfb 100644
--- a/arch/arm/mach-versatile/clock.c
+++ b/arch/arm/mach-versatile/clock.c
@@ -87,8 +87,8 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 	if (clk->setvco) {
 		struct icst525_vco vco;
 
-		vco = icst525_khz_to_vco(clk->params, rate);
-		clk->rate = icst525_khz(clk->params, vco);
+		vco = icst525_khz_to_vco(clk->params, rate / 1000);
+		clk->rate = icst525_khz(clk->params, vco) * 1000;
 
 		printk("Clock %s: setting VCO reg params: S=%d R=%d V=%d\n",
 			clk->name, vco.s, vco.r, vco.v);
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 285ca9abb..239d9897d 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -21,6 +21,7 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/device.h>
+#include <linux/dma-mapping.h>
 #include <linux/sysdev.h>
 #include <linux/interrupt.h>
 
@@ -31,6 +32,7 @@
 #include <asm/leds.h>
 #include <asm/mach-types.h>
 #include <asm/hardware/amba.h>
+#include <asm/hardware/amba_clcd.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
@@ -325,6 +327,213 @@ static struct mmc_platform_data mmc1_plat_data = {
 };
 #endif
 
+/*
+ * CLCD support.
+ */
+#define SYS_CLCD_MODE_MASK	(3 << 0)
+#define SYS_CLCD_MODE_5551	(0 << 0)
+#define SYS_CLCD_MODE_565	(1 << 0)
+#define SYS_CLCD_MODE_888	(2 << 0)
+#define SYS_CLCD_MODE_LT	(3 << 0)
+#define SYS_CLCD_NLCDIOON	(1 << 2)
+#define SYS_CLCD_VDDPOSSWITCH	(1 << 3)
+#define SYS_CLCD_PWR3V5SWITCH	(1 << 4)
+#define SYS_CLCD_ID_MASK	(0x1f << 8)
+#define SYS_CLCD_ID_SANYO_3_8	(0x00 << 8)
+#define SYS_CLCD_ID_UNKNOWN_8_4	(0x01 << 8)
+#define SYS_CLCD_ID_EPSON_2_2	(0x02 << 8)
+#define SYS_CLCD_ID_VGA		(0x1f << 8)
+
+static struct clcd_panel vga = {
+	.mode		= {
+		.name		= "VGA",
+		.refresh	= 60,
+		.xres		= 640,
+		.yres		= 480,
+		.pixclock	= 39721,
+		.left_margin	= 40,
+		.right_margin	= 24,
+		.upper_margin	= 32,
+		.lower_margin	= 11,
+		.hsync_len	= 96,
+		.vsync_len	= 2,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_BCD | TIM2_IPC,
+	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+	.bpp		= 16,
+};
+
+static struct clcd_panel sanyo_3_8_in = {
+	.mode		= {
+		.name		= "Sanyo QVGA",
+		.refresh	= 116,
+		.xres		= 320,
+		.yres		= 240,
+		.pixclock	= 100000,
+		.left_margin	= 6,
+		.right_margin	= 6,
+		.upper_margin	= 5,
+		.lower_margin	= 5,
+		.hsync_len	= 6,
+		.vsync_len	= 6,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_BCD,
+	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+	.bpp		= 16,
+};
+
+static struct clcd_panel epson_2_2_in = {
+	.mode		= {
+		.name		= "Epson QCIF",
+		.refresh	= 390,
+		.xres		= 176,
+		.yres		= 220,
+		.pixclock	= 62500,
+		.left_margin	= 3,
+		.right_margin	= 2,
+		.upper_margin	= 1,
+		.lower_margin	= 0,
+		.hsync_len	= 3,
+		.vsync_len	= 2,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_BCD | TIM2_IPC,
+	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+	.bpp		= 16,
+};
+
+/*
+ * Detect which LCD panel is connected, and return the appropriate
+ * clcd_panel structure.  Note: we do not have any information on
+ * the required timings for the 8.4in panel, so we presently assume
+ * VGA timings.
+ */
+static struct clcd_panel *versatile_clcd_panel(void)
+{
+	unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
+	struct clcd_panel *panel = &vga;
+	u32 val;
+
+	val = readl(sys_clcd) & SYS_CLCD_ID_MASK;
+	if (val == SYS_CLCD_ID_SANYO_3_8)
+		panel = &sanyo_3_8_in;
+	else if (val == SYS_CLCD_ID_EPSON_2_2)
+		panel = &epson_2_2_in;
+	else if (val == SYS_CLCD_ID_VGA)
+		panel = &vga;
+	else {
+		printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n",
+			val);
+	}
+
+	return &vga;
+}
+
+/*
+ * Disable all display connectors on the interface module.
+ */
+static void versatile_clcd_disable(struct clcd_fb *fb)
+{
+	unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
+	u32 val;
+
+	val = readl(sys_clcd);
+	val &= ~SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH;
+	writel(val, sys_clcd);
+}
+
+/*
+ * Enable the relevant connector on the interface module.
+ */
+static void versatile_clcd_enable(struct clcd_fb *fb)
+{
+	unsigned long sys_clcd = IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
+	u32 val;
+
+	val = readl(sys_clcd);
+	val &= ~SYS_CLCD_MODE_MASK;
+
+	switch (fb->fb.var.green.length) {
+	case 5:
+#if 0
+		/*
+		 * For some undocumented reason, we need to select 565 mode
+		 * even when using 555 with VGA.  Maybe this is only true
+		 * for the VGA output and needs to be done for LCD panels?
+		 * I can't get an explaination from the people who should
+		 * know.
+		 */
+		val |= SYS_CLCD_MODE_5551;
+		break;
+#endif
+	case 6:
+		val |= SYS_CLCD_MODE_565;
+		break;
+	case 8:
+		val |= SYS_CLCD_MODE_888;
+		break;
+	}
+
+	/*
+	 * Set the MUX
+	 */
+	writel(val, sys_clcd);
+
+	/*
+	 * And now enable the PSUs
+	 */
+	val |= SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH;
+	writel(val, sys_clcd);
+}
+
+static unsigned long framesize = SZ_1M;
+
+static int versatile_clcd_setup(struct clcd_fb *fb)
+{
+	dma_addr_t dma;
+
+	fb->panel		= versatile_clcd_panel();
+
+	fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
+						    &dma, GFP_KERNEL);
+	if (!fb->fb.screen_base) {
+		printk(KERN_ERR "CLCD: unable to map framebuffer\n");
+		return -ENOMEM;
+	}
+
+	fb->fb.fix.smem_start	= dma;
+	fb->fb.fix.smem_len	= framesize;
+
+	return 0;
+}
+
+static void versatile_clcd_remove(struct clcd_fb *fb)
+{
+	dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
+			      fb->fb.screen_base, fb->fb.fix.smem_start);
+}
+
+static struct clcd_board clcd_plat_data = {
+	.name		= "Versatile PB",
+	.check		= clcdfb_check,
+	.decode		= clcdfb_decode,
+	.disable	= versatile_clcd_disable,
+	.enable		= versatile_clcd_enable,
+	.setup		= versatile_clcd_setup,
+	.remove		= versatile_clcd_remove,
+};
+
 #define AMBA_DEVICE(name,busid,base,plat)			\
 static struct amba_device name##_device = {			\
 	.dev		= {					\
@@ -417,7 +626,7 @@ AMBA_DEVICE(mmc1,  "fpga:0b", MMCI1,    &mmc1_plat_data);
 /* DevChip Primecells */
 AMBA_DEVICE(smc,   "dev:00",  SMC,      NULL);
 AMBA_DEVICE(mpmc,  "dev:10",  MPMC,     NULL);
-AMBA_DEVICE(clcd,  "dev:20",  CLCD,     NULL);
+AMBA_DEVICE(clcd,  "dev:20",  CLCD,     &clcd_plat_data);
 AMBA_DEVICE(dmac,  "dev:30",  DMAC,     NULL);
 AMBA_DEVICE(sctl,  "dev:e0",  SCTL,     NULL);
 AMBA_DEVICE(wdog,  "dev:e1",  WATCHDOG, NULL);
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 545a548b1..f0a878204 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -43,7 +43,7 @@ config CPU_ARM710
 # ARM720T
 config CPU_ARM720T
 	bool "Support ARM720T processor" if !ARCH_CLPS711X && !ARCH_L7200 && !ARCH_CDB89712 && ARCH_INTEGRATOR
-	default y if ARCH_CLPS711X || ARCH_L7200 || ARCH_CDB89712
+	default y if ARCH_CLPS711X || ARCH_L7200 || ARCH_CDB89712 || ARCH_H720X
 	select CPU_32v4
 	select CPU_ABRT_LV4T
 	select CPU_CACHE_V4
@@ -59,7 +59,7 @@ config CPU_ARM720T
 # ARM920T
 config CPU_ARM920T
 	bool "Support ARM920T processor" if !ARCH_S3C2410
-	depends on ARCH_INTEGRATOR || ARCH_S3C2410
+	depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX
 	default y if ARCH_S3C2410
 	select CPU_32v4
 	select CPU_ABRT_EV4T
@@ -220,7 +220,7 @@ config CPU_SA1100
 # XScale
 config CPU_XSCALE
 	bool
-	depends on ARCH_IOP3XX || ARCH_PXA || ARCH_IXP4XX
+	depends on ARCH_IOP3XX || ARCH_PXA || ARCH_IXP4XX || ARCH_IXP2000
 	default y
 	select CPU_32v5
 	select CPU_ABRT_EV5T
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index fc764e17e..ccf316c11 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -3,7 +3,8 @@
 #
 
 obj-y				:= consistent.o extable.o fault-armv.o \
-				   fault.o init.o ioremap.o mmap.o mm-armv.o
+				   fault.o flush.o init.o ioremap.o mmap.o \
+				   mm-armv.o
 
 obj-$(CONFIG_MODULES)		+= proc-syms.o
 
diff --git a/arch/arm/mm/abort-ev5tj.S b/arch/arm/mm/abort-ev5tj.S
index 922e05a4d..fd0584a92 100644
--- a/arch/arm/mm/abort-ev5tj.S
+++ b/arch/arm/mm/abort-ev5tj.S
@@ -23,7 +23,6 @@ ENTRY(v5tj_early_abort)
 	mrc	p15, 0, r0, c6, c0, 0		@ get FAR
 	bic	r1, r1, #1 << 11 | 1 << 10	@ clear bits 11 and 10 of FSR
 	tst	r3, #PSR_J_BIT			@ Java?
-	orrne	r1, r1, #1 << 11		@ always assume write
 	movne	pc, lr
 	tst	r3, #PSR_T_BIT			@ Thumb?
 	ldrneh	r3, [r2]			@ read aborted thumb instruction
diff --git a/arch/arm/mm/cache-v3.S b/arch/arm/mm/cache-v3.S
index 6659439f6..e1994788c 100644
--- a/arch/arm/mm/cache-v3.S
+++ b/arch/arm/mm/cache-v3.S
@@ -57,6 +57,19 @@ ENTRY(v3_flush_user_cache_range)
  *	- end	 - virtual end address
  */
 ENTRY(v3_coherent_kern_range)
+	/* FALLTHROUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(v3_coherent_user_range)
 	mov	pc, lr
 
 /*
@@ -116,6 +129,7 @@ ENTRY(v3_cache_fns)
 	.long	v3_flush_user_cache_all
 	.long	v3_flush_user_cache_range
 	.long	v3_coherent_kern_range
+	.long	v3_coherent_user_range
 	.long	v3_flush_kern_dcache_page
 	.long	v3_dma_inv_range
 	.long	v3_dma_clean_range
diff --git a/arch/arm/mm/cache-v4.S b/arch/arm/mm/cache-v4.S
index bbc822f16..b8ad5d58e 100644
--- a/arch/arm/mm/cache-v4.S
+++ b/arch/arm/mm/cache-v4.S
@@ -59,6 +59,19 @@ ENTRY(v4_flush_user_cache_range)
  *	- end	 - virtual end address
  */
 ENTRY(v4_coherent_kern_range)
+	/* FALLTHROUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(v4_coherent_user_range)
 	mov	pc, lr
 
 /*
@@ -118,6 +131,7 @@ ENTRY(v4_cache_fns)
 	.long	v4_flush_user_cache_all
 	.long	v4_flush_user_cache_range
 	.long	v4_coherent_kern_range
+	.long	v4_coherent_user_range
 	.long	v4_flush_kern_dcache_page
 	.long	v4_dma_inv_range
 	.long	v4_dma_clean_range
diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S
index 4f7c918e6..5c4055b62 100644
--- a/arch/arm/mm/cache-v4wb.S
+++ b/arch/arm/mm/cache-v4wb.S
@@ -121,6 +121,19 @@ ENTRY(v4wb_flush_kern_dcache_page)
  *	- end	 - virtual end address
  */
 ENTRY(v4wb_coherent_kern_range)
+	/* fall through */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(v4wb_coherent_user_range)
 	bic	r0, r0, #CACHE_DLINESIZE - 1
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	mcr	p15, 0, r0, c7, c6, 1		@ invalidate D entry
@@ -195,6 +208,7 @@ ENTRY(v4wb_cache_fns)
 	.long	v4wb_flush_user_cache_all
 	.long	v4wb_flush_user_cache_range
 	.long	v4wb_coherent_kern_range
+	.long	v4wb_coherent_user_range
 	.long	v4wb_flush_kern_dcache_page
 	.long	v4wb_dma_inv_range
 	.long	v4wb_dma_clean_range
diff --git a/arch/arm/mm/cache-v4wt.S b/arch/arm/mm/cache-v4wt.S
index 61c9fc60f..9bcabd86c 100644
--- a/arch/arm/mm/cache-v4wt.S
+++ b/arch/arm/mm/cache-v4wt.S
@@ -97,6 +97,19 @@ ENTRY(v4wt_flush_user_cache_range)
  *	- end	 - virtual end address
  */
 ENTRY(v4wt_coherent_kern_range)
+	/* FALLTRHOUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ */
+ENTRY(v4wt_coherent_user_range)
 	bic	r0, r0, #CACHE_DLINESIZE - 1
 1:	mcr	p15, 0, r0, c7, c5, 1		@ invalidate I entry
 	add	r0, r0, #CACHE_DLINESIZE
@@ -167,6 +180,7 @@ ENTRY(v4wt_cache_fns)
 	.long	v4wt_flush_user_cache_all
 	.long	v4wt_flush_user_cache_range
 	.long	v4wt_coherent_kern_range
+	.long	v4wt_coherent_user_range
 	.long	v4wt_flush_kern_dcache_page
 	.long	v4wt_dma_inv_range
 	.long	v4wt_dma_clean_range
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S
index 336aa0e40..85c10a71e 100644
--- a/arch/arm/mm/cache-v6.S
+++ b/arch/arm/mm/cache-v6.S
@@ -75,6 +75,22 @@ ENTRY(v6_flush_user_cache_range)
  *	- the Icache does not read data from the write buffer
  */
 ENTRY(v6_coherent_kern_range)
+	/* FALLTHROUGH */
+
+/*
+ *	v6_coherent_user_range(start,end)
+ *
+ *	Ensure that the I and D caches are coherent within specified
+ *	region.  This is typically used when code has been written to
+ *	a memory region, and will be executed.
+ *
+ *	- start   - virtual start address of region
+ *	- end     - virtual end address of region
+ *
+ *	It is assumed that:
+ *	- the Icache does not read data from the write buffer
+ */
+ENTRY(v6_coherent_user_range)
 	bic	r0, r0, #CACHE_LINE_SIZE - 1
 1:
 #ifdef HARVARD_CACHE
@@ -203,6 +219,7 @@ ENTRY(v6_cache_fns)
 	.long	v6_flush_user_cache_all
 	.long	v6_flush_user_cache_range
 	.long	v6_coherent_kern_range
+	.long	v6_coherent_user_range
 	.long	v6_flush_kern_dcache_page
 	.long	v6_dma_inv_range
 	.long	v6_dma_clean_range
diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
index f9b8fe2c7..57b0be2ab 100644
--- a/arch/arm/mm/consistent.c
+++ b/arch/arm/mm/consistent.c
@@ -138,7 +138,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, int gfp,
 	struct page *page;
 	struct vm_region *c;
 	unsigned long order;
-	u64 mask = 0x00ffffff, limit; /* ISA default */
+	u64 mask = ISA_DMA_THRESHOLD, limit;
 
 	if (!consistent_pte) {
 		printk(KERN_ERR "%s: not initialised\n", __func__);
@@ -148,19 +148,34 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, int gfp,
 
 	if (dev) {
 		mask = dev->coherent_dma_mask;
+
+		/*
+		 * Sanity check the DMA mask - it must be non-zero, and
+		 * must be able to be satisfied by a DMA allocation.
+		 */
 		if (mask == 0) {
 			dev_warn(dev, "coherent DMA mask is unset\n");
-			return NULL;
+			goto no_page;
+		}
+
+		if ((~mask) & ISA_DMA_THRESHOLD) {
+			dev_warn(dev, "coherent DMA mask %#llx is smaller "
+				 "than system GFP_DMA mask %#llx\n",
+				 mask, (unsigned long long)ISA_DMA_THRESHOLD);
+			goto no_page;
 		}
 	}
 
+	/*
+	 * Sanity check the allocation size.
+	 */
 	size = PAGE_ALIGN(size);
 	limit = (mask + 1) & ~mask;
-	if ((limit && size >= limit) || size >= (CONSISTENT_END - CONSISTENT_BASE)) {
-		printk(KERN_WARNING "coherent allocation too big (requested %#x mask %#Lx)\n",
-		       size, mask);
-		*handle = ~0;
-		return NULL;
+	if ((limit && size >= limit) ||
+	    size >= (CONSISTENT_END - CONSISTENT_BASE)) {
+		printk(KERN_WARNING "coherent allocation too big "
+		       "(requested %#x mask %#llx)\n", size, mask);
+		goto no_page;
 	}
 
 	order = get_order(size);
@@ -221,6 +236,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, int gfp,
 	if (page)
 		__free_pages(page, order);
  no_page:
+	*handle = ~0;
 	return NULL;
 }
 
diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c
index e6a139ee2..402dad21a 100644
--- a/arch/arm/mm/copypage-v6.c
+++ b/arch/arm/mm/copypage-v6.c
@@ -31,14 +31,46 @@ static spinlock_t v6_lock = SPIN_LOCK_UNLOCKED;
 
 #define DCACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
 
+/*
+ * Copy the user page.  No aliasing to deal with so we can just
+ * attack the kernel's existing mapping of these pages.
+ */
+void v6_copy_user_page_nonaliasing(void *kto, const void *kfrom, unsigned long vaddr)
+{
+	copy_page(kto, kfrom);
+}
+
+/*
+ * Clear the user page.  No aliasing to deal with so we can just
+ * attack the kernel's existing mapping of this page.
+ */
+void v6_clear_user_page_nonaliasing(void *kaddr, unsigned long vaddr)
+{
+	clear_page(kaddr);
+}
+
 /*
  * Copy the page, taking account of the cache colour.
  */
-void v6_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr)
+void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vaddr)
 {
 	unsigned int offset = DCACHE_COLOUR(vaddr);
 	unsigned long from, to;
 
+	/*
+	 * Discard data in the kernel mapping for the new page.
+	 * FIXME: needs this MCRR to be supported.
+	 */
+	__asm__("mcrr	p15, 0, %1, %0, c6	@ 0xec401f06"
+	   :
+	   : "r" (kto),
+	     "r" ((unsigned long)kto + PAGE_SIZE - L1_CACHE_BYTES)
+	   : "cc");
+
+	/*
+	 * Now copy the page using the same cache colour as the
+	 * pages ultimate destination.
+	 */
 	spin_lock(&v6_lock);
 
 	set_pte(from_pte + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, from_pgprot));
@@ -55,11 +87,30 @@ void v6_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr)
 	spin_unlock(&v6_lock);
 }
 
-void v6_clear_user_page(void *kaddr, unsigned long vaddr)
+/*
+ * Clear the user page.  We need to deal with the aliasing issues,
+ * so remap the kernel page into the same cache colour as the user
+ * page.
+ */
+void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr)
 {
 	unsigned int offset = DCACHE_COLOUR(vaddr);
 	unsigned long to = to_address + (offset << PAGE_SHIFT);
 
+	/*
+	 * Discard data in the kernel mapping for the new page
+	 * FIXME: needs this MCRR to be supported.
+	 */
+	__asm__("mcrr	p15, 0, %1, %0, c6	@ 0xec401f06"
+	   :
+	   : "r" (kaddr),
+	     "r" ((unsigned long)kaddr + PAGE_SIZE - L1_CACHE_BYTES)
+	   : "cc");
+
+	/*
+	 * Now clear the page using the same cache colour as
+	 * the pages ultimate destination.
+	 */
 	spin_lock(&v6_lock);
 
 	set_pte(to_pte + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, to_pgprot));
@@ -70,26 +121,31 @@ void v6_clear_user_page(void *kaddr, unsigned long vaddr)
 }
 
 struct cpu_user_fns v6_user_fns __initdata = {
-	.cpu_clear_user_page	= v6_clear_user_page,
-	.cpu_copy_user_page	= v6_copy_user_page,
+	.cpu_clear_user_page	= v6_clear_user_page_nonaliasing,
+	.cpu_copy_user_page	= v6_copy_user_page_nonaliasing,
 };
 
 static int __init v6_userpage_init(void)
 {
-	pgd_t *pgd;
-	pmd_t *pmd;
-
-	pgd = pgd_offset_k(from_address);
-	pmd = pmd_alloc(&init_mm, pgd, from_address);
-	if (!pmd)
-		BUG();
-	from_pte = pte_alloc_kernel(&init_mm, pmd, from_address);
-	if (!from_pte)
-		BUG();
-
-	to_pte = pte_alloc_kernel(&init_mm, pmd, to_address);
-	if (!to_pte)
-		BUG();
+	if (cache_is_vipt_aliasing()) {
+		pgd_t *pgd;
+		pmd_t *pmd;
+
+		pgd = pgd_offset_k(from_address);
+		pmd = pmd_alloc(&init_mm, pgd, from_address);
+		if (!pmd)
+			BUG();
+		from_pte = pte_alloc_kernel(&init_mm, pmd, from_address);
+		if (!from_pte)
+			BUG();
+
+		to_pte = pte_alloc_kernel(&init_mm, pmd, to_address);
+		if (!to_pte)
+			BUG();
+
+		cpu_user.cpu_clear_user_page = v6_clear_user_page_aliasing;
+		cpu_user.cpu_copy_user_page = v6_copy_user_page_aliasing;
+	}
 
 	return 0;
 }
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index d03940c1b..5f0a79094 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -76,59 +76,12 @@ no_pmd:
 	return 0;
 }
 
-static void __flush_dcache_page(struct page *page)
-{
-	struct address_space *mapping = page_mapping(page);
-	struct mm_struct *mm = current->active_mm;
-	struct vm_area_struct *mpnt = NULL;
-	struct prio_tree_iter iter;
-	unsigned long offset;
-	pgoff_t pgoff;
-
-	__cpuc_flush_dcache_page(page_address(page));
-
-	if (!mapping)
-		return;
-
-	/*
-	 * With a VIVT cache, we need to also write back
-	 * and invalidate any user data.
-	 */
-	pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
-
-	flush_dcache_mmap_lock(mapping);
-	while ((mpnt = vma_prio_tree_next(mpnt, &mapping->i_mmap,
-					&iter, pgoff, pgoff)) != NULL) {
-		/*
-		 * If this VMA is not in our MM, we can ignore it.
-		 */
-		if (mpnt->vm_mm != mm)
-			continue;
-		if (!(mpnt->vm_flags & VM_MAYSHARE))
-			continue;
-		offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
-		flush_cache_page(mpnt, mpnt->vm_start + offset);
-	}
-	flush_dcache_mmap_unlock(mapping);
-}
-
-void flush_dcache_page(struct page *page)
-{
-	struct address_space *mapping = page_mapping(page);
-
-	if (mapping && !mapping_mapped(mapping))
-		set_bit(PG_dcache_dirty, &page->flags);
-	else
-		__flush_dcache_page(page);
-}
-EXPORT_SYMBOL(flush_dcache_page);
-
 static void
 make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, int dirty)
 {
 	struct address_space *mapping = page_mapping(page);
 	struct mm_struct *mm = vma->vm_mm;
-	struct vm_area_struct *mpnt = NULL;
+	struct vm_area_struct *mpnt;
 	struct prio_tree_iter iter;
 	unsigned long offset;
 	pgoff_t pgoff;
@@ -145,8 +98,7 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page,
 	 * cache coherency.
 	 */
 	flush_dcache_mmap_lock(mapping);
-	while ((mpnt = vma_prio_tree_next(mpnt, &mapping->i_mmap,
-					&iter, pgoff, pgoff)) != NULL) {
+	vma_prio_tree_foreach(mpnt, &iter, &mapping->i_mmap, pgoff, pgoff) {
 		/*
 		 * If this VMA is not in our MM, we can ignore it.
 		 * Note that we intentionally mask out the VMA
@@ -190,10 +142,21 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
 	if (page_mapping(page)) {
 		int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
 
-		if (dirty)
+		if (dirty) {
+			/*
+			 * This is our first userspace mapping of this page.
+			 * Ensure that the physical page is coherent with
+			 * the kernel mapping.
+			 *
+			 * FIXME: only need to do this on VIVT and aliasing
+			 *        VIPT cache architectures.  We can do that
+			 *	  by choosing whether to set this bit...
+			 */
 			__cpuc_flush_dcache_page(page_address(page));
+		}
 
-		make_coherent(vma, addr, page, dirty);
+		if (cache_is_vivt())
+			make_coherent(vma, addr, page, dirty);
 	}
 }
 
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 060fea2e1..d7b4441ac 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -14,6 +14,7 @@
 #include <linux/swap.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
+#include <linux/mman.h>
 #include <linux/initrd.h>
 
 #include <asm/mach-types.h>
@@ -344,7 +345,7 @@ static inline void free_bootmem_node_bank(int node, struct meminfo *mi)
  * Initialise the bootmem allocator for all nodes.  This is called
  * early during the architecture specific initialisation.
  */
-void __init bootmem_init(struct meminfo *mi)
+static void __init bootmem_init(struct meminfo *mi)
 {
 	struct node_info node_info[MAX_NUMNODES], *np = node_info;
 	unsigned int bootmap_pages, bootmap_pfn, map_pg;
@@ -412,9 +413,7 @@ void __init bootmem_init(struct meminfo *mi)
 	}
 #endif
 
-	if (map_pg != bootmap_pfn + bootmap_pages)
-		BUG();
-
+	BUG_ON(map_pg != bootmap_pfn + bootmap_pages);
 }
 
 /*
@@ -426,6 +425,8 @@ void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc)
 	void *zero_page;
 	int node;
 
+	bootmem_init(mi);
+
 	memcpy(&meminfo, mi, sizeof(meminfo));
 
 	/*
@@ -495,7 +496,7 @@ void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc)
 		 */
 		arch_adjust_zones(node, zone_size, zhole_size);
 
-		free_area_init_node(node, pgdat, NULL, zone_size,
+		free_area_init_node(node, pgdat, zone_size,
 				bdata->node_boot_start >> PAGE_SHIFT, zhole_size);
 	}
 
@@ -590,7 +591,7 @@ void __init mem_init(void)
 		 * anywhere without overcommit, so turn
 		 * it on by default.
 		 */
-		sysctl_overcommit_memory = 1;
+		sysctl_overcommit_memory = OVERCOMMIT_ALWAYS;
 	}
 }
 
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
index 7fe21a95d..1267ab586 100644
--- a/arch/arm/mm/proc-arm1020.S
+++ b/arch/arm/mm/proc-arm1020.S
@@ -196,6 +196,19 @@ ENTRY(arm1020_flush_user_cache_range)
  *	- end	- virtual end address
  */
 ENTRY(arm1020_coherent_kern_range)
+	/* FALLTRHOUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm1020_coherent_user_range)
 	mov	ip, #0
 	bic	r0, r0, #CACHE_DLINESIZE - 1
 	mcr	p15, 0, ip, c7, c10, 4
@@ -317,6 +330,7 @@ ENTRY(arm1020_cache_fns)
 	.long	arm1020_flush_user_cache_all
 	.long	arm1020_flush_user_cache_range
 	.long	arm1020_coherent_kern_range
+	.long	arm1020_coherent_user_range
 	.long	arm1020_flush_kern_dcache_page
 	.long	arm1020_dma_inv_range
 	.long	arm1020_dma_clean_range
diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
index 0332c3e69..947790dd3 100644
--- a/arch/arm/mm/proc-arm1020e.S
+++ b/arch/arm/mm/proc-arm1020e.S
@@ -193,6 +193,18 @@ ENTRY(arm1020e_flush_user_cache_range)
  *	- end	- virtual end address
  */
 ENTRY(arm1020e_coherent_kern_range)
+	/* FALLTHROUGH */
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm1020e_coherent_user_range)
 	mov	ip, #0
 	bic	r0, r0, #CACHE_DLINESIZE - 1
 1:
@@ -304,6 +316,7 @@ ENTRY(arm1020e_cache_fns)
 	.long	arm1020e_flush_user_cache_all
 	.long	arm1020e_flush_user_cache_range
 	.long	arm1020e_coherent_kern_range
+	.long	arm1020e_coherent_user_range
 	.long	arm1020e_flush_kern_dcache_page
 	.long	arm1020e_dma_inv_range
 	.long	arm1020e_dma_clean_range
@@ -495,7 +508,7 @@ __arm1020e_proc_info:
 	b	__arm1020e_setup
 	.long	cpu_arch_name
 	.long	cpu_elf_name
-	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
+	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_EDSP
 	.long	cpu_arm1020e_name
 	.long	arm1020e_processor_functions
 	.long	v4wbi_tlb_fns
diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
index 35a5c2f00..7c8426384 100644
--- a/arch/arm/mm/proc-arm1022.S
+++ b/arch/arm/mm/proc-arm1022.S
@@ -180,6 +180,19 @@ ENTRY(arm1022_flush_user_cache_range)
  *	- end	- virtual end address
  */
 ENTRY(arm1022_coherent_kern_range)
+	/* FALLTHROUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm1022_coherent_user_range)
 	mov	ip, #0
 	bic	r0, r0, #CACHE_DLINESIZE - 1
 1:
@@ -291,6 +304,7 @@ ENTRY(arm1022_cache_fns)
 	.long	arm1022_flush_user_cache_all
 	.long	arm1022_flush_user_cache_range
 	.long	arm1022_coherent_kern_range
+	.long	arm1022_coherent_user_range
 	.long	arm1022_flush_kern_dcache_page
 	.long	arm1022_dma_inv_range
 	.long	arm1022_dma_clean_range
@@ -475,7 +489,7 @@ __arm1022_proc_info:
 	b	__arm1022_setup
 	.long	cpu_arch_name
 	.long	cpu_elf_name
-	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB
+	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_EDSP
 	.long	cpu_arm1022_name
 	.long	arm1022_processor_functions
 	.long	v4wbi_tlb_fns
diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
index 0009f2d27..38a06cb1e 100644
--- a/arch/arm/mm/proc-arm1026.S
+++ b/arch/arm/mm/proc-arm1026.S
@@ -175,6 +175,18 @@ ENTRY(arm1026_flush_user_cache_range)
  *	- end	- virtual end address
  */
 ENTRY(arm1026_coherent_kern_range)
+	/* FALLTHROUGH */
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm1026_coherent_user_range)
 	mov	ip, #0
 	bic	r0, r0, #CACHE_DLINESIZE - 1
 1:
@@ -286,6 +298,7 @@ ENTRY(arm1026_cache_fns)
 	.long	arm1026_flush_user_cache_all
 	.long	arm1026_flush_user_cache_range
 	.long	arm1026_coherent_kern_range
+	.long	arm1026_coherent_user_range
 	.long	arm1026_flush_kern_dcache_page
 	.long	arm1026_dma_inv_range
 	.long	arm1026_dma_clean_range
@@ -471,7 +484,7 @@ __arm1026_proc_info:
 	b	__arm1026_setup
 	.long	cpu_arch_name
 	.long	cpu_elf_name
-	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_FAST_MULT
+	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_JAVA
 	.long	cpu_arm1026_name
 	.long	arm1026_processor_functions
 	.long	v4wbi_tlb_fns
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index 3922a8213..8c9204a7c 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -182,6 +182,19 @@ ENTRY(arm920_flush_user_cache_range)
  *	- end	- virtual end address
  */
 ENTRY(arm920_coherent_kern_range)
+	/* FALLTHROUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start, end.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm920_coherent_user_range)
 	bic	r0, r0, #CACHE_DLINESIZE - 1
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	mcr	p15, 0, r0, c7, c5, 1		@ invalidate I entry
@@ -277,6 +290,7 @@ ENTRY(arm920_cache_fns)
 	.long	arm920_flush_user_cache_all
 	.long	arm920_flush_user_cache_range
 	.long	arm920_coherent_kern_range
+	.long	arm920_coherent_user_range
 	.long	arm920_flush_kern_dcache_page
 	.long	arm920_dma_inv_range
 	.long	arm920_dma_clean_range
diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
index 86065117c..13e65cb8a 100644
--- a/arch/arm/mm/proc-arm922.S
+++ b/arch/arm/mm/proc-arm922.S
@@ -184,6 +184,19 @@ ENTRY(arm922_flush_user_cache_range)
  *	- end	- virtual end address
  */
 ENTRY(arm922_coherent_kern_range)
+	/* FALLTHROUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start, end.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm922_coherent_user_range)
 	bic	r0, r0, #CACHE_DLINESIZE - 1
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	mcr	p15, 0, r0, c7, c5, 1		@ invalidate I entry
@@ -279,6 +292,7 @@ ENTRY(arm922_cache_fns)
 	.long	arm922_flush_user_cache_all
 	.long	arm922_flush_user_cache_range
 	.long	arm922_coherent_kern_range
+	.long	arm922_coherent_user_range
 	.long	arm922_flush_kern_dcache_page
 	.long	arm922_dma_inv_range
 	.long	arm922_dma_clean_range
diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
index 917eb5e16..e8b3ff1fb 100644
--- a/arch/arm/mm/proc-arm925.S
+++ b/arch/arm/mm/proc-arm925.S
@@ -225,6 +225,19 @@ ENTRY(arm925_flush_user_cache_range)
  *	- end	- virtual end address
  */
 ENTRY(arm925_coherent_kern_range)
+	/* FALLTHROUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start, end.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm925_coherent_user_range)
 	bic	r0, r0, #CACHE_DLINESIZE - 1
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	mcr	p15, 0, r0, c7, c5, 1		@ invalidate I entry
@@ -329,6 +342,7 @@ ENTRY(arm925_cache_fns)
 	.long	arm925_flush_user_cache_all
 	.long	arm925_flush_user_cache_range
 	.long	arm925_coherent_kern_range
+	.long	arm925_coherent_user_range
 	.long	arm925_flush_kern_dcache_page
 	.long	arm925_dma_inv_range
 	.long	arm925_dma_clean_range
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index 9b098e05c..5631c8bbd 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -185,6 +185,19 @@ ENTRY(arm926_flush_user_cache_range)
  *	- end	- virtual end address
  */
 ENTRY(arm926_coherent_kern_range)
+	/* FALLTHROUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start, end.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start	- virtual start address
+ *	- end	- virtual end address
+ */
+ENTRY(arm926_coherent_user_range)
 	bic	r0, r0, #CACHE_DLINESIZE - 1
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	mcr	p15, 0, r0, c7, c5, 1		@ invalidate I entry
@@ -289,6 +302,7 @@ ENTRY(arm926_cache_fns)
 	.long	arm926_flush_user_cache_all
 	.long	arm926_flush_user_cache_range
 	.long	arm926_coherent_kern_range
+	.long	arm926_coherent_user_range
 	.long	arm926_flush_kern_dcache_page
 	.long	arm926_dma_inv_range
 	.long	arm926_dma_clean_range
@@ -473,7 +487,7 @@ __arm926_proc_info:
 	b	__arm926_setup
 	.long	cpu_arch_name
 	.long	cpu_elf_name
-	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_FAST_MULT | HWCAP_JAVA
+	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_JAVA
 	.long	cpu_arm926_name
 	.long	arm926_processor_functions
 	.long	v4wbi_tlb_fns
diff --git a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c
index 8df666f8d..6c5f0fe57 100644
--- a/arch/arm/mm/proc-syms.c
+++ b/arch/arm/mm/proc-syms.c
@@ -22,10 +22,10 @@ EXPORT_SYMBOL(processor);
 #endif
 
 #ifndef MULTI_CACHE
-EXPORT_SYMBOL_NOVERS(__cpuc_flush_kern_all);
-EXPORT_SYMBOL_NOVERS(__cpuc_flush_user_all);
-EXPORT_SYMBOL_NOVERS(__cpuc_flush_user_range);
-EXPORT_SYMBOL_NOVERS(__cpuc_coherent_kern_range);
+EXPORT_SYMBOL(__cpuc_flush_kern_all);
+EXPORT_SYMBOL(__cpuc_flush_user_all);
+EXPORT_SYMBOL(__cpuc_flush_user_range);
+EXPORT_SYMBOL(__cpuc_coherent_kern_range);
 #else
 EXPORT_SYMBOL(cpu_cache);
 #endif
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index c22cc3601..0a4ff2624 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -189,12 +189,10 @@ cpu_v6_name:
  *	- cache type register is implemented
  */
 __v6_setup:
-	mrc	p15, 0, r10, c0, c0, 1		@ read cache type register
-	tst	r10, #1 << 24			@ Harvard cache?
 	mov	r10, #0
-	mcrne	p15, 0, r10, c7, c14, 0		@ clean+invalidate D cache
-	mcrne	p15, 0, r10, c7, c5, 0		@ invalidate I cache
-	mcreq	p15, 0, r10, c7, c15, 0		@ clean+invalidate cache
+	mcr	p15, 0, r10, c7, c14, 0		@ clean+invalidate D cache
+	mcr	p15, 0, r10, c7, c5, 0		@ invalidate I cache
+	mcr	p15, 0, r10, c7, c15, 0		@ clean+invalidate cache
 	mcr	p15, 0, r10, c7, c10, 4		@ drain write buffer
 	mcr	p15, 0, r10, c8, c7, 0		@ invalidate I + D TLBs
 	mcr	p15, 0, r10, c2, c0, 2		@ TTB control register
@@ -258,7 +256,7 @@ __v6_proc_info:
 	b	__v6_setup
 	.long	cpu_arch_name
 	.long	cpu_elf_name
-	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_FAST_MULT | HWCAP_VFP
+	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_VFP|HWCAP_EDSP|HWCAP_JAVA
 	.long	cpu_v6_name
 	.long	v6_processor_functions
 	.long	v6wbi_tlb_fns
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index 2652d141f..2be02f7f5 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -241,6 +241,22 @@ ENTRY(xscale_flush_user_cache_range)
  *	it also trashes the mini I-cache used by JTAG debuggers.
  */
 ENTRY(xscale_coherent_kern_range)
+	/* FALLTHROUGH */
+
+/*
+ *	coherent_user_range(start, end)
+ *
+ *	Ensure coherency between the Icache and the Dcache in the
+ *	region described by start.  If you have non-snooping
+ *	Harvard caches, you need to implement this function.
+ *
+ *	- start  - virtual start address
+ *	- end	 - virtual end address
+ *
+ *	Note: single I-cache line invalidation isn't used here since
+ *	it also trashes the mini I-cache used by JTAG debuggers.
+ */
+ENTRY(xscale_coherent_user_range)
 	bic	r0, r0, #CACHELINESIZE - 1
 1:	mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 	add	r0, r0, #CACHELINESIZE
@@ -341,6 +357,7 @@ ENTRY(xscale_cache_fns)
 	.long	xscale_flush_user_cache_all
 	.long	xscale_flush_user_cache_range
 	.long	xscale_coherent_kern_range
+	.long	xscale_coherent_user_range
 	.long	xscale_flush_kern_dcache_page
 	.long	xscale_dma_inv_range
 	.long	xscale_dma_clean_range
@@ -585,7 +602,12 @@ __xscale_setup:
 	mcr	p15, 0, r4, c2, c0, 0		@ load page table pointer
 	mov	r0, #0x1f			@ Domains 0, 1 = client
 	mcr	p15, 0, r0, c3, c0, 0		@ load domain access register
-	mov	r0, #1				@ Allow access to CP0 and CP13
+#ifdef CONFIG_IWMMXT
+	mov	r0, #0				@ initially disallow access to CP0/CP1
+#else
+	mov	r0, #1				@ Allow access to CP0
+#endif
+	orr     r0, r0, #1 << 6			@ cp6 for IOP3xx and Bulverde
 	orr	r0, r0, #1 << 13		@ Its undefined whether this
 	mcr	p15, 0, r0, c15, c1, 0		@ affects USR or SVC modes
 	mrc	p15, 0, r0, c1, c0, 0		@ get control register
@@ -632,10 +654,15 @@ cpu_80200_name:
 	.asciz	"XScale-80200"
 	.size	cpu_80200_name, . - cpu_80200_name
 
-	.type	cpu_80321_name, #object
-cpu_80321_name:
-	.asciz	"XScale-IOP80321"
-	.size	cpu_80321_name, . - cpu_80321_name
+	.type	cpu_8032x_name, #object
+cpu_8032x_name:
+	.asciz	"XScale-IOP8032x Family"
+	.size	cpu_8032x_name, . - cpu_8032x_name
+
+	.type	cpu_8033x_name, #object
+cpu_8033x_name:
+	.asciz	"XScale-IOP8033x Family"
+	.size	cpu_8033x_name, . - cpu_8033x_name
 
 	.type	cpu_pxa250_name, #object
 cpu_pxa250_name:
@@ -652,6 +679,16 @@ cpu_ixp42x_name:
 	.asciz	"XScale-IXP42x Family"
 	.size	cpu_ixp42x_name, . - cpu_ixp42x_name
 
+	.type	cpu_ixp2400_name, #object
+cpu_ixp2400_name:
+	.asciz	"XScale-IXP2400"
+	.size	cpu_ixp2400_name, . - cpu_ixp2400_name
+
+	.type	cpu_ixp2800_name, #object
+cpu_ixp2800_name:
+	.asciz	"XScale-IXP2800"
+	.size	cpu_ixp2800_name, . - cpu_ixp2800_name
+
 	.type	cpu_pxa255_name, #object
 cpu_pxa255_name:
 	.asciz	"XScale-PXA255"
@@ -682,21 +719,37 @@ __80200_proc_info:
 	.long	xscale_cache_fns
 	.size	__80200_proc_info, . - __80200_proc_info
 
-	.type	__80321_proc_info,#object
-__80321_proc_info:
+	.type	__8032x_proc_info,#object
+__8032x_proc_info:
 	.long	0x69052420
-	.long	0xfffff7e0
+	.long	0xfffff5e0      @ mask should accomodate IOP80219 also
+	.long	0x00000c0e
+	b	__xscale_setup
+	.long	cpu_arch_name
+	.long	cpu_elf_name
+	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+	.long	cpu_8032x_name
+	.long	xscale_processor_functions
+	.long	v4wbi_tlb_fns
+	.long	xscale_mc_user_fns
+	.long	xscale_cache_fns
+	.size	__8032x_proc_info, . - __8032x_proc_info
+
+	.type	__8033x_proc_info,#object
+__8033x_proc_info:
+	.long	0x69054090
+	.long	0xffffffb0
 	.long	0x00000c0e
 	b	__xscale_setup
 	.long	cpu_arch_name
 	.long	cpu_elf_name
 	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
-	.long	cpu_80321_name
+	.long	cpu_8033x_name
 	.long	xscale_processor_functions
 	.long	v4wbi_tlb_fns
 	.long	xscale_mc_user_fns
 	.long	xscale_cache_fns
-	.size	__80321_proc_info, . - __80321_proc_info
+	.size	__8033x_proc_info, . - __8033x_proc_info
 
 	.type	__pxa250_proc_info,#object
 __pxa250_proc_info:
@@ -730,6 +783,38 @@ __pxa210_proc_info:
 	.long	xscale_cache_fns
 	.size	__pxa210_proc_info, . - __pxa210_proc_info
 
+	.type	__ixp2400_proc_info, #object
+__ixp2400_proc_info:
+	.long   0x69054190
+	.long   0xfffffff0
+	.long   0x00000c0e
+	b       __xscale_setup
+	.long   cpu_arch_name
+	.long   cpu_elf_name
+	.long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+	.long   cpu_ixp2400_name
+	.long   xscale_processor_functions
+	.long	v4wbi_tlb_fns
+	.long	xscale_mc_user_fns
+	.long	xscale_cache_fns
+	.size   __ixp2400_proc_info, . - __ixp2400_proc_info                
+
+	.type	__ixp2800_proc_info, #object
+__ixp2800_proc_info:
+	.long   0x690541a0
+	.long   0xfffffff0
+	.long   0x00000c0e
+	b       __xscale_setup
+	.long   cpu_arch_name
+	.long   cpu_elf_name
+	.long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+	.long   cpu_ixp2800_name
+	.long   xscale_processor_functions
+	.long	v4wbi_tlb_fns
+	.long	xscale_mc_user_fns
+	.long	xscale_cache_fns
+	.size   __ixp2800_proc_info, . - __ixp2800_proc_info                
+
 	.type	__ixp42x_proc_info, #object
 __ixp42x_proc_info:
 	.long   0x690541c0
diff --git a/arch/arm/nwfpe/fpa11_cpdt.c b/arch/arm/nwfpe/fpa11_cpdt.c
index 2ad457558..95fb63fa9 100644
--- a/arch/arm/nwfpe/fpa11_cpdt.c
+++ b/arch/arm/nwfpe/fpa11_cpdt.c
@@ -42,8 +42,13 @@ static inline void loadDouble(const unsigned int Fn, const unsigned int __user *
 	unsigned int *p;
 	p = (unsigned int *) &fpa11->fpreg[Fn].fDouble;
 	fpa11->fType[Fn] = typeDouble;
+#ifdef __ARMEB__
+	get_user(p[0], &pMem[0]);	/* sign & exponent */
+	get_user(p[1], &pMem[1]);
+#else
 	get_user(p[0], &pMem[1]);
 	get_user(p[1], &pMem[0]);	/* sign & exponent */
+#endif
 }
 
 #ifdef CONFIG_FPE_NWFPE_XP
@@ -140,8 +145,13 @@ static inline void storeDouble(const unsigned int Fn, unsigned int __user *pMem)
 		val.f = fpa11->fpreg[Fn].fDouble;
 	}
 
+#ifdef __ARMEB__
+	put_user(val.i[0], &pMem[0]);	/* msw */
+	put_user(val.i[1], &pMem[1]);	/* lsw */
+#else
 	put_user(val.i[1], &pMem[0]);	/* msw */
 	put_user(val.i[0], &pMem[1]);	/* lsw */
+#endif
 }
 
 #ifdef CONFIG_FPE_NWFPE_XP
diff --git a/arch/arm/oprofile/op_model_xscale.c b/arch/arm/oprofile/op_model_xscale.c
index 284874be3..447653df1 100644
--- a/arch/arm/oprofile/op_model_xscale.c
+++ b/arch/arm/oprofile/op_model_xscale.c
@@ -7,7 +7,7 @@
  * @remark Copyright 2004 Dave Jiang <dave.jiang@intel.com>
  * @remark Copyright 2004 Intel Corporation
  * @remark Copyright 2004 Zwane Mwaikambo <zwane@arm.linux.org.uk>
- * @remark Copyright 2004 Oprofile Authors
+ * @remark Copyright 2004 OProfile Authors
  *
  * @remark Read the file COPYING
  *
@@ -30,6 +30,7 @@
 #define PMN_RESET	0x002	/* Reset event counters */
 #define	CCNT_RESET	0x004	/* Reset clock counter */
 #define	PMU_RESET	(CCNT_RESET | PMN_RESET)
+#define PMU_CNT64	0x008	/* Make CCNT count every 64th cycle */
 
 /* TODO do runtime detection */
 #ifdef CONFIG_ARCH_IOP310
@@ -125,12 +126,15 @@ static struct pmu_type *pmu;
 
 static void write_pmnc(u32 val)
 {
-	/* upper 4bits and 7, 11 are write-as-0 */
-	val &= 0xffff77f;
-	if (pmu->id == PMU_XSC1)
+	if (pmu->id == PMU_XSC1) {
+		/* upper 4bits and 7, 11 are write-as-0 */
+		val &= 0xffff77f;
 		__asm__ __volatile__ ("mcr p14, 0, %0, c0, c0, 0" : : "r" (val));
-	else
+	} else {
+		/* bits 4-23 are write-as-0, 24-31 are write ignored */
+		val &= 0xf;
 		__asm__ __volatile__ ("mcr p14, 0, %0, c0, c1, 0" : : "r" (val));
+	}
 }
 
 static u32 read_pmnc(void)
@@ -139,8 +143,11 @@ static u32 read_pmnc(void)
 
 	if (pmu->id == PMU_XSC1)
 		__asm__ __volatile__ ("mrc p14, 0, %0, c0, c0, 0" : "=r" (val));
-	else
+	else {
 		__asm__ __volatile__ ("mrc p14, 0, %0, c0, c1, 0" : "=r" (val));
+		/* bits 1-2 and 4-23 are read-unpredictable */
+		val &= 0xff000009;
+	}
 
 	return val;
 }
@@ -249,7 +256,7 @@ static int xscale_setup_ctrs(void)
 	int i;
 
 	for (i = CCNT; i < MAX_COUNTERS; i++) {
-		if (counter_config[i].event)
+		if (counter_config[i].enabled)
 			continue;
 
 		counter_config[i].event = EVT_UNUSED;
@@ -336,7 +343,7 @@ static void inline __xsc2_check_ctrs(void)
 
 static irqreturn_t xscale_pmu_interrupt(int irq, void *arg, struct pt_regs *regs)
 {
-	unsigned long eip = instruction_pointer(regs);
+	unsigned long pc = profile_pc(regs);
 	int i, is_kernel = !user_mode(regs);
 	u32 pmnc;
 
@@ -350,7 +357,7 @@ static irqreturn_t xscale_pmu_interrupt(int irq, void *arg, struct pt_regs *regs
 			continue;
 
 		write_counter(i, -(u32)results[i].reset_counter);
-		oprofile_add_sample(eip, is_kernel, i, smp_processor_id());
+		oprofile_add_sample(pc, is_kernel, i, smp_processor_id());
 		results[i].ovf--;
 	}
 
@@ -386,8 +393,10 @@ static int xscale_pmu_start(void)
 
 	if (pmu->id == PMU_XSC1)
 		pmnc |= pmu->int_enable;
-	else
+	else {
 		__asm__ __volatile__ ("mcr p14, 0, %0, c4, c1, 0" : : "r" (pmu->int_enable));
+		pmnc &= ~PMU_CNT64;
+	}
 
 	pmnc |= PMU_ENABLE;
 	write_pmnc(pmnc);
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index d2ce22372..4df5b0f30 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -6,7 +6,7 @@
 # To add an entry into this database, please see Documentation/arm/README,
 # or contact rmk@arm.linux.org.uk
 #
-# Last update: Fri Jul 2 11:58:36 2004
+# Last update: Thu Sep 30 15:23:21 2004
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -519,7 +519,7 @@ scb9328			MACH_SCB9328		SCB9328			508
 omap_h3			MACH_OMAP_H3		OMAP_H3			509
 omap_h4			MACH_OMAP_H4		OMAP_H4			510
 n10			MACH_N10		N10			511
-montajade		MACH_MONTAJADE		MONTAJADE		512
+montejade		MACH_MONTAJADE		MONTAJADE		512
 sg560			MACH_SG560		SG560			513
 dp1000			MACH_DP1000		DP1000			514
 omap_osk		MACH_OMAP_OSK		OMAP_OSK		515
@@ -559,3 +559,59 @@ lpc2294			MACH_LPC2294		LPC2294			548
 switchgrass		MACH_SWITCHGRASS	SWITCHGRASS		549
 ens_cmu			MACH_ENS_CMU		ENS_CMU			550
 mm6_sdb			MACH_MM6_SDB		MM6_SDB			551
+saturn			MACH_SATURN		SATURN			552
+argonplusevb		MACH_ARGONPLUSEVB	ARGONPLUSEVB		553
+scma11evb		MACH_SCMA11EVB		SCMA11EVB		554
+smdk2800		MACH_SMDK2800		SMDK2800		555
+mtwilson		MACH_MTWILSON		MTWILSON		556
+ziti			MACH_ZITI		ZITI			557
+grandfather		MACH_GRANDFATHER	GRANDFATHER		558
+tengine			MACH_TENGINE		TENGINE			559
+s3c2460			MACH_S3C2460		S3C2460			560
+pdm			MACH_PDM		PDM			561
+h4700			MACH_H4700		H4700			562
+h6300			MACH_H6300		H6300			563
+rz1700			MACH_RZ1700		RZ1700			564
+a716			MACH_A716		A716			565
+estk2440a		MACH_ESTK2440A		ESTK2440A		566
+atwixp425		MACH_ATWIXP425		ATWIXP425		567
+csb336			MACH_CSB336		CSB336			568
+rirm2			MACH_RIRM2		RIRM2			569
+cx23518			MACH_CX23518		CX23518			570
+cx2351x			MACH_CX2351X		CX2351X			571
+computime		MACH_COMPUTIME		COMPUTIME		572
+izarus			MACH_IZARUS		IZARUS			573
+pxa_rts			MACH_RTS		RTS			574
+se5100			MACH_SE5100		SE5100			575
+s3c2510			MACH_S3C2510		S3C2510			576
+csb437tl		MACH_CSB437TL		CSB437TL		577
+slauson			MACH_SLAUSON		SLAUSON			578
+pearlriver		MACH_PEARLRIVER		PEARLRIVER		579
+tdc_p210		MACH_TDC_P210		TDC_P210		580
+sg580			MACH_SG580		SG580			581
+wrsbcarm7		MACH_WRSBCARM7		WRSBCARM7		582
+ipd			MACH_IPD		IPD			583
+pxa_dnp2110		MACH_PXA_DNP2110	PXA_DNP2110		584
+xaeniax			MACH_XAENIAX		XAENIAX			585
+somn4250		MACH_SOMN4250		SOMN4250		586
+pleb2			MACH_PLEB2		PLEB2			587
+cwl			MACH_CWL		CWL			588
+gd			MACH_GD			GD			589
+chaffee			MACH_CHAFFEE		CHAFFEE			590
+rms101			MACH_RMS101		RMS101			591
+rx3715			MACH_RX3715		RX3715			592
+swift			MACH_SWIFT		SWIFT			593
+roverp7			MACH_ROVERP7		ROVERP7			594
+pr818s			MACH_PR818S		PR818S			595
+trxpro			MACH_TRXPRO		TRXPRO			596
+nslu2			MACH_NSLU2		NSLU2			597
+e400			MACH_E400		E400			598
+trab			MACH_TRAB		TRAB			599
+cmc_pu2			MACH_CMC_PU2		CMC_PU2			600
+fulcrum			MACH_FULCRUM		FULCRUM			601
+netgate42x		MACH_NETGATE42X		NETGATE42X		602
+str710			MACH_STR710		STR710			603
+ixdpg425		MACH_IXDPG425		IXDPG425		604
+tomtomgo		MACH_TOMTOMGO		TOMTOMGO		605
+versatile_ab		MACH_VERSATILE_AB	VERSATILE_AB		606
+edb9307			MACH_EDB9307		EDB9307			607
diff --git a/arch/arm26/Kconfig b/arch/arm26/Kconfig
index b40758b9f..500780d9d 100644
--- a/arch/arm26/Kconfig
+++ b/arch/arm26/Kconfig
@@ -62,7 +62,7 @@ config ARCH_ARC
         bool "Archimedes"
         help
           Say Y to support the Acorn Archimedes.
-	  
+
 	  The Acorn Archimedes was an personal computer based on an 8MHz ARM2
           processor, released in 1987.  It supported up to 16MB of RAM in
 	  later models and floppy, harddisc, ethernet etc.
@@ -71,7 +71,7 @@ config ARCH_A5K
         bool "A5000"
         help
           Say Y here to to support the Acorn A5000.
-	  
+
 	  Linux can support the
           internal IDE disk and CD-ROM interface, serial and parallel port,
           and the floppy drive.  Note that on some A5000s the floppy is
@@ -214,118 +214,7 @@ source "drivers/misc/Kconfig"
 
 source "drivers/usb/Kconfig"
 
-menu "Kernel hacking"
-
-# RMK wants arm kernels compiled with frame pointers so hardwire this to y.
-# If you know what you are doing and are willing to live without stack
-# traces, you can get a slightly smaller kernel by setting this option to
-# n, but then RMK will have to kill you ;).
-config FRAME_POINTER
-	bool
-	default y
-	help
-	  If you say N here, the resulting kernel will be slightly smaller and
-	  faster. However, when a problem occurs with the kernel, the
-	  information that is reported is severely limited. Most people
-	  should say Y here.
-
-config DEBUG_USER
-	bool "Verbose user fault messages"
-	help
-	  When a user program crashes due to an exception, the kernel can
-	  print a brief message explaining what the problem was. This is
-	  sometimes helpful for debugging but serves no purpose on a
-	  production system. Most people should say N here.
-
-config DEBUG_INFO
-	bool "Include GDB debugging information in kernel binary"
-	help
-	  Say Y here to include source-level debugging information in the
-	  `vmlinux' binary image. This is handy if you want to use gdb or
-	  addr2line to debug the kernel. It has no impact on the in-memory
-	  footprint of the running kernel but it can increase the amount of
-	  time and disk space needed for compilation of the kernel. If in
-	  doubt say N.
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SPINLOCK
-	bool "Spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here and build SMP to catch missing spinlock initialization
-	  and certain other kinds of spinlock errors commonly made.  This is
-	  best used in conjunction with the NMI watchdog so that spinlock
-	  deadlocks are also debuggable.
-
-config DEBUG_WAITQ
-	bool "Wait queue debugging"
-	depends on DEBUG_KERNEL
-
-config DEBUG_BUGVERBOSE
-	bool "Verbose BUG() reporting (adds 70K)"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to make BUG() panics output the file name and line number
-	  of the BUG call as well as the EIP and oops trace.  This aids
-	  debugging but costs about 70-100K of memory.
-
-config DEBUG_ERRORS
-	bool "Verbose kernel error messages"
-	depends on DEBUG_KERNEL
-	help
-	  This option controls verbose debugging information which can be
-	  printed when the kernel detects an internal error. This debugging
-	  information is useful to kernel hackers when tracking down problems,
-	  but mostly meaningless to other people. It's safe to say Y unless
-	  you are concerned with the code size or don't want to see these
-	  messages.
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  If you don't debug the kernel, you can say N.
-
-# These options are only for real kernel hackers who want to get their hands dirty. 
-config DEBUG_LL
-	bool "Kernel low-level debugging functions"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to include definitions of printascii, printchar, printhex
-	  in the kernel.  This is helpful if you are debugging code that
-	  executes before the console is initialized.
-
-endmenu
+source "arch/arm26/Kconfig.debug"
 
 source "kernel/vserver/Kconfig"
 
diff --git a/arch/arm26/Makefile b/arch/arm26/Makefile
index 3b0294a8d..631c20aef 100644
--- a/arch/arm26/Makefile
+++ b/arch/arm26/Makefile
@@ -8,8 +8,7 @@
 # Copyright (C) 1995-2001 by Russell King
 
 LDFLAGS_vmlinux	:=-p -X
-LDFLAGS_BLOB	:=--format binary
-AFLAGS_vmlinux.lds.o = -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
+CPPFLAGS_vmlinux.lds = -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
 OBJCOPYFLAGS	:=-O binary -R .note -R .comment -S
 GZFLAGS		:=-9
 
@@ -28,7 +27,6 @@ CFLAGS		+=-mapcs-26 -mcpu=arm3 -mshort-load-bytes -msoft-float -Wa,-mno-fpu -Uar
 AFLAGS		+=-mapcs-26 -mcpu=arm3 -mno-fpu -msoft-float -Wa,-mno-fpu
 
 head-y		:= arch/arm26/machine/head.o arch/arm26/kernel/init_task.o
-LDFLAGS_BLOB	+= --oformat elf32-littlearm
 
 ifeq ($(CONFIG_XIP_KERNEL),y)
   TEXTADDR	 := 0x03880000
diff --git a/arch/arm26/boot/Makefile b/arch/arm26/boot/Makefile
index 3d992e597..004dd81f9 100644
--- a/arch/arm26/boot/Makefile
+++ b/arch/arm26/boot/Makefile
@@ -67,12 +67,12 @@ initrd:
 
 install: $(obj)/Image
 	$(CONFIG_SHELL) $(obj)/install.sh \
-	$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) \
+	$(KERNELRELEASE) \
 	$(obj)/Image System.map "$(INSTALL_PATH)"
 
 zinstall: $(obj)/zImage
 	$(CONFIG_SHELL) $(obj)/install.sh \
-	$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) \
+	$(KERNELRELEASE) \
 	$(obj)/zImage System.map "$(INSTALL_PATH)"
 
 subdir-	    := compressed
diff --git a/arch/arm26/kernel/Makefile b/arch/arm26/kernel/Makefile
index 7e10b557c..e2e5503f7 100644
--- a/arch/arm26/kernel/Makefile
+++ b/arch/arm26/kernel/Makefile
@@ -14,5 +14,5 @@ obj-y		:= compat.o dma.o entry.o irq.o   \
 obj-$(CONFIG_FIQ)		+= fiq.o
 obj-$(CONFIG_MODULES)		+= armksyms.o
 
-extra-y := init_task.o vmlinux.lds.s
+extra-y := init_task.o vmlinux.lds
 
diff --git a/arch/arm26/kernel/armksyms.c b/arch/arm26/kernel/armksyms.c
index c540f22f9..bd6c30669 100644
--- a/arch/arm26/kernel/armksyms.c
+++ b/arch/arm26/kernel/armksyms.c
@@ -95,7 +95,7 @@ EXPORT_SYMBOL(ret_from_exception);
 EXPORT_SYMBOL(kd_mksound);
 #endif
 
-EXPORT_SYMBOL_NOVERS(__do_softirq);
+EXPORT_SYMBOL(__do_softirq);
 
 	/* platform dependent support */
 EXPORT_SYMBOL(dump_thread);
@@ -125,71 +125,71 @@ EXPORT_SYMBOL(__csum_ipv6_magic);
 
 	/* io */
 #ifndef __raw_readsb
-EXPORT_SYMBOL_NOVERS(__raw_readsb);
+EXPORT_SYMBOL(__raw_readsb);
 #endif
 #ifndef __raw_readsw
-EXPORT_SYMBOL_NOVERS(__raw_readsw);
+EXPORT_SYMBOL(__raw_readsw);
 #endif
 #ifndef __raw_readsl
-EXPORT_SYMBOL_NOVERS(__raw_readsl);
+EXPORT_SYMBOL(__raw_readsl);
 #endif
 #ifndef __raw_writesb
-EXPORT_SYMBOL_NOVERS(__raw_writesb);
+EXPORT_SYMBOL(__raw_writesb);
 #endif
 #ifndef __raw_writesw
-EXPORT_SYMBOL_NOVERS(__raw_writesw);
+EXPORT_SYMBOL(__raw_writesw);
 #endif
 #ifndef __raw_writesl
-EXPORT_SYMBOL_NOVERS(__raw_writesl);
+EXPORT_SYMBOL(__raw_writesl);
 #endif
 
 	/* string / mem functions */
-EXPORT_SYMBOL_NOVERS(strcpy);
-EXPORT_SYMBOL_NOVERS(strncpy);
-EXPORT_SYMBOL_NOVERS(strcat);
-EXPORT_SYMBOL_NOVERS(strncat);
-EXPORT_SYMBOL_NOVERS(strcmp);
-EXPORT_SYMBOL_NOVERS(strncmp);
-EXPORT_SYMBOL_NOVERS(strchr);
-EXPORT_SYMBOL_NOVERS(strlen);
-EXPORT_SYMBOL_NOVERS(strnlen);
-EXPORT_SYMBOL_NOVERS(strpbrk);
-EXPORT_SYMBOL_NOVERS(strrchr);
-EXPORT_SYMBOL_NOVERS(strstr);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memmove);
-EXPORT_SYMBOL_NOVERS(memcmp);
-EXPORT_SYMBOL_NOVERS(memscan);
-EXPORT_SYMBOL_NOVERS(__memzero);
+EXPORT_SYMBOL(strcpy);
+EXPORT_SYMBOL(strncpy);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strncat);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strpbrk);
+EXPORT_SYMBOL(strrchr);
+EXPORT_SYMBOL(strstr);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(__memzero);
 
 	/* user mem (segment) */
 EXPORT_SYMBOL(uaccess_kernel);
 EXPORT_SYMBOL(uaccess_user);
 
-EXPORT_SYMBOL_NOVERS(__get_user_1);
-EXPORT_SYMBOL_NOVERS(__get_user_2);
-EXPORT_SYMBOL_NOVERS(__get_user_4);
-EXPORT_SYMBOL_NOVERS(__get_user_8);
+EXPORT_SYMBOL(__get_user_1);
+EXPORT_SYMBOL(__get_user_2);
+EXPORT_SYMBOL(__get_user_4);
+EXPORT_SYMBOL(__get_user_8);
 
-EXPORT_SYMBOL_NOVERS(__put_user_1);
-EXPORT_SYMBOL_NOVERS(__put_user_2);
-EXPORT_SYMBOL_NOVERS(__put_user_4);
-EXPORT_SYMBOL_NOVERS(__put_user_8);
+EXPORT_SYMBOL(__put_user_1);
+EXPORT_SYMBOL(__put_user_2);
+EXPORT_SYMBOL(__put_user_4);
+EXPORT_SYMBOL(__put_user_8);
 
 	/* gcc lib functions */
-EXPORT_SYMBOL_NOVERS(__ashldi3);
-EXPORT_SYMBOL_NOVERS(__ashrdi3);
-EXPORT_SYMBOL_NOVERS(__divsi3);
-EXPORT_SYMBOL_NOVERS(__lshrdi3);
-EXPORT_SYMBOL_NOVERS(__modsi3);
-EXPORT_SYMBOL_NOVERS(__muldi3);
-EXPORT_SYMBOL_NOVERS(__ucmpdi2);
-EXPORT_SYMBOL_NOVERS(__udivdi3);
-EXPORT_SYMBOL_NOVERS(__umoddi3);
-EXPORT_SYMBOL_NOVERS(__udivmoddi4);
-EXPORT_SYMBOL_NOVERS(__udivsi3);
-EXPORT_SYMBOL_NOVERS(__umodsi3);
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__divsi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__modsi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__ucmpdi2);
+EXPORT_SYMBOL(__udivdi3);
+EXPORT_SYMBOL(__umoddi3);
+EXPORT_SYMBOL(__udivmoddi4);
+EXPORT_SYMBOL(__udivsi3);
+EXPORT_SYMBOL(__umodsi3);
 
 	/* bitops */
 EXPORT_SYMBOL(_set_bit_le);
@@ -214,10 +214,10 @@ EXPORT_SYMBOL(sys_exit);
 EXPORT_SYMBOL(sys_wait4);
 
 	/* semaphores */
-EXPORT_SYMBOL_NOVERS(__down_failed);
-EXPORT_SYMBOL_NOVERS(__down_interruptible_failed);
-EXPORT_SYMBOL_NOVERS(__down_trylock_failed);
-EXPORT_SYMBOL_NOVERS(__up_wakeup);
+EXPORT_SYMBOL(__down_failed);
+EXPORT_SYMBOL(__down_interruptible_failed);
+EXPORT_SYMBOL(__down_trylock_failed);
+EXPORT_SYMBOL(__up_wakeup);
 
 EXPORT_SYMBOL(get_wchan);
 
diff --git a/arch/arm26/kernel/irq.c b/arch/arm26/kernel/irq.c
index 7869d1b22..be2ebeaa8 100644
--- a/arch/arm26/kernel/irq.c
+++ b/arch/arm26/kernel/irq.c
@@ -187,6 +187,7 @@ static void
 __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
 {
 	unsigned int status;
+	int ret;
 
 	spin_unlock(&irq_controller_lock);
 	if (!(action->flags & SA_INTERRUPT))
@@ -194,8 +195,9 @@ __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
 
 	status = 0;
 	do {
-		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
 		action = action->next;
 	} while (action);
 
diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c
index 78cd8931d..ae9c558b2 100644
--- a/arch/arm26/kernel/ptrace.c
+++ b/arch/arm26/kernel/ptrace.c
@@ -731,11 +731,8 @@ asmlinkage void syscall_trace(int why, struct pt_regs *regs)
 
 	/* the 0x80 provides a way for the tracing parent to distinguish
 	   between a syscall stop and SIGTRAP delivery */
-	current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-					? 0x80 : 0);
-	current->state = TASK_STOPPED;
-	notify_parent(current, SIGCHLD);
-	schedule();
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+				 ? 0x80 : 0));
 	/*
 	 * this isn't the same as continuing with a signal, but it will do
 	 * for normal use.  strace only continues with a signal if the
diff --git a/arch/arm26/kernel/signal.c b/arch/arm26/kernel/signal.c
index 16cf7db5c..bf05f1537 100644
--- a/arch/arm26/kernel/signal.c
+++ b/arch/arm26/kernel/signal.c
@@ -465,9 +465,7 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
 		return;
 	}
 
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, tsk);
+	force_sigsegv(sig, tsk);
 }
 
 /*
diff --git a/arch/arm26/kernel/sys_arm.c b/arch/arm26/kernel/sys_arm.c
index 0d1cdd503..431f9f85e 100644
--- a/arch/arm26/kernel/sys_arm.c
+++ b/arch/arm26/kernel/sys_arm.c
@@ -256,7 +256,7 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, struct
 	if (!newsp)
 		newsp = regs->ARM_sp;
 
-	return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL);
+	return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
 }
 
 asmlinkage int sys_vfork(struct pt_regs *regs)
diff --git a/arch/arm26/kernel/time.c b/arch/arm26/kernel/time.c
index af2905a1f..dbbc21404 100644
--- a/arch/arm26/kernel/time.c
+++ b/arch/arm26/kernel/time.c
@@ -67,28 +67,6 @@ static unsigned long dummy_gettimeoffset(void)
  */
 unsigned long (*gettimeoffset)(void) = dummy_gettimeoffset;
 
-/*
- * Handle kernel profile stuff...
- */
-static inline void do_profile(struct pt_regs *regs)
-{
-	if (!user_mode(regs) &&
-	    prof_buffer &&
-	    current->pid) {
-		unsigned long pc = instruction_pointer(regs);
-		extern int _stext;
-
-		pc -= (unsigned long)&_stext;
-
-		pc >>= prof_shift;
-
-		if (pc >= prof_len)
-			pc = prof_len - 1;
-
-		prof_buffer[pc] += 1;
-	}
-}
-
 static unsigned long next_rtc_update;
 
 /*
@@ -189,7 +167,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
         do_timer(regs);
         do_set_rtc(); //FIME - EVERY timer IRQ?
-        do_profile(regs);
+        profile_tick(CPU_PROFILING, regs);
 	return IRQ_HANDLED; //FIXME - is this right?
 }
 
diff --git a/arch/arm26/kernel/vmlinux-arm26-xip.lds.in b/arch/arm26/kernel/vmlinux-arm26-xip.lds.in
index 61eedf0bc..cbbda2766 100644
--- a/arch/arm26/kernel/vmlinux-arm26-xip.lds.in
+++ b/arch/arm26/kernel/vmlinux-arm26-xip.lds.in
@@ -34,9 +34,6 @@ SECTIONS
 		__early_begin = .;
 			*(__early_param)
 		__early_end = .;
-		__start___param = .;
-			*(__param)
-		__stop___param = .;
 		__initcall_start = .;
 			*(.initcall1.init)
 			*(.initcall2.init)
diff --git a/arch/arm26/kernel/vmlinux-arm26.lds.in b/arch/arm26/kernel/vmlinux-arm26.lds.in
index 2393f3805..128eb9195 100644
--- a/arch/arm26/kernel/vmlinux-arm26.lds.in
+++ b/arch/arm26/kernel/vmlinux-arm26.lds.in
@@ -35,9 +35,6 @@ SECTIONS
 		__early_begin = .;
 			*(__early_param)
 		__early_end = .;
-		__start___param = .;
-			*(__param)
-		__stop___param = .;
 		__initcall_start = .;
 			*(.initcall1.init)
 			*(.initcall2.init)
diff --git a/arch/arm26/mm/init.c b/arch/arm26/mm/init.c
index ad41cebe2..17f7dc3e9 100644
--- a/arch/arm26/mm/init.c
+++ b/arch/arm26/mm/init.c
@@ -305,8 +305,8 @@ void __init paging_init(struct meminfo *mi)
 			(bdata->node_boot_start >> PAGE_SHIFT);
 	if (!zone_size[0])
 		BUG();
-
-	free_area_init_node(0, pgdat, 0, zone_size,
+	pgdat->node_mem_map = NULL;
+	free_area_init_node(0, pgdat, zone_size,
 			bdata->node_boot_start >> PAGE_SHIFT, zhole_size);
 
 	mem_map = NODE_DATA(0)->node_mem_map;
@@ -376,7 +376,7 @@ void __init mem_init(void)
 	 * Turn on overcommit on tiny machines
 	 */
 	if (PAGE_SIZE >= 16384 && num_physpages <= 128) {
-		sysctl_overcommit_memory = 1;
+		sysctl_overcommit_memory = OVERCOMMIT_ALWAYS;
 		printk("Turning on overcommit\n");
 	}
 }
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index 93d52b712..a8e4c25c7 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -20,8 +20,11 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
 	bool
 
-source "init/Kconfig"
+config CRIS
+	bool
+	default y
 
+source "init/Kconfig"
 
 menu "General setup"
 
@@ -51,7 +54,7 @@ config ETRAX_FAST_TIMER
        bool "Enable ETRAX fast timer API"
        help
          This options enables the API to a fast timer implementation using
-	 timer1 to get sub jiffie resolution timers (primarily one-shot 
+	 timer1 to get sub jiffie resolution timers (primarily one-shot
 	 timers).
 	 This is needed if CONFIG_ETRAX_SERIAL_FAST_TIMER is enabled.
 
@@ -69,7 +72,6 @@ config PREEMPT
 
 endmenu
 
-
 menu "Hardware setup"
 
 choice
@@ -96,7 +98,7 @@ endchoice
 config ETRAX_ARCH_V10
        bool
        default y if ETRAX100LX || ETRAX100LX_V2
-       default n if !(ETRAX100LX || ETRAX100LX_V2) 
+       default n if !(ETRAX100LX || ETRAX100LX_V2)
 
 config ETRAX_DRAM_SIZE
 	int "DRAM size (dec, in MB)"
@@ -165,50 +167,7 @@ source "sound/Kconfig"
 
 source "drivers/usb/Kconfig"
 
-
-menu "Kernel hacking"
-
-#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
-config PROFILE
-	bool "Kernel profiling support"
-
-config PROFILE_SHIFT
-	int "Profile shift count"
-	depends on PROFILE
-	default "2"
-
-config ETRAX_KGDB
-	bool "Use kernel GDB debugger"
-	---help---
-	  The CRIS version of gdb can be used to remotely debug a running
-	  Linux kernel via the serial debug port.  Provided you have gdb-cris
-	  installed, run gdb-cris vmlinux, then type
-
-	  (gdb) set remotebaud 115200           <- kgdb uses 115200 as default
-	  (gdb) target remote /dev/ttyS0        <- maybe you use another port
-
-	  This should connect you to your booted kernel (or boot it now if you
-	  didn't before).  The kernel halts when it boots, waiting for gdb if
-	  this option is turned on!
-
-
-config DEBUG_INFO
-        bool "Compile the kernel with debug info"
-        help
-          If you say Y here the resulting kernel image will include
-          debugging info resulting in a larger kernel image.
-          Say Y here only if you plan to use gdb to debug the kernel.
-          If you don't debug the kernel, you can say N.
-
-config FRAME_POINTER
-        bool "Compile the kernel with frame pointers"
-        help
-          If you say Y here the resulting kernel image will be slightly larger
-          and slower, but 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 pointers.
-
-endmenu
+source "arch/cris/Kconfig.debug"
 
 source "kernel/vserver/Kconfig"
 
@@ -217,4 +176,3 @@ source "security/Kconfig"
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff --git a/arch/cris/Makefile b/arch/cris/Makefile
index 30585a70c..0c6944c7c 100644
--- a/arch/cris/Makefile
+++ b/arch/cris/Makefile
@@ -24,12 +24,10 @@ SARCH :=
 endif
 
 LD = $(CROSS_COMPILE)ld -mcrislinux
-LDFLAGS_BLOB	:= --format binary --oformat elf32-cris \
-		   -T arch/cris/$(SARCH)/output_arch.ld
 
 OBJCOPYFLAGS := -O binary -R .note -R .comment -S
 
-AFLAGS_vmlinux.lds.o = -DDRAM_VIRTUAL_BASE=0x$(CONFIG_ETRAX_DRAM_VIRTUAL_BASE)
+CPPFLAGS_vmlinux.lds = -DDRAM_VIRTUAL_BASE=0x$(CONFIG_ETRAX_DRAM_VIRTUAL_BASE)
 AFLAGS += -mlinux
 
 CFLAGS := $(CFLAGS) -mlinux -march=$(arch-y) -pipe
@@ -39,7 +37,7 @@ CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS)) -g
 CFLAGS += -fno-omit-frame-pointer
 endif
 
-HEAD := arch/$(ARCH)/$(SARCH)/kernel/head.o
+head-y := arch/$(ARCH)/$(SARCH)/kernel/head.o
 
 LIBGCC = $(shell $(CC) $(CFLAGS) -print-file-name=libgcc.a)
 
diff --git a/arch/cris/arch-v10/kernel/debugport.c b/arch/cris/arch-v10/kernel/debugport.c
index d80269f6f..d8f20d79f 100644
--- a/arch/cris/arch-v10/kernel/debugport.c
+++ b/arch/cris/arch-v10/kernel/debugport.c
@@ -259,7 +259,7 @@ static struct console sercons = {
 void __init 
 init_etrax_debug(void)
 {
-#if CONFIG_ETRAX_DEBUG_PORT_NULL
+#ifdef CONFIG_ETRAX_DEBUG_PORT_NULL
 	return;
 #endif
 
diff --git a/arch/cris/arch-v10/kernel/process.c b/arch/cris/arch-v10/kernel/process.c
index 8aba42472..d0993bf72 100644
--- a/arch/cris/arch-v10/kernel/process.c
+++ b/arch/cris/arch-v10/kernel/process.c
@@ -180,7 +180,7 @@ asmlinkage int sys_clone(unsigned long newusp, unsigned long flags,
 {
 	if (!newusp)
 		newusp = rdusp();
-	return do_fork(flags & ~CLONE_IDLETASK, newusp, regs, 0, parent_tid, child_tid);
+	return do_fork(flags, newusp, regs, 0, parent_tid, child_tid);
 }
 
 /* vfork is a system call in i386 because of register-pressure - maybe
diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c
index 39dcc3c72..3c7e0a51a 100644
--- a/arch/cris/arch-v10/kernel/ptrace.c
+++ b/arch/cris/arch-v10/kernel/ptrace.c
@@ -85,17 +85,8 @@ sys_ptrace(long request, long pid, long addr, long data)
 		goto out_tsk;
 	}
 	
-	ret = -ESRCH;
-	
-	if (!(child->ptrace & PT_PTRACED))
-		goto out_tsk;
-	
-	if (child->state != TASK_STOPPED) {
-		if (request != PTRACE_KILL)
-			goto out_tsk;
-	}
-	
-	if (child->parent != current)
+	ret = ptrace_check_attach(child, request == PTRACE_KILL);
+	if (ret < 0)
 		goto out_tsk;
 
 	switch (request) {
diff --git a/arch/cris/arch-v10/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c
index 8db985e29..19f93fe42 100644
--- a/arch/cris/arch-v10/kernel/signal.c
+++ b/arch/cris/arch-v10/kernel/signal.c
@@ -409,9 +409,7 @@ static void setup_frame(int sig, struct k_sigaction *ka,
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -475,9 +473,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 /*
diff --git a/arch/cris/arch-v10/mm/init.c b/arch/cris/arch-v10/mm/init.c
index df03dea5b..720b9c156 100644
--- a/arch/cris/arch-v10/mm/init.c
+++ b/arch/cris/arch-v10/mm/init.c
@@ -183,7 +183,7 @@ paging_init(void)
 	 * mem_map page array.
 	 */
 
-	free_area_init_node(0, &contig_page_data, 0, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0);
+	free_area_init_node(0, &contig_page_data, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0);
 	mem_map = contig_page_data.node_mem_map;
 }
 
diff --git a/arch/cris/arch-v10/vmlinux.lds.S b/arch/cris/arch-v10/vmlinux.lds.S
index 6b73a2c0d..9e134c688 100644
--- a/arch/cris/arch-v10/vmlinux.lds.S
+++ b/arch/cris/arch-v10/vmlinux.lds.S
@@ -64,9 +64,6 @@ SECTIONS
   	__setup_start = .;
   	.init.setup : { *(.init.setup) }
   	__setup_end = .;
-	__start___param = .;
-	__param : { *(__param) }
-	__stop___param = .;
   	.initcall.init : {
 		__initcall_start = .;
 		*(.initcall1.init);
diff --git a/arch/cris/kernel/Makefile b/arch/cris/kernel/Makefile
index 7c071a765..1546a0e74 100644
--- a/arch/cris/kernel/Makefile
+++ b/arch/cris/kernel/Makefile
@@ -3,7 +3,7 @@
 # Makefile for the linux kernel.
 #
 
-extra-y	:= vmlinux.lds.s
+extra-y	:= vmlinux.lds
 
 obj-y   := process.o traps.o irq.o ptrace.o setup.o \
 	   time.o sys_cris.o semaphore.o
diff --git a/arch/cris/kernel/crisksyms.c b/arch/cris/kernel/crisksyms.c
index 6ded633f8..7141bbecd 100644
--- a/arch/cris/kernel/crisksyms.c
+++ b/arch/cris/kernel/crisksyms.c
@@ -16,7 +16,6 @@
 #include <asm/uaccess.h>
 #include <asm/checksum.h>
 #include <asm/io.h>
-#include <asm/hardirq.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
 #include <asm/pgtable.h>
@@ -91,8 +90,8 @@ EXPORT_SYMBOL(prepare_rx_descriptor);
 #undef memset
 extern void * memset(void *, int, __kernel_size_t);
 extern void * memcpy(void *, const void *, __kernel_size_t);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
 
 #ifdef CONFIG_ETRAX_FAST_TIMER
 /* Fast timer functions */
diff --git a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c
index 94d702790..bb8d2e4e7 100644
--- a/arch/cris/kernel/irq.c
+++ b/arch/cris/kernel/irq.c
@@ -125,7 +125,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
 {
 	struct irqaction *action;
 	int do_random, cpu;
-        int retval = 0;
+        int ret, retval = 0;
 
         cpu = smp_processor_id();
         irq_enter();
@@ -137,8 +137,10 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
                         local_irq_enable();
                 do_random = 0;
                 do {
-                        do_random |= action->flags;
-                        retval |= action->handler(irq, action->dev_id, regs);
+			ret = action->handler(irq, action->dev_id, regs);
+			if (ret == IRQ_HANDLED)
+				do_random |= action->flags;
+                        retval |= ret;
                         action = action->next;
                 } while (action);
 
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index 47356589a..d0b845ac0 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -176,82 +176,12 @@ source "drivers/serial/Kconfig"
 source "drivers/i2c/Kconfig"
 
 source "drivers/usb/Kconfig"
- 
+
 endmenu
 
 source "fs/Kconfig"
 
-menu "Kernel hacking"
-
-config FULLDEBUG
-	bool "Full Symbolic/Source Debugging support"
-	help
-	  Enable debugging symbols on kernel build.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	help
-	  Enables console device to interprent special characters as
-	  commands to dump state information.
-
-config HIGHPROFILE
-	bool "Use fast second timer for profiling"
-	help
-	  Use a fast secondary clock to produce profiling information.
-
-config NO_KERNEL_MSG
-	bool "Suppress Kernel BUG Messages"
-	help
-	  Do not output any debug BUG messages within the kernel.
-
-config GDB_MAGICPRINT
-	bool "Message Output for GDB MagicPrint service"
-	depends on (H8300H_SIM || H8S_SIM)
-	help
-	  kernel messages output useing MagicPrint service from GDB
-
-config SYSCALL_PRINT
-	bool "SystemCall trace print"
-	help
-	  outout history of systemcall
-
-config GDB_DEBUG
-   	bool "Use gdb stub"
-	depends on (!H8300H_SIM && !H8S_SIM)
-	help
-	  gdb stub exception support
-
-config CONFIG_SH_STANDARD_BIOS
-	bool "Use gdb protocol serial console"
-	depends on (!H8300H_SIM && !H8S_SIM)
-	help
-	  serial console output using GDB protocol.
-	  Require eCos/RedBoot
-
-config DEFAULT_CMDLINE
-	bool "Use buildin commandline"
-	default n
-	help
-	  buildin kernel commandline enabled.
-
-config KERNEL_COMMAND
-	string "Buildin commmand string"
-	depends on DEFAULT_CMDLINE
-	help
-	  buildin kernel commandline strings.
-
-config BLKDEV_RESERVE
-	bool "BLKDEV Reserved Memory"
-	default n
-	help
-	  Reserved BLKDEV area.
-
-config CONFIG_BLKDEV_RESERVE_ADDRESS
-	hex 'start address'
-	depends on BLKDEV_RESERVE
-	help
-	  BLKDEV start address.
-endmenu
+source "arch/h8300/Kconfig.debug"
 
 source "kernel/vserver/Kconfig"
 
@@ -260,4 +190,3 @@ source "security/Kconfig"
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff --git a/arch/h8300/kernel/Makefile b/arch/h8300/kernel/Makefile
index 1f4ef89b5..71b6131e9 100644
--- a/arch/h8300/kernel/Makefile
+++ b/arch/h8300/kernel/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-extra-y := vmlinux.lds.s
+extra-y := vmlinux.lds
 
 obj-y := process.o traps.o ptrace.o ints.o \
 	 sys_h8300.o time.o semaphore.o signal.o \
diff --git a/arch/h8300/kernel/asm-offsets.c b/arch/h8300/kernel/asm-offsets.c
index 5e50c0893..b78b82ad2 100644
--- a/arch/h8300/kernel/asm-offsets.c
+++ b/arch/h8300/kernel/asm-offsets.c
@@ -12,9 +12,9 @@
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <linux/ptrace.h>
+#include <linux/hardirq.h>
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
-#include <asm/hardirq.h>
 #include <asm/ptrace.h>
 
 #define DEFINE(sym, val) \
diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c
index ca8578fed..5a6302331 100644
--- a/arch/h8300/kernel/h8300_ksyms.c
+++ b/arch/h8300/kernel/h8300_ksyms.c
@@ -15,7 +15,6 @@
 #include <asm/io.h>
 #include <asm/semaphore.h>
 #include <asm/checksum.h>
-#include <asm/hardirq.h>
 #include <asm/current.h>
 #include <asm/gpio.h>
 
@@ -50,13 +49,13 @@ EXPORT_SYMBOL(csum_partial_copy);
    explicitly (the C compiler generates them).  Fortunately,
    their interface isn't gonna change any time soon now, so
    it's OK to leave it out of version control.  */
-//EXPORT_SYMBOL_NOVERS(__ashrdi3);
-//EXPORT_SYMBOL_NOVERS(__lshrdi3);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memcmp);
-EXPORT_SYMBOL_NOVERS(memscan);
-EXPORT_SYMBOL_NOVERS(memmove);
+//EXPORT_SYMBOL(__ashrdi3);
+//EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(memmove);
 
 EXPORT_SYMBOL(get_wchan);
 
@@ -85,29 +84,29 @@ extern void __umoddi3(void);
 extern void __umodsi3(void);
 
         /* gcc lib functions */
-EXPORT_SYMBOL_NOVERS(__gcc_bcmp);
-EXPORT_SYMBOL_NOVERS(__ashldi3);
-EXPORT_SYMBOL_NOVERS(__ashrdi3);
-EXPORT_SYMBOL_NOVERS(__cmpdi2);
-EXPORT_SYMBOL_NOVERS(__divdi3);
-EXPORT_SYMBOL_NOVERS(__divsi3);
-EXPORT_SYMBOL_NOVERS(__lshrdi3);
-EXPORT_SYMBOL_NOVERS(__moddi3);
-EXPORT_SYMBOL_NOVERS(__modsi3);
-EXPORT_SYMBOL_NOVERS(__muldi3);
-EXPORT_SYMBOL_NOVERS(__mulsi3);
-EXPORT_SYMBOL_NOVERS(__negdi2);
-EXPORT_SYMBOL_NOVERS(__ucmpdi2);
-EXPORT_SYMBOL_NOVERS(__udivdi3);
-EXPORT_SYMBOL_NOVERS(__udivmoddi4);
-EXPORT_SYMBOL_NOVERS(__udivsi3);
-EXPORT_SYMBOL_NOVERS(__umoddi3);
-EXPORT_SYMBOL_NOVERS(__umodsi3);
+EXPORT_SYMBOL(__gcc_bcmp);
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__cmpdi2);
+EXPORT_SYMBOL(__divdi3);
+EXPORT_SYMBOL(__divsi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__moddi3);
+EXPORT_SYMBOL(__modsi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__mulsi3);
+EXPORT_SYMBOL(__negdi2);
+EXPORT_SYMBOL(__ucmpdi2);
+EXPORT_SYMBOL(__udivdi3);
+EXPORT_SYMBOL(__udivmoddi4);
+EXPORT_SYMBOL(__udivsi3);
+EXPORT_SYMBOL(__umoddi3);
+EXPORT_SYMBOL(__umodsi3);
 
 #ifdef MAGIC_ROM_PTR
-EXPORT_SYMBOL_NOVERS(is_in_rom);
+EXPORT_SYMBOL(is_in_rom);
 #endif
 
-EXPORT_SYMBOL_NOVERS(h8300_reserved_gpio);
-EXPORT_SYMBOL_NOVERS(h8300_free_gpio);
-EXPORT_SYMBOL_NOVERS(h8300_set_gpio_dir);
+EXPORT_SYMBOL(h8300_reserved_gpio);
+EXPORT_SYMBOL(h8300_free_gpio);
+EXPORT_SYMBOL(h8300_set_gpio_dir);
diff --git a/arch/h8300/kernel/ints.c b/arch/h8300/kernel/ints.c
index 7246e29ea..edb3c4170 100644
--- a/arch/h8300/kernel/ints.c
+++ b/arch/h8300/kernel/ints.c
@@ -22,13 +22,13 @@
 #include <linux/init.h>
 #include <linux/random.h>
 #include <linux/bootmem.h>
+#include <linux/hardirq.h>
 
 #include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/traps.h>
 #include <asm/io.h>
 #include <asm/setup.h>
-#include <asm/hardirq.h>
 #include <asm/errno.h>
 
 /*
diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c
index d7c058d64..134aec1c6 100644
--- a/arch/h8300/kernel/process.c
+++ b/arch/h8300/kernel/process.c
@@ -189,7 +189,7 @@ asmlinkage int h8300_clone(struct pt_regs *regs)
 	newsp = regs->er2;
 	if (!newsp)
 		newsp  = rdusp();
-	return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL);
+	return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
 
 }
 
diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c
index 51777001a..838e0c993 100644
--- a/arch/h8300/kernel/ptrace.c
+++ b/arch/h8300/kernel/ptrace.c
@@ -91,13 +91,6 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 		ret = ptrace_attach(child);
 		goto out_tsk;
 	}
-	ret = -ESRCH;
-	if (!(child->ptrace & PT_PTRACED))
-		goto out_tsk;
-	if (child->state != TASK_STOPPED) {
-		if (request != PTRACE_KILL)
-			goto out_tsk;
-	}
 	ret = ptrace_check_attach(child, request == PTRACE_KILL);
 	if (ret < 0)
 		goto out_tsk;
@@ -116,7 +109,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 
 	/* read the word at location addr in the USER area. */
 		case PTRACE_PEEKUSR: {
-			unsigned long tmp;
+			unsigned long tmp = 0;
 			
 			if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) {
 				ret = -EIO;
@@ -272,10 +265,8 @@ asmlinkage void syscall_trace(void)
 		return;
 	if (!(current->ptrace & PT_PTRACED))
 		return;
-	current->exit_code = SIGTRAP;
-	current->state = TASK_STOPPED;
-	notify_parent(current, SIGCHLD);
-	schedule();
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+				 ? 0x80 : 0));
 	/*
 	 * this isn't the same as continuing with a signal, but it will do
 	 * for normal use.  strace only continues with a signal if the
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c
index 17c83890c..5fd383a6a 100644
--- a/arch/h8300/kernel/signal.c
+++ b/arch/h8300/kernel/signal.c
@@ -391,9 +391,7 @@ static void setup_frame (int sig, struct k_sigaction *ka,
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -443,9 +441,7 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static inline void
diff --git a/arch/h8300/kernel/time.c b/arch/h8300/kernel/time.c
index 87e284901..0b293d652 100644
--- a/arch/h8300/kernel/time.c
+++ b/arch/h8300/kernel/time.c
@@ -36,24 +36,6 @@ u64 jiffies_64;
 
 EXPORT_SYMBOL(jiffies_64);
 
-static inline void do_profile (unsigned long pc)
-{
-	if (prof_buffer && current->pid) {
-		extern int _stext;
-		pc -= (unsigned long) &_stext;
-		pc >>= prof_shift;
-		if (pc < prof_len)
-			++prof_buffer[pc];
-		else
-		/*
-		 * Don't ignore out-of-bounds PC values silently,
-		 * put them into the last histogram slot, so if
-		 * present, they will show up as a sharp peak.
-		 */
-			++prof_buffer[prof_len-1];
-	}
-}
-
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
@@ -64,10 +46,7 @@ static void timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
 	platform_timer_eoi();
 
 	do_timer(regs);
-
-	if (!user_mode(regs))
-		do_profile(regs->pc);
-
+	profile_tick(CPU_PROFILING, regs);
 }
 
 void time_init(void)
diff --git a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S
index 7a6009cf2..427f1891c 100644
--- a/arch/h8300/kernel/vmlinux.lds.S
+++ b/arch/h8300/kernel/vmlinux.lds.S
@@ -150,9 +150,6 @@ SECTIONS
 		*(.init.setup)
 	. = ALIGN(0x4) ;
 	___setup_end = .;
-	___start___param = .;
-		*(__param)
-	___stop___param = .;
 	___initcall_start = .;
 		*(.initcall1.init)
 		*(.initcall2.init)
diff --git a/arch/h8300/lib/checksum.c b/arch/h8300/lib/checksum.c
index 6691d0b93..5aa688d92 100644
--- a/arch/h8300/lib/checksum.c
+++ b/arch/h8300/lib/checksum.c
@@ -32,6 +32,7 @@
    of the assembly has to go. */
 
 #include <net/checksum.h>
+#include <linux/module.h>
 
 static inline unsigned short from32to16(unsigned long x)
 {
diff --git a/arch/h8300/platform/h8300h/generic/timer.c b/arch/h8300/platform/h8300h/generic/timer.c
index ffc0349b7..6590f89e5 100644
--- a/arch/h8300/platform/h8300h/generic/timer.c
+++ b/arch/h8300/platform/h8300h/generic/timer.c
@@ -32,7 +32,7 @@
 
 #define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*1000/8192 /* Timer input freq. */
 
-int platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
+void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
 {
 	/* setup 8bit timer ch2 */
 	ctrl_outb(H8300_TIMER_FREQ / HZ, TCORA2);      /* set interval */
@@ -69,7 +69,7 @@ void platform_timer_eoi(void)
 
 #define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*1000/8 /* Timer input freq. */
 
-int platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
+void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
 {
 	*(unsigned short *)GRA= H8300_TIMER_FREQ / HZ;  /* set interval */
 	*(unsigned short *)TCNT=0;                      /* clear counter */
diff --git a/arch/h8300/platform/h8s/ints.c b/arch/h8300/platform/h8s/ints.c
index bbefac403..5441cdd12 100644
--- a/arch/h8300/platform/h8s/ints.c
+++ b/arch/h8300/platform/h8s/ints.c
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/random.h>
+#include <linux/hardirq.h>
 
 #include <asm/system.h>
 #include <asm/irq.h>
@@ -29,7 +30,6 @@
 #include <asm/io.h>
 #include <asm/setup.h>
 #include <asm/gpio.h>
-#include <asm/hardirq.h>
 #include <asm/regs267x.h>
 #include <asm/errno.h>
 
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index 51f5417a6..9323ae3e3 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -29,8 +29,11 @@ config GENERIC_ISA_DMA
 	bool
 	default y
 
-source "init/Kconfig"
+config GENERIC_IOMAP
+	bool
+	default y
 
+source "init/Kconfig"
 
 menu "Processor type and features"
 
@@ -55,20 +58,20 @@ config X86_ELAN
 config X86_VOYAGER
 	bool "Voyager (NCR)"
 	help
-	  Voyager is a MCA based 32 way capable SMP architecture proprietary
-	  to NCR Corp.  Machine classes 345x/35xx/4100/51xx are voyager based.
-	  
+	  Voyager is an MCA-based 32-way capable SMP architecture proprietary
+	  to NCR Corp.  Machine classes 345x/35xx/4100/51xx are Voyager-based.
+
 	  *** WARNING ***
-	
+
 	  If you do not specifically know you have a Voyager based machine,
-	  say N here otherwise the kernel you build will not be bootable.
+	  say N here, otherwise the kernel you build will not be bootable.
 
 config X86_NUMAQ
 	bool "NUMAQ (IBM/Sequent)"
 	select DISCONTIGMEM
 	select NUMA
 	help
-	  This option is used for getting Linux to run on a (IBM/Sequent) NUMA 
+	  This option is used for getting Linux to run on a (IBM/Sequent) NUMA
 	  multiquad box. This changes the way that processors are bootstrapped,
 	  and uses Clustered Logical APIC addressing mode instead of Flat Logical.
 	  You will need a new lynxer.elf file to flash your firmware with - send
@@ -115,8 +118,8 @@ config X86_ES7000
 	depends on SMP
 	help
 	  Support for Unisys ES7000 systems.  Say 'Y' here if this kernel is
-	  supposed to run on an IA32-based Unisys ES7000 system. 
-	  Only choose this option if you have such a system, otherwise you 
+	  supposed to run on an IA32-based Unisys ES7000 system.
+	  Only choose this option if you have such a system, otherwise you
 	  should say N here.
 
 endchoice
@@ -322,7 +325,7 @@ config MVIAC3_2
 endchoice
 
 config X86_GENERIC
-       bool "Generic x86 support" 
+       bool "Generic x86 support"
        help
 	  Instead of just including optimizations for the selected
 	  x86 variant (e.g. PII, Crusoe or Athlon), include some more
@@ -711,6 +714,46 @@ config HIGHMEM64G
 
 endchoice
 
+choice
+	prompt "Memory Split User Space"
+	default SPLIT_3GB
+	help
+	  A different Userspace/Kernel split allows you to
+	  utilize up to alsmost 3GB of RAM without the requirement
+	  for HIGHMEM. It also increases the available lowmem.
+
+config SPLIT_3GB
+	bool "3.0GB/1.0GB Kernel (Default)"
+	help
+	  This is the default split of 3GB userspace to 1GB kernel
+	  space, which will result in about 860MB of lowmem.
+
+config SPLIT_25GB
+	bool "2.5GB/1.5GB Kernel"
+	help
+	  This split provides 2.5GB userspace and 1.5GB kernel
+	  space, which will result in about 1370MB of lowmem.
+
+config SPLIT_2GB
+	bool "2.0GB/2.0GB Kernel"
+	help
+	  This split provides 2GB userspace and 2GB kernel
+	  space, which will result in about 1880MB of lowmem.
+
+config SPLIT_15GB
+	bool "1.5GB/2.5GB Kernel"
+	help
+	  This split provides 1.5GB userspace and 2.5GB kernel
+	  space, which will result in about 2390MB of lowmem.
+
+config SPLIT_1GB
+	bool "1.0GB/3.0GB Kernel"
+	help
+	  This split provides 1GB userspace and 3GB kernel
+	  space, which will result in about 2900MB of lowmem.
+
+endchoice
+
 config HIGHMEM
 	bool
 	depends on HIGHMEM64G || HIGHMEM4G
@@ -1027,7 +1070,6 @@ source "arch/i386/kernel/cpu/cpufreq/Kconfig"
 
 endmenu
 
-
 menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
 
 config X86_VISWS_APIC
@@ -1105,7 +1147,7 @@ config PCI_DIRECT
 
 config PCI_MMCONFIG
 	bool
-	depends on PCI && (PCI_GOMMCONFIG || PCI_GOANY)
+	depends on PCI && (PCI_GOMMCONFIG || (PCI_GOANY && ACPI))
 	select ACPI_BOOT
 	default y
 
@@ -1158,7 +1200,7 @@ config SCx200
 	tristate "NatSemi SCx200 support"
 	depends on !X86_VOYAGER
 	help
-	  This provides basic support for the National Semiconductor SCx200 
+	  This provides basic support for the National Semiconductor SCx200
 	  processor.  Right now this is just a driver for the GPIO pins.
 
 	  If you don't know what to do here, say N.
@@ -1172,7 +1214,6 @@ source "drivers/pci/hotplug/Kconfig"
 
 endmenu
 
-
 menu "Executable file formats"
 
 source "fs/Kconfig.binfmt"
@@ -1185,130 +1226,7 @@ source "fs/Kconfig"
 
 source "arch/i386/oprofile/Kconfig"
 
-
-menu "Kernel hacking"
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
-config EARLY_PRINTK
-	bool "Early printk" if EMBEDDED
-	default y
-	help
-	  Write kernel log output directly into the VGA buffer or to a serial
-	  port.
-
-	  This is useful for kernel debugging when your machine crashes very
-	  early before the console code is initialized. For normal operation
-	  it is not recommended because it looks ugly and doesn't cooperate
-	  with klogd/syslogd or the X server. You should normally N here,
-	  unless you want to debug such a crash.
-
-config DEBUG_STACKOVERFLOW
-	bool "Check for stack overflows"
-	depends on DEBUG_KERNEL
-
-config DEBUG_STACK_USAGE
-	bool "Stack utilization instrumentation"
-	depends on DEBUG_KERNEL
-	help
-	  Enables the display of the minimum amount of free stack which each
-	  task has ever had available in the sysrq-T and sysrq-P debug output.
-
-	  This option will slow down process creation somewhat.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SPINLOCK
-	bool "Spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here and build SMP to catch missing spinlock initialization
-	  and certain other kinds of spinlock errors commonly made.  This is
-	  best used in conjunction with the NMI watchdog so that spinlock
-	  deadlocks are also debuggable.
-
-config DEBUG_PAGEALLOC
-	bool "Page alloc debugging"
-	depends on DEBUG_KERNEL
-	help
-	  Unmap pages from the kernel linear mapping after free_pages().
-	  This results in a large slowdown, but helps to find certain types
-	  of memory corruptions.
-
-config DEBUG_HIGHMEM
-	bool "Highmem debugging"
-	depends on DEBUG_KERNEL && HIGHMEM
-	help
-	  This options enables addition error checking for high memory systems.
-	  Disable for production systems.
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  If you don't debug the kernel, you can say N.
-	  
-config DEBUG_SPINLOCK_SLEEP
-	bool "Sleep-inside-spinlock checking"
-	help
-	  If you say Y here, various routines which may sleep will become very
-	  noisy if they are called with a spinlock held.	
-
-config FRAME_POINTER
-	bool "Compile the kernel with frame pointers"
-	help
-	  If you say Y here the resulting kernel image will be slightly larger
-	  and slower, but 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 pointers.
-
-config 4KSTACKS
-	bool "Use 4Kb for kernel stacks instead of 8Kb"
-	help
-	  If you say Y here the kernel will use a 4Kb stacksize for the
-	  kernel stack attached to each process/thread. This facilitates
-	  running more threads on a system and also reduces the pressure
-	  on the VM subsystem for higher order allocations. This option
-	  will also use IRQ stacks to compensate for the reduced stackspace.
-
-config X86_FIND_SMP_CONFIG
-	bool
-	depends on X86_LOCAL_APIC || X86_VOYAGER
-	default y
-
-config X86_MPPARSE
-	bool
-	depends on X86_LOCAL_APIC && !X86_VISWS
-	default y
-
-endmenu
+source "arch/i386/Kconfig.debug"
 
 source "kernel/vserver/Kconfig"
 
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index 1e446b234..8fc05ee7c 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -18,48 +18,47 @@
 LDFLAGS		:= -m elf_i386
 OBJCOPYFLAGS	:= -O binary -R .note -R .comment -S
 LDFLAGS_vmlinux :=
-CHECK		:= $(CHECK) -D__i386__=1
+CHECKFLAGS	+= -D__i386__
 
 CFLAGS += -pipe -msoft-float
 
 # prevent gcc from keeping the stack 16 byte aligned
-CFLAGS += $(call check_gcc,-mpreferred-stack-boundary=2,)
-
-align := $(subst -functions=0,,$(call check_gcc,-falign-functions=0,-malign-functions=0))
+CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2)
 
+align := $(subst -functions=0,,$(call cc-option,-falign-functions=0,-malign-functions=0))
 cflags-$(CONFIG_M386)		+= -march=i386
 cflags-$(CONFIG_M486)		+= -march=i486
 cflags-$(CONFIG_M586)		+= -march=i586
 cflags-$(CONFIG_M586TSC)	+= -march=i586
-cflags-$(CONFIG_M586MMX)	+= $(call check_gcc,-march=pentium-mmx,-march=i586)
+cflags-$(CONFIG_M586MMX)	+= $(call cc-option,-march=pentium-mmx,-march=i586)
 cflags-$(CONFIG_M686)		+= -march=i686
-cflags-$(CONFIG_MPENTIUMII)	+= $(call check_gcc,-march=pentium2,-march=i686)
-cflags-$(CONFIG_MPENTIUMIII)	+= $(call check_gcc,-march=pentium3,-march=i686)
-cflags-$(CONFIG_MPENTIUMM)	+= $(call check_gcc,-march=pentium3,-march=i686)
-cflags-$(CONFIG_MPENTIUM4)	+= $(call check_gcc,-march=pentium4,-march=i686)
+cflags-$(CONFIG_MPENTIUMII)	+= $(call cc-option,-march=pentium2,-march=i686)
+cflags-$(CONFIG_MPENTIUMIII)	+= $(call cc-option,-march=pentium3,-march=i686)
+cflags-$(CONFIG_MPENTIUMM)	+= $(call cc-option,-march=pentium3,-march=i686)
+cflags-$(CONFIG_MPENTIUM4)	+= $(call cc-option,-march=pentium4,-march=i686)
 cflags-$(CONFIG_MK6)		+= -march=k6
 # Please note, that patches that add -march=athlon-xp and friends are pointless.
 # They make zero difference whatsosever to performance at this time.
-cflags-$(CONFIG_MK7)		+= $(call check_gcc,-march=athlon,-march=i686 $(align)-functions=4)
-cflags-$(CONFIG_MK8)		+= $(call check_gcc,-march=k8,$(call check_gcc,-march=athlon,-march=i686 $(align)-functions=4))
+cflags-$(CONFIG_MK7)		+= $(call cc-option,-march=athlon,-march=i686 $(align)-functions=4)
+cflags-$(CONFIG_MK8)		+= $(call cc-option,-march=k8,$(call cc-option,-march=athlon,-march=i686 $(align)-functions=4))
 cflags-$(CONFIG_MCRUSOE)	+= -march=i686 $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
-cflags-$(CONFIG_MWINCHIPC6)	+= $(call check_gcc,-march=winchip-c6,-march=i586)
-cflags-$(CONFIG_MWINCHIP2)	+= $(call check_gcc,-march=winchip2,-march=i586)
-cflags-$(CONFIG_MWINCHIP3D)	+= $(call check_gcc,-march=winchip2,-march=i586)
-cflags-$(CONFIG_MCYRIXIII)	+= $(call check_gcc,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
-cflags-$(CONFIG_MVIAC3_2)	+= $(call check_gcc,-march=c3-2,-march=i686)
+cflags-$(CONFIG_MWINCHIPC6)	+= $(call cc-option,-march=winchip-c6,-march=i586)
+cflags-$(CONFIG_MWINCHIP2)	+= $(call cc-option,-march=winchip2,-march=i586)
+cflags-$(CONFIG_MWINCHIP3D)	+= $(call cc-option,-march=winchip2,-march=i586)
+cflags-$(CONFIG_MCYRIXIII)	+= $(call cc-option,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0
+cflags-$(CONFIG_MVIAC3_2)	+= $(call cc-option,-march=c3-2,-march=i686)
 
 # AMD Elan support
 cflags-$(CONFIG_X86_ELAN)	+= -march=i486
 
 # -mregparm=3 works ok on gcc-3.0 and later
 #
-GCC_VERSION			:= $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC))
+GCC_VERSION			:= $(call cc-version)
 cflags-$(CONFIG_REGPARM) 	+= $(shell if [ $(GCC_VERSION) -ge 0300 ] ; then echo "-mregparm=3"; fi ;)
 
 # Disable unit-at-a-time mode, it makes gcc use a lot more stack
 # due to the lack of sharing of stacklots.
-CFLAGS += $(call check_gcc,-fno-unit-at-a-time,)
+CFLAGS += $(call cc-option,-fno-unit-at-a-time)
 
 CFLAGS += $(cflags-y)
 
diff --git a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile
index d70853d99..aa7064a75 100644
--- a/arch/i386/boot/Makefile
+++ b/arch/i386/boot/Makefile
@@ -29,9 +29,9 @@ targets		:= vmlinux.bin bootsect bootsect.o setup setup.o \
 		   zImage bzImage
 subdir- 	:= compressed
 
-host-progs	:= tools/build
+hostprogs-y	:= tools/build
 
-HOSTCFLAGS_build.o := -Iinclude
+HOSTCFLAGS_build.o := $(LINUXINCLUDE)
 
 # ---------------------------------------------------------------------------
 
diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
index d606d0687..5623e821f 100644
--- a/arch/i386/boot/setup.S
+++ b/arch/i386/boot/setup.S
@@ -156,7 +156,7 @@ cmd_line_ptr:	.long 0			# (Header version 0x0202 or later)
 					# can be located anywhere in
 					# low memory 0x10000 or higher.
 
-ramdisk_max:	.long (MAXMEM-1) & 0x7fffffff
+ramdisk_max:	.long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff
 					# (Header version 0x0203 or later)
 					# The highest safe address for
 					# the contents of an initrd
diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S
index 7e2c665e6..a6e043c46 100644
--- a/arch/i386/boot/video.S
+++ b/arch/i386/boot/video.S
@@ -232,6 +232,41 @@ mopar_gr:
 	xorl	%eax, %eax
 	movw	18(%di), %ax
 	movl	%eax, %fs:(PARAM_LFB_SIZE)
+
+# switching the DAC to 8-bit is for <= 8 bpp only
+	movw	%fs:(PARAM_LFB_DEPTH), %ax
+	cmpw	$8, %ax
+	jg	dac_done
+
+# get DAC switching capability
+	xorl	%eax, %eax
+	movb	10(%di), %al
+	testb	$1, %al
+	jz	dac_set
+
+# attempt to switch DAC to 8-bit
+	movw	$0x4f08, %ax
+	movw	$0x0800, %bx
+	int	$0x10
+	cmpw	$0x004f, %ax
+	jne     dac_set
+	movb    %bh, dac_size		# store actual DAC size
+
+dac_set:
+# set color size to DAC size
+	movb	dac_size, %al
+	movb	%al, %fs:(PARAM_LFB_COLORS+0)
+	movb	%al, %fs:(PARAM_LFB_COLORS+2)
+	movb	%al, %fs:(PARAM_LFB_COLORS+4)
+	movb	%al, %fs:(PARAM_LFB_COLORS+6)
+
+# set color offsets to 0
+	movb	$0, %fs:(PARAM_LFB_COLORS+1)
+	movb	$0, %fs:(PARAM_LFB_COLORS+3)
+	movb	$0, %fs:(PARAM_LFB_COLORS+5)
+	movb	$0, %fs:(PARAM_LFB_COLORS+7)
+
+dac_done:
 # get protected mode interface informations
 	movw	$0x4f0a, %ax
 	xorw	%bx, %bx
@@ -1929,6 +1964,7 @@ scanning:	.byte	0	# Performing mode scan
 do_restore:	.byte	0	# Screen contents altered during mode change
 svga_prefix:	.byte	VIDEO_FIRST_BIOS>>8	# Default prefix for BIOS modes
 graphic_mode:	.byte	0	# Graphic mode with a linear frame buffer
+dac_size:	.byte	6	# DAC bit depth
 
 # Status messages
 keymsg:		.ascii	"Press <RETURN> to see video modes available, "
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 00cc32e33..3d828bbac 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-extra-y := head.o init_task.o vmlinux.lds.s
+extra-y := head.o init_task.o vmlinux.lds
 
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
 		ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
@@ -25,6 +25,7 @@ obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o nmi.o
 obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o
 obj-$(CONFIG_X86_NUMAQ)		+= numaq.o
 obj-$(CONFIG_X86_SUMMIT_NUMA)	+= summit.o
+obj-$(CONFIG_KPROBES)		+= kprobes.o
 obj-$(CONFIG_MODULES)		+= module.o
 obj-y				+= sysenter.o vsyscall.o
 obj-$(CONFIG_ACPI_SRAT) 	+= srat.o
@@ -41,12 +42,15 @@ obj-$(CONFIG_SCx200)		+= scx200.o
 # Note: kbuild does not track this dependency due to usage of .incbin
 $(obj)/vsyscall.o: $(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so
 targets += $(foreach F,int80 sysenter,vsyscall-$F.o vsyscall-$F.so)
+targets += vsyscall.lds
 
 # The DSO images are built using a special linker script.
 quiet_cmd_syscall = SYSCALL $@
       cmd_syscall = $(CC) -nostdlib $(SYSCFLAGS_$(@F)) \
 		          -Wl,-T,$(filter-out FORCE,$^) -o $@
 
+export CPPFLAGS_vsyscall.lds += -P -C -U$(ARCH)
+
 vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1
 SYSCFLAGS_vsyscall-sysenter.so	= $(vsyscall-flags)
 SYSCFLAGS_vsyscall-int80.so	= $(vsyscall-flags)
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index e54aefaa8..8a0536250 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -71,6 +71,7 @@ int acpi_ht __initdata = 1;	/* enable HT */
 int acpi_lapic;
 int acpi_ioapic;
 int acpi_strict;
+EXPORT_SYMBOL(acpi_strict);
 
 acpi_interrupt_flags acpi_sci_flags __initdata;
 int acpi_sci_override_gsi __initdata;
@@ -84,6 +85,11 @@ static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
 #warning ACPI uses CMPXCHG, i486 and later hardware
 #endif
 
+#define MAX_MADT_ENTRIES	256
+u8 x86_acpiid_to_apicid[MAX_MADT_ENTRIES] =
+			{ [0 ... MAX_MADT_ENTRIES-1] = 0xff };
+EXPORT_SYMBOL(x86_acpiid_to_apicid);
+
 /* --------------------------------------------------------------------------
                               Boot-time Configuration
    -------------------------------------------------------------------------- */
@@ -225,6 +231,8 @@ acpi_parse_lapic (
 	if (processor->flags.enabled == 0)
 		return 0;
 
+	x86_acpiid_to_apicid[processor->acpi_id] = processor->id;
+
 	mp_register_lapic (
 		processor->id,					   /* APIC ID */
 		processor->flags.enabled);			  /* Enabled? */
@@ -822,9 +830,15 @@ acpi_boot_init (void)
 	 */
 	error = acpi_blacklisted();
 	if (error) {
-		printk(KERN_WARNING PREFIX "BIOS listed in blacklist, disabling ACPI support\n");
-		disable_acpi();
-		return error;
+		extern int acpi_force;
+
+		if (acpi_force) {
+			printk(KERN_WARNING PREFIX "acpi=force override\n");
+		} else {
+			printk(KERN_WARNING PREFIX "Disabling ACPI support\n");
+			disable_acpi();
+			return error;
+		}
 	}
 
 	/*
diff --git a/arch/i386/kernel/acpi/sleep.c b/arch/i386/kernel/acpi/sleep.c
index 92fd1760a..2a12d12e3 100644
--- a/arch/i386/kernel/acpi/sleep.c
+++ b/arch/i386/kernel/acpi/sleep.c
@@ -77,10 +77,7 @@ void __init acpi_reserve_bootmem(void)
 		printk(KERN_ERR "ACPI: Wakeup code way too big, S3 disabled.\n");
 		return;
 	}
-#ifdef CONFIG_X86_PAE
-	printk(KERN_ERR "ACPI: S3 and PAE do not like each other for now, S3 disabled.\n");
-	return;
-#endif
+
 	acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE);
 	if (!acpi_wakeup_address)
 		printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n");
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index ecf2b632f..64c175ff4 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -39,6 +39,12 @@
 
 #include "io_ports.h"
 
+/*
+ * Debug level
+ */
+int apic_verbosity;
+
+
 static void apic_pm_activate(void);
 
 void __init apic_intr_init(void)
@@ -85,7 +91,7 @@ int get_physical_broadcast(void)
 	unsigned int lvr, version;
 	lvr = apic_read(APIC_LVR);
 	version = GET_APIC_VERSION(lvr);
-	if (version >= 0x14)
+	if (!APIC_INTEGRATED(version) || version >= 0x14)
 		return 0xff;
 	else
 		return 0xf;
@@ -173,7 +179,8 @@ void __init connect_bsp_APIC(void)
 		 * PIC mode, enable APIC mode in the IMCR, i.e.
 		 * connect BSP's local APIC to INT and NMI lines.
 		 */
-		printk("leaving PIC mode, enabling APIC mode.\n");
+		apic_printk(APIC_VERBOSE, "leaving PIC mode, "
+				"enabling APIC mode.\n");
 		outb(0x70, 0x22);
 		outb(0x01, 0x23);
 	}
@@ -189,7 +196,8 @@ void disconnect_bsp_APIC(void)
 		 * interrupts, including IPIs, won't work beyond
 		 * this point!  The only exception are INIT IPIs.
 		 */
-		printk("disabling APIC mode, entering PIC mode.\n");
+		apic_printk(APIC_VERBOSE, "disabling APIC mode, "
+				"entering PIC mode.\n");
 		outb(0x70, 0x22);
 		outb(0x00, 0x23);
 	}
@@ -230,10 +238,10 @@ int __init verify_local_APIC(void)
 	 * The version register is read-only in a real APIC.
 	 */
 	reg0 = apic_read(APIC_LVR);
-	Dprintk("Getting VERSION: %x\n", reg0);
+	apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg0);
 	apic_write(APIC_LVR, reg0 ^ APIC_LVR_MASK);
 	reg1 = apic_read(APIC_LVR);
-	Dprintk("Getting VERSION: %x\n", reg1);
+	apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg1);
 
 	/*
 	 * The two version reads above should print the same
@@ -257,7 +265,7 @@ int __init verify_local_APIC(void)
 	 * The ID register is read/write in a real APIC.
 	 */
 	reg0 = apic_read(APIC_ID);
-	Dprintk("Getting ID: %x\n", reg0);
+	apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0);
 
 	/*
 	 * The next two are just to see if we have sane values.
@@ -265,9 +273,9 @@ int __init verify_local_APIC(void)
 	 * compatibility mode, but most boxes are anymore.
 	 */
 	reg0 = apic_read(APIC_LVT0);
-	Dprintk("Getting LVT0: %x\n", reg0);
+	apic_printk(APIC_DEBUG, "Getting LVT0: %x\n", reg0);
 	reg1 = apic_read(APIC_LVT1);
-	Dprintk("Getting LVT1: %x\n", reg1);
+	apic_printk(APIC_DEBUG, "Getting LVT1: %x\n", reg1);
 
 	return 1;
 }
@@ -279,7 +287,7 @@ void __init sync_Arb_IDs(void)
 	 */
 	apic_wait_icr_idle();
 
-	Dprintk("Synchronizing Arb IDs.\n");
+	apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n");
 	apic_write_around(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG
 				| APIC_DM_INIT);
 }
@@ -335,7 +343,7 @@ void __init init_bsp_APIC(void)
 
 void __init setup_local_APIC (void)
 {
-	unsigned long value, ver, maxlvt;
+	unsigned long oldvalue, value, ver, maxlvt;
 
 	/* Pound the ESR really hard over the head with a big hammer - mbligh */
 	if (esr_disable) {
@@ -427,10 +435,12 @@ void __init setup_local_APIC (void)
 	value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
 	if (!smp_processor_id() && (pic_mode || !value)) {
 		value = APIC_DM_EXTINT;
-		printk("enabled ExtINT on CPU#%d\n", smp_processor_id());
+		apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n",
+				smp_processor_id());
 	} else {
 		value = APIC_DM_EXTINT | APIC_LVT_MASKED;
-		printk("masked ExtINT on CPU#%d\n", smp_processor_id());
+		apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n",
+				smp_processor_id());
 	}
 	apic_write_around(APIC_LVT0, value);
 
@@ -449,8 +459,7 @@ void __init setup_local_APIC (void)
 		maxlvt = get_maxlvt();
 		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP. */
 			apic_write(APIC_ESR, 0);
-		value = apic_read(APIC_ESR);
-		printk("ESR value before enabling vector: %08lx\n", value);
+		oldvalue = apic_read(APIC_ESR);
 
 		value = ERROR_APIC_VECTOR;      // enables sending errors
 		apic_write_around(APIC_LVTERR, value);
@@ -460,7 +469,10 @@ void __init setup_local_APIC (void)
 		if (maxlvt > 3)
 			apic_write(APIC_ESR, 0);
 		value = apic_read(APIC_ESR);
-		printk("ESR value after enabling vector: %08lx\n", value);
+		if (value != oldvalue)
+			apic_printk(APIC_VERBOSE, "ESR value before enabling "
+				"vector: 0x%08lx  after: 0x%08lx\n",
+				oldvalue, value);
 	} else {
 		if (esr_disable)	
 			/* 
@@ -635,6 +647,21 @@ static int __init lapic_enable(char *str)
 }
 __setup("lapic", lapic_enable);
 
+static int __init apic_set_verbosity(char *str)
+{
+	if (strcmp("debug", str) == 0)
+		apic_verbosity = APIC_DEBUG;
+	else if (strcmp("verbose", str) == 0)
+		apic_verbosity = APIC_VERBOSE;
+	else
+		printk(KERN_WARNING "APIC Verbosity level %s not recognised"
+				" use apic=verbose or apic=debug", str);
+
+	return 0;
+}
+
+__setup("apic=", apic_set_verbosity);
+
 static int __init detect_init_APIC (void)
 {
 	u32 h, l, features;
@@ -664,6 +691,12 @@ static int __init detect_init_APIC (void)
 	}
 
 	if (!cpu_has_apic) {
+		/*
+		 * Over-ride BIOS and try to enable LAPIC
+		 * only if "lapic" specified
+		 */
+		if (enable_local_apic != 1)
+			goto no_apic;
 		/*
 		 * Some BIOSes disable the local APIC in the
 		 * APIC_BASE MSR. This can only be done in
@@ -671,7 +704,8 @@ static int __init detect_init_APIC (void)
 		 */
 		rdmsr(MSR_IA32_APICBASE, l, h);
 		if (!(l & MSR_IA32_APICBASE_ENABLE)) {
-			printk("Local APIC disabled by BIOS -- reenabling.\n");
+			apic_printk(APIC_VERBOSE, "Local APIC disabled "
+					"by BIOS -- reenabling.\n");
 			l &= ~MSR_IA32_APICBASE_BASE;
 			l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
 			wrmsr(MSR_IA32_APICBASE, l, h);
@@ -698,7 +732,7 @@ static int __init detect_init_APIC (void)
 	if (nmi_watchdog != NMI_NONE)
 		nmi_watchdog = NMI_LOCAL_APIC;
 
-	printk("Found and enabled local APIC!\n");
+	apic_printk(APIC_VERBOSE, "Found and enabled local APIC!\n");
 
 	apic_pm_activate();
 
@@ -725,7 +759,8 @@ void __init init_apic_mappings(void)
 		apic_phys = mp_lapic_addr;
 
 	set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
-	Dprintk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys);
+	apic_printk(APIC_DEBUG, "mapped APIC to %08lx (%08lx)\n", APIC_BASE,
+			apic_phys);
 
 	/*
 	 * Fetch the APIC ID of the BSP in case we have a
@@ -755,7 +790,8 @@ fake_ioapic_page:
 				ioapic_phys = __pa(ioapic_phys);
 			}
 			set_fixmap_nocache(idx, ioapic_phys);
-			Dprintk("mapped IOAPIC to %08lx (%08lx)\n",
+			apic_printk(APIC_DEBUG, "mapped IOAPIC to "
+					"%08lx (%08lx)\n",
 					__fix_to_virt(idx), ioapic_phys);
 			idx++;
 		}
@@ -894,7 +930,7 @@ int __init calibrate_APIC_clock(void)
 	int i;
 	const int LOOPS = HZ/10;
 
-	printk("calibrating APIC timer ...\n");
+	apic_printk(APIC_VERBOSE, "calibrating APIC timer ...\n");
 
 	/*
 	 * Put whatever arbitrary (but long enough) timeout
@@ -939,11 +975,13 @@ int __init calibrate_APIC_clock(void)
 	result = (tt1-tt2)*APIC_DIVISOR/LOOPS;
 
 	if (cpu_has_tsc)
-		printk("..... CPU clock speed is %ld.%04ld MHz.\n",
+		apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
+			"%ld.%04ld MHz.\n",
 			((long)(t2-t1)/LOOPS)/(1000000/HZ),
 			((long)(t2-t1)/LOOPS)%(1000000/HZ));
 
-	printk("..... host bus clock speed is %ld.%04ld MHz.\n",
+	apic_printk(APIC_VERBOSE, "..... host bus clock speed is "
+		"%ld.%04ld MHz.\n",
 		result/(1000000/HZ),
 		result%(1000000/HZ));
 
@@ -954,7 +992,7 @@ static unsigned int calibration_result;
 
 void __init setup_boot_APIC_clock(void)
 {
-	printk("Using local APIC timer interrupts.\n");
+	apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n");
 	using_apic_timer = 1;
 
 	local_irq_disable();
@@ -1039,8 +1077,7 @@ inline void smp_local_timer_interrupt(struct pt_regs * regs)
 {
 	int cpu = smp_processor_id();
 
-	x86_do_profile(regs);
-
+	profile_tick(CPU_PROFILING, regs);
 	if (--per_cpu(prof_counter, cpu) <= 0) {
 		/*
 		 * The multiplier may have changed since the last time we got
@@ -1159,7 +1196,7 @@ asmlinkage void smp_error_interrupt(void)
 	   6: Received illegal vector
 	   7: Illegal register address
 	*/
-	printk (KERN_INFO "APIC error on CPU%d: %02lx(%02lx)\n",
+	printk (KERN_DEBUG "APIC error on CPU%d: %02lx(%02lx)\n",
 	        smp_processor_id(), v , v1);
 	irq_exit();
 }
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index 3b1ef4bcb..d9a80ba23 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -601,8 +601,8 @@ static u8 apm_bios_call(u32 func, u32 ebx_in, u32 ecx_in,
 	cpus = apm_save_cpus();
 	
 	cpu = get_cpu();
-	save_desc_40 = cpu_gdt_table[cpu][0x40 / 8];
-	cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc;
+	save_desc_40 = per_cpu(cpu_gdt_table, cpu)[0x40 / 8];
+	per_cpu(cpu_gdt_table, cpu)[0x40 / 8] = bad_bios_desc;
 
 	local_save_flags(flags);
 	APM_DO_CLI;
@@ -610,7 +610,7 @@ static u8 apm_bios_call(u32 func, u32 ebx_in, u32 ecx_in,
 	apm_bios_call_asm(func, ebx_in, ecx_in, eax, ebx, ecx, edx, esi);
 	APM_DO_RESTORE_SEGS;
 	local_irq_restore(flags);
-	cpu_gdt_table[cpu][0x40 / 8] = save_desc_40;
+	per_cpu(cpu_gdt_table, cpu)[0x40 / 8] = save_desc_40;
 	put_cpu();
 	apm_restore_cpus(cpus);
 	
@@ -644,8 +644,8 @@ static u8 apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax)
 	cpus = apm_save_cpus();
 	
 	cpu = get_cpu();
-	save_desc_40 = cpu_gdt_table[cpu][0x40 / 8];
-	cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc;
+	save_desc_40 = per_cpu(cpu_gdt_table, cpu)[0x40 / 8];
+	per_cpu(cpu_gdt_table, cpu)[0x40 / 8] = bad_bios_desc;
 
 	local_save_flags(flags);
 	APM_DO_CLI;
@@ -653,7 +653,7 @@ static u8 apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax)
 	error = apm_bios_call_simple_asm(func, ebx_in, ecx_in, eax);
 	APM_DO_RESTORE_SEGS;
 	local_irq_restore(flags);
-	cpu_gdt_table[smp_processor_id()][0x40 / 8] = save_desc_40;
+	__get_cpu_var(cpu_gdt_table)[0x40 / 8] = save_desc_40;
 	put_cpu();
 	apm_restore_cpus(cpus);
 	return error;
@@ -2271,10 +2271,12 @@ static int __init apm_init(void)
 	}
 	if ((num_online_cpus() > 1) && !power_off && !smp) {
 		printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
+		apm_info.disabled = 1;
 		return -ENODEV;
 	}
 	if (PM_IS_ACTIVE()) {
 		printk(KERN_NOTICE "apm: overridden by ACPI.\n");
+		apm_info.disabled = 1;
 		return -ENODEV;
 	}
 	pm_active = 1;
@@ -2292,35 +2294,35 @@ static int __init apm_init(void)
 	apm_bios_entry.segment = APM_CS;
 
 	for (i = 0; i < NR_CPUS; i++) {
-		set_base(cpu_gdt_table[i][APM_CS >> 3],
+		set_base(per_cpu(cpu_gdt_table, i)[APM_CS >> 3],
 			 __va((unsigned long)apm_info.bios.cseg << 4));
-		set_base(cpu_gdt_table[i][APM_CS_16 >> 3],
+		set_base(per_cpu(cpu_gdt_table, i)[APM_CS_16 >> 3],
 			 __va((unsigned long)apm_info.bios.cseg_16 << 4));
-		set_base(cpu_gdt_table[i][APM_DS >> 3],
+		set_base(per_cpu(cpu_gdt_table, i)[APM_DS >> 3],
 			 __va((unsigned long)apm_info.bios.dseg << 4));
 #ifndef APM_RELAX_SEGMENTS
 		if (apm_info.bios.version == 0x100) {
 #endif
 			/* For ASUS motherboard, Award BIOS rev 110 (and others?) */
-			_set_limit((char *)&cpu_gdt_table[i][APM_CS >> 3], 64 * 1024 - 1);
+			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS >> 3], 64 * 1024 - 1);
 			/* For some unknown machine. */
-			_set_limit((char *)&cpu_gdt_table[i][APM_CS_16 >> 3], 64 * 1024 - 1);
+			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS_16 >> 3], 64 * 1024 - 1);
 			/* For the DEC Hinote Ultra CT475 (and others?) */
-			_set_limit((char *)&cpu_gdt_table[i][APM_DS >> 3], 64 * 1024 - 1);
+			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_DS >> 3], 64 * 1024 - 1);
 #ifndef APM_RELAX_SEGMENTS
 		} else {
-			_set_limit((char *)&cpu_gdt_table[i][APM_CS >> 3],
+			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS >> 3],
 				(apm_info.bios.cseg_len - 1) & 0xffff);
-			_set_limit((char *)&cpu_gdt_table[i][APM_CS_16 >> 3],
+			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS_16 >> 3],
 				(apm_info.bios.cseg_16_len - 1) & 0xffff);
-			_set_limit((char *)&cpu_gdt_table[i][APM_DS >> 3],
+			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_DS >> 3],
 				(apm_info.bios.dseg_len - 1) & 0xffff);
 		      /* workaround for broken BIOSes */
 	                if (apm_info.bios.cseg_len <= apm_info.bios.offset)
-        	                _set_limit((char *)&cpu_gdt_table[i][APM_CS >> 3], 64 * 1024 -1);
+        	                _set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS >> 3], 64 * 1024 -1);
                        if (apm_info.bios.dseg_len <= 0x40) { /* 0x40 * 4kB == 64kB */
                         	/* for the BIOS that assumes granularity = 1 */
-                        	cpu_gdt_table[i][APM_DS >> 3].b |= 0x800000;
+                        	per_cpu(cpu_gdt_table, i)[APM_DS >> 3].b |= 0x800000;
                         	printk(KERN_NOTICE "apm: we set the granularity of dseg.\n");
         	        }
 		}
@@ -2360,8 +2362,15 @@ static void __exit apm_exit(void)
 {
 	int	error;
 
-	if (set_pm_idle)
+	if (set_pm_idle) {
 		pm_idle = original_pm_idle;
+		/*
+		 * 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.
+		 */
+		synchronize_kernel();
+	}
 	if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0)
 	    && (apm_info.connection_version > 0x0100)) {
 		error = apm_engage_power_management(APM_DEVICE_ALL, 0);
diff --git a/arch/i386/kernel/asm-offsets.c b/arch/i386/kernel/asm-offsets.c
index 6248bf257..38d82e380 100644
--- a/arch/i386/kernel/asm-offsets.c
+++ b/arch/i386/kernel/asm-offsets.c
@@ -62,4 +62,5 @@ void foo(void)
 		 sizeof(struct tss_struct));
 
 	DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
+	DEFINE(VSYSCALL_BASE, __fix_to_virt(FIX_VSYSCALL));
 }
diff --git a/arch/i386/kernel/cpu/centaur.c b/arch/i386/kernel/cpu/centaur.c
index e85f4827e..394814e57 100644
--- a/arch/i386/kernel/cpu/centaur.c
+++ b/arch/i386/kernel/cpu/centaur.c
@@ -286,23 +286,20 @@ static void __init init_c3(struct cpuinfo_x86 *c)
 		c->x86_capability[5] = cpuid_edx(0xC0000001);
 	}
 
-	switch (c->x86_model) {
-		case 6 ... 8:		/* Cyrix III family */
-			rdmsr (MSR_VIA_FCR, lo, hi);
-			lo |= (1<<1 | 1<<7);	/* Report CX8 & enable PGE */
-			wrmsr (MSR_VIA_FCR, lo, hi);
-
-			set_bit(X86_FEATURE_CX8, c->x86_capability);
-			set_bit(X86_FEATURE_3DNOW, c->x86_capability);
+	/* Cyrix III family needs CX8 & PGE explicity enabled. */
+	if (c->x86_model >=6 && c->x86_model <= 9) {
+		rdmsr (MSR_VIA_FCR, lo, hi);
+		lo |= (1<<1 | 1<<7);
+		wrmsr (MSR_VIA_FCR, lo, hi);
+		set_bit(X86_FEATURE_CX8, c->x86_capability);
+	}
 
-			/* fall through */
+	/* Before Nehemiah, the C3's had 3dNOW! */
+	if (c->x86_model >=6 && c->x86_model <9)
+		set_bit(X86_FEATURE_3DNOW, c->x86_capability);
 
-		case 9:	/* Nehemiah */
-		default:
-			get_model_name(c);
-			display_cacheinfo(c);
-			break;
-	}
+	get_model_name(c);
+	display_cacheinfo(c);
 }
 
 static void __init init_centaur(struct cpuinfo_x86 *c)
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 30e25e357..89dc79a65 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -2,6 +2,8 @@
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/smp.h>
+#include <linux/module.h>
+#include <linux/percpu.h>
 #include <asm/semaphore.h>
 #include <asm/processor.h>
 #include <asm/i387.h>
@@ -11,6 +13,9 @@
 
 #include "cpu.h"
 
+DEFINE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]);
+EXPORT_PER_CPU_SYMBOL(cpu_gdt_table);
+
 static int cachesize_override __initdata = -1;
 static int disable_x86_fxsr __initdata = 0;
 static int disable_x86_serial_nr __initdata = 1;
@@ -501,7 +506,7 @@ void __init early_cpu_init(void)
 void __init cpu_init (void)
 {
 	int cpu = smp_processor_id();
-	struct tss_struct * t = init_tss + cpu;
+	struct tss_struct * t = &per_cpu(init_tss, cpu);
 	struct thread_struct *thread = &current->thread;
 
 	if (test_and_set_bit(cpu, &cpu_initialized)) {
@@ -523,15 +528,17 @@ void __init cpu_init (void)
 	 * Initialize the per-CPU GDT with the boot GDT,
 	 * and set up the GDT descriptor:
 	 */
-	if (cpu) {
-		memcpy(cpu_gdt_table[cpu], cpu_gdt_table[0], GDT_SIZE);
-		cpu_gdt_descr[cpu].size = GDT_SIZE - 1;
-		cpu_gdt_descr[cpu].address = (unsigned long)cpu_gdt_table[cpu];
-	}
+	memcpy(&per_cpu(cpu_gdt_table, cpu), cpu_gdt_table,
+	       GDT_SIZE);
+	cpu_gdt_descr[cpu].size = GDT_SIZE - 1;
+	cpu_gdt_descr[cpu].address =
+	    (unsigned long)&per_cpu(cpu_gdt_table, cpu);
+
 	/*
 	 * Set up the per-thread TLS descriptor cache:
 	 */
-	memcpy(thread->tls_array, cpu_gdt_table[cpu], GDT_ENTRY_TLS_ENTRIES * 8);
+	memcpy(thread->tls_array, &per_cpu(cpu_gdt_table, cpu),
+		GDT_ENTRY_TLS_ENTRIES * 8);
 
 	__asm__ __volatile__("lgdt %0" : : "m" (cpu_gdt_descr[cpu]));
 	__asm__ __volatile__("lidt %0" : : "m" (idt_descr));
@@ -552,13 +559,11 @@ void __init cpu_init (void)
 
 	load_esp0(t, thread);
 	set_tss_desc(cpu,t);
-	cpu_gdt_table[cpu][GDT_ENTRY_TSS].b &= 0xfffffdff;
 	load_TR_desc();
 	load_LDT(&init_mm.context);
 
 	/* Set up doublefault TSS pointer in the GDT */
 	__set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss);
-	cpu_gdt_table[cpu][GDT_ENTRY_DOUBLEFAULT_TSS].b &= 0xfffffdff;
 
 	/* Clear %fs and %gs. */
 	asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs");
diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig
index d285dc1ba..5cd444214 100644
--- a/arch/i386/kernel/cpu/cpufreq/Kconfig
+++ b/arch/i386/kernel/cpu/cpufreq/Kconfig
@@ -88,6 +88,11 @@ config X86_POWERNOW_K7
 
 	  If in doubt, say N.
 
+config X86_POWERNOW_K7_ACPI
+	bool
+	depends on ((X86_POWERNOW_K7 = "m" && ACPI_PROCESSOR) || (X86_POWERNOW_K7 = "y" && ACPI_PROCESSOR = "y"))
+	default y
+
 config X86_POWERNOW_K8
 	tristate "AMD Opteron/Athlon64 PowerNow!"
 	depends on CPU_FREQ && EXPERIMENTAL
@@ -98,6 +103,11 @@ config X86_POWERNOW_K8
 
 	  If in doubt, say N.
 
+config X86_POWERNOW_K8_ACPI
+	bool
+	depends on ((X86_POWERNOW_K8 = "m" && ACPI_PROCESSOR) || (X86_POWERNOW_K8 = "y" && ACPI_PROCESSOR = "y"))
+	default y
+
 config X86_GX_SUSPMOD
 	tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation"
 	depends on CPU_FREQ
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi.c b/arch/i386/kernel/cpu/cpufreq/acpi.c
index 8c056882d..4ba912733 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi.c
@@ -108,13 +108,27 @@ acpi_processor_set_performance (
 	u32			value = 0;
 	int			i = 0;
 	struct cpufreq_freqs    cpufreq_freqs;
+	cpumask_t		saved_mask;
+	int			retval;
 
 	ACPI_FUNCTION_TRACE("acpi_processor_set_performance");
 
+	/*
+	 * TBD: Use something other than set_cpus_allowed.
+	 * As set_cpus_allowed is a bit racy, 
+	 * with any other set_cpus_allowed for this process.
+	 */
+	saved_mask = current->cpus_allowed;
+	set_cpus_allowed(current, cpumask_of_cpu(cpu));
+	if (smp_processor_id() != cpu) {
+		return_VALUE(-EAGAIN);
+	}
+	
 	if (state == data->acpi_data.state) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
 			"Already at target state (P%d)\n", state));
-		return_VALUE(0);
+		retval = 0;
+		goto migrate_end;
 	}
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Transitioning from P%d to P%d\n",
@@ -144,7 +158,8 @@ acpi_processor_set_performance (
 	if (ret) {
 		ACPI_DEBUG_PRINT((ACPI_DB_WARN,
 			"Invalid port width 0x%04x\n", bit_width));
-		return_VALUE(ret);
+		retval = ret;
+		goto migrate_end;
 	}
 
 	/*
@@ -166,7 +181,8 @@ acpi_processor_set_performance (
 		if (ret) {	
 			ACPI_DEBUG_PRINT((ACPI_DB_WARN,
 				"Invalid port width 0x%04x\n", bit_width));
-			return_VALUE(ret);
+			retval = ret;
+			goto migrate_end;
 		}
 		if (value == (u32) data->acpi_data.states[state].status)
 			break;
@@ -183,7 +199,8 @@ acpi_processor_set_performance (
 		cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
 		cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
 		ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Transition failed\n"));
-		return_VALUE(-ENODEV);
+		retval = -ENODEV;
+		goto migrate_end;
 	}
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
@@ -192,7 +209,10 @@ acpi_processor_set_performance (
 
 	data->acpi_data.state = state;
 
-	return_VALUE(0);
+	retval = 0;
+migrate_end:
+	set_cpus_allowed(current, saved_mask);
+	return_VALUE(retval);
 }
 
 
@@ -266,6 +286,69 @@ acpi_cpufreq_guess_freq (
 	
 }
 
+
+/* 
+ * acpi_processor_cpu_init_pdc_est - let BIOS know about the SMP capabilities
+ * of this driver
+ * @perf: processor-specific acpi_io_data struct
+ * @cpu: CPU being initialized
+ *
+ * To avoid issues with legacy OSes, some BIOSes require to be informed of
+ * the SMP capabilities of OS P-state driver. Here we set the bits in _PDC 
+ * accordingly, for Enhanced Speedstep. Actual call to _PDC is done in
+ * driver/acpi/processor.c
+ */
+static void 
+acpi_processor_cpu_init_pdc_est(
+		struct acpi_processor_performance *perf, 
+		unsigned int cpu,
+		struct acpi_object_list *obj_list
+		)
+{
+	union acpi_object *obj;
+	u32 *buf;
+	struct cpuinfo_x86 *c = cpu_data + cpu;
+	ACPI_FUNCTION_TRACE("acpi_processor_cpu_init_pdc_est");
+
+	if (!cpu_has(c, X86_FEATURE_EST))
+		return_VOID;
+
+	/* Initialize pdc. It will be used later. */
+	if (!obj_list)
+		return_VOID;
+		
+	if (!(obj_list->count && obj_list->pointer))
+		return_VOID;
+
+	obj = obj_list->pointer;
+	if ((obj->buffer.length == 12) && obj->buffer.pointer) {
+		buf = (u32 *)obj->buffer.pointer;
+       		buf[0] = ACPI_PDC_REVISION_ID;
+       		buf[1] = 1;
+       		buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
+		perf->pdc = obj_list;
+	}
+	return_VOID;
+}
+ 
+
+/* CPU specific PDC initialization */
+static void 
+acpi_processor_cpu_init_pdc(
+		struct acpi_processor_performance *perf, 
+		unsigned int cpu,
+		struct acpi_object_list *obj_list
+		)
+{
+	struct cpuinfo_x86 *c = cpu_data + cpu;
+	ACPI_FUNCTION_TRACE("acpi_processor_cpu_init_pdc");
+	perf->pdc = NULL;
+	if (cpu_has(c, X86_FEATURE_EST))
+		acpi_processor_cpu_init_pdc_est(perf, cpu, obj_list);
+	return_VOID;
+}
+
+
 static int
 acpi_cpufreq_cpu_init (
 	struct cpufreq_policy   *policy)
@@ -275,7 +358,14 @@ acpi_cpufreq_cpu_init (
 	struct cpufreq_acpi_io	*data;
 	unsigned int		result = 0;
 
+	union acpi_object		arg0 = {ACPI_TYPE_BUFFER};
+	u32				arg0_buf[3];
+	struct acpi_object_list 	arg_list = {1, &arg0};
+
 	ACPI_FUNCTION_TRACE("acpi_cpufreq_cpu_init");
+	/* setup arg_list for _PDC settings */
+        arg0.buffer.length = 12;
+        arg0.buffer.pointer = (u8 *) arg0_buf;
 
 	data = kmalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
 	if (!data)
@@ -284,7 +374,10 @@ acpi_cpufreq_cpu_init (
 
 	acpi_io_data[cpu] = data;
 
+	acpi_processor_cpu_init_pdc(&data->acpi_data, cpu, &arg_list);
 	result = acpi_processor_register_performance(&data->acpi_data, cpu);
+	data->acpi_data.pdc = NULL;
+
 	if (result)
 		goto err_free;
 
diff --git a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
index fefaf45a0..1f855c54c 100644
--- a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
+++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
@@ -297,6 +297,7 @@ static void gx_set_cpuspeed(unsigned int khz)
 		case PCI_DEVICE_ID_CYRIX_5520:
 		case PCI_DEVICE_ID_CYRIX_5510:
 			suscfg = gx_params->pci_suscfg | SUSMOD;
+			break;
 		default:
 			local_irq_restore(flags);
 			dprintk("fatal: try to set unknown chipset.\n");
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index 57c0377b4..e243f0fdd 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -5,14 +5,19 @@
  *  Licensed under the terms of the GNU GPL License version 2.
  *  Based upon datasheets & sample CPUs kindly provided by VIA.
  *
- *  VIA have currently 2 different versions of Longhaul.
+ *  VIA have currently 3 different versions of Longhaul.
  *  Version 1 (Longhaul) uses the BCR2 MSR at 0x1147.
- *   It is present only in Samuel 1, Samuel 2 and Ezra.
- *  Version 2 (Powersaver) uses the POWERSAVER MSR at 0x110a.
- *   It is present in Ezra-T, Nehemiah and above.
- *   In addition to scaling multiplier, it can also scale voltage.
- *   There is provision for scaling FSB too, but this doesn't work
- *   too well in practice.
+ *   It is present only in Samuel 1 (C5A), Samuel 2 (C5B) stepping 0.
+ *  Version 2 of longhaul is the same as v1, but adds voltage scaling.
+ *   Present in Samuel 2 (steppings 1-7 only) (C5B), and Ezra (C5C)
+ *   voltage scaling support has currently been disabled in this driver
+ *   until we have code that gets it right.
+ *  Version 3 of longhaul got renamed to Powersaver and redesigned
+ *   to use the POWERSAVER MSR at 0x110a.
+ *   It is present in Ezra-T (C5M), Nehemiah (C5X) and above.
+ *   It's pretty much the same feature wise to longhaul v2, though
+ *   there is provision for scaling FSB too, but this doesn't work
+ *   too well in practice so we don't even try to use this.
  *
  *  BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
  */
@@ -33,6 +38,17 @@
 
 #define PFX "longhaul: "
 
+#define TYPE_LONGHAUL_V1	1
+#define TYPE_LONGHAUL_V2	2
+#define TYPE_POWERSAVER		3
+
+#define	CPU_SAMUEL	1
+#define	CPU_SAMUEL2	2
+#define	CPU_EZRA	3
+#define	CPU_EZRA_T	4
+#define	CPU_NEHEMIAH	5
+
+static int cpu_model;
 static unsigned int numscales=16, numvscales;
 static unsigned int fsb;
 static int minvid, maxvid;
@@ -68,9 +84,23 @@ static int voltage_table[32];
 static unsigned int highest_speed, lowest_speed; /* kHz */
 static int longhaul_version;
 static struct cpufreq_frequency_table *longhaul_table;
+static char speedbuffer[8];
+
+static char *print_speed(int speed)
+{
+	if (speed > 1000) {
+		if (speed%1000 == 0)
+			sprintf (speedbuffer, "%dGHz", speed/1000);
+		else
+			sprintf (speedbuffer, "%d.%dGHz", speed/1000, (speed%1000)/100);
+	} else
+		sprintf (speedbuffer, "%dMHz", speed);
+
+	return speedbuffer;
+}
 
 
-static unsigned int calc_speed(int mult, int fsb)
+static unsigned int calc_speed(int mult)
 {
 	int khz;
 	khz = (mult/10)*fsb;
@@ -87,7 +117,7 @@ static int longhaul_get_cpu_mult(void)
 
 	rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi);
 	invalue = (lo & (1<<22|1<<23|1<<24|1<<25)) >>22;
-	if (longhaul_version==2 || longhaul_version==3) {
+	if (longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) {
 		if (lo & (1<<27))
 			invalue+=16;
 	}
@@ -95,11 +125,45 @@ static int longhaul_get_cpu_mult(void)
 }
 
 
+static void do_powersaver(union msr_longhaul *longhaul,
+			unsigned int clock_ratio_index)
+{
+	int version;
+
+	switch (cpu_model) {
+	case CPU_EZRA_T:
+		version = 3;
+		break;
+	case CPU_NEHEMIAH:
+		version = 0xf;
+		break;
+	default:
+		return;
+	}
+
+	rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
+	longhaul->bits.SoftBusRatio = clock_ratio_index & 0xf;
+	longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
+	longhaul->bits.EnableSoftBusRatio = 1;
+	longhaul->bits.RevisionKey = 0;
+	local_irq_disable();
+	wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
+	local_irq_enable();
+	__hlt();
+
+	rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
+	longhaul->bits.EnableSoftBusRatio = 0;
+	longhaul->bits.RevisionKey = version;
+	local_irq_disable();
+	wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
+	local_irq_enable();
+}
+
 /**
  * longhaul_set_cpu_frequency()
  * @clock_ratio_index : bitpattern of the new multiplier.
  *
- * Sets a new clock ratio, and -if applicable- a new Front Side Bus
+ * Sets a new clock ratio.
  */
 
 static void longhaul_setstate(unsigned int clock_ratio_index)
@@ -108,79 +172,71 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
 	struct cpufreq_freqs freqs;
 	union msr_longhaul longhaul;
 	union msr_bcr2 bcr2;
+	static unsigned int old_ratio=-1;
+
+	if (old_ratio == clock_ratio_index)
+		return;
+	old_ratio = clock_ratio_index;
 
 	mult = clock_ratio[clock_ratio_index];
 	if (mult == -1)
 		return;
 
-	speed = calc_speed (mult, fsb);
+	speed = calc_speed(mult);
 	if ((speed > highest_speed) || (speed < lowest_speed))
 		return;
 
-	freqs.old = calc_speed (longhaul_get_cpu_mult(), fsb);
+	freqs.old = calc_speed(longhaul_get_cpu_mult());
 	freqs.new = speed;
 	freqs.cpu = 0; /* longhaul.c is UP only driver */
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
-	dprintk (KERN_INFO PFX "FSB:%d Mult:%d.%dx\n", fsb, mult/10, mult%10);
+	dprintk (KERN_INFO PFX "Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
+			fsb, mult/10, mult%10, print_speed(speed/1000));
 
 	switch (longhaul_version) {
-	case 1:
+
+	/*
+	 * Longhaul v1. (Samuel[C5A] and Samuel2 stepping 0[C5B])
+	 * Software controlled multipliers only.
+	 *
+	 * *NB* Until we get voltage scaling working v1 & v2 are the same code.
+	 * Longhaul v2 appears in Samuel2 Steppings 1->7 [C5b] and Ezra [C5C]
+	 */
+	case TYPE_LONGHAUL_V1:
+	case TYPE_LONGHAUL_V2:
 		rdmsrl (MSR_VIA_BCR2, bcr2.val);
 		/* Enable software clock multiplier */
 		bcr2.bits.ESOFTBF = 1;
 		bcr2.bits.CLOCKMUL = clock_ratio_index;
+		local_irq_disable();
 		wrmsrl (MSR_VIA_BCR2, bcr2.val);
+		local_irq_enable();
 
 		__hlt();
 
 		/* Disable software clock multiplier */
 		rdmsrl (MSR_VIA_BCR2, bcr2.val);
 		bcr2.bits.ESOFTBF = 0;
+		local_irq_disable();
 		wrmsrl (MSR_VIA_BCR2, bcr2.val);
+		local_irq_enable();
 		break;
 
 	/*
-	 * Powersaver. (Ezra-T [C5M], Nehemiah [C5N])
+	 * Longhaul v3 (aka Powersaver). (Ezra-T [C5M] & Nehemiah [C5N])
 	 * We can scale voltage with this too, but that's currently
 	 * disabled until we come up with a decent 'match freq to voltage'
 	 * algorithm.
-	 * We also need to do the voltage/freq setting in order depending
-	 * on the direction of scaling (like we do in powernow-k7.c)
-	 * Ezra-T was alleged to do FSB scaling too, but it never worked in practice.
+	 * When we add voltage scaling, we will also need to do the
+	 * voltage/freq setting in order depending on the direction
+	 * of scaling (like we do in powernow-k7.c)
+	 * Nehemiah can do FSB scaling too, but this has never been proven
+	 * to work in practice.
 	 */
-	case 2:
-		rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
-		longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf;
-		longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
-		longhaul.bits.EnableSoftBusRatio = 1;
-		/* We must program the revision key only with values we
-		 * know about, not blindly copy it from 0:3 */
-		longhaul.bits.RevisionKey = 3;	/* SoftVID & SoftBSEL */
-		wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
-		__hlt();
-
-		rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
-		longhaul.bits.EnableSoftBusRatio = 0;
-		longhaul.bits.RevisionKey = 3;
-		wrmsrl (MSR_VIA_LONGHAUL, longhaul.val);
-		break;
-	case 3:
-		rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
-		longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf;
-		longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
-		longhaul.bits.EnableSoftBusRatio = 1;
-
-		longhaul.bits.RevisionKey = 0x0;
-
-		wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
-		__hlt();
-
-		rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
-		longhaul.bits.EnableSoftBusRatio = 0;
-		longhaul.bits.RevisionKey = 0xf;
-		wrmsrl (MSR_VIA_LONGHAUL, longhaul.val);
+	case TYPE_POWERSAVER:
+		do_powersaver(&longhaul, clock_ratio_index);
 		break;
 	}
 
@@ -230,7 +286,6 @@ static int guess_fsb(void)
 
 static int __init longhaul_get_ranges(void)
 {
-	struct cpuinfo_x86 *c = cpu_data;
 	unsigned long invalue;
 	unsigned int multipliers[32]= {
 		50,30,40,100,55,35,45,95,90,70,80,60,120,75,85,65,
@@ -242,58 +297,66 @@ static int __init longhaul_get_ranges(void)
 	unsigned int eblcr_fsb_table_v2[] = { 133, 100, -1, 66 };
 
 	switch (longhaul_version) {
-	case 1:
+	case TYPE_LONGHAUL_V1:
+	case TYPE_LONGHAUL_V2:
 		/* Ugh, Longhaul v1 didn't have the min/max MSRs.
 		   Assume min=3.0x & max = whatever we booted at. */
 		minmult = 30;
 		maxmult = longhaul_get_cpu_mult();
 		rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi);
 		invalue = (lo & (1<<18|1<<19)) >>18;
-		if (c->x86_model==6)
+		if (cpu_model==CPU_SAMUEL || cpu_model==CPU_SAMUEL2)
 			fsb = eblcr_fsb_table_v1[invalue];
 		else
 			fsb = guess_fsb();
 		break;
 
-	case 2:
-		rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
-
-		invalue = longhaul.bits.MaxMHzBR;
-		if (longhaul.bits.MaxMHzBR4)
-			invalue += 16;
-		maxmult=multipliers[invalue];
-
-		invalue = longhaul.bits.MinMHzBR;
-		if (longhaul.bits.MinMHzBR4 == 1)
-			minmult = 30;
-		else
-			minmult = multipliers[invalue];
-
-		fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
-		break;
+	case TYPE_POWERSAVER:
+		/* Ezra-T */
+		if (cpu_model==CPU_EZRA_T) {
+			rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
+			invalue = longhaul.bits.MaxMHzBR;
+			if (longhaul.bits.MaxMHzBR4)
+				invalue += 16;
+			maxmult=multipliers[invalue];
+
+			invalue = longhaul.bits.MinMHzBR;
+			if (longhaul.bits.MinMHzBR4 == 1)
+				minmult = 30;
+			else
+				minmult = multipliers[invalue];
+			fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
+			break;
+		}
 
-	case 3:
-		rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
-
-		/*
-		 * TODO: This code works, but raises a lot of questions.
-		 * - Some Nehemiah's seem to have broken Min/MaxMHzBR's.
-		 *   We get around this by using a hardcoded multiplier of 5.0x
-		 *   for the minimimum speed, and the speed we booted up at for the max.
-		 *   This is done in longhaul_get_cpu_mult() by reading the EBLCR register.
-		 * - According to some VIA documentation EBLCR is only
-		 *   in pre-Nehemiah C3s. How this still works is a mystery.
-		 *   We're possibly using something undocumented and unsupported,
-		 *   But it works, so we don't grumble.
-		 */
-		minmult=50;
-		maxmult=longhaul_get_cpu_mult();
-
-		fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
-		break;
+		/* Nehemiah */
+		if (cpu_model==CPU_NEHEMIAH) {
+			rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
+
+			/*
+			 * TODO: This code works, but raises a lot of questions.
+			 * - Some Nehemiah's seem to have broken Min/MaxMHzBR's.
+			 *   We get around this by using a hardcoded multiplier of 4.0x
+			 *   for the minimimum speed, and the speed we booted up at for the max.
+			 *   This is done in longhaul_get_cpu_mult() by reading the EBLCR register.
+			 * - According to some VIA documentation EBLCR is only
+			 *   in pre-Nehemiah C3s. How this still works is a mystery.
+			 *   We're possibly using something undocumented and unsupported,
+			 *   But it works, so we don't grumble.
+			 */
+			minmult=40;
+			maxmult=longhaul_get_cpu_mult();
+
+			/* Starting with the 1.2GHz parts, theres a 200MHz bus. */
+			if ((cpu_khz/1000) > 1200)
+				fsb = 200;
+			else
+				fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB];
+			break;
+		}
 	}
 
-	dprintk (KERN_INFO PFX "MinMult=%d.%dx MaxMult=%d.%dx\n",
+	dprintk (KERN_INFO PFX "MinMult:%d.%dx MaxMult:%d.%dx\n",
 		 minmult/10, minmult%10, maxmult/10, maxmult%10);
 
 	if (fsb == -1) {
@@ -301,10 +364,11 @@ static int __init longhaul_get_ranges(void)
 		return -EINVAL;
 	}
 
-	highest_speed = calc_speed (maxmult, fsb);
-	lowest_speed = calc_speed (minmult,fsb);
-	dprintk (KERN_INFO PFX "FSB: %dMHz Lowestspeed=%dMHz Highestspeed=%dMHz\n",
-		 fsb, lowest_speed/1000, highest_speed/1000);
+	highest_speed = calc_speed(maxmult);
+	lowest_speed = calc_speed(minmult);
+	dprintk (KERN_INFO PFX "FSB:%dMHz  ", fsb);
+	dprintk ("Lowest speed:%s  ", print_speed(lowest_speed/1000));
+	dprintk ("Highest speed:%s\n", print_speed(highest_speed/1000));
 
 	if (lowest_speed == highest_speed) {
 		printk (KERN_INFO PFX "highestspeed == lowest, aborting.\n");
@@ -327,7 +391,7 @@ static int __init longhaul_get_ranges(void)
 			continue;
 		if (ratio > maxmult || ratio < minmult)
 			continue;
-		longhaul_table[k].frequency = calc_speed (ratio, fsb);
+		longhaul_table[k].frequency = calc_speed(ratio);
 		longhaul_table[k].index	= j;
 		k++;
 	}
@@ -403,8 +467,7 @@ static int longhaul_verify(struct cpufreq_policy *policy)
 
 
 static int longhaul_target(struct cpufreq_policy *policy,
-			    unsigned int target_freq,
-			    unsigned int relation)
+			    unsigned int target_freq, unsigned int relation)
 {
 	unsigned int table_index = 0;
 	unsigned int new_clock_ratio = 0;
@@ -419,13 +482,15 @@ static int longhaul_target(struct cpufreq_policy *policy,
 	return 0;
 }
 
+
 static unsigned int longhaul_get(unsigned int cpu)
 {
 	if (cpu)
 		return 0;
-	return (calc_speed (longhaul_get_cpu_mult(), fsb));
+	return calc_speed(longhaul_get_cpu_mult());
 }
 
+
 static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
 {
 	struct cpuinfo_x86 *c = cpu_data;
@@ -434,26 +499,31 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
 
 	switch (c->x86_model) {
 	case 6:
+		cpu_model = CPU_SAMUEL;
 		cpuname = "C3 'Samuel' [C5A]";
-		longhaul_version=1;
+		longhaul_version = TYPE_LONGHAUL_V1;
 		memcpy (clock_ratio, samuel1_clock_ratio, sizeof(samuel1_clock_ratio));
 		memcpy (eblcr_table, samuel1_eblcr, sizeof(samuel1_eblcr));
 		break;
 
-	case 7:		/* C5B / C5C */
-		longhaul_version=1;
+	case 7:
+		longhaul_version = TYPE_LONGHAUL_V1;
 		switch (c->x86_mask) {
 		case 0:
+			cpu_model = CPU_SAMUEL2;
 			cpuname = "C3 'Samuel 2' [C5B]";
 			/* Note, this is not a typo, early Samuel2's had Samuel1 ratios. */
 			memcpy (clock_ratio, samuel1_clock_ratio, sizeof(samuel1_clock_ratio));
 			memcpy (eblcr_table, samuel2_eblcr, sizeof(samuel2_eblcr));
 			break;
 		case 1 ... 15:
-			if (c->x86_mask < 8)
+			if (c->x86_mask < 8) {
+				cpu_model = CPU_SAMUEL2;
 				cpuname = "C3 'Samuel 2' [C5B]";
-			else
+			} else {
+				cpu_model = CPU_EZRA;
 				cpuname = "C3 'Ezra' [C5C]";
+			}
 			memcpy (clock_ratio, ezra_clock_ratio, sizeof(ezra_clock_ratio));
 			memcpy (eblcr_table, ezra_eblcr, sizeof(ezra_eblcr));
 			break;
@@ -461,15 +531,17 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
 		break;
 
 	case 8:
+		cpu_model = CPU_EZRA_T;
 		cpuname = "C3 'Ezra-T' [C5M]";
-		longhaul_version=2;
+		longhaul_version = TYPE_POWERSAVER;
 		numscales=32;
 		memcpy (clock_ratio, ezrat_clock_ratio, sizeof(ezrat_clock_ratio));
 		memcpy (eblcr_table, ezrat_eblcr, sizeof(ezrat_eblcr));
 		break;
 
 	case 9:
-		longhaul_version=3;
+		cpu_model = CPU_NEHEMIAH;
+		longhaul_version = TYPE_POWERSAVER;
 		numscales=32;
 		switch (c->x86_mask) {
 		case 0 ... 1:
@@ -495,19 +567,28 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
 		break;
 	}
 
-	printk (KERN_INFO PFX "VIA %s CPU detected. Longhaul v%d supported.\n",
-					cpuname, longhaul_version);
+	printk (KERN_INFO PFX "VIA %s CPU detected.  ", cpuname);
+	switch (longhaul_version) {
+	case TYPE_LONGHAUL_V1:
+	case TYPE_LONGHAUL_V2:
+		printk ("Longhaul v%d supported.\n", longhaul_version);
+		break;
+	case TYPE_POWERSAVER:
+		printk ("Powersaver supported.\n");
+		break;
+	};
 
 	ret = longhaul_get_ranges();
 	if (ret != 0)
 		return ret;
 
-	if ((longhaul_version==2) && (dont_scale_voltage==0))
+	if ((longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) &&
+		 (dont_scale_voltage==0))
 		longhaul_setup_voltagescaling();
 
 	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
 	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-	policy->cur = calc_speed (longhaul_get_cpu_mult(), fsb);
+	policy->cur = calc_speed(longhaul_get_cpu_mult());
 
 	ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table);
 	if (ret)
@@ -540,6 +621,7 @@ static struct cpufreq_driver longhaul_driver = {
 	.attr	= longhaul_attr,
 };
 
+
 static int __init longhaul_init(void)
 {
 	struct cpuinfo_x86 *c = cpu_data;
@@ -557,16 +639,17 @@ static int __init longhaul_init(void)
 	return -ENODEV;
 }
 
+
 static void __exit longhaul_exit(void)
 {
 	int i=0;
-	unsigned int new_clock_ratio;
-
-	while (clock_ratio[i] != maxmult)
-		i++;
 
-	new_clock_ratio = longhaul_table[i].index & 0xFF;
-	longhaul_setstate(new_clock_ratio);
+	for (i=0; i < numscales; i++) {
+		if (clock_ratio[i] == maxmult) {
+			longhaul_setstate(i);
+			break;
+		}
+	}
 
 	cpufreq_unregister_driver(&longhaul_driver);
 	kfree(longhaul_table);
diff --git a/arch/i386/kernel/cpu/cpufreq/longrun.c b/arch/i386/kernel/cpu/cpufreq/longrun.c
index c04c99bba..ab3cfc3cd 100644
--- a/arch/i386/kernel/cpu/cpufreq/longrun.c
+++ b/arch/i386/kernel/cpu/cpufreq/longrun.c
@@ -7,7 +7,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h> 
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/cpufreq.h>
@@ -19,7 +19,7 @@
 static struct cpufreq_driver	longrun_driver;
 
 /**
- * longrun_{low,high}_freq is needed for the conversion of cpufreq kHz 
+ * longrun_{low,high}_freq is needed for the conversion of cpufreq kHz
  * values into per cent values. In TMTA microcode, the following is valid:
  * performance_pctg = (current_freq - low_freq)/(high_freq - low_freq)
  */
@@ -42,18 +42,18 @@ static void __init longrun_get_policy(struct cpufreq_policy *policy)
 		policy->policy = CPUFREQ_POLICY_PERFORMANCE;
 	else
 		policy->policy = CPUFREQ_POLICY_POWERSAVE;
-	
+
 	rdmsr(MSR_TMTA_LONGRUN_CTRL, msr_lo, msr_hi);
 	msr_lo &= 0x0000007F;
 	msr_hi &= 0x0000007F;
-	
+
 	if ( longrun_high_freq <= longrun_low_freq ) {
 		/* Assume degenerate Longrun table */
 		policy->min = policy->max = longrun_high_freq;
 	} else {
-		policy->min = longrun_low_freq + msr_lo * 
+		policy->min = longrun_low_freq + msr_lo *
 			((longrun_high_freq - longrun_low_freq) / 100);
-		policy->max = longrun_low_freq + msr_hi * 
+		policy->max = longrun_low_freq + msr_hi *
 			((longrun_high_freq - longrun_low_freq) / 100);
 	}
 	policy->cpu = 0;
@@ -79,9 +79,9 @@ static int longrun_set_policy(struct cpufreq_policy *policy)
 		/* Assume degenerate Longrun table */
 		pctg_lo = pctg_hi = 100;
 	} else {
-		pctg_lo = (policy->min - longrun_low_freq) / 
+		pctg_lo = (policy->min - longrun_low_freq) /
 			((longrun_high_freq - longrun_low_freq) / 100);
-		pctg_hi = (policy->max - longrun_low_freq) / 
+		pctg_hi = (policy->max - longrun_low_freq) /
 			((longrun_high_freq - longrun_low_freq) / 100);
 	}
 
@@ -118,7 +118,7 @@ static int longrun_set_policy(struct cpufreq_policy *policy)
  * longrun_verify_poliy - verifies a new CPUFreq policy
  * @policy: the policy to verify
  *
- * Validates a new CPUFreq policy. This function has to be called with 
+ * Validates a new CPUFreq policy. This function has to be called with
  * cpufreq_driver locked.
  */
 static int longrun_verify_policy(struct cpufreq_policy *policy)
@@ -127,8 +127,8 @@ static int longrun_verify_policy(struct cpufreq_policy *policy)
 		return -EINVAL;
 
 	policy->cpu = 0;
-	cpufreq_verify_within_limits(policy, 
-		policy->cpuinfo.min_freq, 
+	cpufreq_verify_within_limits(policy,
+		policy->cpuinfo.min_freq,
 		policy->cpuinfo.max_freq);
 
 	if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) &&
@@ -160,7 +160,7 @@ static unsigned int longrun_get(unsigned int cpu)
  * TMTA rules:
  * performance_pctg = (target_freq - low_freq)/(high_freq - low_freq)
  */
-static unsigned int __init longrun_determine_freqs(unsigned int *low_freq, 
+static unsigned int __init longrun_determine_freqs(unsigned int *low_freq,
 						   unsigned int *high_freq)
 {
 	u32 msr_lo, msr_hi;
@@ -174,9 +174,9 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq,
 
 	if (cpu_has(c, X86_FEATURE_LRTI)) {
 		/* if the LongRun Table Interface is present, the
-		 * detection is a bit easier: 
+		 * detection is a bit easier:
 		 * For minimum frequency, read out the maximum
-		 * level (msr_hi), write that into "currently 
+		 * level (msr_hi), write that into "currently
 		 * selected level", and read out the frequency.
 		 * For maximum frequency, read out level zero.
 		 */
@@ -223,7 +223,7 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq,
 		cpuid(0x80860007, &eax, &ebx, &ecx, &edx);
 
 		/* restore values */
-		wrmsr(MSR_TMTA_LONGRUN_CTRL, save_lo, save_hi);	
+		wrmsr(MSR_TMTA_LONGRUN_CTRL, save_lo, save_hi);
 	}
 
 	/* performance_pctg = (current_freq - low_freq)/(high_freq - low_freq)
@@ -237,7 +237,7 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq,
 	if ((ecx > 95) || (ecx == 0) || (eax < ebx))
 		return -EIO;
 
-	edx = (eax - ebx) / (100 - ecx); 
+	edx = (eax - ebx) / (100 - ecx);
 	*low_freq = edx * 1000; /* back to kHz */
 
 	if (*low_freq > *high_freq)
@@ -249,7 +249,7 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq,
 
 static int __init longrun_cpu_init(struct cpufreq_policy *policy)
 {
-	int                     result = 0;
+	int result = 0;
 
 	/* capability check */
 	if (policy->cpu != 0)
@@ -265,15 +265,15 @@ static int __init longrun_cpu_init(struct cpufreq_policy *policy)
 	policy->cpuinfo.max_freq = longrun_high_freq;
 	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
 	longrun_get_policy(policy);
-	
+
 	return 0;
 }
 
 
 static struct cpufreq_driver longrun_driver = {
 	.flags		= CPUFREQ_CONST_LOOPS,
-	.verify 	= longrun_verify_policy,
-	.setpolicy 	= longrun_set_policy,
+	.verify		= longrun_verify_policy,
+	.setpolicy	= longrun_set_policy,
 	.get		= longrun_get,
 	.init		= longrun_cpu_init,
 	.name		= "longrun",
@@ -290,7 +290,7 @@ static int __init longrun_init(void)
 {
 	struct cpuinfo_x86 *c = cpu_data;
 
-	if (c->x86_vendor != X86_VENDOR_TRANSMETA || 
+	if (c->x86_vendor != X86_VENDOR_TRANSMETA ||
 	    !cpu_has(c, X86_FEATURE_LONGRUN))
 		return -ENODEV;
 
diff --git a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
index fa01a95bb..ef1394964 100644
--- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
+++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
@@ -184,7 +184,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
 		       "The speedstep_centrino module offers voltage scaling"
 		       " in addition of frequency scaling. You should use "
 		       "that instead of p4-clockmod, if possible.\n");
-		/* on P-4s, the TSC runs with constant frequency independent wether
+		/* on P-4s, the TSC runs with constant frequency independent whether
 		 * throttling is active or not. */
 		p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
 		return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM);
@@ -195,7 +195,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
 		return 0;
 	}
 
-	/* on P-4s, the TSC runs with constant frequency independent wether
+	/* on P-4s, the TSC runs with constant frequency independent whether
 	 * throttling is active or not. */
 	p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS;
 
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
index 18d30ab9a..c7e3aa60d 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
@@ -6,8 +6,6 @@
  *  Licensed under the terms of the GNU GPL License version 2.
  *  Based upon datasheets & sample CPUs kindly provided by AMD.
  *
- *  BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
- *
  * Errata 5: Processor may fail to execute a FID/VID change in presence of interrupt.
  * - We cli/sti on stepping A0 CPUs around the FID/VID transition.
  * Errata 15: Processors with half frequency multipliers may hang upon wakeup from disconnect.
@@ -29,21 +27,13 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
-#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
+#ifdef CONFIG_X86_POWERNOW_K7_ACPI
 #include <linux/acpi.h>
 #include <acpi/processor.h>
 #endif
 
 #include "powernow-k7.h"
 
-#define DEBUG
-
-#ifdef DEBUG
-#define dprintk(msg...) printk(msg)
-#else
-#define dprintk(msg...) do { } while(0)
-#endif
-
 #define PFX "powernow: "
 
 
@@ -64,7 +54,7 @@ struct pst_s {
 	u8 numpstates;
 };
 
-#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
+#ifdef CONFIG_X86_POWERNOW_K7_ACPI
 union powernow_acpi_control_t {
 	struct {
 		unsigned long fid:5,
@@ -97,6 +87,7 @@ static int fid_codes[32] = {
  */
 
 static int acpi_force;
+static int debug;
 
 static struct cpufreq_frequency_table *powernow_table;
 
@@ -109,6 +100,21 @@ static unsigned int fsb;
 static unsigned int latency;
 static char have_a0;
 
+static void dprintk(const char *fmt, ...)
+{
+	char s[256];
+	va_list args;
+
+	if (debug==0)
+		return;
+
+	va_start(args,fmt);
+	vsprintf(s, fmt, args);
+	printk(s);
+	va_end(args);
+}
+
+
 static int check_fsb(unsigned int fsbspeed)
 {
 	int delta;
@@ -190,13 +196,13 @@ static int get_ranges (unsigned char *pst)
 		speed = powernow_table[j].frequency;
 
 		if ((fid_codes[fid] % 10)==5) {
-#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
+#ifdef CONFIG_X86_POWERNOW_K7_ACPI
 			if (have_a0 == 1)
 				powernow_table[j].frequency = CPUFREQ_ENTRY_INVALID;
 #endif
 		}
 
-		dprintk (KERN_INFO PFX "   FID: 0x%x (%d.%dx [%dMHz])\t", fid,
+		dprintk (KERN_INFO PFX "   FID: 0x%x (%d.%dx [%dMHz])  ", fid,
 			fid_codes[fid] / 10, fid_codes[fid] % 10, speed/1000);
 
 		if (speed < minimum_speed)
@@ -285,7 +291,7 @@ static void change_speed (unsigned int index)
 		change_VID(vid);
 		change_FID(fid);
 	}
-	
+
 
 	if (have_a0 == 1)
 		local_irq_enable();
@@ -294,7 +300,7 @@ static void change_speed (unsigned int index)
 }
 
 
-#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
+#ifdef CONFIG_X86_POWERNOW_K7_ACPI
 
 struct acpi_processor_performance *acpi_processor_perf;
 
@@ -377,7 +383,7 @@ static int powernow_acpi_init(void)
 				powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
 		}
 
-		dprintk (KERN_INFO PFX "   FID: 0x%x (%d.%dx [%dMHz])\t", fid,
+		dprintk (KERN_INFO PFX "   FID: 0x%x (%d.%dx [%dMHz])  ", fid,
 			fid_codes[fid] / 10, fid_codes[fid] % 10, speed/1000);
 		dprintk ("VID: 0x%x (%d.%03dV)\n", vid,	mobile_vid_table[vid]/1000,
 			mobile_vid_table[vid]%1000);
@@ -467,9 +473,9 @@ static int powernow_decode_bios (int maxfid, int startvid)
 				    (maxfid==pst->maxfid) && (startvid==pst->startvid))
 				{
 					dprintk (KERN_INFO PFX "PST:%d (@%p)\n", i, pst);
-					dprintk (KERN_INFO PFX " cpuid: 0x%x\t", pst->cpuid);
-					dprintk ("fsb: %d\t", pst->fsbspeed);
-					dprintk ("maxFID: 0x%x\t", pst->maxfid);
+					dprintk (KERN_INFO PFX " cpuid: 0x%x  ", pst->cpuid);
+					dprintk ("fsb: %d  ", pst->fsbspeed);
+					dprintk ("maxFID: 0x%x  ", pst->maxfid);
 					dprintk ("startvid: 0x%x\n", pst->startvid);
 
 					ret = get_ranges ((char *) pst + sizeof (struct pst_s));
@@ -591,14 +597,14 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy)
 	rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
 
 	/* A K7 with powernow technology is set to max frequency by BIOS */
-	fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID];
+	fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.MFID];
 	if (!fsb) {
 		printk(KERN_WARNING PFX "can not determine bus frequency\n");
 		return -EINVAL;
 	}
 	dprintk(KERN_INFO PFX "FSB: %3d.%03d MHz\n", fsb/1000, fsb%1000);
 
- 	if (dmi_check_system(powernow_dmi_table) || acpi_force) {
+	if (dmi_check_system(powernow_dmi_table) || acpi_force) {
 		printk (KERN_INFO PFX "PSB/PST known to be broken.  Trying ACPI instead\n");
 		result = powernow_acpi_init();
 	} else {
@@ -628,7 +634,7 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy)
 
 	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
 
-	policy->cpuinfo.transition_latency = 20 * latency / fsb;
+	policy->cpuinfo.transition_latency = cpufreq_scale(2000000UL, fsb, latency);
 
 	policy->cur = powernow_get(0);
 
@@ -648,14 +654,14 @@ static struct freq_attr* powernow_table_attr[] = {
 };
 
 static struct cpufreq_driver powernow_driver = {
-	.verify 	= powernow_verify,
-	.target 	= powernow_target,
-	.get		= powernow_get,	
-	.init		= powernow_cpu_init,
-	.exit		= powernow_cpu_exit,
-	.name		= "powernow-k7",
-	.owner		= THIS_MODULE,
-	.attr		= powernow_table_attr,
+	.verify	= powernow_verify,
+	.target	= powernow_target,
+	.get	= powernow_get,
+	.init	= powernow_cpu_init,
+	.exit	= powernow_cpu_exit,
+	.name	= "powernow-k7",
+	.owner	= THIS_MODULE,
+	.attr	= powernow_table_attr,
 };
 
 static int __init powernow_init (void)
@@ -668,7 +674,7 @@ static int __init powernow_init (void)
 
 static void __exit powernow_exit (void)
 {
-#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
+#ifdef CONFIG_X86_POWERNOW_K7_ACPI
 	if (acpi_processor_perf) {
 		acpi_processor_unregister_performance(acpi_processor_perf, 0);
 		kfree(acpi_processor_perf);
@@ -679,8 +685,10 @@ static void __exit powernow_exit (void)
 		kfree(powernow_table);
 }
 
+module_param(debug, int, 0444);
+MODULE_PARM_DESC(debug, "enable debug output.");
 module_param(acpi_force,  int, 0444);
-MODULE_PARM_DESC(acpi_force, "Force ACPI to be used");
+MODULE_PARM_DESC(acpi_force, "Force ACPI to be used.");
 
 MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");
 MODULE_DESCRIPTION ("Powernow driver for AMD K7 processors.");
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
index 05ed9025e..e52390d12 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
@@ -32,7 +32,7 @@
 #include <asm/io.h>
 #include <asm/delay.h>
 
-#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
+#ifdef CONFIG_X86_POWERNOW_K8_ACPI
 #include <linux/acpi.h>
 #include <acpi/processor.h>
 #endif
@@ -664,7 +664,7 @@ static int find_psb_table(struct powernow_k8_data *data)
 	return -ENODEV;
 }
 
-#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
+#ifdef CONFIG_X86_POWERNOW_K8_ACPI
 static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index)
 {
 	if (!data->acpi_data.state_count)
@@ -948,13 +948,13 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
 		 * an UP version, and is deprecated by AMD.
 		 */
 
-		if (pol->cpu != 0) {
-			printk(KERN_ERR PFX "init not cpu 0\n");
+		if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) {
+			printk(KERN_INFO PFX "MP systems not supported by PSB BIOS structure\n");
 			kfree(data);
 			return -ENODEV;
 		}
-		if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) {
-			printk(KERN_INFO PFX "MP systems not supported by PSB BIOS structure\n");
+		if (pol->cpu != 0) {
+			printk(KERN_ERR PFX "init not cpu 0\n");
 			kfree(data);
 			return -ENODEV;
 		}
@@ -1024,7 +1024,7 @@ err_out:
 	return -ENODEV;
 }
 
-static int __exit powernowk8_cpu_exit (struct cpufreq_policy *pol)
+static int __devexit powernowk8_cpu_exit (struct cpufreq_policy *pol)
 {
 	struct powernow_k8_data *data = powernow_data[pol->cpu];
 
@@ -1076,7 +1076,7 @@ static struct cpufreq_driver cpufreq_amd64_driver = {
 	.verify = powernowk8_verify,
 	.target = powernowk8_target,
 	.init = powernowk8_cpu_init,
-	.exit = powernowk8_cpu_exit,
+	.exit = __devexit_p(powernowk8_cpu_exit),
 	.get = powernowk8_get,
 	.name = "powernow-k8",
 	.owner = THIS_MODULE,
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
index 500f28d27..a95db64a9 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
@@ -29,7 +29,7 @@ struct powernow_k8_data {
 	 * frequency is in kHz */
 	struct cpufreq_frequency_table  *powernow_table;
 
-#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
+#ifdef CONFIG_X86_POWERNOW_K8_ACPI
 	/* the acpi table needs to be kept. it's only available if ACPI was
 	 * used to determine valid frequency/vid/fid states */
 	struct acpi_processor_performance acpi_data;
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
index ea9173812..56aafbde6 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -10,7 +10,7 @@
  * Copyright (C) 2003 Jeremy Fitzhardinge <jeremy@goop.org>
  *
  * WARNING WARNING WARNING
- * 
+ *
  * This driver manipulates the PERF_CTL MSR, which is only somewhat
  * documented.  While it seems to work on my laptop, it has not been
  * tested anywhere else, and it may not work for you, do strange
@@ -23,6 +23,11 @@
 #include <linux/cpufreq.h>
 #include <linux/config.h>
 
+#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
+#include <linux/acpi.h>
+#include <acpi/processor.h>
+#endif
+
 #include <asm/msr.h>
 #include <asm/processor.h>
 #include <asm/cpufeature.h>
@@ -41,24 +46,24 @@
 struct cpu_id
 {
 	__u8	x86;            /* CPU family */
-	__u8	x86_vendor;     /* CPU vendor */
 	__u8	x86_model;	/* model */
 	__u8	x86_mask;	/* stepping */
 };
 
-static const struct cpu_id cpu_id_banias = {
-	.x86_vendor = X86_VENDOR_INTEL,
-	.x86 = 6,
-	.x86_model = 9,
-	.x86_mask = 5,
+enum {
+	CPU_BANIAS,
+	CPU_DOTHAN_A1,
+	CPU_DOTHAN_A2,
+	CPU_DOTHAN_B0,
 };
 
-static const struct cpu_id cpu_id_dothan_a1 = {
-	.x86_vendor = X86_VENDOR_INTEL,
-	.x86 = 6,
-	.x86_model = 13,
-	.x86_mask = 1,
+static const struct cpu_id cpu_ids[] = {
+	[CPU_BANIAS]	= { 6,  9, 5 },
+	[CPU_DOTHAN_A1]	= { 6, 13, 1 },
+	[CPU_DOTHAN_A2]	= { 6, 13, 2 },
+	[CPU_DOTHAN_B0]	= { 6, 13, 6 },
 };
+#define N_IDS	(sizeof(cpu_ids)/sizeof(cpu_ids[0]))
 
 struct cpu_model
 {
@@ -68,10 +73,11 @@ struct cpu_model
 
 	struct cpufreq_frequency_table *op_points; /* clock/voltage pairs */
 };
-static int centrino_verify_cpu_id(struct cpuinfo_x86 *c, const struct cpu_id *x);
+static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x);
 
 /* Operating points for current CPU */
 static struct cpu_model *centrino_model;
+static int centrino_cpu;
 
 #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE
 
@@ -84,7 +90,7 @@ static struct cpu_model *centrino_model;
 		.index = (((mhz)/100) << 8) | ((mv - 700) / 16)		\
 	}
 
-/* 
+/*
  * These voltage tables were derived from the Intel Pentium M
  * datasheet, document 25261202.pdf, Table 5.  I have verified they
  * are consistent with my IBM ThinkPad X31, which has a 1.3GHz Pentium
@@ -103,9 +109,9 @@ static struct cpufreq_frequency_table banias_900[] =
 /* Ultra Low Voltage Intel Pentium M processor 1000MHz (Banias) */
 static struct cpufreq_frequency_table banias_1000[] =
 {
-	OP(600,  844),
-	OP(800,  972),
-	OP(900,  988),
+	OP(600,   844),
+	OP(800,   972),
+	OP(900,   988),
 	OP(1000, 1004),
 	{ .frequency = CPUFREQ_TABLE_END }
 };
@@ -135,7 +141,7 @@ static struct cpufreq_frequency_table banias_1200[] =
 };
 
 /* Intel Pentium M processor 1.30GHz (Banias) */
-static struct cpufreq_frequency_table banias_1300[] = 
+static struct cpufreq_frequency_table banias_1300[] =
 {
 	OP( 600,  956),
 	OP( 800, 1260),
@@ -146,7 +152,7 @@ static struct cpufreq_frequency_table banias_1300[] =
 };
 
 /* Intel Pentium M processor 1.40GHz (Banias) */
-static struct cpufreq_frequency_table banias_1400[] = 
+static struct cpufreq_frequency_table banias_1400[] =
 {
 	OP( 600,  956),
 	OP( 800, 1180),
@@ -157,7 +163,7 @@ static struct cpufreq_frequency_table banias_1400[] =
 };
 
 /* Intel Pentium M processor 1.50GHz (Banias) */
-static struct cpufreq_frequency_table banias_1500[] = 
+static struct cpufreq_frequency_table banias_1500[] =
 {
 	OP( 600,  956),
 	OP( 800, 1116),
@@ -169,7 +175,7 @@ static struct cpufreq_frequency_table banias_1500[] =
 };
 
 /* Intel Pentium M processor 1.60GHz (Banias) */
-static struct cpufreq_frequency_table banias_1600[] = 
+static struct cpufreq_frequency_table banias_1600[] =
 {
 	OP( 600,  956),
 	OP( 800, 1036),
@@ -199,13 +205,13 @@ static struct cpufreq_frequency_table banias_1700[] =
 	.max_freq	= (max)*1000,	\
 	.op_points	= banias_##max,	\
 }
-#define BANIAS(max)	_BANIAS(&cpu_id_banias, max, #max)
+#define BANIAS(max)	_BANIAS(&cpu_ids[CPU_BANIAS], max, #max)
 
 /* CPU models, their operating frequency range, and freq/voltage
    operating points */
-static struct cpu_model models[] = 
+static struct cpu_model models[] =
 {
-	_BANIAS(&cpu_id_banias, 900, " 900"),
+	_BANIAS(&cpu_ids[CPU_BANIAS], 900, " 900"),
 	BANIAS(1000),
 	BANIAS(1100),
 	BANIAS(1200),
@@ -214,6 +220,12 @@ static struct cpu_model models[] =
 	BANIAS(1500),
 	BANIAS(1600),
 	BANIAS(1700),
+
+	/* NULL model_name is a wildcard */
+	{ &cpu_ids[CPU_DOTHAN_A1], NULL, 0, NULL },
+	{ &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL },
+	{ &cpu_ids[CPU_DOTHAN_B0], NULL, 0, NULL },
+
 	{ NULL, }
 };
 #undef _BANIAS
@@ -224,19 +236,30 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
 	struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu];
 	struct cpu_model *model;
 
-	for(model = models; model->model_name != NULL; model++)
-		if ((strcmp(cpu->x86_model_id, model->model_name) == 0) &&
-		    (!centrino_verify_cpu_id(cpu, model->cpu_id)))
+	for(model = models; model->cpu_id != NULL; model++)
+		if (centrino_verify_cpu_id(cpu, model->cpu_id) &&
+		    (model->model_name == NULL ||
+		     strcmp(cpu->x86_model_id, model->model_name) == 0))
 			break;
-	if (model->model_name == NULL) {
+
+	if (model->cpu_id == NULL) {
+		/* No match at all */
 		printk(KERN_INFO PFX "no support for CPU model \"%s\": "
 		       "send /proc/cpuinfo to " MAINTAINER "\n",
 		       cpu->x86_model_id);
 		return -ENOENT;
 	}
 
+	if (model->op_points == NULL) {
+		/* Matched a non-match */
+		printk(KERN_INFO PFX "no table support for CPU model \"%s\": \n",
+		       cpu->x86_model_id);
+		printk(KERN_INFO PFX "try compiling with CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI enabled\n");
+		return -ENOENT;
+	}
+
 	centrino_model = model;
-		
+
 	printk(KERN_INFO PFX "found \"%s\": max frequency: %dkHz\n",
 	       model->model_name, model->max_freq);
 
@@ -247,31 +270,54 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)
 static inline int centrino_cpu_init_table(struct cpufreq_policy *policy) { return -ENODEV; }
 #endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE */
 
-static int centrino_verify_cpu_id(struct cpuinfo_x86 *c, const struct cpu_id *x)
+static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x)
 {
 	if ((c->x86 == x->x86) &&
-	    (c->x86_vendor == x->x86_vendor) &&
 	    (c->x86_model == x->x86_model) &&
 	    (c->x86_mask == x->x86_mask))
-		return 0;
-	return -ENODEV;
+		return 1;
+	return 0;
 }
 
-/* Extract clock in kHz from PERF_CTL value */
+/* To be called only after centrino_model is initialized */
 static unsigned extract_clock(unsigned msr)
 {
-	msr = (msr >> 8) & 0xff;
-	return msr * 100000;
+	int i;
+
+	/*
+	 * Extract clock in kHz from PERF_CTL value
+	 * for centrino, as some DSDTs are buggy.
+	 * Ideally, this can be done using the acpi_data structure.
+	 */
+	if (centrino_cpu) {
+		msr = (msr >> 8) & 0xff;
+		return msr * 100000;
+	}
+
+	if ((!centrino_model) || (!centrino_model->op_points))
+		return 0;
+
+	msr &= 0xffff;
+	for (i=0;centrino_model->op_points[i].frequency != CPUFREQ_TABLE_END; i++) {
+		if (msr == centrino_model->op_points[i].index)
+		return centrino_model->op_points[i].frequency;
+	}
+	return 0;
 }
 
 /* Return the current CPU frequency in kHz */
 static unsigned int get_cur_freq(unsigned int cpu)
 {
 	unsigned l, h;
-	if (cpu)
+	cpumask_t saved_mask;
+
+	saved_mask = current->cpus_allowed;
+	set_cpus_allowed(current, cpumask_of_cpu(cpu));
+	if (smp_processor_id() != cpu)
 		return 0;
 
 	rdmsr(MSR_IA32_PERF_STATUS, l, h);
+	set_cpus_allowed(current, saved_mask);
 	return extract_clock(l);
 }
 
@@ -280,13 +326,8 @@ static unsigned int get_cur_freq(unsigned int cpu)
 
 static struct acpi_processor_performance p;
 
-#include <linux/acpi.h>
-#include <acpi/processor.h>
-
-#define ACPI_PDC_CAPABILITY_ENHANCED_SPEEDSTEP 0x1
-
 /*
- * centrino_cpu_init_acpi - register with ACPI P-States library 
+ * centrino_cpu_init_acpi - register with ACPI P-States library
  *
  * Register with the ACPI P-States library (part of drivers/acpi/processor.c)
  * in order to determine correct frequency and voltage pairings by reading
@@ -296,7 +337,7 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
 {
 	union acpi_object		arg0 = {ACPI_TYPE_BUFFER};
 	u32				arg0_buf[3];
-	struct acpi_object_list 	arg_list = {1, &arg0};
+	struct acpi_object_list		arg_list = {1, &arg0};
 	unsigned long			cur_freq;
 	int				result = 0, i;
 
@@ -305,12 +346,12 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
         arg0.buffer.pointer = (u8 *) arg0_buf;
         arg0_buf[0] = ACPI_PDC_REVISION_ID;
         arg0_buf[1] = 1;
-        arg0_buf[2] = ACPI_PDC_CAPABILITY_ENHANCED_SPEEDSTEP;
+        arg0_buf[2] = ACPI_PDC_EST_CAPABILITY_SMP | ACPI_PDC_EST_CAPABILITY_MSR;
 
 	p.pdc = &arg_list;
 
 	/* register with ACPI core */
-        if (acpi_processor_register_performance(&p, 0))
+        if (acpi_processor_register_performance(&p, policy->cpu))
                 return -EIO;
 
 	/* verify the acpi_data */
@@ -318,7 +359,7 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
                 printk(KERN_DEBUG "No P-States\n");
                 result = -ENODEV;
                 goto err_unreg;
- 	}
+	}
 
 	if ((p.control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) ||
 	    (p.status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) {
@@ -340,11 +381,10 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
 			goto err_unreg;
 		}
 
-		if (extract_clock(p.states[i].control) != 
-		    (p.states[i].core_frequency * 1000)) {
-			printk(KERN_DEBUG "Invalid encoded frequency\n");
-			result = -EINVAL;
-			goto err_unreg;
+		if (p.states[i].core_frequency > p.states[0].core_frequency) {
+			printk(KERN_DEBUG "P%u has larger frequency than P0, skipping\n", i);
+			p.states[i].core_frequency = 0;
+			continue;
 		}
 	}
 
@@ -357,29 +397,43 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
 
 	centrino_model->model_name=NULL;
 	centrino_model->max_freq = p.states[0].core_frequency * 1000;
-	centrino_model->op_points =  kmalloc(sizeof(struct cpufreq_frequency_table) * 
+	centrino_model->op_points =  kmalloc(sizeof(struct cpufreq_frequency_table) *
 					     (p.state_count + 1), GFP_KERNEL);
         if (!centrino_model->op_points) {
                 result = -ENOMEM;
                 goto err_kfree;
         }
 
-	cur_freq = get_cur_freq(0);
-
         for (i=0; i<p.state_count; i++) {
 		centrino_model->op_points[i].index = p.states[i].control;
 		centrino_model->op_points[i].frequency = p.states[i].core_frequency * 1000;
+	}
+	centrino_model->op_points[p.state_count].frequency = CPUFREQ_TABLE_END;
+
+	cur_freq = get_cur_freq(policy->cpu);
+
+	for (i=0; i<p.state_count; i++) {
+		if (extract_clock(centrino_model->op_points[i].index) !=
+		    (centrino_model->op_points[i].frequency)) {
+			printk(KERN_DEBUG "Invalid encoded frequency\n");
+			result = -EINVAL;
+			goto err_kfree_all;
+		}
+
 		if (cur_freq == centrino_model->op_points[i].frequency)
 			p.state = i;
+		if (!p.states[i].core_frequency)
+			centrino_model->op_points[i].frequency = CPUFREQ_ENTRY_INVALID;
 	}
-	centrino_model->op_points[p.state_count].frequency = CPUFREQ_TABLE_END;
 
 	return 0;
 
+ err_kfree_all:
+	kfree(centrino_model->op_points);
  err_kfree:
 	kfree(centrino_model);
  err_unreg:
-	acpi_processor_unregister_performance(&p, 0);
+	acpi_processor_unregister_performance(&p, policy->cpu);
 	return (result);
 }
 #else
@@ -392,21 +446,30 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
 	unsigned freq;
 	unsigned l, h;
 	int ret;
+	int i;
 
-	if (policy->cpu != 0)
+	/* Only Intel makes Enhanced Speedstep-capable CPUs */
+	if (cpu->x86_vendor != X86_VENDOR_INTEL || !cpu_has(cpu, X86_FEATURE_EST))
 		return -ENODEV;
 
-	if (!cpu_has(cpu, X86_FEATURE_EST))
-		return -ENODEV;
+	for (i = 0; i < N_IDS; i++)
+		if (centrino_verify_cpu_id(cpu, &cpu_ids[i]))
+			break;
 
-	if ((centrino_verify_cpu_id(cpu, &cpu_id_banias)) &&
-	    (centrino_verify_cpu_id(cpu, &cpu_id_dothan_a1))) {
-		printk(KERN_INFO PFX "found unsupported CPU with Enhanced SpeedStep: "
-		       "send /proc/cpuinfo to " MAINTAINER "\n");
-		return -ENODEV;
-	}
+	if (i != N_IDS)
+		centrino_cpu = 1;
 
 	if (centrino_cpu_init_acpi(policy)) {
+		if (policy->cpu != 0)
+			return -ENODEV;
+
+		if (!centrino_cpu) {
+			printk(KERN_INFO PFX "found unsupported CPU with "
+			"Enhanced SpeedStep: send /proc/cpuinfo to "
+			MAINTAINER "\n");
+			return -ENODEV;
+		}
+
 		if (centrino_cpu_init_table(policy)) {
 			return -ENODEV;
 		}
@@ -415,11 +478,11 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
 	/* Check to see if Enhanced SpeedStep is enabled, and try to
 	   enable it if not. */
 	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
-		
+
 	if (!(l & (1<<16))) {
 		l |= (1<<16);
 		wrmsr(MSR_IA32_MISC_ENABLE, l, h);
-		
+
 		/* check to see if it stuck */
 		rdmsr(MSR_IA32_MISC_ENABLE, l, h);
 		if (!(l & (1<<16))) {
@@ -428,7 +491,7 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
 		}
 	}
 
-	freq = get_cur_freq(0);
+	freq = get_cur_freq(policy->cpu);
 
 	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
 	policy->cpuinfo.transition_latency = 10000; /* 10uS transition latency */
@@ -436,7 +499,7 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
 
 	dprintk(KERN_INFO PFX "centrino_cpu_init: policy=%d cur=%dkHz\n",
 		policy->policy, policy->cur);
-	
+
 	ret = cpufreq_frequency_table_cpuinfo(policy, centrino_model->op_points);
 	if (ret)
 		return (ret);
@@ -455,7 +518,7 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy)
 
 #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
 	if (!centrino_model->model_name) {
-		acpi_processor_unregister_performance(&p, 0);
+		acpi_processor_unregister_performance(&p, policy->cpu);
 		kfree(centrino_model->op_points);
 		kfree(centrino_model);
 	}
@@ -493,19 +556,35 @@ static int centrino_target (struct cpufreq_policy *policy,
 	unsigned int    newstate = 0;
 	unsigned int	msr, oldmsr, h;
 	struct cpufreq_freqs	freqs;
+	cpumask_t		saved_mask;
+	int			retval;
 
 	if (centrino_model == NULL)
 		return -ENODEV;
 
+	/*
+	 * Support for SMP systems.
+	 * Make sure we are running on the CPU that wants to change frequency
+	 */
+	saved_mask = current->cpus_allowed;
+	set_cpus_allowed(current, cpumask_of_cpu(policy->cpu));
+	if (smp_processor_id() != policy->cpu) {
+		return(-EAGAIN);
+	}
+
 	if (cpufreq_frequency_table_target(policy, centrino_model->op_points, target_freq,
-					   relation, &newstate))
-		return -EINVAL;
+					   relation, &newstate)) {
+		retval = -EINVAL;
+		goto migrate_end;
+	}
 
 	msr = centrino_model->op_points[newstate].index;
 	rdmsr(MSR_IA32_PERF_CTL, oldmsr, h);
 
-	if (msr == (oldmsr & 0xffff))
-		return 0;
+	if (msr == (oldmsr & 0xffff)) {
+		retval = 0;
+		goto migrate_end;
+	}
 
 	/* Hm, old frequency can either be the last value we put in
 	   PERF_CTL, or whatever it is now. The trouble is that TM2
@@ -514,31 +593,34 @@ static int centrino_target (struct cpufreq_policy *policy,
 	   tell us something happened, but it may leave the things on
 	   the notifier chain confused; we therefore stick to using
 	   the last programmed speed rather than the current speed for
-	   "old". 
+	   "old".
 
 	   TODO: work out how the TCC interrupts work, and try to
 	   catch the CPU changing things under us.
 	*/
-	freqs.cpu = 0;
+	freqs.cpu = policy->cpu;
 	freqs.old = extract_clock(oldmsr);
 	freqs.new = extract_clock(msr);
-	
+
 	dprintk(KERN_INFO PFX "target=%dkHz old=%d new=%d msr=%04x\n",
 		target_freq, freqs.old, freqs.new, msr);
 
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);	
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
 	/* all but 16 LSB are "reserved", so treat them with
 	   care */
 	oldmsr &= ~0xffff;
 	msr &= 0xffff;
 	oldmsr |= msr;
-	
+
 	wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
-	return 0;
+	retval = 0;
+migrate_end:
+	set_cpus_allowed(current, saved_mask);
+	return (retval);
 }
 
 static struct freq_attr* centrino_attr[] = {
@@ -547,12 +629,12 @@ static struct freq_attr* centrino_attr[] = {
 };
 
 static struct cpufreq_driver centrino_driver = {
-	.name		= "centrino", /* should be speedstep-centrino, 
+	.name		= "centrino", /* should be speedstep-centrino,
 					 but there's a 16 char limit */
 	.init		= centrino_cpu_init,
 	.exit		= centrino_cpu_exit,
-	.verify 	= centrino_verify,
-	.target 	= centrino_target,
+	.verify		= centrino_verify,
+	.target		= centrino_target,
 	.get		= get_cur_freq,
 	.attr           = centrino_attr,
 	.owner		= THIS_MODULE,
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
index 93b70f0dc..5f94c4fa2 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c
@@ -7,7 +7,7 @@
  *  for chipsets ICH2-M and ICH3-M.
  *
  *  Many thanks to Ducrot Bruno for finding and fixing the last
- *  "missing link" for ICH2-M/ICH3-M support, and to Thomas Winkler 
+ *  "missing link" for ICH2-M/ICH3-M support, and to Thomas Winkler
  *  for extensive testing.
  *
  *  BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
@@ -19,7 +19,7 @@
  *********************************************************************/
 
 #include <linux/kernel.h>
-#include <linux/module.h> 
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/cpufreq.h>
 #include <linux/pci.h>
@@ -29,24 +29,24 @@
 
 
 /* speedstep_chipset:
- *   It is necessary to know which chipset is used. As accesses to 
- * this device occur at various places in this module, we need a 
+ *   It is necessary to know which chipset is used. As accesses to
+ * this device occur at various places in this module, we need a
  * static struct pci_dev * pointing to that device.
  */
-static struct pci_dev			*speedstep_chipset_dev;
+static struct pci_dev *speedstep_chipset_dev;
 
 
 /* speedstep_processor
  */
-static unsigned int			speedstep_processor = 0;
+static unsigned int speedstep_processor = 0;
 
 
-/* 
+/*
  *   There are only two frequency states for each processor. Values
  * are in kHz for the time being.
  */
 static struct cpufreq_frequency_table speedstep_freqs[] = {
-	{SPEEDSTEP_HIGH, 	0},
+	{SPEEDSTEP_HIGH,	0},
 	{SPEEDSTEP_LOW,		0},
 	{0,			CPUFREQ_TABLE_END},
 };
@@ -68,22 +68,21 @@ static struct cpufreq_frequency_table speedstep_freqs[] = {
  * speedstep_set_state - set the SpeedStep state
  * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH)
  *
- *   Tries to change the SpeedStep state. 
+ *   Tries to change the SpeedStep state.
  */
 static void speedstep_set_state (unsigned int state)
 {
-	u32			pmbase;
-	u8			pm2_blk;
-	u8			value;
-	unsigned long		flags;
+	u32 pmbase;
+	u8 pm2_blk;
+	u8 value;
+	unsigned long flags;
 
 	if (!speedstep_chipset_dev || (state > 0x1))
 		return;
 
 	/* get PMBASE */
 	pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
-	if (!(pmbase & 0x01))
-	{
+	if (!(pmbase & 0x01)) {
 		printk(KERN_ERR "cpufreq: could not find speedstep register\n");
 		return;
 	}
@@ -146,18 +145,16 @@ static void speedstep_set_state (unsigned int state)
  */
 static int speedstep_activate (void)
 {
-	u16		value = 0;
+	u16 value = 0;
 
 	if (!speedstep_chipset_dev)
 		return -EINVAL;
 
-	pci_read_config_word(speedstep_chipset_dev, 
-			     0x00A0, &value);
+	pci_read_config_word(speedstep_chipset_dev, 0x00A0, &value);
 	if (!(value & 0x08)) {
 		value |= 0x08;
 		dprintk(KERN_DEBUG "cpufreq: activating SpeedStep (TM) registers\n");
-		pci_write_config_word(speedstep_chipset_dev, 
-				      0x00A0, value);
+		pci_write_config_word(speedstep_chipset_dev, 0x00A0, value);
 	}
 
 	return 0;
@@ -167,15 +164,15 @@ static int speedstep_activate (void)
 /**
  * speedstep_detect_chipset - detect the Southbridge which contains SpeedStep logic
  *
- *   Detects ICH2-M, ICH3-M and ICH4-M so far. The pci_dev points to 
- * the LPC bridge / PM module which contains all power-management 
+ *   Detects ICH2-M, ICH3-M and ICH4-M so far. The pci_dev points to
+ * the LPC bridge / PM module which contains all power-management
  * functions. Returns the SPEEDSTEP_CHIPSET_-number for the detected
  * chipset, or zero on failure.
  */
 static unsigned int speedstep_detect_chipset (void)
 {
 	speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
-			      PCI_DEVICE_ID_INTEL_82801DB_12, 
+			      PCI_DEVICE_ID_INTEL_82801DB_12,
 			      PCI_ANY_ID,
 			      PCI_ANY_ID,
 			      NULL);
@@ -183,7 +180,7 @@ static unsigned int speedstep_detect_chipset (void)
 		return 4; /* 4-M */
 
 	speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
-			      PCI_DEVICE_ID_INTEL_82801CA_12, 
+			      PCI_DEVICE_ID_INTEL_82801CA_12,
 			      PCI_ANY_ID,
 			      PCI_ANY_ID,
 			      NULL);
@@ -198,11 +195,11 @@ static unsigned int speedstep_detect_chipset (void)
 			      NULL);
 	if (speedstep_chipset_dev) {
 		/* speedstep.c causes lockups on Dell Inspirons 8000 and
-		 * 8100 which use a pretty old revision of the 82815 
+		 * 8100 which use a pretty old revision of the 82815
 		 * host brige. Abort on these systems.
 		 */
-		static struct pci_dev	*hostbridge;
-		u8			rev = 0;
+		static struct pci_dev *hostbridge;
+		u8 rev = 0;
 
 		hostbridge  = pci_find_subsys(PCI_VENDOR_ID_INTEL,
 			      PCI_DEVICE_ID_INTEL_82815_MC,
@@ -212,7 +209,7 @@ static unsigned int speedstep_detect_chipset (void)
 
 		if (!hostbridge)
 			return 2; /* 2-M */
-			
+
 		pci_read_config_byte(hostbridge, PCI_REVISION_ID, &rev);
 		if (rev < 5) {
 			dprintk(KERN_INFO "cpufreq: hostbridge does not support speedstep\n");
@@ -226,6 +223,23 @@ static unsigned int speedstep_detect_chipset (void)
 	return 0;
 }
 
+static unsigned int speedstep_get(unsigned int cpu)
+{
+	unsigned int speed;
+	cpumask_t cpus_allowed,affected_cpu_map;
+
+	/* only run on CPU to be set, or on its sibling */
+	cpus_allowed = current->cpus_allowed;
+#ifdef CONFIG_SMP
+	affected_cpu_map = cpu_sibling_map[cpu];
+#else
+	affected_cpu_map = cpumask_of_cpu(cpu);
+#endif
+	set_cpus_allowed(current, affected_cpu_map);
+	speed=speedstep_get_processor_frequency(speedstep_processor);
+	set_cpus_allowed(current, cpus_allowed);
+	return speed;
+}
 
 /**
  * speedstep_target - set a new CPUFreq policy
@@ -239,7 +253,7 @@ static int speedstep_target (struct cpufreq_policy *policy,
 			     unsigned int target_freq,
 			     unsigned int relation)
 {
-	unsigned int	newstate = 0;
+	unsigned int newstate = 0;
 	struct cpufreq_freqs freqs;
 	cpumask_t cpus_allowed, affected_cpu_map;
 	int i;
@@ -247,14 +261,14 @@ static int speedstep_target (struct cpufreq_policy *policy,
 	if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate))
 		return -EINVAL;
 
+	freqs.old = speedstep_get(policy->cpu);
+	freqs.new = speedstep_freqs[newstate].frequency;
+	freqs.cpu = policy->cpu;
+
 	/* no transition necessary */
 	if (freqs.old == freqs.new)
 		return 0;
 
-	freqs.old = speedstep_get_processor_frequency(speedstep_processor);
-	freqs.new = speedstep_freqs[newstate].frequency;
-	freqs.cpu = policy->cpu;
-
 	cpus_allowed = current->cpus_allowed;
 
 	/* only run on CPU to be set, or on its sibling */
@@ -301,9 +315,9 @@ static int speedstep_verify (struct cpufreq_policy *policy)
 
 static int speedstep_cpu_init(struct cpufreq_policy *policy)
 {
-	int		result = 0;
-	unsigned int	speed;
-	cpumask_t       cpus_allowed,affected_cpu_map;
+	int result = 0;
+	unsigned int speed;
+	cpumask_t cpus_allowed,affected_cpu_map;
 
 
 	/* capability check */
@@ -324,18 +338,16 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
 				     &speedstep_freqs[SPEEDSTEP_LOW].frequency,
 				     &speedstep_freqs[SPEEDSTEP_HIGH].frequency,
 				     &speedstep_set_state);
-	if (result) {
-		set_cpus_allowed(current, cpus_allowed);
+	set_cpus_allowed(current, cpus_allowed);
+	if (result)
 		return result;
-	}
 
 	/* get current speed setting */
-	speed = speedstep_get_processor_frequency(speedstep_processor);
-	set_cpus_allowed(current, cpus_allowed);
+	speed = speedstep_get(policy->cpu);
 	if (!speed)
 		return -EIO;
 
-	dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n", 
+	dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n",
 		(speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? "low" : "high",
 		(speed / 1000));
 
@@ -360,11 +372,6 @@ static int speedstep_cpu_exit(struct cpufreq_policy *policy)
 	return 0;
 }
 
-static unsigned int speedstep_get(unsigned int cpu)
-{
-	return speedstep_get_processor_frequency(speedstep_processor);
-}
-
 static struct freq_attr* speedstep_attr[] = {
 	&cpufreq_freq_attr_scaling_available_freqs,
 	NULL,
@@ -372,14 +379,14 @@ static struct freq_attr* speedstep_attr[] = {
 
 
 static struct cpufreq_driver speedstep_driver = {
-	.name		= "speedstep-ich",
-	.verify 	= speedstep_verify,
-	.target 	= speedstep_target,
-	.init		= speedstep_cpu_init,
-	.exit		= speedstep_cpu_exit,
-	.get		= speedstep_get,
-	.owner		= THIS_MODULE,
-	.attr		= speedstep_attr,
+	.name	= "speedstep-ich",
+	.verify	= speedstep_verify,
+	.target	= speedstep_target,
+	.init	= speedstep_cpu_init,
+	.exit	= speedstep_cpu_exit,
+	.get	= speedstep_get,
+	.owner	= THIS_MODULE,
+	.attr	= speedstep_attr,
 };
 
 
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
index 6aa31cd5a..5d176b19a 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
@@ -115,6 +115,11 @@ static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high)
 		: "=a" (result), "=b" (high_mhz), "=c" (low_mhz), "=d" (state), "=D" (edi)
 		: "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0)
 	);
+
+	/* abort if results are obviously incorrect... */
+	if ((high_mhz + low_mhz) < 600)
+		return -EINVAL;
+
 	*high = high_mhz * 1000;
 	*low  = low_mhz  * 1000;
 
@@ -180,7 +185,7 @@ static void speedstep_set_state (unsigned int state)
 	local_irq_restore(flags);
 
 	if (new_state == state) {
-		dprintk(KERN_INFO "cpufreq: change to %u MHz succeeded after %u tries with result %u\n", (freqs.new / 1000), retry, result);
+		dprintk(KERN_INFO "cpufreq: change to %u MHz succeeded after %u tries with result %u\n", (speedstep_freqs[new_state].frequency / 1000), retry, result);
 	} else {
 		printk(KERN_ERR "cpufreq: change failed with new_state %u and result %u\n", new_state, result);
 	}
diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c
index 09acdd76b..d13f9bb47 100644
--- a/arch/i386/kernel/cpu/intel.c
+++ b/arch/i386/kernel/cpu/intel.c
@@ -72,41 +72,44 @@ struct _cache_table
 /* all the cache descriptor types we care about (no TLB or trace cache entries) */
 static struct _cache_table cache_table[] __initdata =
 {
-	{ 0x06, LVL_1_INST, 8 },
-	{ 0x08, LVL_1_INST, 16 },
-	{ 0x0a, LVL_1_DATA, 8 },
-	{ 0x0c, LVL_1_DATA, 16 },
-	{ 0x22, LVL_3,      512 },
-	{ 0x23, LVL_3,      1024 },
-	{ 0x25, LVL_3,      2048 },
-	{ 0x29, LVL_3,      4096 },
-	{ 0x2c, LVL_1_DATA, 32 },
-	{ 0x30, LVL_1_INST, 32 },
-	{ 0x39, LVL_2,      128 },
-	{ 0x3b, LVL_2,      128 },
-	{ 0x3c, LVL_2,      256 },
-	{ 0x41, LVL_2,      128 },
-	{ 0x42, LVL_2,      256 },
-	{ 0x43, LVL_2,      512 },
-	{ 0x44, LVL_2,      1024 },
-	{ 0x45, LVL_2,      2048 },
-	{ 0x60, LVL_1_DATA, 16 },
-	{ 0x66, LVL_1_DATA, 8 },
-	{ 0x67, LVL_1_DATA, 16 },
-	{ 0x68, LVL_1_DATA, 32 },
-	{ 0x70, LVL_TRACE,  12 },
-	{ 0x71, LVL_TRACE,  16 },
-	{ 0x72, LVL_TRACE,  32 },
-	{ 0x79, LVL_2,      128 },
-	{ 0x7a, LVL_2,      256 },
-	{ 0x7b, LVL_2,      512 },
-	{ 0x7c, LVL_2,      1024 },
-	{ 0x82, LVL_2,      256 },
-	{ 0x83, LVL_2,      512 },
-	{ 0x84, LVL_2,      1024 },
-	{ 0x85, LVL_2,      2048 },
-	{ 0x86, LVL_2,      512 },
-	{ 0x87, LVL_2,      1024 },
+	{ 0x06, LVL_1_INST, 8 },	/* 4-way set assoc, 32 byte line size */
+	{ 0x08, LVL_1_INST, 16 },	/* 4-way set assoc, 32 byte line size */
+	{ 0x0a, LVL_1_DATA, 8 },	/* 2 way set assoc, 32 byte line size */
+	{ 0x0c, LVL_1_DATA, 16 },	/* 4-way set assoc, 32 byte line size */
+	{ 0x22, LVL_3,      512 },	/* 4-way set assoc, sectored cache, 64 byte line size */
+	{ 0x23, LVL_3,      1024 },	/* 8-way set assoc, sectored cache, 64 byte line size */
+	{ 0x25, LVL_3,      2048 },	/* 8-way set assoc, sectored cache, 64 byte line size */
+	{ 0x29, LVL_3,      4096 },	/* 8-way set assoc, sectored cache, 64 byte line size */
+	{ 0x2c, LVL_1_DATA, 32 },	/* 8-way set assoc, 64 byte line size */
+	{ 0x30, LVL_1_INST, 32 },	/* 8-way set assoc, 64 byte line size */
+	{ 0x39, LVL_2,      128 },	/* 4-way set assoc, sectored cache, 64 byte line size */
+	{ 0x3b, LVL_2,      128 },	/* 2-way set assoc, sectored cache, 64 byte line size */
+	{ 0x3c, LVL_2,      256 },	/* 4-way set assoc, sectored cache, 64 byte line size */
+	{ 0x41, LVL_2,      128 },	/* 4-way set assoc, 32 byte line size */
+	{ 0x42, LVL_2,      256 },	/* 4-way set assoc, 32 byte line size */
+	{ 0x43, LVL_2,      512 },	/* 4-way set assoc, 32 byte line size */
+	{ 0x44, LVL_2,      1024 },	/* 4-way set assoc, 32 byte line size */
+	{ 0x45, LVL_2,      2048 },	/* 4-way set assoc, 32 byte line size */
+	{ 0x60, LVL_1_DATA, 16 },	/* 8-way set assoc, sectored cache, 64 byte line size */
+	{ 0x66, LVL_1_DATA, 8 },	/* 4-way set assoc, sectored cache, 64 byte line size */
+	{ 0x67, LVL_1_DATA, 16 },	/* 4-way set assoc, sectored cache, 64 byte line size */
+	{ 0x68, LVL_1_DATA, 32 },	/* 4-way set assoc, sectored cache, 64 byte line size */
+	{ 0x70, LVL_TRACE,  12 },	/* 8-way set assoc */
+	{ 0x71, LVL_TRACE,  16 },	/* 8-way set assoc */
+	{ 0x72, LVL_TRACE,  32 },	/* 8-way set assoc */
+	{ 0x78, LVL_2,    1024 },	/* 4-way set assoc, 64 byte line size */
+	{ 0x79, LVL_2,     128 },	/* 8-way set assoc, sectored cache, 64 byte line size */
+	{ 0x7a, LVL_2,     256 },	/* 8-way set assoc, sectored cache, 64 byte line size */
+	{ 0x7b, LVL_2,     512 },	/* 8-way set assoc, sectored cache, 64 byte line size */
+	{ 0x7c, LVL_2,    1024 },	/* 8-way set assoc, sectored cache, 64 byte line size */
+	{ 0x7d, LVL_2,    2048 },	/* 8-way set assoc, 64 byte line size */
+	{ 0x7f, LVL_2,     512 },	/* 2-way set assoc, 64 byte line size */
+	{ 0x82, LVL_2,     256 },	/* 8-way set assoc, 32 byte line size */
+	{ 0x83, LVL_2,     512 },	/* 8-way set assoc, 32 byte line size */
+	{ 0x84, LVL_2,    1024 },	/* 8-way set assoc, 32 byte line size */
+	{ 0x85, LVL_2,    2048 },	/* 8-way set assoc, 32 byte line size */
+	{ 0x86, LVL_2,     512 },	/* 4-way set assoc, 64 byte line size */
+	{ 0x87, LVL_2,    1024 },	/* 8-way set assoc, 64 byte line size */
 	{ 0x00, 0, 0}
 };
 
diff --git a/arch/i386/kernel/cpu/mtrr/mtrr.h b/arch/i386/kernel/cpu/mtrr/mtrr.h
index fee8b5ccc..0d10c115d 100644
--- a/arch/i386/kernel/cpu/mtrr/mtrr.h
+++ b/arch/i386/kernel/cpu/mtrr/mtrr.h
@@ -52,7 +52,6 @@ struct mtrr_ops {
 };
 
 extern int generic_get_free_region(unsigned long base, unsigned long size);
-extern void generic_init_secondary(void);
 extern int generic_validate_add_page(unsigned long base, unsigned long size,
 				     unsigned int type);
 
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
index 423429491..bdd13285f 100644
--- a/arch/i386/kernel/cpu/proc.c
+++ b/arch/i386/kernel/cpu/proc.c
@@ -44,8 +44,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
 		/* Intel-defined (#2) */
-		"pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "tm2",
-		"est", NULL, "cid", NULL, NULL, NULL, NULL, NULL,
+		"pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "est",
+		"tm2", NULL, "cid", NULL, NULL, NULL, "xtpr", NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
diff --git a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
index d2d2610f2..d4f4a5aff 100644
--- a/arch/i386/kernel/dmi_scan.c
+++ b/arch/i386/kernel/dmi_scan.c
@@ -4,7 +4,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <asm/acpi.h>
+#include <linux/acpi.h>
 #include <asm/io.h>
 #include <linux/pm.h>
 #include <asm/system.h>
@@ -162,27 +162,6 @@ static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
 #define NO_MATCH	{ DMI_NONE, NULL}
 #define MATCH		DMI_MATCH
 
-/*
- * Some machines, usually laptops, can't handle an enabled local APIC.
- * The symptoms include hangs or reboots when suspending or resuming,
- * attaching or detaching the power cord, or entering BIOS setup screens
- * through magic key sequences.
- */
-static int __init local_apic_kills_bios(struct dmi_blacklist *d)
-{
-#ifdef CONFIG_X86_LOCAL_APIC
-	extern int enable_local_apic;
-	if (enable_local_apic == 0) {
-		enable_local_apic = -1;
-		printk(KERN_WARNING "%s with broken BIOS detected. "
-		       "Refusing to enable the local APIC.\n",
-		       d->ident);
-	}
-#endif
-	return 0;
-}
-
-
 /*
  * Toshiba keyboard likes to repeat keys when they are not repeated.
  */
@@ -284,32 +263,6 @@ static __init int disable_acpi_pci(struct dmi_blacklist *d)
  
 static __initdata struct dmi_blacklist dmi_blacklist[]={
 
-	/* Machines which have problems handling enabled local APICs */
-
-	{ local_apic_kills_bios, "Dell Inspiron", {
-			MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
-			MATCH(DMI_PRODUCT_NAME, "Inspiron"),
-			NO_MATCH, NO_MATCH
-			} },
-
-	{ local_apic_kills_bios, "Dell Latitude", {
-			MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
-			MATCH(DMI_PRODUCT_NAME, "Latitude"),
-			NO_MATCH, NO_MATCH
-			} },
-
-	{ local_apic_kills_bios, "IBM Thinkpad T20", {
-			MATCH(DMI_BOARD_VENDOR, "IBM"),
-			MATCH(DMI_BOARD_NAME, "264741U"),
-			NO_MATCH, NO_MATCH
-			} },
-
-	{ local_apic_kills_bios, "ASUS L3C", {
-			MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
-			MATCH(DMI_BOARD_NAME, "P4_L3C"),
-			NO_MATCH, NO_MATCH
-			} },
-
 	{ broken_toshiba_keyboard, "Toshiba Satellite 4030cdt", { /* Keyboard generates spurious repeats */
 			MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
 			NO_MATCH, NO_MATCH, NO_MATCH
@@ -490,41 +443,6 @@ static __initdata struct dmi_blacklist dmi_blacklist[]={
 
 	{ NULL, }
 };
-	
-	
-/*
- *	Walk the blacklist table running matching functions until someone 
- *	returns 1 or we hit the end.
- */
- 
-
-static __init void dmi_check_blacklist(void)
-{
-#ifdef	CONFIG_ACPI_BOOT
-#define	ACPI_BLACKLIST_CUTOFF_YEAR	2001
-
-	if (dmi_ident[DMI_BIOS_DATE]) { 
-		char *s = strrchr(dmi_ident[DMI_BIOS_DATE], '/'); 
-		if (s) { 
-			int year, disable = 0;
-			s++; 
-			year = simple_strtoul(s,NULL,0); 
-			if (year >= 1000) 
-				disable = year < ACPI_BLACKLIST_CUTOFF_YEAR; 
-			else if (year < 1 || (year > 90 && year <= 99))
-				disable = 1; 
-			if (disable && !acpi_force) { 
-				printk(KERN_NOTICE "ACPI disabled because your bios is from %s and too old\n", s);
-				printk(KERN_NOTICE "You can enable it with acpi=force\n");
-				disable_acpi();
-			} 
-		}
-	}
-#endif
- 	dmi_check_system(dmi_blacklist);
-}
-
-	
 
 /*
  *	Process a DMI table entry. Right now all we care about are the BIOS
@@ -582,7 +500,7 @@ void __init dmi_scan_machine(void)
 {
 	int err = dmi_iterate(dmi_decode);
 	if(err == 0)
-		dmi_check_blacklist();
+ 		dmi_check_system(dmi_blacklist);
 	else
 		printk(KERN_INFO "DMI not present.\n");
 }
diff --git a/arch/i386/kernel/doublefault.c b/arch/i386/kernel/doublefault.c
index 6b4a8f3cc..789af3e9f 100644
--- a/arch/i386/kernel/doublefault.c
+++ b/arch/i386/kernel/doublefault.c
@@ -13,7 +13,7 @@
 static unsigned long doublefault_stack[DOUBLEFAULT_STACKSIZE];
 #define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE)
 
-#define ptr_ok(x) ((x) > 0xc0000000 && (x) < 0xc1000000)
+#define ptr_ok(x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + 0x1000000)
 
 static void doublefault_fn(void)
 {
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index 6387a7e0c..1c230a7cb 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -255,11 +255,11 @@ sysenter_past_esp:
 	pushl %eax
 	SAVE_ALL
 	GET_THREAD_INFO(%ebp)
-	cmpl $(nr_syscalls), %eax
-	jae syscall_badsys
 
 	testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
 	jnz syscall_trace_entry
+	cmpl $(nr_syscalls), %eax
+	jae syscall_badsys
 	call *sys_call_table(,%eax,4)
 	movl %eax,EAX(%esp)
 	cli
@@ -278,11 +278,11 @@ ENTRY(system_call)
 	pushl %eax			# save orig_eax
 	SAVE_ALL
 	GET_THREAD_INFO(%ebp)
-	cmpl $(nr_syscalls), %eax
-	jae syscall_badsys
 					# system call tracing in operation
 	testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
 	jnz syscall_trace_entry
+	cmpl $(nr_syscalls), %eax
+	jae syscall_badsys
 syscall_call:
 	call *sys_call_table(,%eax,4)
 	movl %eax,EAX(%esp)		# store the return value
@@ -348,7 +348,7 @@ syscall_trace_entry:
 	# perform syscall exit tracing
 	ALIGN
 syscall_exit_work:
-	testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT), %cl
+	testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl
 	jz work_pending
 	sti				# could let do_syscall_trace() call
 					# schedule() instead
@@ -489,9 +489,16 @@ ENTRY(debug)
 	jne debug_stack_correct
 	FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn)
 debug_stack_correct:
-	pushl $0
-	pushl $do_debug
-	jmp error_code
+	pushl $-1			# mark this as an int
+	SAVE_ALL
+	movl %esp,%edx
+  	pushl $0
+	pushl %edx
+	call do_debug
+	addl $8,%esp
+	testl %eax,%eax
+	jnz restore_all
+	jmp ret_from_exception
 
 /*
  * NMI is doubly nasty. It can happen _while_ we're handling
@@ -540,9 +547,16 @@ nmi_debug_stack_fixup:
 	jmp nmi_stack_correct
 
 ENTRY(int3)
+	pushl $-1			# mark this as an int
+	SAVE_ALL
+	movl %esp,%edx
 	pushl $0
-	pushl $do_int3
-	jmp error_code
+	pushl %edx
+	call do_int3
+	addl $8,%esp
+	testl %eax,%eax
+	jnz restore_all
+	jmp ret_from_exception
 
 ENTRY(overflow)
 	pushl $0
@@ -886,5 +900,6 @@ ENTRY(sys_call_table)
 	.long sys_mq_notify
 	.long sys_mq_getsetattr
 	.long sys_ni_syscall		/* reserved for kexec */
+	.long sys_waitid
 
 syscall_table_size=(.-sys_call_table)
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index 69bad9bd0..95fe2fdf4 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -521,6 +521,3 @@ ENTRY(cpu_gdt_table)
 	.quad 0x0000000000000000	/* 0xf0 - unused */
 	.quad 0x0000000000000000	/* 0xf8 - GDT entry 31: double-fault TSS */
 
-#ifdef CONFIG_SMP
-	.fill (NR_CPUS-1)*GDT_ENTRIES,8,0 /* other CPU's GDT */
-#endif
diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
index 064d6fb8a..b93f0332d 100644
--- a/arch/i386/kernel/i386_ksyms.c
+++ b/arch/i386/kernel/i386_ksyms.c
@@ -23,7 +23,6 @@
 #include <asm/uaccess.h>
 #include <asm/checksum.h>
 #include <asm/io.h>
-#include <asm/hardirq.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
 #include <asm/mmx.h>
@@ -32,6 +31,7 @@
 #include <asm/tlbflush.h>
 #include <asm/nmi.h>
 #include <asm/ist.h>
+#include <asm/kdebug.h>
 
 extern void dump_thread(struct pt_regs *, struct user *);
 extern spinlock_t rtc_lock;
@@ -87,10 +87,10 @@ EXPORT_SYMBOL(get_cmos_time);
 EXPORT_SYMBOL(cpu_khz);
 EXPORT_SYMBOL(apm_info);
 
-EXPORT_SYMBOL_NOVERS(__down_failed);
-EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
-EXPORT_SYMBOL_NOVERS(__down_failed_trylock);
-EXPORT_SYMBOL_NOVERS(__up_wakeup);
+EXPORT_SYMBOL(__down_failed);
+EXPORT_SYMBOL(__down_failed_interruptible);
+EXPORT_SYMBOL(__down_failed_trylock);
+EXPORT_SYMBOL(__up_wakeup);
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial_copy_generic);
 /* Delay loops */
@@ -99,9 +99,9 @@ EXPORT_SYMBOL(__udelay);
 EXPORT_SYMBOL(__delay);
 EXPORT_SYMBOL(__const_udelay);
 
-EXPORT_SYMBOL_NOVERS(__get_user_1);
-EXPORT_SYMBOL_NOVERS(__get_user_2);
-EXPORT_SYMBOL_NOVERS(__get_user_4);
+EXPORT_SYMBOL(__get_user_1);
+EXPORT_SYMBOL(__get_user_2);
+EXPORT_SYMBOL(__get_user_4);
 
 EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strstr);
@@ -142,8 +142,8 @@ EXPORT_SYMBOL(cpu_sibling_map);
 EXPORT_SYMBOL(cpu_data);
 EXPORT_SYMBOL(cpu_online_map);
 EXPORT_SYMBOL(cpu_callout_map);
-EXPORT_SYMBOL_NOVERS(__write_lock_failed);
-EXPORT_SYMBOL_NOVERS(__read_lock_failed);
+EXPORT_SYMBOL(__write_lock_failed);
+EXPORT_SYMBOL(__read_lock_failed);
 
 /* Global SMP stuff */
 EXPORT_SYMBOL(synchronize_irq);
@@ -175,8 +175,9 @@ EXPORT_SYMBOL_GPL(unset_nmi_callback);
 
 #undef memcmp
 extern int memcmp(const void *,const void *,__kernel_size_t);
-EXPORT_SYMBOL_NOVERS(memcmp);
+EXPORT_SYMBOL(memcmp);
 
+EXPORT_SYMBOL(register_die_notifier);
 #ifdef CONFIG_HAVE_DEC_LOCK
 EXPORT_SYMBOL(atomic_dec_and_lock);
 #endif
diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
index 97653d20f..dec7ebf49 100644
--- a/arch/i386/kernel/i8259.c
+++ b/arch/i386/kernel/i8259.c
@@ -4,7 +4,6 @@
 #include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
-#include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/smp_lock.h>
@@ -12,10 +11,12 @@
 #include <linux/kernel_stat.h>
 #include <linux/sysdev.h>
 
+#include <asm/8253pit.h>
 #include <asm/atomic.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/timer.h>
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 #include <asm/delay.h>
@@ -225,7 +226,7 @@ spurious_8259A_irq:
 		 * lets ACK and report it. [once per IRQ]
 		 */
 		if (!(spurious_irq_mask & irqmask)) {
-			printk("spurious 8259A interrupt: IRQ%d.\n", irq);
+			printk(KERN_DEBUG "spurious 8259A interrupt: IRQ%d.\n", irq);
 			spurious_irq_mask |= irqmask;
 		}
 		atomic_inc(&irq_err_count);
@@ -238,14 +239,39 @@ spurious_8259A_irq:
 	}
 }
 
+static char irq_trigger[2];
+/**
+ * ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ
+ */
+static void restore_ELCR(char *trigger)
+{
+	outb(trigger[0], 0x4d0);
+	outb(trigger[1], 0x4d1);
+}
+
+static void save_ELCR(char *trigger)
+{
+	/* IRQ 0,1,2,8,13 are marked as reserved */
+	trigger[0] = inb(0x4d0) & 0xF8;
+	trigger[1] = inb(0x4d1) & 0xDE;
+}
+
 static int i8259A_resume(struct sys_device *dev)
 {
 	init_8259A(0);
+	restore_ELCR(irq_trigger);
+	return 0;
+}
+
+static int i8259A_suspend(struct sys_device *dev, u32 state)
+{
+	save_ELCR(irq_trigger);
 	return 0;
 }
 
 static struct sysdev_class i8259_sysdev_class = {
 	set_kset_name("i8259"),
+	.suspend = i8259A_suspend,
 	.resume = i8259A_resume,
 };
 
@@ -362,46 +388,6 @@ void __init init_ISA_irqs (void)
 	}
 }
 
-static void setup_timer(void)
-{
-	extern spinlock_t i8253_lock;
-	unsigned long flags;
-
-	spin_lock_irqsave(&i8253_lock, flags);
-	outb_p(0x34,PIT_MODE);		/* binary, mode 2, LSB/MSB, ch 0 */
-	udelay(10);
-	outb_p(LATCH & 0xff , PIT_CH0);	/* LSB */
-	udelay(10);
-	outb(LATCH >> 8 , PIT_CH0);	/* MSB */
-	spin_unlock_irqrestore(&i8253_lock, flags);
-}
-
-static int timer_resume(struct sys_device *dev)
-{
-	setup_timer();
-	return 0;
-}
-
-static struct sysdev_class timer_sysclass = {
-	set_kset_name("timer"),
-	.resume	= timer_resume,
-};
-
-static struct sys_device device_timer = {
-	.id	= 0,
-	.cls	= &timer_sysclass,
-};
-
-static int __init init_timer_sysfs(void)
-{
-	int error = sysdev_class_register(&timer_sysclass);
-	if (!error)
-		error = sysdev_register(&device_timer);
-	return error;
-}
-
-device_initcall(init_timer_sysfs);
-
 void __init init_IRQ(void)
 {
 	int i;
@@ -431,7 +417,7 @@ void __init init_IRQ(void)
 	 * Set the clock to HZ Hz, we already have a valid
 	 * vector now:
 	 */
-	setup_timer();
+	setup_pit_timer();
 
 	/*
 	 * External FPU? Set up irq13 if so, for
diff --git a/arch/i386/kernel/init_task.c b/arch/i386/kernel/init_task.c
index 5e1897649..9caa8e8db 100644
--- a/arch/i386/kernel/init_task.c
+++ b/arch/i386/kernel/init_task.c
@@ -40,10 +40,7 @@ EXPORT_SYMBOL(init_task);
 
 /*
  * per-CPU TSS segments. Threads are completely 'soft' on Linux,
- * no more per-task TSS's. The TSS size is kept cacheline-aligned
- * so they are allowed to end up in the .data.cacheline_aligned
- * section. Since TSS's are completely CPU-local, we want them
- * on exact cacheline boundaries, to eliminate cacheline ping-pong.
+ * no more per-task TSS's.
  */ 
-struct tss_struct init_tss[NR_CPUS] __cacheline_aligned = { [0 ... NR_CPUS-1] = INIT_TSS };
+DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_maxaligned_in_smp = INIT_TSS;
 
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index a40687e7c..4bbd49692 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -32,6 +32,7 @@
 #include <linux/compiler.h>
 #include <linux/acpi.h>
 
+#include <linux/sysdev.h>
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/desc.h>
@@ -85,7 +86,7 @@ int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1};
  * shared ISA-space IRQs, so we have to support them. We are super
  * fast in the common case, and fast for shared ISA-space IRQs.
  */
-static void __init add_pin_to_irq(unsigned int irq, int apic, int pin)
+static void add_pin_to_irq(unsigned int irq, int apic, int pin)
 {
 	static int first_free_entry = NR_IRQS;
 	struct irq_pin_list *entry = irq_2_pin + irq;
@@ -705,13 +706,15 @@ static int __init ioapic_pirq_setup(char *str)
 		pirq_entries[i] = -1;
 
 	pirqs_enabled = 1;
-	printk(KERN_INFO "PIRQ redirection, working around broken MP-BIOS.\n");
+	apic_printk(APIC_VERBOSE, KERN_INFO
+			"PIRQ redirection, working around broken MP-BIOS.\n");
 	max = MAX_PIRQS;
 	if (ints[0] < MAX_PIRQS)
 		max = ints[0];
 
 	for (i = 0; i < max; i++) {
-		printk(KERN_DEBUG "... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
+		apic_printk(APIC_VERBOSE, KERN_DEBUG
+				"... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
 		/*
 		 * PIRQs are mapped upside down, usually.
 		 */
@@ -742,7 +745,7 @@ static int __init find_irq_entry(int apic, int pin, int type)
 /*
  * Find the pin to which IRQ[irq] (ISA) is connected
  */
-static int __init find_isa_irq_pin(int irq, int type)
+static int find_isa_irq_pin(int irq, int type)
 {
 	int i;
 
@@ -772,8 +775,8 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
 {
 	int apic, i, best_guess = -1;
 
-	Dprintk("querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
-		bus, slot, pin);
+	apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, "
+		"slot:%d, pin:%d.\n", bus, slot, pin);
 	if (mp_bus_id_to_pci_bus[bus] == -1) {
 		printk(KERN_WARNING "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
 		return -1;
@@ -841,7 +844,8 @@ static int __init EISA_ELCR(unsigned int irq)
 		unsigned int port = 0x4d0 + (irq >> 3);
 		return (inb(port) >> (irq & 7)) & 1;
 	}
-	printk(KERN_INFO "Broken MPtable reports ISA irq %d\n", irq);
+	apic_printk(APIC_VERBOSE, KERN_INFO
+			"Broken MPtable reports ISA irq %d\n", irq);
 	return 0;
 }
 
@@ -1083,10 +1087,12 @@ static int pin_2_irq(int idx, int apic, int pin)
 	if ((pin >= 16) && (pin <= 23)) {
 		if (pirq_entries[pin-16] != -1) {
 			if (!pirq_entries[pin-16]) {
-				printk(KERN_DEBUG "disabling PIRQ%d\n", pin-16);
+				apic_printk(APIC_VERBOSE, KERN_DEBUG
+						"disabling PIRQ%d\n", pin-16);
 			} else {
 				irq = pirq_entries[pin-16];
-				printk(KERN_DEBUG "using PIRQ%d -> IRQ %d\n",
+				apic_printk(APIC_VERBOSE, KERN_DEBUG
+						"using PIRQ%d -> IRQ %d\n",
 						pin-16, irq);
 			}
 		}
@@ -1114,11 +1120,7 @@ static inline int IO_APIC_irq_trigger(int irq)
 /* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
 u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 };
 
-#ifdef CONFIG_PCI_MSI
 int assign_irq_vector(int irq)
-#else
-int __init assign_irq_vector(int irq)
-#endif
 {
 	static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
 
@@ -1176,7 +1178,7 @@ void __init setup_IO_APIC_irqs(void)
 	int apic, pin, idx, irq, first_notcon = 1, vector;
 	unsigned long flags;
 
-	printk(KERN_DEBUG "init IO_APIC IRQs\n");
+	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
 	for (apic = 0; apic < nr_ioapics; apic++) {
 	for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
@@ -1195,10 +1197,14 @@ void __init setup_IO_APIC_irqs(void)
 		idx = find_irq_entry(apic,pin,mp_INT);
 		if (idx == -1) {
 			if (first_notcon) {
-				printk(KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mpc_apicid, pin);
+				apic_printk(APIC_VERBOSE, KERN_DEBUG
+						" IO-APIC (apicid-pin) %d-%d",
+						mp_ioapics[apic].mpc_apicid,
+						pin);
 				first_notcon = 0;
 			} else
-				printk(", %d-%d", mp_ioapics[apic].mpc_apicid, pin);
+				apic_printk(APIC_VERBOSE, ", %d-%d",
+					mp_ioapics[apic].mpc_apicid, pin);
 			continue;
 		}
 
@@ -1239,7 +1245,7 @@ void __init setup_IO_APIC_irqs(void)
 	}
 
 	if (!first_notcon)
-		printk(" not connected.\n");
+		apic_printk(APIC_VERBOSE, " not connected.\n");
 }
 
 /*
@@ -1299,6 +1305,9 @@ void __init print_IO_APIC(void)
 	union IO_APIC_reg_03 reg_03;
 	unsigned long flags;
 
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
  	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
 	for (i = 0; i < nr_ioapics; i++)
 		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
@@ -1441,6 +1450,9 @@ static void print_APIC_bitfield (int base)
 	unsigned int v;
 	int i, j;
 
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
 	printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG);
 	for (i = 0; i < 8; i++) {
 		v = apic_read(base + i*0x10);
@@ -1458,6 +1470,9 @@ void /*__init*/ print_local_APIC(void * dummy)
 {
 	unsigned int v, ver, maxlvt;
 
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
 	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
 		smp_processor_id(), hard_smp_processor_id());
 	v = apic_read(APIC_ID);
@@ -1545,6 +1560,9 @@ void /*__init*/ print_PIC(void)
 	unsigned int v;
 	unsigned long flags;
 
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
 	printk(KERN_DEBUG "\nprinting PIC contents\n");
 
 	spin_lock_irqsave(&i8259A_lock, flags);
@@ -1680,7 +1698,9 @@ static void __init setup_ioapic_ids_from_mpc(void)
 		} else {
 			physid_mask_t tmp;
 			tmp = apicid_to_cpu_present(mp_ioapics[apic].mpc_apicid);
-			printk("Setting %d in the phys_id_present_map\n", mp_ioapics[apic].mpc_apicid);
+			apic_printk(APIC_VERBOSE, "Setting %d in the "
+					"phys_id_present_map\n",
+					mp_ioapics[apic].mpc_apicid);
 			physids_or(phys_id_present_map, phys_id_present_map, tmp);
 		}
 
@@ -1699,8 +1719,9 @@ static void __init setup_ioapic_ids_from_mpc(void)
 		 * Read the right value from the MPC table and
 		 * write it into the ID register.
 	 	 */
-		printk(KERN_INFO "...changing IO-APIC physical APIC ID to %d ...",
-					mp_ioapics[apic].mpc_apicid);
+		apic_printk(APIC_VERBOSE, KERN_INFO
+			"...changing IO-APIC physical APIC ID to %d ...",
+			mp_ioapics[apic].mpc_apicid);
 
 		reg_00.bits.ID = mp_ioapics[apic].mpc_apicid;
 		spin_lock_irqsave(&ioapic_lock, flags);
@@ -1714,9 +1735,9 @@ static void __init setup_ioapic_ids_from_mpc(void)
 		reg_00.raw = io_apic_read(apic, 0);
 		spin_unlock_irqrestore(&ioapic_lock, flags);
 		if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid)
-			panic("could not set ID!\n");
+			printk("could not set ID!\n");
 		else
-			printk(" ok.\n");
+			apic_printk(APIC_VERBOSE, " ok.\n");
 	}
 }
 #else
@@ -2031,11 +2052,11 @@ static void setup_nmi (void)
 	 * is from Maciej W. Rozycki - so we do not have to EOI from
 	 * the NMI handler or the timer interrupt.
 	 */ 
-	printk(KERN_INFO "activating NMI Watchdog ...");
+	apic_printk(APIC_VERBOSE, KERN_INFO "activating NMI Watchdog ...");
 
 	on_each_cpu(enable_NMI_through_LVT0, NULL, 1, 1);
 
-	printk(" done.\n");
+	apic_printk(APIC_VERBOSE, " done.\n");
 }
 
 /*
@@ -2212,7 +2233,8 @@ static inline void check_timer(void)
 		return;
 	}
 	printk(" failed :(.\n");
-	panic("IO-APIC + timer doesn't work! Try using the 'noapic' kernel parameter\n");
+	panic("IO-APIC + timer doesn't work!  Boot with apic=debug and send a "
+		"report.  Then try booting with the 'noapic' option");
 }
 
 /*
@@ -2262,6 +2284,98 @@ static int __init io_apic_bug_finalize(void)
 
 late_initcall(io_apic_bug_finalize);
 
+struct sysfs_ioapic_data {
+	struct sys_device dev;
+	struct IO_APIC_route_entry entry[0];
+};
+static struct sysfs_ioapic_data * mp_ioapic_data[MAX_IO_APICS];
+
+static int ioapic_suspend(struct sys_device *dev, u32 state)
+{
+	struct IO_APIC_route_entry *entry;
+	struct sysfs_ioapic_data *data;
+	unsigned long flags;
+	int i;
+	
+	data = container_of(dev, struct sysfs_ioapic_data, dev);
+	entry = data->entry;
+	spin_lock_irqsave(&ioapic_lock, flags);
+	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
+		*(((int *)entry) + 1) = io_apic_read(dev->id, 0x11 + 2 * i);
+		*(((int *)entry) + 0) = io_apic_read(dev->id, 0x10 + 2 * i);
+	}
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	return 0;
+}
+
+static int ioapic_resume(struct sys_device *dev)
+{
+	struct IO_APIC_route_entry *entry;
+	struct sysfs_ioapic_data *data;
+	unsigned long flags;
+	union IO_APIC_reg_00 reg_00;
+	int i;
+	
+	data = container_of(dev, struct sysfs_ioapic_data, dev);
+	entry = data->entry;
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	reg_00.raw = io_apic_read(dev->id, 0);
+	if (reg_00.bits.ID != mp_ioapics[dev->id].mpc_apicid) {
+		reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid;
+		io_apic_write(dev->id, 0, reg_00.raw);
+	}
+	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
+		io_apic_write(dev->id, 0x11+2*i, *(((int *)entry)+1));
+		io_apic_write(dev->id, 0x10+2*i, *(((int *)entry)+0));
+	}
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	return 0;
+}
+
+static struct sysdev_class ioapic_sysdev_class = {
+	set_kset_name("ioapic"),
+	.suspend = ioapic_suspend,
+	.resume = ioapic_resume,
+};
+
+static int __init ioapic_init_sysfs(void)
+{
+	struct sys_device * dev;
+	int i, size, error = 0;
+
+	error = sysdev_class_register(&ioapic_sysdev_class);
+	if (error)
+		return error;
+
+	for (i = 0; i < nr_ioapics; i++ ) {
+		size = sizeof(struct sys_device) + nr_ioapic_registers[i] 
+			* sizeof(struct IO_APIC_route_entry);
+		mp_ioapic_data[i] = kmalloc(size, GFP_KERNEL);
+		if (!mp_ioapic_data[i]) {
+			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
+			continue;
+		}
+		memset(mp_ioapic_data[i], 0, size);
+		dev = &mp_ioapic_data[i]->dev;
+		dev->id = i; 
+		dev->cls = &ioapic_sysdev_class;
+		error = sysdev_register(dev);
+		if (error) {
+			kfree(mp_ioapic_data[i]);
+			mp_ioapic_data[i] = NULL;
+			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
+			continue;
+		}
+	}
+
+	return 0;
+}
+
+device_initcall(ioapic_init_sysfs);
+
 /* --------------------------------------------------------------------------
                           ACPI-based IOAPIC Configuration
    -------------------------------------------------------------------------- */
@@ -2334,7 +2448,8 @@ int __init io_apic_get_unique_id (int ioapic, int apic_id)
 			panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic);
 	}
 
-	printk(KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
+	apic_printk(APIC_VERBOSE, KERN_INFO
+			"IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
 
 	return apic_id;
 }
@@ -2400,19 +2515,12 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
 
 	entry.vector = assign_irq_vector(irq);
 
-	Dprintk(KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> "
-		"IRQ %d Mode:%i Active:%i)\n", ioapic, 
-		mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq, edge_level, active_high_low);
-
- 	if (use_pci_vector() && !platform_legacy_irq(irq))
-		irq = IO_APIC_VECTOR(irq);
-	if (edge_level) {
-		irq_desc[irq].handler = &ioapic_level_type;
-	} else {
-		irq_desc[irq].handler = &ioapic_edge_type;
-	}
+	apic_printk(APIC_DEBUG, KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry "
+		"(%d-%d -> 0x%x -> IRQ %d Mode:%i Active:%i)\n", ioapic,
+		mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq,
+		edge_level, active_high_low);
 
-	set_intr_gate(entry.vector, interrupt[irq]);
+	ioapic_register_intr(irq, entry.vector, edge_level);
 
 	if (!ioapic && (irq < 16))
 		disable_8259A_irq(irq);
diff --git a/arch/i386/kernel/ioport.c b/arch/i386/kernel/ioport.c
index 3346657c3..8b2516039 100644
--- a/arch/i386/kernel/ioport.c
+++ b/arch/i386/kernel/ioport.c
@@ -56,6 +56,7 @@ static void set_bitmap(unsigned long *bitmap, unsigned int base, unsigned int ex
  */
 asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
 {
+	unsigned long i, max_long, bytes, bytes_updated;
 	struct thread_struct * t = &current->thread;
 	struct tss_struct * tss;
 	unsigned long *bitmap;
@@ -81,16 +82,37 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
 
 	/*
 	 * do it in the per-thread copy and in the TSS ...
+	 *
+	 * Disable preemption via get_cpu() - we must not switch away
+	 * because the ->io_bitmap_max value must match the bitmap
+	 * contents:
 	 */
+	tss = &per_cpu(init_tss, get_cpu());
+
 	set_bitmap(t->io_bitmap_ptr, from, num, !turn_on);
-	tss = init_tss + get_cpu();
-	if (tss->io_bitmap_base == IO_BITMAP_OFFSET) { /* already active? */
-		set_bitmap(tss->io_bitmap, from, num, !turn_on);
-	} else {
-		memcpy(tss->io_bitmap, t->io_bitmap_ptr, IO_BITMAP_BYTES);
-		tss->io_bitmap_base = IO_BITMAP_OFFSET; /* Activate it in the TSS */
-	}
+
+	/*
+	 * Search for a (possibly new) maximum. This is simple and stupid,
+	 * to keep it obviously correct:
+	 */
+	max_long = 0;
+	for (i = 0; i < IO_BITMAP_LONGS; i++)
+		if (t->io_bitmap_ptr[i] != ~0UL)
+			max_long = i;
+
+	bytes = (max_long + 1) * sizeof(long);
+	bytes_updated = max(bytes, t->io_bitmap_max);
+
+	t->io_bitmap_max = bytes;
+
+	/*
+	 * Sets the lazy trigger so that the next I/O operation will
+	 * reload the correct bitmap.
+	 */
+	tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY;
+
 	put_cpu();
+
 	return 0;
 }
 
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index 355dc0eca..693b41afd 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -220,14 +220,16 @@ asmlinkage int handle_IRQ_event(unsigned int irq,
 		struct pt_regs *regs, struct irqaction *action)
 {
 	int status = 1;	/* Force the "do bottom halves" bit */
-	int retval = 0;
+	int ret, retval = 0;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
-		status |= action->flags;
-		retval |= action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
+		retval |= ret;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
@@ -1025,32 +1027,6 @@ static int irq_affinity_write_proc(struct file *file, const char __user *buffer,
 }
 
 #endif
-
-static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
-	if (count - len < 2)
-		return -EINVAL;
-	len += sprintf(page + len, "\n");
-	return len;
-}
-
-static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer,
-					unsigned long count, void *data)
-{
-	cpumask_t *mask = (cpumask_t *)data;
-	unsigned long full_count = count, err;
-	cpumask_t new_value;
-
-	err = cpumask_parse(buffer, count, new_value);
-	if (err)
-		return err;
-
-	*mask = new_value;
-	return full_count;
-}
-
 #define MAX_NAMELEN 10
 
 static void register_irq_proc (unsigned int irq)
@@ -1086,27 +1062,13 @@ static void register_irq_proc (unsigned int irq)
 #endif
 }
 
-unsigned long prof_cpu_mask = -1;
-
 void init_irq_proc (void)
 {
-	struct proc_dir_entry *entry;
 	int i;
 
 	/* create /proc/irq */
 	root_irq_dir = proc_mkdir("irq", NULL);
-
-	/* create /proc/irq/prof_cpu_mask */
-	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
-
-	if (!entry)
-	    return;
-
-	entry->nlink = 1;
-	entry->data = (void *)&prof_cpu_mask;
-	entry->read_proc = prof_cpu_mask_read_proc;
-	entry->write_proc = prof_cpu_mask_write_proc;
-
+	create_prof_cpu_mask(root_irq_dir);
 	/*
 	 * Create entries for all existing IRQs.
 	 */
diff --git a/arch/i386/kernel/ldt.c b/arch/i386/kernel/ldt.c
index 038d30034..bb50afbee 100644
--- a/arch/i386/kernel/ldt.c
+++ b/arch/i386/kernel/ldt.c
@@ -142,12 +142,17 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
 		err = -EFAULT;
 	up(&mm->context.sem);
 	if (err < 0)
-		return err;
+		goto error_return;
 	if (size != bytecount) {
 		/* zero-fill the rest */
-		clear_user(ptr+size, bytecount-size);
+		if (clear_user(ptr+size, bytecount-size) != 0) {
+			err = -EFAULT;
+			goto error_return;
+		}
 	}
 	return bytecount;
+error_return:
+	return err;
 }
 
 static int read_default_ldt(void __user * ptr, unsigned long bytecount)
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index 12ccd65bd..aca20edc5 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -485,6 +485,7 @@ static struct file_operations microcode_fops = {
 static struct miscdevice microcode_dev = {
 	.minor		= MICROCODE_MINOR,
 	.name		= "microcode",
+	.devfs_name	= "cpu/microcode",
 	.fops		= &microcode_fops,
 };
 
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index 16d91e3e1..c9dcd1f42 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -25,13 +25,17 @@
 #include <linux/module.h>
 #include <linux/nmi.h>
 #include <linux/sysdev.h>
+#include <linux/sysctl.h>
 
 #include <asm/smp.h>
 #include <asm/mtrr.h>
 #include <asm/mpspec.h>
 #include <asm/nmi.h>
 
+#include "mach_traps.h"
+
 unsigned int nmi_watchdog = NMI_NONE;
+extern int unknown_nmi_panic;
 static unsigned int nmi_hz = HZ;
 static unsigned int nmi_perfctr_msr;	/* the MSR to reset in NMI handler */
 static unsigned int nmi_p4_cccr_val;
@@ -376,7 +380,13 @@ static int setup_p4_watchdog(void)
 		clear_msr_range(0x3F1, 2);
 	/* MSR 0x3F0 seems to have a default value of 0xFC00, but current
 	   docs doesn't fully define it, so leave it alone for now. */
-	clear_msr_range(0x3A0, 31);
+	if (boot_cpu_data.x86_model >= 0x3) {
+		/* MSR_P4_IQ_ESCR0/1 (0x3ba/0x3bb) removed */
+		clear_msr_range(0x3A0, 26);
+		clear_msr_range(0x3BC, 3);
+	} else {
+		clear_msr_range(0x3A0, 31);
+	}
 	clear_msr_range(0x3C0, 6);
 	clear_msr_range(0x3C8, 6);
 	clear_msr_range(0x3E0, 2);
@@ -426,8 +436,6 @@ void setup_apic_nmi_watchdog (void)
 	nmi_active = 1;
 }
 
-static spinlock_t nmi_print_lock = SPIN_LOCK_UNLOCKED;
-
 /*
  * the best way to detect whether a CPU has a 'hard lockup' problem
  * is to check it's local APIC timer IRQ counts. If they are not
@@ -459,6 +467,8 @@ void touch_nmi_watchdog (void)
 		alert_counter[i] = 0;
 }
 
+extern void die_nmi(struct pt_regs *, const char *msg);
+
 void nmi_watchdog_tick (struct pt_regs * regs)
 {
 
@@ -477,21 +487,8 @@ void nmi_watchdog_tick (struct pt_regs * regs)
 		 * wait a few IRQs (5 seconds) before doing the oops ...
 		 */
 		alert_counter[cpu]++;
-		if (alert_counter[cpu] == 5*nmi_hz) {
-			spin_lock(&nmi_print_lock);
-			/*
-			 * We are in trouble anyway, lets at least try
-			 * to get a message out.
-			 */
-			bust_spinlocks(1);
-			printk("NMI Watchdog detected LOCKUP on CPU%d, eip %08lx, registers:\n", cpu, regs->eip);
-			show_registers(regs);
-			printk("console shuts up ...\n");
-			console_silent();
-			spin_unlock(&nmi_print_lock);
-			bust_spinlocks(0);
-			do_exit(SIGSEGV);
-		}
+		if (alert_counter[cpu] == 5*nmi_hz)
+			die_nmi(regs, "NMI Watchdog detected LOCKUP");
 	} else {
 		last_irq_sums[cpu] = sum;
 		alert_counter[cpu] = 0;
@@ -518,6 +515,49 @@ void nmi_watchdog_tick (struct pt_regs * regs)
 	}
 }
 
+#ifdef CONFIG_SYSCTL
+
+static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu)
+{
+	unsigned char reason = get_nmi_reason();
+	char buf[64];
+
+	if (!(reason & 0xc0)) {
+		sprintf(buf, "NMI received for unknown reason %02x\n", reason);
+		die_nmi(regs, buf);
+	}
+	return 0;
+}
+
+/*
+ * proc handler for /proc/sys/kernel/unknown_nmi_panic
+ */
+int proc_unknown_nmi_panic(ctl_table *table, int write, struct file *file,
+			void __user *buffer, size_t *length, loff_t *ppos)
+{
+	int old_state;
+
+	old_state = unknown_nmi_panic;
+	proc_dointvec(table, write, file, buffer, length, ppos);
+	if (!!old_state == !!unknown_nmi_panic)
+		return 0;
+
+	if (unknown_nmi_panic) {
+		if (reserve_lapic_nmi() < 0) {
+			unknown_nmi_panic = 0;
+			return -EBUSY;
+		} else {
+			set_nmi_callback(unknown_nmi_panic_callback);
+		}
+	} else {
+		release_lapic_nmi();
+		unset_nmi_callback();
+	}
+	return 0;
+}
+
+#endif
+
 EXPORT_SYMBOL(nmi_active);
 EXPORT_SYMBOL(nmi_watchdog);
 EXPORT_SYMBOL(reserve_lapic_nmi);
diff --git a/arch/i386/kernel/pci-dma.c b/arch/i386/kernel/pci-dma.c
index 10dc6b79d..982fe8c2b 100644
--- a/arch/i386/kernel/pci-dma.c
+++ b/arch/i386/kernel/pci-dma.c
@@ -13,17 +13,40 @@
 #include <linux/pci.h>
 #include <asm/io.h>
 
+struct dma_coherent_mem {
+	void		*virt_base;
+	u32		device_base;
+	int		size;
+	int		flags;
+	unsigned long	*bitmap;
+};
+
 void *dma_alloc_coherent(struct device *dev, size_t size,
 			   dma_addr_t *dma_handle, int gfp)
 {
 	void *ret;
+	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
+	int order = get_order(size);
 	/* ignore region specifiers */
 	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
 
+	if (mem) {
+		int page = bitmap_find_free_region(mem->bitmap, mem->size,
+						     order);
+		if (page >= 0) {
+			*dma_handle = mem->device_base + (page << PAGE_SHIFT);
+			ret = mem->virt_base + (page << PAGE_SHIFT);
+			memset(ret, 0, size);
+			return ret;
+		}
+		if (mem->flags & DMA_MEMORY_EXCLUSIVE)
+			return NULL;
+	}
+
 	if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
 		gfp |= GFP_DMA;
 
-	ret = (void *)__get_free_pages(gfp, get_order(size));
+	ret = (void *)__get_free_pages(gfp, order);
 
 	if (ret != NULL) {
 		memset(ret, 0, size);
@@ -35,5 +58,89 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
 void dma_free_coherent(struct device *dev, size_t size,
 			 void *vaddr, dma_addr_t dma_handle)
 {
-	free_pages((unsigned long)vaddr, get_order(size));
+	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
+	int order = get_order(size);
+	
+	if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) {
+		int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
+
+		bitmap_release_region(mem->bitmap, page, order);
+	} else
+		free_pages((unsigned long)vaddr, order);
+}
+
+int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+				dma_addr_t device_addr, size_t size, int flags)
+{
+	void __iomem *mem_base;
+	int pages = size >> PAGE_SHIFT;
+	int bitmap_size = (pages + 31)/32;
+
+	if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
+		goto out;
+	if (!size)
+		goto out;
+	if (dev->dma_mem)
+		goto out;
+
+	/* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
+
+	mem_base = ioremap(bus_addr, size);
+	if (!mem_base)
+		goto out;
+
+	dev->dma_mem = kmalloc(GFP_KERNEL, sizeof(struct dma_coherent_mem));
+	if (!dev->dma_mem)
+		goto out;
+	memset(dev->dma_mem, 0, sizeof(struct dma_coherent_mem));
+	dev->dma_mem->bitmap = kmalloc(GFP_KERNEL, bitmap_size);
+	if (!dev->dma_mem->bitmap)
+		goto free1_out;
+	memset(dev->dma_mem->bitmap, 0, bitmap_size);
+
+	dev->dma_mem->virt_base = mem_base;
+	dev->dma_mem->device_base = device_addr;
+	dev->dma_mem->size = pages;
+	dev->dma_mem->flags = flags;
+
+	if (flags & DMA_MEMORY_MAP)
+		return DMA_MEMORY_MAP;
+
+	return DMA_MEMORY_IO;
+
+ free1_out:
+	kfree(dev->dma_mem->bitmap);
+ out:
+	return 0;
+}
+EXPORT_SYMBOL(dma_declare_coherent_memory);
+
+void dma_release_declared_memory(struct device *dev)
+{
+	struct dma_coherent_mem *mem = dev->dma_mem;
+	
+	if(!mem)
+		return;
+	dev->dma_mem = NULL;
+	kfree(mem->bitmap);
+	kfree(mem);
+}
+EXPORT_SYMBOL(dma_release_declared_memory);
+
+void *dma_mark_declared_memory_occupied(struct device *dev,
+					dma_addr_t device_addr, size_t size)
+{
+	struct dma_coherent_mem *mem = dev->dma_mem;
+	int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	int pos, err;
+
+	if (!mem)
+		return ERR_PTR(-EINVAL);
+
+	pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
+	err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages));
+	if (err != 0)
+		return ERR_PTR(err);
+	return mem->virt_base + (pos << PAGE_SHIFT);
 }
+EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 75b200985..0095fa1dd 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -142,13 +142,21 @@ void cpu_idle (void)
 	/* endless idle loop with no priority at all */
 	while (1) {
 		while (!need_resched()) {
-			void (*idle)(void) = pm_idle;
+			void (*idle)(void);
+			/*
+			 * Mark this as an RCU critical section so that
+			 * synchronize_kernel() in the unload path waits
+			 * for our completion.
+			 */
+			rcu_read_lock();
+			idle = pm_idle;
 
 			if (!idle)
 				idle = default_idle;
 
 			irq_stat[smp_processor_id()].idle_timestamp = jiffies;
 			idle();
+			rcu_read_unlock();
 		}
 		schedule();
 	}
@@ -183,18 +191,13 @@ void __init select_idle_routine(const struct cpuinfo_x86 *c)
 		printk("monitor/mwait feature present.\n");
 		/*
 		 * Skip, if setup has overridden idle.
-		 * Also, take care of system with asymmetric CPUs.
-		 * Use, mwait_idle only if all cpus support it.
-		 * If not, we fallback to default_idle()
+		 * One CPU supports mwait => All CPUs supports mwait
 		 */
 		if (!pm_idle) {
 			printk("using mwait in idle threads.\n");
 			pm_idle = mwait_idle;
 		}
-		return;
 	}
-	pm_idle = default_idle;
-	return;
 }
 
 static int __init idle_setup (char *str)
@@ -294,13 +297,22 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 void exit_thread(void)
 {
 	struct task_struct *tsk = current;
+	struct thread_struct *t = &tsk->thread;
 
 	/* The process may have allocated an io port bitmap... nuke it. */
-	if (unlikely(NULL != tsk->thread.io_bitmap_ptr)) {
+	if (unlikely(NULL != t->io_bitmap_ptr)) {
 		int cpu = get_cpu();
-		struct tss_struct *tss = init_tss + cpu;
-		kfree(tsk->thread.io_bitmap_ptr);
-		tsk->thread.io_bitmap_ptr = NULL;
+		struct tss_struct *tss = &per_cpu(init_tss, cpu);
+
+		kfree(t->io_bitmap_ptr);
+		t->io_bitmap_ptr = NULL;
+		/*
+		 * Careful, clear this in the TSS too:
+		 */
+		memset(tss->io_bitmap, 0xff, tss->io_bitmap_max);
+		t->io_bitmap_max = 0;
+		tss->io_bitmap_owner = NULL;
+		tss->io_bitmap_max = 0;
 		tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
 		put_cpu();
 	}
@@ -369,8 +381,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
 	tsk = current;
 	if (unlikely(NULL != tsk->thread.io_bitmap_ptr)) {
 		p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
-		if (!p->thread.io_bitmap_ptr)
+		if (!p->thread.io_bitmap_ptr) {
+			p->thread.io_bitmap_max = 0;
 			return -ENOMEM;
+		}
 		memcpy(p->thread.io_bitmap_ptr, tsk->thread.io_bitmap_ptr,
 			IO_BITMAP_BYTES);
 	}
@@ -401,8 +415,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
 
 	err = 0;
  out:
-	if (err && p->thread.io_bitmap_ptr)
+	if (err && p->thread.io_bitmap_ptr) {
 		kfree(p->thread.io_bitmap_ptr);
+		p->thread.io_bitmap_max = 0;
+	}
 	return err;
 }
 
@@ -467,6 +483,37 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
 	return 1;
 }
 
+static inline void
+handle_io_bitmap(struct thread_struct *next, struct tss_struct *tss)
+{
+	if (!next->io_bitmap_ptr) {
+		/*
+		 * Disable the bitmap via an invalid offset. We still cache
+		 * the previous bitmap owner and the IO bitmap contents:
+		 */
+		tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
+		return;
+	}
+	if (likely(next == tss->io_bitmap_owner)) {
+		/*
+		 * Previous owner of the bitmap (hence the bitmap content)
+		 * matches the next task, we dont have to do anything but
+		 * to set a valid offset in the TSS:
+		 */
+		tss->io_bitmap_base = IO_BITMAP_OFFSET;
+		return;
+	}
+	/*
+	 * Lazy TSS's I/O bitmap copy. We set an invalid offset here
+	 * and we let the task to get a GPF in case an I/O instruction
+	 * is performed.  The handler of the GPF will verify that the
+	 * faulting task has a valid I/O bitmap and, it true, does the
+	 * real copy and restart the instruction.  This will save us
+	 * redundant copies when the currently switched task does not
+	 * perform any I/O during its timeslice.
+	 */
+	tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY;
+}
 /*
  * This special macro can be used to load a debugging register
  */
@@ -507,7 +554,7 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
 	struct thread_struct *prev = &prev_p->thread,
 				 *next = &next_p->thread;
 	int cpu = smp_processor_id();
-	struct tss_struct *tss = init_tss + cpu;
+	struct tss_struct *tss = &per_cpu(init_tss, cpu);
 
 	/* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
 
@@ -551,28 +598,9 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
 		loaddebug(next, 7);
 	}
 
-	if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) {
-		if (next->io_bitmap_ptr) {
-			/*
-			 * 4 cachelines copy ... not good, but not that
-			 * bad either. Anyone got something better?
-			 * This only affects processes which use ioperm().
-			 * [Putting the TSSs into 4k-tlb mapped regions
-			 * and playing VM tricks to switch the IO bitmap
-			 * is not really acceptable.]
-			 */
-			memcpy(tss->io_bitmap, next->io_bitmap_ptr,
-				IO_BITMAP_BYTES);
-			tss->io_bitmap_base = IO_BITMAP_OFFSET;
-		} else
-			/*
-			 * a bitmap offset pointing outside of the TSS limit
-			 * causes a nicely controllable SIGSEGV if a process
-			 * tries to use a port IO instruction. The first
-			 * sys_ioperm() call sets up the bitmap properly.
-			 */
-			tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
-	}
+	if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr))
+		handle_io_bitmap(next, tss);
+
 	return prev_p;
 }
 
@@ -593,7 +621,7 @@ asmlinkage int sys_clone(struct pt_regs regs)
 	child_tidptr = (int __user *)regs.edi;
 	if (!newsp)
 		newsp = regs.esp;
-	return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0, parent_tidptr, child_tidptr);
+	return do_fork(clone_flags, newsp, &regs, 0, parent_tidptr, child_tidptr);
 }
 
 /*
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index 6f3a62694..58a4f2f1d 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -147,6 +147,7 @@ void ptrace_disable(struct task_struct *child)
 { 
 	long tmp;
 
+	clear_tsk_thread_flag(child, TIF_SINGLESTEP);
 	tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
 	put_stack_long(child, EFL_OFFSET, tmp);
 }
@@ -372,6 +373,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 		else {
 			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 		}
+		clear_tsk_thread_flag(child, TIF_SINGLESTEP);
 		child->exit_code = data;
 	/* make sure the single step bit is not set. */
 		tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
@@ -393,6 +395,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 		if (child->state == TASK_ZOMBIE)	/* already dead */
 			break;
 		child->exit_code = SIGKILL;
+		clear_tsk_thread_flag(child, TIF_SINGLESTEP);
 		/* make sure the single step bit is not set. */
 		tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
 		put_stack_long(child, EFL_OFFSET, tmp);
@@ -413,6 +416,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 		}
 		tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG;
 		put_stack_long(child, EFL_OFFSET, tmp);
+		set_tsk_thread_flag(child, TIF_SINGLESTEP);
 		child->exit_code = data;
 		/* give it a chance to run. */
 		wake_up_process(child);
@@ -537,14 +541,15 @@ void do_syscall_trace(struct pt_regs *regs, int entryexit)
 			audit_syscall_exit(current, regs->eax);
 	}
 
-	if (!test_thread_flag(TIF_SYSCALL_TRACE))
+	if (!test_thread_flag(TIF_SYSCALL_TRACE) &&
+	    !test_thread_flag(TIF_SINGLESTEP))
 		return;
 	if (!(current->ptrace & PT_PTRACED))
 		return;
 	/* the 0x80 provides a way for the tracing parent to distinguish
 	   between a syscall stop and SIGTRAP delivery */
-	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-				 ? 0x80 : 0));
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) &&
+				 !test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0));
 
 	/*
 	 * this isn't the same as continuing with a signal, but it will do
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 375fd0761..19827c0c5 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -49,6 +49,7 @@
 #include <asm/ist.h>
 #include <asm/io.h>
 #include "setup_arch_pre.h"
+#include <bios_ebda.h>
 
 /* This value is set up by the early boot code to point to the value
    immediately after the boot time page tables.  It contains a *physical*
@@ -218,9 +219,14 @@ static struct resource standard_io_resources[] = { {
 	.end	= 0x0021,
 	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
 }, {
-	.name	= "timer",
+	.name   = "timer0",
 	.start	= 0x0040,
-	.end	= 0x005f,
+	.end    = 0x0043,
+	.flags  = IORESOURCE_BUSY | IORESOURCE_IO
+}, {
+	.name   = "timer1",
+	.start  = 0x0050,
+	.end    = 0x0053,
 	.flags	= IORESOURCE_BUSY | IORESOURCE_IO
 }, {
 	.name	= "keyboard",
@@ -809,6 +815,14 @@ static void __init parse_cmdline_early (char ** cmdline_p)
 		if (c == ' ' && !memcmp(from, "highmem=", 8))
 			highmem_pages = memparse(from+8, &from) >> PAGE_SHIFT;
 	
+		/*
+		 * vmalloc=size forces the vmalloc area to be exactly 'size'
+		 * bytes. This can be used to increase (or decrease) the
+		 * vmalloc area - the default is 128m.
+		 */
+		if (c == ' ' && !memcmp(from, "vmalloc=", 8))
+			__VMALLOC_RESERVE = memparse(from+8, &from);
+
 		c = *(from++);
 		if (!c)
 			break;
@@ -991,6 +1005,17 @@ static void __init register_bootmem_low_pages(unsigned long max_low_pfn)
 	}
 }
 
+/*
+ * workaround for Dell systems that neglect to reserve EBDA
+ */
+static void __init reserve_ebda_region(void)
+{
+	unsigned int addr;
+	addr = get_bios_ebda();
+	if (addr)
+		reserve_bootmem(addr, PAGE_SIZE);	
+}
+
 static unsigned long __init setup_memory(void)
 {
 	unsigned long bootmap_size, start_pfn, max_low_pfn;
@@ -1037,6 +1062,9 @@ static unsigned long __init setup_memory(void)
 	 */
 	reserve_bootmem(0, PAGE_SIZE);
 
+	/* reserve EBDA region, it's a 4K region */
+	reserve_ebda_region();
+
     /* could be an AMD 768MPX chipset. Reserve a page  before VGA to prevent
        PCI prefetch into it (errata #56). Usually the page is reserved anyways,
        unless you have no PS/2 mouse plugged in. */
@@ -1335,7 +1363,12 @@ void __init setup_arch(char **cmdline_p)
 
 	/*
 	 * NOTE: before this point _nobody_ is allowed to allocate
-	 * any memory using the bootmem allocator.
+	 * any memory using the bootmem allocator.  Although the
+	 * alloctor is now initialised only the first 8Mb of the kernel
+	 * virtual address space has been mapped.  All allocations before
+	 * paging_init() has completed must use the alloc_bootmem_low_pages()
+	 * variant (which allocates DMA'able memory) and care must be taken
+	 * not to exceed the 8Mb limit.
 	 */
 
 #ifdef CONFIG_SMP
@@ -1343,6 +1376,10 @@ void __init setup_arch(char **cmdline_p)
 #endif
 	paging_init();
 
+	/*
+	 * NOTE: at this point the bootmem allocator is fully available.
+	 */
+
 #ifdef CONFIG_EARLY_PRINTK
 	{
 		char *s = strstr(*cmdline_p, "earlyprintk=");
diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
index 57e88b625..a9b33b1e9 100644
--- a/arch/i386/kernel/signal.c
+++ b/arch/i386/kernel/signal.c
@@ -19,6 +19,7 @@
 #include <linux/stddef.h>
 #include <linux/personality.h>
 #include <linux/suspend.h>
+#include <linux/ptrace.h>
 #include <linux/elf.h>
 #include <asm/processor.h>
 #include <asm/ucontext.h>
@@ -269,6 +270,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate,
 		 struct pt_regs *regs, unsigned long mask)
 {
 	int tmp, err = 0;
+	unsigned long eflags;
 
 	tmp = 0;
 	__asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
@@ -290,7 +292,11 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate,
 	err |= __put_user(current->thread.error_code, &sc->err);
 	err |= __put_user(regs->eip, &sc->eip);
 	err |= __put_user(regs->xcs, (unsigned int __user *)&sc->cs);
-	err |= __put_user(regs->eflags, &sc->eflags);
+	eflags = regs->eflags;
+	if (current->ptrace & PT_PTRACED) {
+		eflags &= ~TF_MASK;
+	}
+	err |= __put_user(eflags, &sc->eflags);
 	err |= __put_user(regs->esp, &sc->esp_at_signal);
 	err |= __put_user(regs->xss, (unsigned int __user *)&sc->ss);
 
@@ -345,18 +351,20 @@ static void setup_frame(int sig, struct k_sigaction *ka,
 	void __user *restorer;
 	struct sigframe __user *frame;
 	int err = 0;
+	int usig;
 
 	frame = get_sigframe(ka, regs, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		goto give_sigsegv;
 
-	err |= __put_user((current_thread_info()->exec_domain
-		           && current_thread_info()->exec_domain->signal_invmap
-		           && sig < 32
-		           ? current_thread_info()->exec_domain->signal_invmap[sig]
-		           : sig),
-		          &frame->sig);
+	usig = current_thread_info()->exec_domain
+		&& current_thread_info()->exec_domain->signal_invmap
+		&& sig < 32
+		? current_thread_info()->exec_domain->signal_invmap[sig]
+		: sig;
+
+	err |= __put_user(usig, &frame->sig);
 	if (err)
 		goto give_sigsegv;
 
@@ -395,13 +403,22 @@ static void setup_frame(int sig, struct k_sigaction *ka,
 	/* Set up registers for signal handler */
 	regs->esp = (unsigned long) frame;
 	regs->eip = (unsigned long) ka->sa.sa_handler;
+	regs->eax = (unsigned long) sig;
+	regs->edx = (unsigned long) 0;
+	regs->ecx = (unsigned long) 0;
 
 	set_fs(USER_DS);
 	regs->xds = __USER_DS;
 	regs->xes = __USER_DS;
 	regs->xss = __USER_DS;
 	regs->xcs = __USER_CS;
-	regs->eflags &= ~TF_MASK;
+	if (regs->eflags & TF_MASK) {
+		if (current->ptrace & PT_PTRACED) {
+			ptrace_notify(SIGTRAP);
+		} else {
+			regs->eflags &= ~TF_MASK;
+		}
+	}
 
 #if DEBUG_SIG
 	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
@@ -411,9 +428,7 @@ static void setup_frame(int sig, struct k_sigaction *ka,
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -422,18 +437,20 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	void __user *restorer;
 	struct rt_sigframe __user *frame;
 	int err = 0;
+	int usig;
 
 	frame = get_sigframe(ka, regs, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		goto give_sigsegv;
 
-	err |= __put_user((current_thread_info()->exec_domain
-		    	   && current_thread_info()->exec_domain->signal_invmap
-		    	   && sig < 32
-		    	   ? current_thread_info()->exec_domain->signal_invmap[sig]
-			   : sig),
-			  &frame->sig);
+	usig = current_thread_info()->exec_domain
+		&& current_thread_info()->exec_domain->signal_invmap
+		&& sig < 32
+		? current_thread_info()->exec_domain->signal_invmap[sig]
+		: sig;
+
+	err |= __put_user(usig, &frame->sig);
 	err |= __put_user(&frame->info, &frame->pinfo);
 	err |= __put_user(&frame->uc, &frame->puc);
 	err |= copy_siginfo_to_user(&frame->info, info);
@@ -476,13 +493,22 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	/* Set up registers for signal handler */
 	regs->esp = (unsigned long) frame;
 	regs->eip = (unsigned long) ka->sa.sa_handler;
+	regs->eax = (unsigned long) usig;
+	regs->edx = (unsigned long) &frame->info;
+	regs->ecx = (unsigned long) &frame->uc;
 
 	set_fs(USER_DS);
 	regs->xds = __USER_DS;
 	regs->xes = __USER_DS;
 	regs->xss = __USER_DS;
 	regs->xcs = __USER_CS;
-	regs->eflags &= ~TF_MASK;
+	if (regs->eflags & TF_MASK) {
+		if (current->ptrace & PT_PTRACED) {
+			ptrace_notify(SIGTRAP);
+		} else {
+			regs->eflags &= ~TF_MASK;
+		}
+	}
 
 #if DEBUG_SIG
 	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
@@ -492,9 +518,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 /*
@@ -502,11 +526,9 @@ give_sigsegv:
  */	
 
 static void
-handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
-	struct pt_regs * regs)
+handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
+	      sigset_t *oldset,	struct pt_regs * regs)
 {
-	struct k_sigaction *ka = &current->sighand->action[sig-1];
-
 	/* Are we from a system call? */
 	if (regs->orig_eax >= 0) {
 		/* If so, check system call restarting.. */
@@ -534,9 +556,6 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
 	else
 		setup_frame(sig, ka, oldset, regs);
 
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
-
 	if (!(ka->sa.sa_flags & SA_NODEFER)) {
 		spin_lock_irq(&current->sighand->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -555,6 +574,7 @@ int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset)
 {
 	siginfo_t info;
 	int signr;
+	struct k_sigaction ka;
 
 	/*
 	 * We want the common case to go fast, which
@@ -573,7 +593,7 @@ int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset)
 	if (!oldset)
 		oldset = &current->blocked;
 
-	signr = get_signal_to_deliver(&info, regs, NULL);
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
 		/* Reenable any watchpoints before delivering the
 		 * signal to user space. The processor register will
@@ -583,7 +603,7 @@ int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset)
 		__asm__("movl %0,%%db7"	: : "r" (current->thread.debugreg[7]));
 
 		/* Whee!  Actually deliver the signal.  */
-		handle_signal(signr, &info, oldset, regs);
+		handle_signal(signr, &info, &ka, oldset, regs);
 		return 1;
 	}
 
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index bb5960134..cf6ddbcf9 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -22,7 +22,6 @@
 
 #include <asm/mtrr.h>
 #include <asm/tlbflush.h>
-#include <mach_ipi.h>
 #include <mach_apic.h>
 
 /*
@@ -104,7 +103,7 @@
  *	about nothing of note with C stepping upwards.
  */
 
-struct tlb_state cpu_tlbstate[NR_CPUS] __cacheline_aligned = {[0 ... NR_CPUS-1] = { &init_mm, 0, }};
+DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0, };
 
 /*
  * the following functions deal with sending IPIs between CPUs.
@@ -122,7 +121,7 @@ static inline int __prepare_ICR2 (unsigned int mask)
 	return SET_APIC_DEST_FIELD(mask);
 }
 
-inline void __send_IPI_shortcut(unsigned int shortcut, int vector)
+void __send_IPI_shortcut(unsigned int shortcut, int vector)
 {
 	/*
 	 * Subtle. In the case of the 'never do double writes' workaround
@@ -157,7 +156,7 @@ void fastcall send_IPI_self(int vector)
 /*
  * This is only used on smaller machines.
  */
-inline void send_IPI_mask_bitmask(cpumask_t cpumask, int vector)
+void send_IPI_mask_bitmask(cpumask_t cpumask, int vector)
 {
 	unsigned long mask = cpus_addr(cpumask)[0];
 	unsigned long cfg;
@@ -230,6 +229,8 @@ inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
 	local_irq_restore(flags);
 }
 
+#include <mach_ipi.h> /* must come after the send_IPI functions above for inlining */
+
 /*
  *	Smarter SMP flushing macros. 
  *		c/o Linus Torvalds.
@@ -255,9 +256,9 @@ static spinlock_t tlbstate_lock = SPIN_LOCK_UNLOCKED;
  */
 static inline void leave_mm (unsigned long cpu)
 {
-	if (cpu_tlbstate[cpu].state == TLBSTATE_OK)
+	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK)
 		BUG();
-	cpu_clear(cpu, cpu_tlbstate[cpu].active_mm->cpu_vm_mask);
+	cpu_clear(cpu, per_cpu(cpu_tlbstate, cpu).active_mm->cpu_vm_mask);
 	load_cr3(swapper_pg_dir);
 }
 
@@ -324,8 +325,8 @@ asmlinkage void smp_invalidate_interrupt (void)
 		 * BUG();
 		 */
 		 
-	if (flush_mm == cpu_tlbstate[cpu].active_mm) {
-		if (cpu_tlbstate[cpu].state == TLBSTATE_OK) {
+	if (flush_mm == per_cpu(cpu_tlbstate, cpu).active_mm) {
+		if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) {
 			if (flush_va == FLUSH_ALL)
 				local_flush_tlb();
 			else
@@ -457,7 +458,7 @@ static void do_flush_tlb_all(void* info)
 	unsigned long cpu = smp_processor_id();
 
 	__flush_tlb_all();
-	if (cpu_tlbstate[cpu].state == TLBSTATE_LAZY)
+	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_LAZY)
 		leave_mm(cpu);
 }
 
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 1a9b08190..016a07067 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -17,7 +17,7 @@
  *	Fixes
  *		Felix Koop	:	NR_CPUS used properly
  *		Jose Renau	:	Handle single CPU case.
- *		Alan Cox	:	By repeated request 8) - Total BogoMIP report.
+ *		Alan Cox	:	By repeated request 8) - Total BogoMIPS report.
  *		Greg Wright	:	Fix for kernel stacks panic.
  *		Erich Boleyn	:	MP v1.4 and additional changes.
  *	Matthias Sattler	:	Changes for 2.1 kernel map.
@@ -72,6 +72,10 @@ static cpumask_t smp_commenced_mask;
 /* Per CPU bogomips and other parameters */
 struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
 
+u8 x86_cpu_to_apicid[NR_CPUS] =
+			{ [0 ... NR_CPUS-1] = 0xff };
+EXPORT_SYMBOL(x86_cpu_to_apicid);
+
 /* Set when the idlers are all forked */
 int smp_threads_ready;
 
@@ -187,34 +191,6 @@ static unsigned long long tsc_values[NR_CPUS];
 
 #define NR_LOOPS 5
 
-/*
- * accurate 64-bit/32-bit division, expanded to 32-bit divisions and 64-bit
- * multiplication. Not terribly optimized but we need it at boot time only
- * anyway.
- *
- * result == a / b
- *	== (a1 + a2*(2^32)) / b
- *	== a1/b + a2*(2^32/b)
- *	== a1/b + a2*((2^32-1)/b) + a2/b + (a2*((2^32-1) % b))/b
- *		    ^---- (this multiplication can overflow)
- */
-
-static unsigned long long __init div64 (unsigned long long a, unsigned long b0)
-{
-	unsigned int a1, a2;
-	unsigned long long res;
-
-	a1 = ((unsigned int*)&a)[0];
-	a2 = ((unsigned int*)&a)[1];
-
-	res = a1/b0 +
-		(unsigned long long)a2 * (unsigned long long)(0xffffffff/b0) +
-		a2 / b0 +
-		(a2 * (0xffffffff % b0)) / b0;
-
-	return res;
-}
-
 static void __init synchronize_tsc_bp (void)
 {
 	int i;
@@ -224,7 +200,7 @@ static void __init synchronize_tsc_bp (void)
 	unsigned long one_usec;
 	int buggy = 0;
 
-	printk("checking TSC synchronization across %u CPUs: ", num_booting_cpus());
+	printk(KERN_INFO "checking TSC synchronization across %u CPUs: ", num_booting_cpus());
 
 	/* convert from kcyc/sec to cyc/usec */
 	one_usec = cpu_khz / 1000;
@@ -279,7 +255,8 @@ static void __init synchronize_tsc_bp (void)
 			sum += t0;
 		}
 	}
-	avg = div64(sum, num_booting_cpus());
+	avg = sum;
+	do_div(avg, num_booting_cpus());
 
 	sum = 0;
 	for (i = 0; i < NR_CPUS; i++) {
@@ -297,18 +274,18 @@ static void __init synchronize_tsc_bp (void)
 				buggy = 1;
 				printk("\n");
 			}
-			realdelta = div64(delta, one_usec);
+			realdelta = delta;
+			do_div(realdelta, one_usec);
 			if (tsc_values[i] < avg)
 				realdelta = -realdelta;
 
-			printk("BIOS BUG: CPU#%d improperly initialized, has %ld usecs TSC skew! FIXED.\n", i, realdelta);
+			printk(KERN_INFO "CPU#%d had %ld usecs TSC skew, fixed it up.\n", i, realdelta);
 		}
 
 		sum += delta;
 	}
 	if (!buggy)
 		printk("passed.\n");
-		;
 }
 
 static void __init synchronize_tsc_ap (void)
@@ -492,16 +469,6 @@ extern struct {
 	unsigned short ss;
 } stack_start;
 
-static struct task_struct * __init fork_by_hand(void)
-{
-	struct pt_regs regs;
-	/*
-	 * don't care about the eip and regs settings since
-	 * we'll never reschedule the forked task.
-	 */
-	return copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
-}
-
 #ifdef CONFIG_NUMA
 
 /* which logical CPUs are on which nodes */
@@ -797,21 +764,10 @@ static int __init do_boot_cpu(int apicid)
 	 * We can't use kernel_thread since we must avoid to
 	 * reschedule the child.
 	 */
-	idle = fork_by_hand();
+	idle = fork_idle(cpu);
 	if (IS_ERR(idle))
 		panic("failed fork for CPU %d", cpu);
-	wake_up_forked_process(idle);
-
-	/*
-	 * We remove it from the pidhash and the runqueue
-	 * once we got the process:
-	 */
-	init_idle(idle, cpu);
-
 	idle->thread.eip = (unsigned long) start_secondary;
-
-	unhash_process(idle);
-
 	/* start_eip had better be page-aligned! */
 	start_eip = setup_trampoline();
 
@@ -875,6 +831,7 @@ static int __init do_boot_cpu(int apicid)
 			inquire_remote_apic(apicid);
 		}
 	}
+	x86_cpu_to_apicid[cpu] = apicid;
 	if (boot_error) {
 		/* Try to put things back the way they were before ... */
 		unmap_cpu_to_logical_apicid(cpu);
@@ -957,6 +914,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
 
 	boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
 	boot_cpu_logical_apicid = logical_smp_processor_id();
+	x86_cpu_to_apicid[0] = boot_cpu_physical_apicid;
 
 	current_thread_info()->cpu = 0;
 	smp_tune_scheduling();
@@ -1132,213 +1090,6 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
 		synchronize_tsc_bp();
 }
 
-#ifdef CONFIG_SCHED_SMT
-#ifdef CONFIG_NUMA
-static struct sched_group sched_group_cpus[NR_CPUS];
-static struct sched_group sched_group_phys[NR_CPUS];
-static struct sched_group sched_group_nodes[MAX_NUMNODES];
-static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
-static DEFINE_PER_CPU(struct sched_domain, phys_domains);
-static DEFINE_PER_CPU(struct sched_domain, node_domains);
-__init void arch_init_sched_domains(void)
-{
-	int i;
-	struct sched_group *first = NULL, *last = NULL;
-
-	/* Set up domains */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		struct sched_domain *phys_domain = &per_cpu(phys_domains, i);
-		struct sched_domain *node_domain = &per_cpu(node_domains, i);
-		int node = cpu_to_node(i);
-		cpumask_t nodemask = node_to_cpumask(node);
-
-		*cpu_domain = SD_SIBLING_INIT;
-		cpu_domain->span = cpu_sibling_map[i];
-		cpu_domain->parent = phys_domain;
-		cpu_domain->groups = &sched_group_cpus[i];
-
-		*phys_domain = SD_CPU_INIT;
-		phys_domain->span = nodemask;
-		phys_domain->parent = node_domain;
-		phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)];
-
-		*node_domain = SD_NODE_INIT;
-		node_domain->span = cpu_possible_map;
-		node_domain->groups = &sched_group_nodes[cpu_to_node(i)];
-	}
-
-	/* Set up CPU (sibling) groups */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		int j;
-		first = last = NULL;
-
-		if (i != first_cpu(cpu_domain->span))
-			continue;
-
-		for_each_cpu_mask(j, cpu_domain->span) {
-			struct sched_group *cpu = &sched_group_cpus[j];
-
-			cpu->cpumask = CPU_MASK_NONE;
-			cpu_set(j, cpu->cpumask);
-			cpu->cpu_power = SCHED_LOAD_SCALE;
-
-			if (!first)
-				first = cpu;
-			if (last)
-				last->next = cpu;
-			last = cpu;
-		}
-		last->next = first;
-	}
-
-	for (i = 0; i < MAX_NUMNODES; i++) {
-		int j;
-		cpumask_t nodemask;
-		struct sched_group *node = &sched_group_nodes[i];
-		cpumask_t node_cpumask = node_to_cpumask(i);
-
-		cpus_and(nodemask, node_cpumask, cpu_possible_map);
-
-		if (cpus_empty(nodemask))
-			continue;
-
-		first = last = NULL;
-		/* Set up physical groups */
-		for_each_cpu_mask(j, nodemask) {
-			struct sched_domain *cpu_domain = &per_cpu(cpu_domains, j);
-			struct sched_group *cpu = &sched_group_phys[j];
-
-			if (j != first_cpu(cpu_domain->span))
-				continue;
-
-			cpu->cpumask = cpu_domain->span;
-			/*
-			 * Make each extra sibling increase power by 10% of
-			 * the basic CPU. This is very arbitrary.
-			 */
-			cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10;
-			node->cpu_power += cpu->cpu_power;
-
-			if (!first)
-				first = cpu;
-			if (last)
-				last->next = cpu;
-			last = cpu;
-		}
-		last->next = first;
-	}
-
-	/* Set up nodes */
-	first = last = NULL;
-	for (i = 0; i < MAX_NUMNODES; i++) {
-		struct sched_group *cpu = &sched_group_nodes[i];
-		cpumask_t nodemask;
-		cpumask_t node_cpumask = node_to_cpumask(i);
-
-		cpus_and(nodemask, node_cpumask, cpu_possible_map);
-
-		if (cpus_empty(nodemask))
-			continue;
-
-		cpu->cpumask = nodemask;
-		/* ->cpu_power already setup */
-
-		if (!first)
-			first = cpu;
-		if (last)
-			last->next = cpu;
-		last = cpu;
-	}
-	last->next = first;
-
-	mb();
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		cpu_attach_domain(cpu_domain, i);
-	}
-}
-#else /* !CONFIG_NUMA */
-static struct sched_group sched_group_cpus[NR_CPUS];
-static struct sched_group sched_group_phys[NR_CPUS];
-static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
-static DEFINE_PER_CPU(struct sched_domain, phys_domains);
-__init void arch_init_sched_domains(void)
-{
-	int i;
-	struct sched_group *first = NULL, *last = NULL;
-
-	/* Set up domains */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		struct sched_domain *phys_domain = &per_cpu(phys_domains, i);
-
-		*cpu_domain = SD_SIBLING_INIT;
-		cpu_domain->span = cpu_sibling_map[i];
-		cpu_domain->parent = phys_domain;
-		cpu_domain->groups = &sched_group_cpus[i];
-
-		*phys_domain = SD_CPU_INIT;
-		phys_domain->span = cpu_possible_map;
-		phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)];
-	}
-
-	/* Set up CPU (sibling) groups */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		int j;
-		first = last = NULL;
-
-		if (i != first_cpu(cpu_domain->span))
-			continue;
-
-		for_each_cpu_mask(j, cpu_domain->span) {
-			struct sched_group *cpu = &sched_group_cpus[j];
-
-			cpus_clear(cpu->cpumask);
-			cpu_set(j, cpu->cpumask);
-			cpu->cpu_power = SCHED_LOAD_SCALE;
-
-			if (!first)
-				first = cpu;
-			if (last)
-				last->next = cpu;
-			last = cpu;
-		}
-		last->next = first;
-	}
-
-	first = last = NULL;
-	/* Set up physical groups */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		struct sched_group *cpu = &sched_group_phys[i];
-
-		if (i != first_cpu(cpu_domain->span))
-			continue;
-
-		cpu->cpumask = cpu_domain->span;
-		/* See SMT+NUMA setup for comment */
-		cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10;
-
-		if (!first)
-			first = cpu;
-		if (last)
-			last->next = cpu;
-		last = cpu;
-	}
-	last->next = first;
-
-	mb();
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		cpu_attach_domain(cpu_domain, i);
-	}
-}
-#endif /* CONFIG_NUMA */
-#endif /* CONFIG_SCHED_SMT */
-
 /* These are wrappers to interface to the new boot process.  Someone
    who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */
 void __init smp_prepare_cpus(unsigned int max_cpus)
diff --git a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c
index 0daa404f5..960d8bd13 100644
--- a/arch/i386/kernel/sysenter.c
+++ b/arch/i386/kernel/sysenter.c
@@ -24,7 +24,7 @@ extern asmlinkage void sysenter_entry(void);
 void enable_sep_cpu(void *info)
 {
 	int cpu = get_cpu();
-	struct tss_struct *tss = init_tss + cpu;
+	struct tss_struct *tss = &per_cpu(init_tss, cpu);
 
 	tss->ss1 = __KERNEL_CS;
 	tss->esp1 = sizeof(struct tss_struct) + (unsigned long) tss;
@@ -43,18 +43,18 @@ extern const char vsyscall_sysenter_start, vsyscall_sysenter_end;
 
 static int __init sysenter_setup(void)
 {
-	unsigned long page = get_zeroed_page(GFP_ATOMIC);
+	void *page = (void *)get_zeroed_page(GFP_ATOMIC);
 
 	__set_fixmap(FIX_VSYSCALL, __pa(page), PAGE_READONLY_EXEC);
 
 	if (!boot_cpu_has(X86_FEATURE_SEP)) {
-		memcpy((void *) page,
+		memcpy(page,
 		       &vsyscall_int80_start,
 		       &vsyscall_int80_end - &vsyscall_int80_start);
 		return 0;
 	}
 
-	memcpy((void *) page,
+	memcpy(page,
 	       &vsyscall_sysenter_start,
 	       &vsyscall_sysenter_end - &vsyscall_sysenter_start);
 
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index f8dcf5d68..a9711fc35 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -200,6 +200,18 @@ unsigned long long monotonic_clock(void)
 }
 EXPORT_SYMBOL(monotonic_clock);
 
+#if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER)
+unsigned long profile_pc(struct pt_regs *regs)
+{
+	unsigned long pc = instruction_pointer(regs);
+
+	if (in_lock_functions(pc))
+		return *(unsigned long *)(regs->ebp + 4);
+
+	return pc;
+}
+EXPORT_SYMBOL(profile_pc);
+#endif
 
 /*
  * timer_interrupt() needs to keep up the real-time clock,
@@ -321,11 +333,12 @@ static int time_suspend(struct sys_device *dev, u32 state)
 
 static int time_resume(struct sys_device *dev)
 {
+	unsigned long flags;
 	unsigned long sec = get_cmos_time() + clock_cmos_diff;
-	write_seqlock_irq(&xtime_lock);
+	write_seqlock_irqsave(&xtime_lock, flags);
 	xtime.tv_sec = sec;
 	xtime.tv_nsec = 0;
-	write_sequnlock_irq(&xtime_lock);
+	write_sequnlock_irqrestore(&xtime_lock, flags);
 	return 0;
 }
 
diff --git a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c
index 0ec677d9e..52fc52661 100644
--- a/arch/i386/kernel/time_hpet.c
+++ b/arch/i386/kernel/time_hpet.c
@@ -29,7 +29,7 @@ unsigned long hpet_address;	/* hpet memory map physical address */
 
 static int use_hpet; 		/* can be used for runtime check of hpet */
 static int boot_hpet_disable; 	/* boottime override for HPET timer */
-static unsigned long hpet_virt_address;	/* hpet kernel virtual address */
+static void __iomem * hpet_virt_address;	/* hpet kernel virtual address */
 
 #define FSEC_TO_USEC (1000000000UL)
 
@@ -76,8 +76,7 @@ int __init hpet_enable(void)
 	if (!hpet_address) {
 		return -1;
 	}
-	hpet_virt_address = (unsigned long) ioremap_nocache(hpet_address,
-	                                                    HPET_MMAP_SIZE);
+	hpet_virt_address = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
 	/*
 	 * Read the period, compute tick and quotient.
 	 */
@@ -162,11 +161,11 @@ int __init hpet_enable(void)
 		hd.hd_irq[0] = HPET_LEGACY_8254;
 		hd.hd_irq[1] = HPET_LEGACY_RTC;
 		if (ntimer > 2) {
-			struct hpet		*hpet;
-			struct hpet_timer	*timer;
+			struct hpet __iomem	*hpet;
+			struct hpet_timer __iomem *timer;
 			int			i;
 
-			hpet = (struct hpet *) hpet_virt_address;
+			hpet = hpet_virt_address;
 
 			for (i = 2, timer = &hpet->hpet_timers[2]; i < ntimer;
 				timer++, i++)
diff --git a/arch/i386/kernel/timers/timer_pit.c b/arch/i386/kernel/timers/timer_pit.c
index 7ddbf1c76..a433cb046 100644
--- a/arch/i386/kernel/timers/timer_pit.c
+++ b/arch/i386/kernel/timers/timer_pit.c
@@ -7,6 +7,9 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/irq.h>
+#include <linux/sysdev.h>
+#include <linux/timex.h>
+#include <asm/delay.h>
 #include <asm/mpspec.h>
 #include <asm/timer.h>
 #include <asm/smp.h>
@@ -156,3 +159,44 @@ struct timer_opts timer_pit = {
 	.monotonic_clock = monotonic_clock_pit,
 	.delay = delay_pit,
 };
+
+void setup_pit_timer(void)
+{
+	extern spinlock_t i8253_lock;
+	unsigned long flags;
+
+	spin_lock_irqsave(&i8253_lock, flags);
+	outb_p(0x34,PIT_MODE);		/* binary, mode 2, LSB/MSB, ch 0 */
+	udelay(10);
+	outb_p(LATCH & 0xff , PIT_CH0);	/* LSB */
+	udelay(10);
+	outb(LATCH >> 8 , PIT_CH0);	/* MSB */
+	spin_unlock_irqrestore(&i8253_lock, flags);
+}
+
+static int timer_resume(struct sys_device *dev)
+{
+	setup_pit_timer();
+	return 0;
+}
+
+static struct sysdev_class timer_sysclass = {
+	set_kset_name("timer"),
+	.resume	= timer_resume,
+};
+
+static struct sys_device device_timer = {
+	.id	= 0,
+	.cls	= &timer_sysclass,
+};
+
+static int __init init_timer_sysfs(void)
+{
+	int error = sysdev_class_register(&timer_sysclass);
+	if (!error)
+		error = sysdev_register(&device_timer);
+	return error;
+}
+
+device_initcall(init_timer_sysfs);
+
diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
index a1e3f6f96..34e9b8eba 100644
--- a/arch/i386/kernel/timers/timer_tsc.c
+++ b/arch/i386/kernel/timers/timer_tsc.c
@@ -265,7 +265,8 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
 {
 	struct cpufreq_freqs *freq = data;
 
-	write_seqlock_irq(&xtime_lock);
+	if (val != CPUFREQ_RESUMECHANGE)
+		write_seqlock_irq(&xtime_lock);
 	if (!ref_freq) {
 		ref_freq = freq->old;
 		loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy;
@@ -291,7 +292,9 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
 		}
 #endif
 	}
-	write_sequnlock_irq(&xtime_lock);
+
+	if (val != CPUFREQ_RESUMECHANGE)
+		write_sequnlock_irq(&xtime_lock);
 
 	return 0;
 }
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index a3daea013..e8889024f 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -26,6 +26,7 @@
 #include <linux/kallsyms.h>
 #include <linux/ptrace.h>
 #include <linux/version.h>
+#include <linux/kprobes.h>
 
 #ifdef CONFIG_EISA
 #include <linux/ioport.h>
@@ -48,6 +49,7 @@
 
 #include <asm/smp.h>
 #include <asm/arch_hooks.h>
+#include <asm/kdebug.h>
 
 #include <linux/irq.h>
 #include <linux/module.h>
@@ -92,6 +94,18 @@ asmlinkage void spurious_interrupt_bug(void);
 asmlinkage void machine_check(void);
 
 static int kstack_depth_to_print = 24;
+struct notifier_block *i386die_chain;
+static spinlock_t die_notifier_lock = SPIN_LOCK_UNLOCKED;
+
+int register_die_notifier(struct notifier_block *nb)
+{
+	int err = 0;
+	unsigned long flags;
+	spin_lock_irqsave(&die_notifier_lock, flags);
+	err = notifier_chain_register(&i386die_chain, nb);
+	spin_unlock_irqrestore(&die_notifier_lock, flags);
+	return err;
+}
 
 static int valid_stack_ptr(struct task_struct *task, void *p)
 {
@@ -216,7 +230,7 @@ void show_registers(struct pt_regs *regs)
 		ss = regs->xss & 0xffff;
 	}
 	print_modules();
-	printk("CPU:    %d\nEIP:    %04x:[<%08lx>]    %s\nEFLAGS: %08lx"
+	printk("CPU:    %d\nEIP:    %04x:[<%08lx>]    %s VLI\nEFLAGS: %08lx"
 			"   (%s) \n",
 		smp_processor_id(), 0xffff & regs->xcs, regs->eip,
 		print_tainted(), regs->eflags, UTS_RELEASE);
@@ -234,23 +248,25 @@ void show_registers(struct pt_regs *regs)
 	 * time of the fault..
 	 */
 	if (in_kernel) {
+		u8 *eip;
 
 		printk("\nStack: ");
 		show_stack(NULL, (unsigned long*)esp);
 
 		printk("Code: ");
-		if(regs->eip < PAGE_OFFSET)
-			goto bad;
 
-		for(i=0;i<20;i++)
-		{
+		eip = (u8 *)regs->eip - 43;
+		for (i = 0; i < 64; i++, eip++) {
 			unsigned char c;
-			if(__get_user(c, &((unsigned char*)regs->eip)[i])) {
-bad:
+
+			if (eip < (u8 *)PAGE_OFFSET || __get_user(c, eip)) {
 				printk(" Bad EIP value.");
 				break;
 			}
-			printk("%02x ", c);
+			if (eip == (u8 *)regs->eip)
+				printk("<%02x> ", c);
+			else
+				printk("%02x ", c);
 		}
 	}
 	printk("\n");
@@ -292,35 +308,53 @@ bug:
 	printk("Kernel BUG\n");
 }
 
-spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
-
 void die(const char * str, struct pt_regs * regs, long err)
 {
+	static struct {
+		spinlock_t lock;
+		u32 lock_owner;
+		int lock_owner_depth;
+	} die = {
+		.lock =			SPIN_LOCK_UNLOCKED,
+		.lock_owner =		-1,
+		.lock_owner_depth =	0
+	};
 	static int die_counter;
-	int nl = 0;
 
-	console_verbose();
-	spin_lock_irq(&die_lock);
-	bust_spinlocks(1);
-	handle_BUG(regs);
-	printk(KERN_ALERT "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
+	if (die.lock_owner != smp_processor_id()) {
+		console_verbose();
+		spin_lock_irq(&die.lock);
+		die.lock_owner = smp_processor_id();
+		die.lock_owner_depth = 0;
+		bust_spinlocks(1);
+	}
+
+	if (++die.lock_owner_depth < 3) {
+		int nl = 0;
+		handle_BUG(regs);
+		printk(KERN_ALERT "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
 #ifdef CONFIG_PREEMPT
-	printk("PREEMPT ");
-	nl = 1;
+		printk("PREEMPT ");
+		nl = 1;
 #endif
 #ifdef CONFIG_SMP
-	printk("SMP ");
-	nl = 1;
+		printk("SMP ");
+		nl = 1;
 #endif
 #ifdef CONFIG_DEBUG_PAGEALLOC
-	printk("DEBUG_PAGEALLOC");
-	nl = 1;
+		printk("DEBUG_PAGEALLOC");
+		nl = 1;
 #endif
-	if (nl)
-		printk("\n");
-	show_registers(regs);
+		if (nl)
+			printk("\n");
+	notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV);
+		show_registers(regs);
+  	} else
+		printk(KERN_ERR "Recursive die() failure, output suppressed\n");
+
 	bust_spinlocks(0);
-	spin_unlock_irq(&die_lock);
+	die.lock_owner = -1;
+	spin_unlock_irq(&die.lock);
 	if (in_interrupt())
 		panic("Fatal exception in interrupt");
 
@@ -387,6 +421,9 @@ static inline void do_trap(int trapnr, int signr, char *str, int vm86,
 #define DO_ERROR(trapnr, signr, str, name) \
 asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
 { \
+	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+						== NOTIFY_STOP) \
+		return; \
 	do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \
 }
 
@@ -398,12 +435,18 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
 	info.si_errno = 0; \
 	info.si_code = sicode; \
 	info.si_addr = (void __user *)siaddr; \
+	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+						== NOTIFY_STOP) \
+		return; \
 	do_trap(trapnr, signr, str, 0, regs, error_code, &info); \
 }
 
 #define DO_VM86_ERROR(trapnr, signr, str, name) \
 asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
 { \
+	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+						== NOTIFY_STOP) \
+		return; \
 	do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \
 }
 
@@ -415,11 +458,16 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
 	info.si_errno = 0; \
 	info.si_code = sicode; \
 	info.si_addr = (void __user *)siaddr; \
+	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+						== NOTIFY_STOP) \
+		return; \
 	do_trap(trapnr, signr, str, 1, regs, error_code, &info); \
 }
 
 DO_VM86_ERROR_INFO( 0, SIGFPE,  "divide error", divide_error, FPE_INTDIV, regs->eip)
+#ifndef CONFIG_KPROBES
 DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
+#endif
 DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
 DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)
 DO_ERROR_INFO( 6, SIGILL,  "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
@@ -427,13 +475,40 @@ DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun
 DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
 DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
 DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)
-DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, get_cr2())
+DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
 
 asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
 {
-	if (regs->eflags & X86_EFLAGS_IF)
-		local_irq_enable();
- 
+	int cpu = get_cpu();
+	struct tss_struct *tss = &per_cpu(init_tss, cpu);
+	struct thread_struct *thread = &current->thread;
+
+	/*
+	 * Perform the lazy TSS's I/O bitmap copy. If the TSS has an
+	 * invalid offset set (the LAZY one) and the faulting thread has
+	 * a valid I/O bitmap pointer, we copy the I/O bitmap in the TSS
+	 * and we set the offset field correctly. Then we let the CPU to
+	 * restart the faulting instruction.
+	 */
+	if (tss->io_bitmap_base == INVALID_IO_BITMAP_OFFSET_LAZY &&
+	    thread->io_bitmap_ptr) {
+		memcpy(tss->io_bitmap, thread->io_bitmap_ptr,
+		       thread->io_bitmap_max);
+		/*
+		 * If the previously set map was extending to higher ports
+		 * than the current one, pad extra space with 0xff (no access).
+		 */
+		if (thread->io_bitmap_max < tss->io_bitmap_max)
+			memset((char *) tss->io_bitmap +
+				thread->io_bitmap_max, 0xff,
+				tss->io_bitmap_max - thread->io_bitmap_max);
+		tss->io_bitmap_max = thread->io_bitmap_max;
+		tss->io_bitmap_base = IO_BITMAP_OFFSET;
+		put_cpu();
+		return;
+	}
+	put_cpu();
+
 	if (regs->eflags & VM_MASK)
 		goto gp_in_vm86;
 
@@ -451,8 +526,12 @@ gp_in_vm86:
 	return;
 
 gp_in_kernel:
-	if (!fixup_exception(regs))
+	if (!fixup_exception(regs)) {
+		if (notify_die(DIE_GPF, "general protection fault", regs,
+				error_code, 13, SIGSEGV) == NOTIFY_STOP);
+			return;
 		die("general protection fault", regs, error_code);
+	}
 }
 
 static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
@@ -496,11 +575,35 @@ static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
 	printk("Do you have a strange power saving mode enabled?\n");
 }
 
+static spinlock_t nmi_print_lock = SPIN_LOCK_UNLOCKED;
+
+void die_nmi (struct pt_regs *regs, const char *msg)
+{
+	spin_lock(&nmi_print_lock);
+	/*
+	* We are in trouble anyway, lets at least try
+	* to get a message out.
+	*/
+	bust_spinlocks(1);
+	printk(msg);
+	printk(" on CPU%d, eip %08lx, registers:\n",
+		smp_processor_id(), regs->eip);
+	show_registers(regs);
+	printk("console shuts up ...\n");
+	console_silent();
+	spin_unlock(&nmi_print_lock);
+	bust_spinlocks(0);
+	do_exit(SIGSEGV);
+}
+
 static void default_do_nmi(struct pt_regs * regs)
 {
 	unsigned char reason = get_nmi_reason();
  
 	if (!(reason & 0xc0)) {
+		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT)
+							== NOTIFY_STOP)
+			return;
 #ifdef CONFIG_X86_LOCAL_APIC
 		/*
 		 * Ok, so this is none of the documented NMI sources,
@@ -514,6 +617,8 @@ static void default_do_nmi(struct pt_regs * regs)
 		unknown_nmi_error(reason, regs);
 		return;
 	}
+	if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_STOP)
+		return;
 	if (reason & 0x80)
 		mem_parity_error(reason, regs);
 	if (reason & 0x40)
@@ -557,6 +662,20 @@ void unset_nmi_callback(void)
 	nmi_callback = dummy_nmi_callback;
 }
 
+#ifdef CONFIG_KPROBES
+asmlinkage int do_int3(struct pt_regs *regs, long error_code)
+{
+	if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP)
+			== NOTIFY_STOP)
+		return 1;
+	/* This is an interrupt gate, because kprobes wants interrupts
+	disabled.  Normal trap handlers don't. */
+	restore_interrupts(regs);
+	do_trap(3, SIGTRAP, "int3", 1, regs, error_code, NULL);
+	return 0;
+}
+#endif
+
 /*
  * Our handling of the processor debug registers is non-trivial.
  * We do not clear them on entry and exit from the kernel. Therefore
@@ -587,6 +706,9 @@ asmlinkage void do_debug(struct pt_regs * regs, long error_code)
 
 	__asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
 
+	if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
+					SIGTRAP) == NOTIFY_STOP)
+		return;
 	/* It's safe to allow irq's after DR6 has been saved */
 	if (regs->eflags & X86_EFLAGS_IF)
 		local_irq_enable();
@@ -875,6 +997,14 @@ void set_intr_gate(unsigned int n, void *addr)
 	_set_gate(idt_table+n,14,0,addr,__KERNEL_CS);
 }
 
+/*
+ * This routine sets up an interrupt gate at directory privilege level 3.
+ */
+static inline void set_system_intr_gate(unsigned int n, void *addr)
+{
+	_set_gate(idt_table+n, 14, 3, addr, __KERNEL_CS);
+}
+
 static void __init set_trap_gate(unsigned int n, void *addr)
 {
 	_set_gate(idt_table+n,15,0,addr,__KERNEL_CS);
@@ -911,7 +1041,7 @@ void __init trap_init(void)
 	set_trap_gate(0,&divide_error);
 	set_intr_gate(1,&debug);
 	set_intr_gate(2,&nmi);
-	set_system_gate(3,&int3);	/* int3-5 can be called from all */
+	set_system_intr_gate(3, &int3); /* int3-5 can be called from all */
 	set_system_gate(4,&overflow);
 	set_system_gate(5,&bounds);
 	set_trap_gate(6,&invalid_op);
diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
index 4484e47a7..483e9b2e4 100644
--- a/arch/i386/kernel/vm86.c
+++ b/arch/i386/kernel/vm86.c
@@ -121,7 +121,7 @@ struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs)
 		do_exit(SIGSEGV);
 	}
 
-	tss = init_tss + get_cpu();
+	tss = &per_cpu(init_tss, get_cpu());
 	current->thread.esp0 = current->thread.saved_esp0;
 	current->thread.sysenter_cs = __KERNEL_CS;
 	load_esp0(tss, &current->thread);
@@ -303,7 +303,7 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
 	asm volatile("movl %%fs,%0":"=m" (tsk->thread.saved_fs));
 	asm volatile("movl %%gs,%0":"=m" (tsk->thread.saved_gs));
 
-	tss = init_tss + get_cpu();
+	tss = &per_cpu(init_tss, get_cpu());
 	tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
 	if (cpu_has_sep)
 		tsk->thread.sysenter_cs = 0;
diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
index 829f1c91d..e0512cc8b 100644
--- a/arch/i386/kernel/vmlinux.lds.S
+++ b/arch/i386/kernel/vmlinux.lds.S
@@ -4,6 +4,7 @@
 
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/thread_info.h>
+#include <asm/page.h>
 
 OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
 OUTPUT_ARCH(i386)
@@ -11,12 +12,13 @@ ENTRY(startup_32)
 jiffies = jiffies_64;
 SECTIONS
 {
-  . = 0xC0000000 + 0x100000;
+  . = __PAGE_OFFSET + 0x100000;
   /* read-only */
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
 	SCHED_TEXT
+	LOCK_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x9090
@@ -66,9 +68,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : {
 	*(.initcall1.init) 
diff --git a/arch/i386/lib/memcpy.c b/arch/i386/lib/memcpy.c
index ad16efa52..891b2359d 100644
--- a/arch/i386/lib/memcpy.c
+++ b/arch/i386/lib/memcpy.c
@@ -13,13 +13,13 @@ void *memcpy(void *to, const void *from, size_t n)
 	return __memcpy(to, from, n);
 #endif
 }
-EXPORT_SYMBOL_NOVERS(memcpy);
+EXPORT_SYMBOL(memcpy);
 
 void *memset(void *s, int c, size_t count)
 {
 	return __memset(s, c, count);
 }
-EXPORT_SYMBOL_NOVERS(memset);
+EXPORT_SYMBOL(memset);
 
 void *memmove(void *dest, const void *src, size_t n)
 {
@@ -41,4 +41,4 @@ void *memmove(void *dest, const void *src, size_t n)
 	}
 	return dest;
 }
-EXPORT_SYMBOL_NOVERS(memmove);
+EXPORT_SYMBOL(memmove);
diff --git a/arch/i386/lib/mmx.c b/arch/i386/lib/mmx.c
index d6fc84f37..01f8b1a2c 100644
--- a/arch/i386/lib/mmx.c
+++ b/arch/i386/lib/mmx.c
@@ -2,9 +2,9 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/sched.h>
+#include <linux/hardirq.h>
 
 #include <asm/i387.h>
-#include <asm/hardirq.h> 
 
 
 /*
diff --git a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c
index e1bcec2b5..3347c47b0 100644
--- a/arch/i386/lib/usercopy.c
+++ b/arch/i386/lib/usercopy.c
@@ -31,6 +31,7 @@ static inline int __movsl_is_ok(unsigned long a1, unsigned long a2, unsigned lon
 #define __do_strncpy_from_user(dst,src,count,res)			   \
 do {									   \
 	int __d0, __d1, __d2;						   \
+	might_sleep();							   \
 	__asm__ __volatile__(						   \
 		"	testl %1,%1\n"					   \
 		"	jz 2f\n"					   \
@@ -119,6 +120,7 @@ strncpy_from_user(char *dst, const char __user *src, long count)
 #define __do_clear_user(addr,size)					\
 do {									\
 	int __d0;							\
+	might_sleep();							\
   	__asm__ __volatile__(						\
 		"0:	rep; stosl\n"					\
 		"	movl %2,%0\n"					\
diff --git a/arch/i386/mach-es7000/es7000.h b/arch/i386/mach-es7000/es7000.h
index 1cb878fc5..1ff0caeb8 100644
--- a/arch/i386/mach-es7000/es7000.h
+++ b/arch/i386/mach-es7000/es7000.h
@@ -29,7 +29,7 @@
 
 #define	MIP_BUSY		1
 #define	MIP_SPIN		0xf0000
-#define	MIP_VALID		0x0100000000000000
+#define	MIP_VALID		0x0100000000000000ULL
 #define	MIP_PORT(VALUE)	((VALUE >> 32) & 0xffff)
 
 #define	MIP_RD_LO(VALUE)	(VALUE & 0xffffffff)   
@@ -104,6 +104,13 @@ struct mip_reg {
 #define	MIP_SW_APIC		0x1020b
 #define	MIP_FUNC(VALUE) 	(VALUE & 0xff)
 
+#if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_ACPI_BOOT))
+#define IOAPIC_GSI_BOUND(ioapic) ((ioapic+1) * (nr_ioapic_registers[ioapic]-1))
+#define MAX_GSI_MAPSIZE 32
+#endif
+
+extern unsigned long io_apic_irqs;
+
 extern int parse_unisys_oem (char *oemptr, int oem_entries);
 extern int find_unisys_acpi_oem_table(unsigned long *oem_addr, int *length);
 extern int es7000_start_cpu(int cpu, unsigned long eip);
diff --git a/arch/i386/mach-es7000/es7000plat.c b/arch/i386/mach-es7000/es7000plat.c
index 784576c53..1d1954a7f 100644
--- a/arch/i386/mach-es7000/es7000plat.c
+++ b/arch/i386/mach-es7000/es7000plat.c
@@ -51,27 +51,74 @@ struct mip_reg		*host_reg;
 int 			mip_port;
 unsigned long		mip_addr, host_addr;
 
+#if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_ACPI_BOOT))
+static unsigned long cycle_irqs = 0;
+static unsigned long free_irqs = 0;
+static int gsi_map[MAX_GSI_MAPSIZE] = { [0 ... MAX_GSI_MAPSIZE-1] = -1 };
+
+/*
+ * GSI override for ES7000 platforms.
+ */
+
+static int __init
+es7000_gsi_override(int ioapic, int gsi)
+{
+	static int newgsi = 0;
+
+	if (gsi_map[gsi] != -1)
+		gsi = gsi_map[gsi];
+	else if (cycle_irqs ^ free_irqs) {
+		newgsi = find_next_bit(&cycle_irqs, IOAPIC_GSI_BOUND(0), newgsi);
+		__set_bit(newgsi, &free_irqs);
+		gsi_map[gsi] = newgsi;
+		gsi = newgsi;
+		newgsi++;
+		Dprintk("es7000_gsi_override: free_irqs = 0x%lx\n", free_irqs);
+	}
+
+	return gsi;
+}
+
 static int __init
 es7000_rename_gsi(int ioapic, int gsi)
 {
+	static int initialized = 0;
+	int i;
+
+	/*
+	 * These should NEVER be true at this point but we'd rather be
+	 * safe than sorry.
+	 */
+	if (acpi_disabled || acpi_pci_disabled || acpi_noirq)
+ 		return gsi;
+
 	if (ioapic)
-		return gsi;
-	else {
-		if (gsi == 0)
-			return 13;
-		if (gsi == 1)
-			return 16;
-		if (gsi == 4)
-			return 17;
-		if (gsi == 6)
-			return 18;
-		if (gsi == 7)
-			return 19;
-		if (gsi == 8)
-			return 20;
-		return gsi;
-        }
+ 		return gsi;
+
+	if (!initialized) {
+		unsigned long tmp_irqs = 0;
+
+		for (i = 0; i < nr_ioapic_registers[0]; i++)
+			__set_bit(mp_irqs[i].mpc_srcbusirq, &tmp_irqs);
+
+		cycle_irqs = (~tmp_irqs & io_apic_irqs & ((1 << IOAPIC_GSI_BOUND(0)) - 1));
+
+		initialized = 1;
+		Dprintk("es7000_rename_gsi: cycle_irqs = 0x%lx\n", cycle_irqs);
+	}
+
+	for (i = 0; i < nr_ioapic_registers[0]; i++) {
+		if (mp_irqs[i].mpc_srcbusirq == gsi) {
+			if (mp_irqs[i].mpc_dstirq == gsi)
+				return gsi;
+			else
+				return es7000_gsi_override(0, gsi);
+		}
+	}
+
+	return gsi;
 }
+#endif // (CONFIG_X86_IO_APIC) && (CONFIG_ACPI_INTERPRETER || CONFIG_ACPI_BOOT)
 
 /*
  * Parse the OEM Table
@@ -193,7 +240,7 @@ find_unisys_acpi_oem_table(unsigned long *oem_addr, int *length)
 			}
 		}
 	}
-	printk("ES7000: did not find Unisys ACPI OEM table!\n");
+	Dprintk("ES7000: did not find Unisys ACPI OEM table!\n");
 	return -1;
 }
 
@@ -237,7 +284,7 @@ es7000_mip_write(struct mip_reg *mip_reg)
 	}
 
 	status = ((unsigned long long)mip_reg->off_0 &
-		(unsigned long long)0xffff0000000000) >> 48;
+		(unsigned long long)0xffff0000000000ULL) >> 48;
 	mip_reg->off_38 = ((unsigned long long)mip_reg->off_38 &
 		(unsigned long long)~MIP_VALID);
 	return status;
diff --git a/arch/i386/mach-generic/bigsmp.c b/arch/i386/mach-generic/bigsmp.c
index f599d8564..25883b44f 100644
--- a/arch/i386/mach-generic/bigsmp.c
+++ b/arch/i386/mach-generic/bigsmp.c
@@ -13,15 +13,41 @@
 #include <linux/kernel.h>
 #include <linux/smp.h>
 #include <linux/init.h>
+#include <linux/dmi.h>
 #include <asm/mach-bigsmp/mach_apic.h>
 #include <asm/mach-bigsmp/mach_apicdef.h>
 #include <asm/mach-bigsmp/mach_ipi.h>
 #include <asm/mach-default/mach_mpparse.h>
 
-int dmi_bigsmp; /* can be set by dmi scanners */
+static int dmi_bigsmp; /* can be set by dmi scanners */
+
+static __init int hp_ht_bigsmp(struct dmi_system_id *d)
+{
+#ifdef CONFIG_X86_GENERICARCH
+	printk(KERN_NOTICE "%s detected: force use of apic=bigsmp\n", d->ident);
+	dmi_bigsmp = 1;
+#endif
+	return 0;
+}
+
+
+static struct dmi_system_id __initdata bigsmp_dmi_table[] = {
+	{ hp_ht_bigsmp, "HP ProLiant DL760 G2", {
+		DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
+		DMI_MATCH(DMI_BIOS_VERSION, "P44-"),
+	}},
+
+	{ hp_ht_bigsmp, "HP ProLiant DL740", {
+		DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
+		DMI_MATCH(DMI_BIOS_VERSION, "P47-"),
+	 }},
+	 { }
+};
+
 
 static __init int probe_bigsmp(void)
 { 
+	dmi_check_system(bigsmp_dmi_table);
 	return dmi_bigsmp; 
 } 
 
diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c
index 90c918f11..7cb7e8046 100644
--- a/arch/i386/mach-voyager/voyager_smp.c
+++ b/arch/i386/mach-voyager/voyager_smp.c
@@ -35,7 +35,7 @@
 int reboot_smp = 0;
 
 /* TLB state -- visible externally, indexed physically */
-struct tlb_state cpu_tlbstate[NR_CPUS] __cacheline_aligned = {[0 ... NR_CPUS-1] = { &init_mm, 0 }};
+DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0 };
 
 /* CPU IRQ affinity -- set to all ones initially */
 static unsigned long cpu_irq_affinity[NR_CPUS] __cacheline_aligned = { [0 ... NR_CPUS-1]  = ~0UL };
@@ -523,15 +523,6 @@ start_secondary(void *unused)
 	return cpu_idle();
 }
 
-static struct task_struct * __init
-fork_by_hand(void)
-{
-	struct pt_regs regs;
-	/* don't care about the eip and regs settings since we'll
-	 * never reschedule the forked task. */
-	return copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
-}
-
 
 /* Routine to kick start the given CPU and wait for it to report ready
  * (or timeout in startup).  When this routine returns, the requested
@@ -587,16 +578,10 @@ do_boot_cpu(__u8 cpu)
 	hijack_source.idt.Segment = (start_phys_address >> 4) & 0xFFFF;
 
 	cpucount++;
-	idle = fork_by_hand();
+	idle = fork_idle(cpu);
 	if(IS_ERR(idle))
 		panic("failed fork for CPU%d", cpu);
-
-	wake_up_forked_process(idle);
-
-	init_idle(idle, cpu);
-
 	idle->thread.eip = (unsigned long) start_secondary;
-	unhash_process(idle);
 	/* init_tasks (in sched.c) is indexed logically */
 	stack_start.esp = (void *) idle->thread.esp;
 
@@ -860,9 +845,9 @@ static spinlock_t tlbstate_lock = SPIN_LOCK_UNLOCKED;
 static inline void
 leave_mm (unsigned long cpu)
 {
-	if (cpu_tlbstate[cpu].state == TLBSTATE_OK)
+	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK)
 		BUG();
-	cpu_clear(cpu,  cpu_tlbstate[cpu].active_mm->cpu_vm_mask);
+	cpu_clear(cpu, per_cpu(cpu_tlbstate, cpu).active_mm->cpu_vm_mask);
 	load_cr3(swapper_pg_dir);
 }
 
@@ -883,8 +868,8 @@ smp_invalidate_interrupt(void)
 		smp_processor_id()));
 	*/
 
-	if (flush_mm == cpu_tlbstate[cpu].active_mm) {
-		if (cpu_tlbstate[cpu].state == TLBSTATE_OK) {
+	if (flush_mm == per_cpu(cpu_tlbstate, cpu).active_mm) {
+		if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) {
 			if (flush_va == FLUSH_ALL)
 				local_flush_tlb();
 			else
@@ -1218,7 +1203,7 @@ do_flush_tlb_all(void* info)
 	unsigned long cpu = smp_processor_id();
 
 	__flush_tlb_all();
-	if (cpu_tlbstate[cpu].state == TLBSTATE_LAZY)
+	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_LAZY)
 		leave_mm(cpu);
 }
 
@@ -1302,8 +1287,7 @@ smp_local_timer_interrupt(struct pt_regs * regs)
 	int cpu = smp_processor_id();
 	long weight;
 
-	x86_do_profile(regs);
-
+	profile_tick(CPU_PROFILING, regs);
 	if (--per_cpu(prof_counter, cpu) <= 0) {
 		/*
 		 * The multiplier may have changed since the last time we got
diff --git a/arch/i386/math-emu/fpu_proto.h b/arch/i386/math-emu/fpu_proto.h
index a8618dfd6..a9fe07c9b 100644
--- a/arch/i386/math-emu/fpu_proto.h
+++ b/arch/i386/math-emu/fpu_proto.h
@@ -69,7 +69,6 @@ extern int isNaN(FPU_REG const *ptr);
 extern void FPU_pop(void);
 extern int FPU_empty_i(int stnr);
 extern int FPU_stackoverflow(FPU_REG **st_new_ptr);
-extern void FPU_sync_tags(void);
 extern void FPU_copy_to_regi(FPU_REG const *r, u_char tag, int stnr);
 extern void FPU_copy_to_reg1(FPU_REG const *r, u_char tag);
 extern void FPU_copy_to_reg0(FPU_REG const *r, u_char tag);
diff --git a/arch/i386/mm/Makefile b/arch/i386/mm/Makefile
index 87dd63c98..fc3272506 100644
--- a/arch/i386/mm/Makefile
+++ b/arch/i386/mm/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the linux i386-specific parts of the memory manager.
 #
 
-obj-y	:= init.o pgtable.o fault.o ioremap.o extable.o pageattr.o 
+obj-y	:= init.o pgtable.o fault.o ioremap.o extable.o pageattr.o mmap.o
 
 obj-$(CONFIG_DISCONTIGMEM)	+= discontig.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c
index 569e08e5b..efdcb0da9 100644
--- a/arch/i386/mm/discontig.c
+++ b/arch/i386/mm/discontig.c
@@ -31,6 +31,7 @@
 #include <asm/e820.h>
 #include <asm/setup.h>
 #include <asm/mmzone.h>
+#include <bios_ebda.h>
 
 struct pglist_data *node_data[MAX_NUMNODES];
 bootmem_data_t node0_bdata;
@@ -219,6 +220,17 @@ static unsigned long calculate_numa_remap_pages(void)
 	return reserve_pages;
 }
 
+/*
+ * workaround for Dell systems that neglect to reserve EBDA
+ */
+static void __init reserve_ebda_region_node(void)
+{
+	unsigned int addr;
+	addr = get_bios_ebda();
+	if (addr)
+		reserve_bootmem_node(NODE_DATA(0), addr, PAGE_SIZE);
+}
+
 unsigned long __init setup_memory(void)
 {
 	int nid;
@@ -318,6 +330,9 @@ unsigned long __init setup_memory(void)
 	 */
 	reserve_bootmem_node(NODE_DATA(0), PAGE_SIZE, PAGE_SIZE);
 
+	/* reserve EBDA region, it's a 4K region */
+	reserve_ebda_region_node();
+
 #ifdef CONFIG_ACPI_SLEEP
 	/*
 	 * Reserve low memory region for sleep support.
@@ -402,15 +417,15 @@ void __init zone_sizes_init(void)
 		 * remapped KVA area - mbligh
 		 */
 		if (!nid)
-			free_area_init_node(nid, NODE_DATA(nid), 0, 
-				zones_size, start, zholes_size);
+			free_area_init_node(nid, NODE_DATA(nid),
+					zones_size, start, zholes_size);
 		else {
 			unsigned long lmem_map;
 			lmem_map = (unsigned long)node_remap_start_vaddr[nid];
 			lmem_map += sizeof(pg_data_t) + PAGE_SIZE - 1;
 			lmem_map &= PAGE_MASK;
-			free_area_init_node(nid, NODE_DATA(nid), 
-				(struct page *)lmem_map, zones_size, 
+			NODE_DATA(nid)->node_mem_map = (struct page *)lmem_map;
+			free_area_init_node(nid, NODE_DATA(nid), zones_size,
 				start, zholes_size);
 		}
 	}
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index debed4754..e92938476 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -24,8 +24,8 @@
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 #include <asm/desc.h>
+#include <asm/kdebug.h>
 
 extern void die(const char *,struct pt_regs *,long);
 
@@ -107,7 +107,7 @@ static inline unsigned long get_segment_eip(struct pt_regs *regs,
 		desc = (void *)desc + (seg & ~7);
 	} else {
 		/* Must disable preemption while reading the GDT. */
-		desc = (u32 *)&cpu_gdt_table[get_cpu()];
+		desc = (u32 *)&per_cpu(cpu_gdt_table, get_cpu());
 		desc = (void *)desc + (seg & ~7);
 	}
 
@@ -226,6 +226,9 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
 	/* get the address */
 	__asm__("movl %%cr2,%0":"=r" (address));
 
+	if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
+					SIGSEGV) == NOTIFY_STOP)
+		return;
 	/* It's safe to allow irq's after cr2 has been saved */
 	if (regs->eflags & (X86_EFLAGS_IF|VM_MASK))
 		local_irq_enable();
@@ -513,12 +516,13 @@ vmalloc_fault:
 		 * an interrupt in the middle of a task switch..
 		 */
 		int index = pgd_index(address);
+		unsigned long pgd_paddr;
 		pgd_t *pgd, *pgd_k;
 		pmd_t *pmd, *pmd_k;
 		pte_t *pte_k;
 
-		asm("movl %%cr3,%0":"=r" (pgd));
-		pgd = index + (pgd_t *)__va(pgd);
+		asm("movl %%cr3,%0":"=r" (pgd_paddr));
+		pgd = index + (pgd_t *)__va(pgd_paddr);
 		pgd_k = init_mm.pgd + index;
 
 		if (!pgd_present(*pgd_k))
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index a8bd0544a..567ec7c49 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -40,10 +40,12 @@
 #include <asm/tlbflush.h>
 #include <asm/sections.h>
 
+unsigned int __VMALLOC_RESERVE = 128 << 20;
+
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 unsigned long highstart_pfn, highend_pfn;
 
-static int do_test_wp_bit(void);
+static int noinline do_test_wp_bit(void);
 
 /*
  * Creates a middle page table and puts a pointer to it in the
@@ -671,7 +673,7 @@ void __init pgtable_cache_init(void)
  * This function cannot be __init, since exceptions don't work in that
  * section.  Put this after the callers, so that it cannot be inlined.
  */
-static int do_test_wp_bit(void)
+static int noinline do_test_wp_bit(void)
 {
 	char tmp_reg;
 	int flag;
diff --git a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
index 7b11be028..aee0bb1f4 100644
--- a/arch/i386/mm/ioremap.c
+++ b/arch/i386/mm/ioremap.c
@@ -110,9 +110,9 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr,
  * have to convert them into an offset in a page-aligned mapping, but the
  * caller shouldn't need to know that small detail.
  */
-void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
 {
-	void * addr;
+	void __iomem * addr;
 	struct vm_struct * area;
 	unsigned long offset, last_addr;
 
@@ -125,7 +125,7 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
 	 * Don't remap the low PCI/ISA area, it's always mapped..
 	 */
 	if (phys_addr >= 0xA0000 && last_addr < 0x100000)
-		return phys_to_virt(phys_addr);
+		return (void __iomem *) phys_to_virt(phys_addr);
 
 	/*
 	 * Don't allow anybody to remap normal RAM that we're using..
@@ -156,12 +156,12 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
 	if (!area)
 		return NULL;
 	area->phys_addr = phys_addr;
-	addr = area->addr;
+	addr = (void __iomem *) area->addr;
 	if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) {
-		vunmap(addr);
+		vunmap((void __force *) addr);
 		return NULL;
 	}
-	return (void *) (offset + (char *)addr);
+	return (void __iomem *) (offset + (char __iomem *)addr);
 }
 
 
@@ -187,10 +187,10 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
  * Must be freed with iounmap.
  */
 
-void *ioremap_nocache (unsigned long phys_addr, unsigned long size)
+void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
 {
 	unsigned long last_addr;
-	void *p = __ioremap(phys_addr, size, _PAGE_PCD);
+	void __iomem *p = __ioremap(phys_addr, size, _PAGE_PCD);
 	if (!p) 
 		return p; 
 
@@ -221,12 +221,12 @@ void *ioremap_nocache (unsigned long phys_addr, unsigned long size)
 	return p;					
 }
 
-void iounmap(void *addr)
+void iounmap(volatile void __iomem *addr)
 {
 	struct vm_struct *p;
-	if (addr <= high_memory) 
+	if ((void __force *) addr <= high_memory) 
 		return; 
-	p = remove_vm_area((void *) (PAGE_MASK & (unsigned long) addr));
+	p = remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
 	if (!p) { 
 		printk("__iounmap: bad address %p\n", addr);
 		return;
diff --git a/arch/i386/mm/mmap.c b/arch/i386/mm/mmap.c
index f88a6c88d..a6270ee14 100644
--- a/arch/i386/mm/mmap.c
+++ b/arch/i386/mm/mmap.c
@@ -57,7 +57,8 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 	 * Fall back to the standard layout if the personality
 	 * bit is set, or if the expected stack growth is unlimited:
 	 */
-	if (sysctl_legacy_va_layout || (current->personality & ADDR_COMPAT_LAYOUT) ||
+	if (sysctl_legacy_va_layout ||
+			(current->personality & ADDR_COMPAT_LAYOUT) ||
 			current->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) {
 		mm->mmap_base = TASK_UNMAPPED_BASE;
 		mm->get_unmapped_area = arch_get_unmapped_area;
@@ -65,7 +66,6 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 	} else {
 		mm->mmap_base = mmap_base(mm);
 		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
-		mm->get_unmapped_exec_area = arch_get_unmapped_exec_area;
 		mm->unmap_area = arch_unmap_area_topdown;
 	}
 }
diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c
index 8eb95be7d..4cfc30349 100644
--- a/arch/i386/mm/pageattr.c
+++ b/arch/i386/mm/pageattr.c
@@ -114,7 +114,7 @@ __change_page_attr(struct page *page, pgprot_t prot)
 	kpte = lookup_address(address);
 	if (!kpte)
 		return -EINVAL;
-	kpte_page = virt_to_page(((unsigned long)kpte) & PAGE_MASK);
+	kpte_page = virt_to_page(kpte);
 	if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) { 
 		if ((pte_val(*kpte) & _PAGE_PSE) == 0) { 
 			pte_t old = *kpte;
diff --git a/arch/i386/oprofile/op_model_athlon.c b/arch/i386/oprofile/op_model_athlon.c
index 5f6cc84ab..0d4e00f42 100644
--- a/arch/i386/oprofile/op_model_athlon.c
+++ b/arch/i386/oprofile/op_model_athlon.c
@@ -70,7 +70,7 @@ static void athlon_setup_ctrs(struct op_msrs const * const msrs)
 
 	/* enable active counters */
 	for (i = 0; i < NUM_COUNTERS; ++i) {
-		if (counter_config[i].event) {
+		if (counter_config[i].enabled) {
 			reset_value[i] = counter_config[i].count;
 
 			CTR_WRITE(counter_config[i].count, msrs, i);
@@ -96,7 +96,7 @@ static int athlon_check_ctrs(unsigned int const cpu,
 {
 	unsigned int low, high;
 	int i;
-	unsigned long eip = instruction_pointer(regs);
+	unsigned long eip = profile_pc(regs);
 	int is_kernel = !user_mode(regs);
 
 	for (i = 0 ; i < NUM_COUNTERS; ++i) {
diff --git a/arch/i386/oprofile/op_model_p4.c b/arch/i386/oprofile/op_model_p4.c
index e92eaed25..1b3626df5 100644
--- a/arch/i386/oprofile/op_model_p4.c
+++ b/arch/i386/oprofile/op_model_p4.c
@@ -419,9 +419,28 @@ static void p4_fill_in_addresses(struct op_msrs * const msrs)
 		msrs->controls[i].addr = addr;
 	}
 	
-	/* 43 ESCR registers in three discontiguous group */
+	/* 43 ESCR registers in three or four discontiguous group */
 	for (addr = MSR_P4_BSU_ESCR0 + stag;
-	     addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) { 
+	     addr < MSR_P4_IQ_ESCR0; ++i, addr += addr_increment()) {
+		msrs->controls[i].addr = addr;
+	}
+
+	/* no IQ_ESCR0/1 on some models, we save a seconde time BSU_ESCR0/1
+	 * to avoid special case in nmi_{save|restore}_registers() */
+	if (boot_cpu_data.x86_model >= 0x3) {
+		for (addr = MSR_P4_BSU_ESCR0 + stag;
+		     addr <= MSR_P4_BSU_ESCR1; ++i, addr += addr_increment()) {
+			msrs->controls[i].addr = addr;
+		}
+	} else {
+		for (addr = MSR_P4_IQ_ESCR0 + stag;
+		     addr <= MSR_P4_IQ_ESCR1; ++i, addr += addr_increment()) {
+			msrs->controls[i].addr = addr;
+		}
+	}
+
+	for (addr = MSR_P4_RAT_ESCR0 + stag;
+	     addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) {
 		msrs->controls[i].addr = addr;
 	}
 	
@@ -553,7 +572,18 @@ static void p4_setup_ctrs(struct op_msrs const * const msrs)
 
 	/* clear all escrs (including those outside our concern) */
 	for (addr = MSR_P4_BSU_ESCR0 + stag;
-	     addr <= MSR_P4_SSU_ESCR0; addr += addr_increment()) { 
+	     addr <  MSR_P4_IQ_ESCR0; addr += addr_increment()) {
+		wrmsr(addr, 0, 0);
+	}
+
+	/* On older models clear also MSR_P4_IQ_ESCR0/1 */
+	if (boot_cpu_data.x86_model < 0x3) {
+		wrmsr(MSR_P4_IQ_ESCR0, 0, 0);
+		wrmsr(MSR_P4_IQ_ESCR1, 0, 0);
+	}
+
+	for (addr = MSR_P4_RAT_ESCR0 + stag;
+	     addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) {
 		wrmsr(addr, 0, 0);
 	}
 	
@@ -578,7 +608,7 @@ static void p4_setup_ctrs(struct op_msrs const * const msrs)
 	
 	/* setup all counters */
 	for (i = 0 ; i < num_counters ; ++i) {
-		if (counter_config[i].event) {
+		if (counter_config[i].enabled) {
 			reset_value[i] = counter_config[i].count;
 			pmc_setup_one_p4_counter(i);
 			CTR_WRITE(counter_config[i].count, VIRT_CTR(stag, i));
@@ -595,7 +625,7 @@ static int p4_check_ctrs(unsigned int const cpu,
 {
 	unsigned long ctr, low, high, stag, real;
 	int i;
-	unsigned long eip = instruction_pointer(regs);
+	unsigned long eip = profile_pc(regs);
 	int is_kernel = !user_mode(regs);
 
 	stag = get_stagger();
diff --git a/arch/i386/oprofile/op_model_ppro.c b/arch/i386/oprofile/op_model_ppro.c
index 21578b26d..0cc80654d 100644
--- a/arch/i386/oprofile/op_model_ppro.c
+++ b/arch/i386/oprofile/op_model_ppro.c
@@ -67,7 +67,7 @@ static void ppro_setup_ctrs(struct op_msrs const * const msrs)
 
 	/* enable active counters */
 	for (i = 0; i < NUM_COUNTERS; ++i) {
-		if (counter_config[i].event) {
+		if (counter_config[i].enabled) {
 			reset_value[i] = counter_config[i].count;
 
 			CTR_WRITE(counter_config[i].count, msrs, i);
@@ -91,7 +91,7 @@ static int ppro_check_ctrs(unsigned int const cpu,
 {
 	unsigned int low, high;
 	int i;
-	unsigned long eip = instruction_pointer(regs);
+	unsigned long eip = profile_pc(regs);
 	int is_kernel = !user_mode(regs);
  
 	for (i = 0 ; i < NUM_COUNTERS; ++i) {
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c
index 383827d92..88c832a0e 100644
--- a/arch/i386/pci/common.c
+++ b/arch/i386/pci/common.c
@@ -70,7 +70,7 @@ static void __devinit pcibios_fixup_ghosts(struct pci_bus *b)
 	int i;
 
 	DBG("PCI: Scanning for ghost devices on bus %d\n", b->number);
-	for (ln=b->devices.next; ln != &b->devices; ln=ln->next) {
+	list_for_each(ln, &b->devices) {
 		d = pci_dev_b(ln);
 		if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST)
 			seen_host_bridge++;
diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c
index a8b1954ae..bfcecdc55 100644
--- a/arch/i386/pci/fixup.c
+++ b/arch/i386/pci/fixup.c
@@ -29,6 +29,7 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d)
 	}
 	pcibios_last_bus = -1;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx);
 
 static void __devinit pci_fixup_i450gx(struct pci_dev *d)
 {
@@ -42,6 +43,7 @@ static void __devinit pci_fixup_i450gx(struct pci_dev *d)
 	pci_scan_bus(busno, &pci_root_ops, NULL);
 	pcibios_last_bus = -1;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx);
 
 static void __devinit  pci_fixup_umc_ide(struct pci_dev *d)
 {
@@ -55,6 +57,7 @@ static void __devinit  pci_fixup_umc_ide(struct pci_dev *d)
 	for(i=0; i<4; i++)
 		d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide);
 
 static void __devinit  pci_fixup_ncr53c810(struct pci_dev *d)
 {
@@ -67,6 +70,7 @@ static void __devinit  pci_fixup_ncr53c810(struct pci_dev *d)
 		d->class = PCI_CLASS_STORAGE_SCSI << 8;
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, pci_fixup_ncr53c810);
 
 static void __devinit pci_fixup_ide_bases(struct pci_dev *d)
 {
@@ -86,6 +90,7 @@ static void __devinit pci_fixup_ide_bases(struct pci_dev *d)
 		}
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
 
 static void __devinit  pci_fixup_ide_trash(struct pci_dev *d)
 {
@@ -108,6 +113,10 @@ static void __devinit  pci_fixup_ide_trash(struct pci_dev *d)
 	for(i=0; i<4; i++)
 		d->resource[i].start = d->resource[i].end = d->resource[i].flags = 0;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_fixup_ide_trash);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, pci_fixup_ide_trash);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_11, pci_fixup_ide_trash);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_9, pci_fixup_ide_trash);
 
 static void __devinit  pci_fixup_latency(struct pci_dev *d)
 {
@@ -118,6 +127,8 @@ static void __devinit  pci_fixup_latency(struct pci_dev *d)
 	DBG("PCI: Setting max latency to 32\n");
 	pcibios_max_latency = 32;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5598, pci_fixup_latency);
 
 static void __devinit pci_fixup_piix4_acpi(struct pci_dev *d)
 {
@@ -126,6 +137,7 @@ static void __devinit pci_fixup_piix4_acpi(struct pci_dev *d)
 	 */
 	d->irq = 9;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, pci_fixup_piix4_acpi);
 
 /*
  * Addresses issues with problems in the memory write queue timer in
@@ -179,6 +191,10 @@ static void __devinit pci_fixup_via_northbridge_bug(struct pci_dev *d)
 		pci_write_config_byte(d, where, v);
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_via_northbridge_bug);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8622, pci_fixup_via_northbridge_bug);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_northbridge_bug);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_northbridge_bug);
 
 /*
  * For some reasons Intel decided that certain parts of their
@@ -195,6 +211,7 @@ static void __devinit pci_fixup_transparent_bridge(struct pci_dev *dev)
 	    (dev->device & 0xff00) == 0x2400)
 		dev->transparent = 1;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_fixup_transparent_bridge);
 
 /*
  * Fixup for C1 Halt Disconnect problem on nForce2 systems.
@@ -236,115 +253,5 @@ static void __init pci_fixup_nforce2(struct pci_dev *dev)
 		pci_write_config_dword(dev, 0x6c, fixed_val);
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2);
 
-struct pci_fixup pcibios_fixups[] = {
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_INTEL,
-		.device		= PCI_DEVICE_ID_INTEL_82451NX,
-		.hook		= pci_fixup_i450nx
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_INTEL,
-		.device		= PCI_DEVICE_ID_INTEL_82454GX,
-		.hook		= pci_fixup_i450gx
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_UMC,
-		.device		= PCI_DEVICE_ID_UMC_UM8886BF,
-		.hook		= pci_fixup_umc_ide
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_SI,
-		.device		= PCI_DEVICE_ID_SI_5513,
-		.hook		= pci_fixup_ide_trash
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_ANY_ID,
-		.device		= PCI_ANY_ID,
-		.hook		= pci_fixup_ide_bases
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_SI,
-		.device		= PCI_DEVICE_ID_SI_5597,
-		.hook		= pci_fixup_latency
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_SI,
-		.device		= PCI_DEVICE_ID_SI_5598,
-		.hook		= pci_fixup_latency
-	},
- 	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_INTEL,
-		.device		= PCI_DEVICE_ID_INTEL_82371AB_3,
-		.hook		= pci_fixup_piix4_acpi
-	},
- 	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_INTEL,
-		.device		= PCI_DEVICE_ID_INTEL_82801CA_10,
-		.hook		= pci_fixup_ide_trash
-	},
- 	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_INTEL,
-		.device		= PCI_DEVICE_ID_INTEL_82801CA_11,
-		.hook		= pci_fixup_ide_trash
-	},
- 	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_INTEL,
-		.device		= PCI_DEVICE_ID_INTEL_82801DB_9,
-		.hook		= pci_fixup_ide_trash
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_VIA,
-		.device		= PCI_DEVICE_ID_VIA_8363_0,
-		.hook		= pci_fixup_via_northbridge_bug
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_VIA,
-		.device		= PCI_DEVICE_ID_VIA_8622,
-		.hook		= pci_fixup_via_northbridge_bug
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_VIA,
-		.device		= PCI_DEVICE_ID_VIA_8361,
-		.hook		= pci_fixup_via_northbridge_bug
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_VIA,
-		.device		= PCI_DEVICE_ID_VIA_8367_0,
-		.hook		= pci_fixup_via_northbridge_bug
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_NCR,
-		.device		= PCI_DEVICE_ID_NCR_53C810,
-		.hook		= pci_fixup_ncr53c810
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_INTEL,
-		.device		= PCI_ANY_ID,
-		.hook		= pci_fixup_transparent_bridge
-	},
-	{
-		.pass		= PCI_FIXUP_HEADER,
-		.vendor		= PCI_VENDOR_ID_NVIDIA,
-		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE2,
-		.hook		= pci_fixup_nforce2
-	},
-	{ .pass = 0 }
-};
diff --git a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c
index 2ebc7c672..ec859ad0e 100644
--- a/arch/i386/pci/i386.c
+++ b/arch/i386/pci/i386.c
@@ -164,7 +164,7 @@ static void __init pcibios_allocate_resources(int pass)
 	}
 }
 
-static void __init pcibios_assign_resources(void)
+static int __init pcibios_assign_resources(void)
 {
 	struct pci_dev *dev = NULL;
 	int idx;
@@ -204,6 +204,7 @@ static void __init pcibios_assign_resources(void)
 				pci_assign_resource(dev, PCI_ROM_RESOURCE);
 		}
 	}
+	return 0;
 }
 
 void __init pcibios_resource_survey(void)
@@ -212,9 +213,14 @@ void __init pcibios_resource_survey(void)
 	pcibios_allocate_bus_resources(&pci_root_buses);
 	pcibios_allocate_resources(0);
 	pcibios_allocate_resources(1);
-	pcibios_assign_resources();
 }
 
+/**
+ * called in fs_initcall (one below subsys_initcall),
+ * give a chance for motherboard reserve resources
+ */
+fs_initcall(pcibios_assign_resources);
+
 int pcibios_enable_resources(struct pci_dev *dev, int mask)
 {
 	u16 cmd, old_cmd;
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index 0b95fc46d..f42c45305 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -1,3 +1,10 @@
+/*
+ * Copyright (C) 2004 Matthew Wilcox <matthew@wil.cx>
+ * Copyright (C) 2004 Intel Corp.
+ *
+ * This code is released under the GNU General Public License version 2.
+ */
+
 /*
  * mmconfig.c - Low-level direct PCI config space access via MMCONFIG
  */
@@ -9,7 +16,7 @@
 /* The physical address of the MMCONFIG aperture.  Set from ACPI tables. */
 u32 pci_mmcfg_base_addr;
 
-#define mmcfg_virt_addr (fix_to_virt(FIX_PCIE_MCFG))
+#define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
 
 /* The base address of the last MMCONFIG device accessed */
 static u32 mmcfg_last_accessed_device;
diff --git a/arch/i386/pci/numa.c b/arch/i386/pci/numa.c
index d77450067..c8046737b 100644
--- a/arch/i386/pci/numa.c
+++ b/arch/i386/pci/numa.c
@@ -100,10 +100,7 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d)
 	}
 	pcibios_last_bus = -1;
 }
-
-struct pci_fixup pcibios_fixups[] = {
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82451NX,	pci_fixup_i450nx },
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx);
 
 static int __init pci_numa_init(void)
 {
diff --git a/arch/i386/pci/pcbios.c b/arch/i386/pci/pcbios.c
index 700188d0f..50fc1f31e 100644
--- a/arch/i386/pci/pcbios.c
+++ b/arch/i386/pci/pcbios.c
@@ -365,7 +365,7 @@ void __devinit pcibios_sort(void)
 		idx = found = 0;
 		while (pci_bios_find_device(dev->vendor, dev->device, idx, &bus, &devfn) == PCIBIOS_SUCCESSFUL) {
 			idx++;
-			for (ln=pci_devices.next; ln != &pci_devices; ln=ln->next) {
+			list_for_each(ln, &pci_devices) {
 				d = pci_dev_g(ln);
 				if (d->bus->number == bus && d->devfn == devfn) {
 					list_del(&d->global_list);
diff --git a/arch/i386/power/Makefile b/arch/i386/power/Makefile
index 2e1c9ab34..8cfa4e8a7 100644
--- a/arch/i386/power/Makefile
+++ b/arch/i386/power/Makefile
@@ -1,3 +1,2 @@
 obj-$(CONFIG_PM)		+= cpu.o
-obj-$(CONFIG_PM_DISK)		+= pmdisk.o
 obj-$(CONFIG_SOFTWARE_SUSPEND)	+= swsusp.o
diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c
index d58d30777..53542e3a9 100644
--- a/arch/i386/power/cpu.c
+++ b/arch/i386/power/cpu.c
@@ -83,10 +83,10 @@ do_fpu_end(void)
 static void fix_processor_context(void)
 {
 	int cpu = smp_processor_id();
-	struct tss_struct * t = init_tss + cpu;
+	struct tss_struct * t = &per_cpu(init_tss, cpu);
 
 	set_tss_desc(cpu,t);	/* This just modifies memory; should not be necessary. But... This is necessary, because 386 hardware has concept of busy TSS or some similar stupidity. */
-        cpu_gdt_table[cpu][GDT_ENTRY_TSS].b &= 0xfffffdff;
+        per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_TSS].b &= 0xfffffdff;
 
 	load_TR_desc();				/* This does ltr */
 	load_LDT(&current->active_mm->context);	/* This does lldt */
diff --git a/arch/i386/power/swsusp.S b/arch/i386/power/swsusp.S
index 8e4a7baca..6e6335f89 100644
--- a/arch/i386/power/swsusp.S
+++ b/arch/i386/power/swsusp.S
@@ -15,83 +15,47 @@
 
 	.text
 
-ENTRY(do_magic)
-	pushl %ebx
-	cmpl $0,8(%esp)
-	jne resume
-	call do_magic_suspend_1
-	call save_processor_state
+ENTRY(swsusp_arch_suspend)
 
 	movl %esp, saved_context_esp
-	movl %eax, saved_context_eax
 	movl %ebx, saved_context_ebx
-	movl %ecx, saved_context_ecx
-	movl %edx, saved_context_edx
 	movl %ebp, saved_context_ebp
 	movl %esi, saved_context_esi
 	movl %edi, saved_context_edi
 	pushfl ; popl saved_context_eflags
 
-	call do_magic_suspend_2
-	popl %ebx
+	call swsusp_save
 	ret
 
-resume:
+ENTRY(swsusp_arch_resume)
 	movl $swsusp_pg_dir-__PAGE_OFFSET,%ecx
 	movl %ecx,%cr3
 
-	call do_magic_resume_1
-	movl $0,loop
-	cmpl $0,nr_copy_pages
-	je copy_done
-copy_loop:
-	movl $0,loop2
+	movl	pagedir_nosave, %ebx
+	xorl	%eax, %eax
+	xorl	%edx, %edx
 	.p2align 4,,7
-copy_one_page:
-	movl pagedir_nosave,%ecx
-	movl loop,%eax
-	movl loop2,%edx
-	sall $4,%eax
-	movl 4(%ecx,%eax),%ebx
-	movl (%ecx,%eax),%eax
-	movb (%edx,%eax),%al
-	movb %al,(%edx,%ebx)
 
-	movl loop2,%eax
-	leal 1(%eax),%edx
-	movl %edx,loop2
-	movl %edx,%eax
-	cmpl $4095,%eax
-	jbe copy_one_page
-	movl loop,%eax
-	leal 1(%eax),%edx
-	movl %edx,loop
-	movl %edx,%eax
-	cmpl nr_copy_pages,%eax
-	jb copy_loop
+copy_loop:
+	movl	4(%ebx,%edx),%edi
+	movl	(%ebx,%edx),%esi
+
+	movl	$1024, %ecx
+	rep
+	movsl
 
-copy_done:
-	movl $__USER_DS,%eax
+	incl	%eax
+	addl	$16, %edx
+	cmpl	nr_copy_pages,%eax
+	jb copy_loop
+	.p2align 4,,7
 
-	movw %ax, %ds
-	movw %ax, %es
 	movl saved_context_esp, %esp
 	movl saved_context_ebp, %ebp
-	movl saved_context_eax, %eax
 	movl saved_context_ebx, %ebx
-	movl saved_context_ecx, %ecx
-	movl saved_context_edx, %edx
 	movl saved_context_esi, %esi
 	movl saved_context_edi, %edi
-	call restore_processor_state
+
 	pushl saved_context_eflags ; popfl
-	call do_magic_resume_2
-	popl %ebx
+	call swsusp_restore
 	ret
-
-       .section .data.nosave
-loop:
-       .quad 0
-loop2:
-       .quad 0
-       .previous
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 8295d4bc4..a9abc29bb 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -38,6 +38,10 @@ config EFI
 	bool
 	default y
 
+config GENERIC_IOMAP
+	bool
+	default y
+
 choice
 	prompt "System type"
 	default IA64_GENERIC
@@ -72,6 +76,12 @@ config IA64_HP_ZX1
 
 config IA64_SGI_SN2
 	bool "SGI-SN2"
+	help
+	  Selecting this option will optimize the kernel for use on sn2 based
+	  systems, but the resulting kernel binary will not run on other
+	  types of ia64 systems.  If you have an SGI Altix system, it's safe
+	  to select this option.  If in doubt, select ia64 generic support
+	  instead.
 
 config IA64_HP_SIM
 	bool "Ski-simulator"
@@ -270,6 +280,9 @@ config COMPAT
 	depends on IA32_SUPPORT
 	default y
 
+config IA64_MCA_RECOVERY
+	tristate "MCA recovery from errors other than TLB."
+
 config PERFMON
 	bool "Performance monitor support"
 	help
@@ -372,119 +385,7 @@ source "arch/ia64/hp/sim/Kconfig"
 
 source "arch/ia64/oprofile/Kconfig"
 
-menu "Kernel hacking"
-
-choice
-	prompt "Physical memory granularity"
-	default IA64_GRANULE_64MB
-
-config IA64_GRANULE_16MB
-	bool "16MB"
-	help
-	  IA-64 identity-mapped regions use a large page size called "granules".
-
-	  Select "16MB" for a small granule size.
-	  Select "64MB" for a large granule size.  This is the current default.
-
-config IA64_GRANULE_64MB
-	bool "64MB"
-	depends on !(IA64_GENERIC || IA64_HP_ZX1 || IA64_SGI_SN2)
-
-endchoice
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
-config IA64_PRINT_HAZARDS
-	bool "Print possible IA-64 dependency violations to console"
-	depends on DEBUG_KERNEL
-	help
-	  Selecting this option prints more information for Illegal Dependency
-	  Faults, that is, for Read-after-Write (RAW), Write-after-Write (WAW),
-	  or Write-after-Read (WAR) violations.  This option is ignored if you
-	  are compiling for an Itanium A step processor
-	  (CONFIG_ITANIUM_ASTEP_SPECIFIC).  If you're unsure, select Y.
-
-config DISABLE_VHPT
-	bool "Disable VHPT"
-	depends on DEBUG_KERNEL
-	help
-	  The Virtual Hash Page Table (VHPT) enhances virtual address
-	  translation performance.  Normally you want the VHPT active but you
-	  can select this option to disable the VHPT for debugging.  If you're
-	  unsure, answer N.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config DEBUG_SPINLOCK
-	bool "Spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here and build SMP to catch missing spinlock initialization
-	  and certain other kinds of spinlock errors commonly made.  This is
-	  best used in conjunction with the NMI watchdog so that spinlock
-	  deadlocks are also debuggable.
-
-config DEBUG_SPINLOCK_SLEEP
-	  bool "Sleep-inside-spinlock checking"
-	  help
-	    If you say Y here, various routines which may sleep will become very
-	    noisy if they are called with a spinlock held.
-
-config IA64_DEBUG_CMPXCHG
-	bool "Turn on compare-and-exchange bug checking (slow!)"
-	depends on DEBUG_KERNEL
-	help
-	  Selecting this option turns on bug checking for the IA-64
-	  compare-and-exchange instructions.  This is slow!  Itaniums
-	  from step B3 or later don't have this problem. If you're unsure,
-	  select N.
-
-config IA64_DEBUG_IRQ
-	bool "Turn on irq debug checks (slow!)"
-	depends on DEBUG_KERNEL
-	help
-	  Selecting this option turns on bug checking for the IA-64 irq_save
-	  and restore instructions.  It's useful for tracking down spinlock
-	  problems, but slow!  If you're unsure, select N.
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  If you don't debug the kernel, you can say N.
-
-config SYSVIPC_COMPAT
-	bool
-	depends on COMPAT && SYSVIPC
-	default y
-endmenu
+source "arch/ia64/Kconfig.debug"
 
 source "kernel/vserver/Kconfig"
 
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile
index f2ca1e231..a32ebd61a 100644
--- a/arch/ia64/Makefile
+++ b/arch/ia64/Makefile
@@ -13,6 +13,8 @@ READELF := $(CROSS_COMPILE)readelf
 
 export AWK
 
+CHECKFLAGS	+= -m64 -D__ia64=1 -D__ia64__=1 -D_LP64 -D__LP64__
+
 OBJCOPYFLAGS	:= --strip-all
 LDFLAGS_vmlinux	:= -static
 LDFLAGS_MODULE	+= -T $(srctree)/arch/ia64/module.lds
@@ -20,14 +22,12 @@ AFLAGS_KERNEL	:= -mconstant-gp
 EXTRA		:=
 
 cflags-y	:= -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f12-f15,f32-f127 \
-		   -falign-functions=32 -frename-registers
+		   -falign-functions=32 -frename-registers -fno-optimize-sibling-calls
 CFLAGS_KERNEL	:= -mconstant-gp
 
-GCC_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.')
-GCC_MINOR_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f2 -d'.')
-
-GAS_STATUS	= $(shell $(srctree)/arch/ia64/scripts/check-gas $(CC) $(OBJDUMP))
-CPPFLAGS += $(shell $(srctree)/arch/ia64/scripts/toolchain-flags $(CC) $(OBJDUMP) $(READELF))
+GCC_VERSION     := $(call cc-version)
+GAS_STATUS	= $(shell $(srctree)/arch/ia64/scripts/check-gas "$(CC)" "$(OBJDUMP)")
+CPPFLAGS += $(shell $(srctree)/arch/ia64/scripts/toolchain-flags "$(CC)" "$(OBJDUMP)" "$(READELF)")
 
 ifeq ($(GAS_STATUS),buggy)
 $(error Sorry, you need a newer version of the assember, one that is built from	\
@@ -37,16 +37,14 @@ $(error Sorry, you need a newer version of the assember, one that is built from
 		ftp://ftp.hpl.hp.com/pub/linux-ia64/gas-030124.tar.gz)
 endif
 
-ifeq ($(GCC_VERSION),2)
+ifneq ($(shell if [ $(GCC_VERSION) -lt 0300 ] ; then echo "bad"; fi ;),)
 $(error Sorry, your compiler is too old.  GCC v2.96 is known to generate bad code.)
 endif
 
-ifeq ($(GCC_VERSION),3)
- ifeq ($(GCC_MINOR_VERSION),4)
+ifeq ($(GCC_VERSION),0304)
 # Workaround Itanium 1 bugs in gcc 3.4.
 #	cflags-$(CONFIG_ITANIUM)	+= -mtune=merced
 	cflags-$(CONFIG_MCKINLEY)	+= -mtune=mckinley
- endif
 endif
 
 cflags-$(CONFIG_ITANIUM_BSTEP_SPECIFIC)	+= -mb-step
diff --git a/arch/ia64/configs/generic_defconfig b/arch/ia64/configs/generic_defconfig
index e64003e02..a2684739b 100644
--- a/arch/ia64/configs/generic_defconfig
+++ b/arch/ia64/configs/generic_defconfig
@@ -1,5 +1,7 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc1
+# Tue Aug 24 15:08:24 2004
 #
 
 #
@@ -126,6 +128,7 @@ CONFIG_PCI_NAMES=y
 CONFIG_HOTPLUG_PCI=m
 # CONFIG_HOTPLUG_PCI_FAKE is not set
 CONFIG_HOTPLUG_PCI_ACPI=m
+# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set
 # CONFIG_HOTPLUG_PCI_CPCI is not set
 # CONFIG_HOTPLUG_PCI_PCIE is not set
 # CONFIG_HOTPLUG_PCI_SHPC is not set
@@ -172,6 +175,7 @@ CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_NBD=m
 # CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=m
 CONFIG_BLK_DEV_RAM_SIZE=4096
 
@@ -313,6 +317,7 @@ CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
 CONFIG_MD_RAID1=m
+# CONFIG_MD_RAID10 is not set
 CONFIG_MD_RAID5=m
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
@@ -365,6 +370,7 @@ CONFIG_SYN_COOKIES=y
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
 # CONFIG_IPV6 is not set
 # CONFIG_NETFILTER is not set
 
@@ -575,6 +581,7 @@ CONFIG_SERIAL_NONSTANDARD=y
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_N_HDLC is not set
 # CONFIG_STALDRV is not set
+CONFIG_SGI_SNSC=y
 
 #
 # Serial drivers
@@ -766,6 +773,7 @@ CONFIG_USB=m
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
 
 #
 # USB Host Controller Drivers
@@ -918,6 +926,8 @@ CONFIG_UDF_NLS=y
 CONFIG_FAT_FS=y
 # CONFIG_MSDOS_FS is not set
 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 is not set
@@ -945,7 +955,6 @@ CONFIG_RAMFS=y
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -970,6 +979,7 @@ CONFIG_EXPORTFS=m
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
 CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 CONFIG_SMB_FS=m
 CONFIG_SMB_NLS_DEFAULT=y
 CONFIG_SMB_NLS_REMOTE="cp437"
@@ -1006,7 +1016,7 @@ CONFIG_EFI_PARTITION=y
 #
 CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_737=m
 CONFIG_NLS_CODEPAGE_775=m
 CONFIG_NLS_CODEPAGE_850=m
@@ -1030,7 +1040,7 @@ CONFIG_NLS_ISO8859_8=m
 CONFIG_NLS_CODEPAGE_1250=m
 CONFIG_NLS_CODEPAGE_1251=m
 # CONFIG_NLS_ASCII is not set
-CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_ISO8859_2=m
 CONFIG_NLS_ISO8859_3=m
 CONFIG_NLS_ISO8859_4=m
@@ -1067,18 +1077,18 @@ CONFIG_CRC32=y
 #
 # Kernel hacking
 #
-CONFIG_IA64_GRANULE_16MB=y
-# CONFIG_IA64_GRANULE_64MB is not set
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_IA64_PRINT_HAZARDS is not set
-# CONFIG_DISABLE_VHPT is not set
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_INFO is not set
+CONFIG_IA64_GRANULE_16MB=y
+# CONFIG_IA64_GRANULE_64MB is not set
+# CONFIG_IA64_PRINT_HAZARDS is not set
+# CONFIG_DISABLE_VHPT is not set
 # CONFIG_IA64_DEBUG_CMPXCHG is not set
 # CONFIG_IA64_DEBUG_IRQ is not set
-# CONFIG_DEBUG_INFO is not set
 CONFIG_SYSVIPC_COMPAT=y
 
 #
@@ -1101,11 +1111,12 @@ CONFIG_CRYPTO_DES=m
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
-# CONFIG_CRYPTO_AES_GENERIC is not set
+# CONFIG_CRYPTO_AES is not set
 # CONFIG_CRYPTO_CAST5 is not set
 # CONFIG_CRYPTO_CAST6 is not set
 # CONFIG_CRYPTO_TEA is not set
 # CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
index 2797cb4eb..80b53c925 100644
--- a/arch/ia64/configs/sn2_defconfig
+++ b/arch/ia64/configs/sn2_defconfig
@@ -1,5 +1,7 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2
+# Fri Sep 24 08:59:00 2004
 #
 
 #
@@ -7,11 +9,11 @@
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
@@ -32,6 +34,8 @@ CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -53,6 +57,7 @@ CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_TIME_INTERPOLATION=y
 CONFIG_EFI=y
+CONFIG_GENERIC_IOMAP=y
 # CONFIG_IA64_GENERIC is not set
 # CONFIG_IA64_DIG is not set
 # CONFIG_IA64_HP_ZX1 is not set
@@ -75,7 +80,7 @@ CONFIG_FORCE_MAX_ZONEORDER=18
 CONFIG_SMP=y
 CONFIG_NR_CPUS=512
 # CONFIG_HOTPLUG_CPU is not set
-# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT=y
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_IA32_SUPPORT=y
 CONFIG_COMPAT=y
@@ -115,7 +120,7 @@ CONFIG_ACPI_SYSTEM=y
 #
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
-# CONFIG_PCI_USE_VECTOR is not set
+# CONFIG_PCI_MSI is not set
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
 
@@ -142,6 +147,7 @@ CONFIG_HOTPLUG_PCI_SGI=y
 #
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=m
 # CONFIG_DEBUG_DRIVER is not set
@@ -171,6 +177,7 @@ CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_NBD=m
 # CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
@@ -185,7 +192,8 @@ 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_IDEDISK is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -206,7 +214,6 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_ADMA=y
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD74XX is not set
@@ -273,7 +280,8 @@ CONFIG_SCSI_FC_ATTRS=y
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
 CONFIG_SCSI_SATA=y
 # CONFIG_SCSI_SATA_SVW is not set
 # CONFIG_SCSI_ATA_PIIX is not set
@@ -316,6 +324,7 @@ CONFIG_BLK_DEV_MD=y
 CONFIG_MD_LINEAR=y
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
+# CONFIG_MD_RAID10 is not set
 CONFIG_MD_RAID5=y
 # CONFIG_MD_RAID6 is not set
 CONFIG_MD_MULTIPATH=y
@@ -329,8 +338,7 @@ CONFIG_DM_ZERO=m
 # Fusion MPT device support
 #
 CONFIG_FUSION=y
-CONFIG_FUSION_MAX_SGE=40
-CONFIG_FUSION_ISENSE=m
+CONFIG_FUSION_MAX_SGE=128
 CONFIG_FUSION_CTL=m
 
 #
@@ -368,11 +376,13 @@ CONFIG_SYN_COOKIES=y
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_IPV6=m
 # CONFIG_IPV6_PRIVACY is not set
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_IPV6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
@@ -527,6 +537,7 @@ CONFIG_SERIAL_NONSTANDARD=y
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_N_HDLC is not set
 # CONFIG_STALDRV is not set
+CONFIG_SGI_SNSC=y
 
 #
 # Serial drivers
@@ -537,11 +548,11 @@ CONFIG_SERIAL_NONSTANDARD=y
 # Non-8250 serial port support
 #
 CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_SGI_L1_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
 
 #
 # IPMI
@@ -566,6 +577,7 @@ CONFIG_EFI_RTC=y
 CONFIG_RAW_DRIVER=m
 # CONFIG_HPET is not set
 CONFIG_MAX_RAW_DEVS=256
+CONFIG_MMTIMER=y
 
 #
 # I2C support
@@ -600,7 +612,6 @@ CONFIG_MAX_RAW_DEVS=256
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 
 #
@@ -620,6 +631,7 @@ CONFIG_USB=m
 # CONFIG_USB_DEVICEFS is not set
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
 
 #
 # USB Host Controller Drivers
@@ -716,7 +728,7 @@ CONFIG_USB_HIDINPUT=y
 #
 # File systems
 #
-CONFIG_EXT2_FS=m
+CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT2_FS_SECURITY=y
@@ -791,7 +803,6 @@ CONFIG_RAMFS=y
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -816,10 +827,12 @@ CONFIG_EXPORTFS=m
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
 CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
 # CONFIG_CIFS_POSIX is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
@@ -906,18 +919,18 @@ CONFIG_ZLIB_DEFLATE=m
 #
 # Kernel hacking
 #
-CONFIG_IA64_GRANULE_16MB=y
-# CONFIG_IA64_GRANULE_64MB is not set
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_IA64_PRINT_HAZARDS is not set
-# CONFIG_DISABLE_VHPT is not set
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_IA64_GRANULE_16MB=y
+# CONFIG_IA64_GRANULE_64MB is not set
+# CONFIG_IA64_PRINT_HAZARDS is not set
+# CONFIG_DISABLE_VHPT is not set
 # CONFIG_IA64_DEBUG_CMPXCHG is not set
 # CONFIG_IA64_DEBUG_IRQ is not set
-CONFIG_DEBUG_INFO=y
 CONFIG_SYSVIPC_COMPAT=y
 
 #
@@ -936,6 +949,7 @@ CONFIG_CRYPTO_MD5=m
 CONFIG_CRYPTO_SHA1=m
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WHIRLPOOL is not set
 CONFIG_CRYPTO_DES=m
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
@@ -945,6 +959,7 @@ CONFIG_CRYPTO_DES=m
 # CONFIG_CRYPTO_CAST6 is not set
 # CONFIG_CRYPTO_TEA is not set
 # CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
 CONFIG_CRYPTO_DEFLATE=m
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
diff --git a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig
index e9eda7323..7ef08d376 100644
--- a/arch/ia64/configs/zx1_defconfig
+++ b/arch/ia64/configs/zx1_defconfig
@@ -1,5 +1,7 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2-aegl
+# Mon Sep 27 19:03:13 2004
 #
 
 #
@@ -7,33 +9,45 @@
 #
 CONFIG_EXPERIMENTAL=y
 # CONFIG_CLEAN_COMPILE is not set
-CONFIG_STANDALONE=y
 CONFIG_BROKEN=y
 CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
 CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_HOTPLUG=y
 # CONFIG_IKCONFIG is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_IOSCHED_NOOP=y
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_KMOD is not set
 
 #
 # Processor type and features
@@ -44,54 +58,53 @@ CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_TIME_INTERPOLATION=y
 CONFIG_EFI=y
-# CONFIG_ITANIUM is not set
-CONFIG_MCKINLEY=y
+CONFIG_GENERIC_IOMAP=y
 # CONFIG_IA64_GENERIC is not set
 # CONFIG_IA64_DIG is not set
 CONFIG_IA64_HP_ZX1=y
 # CONFIG_IA64_SGI_SN2 is not set
 # CONFIG_IA64_HP_SIM is not set
+# CONFIG_ITANIUM is not set
+CONFIG_MCKINLEY=y
 # CONFIG_IA64_PAGE_SIZE_4KB is not set
 # CONFIG_IA64_PAGE_SIZE_8KB is not set
 CONFIG_IA64_PAGE_SIZE_16KB=y
 # CONFIG_IA64_PAGE_SIZE_64KB is not set
-CONFIG_ACPI=y
-CONFIG_ACPI_INTERPRETER=y
-CONFIG_ACPI_KERNEL_CONFIG=y
 CONFIG_IA64_L1_CACHE_SHIFT=7
-# CONFIG_MCKINLEY_ASTEP_SPECIFIC is not set
 # CONFIG_NUMA is not set
 CONFIG_VIRTUAL_MEM_MAP=y
-CONFIG_IA64_MCA=y
 # CONFIG_IA64_CYCLONE is not set
-CONFIG_PM=y
 CONFIG_IOSAPIC=y
 CONFIG_FORCE_MAX_ZONEORDER=18
-# CONFIG_HUGETLB_PAGE_SIZE_4GB is not set
-# CONFIG_HUGETLB_PAGE_SIZE_1GB is not set
-# CONFIG_HUGETLB_PAGE_SIZE_256MB is not set
-CONFIG_HUGETLB_PAGE_SIZE_64MB=y
-# CONFIG_HUGETLB_PAGE_SIZE_16MB is not set
-# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
-# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
-# CONFIG_HUGETLB_PAGE_SIZE_256KB is not set
-CONFIG_IA64_PAL_IDLE=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=16
+# CONFIG_HOTPLUG_CPU is not set
 # CONFIG_PREEMPT is not set
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_IA32_SUPPORT=y
 CONFIG_COMPAT=y
 CONFIG_PERFMON=y
 CONFIG_IA64_PALINFO=y
+
+#
+# Firmware Drivers
+#
 CONFIG_EFI_VARS=y
+CONFIG_EFI_PCDP=y
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
 
+#
+# Power management and ACPI
+#
+CONFIG_PM=y
+CONFIG_ACPI=y
+
 #
 # ACPI (Advanced Configuration and Power Interface) Support
 #
 CONFIG_ACPI_BOOT=y
+CONFIG_ACPI_INTERPRETER=y
 CONFIG_ACPI_BUTTON=y
 CONFIG_ACPI_FAN=y
 CONFIG_ACPI_PROCESSOR=y
@@ -101,8 +114,13 @@ CONFIG_ACPI_BUS=y
 CONFIG_ACPI_POWER=y
 CONFIG_ACPI_PCI=y
 CONFIG_ACPI_SYSTEM=y
+
+#
+# Bus options (PCI, PCMCIA)
+#
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_MSI is not set
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
 
@@ -112,6 +130,7 @@ CONFIG_PCI_NAMES=y
 CONFIG_HOTPLUG_PCI=y
 # CONFIG_HOTPLUG_PCI_FAKE is not set
 CONFIG_HOTPLUG_PCI_ACPI=y
+# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set
 # CONFIG_HOTPLUG_PCI_CPCI is not set
 # CONFIG_HOTPLUG_PCI_PCIE is not set
 # CONFIG_HOTPLUG_PCI_SHPC is not set
@@ -122,20 +141,27 @@ CONFIG_HOTPLUG_PCI_ACPI=y
 # CONFIG_PCMCIA is not set
 
 #
-# Parallel port support
+# Device Drivers
 #
-# CONFIG_PARPORT is not set
 
 #
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
 
 #
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
 
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
 #
 # Plug and Play support
 #
@@ -143,7 +169,6 @@ CONFIG_HOTPLUG_PCI_ACPI=y
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -151,10 +176,11 @@ CONFIG_HOTPLUG_PCI_ACPI=y
 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_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_DCSSBLK is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -165,9 +191,9 @@ 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_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -187,7 +213,6 @@ CONFIG_BLK_DEV_GENERIC=y
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 # CONFIG_IDEDMA_PCI_AUTO is not set
-CONFIG_BLK_DEV_ADMA=y
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD74XX is not set
@@ -208,32 +233,12 @@ CONFIG_BLK_DEV_CMD64X=y
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
 # CONFIG_IDEDMA_AUTO is not set
 # CONFIG_BLK_DEV_HD is not set
 
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-CONFIG_FUSION=y
-CONFIG_FUSION_BOOT=y
-CONFIG_FUSION_MAX_SGE=40
-
 #
 # SCSI device support
 #
@@ -254,21 +259,28 @@ CONFIG_CHR_DEV_SG=y
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_REPORT_LUNS=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
 
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+
 #
 # SCSI low-level drivers
 #
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AACRAID is not set
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_ADVANSYS is not set
-CONFIG_SCSI_MEGARAID=y
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_CPQFCTS is not set
@@ -285,6 +297,7 @@ CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_PCI2000 is not set
 # CONFIG_SCSI_PCI2220I is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
@@ -301,6 +314,28 @@ CONFIG_SCSI_QLA2XXX=y
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
 
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_MAX_SGE=40
+# CONFIG_FUSION_CTL is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
 #
 # Networking support
 #
@@ -322,19 +357,17 @@ CONFIG_IP_MULTICAST=y
 # CONFIG_NET_IPGRE is not set
 # CONFIG_IP_MROUTE is not set
 # CONFIG_ARPD is not set
-# CONFIG_INET_ECN 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_TUNNEL is not set
 
 #
 # IP: Virtual Server Configuration
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -353,10 +386,11 @@ CONFIG_IP_NF_ARPTABLES=y
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP 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
@@ -371,21 +405,27 @@ CONFIG_IPV6_SCTP__=y
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 
 #
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-CONFIG_DUMMY=y
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -429,6 +469,7 @@ CONFIG_E100=y
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -441,7 +482,6 @@ CONFIG_E1000=y
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
 # CONFIG_SK98LIN is not set
 CONFIG_TIGON3=y
 
@@ -449,47 +489,39 @@ CONFIG_TIGON3=y
 # Ethernet (10000 Mbit)
 #
 # CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
+# CONFIG_S2IO is not set
 
 #
 # Token Ring devices
 #
 # CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
 
 #
-# Amateur Radio support
+# Wireless LAN (non-hamradio)
 #
-# CONFIG_HAMRADIO is not set
+# CONFIG_NET_RADIO is not set
 
 #
-# IrDA (infrared) support
+# Wan interfaces
 #
-# CONFIG_IRDA is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
 
 #
-# Bluetooth support
+# ISDN subsystem
 #
-# CONFIG_BT is not set
+# CONFIG_ISDN is not set
 
 #
-# ISDN subsystem
+# Telephony Support
 #
-# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
 
 #
 # Input device support
@@ -518,6 +550,7 @@ CONFIG_SERIO=y
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
 
 #
 # Input Device Drivers
@@ -541,7 +574,6 @@ CONFIG_HW_CONSOLE=y
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_HCDP=y
 CONFIG_SERIAL_8250_ACPI=y
 CONFIG_SERIAL_8250_NR_UARTS=8
 CONFIG_SERIAL_8250_EXTENDED=y
@@ -559,12 +591,6 @@ CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
 
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
 #
 # IPMI
 #
@@ -575,8 +601,6 @@ CONFIG_LEGACY_PTY_COUNT=256
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
-# CONFIG_NVRAM is not set
-# CONFIG_GEN_RTC is not set
 CONFIG_EFI_RTC=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
@@ -585,7 +609,6 @@ CONFIG_EFI_RTC=y
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_FTAPE is not set
 CONFIG_AGP=y
 CONFIG_AGP_HP_ZX1=y
 CONFIG_DRM=y
@@ -596,6 +619,7 @@ CONFIG_DRM_RADEON=y
 # CONFIG_DRM_MGA is not set
 # CONFIG_DRM_SIS is not set
 # CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
 
 #
 # I2C support
@@ -608,11 +632,13 @@ CONFIG_I2C_CHARDEV=y
 #
 CONFIG_I2C_ALGOBIT=y
 CONFIG_I2C_ALGOPCF=y
+# CONFIG_I2C_ALGOPCA is not set
 
 #
 # I2C Hardware Bus support
 #
 # CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
 # CONFIG_I2C_ALI15X3 is not set
 # CONFIG_I2C_AMD756 is not set
 # CONFIG_I2C_AMD8111 is not set
@@ -630,29 +656,55 @@ CONFIG_I2C_ALGOPCF=y
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
 
 #
-# I2C Hardware Sensors Chip support
+# Hardware Sensors Chip support
 #
 # CONFIG_I2C_SENSOR is not set
 # CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_IT87 is not set
 # CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
 # CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
 # CONFIG_SENSORS_LM83 is not set
 # CONFIG_SENSORS_LM85 is not set
 # CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
 #
 # Multimedia devices
 #
@@ -663,6 +715,167 @@ CONFIG_I2C_ALGOPCF=y
 #
 # CONFIG_DVB is not set
 
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+CONFIG_FB_RADEON=y
+CONFIG_FB_RADEON_I2C=y
+CONFIG_FB_RADEON_DEBUG=y
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+CONFIG_USB_BANDWIDTH=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_OHCI_HCD=y
+CONFIG_USB_UHCI_HCD=y
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT 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_HP8200e is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+# 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 is not set
+
+#
+# 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_TIGL is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
 #
 # File systems
 #
@@ -693,6 +906,7 @@ CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 # CONFIG_ZISOFS is not set
 CONFIG_UDF_FS=y
+CONFIG_UDF_NLS=y
 
 #
 # DOS/FAT/NT Filesystems
@@ -700,6 +914,8 @@ CONFIG_UDF_FS=y
 CONFIG_FAT_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
 #
@@ -707,6 +923,7 @@ CONFIG_VFAT_FS=y
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
 # CONFIG_DEVFS_FS is not set
 # CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
@@ -747,11 +964,12 @@ CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
 # CONFIG_AFS_FS is not set
 
 #
@@ -769,7 +987,6 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
@@ -803,6 +1020,7 @@ CONFIG_NLS_CODEPAGE_874=y
 CONFIG_NLS_ISO8859_8=y
 # CONFIG_NLS_CODEPAGE_1250 is not set
 CONFIG_NLS_CODEPAGE_1251=y
+# CONFIG_NLS_ASCII is not set
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_ISO8859_2=y
 CONFIG_NLS_ISO8859_3=y
@@ -818,227 +1036,12 @@ CONFIG_NLS_KOI8_R=y
 CONFIG_NLS_KOI8_U=y
 CONFIG_NLS_UTF8=y
 
-#
-# Graphics support
-#
-CONFIG_FB=y
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
-CONFIG_FB_RADEON=y
-CONFIG_FB_RADEON_I2C=y
-CONFIG_FB_RADEON_DEBUG=y
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_PM3 is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-CONFIG_VGA_CONSOLE=y
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-CONFIG_LOGO_LINUX_CLUT224=y
-
-#
-# Sound
-#
-CONFIG_SOUND=y
-
-#
-# Advanced Linux Sound Architecture
-#
-CONFIG_SND=y
-CONFIG_SND_SEQUENCER=y
-# CONFIG_SND_SEQ_DUMMY is not set
-CONFIG_SND_OSSEMUL=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-CONFIG_SND_SEQUENCER_OSS=y
-# CONFIG_SND_VERBOSE_PRINTK is not set
-# CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
-# CONFIG_SND_DUMMY is not set
-# CONFIG_SND_VIRMIDI is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-
-#
-# PCI devices
-#
-# CONFIG_SND_ALI5451 is not set
-# CONFIG_SND_AZT3328 is not set
-# CONFIG_SND_BT87X is not set
-# CONFIG_SND_CS46XX is not set
-# CONFIG_SND_CS4281 is not set
-# CONFIG_SND_EMU10K1 is not set
-# CONFIG_SND_KORG1212 is not set
-# CONFIG_SND_NM256 is not set
-# CONFIG_SND_RME32 is not set
-# CONFIG_SND_RME96 is not set
-# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_HDSP is not set
-# CONFIG_SND_TRIDENT is not set
-# CONFIG_SND_YMFPCI is not set
-# CONFIG_SND_ALS4000 is not set
-# CONFIG_SND_CMIPCI is not set
-# CONFIG_SND_ENS1370 is not set
-# CONFIG_SND_ENS1371 is not set
-# CONFIG_SND_ES1938 is not set
-# CONFIG_SND_ES1968 is not set
-# CONFIG_SND_MAESTRO3 is not set
-CONFIG_SND_FM801=y
-# CONFIG_SND_ICE1712 is not set
-# CONFIG_SND_ICE1724 is not set
-# CONFIG_SND_INTEL8X0 is not set
-# CONFIG_SND_SONICVIBES is not set
-# CONFIG_SND_VIA82XX is not set
-# CONFIG_SND_VX222 is not set
-
-#
-# ALSA USB devices
-#
-# CONFIG_SND_USB_AUDIO is not set
-
-#
-# Open Sound System
-#
-# CONFIG_SOUND_PRIME is not set
-
-#
-# USB support
-#
-CONFIG_USB=y
-# CONFIG_USB_DEBUG is not set
-
-#
-# Miscellaneous USB options
-#
-# CONFIG_USB_DEVICEFS is not set
-CONFIG_USB_BANDWIDTH=y
-# CONFIG_USB_DYNAMIC_MINORS is not set
-
-#
-# USB Host Controller Drivers
-#
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_UHCI_HCD=y
-
-#
-# USB Device Class drivers
-#
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_BLUETOOTH_TTY is not set
-# CONFIG_USB_MIDI is not set
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
-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_HP8200e is not set
-# CONFIG_USB_STORAGE_SDDR09 is not set
-# CONFIG_USB_STORAGE_SDDR55 is not set
-# CONFIG_USB_STORAGE_JUMPSHOT is not set
-
-#
-# USB Human Interface Devices (HID)
-#
-CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
-# CONFIG_HID_FF is not set
-CONFIG_USB_HIDDEV=y
-# CONFIG_USB_AIPTEK is not set
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_KBTAB is not set
-# CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_XPAD is not set
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
-
-#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
-# USB Network adaptors
-#
-# 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 is not set
-
-#
-# 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_TIGL is not set
-# CONFIG_USB_AUERSWALD is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_LEGOTOWER is not set
-# CONFIG_USB_LCD is not set
-# CONFIG_USB_LED is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
 #
 # Library routines
 #
+# CONFIG_CRC_CCITT is not set
 CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
 
 #
 # Profiling support
@@ -1048,18 +1051,19 @@ CONFIG_CRC32=y
 #
 # Kernel hacking
 #
-CONFIG_IA64_GRANULE_16MB=y
-# CONFIG_IA64_GRANULE_64MB is not set
 CONFIG_DEBUG_KERNEL=y
-CONFIG_IA64_PRINT_HAZARDS=y
-# CONFIG_DISABLE_VHPT is not set
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_INFO is not set
+CONFIG_IA64_GRANULE_16MB=y
+# CONFIG_IA64_GRANULE_64MB is not set
+CONFIG_IA64_PRINT_HAZARDS=y
+# CONFIG_DISABLE_VHPT is not set
 # CONFIG_IA64_DEBUG_CMPXCHG is not set
 # CONFIG_IA64_DEBUG_IRQ is not set
-# CONFIG_DEBUG_INFO is not set
+CONFIG_SYSVIPC_COMPAT=y
 
 #
 # Security options
@@ -1069,4 +1073,26 @@ CONFIG_MAGIC_SYSRQ=y
 #
 # Cryptographic options
 #
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WHIRLPOOL is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index 5333e6190..e50c446e0 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -191,7 +191,7 @@ static unsigned long iovp_shift;
 static unsigned long iovp_mask;
 
 struct ioc {
-	void		*ioc_hpa;	/* I/O MMU base address */
+	void __iomem	*ioc_hpa;	/* I/O MMU base address */
 	char		*res_map;	/* resource map, bit == pdir entry */
 	u64		*pdir_base;	/* physical base address */
 	unsigned long	ibase;		/* pdir IOV Space base */
@@ -203,6 +203,9 @@ struct ioc {
 					/* clearing pdir to prevent races with allocations. */
 	unsigned int	res_bitshift;	/* from the RIGHT! */
 	unsigned int	res_size;	/* size of resource map in bytes */
+#ifdef CONFIG_NUMA
+	unsigned int	node;		/* node where this IOC lives */
+#endif
 #if DELAYED_RESOURCE_CNT > 0
 	spinlock_t	saved_lock;	/* may want to try to get this on a separate cacheline */
 					/* than res_lock for bigger systems. */
@@ -1057,7 +1060,24 @@ sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, int
 	struct ioc *ioc;
 	void *addr;
 
+	ioc = GET_IOC(dev);
+	ASSERT(ioc);
+
+#ifdef CONFIG_NUMA
+	{
+		struct page *page;
+		page = alloc_pages_node(ioc->node == MAX_NUMNODES ?
+		                        numa_node_id() : ioc->node, flags,
+		                        get_order(size));
+
+		if (unlikely(!page))
+			return NULL;
+
+		addr = page_address(page);
+	}
+#else
 	addr = (void *) __get_free_pages(flags, get_order(size));
+#endif
 	if (unlikely(!addr))
 		return NULL;
 
@@ -1081,8 +1101,6 @@ sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, int
 	 * If device can't bypass or bypass is disabled, pass the 32bit fake
 	 * device to map single to get an iova mapping.
 	 */
-	ioc = GET_IOC(dev);
-	ASSERT(ioc);
 	*dma_handle = sba_map_single(&ioc->sac_only_dev->dev, addr, size, 0);
 
 	return addr;
@@ -1135,7 +1153,7 @@ sba_fill_pdir(
 {
 	struct scatterlist *dma_sg = startsg;	/* pointer to current DMA */
 	int n_mappings = 0;
-	u64 *pdirp = 0;
+	u64 *pdirp = NULL;
 	unsigned long dma_offset = 0;
 
 	dma_sg--;
@@ -1799,6 +1817,10 @@ ioc_show(struct seq_file *s, void *v)
 
 	seq_printf(s, "Hewlett Packard %s IOC rev %d.%d\n",
 		ioc->name, ((ioc->rev >> 4) & 0xF), (ioc->rev & 0xF));
+#ifdef CONFIG_NUMA
+	if (ioc->node != MAX_NUMNODES)
+		seq_printf(s, "NUMA node       : %d\n", ioc->node);
+#endif
 	seq_printf(s, "IOVA size       : %ld MB\n", ((ioc->pdir_size >> 3) * iovp_size)/(1024*1024));
 	seq_printf(s, "IOVA page size  : %ld kb\n", iovp_size/1024);
 
@@ -1853,7 +1875,7 @@ ioc_proc_init(void)
 {
 	struct proc_dir_entry *dir, *entry;
 
-	dir = proc_mkdir("bus/mckinley", 0);
+	dir = proc_mkdir("bus/mckinley", NULL);
 	if (!dir)
 		return;
 
@@ -1899,6 +1921,58 @@ sba_connect_bus(struct pci_bus *bus)
 	printk(KERN_WARNING "No IOC for PCI Bus %04x:%02x in ACPI\n", pci_domain_nr(bus), bus->number);
 }
 
+#ifdef CONFIG_NUMA
+static void __init
+sba_map_ioc_to_node(struct ioc *ioc, acpi_handle handle)
+{
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	union acpi_object *obj;
+	acpi_handle phandle;
+	unsigned int node;
+
+	ioc->node = MAX_NUMNODES;
+
+	/*
+	 * Check for a _PXM on this node first.  We don't typically see
+	 * one here, so we'll end up getting it from the parent.
+	 */
+	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PXM", NULL, &buffer))) {
+		if (ACPI_FAILURE(acpi_get_parent(handle, &phandle)))
+			return;
+
+		/* Reset the acpi buffer */
+		buffer.length = ACPI_ALLOCATE_BUFFER;
+		buffer.pointer = NULL;
+
+		if (ACPI_FAILURE(acpi_evaluate_object(phandle, "_PXM", NULL,
+		                                      &buffer)))
+			return;
+	}
+
+	if (!buffer.length || !buffer.pointer)
+		return;
+
+	obj = buffer.pointer;
+
+	if (obj->type != ACPI_TYPE_INTEGER ||
+	    obj->integer.value >= MAX_PXM_DOMAINS) {
+		acpi_os_free(buffer.pointer);
+		return;
+	}
+
+	node = pxm_to_nid_map[obj->integer.value];
+	acpi_os_free(buffer.pointer);
+
+	if (node >= MAX_NUMNODES || !node_online(node))
+		return;
+
+	ioc->node = node;
+	return;
+}
+#else
+#define sba_map_ioc_to_node(ioc, handle)
+#endif
+
 static int __init
 acpi_sba_ioc_add(struct acpi_device *device)
 {
@@ -1941,6 +2015,8 @@ acpi_sba_ioc_add(struct acpi_device *device)
 	if (!ioc)
 		return 1;
 
+	/* setup NUMA node association */
+	sba_map_ioc_to_node(ioc, device->handle);
 	return 0;
 }
 
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
index 381277884..af4b7143d 100644
--- a/arch/ia64/hp/sim/simserial.c
+++ b/arch/ia64/hp/sim/simserial.c
@@ -50,10 +50,6 @@
 #define _INLINE_ inline
 #endif
 
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
 #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
 
 #define SSC_GETCHAR	21
@@ -275,7 +271,7 @@ static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
 	 * Then from the beginning of the buffer until necessary
 	 */
 
-	count = MIN(CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE),
+	count = min(CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE),
 		    SERIAL_XMIT_SIZE - info->xmit.tail);
 	console->write(console, info->xmit.buf+info->xmit.tail, count);
 
@@ -1055,7 +1051,7 @@ simrs_init (void)
 			ia64_ssc_connect_irq(KEYBOARD_INTR, state->irq);
 		}
 
-		printk(KERN_INFO "ttyS%02d at 0x%04lx (irq = %d) is a %s\n",
+		printk(KERN_INFO "ttyS%d at 0x%04lx (irq = %d) is a %s\n",
 		       state->line,
 		       state->port, state->irq,
 		       uart_config[state->type].name);
diff --git a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c
index a6bc522b8..093129cb2 100644
--- a/arch/ia64/ia32/binfmt_elf32.c
+++ b/arch/ia64/ia32/binfmt_elf32.c
@@ -14,7 +14,6 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/security.h>
-#include <linux/vs_memory.h>
 
 #include <asm/param.h>
 #include <asm/signal.h>
@@ -49,6 +48,7 @@ static void elf32_set_personality (void);
 
 extern struct page *ia32_shared_page[];
 extern unsigned long *ia32_gdt;
+extern struct page *ia32_gate_page;
 
 struct page *
 ia32_install_shared_page (struct vm_area_struct *vma, unsigned long address, int *type)
@@ -60,10 +60,25 @@ ia32_install_shared_page (struct vm_area_struct *vma, unsigned long address, int
 	return pg;
 }
 
+struct page *
+ia32_install_gate_page (struct vm_area_struct *vma, unsigned long address, int *type)
+{
+	struct page *pg = ia32_gate_page;
+	get_page(pg);
+	if (type)
+		*type = VM_FAULT_MINOR;
+	return pg;
+}
+
+
 static struct vm_operations_struct ia32_shared_page_vm_ops = {
 	.nopage = ia32_install_shared_page
 };
 
+static struct vm_operations_struct ia32_gate_page_vm_ops = {
+	.nopage = ia32_install_gate_page
+};
+
 void
 ia64_elf32_init (struct pt_regs *regs)
 {
@@ -90,6 +105,29 @@ ia64_elf32_init (struct pt_regs *regs)
 		up_write(&current->mm->mmap_sem);
 	}
 
+	/*
+	 * When user stack is not executable, push sigreturn code to stack makes
+	 * segmentation fault raised when returning to kernel. So now sigreturn
+	 * code is locked in specific gate page, which is pointed by pretcode
+	 * when setup_frame_ia32
+	 */
+	vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+	if (vma) {
+		memset(vma, 0, sizeof(*vma));
+		vma->vm_mm = current->mm;
+		vma->vm_start = IA32_GATE_OFFSET;
+		vma->vm_end = vma->vm_start + PAGE_SIZE;
+		vma->vm_page_prot = PAGE_COPY_EXEC;
+		vma->vm_flags = VM_READ | VM_MAYREAD | VM_EXEC
+				| VM_MAYEXEC | VM_RESERVED;
+		vma->vm_ops = &ia32_gate_page_vm_ops;
+		down_write(&current->mm->mmap_sem);
+		{
+			insert_vm_struct(current->mm, vma);
+		}
+		up_write(&current->mm->mmap_sem);
+	}
+
 	/*
 	 * Install LDT as anonymous memory.  This gives us all-zero segment descriptors
 	 * until a task modifies them via modify_ldt().
@@ -190,9 +228,9 @@ ia32_setup_arg_pages (struct linux_binprm *bprm, int executable_stack)
 		mpnt->vm_page_prot = (mpnt->vm_flags & VM_EXEC)?
 					PAGE_COPY_EXEC: PAGE_COPY;
 		insert_vm_struct(current->mm, mpnt);
-		// current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
-		vx_vmpages_sub(current->mm, current->mm->total_vm -
-			((mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT));
+		// current->mm->stack_vm = current->mm->total_vm = vma_pages(mpnt);
+		vx_vmpages_sub(current->mm, current->mm->total_vm - vma_pages(mpnt));
+		current->mm->stack_vm = current->mm->total_vm;
 	}
 
 	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
diff --git a/arch/ia64/ia32/elfcore32.h b/arch/ia64/ia32/elfcore32.h
index 36f8d42e3..b68534d18 100644
--- a/arch/ia64/ia32/elfcore32.h
+++ b/arch/ia64/ia32/elfcore32.h
@@ -103,11 +103,15 @@ static inline int
 elf_core_copy_task_fpregs(struct task_struct *tsk, struct pt_regs *regs, elf_fpregset_t *fpu)
 {
 	struct ia32_user_i387_struct *fpstate = (void*)fpu;
+	mm_segment_t old_fs;
 
 	if (!tsk->used_math)
 		return 0;
-
-	save_ia32_fpstate(tsk, fpstate);
+	
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	save_ia32_fpstate(tsk, (struct ia32_user_i387_struct __user *) fpstate);
+	set_fs(old_fs);
 
 	return 1;
 }
@@ -117,11 +121,15 @@ static inline int
 elf_core_copy_task_xfpregs(struct task_struct *tsk, elf_fpxregset_t *xfpu)
 {
 	struct ia32_user_fxsr_struct *fpxstate = (void*) xfpu;
+	mm_segment_t old_fs;
 
 	if (!tsk->used_math)
 		return 0;
 
-	save_ia32_fpxstate(tsk, fpxstate);
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	save_ia32_fpxstate(tsk, (struct ia32_user_fxsr_struct __user *) fpxstate);
+	set_fs(old_fs);
 
 	return 1;
 }
diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
index fa3ac962a..4a6319c6d 100644
--- a/arch/ia64/ia32/ia32_entry.S
+++ b/arch/ia64/ia32/ia32_entry.S
@@ -41,7 +41,7 @@ ENTRY(ia32_clone)
 	zxt4 out1=in1				// newsp
 	mov out3=16				// stacksize (compensates for 16-byte scratch area)
 	adds out2=IA64_SWITCH_STACK_SIZE+16,sp	// out2 = &regs
-	dep out0=0,in0,CLONE_IDLETASK_BIT,1	// out0 = clone_flags & ~CLONE_IDLETASK
+	mov out0=in0				// out0 = clone_flags
 	zxt4 out4=in2				// out4 = parent_tidptr
 	zxt4 out5=in4				// out5 = child_tidptr
 	br.call.sptk.many rp=do_fork
@@ -311,7 +311,7 @@ ia32_syscall_table:
 	data8 sys_ni_syscall	  /* old profil syscall holder */
 	data8 compat_sys_statfs
 	data8 compat_sys_fstatfs	  /* 100 */
-	data8 sys32_ioperm
+	data8 sys_ni_syscall	/* ioperm */
 	data8 compat_sys_socketcall
 	data8 sys_syslog
 	data8 compat_sys_setitimer
@@ -320,7 +320,7 @@ ia32_syscall_table:
 	data8 compat_sys_newlstat
 	data8 compat_sys_newfstat
 	data8 sys_ni_syscall
-	data8 sys32_iopl		  /* 110 */
+	data8 sys_ni_syscall	/* iopl */	/* 110 */
 	data8 sys_vhangup
 	data8 sys_ni_syscall		/* used to be sys_idle */
 	data8 sys_ni_syscall
@@ -493,6 +493,8 @@ ia32_syscall_table:
   	data8 compat_sys_mq_timedreceive	/* 280 */
   	data8 compat_sys_mq_notify
   	data8 compat_sys_mq_getsetattr
+	data8 sys_ni_syscall		/* reserved for kexec */
+	data8 sys32_waitid
 
 	// guard against failures to increase IA32_NR_syscalls
 	.org ia32_syscall_table + 8*IA32_NR_syscalls
diff --git a/arch/ia64/ia32/ia32_ldt.c b/arch/ia64/ia32/ia32_ldt.c
index 4cc8242de..a152738c7 100644
--- a/arch/ia64/ia32/ia32_ldt.c
+++ b/arch/ia64/ia32/ia32_ldt.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001 Hewlett-Packard Co
+ * Copyright (C) 2001, 2004 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  *
  * Adapted from arch/i386/kernel/ldt.c
@@ -17,25 +17,24 @@
 
 #include "ia32priv.h"
 
-#define P(p)	((void *) (unsigned long) (p))
-
 /*
  * read_ldt() is not really atomic - this is not a problem since synchronization of reads
  * and writes done to the LDT has to be assured by user-space anyway. Writes are atomic,
  * to protect the security checks done on new descriptors.
  */
 static int
-read_ldt (void *ptr, unsigned long bytecount)
+read_ldt (void __user *ptr, unsigned long bytecount)
 {
-	char *src, *dst, buf[256];	/* temporary buffer (don't overflow kernel stack!) */
 	unsigned long bytes_left, n;
+	char __user *src, *dst;
+	char buf[256];	/* temporary buffer (don't overflow kernel stack!) */
 
 	if (bytecount > IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE)
 		bytecount = IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE;
 
 	bytes_left = bytecount;
 
-	src = (void *) IA32_LDT_OFFSET;
+	src = (void __user *) IA32_LDT_OFFSET;
 	dst = ptr;
 
 	while (bytes_left) {
@@ -61,7 +60,7 @@ read_ldt (void *ptr, unsigned long bytecount)
 }
 
 static int
-read_default_ldt (void * ptr, unsigned long bytecount)
+read_default_ldt (void __user * ptr, unsigned long bytecount)
 {
 	unsigned long size;
 	int err;
@@ -80,7 +79,7 @@ read_default_ldt (void * ptr, unsigned long bytecount)
 }
 
 static int
-write_ldt (void * ptr, unsigned long bytecount, int oldmode)
+write_ldt (void __user * ptr, unsigned long bytecount, int oldmode)
 {
 	struct ia32_user_desc ldt_info;
 	__u64 entry;
@@ -120,7 +119,7 @@ write_ldt (void * ptr, unsigned long bytecount, int oldmode)
 	 * memory, but we still need to guard against out-of-memory, hence we must use
 	 * put_user().
 	 */
-	ret = __put_user(entry, (__u64 *) IA32_LDT_OFFSET + ldt_info.entry_number);
+	ret = __put_user(entry, (__u64 __user *) IA32_LDT_OFFSET + ldt_info.entry_number);
 	ia32_load_segment_descriptors(current);
 	return ret;
 }
@@ -132,16 +131,16 @@ sys32_modify_ldt (int func, unsigned int ptr, unsigned int bytecount)
 
 	switch (func) {
 	      case 0:
-		ret = read_ldt(P(ptr), bytecount);
+		ret = read_ldt(compat_ptr(ptr), bytecount);
 		break;
 	      case 1:
-		ret = write_ldt(P(ptr), bytecount, 1);
+		ret = write_ldt(compat_ptr(ptr), bytecount, 1);
 		break;
 	      case 2:
-		ret = read_default_ldt(P(ptr), bytecount);
+		ret = read_default_ldt(compat_ptr(ptr), bytecount);
 		break;
 	      case 0x11:
-		ret = write_ldt(P(ptr), bytecount, 0);
+		ret = write_ldt(compat_ptr(ptr), bytecount, 0);
 		break;
 	}
 	return ret;
diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c
index 793ec3f76..7f2fc2704 100644
--- a/arch/ia64/ia32/ia32_signal.c
+++ b/arch/ia64/ia32/ia32_signal.c
@@ -66,7 +66,7 @@ struct rt_sigframe_ia32
 };
 
 int
-copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 *from)
+copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 __user *from)
 {
 	unsigned long tmp;
 	int err;
@@ -78,10 +78,10 @@ copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 *from)
 	err |= __get_user(to->si_errno, &from->si_errno);
 	err |= __get_user(to->si_code, &from->si_code);
 
-	if (from->si_code < 0)
+	if (to->si_code < 0)
 		err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
 	else {
-		switch (from->si_code >> 16) {
+		switch (to->si_code >> 16) {
 		      case __SI_CHLD >> 16:
 			err |= __get_user(to->si_utime, &from->si_utime);
 			err |= __get_user(to->si_stime, &from->si_stime);
@@ -92,7 +92,7 @@ copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 *from)
 			break;
 		      case __SI_FAULT >> 16:
 			err |= __get_user(tmp, &from->si_addr);
-			to->si_addr = (void *) tmp;
+			to->si_addr = (void __user *) tmp;
 			break;
 		      case __SI_POLL >> 16:
 			err |= __get_user(to->si_band, &from->si_band);
@@ -110,7 +110,7 @@ copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 *from)
 }
 
 int
-copy_siginfo_to_user32 (siginfo_t32 *to, siginfo_t *from)
+copy_siginfo_to_user32 (siginfo_t32 __user *to, siginfo_t *from)
 {
 	unsigned int addr;
 	int err;
@@ -141,7 +141,8 @@ copy_siginfo_to_user32 (siginfo_t32 *to, siginfo_t *from)
 			err |= __put_user(from->si_uid, &to->si_uid);
 			break;
 		case __SI_FAULT >> 16:
-			err |= __put_user((long)from->si_addr, &to->si_addr);
+			/* avoid type-checking warnings by copying _pad[0] in lieu of si_addr... */
+			err |= __put_user(from->_sifields._pad[0], &to->si_addr);
 			break;
 		case __SI_POLL >> 16:
 			err |= __put_user(from->si_band, &to->si_band);
@@ -202,7 +203,7 @@ copy_siginfo_to_user32 (siginfo_t32 *to, siginfo_t *from)
  */
 
 static int
-save_ia32_fpstate_live (struct _fpstate_ia32 *save)
+save_ia32_fpstate_live (struct _fpstate_ia32 __user *save)
 {
 	struct task_struct *tsk = current;
 	struct pt_regs *ptp;
@@ -310,7 +311,7 @@ save_ia32_fpstate_live (struct _fpstate_ia32 *save)
 }
 
 static int
-restore_ia32_fpstate_live (struct _fpstate_ia32 *save)
+restore_ia32_fpstate_live (struct _fpstate_ia32 __user *save)
 {
 	struct task_struct *tsk = current;
 	struct pt_regs *ptp;
@@ -339,37 +340,37 @@ restore_ia32_fpstate_live (struct _fpstate_ia32 *save)
 	fir = ia64_getreg(_IA64_REG_AR_FIR);
 	fdr = ia64_getreg(_IA64_REG_AR_FDR);
 
-	__get_user(mxcsr, (unsigned int *)&save->mxcsr);
+	__get_user(mxcsr, (unsigned int __user *)&save->mxcsr);
 	/* setting bits 0..5 8..12 with cw and 39..47 from mxcsr */
-	__get_user(lo, (unsigned int *)&save->cw);
+	__get_user(lo, (unsigned int __user *)&save->cw);
 	num64 = mxcsr & 0xff10;
 	num64 = (num64 << 32) | (lo & 0x1f3f);
-	fcr = (fcr & (~0xff1000001f3f)) | num64;
+	fcr = (fcr & (~0xff1000001f3fUL)) | num64;
 
 	/* setting bits 0..31 with sw and tag and 32..37 from mxcsr */
-	__get_user(lo, (unsigned int *)&save->sw);
+	__get_user(lo, (unsigned int __user *)&save->sw);
 	/* set bits 15,7 (fsw.b, fsw.es) to reflect the current error status */
 	if ( !(lo & 0x7f) )
 		lo &= (~0x8080);
-	__get_user(hi, (unsigned int *)&save->tag);
+	__get_user(hi, (unsigned int __user *)&save->tag);
 	num64 = mxcsr & 0x3f;
 	num64 = (num64 << 16) | (hi & 0xffff);
 	num64 = (num64 << 16) | (lo & 0xffff);
-	fsr = (fsr & (~0x3fffffffff)) | num64;
+	fsr = (fsr & (~0x3fffffffffUL)) | num64;
 
 	/* setting bits 0..47 with cssel and ipoff */
-	__get_user(lo, (unsigned int *)&save->ipoff);
-	__get_user(hi, (unsigned int *)&save->cssel);
+	__get_user(lo, (unsigned int __user *)&save->ipoff);
+	__get_user(hi, (unsigned int __user *)&save->cssel);
 	num64 = hi & 0xffff;
 	num64 = (num64 << 32) | lo;
-	fir = (fir & (~0xffffffffffff)) | num64;
+	fir = (fir & (~0xffffffffffffUL)) | num64;
 
 	/* setting bits 0..47 with datasel and dataoff */
-	__get_user(lo, (unsigned int *)&save->dataoff);
-	__get_user(hi, (unsigned int *)&save->datasel);
+	__get_user(lo, (unsigned int __user *)&save->dataoff);
+	__get_user(hi, (unsigned int __user *)&save->datasel);
 	num64 = hi & 0xffff;
 	num64 = (num64 << 32) | lo;
-	fdr = (fdr & (~0xffffffffffff)) | num64;
+	fdr = (fdr & (~0xffffffffffffUL)) | num64;
 
 	ia64_setreg(_IA64_REG_AR_FSR, fsr);
 	ia64_setreg(_IA64_REG_AR_FCR, fcr);
@@ -452,8 +453,8 @@ sigact_set_handler (struct k_sigaction *sa, unsigned int handler, unsigned int r
 		sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler);
 }
 
-asmlinkage long
-ia32_rt_sigsuspend (compat_sigset_t *uset, unsigned int sigsetsize, struct sigscratch *scr)
+long
+__ia32_rt_sigsuspend (compat_sigset_t *sset, unsigned int sigsetsize, struct sigscratch *scr)
 {
 	extern long ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall);
 	sigset_t oldset, set;
@@ -461,10 +462,7 @@ ia32_rt_sigsuspend (compat_sigset_t *uset, unsigned int sigsetsize, struct sigsc
 	scr->scratch_unat = 0;	/* avoid leaking kernel bits to user level */
 	memset(&set, 0, sizeof(&set));
 
-	if (sigsetsize > sizeof(sigset_t))
-		return -EINVAL;
-
-	if (copy_from_user(&set.sig, &uset->sig, sigsetsize))
+	if (memcpy(&set.sig, &sset->sig, sigsetsize))
 		return -EFAULT;
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
@@ -491,10 +489,24 @@ ia32_rt_sigsuspend (compat_sigset_t *uset, unsigned int sigsetsize, struct sigsc
 	}
 }
 
+asmlinkage long
+ia32_rt_sigsuspend (compat_sigset_t __user *uset, unsigned int sigsetsize, struct sigscratch *scr)
+{
+	compat_sigset_t set;
+
+	if (sigsetsize > sizeof(compat_sigset_t))
+		return -EINVAL;
+
+	if (copy_from_user(&set.sig, &uset->sig, sigsetsize))
+		return -EFAULT;
+
+	return __ia32_rt_sigsuspend(&set, sigsetsize, scr);
+}
+
 asmlinkage long
 ia32_sigsuspend (unsigned int mask, struct sigscratch *scr)
 {
-	return ia32_rt_sigsuspend((compat_sigset_t *)&mask, sizeof(mask), scr);
+	return __ia32_rt_sigsuspend((compat_sigset_t *) &mask, sizeof(mask), scr);
 }
 
 asmlinkage long
@@ -512,8 +524,8 @@ sys32_signal (int sig, unsigned int handler)
 }
 
 asmlinkage long
-sys32_rt_sigaction (int sig, struct sigaction32 *act,
-		    struct sigaction32 *oact, unsigned int sigsetsize)
+sys32_rt_sigaction (int sig, struct sigaction32 __user *act,
+		    struct sigaction32 __user *oact, unsigned int sigsetsize)
 {
 	struct k_sigaction new_ka, old_ka;
 	unsigned int handler, restorer;
@@ -547,7 +559,8 @@ sys32_rt_sigaction (int sig, struct sigaction32 *act,
 
 
 asmlinkage long
-sys32_rt_sigprocmask (int how, compat_sigset_t *set, compat_sigset_t *oset, unsigned int sigsetsize)
+sys32_rt_sigprocmask (int how, compat_sigset_t __user *set, compat_sigset_t __user *oset,
+		      unsigned int sigsetsize)
 {
 	mm_segment_t old_fs = get_fs();
 	sigset_t s;
@@ -562,7 +575,9 @@ sys32_rt_sigprocmask (int how, compat_sigset_t *set, compat_sigset_t *oset, unsi
 			return -EFAULT;
 	}
 	set_fs(KERNEL_DS);
-	ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL, sizeof(s));
+	ret = sys_rt_sigprocmask(how,
+				 set ? (sigset_t __user *) &s : NULL,
+				 oset ? (sigset_t __user *) &s : NULL, sizeof(s));
 	set_fs(old_fs);
 	if (ret)
 		return ret;
@@ -574,10 +589,9 @@ sys32_rt_sigprocmask (int how, compat_sigset_t *set, compat_sigset_t *oset, unsi
 }
 
 asmlinkage long
-sys32_rt_sigtimedwait (compat_sigset_t *uthese, siginfo_t32 *uinfo,
-		struct compat_timespec *uts, unsigned int sigsetsize)
+sys32_rt_sigtimedwait (compat_sigset_t __user *uthese, siginfo_t32 __user *uinfo,
+		       struct compat_timespec __user *uts, unsigned int sigsetsize)
 {
-	extern int copy_siginfo_to_user32 (siginfo_t32 *, siginfo_t *);
 	mm_segment_t old_fs = get_fs();
 	struct timespec t;
 	siginfo_t info;
@@ -589,8 +603,10 @@ sys32_rt_sigtimedwait (compat_sigset_t *uthese, siginfo_t32 *uinfo,
 	if (uts && get_compat_timespec(&t, uts))
 		return -EFAULT;
 	set_fs(KERNEL_DS);
-	ret = sys_rt_sigtimedwait(&s, uinfo ? &info : NULL, uts ? &t : NULL,
-			sigsetsize);
+	ret = sys_rt_sigtimedwait((sigset_t __user *) &s,
+				  uinfo ? (siginfo_t __user *) &info : NULL,
+				  uts ? (struct timespec __user *) &t : NULL,
+				  sigsetsize);
 	set_fs(old_fs);
 	if (ret >= 0 && uinfo) {
 		if (copy_siginfo_to_user32(uinfo, &info))
@@ -600,7 +616,7 @@ sys32_rt_sigtimedwait (compat_sigset_t *uthese, siginfo_t32 *uinfo,
 }
 
 asmlinkage long
-sys32_rt_sigqueueinfo (int pid, int sig, siginfo_t32 *uinfo)
+sys32_rt_sigqueueinfo (int pid, int sig, siginfo_t32 __user *uinfo)
 {
 	mm_segment_t old_fs = get_fs();
 	siginfo_t info;
@@ -609,13 +625,13 @@ sys32_rt_sigqueueinfo (int pid, int sig, siginfo_t32 *uinfo)
 	if (copy_siginfo_from_user32(&info, uinfo))
 		return -EFAULT;
 	set_fs(KERNEL_DS);
-	ret = sys_rt_sigqueueinfo(pid, sig, &info);
+	ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);
 	set_fs(old_fs);
 	return ret;
 }
 
 asmlinkage long
-sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact)
+sys32_sigaction (int sig, struct old_sigaction32 __user *act, struct old_sigaction32 __user *oact)
 {
 	struct k_sigaction new_ka, old_ka;
 	unsigned int handler, restorer;
@@ -648,7 +664,7 @@ sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *o
 }
 
 static int
-setup_sigcontext_ia32 (struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate,
+setup_sigcontext_ia32 (struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __user *fpstate,
 		       struct pt_regs *regs, unsigned long mask)
 {
 	int  err = 0;
@@ -657,10 +673,10 @@ setup_sigcontext_ia32 (struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate
 	if (!access_ok(VERIFY_WRITE, sc, sizeof(*sc)))
 		return -EFAULT;
 
-	err |= __put_user((regs->r16 >> 32) & 0xffff, (unsigned int *)&sc->fs);
-	err |= __put_user((regs->r16 >> 48) & 0xffff, (unsigned int *)&sc->gs);
-	err |= __put_user((regs->r16 >> 16) & 0xffff, (unsigned int *)&sc->es);
-	err |= __put_user(regs->r16 & 0xffff, (unsigned int *)&sc->ds);
+	err |= __put_user((regs->r16 >> 32) & 0xffff, (unsigned int __user *)&sc->fs);
+	err |= __put_user((regs->r16 >> 48) & 0xffff, (unsigned int __user *)&sc->gs);
+	err |= __put_user((regs->r16 >> 16) & 0xffff, (unsigned int __user *)&sc->es);
+	err |= __put_user(regs->r16 & 0xffff, (unsigned int __user *)&sc->ds);
 	err |= __put_user(regs->r15, &sc->edi);
 	err |= __put_user(regs->r14, &sc->esi);
 	err |= __put_user(regs->r13, &sc->ebp);
@@ -674,14 +690,14 @@ setup_sigcontext_ia32 (struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate
 	err |= __put_user(current->tss.error_code, &sc->err);
 #endif
 	err |= __put_user(regs->cr_iip, &sc->eip);
-	err |= __put_user(regs->r17 & 0xffff, (unsigned int *)&sc->cs);
+	err |= __put_user(regs->r17 & 0xffff, (unsigned int __user *)&sc->cs);
 	/*
 	 *  `eflags' is in an ar register for this context
 	 */
 	flag = ia64_getreg(_IA64_REG_AR_EFLAG);
 	err |= __put_user((unsigned int)flag, &sc->eflags);
 	err |= __put_user(regs->r12, &sc->esp_at_signal);
-	err |= __put_user((regs->r17 >> 16) & 0xffff, (unsigned int *)&sc->ss);
+	err |= __put_user((regs->r17 >> 16) & 0xffff, (unsigned int __user *)&sc->ss);
 
 	if ( save_ia32_fpstate_live(fpstate) < 0 )
 		err = -EFAULT;
@@ -705,7 +721,7 @@ setup_sigcontext_ia32 (struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate
 }
 
 static int
-restore_sigcontext_ia32 (struct pt_regs *regs, struct sigcontext_ia32 *sc, int *peax)
+restore_sigcontext_ia32 (struct pt_regs *regs, struct sigcontext_ia32 __user *sc, int *peax)
 {
 	unsigned int err = 0;
 
@@ -775,10 +791,10 @@ restore_sigcontext_ia32 (struct pt_regs *regs, struct sigcontext_ia32 *sc, int *
 	}
 
 	{
-		struct _fpstate_ia32 *buf = NULL;
+		struct _fpstate_ia32 __user *buf = NULL;
 		u32    fpstate_ptr;
 		err |= get_user(fpstate_ptr, &(sc->fpstate));
-		buf = (struct _fpstate_ia32 *)(u64)fpstate_ptr;
+		buf = compat_ptr(fpstate_ptr);
 		if (buf) {
 			err |= restore_ia32_fpstate_live(buf);
 		}
@@ -808,7 +824,7 @@ restore_sigcontext_ia32 (struct pt_regs *regs, struct sigcontext_ia32 *sc, int *
 /*
  * Determine which stack to use..
  */
-static inline void *
+static inline void __user *
 get_sigframe (struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
 {
 	unsigned long esp;
@@ -823,14 +839,14 @@ get_sigframe (struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
 	}
 	/* Legacy stack switching not supported */
 
-	return (void *)((esp - frame_size) & -8ul);
+	return (void __user *)((esp - frame_size) & -8ul);
 }
 
 static int
 setup_frame_ia32 (int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs)
 {
 	struct exec_domain *ed = current_thread_info()->exec_domain;
-	struct sigframe_ia32 *frame;
+	struct sigframe_ia32 __user *frame;
 	int err = 0;
 
 	frame = get_sigframe(ka, regs, sizeof(*frame));
@@ -853,14 +869,19 @@ setup_frame_ia32 (int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs
 		unsigned int restorer = IA32_SA_RESTORER(ka);
 		err |= __put_user(restorer, &frame->pretcode);
 	} else {
-		err |= __put_user((long)frame->retcode, &frame->pretcode);
-		/* This is popl %eax ; movl $,%eax ; int $0x80 */
-		err |= __put_user(0xb858, (short *)(frame->retcode+0));
-		err |= __put_user(__IA32_NR_sigreturn & 0xffff, (short *)(frame->retcode+2));
-		err |= __put_user(__IA32_NR_sigreturn >> 16, (short *)(frame->retcode+4));
-		err |= __put_user(0x80cd, (short *)(frame->retcode+6));
+		/* Pointing to restorer in ia32 gate page */
+		err |= __put_user(IA32_GATE_OFFSET, &frame->pretcode);
 	}
 
+	/* This is popl %eax ; movl $,%eax ; int $0x80
+	 * and there for historical reasons only.
+	 * See arch/i386/kernel/signal.c
+	 */
+
+	err |= __put_user(0xb858, (short __user *)(frame->retcode+0));
+	err |= __put_user(__IA32_NR_sigreturn, (int __user *)(frame->retcode+2));
+	err |= __put_user(0x80cd, (short __user *)(frame->retcode+6));
+
 	if (err)
 		goto give_sigsegv;
 
@@ -882,9 +903,7 @@ setup_frame_ia32 (int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs
 	return 1;
 
   give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 	return 0;
 }
 
@@ -893,7 +912,8 @@ setup_rt_frame_ia32 (int sig, struct k_sigaction *ka, siginfo_t *info,
 		     sigset_t *set, struct pt_regs * regs)
 {
 	struct exec_domain *ed = current_thread_info()->exec_domain;
-	struct rt_sigframe_ia32 *frame;
+	compat_uptr_t pinfo, puc;
+	struct rt_sigframe_ia32 __user *frame;
 	int err = 0;
 
 	frame = get_sigframe(ka, regs, sizeof(*frame));
@@ -903,8 +923,11 @@ setup_rt_frame_ia32 (int sig, struct k_sigaction *ka, siginfo_t *info,
 
 	err |= __put_user((ed && ed->signal_invmap
 			   && sig < 32 ? ed->signal_invmap[sig] : sig), &frame->sig);
-	err |= __put_user((long)&frame->info, &frame->pinfo);
-	err |= __put_user((long)&frame->uc, &frame->puc);
+
+	pinfo = (long __user) &frame->info;
+	puc = (long __user) &frame->uc;
+	err |= __put_user(pinfo, &frame->pinfo);
+	err |= __put_user(puc, &frame->puc);
 	err |= copy_siginfo_to_user32(&frame->info, info);
 
 	/* Create the ucontext.  */
@@ -924,13 +947,19 @@ setup_rt_frame_ia32 (int sig, struct k_sigaction *ka, siginfo_t *info,
 		unsigned int restorer = IA32_SA_RESTORER(ka);
 		err |= __put_user(restorer, &frame->pretcode);
 	} else {
-		err |= __put_user((long)frame->retcode, &frame->pretcode);
-		/* This is movl $,%eax ; int $0x80 */
-		err |= __put_user(0xb8, (char *)(frame->retcode+0));
-		err |= __put_user(__IA32_NR_rt_sigreturn, (int *)(frame->retcode+1));
-		err |= __put_user(0x80cd, (short *)(frame->retcode+5));
+		/* Pointing to rt_restorer in ia32 gate page */
+		err |= __put_user(IA32_GATE_OFFSET + 8, &frame->pretcode);
 	}
 
+	/* This is movl $,%eax ; int $0x80
+	 * and there for historical reasons only.
+	 * See arch/i386/kernel/signal.c
+	 */
+
+	err |= __put_user(0xb8, (char __user *)(frame->retcode+0));
+	err |= __put_user(__IA32_NR_rt_sigreturn, (int __user *)(frame->retcode+1));
+	err |= __put_user(0x80cd, (short __user *)(frame->retcode+5));
+
 	if (err)
 		goto give_sigsegv;
 
@@ -952,9 +981,7 @@ setup_rt_frame_ia32 (int sig, struct k_sigaction *ka, siginfo_t *info,
 	return 1;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 	return 0;
 }
 
@@ -975,7 +1002,7 @@ sys32_sigreturn (int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int
 {
 	struct pt_regs *regs = (struct pt_regs *) &stack;
 	unsigned long esp = (unsigned int) regs->r12;
-	struct sigframe_ia32 *frame = (struct sigframe_ia32 *)(esp - 8);
+	struct sigframe_ia32 __user *frame = (struct sigframe_ia32 __user *)(esp - 8);
 	sigset_t set;
 	int eax;
 
@@ -989,7 +1016,7 @@ sys32_sigreturn (int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = (sigset_t) set;
+	current->blocked = set;
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
@@ -1008,9 +1035,8 @@ sys32_rt_sigreturn (int arg0, int arg1, int arg2, int arg3, int arg4, int arg5,
 {
 	struct pt_regs *regs = (struct pt_regs *) &stack;
 	unsigned long esp = (unsigned int) regs->r12;
-	struct rt_sigframe_ia32 *frame = (struct rt_sigframe_ia32 *)(esp - 4);
+	struct rt_sigframe_ia32 __user *frame = (struct rt_sigframe_ia32 __user *)(esp - 4);
 	sigset_t set;
-	stack_t st;
 	int eax;
 
 	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
@@ -1027,11 +1053,9 @@ sys32_rt_sigreturn (int arg0, int arg1, int arg2, int arg3, int arg4, int arg5,
 	if (restore_sigcontext_ia32(regs, &frame->uc.uc_mcontext, &eax))
 		goto badframe;
 
-	if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
-		goto badframe;
 	/* It is more difficult to avoid calling this function than to
 	   call it and ignore errors.  */
-	do_sigaltstack(&st, NULL, esp);
+	do_sigaltstack((stack_t __user *) &frame->uc.uc_stack, NULL, esp);
 
 	return eax;
 
diff --git a/arch/ia64/ia32/ia32_support.c b/arch/ia64/ia32/ia32_support.c
index 4b43f1753..4f630043b 100644
--- a/arch/ia64/ia32/ia32_support.c
+++ b/arch/ia64/ia32/ia32_support.c
@@ -33,6 +33,7 @@ struct exec_domain ia32_exec_domain;
 struct page *ia32_shared_page[NR_CPUS];
 unsigned long *ia32_boot_gdt;
 unsigned long *cpu_gdt_table[NR_CPUS];
+struct page *ia32_gate_page;
 
 static unsigned long
 load_desc (u16 selector)
@@ -75,7 +76,7 @@ ia32_clone_tls (struct task_struct *child, struct pt_regs *childregs)
 	struct ia32_user_desc info;
 	int idx;
 
-	if (copy_from_user(&info, (void *)(childregs->r14 & 0xffffffff), sizeof(info)))
+	if (copy_from_user(&info, (void __user *)(childregs->r14 & 0xffffffff), sizeof(info)))
 		return -EFAULT;
 	if (LDT_empty(&info))
 		return -EINVAL;
@@ -145,6 +146,9 @@ ia32_gdt_init (void)
 	int cpu = smp_processor_id();
 
 	ia32_shared_page[cpu] = alloc_page(GFP_KERNEL);
+	if (!ia32_shared_page[cpu])
+		panic("failed to allocate ia32_shared_page[%d]\n", cpu);
+
 	cpu_gdt_table[cpu] = page_address(ia32_shared_page[cpu]);
 
 	/* Copy from the boot cpu's GDT */
@@ -155,23 +159,26 @@ ia32_gdt_init (void)
 /*
  * Setup IA32 GDT and TSS
  */
-void
+static void
 ia32_boot_gdt_init (void)
 {
 	unsigned long ldt_size;
 
 	ia32_shared_page[0] = alloc_page(GFP_KERNEL);
+	if (!ia32_shared_page[0])
+		panic("failed to allocate ia32_shared_page[0]\n");
+
 	ia32_boot_gdt = page_address(ia32_shared_page[0]);
 	cpu_gdt_table[0] = ia32_boot_gdt;
 
 	/* CS descriptor in IA-32 (scrambled) format */
 	ia32_boot_gdt[__USER_CS >> 3]
-		= IA32_SEG_DESCRIPTOR(0, (IA32_PAGE_OFFSET-1) >> IA32_PAGE_SHIFT,
+		= IA32_SEG_DESCRIPTOR(0, (IA32_GATE_END-1) >> IA32_PAGE_SHIFT,
 				      0xb, 1, 3, 1, 1, 1, 1);
 
 	/* DS descriptor in IA-32 (scrambled) format */
 	ia32_boot_gdt[__USER_DS >> 3]
-		= IA32_SEG_DESCRIPTOR(0, (IA32_PAGE_OFFSET-1) >> IA32_PAGE_SHIFT,
+		= IA32_SEG_DESCRIPTOR(0, (IA32_GATE_END-1) >> IA32_PAGE_SHIFT,
 				      0x3, 1, 3, 1, 1, 1, 1);
 
 	ldt_size = PAGE_ALIGN(IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE);
@@ -181,6 +188,27 @@ ia32_boot_gdt_init (void)
 						       0x2, 0, 3, 1, 1, 1, 0);
 }
 
+static void
+ia32_gate_page_init(void)
+{
+	unsigned long *sr;
+
+	ia32_gate_page = alloc_page(GFP_KERNEL);
+	sr = page_address(ia32_gate_page);
+	/* This is popl %eax ; movl $,%eax ; int $0x80 */
+	*sr++ = 0xb858 | (__IA32_NR_sigreturn << 16) | (0x80cdUL << 48);
+
+	/* This is movl $,%eax ; int $0x80 */
+	*sr = 0xb8 | (__IA32_NR_rt_sigreturn << 8) | (0x80cdUL << 40);
+}
+
+void
+ia32_mem_init(void)
+{
+	ia32_boot_gdt_init();
+	ia32_gate_page_init();
+}
+
 /*
  * Handle bad IA32 interrupt via syscall
  */
@@ -195,7 +223,7 @@ ia32_bad_interrupt (unsigned long int_num, struct pt_regs *regs)
 	siginfo.si_errno = int_num;	/* XXX is it OK to abuse si_errno like this? */
 	siginfo.si_flags = 0;
 	siginfo.si_isr = 0;
-	siginfo.si_addr = 0;
+	siginfo.si_addr = NULL;
 	siginfo.si_imm = 0;
 	siginfo.si_code = TRAP_BRKPT;
 	force_sig_info(SIGTRAP, &siginfo, current);
diff --git a/arch/ia64/ia32/ia32priv.h b/arch/ia64/ia32/ia32priv.h
index ba875e0bb..59c500b23 100644
--- a/arch/ia64/ia32/ia32priv.h
+++ b/arch/ia64/ia32/ia32priv.h
@@ -168,6 +168,9 @@ struct ia32_user_fxsr_struct {
 #define IA32_SA_HANDLER(ka)	((unsigned long) (ka)->sa.sa_handler & 0xffffffff)
 #define IA32_SA_RESTORER(ka)	((unsigned long) (ka)->sa.sa_handler >> 32)
 
+#define __IA32_NR_sigreturn 119
+#define __IA32_NR_rt_sigreturn 173
+
 struct sigaction32 {
        unsigned int sa_handler;		/* Really a pointer, but need to deal with 32 bits */
        unsigned int sa_flags;
@@ -324,14 +327,16 @@ struct old_linux32_dirent {
 
 #define IA32_PAGE_OFFSET	0xc0000000
 #define IA32_STACK_TOP		IA32_PAGE_OFFSET
+#define IA32_GATE_OFFSET	IA32_PAGE_OFFSET
+#define IA32_GATE_END		IA32_PAGE_OFFSET + PAGE_SIZE
 
 /*
  * The system segments (GDT, TSS, LDT) have to be mapped below 4GB so the IA-32 engine can
  * access them.
  */
-#define IA32_GDT_OFFSET		(IA32_PAGE_OFFSET)
-#define IA32_TSS_OFFSET		(IA32_PAGE_OFFSET + PAGE_SIZE)
-#define IA32_LDT_OFFSET		(IA32_PAGE_OFFSET + 2*PAGE_SIZE)
+#define IA32_GDT_OFFSET		(IA32_PAGE_OFFSET + PAGE_SIZE)
+#define IA32_TSS_OFFSET		(IA32_PAGE_OFFSET + 2*PAGE_SIZE)
+#define IA32_LDT_OFFSET		(IA32_PAGE_OFFSET + 3*PAGE_SIZE)
 
 #define ELF_EXEC_PAGESIZE	IA32_PAGE_SIZE
 
@@ -356,7 +361,7 @@ void ia64_elf32_init(struct pt_regs *regs);
 /* This macro yields a string that ld.so will use to load
    implementation specific libraries for optimization.  Not terribly
    relevant until we have real hardware to play with... */
-#define ELF_PLATFORM	0
+#define ELF_PLATFORM	NULL
 
 #ifdef __KERNEL__
 # define SET_PERSONALITY(EX,IBCS2)				\
@@ -434,7 +439,7 @@ void ia64_elf32_init(struct pt_regs *regs);
 	 | ((((sd) >> IA32_SEG_DB) & 0x1) << SEG_DB)						 \
 	 | ((((sd) >> IA32_SEG_G) & 0x1) << SEG_G))
 
-#define IA32_IOBASE	0x2000000000000000 /* Virtual address for I/O space */
+#define IA32_IOBASE	0x2000000000000000UL /* Virtual address for I/O space */
 
 #define IA32_CR0	0x80000001	/* Enable PG and PE bits */
 #define IA32_CR4	0x600		/* MMXEX and FXSR on */
@@ -551,8 +556,8 @@ struct user_regs_struct32 {
 };
 
 /* Prototypes for use in elfcore32.h */
-extern int save_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct *save);
-extern int save_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct *save);
+extern int save_ia32_fpstate (struct task_struct *, struct ia32_user_i387_struct __user *);
+extern int save_ia32_fpxstate (struct task_struct *, struct ia32_user_fxsr_struct __user *);
 
 #endif /* !CONFIG_IA32_SUPPORT */
 
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index a97402c01..1b653dadb 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -70,10 +70,7 @@
 # define DBG(fmt...)
 #endif
 
-#define A(__x)		((unsigned long)(__x))
-#define AA(__x)		((unsigned long)(__x))
 #define ROUND_UP(x,a)	((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1)))
-#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
 
 #define OFFSET4K(a)		((a) & 0xfff)
 #define PAGE_START(addr)	((addr) & PAGE_MASK)
@@ -82,9 +79,6 @@
 #define high2lowuid(uid) ((uid) > 65535 ? 65534 : (uid))
 #define high2lowgid(gid) ((gid) > 65535 ? 65534 : (gid))
 
-extern unsigned long arch_get_unmapped_area (struct file *, unsigned long, unsigned long,
-					     unsigned long, unsigned long);
-
 /*
  * Anything that modifies or inspects ia32 user virtual memory must hold this semaphore
  * while doing so.
@@ -93,7 +87,8 @@ extern unsigned long arch_get_unmapped_area (struct file *, unsigned long, unsig
 static DECLARE_MUTEX(ia32_mmap_sem);
 
 asmlinkage long
-sys32_execve (char *name, compat_uptr_t __user *argv, compat_uptr_t __user *envp, struct pt_regs *regs)
+sys32_execve (char __user *name, compat_uptr_t __user *argv, compat_uptr_t __user *envp,
+	      struct pt_regs *regs)
 {
 	long error;
 	char *filename;
@@ -128,7 +123,7 @@ sys32_execve (char *name, compat_uptr_t __user *argv, compat_uptr_t __user *envp
 	return error;
 }
 
-int cp_compat_stat(struct kstat *stat, struct compat_stat *ubuf)
+int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf)
 {
 	int err;
 
@@ -199,7 +194,7 @@ mmap_subpage (struct file *file, unsigned long start, unsigned long end, int pro
 
 	/* Optimize the case where the old mmap and the new mmap are both anonymous */
 	if ((old_prot & PROT_WRITE) && (flags & MAP_ANONYMOUS) && !vma->vm_file) {
-		if (clear_user((void *) start, end - start)) {
+		if (clear_user((void __user *) start, end - start)) {
 			ret = -EFAULT;
 			goto out;
 		}
@@ -211,11 +206,11 @@ mmap_subpage (struct file *file, unsigned long start, unsigned long end, int pro
 		return -ENOMEM;
 
 	if (old_prot)
-		copy_from_user(page, (void *) PAGE_START(start), PAGE_SIZE);
+		copy_from_user(page, (void __user *) PAGE_START(start), PAGE_SIZE);
 
 	down_write(&current->mm->mmap_sem);
 	{
-		ret = do_mmap(0, PAGE_START(start), PAGE_SIZE, prot | PROT_WRITE,
+		ret = do_mmap(NULL, PAGE_START(start), PAGE_SIZE, prot | PROT_WRITE,
 			      flags | MAP_FIXED | MAP_ANONYMOUS, 0);
 	}
 	up_write(&current->mm->mmap_sem);
@@ -226,9 +221,10 @@ mmap_subpage (struct file *file, unsigned long start, unsigned long end, int pro
 	if (old_prot) {
 		/* copy back the old page contents.  */
 		if (offset_in_page(start))
-			copy_to_user((void *) PAGE_START(start), page, offset_in_page(start));
+			copy_to_user((void __user *) PAGE_START(start), page,
+				     offset_in_page(start));
 		if (offset_in_page(end))
-			copy_to_user((void *) end, page + offset_in_page(end),
+			copy_to_user((void __user *) end, page + offset_in_page(end),
 				     PAGE_SIZE - offset_in_page(end));
 	}
 
@@ -236,7 +232,7 @@ mmap_subpage (struct file *file, unsigned long start, unsigned long end, int pro
 		/* read the file contents */
 		inode = file->f_dentry->d_inode;
 		if (!inode->i_fop || !file->f_op->read
-		    || ((*file->f_op->read)(file, (char *) start, end - start, &off) < 0))
+		    || ((*file->f_op->read)(file, (char __user *) start, end - start, &off) < 0))
 		{
 			ret = -EINVAL;
 			goto out;
@@ -266,9 +262,9 @@ ia32_init_pp_list(void)
 
 	if ((p = kmalloc(sizeof(*p), GFP_KERNEL)) == NULL)
 		return p;
-	p->pp_head = 0;
+	p->pp_head = NULL;
 	p->ppl_rb = RB_ROOT;
-	p->pp_hint = 0;
+	p->pp_hint = NULL;
 	atomic_set(&p->pp_count, 1);
 	return p;
 }
@@ -825,7 +821,7 @@ emulate_mmap (struct file *file, unsigned long start, unsigned long len, int pro
 		if (!(flags & MAP_ANONYMOUS) && is_congruent)
 			ret = do_mmap(file, pstart, pend - pstart, prot, flags | MAP_FIXED, poff);
 		else
-			ret = do_mmap(0, pstart, pend - pstart,
+			ret = do_mmap(NULL, pstart, pend - pstart,
 				      prot | ((flags & MAP_ANONYMOUS) ? 0 : PROT_WRITE),
 				      flags | MAP_FIXED | MAP_ANONYMOUS, 0);
 	}
@@ -838,7 +834,8 @@ emulate_mmap (struct file *file, unsigned long start, unsigned long len, int pro
 		/* read the file contents */
 		inode = file->f_dentry->d_inode;
 		if (!inode->i_fop || !file->f_op->read
-		    || ((*file->f_op->read)(file, (char *) pstart, pend - pstart, &poff) < 0))
+		    || ((*file->f_op->read)(file, (char __user *) pstart, pend - pstart, &poff)
+			< 0))
 		{
 			sys_munmap(pstart, pend - pstart);
 			return -EINVAL;
@@ -927,7 +924,7 @@ struct mmap_arg_struct {
 };
 
 asmlinkage long
-sys32_mmap (struct mmap_arg_struct *arg)
+sys32_mmap (struct mmap_arg_struct __user *arg)
 {
 	struct mmap_arg_struct a;
 	struct file *file = NULL;
@@ -1140,7 +1137,7 @@ sys32_mremap (unsigned int addr, unsigned int old_len, unsigned int new_len,
 }
 
 asmlinkage long
-sys32_pipe (int *fd)
+sys32_pipe (int __user *fd)
 {
 	int retval;
 	int fds[2];
@@ -1155,14 +1152,14 @@ sys32_pipe (int *fd)
 }
 
 static inline long
-get_tv32 (struct timeval *o, struct compat_timeval *i)
+get_tv32 (struct timeval *o, struct compat_timeval __user *i)
 {
 	return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
 		(__get_user(o->tv_sec, &i->tv_sec) | __get_user(o->tv_usec, &i->tv_usec)));
 }
 
 static inline long
-put_tv32 (struct compat_timeval *o, struct timeval *i)
+put_tv32 (struct compat_timeval __user *o, struct timeval *i)
 {
 	return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
 		(__put_user(i->tv_sec, &o->tv_sec) | __put_user(i->tv_usec, &o->tv_usec)));
@@ -1192,7 +1189,7 @@ sys32_alarm (unsigned int seconds)
 extern struct timezone sys_tz;
 
 asmlinkage long
-sys32_gettimeofday (struct compat_timeval *tv, struct timezone *tz)
+sys32_gettimeofday (struct compat_timeval __user *tv, struct timezone __user *tz)
 {
 	if (tv) {
 		struct timeval ktv;
@@ -1208,7 +1205,7 @@ sys32_gettimeofday (struct compat_timeval *tv, struct timezone *tz)
 }
 
 asmlinkage long
-sys32_settimeofday (struct compat_timeval *tv, struct timezone *tz)
+sys32_settimeofday (struct compat_timeval __user *tv, struct timezone __user *tz)
 {
 	struct timeval ktv;
 	struct timespec kts;
@@ -1229,14 +1226,14 @@ sys32_settimeofday (struct compat_timeval *tv, struct timezone *tz)
 }
 
 struct getdents32_callback {
-	struct compat_dirent * current_dir;
-	struct compat_dirent * previous;
+	struct compat_dirent __user *current_dir;
+	struct compat_dirent __user *previous;
 	int count;
 	int error;
 };
 
 struct readdir32_callback {
-	struct old_linux32_dirent * dirent;
+	struct old_linux32_dirent __user * dirent;
 	int count;
 };
 
@@ -1244,9 +1241,9 @@ static int
 filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino,
 	   unsigned int d_type)
 {
-	struct compat_dirent * dirent;
+	struct compat_dirent __user * dirent;
 	struct getdents32_callback * buf = (struct getdents32_callback *) __buf;
-	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1, 4);
+	int reclen = ROUND_UP(offsetof(struct compat_dirent, d_name) + namlen + 1, 4);
 
 	buf->error = -EINVAL;	/* only used if we fail.. */
 	if (reclen > buf->count)
@@ -1263,17 +1260,17 @@ filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino,
 	    || copy_to_user(dirent->d_name, name, namlen)
 	    || put_user(0, dirent->d_name + namlen))
 		return -EFAULT;
-	dirent = (struct compat_dirent *) ((char *) dirent + reclen);
+	dirent = (struct compat_dirent __user *) ((char __user *) dirent + reclen);
 	buf->current_dir = dirent;
 	buf->count -= reclen;
 	return 0;
 }
 
 asmlinkage long
-sys32_getdents (unsigned int fd, struct compat_dirent *dirent, unsigned int count)
+sys32_getdents (unsigned int fd, struct compat_dirent __user *dirent, unsigned int count)
 {
 	struct file * file;
-	struct compat_dirent * lastdirent;
+	struct compat_dirent __user * lastdirent;
 	struct getdents32_callback buf;
 	int error;
 
@@ -1310,7 +1307,7 @@ fillonedir32 (void * __buf, const char * name, int namlen, loff_t offset, ino_t
 	      unsigned int d_type)
 {
 	struct readdir32_callback * buf = (struct readdir32_callback *) __buf;
-	struct old_linux32_dirent * dirent;
+	struct old_linux32_dirent __user * dirent;
 
 	if (buf->count)
 		return -EINVAL;
@@ -1326,7 +1323,7 @@ fillonedir32 (void * __buf, const char * name, int namlen, loff_t offset, ino_t
 }
 
 asmlinkage long
-sys32_readdir (unsigned int fd, void *dirent, unsigned int count)
+sys32_readdir (unsigned int fd, void __user *dirent, unsigned int count)
 {
 	int error;
 	struct file * file;
@@ -1357,7 +1354,7 @@ struct sel_arg_struct {
 };
 
 asmlinkage long
-sys32_old_select (struct sel_arg_struct *arg)
+sys32_old_select (struct sel_arg_struct __user *arg)
 {
 	struct sel_arg_struct a;
 
@@ -1434,7 +1431,7 @@ sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth)
  * so we have to implement this system call here.
  */
 asmlinkage long
-sys32_time (int *tloc)
+sys32_time (int __user *tloc)
 {
 	int i;
 	struct timeval tv;
@@ -1564,8 +1561,8 @@ putreg (struct task_struct *child, int regno, unsigned int value)
 }
 
 static void
-put_fpreg (int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp,
-	   int tos)
+put_fpreg (int regno, struct _fpreg_ia32 __user *reg, struct pt_regs *ptp,
+	   struct switch_stack *swp, int tos)
 {
 	struct _fpreg_ia32 *f;
 	char buf[32];
@@ -1597,8 +1594,8 @@ put_fpreg (int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switc
 }
 
 static void
-get_fpreg (int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switch_stack *swp,
-	   int tos)
+get_fpreg (int regno, struct _fpreg_ia32 __user *reg, struct pt_regs *ptp,
+	   struct switch_stack *swp, int tos)
 {
 
 	if ((regno += tos) >= 8)
@@ -1627,7 +1624,7 @@ get_fpreg (int regno, struct _fpreg_ia32 *reg, struct pt_regs *ptp, struct switc
 }
 
 int
-save_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct *save)
+save_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct __user *save)
 {
 	struct switch_stack *swp;
 	struct pt_regs *ptp;
@@ -1656,7 +1653,7 @@ save_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct *save)
 }
 
 static int
-restore_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct *save)
+restore_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct __user *save)
 {
 	struct switch_stack *swp;
 	struct pt_regs *ptp;
@@ -1666,15 +1663,15 @@ restore_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct *sav
 	if (!access_ok(VERIFY_READ, save, sizeof(*save)))
 		return(-EFAULT);
 
-	__get_user(num32, (unsigned int *)&save->cwd);
+	__get_user(num32, (unsigned int __user *)&save->cwd);
 	tsk->thread.fcr = (tsk->thread.fcr & (~0x1f3f)) | (num32 & 0x1f3f);
-	__get_user(fsrlo, (unsigned int *)&save->swd);
-	__get_user(fsrhi, (unsigned int *)&save->twd);
+	__get_user(fsrlo, (unsigned int __user *)&save->swd);
+	__get_user(fsrhi, (unsigned int __user *)&save->twd);
 	num32 = (fsrhi << 16) | fsrlo;
 	tsk->thread.fsr = (tsk->thread.fsr & (~0xffffffff)) | num32;
-	__get_user(num32, (unsigned int *)&save->fip);
+	__get_user(num32, (unsigned int __user *)&save->fip);
 	tsk->thread.fir = (tsk->thread.fir & (~0xffffffff)) | num32;
-	__get_user(num32, (unsigned int *)&save->foo);
+	__get_user(num32, (unsigned int __user *)&save->foo);
 	tsk->thread.fdr = (tsk->thread.fdr & (~0xffffffff)) | num32;
 
 	/*
@@ -1689,7 +1686,7 @@ restore_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct *sav
 }
 
 int
-save_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct *save)
+save_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct __user *save)
 {
 	struct switch_stack *swp;
 	struct pt_regs *ptp;
@@ -1715,7 +1712,7 @@ save_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct *save)
         ptp = ia64_task_regs(tsk);
 	tos = (tsk->thread.fsr >> 11) & 7;
         for (i = 0; i < 8; i++)
-		put_fpreg(i, (struct _fpreg_ia32 *)&save->st_space[4*i], ptp, swp, tos);
+		put_fpreg(i, (struct _fpreg_ia32 __user *)&save->st_space[4*i], ptp, swp, tos);
 
 	mxcsr = ((tsk->thread.fcr>>32) & 0xff80) | ((tsk->thread.fsr>>32) & 0x3f);
 	__put_user(mxcsr & 0xffff, &save->mxcsr);
@@ -1728,7 +1725,7 @@ save_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct *save)
 }
 
 static int
-restore_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct *save)
+restore_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct __user *save)
 {
 	struct switch_stack *swp;
 	struct pt_regs *ptp;
@@ -1741,15 +1738,15 @@ restore_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct *sa
 	if (!access_ok(VERIFY_READ, save, sizeof(*save)))
 		return(-EFAULT);
 
-	__get_user(num32, (unsigned int *)&save->cwd);
+	__get_user(num32, (unsigned int __user *)&save->cwd);
 	tsk->thread.fcr = (tsk->thread.fcr & (~0x1f3f)) | (num32 & 0x1f3f);
-	__get_user(fsrlo, (unsigned int *)&save->swd);
-	__get_user(fsrhi, (unsigned int *)&save->twd);
+	__get_user(fsrlo, (unsigned int __user *)&save->swd);
+	__get_user(fsrhi, (unsigned int __user *)&save->twd);
 	num32 = (fsrhi << 16) | fsrlo;
 	tsk->thread.fsr = (tsk->thread.fsr & (~0xffffffff)) | num32;
-	__get_user(num32, (unsigned int *)&save->fip);
+	__get_user(num32, (unsigned int __user *)&save->fip);
 	tsk->thread.fir = (tsk->thread.fir & (~0xffffffff)) | num32;
-	__get_user(num32, (unsigned int *)&save->foo);
+	__get_user(num32, (unsigned int __user *)&save->foo);
 	tsk->thread.fdr = (tsk->thread.fdr & (~0xffffffff)) | num32;
 
 	/*
@@ -1759,13 +1756,13 @@ restore_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct *sa
 	ptp = ia64_task_regs(tsk);
 	tos = (tsk->thread.fsr >> 11) & 7;
 	for (i = 0; i < 8; i++)
-	get_fpreg(i, (struct _fpreg_ia32 *)&save->st_space[4*i], ptp, swp, tos);
+	get_fpreg(i, (struct _fpreg_ia32 __user *)&save->st_space[4*i], ptp, swp, tos);
 
-	__get_user(mxcsr, (unsigned int *)&save->mxcsr);
+	__get_user(mxcsr, (unsigned int __user *)&save->mxcsr);
 	num64 = mxcsr & 0xff10;
-	tsk->thread.fcr = (tsk->thread.fcr & (~0xff1000000000)) | (num64<<32);
+	tsk->thread.fcr = (tsk->thread.fcr & (~0xff1000000000UL)) | (num64<<32);
 	num64 = mxcsr & 0x3f;
-	tsk->thread.fsr = (tsk->thread.fsr & (~0x3f00000000)) | (num64<<32);
+	tsk->thread.fsr = (tsk->thread.fsr & (~0x3f00000000UL)) | (num64<<32);
 
 	for (i = 0; i < 8; i++) {
 		copy_from_user(num128, &save->xmm_space[0] + 4*i, sizeof(struct _xmmreg_ia32));
@@ -1823,7 +1820,7 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data,
 	      case PTRACE_PEEKDATA:	/* read word at location addr */
 		ret = ia32_peek(regs, child, addr, &value);
 		if (ret == 0)
-			ret = put_user(value, (unsigned int *) A(data));
+			ret = put_user(value, (unsigned int __user *) compat_ptr(data));
 		else
 			ret = -EIO;
 		goto out_tsk;
@@ -1839,7 +1836,7 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data,
 			break;
 
 		tmp = getreg(child, addr);
-		if (!put_user(tmp, (unsigned int *) A(data)))
+		if (!put_user(tmp, (unsigned int __user *) compat_ptr(data)))
 			ret = 0;
 		break;
 
@@ -1853,24 +1850,24 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data,
 		break;
 
 	      case IA32_PTRACE_GETREGS:
-		if (!access_ok(VERIFY_WRITE, (int *) A(data), 17*sizeof(int))) {
+		if (!access_ok(VERIFY_WRITE, compat_ptr(data), 17*sizeof(int))) {
 			ret = -EIO;
 			break;
 		}
 		for (i = 0; i < (int) (17*sizeof(int)); i += sizeof(int) ) {
-			put_user(getreg(child, i), (unsigned int *) A(data));
+			put_user(getreg(child, i), (unsigned int __user *) compat_ptr(data));
 			data += sizeof(int);
 		}
 		ret = 0;
 		break;
 
 	      case IA32_PTRACE_SETREGS:
-		if (!access_ok(VERIFY_READ, (int *) A(data), 17*sizeof(int))) {
+		if (!access_ok(VERIFY_READ, compat_ptr(data), 17*sizeof(int))) {
 			ret = -EIO;
 			break;
 		}
 		for (i = 0; i < (int) (17*sizeof(int)); i += sizeof(int) ) {
-			get_user(tmp, (unsigned int *) A(data));
+			get_user(tmp, (unsigned int __user *) compat_ptr(data));
 			putreg(child, i, tmp);
 			data += sizeof(int);
 		}
@@ -1878,19 +1875,23 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data,
 		break;
 
 	      case IA32_PTRACE_GETFPREGS:
-		ret = save_ia32_fpstate(child, (struct ia32_user_i387_struct *) A(data));
+		ret = save_ia32_fpstate(child, (struct ia32_user_i387_struct __user *)
+					compat_ptr(data));
 		break;
 
 	      case IA32_PTRACE_GETFPXREGS:
-		ret = save_ia32_fpxstate(child, (struct ia32_user_fxsr_struct *) A(data));
+		ret = save_ia32_fpxstate(child, (struct ia32_user_fxsr_struct __user *)
+					 compat_ptr(data));
 		break;
 
 	      case IA32_PTRACE_SETFPREGS:
-		ret = restore_ia32_fpstate(child, (struct ia32_user_i387_struct *) A(data));
+		ret = restore_ia32_fpstate(child, (struct ia32_user_i387_struct __user *)
+					   compat_ptr(data));
 		break;
 
 	      case IA32_PTRACE_SETFPXREGS:
-		ret = restore_ia32_fpxstate(child, (struct ia32_user_fxsr_struct *) A(data));
+		ret = restore_ia32_fpxstate(child, (struct ia32_user_fxsr_struct __user *)
+					    compat_ptr(data));
 		break;
 
 	      case PTRACE_SYSCALL:	/* continue, stop after next syscall */
@@ -1913,73 +1914,6 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data,
 	return ret;
 }
 
-/*
- *  The IA64 maps 4 I/O ports for each 4K page
- */
-#define IOLEN	((65536 / 4) * 4096)
-
-asmlinkage long
-sys32_iopl (int level)
-{
-	extern unsigned long ia64_iobase;
-	int fd;
-	struct file * file;
-	unsigned int old;
-	unsigned long addr;
-	mm_segment_t old_fs = get_fs ();
-
-	if (level != 3)
-		return(-EINVAL);
-	/* Trying to gain more privileges? */
-	old = ia64_getreg(_IA64_REG_AR_EFLAG);
-	if ((unsigned int) level > ((old >> 12) & 3)) {
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-	}
-	set_fs(KERNEL_DS);
-	fd = sys_open("/dev/mem", O_SYNC | O_RDWR, 0);
-	set_fs(old_fs);
-	if (fd < 0)
-		return fd;
-	file = fget(fd);
-	if (file == NULL) {
-		sys_close(fd);
-		return(-EFAULT);
-	}
-
-	down_write(&current->mm->mmap_sem);
-	addr = do_mmap_pgoff(file, IA32_IOBASE,
-			     IOLEN, PROT_READ|PROT_WRITE, MAP_SHARED,
-			     (ia64_iobase & ~PAGE_OFFSET) >> PAGE_SHIFT);
-	up_write(&current->mm->mmap_sem);
-
-	if (addr >= 0) {
-		old = (old & ~0x3000) | (level << 12);
-		ia64_setreg(_IA64_REG_AR_EFLAG, old);
-	}
-
-	fput(file);
-	sys_close(fd);
-	return 0;
-}
-
-asmlinkage long
-sys32_ioperm (unsigned int from, unsigned int num, int on)
-{
-
-	/*
-	 *  Since IA64 doesn't have permission bits we'd have to go to
-	 *    a lot of trouble to simulate them in software.  There's
-	 *    no point, only trusted programs can make this call so we'll
-	 *    just turn it into an iopl call and let the process have
-	 *    access to all I/O ports.
-	 *
-	 * XXX proper ioperm() support should be emulated by
-	 *	manipulating the page protections...
-	 */
-	return sys32_iopl(3);
-}
-
 typedef struct {
 	unsigned int	ss_sp;
 	unsigned int	ss_flags;
@@ -1987,7 +1921,7 @@ typedef struct {
 } ia32_stack_t;
 
 asmlinkage long
-sys32_sigaltstack (ia32_stack_t *uss32, ia32_stack_t *uoss32,
+sys32_sigaltstack (ia32_stack_t __user *uss32, ia32_stack_t __user *uoss32,
 		   long arg2, long arg3, long arg4, long arg5, long arg6, long arg7, long stack)
 {
 	struct pt_regs *pt = (struct pt_regs *) &stack;
@@ -1999,9 +1933,9 @@ sys32_sigaltstack (ia32_stack_t *uss32, ia32_stack_t *uoss32,
 	if (uss32) {
 		if (copy_from_user(&buf32, uss32, sizeof(ia32_stack_t)))
 			return -EFAULT;
-		uss.ss_sp = (void *) (long) buf32.ss_sp;
+		uss.ss_sp = (void __user *) (long) buf32.ss_sp;
 		uss.ss_flags = buf32.ss_flags;
-		/* MINSIGSTKSZ is different for ia32 vs ia64. We lie here to pass the 
+		/* MINSIGSTKSZ is different for ia32 vs ia64. We lie here to pass the
 	           check and set it to the user requested value later */
 		if ((buf32.ss_flags != SS_DISABLE) && (buf32.ss_size < MINSIGSTKSZ_IA32)) {
 			ret = -ENOMEM;
@@ -2010,14 +1944,15 @@ sys32_sigaltstack (ia32_stack_t *uss32, ia32_stack_t *uoss32,
 		uss.ss_size = MINSIGSTKSZ;
 	}
 	set_fs(KERNEL_DS);
-	ret = do_sigaltstack(uss32 ? &uss : NULL, &uoss, pt->r12);
- 	current->sas_ss_size = buf32.ss_size;	
+	ret = do_sigaltstack(uss32 ? (stack_t __user *) &uss : NULL,
+			     (stack_t __user *) &uoss, pt->r12);
+ 	current->sas_ss_size = buf32.ss_size;
 	set_fs(old_fs);
 out:
 	if (ret < 0)
 		return(ret);
 	if (uoss32) {
-		buf32.ss_sp = (long) uoss.ss_sp;
+		buf32.ss_sp = (long __user) uoss.ss_sp;
 		buf32.ss_flags = uoss.ss_flags;
 		buf32.ss_size = uoss.ss_size;
 		if (copy_to_user(uoss32, &buf32, sizeof(ia32_stack_t)))
@@ -2056,14 +1991,14 @@ struct sysctl32 {
 };
 
 asmlinkage long
-sys32_sysctl (struct sysctl32 *args)
+sys32_sysctl (struct sysctl32 __user *args)
 {
 #ifdef CONFIG_SYSCTL
 	struct sysctl32 a32;
 	mm_segment_t old_fs = get_fs ();
-	void *oldvalp, *newvalp;
+	void __user *oldvalp, *newvalp;
 	size_t oldlen;
-	int *namep;
+	int __user *namep;
 	long ret;
 
 	if (copy_from_user(&a32, args, sizeof(a32)))
@@ -2076,11 +2011,11 @@ sys32_sysctl (struct sysctl32 *args)
 	 * addresses, we KNOW that access_ok() will always succeed, so this is an
 	 * expensive NOP, but so what...
 	 */
-	namep = (int *) A(a32.name);
-	oldvalp = (void *) A(a32.oldval);
-	newvalp = (void *) A(a32.newval);
+	namep = (int __user *) compat_ptr(a32.name);
+	oldvalp = compat_ptr(a32.oldval);
+	newvalp = compat_ptr(a32.newval);
 
-	if ((oldvalp && get_user(oldlen, (int *) A(a32.oldlenp)))
+	if ((oldvalp && get_user(oldlen, (int __user *) compat_ptr(a32.oldlenp)))
 	    || !access_ok(VERIFY_WRITE, namep, 0)
 	    || !access_ok(VERIFY_WRITE, oldvalp, 0)
 	    || !access_ok(VERIFY_WRITE, newvalp, 0))
@@ -2088,11 +2023,12 @@ sys32_sysctl (struct sysctl32 *args)
 
 	set_fs(KERNEL_DS);
 	lock_kernel();
-	ret = do_sysctl(namep, a32.nlen, oldvalp, &oldlen, newvalp, (size_t) a32.newlen);
+	ret = do_sysctl(namep, a32.nlen, oldvalp, (size_t __user *) &oldlen,
+			newvalp, (size_t) a32.newlen);
 	unlock_kernel();
 	set_fs(old_fs);
 
-	if (oldvalp && put_user (oldlen, (int *) A(a32.oldlenp)))
+	if (oldvalp && put_user (oldlen, (int __user *) compat_ptr(a32.oldlenp)))
 		return -EFAULT;
 
 	return ret;
@@ -2102,7 +2038,7 @@ sys32_sysctl (struct sysctl32 *args)
 }
 
 asmlinkage long
-sys32_newuname (struct new_utsname *name)
+sys32_newuname (struct new_utsname __user *name)
 {
 	int ret = sys_newuname(name);
 
@@ -2113,14 +2049,14 @@ sys32_newuname (struct new_utsname *name)
 }
 
 asmlinkage long
-sys32_getresuid16 (u16 *ruid, u16 *euid, u16 *suid)
+sys32_getresuid16 (u16 __user *ruid, u16 __user *euid, u16 __user *suid)
 {
 	uid_t a, b, c;
 	int ret;
 	mm_segment_t old_fs = get_fs();
 
 	set_fs(KERNEL_DS);
-	ret = sys_getresuid(&a, &b, &c);
+	ret = sys_getresuid((uid_t __user *) &a, (uid_t __user *) &b, (uid_t __user *) &c);
 	set_fs(old_fs);
 
 	if (put_user(a, ruid) || put_user(b, euid) || put_user(c, suid))
@@ -2129,14 +2065,14 @@ sys32_getresuid16 (u16 *ruid, u16 *euid, u16 *suid)
 }
 
 asmlinkage long
-sys32_getresgid16 (u16 *rgid, u16 *egid, u16 *sgid)
+sys32_getresgid16 (u16 __user *rgid, u16 __user *egid, u16 __user *sgid)
 {
 	gid_t a, b, c;
 	int ret;
 	mm_segment_t old_fs = get_fs();
 
 	set_fs(KERNEL_DS);
-	ret = sys_getresgid(&a, &b, &c);
+	ret = sys_getresgid((gid_t __user *) &a, (gid_t __user *) &b, (gid_t __user *) &c);
 	set_fs(old_fs);
 
 	if (ret)
@@ -2153,7 +2089,7 @@ sys32_lseek (unsigned int fd, int offset, unsigned int whence)
 }
 
 static int
-groups16_to_user(short *grouplist, struct group_info *group_info)
+groups16_to_user(short __user *grouplist, struct group_info *group_info)
 {
 	int i;
 	short group;
@@ -2168,7 +2104,7 @@ groups16_to_user(short *grouplist, struct group_info *group_info)
 }
 
 static int
-groups16_from_user(struct group_info *group_info, short *grouplist)
+groups16_from_user(struct group_info *group_info, short __user *grouplist)
 {
 	int i;
 	short group;
@@ -2183,7 +2119,7 @@ groups16_from_user(struct group_info *group_info, short *grouplist)
 }
 
 asmlinkage long
-sys32_getgroups16 (int gidsetsize, short *grouplist)
+sys32_getgroups16 (int gidsetsize, short __user *grouplist)
 {
 	int i;
 
@@ -2208,7 +2144,7 @@ out:
 }
 
 asmlinkage long
-sys32_setgroups16 (int gidsetsize, short *grouplist)
+sys32_setgroups16 (int gidsetsize, short __user *grouplist)
 {
 	struct group_info *group_info;
 	int retval;
@@ -2236,7 +2172,7 @@ sys32_setgroups16 (int gidsetsize, short *grouplist)
 asmlinkage long
 sys32_truncate64 (unsigned int path, unsigned int len_lo, unsigned int len_hi)
 {
-	return sys_truncate((const char *) A(path), ((unsigned long) len_hi << 32) | len_lo);
+	return sys_truncate(compat_ptr(path), ((unsigned long) len_hi << 32) | len_lo);
 }
 
 asmlinkage long
@@ -2246,7 +2182,7 @@ sys32_ftruncate64 (int fd, unsigned int len_lo, unsigned int len_hi)
 }
 
 static int
-putstat64 (struct stat64 *ubuf, struct kstat *kbuf)
+putstat64 (struct stat64 __user *ubuf, struct kstat *kbuf)
 {
 	int err;
 	u64 hdev;
@@ -2255,8 +2191,8 @@ putstat64 (struct stat64 *ubuf, struct kstat *kbuf)
 		return -EFAULT;
 
 	hdev = huge_encode_dev(kbuf->dev);
-	err  = __put_user(hdev, (u32*)&ubuf->st_dev);
-	err |= __put_user(hdev >> 32, ((u32*)&ubuf->st_dev) + 1);
+	err  = __put_user(hdev, (u32 __user*)&ubuf->st_dev);
+	err |= __put_user(hdev >> 32, ((u32 __user*)&ubuf->st_dev) + 1);
 	err |= __put_user(kbuf->ino, &ubuf->__st_ino);
 	err |= __put_user(kbuf->ino, &ubuf->st_ino_lo);
 	err |= __put_user(kbuf->ino >> 32, &ubuf->st_ino_hi);
@@ -2265,8 +2201,8 @@ putstat64 (struct stat64 *ubuf, struct kstat *kbuf)
 	err |= __put_user(kbuf->uid, &ubuf->st_uid);
 	err |= __put_user(kbuf->gid, &ubuf->st_gid);
 	hdev = huge_encode_dev(kbuf->rdev);
-	err  = __put_user(hdev, (u32*)&ubuf->st_rdev);
-	err |= __put_user(hdev >> 32, ((u32*)&ubuf->st_rdev) + 1);
+	err  = __put_user(hdev, (u32 __user*)&ubuf->st_rdev);
+	err |= __put_user(hdev >> 32, ((u32 __user*)&ubuf->st_rdev) + 1);
 	err |= __put_user(kbuf->size, &ubuf->st_size_lo);
 	err |= __put_user((kbuf->size >> 32), &ubuf->st_size_hi);
 	err |= __put_user(kbuf->atime.tv_sec, &ubuf->st_atime);
@@ -2281,7 +2217,7 @@ putstat64 (struct stat64 *ubuf, struct kstat *kbuf)
 }
 
 asmlinkage long
-sys32_stat64 (char *filename, struct stat64 *statbuf)
+sys32_stat64 (char __user *filename, struct stat64 __user *statbuf)
 {
 	struct kstat s;
 	long ret = vfs_stat(filename, &s);
@@ -2291,7 +2227,7 @@ sys32_stat64 (char *filename, struct stat64 *statbuf)
 }
 
 asmlinkage long
-sys32_lstat64 (char *filename, struct stat64 *statbuf)
+sys32_lstat64 (char __user *filename, struct stat64 __user *statbuf)
 {
 	struct kstat s;
 	long ret = vfs_lstat(filename, &s);
@@ -2301,7 +2237,7 @@ sys32_lstat64 (char *filename, struct stat64 *statbuf)
 }
 
 asmlinkage long
-sys32_fstat64 (unsigned int fd, struct stat64 *statbuf)
+sys32_fstat64 (unsigned int fd, struct stat64 __user *statbuf)
 {
 	struct kstat s;
 	long ret = vfs_fstat(fd, &s);
@@ -2328,7 +2264,7 @@ struct sysinfo32 {
 };
 
 asmlinkage long
-sys32_sysinfo (struct sysinfo32 *info)
+sys32_sysinfo (struct sysinfo32 __user *info)
 {
 	struct sysinfo s;
 	long ret, err;
@@ -2336,7 +2272,7 @@ sys32_sysinfo (struct sysinfo32 *info)
 	mm_segment_t old_fs = get_fs();
 
 	set_fs(KERNEL_DS);
-	ret = sys_sysinfo(&s);
+	ret = sys_sysinfo((struct sysinfo __user *) &s);
 	set_fs(old_fs);
 	/* Check to see if any memory value is too large for 32-bit and
 	 * scale down if needed.
@@ -2379,14 +2315,14 @@ sys32_sysinfo (struct sysinfo32 *info)
 }
 
 asmlinkage long
-sys32_sched_rr_get_interval (pid_t pid, struct compat_timespec *interval)
+sys32_sched_rr_get_interval (pid_t pid, struct compat_timespec __user *interval)
 {
 	mm_segment_t old_fs = get_fs();
 	struct timespec t;
 	long ret;
 
 	set_fs(KERNEL_DS);
-	ret = sys_sched_rr_get_interval(pid, &t);
+	ret = sys_sched_rr_get_interval(pid, (struct timespec __user *) &t);
 	set_fs(old_fs);
 	if (put_compat_timespec(&t, interval))
 		return -EFAULT;
@@ -2394,19 +2330,19 @@ sys32_sched_rr_get_interval (pid_t pid, struct compat_timespec *interval)
 }
 
 asmlinkage long
-sys32_pread (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi)
+sys32_pread (unsigned int fd, void __user *buf, unsigned int count, u32 pos_lo, u32 pos_hi)
 {
 	return sys_pread64(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo);
 }
 
 asmlinkage long
-sys32_pwrite (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi)
+sys32_pwrite (unsigned int fd, void __user *buf, unsigned int count, u32 pos_lo, u32 pos_hi)
 {
 	return sys_pwrite64(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo);
 }
 
 asmlinkage long
-sys32_sendfile (int out_fd, int in_fd, int *offset, unsigned int count)
+sys32_sendfile (int out_fd, int in_fd, int __user *offset, unsigned int count)
 {
 	mm_segment_t old_fs = get_fs();
 	long ret;
@@ -2416,7 +2352,7 @@ sys32_sendfile (int out_fd, int in_fd, int *offset, unsigned int count)
 		return -EFAULT;
 
 	set_fs(KERNEL_DS);
-	ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
+	ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *) &of : NULL, count);
 	set_fs(old_fs);
 
 	if (!ret && offset && put_user(of, offset))
@@ -2447,7 +2383,7 @@ sys32_brk (unsigned int brk)
 	obrk = mm->brk;
 	ret = sys_brk(brk);
 	if (ret < obrk)
-		clear_user((void *) ret, PAGE_ALIGN(ret) - ret);
+		clear_user(compat_ptr(ret), PAGE_ALIGN(ret) - ret);
 	return ret;
 }
 
@@ -2455,7 +2391,7 @@ sys32_brk (unsigned int brk)
  * Exactly like fs/open.c:sys_open(), except that it doesn't set the O_LARGEFILE flag.
  */
 asmlinkage long
-sys32_open (const char * filename, int flags, int mode)
+sys32_open (const char __user * filename, int flags, int mode)
 {
 	char * tmp;
 	int fd, error;
@@ -2487,10 +2423,10 @@ struct epoll_event32
 {
 	u32 events;
 	u32 data[2];
-}; 
+};
 
 asmlinkage long
-sys32_epoll_ctl(int epfd, int op, int fd, struct epoll_event32 *event)
+sys32_epoll_ctl(int epfd, int op, int fd, struct epoll_event32 __user *event)
 {
 	mm_segment_t old_fs = get_fs();
 	struct epoll_event event64;
@@ -2508,14 +2444,14 @@ sys32_epoll_ctl(int epfd, int op, int fd, struct epoll_event32 *event)
  	event64.data |= (u64)data_halfword << 32;
 
 	set_fs(KERNEL_DS);
-	error = sys_epoll_ctl(epfd, op, fd, &event64);
+	error = sys_epoll_ctl(epfd, op, fd, (struct epoll_event __user *) &event64);
 	set_fs(old_fs);
 
 	return error;
 }
 
 asmlinkage long
-sys32_epoll_wait(int epfd, struct epoll_event32 *events, int maxevents,
+sys32_epoll_wait(int epfd, struct epoll_event32 __user * events, int maxevents,
 		 int timeout)
 {
 	struct epoll_event *events64 = NULL;
@@ -2533,8 +2469,8 @@ sys32_epoll_wait(int epfd, struct epoll_event32 *events, int maxevents,
 				 maxevents * sizeof(struct epoll_event32))))
 		return error;
 
-	/* 
- 	 * Allocate space for the intermediate copy.  If the space needed 
+	/*
+ 	 * Allocate space for the intermediate copy.  If the space needed
 	 * is large enough to cause kmalloc to fail, then try again with
 	 * __get_free_pages.
 	 */
@@ -2543,14 +2479,15 @@ sys32_epoll_wait(int epfd, struct epoll_event32 *events, int maxevents,
 	if (events64 == NULL) {
 		events64 = (struct epoll_event *)
 				__get_free_pages(GFP_KERNEL, get_order(size));
-		if (events64 == NULL) 
+		if (events64 == NULL)
 			return -ENOMEM;
 		do_free_pages = 1;
 	}
 
 	/* Do the system call */
 	set_fs(KERNEL_DS); /* copy_to/from_user should work on kernel mem*/
-	numevents = sys_epoll_wait(epfd, events64, maxevents, timeout);
+	numevents = sys_epoll_wait(epfd, (struct epoll_event __user *) events64,
+				   maxevents, timeout);
 	set_fs(old_fs);
 
 	/* Don't modify userspace memory if we're returning an error */
@@ -2593,7 +2530,7 @@ get_free_idx (void)
  * Set a given TLS descriptor:
  */
 asmlinkage int
-sys32_set_thread_area (struct ia32_user_desc *u_info)
+sys32_set_thread_area (struct ia32_user_desc __user *u_info)
 {
 	struct thread_struct *t = &current->thread;
 	struct ia32_user_desc info;
@@ -2654,7 +2591,7 @@ sys32_set_thread_area (struct ia32_user_desc *u_info)
 #define GET_USEABLE(desc)	(((desc)->b >> 20) & 1)
 
 asmlinkage int
-sys32_get_thread_area (struct ia32_user_desc *u_info)
+sys32_get_thread_area (struct ia32_user_desc __user *u_info)
 {
 	struct ia32_user_desc info;
 	struct desc_struct *desc;
@@ -2682,12 +2619,8 @@ sys32_get_thread_area (struct ia32_user_desc *u_info)
 	return 0;
 }
 
-extern asmlinkage long
-sys_timer_create(clockid_t which_clock, struct sigevent *timer_event_spec,
-		 timer_t * created_timer_id);
-
 asmlinkage long
-sys32_timer_create(u32 clock, struct sigevent32 *se32, timer_t *timer_id)
+sys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *timer_id)
 {
 	struct sigevent se;
 	mm_segment_t oldfs;
@@ -2710,7 +2643,7 @@ sys32_timer_create(u32 clock, struct sigevent32 *se32, timer_t *timer_id)
 
 	oldfs = get_fs();
 	set_fs(KERNEL_DS);
-	err = sys_timer_create(clock, &se, &t);
+	err = sys_timer_create(clock, (struct sigevent __user *) &se, (timer_t __user *) &t);
 	set_fs(oldfs);
 
 	if (!err)
@@ -2728,6 +2661,32 @@ long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high,
 			       advice); 
 } 
 
+asmlinkage long sys32_waitid(int which, compat_pid_t pid,
+			     siginfo_t32 __user *uinfo, int options,
+			     struct compat_rusage __user *uru)
+{
+	siginfo_t info;
+	struct rusage ru;
+	long ret;
+	mm_segment_t old_fs = get_fs();
+
+	info.si_signo = 0;
+	set_fs (KERNEL_DS);
+	ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options,
+			 uru ? &ru : NULL);
+	set_fs (old_fs);
+
+	if (ret < 0 || info.si_signo == 0)
+		return ret;
+
+	if (uru && (ret = put_compat_rusage(&ru, uru)))
+		return ret;
+
+	BUG_ON(info.si_code & __SI_MASK);
+	info.si_code |= __SI_CHLD;
+	return copy_siginfo_to_user32(uinfo, &info);
+}
+
 #ifdef	NOTYET  /* UNTESTED FOR IA64 FROM HERE DOWN */
 
 asmlinkage long sys32_setreuid(compat_uid_t ruid, compat_uid_t euid)
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index 7d1e2f3d4..265ae83da 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-extra-y	:= head.o init_task.o vmlinux.lds.s
+extra-y	:= head.o init_task.o vmlinux.lds
 
 obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o	\
 	 irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o		\
@@ -17,29 +17,31 @@ obj-$(CONFIG_MODULES)		+= module.o
 obj-$(CONFIG_SMP)		+= smp.o smpboot.o
 obj-$(CONFIG_PERFMON)		+= perfmon_default_smpl.o
 obj-$(CONFIG_IA64_CYCLONE)	+= cyclone.o
+obj-$(CONFIG_IA64_MCA_RECOVERY)	+= mca_recovery.o
+mca_recovery-y			+= mca_drv.o mca_drv_asm.o
 
 # The gate DSO image is built using a special linker script.
 targets += gate.so gate-syms.o
 
-extra-y += gate.so gate-syms.o gate.lds.s gate.o
+extra-y += gate.so gate-syms.o gate.lds gate.o
 
 # fp_emulate() expects f2-f5,f16-f31 to contain the user-level state.
 CFLAGS_traps.o  += -mfixed-range=f2-f5,f16-f31
 
-AFLAGS_gate.lds.o += -P -C -U$(ARCH)
+CPPFLAGS_gate.lds := -P -C -U$(ARCH)
 
 quiet_cmd_gate = GATE $@
       cmd_gate = $(CC) -nostdlib $(GATECFLAGS_$(@F)) -Wl,-T,$(filter-out FORCE,$^) -o $@
 
 GATECFLAGS_gate.so = -shared -s -Wl,-soname=linux-gate.so.1
-$(obj)/gate.so: $(obj)/gate.lds.s $(obj)/gate.o FORCE
+$(obj)/gate.so: $(obj)/gate.lds $(obj)/gate.o FORCE
 	$(call if_changed,gate)
 
 $(obj)/built-in.o: $(obj)/gate-syms.o
 $(obj)/built-in.o: ld_flags += -R $(obj)/gate-syms.o
 
 GATECFLAGS_gate-syms.o = -r
-$(obj)/gate-syms.o: $(src)/gate.lds.s $(obj)/gate.o FORCE
+$(obj)/gate-syms.o: $(obj)/gate.lds $(obj)/gate.o FORCE
 	$(call if_changed,gate)
 
 # gate-data.o contains the gate DSO image as data in section .data.gate.
diff --git a/arch/ia64/kernel/acpi-ext.c b/arch/ia64/kernel/acpi-ext.c
index b70f6de25..2623df5e2 100644
--- a/arch/ia64/kernel/acpi-ext.c
+++ b/arch/ia64/kernel/acpi-ext.c
@@ -62,7 +62,7 @@ acpi_find_vendor_resource(acpi_handle obj, struct acpi_vendor_descriptor *id,
 	struct acpi_vendor_info info;
 
 	info.descriptor = id;
-	info.data = 0;
+	info.data = NULL;
 
 	acpi_walk_resources(obj, METHOD_NAME__CRS, acpi_vendor_resource_match, &info);
 	if (!info.data)
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index cf61f3e2a..6e012ba55 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -61,10 +61,16 @@
 void (*pm_idle) (void);
 EXPORT_SYMBOL(pm_idle);
 void (*pm_power_off) (void);
+EXPORT_SYMBOL(pm_power_off);
 
 unsigned char acpi_kbd_controller_present = 1;
 unsigned char acpi_legacy_devices;
 
+#define MAX_SAPICS 256
+u16 ia64_acpiid_to_sapicid[MAX_SAPICS] =
+	{ [0 ... MAX_SAPICS - 1] = -1 };
+EXPORT_SYMBOL(ia64_acpiid_to_sapicid);
+
 const char *
 acpi_get_sysname (void)
 {
@@ -172,8 +178,8 @@ acpi_parse_lapic_addr_ovr (
 		return -EINVAL;
 
 	if (lapic->address) {
-		iounmap((void *) ipi_base_addr);
-		ipi_base_addr = (unsigned long) ioremap(lapic->address, 0);
+		iounmap(ipi_base_addr);
+		ipi_base_addr = ioremap(lapic->address, 0);
 	}
 	return 0;
 }
@@ -193,6 +199,7 @@ acpi_parse_lsapic (acpi_table_entry_header *header, const unsigned long end)
 #ifdef CONFIG_SMP
 		smp_boot_data.cpu_phys_id[available_cpus] = (lsapic->id << 8) | lsapic->eid;
 #endif
+		ia64_acpiid_to_sapicid[lsapic->acpi_id] = (lsapic->id << 8) | lsapic->eid;
 		++available_cpus;
 	}
 
@@ -329,9 +336,9 @@ acpi_parse_madt (unsigned long phys_addr, unsigned long size)
 	/* Get base address of IPI Message Block */
 
 	if (acpi_madt->lapic_address)
-		ipi_base_addr = (unsigned long) ioremap(acpi_madt->lapic_address, 0);
+		ipi_base_addr = ioremap(acpi_madt->lapic_address, 0);
 
-	printk(KERN_INFO PREFIX "Local APIC address 0x%lx\n", ipi_base_addr);
+	printk(KERN_INFO PREFIX "Local APIC address %p\n", ipi_base_addr);
 
 	acpi_madt_oem_check(acpi_madt->header.oem_id,
 		acpi_madt->header.oem_table_id);
@@ -430,8 +437,9 @@ acpi_numa_arch_fixup (void)
 {
 	int i, j, node_from, node_to;
 
-	/* If there's no SRAT, fix the phys_id */
+	/* If there's no SRAT, fix the phys_id and mark node 0 online */
 	if (srat_num_cpus == 0) {
+		node_set_online(0);
 		node_cpuid[0].phys_id = hard_smp_processor_id();
 		return;
 	}
@@ -643,4 +651,71 @@ acpi_gsi_to_irq (u32 gsi, unsigned int *irq)
 	return 0;
 }
 
+#ifdef CONFIG_NUMA
+acpi_status __init
+acpi_map_iosapic (acpi_handle handle, u32 depth, void *context, void **ret)
+{
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	union acpi_object *obj;
+	struct acpi_table_iosapic *iosapic;
+	unsigned int gsi_base;
+	int node;
+
+	/* Only care about objects w/ a method that returns the MADT */
+	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
+		return AE_OK;
+
+	if (!buffer.length || !buffer.pointer)
+		return AE_OK;
+
+	obj = buffer.pointer;
+	if (obj->type != ACPI_TYPE_BUFFER ||
+	    obj->buffer.length < sizeof(*iosapic)) {
+		acpi_os_free(buffer.pointer);
+		return AE_OK;
+	}
+
+	iosapic = (struct acpi_table_iosapic *)obj->buffer.pointer;
+
+	if (iosapic->header.type != ACPI_MADT_IOSAPIC) {
+		acpi_os_free(buffer.pointer);
+		return AE_OK;
+	}
+
+	gsi_base = iosapic->global_irq_base;
+
+	acpi_os_free(buffer.pointer);
+	buffer.length = ACPI_ALLOCATE_BUFFER;
+	buffer.pointer = NULL;
+
+	/*
+	 * OK, it's an IOSAPIC MADT entry, look for a _PXM method to tell
+	 * us which node to associate this with.
+	 */
+	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PXM", NULL, &buffer)))
+		return AE_OK;
+
+	if (!buffer.length || !buffer.pointer)
+		return AE_OK;
+
+	obj = buffer.pointer;
+
+	if (obj->type != ACPI_TYPE_INTEGER ||
+	    obj->integer.value >= MAX_PXM_DOMAINS) {
+		acpi_os_free(buffer.pointer);
+		return AE_OK;
+	}
+
+	node = pxm_to_nid_map[obj->integer.value];
+	acpi_os_free(buffer.pointer);
+
+	if (node >= MAX_NUMNODES || !node_online(node) ||
+	    cpus_empty(node_to_cpumask(node)))
+		return AE_OK;
+
+	/* We know a gsi to node mapping! */
+	map_iosapic_to_node(gsi_base, node);
+	return AE_OK;
+}
+#endif /* CONFIG_NUMA */
 #endif /* CONFIG_ACPI_BOOT */
diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c
index f166571ec..b1ab994b2 100644
--- a/arch/ia64/kernel/asm-offsets.c
+++ b/arch/ia64/kernel/asm-offsets.c
@@ -34,6 +34,11 @@ void foo(void)
 
 	BLANK();
 
+	DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+	DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
+
+	BLANK();
+
 	DEFINE(IA64_TASK_BLOCKED_OFFSET,offsetof (struct task_struct, blocked));
 	DEFINE(IA64_TASK_CLEAR_CHILD_TID_OFFSET,offsetof (struct task_struct, clear_child_tid));
 	DEFINE(IA64_TASK_GROUP_LEADER_OFFSET, offsetof (struct task_struct, group_leader));
@@ -188,18 +193,10 @@ void foo(void)
 	DEFINE(IA64_CLONE_VM, CLONE_VM);
 
 	BLANK();
-    /* used by fsys_gettimeofday in arch/ia64/kernel/fsys.S */
-	DEFINE(IA64_CPUINFO_ITM_DELTA_OFFSET, offsetof (struct cpuinfo_ia64, itm_delta));
-	DEFINE(IA64_CPUINFO_ITM_NEXT_OFFSET, offsetof (struct cpuinfo_ia64, itm_next));
 	DEFINE(IA64_CPUINFO_NSEC_PER_CYC_OFFSET, offsetof (struct cpuinfo_ia64, nsec_per_cyc));
 	DEFINE(IA64_TIMESPEC_TV_NSEC_OFFSET, offsetof (struct timespec, tv_nsec));
 
 
-	DEFINE(CLONE_IDLETASK_BIT, 12);
-#if CLONE_IDLETASK != (1 << 12)
-# error "CLONE_IDLETASK_BIT incorrect, please fix"
-#endif
-
 	DEFINE(CLONE_SETTLS_BIT, 19);
 #if CLONE_SETTLS != (1<<19)
 # error "CLONE_SETTLS_BIT incorrect, please fix"
@@ -207,5 +204,21 @@ void foo(void)
 
 	BLANK();
 	DEFINE(IA64_MCA_TLB_INFO_SIZE, sizeof (struct ia64_mca_tlb_info));
+	/* used by head.S */
+	DEFINE(IA64_CPUINFO_NSEC_PER_CYC_OFFSET, offsetof (struct cpuinfo_ia64, nsec_per_cyc));
 
+	BLANK();
+	/* used by fsys_gettimeofday in arch/ia64/kernel/fsys.S */
+	DEFINE(IA64_TIME_INTERPOLATOR_ADDRESS_OFFSET, offsetof (struct time_interpolator, addr));
+	DEFINE(IA64_TIME_INTERPOLATOR_SOURCE_OFFSET, offsetof (struct time_interpolator, source));
+	DEFINE(IA64_TIME_INTERPOLATOR_SHIFT_OFFSET, offsetof (struct time_interpolator, shift));
+	DEFINE(IA64_TIME_INTERPOLATOR_NSEC_OFFSET, offsetof (struct time_interpolator, nsec_per_cyc));
+	DEFINE(IA64_TIME_INTERPOLATOR_OFFSET_OFFSET, offsetof (struct time_interpolator, offset));
+	DEFINE(IA64_TIME_INTERPOLATOR_LAST_CYCLE_OFFSET, offsetof (struct time_interpolator, last_cycle));
+	DEFINE(IA64_TIME_INTERPOLATOR_LAST_COUNTER_OFFSET, offsetof (struct time_interpolator, last_counter));
+	DEFINE(IA64_TIME_INTERPOLATOR_JITTER_OFFSET, offsetof (struct time_interpolator, jitter));
+	DEFINE(IA64_TIME_SOURCE_CPU, TIME_SOURCE_CPU);
+	DEFINE(IA64_TIME_SOURCE_MMIO64, TIME_SOURCE_MMIO64);
+	DEFINE(IA64_TIME_SOURCE_MMIO32, TIME_SOURCE_MMIO32);
+	DEFINE(IA64_TIMESPEC_TV_NSEC_OFFSET, offsetof (struct timespec, tv_nsec));
 }
diff --git a/arch/ia64/kernel/cyclone.c b/arch/ia64/kernel/cyclone.c
index 19300e958..f8261d3a9 100644
--- a/arch/ia64/kernel/cyclone.c
+++ b/arch/ia64/kernel/cyclone.c
@@ -1,6 +1,8 @@
+#include <linux/module.h>
 #include <linux/smp.h>
 #include <linux/time.h>
 #include <linux/errno.h>
+#include <asm/io.h>
 
 /* IBM Summit (EXA) Cyclone counter code*/
 #define CYCLONE_CBAR_ADDR 0xFEB00CD0
@@ -15,62 +17,10 @@ void __init cyclone_setup(void)
 	use_cyclone = 1;
 }
 
-static u32* volatile cyclone_timer;	/* Cyclone MPMC0 register */
-static u32 last_update_cyclone;
-
-static unsigned long offset_base;
-
-static unsigned long get_offset_cyclone(void)
-{
-	u32 now;
-	unsigned long offset;
-
-	/* Read the cyclone timer */
-	now = readl(cyclone_timer);
-	/* .. relative to previous update*/
-	offset = now - last_update_cyclone;
-
-	/* convert cyclone ticks to nanoseconds */
-	offset = (offset*NSEC_PER_SEC)/CYCLONE_TIMER_FREQ;
-
-	/* our adjusted time in nanoseconds */
-	return offset_base + offset;
-}
-
-static void update_cyclone(long delta_nsec)
-{
-	u32 now;
-	unsigned long offset;
-
-	/* Read the cyclone timer */
-	now = readl(cyclone_timer);
-	/* .. relative to previous update*/
-	offset = now - last_update_cyclone;
-
-	/* convert cyclone ticks to nanoseconds */
-	offset = (offset*NSEC_PER_SEC)/CYCLONE_TIMER_FREQ;
-
-	offset += offset_base;
-
-	/* Be careful about signed/unsigned comparisons here: */
-	if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)
-		offset_base = offset - delta_nsec;
-	else
-		offset_base = 0;
-
-	last_update_cyclone = now;
-}
-
-static void reset_cyclone(void)
-{
-	offset_base = 0;
-	last_update_cyclone = readl(cyclone_timer);
-}
 
 struct time_interpolator cyclone_interpolator = {
-	.get_offset =	get_offset_cyclone,
-	.update =	update_cyclone,
-	.reset =	reset_cyclone,
+	.source =	TIME_SOURCE_MMIO32,
+	.shift =	32,
 	.frequency =	CYCLONE_TIMER_FREQ,
 	.drift =	-100,
 };
@@ -81,6 +31,7 @@ int __init init_cyclone_clock(void)
 	u64 base;	/* saved cyclone base address */
 	u64 offset;	/* offset from pageaddr to cyclone_timer register */
 	int i;
+	u32* volatile cyclone_timer;	/* Cyclone MPMC0 register */
 
 	if (!use_cyclone)
 		return -ENODEV;
@@ -148,7 +99,7 @@ int __init init_cyclone_clock(void)
 		}
 	}
 	/* initialize last tick */
-	last_update_cyclone = readl(cyclone_timer);
+	cyclone_interpolator.addr = cyclone_timer;
 	register_time_interpolator(&cyclone_interpolator);
 
 	return 0;
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index e1e7d91c9..7b23f4dfa 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -48,7 +48,7 @@ static efi_status_t										  \
 prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc)						  \
 {												  \
 	struct ia64_fpreg fr[6];								  \
-	efi_time_cap_t *atc = 0;								  \
+	efi_time_cap_t *atc = NULL;								  \
 	efi_status_t ret;									  \
 												  \
 	if (tc)											  \
@@ -91,7 +91,7 @@ static efi_status_t										\
 prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm)					\
 {												\
 	struct ia64_fpreg fr[6];								\
-	efi_time_t *atm = 0;									\
+	efi_time_t *atm = NULL;									\
 	efi_status_t ret;									\
 												\
 	if (tm)											\
@@ -109,7 +109,7 @@ prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr,		\
 		       unsigned long *data_size, void *data)				\
 {											\
 	struct ia64_fpreg fr[6];							\
-	u32 *aattr = 0;									\
+	u32 *aattr = NULL;									\
 	efi_status_t ret;								\
 											\
 	if (attr)									\
@@ -172,7 +172,7 @@ prefix##_reset_system (int reset_type, efi_status_t status,			\
 		       unsigned long data_size, efi_char16_t *data)		\
 {										\
 	struct ia64_fpreg fr[6];						\
-	efi_char16_t *adata = 0;						\
+	efi_char16_t *adata = NULL;						\
 										\
 	if (data)								\
 		adata = adjust_arg(data);					\
@@ -214,7 +214,7 @@ efi_gettimeofday (struct timespec *ts)
 	efi_time_t tm;
 
 	memset(ts, 0, sizeof(ts));
-	if ((*efi.get_time)(&tm, 0) != EFI_SUCCESS)
+	if ((*efi.get_time)(&tm, NULL) != EFI_SUCCESS)
 		return;
 
 	ts->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second);
@@ -357,8 +357,10 @@ efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
 			if (total_mem >= mem_limit)
 				continue;
 			total_mem += (md->num_pages << EFI_PAGE_SHIFT);
-			if (total_mem > mem_limit)
+			if (total_mem > mem_limit) {
 				md->num_pages -= ((total_mem - mem_limit) >> EFI_PAGE_SHIFT);
+				max_addr = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
+			}
 
 			if (md->num_pages == 0)
 				continue;
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 0b24641ad..5e22d9df6 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -128,7 +128,7 @@ GLOBAL_ENTRY(sys_clone2)
 (p6)	st8 [r2]=in5				// store TLS in r16 for copy_thread()
 	mov out5=in4	// child_tidptr:  valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID
 	adds out2=IA64_SWITCH_STACK_SIZE+16,sp	// out2 = &regs
-	dep out0=0,in0,CLONE_IDLETASK_BIT,1	// out0 = clone_flags & ~CLONE_IDLETASK
+	mov out0=in0				// out0 = clone_flags
 	br.call.sptk.many rp=do_fork
 .ret1:	.restore sp
 	adds sp=IA64_SWITCH_STACK_SIZE,sp	// pop the switch stack
@@ -157,7 +157,7 @@ GLOBAL_ENTRY(sys_clone)
 (p6)	st8 [r2]=in4				// store TLS in r13 (tp)
 	mov out5=in3	// child_tidptr:  valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID
 	adds out2=IA64_SWITCH_STACK_SIZE+16,sp	// out2 = &regs
-	dep out0=0,in0,CLONE_IDLETASK_BIT,1	// out0 = clone_flags & ~CLONE_IDLETASK
+	mov out0=in0				// out0 = clone_flags
 	br.call.sptk.many rp=do_fork
 .ret2:	.restore sp
 	adds sp=IA64_SWITCH_STACK_SIZE,sp	// pop the switch stack
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
index 0f8e5b5fd..4895559ee 100644
--- a/arch/ia64/kernel/fsys.S
+++ b/arch/ia64/kernel/fsys.S
@@ -8,6 +8,8 @@
  * 18-Feb-03 louisk	Implement fsys_gettimeofday().
  * 28-Feb-03 davidm	Fixed several bugs in fsys_gettimeofday().  Tuned it some more,
  *			probably broke it along the way... ;-)
+ * 13-Jul-04 clameter   Implement fsys_clock_gettime and revise fsys_gettimeofday to make
+ *                      it capable of using memory based clocks without falling back to C code.
  */
 
 #include <asm/asmmacro.h>
@@ -144,195 +146,206 @@ ENTRY(fsys_set_tid_address)
 END(fsys_set_tid_address)
 
 /*
- * Note 1: This routine uses floating-point registers, but only with registers that
- *	   operate on integers.  Because of that, we don't need to set ar.fpsr to the
- *	   kernel default value.
- *
- * Note 2: For now, we will assume that all CPUs run at the same clock-frequency.
- *	   If that wasn't the case, we would have to disable preemption (e.g.,
- *	   by disabling interrupts) between reading the ITC and reading
- *	   local_cpu_data->nsec_per_cyc.
- *
- * Note 3: On platforms where the ITC-drift bit is set in the SAL feature vector,
- *	   we ought to either skip the ITC-based interpolation or run an ntp-like
- *	   daemon to keep the ITCs from drifting too far apart.
+ * Ensure that the time interpolator structure is compatible with the asm code
  */
+#if IA64_TIME_INTERPOLATOR_SOURCE_OFFSET !=0 || IA64_TIME_INTERPOLATOR_SHIFT_OFFSET != 2 \
+	|| IA64_TIME_INTERPOLATOR_JITTER_OFFSET != 3 || IA64_TIME_INTERPOLATOR_NSEC_OFFSET != 4
+#error fsys_gettimeofday incompatible with changes to struct time_interpolator
+#endif
+#define CLOCK_REALTIME 0
+#define CLOCK_MONOTONIC 1
+#define CLOCK_DIVIDE_BY_1000 0x4000
+#define CLOCK_ADD_MONOTONIC 0x8000
 
 ENTRY(fsys_gettimeofday)
 	.prologue
 	.altrp b6
 	.body
-	add r9=TI_FLAGS+IA64_TASK_SIZE,r16
-	addl r3=THIS_CPU(cpu_info),r0
-
-#ifdef CONFIG_SMP
-	movl r10=__per_cpu_offset
-	movl r2=sal_platform_features
-	;;
-
-	ld8 r2=[r2]
-	movl r19=xtime			// xtime is a timespec struct
-
-	ld8 r10=[r10]			// r10 <- __per_cpu_offset[0]
-	addl r21=THIS_CPU(cpu_info),r0
-	;;
-	add r10=r21, r10		// r10 <- &cpu_data(time_keeper_id)
-	tbit.nz p8,p0 = r2, IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT_BIT
-(p8)	br.spnt.many fsys_fallback_syscall
-#else
-	;;
-	mov r10=r3
-	movl r19=xtime			// xtime is a timespec struct
-#endif
-	ld4 r9=[r9]
-	movl r17=xtime_lock
-	;;
-
-	// r32, r33 should contain the 2 args of gettimeofday
-	adds r21=IA64_CPUINFO_ITM_NEXT_OFFSET, r10
-	mov r2=-1
-	tnat.nz p6,p7=r32		// guard against NaT args
-	;;
-
-	adds r10=IA64_CPUINFO_ITM_DELTA_OFFSET, r10
-(p7)	tnat.nz p6,p0=r33
-(p6)	br.cond.spnt.few .fail_einval
-
-	adds r8=IA64_CPUINFO_NSEC_PER_CYC_OFFSET, r3
-	movl r24=2361183241434822607	// for division hack (only for / 1000)
-	;;
-
-	ldf8 f7=[r10]			// f7 now contains itm_delta
-	setf.sig f11=r2
-	adds r10=8, r32
-
-	adds r20=IA64_TIMESPEC_TV_NSEC_OFFSET, r19	// r20 = &xtime->tv_nsec
-	movl r26=jiffies
-
-	setf.sig f9=r24			// f9 is used for division hack
-	movl r27=wall_jiffies
-
-	and r9=TIF_ALLWORK_MASK,r9
-	movl r25=last_nsec_offset
-	;;
-
-	/*
-	 * Verify that we have permission to write to struct timeval.  Note:
-	 * Another thread might unmap the mapping before we actually get
-	 * to store the result.  That's OK as long as the stores are also
-	 * protect by EX().
-	 */
-EX(.fail_efault, probe.w.fault r32, 3)		// this must come _after_ NaT-check
-EX(.fail_efault, probe.w.fault r10, 3)		// this must come _after_ NaT-check
-	nop 0
-
-	ldf8 f10=[r8]			// f10 <- local_cpu_data->nsec_per_cyc value
-	cmp.ne p8, p0=0, r9
-(p8)	br.spnt.many fsys_fallback_syscall
-	;;
-.retry:	// *** seq = read_seqbegin(&xtime_lock); ***
-	ld4.acq r23=[r17]		// since &xtime_lock == &xtime_lock->sequence
-	ld8 r14=[r25]			// r14 (old) = last_nsec_offset
-
-	ld8 r28=[r26]			// r28 = jiffies
-	ld8 r29=[r27]			// r29 = wall_jiffies
-	;;
-
-	ldf8 f8=[r21]			// f8 now contains itm_next
-	mov.m r31=ar.itc		// put time stamp into r31 (ITC) == now
-	sub r28=r29, r28, 1		// r28 now contains "-(lost + 1)"
-	;;
-
-	ld8 r2=[r19]			// r2 = sec = xtime.tv_sec
-	ld8 r29=[r20]			// r29 = nsec = xtime.tv_nsec
-	tbit.nz p9, p10=r23, 0		// p9 <- is_odd(r23), p10 <- is_even(r23)
-
-	setf.sig f6=r28			// f6 <- -(lost + 1)				(6 cyc)
-	;;
-
+	mov r31 = r32
+	tnat.nz p6,p0 = r33		// guard against NaT argument
+(p6)    br.cond.spnt.few .fail_einval
+	mov r30 = CLOCK_DIVIDE_BY_1000
+	;;
+.gettime:
+	// Register map
+	// Incoming r31 = pointer to address where to place result
+	//          r30 = flags determining how time is processed
+	// r2,r3 = temp r4-r7 preserved
+	// r8 = result nanoseconds
+	// r9 = result seconds
+	// r10 = temporary storage for clock difference
+	// r11 = preserved: saved ar.pfs
+	// r12 = preserved: memory stack
+	// r13 = preserved: thread pointer
+	// r14 = debug pointer / usable
+	// r15 = preserved: system call number
+	// r16 = preserved: current task pointer
+	// r17 = wall to monotonic use
+	// r18 = time_interpolator->offset
+	// r19 = address of wall_to_monotonic
+	// r20 = pointer to struct time_interpolator / pointer to time_interpolator->address
+	// r21 = shift factor
+	// r22 = address of time interpolator->last_counter
+	// r23 = address of time_interpolator->last_cycle
+	// r24 = adress of time_interpolator->offset
+	// r25 = last_cycle value
+	// r26 = last_counter value
+	// r27 = pointer to xtime
+	// r28 = sequence number at the beginning of critcal section
+	// r29 = address of seqlock
+	// r30 = time processing flags / memory address
+	// r31 = pointer to result
+	// Predicates
+	// p6,p7 short term use
+	// p8 = timesource ar.itc
+	// p9 = timesource mmio64
+	// p10 = timesource mmio32
+	// p11 = timesource not to be handled by asm code
+	// p12 = memory time source ( = p9 | p10)
+	// p13 = do cmpxchg with time_interpolator_last_cycle
+	// p14 = Divide by 1000
+	// p15 = Add monotonic
+	//
+	// Note that instructions are optimized for McKinley. McKinley can process two
+	// bundles simultaneously and therefore we continuously try to feed the CPU
+	// two bundles and then a stop.
+	tnat.nz p6,p0 = r31	// branch deferred since it does not fit into bundle structure
+	mov pr = r30,0xc000	// Set predicates according to function
+	add r2 = TI_FLAGS+IA64_TASK_SIZE,r16
+	movl r20 = time_interpolator
+	;;
+	ld8 r20 = [r20]		// get pointer to time_interpolator structure
+	movl r29 = xtime_lock
+	ld4 r2 = [r2]		// process work pending flags
+	movl r27 = xtime
+	;;	// only one bundle here
+	ld8 r21 = [r20]		// first quad with control information
+	and r2 = TIF_ALLWORK_MASK,r2
+(p6)    br.cond.spnt.few .fail_einval	// deferred branch
+	;;
+	add r10 = IA64_TIME_INTERPOLATOR_ADDRESS_OFFSET,r20
+	extr r3 = r21,32,32	// time_interpolator->nsec_per_cyc
+	extr r8 = r21,0,16	// time_interpolator->source
+	nop.i 123
+	cmp.ne p6, p0 = 0, r2	// Fallback if work is scheduled
+(p6)    br.cond.spnt.many fsys_fallback_syscall
+	;;
+	cmp.eq p8,p12 = 0,r8	// Check for cpu timer
+	cmp.eq p9,p0 = 1,r8	// MMIO64 ?
+	extr r2 = r21,24,8	// time_interpolator->jitter
+	cmp.eq p10,p0 = 2,r8	// MMIO32 ?
+	cmp.ltu p11,p0 = 2,r8	// function or other clock
+(p11)	br.cond.spnt.many fsys_fallback_syscall
+	;;
+	setf.sig f7 = r3	// Setup for scaling of counter
+(p15)	movl r19 = wall_to_monotonic
+(p12)	ld8 r30 = [r10]
+	cmp.ne p13,p0 = r2,r0	// need jitter compensation?
+	extr r21 = r21,16,8	// shift factor
+	;;
+.time_redo:
+	.pred.rel.mutex p8,p9,p10
+	ld4.acq r28 = [r29]	// xtime_lock.sequence. Must come first for locking purposes
+(p8)	mov r2 = ar.itc		// CPU_TIMER. 36 clocks latency!!!
+	add r22 = IA64_TIME_INTERPOLATOR_LAST_COUNTER_OFFSET,r20
+(p9)	ld8 r2 = [r30]		// readq(ti->address). Could also have latency issues..
+(p10)	ld4 r2 = [r30]		// readw(ti->address)
+(p13)	add r23 = IA64_TIME_INTERPOLATOR_LAST_CYCLE_OFFSET,r20
+	;;			// could be removed by moving the last add upward
+	ld8 r26 = [r22]		// time_interpolator->last_counter
+(p13)	ld8 r25 = [r23]		// time interpolator->last_cycle
+	add r24 = IA64_TIME_INTERPOLATOR_OFFSET_OFFSET,r20
+(p15)	ld8 r17 = [r19],IA64_TIMESPEC_TV_NSEC_OFFSET
+ 	ld8 r9 = [r27],IA64_TIMESPEC_TV_NSEC_OFFSET
+	nop.i 123
+	;;
+	ld8 r18 = [r24]		// time_interpolator->offset
+	ld8 r8 = [r27],-IA64_TIMESPEC_TV_NSEC_OFFSET	// xtime.tv_nsec
+(p13)	sub r3 = r25,r2	// Diff needed before comparison (thanks davidm)
+	;;
+(p13)	cmp.gt.unc p6,p7 = r3,r0	// check if it is less than last. p6,p7 cleared
+	sub r10 = r2,r26	// current_counter - last_counter
+	;;
+(p6)	sub r10 = r25,r26	// time we got was less than last_cycle
+(p7)	mov ar.ccv = r25	// more than last_cycle. Prep for cmpxchg
+	;;
+	setf.sig f8 = r10
+	nop.i 123
+	;;
+(p7)	cmpxchg8.rel r3 = [r23],r2,ar.ccv
+EX(.fail_efault, probe.w.fault r31, 3)	// This takes 5 cycles and we have spare time
+	xmpy.l f8 = f8,f7	// nsec_per_cyc*(counter-last_counter)
+(p15)	add r9 = r9,r17		// Add wall to monotonic.secs to result secs
+	;;
+(p15)	ld8 r17 = [r19],-IA64_TIMESPEC_TV_NSEC_OFFSET
+(p7)	cmp.ne p7,p0 = r25,r3	// if cmpxchg not successful redo
+	// simulate tbit.nz.or p7,p0 = r28,0
+	and r28 = ~1,r28	// Make sequence even to force retry if odd
+	getf.sig r2 = f8
 	mf
-	xma.l f8=f6, f7, f8	// f8 (last_tick) <- -(lost + 1)*itm_delta + itm_next	(5 cyc)
-	nop 0
-
-	setf.sig f12=r31		// f12 <- ITC					(6 cyc)
-	// *** if (unlikely(read_seqretry(&xtime_lock, seq))) continue; ***
-	ld4 r24=[r17]			// r24 = xtime_lock->sequence (re-read)
-	nop 0
-	;;
-
-	xma.l f8=f11, f8, f12	// f8 (elapsed_cycles) <- (-1*last_tick + now) = (now - last_tick)
-	nop 0
-	;;
-
-	getf.sig r18=f8			// r18 <- (now - last_tick)
-	xmpy.l f8=f8, f10		// f8 <- elapsed_cycles*nsec_per_cyc (5 cyc)
-	add r3=r29, r14			// r3 = (nsec + old)
-	;;
-
-	cmp.lt p7, p8=r18, r0		// if now < last_tick, set p7 = 1, p8 = 0
-	getf.sig r18=f8			// r18 = elapsed_cycles*nsec_per_cyc		(6 cyc)
-	nop 0
-	;;
-
-(p10)	cmp.ne p9, p0=r23, r24		// if xtime_lock->sequence != seq, set p9
-	shr.u r18=r18, IA64_NSEC_PER_CYC_SHIFT	// r18 <- offset
-(p9)	br.spnt.many .retry
-	;;
-
-	mov ar.ccv=r14			// ar.ccv = old					(1 cyc)
-	cmp.leu p7, p8=r18, r14		// if (offset <= old), set p7 = 1, p8 = 0
-	;;
-
-(p8)	cmpxchg8.rel r24=[r25], r18, ar.ccv	// compare-and-exchange (atomic!)
-(p8)	add r3=r29, r18			// r3 = (nsec + offset)
-	;;
-	shr.u r3=r3, 3			// initiate dividing r3 by 1000
-	;;
-	setf.sig f8=r3			//						(6 cyc)
-	mov r10=1000000			// r10 = 1000000
-	;;
-(p8)	cmp.ne.unc p9, p0=r24, r14
-	xmpy.hu f6=f8, f9		//						(5 cyc)
-(p9)	br.spnt.many .retry
-	;;
-
-	getf.sig r3=f6			//						(6 cyc)
-	;;
-	shr.u r3=r3, 4			// end of division, r3 is divided by 1000 (=usec)
-	;;
-
-1:	cmp.geu p7, p0=r3, r10		// while (usec >= 1000000)
-	;;
-(p7)	sub r3=r3, r10			// usec -= 1000000
-(p7)	adds r2=1, r2			// ++sec
-(p7)	br.spnt.many 1b
-
-	// finally: r2 = sec, r3 = usec
-EX(.fail_efault, st8 [r32]=r2)
-	adds r9=8, r32
-	mov r8=r0			// success
-	;;
-EX(.fail_efault, st8 [r9]=r3)		// store them in the timeval struct
-	mov r10=0
+	add r8 = r8,r18		// Add time interpolator offset
+	;;
+	ld4 r10 = [r29]		// xtime_lock.sequence
+(p15)	add r8 = r8, r17	// Add monotonic.nsecs to nsecs
+	shr.u r2 = r2,r21
+	;;		// overloaded 3 bundles!
+	// End critical section.
+	add r8 = r8,r2		// Add xtime.nsecs
+	cmp4.ne.or p7,p0 = r28,r10
+(p7)	br.cond.dpnt.few .time_redo	// sequence number changed ?
+	// Now r8=tv->tv_nsec and r9=tv->tv_sec
+	mov r10 = r0
+	movl r2 = 1000000000
+	add r23 = IA64_TIMESPEC_TV_NSEC_OFFSET, r31
+(p14)	movl r3 = 2361183241434822607	// Prep for / 1000 hack
+	;;
+.time_normalize:
+	mov r21 = r8
+	cmp.ge p6,p0 = r8,r2
+(p14)	shr.u r20 = r8, 3		// We can repeat this if necessary just wasting some time
+	;;
+(p14)	setf.sig f8 = r20
+(p6)	sub r8 = r8,r2
+(p6)	add r9 = 1,r9			// two nops before the branch.
+(p14)	setf.sig f7 = r3		// Chances for repeats are 1 in 10000 for gettod
+(p6)	br.cond.dpnt.few .time_normalize
+	;;
+	// Divided by 8 though shift. Now divide by 125
+	// The compiler was able to do that with a multiply
+	// and a shift and we do the same
+EX(.fail_efault, probe.w.fault r23, 3)		// This also costs 5 cycles
+(p14)	xmpy.hu f8 = f8, f7			// xmpy has 5 cycles latency so use it...
+	;;
+	mov r8 = r0
+(p14)	getf.sig r2 = f8
+	;;
+(p14)	shr.u r21 = r2, 4
+	;;
+EX(.fail_efault, st8 [r31] = r9)
+EX(.fail_efault, st8 [r23] = r21)
 	FSYS_RETURN
-	/*
-	 * Note: We are NOT clearing the scratch registers here.  Since the only things
-	 *	 in those registers are time-related variables and some addresses (which
-	 *	 can be obtained from System.map), none of this should be security-sensitive
-	 *	 and we should be fine.
-	 */
-
 .fail_einval:
-	mov r8=EINVAL			// r8 = EINVAL
-	mov r10=-1			// r10 = -1
+	mov r8 = EINVAL
+	mov r10 = -1
 	FSYS_RETURN
-
 .fail_efault:
-	mov r8=EFAULT			// r8 = EFAULT
-	mov r10=-1			// r10 = -1
+	mov r8 = EFAULT
+	mov r10 = -1
 	FSYS_RETURN
 END(fsys_gettimeofday)
 
+ENTRY(fsys_clock_gettime)
+	.prologue
+	.altrp b6
+	.body
+	cmp4.ltu p6, p0 = CLOCK_MONOTONIC, r32
+	// Fallback if this is not CLOCK_REALTIME or CLOCK_MONOTONIC
+(p6)	br.spnt.few fsys_fallback_syscall
+	mov r31 = r33
+	shl r30 = r32,15
+	br.many .gettime
+END(fsys_clock_gettime)
+
 /*
  * long fsys_rt_sigprocmask (int how, sigset_t *set, sigset_t *oset, size_t sigsetsize).
  */
@@ -838,7 +851,7 @@ fsyscall_table:
 	data8 0				// timer_getoverrun
 	data8 0				// timer_delete
 	data8 0				// clock_settime
-	data8 0				// clock_gettime
+	data8 fsys_clock_gettime	// clock_gettime
 	data8 0				// clock_getres		// 1255
 	data8 0				// clock_nanosleep
 	data8 0				// fstatfs64
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
index 032defb0f..0e821d0c3 100644
--- a/arch/ia64/kernel/head.S
+++ b/arch/ia64/kernel/head.S
@@ -781,8 +781,7 @@ GLOBAL_ENTRY(ia64_switch_mode_virt)
 
 	// going to virtual
 	//   - for code addresses, set upper bits of addr to KERNEL_START
-	//   - for stack addresses, set upper 3 bits to 0xe.... Dont change any of the
-	//     lower bits since we want it to stay identity mapped
+	//   - for stack addresses, copy from input argument
 	movl r18=KERNEL_START
 	dep r3=0,r3,KERNEL_TR_PAGE_SHIFT,64-KERNEL_TR_PAGE_SHIFT
 	dep r14=0,r14,KERNEL_TR_PAGE_SHIFT,64-KERNEL_TR_PAGE_SHIFT
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index f032ea1b3..51548a8c5 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -104,7 +104,7 @@ static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED;
 /* These tables map IA-64 vectors to the IOSAPIC pin that generates this vector. */
 
 static struct iosapic_intr_info {
-	char		*addr;		/* base address of IOSAPIC */
+	char __iomem	*addr;		/* base address of IOSAPIC */
 	u32		low32;		/* current value of low word of Redirection table entry */
 	unsigned int	gsi_base;	/* first GSI assigned to this IOSAPIC */
 	char		rte_index;	/* IOSAPIC RTE index (-1 => not an IOSAPIC interrupt) */
@@ -114,9 +114,12 @@ static struct iosapic_intr_info {
 } iosapic_intr_info[IA64_NUM_VECTORS];
 
 static struct iosapic {
-	char		*addr;		/* base address of IOSAPIC */
+	char __iomem	*addr;		/* base address of IOSAPIC */
 	unsigned int 	gsi_base;	/* first GSI assigned to this IOSAPIC */
 	unsigned short 	num_rte;	/* number of RTE in this IOSAPIC */
+#ifdef CONFIG_NUMA
+	unsigned short	node;		/* numa node association via pxm */
+#endif
 } iosapic_lists[NR_IOSAPICS];
 
 static int num_iosapic;
@@ -176,7 +179,7 @@ set_rte (unsigned int vector, unsigned int dest, int mask)
 {
 	unsigned long pol, trigger, dmode, flags;
 	u32 low32, high32;
-	char *addr;
+	char __iomem *addr;
 	int rte_index;
 	char redir;
 
@@ -234,7 +237,7 @@ static void
 mask_irq (unsigned int irq)
 {
 	unsigned long flags;
-	char *addr;
+	char __iomem *addr;
 	u32 low32;
 	int rte_index;
 	ia64_vector vec = irq_to_vector(irq);
@@ -258,7 +261,7 @@ static void
 unmask_irq (unsigned int irq)
 {
 	unsigned long flags;
-	char *addr;
+	char __iomem *addr;
 	u32 low32;
 	int rte_index;
 	ia64_vector vec = irq_to_vector(irq);
@@ -284,7 +287,7 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask)
 	unsigned long flags;
 	u32 high32, low32;
 	int dest, rte_index;
-	char *addr;
+	char __iomem *addr;
 	int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0;
 	ia64_vector vec;
 
@@ -409,7 +412,7 @@ struct hw_interrupt_type irq_type_iosapic_edge = {
 };
 
 unsigned int
-iosapic_version (char *addr)
+iosapic_version (char __iomem *addr)
 {
 	/*
 	 * IOSAPIC Version Register return 32 bit structure like:
@@ -454,7 +457,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery,
 	int rte_index;
 	int index;
 	unsigned long gsi_base;
-	char *iosapic_address;
+	void __iomem *iosapic_address;
 
 	index = find_iosapic(gsi);
 	if (index < 0) {
@@ -488,7 +491,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery,
 }
 
 static unsigned int
-get_target_cpu (void)
+get_target_cpu (unsigned int gsi, int vector)
 {
 #ifdef CONFIG_SMP
 	static int cpu = -1;
@@ -507,6 +510,34 @@ get_target_cpu (void)
 	if (!cpu_online(smp_processor_id()))
 		return hard_smp_processor_id();
 
+#ifdef CONFIG_NUMA
+	{
+		int num_cpus, cpu_index, iosapic_index, numa_cpu, i = 0;
+		cpumask_t cpu_mask;
+
+		iosapic_index = find_iosapic(gsi);
+		if (iosapic_index < 0 ||
+		    iosapic_lists[iosapic_index].node == MAX_NUMNODES)
+			goto skip_numa_setup;
+
+		cpu_mask = node_to_cpumask(iosapic_lists[iosapic_index].node);
+		
+		num_cpus = cpus_weight(cpu_mask);
+
+		if (!num_cpus)
+			goto skip_numa_setup;
+
+		/* Use vector assigment to distribute across cpus in node */
+		cpu_index = vector % num_cpus;
+
+		for (numa_cpu = first_cpu(cpu_mask) ; i < cpu_index ; i++)
+			numa_cpu = next_cpu(numa_cpu, cpu_mask);
+
+		if (numa_cpu != NR_CPUS)
+			return cpu_physical_id(numa_cpu);
+	}
+skip_numa_setup:
+#endif
 	/*
 	 * Otherwise, round-robin interrupt vectors across all the
 	 * processors.  (It'd be nice if we could be smarter in the
@@ -550,7 +581,7 @@ iosapic_register_intr (unsigned int gsi,
 		}
 
 		vector = assign_irq_vector(AUTO_ASSIGN);
-		dest = get_target_cpu();
+		dest = get_target_cpu(gsi, vector);
 		register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
 			polarity, trigger);
 	}
@@ -665,7 +696,7 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
 {
 	int num_rte;
 	unsigned int isa_irq, ver;
-	char *addr;
+	char __iomem *addr;
 
 	addr = ioremap(phys_addr, 0);
 	ver = iosapic_version(addr);
@@ -680,6 +711,9 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
 	iosapic_lists[num_iosapic].addr = addr;
 	iosapic_lists[num_iosapic].gsi_base = gsi_base;
 	iosapic_lists[num_iosapic].num_rte = num_rte;
+#ifdef CONFIG_NUMA
+	iosapic_lists[num_iosapic].node = MAX_NUMNODES;
+#endif
 	num_iosapic++;
 
 	if ((gsi_base == 0) && pcat_compat) {
@@ -692,3 +726,20 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
 			iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE);
 	}
 }
+
+#ifdef CONFIG_NUMA
+void __init
+map_iosapic_to_node(unsigned int gsi_base, int node)
+{
+	int index;
+
+	index = find_iosapic(gsi_base);
+	if (index < 0) {
+		printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n",
+		       __FUNCTION__, gsi_base);
+		return;
+	}
+	iosapic_lists[index].node = node;
+	return;
+}
+#endif
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
index 9ec161c63..f779d97a4 100644
--- a/arch/ia64/kernel/irq.c
+++ b/arch/ia64/kernel/irq.c
@@ -84,11 +84,13 @@ irq_desc_t _irq_desc[NR_IRQS] __cacheline_aligned = {
 	}
 };
 
+#ifdef CONFIG_SMP
 /*
  * This is updated when the user sets irq affinity via /proc
  */
 cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS];
 static unsigned long pending_irq_redir[BITS_TO_LONGS(NR_IRQS)];
+#endif
 
 #ifdef CONFIG_IA64_GENERIC
 irq_desc_t * __ia64_irq_desc (unsigned int irq)
@@ -255,14 +257,16 @@ int handle_IRQ_event(unsigned int irq,
 		struct pt_regs *regs, struct irqaction *action)
 {
 	int status = 1;	/* Force the "do bottom halves" bit */
-	int retval = 0;
+	int ret, retval = 0;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
-		status |= action->flags;
-		retval |= action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
+		retval |= ret;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
@@ -962,7 +966,7 @@ static int irq_affinity_read_proc (char *page, char **start, off_t off,
 	return len;
 }
 
-static int irq_affinity_write_proc (struct file *file, const char *buffer,
+static int irq_affinity_write_proc (struct file *file, const char __user *buffer,
 				    unsigned long count, void *data)
 {
 	unsigned int irq = (unsigned long) data;
@@ -1137,31 +1141,6 @@ void fixup_irqs(void)
 }
 #endif
 
-static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
-	if (count - len < 2)
-		return -EINVAL;
-	len += sprintf(page + len, "\n");
-	return len;
-}
-
-static int prof_cpu_mask_write_proc (struct file *file, const char *buffer,
-					unsigned long count, void *data)
-{
-	cpumask_t *mask = (cpumask_t *)data;
-	unsigned long full_count = count, err;
-	cpumask_t new_value;
-
-	err = cpumask_parse(buffer, count, new_value);
-	if (err)
-		return err;
-
-	*mask = new_value;
-	return full_count;
-}
-
 #define MAX_NAMELEN 10
 
 static void register_irq_proc (unsigned int irq)
@@ -1196,26 +1175,15 @@ static void register_irq_proc (unsigned int irq)
 #endif
 }
 
-cpumask_t prof_cpu_mask = CPU_MASK_ALL;
-
 void init_irq_proc (void)
 {
-	struct proc_dir_entry *entry;
 	int i;
 
 	/* create /proc/irq */
-	root_irq_dir = proc_mkdir("irq", 0);
+	root_irq_dir = proc_mkdir("irq", NULL);
 
 	/* create /proc/irq/prof_cpu_mask */
-	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
-
-	if (!entry)
-		return;
-
-	entry->nlink = 1;
-	entry->data = (void *)&prof_cpu_mask;
-	entry->read_proc = prof_cpu_mask_read_proc;
-	entry->write_proc = prof_cpu_mask_write_proc;
+	create_prof_cpu_mask(root_irq_dir);
 
 	/*
 	 * Create entries for all existing IRQs.
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index e853159b8..335d827ce 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -47,7 +47,8 @@
 #define IRQ_DEBUG	0
 
 /* default base addr of IPI table */
-unsigned long ipi_base_addr = (__IA64_UNCACHED_OFFSET | IA64_IPI_DEFAULT_BASE_ADDR);
+void __iomem *ipi_base_addr = ((void __iomem *)
+			       (__IA64_UNCACHED_OFFSET | IA64_IPI_DEFAULT_BASE_ADDR));
 
 /*
  * Legacy IRQ to IA-64 vector translation table.
@@ -254,7 +255,7 @@ init_IRQ (void)
 void
 ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect)
 {
-	unsigned long ipi_addr;
+	void __iomem *ipi_addr;
 	unsigned long ipi_data;
 	unsigned long phys_cpu_id;
 
@@ -269,7 +270,7 @@ ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect)
 	 */
 
 	ipi_data = (delivery_mode << 8) | (vector & 0xff);
-	ipi_addr = ipi_base_addr | (phys_cpu_id << 4) | ((redirect & 1)  << 3);
+	ipi_addr = ipi_base_addr + ((phys_cpu_id << 4) | ((redirect & 1) << 3));
 
 	writeq(ipi_data, ipi_addr);
 }
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 9c5104cc5..aa76ea054 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -82,11 +82,6 @@
 # define IA64_MCA_DEBUG(fmt...)
 #endif
 
-typedef struct ia64_fptr {
-	unsigned long fp;
-	unsigned long gp;
-} ia64_fptr_t;
-
 /* Used by mca_asm.S */
 ia64_mca_sal_to_os_state_t	ia64_sal_to_os_handoff_state;
 ia64_mca_os_to_sal_state_t	ia64_os_to_sal_handoff_state;
@@ -831,6 +826,31 @@ ia64_return_to_sal_check(int recover)
 
 }
 
+/* Function pointer for extra MCA recovery */
+int (*ia64_mca_ucmc_extension)
+	(void*,ia64_mca_sal_to_os_state_t*,ia64_mca_os_to_sal_state_t*)
+	= NULL;
+
+int
+ia64_reg_MCA_extension(void *fn)
+{
+	if (ia64_mca_ucmc_extension)
+		return 1;
+
+	ia64_mca_ucmc_extension = fn;
+	return 0;
+}
+
+void
+ia64_unreg_MCA_extension(void)
+{
+	if (ia64_mca_ucmc_extension)
+		ia64_mca_ucmc_extension = NULL;
+}
+
+EXPORT_SYMBOL(ia64_reg_MCA_extension);
+EXPORT_SYMBOL(ia64_unreg_MCA_extension);
+
 /*
  * ia64_mca_ucmc_handler
  *
@@ -852,11 +872,20 @@ ia64_mca_ucmc_handler(void)
 {
 	pal_processor_state_info_t *psp = (pal_processor_state_info_t *)
 		&ia64_sal_to_os_handoff_state.proc_state_param;
-	int recover = psp->tc && !(psp->cc || psp->bc || psp->rc || psp->uc);
+	int recover; 
 
 	/* Get the MCA error record and log it */
 	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA);
 
+	/* TLB error is only exist in this SAL error record */
+	recover = (psp->tc && !(psp->cc || psp->bc || psp->rc || psp->uc))
+	/* other error recovery */
+	   || (ia64_mca_ucmc_extension 
+		&& ia64_mca_ucmc_extension(
+			IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_MCA),
+			&ia64_sal_to_os_handoff_state,
+			&ia64_os_to_sal_handoff_state)); 
+
 	/*
 	 *  Wakeup all the processors which are spinning in the rendezvous
 	 *  loop.
diff --git a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h
index 540301f6e..b1460dcc3 100644
--- a/arch/ia64/kernel/minstate.h
+++ b/arch/ia64/kernel/minstate.h
@@ -54,8 +54,7 @@
 (pUStk)	mov ar.rsc=0x3;		/* set eager mode, pl 0, little-endian, loadrs=0 */		\
 
 #define MINSTATE_END_SAVE_MIN_PHYS								\
-	or r12=r12,r14;		/* make sp a kernel virtual address */				\
-	or r13=r13,r14;		/* make `current' a kernel virtual address */			\
+	dep r12=-1,r12,61,3;		/* make sp a kernel virtual address */			\
 	;;
 
 #ifdef MINSTATE_VIRT
@@ -65,7 +64,7 @@
 #endif
 
 #ifdef MINSTATE_PHYS
-# define MINSTATE_GET_CURRENT(reg)	mov reg=IA64_KR(CURRENT);; dep reg=0,reg,61,3
+# define MINSTATE_GET_CURRENT(reg)	mov reg=IA64_KR(CURRENT);; tpa reg=reg
 # define MINSTATE_START_SAVE_MIN	MINSTATE_START_SAVE_MIN_PHYS
 # define MINSTATE_END_SAVE_MIN		MINSTATE_END_SAVE_MIN_PHYS
 #endif
@@ -172,7 +171,6 @@
 	;;											\
 .mem.offset 0,0; st8.spill [r16]=r15,16;							\
 .mem.offset 8,0; st8.spill [r17]=r14,16;							\
-	dep r14=-1,r0,61,3;									\
 	;;											\
 .mem.offset 0,0; st8.spill [r16]=r2,16;								\
 .mem.offset 8,0; st8.spill [r17]=r3,16;								\
diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c
index 2ee61a213..febc091c2 100644
--- a/arch/ia64/kernel/module.c
+++ b/arch/ia64/kernel/module.c
@@ -195,10 +195,10 @@ apply_imm22 (struct module *mod, struct insn *insn, uint64_t val)
 		printk(KERN_ERR "%s: value %li out of IMM22 range\n", mod->name, (int64_t)val);
 		return 0;
 	}
-	ia64_patch((u64) insn, 0x01fffcfe000, (  ((val & 0x200000) << 15) /* bit 21 -> 36 */
-					       | ((val & 0x1f0000) <<  6) /* bit 16 -> 22 */
-					       | ((val & 0x00ff80) << 20) /* bit  7 -> 27 */
-					       | ((val & 0x00007f) << 13) /* bit  0 -> 13 */));
+	ia64_patch((u64) insn, 0x01fffcfe000UL, (  ((val & 0x200000UL) << 15) /* bit 21 -> 36 */
+					         | ((val & 0x1f0000UL) <<  6) /* bit 16 -> 22 */
+					         | ((val & 0x00ff80UL) << 20) /* bit  7 -> 27 */
+					         | ((val & 0x00007fUL) << 13) /* bit  0 -> 13 */));
 	return 1;
 }
 
@@ -209,8 +209,8 @@ apply_imm21b (struct module *mod, struct insn *insn, uint64_t val)
 		printk(KERN_ERR "%s: value %li out of IMM21b range\n", mod->name, (int64_t)val);
 		return 0;
 	}
-	ia64_patch((u64) insn, 0x11ffffe000, (  ((val & 0x100000) << 16) /* bit 20 -> 36 */
-					      | ((val & 0x0fffff) << 13) /* bit  0 -> 13 */));
+	ia64_patch((u64) insn, 0x11ffffe000UL, (  ((val & 0x100000UL) << 16) /* bit 20 -> 36 */
+					        | ((val & 0x0fffffUL) << 13) /* bit  0 -> 13 */));
 	return 1;
 }
 
@@ -253,9 +253,9 @@ plt_target (struct plt_entry *plt)
 	long off;
 
 	b0 = b[0]; b1 = b[1];
-	off = (  ((b1 & 0x00fffff000000000) >> 36)		/* imm20b -> bit 0 */
-	       | ((b0 >> 48) << 20) | ((b1 & 0x7fffff) << 36)	/* imm39 -> bit 20 */
-	       | ((b1 & 0x0800000000000000) << 0));		/* i -> bit 59 */
+	off = (  ((b1 & 0x00fffff000000000UL) >> 36)		/* imm20b -> bit 0 */
+	       | ((b0 >> 48) << 20) | ((b1 & 0x7fffffUL) << 36)	/* imm39 -> bit 20 */
+	       | ((b1 & 0x0800000000000000UL) << 0));		/* i -> bit 59 */
 	return (long) plt->bundle[1] + 16*off;
 }
 
@@ -739,7 +739,7 @@ do_reloc (struct module *mod, uint8_t r_type, Elf64_Sym *sym, uint64_t addend,
 			if (gp_addressable(mod, val)) {
 				/* turn "ld8" into "mov": */
 				DEBUGP("%s: patching ld8 at %p to mov\n", __FUNCTION__, location);
-				ia64_patch((u64) location, 0x1fff80fe000, 0x10000000000);
+				ia64_patch((u64) location, 0x1fff80fe000UL, 0x10000000000UL);
 			}
 			return 0;
 
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
index 3cbe961ed..25e7c8344 100644
--- a/arch/ia64/kernel/palinfo.c
+++ b/arch/ia64/kernel/palinfo.c
@@ -446,7 +446,7 @@ register_info(char *page)
 		     "RSE stacked physical registers   : %ld\n"
 		     "RSE load/store hints             : %ld (%s)\n",
 		     phys_stacked, hints.ph_data,
-		     hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(\?\?)");
+		     hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(??)");
 
 	if (ia64_pal_debug_info(&iregs, &dregs))
 		return 0;
@@ -479,7 +479,7 @@ static const char *proc_features[]={
 	"Enable CMCI promotion",
 	"Enable MCA to BINIT promotion",
 	"Enable MCA promotion",
-	"Enable BEER promotion"
+	"Enable BERR promotion"
 };
 
 
diff --git a/arch/ia64/kernel/patch.c b/arch/ia64/kernel/patch.c
index ef04f5df0..367804a60 100644
--- a/arch/ia64/kernel/patch.c
+++ b/arch/ia64/kernel/patch.c
@@ -65,21 +65,21 @@ void
 ia64_patch_imm64 (u64 insn_addr, u64 val)
 {
 	ia64_patch(insn_addr,
-		   0x01fffefe000, (  ((val & 0x8000000000000000) >> 27) /* bit 63 -> 36 */
-				   | ((val & 0x0000000000200000) <<  0) /* bit 21 -> 21 */
-				   | ((val & 0x00000000001f0000) <<  6) /* bit 16 -> 22 */
-				   | ((val & 0x000000000000ff80) << 20) /* bit  7 -> 27 */
-				   | ((val & 0x000000000000007f) << 13) /* bit  0 -> 13 */));
-	ia64_patch(insn_addr - 1, 0x1ffffffffff, val >> 22);
+		   0x01fffefe000UL, (  ((val & 0x8000000000000000UL) >> 27) /* bit 63 -> 36 */
+				     | ((val & 0x0000000000200000UL) <<  0) /* bit 21 -> 21 */
+				     | ((val & 0x00000000001f0000UL) <<  6) /* bit 16 -> 22 */
+				     | ((val & 0x000000000000ff80UL) << 20) /* bit  7 -> 27 */
+				     | ((val & 0x000000000000007fUL) << 13) /* bit  0 -> 13 */));
+	ia64_patch(insn_addr - 1, 0x1ffffffffffUL, val >> 22);
 }
 
 void
 ia64_patch_imm60 (u64 insn_addr, u64 val)
 {
 	ia64_patch(insn_addr,
-		   0x011ffffe000, (  ((val & 0x0800000000000000) >> 23) /* bit 59 -> 36 */
-				   | ((val & 0x00000000000fffff) << 13) /* bit  0 -> 13 */));
-	ia64_patch(insn_addr - 1, 0x1fffffffffc, val >> 18);
+		   0x011ffffe000UL, (  ((val & 0x0800000000000000UL) >> 23) /* bit 59 -> 36 */
+				     | ((val & 0x00000000000fffffUL) << 13) /* bit  0 -> 13 */));
+	ia64_patch(insn_addr - 1, 0x1fffffffffcUL, val >> 18);
 }
 
 /*
@@ -130,10 +130,10 @@ ia64_patch_mckinley_e9 (unsigned long start, unsigned long end)
 
 	while (offp < (s32 *) end) {
 		wp = (u64 *) ia64_imva((char *) offp + *offp);
-		wp[0] = 0x0000000100000000; /* nop.m 0; nop.i 0; nop.i 0 */
-		wp[1] = 0x0004000000000200;
-		wp[2] = 0x0000000100000011; /* nop.m 0; nop.i 0; br.ret.sptk.many b6 */
-		wp[3] = 0x0084006880000200;
+		wp[0] = 0x0000000100000000UL; /* nop.m 0; nop.i 0; nop.i 0 */
+		wp[1] = 0x0004000000000200UL;
+		wp[2] = 0x0000000100000011UL; /* nop.m 0; nop.i 0; br.ret.sptk.many b6 */
+		wp[3] = 0x0084006880000200UL;
 		ia64_fc(wp); ia64_fc(wp + 2);
 		++offp;
 	}
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 2f71b39ea..99b16dacf 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -38,6 +38,8 @@
 #include <linux/pagemap.h>
 #include <linux/mount.h>
 #include <linux/version.h>
+#include <linux/vs_memory.h>
+#include <linux/vs_cvirt.h>
 
 #include <asm/bitops.h>
 #include <asm/errno.h>
@@ -1513,7 +1515,7 @@ exit_pfm_fs(void)
 }
 
 static ssize_t
-pfm_read(struct file *filp, char *buf, size_t size, loff_t *ppos)
+pfm_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
 {
 	pfm_context_t *ctx;
 	pfm_msg_t *msg;
@@ -1606,7 +1608,7 @@ abort:
 }
 
 static ssize_t
-pfm_write(struct file *file, const char *ubuf,
+pfm_write(struct file *file, const char __user *ubuf,
 			  size_t size, loff_t *ppos)
 {
 	DPRINT(("pfm_write called\n"));
@@ -1678,7 +1680,6 @@ static int
 pfm_fasync(int fd, struct file *filp, int on)
 {
 	pfm_context_t *ctx;
-	unsigned long flags;
 	int ret;
 
 	if (PFM_IS_FILE(filp) == 0) {
@@ -1691,19 +1692,21 @@ pfm_fasync(int fd, struct file *filp, int on)
 		printk(KERN_ERR "perfmon: pfm_fasync NULL ctx [%d]\n", current->pid);
 		return -EBADF;
 	}
-
-
-	PROTECT_CTX(ctx, flags);
-
+	/*
+	 * we cannot mask interrupts during this call because this may
+	 * may go to sleep if memory is not readily avalaible.
+	 *
+	 * We are protected from the conetxt disappearing by the get_fd()/put_fd()
+	 * done in caller. Serialization of this function is ensured by caller.
+	 */
 	ret = pfm_do_fasync(fd, filp, ctx, on);
 
+
 	DPRINT(("pfm_fasync called on ctx_fd=%d on=%d async_queue=%p ret=%d\n",
 		fd,
 		on,
 		ctx->ctx_async_queue, ret));
 
-	UNPROTECT_CTX(ctx, flags);
-
 	return ret;
 }
 
@@ -2227,6 +2230,15 @@ out:
 static void
 pfm_free_fd(int fd, struct file *file)
 {
+	struct files_struct *files = current->files;
+
+	/* 
+	 * there ie no fd_uninstall(), so we do it here
+	 */
+	spin_lock(&files->file_lock);
+        files->fd[fd] = NULL;
+	spin_unlock(&files->file_lock);
+
 	if (file) put_filp(file);
 	put_unused_fd(fd);
 }
@@ -2277,7 +2289,7 @@ pfm_smpl_buffer_alloc(struct task_struct *task, pfm_context_t *ctx, unsigned lon
 	 * if ((mm->total_vm << PAGE_SHIFT) + len> task->rlim[RLIMIT_AS].rlim_cur)
 	 * 	return -ENOMEM;
 	 */
-	if (size > task->rlim[RLIMIT_MEMLOCK].rlim_cur) return -EAGAIN;
+	if (size > task->rlim[RLIMIT_MEMLOCK].rlim_cur) return -ENOMEM;
 
 	/*
 	 * We do the easy to undo allocations first.
@@ -2353,7 +2365,7 @@ pfm_smpl_buffer_alloc(struct task_struct *task, pfm_context_t *ctx, unsigned lon
 
 	// mm->total_vm  += size >> PAGE_SHIFT;
 	vx_vmpages_add(mm, size >> PAGE_SHIFT);
-
+	vm_stat_account(vma);
 	up_write(&task->mm->mmap_sem);
 
 	/*
@@ -2593,7 +2605,7 @@ pfm_task_incompatible(pfm_context_t *ctx, struct task_struct *task)
 	 */
 	if (task == current) return 0;
 
-	if (task->state != TASK_STOPPED) {
+	if ((task->state != TASK_STOPPED) && (task->state != TASK_TRACED)) {
 		DPRINT(("cannot attach to non-stopped task [%d] state=%ld\n", task->pid, task->state));
 		return -EBUSY;
 	}
@@ -2660,8 +2672,10 @@ pfm_context_create(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg
 	ctx = pfm_context_alloc();
 	if (!ctx) goto error;
 
-	req->ctx_fd = ctx->ctx_fd = pfm_alloc_fd(&filp);
-	if (req->ctx_fd < 0) goto error_file;
+	ret = pfm_alloc_fd(&filp);
+	if (ret < 0) goto error_file;
+
+	req->ctx_fd = ctx->ctx_fd = ret;
 
 	/*
 	 * attach context to file
@@ -3986,7 +4000,10 @@ pfm_stop(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
 	state     = ctx->ctx_state;
 	is_system = ctx->ctx_fl_system;
 
-	if (state != PFM_CTX_LOADED && state != PFM_CTX_MASKED) return -EINVAL;
+	/*
+	 * context must be attached to issue the stop command (includes LOADED,MASKED,ZOMBIE)
+	 */
+	if (state == PFM_CTX_UNLOADED) return -EINVAL;
 
 	/*
  	 * In system wide and when the context is loaded, access can only happen
@@ -4742,7 +4759,7 @@ recheck:
 	 * the task must be stopped.
 	 */
 	if (PFM_CMD_STOPPED(cmd)) {
-		if (task->state != TASK_STOPPED) {
+		if ((task->state != TASK_STOPPED) && (task->state != TASK_TRACED)) {
 			DPRINT(("[%d] task not in stopped state\n", task->pid));
 			return -EBUSY;
 		}
@@ -4783,7 +4800,7 @@ recheck:
  * system-call entry point (must return long)
  */
 asmlinkage long
-sys_perfmonctl (int fd, int cmd, void *arg, int count, long arg5, long arg6, long arg7,
+sys_perfmonctl (int fd, int cmd, void __user *arg, int count, long arg5, long arg6, long arg7,
 		long arg8, long stack)
 {
 	struct pt_regs *regs = (struct pt_regs *)&stack;
@@ -6313,15 +6330,15 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx)
 	 */
 	is_self = ctx->ctx_task == task ? 1 : 0;
 
-#ifdef CONFIG_SMP
-	if (task == current) {
-#else
 	/*
-	 * in UP, the state can still be in the registers
+	 * can access PMU is task is the owner of the PMU state on the current CPU
+	 * or if we are running on the CPU bound to the context in system-wide mode
+	 * (that is not necessarily the task the context is attached to in this mode).
+	 * In system-wide we always have can_access_pmu true because a task running on an
+	 * invalid processor is flagged earlier in the call stack (see pfm_stop).
 	 */
-	if (task == current || GET_PMU_OWNER() == task) {
-#endif
-		can_access_pmu = 1;
+	can_access_pmu = (GET_PMU_OWNER() == task) || (ctx->ctx_fl_system && ctx->ctx_cpu == smp_processor_id());
+	if (can_access_pmu) {
 		/*
 		 * Mark the PMU as not owned
 		 * This will cause the interrupt handler to do nothing in case an overflow
@@ -6331,6 +6348,7 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx)
 		 * on.
 		 */
 		SET_PMU_OWNER(NULL, NULL);
+		DPRINT(("releasing ownership\n"));
 
 		/*
 		 * read current overflow status:
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 842c95b8a..56ffa1a5d 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -74,12 +74,12 @@ void
 show_stack (struct task_struct *task, unsigned long *sp)
 {
 	if (!task)
-		unw_init_running(ia64_do_show_stack, 0);
+		unw_init_running(ia64_do_show_stack, NULL);
 	else {
 		struct unw_frame_info info;
 
 		unw_init_from_blocked_task(&info, task);
-		ia64_do_show_stack(&info, 0);
+		ia64_do_show_stack(&info, NULL);
 	}
 }
 
@@ -138,7 +138,7 @@ show_regs (struct pt_regs *regs)
 		ndirty = (regs->loadrs >> 19);
 		bsp = ia64_rse_skip_regs((unsigned long *) regs->ar_bspstore, ndirty);
 		for (i = 0; i < sof; ++i) {
-			get_user(val, ia64_rse_skip_regs(bsp, i));
+			get_user(val, (unsigned long __user *) ia64_rse_skip_regs(bsp, i));
 			printk("r%-3u:%c%016lx%s", 32 + i, is_nat ? '*' : ' ', val,
 			       ((i == sof - 1) || (i % 3) == 2) ? "\n" : " ");
 		}
@@ -228,18 +228,26 @@ cpu_idle (void *unused)
 
 	/* endless idle loop with no priority at all */
 	while (1) {
-		void (*idle)(void) = pm_idle;
-		if (!idle)
-			idle = default_idle;
-
 #ifdef CONFIG_SMP
 		if (!need_resched())
 			min_xtp();
 #endif
 		while (!need_resched()) {
+			void (*idle)(void);
+
 			if (mark_idle)
 				(*mark_idle)(1);
+			/*
+			 * Mark this as an RCU critical section so that
+			 * synchronize_kernel() in the unload path waits
+			 * for our completion.
+			 */
+			rcu_read_lock();
+			idle = pm_idle;
+			if (!idle)
+				idle = default_idle;
 			(*idle)();
+			rcu_read_unlock();
 		}
 
 		if (mark_idle)
@@ -602,16 +610,18 @@ dump_fpu (struct pt_regs *pt, elf_fpregset_t dst)
 }
 
 asmlinkage long
-sys_execve (char *filename, char **argv, char **envp, struct pt_regs *regs)
+sys_execve (char __user *filename, char __user * __user *argv, char __user * __user *envp,
+	    struct pt_regs *regs)
 {
+	char *fname;
 	int error;
 
-	filename = getname(filename);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
+	fname = getname(filename);
+	error = PTR_ERR(fname);
+	if (IS_ERR(fname))
 		goto out;
-	error = do_execve(filename, argv, envp, regs);
-	putname(filename);
+	error = do_execve(fname, argv, envp, regs);
+	putname(fname);
 out:
 	return error;
 }
@@ -743,7 +753,7 @@ cpu_halt (void)
 void
 machine_restart (char *restart_cmd)
 {
-	(*efi.reset_system)(EFI_RESET_WARM, 0, 0, 0);
+	(*efi.reset_system)(EFI_RESET_WARM, 0, 0, NULL);
 }
 
 EXPORT_SYMBOL(machine_restart);
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 4ca33dfb8..66e7f9fbc 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -152,7 +152,7 @@ ia64_increment_ip (struct pt_regs *regs)
 		ri = 0;
 		regs->cr_iip += 16;
 	} else if (ri == 2) {
-		get_user(w0, (char *) regs->cr_iip + 0);
+		get_user(w0, (char __user *) regs->cr_iip + 0);
 		if (((w0 >> 1) & 0xf) == IA64_MLX_TEMPLATE) {
 			/*
 			 * rfi'ing to slot 2 of an MLX bundle causes
@@ -174,7 +174,7 @@ ia64_decrement_ip (struct pt_regs *regs)
 	if (ia64_psr(regs)->ri == 0) {
 		regs->cr_iip -= 16;
 		ri = 2;
-		get_user(w0, (char *) regs->cr_iip + 0);
+		get_user(w0, (char __user *) regs->cr_iip + 0);
 		if (((w0 >> 1) & 0xf) == IA64_MLX_TEMPLATE) {
 			/*
 			 * rfi'ing to slot 2 of an MLX bundle causes
@@ -833,7 +833,7 @@ access_uarea (struct task_struct *child, unsigned long addr, unsigned long *data
 		      case PT_CFM:
 			urbs_end = ia64_get_user_rbs_end(child, pt, &cfm);
 			if (write_access) {
-				if (((cfm ^ *data) & 0x3fffffffffU) != 0) {
+				if (((cfm ^ *data) & 0x3fffffffffUL) != 0) {
 					if (ia64_sync_user_rbs(child, sw,
 							       pt->ar_bspstore, urbs_end) < 0)
 						return -1;
@@ -997,12 +997,14 @@ access_uarea (struct task_struct *child, unsigned long addr, unsigned long *data
 }
 
 static long
-ptrace_getregs (struct task_struct *child, struct pt_all_user_regs *ppr)
+ptrace_getregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
 {
+	unsigned long psr, ec, lc, rnat, bsp, cfm, nat_bits, val;
+	struct unw_frame_info info;
+	struct ia64_fpreg fpval;
 	struct switch_stack *sw;
 	struct pt_regs *pt;
 	long ret, retval;
-	struct unw_frame_info info;
 	char nat = 0;
 	int i;
 
@@ -1023,12 +1025,21 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs *ppr)
 		return -EIO;
 	}
 
+	if (access_uarea(child, PT_CR_IPSR, &psr, 0) < 0
+	    || access_uarea(child, PT_AR_EC, &ec, 0) < 0
+	    || access_uarea(child, PT_AR_LC, &lc, 0) < 0
+	    || access_uarea(child, PT_AR_RNAT, &rnat, 0) < 0
+	    || access_uarea(child, PT_AR_BSP, &bsp, 0) < 0
+	    || access_uarea(child, PT_CFM, &cfm, 0)
+	    || access_uarea(child, PT_NAT_BITS, &nat_bits, 0))
+		return -EIO;
+
 	retval = 0;
 
 	/* control regs */
 
 	retval |= __put_user(pt->cr_iip, &ppr->cr_iip);
-	retval |= access_uarea(child, PT_CR_IPSR, &ppr->cr_ipsr, 0);
+	retval |= __put_user(psr, &ppr->cr_ipsr);
 
 	/* app regs */
 
@@ -1039,11 +1050,11 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs *ppr)
 	retval |= __put_user(pt->ar_ccv, &ppr->ar[PT_AUR_CCV]);
 	retval |= __put_user(pt->ar_fpsr, &ppr->ar[PT_AUR_FPSR]);
 
-	retval |= access_uarea(child, PT_AR_EC, &ppr->ar[PT_AUR_EC], 0);
-	retval |= access_uarea(child, PT_AR_LC, &ppr->ar[PT_AUR_LC], 0);
-	retval |= access_uarea(child, PT_AR_RNAT, &ppr->ar[PT_AUR_RNAT], 0);
-	retval |= access_uarea(child, PT_AR_BSP, &ppr->ar[PT_AUR_BSP], 0);
-	retval |= access_uarea(child, PT_CFM, &ppr->cfm, 0);
+	retval |= __put_user(ec, &ppr->ar[PT_AUR_EC]);
+	retval |= __put_user(lc, &ppr->ar[PT_AUR_LC]);
+	retval |= __put_user(rnat, &ppr->ar[PT_AUR_RNAT]);
+	retval |= __put_user(bsp, &ppr->ar[PT_AUR_BSP]);
+	retval |= __put_user(cfm, &ppr->cfm);
 
 	/* gr1-gr3 */
 
@@ -1053,7 +1064,9 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs *ppr)
 	/* gr4-gr7 */
 
 	for (i = 4; i < 8; i++) {
-		retval |= unw_access_gr(&info, i, &ppr->gr[i], &nat, 0);
+		if (unw_access_gr(&info, i, &val, &nat, 0) < 0)
+			return -EIO;
+		retval |= __put_user(val, &ppr->gr[i]);
 	}
 
 	/* gr8-gr11 */
@@ -1077,7 +1090,9 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs *ppr)
 	/* b1-b5 */
 
 	for (i = 1; i < 6; i++) {
-		retval |= unw_access_br(&info, i, &ppr->br[i], 0);
+		if (unw_access_br(&info, i, &val, 0) < 0)
+			return -EIO;
+		__put_user(val, &ppr->br[i]);
 	}
 
 	/* b6-b7 */
@@ -1088,8 +1103,9 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs *ppr)
 	/* fr2-fr5 */
 
 	for (i = 2; i < 6; i++) {
-		retval |= access_fr(&info, i, 0, (unsigned long *) &ppr->fr[i], 0);
-		retval |= access_fr(&info, i, 1, (unsigned long *) &ppr->fr[i] + 1, 0);
+		if (unw_get_fr(&info, i, &fpval) < 0)
+			return -EIO;
+		retval |= __copy_to_user(&ppr->fr[i], &fpval, sizeof (fpval));
 	}
 
 	/* fr6-fr11 */
@@ -1103,8 +1119,9 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs *ppr)
 	/* fr16-fr31 */
 
 	for (i = 16; i < 32; i++) {
-		retval |= access_fr(&info, i, 0, (unsigned long *) &ppr->fr[i], 0);
-		retval |= access_fr(&info, i, 1, (unsigned long *) &ppr->fr[i] + 1, 0);
+		if (unw_get_fr(&info, i, &fpval) < 0)
+			return -EIO;
+		retval |= __copy_to_user(&ppr->fr[i], &fpval, sizeof (fpval));
 	}
 
 	/* fph */
@@ -1118,22 +1135,25 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs *ppr)
 
 	/* nat bits */
 
-	retval |= access_uarea(child, PT_NAT_BITS, &ppr->nat, 0);
+	retval |= __put_user(nat_bits, &ppr->nat);
 
 	ret = retval ? -EIO : 0;
 	return ret;
 }
 
 static long
-ptrace_setregs (struct task_struct *child, struct pt_all_user_regs *ppr)
+ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
 {
+	unsigned long psr, ec, lc, rnat, bsp, cfm, nat_bits, val = 0;
+	struct unw_frame_info info;
 	struct switch_stack *sw;
+	struct ia64_fpreg fpval;
 	struct pt_regs *pt;
 	long ret, retval;
-	struct unw_frame_info info;
-	char nat = 0;
 	int i;
 
+	memset(&fpval, 0, sizeof(fpval));
+
 	retval = verify_area(VERIFY_READ, ppr, sizeof(struct pt_all_user_regs));
 	if (retval != 0) {
 		return -EIO;
@@ -1156,7 +1176,7 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs *ppr)
 	/* control regs */
 
 	retval |= __get_user(pt->cr_iip, &ppr->cr_iip);
-	retval |= access_uarea(child, PT_CR_IPSR, &ppr->cr_ipsr, 1);
+	retval |= __get_user(psr, &ppr->cr_ipsr);
 
 	/* app regs */
 
@@ -1167,11 +1187,11 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs *ppr)
 	retval |= __get_user(pt->ar_ccv, &ppr->ar[PT_AUR_CCV]);
 	retval |= __get_user(pt->ar_fpsr, &ppr->ar[PT_AUR_FPSR]);
 
-	retval |= access_uarea(child, PT_AR_EC, &ppr->ar[PT_AUR_EC], 1);
-	retval |= access_uarea(child, PT_AR_LC, &ppr->ar[PT_AUR_LC], 1);
-	retval |= access_uarea(child, PT_AR_RNAT, &ppr->ar[PT_AUR_RNAT], 1);
-	retval |= access_uarea(child, PT_AR_BSP, &ppr->ar[PT_AUR_BSP], 1);
-	retval |= access_uarea(child, PT_CFM, &ppr->cfm, 1);
+	retval |= __get_user(ec, &ppr->ar[PT_AUR_EC]);
+	retval |= __get_user(lc, &ppr->ar[PT_AUR_LC]);
+	retval |= __get_user(rnat, &ppr->ar[PT_AUR_RNAT]);
+	retval |= __get_user(bsp, &ppr->ar[PT_AUR_BSP]);
+	retval |= __get_user(cfm, &ppr->cfm);
 
 	/* gr1-gr3 */
 
@@ -1181,11 +1201,9 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs *ppr)
 	/* gr4-gr7 */
 
 	for (i = 4; i < 8; i++) {
-		long ret = unw_get_gr(&info, i, &ppr->gr[i], &nat);
-		if (ret < 0) {
-			return ret;
-		}
-		retval |= unw_access_gr(&info, i, &ppr->gr[i], &nat, 1);
+		retval |= __get_user(val, &ppr->gr[i]);
+		if (unw_set_gr(&info, i, val, 0) < 0)	 /* NaT bit will be set via PT_NAT_BITS */
+			return -EIO;
 	}
 
 	/* gr8-gr11 */
@@ -1209,7 +1227,8 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs *ppr)
 	/* b1-b5 */
 
 	for (i = 1; i < 6; i++) {
-		retval |= unw_access_br(&info, i, &ppr->br[i], 1);
+		retval |= __get_user(val, &ppr->br[i]);
+		unw_set_br(&info, i, val);
 	}
 
 	/* b6-b7 */
@@ -1220,8 +1239,9 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs *ppr)
 	/* fr2-fr5 */
 
 	for (i = 2; i < 6; i++) {
-		retval |= access_fr(&info, i, 0, (unsigned long *) &ppr->fr[i], 1);
-		retval |= access_fr(&info, i, 1, (unsigned long *) &ppr->fr[i] + 1, 1);
+		retval |= __copy_from_user(&fpval, &ppr->fr[i], sizeof(fpval));
+		if (unw_set_fr(&info, i, fpval) < 0)
+			return -EIO;
 	}
 
 	/* fr6-fr11 */
@@ -1235,8 +1255,9 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs *ppr)
 	/* fr16-fr31 */
 
 	for (i = 16; i < 32; i++) {
-		retval |= access_fr(&info, i, 0, (unsigned long *) &ppr->fr[i], 1);
-		retval |= access_fr(&info, i, 1, (unsigned long *) &ppr->fr[i] + 1, 1);
+		retval |= __copy_from_user(&fpval, &ppr->fr[i], sizeof(fpval));
+		if (unw_set_fr(&info, i, fpval) < 0)
+			return -EIO;
 	}
 
 	/* fph */
@@ -1250,7 +1271,15 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs *ppr)
 
 	/* nat bits */
 
-	retval |= access_uarea(child, PT_NAT_BITS, &ppr->nat, 1);
+	retval |= __get_user(nat_bits, &ppr->nat);
+
+	retval |= access_uarea(child, PT_CR_IPSR, &psr, 1);
+	retval |= access_uarea(child, PT_AR_EC, &ec, 1);
+	retval |= access_uarea(child, PT_AR_LC, &lc, 1);
+	retval |= access_uarea(child, PT_AR_RNAT, &rnat, 1);
+	retval |= access_uarea(child, PT_AR_BSP, &bsp, 1);
+	retval |= access_uarea(child, PT_CFM, &cfm, 1);
+	retval |= access_uarea(child, PT_NAT_BITS, &nat_bits, 1);
 
 	ret = retval ? -EIO : 0;
 	return ret;
@@ -1432,11 +1461,11 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data,
 		goto out_tsk;
 
 	      case PTRACE_GETREGS:
-		ret = ptrace_getregs(child, (struct pt_all_user_regs*) data);
+		ret = ptrace_getregs(child, (struct pt_all_user_regs __user *) data);
 		goto out_tsk;
 
 	      case PTRACE_SETREGS:
-		ret = ptrace_setregs(child, (struct pt_all_user_regs*) data);
+		ret = ptrace_setregs(child, (struct pt_all_user_regs __user *) data);
 		goto out_tsk;
 
 	      default:
diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c
index dcbc07ec3..3ec0d2d22 100644
--- a/arch/ia64/kernel/sal.c
+++ b/arch/ia64/kernel/sal.c
@@ -10,6 +10,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
 
@@ -262,3 +263,40 @@ ia64_sal_init (struct ia64_sal_systab *systab)
 		p += SAL_DESC_SIZE(*p);
 	}
 }
+
+int
+ia64_sal_oemcall(struct ia64_sal_retval *isrvp, u64 oemfunc, u64 arg1,
+		 u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7)
+{
+	if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX)
+		return -1;
+	SAL_CALL(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+	return 0;
+}
+EXPORT_SYMBOL(ia64_sal_oemcall);
+
+int
+ia64_sal_oemcall_nolock(struct ia64_sal_retval *isrvp, u64 oemfunc, u64 arg1,
+			u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6,
+			u64 arg7)
+{
+	if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX)
+		return -1;
+	SAL_CALL_NOLOCK(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6,
+			arg7);
+	return 0;
+}
+EXPORT_SYMBOL(ia64_sal_oemcall_nolock);
+
+int
+ia64_sal_oemcall_reentrant(struct ia64_sal_retval *isrvp, u64 oemfunc,
+			   u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5,
+			   u64 arg6, u64 arg7)
+{
+	if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX)
+		return -1;
+	SAL_CALL_REENTRANT(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6,
+			   arg7);
+	return 0;
+}
+EXPORT_SYMBOL(ia64_sal_oemcall_reentrant);
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
index a0420ae4d..500e1050c 100644
--- a/arch/ia64/kernel/salinfo.c
+++ b/arch/ia64/kernel/salinfo.c
@@ -268,7 +268,7 @@ salinfo_event_open(struct inode *inode, struct file *file)
 }
 
 static ssize_t
-salinfo_event_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+salinfo_event_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	struct proc_dir_entry *entry = PDE(inode);
@@ -417,11 +417,16 @@ retry:
 
 	if (!data->saved_num)
 		call_on_cpu(cpu, salinfo_log_read_cpu, data);
-	data->state = data->log_size ? STATE_LOG_RECORD : STATE_NO_DATA;
+	if (!data->log_size) {
+	        data->state = STATE_NO_DATA;
+	        clear_bit(cpu, &data->cpu_event);
+	} else {
+	        data->state = STATE_LOG_RECORD;
+	}
 }
 
 static ssize_t
-salinfo_log_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+salinfo_log_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	struct proc_dir_entry *entry = PDE(inode);
@@ -478,7 +483,7 @@ salinfo_log_clear(struct salinfo_data *data, int cpu)
 }
 
 static ssize_t
-salinfo_log_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+salinfo_log_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	struct proc_dir_entry *entry = PDE(inode);
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 8aff39de1..da88d284e 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -680,7 +680,7 @@ cpu_init (void)
 			break;
 	}
 
-	if (ia64_pal_rse_info(&num_phys_stacked, 0) != 0) {
+	if (ia64_pal_rse_info(&num_phys_stacked, NULL) != 0) {
 		printk(KERN_WARNING "cpu_init: PAL RSE info failed; assuming 96 physical "
 		       "stacked regs\n");
 		num_phys_stacked = 96;
diff --git a/arch/ia64/kernel/sigframe.h b/arch/ia64/kernel/sigframe.h
index 55e527527..37b986cb8 100644
--- a/arch/ia64/kernel/sigframe.h
+++ b/arch/ia64/kernel/sigframe.h
@@ -17,7 +17,7 @@ struct sigframe {
 	 * End of architected state.
 	 */
 
-	void *handler;			/* pointer to the plabel of the signal handler */
+	void __user *handler;		/* pointer to the plabel of the signal handler */
 	struct siginfo info;
 	struct sigcontext sc;
 };
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
index 5a609295a..135cb55b1 100644
--- a/arch/ia64/kernel/signal.c
+++ b/arch/ia64/kernel/signal.c
@@ -1,7 +1,7 @@
 /*
  * Architecture-specific signal handling support.
  *
- * Copyright (C) 1999-2003 Hewlett-Packard Co
+ * Copyright (C) 1999-2004 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  *
  * Derived from i386 and Alpha versions.
@@ -43,7 +43,7 @@
 #endif
 
 long
-ia64_rt_sigsuspend (sigset_t *uset, size_t sigsetsize, struct sigscratch *scr)
+ia64_rt_sigsuspend (sigset_t __user *uset, size_t sigsetsize, struct sigscratch *scr)
 {
 	sigset_t oldset, set;
 
@@ -84,7 +84,7 @@ ia64_rt_sigsuspend (sigset_t *uset, size_t sigsetsize, struct sigscratch *scr)
 }
 
 asmlinkage long
-sys_sigaltstack (const stack_t *uss, stack_t *uoss, long arg2, long arg3, long arg4,
+sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2, long arg3, long arg4,
 		 long arg5, long arg6, long arg7, long stack)
 {
 	struct pt_regs *pt = (struct pt_regs *) &stack;
@@ -93,7 +93,7 @@ sys_sigaltstack (const stack_t *uss, stack_t *uoss, long arg2, long arg3, long a
 }
 
 static long
-restore_sigcontext (struct sigcontext *sc, struct sigscratch *scr)
+restore_sigcontext (struct sigcontext __user *sc, struct sigscratch *scr)
 {
 	unsigned long ip, flags, nat, um, cfm;
 	long err;
@@ -155,7 +155,7 @@ restore_sigcontext (struct sigcontext *sc, struct sigscratch *scr)
 }
 
 int
-copy_siginfo_to_user (siginfo_t *to, siginfo_t *from)
+copy_siginfo_to_user (siginfo_t __user *to, siginfo_t *from)
 {
 	if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t)))
 		return -EFAULT;
@@ -211,12 +211,12 @@ long
 ia64_rt_sigreturn (struct sigscratch *scr)
 {
 	extern char ia64_strace_leave_kernel, ia64_leave_kernel;
-	struct sigcontext *sc;
+	struct sigcontext __user *sc;
 	struct siginfo si;
 	sigset_t set;
 	long retval;
 
-	sc = &((struct sigframe *) (scr->pt.r12 + 16))->sc;
+	sc = &((struct sigframe __user *) (scr->pt.r12 + 16))->sc;
 
 	/*
 	 * When we return to the previously executing context, r8 and r10 have already
@@ -260,7 +260,7 @@ ia64_rt_sigreturn (struct sigscratch *scr)
 	 * It is more difficult to avoid calling this function than to
 	 * call it and ignore errors.
 	 */
-	do_sigaltstack(&sc->sc_stack, 0, scr->pt.r12);
+	do_sigaltstack(&sc->sc_stack, NULL, scr->pt.r12);
 	return retval;
 
   give_sigsegv:
@@ -281,7 +281,7 @@ ia64_rt_sigreturn (struct sigscratch *scr)
  * trampoline starts.  Everything else is done at the user-level.
  */
 static long
-setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct sigscratch *scr)
+setup_sigcontext (struct sigcontext __user *sc, sigset_t *mask, struct sigscratch *scr)
 {
 	unsigned long flags = 0, ifs, cfm, nat;
 	long err;
@@ -335,7 +335,7 @@ setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct sigscratch *scr)
 		err |= __put_user(scr->pt.ar_ccv, &sc->sc_ar_ccv);		/* ar.ccv */
 		err |= __put_user(scr->pt.b7, &sc->sc_br[7]);			/* b7 */
 		err |= __put_user(scr->pt.r14, &sc->sc_gr[14]);			/* r14 */
-		err |= __copy_to_user(&scr->pt.ar_csd, &sc->sc_ar25, 2*8); /* ar.csd & ar.ssd */
+		err |= __copy_to_user(&sc->sc_ar25, &scr->pt.ar_csd, 2*8); /* ar.csd & ar.ssd */
 		err |= __copy_to_user(&sc->sc_gr[2], &scr->pt.r2, 2*8);		/* r2-r3 */
 		err |= __copy_to_user(&sc->sc_gr[16], &scr->pt.r16, 16*8);	/* r16-r31 */
 	}
@@ -351,21 +351,50 @@ rbs_on_sig_stack (unsigned long bsp)
 	return (bsp - current->sas_ss_sp < current->sas_ss_size);
 }
 
+static long
+force_sigsegv_info (int sig, void __user *addr)
+{
+	unsigned long flags;
+	struct siginfo si;
+
+	if (sig == SIGSEGV) {
+		/*
+		 * Acquiring siglock around the sa_handler-update is almost
+		 * certainly overkill, but this isn't a
+		 * performance-critical path and I'd rather play it safe
+		 * here than having to debug a nasty race if and when
+		 * something changes in kernel/signal.c that would make it
+		 * no longer safe to modify sa_handler without holding the
+		 * lock.
+		 */
+		spin_lock_irqsave(&current->sighand->siglock, flags);
+		current->sighand->action[sig - 1].sa.sa_handler = SIG_DFL;
+		spin_unlock_irqrestore(&current->sighand->siglock, flags);
+	}
+	si.si_signo = SIGSEGV;
+	si.si_errno = 0;
+	si.si_code = SI_KERNEL;
+	si.si_pid = current->pid;
+	si.si_uid = current->uid;
+	si.si_addr = addr;
+	force_sig_info(SIGSEGV, &si, current);
+	return 0;
+}
+
 static long
 setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
 	     struct sigscratch *scr)
 {
 	extern char __kernel_sigtramp[];
 	unsigned long tramp_addr, new_rbs = 0;
-	struct sigframe *frame;
-	struct siginfo si;
+	struct sigframe __user *frame;
 	long err;
 
-	frame = (void *) scr->pt.r12;
+	frame = (void __user *) scr->pt.r12;
 	tramp_addr = (unsigned long) __kernel_sigtramp;
 	if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags((unsigned long) frame) == 0) {
-		frame = (void *) ((current->sas_ss_sp + current->sas_ss_size)
-				  & ~(STACK_ALIGN - 1));
+		frame = (void __user *) ((current->sas_ss_sp + current->sas_ss_size)
+					 & ~(STACK_ALIGN - 1));
 		/*
 		 * We need to check for the register stack being on the signal stack
 		 * separately, because it's switched separately (memory stack is switched
@@ -374,10 +403,10 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
 		if (!rbs_on_sig_stack(scr->pt.ar_bspstore))
 			new_rbs = (current->sas_ss_sp + sizeof(long) - 1) & ~(sizeof(long) - 1);
 	}
-	frame = (void *) frame - ((sizeof(*frame) + STACK_ALIGN - 1) & ~(STACK_ALIGN - 1));
+	frame = (void __user *) frame - ((sizeof(*frame) + STACK_ALIGN - 1) & ~(STACK_ALIGN - 1));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
+		return force_sigsegv_info(sig, frame);
 
 	err  = __put_user(sig, &frame->arg0);
 	err |= __put_user(&frame->info, &frame->arg1);
@@ -393,8 +422,8 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
 	err |= __put_user(sas_ss_flags(scr->pt.r12), &frame->sc.sc_stack.ss_flags);
 	err |= setup_sigcontext(&frame->sc, set, scr);
 
-	if (err)
-		goto give_sigsegv;
+	if (unlikely(err))
+		return force_sigsegv_info(sig, frame);
 
 	scr->pt.r12 = (unsigned long) frame - 16;	/* new stack pointer */
 	scr->pt.ar_fpsr = FPSR_DEFAULT;			/* reset fpsr for signal handler */
@@ -422,18 +451,6 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
 	       current->comm, current->pid, sig, scr->pt.r12, frame->sc.sc_ip, frame->handler);
 #endif
 	return 1;
-
-  give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	si.si_signo = SIGSEGV;
-	si.si_errno = 0;
-	si.si_code = SI_KERNEL;
-	si.si_pid = current->pid;
-	si.si_uid = current->uid;
-	si.si_addr = frame;
-	force_sig_info(SIGSEGV, &si, current);
-	return 0;
 }
 
 static long
@@ -449,9 +466,6 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse
 		if (!setup_frame(sig, ka, info, oldset, scr))
 			return 0;
 
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
-
 	if (!(ka->sa.sa_flags & SA_NODEFER)) {
 		spin_lock_irq(&current->sighand->siglock);
 		{
@@ -471,7 +485,7 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse
 long
 ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
 {
-	struct k_sigaction *ka;
+	struct k_sigaction ka;
 	siginfo_t info;
 	long restart = in_syscall;
 	long errno = scr->pt.r8;
@@ -493,7 +507,7 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
 	 * need to push through a forced SIGSEGV.
 	 */
 	while (1) {
-		int signr = get_signal_to_deliver(&info, &scr->pt, NULL);
+		int signr = get_signal_to_deliver(&info, &ka, &scr->pt, NULL);
 
 		/*
 		 * get_signal_to_deliver() may have run a debugger (via notify_parent())
@@ -520,8 +534,6 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
 		if (signr <= 0)
 			break;
 
-		ka = &current->sighand->action[signr - 1];
-
 		if (unlikely(restart)) {
 			switch (errno) {
 			      case ERESTART_RESTARTBLOCK:
@@ -531,7 +543,7 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
 				break;
 
 			      case ERESTARTSYS:
-				if ((ka->sa.sa_flags & SA_RESTART) == 0) {
+				if ((ka.sa.sa_flags & SA_RESTART) == 0) {
 					scr->pt.r8 = ERR_CODE(EINTR);
 					/* note: scr->pt.r10 is already -1 */
 					break;
@@ -550,7 +562,7 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
 		 * Whee!  Actually deliver the signal.  If the delivery failed, we need to
 		 * continue to iterate in this loop so we can deliver the SIGSEGV...
 		 */
-		if (handle_signal(signr, ka, &info, oldset, scr))
+		if (handle_signal(signr, &ka, &info, oldset, scr))
 			return 1;
 	}
 
diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
index 99f008853..14134f2e3 100644
--- a/arch/ia64/kernel/smp.c
+++ b/arch/ia64/kernel/smp.c
@@ -225,7 +225,7 @@ smp_send_reschedule (int cpu)
 void
 smp_flush_tlb_all (void)
 {
-	on_each_cpu((void (*)(void *))local_flush_tlb_all, 0, 1, 1);
+	on_each_cpu((void (*)(void *))local_flush_tlb_all, NULL, 1, 1);
 }
 EXPORT_SYMBOL(smp_flush_tlb_all);
 
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 9a0f79233..f0dd8c3dc 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -356,19 +356,15 @@ start_secondary (void *unused)
 	return cpu_idle();
 }
 
-static struct task_struct * __devinit
-fork_by_hand (void)
+struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
 {
-	/*
-	 * Don't care about the IP and regs settings since we'll never reschedule the
-	 * forked task.
-	 */
-	return copy_process(CLONE_VM|CLONE_IDLETASK, 0, 0, 0, NULL, NULL);
+	return NULL;
 }
 
 struct create_idle {
 	struct task_struct *idle;
 	struct completion done;
+	int cpu;
 };
 
 void
@@ -376,7 +372,7 @@ do_fork_idle(void *_c_idle)
 {
 	struct create_idle *c_idle = _c_idle;
 
-	c_idle->idle = fork_by_hand();
+	c_idle->idle = fork_idle(c_idle->cpu);
 	complete(&c_idle->done);
 }
 
@@ -384,10 +380,11 @@ static int __devinit
 do_boot_cpu (int sapicid, int cpu)
 {
 	int timeout;
-	struct create_idle c_idle;
+	struct create_idle c_idle = {
+		.cpu	= cpu,
+		.done	= COMPLETION_INITIALIZER(c_idle.done),
+	};
 	DECLARE_WORK(work, do_fork_idle, &c_idle);
-
-	init_completion(&c_idle.done);
 	/*
 	 * We can't use kernel_thread since we must avoid to reschedule the child.
 	 */
@@ -400,16 +397,6 @@ do_boot_cpu (int sapicid, int cpu)
 
 	if (IS_ERR(c_idle.idle))
 		panic("failed fork for CPU %d", cpu);
-	wake_up_forked_process(c_idle.idle);
-
-	/*
-	 * We remove it from the pidhash and the runqueue
-	 * once we got the process:
-	 */
-	init_idle(c_idle.idle, cpu);
-
-	unhash_process(c_idle.idle);
-
 	task_for_booting_cpu = c_idle.idle;
 
 	Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid);
@@ -719,3 +706,4 @@ init_smp_config(void)
 		printk(KERN_ERR "SMP: Can't set SAL AP Boot Rendezvous: %s\n",
 		       ia64_sal_strerror(sal_ret));
 }
+
diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
index eddde6018..88d8b217f 100644
--- a/arch/ia64/kernel/sys_ia64.c
+++ b/arch/ia64/kernel/sys_ia64.c
@@ -93,7 +93,7 @@ sys_getpagesize (void)
 }
 
 asmlinkage unsigned long
-ia64_shmat (int shmid, void *shmaddr, int shmflg)
+ia64_shmat (int shmid, void __user *shmaddr, int shmflg)
 {
 	unsigned long raddr;
 	int retval;
@@ -183,7 +183,7 @@ static inline unsigned long
 do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, unsigned long pgoff)
 {
 	unsigned long roff;
-	struct file *file = 0;
+	struct file *file = NULL;
 
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 	if (!(flags & MAP_ANONYMOUS)) {
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index e33bcb661..853d8dae7 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -45,192 +45,7 @@ EXPORT_SYMBOL(last_cli_ip);
 
 #endif
 
-static void
-itc_reset (void)
-{
-}
-
-/*
- * Adjust for the fact that xtime has been advanced by delta_nsec (may be negative and/or
- * larger than NSEC_PER_SEC.
- */
-static void
-itc_update (long delta_nsec)
-{
-}
-
-/*
- * Return the number of nano-seconds that elapsed since the last
- * update to jiffy.  It is quite possible that the timer interrupt
- * will interrupt this and result in a race for any of jiffies,
- * wall_jiffies or itm_next.  Thus, the xtime_lock must be at least
- * read synchronised when calling this routine (see do_gettimeofday()
- * below for an example).
- */
-unsigned long
-itc_get_offset (void)
-{
-	unsigned long elapsed_cycles, lost = jiffies - wall_jiffies;
-	unsigned long now = ia64_get_itc(), last_tick;
-
-	last_tick = (cpu_data(TIME_KEEPER_ID)->itm_next
-		     - (lost + 1)*cpu_data(TIME_KEEPER_ID)->itm_delta);
-
-	elapsed_cycles = now - last_tick;
-	return (elapsed_cycles*local_cpu_data->nsec_per_cyc) >> IA64_NSEC_PER_CYC_SHIFT;
-}
-
-static struct time_interpolator itc_interpolator = {
-	.get_offset =	itc_get_offset,
-	.update =	itc_update,
-	.reset =	itc_reset
-};
-
-int
-do_settimeofday (struct timespec *tv)
-{
-	time_t wtm_sec, sec = tv->tv_sec;
-	long wtm_nsec, nsec = tv->tv_nsec;
-
-	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-		return -EINVAL;
-
-	write_seqlock_irq(&xtime_lock);
-	{
-		/*
-		 * This is revolting. We need to set "xtime" correctly. However, the value
-		 * in this location is the value at the most recent update of wall time.
-		 * Discover what correction gettimeofday would have done, and then undo
-		 * it!
-		 */
-		nsec -= time_interpolator_get_offset();
-
-		wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
-		wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
-
-		set_normalized_timespec(&xtime, sec, nsec);
-		set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
-		time_adjust = 0;		/* stop active adjtime() */
-		time_status |= STA_UNSYNC;
-		time_maxerror = NTP_PHASE_LIMIT;
-		time_esterror = NTP_PHASE_LIMIT;
-		time_interpolator_reset();
-	}
-	write_sequnlock_irq(&xtime_lock);
-	clock_was_set();
-	return 0;
-}
-
-EXPORT_SYMBOL(do_settimeofday);
-
-void
-do_gettimeofday (struct timeval *tv)
-{
-	unsigned long seq, nsec, usec, sec, old, offset;
-
-	while (1) {
-		seq = read_seqbegin(&xtime_lock);
-		{
-			old = last_nsec_offset;
-			offset = time_interpolator_get_offset();
-			sec = xtime.tv_sec;
-			nsec = xtime.tv_nsec;
-		}
-		if (unlikely(read_seqretry(&xtime_lock, seq)))
-			continue;
-		/*
-		 * Ensure that for any pair of causally ordered gettimeofday() calls, time
-		 * never goes backwards (even when ITC on different CPUs are not perfectly
-		 * synchronized).  (A pair of concurrent calls to gettimeofday() is by
-		 * definition non-causal and hence it makes no sense to talk about
-		 * time-continuity for such calls.)
-		 *
-		 * Doing this in a lock-free and race-free manner is tricky.  Here is why
-		 * it works (most of the time): read_seqretry() just succeeded, which
-		 * implies we calculated a consistent (valid) value for "offset".  If the
-		 * cmpxchg() below succeeds, we further know that last_nsec_offset still
-		 * has the same value as at the beginning of the loop, so there was
-		 * presumably no timer-tick or other updates to last_nsec_offset in the
-		 * meantime.  This isn't 100% true though: there _is_ a possibility of a
-		 * timer-tick occurring right right after read_seqretry() and then getting
-		 * zero or more other readers which will set last_nsec_offset to the same
-		 * value as the one we read at the beginning of the loop.  If this
-		 * happens, we'll end up returning a slightly newer time than we ought to
-		 * (the jump forward is at most "offset" nano-seconds).  There is no
-		 * danger of causing time to go backwards, though, so we are safe in that
-		 * sense.  We could make the probability of this unlucky case occurring
-		 * arbitrarily small by encoding a version number in last_nsec_offset, but
-		 * even without versioning, the probability of this unlucky case should be
-		 * so small that we won't worry about it.
-		 */
-		if (offset <= old) {
-			offset = old;
-			break;
-		} else if (likely(cmpxchg(&last_nsec_offset, old, offset) == old))
-			break;
-
-		/* someone else beat us to updating last_nsec_offset; try again */
-	}
-
-	usec = (nsec + offset) / 1000;
-
-	while (unlikely(usec >= USEC_PER_SEC)) {
-		usec -= USEC_PER_SEC;
-		++sec;
-	}
-
-	tv->tv_sec = sec;
-	tv->tv_usec = usec;
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
-
-/*
- * The profiling function is SMP safe. (nothing can mess
- * around with "current", and the profiling counters are
- * updated with atomic operations). This is especially
- * useful with a profiling multiplier != 1
- */
-static inline void
-ia64_do_profile (struct pt_regs * regs)
-{
-	unsigned long ip, slot;
-	extern cpumask_t prof_cpu_mask;
-
-	profile_hook(regs);
-
-	if (user_mode(regs))
-		return;
-
-	if (!prof_buffer)
-		return;
-
-	ip = instruction_pointer(regs);
-	/* Conserve space in histogram by encoding slot bits in address
-	 * bits 2 and 3 rather than bits 0 and 1.
-	 */
-	slot = ip & 3;
-	ip = (ip & ~3UL) + 4*slot;
-
-	/*
-	 * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
-	 * (default is all CPUs.)
-	 */
-	if (!cpu_isset(smp_processor_id(), prof_cpu_mask))
-		return;
-
-	ip -= (unsigned long) &_stext;
-	ip >>= prof_shift;
-	/*
-	 * Don't ignore out-of-bounds IP values silently,
-	 * put them into the last histogram slot, so if
-	 * present, they will show up as a sharp peak.
-	 */
-	if (ip > prof_len-1)
-		ip = prof_len-1;
-	atomic_inc((atomic_t *)&prof_buffer[ip]);
-}
+static struct time_interpolator itc_interpolator;
 
 static irqreturn_t
 timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
@@ -249,7 +64,7 @@ timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
 		printk(KERN_ERR "Oops: timer tick before it's due (itc=%lx,itm=%lx)\n",
 		       ia64_get_itc(), new_itm);
 
-	ia64_do_profile(regs);
+	profile_tick(CPU_PROFILING, regs);
 
 	while (1) {
 #ifdef CONFIG_SMP
@@ -323,6 +138,18 @@ ia64_cpu_local_tick (void)
 	ia64_set_itm(local_cpu_data->itm_next);
 }
 
+static int nojitter;
+
+static int __init nojitter_setup(char *str)
+{
+	nojitter = 1;
+	printk("Jitter checking for ITC timers disabled\n");
+	return 1;
+}
+
+__setup("nojitter", nojitter_setup);
+
+
 void __devinit
 ia64_init_itm (void)
 {
@@ -340,7 +167,7 @@ ia64_init_itm (void)
 	if (status != 0) {
 		printk(KERN_ERR "SAL_FREQ_BASE_PLATFORM failed: %s\n", ia64_sal_strerror(status));
 	} else {
-		status = ia64_pal_freq_ratios(&proc_ratio, 0, &itc_ratio);
+		status = ia64_pal_freq_ratios(&proc_ratio, NULL, &itc_ratio);
 		if (status != 0)
 			printk(KERN_ERR "PAL_FREQ_RATIOS failed with status=%ld\n", status);
 	}
@@ -371,7 +198,7 @@ ia64_init_itm (void)
 		itc_drift = -1;
 
 	local_cpu_data->itm_delta = (itc_freq + HZ/2) / HZ;
-	printk(KERN_INFO "CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, "
+	printk(KERN_DEBUG "CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, "
 	       "ITC freq=%lu.%03luMHz+/-%ldppm\n", smp_processor_id(),
 	       platform_base_freq / 1000000, (platform_base_freq / 1000) % 1000,
 	       itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000,
@@ -385,7 +212,23 @@ ia64_init_itm (void)
 
 	if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) {
 		itc_interpolator.frequency = local_cpu_data->itc_freq;
+		itc_interpolator.shift = 16;
 		itc_interpolator.drift = itc_drift;
+		itc_interpolator.source = TIME_SOURCE_CPU;
+#ifdef CONFIG_SMP
+		/* On IA64 in an SMP configuration ITCs are never accurately synchronized.
+		 * Jitter compensation requires a cmpxchg which may limit
+		 * the scalability of the syscalls for retrieving time.
+		 * The ITC synchronization is usually successful to within a few
+		 * ITC ticks but this is not a sure thing. If you need to improve
+		 * timer performance in SMP situations then boot the kernel with the
+		 * "nojitter" option. However, doing so may result in time fluctuating (maybe
+		 * even going backward) if the ITC offsets between the individual CPUs
+		 * are too large.
+		 */
+		if (!nojitter) itc_interpolator.jitter = 1;
+#endif
+		itc_interpolator.addr = NULL;
 		register_time_interpolator(&itc_interpolator);
 	}
 
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
index f89913135..3dd9b1dc7 100644
--- a/arch/ia64/kernel/traps.c
+++ b/arch/ia64/kernel/traps.c
@@ -14,9 +14,9 @@
 #include <linux/tty.h>
 #include <linux/vt_kern.h>		/* For unblank_screen() */
 #include <linux/module.h>       /* for EXPORT_SYMBOL */
+#include <linux/hardirq.h>
 
 #include <asm/fpswa.h>
-#include <asm/hardirq.h>
 #include <asm/ia32.h>
 #include <asm/intrinsics.h>
 #include <asm/processor.h>
@@ -112,7 +112,7 @@ ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
 	int sig, code;
 
 	/* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */
-	siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
+	siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
 	siginfo.si_imm = break_num;
 	siginfo.si_flags = 0;		/* clear __ISR_VALID */
 	siginfo.si_isr = 0;
@@ -282,7 +282,7 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)
 	fault_ip = regs->cr_iip;
 	if (!fp_fault && (ia64_psr(regs)->ri == 0))
 		fault_ip -= 16;
-	if (copy_from_user(bundle, (void *) fault_ip, sizeof(bundle)))
+	if (copy_from_user(bundle, (void __user *) fault_ip, sizeof(bundle)))
 		return -1;
 
 	if (jiffies - last_time > 5*HZ)
@@ -312,7 +312,7 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)
 			siginfo.si_signo = SIGFPE;
 			siginfo.si_errno = 0;
 			siginfo.si_code = __SI_FAULT;	/* default code */
-			siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
+			siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
 			if (isr & 0x11) {
 				siginfo.si_code = FPE_FLTINV;
 			} else if (isr & 0x22) {
@@ -336,7 +336,7 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)
 			siginfo.si_signo = SIGFPE;
 			siginfo.si_errno = 0;
 			siginfo.si_code = __SI_FAULT;	/* default code */
-			siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
+			siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
 			if (isr & 0x880) {
 				siginfo.si_code = FPE_FLTOVF;
 			} else if (isr & 0x1100) {
@@ -383,7 +383,7 @@ ia64_illegal_op_fault (unsigned long ec, unsigned long arg1, unsigned long arg2,
 	memset(&si, 0, sizeof(si));
 	si.si_signo = SIGILL;
 	si.si_code = ILL_ILLOPC;
-	si.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
+	si.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
 	force_sig_info(SIGILL, &si, current);
 	rv.fkt = 0;
 	return rv;
@@ -445,18 +445,18 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
 
 	      case 26: /* NaT Consumption */
 		if (user_mode(regs)) {
-			void *addr;
+			void __user *addr;
 
 			if (((isr >> 4) & 0xf) == 2) {
 				/* NaT page consumption */
 				sig = SIGSEGV;
 				code = SEGV_ACCERR;
-				addr = (void *) ifa;
+				addr = (void __user *) ifa;
 			} else {
 				/* register NaT consumption */
 				sig = SIGILL;
 				code = ILL_ILLOPN;
-				addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
+				addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
 			}
 			siginfo.si_signo = sig;
 			siginfo.si_code = code;
@@ -477,7 +477,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
 			siginfo.si_signo = SIGILL;
 			siginfo.si_code = ILL_ILLOPN;
 			siginfo.si_errno = 0;
-			siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
+			siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
 			siginfo.si_imm = vector;
 			siginfo.si_flags = __ISR_VALID;
 			siginfo.si_isr = isr;
@@ -524,7 +524,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
 		}
 		siginfo.si_signo = SIGTRAP;
 		siginfo.si_errno = 0;
-		siginfo.si_addr  = (void *) ifa;
+		siginfo.si_addr  = (void __user *) ifa;
 		siginfo.si_imm   = 0;
 		siginfo.si_flags = __ISR_VALID;
 		siginfo.si_isr   = isr;
@@ -538,7 +538,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
 			siginfo.si_signo = SIGFPE;
 			siginfo.si_errno = 0;
 			siginfo.si_code = FPE_FLTINV;
-			siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
+			siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
 			siginfo.si_flags = __ISR_VALID;
 			siginfo.si_isr = isr;
 			siginfo.si_imm = 0;
@@ -565,7 +565,8 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
 				siginfo.si_flags = 0;
 				siginfo.si_isr = 0;
 				siginfo.si_imm = 0;
-				siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
+				siginfo.si_addr = (void __user *)
+					(regs->cr_iip + ia64_psr(regs)->ri);
 				force_sig_info(SIGILL, &siginfo, current);
 				return;
 			}
diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c
index b1a68e436..46dad0d21 100644
--- a/arch/ia64/kernel/unaligned.c
+++ b/arch/ia64/kernel/unaligned.c
@@ -760,7 +760,7 @@ emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
 		return -1;
 	}
 	/* this assumes little-endian byte-order: */
-	if (copy_from_user(&val, (void *) ifa, len))
+	if (copy_from_user(&val, (void __user *) ifa, len))
 		return -1;
 	setreg(ld.r1, val, 0, regs);
 
@@ -869,7 +869,7 @@ emulate_store_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
 	 *
 	 * extract the value to be stored
 	 */
-	getreg(ld.imm, &r2, 0, regs);
+	getreg(ld.imm, &r2, NULL, regs);
 
 	/*
 	 * we rely on the macros in unaligned.h for now i.e.,
@@ -887,7 +887,7 @@ emulate_store_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
 	}
 
 	/* this assumes little-endian byte-order: */
-	if (copy_to_user((void *) ifa, &r2, len))
+	if (copy_to_user((void __user *) ifa, &r2, len))
 		return -1;
 
 	/*
@@ -1036,8 +1036,8 @@ emulate_load_floatpair (unsigned long ifa, load_store_t ld, struct pt_regs *regs
 		 * This assumes little-endian byte-order.  Note that there is no "ldfpe"
 		 * instruction:
 		 */
-		if (copy_from_user(&fpr_init[0], (void *) ifa, len)
-		    || copy_from_user(&fpr_init[1], (void *) (ifa + len), len))
+		if (copy_from_user(&fpr_init[0], (void __user *) ifa, len)
+		    || copy_from_user(&fpr_init[1], (void __user *) (ifa + len), len))
 			return -1;
 
 		DPRINT("ld.r1=%d ld.imm=%d x6_sz=%d\n", ld.r1, ld.imm, ld.x6_sz);
@@ -1138,7 +1138,7 @@ emulate_load_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
 	 * See comments in ldX for descriptions on how the various loads are handled.
 	 */
 	if (ld.x6_op != 0x2) {
-		if (copy_from_user(&fpr_init, (void *) ifa, len))
+		if (copy_from_user(&fpr_init, (void __user *) ifa, len))
 			return -1;
 
 		DPRINT("ld.r1=%d x6_sz=%d\n", ld.r1, ld.x6_sz);
@@ -1230,7 +1230,7 @@ emulate_store_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
 	DDUMP("fpr_init =", &fpr_init, len);
 	DDUMP("fpr_final =", &fpr_final, len);
 
-	if (copy_to_user((void *) ifa, &fpr_final, len))
+	if (copy_to_user((void __user *) ifa, &fpr_final, len))
 		return -1;
 
 	/*
@@ -1351,7 +1351,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
 	DPRINT("iip=%lx ifa=%lx isr=%lx (ei=%d, sp=%d)\n",
 	       regs->cr_iip, ifa, regs->cr_ipsr, ipsr->ri, ipsr->it);
 
-	if (__copy_from_user(bundle, (void *) regs->cr_iip, 16))
+	if (__copy_from_user(bundle, (void __user *) regs->cr_iip, 16))
 		goto failure;
 
 	/*
@@ -1496,7 +1496,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
 	si.si_signo = SIGBUS;
 	si.si_errno = 0;
 	si.si_code = BUS_ADRALN;
-	si.si_addr = (void *) ifa;
+	si.si_addr = (void __user *) ifa;
 	si.si_flags = 0;
 	si.si_isr = 0;
 	si.si_imm = 0;
diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c
index 769d880df..69e095abe 100644
--- a/arch/ia64/kernel/unwind.c
+++ b/arch/ia64/kernel/unwind.c
@@ -47,7 +47,6 @@
 #include "entry.h"
 #include "unwind_i.h"
 
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
 #define p5		5
 
 #define UNW_LOG_CACHE_SIZE	7	/* each unw_script is ~256 bytes in size */
@@ -447,7 +446,7 @@ EXPORT_SYMBOL(unw_access_br);
 int
 unw_access_fr (struct unw_frame_info *info, int regnum, struct ia64_fpreg *val, int write)
 {
-	struct ia64_fpreg *addr = 0;
+	struct ia64_fpreg *addr = NULL;
 	struct pt_regs *pt;
 
 	if ((unsigned) (regnum - 2) >= 126) {
@@ -843,7 +842,7 @@ desc_prologue (int body, unw_word rlen, unsigned char mask, unsigned char grsave
 		}
 		sr->gr_save_loc = grsave;
 		sr->any_spills = 0;
-		sr->imask = 0;
+		sr->imask = NULL;
 		sr->spill_offset = 0x10;	/* default to psp+16 */
 	}
 }
@@ -963,13 +962,13 @@ static inline void
 desc_mem_stack_f (unw_word t, unw_word size, struct unw_state_record *sr)
 {
 	set_reg(sr->curr.reg + UNW_REG_PSP, UNW_WHERE_NONE,
-		sr->region_start + MIN((int)t, sr->region_len - 1), 16*size);
+		sr->region_start + min_t(int, t, sr->region_len - 1), 16*size);
 }
 
 static inline void
 desc_mem_stack_v (unw_word t, struct unw_state_record *sr)
 {
-	sr->curr.reg[UNW_REG_PSP].when = sr->region_start + MIN((int)t, sr->region_len - 1);
+	sr->curr.reg[UNW_REG_PSP].when = sr->region_start + min_t(int, t, sr->region_len - 1);
 }
 
 static inline void
@@ -1005,7 +1004,7 @@ desc_reg_when (unsigned char regnum, unw_word t, struct unw_state_record *sr)
 
 	if (reg->where == UNW_WHERE_NONE)
 		reg->where = UNW_WHERE_GR_SAVE;
-	reg->when = sr->region_start + MIN((int)t, sr->region_len - 1);
+	reg->when = sr->region_start + min_t(int, t, sr->region_len - 1);
 }
 
 static inline void
@@ -1073,7 +1072,7 @@ desc_label_state (unw_word label, struct unw_state_record *sr)
 static inline int
 desc_is_active (unsigned char qp, unw_word t, struct unw_state_record *sr)
 {
-	if (sr->when_target <= sr->region_start + MIN((int)t, sr->region_len - 1))
+	if (sr->when_target <= sr->region_start + min_t(int, t, sr->region_len - 1))
 		return 0;
 	if (qp > 0) {
 		if ((sr->pr_val & (1UL << qp)) == 0)
@@ -1114,7 +1113,7 @@ desc_spill_reg_p (unsigned char qp, unw_word t, unsigned char abreg, unsigned ch
 
 	r = sr->curr.reg + decode_abreg(abreg, 0);
 	r->where = where;
-	r->when = sr->region_start + MIN((int)t, sr->region_len - 1);
+	r->when = sr->region_start + min_t(int, t, sr->region_len - 1);
 	r->val = (ytreg & 0x7f);
 }
 
@@ -1129,7 +1128,7 @@ desc_spill_psprel_p (unsigned char qp, unw_word t, unsigned char abreg, unw_word
 
 	r = sr->curr.reg + decode_abreg(abreg, 1);
 	r->where = UNW_WHERE_PSPREL;
-	r->when = sr->region_start + MIN((int)t, sr->region_len - 1);
+	r->when = sr->region_start + min_t(int, t, sr->region_len - 1);
 	r->val = 0x10 - 4*pspoff;
 }
 
@@ -1144,7 +1143,7 @@ desc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg, unw_word
 
 	r = sr->curr.reg + decode_abreg(abreg, 1);
 	r->where = UNW_WHERE_SPREL;
-	r->when = sr->region_start + MIN((int)t, sr->region_len - 1);
+	r->when = sr->region_start + min_t(int, t, sr->region_len - 1);
 	r->val = 4*spoff;
 }
 
@@ -1206,7 +1205,7 @@ desc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg, unw_word
 static inline unw_hash_index_t
 hash (unsigned long ip)
 {
-#	define hashmagic	0x9e3779b97f4a7c16	/* based on (sqrt(5)/2-1)*2^64 */
+#	define hashmagic	0x9e3779b97f4a7c16UL	/* based on (sqrt(5)/2-1)*2^64 */
 
 	return (ip >> 4)*hashmagic >> (64 - UNW_LOG_HASH_SIZE);
 #undef hashmagic
@@ -1231,7 +1230,7 @@ script_lookup (struct unw_frame_info *info)
 	unsigned long ip, pr;
 
 	if (UNW_DEBUG_ON(0))
-		return 0;	/* Always regenerate scripts in debug mode */
+		return NULL;	/* Always regenerate scripts in debug mode */
 
 	STAT(++unw.stat.cache.lookups);
 
@@ -1245,7 +1244,7 @@ script_lookup (struct unw_frame_info *info)
 
 	index = unw.hash[hash(ip)];
 	if (index >= UNW_CACHE_SIZE)
-		return 0;
+		return NULL;
 
 	script = unw.cache + index;
 	while (1) {
@@ -1256,7 +1255,7 @@ script_lookup (struct unw_frame_info *info)
 			return script;
 		}
 		if (script->coll_chain >= UNW_HASH_SIZE)
-			return 0;
+			return NULL;
 		script = unw.cache + script->coll_chain;
 		STAT(++unw.stat.cache.collision_chain_traversals);
 	}
@@ -1306,7 +1305,7 @@ script_new (unsigned long ip)
 		if (script->ip) {
 			index = hash(script->ip);
 			tmp = unw.cache + unw.hash[index];
-			prev = 0;
+			prev = NULL;
 			while (1) {
 				if (tmp == script) {
 					if (prev)
@@ -1511,7 +1510,7 @@ compile_reg (struct unw_state_record *sr, int i, struct unw_script *script)
 static inline const struct unw_table_entry *
 lookup (struct unw_table *table, unsigned long rel_ip)
 {
-	const struct unw_table_entry *e = 0;
+	const struct unw_table_entry *e = NULL;
 	unsigned long lo, hi, mid;
 
 	/* do a binary search for right entry: */
@@ -1537,8 +1536,8 @@ lookup (struct unw_table *table, unsigned long rel_ip)
 static inline struct unw_script *
 build_script (struct unw_frame_info *info)
 {
-	const struct unw_table_entry *e = 0;
-	struct unw_script *script = 0;
+	const struct unw_table_entry *e = NULL;
+	struct unw_script *script = NULL;
 	struct unw_labeled_state *ls, *next;
 	unsigned long ip = info->ip;
 	struct unw_state_record sr;
@@ -1563,7 +1562,7 @@ build_script (struct unw_frame_info *info)
 	if (!script) {
 		UNW_DPRINT(0, "unwind.%s: failed to create unwind script\n",  __FUNCTION__);
 		STAT(unw.stat.script.build_time += ia64_get_itc() - start);
-		return 0;
+		return NULL;
 	}
 	unw.cache[info->prev_script].hint = script - unw.cache;
 
@@ -1836,7 +1835,7 @@ find_save_locs (struct unw_frame_info *info)
 		/* don't let obviously bad addresses pollute the cache */
 		/* FIXME: should really be level 0 but it occurs too often. KAO */
 		UNW_DPRINT(1, "unwind.%s: rejecting bad ip=0x%lx\n", __FUNCTION__, info->ip);
-		info->rp_loc = 0;
+		info->rp_loc = NULL;
 		return -1;
 	}
 
@@ -2093,12 +2092,12 @@ unw_add_unwind_table (const char *name, unsigned long segment_base, unsigned lon
 	if (end - start <= 0) {
 		UNW_DPRINT(0, "unwind.%s: ignoring attempt to insert empty unwind table\n",
 			   __FUNCTION__);
-		return 0;
+		return NULL;
 	}
 
 	table = kmalloc(sizeof(*table), GFP_USER);
 	if (!table)
-		return 0;
+		return NULL;
 
 	init_unwind_table(table, name, segment_base, gp, table_start, table_end);
 
@@ -2300,7 +2299,7 @@ unw_init (void)
  *	EFAULT	BUF points outside your accessible address space.
  */
 asmlinkage long
-sys_getunwind (void *buf, size_t buf_size)
+sys_getunwind (void __user *buf, size_t buf_size)
 {
 	if (buf && buf_size >= unw.gate_table_size)
 		if (copy_to_user(buf, unw.gate_table, unw.gate_table_size) != 0)
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index 57912212b..b9f0db4c1 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -42,6 +42,7 @@ SECTIONS
 	*(.text.ivt)
 	*(.text)
 	SCHED_TEXT
+	LOCK_TEXT
 	*(.gnu.linkonce.t*)
     }
   .text2 : AT(ADDR(.text2) - LOAD_OFFSET)
@@ -135,12 +136,6 @@ SECTIONS
 	  *(.init.setup)
 	  __setup_end = .;
 	}
-  __param : AT(ADDR(__param) - LOAD_OFFSET)
-        {
-	  __start___param = .;
-	  *(__param)
-	  __stop___param = .;
-	}
   .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET)
 	{
 	  __initcall_start = .;
diff --git a/arch/ia64/lib/csum_partial_copy.c b/arch/ia64/lib/csum_partial_copy.c
index 269dcc2cb..ca7ba1e9c 100644
--- a/arch/ia64/lib/csum_partial_copy.c
+++ b/arch/ia64/lib/csum_partial_copy.c
@@ -1,7 +1,7 @@
 /*
  * Network Checksum & Copy routine
  *
- * Copyright (C) 1999, 2003 Hewlett-Packard Co
+ * Copyright (C) 1999, 2003-2004 Hewlett-Packard Co
  *	Stephane Eranian <eranian@hpl.hp.com>
  *
  * Most of the code has been imported from Linux/Alpha
@@ -105,7 +105,7 @@ out:
 extern unsigned long do_csum(const unsigned char *, long);
 
 static unsigned int
-do_csum_partial_copy_from_user (const char *src, char *dst, int len,
+do_csum_partial_copy_from_user (const char __user *src, char *dst, int len,
 				unsigned int psum, int *errp)
 {
 	unsigned long result;
@@ -129,10 +129,10 @@ do_csum_partial_copy_from_user (const char *src, char *dst, int len,
 }
 
 unsigned int
-csum_partial_copy_from_user(const char *src, char *dst, int len,
-			    unsigned int sum, int *errp)
+csum_partial_copy_from_user (const char __user *src, char *dst, int len,
+			     unsigned int sum, int *errp)
 {
-	if (!access_ok(src, len, VERIFY_READ)) {
+	if (!access_ok(VERIFY_READ, src, len)) {
 		*errp = -EFAULT;
 		memset(dst, 0, len);
 		return sum;
@@ -142,7 +142,7 @@ csum_partial_copy_from_user(const char *src, char *dst, int len,
 }
 
 unsigned int
-csum_partial_copy_nocheck(const char *src, char *dst, int len, unsigned int sum)
+csum_partial_copy_nocheck(const char __user *src, char *dst, int len, unsigned int sum)
 {
 	return do_csum_partial_copy_from_user(src, dst, len, sum, NULL);
 }
diff --git a/arch/ia64/lib/io.c b/arch/ia64/lib/io.c
index 90f0f3061..2bc5be82d 100644
--- a/arch/ia64/lib/io.c
+++ b/arch/ia64/lib/io.c
@@ -9,7 +9,7 @@
  * This needs to be optimized.
  */
 void
-__ia64_memcpy_fromio (void *to, unsigned long from, long count)
+__ia64_memcpy_fromio (void *to, volatile void __iomem *from, long count)
 {
 	char *dst = to;
 
@@ -25,7 +25,7 @@ EXPORT_SYMBOL(__ia64_memcpy_fromio);
  * This needs to be optimized.
  */
 void
-__ia64_memcpy_toio (unsigned long to, void *from, long count)
+__ia64_memcpy_toio (volatile void __iomem *to, void *from, long count)
 {
 	char *src = from;
 
@@ -41,7 +41,7 @@ EXPORT_SYMBOL(__ia64_memcpy_toio);
  * This needs to be optimized.
  */
 void
-__ia64_memset_c_io (unsigned long dst, unsigned long c, long count)
+__ia64_memset_c_io (volatile void __iomem *dst, unsigned long c, long count)
 {
 	unsigned char ch = (char)(c & 0xff);
 
@@ -111,49 +111,49 @@ __ia64_outl (unsigned int val, unsigned long port)
 }
 
 unsigned char
-__ia64_readb (void *addr)
+__ia64_readb (void __iomem *addr)
 {
 	return ___ia64_readb (addr);
 }
 
 unsigned short
-__ia64_readw (void *addr)
+__ia64_readw (void __iomem *addr)
 {
 	return ___ia64_readw (addr);
 }
 
 unsigned int
-__ia64_readl (void *addr)
+__ia64_readl (void __iomem *addr)
 {
 	return ___ia64_readl (addr);
 }
 
 unsigned long
-__ia64_readq (void *addr)
+__ia64_readq (void __iomem *addr)
 {
 	return ___ia64_readq (addr);
 }
 
 unsigned char
-__ia64_readb_relaxed (void *addr)
+__ia64_readb_relaxed (void __iomem *addr)
 {
 	return ___ia64_readb (addr);
 }
 
 unsigned short
-__ia64_readw_relaxed (void *addr)
+__ia64_readw_relaxed (void __iomem *addr)
 {
 	return ___ia64_readw (addr);
 }
 
 unsigned int
-__ia64_readl_relaxed (void *addr)
+__ia64_readl_relaxed (void __iomem *addr)
 {
 	return ___ia64_readl (addr);
 }
 
 unsigned long
-__ia64_readq_relaxed (void *addr)
+__ia64_readq_relaxed (void __iomem *addr)
 {
 	return ___ia64_readq (addr);
 }
diff --git a/arch/ia64/lib/swiotlb.c b/arch/ia64/lib/swiotlb.c
index 781e23e66..9d4486f87 100644
--- a/arch/ia64/lib/swiotlb.c
+++ b/arch/ia64/lib/swiotlb.c
@@ -11,6 +11,7 @@
  * 03/05/07 davidm	Switch from PCI-DMA to generic device DMA API.
  * 00/12/13 davidm	Rename to swiotlb.c and add mark_clean() to avoid
  *			unnecessary i-cache flushing.
+ * 04/07/.. ak          Better overflow handling. Assorted fixes.
  */
 
 #include <linux/cache.h>
@@ -20,6 +21,7 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/types.h>
+#include <linux/ctype.h>
 
 #include <asm/io.h>
 #include <asm/pci.h>
@@ -46,6 +48,8 @@
  */
 #define IO_TLB_SHIFT 11
 
+int swiotlb_force;
+
 /*
  * Used to do a quick range check in swiotlb_unmap_single and swiotlb_sync_single_*, to see
  * if the memory was in fact allocated by this API.
@@ -55,8 +59,16 @@ static char *io_tlb_start, *io_tlb_end;
 /*
  * The number of IO TLB blocks (in groups of 64) betweeen io_tlb_start and io_tlb_end.
  * This is command line adjustable via setup_io_tlb_npages.
+ * Default to 64MB.
+ */
+static unsigned long io_tlb_nslabs = 32768;
+
+/* 
+ * When the IOMMU overflows we return a fallback buffer. This sets the size.
  */
-static unsigned long io_tlb_nslabs = 1024;
+static unsigned long io_tlb_overflow = 32*1024;
+
+void *io_tlb_overflow_buffer; 
 
 /*
  * This is a free list describing the number of free entries available from each index
@@ -78,15 +90,19 @@ static spinlock_t io_tlb_lock = SPIN_LOCK_UNLOCKED;
 static int __init
 setup_io_tlb_npages (char *str)
 {
-	io_tlb_nslabs = simple_strtoul(str, NULL, 0) << (PAGE_SHIFT - IO_TLB_SHIFT);
-
-	/* avoid tail segment of size < IO_TLB_SEGSIZE */
-	io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
-
+	if (isdigit(*str)) { 
+		io_tlb_nslabs = simple_strtoul(str, &str, 0) << (PAGE_SHIFT - IO_TLB_SHIFT);
+		/* avoid tail segment of size < IO_TLB_SEGSIZE */
+		io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
+	}
+	if (*str == ',')
+		++str;
+	if (!strcmp(str, "force"))
+		swiotlb_force = 1;
 	return 1;
 }
 __setup("swiotlb=", setup_io_tlb_npages);
-
+/* make io_tlb_overflow tunable too? */
 
 /*
  * Statically reserve bounce buffer space and initialize bounce buffer data structures for
@@ -102,7 +118,7 @@ swiotlb_init (void)
 	 */
 	io_tlb_start = alloc_bootmem_low_pages(io_tlb_nslabs * (1 << IO_TLB_SHIFT));
 	if (!io_tlb_start)
-		BUG();
+		panic("Cannot allocate SWIOTLB buffer");
 	io_tlb_end = io_tlb_start + io_tlb_nslabs * (1 << IO_TLB_SHIFT);
 
 	/*
@@ -115,11 +131,23 @@ swiotlb_init (void)
  		io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
 	io_tlb_index = 0;
 	io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(char *));
-
-	printk(KERN_INFO "Placing software IO TLB between 0x%p - 0x%p\n",
-	       (void *) io_tlb_start, (void *) io_tlb_end);
+	
+	/* 
+	 * Get the overflow emergency buffer 
+	 */
+	io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow); 
+	printk(KERN_INFO "Placing software IO TLB between 0x%lx - 0x%lx\n",
+	       virt_to_phys(io_tlb_start), virt_to_phys(io_tlb_end));
 }
 
+static inline int address_needs_mapping(struct device *hwdev, dma_addr_t addr)
+{ 
+	dma_addr_t mask = 0xffffffff; 
+	if (hwdev && hwdev->dma_mask) 
+		mask = *hwdev->dma_mask; 
+	return (addr & ~mask) != 0; 		
+} 
+
 /*
  * Allocates bounce buffer and returns its kernel virtual address.
  */
@@ -184,11 +212,8 @@ map_single (struct device *hwdev, char *buffer, size_t size, int dir)
 				index = 0;
 		} while (index != wrap);
 
-		/*
-		 * XXX What is a suitable recovery mechanism here?  We cannot
-		 * sleep because we are called from with in interrupts!
-		 */
-		panic("map_single: could not allocate software IO TLB (%ld bytes)", size);
+		spin_unlock_irqrestore(&io_tlb_lock, flags);
+		return NULL;
 	}
   found:
 	spin_unlock_irqrestore(&io_tlb_lock, flags);
@@ -285,7 +310,7 @@ swiotlb_alloc_coherent (struct device *hwdev, size_t size, dma_addr_t *dma_handl
 
 	memset(ret, 0, size);
 	dev_addr = virt_to_phys(ret);
-	if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0)
+	if (address_needs_mapping(hwdev,dev_addr))
 		panic("swiotlb_alloc_consistent: allocated memory is out of range for device");
 	*dma_handle = dev_addr;
 	return ret;
@@ -297,6 +322,28 @@ swiotlb_free_coherent (struct device *hwdev, size_t size, void *vaddr, dma_addr_
 	free_pages((unsigned long) vaddr, get_order(size));
 }
 
+static void swiotlb_full(struct device *dev, size_t size, int dir, int do_panic)
+{
+	/* 
+	 * Ran out of IOMMU space for this operation. This is very bad.
+	 * Unfortunately the drivers cannot handle this operation properly.
+	 * unless they check for pci_dma_mapping_error (most don't)
+	 * When the mapping is small enough return a static buffer to limit
+	 * the damage, or panic when the transfer is too big. 
+	 */ 
+	
+	printk(KERN_ERR 
+  "PCI-DMA: Out of SW-IOMMU space for %lu bytes at device %s\n",
+	       size, dev ? dev->bus_id : "?");
+
+	if (size > io_tlb_overflow && do_panic) {
+		if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL)
+			panic("PCI-DMA: Memory would be corrupted\n");
+		if (dir == PCI_DMA_TODEVICE || dir == PCI_DMA_BIDIRECTIONAL) 
+			panic("PCI-DMA: Random memory would be DMAed\n"); 
+	} 
+} 
+
 /*
  * Map a single buffer of the indicated size for DMA in streaming mode.  The PCI address
  * to use is returned.
@@ -308,13 +355,14 @@ dma_addr_t
 swiotlb_map_single (struct device *hwdev, void *ptr, size_t size, int dir)
 {
 	unsigned long dev_addr = virt_to_phys(ptr);
+	void *map; 
 
 	if (dir == DMA_NONE)
 		BUG();
 	/*
 	 * Check if the PCI device can DMA to ptr... if so, just return ptr
 	 */
-	if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) == 0)
+	if (!address_needs_mapping(hwdev, dev_addr) && !swiotlb_force) 
 		/*
 		 * Device is bit capable of DMA'ing to the buffer... just return the PCI
 		 * address of ptr
@@ -324,12 +372,18 @@ swiotlb_map_single (struct device *hwdev, void *ptr, size_t size, int dir)
 	/*
 	 * get a bounce buffer:
 	 */
-	dev_addr = virt_to_phys(map_single(hwdev, ptr, size, dir));
+	map = map_single(hwdev, ptr, size, dir);
+	if (!map) { 
+		swiotlb_full(hwdev, size, dir, 1);		
+		map = io_tlb_overflow_buffer; 
+	}
+
+	dev_addr = virt_to_phys(map);
 
 	/*
 	 * Ensure that the address returned is DMA'ble:
 	 */
-	if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0)
+	if (address_needs_mapping(hwdev, dev_addr))
 		panic("map_single: bounce buffer is not DMA'ble");
 
 	return dev_addr;
@@ -437,9 +491,17 @@ swiotlb_map_sg (struct device *hwdev, struct scatterlist *sg, int nelems, int di
 	for (i = 0; i < nelems; i++, sg++) {
 		addr = SG_ENT_VIRT_ADDRESS(sg);
 		dev_addr = virt_to_phys(addr);
-		if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0)
-			sg->dma_address = (dma_addr_t) map_single(hwdev, addr, sg->length, dir);
-		else
+		if (swiotlb_force || address_needs_mapping(hwdev, dev_addr)) {
+			sg->dma_address = (dma_addr_t) virt_to_phys(map_single(hwdev, addr, sg->length, dir));
+			if (!sg->dma_address) {
+				/* Don't panic here, we expect pci_map_sg users
+				   to do proper error handling. */
+				swiotlb_full(hwdev, sg->length, dir, 0); 
+				swiotlb_unmap_sg(hwdev, sg - i, i, dir);
+				sg[0].dma_length = 0;
+				return 0;
+			}
+		} else
 			sg->dma_address = dev_addr;
 		sg->dma_length = sg->length;
 	}
@@ -460,7 +522,7 @@ swiotlb_unmap_sg (struct device *hwdev, struct scatterlist *sg, int nelems, int
 
 	for (i = 0; i < nelems; i++, sg++)
 		if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
-			unmap_single(hwdev, (void *) sg->dma_address, sg->dma_length, dir);
+			unmap_single(hwdev, (void *) phys_to_virt(sg->dma_address), sg->dma_length, dir);
 		else if (dir == DMA_FROM_DEVICE)
 			mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
 }
@@ -501,7 +563,7 @@ swiotlb_sync_sg_for_device (struct device *hwdev, struct scatterlist *sg, int ne
 int
 swiotlb_dma_mapping_error (dma_addr_t dma_addr)
 {
-	return 0;
+	return (dma_addr == virt_to_phys(io_tlb_overflow_buffer));
 }
 
 /*
diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
index c0f8f4a3e..0f905a637 100644
--- a/arch/ia64/mm/contig.c
+++ b/arch/ia64/mm/contig.c
@@ -116,19 +116,19 @@ find_bootmap_location (unsigned long start, unsigned long end, void *arg)
 		range_start = max(start, free_start);
 		range_end   = min(end, rsvd_region[i].start & PAGE_MASK);
 
+		free_start = PAGE_ALIGN(rsvd_region[i].end);
+
 		if (range_end <= range_start)
 			continue; /* skip over empty range */
 
-	       	if (range_end - range_start >= needed) {
+		if (range_end - range_start >= needed) {
 			bootmap_start = __pa(range_start);
-			return 1;	/* done */
+			return -1;	/* done */
 		}
 
 		/* nothing more available in this segment */
 		if (range_end == end)
 			return 0;
-
-		free_start = PAGE_ALIGN(rsvd_region[i].end);
 	}
 	return 0;
 }
@@ -267,9 +267,8 @@ paging_init (void)
 	efi_memmap_walk(find_largest_hole, (u64 *)&max_gap);
 	if (max_gap < LARGE_GAP) {
 		vmem_map = (struct page *) 0;
-		free_area_init_node(0, &contig_page_data, NULL, zones_size, 0,
+		free_area_init_node(0, &contig_page_data, zones_size, 0,
 				    zholes_size);
-		mem_map = contig_page_data.node_mem_map;
 	} else {
 		unsigned long map_size;
 
@@ -278,12 +277,12 @@ paging_init (void)
 		map_size = PAGE_ALIGN(max_low_pfn * sizeof(struct page));
 		vmalloc_end -= map_size;
 		vmem_map = (struct page *) vmalloc_end;
-		efi_memmap_walk(create_mem_map_page_table, 0);
+		efi_memmap_walk(create_mem_map_page_table, NULL);
 
-		free_area_init_node(0, &contig_page_data, vmem_map, zones_size,
+		mem_map = contig_page_data.node_mem_map = vmem_map;
+		free_area_init_node(0, &contig_page_data, zones_size,
 				    0, zholes_size);
 
-		mem_map = contig_page_data.node_mem_map;
 		printk("Virtual mem_map starts at 0x%p\n", mem_map);
 	}
 #else /* !CONFIG_VIRTUAL_MEM_MAP */
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index 23a9490fc..eb464cbb9 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -53,11 +53,12 @@ static struct early_node_data mem_data[NR_NODES] __initdata;
 static void __init reassign_cpu_only_nodes(void)
 {
 	struct node_memblk_s *p;
-	int i, j, k, nnode, nid, cpu, cpunid;
+	int i, j, k, nnode, nid, cpu, cpunid, pxm;
 	u8 cslit, slit;
 	static DECLARE_BITMAP(nodes_with_mem, NR_NODES) __initdata;
 	static u8 numa_slit_fix[MAX_NUMNODES * MAX_NUMNODES] __initdata;
 	static int node_flip[NR_NODES] __initdata;
+	static int old_nid_map[NR_CPUS] __initdata;
 
 	for (nnode = 0, p = &node_memblk[0]; p < &node_memblk[num_node_memblks]; p++)
 		if (!test_bit(p->nid, (void *) nodes_with_mem)) {
@@ -104,9 +105,14 @@ static void __init reassign_cpu_only_nodes(void)
 
 		for (cpu = 0; cpu < NR_CPUS; cpu++)
 			if (node_cpuid[cpu].nid == i) {
-				/* For nodes not being reassigned just fix the cpu's nid. */
+				/*
+				 * For nodes not being reassigned just
+				 * fix the cpu's nid and reverse pxm map
+				 */
 				if (cpunid < numnodes) {
-					node_cpuid[cpu].nid = cpunid;
+					pxm = nid_to_pxm_map[i];
+					pxm_to_nid_map[pxm] =
+					          node_cpuid[cpu].nid = cpunid;
 					continue;
 				}
 
@@ -126,6 +132,8 @@ static void __init reassign_cpu_only_nodes(void)
 						}
 					}
 
+				/* save old nid map so we can update the pxm */
+				old_nid_map[cpu] = node_cpuid[cpu].nid;
 				node_cpuid[cpu].nid = k;
 			}
 	}
@@ -134,14 +142,19 @@ static void __init reassign_cpu_only_nodes(void)
 	 * Fixup temporary nid values for CPU-only nodes.
 	 */
 	for (cpu = 0; cpu < NR_CPUS; cpu++)
-		if (node_cpuid[cpu].nid == (numnodes + numnodes))
-			node_cpuid[cpu].nid = nnode - 1;
-		else
-			for (i = 0; i < nnode; i++)
-				if (node_flip[i] == (node_cpuid[cpu].nid - numnodes)) {
-					node_cpuid[cpu].nid = i;
-					break;
-				}
+		if (node_cpuid[cpu].nid == (numnodes + numnodes)) {
+			pxm = nid_to_pxm_map[old_nid_map[cpu]];
+			pxm_to_nid_map[pxm] = node_cpuid[cpu].nid = nnode - 1;
+		} else {
+			for (i = 0; i < nnode; i++) {
+				if (node_flip[i] != (node_cpuid[cpu].nid - numnodes))
+					continue;
+
+				pxm = nid_to_pxm_map[old_nid_map[cpu]];
+				pxm_to_nid_map[pxm] = node_cpuid[cpu].nid = i;
+				break;
+			}
+		}
 
 	/*
 	 * Fix numa_slit by compressing from larger
@@ -492,14 +505,17 @@ void *per_cpu_init(void)
  */
 void show_mem(void)
 {
-	int i, reserved = 0;
-	int shared = 0, cached = 0;
+	int i, total_reserved = 0;
+	int total_shared = 0, total_cached = 0;
+	unsigned long total_present = 0;
 	pg_data_t *pgdat;
 
 	printk("Mem-info:\n");
 	show_free_areas();
 	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
 	for_each_pgdat(pgdat) {
+		unsigned long present = pgdat->node_present_pages;
+		int shared = 0, cached = 0, reserved = 0;
 		printk("Node ID: %d\n", pgdat->node_id);
 		for(i = 0; i < pgdat->node_spanned_pages; i++) {
 			if (!ia64_pfn_valid(pgdat->node_start_pfn+i))
@@ -511,11 +527,19 @@ void show_mem(void)
 			else if (page_count(pgdat->node_mem_map+i))
 				shared += page_count(pgdat->node_mem_map+i)-1;
 		}
-		printk("\t%ld pages of RAM\n", pgdat->node_present_pages);
+		total_present += present;
+		total_reserved += reserved;
+		total_cached += cached;
+		total_shared += shared;
+		printk("\t%ld pages of RAM\n", present);
 		printk("\t%d reserved pages\n", reserved);
 		printk("\t%d pages shared\n", shared);
 		printk("\t%d pages swap cached\n", cached);
 	}
+	printk("%ld pages of RAM\n", total_present);
+	printk("%d reserved pages\n", total_reserved);
+	printk("%d pages shared\n", total_shared);
+	printk("%d pages swap cached\n", total_cached);
 	printk("Total of %ld pages in page table cache\n", pgtable_cache_size);
 	printk("%d free buffer pages\n", nr_free_buffer_pages());
 }
@@ -607,12 +631,10 @@ void paging_init(void)
 	unsigned long max_dma;
 	unsigned long zones_size[MAX_NR_ZONES];
 	unsigned long zholes_size[MAX_NR_ZONES];
-	unsigned long max_gap, pfn_offset = 0;
+	unsigned long pfn_offset = 0;
 	int node;
 
 	max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-	max_gap = 0;
-	efi_memmap_walk(find_largest_hole, &max_gap);
 
 	/* so min() will work in count_node_pages */
 	for (node = 0; node < numnodes; node++)
@@ -664,8 +686,8 @@ void paging_init(void)
 
 		pfn_offset = mem_data[node].min_pfn;
 
-		free_area_init_node(node, NODE_DATA(node),
-				    vmem_map + pfn_offset, zones_size,
+		NODE_DATA(node)->node_mem_map = vmem_map + pfn_offset;
+		free_area_init_node(node, NODE_DATA(node), zones_size,
 				    pfn_offset, zholes_size);
 	}
 
diff --git a/arch/ia64/mm/extable.c b/arch/ia64/mm/extable.c
index 2353cc795..99edfed31 100644
--- a/arch/ia64/mm/extable.c
+++ b/arch/ia64/mm/extable.c
@@ -77,7 +77,7 @@ search_extable (const struct exception_table_entry *first,
                 else
                         last = mid - 1;
         }
-        return 0;
+        return NULL;
 }
 
 void
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
index 8e63f14ac..134d24b97 100644
--- a/arch/ia64/mm/fault.c
+++ b/arch/ia64/mm/fault.c
@@ -9,12 +9,12 @@
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
+#include <linux/vs_memory.h>
 
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 
 extern void die (char *, struct pt_regs *, long);
 
@@ -47,6 +47,7 @@ expand_backing_store (struct vm_area_struct *vma, unsigned long address)
 	if (vma->vm_flags & VM_LOCKED)
 		// vma->vm_mm->locked_vm += grow;
 		vx_vmlocked_add(vma->vm_mm, grow);
+	__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow);
 	return 0;
 }
 
@@ -203,7 +204,7 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
 		si.si_signo = signal;
 		si.si_errno = 0;
 		si.si_code = code;
-		si.si_addr = (void *) address;
+		si.si_addr = (void __user *) address;
 		si.si_isr = isr;
 		si.si_flags = __ISR_VALID;
 		force_sig_info(signal, &si, current);
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index 3ab0b37e0..87a8016f5 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -67,9 +67,9 @@ check_pgt_cache (void)
 	if (pgtable_cache_size > (u64) high) {
 		do {
 			if (pgd_quicklist)
-				free_page((unsigned long)pgd_alloc_one_fast(0));
+				free_page((unsigned long)pgd_alloc_one_fast(NULL));
 			if (pmd_quicklist)
-				free_page((unsigned long)pmd_alloc_one_fast(0, 0));
+				free_page((unsigned long)pmd_alloc_one_fast(NULL, 0));
 		} while (pgtable_cache_size > (u64) low);
 	}
 	preempt_enable();
@@ -429,20 +429,22 @@ virtual_memmap_init (u64 start, u64 end, void *arg)
 		    / sizeof(struct page));
 
 	if (map_start < map_end)
-		memmap_init_zone(map_start, (unsigned long) (map_end - map_start),
+		memmap_init_zone((unsigned long)(map_end - map_start),
 				 args->nid, args->zone, page_to_pfn(map_start));
 	return 0;
 }
 
 void
-memmap_init (struct page *start, unsigned long size, int nid,
-	     unsigned long zone, unsigned long start_pfn)
+memmap_init (unsigned long size, int nid, unsigned long zone,
+	     unsigned long start_pfn)
 {
 	if (!vmem_map)
-		memmap_init_zone(start, size, nid, zone, start_pfn);
+		memmap_init_zone(size, nid, zone, start_pfn);
 	else {
+		struct page *start;
 		struct memmap_init_callback_data args;
 
+		start = pfn_to_page(start_pfn);
 		args.start = start;
 		args.end = start + size;
 		args.nid = nid;
@@ -458,9 +460,9 @@ ia64_pfn_valid (unsigned long pfn)
 	char byte;
 	struct page *pg = pfn_to_page(pfn);
 
-	return     (__get_user(byte, (char *) pg) == 0)
+	return     (__get_user(byte, (char __user *) pg) == 0)
 		&& ((((u64)pg & PAGE_MASK) == (((u64)(pg + 1) - 1) & PAGE_MASK))
-			|| (__get_user(byte, (char *) (pg + 1) - 1) == 0));
+			|| (__get_user(byte, (char __user *) (pg + 1) - 1) == 0));
 }
 EXPORT_SYMBOL(ia64_pfn_valid);
 
@@ -585,6 +587,6 @@ mem_init (void)
 	setup_gate();
 
 #ifdef CONFIG_IA32_SUPPORT
-	ia32_boot_gdt_init();
+	ia32_mem_init();
 #endif
 }
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
index dc15aa01c..0c5cb3c61 100644
--- a/arch/ia64/mm/tlb.c
+++ b/arch/ia64/mm/tlb.c
@@ -176,7 +176,7 @@ ia64_tlb_init (void)
 	if ((status = ia64_pal_vm_page_size(&tr_pgbits, &purge.mask)) != 0) {
 		printk(KERN_ERR "PAL_VM_PAGE_SIZE failed with status=%ld;"
 		       "defaulting to architected purge page-sizes.\n", status);
-		purge.mask = 0x115557000;
+		purge.mask = 0x115557000UL;
 	}
 	purge.max_bits = ia64_fls(purge.mask);
 
diff --git a/arch/ia64/oprofile/Kconfig b/arch/ia64/oprofile/Kconfig
index bfac82f3e..56e6f614b 100644
--- a/arch/ia64/oprofile/Kconfig
+++ b/arch/ia64/oprofile/Kconfig
@@ -16,6 +16,10 @@ config OPROFILE
 	  whole system, include the kernel, kernel modules, libraries,
 	  and applications.
 
+	  Due to firmware bugs, you may need to use the "nohalt" boot
+	  option if you're using OProfile with the hardware performance
+	  counters.
+
 	  If unsure, say N.
 
 endmenu
diff --git a/arch/ia64/oprofile/Makefile b/arch/ia64/oprofile/Makefile
index 06e7c81ea..29aeef4f6 100644
--- a/arch/ia64/oprofile/Makefile
+++ b/arch/ia64/oprofile/Makefile
@@ -7,3 +7,4 @@ DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
 		timer_int.o )
 
 oprofile-y := $(DRIVER_OBJS) init.o
+oprofile-$(CONFIG_PERFMON) += perfmon.o
diff --git a/arch/ia64/oprofile/init.c b/arch/ia64/oprofile/init.c
index 558561d6d..6d0c132b0 100644
--- a/arch/ia64/oprofile/init.c
+++ b/arch/ia64/oprofile/init.c
@@ -12,14 +12,21 @@
 #include <linux/init.h>
 #include <linux/errno.h>
  
-extern void timer_init(struct oprofile_operations ** ops);
+extern int perfmon_init(struct oprofile_operations ** ops);
+extern void perfmon_exit(void);
 
 int __init oprofile_arch_init(struct oprofile_operations ** ops)
 {
+#ifdef CONFIG_PERFMON
+	return perfmon_init(ops);
+#endif
 	return -ENODEV;
 }
 
 
 void oprofile_arch_exit(void)
 {
+#ifdef CONFIG_PERFMON
+	perfmon_exit();
+#endif
 }
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 82204f1bd..dd33eaf87 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -46,8 +46,6 @@
 #define DBG(x...)
 #endif
 
-struct pci_fixup pcibios_fixups[1];
-
 /*
  * Low-level SAL-based PCI configuration access functions. Note that SAL
  * calls are already serialized (via sal_lock), so we don't need another
@@ -138,6 +136,11 @@ pci_acpi_init (void)
 
 	printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
 
+#ifdef CONFIG_NUMA
+extern acpi_status acpi_map_iosapic (acpi_handle, u32, void*, void**);
+
+	acpi_get_devices(NULL, acpi_map_iosapic, NULL, NULL);
+#endif
 	/*
 	 * PCI IRQ routing is set up by pci_enable_device(), but we
 	 * also do it here in case there are still broken drivers that
@@ -332,7 +335,7 @@ pcibios_fixup_device_resources (struct pci_dev *dev, struct pci_bus *bus)
 	struct pci_window *window;
 	int i, j;
 	int limit = (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) ? \
-		PCI_ROM_RESOURCE : PCI_NUM_RESOURCES;
+		PCI_BRIDGE_RESOURCES : PCI_NUM_RESOURCES;
 
 	for (i = 0; i < limit; i++) {
 		if (!dev->resource[i].start)
diff --git a/arch/ia64/sn/io/hwgfs/interface.c b/arch/ia64/sn/io/hwgfs/interface.c
index caac7f067..4e1941805 100644
--- a/arch/ia64/sn/io/hwgfs/interface.c
+++ b/arch/ia64/sn/io/hwgfs/interface.c
@@ -42,7 +42,7 @@ walk_parents_mkdir(
 
 		nd->dentry = lookup_create(nd, is_dir);
 		nd->flags |= LOOKUP_PARENT;
-		if (unlikely(IS_ERR(nd->dentry)))
+		if (IS_ERR(nd->dentry))
 			return PTR_ERR(nd->dentry);
 
 		if (!nd->dentry->d_inode)
@@ -89,7 +89,7 @@ hwgfs_decode(
 
 	*dentry = lookup_create(&nd, is_dir);
 
-	if (unlikely(IS_ERR(*dentry)))
+	if (IS_ERR(*dentry))
 		return PTR_ERR(*dentry);
 	*parent_inode = (*dentry)->d_parent->d_inode;
 	return 0;
diff --git a/arch/ia64/sn/io/machvec/pci_bus_cvlink.c b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c
index ba9e42c12..cb91a4d07 100644
--- a/arch/ia64/sn/io/machvec/pci_bus_cvlink.c
+++ b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c
@@ -290,6 +290,7 @@ sn_pci_fixup_slot(struct pci_dev *dev)
 			addr |= __IA64_UNCACHED_OFFSET;
 			dev->resource[idx].start = addr;
 			dev->resource[idx].end = addr + size;
+			dev->resource[idx].parent = &ioport_resource;
 		}
 
 		if (dev->resource[idx].flags & IORESOURCE_IO)
@@ -322,6 +323,7 @@ sn_pci_fixup_slot(struct pci_dev *dev)
 			addr |= __IA64_UNCACHED_OFFSET;
 			dev->resource[idx].start = addr;
 			dev->resource[idx].end = addr + size;
+			dev->resource[idx].parent = &iomem_resource;
 		}
 
 		if (dev->resource[idx].flags & IORESOURCE_MEM)
@@ -351,10 +353,24 @@ sn_pci_fixup_slot(struct pci_dev *dev)
                         addr |= __IA64_UNCACHED_OFFSET;
                         dev->resource[PCI_ROM_RESOURCE].start = addr;
                         dev->resource[PCI_ROM_RESOURCE].end = addr + size;
+			dev->resource[idx].parent = &iomem_resource;
                         if (dev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_MEM)
                                 cmd |= PCI_COMMAND_MEMORY;
                 }
-        }
+        } else {
+		/*
+		 * Remove other ROM resources since they don't have valid
+		 * CPU addresses.
+		 */
+                size = dev->resource[PCI_ROM_RESOURCE].end -
+                        dev->resource[PCI_ROM_RESOURCE].start;
+
+		if (size) {
+			dev->resource[PCI_ROM_RESOURCE].start = 0;
+			dev->resource[PCI_ROM_RESOURCE].end = 0;
+			dev->resource[PCI_ROM_RESOURCE].flags = 0;
+		}
+	}
 
 	/*
 	 * Update the Command Word on the Card.
diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c
index e040fc3c4..94a99eeb1 100644
--- a/arch/ia64/sn/kernel/bte.c
+++ b/arch/ia64/sn/kernel/bte.c
@@ -421,9 +421,10 @@ bte_init_node(nodepda_t * mynodepda, cnodeid_t cnode)
 	mynodepda->bte_recovery_timer.data = (unsigned long) mynodepda;
 
 	for (i = 0; i < BTES_PER_NODE; i++) {
-		(u64) mynodepda->bte_if[i].bte_base_addr =
-		    REMOTE_HUB_ADDR(cnodeid_to_nasid(cnode),
-			(i == 0 ? IIO_IBLS0 : IIO_IBLS1));
+		/* Which link status register should we use? */
+		unsigned long link_status = (i == 0 ? IIO_IBLS0 : IIO_IBLS1);
+		mynodepda->bte_if[i].bte_base_addr = (u64 *)
+			REMOTE_HUB_ADDR(cnodeid_to_nasid(cnode), link_status);
 
 		/*
 		 * Initialize the notification and spinlock
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index d3830e338..4a0aa40c4 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -64,6 +64,8 @@ extern unsigned char acpi_kbd_controller_present;
 
 unsigned long sn_rtc_cycles_per_second;   
 
+EXPORT_SYMBOL(sn_rtc_cycles_per_second);
+
 partid_t sn_partid = -1;
 char sn_system_serial_number_string[128];
 u64 sn_partition_serial_number;
diff --git a/arch/ia64/sn/kernel/sn2/Makefile b/arch/ia64/sn/kernel/sn2/Makefile
index 0143b8182..170bde454 100644
--- a/arch/ia64/sn/kernel/sn2/Makefile
+++ b/arch/ia64/sn/kernel/sn2/Makefile
@@ -10,4 +10,4 @@
 #
 
 obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \
-	 prominfo_proc.o timer.o timer_interrupt.o
+	 prominfo_proc.o timer.o timer_interrupt.o sn_hwperf.o
diff --git a/arch/ia64/sn/kernel/sn2/prominfo_proc.c b/arch/ia64/sn/kernel/sn2/prominfo_proc.c
index bcc938b28..32db72ae7 100644
--- a/arch/ia64/sn/kernel/sn2/prominfo_proc.c
+++ b/arch/ia64/sn/kernel/sn2/prominfo_proc.c
@@ -3,10 +3,10 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1999,2001-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (C) 1999,2001-2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * Module to export the system's Firmware Interface Tables, including
- * PROM revision numbers, in /proc
+ * PROM revision numbers and banners, in /proc
  */
 #include <linux/config.h>
 #include <linux/module.h>
@@ -14,41 +14,14 @@
 #include <linux/proc_fs.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/sn/sn2/addrs.h>
-#include <asm/sn/simulator.h>
-
-/* to lookup nasids */
+#include <asm/sn/sn_sal.h>
 #include <asm/sn/sn_cpuid.h>
+#include <asm/sn/sn2/addrs.h>
 
 MODULE_DESCRIPTION("PROM version reporting for /proc");
 MODULE_AUTHOR("Chad Talbott");
 MODULE_LICENSE("GPL");
 
-#undef DEBUG_PROMINFO
-
-#define TRACE_PROMINFO
-
-#if defined(DEBUG_PROMINFO)
-#  define DPRINTK(x...) printk(KERN_DEBUG x)
-#else
-#  define DPRINTK(x...)
-#endif
-
-#if defined(TRACE_PROMINFO) && defined(DEBUG_PROMINFO)
-#  if defined(__GNUC__)
-#    define TRACE()	printk(KERN_DEBUG "%s:%d:%s\n", \
-			       __FILE__, __LINE__, __FUNCTION__)
-#  else
-#    define TRACE()	printk(KERN_DEBUG "%s:%d\n", __LINE__, __FILE__)
-#  endif
-#else
-#  define TRACE()
-#endif
-
-/* Sub-regions determined by bits in Node Offset */
-#define	LB_PROM_SPACE		0x0000000700000000ul /* Local LB PROM */
-
-#define FIT_SIGNATURE		0x2020205f5449465ful
 /* Standard Intel FIT entry types */
 #define FIT_ENTRY_FIT_HEADER	0x00	/* FIT header entry */
 #define FIT_ENTRY_PAL_B		0x01	/* PAL_B entry */
@@ -81,12 +54,6 @@ MODULE_LICENSE("GPL");
 #define FIT_TYPE(q)	\
 	((unsigned) ((q) >> FIT_TYPE_SHIFT) & FIT_TYPE_MASK)
 
-#define FIT_ENTRY(type, maj, min, size)					\
-	((((unsigned long)(maj) & FIT_MAJOR_MASK) << FIT_MAJOR_SHIFT) |	\
-	 (((unsigned long)(min) & FIT_MINOR_MASK) << FIT_MINOR_SHIFT) |	\
-	 (((unsigned long)(type) & FIT_TYPE_MASK) << FIT_TYPE_SHIFT) |	\
-	 (size))
-
 struct fit_type_map_t {
 	unsigned char	type;
 	const char	*name;
@@ -125,32 +92,148 @@ fit_type_name(unsigned char type)
 	return "Unknown type";
 }
 
-/* These two routines read the FIT table directly from the FLASH PROM
- * on a specific node.  The PROM can only be accessed using aligned 64
- * bit reads, so we do that and then shift and mask the result to get
- * at each field.
+
+/* ============ BEGIN temp til old PROMs are no longer supported =============
+ *
+ * The OS should not make direct access to the PROM flash memory. Access to
+ * this region must be serialized with a PROM lock. If SAL on one cpu is
+ * updating the FLASH error log at the same time another cpu is accessing the
+ * PROM, data corruption will occur.
+ *
+ * To solve the problem, all flash PROM access has been moved to SAL. Because
+ * not all systems will have instant PROM updates, we need to support a new OS
+ * running on a system with old PROMs.
+ *
+ * This code should be deleted after 1 OS/PROM release has occurred & the OS
+ * no longer supports downrev PROMs. (PROM support should be in the 3.50
+ * PROMs).
+ */
+#define SUPPORT_OLD_PROMS
+#ifdef SUPPORT_OLD_PROMS
+
+
+#define FIT_SIGNATURE		0x2020205f5449465ful
+
+/* Sub-regions determined by bits in Node Offset */
+#define	LB_PROM_SPACE		0x0000000700000000ul /* Local LB PROM */
+
+/* Offset of PROM banner pointers in SAL A and SAL B */
+#define SAL_A_BANNER_OFFSET	(1 * 16)
+#define SAL_B_BANNER_OFFSET	(3 * 16)
+
+/* Architected IA64 firmware space */
+#define FW_BASE                 0x00000000FF000000
+#define FW_TOP                  0x0000000100000000
+
+static unsigned long
+convert_fw_addr(nasid_t nasid, unsigned long addr)
+{
+	/* snag just the node-relative offset */
+	addr &= ~0ul >> (63-35);
+	/* the pointer to SAL A is relative to IA-64 compatibility
+	 * space.  However, the PROM is mapped at a different offset
+	 * in MMR space (both local and global)
+	 */
+	addr += 0x700000000;
+	return GLOBAL_MMR_ADDR(nasid, addr);
+}
+
+static int
+valid_fw_addr(unsigned long addr)
+{
+	addr &= ~(1ul << 63); /* Clear cached/uncached bit */
+	return (addr >= FW_BASE && addr < FW_TOP);
+}
+
+static unsigned long *
+lookup_fit(int nasid)
+{
+	unsigned long *fitp;
+	unsigned long fit_paddr;
+	unsigned long *fit_vaddr;
+
+	fitp = (void *)GLOBAL_MMR_ADDR(nasid, LB_PROM_SPACE - 32);
+	fit_paddr = readq(fitp);
+	fit_vaddr = (unsigned long *) convert_fw_addr(nasid, fit_paddr);
+	return fit_vaddr;
+}
+#endif /* SUPPORT_OLD_PROMS */
+/* ============ END temp til old PROMs are no longer supported ============= */
+
+static int
+get_fit_entry(unsigned long nasid, int index, unsigned long *fentry,
+	      char *banner, int banlen)
+{
+	int ret;
+
+	ret = ia64_sn_get_fit_compt(nasid, index, fentry, banner, banlen);
+
+#ifdef SUPPORT_OLD_PROMS
+	/* The following is hack is temporary until PROMs are updated */
+	if (ret == SALRET_NOT_IMPLEMENTED) {
+		unsigned long *fitadr = lookup_fit(nasid);
+		int nentries;
+
+		if (readq(fitadr) != FIT_SIGNATURE) {
+			printk(KERN_WARNING "Unrecognized FIT signature");
+			return -2;
+		}
+
+		nentries = (unsigned int) (readq(fitadr + 1) & 0xffffff);
+		if (index >= nentries)
+			return -2;
+
+		fentry[0] = readq(fitadr + 2 * index);
+		fentry[1] = readq(fitadr + 2 * index + 1);
+		ret = 0;
+
+		if (banner && FIT_TYPE(fentry[1]) == FIT_ENTRY_SAL_A) {
+			unsigned long i, qw, *bwp, *qwp;
+
+			banner[0] = '\0';
+			qw = fentry[0];	/* Address of SAL A */
+			if (!valid_fw_addr(qw))
+				return 0;
+
+			qw += SAL_A_BANNER_OFFSET;
+			qw = convert_fw_addr(nasid, qw);
+
+			qw = readq(qw);			/* Address of banner */
+			if (!valid_fw_addr(qw))
+				return 0;
+			qw = convert_fw_addr(nasid, qw);
+			qwp = (unsigned long *) qw;
+			bwp = (unsigned long *) banner;
+			for (i=0; i<banlen/8; i++)
+				bwp[i] = qwp[i];
+		}
+	}
+#endif /* SUPPORT_OLD_PROMS */
+	return ret;
+}
+
+
+/*
+ * These two routines display the FIT table for each node.
  */
 static int
 dump_fit_entry(char *page, unsigned long *fentry)
 {
-	unsigned long q1, q2;
 	unsigned type;
 
-	TRACE();
-
-	q1 = readq(fentry);
-	q2 = readq(fentry + 1);
-	type = FIT_TYPE(q2);
+	type = FIT_TYPE(fentry[1]);
 	return sprintf(page, "%02x %-25s %x.%02x %016lx %u\n",
 		       type,
 		       fit_type_name(type),
-		       FIT_MAJOR(q2), FIT_MINOR(q2),
-		       q1,
+		       FIT_MAJOR(fentry[1]), FIT_MINOR(fentry[1]),
+		       fentry[0],
 		       /* mult by sixteen to get size in bytes */
-		       (unsigned)q2 * 16);
+		       (unsigned)(fentry[1] & 0xffffff) * 16);
 }
 
-/* We assume that the fit table will be small enough that we can print
+
+/*
+ * We assume that the fit table will be small enough that we can print
  * the whole thing into one page.  (This is true for our default 16kB
  * pages -- each entry is about 60 chars wide when printed.)  I read
  * somewhere that the maximum size of the FIT is 128 entries, so we're
@@ -158,55 +241,47 @@ dump_fit_entry(char *page, unsigned long *fentry)
  * anyway).
  */
 static int
-dump_fit(char *page, unsigned long *fit)
+dump_fit(char *page, unsigned long nasid)
 {
-	unsigned long qw;
-	int nentries;
-	int fentry;
+	unsigned long fentry[2];
+	int index;
 	char *p;
 
-	TRACE();
-
-	DPRINTK("dumping fit from %p\n", (void *)fit);
-
-	qw = readq(fit);
-	DPRINTK("FIT signature: %016lx (%.8s)\n", qw, (char *)&qw);
-	if (qw != FIT_SIGNATURE)
-		printk(KERN_WARNING "Unrecognized FIT signature");
-
-	qw = readq(fit + 1);
-	nentries = (unsigned)qw;
-	DPRINTK("number of fit entries: %u\n", nentries);
-	/* check that we won't overflow the page -- see comment above */
-	BUG_ON(nentries * 60 > PAGE_SIZE);
-
 	p = page;
-	for (fentry = 0; fentry < nentries; fentry++)
-		/* each FIT entry is two 64 bit words */
-		p += dump_fit_entry(p, fit + 2 * fentry);
+	for (index=0;;index++) {
+		BUG_ON(index * 60 > PAGE_SIZE);
+		if (get_fit_entry(nasid, index, fentry, NULL, 0))
+			break;
+		p += dump_fit_entry(p, fentry);
+	}
 
 	return p - page;
 }
 
 static int
-dump_version(char *page, unsigned long *fit)
+dump_version(char *page, unsigned long nasid)
 {
-	int nentries;
-	int fentry;
-	unsigned long qw;
+	unsigned long fentry[2];
+	char banner[128];
+	int index;
+	int len;
+
+	for (index = 0; ; index++) {
+		if (get_fit_entry(nasid, index, fentry, banner,
+				  sizeof(banner)))
+			return 0;
+		if (FIT_TYPE(fentry[1]) == FIT_ENTRY_SAL_A)
+			break;
+	}
 
-	TRACE();
+	len = sprintf(page, "%x.%02x\n", FIT_MAJOR(fentry[1]),
+		      FIT_MINOR(fentry[1]));
+	page += len;
 
-	nentries = (unsigned)readq(fit + 1);
-	BUG_ON(nentries * 60 > PAGE_SIZE);
+	if (banner[0])
+		len += snprintf(page, PAGE_SIZE-len, "%s\n", banner);
 
-	for (fentry = 0; fentry < nentries; fentry++) {
-		qw = readq(fit + 2 * fentry + 1);
-		if (FIT_TYPE(qw) == FIT_ENTRY_SAL_A)
-			return sprintf(page, "%x.%02x\n",
-				       FIT_MAJOR(qw), FIT_MINOR(qw));
-	}
-	return 0;
+	return len;
 }
 
 /* same as in proc_misc.c */
@@ -228,8 +303,8 @@ read_version_entry(char *page, char **start, off_t off, int count, int *eof,
 {
 	int len = 0;
 
-	/* data holds the pointer to this node's FIT */
-	len = dump_version(page, (unsigned long *)data);
+	/* data holds the NASID of the node */
+	len = dump_version(page, (unsigned long)data);
 	len = proc_calc_metrics(page, start, off, count, eof, len);
 	return len;
 }
@@ -240,56 +315,13 @@ read_fit_entry(char *page, char **start, off_t off, int count, int *eof,
 {
 	int len = 0;
 
-	/* data holds the pointer to this node's FIT */
-	len = dump_fit(page, (unsigned long *)data);
+	/* data holds the NASID of the node */
+	len = dump_fit(page, (unsigned long)data);
 	len = proc_calc_metrics(page, start, off, count, eof, len);
 
 	return len;
 }
 
-/* this is a fake FIT that's used on the medusa simulator which
- * doesn't usually run a complete PROM. 
- */
-#ifdef CONFIG_IA64_SGI_SN_SIM
-static unsigned long fakefit[] = {
-	/* this is all we need to satisfy the code below */
-	FIT_SIGNATURE,
-	FIT_ENTRY(FIT_ENTRY_FIT_HEADER, 0x02, 0x60, 2),
-	/* dump something arbitrary for
-	 * /proc/sgi_prominfo/nodeX/version */
-	0xbadbeef00fa3ef17ul,
-	FIT_ENTRY(FIT_ENTRY_SAL_A, 0, 0x99, 0x100)
-};	
-#endif
-
-static unsigned long *
-lookup_fit(int nasid)
-{
-	unsigned long *fitp;
-	unsigned long fit_paddr;
-	unsigned long *fit_vaddr;
-
-#ifdef CONFIG_IA64_SGI_SN_SIM
-	if (IS_RUNNING_ON_SIMULATOR())
-		return fakefit;
-#endif
-
-	fitp = (void *)GLOBAL_MMR_ADDR(nasid, LB_PROM_SPACE - 32);
-	DPRINTK("pointer to fit at %p\n", (void *)fitp);
-	fit_paddr = readq(fitp);
-	DPRINTK("fit pointer contains %lx\n", fit_paddr);
-	/* snag just the node-relative offset */
-	fit_paddr &= ~0ul >> (63-35);
-	/* the pointer to the FIT is relative to IA-64 compatibility
-	 * space.  However, the PROM is mapped at a different offset
-	 * in MMR space (both local and global)
-	 */
-	fit_paddr += 0x700000000;
-	fit_vaddr = (void *)GLOBAL_MMR_ADDR(nasid, fit_paddr);
-	DPRINTK("fit at %p\n", (void *)fit_vaddr);
-	return fit_vaddr;
-}
-
 /* module entry points */
 int __init prominfo_init(void);
 void __exit prominfo_exit(void);
@@ -308,17 +340,12 @@ prominfo_init(void)
 	struct proc_dir_entry **entp;
 	struct proc_dir_entry *p;
 	cnodeid_t cnodeid;
-	nasid_t nasid;
+	unsigned long nasid;
 	char name[NODE_NAME_LEN];
 
 	if (!ia64_platform_is("sn2"))
 		return 0;
 
-	TRACE();
-
-	DPRINTK("running on cpu %d\n", smp_processor_id());
-	DPRINTK("numnodes %d\n", numnodes);
-
 	proc_entries = kmalloc(numnodes * sizeof(struct proc_dir_entry *),
 			       GFP_KERNEL);
 
@@ -332,12 +359,12 @@ prominfo_init(void)
 		nasid = cnodeid_to_nasid(cnodeid);
 		p = create_proc_read_entry(
 			"fit", 0, *entp, read_fit_entry,
-			lookup_fit(nasid));
+			(void *)nasid);
 		if (p)
 			p->owner = THIS_MODULE;
 		p = create_proc_read_entry(
 			"version", 0, *entp, read_version_entry,
-			lookup_fit(nasid));
+			(void *)nasid);
 		if (p)
 			p->owner = THIS_MODULE;
 	}
@@ -352,8 +379,6 @@ prominfo_exit(void)
 	unsigned cnodeid;
 	char name[NODE_NAME_LEN];
 
-	TRACE();
-
 	for (cnodeid = 0, entp = proc_entries;
 	     cnodeid < numnodes;
 	     cnodeid++, entp++) {
diff --git a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
index 14840791a..55c1065e9 100644
--- a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
+++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
@@ -3,74 +3,48 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved.
  */
 #include <linux/config.h>
 #include <asm/uaccess.h>
 
 #ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <asm/sn/sgi.h>
 #include <asm/sn/sn_sal.h>
 
-
-static int partition_id_read_proc(char *page, char **start, off_t off,
-		int count, int *eof, void *data) {
-
-	return sprintf(page, "%d\n", sn_local_partid());
+static int partition_id_show(struct seq_file *s, void *p)
+{
+	seq_printf(s, "%d\n", sn_local_partid());
+	return 0;
 }
 
-static struct proc_dir_entry * sgi_proc_dir;
-
-void
-register_sn_partition_id(void) {
-	struct proc_dir_entry *entry;
-
-	if (!sgi_proc_dir) {
-		sgi_proc_dir = proc_mkdir("sgi_sn", 0);
-	}
-	entry = create_proc_entry("partition_id", 0444, sgi_proc_dir);
-	if (entry) {
-		entry->nlink = 1;
-		entry->data = 0;
-		entry->read_proc = partition_id_read_proc;
-		entry->write_proc = NULL;
-	}
+static int partition_id_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, partition_id_show, NULL);
 }
 
-static int
-system_serial_number_read_proc(char *page, char **start, off_t off,
-		int count, int *eof, void *data) {
-	return sprintf(page, "%s\n", sn_system_serial_number());
+static int system_serial_number_show(struct seq_file *s, void *p)
+{
+	seq_printf(s, "%s\n", sn_system_serial_number());
+	return 0;
 }
 
-static int
-licenseID_read_proc(char *page, char **start, off_t off,
-		int count, int *eof, void *data) {
-	return sprintf(page, "0x%lx\n",sn_partition_serial_number_val());
+static int system_serial_number_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, system_serial_number_show, NULL);
 }
 
-void
-register_sn_serial_numbers(void) {
-	struct proc_dir_entry *entry;
+static int licenseID_show(struct seq_file *s, void *p)
+{
+	seq_printf(s, "0x%lx\n", sn_partition_serial_number_val());
+	return 0;
+}
 
-	if (!sgi_proc_dir) {
-		sgi_proc_dir = proc_mkdir("sgi_sn", 0);
-	}
-	entry = create_proc_entry("system_serial_number", 0444, sgi_proc_dir);
-	if (entry) {
-		entry->nlink = 1;
-		entry->data = 0;
-		entry->read_proc = system_serial_number_read_proc;
-		entry->write_proc = NULL;
-	}
-	entry = create_proc_entry("licenseID", 0444, sgi_proc_dir);
-	if (entry) {
-		entry->nlink = 1;
-		entry->data = 0;
-		entry->read_proc = licenseID_read_proc;
-		entry->write_proc = NULL;
-	}
+static int licenseID_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, licenseID_show, NULL);
 }
 
 /*
@@ -81,48 +55,90 @@ register_sn_serial_numbers(void) {
  */
 int sn_force_interrupt_flag = 1;
 
-static int
-sn_force_interrupt_read_proc(char *page, char **start, off_t off,
-		int count, int *eof, void *data) {
-	if (sn_force_interrupt_flag) {
-		return sprintf(page, "Force interrupt is enabled\n");
-	}
-	return sprintf(page, "Force interrupt is disabled\n");
+static int sn_force_interrupt_show(struct seq_file *s, void *p)
+{
+	seq_printf(s, "Force interrupt is %s\n",
+		sn_force_interrupt_flag ? "enabled" : "disabled");
+	return 0;
 }
 
-static int 
-sn_force_interrupt_write_proc(struct file *file, const char *buffer,
-                                        unsigned long count, void *data)
+static ssize_t sn_force_interrupt_write_proc(struct file *file,
+		const __user char *buffer, size_t count, loff_t *data)
 {
-	if (*buffer == '0') {
-		sn_force_interrupt_flag = 0;
-	} else {
-		sn_force_interrupt_flag = 1;
-	}
-	return 1;
+	sn_force_interrupt_flag = (*buffer == '0') ? 0 : 1;
+	return count;
 }
 
-void
-register_sn_force_interrupt(void) {
-	struct proc_dir_entry *entry;
+static int sn_force_interrupt_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, sn_force_interrupt_show, NULL);
+}
 
-	if (!sgi_proc_dir) {
-		sgi_proc_dir = proc_mkdir("sgi_sn", 0);
-	}
-	entry = create_proc_entry("sn_force_interrupt",0444, sgi_proc_dir);
-	if (entry) {
-		entry->nlink = 1;
-		entry->data = 0;
-		entry->read_proc = sn_force_interrupt_read_proc;
-		entry->write_proc = sn_force_interrupt_write_proc;
+static int coherence_id_show(struct seq_file *s, void *p)
+{
+	seq_printf(s, "%d\n", cpuid_to_coherence_id(smp_processor_id()));
+	return 0;
+}
+
+static int coherence_id_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, coherence_id_show, NULL);
+}
+
+static struct proc_dir_entry *sn_procfs_create_entry(
+	const char *name, struct proc_dir_entry *parent,
+	int (*openfunc)(struct inode *, struct file *),
+	int (*releasefunc)(struct inode *, struct file *))
+{
+	struct proc_dir_entry *e = create_proc_entry(name, 0444, parent);
+
+	if (e) {
+		e->proc_fops = (struct file_operations *)kmalloc(
+			sizeof(struct file_operations), GFP_KERNEL);
+		if (e->proc_fops) {
+			memset(e->proc_fops, 0, sizeof(struct file_operations));
+			e->proc_fops->open = openfunc;
+			e->proc_fops->read = seq_read;
+			e->proc_fops->llseek = seq_lseek;
+			e->proc_fops->release = releasefunc;
+		}
 	}
+
+	return e;
 }
 
-void
-register_sn_procfs(void) {
-	register_sn_partition_id();
-	register_sn_serial_numbers();
-	register_sn_force_interrupt();
+/* /proc/sgi_sn/sn_topology uses seq_file, see sn_hwperf.c */
+extern int sn_topology_open(struct inode *, struct file *);
+extern int sn_topology_release(struct inode *, struct file *);
+
+void register_sn_procfs(void)
+{
+	static struct proc_dir_entry *sgi_proc_dir = NULL;
+	struct proc_dir_entry *e;
+
+	BUG_ON(sgi_proc_dir != NULL);
+	if (!(sgi_proc_dir = proc_mkdir("sgi_sn", 0)))
+		return;
+
+	sn_procfs_create_entry("partition_id", sgi_proc_dir,
+		partition_id_open, single_release);
+
+	sn_procfs_create_entry("system_serial_number", sgi_proc_dir,
+		system_serial_number_open, single_release);
+
+	sn_procfs_create_entry("licenseID", sgi_proc_dir, 
+		licenseID_open, single_release);
+
+	e = sn_procfs_create_entry("sn_force_interrupt", sgi_proc_dir, 
+		sn_force_interrupt_open, single_release);
+	if (e) 
+		e->proc_fops->write = sn_force_interrupt_write_proc;
+
+	sn_procfs_create_entry("coherence_id", sgi_proc_dir, 
+		coherence_id_open, single_release);
+	
+	sn_procfs_create_entry("sn_topology", sgi_proc_dir,
+		sn_topology_open, sn_topology_release);
 }
 
 #endif /* CONFIG_PROC_FS */
diff --git a/arch/ia64/sn/kernel/sn2/timer.c b/arch/ia64/sn/kernel/sn2/timer.c
index 57844feea..85f7d215a 100644
--- a/arch/ia64/sn/kernel/sn2/timer.c
+++ b/arch/ia64/sn/kernel/sn2/timer.c
@@ -20,57 +20,16 @@
 
 
 extern unsigned long sn_rtc_cycles_per_second;
-static volatile unsigned long last_wall_rtc;
 
-static unsigned long rtc_offset;	/* updated only when xtime write-lock is held! */
-static long rtc_nsecs_per_cycle;
-static long rtc_per_timer_tick;
-
-static unsigned long
-getoffset(void)
-{
-	return rtc_offset + (GET_RTC_COUNTER() - last_wall_rtc)*rtc_nsecs_per_cycle;
-}
-
-
-static void
-update(long delta_nsec)
-{
-	unsigned long rtc_counter = GET_RTC_COUNTER();
-	unsigned long offset = rtc_offset + (rtc_counter - last_wall_rtc)*rtc_nsecs_per_cycle;
-
-	/* Be careful about signed/unsigned comparisons here: */
-	if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)
-		rtc_offset = offset - delta_nsec;
-	else
-		rtc_offset = 0;
-	last_wall_rtc = rtc_counter;
-}
-
-
-static void
-reset(void)
-{
-	rtc_offset = 0;
-	last_wall_rtc = GET_RTC_COUNTER();
-}
-
-
-static struct time_interpolator sn2_interpolator = {
-	.get_offset =	getoffset,
-	.update =	update,
-	.reset =	reset
-};
+static struct time_interpolator sn2_interpolator;
 
 void __init
 sn_timer_init(void)
 {
 	sn2_interpolator.frequency = sn_rtc_cycles_per_second;
 	sn2_interpolator.drift = -1;	/* unknown */
+	sn2_interpolator.shift = 10;	/* RTC is 54 bits maximum shift is 10 */
+	sn2_interpolator.addr = RTC_COUNTER_ADDR;
+	sn2_interpolator.source = TIME_SOURCE_MMIO64;
 	register_time_interpolator(&sn2_interpolator);
-
-	rtc_per_timer_tick = sn_rtc_cycles_per_second / HZ;
-	rtc_nsecs_per_cycle = 1000000000 / sn_rtc_cycles_per_second;
-
-	last_wall_rtc = GET_RTC_COUNTER();
 }
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 35ea6886f..fc2c3d0cb 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -21,12 +21,10 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
 	bool
 
-
 mainmenu "Linux/68k Kernel Configuration"
 
 source "init/Kconfig"
 
-
 menu "Platform dependent setup"
 
 config EISA
@@ -355,7 +353,6 @@ config 060_WRITETHROUGH
 
 endmenu
 
-
 menu "General setup"
 
 source "fs/Kconfig.binfmt"
@@ -447,7 +444,6 @@ endmenu
 
 source "drivers/Kconfig"
 
-
 menu "Character devices"
 
 config ATARI_MFPSER
@@ -652,43 +648,7 @@ endmenu
 
 source "fs/Kconfig"
 
-menu "Kernel hacking"
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-
-config DEBUG_BUGVERBOSE
-	bool "Verbose BUG() reporting"
-	depends on DEBUG_KERNEL
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  If you don't debug the kernel, you can say N.
-
-endmenu
+source "arch/m68k/Kconfig.debug"
 
 source "kernel/vserver/Kconfig"
 
@@ -697,4 +657,3 @@ source "security/Kconfig"
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
index bc79771e8..59c25bc9d 100644
--- a/arch/m68k/Makefile
+++ b/arch/m68k/Makefile
@@ -28,7 +28,7 @@ ifdef CONFIG_SUN3
 LDFLAGS_vmlinux = -N
 endif
 
-CHECK := $(CHECK) -D__mc68000__=1 -I$(shell $(CC) -print-file-name=include)
+CHECKFLAGS += -D__mc68000__ -I$(shell $(CC) -print-file-name=include)
 
 # without -fno-strength-reduce the 53c7xx.c driver fails ;-(
 CFLAGS += -pipe -fno-strength-reduce -ffixed-a2
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
index 081a6747c..458925c47 100644
--- a/arch/m68k/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile
@@ -7,7 +7,7 @@ ifndef CONFIG_SUN3
 else
   extra-y := sun3-head.o
 endif
-extra-y	+= vmlinux.lds.s
+extra-y	+= vmlinux.lds
 
 obj-y		:= entry.o process.o traps.o ints.o signal.o ptrace.o \
 			sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o
diff --git a/arch/m68k/kernel/bios32.c b/arch/m68k/kernel/bios32.c
index be2f7e616..738531ca2 100644
--- a/arch/m68k/kernel/bios32.c
+++ b/arch/m68k/kernel/bios32.c
@@ -77,11 +77,6 @@ static int disable_pci_burst;		/* If set do not allow PCI bursts. */
 static unsigned int io_base;
 static unsigned int mem_base;
 
-struct pci_fixup pcibios_fixups[] =
-{
-	{ 0 }
-};
-
 /*
  * static void disable_dev(struct pci_dev *dev)
  *
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
index b069b0c84..fe837e31a 100644
--- a/arch/m68k/kernel/m68k_ksyms.c
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -16,7 +16,6 @@
 #include <asm/io.h>
 #include <asm/semaphore.h>
 #include <asm/checksum.h>
-#include <asm/hardirq.h>
 
 asmlinkage long long __ashldi3 (long long, int);
 asmlinkage long long __ashrdi3 (long long, int);
@@ -72,18 +71,18 @@ EXPORT_SYMBOL(vme_brdtype);
    explicitly (the C compiler generates them).  Fortunately,
    their interface isn't gonna change any time soon now, so
    it's OK to leave it out of version control.  */
-EXPORT_SYMBOL_NOVERS(__ashldi3);
-EXPORT_SYMBOL_NOVERS(__ashrdi3);
-EXPORT_SYMBOL_NOVERS(__lshrdi3);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memcmp);
-EXPORT_SYMBOL_NOVERS(memscan);
-EXPORT_SYMBOL_NOVERS(__muldi3);
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(__muldi3);
 
-EXPORT_SYMBOL_NOVERS(__down_failed);
-EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
-EXPORT_SYMBOL_NOVERS(__down_failed_trylock);
-EXPORT_SYMBOL_NOVERS(__up_wakeup);
+EXPORT_SYMBOL(__down_failed);
+EXPORT_SYMBOL(__down_failed_interruptible);
+EXPORT_SYMBOL(__down_failed_trylock);
+EXPORT_SYMBOL(__up_wakeup);
 
 EXPORT_SYMBOL(get_wchan);
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index b426ab55a..93b043e2a 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -232,7 +232,7 @@ asmlinkage int m68k_clone(struct pt_regs *regs)
 	child_tidptr = (int *)regs->d4;
 	if (!newsp)
 		newsp = rdusp();
-	return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0,
+	return do_fork(clone_flags, newsp, regs, 0,
 		       parent_tidptr, child_tidptr);
 }
 
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c
index 0f0b28d34..0e0c31fd5 100644
--- a/arch/m68k/kernel/ptrace.c
+++ b/arch/m68k/kernel/ptrace.c
@@ -381,11 +381,8 @@ asmlinkage void syscall_trace(void)
 	if (!current->thread.work.delayed_trace &&
 	    !current->thread.work.syscall_trace)
 		return;
-	current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-					? 0x80 : 0);
-	current->state = TASK_STOPPED;
-	notify_parent(current, SIGCHLD);
-	schedule();
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+				 ? 0x80 : 0));
 	/*
 	 * this isn't the same as continuing with a signal, but it will do
 	 * for normal use.  strace only continues with a signal if the
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index c37c4dbb8..4a319bdef 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -842,9 +842,7 @@ adjust_stack:
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 	goto adjust_stack;
 }
 
@@ -925,9 +923,7 @@ adjust_stack:
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 	goto adjust_stack;
 }
 
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
index d85616f14..11d122980 100644
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -38,24 +38,6 @@ static inline int set_rtc_mmss(unsigned long nowtime)
   return -1;
 }
 
-static inline void do_profile (unsigned long pc)
-{
-	if (prof_buffer && current->pid) {
-		extern int _stext;
-		pc -= (unsigned long) &_stext;
-		pc >>= prof_shift;
-		if (pc < prof_len)
-			++prof_buffer[pc];
-		else
-		/*
-		 * Don't ignore out-of-bounds PC values silently,
-		 * put them into the last histogram slot, so if
-		 * present, they will show up as a sharp peak.
-		 */
-			++prof_buffer[prof_len-1];
-	}
-}
-
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
@@ -63,9 +45,7 @@ static inline void do_profile (unsigned long pc)
 static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
 {
 	do_timer(regs);
-
-	if (!user_mode(regs))
-		do_profile(regs->pc);
+	profile_tick(CPU_PROFILING, regs);
 
 #ifdef CONFIG_HEARTBEAT
 	/* use power LED as a heartbeat instead -- much more useful
diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds
index b0a5cd53d..42aeea9fc 100644
--- a/arch/m68k/kernel/vmlinux-std.lds
+++ b/arch/m68k/kernel/vmlinux-std.lds
@@ -51,9 +51,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : {
 	*(.initcall1.init)
diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds
index 12931b324..7a18ed062 100644
--- a/arch/m68k/kernel/vmlinux-sun3.lds
+++ b/arch/m68k/kernel/vmlinux-sun3.lds
@@ -45,9 +45,6 @@ __init_begin = .;
 	__setup_start = .;
 	.init.setup : { *(.init.setup) }
 	__setup_end = .;
-	__start___param = .;
-	__param : { *(__param) }
-	__stop___param = .;
 	__initcall_start = .;
 	.initcall.init : {
 		*(.initcall1.init)
diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c
index 541897351..1215b5bea 100644
--- a/arch/m68k/q40/q40ints.c
+++ b/arch/m68k/q40/q40ints.c
@@ -19,12 +19,12 @@
 #include <linux/sched.h>
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
+#include <linux/hardirq.h>
 
 #include <asm/rtc.h>
 #include <asm/ptrace.h>
 #include <asm/system.h>
 #include <asm/irq.h>
-#include <asm/hardirq.h>
 #include <asm/traps.h>
 
 #include <asm/q40_master.h>
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index b8f71e760..90cd4079b 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -5,6 +5,10 @@
 
 mainmenu "uClinux/68k (w/o MMU) Kernel Configuration"
 
+config M68KNOMMU
+	bool
+	default y
+
 config MMU
 	bool
 	default n
@@ -25,7 +29,6 @@ config RWSEM_XCHGADD_ALGORITHM
 	bool
 	default n
 
-
 source "init/Kconfig"
 
 menu "Processor type and features"
@@ -388,7 +391,7 @@ config LARGE_ALLOCS
 	  a lot of RAM, and you need to able to allocate very large
 	  contiguous chunks. If unsure, say N.
 
-choice 
+choice
 	prompt "RAM size"
 	default AUTO
 
@@ -421,7 +424,7 @@ config RAM32MB
 
 endchoice
 
-choice 
+choice
 	prompt "RAM bus width"
 	default RAMAUTOBIT
 
@@ -472,7 +475,6 @@ endchoice
 
 endmenu
 
-
 menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
 
 config PCI
@@ -511,60 +513,7 @@ source "drivers/Kconfig"
 
 source "fs/Kconfig"
 
-menu "Kernel hacking"
-
-config FULLDEBUG
-	bool "Full Symbolic/Source Debugging support"
-	help
-	  Enable debuging symbols on kernel build.
-
-config FRAME_POINTER
-	bool "Compile the kernel with frame pointers"
-	help
-	  If you say Y here the resulting kernel image will be slightly larger
-	  and slower, but 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 pointers.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	help
-	  Enables console device to interpret special characters as
-	  commands to dump state information.
-
-config HIGHPROFILE
-	bool "Use fast second timer for profiling"
-	depends on COLDFIRE
-	help
-	  Use a fast secondary clock to produce profiling information.
-
-config BOOTPARAM
-	bool 'Compiled-in Kernel Boot Parameter'
-
-config BOOTPARAM_STRING 
-	string 'Kernel Boot Parameter'
-	default 'console=ttyS0,19200'
-	depends on BOOTPARAM
-
-config DUMPTOFLASH
-	bool "Panic/Dump to FLASH"
-	depends on COLDFIRE
-	help
-	  Dump any panic of trap output into a flash memory segment
-	  for later analysis.
-
-config NO_KERNEL_MSG
-	bool "Suppress Kernel BUG Messages"
-	help
-	  Do not output any debug BUG messages within the kernel.
-
-config BDM_DISABLE
-	bool "Disable BDM signals"
-	depends on (EXPERIMENTAL && COLDFIRE)
-	help
-	  Disable the ColdFire CPU's BDM signals.
-
-endmenu
+source "arch/m68knommu/Kconfig.debug"
 
 source "kernel/vserver/Kconfig"
 
@@ -573,4 +522,3 @@ source "security/Kconfig"
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff --git a/arch/m68knommu/kernel/Makefile b/arch/m68knommu/kernel/Makefile
index 1a6a3600e..1c6cd1ab5 100644
--- a/arch/m68knommu/kernel/Makefile
+++ b/arch/m68knommu/kernel/Makefile
@@ -2,7 +2,7 @@
 # Makefile for arch/m68knommu/kernel.
 #
 
-extra-y := vmlinux.lds.s
+extra-y := vmlinux.lds
 
 obj-y += dma.o entry.o init_task.o m68k_ksyms.o process.o ptrace.o semaphore.o \
 	 setup.o signal.o syscalltable.o sys_m68k.o time.o traps.o
diff --git a/arch/m68knommu/kernel/asm-offsets.c b/arch/m68knommu/kernel/asm-offsets.c
index c803fe64e..02c56f538 100644
--- a/arch/m68knommu/kernel/asm-offsets.c
+++ b/arch/m68knommu/kernel/asm-offsets.c
@@ -12,9 +12,9 @@
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <linux/ptrace.h>
+#include <linux/hardirq.h>
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
-#include <asm/hardirq.h>
 
 #define DEFINE(sym, val) \
         asm volatile("\n->" #sym " %0 " #val : : "i" (val))
diff --git a/arch/m68knommu/kernel/comempci.c b/arch/m68knommu/kernel/comempci.c
index ce5dafa69..8670938f1 100644
--- a/arch/m68knommu/kernel/comempci.c
+++ b/arch/m68knommu/kernel/comempci.c
@@ -351,8 +351,6 @@ char *pcibios_setup(char *option)
 }
 /*****************************************************************************/
 
-struct pci_fixup pcibios_fixups[] = { { 0 } };
-
 void pcibios_fixup_bus(struct pci_bus *b)
 {
 }
diff --git a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68knommu/kernel/m68k_ksyms.c
index 33e084146..e93a5ad56 100644
--- a/arch/m68knommu/kernel/m68k_ksyms.c
+++ b/arch/m68knommu/kernel/m68k_ksyms.c
@@ -16,7 +16,6 @@
 #include <asm/io.h>
 #include <asm/semaphore.h>
 #include <asm/checksum.h>
-#include <asm/hardirq.h>
 #include <asm/current.h>
 
 extern void dump_thread(struct pt_regs *, struct user *);
@@ -50,16 +49,16 @@ EXPORT_SYMBOL(csum_partial_copy);
    explicitly (the C compiler generates them).  Fortunately,
    their interface isn't gonna change any time soon now, so
    it's OK to leave it out of version control.  */
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memcmp);
-EXPORT_SYMBOL_NOVERS(memscan);
-EXPORT_SYMBOL_NOVERS(memmove);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(memmove);
 
-EXPORT_SYMBOL_NOVERS(__down_failed);
-EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
-EXPORT_SYMBOL_NOVERS(__down_failed_trylock);
-EXPORT_SYMBOL_NOVERS(__up_wakeup);
+EXPORT_SYMBOL(__down_failed);
+EXPORT_SYMBOL(__down_failed_interruptible);
+EXPORT_SYMBOL(__down_failed_trylock);
+EXPORT_SYMBOL(__up_wakeup);
 
 EXPORT_SYMBOL(get_wchan);
 
@@ -79,27 +78,27 @@ extern void __udivsi3(void);
 extern void __umodsi3(void);
 
         /* gcc lib functions */
-EXPORT_SYMBOL_NOVERS(__ashldi3);
-EXPORT_SYMBOL_NOVERS(__ashrdi3);
-EXPORT_SYMBOL_NOVERS(__divsi3);
-EXPORT_SYMBOL_NOVERS(__lshrdi3);
-EXPORT_SYMBOL_NOVERS(__modsi3);
-EXPORT_SYMBOL_NOVERS(__muldi3);
-EXPORT_SYMBOL_NOVERS(__mulsi3);
-EXPORT_SYMBOL_NOVERS(__udivsi3);
-EXPORT_SYMBOL_NOVERS(__umodsi3);
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__divsi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__modsi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__mulsi3);
+EXPORT_SYMBOL(__udivsi3);
+EXPORT_SYMBOL(__umodsi3);
 
-EXPORT_SYMBOL_NOVERS(is_in_rom);
+EXPORT_SYMBOL(is_in_rom);
 
 #ifdef CONFIG_COLDFIRE
 extern unsigned int *dma_device_address;
 extern unsigned long dma_base_addr, _ramend;
-EXPORT_SYMBOL_NOVERS(dma_base_addr);
-EXPORT_SYMBOL_NOVERS(dma_device_address);
-EXPORT_SYMBOL_NOVERS(_ramend);
+EXPORT_SYMBOL(dma_base_addr);
+EXPORT_SYMBOL(dma_device_address);
+EXPORT_SYMBOL(_ramend);
 
 extern asmlinkage void trap(void);
 extern void	*_ramvec;
-EXPORT_SYMBOL_NOVERS(trap);
-EXPORT_SYMBOL_NOVERS(_ramvec);
+EXPORT_SYMBOL(trap);
+EXPORT_SYMBOL(_ramvec);
 #endif /* CONFIG_COLDFIRE */
diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c
index 581eef2b7..b0901d817 100644
--- a/arch/m68knommu/kernel/process.c
+++ b/arch/m68knommu/kernel/process.c
@@ -188,7 +188,7 @@ asmlinkage int m68k_clone(struct pt_regs *regs)
 	newsp = regs->d2;
 	if (!newsp)
 		newsp = rdusp();
-        return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL);
+        return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
 }
 
 int copy_thread(int nr, unsigned long clone_flags,
diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c
index 0c57f873a..9276a052c 100644
--- a/arch/m68knommu/kernel/ptrace.c
+++ b/arch/m68knommu/kernel/ptrace.c
@@ -135,13 +135,6 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 		ret = ptrace_attach(child);
 		goto out_tsk;
 	}
-	ret = -ESRCH;
-	if (!(child->ptrace & PT_PTRACED))
-		goto out_tsk;
-	if (child->state != TASK_STOPPED) {
-		if (request != PTRACE_KILL)
-			goto out_tsk;
-	}
 	ret = ptrace_check_attach(child, request == PTRACE_KILL);
 	if (ret < 0)
 		goto out_tsk;
@@ -378,10 +371,8 @@ asmlinkage void syscall_trace(void)
 		return;
 	if (!(current->ptrace & PT_PTRACED))
 		return;
-	current->exit_code = SIGTRAP;
-	current->state = TASK_STOPPED;
-	notify_parent(current, SIGCHLD);
-	schedule();
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+				 ? 0x80 : 0));
 	/*
 	 * this isn't the same as continuing with a signal, but it will do
 	 * for normal use.  strace only continues with a signal if the
diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c
index 3fb0d78f4..0d5891567 100644
--- a/arch/m68knommu/kernel/signal.c
+++ b/arch/m68knommu/kernel/signal.c
@@ -616,9 +616,7 @@ adjust_stack:
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 	goto adjust_stack;
 }
 
@@ -685,9 +683,7 @@ adjust_stack:
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 	goto adjust_stack;
 }
 
diff --git a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c
index 74308a533..e328f2810 100644
--- a/arch/m68knommu/kernel/time.c
+++ b/arch/m68knommu/kernel/time.c
@@ -41,24 +41,6 @@ static inline int set_rtc_mmss(unsigned long nowtime)
 	return -1;
 }
 
-static inline void do_profile (unsigned long pc)
-{
-	if (prof_buffer && current->pid) {
-		extern int _stext;
-		pc -= (unsigned long) &_stext;
-		pc >>= prof_shift;
-		if (pc < prof_len)
-			++prof_buffer[pc];
-		else
-		/*
-		 * Don't ignore out-of-bounds PC values silently,
-		 * put them into the last histogram slot, so if
-		 * present, they will show up as a sharp peak.
-		 */
-			++prof_buffer[prof_len-1];
-	}
-}
-
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
@@ -75,9 +57,8 @@ static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs)
 	write_seqlock(&xtime_lock);
 
 	do_timer(regs);
-
-	if (!user_mode(regs))
-		do_profile(regs->pc);
+	if (current->pid)
+		profile_tick(CPU_PROFILING, regs);
 
 	/*
 	 * If we have an externally synchronized Linux clock, then update
diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S
index 4d8f716d7..87f3bc407 100644
--- a/arch/m68knommu/kernel/vmlinux.lds.S
+++ b/arch/m68knommu/kernel/vmlinux.lds.S
@@ -284,9 +284,6 @@ SECTIONS {
 		__setup_start = .;
 		*(.init.setup)
 		__setup_end = .;
-		__start___param = .;
-		*(__param)
-		__stop___param = .;
 		__initcall_start = .;
 		*(.initcall1.init)
 		*(.initcall2.init)
diff --git a/arch/m68knommu/platform/5307/timers.c b/arch/m68knommu/platform/5307/timers.c
index 99c7d9935..ef49596aa 100644
--- a/arch/m68knommu/platform/5307/timers.c
+++ b/arch/m68knommu/platform/5307/timers.c
@@ -110,17 +110,8 @@ void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs)
 {
 	/* Reset ColdFire timer2 */
 	mcf_proftp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
-
-        if (!user_mode(regs)) {
-                if (prof_buffer && current->pid) {
-                        extern int _stext;
-                        unsigned long ip = instruction_pointer(regs);
-                        ip -= (unsigned long) &_stext;
-                        ip >>= prof_shift;
-                        if (ip < prof_len)
-                                prof_buffer[ip]++;
-                }
-        }
+	if (current->pid)
+		profile_tick(CPU_PROFILING, regs);
 }
 
 /***************************************************************************/
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 6c1c24b69..03562f510 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -381,7 +381,7 @@ config DDB5476
 	  evaluation board.
 
 	  Features : kernel debugging, serial terminal, NFS root fs, on-board
-	  ether port USB, AC97, PCI, PCI VGA card & framebuffer console, 
+	  ether port USB, AC97, PCI, PCI VGA card & framebuffer console,
 	  IDE controller, PS2 keyboard, PS2 mouse, etc.
 
 config DDB5477
@@ -400,7 +400,7 @@ config DDB5477_BUS_FREQUENCY
 	int "bus frequency (in kHZ, 0 for auto-detect)"
 	depends on DDB5477
 	default 0
-	
+
 config NEC_OSPREY
 	bool "Support for NEC Osprey board"
 	select DMA_NONCOHERENT
@@ -513,15 +513,15 @@ config SOC_AU1550
 
 endchoice
 
-choice  
+choice
         prompt "AMD/Alchemy Au1x00 board support"
         depends on SOC_AU1X00
 	help
 	  These are evaluation boards built by AMD/Alchemy to
 	  showcase their Au1X00 Internet Edge Processors. The SOC design
-	  is based on the MIPS32 architecture running at 266/400/500MHz 
-          with many integrated peripherals. Further information can be 
-          found at their website, <http://www.amd.com/>. Say Y here if you 
+	  is based on the MIPS32 architecture running at 266/400/500MHz
+          with many integrated peripherals. Further information can be
+          found at their website, <http://www.amd.com/>. Say Y here if you
           wish to build a kernel for this platform.
 
 config MIPS_PB1000
@@ -1091,7 +1091,6 @@ config TANBAC_TB0219
 
 endmenu
 
-
 menu "CPU selection"
 
 choice
@@ -1194,7 +1193,7 @@ config PAGE_SIZE_4KB
 	 This option select the standard 4kB Linux page size.  On some
 	 R3000-family processors this is the only available page size.  Using
 	 4kB page size will minimize memory consumption and is therefore
-	 recommended for low memory systems. 
+	 recommended for low memory systems.
 
 config PAGE_SIZE_8KB
 	bool "8kB"
@@ -1382,21 +1381,6 @@ config PREEMPT
 	  This allows applications to run more reliably even when the system is
 	  under load.
 
-config DEBUG_SPINLOCK
-	bool "Spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here and build SMP to catch missing spinlock initialization
-	  and certain other kinds of spinlock errors commonly made.  This is
-	  best used in conjunction with the NMI watchdog so that spinlock
-	  deadlocks are also debuggable.
-
-config DEBUG_SPINLOCK_SLEEP
-	bool "Sleep-inside-spinlock checking"
-	help
-	  If you say Y here, various routines which may sleep will become very
-	  noisy if they are called with a spinlock held.
-
 config RTC_DS1742
 	bool "DS1742 BRAM/RTC support"
 	depends on TOSHIBA_JMR3927 || TOSHIBA_RBTX4927
@@ -1562,7 +1546,7 @@ config EMBEDDED_RAMDISK_IMAGE
 	default "ramdisk.gz"
 	help
 	  This is the filename of the ramdisk image to be built into the
-	  kernel.  Relative pathnames are relative to arch/mips/ramdisk/.  
+	  kernel.  Relative pathnames are relative to arch/mips/ramdisk/.
 	  The ramdisk image is not part of the kernel distribution; you must
 	  provide one yourself.
 
@@ -1572,119 +1556,7 @@ source "drivers/Kconfig"
 
 source "fs/Kconfig"
 
-menu "Kernel hacking"
-
-config CROSSCOMPILE
-	bool "Are you using a crosscompiler"
-	help
-	  Say Y here if you are compiling the kernel on a different
-	  architecture than the one it is intended to run on.
-
-config CMDLINE
-	string "Default kernel command string"
-	default ""
-	help
-          On some platforms, there is currently no way for the boot loader to
-          pass arguments to the kernel. For these platforms, you can supply
-          some command-line options at build time by entering them here.  In
-          other cases you can specify kernel args so that you don't have
-	  to set them up in board prom initialization routines.
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-
-config DEBUG_STACK_USAGE
-	bool "Enable stack utilization instrumentation"
-	depends on DEBUG_KERNEL
-	help
-	  Enables the display of the minimum amount of free stack which each
-	  task has ever had available in the sysrq-T and sysrq-P debug output.
-
-	  This option will slow down process creation somewhat.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config KGDB
-	bool "Remote GDB kernel debugging"
-	depends on DEBUG_KERNEL
-	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 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 DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  If you don't debug the kernel, you can say N.
-
-config SB1XXX_CORELIS
-	bool "Corelis Debugger"
-	depends on SIBYTE_SB1xxx_SOC
-	select DEBUG_INFO
-	help
-	  Select compile flags that produce code that can be processed by the
-	  Corelis mksym utility and UDB Emulator.
-
-config RUNTIME_DEBUG
-	bool "Enable run-time debugging"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, some debugging macros will do run-time checking.
-	  If you say N here, those macros will mostly turn to no-ops.  See 
-	  include/asm-mips/debug.h for debuging macros.
-	  If unsure, say N.
-
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config MIPS_UNCACHED
-	bool "Run uncached"
-	depends on DEBUG_KERNEL && !SMP && !SGI_IP27
-	help
-	  If you say Y here there kernel will disable all CPU caches.  This will
-	  reduce the system's performance dramatically but can help finding
-	  otherwise hard to track bugs.  It can also useful if you're doing
-	  hardware debugging with a logic analyzer and need to see all traffic
-	  on the bus.
-
-config DEBUG_HIGHMEM
-	bool "Highmem debugging"
-	depends on DEBUG_KERNEL && HIGHMEM
-
-endmenu
+source "arch/mips/Kconfig.debug"
 
 source "kernel/vserver/Kconfig"
 
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 371558708..5025c01b9 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -56,14 +56,12 @@ endif
 #
 cflags-y			:= -I $(TOPDIR)/include/asm/gcc
 cflags-y			+= -G 0 -mno-abicalls -fno-pic -pipe
-cflags-y			+= $(call check_gcc, -finline-limit=100000,)
+cflags-y			+= $(call cc-option, -finline-limit=100000)
 LDFLAGS_vmlinux			+= -G 0 -static -n
 MODFLAGS			+= -mlong-calls
 
 cflags-$(CONFIG_SB1XXX_CORELIS)	+= -mno-sched-prolog -fno-omit-frame-pointer
 
-check_warning = $(shell if $(CC) $(1) -c -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi)
-
 #
 # Use: $(call set_gccflags,<cpu0>,<isa0>,<cpu1>,<isa1>,<isa2>)
 #
@@ -162,7 +160,7 @@ cflags-$(CONFIG_CPU_R5432)	+= \
 cflags-$(CONFIG_CPU_NEVADA)	+= \
 			$(call set_gccflags,rm5200,mips4,r5000,mips4,mips2) \
 			-Wa,--trap
-#			$(call check_gcc,-mmad,)
+#			$(call cc-option,-mmad)
 
 cflags-$(CONFIG_CPU_RM7000)	+= \
 			$(call set_gccflags,rm7000,mips4,r5000,mips4,mips2) \
@@ -643,7 +641,7 @@ endif
 # none has been choosen above.
 #
 
-AFLAGS_vmlinux.lds.o := \
+CPPFLAGS_vmlinux.lds := \
 	-D"LOADADDR=$(load-y)" \
 	-D"JIFFIES=$(JIFFIES)" \
 	-imacros $(srctree)/include/asm-$(ARCH)/sn/mapped_kernel.h
diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c
index f58f454cd..a72de9727 100644
--- a/arch/mips/au1000/common/time.c
+++ b/arch/mips/au1000/common/time.c
@@ -38,11 +38,11 @@
 #include <linux/kernel_stat.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
+#include <linux/hardirq.h>
 
 #include <asm/mipsregs.h>
 #include <asm/ptrace.h>
 #include <asm/time.h>
-#include <asm/hardirq.h>
 #include <asm/div64.h>
 #include <asm/mach-au1x00/au1000.h>
 
diff --git a/arch/mips/baget/irq.c b/arch/mips/baget/irq.c
index d2067c037..3dcc16efd 100644
--- a/arch/mips/baget/irq.c
+++ b/arch/mips/baget/irq.c
@@ -180,7 +180,7 @@ skip:
 static void do_IRQ(int irq, struct pt_regs * regs)
 {
 	struct irqaction *action;
-	int do_random, cpu;
+	int ret, do_random, cpu;
 
 	cpu = smp_processor_id();
 	irq_enter();
@@ -194,8 +194,9 @@ static void do_IRQ(int irq, struct pt_regs * regs)
 		action = *(irq + irq_action);
 		do_random = 0;
         	do {
-			do_random |= action->flags;
-			action->handler(irq, action->dev_id, regs);
+			ret = action->handler(irq, action->dev_id, regs);
+			if (ret == IRQ_HANDLED)
+				do_random |= action->flags;
 			action = action->next;
         	} while (action);
 		if (do_random & SA_SAMPLE_RANDOM)
diff --git a/arch/mips/configs/jaguar-atx_defconfig b/arch/mips/configs/jaguar-atx_defconfig
index b6f70da71..141dc6da4 100644
--- a/arch/mips/configs/jaguar-atx_defconfig
+++ b/arch/mips/configs/jaguar-atx_defconfig
@@ -306,10 +306,10 @@ CONFIG_EEPRO100=y
 # CONFIG_R8169 is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
-CONFIG_MV64340_ETH=y
-CONFIG_MV64340_ETH_0=y
-CONFIG_MV64340_ETH_1=y
-CONFIG_MV64340_ETH_2=y
+CONFIG_MV643XX_ETH=y
+CONFIG_MV643XX_ETH_0=y
+CONFIG_MV643XX_ETH_1=y
+CONFIG_MV643XX_ETH_2=y
 
 #
 # Ethernet (10000 Mbit)
diff --git a/arch/mips/configs/ocelot_c_defconfig b/arch/mips/configs/ocelot_c_defconfig
index 3eafe9ae7..c7eb418e3 100644
--- a/arch/mips/configs/ocelot_c_defconfig
+++ b/arch/mips/configs/ocelot_c_defconfig
@@ -303,7 +303,7 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_R8169 is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
-# CONFIG_MV64340_ETH is not set
+# CONFIG_MV643XX_ETH is not set
 
 #
 # Ethernet (10000 Mbit)
diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig
index d942862ad..9933eede8 100644
--- a/arch/mips/configs/tb0226_defconfig
+++ b/arch/mips/configs/tb0226_defconfig
@@ -272,7 +272,6 @@ CONFIG_IP_ADVANCED_ROUTER=y
 CONFIG_IP_MULTIPLE_TABLES=y
 CONFIG_IP_ROUTE_NAT=y
 CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_TOS=y
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_DHCP is not set
diff --git a/arch/mips/configs/tb0229_defconfig b/arch/mips/configs/tb0229_defconfig
index cd08e3c03..5be7f568f 100644
--- a/arch/mips/configs/tb0229_defconfig
+++ b/arch/mips/configs/tb0229_defconfig
@@ -229,7 +229,6 @@ CONFIG_IP_ADVANCED_ROUTER=y
 CONFIG_IP_MULTIPLE_TABLES=y
 CONFIG_IP_ROUTE_NAT=y
 CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_TOS=y
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_DHCP is not set
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 3fd457737..86783790d 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the Linux/MIPS kernel.
 #
 
-extra-y		:= head.o init_task.o vmlinux.lds.s
+extra-y		:= head.o init_task.o vmlinux.lds
 
 obj-y		+= cpu-probe.o branch.o entry.o genex.o irq.o process.o \
 		   ptrace.o reset.o semaphore.o setup.o signal.o syscall.o \
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
index b15f3b0de..15ae6af5a 100644
--- a/arch/mips/kernel/irixsig.c
+++ b/arch/mips/kernel/irixsig.c
@@ -121,9 +121,7 @@ static void setup_irix_frame(struct k_sigaction *ka, struct pt_regs *regs,
 	return;
 
 segv_and_exit:
-	if (signr == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(signr, current);
 }
 
 static void inline
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 13acf876b..7c1dae720 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -144,14 +144,16 @@ inline void synchronize_irq(unsigned int irq)
 int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
 {
 	int status = 1;	/* Force the "do bottom halves" bit */
-	int retval = 0;
+	int ret, retval = 0;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
-		status |= action->flags;
-		retval |= action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
+		retval |= ret;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
@@ -872,30 +874,6 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer,
 
 #endif
 
-static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
-	if (count - len < 2)
-		return -EINVAL;
-	len += sprintf(page + len, "\n");
-	return len;
-}
-
-static int prof_cpu_mask_write_proc (struct file *file, const char *buffer,
-					unsigned long count, void *data)
-{
-	cpumask_t *mask = (cpumask_t *)data, new_value;
-	unsigned long full_count = count, err;
-
-	err = cpumask_parse(buffer, count, new_value);
-	if (err)
-		return err;
-
-	*mask = new_value;
-	return full_count;
-}
-
 #define MAX_NAMELEN 10
 
 static void register_irq_proc (unsigned int irq)
@@ -931,26 +909,15 @@ static void register_irq_proc (unsigned int irq)
 #endif
 }
 
-unsigned long prof_cpu_mask = -1;
-
 void init_irq_proc (void)
 {
-	struct proc_dir_entry *entry;
 	int i;
 
 	/* create /proc/irq */
 	root_irq_dir = proc_mkdir("irq", 0);
 
 	/* create /proc/irq/prof_cpu_mask */
-	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
-
-	if (!entry)
-	    return;
-
-	entry->nlink = 1;
-	entry->data = (void *)&prof_cpu_mask;
-	entry->read_proc = prof_cpu_mask_read_proc;
-	entry->write_proc = prof_cpu_mask_write_proc;
+	create_prof_cpu_mask(root_irq_dir);
 
 	/*
 	 * Create entries for all existing IRQs.
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
index 2b2265ada..169393cc9 100644
--- a/arch/mips/kernel/mips_ksyms.c
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -26,36 +26,36 @@ extern long __strnlen_user_asm(const char *s);
 /*
  * String functions
  */
-EXPORT_SYMBOL_NOVERS(memchr);
-EXPORT_SYMBOL_NOVERS(memcmp);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memmove);
-EXPORT_SYMBOL_NOVERS(strcat);
-EXPORT_SYMBOL_NOVERS(strchr);
+EXPORT_SYMBOL(memchr);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strchr);
 #ifdef CONFIG_MIPS64
-EXPORT_SYMBOL_NOVERS(strncmp);
+EXPORT_SYMBOL(strncmp);
 #endif
-EXPORT_SYMBOL_NOVERS(strlen);
-EXPORT_SYMBOL_NOVERS(strpbrk);
-EXPORT_SYMBOL_NOVERS(strncat);
-EXPORT_SYMBOL_NOVERS(strnlen);
-EXPORT_SYMBOL_NOVERS(strrchr);
-EXPORT_SYMBOL_NOVERS(strstr);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strpbrk);
+EXPORT_SYMBOL(strncat);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strrchr);
+EXPORT_SYMBOL(strstr);
 
 EXPORT_SYMBOL(kernel_thread);
 
 /*
  * Userspace access stuff.
  */
-EXPORT_SYMBOL_NOVERS(__copy_user);
-EXPORT_SYMBOL_NOVERS(__bzero);
-EXPORT_SYMBOL_NOVERS(__strncpy_from_user_nocheck_asm);
-EXPORT_SYMBOL_NOVERS(__strncpy_from_user_asm);
-EXPORT_SYMBOL_NOVERS(__strlen_user_nocheck_asm);
-EXPORT_SYMBOL_NOVERS(__strlen_user_asm);
-EXPORT_SYMBOL_NOVERS(__strnlen_user_nocheck_asm);
-EXPORT_SYMBOL_NOVERS(__strnlen_user_asm);
+EXPORT_SYMBOL(__copy_user);
+EXPORT_SYMBOL(__bzero);
+EXPORT_SYMBOL(__strncpy_from_user_nocheck_asm);
+EXPORT_SYMBOL(__strncpy_from_user_asm);
+EXPORT_SYMBOL(__strlen_user_nocheck_asm);
+EXPORT_SYMBOL(__strlen_user_asm);
+EXPORT_SYMBOL(__strnlen_user_nocheck_asm);
+EXPORT_SYMBOL(__strnlen_user_asm);
 
 EXPORT_SYMBOL(csum_partial);
 
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index a820be85e..325705fcc 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -406,9 +406,7 @@ static void inline setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
         return;
 
 give_sigsegv:
-	if (signr == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(signr, current);
 }
 #endif
 
@@ -475,19 +473,15 @@ static void inline setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
 	return;
 
 give_sigsegv:
-	if (signr == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(signr, current);
 }
 
 extern void setup_rt_frame_n32(struct k_sigaction * ka,
 	struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info);
 
 static inline void handle_signal(unsigned long sig, siginfo_t *info,
-	sigset_t *oldset, struct pt_regs *regs)
+	struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs)
 {
-	struct k_sigaction *ka = &current->sighand->action[sig-1];
-
 	switch(regs->regs[0]) {
 	case ERESTART_RESTARTBLOCK:
 	case ERESTARTNOHAND:
@@ -539,6 +533,7 @@ extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs);
 
 asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
 {
+	struct k_sigaction ka;
 	siginfo_t info;
 	int signr;
 
@@ -564,9 +559,9 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
 	if (!oldset)
 		oldset = &current->blocked;
 
-	signr = get_signal_to_deliver(&info, regs, NULL);
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
-		handle_signal(signr, &info, oldset, regs);
+		handle_signal(signr, &info, &ka, oldset, regs);
 		return 1;
 	}
 
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index 407beff81..a449a5651 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -574,9 +574,7 @@ static inline void setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
         return;
 
 give_sigsegv:
-	if (signr == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(signr, current);
 }
 
 static inline void setup_rt_frame(struct k_sigaction * ka,
@@ -647,9 +645,7 @@ static inline void setup_rt_frame(struct k_sigaction * ka,
 	return;
 
 give_sigsegv:
-	if (signr == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(signr, current);
 }
 
 static inline void handle_signal(unsigned long sig, siginfo_t *info,
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
index d262fbdc9..d2f8b8cf6 100644
--- a/arch/mips/kernel/signal_n32.c
+++ b/arch/mips/kernel/signal_n32.c
@@ -208,7 +208,5 @@ void setup_rt_frame_n32(struct k_sigaction * ka,
 	return;
 
 give_sigsegv:
-	if (signr == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(signr, current);
 }
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 1f917fe93..6d1c473f6 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -35,7 +35,6 @@
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <asm/system.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/smp.h>
 
@@ -254,16 +253,6 @@ void __devinit smp_prepare_boot_cpu(void)
 	cpu_set(0, cpu_callin_map);
 }
 
-static struct task_struct * __init fork_by_hand(void)
-{
-	struct pt_regs regs;
-	/*
-	 * don't care about the eip and regs settings since
-	 * we'll never reschedule the forked task.
-	 */
-	return copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
-}
-
 /*
  * Startup the CPU with this logical number
  */
@@ -275,20 +264,10 @@ static int __init do_boot_cpu(int cpu)
 	 * The following code is purely to make sure
 	 * Linux can schedule processes on this slave.
 	 */
-	idle = fork_by_hand();
+	idle = fork_idle(cpu);
 	if (IS_ERR(idle))
 		panic("failed fork for CPU %d\n", cpu);
 
-	wake_up_forked_process(idle);
-
-	/*
-	 * We remove it from the pidhash and the runqueue once we've
-	 * got the process:
-	 */
-	init_idle(idle, cpu);
-
-	unhash_process(idle);
-
 	prom_boot_secondary(cpu, idle);
 
 	/* XXXKW timeout */
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 8cc462dc3..bdd7fbbf1 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -181,7 +181,7 @@ static_unused int _sys_clone(nabi_no_regargs struct pt_regs regs)
 		newsp = regs.regs[29];
 	parent_tidptr = (int *) regs.regs[6];
 	child_tidptr = (int *) regs.regs[7];
-	return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0,
+	return do_fork(clone_flags, newsp, &regs, 0,
 	               parent_tidptr, child_tidptr);
 }
 
@@ -266,7 +266,7 @@ asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
 		strncpy(vx_new_uts(nodename), nodename, len);
 		nodename[__NEW_UTS_LEN] = '\0';
 		strlcpy(vx_new_uts(nodename), nodename,
-		        sizeof(vx_new_uts(nodename)));
+			sizeof(vx_new_uts(nodename)));
 		up_write(&uts_sem);
 		return 0;
 	}
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index e82b61fbe..15272d8c1 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -812,8 +812,8 @@ asmlinkage int irix_times(struct tms * tbuf)
 			return err;
 		err |= __put_user(current->utime, &tbuf->tms_utime);
 		err |= __put_user(current->stime, &tbuf->tms_stime);
-		err |= __put_user(current->cutime, &tbuf->tms_cutime);
-		err |= __put_user(current->cstime, &tbuf->tms_cstime);
+		err |= __put_user(current->signal->cutime, &tbuf->tms_cutime);
+		err |= __put_user(current->signal->cstime, &tbuf->tms_cstime);
 	}
 
 	return err;
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 0199485a4..915e5539e 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -29,7 +29,6 @@
 #include <asm/cpu.h>
 #include <asm/cpu-features.h>
 #include <asm/div64.h>
-#include <asm/hardirq.h>
 #include <asm/sections.h>
 #include <asm/time.h>
 
@@ -417,23 +416,8 @@ static long last_rtc_update;
  */
 void local_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	if (!user_mode(regs)) {
-		if (prof_buffer && current->pid) {
-			unsigned long pc = regs->cp0_epc;
-
-			pc -= (unsigned long) _stext;
-			pc >>= prof_shift;
-			/*
-			 * Dont ignore out-of-bounds pc values silently,
-			 * put them into the last histogram slot, so if
-			 * present, they will show up as a sharp peak.
-			 */
-			if (pc > prof_len - 1)
-				pc = prof_len - 1;
-			atomic_inc((atomic_t *)&prof_buffer[pc]);
-		}
-	}
-
+	if (current->pid)
+		profile_tick(CPU_PROFILING, regs);
 #ifdef CONFIG_SMP
 	/* in UP mode, update_process_times() is invoked by do_timer() */
 	update_process_times(user_mode(regs));
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 098cfaa23..e70684ee0 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -29,6 +29,7 @@ SECTIONS
   .text : {
     *(.text)
     SCHED_TEXT
+    LOCK_TEXT
     *(.fixup)
     *(.gnu.warning)
   } =0
@@ -96,9 +97,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
 
   .early_initcall.init : {
   __earlyinitcall_start = .;
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
index 9348cd3e6..fe7fc1730 100644
--- a/arch/mips/mips-boards/generic/time.c
+++ b/arch/mips/mips-boards/generic/time.c
@@ -31,7 +31,6 @@
 
 #include <asm/mipsregs.h>
 #include <asm/ptrace.h>
-#include <asm/hardirq.h>
 #include <asm/div64.h>
 #include <asm/cpu.h>
 #include <asm/time.h>
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index 820c3af08..ec8077c74 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -21,7 +21,6 @@
 #include <linux/module.h>
 
 #include <asm/branch.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
diff --git a/arch/mips/momentum/jaguar_atx/prom.c b/arch/mips/momentum/jaguar_atx/prom.c
index df52d2adf..fa5982ac0 100644
--- a/arch/mips/momentum/jaguar_atx/prom.c
+++ b/arch/mips/momentum/jaguar_atx/prom.c
@@ -40,7 +40,7 @@ const char *get_system_type(void)
 	return "Momentum Jaguar-ATX";
 }
 
-#ifdef CONFIG_MV64340_ETH
+#ifdef CONFIG_MV643XX_ETH
 extern unsigned char prom_mac_addr_base[6];
 
 static void burn_clocks(void)
@@ -230,7 +230,7 @@ void __init prom_init(void)
 	mips_machgroup = MACH_GROUP_MOMENCO;
 	mips_machtype = MACH_MOMENCO_JAGUAR_ATX;
 
-#ifdef CONFIG_MV64340_ETH
+#ifdef CONFIG_MV643XX_ETH
 	/* get the base MAC address for on-board ethernet ports */
 	get_mac(prom_mac_addr_base);
 #endif
diff --git a/arch/mips/momentum/ocelot_c/prom.c b/arch/mips/momentum/ocelot_c/prom.c
index 762112965..49ac302d8 100644
--- a/arch/mips/momentum/ocelot_c/prom.c
+++ b/arch/mips/momentum/ocelot_c/prom.c
@@ -32,7 +32,7 @@ struct callvectors* debug_vectors;
 extern unsigned long marvell_base;
 extern unsigned long cpu_clock;
 
-#ifdef CONFIG_MV64340_ETH
+#ifdef CONFIG_MV643XX_ETH
 extern unsigned char prom_mac_addr_base[6];
 #endif
 
@@ -45,7 +45,7 @@ const char *get_system_type(void)
 #endif
 }
 
-#ifdef CONFIG_MV64340_ETH
+#ifdef CONFIG_MV643XX_ETH
 static void burn_clocks(void)
 {
 	int i;
@@ -227,7 +227,7 @@ void __init prom_init(void)
 	mips_machgroup = MACH_GROUP_MOMENCO;
 	mips_machtype = MACH_MOMENCO_OCELOT_C;
 
-#ifdef CONFIG_MV64340_ETH
+#ifdef CONFIG_MV643XX_ETH
 	/* get the base MAC address for on-board ethernet ports */
 	get_mac(prom_mac_addr_base);
 #endif
diff --git a/arch/mips/pci/fixup-atlas.c b/arch/mips/pci/fixup-atlas.c
index 4cbef3431..ae1930e67 100644
--- a/arch/mips/pci/fixup-atlas.c
+++ b/arch/mips/pci/fixup-atlas.c
@@ -60,13 +60,7 @@ static void atlas_saa9730_base_fixup (struct pci_dev *pdev)
 	printk ("saa9730_base = %x\n", saa9730_base);
 }
 
-#endif
-
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA9730,
+	atlas_saa9730_base_fixup);
 
-struct pci_fixup pcibios_fixups[] __initdata = {
-#ifdef CONFIG_KGDB
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA9730,
-	 atlas_saa9730_base_fixup},
 #endif
-	{ 0 }
-};
diff --git a/arch/mips/pci/fixup-au1000.c b/arch/mips/pci/fixup-au1000.c
index 7bbe12336..2d42f9aa9 100644
--- a/arch/mips/pci/fixup-au1000.c
+++ b/arch/mips/pci/fixup-au1000.c
@@ -102,7 +102,3 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 return irq_tab_alchemy[slot][pin];
 }
-
-struct pci_fixup pcibios_fixups[] __initdata = {
-{ 0 }
-};
diff --git a/arch/mips/pci/fixup-capcella.c b/arch/mips/pci/fixup-capcella.c
index 9a0d68ed6..458270a02 100644
--- a/arch/mips/pci/fixup-capcella.c
+++ b/arch/mips/pci/fixup-capcella.c
@@ -42,7 +42,3 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	return irq_tab_capcella[slot][pin];
 }
-
-struct pci_fixup pcibios_fixups[] __initdata = {
-	{	.pass = 0,	},
-};
diff --git a/arch/mips/pci/fixup-cobalt.c b/arch/mips/pci/fixup-cobalt.c
index f72022a08..84c7e98de 100644
--- a/arch/mips/pci/fixup-cobalt.c
+++ b/arch/mips/pci/fixup-cobalt.c
@@ -41,6 +41,9 @@ static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev)
 	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7);
 }
 
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1,
+	 qube_raq_via_bmIDE_fixup);
+
 static void qube_raq_galileo_fixup(struct pci_dev *dev)
 {
 	unsigned short galileo_id;
@@ -73,13 +76,8 @@ static void qube_raq_galileo_fixup(struct pci_dev *dev)
 	}
 }
 
-struct pci_fixup pcibios_fixups[] __initdata = {
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1,
-	 qube_raq_via_bmIDE_fixup},
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_GALILEO, PCI_ANY_ID,
-	 qube_raq_galileo_fixup},
-	0
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_GALILEO, PCI_ANY_ID,
+	qube_raq_galileo_fixup);
 
 static char irq_tab_cobalt[] __initdata = {
   [COBALT_PCICONF_CPU]     = 0,
diff --git a/arch/mips/pci/fixup-ddb5074.c b/arch/mips/pci/fixup-ddb5074.c
index 025285f9a..785bc03f8 100644
--- a/arch/mips/pci/fixup-ddb5074.c
+++ b/arch/mips/pci/fixup-ddb5074.c
@@ -17,8 +17,5 @@ static void ddb5074_fixup(struct pci_dev *dev)
 	pci_write_config_byte(dev, 0x7e, t8);
 }
 
-struct pci_fixup pcibios_fixups[] __initdata = {
-	{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
-	  ddb5074_fixup },
-	{0}
-};
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
+	ddb5074_fixup);
diff --git a/arch/mips/pci/fixup-ddb5477.c b/arch/mips/pci/fixup-ddb5477.c
index 985441343..25bf49307 100644
--- a/arch/mips/pci/fixup-ddb5477.c
+++ b/arch/mips/pci/fixup-ddb5477.c
@@ -41,6 +41,11 @@ static void ddb5477_fixup(struct pci_dev *dev)
 	pci_write_config_byte(dev, 0x41, old | 0xd0);
 }
 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
+	  ddb5477_fixup);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1535,
+	  ddb5477_fixup);
+
 /*
  * Fixup baseboard AMD chip so that tx does not underflow.
  *      bcr_18 |= 0x0800
@@ -69,12 +74,5 @@ static void ddb5477_amd_lance_fixup(struct pci_dev *dev)
 	outw(temp, ioaddr + PCNET32_WIO_BDP);
 }
 
-struct pci_fixup pcibios_fixups[] __initdata = {
-	{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
-	  ddb5477_fixup },
-	{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1535,
-	  ddb5477_fixup },
-	{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE,
-	  ddb5477_amd_lance_fixup },
-	{0}
-};
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE,
+          ddb5477_amd_lance_fixup);
diff --git a/arch/mips/pci/fixup-ip32.c b/arch/mips/pci/fixup-ip32.c
index 90c67c35f..f64529b7b 100644
--- a/arch/mips/pci/fixup-ip32.c
+++ b/arch/mips/pci/fixup-ip32.c
@@ -44,7 +44,3 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	return irq_tab_mace[slot][pin];
 }
-
-struct pci_fixup pcibios_fixups[] = {
-	{0}
-};
diff --git a/arch/mips/pci/fixup-jaguar.c b/arch/mips/pci/fixup-jaguar.c
index fa78b9b1f..29b6a4615 100644
--- a/arch/mips/pci/fixup-jaguar.c
+++ b/arch/mips/pci/fixup-jaguar.c
@@ -36,7 +36,3 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 return 0;
 	panic("Whooops in pcibios_map_irq");
 }
-
-struct pci_fixup pcibios_fixups[] = {
-	{0}
-};
diff --git a/arch/mips/pci/fixup-lasat.c b/arch/mips/pci/fixup-lasat.c
index 49d33ff56..e2ab64ab8 100644
--- a/arch/mips/pci/fixup-lasat.c
+++ b/arch/mips/pci/fixup-lasat.c
@@ -4,7 +4,3 @@
 void __init pcibios_fixup_irqs(void)
 {
 }
-
-struct pci_fixup pcibios_fixups[] __initdata = {
-    { 0 }
-};
diff --git a/arch/mips/pci/fixup-malta.c b/arch/mips/pci/fixup-malta.c
index 3345e1952..bcde09eea 100644
--- a/arch/mips/pci/fixup-malta.c
+++ b/arch/mips/pci/fixup-malta.c
@@ -79,6 +79,8 @@ static void __init malta_piix_func0_fixup(struct pci_dev *pdev)
 	}
 }
 
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
+	 malta_piix_func0_fixup);
 
 static void __init malta_piix_func1_fixup(struct pci_dev *pdev)
 {
@@ -96,10 +98,5 @@ static void __init malta_piix_func1_fixup(struct pci_dev *pdev)
 	}
 }
 
-struct pci_fixup pcibios_fixups[] __initdata = {
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
-	 malta_piix_func0_fixup},
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB,
-	 malta_piix_func1_fixup},
-	{ 0 }
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB,
+	malta_piix_func1_fixup);
diff --git a/arch/mips/pci/fixup-mpc30x.c b/arch/mips/pci/fixup-mpc30x.c
index 1320c42af..8e5db12a4 100644
--- a/arch/mips/pci/fixup-mpc30x.c
+++ b/arch/mips/pci/fixup-mpc30x.c
@@ -42,7 +42,3 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 
 	return irq_tab_mpc30x[slot];
 }
-
-struct pci_fixup pcibios_fixups[] __initdata = {
-	{	.pass = 0,	},
-};
diff --git a/arch/mips/pci/fixup-ocelot-c.c b/arch/mips/pci/fixup-ocelot-c.c
index 0cc86eceb..9edc05950 100644
--- a/arch/mips/pci/fixup-ocelot-c.c
+++ b/arch/mips/pci/fixup-ocelot-c.c
@@ -33,7 +33,3 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 return 0;
 	panic("Whooops in pcibios_map_irq");
 }
-
-struct pci_fixup pcibios_fixups[] = {
-	{0}
-};
diff --git a/arch/mips/pci/fixup-ocelot-g.c b/arch/mips/pci/fixup-ocelot-g.c
index 9a2cc8505..a79fc4a08 100644
--- a/arch/mips/pci/fixup-ocelot-g.c
+++ b/arch/mips/pci/fixup-ocelot-g.c
@@ -29,7 +29,3 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 
 	return -1;
 }
-
-struct pci_fixup pcibios_fixups[] = {
-	{0}
-};
diff --git a/arch/mips/pci/fixup-sni.c b/arch/mips/pci/fixup-sni.c
index 99067c76b..563fb2c89 100644
--- a/arch/mips/pci/fixup-sni.c
+++ b/arch/mips/pci/fixup-sni.c
@@ -82,7 +82,3 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 
 	return irq_tab_rm200[slot][pin];
 }
-
-struct pci_fixup pcibios_fixups[] = {
-	{0}
-};
diff --git a/arch/mips/pci/fixup-tb0219.c b/arch/mips/pci/fixup-tb0219.c
index ca4d99fbe..4d62bce5b 100644
--- a/arch/mips/pci/fixup-tb0219.c
+++ b/arch/mips/pci/fixup-tb0219.c
@@ -58,7 +58,3 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 
 	return irq;
 }
-
-struct pci_fixup pcibios_fixups[] __initdata = {
-	{	.pass = 0,	},
-};
diff --git a/arch/mips/pci/fixup-tb0226.c b/arch/mips/pci/fixup-tb0226.c
index 50e639e04..6643462f7 100644
--- a/arch/mips/pci/fixup-tb0226.c
+++ b/arch/mips/pci/fixup-tb0226.c
@@ -77,7 +77,3 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 
 	return irq;
 }
-
-struct pci_fixup pcibios_fixups[] __initdata = {
-	{	.pass = 0,	},
-};
diff --git a/arch/mips/pci/fixup-yosemite.c b/arch/mips/pci/fixup-yosemite.c
index 92e40b091..e39ba2c54 100644
--- a/arch/mips/pci/fixup-yosemite.c
+++ b/arch/mips/pci/fixup-yosemite.c
@@ -33,7 +33,3 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 
 	return 3;			/* Everything goes to one irq bit */
 }
-
-struct pci_fixup pcibios_fixups[] = {
-	{0}
-};
diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c
index 3c4183d45..b996766a2 100644
--- a/arch/mips/pci/pci-ip27.c
+++ b/arch/mips/pci/pci-ip27.c
@@ -329,6 +329,9 @@ static void __init pci_fixup_ioc3(struct pci_dev *d)
 	pci_disable_swapping(d);
 }
 
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3,
+	 pci_fixup_ioc3);
+
 static void __init pci_fixup_isp1020(struct pci_dev *d)
 {
 	struct bridge_controller *bc = BRIDGE_CONTROLLER(d->bus);
@@ -353,6 +356,9 @@ static void __init pci_fixup_isp1020(struct pci_dev *d)
 	pci_enable_swapping(d);
 }
 
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1020,
+	 pci_fixup_isp1020);
+
 static void __init pci_fixup_isp2x00(struct pci_dev *d)
 {
 	struct bridge_controller *bc = BRIDGE_CONTROLLER(d->bus);
@@ -427,14 +433,7 @@ static void __init pci_fixup_isp2x00(struct pci_dev *d)
 	/*d->resource[1].flags |= 1; */
 }
 
-struct pci_fixup pcibios_fixups[] = {
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3,
-	 pci_fixup_ioc3},
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1020,
-	 pci_fixup_isp1020},
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100,
-	 pci_fixup_isp2x00},
-	{PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200,
-	 pci_fixup_isp2x00},
-	{0}
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100,
+	 pci_fixup_isp2x00);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200,
+	 pci_fixup_isp2x00);
diff --git a/arch/mips/pci/pci-sb1250.c b/arch/mips/pci/pci-sb1250.c
index 18e06ecd4..8c7c385e4 100644
--- a/arch/mips/pci/pci-sb1250.c
+++ b/arch/mips/pci/pci-sb1250.c
@@ -279,7 +279,3 @@ static int __init sb1250_pcibios_init(void)
 	return 0;
 }
 arch_initcall(sb1250_pcibios_init);
-
-struct pci_fixup pcibios_fixups[] = {
-	{0}
-};
diff --git a/arch/mips/pmc-sierra/yosemite/ht.c b/arch/mips/pmc-sierra/yosemite/ht.c
index b9a12e90a..95bbfd013 100644
--- a/arch/mips/pmc-sierra/yosemite/ht.c
+++ b/arch/mips/pmc-sierra/yosemite/ht.c
@@ -414,11 +414,6 @@ struct pci_ops titan_pci_ops = {
         titan_ht_config_write_dword
 };
 
-
-struct pci_fixup pcibios_fixups[] = {
-        {0}
-};
-
 void __init pcibios_fixup_bus(struct pci_bus *c)
 {
         titan_ht_pcibios_fixup_bus(c);
diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c
index 6c6df7b5b..e3cdb9582 100644
--- a/arch/mips/sgi-ip27/ip27-memory.c
+++ b/arch/mips/sgi-ip27/ip27-memory.c
@@ -225,7 +225,7 @@ void __init paging_init(void)
 		pfn_t end_pfn = node_getmaxclick(node) + 1;
 
 		zones_size[ZONE_DMA] = end_pfn - start_pfn;
-		free_area_init_node(node, NODE_DATA(node), NULL,
+		free_area_init_node(node, NODE_DATA(node),
 				zones_size, start_pfn, NULL);
 
 		if (end_pfn > max_low_pfn)
diff --git a/arch/mips/vr41xx/common/giu.c b/arch/mips/vr41xx/common/giu.c
index bd2978fd5..fa93b0331 100644
--- a/arch/mips/vr41xx/common/giu.c
+++ b/arch/mips/vr41xx/common/giu.c
@@ -63,6 +63,12 @@
 
 static uint32_t giu_base;
 
+static struct irqaction giu_cascade = {
+	.handler	= no_action,
+	.mask		= CPU_MASK_NONE,
+	.name		= "cascade",
+};
+
 #define read_giuint(offset)		readw(giu_base + (offset))
 #define write_giuint(val, offset)	writew((val), giu_base + (offset))
 
@@ -303,7 +309,6 @@ struct vr41xx_giuint_cascade {
 };
 
 static struct vr41xx_giuint_cascade giuint_cascade[GIUINT_NR_IRQS];
-static struct irqaction giu_cascade = {no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL};
 
 static int no_irq_number(int irq)
 {
diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c
index 4fd195bc9..19ccb3b56 100644
--- a/arch/mips/vr41xx/common/icu.c
+++ b/arch/mips/vr41xx/common/icu.c
@@ -51,6 +51,12 @@ extern void giuint_irq_dispatch(struct pt_regs *regs);
 static uint32_t icu1_base;
 static uint32_t icu2_base;
 
+static struct irqaction icu_cascade = {
+	.handler	= no_action,
+	.mask		= CPU_MASK_NONE,
+	.name		= "cascade",
+};
+
 static unsigned char sysint1_assign[16] = {
 	0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 static unsigned char sysint2_assign[16] = {
@@ -159,218 +165,268 @@ void vr41xx_enable_piuint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + PIU_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu1(MPIUINTREG);
-	val |= mask;
-	write_icu1(val, MPIUINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4111 ||
+	    current_cpu_data.cputype == CPU_VR4121) {
+		spin_lock_irqsave(&desc->lock, flags);
+		set_icu1(MPIUINTREG, mask);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_enable_piuint);
+
 void vr41xx_disable_piuint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + PIU_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu1(MPIUINTREG);
-	val &= ~mask;
-	write_icu1(val, MPIUINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4111 ||
+	    current_cpu_data.cputype == CPU_VR4121) {
+		spin_lock_irqsave(&desc->lock, flags);
+		clear_icu1(MPIUINTREG, mask);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_disable_piuint);
+
 void vr41xx_enable_aiuint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + AIU_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu1(MAIUINTREG);
-	val |= mask;
-	write_icu1(val, MAIUINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4111 ||
+	    current_cpu_data.cputype == CPU_VR4121) {
+		spin_lock_irqsave(&desc->lock, flags);
+		set_icu1(MAIUINTREG, mask);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_enable_aiuint);
+
 void vr41xx_disable_aiuint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + AIU_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu1(MAIUINTREG);
-	val &= ~mask;
-	write_icu1(val, MAIUINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4111 ||
+	    current_cpu_data.cputype == CPU_VR4121) {
+		spin_lock_irqsave(&desc->lock, flags);
+		clear_icu1(MAIUINTREG, mask);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_disable_aiuint);
+
 void vr41xx_enable_kiuint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + KIU_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu1(MKIUINTREG);
-	val |= mask;
-	write_icu1(val, MKIUINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4111 ||
+	    current_cpu_data.cputype == CPU_VR4121) {
+		spin_lock_irqsave(&desc->lock, flags);
+		set_icu1(MKIUINTREG, mask);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_enable_kiuint);
+
 void vr41xx_disable_kiuint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + KIU_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu1(MKIUINTREG);
-	val &= ~mask;
-	write_icu1(val, MKIUINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4111 ||
+	    current_cpu_data.cputype == CPU_VR4121) {
+		spin_lock_irqsave(&desc->lock, flags);
+		clear_icu1(MKIUINTREG, mask);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_disable_kiuint);
+
 void vr41xx_enable_dsiuint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + DSIU_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
 	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu1(MDSIUINTREG);
-	val |= mask;
-	write_icu1(val, MDSIUINTREG);
+	set_icu1(MDSIUINTREG, mask);
 	spin_unlock_irqrestore(&desc->lock, flags);
 }
 
+EXPORT_SYMBOL(vr41xx_enable_dsiuint);
+
 void vr41xx_disable_dsiuint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + DSIU_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
 	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu1(MDSIUINTREG);
-	val &= ~mask;
-	write_icu1(val, MDSIUINTREG);
+	clear_icu1(MDSIUINTREG, mask);
 	spin_unlock_irqrestore(&desc->lock, flags);
 }
 
+EXPORT_SYMBOL(vr41xx_disable_dsiuint);
+
 void vr41xx_enable_firint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + FIR_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
 	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu2(MFIRINTREG);
-	val |= mask;
-	write_icu2(val, MFIRINTREG);
+	set_icu2(MFIRINTREG, mask);
 	spin_unlock_irqrestore(&desc->lock, flags);
 }
 
+EXPORT_SYMBOL(vr41xx_enable_firint);
+
 void vr41xx_disable_firint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + FIR_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
 	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu2(MFIRINTREG);
-	val &= ~mask;
-	write_icu2(val, MFIRINTREG);
+	clear_icu2(MFIRINTREG, mask);
 	spin_unlock_irqrestore(&desc->lock, flags);
 }
 
+EXPORT_SYMBOL(vr41xx_disable_firint);
+
 void vr41xx_enable_pciint(void)
 {
 	irq_desc_t *desc = irq_desc + PCI_IRQ;
 	unsigned long flags;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	write_icu2(PCIINT0, MPCIINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4122 ||
+	    current_cpu_data.cputype == CPU_VR4131 ||
+	    current_cpu_data.cputype == CPU_VR4133) {
+		spin_lock_irqsave(&desc->lock, flags);
+		write_icu2(PCIINT0, MPCIINTREG);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_enable_pciint);
+
 void vr41xx_disable_pciint(void)
 {
 	irq_desc_t *desc = irq_desc + PCI_IRQ;
 	unsigned long flags;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	write_icu2(0, MPCIINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4122 ||
+	    current_cpu_data.cputype == CPU_VR4131 ||
+	    current_cpu_data.cputype == CPU_VR4133) {
+		spin_lock_irqsave(&desc->lock, flags);
+		write_icu2(0, MPCIINTREG);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_disable_pciint);
+
 void vr41xx_enable_scuint(void)
 {
 	irq_desc_t *desc = irq_desc + SCU_IRQ;
 	unsigned long flags;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	write_icu2(SCUINT0, MSCUINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4122 ||
+	    current_cpu_data.cputype == CPU_VR4131 ||
+	    current_cpu_data.cputype == CPU_VR4133) {
+		spin_lock_irqsave(&desc->lock, flags);
+		write_icu2(SCUINT0, MSCUINTREG);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_enable_scuint);
+
 void vr41xx_disable_scuint(void)
 {
 	irq_desc_t *desc = irq_desc + SCU_IRQ;
 	unsigned long flags;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	write_icu2(0, MSCUINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4122 ||
+	    current_cpu_data.cputype == CPU_VR4131 ||
+	    current_cpu_data.cputype == CPU_VR4133) {
+		spin_lock_irqsave(&desc->lock, flags);
+		write_icu2(0, MSCUINTREG);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_disable_scuint);
+
 void vr41xx_enable_csiint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + CSI_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu2(MCSIINTREG);
-	val |= mask;
-	write_icu2(val, MCSIINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4122 ||
+	    current_cpu_data.cputype == CPU_VR4131 ||
+	    current_cpu_data.cputype == CPU_VR4133) {
+		spin_lock_irqsave(&desc->lock, flags);
+		set_icu2(MCSIINTREG, mask);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_enable_csiint);
+
 void vr41xx_disable_csiint(uint16_t mask)
 {
 	irq_desc_t *desc = irq_desc + CSI_IRQ;
 	unsigned long flags;
-	uint16_t val;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	val = read_icu2(MCSIINTREG);
-	val &= ~mask;
-	write_icu2(val, MCSIINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4122 ||
+	    current_cpu_data.cputype == CPU_VR4131 ||
+	    current_cpu_data.cputype == CPU_VR4133) {
+		spin_lock_irqsave(&desc->lock, flags);
+		clear_icu2(MCSIINTREG, mask);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_disable_csiint);
+
 void vr41xx_enable_bcuint(void)
 {
 	irq_desc_t *desc = irq_desc + BCU_IRQ;
 	unsigned long flags;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	write_icu2(BCUINTR, MBCUINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4122 ||
+	    current_cpu_data.cputype == CPU_VR4131 ||
+	    current_cpu_data.cputype == CPU_VR4133) {
+		spin_lock_irqsave(&desc->lock, flags);
+		write_icu2(BCUINTR, MBCUINTREG);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_enable_bcuint);
+
 void vr41xx_disable_bcuint(void)
 {
 	irq_desc_t *desc = irq_desc + BCU_IRQ;
 	unsigned long flags;
 
-	spin_lock_irqsave(&desc->lock, flags);
-	write_icu2(0, MBCUINTREG);
-	spin_unlock_irqrestore(&desc->lock, flags);
+	if (current_cpu_data.cputype == CPU_VR4122 ||
+	    current_cpu_data.cputype == CPU_VR4131 ||
+	    current_cpu_data.cputype == CPU_VR4133) {
+		spin_lock_irqsave(&desc->lock, flags);
+		write_icu2(0, MBCUINTREG);
+		spin_unlock_irqrestore(&desc->lock, flags);
+	}
 }
 
+EXPORT_SYMBOL(vr41xx_disable_bcuint);
+
 /*=======================================================================*/
 
 static unsigned int startup_sysint1_irq(unsigned int irq)
@@ -674,8 +730,6 @@ early_initcall(vr41xx_icu_init);
 
 /*=======================================================================*/
 
-static struct irqaction icu_cascade = {no_action, 0, 0, "cascade", NULL, NULL};
-
 static inline void init_vr41xx_icu_irq(void)
 {
 	int i;
diff --git a/arch/mips/vr41xx/common/serial.c b/arch/mips/vr41xx/common/serial.c
index cc445eeff..939ac827e 100644
--- a/arch/mips/vr41xx/common/serial.c
+++ b/arch/mips/vr41xx/common/serial.c
@@ -115,7 +115,7 @@ void __init vr41xx_siu_init(void)
 	port.line = vr41xx_serial_ports;
 	port.uartclk = SIU_BASE_BAUD * 16;
 	port.irq = SIU_IRQ;
-	port.flags = UPF_RESOURCES | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+	port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
 	switch (current_cpu_data.cputype) {
 	case CPU_VR4111:
 	case CPU_VR4121:
@@ -160,7 +160,7 @@ void __init vr41xx_dsiu_init(void)
 	port.line = vr41xx_serial_ports;
 	port.uartclk = DSIU_BASE_BAUD * 16;
 	port.irq = DSIU_IRQ;
-	port.flags = UPF_RESOURCES | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+	port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
 	port.mapbase = DSIU_BASE;
 	port.regshift = 0;
 	port.iotype = UPIO_MEM;
diff --git a/arch/mips/vr41xx/common/vrc4173.c b/arch/mips/vr41xx/common/vrc4173.c
index 3b006358c..0bbad1e8c 100644
--- a/arch/mips/vr41xx/common/vrc4173.c
+++ b/arch/mips/vr41xx/common/vrc4173.c
@@ -316,6 +316,96 @@ static inline void vrc4173_giu_init(void)
 	spin_lock_init(&vrc4173_giu_lock);
 }
 
+void vrc4173_enable_piuint(uint16_t mask)
+{
+	irq_desc_t *desc = irq_desc + VRC4173_PIU_IRQ;
+	unsigned long flags;
+	uint16_t val;
+
+	spin_lock_irqsave(&desc->lock, flags);
+	val = vrc4173_inw(VRC4173_MPIUINTREG);
+	val |= mask;
+	vrc4173_outw(val, VRC4173_MPIUINTREG);
+	spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vrc4173_eanble_piuint);
+
+void vrc4173_disable_piuint(uint16_t mask)
+{
+	irq_desc_t *desc = irq_desc + VRC4173_PIU_IRQ;
+	unsigned long flags;
+	uint16_t val;
+
+	spin_lock_irqsave(&desc->lock, flags);
+	val = vrc4173_inw(VRC4173_MPIUINTREG);
+	val &= ~mask;
+	vrc4173_outw(val, VRC4173_MPIUINTREG);
+	spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vrc4173_disable_piuint);
+
+void vrc4173_enable_aiuint(uint16_t mask)
+{
+	irq_desc_t *desc = irq_desc + VRC4173_AIU_IRQ;
+	unsigned long flags;
+	uint16_t val;
+
+	spin_lock_irqsave(&desc->lock, flags);
+	val = vrc4173_inw(VRC4173_MAIUINTREG);
+	val |= mask;
+	vrc4173_outw(val, VRC4173_MAIUINTREG);
+	spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vrc4173_enable_aiuint);
+
+void vrc4173_disable_aiuint(uint16_t mask)
+{
+	irq_desc_t *desc = irq_desc + VRC4173_AIU_IRQ;
+	unsigned long flags;
+	uint16_t val;
+
+	spin_lock_irqsave(&desc->lock, flags);
+	val = vrc4173_inw(VRC4173_MAIUINTREG);
+	val &= ~mask;
+	vrc4173_outw(val, VRC4173_MAIUINTREG);
+	spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vrc4173_disable_aiuint);
+
+void vrc4173_enable_kiuint(uint16_t mask)
+{
+	irq_desc_t *desc = irq_desc + VRC4173_KIU_IRQ;
+	unsigned long flags;
+	uint16_t val;
+
+	spin_lock_irqsave(&desc->lock, flags);
+	val = vrc4173_inw(VRC4173_MKIUINTREG);
+	val |= mask;
+	vrc4173_outw(val, VRC4173_MKIUINTREG);
+	spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vrc4173_enable_kiuint);
+
+void vrc4173_disable_kiuint(uint16_t mask)
+{
+	irq_desc_t *desc = irq_desc + VRC4173_KIU_IRQ;
+	unsigned long flags;
+	uint16_t val;
+
+	spin_lock_irqsave(&desc->lock, flags);
+	val = vrc4173_inw(VRC4173_MKIUINTREG);
+	val &= ~mask;
+	vrc4173_outw(val, VRC4173_MKIUINTREG);
+	spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vrc4173_disable_kiuint);
+
 static void enable_vrc4173_irq(unsigned int irq)
 {
 	uint16_t val;
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 1c018a72a..093e8046f 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -106,7 +106,7 @@ config PARISC64
 	depends on PA8X00
 	help
 	  Enable this if you want to support 64bit kernel on PA-RISC platform.
-	  
+
 	  At the moment, only people willing to use more than 2GB of RAM,
 	  or having a 64bit-only capable PA-RISC machine should say Y here.
 
@@ -188,72 +188,7 @@ source "fs/Kconfig"
 
 source "arch/parisc/oprofile/Kconfig"
 
-menu "Kernel hacking"
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SPINLOCK
-        bool "Spinlock debugging"
-        depends on DEBUG_KERNEL
-        help
-          Say Y here and build SMP to catch missing spinlock initialization
-          and certain other kinds of spinlock errors commonly made.  This is
-          best used in conjunction with the NMI watchdog so that spinlock
-          deadlocks are also debuggable.
-
-config DEBUG_RWLOCK
-        bool "Read-write spinlock debugging"
-        depends on DEBUG_KERNEL && SMP
-        help
-          If you say Y here then read-write lock processing will count how many
-          times it has tried to get the lock and issue an error message after
-          too many attempts.  If you suspect a rwlock problem or a kernel
-          hacker asks for this option then say Y.  Otherwise say N.
-
-config FRAME_POINTER
-	bool "Compile the kernel with frame pointers"
-	help
-	  If you say Y here the resulting kernel image will be slightly larger
-	  and slower, but 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 pointers.
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  If you don't debug the kernel, you can say N.
-	  
-endmenu
+source "arch/parisc/Kconfig.debug"
 
 source "kernel/vserver/Kconfig"
 
@@ -262,4 +197,3 @@ source "security/Kconfig"
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile
index b032c6b79..adffb0504 100644
--- a/arch/parisc/kernel/Makefile
+++ b/arch/parisc/kernel/Makefile
@@ -4,7 +4,7 @@
 
 head-y			:= head.o
 head-$(CONFIG_PARISC64)	:= head64.o
-extra-y			:= init_task.o $(head-y) vmlinux.lds.s
+extra-y			:= init_task.o $(head-y) vmlinux.lds
 
 AFLAGS_entry.o	:= -traditional
 AFLAGS_pacache.o := -traditional
diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c
index 64d49cb2d..cf8a8583f 100644
--- a/arch/parisc/kernel/asm-offsets.c
+++ b/arch/parisc/kernel/asm-offsets.c
@@ -32,11 +32,11 @@
 #include <linux/thread_info.h>
 #include <linux/version.h>
 #include <linux/ptrace.h>
-#include <asm/pgtable.h>
+#include <linux/hardirq.h>
 
+#include <asm/pgtable.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
-#include <asm/hardirq.h>
 #include <asm/pdc.h>
 
 #define DEFINE(sym, val) \
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index eadc88c5a..0703ab036 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -245,7 +245,7 @@ void disable_sr_hashing(void)
 void flush_dcache_page(struct page *page)
 {
 	struct address_space *mapping = page_mapping(page);
-	struct vm_area_struct *mpnt = NULL;
+	struct vm_area_struct *mpnt;
 	struct prio_tree_iter iter;
 	unsigned long offset;
 	unsigned long addr;
@@ -272,8 +272,7 @@ void flush_dcache_page(struct page *page)
 	 * to flush one address here for them all to become coherent */
 
 	flush_dcache_mmap_lock(mapping);
-	while ((mpnt = vma_prio_tree_next(mpnt, &mapping->i_mmap,
-					&iter, pgoff, pgoff)) != NULL) {
+	vma_prio_tree_foreach(mpnt, &iter, &mapping->i_mmap, pgoff, pgoff) {
 		offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
 		addr = mpnt->vm_start + offset;
 
diff --git a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c
index 6b65bf468..4abd43910 100644
--- a/arch/parisc/kernel/hardware.c
+++ b/arch/parisc/kernel/hardware.c
@@ -7,7 +7,7 @@
  *    Reference Specification", March 7, 1999, version 0.96.  This
  *    is available at http://parisc-linux.org/documentation/
  *
- *    Copyright 1999 by Alex deVries <adevries@thepuffingroup.com>
+ *    Copyright 1999 by Alex deVries <alex@onefishtwo.ca>
  *    and copyright 1999 The Puffin Group Inc.
  *
  *    This program is free software; you can redistribute it and/or modify
diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
index 937ab23ca..3cb08a4a5 100644
--- a/arch/parisc/kernel/pci.c
+++ b/arch/parisc/kernel/pci.c
@@ -146,15 +146,6 @@ char *pcibios_setup(char *str)
 	return str;
 }
 
-/* Used in drivers/pci/quirks.c */
-struct pci_fixup pcibios_fixups[] = { 
-#ifdef CONFIG_SUPERIO
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_NS,	PCI_DEVICE_ID_NS_87415,	superio_fixup_pci },
-#endif
-	{ 0 }
-};
-
-
 /*
  * Called by pci_set_master() - a driver interface.
  *
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index dd938ef77..d7365b958 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -262,7 +262,7 @@ sys_clone(unsigned long clone_flags, unsigned long usp,
 	if(usp == 0)
 		usp = regs->gr[30];
 
-	return do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0, user_tid, NULL);
+	return do_fork(clone_flags, usp, regs, 0, user_tid, NULL);
 }
 
 int
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index d45980cb5..871d7857f 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -407,11 +407,8 @@ void syscall_trace(void)
 		return;
 	if (!(current->ptrace & PT_PTRACED))
 		return;
-	current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-					? 0x80 : 0);
-	current->state = TASK_STOPPED;
-	notify_parent(current, SIGCHLD);
-	schedule();
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+				 ? 0x80 : 0));
 	/*
 	 * this isn't the same as continuing with a signal, but it will do
 	 * for normal use.  strace only continues with a signal if the
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index 0f1daa584..9def95a43 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -485,24 +485,6 @@ void __init smp_callin(void)
 	panic("smp_callin() AAAAaaaaahhhh....\n");
 }
 
-/*
- * Create the idle task for a new Slave CPU.  DO NOT use kernel_thread()
- * because that could end up calling schedule(). If it did, the new idle
- * task could get scheduled before we had a chance to remove it from the
- * run-queue...
- */
-static struct task_struct *fork_by_hand(void)
-{
-	struct pt_regs regs;  
-
-	/*
-	 * don't care about the regs settings since
-	 * we'll never reschedule the forked task.
-	 */
-	return copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
-}
-
-
 /*
  * Bring one cpu online.
  */
@@ -521,13 +503,10 @@ int __init smp_boot_one_cpu(int cpuid)
 	 * Sheesh . . .
 	 */
 
-	idle = fork_by_hand();
+	idle = fork_idle(cpuid);
 	if (IS_ERR(idle))
 		panic("SMP: fork failed for CPU:%d", cpuid);
 
-	wake_up_forked_process(idle);
-	init_idle(idle, cpuid);
-	unhash_process(idle);
 	idle->thread_info->cpu = cpuid;
 
 	/* Let _start know what logical CPU we're booting
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index 949998ffb..8f4ad0cf2 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -47,44 +47,6 @@ static long halftick;
 extern void smp_do_timer(struct pt_regs *regs);
 #endif
 
-static inline void
-parisc_do_profile(struct pt_regs *regs)
-{
-	unsigned long pc = regs->iaoq[0];
-#if 0
-	extern unsigned long prof_cpu_mask;
-#endif
-	extern char _stext;
-
-	profile_hook(regs);
-
-	if (user_mode(regs))
-		return;
-
-	if (!prof_buffer)
-		return;
-
-#if 0
-	/* FIXME: when we have irq affinity to cpu, we need to
-	 * only look at the cpus specified in this mask 
-	 */
-
-	if (!((1 << smp_processor_id()) & prof_cpu_mask))
-		return;
-#endif
-
-	pc -= (unsigned long) &_stext;
-	pc >>= prof_shift;
-	/*
-	 * Don't ignore out-of-bounds PC values silently,
-	 * put them into the last histogram slot, so if
-	 * present, they will show up as a sharp peak.
-	 */
-	if (pc > prof_len - 1)
-		pc = prof_len - 1;
-	atomic_inc((atomic_t *)&prof_buffer[pc]);
-}
-
 irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	long now;
@@ -92,7 +54,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 	int nticks;
 	int cpu = smp_processor_id();
 
-	parisc_do_profile(regs);
+	profile_tick(CPU_PROFILING, regs);
 
 	now = mfctl(16);
 	/* initialize next_tick to time at last clocktick */
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 7da318ed0..e011bc856 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -52,6 +52,7 @@ SECTIONS
   .text ALIGN(16) : {
 	*(.text)
 	SCHED_TEXT
+	LOCK_TEXT
 	*(.text.do_softirq)
 	*(.text.sys_exit)
 	*(.text.do_sigaltstack)
@@ -130,9 +131,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : {
 	*(.initcall1.init) 
diff --git a/arch/parisc/lib/debuglocks.c b/arch/parisc/lib/debuglocks.c
index 7e79f1bad..5166a9378 100644
--- a/arch/parisc/lib/debuglocks.c
+++ b/arch/parisc/lib/debuglocks.c
@@ -25,8 +25,8 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
+#include <linux/hardirq.h>	/* in_interrupt() */
 #include <asm/system.h>
-#include <asm/hardirq.h>	/* in_interrupt() */
 
 #undef INIT_STUCK
 #define INIT_STUCK 1L << 30
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index 871d7df27..065da5807 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -804,7 +804,7 @@ void __init paging_init(void)
 		   ZONE_DMA zone. */
 		zones_size[ZONE_DMA] = pmem_ranges[i].pages;
 
-		free_area_init_node(i,NODE_DATA(i),NULL,zones_size,
+		free_area_init_node(i, NODE_DATA(i), zones_size,
 				pmem_ranges[i].start_pfn, 0);
 
 #ifdef CONFIG_DISCONTIGMEM
diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c
index d56a031e6..41ca12432 100644
--- a/arch/ppc/8260_io/fcc_enet.c
+++ b/arch/ppc/8260_io/fcc_enet.c
@@ -1986,9 +1986,9 @@ fcc_restart(struct net_device *dev, int duplex)
 	fccp = fcp->fccp;
 
 	if (duplex)
-		fccp->fcc_fpsmr |= FCC_PSMR_FDE;
+		fccp->fcc_fpsmr |= FCC_PSMR_FDE | FCC_PSMR_LPB;
 	else
-		fccp->fcc_fpsmr &= ~FCC_PSMR_FDE;
+		fccp->fcc_fpsmr &= ~(FCC_PSMR_FDE | FCC_PSMR_LPB);
 
 	/* Enable transmit/receive */
 	fccp->fcc_gfmr |= FCC_GFMR_ENR | FCC_GFMR_ENT;
diff --git a/arch/ppc/8xx_io/uart.c b/arch/ppc/8xx_io/uart.c
index 171e5e900..34a463a94 100644
--- a/arch/ppc/8xx_io/uart.c
+++ b/arch/ppc/8xx_io/uart.c
@@ -2592,7 +2592,7 @@ static int __init rs_8xx_init(void)
 		state->icount.rx = state->icount.tx = 0;
 		state->icount.frame = state->icount.parity = 0;
 		state->icount.overrun = state->icount.brk = 0;
-		printk(KERN_INFO "ttyS%02d at 0x%04x is a %s\n",
+		printk(KERN_INFO "ttyS%d at 0x%04x is a %s\n",
 		       i, (unsigned int)(state->port),
 		       (state->smc_scc_num & NUM_IS_SCC) ? "SCC" : "SMC");
 #ifdef CONFIG_SERIAL_CONSOLE
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 051832b2e..37104324d 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -49,7 +49,7 @@ config 6xx
 	  There are four types of PowerPC chips supported.  The more common
 	  types (601, 603, 604, 740, 750, 7400), the Motorola embedded
 	  versions (821, 823, 850, 855, 860, 52xx, 8260), the IBM embedded
-	  versions (403 and 405) and the high end 64 bit Power processors 
+	  versions (403 and 405) and the high end 64 bit Power processors
 	  (POWER 3, POWER4, and IBM 970 also known as G5)
 	  Unless you are building a kernel for one of the embedded processor
 	  systems, 64 bit IBM RS/6000 or an Apple G5, choose 6xx.
@@ -626,7 +626,7 @@ config EMBEDDEDBOOT
 	bool
 	depends on 8xx || 8260
 	default y
-	
+
 config PPC_MPC52xx
 	bool
 
@@ -685,7 +685,8 @@ config PPC_OF
 
 config PPC_GEN550
 	bool
-	depends on SANDPOINT || MCPN765 || SPRUCE || PPLUS || PCORE || PRPMC750 || K2 || PRPMC800
+	depends on SANDPOINT || MCPN765 || SPRUCE || PPLUS || PCORE || \
+		PRPMC750 || K2 || PRPMC800 || LOPEC
 	default y
 
 config FORCE
@@ -811,10 +812,6 @@ config PREEMPT
 config HIGHMEM
 	bool "High memory support"
 
-config KERNEL_ELF
-	bool
-	default y
-
 source "fs/Kconfig.binfmt"
 
 config PROC_DEVICETREE
@@ -832,10 +829,11 @@ config PREP_RESIDUAL
 	  Some PReP systems have residual data passed to the kernel by the
 	  firmware.  This allows detection of memory size, devices present and
 	  other useful pieces of information.  Sometimes this information is
-	  not present or incorrect.
+	  not present or incorrect, in which case it could lead to the machine 
+	  behaving incorrectly.  If this happens, either disable PREP_RESIDUAL
+	  or pass the 'noresidual' option to the kernel.
 
-	  Unless you expect to boot on a PReP system, there is no need to
-	  select Y.
+	  If you are running a PReP system, say Y here, otherwise say N.
 
 config PROC_PREPRESIDUAL
 	bool "Support for reading of PReP Residual Data in /proc"
@@ -1043,13 +1041,13 @@ config PCI_8260
 	bool
 	depends on PCI && 8260 && !8272
 	default y
-	
+
 config 8260_PCI9
 	bool "  Enable workaround for MPC826x erratum PCI 9"
 	depends on PCI_8260
 	default y
 
-choice 
+choice
 	prompt "  IDMA channel for PCI 9 workaround"
 	depends on 8260_PCI9
 
@@ -1228,128 +1226,7 @@ source "lib/Kconfig"
 
 source "arch/ppc/oprofile/Kconfig"
 
-menu "Kernel hacking"
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SPINLOCK
-	bool "Spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here and to CONFIG_SMP to include code to check for missing
-	  spinlock initialization and some other common spinlock errors.
-
-config DEBUG_HIGHMEM
-	bool "Highmem debugging"
-	depends on DEBUG_KERNEL && HIGHMEM
-	help
-	  This options enables additional error checking for high memory
-	  systems.  Disable for production systems.
-
-config DEBUG_SPINLOCK_SLEEP
-	bool "Sleep-inside-spinlock checking"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, various routines which may sleep will become very
-	  noisy if they are called with a spinlock held.
-
-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
-	help
-	  Include in-kernel hooks for the xmon kernel monitor/debugger.
-	  Unless you are intending to debug the kernel, say N here.
-
-config BDI_SWITCH
-	bool "Include BDI-2000 user context switcher"
-	depends on DEBUG_KERNEL
-	help
-	  Include in-kernel support for the Abatron BDI2000 debugger.
-	  Unless you are intending to debug the kernel with one of these
-	  machines, say N here.
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use some sort of debugger to
-	  debug the kernel.
-	  If you don't debug the kernel, you can say N.
-
-config BOOTX_TEXT
-	bool "Support for early boot text console (BootX or OpenFirmware only)"
-	depends PPC_OF
-	help
-	  Say Y here to see progress messages from the boot firmware in text
-	  mode. Requires either BootX or Open Firmware.
-
-config SERIAL_TEXT_DEBUG
-	bool "Support for early boot texts over serial port"
-	depends on 4xx || GT64260 || LOPEC || PPLUS || PRPMC800 || PPC_GEN550 || PPC_MPC52xx
-
-config PPC_OCP
-	bool
-	depends on IBM_OCP || FSL_OCP
-	default y
-
-endmenu
+source "arch/ppc/Kconfig.debug"
 
 source "kernel/vserver/Kconfig"
 
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
index e15c6919a..53dd5640d 100644
--- a/arch/ppc/Makefile
+++ b/arch/ppc/Makefile
@@ -13,7 +13,7 @@
 # This must match PAGE_OFFSET in include/asm-ppc/page.h.
 KERNELLOAD	:= $(CONFIG_KERNEL_START)
 
-HAS_BIARCH	:= $(shell if $(CC) -m32 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi;)
+HAS_BIARCH	:= $(call cc-option-yn, -m32)
 ifeq ($(HAS_BIARCH),y)
 AS		:= $(AS) -a32
 LD		:= $(LD) -m elf32ppc
@@ -24,10 +24,10 @@ LDFLAGS_vmlinux	:= -Ttext $(KERNELLOAD) -Bstatic
 CPPFLAGS	+= -Iarch/$(ARCH)
 AFLAGS		+= -Iarch/$(ARCH)
 CFLAGS		+= -Iarch/$(ARCH) -msoft-float -pipe \
-		-ffixed-r2 -Wno-uninitialized -mmultiple
+		-ffixed-r2 -mmultiple
 CPP		= $(CC) -E $(CFLAGS)
 
-CHECK		:= $(CHECK) -D__powerpc__=1
+CHECKFLAGS	+= -D__powerpc__
 
 ifndef CONFIG_E500
 CFLAGS		+= -mstring
@@ -70,7 +70,7 @@ BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm
 
 all: zImage
 
-AFLAGS_vmlinux.lds.o	:= -Upowerpc
+CPPFLAGS_vmlinux.lds	:= -Upowerpc
 
 # All the instructions talk about "make bzImage".
 bzImage: zImage
@@ -104,16 +104,15 @@ arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
 include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
 	$(call filechk,gen-asm-offsets)
 
-ifdef CONFIG_6xx
-# Ensure this is binutils 2.12.1 (or 2.12.90.0.7) or later
-NEW_AS	:= $(shell echo dssall | $(AS) -many -o /dev/null >/dev/null 2>&1 ; echo $$?)
-GOODVER	:= 2.12.1
-else
-NEW_AS	:= 0
-endif
+# Use the file '.tmp_gas_check' for binutils tests, as gas won't output
+# to stdout and these checks are run even on install targets.
+TOUT	:= .tmp_gas_check
+# Ensure this is binutils 2.12.1 (or 2.12.90.0.7) or later for altivec
+# instructions.
+AS_ALTIVEC	:= $(shell echo dssall | $(AS) -many -o $(TOUT) >/dev/null 2>&1 ; echo $$?)
 # gcc-3.4 and binutils-2.14 are a fatal combination.
-GCC_VERSION	:= $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC))
-BAD_GCC_AS	:= $(shell echo mftb 5 | $(AS) -mppc -many -o /dev/null >/dev/null 2>&1 && echo 0 || echo 1)
+GCC_VERSION	:= $(call cc-version)
+BAD_GCC_AS	:= $(shell echo mftb 5 | $(AS) -mppc -many -o $(TOUT) >/dev/null 2>&1 && echo 0 || echo 1)
 
 checkbin:
 ifeq ($(GCC_VERSION)$(BAD_GCC_AS),03041)
@@ -122,13 +121,16 @@ ifeq ($(GCC_VERSION)$(BAD_GCC_AS),03041)
 	@echo '*** Please upgrade your binutils or downgrade your gcc'
 	@false
 endif
-ifneq ($(NEW_AS),0)
+ifneq ($(AS_ALTIVEC),0)
+	echo $(AS_ALTIVEC)
 	@echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build '
 	@echo 'correctly with old versions of binutils.'
-	@echo '*** Please upgrade your binutils to ${GOODVER} or newer'
+	@echo '*** Please upgrade your binutils to 2.12.1 or newer'
 	@false
 endif
 	@true
 
 CLEAN_FILES +=	include/asm-$(ARCH)/offsets.h \
-		arch/$(ARCH)/kernel/asm-offsets.s
+		arch/$(ARCH)/kernel/asm-offsets.s \
+		$(TOUT)
+
diff --git a/arch/ppc/amiga/config.c b/arch/ppc/amiga/config.c
index cc93c9eb3..af881d745 100644
--- a/arch/ppc/amiga/config.c
+++ b/arch/ppc/amiga/config.c
@@ -423,9 +423,6 @@ void __init config_amiga(void)
   mach_floppy_setup    = amiga_floppy_setup;
 #endif
   mach_reset           = amiga_reset;
-#ifdef CONFIG_DUMMY_CONSOLE
-  conswitchp           = &dummy_con;
-#endif
 #ifdef CONFIG_HEARTBEAT
   mach_heartbeat = amiga_heartbeat;
 #endif
diff --git a/arch/ppc/boot/Makefile b/arch/ppc/boot/Makefile
index 8c1d7eb8b..995f89bb0 100644
--- a/arch/ppc/boot/Makefile
+++ b/arch/ppc/boot/Makefile
@@ -23,12 +23,12 @@ subdir-$(CONFIG_PPC_OF)		+= of1275
 # for cleaning
 subdir-				+= simple openfirmware
 
-host-progs := $(addprefix utils/, addnote mknote hack-coff mkprep mkbugboot mktree)
+hostprogs-y := $(addprefix utils/, addnote mknote hack-coff mkprep mkbugboot mktree)
 
 .PHONY: $(BOOT_TARGETS) $(bootdir-y)
 
 $(BOOT_TARGETS): $(bootdir-y)
 
 $(bootdir-y): $(addprefix $(obj)/,$(subdir-y)) \
-		$(addprefix $(obj)/,$(host-progs))
+		$(addprefix $(obj)/,$(hostprogs-y))
 	$(Q)$(MAKE) $(build)=$(obj)/$@ $(MAKECMDGOALS)
diff --git a/arch/ppc/boot/common/misc-common.c b/arch/ppc/boot/common/misc-common.c
index 868fa81b7..7acd03b31 100644
--- a/arch/ppc/boot/common/misc-common.c
+++ b/arch/ppc/boot/common/misc-common.c
@@ -17,7 +17,7 @@
 #include <stdarg.h>	/* for va_ bits */
 #include <linux/config.h>
 #include <linux/string.h>
-#include "zlib.h"
+#include <linux/zlib.h>
 #include "nonstdio.h"
 
 /* If we're on a PReP, assume we have a keyboard controller
@@ -202,11 +202,10 @@ void error(char *x)
 	while(1);	/* Halt */
 }
 
-void *zalloc(void *x, unsigned items, unsigned size)
+static void *zalloc(unsigned size)
 {
 	void *p = avail_ram;
 
-	size *= items;
 	size = (size + 7) & -8;
 	avail_ram += size;
 	if (avail_ram > end_avail) {
@@ -216,18 +215,12 @@ void *zalloc(void *x, unsigned items, unsigned size)
 	return p;
 }
 
-void zfree(void *x, void *addr, unsigned nb)
-{
-}
-
 #define HEAD_CRC	2
 #define EXTRA_FIELD	4
 #define ORIG_NAME	8
 #define COMMENT		0x10
 #define RESERVED	0xe0
 
-#define DEFLATED	8
-
 void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
 {
 	z_stream s;
@@ -236,7 +229,7 @@ void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
 	/* skip header */
 	i = 10;
 	flags = src[3];
-	if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
+	if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) {
 		puts("bad gzipped data\n");
 		exit();
 	}
@@ -255,24 +248,24 @@ void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
 		exit();
 	}
 
-	s.zalloc = zalloc;
-	s.zfree = zfree;
-	r = inflateInit2(&s, -MAX_WBITS);
+	/* Initialize ourself. */
+	s.workspace = zalloc(zlib_inflate_workspacesize());
+	r = zlib_inflateInit2(&s, -MAX_WBITS);
 	if (r != Z_OK) {
-		puts("inflateInit2 returned "); puthex(r); puts("\n");
+		puts("zlib_inflateInit2 returned "); puthex(r); puts("\n");
 		exit();
 	}
 	s.next_in = src + i;
 	s.avail_in = *lenp - i;
 	s.next_out = dst;
 	s.avail_out = dstlen;
-	r = inflate(&s, Z_FINISH);
+	r = zlib_inflate(&s, Z_FINISH);
 	if (r != Z_OK && r != Z_STREAM_END) {
 		puts("inflate returned "); puthex(r); puts("\n");
 		exit();
 	}
 	*lenp = s.next_out - (unsigned char *) dst;
-	inflateEnd(&s);
+	zlib_inflateEnd(&s);
 }
 
 void
@@ -526,6 +519,11 @@ _dump_buf(unsigned char *p, int s)
  * on others it's an offset from a given location. -- Tom
  */
 
+void ISA_init(unsigned long base)
+{
+	ISA_io = (unsigned char *)base;
+}
+
 void
 outb(int port, unsigned char val)
 {
diff --git a/arch/ppc/boot/common/ns16550.c b/arch/ppc/boot/common/ns16550.c
index 8eb07a63f..9017c547a 100644
--- a/arch/ppc/boot/common/ns16550.c
+++ b/arch/ppc/boot/common/ns16550.c
@@ -5,14 +5,14 @@
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/serial.h>
-#include <linux/serialP.h>
 #include <linux/serial_reg.h>
 #include <asm/serial.h>
 
+#include "nonstdio.h"
+#include "serial.h"
+
 #define SERIAL_BAUD	9600
 
-extern void outb(int port, unsigned char val);
-extern unsigned char inb(int port);
 extern unsigned long ISA_io;
 
 static struct serial_state rs_table[RS_TABLE_SIZE] = {
diff --git a/arch/ppc/boot/common/serial_stub.c b/arch/ppc/boot/common/serial_stub.c
index 2dc176ed0..03dfaa01f 100644
--- a/arch/ppc/boot/common/serial_stub.c
+++ b/arch/ppc/boot/common/serial_stub.c
@@ -11,11 +11,6 @@
  * is" without any warranty of any kind, whether express or implied.
  */
 
-void __attribute__ ((weak))
-serial_fixups(void)
-{
-}
-
 unsigned long __attribute__ ((weak))
 serial_init(int chan, void *ignored)
 {
diff --git a/arch/ppc/boot/common/util.S b/arch/ppc/boot/common/util.S
index 93771e298..7c4fb8f57 100644
--- a/arch/ppc/boot/common/util.S
+++ b/arch/ppc/boot/common/util.S
@@ -41,7 +41,7 @@ disable_6xx_mmu:
 	/* Test for a 601 */
 	mfpvr	r10
 	srwi	r10,r10,16
-	cmpi	0,r10,1		/* 601 ? */
+	cmpwi	0,r10,1		/* 601 ? */
 	beq	.clearbats_601
 
 	/* Clear BATs */
@@ -117,9 +117,9 @@ _setup_L2CR:
 	/* Wait for the invalidation to complete */
 	mfspr   r8,PVR
 	srwi    r8,r8,16
-	cmpli	cr0,r8,0x8000			/* 7450 */
-	cmpli	cr1,r8,0x8001			/* 7455 */
-	cmpli	cr2,r8,0x8002			/* 7457 */
+	cmplwi	cr0,r8,0x8000			/* 7450 */
+	cmplwi	cr1,r8,0x8001			/* 7455 */
+	cmplwi	cr2,r8,0x8002			/* 7457 */
 	cror	4*cr0+eq,4*cr0+eq,4*cr1+eq	/* Now test if any are true. */
 	cror	4*cr0+eq,4*cr0+eq,4*cr2+eq
 	bne     2f
@@ -190,7 +190,7 @@ timebase_period_ns:
 udelay:
 	mfspr	r4,PVR
 	srwi	r4,r4,16
-	cmpi	0,r4,1		/* 601 ? */
+	cmpwi	0,r4,1		/* 601 ? */
 	bne	.udelay_not_601
 00:	li	r0,86	/* Instructions / microsecond? */
 	mtctr	r0
@@ -213,16 +213,16 @@ udelay:
 1:	mftbu	r5
 	mftb	r6
 	mftbu	r7
-	cmp	0,r5,r7
+	cmpw	0,r5,r7
 	bne	1b		/* Get [synced] base time */
 	addc	r9,r6,r4	/* Compute end time */
 	addze	r8,r5
 2:	mftbu	r5
-	cmp	0,r5,r8
+	cmpw	0,r5,r8
 	blt	2b
 	bgt	3f
 	mftb	r6
-	cmp	0,r6,r9
+	cmpw	0,r6,r9
 	blt	2b
 3:	blr
 
diff --git a/arch/ppc/boot/include/nonstdio.h b/arch/ppc/boot/include/nonstdio.h
index 7a0f027f9..f2b5526fa 100644
--- a/arch/ppc/boot/include/nonstdio.h
+++ b/arch/ppc/boot/include/nonstdio.h
@@ -30,3 +30,5 @@ extern void puthex(unsigned long val);
 extern void puts(const char *);
 extern void udelay(long delay);
 extern unsigned char inb(int port);
+extern void board_isa_init(void);
+extern void ISA_init(unsigned long base);
diff --git a/arch/ppc/boot/lib/Makefile b/arch/ppc/boot/lib/Makefile
index 97ef7d19e..9d088a566 100644
--- a/arch/ppc/boot/lib/Makefile
+++ b/arch/ppc/boot/lib/Makefile
@@ -4,5 +4,7 @@
 
 CFLAGS_kbd.o	+= -Idrivers/char
 
-lib-y := zlib.o div64.o
+lib-y := $(addprefix ../../../../lib/zlib_inflate/, \
+           infblock.o infcodes.o inffast.o inflate.o inftrees.o infutil.o)
+lib-y += div64.o
 lib-$(CONFIG_VGA_CONSOLE) += vreset.o kbd.o
diff --git a/arch/ppc/boot/openfirmware/coffmain.c b/arch/ppc/boot/openfirmware/coffmain.c
index 94c23c0c9..04ba9d57e 100644
--- a/arch/ppc/boot/openfirmware/coffmain.c
+++ b/arch/ppc/boot/openfirmware/coffmain.c
@@ -12,7 +12,6 @@
 
 #include "nonstdio.h"
 #include "of1275.h"
-#include "zlib.h"
 
 /* Passed from the linker */
 extern char __image_begin, __image_end;
diff --git a/arch/ppc/boot/openfirmware/common.c b/arch/ppc/boot/openfirmware/common.c
index 71195067c..9e6952781 100644
--- a/arch/ppc/boot/openfirmware/common.c
+++ b/arch/ppc/boot/openfirmware/common.c
@@ -7,10 +7,10 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include "zlib.h"
 #include "nonstdio.h"
 #include "of1275.h"
 #include <linux/string.h>
+#include <linux/zlib.h>
 #include <asm/bootinfo.h>
 #include <asm/page.h>
 
@@ -30,12 +30,11 @@ struct memchunk {
 
 static struct memchunk *freechunks;
 
-static void *zalloc(void *x, unsigned items, unsigned size)
+static void *zalloc(unsigned size)
 {
     void *p;
     struct memchunk **mpp, *mp;
 
-    size *= items;
     size = (size + 7) & -8;
     heap_use += size;
     if (heap_use > heap_max)
@@ -57,74 +56,57 @@ static void *zalloc(void *x, unsigned items, unsigned size)
     return p;
 }
 
-static void zfree(void *x, void *addr, unsigned nb)
-{
-    struct memchunk *mp = addr;
-
-    nb = (nb + 7) & -8;
-    heap_use -= nb;
-    if (avail_ram == addr + nb) {
-	avail_ram = addr;
-	return;
-    }
-    mp->size = nb;
-    mp->next = freechunks;
-    freechunks = mp;
-}
-
 #define HEAD_CRC	2
 #define EXTRA_FIELD	4
 #define ORIG_NAME	8
 #define COMMENT		0x10
 #define RESERVED	0xe0
 
-#define DEFLATED	8
-
 void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
 {
-    z_stream s;
-    int r, i, flags;
-
-    /* skip header */
-    i = 10;
-    flags = src[3];
-    if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
-	printf("bad gzipped data\n\r");
-	exit();
-    }
-    if ((flags & EXTRA_FIELD) != 0)
-	i = 12 + src[10] + (src[11] << 8);
-    if ((flags & ORIG_NAME) != 0)
-	while (src[i++] != 0)
-	    ;
-    if ((flags & COMMENT) != 0)
-	while (src[i++] != 0)
-	    ;
-    if ((flags & HEAD_CRC) != 0)
-	i += 2;
-    if (i >= *lenp) {
-	printf("gunzip: ran out of data in header\n\r");
-	exit();
-    }
+	z_stream s;
+	int r, i, flags;
+
+	/* skip header */
+	i = 10;
+	flags = src[3];
+	if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) {
+		printf("bad gzipped data\n\r");
+		exit();
+	}
+	if ((flags & EXTRA_FIELD) != 0)
+		i = 12 + src[10] + (src[11] << 8);
+	if ((flags & ORIG_NAME) != 0)
+		while (src[i++] != 0)
+			;
+	if ((flags & COMMENT) != 0)
+		while (src[i++] != 0)
+			;
+	if ((flags & HEAD_CRC) != 0)
+		i += 2;
+	if (i >= *lenp) {
+		printf("gunzip: ran out of data in header\n\r");
+		exit();
+	}
 
-    s.zalloc = zalloc;
-    s.zfree = zfree;
-    r = inflateInit2(&s, -MAX_WBITS);
-    if (r != Z_OK) {
-	printf("inflateInit2 returned %d\n\r", r);
-	exit();
-    }
-    s.next_in = src + i;
-    s.avail_in = *lenp - i;
-    s.next_out = dst;
-    s.avail_out = dstlen;
-    r = inflate(&s, Z_FINISH);
-    if (r != Z_OK && r != Z_STREAM_END) {
-	printf("inflate returned %d msg: %s\n\r", r, s.msg);
-	exit();
-    }
-    *lenp = s.next_out - (unsigned char *) dst;
-    inflateEnd(&s);
+	/* Initialize ourself. */
+	s.workspace = zalloc(zlib_inflate_workspacesize());
+	r = zlib_inflateInit2(&s, -MAX_WBITS);
+	if (r != Z_OK) {
+		printf("zlib_inflateInit2 returned %d\n\r", r);
+		exit();
+	}
+	s.next_in = src + i;
+	s.avail_in = *lenp - i;
+	s.next_out = dst;
+	s.avail_out = dstlen;
+	r = zlib_inflate(&s, Z_FINISH);
+	if (r != Z_OK && r != Z_STREAM_END) {
+		printf("inflate returned %d msg: %s\n\r", r, s.msg);
+		exit();
+	}
+	*lenp = s.next_out - (unsigned char *) dst;
+	zlib_inflateEnd(&s);
 }
 
 /* Make a bi_rec in OF.  We need to be passed a name for BI_BOOTLOADER_ID,
diff --git a/arch/ppc/boot/openfirmware/misc.S b/arch/ppc/boot/openfirmware/misc.S
index 844c0bca2..ab9e897ca 100644
--- a/arch/ppc/boot/openfirmware/misc.S
+++ b/arch/ppc/boot/openfirmware/misc.S
@@ -16,7 +16,7 @@
 setup_bats:
 	mfpvr	5
 	rlwinm	5,5,16,16,31		/* r3 = 1 for 601, 4 for 604 */
-	cmpi	0,5,1
+	cmpwi	0,5,1
 	li	0,0
 	bne	4f
 	mtibatl	3,0			/* invalidate BAT first */
diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
index e31b7e499..895b55750 100644
--- a/arch/ppc/boot/simple/Makefile
+++ b/arch/ppc/boot/simple/Makefile
@@ -64,6 +64,7 @@ zimageinitrd-$(CONFIG_EBONY)		:= zImage.initrd-TREE
 zimageinitrd-$(CONFIG_OCOTEA)		:= zImage.initrd-TREE
          end-$(CONFIG_OCOTEA)		:= ocotea
   entrypoint-$(CONFIG_OCOTEA)		:= 0x01000000
+     extra.o-$(CONFIG_OCOTEA)		:= pibs.o
 
      extra.o-$(CONFIG_EV64260)		:= direct.o misc-ev64260.o
          end-$(CONFIG_EV64260)		:= ev64260
@@ -73,7 +74,7 @@ zimageinitrd-$(CONFIG_OCOTEA)		:= zImage.initrd-TREE
 zimageinitrd-$(CONFIG_GEMINI)		:= zImage.initrd-STRIPELF
          end-$(CONFIG_GEMINI)		:= gemini
 
-     extra.o-$(CONFIG_K2)		:= legacy.o
+     extra.o-$(CONFIG_K2)		:= prepmap.o
          end-$(CONFIG_K2)		:= k2
    cacheflag-$(CONFIG_K2)		:= -include $(clear_L2_L3)
 
@@ -89,7 +90,7 @@ zimageinitrd-$(motorola)		:= zImage.initrd-PPLUS
          end-$(motorola)		:= pplus
 
 # Overrides previous assingment
-     extra.o-$(CONFIG_PPLUS)		:= legacy.o
+     extra.o-$(CONFIG_PPLUS)		:= prepmap.o
      extra.o-$(CONFIG_LOPEC)		:= mpc10x_memory.o
 
       zimage-$(pcore)			:= zImage-STRIPELF
@@ -100,7 +101,7 @@ zimageinitrd-$(pcore)			:= zImage.initrd-STRIPELF
 
       zimage-$(CONFIG_PPC_PREP)		:= zImage-PPLUS
 zimageinitrd-$(CONFIG_PPC_PREP)		:= zImage.initrd-PPLUS
-     extra.o-$(CONFIG_PPC_PREP)		:= legacy.o
+     extra.o-$(CONFIG_PPC_PREP)		:= prepmap.o
         misc-$(CONFIG_PPC_PREP)		+= misc-prep.o mpc10x_memory.o
          end-$(CONFIG_PPC_PREP)		:= prep
 
diff --git a/arch/ppc/boot/simple/misc-embedded.c b/arch/ppc/boot/simple/misc-embedded.c
index 58e2a92e8..8615d5f22 100644
--- a/arch/ppc/boot/simple/misc-embedded.c
+++ b/arch/ppc/boot/simple/misc-embedded.c
@@ -22,7 +22,6 @@
 #endif
 
 #include "nonstdio.h"
-#include "zlib.h"
 
 /* The linker tells us where the image is. */
 extern char __image_begin, __image_end;
@@ -72,6 +71,14 @@ extern void flush_instruction_cache(void);
 extern void gunzip(void *, int, unsigned char *, int *);
 extern void embed_config(bd_t **bp);
 
+/* Weak function for boards which don't need to build the
+ * board info struct because they are using PPCBoot/U-Boot.
+ */
+void __attribute__ ((weak))
+embed_config(bd_t **bdp)
+{
+}
+
 unsigned long
 load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, bd_t *bp)
 {
diff --git a/arch/ppc/boot/simple/misc-prep.c b/arch/ppc/boot/simple/misc-prep.c
index da29deca4..75380ac41 100644
--- a/arch/ppc/boot/simple/misc-prep.c
+++ b/arch/ppc/boot/simple/misc-prep.c
@@ -88,6 +88,7 @@ load_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
 		ofinit(OFW_interface);
 	}
 
+	board_isa_init();
 #if defined(CONFIG_VGA_CONSOLE)
 	vga_init((unsigned char *)0xC0000000);
 #endif /* CONFIG_VGA_CONSOLE */
diff --git a/arch/ppc/boot/simple/misc-spruce.c b/arch/ppc/boot/simple/misc-spruce.c
index fa181ffb7..d012c3927 100644
--- a/arch/ppc/boot/simple/misc-spruce.c
+++ b/arch/ppc/boot/simple/misc-spruce.c
@@ -26,7 +26,6 @@ extern unsigned long decompress_kernel(unsigned long load_addr, int num_words,
 /* Define some important locations of the Spruce. */
 #define SPRUCE_PCI_CONFIG_ADDR	0xfec00000
 #define SPRUCE_PCI_CONFIG_DATA	0xfec00004
-#define SPRUCE_ISA_IO_BASE	0xf8000000
 
 /* PCI configuration space access routines. */
 unsigned int *pci_config_address = (unsigned int *)SPRUCE_PCI_CONFIG_ADDR;
@@ -86,8 +85,6 @@ void cpc700_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
 	out_le32((unsigned *)pci_config_data, val);
 }
 
-unsigned long isa_io_base = SPRUCE_ISA_IO_BASE;
-
 #define PCNET32_WIO_RDP		0x10
 #define PCNET32_WIO_RAP		0x12
 #define PCNET32_WIO_RESET	0x14
diff --git a/arch/ppc/boot/simple/misc.c b/arch/ppc/boot/simple/misc.c
index f09af4f28..1b2ae8d77 100644
--- a/arch/ppc/boot/simple/misc.c
+++ b/arch/ppc/boot/simple/misc.c
@@ -29,7 +29,6 @@
 #include <asm/reg.h>
 
 #include "nonstdio.h"
-#include "zlib.h"
 
 /* Default cmdline */
 #ifdef CONFIG_CMDLINE
@@ -49,7 +48,9 @@
  * Val Henson has requested that Gemini doesn't wait for the
  * user to edit the cmdline or not.
  */
-#if (defined(CONFIG_SERIAL_8250_CONSOLE) || defined(CONFIG_VGA_CONSOLE)) \
+#if (defined(CONFIG_SERIAL_8250_CONSOLE) \
+	|| defined(CONFIG_VGA_CONSOLE) \
+	|| defined(CONFIG_SERIAL_MPC52xx_CONSOLE)) \
 	&& !defined(CONFIG_GEMINI)
 #define INTERACTIVE_CONSOLE	1
 #endif
@@ -95,9 +96,8 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum)
 #endif
 	char *cp;
 	struct bi_record *rec;
-	unsigned long initrd_loc, TotalMemory = 0;
+	unsigned long initrd_loc = 0, TotalMemory = 0;
 
-	serial_fixups();
 #ifdef CONFIG_SERIAL_8250_CONSOLE
 	com_port = serial_init(0, NULL);
 #endif
@@ -221,7 +221,7 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum)
 	puts("\n");
 
 	puts("Uncompressing Linux...");
-	gunzip(NULL, 0x400000, zimage_start, &zimage_size);
+	gunzip(0x0, 0x400000, zimage_start, &zimage_size);
 	puts("done.\n");
 
 	/* get the bi_rec address */
@@ -268,10 +268,16 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum)
 	return rec;
 }
 
+void __attribute__ ((weak))
+board_isa_init(void)
+{
+}
+
 /* Allow decompress_kernel to be hooked into.  This is the default. */
 void * __attribute__ ((weak))
 load_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
 		void *ign1, void *ign2)
 {
+		board_isa_init();
 		return decompress_kernel(load_addr, num_words, cksum);
 }
diff --git a/arch/ppc/boot/simple/relocate.S b/arch/ppc/boot/simple/relocate.S
index e57d9673e..555a216cc 100644
--- a/arch/ppc/boot/simple/relocate.S
+++ b/arch/ppc/boot/simple/relocate.S
@@ -50,7 +50,7 @@ relocate:
 	 * Check if we need to relocate ourselves to the link addr or were
 	 * we loaded there to begin with.
 	 */
-	cmp	cr0,r3,r4
+	cmpw	cr0,r3,r4
 	beq	start_ldr	/* If 0, we don't need to relocate */
 
 	/* Move this code somewhere safe.  This is max(load + size, end)
@@ -122,7 +122,7 @@ do_relocate:
 	GETSYM(r4, start)
 	mr	r3,r8		/* Get the load addr */
 
-	cmp	cr0,r4,r3	/* If we need to copy from the end, do so */
+	cmpw	cr0,r4,r3	/* If we need to copy from the end, do so */
 	bgt	do_relocate_from_end
 
 do_relocate_from_start:
@@ -165,7 +165,7 @@ start_ldr:
 	subi	r4,r4,4
 	li	r0,0
 50:	stwu	r0,4(r3)
-	cmp	cr0,r3,r4
+	cmpw	cr0,r3,r4
 	bne	50b
 90:	mr	r9,r1		/* Save old stack pointer (in case it matters) */
 	lis	r1,.stack@h
diff --git a/arch/ppc/boot/utils/mkbugboot.c b/arch/ppc/boot/utils/mkbugboot.c
index 8158d8c6f..f6629a28e 100644
--- a/arch/ppc/boot/utils/mkbugboot.c
+++ b/arch/ppc/boot/utils/mkbugboot.c
@@ -1,5 +1,5 @@
 /*
- * arch/ppc/pp3boot/mkbugboot.c
+ * arch/ppc/boot/utils/mkbugboot.c
  *
  * Makes a Motorola PPCBUG ROM bootable image which can be flashed
  * into one of the FLASH banks on a Motorola PowerPlus board.
@@ -21,6 +21,11 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <fcntl.h>
+#ifdef __sun__
+#include <inttypes.h>
+#else
+#include <stdint.h>
+#endif
 
 #ifdef __i386__
 #define cpu_to_be32(x) le32_to_cpu(x)
@@ -49,11 +54,6 @@ unsigned short le16_to_cpu(unsigned short x)
 /* size of read buffer */
 #define SIZE 0x1000
 
-/* typedef long int32_t; */
-typedef unsigned long uint32_t;
-typedef unsigned short uint16_t;
-typedef unsigned char uint8_t;
-
 /* PPCBUG ROM boot header */
 typedef struct bug_boot_header {
   uint8_t	magic_word[4];		/* "BOOT" */
diff --git a/arch/ppc/boot/utils/mktree.c b/arch/ppc/boot/utils/mktree.c
index 7ef98c077..2be22e28f 100644
--- a/arch/ppc/boot/utils/mktree.c
+++ b/arch/ppc/boot/utils/mktree.c
@@ -15,7 +15,11 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <netinet/in.h>
+#ifdef __sun__
+#include <inttypes.h>
+#else
 #include <stdint.h>
+#endif
 
 /* This gets tacked on the front of the image.  There are also a few
  * bytes allocated after the _start label used by the boot rom (see
diff --git a/arch/ppc/configs/mvme5100_defconfig b/arch/ppc/configs/mvme5100_defconfig
index 6e1a38d72..46776b9c1 100644
--- a/arch/ppc/configs/mvme5100_defconfig
+++ b/arch/ppc/configs/mvme5100_defconfig
@@ -1,26 +1,48 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2
+# Wed Sep 22 09:53:26 2004
 #
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_GENERIC_IOMAP=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_EMBEDDED is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -33,24 +55,26 @@ CONFIG_OBSOLETE_MODPARM=y
 CONFIG_KMOD=y
 
 #
-# Platform support
+# Processor
 #
-CONFIG_PPC=y
-CONFIG_PPC32=y
 CONFIG_6xx=y
 # CONFIG_40x is not set
+# CONFIG_44x is not set
 # CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
 # CONFIG_8xx is not set
+# CONFIG_E500 is not set
+CONFIG_ALTIVEC=y
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_STD_MMU=y
 
 #
-# IBM 4xx options
+# Platform options
 #
-# CONFIG_8260 is not set
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_PPC_STD_MMU=y
 # CONFIG_PPC_MULTIPLATFORM is not set
 # CONFIG_APUS is not set
-# CONFIG_WILLOW_2 is not set
+# CONFIG_WILLOW is not set
 # CONFIG_PCORE is not set
 # CONFIG_POWERPMC250 is not set
 # CONFIG_EV64260 is not set
@@ -66,34 +90,30 @@ CONFIG_MVME5100=y
 # CONFIG_K2 is not set
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX8260 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_LITE5200 is not set
 # CONFIG_MVME5100_IPMC761_PRESENT is not set
 # CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
-CONFIG_ALTIVEC=y
-# CONFIG_TAU is not set
-# CONFIG_CPU_FREQ is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="ip=on"
 
 #
-# General setup
+# Bus options
 #
-# CONFIG_HIGHMEM is not set
+CONFIG_GENERIC_ISA_DMA=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-CONFIG_KERNEL_ELF=y
-# CONFIG_BINFMT_MISC is not set
 # CONFIG_PCI_LEGACY_PROC is not set
 # CONFIG_PCI_NAMES is not set
-# CONFIG_HOTPLUG is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-# CONFIG_PPC601_SYNC_FIX is not set
-CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="ip=on"
 
 #
 # Advanced setup
@@ -109,15 +129,29 @@ CONFIG_KERNEL_START=0xc0000000
 CONFIG_TASK_SIZE=0x80000000
 CONFIG_BOOT_LOAD=0x00800000
 
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+
 #
 # Memory Technology Devices (MTD)
 #
 # CONFIG_MTD is not set
 
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
 #
 # Plug and Play support
 #
-# CONFIG_PNP is not set
 
 #
 # Block devices
@@ -129,46 +163,46 @@ CONFIG_BOOT_LOAD=0x00800000
 # CONFIG_BLK_DEV_UMEM is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
 
 #
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# ATA/IDE/MFM/RLL support
+# ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
-
-#
-# IDE, ATA and ATAPI Block devices
-#
 CONFIG_BLK_DEV_IDE=y
 
 #
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_IDE_SATA is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
 # CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
 
 #
 # IDE chipset support/bugfixes
 #
+CONFIG_IDE_GENERIC=y
 # CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
 
 #
-# SCSI support
+# SCSI device support
 #
 CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
 
 #
 # SCSI support type (disk, tape, CD-ROM)
@@ -184,64 +218,70 @@ CONFIG_BLK_DEV_SR=y
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 # CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_REPORT_LUNS is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+
 #
 # SCSI low-level drivers
 #
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AACRAID is not set
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_DPT_I2O is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_AM53C974 is not set
-# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
-# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_NCR53C7xx is not set
-# CONFIG_SCSI_SYM53C8XX_2 is not set
-# CONFIG_SCSI_NCR53C8XX is not set
-CONFIG_SCSI_SYM53C8XX=y
-CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
-CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
-CONFIG_SCSI_NCR53C8XX_SYNC=20
-# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
-# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
-# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set
-# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=8
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=32
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA6322 is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
 #
 # Fusion MPT device support
 #
 # CONFIG_FUSION is not set
 
 #
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+# IEEE 1394 (FireWire) support
 #
 # CONFIG_IEEE1394 is not set
 
@@ -250,6 +290,10 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20
 #
 # CONFIG_I2O is not set
 
+#
+# Macintosh device drivers
+#
+
 #
 # Networking support
 #
@@ -261,86 +305,90 @@ CONFIG_NET=y
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 # CONFIG_NETLINK_DEV is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
 # 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_INET_ECN 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_TUNNEL=m
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
 
 #
 # IP: Netfilter Configuration
 #
 CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
 CONFIG_IP_NF_FTP=m
 CONFIG_IP_NF_IRC=m
-# CONFIG_IP_NF_TFTP is not set
-# CONFIG_IP_NF_AMANDA is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
 # CONFIG_IP_NF_QUEUE is not set
 CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
+# CONFIG_IP_NF_MATCH_LIMIT is not set
+# CONFIG_IP_NF_MATCH_IPRANGE is not set
+# CONFIG_IP_NF_MATCH_MAC is not set
+# CONFIG_IP_NF_MATCH_PKTTYPE is not set
+# CONFIG_IP_NF_MATCH_MARK is not set
+# CONFIG_IP_NF_MATCH_MULTIPORT 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_DSCP is not set
+# CONFIG_IP_NF_MATCH_AH_ESP is not set
+# CONFIG_IP_NF_MATCH_LENGTH is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+# CONFIG_IP_NF_MATCH_TCPMSS is not set
 CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_UNCLEAN=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_MIRROR=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-# CONFIG_IP_NF_NAT_LOCAL is not set
-# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_MATCH_STATE is not set
+# CONFIG_IP_NF_MATCH_CONNTRACK is not set
+# CONFIG_IP_NF_MATCH_OWNER is not set
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_REALM is not set
+# CONFIG_IP_NF_MATCH_SCTP is not set
+# CONFIG_IP_NF_FILTER is not set
 # CONFIG_IP_NF_TARGET_LOG is not set
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
+# CONFIG_IP_NF_TARGET_ULOG is not set
+# CONFIG_IP_NF_TARGET_TCPMSS is not set
+# CONFIG_IP_NF_NAT is not set
+# CONFIG_IP_NF_MANGLE is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
 # CONFIG_IP_NF_COMPAT_IPFWADM is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
 
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
 # CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_NET_DIVERT is not set
@@ -352,29 +400,33 @@ CONFIG_IPV6_SCTP__=y
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 
 #
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-# CONFIG_OAKNET is not set
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
@@ -382,17 +434,26 @@ CONFIG_MII=y
 #
 # Tulip family network device support
 #
-# CONFIG_NET_TULIP is not set
+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_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 is not set
+# CONFIG_FORCEDETH is not set
 # CONFIG_DGRS is not set
-CONFIG_EEPRO100=y
-# CONFIG_EEPRO100_PIO is not set
-# CONFIG_E100 is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_E100_NAPI is not set
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
@@ -403,6 +464,7 @@ CONFIG_EEPRO100=y
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -421,52 +483,39 @@ CONFIG_EEPRO100=y
 # Ethernet (10000 Mbit)
 #
 # CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
+# CONFIG_S2IO is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Token Ring devices
 #
-# CONFIG_NET_RADIO is not set
+# CONFIG_TR is not set
 
 #
-# Token Ring devices (depends on LLC=y)
+# Wireless LAN (non-hamradio)
 #
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
+# CONFIG_NET_RADIO is not set
 
 #
 # Wan interfaces
 #
 # CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
 
 #
 # ISDN subsystem
 #
-# CONFIG_ISDN_BOOL is not set
+# CONFIG_ISDN is not set
 
 #
-# Graphics support
+# Telephony Support
 #
-# CONFIG_FB is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
+# CONFIG_PHONE is not set
 
 #
 # Input device support
@@ -483,18 +532,16 @@ CONFIG_EEPRO100=y
 # CONFIG_GAMEPORT is not set
 CONFIG_SOUND_GAMEPORT=y
 # CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
 
 #
 # Input Device Drivers
 #
 
-#
-# Macintosh device drivers
-#
-
 #
 # Character devices
 #
+# CONFIG_VT is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -502,6 +549,7 @@ CONFIG_SOUND_GAMEPORT=y
 #
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
 
 #
@@ -510,27 +558,8 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
 
 #
 # IPMI
@@ -551,11 +580,23 @@ CONFIG_GEN_RTC=y
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_FTAPE is not set
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
 
 #
 # Multimedia devices
@@ -567,6 +608,26 @@ CONFIG_GEN_RTC=y
 #
 # CONFIG_DVB is not set
 
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
 #
 # File systems
 #
@@ -592,17 +653,20 @@ CONFIG_EXT2_FS=y
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
 # CONFIG_NTFS_FS is not set
 
 #
 # Pseudo filesystems
 #
 CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
 # CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
 # CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
 #
@@ -611,6 +675,7 @@ CONFIG_RAMFS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
@@ -625,19 +690,21 @@ CONFIG_RAMFS=y
 # Network File Systems
 #
 CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+CONFIG_NFS_V3=y
 # CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
 # CONFIG_EXPORTFS is not set
 CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
 # CONFIG_AFS_FS is not set
 
 #
@@ -647,31 +714,26 @@ CONFIG_SUNRPC=y
 CONFIG_MSDOS_PARTITION=y
 
 #
-# Sound
+# Native Language Support
 #
-# CONFIG_SOUND is not set
+# CONFIG_NLS is not set
 
 #
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
+# Library routines
 #
-# CONFIG_BT is not set
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
 
 #
-# Library routines
+# Profiling support
 #
-# CONFIG_CRC32 is not set
+# CONFIG_PROFILING is not set
 
 #
 # Kernel hacking
 #
 # CONFIG_DEBUG_KERNEL is not set
-# CONFIG_KALLSYMS is not set
 
 #
 # Security options
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index 2531070a6..94e0b41d6 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -9,7 +9,7 @@ extra-$(CONFIG_E500)		:= head_e500.o
 extra-$(CONFIG_8xx)		:= head_8xx.o
 extra-$(CONFIG_6xx)		+= idle_6xx.o
 extra-$(CONFIG_POWER4)		+= idle_power4.o
-extra-y				+= vmlinux.lds.s
+extra-y				+= vmlinux.lds
 
 obj-y				:= entry.o traps.o irq.o idle.o time.o misc.o \
 					process.o signal.o ptrace.o align.o \
diff --git a/arch/ppc/kernel/align.c b/arch/ppc/kernel/align.c
index 39f51985e..c7d99f033 100644
--- a/arch/ppc/kernel/align.c
+++ b/arch/ppc/kernel/align.c
@@ -37,6 +37,7 @@ struct aligninfo {
 #define U	0x10	/* update index register */
 #define M	0x20	/* multiple load/store */
 #define S	0x40	/* single-precision fp, or byte-swap value */
+#define SX	0x40	/* byte count in XER */
 #define HARD	0x80	/* string, stwcx. */
 
 #define DCBZ	0x5f	/* 8xx/82xx dcbz faults when cache not enabled */
@@ -88,10 +89,10 @@ static struct aligninfo aligninfo[128] = {
 	INVALID,		/* 01 0 0101: lwax */
 	INVALID,		/* 01 0 0110 */
 	INVALID,		/* 01 0 0111 */
-	{ 0, LD+HARD },		/* 01 0 1000: lswx */
-	{ 0, LD+HARD },		/* 01 0 1001: lswi */
-	{ 0, ST+HARD },		/* 01 0 1010: stswx */
-	{ 0, ST+HARD },		/* 01 0 1011: stswi */
+	{ 4, LD+M+HARD+SX },	/* 01 0 1000: lswx */
+	{ 4, LD+M+HARD },	/* 01 0 1001: lswi */
+	{ 4, ST+M+HARD+SX },	/* 01 0 1010: stswx */
+	{ 4, ST+M+HARD },	/* 01 0 1011: stswi */
 	INVALID,		/* 01 0 1100 */
 	INVALID,		/* 01 0 1101 */
 	INVALID,		/* 01 0 1110 */
@@ -189,7 +190,9 @@ fix_alignment(struct pt_regs *regs)
 #endif
 	int i, t;
 	int reg, areg;
+	int offset, nb0;
 	unsigned char __user *addr;
+	unsigned char *rptr;
 	union {
 		long l;
 		float f;
@@ -206,7 +209,8 @@ fix_alignment(struct pt_regs *regs)
 	 * an alignment fault.  -- paulus
 	 */
 
-	instr = *((unsigned int *)regs->nip);
+	if (__get_user(instr, (unsigned int __user *) regs->nip))
+		return 0;
 	opcode = OPCD(instr);
 	reg = RS(instr);
 	areg = RA(instr);
@@ -230,7 +234,7 @@ fix_alignment(struct pt_regs *regs)
 
 	nb = aligninfo[instr].len;
 	if (nb == 0) {
-		long *p;
+		long __user *p;
 		int i;
 
 		if (instr != DCBZ)
@@ -242,13 +246,19 @@ fix_alignment(struct pt_regs *regs)
 		 * case when we are running with the cache disabled
 		 * for debugging.
 		 */
-		p = (long *) (regs->dar & -L1_CACHE_BYTES);
+		p = (long __user *) (regs->dar & -L1_CACHE_BYTES);
+		if (user_mode(regs)
+		    && verify_area(VERIFY_WRITE, p, L1_CACHE_BYTES))
+			return -EFAULT;
 		for (i = 0; i < L1_CACHE_BYTES / sizeof(long); ++i)
-			p[i] = 0;
+			if (__put_user(0, p+i))
+				return -EFAULT;
 		return 1;
 	}
 
 	flags = aligninfo[instr].flags;
+	if ((flags & (LD|ST)) == 0)
+		return 0;
 
 	/* For the 4xx-family & Book-E processors, the 'dar' field of the
 	 * pt_regs structure is overloaded and is really from the DEAR.
@@ -256,6 +266,66 @@ fix_alignment(struct pt_regs *regs)
 
 	addr = (unsigned char __user *)regs->dar;
 
+	if (flags & M) {
+		/* lmw, stmw, lswi/x, stswi/x */
+		nb0 = 0;
+		if (flags & HARD) {
+			if (flags & SX) {
+				nb = regs->xer & 127;
+				if (nb == 0)
+					return 1;
+			} else {
+				if (__get_user(instr,
+					    (unsigned int __user *)regs->nip))
+					return 0;
+				nb = (instr >> 11) & 0x1f;
+				if (nb == 0)
+					nb = 32;
+			}
+			if (nb + reg * 4 > 128) {
+				nb0 = nb + reg * 4 - 128;
+				nb = 128 - reg * 4;
+			}
+		} else {
+			/* lwm, stmw */
+			nb = (32 - reg) * 4;
+		}
+		rptr = (unsigned char *) &regs->gpr[reg];
+		if (flags & LD) {
+			for (i = 0; i < nb; ++i)
+				if (__get_user(rptr[i], addr+i))
+					return -EFAULT;
+			if (nb0 > 0) {
+				rptr = (unsigned char *) &regs->gpr[0];
+				addr += nb;
+				for (i = 0; i < nb0; ++i)
+					if (__get_user(rptr[i], addr+i))
+						return -EFAULT;
+			}
+			for (; (i & 3) != 0; ++i)
+				rptr[i] = 0;
+		} else {
+			for (i = 0; i < nb; ++i)
+				if (__put_user(rptr[i], addr+i))
+					return -EFAULT;
+			if (nb0 > 0) {
+				rptr = (unsigned char *) &regs->gpr[0];
+				addr += nb;
+				for (i = 0; i < nb0; ++i)
+					if (__put_user(rptr[i], addr+i))
+						return -EFAULT;
+			}
+		}
+		return 1;
+	}
+
+	offset = 0;
+	if (nb < 4) {
+		/* read/write the least significant bits */
+		data.l = 0;
+		offset = 4 - nb;
+	}
+
 	/* Verify the address of the operand */
 	if (user_mode(regs)) {
 		if (verify_area((flags & ST? VERIFY_WRITE: VERIFY_READ), addr, nb))
@@ -268,45 +338,26 @@ fix_alignment(struct pt_regs *regs)
 			giveup_fpu(current);
 		preempt_enable();
 	}
-	if (flags & M)
-		return 0;		/* too hard for now */
 
-	/* If we read the operand, copy it in */
+	/* If we read the operand, copy it in, else get register values */
 	if (flags & LD) {
-		if (nb == 2) {
-			data.v[0] = data.v[1] = 0;
-			if (__get_user(data.v[2], addr)
-			    || __get_user(data.v[3], addr+1))
+		for (i = 0; i < nb; ++i)
+			if (__get_user(data.v[offset+i], addr+i))
 				return -EFAULT;
-		} else {
-			for (i = 0; i < nb; ++i)
-				if (__get_user(data.v[i], addr+i))
-					return -EFAULT;
-		}
+	} else if (flags & F) {
+		data.d = current->thread.fpr[reg];
+	} else {
+		data.l = regs->gpr[reg];
 	}
 
 	switch (flags & ~U) {
-	case LD+SE:
+	case LD+SE:	/* sign extend */
 		if (data.v[2] >= 0x80)
 			data.v[0] = data.v[1] = -1;
-		/* fall through */
-	case LD:
-		regs->gpr[reg] = data.l;
-		break;
-	case LD+S:
-		if (nb == 2) {
-			SWAP(data.v[2], data.v[3]);
-		} else {
-			SWAP(data.v[0], data.v[3]);
-			SWAP(data.v[1], data.v[2]);
-		}
-		regs->gpr[reg] = data.l;
-		break;
-	case ST:
-		data.l = regs->gpr[reg];
 		break;
+
+	case LD+S:	/* byte-swap */
 	case ST+S:
-		data.l = regs->gpr[reg];
 		if (nb == 2) {
 			SWAP(data.v[2], data.v[3]);
 		} else {
@@ -314,50 +365,34 @@ fix_alignment(struct pt_regs *regs)
 			SWAP(data.v[1], data.v[2]);
 		}
 		break;
-	case LD+F:
-		current->thread.fpr[reg] = data.d;
-		break;
-	case ST+F:
-		data.d = current->thread.fpr[reg];
-		break;
-	/* these require some floating point conversions... */
-	/* we'd like to use the assignment, but we have to compile
-	 * the kernel with -msoft-float so it doesn't use the
-	 * fp regs for copying 8-byte objects. */
+
+	/* Single-precision FP load and store require conversions... */
 	case LD+F+S:
 		preempt_disable();
 		enable_kernel_fp();
-		cvt_fd(&data.f, &current->thread.fpr[reg], &current->thread.fpscr);
-		/* current->thread.fpr[reg] = data.f; */
+		cvt_fd(&data.f, &data.d, &current->thread.fpscr);
 		preempt_enable();
 		break;
 	case ST+F+S:
 		preempt_disable();
 		enable_kernel_fp();
-		cvt_df(&current->thread.fpr[reg], &data.f, &current->thread.fpscr);
-		/* data.f = current->thread.fpr[reg]; */
+		cvt_df(&data.d, &data.f, &current->thread.fpscr);
 		preempt_enable();
 		break;
-	default:
-		printk("align: can't handle flags=%x\n", flags);
-		return 0;
 	}
 
 	if (flags & ST) {
-		if (nb == 2) {
-			if (__put_user(data.v[2], addr)
-			    || __put_user(data.v[3], addr+1))
+		for (i = 0; i < nb; ++i)
+			if (__put_user(data.v[offset+i], addr+i))
 				return -EFAULT;
-		} else {
-			for (i = 0; i < nb; ++i)
-				if (__put_user(data.v[i], addr+i))
-					return -EFAULT;
-		}
+	} else if (flags & F) {
+		current->thread.fpr[reg] = data.d;
+	} else {
+		regs->gpr[reg] = data.l;
 	}
 
-	if (flags & U) {
+	if (flags & U)
 		regs->gpr[areg] = regs->dar;
-	}
 
 	return 1;
 }
diff --git a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c
index 1999a42d8..946ea9922 100644
--- a/arch/ppc/kernel/asm-offsets.c
+++ b/arch/ppc/kernel/asm-offsets.c
@@ -129,6 +129,13 @@ main(void)
 	DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features));
 	DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
 
+	DEFINE(TI_TASK, offsetof(struct thread_info, task));
+	DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
+	DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+	DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
+	DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
+	DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
+
 	DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28);
 	return 0;
 }
diff --git a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/ppc/kernel/cpu_setup_6xx.S
index ee0705c6e..e42049f3e 100644
--- a/arch/ppc/kernel/cpu_setup_6xx.S
+++ b/arch/ppc/kernel/cpu_setup_6xx.S
@@ -172,9 +172,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
 setup_750cx:
 	mfspr	r10, SPRN_HID1
 	rlwinm	r10,r10,4,28,31
-	cmpi	cr0,r10,7
-	cmpi	cr1,r10,9
-	cmpi	cr2,r10,11
+	cmpwi	cr0,r10,7
+	cmpwi	cr1,r10,9
+	cmpwi	cr2,r10,11
 	cror	4*cr0+eq,4*cr0+eq,4*cr1+eq
 	cror	4*cr0+eq,4*cr0+eq,4*cr2+eq
 	bnelr
@@ -218,10 +218,10 @@ setup_745x_specifics:
 
 	/* All of the bits we have to set.....
 	 */
-	ori	r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE | HID0_LRSTK
+	ori	r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE | HID0_LRSTK | HID0_BTIC
 BEGIN_FTR_SECTION
-	ori	r11,r11,HID0_BTIC
-END_FTR_SECTION_IFCLR(CPU_FTR_NO_BTIC)
+	xori	r11,r11,HID0_BTIC
+END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC)
 BEGIN_FTR_SECTION
 	oris	r11,r11,HID0_DPM@h	/* enable dynamic power mgmt */
 END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
@@ -287,12 +287,12 @@ _GLOBAL(__save_cpu_setup)
 	/* Now deal with CPU type dependent registers */
 	mfspr	r3,PVR
 	srwi	r3,r3,16
-	cmpli	cr0,r3,0x8000	/* 7450 */
-	cmpli	cr1,r3,0x000c	/* 7400 */
-	cmpli	cr2,r3,0x800c	/* 7410 */
-	cmpli	cr3,r3,0x8001	/* 7455 */
-	cmpli	cr4,r3,0x8002	/* 7457 */
-	cmpli	cr5,r3,0x7000	/* 750FX */
+	cmplwi	cr0,r3,0x8000	/* 7450 */
+	cmplwi	cr1,r3,0x000c	/* 7400 */
+	cmplwi	cr2,r3,0x800c	/* 7410 */
+	cmplwi	cr3,r3,0x8001	/* 7455 */
+	cmplwi	cr4,r3,0x8002	/* 7457 */
+	cmplwi	cr5,r3,0x7000	/* 750FX */
 	/* cr1 is 7400 || 7410 */
 	cror	4*cr1+eq,4*cr1+eq,4*cr2+eq
 	/* cr0 is 74xx */
@@ -323,7 +323,7 @@ _GLOBAL(__save_cpu_setup)
 	/* If rev 2.x, backup HID2 */
 	mfspr	r3,PVR
 	andi.	r3,r3,0xff00
-	cmpi	cr0,r3,0x0200
+	cmpwi	cr0,r3,0x0200
 	bne	1f
 	mfspr	r4,SPRN_HID2
 	stw	r4,CS_HID2(r5)
@@ -354,12 +354,12 @@ _GLOBAL(__restore_cpu_setup)
 	/* Now deal with CPU type dependent registers */
 	mfspr	r3,PVR
 	srwi	r3,r3,16
-	cmpli	cr0,r3,0x8000	/* 7450 */
-	cmpli	cr1,r3,0x000c	/* 7400 */
-	cmpli	cr2,r3,0x800c	/* 7410 */
-	cmpli	cr3,r3,0x8001	/* 7455 */
-	cmpli	cr4,r3,0x8002	/* 7457 */
-	cmpli	cr5,r3,0x7000	/* 750FX */
+	cmplwi	cr0,r3,0x8000	/* 7450 */
+	cmplwi	cr1,r3,0x000c	/* 7400 */
+	cmplwi	cr2,r3,0x800c	/* 7410 */
+	cmplwi	cr3,r3,0x8001	/* 7455 */
+	cmplwi	cr4,r3,0x8002	/* 7457 */
+	cmplwi	cr5,r3,0x7000	/* 750FX */
 	/* cr1 is 7400 || 7410 */
 	cror	4*cr1+eq,4*cr1+eq,4*cr2+eq
 	/* cr0 is 74xx */
@@ -412,7 +412,7 @@ _GLOBAL(__restore_cpu_setup)
 	/* If rev 2.x, restore HID2 with low voltage bit cleared */
 	mfspr	r3,PVR
 	andi.	r3,r3,0xff00
-	cmpi	cr0,r3,0x0200
+	cmpwi	cr0,r3,0x0200
 	bne	4f
 	lwz	r4,CS_HID2(r5)
 	rlwinm	r4,r4,0,19,17
@@ -426,7 +426,7 @@ _GLOBAL(__restore_cpu_setup)
 	mftbl	r5
 3:	mftbl	r6
 	sub	r6,r6,r5
-	cmpli	cr0,r6,10000
+	cmplwi	cr0,r6,10000
 	ble	3b
 	/* Setup final PLL */
 	mtspr	SPRN_HID1,r4
diff --git a/arch/ppc/kernel/cpu_setup_power4.S b/arch/ppc/kernel/cpu_setup_power4.S
index 6a6ee985c..f2ea1a990 100644
--- a/arch/ppc/kernel/cpu_setup_power4.S
+++ b/arch/ppc/kernel/cpu_setup_power4.S
@@ -112,7 +112,9 @@ _GLOBAL(__save_cpu_setup)
 	/* We only deal with 970 for now */
 	mfspr	r0,SPRN_PVR
 	srwi	r0,r0,16
-	cmpwi	r0,0x39
+	cmpwi	cr0,r0,0x39
+	cmpwi	cr1,r0,0x3c
+	cror	4*cr0+eq,4*cr0+eq,4*cr1+eq
 	bne	1f
 
 	/* Save HID0,1,4 and 5 */
@@ -144,7 +146,9 @@ _GLOBAL(__restore_cpu_setup)
 	/* We only deal with 970 for now */
 	mfspr	r0,SPRN_PVR
 	srwi	r0,r0,16
-	cmpwi	r0,0x39
+	cmpwi	cr0,r0,0x39
+	cmpwi	cr1,r0,0x3c
+	cror	4*cr0+eq,4*cr0+eq,4*cr1+eq
 	bne	1f
 
 	/* Clear interrupt prefix */
diff --git a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c
index b60fa998b..605afa6c6 100644
--- a/arch/ppc/kernel/cputable.c
+++ b/arch/ppc/kernel/cputable.c
@@ -55,7 +55,7 @@ extern void __setup_cpu_generic(unsigned long offset, int cpu_nr, struct cpu_spe
 #endif
 
 /* We need to mark all pages as being coherent if we're SMP or we
- * have a 754x and an MPC107 host bridge.
+ * have a 74[45]x and an MPC107 host bridge.
  */
 #if defined(CONFIG_SMP) || defined(CONFIG_MPC10X_BRIDGE)
 #define CPU_FTR_COMMON                  CPU_FTR_NEED_COHERENT
@@ -63,6 +63,17 @@ extern void __setup_cpu_generic(unsigned long offset, int cpu_nr, struct cpu_spe
 #define CPU_FTR_COMMON                  0
 #endif
 
+/* The powersave features NAP & DOZE seems to confuse BDI when
+   debugging. So if a BDI is used, disable theses
+ */
+#ifndef CONFIG_BDI_SWITCH
+#define CPU_FTR_MAYBE_CAN_DOZE	CPU_FTR_CAN_DOZE
+#define CPU_FTR_MAYBE_CAN_NAP	CPU_FTR_CAN_NAP
+#else
+#define CPU_FTR_MAYBE_CAN_DOZE	0
+#define CPU_FTR_MAYBE_CAN_NAP	0
+#endif
+
 struct cpu_spec	cpu_specs[] = {
 #if CLASSIC_PPC
     { 	/* 601 */
@@ -76,8 +87,8 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 603 */
     	0xffff0000, 0x00030000, "603",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-    	CPU_FTR_CAN_NAP,
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+    	CPU_FTR_MAYBE_CAN_NAP,
 	COMMON_PPC,
     	32, 32,
 	__setup_cpu_603
@@ -85,8 +96,8 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 603e */
     	0xffff0000, 0x00060000, "603e",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-    	CPU_FTR_CAN_NAP,
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+    	CPU_FTR_MAYBE_CAN_NAP,
 	COMMON_PPC,
 	32, 32,
 	__setup_cpu_603
@@ -94,8 +105,8 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 603ev */
     	0xffff0000, 0x00070000, "603ev",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-    	CPU_FTR_CAN_NAP,
+    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+    	CPU_FTR_MAYBE_CAN_NAP,
 	COMMON_PPC,
 	32, 32,
 	__setup_cpu_603
@@ -139,8 +150,8 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 740/750 (0x4202, don't support TAU ?) */
     	0xffffffff, 0x00084202, "740/750",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-	CPU_FTR_L2CR | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP,
+    	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,
 	COMMON_PPC,
 	32, 32,
 	__setup_cpu_750
@@ -148,8 +159,8 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 745/755 */
     	0xfffff000, 0x00083000, "745/755",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP,
+    	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,
 	COMMON_PPC,
 	32, 32,
 	__setup_cpu_750
@@ -157,8 +168,8 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 750CX (80100 and 8010x?) */
     	0xfffffff0, 0x00080100, "750CX",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP,
+    	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,
 	COMMON_PPC,
 	32, 32,
 	__setup_cpu_750cx
@@ -166,8 +177,8 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 750CX (82201 and 82202) */
     	0xfffffff0, 0x00082200, "750CX",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP,
+    	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,
 	COMMON_PPC,
 	32, 32,
 	__setup_cpu_750cx
@@ -175,8 +186,8 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 750CXe (82214) */
     	0xfffffff0, 0x00082210, "750CXe",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP,
+    	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,
 	COMMON_PPC,
 	32, 32,
 	__setup_cpu_750cx
@@ -184,8 +195,8 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 750FX rev 1.x */
     	0xffffff00, 0x70000100, "750FX",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP |
+    	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,
 	COMMON_PPC,
 	32, 32,
@@ -194,8 +205,8 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 750FX rev 2.0 must disable HID0[DPM] */
     	0xffffffff, 0x70000200, "750FX",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP |
+    	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,
 	COMMON_PPC,
 	32, 32,
@@ -204,8 +215,8 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 750FX (All revs except 2.0) */
     	0xffff0000, 0x70000000, "750FX",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP |
+    	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,
 	COMMON_PPC,
 	32, 32,
@@ -213,8 +224,8 @@ struct cpu_spec	cpu_specs[] = {
     },
     {	/* 750GX */
     	0xffff0000, 0x70020000, "750GX",
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP |
+    	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,
 	COMMON_PPC,
 	32, 32,
@@ -223,8 +234,8 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 740/750 (L2CR bit need fixup for 740) */
     	0xffff0000, 0x00080000, "740/750",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP,
+    	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,
 	COMMON_PPC,
 	32, 32,
 	__setup_cpu_750
@@ -232,9 +243,9 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 7400 rev 1.1 ? (no TAU) */
     	0xffffffff, 0x000c1101, "7400 (1.1)",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
+    	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_CAN_NAP,
+	CPU_FTR_MAYBE_CAN_NAP,
 	COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
 	32, 32,
 	__setup_cpu_7400
@@ -242,9 +253,9 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 7400 */
     	0xffff0000, 0x000c0000, "7400",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
+    	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_CAN_NAP,
+	CPU_FTR_MAYBE_CAN_NAP,
 	COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
 	32, 32,
 	__setup_cpu_7400
@@ -252,9 +263,9 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 7410 */
     	0xffff0000, 0x800c0000, "7410",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
+    	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_CAN_NAP,
+	CPU_FTR_MAYBE_CAN_NAP,
 	COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP,
 	32, 32,
 	__setup_cpu_7410
@@ -272,7 +283,7 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 7450 2.1 */
     	0xffffffff, 0x80000201, "7450",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+    	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,
@@ -283,7 +294,7 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 7450 2.3 and newer */
     	0xffff0000, 0x80000000, "7450",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+    	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,
@@ -305,7 +316,7 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 7455 rev 2.0 */
     	0xffffffff, 0x80010200, "7455",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+    	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,
@@ -316,7 +327,7 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 7455 others */
     	0xffff0000, 0x80010000, "7455",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+    	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,
@@ -327,7 +338,7 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 7447/7457 Rev 1.0 */
     	0xffffffff, 0x80020100, "7447/7457",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+    	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,
@@ -338,7 +349,7 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 7447/7457 Rev 1.1 */
     	0xffffffff, 0x80020101, "7447/7457",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+    	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,
@@ -349,7 +360,7 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 7447/7457 Rev 1.2 and later */
     	0xffff0000, 0x80020000, "7447/7457",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+    	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,
@@ -360,7 +371,7 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 7447A */
     	0xffff0000, 0x80030000, "7447A",
 	CPU_FTR_COMMON |
-    	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
+    	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,
@@ -371,15 +382,15 @@ struct cpu_spec	cpu_specs[] = {
     {	/* 82xx (8240, 8245, 8260 are all 603e cores) */
 	0x7fff0000, 0x00810000, "82xx",
 	CPU_FTR_COMMON |
-	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB,
+	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB,
 	COMMON_PPC,
 	32, 32,
 	__setup_cpu_603
     },
     {	/* All G2_LE (603e core, plus some) have the same pvr */
 	0x7fff0000, 0x00820000, "G2_LE",
-	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB |
-	CPU_FTR_CAN_NAP | CPU_FTR_HAS_HIGH_BATS,
+	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+	CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS,
 	COMMON_PPC,
 	32, 32,
 	__setup_cpu_603
@@ -440,7 +451,16 @@ struct cpu_spec	cpu_specs[] = {
 	0xffff0000, 0x00390000, "PPC970",
 	CPU_FTR_COMMON |
 	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
-	CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP,
+	CPU_FTR_ALTIVEC_COMP | CPU_FTR_MAYBE_CAN_NAP,
+	COMMON_PPC | PPC_FEATURE_64 | PPC_FEATURE_ALTIVEC_COMP,
+	128, 128,
+	__setup_cpu_ppc970
+    },
+    {	/* PPC970FX */
+	0xffff0000, 0x003c0000, "PPC970FX",
+	CPU_FTR_COMMON |
+	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+	CPU_FTR_ALTIVEC_COMP | CPU_FTR_MAYBE_CAN_NAP,
 	COMMON_PPC | PPC_FEATURE_64 | PPC_FEATURE_ALTIVEC_COMP,
 	128, 128,
 	__setup_cpu_ppc970
@@ -449,7 +469,8 @@ struct cpu_spec	cpu_specs[] = {
 #ifdef CONFIG_8xx
     {	/* 8xx */
     	0xffff0000, 0x00500000, "8xx",
-		/* CPU_FTR_CAN_DOZE is possible, if the 8xx code is there.... */
+		/* CPU_FTR_MAYBE_CAN_DOZE is possible,
+		 * if the 8xx code is there.... */
     	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
     	PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
  	16, 16,
@@ -590,7 +611,7 @@ struct cpu_spec	cpu_specs[] = {
 #ifdef CONFIG_E500
     { /* e500 */
         0xffff0000, 0x80200000, "e500",
-	/* xxx - galak: add CPU_FTR_CAN_DOZE */
+	/* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
         CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB,
         PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
         32, 32,
diff --git a/arch/ppc/kernel/dma-mapping.c b/arch/ppc/kernel/dma-mapping.c
index 54f9a3e75..334b8bfdc 100644
--- a/arch/ppc/kernel/dma-mapping.c
+++ b/arch/ppc/kernel/dma-mapping.c
@@ -41,11 +41,11 @@
 #include <linux/bootmem.h>
 #include <linux/highmem.h>
 #include <linux/dma-mapping.h>
+#include <linux/hardirq.h>
 
 #include <asm/pgalloc.h>
 #include <asm/prom.h>
 #include <asm/io.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
@@ -381,6 +381,7 @@ void __dma_sync(void *vaddr, size_t size, int direction)
 		break;
 	}
 }
+EXPORT_SYMBOL(__dma_sync);
 
 #ifdef CONFIG_HIGHMEM
 /*
@@ -438,3 +439,4 @@ void __dma_sync_page(struct page *page, unsigned long offset,
 	__dma_sync((void *)start, size, direction);
 #endif
 }
+EXPORT_SYMBOL(__dma_sync_page);
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index 4963b79c7..91318c15c 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -206,7 +206,7 @@ _GLOBAL(DoSyscall)
 	andi.	r11,r11,_TIF_SYSCALL_TRACE
 	bne-	syscall_dotrace
 syscall_dotrace_cont:
-	cmpli	0,r0,NR_syscalls
+	cmplwi	0,r0,NR_syscalls
 	lis	r10,sys_call_table@h
 	ori	r10,r10,sys_call_table@l
 	slwi	r0,r0,2
@@ -222,7 +222,7 @@ ret_from_syscall:
 #endif
 	mr	r6,r3
 	li	r11,-_LAST_ERRNO
-	cmpl	0,r3,r11
+	cmplw	0,r3,r11
 	rlwinm	r12,r1,0,0,18	/* current_thread_info() */
 	blt+	30f
 	lwz	r11,TI_LOCAL_FLAGS(r12)
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index 121978c19..3a3e3c742 100644
--- a/arch/ppc/kernel/head.S
+++ b/arch/ppc/kernel/head.S
@@ -800,7 +800,7 @@ load_up_fpu:
 	tophys(r6,0)			/* get __pa constant */
 	addis	r3,r6,last_task_used_math@ha
 	lwz	r4,last_task_used_math@l(r3)
-	cmpi	0,r4,0
+	cmpwi	0,r4,0
 	beq	1f
 	add	r4,r4,r6
 	addi	r4,r4,THREAD		/* want last_task_used_math->thread */
@@ -927,7 +927,7 @@ load_up_altivec:
 	tophys(r6,0)
 	addis	r3,r6,last_task_used_altivec@ha
 	lwz	r4,last_task_used_altivec@l(r3)
-	cmpi	0,r4,0
+	cmpwi	0,r4,0
 	beq	1f
 	add	r4,r4,r6
 	addi	r4,r4,THREAD	/* want THREAD of last_task_used_altivec */
@@ -992,11 +992,11 @@ giveup_altivec:
 	SYNC
 	MTMSRD(r5)			/* enable use of AltiVec now */
 	isync
-	cmpi	0,r3,0
+	cmpwi	0,r3,0
 	beqlr-				/* if no previous owner, done */
 	addi	r3,r3,THREAD		/* want THREAD of task */
 	lwz	r5,PT_REGS(r3)
-	cmpi	0,r5,0
+	cmpwi	0,r5,0
 	SAVE_32VR(0, r4, r3)
 	mfvscr	vr0
 	li	r4,THREAD_VSCR
@@ -1030,11 +1030,11 @@ giveup_fpu:
 	MTMSRD(r5)			/* enable use of fpu now */
 	SYNC_601
 	isync
-	cmpi	0,r3,0
+	cmpwi	0,r3,0
 	beqlr-				/* if no previous owner, done */
 	addi	r3,r3,THREAD	        /* want THREAD of task */
 	lwz	r5,PT_REGS(r3)
-	cmpi	0,r5,0
+	cmpwi	0,r5,0
 	SAVE_32FPRS(0, r3)
 	mffs	fr0
 	stfd	fr0,THREAD_FPSCR-4(r3)
@@ -1539,7 +1539,7 @@ initial_bats:
 #ifndef CONFIG_PPC64BRIDGE
 	mfspr	r9,PVR
 	rlwinm	r9,r9,16,16,31		/* r9 = 1 for 601, 4 for 604 */
-	cmpi	0,r9,1
+	cmpwi	0,r9,1
 	bne	4f
 	ori	r11,r11,4		/* set up BAT registers for 601 */
 	li	r8,0x7f			/* valid, block length = 8MB */
@@ -1591,7 +1591,7 @@ setup_disp_bat:
 	lwz	r8,4(r8)
 	mfspr	r9,PVR
 	rlwinm	r9,r9,16,16,31		/* r9 = 1 for 601, 4 for 604 */
-	cmpi	0,r9,1
+	cmpwi	0,r9,1
 	beq	1f
 	mtspr	DBAT3L,r8
 	mtspr	DBAT3U,r11
diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S
index f883dc239..73fd71105 100644
--- a/arch/ppc/kernel/head_44x.S
+++ b/arch/ppc/kernel/head_44x.S
@@ -41,16 +41,9 @@
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
 #include <asm/offsets.h>
+#include "head_booke.h"
 
-/*
- * Macros
- */
 
-#define SET_IVOR(vector_number, vector_label)		\
-		li	r26,vector_label@l; 		\
-		mtspr	SPRN_IVOR##vector_number,r26;	\
-		sync
-				
 /* As with the other PowerPC ports, it is expected that when code
  * execution begins here, the following registers contain valid, yet
  * optional, information:
@@ -302,234 +295,6 @@ skpinv:	addi	r4,r4,1				/* Increment */
  * We align on a 32 byte cache line boundary for good measure.
  */
 
-#define NORMAL_EXCEPTION_PROLOG						     \
-	mtspr	SPRN_SPRG0,r10;		/* save two registers to work with */\
-	mtspr	SPRN_SPRG1,r11;						     \
-	mtspr	SPRN_SPRG4W,r1;						     \
-	mfcr	r10;			/* save CR in r10 for now	   */\
-	mfspr	r11,SPRN_SRR1;		/* check whether user or kernel    */\
-	andi.	r11,r11,MSR_PR;						     \
-	beq	1f;							     \
-	mfspr	r1,SPRG3;		/* if from user, start at top of   */\
-	lwz	r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack   */\
-	addi	r1,r1,THREAD_SIZE;					     \
-1:	subi	r1,r1,INT_FRAME_SIZE;	/* Allocate an exception frame     */\
-	tophys(r11,r1);							     \
-	stw	r10,_CCR(r11);          /* save various registers	   */\
-	stw	r12,GPR12(r11);						     \
-	stw	r9,GPR9(r11);						     \
-	mfspr	r10,SPRG0;						     \
-	stw	r10,GPR10(r11);						     \
-	mfspr	r12,SPRG1;						     \
-	stw	r12,GPR11(r11);						     \
-	mflr	r10;							     \
-	stw	r10,_LINK(r11);						     \
-	mfspr	r10,SPRG4R;						     \
-	mfspr	r12,SRR0;						     \
-	stw	r10,GPR1(r11);						     \
-	mfspr	r9,SRR1;						     \
-	stw	r10,0(r11);						     \
-	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
-	stw	r0,GPR0(r11);						     \
-	SAVE_4GPRS(3, r11);						     \
-	SAVE_2GPRS(7, r11)
-
-/*
- * Exception prolog for critical exceptions.  This is a little different
- * from the normal exception prolog above since a critical exception
- * can potentially occur at any point during normal exception processing.
- * Thus we cannot use the same SPRG registers as the normal prolog above.
- * Instead we use a couple of words of memory at low physical addresses.
- * This is OK since we don't support SMP on these processors. For Book E
- * processors, we also have a reserved register (SPRG2) that is only used
- * in critical exceptions so we can free up a GPR to use as the base for
- * indirect access to the critical exception save area.  This is necessary
- * since the MMU is always on and the save area is offset from KERNELBASE.
- */
-#define CRITICAL_EXCEPTION_PROLOG					     \
-	mtspr	SPRG2,r8;		/* SPRG2 only used in criticals */   \
-	lis	r8,crit_save@ha;					     \
-	stw	r10,crit_r10@l(r8);					     \
-	stw	r11,crit_r11@l(r8);					     \
-	mfspr	r10,SPRG0;						     \
-	stw	r10,crit_sprg0@l(r8);					     \
-	mfspr	r10,SPRG1;						     \
-	stw	r10,crit_sprg1@l(r8);					     \
-	mfspr	r10,SPRG4R;						     \
-	stw	r10,crit_sprg4@l(r8);					     \
-	mfspr	r10,SPRG5R;						     \
-	stw	r10,crit_sprg5@l(r8);					     \
-	mfspr	r10,SPRG7R;						     \
-	stw	r10,crit_sprg7@l(r8);					     \
-	mfspr	r10,SPRN_PID;						     \
-	stw	r10,crit_pid@l(r8);					     \
-	mfspr	r10,SRR0;						     \
-	stw	r10,crit_srr0@l(r8);					     \
-	mfspr	r10,SRR1;						     \
-	stw	r10,crit_srr1@l(r8);					     \
-	mfspr	r8,SPRG2;		/* SPRG2 only used in criticals */   \
-	mfcr	r10;			/* save CR in r10 for now	   */\
-	mfspr	r11,SPRN_CSRR1;		/* check whether user or kernel    */\
-	andi.	r11,r11,MSR_PR;						     \
-	lis	r11,critical_stack_top@h;				     \
-	ori	r11,r11,critical_stack_top@l;				     \
-	beq	1f;							     \
-	/* COMING FROM USER MODE */					     \
-	mfspr	r11,SPRG3;		/* if from user, start at top of   */\
-	lwz	r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
-	addi	r11,r11,THREAD_SIZE;					     \
-1:	subi	r11,r11,INT_FRAME_SIZE;	/* Allocate an exception frame     */\
-	stw	r10,_CCR(r11);          /* save various registers	   */\
-	stw	r12,GPR12(r11);						     \
-	stw	r9,GPR9(r11);						     \
-	mflr	r10;							     \
-	stw	r10,_LINK(r11);						     \
-	mfspr	r12,SPRN_DEAR;		/* save DEAR and ESR in the frame  */\
-	stw	r12,_DEAR(r11);		/* since they may have had stuff   */\
-	mfspr	r9,SPRN_ESR;		/* in them at the point where the  */\
-	stw	r9,_ESR(r11);		/* exception was taken		   */\
-	mfspr	r12,CSRR0;						     \
-	stw	r1,GPR1(r11);						     \
-	mfspr	r9,CSRR1;						     \
-	stw	r1,0(r11);						     \
-	tovirt(r1,r11);							     \
-	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
-	stw	r0,GPR0(r11);						     \
-	SAVE_4GPRS(3, r11);						     \
-	SAVE_2GPRS(7, r11)
-
-/*
- * Exception prolog for machine check exceptions.  This is similar to
- * the critical exception prolog, except that machine check exceptions
- * have their own save area.  For Book E processors, we also have a
- * reserved register (SPRG6) that is only used in machine check exceptions
- * so we can free up a GPR to use as the base for indirect access to the
- * machine check exception save area.  This is necessary since the MMU
- * is always on and the save area is offset from KERNELBASE.
- */
-#define MCHECK_EXCEPTION_PROLOG					     \
-	mtspr	SPRG6W,r8;		/* SPRG6 used in machine checks */   \
-	lis	r8,mcheck_save@ha;					     \
-	stw	r10,mcheck_r10@l(r8);					     \
-	stw	r11,mcheck_r11@l(r8);					     \
-	mfspr	r10,SPRG0;						     \
-	stw	r10,mcheck_sprg0@l(r8);					     \
-	mfspr	r10,SPRG1;						     \
-	stw	r10,mcheck_sprg1@l(r8);					     \
-	mfspr	r10,SPRG4R;						     \
-	stw	r10,mcheck_sprg4@l(r8);					     \
-	mfspr	r10,SPRG5R;						     \
-	stw	r10,mcheck_sprg5@l(r8);					     \
-	mfspr	r10,SPRG7R;						     \
-	stw	r10,mcheck_sprg7@l(r8);					     \
-	mfspr	r10,SPRN_PID;						     \
-	stw	r10,mcheck_pid@l(r8);					     \
-	mfspr	r10,SRR0;						     \
-	stw	r10,mcheck_srr0@l(r8);					     \
-	mfspr	r10,SRR1;						     \
-	stw	r10,mcheck_srr1@l(r8);					     \
-	mfspr	r10,CSRR0;						     \
-	stw	r10,mcheck_csrr0@l(r8);					     \
-	mfspr	r10,CSRR1;						     \
-	stw	r10,mcheck_csrr1@l(r8);					     \
-	mfspr	r8,SPRG6R;		/* SPRG6 used in machine checks */   \
-	mfcr	r10;			/* save CR in r10 for now	   */\
-	mfspr	r11,SPRN_MCSRR1;	/* check whether user or kernel    */\
-	andi.	r11,r11,MSR_PR;						     \
-	lis	r11,mcheck_stack_top@h;					     \
-	ori	r11,r11,mcheck_stack_top@l;				     \
-	beq	1f;							     \
-	/* COMING FROM USER MODE */					     \
-	mfspr	r11,SPRG3;		/* if from user, start at top of   */\
-	lwz	r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
-	addi	r11,r11,THREAD_SIZE;					     \
-1:	subi	r11,r11,INT_FRAME_SIZE;	/* Allocate an exception frame     */\
-	stw	r10,_CCR(r11);          /* save various registers	   */\
-	stw	r12,GPR12(r11);						     \
-	stw	r9,GPR9(r11);						     \
-	mflr	r10;							     \
-	stw	r10,_LINK(r11);						     \
-	mfspr	r12,SPRN_DEAR;		/* save DEAR and ESR in the frame  */\
-	stw	r12,_DEAR(r11);		/* since they may have had stuff   */\
-	mfspr	r9,SPRN_ESR;		/* in them at the point where the  */\
-	stw	r9,_ESR(r11);		/* exception was taken		   */\
-	mfspr	r12,MCSRR0;						     \
-	stw	r1,GPR1(r11);						     \
-	mfspr	r9,MCSRR1;						     \
-	stw	r1,0(r11);						     \
-	tovirt(r1,r11);							     \
-	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
-	stw	r0,GPR0(r11);						     \
-	SAVE_4GPRS(3, r11);						     \
-	SAVE_2GPRS(7, r11)
-
-/*
- * Exception vectors.
- */
-#define	START_EXCEPTION(label)						     \
-        .align 5;              						     \
-label:
-
-#define FINISH_EXCEPTION(func)					\
-	bl	transfer_to_handler_full;			\
-	.long	func;						\
-	.long	ret_from_except_full
-
-#define EXCEPTION(n, label, hdlr, xfer)				\
-	START_EXCEPTION(label);					\
-	NORMAL_EXCEPTION_PROLOG;				\
-	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
-	xfer(n, hdlr)
-
-#define CRITICAL_EXCEPTION(n, label, hdlr)			\
-	START_EXCEPTION(label);					\
-	CRITICAL_EXCEPTION_PROLOG;				\
-	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
-	EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
-			  NOCOPY, transfer_to_handler_full, \
-			  ret_from_except_full)
-
-#define MCHECK_EXCEPTION(n, label, hdlr)			\
-	START_EXCEPTION(label);					\
-	MCHECK_EXCEPTION_PROLOG;				\
-	lis	r4,MCSR_MCS@h;					\
-	mtspr	SPRN_MCSR,r4;					\
-	mfspr	r5,SPRN_ESR;					\
-	stw	r5,_ESR(r11);					\
-	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
-	EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
-			  NOCOPY, mcheck_transfer_to_handler,   \
-			  ret_from_mcheck_exc)
-
-#define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret)	\
-	li	r10,trap;					\
-	stw	r10,TRAP(r11);					\
-	lis	r10,msr@h;					\
-	ori	r10,r10,msr@l;					\
-	copyee(r10, r9);					\
-	bl	tfer;		 				\
-	.long	hdlr;						\
-	.long	ret
-
-#define COPY_EE(d, s)		rlwimi d,s,0,16,16
-#define NOCOPY(d, s)
-
-#define EXC_XFER_STD(n, hdlr)		\
-	EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \
-			  ret_from_except_full)
-
-#define EXC_XFER_LITE(n, hdlr)		\
-	EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \
-			  ret_from_except)
-
-#define EXC_XFER_EE(n, hdlr)		\
-	EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \
-			  ret_from_except_full)
-
-#define EXC_XFER_EE_LITE(n, hdlr)	\
-	EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
-			  ret_from_except)
-
 interrupt_base:
 	/* Critical Input Interrupt */
 	CRITICAL_EXCEPTION(0x0100, CriticalInput, UnknownException)
diff --git a/arch/ppc/kernel/head_e500.S b/arch/ppc/kernel/head_e500.S
index ceb51d343..cf964198e 100644
--- a/arch/ppc/kernel/head_e500.S
+++ b/arch/ppc/kernel/head_e500.S
@@ -41,15 +41,7 @@
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
 #include <asm/offsets.h>
-
-/*
- * Macros
- */
-
-#define SET_IVOR(vector_number, vector_label)		\
-		li	r26,vector_label@l; 		\
-		mtspr	SPRN_IVOR##vector_number,r26;	\
-		sync
+#include "head_booke.h"
 
 /* As with the other PowerPC ports, it is expected that when code
  * execution begins here, the following registers contain valid, yet
@@ -371,232 +363,6 @@ skpinv:	addi	r6,r6,1				/* Increment */
  * We align on a 32 byte cache line boundary for good measure.
  */
 
-#define NORMAL_EXCEPTION_PROLOG						     \
-	mtspr	SPRN_SPRG0,r10;		/* save two registers to work with */\
-	mtspr	SPRN_SPRG1,r11;						     \
-	mtspr	SPRN_SPRG4W,r1;						     \
-	mfcr	r10;			/* save CR in r10 for now	   */\
-	mfspr	r11,SPRN_SRR1;		/* check whether user or kernel    */\
-	andi.	r11,r11,MSR_PR;						     \
-	beq	1f;							     \
-	mfspr	r1,SPRG3;		/* if from user, start at top of   */\
-	lwz	r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack   */\
-	addi	r1,r1,THREAD_SIZE;					     \
-1:	subi	r1,r1,INT_FRAME_SIZE;	/* Allocate an exception frame     */\
-	tophys(r11,r1);							     \
-	stw	r10,_CCR(r11);          /* save various registers	   */\
-	stw	r12,GPR12(r11);						     \
-	stw	r9,GPR9(r11);						     \
-	mfspr	r10,SPRG0;						     \
-	stw	r10,GPR10(r11);						     \
-	mfspr	r12,SPRG1;						     \
-	stw	r12,GPR11(r11);						     \
-	mflr	r10;							     \
-	stw	r10,_LINK(r11);						     \
-	mfspr	r10,SPRG4R;						     \
-	mfspr	r12,SRR0;						     \
-	stw	r10,GPR1(r11);						     \
-	mfspr	r9,SRR1;						     \
-	stw	r10,0(r11);						     \
-	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
-	stw	r0,GPR0(r11);						     \
-	SAVE_4GPRS(3, r11);						     \
-	SAVE_2GPRS(7, r11)
-
-/*
- * Exception prolog for critical exceptions.  This is a little different
- * from the normal exception prolog above since a critical exception
- * can potentially occur at any point during normal exception processing.
- * Thus we cannot use the same SPRG registers as the normal prolog above.
- * Instead we use a couple of words of memory at low physical addresses.
- * This is OK since we don't support SMP on these processors. For Book E
- * processors, we also have a reserved register (SPRG2) that is only used
- * in critical exceptions so we can free up a GPR to use as the base for
- * indirect access to the critical exception save area.  This is necessary
- * since the MMU is always on and the save area is offset from KERNELBASE.
- */
-#define CRITICAL_EXCEPTION_PROLOG					     \
-	mtspr	SPRG2,r8;		/* SPRG2 only used in criticals */   \
-	lis	r8,crit_save@ha;					     \
-	stw	r10,crit_r10@l(r8);					     \
-	stw	r11,crit_r11@l(r8);					     \
-	mfspr	r10,SPRG0;						     \
-	stw	r10,crit_sprg0@l(r8);					     \
-	mfspr	r10,SPRG1;						     \
-	stw	r10,crit_sprg1@l(r8);					     \
-	mfspr	r10,SPRG4R;						     \
-	stw	r10,crit_sprg4@l(r8);					     \
-	mfspr	r10,SPRG5R;						     \
-	stw	r10,crit_sprg5@l(r8);					     \
-	mfspr	r10,SPRG7R;						     \
-	stw	r10,crit_sprg7@l(r8);					     \
-	mfspr	r10,SPRN_PID;						     \
-	stw	r10,crit_pid@l(r8);					     \
-	mfspr	r10,SRR0;						     \
-	stw	r10,crit_srr0@l(r8);					     \
-	mfspr	r10,SRR1;						     \
-	stw	r10,crit_srr1@l(r8);					     \
-	mfspr	r8,SPRG2;		/* SPRG2 only used in criticals */   \
-	mfcr	r10;			/* save CR in r10 for now	   */\
-	mfspr	r11,SPRN_CSRR1;		/* check whether user or kernel    */\
-	andi.	r11,r11,MSR_PR;						     \
-	lis	r11,critical_stack_top@h;				     \
-	ori	r11,r11,critical_stack_top@l;				     \
-	beq	1f;							     \
-	/* COMING FROM USER MODE */					     \
-	mfspr	r11,SPRG3;		/* if from user, start at top of   */\
-	lwz	r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
-	addi	r11,r11,THREAD_SIZE;					     \
-1:	subi	r11,r11,INT_FRAME_SIZE;	/* Allocate an exception frame     */\
-	stw	r10,_CCR(r11);          /* save various registers	   */\
-	stw	r12,GPR12(r11);						     \
-	stw	r9,GPR9(r11);						     \
-	mflr	r10;							     \
-	stw	r10,_LINK(r11);						     \
-	mfspr	r12,SPRN_DEAR;		/* save DEAR and ESR in the frame  */\
-	stw	r12,_DEAR(r11);		/* since they may have had stuff   */\
-	mfspr	r9,SPRN_ESR;		/* in them at the point where the  */\
-	stw	r9,_ESR(r11);		/* exception was taken		   */\
-	mfspr	r12,CSRR0;						     \
-	stw	r1,GPR1(r11);						     \
-	mfspr	r9,CSRR1;						     \
-	stw	r1,0(r11);						     \
-	tovirt(r1,r11);							     \
-	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
-	stw	r0,GPR0(r11);						     \
-	SAVE_4GPRS(3, r11);						     \
-	SAVE_2GPRS(7, r11)
-
-/*
- * Exception prolog for machine check exceptions.  This is similar to
- * the critical exception prolog, except that machine check exceptions
- * have their own save area.  For Book E processors, we also have a
- * reserved register (SPRG6) that is only used in machine check exceptions
- * so we can free up a GPR to use as the base for indirect access to the
- * machine check exception save area.  This is necessary since the MMU
- * is always on and the save area is offset from KERNELBASE.
- */
-#define MCHECK_EXCEPTION_PROLOG					     \
-	mtspr	SPRG6W,r8;		/* SPRG6 used in machine checks */   \
-	lis	r8,mcheck_save@ha;					     \
-	stw	r10,mcheck_r10@l(r8);					     \
-	stw	r11,mcheck_r11@l(r8);					     \
-	mfspr	r10,SPRG0;						     \
-	stw	r10,mcheck_sprg0@l(r8);					     \
-	mfspr	r10,SPRG1;						     \
-	stw	r10,mcheck_sprg1@l(r8);					     \
-	mfspr	r10,SPRG4R;						     \
-	stw	r10,mcheck_sprg4@l(r8);					     \
-	mfspr	r10,SPRG5R;						     \
-	stw	r10,mcheck_sprg5@l(r8);					     \
-	mfspr	r10,SPRG7R;						     \
-	stw	r10,mcheck_sprg7@l(r8);					     \
-	mfspr	r10,SPRN_PID;						     \
-	stw	r10,mcheck_pid@l(r8);					     \
-	mfspr	r10,SRR0;						     \
-	stw	r10,mcheck_srr0@l(r8);					     \
-	mfspr	r10,SRR1;						     \
-	stw	r10,mcheck_srr1@l(r8);					     \
-	mfspr	r10,CSRR0;						     \
-	stw	r10,mcheck_csrr0@l(r8);					     \
-	mfspr	r10,CSRR1;						     \
-	stw	r10,mcheck_csrr1@l(r8);					     \
-	mfspr	r8,SPRG6R;		/* SPRG6 used in machine checks */   \
-	mfcr	r10;			/* save CR in r10 for now	   */\
-	mfspr	r11,SPRN_MCSRR1;	/* check whether user or kernel    */\
-	andi.	r11,r11,MSR_PR;						     \
-	lis	r11,mcheck_stack_top@h;					     \
-	ori	r11,r11,mcheck_stack_top@l;				     \
-	beq	1f;							     \
-	/* COMING FROM USER MODE */					     \
-	mfspr	r11,SPRG3;		/* if from user, start at top of   */\
-	lwz	r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
-	addi	r11,r11,THREAD_SIZE;					     \
-1:	subi	r11,r11,INT_FRAME_SIZE;	/* Allocate an exception frame     */\
-	stw	r10,_CCR(r11);          /* save various registers	   */\
-	stw	r12,GPR12(r11);						     \
-	stw	r9,GPR9(r11);						     \
-	mflr	r10;							     \
-	stw	r10,_LINK(r11);						     \
-	mfspr	r12,SPRN_DEAR;		/* save DEAR and ESR in the frame  */\
-	stw	r12,_DEAR(r11);		/* since they may have had stuff   */\
-	mfspr	r9,SPRN_ESR;		/* in them at the point where the  */\
-	stw	r9,_ESR(r11);		/* exception was taken		   */\
-	mfspr	r12,MCSRR0;						     \
-	stw	r1,GPR1(r11);						     \
-	mfspr	r9,MCSRR1;						     \
-	stw	r1,0(r11);						     \
-	tovirt(r1,r11);							     \
-	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
-	stw	r0,GPR0(r11);						     \
-	SAVE_4GPRS(3, r11);						     \
-	SAVE_2GPRS(7, r11)
-
-/*
- * Exception vectors.
- */
-#define	START_EXCEPTION(label)						     \
-        .align 5;              						     \
-label:
-
-#define FINISH_EXCEPTION(func)					\
-	bl	transfer_to_handler_full;			\
-	.long	func;						\
-	.long	ret_from_except_full
-
-#define EXCEPTION(n, label, hdlr, xfer)				\
-	START_EXCEPTION(label);					\
-	NORMAL_EXCEPTION_PROLOG;				\
-	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
-	xfer(n, hdlr)
-
-#define CRITICAL_EXCEPTION(n, label, hdlr)			\
-	START_EXCEPTION(label);					\
-	CRITICAL_EXCEPTION_PROLOG;				\
-	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
-	EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
-			  NOCOPY, transfer_to_handler_full, \
-			  ret_from_except_full)
-
-#define MCHECK_EXCEPTION(n, label, hdlr)			\
-	START_EXCEPTION(label);					\
-	MCHECK_EXCEPTION_PROLOG;				\
-	mfspr	r5,SPRN_ESR;					\
-	stw	r5,_ESR(r11);					\
-	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
-	EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
-			  NOCOPY, mcheck_transfer_to_handler,   \
-			  ret_from_mcheck_exc)
-
-#define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret)	\
-	li	r10,trap;					\
-	stw	r10,TRAP(r11);					\
-	lis	r10,msr@h;					\
-	ori	r10,r10,msr@l;					\
-	copyee(r10, r9);					\
-	bl	tfer;		 				\
-	.long	hdlr;						\
-	.long	ret
-
-#define COPY_EE(d, s)		rlwimi d,s,0,16,16
-#define NOCOPY(d, s)
-
-#define EXC_XFER_STD(n, hdlr)		\
-	EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \
-			  ret_from_except_full)
-
-#define EXC_XFER_LITE(n, hdlr)		\
-	EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \
-			  ret_from_except)
-
-#define EXC_XFER_EE(n, hdlr)		\
-	EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \
-			  ret_from_except_full)
-
-#define EXC_XFER_EE_LITE(n, hdlr)	\
-	EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
-			  ret_from_except)
-
 interrupt_base:
 	/* Critical Input Interrupt */
 	CRITICAL_EXCEPTION(0x0100, CriticalInput, UnknownException)
diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c
index 5adb6be19..6db80f60c 100644
--- a/arch/ppc/kernel/idle.c
+++ b/arch/ppc/kernel/idle.c
@@ -21,6 +21,7 @@
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
 #include <linux/slab.h>
+#include <linux/sysctl.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -65,3 +66,36 @@ int cpu_idle(void)
 			default_idle();
 	return 0;
 }
+
+#if defined(CONFIG_SYSCTL) && defined(CONFIG_6xx)
+/*
+ * Register the sysctl to set/clear powersave_nap.
+ */
+extern unsigned long powersave_nap;
+
+static ctl_table powersave_nap_ctl_table[]={
+	{
+		.ctl_name	= KERN_PPC_POWERSAVE_NAP,
+		.procname	= "powersave-nap",
+		.data		= &powersave_nap,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{ 0, },
+};
+static ctl_table powersave_nap_sysctl_root[] = {
+	{ 1, "kernel", NULL, 0, 0755, powersave_nap_ctl_table, },
+ 	{ 0,},
+};
+
+static int __init
+register_powersave_nap_sysctl(void)
+{
+	register_sysctl_table(powersave_nap_sysctl_root, 0);
+
+	return 0;
+}
+
+__initcall(register_powersave_nap_sysctl);
+#endif
diff --git a/arch/ppc/kernel/idle_6xx.S b/arch/ppc/kernel/idle_6xx.S
index 608f71ccb..25d009c75 100644
--- a/arch/ppc/kernel/idle_6xx.S
+++ b/arch/ppc/kernel/idle_6xx.S
@@ -79,12 +79,12 @@ BEGIN_FTR_SECTION
 	/* Now check if user or arch enabled NAP mode */
 	lis	r4,powersave_nap@ha
 	lwz	r4,powersave_nap@l(r4)
-	cmpi	0,r4,0
+	cmpwi	0,r4,0
 	beq	1f
 	lis	r3,HID0_NAP@h
 1:	
 END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
-	cmpi	0,r3,0
+	cmpwi	0,r3,0
 	beqlr
 
 	/* Clear MSR:EE */
@@ -133,7 +133,7 @@ BEGIN_FTR_SECTION
 	/* Go to low speed mode on some 750FX */
 	lis	r4,powersave_lowspeed@ha
 	lwz	r4,powersave_lowspeed@l(r4)
-	cmpi	0,r4,0
+	cmpwi	0,r4,0
 	beq	1f
 	mfspr	r4,SPRN_HID1
 	oris	r4,r4,0x0001
diff --git a/arch/ppc/kernel/idle_power4.S b/arch/ppc/kernel/idle_power4.S
index 538a044f4..73a58ff03 100644
--- a/arch/ppc/kernel/idle_power4.S
+++ b/arch/ppc/kernel/idle_power4.S
@@ -56,7 +56,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
 	/* Now check if user or arch enabled NAP mode */
 	lis	r4,powersave_nap@ha
 	lwz	r4,powersave_nap@l(r4)
-	cmpi	0,r4,0
+	cmpwi	0,r4,0
 	beqlr
 
 	/* Clear MSR:EE */
diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
index 2ac2e4b55..d4612e986 100644
--- a/arch/ppc/kernel/irq.c
+++ b/arch/ppc/kernel/irq.c
@@ -46,6 +46,7 @@
 #include <linux/random.h>
 #include <linux/seq_file.h>
 #include <linux/cpumask.h>
+#include <linux/profile.h>
 
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
@@ -414,13 +415,15 @@ static inline void
 handle_irq_event(int irq, struct pt_regs *regs, struct irqaction *action)
 {
 	int status = 0;
+	int ret;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
-		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
@@ -620,32 +623,6 @@ static int irq_affinity_write_proc (struct file *file, const char __user *buffer
 	return full_count;
 }
 
-static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
-	if (count - len < 2)
-		return -EINVAL;
-	len += sprintf(page + len, "\n");
-	return len;
-}
-
-static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer,
-					unsigned long count, void *data)
-{
-	int err;
-	int full_count = count;
-	cpumask_t *mask = (cpumask_t *)data;
-	cpumask_t new_value;
-
-	err = cpumask_parse(buffer, count, new_value);
-	if (err)
-		return err;
-
-	*mask = new_value;
-	return full_count;
-}
-
 #define MAX_NAMELEN 10
 
 static void register_irq_proc (unsigned int irq)
@@ -673,23 +650,14 @@ static void register_irq_proc (unsigned int irq)
 	smp_affinity_entry[irq] = entry;
 }
 
-unsigned long prof_cpu_mask = -1;
-
 void init_irq_proc (void)
 {
-	struct proc_dir_entry *entry;
 	int i;
 
 	/* create /proc/irq */
 	root_irq_dir = proc_mkdir("irq", NULL);
-
 	/* create /proc/irq/prof_cpu_mask */
-	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
-
-	entry->nlink = 1;
-	entry->data = (void *)&prof_cpu_mask;
-	entry->read_proc = prof_cpu_mask_read_proc;
-	entry->write_proc = prof_cpu_mask_write_proc;
+	create_prof_cpu_mask(root_irq_dir);
 
 	/*
 	 * Create entries for all existing IRQs.
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index 017da4476..55ca736d1 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -214,7 +214,7 @@ _GLOBAL(low_choose_750fx_pll)
 	mtmsr	r0
 
 	/* If switching to PLL1, disable HID0:BTIC */
-	cmpli	cr0,r3,0
+	cmplwi	cr0,r3,0
 	beq	1f
 	mfspr	r5,HID0
 	rlwinm	r5,r5,0,27,25
@@ -239,7 +239,7 @@ _GLOBAL(low_choose_750fx_pll)
 	stw	r4,nap_save_hid1@l(r6)
 
 	/* If switching to PLL0, enable HID0:BTIC */
-	cmpli	cr0,r3,0
+	cmplwi	cr0,r3,0
 	bne	1f
 	mfspr	r5,HID0
 	ori	r5,r5,HID0_BTIC
@@ -470,7 +470,7 @@ _GLOBAL(_tlbia)
 	ori	r9,r9,mmu_hash_lock@l
 	tophys(r9,r9)
 10:	lwarx	r7,0,r9
-	cmpi	0,r7,0
+	cmpwi	0,r7,0
 	bne-	10b
 	stwcx.	r8,0,r9
 	bne-	10b
@@ -551,7 +551,7 @@ _GLOBAL(_tlbie)
 	ori	r9,r9,mmu_hash_lock@l
 	tophys(r9,r9)
 10:	lwarx	r7,0,r9
-	cmpi	0,r7,0
+	cmpwi	0,r7,0
 	bne-	10b
 	stwcx.	r8,0,r9
 	bne-	10b
@@ -599,7 +599,7 @@ _GLOBAL(flush_instruction_cache)
 #else
 	mfspr	r3,PVR
 	rlwinm	r3,r3,16,16,31
-	cmpi	0,r3,1
+	cmpwi	0,r3,1
 	beqlr			/* for 601, do nothing */
 	/* 603/604 processor - use invalidate-all bit in HID0 */
 	mfspr	r3,HID0
@@ -617,10 +617,9 @@ _GLOBAL(flush_instruction_cache)
  * flush_icache_range(unsigned long start, unsigned long stop)
  */
 _GLOBAL(flush_icache_range)
-	mfspr	r5,PVR
-	rlwinm	r5,r5,16,16,31
-	cmpi	0,r5,1
-	beqlr				/* for 601, do nothing */
+BEGIN_FTR_SECTION
+	blr				/* for 601, do nothing */
+END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE)
 	li	r5,L1_CACHE_LINE_SIZE-1
 	andc	r3,r3,r5
 	subf	r4,r3,r4
@@ -735,10 +734,9 @@ _GLOBAL(flush_dcache_all)
  *	void __flush_dcache_icache(void *page)
  */
 _GLOBAL(__flush_dcache_icache)
-	mfspr	r5,PVR
-	rlwinm	r5,r5,16,16,31
-	cmpi	0,r5,1
-	beqlr					/* for 601, do nothing */
+BEGIN_FTR_SECTION
+	blr					/* for 601, do nothing */
+END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE)
 	rlwinm	r3,r3,0,0,19			/* Get page base address */
 	li	r4,4096/L1_CACHE_LINE_SIZE	/* Number of lines in a page */
 	mtctr	r4
@@ -764,10 +762,9 @@ _GLOBAL(__flush_dcache_icache)
  *	void __flush_dcache_icache_phys(unsigned long physaddr)
  */
 _GLOBAL(__flush_dcache_icache_phys)
-	mfspr	r5,PVR
-	rlwinm	r5,r5,16,16,31
-	cmpi	0,r5,1
-	beqlr					/* for 601, do nothing */
+BEGIN_FTR_SECTION
+	blr					/* for 601, do nothing */
+END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE)
 	mfmsr	r10
 	rlwinm	r0,r10,0,28,26			/* clear DR */
 	mtmsr	r0
@@ -1144,7 +1141,7 @@ _GLOBAL(kernel_thread)
 	li	r4,0		/* new sp (unused) */
 	li	r0,__NR_clone
 	sc
-	cmpi	0,r3,0		/* parent or child? */
+	cmpwi	0,r3,0		/* parent or child? */
 	bne	1f		/* return if parent */
 	li	r0,0		/* make top-level stack frame */
 	stwu	r0,-16(r1)
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 4145ff7bf..08cdddee7 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -33,6 +33,7 @@
 unsigned long isa_io_base     = 0;
 unsigned long isa_mem_base    = 0;
 unsigned long pci_dram_offset = 0;
+int pcibios_assign_bus_offset = 1;
 
 void pcibios_make_OF_bus_map(void);
 
@@ -45,11 +46,6 @@ static void fixup_broken_pcnet32(struct pci_dev* dev);
 static int reparent_resources(struct resource *parent, struct resource *res);
 static void fixup_rev1_53c810(struct pci_dev* dev);
 static void fixup_cpc710_pci64(struct pci_dev* dev);
-#ifdef CONFIG_PPC_PMAC
-extern void pmac_pci_fixup_cardbus(struct pci_dev* dev);
-extern void pmac_pci_fixup_pciata(struct pci_dev* dev);
-extern void pmac_pci_fixup_k2_sata(struct pci_dev* dev);
-#endif
 #ifdef CONFIG_PPC_OF
 static u8* pci_to_OF_bus_map;
 #endif
@@ -64,20 +60,6 @@ struct pci_controller** hose_tail = &hose_head;
 
 static int pci_bus_count;
 
-struct pci_fixup pcibios_fixups[] = {
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_TRIDENT,	PCI_ANY_ID,			fixup_broken_pcnet32 },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_NCR,	PCI_DEVICE_ID_NCR_53C810,	fixup_rev1_53c810 },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_IBM,	PCI_DEVICE_ID_IBM_CPC710_PCI64,	fixup_cpc710_pci64},
-	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,		PCI_ANY_ID,			pcibios_fixup_resources },
-#ifdef CONFIG_PPC_PMAC
-	/* We should add per-machine fixup support in xxx_setup.c or xxx_pci.c */
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_TI,	PCI_ANY_ID,			pmac_pci_fixup_cardbus },
-	{ PCI_FIXUP_FINAL,	PCI_ANY_ID,		PCI_ANY_ID,			pmac_pci_fixup_pciata },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SERVERWORKS, 0x0240,			pmac_pci_fixup_k2_sata },
-#endif /* CONFIG_PPC_PMAC */
- 	{ 0 }
-};
-
 static void
 fixup_rev1_53c810(struct pci_dev* dev)
 {
@@ -90,6 +72,7 @@ fixup_rev1_53c810(struct pci_dev* dev)
 		dev->class = PCI_CLASS_STORAGE_SCSI;
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR,	PCI_DEVICE_ID_NCR_53C810,	fixup_rev1_53c810);
 
 static void
 fixup_broken_pcnet32(struct pci_dev* dev)
@@ -100,6 +83,7 @@ fixup_broken_pcnet32(struct pci_dev* dev)
 		pci_name_device(dev);
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT,	PCI_ANY_ID,			fixup_broken_pcnet32);
 
 static void
 fixup_cpc710_pci64(struct pci_dev* dev)
@@ -112,6 +96,7 @@ fixup_cpc710_pci64(struct pci_dev* dev)
 	dev->resource[1].start = dev->resource[1].end = 0;
 	dev->resource[1].flags = 0;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM,	PCI_DEVICE_ID_IBM_CPC710_PCI64,	fixup_cpc710_pci64);
 
 static void
 pcibios_fixup_resources(struct pci_dev *dev)
@@ -158,9 +143,9 @@ pcibios_fixup_resources(struct pci_dev *dev)
 	if (ppc_md.pcibios_fixup_resources)
 		ppc_md.pcibios_fixup_resources(dev);
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID,		PCI_ANY_ID,			pcibios_fixup_resources);
 
-void
-pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
 			struct resource *res)
 {
 	unsigned long offset = 0;
@@ -173,6 +158,7 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
 	region->start = res->start - offset;
 	region->end = res->end - offset;
 }
+EXPORT_SYMBOL(pcibios_resource_to_bus);
 
 /*
  * We need to avoid collisions with `mirrored' VGA ports
@@ -187,8 +173,7 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
  * but we want to try to avoid allocating at 0x2900-0x2bff
  * which might have be mirrored at 0x0100-0x03ff..
  */
-void
-pcibios_align_resource(void *data, struct resource *res, unsigned long size,
+void pcibios_align_resource(void *data, struct resource *res, unsigned long size,
 		       unsigned long align)
 {
 	struct pci_dev *dev = data;
@@ -208,7 +193,7 @@ pcibios_align_resource(void *data, struct resource *res, unsigned long size,
 		}
 	}
 }
-
+EXPORT_SYMBOL(pcibios_align_resource);
 
 /*
  *  Handle resources of PCI devices.  If the world were perfect, we could
@@ -427,7 +412,7 @@ probe_resource(struct pci_bus *parent, struct resource *pr,
 			r = &dev->resource[i];
 			if (!r->flags || (r->flags & IORESOURCE_UNSET))
 				continue;
-			if (pci_find_parent_resource(bus->self, r) != pr)
+			if (pci_find_parent_resource(dev, r) != pr)
 				continue;
 			if (r->end >= res->start && res->end >= r->start) {
 				*conflict = r;
@@ -1279,7 +1264,7 @@ pcibios_init(void)
 		bus = pci_scan_bus(hose->first_busno, hose->ops, hose);
 		hose->last_busno = bus->subordinate;
 		if (pci_assign_all_busses || next_busno <= hose->last_busno)
-			next_busno = hose->last_busno+1;
+			next_busno = hose->last_busno + pcibios_assign_bus_offset;
 	}
 	pci_bus_count = next_busno;
 
@@ -1724,6 +1709,32 @@ pci_init_resource(struct resource *res, unsigned long start, unsigned long end,
 	res->child = NULL;
 }
 
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
+{
+	unsigned long start = pci_resource_start(dev, bar);
+	unsigned long len = pci_resource_len(dev, bar);
+	unsigned long flags = pci_resource_flags(dev, bar);
+
+	if (!len)
+		return NULL;
+	if (max && len > max)
+		len = max;
+	if (flags & IORESOURCE_IO)
+		return ioport_map(start, len);
+	if (flags & IORESOURCE_MEM)
+		return (void __iomem *) start;
+	/* What? */
+	return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+	/* Nothing to do */
+}
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
+
+
 /*
  * Null PCI config access functions, for the case when we can't
  * find a hose.
diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c
index 91592c03e..d8e027fd4 100644
--- a/arch/ppc/kernel/ppc_htab.c
+++ b/arch/ppc/kernel/ppc_htab.c
@@ -20,6 +20,7 @@
 #include <linux/threads.h>
 #include <linux/smp_lock.h>
 #include <linux/seq_file.h>
+#include <linux/init.h>
 
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
@@ -34,9 +35,6 @@
 static int ppc_htab_show(struct seq_file *m, void *v);
 static ssize_t ppc_htab_write(struct file * file, const char __user * buffer,
 			      size_t count, loff_t *ppos);
-int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
-		  void __user *buffer, size_t *lenp, loff_t *ppos);
-
 extern PTE *Hash, *Hash_end;
 extern unsigned long Hash_size, Hash_mask;
 extern unsigned long _SDR1;
@@ -438,3 +436,32 @@ int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
 	*ppos += *lenp;
 	return 0;
 }
+
+#ifdef CONFIG_SYSCTL
+/*
+ * Register our sysctl.
+ */
+static ctl_table htab_ctl_table[]={
+	{
+		.ctl_name	= KERN_PPC_L2CR,
+		.procname	= "l2cr",
+		.mode		= 0644,
+		.proc_handler	= &proc_dol2crvec,
+	},
+	{ 0, },
+};
+static ctl_table htab_sysctl_root[] = {
+	{ 1, "kernel", NULL, 0, 0755, htab_ctl_table, },
+ 	{ 0,},
+};
+
+static int __init
+register_ppc_htab_sysctl(void)
+{
+	register_sysctl_table(htab_sysctl_root, 0);
+
+	return 0;
+}
+
+__initcall(register_ppc_htab_sysctl);
+#endif
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 2d3e630a7..965a874a4 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -352,3 +352,7 @@ EXPORT_SYMBOL(cur_cpu_spec);
 extern unsigned long agp_special_page;
 EXPORT_SYMBOL(agp_special_page);
 #endif
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+EXPORT_SYMBOL(__mtdcr);
+EXPORT_SYMBOL(__mfdcr);
+#endif
diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
index 2ea505381..d9ab6a7de 100644
--- a/arch/ppc/kernel/process.c
+++ b/arch/ppc/kernel/process.c
@@ -36,6 +36,7 @@
 #include <linux/module.h>
 #include <linux/kallsyms.h>
 #include <linux/mqueue.h>
+#include <linux/hardirq.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -44,7 +45,6 @@
 #include <asm/processor.h>
 #include <asm/mmu.h>
 #include <asm/prom.h>
-#include <asm/hardirq.h>
 
 extern unsigned long _get_SP(void);
 
@@ -555,8 +555,7 @@ int sys_clone(unsigned long clone_flags, unsigned long usp,
 	CHECK_FULL_REGS(regs);
 	if (usp == 0)
 		usp = regs->gpr[1];	/* stack pointer for child */
- 	return do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0,
-			parent_tidp, child_tidp);
+ 	return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp);
 }
 
 int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
@@ -662,7 +661,7 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
 		++count;
 		sp = *(unsigned long *)sp;
 	}
-#if !CONFIG_KALLSYMS
+#ifndef CONFIG_KALLSYMS
 	if (count > 0)
 		printk("\n");
 #endif
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 376f7369c..57b70aec7 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -418,7 +418,6 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
 	 * are used for initrd_start and initrd_size,
 	 * otherwise they contain 0xdeadbeef.
 	 */
-	cmd_line[0] = 0;
 	if (r3 >= 0x4000 && r3 < 0x800000 && r4 == 0) {
 		strlcpy(cmd_line, (char *)r3 + KERNELBASE,
 			sizeof(cmd_line));
@@ -484,6 +483,9 @@ static int __init set_preferred_console(void)
 	char *name;
 	int offset;
 
+	if (of_stdout_device == NULL)
+		return -ENODEV;
+
 	/* The user has requested a console so this is already set up. */
 	if (strstr(saved_command_line, "console="))
 		return -EBUSY;
@@ -744,6 +746,10 @@ void __init setup_arch(char **cmdline_p)
 	if ( ppc_md.progress ) ppc_md.progress("ocp: exit", 0x3eab);
 #endif
 
+#ifdef CONFIG_DUMMY_CONSOLE
+	conswitchp = &dummy_con;
+#endif
+
 	ppc_md.setup_arch();
 	if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
 
diff --git a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c
index 20b6446c0..260716af5 100644
--- a/arch/ppc/kernel/signal.c
+++ b/arch/ppc/kernel/signal.c
@@ -270,7 +270,7 @@ save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, int sigret)
 static int
 restore_user_regs(struct pt_regs *regs, struct mcontext __user *sr, int sig)
 {
-	unsigned long save_r2;
+	unsigned long save_r2 = 0;
 #if defined(CONFIG_ALTIVEC) || defined(CONFIG_SPE)
 	unsigned long msr;
 #endif
@@ -404,9 +404,7 @@ badframe:
 	printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n",
 	       regs, frame, newsp);
 #endif
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int sig)
@@ -556,9 +554,7 @@ badframe:
 	printk("badframe in handle_signal, regs=%p frame=%p newsp=%lx\n",
 	       regs, frame, newsp);
 #endif
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 /*
@@ -604,7 +600,7 @@ badframe:
 int do_signal(sigset_t *oldset, struct pt_regs *regs)
 {
 	siginfo_t info;
-	struct k_sigaction *ka;
+	struct k_sigaction ka;
 	unsigned long frame, newsp;
 	int signr, ret;
 
@@ -613,9 +609,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
 
 	newsp = frame = 0;
 
-	signr = get_signal_to_deliver(&info, regs, NULL);
-
-	ka = (signr == 0)? NULL: &current->sighand->action[signr-1];
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
 	if (TRAP(regs) == 0x0C00		/* System Call! */
 	    && regs->ccr & 0x10000000		/* error signalled */
@@ -626,7 +620,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
 		if (signr > 0
 		    && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK
 			|| (ret == ERESTARTSYS
-			    && !(ka->sa.sa_flags & SA_RESTART)))) {
+			    && !(ka.sa.sa_flags & SA_RESTART)))) {
 			/* make the system call return an EINTR error */
 			regs->result = -EINTR;
 			regs->gpr[3] = EINTR;
@@ -645,7 +639,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
 	if (signr == 0)
 		return 0;		/* no signals delivered */
 
-	if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
+	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
@@ -653,17 +647,14 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
 	newsp &= ~0xfUL;
 
 	/* Whee!  Actually deliver the signal.  */
-	if (ka->sa.sa_flags & SA_SIGINFO)
-		handle_rt_signal(signr, ka, &info, oldset, regs, newsp);
+	if (ka.sa.sa_flags & SA_SIGINFO)
+		handle_rt_signal(signr, &ka, &info, oldset, regs, newsp);
 	else
-		handle_signal(signr, ka, &info, oldset, regs, newsp);
-
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
+		handle_signal(signr, &ka, &info, oldset, regs, newsp);
 
-	if (!(ka->sa.sa_flags & SA_NODEFER)) {
+	if (!(ka.sa.sa_flags & SA_NODEFER)) {
 		spin_lock_irq(&current->sighand->siglock);
-		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+		sigorsets(&current->blocked,&current->blocked,&ka.sa.sa_mask);
 		sigaddset(&current->blocked, signr);
 		recalc_sigpending();
 		spin_unlock_irq(&current->sighand->siglock);
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index c28fbf398..dae491743 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -26,7 +26,6 @@
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/hardirq.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/smp.h>
@@ -364,22 +363,15 @@ int __devinit start_secondary(void *unused)
 
 int __cpu_up(unsigned int cpu)
 {
-	struct pt_regs regs;
 	struct task_struct *p;
 	char buf[32];
 	int c;
 
 	/* create a process for the processor */
 	/* only regs.msr is actually used, and 0 is OK for it */
-	memset(&regs, 0, sizeof(struct pt_regs));
-	p = copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
+	p = fork_idle(cpu);
 	if (IS_ERR(p))
 		panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
-	wake_up_forked_process(p);
-
-	init_idle(p, cpu);
-	unhash_process(p);
-
 	secondary_ti = p->thread_info;
 	p->thread_info->cpu = cpu;
 
diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
index cfeff0479..60e7ef5ad 100644
--- a/arch/ppc/kernel/time.c
+++ b/arch/ppc/kernel/time.c
@@ -108,41 +108,18 @@ static inline int tb_delta(unsigned *jiffy_stamp) {
 	return delta;
 }
 
-extern char _stext;
-
-static inline void ppc_do_profile (struct pt_regs *regs)
+#ifdef CONFIG_SMP
+unsigned long profile_pc(struct pt_regs *regs)
 {
-	unsigned long nip;
-	extern unsigned long prof_cpu_mask;
-
-	profile_hook(regs);
-
-	if (user_mode(regs))
-		return;
-
-	if (!prof_buffer)
-		return;
+	unsigned long pc = instruction_pointer(regs);
 
-	nip = instruction_pointer(regs);
+	if (in_lock_functions(pc))
+		return regs->link;
 
-	/*
-	 * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
-	 * (default is all CPUs.)
-	 */
-	if (!((1<<smp_processor_id()) & prof_cpu_mask))
-		return;
-
-	nip -= (unsigned long) &_stext;
-	nip >>= prof_shift;
-	/*
-	 * Don't ignore out-of-bounds EIP values silently,
-	 * put them into the last histogram slot, so if
-	 * present, they will show up as a sharp peak.
-	 */
-	if (nip > prof_len-1)
-		nip = prof_len-1;
-	atomic_inc((atomic_t *)&prof_buffer[nip]);
+	return pc;
 }
+EXPORT_SYMBOL(profile_pc);
+#endif
 
 /*
  * timer_interrupt - gets called when the decrementer overflows,
@@ -161,10 +138,10 @@ void timer_interrupt(struct pt_regs * regs)
 
 	irq_enter();
 
-	while ((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) < 0) {
+	while ((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) <= 0) {
 		jiffy_stamp += tb_ticks_per_jiffy;
 		
-		ppc_do_profile(regs);
+		profile_tick(CPU_PROFILING, regs);
 
 	  	if (smp_processor_id())
 			continue;
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index 544ea9fb5..7870bb680 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -357,7 +357,7 @@ void RunModeException(struct pt_regs *regs)
 
 /* Illegal instruction emulation support.  Originally written to
  * provide the PVR to user applications using the mfspr rd, PVR.
- * Return non-zero if we can't emulate, or EFAULT if the associated
+ * Return non-zero if we can't emulate, or -EFAULT if the associated
  * memory access caused an access fault.  Return zero on success.
  *
  * There are a couple of ways to do this, either "decode" the instruction
@@ -368,16 +368,19 @@ void RunModeException(struct pt_regs *regs)
 #define INST_MFSPR_PVR		0x7c1f42a6
 #define INST_MFSPR_PVR_MASK	0xfc1fffff
 
+#define INST_DCBA		0x7c0005ec
+#define INST_DCBA_MASK		0x7c0007fe
+
+#define INST_MCRXR		0x7c000400
+#define INST_MCRXR_MASK		0x7c0007fe
+
 static int emulate_instruction(struct pt_regs *regs)
 {
 	u32 instword;
 	u32 rd;
-	int retval;
-
-	retval = -EINVAL;
 
 	if (!user_mode(regs))
-		return retval;
+		return -EINVAL;
 	CHECK_FULL_REGS(regs);
 
 	if (get_user(instword, (u32 __user *)(regs->nip)))
@@ -388,10 +391,24 @@ static int emulate_instruction(struct pt_regs *regs)
 	if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) {
 		rd = (instword >> 21) & 0x1f;
 		regs->gpr[rd] = mfspr(PVR);
-		retval = 0;
-		regs->nip += 4;
+		return 0;
 	}
-	return retval;
+
+	/* Emulating the dcba insn is just a no-op.  */
+	if ((instword & INST_DCBA_MASK) == INST_DCBA)
+		return 0;
+
+	/* Emulate the mcrxr insn.  */
+	if ((instword & INST_MCRXR_MASK) == INST_MCRXR) {
+		int shift = (instword >> 21) & 0x1c;
+		unsigned long msk = 0xf0000000UL >> shift;
+
+		regs->ccr = (regs->ccr & ~msk) | ((regs->xer >> shift) & msk);
+		regs->xer &= ~0xf0000000UL;
+		return 0;
+	}
+
+	return -EINVAL;
 }
 
 /*
@@ -528,17 +545,23 @@ void ProgramCheckException(struct pt_regs *regs)
 		return;
 	}
 
-	if (reason & REASON_PRIVILEGED) {
-		/* Try to emulate it if we should. */
-		if (emulate_instruction(regs) == 0) {
+	/* Try to emulate it if we should. */
+	if (reason & (REASON_ILLEGAL | REASON_PRIVILEGED)) {
+		switch (emulate_instruction(regs)) {
+		case 0:
+			regs->nip += 4;
 			emulate_single_step(regs);
 			return;
+		case -EFAULT:
+			_exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
+			return;
 		}
-		_exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
-		return;
 	}
 
-	_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
+	if (reason & REASON_PRIVILEGED)
+		_exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
+	else
+		_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
 }
 
 void SingleStepException(struct pt_regs *regs)
diff --git a/arch/ppc/kernel/vector.S b/arch/ppc/kernel/vector.S
index d8fe6b5fb..82a21346b 100644
--- a/arch/ppc/kernel/vector.S
+++ b/arch/ppc/kernel/vector.S
@@ -106,7 +106,7 @@ vmaddfp:
 1:	lfsx	fr0,r4,r7
 	lfsx	fr1,r5,r7
 	lfsx	fr2,r6,r7
-	fmadds	fr0,fr0,fr1,fr2
+	fmadds	fr0,fr0,fr2,fr1
 	stfsx	fr0,r3,r7
 	addi	r7,r7,4
 	bdnz	1b
@@ -133,7 +133,7 @@ vnmsubfp:
 1:	lfsx	fr0,r4,r7
 	lfsx	fr1,r5,r7
 	lfsx	fr2,r6,r7
-	fnmsubs	fr0,fr0,fr1,fr2
+	fnmsubs	fr0,fr0,fr2,fr1
 	stfsx	fr0,r3,r7
 	addi	r7,r7,4
 	bdnz	1b
diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S
index 342848fe5..5d2cbc780 100644
--- a/arch/ppc/kernel/vmlinux.lds.S
+++ b/arch/ppc/kernel/vmlinux.lds.S
@@ -32,6 +32,7 @@ SECTIONS
   {
     *(.text)
     SCHED_TEXT
+    LOCK_TEXT
     *(.fixup)
     *(.got1)
     __got2_start = .;
@@ -102,9 +103,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : {
 	*(.initcall1.init)
diff --git a/arch/ppc/lib/checksum.S b/arch/ppc/lib/checksum.S
index 74928a7a2..7874e8a80 100644
--- a/arch/ppc/lib/checksum.S
+++ b/arch/ppc/lib/checksum.S
@@ -80,13 +80,13 @@ _GLOBAL(csum_partial)
 	adde	r0,r0,r5	/* be unnecessary to unroll this loop */
 	bdnz	2b
 	andi.	r4,r4,3
-3:	cmpi	0,r4,2
+3:	cmpwi	0,r4,2
 	blt+	4f
 	lhz	r5,4(r3)
 	addi	r3,r3,2
 	subi	r4,r4,2
 	adde	r0,r0,r5
-4:	cmpi	0,r4,1
+4:	cmpwi	0,r4,1
 	bne+	5f
 	lbz	r5,4(r3)
 	slwi	r5,r5,8		/* Upper byte of word */
@@ -143,7 +143,7 @@ _GLOBAL(csum_partial_copy_generic)
 	adde	r0,r0,r9
 	bdnz	82b
 13:	andi.	r5,r5,3
-3:	cmpi	0,r5,2
+3:	cmpwi	0,r5,2
 	blt+	4f
 83:	lhz	r6,4(r3)
 	addi	r3,r3,2
@@ -151,7 +151,7 @@ _GLOBAL(csum_partial_copy_generic)
 93:	sth	r6,4(r4)
 	addi	r4,r4,2
 	adde	r0,r0,r6
-4:	cmpi	0,r5,1
+4:	cmpwi	0,r5,1
 	bne+	5f
 84:	lbz	r6,4(r3)
 94:	stb	r6,4(r4)
@@ -188,7 +188,7 @@ src_error_3:
 97:	stbu	r6,1(r4)
 	bdnz	97b
 src_error:
-	cmpi	0,r7,0
+	cmpwi	0,r7,0
 	beq	1f
 	li	r6,-EFAULT
 	stw	r6,0(r7)
@@ -196,7 +196,7 @@ src_error:
 	blr
 
 dst_error:
-	cmpi	0,r8,0
+	cmpwi	0,r8,0
 	beq	1f
 	li	r6,-EFAULT
 	stw	r6,0(r8)
diff --git a/arch/ppc/lib/rheap.c b/arch/ppc/lib/rheap.c
index 103765660..9991c48f9 100644
--- a/arch/ppc/lib/rheap.c
+++ b/arch/ppc/lib/rheap.c
@@ -216,7 +216,7 @@ static void attach_free_block(rh_info_t * info, rh_block_t * blkn)
 
 	/* Grow the after block backwards */
 	if (before == NULL && after != NULL) {
-		(int8_t *) after->start -= size;
+		after->start = (int8_t *)after->start - size;
 		after->size += size;
 		return;
 	}
@@ -407,7 +407,7 @@ void *rh_detach_region(rh_info_t * info, void *start, int size)
 	/* blk still in free list, with updated start and/or size */
 	if (bs == s || be == e) {
 		if (bs == s)
-			(int8_t *) blk->start += size;
+			blk->start = (int8_t *)blk->start + size;
 		blk->size -= size;
 
 	} else {
@@ -471,7 +471,7 @@ void *rh_alloc(rh_info_t * info, int size, const char *owner)
 	newblk->owner = owner;
 
 	/* blk still in free list, with updated start, size */
-	(int8_t *) blk->start += size;
+	blk->start = (int8_t *)blk->start + size;
 	blk->size -= size;
 
 	start = newblk->start;
@@ -535,7 +535,7 @@ void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
 	/* blk still in free list, with updated start and/or size */
 	if (bs == s || be == e) {
 		if (bs == s)
-			(int8_t *) blk->start += size;
+			blk->start = (int8_t *)blk->start + size;
 		blk->size -= size;
 
 	} else {
diff --git a/arch/ppc/math-emu/op-common.h b/arch/ppc/math-emu/op-common.h
index aeaa1cde5..afb82b649 100644
--- a/arch/ppc/math-emu/op-common.h
+++ b/arch/ppc/math-emu/op-common.h
@@ -82,7 +82,6 @@ do {									\
 	if (X##_e <= _FP_WFRACBITS_##fs)			\
 	  {							\
 	    _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs);	\
-	    __ret |= _FP_ROUND(wc, X);				\
 	    _FP_FRAC_SLL_##wc(X, 1);				\
 	    if (_FP_FRAC_OVERP_##wc(fs, X))			\
 	      {							\
diff --git a/arch/ppc/mm/44x_mmu.c b/arch/ppc/mm/44x_mmu.c
index 1d79838d9..a2ab8b053 100644
--- a/arch/ppc/mm/44x_mmu.c
+++ b/arch/ppc/mm/44x_mmu.c
@@ -72,7 +72,7 @@ unsigned int tlb_44x_hwater = 62;
 static void __init
 ppc44x_pin_tlb(int slot, unsigned int virt, unsigned int phys)
 {
-	unsigned long attrib;
+	unsigned long attrib = 0;
 
 	__asm__ __volatile__("\
 	clrrwi	%2,%2,10\n\
diff --git a/arch/ppc/mm/4xx_mmu.c b/arch/ppc/mm/4xx_mmu.c
index 6066ff35c..a7f616140 100644
--- a/arch/ppc/mm/4xx_mmu.c
+++ b/arch/ppc/mm/4xx_mmu.c
@@ -52,6 +52,7 @@
 #include <asm/setup.h>
 #include "mmu_decl.h"
 
+extern int __map_without_ltlbs;
 /*
  * MMU_init_hw does the chip-specific initialization of the MMU hardware.
  */
@@ -102,6 +103,10 @@ unsigned long __init mmu_mapin_ram(void)
 	p = PPC_MEMSTART;
 	s = 0;
 
+	if (__map_without_ltlbs) {
+		return s;
+	}
+
 	while (s <= (total_lowmem - LARGE_PAGE_SIZE_16M)) {
 		pmd_t *pmdp;
 		unsigned long val = p | _PMD_SIZE_16M | _PAGE_HWEXEC | _PAGE_HWWRITE;
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index 448e80c11..cbed55208 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -104,6 +104,7 @@ extern unsigned long sysmap_size;
  * -- Cort
  */
 int __map_without_bats;
+int __map_without_ltlbs;
 
 /* max amount of RAM to use */
 unsigned long __max_memory;
@@ -204,6 +205,10 @@ void MMU_setup(void)
 		__map_without_bats = 1;
 	}
 
+	if (strstr(cmd_line, "noltlbs")) {
+		__map_without_ltlbs = 1;
+	}
+
 	/* Look for mem= option on command line */
 	if (strstr(cmd_line, "mem=")) {
 		char *p, *q;
diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
index c16d4cce4..30482852c 100644
--- a/arch/ppc/mm/pgtable.c
+++ b/arch/ppc/mm/pgtable.c
@@ -22,6 +22,7 @@
 
 #include <linux/config.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
@@ -271,6 +272,18 @@ void iounmap(void *addr)
 		vunmap((void *) (PAGE_MASK & (unsigned long)addr));
 }
 
+void __iomem *ioport_map(unsigned long port, unsigned int len)
+{
+	return (void __iomem *) (port + _IO_BASE);
+}
+
+void ioport_unmap(void __iomem *addr)
+{
+	/* Nothing to do */
+}
+EXPORT_SYMBOL(ioport_map);
+EXPORT_SYMBOL(ioport_unmap);
+
 int
 map_page(unsigned long va, phys_addr_t pa, int flags)
 {
diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c
index 6c9bde473..118d8520e 100644
--- a/arch/ppc/platforms/4xx/ebony.c
+++ b/arch/ppc/platforms/4xx/ebony.c
@@ -4,9 +4,11 @@
  * Ebony board specific routines
  *
  * Matt Porter <mporter@mvista.com>
- *
  * Copyright 2002 MontaVista Software Inc.
  *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003, 2004 Zultys Technologies
+ *
  * 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
@@ -118,7 +120,7 @@ static u_char ebony_IRQ_initsenses[] __initdata = {
 	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* 63: EMAC 1 WOL */
 };
 
-extern void abort(void);
+static struct ibm44x_clocks clocks __initdata;
 
 static void __init
 ebony_calibrate_decr(void)
@@ -143,18 +145,7 @@ ebony_calibrate_decr(void)
 			break;
 	}
 
-	tb_ticks_per_jiffy = freq / HZ;
-	tb_to_us = mulhwu_scale_factor(freq, 1000000);
-
-	/* Set the time base to zero */
-	mtspr(SPRN_TBWL, 0);
-	mtspr(SPRN_TBWU, 0);
-
-	/* Clear any pending timer interrupts */
-	mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
-
-	/* Enable decrementer interrupt */
-	mtspr(SPRN_TCR, TCR_DIE);
+	ibm44x_calibrate_decr(freq);
 }
 
 static int
@@ -283,7 +274,7 @@ ebony_early_serial_map(void)
 	memset(&port, 0, sizeof(port));
 	port.membase = ioremap64(PPC440GP_UART0_ADDR, 8);
 	port.irq = 0;
-	port.uartclk = BASE_BAUD * 16;
+	port.uartclk = clocks.uart0;
 	port.regshift = 0;
 	port.iotype = SERIAL_IO_MEM;
 	port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
@@ -306,7 +297,6 @@ static void __init
 ebony_setup_arch(void)
 {
 	unsigned char * vpd_base;
-	struct ibm44x_clocks clocks;
 	struct ocp_def *def;
 	struct ocp_func_emac_data *emacdata;
 
@@ -361,10 +351,6 @@ ebony_setup_arch(void)
 		ROOT_DEV = Root_HDA1;
 #endif
 
-#ifdef CONFIG_VT
-	conswitchp = &dummy_con;
-#endif
-
 	ebony_early_serial_map();
 
 	ibm4xxPIC_InitSenses = ebony_IRQ_initsenses;
@@ -374,152 +360,17 @@ ebony_setup_arch(void)
 	printk("IBM Ebony port (MontaVista Software, Inc. (source@mvista.com))\n");
 }
 
-static void
-ebony_restart(char *cmd)
-{
-	local_irq_disable();
-	abort();
-}
-
-static void
-ebony_power_off(void)
-{
-	local_irq_disable();
-	for(;;);
-}
-
-static void
-ebony_halt(void)
-{
-	local_irq_disable();
-	for(;;);
-}
-
-/*
- * Read the 440GP memory controller to get size of system memory.
- */
-static unsigned long __init
-ebony_find_end_of_memory(void)
-{
-	u32 i, bank_config;
-	u32 mem_size = 0;
-
-	for (i=0; i<4; i++)
-	{
-		switch (i)
-		{
-			case 0:
-				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B0CR);
-				break;
-			case 1:
-				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B1CR);
-				break;
-			case 2:
-				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B2CR);
-				break;
-			case 3:
-				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B3CR);
-				break;
-		}
-
-		bank_config = mfdcr(DCRN_SDRAM0_CFGDATA);
-
-		if (!(bank_config & SDRAM_CONFIG_BANK_ENABLE))
-			continue;
-		switch (SDRAM_CONFIG_BANK_SIZE(bank_config))
-		{
-			case SDRAM_CONFIG_SIZE_8M:
-				mem_size += PPC44x_MEM_SIZE_8M;
-				break;
-			case SDRAM_CONFIG_SIZE_16M:
-				mem_size += PPC44x_MEM_SIZE_16M;
-				break;
-			case SDRAM_CONFIG_SIZE_32M:
-				mem_size += PPC44x_MEM_SIZE_32M;
-				break;
-			case SDRAM_CONFIG_SIZE_64M:
-				mem_size += PPC44x_MEM_SIZE_64M;
-				break;
-			case SDRAM_CONFIG_SIZE_128M:
-				mem_size += PPC44x_MEM_SIZE_128M;
-				break;
-			case SDRAM_CONFIG_SIZE_256M:
-				mem_size += PPC44x_MEM_SIZE_256M;
-				break;
-			case SDRAM_CONFIG_SIZE_512M:
-				mem_size += PPC44x_MEM_SIZE_512M;
-				break;
-		}
-	}
-	return mem_size;
-}
-
-static void __init
-ebony_init_irq(void)
-{
-	int i;
-
-	ppc4xx_pic_init();
-
-	for (i = 0; i < NR_IRQS; i++)
-		irq_desc[i].handler = ppc4xx_pic;
-}
-
-#ifdef CONFIG_SERIAL_TEXT_DEBUG
-#include <linux/serialP.h>
-#include <linux/serial_reg.h>
-#include <asm/serial.h>
-
-static struct serial_state rs_table[RS_TABLE_SIZE] = {
-	SERIAL_PORT_DFNS	/* Defined in <asm/serial.h> */
-};
-
-static void
-ebony_progress(char *s, unsigned short hex)
-{
-	volatile char c;
-	volatile unsigned long com_port;
-	u16 shift;
-
-	com_port = (unsigned long)rs_table[0].iomem_base;
-	shift = rs_table[0].iomem_reg_shift;
-
-	while ((c = *s++) != 0) {
-		while ((*((volatile unsigned char *)com_port +
-				(UART_LSR << shift)) & UART_LSR_THRE) == 0)
-			;
-		*(volatile unsigned char *)com_port = c;
-
-	}
-
-	/* Send LF/CR to pretty up output */
-	while ((*((volatile unsigned char *)com_port +
-		(UART_LSR << shift)) & UART_LSR_THRE) == 0)
-		;
-	*(volatile unsigned char *)com_port = '\r';
-	while ((*((volatile unsigned char *)com_port +
-		(UART_LSR << shift)) & UART_LSR_THRE) == 0)
-		;
-	*(volatile unsigned char *)com_port = '\n';
-}
-#endif /* CONFIG_SERIAL_TEXT_DEBUG */
-
 void __init platform_init(unsigned long r3, unsigned long r4,
 		unsigned long r5, unsigned long r6, unsigned long r7)
 {
 	parse_bootinfo((struct bi_record *) (r3 + KERNELBASE));
 
+	ibm44x_platform_init();
+
 	ppc_md.setup_arch = ebony_setup_arch;
 	ppc_md.show_cpuinfo = ebony_show_cpuinfo;
-	ppc_md.init_IRQ = ebony_init_irq;
 	ppc_md.get_irq = NULL;		/* Set in ppc4xx_pic_init() */
 
-	ppc_md.find_end_of_memory = ebony_find_end_of_memory;
-
-	ppc_md.restart = ebony_restart;
-	ppc_md.power_off = ebony_power_off;
-	ppc_md.halt = ebony_halt;
-
 	ppc_md.calibrate_decr = ebony_calibrate_decr;
 	ppc_md.time_init = todc_time_init;
 	ppc_md.set_rtc_time = todc_set_rtc_time;
@@ -528,9 +379,6 @@ void __init platform_init(unsigned long r3, unsigned long r4,
 	ppc_md.nvram_read_val = todc_direct_read_val;
 	ppc_md.nvram_write_val = todc_direct_write_val;
 
-#ifdef CONFIG_SERIAL_TEXT_DEBUG
-	ppc_md.progress = ebony_progress;
-#endif /* CONFIG_SERIAL_TEXT_DEBUG */
 #ifdef CONFIG_KGDB
 	ppc_md.early_serial_map = ebony_early_serial_map;
 #endif
diff --git a/arch/ppc/platforms/4xx/ebony.h b/arch/ppc/platforms/4xx/ebony.h
index c4352e6bb..f90ddf309 100755
--- a/arch/ppc/platforms/4xx/ebony.h
+++ b/arch/ppc/platforms/4xx/ebony.h
@@ -40,21 +40,21 @@
 #define EBONY_RTC_SIZE		0x2000
 
 /* Flash */
-#define EBONY_FPGA_ADDR		0x0000000148300000
+#define EBONY_FPGA_ADDR		0x0000000148300000ULL
 #define EBONY_BOOT_SMALL_FLASH(x)	(x & 0x20)
 #define EBONY_ONBRD_FLASH_EN(x)		(x & 0x02)
 #define EBONY_FLASH_SEL(x)		(x & 0x01)
-#define EBONY_SMALL_FLASH_LOW1	0x00000001ff800000
-#define EBONY_SMALL_FLASH_LOW2	0x00000001ff880000
-#define EBONY_SMALL_FLASH_HIGH1	0x00000001fff00000
-#define EBONY_SMALL_FLASH_HIGH2	0x00000001fff80000
+#define EBONY_SMALL_FLASH_LOW1	0x00000001ff800000ULL
+#define EBONY_SMALL_FLASH_LOW2	0x00000001ff880000ULL
+#define EBONY_SMALL_FLASH_HIGH1	0x00000001fff00000ULL
+#define EBONY_SMALL_FLASH_HIGH2	0x00000001fff80000ULL
 #define EBONY_SMALL_FLASH_SIZE	0x80000
-#define EBONY_LARGE_FLASH_LOW	0x00000001ff800000
-#define EBONY_LARGE_FLASH_HIGH	0x00000001ffc00000
+#define EBONY_LARGE_FLASH_LOW	0x00000001ff800000ULL
+#define EBONY_LARGE_FLASH_HIGH	0x00000001ffc00000ULL
 #define EBONY_LARGE_FLASH_SIZE	0x400000
 
-#define EBONY_SMALL_FLASH_BASE	0x00000001fff80000
-#define EBONY_LARGE_FLASH_BASE	0x00000001ff800000
+#define EBONY_SMALL_FLASH_BASE	0x00000001fff80000ULL
+#define EBONY_LARGE_FLASH_BASE	0x00000001ff800000ULL
 
 /*
  * Serial port defines
diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c
index 6376890e3..c981f70aa 100644
--- a/arch/ppc/platforms/4xx/ocotea.c
+++ b/arch/ppc/platforms/4xx/ocotea.c
@@ -47,6 +47,7 @@
 #include <asm/todc.h>
 #include <asm/bootinfo.h>
 #include <asm/ppc4xx_pic.h>
+#include <asm/ppcboot.h>
 
 #include <syslib/ibm440gx_common.h>
 
@@ -57,27 +58,21 @@
  */
 #include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h"
 
-extern void abort(void);
+bd_t __res;
+
+static struct ibm44x_clocks clocks __initdata;
 
 static void __init
 ocotea_calibrate_decr(void)
 {
 	unsigned int freq;
 
-	freq = OCOTEA_SYSCLK;
-
-	tb_ticks_per_jiffy = freq / HZ;
-	tb_to_us = mulhwu_scale_factor(freq, 1000000);
-
-	/* Set the time base to zero */
-	mtspr(SPRN_TBWL, 0);
-	mtspr(SPRN_TBWU, 0);
-
-	/* Clear any pending timer interrupts */
-	mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
+	if (mfspr(SPRN_CCR1) & CCR1_TCS)
+		freq = OCOTEA_TMR_CLK;
+	else
+		freq = clocks.cpu;
 
-	/* Enable decrementer interrupt */
-	mtspr(SPRN_TCR, TCR_DIE);
+	ibm44x_calibrate_decr(freq);
 }
 
 static int
@@ -88,6 +83,7 @@ ocotea_show_cpuinfo(struct seq_file *m)
 
 	return 0;
 }
+
 static inline int
 ocotea_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
 {
@@ -107,6 +103,46 @@ ocotea_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
 	return PCI_IRQ_TABLE_LOOKUP;
 }
 
+static void __init ocotea_set_emacdata(void)
+{
+	struct ocp_def *def;
+	struct ocp_func_emac_data *emacdata;
+	int i;
+
+	/*
+	 * Note: Current rev. board only operates in Group 4a
+	 * mode, so we always set EMAC0-1 for SMII and EMAC2-3
+	 * for RGMII (though these could run in RTBI just the same).
+	 *
+	 * The FPGA reg 3 information isn't even suitable for
+	 * determining the phy_mode, so if the board becomes
+	 * usable in !4a, it will be necessary to parse an environment
+	 * variable from the firmware or similar to properly configure
+	 * the phy_map/phy_mode.
+	 */
+	/* Set phy_map, phy_mode, and mac_addr for each EMAC */
+	for (i=0; i<4; i++) {
+		def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, i);
+		emacdata = def->additions;
+		if (i < 2) {
+			emacdata->phy_map = 0x00000001;	/* Skip 0x00 */
+			emacdata->phy_mode = PHY_MODE_SMII;
+		}
+		else {
+			emacdata->phy_map = 0x0000ffff; /* Skip 0x00-0x0f */
+			emacdata->phy_mode = PHY_MODE_RGMII;
+		}
+		if (i == 0)
+			memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6);
+		else if (i == 1)
+			memcpy(emacdata->mac_addr, __res.bi_enet1addr, 6);
+		else if (i == 2)
+			memcpy(emacdata->mac_addr, __res.bi_enet2addr, 6);
+		else if (i == 3)
+			memcpy(emacdata->mac_addr, __res.bi_enet3addr, 6);
+	}
+}
+
 #define PCIX_READW(offset) \
 	(readw((u32)pcix_reg_base+offset))
 
@@ -209,7 +245,7 @@ ocotea_setup_hose(void)
 TODC_ALLOC();
 
 static void __init
-ocotea_early_serial_map(const struct ibm44x_clocks *clks)
+ocotea_early_serial_map(void)
 {
 	struct uart_port port;
 
@@ -217,7 +253,7 @@ ocotea_early_serial_map(const struct ibm44x_clocks *clks)
 	memset(&port, 0, sizeof(port));
 	port.membase = ioremap64(PPC440GX_UART0_ADDR, 8);
 	port.irq = UART0_INT;
-	port.uartclk = clks->uart0;
+	port.uartclk = clocks.uart0;
 	port.regshift = 0;
 	port.iotype = SERIAL_IO_MEM;
 	port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST;
@@ -229,7 +265,7 @@ ocotea_early_serial_map(const struct ibm44x_clocks *clks)
 
 	port.membase = ioremap64(PPC440GX_UART1_ADDR, 8);
 	port.irq = UART1_INT;
-	port.uartclk = clks->uart1;
+	port.uartclk = clocks.uart1;
 	port.line = 1;
 
 	if (early_serial_setup(&port) != 0) {
@@ -240,41 +276,7 @@ ocotea_early_serial_map(const struct ibm44x_clocks *clks)
 static void __init
 ocotea_setup_arch(void)
 {
-	unsigned char *addr;
-	unsigned long long mac64;
-	struct ocp_def *def;
-	struct ocp_func_emac_data *emacdata;
-	int i;
-	struct ibm44x_clocks clocks;
-
-	/*
-	 * Note: Current rev. board only operates in Group 4a
-	 * mode, so we always set EMAC0-1 for SMII and EMAC2-3
-	 * for RGMII (though these could run in RTBI just the same).
-	 *
-	 * The FPGA reg 3 information isn't even suitable for
-	 * determining the phy_mode, so if the board becomes
-	 * usable in !4a, it will be necessary to parse an environment
-	 * variable from the firmware or similar to properly configure
-	 * the phy_map/phy_mode.
-	 */
-	/* Set phy_map, phy_mode, and mac_addr for each EMAC */
-	addr = ioremap64(OCOTEA_MAC_BASE, OCOTEA_MAC_SIZE);
-	for (i=0; i<4; i++) {
-		mac64 = simple_strtoull(addr+OCOTEA_MAC_OFFSET*i, 0, 16);
-		def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, i);
-		emacdata = def->additions;
-		if (i < 2) {
-			emacdata->phy_map = 0x00000001;	/* Skip 0x00 */
-			emacdata->phy_mode = PHY_MODE_SMII;
-		}
-		else {
-			emacdata->phy_map = 0x0000ffff; /* Skip 0x00-0x0f */
-			emacdata->phy_mode = PHY_MODE_RGMII;
-		}
-		memcpy(emacdata->mac_addr, (char *)&mac64+2, 6);
-	}
-	iounmap(addr);
+	ocotea_set_emacdata();
 
 	ibm440gx_tah_enable();
 
@@ -319,173 +321,33 @@ ocotea_setup_arch(void)
 		ROOT_DEV = Root_HDA1;
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
-	ocotea_early_serial_map(&clocks);
+	ocotea_early_serial_map();
 
 	/* Identify the system */
 	printk("IBM Ocotea port (MontaVista Software, Inc. <source@mvista.com>)\n");
 }
 
-static void
-ocotea_restart(char *cmd)
-{
-	local_irq_disable();
-	abort();
-}
-
-static void
-ocotea_power_off(void)
-{
-	local_irq_disable();
-	for(;;);
-}
-
-static void
-ocotea_halt(void)
-{
-	local_irq_disable();
-	for(;;);
-}
-
-/*
- * Read the 440GX memory controller to get size of system memory.
- */
-static unsigned long __init
-ocotea_find_end_of_memory(void)
-{
-	u32 i, bank_config;
-	u32 mem_size = 0;
-
-	for (i=0; i<4; i++)
-	{
-		switch (i)
-		{
-			case 0:
-				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B0CR);
-				break;
-			case 1:
-				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B1CR);
-				break;
-			case 2:
-				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B2CR);
-				break;
-			case 3:
-				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B3CR);
-				break;
-		}
-
-		bank_config = mfdcr(DCRN_SDRAM0_CFGDATA);
-
-		if (!(bank_config & SDRAM_CONFIG_BANK_ENABLE))
-			continue;
-		switch (SDRAM_CONFIG_BANK_SIZE(bank_config))
-		{
-			case SDRAM_CONFIG_SIZE_8M:
-				mem_size += PPC44x_MEM_SIZE_8M;
-				break;
-			case SDRAM_CONFIG_SIZE_16M:
-				mem_size += PPC44x_MEM_SIZE_16M;
-				break;
-			case SDRAM_CONFIG_SIZE_32M:
-				mem_size += PPC44x_MEM_SIZE_32M;
-				break;
-			case SDRAM_CONFIG_SIZE_64M:
-				mem_size += PPC44x_MEM_SIZE_64M;
-				break;
-			case SDRAM_CONFIG_SIZE_128M:
-				mem_size += PPC44x_MEM_SIZE_128M;
-				break;
-			case SDRAM_CONFIG_SIZE_256M:
-				mem_size += PPC44x_MEM_SIZE_256M;
-				break;
-			case SDRAM_CONFIG_SIZE_512M:
-				mem_size += PPC44x_MEM_SIZE_512M;
-				break;
-		}
-	}
-	return mem_size;
-}
-
-static void __init
-ocotea_init_irq(void)
-{
-	int i;
-
-	ppc4xx_pic_init();
-
-	for (i = 0; i < NR_IRQS; i++)
-		irq_desc[i].handler = ppc4xx_pic;
-}
-
-#ifdef CONFIG_SERIAL_TEXT_DEBUG
-#include <linux/serialP.h>
-#include <linux/serial_reg.h>
-#include <asm/serial.h>
-struct serial_state rs_table[RS_TABLE_SIZE] = {
-	SERIAL_PORT_DFNS	/* Defined in <asm/serial.h> */
-};
-
-static void
-ocotea_progress(char *s, unsigned short hex)
-{
-	volatile char c;
-	volatile unsigned long com_port;
-	u16 shift;
-
-	com_port = (unsigned long)rs_table[0].iomem_base;
-	shift = rs_table[0].iomem_reg_shift;
-
-	while ((c = *s++) != 0) {
-		while ((*((volatile unsigned char *)com_port +
-				(UART_LSR << shift)) & UART_LSR_THRE) == 0)
-			;
-		*(volatile unsigned char *)com_port = c;
-
-	}
-
-	/* Send LF/CR to pretty up output */
-	while ((*((volatile unsigned char *)com_port +
-		(UART_LSR << shift)) & UART_LSR_THRE) == 0)
-		;
-	*(volatile unsigned char *)com_port = '\r';
-	while ((*((volatile unsigned char *)com_port +
-		(UART_LSR << shift)) & UART_LSR_THRE) == 0)
-		;
-	*(volatile unsigned char *)com_port = '\n';
-}
-#endif /* CONFIG_SERIAL_TEXT_DEBUG */
-
-#if 0
-static void __init
-ocotea_map_io(void)
-{
-	io_block_mapping(0xe0000000, 0x0000000140000000,
-			 0x00001000, _PAGE_IO);
-}
-#endif
-
 void __init platform_init(unsigned long r3, unsigned long r4,
 		unsigned long r5, unsigned long r6, unsigned long r7)
 {
-	parse_bootinfo((struct bi_record *) (r3 + KERNELBASE));
+	parse_bootinfo(find_bootinfo());
+
+	/*
+	 * If we were passed in a board information, copy it into the
+	 * residual data area.
+	 */
+	if (r3)
+		__res = *(bd_t *)(r3 + KERNELBASE);
 
 	/* Disable L2-Cache due to hardware issues */
 	ibm440gx_l2c_disable();
 
+	ibm44x_platform_init();
+
 	ppc_md.setup_arch = ocotea_setup_arch;
 	ppc_md.show_cpuinfo = ocotea_show_cpuinfo;
-	ppc_md.init_IRQ = ocotea_init_irq;
 	ppc_md.get_irq = NULL;		/* Set in ppc4xx_pic_init() */
 
-	ppc_md.find_end_of_memory = ocotea_find_end_of_memory;
-
-	ppc_md.restart = ocotea_restart;
-	ppc_md.power_off = ocotea_power_off;
-	ppc_md.halt = ocotea_halt;
-
 	ppc_md.calibrate_decr = ocotea_calibrate_decr;
 	ppc_md.time_init = todc_time_init;
 	ppc_md.set_rtc_time = todc_set_rtc_time;
@@ -494,9 +356,6 @@ void __init platform_init(unsigned long r3, unsigned long r4,
 	ppc_md.nvram_read_val = todc_direct_read_val;
 	ppc_md.nvram_write_val = todc_direct_write_val;
 
-#ifdef CONFIG_SERIAL_TEXT_DEBUG
-	ppc_md.progress = ocotea_progress;
-#endif /* CONFIG_SERIAL_TEXT_DEBUG */
 #ifdef CONFIG_KGDB
 	ppc_md.early_serial_map = ocotea_early_serial_map;
 #endif
diff --git a/arch/ppc/platforms/4xx/ocotea.h b/arch/ppc/platforms/4xx/ocotea.h
index 17fe8dada..90cd0afa1 100644
--- a/arch/ppc/platforms/4xx/ocotea.h
+++ b/arch/ppc/platforms/4xx/ocotea.h
@@ -24,13 +24,14 @@
 /* F/W TLB mapping used in bootloader glue to reset EMAC */
 #define PPC44x_EMAC0_MR0	0xE0000800
 
-/* Location of MAC addresses in firmware */
-#define OCOTEA_MAC_BASE		(OCOTEA_SMALL_FLASH_HIGH+0xb0500)
-#define OCOTEA_MAC_SIZE		0x200
-#define OCOTEA_MAC_OFFSET	0x100
-
-/* Default clock rate */
-#define OCOTEA_SYSCLK		25000000
+/* Location of MAC addresses in PIBS image */
+#define OCOTEA_PIBS_FLASH	0xfff00000
+#define OCOTEA_PIBS_MAC_BASE	(OCOTEA_PIBS_FLASH+0xb0500)
+#define OCOTEA_PIBS_MAC_SIZE	0x200
+#define OCOTEA_PIBS_MAC_OFFSET	0x100
+
+/* External timer clock frequency */
+#define OCOTEA_TMR_CLK	25000000
 
 /* RTC/NVRAM location */
 #define OCOTEA_RTC_ADDR		0x0000000148000000ULL
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c
index aada7e456..686dd6d9a 100644
--- a/arch/ppc/platforms/85xx/mpc8540_ads.c
+++ b/arch/ppc/platforms/85xx/mpc8540_ads.c
@@ -120,10 +120,6 @@ mpc8540ads_setup_arch(void)
 	mpc85xx_setup_hose();
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
 #ifdef CONFIG_SERIAL_8250
 	mpc85xx_early_serial_map();
 #endif
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
index c7e53e39c..5eb6e4218 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
@@ -307,7 +307,7 @@ mpc85xx_exclude_device(u_char bus, u_char devfn)
 {
 	if (bus == 0 && PCI_SLOT(devfn) == 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
-#if CONFIG_85xx_PCI2
+#ifdef CONFIG_85xx_PCI2
 	/* With the current code we know PCI2 will be bus 2, however this may
 	 * not be guarnteed */
 	if (bus == 2 && PCI_SLOT(devfn) == 0)
@@ -358,10 +358,6 @@ mpc85xx_cds_setup_arch(void)
         mpc85xx_setup_hose();
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-        conswitchp = &dummy_con;
-#endif
-
 #ifdef CONFIG_SERIAL_8250
         mpc85xx_early_serial_map();
 #endif
diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c
index a4a91aa6a..50cc50a0c 100644
--- a/arch/ppc/platforms/85xx/sbc8560.c
+++ b/arch/ppc/platforms/85xx/sbc8560.c
@@ -144,9 +144,6 @@ sbc8560_setup_arch(void)
 	/* setup PCI host bridges */
 	mpc85xx_setup_hose();
 #endif
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
 #ifdef CONFIG_SERIAL_8250
 	sbc8560_early_serial_map();
 #endif
diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
index c59d4871d..c393f58e5 100644
--- a/arch/ppc/platforms/Makefile
+++ b/arch/ppc/platforms/Makefile
@@ -21,23 +21,21 @@ endif
 obj-$(CONFIG_PMAC_BACKLIGHT)	+= pmac_backlight.o
 obj-$(CONFIG_PREP_RESIDUAL)	+= residual.o
 obj-$(CONFIG_ADIR)		+= adir_setup.o adir_pic.o adir_pci.o
-obj-$(CONFIG_EST8260)		+= est8260_setup.o
-obj-$(CONFIG_PQ2ADS)		+= pq2ads_setup.o
+obj-$(CONFIG_PQ2ADS)		+= pq2ads.o
 obj-$(CONFIG_TQM8260)		+= tqm8260_setup.o
 obj-$(CONFIG_EV64260)		+= ev64260_setup.o
 obj-$(CONFIG_GEMINI)		+= gemini_pci.o gemini_setup.o gemini_prom.o
 obj-$(CONFIG_K2)		+= k2.o
-obj-$(CONFIG_LOPEC)		+= lopec_setup.o lopec_pci.o
+obj-$(CONFIG_LOPEC)		+= lopec.o
 obj-$(CONFIG_MCPN765)		+= mcpn765.o
 obj-$(CONFIG_MENF1)		+= menf1_setup.o menf1_pci.o
-obj-$(CONFIG_MVME5100)		+= mvme5100_setup.o mvme5100_pci.o
+obj-$(CONFIG_MVME5100)		+= mvme5100.o
 obj-$(CONFIG_PAL4)		+= pal4_setup.o pal4_pci.o
 obj-$(CONFIG_PCORE)		+= pcore.o
 obj-$(CONFIG_POWERPMC250)	+= powerpmc250.o
 obj-$(CONFIG_PPLUS)		+= pplus.o
 obj-$(CONFIG_PRPMC750)		+= prpmc750.o
 obj-$(CONFIG_PRPMC800)		+= prpmc800.o
-obj-$(CONFIG_RPX8260)		+= rpx8260.o
 obj-$(CONFIG_SANDPOINT)		+= sandpoint.o
 obj-$(CONFIG_SBC82xx)		+= sbc82xx.o
 obj-$(CONFIG_SPRUCE)		+= spruce.o
diff --git a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c
index 56be78eb4..3514bb9ed 100644
--- a/arch/ppc/platforms/chrp_setup.c
+++ b/arch/ppc/platforms/chrp_setup.c
@@ -250,13 +250,6 @@ chrp_setup_arch(void)
 	 */
 	sio_init();
 
-	/*
-	 *  Setup the console operations
-	 */
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
 	/* Get the event scan rate for the rtas so we know how
 	 * often it expects a heartbeat. -- Cort
 	 */
@@ -382,7 +375,7 @@ void __init chrp_init_IRQ(void)
 {
 	struct device_node *np;
 	int i;
-	unsigned long chrp_int_ack;
+	unsigned long chrp_int_ack = 0;
 	unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS];
 #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
 	struct device_node *kbd;
diff --git a/arch/ppc/platforms/chrp_smp.c b/arch/ppc/platforms/chrp_smp.c
index 71f62a055..863d1e325 100644
--- a/arch/ppc/platforms/chrp_smp.c
+++ b/arch/ppc/platforms/chrp_smp.c
@@ -24,7 +24,6 @@
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/hardirq.h>
 #include <asm/sections.h>
 #include <asm/io.h>
 #include <asm/prom.h>
diff --git a/arch/ppc/platforms/est8260.h b/arch/ppc/platforms/est8260.h
index bc51f072a..adba68ecf 100644
--- a/arch/ppc/platforms/est8260.h
+++ b/arch/ppc/platforms/est8260.h
@@ -10,6 +10,9 @@
 
 #define BOOTROM_RESTART_ADDR	((uint)0xff000104)
 
+/* For our show_cpuinfo hooks. */
+#define CPUINFO_VENDOR		"EST Corporation"
+#define CPUINFO_MACHINE		"SBC8260 PowerPC"
 
 /* A Board Information structure that is given to a program when
  * prom starts it up.
diff --git a/arch/ppc/platforms/k2.c b/arch/ppc/platforms/k2.c
index 4e2e18a52..8a602039f 100644
--- a/arch/ppc/platforms/k2.c
+++ b/arch/ppc/platforms/k2.c
@@ -464,10 +464,6 @@ static void __init k2_setup_arch(void)
 		ROOT_DEV = Root_HDC1;
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
 	/* Identify the system */
 	printk(KERN_INFO "System Identification: SBS K2 - PowerPC 750 @ "
 			"%d Mhz\n", k2_get_cpu_speed() / 1000000);
diff --git a/arch/ppc/platforms/lite5200.c b/arch/ppc/platforms/lite5200.c
index 043040dc9..db6ea440c 100644
--- a/arch/ppc/platforms/lite5200.c
+++ b/arch/ppc/platforms/lite5200.c
@@ -36,6 +36,8 @@
 #include <asm/mpc52xx.h>
 
 
+extern int powersave_nap;
+
 /* Board data given by U-Boot */
 bd_t __res;
 EXPORT_SYMBOL(__res);	/* For modules */
@@ -64,25 +66,55 @@ struct ocp_def board_ocp[] = {
 		.vendor		= OCP_VENDOR_INVALID
 	}
 };
-	
+
 
 /* ======================================================================== */
 /* Platform specific code                                                   */
 /* ======================================================================== */
 
 static int
-icecube_show_cpuinfo(struct seq_file *m)
+lite5200_show_cpuinfo(struct seq_file *m)
 {
 	seq_printf(m, "machine\t\t: Freescale LITE5200\n");
 	return 0;
 }
 
 static void __init
-icecube_setup_arch(void)
+lite5200_setup_cpu(void)
 {
+	struct mpc52xx_intr *intr;
+
+	u32 intr_ctrl;
+
+	/* Map zones */
+	intr = (struct mpc52xx_intr *)
+		ioremap(MPC52xx_INTR,sizeof(struct mpc52xx_intr));
+
+	if (!intr) {
+		printk("lite5200.c: Error while mapping INTR during lite5200_setup_cpu\n");
+		goto unmap_regs;
+	}
+
+	/* IRQ[0-3] setup : IRQ0     - Level Active Low  */
+	/*                  IRQ[1-3] - Level Active High */
+	intr_ctrl = in_be32(&intr->ctrl);
+	intr_ctrl &= ~0x00ff0000;
+	intr_ctrl |=  0x00c00000;
+	out_be32(&intr->ctrl, intr_ctrl);
+
+	/* Unmap reg zone */
+unmap_regs:
+	if (intr) iounmap(intr);
+}
 
+static void __init
+lite5200_setup_arch(void)
+{
 	/* Add board OCP definitions */
 	mpc52xx_add_board_devices(board_ocp);
+
+	/* CPU & Port mux setup */
+	lite5200_setup_cpu();
 }
 
 void __init
@@ -110,7 +142,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
 			initrd_end = r5 + KERNELBASE;
 		}
 #endif
-	
+
 		/* Load the command line */
 		if (r6) {
 			*(char *)(r7+KERNELBASE) = 0;
@@ -120,14 +152,17 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
 
 	/* BAT setup */
 	mpc52xx_set_bat();
-	
+
 	/* No ISA bus AFAIK */
 	isa_io_base		= 0;
 	isa_mem_base		= 0;
 
+	/* Powersave */
+	powersave_nap = 1;	/* We allow this platform to NAP */
+
 	/* Setup the ppc_md struct */
-	ppc_md.setup_arch	= icecube_setup_arch;
-	ppc_md.show_cpuinfo	= icecube_show_cpuinfo;
+	ppc_md.setup_arch	= lite5200_setup_arch;
+	ppc_md.show_cpuinfo	= lite5200_show_cpuinfo;
 	ppc_md.show_percpuinfo	= NULL;
 	ppc_md.init_IRQ		= mpc52xx_init_irq;
 	ppc_md.get_irq		= mpc52xx_get_irq;
@@ -138,12 +173,12 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
 	ppc_md.restart		= mpc52xx_restart;
 	ppc_md.power_off	= mpc52xx_power_off;
 	ppc_md.halt		= mpc52xx_halt;
-	
-		/* No time keeper on the IceCube */
+
+		/* No time keeper on the LITE5200 */
 	ppc_md.time_init	= NULL;
 	ppc_md.get_rtc_time	= NULL;
 	ppc_md.set_rtc_time	= NULL;
-	
+
 	ppc_md.calibrate_decr	= mpc52xx_calibrate_decr;
 #ifdef CONFIG_SERIAL_TEXT_DEBUG
 	ppc_md.progress		= mpc52xx_progress;
diff --git a/arch/ppc/platforms/mcpn765.c b/arch/ppc/platforms/mcpn765.c
index 06ed9384f..348118b75 100644
--- a/arch/ppc/platforms/mcpn765.c
+++ b/arch/ppc/platforms/mcpn765.c
@@ -58,8 +58,6 @@
 #include <asm/kgdb.h>
 
 #include "mcpn765.h"
-#include "mcpn765_serial.h"
-
 
 static u_char mcpn765_openpic_initsenses[] __initdata = {
 	(IRQ_SENSE_EDGE  | IRQ_POLARITY_POSITIVE),/* 16: i8259 cascade */
@@ -324,10 +322,6 @@ mcpn765_setup_arch(void)
 		ROOT_DEV = Root_SDA2;
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
 	if ( ppc_md.progress )
 		ppc_md.progress("mcpn765_setup_arch: find_bridges", 0);
 
diff --git a/arch/ppc/platforms/mcpn765.h b/arch/ppc/platforms/mcpn765.h
index 872338317..4d35ecad0 100644
--- a/arch/ppc/platforms/mcpn765.h
+++ b/arch/ppc/platforms/mcpn765.h
@@ -6,7 +6,7 @@
  * Author: Mark A. Greer
  *         mgreer@mvista.com
  *
- * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
+ * 2001-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.
@@ -25,6 +25,7 @@
 
 #ifndef __PPC_PLATFORMS_MCPN765_H
 #define __PPC_PLATFORMS_MCPN765_H
+#include <linux/config.h>
 
 /* PCI Memory space mapping info */
 #define	MCPN765_PCI_MEM_SIZE		0x40000000U
@@ -65,14 +66,57 @@
 #define	MCPN765_BOARD_EXT_FEATURE_REG	0xfef880f0U
 #define	MCPN765_BOARD_LAST_RESET_REG	0xfef880f8U
 
-/* UART base addresses are defined in <asm-ppc/platforms/mcpn765_serial.h> */
+/* Defines for UART */
+
+/* Define the UART base addresses */
+#define	MCPN765_SERIAL_1		0xfef88000
+#define	MCPN765_SERIAL_2		0xfef88200
+#define	MCPN765_SERIAL_3		0xfef88400
+#define	MCPN765_SERIAL_4		0xfef88600
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE  64
+#else
+#define RS_TABLE_SIZE  4
+#endif
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD	( 1843200 / 16 )
+#define UART_CLK	1843200
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#endif
+
+/* All UART IRQ's are wire-OR'd to IRQ 17 */
+#define STD_SERIAL_PORT_DFNS \
+        { 0, BASE_BAUD, MCPN765_SERIAL_1, 17, STD_COM_FLAGS, /* ttyS0 */\
+		iomem_base: (u8 *)MCPN765_SERIAL_1,			\
+		iomem_reg_shift: 4,					\
+		io_type: SERIAL_IO_MEM },				\
+        { 0, BASE_BAUD, MCPN765_SERIAL_2, 17, STD_COM_FLAGS, /* ttyS1 */\
+		iomem_base: (u8 *)MCPN765_SERIAL_2,			\
+		iomem_reg_shift: 4,					\
+		io_type: SERIAL_IO_MEM },				\
+        { 0, BASE_BAUD, MCPN765_SERIAL_3, 17, STD_COM_FLAGS, /* ttyS2 */\
+		iomem_base: (u8 *)MCPN765_SERIAL_3,			\
+		iomem_reg_shift: 4,					\
+		io_type: SERIAL_IO_MEM },				\
+        { 0, BASE_BAUD, MCPN765_SERIAL_4, 17, STD_COM_FLAGS, /* ttyS3 */\
+		iomem_base: (u8 *)MCPN765_SERIAL_4,			\
+		iomem_reg_shift: 4,					\
+		io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DFNS
 
 /* Define the NVRAM/RTC address strobe & data registers */
 #define MCPN765_PHYS_NVRAM_AS0          0xfef880c8U
 #define MCPN765_PHYS_NVRAM_AS1          0xfef880d0U
 #define MCPN765_PHYS_NVRAM_DATA         0xfef880d8U
 
-
 extern void mcpn765_find_bridges(void);
 
 #endif /* __PPC_PLATFORMS_MCPN765_H */
diff --git a/arch/ppc/platforms/mpc5200.c b/arch/ppc/platforms/mpc5200.c
index 30b6936c3..dce7225ad 100644
--- a/arch/ppc/platforms/mpc5200.c
+++ b/arch/ppc/platforms/mpc5200.c
@@ -16,6 +16,12 @@
 #include <asm/ocp.h>
 #include <asm/mpc52xx.h>
 
+
+struct ocp_fs_i2c_data mpc5200_i2c_def = {
+        .flags  = FS_I2C_CLOCK_5200,
+};
+
+
 /* Here is the core_ocp struct.
  * With all the devices common to all board. Even if port multiplexing is
  * not setup for them (if the user don't want them, just don't select the
@@ -23,6 +29,24 @@
  * board specific file.
  */
 struct ocp_def core_ocp[] = {
+	{
+		.vendor         = OCP_VENDOR_FREESCALE,
+		.function       = OCP_FUNC_IIC,
+		.index          = 0,
+		.paddr          = MPC52xx_I2C1,
+		.irq            = OCP_IRQ_NA,   /* MPC52xx_IRQ_I2C1 - Buggy */
+		.pm             = OCP_CPM_NA,
+		.additions      = &mpc5200_i2c_def,
+	},
+	{
+		.vendor         = OCP_VENDOR_FREESCALE,
+		.function       = OCP_FUNC_IIC,
+		.index          = 1,
+		.paddr          = MPC52xx_I2C2,
+		.irq            = OCP_IRQ_NA,   /* MPC52xx_IRQ_I2C2 - Buggy */
+		.pm             = OCP_CPM_NA,
+		.additions      = &mpc5200_i2c_def,
+	},
 	{	/* Terminating entry */
 		.vendor		= OCP_VENDOR_INVALID
 	}
diff --git a/arch/ppc/platforms/mvme5100.h b/arch/ppc/platforms/mvme5100.h
index 5cc61d18b..edd479439 100644
--- a/arch/ppc/platforms/mvme5100.h
+++ b/arch/ppc/platforms/mvme5100.h
@@ -63,10 +63,29 @@
 #define MVME5100_SERIAL_IRQ		1
 #endif
 
-#define MVME5100_WINBOND_DEVFN		0x58
-#define MVME5100_WINBOND_VIDDID		0x056510ad
+#define RS_TABLE_SIZE  4
 
-extern void mvme5100_setup_bridge(void);
+#define BASE_BAUD ( MVME5100_BASE_BAUD / 16 )
+
+#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF
+
+/* All UART IRQ's are wire-OR'd to one MPIC IRQ */
+#define STD_SERIAL_PORT_DFNS \
+        { 0, BASE_BAUD, MVME5100_SERIAL_1, \
+		MVME5100_SERIAL_IRQ, \
+		STD_COM_FLAGS, /* ttyS0 */ \
+		iomem_base: (unsigned char *)MVME5100_SERIAL_1,		\
+		iomem_reg_shift: 4,					\
+		io_type: SERIAL_IO_MEM },				\
+        { 0, BASE_BAUD, MVME5100_SERIAL_2, \
+		MVME5100_SERIAL_IRQ, \
+		STD_COM_FLAGS, /* ttyS1 */ \
+		iomem_base: (unsigned char *)MVME5100_SERIAL_2,		\
+		iomem_reg_shift: 4,					\
+		io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DFNS
 
 #endif /* __ASM_MVME5100_H__ */
 #endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/pcore.c b/arch/ppc/platforms/pcore.c
index 9c428720d..da022ecd8 100644
--- a/arch/ppc/platforms/pcore.c
+++ b/arch/ppc/platforms/pcore.c
@@ -228,10 +228,6 @@ pcore_setup_arch(void)
 		ROOT_DEV = Root_SDA2;
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
  	printk(KERN_INFO "Force PowerCore ");
 	if (board_type == PCORE_TYPE_6750)
 		printk("6750\n");
diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c
index 5b2221a14..b51b37d16 100644
--- a/arch/ppc/platforms/pmac_cpufreq.c
+++ b/arch/ppc/platforms/pmac_cpufreq.c
@@ -24,10 +24,10 @@
 #include <linux/init.h>
 #include <linux/sysdev.h>
 #include <linux/i2c.h>
+#include <linux/hardirq.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/irq.h>
-#include <asm/hardirq.h>
 #include <asm/pmac_feature.h>
 #include <asm/mmu_context.h>
 #include <asm/sections.h>
@@ -301,7 +301,6 @@ static int __pmac pmu_set_cpu_speed(int low_speed)
 static int __pmac do_set_cpu_speed(int speed_mode)
 {
 	struct cpufreq_freqs freqs;
-	int rc;
 
 	freqs.old = cur_freq;
 	freqs.new = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq;
@@ -315,7 +314,7 @@ static int __pmac do_set_cpu_speed(int speed_mode)
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 	cur_freq = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq;
 
-	return rc;
+	return 0;
 }
 
 static int __pmac pmac_cpufreq_verify(struct cpufreq_policy *policy)
@@ -498,7 +497,7 @@ static int __pmac pmac_cpufreq_init_7447A(struct device_node *cpunode)
  *  - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz)
  *  - Titanium PowerBook 400 (PMU based, 300Mhz & 400Mhz)
  *  - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz)
- *  - iBook2 500 (PMU based, 400Mhz & 500Mhz)
+ *  - iBook2 500/600 (PMU based, 400Mhz & 500/600Mhz)
  *  - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage)
  *  - Recent MacRISC3 laptops
  *  - iBook G4s and PowerBook G4s with 7447A CPUs
@@ -533,11 +532,8 @@ static int __init pmac_cpufreq_setup(void)
 		   machine_is_compatible("PowerBook3,5") ||
 		   machine_is_compatible("MacRISC3")) {
 		pmac_cpufreq_init_MacRISC3(cpunode);
-	/* Else check for iBook2 500 */
+	/* Else check for iBook2 500/600 */
 	} else if (machine_is_compatible("PowerBook4,1")) {
-		/* We only know about 500Mhz model */
-		if (cur_freq < 450000 || cur_freq > 550000)
-			goto out;
 		hi_freq = cur_freq;
 		low_freq = 400000;
 		set_speed_proc = pmu_set_cpu_speed;
diff --git a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c
index 35714de24..24b221450 100644
--- a/arch/ppc/platforms/pmac_feature.c
+++ b/arch/ppc/platforms/pmac_feature.c
@@ -2665,7 +2665,7 @@ set_initial_features(void)
 			struct device_node *p = of_get_parent(ui2c);
 			if (p && !strcmp(p->name, "uni-n"))
 				break;
-			ui2c = of_find_node_by_type(np, "i2c");
+			ui2c = of_find_node_by_type(ui2c, "i2c");
 		}
 		if (ui2c == NULL)
 			break;
diff --git a/arch/ppc/platforms/pmac_pci.c b/arch/ppc/platforms/pmac_pci.c
index 9dcc4e2e5..4e53bea90 100644
--- a/arch/ppc/platforms/pmac_pci.c
+++ b/arch/ppc/platforms/pmac_pci.c
@@ -50,6 +50,7 @@ static struct pci_controller *u3_agp;
 #endif /* CONFIG_POWER4 */
 
 extern u8 pci_cache_line_size;
+extern int pcibios_assign_bus_offset;
 
 struct pci_dev *k2_skiplist[2];
 
@@ -315,6 +316,10 @@ u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
 	unsigned int addr;
 	int i;
 
+	struct device_node *np = pci_busdev_to_OF_node(bus, devfn);
+	if (np == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
 	/*
 	 * When a device in K2 is powered down, we die on config
 	 * cycle accesses. Fix that here.
@@ -362,6 +367,9 @@ u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
 	unsigned int addr;
 	int i;
 
+	struct device_node *np = pci_busdev_to_OF_node(bus, devfn);
+	if (np == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
 	/*
 	 * When a device in K2 is powered down, we die on config
 	 * cycle accesses. Fix that here.
@@ -565,6 +573,14 @@ pmac_find_bridges(void)
 
 	init_p2pbridge();
 	fixup_nec_usb2();
+	
+	/* We are still having some issues with the Xserve G4, enabling
+	 * some offset between bus number and domains for now when we
+	 * assign all busses should help for now
+	 */
+	if (pci_assign_all_busses)
+		pcibios_assign_bus_offset = 0x10;
+
 #ifdef CONFIG_POWER4 
 	/* There is something wrong with DMA on U3/HT. I haven't figured out
 	 * the details yet, but if I set the cache line size to 128 bytes like
@@ -707,7 +723,7 @@ setup_u3_ht(struct pci_controller* hose, struct reg_property *addr)
 	 * properties or figuring out the U3 address space decoding logic and
 	 * then read its configuration register (if any).
 	 */
-	hose->io_base_phys = 0xf4000000 + 0x00400000;
+	hose->io_base_phys = 0xf4000000;
 	hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000);
 	isa_io_base = (unsigned long) hose->io_base_virt;
 	hose->io_resource.name = np->full_name;
@@ -1034,6 +1050,8 @@ void pmac_pci_fixup_cardbus(struct pci_dev* dev)
 	}
 }
 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_ANY_ID, pmac_pci_fixup_cardbus);
+
 void pmac_pci_fixup_pciata(struct pci_dev* dev)
 {
        u8 progif = 0;
@@ -1074,6 +1092,8 @@ void pmac_pci_fixup_pciata(struct pci_dev* dev)
 			printk(KERN_ERR "Rewrite of PROGIF failed !\n");
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pmac_pci_fixup_pciata);
+
 
 /*
  * Disable second function on K2-SATA, it's broken
@@ -1104,3 +1124,4 @@ void __pmac pmac_pci_fixup_k2_sata(struct pci_dev* dev)
 		}
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, 0x0240, pmac_pci_fixup_k2_sata);
diff --git a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c
index b05cee1f7..79fc29514 100644
--- a/arch/ppc/platforms/pmac_setup.c
+++ b/arch/ppc/platforms/pmac_setup.c
@@ -318,9 +318,6 @@ pmac_setup_arch(void)
 #ifdef CONFIG_NVRAM
 	pmac_nvram_init();
 #endif
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start)
 		ROOT_DEV = Root_RAM0;
diff --git a/arch/ppc/platforms/pmac_smp.c b/arch/ppc/platforms/pmac_smp.c
index 704742257..1a300ff40 100644
--- a/arch/ppc/platforms/pmac_smp.c
+++ b/arch/ppc/platforms/pmac_smp.c
@@ -32,13 +32,13 @@
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
+#include <linux/hardirq.h>
 
 #include <asm/ptrace.h>
 #include <asm/atomic.h>
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/hardirq.h>
 #include <asm/sections.h>
 #include <asm/io.h>
 #include <asm/prom.h>
diff --git a/arch/ppc/platforms/pmac_time.c b/arch/ppc/platforms/pmac_time.c
index cd8e3e7c4..09636546f 100644
--- a/arch/ppc/platforms/pmac_time.c
+++ b/arch/ppc/platforms/pmac_time.c
@@ -19,6 +19,7 @@
 #include <linux/adb.h>
 #include <linux/cuda.h>
 #include <linux/pmu.h>
+#include <linux/hardirq.h>
 
 #include <asm/sections.h>
 #include <asm/prom.h>
@@ -26,7 +27,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
-#include <asm/hardirq.h>
 #include <asm/time.h>
 #include <asm/nvram.h>
 
diff --git a/arch/ppc/platforms/powerpmc250.h b/arch/ppc/platforms/powerpmc250.h
index b834e1786..41a6dc881 100644
--- a/arch/ppc/platforms/powerpmc250.h
+++ b/arch/ppc/platforms/powerpmc250.h
@@ -7,7 +7,7 @@
  *
  * Borrowed heavily from prpmc750.h by Matt Porter <mporter@mvista.com>
  *
- * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
+ * 2001-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.
@@ -16,8 +16,6 @@
 #ifndef __ASMPPC_POWERPMC250_H
 #define __ASMPPC_POWERPMC250_H
 
-#include <linux/serial_reg.h>
-
 #define POWERPMC250_PCI_CONFIG_ADDR	0x80000cf8
 #define POWERPMC250_PCI_CONFIG_DATA	0x80000cfc
 
@@ -37,4 +35,18 @@
 #define POWERPMC250_SERIAL		0xff000000
 #define POWERPMC250_SERIAL_IRQ		20
 
+/* UART Defines. */
+#define RS_TABLE_SIZE  1
+
+#define BASE_BAUD  (POWERPMC250_BASE_BAUD / 16)
+
+#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF
+
+#define SERIAL_PORT_DFNS \
+	{ 0, BASE_BAUD, POWERPMC250_SERIAL, POWERPMC250_SERIAL_IRQ,	\
+		STD_COM_FLAGS, 				/* ttyS0 */	\
+		iomem_base: (u8 *)POWERPMC250_SERIAL,			\
+		iomem_reg_shift: 0,					\
+		io_type: SERIAL_IO_MEM }
+
 #endif /* __ASMPPC_POWERPMC250_H */
diff --git a/arch/ppc/platforms/pplus.c b/arch/ppc/platforms/pplus.c
index 673641ff4..7922346f1 100644
--- a/arch/ppc/platforms/pplus.c
+++ b/arch/ppc/platforms/pplus.c
@@ -583,8 +583,6 @@ static void __init pplus_setup_arch(void)
 	vgacon_remap_base = (unsigned long)ioremap(PPLUS_ISA_MEM_BASE,
 						   0x08000000);
 	conswitchp = &vga_con;
-#elif defined(CONFIG_DUMMY_CONSOLE)
-	conswitchp = &dummy_con;
 #endif
 #ifdef CONFIG_PPCBUG_NVRAM
 	/* Read in NVRAM data */
diff --git a/arch/ppc/platforms/pq2ads.h b/arch/ppc/platforms/pq2ads.h
index 1bee6ca56..0c17a0cda 100644
--- a/arch/ppc/platforms/pq2ads.h
+++ b/arch/ppc/platforms/pq2ads.h
@@ -23,6 +23,10 @@
 
 #define BOOTROM_RESTART_ADDR	((uint)0xff000104)
 
+/* For our show_cpuinfo hooks. */
+#define CPUINFO_VENDOR		"Motorola"
+#define CPUINFO_MACHINE		"PQ2 ADS PowerPC"
+
 /* The ADS8260 has 16, 32-bit wide control/status registers, accessed
  * only on word boundaries.
  * Not all are used (yet), or are interesting to us (yet).
diff --git a/arch/ppc/platforms/prep_pci.c b/arch/ppc/platforms/prep_pci.c
index 58775fc7f..a528562cc 100644
--- a/arch/ppc/platforms/prep_pci.c
+++ b/arch/ppc/platforms/prep_pci.c
@@ -836,52 +836,59 @@ struct mot_info {
 void __init
 ibm_prep_init(void)
 {
-#ifdef CONFIG_PREP_RESIDUAL
-	u32 addr, real_addr, len;
-	PPC_DEVICE *mpic;
-	PnP_TAG_PACKET *pkt;
-
-	/* Use the PReP residual data to determine if an OpenPIC is
-	 * present.  If so, get the large vendor packet which will
-	 * tell us the base address and length in memory.
-	 * If we are successful, ioremap the memory area and set
-	 * OpenPIC_Addr (this indicates that the OpenPIC was found).
-	 */
-	mpic = residual_find_device(-1, NULL, SystemPeripheral,
-			    ProgrammableInterruptController, MPIC, 0);
-	if (!mpic)
-		return;
+	if (have_residual_data) {
+		u32 addr, real_addr, len, offset;
+		PPC_DEVICE *mpic;
+		PnP_TAG_PACKET *pkt;
+
+		/* Use the PReP residual data to determine if an OpenPIC is
+		 * present.  If so, get the large vendor packet which will
+		 * tell us the base address and length in memory.
+		 * If we are successful, ioremap the memory area and set
+		 * OpenPIC_Addr (this indicates that the OpenPIC was found).
+		 */
+		mpic = residual_find_device(-1, NULL, SystemPeripheral,
+				    ProgrammableInterruptController, MPIC, 0);
+		if (!mpic)
+			return;
 
-	pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
-			mpic->AllocatedOffset, 9, 0);
+		pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
+				mpic->AllocatedOffset, 9, 0);
 
-	if (!pkt)
-		return;
+		if (!pkt)
+			return;
 
 #define p pkt->L4_Pack.L4_Data.L4_PPCPack
-	if (!((p.PPCData[0] == 2) && (p.PPCData[1] == 32)))
-		return; /* not a 32-bit memory address */
+	 	if (p.PPCData[1] == 32) {
+			switch (p.PPCData[0]) {
+				case 1:  offset = PREP_ISA_IO_BASE;  break;
+				case 2:  offset = PREP_ISA_MEM_BASE; break;
+				default: return; /* Not I/O or memory?? */
+			}
+		}
+		else
+			return; /* Not a 32-bit address */
 
-	real_addr = ld_le32((unsigned int *) (p.PPCData + 4));
-	if (real_addr == 0xffffffff)
-		return;
+		real_addr = ld_le32((unsigned int *) (p.PPCData + 4));
+		if (real_addr == 0xffffffff)
+			return;
 
-	/* Adjust address to be as seen by CPU */
-	addr = real_addr + PREP_ISA_MEM_BASE;
+		/* Adjust address to be as seen by CPU */
+		addr = real_addr + offset;
 
-	len = ld_le32((unsigned int *) (p.PPCData + 12));
-	if (!len)
-		return;
+		len = ld_le32((unsigned int *) (p.PPCData + 12));
+		if (!len)
+			return;
 #undef p
-	OpenPIC_Addr = ioremap(addr, len);
-	ppc_md.get_irq = openpic_get_irq;
+		OpenPIC_Addr = ioremap(addr, len);
+		ppc_md.get_irq = openpic_get_irq;
 
-	OpenPIC_InitSenses = prep_openpic_initsenses;
-	OpenPIC_NumInitSenses = sizeof(prep_openpic_initsenses);
+		OpenPIC_InitSenses = prep_openpic_initsenses;
+		OpenPIC_NumInitSenses = sizeof(prep_openpic_initsenses);
 
-	printk(KERN_INFO "MPIC at 0x%08x (0x%08x), length 0x%08x "
-	       "mapped to 0x%p\n", addr, real_addr, len, OpenPIC_Addr);
-#endif
+		printk(KERN_INFO "MPIC at 0x%08x (0x%08x), length 0x%08x "
+		       "mapped to 0x%p\n", addr, real_addr, len, OpenPIC_Addr);
+	}
 }
 
 static void __init
@@ -900,6 +907,17 @@ ibm43p_pci_map_non0(struct pci_dev *dev)
 	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
 }
 
+void __init
+prep_residual_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
+{
+	if (have_residual_data) {
+		Motherboard_map_name = res->VitalProductData.PrintableModel;
+		Motherboard_map = NULL;
+		Motherboard_routes = NULL;
+		residual_irq_mask(irq_edge_mask_lo, irq_edge_mask_hi);
+	}
+}
+
 void __init
 prep_sandalfoot_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
 {
@@ -1011,21 +1029,31 @@ prep_route_pci_interrupts(void)
 		}
 	} else if ( _prep_type == _PREP_IBM ) {
 		unsigned char irq_edge_mask_lo, irq_edge_mask_hi;
+		unsigned short irq_edge_mask;
+		int i;
 
 		setup_ibm_pci(&irq_edge_mask_lo, &irq_edge_mask_hi);
 
 		outb(inb(0x04d0)|irq_edge_mask_lo, 0x4d0); /* primary 8259 */
 		outb(inb(0x04d1)|irq_edge_mask_hi, 0x4d1); /* cascaded 8259 */
+
+		irq_edge_mask = (irq_edge_mask_hi << 8) | irq_edge_mask_lo;
+		for (i = 0; i < 16; ++i, irq_edge_mask >>= 1)
+			if (irq_edge_mask & 1)
+				irq_desc[i].status |= IRQ_LEVEL;
 	} else {
 		printk("No known machine pci routing!\n");
 		return;
 	}
 
 	/* Set up mapping from slots */
-	for (i = 1;  i <= 4;  i++)
-		ibc_pirq[i-1] = Motherboard_routes[i];
-	/* Enable PCI interrupts */
-	*ibc_pcicon |= 0x20;
+	if (Motherboard_routes) {
+		for (i = 1;  i <= 4;  i++)
+			ibc_pirq[i-1] = Motherboard_routes[i];
+
+		/* Enable PCI interrupts */
+		*ibc_pcicon |= 0x20;
+	}
 }
 
 void __init
@@ -1171,38 +1199,52 @@ void __init
 prep_pcibios_fixup(void)
 {
         struct pci_dev *dev = NULL;
+	int irq;
+	int have_openpic = (OpenPIC_Addr != NULL);
 
 	prep_route_pci_interrupts();
 
 	printk("Setting PCI interrupts for a \"%s\"\n", Motherboard_map_name);
-	if (OpenPIC_Addr) {
-		/* PCI interrupts are controlled by the OpenPIC */
-		while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-			if (dev->bus->number == 0) {
-                       		dev->irq = openpic_to_irq(Motherboard_map[PCI_SLOT(dev->devfn)]);
-				pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-			} else {
-				if (Motherboard_non0 != NULL)
-					Motherboard_non0(dev);
-			}
-		}
-
-		/* Setup the Winbond or Via PIB */
-		prep_pib_init();
-
-		return;
-	}
 
-	dev = NULL;
+	/* Iterate through all the PCI devices, setting the IRQ */
 	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
 		/*
-		 * Use our old hard-coded kludge to figure out what
-		 * irq this device uses.  This is necessary on things
-		 * without residual data. -- Cort
+		 * If we have residual data, then this is easy: query the
+		 * residual data for the IRQ line allocated to the device.
+		 * This works the same whether we have an OpenPic or not.
+		 */
+		if (have_residual_data) {
+			irq = residual_pcidev_irq(dev);
+			dev->irq = have_openpic ? openpic_to_irq(irq) : irq;
+		}
+		/*
+		 * If we don't have residual data, then we need to use
+		 * tables to determine the IRQ.  The table organisation
+		 * is different depending on whether there is an OpenPIC
+		 * or not.  The tables are only used for bus 0, so check
+		 * this first.
 		 */
-		unsigned char d = PCI_SLOT(dev->devfn);
-		dev->irq = Motherboard_routes[Motherboard_map[d]];
+		else if (dev->bus->number == 0) {
+			irq = Motherboard_map[PCI_SLOT(dev->devfn)];
+			dev->irq = have_openpic ? openpic_to_irq(irq)
+						: Motherboard_routes[irq];
+		}
+		/*
+		 * Finally, if we don't have residual data and the bus is
+		 * non-zero, use the callback (if provided)
+		 */
+		else {
+			if (Motherboard_non0 != NULL)
+				Motherboard_non0(dev);
+
+			continue;
+		}
+
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
 	}
+
+	/* Setup the Winbond or Via PIB */
+	prep_pib_init();
 }
 
 static void __init
@@ -1262,14 +1304,15 @@ prep_find_bridges(void)
 			   PREP_ISA_IO_BASE + 0xcfc);
 
 	printk("PReP architecture\n");
-#ifdef CONFIG_PREP_RESIDUAL
-	{
+
+	if (have_residual_data) {
 		PPC_DEVICE *hostbridge;
 
 		hostbridge = residual_find_device(PROCESSORDEVICE, NULL,
 			BridgeController, PCIBridge, -1, 0);
 		if (hostbridge &&
-			hostbridge->DeviceId.Interface == PCIBridgeIndirect) {
+			((hostbridge->DeviceId.Interface == PCIBridgeIndirect) ||
+			 (hostbridge->DeviceId.Interface == PCIBridgeRS6K))) {
 			PnP_TAG_PACKET * pkt;
 			pkt = PnP_find_large_vendor_packet(
 				res->DevicePnPHeap+hostbridge->AllocatedOffset,
@@ -1284,7 +1327,6 @@ prep_find_bridges(void)
 				setup_indirect_pci(hose, 0x80000cf8, 0x80000cfc);
 		}
 	}
-#endif /* CONFIG_PREP_RESIDUAL */
 
 	ppc_md.pcibios_fixup = prep_pcibios_fixup;
 	ppc_md.pcibios_after_init = prep_pcibios_after_init;
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
index 99acd5170..8051df176 100644
--- a/arch/ppc/platforms/prep_setup.c
+++ b/arch/ppc/platforms/prep_setup.c
@@ -79,6 +79,7 @@ extern void prep_find_bridges(void);
 
 int _prep_type;
 
+extern void prep_residual_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
 extern void prep_sandalfoot_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
 extern void prep_thinkpad_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
 extern void prep_carolina_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
@@ -193,9 +194,8 @@ prep_ibm_cpuinfo(struct seq_file *m)
 		seq_printf(m, "bad");
 	seq_printf(m, "\n");
 
-#ifdef CONFIG_PREP_RESIDUAL
 	/* print info about SIMMs */
-	if (res->ResidualLength != 0) {
+	if (have_residual_data) {
 		int i;
 		seq_printf(m, "simms\t\t: ");
 		for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) {
@@ -207,7 +207,13 @@ prep_ibm_cpuinfo(struct seq_file *m)
 		}
 		seq_printf(m, "\n");
 	}
-#endif
+}
+
+static int __prep
+prep_gen_cpuinfo(struct seq_file *m)
+{
+	prep_ibm_cpuinfo(m);
+	return 0;
 }
 
 static int __prep
@@ -431,9 +437,8 @@ prep_mot_cpuinfo(struct seq_file *m)
 	}
 
 no_l2:
-#ifdef CONFIG_PREP_RESIDUAL
 	/* print info about SIMMs */
-	if (res->ResidualLength != 0) {
+	if (have_residual_data) {
 		int i;
 		seq_printf(m, "simms\t\t: ");
 		for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) {
@@ -445,17 +450,10 @@ no_l2:
 		}
 		seq_printf(m, "\n");
 	}
-#endif
 
 	return 0;
 }
 
-static void __prep
-prep_tiger1_progress(char *msg, unsigned short code)
-{
-	outw(code, PREP_IBM_DISP);
-}
-
 static void __prep
 prep_restart(char *cmd)
 {
@@ -561,14 +559,12 @@ prep_show_percpuinfo(struct seq_file *m, int i)
 {
 	/* PREP's without residual data will give incorrect values here */
 	seq_printf(m, "clock\t\t: ");
-#ifdef CONFIG_PREP_RESIDUAL
-	if (res->ResidualLength)
+	if (have_residual_data)
 		seq_printf(m, "%ldMHz\n",
 			   (res->VitalProductData.ProcessorHz > 1024) ?
 			   res->VitalProductData.ProcessorHz / 1000000 :
 			   res->VitalProductData.ProcessorHz);
 	else
-#endif /* CONFIG_PREP_RESIDUAL */
 		seq_printf(m, "???\n");
 
 	return 0;
@@ -598,9 +594,10 @@ static void __init prep_init_sound(void)
 	 * Get the needed resource informations from residual data.
 	 *
 	 */
-#ifdef CONFIG_PREP_RESIDUAL
-	audiodevice = residual_find_device(~0, NULL, MultimediaController,
-			AudioController, -1, 0);
+	if (have_residual_data)
+		audiodevice = residual_find_device(~0, NULL,
+				MultimediaController, AudioController, -1, 0);
+
 	if (audiodevice != NULL) {
 		PnP_TAG_PACKET *pkt;
 
@@ -613,7 +610,6 @@ static void __init prep_init_sound(void)
 		if (pkt != NULL)
 			ppc_cs4232_dma2 = masktoint(pkt->S5_Pack.DMAMask);
 	}
-#endif
 
 	/*
 	 * These are the PReP specs' defaults for the cs4231.  We use these
@@ -649,13 +645,14 @@ static void __init prep_init_sound(void)
 static void __init
 prep_init_vesa(void)
 {
-#if defined(CONFIG_PREP_RESIDUAL) && \
-	(defined(CONFIG_FB_VGA16) || defined(CONFIG_FB_VGA_16_MODULE) || \
+#if     (defined(CONFIG_FB_VGA16) || defined(CONFIG_FB_VGA_16_MODULE) || \
 	 defined(CONFIG_FB_VESA))
-	PPC_DEVICE *vgadev;
+	PPC_DEVICE *vgadev = NULL;
+
+	if (have_residual_data)
+		vgadev = residual_find_device(~0, NULL, DisplayController,
+							SVGAController, -1, 0);
 
-	vgadev = residual_find_device(~0, NULL, DisplayController, SVGAController,
-									-1, 0);
 	if (vgadev != NULL) {
 		PnP_TAG_PACKET *pkt;
 
@@ -680,7 +677,112 @@ prep_init_vesa(void)
 			}
 		}
 	}
-#endif /* CONFIG_PREP_RESIDUAL */
+#endif
+}
+
+/*
+ * Set DBAT 2 to access 0x80000000 so early progress messages will work
+ */
+static __inline__ void
+prep_set_bat(void)
+{
+	/* wait for all outstanding memory access to complete */
+	mb();
+
+	/* setup DBATs */
+	mtspr(DBAT2U, 0x80001ffe);
+	mtspr(DBAT2L, 0x8000002a);
+
+	/* wait for updates */
+	mb();
+}
+
+/*
+ * IBM 3-digit status LED
+ */
+static unsigned int ibm_statusled_base __prepdata;
+
+static void __prep
+ibm_statusled_progress(char *s, unsigned short hex);
+
+static int __prep
+ibm_statusled_panic(struct notifier_block *dummy1, unsigned long dummy2,
+		    void * dummy3)
+{
+	ibm_statusled_progress(NULL, 0x505); /* SOS */
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block ibm_statusled_block __prepdata = {
+	ibm_statusled_panic,
+	NULL,
+	INT_MAX /* try to do it first */
+};
+
+static void __prep
+ibm_statusled_progress(char *s, unsigned short hex)
+{
+	static int notifier_installed;
+	/*
+	 * Progress uses 4 digits and we have only 3.  So, we map 0xffff to
+	 * 0xfff for display switch off.  Out of range values are mapped to
+	 * 0xeff, as I'm told 0xf00 and above are reserved for hardware codes.
+	 * Install the panic notifier when the display is first switched off.
+	 */
+	if (hex == 0xffff) {
+		hex = 0xfff;
+		if (!notifier_installed) {
+			++notifier_installed;
+			notifier_chain_register(&panic_notifier_list,
+						&ibm_statusled_block);
+		}
+	}
+	else
+		if (hex > 0xfff)
+			hex = 0xeff;
+
+	mb();
+	outw(hex, ibm_statusled_base);
+}
+
+static void __init
+ibm_statusled_init(void)
+{
+	/*
+	 * The IBM 3-digit LED display is specified in the residual data
+	 * as an operator panel device, type "System Status LED".  Find
+	 * that device and determine its address.  We validate all the
+	 * other parameters on the off-chance another, similar device
+	 * exists.
+	 */
+	if (have_residual_data) {
+		PPC_DEVICE *led;
+		PnP_TAG_PACKET *pkt;
+
+		led = residual_find_device(~0, NULL, SystemPeripheral,
+					   OperatorPanel, SystemStatusLED, 0);
+		if (!led)
+			return;
+
+		pkt = PnP_find_packet((unsigned char *)
+		       &res->DevicePnPHeap[led->AllocatedOffset], S8_Packet, 0);
+		if (!pkt)
+			return;
+
+		if (pkt->S8_Pack.IOInfo != ISAAddr16bit)
+			return;
+		if (*(unsigned short *)pkt->S8_Pack.RangeMin !=
+		    *(unsigned short *)pkt->S8_Pack.RangeMax)
+			return;
+		if (pkt->S8_Pack.IOAlign != 2)
+			return;
+		if (pkt->S8_Pack.IONum != 2)
+			return;
+
+		ibm_statusled_base = ld_le16((unsigned short *)
+					     (pkt->S8_Pack.RangeMin));
+		ppc_md.progress = ibm_statusled_progress;
+	}
 }
 
 static void __init
@@ -706,7 +808,7 @@ prep_setup_arch(void)
 	{
 	case _PREP_IBM:
 		reg = inb(PREP_IBM_PLANAR);
-		printk(KERN_INFO "IBM planar ID: %08x", reg);
+		printk(KERN_INFO "IBM planar ID: %02x", reg);
 		switch (reg) {
 			case PREP_IBM_SANDALFOOT:
 				prep_gen_enable_l2();
@@ -721,7 +823,16 @@ prep_setup_arch(void)
 				ppc_md.show_cpuinfo = prep_thinkpad_cpuinfo;
 				break;
 			default:
-				printk(" -- unknown! Assuming Carolina");
+				if (have_residual_data) {
+					prep_gen_enable_l2();
+					setup_ibm_pci = prep_residual_setup_pci;
+					ppc_md.power_off = prep_halt;
+					ppc_md.show_cpuinfo = prep_gen_cpuinfo;
+					break;
+				}
+				else
+					printk(" - unknown! Assuming Carolina");
+					/* fall through */
 			case PREP_IBM_CAROLINA_IDE_0:
 			case PREP_IBM_CAROLINA_IDE_1:
 			case PREP_IBM_CAROLINA_IDE_2:
@@ -745,7 +856,6 @@ prep_setup_arch(void)
 				setup_ibm_pci = prep_tiger1_setup_pci;
 				ppc_md.power_off = prep_sig750_poweroff;
 				ppc_md.show_cpuinfo = prep_tiger1_cpuinfo;
-				ppc_md.progress = prep_tiger1_progress;
 				break;
 		}
 		printk("\n");
@@ -808,8 +918,6 @@ prep_setup_arch(void)
 	/* vgacon.c needs to know where we mapped IO memory in io_block_mapping() */
 	vgacon_remap_base = 0xf0000000;
 	conswitchp = &vga_con;
-#elif defined(CONFIG_DUMMY_CONSOLE)
-	conswitchp = &dummy_con;
 #endif
 }
 
@@ -821,18 +929,19 @@ prep_setup_arch(void)
 static void __init
 prep_calibrate_decr(void)
 {
-#ifdef CONFIG_PREP_RESIDUAL
-	unsigned long freq, divisor = 4;
-
-	if ( res->VitalProductData.ProcessorBusHz ) {
-		freq = res->VitalProductData.ProcessorBusHz;
-		printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
-				(freq/divisor)/1000000,
-				(freq/divisor)%1000000);
-		tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
-		tb_ticks_per_jiffy = freq / HZ / divisor;
-	} else
-#endif
+	if (have_residual_data) {
+		unsigned long freq, divisor = 4;
+
+		if ( res->VitalProductData.ProcessorBusHz ) {
+			freq = res->VitalProductData.ProcessorBusHz;
+			printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+					(freq/divisor)/1000000,
+					(freq/divisor)%1000000);
+			tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
+			tb_ticks_per_jiffy = freq / HZ / divisor;
+		}
+	}
+	else
 		todc_calibrate_decr();
 }
 
@@ -863,6 +972,12 @@ prep_init_IRQ(void)
 	}
 	for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ )
 		irq_desc[i].handler = &i8259_pic;
+
+	if (have_residual_data) {
+		i8259_init(residual_isapic_addr());
+		return;
+	}
+
 	/* If we have a Raven PCI bridge or a Hawk PCI bridge / Memory
 	 * controller, we poll (as they have a different int-ack address). */
 	early_read_config_dword(NULL, 0, 0, PCI_VENDOR_ID, &pci_viddid);
@@ -1000,18 +1115,27 @@ prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
 	DMA_MODE_WRITE = 0x48;
 
 	/* figure out what kind of prep workstation we are */
-#ifdef CONFIG_PREP_RESIDUAL
-	if ( res->ResidualLength != 0 ) {
+	if (have_residual_data) {
 		if ( !strncmp(res->VitalProductData.PrintableModel,"IBM",3) )
 			_prep_type = _PREP_IBM;
 		else
 			_prep_type = _PREP_Motorola;
-	} else /* assume motorola if no residual (netboot?) */
-#endif
-	{
+	}
+	else {
+		/* assume motorola if no residual (netboot?) */
 		_prep_type = _PREP_Motorola;
 	}
 
+#ifdef CONFIG_PREP_PRESIDUAL
+	/* Switch off all residual data processing if the user requests it */
+	if (strstr(cmd_line, "noresidual") != NULL)
+			res = NULL;
+#endif
+
+	/* Initialise progress early to get maximum benefit */
+	prep_set_bat();
+	ibm_statusled_init();
+
 	ppc_md.setup_arch     = prep_setup_arch;
 	ppc_md.show_percpuinfo = prep_show_percpuinfo;
 	ppc_md.show_cpuinfo   = NULL; /* set in prep_setup_arch() */
diff --git a/arch/ppc/platforms/prpmc750.c b/arch/ppc/platforms/prpmc750.c
index e0ab8e301..a75553c9a 100644
--- a/arch/ppc/platforms/prpmc750.c
+++ b/arch/ppc/platforms/prpmc750.c
@@ -193,10 +193,6 @@ static void __init prpmc750_setup_arch(void)
 		ROOT_DEV = Root_SDA2;
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
 	OpenPIC_InitSenses = prpmc750_openpic_initsenses;
 	OpenPIC_NumInitSenses = sizeof(prpmc750_openpic_initsenses);
 
diff --git a/arch/ppc/platforms/prpmc750.h b/arch/ppc/platforms/prpmc750.h
index 23ed94140..015b4f52c 100644
--- a/arch/ppc/platforms/prpmc750.h
+++ b/arch/ppc/platforms/prpmc750.h
@@ -5,20 +5,16 @@
  *
  * Author: Matt Porter <mporter@mvista.com>
  *
- * Copyright 2001 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.
+ * 2001-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.
  */
 
 #ifdef __KERNEL__
 #ifndef __ASM_PRPMC750_H__
 #define __ASM_PRPMC750_H__
 
-#include <linux/serial_reg.h>
-
 /*
  * Due to limiations imposed by legacy hardware (primaryily IDE controllers),
  * the PrPMC750 carrier board operates using a PReP address map.
@@ -81,5 +77,19 @@
 #define PRPMC750_TBEN_REG		0xfef880c0
 #define PRPMC750_TBEN_MASK		0x01
 
+/* UART Defines. */
+#define RS_TABLE_SIZE  4
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD  (PRPMC750_BASE_BAUD / 16)
+
+#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF
+
+#define SERIAL_PORT_DFNS \
+        { 0, BASE_BAUD, PRPMC750_SERIAL_0, 1, STD_COM_FLAGS, \
+		iomem_base: (unsigned char *)PRPMC750_SERIAL_0, \
+		iomem_reg_shift: 4, \
+		io_type: SERIAL_IO_MEM } /* ttyS0 */
+
 #endif				/* __ASM_PRPMC750_H__ */
 #endif				/* __KERNEL__ */
diff --git a/arch/ppc/platforms/prpmc800.c b/arch/ppc/platforms/prpmc800.c
index 0ffcfdfb1..0e99f8bc3 100644
--- a/arch/ppc/platforms/prpmc800.c
+++ b/arch/ppc/platforms/prpmc800.c
@@ -309,10 +309,6 @@ static void __init prpmc800_setup_arch(void)
 		ROOT_DEV = Root_SDA2;
 #endif
 
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
 	printk(KERN_INFO "Port by MontaVista Software, Inc. "
 			 "(source@mvista.com)\n");
 }
diff --git a/arch/ppc/platforms/prpmc800.h b/arch/ppc/platforms/prpmc800.h
index 4af2f2c9a..e53ec9b42 100644
--- a/arch/ppc/platforms/prpmc800.h
+++ b/arch/ppc/platforms/prpmc800.h
@@ -5,12 +5,10 @@
  *
  * Author: Dale Farnsworth <dale.farnsworth@mvista.com>
  *
- * Copyright 2001 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.
+ * 2001-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.
  */
  /*
   * From Processor to PCI:
@@ -63,4 +61,22 @@
 #define PRPMC800_INT_IRQ			16
 #define PRPMC800_INT_PRI			15
 
+/* UART Defines. */
+#define RS_TABLE_SIZE  4
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD (PRPMC800_BASE_BAUD / 16)
+
+#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF
+
+/* UARTS are at IRQ 16 */
+#define STD_SERIAL_PORT_DFNS \
+        { 0, BASE_BAUD, PRPMC800_SERIAL_1, 16, STD_COM_FLAGS, /* ttyS0 */\
+		iomem_base: (unsigned char *)PRPMC800_SERIAL_1,		\
+		iomem_reg_shift: 0,					\
+		io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DFNS
+
 #endif				/* __ASMPPC_PRPMC800_H */
diff --git a/arch/ppc/platforms/residual.c b/arch/ppc/platforms/residual.c
index b094e2715..0f84ca603 100644
--- a/arch/ppc/platforms/residual.c
+++ b/arch/ppc/platforms/residual.c
@@ -504,7 +504,7 @@ void __init print_residual_device_info(void)
 #define did dev->DeviceId
 
 	/* make sure we have residual data first */
-	if ( res->ResidualLength == 0 )
+	if (!have_residual_data)
 		return;
 
 	printk("Residual: %ld devices\n", res->ActualNumDevices);
@@ -639,7 +639,7 @@ void print_residual_device_info(void)
 #define did dev->DeviceId
 
 	/* make sure we have residual data first */
-	if ( res->ResidualLength == 0 )
+	if (!have_residual_data)
 		return;
 	printk("Residual: %ld devices\n", res->ActualNumDevices);
 	for ( i = 0;
@@ -790,7 +790,7 @@ PPC_DEVICE __init *residual_find_device(unsigned long BusMask,
 			 int n)
 {
 	int i;
-	if ( !res->ResidualLength ) return NULL;
+	if (!have_residual_data) return NULL;
 	for (i=0; i<res->ActualNumDevices; i++) {
 #define Dev res->Devices[i].DeviceId
 		if ( (Dev.BusId&BusMask)                                  &&
@@ -813,7 +813,7 @@ PPC_DEVICE __init *residual_find_device_id(unsigned long BusMask,
 			 int n)
 {
 	int i;
-	if ( !res->ResidualLength ) return NULL;
+	if (!have_residual_data) return NULL;
 	for (i=0; i<res->ActualNumDevices; i++) {
 #define Dev res->Devices[i].DeviceId
 		if ( (Dev.BusId&BusMask)                                  &&
@@ -827,6 +827,129 @@ PPC_DEVICE __init *residual_find_device_id(unsigned long BusMask,
 	return NULL;
 }
 
+static int __init
+residual_scan_pcibridge(PnP_TAG_PACKET * pkt, struct pci_dev *dev)
+{
+	int irq = -1;
+
+#define data pkt->L4_Pack.L4_Data.L4_PPCPack.PPCData
+	if (dev->bus->number == data[16]) {
+		int i, size;
+
+		size = 3 + ld_le16((u_short *) (&pkt->L4_Pack.Count0));
+		for (i = 20; i < size - 4; i += 12) {
+			unsigned char pin;
+			int line_irq;
+
+			if (dev->devfn != data[i + 1])
+				continue;
+
+			pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+			if (pin) {
+				line_irq = ld_le16((unsigned short *)
+						(&data[i + 4 + 2 * (pin - 1)]));
+				irq = (line_irq == 0xffff) ? 0
+							   : line_irq & 0x7fff;
+			} else
+				irq = 0;
+
+			break;
+		}
+	}
+#undef data
+
+	return irq;
+}
+
+int __init
+residual_pcidev_irq(struct pci_dev *dev)
+{
+	int i = 0;
+	int irq = -1;
+	PPC_DEVICE *bridge;
+
+	while ((bridge = residual_find_device
+	       (-1, NULL, BridgeController, PCIBridge, -1, i++))) {
+
+		PnP_TAG_PACKET *pkt;
+		if (bridge->AllocatedOffset) {
+			pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
+					   bridge->AllocatedOffset, 3, 0);
+			if (!pkt)
+				continue;
+
+			irq = residual_scan_pcibridge(pkt, dev);
+			if (irq != -1)
+				break;
+		}
+	}
+
+	return (irq < 0) ? 0 : irq;
+}
+
+void __init residual_irq_mask(char *irq_edge_mask_lo, char *irq_edge_mask_hi)
+{
+	PPC_DEVICE *dev;
+	int i = 0;
+	unsigned short irq_mask = 0x000; /* default to edge */
+
+	while ((dev = residual_find_device(-1, NULL, -1, -1, -1, i++))) {
+		PnP_TAG_PACKET *pkt;
+		unsigned short mask;
+		int size;
+		int offset = dev->AllocatedOffset;
+
+		if (!offset)
+			continue;
+
+		pkt = PnP_find_packet(res->DevicePnPHeap + offset,
+					      IRQFormat, 0);
+		if (!pkt)
+			continue;
+
+		size = tag_small_count(pkt->S1_Pack.Tag) + 1;
+		mask = ld_le16((unsigned short *)pkt->S4_Pack.IRQMask);
+		if (size > 3 && (pkt->S4_Pack.IRQInfo & 0x0c))
+			irq_mask |= mask;
+	}
+
+	*irq_edge_mask_lo = irq_mask & 0xff;
+	*irq_edge_mask_hi = irq_mask >> 8;
+}
+
+unsigned int __init residual_isapic_addr(void)
+{
+	PPC_DEVICE *isapic;
+	PnP_TAG_PACKET *pkt;
+	unsigned int addr;
+
+	isapic = residual_find_device(~0, NULL, SystemPeripheral,
+				      ProgrammableInterruptController,
+				      ISA_PIC, 0);
+	if (!isapic)
+		goto unknown;
+
+	pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap +
+						isapic->AllocatedOffset, 9, 0);
+	if (!pkt)
+		goto unknown;
+
+#define p pkt->L4_Pack.L4_Data.L4_PPCPack
+	/* Must be 32-bit system address */
+	if (!((p.PPCData[0] == 3) && (p.PPCData[1] == 32)))
+		goto unknown;
+
+	/* It doesn't seem to work where length != 1 (what can I say? :-/ ) */
+	if (ld_le32((unsigned int *)(p.PPCData + 12)) != 1)
+		goto unknown;
+
+	addr = ld_le32((unsigned int *) (p.PPCData + 4));
+#undef p
+	return addr;
+unknown:
+	return 0;
+}
+
 PnP_TAG_PACKET *PnP_find_packet(unsigned char *p,
 				unsigned packet_tag,
 				int n)
@@ -901,7 +1024,7 @@ static int proc_prep_residual_read(char * buf, char ** start, off_t off,
 int __init
 proc_prep_residual_init(void)
 {
-	if (res->ResidualLength)
+	if (have_residual_data)
 		create_proc_read_entry("residual", S_IRUGO, NULL,
 					proc_prep_residual_read, NULL);
 	return 0;
diff --git a/arch/ppc/platforms/rpx8260.h b/arch/ppc/platforms/rpx8260.h
index 7d5cd8893..843494a50 100644
--- a/arch/ppc/platforms/rpx8260.h
+++ b/arch/ppc/platforms/rpx8260.h
@@ -70,5 +70,12 @@ extern volatile u_char *rpx6_csr_addr;
 
 #define PHY_INTERRUPT	SIU_INT_IRQ7
 
+/* For our show_cpuinfo hooks. */
+#define CPUINFO_VENDOR		"Embedded Planet"
+#define CPUINFO_MACHINE		"EP8260 PowerPC"
+
+/* Warm reset vector. */
+#define BOOTROM_RESTART_ADDR	((uint)0xfff00104)
+
 #endif /* __ASM_PLATFORMS_RPX8260_H__ */
 #endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/sandpoint.c b/arch/ppc/platforms/sandpoint.c
index fdcbcf240..d9307a261 100644
--- a/arch/ppc/platforms/sandpoint.c
+++ b/arch/ppc/platforms/sandpoint.c
@@ -303,10 +303,6 @@ sandpoint_setup_arch(void)
 	/* Lookup PCI host bridges */
 	sandpoint_find_bridges();
 
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
 	printk(KERN_INFO "Motorola SPS Sandpoint Test Platform\n");
 	printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
 
diff --git a/arch/ppc/platforms/sbc82xx.c b/arch/ppc/platforms/sbc82xx.c
index 28a77dba3..3a404a88c 100644
--- a/arch/ppc/platforms/sbc82xx.c
+++ b/arch/ppc/platforms/sbc82xx.c
@@ -16,10 +16,11 @@
  */
 
 #include <linux/config.h>
-#include <linux/seq_file.h>
 #include <linux/stddef.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/pci.h>
 
 #include <asm/mpc8260.h>
 #include <asm/machdep.h>
@@ -28,39 +29,12 @@
 #include <asm/immap_cpm2.h>
 #include <asm/pci.h>
 
-static void (*callback_setup_arch)(void);
 static void (*callback_init_IRQ)(void);
 
 extern unsigned char __res[sizeof(bd_t)];
 
-extern void m8260_init(unsigned long r3, unsigned long r4,
-	unsigned long r5, unsigned long r6, unsigned long r7);
-
 extern void (*late_time_init)(void);
 
-static int
-sbc82xx_show_cpuinfo(struct seq_file *m)
-{
-	bd_t	*binfo = (bd_t *)__res;
-
-	seq_printf(m, "vendor\t\t: Wind River\n"
-		      "machine\t\t: SBC PowerQUICC II\n"
-		      "\n"
-		      "mem size\t\t: 0x%08lx\n"
-		      "console baud\t\t: %ld\n"
-		      "\n",
-		      binfo->bi_memsize,
-		      binfo->bi_baudrate);
-	return 0;
-}
-
-static void __init
-sbc82xx_setup_arch(void)
-{
-	printk("SBC PowerQUICC II Port\n");
-	callback_setup_arch();
-}
-
 #ifdef CONFIG_GEN_RTC
 TODC_ALLOC();
 
@@ -236,26 +210,36 @@ static int sbc82xx_pci_map_irq(struct pci_dev *dev, unsigned char idsel,
 	return PCI_IRQ_TABLE_LOOKUP;
 }
 
+static void __devinit quirk_sbc8260_cardbus(struct pci_dev *pdev)
+{
+	uint32_t ctrl;
+
+	if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(17, 0))
+		return;
+
+	printk(KERN_INFO "Setting up CardBus controller\n");
+
+	/* Set P2CCLK bit in System Control Register */
+	pci_read_config_dword(pdev, 0x80, &ctrl);
+	ctrl |= (1<<27);
+	pci_write_config_dword(pdev, 0x80, ctrl);
 
+	/* Set MFUNC up for PCI IRQ routing via INTA and INTB, and LEDs. */
+	pci_write_config_dword(pdev, 0x8c, 0x00c01d22);
+
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1420, quirk_sbc8260_cardbus);
 
 void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
-	      unsigned long r6, unsigned long r7)
+m82xx_board_init(void)
 {
-	/* Generic 8260 platform initialization */
-	m8260_init(r3, r4, r5, r6, r7);
-
 	/* u-boot may be using one of the FCC Ethernet devices.
 	   Use the MAC address to the SCC. */
 	__res[offsetof(bd_t, bi_enetaddr[5])] &= ~3;
 
 	/* Anything special for this platform */
-	ppc_md.show_cpuinfo	= sbc82xx_show_cpuinfo;
-
-	callback_setup_arch	= ppc_md.setup_arch;
 	callback_init_IRQ	= ppc_md.init_IRQ;
 
-	ppc_md.setup_arch	= sbc82xx_setup_arch;
 	ppc_md.init_IRQ		= sbc82xx_init_IRQ;
 	ppc_md.pci_map_irq	= sbc82xx_pci_map_irq;
 #ifdef CONFIG_GEN_RTC
diff --git a/arch/ppc/platforms/sbc82xx.h b/arch/ppc/platforms/sbc82xx.h
index adafd49be..e4042d499 100644
--- a/arch/ppc/platforms/sbc82xx.h
+++ b/arch/ppc/platforms/sbc82xx.h
@@ -18,6 +18,10 @@
 #define SBC82xx_MACADDR_NVRAM_FCC2	0x220000d5	/* JP7A */
 #define SBC82xx_MACADDR_NVRAM_FCC3	0x220000db	/* JP7B */
 
+/* For our show_cpuinfo hooks. */
+#define CPUINFO_VENDOR		"Wind River"
+#define CPUINFO_MACHINE		"SBC PowerQUICC II"
+
 #define BOOTROM_RESTART_ADDR      ((uint)0x40000104)
 
 #define SBC82xx_PC_IRQA (NR_SIU_INTS+0)
diff --git a/arch/ppc/platforms/spruce.c b/arch/ppc/platforms/spruce.c
index ad671021e..74be32456 100644
--- a/arch/ppc/platforms/spruce.c
+++ b/arch/ppc/platforms/spruce.c
@@ -228,11 +228,6 @@ spruce_setup_arch(void)
 		ROOT_DEV = Root_SDA1;
 #endif
 
-#ifdef CONFIG_VT
-	conswitchp = &dummy_con;
-#endif
-
-
 	/* Identify the system */
 	printk(KERN_INFO "System Identification: IBM Spruce\n");
 	printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
diff --git a/arch/ppc/platforms/tqm8260.h b/arch/ppc/platforms/tqm8260.h
index 3366cbded..c7a78a646 100644
--- a/arch/ppc/platforms/tqm8260.h
+++ b/arch/ppc/platforms/tqm8260.h
@@ -14,6 +14,10 @@
 #define CPM_MAP_ADDR		((uint)0xFFF00000)
 #define PHY_INTERRUPT		25
 
+/* For our show_cpuinfo hooks. */
+#define CPUINFO_VENDOR		"IN2 Systems"
+#define CPUINFO_MACHINE		"TQM8260 PowerPC"
+
 #define BOOTROM_RESTART_ADDR	((uint)0x40000104)
 
 #endif	/* __TQM8260_PLATFORM */
diff --git a/arch/ppc/platforms/tqm8260_setup.c b/arch/ppc/platforms/tqm8260_setup.c
index 1241ed5d4..a8880bfc0 100644
--- a/arch/ppc/platforms/tqm8260_setup.c
+++ b/arch/ppc/platforms/tqm8260_setup.c
@@ -14,33 +14,12 @@
  * option) any later version.
  */
 
-#include <linux/config.h>
-#include <linux/seq_file.h>
+#include <linux/init.h>
 
 #include <asm/immap_cpm2.h>
 #include <asm/mpc8260.h>
 #include <asm/machdep.h>
 
-static void (*callback_setup_arch)(void);
-
-extern unsigned char __res[sizeof(bd_t)];
-
-extern void m8260_init(unsigned long r3, unsigned long r4,
-	unsigned long r5, unsigned long r6, unsigned long r7);
-
-static int
-tqm8260_show_cpuinfo(struct seq_file *m)
-{
-	bd_t	*binfo = (bd_t *)__res;
-
-	seq_printf(m, "vendor\t\t: IN2 Systems\n"
-		      "machine\t\t: TQM8260 PowerPC\n"
-		      "mem size\t\t: 0x%08x\n"
-		      "\n",
-		      binfo->bi_memsize);
-	return 0;
-}
-
 static int
 tqm8260_set_rtc_time(unsigned long time)
 {
@@ -56,24 +35,10 @@ tqm8260_get_rtc_time(void)
 	return ((cpm2_map_t *)CPM_MAP_ADDR)->im_sit.sit_tmcnt;
 }
 
-static void __init
-tqm8260_setup_arch(void)
-{
-	printk("IN2 Systems TQM8260 port\n");
-	callback_setup_arch();
-}
-
 void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
-	      unsigned long r6, unsigned long r7)
+m82xx_board_init(void)
 {
-	/* Generic 8260 platform initialization */
-	m8260_init(r3, r4, r5, r6, r7);
-
 	/* Anything special for this platform */
-	ppc_md.show_cpuinfo	= tqm8260_show_cpuinfo;
 	ppc_md.set_rtc_time	= tqm8260_set_rtc_time;
 	ppc_md.get_rtc_time	= tqm8260_get_rtc_time;
-
-	callback_setup_arch	= ppc_md.setup_arch;
-	ppc_md.setup_arch	= tqm8260_setup_arch;
+}
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 4de92f498..fe15101b2 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -5,6 +5,8 @@
 CFLAGS_prom_init.o      += -fPIC
 CFLAGS_btext.o          += -fPIC
 
+wdt-mpc8xx-$(CONFIG_8xx_WDT)	+= m8xx_wdt.o
+
 obj-$(CONFIG_PPCBUG_NVRAM)	+= prep_nvram.o
 obj-$(CONFIG_PPC_OCP)		+= ocp.o
 obj-$(CONFIG_IBM_OCP)		+= ibm_ocp.o
@@ -22,7 +24,7 @@ obj-$(CONFIG_KGDB)		+= ppc4xx_kgdb.o
 obj-$(CONFIG_PCI)		+= indirect_pci.o pci_auto.o ppc405_pci.o
 endif
 endif
-obj-$(CONFIG_8xx)		+= m8xx_setup.o ppc8xx_pic.o
+obj-$(CONFIG_8xx)		+= m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y)
 ifeq ($(CONFIG_8xx),y)
 obj-$(CONFIG_PCI)		+= qspan_pci.o i8259.o
 endif
diff --git a/arch/ppc/syslib/cpm2_pic.c b/arch/ppc/syslib/cpm2_pic.c
index 43eac4135..bd8335b84 100644
--- a/arch/ppc/syslib/cpm2_pic.c
+++ b/arch/ppc/syslib/cpm2_pic.c
@@ -1,12 +1,3 @@
-#include <linux/stddef.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <asm/irq.h>
-#include <asm/immap_cpm2.h>
-#include <asm/mpc8260.h>
-#include "cpm2_pic.h"
-
 /* The CPM2 internal interrupt controller.  It is usually
  * the only interrupt controller.
  * There are two 32-bit registers (high/low) for up to 64
@@ -18,6 +9,18 @@
  * We create two tables, indexed by vector number, to indicate
  * which register to use and which bit in the register to use.
  */
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/irq.h>
+
+#include <asm/immap_cpm2.h>
+#include <asm/mpc8260.h>
+
+#include "cpm2_pic.h"
+
 static	u_char	irq_to_siureg[] = {
 	1, 1, 1, 1, 1, 1, 1, 1,
 	1, 1, 1, 1, 1, 1, 1, 1,
@@ -123,9 +126,5 @@ cpm2_get_irq(struct pt_regs *regs)
 
 	if (irq == 0)
 		return(-1);
-#if 0
-        irq += ppc8260_pic.irq_offset;
-#endif
 	return irq;
 }
-
diff --git a/arch/ppc/syslib/cpm2_pic.h b/arch/ppc/syslib/cpm2_pic.h
index a9da44168..d05003b09 100644
--- a/arch/ppc/syslib/cpm2_pic.h
+++ b/arch/ppc/syslib/cpm2_pic.h
@@ -1,13 +1,7 @@
 #ifndef _PPC_KERNEL_CPM2_H
 #define _PPC_KERNEL_CPM2_H
 
-#include <linux/irq.h>
-
 extern struct hw_interrupt_type cpm2_pic;
-
-void cpm2_pic_init(void);
-void cpm2_do_IRQ(struct pt_regs *regs,
-                 int            cpu);
-int cpm2_get_irq(struct pt_regs *regs);
+extern int cpm2_get_irq(struct pt_regs *regs);
 
 #endif /* _PPC_KERNEL_CPM2_H */
diff --git a/arch/ppc/syslib/hawk_common.c b/arch/ppc/syslib/hawk_common.c
index 9c2e1506a..a9911dc3a 100644
--- a/arch/ppc/syslib/hawk_common.c
+++ b/arch/ppc/syslib/hawk_common.c
@@ -285,3 +285,35 @@ hawk_get_mem_size(uint smc_base)
 
 	return total;
 }
+
+int __init
+hawk_mpic_init(unsigned int pci_mem_offset)
+{
+	unsigned short	devid;
+	unsigned int	pci_membase;
+
+	/* Check the first PCI device to see if it is a Raven or Hawk. */
+	early_read_config_word(0, 0, 0, PCI_DEVICE_ID, &devid);
+
+	switch (devid) {
+	case PCI_DEVICE_ID_MOTOROLA_RAVEN:
+	case PCI_DEVICE_ID_MOTOROLA_HAWK:
+		break;
+	default:
+		OpenPIC_Addr = NULL;
+		return 1;
+	}
+
+	/* Read the memory base register. */
+	early_read_config_dword(0, 0, 0, PCI_BASE_ADDRESS_1, &pci_membase);
+
+	if (pci_membase == 0) {
+		OpenPIC_Addr = NULL;
+		return 1;
+	}
+
+	/* Map the MPIC registers to virtual memory. */
+	OpenPIC_Addr = ioremap(pci_membase + pci_mem_offset, 0x22000);
+
+	return 0;
+}
diff --git a/arch/ppc/syslib/ibm44x_common.c b/arch/ppc/syslib/ibm44x_common.c
index a0cefdc7c..76d18d337 100644
--- a/arch/ppc/syslib/ibm44x_common.c
+++ b/arch/ppc/syslib/ibm44x_common.c
@@ -6,6 +6,9 @@
  * Matt Porter <mporter@mvista.com>
  * Copyright 2002-2003 MontaVista Software Inc.
  *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003, 2004 Zultys Technologies
+ *
  * 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
@@ -14,8 +17,14 @@
  */
 #include <linux/config.h>
 #include <linux/types.h>
+#include <linux/serial.h>
+
+#include <asm/param.h>
 #include <asm/ibm44x.h>
 #include <asm/mmu.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/ppc4xx_pic.h>
 
 phys_addr_t fixup_bigphys_addr(phys_addr_t addr, phys_addr_t size)
 {
@@ -35,3 +44,159 @@ phys_addr_t fixup_bigphys_addr(phys_addr_t addr, phys_addr_t size)
 
 	return (page_4gb | addr);
 };
+
+void __init ibm44x_calibrate_decr(unsigned int freq)
+{
+	tb_ticks_per_jiffy = freq / HZ;
+	tb_to_us = mulhwu_scale_factor(freq, 1000000);
+
+	/* Set the time base to zero */
+	mtspr(SPRN_TBWL, 0);
+	mtspr(SPRN_TBWU, 0);
+
+	/* Clear any pending timer interrupts */
+	mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
+
+	/* Enable decrementer interrupt */
+	mtspr(SPRN_TCR, TCR_DIE);
+}
+
+extern void abort(void);
+
+static void ibm44x_restart(char *cmd)
+{
+	local_irq_disable();
+	abort();
+}
+
+static void ibm44x_power_off(void)
+{
+	local_irq_disable();
+	for(;;);
+}
+
+static void ibm44x_halt(void)
+{
+	local_irq_disable();
+	for(;;);
+}
+
+/*
+ * Read the 44x memory controller to get size of system memory.
+ */
+static unsigned long __init ibm44x_find_end_of_memory(void)
+{
+	u32 i, bank_config;
+	u32 mem_size = 0;
+
+	for (i=0; i<4; i++)
+	{
+		switch (i)
+		{
+			case 0:
+				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B0CR);
+				break;
+			case 1:
+				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B1CR);
+				break;
+			case 2:
+				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B2CR);
+				break;
+			case 3:
+				mtdcr(DCRN_SDRAM0_CFGADDR, SDRAM0_B3CR);
+				break;
+		}
+
+		bank_config = mfdcr(DCRN_SDRAM0_CFGDATA);
+
+		if (!(bank_config & SDRAM_CONFIG_BANK_ENABLE))
+			continue;
+		switch (SDRAM_CONFIG_BANK_SIZE(bank_config))
+		{
+			case SDRAM_CONFIG_SIZE_8M:
+				mem_size += PPC44x_MEM_SIZE_8M;
+				break;
+			case SDRAM_CONFIG_SIZE_16M:
+				mem_size += PPC44x_MEM_SIZE_16M;
+				break;
+			case SDRAM_CONFIG_SIZE_32M:
+				mem_size += PPC44x_MEM_SIZE_32M;
+				break;
+			case SDRAM_CONFIG_SIZE_64M:
+				mem_size += PPC44x_MEM_SIZE_64M;
+				break;
+			case SDRAM_CONFIG_SIZE_128M:
+				mem_size += PPC44x_MEM_SIZE_128M;
+				break;
+			case SDRAM_CONFIG_SIZE_256M:
+				mem_size += PPC44x_MEM_SIZE_256M;
+				break;
+			case SDRAM_CONFIG_SIZE_512M:
+				mem_size += PPC44x_MEM_SIZE_512M;
+				break;
+		}
+	}
+	return mem_size;
+}
+
+static void __init ibm44x_init_irq(void)
+{
+	int i;
+
+	ppc4xx_pic_init();
+
+	for (i = 0; i < NR_IRQS; i++)
+		irq_desc[i].handler = ppc4xx_pic;
+}
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+#include <linux/serialP.h>
+#include <linux/serial_reg.h>
+#include <asm/serial.h>
+
+static struct serial_state rs_table[RS_TABLE_SIZE] = {
+	SERIAL_PORT_DFNS	/* Defined in <asm/serial.h> */
+};
+
+static void ibm44x_progress(char *s, unsigned short hex)
+{
+	volatile char c;
+	volatile unsigned long com_port;
+	u16 shift;
+
+	com_port = (unsigned long)rs_table[0].iomem_base;
+	shift = rs_table[0].iomem_reg_shift;
+
+	while ((c = *s++) != 0) {
+		while ((*((volatile unsigned char *)com_port +
+				(UART_LSR << shift)) & UART_LSR_THRE) == 0)
+			;
+		*(volatile unsigned char *)com_port = c;
+
+	}
+
+	/* Send LF/CR to pretty up output */
+	while ((*((volatile unsigned char *)com_port +
+		(UART_LSR << shift)) & UART_LSR_THRE) == 0)
+		;
+	*(volatile unsigned char *)com_port = '\r';
+	while ((*((volatile unsigned char *)com_port +
+		(UART_LSR << shift)) & UART_LSR_THRE) == 0)
+		;
+	*(volatile unsigned char *)com_port = '\n';
+}
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+
+void __init ibm44x_platform_init(void)
+{
+	ppc_md.init_IRQ = ibm44x_init_irq;
+	ppc_md.find_end_of_memory = ibm44x_find_end_of_memory;
+	ppc_md.restart = ibm44x_restart;
+	ppc_md.power_off = ibm44x_power_off;
+	ppc_md.halt = ibm44x_halt;
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+	ppc_md.progress = ibm44x_progress;
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+}
+
diff --git a/arch/ppc/syslib/ibm44x_common.h b/arch/ppc/syslib/ibm44x_common.h
index ee1053ac2..b14eb603c 100644
--- a/arch/ppc/syslib/ibm44x_common.h
+++ b/arch/ppc/syslib/ibm44x_common.h
@@ -4,7 +4,7 @@
  * PPC44x system library
  *
  * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
- * Copyright (c) 2003 Zultys Technologies
+ * Copyright (c) 2003, 2004 Zultys Technologies
  *
  * 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
@@ -31,6 +31,12 @@ struct ibm44x_clocks {
 	unsigned int uart1;
 };
 
+/* common 44x platform init */
+void ibm44x_platform_init(void) __init;
+
+/* initialize decrementer and tick-related variables */
+void ibm44x_calibrate_decr(unsigned int freq) __init;
+
 #endif /* __ASSEMBLY__ */
 #endif /* __PPC_SYSLIB_IBM44x_COMMON_H */
 #endif /* __KERNEL__ */
diff --git a/arch/ppc/syslib/m8260_pci.h b/arch/ppc/syslib/m8260_pci.h
index 4e2ce7f7c..d1352120a 100644
--- a/arch/ppc/syslib/m8260_pci.h
+++ b/arch/ppc/syslib/m8260_pci.h
@@ -66,6 +66,7 @@
 #endif
 
 #ifdef CONFIG_8260_PCI9
+struct pci_controller;
 extern void setup_m8260_indirect_pci(struct pci_controller* hose,
 				     u32 cfg_addr, u32 cfg_data);
 #else
diff --git a/arch/ppc/syslib/m8260_setup.c b/arch/ppc/syslib/m8260_setup.c
index 24e1494c1..bfa66a235 100644
--- a/arch/ppc/syslib/m8260_setup.c
+++ b/arch/ppc/syslib/m8260_setup.c
@@ -1,5 +1,5 @@
 /*
- *  arch/ppc/kernel/setup.c
+ *  arch/ppc/syslib/m8260_setup.c
  *
  *  Copyright (C) 1995  Linus Torvalds
  *  Adapted from 'alpha' version by Gary Thomas
@@ -8,36 +8,20 @@
  *  Further modified for generic 8xx and 8260 by Dan.
  */
 
-/*
- * bootup setup stuff..
- */
-
 #include <linux/config.h>
-#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
 #include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/a.out.h>
-#include <linux/tty.h>
-#include <linux/major.h>
-#include <linux/interrupt.h>
-#include <linux/reboot.h>
 #include <linux/init.h>
 #include <linux/initrd.h>
-#include <linux/ioport.h>
-#include <linux/ide.h>
 #include <linux/seq_file.h>
+#include <linux/irq.h>
 
 #include <asm/mmu.h>
-#include <asm/residual.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
-#include <asm/ide.h>
 #include <asm/mpc8260.h>
 #include <asm/immap_cpm2.h>
 #include <asm/machdep.h>
@@ -46,10 +30,6 @@
 
 #include "cpm2_pic.h"
 
-static int m8260_set_rtc_time(unsigned long time);
-static unsigned long m8260_get_rtc_time(void);
-static void m8260_calibrate_decr(void);
-
 unsigned char __res[sizeof(bd_t)];
 
 extern void cpm2_reset(void);
@@ -59,8 +39,10 @@ extern void idma_pci9_init(void);
 static void __init
 m8260_setup_arch(void)
 {
-	/* Reset the Communication Processor Module.
-	*/
+	/* Print out Vendor and Machine info. */
+	printk(KERN_INFO "%s %s port\n", CPUINFO_VENDOR, CPUINFO_MACHINE);
+
+	/* Reset the Communication Processor Module. */
 	cpm2_reset();
 #ifdef CONFIG_8260_PCI9
 	/* Initialise IDMA for PCI erratum workaround */
@@ -69,6 +51,10 @@ m8260_setup_arch(void)
 #ifdef CONFIG_PCI_8260
 	m8260_find_bridges();
 #endif
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+#endif
 }
 
 /* The decrementer counts at the system (internal) clock frequency
@@ -77,7 +63,7 @@ m8260_setup_arch(void)
 static void __init
 m8260_calibrate_decr(void)
 {
-	bd_t	*binfo = (bd_t *)__res;
+	bd_t *binfo = (bd_t *)__res;
 	int freq, divisor;
 
 	freq = binfo->bi_busfreq;
@@ -145,18 +131,22 @@ m8260_power_off(void)
 }
 
 static int
-m8260_show_percpuinfo(struct seq_file *m, int i)
+m8260_show_cpuinfo(struct seq_file *m)
 {
-	bd_t	*bp;
-
-	bp = (bd_t *)__res;
-
-	seq_printf(m, "core clock\t: %ld MHz\n"
-		   "CPM  clock\t: %ld MHz\n"
-		   "bus  clock\t: %ld MHz\n",
-		   bp->bi_intfreq / 1000000,
-		   bp->bi_cpmfreq / 1000000,
-		   bp->bi_busfreq / 1000000);
+	bd_t *bp = (bd_t *)__res;
+
+	seq_printf(m, "vendor\t\t: %s\n"
+		   "machine\t\t: %s\n"
+		   "\n"
+		   "mem size\t\t: 0x%08x\n"
+		   "console baud\t\t: %d\n"
+		   "\n"
+		   "core clock\t: %u MHz\n"
+		   "CPM  clock\t: %u MHz\n"
+		   "bus  clock\t: %u MHz\n",
+		   CPUINFO_VENDOR, CPUINFO_MACHINE, bp->bi_memsize,
+		   bp->bi_baudrate, bp->bi_intfreq / 1000000,
+		   bp->bi_cpmfreq / 1000000, bp->bi_busfreq / 1000000);
 	return 0;
 }
 
@@ -170,7 +160,6 @@ static void __init
 m8260_init_IRQ(void)
 {
 	int i;
-	void cpm_interrupt_init(void);
 
         for ( i = 0 ; i < NR_SIU_INTS ; i++ )
                 irq_desc[i].handler = &cpm2_pic;
@@ -190,10 +179,7 @@ m8260_init_IRQ(void)
 static unsigned long __init
 m8260_find_end_of_memory(void)
 {
-	bd_t	*binfo;
-	extern unsigned char __res[];
-
-	binfo = (bd_t *)__res;
+	bd_t *binfo = (bd_t *)__res;
 
 	return binfo->bi_memsize;
 }
@@ -216,6 +202,12 @@ m8260_map_io(void)
 	io_block_mapping(IO_VIRT_ADDR, IO_PHYS_ADDR, 0x10000000, _PAGE_IO);
 }
 
+/* Place-holder for board-specific init */
+void __attribute__ ((weak)) __init
+m82xx_board_init(void)
+{
+}
+
 /* Inputs:
  *   r3 - Optional pointer to a board information structure.
  *   r4 - Optional pointer to the physical starting address of the init RAM
@@ -228,7 +220,7 @@ m8260_map_io(void)
  *        command-line parameters.
  */
 void __init
-m8260_init(unsigned long r3, unsigned long r4, unsigned long r5,
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
 	      unsigned long r6, unsigned long r7)
 {
 	parse_bootinfo(find_bootinfo());
@@ -249,18 +241,18 @@ m8260_init(unsigned long r3, unsigned long r4, unsigned long r5,
 		strcpy(cmd_line, (char *)(r6+KERNELBASE));
 	}
 
+	/* Call back for board-specific settings. */
+	m82xx_board_init();
+
 	ppc_md.setup_arch		= m8260_setup_arch;
-	ppc_md.show_percpuinfo		= m8260_show_percpuinfo;
-	ppc_md.irq_canonicalize	= NULL;
+	ppc_md.show_cpuinfo		= m8260_show_cpuinfo;
 	ppc_md.init_IRQ			= m8260_init_IRQ;
 	ppc_md.get_irq			= cpm2_get_irq;
-	ppc_md.init			= NULL;
 
 	ppc_md.restart			= m8260_restart;
 	ppc_md.power_off		= m8260_power_off;
 	ppc_md.halt			= m8260_halt;
 
-	ppc_md.time_init		= NULL;
 	ppc_md.set_rtc_time		= m8260_set_rtc_time;
 	ppc_md.get_rtc_time		= m8260_get_rtc_time;
 	ppc_md.calibrate_decr		= m8260_calibrate_decr;
diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c
index 5ccf07149..0dc7889a8 100644
--- a/arch/ppc/syslib/m8xx_setup.c
+++ b/arch/ppc/syslib/m8xx_setup.c
@@ -60,6 +60,11 @@ extern unsigned long find_available_memory(void);
 extern void m8xx_cpm_reset(uint);
 extern void rpxfb_alloc_pages(void);
 
+void __attribute__ ((weak))
+board_init(void)
+{
+}
+
 void __init
 m8xx_setup_arch(void)
 {
@@ -102,6 +107,7 @@ m8xx_setup_arch(void)
 	}
 #endif
 #endif
+	board_init();
 }
 
 void
diff --git a/arch/ppc/syslib/mpc52xx_pic.c b/arch/ppc/syslib/mpc52xx_pic.c
index 0f88e63b0..4de79d3b9 100644
--- a/arch/ppc/syslib/mpc52xx_pic.c
+++ b/arch/ppc/syslib/mpc52xx_pic.c
@@ -114,7 +114,7 @@ mpc52xx_ic_ack(unsigned int irq)
 	/*
 	 * Only some irqs are reset here, others in interrupting hardware.
 	 */
-			
+
 	switch (irq) {
 	case MPC52xx_IRQ0:
 		val = in_be32(&intr->ctrl);
@@ -180,13 +180,14 @@ void __init
 mpc52xx_init_irq(void)
 {
 	int i;
+	u32 intr_ctrl;
 
 	/* Remap the necessary zones */
 	intr = (struct mpc52xx_intr *)
 		ioremap(MPC52xx_INTR, sizeof(struct mpc52xx_intr));
 	sdma = (struct mpc52xx_sdma *)
 		ioremap(MPC52xx_SDMA, sizeof(struct mpc52xx_sdma));
-	
+
 	if ((intr==NULL) || (sdma==NULL))
 		panic("Can't ioremap PIC/SDMA register for init_irq !");
 
@@ -195,12 +196,13 @@ mpc52xx_init_irq(void)
 	out_be32(&sdma->IntMask, 0xffffffff);	/* 1 means disabled */
 	out_be32(&intr->per_mask, 0x7ffffc00);	/* 1 means disabled */
 	out_be32(&intr->main_mask, 0x00010fff);	/* 1 means disabled */
-	out_be32(&intr->ctrl,
-			0x0f000000 |	/* clear IRQ 0-3 */
-			0x00c00000 |	/* IRQ0: level-sensitive, active low */
+	intr_ctrl = in_be32(&intr->ctrl);
+	intr_ctrl &=    0x00ff0000;	/* Keeps IRQ[0-3] config */
+	intr_ctrl |=	0x0f000000 |	/* clear IRQ 0-3 */
 			0x00001000 |	/* MEE master external enable */
 			0x00000000 |	/* 0 means disable IRQ 0-3 */
-			0x00000001);	/* CEb route critical normally */
+			0x00000001;	/* CEb route critical normally */
+	out_be32(&intr->ctrl, intr_ctrl);
 
 	/* Zero a bunch of the priority settings.  */
 	out_be32(&intr->per_pri1, 0);
@@ -214,6 +216,14 @@ mpc52xx_init_irq(void)
 		irq_desc[i].handler = &mpc52xx_ic;
 		irq_desc[i].status = IRQ_LEVEL;
 	}
+
+	#define IRQn_MODE(intr_ctrl,irq) (((intr_ctrl) >> (22-(i<<1))) & 0x03)
+	for (i=0 ; i<4 ; i++) {
+		int mode;
+		mode = IRQn_MODE(intr_ctrl,i);
+		if ((mode == 0x1) || (mode == 0x2))
+			irq_desc[i?MPC52xx_IRQ1+i-1:MPC52xx_IRQ0].status = 0;
+	}
 }
 
 int
diff --git a/arch/ppc/syslib/mpc52xx_setup.c b/arch/ppc/syslib/mpc52xx_setup.c
index 631cea34b..d73e6fea5 100644
--- a/arch/ppc/syslib/mpc52xx_setup.c
+++ b/arch/ppc/syslib/mpc52xx_setup.c
@@ -1,5 +1,5 @@
 /*
- * arch/ppc/syslib/mpc52xx_common.c
+ * arch/ppc/syslib/mpc52xx_setup.c
  *
  * Common code for the boards based on Freescale MPC52xx embedded CPU.
  *
@@ -23,6 +23,7 @@
 #include <asm/mpc52xx.h>
 #include <asm/mpc52xx_psc.h>
 #include <asm/ocp.h>
+#include <asm/pgtable.h>
 #include <asm/ppcboot.h>
 
 extern bd_t __res;
@@ -38,9 +39,9 @@ void
 mpc52xx_restart(char *cmd)
 {
 	struct mpc52xx_gpt* gpt0 = (struct mpc52xx_gpt*) MPC52xx_GPTx(0);
-	
+
 	local_irq_disable();
-	
+
 	/* Turn on the watchdog and wait for it to expire. It effectively
 	  does a reset */
 	if (gpt0 != NULL) {
@@ -99,24 +100,28 @@ mpc52xx_map_io(void)
 #error "mpc52xx PSC for console not selected"
 #endif
 
+static void
+mpc52xx_psc_putc(struct mpc52xx_psc * psc, unsigned char c)
+{
+	while (!(in_be16(&psc->mpc52xx_psc_status) &
+	         MPC52xx_PSC_SR_TXRDY));
+	out_8(&psc->mpc52xx_psc_buffer_8, c);
+}
+
 void
 mpc52xx_progress(char *s, unsigned short hex)
 {
 	struct mpc52xx_psc *psc = (struct mpc52xx_psc *)MPC52xx_CONSOLE;
 	char c;
 
-		/* Don't we need to disable serial interrupts ? */
-	
 	while ((c = *s++) != 0) {
-		if (c == '\n') {
-			while (!(in_be16(&psc->mpc52xx_psc_status) &
-			         MPC52xx_PSC_SR_TXRDY)) ;
-			out_8(&psc->mpc52xx_psc_buffer_8, '\r');
-		}
-		while (!(in_be16(&psc->mpc52xx_psc_status) &
-		         MPC52xx_PSC_SR_TXRDY)) ;
-		out_8(&psc->mpc52xx_psc_buffer_8, c);
+		if (c == '\n')
+			mpc52xx_psc_putc(psc, '\r');
+		mpc52xx_psc_putc(psc, c);
 	}
+
+	mpc52xx_psc_putc(psc, '\r');
+	mpc52xx_psc_putc(psc, '\n');
 }
 
 #endif  /* CONFIG_SERIAL_TEXT_DEBUG */
@@ -137,7 +142,7 @@ mpc52xx_find_end_of_memory(void)
 
 		/* Temp BAT2 mapping active when this is called ! */
 		mmap_ctl = (struct mpc52xx_mmap_ctl*) MPC52xx_MMAP_CTL;
-			
+
 		sdram_config_0 = in_be32(&mmap_ctl->sdram0);
 		sdram_config_1 = in_be32(&mmap_ctl->sdram1);
 
@@ -147,10 +152,8 @@ mpc52xx_find_end_of_memory(void)
 		if (((sdram_config_1 & 0x1f) >= 0x13) &&
 				((sdram_config_1 & 0xfff00000) == ramsize))
 			ramsize += 1 << ((sdram_config_1 & 0xf) + 17);
-
-		iounmap(mmap_ctl);
 	}
-	
+
 	return ramsize;
 }
 
@@ -167,7 +170,7 @@ mpc52xx_calibrate_decr(void)
 		/* Get RTC & Clock manager modules */
 		struct mpc52xx_rtc *rtc;
 		struct mpc52xx_cdm *cdm;
-		
+
 		rtc = (struct mpc52xx_rtc*)
 			ioremap(MPC52xx_RTC, sizeof(struct mpc52xx_rtc));
 		cdm = (struct mpc52xx_cdm*)
@@ -206,7 +209,7 @@ mpc52xx_calibrate_decr(void)
 		__res.bi_intfreq = cpufreq;
 		__res.bi_ipbfreq = ipbfreq;
 		__res.bi_pcifreq = pcifreq;
-	
+
 		/* Release mapping */
 		iounmap((void*)rtc);
 		iounmap((void*)cdm);
diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c
index a19f8c2d9..133797ab3 100644
--- a/arch/ppc/syslib/open_pic.c
+++ b/arch/ppc/syslib/open_pic.c
@@ -16,6 +16,7 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/sysdev.h>
+#include <linux/errno.h>
 #include <asm/ptrace.h>
 #include <asm/signal.h>
 #include <asm/io.h>
@@ -24,7 +25,6 @@
 #include <asm/sections.h>
 #include <asm/open_pic.h>
 #include <asm/i8259.h>
-#include <asm/hardirq.h>
 
 #include "open_pic_defs.h"
 
@@ -412,7 +412,7 @@ void __init openpic_init(int offset)
 
 	/* Initialize the spurious interrupt */
 	if (ppc_md.progress) ppc_md.progress("openpic: spurious",0x3bd);
-	openpic_set_spurious(OPENPIC_VEC_SPURIOUS+offset);
+	openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
 	openpic_disable_8259_pass_through();
 #ifdef CONFIG_EPIC_SERIAL_MODE
 	openpic_eicr_set_clk(7);	/* Slowest value until we know better */
@@ -865,7 +865,7 @@ openpic_get_irq(struct pt_regs *regs)
 			irq = cirq;
 			openpic_eoi();
 		}
-        } else if (irq == OPENPIC_VEC_SPURIOUS + open_pic_irq_offset)
+	} else if (irq == OPENPIC_VEC_SPURIOUS)
 		irq = -1;
 	return irq;
 }
@@ -988,9 +988,9 @@ int openpic_resume(struct sys_device *sysdev)
 
 	/* OpenPIC sometimes seem to need some time to be fully back up... */
 	do {
-		openpic_set_spurious(OPENPIC_VEC_SPURIOUS+open_pic_irq_offset);
+		openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
 	} while(openpic_readfield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK)
-			!= (OPENPIC_VEC_SPURIOUS + open_pic_irq_offset));
+			!= OPENPIC_VEC_SPURIOUS);
 	
 	openpic_disable_8259_pass_through();
 
diff --git a/arch/ppc/syslib/open_pic2.c b/arch/ppc/syslib/open_pic2.c
index 52cb4a494..191e5af0e 100644
--- a/arch/ppc/syslib/open_pic2.c
+++ b/arch/ppc/syslib/open_pic2.c
@@ -20,6 +20,7 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/sysdev.h>
+#include <linux/errno.h>
 #include <asm/ptrace.h>
 #include <asm/signal.h>
 #include <asm/io.h>
@@ -28,7 +29,6 @@
 #include <asm/sections.h>
 #include <asm/open_pic.h>
 #include <asm/i8259.h>
-#include <asm/hardirq.h>
 
 #include "open_pic_defs.h"
 
diff --git a/arch/ppc/syslib/ppc4xx_pic.c b/arch/ppc/syslib/ppc4xx_pic.c
index e6da0a20d..2dc63a58c 100644
--- a/arch/ppc/syslib/ppc4xx_pic.c
+++ b/arch/ppc/syslib/ppc4xx_pic.c
@@ -256,7 +256,7 @@ static void
 ppc4xx_uic_end(unsigned int irq)
 {
 	int bit, word;
-	unsigned int tr_bits;
+	unsigned int tr_bits = 0;
 
 	bit = irq & 0x1f;
 	word = irq >> 5;
diff --git a/arch/ppc/syslib/ppc4xx_setup.c b/arch/ppc/syslib/ppc4xx_setup.c
index f7458822f..735f3aec8 100644
--- a/arch/ppc/syslib/ppc4xx_setup.c
+++ b/arch/ppc/syslib/ppc4xx_setup.c
@@ -61,10 +61,6 @@ ppc4xx_setup_arch(void)
 #ifdef CONFIG_PCI
 	ppc4xx_find_bridges();
 #endif
-
-#if defined(CONFIG_FB)
-	conswitchp = &dummy_con;
-#endif
 }
 
 /*
diff --git a/arch/ppc/syslib/ppc85xx_setup.c b/arch/ppc/syslib/ppc85xx_setup.c
index 6ceea97f4..d4e651534 100644
--- a/arch/ppc/syslib/ppc85xx_setup.c
+++ b/arch/ppc/syslib/ppc85xx_setup.c
@@ -277,7 +277,7 @@ mpc85xx_setup_hose(void)
 	hose_a->io_space.start = MPC85XX_PCI1_LOWER_IO;
 	hose_a->io_space.end = MPC85XX_PCI1_UPPER_IO;
 	hose_a->io_base_phys = MPC85XX_PCI1_IO_BASE;
-#if CONFIG_85xx_PCI2
+#ifdef CONFIG_85xx_PCI2
 	isa_io_base =
 		(unsigned long) ioremap(MPC85XX_PCI1_IO_BASE,
 					MPC85XX_PCI1_IO_SIZE +
@@ -304,7 +304,7 @@ mpc85xx_setup_hose(void)
 
 	hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno);
 
-#if CONFIG_85xx_PCI2
+#ifdef CONFIG_85xx_PCI2
 	hose_b = pcibios_alloc_controller();
 
 	if (!hose_b)
diff --git a/arch/ppc/syslib/prom_init.c b/arch/ppc/syslib/prom_init.c
index c9701d5ba..ac4c8b158 100644
--- a/arch/ppc/syslib/prom_init.c
+++ b/arch/ppc/syslib/prom_init.c
@@ -115,11 +115,11 @@ prom_entry prom __initdata;
 ihandle prom_chosen __initdata;
 ihandle prom_stdout __initdata;
 
-char *prom_display_paths[FB_MAX] __initdata;
-phandle prom_display_nodes[FB_MAX] __initdata;
-unsigned int prom_num_displays __initdata;
-char *of_stdout_device __initdata;
+static char *prom_display_paths[FB_MAX] __initdata;
+static phandle prom_display_nodes[FB_MAX] __initdata;
+static unsigned int prom_num_displays __initdata;
 static ihandle prom_disp_node __initdata;
+char *of_stdout_device __initdata;
 
 unsigned int rtas_data;   /* physical pointer */
 unsigned int rtas_entry;  /* physical pointer */
@@ -403,6 +403,7 @@ check_display(unsigned long mem)
 
 	for (j=0; j<prom_num_displays; j++) {
 		path = prom_display_paths[j];
+		node = prom_display_nodes[j];
 		prom_print("opening display ");
 		prom_print(path);
 		ih = call_prom("open", 1, 1, path);
@@ -420,6 +421,8 @@ check_display(unsigned long mem)
 			continue;
 		} else {
 			prom_print("... ok\n");
+			call_prom("setprop", 4, 1, node, "linux,opened", 0, NULL);
+
 			/*
 			 * Setup a usable color table when the appropriate
 			 * method is available.
@@ -441,6 +444,19 @@ check_display(unsigned long mem)
 #endif /* CONFIG_LOGO_LINUX_CLUT224 */
 		}
 	}
+	
+	if (prom_stdout) {
+		phandle p;
+		p = call_prom("instance-to-package", 1, 1, prom_stdout);
+		if (p && (int)p != -1) {
+			type[0] = 0;
+			call_prom("getprop", 4, 1, p, "device_type",
+				  type, sizeof(type));
+			if (strcmp(type, "display") == 0)
+				call_prom("setprop", 4, 1, p, "linux,boot-display",
+					  0, NULL);
+		}
+	}
 
 	return ALIGNUL(mem);
 }
diff --git a/arch/ppc/syslib/todc_time.c b/arch/ppc/syslib/todc_time.c
index c1eb1f429..1dc7e0bf5 100644
--- a/arch/ppc/syslib/todc_time.c
+++ b/arch/ppc/syslib/todc_time.c
@@ -277,9 +277,9 @@ todc_time_init(void)
 ulong
 todc_get_rtc_time(void)
 {
-	uint	year, mon, day, hour, min, sec;
+	uint	year = 0, mon = 0, day = 0, hour = 0, min = 0, sec = 0;
 	uint	limit, i;
-	u_char	save_control, uip;
+	u_char	save_control, uip = 0;
 
 	spin_lock(&rtc_lock);
 	save_control = todc_read_val(todc_info->control_a);
@@ -361,7 +361,7 @@ int
 todc_set_rtc_time(unsigned long nowtime)
 {
 	struct rtc_time	tm;
-	u_char		save_control, save_freq_select;
+	u_char		save_control, save_freq_select = 0;
 
 	spin_lock(&rtc_lock);
 	to_tm(nowtime, &tm);
@@ -416,7 +416,7 @@ todc_set_rtc_time(unsigned long nowtime)
  */
 static unsigned char __init todc_read_timereg(int addr)
 {
-	unsigned char save_control, val;
+	unsigned char save_control = 0, val;
 
 	switch (todc_info->rtc_type) {
 		case TODC_TYPE_DS1557:
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
index e9431d81a..6a4adf98f 100644
--- a/arch/ppc64/Kconfig
+++ b/arch/ppc64/Kconfig
@@ -1,4 +1,4 @@
-# 
+#
 # For a description of the syntax of this configuration file,
 # see Documentation/kbuild/kconfig-language.txt.
 #
@@ -58,16 +58,28 @@ menu "Platform support"
 
 choice
 	prompt "Platform Type"
-	default PPC_PSERIES
+	default PPC_MULTIPLATFORM
 
 config PPC_ISERIES
-	bool "iSeries"
+	bool "IBM Legacy iSeries"
 
-config PPC_PSERIES
-	bool "pSeries / PowerMac G5"
+config PPC_MULTIPLATFORM
+	bool "Generic"
 
 endchoice
 
+config PPC_PSERIES
+	depends on PPC_MULTIPLATFORM
+	bool "  IBM pSeries & new iSeries"
+	default y
+
+config PPC_PMAC
+	depends on PPC_MULTIPLATFORM
+	bool "  Apple G5 based machines"
+	default y
+	select ADB_PMU
+	select U3_DART
+
 config PPC
 	bool
 	default y
@@ -77,7 +89,7 @@ config PPC64
 	default y
 
 config PPC_OF
-	depends on PPC_PSERIES
+	depends on PPC_MULTIPLATFORM
 	bool
 	default y
 
@@ -85,14 +97,9 @@ config PPC_OF
 # exception vectors for it
 config ALTIVEC
 	bool "Support for VMX (Altivec) vector unit"
-	depends on PPC_PSERIES
+	depends on PPC_MULTIPLATFORM
 	default y
 
-config PPC_PMAC
-	depends on PPC_PSERIES
-	bool "Apple PowerMac G5 support"
-	select ADB_PMU
-
 config PPC_SPLPAR
 	depends on PPC_PSERIES
 	bool "Support for shared-processor logical partitions"
@@ -103,16 +110,10 @@ config PPC_SPLPAR
 	  processors, that is, which share physical processors between
 	  two or more partitions.
 
-config PMAC_DART
-	bool "Enable DART/IOMMU on PowerMac (allow >2G of RAM)"
-	depends on PPC_PMAC
-	depends on EXPERIMENTAL
+config U3_DART
+	bool 
+	depends on PPC_MULTIPLATFORM
 	default n
-	help
-	  Enabling DART makes it possible to boot a PowerMac G5 with more
-	  than 2GB of memory. Note that the code is very new and untested
-	  at this time, so it has to be considered experimental. Enabling
-	  this might result in data loss.
 
 config PPC_PMAC64
 	bool
@@ -163,7 +164,7 @@ config SMP
 
 config IRQ_ALL_CPUS
 	bool "Distribute interrupts on all CPUs by default"
-	depends on SMP && PPC_PSERIES
+	depends on SMP && PPC_MULTIPLATFORM
 	help
 	  This option gives the kernel permission to distribute IRQs across
 	  multiple CPUs.  Saying N here will route all IRQs to the first
@@ -214,7 +215,7 @@ config MSCHUNKS
 
 config PPC_RTAS
 	bool "Proc interface to RTAS"
-	depends on !PPC_ISERIES
+	depends on PPC_PSERIES
 
 config RTAS_FLASH
 	tristate "Firmware flash interface"
@@ -226,8 +227,9 @@ config SCANLOG
 
 config LPARCFG
 	tristate "LPAR Configuration Data"
+	depends on PPC_PSERIES || PPC_ISERIES
 	help
-	Provide system capacity information via human readable 
+	Provide system capacity information via human readable
 	<key word>=<value> pairs through a /proc/ppc64/lparcfg interface.
 
 endmenu
@@ -272,7 +274,7 @@ source "drivers/pci/Kconfig"
 
 config HOTPLUG_CPU
 	bool "Support for hot-pluggable CPUs"
-	depends on SMP && HOTPLUG && EXPERIMENTAL
+	depends on SMP && HOTPLUG && EXPERIMENTAL && PPC_PSERIES
 	---help---
 	  Say Y here to be able to turn CPUs off and on.
 
@@ -343,98 +345,7 @@ config VIOPATH
 
 source "arch/ppc64/oprofile/Kconfig"
 
-menu "Kernel hacking"
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
-config DEBUG_STACKOVERFLOW
-	bool "Check for stack overflows"
-	depends on DEBUG_KERNEL
-
-config DEBUG_STACK_USAGE
-	bool "Stack utilization instrumentation"
-	depends on DEBUG_KERNEL
-	help
-	  Enables the display of the minimum amount of free stack which each
-	  task has ever had available in the sysrq-T and sysrq-P debug output.
-
-	  This option will slow down process creation somewhat.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-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 XMON
-	bool "Include xmon kernel debugger"
-	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.
-
-config XMON_DEFAULT
-	bool "Enable xmon by default"
-	depends on XMON
-
-config PPCDBG
-	bool "Include PPCDBG realtime debugging"
-	depends on DEBUG_KERNEL
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  If you don't debug the kernel, you can say N.
-
-config IRQSTACKS
-	bool "Use separate kernel stacks when processing interrupts"
-	help
-	  If you say Y here the kernel will use separate kernel stacks
-	  for handling hard and soft interrupts.  This can help avoid
-	  overflowing the process kernel stacks.
-	  
-config SPINLINE
-	bool "Inline spinlock code at each call site"
-	depends on SMP && !PPC_SPLPAR && !PPC_ISERIES
-	help
-	  Say Y if you want to have the code for acquiring spinlocks
-	  and rwlocks inlined at each call site.  This makes the kernel
-	  somewhat bigger, but can be useful when profiling the kernel.
-
-	  If in doubt, say N.
-
-endmenu
+source "arch/ppc64/Kconfig.debug"
 
 source "kernel/vserver/Kconfig"
 
@@ -443,4 +354,3 @@ source "security/Kconfig"
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff --git a/arch/ppc64/Makefile b/arch/ppc64/Makefile
index 10c1d6299..59fdc0e27 100644
--- a/arch/ppc64/Makefile
+++ b/arch/ppc64/Makefile
@@ -15,29 +15,34 @@
 
 KERNELLOAD	:= 0xc000000000000000
 
-HAS_BIARCH      := $(shell if $(CC) -m64 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi;)
+HAS_BIARCH      := $(call cc-option-yn, -m64)
 ifeq ($(HAS_BIARCH),y)
 AS              := $(AS) -a64
 LD              := $(LD) -m elf64ppc
 CC		:= $(CC) -m64
 endif
 
-CHECK		:= $(CHECK) -m64 -D__powerpc__=1
+new_nm := $(shell if $(NM) --help 2>&1 | grep -- '--synthetic' > /dev/null; then echo y; else echo n; fi)
+
+ifeq ($(new_nm),y)
+NM		:= $(NM) --synthetic
+endif
+
+CHECKFLAGS	+= -m64 -D__powerpc__
 
 LDFLAGS		:= -m elf64ppc
 LDFLAGS_vmlinux	:= -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD)
-CFLAGS		+= -msoft-float -pipe -Wno-uninitialized -mminimal-toc \
-		   -mtraceback=none
+CFLAGS		+= -msoft-float -pipe -mminimal-toc -mtraceback=none
 
 ifeq ($(CONFIG_POWER4_ONLY),y)
-	CFLAGS += $(call check_gcc,-mcpu=power4,)
+	CFLAGS += $(call cc-option,-mcpu=power4)
 else
-	CFLAGS += $(call check_gcc,-mtune=power4,)
+	CFLAGS += $(call cc-option,-mtune=power4)
 endif
 
 # Enable unit-at-a-time mode when possible. It shrinks the
 # kernel considerably.
-CFLAGS += $(call check_gcc,-funit-at-a-time,)
+CFLAGS += $(call cc-option,-funit-at-a-time)
 
 head-y := arch/ppc64/kernel/head.o
 
diff --git a/arch/ppc64/boot/Makefile b/arch/ppc64/boot/Makefile
index 9d6431dd6..8f99c9dbc 100644
--- a/arch/ppc64/boot/Makefile
+++ b/arch/ppc64/boot/Makefile
@@ -25,11 +25,11 @@ CROSS32_COMPILE ?=
 
 BOOTCC		:= $(CROSS32_COMPILE)gcc
 HOSTCC		:= gcc
-BOOTCFLAGS	:= $(HOSTCFLAGS) -Iinclude -fno-builtin 
+BOOTCFLAGS	:= $(HOSTCFLAGS) $(LINUXINCLUDE) -fno-builtin 
 BOOTAS		:= $(CROSS32_COMPILE)as
 BOOTAFLAGS	:= -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional
 BOOTLD		:= $(CROSS32_COMPILE)ld
-BOOTLFLAGS	:= -Ttext 0x00400000 -e _start -T $(obj)/zImage.lds
+BOOTLFLAGS	:= -Ttext 0x00400000 -e _start -T $(srctree)/$(src)/zImage.lds
 BOOTOBJCOPY	:= $(CROSS32_COMPILE)objcopy
 OBJCOPYFLAGS    := contents,alloc,load,readonly,data
 
@@ -51,36 +51,31 @@ $(patsubst %.S,%.o, $(filter %.S, $(src-boot))): %.o: %.S
 #-----------------------------------------------------------
 # ELF sections within the zImage bootloader/wrapper
 #-----------------------------------------------------------
-required := vmlinux .config System.map
+required := vmlinux.strip
 initrd   := initrd
 
 obj-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.o, $(section)))
 src-sec = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.c, $(section)))
 gz-sec  = $(foreach section, $(1), $(patsubst %,$(obj)/kernel-%.gz, $(section)))
 
-host-progs		:= piggy addnote addSystemMap addRamDisk
+hostprogs-y		:= piggy addnote addRamDisk
 targets 		+= zImage zImage.initrd imagesize.c \
 			   $(patsubst $(obj)/%,%, $(call obj-sec, $(required) $(initrd))) \
 			   $(patsubst $(obj)/%,%, $(call src-sec, $(required) $(initrd))) \
 			   $(patsubst $(obj)/%,%, $(call gz-sec, $(required) $(initrd))) \
-			   vmlinux.sm vmlinux.initrd vmlinux.sminitrd
-extra-y			:= sysmap.o initrd.o
-
-quiet_cmd_sysmap = SYSMAP   $@
-      cmd_sysmap = $(obj)/addSystemMap System.map $< $@
-$(obj)/vmlinux.sm: vmlinux $(obj)/addSystemMap System.map FORCE
-	$(call if_changed,sysmap)
+			   vmlinux.initrd
+extra-y			:= initrd.o
 
 quiet_cmd_ramdisk = RAMDISK $@
-      cmd_ramdisk = $(obj)/addRamDisk $(obj)/ramdisk.image.gz System.map $< $@
-$(obj)/vmlinux.initrd: vmlinux $(obj)/addRamDisk $(obj)/ramdisk.image.gz System.map FORCE
-	$(call if_changed,ramdisk)
+      cmd_ramdisk = $(obj)/addRamDisk $(obj)/ramdisk.image.gz $< $@
 
-$(obj)/vmlinux.sminitrd: $(obj)/vmlinux.sm $(obj)/addRamDisk $(obj)/ramdisk.image.gz FORCE
-	$(call if_changed,ramdisk)
+quiet_cmd_stripvm = STRIP $@
+      cmd_stripvm = $(STRIP) -s $< -o $@
 
-$(obj)/sysmap.o: System.map $(obj)/piggyback FORCE
-	$(call if_changed,piggy)
+vmlinux.strip: vmlinux FORCE
+	$(call if_changed,stripvm)
+$(obj)/vmlinux.initrd: vmlinux.strip $(obj)/addRamDisk $(obj)/ramdisk.image.gz FORCE
+	$(call if_changed,ramdisk)
 
 addsection = $(BOOTOBJCOPY) $(1) \
 		--add-section=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $(1)))=$(patsubst %.o,%.gz, $(1)) \
@@ -113,9 +108,9 @@ $(obj)/zImage.initrd: obj-boot += $(call obj-sec, $(required) $(initrd))
 $(obj)/zImage.initrd: $(call obj-sec, $(required) $(initrd)) $(obj-boot) $(obj)/addnote FORCE
 	$(call if_changed,addnote)
 
-$(obj)/imagesize.c: vmlinux
+$(obj)/imagesize.c: vmlinux.strip
 	@echo Generating $@
-	ls -l vmlinux | \
+	ls -l vmlinux.strip | \
 	awk '{printf "/* generated -- do not edit! */\n" \
 		"unsigned long vmlinux_filesize = %d;\n", $$5}' > $(obj)/imagesize.c
 	$(CROSS_COMPILE)nm -n vmlinux | tail -n 1 | \
@@ -123,6 +118,6 @@ $(obj)/imagesize.c: vmlinux
 		>> $(obj)/imagesize.c
 
 install: $(CONFIGURE) $(obj)/$(BOOTIMAGE)
-	sh -x $(src)/install.sh "$(KERNELRELEASE)" "$(obj)/$(BOOTIMAGE)" "$(TOPDIR)/System.map" "$(INSTALL_PATH)"
+	sh -x $(src)/install.sh "$(KERNELRELEASE)" "$(obj)/$(BOOTIMAGE)" "$(INSTALL_PATH)"
 
-clean-files := $(patsubst $(obj)/%,%, $(obj-boot))
+clean-files := $(addprefix $(objtree)/, $(obj-boot) vmlinux.strip)
diff --git a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c
index f5a9718ef..6cf78020a 100644
--- a/arch/ppc64/boot/main.c
+++ b/arch/ppc64/boot/main.c
@@ -31,13 +31,9 @@ unsigned long strlen(const char *s);
 void *memmove(void *dest, const void *src, unsigned long n);
 void *memcpy(void *dest, const void *src, unsigned long n);
 
-static struct bi_record *make_bi_recs(unsigned long);
-
-#define RAM_START	0x00000000
-#define RAM_END		(64<<20)
-
 /* Value picked to match that used by yaboot */
 #define PROG_START	0x01400000
+#define RAM_END		(256<<20) // Fixme: use OF */
 
 char *avail_ram;
 char *begin_avail, *end_avail;
@@ -48,8 +44,6 @@ unsigned int heap_max;
 extern char _start[];
 extern char _vmlinux_start[];
 extern char _vmlinux_end[];
-extern char _sysmap_start[];
-extern char _sysmap_end[];
 extern char _initrd_start[];
 extern char _initrd_end[];
 extern unsigned long vmlinux_filesize;
@@ -62,7 +56,6 @@ struct addr_range {
 };
 struct addr_range vmlinux = {0, 0, 0};
 struct addr_range vmlinuz = {0, 0, 0};
-struct addr_range sysmap  = {0, 0, 0};
 struct addr_range initrd  = {0, 0, 0};
 
 static char scratch[128<<10];	/* 128kB of scratch space for gunzip */
@@ -70,7 +63,7 @@ static char scratch[128<<10];	/* 128kB of scratch space for gunzip */
 typedef void (*kernel_entry_t)( unsigned long,
                                 unsigned long,
                                 void *,
-				struct bi_record *);
+				void *);
 
 
 int (*prom)(void *);
@@ -80,12 +73,31 @@ void *stdin;
 void *stdout;
 void *stderr;
 
+#define DEBUG
+
+static unsigned long claim_base = PROG_START;
+
+static unsigned long try_claim(unsigned long size)
+{
+	unsigned long addr = 0;
+
+	for(; claim_base < RAM_END; claim_base += 0x100000) {
+#ifdef DEBUG
+		printf("    trying: 0x%08lx\n\r", claim_base);
+#endif
+		addr = (unsigned long)claim(claim_base, size, 0);
+		if ((void *)addr != (void *)-1)
+			break;
+	}
+	if (addr == 0)
+		return 0;
+	claim_base = PAGE_ALIGN(claim_base + size);
+	return addr;
+}
 
-void
-start(unsigned long a1, unsigned long a2, void *promptr)
+void start(unsigned long a1, unsigned long a2, void *promptr)
 {
-	unsigned long i, claim_addr, claim_size;
-	struct bi_record *bi_recs;
+	unsigned long i;
 	kernel_entry_t kernel_entry;
 	Elf64_Ehdr *elf64;
 	Elf64_Phdr *elf64ph;
@@ -102,61 +114,59 @@ start(unsigned long a1, unsigned long a2, void *promptr)
 
 	printf("zImage starting: loaded at 0x%x\n\r", (unsigned)_start);
 
-#if 0
-	sysmap.size = (unsigned long)(_sysmap_end - _sysmap_start);
-	sysmap.memsize = sysmap.size;
-	if ( sysmap.size > 0 ) {
-		sysmap.addr = (RAM_END - sysmap.size) & ~0xFFF;
-		claim(sysmap.addr, RAM_END - sysmap.addr, 0);
-		printf("initial ramdisk moving 0x%lx <- 0x%lx (%lx bytes)\n\r",
-		       sysmap.addr, (unsigned long)_sysmap_start, sysmap.size);
-		memcpy((void *)sysmap.addr, (void *)_sysmap_start, sysmap.size);
+	/*
+	 * Now we try to claim some memory for the kernel itself
+	 * our "vmlinux_memsize" is the memory footprint in RAM, _HOWEVER_, what
+	 * our Makefile stuffs in is an image containing all sort of junk including
+	 * an ELF header. We need to do some calculations here to find the right
+	 * size... In practice we add 1Mb, that is enough, but we should really
+	 * consider fixing the Makefile to put a _raw_ kernel in there !
+	 */
+	vmlinux_memsize += 0x100000;
+	printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux_memsize);
+	vmlinux.addr = try_claim(vmlinux_memsize);
+	if (vmlinux.addr == 0) {
+		printf("Can't allocate memory for kernel image !\n\r");
+		exit();
 	}
-#endif
+	vmlinuz.addr = (unsigned long)_vmlinux_start;
+	vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
+	vmlinux.size = PAGE_ALIGN(vmlinux_filesize);
+	vmlinux.memsize = vmlinux_memsize;
 
+	/*
+	 * Now we try to claim memory for the initrd (and copy it there)
+	 */
 	initrd.size = (unsigned long)(_initrd_end - _initrd_start);
 	initrd.memsize = initrd.size;
 	if ( initrd.size > 0 ) {
-		initrd.addr = (RAM_END - initrd.size) & ~0xFFF;
-		a1 = a2 = 0;
-		claim(initrd.addr, RAM_END - initrd.addr, 0);
+		printf("Allocating 0x%lx bytes for initrd ...\n\r", initrd.size);
+		initrd.addr = try_claim(initrd.size);
+		if (initrd.addr == 0) {
+			printf("Can't allocate memory for initial ramdisk !\n\r");
+			exit();
+		}
+		a1 = initrd.addr;
+		a2 = initrd.size;
 		printf("initial ramdisk moving 0x%lx <- 0x%lx (%lx bytes)\n\r",
 		       initrd.addr, (unsigned long)_initrd_start, initrd.size);
-		memcpy((void *)initrd.addr, (void *)_initrd_start, initrd.size);
-	}
-
-	vmlinuz.addr = (unsigned long)_vmlinux_start;
-	vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
-	vmlinux.addr = (unsigned long)(void *)-1;
-	vmlinux.size = PAGE_ALIGN(vmlinux_filesize);
-	vmlinux.memsize = vmlinux_memsize;
-
-	claim_size = vmlinux.memsize /* PPPBBB: + fudge for bi_recs */;
-	for(claim_addr = PROG_START; 
-	    claim_addr <= PROG_START * 8; 
-	    claim_addr += 0x100000) {
-#ifdef DEBUG
-		printf("    trying: 0x%08lx\n\r", claim_addr);
-#endif
-		vmlinux.addr = (unsigned long)claim(claim_addr, claim_size, 0);
-		if ((void *)vmlinux.addr != (void *)-1) break;
-	}
-	if ((void *)vmlinux.addr == (void *)-1) {
-		printf("claim error, can't allocate kernel memory\n\r");
-		exit();
+		memmove((void *)initrd.addr, (void *)_initrd_start, initrd.size);
+		printf("initrd head: 0x%lx\n", *((u32 *)initrd.addr));
 	}
 
-	/* PPPBBB: should kernel always be gziped? */
+	/* Eventually gunzip the kernel */
 	if (*(unsigned short *)vmlinuz.addr == 0x1f8b) {
+		int len;
 		avail_ram = scratch;
 		begin_avail = avail_high = avail_ram;
 		end_avail = scratch + sizeof(scratch);
 		printf("gunzipping (0x%lx <- 0x%lx:0x%0lx)...",
 		       vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size);
+		len = vmlinuz.size;
 		gunzip((void *)vmlinux.addr, vmlinux.size,
-			(unsigned char *)vmlinuz.addr, (int *)&vmlinuz.size);
-		printf("done %lu bytes\n\r", vmlinuz.size);
-		printf("%u bytes of heap consumed, max in use %u\n\r",
+			(unsigned char *)vmlinuz.addr, &len);
+		printf("done 0x%lx bytes\n\r", len);
+		printf("0x%x bytes of heap consumed, max in use 0x%\n\r",
 		       (unsigned)(avail_high - begin_avail), heap_max);
 	} else {
 		memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,vmlinuz.size);
@@ -192,7 +202,8 @@ start(unsigned long a1, unsigned long a2, void *promptr)
 
 	flush_cache((void *)vmlinux.addr, vmlinux.memsize);
 
-	bi_recs = make_bi_recs(vmlinux.addr + vmlinux.memsize);
+	if (a1)
+		printf("initrd head: 0x%lx\n\r", *((u32 *)initrd.addr));
 
 	kernel_entry = (kernel_entry_t)vmlinux.addr;
 #ifdef DEBUG
@@ -203,65 +214,16 @@ start(unsigned long a1, unsigned long a2, void *promptr)
 		"        prom       = 0x%lx,\n\r"
 		"        bi_recs    = 0x%lx,\n\r",
 		(unsigned long)kernel_entry, a1, a2,
-		(unsigned long)prom, (unsigned long)bi_recs);
+		(unsigned long)prom, NULL);
 #endif
 
-	kernel_entry( a1, a2, prom, bi_recs );
+	kernel_entry( a1, a2, prom, NULL );
 
 	printf("Error: Linux kernel returned to zImage bootloader!\n\r");
 
 	exit();
 }
 
-static struct bi_record *
-make_bi_recs(unsigned long addr)
-{
-	struct bi_record *bi_recs;
-	struct bi_record *rec;
-
-	bi_recs = rec = bi_rec_init(addr);
-
-	rec = bi_rec_alloc(rec, 2);
-	rec->tag = BI_FIRST;
-	/* rec->data[0] = ...;	# Written below before return */
-	/* rec->data[1] = ...;	# Written below before return */
-
-	rec = bi_rec_alloc_bytes(rec, strlen("chrpboot")+1);
-	rec->tag = BI_BOOTLOADER_ID;
-	sprintf( (char *)rec->data, "chrpboot");
-
-	rec = bi_rec_alloc(rec, 2);
-	rec->tag = BI_MACHTYPE;
-	rec->data[0] = PLATFORM_PSERIES;
-	rec->data[1] = 1;
-
-	if ( initrd.size > 0 ) {
-		rec = bi_rec_alloc(rec, 2);
-		rec->tag = BI_INITRD;
-		rec->data[0] = initrd.addr;
-		rec->data[1] = initrd.size;
-	}
-
-	if ( sysmap.size > 0 ) {
-		rec = bi_rec_alloc(rec, 2);
-		rec->tag = BI_SYSMAP;
-		rec->data[0] = (unsigned long)sysmap.addr;
-		rec->data[1] = (unsigned long)sysmap.size;
-	}
-
-	rec = bi_rec_alloc(rec, 1);
-	rec->tag = BI_LAST;
-	rec->data[0] = (bi_rec_field)bi_recs;
-
-	/* Save the _end_ address of the bi_rec's in the first bi_rec
-	 * data field for easy access by the kernel.
-	 */
-	bi_recs->data[0] = (bi_rec_field)rec;
-	bi_recs->data[1] = (bi_rec_field)rec + rec->size - (bi_rec_field)bi_recs;
-
-	return bi_recs;
-}
-
 struct memchunk {
 	unsigned int size;
 	unsigned int pad;
diff --git a/arch/ppc64/boot/zImage.lds b/arch/ppc64/boot/zImage.lds
index 7070cd2f7..941ade38f 100644
--- a/arch/ppc64/boot/zImage.lds
+++ b/arch/ppc64/boot/zImage.lds
@@ -61,19 +61,9 @@ SECTIONS
 
   . = ALIGN(4096);
   _vmlinux_start =  .;
-  .kernel:vmlinux : { *(.kernel:vmlinux) }
+  .kernel:vmlinux.strip : { *(.kernel:vmlinux.strip) }
   _vmlinux_end =  .;
 
-  . = ALIGN(4096);
-  _dotconfig_start =  .;
-  .kernel:.config : { *(.kernel:.config) }
-  _dotconfig_end =  .;
-
-  . = ALIGN(4096);
-  _sysmap_start =  .;
-  .kernel:System.map : { *(.kernel:System.map) }
-  _sysmap_end =  .;
-
   . = ALIGN(4096);
   _initrd_start =  .;
   .kernel:initrd : { *(.kernel:initrd) }
diff --git a/arch/ppc64/configs/g5_defconfig b/arch/ppc64/configs/g5_defconfig
index 0485eed76..9cc01b5ba 100644
--- a/arch/ppc64/configs/g5_defconfig
+++ b/arch/ppc64/configs/g5_defconfig
@@ -1,5 +1,7 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc3
+# Thu Oct  7 15:18:38 2004
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
@@ -16,11 +18,11 @@ CONFIG_FORCE_MAX_ZONEORDER=13
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
@@ -32,6 +34,8 @@ CONFIG_HOTPLUG=y
 # CONFIG_IKCONFIG is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_IOSCHED_NOOP=y
@@ -39,6 +43,8 @@ CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -50,18 +56,20 @@ CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_KMOD is not set
 CONFIG_STOP_MACHINE=y
+CONFIG_SYSVIPC_COMPAT=y
 
 #
 # Platform support
 #
 # CONFIG_PPC_ISERIES is not set
-CONFIG_PPC_PSERIES=y
+CONFIG_PPC_MULTIPLATFORM=y
+# CONFIG_PPC_PSERIES is not set
+CONFIG_PPC_PMAC=y
 CONFIG_PPC=y
 CONFIG_PPC64=y
 CONFIG_PPC_OF=y
 CONFIG_ALTIVEC=y
-CONFIG_PPC_PMAC=y
-CONFIG_PMAC_DART=y
+CONFIG_U3_DART=y
 CONFIG_PPC_PMAC64=y
 CONFIG_BOOTX_TEXT=y
 CONFIG_POWER4_ONLY=y
@@ -69,8 +77,8 @@ CONFIG_IOMMU_VMERGE=y
 CONFIG_SMP=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_NR_CPUS=2
-# CONFIG_HMT is not set
-# CONFIG_DISCONTIGMEM is not set
+# CONFIG_SCHED_SMT is not set
+# CONFIG_PREEMPT is not set
 # CONFIG_PPC_RTAS is not set
 # CONFIG_LPARCFG is not set
 
@@ -104,6 +112,8 @@ CONFIG_PROC_DEVICETREE=y
 #
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
 
@@ -132,7 +142,8 @@ CONFIG_FW_LOADER=y
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 CONFIG_BLK_DEV_NBD=m
-# CONFIG_BLK_DEV_CARMEL 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_SIZE=8192
 CONFIG_BLK_DEV_INITRD=y
@@ -146,9 +157,9 @@ 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_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
 CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_IDETAPE=y
 CONFIG_BLK_DEV_IDEFLOPPY=y
@@ -170,7 +181,6 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_ADMA=y
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD74XX is not set
@@ -196,6 +206,7 @@ CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
 CONFIG_BLK_DEV_IDEDMA_PMAC=y
 # CONFIG_BLK_DEV_IDE_PMAC_BLINK is not set
 CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO=y
+# CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
 CONFIG_IDEDMA_AUTO=y
@@ -221,7 +232,6 @@ CONFIG_CHR_DEV_SG=y
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_REPORT_LUNS=y
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
 
@@ -235,23 +245,25 @@ CONFIG_SCSI_SPI_ATTRS=y
 # SCSI low-level drivers
 #
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AACRAID is not set
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
 CONFIG_SCSI_SATA=y
 CONFIG_SCSI_SATA_SVW=y
 # CONFIG_SCSI_ATA_PIIX is not set
+# CONFIG_SCSI_SATA_NV is not set
 # CONFIG_SCSI_SATA_PROMISE is not set
+# CONFIG_SCSI_SATA_SX4 is not set
 # CONFIG_SCSI_SATA_SIL is not set
 # CONFIG_SCSI_SATA_SIS is not set
 # CONFIG_SCSI_SATA_VIA is not set
 # CONFIG_SCSI_SATA_VITESSE is not set
 # CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_PIO is not set
@@ -264,6 +276,7 @@ CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -277,7 +290,6 @@ CONFIG_SCSI_QLA2XXX=y
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_MESH is not set
 # CONFIG_SCSI_MAC53C94 is not set
 
 #
@@ -288,11 +300,15 @@ CONFIG_BLK_DEV_MD=y
 CONFIG_MD_LINEAR=y
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
+# CONFIG_MD_RAID10 is not set
 CONFIG_MD_RAID5=y
 # CONFIG_MD_RAID6 is not set
 # CONFIG_MD_MULTIPATH is not set
 CONFIG_BLK_DEV_DM=y
 # CONFIG_DM_CRYPT is not set
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
 
 #
 # Fusion MPT device support
@@ -332,6 +348,7 @@ CONFIG_IEEE1394_RAWIO=y
 #
 # I2O device support
 #
+# CONFIG_I2O is not set
 
 #
 # Macintosh device drivers
@@ -340,7 +357,6 @@ CONFIG_ADB=y
 CONFIG_ADB_PMU=y
 # CONFIG_PMAC_PBOOK is not set
 # CONFIG_PMAC_BACKLIGHT is not set
-# CONFIG_MAC_SERIAL is not set
 # CONFIG_INPUT_ADBHID is not set
 CONFIG_THERM_PM72=y
 
@@ -369,14 +385,13 @@ CONFIG_SYN_COOKIES=y
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
+CONFIG_INET_TUNNEL=y
 
 #
 # IP: Virtual Server Configuration
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -384,6 +399,8 @@ CONFIG_NETFILTER=y
 # IP: Netfilter Configuration
 #
 CONFIG_IP_NF_CONNTRACK=y
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
 # CONFIG_IP_NF_FTP is not set
 # CONFIG_IP_NF_IRC is not set
 # CONFIG_IP_NF_TFTP is not set
@@ -408,8 +425,15 @@ CONFIG_IP_NF_MATCH_HELPER=y
 CONFIG_IP_NF_MATCH_STATE=y
 CONFIG_IP_NF_MATCH_CONNTRACK=y
 CONFIG_IP_NF_MATCH_OWNER=y
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_REALM is not set
+# CONFIG_IP_NF_MATCH_SCTP is not set
+# CONFIG_IP_NF_MATCH_COMMENT is not set
 CONFIG_IP_NF_FILTER=y
 CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_IP_NF_TARGET_ULOG=y
+CONFIG_IP_NF_TARGET_TCPMSS=y
 CONFIG_IP_NF_NAT=y
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=y
@@ -424,9 +448,7 @@ CONFIG_IP_NF_TARGET_ECN=y
 CONFIG_IP_NF_TARGET_DSCP=y
 CONFIG_IP_NF_TARGET_MARK=y
 CONFIG_IP_NF_TARGET_CLASSIFY=y
-CONFIG_IP_NF_TARGET_LOG=y
-CONFIG_IP_NF_TARGET_ULOG=y
-CONFIG_IP_NF_TARGET_TCPMSS=y
+# CONFIG_IP_NF_RAW is not set
 CONFIG_IP_NF_ARPTABLES=y
 CONFIG_IP_NF_ARPFILTER=y
 CONFIG_IP_NF_ARP_MANGLE=y
@@ -438,7 +460,9 @@ CONFIG_XFRM=y
 #
 # CONFIG_IP_SCTP 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_LLC=y
 # CONFIG_LLC2 is not set
 # CONFIG_IPX is not set
@@ -454,30 +478,33 @@ CONFIG_LLC=y
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
 
 #
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-CONFIG_DUMMY=m
-CONFIG_BONDING=m
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-# CONFIG_MACE is not set
-# CONFIG_BMAC is not set
-# CONFIG_OAKNET is not set
 # CONFIG_HAPPYMEAL is not set
 CONFIG_SUNGEM=y
 # CONFIG_NET_VENDOR_3COM is not set
@@ -509,57 +536,38 @@ CONFIG_TIGON3=m
 #
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_IBMVETH is not set
-CONFIG_PPP=m
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPPOE=m
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
 
 #
 # Token Ring devices
 #
 CONFIG_TR=y
 CONFIG_IBMOL=y
-# CONFIG_IBMLS is not set
 # CONFIG_3C359 is not set
 # CONFIG_TMS380TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
 
 #
-# IrDA (infrared) support
+# Wireless LAN (non-hamradio)
 #
-# CONFIG_IRDA is not set
+# CONFIG_NET_RADIO is not set
 
 #
-# Bluetooth support
+# Wan interfaces
 #
-# CONFIG_BT is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER 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=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
 
 #
 # ISDN subsystem
@@ -598,6 +606,7 @@ CONFIG_SERIO=y
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
 
 #
 # Input Device Drivers
@@ -636,8 +645,6 @@ CONFIG_HW_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
-CONFIG_HVC_CONSOLE=y
-# CONFIG_QIC02_TAPE is not set
 
 #
 # IPMI
@@ -673,6 +680,7 @@ CONFIG_I2C_CHARDEV=y
 #
 CONFIG_I2C_ALGOBIT=y
 # CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
 
 #
 # I2C Hardware Bus support
@@ -697,23 +705,29 @@ CONFIG_I2C_KEYWEST=y
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Hardware Sensors Chip support
 #
 # CONFIG_I2C_SENSOR is not set
 # CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ASB100 is not set
 # CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_IT87 is not set
 # CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
 # CONFIG_SENSORS_LM78 is not set
 # CONFIG_SENSORS_LM80 is not set
 # CONFIG_SENSORS_LM83 is not set
 # CONFIG_SENSORS_LM85 is not set
 # CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
@@ -725,11 +739,17 @@ CONFIG_I2C_KEYWEST=y
 # CONFIG_SENSORS_EEPROM is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
 #
 # Misc devices
 #
@@ -748,6 +768,8 @@ CONFIG_I2C_KEYWEST=y
 # Graphics support
 #
 CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
 CONFIG_FB_OF=y
@@ -755,10 +777,12 @@ CONFIG_FB_OF=y
 # CONFIG_FB_PLATINUM is not set
 # CONFIG_FB_VALKYRIE is not set
 # CONFIG_FB_CT65550 is not set
+# CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_VGA16 is not set
 CONFIG_FB_RIVA=y
+# CONFIG_FB_RIVA_I2C is not set
+# CONFIG_FB_RIVA_DEBUG is not set
 # CONFIG_FB_MATROX is not set
 # CONFIG_FB_RADEON_OLD is not set
 CONFIG_FB_RADEON=y
@@ -778,10 +802,8 @@ CONFIG_FB_RADEON_I2C=y
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
@@ -811,6 +833,7 @@ CONFIG_USB=y
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
 
 #
 # USB Host Controller Drivers
@@ -829,6 +852,7 @@ CONFIG_USB_ACM=m
 CONFIG_USB_PRINTER=y
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT is not set
 CONFIG_USB_STORAGE_DATAFAB=y
 CONFIG_USB_STORAGE_FREECOM=y
 CONFIG_USB_STORAGE_ISD200=y
@@ -853,6 +877,7 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
 # CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
 
@@ -959,6 +984,7 @@ CONFIG_USB_EZUSB=y
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -997,6 +1023,7 @@ 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
@@ -1004,6 +1031,8 @@ CONFIG_UDF_FS=m
 CONFIG_FAT_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
 #
@@ -1016,8 +1045,8 @@ CONFIG_SYSFS=y
 CONFIG_DEVPTS_FS_XATTR=y
 # CONFIG_DEVPTS_FS_SECURITY is not set
 CONFIG_TMPFS=y
-# CONFIG_HUGETLBFS is not set
-# CONFIG_HUGETLB_PAGE is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
 
 #
@@ -1030,7 +1059,7 @@ CONFIG_RAMFS=y
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
+CONFIG_CRAMFS=y
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
@@ -1054,11 +1083,14 @@ CONFIG_EXPORTFS=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
 CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_POSIX is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
 # CONFIG_AFS_FS is not set
 
 #
@@ -1076,7 +1108,6 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
@@ -1110,6 +1141,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
 # CONFIG_NLS_ISO8859_1 is not set
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
@@ -1135,13 +1167,16 @@ CONFIG_OPROFILE=y
 # Kernel hacking
 #
 CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_SLAB is not set
-CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUGGER is not set
 # CONFIG_PPCDBG is not set
-# CONFIG_DEBUG_INFO is not set
+CONFIG_IRQSTACKS=y
+# CONFIG_SCHEDSTATS is not set
 
 #
 # Security options
@@ -1159,6 +1194,7 @@ CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
+# CONFIG_CRYPTO_WP512 is not set
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
@@ -1166,14 +1202,19 @@ CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
+# CONFIG_CRYPTO_TEA is not set
 CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_CRC32C is not set
 CONFIG_CRYPTO_TEST=m
 
 #
 # Library routines
 #
+CONFIG_CRC_CCITT=m
 CONFIG_CRC32=y
-CONFIG_ZLIB_INFLATE=m
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/ppc64/configs/iSeries_defconfig b/arch/ppc64/configs/iSeries_defconfig
index 63ec73f75..84ae55bcc 100644
--- a/arch/ppc64/configs/iSeries_defconfig
+++ b/arch/ppc64/configs/iSeries_defconfig
@@ -16,17 +16,17 @@ CONFIG_FORCE_MAX_ZONEORDER=13
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
 
 #
 # General setup
 #
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
+CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_HOTPLUG=y
 CONFIG_IKCONFIG=y
@@ -34,6 +34,7 @@ CONFIG_IKCONFIG_PROC=y
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_IOSCHED_NOOP=y
@@ -41,6 +42,8 @@ CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -62,10 +65,11 @@ CONFIG_PPC_ISERIES=y
 CONFIG_PPC=y
 CONFIG_PPC64=y
 # CONFIG_POWER4_ONLY is not set
-# CONFIG_IOMMU_VMERGE is not set
+CONFIG_IOMMU_VMERGE=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=32
 # CONFIG_SCHED_SMT is not set
+# CONFIG_PREEMPT is not set
 CONFIG_MSCHUNKS=y
 CONFIG_LPARCFG=y
 
@@ -97,6 +101,8 @@ CONFIG_PCI_NAMES=y
 #
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=m
 # CONFIG_DEBUG_DRIVER is not set
 
@@ -125,7 +131,7 @@ CONFIG_FW_LOADER=m
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 CONFIG_BLK_DEV_NBD=m
-# CONFIG_BLK_DEV_CARMEL is not set
+# CONFIG_BLK_DEV_SX8 is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
@@ -168,22 +174,23 @@ CONFIG_SCSI_FC_ATTRS=y
 # SCSI low-level drivers
 #
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AACRAID is not set
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
+CONFIG_SCSI_IBMVSCSI=m
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -209,11 +216,15 @@ CONFIG_BLK_DEV_MD=y
 CONFIG_MD_LINEAR=y
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
+CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=y
-CONFIG_MD_RAID6=y
-# CONFIG_MD_MULTIPATH is not set
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
 CONFIG_BLK_DEV_DM=y
 CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
 
 #
 # Fusion MPT device support
@@ -259,6 +270,7 @@ CONFIG_SYN_COOKIES=y
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
+CONFIG_INET_TUNNEL=y
 
 #
 # IP: Virtual Server Configuration
@@ -324,7 +336,13 @@ CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_IP_NF_COMPAT_IPCHAINS=m
 CONFIG_IP_NF_COMPAT_IPFWADM=m
-# CONFIG_IP_NF_RAW is not set
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+# CONFIG_IP_NF_CT_ACCT is not set
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_CT_PROTO_SCTP=m
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
 
@@ -351,6 +369,7 @@ CONFIG_LLC=y
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
 
 #
 # Network testing
@@ -379,7 +398,6 @@ CONFIG_TUN=m
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-# CONFIG_OAKNET is not set
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
@@ -408,18 +426,32 @@ CONFIG_E100=y
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
 
 #
-# Gigabit Ethernet (1000/10000 Mbit)
+# Ethernet (1000 Mbit)
 #
-# CONFIG_NET_GIGE is not set
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
 
 #
 # Token Ring devices
 #
 CONFIG_TR=y
 CONFIG_IBMOL=y
-# CONFIG_IBMLS is not set
 # CONFIG_3C359 is not set
 # CONFIG_TMS380TR is not set
 
@@ -508,10 +540,11 @@ CONFIG_SERIO_SERPORT=y
 #
 # Non-8250 serial port support
 #
+CONFIG_SERIAL_CORE=m
+CONFIG_SERIAL_ICOM=m
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
 
 #
 # IPMI
@@ -541,6 +574,11 @@ CONFIG_MAX_RAW_DEVS=256
 #
 # CONFIG_I2C is not set
 
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
 #
 # Misc devices
 #
@@ -592,8 +630,10 @@ CONFIG_FS_MBCACHE=y
 CONFIG_REISERFS_FS=y
 # CONFIG_REISERFS_CHECK is not set
 # CONFIG_REISERFS_PROC_INFO is not set
-# CONFIG_REISERFS_FS_XATTR is not set
-CONFIG_JFS_FS=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_JFS_FS=m
 CONFIG_JFS_POSIX_ACL=y
 # CONFIG_JFS_DEBUG is not set
 # CONFIG_JFS_STATISTICS is not set
@@ -616,6 +656,7 @@ 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
@@ -623,6 +664,8 @@ CONFIG_UDF_FS=m
 CONFIG_FAT_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
 #
@@ -663,19 +706,22 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
 # CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
+CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
 CONFIG_NFSD_V4=y
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
+CONFIG_EXPORTFS=m
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
 CONFIG_RPCSEC_GSS_KRB5=y
+CONFIG_RPCSEC_GSS_SPKM3=m
 # CONFIG_SMB_FS is not set
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -691,7 +737,7 @@ CONFIG_MSDOS_PARTITION=y
 #
 CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
+CONFIG_NLS_CODEPAGE_437=y
 # CONFIG_NLS_CODEPAGE_737 is not set
 # CONFIG_NLS_CODEPAGE_775 is not set
 # CONFIG_NLS_CODEPAGE_850 is not set
@@ -714,7 +760,8 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ISO8859_1 is not set
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
 # CONFIG_NLS_ISO8859_4 is not set
@@ -748,14 +795,16 @@ CONFIG_OPROFILE=y
 # Kernel hacking
 #
 CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
-# CONFIG_DEBUG_SLAB is not set
-CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUGGER is not set
 # CONFIG_PPCDBG is not set
-# CONFIG_DEBUG_INFO is not set
 # CONFIG_IRQSTACKS is not set
+# CONFIG_SCHEDSTATS is not set
 
 #
 # Security options
@@ -773,6 +822,7 @@ CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WHIRLPOOL=m
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
@@ -780,16 +830,19 @@ CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_DEFLATE=m
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
 CONFIG_CRYPTO_TEST=m
 
 #
 # Library routines
 #
+CONFIG_CRC_CCITT=m
 CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
+CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/ppc64/configs/pSeries_defconfig b/arch/ppc64/configs/pSeries_defconfig
index f5503873a..73981148d 100644
--- a/arch/ppc64/configs/pSeries_defconfig
+++ b/arch/ppc64/configs/pSeries_defconfig
@@ -1,5 +1,7 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2
+# Thu Sep 23 16:45:05 2004
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
@@ -16,27 +18,35 @@ CONFIG_FORCE_MAX_ZONEORDER=13
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_HOTPLUG=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_IOSCHED_NOOP=y
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -48,25 +58,31 @@ CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_KMOD is not set
 CONFIG_STOP_MACHINE=y
+CONFIG_SYSVIPC_COMPAT=y
 
 #
 # Platform support
 #
 # CONFIG_PPC_ISERIES is not set
+CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_PPC_PSERIES=y
+# CONFIG_PPC_PMAC is not set
 CONFIG_PPC=y
 CONFIG_PPC64=y
 CONFIG_PPC_OF=y
 CONFIG_ALTIVEC=y
-# CONFIG_PPC_PMAC is not set
+CONFIG_PPC_SPLPAR=y
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_POWER4_ONLY is not set
-# CONFIG_IOMMU_VMERGE is not set
+CONFIG_IOMMU_VMERGE=y
 CONFIG_SMP=y
 CONFIG_IRQ_ALL_CPUS=y
-CONFIG_NR_CPUS=32
+CONFIG_NR_CPUS=128
 # CONFIG_HMT is not set
-# CONFIG_DISCONTIGMEM is not set
+CONFIG_DISCONTIGMEM=y
+CONFIG_NUMA=y
+CONFIG_SCHED_SMT=y
+# CONFIG_PREEMPT is not set
 CONFIG_PPC_RTAS=y
 CONFIG_RTAS_FLASH=m
 CONFIG_SCANLOG=m
@@ -81,6 +97,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
+CONFIG_HOTPLUG_CPU=y
 
 #
 # PCMCIA/CardBus support
@@ -107,7 +124,9 @@ CONFIG_PROC_DEVICETREE=y
 #
 # Generic Driver Options
 #
-CONFIG_FW_LOADER=m
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
 
 #
@@ -127,7 +146,7 @@ CONFIG_FW_LOADER=m
 #
 # Block devices
 #
-CONFIG_BLK_DEV_FD=y
+CONFIG_BLK_DEV_FD=m
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -135,7 +154,8 @@ CONFIG_BLK_DEV_FD=y
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 CONFIG_BLK_DEV_NBD=m
-# CONFIG_BLK_DEV_CARMEL 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_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
@@ -149,9 +169,9 @@ 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_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -173,7 +193,6 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_ADMA=y
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 CONFIG_BLK_DEV_AMD74XX=y
@@ -194,6 +213,7 @@ CONFIG_BLK_DEV_AMD74XX=y
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
 CONFIG_IDEDMA_AUTO=y
@@ -219,7 +239,6 @@ CONFIG_CHR_DEV_SG=y
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_REPORT_LUNS=y
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
 
@@ -233,28 +252,32 @@ CONFIG_SCSI_FC_ATTRS=y
 # SCSI low-level drivers
 #
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AACRAID is not set
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
+CONFIG_SCSI_IBMVSCSI=m
 # CONFIG_SCSI_INIA100 is not set
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+CONFIG_SCSI_IPR=y
+# CONFIG_SCSI_IPR_TRACE is not set
+# CONFIG_SCSI_IPR_DUMP is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -277,11 +300,15 @@ CONFIG_BLK_DEV_MD=y
 CONFIG_MD_LINEAR=y
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
+CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=y
-CONFIG_MD_RAID6=y
-# CONFIG_MD_MULTIPATH is not set
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
 CONFIG_BLK_DEV_DM=y
 CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
 
 #
 # Fusion MPT device support
@@ -296,6 +323,7 @@ CONFIG_DM_CRYPT=m
 #
 # I2O device support
 #
+# CONFIG_I2O is not set
 
 #
 # Macintosh device drivers
@@ -322,19 +350,17 @@ CONFIG_NET_IPIP=y
 # CONFIG_NET_IPGRE is not set
 # CONFIG_IP_MROUTE is not set
 # CONFIG_ARPD is not set
-CONFIG_INET_ECN=y
 CONFIG_SYN_COOKIES=y
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
+CONFIG_INET_TUNNEL=y
 
 #
 # IP: Virtual Server Configuration
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -342,6 +368,8 @@ CONFIG_NETFILTER=y
 # IP: Netfilter Configuration
 #
 CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+CONFIG_IP_NF_CT_PROTO_SCTP=m
 CONFIG_IP_NF_FTP=m
 CONFIG_IP_NF_IRC=m
 CONFIG_IP_NF_TFTP=m
@@ -366,8 +394,14 @@ CONFIG_IP_NF_MATCH_HELPER=m
 CONFIG_IP_NF_MATCH_STATE=m
 CONFIG_IP_NF_MATCH_CONNTRACK=m
 CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
 CONFIG_IP_NF_NAT=m
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -386,9 +420,8 @@ CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_DSCP=m
 CONFIG_IP_NF_TARGET_MARK=m
 CONFIG_IP_NF_TARGET_CLASSIFY=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
@@ -400,10 +433,11 @@ CONFIG_XFRM_USER=m
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP 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_LLC=y
 # CONFIG_LLC2 is not set
 # CONFIG_IPX is not set
@@ -419,28 +453,35 @@ CONFIG_LLC=y
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_RX=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
 
 #
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-CONFIG_DUMMY=m
-CONFIG_BONDING=m
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-# CONFIG_OAKNET is not set
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 CONFIG_NET_VENDOR_3COM=y
@@ -452,6 +493,7 @@ CONFIG_VORTEX=y
 #
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
+CONFIG_IBMVETH=m
 CONFIG_NET_PCI=y
 CONFIG_PCNET32=y
 # CONFIG_AMD8111_ETH is not set
@@ -471,6 +513,7 @@ CONFIG_E100=y
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -484,7 +527,6 @@ CONFIG_E1000=y
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
 # CONFIG_SK98LIN is not set
 CONFIG_TIGON3=y
 
@@ -493,59 +535,40 @@ CONFIG_TIGON3=y
 #
 CONFIG_IXGB=m
 # CONFIG_IXGB_NAPI is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_IBMVETH=m
-CONFIG_PPP=m
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPPOE=m
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
+CONFIG_S2IO=m
+# CONFIG_S2IO_NAPI is not set
 
 #
 # Token Ring devices
 #
 CONFIG_TR=y
 CONFIG_IBMOL=y
-# CONFIG_IBMLS is not set
 # CONFIG_3C359 is not set
 # CONFIG_TMS380TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-CONFIG_NETCONSOLE=y
 
 #
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
+# Wireless LAN (non-hamradio)
 #
-# CONFIG_IRDA is not set
+# CONFIG_NET_RADIO is not set
 
 #
-# Bluetooth support
+# Wan interfaces
 #
-# CONFIG_BT is not set
-CONFIG_NETPOLL=y
-CONFIG_NETPOLL_RX=y
-CONFIG_NETPOLL_TRAP=y
-CONFIG_NET_POLL_CONTROLLER=y
+# 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=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=y
 
 #
 # ISDN subsystem
@@ -584,6 +607,7 @@ CONFIG_SERIO_I8042=y
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
 
 #
 # Input Device Drivers
@@ -591,15 +615,17 @@ CONFIG_SERIO_I8042=y
 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_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 # CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 CONFIG_INPUT_MISC=y
-CONFIG_INPUT_PCSPKR=y
+# CONFIG_INPUT_PCSPKR is not set
 # CONFIG_INPUT_UINPUT is not set
 
 #
@@ -624,16 +650,12 @@ CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_PMACZILOG is not set
+CONFIG_SERIAL_ICOM=m
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
 CONFIG_HVC_CONSOLE=y
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
+CONFIG_HVCS=m
 
 #
 # IPMI
@@ -656,7 +678,7 @@ CONFIG_HVC_CONSOLE=y
 # CONFIG_AGP is not set
 # CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=y
-CONFIG_MAX_RAW_DEVS=256
+CONFIG_MAX_RAW_DEVS=1024
 
 #
 # I2C support
@@ -669,11 +691,13 @@ CONFIG_I2C=y
 #
 CONFIG_I2C_ALGOBIT=y
 # CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
 
 #
 # I2C Hardware Bus support
 #
 # CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
 # CONFIG_I2C_ALI15X3 is not set
 # CONFIG_I2C_AMD756 is not set
 # CONFIG_I2C_AMD8111 is not set
@@ -691,29 +715,51 @@ CONFIG_I2C_ALGOBIT=y
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
 
 #
-# I2C Hardware Sensors Chip support
+# Hardware Sensors Chip support
 #
 # CONFIG_I2C_SENSOR is not set
 # CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_IT87 is not set
 # CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
 # CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
 # CONFIG_SENSORS_LM83 is not set
 # CONFIG_SENSORS_LM85 is not set
 # CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
 #
 # Misc devices
 #
@@ -732,12 +778,14 @@ CONFIG_I2C_ALGOBIT=y
 # Graphics support
 #
 CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
 CONFIG_FB_OF=y
 # CONFIG_FB_CT65550 is not set
+# CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_VGA16 is not set
 # CONFIG_FB_RIVA is not set
 CONFIG_FB_MATROX=y
@@ -765,10 +813,8 @@ CONFIG_FB_RADEON_I2C=y
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
@@ -798,11 +844,14 @@ CONFIG_USB=y
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS 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_OHCI_HCD=y
 # CONFIG_USB_UHCI_HCD is not set
 
@@ -814,6 +863,7 @@ CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_PRINTER is not set
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
@@ -834,7 +884,10 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_WACOM is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
 # CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
 
 #
 # USB Imaging devices
@@ -881,6 +934,8 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -905,7 +960,10 @@ CONFIG_FS_MBCACHE=y
 CONFIG_REISERFS_FS=y
 # CONFIG_REISERFS_CHECK is not set
 # CONFIG_REISERFS_PROC_INFO is not set
-CONFIG_JFS_FS=y
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_JFS_FS=m
 CONFIG_JFS_POSIX_ACL=y
 # CONFIG_JFS_DEBUG is not set
 # CONFIG_JFS_STATISTICS is not set
@@ -928,6 +986,7 @@ 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
@@ -935,6 +994,8 @@ CONFIG_UDF_FS=m
 CONFIG_FAT_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
 #
@@ -942,6 +1003,7 @@ CONFIG_VFAT_FS=y
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
 # CONFIG_DEVFS_FS is not set
 CONFIG_DEVPTS_FS_XATTR=y
 # CONFIG_DEVPTS_FS_SECURITY is not set
@@ -974,18 +1036,22 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
 # CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
+CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
 CONFIG_NFSD_V4=y
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
+CONFIG_EXPORTFS=m
 CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=m
-CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+CONFIG_RPCSEC_GSS_SPKM3=m
 # CONFIG_SMB_FS is not set
 CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1001,7 +1067,7 @@ CONFIG_MSDOS_PARTITION=y
 #
 CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
+CONFIG_NLS_CODEPAGE_437=y
 # CONFIG_NLS_CODEPAGE_737 is not set
 # CONFIG_NLS_CODEPAGE_775 is not set
 # CONFIG_NLS_CODEPAGE_850 is not set
@@ -1024,7 +1090,8 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ISO8859_1 is not set
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
 # CONFIG_NLS_ISO8859_4 is not set
@@ -1049,15 +1116,18 @@ CONFIG_OPROFILE=y
 # Kernel hacking
 #
 CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_INFO is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
-# CONFIG_DEBUG_SLAB is not set
-CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUGGER=y
 CONFIG_XMON=y
 CONFIG_XMON_DEFAULT=y
 # CONFIG_PPCDBG is not set
-# CONFIG_DEBUG_INFO is not set
+CONFIG_IRQSTACKS=y
+# CONFIG_SCHEDSTATS is not set
 
 #
 # Security options
@@ -1071,24 +1141,31 @@ CONFIG_CRYPTO=y
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_WHIRLPOOL=m
+CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
 CONFIG_CRYPTO_TEST=m
 
 #
 # Library routines
 #
+CONFIG_CRC_CCITT=m
 CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/ppc64/kernel/ItLpQueue.c b/arch/ppc64/kernel/ItLpQueue.c
index 6f21bde21..c923a8157 100644
--- a/arch/ppc64/kernel/ItLpQueue.c
+++ b/arch/ppc64/kernel/ItLpQueue.c
@@ -25,7 +25,7 @@ static __inline__ int set_inUse( struct ItLpQueue * lpQueue )
 
 	__asm__ __volatile__("\n\
 1:	lwarx	%0,0,%2		\n\
-	cmpi	0,%0,0		\n\
+	cmpwi	0,%0,0		\n\
 	li	%0,0		\n\
 	bne-	2f		\n\
 	addi	%0,%0,1		\n\
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
index c5dd7e13b..020b64fac 100644
--- a/arch/ppc64/kernel/Makefile
+++ b/arch/ppc64/kernel/Makefile
@@ -3,11 +3,11 @@
 #
 
 EXTRA_CFLAGS	+= -mno-minimal-toc
-extra-y		:= head.o vmlinux.lds.s
+extra-y		:= head.o vmlinux.lds
 
 obj-y               :=	setup.o entry.o traps.o irq.o idle.o dma.o \
 			time.o process.o signal.o syscalls.o misc.o ptrace.o \
-			align.o semaphore.o bitops.o stab.o pacaData.o \
+			align.o semaphore.o bitops.o pacaData.o \
 			udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \
 			ptrace32.o signal32.o rtc.o init_task.o \
 			lmb.o cputable.o cpu_setup_power4.o idle_power4.o \
@@ -17,9 +17,9 @@ obj-$(CONFIG_PPC_OF) +=	of_device.o
 
 pci-obj-$(CONFIG_PPC_ISERIES)	+= iSeries_pci.o iSeries_pci_reset.o \
 				     iSeries_IoMmTable.o
-pci-obj-$(CONFIG_PPC_PSERIES)	+= pci_dn.o pci_dma_direct.o
+pci-obj-$(CONFIG_PPC_MULTIPLATFORM)	+= pci_dn.o pci_dma_direct.o
 
-obj-$(CONFIG_PCI)	+= pci.o pci_iommu.o $(pci-obj-y)
+obj-$(CONFIG_PCI)	+= pci.o pci_iommu.o iomap.o $(pci-obj-y)
 
 obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \
 			     iSeries_VpdInfo.o XmPciLpEvent.o \
@@ -28,10 +28,11 @@ obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \
 			     mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \
 			     iSeries_iommu.o
 
+obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o open_pic.o i8259.o prom_init.o prom.o
+
 obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \
-			     eeh.o nvram.o pSeries_nvram.o rtasd.o ras.o \
-			     open_pic.o xics.o pSeries_htab.o rtas.o \
-			     chrp_setup.o i8259.o prom.o pSeries_iommu.o
+			     eeh.o pSeries_nvram.o rtasd.o ras.o \
+			     xics.o rtas.o pSeries_setup.o pSeries_iommu.o
 
 obj-$(CONFIG_PROC_FS)		+= proc_ppc64.o
 obj-$(CONFIG_RTAS_FLASH)	+= rtas_flash.o
@@ -48,7 +49,7 @@ obj-$(CONFIG_HVCS)		+= hvcserver.o
 obj-$(CONFIG_PPC_PMAC)		+= pmac_setup.o pmac_feature.o pmac_pci.o \
 				   pmac_time.o pmac_nvram.o pmac_low_i2c.o \
 				   open_pic_u3.o
-obj-$(CONFIG_PMAC_DART)		+= pmac_iommu.o
+obj-$(CONFIG_U3_DART)		+= u3_iommu.o
 
 ifdef CONFIG_SMP
 obj-$(CONFIG_PPC_PMAC)		+= pmac_smp.o smp-tbsync.o
diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c
index f19f76379..618592161 100644
--- a/arch/ppc64/kernel/asm-offsets.c
+++ b/arch/ppc64/kernel/asm-offsets.c
@@ -22,18 +22,17 @@
 #include <linux/types.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
+#include <linux/hardirq.h>
 #include <asm/io.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
-#include <asm/hardirq.h>
 
 #include <asm/naca.h>
 #include <asm/paca.h>
 #include <asm/iSeries/ItLpPaca.h>
 #include <asm/iSeries/ItLpQueue.h>
 #include <asm/iSeries/HvLpEvent.h>
-#include <asm/prom.h>
 #include <asm/rtas.h>
 #include <asm/cputable.h>
 
@@ -58,6 +57,7 @@ int main(void)
 	DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0]));
 	DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr));
 	DEFINE(KSP, offsetof(struct thread_struct, ksp));
+	DEFINE(KSP_VSID, offsetof(struct thread_struct, ksp_vsid));
 
 #ifdef CONFIG_ALTIVEC
 	DEFINE(THREAD_VR0, offsetof(struct thread_struct, vr[0]));
@@ -93,16 +93,10 @@ int main(void)
 	DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache));
 	DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr));
 	DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
-	DEFINE(PACASLBR3, offsetof(struct paca_struct, slb_r3));
 #ifdef CONFIG_HUGETLB_PAGE
 	DEFINE(PACAHTLBSEGS, offsetof(struct paca_struct, context.htlb_segs));
 #endif /* CONFIG_HUGETLB_PAGE */
 	DEFINE(PACADEFAULTDECR, offsetof(struct paca_struct, default_decr));
-	DEFINE(PACAPROFENABLED, offsetof(struct paca_struct, prof_enabled));
-	DEFINE(PACAPROFLEN, offsetof(struct paca_struct, prof_len));
-	DEFINE(PACAPROFSHIFT, offsetof(struct paca_struct, prof_shift));
-	DEFINE(PACAPROFBUFFER, offsetof(struct paca_struct, prof_buffer));
-	DEFINE(PACAPROFSTEXT, offsetof(struct paca_struct, prof_stext));
         DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen));
         DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc));
         DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb));
@@ -113,15 +107,10 @@ int main(void)
         DEFINE(LPPACASRR1, offsetof(struct ItLpPaca, xSavedSrr1));
 	DEFINE(LPPACAANYINT, offsetof(struct ItLpPaca, xIntDword.xAnyInt));
 	DEFINE(LPPACADECRINT, offsetof(struct ItLpPaca, xIntDword.xFields.xDecrInt));
-        DEFINE(LPQCUREVENTPTR, offsetof(struct ItLpQueue, xSlicCurEventPtr));
-        DEFINE(LPQOVERFLOW, offsetof(struct ItLpQueue, xPlicOverflowIntPending));
-        DEFINE(LPEVENTFLAGS, offsetof(struct HvLpEvent, xFlags));
-	DEFINE(PROMENTRY, offsetof(struct prom_t, entry));
 
 	/* RTAS */
 	DEFINE(RTASBASE, offsetof(struct rtas_t, base));
 	DEFINE(RTASENTRY, offsetof(struct rtas_t, entry));
-	DEFINE(RTASSIZE, offsetof(struct rtas_t, size));
 
 	/* Interrupt register frame */
 	DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
@@ -148,10 +137,6 @@ int main(void)
 	DEFINE(GPR11, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[11]));
 	DEFINE(GPR12, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[12]));
 	DEFINE(GPR13, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[13]));
-	DEFINE(GPR20, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[20]));
-	DEFINE(GPR21, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[21]));
-	DEFINE(GPR22, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[22]));
-	DEFINE(GPR23, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[23]));
 	/*
 	 * Note: these symbols include _ because they overlap with special
 	 * register names
diff --git a/arch/ppc64/kernel/btext.c b/arch/ppc64/kernel/btext.c
index 33e10865d..c53f079e9 100644
--- a/arch/ppc64/kernel/btext.c
+++ b/arch/ppc64/kernel/btext.c
@@ -10,7 +10,7 @@
 #include <linux/version.h>
 
 #include <asm/sections.h>
-#include <asm/bootx.h>
+#include <asm/prom.h>
 #include <asm/btext.h>
 #include <asm/prom.h>
 #include <asm/page.h>
@@ -36,6 +36,11 @@ static int g_loc_Y;
 static int g_max_loc_X;
 static int g_max_loc_Y;
 
+static int dispDeviceRowBytes;
+static int dispDeviceDepth;
+static int dispDeviceRect[4];
+static unsigned char *dispDeviceBase, *logicalDisplayBase;
+
 unsigned long disp_BAT[2] __initdata = {0, 0};
 
 #define cmapsz	(16*256)
@@ -45,30 +50,6 @@ static unsigned char vga_font[cmapsz];
 int boot_text_mapped;
 int force_printk_to_btext = 0;
 
-boot_infos_t disp_bi;
-
-/* This function will enable the early boot text when doing OF booting. This
- * way, xmon output should work too
- */
-void __init btext_setup_display(int width, int height, int depth, int pitch,
-		    unsigned long address)
-{
-	unsigned long offset = reloc_offset();
-	boot_infos_t* bi = PTRRELOC(&disp_bi);
-
-	RELOC(g_loc_X) = 0;
-	RELOC(g_loc_Y) = 0;
-	RELOC(g_max_loc_X) = width / 8;
-	RELOC(g_max_loc_Y) = height / 16;
-	bi->logicalDisplayBase = (unsigned char *)address;
-	bi->dispDeviceBase = (unsigned char *)address;
-	bi->dispDeviceRowBytes = pitch;
-	bi->dispDeviceDepth = depth;
-	bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0;
-	bi->dispDeviceRect[2] = width;
-	bi->dispDeviceRect[3] = height;
-	RELOC(boot_text_mapped) = 1;
-}
 
 /* Here's a small text engine to use during early boot
  * or for debugging purposes
@@ -84,34 +65,84 @@ void __init btext_setup_display(int width, int height, int depth, int pitch,
 void map_boot_text(void)
 {
 	unsigned long base, offset, size;
-	boot_infos_t *bi = &disp_bi;
 	unsigned char *vbase;
 
 	/* By default, we are no longer mapped */
 	boot_text_mapped = 0;
-	if (bi->dispDeviceBase == 0)
+	if (dispDeviceBase == 0)
 		return;
-	base = ((unsigned long) bi->dispDeviceBase) & 0xFFFFF000UL;
-	offset = ((unsigned long) bi->dispDeviceBase) - base;
-	size = bi->dispDeviceRowBytes * bi->dispDeviceRect[3] + offset
-		+ bi->dispDeviceRect[0];
+	base = ((unsigned long) dispDeviceBase) & 0xFFFFF000UL;
+	offset = ((unsigned long) dispDeviceBase) - base;
+	size = dispDeviceRowBytes * dispDeviceRect[3] + offset
+		+ dispDeviceRect[0];
 	vbase = __ioremap(base, size, _PAGE_NO_CACHE);
 	if (vbase == 0)
 		return;
-	bi->logicalDisplayBase = vbase + offset;
+	logicalDisplayBase = vbase + offset;
 	boot_text_mapped = 1;
 }
 
+int btext_initialize(struct device_node *np)
+{
+	unsigned int width, height, depth, pitch;
+	unsigned long address = 0;
+	u32 *prop;
+
+	prop = (u32 *)get_property(np, "width", NULL);
+	if (prop == NULL)
+		return -EINVAL;
+	width = *prop;
+	prop = (u32 *)get_property(np, "height", NULL);
+	if (prop == NULL)
+		return -EINVAL;
+	height = *prop;
+	prop = (u32 *)get_property(np, "depth", NULL);
+	if (prop == NULL)
+		return -EINVAL;
+	depth = *prop;
+	pitch = width * ((depth + 7) / 8);
+	prop = (u32 *)get_property(np, "linebytes", NULL);
+	if (prop)
+		pitch = *prop;
+	if (pitch == 1)
+		pitch = 0x1000;
+	prop = (u32 *)get_property(np, "address", NULL);
+	if (prop)
+		address = *prop;
+
+	/* FIXME: Add support for PCI reg properties */
+
+	if (address == 0)
+		return -EINVAL;
+
+	g_loc_X = 0;
+	g_loc_Y = 0;
+	g_max_loc_X = width / 8;
+	g_max_loc_Y = height / 16;
+	logicalDisplayBase = (unsigned char *)address;
+	dispDeviceBase = (unsigned char *)address;
+	dispDeviceRowBytes = pitch;
+	dispDeviceDepth = depth;
+	dispDeviceRect[0] = dispDeviceRect[1] = 0;
+	dispDeviceRect[2] = width;
+	dispDeviceRect[3] = height;
+
+	map_boot_text();
+
+	return 0;
+}
+
+
 /* Calc the base address of a given point (x,y) */
-static unsigned char * calc_base(boot_infos_t *bi, int x, int y)
+static unsigned char * calc_base(int x, int y)
 {
 	unsigned char *base;
 
-	base = bi->logicalDisplayBase;
+	base = logicalDisplayBase;
 	if (base == 0)
-		base = bi->dispDeviceBase;
-	base += (x + bi->dispDeviceRect[0]) * (bi->dispDeviceDepth >> 3);
-	base += (y + bi->dispDeviceRect[1]) * bi->dispDeviceRowBytes;
+		base = dispDeviceBase;
+	base += (x + dispDeviceRect[0]) * (dispDeviceDepth >> 3);
+	base += (y + dispDeviceRect[1]) * dispDeviceRowBytes;
 	return base;
 }
 
@@ -119,24 +150,22 @@ static unsigned char * calc_base(boot_infos_t *bi, int x, int y)
 void btext_update_display(unsigned long phys, int width, int height,
 			  int depth, int pitch)
 {
-	boot_infos_t *bi = &disp_bi;
-
-	if (bi->dispDeviceBase == 0)
+	if (dispDeviceBase == 0)
 		return;
 
 	/* check it's the same frame buffer (within 256MB) */
-	if ((phys ^ (unsigned long)bi->dispDeviceBase) & 0xf0000000)
+	if ((phys ^ (unsigned long)dispDeviceBase) & 0xf0000000)
 		return;
 
-	bi->dispDeviceBase = (__u8 *) phys;
-	bi->dispDeviceRect[0] = 0;
-	bi->dispDeviceRect[1] = 0;
-	bi->dispDeviceRect[2] = width;
-	bi->dispDeviceRect[3] = height;
-	bi->dispDeviceDepth = depth;
-	bi->dispDeviceRowBytes = pitch;
+	dispDeviceBase = (__u8 *) phys;
+	dispDeviceRect[0] = 0;
+	dispDeviceRect[1] = 0;
+	dispDeviceRect[2] = width;
+	dispDeviceRect[3] = height;
+	dispDeviceDepth = depth;
+	dispDeviceRowBytes = pitch;
 	if (boot_text_mapped) {
-		iounmap(bi->logicalDisplayBase);
+		iounmap(logicalDisplayBase);
 		boot_text_mapped = 0;
 	}
 	map_boot_text();
@@ -148,108 +177,101 @@ void btext_update_display(unsigned long phys, int width, int height,
 
 void btext_clearscreen(void)
 {
-	unsigned long offset = reloc_offset();
-	boot_infos_t* bi	= PTRRELOC(&disp_bi);
-	unsigned long *base	= (unsigned long *)calc_base(bi, 0, 0);
-	unsigned long width 	= ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
-					(bi->dispDeviceDepth >> 3)) >> 3;
+	unsigned long *base	= (unsigned long *)calc_base(0, 0);
+	unsigned long width 	= ((dispDeviceRect[2] - dispDeviceRect[0]) *
+					(dispDeviceDepth >> 3)) >> 3;
 	int i,j;
 
-	for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++)
+	for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++)
 	{
 		unsigned long *ptr = base;
 		for(j=width; j; --j)
 			*(ptr++) = 0;
-		base += (bi->dispDeviceRowBytes >> 3);
+		base += (dispDeviceRowBytes >> 3);
 	}
 }
 
 #ifndef NO_SCROLL
 static void scrollscreen(void)
 {
-	unsigned long offset   	= reloc_offset();
-	boot_infos_t* bi       	= PTRRELOC(&disp_bi);
-	unsigned long *src     	= (unsigned long *)calc_base(bi,0,16);
-	unsigned long *dst     	= (unsigned long *)calc_base(bi,0,0);
-	unsigned long width    	= ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
-				   (bi->dispDeviceDepth >> 3)) >> 3;
+	unsigned long *src     	= (unsigned long *)calc_base(0,16);
+	unsigned long *dst     	= (unsigned long *)calc_base(0,0);
+	unsigned long width    	= ((dispDeviceRect[2] - dispDeviceRect[0]) *
+				   (dispDeviceDepth >> 3)) >> 3;
 	int i,j;
 
-	for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1] - 16); i++)
+	for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++)
 	{
 		unsigned long *src_ptr = src;
 		unsigned long *dst_ptr = dst;
 		for(j=width; j; --j)
 			*(dst_ptr++) = *(src_ptr++);
-		src += (bi->dispDeviceRowBytes >> 3);
-		dst += (bi->dispDeviceRowBytes >> 3);
+		src += (dispDeviceRowBytes >> 3);
+		dst += (dispDeviceRowBytes >> 3);
 	}
 	for (i=0; i<16; i++)
 	{
 		unsigned long *dst_ptr = dst;
 		for(j=width; j; --j)
 			*(dst_ptr++) = 0;
-		dst += (bi->dispDeviceRowBytes >> 3);
+		dst += (dispDeviceRowBytes >> 3);
 	}
 }
 #endif /* ndef NO_SCROLL */
 
 void btext_drawchar(char c)
 {
-	unsigned long offset = reloc_offset();
 	int cline = 0;
 #ifdef NO_SCROLL
 	int x;
 #endif
-	if (!RELOC(boot_text_mapped))
+	if (!boot_text_mapped)
 		return;
 
 	switch (c) {
 	case '\b':
-		if (RELOC(g_loc_X) > 0)
-			--RELOC(g_loc_X);
+		if (g_loc_X > 0)
+			--g_loc_X;
 		break;
 	case '\t':
-		RELOC(g_loc_X) = (RELOC(g_loc_X) & -8) + 8;
+		g_loc_X = (g_loc_X & -8) + 8;
 		break;
 	case '\r':
-		RELOC(g_loc_X) = 0;
+		g_loc_X = 0;
 		break;
 	case '\n':
-		RELOC(g_loc_X) = 0;
-		RELOC(g_loc_Y)++;
+		g_loc_X = 0;
+		g_loc_Y++;
 		cline = 1;
 		break;
 	default:
-		draw_byte(c, RELOC(g_loc_X)++, RELOC(g_loc_Y));
+		draw_byte(c, g_loc_X++, g_loc_Y);
 	}
-	if (RELOC(g_loc_X) >= RELOC(g_max_loc_X)) {
-		RELOC(g_loc_X) = 0;
-		RELOC(g_loc_Y)++;
+	if (g_loc_X >= g_max_loc_X) {
+		g_loc_X = 0;
+		g_loc_Y++;
 		cline = 1;
 	}
 #ifndef NO_SCROLL
-	while (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) {
+	while (g_loc_Y >= g_max_loc_Y) {
 		scrollscreen();
-		RELOC(g_loc_Y)--;
+		g_loc_Y--;
 	}
 #else
 	/* wrap around from bottom to top of screen so we don't
 	   waste time scrolling each line.  -- paulus. */
-	if (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y))
-		RELOC(g_loc_Y) = 0;
+	if (g_loc_Y >= g_max_loc_Y)
+		g_loc_Y = 0;
 	if (cline) {
-		for (x = 0; x < RELOC(g_max_loc_X); ++x)
-			draw_byte(' ', x, RELOC(g_loc_Y));
+		for (x = 0; x < g_max_loc_X; ++x)
+			draw_byte(' ', x, g_loc_Y);
 	}
 #endif
 }
 
 void btext_drawstring(const char *c)
 {
-	unsigned long offset = reloc_offset();
-
-	if (!RELOC(boot_text_mapped))
+	if (!boot_text_mapped)
 		return;
 	while (*c)
 		btext_drawchar(*c++);
@@ -257,10 +279,9 @@ void btext_drawstring(const char *c)
 
 void btext_drawhex(unsigned long v)
 {
-	unsigned long offset = reloc_offset();
-	char *hex_table = RELOC("0123456789abcdef");
+	char *hex_table = "0123456789abcdef";
 
-	if (!RELOC(boot_text_mapped))
+	if (!boot_text_mapped)
 		return;
 	btext_drawchar(hex_table[(v >> 60) & 0x0000000FUL]);
 	btext_drawchar(hex_table[(v >> 56) & 0x0000000FUL]);
@@ -283,14 +304,11 @@ void btext_drawhex(unsigned long v)
 
 static void draw_byte(unsigned char c, long locX, long locY)
 {
-	unsigned long offset	= reloc_offset();
-	boot_infos_t* bi       	= PTRRELOC(&disp_bi);
-	unsigned char *base	= calc_base(bi, locX << 3, locY << 4);
-	unsigned char *font	= PTRRELOC(&vga_font[((unsigned int)c) * 16]);
-	int rb			= bi->dispDeviceRowBytes;
-
-#if 0
-	switch(bi->dispDeviceDepth) {
+	unsigned char *base	= calc_base(locX << 3, locY << 4);
+	unsigned char *font	= &vga_font[((unsigned int)c) * 16];
+	int rb			= dispDeviceRowBytes;
+
+	switch(dispDeviceDepth) {
 	case 24:
 	case 32:
 		draw_byte_32(font, (unsigned int *)base, rb);
@@ -303,17 +321,6 @@ static void draw_byte(unsigned char c, long locX, long locY)
 		draw_byte_8(font, (unsigned int *)base, rb);
 		break;
 	}
-#else
-	if(bi->dispDeviceDepth == 24 ||
-	   bi->dispDeviceDepth == 32) {
-		draw_byte_32(font, (unsigned int *)base, rb);
-	} else if(bi->dispDeviceDepth == 15 ||
-	   bi->dispDeviceDepth == 16) {
-		draw_byte_16(font, (unsigned int *)base, rb);
-	} else if(bi->dispDeviceDepth == 8) {
-		draw_byte_8(font, (unsigned int *)base, rb);
-	} 
-#endif
 }
 
 static unsigned int expand_bits_8[16] = {
@@ -369,8 +376,7 @@ static void draw_byte_16(unsigned char *font, unsigned int *base, int rb)
 	int l, bits;
 	int fg = 0xFFFFFFFFUL;
 	int bg = 0x00000000UL;
-	unsigned long offset = reloc_offset();
-	unsigned int *eb = PTRRELOC((int *)expand_bits_16);
+	unsigned int *eb = (int *)expand_bits_16;
 
 	for (l = 0; l < 16; ++l)
 	{
@@ -388,8 +394,7 @@ static void draw_byte_8(unsigned char *font, unsigned int *base, int rb)
 	int l, bits;
 	int fg = 0x0F0F0F0FUL;
 	int bg = 0x00000000UL;
-	unsigned long offset = reloc_offset();
-	unsigned int *eb = PTRRELOC((int *)expand_bits_8);
+	unsigned int *eb = (int *)expand_bits_8;
 
 	for (l = 0; l < 16; ++l)
 	{
diff --git a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c
index 5fdcce2db..6e87e5631 100644
--- a/arch/ppc64/kernel/eeh.c
+++ b/arch/ppc64/kernel/eeh.c
@@ -48,9 +48,6 @@ static int ibm_read_slot_reset_state;
 static int ibm_slot_error_detail;
 
 static int eeh_subsystem_enabled;
-#define EEH_MAX_OPTS 4096
-static char *eeh_opts;
-static int eeh_opts_last;
 
 /* Buffer for reporting slot-error-detail rtas calls */
 static unsigned char slot_errbuf[RTAS_ERROR_LOG_MAX];
@@ -62,10 +59,6 @@ static DEFINE_PER_CPU(unsigned long, total_mmio_ffs);
 static DEFINE_PER_CPU(unsigned long, false_positives);
 static DEFINE_PER_CPU(unsigned long, ignored_failures);
 
-static int eeh_check_opts_config(struct device_node *dn, int class_code,
-				 int vendor_id, int device_id,
-				 int default_state);
-
 /**
  * The pci address cache subsystem.  This subsystem places
  * PCI device address resources into a red-black tree, sorted
@@ -209,6 +202,7 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev)
 {
 	struct device_node *dn;
 	int i;
+	int inserted = 0;
 
 	dn = pci_device_to_OF_node(dev);
 	if (!dn) {
@@ -242,7 +236,12 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev)
 		if (start == 0 || ~start == 0 || end == 0 || ~end == 0)
 			 continue;
 		pci_addr_cache_insert(dev, start, end, flags);
+		inserted = 1;
 	}
+
+	/* If there was nothing to add, the cache has no reference... */
+	if (!inserted)
+		pci_dev_put(dev);
 }
 
 /**
@@ -265,6 +264,7 @@ void pci_addr_cache_insert_device(struct pci_dev *dev)
 static inline void __pci_addr_cache_remove_device(struct pci_dev *dev)
 {
 	struct rb_node *n;
+	int removed = 0;
 
 restart:
 	n = rb_first(&pci_io_addr_cache_root.rb_root);
@@ -274,6 +274,7 @@ restart:
 
 		if (piar->pcidev == dev) {
 			rb_erase(n, &pci_io_addr_cache_root.rb_root);
+			removed = 1;
 			kfree(piar);
 			goto restart;
 		}
@@ -281,7 +282,8 @@ restart:
 	}
 
 	/* The cache no longer holds its reference to this device... */
-	pci_dev_put(dev);
+	if (removed)
+		pci_dev_put(dev);
 }
 
 /**
@@ -333,47 +335,38 @@ void __init pci_addr_cache_build(void)
 
 /**
  * eeh_token_to_phys - convert EEH address token to phys address
- * @token i/o token, should be address in the form 0xA....
- *
- * Converts EEH address tokens into physical addresses.  Note that
- * ths routine does *not* convert I/O BAR addresses (which start
- * with 0xE...) to phys addresses!
+ * @token i/o token, should be address in the form 0xE....
  */
-static unsigned long eeh_token_to_phys(unsigned long token)
+static inline unsigned long eeh_token_to_phys(unsigned long token)
 {
 	pte_t *ptep;
-	unsigned long pa, vaddr;
+	unsigned long pa;
 
-	if (REGION_ID(token) == EEH_REGION_ID)
-		vaddr = IO_TOKEN_TO_ADDR(token);
-	else
+	ptep = find_linux_pte(ioremap_mm.pgd, token);
+	if (!ptep)
 		return token;
-
-	ptep = find_linux_pte(ioremap_mm.pgd, vaddr);
 	pa = pte_pfn(*ptep) << PAGE_SHIFT;
 
-	return pa | (vaddr & (PAGE_SIZE-1));
+	return pa | (token & (PAGE_SIZE-1));
 }
 
 /**
- * eeh_check_failure - check if all 1's data is due to EEH slot freeze
- * @token i/o token, should be address in the form 0xA....
- * @val value, should be all 1's (XXX why do we need this arg??)
+ * eeh_dn_check_failure - check if all 1's data is due to EEH slot freeze
+ * @dn device node
+ * @dev pci device, if known
  *
- * Check for an eeh failure at the given token address.
- * The given value has been read and it should be 1's (0xff, 0xffff or
- * 0xffffffff).
+ * Check for an EEH failure for the given device node.  Call this
+ * routine if the result of a read was all 0xff's and you want to
+ * find out if this is due to an EEH slot freeze event.  This routine
+ * will query firmware for the EEH status.
  *
- * Probe to determine if an error actually occurred.  If not return val.
- * Otherwise panic.
+ * Returns 0 if there has not been an EEH error; otherwise returns
+ * an error code.
  *
- * Note this routine might be called in an interrupt context ...
+ * It is safe to call this routine in an interrupt context.
  */
-unsigned long eeh_check_failure(void *token, unsigned long val)
+int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
 {
-	unsigned long addr;
-	struct pci_dev *dev;
-	struct device_node *dn;
 	int ret;
 	int rets[2];
 	unsigned long flags;
@@ -381,30 +374,19 @@ unsigned long eeh_check_failure(void *token, unsigned long val)
 	__get_cpu_var(total_mmio_ffs)++;
 
 	if (!eeh_subsystem_enabled)
-		return val;
+		return 0;
 
-	/* Finding the phys addr + pci device; this is pretty quick. */
-	addr = eeh_token_to_phys((unsigned long)token);
-	dev = pci_get_device_by_addr(addr);
-	if (!dev)
-		return val;
-
-	dn = pci_device_to_OF_node(dev);
-	if (!dn) {
-		pci_dev_put(dev);
-		return val;
-	}
+	if (!dn)
+		return 0;
 
 	/* Access to IO BARs might get this far and still not want checking. */
 	if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) ||
 	    dn->eeh_mode & EEH_MODE_NOCHECK) {
-		pci_dev_put(dev);
-		return val;
+		return 0;
 	}
 
 	if (!dn->eeh_config_addr) {
-		pci_dev_put(dev);
-		return val;
+		return 0;
 	}
 
 	/*
@@ -418,7 +400,7 @@ unsigned long eeh_check_failure(void *token, unsigned long val)
 			dn->eeh_config_addr, BUID_HI(dn->phb->buid),
 			BUID_LO(dn->phb->buid));
 
-	if (ret == 0 && rets[1] == 1 && rets[0] >= 2) {
+	if (ret == 0 && rets[1] == 1 && (rets[0] == 2 || rets[0] == 4)) {
 		int log_event;
 
 		spin_lock_irqsave(&slot_errbuf_lock, flags);
@@ -430,7 +412,7 @@ unsigned long eeh_check_failure(void *token, unsigned long val)
 		                      BUID_LO(dn->phb->buid), NULL, 0,
 		                      virt_to_phys(slot_errbuf),
 		                      eeh_error_buf_size,
-		                      2 /* Permanent Error */);
+		                      1 /* Temporary Error */);
 
 		if (log_event == 0)
 			log_error(slot_errbuf, ERR_TYPE_RTAS_LOG,
@@ -438,6 +420,10 @@ unsigned long eeh_check_failure(void *token, unsigned long val)
 
 		spin_unlock_irqrestore(&slot_errbuf_lock, flags);
 
+		printk(KERN_INFO "EEH: MMIO failure (%d) on device: %s %s\n",
+		       rets[0], dn->name, dn->full_name);
+		WARN_ON(1);
+
 		/*
 		 * XXX We should create a separate sysctl for this.
 		 *
@@ -446,26 +432,57 @@ unsigned long eeh_check_failure(void *token, unsigned long val)
 		 * can use it here.
 		 */
 		if (panic_on_oops) {
-			panic("EEH: MMIO failure (%d) on device:%s %s\n",
-			      rets[0], pci_name(dev), pci_pretty_name(dev));
+			panic("EEH: MMIO failure (%d) on device: %s %s\n",
+			      rets[0], dn->name, dn->full_name);
 		} else {
 			__get_cpu_var(ignored_failures)++;
-			printk(KERN_INFO "EEH: MMIO failure (%d) on device:%s %s\n",
-			       rets[0], pci_name(dev), pci_pretty_name(dev));
 		}
 	} else {
 		__get_cpu_var(false_positives)++;
 	}
 
+	return 0;
+}
+
+EXPORT_SYMBOL(eeh_dn_check_failure);
+
+/**
+ * eeh_check_failure - check if all 1's data is due to EEH slot freeze
+ * @token i/o token, should be address in the form 0xA....
+ * @val value, should be all 1's (XXX why do we need this arg??)
+ *
+ * Check for an eeh failure at the given token address.
+ * Check for an EEH failure at the given token address.  Call this
+ * routine if the result of a read was all 0xff's and you want to
+ * find out if this is due to an EEH slot freeze event.  This routine
+ * will query firmware for the EEH status.
+ *
+ * Note this routine is safe to call in an interrupt context.
+ */
+unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val)
+{
+	unsigned long addr;
+	struct pci_dev *dev;
+	struct device_node *dn;
+
+	/* Finding the phys addr + pci device; this is pretty quick. */
+	addr = eeh_token_to_phys((unsigned long __force) token);
+	dev = pci_get_device_by_addr(addr);
+	if (!dev)
+		return val;
+
+	dn = pci_device_to_OF_node(dev);
+	eeh_dn_check_failure (dn, dev);
+
 	pci_dev_put(dev);
 	return val;
 }
+
 EXPORT_SYMBOL(eeh_check_failure);
 
 struct eeh_early_enable_info {
 	unsigned int buid_hi;
 	unsigned int buid_lo;
-	int force_off;
 };
 
 /* Enable eeh for the given device node. */
@@ -507,18 +524,8 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
 	if ((*class_code >> 16) == PCI_BASE_CLASS_DISPLAY)
 		enable = 0;
 
-	if (!eeh_check_opts_config(dn, *class_code, *vendor_id, *device_id,
-				   enable)) {
-		if (enable) {
-			printk(KERN_WARNING "EEH: %s user requested to run "
-			       "without EEH checking.\n", dn->full_name);
-			enable = 0;
-		}
-	}
-
-	if (!enable || info->force_off) {
+	if (!enable)
 		dn->eeh_mode |= EEH_MODE_NOCHECK;
-	}
 
 	/* Ok... see if this device supports EEH.  Some do, some don't,
 	 * and the only way to find out is to check each and every one. */
@@ -572,15 +579,12 @@ void __init eeh_init(void)
 {
 	struct device_node *phb, *np;
 	struct eeh_early_enable_info info;
-	char *eeh_force_off = strstr(saved_command_line, "eeh-force-off");
 
 	init_pci_config_tokens();
 
 	np = of_find_node_by_path("/rtas");
-	if (np == NULL) {
-		printk(KERN_WARNING "EEH: RTAS not found !\n");
+	if (np == NULL)
 		return;
-	}
 
 	ibm_set_eeh_option = rtas_token("ibm,set-eeh-option");
 	ibm_set_slot_reset = rtas_token("ibm,set-slot-reset");
@@ -600,13 +604,6 @@ void __init eeh_init(void)
 		eeh_error_buf_size = RTAS_ERROR_LOG_MAX;
 	}
 
-	info.force_off = 0;
-	if (eeh_force_off) {
-		printk(KERN_WARNING "EEH: WARNING: PCI Enhanced I/O Error "
-		       "Handling is user disabled\n");
-		info.force_off = 1;
-	}
-
 	/* Enable EEH for all adapters.  Note that eeh requires buid's */
 	for (phb = of_find_node_by_name(NULL, "pci"); phb;
 	     phb = of_find_node_by_name(phb, "pci")) {
@@ -621,11 +618,10 @@ void __init eeh_init(void)
 		traverse_pci_devices(phb, early_enable_eeh, &info);
 	}
 
-	if (eeh_subsystem_enabled) {
+	if (eeh_subsystem_enabled)
 		printk(KERN_INFO "EEH: PCI Enhanced I/O Error Handling Enabled\n");
-	} else {
-		printk(KERN_WARNING "EEH: disabled PCI Enhanced I/O Error Handling\n");
-	}
+	else
+		printk(KERN_WARNING "EEH: No capable adapters found\n");
 }
 
 /**
@@ -701,39 +697,6 @@ void eeh_remove_device(struct pci_dev *dev)
 }
 EXPORT_SYMBOL(eeh_remove_device);
 
-/*
- * If EEH is implemented, find the PCI device using given phys addr
- * and check to see if eeh failure checking is disabled.
- * Remap the addr (trivially) to the EEH region if EEH checking enabled.
- * For addresses not known to PCI the vaddr is simply returned unchanged.
- */
-void *eeh_ioremap(unsigned long addr, void *vaddr)
-{
-	struct pci_dev *dev;
-	struct device_node *dn;
-
-	if (!eeh_subsystem_enabled)
-		return vaddr;
-
-	dev = pci_get_device_by_addr(addr);
-	if (!dev)
-		return vaddr;
-
-	dn = pci_device_to_OF_node(dev);
-	if (!dn) {
-		pci_dev_put(dev);
-		return vaddr;
-	}
-
-	if (dn->eeh_mode & EEH_MODE_NOCHECK) {
-		pci_dev_put(dev);
-		return vaddr;
-	}
-
-	pci_dev_put(dev);
-	return (void *)IO_ADDR_TO_TOKEN(vaddr);
-}
-
 static int proc_eeh_show(struct seq_file *m, void *v)
 {
 	unsigned int cpu;
@@ -784,129 +747,3 @@ static int __init eeh_init_proc(void)
 	return 0;
 }
 __initcall(eeh_init_proc);
-
-/*
- * Test if "dev" should be configured on or off.
- * This processes the options literally from left to right.
- * This lets the user specify stupid combinations of options,
- * but at least the result should be very predictable.
- */
-static int eeh_check_opts_config(struct device_node *dn,
-				 int class_code, int vendor_id, int device_id,
-				 int default_state)
-{
-	char devname[32], classname[32];
-	char *strs[8], *s;
-	int nstrs, i;
-	int ret = default_state;
-
-	/* Build list of strings to match */
-	nstrs = 0;
-	s = (char *)get_property(dn, "ibm,loc-code", NULL);
-	if (s)
-		strs[nstrs++] = s;
-	sprintf(devname, "dev%04x:%04x", vendor_id, device_id);
-	strs[nstrs++] = devname;
-	sprintf(classname, "class%04x", class_code);
-	strs[nstrs++] = classname;
-	strs[nstrs++] = "";	/* yes, this matches the empty string */
-
-	/*
-	 * Now see if any string matches the eeh_opts list.
-	 * The eeh_opts list entries start with + or -.
-	 */
-	for (s = eeh_opts; s && (s < (eeh_opts + eeh_opts_last));
-	     s += strlen(s)+1) {
-		for (i = 0; i < nstrs; i++) {
-			if (strcasecmp(strs[i], s+1) == 0) {
-				ret = (strs[i][0] == '+') ? 1 : 0;
-			}
-		}
-	}
-	return ret;
-}
-
-/*
- * Handle kernel eeh-on & eeh-off cmd line options for eeh.
- *
- * We support:
- *	eeh-off=loc1,loc2,loc3...
- *
- * and this option can be repeated so
- *      eeh-off=loc1,loc2 eeh-off=loc3
- * is the same as eeh-off=loc1,loc2,loc3
- *
- * loc is an IBM location code that can be found in a manual or
- * via openfirmware (or the Hardware Management Console).
- *
- * We also support these additional "loc" values:
- *
- *	dev#:#    vendor:device id in hex (e.g. dev1022:2000)
- *	class#    class id in hex (e.g. class0200)
- *
- * If no location code is specified all devices are assumed
- * so eeh-off means eeh by default is off.
- */
-
-/*
- * This is implemented as a null separated list of strings.
- * Each string looks like this:  "+X" or "-X"
- * where X is a loc code, vendor:device, class (as shown above)
- * or empty which is used to indicate all.
- *
- * We interpret this option string list so that it will literally
- * behave left-to-right even if some combinations don't make sense.
- */
-static int __init eeh_parm(char *str, int state)
-{
-	char *s, *cur, *curend;
-
-	if (!eeh_opts) {
-		eeh_opts = alloc_bootmem(EEH_MAX_OPTS);
-		eeh_opts[eeh_opts_last++] = '+'; /* default */
-		eeh_opts[eeh_opts_last++] = '\0';
-	}
-	if (*str == '\0') {
-		eeh_opts[eeh_opts_last++] = state ? '+' : '-';
-		eeh_opts[eeh_opts_last++] = '\0';
-		return 1;
-	}
-	if (*str == '=')
-		str++;
-	for (s = str; s && *s != '\0'; s = curend) {
-		cur = s;
-		/* ignore empties.  Don't treat as "all-on" or "all-off" */
-		while (*cur == ',')
-			cur++;
-		curend = strchr(cur, ',');
-		if (!curend)
-			curend = cur + strlen(cur);
-		if (*cur) {
-			int curlen = curend-cur;
-			if (eeh_opts_last + curlen > EEH_MAX_OPTS-2) {
-				printk(KERN_WARNING "EEH: sorry...too many "
-				       "eeh cmd line options\n");
-				return 1;
-			}
-			eeh_opts[eeh_opts_last++] = state ? '+' : '-';
-			strncpy(eeh_opts+eeh_opts_last, cur, curlen);
-			eeh_opts_last += curlen;
-			eeh_opts[eeh_opts_last++] = '\0';
-		}
-	}
-
-	return 1;
-}
-
-static int __init eehoff_parm(char *str)
-{
-	return eeh_parm(str, 0);
-}
-
-static int __init eehon_parm(char *str)
-{
-	return eeh_parm(str, 1);
-}
-
-__setup("eeh-off", eehoff_parm);
-__setup("eeh-on", eehon_parm);
diff --git a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S
index 2d48d24e7..f0a12eaa3 100644
--- a/arch/ppc64/kernel/entry.S
+++ b/arch/ppc64/kernel/entry.S
@@ -122,7 +122,7 @@ SystemCall_common:
 	andi.	r11,r10,_TIF_SYSCALL_T_OR_A
 	bne-	syscall_dotrace
 syscall_dotrace_cont:
-	cmpli	0,r0,NR_syscalls
+	cmpldi	0,r0,NR_syscalls
 	bge-	syscall_enosys
 
 system_call:			/* label this so stack traces look sane */
@@ -204,7 +204,7 @@ syscall_enosys:
 
 syscall_error:
 	lbz	r11,TI_SC_NOERR(r12)
-	cmpi	0,r11,0
+	cmpwi	0,r11,0
 	bne-	syscall_error_cont
 	neg	r3,r3
 	oris	r5,r5,0x1000	/* Set SO bit in CR */
@@ -393,9 +393,17 @@ BEGIN_FTR_SECTION
 	cmpd	cr1,r6,r9	/* or is new ESID the same as current ESID? */
 	cror	eq,4*cr1+eq,eq
 	beq	2f		/* if yes, don't slbie it */
-	oris	r6,r6,0x0800	/* set C (class) bit */
-	slbie	r6
-	slbie	r6		/* Workaround POWER5 < DD2.1 issue */
+	oris	r0,r6,0x0800	/* set C (class) bit */
+
+	/* Bolt in the new stack SLB entry */
+	ld	r7,KSP_VSID(r4)	/* Get new stack's VSID */
+	oris	r6,r6,(SLB_ESID_V)@h
+	ori	r6,r6,(SLB_NUM_BOLTED-1)@l
+	slbie	r0
+	slbie	r0		/* Workaround POWER5 < DD2.1 issue */
+	slbmte	r7,r6
+	isync
+
 2:
 END_FTR_SECTION_IFSET(CPU_FTR_SLB)
 	clrrdi	r7,r8,THREAD_SHIFT	/* base of new stack */
@@ -738,6 +746,10 @@ _STATIC(rtas_restore_regs)
 	mtlr    r0
         blr				/* return to caller */
 
+#endif /* CONFIG_PPC_PSERIES */
+
+#ifdef CONFIG_PPC_MULTIPLATFORM
+
 _GLOBAL(enter_prom)
 	mflr	r0
 	std	r0,16(r1)
@@ -769,11 +781,8 @@ _GLOBAL(enter_prom)
 	std	r11,_MSR(r1)
 
 	/* Get the PROM entrypoint */
-        bl      .reloc_offset
-	LOADADDR(r12,prom)
-	sub	r12,r12,r3
-	ld	r12,PROMENTRY(r12)
-	mtlr	r12
+	ld	r0,GPR4(r1)
+	mtlr	r0
 
 	/* Switch MSR to 32 bits mode
 	 */
@@ -826,4 +835,4 @@ _GLOBAL(enter_prom)
 	mtlr    r0
         blr
 	
-#endif	/* defined(CONFIG_PPC_PSERIES) */
+#endif	/* CONFIG_PPC_MULTIPLATFORM */
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
index a5d67f599..90be51ae4 100644
--- a/arch/ppc64/kernel/head.S
+++ b/arch/ppc64/kernel/head.S
@@ -83,13 +83,14 @@
 	.text
 	.globl  _stext
 _stext:
-#ifdef CONFIG_PPC_PSERIES
-_STATIC(__start)
+#ifdef CONFIG_PPC_MULTIPLATFORM
+_GLOBAL(__start)
 	/* NOP this out unconditionally */
 BEGIN_FTR_SECTION
-	b .__start_initialization_pSeries
+	b .__start_initialization_multiplatform
 END_FTR_SECTION(0, 1)
-#endif
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+
 	/* Catch branch to 0 in real mode */
 	trap
 #ifdef CONFIG_PPC_ISERIES
@@ -117,7 +118,8 @@ embedded_sysmap_start:
 	.globl	embedded_sysmap_end
 embedded_sysmap_end:
 	.llong	0
-#else
+
+#else /* CONFIG_PPC_ISERIES */
 
 	/* Secondary processors spin on this value until it goes to 1. */
 	.globl  __secondary_hold_spinloop
@@ -199,6 +201,7 @@ exception_marker:
 #define EX_R12		24
 #define EX_R13		32
 #define EX_SRR0		40
+#define EX_R3		40	/* SLB miss saves R3, but not SRR0 */
 #define EX_DAR		48
 #define EX_LR		48	/* SLB miss saves LR, but not DAR */
 #define EX_DSISR	56
@@ -322,36 +325,11 @@ label##_Iseries:							\
 	HMT_MEDIUM;							\
 	mtspr	SPRG1,r13;		/* save r13 */			\
 	EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN);				\
-	lbz	r10,PACAPROFENABLED(r13);				\
-	cmpwi	r10,0;							\
-	bne-	label##_Iseries_profile;				\
-label##_Iseries_prof_ret:						\
 	lbz	r10,PACAPROCENABLED(r13);				\
 	cmpwi	0,r10,0;						\
 	beq-	label##_Iseries_masked;					\
 	EXCEPTION_PROLOG_ISERIES_2;					\
 	b	label##_common;						\
-label##_Iseries_profile:						\
-	ld	r12,PACALPPACA+LPPACASRR1(r13);				\
-	andi.	r12,r12,MSR_PR;		/* Test if in kernel */		\
-	bne	label##_Iseries_prof_ret;				\
-	ld	r11,PACALPPACA+LPPACASRR0(r13);				\
-	ld	r12,PACAPROFSTEXT(r13);	/* _stext */			\
-	subf	r11,r12,r11;		/* offset into kernel */	\
-	lwz	r12,PACAPROFSHIFT(r13);					\
-	srd	r11,r11,r12;						\
-	lwz	r12,PACAPROFLEN(r13);	/* profile table length - 1 */	\
-	cmpd	r11,r12;		/* off end? */			\
-	ble	1f;							\
-	mr	r11,r12;		/* force into last entry */	\
-1:	sldi	r11,r11,2;		/* convert to offset */		\
-	ld	r12,PACAPROFBUFFER(r13);/* profile buffer */		\
-	add	r12,r12,r11;						\
-2:	lwarx	r11,0,r12;		/* atomically increment */	\
-	addi	r11,r11,1;						\
-	stwcx.	r11,0,r12;						\
-	bne-	2b;							\
-	b	label##_Iseries_prof_ret
 
 #ifdef DO_SOFT_DISABLE
 #define DISABLE_INTS				\
@@ -446,21 +424,13 @@ DataAccessSLB_Pseries:
 	std	r10,PACA_EXSLB+EX_R10(r13)
 	std	r11,PACA_EXSLB+EX_R11(r13)
 	std	r12,PACA_EXSLB+EX_R12(r13)
-	std	r3,PACASLBR3(r13)
+	std	r3,PACA_EXSLB+EX_R3(r13)
 	mfspr	r9,SPRG1
 	std	r9,PACA_EXSLB+EX_R13(r13)
 	mfcr	r9
-	clrrdi	r12,r13,32		/* get high part of &label */
-	mfmsr	r10
-	mfspr	r11,SRR0		/* save SRR0 */
-	ori	r12,r12,(.do_slb_miss)@l
-	ori	r10,r10,MSR_IR|MSR_DR	/* DON'T set RI for SLB miss */
-	mtspr	SRR0,r12
 	mfspr	r12,SRR1		/* and SRR1 */
-	mtspr	SRR1,r10
 	mfspr	r3,DAR
-	rfid
-	b	.	/* prevent speculative execution */
+	b	.do_slb_miss		/* Rel. branch works in real mode */
 
 	STD_EXCEPTION_PSERIES(0x400, InstructionAccess)
 
@@ -474,21 +444,13 @@ InstructionAccessSLB_Pseries:
 	std	r10,PACA_EXSLB+EX_R10(r13)
 	std	r11,PACA_EXSLB+EX_R11(r13)
 	std	r12,PACA_EXSLB+EX_R12(r13)
-	std	r3,PACASLBR3(r13)
+	std	r3,PACA_EXSLB+EX_R3(r13)
 	mfspr	r9,SPRG1
 	std	r9,PACA_EXSLB+EX_R13(r13)
 	mfcr	r9
-	clrrdi	r12,r13,32		/* get high part of &label */
-	mfmsr	r10
-	mfspr	r11,SRR0		/* save SRR0 */
-	ori	r12,r12,(.do_slb_miss)@l
-	ori	r10,r10,MSR_IR|MSR_DR	/* DON'T set RI for SLB miss */
-	mtspr	SRR0,r12
 	mfspr	r12,SRR1		/* and SRR1 */
-	mtspr	SRR1,r10
-	mr	r3,r11			/* SRR0 is faulting address */
-	rfid
-	b	.	/* prevent speculative execution */
+	mfspr	r3,SRR0			/* SRR0 is faulting address */
+	b	.do_slb_miss		/* Rel. branch works in real mode */
 
 	STD_EXCEPTION_PSERIES(0x500, HardwareInterrupt)
 	STD_EXCEPTION_PSERIES(0x600, Alignment)
@@ -580,7 +542,7 @@ __end_systemcfg:
 	 * VSID generation algorithm.  See include/asm/mmu_context.h.
 	 */
 
-	.llong	1		/* # ESIDs to be mapped by hypervisor	 */
+	.llong	2		/* # ESIDs to be mapped by hypervisor	 */
 	.llong	1		/* # memory ranges to be mapped by hypervisor */
 	.llong	STAB0_PAGE	/* Page # of segment table within load area	*/
 	.llong	0		/* Reserved */
@@ -588,11 +550,15 @@ __end_systemcfg:
 	.llong	0		/* Reserved */
 	.llong	0		/* Reserved */
 	.llong	0		/* Reserved */
-	.llong	0x0c00000000	/* ESID to map (Kernel at EA = 0xC000000000000000) */
-	.llong	0x06a99b4b14	/* VSID to map (Kernel at VA = 0x6a99b4b140000000) */
+	.llong	(KERNELBASE>>SID_SHIFT)
+	.llong	0x408f92c94	/* KERNELBASE VSID */
+	/* We have to list the bolted VMALLOC segment here, too, so that it
+	 * will be restored on shared processor switch */
+	.llong	(VMALLOCBASE>>SID_SHIFT)
+	.llong	0xf09b89af5	/* VMALLOCBASE VSID */
 	.llong	8192		/* # pages to map (32 MB) */
 	.llong	0		/* Offset from start of loadarea to start of map */
-	.llong	0x0006a99b4b140000	/* VPN of first page to map */
+	.llong	0x408f92c940000	/* VPN of first page to map */
 
 	. = 0x6100
 
@@ -630,8 +596,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
 DataAccessSLB_Iseries:
 	mtspr	SPRG1,r13		/* save r13 */
 	EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB)
-	std	r3,PACASLBR3(r13)
-	ld	r11,PACALPPACA+LPPACASRR0(r13)
+	std	r3,PACA_EXSLB+EX_R3(r13)
 	ld	r12,PACALPPACA+LPPACASRR1(r13)
 	mfspr	r3,DAR
 	b	.do_slb_miss
@@ -642,10 +607,9 @@ DataAccessSLB_Iseries:
 InstructionAccessSLB_Iseries:
 	mtspr	SPRG1,r13		/* save r13 */
 	EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB)
-	std	r3,PACASLBR3(r13)
-	ld	r11,PACALPPACA+LPPACASRR0(r13)
+	std	r3,PACA_EXSLB+EX_R3(r13)
 	ld	r12,PACALPPACA+LPPACASRR1(r13)
-	mr	r3,r11
+	ld	r3,PACALPPACA+LPPACASRR0(r13)
 	b	.do_slb_miss
 
 	MASKABLE_EXCEPTION_ISERIES(0x500, HardwareInterrupt)
@@ -1033,6 +997,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
 	 * interrupts if necessary.
 	 */
 	beq	.ret_from_except_lite
+	/* For a hash failure, we don't bother re-enabling interrupts */
+	ble-	12f
+
 	/*
 	 * hash_page couldn't handle it, set soft interrupt enable back
 	 * to what it was before the trap.  Note that .local_irq_restore
@@ -1043,6 +1010,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
 	b	11f
 #else
 	beq	fast_exception_return   /* Return from exception on success */
+	ble-	12f			/* Failure return from hash_page */
+
 	/* fall through */
 #endif
 
@@ -1062,6 +1031,15 @@ _GLOBAL(handle_page_fault)
 	bl	.bad_page_fault
 	b	.ret_from_except
 
+/* We have a page fault that hash_page could handle but HV refused
+ * the PTE insertion
+ */
+12:	bl	.save_nvgprs
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	lwz	r4,_DAR(r1)
+	bl	.low_hash_fault
+	b	.ret_from_except
+
 	/* here we have a segment miss */
 _GLOBAL(do_ste_alloc)
 	bl	.ste_allocate		/* try to insert stab entry */
@@ -1088,18 +1066,9 @@ _GLOBAL(do_stab_bolted)
 	rldimi	r10,r11,7,52	/* r10 = first ste of the group */
 
 	/* Calculate VSID */
-	/* (((ea >> 28) & 0x1fff) << 15) | (ea >> 60) */
-	rldic	r11,r11,15,36
-	ori	r11,r11,0xc
-
-	/* VSID_RANDOMIZER */
-	li	r9,9
-	sldi	r9,r9,32
-	oris	r9,r9,58231
-	ori	r9,r9,39831
-
-	mulld	r9,r11,r9
-	rldic	r9,r9,12,16	/* r9 = vsid << 12 */
+	/* This is a kernel address, so protovsid = ESID */
+	ASM_VSID_SCRAMBLE(r11, r9)
+	rldic	r9,r11,12,16	/* r9 = vsid << 12 */
 
 	/* Search the primary group for a free entry */
 1:	ld	r11,0(r10)	/* Test valid bit of the current ste	*/
@@ -1176,7 +1145,6 @@ _GLOBAL(do_slb_miss)
 	mflr	r10
 
 	stw	r9,PACA_EXSLB+EX_CCR(r13)	/* save CR in exc. frame */
-	std	r11,PACA_EXSLB+EX_SRR0(r13)	/* save SRR0 in exc. frame */
 	std	r10,PACA_EXSLB+EX_LR(r13)	/* save LR */
 
 	bl	.slb_allocate			/* handle it */
@@ -1184,9 +1152,11 @@ _GLOBAL(do_slb_miss)
 	/* All done -- return from exception. */
 
 	ld	r10,PACA_EXSLB+EX_LR(r13)
-	ld	r3,PACASLBR3(r13)
+	ld	r3,PACA_EXSLB+EX_R3(r13)
 	lwz	r9,PACA_EXSLB+EX_CCR(r13)	/* get saved CR */
-	ld	r11,PACA_EXSLB+EX_SRR0(r13)	/* get saved SRR0 */
+#ifdef CONFIG_PPC_ISERIES
+	ld	r11,PACALPPACA+LPPACASRR0(r13)	/* get SRR0 value */
+#endif /* CONFIG_PPC_ISERIES */
 
 	mtlr	r10
 
@@ -1199,8 +1169,10 @@ _GLOBAL(do_slb_miss)
 	mtcrf	0x01,r9		/* slb_allocate uses cr0 and cr7 */
 .machine	pop
 
+#ifdef CONFIG_PPC_ISERIES
 	mtspr	SRR0,r11
 	mtspr	SRR1,r12
+#endif /* CONFIG_PPC_ISERIES */
 	ld	r9,PACA_EXSLB+EX_R9(r13)
 	ld	r10,PACA_EXSLB+EX_R10(r13)
 	ld	r11,PACA_EXSLB+EX_R11(r13)
@@ -1253,12 +1225,10 @@ _GLOBAL(pseries_secondary_smp_init)
 #endif
 	b 	1b			/* Loop until told to go	 */
 #ifdef CONFIG_PPC_ISERIES
-_GLOBAL(__start_initialization_iSeries)
+_STATIC(__start_initialization_iSeries)
 	/* Clear out the BSS */
 	LOADADDR(r11,__bss_stop)
-
 	LOADADDR(r8,__bss_start)
-
 	sub	r11,r11,r8		/* bss size			*/
 	addi	r11,r11,7		/* round up to an even double word */
 	rldicl. r11,r11,61,3		/* shift right by 3		*/
@@ -1295,32 +1265,73 @@ _GLOBAL(__start_initialization_iSeries)
 	ld	r6,PACA(r4)		/* Get the base paca pointer	*/
 	ld	r4,PACASTABVIRT(r6)
 
-	bl	.iSeries_fixup_klimit
+	bl	.iSeries_early_setup
 
 	/* relocation is on at this point */
 
 	b	.start_here_common
-#endif
+#endif /* CONFIG_PPC_ISERIES */
 
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
 
-_STATIC(mmu_off)
+_STATIC(__mmu_off)
 	mfmsr	r3
 	andi.	r0,r3,MSR_IR|MSR_DR
 	beqlr
 	andc	r3,r3,r0
-	mtspr	SRR0,r4
-	mtspr	SRR1,r3
+	mtspr	SPRN_SRR0,r4
+	mtspr	SPRN_SRR1,r3
 	sync
 	rfid
 	b	.	/* prevent speculative execution */
-_GLOBAL(__start_initialization_pSeries)
-	mr	r31,r3			/* save parameters */
+
+
+/*
+ * Here is our main kernel entry point. We support currently 2 kind of entries
+ * depending on the value of r5.
+ *
+ *   r5 != NULL -> OF entry, we go to prom_init, "legacy" parameter content
+ *                 in r3...r7
+ *   
+ *   r5 == NULL -> kexec style entry. r3 is a physical pointer to the
+ *                 DT block, r4 is a physical pointer to the kernel itself
+ *
+ */
+_GLOBAL(__start_initialization_multiplatform)
+	/*
+	 * Are we booted from a PROM Of-type client-interface ?
+	 */
+	cmpldi	cr0,r5,0
+	bne	.__boot_from_prom		/* yes -> prom */
+
+	/* Save parameters */
+	mr	r31,r3
+	mr	r30,r4
+
+	/* Make sure we are running in 64 bits mode */
+	bl	.enable_64b_mode
+
+	/* Setup some critical 970 SPRs before switching MMU off */
+	bl	.__970_cpu_preinit
+
+	/* cpu # */
+	li	r24,0
+
+	/* Switch off MMU if not already */
+	LOADADDR(r4, .__after_prom_start - KERNELBASE)
+	add	r4,r4,r30
+	bl	.__mmu_off
+	b	.__after_prom_start
+
+_STATIC(__boot_from_prom)
+	/* Save parameters */
+	mr	r31,r3
 	mr	r30,r4
 	mr	r29,r5
 	mr	r28,r6
 	mr	r27,r7
 
+	/* Make sure we are running in 64 bits mode */
 	bl	.enable_64b_mode
 
 	/* put a relocation offset into r3 */
@@ -1333,7 +1344,7 @@ _GLOBAL(__start_initialization_pSeries)
 	/* Relocate the TOC from a virt addr to a real addr */
 	sub	r2,r2,r3
 
-	/* Save parameters */
+	/* Restore parameters */
 	mr	r3,r31
 	mr	r4,r30
 	mr	r5,r29
@@ -1342,17 +1353,8 @@ _GLOBAL(__start_initialization_pSeries)
 
 	/* Do all of the interaction with OF client interface */
 	bl	.prom_init
-	mr	r23,r3			/* Save phys address we are running at */
-
-	/* Setup some critical 970 SPRs before switching MMU off */
-	bl	.__970_cpu_preinit
-
-	li	r24,0			/* cpu # */
-
-	/* Switch off MMU if not already */
-	LOADADDR(r4, .__after_prom_start - KERNELBASE)
-	add	r4,r4,r23
-	bl	.mmu_off	
+	/* We never return */
+	trap
 
 /*
  * At this point, r3 contains the physical address we are running at,
@@ -1378,7 +1380,7 @@ _STATIC(__after_prom_start)
 
 	li	r3,0			/* target addr */
 
-	// XXX FIXME: Use phys returned by OF (r23)
+	// XXX FIXME: Use phys returned by OF (r30)
 	sub	r4,r27,r26 		/* source addr			 */
 					/* current address of _start	 */
 					/*   i.e. where we are running	 */
@@ -1403,8 +1405,9 @@ _STATIC(__after_prom_start)
 	ld	r5,0(r5)		/* get the value of klimit */
 	sub	r5,r5,r27
 	bl	.copy_and_flush		/* copy the rest */
-	b	.start_here_pSeries
-#endif
+	b	.start_here_multiplatform
+
+#endif /* CONFIG_PPC_MULTIPLATFORM */
 
 /*
  * Copy routine used to copy the kernel to start at physical address 0
@@ -1609,6 +1612,7 @@ _STATIC(load_up_altivec)
 	li	r10,THREAD_VSCR
 	stw	r4,THREAD_USED_VR(r5)
 	lvx	vr0,r10,r5
+	mtvscr	vr0
 	REST_32VRS(0,r4,r5)
 #ifndef CONFIG_SMP
 	/* Update last_task_used_math to 'current' */
@@ -1823,15 +1827,33 @@ _GLOBAL(enable_64b_mode)
 	isync
 	blr
 
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
 /*
  * This is where the main kernel code starts.
  */
-_STATIC(start_here_pSeries)
+_STATIC(start_here_multiplatform)
 	/* get a new offset, now that the kernel has moved. */
 	bl	.reloc_offset
 	mr	r26,r3
 
+	/* Clear out the BSS. It may have been done in prom_init,
+	 * already but that's irrelevant since prom_init will soon
+	 * be detached from the kernel completely. Besides, we need
+	 * to clear it now for kexec-style entry.
+	 */
+	LOADADDR(r11,__bss_stop)
+	LOADADDR(r8,__bss_start)
+	sub	r11,r11,r8		/* bss size			*/
+	addi	r11,r11,7		/* round up to an even double word */
+	rldicl. r11,r11,61,3		/* shift right by 3		*/
+	beq	4f
+	addi	r8,r8,-8
+	li	r0,0
+	mtctr	r11			/* zero this many doublewords	*/
+3:	stdu	r0,8(r8)
+	bdnz	3b
+4:
+
 	mfmsr	r6
 	ori	r6,r6,MSR_RI
 	mtmsrd	r6			/* RI on */
@@ -1904,8 +1926,11 @@ _STATIC(start_here_pSeries)
 	mr	r5,r26
 	bl	.identify_cpu
 
-	/* Get the pointer to the segment table which is used by		*/
-	/* stab_initialize						 */
+	/* Setup a valid physical PACA pointer in SPRG3 for early_setup
+	 * note that boot_cpuid can always be 0 nowadays since there is
+	 * nowhere it can be initialized differently before we reach this
+	 * code
+	 */
 	LOADADDR(r27, boot_cpuid)
 	sub	r27,r27,r26
 	lwz	r27,0(r27)
@@ -1914,12 +1939,18 @@ _STATIC(start_here_pSeries)
 	mulli	r13,r27,PACA_SIZE	/* Calculate vaddr of right paca */
 	add	r13,r13,r24		/* for this processor.		 */
 	sub	r13,r13,r26		/* convert to physical addr	 */
-
 	mtspr	SPRG3,r13		/* PPPBBB: Temp... -Peter */
-	ld	r3,PACASTABREAL(r13)
-	ori	r4,r3,1			/* turn on valid bit		 */
 	
+	/* Do very early kernel initializations, including initial hash table,
+	 * stab and slb setup before we turn on relocation.	*/
+
+	/* Restore parameters passed from prom_init/kexec */
+	mr	r3,r31
+ 	bl	.early_setup
+
 	/* set the ASR */
+	ld	r3,PACASTABREAL(r13)
+	ori	r4,r3,1			/* turn on valid bit		 */
 	li	r3,SYSTEMCFG_PHYS_ADDR	/* r3 = ptr to systemcfg */
 	lwz	r3,PLATFORM(r3)		/* r3 = platform flags */
 	cmpldi 	r3,PLATFORM_PSERIES_LPAR
@@ -1938,13 +1969,7 @@ _STATIC(start_here_pSeries)
 98:					/* !(rpa hypervisor) || !(star) */
 	mtasr	r4			/* set the stab location	*/
 99:
-	mfspr	r6,SPRG3
-	ld	r3,PACASTABREAL(r6)	/* restore r3 for stab_initialize */
-
-	/* Initialize an initial memory mapping and turn on relocation.	*/
-	bl	.stab_initialize
-	bl	.htab_initialize
-
+	/* Set SDR1 (hash table pointer) */
 	li	r3,SYSTEMCFG_PHYS_ADDR	/* r3 = ptr to systemcfg */
 	lwz	r3,PLATFORM(r3)		/* r3 = platform flags */
 	/* Test if bit 0 is set (LPAR bit) */
@@ -1961,7 +1986,7 @@ _STATIC(start_here_pSeries)
 	mtspr	SRR1,r4
 	rfid
 	b	.	/* prevent speculative execution */
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* CONFIG_PPC_MULTIPLATFORM */
 	
 	/* This is where all platforms converge execution */
 _STATIC(start_here_common)
@@ -2009,13 +2034,6 @@ _STATIC(start_here_common)
 	ld	r2,PACATOC(r13)
 	std	r1,PACAKSAVE(r13)
 
-	/* Restore the parms passed in from the bootloader. */
-	mr	r3,r31
-	mr	r4,r30
-	mr	r5,r29
-	mr	r6,r28
-	mr	r7,r27
-
 	bl	.setup_system
 
 	/* Load up the kernel context */
diff --git a/arch/ppc64/kernel/hvconsole.c b/arch/ppc64/kernel/hvconsole.c
index dedefb305..c72fb8ffe 100644
--- a/arch/ppc64/kernel/hvconsole.c
+++ b/arch/ppc64/kernel/hvconsole.c
@@ -1,6 +1,10 @@
 /*
  * hvconsole.c
  * Copyright (C) 2004 Hollis Blanchard, IBM Corporation
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Additional Author(s):
+ *  Ryan S. Arnold <rsa@us.ibm.com>
  *
  * LPAR console support.
  * 
@@ -22,14 +26,22 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <asm/hvcall.h>
-#include <asm/prom.h>
 #include <asm/hvconsole.h>
+#include <asm/prom.h>
 
-int hvc_get_chars(int index, char *buf, int count)
+/**
+ * hvc_get_chars - retrieve characters from firmware for denoted vterm adatper
+ * @vtermno: The vtermno or unit_address of the adapter from which to fetch the
+ *	data.
+ * @buf: The character buffer into which to put the character data fetched from
+ *	firmware.
+ * @count: not used?
+ */
+int hvc_get_chars(uint32_t vtermno, char *buf, int count)
 {
 	unsigned long got;
 
-	if (plpar_hcall(H_GET_TERM_CHAR, index, 0, 0, 0, &got,
+	if (plpar_hcall(H_GET_TERM_CHAR, vtermno, 0, 0, 0, &got,
 		(unsigned long *)buf, (unsigned long *)buf+1) == H_Success) {
 		/*
 		 * Work around a HV bug where it gives us a null
@@ -53,40 +65,56 @@ int hvc_get_chars(int index, char *buf, int count)
 
 EXPORT_SYMBOL(hvc_get_chars);
 
-int hvc_put_chars(int index, const char *buf, int count)
+/**
+ * hvc_put_chars: send characters to firmware for denoted vterm adapter
+ * @vtermno: The vtermno or unit_address of the adapter from which the data
+ *	originated.
+ * @buf: The character buffer that contains the character data to send to
+ *	firmware.
+ * @count: Send this number of characters.
+ */
+int hvc_put_chars(uint32_t vtermno, const char *buf, int count)
 {
 	unsigned long *lbuf = (unsigned long *) buf;
 	long ret;
 
-	ret = plpar_hcall_norets(H_PUT_TERM_CHAR, index, count, lbuf[0],
+	ret = plpar_hcall_norets(H_PUT_TERM_CHAR, vtermno, count, lbuf[0],
 				 lbuf[1]);
 	if (ret == H_Success)
 		return count;
 	if (ret == H_Busy)
 		return 0;
-	return -1;
+	return -EIO;
 }
 
 EXPORT_SYMBOL(hvc_put_chars);
 
-/* return the number of client vterms present */
-/* XXX this requires an interface change to handle multiple discontiguous
- * vterms */
-int hvc_count(int *start_termno)
+/*
+ * We hope/assume that the first vty found corresponds to the first console
+ * device.
+ */
+int hvc_find_vtys(void)
 {
 	struct device_node *vty;
 	int num_found = 0;
 
-	/* consider only the first vty node.
-	 * we should _always_ be able to find one. */
-	vty = of_find_node_by_name(NULL, "vty");
-	if (vty && device_is_compatible(vty, "hvterm1")) {
-		u32 *termno = (u32 *)get_property(vty, "reg", NULL);
+	for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL;
+			vty = of_find_node_by_name(vty, "vty")) {
+		uint32_t *vtermno;
+
+		/* We have statically defined space for only a certain number of
+		 * console adapters. */
+		if (num_found >= MAX_NR_HVC_CONSOLES)
+			break;
 
-		if (termno && start_termno)
-			*start_termno = *termno;
-		num_found = 1;
-		of_node_put(vty);
+		vtermno = (uint32_t *)get_property(vty, "reg", NULL);
+		if (!vtermno)
+			continue;
+
+		if (device_is_compatible(vty, "hvterm1")) {
+			hvc_instantiate(*vtermno, num_found);
+			++num_found;
+		}
 	}
 
 	return num_found;
diff --git a/arch/ppc64/kernel/hvcserver.c b/arch/ppc64/kernel/hvcserver.c
index fbe445ec0..bde8f42da 100644
--- a/arch/ppc64/kernel/hvcserver.c
+++ b/arch/ppc64/kernel/hvcserver.c
@@ -61,14 +61,21 @@ int hvcs_convert(long to_convert)
 	}
 }
 
+/**
+ * hvcs_free_partner_info - free pi allocated by hvcs_get_partner_info
+ * @head: list_head pointer for an allocated list of partner info structs to
+ *	free.
+ *
+ * This function is used to free the partner info list that was returned by
+ * calling hvcs_get_partner_info().
+ */
 int hvcs_free_partner_info(struct list_head *head)
 {
 	struct hvcs_partner_info *pi;
 	struct list_head *element;
 
-	if (!head) {
+	if (!head)
 		return -EINVAL;
-	}
 
 	while (!list_empty(head)) {
 		element = head->next;
@@ -82,7 +89,7 @@ int hvcs_free_partner_info(struct list_head *head)
 EXPORT_SYMBOL(hvcs_free_partner_info);
 
 /* Helper function for hvcs_get_partner_info */
-int hvcs_next_partner(unsigned int unit_address,
+int hvcs_next_partner(uint32_t unit_address,
 		unsigned long last_p_partition_ID,
 		unsigned long last_p_unit_address, unsigned long *pi_buff)
 
@@ -94,25 +101,37 @@ int hvcs_next_partner(unsigned int unit_address,
 	return hvcs_convert(retval);
 }
 
-/*
- * The unit_address parameter is the unit address of the vty-server vdevice
- * in whose partner information the caller is interested.  This function
- * uses a pointer to a list_head instance in which to store the partner info.
+/**
+ * hvcs_get_partner_info - Get all of the partner info for a vty-server adapter
+ * @unit_address: The unit_address of the vty-server adapter for which this
+ *	function is fetching partner info.
+ * @head: An initialized list_head pointer to an empty list to use to return the
+ *	list of partner info fetched from the hypervisor to the caller.
+ * @pi_buff: A page sized buffer pre-allocated prior to calling this function
+ *	that is to be used to be used by firmware as an iterator to keep track
+ *	of the partner info retrieval.
+ *
  * This function returns non-zero on success, or if there is no partner info.
  *
+ * The pi_buff is pre-allocated prior to calling this function because this
+ * function may be called with a spin_lock held and kmalloc of a page is not
+ * recommended as GFP_ATOMIC.
+ *
+ * The first long of this buffer is used to store a partner unit address.  The
+ * second long is used to store a partner partition ID and starting at
+ * pi_buff[2] is the 79 character Converged Location Code (diff size than the
+ * unsigned longs, hence the casting mumbo jumbo you see later).
+ *
  * Invocation of this function should always be followed by an invocation of
  * hvcs_free_partner_info() using a pointer to the SAME list head instance
- * that was used to store the partner_info list.
+ * that was passed as a parameter to this function.
  */
-int hvcs_get_partner_info(unsigned int unit_address, struct list_head *head,
+int hvcs_get_partner_info(uint32_t unit_address, struct list_head *head,
 		unsigned long *pi_buff)
 {
 	/*
-	 * This is a page sized buffer to be passed to hvcall per invocation.
-	 * NOTE: the first long returned is unit_address.  The second long
-	 * returned is the partition ID and starting with pi_buff[2] are
-	 * HVCS_CLC_LENGTH characters, which are diff size than the unsigned
-	 * long, hence the casting mumbojumbo you see later.
+	 * Dealt with as longs because of the hcall interface even though the
+	 * values are uint32_t.
 	 */
 	unsigned long	last_p_partition_ID;
 	unsigned long	last_p_unit_address;
@@ -122,15 +141,12 @@ int hvcs_get_partner_info(unsigned int unit_address, struct list_head *head,
 
 	memset(pi_buff, 0x00, PAGE_SIZE);
 	/* invalid parameters */
-	if (!head)
+	if (!head || !pi_buff)
 		return -EINVAL;
 
 	last_p_partition_ID = last_p_unit_address = ~0UL;
 	INIT_LIST_HEAD(head);
 
-	if (!pi_buff)
-		return -ENOMEM;
-
 	do {
 		retval = hvcs_next_partner(unit_address, last_p_partition_ID,
 				last_p_unit_address, pi_buff);
@@ -183,21 +199,29 @@ int hvcs_get_partner_info(unsigned int unit_address, struct list_head *head,
 }
 EXPORT_SYMBOL(hvcs_get_partner_info);
 
-/*
+/**
+ * hvcs_register_connection - establish a connection between this vty-server and
+ *	a vty.
+ * @unit_address: The unit address of the vty-server adapter that is to be
+ *	establish a connection.
+ * @p_partition_ID: The partition ID of the vty adapter that is to be connected.
+ * @p_unit_address: The unit address of the vty adapter to which the vty-server
+ *	is to be connected.
+ *
  * If this function is called once and -EINVAL is returned it may
  * indicate that the partner info needs to be refreshed for the
  * target unit address at which point the caller must invoke
  * hvcs_get_partner_info() and then call this function again.  If,
  * for a second time, -EINVAL is returned then it indicates that
  * there is probably already a partner connection registered to a
- * different vty-server@ vdevice.  It is also possible that a second
+ * different vty-server adapter.  It is also possible that a second
  * -EINVAL may indicate that one of the parms is not valid, for
- * instance if the link was removed between the vty-server@ vdevice
- * and the vty@ vdevice that you are trying to open.  Don't shoot the
+ * instance if the link was removed between the vty-server adapter
+ * and the vty adapter that you are trying to open.  Don't shoot the
  * messenger.  Firmware implemented it this way.
  */
-int hvcs_register_connection( unsigned int unit_address,
-		unsigned int p_partition_ID, unsigned int p_unit_address)
+int hvcs_register_connection( uint32_t unit_address,
+		uint32_t p_partition_ID, uint32_t p_unit_address)
 {
 	long retval;
 	retval = plpar_hcall_norets(H_REGISTER_VTERM, unit_address,
@@ -206,11 +230,17 @@ int hvcs_register_connection( unsigned int unit_address,
 }
 EXPORT_SYMBOL(hvcs_register_connection);
 
-/*
- * If -EBUSY is returned continue to call this function
- * until 0 is returned.
+/**
+ * hvcs_free_connection - free the connection between a vty-server and vty
+ * @unit_address: The unit address of the vty-server that is to have its
+ *	connection severed.
+ *
+ * This function is used to free the partner connection between a vty-server
+ * adapter and a vty adapter.
+ *
+ * If -EBUSY is returned continue to call this function until 0 is returned.
  */
-int hvcs_free_connection(unsigned int unit_address)
+int hvcs_free_connection(uint32_t unit_address)
 {
 	long retval;
 	retval = plpar_hcall_norets(H_FREE_VTERM, unit_address);
diff --git a/arch/ppc64/kernel/iSeries_htab.c b/arch/ppc64/kernel/iSeries_htab.c
index 2456227b4..b1177b476 100644
--- a/arch/ppc64/kernel/iSeries_htab.c
+++ b/arch/ppc64/kernel/iSeries_htab.c
@@ -233,4 +233,6 @@ void hpte_init_iSeries(void)
 	ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp;
 	ppc_md.hpte_insert	= iSeries_hpte_insert;
 	ppc_md.hpte_remove     	= iSeries_hpte_remove;
+
+	htab_finish_init();
 }
diff --git a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c
index 3472d188e..d3715a153 100644
--- a/arch/ppc64/kernel/iSeries_pci.c
+++ b/arch/ppc64/kernel/iSeries_pci.c
@@ -419,46 +419,39 @@ static int iSeries_Scan_Bridge_Slot(HvBusNumber Bus,
  * I/0 Memory copy MUST use mmio commands on iSeries
  * To do; For performance, include the hv call directly
  */
-void *iSeries_memset_io(void *dest, char c, size_t Count)
+void iSeries_memset_io(volatile void __iomem *dest, char c, size_t Count)
 {
 	u8 ByteValue = c;
 	long NumberOfBytes = Count;
-	char *IoBuffer = dest;
 
 	while (NumberOfBytes > 0) {
-		iSeries_Write_Byte(ByteValue, (void *)IoBuffer);
-		++IoBuffer;
+		iSeries_Write_Byte(ByteValue, dest++);
 		-- NumberOfBytes;
 	}
-	return dest;
 }
 EXPORT_SYMBOL(iSeries_memset_io);
 
-void *iSeries_memcpy_toio(void *dest, void *source, size_t count)
+void iSeries_memcpy_toio(volatile void __iomem *dest, void *source, size_t count)
 {
-	char *dst = dest;
 	char *src = source;
 	long NumberOfBytes = count;
 
 	while (NumberOfBytes > 0) {
-		iSeries_Write_Byte(*src++, (void *)dst++);
+		iSeries_Write_Byte(*src++, dest++);
 		-- NumberOfBytes;
 	}
-	return dest;
 }
 EXPORT_SYMBOL(iSeries_memcpy_toio);
 
-void *iSeries_memcpy_fromio(void *dest, void *source, size_t count)
+void iSeries_memcpy_fromio(void *dest, const volatile void __iomem *src, size_t count)
 {
 	char *dst = dest;
-	char *src = source;
 	long NumberOfBytes = count;
 
 	while (NumberOfBytes > 0) {
-		*dst++ = iSeries_Read_Byte((void *)src++);
+		*dst++ = iSeries_Read_Byte(src++);
 		-- NumberOfBytes;
 	}
-	return dest;
 }
 EXPORT_SYMBOL(iSeries_memcpy_fromio);
 
@@ -612,17 +605,19 @@ static int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode,
  * Note: Make sure the passed variable end up on the stack to avoid
  * the exposure of being device global.
  */
-static inline struct iSeries_Device_Node *xlateIoMmAddress(void *IoAddress,
+static inline struct iSeries_Device_Node *xlateIoMmAddress(const volatile void __iomem *IoAddress,
 		 u64 *dsaptr, u64 *BarOffsetPtr)
 {
+	unsigned long OrigIoAddr;
 	unsigned long BaseIoAddr;
 	unsigned long TableIndex;
 	struct iSeries_Device_Node *DevNode;
 
-	if (((unsigned long)IoAddress < iSeries_Base_Io_Memory) ||
-			((unsigned long)IoAddress >= iSeries_Max_Io_Memory))
+	OrigIoAddr = (unsigned long __force)IoAddress;
+	if ((OrigIoAddr < iSeries_Base_Io_Memory) ||
+			(OrigIoAddr >= iSeries_Max_Io_Memory))
 		return NULL;
-	BaseIoAddr = (unsigned long)IoAddress - iSeries_Base_Io_Memory;
+	BaseIoAddr = OrigIoAddr - iSeries_Base_Io_Memory;
 	TableIndex = BaseIoAddr / iSeries_IoMmTable_Entry_Size;
 	DevNode = iSeries_IoMmTable[TableIndex];
 
@@ -644,7 +639,7 @@ static inline struct iSeries_Device_Node *xlateIoMmAddress(void *IoAddress,
  * iSeries_Read_Word = Read Word  (16 bit)
  * iSeries_Read_Long = Read Long  (32 bit)
  */
-u8 iSeries_Read_Byte(void *IoAddress)
+u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
 {
 	u64 BarOffset;
 	u64 dsa;
@@ -673,7 +668,7 @@ u8 iSeries_Read_Byte(void *IoAddress)
 }
 EXPORT_SYMBOL(iSeries_Read_Byte);
 
-u16 iSeries_Read_Word(void *IoAddress)
+u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
 {
 	u64 BarOffset;
 	u64 dsa;
@@ -703,7 +698,7 @@ u16 iSeries_Read_Word(void *IoAddress)
 }
 EXPORT_SYMBOL(iSeries_Read_Word);
 
-u32 iSeries_Read_Long(void *IoAddress)
+u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
 {
 	u64 BarOffset;
 	u64 dsa;
@@ -740,7 +735,7 @@ EXPORT_SYMBOL(iSeries_Read_Long);
  * iSeries_Write_Word = Write Word(16 bit)
  * iSeries_Write_Long = Write Long(32 bit)
  */
-void iSeries_Write_Byte(u8 data, void *IoAddress)
+void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress)
 {
 	u64 BarOffset;
 	u64 dsa;
@@ -767,7 +762,7 @@ void iSeries_Write_Byte(u8 data, void *IoAddress)
 }
 EXPORT_SYMBOL(iSeries_Write_Byte);
 
-void iSeries_Write_Word(u16 data, void *IoAddress)
+void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress)
 {
 	u64 BarOffset;
 	u64 dsa;
@@ -794,7 +789,7 @@ void iSeries_Write_Word(u16 data, void *IoAddress)
 }
 EXPORT_SYMBOL(iSeries_Write_Word);
 
-void iSeries_Write_Long(u32 data, void *IoAddress)
+void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress)
 {
 	u64 BarOffset;
 	u64 dsa;
@@ -820,7 +815,3 @@ void iSeries_Write_Long(u32 data, void *IoAddress)
 	} while (CheckReturnCode("WWL", DevNode, rc) != 0);
 }
 EXPORT_SYMBOL(iSeries_Write_Long);
-
-void pcibios_name_device(struct pci_dev *dev)
-{
-}
diff --git a/arch/ppc64/kernel/iSeries_pci_reset.c b/arch/ppc64/kernel/iSeries_pci_reset.c
index e1e48c35e..8848ece79 100644
--- a/arch/ppc64/kernel/iSeries_pci_reset.c
+++ b/arch/ppc64/kernel/iSeries_pci_reset.c
@@ -65,7 +65,8 @@ int iSeries_Device_ToggleReset(struct pci_dev *PciDev, int AssertTime,
 		AssertDelay = (5 * HZ) / 10;
 	else
 		AssertDelay = (AssertTime * HZ) / 10;
-	if (WaitDelay == 0)
+
+	if (DelayTime == 0)
 		WaitDelay = (30 * HZ) / 10;
 	else
 		WaitDelay = (DelayTime * HZ) / 10;
diff --git a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c
index e12b50f8c..9b59f5165 100644
--- a/arch/ppc64/kernel/iSeries_setup.c
+++ b/arch/ppc64/kernel/iSeries_setup.c
@@ -16,6 +16,8 @@
  *      2 of the License, or (at your option) any later version.
  */
  
+#undef DEBUG
+
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/threads.h>
@@ -36,6 +38,7 @@
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
 #include <asm/cputable.h>
+#include <asm/sections.h>
 
 #include <asm/time.h>
 #include "iSeries_setup.h"
@@ -53,18 +56,21 @@
 #include <asm/iSeries/iSeries_proc.h>
 #include <asm/iSeries/mf.h>
 
+extern void hvlog(char *fmt, ...);
+
+#ifdef DEBUG
+#define DBG(fmt...) hvlog(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
 /* Function Prototypes */
-extern void abort(void);
 extern void ppcdbg_initialize(void);
-extern void iSeries_pcibios_init(void);
 extern void tce_init_iSeries(void);
 
 static void build_iSeries_Memory_Map(void);
 static void setup_iSeries_cache_sizes(void);
 static void iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr);
-extern void build_valid_hpte(unsigned long vsid, unsigned long ea, unsigned long pa,
-			     pte_t *ptep, unsigned hpteflags, unsigned bolted);
-static void iSeries_setup_dprofile(void);
 extern void iSeries_setup_arch(void);
 extern void iSeries_pci_final_fixup(void);
 
@@ -77,16 +83,8 @@ static unsigned long tbFreqHz;
 static unsigned long tbFreqMhz;
 static unsigned long tbFreqMhzHundreths;
 
-unsigned long dprof_shift;
-unsigned long dprof_len;
-unsigned int *dprof_buffer;
-
 int piranha_simulator;
 
-int boot_cpuid;
-
-extern char _end[];
-
 extern int rd_size;		/* Defined in drivers/block/rd.c */
 extern unsigned long klimit;
 extern unsigned long embedded_sysmap_start;
@@ -285,8 +283,28 @@ unsigned long iSeries_process_mainstore_vpd(struct MemoryBlock *mb_array,
 	return mem_blocks;
 }
 
-void __init iSeries_init_early(void)
+static void __init iSeries_parse_cmdline(void)
+{
+	char *p, *q;
+
+	/* copy the command line parameter from the primary VSP  */
+	HvCallEvent_dmaToSp(cmd_line, 2 * 64* 1024, 256,
+			HvLpDma_Direction_RemoteToLocal);
+
+	p = cmd_line;
+	q = cmd_line + 255;
+	while(p < q) {
+		if (!*p || *p == '\n')
+			break;
+		++p;
+	}
+	*p = 0;
+}
+
+/*static*/ void __init iSeries_init_early(void)
 {
+	DBG(" -> iSeries_init_early()\n");
+
 	ppcdbg_initialize();
 
 #if defined(CONFIG_BLK_DEV_INITRD)
@@ -310,25 +328,20 @@ void __init iSeries_init_early(void)
 	iSeries_recal_tb = get_tb();
 	iSeries_recal_titan = HvCallXm_loadTod();
 
-	ppc_md.setup_arch = iSeries_setup_arch;
-	ppc_md.get_cpuinfo = iSeries_get_cpuinfo;
-	ppc_md.init_IRQ = iSeries_init_IRQ;
-	ppc_md.get_irq = iSeries_get_irq;
-	ppc_md.init = NULL;
-
-	ppc_md.pcibios_fixup  = iSeries_pci_final_fixup;
-
-	ppc_md.restart = iSeries_restart;
-	ppc_md.power_off = iSeries_power_off;
-	ppc_md.halt = iSeries_halt;
-
-	ppc_md.get_boot_time = iSeries_get_boot_time;
-	ppc_md.set_rtc_time = iSeries_set_rtc_time;
-	ppc_md.get_rtc_time = iSeries_get_rtc_time;
-	ppc_md.calibrate_decr = iSeries_calibrate_decr;
-	ppc_md.progress = iSeries_progress;
+	/*
+	 * Cache sizes must be initialized before hpte_init_iSeries is called
+	 * as the later need them for flush_icache_range()
+	 */
+	setup_iSeries_cache_sizes();
 
+	/*
+	 * Initialize the hash table management pointers
+	 */
 	hpte_init_iSeries();
+
+	/*
+	 * Initialize the DMA/TCE management
+	 */
 	tce_init_iSeries();
 
 	/*
@@ -336,63 +349,36 @@ void __init iSeries_init_early(void)
 	 * AS/400 absolute addresses
 	 */
 	build_iSeries_Memory_Map();
-	setup_iSeries_cache_sizes();
+
 	/* Initialize machine-dependency vectors */
 #ifdef CONFIG_SMP
 	smp_init_iSeries();
 #endif
 	if (itLpNaca.xPirEnvironMode == 0) 
 		piranha_simulator = 1;
-}
-
-void __init iSeries_init(unsigned long r3, unsigned long r4, unsigned long r5, 
-	   unsigned long r6, unsigned long r7)
-{
-	char *p, *q;
 
 	/* Associate Lp Event Queue 0 with processor 0 */
 	HvCallEvent_setLpEventQueueInterruptProc(0, 0);
 
-	/* copy the command line parameter from the primary VSP  */
-	HvCallEvent_dmaToSp(cmd_line, 2 * 64* 1024, 256,
-			HvLpDma_Direction_RemoteToLocal);
-
-	p = cmd_line;
-	q = cmd_line + 255;
-	while( p < q ) {
-		if (!*p || *p == '\n')
-			break;
-		++p;
-	}
-	*p = 0;
-
-        if (strstr(cmd_line, "dprofile=")) {
-                for (q = cmd_line; (p = strstr(q, "dprofile=")) != 0; ) {
-			unsigned long size, new_klimit;
-
-                        q = p + 9;
-                        if ((p > cmd_line) && (p[-1] != ' '))
-                                continue;
-                        dprof_shift = simple_strtoul(q, &q, 0);
-			dprof_len = (unsigned long)_etext -
-				(unsigned long)_stext;
-			dprof_len >>= dprof_shift;
-			size = ((dprof_len * sizeof(unsigned int)) +
-					(PAGE_SIZE-1)) & PAGE_MASK;
-			dprof_buffer = (unsigned int *)((klimit +
-						(PAGE_SIZE-1)) & PAGE_MASK);
-			new_klimit = ((unsigned long)dprof_buffer) + size;
-			lmb_reserve(__pa(klimit), (new_klimit-klimit));
-			klimit = new_klimit;
-			memset(dprof_buffer, 0, size);
-                }
-        }
-
-	iSeries_setup_dprofile();
-
 	mf_init();
 	mf_initialized = 1;
 	mb();
+
+	/* If we were passed an initrd, set the ROOT_DEV properly if the values
+	 * look sensible. If not, clear initrd reference.
+	 */
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE &&
+	    initrd_end > initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+		initrd_start = initrd_end = 0;
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+
+	iSeries_parse_cmdline();
+
+	DBG(" <- iSeries_init_early()\n");
 }
 
 /*
@@ -816,7 +802,7 @@ void __init iSeries_progress(char * st, unsigned short code)
 	}
 }
 
-void iSeries_fixup_klimit(void)
+static void __init iSeries_fixup_klimit(void)
 {
 	/*
 	 * Change klimit to take into account any ram disk
@@ -837,22 +823,6 @@ void iSeries_fixup_klimit(void)
 	}
 }
 
-static void iSeries_setup_dprofile(void)
-{
-	if (dprof_buffer) {
-		unsigned i;
-
-		for (i = 0; i < NR_CPUS; ++i) {
-			paca[i].prof_shift = dprof_shift;
-			paca[i].prof_len = dprof_len - 1;
-			paca[i].prof_buffer = dprof_buffer;
-			paca[i].prof_stext = (unsigned *)_stext;
-			mb();
-			paca[i].prof_enabled = 1;
-		}
-	}
-}
-
 int __init iSeries_src_init(void)
 {
         /* clear the progress line */
@@ -861,3 +831,27 @@ int __init iSeries_src_init(void)
 }
 
 late_initcall(iSeries_src_init);
+
+void __init iSeries_early_setup(void)
+{
+	iSeries_fixup_klimit();
+
+	ppc_md.setup_arch = iSeries_setup_arch;
+	ppc_md.get_cpuinfo = iSeries_get_cpuinfo;
+	ppc_md.init_IRQ = iSeries_init_IRQ;
+	ppc_md.get_irq = iSeries_get_irq;
+	ppc_md.init_early = iSeries_init_early,
+
+	ppc_md.pcibios_fixup  = iSeries_pci_final_fixup;
+
+	ppc_md.restart = iSeries_restart;
+	ppc_md.power_off = iSeries_power_off;
+	ppc_md.halt = iSeries_halt;
+
+	ppc_md.get_boot_time = iSeries_get_boot_time;
+	ppc_md.set_rtc_time = iSeries_set_rtc_time;
+	ppc_md.get_rtc_time = iSeries_get_rtc_time;
+	ppc_md.calibrate_decr = iSeries_calibrate_decr;
+	ppc_md.progress = iSeries_progress;
+}
+
diff --git a/arch/ppc64/kernel/iSeries_setup.h b/arch/ppc64/kernel/iSeries_setup.h
index 240dad4ef..098041b4c 100644
--- a/arch/ppc64/kernel/iSeries_setup.h
+++ b/arch/ppc64/kernel/iSeries_setup.h
@@ -19,10 +19,6 @@
 #ifndef	__ISERIES_SETUP_H__
 #define	__ISERIES_SETUP_H__
 
-extern void iSeries_init_early(void);
-extern void iSeries_init(unsigned long r3, unsigned long ird_start,
-		unsigned long ird_end, unsigned long cline_start,
-		unsigned long cline_end);
 extern void iSeries_setup_arch(void);
 extern void iSeries_setup_residual(struct seq_file *m, int cpu_id);
 extern void iSeries_get_cpuinfo(struct seq_file *m);
diff --git a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c
index bc7dbbd2d..62e509d96 100644
--- a/arch/ppc64/kernel/idle.c
+++ b/arch/ppc64/kernel/idle.c
@@ -16,40 +16,29 @@
  */
 
 #include <linux/config.h>
-#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
-#include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
 #include <linux/cpu.h>
+#include <linux/module.h>
+#include <linux/sysctl.h>
 
-#include <asm/pgtable.h>
-#include <asm/uaccess.h>
 #include <asm/system.h>
-#include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/mmu.h>
-#include <asm/cache.h>
 #include <asm/cputable.h>
 #include <asm/time.h>
-#include <asm/iSeries/LparData.h>
 #include <asm/iSeries/HvCall.h>
 #include <asm/iSeries/ItLpQueue.h>
+#include <asm/plpar_wrappers.h>
 
-extern long cede_processor(void);
-extern long poll_pending(void);
 extern void power4_idle(void);
 
-int (*idle_loop)(void);
+static int (*idle_loop)(void);
 
 #ifdef CONFIG_PPC_ISERIES
-unsigned long maxYieldTime = 0;
-unsigned long minYieldTime = 0xffffffffffffffffUL;
+static unsigned long maxYieldTime = 0;
+static unsigned long minYieldTime = 0xffffffffffffffffUL;
 
 static void yield_shared_processor(void)
 {
@@ -80,7 +69,7 @@ static void yield_shared_processor(void)
 	process_iSeries_events();
 }
 
-int iSeries_idle(void)
+static int iSeries_idle(void)
 {
 	struct paca_struct *lpaca;
 	long oldval;
@@ -91,13 +80,10 @@ int iSeries_idle(void)
 	CTRL = mfspr(CTRLF);
 	CTRL &= ~RUNLATCH;
 	mtspr(CTRLT, CTRL);
-#if 0
-	init_idle();	
-#endif
 
 	lpaca = get_paca();
 
-	for (;;) {
+	while (1) {
 		if (lpaca->lppaca.xSharedProc) {
 			if (ItLpQueue_isLpIntPending(lpaca->lpqueue_ptr))
 				process_iSeries_events();
@@ -125,13 +111,16 @@ int iSeries_idle(void)
 
 		schedule();
 	}
+
 	return 0;
 }
-#endif
 
-int default_idle(void)
+#else
+
+static int default_idle(void)
 {
 	long oldval;
+	unsigned int cpu = smp_processor_id();
 
 	while (1) {
 		oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
@@ -139,9 +128,14 @@ int default_idle(void)
 		if (!oldval) {
 			set_thread_flag(TIF_POLLING_NRFLAG);
 
-			while (!need_resched()) {
+			while (!need_resched() && !cpu_is_offline(cpu)) {
 				barrier();
+				/*
+				 * Go into low thread priority and possibly
+				 * low power mode.
+				 */
 				HMT_low();
+				HMT_very_low();
 			}
 
 			HMT_medium();
@@ -151,8 +145,7 @@ int default_idle(void)
 		}
 
 		schedule();
-		if (cpu_is_offline(smp_processor_id()) &&
-				system_state == SYSTEM_RUNNING)
+		if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
 			cpu_die();
 	}
 
@@ -169,12 +162,15 @@ int dedicated_idle(void)
 	struct paca_struct *lpaca = get_paca(), *ppaca;
 	unsigned long start_snooze;
 	unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay);
+	unsigned int cpu = smp_processor_id();
 
-	ppaca = &paca[smp_processor_id() ^ 1];
+	ppaca = &paca[cpu ^ 1];
 
 	while (1) {
-		/* Indicate to the HV that we are idle.  Now would be
-		 * a good time to find other work to dispatch. */
+		/*
+		 * Indicate to the HV that we are idle. Now would be
+		 * a good time to find other work to dispatch.
+		 */
 		lpaca->lppaca.xIdle = 1;
 
 		oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
@@ -182,42 +178,32 @@ int dedicated_idle(void)
 			set_thread_flag(TIF_POLLING_NRFLAG);
 			start_snooze = __get_tb() +
 				*smt_snooze_delay * tb_ticks_per_usec;
-			while (!need_resched()) {
-				/* need_resched could be 1 or 0 at this 
-				 * point.  If it is 0, set it to 0, so
-				 * an IPI/Prod is sent.  If it is 1, keep
-				 * it that way & schedule work.
+			while (!need_resched() && !cpu_is_offline(cpu)) {
+				/*
+				 * Go into low thread priority and possibly
+				 * low power mode.
 				 */
+				HMT_low();
+				HMT_very_low();
+
 				if (*smt_snooze_delay == 0 ||
-				    __get_tb() < start_snooze) {
-					HMT_low(); /* Low thread priority */
+				    __get_tb() < start_snooze)
 					continue;
-				}
 
-				HMT_very_low(); /* Low power mode */
+				HMT_medium();
 
-				/* If the SMT mode is system controlled & the 
-				 * partner thread is doing work, switch into
-				 * ST mode.
-				 */
-				if((naca->smt_state == SMT_DYNAMIC) &&
-				   (!(ppaca->lppaca.xIdle))) {
-					/* Indicate we are no longer polling for
-					 * work, and then clear need_resched.  If
-					 * need_resched was 1, set it back to 1
-					 * and schedule work
+				if (!(ppaca->lppaca.xIdle)) {
+					local_irq_disable();
+
+					/*
+					 * We are about to sleep the thread
+					 * and so wont be polling any
+					 * more.
 					 */
 					clear_thread_flag(TIF_POLLING_NRFLAG);
-					oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED);
-					if(oldval == 1) {
-						set_need_resched();
-						break;
-					}
 
-					/* DRENG: Go HMT_medium here ? */
-					local_irq_disable(); 
-
-					/* SMT dynamic mode.  Cede will result 
+					/*
+					 * SMT dynamic mode. Cede will result
 					 * in this thread going dormant, if the
 					 * partner thread is still doing work.
 					 * Thread wakes up if partner goes idle,
@@ -225,15 +211,21 @@ int dedicated_idle(void)
 					 * occurs.  Returning from the cede
 					 * enables external interrupts.
 					 */
-					cede_processor();
+					if (!need_resched())
+						cede_processor();
+					else
+						local_irq_enable();
 				} else {
-					/* Give the HV an opportunity at the
+					/*
+					 * Give the HV an opportunity at the
 					 * processor, since we are not doing
 					 * any work.
 					 */
 					poll_pending();
 				}
 			}
+
+			clear_thread_flag(TIF_POLLING_NRFLAG);
 		} else {
 			set_need_resched();
 		}
@@ -241,57 +233,60 @@ int dedicated_idle(void)
 		HMT_medium();
 		lpaca->lppaca.xIdle = 0;
 		schedule();
-		if (cpu_is_offline(smp_processor_id()) &&
-				system_state == SYSTEM_RUNNING)
+		if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING)
 			cpu_die();
 	}
 	return 0;
 }
 
-int shared_idle(void)
+static int shared_idle(void)
 {
 	struct paca_struct *lpaca = get_paca();
+	unsigned int cpu = smp_processor_id();
 
 	while (1) {
-		if (cpu_is_offline(smp_processor_id()) &&
-				system_state == SYSTEM_RUNNING)
-			cpu_die();
-
-		/* Indicate to the HV that we are idle.  Now would be
-		 * a good time to find other work to dispatch. */
+		/*
+		 * Indicate to the HV that we are idle. Now would be
+		 * a good time to find other work to dispatch.
+		 */
 		lpaca->lppaca.xIdle = 1;
 
-		if (!need_resched()) {
-			local_irq_disable(); 
-			
-			/* 
+		while (!need_resched() && !cpu_is_offline(cpu)) {
+			local_irq_disable();
+
+			/*
 			 * Yield the processor to the hypervisor.  We return if
 			 * an external interrupt occurs (which are driven prior
 			 * to returning here) or if a prod occurs from another 
-			 * processor.  When returning here, external interrupts 
+			 * processor. When returning here, external interrupts
 			 * are enabled.
+			 *
+			 * Check need_resched() again with interrupts disabled
+			 * to avoid a race.
 			 */
-			cede_processor();
+			if (!need_resched())
+				cede_processor();
+			else
+				local_irq_enable();
 		}
 
 		HMT_medium();
 		lpaca->lppaca.xIdle = 0;
 		schedule();
+		if (cpu_is_offline(smp_processor_id()) &&
+		    system_state == SYSTEM_RUNNING)
+			cpu_die();
 	}
 
 	return 0;
 }
-#endif
 
-int cpu_idle(void)
-{
-	idle_loop();
-	return 0; 
-}
+#endif /* CONFIG_PPC_PSERIES */
 
-int native_idle(void)
+static int native_idle(void)
 {
 	while(1) {
+		/* check CPU type here */
 		if (!need_resched())
 			power4_idle();
 		if (need_resched())
@@ -300,33 +295,80 @@ int native_idle(void)
 	return 0;
 }
 
+#endif /* CONFIG_PPC_ISERIES */
+
+int cpu_idle(void)
+{
+	idle_loop();
+	return 0;
+}
+
+int powersave_nap;
+
+#ifdef CONFIG_SYSCTL
+/*
+ * Register the sysctl to set/clear powersave_nap.
+ */
+static ctl_table powersave_nap_ctl_table[]={
+	{
+		.ctl_name	= KERN_PPC_POWERSAVE_NAP,
+		.procname	= "powersave-nap",
+		.data		= &powersave_nap,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{ 0, },
+};
+static ctl_table powersave_nap_sysctl_root[] = {
+	{ 1, "kernel", NULL, 0, 0755, powersave_nap_ctl_table, },
+ 	{ 0,},
+};
+
+static int __init
+register_powersave_nap_sysctl(void)
+{
+	register_sysctl_table(powersave_nap_sysctl_root, 0);
+
+	return 0;
+}
+__initcall(register_powersave_nap_sysctl);
+#endif
+
 int idle_setup(void)
 {
+	/*
+	 * Move that junk to each platform specific file, eventually define
+	 * a pSeries_idle for shared processor stuff
+	 */
 #ifdef CONFIG_PPC_ISERIES
 	idle_loop = iSeries_idle;
+	return 1;
 #else
+	idle_loop = default_idle;
+#endif
+#ifdef CONFIG_PPC_PSERIES
 	if (systemcfg->platform & PLATFORM_PSERIES) {
 		if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
 			if (get_paca()->lppaca.xSharedProc) {
-				printk("idle = shared_idle\n");
+				printk(KERN_INFO "Using shared processor idle loop\n");
 				idle_loop = shared_idle;
 			} else {
-				printk("idle = dedicated_idle\n");
+				printk(KERN_INFO "Using dedicated idle loop\n");
 				idle_loop = dedicated_idle;
 			}
 		} else {
-			printk("idle = default_idle\n");
+			printk(KERN_INFO "Using default idle loop\n");
 			idle_loop = default_idle;
 		}
-	} else if (systemcfg->platform == PLATFORM_POWERMAC) {
-		printk("idle = native_idle\n");
+	}
+#endif /* CONFIG_PPC_PSERIES */
+#ifdef CONFIG_PPC_PMAC
+	if (systemcfg->platform == PLATFORM_POWERMAC) {
+		printk(KERN_INFO "Using native/NAP idle loop\n");
 		idle_loop = native_idle;
-	} else {
-		printk("idle_setup: unknown platform, use default_idle\n");
-		idle_loop = default_idle;
 	}
-#endif
+#endif /* CONFIG_PPC_PMAC */
 
 	return 1;
 }
-
diff --git a/arch/ppc64/kernel/idle_power4.S b/arch/ppc64/kernel/idle_power4.S
index fb983069d..97e4a2655 100644
--- a/arch/ppc64/kernel/idle_power4.S
+++ b/arch/ppc64/kernel/idle_power4.S
@@ -46,7 +46,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
 	/* Now check if user or arch enabled NAP mode */
 	LOADBASE(r3,powersave_nap)
 	lwz	r4,powersave_nap@l(r3)
-	cmpi	0,r4,0
+	cmpwi	0,r4,0
 	beqlr
 
 	/* Clear MSR:EE */
diff --git a/arch/ppc64/kernel/ioctl32.c b/arch/ppc64/kernel/ioctl32.c
index 40ba4c17e..94d1a05b7 100644
--- a/arch/ppc64/kernel/ioctl32.c
+++ b/arch/ppc64/kernel/ioctl32.c
@@ -22,9 +22,7 @@
 
 #define INCLUDES
 #include "compat_ioctl.c"
-#include <linux/ncp_fs.h>
 #include <linux/syscalls.h>
-#include <asm/ppc32.h>
 
 #define CODE
 #include "compat_ioctl.c"
diff --git a/arch/ppc64/kernel/iommu.c b/arch/ppc64/kernel/iommu.c
index 5cac0d240..d5d64d1d7 100644
--- a/arch/ppc64/kernel/iommu.c
+++ b/arch/ppc64/kernel/iommu.c
@@ -229,7 +229,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
 		struct scatterlist *sglist, int nelems,
 		enum dma_data_direction direction)
 {
-	dma_addr_t dma_next, dma_addr;
+	dma_addr_t dma_next = 0, dma_addr;
 	unsigned long flags;
 	struct scatterlist *s, *outs, *segstart;
 	int outcount;
diff --git a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c
index 846168746..3ebe47340 100644
--- a/arch/ppc64/kernel/irq.c
+++ b/arch/ppc64/kernel/irq.c
@@ -41,6 +41,7 @@
 #include <linux/proc_fs.h>
 #include <linux/random.h>
 #include <linux/kallsyms.h>
+#include <linux/profile.h>
 
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
@@ -362,14 +363,16 @@ skip:
 int handle_irq_event(int irq, struct pt_regs *regs, struct irqaction *action)
 {
 	int status = 0;
-	int retval = 0;
+	int ret, retval = 0;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
-		status |= action->flags;
-		retval |= action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
+		retval |= ret;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
@@ -586,13 +589,13 @@ void do_IRQ(struct pt_regs *regs)
 	irq_enter();
 
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
-	/* Debugging check for stack overflow: is there less than 4KB free? */
+	/* Debugging check for stack overflow: is there less than 2KB free? */
 	{
 		long sp;
 
 		sp = __get_SP() & (THREAD_SIZE-1);
 
-		if (unlikely(sp < (sizeof(struct thread_info) + 4096))) {
+		if (unlikely(sp < (sizeof(struct thread_info) + 2048))) {
 			printk("do_IRQ: stack overflow: %ld\n",
 				sp - sizeof(struct thread_info));
 			dump_stack();
@@ -629,13 +632,13 @@ void do_IRQ(struct pt_regs *regs)
 	irq_enter();
 
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
-	/* Debugging check for stack overflow: is there less than 4KB free? */
+	/* Debugging check for stack overflow: is there less than 2KB free? */
 	{
 		long sp;
 
 		sp = __get_SP() & (THREAD_SIZE-1);
 
-		if (unlikely(sp < (sizeof(struct thread_info) + 4096))) {
+		if (unlikely(sp < (sizeof(struct thread_info) + 2048))) {
 			printk("do_IRQ: stack overflow: %ld\n",
 				sp - sizeof(struct thread_info));
 			dump_stack();
@@ -674,6 +677,8 @@ unsigned int probe_irq_mask(unsigned long irqs)
 	return 0;
 }
 
+EXPORT_SYMBOL(probe_irq_mask);
+
 void __init init_IRQ(void)
 {
 	static int once = 0;
@@ -757,44 +762,6 @@ out:
 	return ret;
 }
 
-static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
-	if (count - len < 2)
-		return -EINVAL;
-	len += sprintf(page + len, "\n");
-	return len;
-}
-
-static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer,
-					unsigned long count, void *data)
-{
-	cpumask_t *mask = (cpumask_t *)data;
-	unsigned long full_count = count, err;
-	cpumask_t new_value;
-
-	err = cpumask_parse(buffer, count, new_value);
-	if (err)
-		return err;
-
-	*mask = new_value;
-
-#ifdef CONFIG_PPC_ISERIES
-	{
-		unsigned i;
-		for (i=0; i<NR_CPUS; ++i) {
-			if ( paca[i].prof_buffer && cpu_isset(i, new_value) )
-				paca[i].prof_enabled = 1;
-			else
-				paca[i].prof_enabled = 0;
-		}
-	}
-#endif
-
-	return full_count;
-}
-
 #define MAX_NAMELEN 10
 
 static void register_irq_proc (unsigned int irq)
@@ -824,26 +791,15 @@ static void register_irq_proc (unsigned int irq)
 	smp_affinity_entry[irq] = entry;
 }
 
-unsigned long prof_cpu_mask = -1;
-
 void init_irq_proc (void)
 {
-	struct proc_dir_entry *entry;
 	int i;
 
 	/* create /proc/irq */
 	root_irq_dir = proc_mkdir("irq", NULL);
 
 	/* create /proc/irq/prof_cpu_mask */
-	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
-
-	if (!entry)
-		return;
-
-	entry->nlink = 1;
-	entry->data = (void *)&prof_cpu_mask;
-	entry->read_proc = prof_cpu_mask_read_proc;
-	entry->write_proc = prof_cpu_mask_write_proc;
+	create_prof_cpu_mask(root_irq_dir);
 
 	/*
 	 * Create entries for all existing IRQs.
@@ -977,7 +933,7 @@ void irq_ctx_init(void)
 	struct thread_info *tp;
 	int i;
 
-	for (i = 0; i < NR_CPUS; i++) {
+	for_each_cpu(i) {
 		memset((void *)softirq_ctx[i], 0, THREAD_SIZE);
 		tp = softirq_ctx[i];
 		tp->cpu = i;
diff --git a/arch/ppc64/kernel/lmb.c b/arch/ppc64/kernel/lmb.c
index c2e320635..56a26eec0 100644
--- a/arch/ppc64/kernel/lmb.c
+++ b/arch/ppc64/kernel/lmb.c
@@ -20,7 +20,44 @@
 #include <asm/abs_addr.h>
 #include <asm/bitops.h>
 
-struct lmb lmb __initdata;
+struct lmb lmb;
+
+#undef DEBUG
+
+void lmb_dump_all(void)
+{
+#ifdef DEBUG
+	unsigned long i;
+	struct lmb *_lmb  = &lmb;
+
+	udbg_printf("lmb_dump_all:\n");
+	udbg_printf("    memory.cnt		  = 0x%lx\n",
+		    _lmb->memory.cnt);
+	udbg_printf("    memory.size		  = 0x%lx\n",
+		    _lmb->memory.size);
+	for (i=0; i < _lmb->memory.cnt ;i++) {
+		udbg_printf("    memory.region[0x%x].base       = 0x%lx\n",
+			    i, _lmb->memory.region[i].base);
+		udbg_printf("		      .physbase = 0x%lx\n",
+			    _lmb->memory.region[i].physbase);
+		udbg_printf("		      .size     = 0x%lx\n",
+			    _lmb->memory.region[i].size);
+	}
+
+	udbg_printf("\n    reserved.cnt	  = 0x%lx\n",
+		    _lmb->reserved.cnt);
+	udbg_printf("    reserved.size	  = 0x%lx\n",
+		    _lmb->reserved.size);
+	for (i=0; i < _lmb->reserved.cnt ;i++) {
+		udbg_printf("    reserved.region[0x%x].base       = 0x%lx\n",
+			    i, _lmb->reserved.region[i].base);
+		udbg_printf("		      .physbase = 0x%lx\n",
+			    _lmb->reserved.region[i].physbase);
+		udbg_printf("		      .size     = 0x%lx\n",
+			    _lmb->reserved.region[i].size);
+	}
+#endif /* DEBUG */
+}
 
 static unsigned long __init
 lmb_addrs_overlap(unsigned long base1, unsigned long size1,
@@ -71,8 +108,7 @@ lmb_coalesce_regions(struct lmb_region *rgn, unsigned long r1, unsigned long r2)
 void __init
 lmb_init(void)
 {
-	unsigned long offset = reloc_offset();
-	struct lmb *_lmb = PTRRELOC(&lmb);
+	struct lmb *_lmb = &lmb;
 
 	/* Create a dummy zero size LMB which will get coalesced away later.
 	 * This simplifies the lmb_add() code below...
@@ -94,8 +130,7 @@ lmb_analyze(void)
 	unsigned long i;
 	unsigned long mem_size = 0;
 	unsigned long size_mask = 0;
-	unsigned long offset = reloc_offset();
-	struct lmb *_lmb = PTRRELOC(&lmb);
+	struct lmb *_lmb = &lmb;
 #ifdef CONFIG_MSCHUNKS
 	unsigned long physbase = 0;
 #endif
@@ -178,8 +213,7 @@ lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size)
 long __init
 lmb_add(unsigned long base, unsigned long size)
 {
-	unsigned long offset = reloc_offset();
-	struct lmb *_lmb = PTRRELOC(&lmb);
+	struct lmb *_lmb = &lmb;
 	struct lmb_region *_rgn = &(_lmb->memory);
 
 	/* On pSeries LPAR systems, the first LMB is our RMO region. */
@@ -193,8 +227,7 @@ lmb_add(unsigned long base, unsigned long size)
 long __init
 lmb_reserve(unsigned long base, unsigned long size)
 {
-	unsigned long offset = reloc_offset();
-	struct lmb *_lmb = PTRRELOC(&lmb);
+	struct lmb *_lmb = &lmb;
 	struct lmb_region *_rgn = &(_lmb->reserved);
 
 	return lmb_add_region(_rgn, base, size);
@@ -227,8 +260,7 @@ lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr)
 {
 	long i, j;
 	unsigned long base = 0;
-	unsigned long offset = reloc_offset();
-	struct lmb *_lmb = PTRRELOC(&lmb);
+	struct lmb *_lmb = &lmb;
 	struct lmb_region *_mem = &(_lmb->memory);
 	struct lmb_region *_rsv = &(_lmb->reserved);
 
@@ -263,8 +295,7 @@ lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr)
 unsigned long __init
 lmb_phys_mem_size(void)
 {
-	unsigned long offset = reloc_offset();
-	struct lmb *_lmb = PTRRELOC(&lmb);
+	struct lmb *_lmb = &lmb;
 #ifdef CONFIG_MSCHUNKS
 	return _lmb->memory.size;
 #else
@@ -282,8 +313,7 @@ lmb_phys_mem_size(void)
 unsigned long __init
 lmb_end_of_DRAM(void)
 {
-	unsigned long offset = reloc_offset();
-	struct lmb *_lmb = PTRRELOC(&lmb);
+	struct lmb *_lmb = &lmb;
 	struct lmb_region *_mem = &(_lmb->memory);
 	int idx = _mem->cnt - 1;
 
@@ -300,8 +330,7 @@ unsigned long __init
 lmb_abs_to_phys(unsigned long aa)
 {
 	unsigned long i, pa = aa;
-	unsigned long offset = reloc_offset();
-	struct lmb *_lmb = PTRRELOC(&lmb);
+	struct lmb *_lmb = &lmb;
 	struct lmb_region *_mem = &(_lmb->memory);
 
 	for (i=0; i < _mem->cnt; i++) {
diff --git a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c
index d729105e5..f7ac3f742 100644
--- a/arch/ppc64/kernel/lparcfg.c
+++ b/arch/ppc64/kernel/lparcfg.c
@@ -34,31 +34,37 @@
 #include <asm/rtas.h>
 #include <asm/system.h>
 
-#define MODULE_VERS "1.3"
+#define MODULE_VERS "1.4"
 #define MODULE_NAME "lparcfg"
 
 /* #define LPARCFG_DEBUG */
 
 /* find a better place for this function... */
-void log_plpar_hcall_return(unsigned long rc,char * tag)
+void log_plpar_hcall_return(unsigned long rc, char *tag)
 {
-	if (rc ==0 ) /* success, return */
+	if (rc == 0)		/* success, return */
 		return;
 /* check for null tag ? */
 	if (rc == H_Hardware)
-		printk(KERN_INFO "plpar-hcall (%s) failed with hardware fault\n",tag);
+		printk(KERN_INFO
+		       "plpar-hcall (%s) failed with hardware fault\n", tag);
 	else if (rc == H_Function)
-		printk(KERN_INFO "plpar-hcall (%s) failed; function not allowed\n",tag);
+		printk(KERN_INFO
+		       "plpar-hcall (%s) failed; function not allowed\n", tag);
 	else if (rc == H_Authority)
-		printk(KERN_INFO "plpar-hcall (%s) failed; not authorized to this function\n",tag);
+		printk(KERN_INFO
+		       "plpar-hcall (%s) failed; not authorized to this function\n",
+		       tag);
 	else if (rc == H_Parameter)
-		printk(KERN_INFO "plpar-hcall (%s) failed; Bad parameter(s)\n",tag);
+		printk(KERN_INFO "plpar-hcall (%s) failed; Bad parameter(s)\n",
+		       tag);
 	else
-		printk(KERN_INFO "plpar-hcall (%s) failed with unexpected rc(0x%lx)\n",tag,rc);
+		printk(KERN_INFO
+		       "plpar-hcall (%s) failed with unexpected rc(0x%lx)\n",
+		       tag, rc);
 
 }
 
-
 static struct proc_dir_entry *proc_ppc64_lparcfg;
 #define LPARCFG_BUFF_SIZE 4096
 
@@ -78,59 +84,60 @@ static int lparcfg_data(struct seq_file *m, void *v)
 
 	shared = (int)(lpaca->lppaca_ptr->xSharedProc);
 	seq_printf(m, "serial_number=%c%c%c%c%c%c%c\n",
-		      e2a(xItExtVpdPanel.mfgID[2]),
-		      e2a(xItExtVpdPanel.mfgID[3]),
-		      e2a(xItExtVpdPanel.systemSerial[1]),
-		      e2a(xItExtVpdPanel.systemSerial[2]),
-		      e2a(xItExtVpdPanel.systemSerial[3]),
-		      e2a(xItExtVpdPanel.systemSerial[4]),
-		      e2a(xItExtVpdPanel.systemSerial[5])); 
+		   e2a(xItExtVpdPanel.mfgID[2]),
+		   e2a(xItExtVpdPanel.mfgID[3]),
+		   e2a(xItExtVpdPanel.systemSerial[1]),
+		   e2a(xItExtVpdPanel.systemSerial[2]),
+		   e2a(xItExtVpdPanel.systemSerial[3]),
+		   e2a(xItExtVpdPanel.systemSerial[4]),
+		   e2a(xItExtVpdPanel.systemSerial[5]));
 
 	seq_printf(m, "system_type=%c%c%c%c\n",
-		      e2a(xItExtVpdPanel.machineType[0]),
-		      e2a(xItExtVpdPanel.machineType[1]),
-		      e2a(xItExtVpdPanel.machineType[2]),
-		      e2a(xItExtVpdPanel.machineType[3])); 
+		   e2a(xItExtVpdPanel.machineType[0]),
+		   e2a(xItExtVpdPanel.machineType[1]),
+		   e2a(xItExtVpdPanel.machineType[2]),
+		   e2a(xItExtVpdPanel.machineType[3]));
 
-	lp_index = HvLpConfig_getLpIndex(); 
+	lp_index = HvLpConfig_getLpIndex();
 	seq_printf(m, "partition_id=%d\n", (int)lp_index);
 
 	seq_printf(m, "system_active_processors=%d\n",
-		      (int)HvLpConfig_getSystemPhysicalProcessors()); 
+		   (int)HvLpConfig_getSystemPhysicalProcessors());
 
 	seq_printf(m, "system_potential_processors=%d\n",
-		      (int)HvLpConfig_getSystemPhysicalProcessors()); 
+		   (int)HvLpConfig_getSystemPhysicalProcessors());
 
-	processors = (int)HvLpConfig_getPhysicalProcessors(); 
+	processors = (int)HvLpConfig_getPhysicalProcessors();
 	seq_printf(m, "partition_active_processors=%d\n", processors);
 
-	max_processors = (int)HvLpConfig_getMaxPhysicalProcessors(); 
+	max_processors = (int)HvLpConfig_getMaxPhysicalProcessors();
 	seq_printf(m, "partition_potential_processors=%d\n", max_processors);
 
-	if(shared) {
-		entitled_capacity = HvLpConfig_getSharedProcUnits(); 
-		max_entitled_capacity = HvLpConfig_getMaxSharedProcUnits(); 
+	if (shared) {
+		entitled_capacity = HvLpConfig_getSharedProcUnits();
+		max_entitled_capacity = HvLpConfig_getMaxSharedProcUnits();
 	} else {
-		entitled_capacity = processors * 100; 
-		max_entitled_capacity = max_processors * 100; 
+		entitled_capacity = processors * 100;
+		max_entitled_capacity = max_processors * 100;
 	}
 	seq_printf(m, "partition_entitled_capacity=%d\n", entitled_capacity);
 
 	seq_printf(m, "partition_max_entitled_capacity=%d\n",
-		      max_entitled_capacity);
+		   max_entitled_capacity);
 
-	if(shared) {
-		pool_id = HvLpConfig_getSharedPoolIndex(); 
+	if (shared) {
+		pool_id = HvLpConfig_getSharedPoolIndex();
 		seq_printf(m, "pool=%d\n", (int)pool_id);
 		seq_printf(m, "pool_capacity=%d\n",
-		    (int)(HvLpConfig_getNumProcsInSharedPool(pool_id)*100));
+			   (int)(HvLpConfig_getNumProcsInSharedPool(pool_id) *
+				 100));
 	}
 
 	seq_printf(m, "shared_processor_mode=%d\n", shared);
 
 	return 0;
 }
-#endif /* CONFIG_PPC_ISERIES */
+#endif				/* CONFIG_PPC_ISERIES */
 
 #ifdef CONFIG_PPC_PSERIES
 /* 
@@ -158,11 +165,13 @@ static int lparcfg_data(struct seq_file *m, void *v)
  *                  XXXX  - Processors active on platform. 
  */
 static unsigned int h_get_ppp(unsigned long *entitled,
-		unsigned long  *unallocated, unsigned long *aggregation,
-		unsigned long *resource)
+			      unsigned long *unallocated,
+			      unsigned long *aggregation,
+			      unsigned long *resource)
 {
 	unsigned long rc;
-	rc = plpar_hcall_4out(H_GET_PPP,0,0,0,0,entitled,unallocated,aggregation,resource);
+	rc = plpar_hcall_4out(H_GET_PPP, 0, 0, 0, 0, entitled, unallocated,
+			      aggregation, resource);
 
 	log_plpar_hcall_return(rc, "H_GET_PPP");
 
@@ -185,7 +194,7 @@ static unsigned long get_purr(void);
  */
 static unsigned long get_purr()
 {
-	unsigned long sum_purr=0;
+	unsigned long sum_purr = 0;
 	return sum_purr;
 }
 
@@ -202,7 +211,7 @@ static void parse_system_parameter_string(struct seq_file *m)
 {
 	int call_status;
 
-	char * local_buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
+	char *local_buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
 	if (!local_buffer) {
 		printk(KERN_ERR "%s %s kmalloc failure at line %d \n",
 		       __FILE__, __FUNCTION__, __LINE__);
@@ -219,22 +228,23 @@ static void parse_system_parameter_string(struct seq_file *m)
 	spin_unlock(&rtas_data_buf_lock);
 
 	if (call_status != 0) {
-		printk(KERN_INFO "%s %s Error calling get-system-parameter (0x%x)\n",
+		printk(KERN_INFO
+		       "%s %s Error calling get-system-parameter (0x%x)\n",
 		       __FILE__, __FUNCTION__, call_status);
 	} else {
 		int splpar_strlen;
 		int idx, w_idx;
-		char * workbuffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
+		char *workbuffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
 		if (!workbuffer) {
-			printk(KERN_ERR "%s %s kmalloc failure at line %d \n",__FILE__,__FUNCTION__,__LINE__);
+			printk(KERN_ERR "%s %s kmalloc failure at line %d \n",
+			       __FILE__, __FUNCTION__, __LINE__);
 			return;
 		}
-
 #ifdef LPARCFG_DEBUG
 		printk(KERN_INFO "success calling get-system-parameter \n");
 #endif
 		splpar_strlen = local_buffer[0] * 16 + local_buffer[1];
-		local_buffer += 2; /* step over strlen value */
+		local_buffer += 2;	/* step over strlen value */
 
 		memset(workbuffer, 0, SPLPAR_MAXLENGTH);
 		w_idx = 0;
@@ -253,13 +263,15 @@ static void parse_system_parameter_string(struct seq_file *m)
 				w_idx = 0;
 			} else if (local_buffer[idx] == '=') {
 				/* code here to replace workbuffer contents
-				 with different keyword strings */
-				if (0 == strcmp(workbuffer,"MaxEntCap")) {
-					strcpy(workbuffer, "partition_max_entitled_capacity");
+				   with different keyword strings */
+				if (0 == strcmp(workbuffer, "MaxEntCap")) {
+					strcpy(workbuffer,
+					       "partition_max_entitled_capacity");
 					w_idx = strlen(workbuffer);
 				}
-				if (0 == strcmp(workbuffer,"MaxPlatProcs")) {
-					strcpy(workbuffer, "system_potential_processors");
+				if (0 == strcmp(workbuffer, "MaxPlatProcs")) {
+					strcpy(workbuffer,
+					       "system_potential_processors");
 					w_idx = strlen(workbuffer);
 				}
 			}
@@ -283,7 +295,7 @@ static int lparcfg_count_active_processors(void)
 
 	while ((cpus_dn = of_find_node_by_type(cpus_dn, "cpu"))) {
 #ifdef LPARCFG_DEBUG
-		printk(KERN_ERR "cpus_dn %p \n",cpus_dn);
+		printk(KERN_ERR "cpus_dn %p \n", cpus_dn);
 #endif
 		count++;
 	}
@@ -292,7 +304,8 @@ static int lparcfg_count_active_processors(void)
 
 static int lparcfg_data(struct seq_file *m, void *v)
 {
-	int system_active_processors;
+	int partition_potential_processors;
+	int partition_active_processors;
 	struct device_node *rootdn;
 	const char *model = "";
 	const char *system_id = "";
@@ -305,12 +318,11 @@ static int lparcfg_data(struct seq_file *m, void *v)
 		model = get_property(rootdn, "model", NULL);
 		system_id = get_property(rootdn, "system-id", NULL);
 		lp_index_ptr = (unsigned int *)
-			get_property(rootdn, "ibm,partition-no", NULL);
+		    get_property(rootdn, "ibm,partition-no", NULL);
 		if (lp_index_ptr)
 			lp_index = *lp_index_ptr;
 	}
 
-
 	seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS);
 
 	seq_printf(m, "serial_number=%s\n", system_id);
@@ -323,11 +335,13 @@ static int lparcfg_data(struct seq_file *m, void *v)
 	lrdrp = (int *)get_property(rtas_node, "ibm,lrdr-capacity", NULL);
 
 	if (lrdrp == NULL) {
-		system_active_processors = systemcfg->processorCount;
+		partition_potential_processors = systemcfg->processorCount;
 	} else {
-		system_active_processors = *(lrdrp + 4);
+		partition_potential_processors = *(lrdrp + 4);
 	}
 
+	partition_active_processors = lparcfg_count_active_processors();
+
 	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
 		unsigned long h_entitled, h_unallocated;
 		unsigned long h_aggregation, h_resource;
@@ -342,71 +356,69 @@ static int lparcfg_data(struct seq_file *m, void *v)
 		seq_printf(m, "R6=0x%lx\n", h_aggregation);
 		seq_printf(m, "R7=0x%lx\n", h_resource);
 
-		h_pic(&pool_idle_time, &pool_procs);
-
 		purr = get_purr();
 
 		/* this call handles the ibm,get-system-parameter contents */
 		parse_system_parameter_string(m);
 
-		seq_printf(m, "partition_entitled_capacity=%ld\n",
-			      h_entitled);
-
-		seq_printf(m, "pool=%ld\n",
-			      (h_aggregation >> 0*8) & 0xffff);
+		seq_printf(m, "partition_entitled_capacity=%ld\n", h_entitled);
 
-		seq_printf(m, "group=%ld\n",
-			      (h_aggregation >> 2*8) & 0xffff);
+		seq_printf(m, "group=%ld\n", (h_aggregation >> 2 * 8) & 0xffff);
 
 		seq_printf(m, "system_active_processors=%ld\n",
-			      (h_resource >> 0*8) & 0xffff);
+			   (h_resource >> 0 * 8) & 0xffff);
+
+		/* pool related entries are apropriate for shared configs */
+		if (paca[0].lppaca.xSharedProc) {
 
-		seq_printf(m, "pool_capacity=%ld\n",
-			      (h_resource >> 2*8) & 0xffff);
+			h_pic(&pool_idle_time, &pool_procs);
+
+			seq_printf(m, "pool=%ld\n",
+				   (h_aggregation >> 0 * 8) & 0xffff);
+
+			/* report pool_capacity in percentage */
+			seq_printf(m, "pool_capacity=%ld\n",
+				   ((h_resource >> 2 * 8) & 0xffff) * 100);
+
+			seq_printf(m, "pool_idle_time=%ld\n", pool_idle_time);
+
+			seq_printf(m, "pool_num_procs=%ld\n", pool_procs);
+		}
 
 		seq_printf(m, "unallocated_capacity_weight=%ld\n",
-			      (h_resource >> 4*8) & 0xFF);
+			   (h_resource >> 4 * 8) & 0xFF);
 
 		seq_printf(m, "capacity_weight=%ld\n",
-			      (h_resource >> 5*8) & 0xFF);
-
-		seq_printf(m, "capped=%ld\n",
-			      (h_resource >> 6*8) & 0x01);
+			   (h_resource >> 5 * 8) & 0xFF);
 
-		seq_printf(m, "unallocated_capacity=%ld\n",
-			      h_unallocated);
+		seq_printf(m, "capped=%ld\n", (h_resource >> 6 * 8) & 0x01);
 
-		seq_printf(m, "pool_idle_time=%ld\n",
-			      pool_idle_time);
+		seq_printf(m, "unallocated_capacity=%ld\n", h_unallocated);
 
-		seq_printf(m, "pool_num_procs=%ld\n",
-			      pool_procs);
+		seq_printf(m, "purr=%ld\n", purr);
 
-		seq_printf(m, "purr=%ld\n",
-			      purr);
+	} else {		/* non SPLPAR case */
 
-	} else /* non SPLPAR case */ {
 		seq_printf(m, "system_active_processors=%d\n",
-			      system_active_processors);
+			   partition_potential_processors);
 
 		seq_printf(m, "system_potential_processors=%d\n",
-			      system_active_processors);
+			   partition_potential_processors);
 
 		seq_printf(m, "partition_max_entitled_capacity=%d\n",
-			      100*system_active_processors);
+			   partition_potential_processors * 100);
 
 		seq_printf(m, "partition_entitled_capacity=%d\n",
-			      system_active_processors*100);
+			   partition_active_processors * 100);
 	}
 
 	seq_printf(m, "partition_active_processors=%d\n",
-			(int) lparcfg_count_active_processors());
+		   partition_active_processors);
 
 	seq_printf(m, "partition_potential_processors=%d\n",
-			system_active_processors);
+		   partition_potential_processors);
 
-	seq_printf(m, "shared_processor_mode=%d\n",
-			paca[0].lppaca.xSharedProc);
+	seq_printf(m, "shared_processor_mode=%d\n", paca[0].lppaca.xSharedProc);
 
 	return 0;
 }
@@ -421,14 +433,15 @@ static int lparcfg_data(struct seq_file *m, void *v)
  * This function should be invoked only on systems with
  * FW_FEATURE_SPLPAR.
  */
-static ssize_t lparcfg_write(struct file *file, const char __user *buf, size_t count, loff_t *off)
+static ssize_t lparcfg_write(struct file *file, const char __user * buf,
+			     size_t count, loff_t * off)
 {
 	char *kbuf;
 	char *tmp;
 	u64 new_entitled, *new_entitled_ptr = &new_entitled;
 	u8 new_weight, *new_weight_ptr = &new_weight;
 
-	unsigned long current_entitled;    /* parameters for h_get_ppp */
+	unsigned long current_entitled;	/* parameters for h_get_ppp */
 	unsigned long dummy;
 	unsigned long resource;
 	u8 current_weight;
@@ -453,13 +466,13 @@ static ssize_t lparcfg_write(struct file *file, const char __user *buf, size_t c
 
 	if (!strcmp(kbuf, "partition_entitled_capacity")) {
 		char *endp;
-		*new_entitled_ptr = (u64)simple_strtoul(tmp, &endp, 10);
+		*new_entitled_ptr = (u64) simple_strtoul(tmp, &endp, 10);
 		if (endp == tmp)
 			goto out;
 		new_weight_ptr = &current_weight;
 	} else if (!strcmp(kbuf, "capacity_weight")) {
 		char *endp;
-		*new_weight_ptr = (u8)simple_strtoul(tmp, &endp, 10);
+		*new_weight_ptr = (u8) simple_strtoul(tmp, &endp, 10);
 		if (endp == tmp)
 			goto out;
 		new_entitled_ptr = &current_entitled;
@@ -473,7 +486,7 @@ static ssize_t lparcfg_write(struct file *file, const char __user *buf, size_t c
 		goto out;
 	}
 
-	current_weight = (resource>>5*8)&0xFF;
+	current_weight = (resource >> 5 * 8) & 0xFF;
 
 	pr_debug("%s: current_entitled = %lu, current_weight = %lu\n",
 		 __FUNCTION__, current_entitled, current_weight);
@@ -498,23 +511,23 @@ static ssize_t lparcfg_write(struct file *file, const char __user *buf, size_t c
 		retval = -EIO;
 	}
 
-out:
+      out:
 	kfree(kbuf);
 	return retval;
 }
 
-#endif /* CONFIG_PPC_PSERIES */
+#endif				/* CONFIG_PPC_PSERIES */
 
-static int lparcfg_open(struct inode * inode, struct file * file)
+static int lparcfg_open(struct inode *inode, struct file *file)
 {
-	return single_open(file,lparcfg_data,NULL);
+	return single_open(file, lparcfg_data, NULL);
 }
 
 struct file_operations lparcfg_fops = {
-	owner:		THIS_MODULE,
-	read:		seq_read,
-	open:		lparcfg_open,
-	release:	single_release,
+      owner:THIS_MODULE,
+      read:seq_read,
+      open:lparcfg_open,
+      release:single_release,
 };
 
 int __init lparcfg_init(void)
@@ -533,7 +546,8 @@ int __init lparcfg_init(void)
 		ent->proc_fops = &lparcfg_fops;
 		ent->data = kmalloc(LPARCFG_BUFF_SIZE, GFP_KERNEL);
 		if (!ent->data) {
-			printk(KERN_ERR "Failed to allocate buffer for lparcfg\n");
+			printk(KERN_ERR
+			       "Failed to allocate buffer for lparcfg\n");
 			remove_proc_entry("lparcfg", ent->parent);
 			return -ENOMEM;
 		}
@@ -550,7 +564,7 @@ void __exit lparcfg_cleanup(void)
 {
 	if (proc_ppc64_lparcfg) {
 		if (proc_ppc64_lparcfg->data) {
-		    kfree(proc_ppc64_lparcfg->data);
+			kfree(proc_ppc64_lparcfg->data);
 		}
 		remove_proc_entry("lparcfg", proc_ppc64_lparcfg->parent);
 	}
diff --git a/arch/ppc64/kernel/mf_proc.c b/arch/ppc64/kernel/mf_proc.c
index 3ac36a5b9..f98f35569 100644
--- a/arch/ppc64/kernel/mf_proc.c
+++ b/arch/ppc64/kernel/mf_proc.c
@@ -167,22 +167,29 @@ static int proc_mf_change_cmdline(struct file *file, const char *buffer,
 	return count;			
 }
 
-static int proc_mf_change_vmlinux(struct file *file, const char *buffer,
-		unsigned long count, void *data)
+static ssize_t proc_mf_change_vmlinux(struct file *file, 
+				      const char __user *buf,
+				      size_t count, loff_t *ppos)
 {
+	struct inode * inode = file->f_dentry->d_inode;
+	struct proc_dir_entry * dp = PDE(inode);
 	int rc;
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
 
-	rc = mf_setVmlinuxChunk(buffer, count, file->f_pos, (u64)data);
+	rc = mf_setVmlinuxChunk(buf, count, *ppos, (u64)dp->data);
 	if (rc < 0)
 		return rc;
 
-	file->f_pos += count;
+	*ppos += count;
 
 	return count;			
 }
 
+static struct file_operations proc_vmlinux_operations = {
+	.write		= proc_mf_change_vmlinux,
+};
+
 static int __init mf_proc_init(void)
 {
 	struct proc_dir_entry *mf_proc_root;
@@ -218,20 +225,7 @@ static int __init mf_proc_init(void)
 			return 1;
 		ent->nlink = 1;
 		ent->data = (void *)(long)i;
-#if 0
-		if (i == 3) {
-			/*
-			 * if we had a 'D' vmlinux entry, it would only
-			 * be readable.
-			 */
-			ent->read_proc = proc_mf_dump_vmlinux;
-			ent->write_proc = NULL;
-		} else
-#endif
-		{
-			ent->write_proc = proc_mf_change_vmlinux;
-			ent->read_proc = NULL;
-		}
+		ent->proc_fops = &proc_vmlinux_operations;
 	}
 
 	ent = create_proc_entry("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root);
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
index e0857d90d..88e700266 100644
--- a/arch/ppc64/kernel/misc.S
+++ b/arch/ppc64/kernel/misc.S
@@ -127,6 +127,47 @@ _GLOBAL(call_handle_irq_event)
 	blr
 #endif /* CONFIG_IRQSTACKS */
 
+	/*
+ * To be called by C code which needs to do some operations with MMU
+ * disabled. Note that interrupts have to be disabled by the caller
+ * prior to calling us. The code called _MUST_ be in the RMO of course
+ * and part of the linear mapping as we don't attempt to translate the
+ * stack pointer at all. The function is called with the stack switched
+ * to this CPU emergency stack
+ *
+ * prototype is void *call_with_mmu_off(void *func, void *data);
+ *
+ * the called function is expected to be of the form
+ *
+ * void *called(void *data); 
+ */
+_GLOBAL(call_with_mmu_off)
+	mflr	r0			/* get link, save it on stackframe */
+	std	r0,16(r1)
+	mr	r1,r5			/* save old stack ptr */
+	ld	r1,PACAEMERGSP(r13)	/* get emerg. stack */
+	subi	r1,r1,STACK_FRAME_OVERHEAD
+	std	r0,16(r1)		/* save link on emerg. stack */
+	std	r5,0(r1)		/* save old stack ptr in backchain */
+	ld	r3,0(r3)		/* get to real function ptr (assume same TOC) */
+	bl	2f			/* we need LR to return, continue at label 2 */
+
+	ld	r0,16(r1)		/* we return here from the call, get LR and */
+	ld	r1,0(r1)		/* .. old stack ptr */
+	mtspr	SPRN_SRR0,r0		/* and get back to virtual mode with these */
+	mfmsr	r4
+	ori	r4,r4,MSR_IR|MSR_DR
+	mtspr	SPRN_SRR1,r4
+	rfid
+
+2:	mtspr	SPRN_SRR0,r3		/* coming from above, enter real mode */
+	mr	r3,r4			/* get parameter */
+	mfmsr	r0
+	ori	r0,r0,MSR_IR|MSR_DR
+	xori	r0,r0,MSR_IR|MSR_DR
+	mtspr	SPRN_SRR1,r0
+	rfid
+	
 /*
  * Flush instruction cache.
  */
@@ -454,23 +495,6 @@ _GLOBAL(_outsl_ns)
 	sync
 	blr	
 
-_GLOBAL(abs)
-	cmpi	0,r3,0
-	bge	10f
-	neg	r3,r3
-10:	blr
-
-_GLOBAL(_get_PVR)
-	mfspr	r3,PVR
-	blr
-
-_GLOBAL(_get_PIR)
-	mfspr	r3,PIR
-	blr
-
-_GLOBAL(_get_HID0)
-	mfspr	r3,HID0
-	blr
 
 _GLOBAL(cvt_fd)
 	lfd	0,0(r5)		/* load up fpscr value */
@@ -567,6 +591,69 @@ _GLOBAL(do_cpu_ftr_fixups)
 	isync
 	b	1b
 
+#ifdef CONFIG_PPC_PMAC
+/*
+ * Do an IO access in real mode
+ */
+_GLOBAL(real_readb)
+	mfmsr	r7
+	ori	r0,r7,MSR_DR
+	xori	r0,r0,MSR_DR
+	sync
+	mtmsrd	r0
+	sync
+	isync
+	mfspr	r6,SPRN_HID4
+	rldicl	r5,r6,32,0
+	ori	r5,r5,0x100
+	rldicl	r5,r5,32,0
+	sync
+	mtspr	SPRN_HID4,r5
+	isync
+	slbia
+	isync
+	lbz	r3,0(r3)
+	sync
+	mtspr	SPRN_HID4,r6
+	isync
+	slbia
+	isync
+	mtmsrd	r7
+	sync
+	isync
+	blr
+
+	/*
+ * Do an IO access in real mode
+ */
+_GLOBAL(real_writeb)
+	mfmsr	r7
+	ori	r0,r7,MSR_DR
+	xori	r0,r0,MSR_DR
+	sync
+	mtmsrd	r0
+	sync
+	isync
+	mfspr	r6,SPRN_HID4
+	rldicl	r5,r6,32,0
+	ori	r5,r5,0x100
+	rldicl	r5,r5,32,0
+	sync
+	mtspr	SPRN_HID4,r5
+	isync
+	slbia
+	isync
+	stb	r3,0(r4)
+	sync
+	mtspr	SPRN_HID4,r6
+	isync
+	slbia
+	isync
+	mtmsrd	r7
+	sync
+	isync
+	blr
+#endif /* CONFIG_PPC_PMAC */
 
 /*
  * Create a kernel thread
@@ -583,7 +670,7 @@ _GLOBAL(kernel_thread)
 	li	r4,0		/* new sp (unused) */
 	li	r0,__NR_clone
 	sc
-	cmpi	0,r3,0		/* parent or child? */
+	cmpdi	0,r3,0		/* parent or child? */
 	bne	1f		/* return if parent */
 	li	r0,0
 	stdu	r0,-STACK_FRAME_OVERHEAD(r1)
@@ -600,7 +687,7 @@ _GLOBAL(kernel_thread)
 	ld	r30,-16(r1)
 	blr
 
-#ifdef CONFIG_PPC_ISERIES	/* hack hack hack */
+#ifndef CONFIG_PPC_PSERIES	/* hack hack hack */
 #define ppc_rtas	sys_ni_syscall
 #endif
 
@@ -866,9 +953,9 @@ _GLOBAL(sys_call_table32)
 	.llong .sys_ni_syscall		/* 256 reserved for sys_debug_setcontext */
 	.llong .sys_vserver
 	.llong .sys_ni_syscall		/* 258 reserved for new sys_remap_file_pages */
-	.llong .sys_ni_syscall		/* 259 reserved for new sys_mbind */
-	.llong .sys_ni_syscall		/* 260 reserved for new sys_get_mempolicy */
-	.llong .sys_ni_syscall		/* 261 reserved for new sys_set_mempolicy */
+	.llong .compat_mbind
+	.llong .compat_get_mempolicy	/* 260 */
+	.llong .compat_set_mempolicy
 	.llong .compat_sys_mq_open
 	.llong .sys_mq_unlink
 	.llong .compat_sys_mq_timedsend
@@ -1138,9 +1225,9 @@ _GLOBAL(sys_call_table)
 	.llong .sys_ni_syscall		/* 256 reserved for sys_debug_setcontext */
 	.llong .sys_ni_syscall		/* 257 reserved for vserver */
 	.llong .sys_ni_syscall		/* 258 reserved for new sys_remap_file_pages */
-	.llong .sys_ni_syscall		/* 259 reserved for new sys_mbind */
-	.llong .sys_ni_syscall		/* 260 reserved for new sys_get_mempolicy */
-	.llong .sys_ni_syscall		/* 261 reserved for new sys_set_mempolicy */
+	.llong .sys_mbind
+	.llong .sys_get_mempolicy	/* 260 */
+	.llong .sys_set_mempolicy
 	.llong .sys_mq_open
 	.llong .sys_mq_unlink
 	.llong .sys_mq_timedsend
diff --git a/arch/ppc64/kernel/nvram.c b/arch/ppc64/kernel/nvram.c
index 89d6a0ad7..49ddf5e09 100644
--- a/arch/ppc64/kernel/nvram.c
+++ b/arch/ppc64/kernel/nvram.c
@@ -340,7 +340,7 @@ static int nvram_create_os_partition(void)
 	struct list_head * p;
 	struct nvram_partition * part;
 	struct nvram_partition * new_part = NULL;
-	struct nvram_partition * free_part;
+	struct nvram_partition * free_part = NULL;
 	int seq_init[2] = { 0, 0 };
 	loff_t tmp_index;
 	long size = 0;
@@ -603,6 +603,7 @@ void __exit nvram_cleanup(void)
 }
 
 
+#ifdef CONFIG_PPC_PSERIES
 
 /* nvram_write_error_log
  *
@@ -727,6 +728,7 @@ int nvram_clear_error_log()
 	return 0;
 }
 
+#endif /* CONFIG_PPC_PSERIES */
 
 module_init(nvram_init);
 module_exit(nvram_cleanup);
diff --git a/arch/ppc64/kernel/open_pic.c b/arch/ppc64/kernel/open_pic.c
index f0afedd20..656a493bf 100644
--- a/arch/ppc64/kernel/open_pic.c
+++ b/arch/ppc64/kernel/open_pic.c
@@ -362,7 +362,6 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
 	find_ISUs();
 
 	/* Initialize timer interrupts */
-	ppc64_boot_msg(0x21, "OpenPic Timer");
 	for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
 		/* Disabled, Priority 0 */
 		openpic_inittimer(i, 0, openpic_vec_timer+i);
@@ -372,7 +371,6 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
 
 #ifdef CONFIG_SMP
 	/* Initialize IPI interrupts */
-	ppc64_boot_msg(0x22, "OpenPic IPI");
 	openpic_test_broken_IPI();
 	for (i = 0; i < OPENPIC_NUM_IPI; i++) {
 		/* Disabled, Priority 10..13 */
@@ -384,8 +382,6 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
 #endif
 
 	/* Initialize external interrupts */
-	ppc64_boot_msg(0x23, "OpenPic Ext");
-
 	openpic_set_priority(0xf);
 
 	/* SIOint (8259 cascade) is special */
@@ -420,7 +416,6 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
 		irq_desc[i].handler = &open_pic;
 
 	/* Initialize the spurious interrupt */
-	ppc64_boot_msg(0x24, "OpenPic Spurious");
 	openpic_set_spurious(openpic_vec_spurious);
 
 	openpic_set_priority(0);
diff --git a/arch/ppc64/kernel/open_pic_u3.c b/arch/ppc64/kernel/open_pic_u3.c
index 4f9832a3b..42376756c 100644
--- a/arch/ppc64/kernel/open_pic_u3.c
+++ b/arch/ppc64/kernel/open_pic_u3.c
@@ -344,5 +344,5 @@ void __init openpic2_init(int offset)
 	openpic2_set_priority(0);
 	openpic2_disable_8259_pass_through();
 
-	ppc64_boot_msg(0x25, "OpenPic2 Done");
+	ppc64_boot_msg(0x25, "OpenPic U3 Done");
 }
diff --git a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c
index 91749173f..abbbe2823 100644
--- a/arch/ppc64/kernel/pSeries_iommu.c
+++ b/arch/ppc64/kernel/pSeries_iommu.c
@@ -42,6 +42,7 @@
 #include <asm/pci-bridge.h>
 #include <asm/machdep.h>
 #include <asm/abs_addr.h>
+#include <asm/plpar_wrappers.h>
 #include "pci.h"
 
 
@@ -88,9 +89,153 @@ static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages)
 }
 
 
+static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
+				long npages, unsigned long uaddr,
+				enum dma_data_direction direction)
+{
+	u64 rc;
+	union tce_entry tce;
+
+	tce.te_word = 0;
+	tce.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT;
+	tce.te_rdwr = 1;
+	if (direction != DMA_TO_DEVICE)
+		tce.te_pciwr = 1;
+
+	while (npages--) {
+		rc = plpar_tce_put((u64)tbl->it_index, 
+				   (u64)tcenum << 12, 
+				   tce.te_word );
+		
+		if (rc && printk_ratelimit()) {
+			printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
+			printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
+			printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
+			printk("\ttce val = 0x%lx\n", tce.te_word );
+			show_stack(current, (unsigned long *)__get_SP());
+		}
+			
+		tcenum++;
+		tce.te_rpn++;
+	}
+}
+
+DEFINE_PER_CPU(void *, tce_page) = NULL;
+
+static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
+				     long npages, unsigned long uaddr,
+				     enum dma_data_direction direction)
+{
+	u64 rc;
+	union tce_entry tce, *tcep;
+	long l, limit;
+
+	if (npages == 1)
+		return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
+					   direction);
+
+	tcep = __get_cpu_var(tce_page);
+
+	/* This is safe to do since interrupts are off when we're called
+	 * from iommu_alloc{,_sg}()
+	 */
+	if (!tcep) {
+		tcep = (void *)__get_free_page(GFP_ATOMIC);
+		/* If allocation fails, fall back to the loop implementation */
+		if (!tcep)
+			return tce_build_pSeriesLP(tbl, tcenum, npages,
+						   uaddr, direction);
+		__get_cpu_var(tce_page) = tcep;
+	}
+
+	tce.te_word = 0;
+	tce.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT;
+	tce.te_rdwr = 1;
+	if (direction != DMA_TO_DEVICE)
+		tce.te_pciwr = 1;
+
+	/* We can map max one pageful of TCEs at a time */
+	do {
+		/*
+		 * Set up the page with TCE data, looping through and setting
+		 * the values.
+		 */
+		limit = min_t(long, npages, PAGE_SIZE/sizeof(union tce_entry));
+
+		for (l = 0; l < limit; l++) {
+			tcep[l] = tce;
+			tce.te_rpn++;
+		}
+
+		rc = plpar_tce_put_indirect((u64)tbl->it_index,
+					    (u64)tcenum << 12,
+					    (u64)virt_to_abs(tcep),
+					    limit);
+
+		npages -= limit;
+		tcenum += limit;
+	} while (npages > 0 && !rc);
+
+	if (rc && printk_ratelimit()) {
+		printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
+		printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
+		printk("\tnpages  = 0x%lx\n", (u64)npages);
+		printk("\ttce[0] val = 0x%lx\n", tcep[0].te_word);
+		show_stack(current, (unsigned long *)__get_SP());
+	}
+}
+
+static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
+{
+	u64 rc;
+	union tce_entry tce;
+
+	tce.te_word = 0;
+
+	while (npages--) {
+		rc = plpar_tce_put((u64)tbl->it_index,
+				   (u64)tcenum << 12,
+				   tce.te_word);
+
+		if (rc && printk_ratelimit()) {
+			printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
+			printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
+			printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
+			printk("\ttce val = 0x%lx\n", tce.te_word );
+			show_stack(current, (unsigned long *)__get_SP());
+		}
+
+		tcenum++;
+	}
+}
+
+
+static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
+{
+	u64 rc;
+	union tce_entry tce;
+
+	tce.te_word = 0;
+
+	rc = plpar_tce_stuff((u64)tbl->it_index,
+			   (u64)tcenum << 12,
+			   tce.te_word,
+			   npages);
+
+	if (rc && printk_ratelimit()) {
+		printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n");
+		printk("\trc      = %ld\n", rc);
+		printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
+		printk("\tnpages  = 0x%lx\n", (u64)npages);
+		printk("\ttce val = 0x%lx\n", tce.te_word );
+		show_stack(current, (unsigned long *)__get_SP());
+	}
+}
+
+
 static void iommu_buses_init(void)
 {
-	struct pci_controller* phb;
+	struct pci_controller *phb, *tmp;
 	struct device_node *dn, *first_dn;
 	int num_slots, num_slots_ilog2;
 	int first_phb = 1;
@@ -106,10 +251,10 @@ static void iommu_buses_init(void)
 	else
 		tcetable_ilog2 = 22;
 
-	/* XXX Should we be using pci_root_buses instead?  -ojn 
+	/* XXX Should we be using pci_root_buses instead?  -ojn
 	 */
 
-	for (phb=hose_head; phb; phb=phb->next) {
+	list_for_each_entry_safe(phb, tmp, &hose_list, list_node) {
 		first_dn = ((struct device_node *)phb->arch_data)->child;
 
 		/* Carve 2GB into the largest dma_window_size possible */
@@ -166,24 +311,25 @@ static void iommu_table_setparms(struct pci_controller *phb,
 				 struct device_node *dn,
 				 struct iommu_table *tbl) 
 {
-	phandle node;
-	unsigned long i;
-	struct of_tce_table *oft;
-
-	node = ((struct device_node *)(phb->arch_data))->node;
+	struct device_node *node;
+	unsigned long *basep;
+	unsigned int *sizep;
 
-	oft = NULL;
+	node = (struct device_node *)phb->arch_data;
 
-	for (i=0; of_tce_table[i].node; i++)
-		if(of_tce_table[i].node == node) {
-			oft = &of_tce_table[i];
-			break;
-		}
-
-	if (!oft)
-		panic("PCI_DMA: iommu_table_setparms: Can't find phb named '%s' in of_tce_table\n", dn->full_name);
-
-	memset((void *)oft->base, 0, oft->size);
+	if (get_property(node, "linux,has-tce-table", NULL) == NULL) {
+		printk(KERN_ERR "PCI_DMA: iommu_table_setparms: %s has no tce table !\n",
+		      dn->full_name);
+		return;
+	}
+	basep = (unsigned long *)get_property(node, "linux,tce-base", NULL);
+	sizep = (unsigned int *)get_property(node, "linux,tce-size", NULL);
+	if (basep == NULL || sizep == NULL) {
+		printk(KERN_ERR "PCI_DMA: iommu_table_setparms: %s has missing tce"
+		       " entries !\n", dn->full_name);
+		return;
+	}
+	memset((void *)(*basep), 0, *sizep);
 
 	tbl->it_busno = phb->bus->number;
 	
@@ -207,10 +353,11 @@ static void iommu_table_setparms(struct pci_controller *phb,
 	if (phb->dma_window_base_cur > (1 << 19))
 		panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); 
 	
-	tbl->it_base = oft->base;
+	tbl->it_base = *basep;
 	tbl->it_index = 0;
 	tbl->it_entrysize = sizeof(union tce_entry);
 	tbl->it_blocksize = 16;
+	tbl->it_type = TCE_PCI;
 }
 
 /*
@@ -246,6 +393,7 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb,
 	tbl->it_index  = dma_window[0];
 	tbl->it_entrysize = sizeof(union tce_entry);
 	tbl->it_blocksize  = 16;
+	tbl->it_type = TCE_PCI;
 }
 
 
@@ -293,8 +441,16 @@ void iommu_setup_pSeries(void)
 /* These are called very early. */
 void tce_init_pSeries(void)
 {
-	ppc_md.tce_build = tce_build_pSeries;
-	ppc_md.tce_free  = tce_free_pSeries;
+	if (!(systemcfg->platform & PLATFORM_LPAR)) {
+		ppc_md.tce_build = tce_build_pSeries;
+		ppc_md.tce_free  = tce_free_pSeries;
+	} else if (cur_cpu_spec->firmware_features & FW_FEATURE_MULTITCE) {
+		ppc_md.tce_build = tce_buildmulti_pSeriesLP;
+		ppc_md.tce_free	 = tce_freemulti_pSeriesLP;
+	} else {
+		ppc_md.tce_build = tce_build_pSeriesLP;
+		ppc_md.tce_free	 = tce_free_pSeriesLP;
+	}
 
 	pci_iommu_init();
 }
diff --git a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c
index a44c33268..68eeb7a81 100644
--- a/arch/ppc64/kernel/pSeries_lpar.c
+++ b/arch/ppc64/kernel/pSeries_lpar.c
@@ -19,6 +19,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
+#define DEBUG
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/dma-mapping.h>
@@ -34,10 +36,16 @@
 #include <asm/naca.h>
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
-#include <asm/hvcall.h>
 #include <asm/prom.h>
 #include <asm/abs_addr.h>
 #include <asm/cputable.h>
+#include <asm/plpar_wrappers.h>
+
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
 
 /* in pSeries_hvCall.S */
 EXPORT_SYMBOL(plpar_hcall);
@@ -45,146 +53,9 @@ EXPORT_SYMBOL(plpar_hcall_4out);
 EXPORT_SYMBOL(plpar_hcall_norets);
 EXPORT_SYMBOL(plpar_hcall_8arg_2ret);
 
-long poll_pending(void)
-{
-	unsigned long dummy;
-	return plpar_hcall(H_POLL_PENDING, 0, 0, 0, 0,
-			   &dummy, &dummy, &dummy);
-}
-
-long prod_processor(void)
-{
-	plpar_hcall_norets(H_PROD);
-	return(0); 
-}
-
-long cede_processor(void)
-{
-	plpar_hcall_norets(H_CEDE);
-	return(0); 
-}
-
-long register_vpa(unsigned long flags, unsigned long proc, unsigned long vpa)
-{
-	plpar_hcall_norets(H_REGISTER_VPA, flags, proc, vpa);
-	return(0); 
-}
-
-long plpar_pte_remove(unsigned long flags,
-		      unsigned long ptex,
-		      unsigned long avpn,
-		      unsigned long *old_pteh_ret, unsigned long *old_ptel_ret)
-{
-	unsigned long dummy;
-	return plpar_hcall(H_REMOVE, flags, ptex, avpn, 0,
-			   old_pteh_ret, old_ptel_ret, &dummy);
-}
-
-long plpar_pte_read(unsigned long flags,
-		    unsigned long ptex,
-		    unsigned long *old_pteh_ret, unsigned long *old_ptel_ret)
-{
-	unsigned long dummy;
-	return plpar_hcall(H_READ, flags, ptex, 0, 0,
-			   old_pteh_ret, old_ptel_ret, &dummy);
-}
-
-long plpar_pte_protect(unsigned long flags,
-		       unsigned long ptex,
-		       unsigned long avpn)
-{
-	return plpar_hcall_norets(H_PROTECT, flags, ptex, avpn);
-}
-
-long plpar_tce_get(unsigned long liobn,
-		   unsigned long ioba,
-		   unsigned long *tce_ret)
-{
-	unsigned long dummy;
-	return plpar_hcall(H_GET_TCE, liobn, ioba, 0, 0,
-			   tce_ret, &dummy, &dummy);
-}
-
-long plpar_tce_put(unsigned long liobn,
-		   unsigned long ioba,
-		   unsigned long tceval)
-{
-	return plpar_hcall_norets(H_PUT_TCE, liobn, ioba, tceval);
-}
+extern void fw_feature_init(void);
+extern void pSeries_find_serial_port(void);
 
-long plpar_get_term_char(unsigned long termno,
-			 unsigned long *len_ret,
-			 char *buf_ret)
-{
-	unsigned long *lbuf = (unsigned long *)buf_ret;  /* ToDo: alignment? */
-	return plpar_hcall(H_GET_TERM_CHAR, termno, 0, 0, 0,
-			   len_ret, lbuf+0, lbuf+1);
-}
-
-long plpar_put_term_char(unsigned long termno,
-			 unsigned long len,
-			 const char *buffer)
-{
-	unsigned long *lbuf = (unsigned long *)buffer;  /* ToDo: alignment? */
-	return plpar_hcall_norets(H_PUT_TERM_CHAR, termno, len, lbuf[0],
-				  lbuf[1]);
-}
-
-static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
-		long npages, unsigned long uaddr,
-		enum dma_data_direction direction)
-{
-	u64 rc;
-	union tce_entry tce;
-
-	tce.te_word = 0;
-	tce.te_rpn = (virt_to_abs(uaddr)) >> PAGE_SHIFT;
-	tce.te_rdwr = 1;
-	if (direction != DMA_TO_DEVICE)
-		tce.te_pciwr = 1;
-
-	while (npages--) {
-		rc = plpar_tce_put((u64)tbl->it_index, 
-				   (u64)tcenum << 12, 
-				   tce.te_word );
-		
-		if (rc && printk_ratelimit()) {
-			printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
-			printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
-			printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
-			printk("\ttce val = 0x%lx\n", tce.te_word );
-			show_stack(current, (unsigned long *)__get_SP());
-		}
-			
-		tcenum++;
-		tce.te_rpn++;
-	}
-}
-
-static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
-{
-	u64 rc;
-	union tce_entry tce;
-
-	tce.te_word = 0;
-
-	while (npages--) {
-		rc = plpar_tce_put((u64)tbl->it_index, 
-				   (u64)tcenum << 12,
-				   tce.te_word );
-		
-		if (rc && printk_ratelimit()) {
-			printk("tce_free_pSeriesLP: plpar_tce_put failed\n");
-			printk("\trc      = %ld\n", rc);
-			printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
-			printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
-			printk("\ttce val = 0x%lx\n", tce.te_word );
-			show_stack(current, (unsigned long *)__get_SP());
-		}
-		
-		tcenum++;
-	}
-}
 
 int vtermno;	/* virtual terminal# for udbg  */
 
@@ -249,8 +120,19 @@ static unsigned char udbg_getcLP(void)
 	}
 }
 
+/* call this from early_init() for a working debug console on
+ * vterm capable LPAR machines
+ */
+void udbg_init_debug_lpar(void)
+{
+	vtermno = 0;
+	ppc_md.udbg_putc = udbg_putcLP;
+	ppc_md.udbg_getc = udbg_getcLP;
+	ppc_md.udbg_getc_poll = udbg_getc_pollLP;
+}
+
 /* returns 0 if couldn't find or use /chosen/stdout as console */
-static int find_udbg_vterm(void)
+int find_udbg_vterm(void)
 {
 	struct device_node *stdout_node;
 	u32 *termno;
@@ -258,15 +140,14 @@ static int find_udbg_vterm(void)
 	int found = 0;
 
 	/* find the boot console from /chosen/stdout */
-	if (!of_stdout_device) {
-		printk(KERN_WARNING "couldn't get path from /chosen/stdout!\n");
-		return found;
-	}
-	stdout_node = of_find_node_by_path(of_stdout_device);
-	if (!stdout_node) {
-		printk(KERN_WARNING "couldn't find node from /chosen/stdout\n");
-		return found;
-	}
+	if (!of_chosen)
+		return 0;
+	name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
+	if (name == NULL)
+		return 0;
+	stdout_node = of_find_node_by_path(name);
+	if (!stdout_node)
+		return 0;
 
 	/* now we have the stdout node; figure out what type of device it is. */
 	name = (char *)get_property(stdout_node, "name", NULL);
@@ -288,15 +169,17 @@ static int find_udbg_vterm(void)
 		} else {
 			/* XXX implement udbg_putcLP_vtty for hvterm-protocol1 case */
 			printk(KERN_WARNING "%s doesn't speak hvterm1; "
-					"can't print udbg messages\n", of_stdout_device);
+					"can't print udbg messages\n",
+			       stdout_node->full_name);
 		}
 	} else if (strncmp(name, "serial", 6)) {
 		/* XXX fix ISA serial console */
 		printk(KERN_WARNING "serial stdout on LPAR ('%s')! "
-				"can't print udbg messages\n", of_stdout_device);
+				"can't print udbg messages\n",
+		       stdout_node->full_name);
 	} else {
 		printk(KERN_WARNING "don't know how to print to stdout '%s'\n",
-				of_stdout_device);
+		       stdout_node->full_name);
 	}
 
 out:
@@ -304,35 +187,6 @@ out:
 	return found;
 }
 
-void pSeries_lpar_mm_init(void);
-
-/* This is called early in setup.c.
- * Use it to setup page table ppc_md stuff as well as udbg.
- */
-void pSeriesLP_init_early(void)
-{
-	pSeries_lpar_mm_init();
-
-	tce_init_pSeries();
-
-	ppc_md.tce_build = tce_build_pSeriesLP;
-	ppc_md.tce_free	 = tce_free_pSeriesLP;
-
-	pci_iommu_init();
-
-#ifdef CONFIG_SMP
-	smp_init_pSeries();
-#endif
-
-	/* The keyboard is not useful in the LPAR environment.
-	 * Leave all the ppc_md keyboard interfaces NULL.
-	 */
-
-	if (0 == find_udbg_vterm()) {
-		printk(KERN_WARNING
-			"can't use stdout; can't print early debug messages.\n");
-	}
-}
 
 long pSeries_lpar_hpte_insert(unsigned long hpte_group,
 			      unsigned long va, unsigned long prpn,
@@ -377,7 +231,7 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group,
 	lpar_rc = plpar_hcall(H_ENTER, flags, hpte_group, lhpte.dw0.dword0,
 			      lhpte.dw1.dword1, &slot, &dummy0, &dummy1);
 
-	if (lpar_rc == H_PTEG_Full)
+	if (unlikely(lpar_rc == H_PTEG_Full))
 		return -1;
 
 	/*
@@ -385,7 +239,7 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group,
 	 * will fail. However we must catch the failure in hash_page
 	 * or we will loop forever, so return -2 in this case.
 	 */
-	if (lpar_rc != H_Success)
+	if (unlikely(lpar_rc != H_Success))
 		return -2;
 
 	/* Because of iSeries, we have to pass down the secondary
@@ -415,9 +269,7 @@ static long pSeries_lpar_hpte_remove(unsigned long hpte_group)
 		if (lpar_rc == H_Success)
 			return i;
 
-		if (lpar_rc != H_Not_Found)
-			panic("Bad return code from pte remove rc = %lx\n",
-			      lpar_rc);
+		BUG_ON(lpar_rc != H_Not_Found);
 
 		slot_offset++;
 		slot_offset &= 0x7;
@@ -426,6 +278,18 @@ static long pSeries_lpar_hpte_remove(unsigned long hpte_group)
 	return -1;
 }
 
+static void pSeries_lpar_hptab_clear(void)
+{
+	unsigned long size_bytes = 1UL << naca->pftSize;
+	unsigned long hpte_count = size_bytes >> 4;
+	unsigned long dummy1, dummy2;
+	int i;
+
+	/* TODO: Use bulk call */
+	for (i = 0; i < hpte_count; i++)
+		plpar_pte_remove(0, i, 0, &dummy1, &dummy2);
+}
+
 /*
  * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
  * the low 3 bits of flags happen to line up.  So no transform is needed.
@@ -447,8 +311,7 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot, unsigned long newpp,
 	if (lpar_rc == H_Not_Found)
 		return -1;
 
-	if (lpar_rc != H_Success)
-		panic("bad return code from pte protect rc = %lx\n", lpar_rc);
+	BUG_ON(lpar_rc != H_Success);
 
 	return 0;
 }
@@ -464,11 +327,10 @@ static unsigned long pSeries_lpar_hpte_getword0(unsigned long slot)
 	/* Do not need RPN to logical page translation */
 	/* No cross CEC PFT access                     */
 	flags = 0;
-	
+
 	lpar_rc = plpar_pte_read(flags, slot, &dword0, &dummy_word1);
 
-	if (lpar_rc != H_Success)
-		panic("Error on pte read in get_hpte0 rc = %lx\n", lpar_rc);
+	BUG_ON(lpar_rc != H_Success);
 
 	return dword0;
 }
@@ -519,15 +381,12 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
 	vpn = va >> PAGE_SHIFT;
 
 	slot = pSeries_lpar_hpte_find(vpn);
-	if (slot == -1)
-		panic("updateboltedpp: Could not find page to bolt\n");
+	BUG_ON(slot == -1);
 
 	flags = newpp & 3;
 	lpar_rc = plpar_pte_protect(flags, slot, 0);
 
-	if (lpar_rc != H_Success)
-		panic("Bad return code from pte bolted protect rc = %lx\n",
-		      lpar_rc); 
+	BUG_ON(lpar_rc != H_Success);
 }
 
 static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
@@ -546,8 +405,7 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
 	if (lpar_rc == H_Not_Found)
 		return;
 
-	if (lpar_rc != H_Success)
-		panic("Bad return code from invalidate rc = %lx\n", lpar_rc);
+	BUG_ON(lpar_rc != H_Success);
 }
 
 /*
@@ -560,18 +418,19 @@ void pSeries_lpar_flush_hash_range(unsigned long context, unsigned long number,
 	int i;
 	unsigned long flags;
 	struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
+	int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE);
 
-	if (!(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE))
+	if (lock_tlbie)
 		spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags);
 
 	for (i = 0; i < number; i++)
 		flush_hash_page(context, batch->addr[i], batch->pte[i], local);
 
-	if (!(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE))
+	if (lock_tlbie)
 		spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags);
 }
 
-void pSeries_lpar_mm_init(void)
+void hpte_init_lpar(void)
 {
 	ppc_md.hpte_invalidate	= pSeries_lpar_hpte_invalidate;
 	ppc_md.hpte_updatepp	= pSeries_lpar_hpte_updatepp;
@@ -579,4 +438,7 @@ void pSeries_lpar_mm_init(void)
 	ppc_md.hpte_insert	= pSeries_lpar_hpte_insert;
 	ppc_md.hpte_remove	= pSeries_lpar_hpte_remove;
 	ppc_md.flush_hash_range	= pSeries_lpar_flush_hash_range;
+	ppc_md.hpte_clear_all   = pSeries_lpar_hptab_clear;
+
+	htab_finish_init();
 }
diff --git a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c
index 92bc868f3..a9afded6c 100644
--- a/arch/ppc64/kernel/pSeries_pci.c
+++ b/arch/ppc64/kernel/pSeries_pci.c
@@ -45,12 +45,6 @@
 #include "open_pic.h"
 #include "pci.h"
 
-/* legal IO pages under MAX_ISA_PORT.  This is to ensure we don't touch
-   devices we don't have access to. */
-unsigned long io_page_mask;
-
-EXPORT_SYMBOL(io_page_mask);
-
 /* RTAS tokens */
 static int read_pci_config;
 static int write_pci_config;
@@ -68,7 +62,9 @@ static int rtas_read_config(struct device_node *dn, int where, int size, u32 *va
 	int ret;
 
 	if (!dn)
-		return -2;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if (where & (size - 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
 
 	addr = (dn->busno << 16) | (dn->devfn << 8) | where;
 	buid = dn->phb->buid;
@@ -79,7 +75,15 @@ static int rtas_read_config(struct device_node *dn, int where, int size, u32 *va
 		ret = rtas_call(read_pci_config, 2, 2, &returnval, addr, size);
 	}
 	*val = returnval;
-	return ret;
+
+	if (ret)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (returnval == EEH_IO_ERROR_VALUE(size)
+	    && eeh_dn_check_failure (dn, NULL))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return PCIBIOS_SUCCESSFUL;
 }
 
 static int rtas_pci_read_config(struct pci_bus *bus,
@@ -106,7 +110,9 @@ static int rtas_write_config(struct device_node *dn, int where, int size, u32 va
 	int ret;
 
 	if (!dn)
-		return -2;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if (where & (size - 1))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
 
 	addr = (dn->busno << 16) | (dn->devfn << 8) | where;
 	buid = dn->phb->buid;
@@ -115,7 +121,11 @@ static int rtas_write_config(struct device_node *dn, int where, int size, u32 va
 	} else {
 		ret = rtas_call(write_pci_config, 3, 1, NULL, addr, size, (ulong)val);
 	}
-	return ret;
+
+	if (ret)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return PCIBIOS_SUCCESSFUL;
 }
 
 static int rtas_pci_write_config(struct pci_bus *bus,
@@ -141,189 +151,6 @@ struct pci_ops rtas_pci_ops = {
 	rtas_pci_write_config
 };
 
-/******************************************************************
- * pci_read_irq_line
- *
- * Reads the Interrupt Pin to determine if interrupt is use by card.
- * If the interrupt is used, then gets the interrupt line from the 
- * openfirmware and sets it in the pci_dev and pci_config line.
- *
- ******************************************************************/
-int pci_read_irq_line(struct pci_dev *pci_dev)
-{
-	u8 intpin;
-	struct device_node *node;
-
-    	pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &intpin);
-
-	if (intpin == 0) {
-		PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Interrupt used by device.\n", pci_name(pci_dev));
-		return 0;	
-	}
-
-	node = pci_device_to_OF_node(pci_dev);
-	if (node == NULL) { 
-		PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s Device Node not found.\n",
-		       pci_name(pci_dev));
-		return -1;	
-	}
-	if (node->n_intrs == 0) 	{
-		PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Device OF interrupts defined.\n", pci_name(pci_dev));
-		return -1;	
-	}
-	pci_dev->irq = node->intrs[0].line;
-
-	if (s7a_workaround) {
-		if (pci_dev->irq > 16)
-			pci_dev->irq -= 3;
-	}
-
-	pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, pci_dev->irq);
-	
-	PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s pci_dev->irq = 0x%02X\n",
-	       pci_name(pci_dev), pci_dev->irq);
-	return 0;
-}
-EXPORT_SYMBOL(pci_read_irq_line);
-
-#define ISA_SPACE_MASK 0x1
-#define ISA_SPACE_IO 0x1
-
-static void pci_process_ISA_OF_ranges(struct device_node *isa_node,
-		                      unsigned long phb_io_base_phys,
-				      void * phb_io_base_virt)
-{
-	struct isa_range *range;
-	unsigned long pci_addr;
-	unsigned int isa_addr;
-	unsigned int size;
-	int rlen = 0;
-
-	range = (struct isa_range *) get_property(isa_node, "ranges", &rlen);
-	if (rlen < sizeof(struct isa_range)) {
-		printk(KERN_ERR "unexpected isa range size: %s\n", 
-				__FUNCTION__);
-		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);
-	}
-}
-
-static void __init pci_process_bridge_OF_ranges(struct pci_controller *hose,
-						struct device_node *dev,
-						int primary)
-{
-	unsigned int *ranges;
-	unsigned long size;
-	int rlen = 0;
-	int memno = 0;
-	struct resource *res;
-	int np, na = prom_n_addr_cells(dev);
-	unsigned long pci_addr, cpu_phys_addr;
-	struct device_node *isa_dn;
-
-	np = na + 5;
-
-	/* From "PCI Binding to 1275"
-	 * The ranges property is laid out as an array of elements,
-	 * each of which comprises:
-	 *   cells 0 - 2:	a PCI address
-	 *   cells 3 or 3+4:	a CPU physical address
-	 *			(size depending on dev->n_addr_cells)
-	 *   cells 4+5 or 5+6:	the size of the range
-	 */
-	rlen = 0;
-	hose->io_base_phys = 0;
-	ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
-	while ((rlen -= np * sizeof(unsigned int)) >= 0) {
-		res = NULL;
-		pci_addr = (unsigned long)ranges[1] << 32 | ranges[2];
-
-		cpu_phys_addr = ranges[3];
-		if (na == 2)
-			cpu_phys_addr = cpu_phys_addr << 32 | ranges[4];
-
-		size = (unsigned long)ranges[na+3] << 32 | ranges[na+4];
-
-		switch (ranges[0] >> 24) {
-		case 1:		/* I/O space */
-			hose->io_base_phys = cpu_phys_addr;
-			hose->io_base_virt = reserve_phb_iospace(size);
-			PPCDBG(PPCDBG_PHBINIT, 
-			       "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);
-                                        /* Allow all IO */
-                                        io_page_mask = -1;
-				}
-			}
-
-			res = &hose->io_resource;
-			res->flags = IORESOURCE_IO;
-			res->start = pci_addr;
-			res->start += (unsigned long)hose->io_base_virt -
-				pci_io_base;
-			break;
-		case 2:		/* memory space */
-			memno = 0;
-			while (memno < 3 && hose->mem_resources[memno].flags)
-				++memno;
-
-			if (memno == 0)
-				hose->pci_mem_offset = cpu_phys_addr - pci_addr;
-			if (memno < 3) {
-				res = &hose->mem_resources[memno];
-				res->flags = IORESOURCE_MEM;
-				res->start = cpu_phys_addr;
-			}
-			break;
-		}
-		if (res != NULL) {
-			res->name = dev->full_name;
-			res->end = res->start + size - 1;
-			res->parent = NULL;
-			res->sibling = NULL;
-			res->child = NULL;
-		}
-		ranges += np;
-	}
-}
-
 static void python_countermeasures(unsigned long addr)
 {
 	void *chip_regs;
@@ -481,7 +308,7 @@ unsigned long __init find_and_init_phbs(void)
 	struct pci_controller *phb;
 	unsigned int root_size_cells = 0;
 	unsigned int index;
-	unsigned int *opprop;
+	unsigned int *opprop = NULL;
 	struct device_node *root = of_find_node_by_path("/");
 
 	if (naca->interrupt_controller == IC_OPEN_PIC) {
@@ -519,9 +346,9 @@ unsigned long __init find_and_init_phbs(void)
 	return 0;
 }
 
+#if 0
 void pcibios_name_device(struct pci_dev *dev)
 {
-#if 0
 	struct device_node *dn;
 
 	/*
@@ -541,98 +368,9 @@ void pcibios_name_device(struct pci_dev *dev)
 			}
 		}
 	}
-#endif
 }   
-
-void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
-					   struct pci_bus *bus)
-{
-	/* Update device resources.  */
-	struct pci_controller *hose = PCI_GET_PHB_PTR(bus);
-	int i;
-
-	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-		if (dev->resource[i].flags & IORESOURCE_IO) {
-			unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
-                        unsigned long start, end, mask;
-
-                        start = dev->resource[i].start += offset;
-                        end = dev->resource[i].end += offset;
-
-                        /* Need to allow IO access to pages that are in the
-                           ISA range */
-                        if (start < MAX_ISA_PORT) {
-                                if (end > MAX_ISA_PORT)
-                                        end = MAX_ISA_PORT;
-
-                                start >>= PAGE_SHIFT;
-                                end >>= PAGE_SHIFT;
-
-                                /* get the range of pages for the map */
-                                mask = ((1 << (end+1))-1) ^ ((1 << start)-1);
-                                io_page_mask |= mask;
-                        }
-		}
-                else if (dev->resource[i].flags & IORESOURCE_MEM) {
-			dev->resource[i].start += hose->pci_mem_offset;
-			dev->resource[i].end += hose->pci_mem_offset;
-		}
-        }
-}
-EXPORT_SYMBOL(pcibios_fixup_device_resources);
-
-void __devinit pcibios_fixup_bus(struct pci_bus *bus)
-{
-	struct pci_controller *hose = PCI_GET_PHB_PTR(bus);
-	struct list_head *ln;
-
-	/* XXX or bus->parent? */
-	struct pci_dev *dev = bus->self;
-	struct resource *res;
-	int i;
-
-	if (!dev) {
-		/* Root bus. */
-
-		hose->bus = bus;
-		bus->resource[0] = res = &hose->io_resource;
-		if (!res->flags)
-			BUG();	/* No I/O resource for this PHB? */
-
-		if (request_resource(&ioport_resource, res))
-			printk(KERN_ERR "Failed to request IO on "
-					"PCI domain %d\n", pci_domain_nr(bus));
-
-
-		for (i = 0; i < 3; ++i) {
-			res = &hose->mem_resources[i];
-			if (!res->flags && i == 0)
-				BUG();	/* No memory resource for this PHB? */
-			bus->resource[i+1] = res;
-			if (res->flags && request_resource(&iomem_resource, res))
-				printk(KERN_ERR "Failed to request MEM on "
-						"PCI domain %d\n",
-						pci_domain_nr(bus));
-		}
-	} else if (pci_probe_only &&
-		   (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
-		/* This is a subordinate bridge */
-
-		pci_read_bridge_bases(bus);
-		pcibios_fixup_device_resources(dev, bus);
-	}
-
-	/* XXX Need to check why Alpha doesnt do this - Anton */
-	if (!pci_probe_only)
-		return;
-
-	for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
-		struct pci_dev *dev = pci_dev_b(ln);
-		if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
-			pcibios_fixup_device_resources(dev, bus);
-	}
-}
-EXPORT_SYMBOL(pcibios_fixup_bus);
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device);
+#endif
 
 static void check_s7a(void)
 {
@@ -728,13 +466,34 @@ EXPORT_SYMBOL(remap_bus_range);
 
 static void phbs_fixup_io(void)
 {
-	struct pci_controller *hose;
+	struct pci_controller *hose, *tmp;
 
-	for (hose=hose_head;hose;hose=hose->next) 
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
 		remap_bus_range(hose->bus);
 }
 
-extern void chrp_request_regions(void);
+static void __init pSeries_request_regions(void)
+{
+	struct device_node *i8042;
+
+	request_region(0x20,0x20,"pic1");
+	request_region(0xa0,0x20,"pic2");
+	request_region(0x00,0x20,"dma1");
+	request_region(0x40,0x20,"timer");
+	request_region(0x80,0x10,"dma page reg");
+	request_region(0xc0,0x20,"dma2");
+
+#define I8042_DATA_REG 0x60
+
+	/*
+	 * Some machines have an unterminated i8042 so check the device
+	 * tree and reserve the region if it does not appear. Later on
+	 * the i8042 code will try and reserve this region and fail.
+	 */
+	if (!(i8042 = of_find_node_by_type(NULL, "8042")))
+		request_region(I8042_DATA_REG, 16, "reserved (no i8042)");
+	of_node_put(i8042);
+}
 
 void __init pSeries_final_fixup(void)
 {
@@ -742,58 +501,23 @@ void __init pSeries_final_fixup(void)
 
 	check_s7a();
 
-	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
+	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
 		pci_read_irq_line(dev);
+		if (s7a_workaround) {
+			if (dev->irq > 16) {
+				dev->irq -= 3;
+				pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+			}
+		}
+	}
 
 	phbs_fixup_io();
-	chrp_request_regions();
+	pSeries_request_regions();
 	pci_fix_bus_sysdata();
-	if (!ppc64_iommu_off)
+
+	if (!of_chosen || !get_property(of_chosen, "linux,iommu-off", NULL))
 		iommu_setup_pSeries();
-}
 
-/*********************************************************************** 
- * pci_find_hose_for_OF_device
- *
- * This function finds the PHB that matching device_node in the 
- * OpenFirmware by scanning all the pci_controllers.
- * 
- ***********************************************************************/
-struct pci_controller*
-pci_find_hose_for_OF_device(struct device_node *node)
-{
-	while (node) {
-		struct pci_controller *hose;
-		for (hose=hose_head;hose;hose=hose->next)
-			if (hose->arch_data == node)
-				return hose;
-		node=node->parent;
-	}
-	return NULL;
+	pci_addr_cache_build();
 }
 
-/*
- * ppc64 can have multifunction devices that do not respond to function 0.
- * In this case we must scan all functions.
- */
-int
-pcibios_scan_all_fns(struct pci_bus *bus, int devfn)
-{
-       struct device_node *busdn, *dn;
-
-       if (bus->self)
-               busdn = pci_device_to_OF_node(bus->self);
-       else
-               busdn = bus->sysdata;   /* must be a phb */
-
-       /*
-        * Check to see if there is any of the 8 functions are in the
-        * device tree.  If they are then we need to scan all the
-        * functions of this slot.
-        */
-       for (dn = busdn->child; dn; dn = dn->sibling)
-               if ((dn->devfn >> 3) == (devfn >> 3))
-                       return 1;
-
-       return 0;
-}
diff --git a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c
index 0e4228316..61d7f8e33 100644
--- a/arch/ppc64/kernel/pacaData.c
+++ b/arch/ppc64/kernel/pacaData.c
@@ -27,13 +27,6 @@ struct systemcfg *systemcfg;
  * field correctly */
 extern unsigned long __toc_start;
 
-/* Stack space used when we detect a bad kernel stack pointer, and
- * early in SMP boots before relocation is enabled.
- *
- * ABI requires stack to be 128-byte aligned
- */
-char emergency_stack[PAGE_SIZE * NR_CPUS] __attribute__((aligned(128)));
-
 /* The Paca is an array with one entry per processor.  Each contains an 
  * ItLpPaca, which contains the information shared between the 
  * hypervisor and Linux.  Each also contains an ItLpRegSave area which
@@ -44,18 +37,27 @@ char emergency_stack[PAGE_SIZE * NR_CPUS] __attribute__((aligned(128)));
  * processors.  The processor VPD array needs one entry per physical
  * processor (not thread).
  */
-#define PACAINITDATA(number,start,lpq,asrr,asrv)			    \
-{									    \
+#ifdef CONFIG_PPC_ISERIES
+#define EXTRA_INITS(number, lpq)					    \
 	.lppaca_ptr = &paca[number].lppaca,				    \
+	.lpqueue_ptr = (lpq),		/* &xItLpQueue, */		    \
 	.reg_save_ptr = &paca[number].reg_save,				    \
+	.reg_save = {							    \
+		.xDesc = 0xd397d9e2,	/* "LpRS" */			    \
+		.xSize = sizeof(struct ItLpRegSave)			    \
+	},
+#else
+#define EXTRA_INITS(number, lpq)
+#endif
+
+#define PACAINITDATA(number,start,lpq,asrr,asrv)			    \
+{									    \
 	.lock_token = 0x8000,						    \
 	.paca_index = (number),		/* Paca Index */		    \
-	.lpqueue_ptr = (lpq),		/* &xItLpQueue, */		    \
 	.default_decr = 0x00ff0000,	/* Initial Decr */		    \
 	.kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL,		    \
 	.stab_real = (asrr), 		/* Real pointer to segment table */ \
 	.stab_addr = (asrv),		/* Virt pointer to segment table */ \
-	.emergency_sp = &emergency_stack[((number)+1) * PAGE_SIZE],	    \
 	.cpu_start = (start),		/* Processor start */		    \
 	.lppaca = {							    \
 		.xDesc = 0xd397d781,	/* "LpPa" */			    \
@@ -66,13 +68,10 @@ char emergency_stack[PAGE_SIZE * NR_CPUS] __attribute__((aligned(128)));
 		.xEndOfQuantum = 0xfffffffffffffffful,			    \
 		.xSLBCount = 64,					    \
 	},								    \
-	.reg_save = {							    \
-		.xDesc = 0xd397d9e2,	/* "LpRS" */			    \
-		.xSize = sizeof(struct ItLpRegSave)			    \
-	},								    \
+	EXTRA_INITS((number), (lpq))					    \
 }
 
-struct paca_struct paca[] __page_aligned = {
+struct paca_struct paca[] = {
 #ifdef CONFIG_PPC_ISERIES
 	PACAINITDATA( 0, 1, &xItLpQueue, 0, STAB0_VIRT_ADDR),
 #else
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
index 30e50023c..751071af3 100644
--- a/arch/ppc64/kernel/pci.c
+++ b/arch/ppc64/kernel/pci.c
@@ -23,6 +23,7 @@
 #include <linux/bootmem.h>
 #include <linux/module.h>
 #include <linux/mm.h>
+#include <linux/list.h>
 
 #include <asm/processor.h>
 #include <asm/io.h>
@@ -41,6 +42,13 @@
 unsigned long pci_probe_only = 1;
 unsigned long pci_assign_all_buses = 0;
 
+/* legal IO pages under MAX_ISA_PORT.  This is to ensure we don't touch
+   devices we don't have access to. */
+unsigned long io_page_mask;
+
+EXPORT_SYMBOL(io_page_mask);
+
+
 unsigned int pcibios_assign_all_busses(void)
 {
 	return pci_assign_all_buses;
@@ -55,16 +63,9 @@ unsigned int pcibios_assign_all_busses(void)
 unsigned long isa_io_base;	/* NULL if no ISA bus */
 unsigned long pci_io_base;
 
-void pcibios_name_device(struct pci_dev* dev);
-void pcibios_final_fixup(void);
-static void fixup_broken_pcnet32(struct pci_dev* dev);
-static void fixup_windbond_82c105(struct pci_dev* dev);
-extern void fixup_k2_sata(struct pci_dev* dev);
-
 void iSeries_pcibios_init(void);
 
-struct pci_controller *hose_head;
-struct pci_controller **hose_tail = &hose_head;
+LIST_HEAD(hose_list);
 
 struct pci_dma_ops pci_dma_ops;
 EXPORT_SYMBOL(pci_dma_ops);
@@ -74,20 +75,6 @@ int global_phb_number;		/* Global phb counter */
 /* Cached ISA bridge dev. */
 struct pci_dev *ppc64_isabridge_dev = NULL;
 
-struct pci_fixup pcibios_fixups[] = {
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_TRIDENT,		PCI_ANY_ID,
-	  fixup_broken_pcnet32 },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_WINBOND,		PCI_DEVICE_ID_WINBOND_82C105,
-	  fixup_windbond_82c105 },
-	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,    			PCI_ANY_ID,
-	  pcibios_name_device },
-#ifdef CONFIG_PPC_PMAC
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SERVERWORKS,	0x0240,
-	  fixup_k2_sata },
-#endif
-	{ 0 }
-};
-
 static void fixup_broken_pcnet32(struct pci_dev* dev)
 {
 	if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) {
@@ -96,6 +83,7 @@ static void fixup_broken_pcnet32(struct pci_dev* dev)
 		pci_name_device(dev);
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32);
 
 static void fixup_windbond_82c105(struct pci_dev* dev)
 {
@@ -118,6 +106,7 @@ static void fixup_windbond_82c105(struct pci_dev* dev)
 			dev->resource[i].flags &= ~IORESOURCE_IO;
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, fixup_windbond_82c105);
 
 void 
 pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
@@ -239,9 +228,9 @@ pci_alloc_pci_controller(enum phb_types controller_type)
 		memcpy(hose->what,model,7);
         hose->type = controller_type;
         hose->global_number = global_phb_number++;
-        
-        *hose_tail = hose;
-        hose_tail = &hose->next;
+
+	list_add_tail(&hose->list_node, &hose_list);
+
         return hose;
 }
 
@@ -281,18 +270,17 @@ static void __init pcibios_claim_of_setup(void)
 
 static int __init pcibios_init(void)
 {
-	struct pci_controller *hose;
+	struct pci_controller *hose, *tmp;
 	struct pci_bus *bus;
 
 #ifdef CONFIG_PPC_ISERIES
 	iSeries_pcibios_init(); 
 #endif
 
-	//ppc64_boot_msg(0x40, "PCI Probe");
 	printk("PCI: Probing PCI hardware\n");
 
 	/* Scan all of the recorded PCI controllers.  */
-	for (hose = hose_head; hose; hose = hose->next) {
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
 		hose->last_busno = 0xff;
 		bus = pci_scan_bus(hose->first_busno, hose->ops,
 				   hose->arch_data);
@@ -308,7 +296,7 @@ static int __init pcibios_init(void)
 		   pci_assign_unassigned_resources() is able to work
 		   correctly with [partially] allocated PCI tree. */
 		pci_assign_unassigned_resources();
-#endif
+#endif /* !CONFIG_PPC_ISERIES */
 
 	/* Call machine dependent final fixup */
 	if (ppc_md.pcibios_fixup)
@@ -320,11 +308,6 @@ static int __init pcibios_init(void)
 		printk("ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
 
 	printk("PCI: Probing PCI hardware done\n");
-	//ppc64_boot_msg(0x41, "PCI Done");
-
-#ifdef CONFIG_PPC_PSERIES
-	pci_addr_cache_build();
-#endif
 
 	return 0;
 }
@@ -524,7 +507,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
 	return ret;
 }
 
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
 static ssize_t pci_show_devspec(struct device *dev, char *buf)
 {
 	struct pci_dev *pdev;
@@ -537,11 +520,329 @@ static ssize_t pci_show_devspec(struct device *dev, char *buf)
 	return sprintf(buf, "%s", np->full_name);
 }
 static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* CONFIG_PPC_MULTIPLATFORM */
 
 void pcibios_add_platform_entries(struct pci_dev *pdev)
 {
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
 	device_create_file(&pdev->dev, &dev_attr_devspec);
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+}
+
+#ifdef CONFIG_PPC_MULTIPLATFORM
+
+#define ISA_SPACE_MASK 0x1
+#define ISA_SPACE_IO 0x1
+
+static void pci_process_ISA_OF_ranges(struct device_node *isa_node,
+				      unsigned long phb_io_base_phys,
+				      void * phb_io_base_virt)
+{
+	struct isa_range *range;
+	unsigned long pci_addr;
+	unsigned int isa_addr;
+	unsigned int size;
+	int rlen = 0;
+
+	range = (struct isa_range *) get_property(isa_node, "ranges", &rlen);
+	if (rlen < sizeof(struct isa_range)) {
+		printk(KERN_ERR "unexpected isa range size: %s\n", 
+				__FUNCTION__);
+		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);
+	}
+}
+
+void __init pci_process_bridge_OF_ranges(struct pci_controller *hose,
+					 struct device_node *dev, int primary)
+{
+	unsigned int *ranges;
+	unsigned long size;
+	int rlen = 0;
+	int memno = 0;
+	struct resource *res;
+	int np, na = prom_n_addr_cells(dev);
+	unsigned long pci_addr, cpu_phys_addr;
+	struct device_node *isa_dn;
+
+	np = na + 5;
+
+	/* From "PCI Binding to 1275"
+	 * The ranges property is laid out as an array of elements,
+	 * each of which comprises:
+	 *   cells 0 - 2:	a PCI address
+	 *   cells 3 or 3+4:	a CPU physical address
+	 *			(size depending on dev->n_addr_cells)
+	 *   cells 4+5 or 5+6:	the size of the range
+	 */
+	rlen = 0;
+	hose->io_base_phys = 0;
+	ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
+	while ((rlen -= np * sizeof(unsigned int)) >= 0) {
+		res = NULL;
+		pci_addr = (unsigned long)ranges[1] << 32 | ranges[2];
+
+		cpu_phys_addr = ranges[3];
+		if (na == 2)
+			cpu_phys_addr = cpu_phys_addr << 32 | ranges[4];
+
+		size = (unsigned long)ranges[na+3] << 32 | ranges[na+4];
+
+		switch (ranges[0] >> 24) {
+		case 1:		/* I/O space */
+			hose->io_base_phys = cpu_phys_addr;
+			hose->io_base_virt = reserve_phb_iospace(size);
+			PPCDBG(PPCDBG_PHBINIT, 
+			       "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);
+                                        /* Allow all IO */
+                                        io_page_mask = -1;
+				}
+			}
+
+			res = &hose->io_resource;
+			res->flags = IORESOURCE_IO;
+			res->start = pci_addr;
+			res->start += (unsigned long)hose->io_base_virt -
+				pci_io_base;
+			break;
+		case 2:		/* memory space */
+			memno = 0;
+			while (memno < 3 && hose->mem_resources[memno].flags)
+				++memno;
+
+			if (memno == 0)
+				hose->pci_mem_offset = cpu_phys_addr - pci_addr;
+			if (memno < 3) {
+				res = &hose->mem_resources[memno];
+				res->flags = IORESOURCE_MEM;
+				res->start = cpu_phys_addr;
+			}
+			break;
+		}
+		if (res != NULL) {
+			res->name = dev->full_name;
+			res->end = res->start + size - 1;
+			res->parent = NULL;
+			res->sibling = NULL;
+			res->child = NULL;
+		}
+		ranges += np;
+	}
+}
+
+/*********************************************************************** 
+ * pci_find_hose_for_OF_device
+ *
+ * This function finds the PHB that matching device_node in the 
+ * OpenFirmware by scanning all the pci_controllers.
+ * 
+ ***********************************************************************/
+struct pci_controller* pci_find_hose_for_OF_device(struct device_node *node)
+{
+	while (node) {
+		struct pci_controller *hose, *tmp;
+		list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+			if (hose->arch_data == node)
+				return hose;
+		node=node->parent;
+	}
+	return NULL;
+}
+
+/*
+ * ppc64 can have multifunction devices that do not respond to function 0.
+ * In this case we must scan all functions.
+ */
+int pcibios_scan_all_fns(struct pci_bus *bus, int devfn)
+{
+       struct device_node *busdn, *dn;
+
+       if (bus->self)
+               busdn = pci_device_to_OF_node(bus->self);
+       else
+               busdn = bus->sysdata;   /* must be a phb */
+
+       /*
+        * Check to see if there is any of the 8 functions are in the
+        * device tree.  If they are then we need to scan all the
+        * functions of this slot.
+        */
+       for (dn = busdn->child; dn; dn = dn->sibling)
+               if ((dn->devfn >> 3) == (devfn >> 3))
+                       return 1;
+
+       return 0;
+}
+
+
+void __devinit pcibios_fixup_device_resources(struct pci_dev *dev,
+					   struct pci_bus *bus)
+{
+	/* Update device resources.  */
+	struct pci_controller *hose = PCI_GET_PHB_PTR(bus);
+	int i;
+
+	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+		if (dev->resource[i].flags & IORESOURCE_IO) {
+			unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base;
+                        unsigned long start, end, mask;
+
+                        start = dev->resource[i].start += offset;
+                        end = dev->resource[i].end += offset;
+
+                        /* Need to allow IO access to pages that are in the
+                           ISA range */
+                        if (start < MAX_ISA_PORT) {
+                                if (end > MAX_ISA_PORT)
+                                        end = MAX_ISA_PORT;
+
+                                start >>= PAGE_SHIFT;
+                                end >>= PAGE_SHIFT;
+
+                                /* get the range of pages for the map */
+                                mask = ((1 << (end+1))-1) ^ ((1 << start)-1);
+                                io_page_mask |= mask;
+                        }
+		}
+                else if (dev->resource[i].flags & IORESOURCE_MEM) {
+			dev->resource[i].start += hose->pci_mem_offset;
+			dev->resource[i].end += hose->pci_mem_offset;
+		}
+        }
+}
+EXPORT_SYMBOL(pcibios_fixup_device_resources);
+
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+	struct pci_controller *hose = PCI_GET_PHB_PTR(bus);
+	struct list_head *ln;
+
+	/* XXX or bus->parent? */
+	struct pci_dev *dev = bus->self;
+	struct resource *res;
+	int i;
+
+	if (!dev) {
+		/* Root bus. */
+
+		hose->bus = bus;
+		bus->resource[0] = res = &hose->io_resource;
+		if (!res->flags)
+			BUG();	/* No I/O resource for this PHB? */
+
+		if (request_resource(&ioport_resource, res))
+			printk(KERN_ERR "Failed to request IO on "
+					"PCI domain %d\n", pci_domain_nr(bus));
+
+
+		for (i = 0; i < 3; ++i) {
+			res = &hose->mem_resources[i];
+			if (!res->flags && i == 0)
+				BUG();	/* No memory resource for this PHB? */
+			bus->resource[i+1] = res;
+			if (res->flags && request_resource(&iomem_resource, res))
+				printk(KERN_ERR "Failed to request MEM on "
+						"PCI domain %d\n",
+						pci_domain_nr(bus));
+		}
+	} else if (pci_probe_only &&
+		   (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+		/* This is a subordinate bridge */
+
+		pci_read_bridge_bases(bus);
+		pcibios_fixup_device_resources(dev, bus);
+	}
+
+	/* XXX Need to check why Alpha doesnt do this - Anton */
+	if (!pci_probe_only)
+		return;
+
+	for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
+		struct pci_dev *dev = pci_dev_b(ln);
+		if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
+			pcibios_fixup_device_resources(dev, bus);
+	}
+}
+EXPORT_SYMBOL(pcibios_fixup_bus);
+
+/******************************************************************
+ * pci_read_irq_line
+ *
+ * Reads the Interrupt Pin to determine if interrupt is use by card.
+ * If the interrupt is used, then gets the interrupt line from the 
+ * openfirmware and sets it in the pci_dev and pci_config line.
+ *
+ ******************************************************************/
+int pci_read_irq_line(struct pci_dev *pci_dev)
+{
+	u8 intpin;
+	struct device_node *node;
+
+    	pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &intpin);
+
+	if (intpin == 0) {
+		PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Interrupt used by device.\n",
+		       pci_name(pci_dev));
+		return 0;	
+	}
+
+	node = pci_device_to_OF_node(pci_dev);
+	if (node == NULL) { 
+		PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s Device Node not found.\n",
+		       pci_name(pci_dev));
+		return -1;	
+	}
+	if (node->n_intrs == 0) 	{
+		PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Device OF interrupts defined.\n",
+		       pci_name(pci_dev));
+		return -1;	
+	}
+	pci_dev->irq = node->intrs[0].line;
+
+	pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, pci_dev->irq);
+	
+	PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s pci_dev->irq = 0x%02X\n",
+	       pci_name(pci_dev), pci_dev->irq);
+	return 0;
 }
+EXPORT_SYMBOL(pci_read_irq_line);
+
+#endif /* CONFIG_PPC_MULTIPLATFORM */
diff --git a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h
index 2ca27ccc7..9e85ebd48 100644
--- a/arch/ppc64/kernel/pci.h
+++ b/arch/ppc64/kernel/pci.h
@@ -17,9 +17,7 @@ extern unsigned long isa_io_base;
 extern struct pci_controller* pci_alloc_pci_controller(enum phb_types controller_type);
 extern struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node);
 
-extern struct pci_controller* hose_head;
-extern struct pci_controller** hose_tail;
-
+extern struct list_head hose_list;
 extern int global_phb_number;
 
 /*******************************************************************
diff --git a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c
index c771bdc64..2ef21d7da 100644
--- a/arch/ppc64/kernel/pci_dn.c
+++ b/arch/ppc64/kernel/pci_dn.c
@@ -129,10 +129,10 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre,
  */
 static void *traverse_all_pci_devices(traverse_func pre)
 {
-	struct pci_controller *phb;
+	struct pci_controller *phb, *tmp;
 	void *ret;
 
-	for (phb = hose_head; phb; phb = phb->next)
+	list_for_each_entry_safe(phb, tmp, &hose_list, list_node)
 		if ((ret = traverse_pci_devices(phb->arch_data, pre, phb))
 				!= NULL)
 			return ret;
diff --git a/arch/ppc64/kernel/pci_iommu.c b/arch/ppc64/kernel/pci_iommu.c
index 4d99851fe..951831f99 100644
--- a/arch/ppc64/kernel/pci_iommu.c
+++ b/arch/ppc64/kernel/pci_iommu.c
@@ -54,9 +54,9 @@ static inline struct iommu_table *devnode_table(struct pci_dev *dev)
 	return ISERIES_DEVNODE(dev)->iommu_table;
 #endif /* CONFIG_PPC_ISERIES */
 
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
 	return PCI_GET_DN(dev)->iommu_table;
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* CONFIG_PPC_MULTIPLATFORM */
 }
 
 
diff --git a/arch/ppc64/kernel/pmac_feature.c b/arch/ppc64/kernel/pmac_feature.c
index c059a7608..c45ecbdb2 100644
--- a/arch/ppc64/kernel/pmac_feature.c
+++ b/arch/ppc64/kernel/pmac_feature.c
@@ -44,9 +44,9 @@
 #undef DEBUG_FEATURE
 
 #ifdef DEBUG_FEATURE
-#define DBG(fmt,...) printk(KERN_DEBUG fmt)
+#define DBG(fmt...) printk(KERN_DEBUG fmt)
 #else
-#define DBG(fmt,...)
+#define DBG(fmt...)
 #endif
 
 /*
@@ -343,6 +343,10 @@ static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
 		PMAC_TYPE_POWERMAC_G5,		g5_features,
 		0,
 	},
+	{	"PowerMac7,3",			"PowerMac G5",
+		PMAC_TYPE_POWERMAC_G5,		g5_features,
+		0,
+	},
 	{       "RackMac3,1",                   "XServe G5",
 		PMAC_TYPE_POWERMAC_G5,          g5_features,
 		0,
@@ -611,7 +615,7 @@ int __init pmac_feature_late_init(void)
 
 device_initcall(pmac_feature_late_init);
 
-
+#if 0
 static void dump_HT_speeds(char *name, u32 cfg, u32 frq)
 {
 	int	freqs[16] = { 200,300,400,500,600,800,1000,0,0,0,0,0,0,0,0,0 };
@@ -625,6 +629,7 @@ static void dump_HT_speeds(char *name, u32 cfg, u32 frq)
 		       name, freqs[freq],
 		       bits[(cfg >> 28) & 0x7], bits[(cfg >> 24) & 0x7]);
 }
+#endif
 
 void __init pmac_check_ht_link(void)
 {
diff --git a/arch/ppc64/kernel/pmac_low_i2c.c b/arch/ppc64/kernel/pmac_low_i2c.c
index d07579f2b..52da75719 100644
--- a/arch/ppc64/kernel/pmac_low_i2c.c
+++ b/arch/ppc64/kernel/pmac_low_i2c.c
@@ -50,7 +50,7 @@ struct low_i2c_host
 	struct device_node	*np;		/* OF device node */
 	struct semaphore	mutex;		/* Access mutex for use by i2c-keywest */
 	low_i2c_func_t		func;		/* Access function */
-	int			is_open : 1;	/* Poor man's access control */
+	unsigned		is_open : 1;	/* Poor man's access control */
 	int			mode;		/* Current mode */
 	int			channel;	/* Current channel */
 	int			num_channels;	/* Number of channels */
diff --git a/arch/ppc64/kernel/pmac_pci.c b/arch/ppc64/kernel/pmac_pci.c
index 169195713..9e1a06955 100644
--- a/arch/ppc64/kernel/pmac_pci.c
+++ b/arch/ppc64/kernel/pmac_pci.c
@@ -271,7 +271,7 @@ static int __pmac u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
 				    int offset, int len, u32 *val)
 {
 	struct pci_controller *hose;
-	struct device_node *busdn;
+	struct device_node *busdn, *dn;
 	unsigned long addr;
 
 	if (bus->self)
@@ -284,6 +284,16 @@ static int __pmac u3_ht_read_config(struct pci_bus *bus, unsigned int devfn,
 	if (hose == NULL)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
+	/* We only allow config cycles to devices that are in OF device-tree
+	 * as we are apparently having some weird things going on with some
+	 * revs of K2 on recent G5s
+	 */
+	for (dn = busdn->child; dn; dn = dn->sibling)
+		if (dn->devfn == devfn)
+			break;
+	if (dn == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
 	addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
 	if (!addr)
 		return PCIBIOS_DEVICE_NOT_FOUND;
@@ -419,7 +429,7 @@ static void __init setup_u3_ht(struct pci_controller* hose)
 	 * properties or figuring out the U3 address space decoding logic and
 	 * then read it's configuration register (if any).
 	 */
-	hose->io_base_phys = 0xf4000000 + 0x00400000;
+	hose->io_base_phys = 0xf4000000;
 	hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000);
 	isa_io_base = pci_io_base = (unsigned long) hose->io_base_virt;
 	hose->io_resource.name = np->full_name;
@@ -664,17 +674,15 @@ void __init pmac_pcibios_fixup(void)
 
 	pci_fix_bus_sysdata();
 
-#ifdef CONFIG_PMAC_DART
-	iommu_setup_pmac();
-#endif /* CONFIG_PMAC_DART */
+	iommu_setup_u3();
 
 }
 
 static void __init pmac_fixup_phb_resources(void)
 {
-	struct pci_controller *hose;
+	struct pci_controller *hose, *tmp;
 	
-	for (hose = hose_head; hose; hose = hose->next) {
+	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;
@@ -746,6 +754,9 @@ void __init pmac_pci_init(void)
 	 * the exception of U3/AGP (hook into pci_set_mwi)
 	 */
 	pci_cache_line_size = 16; /* 64 bytes */
+
+	/* Allow all IO */
+	io_page_mask = -1;
 }
 
 /*
@@ -777,3 +788,4 @@ void fixup_k2_sata(struct pci_dev* dev)
 		}
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, 0x0240, fixup_k2_sata);
diff --git a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c
index 58e8b392e..3d1de0f9b 100644
--- a/arch/ppc64/kernel/pmac_setup.c
+++ b/arch/ppc64/kernel/pmac_setup.c
@@ -23,6 +23,8 @@
  * bootup setup stuff..
  */
 
+#undef DEBUG
+
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/errno.h>
@@ -63,7 +65,6 @@
 #include <asm/iommu.h>
 #include <asm/machdep.h>
 #include <asm/dma.h>
-#include <asm/bootx.h>
 #include <asm/btext.h>
 #include <asm/cputable.h>
 #include <asm/pmac_feature.h>
@@ -73,6 +74,13 @@
 
 #include "pmac.h"
 
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+
 static int current_root_goodness = -1;
 #define DEFAULT_ROOT_DEVICE Root_SDA1	/* sda1 - slightly silly choice */
 
@@ -81,10 +89,6 @@ int sccdbg;
 
 extern void udbg_init_scc(struct device_node *np);
 
-#ifdef CONFIG_BOOTX_TEXT
-void pmac_progress(char *s, unsigned short hex);
-#endif
-
 void __pmac pmac_show_cpuinfo(struct seq_file *m)
 {
 	struct device_node *np;
@@ -134,28 +138,20 @@ void __pmac pmac_show_cpuinfo(struct seq_file *m)
 
 void __init pmac_setup_arch(void)
 {
-	struct device_node *cpu;
-	int *fp;
-	unsigned long pvr;
-
-	pvr = PVR_VER(mfspr(PVR));
-
-	/* Set loops_per_jiffy to a half-way reasonable value,
-	   for use until calibrate_delay gets called. */
-	cpu = find_type_devices("cpu");
-	if (cpu != 0) {
-		fp = (int *) get_property(cpu, "clock-frequency", NULL);
-		if (fp != 0) {
-			if (pvr == 4 || pvr >= 8)
-				/* 604, G3, G4 etc. */
-				loops_per_jiffy = *fp / HZ;
-			else
-				/* 601, 603, etc. */
-				loops_per_jiffy = *fp / (2*HZ);
-		} else
-			loops_per_jiffy = 50000000 / HZ;
+	/* init to some ~sane value until calibrate_delay() runs */
+	loops_per_jiffy = 50000000;
+
+	/* Probe motherboard chipset */
+	pmac_feature_init();
+#if 0
+	/* Lock-enable the SCC channel used for debug */
+	if (sccdbg) {
+		np = of_find_node_by_name(NULL, "escc");
+		if (np)
+			pmac_call_feature(PMAC_FTR_SCC_ENABLE, np,
+					  PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
 	}
-	
+#endif
 	/* We can NAP */
 	powersave_nap = 1;
 
@@ -183,67 +179,13 @@ void __init pmac_setup_arch(void)
 #endif
 }
 
-extern char *bootpath;
-extern char *bootdevice;
-void *boot_host;
-int boot_target;
-int boot_part;
-extern dev_t boot_dev;
-
 #ifdef CONFIG_SCSI
-void __init note_scsi_host(struct device_node *node, void *host)
+void note_scsi_host(struct device_node *node, void *host)
 {
-	int l;
-	char *p;
-
-	l = strlen(node->full_name);
-	if (bootpath != NULL && bootdevice != NULL
-	    && strncmp(node->full_name, bootdevice, l) == 0
-	    && (bootdevice[l] == '/' || bootdevice[l] == 0)) {
-		boot_host = host;
-		/*
-		 * There's a bug in OF 1.0.5.  (Why am I not surprised.)
-		 * If you pass a path like scsi/sd@1:0 to canon, it returns
-		 * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0
-		 * That is, the scsi target number doesn't get preserved.
-		 * So we pick the target number out of bootpath and use that.
-		 */
-		p = strstr(bootpath, "/sd@");
-		if (p != NULL) {
-			p += 4;
-			boot_target = simple_strtoul(p, NULL, 10);
-			p = strchr(p, ':');
-			if (p != NULL)
-				boot_part = simple_strtoul(p + 1, NULL, 10);
-		}
-	}
+	/* Obsolete */
 }
 #endif
 
-#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
-static dev_t __init find_ide_boot(void)
-{
-	char *p;
-	int n;
-	dev_t __init pmac_find_ide_boot(char *bootdevice, int n);
-
-	if (bootdevice == NULL)
-		return 0;
-	p = strrchr(bootdevice, '/');
-	if (p == NULL)
-		return 0;
-	n = p - bootdevice;
-
-	return pmac_find_ide_boot(bootdevice, n);
-}
-#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */
-
-void __init find_boot_device(void)
-{
-#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
-	boot_dev = find_ide_boot();
-#endif
-}
 
 static int initializing = 1;
 
@@ -258,7 +200,7 @@ late_initcall(pmac_late_init);
 /* can't be __init - can be called whenever a disk is first accessed */
 void __pmac note_bootable_part(dev_t dev, int part, int goodness)
 {
-	static int found_boot = 0;
+	extern dev_t boot_dev;
 	char *p;
 
 	if (!initializing)
@@ -270,10 +212,6 @@ void __pmac note_bootable_part(dev_t dev, int part, int goodness)
 	if (p != NULL && (p == saved_command_line || p[-1] == ' '))
 		return;
 
-	if (!found_boot) {
-		find_boot_device();
-		found_boot = 1;
-	}
 	if (!boot_dev || dev == boot_dev) {
 		ROOT_DEV = dev + part;
 		boot_dev = 0;
@@ -313,21 +251,73 @@ static void btext_putc(unsigned char c)
 }
 #endif /* CONFIG_BOOTX_TEXT */
 
+static void __init init_boot_display(void)
+{
+	char *name;
+	struct device_node *np = NULL; 
+	int rc = -ENODEV;
+
+	printk("trying to initialize btext ...\n");
+
+	name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
+	if (name != NULL) {
+		np = of_find_node_by_path(name);
+		if (np != NULL) {
+			if (strcmp(np->type, "display") != 0) {
+				printk("boot stdout isn't a display !\n");
+				of_node_put(np);
+				np = NULL;
+			}
+		}
+	}
+	if (np)
+		rc = btext_initialize(np);
+	if (rc == 0)
+		return;
+
+	for (np = NULL; (np = of_find_node_by_type(np, "display"));) {
+		if (get_property(np, "linux,opened", NULL)) {
+			printk("trying %s ...\n", np->full_name);
+			rc = btext_initialize(np);
+			printk("result: %d\n", rc);
+		}
+		if (rc == 0)
+			return;
+	}
+}
+
 /* 
  * Early initialization.
- * Relocation is on but do not reference unbolted pages
- * Also, device-tree hasn't been "finished", so don't muck with
- * it too much
  */
 void __init pmac_init_early(void)
 {
-	hpte_init_pSeries();
+	DBG(" -> pmac_init_early\n");
+
+	/* Initialize hash table, from now on, we can take hash faults
+	 * and call ioremap
+	 */
+	hpte_init_native();
 
+	/* Init SCC */
+       	if (strstr(cmd_line, "sccdbg")) {
+		sccdbg = 1;
+       		udbg_init_scc(NULL);
+       	}
+
+	else {
 #ifdef CONFIG_BOOTX_TEXT
-	ppc_md.udbg_putc = btext_putc;
-	ppc_md.udbg_getc = dummy_getc;
-	ppc_md.udbg_getc_poll = dummy_getc_poll;
+		init_boot_display();
+
+		ppc_md.udbg_putc = btext_putc;
+		ppc_md.udbg_getc = dummy_getc;
+		ppc_md.udbg_getc_poll = dummy_getc_poll;
 #endif /* CONFIG_BOOTX_TEXT */
+	}
+
+	/* Setup interrupt mapping options */
+	naca->interrupt_controller = IC_OPEN_PIC;
+
+	DBG(" <- pmac_init_early\n");
 }
 
 extern void* OpenPIC_Addr;
@@ -417,60 +407,19 @@ static int __init pmac_irq_cascade_init(void)
 
 core_initcall(pmac_irq_cascade_init);
 
-void __init pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
-		      unsigned long r6, unsigned long r7)
-{
-	/* Probe motherboard chipset */
-	pmac_feature_init();
-
-	/* Init SCC */
-	if (strstr(cmd_line, "sccdbg")) {
-		sccdbg = 1;
-		udbg_init_scc(NULL);
-	}
-
-	/* Fill up the machine description */
-	ppc_md.setup_arch     = pmac_setup_arch;
-       	ppc_md.get_cpuinfo    = pmac_show_cpuinfo;
-
-	ppc_md.init_IRQ       = pmac_init_IRQ;
-	ppc_md.get_irq        = openpic_get_irq;
-
-	ppc_md.pcibios_fixup  = pmac_pcibios_fixup;
-
-	ppc_md.restart        = pmac_restart;
-	ppc_md.power_off      = pmac_power_off;
-	ppc_md.halt           = pmac_halt;
-
-       	ppc_md.get_boot_time  = pmac_get_boot_time;
-       	ppc_md.set_rtc_time   = pmac_set_rtc_time;
-       	ppc_md.get_rtc_time   = pmac_get_rtc_time;
-      	ppc_md.calibrate_decr = pmac_calibrate_decr;
-
-	ppc_md.feature_call   = pmac_do_feature_call;
-
-
-#ifdef CONFIG_BOOTX_TEXT
-	ppc_md.progress       = pmac_progress;
-#endif /* CONFIG_BOOTX_TEXT */
-
-	if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0);
-
-}
-
-#ifdef CONFIG_BOOTX_TEXT
-void __init pmac_progress(char *s, unsigned short hex)
+static void __init pmac_progress(char *s, unsigned short hex)
 {
 	if (sccdbg) {
 		udbg_puts(s);
-		udbg_putc('\n');
+		udbg_puts("\n");
 	}
+#ifdef CONFIG_BOOTX_TEXT
 	else if (boot_text_mapped) {
 		btext_drawstring(s);
-		btext_drawchar('\n');
+		btext_drawstring("\n");
 	}
-}
 #endif /* CONFIG_BOOTX_TEXT */
+}
 
 static int __init pmac_declare_of_platform_devices(void)
 {
@@ -489,3 +438,41 @@ static int __init pmac_declare_of_platform_devices(void)
 }
 
 device_initcall(pmac_declare_of_platform_devices);
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init pmac_probe(int platform)
+{
+	if (platform != PLATFORM_POWERMAC)
+		return 0;
+
+	/*
+	 * On U3, the DART (iommu) must be allocated now since it
+	 * has an impact on htab_initialize (due to the large page it
+	 * occupies having to be broken up so the DART itself is not
+	 * part of the cacheable linar mapping
+	 */
+	alloc_u3_dart_table();
+
+	return 1;
+}
+
+struct machdep_calls __initdata pmac_md = {
+	.probe			= pmac_probe,
+	.setup_arch		= pmac_setup_arch,
+	.init_early		= pmac_init_early,
+       	.get_cpuinfo		= pmac_show_cpuinfo,
+	.init_IRQ		= pmac_init_IRQ,
+	.get_irq		= openpic_get_irq,
+	.pcibios_fixup		= pmac_pcibios_fixup,
+	.restart		= pmac_restart,
+	.power_off		= pmac_power_off,
+	.halt			= pmac_halt,
+       	.get_boot_time		= pmac_get_boot_time,
+       	.set_rtc_time		= pmac_set_rtc_time,
+       	.get_rtc_time		= pmac_get_rtc_time,
+      	.calibrate_decr		= pmac_calibrate_decr,
+	.feature_call		= pmac_do_feature_call,
+	.progress		= pmac_progress,
+};
diff --git a/arch/ppc64/kernel/pmac_smp.c b/arch/ppc64/kernel/pmac_smp.c
index a67e2a595..fb6ab4014 100644
--- a/arch/ppc64/kernel/pmac_smp.c
+++ b/arch/ppc64/kernel/pmac_smp.c
@@ -38,7 +38,6 @@
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/hardirq.h>
 #include <asm/sections.h>
 #include <asm/io.h>
 #include <asm/prom.h>
diff --git a/arch/ppc64/kernel/pmac_time.c b/arch/ppc64/kernel/pmac_time.c
index aea28b989..06f379855 100644
--- a/arch/ppc64/kernel/pmac_time.c
+++ b/arch/ppc64/kernel/pmac_time.c
@@ -18,6 +18,7 @@
 #include <linux/time.h>
 #include <linux/adb.h>
 #include <linux/pmu.h>
+#include <linux/interrupt.h>
 
 #include <asm/sections.h>
 #include <asm/prom.h>
@@ -25,7 +26,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
-#include <asm/hardirq.h>
 #include <asm/time.h>
 #include <asm/nvram.h>
 
diff --git a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c
index 836cf2a43..3732fe048 100644
--- a/arch/ppc64/kernel/ppc_ksyms.c
+++ b/arch/ppc64/kernel/ppc_ksyms.c
@@ -119,7 +119,6 @@ EXPORT_SYMBOL(start_thread);
 EXPORT_SYMBOL(kernel_thread);
 
 EXPORT_SYMBOL(flush_instruction_cache);
-EXPORT_SYMBOL(_get_PVR);
 EXPORT_SYMBOL(giveup_fpu);
 #ifdef CONFIG_ALTIVEC
 EXPORT_SYMBOL(giveup_altivec);
@@ -137,7 +136,7 @@ EXPORT_SYMBOL(local_irq_restore);
 
 EXPORT_SYMBOL(ppc_md);
 
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
 EXPORT_SYMBOL(find_devices);
 EXPORT_SYMBOL(find_type_devices);
 EXPORT_SYMBOL(find_compatible_devices);
@@ -148,12 +147,12 @@ EXPORT_SYMBOL(find_all_nodes);
 EXPORT_SYMBOL(get_property);
 #endif
 
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memmove);
-EXPORT_SYMBOL_NOVERS(memscan);
-EXPORT_SYMBOL_NOVERS(memcmp);
-EXPORT_SYMBOL_NOVERS(memchr);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memchr);
 
 EXPORT_SYMBOL(timer_interrupt);
 EXPORT_SYMBOL(irq_desc);
diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c
index 5acc56729..821133707 100644
--- a/arch/ppc64/kernel/process.c
+++ b/arch/ppc64/kernel/process.c
@@ -34,6 +34,7 @@
 #include <linux/prctl.h>
 #include <linux/ptrace.h>
 #include <linux/kallsyms.h>
+#include <linux/interrupt.h>
 #include <linux/version.h>
 
 #include <asm/pgtable.h>
@@ -47,7 +48,6 @@
 #include <asm/ppcdebug.h>
 #include <asm/machdep.h>
 #include <asm/iSeries/HvCallHpt.h>
-#include <asm/hardirq.h>
 #include <asm/cputable.h>
 #include <asm/sections.h>
 #include <asm/tlbflush.h>
@@ -147,7 +147,6 @@ EXPORT_SYMBOL(enable_kernel_altivec);
  */
 void flush_altivec_to_thread(struct task_struct *tsk)
 {
-#ifdef CONFIG_ALTIVEC
 	if (tsk->thread.regs) {
 		preempt_disable();
 		if (tsk->thread.regs->msr & MSR_VEC) {
@@ -158,7 +157,6 @@ void flush_altivec_to_thread(struct task_struct *tsk)
 		}
 		preempt_enable();
 	}
-#endif
 }
 
 int dump_task_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs)
@@ -356,6 +354,16 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
 	kregs = (struct pt_regs *) sp;
 	sp -= STACK_FRAME_OVERHEAD;
 	p->thread.ksp = sp;
+	if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) {
+		unsigned long sp_vsid = get_kernel_vsid(sp);
+
+		sp_vsid <<= SLB_VSID_SHIFT;
+		sp_vsid |= SLB_VSID_KERNEL;
+		if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)
+			sp_vsid |= SLB_VSID_L;
+
+		p->thread.ksp_vsid = sp_vsid;
+	}
 
 	/*
 	 * The PPC64 ABI makes use of a TOC to contain function 
@@ -387,11 +395,22 @@ void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp)
 	/* Check whether the e_entry function descriptor entries
 	 * need to be relocated before we can use them.
 	 */
-	if ( load_addr != 0 ) {
+	if (load_addr != 0) {
 		entry += load_addr;
 		toc   += load_addr;
 	}
 
+	/*
+	 * If we exec out of a kernel thread then thread.regs will not be
+	 * set. Do it now.
+	 */
+	if (!current->thread.regs) {
+		unsigned long childregs = (unsigned long)current->thread_info +
+						THREAD_SIZE;
+		childregs -= sizeof(struct pt_regs);
+		current->thread.regs = (struct pt_regs *)childregs;
+	}
+
 	regs->nip = entry;
 	regs->gpr[1] = sp;
 	regs->gpr[2] = toc;
@@ -458,7 +477,7 @@ int sys_clone(unsigned long clone_flags, unsigned long p2, unsigned long p3,
 		}
 	}
 
-	return do_fork(clone_flags & ~CLONE_IDLETASK, p2, regs, 0,
+	return do_fork(clone_flags, p2, regs, 0,
 		    (int __user *)parent_tidptr, (int __user *)child_tidptr);
 }
 
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
index bdf5e3a47..f121ffbc2 100644
--- a/arch/ppc64/kernel/prom.c
+++ b/arch/ppc64/kernel/prom.c
@@ -15,7 +15,7 @@
  *      2 of the License, or (at your option) any later version.
  */
 
-#undef DEBUG_PROM
+#undef DEBUG
 
 #include <stdarg.h>
 #include <linux/config.h>
@@ -54,1806 +54,58 @@
 #include <asm/machdep.h>
 #include "open_pic.h"
 
-#ifdef CONFIG_LOGO_LINUX_CLUT224
-#include <linux/linux_logo.h>
-extern const struct linux_logo logo_linux_clut224;
-#endif
-
-/*
- * Properties whose value is longer than this get excluded from our
- * copy of the device tree. This value does need to be big enough to
- * ensure that we don't lose things like the interrupt-map property
- * on a PCI-PCI bridge.
- */
-#define MAX_PROPERTY_LENGTH	(1UL * 1024 * 1024)
-
-/*
- * prom_init() is called very early on, before the kernel text
- * and data have been mapped to KERNELBASE.  At this point the code
- * is running at whatever address it has been loaded at, so
- * references to extern and static variables must be relocated
- * explicitly.  The procedure reloc_offset() returns the address
- * we're currently running at minus the address we were linked at.
- * (Note that strings count as static variables.)
- *
- * Because OF may have mapped I/O devices into the area starting at
- * KERNELBASE, particularly on CHRP machines, we can't safely call
- * OF once the kernel has been mapped to KERNELBASE.  Therefore all
- * OF calls should be done within prom_init(), and prom_init()
- * and all routines called within it must be careful to relocate
- * references as necessary.
- *
- * Note that the bss is cleared *after* prom_init runs, so we have
- * to make sure that any static or extern variables it accesses
- * are put in the data segment.
- */
-
-
-#define PROM_BUG() do {						\
-        prom_printf("kernel BUG at %s line 0x%x!\n",		\
-		    RELOC(__FILE__), __LINE__);			\
-        __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR);	\
-} while (0)
-
-#ifdef DEBUG_PROM
-#define prom_debug(x...)	prom_printf(x)
-#else
-#define prom_debug(x...)
-#endif
-
-
-struct pci_reg_property {
-	struct pci_address addr;
-	u32 size_hi;
-	u32 size_lo;
-};
-
-
-struct isa_reg_property {
-	u32 space;
-	u32 address;
-	u32 size;
-};
-
-struct pci_intr_map {
-	struct pci_address addr;
-	u32 dunno;
-	phandle int_ctrler;
-	u32 intr;
-};
-
-
-typedef unsigned long interpret_func(struct device_node *, unsigned long,
-				     int, int, int);
-
-#ifndef FB_MAX			/* avoid pulling in all of the fb stuff */
-#define FB_MAX	8
-#endif
-
-/* prom structure */
-struct prom_t prom;
-
-char *prom_display_paths[FB_MAX] __initdata = { NULL, };
-phandle prom_display_nodes[FB_MAX] __initdata;
-unsigned int prom_num_displays = 0;
-char *of_stdout_device = NULL;
-
-static int iommu_force_on;
-int ppc64_iommu_off;
-
-extern struct rtas_t rtas;
-extern unsigned long klimit;
-extern struct lmb lmb;
-
-#define MAX_PHB (32 * 6)  /* 32 drawers * 6 PHBs/drawer */
-struct of_tce_table of_tce_table[MAX_PHB + 1];
-
-char *bootpath = NULL;
-char *bootdevice = NULL;
-
-int boot_cpuid = 0;
-#define MAX_CPU_THREADS 2
-
-struct device_node *allnodes = NULL;
-/* use when traversing tree through the allnext, child, sibling,
- * or parent members of struct device_node.
- */
-static rwlock_t devtree_lock = RW_LOCK_UNLOCKED;
-
-extern unsigned long reloc_offset(void);
-
-extern void enter_prom(struct prom_args *args);
-extern void copy_and_flush(unsigned long dest, unsigned long src,
-			   unsigned long size, unsigned long offset);
-
-unsigned long dev_tree_size;
-unsigned long _get_PIR(void);
-
-#ifdef CONFIG_HMT
-struct {
-	unsigned int pir;
-	unsigned int threadid;
-} hmt_thread_data[NR_CPUS];
-#endif /* CONFIG_HMT */
-
-char testString[] = "LINUX\n"; 
-
-/*
- * This are used in calls to call_prom.  The 4th and following
- * arguments to call_prom should be 32-bit values.  64 bit values
- * are truncated to 32 bits (and fortunately don't get interpreted
- * as two arguments).
- */
-#define ADDR(x)		(u32) ((unsigned long)(x) - offset)
-
-/* This is the one and *ONLY* place where we actually call open
- * firmware from, since we need to make sure we're running in 32b
- * mode when we do.  We switch back to 64b mode upon return.
- */
-
-#define PROM_ERROR	(-1)
-
-static int __init call_prom(const char *service, int nargs, int nret, ...)
-{
-	int i;
-	unsigned long offset = reloc_offset();
-	struct prom_t *_prom = PTRRELOC(&prom);
-	va_list list;
-
-	_prom->args.service = ADDR(service);
-	_prom->args.nargs = nargs;
-	_prom->args.nret = nret;
-	_prom->args.rets = (prom_arg_t *)&(_prom->args.args[nargs]);
-
-	va_start(list, nret);
-	for (i=0; i < nargs; i++)
-		_prom->args.args[i] = va_arg(list, prom_arg_t);
-	va_end(list);
-
-	for (i=0; i < nret ;i++)
-		_prom->args.rets[i] = 0;
-
-	enter_prom(&_prom->args);
-
-	return (nret > 0)? _prom->args.rets[0]: 0;
-}
-
-
-static void __init prom_print(const char *msg)
-{
-	const char *p, *q;
-	unsigned long offset = reloc_offset();
-	struct prom_t *_prom = PTRRELOC(&prom);
-
-	if (_prom->stdout == 0)
-		return;
-
-	for (p = msg; *p != 0; p = q) {
-		for (q = p; *q != 0 && *q != '\n'; ++q)
-			;
-		if (q > p)
-			call_prom("write", 3, 1, _prom->stdout, p, q - p);
-		if (*q == 0)
-			break;
-		++q;
-		call_prom("write", 3, 1, _prom->stdout, ADDR("\r\n"), 2);
-	}
-}
-
-
-static void __init prom_print_hex(unsigned long val)
-{
-	unsigned long offset = reloc_offset();
-	int i, nibbles = sizeof(val)*2;
-	char buf[sizeof(val)*2+1];
-	struct prom_t *_prom = PTRRELOC(&prom);
-
-	for (i = nibbles-1;  i >= 0;  i--) {
-		buf[i] = (val & 0xf) + '0';
-		if (buf[i] > '9')
-			buf[i] += ('a'-'0'-10);
-		val >>= 4;
-	}
-	buf[nibbles] = '\0';
-	call_prom("write", 3, 1, _prom->stdout, buf, nibbles);
-}
-
-
-static void __init prom_printf(const char *format, ...)
-{
-	unsigned long offset = reloc_offset();
-	const char *p, *q, *s;
-	va_list args;
-	unsigned long v;
-	struct prom_t *_prom = PTRRELOC(&prom);
-
-	va_start(args, format);
-	for (p = PTRRELOC(format); *p != 0; p = q) {
-		for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q)
-			;
-		if (q > p)
-			call_prom("write", 3, 1, _prom->stdout, p, q - p);
-		if (*q == 0)
-			break;
-		if (*q == '\n') {
-			++q;
-			call_prom("write", 3, 1, _prom->stdout,
-				  ADDR("\r\n"), 2);
-			continue;
-		}
-		++q;
-		if (*q == 0)
-			break;
-		switch (*q) {
-		case 's':
-			++q;
-			s = va_arg(args, const char *);
-			prom_print(s);
-			break;
-		case 'x':
-			++q;
-			v = va_arg(args, unsigned long);
-			prom_print_hex(v);
-			break;
-		}
-	}
-}
-
-
-static void __init __attribute__((noreturn)) prom_panic(const char *reason)
-{
-	unsigned long offset = reloc_offset();
-
-	prom_print(PTRRELOC(reason));
-	/* ToDo: should put up an SRC here */
-	call_prom("exit", 0, 0);
-
-	for (;;)			/* should never get here */
-		;
-}
-
-
-static int __init prom_next_node(phandle *nodep)
-{
-	phandle node;
-
-	if ((node = *nodep) != 0
-	    && (*nodep = call_prom("child", 1, 1, node)) != 0)
-		return 1;
-	if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
-		return 1;
-	for (;;) {
-		if ((node = call_prom("parent", 1, 1, node)) == 0)
-			return 0;
-		if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
-			return 1;
-	}
-}
-
-static int __init prom_getprop(phandle node, const char *pname,
-			       void *value, size_t valuelen)
-{
-	unsigned long offset = reloc_offset();
-
-	return call_prom("getprop", 4, 1, node, ADDR(pname),
-			 (u32)(unsigned long) value, (u32) valuelen);
-}
-
-static void __init prom_initialize_naca(void)
-{
-	phandle node;
-	char type[64];
-	unsigned long num_cpus = 0;
-	unsigned long offset = reloc_offset();
-	struct prom_t *_prom = PTRRELOC(&prom);
-	struct naca_struct *_naca = RELOC(naca);
-	struct systemcfg *_systemcfg = RELOC(systemcfg);
-
-	/* NOTE: _naca->debug_switch is already initialized. */
-	prom_debug("prom_initialize_naca: start...\n");
-
-	_naca->pftSize = 0;	/* ilog2 of htab size.  computed below. */
-
-	for (node = 0; prom_next_node(&node); ) {
-		type[0] = 0;
-		prom_getprop(node, "device_type", type, sizeof(type));
-
-		if (!strcmp(type, RELOC("cpu"))) {
-			num_cpus += 1;
-
-			/* We're assuming *all* of the CPUs have the same
-			 * d-cache and i-cache sizes... -Peter
-			 */
-			if ( num_cpus == 1 ) {
-				u32 size, lsize;
-				const char *dc, *ic;
-
-				if (_systemcfg->platform == PLATFORM_POWERMAC){
-					dc = "d-cache-block-size";
-					ic = "i-cache-block-size";
-				} else {
-					dc = "d-cache-line-size";
-					ic = "i-cache-line-size";
-				}
-
-				prom_getprop(node, "d-cache-size",
-					     &size, sizeof(size));
-
-				prom_getprop(node, dc, &lsize, sizeof(lsize));
-
-				_systemcfg->dCacheL1Size = size;
-				_systemcfg->dCacheL1LineSize = lsize;
-				_naca->dCacheL1LogLineSize = __ilog2(lsize);
-				_naca->dCacheL1LinesPerPage = PAGE_SIZE/lsize;
-
-				prom_getprop(node, "i-cache-size",
-					     &size, sizeof(size));
-
-				prom_getprop(node, ic, &lsize, sizeof(lsize));
-
-				_systemcfg->iCacheL1Size = size;
-				_systemcfg->iCacheL1LineSize = lsize;
-				_naca->iCacheL1LogLineSize = __ilog2(lsize);
-				_naca->iCacheL1LinesPerPage = PAGE_SIZE/lsize;
-
-				if (_systemcfg->platform == PLATFORM_PSERIES_LPAR) {
-					u32 pft_size[2];
-					prom_getprop(node, "ibm,pft-size",
-						&pft_size, sizeof(pft_size));
-				/* pft_size[0] is the NUMA CEC cookie */
-					_naca->pftSize = pft_size[1];
-				}
-			}
-		} else if (!strcmp(type, RELOC("serial"))) {
-			phandle isa, pci;
-			struct isa_reg_property reg;
-			union pci_range ranges;
-
-			if (_systemcfg->platform == PLATFORM_POWERMAC)
-				continue;
-			type[0] = 0;
-			prom_getprop(node, "ibm,aix-loc", type, sizeof(type));
-
-			if (strcmp(type, RELOC("S1")))
-				continue;
-
-			prom_getprop(node, "reg", &reg, sizeof(reg));
-
-			isa = call_prom("parent", 1, 1, node);
-			if (!isa)
-				PROM_BUG();
-			pci = call_prom("parent", 1, 1, isa);
-			if (!pci)
-				PROM_BUG();
-
-			prom_getprop(pci, "ranges", &ranges, sizeof(ranges));
-
-			if ( _prom->encode_phys_size == 32 )
-				_naca->serialPortAddr = ranges.pci32.phys+reg.address;
-			else {
-				_naca->serialPortAddr = 
-					((((unsigned long)ranges.pci64.phys_hi) << 32) |
-					 (ranges.pci64.phys_lo)) + reg.address;
-			}
-		}
-	}
-
-	if (_systemcfg->platform == PLATFORM_POWERMAC)
-		_naca->interrupt_controller = IC_OPEN_PIC;
-	else {
-		_naca->interrupt_controller = IC_INVALID;
-		for (node = 0; prom_next_node(&node); ) {
-			type[0] = 0;
-			prom_getprop(node, "name", type, sizeof(type));
-			if (strcmp(type, RELOC("interrupt-controller")))
-				continue;
-			prom_getprop(node, "compatible", type, sizeof(type));
-			if (strstr(type, RELOC("open-pic")))
-				_naca->interrupt_controller = IC_OPEN_PIC;
-			else if (strstr(type, RELOC("ppc-xicp")))
-				_naca->interrupt_controller = IC_PPC_XIC;
-			else
-				prom_printf("prom: failed to recognize"
-					    " interrupt-controller\n");
-			break;
-		}
-	}
-
-	if (_naca->interrupt_controller == IC_INVALID) {
-		prom_printf("prom: failed to find interrupt-controller\n");
-		PROM_BUG();
-	}
-
-	/* We gotta have at least 1 cpu... */
-	if ( (_systemcfg->processorCount = num_cpus) < 1 )
-		PROM_BUG();
-
-	_systemcfg->physicalMemorySize = lmb_phys_mem_size();
-
-	if (_systemcfg->platform == PLATFORM_PSERIES ||
-	    _systemcfg->platform == PLATFORM_POWERMAC) {
-		unsigned long rnd_mem_size, pteg_count;
-
-		/* round mem_size up to next power of 2 */
-		rnd_mem_size = 1UL << __ilog2(_systemcfg->physicalMemorySize);
-		if (rnd_mem_size < _systemcfg->physicalMemorySize)
-			rnd_mem_size <<= 1;
-
-		/* # pages / 2 */
-		pteg_count = (rnd_mem_size >> (12 + 1));
-
-		_naca->pftSize = __ilog2(pteg_count << 7);
-	}
-
-	if (_naca->pftSize == 0) {
-		prom_printf("prom: failed to compute pftSize!\n");
-		PROM_BUG();
-	}
-
-	/* Add an eye catcher and the systemcfg layout version number */
-	strcpy(_systemcfg->eye_catcher, RELOC("SYSTEMCFG:PPC64"));
-	_systemcfg->version.major = SYSTEMCFG_MAJOR;
-	_systemcfg->version.minor = SYSTEMCFG_MINOR;
-	_systemcfg->processor = _get_PVR();
-
-	prom_debug("systemcfg->processorCount       = 0x%x\n",
-		   _systemcfg->processorCount);
-	prom_debug("systemcfg->physicalMemorySize   = 0x%x\n",
-		   _systemcfg->physicalMemorySize);
-	prom_debug("naca->pftSize                   = 0x%x\n",
-		   _naca->pftSize);
-	prom_debug("systemcfg->dCacheL1LineSize     = 0x%x\n",
-		   _systemcfg->dCacheL1LineSize);
-	prom_debug("systemcfg->iCacheL1LineSize     = 0x%x\n",
-		   _systemcfg->iCacheL1LineSize);
-	prom_debug("naca->serialPortAddr            = 0x%x\n",
-		   _naca->serialPortAddr);
-	prom_debug("naca->interrupt_controller      = 0x%x\n",
-		   _naca->interrupt_controller);
-	prom_debug("systemcfg->platform             = 0x%x\n",
-		   _systemcfg->platform);
-	prom_debug("prom_initialize_naca: end...\n");
-}
-
-
-static void __init early_cmdline_parse(void)
-{
-	unsigned long offset = reloc_offset();
-	char *opt;
-#ifndef CONFIG_PMAC_DART
-	struct systemcfg *_systemcfg = RELOC(systemcfg);
-#endif
-
-	opt = strstr(RELOC(cmd_line), RELOC("iommu="));
-	if (opt) {
-		prom_printf("opt is:%s\n", opt);
-		opt += 6;
-		while (*opt && *opt == ' ')
-			opt++;
-		if (!strncmp(opt, RELOC("off"), 3))
-			RELOC(ppc64_iommu_off) = 1;
-		else if (!strncmp(opt, RELOC("force"), 5))
-			RELOC(iommu_force_on) = 1;
-	}
-
-#ifndef CONFIG_PMAC_DART
-	if (_systemcfg->platform == PLATFORM_POWERMAC) {
-		RELOC(ppc64_iommu_off) = 1;
-		prom_printf("DART disabled on PowerMac !\n");
-	}
-#endif
-}
-
-#ifdef DEBUG_PROM
-void prom_dump_lmb(void)
-{
-	unsigned long i;
-	unsigned long offset = reloc_offset();
-	struct lmb *_lmb  = PTRRELOC(&lmb);
-
-	prom_printf("\nprom_dump_lmb:\n");
-	prom_printf("    memory.cnt		  = 0x%x\n",
-		    _lmb->memory.cnt);
-	prom_printf("    memory.size		 = 0x%x\n",
-		    _lmb->memory.size);
-	for (i=0; i < _lmb->memory.cnt ;i++) {
-		prom_printf("    memory.region[0x%x].base       = 0x%x\n",
-			    i, _lmb->memory.region[i].base);
-		prom_printf("		      .physbase = 0x%x\n",
-			    _lmb->memory.region[i].physbase);
-		prom_printf("		      .size     = 0x%x\n",
-			    _lmb->memory.region[i].size);
-	}
-
-	prom_printf("\n    reserved.cnt		  = 0x%x\n",
-		    _lmb->reserved.cnt);
-	prom_printf("    reserved.size		 = 0x%x\n",
-		    _lmb->reserved.size);
-	for (i=0; i < _lmb->reserved.cnt ;i++) {
-		prom_printf("    reserved.region[0x%x\n].base       = 0x%x\n",
-			    i, _lmb->reserved.region[i].base);
-		prom_printf("		      .physbase = 0x%x\n",
-			    _lmb->reserved.region[i].physbase);
-		prom_printf("		      .size     = 0x%x\n",
-			    _lmb->reserved.region[i].size);
-	}
-}
-#endif /* DEBUG_PROM */
-
-static void __init prom_initialize_lmb(void)
-{
-	phandle node;
-	char type[64];
-	unsigned long i, offset = reloc_offset();
-	struct prom_t *_prom = PTRRELOC(&prom);
-	struct systemcfg *_systemcfg = RELOC(systemcfg);
-	union lmb_reg_property reg;
-	unsigned long lmb_base, lmb_size;
-	unsigned long num_regs, bytes_per_reg = (_prom->encode_phys_size*2)/8;
-
-	lmb_init();
-
-	/* XXX Quick HACK. Proper fix is to drop those structures and properly use
-	 * #address-cells. PowerMac has #size-cell set to 1 and #address-cells to 2
-	 */
-	if (_systemcfg->platform == PLATFORM_POWERMAC)
-		bytes_per_reg = 12;
-
-	for (node = 0; prom_next_node(&node); ) {
-		type[0] = 0;
-		prom_getprop(node, "device_type", type, sizeof(type));
-
-		if (strcmp(type, RELOC("memory")))
-			continue;
-
-		num_regs = prom_getprop(node, "reg", &reg, sizeof(reg))
-			/ bytes_per_reg;
-
-		for (i=0; i < num_regs ;i++) {
-			if (_systemcfg->platform == PLATFORM_POWERMAC) {
-				lmb_base = ((unsigned long)reg.addrPM[i].address_hi) << 32;
-				lmb_base |= (unsigned long)reg.addrPM[i].address_lo;
-				lmb_size = reg.addrPM[i].size;
-			} else if (_prom->encode_phys_size == 32) {
-				lmb_base = reg.addr32[i].address;
-				lmb_size = reg.addr32[i].size;
-			} else {
-				lmb_base = reg.addr64[i].address;
-				lmb_size = reg.addr64[i].size;
-			}
-
-			/* We limit memory to 2GB if the IOMMU is off */
-			if (RELOC(ppc64_iommu_off)) {
-				if (lmb_base >= 0x80000000UL)
-					continue;
-
-				if ((lmb_base + lmb_size) > 0x80000000UL)
-					lmb_size = 0x80000000UL - lmb_base;
-			}
-
-			if (lmb_add(lmb_base, lmb_size) < 0)
-				prom_printf("Too many LMB's, discarding this one...\n");
-		}
-
-	}
-
-	lmb_analyze();
-#ifdef DEBUG_PROM
-	prom_dump_lmb();
-#endif /* DEBUG_PROM */
-}
-
-static void __init
-prom_instantiate_rtas(void)
-{
-	unsigned long offset = reloc_offset();
-	struct prom_t *_prom = PTRRELOC(&prom);
-	struct rtas_t *_rtas = PTRRELOC(&rtas);
-	struct systemcfg *_systemcfg = RELOC(systemcfg);
-	ihandle prom_rtas;
-	u32 getprop_rval;
-	char hypertas_funcs[4];
-
-	prom_debug("prom_instantiate_rtas: start...\n");
-
-	prom_rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
-	if (prom_rtas != (ihandle) -1) {
-		unsigned long x;
-		x = prom_getprop(prom_rtas, "ibm,hypertas-functions",
-				 hypertas_funcs, sizeof(hypertas_funcs));
-
-		if (x != PROM_ERROR) {
-			prom_printf("Hypertas detected, assuming LPAR !\n");
-			_systemcfg->platform = PLATFORM_PSERIES_LPAR;
-		}
-
-		prom_getprop(prom_rtas, "rtas-size",
-			     &getprop_rval, sizeof(getprop_rval));
-		_rtas->size = getprop_rval;
-		prom_printf("instantiating rtas");
-		if (_rtas->size != 0) {
-			unsigned long rtas_region = RTAS_INSTANTIATE_MAX;
-
-			/* Grab some space within the first RTAS_INSTANTIATE_MAX bytes
-			 * of physical memory (or within the RMO region) because RTAS
-			 * runs in 32-bit mode and relocate off.
-			 */
-			if ( _systemcfg->platform == PLATFORM_PSERIES_LPAR ) {
-				struct lmb *_lmb  = PTRRELOC(&lmb);
-				rtas_region = min(_lmb->rmo_size, RTAS_INSTANTIATE_MAX);
-			}
-
-			_rtas->base = lmb_alloc_base(_rtas->size, PAGE_SIZE, rtas_region);
-
-			prom_printf(" at 0x%x", _rtas->base);
-
-			prom_rtas = call_prom("open", 1, 1, ADDR("/rtas"));
-			prom_printf("...");
-
-			if (call_prom("call-method", 3, 2,
-				      ADDR("instantiate-rtas"),
-				      prom_rtas,
-				      _rtas->base) != PROM_ERROR) {
-				_rtas->entry = (long)_prom->args.rets[1];
-			}
-			RELOC(rtas_rmo_buf)
-				= lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE,
-							rtas_region);
-		}
-
-		if (_rtas->entry <= 0) {
-			prom_printf(" failed\n");
-		} else {
-			prom_printf(" done\n");
-		}
-
-		prom_debug("rtas->base		= 0x%x\n", _rtas->base);
-		prom_debug("rtas->entry	       = 0x%x\n", _rtas->entry);
-		prom_debug("rtas->size		= 0x%x\n", _rtas->size);
-	}
-	prom_debug("prom_instantiate_rtas: end...\n");
-}
-
-
-#ifdef CONFIG_PMAC_DART
-static void __init prom_initialize_dart_table(void)
-{
-	unsigned long offset = reloc_offset();
-	extern unsigned long dart_tablebase;
-	extern unsigned long dart_tablesize;
-
-	/* Only reserve DART space if machine has more than 2GB of RAM
-	 * or if requested with iommu=on on cmdline.
-	 */
-	if (lmb_end_of_DRAM() <= 0x80000000ull && !RELOC(iommu_force_on))
-		return;
-
-	/* 512 pages (2MB) is max DART tablesize. */
-	RELOC(dart_tablesize) = 1UL << 21;
-	/* 16MB (1 << 24) alignment. We allocate a full 16Mb chuck since we
-	 * will blow up an entire large page anyway in the kernel mapping
-	 */
-	RELOC(dart_tablebase) = (unsigned long)
-		abs_to_virt(lmb_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));
-
-	prom_printf("Dart at: %x\n", RELOC(dart_tablebase));
-}
-#endif /* CONFIG_PMAC_DART */
-
-static void __init prom_initialize_tce_table(void)
-{
-	phandle node;
-	ihandle phb_node;
-	unsigned long offset = reloc_offset();
-	char compatible[64], path[64], type[64], model[64];
-	unsigned long i, table = 0;
-	unsigned long base, vbase, align;
-	unsigned int minalign, minsize;
-	struct of_tce_table *prom_tce_table = RELOC(of_tce_table);
-	unsigned long tce_entry, *tce_entryp;
-
-	if (RELOC(ppc64_iommu_off))
-		return;
-
-	prom_debug("starting prom_initialize_tce_table\n");
-
-	/* Search all nodes looking for PHBs. */
-	for (node = 0; prom_next_node(&node); ) {
-		if (table == MAX_PHB) {
-			prom_printf("WARNING: PCI host bridge ignored, "
-				    "need to increase MAX_PHB\n");
-			continue;
-		}
-
-		compatible[0] = 0;
-		type[0] = 0;
-		model[0] = 0;
-		prom_getprop(node, "compatible",
-			     compatible, sizeof(compatible));
-		prom_getprop(node, "device_type", type, sizeof(type));
-		prom_getprop(node, "model", model, sizeof(model));
-
-		/* Keep the old logic in tack to avoid regression. */
-		if (compatible[0] != 0) {
-			if ((strstr(compatible, RELOC("python")) == NULL) &&
-			    (strstr(compatible, RELOC("Speedwagon")) == NULL) &&
-			    (strstr(compatible, RELOC("Winnipeg")) == NULL))
-				continue;
-		} else if (model[0] != 0) {
-			if ((strstr(model, RELOC("ython")) == NULL) &&
-			    (strstr(model, RELOC("peedwagon")) == NULL) &&
-			    (strstr(model, RELOC("innipeg")) == NULL))
-				continue;
-		}
-
-		if ((type[0] == 0) || (strstr(type, RELOC("pci")) == NULL)) {
-			continue;
-		}
-
-		if (prom_getprop(node, "tce-table-minalign", &minalign,
-				 sizeof(minalign)) == PROM_ERROR) {
-			minalign = 0;
-		}
-
-		if (prom_getprop(node, "tce-table-minsize", &minsize,
-				 sizeof(minsize)) == PROM_ERROR) {
-			minsize = 4UL << 20;
-		}
-
-		/*
-		 * Even though we read what OF wants, we just set the table
-		 * size to 4 MB.  This is enough to map 2GB of PCI DMA space.
-		 * By doing this, we avoid the pitfalls of trying to DMA to
-		 * MMIO space and the DMA alias hole.
-		 *
-		 * On POWER4, firmware sets the TCE region by assuming
-		 * each TCE table is 8MB. Using this memory for anything
-		 * else will impact performance, so we always allocate 8MB.
-		 * Anton
-		 */
-		if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p))
-			minsize = 8UL << 20;
-		else
-			minsize = 4UL << 20;
-
-		/* Align to the greater of the align or size */
-		align = max(minalign, minsize);
-
-		/* Carve out storage for the TCE table. */
-		base = lmb_alloc(minsize, align);
-
-		if ( !base ) {
-			prom_panic("ERROR, cannot find space for TCE table.\n");
-		}
-
-		vbase = (unsigned long)abs_to_virt(base);
-
-		/* Save away the TCE table attributes for later use. */
-		prom_tce_table[table].node = node;
-		prom_tce_table[table].base = vbase;
-		prom_tce_table[table].size = minsize;
-
-		prom_debug("TCE table: 0x%x\n", table);
-		prom_debug("\tnode = 0x%x\n", node);
-		prom_debug("\tbase = 0x%x\n", vbase);
-		prom_debug("\tsize = 0x%x\n", minsize);
-
-		/* Initialize the table to have a one-to-one mapping
-		 * over the allocated size.
-		 */
-		tce_entryp = (unsigned long *)base;
-		for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
-			tce_entry = (i << PAGE_SHIFT);
-			tce_entry |= 0x3;
-			*tce_entryp = tce_entry;
-		}
-
-		/* It seems OF doesn't null-terminate the path :-( */
-		memset(path, 0, sizeof(path));
-		/* Call OF to setup the TCE hardware */
-		if (call_prom("package-to-path", 3, 1, node,
-			      path, sizeof(path)-1) == PROM_ERROR) {
-			prom_printf("package-to-path failed\n");
-		} else {
-			prom_printf("opening PHB %s", path);
-		}
-
-		phb_node = call_prom("open", 1, 1, path);
-		if ( (long)phb_node <= 0) {
-			prom_printf("... failed\n");
-		} else {
-			prom_printf("... done\n");
-		}
-		call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"),
-			  phb_node, -1, minsize,
-			  (u32) base, (u32) (base >> 32));
-		call_prom("close", 1, 0, phb_node);
-
-		table++;
-	}
-
-	/* Flag the first invalid entry */
-	prom_tce_table[table].node = 0;
-	prom_debug("ending prom_initialize_tce_table\n");
-}
-
-/*
- * With CHRP SMP we need to use the OF to start the other
- * processors so we can't wait until smp_boot_cpus (the OF is
- * trashed by then) so we have to put the processors into
- * a holding pattern controlled by the kernel (not OF) before
- * we destroy the OF.
- *
- * This uses a chunk of low memory, puts some holding pattern
- * code there and sends the other processors off to there until
- * smp_boot_cpus tells them to do something.  The holding pattern
- * checks that address until its cpu # is there, when it is that
- * cpu jumps to __secondary_start().  smp_boot_cpus() takes care
- * of setting those values.
- *
- * We also use physical address 0x4 here to tell when a cpu
- * is in its holding pattern code.
- *
- * Fixup comment... DRENG / PPPBBB - Peter
- *
- * -- Cort
- */
-static void __init prom_hold_cpus(unsigned long mem)
-{
-	unsigned long i;
-	unsigned int reg;
-	phandle node;
-	unsigned long offset = reloc_offset();
-	char type[64], *path;
-	int cpuid = 0;
-	unsigned int interrupt_server[MAX_CPU_THREADS];
-	unsigned int cpu_threads, hw_cpu_num;
-	int propsize;
-	extern void __secondary_hold(void);
-	extern unsigned long __secondary_hold_spinloop;
-	extern unsigned long __secondary_hold_acknowledge;
-	unsigned long *spinloop
-		= (void *)virt_to_abs(&__secondary_hold_spinloop);
-	unsigned long *acknowledge
-		= (void *)virt_to_abs(&__secondary_hold_acknowledge);
-	unsigned long secondary_hold
-		= virt_to_abs(*PTRRELOC((unsigned long *)__secondary_hold));
-	struct systemcfg *_systemcfg = RELOC(systemcfg);
-	struct paca_struct *lpaca = PTRRELOC(&paca[0]);
-	struct prom_t *_prom = PTRRELOC(&prom);
-#ifdef CONFIG_SMP
-	struct naca_struct *_naca = RELOC(naca);
-#endif
-
-	/* On pmac, we just fill out the various global bitmasks and
-	 * arrays indicating our CPUs are here, they are actually started
-	 * later on from pmac_smp
-	 */
-	if (_systemcfg->platform == PLATFORM_POWERMAC) {
-		for (node = 0; prom_next_node(&node); ) {
-			type[0] = 0;
-			prom_getprop(node, "device_type", type, sizeof(type));
-			if (strcmp(type, RELOC("cpu")) != 0)
-				continue;
-			reg = -1;
-			prom_getprop(node, "reg", &reg, sizeof(reg));
-			lpaca[cpuid].hw_cpu_id = reg;
-
-#ifdef CONFIG_SMP
-			cpu_set(cpuid, RELOC(cpu_available_map));
-			cpu_set(cpuid, RELOC(cpu_possible_map));
-			cpu_set(cpuid, RELOC(cpu_present_at_boot));
-			if (reg == 0)
-				cpu_set(cpuid, RELOC(cpu_online_map));
-#endif /* CONFIG_SMP */
-			cpuid++;
-		}
-		return;
-	}
-
-	/* Initially, we must have one active CPU. */
-	_systemcfg->processorCount = 1;
-
-	prom_debug("prom_hold_cpus: start...\n");
-	prom_debug("    1) spinloop       = 0x%x\n", (unsigned long)spinloop);
-	prom_debug("    1) *spinloop      = 0x%x\n", *spinloop);
-	prom_debug("    1) acknowledge    = 0x%x\n",
-		   (unsigned long)acknowledge);
-	prom_debug("    1) *acknowledge   = 0x%x\n", *acknowledge);
-	prom_debug("    1) secondary_hold = 0x%x\n", secondary_hold);
-
-	/* Set the common spinloop variable, so all of the secondary cpus
-	 * will block when they are awakened from their OF spinloop.
-	 * This must occur for both SMP and non SMP kernels, since OF will
-	 * be trashed when we move the kernel.
-	 */
-	*spinloop = 0;
-
-#ifdef CONFIG_HMT
-	for (i=0; i < NR_CPUS; i++) {
-		RELOC(hmt_thread_data)[i].pir = 0xdeadbeef;
-	}
-#endif
-	/* look for cpus */
-	for (node = 0; prom_next_node(&node); ) {
-		type[0] = 0;
-		prom_getprop(node, "device_type", type, sizeof(type));
-		if (strcmp(type, RELOC("cpu")) != 0)
-			continue;
-
-		/* Skip non-configured cpus. */
-		prom_getprop(node, "status", type, sizeof(type));
-		if (strcmp(type, RELOC("okay")) != 0)
-			continue;
-
-		reg = -1;
-		prom_getprop(node, "reg", &reg, sizeof(reg));
-
-		path = (char *) mem;
-		memset(path, 0, 256);
-		if (call_prom("package-to-path", 3, 1,
-			      node, path, 255) == PROM_ERROR)
-			continue;
-
-		prom_debug("\ncpuid        = 0x%x\n", cpuid);
-		prom_debug("cpu hw idx   = 0x%x\n", reg);
-		lpaca[cpuid].hw_cpu_id = reg;
-
-		/* Init the acknowledge var which will be reset by
-		 * the secondary cpu when it awakens from its OF
-		 * spinloop.
-		 */
-		*acknowledge = (unsigned long)-1;
-
-		propsize = prom_getprop(node, "ibm,ppc-interrupt-server#s",
-					&interrupt_server,
-					sizeof(interrupt_server));
-		if (propsize < 0) {
-			/* no property.  old hardware has no SMT */
-			cpu_threads = 1;
-			interrupt_server[0] = reg; /* fake it with phys id */
-		} else {
-			/* We have a threaded processor */
-			cpu_threads = propsize / sizeof(u32);
-			if (cpu_threads > MAX_CPU_THREADS) {
-				prom_printf("SMT: too many threads!\n"
-					    "SMT: found %x, max is %x\n",
-					    cpu_threads, MAX_CPU_THREADS);
-				cpu_threads = 1; /* ToDo: panic? */
-			}
-		}
-
-		hw_cpu_num = interrupt_server[0];
-		if (hw_cpu_num != _prom->cpu) {
-			/* Primary Thread of non-boot cpu */
-			prom_printf("%x : starting cpu %s... ", cpuid, path);
-			call_prom("start-cpu", 3, 0, node,
-				  secondary_hold, cpuid);
-
-			for ( i = 0 ; (i < 100000000) && 
-			      (*acknowledge == ((unsigned long)-1)); i++ ) ;
-
-			if (*acknowledge == cpuid) {
-				prom_printf("... done\n");
-				/* We have to get every CPU out of OF,
-				 * even if we never start it. */
-				if (cpuid >= NR_CPUS)
-					goto next;
-#ifdef CONFIG_SMP
-				/* Set the number of active processors. */
-				_systemcfg->processorCount++;
-				cpu_set(cpuid, RELOC(cpu_available_map));
-				cpu_set(cpuid, RELOC(cpu_possible_map));
-				cpu_set(cpuid, RELOC(cpu_present_at_boot));
-#endif
-			} else {
-				prom_printf("... failed: %x\n", *acknowledge);
-			}
-		}
-#ifdef CONFIG_SMP
-		else {
-			prom_printf("%x : booting  cpu %s\n", cpuid, path);
-			cpu_set(cpuid, RELOC(cpu_available_map));
-			cpu_set(cpuid, RELOC(cpu_possible_map));
-			cpu_set(cpuid, RELOC(cpu_online_map));
-			cpu_set(cpuid, RELOC(cpu_present_at_boot));
-		}
-#endif
-next:
-#ifdef CONFIG_SMP
-		/* Init paca for secondary threads.   They start later. */
-		for (i=1; i < cpu_threads; i++) {
-			cpuid++;
-			if (cpuid >= NR_CPUS)
-				continue;
-			lpaca[cpuid].hw_cpu_id = interrupt_server[i];
-			prom_printf("%x : preparing thread ... ",
-				    interrupt_server[i]);
-			if (_naca->smt_state) {
-				cpu_set(cpuid, RELOC(cpu_available_map));
-				cpu_set(cpuid, RELOC(cpu_present_at_boot));
-				prom_printf("available\n");
-			} else {
-				prom_printf("not available\n");
-			}
-		}
-#endif
-		cpuid++;
-	}
-#ifdef CONFIG_HMT
-	/* Only enable HMT on processors that provide support. */
-	if (__is_processor(PV_PULSAR) || 
-	    __is_processor(PV_ICESTAR) ||
-	    __is_processor(PV_SSTAR)) {
-		prom_printf("    starting secondary threads\n");
-
-		for (i = 0; i < NR_CPUS; i += 2) {
-			if (!cpu_online(i))
-				continue;
-
-			if (i == 0) {
-				unsigned long pir = _get_PIR();
-				if (__is_processor(PV_PULSAR)) {
-					RELOC(hmt_thread_data)[i].pir = 
-						pir & 0x1f;
-				} else {
-					RELOC(hmt_thread_data)[i].pir = 
-						pir & 0x3ff;
-				}
-			}
-/* 			cpu_set(i+1, cpu_online_map); */
-			cpu_set(i+1, RELOC(cpu_possible_map));
-		}
-		_systemcfg->processorCount *= 2;
-	} else {
-		prom_printf("Processor is not HMT capable\n");
-	}
-#endif
-
-	if (cpuid > NR_CPUS)
-		prom_printf("WARNING: maximum CPUs (" __stringify(NR_CPUS)
-			    ") exceeded: ignoring extras\n");
-
-	prom_debug("prom_hold_cpus: end...\n");
-}
-
-static void __init smt_setup(void)
-{
-	char *p, *q;
-	char my_smt_enabled = SMT_DYNAMIC;
-	ihandle prom_options = 0;
-	char option[9];
-	unsigned long offset = reloc_offset();
-	struct naca_struct *_naca = RELOC(naca);
-	char found = 0;
-
-	if (strstr(RELOC(cmd_line), RELOC("smt-enabled="))) {
-		for (q = RELOC(cmd_line); (p = strstr(q, RELOC("smt-enabled="))) != 0; ) {
-			q = p + 12;
-			if (p > RELOC(cmd_line) && p[-1] != ' ')
-				continue;
-			found = 1;
-			if (q[0] == 'o' && q[1] == 'f' && 
-			    q[2] == 'f' && (q[3] == ' ' || q[3] == '\0')) {
-				my_smt_enabled = SMT_OFF;
-			} else if (q[0]=='o' && q[1] == 'n' && 
-				   (q[2] == ' ' || q[2] == '\0')) {
-				my_smt_enabled = SMT_ON;
-			} else {
-				my_smt_enabled = SMT_DYNAMIC;
-			} 
-		}
-	}
-	if (!found) {
-		prom_options = call_prom("finddevice", 1, 1, ADDR("/options"));
-		if (prom_options != (ihandle) -1) {
-			prom_getprop(prom_options, "ibm,smt-enabled",
-				     option, sizeof(option));
-			if (option[0] != 0) {
-				found = 1;
-				if (!strcmp(option, RELOC("off")))
-					my_smt_enabled = SMT_OFF;
-				else if (!strcmp(option, RELOC("on")))
-					my_smt_enabled = SMT_ON;
-				else
-					my_smt_enabled = SMT_DYNAMIC;
-			}
-		}
-	}
-
-	if (!found )
-		my_smt_enabled = SMT_DYNAMIC; /* default to on */
-
-	_naca->smt_state = my_smt_enabled;
-}
-
-
-#ifdef CONFIG_BOOTX_TEXT
-
-/* This function will enable the early boot text when doing OF booting. This
- * way, xmon output should work too
- */
-static void __init setup_disp_fake_bi(ihandle dp)
-{
-	int width = 640, height = 480, depth = 8, pitch;
-	unsigned address;
-	struct pci_reg_property addrs[8];
-	int i, naddrs;
-	char name[64];
-	unsigned long offset = reloc_offset();
-
-	memset(name, 0, sizeof(name));
-	prom_getprop(dp, "name", name, sizeof(name));
-	name[sizeof(name)-1] = 0;
-	prom_printf("Initializing fake screen: %s\n", name);
-
-	prom_getprop(dp, "width", &width, sizeof(width));
-	prom_getprop(dp, "height", &height, sizeof(height));
-	prom_getprop(dp, "depth", &depth, sizeof(depth));
-	pitch = width * ((depth + 7) / 8);
-	prom_getprop(dp, "linebytes", &pitch, sizeof(pitch));
-	if (pitch == 1)
-		pitch = 0x1000;		/* for strange IBM display */
-	address = 0;
-
-	prom_printf("width %x height %x depth %x linebytes %x\n",
-		    width, height, depth, depth);
-
-	prom_getprop(dp, "address", &address, sizeof(address));
-	if (address == 0) {
-		/* look for an assigned address with a size of >= 1MB */
-		naddrs = prom_getprop(dp, "assigned-addresses",
-				      addrs, sizeof(addrs));
-		naddrs /= sizeof(struct pci_reg_property);
-		for (i = 0; i < naddrs; ++i) {
-			if (addrs[i].size_lo >= (1 << 20)) {
-				address = addrs[i].addr.a_lo;
-				/* use the BE aperture if possible */
-				if (addrs[i].size_lo >= (16 << 20))
-					address += (8 << 20);
-				break;
-			}
-		}
-		if (address == 0) {
-			prom_printf("Failed to get address of frame buffer\n");
-			return;
-		}
-	}
-	btext_setup_display(width, height, depth, pitch, address);
-	prom_printf("Addr of fb: %x\n", address);
-	RELOC(boot_text_mapped) = 0;
-}
-#endif /* CONFIG_BOOTX_TEXT */
-
-static void __init prom_init_client_services(unsigned long pp)
-{
-	unsigned long offset = reloc_offset();
-	struct prom_t *_prom = PTRRELOC(&prom);
-
-	/* Get a handle to the prom entry point before anything else */
-	_prom->entry = pp;
-
-	/* Init default value for phys size */
-	_prom->encode_phys_size = 32;
-
-	/* get a handle for the stdout device */
-	_prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
-	if ((long)_prom->chosen <= 0)
-		prom_panic("cannot find chosen"); /* msg won't be printed :( */
-
-	/* get device tree root */
-	_prom->root = call_prom("finddevice", 1, 1, ADDR("/"));
-	if ((long)_prom->root <= 0)
-		prom_panic("cannot find device tree root"); /* msg won't be printed :( */
-}
-
-static void __init prom_init_stdout(void)
-{
-	unsigned long offset = reloc_offset();
-	struct prom_t *_prom = PTRRELOC(&prom);
-	u32 val;
-
-	if (prom_getprop(_prom->chosen, "stdout", &val, sizeof(val)) <= 0)
-		prom_panic("cannot find stdout");
-
-	_prom->stdout = val;
-}
-
-static int __init prom_find_machine_type(void)
-{
-	unsigned long offset = reloc_offset();
-	struct prom_t *_prom = PTRRELOC(&prom);
-	char compat[256];
-	int len, i = 0;
-
-	len = prom_getprop(_prom->root, "compatible",
-			   compat, sizeof(compat)-1);
-	if (len > 0) {
-		compat[len] = 0;
-		while (i < len) {
-			char *p = &compat[i];
-			int sl = strlen(p);
-			if (sl == 0)
-				break;
-			if (strstr(p, RELOC("Power Macintosh")) ||
-			    strstr(p, RELOC("MacRISC4")))
-				return PLATFORM_POWERMAC;
-			i += sl + 1;
-		}
-	}
-	/* Default to pSeries */
-	return PLATFORM_PSERIES;
-}
-
-static int __init prom_set_color(ihandle ih, int i, int r, int g, int b)
-{
-	unsigned long offset = reloc_offset();
-
-	return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r);
-}
-
-/*
- * If we have a display that we don't know how to drive,
- * we will want to try to execute OF's open method for it
- * later.  However, OF will probably fall over if we do that
- * we've taken over the MMU.
- * So we check whether we will need to open the display,
- * and if so, open it now.
- */
-static unsigned long __init check_display(unsigned long mem)
-{
-	phandle node;
-	ihandle ih;
-	int i, j;
-	unsigned long offset = reloc_offset();
-	struct prom_t *_prom = PTRRELOC(&prom);
-	char type[16], *path;
-	static unsigned char default_colors[] = {
-		0x00, 0x00, 0x00,
-		0x00, 0x00, 0xaa,
-		0x00, 0xaa, 0x00,
-		0x00, 0xaa, 0xaa,
-		0xaa, 0x00, 0x00,
-		0xaa, 0x00, 0xaa,
-		0xaa, 0xaa, 0x00,
-		0xaa, 0xaa, 0xaa,
-		0x55, 0x55, 0x55,
-		0x55, 0x55, 0xff,
-		0x55, 0xff, 0x55,
-		0x55, 0xff, 0xff,
-		0xff, 0x55, 0x55,
-		0xff, 0x55, 0xff,
-		0xff, 0xff, 0x55,
-		0xff, 0xff, 0xff
-	};
-	const unsigned char *clut;
-
-	_prom->disp_node = 0;
-
-	prom_printf("Looking for displays\n");
-	if (RELOC(of_stdout_device) != 0)
-		prom_printf("OF stdout is    : %s\n",
-			    PTRRELOC(RELOC(of_stdout_device)));
-	for (node = 0; prom_next_node(&node); ) {
-		type[0] = 0;
-		prom_getprop(node, "device_type", type, sizeof(type));
-		if (strcmp(type, RELOC("display")) != 0)
-			continue;
-		/* It seems OF doesn't null-terminate the path :-( */
-		path = (char *) mem;
-		memset(path, 0, 256);
-
-		/*
-		 * leave some room at the end of the path for appending extra
-		 * arguments
-		 */
-		if (call_prom("package-to-path", 3, 1, node, path, 250) < 0)
-			continue;
-		prom_printf("found display   : %s\n", path);
-		
-		/*
-		 * If this display is the device that OF is using for stdout,
-		 * move it to the front of the list.
-		 */
-		mem += strlen(path) + 1;
-		i = RELOC(prom_num_displays);
-		RELOC(prom_num_displays) = i + 1;
-		if (RELOC(of_stdout_device) != 0 && i > 0
-		    && strcmp(PTRRELOC(RELOC(of_stdout_device)), path) == 0) {
-			for (; i > 0; --i) {
-				RELOC(prom_display_paths[i])
-					= RELOC(prom_display_paths[i-1]);
-				RELOC(prom_display_nodes[i])
-					= RELOC(prom_display_nodes[i-1]);
-			}
-			_prom->disp_node = node;
-		}
-		RELOC(prom_display_paths[i]) = PTRUNRELOC(path);
-		RELOC(prom_display_nodes[i]) = node;
-		if (_prom->disp_node == 0)
-			_prom->disp_node = node;
-		if (RELOC(prom_num_displays) >= FB_MAX)
-			break;
-	}
-	prom_printf("Opening displays...\n");
-	for (j = RELOC(prom_num_displays) - 1; j >= 0; j--) {
-		path = PTRRELOC(RELOC(prom_display_paths[j]));
-		prom_printf("opening display : %s", path);
-		ih = call_prom("open", 1, 1, path);
-		if (ih == (ihandle)0 || ih == (ihandle)-1) {
-			prom_printf("... failed\n");
-			continue;
-		}
-
-		prom_printf("... done\n");
-
-		/* Setup a useable color table when the appropriate
-		 * method is available. Should update this to set-colors */
-		clut = RELOC(default_colors);
-		for (i = 0; i < 32; i++, clut += 3)
-			if (prom_set_color(ih, i, clut[0], clut[1],
-					   clut[2]) != 0)
-				break;
-
-#ifdef CONFIG_LOGO_LINUX_CLUT224
-		clut = PTRRELOC(RELOC(logo_linux_clut224.clut));
-		for (i = 0; i < RELOC(logo_linux_clut224.clutsize); i++, clut += 3)
-			if (prom_set_color(ih, i + 32, clut[0], clut[1],
-					   clut[2]) != 0)
-				break;
-#endif /* CONFIG_LOGO_LINUX_CLUT224 */
-	}
-
-	return DOUBLEWORD_ALIGN(mem);
-}
-
-/* Return (relocated) pointer to this much memory: moves initrd if reqd. */
-static void __init *__make_room(unsigned long *mem_start, unsigned long *mem_end,
-				unsigned long needed, unsigned long align)
-{
-	void *ret;
-
-	*mem_start = ALIGN(*mem_start, align);
-	if (*mem_start + needed > *mem_end) {
-#ifdef CONFIG_BLK_DEV_INITRD
-		unsigned long offset = reloc_offset();
-		/* FIXME: Apple OF doesn't map unclaimed mem.  If this
-		 * ever happened on G5, we'd need to fix. */
-		unsigned long initrd_len;
-
-		if (*mem_end != RELOC(initrd_start))
-			prom_panic("No memory for copy_device_tree");
-
-		prom_printf("Huge device_tree: moving initrd\n");
-		/* Move by 4M. */
-		initrd_len = RELOC(initrd_end) - RELOC(initrd_start);
-		*mem_end = RELOC(initrd_start) + 4 * 1024 * 1024;
-		memmove((void *)*mem_end, (void *)RELOC(initrd_start),
-			initrd_len);
-		RELOC(initrd_start) = *mem_end;
-		RELOC(initrd_end) = RELOC(initrd_start) + initrd_len;
-#else
-		prom_panic("No memory for copy_device_tree");
-#endif
-	}
-
-	ret = (void *)*mem_start;
-	*mem_start += needed;
-
-	return ret;
-}
-
-#define make_room(startp, endp, type) \
-	__make_room(startp, endp, sizeof(type), __alignof__(type))
-
-static void __init
-inspect_node(phandle node, struct device_node *dad,
-	     unsigned long *mem_start, unsigned long *mem_end,
-	     struct device_node ***allnextpp)
-{
-	int l;
-	phandle child;
-	struct device_node *np;
-	struct property *pp, **prev_propp;
-	char *prev_name, *namep;
-	unsigned char *valp;
-	unsigned long offset = reloc_offset();
-	phandle ibm_phandle;
-
-	np = make_room(mem_start, mem_end, struct device_node);
-	memset(np, 0, sizeof(*np));
-
-	np->node = node;
-	**allnextpp = PTRUNRELOC(np);
-	*allnextpp = &np->allnext;
-	if (dad != 0) {
-		np->parent = PTRUNRELOC(dad);
-		/* we temporarily use the `next' field as `last_child'. */
-		if (dad->next == 0)
-			dad->child = PTRUNRELOC(np);
-		else
-			dad->next->sibling = PTRUNRELOC(np);
-		dad->next = np;
-	}
-
-	/* get and store all properties */
-	prev_propp = &np->properties;
-	prev_name = RELOC("");
-	for (;;) {
-		/* 32 is max len of name including nul. */
-		namep = make_room(mem_start, mem_end, char[32]);
-		if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0) {
-			/* No more nodes: unwind alloc */
-			*mem_start = (unsigned long)namep;
-			break;
-		}
-		/* Trim off some if we can */
-		*mem_start = DOUBLEWORD_ALIGN((unsigned long)namep
-					     + strlen(namep) + 1);
-		pp = make_room(mem_start, mem_end, struct property);
-		pp->name = PTRUNRELOC(namep);
-		prev_name = namep;
-
-		pp->length = call_prom("getproplen", 2, 1, node, namep);
-		if (pp->length < 0)
-			continue;
-		if (pp->length > MAX_PROPERTY_LENGTH) {
-			char path[128];
-
-			prom_printf("WARNING: ignoring large property ");
-			/* It seems OF doesn't null-terminate the path :-( */
-			memset(path, 0, sizeof(path));
-			if (call_prom("package-to-path", 3, 1, node,
-				      path, sizeof(path)-1) > 0)
-				prom_printf("[%s] ", path);
-			prom_printf("%s length 0x%x\n", namep, pp->length);
-			continue;
-		}
-		valp = __make_room(mem_start, mem_end, pp->length, 1);
-		pp->value = PTRUNRELOC(valp);
-		call_prom("getprop", 4, 1, node, namep, valp, pp->length);
-		*prev_propp = PTRUNRELOC(pp);
-		prev_propp = &pp->next;
-	}
-
-	/* Add a "linux,phandle" property. */
-	namep = make_room(mem_start, mem_end, char[16]);
-	strcpy(namep, RELOC("linux,phandle"));
-	pp = make_room(mem_start, mem_end, struct property);
-	pp->name = PTRUNRELOC(namep);
-	pp->length = sizeof(phandle);
-	valp = make_room(mem_start, mem_end, phandle);
-	pp->value = PTRUNRELOC(valp);
-	*(phandle *)valp = node;
-	*prev_propp = PTRUNRELOC(pp);
-	pp->next = NULL;
-
-	/* Set np->linux_phandle to the value of the ibm,phandle property
-	   if it exists, otherwise to the phandle for this node. */
-	np->linux_phandle = node;
-	if (prom_getprop(node, "ibm,phandle",
-			 &ibm_phandle, sizeof(ibm_phandle)) > 0)
-		np->linux_phandle = ibm_phandle;
-
-	/* get the node's full name */
-	namep = (char *)*mem_start;
-	l = call_prom("package-to-path", 3, 1, node,
-		      namep, *mem_end - *mem_start);
-	if (l >= 0) {
-		/* Didn't fit?  Get more room. */
-		if (l+1 > *mem_end - *mem_start) {
-			namep = __make_room(mem_start, mem_end, l+1, 1);
-			call_prom("package-to-path", 3, 1, node, namep, l);
-		}
-		np->full_name = PTRUNRELOC(namep);
-		namep[l] = '\0';
-		*mem_start = DOUBLEWORD_ALIGN(*mem_start + l + 1);
-	}
-
-	/* do all our children */
-	child = call_prom("child", 1, 1, node);
-	while (child != (phandle)0) {
-		inspect_node(child, np, mem_start, mem_end,
-					 allnextpp);
-		child = call_prom("peer", 1, 1, child);
-	}
-}
-
-/*
- * Make a copy of the device tree from the PROM.
- */
-static unsigned long __init
-copy_device_tree(unsigned long mem_start)
-{
-	phandle root;
-	struct device_node **allnextp;
-	unsigned long offset = reloc_offset();
-	unsigned long mem_end;
-
-	/* We pass mem_end-mem_start to OF: keep it well under 32-bit */
-	mem_end = mem_start + 1024*1024*1024;
-#ifdef CONFIG_BLK_DEV_INITRD
-	if (RELOC(initrd_start) && RELOC(initrd_start) > mem_start)
-		mem_end = RELOC(initrd_start);
-#endif /* CONFIG_BLK_DEV_INITRD */
-
-	root = call_prom("peer", 1, 1, (phandle)0);
-	if (root == (phandle)0) {
-		prom_panic("couldn't get device tree root\n");
-	}
-	allnextp = &RELOC(allnodes);
-	inspect_node(root, NULL, &mem_start, &mem_end, &allnextp);
-	*allnextp = NULL;
-	return mem_start;
-}
-
-/* Verify bi_recs are good */
-static struct bi_record * __init prom_bi_rec_verify(struct bi_record *bi_recs)
-{
-	struct bi_record *first, *last;
-
-	prom_debug("birec_verify: r6=0x%x\n", (unsigned long)bi_recs);
-	if (bi_recs != NULL)
-		prom_debug("  tag=0x%x\n", bi_recs->tag);
-
-	if ( bi_recs == NULL || bi_recs->tag != BI_FIRST )
-		return NULL;
-
-	last = (struct bi_record *)(long)bi_recs->data[0];
-
-	prom_debug("  last=0x%x\n", (unsigned long)last);
-	if (last != NULL)
-		prom_debug("  last_tag=0x%x\n", last->tag);
-
-	if ( last == NULL || last->tag != BI_LAST )
-		return NULL;
-
-	first = (struct bi_record *)(long)last->data[0];
-	prom_debug("  first=0x%x\n", (unsigned long)first);
-
-	if ( first == NULL || first != bi_recs )
-		return NULL;
-
-	return bi_recs;
-}
-
-static void __init prom_bi_rec_reserve(void)
-{
-	unsigned long offset = reloc_offset();
-	struct prom_t *_prom = PTRRELOC(&prom);
-	struct bi_record *rec;
-
-	if ( _prom->bi_recs != NULL) {
-
-		for ( rec=_prom->bi_recs;
-		      rec->tag != BI_LAST;
-		      rec=bi_rec_next(rec) ) {
-			prom_debug("bi: 0x%x\n", rec->tag);
-			switch (rec->tag) {
-#ifdef CONFIG_BLK_DEV_INITRD
-			case BI_INITRD:
-				RELOC(initrd_start) = (unsigned long)(rec->data[0]);
-				RELOC(initrd_end) = RELOC(initrd_start) + rec->data[1];
-				break;
-#endif /* CONFIG_BLK_DEV_INITRD */
-			}
-		}
-		/* The next use of this field will be after relocation
-	 	 * is enabled, so convert this physical address into a
-	 	 * virtual address.
-	 	 */
-		_prom->bi_recs = PTRUNRELOC(_prom->bi_recs);
-	}
-}
-
-/*
- * We enter here early on, when the Open Firmware prom is still
- * handling exceptions and the MMU hash table for us.
- */
-
-unsigned long __init
-prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
-	  unsigned long r6, unsigned long r7)
-{
-	unsigned long mem;
-	ihandle prom_cpu;
-	phandle cpu_pkg;
-	unsigned long offset = reloc_offset();
-	long l;
-	char *p, *d;
-	unsigned long phys;
-	u32 getprop_rval;
-	struct systemcfg *_systemcfg;
-	struct paca_struct *lpaca = PTRRELOC(&paca[0]);
-	struct prom_t *_prom = PTRRELOC(&prom);
-
-	/* First zero the BSS -- use memset, some arches don't have
-	 * caches on yet */
-	memset(PTRRELOC(&__bss_start), 0, __bss_stop - __bss_start);
-
-	/* Setup systemcfg and NACA pointers now */
-	RELOC(systemcfg) = _systemcfg = (struct systemcfg *)(SYSTEMCFG_VIRT_ADDR - offset);
-	RELOC(naca) = (struct naca_struct *)(NACA_VIRT_ADDR - offset);
-
-	/* Init interface to Open Firmware and pickup bi-recs */
-	prom_init_client_services(pp);
-
-	/* Init prom stdout device */
-	prom_init_stdout();
-
-	prom_debug("klimit=0x%x\n", RELOC(klimit));
-	prom_debug("offset=0x%x\n", offset);
-	prom_debug("->mem=0x%x\n", RELOC(klimit) - offset);
-
-	/* check out if we have bi_recs */
-	_prom->bi_recs = prom_bi_rec_verify((struct bi_record *)r6);
-	if ( _prom->bi_recs != NULL ) {
-		RELOC(klimit) = PTRUNRELOC((unsigned long)_prom->bi_recs +
-					   _prom->bi_recs->data[1]);
-		prom_debug("bi_recs=0x%x\n", (unsigned long)_prom->bi_recs);
-		prom_debug("new mem=0x%x\n", RELOC(klimit) - offset);
-	}
-
-	/* If we don't have birec's or didn't find them, check for an initrd
-	 * using the "yaboot" way
-	 */
-#ifdef CONFIG_BLK_DEV_INITRD
-	if ( _prom->bi_recs == NULL && r3 && r4 && r4 != 0xdeadbeef) {
-		RELOC(initrd_start) = (r3 >= KERNELBASE) ? __pa(r3) : r3;
-		RELOC(initrd_end) = RELOC(initrd_start) + r4;
-		RELOC(initrd_below_start_ok) = 1;
-	}
-#endif /* CONFIG_BLK_DEV_INITRD */
-
-	/* Default machine type. */
-	_systemcfg->platform = prom_find_machine_type();
-
-	/* On pSeries, copy the CPU hold code */
-	if (_systemcfg->platform == PLATFORM_PSERIES)
-		copy_and_flush(0, KERNELBASE - offset, 0x100, 0);
-
-	/* Start storing things at klimit */
-	mem = RELOC(klimit) - offset;
-
-	/* Get the full OF pathname of the stdout device */
-	p = (char *) mem;
-	memset(p, 0, 256);
-	call_prom("instance-to-path", 3, 1, _prom->stdout, p, 255);
-	RELOC(of_stdout_device) = PTRUNRELOC(p);
-	mem += strlen(p) + 1;
-
-	getprop_rval = 1;
-	prom_getprop(_prom->root, "#size-cells",
-		     &getprop_rval, sizeof(getprop_rval));
-	_prom->encode_phys_size = (getprop_rval == 1) ? 32 : 64;
-
-	/* Determine which cpu is actually running right _now_ */
-	if (prom_getprop(_prom->chosen, "cpu",
-			 &prom_cpu, sizeof(prom_cpu)) <= 0)
-		prom_panic("cannot find boot cpu");
-
-	cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
-	prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval));
-	_prom->cpu = getprop_rval;
-	lpaca[0].hw_cpu_id = _prom->cpu;
-
-	RELOC(boot_cpuid) = 0;
-
-	prom_debug("Booting CPU hw index = 0x%x\n", _prom->cpu);
-
-	/* Get the boot device and translate it to a full OF pathname. */
-	p = (char *) mem;
-	l = prom_getprop(_prom->chosen, "bootpath", p, 1<<20);
-	if (l > 0) {
-		p[l] = 0;	/* should already be null-terminated */
-		RELOC(bootpath) = PTRUNRELOC(p);
-		mem += l + 1;
-		d = (char *) mem;
-		*d = 0;
-		call_prom("canon", 3, 1, p, d, 1<<20);
-		RELOC(bootdevice) = PTRUNRELOC(d);
-		mem = DOUBLEWORD_ALIGN(mem + strlen(d) + 1);
-	}
-
-	RELOC(cmd_line[0]) = 0;
-	if ((long)_prom->chosen > 0) {
-		prom_getprop(_prom->chosen, "bootargs", p, sizeof(cmd_line));
-		if (p != NULL && p[0] != 0)
-			strlcpy(RELOC(cmd_line), p, sizeof(cmd_line));
-	}
-
-	early_cmdline_parse();
-
-	prom_initialize_lmb();
-
-	prom_bi_rec_reserve();
-
-	mem = check_display(mem);
-
-	if (_systemcfg->platform != PLATFORM_POWERMAC)
-		prom_instantiate_rtas();
-
-	/* Initialize some system info into the Naca early... */
-	prom_initialize_naca();
-
-	smt_setup();
-
-	/* If we are on an SMP machine, then we *MUST* do the
-	 * following, regardless of whether we have an SMP
-	 * kernel or not.
-	 */
-	prom_hold_cpus(mem);
-
-	prom_debug("after basic inits, mem=0x%x\n", mem);
-#ifdef CONFIG_BLK_DEV_INITRD
-	prom_debug("initrd_start=0x%x\n", RELOC(initrd_start));
-	prom_debug("initrd_end=0x%x\n", RELOC(initrd_end));
-#endif /* CONFIG_BLK_DEV_INITRD */
-	prom_debug("copying OF device tree...\n");
-
-	mem = copy_device_tree(mem);
-
-	RELOC(klimit) = mem + offset;
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
 
-	prom_debug("new klimit is\n");
-	prom_debug("klimit=0x%x\n", RELOC(klimit));
-	prom_debug(" ->mem=0x%x\n", mem);
+struct pci_reg_property {
+	struct pci_address addr;
+	u32 size_hi;
+	u32 size_lo;
+};
 
-	lmb_reserve(0, __pa(RELOC(klimit)));
+struct isa_reg_property {
+	u32 space;
+	u32 address;
+	u32 size;
+};
 
-#ifdef CONFIG_BLK_DEV_INITRD
-	if (RELOC(initrd_start)) {
-		unsigned long initrd_len;
-		initrd_len = RELOC(initrd_end) - RELOC(initrd_start);
 
-		/* Move initrd if it's where we're going to copy kernel. */
-		if (RELOC(initrd_start) < __pa(RELOC(klimit))) {
-			memmove((void *)mem, (void *)RELOC(initrd_start),
-				initrd_len);
-			RELOC(initrd_start) = mem;
-			RELOC(initrd_end) = mem + initrd_len;
-		}
+typedef unsigned long interpret_func(struct device_node *, unsigned long,
+				     int, int, int);
 
-		lmb_reserve(RELOC(initrd_start), initrd_len);
-	}
-#endif /* CONFIG_BLK_DEV_INITRD */
+extern struct rtas_t rtas;
+extern struct lmb lmb;
+extern unsigned long klimit;
 
-	if (_systemcfg->platform == PLATFORM_PSERIES)
-		prom_initialize_tce_table();
+static int __initdata dt_root_addr_cells;
+static int __initdata dt_root_size_cells;
+static int __initdata iommu_is_off;
+int __initdata iommu_force_on;
+typedef u32 cell_t;
 
-#ifdef CONFIG_PMAC_DART
-	if (_systemcfg->platform == PLATFORM_POWERMAC)
-		prom_initialize_dart_table();
+#if 0
+static struct boot_param_header *initial_boot_params __initdata;
+#else
+struct boot_param_header *initial_boot_params;
 #endif
 
-#ifdef CONFIG_BOOTX_TEXT
-	if (_prom->disp_node) {
-		prom_printf("Setting up bi display...\n");
-		setup_disp_fake_bi(_prom->disp_node);
-	}
-#endif /* CONFIG_BOOTX_TEXT */
-
-	prom_printf("Calling quiesce ...\n");
-	call_prom("quiesce", 0, 0);
-	phys = KERNELBASE - offset;
+static struct device_node *allnodes = NULL;
 
-#ifdef CONFIG_BLK_DEV_INITRD
-	/* If we had an initrd, we convert its address to virtual */
-	if (RELOC(initrd_start)) {
-		RELOC(initrd_start) = (unsigned long)__va(RELOC(initrd_start));
-		RELOC(initrd_end) = (unsigned long)__va(RELOC(initrd_end));
-	}
-#endif /* CONFIG_BLK_DEV_INITRD */
+/* use when traversing tree through the allnext, child, sibling,
+ * or parent members of struct device_node.
+ */
+static rwlock_t devtree_lock = RW_LOCK_UNLOCKED;
 
-	prom_printf("returning from prom_init\n");
-	return phys;
-}
+/* export that to outside world */
+struct device_node *of_chosen;
 
 /*
  * Find the device_node with a given phandle.
  */
-static struct device_node * __devinit
-find_phandle(phandle ph)
+static struct device_node * find_phandle(phandle ph)
 {
 	struct device_node *np;
 
@@ -1866,8 +118,7 @@ find_phandle(phandle ph)
 /*
  * Find the interrupt parent of a node.
  */
-static struct device_node * __devinit
-intr_parent(struct device_node *p)
+static struct device_node * __devinit intr_parent(struct device_node *p)
 {
 	phandle *parp;
 
@@ -1908,14 +159,14 @@ int __devinit prom_n_intr_cells(struct device_node *np)
  * Map an interrupt from a device up to the platform interrupt
  * descriptor.
  */
-static int __devinit
-map_interrupt(unsigned int **irq, struct device_node **ictrler,
-	      struct device_node *np, unsigned int *ints, int nintrc)
+static int __devinit map_interrupt(unsigned int **irq, struct device_node **ictrler,
+				   struct device_node *np, unsigned int *ints,
+				   int nintrc)
 {
 	struct device_node *p, *ipar;
 	unsigned int *imap, *imask, *ip;
 	int i, imaplen, match;
-	int newintrc, newaddrc;
+	int newintrc = 0, newaddrc = 0;
 	unsigned int *reg;
 	int naddrc;
 
@@ -2004,9 +255,9 @@ map_interrupt(unsigned int **irq, struct device_node **ictrler,
 	return nintrc;
 }
 
-static unsigned long __init
-finish_node_interrupts(struct device_node *np, unsigned long mem_start,
-		       int measure_only)
+static unsigned long __init finish_node_interrupts(struct device_node *np,
+						   unsigned long mem_start,
+						   int measure_only)
 {
 	unsigned int *ints;
 	int intlen, intrcells, intrcount;
@@ -2067,9 +318,10 @@ finish_node_interrupts(struct device_node *np, unsigned long mem_start,
 	return mem_start;
 }
 
-static unsigned long __init
-interpret_pci_props(struct device_node *np, unsigned long mem_start,
-		    int naddrc, int nsizec, int measure_only)
+static unsigned long __init interpret_pci_props(struct device_node *np,
+						unsigned long mem_start,
+						int naddrc, int nsizec,
+						int measure_only)
 {
 	struct address_range *adr;
 	struct pci_reg_property *pci_addrs;
@@ -2095,9 +347,10 @@ interpret_pci_props(struct device_node *np, unsigned long mem_start,
 	return mem_start;
 }
 
-static unsigned long __init
-interpret_dbdma_props(struct device_node *np, unsigned long mem_start,
-		      int naddrc, int nsizec, int measure_only)
+static unsigned long __init interpret_dbdma_props(struct device_node *np,
+						  unsigned long mem_start,
+						  int naddrc, int nsizec,
+						  int measure_only)
 {
 	struct reg_property32 *rp;
 	struct address_range *adr;
@@ -2135,9 +388,10 @@ interpret_dbdma_props(struct device_node *np, unsigned long mem_start,
 	return mem_start;
 }
 
-static unsigned long __init
-interpret_macio_props(struct device_node *np, unsigned long mem_start,
-		      int naddrc, int nsizec, int measure_only)
+static unsigned long __init interpret_macio_props(struct device_node *np,
+						  unsigned long mem_start,
+						  int naddrc, int nsizec,
+						  int measure_only)
 {
 	struct reg_property32 *rp;
 	struct address_range *adr;
@@ -2175,9 +429,10 @@ interpret_macio_props(struct device_node *np, unsigned long mem_start,
 	return mem_start;
 }
 
-static unsigned long __init
-interpret_isa_props(struct device_node *np, unsigned long mem_start,
-		    int naddrc, int nsizec, int measure_only)
+static unsigned long __init interpret_isa_props(struct device_node *np,
+						unsigned long mem_start,
+						int naddrc, int nsizec,
+						int measure_only)
 {
 	struct isa_reg_property *rp;
 	struct address_range *adr;
@@ -2203,9 +458,10 @@ interpret_isa_props(struct device_node *np, unsigned long mem_start,
 	return mem_start;
 }
 
-static unsigned long __init
-interpret_root_props(struct device_node *np, unsigned long mem_start,
-		     int naddrc, int nsizec, int measure_only)
+static unsigned long __init interpret_root_props(struct device_node *np,
+						 unsigned long mem_start,
+						 int naddrc, int nsizec,
+						 int measure_only)
 {
 	struct address_range *adr;
 	int i, l;
@@ -2233,21 +489,15 @@ interpret_root_props(struct device_node *np, unsigned long mem_start,
 	return mem_start;
 }
 
-static unsigned long __init
-finish_node(struct device_node *np, unsigned long mem_start,
-	    interpret_func *ifunc, int naddrc, int nsizec, int measure_only)
+static unsigned long __init finish_node(struct device_node *np,
+					unsigned long mem_start,
+					interpret_func *ifunc,
+					int naddrc, int nsizec,
+					int measure_only)
 {
 	struct device_node *child;
 	int *ip;
 
-	np->name = get_property(np, "name", NULL);
-	np->type = get_property(np, "device_type", NULL);
-
-	if (!np->name)
-		np->name = "<NULL>";
-	if (!np->type)
-		np->type = "<NULL>";
-
 	/* get the device addresses and interrupts */
 	if (ifunc != NULL)
 		mem_start = ifunc(np, mem_start, naddrc, nsizec, measure_only);
@@ -2298,24 +548,516 @@ finish_node(struct device_node *np, unsigned long mem_start,
 /**
  * finish_device_tree is called once things are running normally
  * (i.e. with text and data mapped to the address they were linked at).
- * It traverses the device tree and fills in the name, type,
- * {n_}addrs and {n_}intrs fields of each node.
+ * It traverses the device tree and fills in some of the additional,
+ * fields in each node like {n_}addrs and {n_}intrs, the virt interrupt
+ * mapping is also initialized at this point.
  */
-void __init
-finish_device_tree(void)
+void __init finish_device_tree(void)
 {
-	unsigned long mem = klimit;
+	unsigned long mem, size;
+
+	DBG(" -> finish_device_tree\n");
 
+	if (naca->interrupt_controller == IC_INVALID) {
+		DBG("failed to configure interrupt controller type\n");
+		panic("failed to configure interrupt controller type\n");
+	}
+	
+	/* Initialize virtual IRQ map */
 	virt_irq_init();
 
-	dev_tree_size = finish_node(allnodes, 0, NULL, 0, 0, 1);
-	mem = (long)abs_to_virt(lmb_alloc(dev_tree_size,
-					  __alignof__(struct device_node)));
-	if (finish_node(allnodes, mem, NULL, 0, 0, 0) != mem + dev_tree_size)
+	/* Finish device-tree (pre-parsing some properties etc...) */
+	size = finish_node(allnodes, 0, NULL, 0, 0, 1);
+	mem = (unsigned long)abs_to_virt(lmb_alloc(size, 128));
+	if (finish_node(allnodes, mem, NULL, 0, 0, 0) != mem + size)
 		BUG();
-	rtas.dev = of_find_node_by_name(NULL, "rtas");
+
+	DBG(" <- finish_device_tree\n");
+}
+
+#ifdef DEBUG
+#define printk udbg_printf
+#endif
+
+static inline char *find_flat_dt_string(u32 offset)
+{
+	return ((char *)initial_boot_params) + initial_boot_params->off_dt_strings
+		+ offset;
+}
+
+/**
+ * This function is used to scan the flattened device-tree, it is
+ * used to extract the memory informations at boot before we can
+ * unflatten the tree
+ */
+static int __init scan_flat_dt(int (*it)(unsigned long node,
+					 const char *full_path, void *data),
+			       void *data)
+{
+	unsigned long p = ((unsigned long)initial_boot_params) +
+		initial_boot_params->off_dt_struct;
+	int rc = 0;
+
+	do {
+		u32 tag = *((u32 *)p);
+		char *pathp;
+		
+		p += 4;
+		if (tag == OF_DT_END_NODE)
+			continue;
+		if (tag == OF_DT_END)
+			break;
+		if (tag == OF_DT_PROP) {
+			u32 sz = *((u32 *)p);
+			p += 8;
+			p = _ALIGN(p, sz >= 8 ? 8 : 4);
+			p += sz;
+			p = _ALIGN(p, 4);
+			continue;
+		}
+		if (tag != OF_DT_BEGIN_NODE) {
+			printk(KERN_WARNING "Invalid tag %x scanning flattened"
+			       " device tree !\n", tag);
+			return -EINVAL;
+		}
+		pathp = (char *)p;
+		p = _ALIGN(p + strlen(pathp) + 1, 4);
+		rc = it(p, pathp, data);
+		if (rc != 0)
+			break;		
+	} while(1);
+
+	return rc;
+}
+
+/**
+ * This  function can be used within scan_flattened_dt callback to get
+ * access to properties
+ */
+static void* __init get_flat_dt_prop(unsigned long node, const char *name,
+				     unsigned long *size)
+{
+	unsigned long p = node;
+
+	do {
+		u32 tag = *((u32 *)p);
+		u32 sz, noff;
+		const char *nstr;
+
+		p += 4;
+		if (tag != OF_DT_PROP)
+			return NULL;
+
+		sz = *((u32 *)p);
+		noff = *((u32 *)(p + 4));
+		p += 8;
+		p = _ALIGN(p, sz >= 8 ? 8 : 4);
+
+		nstr = find_flat_dt_string(noff);
+		if (nstr == NULL) {
+			printk(KERN_WARNING "Can't find property index name !\n");
+			return NULL;
+		}
+		if (strcmp(name, nstr) == 0) {
+			if (size)
+				*size = sz;
+			return (void *)p;
+		}
+		p += sz;
+		p = _ALIGN(p, 4);
+	} while(1);
+}
+
+static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
+					       unsigned long align)
+{
+	void *res;
+
+	*mem = _ALIGN(*mem, align);
+	res = (void *)*mem;
+	*mem += size;
+
+	return res;
+}
+
+static unsigned long __init unflatten_dt_node(unsigned long mem,
+					      unsigned long *p,
+					      struct device_node *dad,
+					      struct device_node ***allnextpp)
+{
+	struct device_node *np;
+	struct property *pp, **prev_pp = NULL;
+	char *pathp;
+	u32 tag;
+	unsigned int l;
+
+	tag = *((u32 *)(*p));
+	if (tag != OF_DT_BEGIN_NODE) {
+		printk("Weird tag at start of node: %x\n", tag);
+		return mem;
+	}
+	*p += 4;
+	pathp = (char *)*p;
+	l = strlen(pathp) + 1;
+	*p = _ALIGN(*p + l, 4);
+
+	np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + l,
+				__alignof__(struct device_node));
+	if (allnextpp) {
+		memset(np, 0, sizeof(*np));
+		np->full_name = ((char*)np) + sizeof(struct device_node);
+		memcpy(np->full_name, pathp, l);
+		prev_pp = &np->properties;
+		**allnextpp = np;
+		*allnextpp = &np->allnext;
+		if (dad != NULL) {
+			np->parent = dad;
+			/* we temporarily use the `next' field as `last_child'. */
+			if (dad->next == 0)
+				dad->child = np;
+			else
+				dad->next->sibling = np;
+			dad->next = np;
+		}
+	}
+	while(1) {
+		u32 sz, noff;
+		char *pname;
+
+		tag = *((u32 *)(*p));
+		if (tag != OF_DT_PROP)
+			break;
+		*p += 4;
+		sz = *((u32 *)(*p));
+		noff = *((u32 *)((*p) + 4));
+		*p = _ALIGN((*p) + 8, sz >= 8 ? 8 : 4);
+
+		pname = find_flat_dt_string(noff);
+		if (pname == NULL) {
+			printk("Can't find property name in list !\n");
+			break;
+		}
+		l = strlen(pname) + 1;
+		pp = unflatten_dt_alloc(&mem, sizeof(struct property),
+					__alignof__(struct property));
+		if (allnextpp) {
+			if (strcmp(pname, "linux,phandle") == 0) {
+				np->node = *((u32 *)*p);
+				if (np->linux_phandle == 0)
+					np->linux_phandle = np->node;
+			}
+			if (strcmp(pname, "ibm,phandle") == 0)
+				np->linux_phandle = *((u32 *)*p);
+			pp->name = pname;
+			pp->length = sz;
+			pp->value = (void *)*p;
+			*prev_pp = pp;
+			prev_pp = &pp->next;
+		}
+		*p = _ALIGN((*p) + sz, 4);
+	}
+	if (allnextpp) {
+		*prev_pp = NULL;
+		np->name = get_property(np, "name", NULL);
+		np->type = get_property(np, "device_type", NULL);
+
+		if (!np->name)
+			np->name = "<NULL>";
+		if (!np->type)
+			np->type = "<NULL>";
+	}
+	while (tag == OF_DT_BEGIN_NODE) {
+		mem = unflatten_dt_node(mem, p, np, allnextpp);
+		tag = *((u32 *)(*p));
+	}
+	if (tag != OF_DT_END_NODE) {
+		printk("Weird tag at start of node: %x\n", tag);
+		return mem;
+	}
+	*p += 4;
+	return mem;
+}
+
+
+/**
+ * unflattens the device-tree passed by the firmware, creating the
+ * tree of struct device_node. It also fills the "name" and "type"
+ * pointers of the nodes so the normal device-tree walking functions
+ * can be used (this used to be done by finish_device_tree)
+ */
+void __init unflatten_device_tree(void)
+{
+	unsigned long start, mem, size;
+	struct device_node **allnextp = &allnodes;
+	char *p;
+	int l = 0;
+
+	DBG(" -> unflatten_device_tree()\n");
+
+	/* First pass, scan for size */
+	start = ((unsigned long)initial_boot_params) +
+		initial_boot_params->off_dt_struct;
+	size = unflatten_dt_node(0, &start, NULL, NULL);
+
+	DBG("  size is %lx, allocating...\n", size);
+
+	/* Allocate memory for the expanded device tree */
+	mem = (unsigned long)abs_to_virt(lmb_alloc(size,
+						   __alignof__(struct device_node)));
+	DBG("  unflattening...\n", mem);
+
+	/* Second pass, do actual unflattening */
+	start = ((unsigned long)initial_boot_params) +
+		initial_boot_params->off_dt_struct;
+	unflatten_dt_node(mem, &start, NULL, &allnextp);
+	if (*((u32 *)start) != OF_DT_END)
+		printk(KERN_WARNING "Weird tag at end of tree: %x\n", *((u32 *)start));
+	*allnextp = NULL;
+
+	/* Get pointer to OF "/chosen" node for use everywhere */
+	of_chosen = of_find_node_by_path("/chosen");
+
+	/* Retreive command line */
+	if (of_chosen != NULL) {
+		p = (char *)get_property(of_chosen, "bootargs", &l);
+		if (p != NULL && l > 0)
+			strlcpy(cmd_line, p, min(l, COMMAND_LINE_SIZE));
+	}
+#ifdef CONFIG_CMDLINE
+	if (l == 0) /* dbl check */
+		strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
+#endif /* CONFIG_CMDLINE */
+
+	DBG("Command line is: %s\n", cmd_line);
+
+	DBG(" <- unflatten_device_tree()\n");
+}
+
+
+static int __init early_init_dt_scan_cpus(unsigned long node,
+					  const char *full_path, void *data)
+{
+	char *type = get_flat_dt_prop(node, "device_type", NULL);
+
+	/* We are scanning "cpu" nodes only */
+	if (type == NULL || strcmp(type, "cpu") != 0)
+		return 0;
+
+	/* On LPAR, look for the first ibm,pft-size property for the  hash table size
+	 */
+	if (systemcfg->platform == PLATFORM_PSERIES_LPAR && naca->pftSize == 0) {
+		u32 *pft_size;
+		pft_size = (u32 *)get_flat_dt_prop(node, "ibm,pft-size", NULL);
+		if (pft_size != NULL) {
+			/* pft_size[0] is the NUMA CEC cookie */
+			naca->pftSize = pft_size[1];
+		}
+	}
+
+	/* Check if it's the boot-cpu, set it's hw index in paca now */
+	if (get_flat_dt_prop(node, "linux,boot-cpu", NULL) != NULL) {
+		u32 *prop = get_flat_dt_prop(node, "reg", NULL);
+		paca[0].hw_cpu_id = prop == NULL ? 0 : *prop;
+	}
+
+	return 0;
+}
+
+static int __init early_init_dt_scan_chosen(unsigned long node,
+					    const char *full_path, void *data)
+{
+	u32 *prop;
+
+	if (strcmp(full_path, "/chosen") != 0)
+		return 0;
+
+	/* get platform type */
+	prop = (u32 *)get_flat_dt_prop(node, "linux,platform", NULL);
+	if (prop == NULL)
+		return 0;
+	systemcfg->platform = *prop;
+
+	/* check if iommu is forced on or off */
+	if (get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL)
+		iommu_is_off = 1;
+	if (get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL)
+		iommu_force_on = 1;
+
+#ifdef CONFIG_PPC_PSERIES
+	/* To help early debugging via the front panel, we retreive a minimal
+	 * set of RTAS infos now if available
+	 */
+	{
+		u64 *basep, *entryp;
+
+		basep = (u64*)get_flat_dt_prop(node, "linux,rtas-base", NULL);
+		entryp = (u64*)get_flat_dt_prop(node, "linux,rtas-entry", NULL);
+		prop = (u32*)get_flat_dt_prop(node, "linux,rtas-size", NULL);
+		if (basep && entryp && prop) {
+			rtas.base = *basep;
+			rtas.entry = *entryp;
+			rtas.size = *prop;
+		}
+	}
+#endif /* CONFIG_PPC_PSERIES */
+
+	/* break now */
+	return 1;
+}
+
+static int __init early_init_dt_scan_root(unsigned long node,
+					  const char *full_path, void *data)
+{
+	u32 *prop;
+
+	if (strcmp(full_path, "/") != 0)
+		return 0;
+
+	prop = (u32 *)get_flat_dt_prop(node, "#size-cells", NULL);
+	dt_root_size_cells = (prop == NULL) ? 1 : *prop;
+		
+	prop = (u32 *)get_flat_dt_prop(node, "#address-cells", NULL);
+	dt_root_addr_cells = (prop == NULL) ? 2 : *prop;
+	
+	/* break now */
+	return 1;
+}
+
+static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp)
+{
+	cell_t *p = *cellp;
+	unsigned long r = 0;
+
+	/* Ignore more than 2 cells */
+	while (s > 2) {
+		p++;
+		s--;
+	}
+	while (s) {
+		r <<= 32;
+		r |= *(p++);
+		s--;
+	}
+
+	*cellp = p;
+	return r;
+}
+
+
+static int __init early_init_dt_scan_memory(unsigned long node,
+					    const char *full_path, void *data)
+{
+	char *type = get_flat_dt_prop(node, "device_type", NULL);
+	cell_t *reg, *endp;
+	unsigned long l;
+
+	/* We are scanning "memory" nodes only */
+	if (type == NULL || strcmp(type, "memory") != 0)
+		return 0;
+
+	reg = (cell_t *)get_flat_dt_prop(node, "reg", &l);
+	if (reg == NULL)
+		return 0;
+
+	endp = reg + (l / sizeof(cell_t));
+
+	DBG("memory scan node %s ...\n", full_path);
+	while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
+		unsigned long base, size;
+
+		base = dt_mem_next_cell(dt_root_addr_cells, &reg);
+		size = dt_mem_next_cell(dt_root_size_cells, &reg);
+
+		if (size == 0)
+			continue;
+		DBG(" - %lx ,  %lx\n", base, size);
+		if (iommu_is_off) {
+			if (base >= 0x80000000ul)
+				continue;
+			if ((base + size) > 0x80000000ul)
+				size = 0x80000000ul - base;
+		}
+		lmb_add(base, size);
+	}
+	return 0;
+}
+
+static void __init early_reserve_mem(void)
+{
+	u64 base, size;
+	u64 *reserve_map = (u64 *)(((unsigned long)initial_boot_params) +
+				   initial_boot_params->off_mem_rsvmap);
+	while (1) {
+		base = *(reserve_map++);
+		size = *(reserve_map++);
+		if (size == 0)
+			break;
+		DBG("reserving: %lx -> %lx\n", base, size);
+		lmb_reserve(base, size);
+	}
+
+#if 0
+	DBG("memory reserved, lmbs :\n");
+      	lmb_dump_all();
+#endif
+}
+
+void __init early_init_devtree(void *params)
+{
+	DBG(" -> early_init_devtree()\n");
+
+	/* Setup flat device-tree pointer */
+	initial_boot_params = params;
+
+	/* By default, hash size is not set */
+	naca->pftSize = 0;
+
+	/* Retreive various informations from the /chosen node of the
+	 * device-tree, including the platform type, initrd location and
+	 * size, TCE reserve, and more ...
+	 */
+	scan_flat_dt(early_init_dt_scan_chosen, NULL);
+
+	/* Scan memory nodes and rebuild LMBs */
+	lmb_init();
+	scan_flat_dt(early_init_dt_scan_root, NULL);
+	scan_flat_dt(early_init_dt_scan_memory, NULL);
+	lmb_analyze();
+	systemcfg->physicalMemorySize = lmb_phys_mem_size();
+
+	DBG("Phys. mem: %lx\n", systemcfg->physicalMemorySize);
+
+	/* Reserve LMB regions used by kernel, initrd, dt, etc... */
+	early_reserve_mem();
+
+	DBG("Scanning CPUs ...\n");
+
+	/* Retreive hash table size from flattened tree */
+	scan_flat_dt(early_init_dt_scan_cpus, NULL);
+
+	/* If hash size wasn't obtained above, we calculate it now based on
+	 * the total RAM size
+	 */
+	if (naca->pftSize == 0) {
+		unsigned long rnd_mem_size, pteg_count;
+
+		/* round mem_size up to next power of 2 */
+		rnd_mem_size = 1UL << __ilog2(systemcfg->physicalMemorySize);
+		if (rnd_mem_size < systemcfg->physicalMemorySize)
+			rnd_mem_size <<= 1;
+
+		/* # pages / 2 */
+		pteg_count = (rnd_mem_size >> (12 + 1));
+
+		naca->pftSize = __ilog2(pteg_count << 7);
+	}
+
+	DBG("Hash pftSize: %x\n", (int)naca->pftSize);
+	DBG(" <- early_init_devtree()\n");
 }
 
+#undef printk
+
 int
 prom_n_addr_cells(struct device_node* np)
 {
@@ -2627,6 +1369,28 @@ struct device_node *of_find_node_by_path(const char *path)
 }
 EXPORT_SYMBOL(of_find_node_by_path);
 
+/**
+ *	of_find_node_by_phandle - Find a node given a phandle
+ *	@handle:	phandle of the node to find
+ *
+ *	Returns a node pointer with refcount incremented, use
+ *	of_node_put() on it when done.
+ */
+struct device_node *of_find_node_by_phandle(phandle handle)
+{
+	struct device_node *np;
+
+	read_lock(&devtree_lock);
+	for (np = allnodes; np != 0; np = np->allnext)
+		if (np->linux_phandle == handle)
+			break;
+	if (np)
+		of_node_get(np);
+	read_unlock(&devtree_lock);
+	return np;
+}
+EXPORT_SYMBOL(of_find_node_by_phandle);
+
 /**
  *	of_find_all_nodes - Get next node in global list
  *	@prev:	Previous node or NULL to start iteration
@@ -2886,6 +1650,7 @@ static int of_finish_dynamic_node_interrupts(struct device_node *node)
 	return 0;
 }
 
+
 /*
  * Fix up the uninitialized fields in a new device node:
  * name, type, n_addrs, addrs, n_intrs, intrs, and pci-specific fields
@@ -2971,12 +1736,14 @@ static int of_finish_dynamic_node(struct device_node *node)
 
 	/* fixing up iommu_table */
 
+#ifdef CONFIG_PPC_PSERIES
 	if (strcmp(node->name, "pci") == 0 &&
 	    get_property(node, "ibm,dma-window", NULL)) {
 		node->bussubno = node->busno;
 		iommu_devnode_init(node);
 	} else
 		node->iommu_table = parent->iommu_table;
+#endif /* CONFIG_PPC_PSERIES */
 
 out:
 	of_node_put(parent);
@@ -3163,3 +1930,13 @@ print_properties(struct device_node *np)
 	}
 }
 #endif
+
+
+
+
+
+
+
+
+
+
diff --git a/arch/ppc64/kernel/ras.c b/arch/ppc64/kernel/ras.c
index 595ae6ec2..75ced99c5 100644
--- a/arch/ppc64/kernel/ras.c
+++ b/arch/ppc64/kernel/ras.c
@@ -161,7 +161,8 @@ ras_epow_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 			   RAS_VECTOR_OFFSET,
 			   virt_irq_to_real(irq_offset_down(irq)),
 			   RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS,
-			   critical, __pa(&ras_log_buf), RTAS_ERROR_LOG_MAX);
+			   critical, __pa(&ras_log_buf),
+				rtas_get_error_log_max());
 
 	udbg_printf("EPOW <0x%lx 0x%x 0x%x>\n",
 		    *((unsigned long *)&ras_log_buf), status, state);
@@ -196,11 +197,12 @@ ras_error_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 			   RAS_VECTOR_OFFSET,
 			   virt_irq_to_real(irq_offset_down(irq)),
 			   RTAS_INTERNAL_ERROR, 1 /*Time Critical */,
-			   __pa(&ras_log_buf), RTAS_ERROR_LOG_MAX);
+			   __pa(&ras_log_buf),
+				rtas_get_error_log_max());
 
 	rtas_elog = (struct rtas_error_log *)ras_log_buf;
 
-	if ((status == 0) && (rtas_elog->severity >= SEVERITY_ERROR_SYNC))
+	if ((status == 0) && (rtas_elog->severity >= RTAS_SEVERITY_ERROR_SYNC))
 		fatal = 1;
 	else
 		fatal = 0;
diff --git a/arch/ppc64/kernel/rtas-proc.c b/arch/ppc64/kernel/rtas-proc.c
index a055759b6..bd75066cc 100644
--- a/arch/ppc64/kernel/rtas-proc.c
+++ b/arch/ppc64/kernel/rtas-proc.c
@@ -580,7 +580,7 @@ static void ppc_rtas_process_sensor(struct seq_file *m,
 			}
 			break;
 		case THERMAL_SENSOR:
-			seq_printf(m, "Temp. (°C/°F):\t");
+			seq_printf(m, "Temp. (C/F):\t");
 			temperature = 1;
 			break;
 		case LID_STATUS:
diff --git a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c
index 438d258dc..becb652e1 100644
--- a/arch/ppc64/kernel/rtas.c
+++ b/arch/ppc64/kernel/rtas.c
@@ -22,7 +22,6 @@
 #include <asm/rtas.h>
 #include <asm/semaphore.h>
 #include <asm/machdep.h>
-#include <asm/paca.h>
 #include <asm/page.h>
 #include <asm/param.h>
 #include <asm/system.h>
@@ -37,17 +36,22 @@ struct rtas_t rtas = {
 	.lock = SPIN_LOCK_UNLOCKED
 };
 
+EXPORT_SYMBOL(rtas);
+
 char rtas_err_buf[RTAS_ERROR_LOG_MAX];
 
 spinlock_t rtas_data_buf_lock = SPIN_LOCK_UNLOCKED;
 char rtas_data_buf[RTAS_DATA_BUF_SIZE]__page_aligned;
+unsigned long rtas_rmo_buf;
 
 void
-call_rtas_display_status(char c)
+call_rtas_display_status(unsigned char c)
 {
 	struct rtas_args *args = &rtas.args;
 	unsigned long s;
 
+	if (!rtas.base)
+		return;
 	spin_lock_irqsave(&rtas.lock, s);
 
 	args->token = 10;
@@ -61,6 +65,31 @@ call_rtas_display_status(char c)
 	spin_unlock_irqrestore(&rtas.lock, s);
 }
 
+void
+call_rtas_display_status_delay(unsigned char c)
+{
+	static int pending_newline = 0;  /* did last write end with unprinted newline? */
+	static int width = 16;
+
+	if (c == '\n') {	
+		while (width-- > 0)
+			call_rtas_display_status(' ');
+		width = 16;
+		udelay(500000);
+		pending_newline = 1;
+	} else {
+		if (pending_newline) {
+			call_rtas_display_status('\r');
+			call_rtas_display_status('\n');
+		} 
+		pending_newline = 0;
+		if (width--) {
+			call_rtas_display_status(c);
+			udelay(10000);
+		}
+	}
+}
+
 int
 rtas_token(const char *service)
 {
@@ -73,7 +102,6 @@ rtas_token(const char *service)
 	return tokp ? *tokp : RTAS_UNKNOWN_SERVICE;
 }
 
-
 /** Return a copy of the detailed error text associated with the
  *  most recent failed call to rtas.  Because the error text
  *  might go stale if there are any other intervening rtas calls,
@@ -84,28 +112,32 @@ static int
 __fetch_rtas_last_error(void)
 {
 	struct rtas_args err_args, save_args;
+	u32 bufsz;
+
+	bufsz = rtas_token ("rtas-error-log-max");
+	if ((bufsz == RTAS_UNKNOWN_SERVICE) ||
+	    (bufsz > RTAS_ERROR_LOG_MAX)) {
+		printk (KERN_WARNING "RTAS: bad log buffer size %d\n", bufsz);
+		bufsz = RTAS_ERROR_LOG_MAX;
+	}
 
 	err_args.token = rtas_token("rtas-last-error");
 	err_args.nargs = 2;
 	err_args.nret = 1;
-	err_args.rets = (rtas_arg_t *)&(err_args.args[2]);
 
 	err_args.args[0] = (rtas_arg_t)__pa(rtas_err_buf);
-	err_args.args[1] = RTAS_ERROR_LOG_MAX;
+	err_args.args[1] = bufsz;
 	err_args.args[2] = 0;
 
 	save_args = rtas.args;
 	rtas.args = err_args;
 
-	PPCDBG(PPCDBG_RTAS, "\tentering rtas with 0x%lx\n",
-	       __pa(&err_args));
 	enter_rtas(__pa(&rtas.args));
-	PPCDBG(PPCDBG_RTAS, "\treturned from rtas ...\n");
 
 	err_args = rtas.args;
 	rtas.args = save_args;
 
-	return err_args.rets[0];
+	return err_args.args[2];
 }
 
 int rtas_call(int token, int nargs, int nret, int *outputs, ...)
@@ -165,9 +197,12 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
 
 	/* Log the error in the unlikely case that there was one. */
 	if (unlikely(logit)) {
-		buff_copy = kmalloc(RTAS_ERROR_LOG_MAX, GFP_ATOMIC);
-		if (buff_copy) {
-			memcpy(buff_copy, rtas_err_buf, RTAS_ERROR_LOG_MAX);
+		buff_copy = rtas_err_buf;
+		if (mem_init_done) {
+			buff_copy = kmalloc(RTAS_ERROR_LOG_MAX, GFP_ATOMIC);
+			if (buff_copy)
+				memcpy(buff_copy, rtas_err_buf,
+				       RTAS_ERROR_LOG_MAX);
 		}
 	}
 
@@ -176,7 +211,8 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
 
 	if (buff_copy) {
 		log_error(buff_copy, ERR_TYPE_RTAS_LOG, 0);
-		kfree(buff_copy);
+		if (mem_init_done)
+			kfree(buff_copy);
 	}
 	return ret;
 }
@@ -417,7 +453,6 @@ void rtas_os_term(char *str)
 	} while (status == RTAS_BUSY);
 }
 
-unsigned long rtas_rmo_buf = 0;
 
 asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
 {
@@ -508,6 +543,73 @@ void rtas_stop_self(void)
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
+/*
+ * Return the firmware-specified size of the error log buffer
+ *  for all rtas calls that require an error buffer argument.
+ *  This includes 'check-exception' and 'rtas-last-error'.
+ */
+int rtas_get_error_log_max(void)
+{
+	static int rtas_error_log_max;
+	if (rtas_error_log_max)
+		return rtas_error_log_max;
+
+	rtas_error_log_max = rtas_token ("rtas-error-log-max");
+	if ((rtas_error_log_max == RTAS_UNKNOWN_SERVICE) ||
+	    (rtas_error_log_max > RTAS_ERROR_LOG_MAX)) {
+		printk (KERN_WARNING "RTAS: bad log buffer size %d\n", rtas_error_log_max);
+		rtas_error_log_max = RTAS_ERROR_LOG_MAX;
+	}
+	return rtas_error_log_max;
+}
+
+/*
+ * Call early during boot, before mem init or bootmem, to retreive the RTAS
+ * informations from the device-tree and allocate the RMO buffer for userland
+ * accesses.
+ */
+void __init rtas_initialize(void)
+{
+	/* Get RTAS dev node and fill up our "rtas" structure with infos
+	 * about it.
+	 */
+	rtas.dev = of_find_node_by_name(NULL, "rtas");
+	if (rtas.dev) {
+		u64 *basep, *entryp;
+		u32 *sizep;
+
+		basep = (u64 *)get_property(of_chosen, "linux,rtas-base", NULL);
+		sizep = (u32 *)get_property(of_chosen, "linux,rtas-size", NULL);
+		if (basep != NULL && sizep != NULL) {
+			rtas.base = *basep;
+			rtas.size = *sizep;
+			entryp = (u64 *)get_property(of_chosen, "linux,rtas-entry", NULL);
+			if (entryp == NULL) /* Ugh */
+				rtas.entry = rtas.base;
+			else
+				rtas.entry = *entryp;
+		} else
+			rtas.dev = NULL;
+	}
+	/* If RTAS was found, allocate the RMO buffer for it and look for
+	 * the stop-self token if any
+	 */
+	if (rtas.dev) {
+		unsigned long rtas_region = RTAS_INSTANTIATE_MAX;
+		if (systemcfg->platform == PLATFORM_PSERIES_LPAR)
+			rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX);
+
+		rtas_rmo_buf = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE,
+							rtas_region);
+
+#ifdef CONFIG_HOTPLUG_CPU
+		rtas_stop_self_args.token = rtas_token("stop-self");
+#endif /* CONFIG_HOTPLUG_CPU */
+	}
+
+}
+
+
 EXPORT_SYMBOL(rtas_firmware_flash_list);
 EXPORT_SYMBOL(rtas_token);
 EXPORT_SYMBOL(rtas_call);
@@ -518,3 +620,4 @@ EXPORT_SYMBOL(rtas_get_sensor);
 EXPORT_SYMBOL(rtas_get_power_level);
 EXPORT_SYMBOL(rtas_set_power_level);
 EXPORT_SYMBOL(rtas_set_indicator);
+EXPORT_SYMBOL(rtas_get_error_log_max);
diff --git a/arch/ppc64/kernel/rtasd.c b/arch/ppc64/kernel/rtasd.c
index 7538cea27..c6370a8e3 100644
--- a/arch/ppc64/kernel/rtasd.c
+++ b/arch/ppc64/kernel/rtasd.c
@@ -46,6 +46,8 @@ static unsigned int rtas_event_scan_rate;
 static unsigned int rtas_error_log_max;
 static unsigned int rtas_error_log_buffer_max;
 
+static int full_rtas_msgs = 0;
+
 extern volatile int no_more_logging;
 
 volatile int error_log_cnt = 0;
@@ -57,6 +59,37 @@ volatile int error_log_cnt = 0;
  */
 static unsigned char logdata[RTAS_ERROR_LOG_MAX];
 
+static int get_eventscan_parms(void);
+
+static char *rtas_type[] = {
+	"Unknown", "Retry", "TCE Error", "Internal Device Failure",
+	"Timeout", "Data Parity", "Address Parity", "Cache Parity",
+	"Address Invalid", "ECC Uncorrected", "ECC Corrupted",
+};
+
+static char *rtas_event_type(int type)
+{
+	if ((type > 0) && (type < 11))
+		return rtas_type[type];
+
+	switch (type) {
+		case RTAS_TYPE_EPOW:
+			return "EPOW";
+		case RTAS_TYPE_PLATFORM:
+			return "Platform Error";
+		case RTAS_TYPE_IO:
+			return "I/O Event";
+		case RTAS_TYPE_INFO:
+			return "Platform Information Event";
+		case RTAS_TYPE_DEALLOC:
+			return "Resource Deallocation Event";
+		case RTAS_TYPE_DUMP:
+			return "Dump Notification Event";
+	}
+
+	return rtas_type[0];
+}
+
 /* To see this info, grep RTAS /var/log/messages and each entry
  * will be collected together with obvious begin/end.
  * There will be a unique identifier on the begin and end lines.
@@ -73,38 +106,48 @@ static unsigned char logdata[RTAS_ERROR_LOG_MAX];
 static void printk_log_rtas(char *buf, int len)
 {
 
-	int i,j,n;
+	int i,j,n = 0;
 	int perline = 16;
 	char buffer[64];
 	char * str = "RTAS event";
 
-	printk(RTAS_DEBUG "%d -------- %s begin --------\n", error_log_cnt, str);
-
-	/*
-	 * Print perline bytes on each line, each line will start
-	 * with RTAS and a changing number, so syslogd will
-	 * print lines that are otherwise the same.  Separate every
-	 * 4 bytes with a space.
-	 */
-	for (i=0; i < len; i++) {
-		j = i % perline;
-		if (j == 0) {
-			memset(buffer, 0, sizeof(buffer));
-			n = sprintf(buffer, "RTAS %d:", i/perline);
+	if (full_rtas_msgs) {
+		printk(RTAS_DEBUG "%d -------- %s begin --------\n",
+		       error_log_cnt, str);
+
+		/*
+		 * Print perline bytes on each line, each line will start
+		 * with RTAS and a changing number, so syslogd will
+		 * print lines that are otherwise the same.  Separate every
+		 * 4 bytes with a space.
+		 */
+		for (i = 0; i < len; i++) {
+			j = i % perline;
+			if (j == 0) {
+				memset(buffer, 0, sizeof(buffer));
+				n = sprintf(buffer, "RTAS %d:", i/perline);
+			}
+
+			if ((i % 4) == 0)
+				n += sprintf(buffer+n, " ");
+
+			n += sprintf(buffer+n, "%02x", (unsigned char)buf[i]);
+
+			if (j == (perline-1))
+				printk(KERN_DEBUG "%s\n", buffer);
 		}
+		if ((i % perline) != 0)
+			printk(KERN_DEBUG "%s\n", buffer);
 
-		if ((i % 4) == 0)
-			n += sprintf(buffer+n, " ");
-
-		n += sprintf(buffer+n, "%02x", (unsigned char)buf[i]);
+		printk(RTAS_DEBUG "%d -------- %s end ----------\n",
+		       error_log_cnt, str);
+	} else {
+		struct rtas_error_log *errlog = (struct rtas_error_log *)buf;
 
-		if (j == (perline-1))
-			printk(KERN_DEBUG "%s\n", buffer);
+		printk(RTAS_DEBUG "event: %d, Type: %s, Severity: %d\n",
+		       error_log_cnt, rtas_event_type(errlog->type),
+		       errlog->severity);
 	}
-	if ((i % perline) != 0)
-		printk(KERN_DEBUG "%s\n", buffer);
-
-	printk(RTAS_DEBUG "%d -------- %s end ----------\n", error_log_cnt, str);
 }
 
 static int log_rtas_len(char * buf)
@@ -121,6 +164,9 @@ static int log_rtas_len(char * buf)
 		len += err->extended_log_length;
 	}
 
+	if (rtas_error_log_max == 0) {
+		get_eventscan_parms();
+	}
 	if (len > rtas_error_log_max)
 		len = rtas_error_log_max;
 
@@ -148,7 +194,6 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal)
 	int len = 0;
 
 	DEBUG("logging event\n");
-
 	if (buf == NULL)
 		return;
 
@@ -171,6 +216,14 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal)
 	if (!no_more_logging && !(err_type & ERR_FLAG_BOOT))
 		nvram_write_error_log(buf, len, err_type);
 
+	/*
+	 * rtas errors can occur during boot, and we do want to capture
+	 * those somewhere, even if nvram isn't ready (why not?), and even
+	 * if rtasd isn't ready. Put them into the boot log, at least.
+	 */
+	if ((err_type & ERR_TYPE_MASK) == ERR_TYPE_RTAS_LOG)
+		printk_log_rtas(buf, len);
+
 	/* Check to see if we need to or have stopped logging */
 	if (fatal || no_more_logging) {
 		no_more_logging = 1;
@@ -181,9 +234,6 @@ void pSeries_log_error(char *buf, unsigned int err_type, int fatal)
 	/* call type specific method for error */
 	switch (err_type & ERR_TYPE_MASK) {
 	case ERR_TYPE_RTAS_LOG:
-		/* put into syslog and error_log file */
-		printk_log_rtas(buf, len);
-
 		offset = rtas_error_log_buffer_max *
 			((rtas_log_start+rtas_log_size) & LOG_NUMBER_MASK);
 
@@ -291,15 +341,18 @@ static int enable_surveillance(int timeout)
 {
 	int error;
 
-	error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL,
-			  SURVEILLANCE_TOKEN, 0, timeout);
+	error = rtas_set_indicator(SURVEILLANCE_TOKEN, 0, timeout);
 
-	if (error) {
-		printk(KERN_ERR "rtasd: could not enable surveillance\n");
-		return -1;
+	if (error == 0)
+		return 0;
+
+	if (error == RTAS_NO_SUCH_INDICATOR) {
+		printk(KERN_INFO "rtasd: surveillance not supported\n");
+		return 0;
 	}
 
-	return 0;
+	printk(KERN_ERR "rtasd: could not update surveillance\n");
+	return -1;
 }
 
 static int get_eventscan_parms(void)
@@ -318,21 +371,8 @@ static int get_eventscan_parms(void)
 	rtas_event_scan_rate = *ip;
 	DEBUG("rtas-event-scan-rate %d\n", rtas_event_scan_rate);
 
-	ip = (int *)get_property(node, "rtas-error-log-max", NULL);
-	if (ip == NULL) {
-		printk(KERN_ERR "rtasd: no rtas-error-log-max\n");
-		of_node_put(node);
-		return -1;
-	}
-	rtas_error_log_max = *ip;
-	DEBUG("rtas-error-log-max %d\n", rtas_error_log_max);
-
-	if (rtas_error_log_max > RTAS_ERROR_LOG_MAX) {
-		printk(KERN_ERR "rtasd: truncated error log from %d to %d bytes\n", rtas_error_log_max, RTAS_ERROR_LOG_MAX);
-		rtas_error_log_max = RTAS_ERROR_LOG_MAX;
-	}
-
 	/* Make room for the sequence number */
+	rtas_error_log_max = rtas_get_error_log_max();
 	rtas_error_log_buffer_max = rtas_error_log_max + sizeof(int);
 
 	of_node_put(node);
@@ -473,5 +513,15 @@ static int __init surveillance_setup(char *str)
 	return 1;
 }
 
+static int __init rtasmsgs_setup(char *str)
+{
+	if (strcmp(str, "on") == 0)
+		full_rtas_msgs = 1;
+	else if (strcmp(str, "off") == 0)
+		full_rtas_msgs = 0;
+
+	return 1;
+}
 __initcall(rtas_init);
 __setup("surveillance=", surveillance_setup);
+__setup("rtasmsgs=", rtasmsgs_setup);
diff --git a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c
index 7bf41f3ca..536a49918 100644
--- a/arch/ppc64/kernel/rtc.c
+++ b/arch/ppc64/kernel/rtc.c
@@ -34,8 +34,8 @@
 #include <linux/proc_fs.h>
 #include <linux/spinlock.h>
 #include <linux/bcd.h>
+#include <linux/interrupt.h>
 
-#include <asm/hardirq.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c
index dc090d425..1951866a7 100644
--- a/arch/ppc64/kernel/setup.c
+++ b/arch/ppc64/kernel/setup.c
@@ -10,6 +10,8 @@
  *      2 of the License, or (at your option) any later version.
  */
 
+#undef DEBUG
+
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/string.h>
@@ -27,6 +29,7 @@
 #include <linux/root_dev.h>
 #include <linux/notifier.h>
 #include <linux/cpu.h>
+#include <linux/unistd.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/processor.h>
@@ -47,60 +50,79 @@
 #include <asm/setup.h>
 #include <asm/system.h>
 #include <asm/rtas.h>
+#include <asm/iommu.h>
+
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+/*
+ * Here are some early debugging facilities. You can enable one
+ * but your kernel will not boot on anything else if you do so
+ */
+
+/* This one is for use on LPAR machines that support an HVC console
+ * on vterm 0
+ */
+extern void udbg_init_debug_lpar(void);
+/* This one is for use on Apple G5 machines
+ */
+extern void udbg_init_pmac_realmode(void);
+/* That's RTAS panel debug */
+extern void call_rtas_display_status_delay(unsigned char c);
+
+#define EARLY_DEBUG_INIT() do {} while(0)
+
+#if 0
+#define EARLY_DEBUG_INIT() udbg_init_debug_lpar()
+#define EARLY_DEBUG_INIT() udbg_init_pmac_realmode()
+#define EARLY_DEBUG_INIT()						\
+	do { ppc_md.udbg_putc = call_rtas_display_status_delay; } while(0)
+#endif
 
-extern unsigned long klimit;
 /* extern void *stab; */
 extern HTAB htab_data;
-extern unsigned long loops_per_jiffy;
-
-int have_of = 1;
+extern unsigned long klimit;
 
-extern void  chrp_init(unsigned long r3,
-		       unsigned long r4,
-		       unsigned long r5,
-		       unsigned long r6,
-		       unsigned long r7);
-
-extern void  pmac_init(unsigned long r3,
-		       unsigned long r4,
-		       unsigned long r5,
-		       unsigned long r6,
-		       unsigned long r7);
-
-extern void iSeries_init( void );
-extern void iSeries_init_early( void );
-extern void pSeries_init_early( void );
-extern void pSeriesLP_init_early(void);
-extern void pmac_init_early(void);
-extern void mm_init_ppc64( void ); 
-extern void pseries_secondary_smp_init(unsigned long); 
+extern void mm_init_ppc64(void);
 extern int  idle_setup(void);
-extern void vpa_init(int cpu);
+extern void stab_initialize(unsigned long stab);
+extern void htab_initialize(void);
+extern void early_init_devtree(void *flat_dt);
+extern void unflatten_device_tree(void);
 
 unsigned long decr_overclock = 1;
 unsigned long decr_overclock_proc0 = 1;
 unsigned long decr_overclock_set = 0;
 unsigned long decr_overclock_proc0_set = 0;
 
-int powersave_nap;
+int have_of = 1;
+int boot_cpuid = 0;
+dev_t boot_dev;
 
-unsigned char aux_device_present;
+/*
+ * These are used in binfmt_elf.c to put aux entries on the stack
+ * for each elf executable being started.
+ */
+int dcache_bsize;
+int icache_bsize;
+int ucache_bsize;
 
-void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5,
-		    unsigned long r6, unsigned long r7);
-int parse_bootinfo(void);
+/* The main machine-dep calls structure
+ */
+struct machdep_calls ppc_md;
 
 #ifdef CONFIG_MAGIC_SYSRQ
 unsigned long SYSRQ_KEY;
 #endif /* CONFIG_MAGIC_SYSRQ */
 
-struct machdep_calls ppc_md;
 
 static int ppc64_panic_event(struct notifier_block *, unsigned long, void *);
-
 static struct notifier_block ppc64_panic_block = {
-	notifier_call: ppc64_panic_event,
-	priority: INT_MIN /* may not return; must be done last */
+	.notifier_call = ppc64_panic_event,
+	.priority = INT_MIN /* may not return; must be done last */
 };
 
 /*
@@ -112,42 +134,32 @@ static struct notifier_block ppc64_panic_block = {
  * these processors use on existing boards.  -- Dan
  */ 
 struct screen_info screen_info = {
-	0, 25,			/* orig-x, orig-y */
-	0,			/* unused */
-	0,			/* orig-video-page */
-	0,			/* orig-video-mode */
-	80,			/* orig-video-cols */
-	0,0,0,			/* ega_ax, ega_bx, ega_cx */
-	25,			/* orig-video-lines */
-	1,			/* orig-video-isVGA */
-	16			/* orig-video-points */
+	.orig_x = 0,
+	.orig_y = 25,
+	.orig_video_cols = 80,
+	.orig_video_lines = 25,
+	.orig_video_isVGA = 1,
+	.orig_video_points = 16
 };
 
-/*
- * These are used in binfmt_elf.c to put aux entries on the stack
- * for each elf executable being started.
- */
-int dcache_bsize;
-int icache_bsize;
-int ucache_bsize;
-
 /*
  * Initialize the PPCDBG state.  Called before relocation has been enabled.
  */
-void ppcdbg_initialize(void) {
-	unsigned long offset = reloc_offset();
-	struct naca_struct *_naca = RELOC(naca);
-
-	_naca->debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */;
+void __init ppcdbg_initialize(void)
+{
+	naca->debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | */
+	/* PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */;
 }
 
+/*
+ * Early boot console based on udbg
+ */
 static struct console udbg_console = {
 	.name	= "udbg",
 	.write	= udbg_console_write,
 	.flags	= CON_PRINTBUFFER,
 	.index	= -1,
 };
-
 static int early_console_initialized;
 
 void __init disable_early_printk(void)
@@ -158,111 +170,457 @@ void __init disable_early_printk(void)
 	early_console_initialized = 0;
 }
 
-/*
- * Do some initial setup of the system.  The parameters are those which 
- * were passed in from the bootloader.
+#if defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_SMP)
+
+static int smt_enabled_cmdline;
+
+/* Look for ibm,smt-enabled OF option */
+static void check_smt_enabled(void)
+{
+	struct device_node *dn;
+	char *smt_option;
+
+	/* Allow the command line to overrule the OF option */
+	if (smt_enabled_cmdline)
+		return;
+
+	dn = of_find_node_by_path("/options");
+
+	if (dn) {
+		smt_option = (char *)get_property(dn, "ibm,smt-enabled", NULL);
+
+                if (smt_option) {
+			if (!strcmp(smt_option, "on"))
+				smt_enabled_at_boot = 1;
+			else if (!strcmp(smt_option, "off"))
+				smt_enabled_at_boot = 0;
+                }
+        }
+}
+
+/* Look for smt-enabled= cmdline option */
+static int __init early_smt_enabled(char *p)
+{
+	smt_enabled_cmdline = 1;
+
+	if (!p)
+		return 0;
+
+	if (!strcmp(p, "on") || !strcmp(p, "1"))
+		smt_enabled_at_boot = 1;
+	else if (!strcmp(p, "off") || !strcmp(p, "0"))
+		smt_enabled_at_boot = 0;
+
+	return 0;
+}
+early_param("smt-enabled", early_smt_enabled);
+
+/**
+ * setup_cpu_maps - initialize the following cpu maps:
+ *                  cpu_possible_map
+ *                  cpu_present_map
+ *                  cpu_sibling_map
+ *
+ * Having the possible map set up early allows us to restrict allocations
+ * of things like irqstacks to num_possible_cpus() rather than NR_CPUS.
+ *
+ * We do not initialize the online map here; cpus set their own bits in
+ * cpu_online_map as they come up.
+ *
+ * This function is valid only for Open Firmware systems.  finish_device_tree
+ * must be called before using this.
+ *
+ * While we're here, we may as well set the "physical" cpu ids in the paca.
  */
-void setup_system(unsigned long r3, unsigned long r4, unsigned long r5,
-		  unsigned long r6, unsigned long r7)
+static void __init setup_cpu_maps(void)
 {
-#if defined(CONFIG_SMP) && defined(CONFIG_PPC_PSERIES)
-	int ret, i;
-#endif
+	struct device_node *dn = NULL;
+	int cpu = 0;
+
+	check_smt_enabled();
+
+	while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) {
+		u32 *intserv;
+		int j, len = sizeof(u32), nthreads;
+
+		intserv = (u32 *)get_property(dn, "ibm,ppc-interrupt-server#s",
+					      &len);
+		if (!intserv)
+			intserv = (u32 *)get_property(dn, "reg", NULL);
+
+		nthreads = len / sizeof(u32);
+
+		for (j = 0; j < nthreads && cpu < NR_CPUS; j++) {
+			/*
+			 * Only spin up secondary threads if SMT is enabled.
+			 * We must leave space in the logical map for the
+			 * threads.
+			 */
+			if (j == 0 || smt_enabled_at_boot) {
+				cpu_set(cpu, cpu_present_map);
+				set_hard_smp_processor_id(cpu, intserv[j]);
+			}
+			cpu_set(cpu, cpu_possible_map);
+			cpu++;
+		}
+	}
 
-#ifdef CONFIG_XMON_DEFAULT
-	xmon_init();
-#endif
+	/*
+	 * On pSeries LPAR, we need to know how many cpus
+	 * could possibly be added to this partition.
+	 */
+	if (systemcfg->platform == PLATFORM_PSERIES_LPAR &&
+				(dn = of_find_node_by_path("/rtas"))) {
+		int num_addr_cell, num_size_cell, maxcpus;
+		unsigned int *ireg;
+
+		num_addr_cell = prom_n_addr_cells(dn);
+		num_size_cell = prom_n_size_cells(dn);
+
+		ireg = (unsigned int *)
+			get_property(dn, "ibm,lrdr-capacity", NULL);
+
+		if (!ireg)
+			goto out;
+
+		maxcpus = ireg[num_addr_cell + num_size_cell];
+
+		/* Double maxcpus for processors which have SMT capability */
+		if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+			maxcpus *= 2;
+
+		if (maxcpus > NR_CPUS) {
+			printk(KERN_WARNING
+			       "Partition configured for %d cpus, "
+			       "operating system maximum is %d.\n",
+			       maxcpus, NR_CPUS);
+			maxcpus = NR_CPUS;
+		} else
+			printk(KERN_INFO "Partition configured for %d cpus.\n",
+			       maxcpus);
+
+		for (cpu = 0; cpu < maxcpus; cpu++)
+			cpu_set(cpu, cpu_possible_map);
+	out:
+		of_node_put(dn);
+	}
+
+	/*
+	 * Do the sibling map; assume only two threads per processor.
+	 */
+	for_each_cpu(cpu) {
+		cpu_set(cpu, cpu_sibling_map[cpu]);
+		if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+			cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]);
+	}
+
+	systemcfg->processorCount = num_present_cpus();
+}
+#endif /* defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_SMP) */
 
-#ifdef CONFIG_PPC_ISERIES
-	/* pSeries systems are identified in prom.c via OF. */
-	if ( itLpNaca.xLparInstalled == 1 )
-		systemcfg->platform = PLATFORM_ISERIES_LPAR;
-#endif
-	
-	switch (systemcfg->platform) {
-#ifdef CONFIG_PPC_ISERIES
-	case PLATFORM_ISERIES_LPAR:
-		iSeries_init_early();
-		break;
-#endif
 
+#ifdef CONFIG_PPC_MULTIPLATFORM
+
+extern struct machdep_calls pSeries_md;
+extern struct machdep_calls pmac_md;
+
+/* Ultimately, stuff them in an elf section like initcalls... */
+static struct machdep_calls __initdata *machines[] = {
 #ifdef CONFIG_PPC_PSERIES
-	case PLATFORM_PSERIES:
-		pSeries_init_early();
-		parse_bootinfo();
-		break;
-
-	case PLATFORM_PSERIES_LPAR:
-		pSeriesLP_init_early();
-		parse_bootinfo();
-		break;
+	&pSeries_md,
 #endif /* CONFIG_PPC_PSERIES */
 #ifdef CONFIG_PPC_PMAC
-	case PLATFORM_POWERMAC:
-		pmac_init_early();
-		parse_bootinfo();
+	&pmac_md,
 #endif /* CONFIG_PPC_PMAC */
+	NULL
+};
+
+/*
+ * Early initialization entry point. This is called by head.S
+ * with MMU translation disabled. We rely on the "feature" of
+ * the CPU that ignores the top 2 bits of the address in real
+ * mode so we can access kernel globals normally provided we
+ * only toy with things in the RMO region. From here, we do
+ * some early parsing of the device-tree to setup out LMB
+ * data structures, and allocate & initialize the hash table
+ * and segment tables so we can start running with translation
+ * enabled.
+ *
+ * It is this function which will call the probe() callback of
+ * the various platform types and copy the matching one to the
+ * global ppc_md structure. Your platform can eventually do
+ * some very early initializations from the probe() routine, but
+ * this is not recommended, be very careful as, for example, the
+ * device-tree is not accessible via normal means at this point.
+ */
+
+void __init early_setup(unsigned long dt_ptr)
+{
+	struct paca_struct *lpaca = get_paca();
+	static struct machdep_calls **mach;
+
+	/*
+	 * Enable early debugging if any specified (see top of
+	 * this file)
+	 */
+	EARLY_DEBUG_INIT();
+
+	DBG(" -> early_setup()\n");
+
+	/*
+	 * Fill the default DBG level in naca (do we want to keep
+	 * that old mecanism around forever ?)
+	 */
+	ppcdbg_initialize();
+
+	/*
+	 * Do early initializations using the flattened device
+	 * tree, like retreiving the physical memory map or
+	 * calculating/retreiving the hash table size
+	 */
+	early_init_devtree(__va(dt_ptr));
+
+	/*
+	 * Iterate all ppc_md structures until we find the proper
+	 * one for the current machine type
+	 */
+	DBG("Probing machine type for platform %x...\n",
+	    systemcfg->platform);
+
+	for (mach = machines; *mach; mach++) {
+		if ((*mach)->probe(systemcfg->platform))
+			break;
+	}
+	/* What can we do if we didn't find ? */
+	if (*mach == NULL) {
+		DBG("No suitable machine found !\n");
+		for (;;);
+	}
+	ppc_md = **mach;
+
+	/* our udbg callbacks got overriden by the above, let's put them
+	 * back in. Ultimately, I want those things to be split from the
+	 * main ppc_md
+	 */
+	EARLY_DEBUG_INIT();
+
+	DBG("Found, Initializing memory management...\n");
+
+	/*
+	 * Initialize stab / SLB management
+	 */
+	stab_initialize(lpaca->stab_real);
+
+	/*
+	 * Initialize the MMU Hash table and create the linear mapping
+	 * of memory
+	 */
+	htab_initialize();
+
+	DBG(" <- early_setup()\n");
+}
+
+
+/*
+ * Initialize some remaining members of the naca and systemcfg structures
+ * (at least until we get rid of them completely). This is mostly some
+ * cache informations about the CPU that will be used by cache flush
+ * routines and/or provided to userland
+ */
+static void __init initialize_naca(void)
+{
+	struct device_node *np;
+	unsigned long num_cpus = 0;
+
+	DBG(" -> initialize_naca()\n");
+
+	for (np = NULL; (np = of_find_node_by_type(np, "cpu"));) {
+		num_cpus += 1;
+
+		/* We're assuming *all* of the CPUs have the same
+		 * d-cache and i-cache sizes... -Peter
+		 */
+
+		if ( num_cpus == 1 ) {
+			u32 *sizep, *lsizep;
+			u32 size, lsize;
+			const char *dc, *ic;
+
+			/* Then read cache informations */
+			if (systemcfg->platform == PLATFORM_POWERMAC) {
+				dc = "d-cache-block-size";
+				ic = "i-cache-block-size";
+			} else {
+				dc = "d-cache-line-size";
+				ic = "i-cache-line-size";
+			}
+
+			size = 0;
+			lsize = cur_cpu_spec->dcache_bsize;
+			sizep = (u32 *)get_property(np, "d-cache-size", NULL);
+			if (sizep != NULL)
+				size = *sizep;
+			lsizep = (u32 *) get_property(np, dc, NULL);
+			if (lsizep != NULL)
+				lsize = *lsizep;
+
+			if (sizep == 0 || lsizep == 0)
+				DBG("Argh, can't find dcache properties ! "
+				    "sizep: %p, lsizep: %p\n", sizep, lsizep);
+
+			systemcfg->dCacheL1Size = size;
+			systemcfg->dCacheL1LineSize = lsize;
+			naca->dCacheL1LogLineSize = __ilog2(lsize);
+			naca->dCacheL1LinesPerPage = PAGE_SIZE/(lsize);
+
+			size = 0;
+			lsize = cur_cpu_spec->icache_bsize;
+			sizep = (u32 *)get_property(np, "i-cache-size", NULL);
+			if (sizep != NULL)
+				size = *sizep;
+			lsizep = (u32 *)get_property(np, ic, NULL);
+			if (lsizep != NULL)
+				lsize = *lsizep;
+			if (sizep == 0 || lsizep == 0)
+				DBG("Argh, can't find icache properties ! "
+				    "sizep: %p, lsizep: %p\n", sizep, lsizep);
+
+			systemcfg->iCacheL1Size = size;
+			systemcfg->iCacheL1LineSize = lsize;
+			naca->iCacheL1LogLineSize = __ilog2(lsize);
+			naca->iCacheL1LinesPerPage = PAGE_SIZE/(lsize);
+
+		}
+	}
+
+	/* Add an eye catcher and the systemcfg layout version number */
+	strcpy(systemcfg->eye_catcher, "SYSTEMCFG:PPC64");
+	systemcfg->version.major = SYSTEMCFG_MAJOR;
+	systemcfg->version.minor = SYSTEMCFG_MINOR;
+	systemcfg->processor = mfspr(SPRN_PVR);
+
+	DBG(" <- initialize_naca()\n");
+}
+
+static void __init check_for_initrd(void)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+	u64 *prop;
+
+	DBG(" -> check_for_initrd()\n");
+
+	prop = (u64 *)get_property(of_chosen, "linux,initrd-start", NULL);
+	if (prop != NULL) {
+		initrd_start = (unsigned long)__va(*prop);
+		prop = (u64 *)get_property(of_chosen, "linux,initrd-end", NULL);
+		if (prop != NULL) {
+			initrd_end = (unsigned long)__va(*prop);
+			initrd_below_start_ok = 1;
+		} else
+			initrd_start = 0;
 	}
 
 	/* If we were passed an initrd, set the ROOT_DEV properly if the values
 	 * look sensible. If not, clear initrd reference.
 	 */
-#ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE &&
 	    initrd_end > initrd_start)
 		ROOT_DEV = Root_RAM0;
 	else
 		initrd_start = initrd_end = 0;
+
+	if (initrd_start)
+		printk("Found initrd at 0x%lx:0x%lx\n", initrd_start, initrd_end);
+
+	DBG(" <- check_for_initrd()\n");
 #endif /* CONFIG_BLK_DEV_INITRD */
+}
 
-#ifdef CONFIG_BOOTX_TEXT
-	map_boot_text();
-	if (systemcfg->platform == PLATFORM_POWERMAC) {
-		early_console_initialized = 1;
-		register_console(&udbg_console);
-	}
-#endif /* CONFIG_BOOTX_TEXT */
+#endif /* CONFIG_PPC_MULTIPLATFORM */
 
-#ifdef CONFIG_PPC_PSERIES
-	if (systemcfg->platform & PLATFORM_PSERIES) {
-		early_console_initialized = 1;
-		register_console(&udbg_console);
-		__irq_offset_value = NUM_ISA_INTERRUPTS;
-		finish_device_tree();
-		chrp_init(r3, r4, r5, r6, r7);
+/*
+ * Do some initial setup of the system.  The parameters are those which 
+ * were passed in from the bootloader.
+ */
+void __init setup_system(void)
+{
+	DBG(" -> setup_system()\n");
 
-#ifdef CONFIG_SMP
-		/* Start secondary threads on SMT systems */
-		for (i = 0; i < NR_CPUS; i++) {
-			if (cpu_available(i) && !cpu_possible(i)) {
-				printk("%16.16x : starting thread\n", i);
-				rtas_call(rtas_token("start-cpu"), 3, 1, &ret,
-					  get_hard_smp_processor_id(i), 
-					  (u32)*((unsigned long *)pseries_secondary_smp_init),
-					  i);
-				cpu_set(i, cpu_possible_map);
-				systemcfg->processorCount++;
-			}
-		}
-#endif /* CONFIG_SMP */
-	}
+#ifdef CONFIG_PPC_ISERIES
+	/* pSeries systems are identified in prom.c via OF. */
+	if (itLpNaca.xLparInstalled == 1)
+		systemcfg->platform = PLATFORM_ISERIES_LPAR;
+
+	ppc_md.init_early();
+#else /* CONFIG_PPC_ISERIES */
+
+	/*
+	 * Unflatten the device-tree passed by prom_init or kexec
+	 */
+	unflatten_device_tree();
+
+	/*
+	 * Fill the naca & systemcfg structures with informations
+	 * retreived from the device-tree. Need to be called before
+	 * finish_device_tree() since the later requires some of the
+	 * informations filled up here to properly parse the interrupt
+	 * tree.
+	 * It also sets up the cache line sizes which allows to call
+	 * routines like flush_icache_range (used by the hash init
+	 * later on).
+	 */
+	initialize_naca();
+
+#ifdef CONFIG_PPC_PSERIES
+	/*
+	 * Initialize RTAS if available
+	 */
+	rtas_initialize();
 #endif /* CONFIG_PPC_PSERIES */
 
-#ifdef CONFIG_PPC_PMAC
-	if (systemcfg->platform == PLATFORM_POWERMAC) {
-		finish_device_tree();
-		pmac_init(r3, r4, r5, r6, r7);
-	}
-#endif /* CONFIG_PPC_PMAC */
+	/*
+	 * Check if we have an initrd provided via the device-tree
+	 */
+	check_for_initrd();
 
-#if defined(CONFIG_HOTPLUG_CPU) &&  !defined(CONFIG_PPC_PMAC)
-	rtas_stop_self_args.token = rtas_token("stop-self");
-#endif /* CONFIG_HOTPLUG_CPU && !CONFIG_PPC_PMAC */
+	/*
+	 * Do some platform specific early initializations, that includes
+	 * setting up the hash table pointers. It also sets up some interrupt-mapping
+	 * related options that will be used by finish_device_tree()
+	 */
+	ppc_md.init_early();
 
-	/* Finish initializing the hash table (do the dynamic
-	 * patching for the fast-path hashtable.S code)
+	/*
+	 * "Finish" the device-tree, that is do the actual parsing of
+	 * some of the properties like the interrupt map
 	 */
-	htab_finish_init();
+	finish_device_tree();
+
+	/*
+	 * Initialize xmon
+	 */
+#ifdef CONFIG_XMON_DEFAULT
+	xmon_init();
+#endif
+	/*
+	 * Register early console
+	 */
+	early_console_initialized = 1;
+	register_console(&udbg_console);
+
+#endif /* !CONFIG_PPC_ISERIES */
+
+	/* Save unparsed command line copy for /proc/cmdline */
+	strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
+
+	parse_early_param();
+
+#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES)
+	/*
+	 * iSeries has already initialized the cpu maps at this point.
+	 */
+	setup_cpu_maps();
+#endif /* defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES) */
 
 	printk("Starting Linux PPC64 %s\n", UTS_RELEASE);
 
@@ -282,28 +640,10 @@ void setup_system(unsigned long r3, unsigned long r4, unsigned long r5,
 
 	mm_init_ppc64();
 
-#if defined(CONFIG_SMP) && defined(CONFIG_PPC_PSERIES)
-	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
-		vpa_init(boot_cpuid);
-	}
-#endif
-
-	/* Select the correct idle loop for the platform. */
-	idle_setup();
-
-	switch (systemcfg->platform) {
-#ifdef CONFIG_PPC_ISERIES
-	case PLATFORM_ISERIES_LPAR:
-		iSeries_init();
-		break;
-#endif
-	default:
-		/* The following relies on the device tree being */
-		/* fully configured.                             */
-		parse_cmd_line(r3, r4, r5, r6, r7);
-	}
+	DBG(" <- setup_system()\n");
 }
 
+
 void machine_restart(char *cmd)
 {
 	if (ppc_md.nvram_sync)
@@ -373,7 +713,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 #ifdef CONFIG_SMP
 	pvr = per_cpu(pvr, cpu_id);
 #else
-	pvr = _get_PVR();
+	pvr = mfspr(SPRN_PVR);
 #endif
 	maj = (pvr >> 8) & 0xFF;
 	min = pvr & 0xFF;
@@ -425,74 +765,75 @@ struct seq_operations cpuinfo_op = {
 	.show =	show_cpuinfo,
 };
 
-/*
- * Fetch the cmd_line from open firmware. 
- */
-void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5,
-		  unsigned long r6, unsigned long r7)
-{
-	cmd_line[0] = 0;
+#if 0 /* XXX not currently used */
+unsigned long memory_limit;
 
-#ifdef CONFIG_CMDLINE
-	strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
-#endif /* CONFIG_CMDLINE */
+static int __init early_parsemem(char *p)
+{
+	if (!p)
+		return 0;
 
-#ifdef CONFIG_PPC_PSERIES
-	{
-	struct device_node *chosen;
-
-	chosen = of_find_node_by_name(NULL, "chosen");
-	if (chosen != NULL) {
-		char *p;
-		p = get_property(chosen, "bootargs", NULL);
-		if (p != NULL && p[0] != 0)
-			strlcpy(cmd_line, p, sizeof(cmd_line));
-		of_node_put(chosen);
-	}
-	}
-#endif
+	memory_limit = memparse(p, &p);
 
-	/* Look for mem= option on command line */
-	if (strstr(cmd_line, "mem=")) {
-		char *p, *q;
-		unsigned long maxmem = 0;
-		extern unsigned long __max_memory;
-
-		for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {
-			q = p + 4;
-			if (p > cmd_line && p[-1] != ' ')
-				continue;
-			maxmem = simple_strtoul(q, &q, 0);
-			if (*q == 'k' || *q == 'K') {
-				maxmem <<= 10;
-				++q;
-			} else if (*q == 'm' || *q == 'M') {
-				maxmem <<= 20;
-				++q;
-			}
-		}
-		__max_memory = maxmem;
-	}
+	return 0;
 }
+early_param("mem", early_parsemem);
+#endif
 
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
 static int __init set_preferred_console(void)
 {
 	struct device_node *prom_stdout;
 	char *name;
-	int offset;
+	int offset = 0;
+#if  0
+	phandle *stdout_ph;
+#endif
+	DBG(" -> set_preferred_console()\n");
 
 	/* The user has requested a console so this is already set up. */
-	if (strstr(saved_command_line, "console="))
+	if (strstr(saved_command_line, "console=")) {
+		DBG(" console was specified !\n");
 		return -EBUSY;
+	}
 
-	prom_stdout = find_path_device(of_stdout_device);
-	if (!prom_stdout)
+	if (!of_chosen) {
+		DBG(" of_chosen is NULL !\n");
 		return -ENODEV;
+	}
+	/* We are getting a weird phandle from OF ... */
+#if 0
+	stdout_ph = (phandle *)get_property(of_chosen, "linux,stdout-package", NULL);
+	if (stdout_ph == NULL) {
+		DBG(" no linux,stdout-package !\n");
+		return -ENODEV;
+	}
+	prom_stdout = of_find_node_by_phandle(*stdout_ph);
+	if (!prom_stdout) {
+		DBG(" can't find stdout package for phandle 0x%x !\n", *stdout_ph);
+		return -ENODEV;
+	}
+#endif
+	/* ... So use the full path instead */
+#if 1
+	name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
+	if (name == NULL) {
+		DBG(" no linux,stdout-path !\n");
+		return -ENODEV;
+	}
+	prom_stdout = of_find_node_by_path(name);
+	if (!prom_stdout) {
+		DBG(" can't find stdout package %s !\n", name);
+		return -ENODEV;
+	}	
+#endif
+	DBG("stdout is %s\n", prom_stdout->full_name);
 
 	name = (char *)get_property(prom_stdout, "name", NULL);
-	if (!name)
-		return -ENODEV;
+	if (!name) {
+		DBG(" stdout package has no name !\n");
+		goto not_found;
+	}
 
 	if (strcmp(name, "serial") == 0) {
 		int i;
@@ -513,76 +854,69 @@ static int __init set_preferred_console(void)
 					break;
 				default:
 					/* We dont recognise the serial port */
-					return -ENODEV;
+					goto not_found;
 			}
 		}
-	} else if (strcmp(name, "vty") == 0)
-		/* pSeries LPAR virtual console */
-		return add_preferred_console("hvc", 0, NULL);
+	}
+#ifdef CONFIG_PPC_PSERIES
+	else if (strcmp(name, "vty") == 0) {
+ 		u32 *reg = (u32 *)get_property(prom_stdout, "reg", NULL);
+ 		char *compat = (char *)get_property(prom_stdout, "compatible", NULL);
+
+ 		if (reg && compat && (strcmp(compat, "hvterm-protocol") == 0)) {
+ 			/* Host Virtual Serial Interface */
+ 			int offset;
+ 			switch (reg[0]) {
+ 				case 0x30000000:
+ 					offset = 0;
+ 					break;
+ 				case 0x30000001:
+ 					offset = 1;
+ 					break;
+ 				default:
+					goto not_found;
+ 			}
+			of_node_put(prom_stdout);
+			DBG("Found hvsi console at offset %d\n", offset);
+ 			return add_preferred_console("hvsi", offset, NULL);
+ 		} else {
+ 			/* pSeries LPAR virtual console */
+			of_node_put(prom_stdout);
+			DBG("Found hvc console\n");
+ 			return add_preferred_console("hvc", 0, NULL);
+ 		}
+	}
+#endif /* CONFIG_PPC_PSERIES */
 	else if (strcmp(name, "ch-a") == 0)
 		offset = 0;
 	else if (strcmp(name, "ch-b") == 0)
 		offset = 1;
 	else
-		return -ENODEV;
+		goto not_found;
+	of_node_put(prom_stdout);
+
+	DBG("Found serial console at ttyS%d\n", offset);
 
 	return add_preferred_console("ttyS", offset, NULL);
 
+ not_found:
+	DBG("No preferred console found !\n");
+	of_node_put(prom_stdout);
+	return -ENODEV;
 }
 console_initcall(set_preferred_console);
-
-int parse_bootinfo(void)
-{
-	struct bi_record *rec;
-
-	rec = prom.bi_recs;
-
-	if ( rec == NULL || rec->tag != BI_FIRST )
-		return -1;
-
-	for ( ; rec->tag != BI_LAST ; rec = bi_rec_next(rec) ) {
-		switch (rec->tag) {
-		case BI_CMD_LINE:
-			strlcpy(cmd_line, (void *)rec->data, sizeof(cmd_line));
-			break;
-		}
-	}
-
-	return 0;
-}
-#endif
-
-int __init ppc_init(void)
-{
-	/* clear the progress line */
-	ppc_md.progress(" ", 0xffff);
-
-	if (ppc_md.init != NULL) {
-		ppc_md.init();
-	}
-	return 0;
-}
-
-arch_initcall(ppc_init);
-
-void __init ppc64_calibrate_delay(void)
-{
-	loops_per_jiffy = tb_ticks_per_jiffy;
-
-	printk("Calibrating delay loop... %lu.%02lu BogoMips\n",
-			       loops_per_jiffy/(500000/HZ),
-			       loops_per_jiffy/(5000/HZ) % 100);
-}	
-
-extern void (*calibrate_delay)(void);
+#endif /* CONFIG_PPC_MULTIPLATFORM */
 
 #ifdef CONFIG_IRQSTACKS
 static void __init irqstack_early_init(void)
 {
-	int i;
+	unsigned int i;
 
-	/* interrupt stacks must be under 256MB, we cannot afford to take SLB misses on them */
-	for (i = 0; i < NR_CPUS; i++) {
+	/*
+	 * interrupt stacks must be under 256MB, we cannot afford to take
+	 * SLB misses on them.
+	 */
+	for_each_cpu(i) {
 		softirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE,
 					THREAD_SIZE, 0x10000000));
 		hardirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE,
@@ -593,6 +927,31 @@ static void __init irqstack_early_init(void)
 #define irqstack_early_init()
 #endif
 
+/*
+ * Stack space used when we detect a bad kernel stack pointer, and
+ * early in SMP boots before relocation is enabled.
+ */
+static void __init emergency_stack_init(void)
+{
+	unsigned long limit;
+	unsigned int i;
+
+	/*
+	 * Emergency stacks must be under 256MB, we cannot afford to take
+	 * SLB misses on them. The ABI also requires them to be 128-byte
+	 * aligned.
+	 *
+	 * Since we use these as temporary stacks during secondary CPU
+	 * bringup, we need to get at them in real mode. This means they
+	 * must also be within the RMO region.
+	 */
+	limit = min(0x10000000UL, lmb.rmo_size);
+
+	for_each_cpu(i)
+		paca[i].emergency_sp = __va(lmb_alloc_base(PAGE_SIZE, 128,
+						limit)) + PAGE_SIZE;
+}
+
 /*
  * Called into from start_kernel, after lock_kernel has been called.
  * Initializes bootmem, which is unsed to manage page allocation until
@@ -603,17 +962,9 @@ void __init setup_arch(char **cmdline_p)
 	extern int panic_timeout;
 	extern void do_init_bootmem(void);
 
-	calibrate_delay = ppc64_calibrate_delay;
-
 	ppc64_boot_msg(0x12, "Setup Arch");
 
-#ifdef CONFIG_XMON
-	if (strstr(cmd_line, "xmon")) {
-		/* ensure xmon is enabled */
-		xmon_init();
-		debugger(0);
-	}
-#endif /* CONFIG_XMON */
+	*cmdline_p = cmd_line;
 
 	/*
 	 * Set cache line size based on type of cpu as a default.
@@ -634,21 +985,22 @@ void __init setup_arch(char **cmdline_p)
 	init_mm.end_data = (unsigned long) _edata;
 	init_mm.brk = klimit;
 	
-	/* Save unparsed command line copy for /proc/cmdline */
-	strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
-	*cmdline_p = cmd_line;
-
 	irqstack_early_init();
+	emergency_stack_init();
 
 	/* set up the bootmem stuff with available memory */
 	do_init_bootmem();
 
+	/* Select the correct idle loop for the platform. */
+	idle_setup();
+
 	ppc_md.setup_arch();
 
 	paging_init();
 	ppc64_boot_msg(0x15, "Setup Done");
 }
 
+
 /* ToDo: do something useful if ppc_md is not yet setup. */
 #define PPC64_LINUX_FUNCTION 0x0f000000
 #define PPC64_IPL_MESSAGE 0xc0000000
@@ -753,3 +1105,16 @@ int set_decr_overclock( char * str )
 __setup("spread_lpevents=", set_spread_lpevents );
 __setup("decr_overclock_proc0=", set_decr_overclock_proc0 );
 __setup("decr_overclock=", set_decr_overclock );
+
+#ifdef CONFIG_XMON
+static int __init early_xmon(char *p)
+{
+	/* ensure xmon is enabled */
+	xmon_init();
+	debugger(0);
+
+	return 0;
+}
+early_param("xmon", early_xmon);
+#endif
+
diff --git a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c
index 8323d7355..ce616280b 100644
--- a/arch/ppc64/kernel/signal.c
+++ b/arch/ppc64/kernel/signal.c
@@ -26,7 +26,6 @@
 #include <linux/unistd.h>
 #include <linux/stddef.h>
 #include <linux/elf.h>
-#include <asm/ppc32.h>
 #include <asm/sigcontext.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
@@ -127,7 +126,7 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
 	 * v_regs pointer or not
 	 */
 #ifdef CONFIG_ALTIVEC
-	elf_vrreg_t __user *v_regs = (elf_vrreg_t __user *)(((unsigned long)sc->vmx_reserve) & ~0xful);
+	elf_vrreg_t __user *v_regs = (elf_vrreg_t __user *)(((unsigned long)sc->vmx_reserve + 15) & ~0xful);
 #endif
 	long err = 0;
 
@@ -178,7 +177,7 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
 	elf_vrreg_t __user *v_regs;
 #endif
 	unsigned long err = 0;
-	unsigned long save_r13;
+	unsigned long save_r13 = 0;
 	elf_greg_t *gregs = (elf_greg_t *)regs;
 	int i;
 
@@ -371,7 +370,8 @@ badframe:
 	printk("badframe in sys_rt_sigreturn, regs=%p uc=%p &uc->uc_mcontext=%p\n",
 	       regs, uc, &uc->uc_mcontext);
 #endif
-	do_exit(SIGSEGV);
+	force_sig(SIGSEGV, current);
+	return 0;
 }
 
 static void setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
@@ -446,7 +446,7 @@ badframe:
 	printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n",
 	       regs, frame, newsp);
 #endif
-	do_exit(SIGSEGV);
+	force_sigsegv(signr, current);
 }
 
 
@@ -459,17 +459,13 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
 	/* Set up Signal Frame */
 	setup_rt_frame(sig, ka, info, oldset, regs);
 
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
-
 	if (!(ka->sa.sa_flags & SA_NODEFER)) {
 		spin_lock_irq(&current->sighand->siglock);
-		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+		sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
 		sigaddset(&current->blocked,sig);
 		recalc_sigpending();
 		spin_unlock_irq(&current->sighand->siglock);
 	}
-	return;
 }
 
 static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
@@ -512,6 +508,7 @@ 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
@@ -523,14 +520,12 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
 	if (!oldset)
 		oldset = &current->blocked;
 
-	signr = get_signal_to_deliver(&info, regs, NULL);
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
-		struct k_sigaction *ka = &current->sighand->action[signr-1];
-
 		/* Whee!  Actually deliver the signal.  */
 		if (TRAP(regs) == 0x0C00)
-			syscall_restart(regs, ka);
-		handle_signal(signr, ka, &info, oldset, regs);
+			syscall_restart(regs, &ka);
+		handle_signal(signr, &ka, &info, oldset, regs);
 		return 1;
 	}
 
diff --git a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c
index 106f008af..79f7b8446 100644
--- a/arch/ppc64/kernel/signal32.c
+++ b/arch/ppc64/kernel/signal32.c
@@ -189,7 +189,7 @@ static long restore_user_regs(struct pt_regs *regs,
 	elf_greg_t64 *gregs = (elf_greg_t64 *)regs;
 	int i;
 	long err = 0;
-	unsigned int save_r2;
+	unsigned int save_r2 = 0;
 #ifdef CONFIG_ALTIVEC
 	unsigned long msr;
 #endif
@@ -472,10 +472,14 @@ static long copy_siginfo_to_user32(compat_siginfo_t __user *d, siginfo_t *s)
 				  &d->si_addr);
 		break;
 	case __SI_POLL >> 16:
-	case __SI_TIMER >> 16:
 		err |= __put_user(s->si_band, &d->si_band);
 		err |= __put_user(s->si_fd, &d->si_fd);
 		break;
+	case __SI_TIMER >> 16:
+		err |= __put_user(s->si_tid, &d->si_tid);
+		err |= __put_user(s->si_overrun, &d->si_overrun);
+		err |= __put_user(s->si_int, &d->si_int);
+		break;
 	case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */
 	case __SI_MESGQ >> 16:
 		err |= __put_user(s->si_int, &d->si_int);
@@ -699,9 +703,7 @@ badframe:
 	printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n",
 	       regs, frame, newsp);
 #endif
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static long do_setcontext32(struct ucontext32 __user *ucp, struct pt_regs *regs, int sig)
@@ -864,9 +866,7 @@ badframe:
 	printk("badframe in handle_signal, regs=%p frame=%x newsp=%x\n",
 	       regs, frame, *newspp);
 #endif
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 /*
@@ -928,18 +928,16 @@ badframe:
 int do_signal32(sigset_t *oldset, struct pt_regs *regs)
 {
 	siginfo_t info;
-	struct k_sigaction *ka;
 	unsigned int frame, newsp;
 	int signr, ret;
+	struct k_sigaction ka;
 
 	if (!oldset)
 		oldset = &current->blocked;
 
 	newsp = frame = 0;
 
-	signr = get_signal_to_deliver(&info, regs, NULL);
-
-	ka = (signr == 0)? NULL: &current->sighand->action[signr-1];
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
 	if (TRAP(regs) == 0x0C00		/* System Call! */
 	    && regs->ccr & 0x10000000		/* error signalled */
@@ -950,7 +948,7 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
 		if (signr > 0
 		    && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK
 			|| (ret == ERESTARTSYS
-			    && !(ka->sa.sa_flags & SA_RESTART)))) {
+			    && !(ka.sa.sa_flags & SA_RESTART)))) {
 			/* make the system call return an EINTR error */
 			regs->result = -EINTR;
 			regs->gpr[3] = EINTR;
@@ -969,7 +967,7 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
 	if (signr == 0)
 		return 0;		/* no signals delivered */
 
-	if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
+	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
@@ -977,17 +975,15 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
 	newsp &= ~0xfUL;
 
 	/* Whee!  Actually deliver the signal.  */
-	if (ka->sa.sa_flags & SA_SIGINFO)
-		handle_rt_signal32(signr, ka, &info, oldset, regs, newsp);
+	if (ka.sa.sa_flags & SA_SIGINFO)
+		handle_rt_signal32(signr, &ka, &info, oldset, regs, newsp);
 	else
-		handle_signal32(signr, ka, &info, oldset, regs, newsp);
-
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
+		handle_signal32(signr, &ka, &info, oldset, regs, newsp);
 
-	if (!(ka->sa.sa_flags & SA_NODEFER)) {
+	if (!(ka.sa.sa_flags & SA_NODEFER)) {
 		spin_lock_irq(&current->sighand->siglock);
-		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+		sigorsets(&current->blocked, &current->blocked,
+			  &ka.sa.sa_mask);
 		sigaddset(&current->blocked, signr);
 		recalc_sigpending();
 		spin_unlock_irq(&current->sighand->siglock);
diff --git a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c
index 1f3003408..75ced7528 100644
--- a/arch/ppc64/kernel/smp.c
+++ b/arch/ppc64/kernel/smp.c
@@ -15,6 +15,8 @@
  *      2 of the License, or (at your option) any later version.
  */
 
+#undef DEBUG
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -36,7 +38,6 @@
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/hardirq.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/smp.h>
@@ -53,14 +54,20 @@
 #include <asm/cputable.h>
 #include <asm/system.h>
 #include <asm/rtas.h>
+#include <asm/plpar_wrappers.h>
+
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
 
 int smp_threads_ready;
 unsigned long cache_decay_ticks;
 
 cpumask_t cpu_possible_map = CPU_MASK_NONE;
 cpumask_t cpu_online_map = CPU_MASK_NONE;
-cpumask_t cpu_available_map = CPU_MASK_NONE;
-cpumask_t cpu_present_at_boot = CPU_MASK_NONE;
+cpumask_t cpu_sibling_map[NR_CPUS] = { [0 ... NR_CPUS-1] = CPU_MASK_NONE };
 
 EXPORT_SYMBOL(cpu_online_map);
 EXPORT_SYMBOL(cpu_possible_map);
@@ -76,9 +83,13 @@ void smp_call_function_interrupt(void);
 extern long register_vpa(unsigned long flags, unsigned long proc,
 			 unsigned long vpa);
 
+int smt_enabled_at_boot = 1;
+
 /* Low level assembly function used to backup CPU 0 state */
 extern void __save_cpu_setup(void);
 
+extern void pseries_secondary_smp_init(unsigned long); 
+
 #ifdef CONFIG_PPC_ISERIES
 static unsigned long iSeries_smp_message[NR_CPUS];
 
@@ -124,9 +135,8 @@ static int smp_iSeries_numProcs(void)
 	np = 0;
         for (i=0; i < NR_CPUS; ++i) {
                 if (paca[i].lppaca.xDynProcStatus < 2) {
-			cpu_set(i, cpu_available_map);
 			cpu_set(i, cpu_possible_map);
-			cpu_set(i, cpu_present_at_boot);
+			cpu_set(i, cpu_present_map);
                         ++np;
                 }
         }
@@ -183,7 +193,7 @@ void __init smp_init_iSeries(void)
 }
 #endif
 
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
 void smp_openpic_message_pass(int target, int msg)
 {
 	/* make sure we're sending something that translates to an IPI */
@@ -224,7 +234,10 @@ static void __devinit smp_openpic_setup_cpu(int cpu)
 	do_openpic_setup_cpu();
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+
+#ifdef CONFIG_PPC_PSERIES
+
 /* Get state of physical CPU.
  * Return codes:
  *	0	- The processor is in the RTAS stopped state
@@ -233,13 +246,15 @@ static void __devinit smp_openpic_setup_cpu(int cpu)
  *	-1	- Hardware Error
  *	-2	- Hardware Busy, Try again later.
  */
-static int query_cpu_stopped(unsigned int pcpu)
+int query_cpu_stopped(unsigned int pcpu)
 {
 	int cpu_status;
 	int status, qcss_tok;
 
+	DBG(" -> query_cpu_stopped(%d)\n", pcpu);
 	qcss_tok = rtas_token("query-cpu-stopped-state");
-	BUG_ON(qcss_tok == RTAS_UNKNOWN_SERVICE);
+	if (qcss_tok == RTAS_UNKNOWN_SERVICE)
+		return -1;
 	status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu);
 	if (status != 0) {
 		printk(KERN_ERR
@@ -247,9 +262,13 @@ static int query_cpu_stopped(unsigned int pcpu)
 		return status;
 	}
 
+	DBG(" <- query_cpu_stopped(), status: %d\n", cpu_status);
+
 	return cpu_status;
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+
 int __cpu_disable(void)
 {
 	/* FIXME: go put this in a header somewhere */
@@ -272,13 +291,12 @@ void __cpu_die(unsigned int cpu)
 	int cpu_status;
 	unsigned int pcpu = get_hard_smp_processor_id(cpu);
 
-	for (tries = 0; tries < 5; tries++) {
+	for (tries = 0; tries < 25; tries++) {
 		cpu_status = query_cpu_stopped(pcpu);
-
-		if (cpu_status == 0)
+		if (cpu_status == 0 || cpu_status == -1)
 			break;
 		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ);
+		schedule_timeout(HZ/5);
 	}
 	if (cpu_status != 0) {
 		printk("Querying DEAD? cpu %i (%i) shows %i\n",
@@ -372,13 +390,13 @@ out:
 static inline int __devinit smp_startup_cpu(unsigned int lcpu)
 {
 	int status;
-	extern void (*pseries_secondary_smp_init)(unsigned int cpu);
-	unsigned long start_here = __pa(pseries_secondary_smp_init);
+	unsigned long start_here = __pa((u32)*((unsigned long *)
+					       pseries_secondary_smp_init));
 	unsigned int pcpu;
 
 	/* At boot time the cpus are already spinning in hold
 	 * loops, so nothing to do. */
- 	if (system_state == SYSTEM_BOOTING)
+ 	if (system_state < SYSTEM_RUNNING)
 		return 1;
 
 	pcpu = find_physical_cpu_to_start(get_hard_smp_processor_id(lcpu));
@@ -401,56 +419,11 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
 	}
 	return 1;
 }
-
-static inline void look_for_more_cpus(void)
-{
-	int num_addr_cell, num_size_cell, len, i, maxcpus;
-	struct device_node *np;
-	unsigned int *ireg;
-
-	/* Find the property which will tell us about how many CPUs
-	 * we're allowed to have. */
-	if ((np = find_path_device("/rtas")) == NULL) {
-		printk(KERN_ERR "Could not find /rtas in device tree!");
-		return;
-	}
-	num_addr_cell = prom_n_addr_cells(np);
-	num_size_cell = prom_n_size_cells(np);
-
-	ireg = (unsigned int *)get_property(np, "ibm,lrdr-capacity", &len);
-	if (ireg == NULL) {
-		/* FIXME: make sure not marked as lrdr_capable() */
-		return;
-	}
-
-	maxcpus = ireg[num_addr_cell + num_size_cell];
-
-	/* Double maxcpus for processors which have SMT capability */
-	if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
-		maxcpus *= 2;
-
-
-	if (maxcpus > NR_CPUS) {
-		printk(KERN_WARNING
-		       "Partition configured for %d cpus, "
-		       "operating system maximum is %d.\n", maxcpus, NR_CPUS);
-		maxcpus = NR_CPUS;
-	} else
-		printk(KERN_INFO "Partition configured for %d cpus.\n",
-		       maxcpus);
-
-	/* Make those cpus (which might appear later) possible too. */
-	for (i = 0; i < maxcpus; i++)
-		cpu_set(i, cpu_possible_map);
-}
 #else /* ... CONFIG_HOTPLUG_CPU */
 static inline int __devinit smp_startup_cpu(unsigned int lcpu)
 {
 	return 1;
 }
-static inline void look_for_more_cpus(void)
-{
-}
 #endif /* CONFIG_HOTPLUG_CPU */
 
 static void smp_pSeries_kick_cpu(int nr)
@@ -485,13 +458,13 @@ static void __init smp_space_timers(unsigned int max_cpus)
 }
 
 #ifdef CONFIG_PPC_PSERIES
-void vpa_init(int cpu)
+static void vpa_init(int cpu)
 {
-	unsigned long flags;
+	unsigned long flags, pcpu = get_hard_smp_processor_id(cpu);
 
 	/* Register the Virtual Processor Area (VPA) */
 	flags = 1UL << (63 - 18);
-	register_vpa(flags, cpu, __pa((unsigned long)&(paca[cpu].lppaca)));
+	register_vpa(flags, pcpu, __pa((unsigned long)&(paca[cpu].lppaca)));
 }
 
 static inline void smp_xics_do_message(int cpu, int msg)
@@ -576,26 +549,47 @@ static struct smp_ops_t pSeries_xics_smp_ops = {
 /* This is called very early */
 void __init smp_init_pSeries(void)
 {
+	int ret, i;
+
+	DBG(" -> smp_init_pSeries()\n");
 
 	if (naca->interrupt_controller == IC_OPEN_PIC)
 		smp_ops = &pSeries_openpic_smp_ops;
 	else
 		smp_ops = &pSeries_xics_smp_ops;
 
+	/* Start secondary threads on SMT systems; primary threads
+	 * are already in the running state.
+	 */
+	for_each_present_cpu(i) {
+		if (query_cpu_stopped(get_hard_smp_processor_id(i)) == 0) {
+			printk("%16.16x : starting thread\n", i);
+			DBG("%16.16x : starting thread\n", i);
+			rtas_call(rtas_token("start-cpu"), 3, 1, &ret,
+				  get_hard_smp_processor_id(i),
+				  __pa((u32)*((unsigned long *)
+					      pseries_secondary_smp_init)),
+				  i);
+		}
+	}
+
+	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
+		vpa_init(boot_cpuid);
+
 	/* Non-lpar has additional take/give timebase */
 	if (systemcfg->platform == PLATFORM_PSERIES) {
 		smp_ops->give_timebase = pSeries_give_timebase;
 		smp_ops->take_timebase = pSeries_take_timebase;
 	}
+
+
+	DBG(" <- smp_init_pSeries()\n");
 }
-#endif
+#endif /* CONFIG_PPC_PSERIES */
 
 void smp_local_timer_interrupt(struct pt_regs * regs)
 {
-	if (!--(get_paca()->prof_counter)) {
-		update_process_times(user_mode(regs));
-		(get_paca()->prof_counter)=get_paca()->prof_multiplier;
-	}
+	update_process_times(user_mode(regs));
 }
 
 void smp_message_recv(int msg, struct pt_regs *regs)
@@ -751,6 +745,8 @@ out:
 	return ret;
 }
 
+EXPORT_SYMBOL(smp_call_function);
+
 void smp_call_function_interrupt(void)
 {
 	void (*func) (void *info);
@@ -794,26 +790,17 @@ DECLARE_PER_CPU(unsigned int, pvr);
 
 static void __devinit smp_store_cpu_info(int id)
 {
-	per_cpu(pvr, id) = _get_PVR();
+	per_cpu(pvr, id) = mfspr(SPRN_PVR);
 }
 
 static void __init smp_create_idle(unsigned int cpu)
 {
-	struct pt_regs regs;
 	struct task_struct *p;
 
 	/* create a process for the processor */
-	/* only regs.msr is actually used, and 0 is OK for it */
-	memset(&regs, 0, sizeof(struct pt_regs));
-	p = copy_process(CLONE_VM | CLONE_IDLETASK,
-			 0, &regs, 0, NULL, NULL);
+	p = fork_idle(cpu);
 	if (IS_ERR(p))
 		panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
-
-	wake_up_forked_process(p);
-	init_idle(p, cpu);
-	unhash_process(p);
-
 	paca[cpu].__current = p;
 	current_set[cpu] = p->thread_info;
 }
@@ -831,8 +818,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 	/* Fixup boot cpu */
 	smp_store_cpu_info(boot_cpuid);
 	cpu_callin_map[boot_cpuid] = 1;
-	paca[boot_cpuid].prof_counter = 1;
-	paca[boot_cpuid].prof_multiplier = 1;
 
 #ifndef CONFIG_PPC_ISERIES
 	paca[boot_cpuid].next_jiffy_update_tb = tb_last_stamp = get_tb();
@@ -843,8 +828,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 	 * number of msecs off until someone does a settimeofday()
 	 */
 	do_gtod.tb_orig_stamp = tb_last_stamp;
-
-	look_for_more_cpus();
+	systemcfg->tb_orig_stamp = tb_last_stamp;
 #endif
 
 	max_cpus = smp_ops->probe();
@@ -863,7 +847,6 @@ void __devinit smp_prepare_boot_cpu(void)
 {
 	BUG_ON(smp_processor_id() != boot_cpuid);
 
-	/* cpu_possible is set up in prom.c */
 	cpu_set(boot_cpuid, cpu_online_map);
 
 	paca[boot_cpuid].__current = current;
@@ -875,11 +858,9 @@ int __devinit __cpu_up(unsigned int cpu)
 	int c;
 
 	/* At boot, don't bother with non-present cpus -JSCHOPP */
-	if (system_state == SYSTEM_BOOTING && !cpu_present_at_boot(cpu))
+	if (system_state < SYSTEM_RUNNING && !cpu_present(cpu))
 		return -ENOENT;
 
-	paca[cpu].prof_counter = 1;
-	paca[cpu].prof_multiplier = 1;
 	paca[cpu].default_decr = tb_ticks_per_jiffy / decr_overclock;
 
 	if (!(cur_cpu_spec->cpu_features & CPU_FTR_SLB)) {
@@ -909,7 +890,7 @@ int __devinit __cpu_up(unsigned int cpu)
 	 * use this value that I found through experimentation.
 	 * -- Cort
 	 */
-	if (system_state == SYSTEM_BOOTING)
+	if (system_state < SYSTEM_RUNNING)
 		for (c = 5000; c && !cpu_callin_map[cpu]; c--)
 			udelay(100);
 #ifdef CONFIG_HOTPLUG_CPU
@@ -1004,219 +985,12 @@ void __init smp_cpus_done(unsigned int max_cpus)
 	smp_threads_ready = 1;
 
 	set_cpus_allowed(current, old_mask);
-}
-
-#ifdef CONFIG_SCHED_SMT
-#ifdef CONFIG_NUMA
-static struct sched_group sched_group_cpus[NR_CPUS];
-static struct sched_group sched_group_phys[NR_CPUS];
-static struct sched_group sched_group_nodes[MAX_NUMNODES];
-static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
-static DEFINE_PER_CPU(struct sched_domain, phys_domains);
-static DEFINE_PER_CPU(struct sched_domain, node_domains);
-__init void arch_init_sched_domains(void)
-{
-	int i;
-	struct sched_group *first = NULL, *last = NULL;
-
-	/* Set up domains */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		struct sched_domain *phys_domain = &per_cpu(phys_domains, i);
-		struct sched_domain *node_domain = &per_cpu(node_domains, i);
-		int node = cpu_to_node(i);
-		cpumask_t nodemask = node_to_cpumask(node);
-		cpumask_t my_cpumask = cpumask_of_cpu(i);
-		cpumask_t sibling_cpumask = cpumask_of_cpu(i ^ 0x1);
-
-		*cpu_domain = SD_SIBLING_INIT;
-		if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
-			cpus_or(cpu_domain->span, my_cpumask, sibling_cpumask);
-		else
-			cpu_domain->span = my_cpumask;
-		cpu_domain->parent = phys_domain;
-		cpu_domain->groups = &sched_group_cpus[i];
-
-		*phys_domain = SD_CPU_INIT;
-		phys_domain->span = nodemask;
-		phys_domain->parent = node_domain;
-		phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)];
-
-		*node_domain = SD_NODE_INIT;
-		node_domain->span = cpu_possible_map;
-		node_domain->groups = &sched_group_nodes[node];
-	}
-
-	/* Set up CPU (sibling) groups */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		int j;
-		first = last = NULL;
 
-		if (i != first_cpu(cpu_domain->span))
-			continue;
-
-		for_each_cpu_mask(j, cpu_domain->span) {
-			struct sched_group *cpu = &sched_group_cpus[j];
-
-			cpus_clear(cpu->cpumask);
-			cpu_set(j, cpu->cpumask);
-			cpu->cpu_power = SCHED_LOAD_SCALE;
-
-			if (!first)
-				first = cpu;
-			if (last)
-				last->next = cpu;
-			last = cpu;
-		}
-		last->next = first;
-	}
-
-	for (i = 0; i < MAX_NUMNODES; i++) {
-		int j;
-		cpumask_t nodemask;
-		struct sched_group *node = &sched_group_nodes[i];
-		cpumask_t node_cpumask = node_to_cpumask(i);
-		cpus_and(nodemask, node_cpumask, cpu_possible_map);
-
-		if (cpus_empty(nodemask))
-			continue;
-
-		first = last = NULL;
-		/* Set up physical groups */
-		for_each_cpu_mask(j, nodemask) {
-			struct sched_domain *cpu_domain = &per_cpu(cpu_domains, j);
-			struct sched_group *cpu = &sched_group_phys[j];
-
-			if (j != first_cpu(cpu_domain->span))
-				continue;
-
-			cpu->cpumask = cpu_domain->span;
-			/*
-			 * Make each extra sibling increase power by 10% of
-			 * the basic CPU. This is very arbitrary.
-			 */
-			cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10;
-			node->cpu_power += cpu->cpu_power;
-
-			if (!first)
-				first = cpu;
-			if (last)
-				last->next = cpu;
-			last = cpu;
-		}
-		last->next = first;
-	}
-
-	/* Set up nodes */
-	first = last = NULL;
-	for (i = 0; i < MAX_NUMNODES; i++) {
-		struct sched_group *cpu = &sched_group_nodes[i];
-		cpumask_t nodemask;
-		cpumask_t node_cpumask = node_to_cpumask(i);
-		cpus_and(nodemask, node_cpumask, cpu_possible_map);
-
-		if (cpus_empty(nodemask))
-			continue;
-
-		cpu->cpumask = nodemask;
-		/* ->cpu_power already setup */
-
-		if (!first)
-			first = cpu;
-		if (last)
-			last->next = cpu;
-		last = cpu;
-	}
-	last->next = first;
-
-	mb();
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		cpu_attach_domain(cpu_domain, i);
-	}
-}
-#else /* !CONFIG_NUMA */
-static struct sched_group sched_group_cpus[NR_CPUS];
-static struct sched_group sched_group_phys[NR_CPUS];
-static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
-static DEFINE_PER_CPU(struct sched_domain, phys_domains);
-__init void arch_init_sched_domains(void)
-{
-	int i;
-	struct sched_group *first = NULL, *last = NULL;
-
-	/* Set up domains */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		struct sched_domain *phys_domain = &per_cpu(phys_domains, i);
-		cpumask_t my_cpumask = cpumask_of_cpu(i);
-		cpumask_t sibling_cpumask = cpumask_of_cpu(i ^ 0x1);
-
-		*cpu_domain = SD_SIBLING_INIT;
-		if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
-			cpus_or(cpu_domain->span, my_cpumask, sibling_cpumask);
-		else
-			cpu_domain->span = my_cpumask;
-		cpu_domain->parent = phys_domain;
-		cpu_domain->groups = &sched_group_cpus[i];
-
-		*phys_domain = SD_CPU_INIT;
-		phys_domain->span = cpu_possible_map;
-		phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)];
-	}
-
-	/* Set up CPU (sibling) groups */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		int j;
-		first = last = NULL;
-
-		if (i != first_cpu(cpu_domain->span))
-			continue;
-
-		for_each_cpu_mask(j, cpu_domain->span) {
-			struct sched_group *cpu = &sched_group_cpus[j];
-
-			cpus_clear(cpu->cpumask);
-			cpu_set(j, cpu->cpumask);
-			cpu->cpu_power = SCHED_LOAD_SCALE;
-
-			if (!first)
-				first = cpu;
-			if (last)
-				last->next = cpu;
-			last = cpu;
-		}
-		last->next = first;
-	}
-
-	first = last = NULL;
-	/* Set up physical groups */
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		struct sched_group *cpu = &sched_group_phys[i];
-
-		if (i != first_cpu(cpu_domain->span))
-			continue;
-
-		cpu->cpumask = cpu_domain->span;
-		/* See SMT+NUMA setup for comment */
-		cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10;
-
-		if (!first)
-			first = cpu;
-		if (last)
-			last->next = cpu;
-		last = cpu;
-	}
-	last->next = first;
-
-	mb();
-	for_each_cpu(i) {
-		struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-		cpu_attach_domain(cpu_domain, i);
-	}
+	/*
+	 * We know at boot the maximum number of cpus we can add to
+	 * a partition and set cpu_possible_map accordingly. cpu_present_map
+	 * needs to match for the hotplug code to allow us to hot add
+	 * any offline cpus.
+	 */
+	cpu_present_map = cpu_possible_map;
 }
-#endif /* CONFIG_NUMA */
-#endif /* CONFIG_SCHED_SMT */
diff --git a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
index 376dc4a06..2ac5c7d01 100644
--- a/arch/ppc64/kernel/sys_ppc32.c
+++ b/arch/ppc64/kernel/sys_ppc32.c
@@ -73,7 +73,6 @@
 #include <asm/semaphore.h>
 #include <asm/ppcdebug.h>
 #include <asm/time.h>
-#include <asm/ppc32.h>
 #include <asm/mmu_context.h>
 
 #include "pci.h"
@@ -635,8 +634,24 @@ out:
 void start_thread32(struct pt_regs* regs, unsigned long nip, unsigned long sp)
 {
 	set_fs(USER_DS);
-	memset(regs->gpr, 0, sizeof(regs->gpr));
-	memset(&regs->ctr, 0, 4 * sizeof(regs->ctr));
+
+	/*
+	 * If we exec out of a kernel thread then thread.regs will not be
+	 * set. Do it now.
+	 */
+	if (!current->thread.regs) {
+		unsigned long childregs = (unsigned long)current->thread_info +
+						THREAD_SIZE;
+		childregs -= sizeof(struct pt_regs);
+		current->thread.regs = (struct pt_regs *)childregs;
+	}
+
+	/*
+	 * ELF_PLAT_INIT already clears all registers but it also sets r2.
+	 * So just clear r2 here.
+	 */
+	regs->gpr[2] = 0;
+
 	regs->nip = nip;
 	regs->gpr[1] = sp;
 	regs->msr = MSR_USER32;
@@ -701,7 +716,7 @@ asmlinkage int sys32_pciconfig_read(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf
 				  (unsigned long) dfn,
 				  (unsigned long) off,
 				  (unsigned long) len,
-				  (unsigned char __user *)AA(ubuf));
+				  compat_ptr(ubuf));
 }
 
 asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
@@ -710,7 +725,7 @@ asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubu
 				   (unsigned long) dfn,
 				   (unsigned long) off,
 				   (unsigned long) len,
-				   (unsigned char __user *)AA(ubuf));
+				   compat_ptr(ubuf));
 }
 
 #define IOBASE_BRIDGE_NUMBER	0
@@ -1096,7 +1111,7 @@ struct __sysctl_args32 {
 	u32 __unused[4];
 };
 
-extern asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
+asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
 {
 	struct __sysctl_args32 tmp;
 	int error;
@@ -1115,19 +1130,20 @@ extern asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
 		   glibc's __sysctl uses rw memory for the structure
 		   anyway.  */
 		oldlenp = (size_t __user *)addr;
-		if (get_user(oldlen, (u32 __user *)A(tmp.oldlenp)) ||
+		if (get_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp)) ||
 		    put_user(oldlen, oldlenp))
 			return -EFAULT;
 	}
 
 	lock_kernel();
-	error = do_sysctl((int __user *)A(tmp.name), tmp.nlen, (void __user *)A(tmp.oldval),
-			  oldlenp, (void __user *)A(tmp.newval), tmp.newlen);
+	error = do_sysctl(compat_ptr(tmp.name), tmp.nlen,
+			  compat_ptr(tmp.oldval), oldlenp,
+			  compat_ptr(tmp.newval), tmp.newlen);
 	unlock_kernel();
 	if (oldlenp) {
 		if (!error) {
 			if (get_user(oldlen, oldlenp) ||
-			    put_user(oldlen, (u32 __user *)A(tmp.oldlenp)))
+			    put_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp)))
 				error = -EFAULT;
 		}
 		copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
diff --git a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c
index 41b34932f..cfc3c0b7b 100644
--- a/arch/ppc64/kernel/sysfs.c
+++ b/arch/ppc64/kernel/sysfs.c
@@ -5,6 +5,7 @@
 #include <linux/percpu.h>
 #include <linux/init.h>
 #include <linux/sched.h>
+#include <linux/module.h>
 #include <asm/current.h>
 #include <asm/processor.h>
 #include <asm/cputable.h>
@@ -96,6 +97,14 @@ __setup("smt-snooze-delay=", setup_smt_snooze_delay);
 
 /* PMC stuff */
 
+#ifdef CONFIG_PPC_ISERIES
+void ppc64_enable_pmcs(void)
+{
+	/* XXX Implement for iseries */
+}
+#endif
+
+#ifdef CONFIG_PPC_MULTIPLATFORM
 /*
  * Enabling PMCs will slow partition context switch times so we only do
  * it the first time we write to the PMCs.
@@ -103,18 +112,14 @@ __setup("smt-snooze-delay=", setup_smt_snooze_delay);
 
 static DEFINE_PER_CPU(char, pmcs_enabled);
 
-#ifdef CONFIG_PPC_ISERIES
-void ppc64_enable_pmcs(void)
-{
-	/* XXX Implement for iseries */
-}
-#else
 void ppc64_enable_pmcs(void)
 {
 	unsigned long hid0;
+#ifdef CONFIG_PPC_PSERIES
 	unsigned long set, reset;
 	int ret;
 	unsigned int ctrl;
+#endif /* CONFIG_PPC_PSERIES */
 
 	/* Only need to enable them once */
 	if (__get_cpu_var(pmcs_enabled))
@@ -123,37 +128,42 @@ void ppc64_enable_pmcs(void)
 	__get_cpu_var(pmcs_enabled) = 1;
 
 	switch (systemcfg->platform) {
-		case PLATFORM_PSERIES:
-			hid0 = mfspr(HID0);
-			hid0 |= 1UL << (63 - 20);
-
-			/* POWER4 requires the following sequence */
-			asm volatile(
-				"sync\n"
-				"mtspr	%1, %0\n"
-				"mfspr	%0, %1\n"
-				"mfspr	%0, %1\n"
-				"mfspr	%0, %1\n"
-				"mfspr	%0, %1\n"
-				"mfspr	%0, %1\n"
-				"mfspr	%0, %1\n"
-				"isync" : "=&r" (hid0) : "i" (HID0), "0" (hid0):
-				"memory");
-			break;
-
-		case PLATFORM_PSERIES_LPAR:
-			set = 1UL << 63;
-			reset = 0;
-			ret = plpar_hcall_norets(H_PERFMON, set, reset);
-			if (ret)
-				printk(KERN_ERR "H_PERFMON call returned %d",
-				       ret);
-			break;
-
-		default:
-			break;
+	case PLATFORM_PSERIES:
+	case PLATFORM_POWERMAC:
+		hid0 = mfspr(HID0);
+		hid0 |= 1UL << (63 - 20);
+
+		/* POWER4 requires the following sequence */
+		asm volatile(
+			     "sync\n"
+			     "mtspr	%1, %0\n"
+			     "mfspr	%0, %1\n"
+			     "mfspr	%0, %1\n"
+			     "mfspr	%0, %1\n"
+			     "mfspr	%0, %1\n"
+			     "mfspr	%0, %1\n"
+			     "mfspr	%0, %1\n"
+			     "isync" : "=&r" (hid0) : "i" (HID0), "0" (hid0):
+			     "memory");
+		break;
+
+#ifdef CONFIG_PPC_PSERIES
+	case PLATFORM_PSERIES_LPAR:
+		set = 1UL << 63;
+		reset = 0;
+		ret = plpar_hcall_norets(H_PERFMON, set, reset);
+		if (ret)
+			printk(KERN_ERR "H_PERFMON call on cpu %u "
+			       "returned %d\n",
+			       smp_processor_id(), ret);
+		break;
+#endif /* CONFIG_PPC_PSERIES */
+
+	default:
+		break;
 	}
 
+#ifdef CONFIG_PPC_PSERIES
 	/* instruct hypervisor to maintain PMCs */
 	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
 		char *ptr = (char *)&paca[smp_processor_id()].lppaca;
@@ -169,8 +179,11 @@ void ppc64_enable_pmcs(void)
 		ctrl |= RUNLATCH;
 		mtspr(CTRLT, ctrl);
 	}
+#endif /* CONFIG_PPC_PSERIES */
 }
-#endif
+#endif /* CONFIG_PPC_MULTIPLATFORM */
+
+EXPORT_SYMBOL(ppc64_enable_pmcs);
 
 /* XXX convert to rusty's on_one_cpu */
 static unsigned long run_on_cpu(unsigned long cpu,
diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
index 64844df4a..ef44a3ec4 100644
--- a/arch/ppc64/kernel/time.c
+++ b/arch/ppc64/kernel/time.c
@@ -48,6 +48,7 @@
 #include <linux/time.h>
 #include <linux/init.h>
 #include <linux/profile.h>
+#include <linux/cpu.h>
 
 #include <asm/segment.h>
 #include <asm/io.h>
@@ -83,7 +84,7 @@ static unsigned long first_settimeofday = 1;
 #define XSEC_PER_SEC (1024*1024)
 
 unsigned long tb_ticks_per_jiffy;
-unsigned long tb_ticks_per_usec;
+unsigned long tb_ticks_per_usec = 100; /* sane default */
 unsigned long tb_ticks_per_sec;
 unsigned long next_xtime_sync_tb;
 unsigned long xtime_sync_interval;
@@ -101,50 +102,12 @@ extern unsigned long wall_jiffies;
 extern unsigned long lpevent_count;
 extern int smp_tb_synchronized;
 
+extern struct timezone sys_tz;
+
 void ppc_adjtimex(void);
 
 static unsigned adjusting_time = 0;
 
-/*
- * The profiling function is SMP safe. (nothing can mess
- * around with "current", and the profiling counters are
- * updated with atomic operations). This is especially
- * useful with a profiling multiplier != 1
- */
-static inline void ppc64_do_profile(struct pt_regs *regs)
-{
-	unsigned long nip;
-	extern unsigned long prof_cpu_mask;
-
-	profile_hook(regs);
-
-	if (user_mode(regs))
-		return;
-
-	if (!prof_buffer)
-		return;
-
-	nip = instruction_pointer(regs);
-
-	/*
-	 * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
-	 * (default is all CPUs.)
-	 */
-	if (!((1<<smp_processor_id()) & prof_cpu_mask))
-		return;
-
-	nip -= (unsigned long)_stext;
-	nip >>= prof_shift;
-	/*
-	 * Don't ignore out-of-bounds EIP values silently,
-	 * put them into the last histogram slot, so if
-	 * present, they will show up as a sharp peak.
-	 */
-	if (nip > prof_len-1)
-		nip = prof_len-1;
-	atomic_inc((atomic_t *)&prof_buffer[nip]);
-}
-
 static __inline__ void timer_check_rtc(void)
 {
         /*
@@ -195,6 +158,19 @@ static __inline__ void timer_sync_xtime( unsigned long cur_tb )
 	}
 }
 
+#ifdef CONFIG_SMP
+unsigned long profile_pc(struct pt_regs *regs)
+{
+	unsigned long pc = instruction_pointer(regs);
+
+	if (in_lock_functions(pc))
+		return regs->link;
+
+	return pc;
+}
+EXPORT_SYMBOL(profile_pc);
+#endif
+
 #ifdef CONFIG_PPC_ISERIES
 
 /* 
@@ -233,6 +209,8 @@ static void iSeries_tb_recal(void)
 				do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
 				tb_to_xs = divres.result_low;
 				do_gtod.varp->tb_to_xs = tb_to_xs;
+				systemcfg->tb_ticks_per_sec = tb_ticks_per_sec;
+				systemcfg->tb_to_xs = tb_to_xs;
 			}
 			else {
 				printk( "Titan recalibrate: FAILED (difference > 4 percent)\n"
@@ -273,7 +251,7 @@ int timer_interrupt(struct pt_regs * regs)
 	irq_enter();
 
 #ifndef CONFIG_PPC_ISERIES
-	ppc64_do_profile(regs);
+	profile_tick(CPU_PROFILING, regs);
 #endif
 
 	lpaca->lppaca.xIntDword.xFields.xDecrInt = 0;
@@ -281,8 +259,20 @@ int timer_interrupt(struct pt_regs * regs)
 	while (lpaca->next_jiffy_update_tb <= (cur_tb = get_tb())) {
 
 #ifdef CONFIG_SMP
-		smp_local_timer_interrupt(regs);
+		/*
+		 * We cannot disable the decrementer, so in the period
+		 * between this cpu's being marked offline in cpu_online_map
+		 * and calling stop-self, it is taking timer interrupts.
+		 * Avoid calling into the scheduler rebalancing code if this
+		 * is the case.
+		 */
+		if (!cpu_is_offline(cpu))
+			smp_local_timer_interrupt(regs);
 #endif
+		/*
+		 * No need to check whether cpu is offline here; boot_cpuid
+		 * should have been fixed up by now.
+		 */
 		if (cpu == boot_cpuid) {
 			write_seqlock(&xtime_lock);
 			tb_last_stamp = lpaca->next_jiffy_update_tb;
@@ -408,6 +398,7 @@ int do_settimeofday(struct timespec *tv)
 	new_xsec += new_sec * XSEC_PER_SEC;
 	if ( new_xsec > delta_xsec ) {
 		do_gtod.varp->stamp_xsec = new_xsec - delta_xsec;
+		systemcfg->stamp_xsec = new_xsec - delta_xsec;
 	}
 	else {
 		/* This is only for the case where the user is setting the time
@@ -416,8 +407,13 @@ int do_settimeofday(struct timespec *tv)
 		 * the time to Jan 5, 1970 */
 		do_gtod.varp->stamp_xsec = new_xsec;
 		do_gtod.tb_orig_stamp = tb_last_stamp;
+		systemcfg->stamp_xsec = new_xsec;
+		systemcfg->tb_orig_stamp = tb_last_stamp;
 	}
 
+	systemcfg->tz_minuteswest = sys_tz.tz_minuteswest;
+	systemcfg->tz_dsttime = sys_tz.tz_dsttime;
+
 	write_sequnlock_irqrestore(&xtime_lock, flags);
 	clock_was_set();
 	return 0;
@@ -520,6 +516,11 @@ void __init time_init(void)
 	do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
 	do_gtod.varp->tb_to_xs = tb_to_xs;
 	do_gtod.tb_to_us = tb_to_us;
+	systemcfg->tb_orig_stamp = tb_last_stamp;
+	systemcfg->tb_update_count = 0;
+	systemcfg->tb_ticks_per_sec = tb_ticks_per_sec;
+	systemcfg->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC;
+	systemcfg->tb_to_xs = tb_to_xs;
 
 	xtime_sync_interval = tb_ticks_per_sec - (tb_ticks_per_sec/8);
 	next_xtime_sync_tb = tb_last_stamp + xtime_sync_interval;
@@ -655,6 +656,22 @@ void ppc_adjtimex(void)
 	do_gtod.varp = temp_varp;
 	do_gtod.var_idx = temp_idx;
 
+	/*
+	 * tb_update_count is used to allow the problem state gettimeofday code
+	 * to assure itself that it sees a consistent view of the tb_to_xs and
+	 * stamp_xsec variables.  It reads the tb_update_count, then reads
+	 * tb_to_xs and stamp_xsec and then reads tb_update_count again.  If
+	 * the two values of tb_update_count match and are even then the
+	 * tb_to_xs and stamp_xsec values are consistent.  If not, then it
+	 * loops back and reads them again until this criteria is met.
+	 */
+	++(systemcfg->tb_update_count);
+	wmb();
+	systemcfg->tb_to_xs = new_tb_to_xs;
+	systemcfg->stamp_xsec = new_stamp_xsec;
+	wmb();
+	++(systemcfg->tb_update_count);
+
 	write_sequnlock_irqrestore( &xtime_lock, flags );
 
 }
diff --git a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c
index 5f70f7bc1..90700b414 100644
--- a/arch/ppc64/kernel/traps.c
+++ b/arch/ppc64/kernel/traps.c
@@ -134,14 +134,20 @@ int die(const char *str, struct pt_regs *regs, long err)
 }
 
 static void
-_exception(int signr, siginfo_t *info, struct pt_regs *regs)
+_exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
 {
+	siginfo_t info;
+
 	if (!user_mode(regs)) {
 		if (die("Exception in kernel mode", regs, signr))
 			return;
 	}
 
-	force_sig_info(signr, info, current);
+	memset(&info, 0, sizeof(info));
+	info.si_signo = signr;
+	info.si_code = code;
+	info.si_addr = (void __user *) addr;
+	force_sig_info(signr, &info, current);
 }
 
 #ifdef CONFIG_PPC_PSERIES
@@ -213,27 +219,21 @@ SystemResetException(struct pt_regs *regs)
  */
 static int recover_mce(struct pt_regs *regs, struct rtas_error_log err)
 {
-	siginfo_t info;
-
-	if (err.disposition == DISP_FULLY_RECOVERED) {
+	if (err.disposition == RTAS_DISP_FULLY_RECOVERED) {
 		/* Platform corrected itself */
 		return 1;
 	} else if ((regs->msr & MSR_RI) &&
 		   user_mode(regs) &&
-		   err.severity == SEVERITY_ERROR_SYNC &&
-		   err.disposition == DISP_NOT_RECOVERED &&
-		   err.target == TARGET_MEMORY &&
-		   err.type == TYPE_ECC_UNCORR &&
+		   err.severity == RTAS_SEVERITY_ERROR_SYNC &&
+		   err.disposition == RTAS_DISP_NOT_RECOVERED &&
+		   err.target == RTAS_TARGET_MEMORY &&
+		   err.type == RTAS_TYPE_ECC_UNCORR &&
 		   !(current->pid == 0 || current->pid == 1)) {
 		/* Kill off a user process with an ECC error */
-		info.si_signo = SIGBUS;
-		info.si_errno = 0;
-		/* XXX something better for ECC error? */
-		info.si_code = BUS_ADRERR;
-		info.si_addr = (void __user *)regs->nip;
 		printk(KERN_ERR "MCE: uncorrectable ecc error for pid %d\n",
 		       current->pid);
-		_exception(SIGBUS, &info, regs);
+		/* XXX something better for ECC error? */
+		_exception(SIGBUS, regs, BUS_ADRERR, regs->nip);
 		return 1;
 	}
 	return 0;
@@ -278,35 +278,46 @@ MachineCheckException(struct pt_regs *regs)
 void
 UnknownException(struct pt_regs *regs)
 {
-	siginfo_t info;
-
 	printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
 	       regs->nip, regs->msr, regs->trap);
 
-	info.si_signo = SIGTRAP;
-	info.si_errno = 0;
-	info.si_code = 0;
-	info.si_addr = NULL;
-	_exception(SIGTRAP, &info, regs);	
+	_exception(SIGTRAP, regs, 0, 0);
 }
 
 void
 InstructionBreakpointException(struct pt_regs *regs)
 {
-	siginfo_t info;
-
 	if (debugger_iabr_match(regs))
 		return;
-	info.si_signo = SIGTRAP;
-	info.si_errno = 0;
-	info.si_code = TRAP_BRKPT;
-	info.si_addr = (void __user *)regs->nip;
-	_exception(SIGTRAP, &info, regs);
+	_exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
+}
+
+void
+SingleStepException(struct pt_regs *regs)
+{
+	regs->msr &= ~MSR_SE;  /* Turn off 'trace' bit */
+
+	if (debugger_sstep(regs))
+		return;
+
+	_exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
+}
+
+/*
+ * After we have successfully emulated an instruction, we have to
+ * check if the instruction was being single-stepped, and if so,
+ * pretend we got a single-step exception.  This was pointed out
+ * by Kumar Gala.  -- paulus
+ */
+static inline void emulate_single_step(struct pt_regs *regs)
+{
+	if (regs->msr & MSR_SE)
+		SingleStepException(regs);
 }
 
 static void parse_fpe(struct pt_regs *regs)
 {
-	siginfo_t info;
+	int code = 0;
 	unsigned long fpscr;
 
 	flush_fp_to_thread(current);
@@ -315,31 +326,84 @@ static void parse_fpe(struct pt_regs *regs)
 
 	/* Invalid operation */
 	if ((fpscr & FPSCR_VE) && (fpscr & FPSCR_VX))
-		info.si_code = FPE_FLTINV;
+		code = FPE_FLTINV;
 
 	/* Overflow */
 	else if ((fpscr & FPSCR_OE) && (fpscr & FPSCR_OX))
-		info.si_code = FPE_FLTOVF;
+		code = FPE_FLTOVF;
 
 	/* Underflow */
 	else if ((fpscr & FPSCR_UE) && (fpscr & FPSCR_UX))
-		info.si_code = FPE_FLTUND;
+		code = FPE_FLTUND;
 
 	/* Divide by zero */
 	else if ((fpscr & FPSCR_ZE) && (fpscr & FPSCR_ZX))
-		info.si_code = FPE_FLTDIV;
+		code = FPE_FLTDIV;
 
 	/* Inexact result */
 	else if ((fpscr & FPSCR_XE) && (fpscr & FPSCR_XX))
-		info.si_code = FPE_FLTRES;
+		code = FPE_FLTRES;
+
+	_exception(SIGFPE, regs, code, regs->nip);
+}
+
+/*
+ * Illegal instruction emulation support.  Return non-zero if we can't
+ * emulate, or -EFAULT if the associated memory access caused an access
+ * fault.  Return zero on success.
+ */
+
+#define INST_DCBA		0x7c0005ec
+#define INST_DCBA_MASK		0x7c0007fe
+
+#define INST_MCRXR		0x7c000400
+#define INST_MCRXR_MASK		0x7c0007fe
+
+static int emulate_instruction(struct pt_regs *regs)
+{
+	unsigned int instword;
 
-	else
-		info.si_code = 0;
+	if (!user_mode(regs))
+		return -EINVAL;
 
-	info.si_signo = SIGFPE;
-	info.si_errno = 0;
-	info.si_addr = (void __user *)regs->nip;
-	_exception(SIGFPE, &info, regs);
+	CHECK_FULL_REGS(regs);
+
+	if (get_user(instword, (unsigned int __user *)(regs->nip)))
+		return -EFAULT;
+
+	/* Emulating the dcba insn is just a no-op.  */
+	if ((instword & INST_DCBA_MASK) == INST_DCBA) {
+		static int warned;
+
+		if (!warned) {
+			printk(KERN_WARNING
+			       "process %d (%s) uses obsolete 'dcba' insn\n",
+			       current->pid, current->comm);
+			warned = 1;
+		}
+		return 0;
+	}
+
+	/* Emulate the mcrxr insn.  */
+	if ((instword & INST_MCRXR_MASK) == INST_MCRXR) {
+		static int warned;
+		unsigned int shift;
+
+		if (!warned) {
+			printk(KERN_WARNING
+			       "process %d (%s) uses obsolete 'mcrxr' insn\n",
+			       current->pid, current->comm);
+			warned = 1;
+		}
+
+		shift = (instword >> 21) & 0x1c;
+		regs->ccr &= ~(0xf0000000 >> shift);
+		regs->ccr |= (regs->xer & 0xf0000000) >> shift;
+		regs->xer &= ~0xf0000000;
+		return 0;
+	}
+
+	return -EINVAL;
 }
 
 /*
@@ -395,20 +459,14 @@ check_bug_trap(struct pt_regs *regs)
 void
 ProgramCheckException(struct pt_regs *regs)
 {
-	siginfo_t info;
-
 	if (regs->msr & 0x100000) {
 		/* IEEE FP exception */
-
 		parse_fpe(regs);
+
 	} else if (regs->msr & 0x40000) {
 		/* Privileged instruction */
+		_exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
 
-		info.si_signo = SIGILL;
-		info.si_errno = 0;
-		info.si_code = ILL_PRVOPC;
-		info.si_addr = (void __user *)regs->nip;
-		_exception(SIGILL, &info, regs);
 	} else if (regs->msr & 0x20000) {
 		/* trap exception */
 
@@ -419,19 +477,24 @@ ProgramCheckException(struct pt_regs *regs)
 			regs->nip += 4;
 			return;
 		}
-		info.si_signo = SIGTRAP;
-		info.si_errno = 0;
-		info.si_code = TRAP_BRKPT;
-		info.si_addr = (void __user *)regs->nip;
-		_exception(SIGTRAP, &info, regs);
+		_exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
+
 	} else {
-		/* Illegal instruction */
+		/* Illegal instruction; try to emulate it.  */
+		switch (emulate_instruction(regs)) {
+		case 0:
+			regs->nip += 4;
+			emulate_single_step(regs);
+			break;
 
-		info.si_signo = SIGILL;
-		info.si_errno = 0;
-		info.si_code = ILL_ILLTRP;
-		info.si_addr = (void __user *)regs->nip;
-		_exception(SIGILL, &info, regs);
+		case -EFAULT:
+			_exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip);
+			break;
+
+		default:
+			_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
+			break;
+		}
 	}
 }
 
@@ -448,13 +511,7 @@ void AltivecUnavailableException(struct pt_regs *regs)
 	if (user_mode(regs)) {
 		/* A user program has executed an altivec instruction,
 		   but this kernel doesn't support altivec. */
-		siginfo_t info;
-
-		memset(&info, 0, sizeof(info));
-		info.si_signo = SIGILL;
-		info.si_code = ILL_ILLOPC;
-		info.si_addr = (void *) regs->nip;
-		_exception(SIGILL, &info, regs);
+		_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
 		return;
 	}
 #endif
@@ -463,41 +520,22 @@ void AltivecUnavailableException(struct pt_regs *regs)
 	die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT);
 }
 
-void
-SingleStepException(struct pt_regs *regs)
-{
-	siginfo_t info;
-
-	regs->msr &= ~MSR_SE;  /* Turn off 'trace' bit */
-
-	if (debugger_sstep(regs))
-		return;
-
-	info.si_signo = SIGTRAP;
-	info.si_errno = 0;
-	info.si_code = TRAP_TRACE;
-	info.si_addr = (void __user *)regs->nip;
-	_exception(SIGTRAP, &info, regs);	
-}
-
-/*
- * After we have successfully emulated an instruction, we have to
- * check if the instruction was being single-stepped, and if so,
- * pretend we got a single-step exception.  This was pointed out
- * by Kumar Gala.  -- paulus
- */
-static inline void emulate_single_step(struct pt_regs *regs)
-{
-	if (regs->msr & MSR_SE)
-		SingleStepException(regs);
-}
+/* Ensure exceptions are disabled */
+#define MMCR0_PMXE      (1UL << (31 - 5))
+#define MMCR0_PMAO      (1UL << (31 - 24))
 
 static void dummy_perf(struct pt_regs *regs)
 {
+	unsigned int mmcr0 = mfspr(SPRN_MMCR0);
+
+	mmcr0 &= ~(MMCR0_PMXE|MMCR0_PMAO);
+	mtspr(SPRN_MMCR0, mmcr0);
 }
 
 void (*perf_irq)(struct pt_regs *) = dummy_perf;
 
+EXPORT_SYMBOL(perf_irq);
+
 void
 PerformanceMonitorException(struct pt_regs *regs)
 {
@@ -508,7 +546,6 @@ void
 AlignmentException(struct pt_regs *regs)
 {
 	int fixed;
-	siginfo_t info;
 
 	fixed = fix_alignment(regs);
 
@@ -521,11 +558,7 @@ AlignmentException(struct pt_regs *regs)
 	/* Operand address was bad */	
 	if (fixed == -EFAULT) {
 		if (user_mode(regs)) {
-			info.si_signo = SIGSEGV;
-			info.si_errno = 0;
-			info.si_code = SEGV_MAPERR;
-			info.si_addr = (void __user *)regs->dar;
-			force_sig_info(SIGSEGV, &info, current);
+			_exception(SIGSEGV, regs, SEGV_MAPERR, regs->dar);
 		} else {
 			/* Search exception table */
 			bad_page_fault(regs, regs->dar, SIGSEGV);
@@ -534,11 +567,7 @@ AlignmentException(struct pt_regs *regs)
 		return;
 	}
 
-	info.si_signo = SIGBUS;
-	info.si_errno = 0;
-	info.si_code = BUS_ADRALN;
-	info.si_addr = (void __user *)regs->nip;
-	_exception(SIGBUS, &info, regs);	
+	_exception(SIGBUS, regs, BUS_ADRALN, regs->nip);
 }
 
 #ifdef CONFIG_ALTIVEC
diff --git a/arch/ppc64/kernel/udbg.c b/arch/ppc64/kernel/udbg.c
index da2179154..2f0470dbd 100644
--- a/arch/ppc64/kernel/udbg.c
+++ b/arch/ppc64/kernel/udbg.c
@@ -84,23 +84,38 @@ static unsigned char scc_inittab[] = {
 
 void udbg_init_scc(struct device_node *np)
 {
+	u32 *reg;
 	unsigned long addr;
 	int i, x;
 
 	if (np == NULL)
 		np = of_find_node_by_name(NULL, "escc");
-	if (np == NULL)
+	if (np == NULL || np->parent == NULL)
+		return;
+
+	udbg_printf("found SCC...\n");
+	/* Get address within mac-io ASIC */ 
+	reg = (u32 *)get_property(np, "reg", NULL);
+	if (reg == NULL)
+		return;
+	addr = reg[0];
+	udbg_printf("local addr: %lx\n", addr);
+	/* Get address of mac-io PCI itself */
+	reg = (u32 *)get_property(np->parent, "assigned-addresses", NULL);
+	if (reg == NULL)
 		return;
-	
-	/* Lock-enable the SCC channel */
-	pmac_call_feature(PMAC_FTR_SCC_ENABLE, np, PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
+	addr += reg[2];
+	udbg_printf("final addr: %lx\n", addr);
 
 	/* Setup for 57600 8N1 */
-	addr = np->addrs[0].address + 0x20;
+	addr += 0x20;
 	sccc = (volatile u8 *) ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
 	sccc += addr & ~PAGE_MASK;
 	sccd = sccc + 0x10;
 
+	udbg_printf("ioremap result sccc: %p\n", sccc);
+	mb();
+
 	for (i = 20000; i != 0; --i)
 		x = *sccc; eieio();
 	*sccc = 9; eieio();		/* reset A or B side */
@@ -119,6 +134,30 @@ void udbg_init_scc(struct device_node *np)
 
 #endif /* CONFIG_PPC_PMAC */
 
+#if CONFIG_PPC_PMAC
+extern u8 real_readb(volatile u8 *addr);
+extern void real_writeb(u8 data, volatile u8 *addr);
+
+static void udbg_real_putc(unsigned char c)
+{
+	while ((real_readb(sccc) & SCC_TXRDY) == 0)
+		;
+	real_writeb(c, sccd);
+	if (c == '\n')
+		udbg_real_putc('\r');
+}
+
+void udbg_init_pmac_realmode(void)
+{
+	sccc = (volatile u8 *)0x80013020ul;
+	sccd = (volatile u8 *)0x80013030ul;
+
+	ppc_md.udbg_putc = udbg_real_putc;
+	ppc_md.udbg_getc = NULL;
+	ppc_md.udbg_getc_poll = NULL;
+}
+#endif /* CONFIG_PPC_PMAC */
+
 void udbg_putc(unsigned char c)
 {
 	if (udbg_comport) {
@@ -191,9 +230,12 @@ void udbg_puts(const char *s)
 			while ((c = *s++) != '\0')
 				ppc_md.udbg_putc(c);
 		}
-	} else {
+	}
+#if 0
+	else {
 		printk("%s", s);
 	}
+#endif
 }
 
 int udbg_write(const char *s, int n)
@@ -218,7 +260,7 @@ int udbg_read(char *buf, int buflen)
 	char c, *p = buf;
 	int i;
 
-	if (!ppc_md.udbg_putc)
+	if (!ppc_md.udbg_getc)
 		return 0;
 
 	for (i = 0; i < buflen; ++i) {
diff --git a/arch/ppc64/kernel/vector.S b/arch/ppc64/kernel/vector.S
index 940cd7287..b79d33e40 100644
--- a/arch/ppc64/kernel/vector.S
+++ b/arch/ppc64/kernel/vector.S
@@ -89,7 +89,7 @@ _GLOBAL(vmaddfp)
 1:	lfsx	fr0,r4,r7
 	lfsx	fr1,r5,r7
 	lfsx	fr2,r6,r7
-	fmadds	fr0,fr0,fr1,fr2
+	fmadds	fr0,fr0,fr2,fr1
 	stfsx	fr0,r3,r7
 	addi	r7,r7,4
 	bdnz	1b
@@ -109,7 +109,7 @@ _GLOBAL(vnmsubfp)
 1:	lfsx	fr0,r4,r7
 	lfsx	fr1,r5,r7
 	lfsx	fr2,r6,r7
-	fnmsubs	fr0,fr0,fr1,fr2
+	fnmsubs	fr0,fr0,fr2,fr1
 	stfsx	fr0,r3,r7
 	addi	r7,r7,4
 	bdnz	1b
diff --git a/arch/ppc64/kernel/vio.c b/arch/ppc64/kernel/vio.c
index a5fd6e772..48c4b0a0a 100644
--- a/arch/ppc64/kernel/vio.c
+++ b/arch/ppc64/kernel/vio.c
@@ -225,6 +225,10 @@ static void probe_bus_iseries(void)
 	struct vio_dev *viodev;
 	int i;
 
+	/* there is only one of each of these */
+	vio_register_device_iseries("viocons", 0);
+	vio_register_device_iseries("vscsi", 0);
+
 	vlan_map = HvLpConfig_getVirtualLanIndexMap();
 	for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
 		if ((vlan_map & (0x8000 >> i)) == 0)
diff --git a/arch/ppc64/kernel/viopath.c b/arch/ppc64/kernel/viopath.c
index 7b6c257f4..66a810239 100644
--- a/arch/ppc64/kernel/viopath.c
+++ b/arch/ppc64/kernel/viopath.c
@@ -38,8 +38,8 @@
 #include <linux/wait.h>
 #include <linux/seq_file.h>
 #include <linux/smp_lock.h>
+#include <linux/interrupt.h>
 
-#include <asm/hardirq.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/iSeries/LparData.h>
diff --git a/arch/ppc64/kernel/vmlinux.lds.S b/arch/ppc64/kernel/vmlinux.lds.S
index 1d9b61143..4103cc13f 100644
--- a/arch/ppc64/kernel/vmlinux.lds.S
+++ b/arch/ppc64/kernel/vmlinux.lds.S
@@ -14,6 +14,7 @@ SECTIONS
   .text : {
 	*(.text .text.*)
 	SCHED_TEXT
+	LOCK_TEXT
 	*(.fixup)
 	. = ALIGN(4096);
 	_etext = .;
@@ -61,12 +62,6 @@ SECTIONS
 	__setup_end = .;
 	}
 
-  __param : {
-	__start___param = .;
-	*(__param)
-	__stop___param = .;
-	}
-
   .initcall.init : {
 	__initcall_start = .;
 	*(.initcall1.init)
@@ -122,10 +117,13 @@ SECTIONS
 
   .data : {
 	*(.data .data.rel* .toc1)
-	*(.opd)
 	*(.branch_lt)
 	}
 
+  .opd : {
+	*(.opd)
+	}
+
   .got : {
 	__toc_start = .;
 	*(.got)
diff --git a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c
index c9f950c2c..ae15d2215 100644
--- a/arch/ppc64/kernel/xics.c
+++ b/arch/ppc64/kernel/xics.c
@@ -536,7 +536,7 @@ nextnode:
 #ifdef CONFIG_SMP
 		for_each_cpu(i) {
 			/* FIXME: Do this dynamically! --RR */
-			if (!cpu_present_at_boot(i))
+			if (!cpu_present(i))
 				continue;
 			xics_per_cpu[i] = __ioremap((ulong)inodes[get_hard_smp_processor_id(i)].addr, 
 						    (ulong)inodes[get_hard_smp_processor_id(i)].size,
diff --git a/arch/ppc64/lib/checksum.S b/arch/ppc64/lib/checksum.S
index 4ac6a63ca..ef96c6c58 100644
--- a/arch/ppc64/lib/checksum.S
+++ b/arch/ppc64/lib/checksum.S
@@ -92,19 +92,19 @@ _GLOBAL(csum_partial)
         adde    r5,r5,r6
         bdnz    2b
         andi.	r4,r4,7         /* compute bytes left to sum after doublewords */
-3:	cmpi	0,r4,4		/* is at least a full word left? */
+3:	cmpwi	0,r4,4		/* is at least a full word left? */
 	blt	4f
 	lwz	r6,8(r3)	/* sum this word */
 	addi	r3,r3,4
 	subi	r4,r4,4
 	adde	r5,r5,r6
-4:      cmpi    0,r4,2		/* is at least a halfword left? */
+4:	cmpwi	0,r4,2		/* is at least a halfword left? */
         blt+	5f
         lhz     r6,8(r3)        /* sum this halfword */
         addi    r3,r3,2
         subi    r4,r4,2
         adde    r5,r5,r6
-5:      cmpi    0,r4,1		/* is at least a byte left? */
+5:	cmpwi	0,r4,1		/* is at least a byte left? */
         bne+    6f
         lbz     r6,8(r3)        /* sum this byte */
         slwi    r6,r6,8         /* this byte is assumed to be the upper byte of a halfword */
@@ -150,7 +150,7 @@ _GLOBAL(csum_partial_copy_generic)
 	adde	r0,r0,r6
 	bdnz	82b
 	andi.	r5,r5,3
-3:	cmpi	0,r5,2
+3:	cmpwi	0,r5,2
 	blt+	4f
 83:	lhz	r6,4(r3)
 	addi	r3,r3,2
@@ -158,7 +158,7 @@ _GLOBAL(csum_partial_copy_generic)
 93:	sth	r6,4(r4)
 	addi	r4,r4,2
 	adde	r0,r0,r6
-4:	cmpi	0,r5,1
+4:	cmpwi	0,r5,1
 	bne+	5f
 84:	lbz	r6,4(r3)
 94:	stb	r6,4(r4)
@@ -198,7 +198,7 @@ src_error_3:
 	bdnz	97b
 	.globl src_error
 src_error:
-	cmpi	0,r7,0
+	cmpdi	0,r7,0
 	beq	1f
 	li	r6,-EFAULT
 	stw	r6,0(r7)
@@ -207,7 +207,7 @@ src_error:
 
 	.globl dst_error
 dst_error:
-	cmpi	0,r8,0
+	cmpdi	0,r8,0
 	beq	1f
 	li	r6,-EFAULT
 	stw	r6,0(r8)
diff --git a/arch/ppc64/lib/locks.c b/arch/ppc64/lib/locks.c
index 58e973cc8..72d642d7e 100644
--- a/arch/ppc64/lib/locks.c
+++ b/arch/ppc64/lib/locks.c
@@ -20,28 +20,9 @@
 #include <asm/hvcall.h>
 #include <asm/iSeries/HvCall.h>
 
-#ifndef CONFIG_SPINLINE
-
-/*
- * On a system with shared processors (that is, where a physical
- * processor is multiplexed between several virtual processors),
- * there is no point spinning on a lock if the holder of the lock
- * isn't currently scheduled on a physical processor.  Instead
- * we detect this situation and ask the hypervisor to give the
- * rest of our timeslice to the lock holder.
- *
- * So that we can tell which virtual processor is holding a lock,
- * we put 0x80000000 | smp_processor_id() in the lock when it is
- * held.  Conveniently, we have a word in the paca that holds this
- * value.
- */
-
 /* waiting for a spinlock... */
 #if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES)
 
-/* We only yield to the hypervisor if we are in shared processor mode */
-#define SHARED_PROCESSOR (get_paca()->lppaca.xSharedProc)
-
 void __spin_yield(spinlock_t *lock)
 {
 	unsigned int lock_value, holder_cpu, yield_count;
@@ -63,100 +44,16 @@ void __spin_yield(spinlock_t *lock)
 	HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
 		((u64)holder_cpu << 32) | yield_count);
 #else
-	plpar_hcall_norets(H_CONFER, holder_cpu, yield_count);
+	plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(holder_cpu),
+			   yield_count);
 #endif
 }
 
-#else /* SPLPAR || ISERIES */
-#define __spin_yield(x)	barrier()
-#define SHARED_PROCESSOR	0
-#endif
-
-/*
- * This returns the old value in the lock, so we succeeded
- * in getting the lock if the return value is 0.
- */
-static __inline__ unsigned long __spin_trylock(spinlock_t *lock)
-{
-	unsigned long tmp, tmp2;
-
-	__asm__ __volatile__(
-"	lwz		%1,%3(13)		# __spin_trylock\n\
-1:	lwarx		%0,0,%2\n\
-	cmpwi		0,%0,0\n\
-	bne-		2f\n\
-	stwcx.		%1,0,%2\n\
-	bne-		1b\n\
-	isync\n\
-2:"	: "=&r" (tmp), "=&r" (tmp2)
-	: "r" (&lock->lock), "i" (offsetof(struct paca_struct, lock_token))
-	: "cr0", "memory");
-
-	return tmp;
-}
-
-int _raw_spin_trylock(spinlock_t *lock)
-{
-	return __spin_trylock(lock) == 0;
-}
-
-EXPORT_SYMBOL(_raw_spin_trylock);
-
-void _raw_spin_lock(spinlock_t *lock)
-{
-	while (1) {
-		if (likely(__spin_trylock(lock) == 0))
-			break;
-		do {
-			HMT_low();
-			if (SHARED_PROCESSOR)
-				__spin_yield(lock);
-		} while (likely(lock->lock != 0));
-		HMT_medium();
-	}
-}
-
-EXPORT_SYMBOL(_raw_spin_lock);
-
-void _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags)
-{
-	unsigned long flags_dis;
-
-	while (1) {
-		if (likely(__spin_trylock(lock) == 0))
-			break;
-		local_save_flags(flags_dis);
-		local_irq_restore(flags);
-		do {
-			HMT_low();
-			if (SHARED_PROCESSOR)
-				__spin_yield(lock);
-		} while (likely(lock->lock != 0));
-		HMT_medium();
-		local_irq_restore(flags_dis);
-	}
-}
-
-EXPORT_SYMBOL(_raw_spin_lock_flags);
-
-void spin_unlock_wait(spinlock_t *lock)
-{
-	while (lock->lock) {
-		HMT_low();
-		if (SHARED_PROCESSOR)
-			__spin_yield(lock);
-	}
-	HMT_medium();
-}
-
-EXPORT_SYMBOL(spin_unlock_wait);
-
 /*
  * Waiting for a read lock or a write lock on a rwlock...
  * This turns out to be the same for read and write locks, since
  * we only know the holder if it is write-locked.
  */
-#if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES)
 void __rw_yield(rwlock_t *rw)
 {
 	int lock_value;
@@ -179,121 +76,20 @@ void __rw_yield(rwlock_t *rw)
 	HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
 		((u64)holder_cpu << 32) | yield_count);
 #else
-	plpar_hcall_norets(H_CONFER, holder_cpu, yield_count);
+	plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(holder_cpu),
+			   yield_count);
 #endif
 }
-
-#else /* SPLPAR || ISERIES */
-#define __rw_yield(x)	barrier()
 #endif
 
-/*
- * This returns the old value in the lock + 1,
- * so we got a read lock if the return value is > 0.
- */
-static __inline__ long __read_trylock(rwlock_t *rw)
-{
-	long tmp;
-
-	__asm__ __volatile__(
-"1:	lwarx		%0,0,%1		# read_trylock\n\
-	extsw		%0,%0\n\
-	addic.		%0,%0,1\n\
-	ble-		2f\n\
-	stwcx.		%0,0,%1\n\
-	bne-		1b\n\
-	isync\n\
-2:"	: "=&r" (tmp)
-	: "r" (&rw->lock)
-	: "cr0", "xer", "memory");
-
-	return tmp;
-}
-
-int _raw_read_trylock(rwlock_t *rw)
-{
-	return __read_trylock(rw) > 0;
-}
-
-EXPORT_SYMBOL(_raw_read_trylock);
-
-void _raw_read_lock(rwlock_t *rw)
-{
-	while (1) {
-		if (likely(__read_trylock(rw) > 0))
-			break;
-		do {
-			HMT_low();
-			if (SHARED_PROCESSOR)
-				__rw_yield(rw);
-		} while (likely(rw->lock < 0));
-		HMT_medium();
-	}
-}
-
-EXPORT_SYMBOL(_raw_read_lock);
-
-void _raw_read_unlock(rwlock_t *rw)
-{
-	long tmp;
-
-	__asm__ __volatile__(
-	"eieio				# read_unlock\n\
-1:	lwarx		%0,0,%1\n\
-	addic		%0,%0,-1\n\
-	stwcx.		%0,0,%1\n\
-	bne-		1b"
-	: "=&r"(tmp)
-	: "r"(&rw->lock)
-	: "cr0", "memory");
-}
-
-EXPORT_SYMBOL(_raw_read_unlock);
-
-/*
- * This returns the old value in the lock,
- * so we got the write lock if the return value is 0.
- */
-static __inline__ long __write_trylock(rwlock_t *rw)
-{
-	long tmp, tmp2;
-
-	__asm__ __volatile__(
-"	lwz		%1,%3(13)	# write_trylock\n\
-1:	lwarx		%0,0,%2\n\
-	cmpwi		0,%0,0\n\
-	bne-		2f\n\
-	stwcx.		%1,0,%2\n\
-	bne-		1b\n\
-	isync\n\
-2:"	: "=&r" (tmp), "=&r" (tmp2)
-	: "r" (&rw->lock), "i" (offsetof(struct paca_struct, lock_token))
-	: "cr0", "memory");
-
-	return tmp;
-}
-
-int _raw_write_trylock(rwlock_t *rw)
-{
-	return __write_trylock(rw) == 0;
-}
-
-EXPORT_SYMBOL(_raw_write_trylock);
-
-void _raw_write_lock(rwlock_t *rw)
+void spin_unlock_wait(spinlock_t *lock)
 {
-	while (1) {
-		if (likely(__write_trylock(rw) == 0))
-			break;
-		do {
-			HMT_low();
-			if (SHARED_PROCESSOR)
-				__rw_yield(rw);
-		} while (likely(rw->lock != 0));
-		HMT_medium();
+	while (lock->lock) {
+		HMT_low();
+		if (SHARED_PROCESSOR)
+			__spin_yield(lock);
 	}
+	HMT_medium();
 }
 
-EXPORT_SYMBOL(_raw_write_lock);
-
-#endif /* CONFIG_SPINLINE */
+EXPORT_SYMBOL(spin_unlock_wait);
diff --git a/arch/ppc64/mm/Makefile b/arch/ppc64/mm/Makefile
index 0306babff..ac522d57b 100644
--- a/arch/ppc64/mm/Makefile
+++ b/arch/ppc64/mm/Makefile
@@ -4,6 +4,8 @@
 
 EXTRA_CFLAGS += -mno-minimal-toc
 
-obj-y := fault.o init.o imalloc.o hash_utils.o hash_low.o tlb.o slb_low.o slb.o
+obj-y := fault.o init.o imalloc.o hash_utils.o hash_low.o tlb.o \
+	slb_low.o slb.o stab.o mmap.o
 obj-$(CONFIG_DISCONTIGMEM) += numa.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
+obj-$(CONFIG_PPC_MULTIPLATFORM) += hash_native.o
diff --git a/arch/ppc64/mm/hash_low.S b/arch/ppc64/mm/hash_low.S
index 0d6b5c29b..68dd4b9ad 100644
--- a/arch/ppc64/mm/hash_low.S
+++ b/arch/ppc64/mm/hash_low.S
@@ -172,9 +172,9 @@ htab_insert_pte:
 	li	r9,0
 _GLOBAL(htab_call_hpte_insert1)
 	bl	.			/* Will be patched by htab_finish_init() */
-	cmpi	0,r3,0
+	cmpdi	0,r3,0
 	bge	htab_pte_insert_ok	/* Insertion successful */
-	cmpi	0,r3,-2			/* Critical failure */
+	cmpdi	0,r3,-2			/* Critical failure */
 	beq-	htab_pte_insert_failure
 
 	/* Now try secondary slot */
@@ -194,9 +194,9 @@ _GLOBAL(htab_call_hpte_insert1)
 	li	r9,0
 _GLOBAL(htab_call_hpte_insert2)
 	bl	.			/* Will be patched by htab_finish_init() */
-	cmpi	0,r3,0
+	cmpdi	0,r3,0
 	bge+	htab_pte_insert_ok	/* Insertion successful */
-	cmpi	0,r3,-2			/* Critical failure */
+	cmpdi	0,r3,-2			/* Critical failure */
 	beq-	htab_pte_insert_failure
 
 	/* Both are full, we need to evict something */
@@ -263,7 +263,7 @@ _GLOBAL(htab_call_hpte_updatepp)
 	/* if we failed because typically the HPTE wasn't really here
 	 * we try an insertion. 
 	 */
-	cmpi	0,r3,-1
+	cmpdi	0,r3,-1
 	beq-	htab_insert_pte
 
 	/* Clear the BUSY bit and Write out the PTE */
@@ -278,6 +278,10 @@ htab_wrong_access:
 	b	bail
 
 htab_pte_insert_failure:
-	b	.htab_insert_failure
+	/* Bail out restoring old PTE */
+	ld	r6,STK_PARM(r6)(r1)
+	std	r31,0(r6)
+	li	r3,-1
+	b	bail
 
 
diff --git a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c
index f40565840..3a8a61380 100644
--- a/arch/ppc64/mm/hash_utils.c
+++ b/arch/ppc64/mm/hash_utils.c
@@ -18,6 +18,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#undef DEBUG
+
 #include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
@@ -28,6 +30,7 @@
 #include <linux/ctype.h>
 #include <linux/cache.h>
 #include <linux/init.h>
+#include <linux/signal.h>
 
 #include <asm/ppcdebug.h>
 #include <asm/processor.h>
@@ -50,6 +53,12 @@
 #include <asm/cputable.h>
 #include <asm/abs_addr.h>
 
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
 /*
  * Note:  pte   --> Linux PTE
  *        HPTE  --> PowerPC Hashed Page Table Entry
@@ -62,9 +71,9 @@
  *
  */
 
-#ifdef CONFIG_PMAC_DART
+#ifdef CONFIG_U3_DART
 extern unsigned long dart_tablebase;
-#endif /* CONFIG_PMAC_DART */
+#endif /* CONFIG_U3_DART */
 
 HTAB htab_data = {NULL, 0, 0, 0, 0};
 
@@ -80,7 +89,7 @@ static inline void loop_forever(void)
 		;
 }
 
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
 static inline void create_pte_mapping(unsigned long start, unsigned long end,
 				      unsigned long mode, int large)
 {
@@ -99,7 +108,7 @@ static inline void create_pte_mapping(unsigned long start, unsigned long end,
 		int ret;
 
 		if (large)
-			vpn = va >> LARGE_PAGE_SHIFT;
+			vpn = va >> HPAGE_SHIFT;
 		else
 			vpn = va >> PAGE_SHIFT;
 
@@ -107,12 +116,14 @@ static inline void create_pte_mapping(unsigned long start, unsigned long end,
 
 		hpteg = ((hash & htab_data.htab_hash_mask)*HPTES_PER_GROUP);
 
-		if (systemcfg->platform == PLATFORM_PSERIES_LPAR)
+#ifdef CONFIG_PPC_PSERIES
+		if (systemcfg->platform & PLATFORM_LPAR)
 			ret = pSeries_lpar_hpte_insert(hpteg, va,
 				virt_to_abs(addr) >> PAGE_SHIFT,
 				0, mode, 1, large);
 		else
-			ret = pSeries_hpte_insert(hpteg, va,
+#endif /* CONFIG_PPC_PSERIES */
+			ret = native_hpte_insert(hpteg, va,
 				virt_to_abs(addr) >> PAGE_SHIFT,
 				0, mode, 1, large);
 
@@ -130,6 +141,8 @@ void __init htab_initialize(void)
 	unsigned long mode_rw;
 	int i, use_largepages = 0;
 
+	DBG(" -> htab_initialize()\n");
+
 	/*
 	 * Calculate the required size of the htab.  We want the number of
 	 * PTEGs to equal one half the number of real pages.
@@ -146,12 +159,19 @@ void __init htab_initialize(void)
 	htab_data.htab_num_ptegs = pteg_count;
 	htab_data.htab_hash_mask = pteg_count - 1;
 
-	if (systemcfg->platform == PLATFORM_PSERIES ||
-	    systemcfg->platform == PLATFORM_POWERMAC) {
+	if (systemcfg->platform & PLATFORM_LPAR) {
+		/* Using a hypervisor which owns the htab */
+		htab_data.htab = NULL;
+		_SDR1 = 0; 
+	} else {
 		/* Find storage for the HPT.  Must be contiguous in
 		 * the absolute address space.
 		 */
 		table = lmb_alloc(htab_size_bytes, htab_size_bytes);
+
+		DBG("Hash table allocated at %lx, size: %lx\n", table,
+		    htab_size_bytes);
+
 		if ( !table ) {
 			ppc64_terminate_msg(0x20, "hpt space");
 			loop_forever();
@@ -163,10 +183,6 @@ void __init htab_initialize(void)
 
 		/* Initialize the HPT with no entries */
 		memset((void *)table, 0, htab_size_bytes);
-	} else {
-		/* Using a hypervisor which owns the htab */
-		htab_data.htab = NULL;
-		_SDR1 = 0; 
 	}
 
 	mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX;
@@ -178,14 +194,16 @@ void __init htab_initialize(void)
 	if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)
 		use_largepages = 1;
 
-	/* add all physical memory to the bootmem map */
+	/* create bolted the linear mapping in the hash table */
 	for (i=0; i < lmb.memory.cnt; i++) {
 		unsigned long base, size;
 
 		base = lmb.memory.region[i].physbase + KERNELBASE;
 		size = lmb.memory.region[i].size;
 
-#ifdef CONFIG_PMAC_DART
+		DBG("creating mapping for region: %lx : %lx\n", base, size);
+
+#ifdef CONFIG_U3_DART
 		/* Do not map the DART space. Fortunately, it will be aligned
 		 * in such a way that it will not cross two lmb regions and will
 		 * fit within a single 16Mb page.
@@ -193,6 +211,8 @@ void __init htab_initialize(void)
 		 * only use 2Mb of that space. We will use more of it later for
 		 * AGP GART. We have to use a full 16Mb large page.
 		 */
+		DBG("DART base: %lx\n", dart_tablebase);
+
 		if (dart_tablebase != 0 && dart_tablebase >= base
 		    && dart_tablebase < (base + size)) {
 			if (base != dart_tablebase)
@@ -203,13 +223,14 @@ void __init htab_initialize(void)
 						   mode_rw, use_largepages);
 			continue;
 		}
-#endif /* CONFIG_PMAC_DART */
+#endif /* CONFIG_U3_DART */
 		create_pte_mapping(base, base + size, mode_rw, use_largepages);
 	}
+	DBG(" <- htab_initialize()\n");
 }
 #undef KB
 #undef MB
-#endif
+#endif /* CONFIG_PPC_MULTIPLATFORM */
 
 /*
  * Called by asm hashtable.S for doing lazy icache flush
@@ -236,14 +257,11 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
 	return pp;
 }
 
-/*
- * Called by asm hashtable.S in case of critical insert failure
+/* Result code is:
+ *  0 - handled
+ *  1 - normal page fault
+ * -1 - critical hash insertion error
  */
-void htab_insert_failure(void)
-{
-	panic("hash_page: pte_insert failed\n");
-}
-
 int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
 {
 	void *pgdir;
@@ -255,24 +273,24 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
 	int local = 0;
 	cpumask_t tmp;
 
-	/* Check for invalid addresses. */
-	if (!IS_VALID_EA(ea))
-		return 1;
-
  	switch (REGION_ID(ea)) {
 	case USER_REGION_ID:
 		user_region = 1;
 		mm = current->mm;
-		if (mm == NULL)
+		if ((ea > USER_END) || (! mm))
 			return 1;
 
 		vsid = get_vsid(mm->context.id, ea);
 		break;
 	case IO_REGION_ID:
+		if (ea > IMALLOC_END)
+			return 1;
 		mm = &ioremap_mm;
 		vsid = get_kernel_vsid(ea);
 		break;
 	case VMALLOC_REGION_ID:
+		if (ea > VMALLOC_END)
+			return 1;
 		mm = &init_mm;
 		vsid = get_kernel_vsid(ea);
 		break;
@@ -334,7 +352,7 @@ void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte,
 
 	va = (vsid << 28) | (ea & 0x0fffffff);
 	if (large)
-		vpn = va >> LARGE_PAGE_SHIFT;
+		vpn = va >> HPAGE_SHIFT;
 	else
 		vpn = va >> PAGE_SHIFT;
 	hash = hpt_hash(vpn, large);
@@ -371,6 +389,25 @@ static inline void make_bl(unsigned int *insn_addr, void *func)
 			   (unsigned long)insn_addr);
 }
 
+/*
+ * low_hash_fault is called when we the low level hash code failed
+ * to instert a PTE due to an hypervisor error
+ */
+void low_hash_fault(struct pt_regs *regs, unsigned long address)
+{
+	if (user_mode(regs)) {
+		siginfo_t info;
+
+		info.si_signo = SIGBUS;
+		info.si_errno = 0;
+		info.si_code = BUS_ADRERR;
+		info.si_addr = (void *)address;
+		force_sig_info(SIGBUS, &info, current);
+		return;
+	}
+	bad_page_fault(regs, address, SIGBUS);
+}
+
 void __init htab_finish_init(void)
 {
 	extern unsigned int *htab_call_hpte_insert1;
diff --git a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c
index 403c79bea..7e1a9bf28 100644
--- a/arch/ppc64/mm/hugetlbpage.c
+++ b/arch/ppc64/mm/hugetlbpage.c
@@ -530,6 +530,108 @@ full_search:
 	return -ENOMEM;
 }
 
+/*
+ * This mmap-allocator allocates new areas top-down from below the
+ * stack's low limit (the base):
+ *
+ * Because we have an exclusive hugepage region which lies within the
+ * normal user address space, we have to take special measures to make
+ * non-huge mmap()s evade the hugepage reserved regions.
+ */
+unsigned long
+arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
+			  const unsigned long len, const unsigned long pgoff,
+			  const unsigned long flags)
+{
+	struct vm_area_struct *vma, *prev_vma;
+	struct mm_struct *mm = current->mm;
+	unsigned long base = mm->mmap_base, addr = addr0;
+	int first_time = 1;
+
+	/* requested length too big for entire address space */
+	if (len > TASK_SIZE)
+		return -ENOMEM;
+
+	/* dont allow allocations above current base */
+	if (mm->free_area_cache > base)
+		mm->free_area_cache = base;
+
+	/* requesting a specific address */
+	if (addr) {
+		addr = PAGE_ALIGN(addr);
+		vma = find_vma(mm, addr);
+		if (TASK_SIZE - len >= addr &&
+				(!vma || addr + len <= vma->vm_start)
+				&& !is_hugepage_only_range(addr,len))
+			return addr;
+	}
+
+try_again:
+	/* make sure it can fit in the remaining address space */
+	if (mm->free_area_cache < len)
+		goto fail;
+
+	/* either no address requested or cant fit in requested address hole */
+	addr = (mm->free_area_cache - len) & PAGE_MASK;
+	do {
+hugepage_recheck:
+		if (touches_hugepage_low_range(addr, len)) {
+			addr = (addr & ((~0) << SID_SHIFT)) - len;
+			goto hugepage_recheck;
+		} else if (touches_hugepage_high_range(addr, len)) {
+			addr = TASK_HPAGE_BASE - len;
+		}
+
+		/*
+		 * Lookup failure means no vma is above this address,
+		 * i.e. return with success:
+		 */
+ 	 	if (!(vma = find_vma_prev(mm, addr, &prev_vma)))
+			return addr;
+
+		/*
+		 * new region fits between prev_vma->vm_end and
+		 * vma->vm_start, use it:
+		 */
+		if (addr+len <= vma->vm_start &&
+				(!prev_vma || (addr >= prev_vma->vm_end)))
+			/* remember the address as a hint for next time */
+			return (mm->free_area_cache = addr);
+		else
+			/* pull free_area_cache down to the first hole */
+			if (mm->free_area_cache == vma->vm_end)
+				mm->free_area_cache = vma->vm_start;
+
+		/* try just below the current vma->vm_start */
+		addr = vma->vm_start-len;
+	} while (len <= vma->vm_start);
+
+fail:
+	/*
+	 * if hint left us with no space for the requested
+	 * mapping then try again:
+	 */
+	if (first_time) {
+		mm->free_area_cache = base;
+		first_time = 0;
+		goto try_again;
+	}
+	/*
+	 * A failed mmap() very likely causes application failure,
+	 * so fall back to the bottom-up function here. This scenario
+	 * can happen with large stack limits and large mmap()
+	 * allocations.
+	 */
+	mm->free_area_cache = TASK_UNMAPPED_BASE;
+	addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
+	/*
+	 * Restore the topdown base:
+	 */
+	mm->free_area_cache = base;
+
+	return addr;
+}
+
 static unsigned long htlb_get_low_area(unsigned long len, u16 segmask)
 {
 	unsigned long addr = 0;
@@ -754,7 +856,7 @@ static void flush_hash_hugepage(mm_context_t context, unsigned long ea,
 	vsid = get_vsid(context.id, ea);
 
 	va = (vsid << 28) | (ea & 0x0fffffff);
-	vpn = va >> LARGE_PAGE_SHIFT;
+	vpn = va >> HPAGE_SHIFT;
 	hash = hpt_hash(vpn, 1);
 	if (hugepte_val(pte) & _HUGEPAGE_SECONDARY)
 		hash = ~hash;
diff --git a/arch/ppc64/mm/imalloc.c b/arch/ppc64/mm/imalloc.c
index 2399f3fcb..9d92b0d9c 100644
--- a/arch/ppc64/mm/imalloc.c
+++ b/arch/ppc64/mm/imalloc.c
@@ -37,33 +37,51 @@ static int get_free_im_addr(unsigned long size, unsigned long *im_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 
+ * 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) The first region is not a subset of the second
+ * 3) Neither region is a subset of the other
  */
-static inline int im_region_overlaps(unsigned long v_addr, unsigned long size,
+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);
 }
 
-/* Return whether the region described by v_addr and size is a subset
- * of the region described by vm
- */
-static inline int im_region_is_subset(unsigned long v_addr, unsigned long size,
-			struct vm_struct *vm)
-{
-	return (int) (v_addr >= (unsigned long) vm->addr && 
-	              v_addr < (unsigned long) vm->addr + vm->size &&
-	    	      size < vm->size);
-}
-
 /* 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.
@@ -73,28 +91,37 @@ static inline int im_region_is_subset(unsigned long v_addr, unsigned long size,
  * 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 -  A portion of the region is already allocated in 
- *                       imalloc space.
+ * 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, 
+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) 
+	for (tmp = imlist; tmp; tmp = tmp->next)
+		if (v_addr < (unsigned long) tmp->addr + tmp->size)
 			break;
-					
+
 	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))
+		if (im_region_is_subset(v_addr, size, tmp)) {
+			/* Return with tmp pointing to superset */
 			return IM_REGION_SUBSET;
-		else if (v_addr == (unsigned long) tmp->addr && 
-		 	 size == tmp->size) 
+		}
+		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;
+		}
 	}
 
 	*vm = NULL;
@@ -208,6 +235,10 @@ static struct vm_struct * __im_get_area(unsigned long req_addr,
 		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",
diff --git a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
index 99d923868..cf0c57a7d 100644
--- a/arch/ppc64/mm/init.c
+++ b/arch/ppc64/mm/init.c
@@ -36,6 +36,7 @@
 #include <linux/delay.h>
 #include <linux/bootmem.h>
 #include <linux/highmem.h>
+#include <linux/idr.h>
 
 #include <asm/pgalloc.h>
 #include <asm/page.h>
@@ -62,8 +63,6 @@
 #include <asm/iommu.h>
 #include <asm/abs_addr.h>
 
-
-struct mmu_context_queue_t mmu_context_queue;
 int mem_init_done;
 unsigned long ioremap_bot = IMALLOC_BASE;
 static unsigned long phbs_io_bot = PHBS_IO_BASE;
@@ -85,7 +84,6 @@ unsigned long __max_memory;
 /* info on what we think the IO hole is */
 unsigned long 	io_hole_start;
 unsigned long	io_hole_size;
-unsigned long	top_of_ram;
 
 void show_mem(void)
 {
@@ -118,18 +116,18 @@ void show_mem(void)
 
 #ifdef CONFIG_PPC_ISERIES
 
-void *ioremap(unsigned long addr, unsigned long size)
+void __iomem *ioremap(unsigned long addr, unsigned long size)
 {
-	return (void *)addr;
+	return (void __iomem *)addr;
 }
 
-extern void *__ioremap(unsigned long addr, unsigned long size,
+extern void __iomem *__ioremap(unsigned long addr, unsigned long size,
 		       unsigned long flags)
 {
-	return (void *)addr;
+	return (void __iomem *)addr;
 }
 
-void iounmap(void *addr)
+void iounmap(volatile void __iomem *addr)
 {
 	return;
 }
@@ -183,7 +181,7 @@ static void map_io_page(unsigned long ea, unsigned long pa, int flags)
 }
 
 
-static void * __ioremap_com(unsigned long addr, unsigned long pa,
+static void __iomem * __ioremap_com(unsigned long addr, unsigned long pa,
 			    unsigned long ea, unsigned long size,
 			    unsigned long flags)
 {
@@ -198,20 +196,17 @@ static void * __ioremap_com(unsigned long addr, unsigned long pa,
 		map_io_page(ea+i, pa+i, flags);
 	}
 
-	return (void *) (ea + (addr & ~PAGE_MASK));
+	return (void __iomem *) (ea + (addr & ~PAGE_MASK));
 }
 
 
-void *
+void __iomem *
 ioremap(unsigned long addr, unsigned long size)
 {
-	void *ret = __ioremap(addr, size, _PAGE_NO_CACHE);
-	if(mem_init_done)
-		return eeh_ioremap(addr, ret);	/* may remap the addr */
-	return ret;
+	return __ioremap(addr, size, _PAGE_NO_CACHE);
 }
 
-void *
+void __iomem *
 __ioremap(unsigned long addr, unsigned long size, unsigned long flags)
 {
 	unsigned long pa, ea;
@@ -354,19 +349,18 @@ static void unmap_im_area_pmd(pgd_t *dir, unsigned long address,
  *
  * XXX	what about calls before mem_init_done (ie python_countermeasures())	
  */
-void iounmap(void *addr)
+void iounmap(volatile void __iomem *token)
 {
 	unsigned long address, start, end, size;
 	struct mm_struct *mm;
 	pgd_t *dir;
+	void *addr;
 
 	if (!mem_init_done) {
 		return;
 	}
 	
-	/* addr could be in EEH or IO region, map it to IO region regardless.
-	 */
-	addr = (void *) (IO_TOKEN_TO_ADDR(addr) & PAGE_MASK);
+	addr = (void *) ((unsigned long __force) token & PAGE_MASK);
 	
 	if ((size = im_free(addr)) == 0) {
 		return;
@@ -392,27 +386,55 @@ void iounmap(void *addr)
 	return;
 }
 
-int iounmap_explicit(void *addr, unsigned long size)
+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 could be in EEH or IO region, map it to IO region regardless.
-	 */
-	addr = (void *) (IO_TOKEN_TO_ADDR(addr) & PAGE_MASK);
+	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((unsigned long) addr, size, 
+	area = im_get_area(addr, size, 
 			    IM_REGION_EXISTS | IM_REGION_SUBSET);
 	if (area == NULL) {
-		printk(KERN_ERR "%s() cannot unmap nonexistent range 0x%lx\n",
-				__FUNCTION__, (unsigned long) addr);
-		return 1;
+		/* 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;
 }
 
@@ -447,41 +469,81 @@ void free_initrd_mem(unsigned long start, unsigned long end)
 }
 #endif
 
+static spinlock_t mmu_context_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_IDR(mmu_context_idr);
+
+int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+	int index;
+	int err;
+
+again:
+	if (!idr_pre_get(&mmu_context_idr, GFP_KERNEL))
+		return -ENOMEM;
+
+	spin_lock(&mmu_context_lock);
+	err = idr_get_new(&mmu_context_idr, NULL, &index);
+	spin_unlock(&mmu_context_lock);
+
+	if (err == -EAGAIN)
+		goto again;
+	else if (err)
+		return err;
+
+	if (index > MAX_CONTEXT) {
+		idr_remove(&mmu_context_idr, index);
+		return -ENOMEM;
+	}
+
+	mm->context.id = index;
+
+	return 0;
+}
+
+void destroy_context(struct mm_struct *mm)
+{
+	spin_lock(&mmu_context_lock);
+	idr_remove(&mmu_context_idr, mm->context.id);
+	spin_unlock(&mmu_context_lock);
+
+	mm->context.id = NO_CONTEXT;
+}
+
+static int __init mmu_context_init(void)
+{
+	int index;
+
+	/* Reserve the first (invalid) context*/
+	idr_pre_get(&mmu_context_idr, GFP_KERNEL);
+	idr_get_new(&mmu_context_idr, NULL, &index);
+	BUG_ON(0 != index);
+
+	return 0;
+}
+arch_initcall(mmu_context_init);
+
 /*
  * Do very early mm setup.
  */
 void __init mm_init_ppc64(void)
 {
+#ifndef CONFIG_PPC_ISERIES
 	unsigned long i;
+#endif
 
 	ppc64_boot_msg(0x100, "MM Init");
 
-	/* Reserve all contexts < FIRST_USER_CONTEXT for kernel use.
-	 * The range of contexts [FIRST_USER_CONTEXT, NUM_USER_CONTEXT)
-	 * are stored on a stack/queue for easy allocation and deallocation.
-	 */
-	mmu_context_queue.lock = SPIN_LOCK_UNLOCKED;
-	mmu_context_queue.head = 0;
-	mmu_context_queue.tail = NUM_USER_CONTEXT-1;
-	mmu_context_queue.size = NUM_USER_CONTEXT;
-	for (i = 0; i < NUM_USER_CONTEXT; i++)
-		mmu_context_queue.elements[i] = i + FIRST_USER_CONTEXT;
-
 	/* This is the story of the IO hole... please, keep seated,
 	 * unfortunately, we are out of oxygen masks at the moment.
 	 * So we need some rough way to tell where your big IO hole
 	 * is. On pmac, it's between 2G and 4G, on POWER3, it's around
 	 * that area as well, on POWER4 we don't have one, etc...
-	 * We need that to implement something approx. decent for
-	 * page_is_ram() so that /dev/mem doesn't map cacheable IO space
-	 * when XFree resquest some IO regions witout using O_SYNC, we
-	 * also need that as a "hint" when sizing the TCE table on POWER3
+	 * We need that as a "hint" when sizing the TCE table on POWER3
 	 * So far, the simplest way that seem work well enough for us it
 	 * to just assume that the first discontinuity in our physical
 	 * RAM layout is the IO hole. That may not be correct in the future
 	 * (and isn't on iSeries but then we don't care ;)
 	 */
-	top_of_ram = lmb_end_of_DRAM();
 
 #ifndef CONFIG_PPC_ISERIES
 	for (i = 1; i < lmb.memory.cnt; i++) {
@@ -504,22 +566,32 @@ void __init mm_init_ppc64(void)
 	ppc64_boot_msg(0x100, "MM Init Done");
 }
 
-
 /*
  * This is called by /dev/mem to know if a given address has to
  * be mapped non-cacheable or not
  */
-int page_is_ram(unsigned long physaddr)
+int page_is_ram(unsigned long pfn)
 {
-#ifdef CONFIG_PPC_ISERIES
-	return 1;
+	int i;
+	unsigned long paddr = (pfn << PAGE_SHIFT);
+
+	for (i=0; i < lmb.memory.cnt; i++) {
+		unsigned long base;
+
+#ifdef CONFIG_MSCHUNKS
+		base = lmb.memory.region[i].physbase;
+#else
+		base = lmb.memory.region[i].base;
 #endif
-	if (physaddr >= top_of_ram)
-		return 0;
-	return io_hole_start == 0 ||  physaddr < io_hole_start ||
-		physaddr >= (io_hole_start + io_hole_size);
-}
+		if ((paddr >= base) &&
+			(paddr < (base + lmb.memory.region[i].size))) {
+			return 1;
+		}
+	}
 
+	return 0;
+}
+EXPORT_SYMBOL(page_is_ram);
 
 /*
  * Initialize the bootmem system and give it all the memory we
@@ -573,6 +645,7 @@ void __init paging_init(void)
 	unsigned long zones_size[MAX_NR_ZONES];
 	unsigned long zholes_size[MAX_NR_ZONES];
 	unsigned long total_ram = lmb_phys_mem_size();
+	unsigned long top_of_ram = lmb_end_of_DRAM();
 
 	printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
 	       top_of_ram, total_ram);
@@ -587,7 +660,7 @@ void __init paging_init(void)
 	zones_size[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
 	zholes_size[ZONE_DMA] = (top_of_ram - total_ram) >> PAGE_SHIFT;
 
-	free_area_init_node(0, &contig_page_data, NULL, zones_size,
+	free_area_init_node(0, &contig_page_data, zones_size,
 			    __pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size);
 	mem_map = contig_page_data.node_mem_map;
 }
@@ -622,59 +695,53 @@ module_init(setup_kcore);
 
 void __init mem_init(void)
 {
-#ifndef CONFIG_DISCONTIGMEM
-	unsigned long addr;
+#ifdef CONFIG_DISCONTIGMEM
+	int nid;
 #endif
-	int codepages = 0;
-	int datapages = 0;
-	int initpages = 0;
+	pg_data_t *pgdat;
+	unsigned long i;
+	struct page *page;
+	unsigned long reservedpages = 0, codesize, initsize, datasize, bsssize;
 
 	num_physpages = max_low_pfn;	/* RAM is assumed contiguous */
 	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
 
 #ifdef CONFIG_DISCONTIGMEM
-{
-	int nid;
-
         for (nid = 0; nid < numnodes; nid++) {
-		if (node_data[nid].node_spanned_pages != 0) {
+		if (NODE_DATA(nid)->node_spanned_pages != 0) {
 			printk("freeing bootmem node %x\n", nid);
 			totalram_pages +=
 				free_all_bootmem_node(NODE_DATA(nid));
 		}
 	}
-
-	printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08lx,%08lx]\n",
-	       (unsigned long)nr_free_pages()<< (PAGE_SHIFT-10),
-	       codepages<< (PAGE_SHIFT-10), datapages<< (PAGE_SHIFT-10),
-	       initpages<< (PAGE_SHIFT-10),
-	       PAGE_OFFSET, (unsigned long)__va(lmb_end_of_DRAM()));
-}
 #else
 	max_mapnr = num_physpages;
-
 	totalram_pages += free_all_bootmem();
+#endif
 
-	for (addr = KERNELBASE; addr < (unsigned long)__va(lmb_end_of_DRAM());
-	     addr += PAGE_SIZE) {
-		if (!PageReserved(virt_to_page(addr)))
-			continue;
-		if (addr < (unsigned long)_etext)
-			codepages++;
-
-		else if (addr >= (unsigned long)__init_begin
-			 && addr < (unsigned long)__init_end)
-			initpages++;
-		else if (addr < klimit)
-			datapages++;
+	for_each_pgdat(pgdat) {
+		for (i = 0; i < pgdat->node_spanned_pages; i++) {
+			page = pgdat->node_mem_map + i;
+			if (PageReserved(page))
+				reservedpages++;
+		}
 	}
 
-	printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08lx,%08lx]\n",
-	       (unsigned long)nr_free_pages()<< (PAGE_SHIFT-10),
-	       codepages<< (PAGE_SHIFT-10), datapages<< (PAGE_SHIFT-10),
-	       initpages<< (PAGE_SHIFT-10),
-	       PAGE_OFFSET, (unsigned long)__va(lmb_end_of_DRAM()));
-#endif
+	codesize = (unsigned long)&_etext - (unsigned long)&_stext;
+	initsize = (unsigned long)&__init_end - (unsigned long)&__init_begin;
+	datasize = (unsigned long)&_edata - (unsigned long)&__init_end;
+	bsssize = (unsigned long)&__bss_stop - (unsigned long)&__bss_start;
+
+	printk(KERN_INFO "Memory: %luk/%luk available (%luk kernel code, "
+	       "%luk reserved, %luk data, %luk bss, %luk init)\n",
+		(unsigned long)nr_free_pages() << (PAGE_SHIFT-10),
+		num_physpages << (PAGE_SHIFT-10),
+		codesize >> 10,
+		reservedpages << (PAGE_SHIFT-10),
+		datasize >> 10,
+		bsssize >> 10,
+		initsize >> 10);
+
 	mem_init_done = 1;
 
 #ifdef CONFIG_PPC_ISERIES
diff --git a/arch/ppc64/mm/mmap.c b/arch/ppc64/mm/mmap.c
index 5ebf68668..f90dd1f7a 100644
--- a/arch/ppc64/mm/mmap.c
+++ b/arch/ppc64/mm/mmap.c
@@ -54,13 +54,13 @@ static inline int mmap_is_legacy(void)
 	 */
 	if (!test_thread_flag(TIF_32BIT))
 		return 1;
-		
-	if (current->personality & ADDR_COMPAT_LAYOUT) 
+
+	if (current->personality & ADDR_COMPAT_LAYOUT)
 		return 1;
-	
+
 	if (current->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY)
 		return 1;
-		
+
 	return sysctl_legacy_va_layout;
 }
 
@@ -81,7 +81,6 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 	} else {
 		mm->mmap_base = mmap_base();
 		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
-		mm->get_unmapped_exec_area = arch_get_unmapped_exec_area;
 		mm->unmap_area = arch_unmap_area_topdown;
 	}
 }
diff --git a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c
index eb3313694..977140f78 100644
--- a/arch/ppc64/mm/numa.c
+++ b/arch/ppc64/mm/numa.c
@@ -18,11 +18,10 @@
 #include <asm/machdep.h>
 #include <asm/abs_addr.h>
 
-#if 1
-#define dbg(args...) printk(KERN_INFO args)
-#else
-#define dbg(args...)
-#endif
+static int numa_enabled = 1;
+
+static int numa_debug;
+#define dbg(args...) if (numa_debug) { printk(KERN_INFO args); }
 
 #ifdef DEBUG_NUMA
 #define ARRAY_INITIALISER -1
@@ -36,10 +35,19 @@ char *numa_memory_lookup_table;
 cpumask_t numa_cpumask_lookup_table[MAX_NUMNODES];
 int nr_cpus_in_node[MAX_NUMNODES] = { [0 ... (MAX_NUMNODES -1)] = 0};
 
-struct pglist_data node_data[MAX_NUMNODES];
-bootmem_data_t plat_node_bdata[MAX_NUMNODES];
+struct pglist_data *node_data[MAX_NUMNODES];
+bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES];
 static unsigned long node0_io_hole_size;
 
+/*
+ * We need somewhere to store start/span for each node until we have
+ * allocated the real node_data structures.
+ */
+static struct {
+	unsigned long node_start_pfn;
+	unsigned long node_spanned_pages;
+} init_node_data[MAX_NUMNODES] __initdata;
+
 EXPORT_SYMBOL(node_data);
 EXPORT_SYMBOL(numa_cpu_lookup_table);
 EXPORT_SYMBOL(numa_memory_lookup_table);
@@ -48,7 +56,6 @@ EXPORT_SYMBOL(nr_cpus_in_node);
 
 static inline void map_cpu_to_node(int cpu, int node)
 {
-	dbg("cpu %d maps to domain %d\n", cpu, node);
 	numa_cpu_lookup_table[cpu] = node;
 	if (!(cpu_isset(cpu, numa_cpumask_lookup_table[node]))) {
 		cpu_set(cpu, numa_cpumask_lookup_table[node]);
@@ -107,8 +114,8 @@ static int of_node_numa_domain(struct device_node *device, int depth)
 	if (tmp && (tmp[0] >= depth)) {
 		numa_domain = tmp[depth];
 	} else {
-		printk(KERN_ERR "WARNING: no NUMA information for "
-		       "%s\n", device->full_name);
+		dbg("WARNING: no NUMA information for %s\n",
+		    device->full_name);
 		numa_domain = 0;
 	}
 	return numa_domain;
@@ -137,11 +144,8 @@ static int find_min_common_depth(void)
 
 	rtas_root = of_find_node_by_path("/rtas");
 
-	if (!rtas_root) {
-		printk(KERN_ERR "WARNING: %s() could not find rtas root\n",
-				__FUNCTION__);
+	if (!rtas_root)
 		return -1;
-	}
 
 	/*
 	 * this property is 2 32-bit integers, each representing a level of
@@ -155,8 +159,8 @@ static int find_min_common_depth(void)
 	if ((len >= 1) && ref_points) {
 		depth = ref_points[1];
 	} else {
-		printk(KERN_ERR "WARNING: could not find NUMA "
-				"associativity reference point\n");
+		dbg("WARNING: could not find NUMA "
+		    "associativity reference point\n");
 		depth = -1;
 	}
 	of_node_put(rtas_root);
@@ -187,20 +191,21 @@ static int __init parse_numa_properties(void)
 	long entries = lmb_end_of_DRAM() >> MEMORY_INCREMENT_SHIFT;
 	unsigned long i;
 
-	if (strstr(saved_command_line, "numa=off")) {
+	if (numa_enabled == 0) {
 		printk(KERN_WARNING "NUMA disabled by user\n");
 		return -1;
 	}
 
 	numa_memory_lookup_table =
 		(char *)abs_to_virt(lmb_alloc(entries * sizeof(char), 1));
+	memset(numa_memory_lookup_table, 0, entries * sizeof(char));
 
 	for (i = 0; i < entries ; i++)
 		numa_memory_lookup_table[i] = ARRAY_INITIALISER;
 
 	depth = find_min_common_depth();
 
-	printk(KERN_INFO "NUMA associativity depth for CPU/Memory: %d\n", depth);
+	dbg("NUMA associativity depth for CPU/Memory: %d\n", depth);
 	if (depth < 0)
 		return depth;
 
@@ -225,8 +230,7 @@ static int __init parse_numa_properties(void)
 				numa_domain = 0;
 			}
 		} else {
-			printk(KERN_ERR "WARNING: no NUMA information for "
-			       "cpu %ld\n", i);
+			dbg("WARNING: no NUMA information for cpu %ld\n", i);
 			numa_domain = 0;
 		}
 
@@ -281,22 +285,22 @@ new_range:
 		 * this simple case and complain if there is a gap in
 		 * memory
 		 */
-		if (node_data[numa_domain].node_spanned_pages) {
+		if (init_node_data[numa_domain].node_spanned_pages) {
 			unsigned long shouldstart =
-				node_data[numa_domain].node_start_pfn + 
-				node_data[numa_domain].node_spanned_pages;
+				init_node_data[numa_domain].node_start_pfn +
+				init_node_data[numa_domain].node_spanned_pages;
 			if (shouldstart != (start / PAGE_SIZE)) {
-				printk(KERN_ERR "Hole in node, disabling "
-						"region start %lx length %lx\n",
-						start, size);
+				printk(KERN_ERR "WARNING: Hole in node, "
+						"disabling region start %lx "
+						"length %lx\n", start, size);
 				continue;
 			}
-			node_data[numa_domain].node_spanned_pages +=
+			init_node_data[numa_domain].node_spanned_pages +=
 				size / PAGE_SIZE;
 		} else {
-			node_data[numa_domain].node_start_pfn =
+			init_node_data[numa_domain].node_start_pfn =
 				start / PAGE_SIZE;
-			node_data[numa_domain].node_spanned_pages =
+			init_node_data[numa_domain].node_spanned_pages =
 				size / PAGE_SIZE;
 		}
 
@@ -304,9 +308,6 @@ new_range:
 			numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] =
 				numa_domain;
 
-		dbg("memory region %lx to %lx maps to domain %d\n",
-		    start, start+size, numa_domain);
-
 		ranges--;
 		if (ranges)
 			goto new_range;
@@ -332,6 +333,7 @@ static void __init setup_nonnuma(void)
 		long entries = top_of_ram >> MEMORY_INCREMENT_SHIFT;
 		numa_memory_lookup_table =
 			(char *)abs_to_virt(lmb_alloc(entries * sizeof(char), 1));
+		memset(numa_memory_lookup_table, 0, entries * sizeof(char));
 		for (i = 0; i < entries ; i++)
 			numa_memory_lookup_table[i] = ARRAY_INITIALISER;
 	}
@@ -341,8 +343,8 @@ static void __init setup_nonnuma(void)
 
 	node_set_online(0);
 
-	node_data[0].node_start_pfn = 0;
-	node_data[0].node_spanned_pages = lmb_end_of_DRAM() / PAGE_SIZE;
+	init_node_data[0].node_start_pfn = 0;
+	init_node_data[0].node_spanned_pages = lmb_end_of_DRAM() / PAGE_SIZE;
 
 	for (i = 0 ; i < top_of_ram; i += MEMORY_INCREMENT)
 		numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = 0;
@@ -350,6 +352,108 @@ static void __init setup_nonnuma(void)
 	node0_io_hole_size = top_of_ram - total_ram;
 }
 
+static void __init dump_numa_topology(void)
+{
+	unsigned int node;
+	unsigned int cpu, count;
+
+	for (node = 0; node < MAX_NUMNODES; node++) {
+		if (!node_online(node))
+			continue;
+
+		printk(KERN_INFO "Node %d CPUs:", node);
+
+		count = 0;
+		/*
+		 * If we used a CPU iterator here we would miss printing
+		 * the holes in the cpumap.
+		 */
+		for (cpu = 0; cpu < NR_CPUS; cpu++) {
+			if (cpu_isset(cpu, numa_cpumask_lookup_table[node])) {
+				if (count == 0)
+					printk(" %u", cpu);
+				++count;
+			} else {
+				if (count > 1)
+					printk("-%u", cpu - 1);
+				count = 0;
+			}
+		}
+
+		if (count > 1)
+			printk("-%u", NR_CPUS - 1);
+		printk("\n");
+	}
+
+	for (node = 0; node < MAX_NUMNODES; node++) {
+		unsigned long i;
+
+		if (!node_online(node))
+			continue;
+
+		printk(KERN_INFO "Node %d Memory:", node);
+
+		count = 0;
+
+		for (i = 0; i < lmb_end_of_DRAM(); i += MEMORY_INCREMENT) {
+			if (numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] == node) {
+				if (count == 0)
+					printk(" 0x%lx", i);
+				++count;
+			} else {
+				if (count > 0)
+					printk("-0x%lx", i);
+				count = 0;
+			}
+		}
+
+		if (count > 0)
+			printk("-0x%lx", i);
+		printk("\n");
+	}
+}
+
+/*
+ * Allocate some memory, satisfying the lmb or bootmem allocator where
+ * required. nid is the preferred node and end is the physical address of
+ * the highest address in the node.
+ *
+ * Returns the physical address of the memory.
+ */
+static unsigned long careful_allocation(int nid, unsigned long size,
+					unsigned long align, unsigned long end)
+{
+	unsigned long ret = lmb_alloc_base(size, align, end);
+
+	/* retry over all memory */
+	if (!ret)
+		ret = lmb_alloc_base(size, align, lmb_end_of_DRAM());
+
+	if (!ret)
+		panic("numa.c: cannot allocate %lu bytes on node %d",
+		      size, nid);
+
+	/*
+	 * If the memory came from a previously allocated node, we must
+	 * retry with the bootmem allocator.
+	 */
+	if (pa_to_nid(ret) < nid) {
+		nid = pa_to_nid(ret);
+		ret = (unsigned long)__alloc_bootmem_node(NODE_DATA(nid),
+				size, align, 0);
+
+		if (!ret)
+			panic("numa.c: cannot allocate %lu bytes on node %d",
+			      size, nid);
+
+		ret = virt_to_abs(ret);
+
+		dbg("alloc_bootmem %lx %lx\n", ret, size);
+	}
+
+	return ret;
+}
+
 void __init do_init_bootmem(void)
 {
 	int nid;
@@ -360,6 +464,8 @@ void __init do_init_bootmem(void)
 
 	if (parse_numa_properties())
 		setup_nonnuma();
+	else
+		dump_numa_topology();
 
 	for (nid = 0; nid < numnodes; nid++) {
 		unsigned long start_paddr, end_paddr;
@@ -367,24 +473,38 @@ void __init do_init_bootmem(void)
 		unsigned long bootmem_paddr;
 		unsigned long bootmap_pages;
 
-		if (node_data[nid].node_spanned_pages == 0)
-			continue;
+		start_paddr = init_node_data[nid].node_start_pfn * PAGE_SIZE;
+		end_paddr = start_paddr + (init_node_data[nid].node_spanned_pages * PAGE_SIZE);
 
-		start_paddr = node_data[nid].node_start_pfn * PAGE_SIZE;
-		end_paddr = start_paddr + 
-				(node_data[nid].node_spanned_pages * PAGE_SIZE);
+		/* Allocate the node structure node local if possible */
+		NODE_DATA(nid) = (struct pglist_data *)careful_allocation(nid,
+					sizeof(struct pglist_data),
+					SMP_CACHE_BYTES, end_paddr);
+		NODE_DATA(nid) = abs_to_virt(NODE_DATA(nid));
+		memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
 
-		dbg("node %d\n", nid);
-		dbg("start_paddr = %lx\n", start_paddr);
-		dbg("end_paddr = %lx\n", end_paddr);
+  		dbg("node %d\n", nid);
+		dbg("NODE_DATA() = %p\n", NODE_DATA(nid));
 
 		NODE_DATA(nid)->bdata = &plat_node_bdata[nid];
+		NODE_DATA(nid)->node_start_pfn =
+			init_node_data[nid].node_start_pfn;
+		NODE_DATA(nid)->node_spanned_pages =
+			init_node_data[nid].node_spanned_pages;
+
+		if (init_node_data[nid].node_spanned_pages == 0)
+  			continue;
+
+  		dbg("start_paddr = %lx\n", start_paddr);
+  		dbg("end_paddr = %lx\n", end_paddr);
 
 		bootmap_pages = bootmem_bootmap_pages((end_paddr - start_paddr) >> PAGE_SHIFT);
-		dbg("bootmap_pages = %lx\n", bootmap_pages);
 
-		bootmem_paddr = lmb_alloc_base(bootmap_pages << PAGE_SHIFT,
+		bootmem_paddr = careful_allocation(nid,
+				bootmap_pages << PAGE_SHIFT,
 				PAGE_SIZE, end_paddr);
+		memset(abs_to_virt(bootmem_paddr), 0,
+		       bootmap_pages << PAGE_SHIFT);
 		dbg("bootmap_paddr = %lx\n", bootmem_paddr);
 
 		init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT,
@@ -442,7 +562,6 @@ void __init paging_init(void)
 {
 	unsigned long zones_size[MAX_NR_ZONES];
 	unsigned long zholes_size[MAX_NR_ZONES];
-	struct page *node_mem_map; 
 	int nid;
 
 	memset(zones_size, 0, sizeof(zones_size));
@@ -463,17 +582,22 @@ void __init paging_init(void)
 		dbg("free_area_init node %d %lx %lx (hole: %lx)\n", nid,
 		    zones_size[ZONE_DMA], start_pfn, zholes_size[ZONE_DMA]);
 
-		/* 
-		 * Give this empty node a dummy struct page to avoid
-		 * us from trying to allocate a node local mem_map
-		 * in free_area_init_node (which will fail).
-		 */
-		if (!node_data[nid].node_spanned_pages)
-			node_mem_map = alloc_bootmem(sizeof(struct page));
-		else
-			node_mem_map = NULL;
-
-		free_area_init_node(nid, NODE_DATA(nid), node_mem_map,
-				    zones_size, start_pfn, zholes_size);
+		free_area_init_node(nid, NODE_DATA(nid), zones_size,
+							start_pfn, zholes_size);
 	}
 }
+
+static int __init early_numa(char *p)
+{
+	if (!p)
+		return 0;
+
+	if (strstr(p, "off"))
+		numa_enabled = 0;
+
+	if (strstr(p, "debug"))
+		numa_debug = 1;
+
+	return 0;
+}
+early_param("numa", early_numa);
diff --git a/arch/ppc64/mm/slb.c b/arch/ppc64/mm/slb.c
index bc6125804..7424d8d24 100644
--- a/arch/ppc64/mm/slb.c
+++ b/arch/ppc64/mm/slb.c
@@ -24,32 +24,55 @@
 
 extern void slb_allocate(unsigned long ea);
 
+static inline unsigned long mk_esid_data(unsigned long ea, unsigned long slot)
+{
+	return (ea & ESID_MASK) | SLB_ESID_V | slot;
+}
+
+static inline unsigned long mk_vsid_data(unsigned long ea, unsigned long flags)
+{
+	return (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | flags;
+}
+
 static inline void create_slbe(unsigned long ea, unsigned long vsid,
 			       unsigned long flags, unsigned long entry)
 {
-	ea = (ea & ESID_MASK) | SLB_ESID_V | entry;
-	vsid = (vsid << SLB_VSID_SHIFT) | flags;
 	asm volatile("slbmte  %0,%1" :
-		     : "r" (vsid), "r" (ea)
+		     : "r" (mk_vsid_data(ea, flags)),
+		       "r" (mk_esid_data(ea, entry))
 		     : "memory" );
 }
 
-static void slb_add_bolted(void)
+static void slb_flush_and_rebolt(void)
 {
-#ifndef CONFIG_PPC_ISERIES
-	WARN_ON(!irqs_disabled());
-
 	/* If you change this make sure you change SLB_NUM_BOLTED
-	 * appropriately too */
+	 * appropriately too. */
+	unsigned long ksp_flags = SLB_VSID_KERNEL;
+	unsigned long ksp_esid_data;
 
-	/* Slot 1 - first VMALLOC segment
-         * 	Since modules end up there it gets hit very heavily.
-         */
-	create_slbe(VMALLOCBASE, get_kernel_vsid(VMALLOCBASE),
-		    SLB_VSID_KERNEL, 1);
+	WARN_ON(!irqs_disabled());
 
-	asm volatile("isync":::"memory");
-#endif
+	if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)
+		ksp_flags |= SLB_VSID_L;
+
+	ksp_esid_data = mk_esid_data(get_paca()->kstack, 2);
+	if ((ksp_esid_data & ESID_MASK) == KERNELBASE)
+		ksp_esid_data &= ~SLB_ESID_V;
+
+	/* We need to do this all in asm, so we're sure we don't touch
+	 * the stack between the slbia and rebolting it. */
+	asm volatile("isync\n"
+		     "slbia\n"
+		     /* Slot 1 - first VMALLOC segment */
+		     "slbmte	%0,%1\n"
+		     /* Slot 2 - kernel stack */
+		     "slbmte	%2,%3\n"
+		     "isync"
+		     :: "r"(mk_vsid_data(VMALLOCBASE, SLB_VSID_KERNEL)),
+		        "r"(mk_esid_data(VMALLOCBASE, 1)),
+		        "r"(mk_vsid_data(ksp_esid_data, ksp_flags)),
+		        "r"(ksp_esid_data)
+		     : "memory");
 }
 
 /* Flush all user entries from the segment table of the current processor. */
@@ -71,8 +94,7 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
 		}
 		asm volatile("isync" : : : "memory");
 	} else {
-		asm volatile("isync; slbia; isync" : : : "memory");
-		slb_add_bolted();
+		slb_flush_and_rebolt();
 	}
 
 	/* Workaround POWER5 < DD2.1 issue */
@@ -115,22 +137,27 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
 
 void slb_initialize(void)
 {
-#ifdef CONFIG_PPC_ISERIES
-	asm volatile("isync; slbia; isync":::"memory");
-#else
+	/* On iSeries the bolted entries have already been set up by
+	 * the hypervisor from the lparMap data in head.S */
+#ifndef CONFIG_PPC_ISERIES
 	unsigned long flags = SLB_VSID_KERNEL;
 
-	/* Invalidate the entire SLB (even slot 0) & all the ERATS */
-	if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)
-		flags |= SLB_VSID_L;
+ 	/* Invalidate the entire SLB (even slot 0) & all the ERATS */
+ 	if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)
+ 		flags |= SLB_VSID_L;
 
-	asm volatile("isync":::"memory");
-	asm volatile("slbmte  %0,%0"::"r" (0) : "memory");
+ 	asm volatile("isync":::"memory");
+ 	asm volatile("slbmte  %0,%0"::"r" (0) : "memory");
 	asm volatile("isync; slbia; isync":::"memory");
-	create_slbe(KERNELBASE, get_kernel_vsid(KERNELBASE),
-		    flags, 0);
-
+	create_slbe(KERNELBASE, get_kernel_vsid(KERNELBASE), flags, 0);
+	create_slbe(VMALLOCBASE, get_kernel_vsid(KERNELBASE),
+		    SLB_VSID_KERNEL, 1);
+	/* We don't bolt the stack for the time being - we're in boot,
+	 * so the stack is in the bolted segment.  By the time it goes
+	 * elsewhere, we'll call _switch() which will bolt in the new
+	 * one. */
+	asm volatile("isync":::"memory");
 #endif
-	slb_add_bolted();
+
 	get_paca()->stab_rr = SLB_NUM_BOLTED;
 }
diff --git a/arch/ppc64/mm/slb_low.S b/arch/ppc64/mm/slb_low.S
index 4b3dfe091..8379d678f 100644
--- a/arch/ppc64/mm/slb_low.S
+++ b/arch/ppc64/mm/slb_low.S
@@ -37,8 +37,21 @@ _GLOBAL(slb_allocate)
 	 * a free slot first but that took too long. Unfortunately we
 	 * dont have any LRU information to help us choose a slot.
 	 */
+#ifdef CONFIG_PPC_ISERIES
+	/*
+	 * On iSeries, the "bolted" stack segment can be cast out on
+	 * shared processor switch so we need to check for a miss on
+	 * it and restore it to the right slot.
+	 */
+	ld	r9,PACAKSAVE(r13)
+	clrrdi	r9,r9,28
+	clrrdi	r11,r3,28
+	li	r10,SLB_NUM_BOLTED-1	/* Stack goes in last bolted slot */
+	cmpld	r9,r11
+	beq	3f
+#endif /* CONFIG_PPC_ISERIES */
+
 	ld	r10,PACASTABRR(r13)
-3:
 	addi	r10,r10,1
 	/* use a cpu feature mask if we ever change our slb size */
 	cmpldi	r10,SLB_NUM_ENTRIES
@@ -46,55 +59,28 @@ _GLOBAL(slb_allocate)
 	blt+	4f
 	li	r10,SLB_NUM_BOLTED
 
-	/*
-	 * Never cast out the segment for our kernel stack. Since we
-	 * dont invalidate the ERAT we could have a valid translation
-	 * for the kernel stack during the first part of exception exit
-	 * which gets invalidated due to a tlbie from another cpu at a
-	 * non recoverable point (after setting srr0/1) - Anton
-	 */
-4:	slbmfee	r11,r10
-	srdi	r11,r11,27
-	/*
-	 * Use paca->ksave as the value of the kernel stack pointer,
-	 * because this is valid at all times.
-	 * The >> 27 (rather than >> 28) is so that the LSB is the
-	 * valid bit - this way we check valid and ESID in one compare.
-	 * In order to completely close the tiny race in the context
-	 * switch (between updating r1 and updating paca->ksave),
-	 * we check against both r1 and paca->ksave.
-	 */
-	srdi	r9,r1,27
-	ori	r9,r9,1			/* mangle SP for later compare */
-	cmpd	r11,r9
-	beq-	3b
-	ld	r9,PACAKSAVE(r13)
-	srdi	r9,r9,27
-	ori	r9,r9,1
-	cmpd	r11,r9
-	beq-	3b
-
+4:
 	std	r10,PACASTABRR(r13)
-
+3:
 	/* r3 = faulting address, r10 = entry */
 
 	srdi	r9,r3,60		/* get region */
 	srdi	r3,r3,28		/* get esid */
 	cmpldi	cr7,r9,0xc		/* cmp KERNELBASE for later use */
 
-	/* r9 = region, r3 = esid, cr7 = <>KERNELBASE */
-
-	rldicr.	r11,r3,32,16
-	bne-	8f			/* invalid ea bits set */
-	addi	r11,r9,-1
-	cmpldi	r11,0xb
-	blt-	8f			/* invalid region */
+	rldimi	r10,r3,28,0		/* r10= ESID<<28 | entry */
+	oris	r10,r10,SLB_ESID_V@h	/* r10 |= SLB_ESID_V */
 
-	/* r9 = region, r3 = esid, r10 = entry, cr7 = <>KERNELBASE */
+	/* r3 = esid, r10 = esid_data, cr7 = <>KERNELBASE */
 
 	blt	cr7,0f			/* user or kernel? */
 
-	/* kernel address */
+	/* kernel address: proto-VSID = ESID */
+	/* WARNING - MAGIC: we don't use the VSID 0xfffffffff, but
+	 * this code will generate the protoVSID 0xfffffffff for the
+	 * top segment.  That's ok, the scramble below will translate
+	 * it to VSID 0, which is reserved as a bad VSID - one which
+	 * will never have any pages in it.  */
 	li	r11,SLB_VSID_KERNEL
 BEGIN_FTR_SECTION
 	bne	cr7,9f
@@ -102,8 +88,12 @@ BEGIN_FTR_SECTION
 END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
 	b	9f
 
-0:	/* user address */
+0:	/* user address: proto-VSID = context<<15 | ESID */
 	li	r11,SLB_VSID_USER
+
+	srdi.	r9,r3,13
+	bne-	8f			/* invalid ea bits set */
+
 #ifdef CONFIG_HUGETLB_PAGE
 BEGIN_FTR_SECTION
 	/* check against the hugepage ranges */
@@ -125,33 +115,18 @@ END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
 #endif /* CONFIG_HUGETLB_PAGE */
 
 6:	ld	r9,PACACONTEXTID(r13)
+	rldimi	r3,r9,USER_ESID_BITS,0
 
-9:	/* r9 = "context", r3 = esid, r11 = flags, r10 = entry */
-
-	rldimi	r9,r3,15,0		/* r9= VSID ordinal */
-
-7:	rldimi	r10,r3,28,0		/* r10= ESID<<28 | entry */
-	oris	r10,r10,SLB_ESID_V@h	/* r10 |= SLB_ESID_V */
-
-	/* r9 = ordinal, r3 = esid, r11 = flags, r10 = esid_data */
-
-	li	r3,VSID_RANDOMIZER@higher
-	sldi	r3,r3,32
-	oris	r3,r3,VSID_RANDOMIZER@h
-	ori	r3,r3,VSID_RANDOMIZER@l
-
-	mulld	r9,r3,r9		/* r9 = ordinal * VSID_RANDOMIZER */
-	clrldi	r9,r9,28		/* r9 &= VSID_MASK */
-	sldi	r9,r9,SLB_VSID_SHIFT	/* r9 <<= SLB_VSID_SHIFT */
-	or	r9,r9,r11		/* r9 |= flags */
+9:	/* r3 = protovsid, r11 = flags, r10 = esid_data, cr7 = <>KERNELBASE */
+	ASM_VSID_SCRAMBLE(r3,r9)
 
-	/* r9 = vsid_data, r10 = esid_data, cr7 = <>KERNELBASE */
+	rldimi	r11,r3,SLB_VSID_SHIFT,16	/* combine VSID and flags */
 
 	/*
 	 * No need for an isync before or after this slbmte. The exception
 	 * we enter with and the rfid we exit with are context synchronizing.
 	 */
-	slbmte	r9,r10
+	slbmte	r11,r10
 
 	bgelr	cr7			/* we're done for kernel addresses */
 
@@ -174,6 +149,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
 	blr
 
 8:	/* invalid EA */
-	li	r9,0			/* 0 VSID ordinal -> BAD_VSID */
+	li	r3,0			/* BAD_VSID */
 	li	r11,SLB_VSID_USER	/* flags don't much matter */
-	b	7b
+	b	9b
diff --git a/arch/ppc64/mm/tlb.c b/arch/ppc64/mm/tlb.c
index 8825e14cb..aa2d76ca4 100644
--- a/arch/ppc64/mm/tlb.c
+++ b/arch/ppc64/mm/tlb.c
@@ -26,10 +26,10 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/percpu.h>
+#include <linux/hardirq.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
-#include <asm/hardirq.h>
 #include <linux/highmem.h>
 
 DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch);
diff --git a/arch/ppc64/oprofile/common.c b/arch/ppc64/oprofile/common.c
index 391e9afba..bd0dcd2e8 100644
--- a/arch/ppc64/oprofile/common.c
+++ b/arch/ppc64/oprofile/common.c
@@ -52,17 +52,10 @@ static int op_ppc64_setup(void)
 
 static void op_ppc64_shutdown(void)
 {
-	/*
-	 * We need to be sure we have cleared all pending exceptions before
-	 * removing the interrupt handler. For the moment we play it safe and
-	 * leave it in
-	 */
-#if 0
 	mb();
 
 	/* Remove our interrupt handler. We may be removing this module. */
 	perf_irq = save_perf_irq;
-#endif
 }
 
 static void op_ppc64_cpu_start(void *dummy)
@@ -90,6 +83,14 @@ static int op_ppc64_create_files(struct super_block *sb, struct dentry *root)
 {
 	int i;
 
+	/*
+	 * There is one mmcr0, mmcr1 and mmcra for setting the events for
+	 * all of the counters.
+	 */
+	oprofilefs_create_ulong(sb, root, "mmcr0", &sys.mmcr0);
+	oprofilefs_create_ulong(sb, root, "mmcr1", &sys.mmcr1);
+	oprofilefs_create_ulong(sb, root, "mmcra", &sys.mmcra);
+
 	for (i = 0; i < model->num_counters; ++i) {
 		struct dentry *dir;
 		char buf[3];
@@ -112,6 +113,10 @@ static int op_ppc64_create_files(struct super_block *sb, struct dentry *root)
 	oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel);
 	oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user);
 
+	/* Default to tracing both kernel and user */
+	sys.enable_kernel = 1;
+	sys.enable_user = 1;
+
 	return 0;
 }
 
@@ -128,7 +133,7 @@ int __init oprofile_arch_init(struct oprofile_operations **ops)
 {
 	unsigned int pvr;
 
-	pvr = _get_PVR();
+	pvr = mfspr(SPRN_PVR);
 
 	switch (PVR_VER(pvr)) {
 		case PV_630:
diff --git a/arch/ppc64/oprofile/op_impl.h b/arch/ppc64/oprofile/op_impl.h
index aa9c8af60..c936c5ce6 100644
--- a/arch/ppc64/oprofile/op_impl.h
+++ b/arch/ppc64/oprofile/op_impl.h
@@ -19,6 +19,12 @@
 /* freeze counters. set to 1 on a perfmon exception */
 #define MMCR0_FC	(1UL << (31 - 0))
 
+/* freeze in supervisor state */
+#define MMCR0_KERNEL_DISABLE (1UL << (31 - 1))
+
+/* freeze in problem state */
+#define MMCR0_PROBLEM_DISABLE (1UL << (31 - 2))
+
 /* freeze counters while MSR mark = 1 */
 #define MMCR0_FCM1	(1UL << (31 - 3))
 
@@ -28,15 +34,15 @@
 /* freeze counters on enabled condition or event */
 #define MMCR0_FCECE	(1UL << (31 - 6))
 
-/* performance monitor alert has occurred, set to 0 after handling exception */
-#define MMCR0_PMAO	(1UL << (31 - 24))
-
 /* PMC1 count enable*/
 #define MMCR0_PMC1INTCONTROL	(1UL << (31 - 16))
 
 /* PMCn count enable*/
 #define MMCR0_PMCNINTCONTROL	(1UL << (31 - 17))
 
+/* performance monitor alert has occurred, set to 0 after handling exception */
+#define MMCR0_PMAO	(1UL << (31 - 24))
+
 /* state of MSR HV when SIAR set */
 #define MMCRA_SIHV	(1UL << (63 - 35))
 
@@ -60,6 +66,9 @@ struct op_counter_config {
 
 /* System-wide configuration as set via oprofilefs.  */
 struct op_system_config {
+	unsigned long mmcr0;
+	unsigned long mmcr1;
+	unsigned long mmcra;
 	unsigned long enable_kernel;
 	unsigned long enable_user;
 };
diff --git a/arch/ppc64/oprofile/op_model_power4.c b/arch/ppc64/oprofile/op_model_power4.c
index 8a0e7a867..b2a512cdb 100644
--- a/arch/ppc64/oprofile/op_model_power4.c
+++ b/arch/ppc64/oprofile/op_model_power4.c
@@ -17,7 +17,7 @@
 #include <asm/systemcfg.h>
 #include <asm/rtas.h>
 
-#define dbg(args...) printk(args)
+#define dbg(args...)
 
 #include "op_impl.h"
 
@@ -27,6 +27,11 @@ static int num_counters;
 static int oprofile_running;
 static int mmcra_has_sihv;
 
+/* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */
+static u32 mmcr0_val;
+static u64 mmcr1_val;
+static u32 mmcra_val;
+
 static void power4_reg_setup(struct op_counter_config *ctr,
 			     struct op_system_config *sys,
 			     int num_ctrs)
@@ -45,18 +50,36 @@ static void power4_reg_setup(struct op_counter_config *ctr,
 	if (cur_cpu_spec->cpu_features & CPU_FTR_MMCRA_SIHV)
 		mmcra_has_sihv = 1;
 
+	/*
+	 * The performance counter event settings are given in the mmcr0,
+	 * mmcr1 and mmcra values passed from the user in the
+	 * op_system_config structure (sys variable).
+	 */
+	mmcr0_val = sys->mmcr0;
+	mmcr1_val = sys->mmcr1;
+	mmcra_val = sys->mmcra;
+
 	for (i = 0; i < num_counters; ++i)
 		reset_value[i] = 0x80000000UL - ctr[i].count;
 
-	/* XXX setup user and kernel profiling */
+	/* setup user and kernel profiling */
+	if (sys->enable_kernel)
+		mmcr0_val &= ~MMCR0_KERNEL_DISABLE;
+	else
+		mmcr0_val |= MMCR0_KERNEL_DISABLE;
+
+	if (sys->enable_user)
+		mmcr0_val &= ~MMCR0_PROBLEM_DISABLE;
+	else
+		mmcr0_val |= MMCR0_PROBLEM_DISABLE;
 }
 
 extern void ppc64_enable_pmcs(void);
 
 static void power4_cpu_setup(void *unused)
 {
-	unsigned int mmcr0 = mfspr(SPRN_MMCR0);
-	unsigned long mmcra = mfspr(SPRN_MMCRA);
+	unsigned int mmcr0 = mmcr0_val;
+	unsigned long mmcra = mmcra_val;
 
 	ppc64_enable_pmcs();
 
@@ -68,6 +91,8 @@ static void power4_cpu_setup(void *unused)
 	mmcr0 |= MMCR0_PMC1INTCONTROL|MMCR0_PMCNINTCONTROL;
 	mtspr(SPRN_MMCR0, mmcr0);
 
+	mtspr(SPRN_MMCR1, mmcr1_val);
+
 	mmcra |= MMCRA_SAMPLE_ENABLE;
 	mtspr(SPRN_MMCRA, mmcra);
 
diff --git a/arch/ppc64/oprofile/op_model_rs64.c b/arch/ppc64/oprofile/op_model_rs64.c
index 21ceb0b7c..251fdef43 100644
--- a/arch/ppc64/oprofile/op_model_rs64.c
+++ b/arch/ppc64/oprofile/op_model_rs64.c
@@ -15,14 +15,14 @@
 #include <asm/processor.h>
 #include <asm/cputable.h>
 
-#define dbg(args...) printk(args)
+#define dbg(args...)
 
 #include "op_impl.h"
 
 static void ctrl_write(unsigned int i, unsigned int val)
 {
-	unsigned int tmp;
-	unsigned long shift, mask;
+	unsigned int tmp = 0;
+	unsigned long shift = 0, mask = 0;
 
 	dbg("ctrl_write %d %x\n", i, val);
 
diff --git a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c
index d84ac32fa..6ef0b1ec3 100644
--- a/arch/ppc64/xmon/xmon.c
+++ b/arch/ppc64/xmon/xmon.c
@@ -252,30 +252,28 @@ extern inline void sync(void)
 
 static inline void disable_surveillance(void)
 {
-#ifndef CONFIG_PPC_ISERIES
+#ifdef CONFIG_PPC_PSERIES
 	/* Since this can't be a module, args should end up below 4GB. */
 	static struct rtas_args args;
 
-	if (systemcfg->platform & PLATFORM_PSERIES) {
-		/*
-		 * At this point we have got all the cpus we can into
-		 * xmon, so there is hopefully no other cpu calling RTAS
-		 * at the moment, even though we don't take rtas.lock.
-		 * If we did try to take rtas.lock there would be a
-		 * real possibility of deadlock.
-		 */
-		args.token = rtas_token("set-indicator");
-		if (args.token == RTAS_UNKNOWN_SERVICE)
-			return;
-		args.nargs = 3;
-		args.nret = 1;
-		args.rets = &args.args[3];
-		args.args[0] = SURVEILLANCE_TOKEN;
-		args.args[1] = 0;
-		args.args[2] = 0;
-		enter_rtas(__pa(&args));
-	}
-#endif
+	/*
+	 * At this point we have got all the cpus we can into
+	 * xmon, so there is hopefully no other cpu calling RTAS
+	 * at the moment, even though we don't take rtas.lock.
+	 * If we did try to take rtas.lock there would be a
+	 * real possibility of deadlock.
+	 */
+	args.token = rtas_token("set-indicator");
+	if (args.token == RTAS_UNKNOWN_SERVICE)
+		return;
+	args.nargs = 3;
+	args.nret = 1;
+	args.rets = &args.args[3];
+	args.args[0] = SURVEILLANCE_TOKEN;
+	args.args[1] = 0;
+	args.args[2] = 0;
+	enter_rtas(__pa(&args));
+#endif /* CONFIG_PPC_PSERIES */
 }
 
 #ifdef CONFIG_SMP
@@ -2059,7 +2057,7 @@ ppc_inst_dump(unsigned long adr, long count, int praddr)
 {
 	int nr, dotted;
 	unsigned long first_adr;
-	unsigned long inst, last_inst;
+	unsigned long inst, last_inst = 0;
 	unsigned char val[4];
 
 	dotted = 0;
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index d11212073..432c55b05 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -48,34 +48,6 @@ config ARCH_S390_31
 	depends on ARCH_S390X = 'n'
 	default y
 
-choice 
-	prompt "Processor type"
-	default MARCH_G5
-
-config MARCH_G5
-	bool "S/390 model G5 and G6"
-	depends on ARCH_S390_31
-	help
-	  Select this to build a 31 bit kernel that works
-	  on all S/390 and zSeries machines.
-
-config MARCH_Z900
-	bool "IBM eServer zSeries model z800 and z900"
-	help
-	  Select this to optimize for zSeries machines. This
-	  will enable some optimizations that are not available
-	  on older 31 bit only CPUs.
-
-config MARCH_Z990
-	bool "IBM eServer zSeries model z890 and z990"
-	help
-	  Select this enable optimizations for model z890/z990.
-	  This will be slightly faster but does not work on
-	  older machines such as the z900.
-
-endchoice 
-
-
 config SMP
 	bool "Symmetric multi-processing support"
 	---help---
@@ -121,7 +93,7 @@ config MATHEMU
 	depends on MARCH_G5
 	help
 	  This option is required for IEEE compliant floating point arithmetic
-	  on older S/390 machines. Say Y unless you know your machine doesn't 
+	  on older S/390 machines. Say Y unless you know your machine doesn't
 	  need this.
 
 config S390_SUPPORT
@@ -150,13 +122,112 @@ config BINFMT_ELF32
 	  This allows you to run 32-bit Linux/ELF binaries on your zSeries
 	  in 64 bit mode. Everybody wants this; say Y.
 
+comment "Code generation options"
+
+choice
+	prompt "Processor type"
+	default MARCH_G5
+
+config MARCH_G5
+	bool "S/390 model G5 and G6"
+	depends on ARCH_S390_31
+	help
+	  Select this to build a 31 bit kernel that works
+	  on all S/390 and zSeries machines.
+
+config MARCH_Z900
+	bool "IBM eServer zSeries model z800 and z900"
+	help
+	  Select this to optimize for zSeries machines. This
+	  will enable some optimizations that are not available
+	  on older 31 bit only CPUs.
+
+config MARCH_Z990
+	bool "IBM eServer zSeries model z890 and z990"
+	help
+	  Select this enable optimizations for model z890/z990.
+	  This will be slightly faster but does not work on
+	  older machines such as the z900.
+
+endchoice
+
+config PACK_STACK
+	bool "Pack kernel stack"
+	help
+	  This option enables the compiler option -mkernel-backchain if it
+	  is available. If the option is available the compiler supports
+	  the new stack layout which dramatically reduces the minimum stack
+	  frame size. With an old compiler a non-leaf function needs a
+	  minimum of 96 bytes on 31 bit and 160 bytes on 64 bit. With
+	  -mkernel-backchain the minimum size drops to 16 byte on 31 bit
+	  and 24 byte on 64 bit.
+
+	  Say Y if you are unsure.
+
+config SMALL_STACK
+	bool "Use 4kb/8kb for kernel stack instead of 8kb/16kb"
+	depends on PACK_STACK
+	help
+	  If you say Y here and the compiler supports the -mkernel-backchain
+	  option the kernel will use a smaller kernel stack size. For 31 bit
+	  the reduced size is 4kb instead of 8kb and for 64 bit it is 8kb
+	  instead of 16kb. This allows to run more thread on a system and
+	  reduces the pressure on the memory management for higher order
+	  page allocations.
+
+	  Say N if you are unsure.
+
+
+config CHECK_STACK
+	bool "Detect kernel stack overflow"
+	help
+	  This option enables the compiler option -mstack-guard and
+	  -mstack-size if they are available. If the compiler supports them
+	  it will emit additional code to each function prolog to trigger
+	  an illegal operation if the kernel stack is about to overflow.
+
+	  Say N if you are unsure.
+
+config STACK_GUARD
+	int "Size of the guard area (128-1024)"
+	range 128 1024
+	depends on CHECK_STACK
+	default "256"
+	help
+	  This allows you to specify the size of the guard area at the lower
+	  end of the kernel stack. If the kernel stack points into the guard
+	  area on function entry an illegal operation is triggered. The size
+	  needs to be a power of 2. Please keep in mind that the size of an
+	  interrupt frame is 184 bytes for 31 bit and 328 bytes on 64 bit.
+	  The minimum size for the stack guard should be 256 for 31 bit and
+	  512 for 64 bit.
+
+config WARN_STACK
+	bool "Emit compiler warnings for function with broken stack usage"
+	help
+	  This option enables the compiler options -mwarn-framesize and
+	  -mwarn-dynamicstack. If the compiler supports these options it
+	  will generate warnings for function which either use alloca or
+	  create a stack frame bigger then CONFIG_WARN_STACK_SIZE.
+
+	  Say N if you are unsure.
+
+config WARN_STACK_SIZE
+	int "Maximum frame size considered safe (128-2048)"
+	range 128 2048
+	depends on WARN_STACK
+	default "256"
+	help
+	  This allows you to specify the maximum frame size a function may
+	  have without the compiler complaining about it.
+
 comment "I/O subsystem configuration"
 
 config MACHCHK_WARNING
 	bool "Process warning machine checks"
 	help
 	  Select this option if you want the machine check handler on IBM S/390 or
-	  zSeries to process warning machine checks (e.g. on power failures). 
+	  zSeries to process warning machine checks (e.g. on power failures).
 	  If unsure, say "Y".
 
 config QDIO
@@ -388,60 +459,7 @@ source "fs/Kconfig"
 
 source "arch/s390/oprofile/Kconfig"
 
-menu "Kernel hacking"
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config KALLSYMS
-	bool "Load all symbols for debugging/kksymoops"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to let the kernel print out symbolic crash information and
-	  symbolic stack backtraces. This increases the size of the kernel
-	  somewhat, as all symbols have to be loaded into the kernel image.
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  If you don't debug the kernel, you can say N.
-	  
-config DEBUG_SPINLOCK_SLEEP
-	bool "Sleep-inside-spinlock checking"
-	help
-	  If you say Y here, various routines which may sleep will become very
-	  noisy if they are called with a spinlock held.	
-
-endmenu
+source "arch/s390/Kconfig.debug"
 
 source "kernel/vserver/Kconfig"
 
@@ -450,4 +468,3 @@ source "security/Kconfig"
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 68c1a72b0..6d2c7ebc4 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -18,6 +18,7 @@ LDFLAGS		:= -m elf_s390
 CFLAGS		+= -m31
 AFLAGS		+= -m31
 UTS_MACHINE	:= s390
+STACK_SIZE	:= 8192
 endif
 
 ifdef CONFIG_ARCH_S390X
@@ -26,16 +27,37 @@ MODFLAGS	+= -fpic -D__PIC__
 CFLAGS		+= -m64
 AFLAGS		+= -m64
 UTS_MACHINE	:= s390x
+STACK_SIZE	:= 16384
 endif
 
-cflags-$(CONFIG_MARCH_G5)   += $(call check_gcc,-march=g5,)
-cflags-$(CONFIG_MARCH_Z900) += $(call check_gcc,-march=z900,)
-cflags-$(CONFIG_MARCH_Z990) += $(call check_gcc,-march=z990,)
+cflags-$(CONFIG_MARCH_G5)   += $(call cc-option,-march=g5)
+cflags-$(CONFIG_MARCH_Z900) += $(call cc-option,-march=z900)
+cflags-$(CONFIG_MARCH_Z990) += $(call cc-option,-march=z990)
+
+ifeq ($(call cc-option-yn,-mkernel-backchain),y)
+cflags-$(CONFIG_PACK_STACK)  += -mkernel-backchain -D__PACK_STACK
+aflags-$(CONFIG_PACK_STACK)  += -D__PACK_STACK
+cflags-$(CONFIG_SMALL_STACK) += -D__SMALL_STACK
+aflags-$(CONFIG_SMALL_STACK) += -D__SMALL_STACK
+ifdef CONFIG_SMALL_STACK
+STACK_SIZE := $(shell echo $$(($(STACK_SIZE)/2)) )
+endif
+endif
+
+ifeq ($(call cc-option-yn,-mstack-size=8192 -mstack-guard=128),y)
+cflags-$(CONFIG_CHECK_STACK) += -mstack-size=$(STACK_SIZE)
+cflags-$(CONFIG_CHECK_STACK) += -mstack-guard=$(CONFIG_STACK_GUARD)
+endif
+
+ifeq ($(call cc-option-yn,-mwarn-dynamicstack),y)
+cflags-$(CONFIG_WARN_STACK) += -mwarn-dynamicstack
+cflags-$(CONFIG_WARN_STACK) += -mwarn-framesize=$(CONFIG_WARN_STACK_SIZE)
+endif
 
-CFLAGS		+= $(cflags-y)
-CFLAGS		+= $(call check_gcc,-finline-limit=10000,)
+CFLAGS		+= -mbackchain $(cflags-y)
+CFLAGS		+= $(call cc-option,-finline-limit=10000)
 CFLAGS 		+= -pipe -fno-strength-reduce -Wno-sign-compare 
-CFLAGS		+= -mbackchain
+AFLAGS		+= $(aflags-y)
 
 OBJCOPYFLAGS	:= -O binary
 LDFLAGS_vmlinux := -e start
diff --git a/arch/s390/appldata/appldata_mem.c b/arch/s390/appldata/appldata_mem.c
index a21e30846..462ee9a84 100644
--- a/arch/s390/appldata/appldata_mem.c
+++ b/arch/s390/appldata/appldata_mem.c
@@ -102,8 +102,12 @@ static inline void appldata_debug_print(struct appldata_mem_data *mem_data)
  */
 static void appldata_get_mem_data(void *data)
 {
-	struct sysinfo val;
-	struct page_state ps;
+	/*
+	 * don't put large structures on the stack, we are
+	 * serialized through the appldata_ops_lock and can use static
+	 */
+	static struct sysinfo val;
+	static struct page_state ps;
 	struct appldata_mem_data *mem_data;
 
 	mem_data = data;
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index d4cd42c3e..55def7d33 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,5 +1,7 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc3
+# Fri Oct  8 19:17:35 2004
 #
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
@@ -15,6 +17,7 @@ CONFIG_CLEAN_COMPILE=y
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
@@ -36,6 +39,8 @@ CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -56,14 +61,22 @@ CONFIG_KMOD=y
 # CONFIG_ARCH_S390X is not set
 # CONFIG_64BIT is not set
 CONFIG_ARCH_S390_31=y
-CONFIG_MARCH_G5=y
-# CONFIG_MARCH_Z900 is not set
-# CONFIG_MARCH_Z990 is not set
 CONFIG_SMP=y
 CONFIG_NR_CPUS=32
 # CONFIG_HOTPLUG_CPU is not set
 CONFIG_MATHEMU=y
 
+#
+# Code generation options
+#
+CONFIG_MARCH_G5=y
+# CONFIG_MARCH_Z900 is not set
+# CONFIG_MARCH_Z990 is not set
+CONFIG_PACK_STACK=y
+# CONFIG_SMALL_STACK is not set
+# CONFIG_CHECK_STACK is not set
+# CONFIG_WARN_STACK is not set
+
 #
 # I/O subsystem configuration
 #
@@ -130,9 +143,7 @@ CONFIG_SCSI_FC_ATTRS=y
 #
 # SCSI low-level drivers
 #
-# CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_DEBUG is not set
 CONFIG_ZFCP=y
 CONFIG_CCW=y
@@ -154,7 +165,7 @@ CONFIG_BLK_DEV_INITRD=y
 CONFIG_BLK_DEV_XPRAM=m
 # CONFIG_DCSSBLK is not set
 CONFIG_DASD=y
-# CONFIG_DASD_PROFILE is not set
+CONFIG_DASD_PROFILE=y
 CONFIG_DASD_ECKD=y
 CONFIG_DASD_FBA=y
 CONFIG_DASD_DIAG=y
@@ -168,6 +179,7 @@ CONFIG_BLK_DEV_MD=y
 CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
 CONFIG_MD_RAID1=m
+# CONFIG_MD_RAID10 is not set
 CONFIG_MD_RAID5=m
 # CONFIG_MD_RAID6 is not set
 CONFIG_MD_MULTIPATH=m
@@ -236,11 +248,13 @@ CONFIG_IP_MULTICAST=y
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_IPV6=y
 # CONFIG_IPV6_PRIVACY is not set
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_IPV6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 CONFIG_XFRM=y
@@ -419,7 +433,6 @@ CONFIG_RAMFS=y
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -443,6 +456,7 @@ CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
@@ -486,8 +500,8 @@ CONFIG_MSDOS_PARTITION=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_INFO is not set
 
 #
 # Security options
@@ -506,16 +520,18 @@ CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_SHA1_Z990 is not set
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
 # CONFIG_CRYPTO_DES is not set
 # CONFIG_CRYPTO_DES_Z990 is not set
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
 # CONFIG_CRYPTO_SERPENT is not set
-# CONFIG_CRYPTO_AES_GENERIC is not set
+# CONFIG_CRYPTO_AES is not set
 # CONFIG_CRYPTO_CAST5 is not set
 # CONFIG_CRYPTO_CAST6 is not set
 # CONFIG_CRYPTO_TEA is not set
 # CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 892b7e1b0..a19cb59ed 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -6,11 +6,11 @@ EXTRA_AFLAGS	:= -traditional
 
 obj-y	:=  bitmap.o traps.o time.o process.o \
             setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
-            semaphore.o s390_ext.o debug.o profile.o
+            semaphore.o s390_ext.o debug.o profile.o irq.o
 
 extra-$(CONFIG_ARCH_S390_31)	+= head.o 
 extra-$(CONFIG_ARCH_S390X)	+= head64.o 
-extra-y				+= init_task.o vmlinux.lds.s
+extra-y				+= init_task.o vmlinux.lds
 
 obj-$(CONFIG_MODULES)		+= s390_ksyms.o module.o
 obj-$(CONFIG_SMP)		+= smp.o
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index ce2b03578..7537972ac 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -39,5 +39,9 @@ int main(void)
 	DEFINE(__PT_ILC, offsetof(struct pt_regs, ilc),);
 	DEFINE(__PT_TRAP, offsetof(struct pt_regs, trap),);
 	DEFINE(__PT_SIZE, sizeof(struct pt_regs),);
+	BLANK();
+	DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain),);
+	DEFINE(__SF_GPRS, offsetof(struct stack_frame, gprs),);
+	DEFINE(__SF_EMPTY, offsetof(struct stack_frame, empty1),);
 	return 0;
 }
diff --git a/arch/s390/kernel/compat_exec.c b/arch/s390/kernel/compat_exec.c
index 3e781bd77..00974b812 100644
--- a/arch/s390/kernel/compat_exec.c
+++ b/arch/s390/kernel/compat_exec.c
@@ -72,9 +72,9 @@ int setup_arg_pages32(struct linux_binprm *bprm, int executable_stack)
 		mpnt->vm_page_prot = PAGE_COPY;
 		mpnt->vm_flags = VM_STACK_FLAGS;
 		insert_vm_struct(mm, mpnt);
-		// mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
-		vx_vmpages_sub(mm, mm->total_vm -
-			((mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT));
+		// mm->stack_vm = mm->total_vm = vma_pages(mpnt);
+		vx_vmpages_sub(mm, mm->total_vm - vma_pages(mpnt));
+		mm->stack_vm = mm->total_vm;
 	} 
 
 	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 5685c5feb..5c0a63aff 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -725,8 +725,7 @@ sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 __user *uinfo)
 	int ret;
 	mm_segment_t old_fs = get_fs();
 	
-	if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
-	    copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
+	if (copy_siginfo_from_user32(&info, uinfo))
 		return -EFAULT;
 	set_fs (KERNEL_DS);
 	ret = sys_rt_sigqueueinfo(pid, sig, &info);
@@ -1219,7 +1218,7 @@ asmlinkage long sys32_clone(struct pt_regs regs)
 	child_tidptr = (int *) (regs.gprs[5] & 0x7fffffffUL);
         if (!newsp)
                 newsp = regs.gprs[15];
-        return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0,
+        return do_fork(clone_flags, newsp, &regs, 0,
 		       parent_tidptr, child_tidptr);
 }
 
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index e8c8b2fe7..f29bcb856 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -118,10 +118,10 @@ int copy_siginfo_from_user32(siginfo_t *to, siginfo_t32 __user *from)
 	err |= __get_user(to->si_errno, &from->si_errno);
 	err |= __get_user(to->si_code, &from->si_code);
 
-	if (from->si_code < 0)
+	if (to->si_code < 0)
 		err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
 	else {
-		switch (from->si_code >> 16) {
+		switch (to->si_code >> 16) {
 		case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */
 		case __SI_MESGQ >> 16:
 			err |= __get_user(to->si_int, &from->si_int);
@@ -218,14 +218,17 @@ sys32_sigaction(int sig, const struct old_sigaction32 __user *act,
 		 struct old_sigaction32 __user *oact)
 {
         struct k_sigaction new_ka, old_ka;
+	unsigned long sa_handler, sa_restorer;
         int ret;
 
         if (act) {
 		compat_old_sigset_t mask;
 		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
-		    __get_user((unsigned long)new_ka.sa.sa_handler, &act->sa_handler) ||
-		    __get_user((unsigned long)new_ka.sa.sa_restorer, &act->sa_restorer))
+		    __get_user(sa_handler, &act->sa_handler) ||
+		    __get_user(sa_restorer, &act->sa_restorer))
 			return -EFAULT;
+		new_ka.sa.sa_handler = (__sighandler_t) sa_handler;
+		new_ka.sa.sa_restorer = (void (*)(void)) sa_restorer;
 		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
 		__get_user(mask, &act->sa_mask);
 		siginitset(&new_ka.sa.sa_mask, mask);
@@ -234,9 +237,11 @@ sys32_sigaction(int sig, const struct old_sigaction32 __user *act,
         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 
 	if (!ret && oact) {
+		sa_handler = (unsigned long) old_ka.sa.sa_handler;
+		sa_restorer = (unsigned long) old_ka.sa.sa_restorer;
 		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
-		    __put_user((unsigned long)old_ka.sa.sa_handler, &oact->sa_handler) ||
-		    __put_user((unsigned long)old_ka.sa.sa_restorer, &oact->sa_restorer))
+		    __put_user(sa_handler, &oact->sa_handler) ||
+		    __put_user(sa_restorer, &oact->sa_restorer))
 			return -EFAULT;
 		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
 		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
@@ -253,6 +258,7 @@ sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
 	   struct sigaction32 __user *oact,  size_t sigsetsize)
 {
 	struct k_sigaction new_ka, old_ka;
+	unsigned long sa_handler;
 	int ret;
 	compat_sigset_t set32;
 
@@ -261,7 +267,7 @@ sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
 		return -EINVAL;
 
 	if (act) {
-		ret = get_user((unsigned long)new_ka.sa.sa_handler, &act->sa_handler);
+		ret = get_user(sa_handler, &act->sa_handler);
 		ret |= __copy_from_user(&set32, &act->sa_mask,
 					sizeof(compat_sigset_t));
 		switch (_NSIG_WORDS) {
@@ -278,6 +284,7 @@ sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
 		
 		if (ret)
 			return -EFAULT;
+		new_ka.sa.sa_handler = (__sighandler_t) sa_handler;
 	}
 
 	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
@@ -311,17 +318,19 @@ sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss,
 							struct pt_regs *regs)
 {
 	stack_t kss, koss;
+	unsigned long ss_sp;
 	int ret, err = 0;
 	mm_segment_t old_fs = get_fs();
 
 	if (uss) {
 		if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
 			return -EFAULT;
-		err |= __get_user((unsigned long) kss.ss_sp, &uss->ss_sp);
+		err |= __get_user(ss_sp, &uss->ss_sp);
 		err |= __get_user(kss.ss_size, &uss->ss_size);
 		err |= __get_user(kss.ss_flags, &uss->ss_flags);
 		if (err)
 			return -EFAULT;
+		kss.ss_sp = (void *) ss_sp;
 	}
 
 	set_fs (KERNEL_DS);
@@ -333,7 +342,8 @@ sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss,
 	if (!ret && uoss) {
 		if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
 			return -EFAULT;
-		err |= __put_user((unsigned long) koss.ss_sp, &uoss->ss_sp);
+		ss_sp = (unsigned long) koss.ss_sp;
+		err |= __put_user(ss_sp, &uoss->ss_sp);
 		err |= __put_user(koss.ss_size, &uoss->ss_size);
 		err |= __put_user(koss.ss_flags, &uoss->ss_flags);
 		if (err)
@@ -552,9 +562,7 @@ static void setup_frame32(int sig, struct k_sigaction *ka,
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -604,9 +612,7 @@ static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 /*
@@ -614,20 +620,15 @@ give_sigsegv:
  */	
 
 void
-handle_signal32(unsigned long sig, siginfo_t *info, sigset_t *oldset,
-	struct pt_regs * regs)
+handle_signal32(unsigned long sig, struct k_sigaction *ka,
+		siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
 {
-	struct k_sigaction *ka = &current->sighand->action[sig-1];
-
 	/* Set up the stack frame */
 	if (ka->sa.sa_flags & SA_SIGINFO)
 		setup_rt_frame32(sig, ka, info, oldset, regs);
 	else
 		setup_frame32(sig, ka, oldset, regs);
 
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
-
 	if (!(ka->sa.sa_flags & SA_NODEFER)) {
 		spin_lock_irq(&current->sighand->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index f1e538c9d..8669d6c3e 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -24,7 +24,6 @@
 
 #include <asm/debug.h>
 
-#define MIN(a,b) (((a)<(b))?(a):(b))
 #define DEBUG_PROLOG_ENTRY -1
 
 /* typedefs */
@@ -435,7 +434,7 @@ static ssize_t debug_output(struct file *file,		/* file descriptor */
 
 	while(count < len){
 		size = debug_format_entry(p_info);
-		size = MIN((len - count), (size - entry_offset));
+		size = min((len - count), (size - entry_offset));
 
 		if(size){
 			if (copy_to_user(user_buf + count, 
@@ -723,7 +722,7 @@ debug_entry_t *debug_event_common(debug_info_t * id, int level, const void *buf,
 	spin_lock_irqsave(&id->lock, flags);
 	active = get_active_entry(id);
 	memset(DEBUG_DATA(active), 0, id->buf_size);
-	memcpy(DEBUG_DATA(active), buf, MIN(len, id->buf_size));
+	memcpy(DEBUG_DATA(active), buf, min(len, id->buf_size));
 	debug_finish_entry(id, active, level, 0);
 	spin_unlock_irqrestore(&id->lock, flags);
 
@@ -744,7 +743,7 @@ debug_entry_t *debug_exception_common(debug_info_t * id, int level,
 	spin_lock_irqsave(&id->lock, flags);
 	active = get_active_entry(id);
 	memset(DEBUG_DATA(active), 0, id->buf_size);
-	memcpy(DEBUG_DATA(active), buf, MIN(len, id->buf_size));
+	memcpy(DEBUG_DATA(active), buf, min(len, id->buf_size));
 	debug_finish_entry(id, active, level, 1);
 	spin_unlock_irqrestore(&id->lock, flags);
 
@@ -789,7 +788,7 @@ debug_entry_t *debug_sprintf_event(debug_info_t* id,
 	curr_event=(debug_sprintf_entry_t *) DEBUG_DATA(active);
 	va_start(ap,string);
 	curr_event->string=string;
-	for(idx=0;idx<MIN(numargs,((id->buf_size / sizeof(long))-1));idx++)
+	for(idx=0;idx<min(numargs,(int)(id->buf_size / sizeof(long))-1);idx++)
 		curr_event->args[idx]=va_arg(ap,long);
 	va_end(ap);
 	debug_finish_entry(id, active, level, 0);
@@ -821,7 +820,7 @@ debug_entry_t *debug_sprintf_exception(debug_info_t* id,
 	curr_event=(debug_sprintf_entry_t *)DEBUG_DATA(active);
 	va_start(ap,string);
 	curr_event->string=string;
-	for(idx=0;idx<MIN(numargs,((id->buf_size / sizeof(long))-1));idx++)
+	for(idx=0;idx<min(numargs,(int)(id->buf_size / sizeof(long))-1);idx++)
 		curr_event->args[idx]=va_arg(ap,long);
 	va_end(ap);
 	debug_finish_entry(id, active, level, 1);
@@ -1157,7 +1156,7 @@ int debug_sprintf_format_fn(debug_info_t * id, struct debug_view *view,
 	}
 
 	/* number of arguments used for sprintf (without the format string) */
-	num_used_args   = MIN(DEBUG_SPRINTF_MAX_ARGS, (num_longs - 1));
+	num_used_args   = min(DEBUG_SPRINTF_MAX_ARGS, (num_longs - 1));
 
 	memset(index,0, DEBUG_SPRINTF_MAX_ARGS * sizeof(int));
 
diff --git a/arch/s390/kernel/ebcdic.c b/arch/s390/kernel/ebcdic.c
index 52d5a78b5..bb0f97313 100644
--- a/arch/s390/kernel/ebcdic.c
+++ b/arch/s390/kernel/ebcdic.c
@@ -391,10 +391,10 @@ __u8 _ebc_toupper[256] =
 	0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
 };
 
-EXPORT_SYMBOL_NOVERS(_ascebc_500);
-EXPORT_SYMBOL_NOVERS(_ebcasc_500);
-EXPORT_SYMBOL_NOVERS(_ascebc);
-EXPORT_SYMBOL_NOVERS(_ebcasc);
-EXPORT_SYMBOL_NOVERS(_ebc_tolower);
-EXPORT_SYMBOL_NOVERS(_ebc_toupper);
+EXPORT_SYMBOL(_ascebc_500);
+EXPORT_SYMBOL(_ebcasc_500);
+EXPORT_SYMBOL(_ascebc);
+EXPORT_SYMBOL(_ebcasc);
+EXPORT_SYMBOL(_ebc_tolower);
+EXPORT_SYMBOL(_ebc_toupper);
 
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 1f87bf29c..06312d09c 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -19,6 +19,7 @@
 #include <asm/thread_info.h>
 #include <asm/offsets.h>
 #include <asm/unistd.h>
+#include <asm/page.h>
 
 /*
  * Stack layout for the system_call stack entry.
@@ -52,6 +53,9 @@ _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
 		 _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
 _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
 
+STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
+STACK_SIZE  = 1 << STACK_SHIFT
+
 #define BASED(name) name-system_call(%r13)
 
 /*
@@ -86,10 +90,16 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
 	bnz	BASED(1f)
 0:	l	%r14,__LC_ASYNC_STACK	# are we already on the async stack ?
 	slr	%r14,%r15
-	sra	%r14,13
+	sra	%r14,STACK_SHIFT
 	be	BASED(2f)
 1:	l	%r15,__LC_ASYNC_STACK
 	.endif
+#ifdef CONFIG_CHECK_STACK
+	b	BASED(3f)
+2:	tml	%r15,STACK_SIZE - CONFIG_STACK_GUARD
+	bz	BASED(stack_overflow)
+3:
+#endif
 2:	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
 	mvc	SP_PSW(8,%r15),0(%r12)	# move user PSW to stack
 	la	%r12,\psworg
@@ -99,7 +109,7 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
 	st	%r12,SP_ILC(%r15)
 	mvc	SP_R12(16,%r15),\savearea # move %r12-%r15 to stack
 	la	%r12,0
-	st	%r12,0(%r15)		# clear back chain
+	st	%r12,__SF_BACKCHAIN(%r15)	# clear back chain
 	.endm
 
 	.macro  RESTORE_ALL sync
@@ -124,46 +134,22 @@ __switch_to:
 __switch_to_base:
 	tm	__THREAD_per(%r3),0xe8		# new process is using per ?
 	bz	__switch_to_noper-__switch_to_base(%r1)	# if not we're fine
-        stctl   %c9,%c11,24(%r15)		# We are using per stuff
-        clc     __THREAD_per(12,%r3),24(%r15)
+        stctl   %c9,%c11,__SF_EMPTY(%r15)	# We are using per stuff
+        clc     __THREAD_per(12,%r3),__SF_EMPTY(%r15)
         be      __switch_to_noper-__switch_to_base(%r1)	# we got away w/o bashing TLB's
         lctl    %c9,%c11,__THREAD_per(%r3)	# Nope we didn't
 __switch_to_noper:
-        stm     %r6,%r15,24(%r15)       # store __switch_to registers of prev task
+        stm     %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
 	st	%r15,__THREAD_ksp(%r2)	# store kernel stack to prev->tss.ksp
 	l	%r15,__THREAD_ksp(%r3)	# load kernel stack from next->tss.ksp
-	lm	%r6,%r15,24(%r15)	# load __switch_to registers of next task
+	lm	%r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task
 	st	%r3,__LC_CURRENT	# __LC_CURRENT = current task struct
 	l	%r3,__THREAD_info(%r3)  # load thread_info from task struct
 	st	%r3,__LC_THREAD_INFO
-	ahi	%r3,8192
+	ahi	%r3,STACK_SIZE
 	st	%r3,__LC_KERNEL_STACK	# __LC_KERNEL_STACK = new kernel stack
 	br	%r14
 
-/*
- * do_softirq calling function. We want to run the softirq functions on the
- * asynchronous interrupt stack.
- */
-	.global do_call_softirq
-do_call_softirq:
-	stnsm	24(%r15),0xfc
-	stm	%r12,%r15,28(%r15)
-	lr	%r12,%r15
-        basr    %r13,0
-do_call_base:
-	l	%r0,__LC_ASYNC_STACK
-	slr     %r0,%r15
-	sra	%r0,13
-	be	0f-do_call_base(%r13)
-	l	%r15,__LC_ASYNC_STACK
-0:	sl	%r15,.Lc_overhead-do_call_base(%r13)
-        st	%r12,0(%r15)	# store backchain
-	l	%r1,.Ldo_softirq-do_call_base(%r13)
-	basr	%r14,%r1
-	lm	%r12,%r15,28(%r12)
-	ssm	24(%r15)
-	br	%r14
-	
 __critical_start:
 /*
  * SVC interrupt handler routine. System calls are synchronous events and
@@ -304,9 +290,12 @@ sysc_tracenogo:
 ret_from_fork:
 	l	%r13,__LC_SVC_NEW_PSW+4
 	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
-        l       %r1,BASED(.Lschedtail)
+	tm	SP_PSW+1(%r15),0x01	# forking a kernel thread ?
+	bo	BASED(0f)
+	st	%r15,SP_R15(%r15)	# store stack pointer for new kthread
+0:	l       %r1,BASED(.Lschedtail)
 	basr    %r14,%r1
-        stosm   24(%r15),0x03     # reenable interrupts
+        stosm   __SF_EMPTY(%r15),0x03     # reenable interrupts
 	b	BASED(sysc_return)
 
 #
@@ -457,7 +446,7 @@ pgm_svcper:
 	mvc	__THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS
 	mvc	__THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
 	oi	__TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
-	stosm	24(%r15),0x03		# reenable interrupts
+	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
 	b	BASED(sysc_do_svc)
 
 /*
@@ -493,16 +482,16 @@ io_preempt:
 	l	%r1,SP_R15(%r15)
 	s	%r1,BASED(.Lc_spsize)
 	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
-        xc      0(4,%r1),0(%r1)        # clear back chain
+        xc      __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
 	lr	%r15,%r1
 io_resume_loop:
 	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED
 	bno	BASED(io_leave)
 	mvc     __TI_precount(4,%r9),BASED(.Lc_pactive)
-        stosm   24(%r15),0x03          # reenable interrupts
+        stosm   __SF_EMPTY(%r15),0x03  # reenable interrupts
         l       %r1,BASED(.Lschedule)
 	basr	%r14,%r1	       # call schedule
-        stnsm   24(%r15),0xfc          # disable I/O and ext. interrupts
+        stnsm   __SF_EMPTY(%r15),0xfc  # disable I/O and ext. interrupts
 	xc      __TI_precount(4,%r9),__TI_precount(%r9)
 	b	BASED(io_resume_loop)
 #endif
@@ -514,7 +503,7 @@ io_work:
 	l	%r1,__LC_KERNEL_STACK
 	s	%r1,BASED(.Lc_spsize)
 	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
-        xc      0(4,%r1),0(%r1)        # clear back chain
+        xc      __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
 	lr	%r15,%r1
 #
 # One of the work bits is on. Find out which one.
@@ -532,9 +521,9 @@ io_work_loop:
 #	
 io_reschedule:        
         l       %r1,BASED(.Lschedule)
-        stosm   24(%r15),0x03          # reenable interrupts
+        stosm   __SF_EMPTY(%r15),0x03  # reenable interrupts
 	basr    %r14,%r1	       # call scheduler
-        stnsm   24(%r15),0xfc          # disable I/O and ext. interrupts
+        stnsm   __SF_EMPTY(%r15),0xfc  # disable I/O and ext. interrupts
 	tm	__TI_flags+3(%r9),_TIF_WORK_INT
 	bz	BASED(io_leave)        # there is no work to do
 	b	BASED(io_work_loop)
@@ -543,12 +532,12 @@ io_reschedule:
 # _TIF_SIGPENDING is set, call do_signal
 #
 io_sigpending:     
-        stosm   24(%r15),0x03          # reenable interrupts
+        stosm   __SF_EMPTY(%r15),0x03  # reenable interrupts
         la      %r2,SP_PTREGS(%r15)    # load pt_regs
         sr      %r3,%r3                # clear *oldset
         l       %r1,BASED(.Ldo_signal)
 	basr    %r14,%r1	       # call do_signal
-        stnsm   24(%r15),0xfc          # disable I/O and ext. interrupts
+        stnsm   __SF_EMPTY(%r15),0xfc  # disable I/O and ext. interrupts
 	b	BASED(io_leave)        # out of here, do NOT recheck
 
 /*
@@ -589,8 +578,8 @@ restart_int_handler:
         l       %r15,__LC_SAVE_AREA+60 # load ksp
         lctl    %c0,%c15,__LC_CREGS_SAVE_AREA # get new ctl regs
         lam     %a0,%a15,__LC_AREGS_SAVE_AREA
-        stosm   0(%r15),0x04           # now we can turn dat on
-        lm      %r6,%r15,24(%r15)      # load registers from clone
+        lm      %r6,%r15,__SF_GPRS(%r15) # load registers from clone
+        stosm   __SF_EMPTY(%r15),0x04    # now we can turn dat on
         basr    %r14,0
         l       %r14,restart_addr-.(%r14)
         br      %r14                   # branch to start_secondary
@@ -611,6 +600,31 @@ restart_crash:
 restart_go:
 #endif
 
+#ifdef CONFIG_CHECK_STACK
+/*
+ * The synchronous or the asynchronous stack overflowed. We are dead.
+ * No need to properly save the registers, we are going to panic anyway.
+ * Setup a pt_regs so that show_trace can provide a good call trace.
+ */
+stack_overflow:
+	l	%r15,__LC_PANIC_STACK	# change to panic stack
+	sl	%r15,BASED(.Lc_spsize)
+	mvc	SP_PSW(8,%r15),0(%r12)	# move user PSW to stack
+	stm	%r0,%r11,SP_R0(%r15)	# store gprs %r0-%r11 to kernel stack
+	la	%r1,__LC_SAVE_AREA
+	ch	%r12,BASED(.L0x020)	# old psw addr == __LC_SVC_OLD_PSW ?
+	be	BASED(0f)
+	ch	%r12,BASED(.L0x028)	# old psw addr == __LC_PGM_OLD_PSW ?
+	be	BASED(0f)
+	la	%r1,__LC_SAVE_AREA+16
+0:	mvc	SP_R12(16,%r15),0(%r1)	# move %r12-%r15 to stack
+        xc      __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear back chain
+	l	%r1,BASED(1f)		# branch to kernel_stack_overflow
+        la      %r2,SP_PTREGS(%r15)	# load pt_regs
+	br	%r1
+1:	.long  kernel_stack_overflow
+#endif
+
 cleanup_table_system_call:
 	.long	system_call + 0x80000000, sysc_do_svc + 0x80000000
 cleanup_table_sysc_return:
@@ -695,7 +709,6 @@ cleanup_sysc_leave_lpsw:
 .Ldo_IRQ:      .long  do_IRQ
 .Ldo_extint:   .long  do_extint
 .Ldo_signal:   .long  do_signal
-.Ldo_softirq:  .long  do_softirq
 .Lhandle_per:  .long  do_single_step
 .Ljump_table:  .long  pgm_check_table
 .Lschedule:    .long  schedule
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 54190092b..10056f2b1 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -19,6 +19,7 @@
 #include <asm/thread_info.h>
 #include <asm/offsets.h>
 #include <asm/unistd.h>
+#include <asm/page.h>
 
 /*
  * Stack layout for the system_call stack entry.
@@ -48,6 +49,9 @@ SP_ILC       =  STACK_FRAME_OVERHEAD + __PT_ILC
 SP_TRAP      =  STACK_FRAME_OVERHEAD + __PT_TRAP
 SP_SIZE      =  STACK_FRAME_OVERHEAD + __PT_SIZE
 
+STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
+STACK_SIZE  = 1 << STACK_SHIFT
+
 _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
 		 _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
 _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
@@ -85,10 +89,16 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
 	jnz	1f
 0:	lg	%r14,__LC_ASYNC_STACK	# are we already on the async. stack ?
 	slgr	%r14,%r15
-	srag	%r14,%r14,14
+	srag	%r14,%r14,STACK_SHIFT
 	jz	2f
 1:	lg	%r15,__LC_ASYNC_STACK	# load async stack
 	.endif
+#ifdef CONFIG_CHECK_STACK
+	j	3f
+2:	tml	%r15,STACK_SIZE - CONFIG_STACK_GUARD
+	jz	stack_overflow
+3:
+#endif
 2:	aghi    %r15,-SP_SIZE		# make room for registers & psw
 	mvc     SP_PSW(16,%r15),0(%r12)	# move user PSW to stack
 	la	%r12,\psworg
@@ -98,7 +108,7 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
 	st	%r12,SP_ILC(%r15)
 	mvc	SP_R12(32,%r15),\savearea # move %r12-%r15 to stack
 	la	%r12,0
-	stg	%r12,0(%r15)
+	stg	%r12,__SF_BACKCHAIN(%r15)
         .endm
 
 	.macro	RESTORE_ALL sync
@@ -121,43 +131,22 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
 __switch_to:
 	tm	__THREAD_per+4(%r3),0xe8 # is the new process using per ?
 	jz	__switch_to_noper		# if not we're fine
-        stctg   %c9,%c11,48(%r15)       # We are using per stuff
-        clc     __THREAD_per(24,%r3),48(%r15)
+        stctg   %c9,%c11,__SF_EMPTY(%r15)# We are using per stuff
+        clc     __THREAD_per(24,%r3),__SF_EMPTY(%r15)
         je      __switch_to_noper            # we got away without bashing TLB's
         lctlg   %c9,%c11,__THREAD_per(%r3)	# Nope we didn't
 __switch_to_noper:
-        stmg    %r6,%r15,48(%r15)       # store __switch_to registers of prev task
+        stmg    %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
 	stg	%r15,__THREAD_ksp(%r2)	# store kernel stack to prev->tss.ksp
 	lg	%r15,__THREAD_ksp(%r3)	# load kernel stack from next->tss.ksp
-        lmg     %r6,%r15,48(%r15)       # load __switch_to registers of next task
+        lmg     %r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task
 	stg	%r3,__LC_CURRENT	# __LC_CURRENT = current task struct
 	lg	%r3,__THREAD_info(%r3)  # load thread_info from task struct
 	stg	%r3,__LC_THREAD_INFO
-	aghi	%r3,16384
+	aghi	%r3,STACK_SIZE
 	stg	%r3,__LC_KERNEL_STACK	# __LC_KERNEL_STACK = new kernel stack
 	br	%r14
 
-/*
- * do_softirq calling function. We want to run the softirq functions on the
- * asynchronous interrupt stack.
- */
-	.global do_call_softirq
-do_call_softirq:
-	stnsm	48(%r15),0xfc
-	stmg	%r12,%r15,56(%r15)
-	lgr	%r12,%r15
-	lg	%r0,__LC_ASYNC_STACK
-	slgr    %r0,%r15
-	srag	%r0,%r0,14
-	je	0f
-	lg	%r15,__LC_ASYNC_STACK
-0:	aghi	%r15,-STACK_FRAME_OVERHEAD
-	stg	%r12,0(%r15)		# store back chain
-	brasl	%r14,do_softirq
-	lmg	%r12,%r15,56(%r12)
-	ssm	48(%r15)
-	br	%r14
-
 __critical_start:
 /*
  * SVC interrupt handler routine. System calls are synchronous events and
@@ -304,7 +293,10 @@ sysc_tracenogo:
 ret_from_fork:
 	lg	%r13,__LC_SVC_NEW_PSW+8
 	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
-        brasl   %r14,schedule_tail
+	tm	SP_PSW+1(%r15),0x01	# forking a kernel thread ?
+	jo	0f
+	stg	%r15,SP_R15(%r15)	# store stack pointer for new kthread
+0:	brasl   %r14,schedule_tail
         stosm   24(%r15),0x03     # reenable interrupts
 	j	sysc_return
 
@@ -504,7 +496,7 @@ pgm_svcper:
 	mvc	__THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS
 	mvc	__THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID
 	oi	__TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP
-	stosm	48(%r15),0x03		# reenable interrupts
+	stosm	__SF_EMPTY(%r15),0x03	# reenable interrupts
 	j	sysc_do_svc
 
 /*
@@ -539,16 +531,16 @@ io_preempt:
 	lg	%r1,SP_R15(%r15)
 	aghi	%r1,-SP_SIZE
 	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
-        xc      0(8,%r1),0(%r1)        # clear back chain
+        xc      __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
 	lgr	%r15,%r1
 io_resume_loop:
 	tm	__TI_flags+7(%r9),_TIF_NEED_RESCHED
 	jno	io_leave
 	larl    %r1,.Lc_pactive
 	mvc     __TI_precount(4,%r9),0(%r1)
-        stosm   48(%r15),0x03          # reenable interrupts
+        stosm   __SF_EMPTY(%r15),0x03   # reenable interrupts
 	brasl   %r14,schedule          # call schedule
-        stnsm   48(%r15),0xfc          # disable I/O and ext. interrupts
+        stnsm   __SF_EMPTY(%r15),0xfc   # disable I/O and ext. interrupts
 	xc      __TI_precount(4,%r9),__TI_precount(%r9)
 	j	io_resume_loop
 #endif
@@ -560,7 +552,7 @@ io_work:
 	lg	%r1,__LC_KERNEL_STACK
 	aghi	%r1,-SP_SIZE
 	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
-        xc      0(8,%r1),0(%r1)        # clear back chain
+        xc      __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
 	lgr	%r15,%r1
 #
 # One of the work bits is on. Find out which one.
@@ -577,23 +569,23 @@ io_work_loop:
 # _TIF_NEED_RESCHED is set, call schedule
 #	
 io_reschedule:        
-        stosm   48(%r15),0x03       # reenable interrupts
-        brasl   %r14,schedule       # call scheduler
-        stnsm   48(%r15),0xfc       # disable I/O and ext. interrupts
+	stosm   __SF_EMPTY(%r15),0x03	# reenable interrupts
+	brasl   %r14,schedule		# call scheduler
+	stnsm   __SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts
 	tm	__TI_flags+7(%r9),_TIF_WORK_INT
-	jz	io_leave               # there is no work to do
+	jz	io_leave		# there is no work to do
 	j	io_work_loop
 
 #
 # _TIF_SIGPENDING is set, call do_signal
 #
 io_sigpending:     
-        stosm   48(%r15),0x03       # reenable interrupts
-        la      %r2,SP_PTREGS(%r15) # load pt_regs
-        slgr    %r3,%r3             # clear *oldset
-	brasl	%r14,do_signal      # call do_signal
-        stnsm   48(%r15),0xfc       # disable I/O and ext. interrupts
-	j	sysc_leave          # out of here, do NOT recheck
+	stosm   __SF_EMPTY(%r15),0x03	# reenable interrupts
+	la      %r2,SP_PTREGS(%r15)	# load pt_regs
+	slgr    %r3,%r3			# clear *oldset
+	brasl	%r14,do_signal		# call do_signal
+	stnsm   __SF_EMPTY(%r15),0xfc	# disable I/O and ext. interrupts
+	j	sysc_leave		# out of here, do NOT recheck
 
 /*
  * External interrupt handler routine
@@ -631,8 +623,8 @@ restart_int_handler:
         lctlg   %c0,%c15,0(%r10) # get new ctl regs
         lghi    %r10,__LC_AREGS_SAVE_AREA
         lam     %a0,%a15,0(%r10)
-        stosm   0(%r15),0x04           # now we can turn dat on
-        lmg     %r6,%r15,48(%r15)      # load registers from clone
+        lmg     %r6,%r15,__SF_GPRS(%r15) # load registers from clone
+        stosm   __SF_EMPTY(%r15),0x04    # now we can turn dat on
 	jg      start_secondary
 #else
 /*
@@ -649,6 +641,29 @@ restart_crash:
 restart_go:
 #endif
 
+#ifdef CONFIG_CHECK_STACK
+/*
+ * The synchronous or the asynchronous stack overflowed. We are dead.
+ * No need to properly save the registers, we are going to panic anyway.
+ * Setup a pt_regs so that show_trace can provide a good call trace.
+ */
+stack_overflow:
+	lg	%r15,__LC_PANIC_STACK	# change to panic stack
+	aghi	%r1,-SP_SIZE
+	mvc	SP_PSW(16,%r15),0(%r12)	# move user PSW to stack
+	stmg	%r0,%r11,SP_R0(%r15)	# store gprs %r0-%r11 to kernel stack
+	la	%r1,__LC_SAVE_AREA
+	chi	%r12,__LC_SVC_OLD_PSW
+	je	0f
+	chi	%r12,__LC_PGM_OLD_PSW
+	je	0f
+	la	%r1,__LC_SAVE_AREA+16
+0:	mvc	SP_R12(32,%r15),0(%r1)  # move %r12-%r15 to stack
+        xc      __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # clear back chain
+        la      %r2,SP_PTREGS(%r15)	# load pt_regs
+	jg	kernel_stack_overflow
+#endif
+
 cleanup_table_system_call:
 	.quad	system_call, sysc_do_svc
 cleanup_table_sysc_return:
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index fb295b79f..b804c55bd 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -31,6 +31,8 @@
 #include <asm/setup.h>
 #include <asm/lowcore.h>
 #include <asm/offsets.h>
+#include <asm/thread_info.h>
+#include <asm/page.h>
 
 #ifndef CONFIG_IPL
         .org   0
@@ -741,10 +743,10 @@ _stext:	basr  %r13,0                    # get base
 #
         l     %r15,.Linittu-.LPG2(%r13)
 	mvc   __LC_CURRENT(4),__TI_task(%r15)
-        ahi   %r15,8192                 # init_task_union + 8192
+        ahi   %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE
         st    %r15,__LC_KERNEL_STACK    # set end of kernel stack
         ahi   %r15,-96
-        xc    0(4,%r15),0(%r15)         # set backchain to zero
+        xc    __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
 
 # check control registers
         stctl  %c0,%c15,0(%r15)
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index e32a8e90f..8366793bc 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -31,6 +31,8 @@
 #include <asm/setup.h>
 #include <asm/lowcore.h>
 #include <asm/offsets.h>
+#include <asm/thread_info.h>
+#include <asm/page.h>
 
 #ifndef CONFIG_IPL
         .org   0
@@ -741,10 +743,10 @@ _stext:	basr  %r13,0                    # get base
 	larl  %r15,init_thread_union
 	lg    %r14,__TI_task(%r15)      # cache current in lowcore
 	stg   %r14,__LC_CURRENT
-        aghi  %r15,16384                # init_task_union + 16384
+        aghi  %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE
         stg   %r15,__LC_KERNEL_STACK    # set end of kernel stack
         aghi  %r15,-160
-        xc    0(8,%r15),0(%r15)         # set backchain to zero
+        xc    __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
 
 # check control registers
         stctg  %c0,%c15,0(%r15)
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 73cb6baeb..5d56e77c7 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -58,14 +58,11 @@ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
  */
 unsigned long thread_saved_pc(struct task_struct *tsk)
 {
-	unsigned long bc;
+	struct stack_frame *sf;
 
-	bc = *((unsigned long *) tsk->thread.ksp);
-#ifndef CONFIG_ARCH_S390X
-	return *((unsigned long *) (bc+56));
-#else
-	return *((unsigned long *) (bc+112));
-#endif
+	sf = (struct stack_frame *) tsk->thread.ksp;
+	sf = (struct stack_frame *) sf->back_chain;
+	return sf->gprs[8];
 }
 
 /*
@@ -186,41 +183,20 @@ void show_regs(struct pt_regs *regs)
 
 extern void kernel_thread_starter(void);
 
-#ifndef CONFIG_ARCH_S390X
-
 __asm__(".align 4\n"
 	"kernel_thread_starter:\n"
-	"    l     15,0(8)\n"
-	"    sr    15,7\n"
-	"    stosm 24(15),3\n"
-	"    lr    2,10\n"
+	"    la    2,0(10)\n"
 	"    basr  14,9\n"
-	"    sr    2,2\n"
+	"    la    2,0\n"
 	"    br    11\n");
 
-#else /* CONFIG_ARCH_S390X */
-
-__asm__(".align 4\n"
-	"kernel_thread_starter:\n"
-	"    lg    15,0(8)\n"
-	"    sgr   15,7\n"
-	"    stosm 48(15),3\n"
-	"    lgr   2,10\n"
-	"    basr  14,9\n"
-	"    sgr   2,2\n"
-	"    br    11\n");
-
-#endif /* CONFIG_ARCH_S390X */
-
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {
 	struct pt_regs regs;
 
 	memset(&regs, 0, sizeof(regs));
-	regs.psw.mask = PSW_KERNEL_BITS;
+	regs.psw.mask = PSW_KERNEL_BITS | PSW_MASK_IO | PSW_MASK_EXT;
 	regs.psw.addr = (unsigned long) kernel_thread_starter | PSW_ADDR_AMODE;
-	regs.gprs[7] = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
-	regs.gprs[8] = __LC_KERNEL_STACK;
 	regs.gprs[9] = (unsigned long) fn;
 	regs.gprs[10] = (unsigned long) arg;
 	regs.gprs[11] = (unsigned long) do_exit;
@@ -253,20 +229,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
 	unsigned long unused,
         struct task_struct * p, struct pt_regs * regs)
 {
-        struct stack_frame
+        struct fake_frame
           {
-            unsigned long back_chain;
-            unsigned long eos;
-            unsigned long glue1;
-            unsigned long glue2;
-            unsigned long scratch[2];
-            unsigned long gprs[10];    /* gprs 6 -15                       */
-            unsigned int  fprs[4];     /* fpr 4 and 6                      */
-            unsigned int  empty[4];
+	    struct stack_frame sf;
             struct pt_regs childregs;
           } *frame;
 
-        frame = ((struct stack_frame *)
+        frame = ((struct fake_frame *)
 		 (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
         p->thread.ksp = (unsigned long) frame;
 	p->set_child_tid = p->clear_child_tid = NULL;
@@ -274,13 +243,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
         frame->childregs = *regs;
 	frame->childregs.gprs[2] = 0;	/* child returns 0 on fork. */
         frame->childregs.gprs[15] = new_stackp;
-        frame->back_chain = frame->eos = 0;
+        frame->sf.back_chain = 0;
 
         /* new return point is ret_from_fork */
-        frame->gprs[8] = (unsigned long) ret_from_fork;
+        frame->sf.gprs[8] = (unsigned long) ret_from_fork;
 
         /* fake return stack for resume(), don't go back to schedule */
-        frame->gprs[9] = (unsigned long) frame;
+        frame->sf.gprs[9] = (unsigned long) frame;
 
 	/* Save access registers to new thread structure. */
 	save_access_regs(&p->thread.acrs[0]);
@@ -336,7 +305,7 @@ asmlinkage long sys_clone(struct pt_regs regs)
 	child_tidptr = (int __user *) regs.gprs[5];
         if (!newsp)
                 newsp = regs.gprs[15];
-        return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0,
+        return do_fork(clone_flags, newsp, &regs, 0,
 		       parent_tidptr, child_tidptr);
 }
 
@@ -423,30 +392,26 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
 
 unsigned long get_wchan(struct task_struct *p)
 {
-	unsigned long r14, r15, bc;
-	unsigned long stack_page;
-	int count = 0;
-	if (!p || p == current || p->state == TASK_RUNNING)
+	struct stack_frame *sf, *low, *high;
+	unsigned long return_address;
+	int count;
+
+	if (!p || p == current || p->state == TASK_RUNNING || !p->thread_info)
 		return 0;
-	stack_page = (unsigned long) p->thread_info;
-	r15 = p->thread.ksp;
-	if (!stack_page || r15 < stack_page ||
-	    r15 >= THREAD_SIZE - sizeof(unsigned long) + stack_page)
+	low = (struct stack_frame *) p->thread_info;
+	high = (struct stack_frame *)
+		((unsigned long) p->thread_info + THREAD_SIZE) - 1;
+	sf = (struct stack_frame *) (p->thread.ksp & PSW_ADDR_INSN);
+	if (sf <= low || sf > high)
 		return 0;
-	bc = (*(unsigned long *) r15) & PSW_ADDR_INSN;
-	do {
-		if (bc < stack_page ||
-		    bc >= THREAD_SIZE - sizeof(unsigned long) + stack_page)
+	for (count = 0; count < 16; count++) {
+		sf = (struct stack_frame *) (sf->back_chain & PSW_ADDR_INSN);
+		if (sf <= low || sf > high)
 			return 0;
-#ifndef CONFIG_ARCH_S390X
-		r14 = (*(unsigned long *) (bc+56)) & PSW_ADDR_INSN;
-#else
-		r14 = *(unsigned long *) (bc+112);
-#endif
-		if (!in_sched_functions(r14))
-			return r14;
-		bc = (*(unsigned long *) bc) & PSW_ADDR_INSN;
-	} while (count++ < 16);
+		return_address = sf->gprs[8] & PSW_ADDR_INSN;
+		if (!in_sched_functions(return_address))
+			return return_address;
+	}
 	return 0;
 }
 
diff --git a/arch/s390/kernel/profile.c b/arch/s390/kernel/profile.c
index f219748d7..7ba777eec 100644
--- a/arch/s390/kernel/profile.c
+++ b/arch/s390/kernel/profile.c
@@ -6,52 +6,15 @@
  *
  */
 #include <linux/proc_fs.h>
+#include <linux/profile.h>
 
 static struct proc_dir_entry * root_irq_dir;
 
-static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
-					int count, int *eof, void *data)
-{
-	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
-	if (count - len < 2)
-		return -EINVAL;
-	len += sprintf(page + len, "\n");
-	return len;
-}
-
-static int prof_cpu_mask_write_proc (struct file *file,
-					const char __user *buffer,
-					unsigned long count, void *data)
-{
-	cpumask_t *mask = (cpumask_t *)data;
-	unsigned long full_count = count, err;
-	cpumask_t new_value;
-
-	err = cpumask_parse(buffer, count, new_value);
-	if (err)
-		return err;
-
-	*mask = new_value;
-	return full_count;
-}
-
-cpumask_t prof_cpu_mask = CPU_MASK_ALL;
-
 void init_irq_proc(void)
 {
-	struct proc_dir_entry *entry;
-
 	/* create /proc/irq */
 	root_irq_dir = proc_mkdir("irq", 0);
 
 	/* create /proc/irq/prof_cpu_mask */
-	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
-
-	if (!entry)
-		return;
-
-	entry->nlink = 1;
-	entry->data = (void *)&prof_cpu_mask;
-	entry->read_proc = prof_cpu_mask_read_proc;
-	entry->write_proc = prof_cpu_mask_write_proc;
+	create_prof_cpu_mask(root_irq_dir);
 }
diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c
index c00e5e328..b61490bd1 100644
--- a/arch/s390/kernel/s390_ext.c
+++ b/arch/s390/kernel/s390_ext.c
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/kernel_stat.h>
+#include <linux/interrupt.h>
 
 #include <asm/lowcore.h>
 #include <asm/s390_ext.h>
diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c
index 43afd32f8..1a5ba047e 100644
--- a/arch/s390/kernel/s390_ksyms.c
+++ b/arch/s390/kernel/s390_ksyms.c
@@ -23,16 +23,18 @@
 /*
  * memory management
  */
-EXPORT_SYMBOL_NOVERS(_oi_bitmap);
-EXPORT_SYMBOL_NOVERS(_ni_bitmap);
-EXPORT_SYMBOL_NOVERS(_zb_findmap);
-EXPORT_SYMBOL_NOVERS(_sb_findmap);
-EXPORT_SYMBOL_NOVERS(__copy_from_user_asm);
-EXPORT_SYMBOL_NOVERS(__copy_to_user_asm);
-EXPORT_SYMBOL_NOVERS(__clear_user_asm);
-EXPORT_SYMBOL_NOVERS(__strncpy_from_user_asm);
-EXPORT_SYMBOL_NOVERS(__strnlen_user_asm);
+EXPORT_SYMBOL(_oi_bitmap);
+EXPORT_SYMBOL(_ni_bitmap);
+EXPORT_SYMBOL(_zb_findmap);
+EXPORT_SYMBOL(_sb_findmap);
+EXPORT_SYMBOL(__copy_from_user_asm);
+EXPORT_SYMBOL(__copy_to_user_asm);
+EXPORT_SYMBOL(__copy_in_user_asm);
+EXPORT_SYMBOL(__clear_user_asm);
+EXPORT_SYMBOL(__strncpy_from_user_asm);
+EXPORT_SYMBOL(__strnlen_user_asm);
 EXPORT_SYMBOL(diag10);
+EXPORT_SYMBOL(default_storage_key);
 
 /*
  * semaphore ops
@@ -60,6 +62,5 @@ EXPORT_SYMBOL(csum_fold);
 EXPORT_SYMBOL(console_mode);
 EXPORT_SYMBOL(console_devno);
 EXPORT_SYMBOL(console_irq);
-EXPORT_SYMBOL_NOVERS(do_call_softirq);
 EXPORT_SYMBOL(sys_wait4);
 EXPORT_SYMBOL(cpcmd);
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index a50891ce0..1324fc6ce 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -53,6 +53,7 @@ unsigned int console_devno = -1;
 unsigned int console_irq = -1;
 unsigned long memory_size = 0;
 unsigned long machine_flags = 0;
+unsigned int default_storage_key = 0;
 struct {
 	unsigned long addr, size, type;
 } memory_chunk[MEMORY_CHUNKS] = { { 0 } };
@@ -503,6 +504,10 @@ void __init setup_arch(char **cmdline_p)
 	lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
 	lc->async_stack = (unsigned long)
 		__alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE;
+#ifdef CONFIG_CHECK_STACK
+	lc->panic_stack = (unsigned long)
+		__alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE;
+#endif
 	lc->current_task = (unsigned long) init_thread_union.thread_info.task;
 	lc->thread_info = (unsigned long) &init_thread_union;
 #ifdef CONFIG_ARCH_S390X
@@ -604,49 +609,3 @@ struct seq_operations cpuinfo_op = {
 	.show	= show_cpuinfo,
 };
 
-/*
- * show_interrupts is needed by /proc/interrupts.
- */
-
-static const char *intrclass_names[] = {
-	"EXT",
-	"I/O",
-};
-
-int show_interrupts(struct seq_file *p, void *v)
-{
-        int i = *(loff_t *) v, j;
-	
-	if (i == 0) {
-		seq_puts(p, "           ");
-		for (j=0; j<NR_CPUS; j++)
-			if (cpu_online(j))
-				seq_printf(p, "CPU%d       ",j);
-		seq_putc(p, '\n');
-	}
-	
-	if (i < NR_IRQS) {
-		seq_printf(p, "%s: ", intrclass_names[i]);
-#ifndef CONFIG_SMP
-		seq_printf(p, "%10u ", kstat_irqs(i));
-#else
-		for (j = 0; j < NR_CPUS; j++)
-			if (cpu_online(j))
-				seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
-#endif
-                seq_putc(p, '\n');
-		
-        }
-	
-        return 0;
-}
-
-/*
- * For compatibilty only. S/390 specific setup of interrupts et al. is done
- * much later in init_channel_subsystem().
- */
-void __init
-init_IRQ(void)
-{
-	/* nothing... */
-}
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index d5b648153..179db7e03 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -358,9 +358,7 @@ static void setup_frame(int sig, struct k_sigaction *ka,
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -414,9 +412,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 /*
@@ -424,20 +420,15 @@ give_sigsegv:
  */	
 
 static void
-handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
-	struct pt_regs * regs)
+handle_signal(unsigned long sig, struct k_sigaction *ka,
+	      siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
 {
-	struct k_sigaction *ka = &current->sighand->action[sig-1];
-
 	/* Set up the stack frame */
 	if (ka->sa.sa_flags & SA_SIGINFO)
 		setup_rt_frame(sig, ka, info, oldset, regs);
 	else
 		setup_frame(sig, ka, oldset, regs);
 
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
-
 	if (!(ka->sa.sa_flags & SA_NODEFER)) {
 		spin_lock_irq(&current->sighand->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -461,6 +452,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
 	unsigned long retval = 0, continue_addr = 0, restart_addr = 0;
 	siginfo_t info;
 	int signr;
+	struct k_sigaction ka;
 
 	/*
 	 * We want the common case to go fast, which
@@ -494,7 +486,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
 
 	/* Get signal to deliver.  When running under ptrace, at this point
 	   the debugger may change all our registers ... */
-	signr = get_signal_to_deliver(&info, regs, NULL);
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
 	/* Depending on the signal settings we may need to revert the
 	   decision to restart the system call. */
@@ -513,14 +505,15 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
 #ifdef CONFIG_S390_SUPPORT
 		if (test_thread_flag(TIF_31BIT)) {
 			extern void handle_signal32(unsigned long sig,
+						    struct k_sigaction *ka,
 						    siginfo_t *info,
 						    sigset_t *oldset,
 						    struct pt_regs *regs);
-			handle_signal32(signr, &info, oldset, regs);
+			handle_signal32(signr, &ka, &info, oldset, regs);
 			return 1;
 	        }
 #endif
-		handle_signal(signr, &info, oldset, regs);
+		handle_signal(signr, &ka, &info, oldset, regs);
 		return 1;
 	}
 
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index eb8a5161a..b5c09d144 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -562,21 +562,15 @@ int __devinit start_secondary(void *cpuvoid)
 
 static void __init smp_create_idle(unsigned int cpu)
 {
-	struct pt_regs regs;
 	struct task_struct *p;
 
 	/*
 	 *  don't care about the psw and regs settings since we'll never
 	 *  reschedule the forked task.
 	 */
-	memset(&regs, 0, sizeof(struct pt_regs));
-	p = copy_process(CLONE_VM | CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
+	p = fork_idle(cpu);
 	if (IS_ERR(p))
 		panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
-
-	wake_up_forked_process(p);
-	init_idle(p, cpu);
-	unhash_process(p);
 	current_set[cpu] = p;
 }
 
@@ -643,6 +637,7 @@ __cpu_up(unsigned int cpu)
 {
 	struct task_struct *idle;
         struct _lowcore    *cpu_lowcore;
+	struct stack_frame *sf;
         sigp_ccode          ccode;
 	int                 curr_cpu;
 
@@ -666,9 +661,14 @@ __cpu_up(unsigned int cpu)
 
 	idle = current_set[cpu];
         cpu_lowcore = lowcore_ptr[cpu];
-	cpu_lowcore->save_area[15] = idle->thread.ksp;
 	cpu_lowcore->kernel_stack = (unsigned long)
 		idle->thread_info + (THREAD_SIZE);
+	sf = (struct stack_frame *) (cpu_lowcore->kernel_stack
+				     - sizeof(struct pt_regs)
+				     - sizeof(struct stack_frame));
+	memset(sf, 0, sizeof(struct stack_frame));
+	sf->gprs[9] = (unsigned long) sf;
+	cpu_lowcore->save_area[15] = (unsigned long) sf;
 	__ctl_store(cpu_lowcore->cregs_save_area[0], 0, 15);
 	__asm__ __volatile__("stam  0,15,0(%0)"
 			     : : "a" (&cpu_lowcore->access_regs_save_area)
@@ -747,7 +747,7 @@ cpu_die(void)
 
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
-	unsigned long async_stack;
+	unsigned long stack;
 	unsigned int cpu;
         int i;
 
@@ -767,12 +767,18 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 		lowcore_ptr[i] = (struct _lowcore *)
 			__get_free_pages(GFP_KERNEL|GFP_DMA, 
 					sizeof(void*) == 8 ? 1 : 0);
-		async_stack = __get_free_pages(GFP_KERNEL,ASYNC_ORDER);
-		if (lowcore_ptr[i] == NULL || async_stack == 0ULL)
+		stack = __get_free_pages(GFP_KERNEL,ASYNC_ORDER);
+		if (lowcore_ptr[i] == NULL || stack == 0ULL)
 			panic("smp_boot_cpus failed to allocate memory\n");
 
 		*(lowcore_ptr[i]) = S390_lowcore;
-		lowcore_ptr[i]->async_stack = async_stack + (ASYNC_SIZE);
+		lowcore_ptr[i]->async_stack = stack + (ASYNC_SIZE);
+#ifdef CONFIG_CHECK_STACK
+		stack = __get_free_pages(GFP_KERNEL,0);
+		if (stack == 0ULL)
+			panic("smp_boot_cpus failed to allocate memory\n");
+		lowcore_ptr[i]->panic_stack = stack + (PAGE_SIZE);
+#endif
 	}
 	set_prefix((u32)(unsigned long) lowcore_ptr[smp_processor_id()]);
 
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 12f46a65a..8f2794216 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -174,47 +174,7 @@ __calculate_ticks(__u64 elapsed)
 
 
 #ifdef CONFIG_PROFILING
-extern char _stext, _etext;
-
-/*
- * The profiling function is SMP safe. (nothing can mess
- * around with "current", and the profiling counters are
- * updated with atomic operations). This is especially
- * useful with a profiling multiplier != 1
- */
-static inline void s390_do_profile(struct pt_regs * regs)
-{
-	unsigned long eip;
-	extern cpumask_t prof_cpu_mask;
-
-	profile_hook(regs);
-
-	if (user_mode(regs))
-		return;
-
-	if (!prof_buffer)
-		return;
-
-	eip = instruction_pointer(regs);
-
-	/*
-	 * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
-	 * (default is all CPUs.)
-	 */
-	if (!cpu_isset(smp_processor_id(), prof_cpu_mask))
-		return;
-
-	eip -= (unsigned long) &_stext;
-	eip >>= prof_shift;
-	/*
-	 * Don't ignore out-of-bounds EIP values silently,
-	 * put them into the last histogram slot, so if
-	 * present, they will show up as a sharp peak.
-	 */
-	if (eip > prof_len-1)
-		eip = prof_len-1;
-	atomic_inc((atomic_t *)&prof_buffer[eip]);
-}
+#define s390_do_profile(regs)	profile_tick(CPU_PROFILING, regs)
 #else
 #define s390_do_profile(regs)  do { ; } while(0)
 #endif /* CONFIG_PROFILING */
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 6614d4be1..e67ee2702 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -67,54 +67,93 @@ extern pgm_check_handler_t do_monitor_call;
 #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
 
 #ifndef CONFIG_ARCH_S390X
-#define RET_ADDR 56
 #define FOURLONG "%08lx %08lx %08lx %08lx\n"
 static int kstack_depth_to_print = 12;
-
 #else /* CONFIG_ARCH_S390X */
-#define RET_ADDR 112
 #define FOURLONG "%016lx %016lx %016lx %016lx\n"
 static int kstack_depth_to_print = 20;
-
 #endif /* CONFIG_ARCH_S390X */
 
-void show_trace(struct task_struct *task, unsigned long * stack)
+/*
+ * For show_trace we have tree different stack to consider:
+ *   - the panic stack which is used if the kernel stack has overflown
+ *   - the asynchronous interrupt stack (cpu related)
+ *   - the synchronous kernel stack (process related)
+ * The stack trace can start at any of the three stack and can potentially
+ * touch all of them. The order is: panic stack, async stack, sync stack.
+ */
+static unsigned long
+__show_trace(unsigned long sp, unsigned long low, unsigned long high)
 {
-	unsigned long backchain, low_addr, high_addr, ret_addr;
+	struct stack_frame *sf;
+	struct pt_regs *regs;
 
-	if (!stack)
-		stack = (task == NULL) ? *stack_pointer : &(task->thread.ksp);
+	while (1) {
+		sp = sp & PSW_ADDR_INSN;
+		if (sp < low || sp > high - sizeof(*sf))
+			return sp;
+		sf = (struct stack_frame *) sp;
+		printk("([<%016lx>] ", sf->gprs[8] & PSW_ADDR_INSN);
+		print_symbol("%s)\n", sf->gprs[8] & PSW_ADDR_INSN);
+		/* Follow the backchain. */
+		while (1) {
+			low = sp;
+			sp = sf->back_chain & PSW_ADDR_INSN;
+			if (!sp)
+				break;
+			if (sp <= low || sp > high - sizeof(*sf))
+				return sp;
+			sf = (struct stack_frame *) sp;
+			printk(" [<%016lx>] ", sf->gprs[8] & PSW_ADDR_INSN);
+			print_symbol("%s\n", sf->gprs[8] & PSW_ADDR_INSN);
+		}
+		/* Zero backchain detected, check for interrupt frame. */
+		sp = (unsigned long) (sf + 1);
+		if (sp <= low || sp > high - sizeof(*regs))
+			return sp;
+		regs = (struct pt_regs *) sp;
+		printk(" [<%016lx>] ", regs->psw.addr & PSW_ADDR_INSN);
+		print_symbol("%s\n", regs->psw.addr & PSW_ADDR_INSN);
+		low = sp;
+		sp = regs->gprs[15];
+	}
+}
 
+void show_trace(struct task_struct *task, unsigned long * stack)
+{
+	register unsigned long __r15 asm ("15");
+	unsigned long sp;
+
+	sp = (unsigned long) stack;
+	if (!sp)
+		sp = task ? task->thread.ksp : __r15;
 	printk("Call Trace:\n");
-	low_addr = ((unsigned long) stack) & PSW_ADDR_INSN;
-	high_addr = (low_addr & (-THREAD_SIZE)) + THREAD_SIZE;
-	/* Skip the first frame (biased stack) */
-	backchain = *((unsigned long *) low_addr) & PSW_ADDR_INSN;
-	/* Print up to 8 lines */
-	while  (backchain > low_addr && backchain <= high_addr) {
-		ret_addr = *((unsigned long *) (backchain+RET_ADDR)) & PSW_ADDR_INSN;
-		printk(" [<%016lx>] ", ret_addr);
-		print_symbol("%s\n", ret_addr);
-		low_addr = backchain;
-		backchain = *((unsigned long *) backchain) & PSW_ADDR_INSN;
-	}
+#ifdef CONFIG_CHECK_STACK
+	sp = __show_trace(sp, S390_lowcore.panic_stack - 4096,
+			  S390_lowcore.panic_stack);
+#endif
+	sp = __show_trace(sp, S390_lowcore.async_stack - ASYNC_SIZE,
+			  S390_lowcore.async_stack);
+	if (task)
+		__show_trace(sp, (unsigned long) task->thread_info,
+			     (unsigned long) task->thread_info + THREAD_SIZE);
+	else
+		__show_trace(sp, S390_lowcore.thread_info,
+			     S390_lowcore.thread_info + THREAD_SIZE);
 	printk("\n");
 }
 
 void show_stack(struct task_struct *task, unsigned long *sp)
 {
+	register unsigned long * __r15 asm ("15");
 	unsigned long *stack;
 	int i;
 
 	// debugging aid: "show_stack(NULL);" prints the
 	// back trace for this cpu.
 
-	if (!sp) {
-		if (task)
-			sp = (unsigned long *) task->thread.ksp;
-		else
-			sp = *stack_pointer;
-	}
+	if (!sp)
+		sp = task ? (unsigned long *) task->thread.ksp : __r15;
 
 	stack = sp;
 	for (i = 0; i < kstack_depth_to_print; i++) {
@@ -591,6 +630,11 @@ asmlinkage void data_exception(struct pt_regs * regs, long interruption_code)
 	}
 }
 
+asmlinkage void kernel_stack_overflow(struct pt_regs * regs)
+{
+	die("Kernel stack overflow", regs, 0);
+	panic("Corrupt kernel stack, can't continue.");
+}
 
 
 /* init is done in lowcore.S and head.S */
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index b4534b286..89fdb3808 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -24,6 +24,7 @@ SECTIONS
   .text : {
 	*(.text)
 	SCHED_TEXT
+	LOCK_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x0700
@@ -78,9 +79,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : {
 	*(.initcall1.init) 
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index d9ccdbdc2..02d2179e4 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -21,7 +21,7 @@
 #include <asm/s390_ext.h>
 #include <asm/timer.h>
 
-#define VTIMER_MAGIC (0x4b87ad6e + 1)
+#define VTIMER_MAGIC (TIMER_MAGIC + 1)
 static ext_int_info_t ext_int_info_timer;
 DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
 
diff --git a/arch/s390/lib/string.c b/arch/s390/lib/string.c
index 966af7c52..9cf22aa48 100644
--- a/arch/s390/lib/string.c
+++ b/arch/s390/lib/string.c
@@ -46,7 +46,7 @@ size_t strlen(const char *s)
 {
 	return __strend(s) - s;
 }
-EXPORT_SYMBOL_NOVERS(strlen);
+EXPORT_SYMBOL(strlen);
 
 /**
  * strnlen - Find the length of a length-limited string
@@ -59,7 +59,7 @@ size_t strnlen(const char * s, size_t n)
 {
 	return __strnend(s, n) - s;
 }
-EXPORT_SYMBOL_NOVERS(strnlen);
+EXPORT_SYMBOL(strnlen);
 
 /**
  * strcpy - Copy a %NUL terminated string
@@ -79,7 +79,7 @@ char *strcpy(char *dest, const char *src)
 		      : "cc", "memory" );
 	return ret;
 }
-EXPORT_SYMBOL_NOVERS(strcpy);
+EXPORT_SYMBOL(strcpy);
 
 /**
  * strlcpy - Copy a %NUL terminated string into a sized buffer
@@ -103,7 +103,7 @@ size_t strlcpy(char *dest, const char *src, size_t size)
 	}
 	return ret;
 }
-EXPORT_SYMBOL_NOVERS(strlcpy);
+EXPORT_SYMBOL(strlcpy);
 
 /**
  * strncpy - Copy a length-limited, %NUL-terminated string
@@ -121,7 +121,7 @@ char *strncpy(char *dest, const char *src, size_t n)
 	__builtin_memcpy(dest, src, len);
 	return dest;
 }
-EXPORT_SYMBOL_NOVERS(strncpy);
+EXPORT_SYMBOL(strncpy);
 
 /**
  * strcat - Append one %NUL-terminated string to another
@@ -144,7 +144,7 @@ char *strcat(char *dest, const char *src)
 		      : "d" (r0), "0" (0UL) : "cc", "memory" );
 	return ret;
 }
-EXPORT_SYMBOL_NOVERS(strcat);
+EXPORT_SYMBOL(strcat);
 
 /**
  * strlcat - Append a length-limited, %NUL-terminated string to another
@@ -168,7 +168,7 @@ size_t strlcat(char *dest, const char *src, size_t n)
 	}
 	return res;
 }
-EXPORT_SYMBOL_NOVERS(strlcat);
+EXPORT_SYMBOL(strlcat);
 
 /**
  * strncat - Append a length-limited, %NUL-terminated string to another
@@ -190,7 +190,7 @@ char *strncat(char *dest, const char *src, size_t n)
 	__builtin_memcpy(p, src, len);
 	return dest;
 }
-EXPORT_SYMBOL_NOVERS(strncat);
+EXPORT_SYMBOL(strncat);
 
 /**
  * strcmp - Compare two strings
@@ -217,7 +217,7 @@ int strcmp(const char *cs, const char *ct)
 		      : : "cc" );
 	return ret;
 }
-EXPORT_SYMBOL_NOVERS(strcmp);
+EXPORT_SYMBOL(strcmp);
 
 /**
  * strrchr - Find the last occurrence of a character in a string
@@ -235,7 +235,7 @@ char * strrchr(const char * s, int c)
 	       } while (--len > 0);
        return 0;
 }
-EXPORT_SYMBOL_NOVERS(strrchr);
+EXPORT_SYMBOL(strrchr);
 
 /**
  * strstr - Find the first substring in a %NUL terminated string
@@ -269,7 +269,7 @@ char * strstr(const char * s1,const char * s2)
 	}
 	return 0;
 }
-EXPORT_SYMBOL_NOVERS(strstr);
+EXPORT_SYMBOL(strstr);
 
 /**
  * memchr - Find a character in an area of memory.
@@ -293,7 +293,7 @@ void *memchr(const void *s, int c, size_t n)
 		      : "+a" (ret), "+&a" (s) : "d" (r0) : "cc" );
 	return (void *) ret;
 }
-EXPORT_SYMBOL_NOVERS(memchr);
+EXPORT_SYMBOL(memchr);
 
 /**
  * memcmp - Compare two areas of memory
@@ -319,7 +319,7 @@ int memcmp(const void *cs, const void *ct, size_t n)
 		ret = *(char *) r2 - *(char *) r4;
 	return ret;
 }
-EXPORT_SYMBOL_NOVERS(memcmp);
+EXPORT_SYMBOL(memcmp);
 
 /**
  * memscan - Find a character in an area of memory.
@@ -340,7 +340,7 @@ void *memscan(void *s, int c, size_t n)
 		      : "+a" (ret), "+&a" (s) : "d" (r0) : "cc" );
 	return (void *) ret;
 }
-EXPORT_SYMBOL_NOVERS(memscan);
+EXPORT_SYMBOL(memscan);
 
 /**
  * memcpy - Copy one area of memory to another
@@ -354,7 +354,7 @@ void *memcpy(void *dest, const void *src, size_t n)
 {
 	return __builtin_memcpy(dest, src, n);
 }
-EXPORT_SYMBOL_NOVERS(memcpy);
+EXPORT_SYMBOL(memcpy);
 
 /**
  * bcopy - Copy one area of memory to another
@@ -369,7 +369,7 @@ void bcopy(const void *srcp, void *destp, size_t n)
 {
 	__builtin_memcpy(destp, srcp, n);
 }
-EXPORT_SYMBOL_NOVERS(bcopy);
+EXPORT_SYMBOL(bcopy);
 
 /**
  * memset - Fill a region of memory with the given value
@@ -393,4 +393,4 @@ void *memset(void *s, int c, size_t n)
 		} while (--n > 0);
 	return s;
 }
-EXPORT_SYMBOL_NOVERS(memset);
+EXPORT_SYMBOL(memset);
diff --git a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile
index f8583caa6..aa9a42b6e 100644
--- a/arch/s390/mm/Makefile
+++ b/arch/s390/mm/Makefile
@@ -2,6 +2,6 @@
 # Makefile for the linux s390-specific parts of the memory manager.
 #
 
-obj-y	 := init.o fault.o ioremap.o extmem.o
+obj-y	 := init.o fault.o ioremap.o extmem.o mmap.o
 obj-$(CONFIG_CMM) += cmm.o
 
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 8b2dda883..d6bd3d429 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -25,11 +25,11 @@
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/module.h>
+#include <linux/hardirq.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
-#include <asm/hardirq.h>
 
 #ifndef CONFIG_ARCH_S390X
 #define __FAIL_ADDR_MASK 0x7ffff000
@@ -126,8 +126,8 @@ static inline int check_user_space(struct pt_regs *regs, int error_code)
  * Send SIGSEGV to task.  This is an external routine
  * to keep the stack usage of do_page_fault small.
  */
-static void force_sigsegv(struct pt_regs *regs, unsigned long error_code,
-			  int si_code, unsigned long address)
+static void do_sigsegv(struct pt_regs *regs, unsigned long error_code,
+		       int si_code, unsigned long address)
 {
 	struct siginfo si;
 
@@ -282,7 +282,7 @@ bad_area:
         if (regs->psw.mask & PSW_MASK_PSTATE) {
                 tsk->thread.prot_addr = address;
                 tsk->thread.trap_no = error_code;
-		force_sigsegv(regs, error_code, si_code, address);
+		do_sigsegv(regs, error_code, si_code, address);
                 return;
 	}
 
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 2140eb0ec..65e0fa1ad 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -194,7 +194,7 @@ endchoice
 
 choice
 	prompt "Processor subtype"
-	
+
 config CPU_SUBTYPE_SH7604
 	bool "SH7604"
 	depends on CPU_SH2
@@ -301,7 +301,7 @@ config MEMORY_START
 	---help---
 	  Computers built with Hitachi SuperH processors always
 	  map the ROM starting at address zero.  But the processor
-	  does not specify the range that RAM takes.  
+	  does not specify the range that RAM takes.
 
 	  The physical memory (RAM) start address will be automatically
 	  set to 08000000, unless you selected one of the following
@@ -339,7 +339,7 @@ config MEMORY_SET
 # If none of the above have set memory start/size, ask the user.
 config MEMORY_OVERRIDE
 	bool "Override default load address and memory size"
-	
+
 # XXX: break these out into the board-specific configs below
 config CF_ENABLER
 	bool "Compact Flash Enabler support"
@@ -522,7 +522,7 @@ config SH_STORE_QUEUES
 	help
 	  Selecting this option will enable an in-kernel API for manipulating
 	  the store queues integrated in the SH-4 processors.
-	
+
 config SMP
 	bool "Symmetric multi-processing support"
 	---help---
@@ -711,7 +711,6 @@ source "drivers/pci/hotplug/Kconfig"
 
 endmenu
 
-
 menu "Executable file formats"
 
 source "fs/Kconfig.binfmt"
@@ -742,157 +741,7 @@ source "fs/Kconfig"
 
 source "arch/sh/oprofile/Kconfig"
 
-menu "Kernel hacking"
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SPINLOCK
-	bool "Spinlock debugging"
-	help
-	  Say Y here and build SMP to catch missing spinlock initialization
-	  and certain other kinds of spinlock errors commonly made.  This is
-	  best used in conjunction with the NMI watchdog so that spinlock
-	  deadlocks are also debuggable.
-
-config DEBUG_INFO
-        bool "Compile the kernel with debug info"
-        help
-          If you say Y here the resulting kernel image will include
-          debugging info resulting in a larger kernel image.
-          Say Y here only if you plan to use gdb to debug the kernel.
-          If you don't debug the kernel, you can say N.
-
-config SH_STANDARD_BIOS
-	bool "Use LinuxSH standard BIOS"
-	help
-	  Say Y here if your target has the gdb-sh-stub
-	  package from www.m17n.org (or any conforming standard LinuxSH BIOS)
-	  in FLASH or EPROM.  The kernel will use standard BIOS calls during
-	  boot for various housekeeping tasks (including calls to read and
-	  write characters to a system console, get a MAC address from an
-	  on-board Ethernet interface, and shut down the hardware).  Note this
-	  does not work with machines with an existing operating system in
-	  mask ROM and no flash (WindowsCE machines fall in this category).
-	  If unsure, say N.
-
-config EARLY_SCIF_CONSOLE
-	bool "Use early SCIF console"
-	depends on CPU_SH4
-
-config EARLY_PRINTK
-	bool "Early printk support"
-	depends on SH_STANDARD_BIOS || EARLY_SCIF_CONSOLE
-	help
-	  Say Y here to redirect kernel printk messages to the serial port
-	  used by the SH-IPL bootloader, starting very early in the boot
-	  process and ending when the kernel's serial console is initialised.
-	  This option is only useful porting the kernel to a new machine,
-	  when the kernel may crash or hang before the serial console is
-	  initialised. If unsure, say N.
-
-config KGDB
-	bool "Include KGDB kernel debugger"
-	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 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 KGDB_THREAD
-	bool "Include KGDB thread support"
-	default y
-
-config SH_KGDB_CONSOLE
-	bool "Console messages through GDB"
-	default n
-
-config KGDB_SYSRQ
-	bool "Allow SysRq 'G' to enter KGDB"
-	default y
-
-config KGDB_KERNEL_ASSERTS
-	bool "Include KGDB kernel assertions"
-	default n
-
-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 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 KGDB
-	default KGDB_DEFBITS_8
-
-config KGDB_DEFBITS_8
-	bool "8"
-
-config KGDB_DEFBITS_7
-	bool "7"
-
-endchoice
-
-endmenu
-
-config FRAME_POINTER
-	bool "Compile the kernel with frame pointers"
-	default y if KGDB
-	help
-	  If you say Y here the resulting kernel image will be slightly larger
-	  and slower, but 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 pointers.
-
-endmenu
+source "arch/sh/Kconfig.debug"
 
 source "kernel/vserver/Kconfig"
 
@@ -901,4 +750,3 @@ source "security/Kconfig"
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index 7e0087146..5d2c028d9 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -31,7 +31,7 @@ cflags-$(CONFIG_CPU_LITTLE_ENDIAN)	:= -ml
 cflags-$(CONFIG_CPU_SH2)		+= -m2
 cflags-$(CONFIG_CPU_SH3)		+= -m3
 cflags-$(CONFIG_CPU_SH4)		+= -m4 \
-	$(call check_gcc,-mno-implicit-fp,-m4-nofpu)
+	$(call cc-option,-mno-implicit-fp,-m4-nofpu)
 
 cflags-$(CONFIG_SH_DSP)			+= -Wa,-dsp
 cflags-$(CONFIG_SH_KGDB)		+= -g
@@ -122,7 +122,7 @@ drivers-$(CONFIG_OPROFILE)	+= arch/sh/oprofile/
 
 boot := arch/sh/boot
 
-AFLAGS_vmlinux.lds.o := -traditional
+CPPFLAGS_vmlinux.lds := -traditional
 
 prepare: target_links
 
diff --git a/arch/sh/boards/mpc1211/pci.c b/arch/sh/boards/mpc1211/pci.c
index c9bbd72b4..ba3a65439 100644
--- a/arch/sh/boards/mpc1211/pci.c
+++ b/arch/sh/boards/mpc1211/pci.c
@@ -176,14 +176,7 @@ static void __devinit quirk_ali_ide_ports(struct pci_dev *dev)
 	dev->resource[4].end   = 0xf00f;
 	dev->resource[4].flags = IORESOURCE_IO;
 }
-
-
-/* Add future fixups here... */
-struct pci_fixup pcibios_fixups[] = {
-	{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL,
-	  PCI_DEVICE_ID_AL_M5229, quirk_ali_ide_ports },
-	{ 0 }
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, quirk_ali_ide_ports);
 
 char * __devinit pcibios_setup(char *str)
 {
diff --git a/arch/sh/boards/overdrive/galileo.c b/arch/sh/boards/overdrive/galileo.c
index 54020ebbb..276fa11ee 100644
--- a/arch/sh/boards/overdrive/galileo.c
+++ b/arch/sh/boards/overdrive/galileo.c
@@ -455,13 +455,7 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d)
 		}
 	}
 }
-
-
-/* Add future fixups here... */
-struct pci_fixup pcibios_fixups[] = {
-	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,	PCI_ANY_ID,	pci_fixup_ide_bases },
-	{ 0 }
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
 
 void __init pcibios_init(void)
 {
diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile
index 05ca14dfa..75a6876bf 100644
--- a/arch/sh/boot/compressed/Makefile
+++ b/arch/sh/boot/compressed/Makefile
@@ -22,7 +22,7 @@ CONFIG_MEMORY_START     ?= 0x0c000000
 CONFIG_BOOT_LINK_OFFSET ?= 0x00800000
 IMAGE_OFFSET := $(shell printf "0x%8x" $$[0x80000000+$(CONFIG_MEMORY_START)+$(CONFIG_BOOT_LINK_OFFSET)])
 
-LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup -T $(obj)/../../kernel/vmlinux.lds.s
+LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup -T $(obj)/../../kernel/vmlinux.lds
 
 $(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE
 	$(call if_changed,ld)
diff --git a/arch/sh/drivers/pci/fixups-dreamcast.c b/arch/sh/drivers/pci/fixups-dreamcast.c
index aa5e24a65..d07572bfc 100644
--- a/arch/sh/drivers/pci/fixups-dreamcast.c
+++ b/arch/sh/drivers/pci/fixups-dreamcast.c
@@ -47,11 +47,7 @@ static void __init gapspci_fixup_resources(struct pci_dev *dev)
 	}
 }
 
-struct pci_fixup pcibios_fixups[] = {
-	{ PCI_FIXUP_HEADER, PCI_ANY_ID,
-	  PCI_ANY_ID, gapspci_fixup_resources },
-	{ 0, }
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, gapspci_fixup_resources);
 
 void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
diff --git a/arch/sh/drivers/pci/pci-sh7751.c b/arch/sh/drivers/pci/pci-sh7751.c
index b2bb72972..1a5a883ad 100644
--- a/arch/sh/drivers/pci/pci-sh7751.c
+++ b/arch/sh/drivers/pci/pci-sh7751.c
@@ -177,16 +177,9 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d)
 		}
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
 #endif
 
-/* Add future fixups here... */
-struct pci_fixup pcibios_fixups[] = {
-#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
-	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,	PCI_ANY_ID,	pci_fixup_ide_bases },
-#endif
-	{ 0 }
-};
-
 /*
  *  Called after each bus is probed, but before its children
  *  are examined.
diff --git a/arch/sh/drivers/pci/pci-st40.c b/arch/sh/drivers/pci/pci-st40.c
index 29e7bf619..4be02f627 100644
--- a/arch/sh/drivers/pci/pci-st40.c
+++ b/arch/sh/drivers/pci/pci-st40.c
@@ -160,13 +160,7 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d)
 		}
 	}
 }
-
-
-/* Add future fixups here... */
-struct pci_fixup pcibios_fixups[] = {
-	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,	PCI_ANY_ID,	pci_fixup_ide_bases },
-	{ 0 }
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
 
 int __init st40pci_init(unsigned memStart, unsigned memSize)
 {
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index d36bd9410..8b819698d 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the Linux/SuperH kernel.
 #
 
-extra-y	:= head.o init_task.o vmlinux.lds.s
+extra-y	:= head.o init_task.o vmlinux.lds
 
 obj-y	:= process.o signal.o entry.o traps.o irq.o \
 	ptrace.o setup.o time.o sys_sh.o semaphore.o \
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index d78503dd2..73ec3365d 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -137,14 +137,16 @@ unlock:
 int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
 {
 	int status = 1;	/* Force the "do bottom halves" bit */
-	int retval = 0;
+	int ret, retval = 0;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
-		status |= action->flags;
-		retval |= action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
+		retval |= ret;
 		action = action->next;
 	} while (action);
 
diff --git a/arch/sh/kernel/kgdb_stub.c b/arch/sh/kernel/kgdb_stub.c
index 42638b92b..6c0370fdf 100644
--- a/arch/sh/kernel/kgdb_stub.c
+++ b/arch/sh/kernel/kgdb_stub.c
@@ -412,7 +412,7 @@ static struct task_struct *get_thread(int pid)
 	if (pid == PID_MAX) pid = 0;
 
 	/* First check via PID */
-	thread = find_task_by_pid(pid);
+	thread = find_task_by_real_pid(pid);
 
 	if (thread)
 		return thread;
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index 8ba6dd300..c9a43c8df 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -440,7 +440,7 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
 {
 	if (!newsp)
 		newsp = regs.regs[15];
-	return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0,
+	return do_fork(clone_flags, newsp, &regs, 0,
 			(int __user *)parent_tidptr, (int __user *)child_tidptr);
 }
 
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index 42868fca4..5e5cdd7f2 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -16,7 +16,6 @@
 #include <asm/uaccess.h>
 #include <asm/checksum.h>
 #include <asm/io.h>
-#include <asm/hardirq.h>
 #include <asm/delay.h>
 #include <asm/tlbflush.h>
 #include <asm/cacheflush.h>
@@ -87,7 +86,7 @@ EXPORT_SYMBOL(__udelay);
 EXPORT_SYMBOL(__ndelay);
 EXPORT_SYMBOL(__const_udelay);
 
-#define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL_NOVERS(name)
+#define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name)
 
 /* These symbols are generated by the compiler itself */
 DECLARE_EXPORT(__udivsi3);
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
index ccee2eca5..fc5ef9960 100644
--- a/arch/sh/kernel/signal.c
+++ b/arch/sh/kernel/signal.c
@@ -413,9 +413,7 @@ static void setup_frame(int sig, struct k_sigaction *ka,
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -490,9 +488,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 /*
diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c
index adb8eae9f..6ff83edf8 100644
--- a/arch/sh/kernel/smp.c
+++ b/arch/sh/kernel/smp.c
@@ -26,7 +26,6 @@
 #include <asm/atomic.h>
 #include <asm/processor.h>
 #include <asm/system.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/smp.h>
 
@@ -98,19 +97,12 @@ void __devinit smp_prepare_boot_cpu(void)
 int __cpu_up(unsigned int cpu)
 {
 	struct task_struct *tsk;
-	struct pt_regs regs;
 
-	memset(&regs, 0, sizeof(struct pt_regs));
-	tsk = copy_process(CLONE_VM | CLONE_IDLETASK, 0, &regs, 0, 0, 0);
+	tsk = fork_idle(cpu);
 
 	if (IS_ERR(tsk))
 		panic("Failed forking idle task for cpu %d\n", cpu);
 	
-	wake_up_forked_process(tsk);
-
-	init_idle(tsk, cpu);
-	unhash_process(tsk);
-	
 	tsk->thread_info->cpu = cpu;
 
 	cpu_set(cpu, cpu_online_map);
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index 3bcdf4ca4..75ed2b870 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -24,6 +24,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/smp.h>
+#include <linux/profile.h>
 
 #include <asm/processor.h>
 #include <asm/uaccess.h>
@@ -250,36 +251,6 @@ EXPORT_SYMBOL(do_settimeofday);
 /* last time the RTC clock got updated */
 static long last_rtc_update;
 
-/* Profiling definitions */
-extern unsigned long prof_cpu_mask;
-extern unsigned int * prof_buffer;
-extern unsigned long prof_len;
-extern unsigned long prof_shift;
-extern char _stext;
-
-static inline void sh_do_profile(unsigned long pc)
-{
-	/* Don't profile cpu_idle.. */
-	if (!prof_buffer || !current->pid)
-		return;
-
-	if (pc >= 0xa0000000UL && pc < 0xc0000000UL)
-		pc -= 0x20000000;
-
-	pc -= (unsigned long)&_stext;
-	pc >>= prof_shift;
-
-	/*
-	 * Don't ignore out-of-bounds PC values silently,
-	 * put them into the last histogram slot, so if
-	 * present, they will show up as a sharp peak.
-	 */
-	if (pc > prof_len - 1)
-		pc = prof_len - 1;
-
-	atomic_inc((atomic_t *)&prof_buffer[pc]);
-}
-
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
@@ -287,9 +258,7 @@ static inline void sh_do_profile(unsigned long pc)
 static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	do_timer(regs);
-
-	if (!user_mode(regs))
-		sh_do_profile(regs->pc);
+	profile_tick(CPU_PROFILING, regs);
 
 #ifdef CONFIG_HEARTBEAT
 	if (sh_mv.mv_heartbeat != NULL) 
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 923980741..51bdc1cf7 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -23,6 +23,7 @@ SECTIONS
   .text : {
 	*(.text)
 	SCHED_TEXT
+	LOCK_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x0009
@@ -75,9 +76,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : {
 	*(.initcall1.init) 
diff --git a/arch/sh/mm/fault-nommu.c b/arch/sh/mm/fault-nommu.c
index e757b2c18..34d4e0c68 100644
--- a/arch/sh/mm/fault-nommu.c
+++ b/arch/sh/mm/fault-nommu.c
@@ -26,7 +26,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index 43a9e2689..7abba2161 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -26,7 +26,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 #include <asm/kgdb.h>
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c
index 7b49b6976..030008e1f 100644
--- a/arch/sh/mm/init.c
+++ b/arch/sh/mm/init.c
@@ -214,8 +214,8 @@ void __init paging_init(void)
 	 */
 	disable_mmu();
 #endif
-
-	free_area_init_node(0, NODE_DATA(0), 0, zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
+	NODE_DATA(0)->node_mem_map = NULL;
+	free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
 	/* XXX: MRB-remove - this doesn't seem sane, should this be done somewhere else ?*/
 	mem_map = NODE_DATA(0)->node_mem_map;
 
@@ -225,7 +225,7 @@ void __init paging_init(void)
 	 */
 	zones_size[ZONE_DMA] = __MEMORY_SIZE_2ND >> PAGE_SHIFT;
 	zones_size[ZONE_NORMAL] = 0;
-	free_area_init_node(1, NODE_DATA(1), 0, zones_size, __MEMORY_START_2ND >> PAGE_SHIFT, 0);
+	free_area_init_node(1, NODE_DATA(1), zones_size, __MEMORY_START_2ND >> PAGE_SHIFT, 0);
 #endif
 }
 
diff --git a/arch/sh/mm/tlb-sh3.c b/arch/sh/mm/tlb-sh3.c
index 318d1a529..4bffcf59c 100644
--- a/arch/sh/mm/tlb-sh3.c
+++ b/arch/sh/mm/tlb-sh3.c
@@ -25,7 +25,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
diff --git a/arch/sh/mm/tlb-sh4.c b/arch/sh/mm/tlb-sh4.c
index 4b7a0bcdc..115b1b6be 100644
--- a/arch/sh/mm/tlb-sh4.c
+++ b/arch/sh/mm/tlb-sh4.c
@@ -25,7 +25,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
diff --git a/arch/sh64/Kconfig b/arch/sh64/Kconfig
index 0ac5d418e..551ba9a20 100644
--- a/arch/sh64/Kconfig
+++ b/arch/sh64/Kconfig
@@ -263,58 +263,10 @@ source "fs/Kconfig"
 
 source "arch/sh64/oprofile/Kconfig"
 
-menu "Kernel hacking"
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in Documentation/sysrq.txt. Don't say Y unless
-	  you really know what this hack does.
-
-config EARLY_PRINTK
-	bool "Early SCIF console support"
-
-config DEBUG_KERNEL_WITH_GDB_STUB
-	bool "GDB Stub kernel debug"
-
-config SH64_PROC_TLB
-	bool "Debug: report TLB fill/purge activity through /proc/tlb"
-	depends on PROC_FS
-
-config SH64_PROC_ASIDS
-	bool "Debug: report ASIDs through /proc/asids"
-	depends on PROC_FS
-
-config SH64_SR_WATCH
-	bool "Debug: set SR.WATCH to enable hardware watchpoints and trace"
-
-config SH_ALPHANUMERIC
-	bool "Enable debug outputs to on-board alphanumeric display"
-
-config SH_NO_BSS_INIT
-	bool "Avoid zeroing BSS (to speed-up startup on suitable platforms)"
-
-config FRAME_POINTER
-	bool "Compile the kernel with frame pointers"
-	default y if KGDB
-	help
-	  If you say Y here the resulting kernel image will be slightly larger
-	  and slower, but 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 pointers.
-
-endmenu
+source "arch/sh64/Kconfig.debug"
 
 source "security/Kconfig"
 
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff --git a/arch/sh64/boot/compressed/Makefile b/arch/sh64/boot/compressed/Makefile
index 3f6cbf017..9cd216718 100644
--- a/arch/sh64/boot/compressed/Makefile
+++ b/arch/sh64/boot/compressed/Makefile
@@ -12,7 +12,7 @@
 #
 
 targets		:= vmlinux vmlinux.bin vmlinux.bin.gz \
-		   head.o misc.o cache.o piggy.o vmlinux.lds.o
+		   head.o misc.o cache.o piggy.o vmlinux.lds
 
 EXTRA_AFLAGS	:= -traditional
 
@@ -25,7 +25,7 @@ OBJECTS		:= $(obj)/head.o $(obj)/misc.o $(obj)/cache.o
 ZIMAGE_OFFSET = $(shell printf "0x%8x" $$[$(CONFIG_MEMORY_START)+0x400000+0x10000])
 
 LDFLAGS_vmlinux := -Ttext $(ZIMAGE_OFFSET) -e startup \
-		    -T $(obj)/../../kernel/vmlinux.lds.s \
+		    -T $(obj)/../../kernel/vmlinux.lds \
 		    --no-warn-mismatch
 
 $(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE
@@ -41,6 +41,6 @@ $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
 LDFLAGS_piggy.o := -r --format binary --oformat elf32-sh64-linux -T
 OBJCOPYFLAGS += -R .empty_zero_page
 
-$(obj)/piggy.o: $(obj)/vmlinux.lds.s $(obj)/vmlinux.bin.gz FORCE
+$(obj)/piggy.o: $(obj)/vmlinux.lds $(obj)/vmlinux.bin.gz FORCE
 	$(call if_changed,ld)
 
diff --git a/arch/sh64/kernel/irq.c b/arch/sh64/kernel/irq.c
index bcf6385db..7d0f422e1 100644
--- a/arch/sh64/kernel/irq.c
+++ b/arch/sh64/kernel/irq.c
@@ -148,6 +148,7 @@ asmlinkage void do_NMI(unsigned long vector_num, struct pt_regs * regs)
 int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
 {
 	int status;
+	int ret;
 
 	status = 1;	/* Force the "do bottom halves" bit */
 
@@ -155,8 +156,9 @@ int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction *
                 local_irq_enable();
 
 	do {
-		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
diff --git a/arch/sh64/kernel/pci_sh5.c b/arch/sh64/kernel/pci_sh5.c
index c2b4f00e2..842a24373 100644
--- a/arch/sh64/kernel/pci_sh5.c
+++ b/arch/sh64/kernel/pci_sh5.c
@@ -48,12 +48,7 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d)
 		}
 	}
 }
-
-/* Add future fixups here... */
-struct pci_fixup pcibios_fixups[] = {
-	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,	PCI_ANY_ID,	pci_fixup_ide_bases },
-	{ 0 }
-};
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
 
 char * __init pcibios_setup(char *str)
 {
diff --git a/arch/sh64/kernel/process.c b/arch/sh64/kernel/process.c
index f9e82274e..13cec3579 100644
--- a/arch/sh64/kernel/process.c
+++ b/arch/sh64/kernel/process.c
@@ -820,7 +820,7 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
 {
 	if (!newsp)
 		newsp = pregs->regs[15];
-	return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, pregs, 0, 0, 0);
+	return do_fork(clone_flags, newsp, pregs, 0, 0, 0);
 }
 
 /*
@@ -901,7 +901,7 @@ unsigned long get_wchan(struct task_struct *p)
 	 */
 	pc = thread_saved_pc(p);
 
-#if CONFIG_FRAME_POINTER
+#ifdef CONFIG_FRAME_POINTER
 	if (in_sh64_switch_to(pc)) {
 		sh64_switch_to_fp = (long) p->thread.sp;
 		/* r14 is saved at offset 4 in the sh64_switch_to frame */
diff --git a/arch/sh64/kernel/ptrace.c b/arch/sh64/kernel/ptrace.c
index 887e89a45..c48bc4a27 100644
--- a/arch/sh64/kernel/ptrace.c
+++ b/arch/sh64/kernel/ptrace.c
@@ -311,11 +311,8 @@ asmlinkage void syscall_trace(void)
 	if (!(tsk->ptrace & PT_PTRACED))
 		return;
 
-	tsk->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-				    ? 0x80 : 0);
-	tsk->state = TASK_STOPPED;
-	notify_parent(tsk, SIGCHLD);
-	schedule();
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+				 ? 0x80 : 0));
 	/*
 	 * this isn't the same as continuing with a signal, but it will do
 	 * for normal use.  strace only continues with a signal if the
diff --git a/arch/sh64/kernel/sh_ksyms.c b/arch/sh64/kernel/sh_ksyms.c
index 80712f1ef..36cd5de95 100644
--- a/arch/sh64/kernel/sh_ksyms.c
+++ b/arch/sh64/kernel/sh_ksyms.c
@@ -25,7 +25,6 @@
 #include <asm/uaccess.h>
 #include <asm/checksum.h>
 #include <asm/io.h>
-#include <asm/hardirq.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
 
@@ -59,17 +58,17 @@ EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(screen_info);
 #endif
 
-EXPORT_SYMBOL_NOVERS(__down);
-EXPORT_SYMBOL_NOVERS(__down_trylock);
-EXPORT_SYMBOL_NOVERS(__up);
-EXPORT_SYMBOL_NOVERS(__put_user_asm_l);
-EXPORT_SYMBOL_NOVERS(__get_user_asm_l);
-EXPORT_SYMBOL_NOVERS(memcmp);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memscan);
-EXPORT_SYMBOL_NOVERS(strchr);
-EXPORT_SYMBOL_NOVERS(strlen);
+EXPORT_SYMBOL(__down);
+EXPORT_SYMBOL(__down_trylock);
+EXPORT_SYMBOL(__up);
+EXPORT_SYMBOL(__put_user_asm_l);
+EXPORT_SYMBOL(__get_user_asm_l);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strlen);
 
 EXPORT_SYMBOL(flush_dcache_page);
 
@@ -78,7 +77,7 @@ EXPORT_SYMBOL(flush_dcache_page);
 extern void __sdivsi3(void);
 extern void __muldi3(void);
 extern void __udivsi3(void);
-EXPORT_SYMBOL_NOVERS(__sdivsi3);
-EXPORT_SYMBOL_NOVERS(__muldi3);
-EXPORT_SYMBOL_NOVERS(__udivsi3);
+EXPORT_SYMBOL(__sdivsi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__udivsi3);
 
diff --git a/arch/sh64/kernel/signal.c b/arch/sh64/kernel/signal.c
index 376b8998b..a848fbdb1 100644
--- a/arch/sh64/kernel/signal.c
+++ b/arch/sh64/kernel/signal.c
@@ -520,9 +520,7 @@ static void setup_frame(int sig, struct k_sigaction *ka,
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -628,9 +626,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 /*
diff --git a/arch/sh64/kernel/time.c b/arch/sh64/kernel/time.c
index 128bd22af..b3738ed37 100644
--- a/arch/sh64/kernel/time.c
+++ b/arch/sh64/kernel/time.c
@@ -298,37 +298,6 @@ static int set_rtc_time(unsigned long nowtime)
 /* last time the RTC clock got updated */
 static long last_rtc_update = 0;
 
-static inline void sh64_do_profile(struct pt_regs *regs)
-{
-	extern int _stext;
-	unsigned long pc;
-
-	profile_hook(regs);
-
-	if (user_mode(regs))
-		return;
-
-	/* Don't profile cpu_idle..  */
-	if (!prof_buffer || !current->pid)
-		return;
-
-	pc = instruction_pointer(regs);
-	pc -= (unsigned long) &_stext;
-	pc >>= prof_shift;
-
-	/*
-	 * Don't ignore out-of-bounds PC values silently, put them into the
-	 * last histogram slot, so if present, they will show up as a sharp
-	 * peak.
-	 */
-	if (pc > prof_len - 1)
-		pc = prof_len - 1;
-
-	/* We could just be sloppy and not lock against a re-entry on this
-	   increment, but the profiling code won't always be linked in anyway. */
-	atomic_inc((atomic_t *)&prof_buffer[pc]);
-}
-
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
@@ -340,8 +309,7 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg
 	ctc_last_interrupt = (unsigned long) current_ctc;
 
 	do_timer(regs);
-
-	sh64_do_profile(regs);
+	profile_tick(CPU_PROFILING, regs);
 
 #ifdef CONFIG_HEARTBEAT
 	{
diff --git a/arch/sh64/kernel/vmlinux.lds.S b/arch/sh64/kernel/vmlinux.lds.S
index a3fba816b..7d9f7a633 100644
--- a/arch/sh64/kernel/vmlinux.lds.S
+++ b/arch/sh64/kernel/vmlinux.lds.S
@@ -59,6 +59,7 @@ SECTIONS
 	*(.text64)
         *(.text..SHmedia32)
 	SCHED_TEXT
+	LOCK_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 #ifdef CONFIG_LITTLE_ENDIAN
@@ -106,9 +107,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : C_PHYS(.init.setup) { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : C_PHYS(__param) { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : C_PHYS(.initcall.init) {
   	*(.initcall1.init)
diff --git a/arch/sh64/mm/fault.c b/arch/sh64/mm/fault.c
index b5ab4a88c..d1190b415 100644
--- a/arch/sh64/mm/fault.c
+++ b/arch/sh64/mm/fault.c
@@ -30,7 +30,6 @@
 #include <asm/tlb.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/registers.h>		/* required by inline asm statements */
 
diff --git a/arch/sh64/mm/init.c b/arch/sh64/mm/init.c
index 17cdeb425..09cd9c879 100644
--- a/arch/sh64/mm/init.c
+++ b/arch/sh64/mm/init.c
@@ -122,8 +122,8 @@ void __init paging_init(void)
 	 * All memory is good as ZONE_NORMAL (fall-through) and ZONE_DMA.
          */
 	zones_size[ZONE_DMA] = MAX_LOW_PFN - START_PFN;
-
-	free_area_init_node(0, NODE_DATA(0), 0, zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
+	NODE_DATA(0)->node_mem_map = NULL;
+	free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
 
 	/* XXX: MRB-remove - this doesn't seem sane, should this be done somewhere else ?*/
 	mem_map = NODE_DATA(0)->node_mem_map;
diff --git a/arch/sh64/mm/tlbmiss.c b/arch/sh64/mm/tlbmiss.c
index a69f7751c..69f686c88 100644
--- a/arch/sh64/mm/tlbmiss.c
+++ b/arch/sh64/mm/tlbmiss.c
@@ -40,7 +40,6 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/registers.h>		/* required by inline asm statements */
 
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 02ce6ccd3..d39216dc5 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -23,8 +23,7 @@ config GENERIC_ISA_DMA
 
 source "init/Kconfig"
 
-
-menu "General setup"
+menu "General machine setup"
 
 config VT
 	bool
@@ -217,8 +216,8 @@ config SUN_PM
 	bool
 	default y
 	help
-	  Enable power management and CPU standby features on supported 
-	  SPARC platforms. 
+	  Enable power management and CPU standby features on supported
+	  SPARC platforms.
 
 config SUN4
 	bool "Support for SUN4 machines (disables SUN4[CDM] support)"
@@ -380,77 +379,7 @@ source "drivers/usb/Kconfig"
 
 source "drivers/char/watchdog/Kconfig"
 
-menu "Kernel hacking"
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
-config DEBUG_STACK_USAGE
-	bool "Enable stack utilization instrumentation"
-	depends on DEBUG_KERNEL
-	help
-	  Enables the display of the minimum amount of free stack which each
-	  task has ever had available in the sysrq-T and sysrq-P debug output.
-
-	  This option will slow down process creation somewhat.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SPINLOCK
-	bool "Spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here and build SMP to catch missing spinlock initialization
-	  and certain other kinds of spinlock errors commonly made.  This is
-	  best used in conjunction with the NMI watchdog so that spinlock
-	  deadlocks are also debuggable.
-
-config DEBUG_HIGHMEM
-	bool "Highmem debugging"
-	depends on DEBUG_KERNEL && HIGHMEM
-	help
-	  This options enables additional error checking for high memory
-	  systems.  Disable for production systems.
-
-config DEBUG_SPINLOCK_SLEEP
-	bool "Sleep-inside-spinlock checking"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, various routines which may sleep will become very
-	  noisy if they are called with a spinlock held.	
-
-config DEBUG_BUGVERBOSE
-	bool "Verbose BUG() reporting (adds 70K)"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to make BUG() panics output the file name and line number
-	  of the BUG call as well as the EIP and oops trace.  This aids
-	  debugging but costs about 70-100K of memory.
-
-endmenu
+source "arch/sparc/Kconfig.debug"
 
 source "kernel/vserver/Kconfig"
 
@@ -459,4 +388,3 @@ source "security/Kconfig"
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index 15fcf89e1..7b3bbaf08 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -13,7 +13,7 @@
 
 AS              := $(AS) -32
 LDFLAGS		:= -m elf32_sparc
-CHECK		:= $(CHECK) -D__sparc__=1
+CHECKFLAGS	+= -D__sparc__
 
 #CFLAGS := $(CFLAGS) -g -pipe -fcall-used-g5 -fcall-used-g7
 CFLAGS := $(CFLAGS) -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile
index b19cc8689..b36508431 100644
--- a/arch/sparc/boot/Makefile
+++ b/arch/sparc/boot/Makefile
@@ -7,28 +7,52 @@
 ROOT_IMG	:= /usr/src/root.img
 ELFTOAOUT	:= elftoaout
 
-host-progs	:= piggyback btfixupprep
-targets		:= tftpboot.img btfix.o btfix.s image
+hostprogs-y	:= piggyback btfixupprep
+targets		:= tftpboot.img btfix.o btfix.S image
 
 quiet_cmd_elftoaout	= ELFTOAOUT $@
       cmd_elftoaout	= $(ELFTOAOUT) $(obj)/image -o $@
-quiet_cmd_piggy		= PIGGY $@
+quiet_cmd_piggy		= PIGGY   $@
       cmd_piggy		= $(obj)/piggyback $@ $(obj)/System.map $(ROOT_IMG)
-quiet_cmd_btfix		= BTFIX $@
+quiet_cmd_btfix		= BTFIX   $@
       cmd_btfix		= $(OBJDUMP) -x vmlinux | $(obj)/btfixupprep > $@
+quiet_cmd_sysmap        = SYSMAP  $(obj)/System.map
+      cmd_sysmap        = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
+quiet_cmd_image = LD      $@
+      cmd_image = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_$(@F)) -o $@
+
+define rule_image
+	$(if $($(quiet)cmd_image),               \
+	  echo '  $($(quiet)cmd_image)' &&)      \
+	  $(cmd_image);                          \
+	$(if $($(quiet)cmd_sysmap),              \
+	  echo '  $($(quiet)cmd_sysmap)' &&)  \
+	$(cmd_sysmap) $@ $(obj)/System.map;      \
+	if [ $$? -ne 0 ]; then                   \
+		rm -f $@;                        \
+		/bin/false;                      \
+	fi;                                      \
+	echo 'cmd_$@ := $(cmd_image)' > $(@D)/.$(@F).cmd
+endef
 
 BTOBJS := $(HEAD_Y) $(INIT_Y)
 BTLIBS := $(CORE_Y) $(LIBS_Y) $(DRIVERS_Y) $(NET_Y)
-LDFLAGS_image := -T arch/sparc/kernel/vmlinux.lds.s $(BTOBJS) --start-group $(BTLIBS) --end-group $(kallsyms.o)
+LDFLAGS_image := -T arch/sparc/kernel/vmlinux.lds $(BTOBJS) \
+                  --start-group $(BTLIBS) --end-group \
+                  $(kallsyms.o) $(obj)/btfix.o
 
-# Actual linking
+# Link the final image including btfixup'ed symbols.
+# This is a replacement for the link done in the top-level Makefile.
+# Note: No dependency on the prerequisite files since that would require
+# make to try check if they are updated - and due to changes
+# in gcc options (path for example) this would result in
+# these files being recompiled for each build.
 $(obj)/image: $(obj)/btfix.o FORCE
-	$(call if_changed,ld)
-	$(NM) $@ | grep -v  '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > $(obj)/System.map
+	$(call if_changed_rule,image)
 
 $(obj)/tftpboot.img: $(obj)/piggyback $(obj)/System.map $(obj)/image FORCE
 	$(call if_changed,elftoaout)
 	$(call if_changed,piggy)
 
-$(obj)/btfix.s: $(obj)/btfixupprep vmlinux FORCE
+$(obj)/btfix.S: $(obj)/btfixupprep vmlinux FORCE
 	$(call if_changed,btfix)
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index fcf149e00..3d22ba2af 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-extra-y		:= head.o init_task.o vmlinux.lds.s
+extra-y		:= head.o init_task.o vmlinux.lds
 
 EXTRA_AFLAGS	:= -ansi
 
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index 14a4b9593..624e2a6ed 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -858,7 +858,7 @@ vac_hwflush_patch1_on:		addcc	%l7, -PAGE_SIZE, %l7
 vac_hwflush_patch2_on:		sta	%g0, [%l3 + %l7] ASI_HWFLUSHSEG
 
 	.globl	invalid_segment_patch1, invalid_segment_patch2
-	.globl	num_context_patch1, num_context_patch2
+	.globl	num_context_patch1
 	.globl	vac_linesize_patch, vac_hwflush_patch1
 	.globl	vac_hwflush_patch2
 
diff --git a/arch/sparc/kernel/init_task.c b/arch/sparc/kernel/init_task.c
index af81a999f..fc31de66b 100644
--- a/arch/sparc/kernel/init_task.c
+++ b/arch/sparc/kernel/init_task.c
@@ -23,6 +23,6 @@ EXPORT_SYMBOL(init_task);
  * in etrap.S which assumes it.
  */
 union thread_union init_thread_union
-	__attribute__((section (".text,#alloc")))
+	__attribute__((section (".text\"\n\t#")))
 	__attribute__((aligned (THREAD_SIZE)))
 	= { INIT_THREAD_INFO(init_task) };
diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c
index cfabf35ee..4e0ed320d 100644
--- a/arch/sparc/kernel/irq.c
+++ b/arch/sparc/kernel/irq.c
@@ -45,7 +45,6 @@
 #include <asm/io.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
-#include <asm/hardirq.h>
 #include <asm/pcic.h>
 #include <asm/cacheflush.h>
 
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index bc52cd482..c982473d1 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -36,10 +36,6 @@
 #include <asm/uaccess.h>
 
 
-struct pci_fixup pcibios_fixups[] = {
-	{ 0 }
-};
-
 unsigned int pcic_pin_to_irq(unsigned int pin, char *name);
 
 /*
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
index 4ff019336..1dc918135 100644
--- a/arch/sparc/kernel/process.c
+++ b/arch/sparc/kernel/process.c
@@ -435,8 +435,6 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags,
 {
 	unsigned long parent_tid_ptr, child_tid_ptr;
 
-	clone_flags &= ~CLONE_IDLETASK;
-
 	parent_tid_ptr = regs->u_regs[UREG_I2];
 	child_tid_ptr = regs->u_regs[UREG_I4];
 
diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c
index 949072b1c..d39739182 100644
--- a/arch/sparc/kernel/ptrace.c
+++ b/arch/sparc/kernel/ptrace.c
@@ -618,12 +618,9 @@ asmlinkage void syscall_trace(void)
 		return;
 	if (!(current->ptrace & PT_PTRACED))
 		return;
-	current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-					? 0x80 : 0);
-	current->state = TASK_STOPPED;
 	current->thread.flags ^= MAGIC_CONSTANT;
-	notify_parent(current, SIGCHLD);
-	schedule();
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+				 ? 0x80 : 0));
 	/*
 	 * this isn't the same as continuing with a signal, but it will do
 	 * for normal use.  strace only continues with a signal if the
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c
index 7bc43b4c0..55352ed85 100644
--- a/arch/sparc/kernel/setup.c
+++ b/arch/sparc/kernel/setup.c
@@ -44,7 +44,6 @@
 #include <asm/kdebug.h>
 #include <asm/mbus.h>
 #include <asm/idprom.h>
-#include <asm/hardirq.h>
 #include <asm/machines.h>
 #include <asm/cpudata.h>
 #include <asm/setup.h>
diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c
index 28edf9319..276860da5 100644
--- a/arch/sparc/kernel/signal.c
+++ b/arch/sparc/kernel/signal.c
@@ -274,7 +274,7 @@ static inline void do_new_sigreturn (struct pt_regs *regs)
 	return;
 
 segv_and_exit:
-	do_exit(SIGSEGV);
+	force_sig(SIGSEGV, current);
 }
 
 asmlinkage void do_sigreturn(struct pt_regs *regs)
@@ -341,7 +341,7 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
 	return;
 
 segv_and_exit:
-	send_sig(SIGSEGV, current, 1);
+	force_sig(SIGSEGV, current);
 }
 
 asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
@@ -401,7 +401,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
 	spin_unlock_irq(&current->sighand->siglock);
 	return;
 segv:
-	send_sig(SIGSEGV, current, 1);
+	force_sig(SIGSEGV, current);
 }
 
 /* Checks if the fp is valid */
@@ -549,7 +549,7 @@ setup_frame(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *old
 sigill_and_return:
 	do_exit(SIGILL);
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signr, current);
 }
 
 
@@ -635,6 +635,7 @@ new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
 	regs->u_regs[UREG_FP] = (unsigned long) sf;
 	regs->u_regs[UREG_I0] = signo;
 	regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
+	regs->u_regs[UREG_I2] = (unsigned long) &sf->info;
 
 	/* 4. signal handler */
 	regs->pc = (unsigned long) ka->sa.sa_handler;
@@ -662,7 +663,7 @@ new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
 sigill_and_return:
 	do_exit(SIGILL);
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signo, current);
 }
 
 static inline void
@@ -719,6 +720,7 @@ new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
 	regs->u_regs[UREG_FP] = (unsigned long) sf;
 	regs->u_regs[UREG_I0] = signo;
 	regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
+	regs->u_regs[UREG_I2] = (unsigned long) &sf->regs;
 
 	regs->pc = (unsigned long) ka->sa.sa_handler;
 	regs->npc = (regs->pc + 4);
@@ -744,7 +746,7 @@ new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
 sigill:
 	do_exit(SIGILL);
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signo, current);
 }
 
 /* Setup a Solaris stack frame */
@@ -874,7 +876,7 @@ setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc,
 sigill_and_return:
 	do_exit(SIGILL);
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signr, current);
 }
 
 asmlinkage int svr4_getcontext(svr4_ucontext_t __user *uc, struct pt_regs *regs)
@@ -887,7 +889,7 @@ asmlinkage int svr4_getcontext(svr4_ucontext_t __user *uc, struct pt_regs *regs)
 	synchronize_user_stack();
 
 	if (current_thread_info()->w_saved)
-		goto sigsegv_and_return;
+		return -EFAULT;
 
 	err = clear_user(uc, sizeof(*uc));
 	if (err)
@@ -928,9 +930,6 @@ asmlinkage int svr4_getcontext(svr4_ucontext_t __user *uc, struct pt_regs *regs)
 	 * we have already stuffed all of it with sync_user_stack
 	 */
 	return (err ? -EFAULT : 0);
-
-sigsegv_and_return:
-	do_exit(SIGSEGV);
 }
 
 /* Set the context for a svr4 application, this is Solaris way to sigreturn */
@@ -1016,7 +1015,7 @@ asmlinkage int svr4_setcontext(svr4_ucontext_t __user *c, struct pt_regs *regs)
 	return (err ? -EFAULT : 0);
 
 sigsegv_and_return:
-	do_exit(SIGSEGV);
+	force_sig(SIGSEGV, current);
 }
 
 static inline void
@@ -1034,8 +1033,6 @@ handle_signal(unsigned long signr, struct k_sigaction *ka,
 		else
 			setup_frame(&ka->sa, regs, signr, oldset, info);
 	}
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
 	if (!(ka->sa.sa_flags & SA_NOMASK)) {
 		spin_lock_irq(&current->sighand->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -1075,6 +1072,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
 {
 	siginfo_t info;
 	struct sparc_deliver_cookie cookie;
+	struct k_sigaction ka;
 	int signr;
 
 	/*
@@ -1094,15 +1092,12 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
 	if (!oldset)
 		oldset = &current->blocked;
 
-	signr = get_signal_to_deliver(&info, regs, &cookie);
+	signr = get_signal_to_deliver(&info, &ka, regs, &cookie);
 	if (signr > 0) {
-		struct k_sigaction *ka;
-		
-		ka = &current->sighand->action[signr-1];
-
 		if (cookie.restart_syscall)
-			syscall_restart(cookie.orig_i0, regs, &ka->sa);
-		handle_signal(signr, ka, &info, oldset, regs, svr4_signal);
+			syscall_restart(cookie.orig_i0, regs, &ka.sa);
+		handle_signal(signr, &ka, &info, oldset,
+			      regs, svr4_signal);
 		return 1;
 	}
 	if (cookie.restart_syscall &&
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index 46591a15e..f11dd14db 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -30,7 +30,6 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/oplib.h>
-#include <asm/hardirq.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/cpudata.h>
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index fdaacfa47..7282bc3ee 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -41,7 +41,6 @@
 #include <asm/smp.h>
 #include <asm/mostek.h>
 #include <asm/ptrace.h>
-#include <asm/hardirq.h>
 #include <asm/user.h>
 #include <asm/uaccess.h>
 #include <asm/checksum.h>
@@ -214,6 +213,10 @@ EXPORT_SYMBOL(pci_dma_sync_single_for_cpu);
 EXPORT_SYMBOL(pci_dma_sync_single_for_device);
 EXPORT_SYMBOL(pci_dma_sync_sg_for_cpu);
 EXPORT_SYMBOL(pci_dma_sync_sg_for_device);
+EXPORT_SYMBOL(pci_map_sg);
+EXPORT_SYMBOL(pci_unmap_sg);
+EXPORT_SYMBOL(pci_map_page);
+EXPORT_SYMBOL(pci_unmap_page);
 /* Actually, ioremap/iounmap are not PCI specific. But it is ok for drivers. */
 EXPORT_SYMBOL(ioremap);
 EXPORT_SYMBOL(iounmap);
@@ -298,6 +301,9 @@ EXPORT_SYMBOL(csum_partial);
 /* Cache flushing.  */
 EXPORT_SYMBOL(sparc_flush_page_to_ram);
 
+/* For when serial stuff is built as modules. */
+EXPORT_SYMBOL(sun_do_break);
+
 EXPORT_SYMBOL(__ret_efault);
 
 EXPORT_SYMBOL(memcmp);
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index 9f659c2f4..1de4c8a39 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -19,6 +19,7 @@
 #include <linux/spinlock.h>
 #include <linux/mm.h>
 #include <linux/swap.h>
+#include <linux/profile.h>
 
 #include <asm/ptrace.h>
 #include <asm/atomic.h>
@@ -29,7 +30,6 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/oplib.h>
-#include <asm/hardirq.h>
 #include <asm/sbus.h>
 #include <asm/sbi.h>
 #include <asm/tlbflush.h>
@@ -201,18 +201,9 @@ void __init smp4d_boot_cpus(void)
 			int no;
 
 			/* Cook up an idler for this guy. */
-			kernel_thread(start_secondary, NULL, CLONE_IDLETASK);
-
+			p = fork_idle(i);
 			cpucount++;
-
-			p = prev_task(&init_task);
-
-			init_idle(p, i);
-
 			current_set[i] = p->thread_info;
-
-			unhash_process(p);
-
 			for (no = 0; !cpu_find_by_instance(no, NULL, &mid)
 				     && mid != i; no++) ;
 
@@ -418,8 +409,6 @@ void smp4d_message_pass(int target, int msg, unsigned long data, int wait)
 	panic("Bogon SMP message pass.");
 }
 
-extern void sparc_do_profile(unsigned long pc, unsigned long o7);
-
 void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
 {
 	int cpu = hard_smp4d_processor_id();
@@ -437,8 +426,7 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
 		show_leds(cpu);
 	}
 
-	if(!user_mode(regs))
-		sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]);
+	profile_tick(CPU_PROFILING, regs);
 
 	if(!--prof_counter(cpu)) {
 		int user = user_mode(regs);
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index f2fc64edc..100433e05 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -16,6 +16,7 @@
 #include <linux/spinlock.h>
 #include <linux/mm.h>
 #include <linux/swap.h>
+#include <linux/profile.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 
@@ -28,7 +29,6 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/oplib.h>
-#include <asm/hardirq.h>
 #include <asm/cpudata.h>
 
 #define IRQ_RESCHEDULE		13
@@ -173,18 +173,9 @@ void __init smp4m_boot_cpus(void)
 			int timeout;
 
 			/* Cook up an idler for this guy. */
-			kernel_thread(start_secondary, NULL, CLONE_IDLETASK);
-
+			p = fork_idle(i);
 			cpucount++;
-
-			p = prev_task(&init_task);
-
-			init_idle(p, i);
-
 			current_set[i] = p->thread_info;
-
-			unhash_process(p);
-
 			/* See trampoline.S for details... */
 			entry += ((i-1) * 3);
 
@@ -400,16 +391,13 @@ void smp4m_cross_call_irq(void)
 	ccall_info.processors_out[i] = 1;
 }
 
-extern void sparc_do_profile(unsigned long pc, unsigned long o7);
-
 void smp4m_percpu_timer_interrupt(struct pt_regs *regs)
 {
 	int cpu = smp_processor_id();
 
 	clear_profile_irq(cpu);
 
-	if(!user_mode(regs))
-		sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]);
+	profile_tick(CPU_PROFILING, regs);
 
 	if(!--prof_counter(cpu)) {
 		int user = user_mode(regs);
diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
index 56c8c878d..5af2fc5bc 100644
--- a/arch/sparc/kernel/systbls.S
+++ b/arch/sparc/kernel/systbls.S
@@ -74,7 +74,7 @@ sys_call_table:
 /*260*/	.long sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
 /*265*/	.long sys_timer_delete, sys_timer_create, sys_vserver, sys_io_setup, sys_io_destroy
 /*270*/	.long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
-/*275*/	.long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_ni_syscall
+/*275*/	.long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
 /*280*/	.long sys_ni_syscall, sys_ni_syscall, sys_ni_syscall
 
 #ifdef CONFIG_SUNOS_EMUL
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
index bdec61be6..60507d394 100644
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -79,38 +79,26 @@ struct intersil *intersil_clock;
 
 #endif
 
-static spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED;
-
-/* 32-bit Sparc specific profiling function. */
-void sparc_do_profile(unsigned long pc, unsigned long o7)
+unsigned long profile_pc(struct pt_regs *regs)
 {
-	if(prof_buffer && current->pid) {
-		extern int _stext;
-		extern int __copy_user_begin, __copy_user_end;
-		extern int __atomic_begin, __atomic_end;
-		extern int __bzero_begin, __bzero_end;
-		extern int __bitops_begin, __bitops_end;
-
-		if ((pc >= (unsigned long) &__copy_user_begin &&
-		     pc < (unsigned long) &__copy_user_end) ||
-		    (pc >= (unsigned long) &__atomic_begin &&
-		     pc < (unsigned long) &__atomic_end) ||
-		    (pc >= (unsigned long) &__bzero_begin &&
-		     pc < (unsigned long) &__bzero_end) ||
-		    (pc >= (unsigned long) &__bitops_begin &&
-		     pc < (unsigned long) &__bitops_end))
-			pc = o7;
-
-		pc -= (unsigned long) &_stext;
-		pc >>= prof_shift;
-
-		spin_lock(&ticker_lock);
-		if(pc < prof_len)
-			prof_buffer[pc]++;
-		else
-			prof_buffer[prof_len - 1]++;
-		spin_unlock(&ticker_lock);
-	}
+	extern char __copy_user_begin[], __copy_user_end[];
+	extern char __atomic_begin[], __atomic_end[];
+	extern char __bzero_begin[], __bzero_end[];
+	extern char __bitops_begin[], __bitops_end[];
+
+	unsigned long pc = regs->pc;
+
+	if (in_lock_functions(pc) ||
+	    (pc >= (unsigned long) __copy_user_begin &&
+	     pc < (unsigned long) __copy_user_end) ||
+	    (pc >= (unsigned long) __atomic_begin &&
+	     pc < (unsigned long) __atomic_end) ||
+	    (pc >= (unsigned long) __bzero_begin &&
+	     pc < (unsigned long) __bzero_end) ||
+	    (pc >= (unsigned long) __bitops_begin &&
+	     pc < (unsigned long) __bitops_end))
+		pc = regs->u_regs[UREG_RETPC];
+	return pc;
 }
 
 __volatile__ unsigned int *master_l10_counter;
@@ -129,8 +117,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 	static long last_rtc_update;
 
 #ifndef CONFIG_SMP
-	if(!user_mode(regs))
-		sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]);
+	profile_tick(CPU_PROFILING, regs);
 #endif
 
 	/* Protect counter clear so that do_gettimeoffset works */
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 8d4bbfaf3..38938d2e6 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -13,6 +13,7 @@ SECTIONS
   {
     *(.text)
     SCHED_TEXT
+    LOCK_TEXT
     *(.gnu.warning)
   } =0
   _etext = .;
@@ -46,9 +47,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : {
 	*(.initcall1.init) 
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index c18475eaa..d5593b5d2 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -1341,7 +1341,7 @@ void __init srmmu_paging_init(void)
 		zones_size[ZONE_HIGHMEM] = npages;
 		zholes_size[ZONE_HIGHMEM] = npages - calc_highpages();
 
-		free_area_init_node(0, &contig_page_data, NULL, zones_size,
+		free_area_init_node(0, &contig_page_data, zones_size,
 				    pfn_base, zholes_size);
 		mem_map = contig_page_data.node_mem_map;
 	}
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
index b56b67b45..fd85c7b01 100644
--- a/arch/sparc/mm/sun4c.c
+++ b/arch/sparc/mm/sun4c.c
@@ -379,7 +379,7 @@ extern unsigned long invalid_segment_patch1, invalid_segment_patch1_ff;
 extern unsigned long invalid_segment_patch2, invalid_segment_patch2_ff;
 extern unsigned long invalid_segment_patch1_1ff, invalid_segment_patch2_1ff;
 extern unsigned long num_context_patch1, num_context_patch1_16;
-extern unsigned long num_context_patch2, num_context_patch2_16;
+extern unsigned long num_context_patch2_16;
 extern unsigned long vac_linesize_patch, vac_linesize_patch_32;
 extern unsigned long vac_hwflush_patch1, vac_hwflush_patch1_on;
 extern unsigned long vac_hwflush_patch2, vac_hwflush_patch2_on;
@@ -2114,7 +2114,7 @@ void __init sun4c_paging_init(void)
 		zones_size[ZONE_HIGHMEM] = npages;
 		zholes_size[ZONE_HIGHMEM] = npages - calc_highpages();
 
-		free_area_init_node(0, &contig_page_data, NULL, zones_size,
+		free_area_init_node(0, &contig_page_data, zones_size,
 				    pfn_base, zholes_size);
 		mem_map = contig_page_data.node_mem_map;
 	}
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index c85f8f25d..0bcd075f2 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -12,10 +12,13 @@ config MMU
 	bool
 	default y
 
-source "init/Kconfig"
+config TIME_INTERPOLATION
+	bool
+	default y
 
+source "init/Kconfig"
 
-menu "General setup"
+menu "General machine setup"
 
 config BBC_I2C
 	tristate "UltraSPARC-III bootbus i2c controller driver"
@@ -549,7 +552,6 @@ config UNIX98_PTY_COUNT
 
 endmenu
 
-
 menu "XFree86 DRI support"
 
 config DRM
@@ -604,109 +606,7 @@ source "drivers/char/watchdog/Kconfig"
 
 source "arch/sparc64/oprofile/Kconfig"
 
-menu "Kernel hacking"
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
-config DEBUG_STACK_USAGE
-	bool "Enable stack utilization instrumentation"
-	depends on DEBUG_KERNEL
-	help
-	  Enables the display of the minimum amount of free stack which each
-	  task has ever had available in the sysrq-T and sysrq-P debug output.
-
-	  This option will slow down process creation somewhat.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SPINLOCK
-	bool "Spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here and build SMP to catch missing spinlock initialization
-	  and certain other kinds of spinlock errors commonly made.  This is
-	  best used in conjunction with the NMI watchdog so that spinlock
-	  deadlocks are also debuggable.
-
-config DEBUG_SPINLOCK_SLEEP
-	bool "Sleep-inside-spinlock checking"
-	depends DEBUG_KERNEL
-	help
-	  If you say Y here, various routines which may sleep will become very
-	  noisy if they are called with a spinlock held.	
-
-config DEBUG_BUGVERBOSE
-	bool "Verbose BUG() reporting (adds 70K)"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to make BUG() panics output the file name and line number
-	  of the BUG call as well as the EIP and oops trace.  This aids
-	  debugging but costs about 70-100K of memory.
-
-config DEBUG_DCFLUSH
-	bool "D-cache flush debugging"
-	depends on DEBUG_KERNEL
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  If you don't debug the kernel, you can say N.
-	  
-config STACK_DEBUG
-	depends on DEBUG_KERNEL
-	bool "Stack Overflow Detection Support"
-
-config DEBUG_BOOTMEM
-	depends on DEBUG_KERNEL
-	bool "Debug BOOTMEM initialization"
-
-# We have a custom atomic_dec_and_lock() implementation but it's not
-# compatible with spinlock debugging so we need to fall back on
-# the generic version in that case.
-config HAVE_DEC_LOCK
-	bool
-	depends on SMP && !DEBUG_SPINLOCK
-	default y
-
-config MCOUNT
-	bool
-	depends on STACK_DEBUG
-	default y
-
-config FRAME_POINTER
-	bool
-	depends on MCOUNT
-	default y
-
-endmenu
+source "arch/sparc64/Kconfig.debug"
 
 source "kernel/vserver/Kconfig"
 
@@ -715,4 +615,3 @@ source "security/Kconfig"
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff --git a/arch/sparc64/Makefile b/arch/sparc64/Makefile
index fc57c40c2..58d4c91ca 100644
--- a/arch/sparc64/Makefile
+++ b/arch/sparc64/Makefile
@@ -8,16 +8,16 @@
 # Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
 #
 
-CHECK		:= $(CHECK) -D__sparc__=1 -D__sparc_v9__=1
+CHECKFLAGS	+= -D__sparc__ -D__sparc_v9__
 
-AFLAGS_vmlinux.lds.o += -Usparc
+CPPFLAGS_vmlinux.lds += -Usparc
 
 CC		:= $(shell if $(CC) -m64 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo $(CC); else echo sparc64-linux-gcc; fi )
 
-NEW_GCC := $(shell if $(CC) -m64 -mcmodel=medlow -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo y; else echo n; fi; )
+NEW_GCC := $(call cc-option-yn, -m64 -mcmodel=medlow)
 NEW_GAS := $(shell if $(LD) -V 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi)
 UNDECLARED_REGS := $(shell if $(CC) -c -x assembler /dev/null -Wa,--help | grep undeclared-regs > /dev/null; then echo y; else echo n; fi; )
-INLINE_LIMIT := $(shell if $(CC) -m64 -finline-limit=100000 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo y; else echo n; fi; )
+INLINE_LIMIT := $(call cc-option-yn, -m64 -finline-limit=100000)
 
 export NEW_GCC
 
diff --git a/arch/sparc64/boot/Makefile b/arch/sparc64/boot/Makefile
index 5eb14ff1c..6968a6da5 100644
--- a/arch/sparc64/boot/Makefile
+++ b/arch/sparc64/boot/Makefile
@@ -7,7 +7,7 @@
 ROOT_IMG	:= /usr/src/root.img
 ELFTOAOUT	:= elftoaout
 
-host-progs	:= piggyback
+hostprogs-y	:= piggyback
 targets		:= image tftpboot.img vmlinux.aout
 
 quiet_cmd_elftoaout = ELF2AOUT $@
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 7fa2d47a6..1b2f3c2cb 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,8 +1,11 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc3
+# Sun Oct  3 14:28:53 2004
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
+CONFIG_TIME_INTERPOLATION=y
 
 #
 # Code maturity level options
@@ -13,6 +16,7 @@ CONFIG_CLEAN_COMPILE=y
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
@@ -33,6 +37,8 @@ CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -46,7 +52,7 @@ CONFIG_KMOD=y
 CONFIG_STOP_MACHINE=y
 
 #
-# General setup
+# General machine setup
 #
 CONFIG_BBC_I2C=m
 CONFIG_VT=y
@@ -65,6 +71,7 @@ CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
 CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=m
 CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
 # CONFIG_CPU_FREQ_24_API is not set
 CONFIG_SPARC64=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
@@ -118,6 +125,7 @@ CONFIG_FW_LOADER=m
 # Graphics support
 #
 CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
 # CONFIG_FB_CIRRUS is not set
 CONFIG_FB_PM2=y
 # CONFIG_FB_PM2_FIFO_DISCONNECT is not set
@@ -153,7 +161,6 @@ CONFIG_FB_FFB=y
 #
 # Console display driver support
 #
-# CONFIG_MDA_CONSOLE is not set
 # CONFIG_PROM_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
@@ -217,6 +224,7 @@ CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_CRYPTOLOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_SX8=m
+CONFIG_BLK_DEV_UB=m
 # CONFIG_BLK_DEV_RAM is not set
 
 #
@@ -251,7 +259,6 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 CONFIG_IDEDMA_PCI_AUTO=y
 CONFIG_IDEDMA_ONLYDISK=y
-CONFIG_BLK_DEV_ADMA=y
 # CONFIG_BLK_DEV_AEC62XX is not set
 CONFIG_BLK_DEV_ALI15X3=y
 # CONFIG_WDC_ALI15X3 is not set
@@ -328,7 +335,8 @@ CONFIG_AIC79XX_RESET_DELAY_MS=15000
 # CONFIG_AIC79XX_DEBUG_ENABLE is not set
 CONFIG_AIC79XX_DEBUG_MASK=0
 # CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
-# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
 CONFIG_SCSI_SATA=y
 CONFIG_SCSI_SATA_SVW=m
 CONFIG_SCSI_ATA_PIIX=m
@@ -353,9 +361,7 @@ CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
-CONFIG_SCSI_IPR=m
-# CONFIG_SCSI_IPR_TRACE is not set
-# CONFIG_SCSI_IPR_DUMP is not set
+# CONFIG_SCSI_IPR is not set
 CONFIG_SCSI_QLOGIC_ISP=m
 CONFIG_SCSI_QLOGIC_FC=y
 CONFIG_SCSI_QLOGIC_FC_FIRMWARE=y
@@ -398,6 +404,7 @@ CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
 CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=m
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
@@ -412,7 +419,6 @@ CONFIG_DM_ZERO=m
 #
 CONFIG_FUSION=m
 CONFIG_FUSION_MAX_SGE=40
-CONFIG_FUSION_ISENSE=m
 CONFIG_FUSION_CTL=m
 CONFIG_FUSION_LAN=m
 
@@ -475,6 +481,7 @@ CONFIG_SYN_COOKIES=y
 CONFIG_INET_AH=y
 CONFIG_INET_ESP=y
 CONFIG_INET_IPCOMP=y
+CONFIG_INET_TUNNEL=y
 
 #
 # IP: Virtual Server Configuration
@@ -514,6 +521,7 @@ CONFIG_IPV6_PRIVACY=y
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
 CONFIG_IPV6_TUNNEL=m
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
@@ -523,6 +531,8 @@ CONFIG_BRIDGE_NETFILTER=y
 # IP: Netfilter Configuration
 #
 CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CT_PROTO_SCTP=m
 CONFIG_IP_NF_FTP=m
 CONFIG_IP_NF_IRC=m
 CONFIG_IP_NF_TFTP=m
@@ -548,8 +558,15 @@ CONFIG_IP_NF_MATCH_STATE=m
 CONFIG_IP_NF_MATCH_CONNTRACK=m
 CONFIG_IP_NF_MATCH_OWNER=m
 CONFIG_IP_NF_MATCH_PHYSDEV=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
 CONFIG_IP_NF_NAT=m
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -568,18 +585,13 @@ CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_DSCP=m
 CONFIG_IP_NF_TARGET_MARK=m
 CONFIG_IP_NF_TARGET_CLASSIFY=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_IP_NF_COMPAT_IPCHAINS=m
 CONFIG_IP_NF_COMPAT_IPFWADM=m
-CONFIG_IP_NF_TARGET_NOTRACK=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_REALM=m
 
 #
 # IPv6: Netfilter Configuration
@@ -599,6 +611,7 @@ CONFIG_IP6_NF_MATCH_IPV6HEADER=m
 CONFIG_IP6_NF_MATCH_AHESP=m
 CONFIG_IP6_NF_MATCH_LENGTH=m
 CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_PHYSDEV=m
 CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_LOG=m
 CONFIG_IP6_NF_MANGLE=m
@@ -704,6 +717,8 @@ CONFIG_NET_CLS_RSVP=m
 CONFIG_NET_CLS_RSVP6=m
 CONFIG_NET_CLS_ACT=y
 CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
 
 #
 # Network testing
@@ -880,6 +895,7 @@ CONFIG_NS83820=m
 CONFIG_HAMACHI=m
 CONFIG_YELLOWFIN=m
 CONFIG_R8169=m
+CONFIG_R8169_NAPI=y
 CONFIG_SK98LIN=m
 CONFIG_TIGON3=m
 
@@ -1064,6 +1080,7 @@ CONFIG_SERIO_I8042=y
 # CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PARKBD is not set
 CONFIG_SERIO_PCIPS2=m
+CONFIG_SERIO_RAW=m
 
 #
 # Input Device Drivers
@@ -1095,6 +1112,7 @@ CONFIG_I2C_CHARDEV=m
 #
 CONFIG_I2C_ALGOBIT=y
 CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
 
 #
 # I2C Hardware Bus support
@@ -1119,6 +1137,7 @@ CONFIG_I2C_SIS96X=m
 CONFIG_I2C_VIA=m
 CONFIG_I2C_VIAPRO=m
 CONFIG_I2C_VOODOO3=m
+CONFIG_I2C_PCA_ISA=m
 
 #
 # Hardware Sensors Chip support
@@ -1140,6 +1159,7 @@ CONFIG_SENSORS_LM83=m
 CONFIG_SENSORS_LM85=m
 CONFIG_SENSORS_LM90=m
 CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_SMSC47M1=m
 CONFIG_SENSORS_VIA686A=m
 CONFIG_SENSORS_W83781D=m
 CONFIG_SENSORS_W83L785TS=m
@@ -1262,6 +1282,7 @@ CONFIG_EXPORTFS=m
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
 CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
 CONFIG_CIFS=m
@@ -1473,6 +1494,7 @@ CONFIG_SND_VIRMIDI=m
 CONFIG_SND_AC97_CODEC=m
 CONFIG_SND_ALI5451=m
 CONFIG_SND_ATIIXP=m
+CONFIG_SND_ATIIXP_MODEM=m
 CONFIG_SND_AU8810=m
 CONFIG_SND_AU8820=m
 CONFIG_SND_AU8830=m
@@ -1512,6 +1534,7 @@ CONFIG_SND_VX222=m
 # ALSA USB devices
 #
 # CONFIG_SND_USB_AUDIO is not set
+CONFIG_SND_USB_USX2Y=m
 
 #
 # ALSA Sparc devices
@@ -1531,6 +1554,7 @@ CONFIG_USB=y
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
 
 #
 # USB Host Controller Drivers
@@ -1596,7 +1620,6 @@ CONFIG_USB_HPUSBSCSI=m
 # CONFIG_USB_IBMCAM is not set
 # CONFIG_USB_KONICAWC is not set
 # CONFIG_USB_OV511 is not set
-CONFIG_USB_PWC=m
 # CONFIG_USB_SE401 is not set
 CONFIG_USB_SN9C102=m
 # CONFIG_USB_STV680 is not set
@@ -1733,14 +1756,15 @@ CONFIG_OPROFILE=m
 # Kernel hacking
 #
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_SLAB is not set
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_DEBUG_DCFLUSH is not set
 # CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_KPROBES=y
+# CONFIG_DEBUG_DCFLUSH is not set
 # CONFIG_STACK_DEBUG is not set
 # CONFIG_DEBUG_BOOTMEM is not set
 CONFIG_HAVE_DEC_LOCK=y
@@ -1761,6 +1785,7 @@ CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=y
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index 2caca47d8..093281bdf 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -5,7 +5,7 @@
 EXTRA_AFLAGS := -ansi
 EXTRA_CFLAGS := -Werror
 
-extra-y		:= head.o init_task.o vmlinux.lds.s
+extra-y		:= head.o init_task.o vmlinux.lds
 
 obj-y		:= process.o setup.o cpu.o idprom.o \
 		   traps.o devices.o auxio.o \
@@ -22,6 +22,7 @@ obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o
 obj-$(CONFIG_MODULES) += module.o
 obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o
 obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o
+obj-$(CONFIG_KPROBES) += kprobes.o
 
 ifdef CONFIG_SUNOS_EMUL
   obj-y += sys_sunos32.o sunos_ioctl32.o
diff --git a/arch/sparc64/kernel/auxio.c b/arch/sparc64/kernel/auxio.c
index 24ecb1075..11672d2d3 100644
--- a/arch/sparc64/kernel/auxio.c
+++ b/arch/sparc64/kernel/auxio.c
@@ -17,7 +17,7 @@
 #include <asm/auxio.h>
 
 /* This cannot be static, as it is referenced in entry.S */
-unsigned long auxio_register = 0UL;
+void __iomem *auxio_register = 0UL;
 
 enum auxio_type {
 	AUXIO_TYPE_NODEV,
@@ -30,7 +30,7 @@ static spinlock_t auxio_lock = SPIN_LOCK_UNLOCKED;
 
 static void __auxio_sbus_set(u8 bits_on, u8 bits_off)
 {
-	if(auxio_register) {
+	if (auxio_register) {
 		unsigned char regval;
 		unsigned long flags;
 		unsigned char newval;
@@ -49,7 +49,7 @@ static void __auxio_sbus_set(u8 bits_on, u8 bits_off)
 
 static void __auxio_ebus_set(u8 bits_on, u8 bits_off)
 {
-	if(auxio_register) {
+	if (auxio_register) {
 		unsigned char regval;
 		unsigned long flags;
 		unsigned char newval;
@@ -126,7 +126,8 @@ found_sdev:
 	if (sdev) {
 		auxio_devtype  = AUXIO_TYPE_SBUS;
 		auxio_register = sbus_ioremap(&sdev->resource[0], 0,
-		  		sdev->reg_addrs[0].reg_size, "auxiliaryIO");
+					      sdev->reg_addrs[0].reg_size,
+					      "auxiliaryIO");
 	}
 #ifdef CONFIG_PCI
 	else {
@@ -142,7 +143,7 @@ found_sdev:
 	ebus_done:
 		if (edev) {
 			auxio_devtype  = AUXIO_TYPE_EBUS;
-			auxio_register = (unsigned long)
+			auxio_register =
 				ioremap(edev->resource[0].start, sizeof(u32));
 		}
 	}
diff --git a/arch/sparc64/kernel/binfmt_elf32.c b/arch/sparc64/kernel/binfmt_elf32.c
index a28046203..fb3e3b780 100644
--- a/arch/sparc64/kernel/binfmt_elf32.c
+++ b/arch/sparc64/kernel/binfmt_elf32.c
@@ -27,12 +27,12 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 #define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs)	\
 do {	unsigned int *dest = &(__elf_regs[0]);		\
 	struct pt_regs *src = (__pt_regs);		\
-	unsigned int *sp;				\
+	unsigned int __user *sp;			\
 	int i;						\
 	for(i = 0; i < 16; i++)				\
 		dest[i] = (unsigned int) src->u_regs[i];\
 	/* Don't try this at home kids... */		\
-	sp = (unsigned int *) (src->u_regs[14] &	\
+	sp = (unsigned int __user *) (src->u_regs[14] &	\
 		0x00000000fffffffc);			\
 	for(i = 0; i < 16; i++)				\
 		__get_user(dest[i+16], &sp[i]);		\
diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c
index 2296525af..97cf912f0 100644
--- a/arch/sparc64/kernel/chmc.c
+++ b/arch/sparc64/kernel/chmc.c
@@ -72,7 +72,7 @@ struct mctrl_info {
 	struct obp_mem_layout	layout_prop;
 	int			layout_size;
 
-	void			*regs;
+	void __iomem		*regs;
 
 	u64			timing_control1;
 	u64			timing_control2;
diff --git a/arch/sparc64/kernel/etrap.S b/arch/sparc64/kernel/etrap.S
index 9468eacdc..d50b755c7 100644
--- a/arch/sparc64/kernel/etrap.S
+++ b/arch/sparc64/kernel/etrap.S
@@ -17,7 +17,8 @@
 
 #define		TASK_REGOFF		(THREAD_SIZE-TRACEREG_SZ-STACKFRAME_SZ)
 #define		ETRAP_PSTATE1		(PSTATE_RMO | PSTATE_PRIV)
-#define		ETRAP_PSTATE2		(PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE)
+#define		ETRAP_PSTATE2		\
+		(PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE)
 
 /*
  * On entry, %g7 is return address - 0x4.
@@ -27,91 +28,91 @@
 		.text		
 		.align	64
 		.globl	etrap, etrap_irq, etraptl1
-etrap:		rdpr	%pil, %g2						! Single 	Group
+etrap:		rdpr	%pil, %g2
 etrap_irq:
-		rdpr	%tstate, %g1						! Single 	Group
-		sllx	%g2, 20, %g3						! IEU0		Group
-		andcc	%g1, TSTATE_PRIV, %g0					! IEU1
-		or	%g1, %g3, %g1						! IEU0		Group
-		bne,pn	%xcc, 1f						! CTI
-		 sub	%sp, STACKFRAME_SZ+TRACEREG_SZ-STACK_BIAS, %g2		! IEU1
-		wrpr	%g0, 7, %cleanwin					! Single	Group+4bubbles
-
-		sethi	%hi(TASK_REGOFF), %g2					! IEU0		Group		
-		sethi	%hi(TSTATE_PEF), %g3					! IEU1
-		or	%g2, %lo(TASK_REGOFF), %g2				! IEU0		Group
-		and	%g1, %g3, %g3						! IEU1
-		brnz,pn	%g3, 1f							! CTI+IEU1	Group
-		 add	%g6, %g2, %g2						! IEU0
-		wr	%g0, 0, %fprs						! Single	Group+4bubbles
-1:		rdpr	%tpc, %g3						! Single	Group
-
-		stx	%g1, [%g2 + STACKFRAME_SZ + PT_V9_TSTATE]		! Store		Group
-		rdpr	%tnpc, %g1						! Single	Group
-		stx	%g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC]			! Store		Group
-		rd	%y, %g3							! Single	Group+4bubbles
-		stx	%g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC]			! Store		Group
-		st	%g3, [%g2 + STACKFRAME_SZ + PT_V9_Y]			! Store		Group
-		save	%g2, -STACK_BIAS, %sp	! Ordering here is critical	! Single	Group
-		mov	%g6, %l6						! IEU0		Group
-
-		bne,pn	%xcc, 3f						! CTI		
-		 mov	PRIMARY_CONTEXT, %l4					! IEU1
-		rdpr	%canrestore, %g3					! Single	Group+4bubbles
-		rdpr	%wstate, %g2						! Single	Group+4bubbles
-		wrpr	%g0, 0, %canrestore					! Single	Group+4bubbles
-		sll	%g2, 3, %g2						! IEU0		Group
-		mov	1, %l5							! IEU1
-		stb	%l5, [%l6 + TI_FPDEPTH]					! Store
-
-		wrpr	%g3, 0, %otherwin					! Single	Group+4bubbles
-		wrpr	%g2, 0, %wstate						! Single	Group+4bubbles
-		stxa	%g0, [%l4] ASI_DMMU					! Store		Group
-		flush	%l6							! Single	Group+9bubbles
-		wr	%g0, ASI_AIUS, %asi					! Single	Group+4bubbles
-2:		wrpr	%g0, 0x0, %tl						! Single	Group+4bubbles
-		mov	%g4, %l4						! IEU1
-		mov	%g5, %l5						! IEU0		Group
-
-		mov	%g7, %l2						! IEU1
-		wrpr	%g0, ETRAP_PSTATE1, %pstate				! Single	Group+4bubbles
-		stx	%g1, [%sp + PTREGS_OFF + PT_V9_G1]			! Store		Group
-		stx	%g2, [%sp + PTREGS_OFF + PT_V9_G2]			! Store		Group
-		stx	%g3, [%sp + PTREGS_OFF + PT_V9_G3]			! Store		Group
-		stx	%g4, [%sp + PTREGS_OFF + PT_V9_G4]			! Store		Group
-		stx	%g5, [%sp + PTREGS_OFF + PT_V9_G5]			! Store		Group
-		stx	%g6, [%sp + PTREGS_OFF + PT_V9_G6]			! Store		Group
-
-		stx	%g7, [%sp + PTREGS_OFF + PT_V9_G7]			! Store		Group
-		stx	%i0, [%sp + PTREGS_OFF + PT_V9_I0]			! Store		Group
-		stx	%i1, [%sp + PTREGS_OFF + PT_V9_I1]			! Store		Group
-		stx	%i2, [%sp + PTREGS_OFF + PT_V9_I2]			! Store		Group
-		stx	%i3, [%sp + PTREGS_OFF + PT_V9_I3]			! Store		Group
-		stx	%i4, [%sp + PTREGS_OFF + PT_V9_I4]			! Store		Group
-		stx	%i5, [%sp + PTREGS_OFF + PT_V9_I5]			! Store		Group
-
-		stx	%i6, [%sp + PTREGS_OFF + PT_V9_I6]			! Store		Group
-		stx	%i7, [%sp + PTREGS_OFF + PT_V9_I7]			! Store		Group
-		wrpr	%g0, ETRAP_PSTATE2, %pstate				! Single	Group+4bubbles
-		mov	%l6, %g6						! IEU0
-		jmpl	%l2 + 0x4, %g0						! CTI		Group
-		 ldx	[%g6 + TI_TASK], %g4					! Load
+		rdpr	%tstate, %g1
+		sllx	%g2, 20, %g3
+		andcc	%g1, TSTATE_PRIV, %g0
+		or	%g1, %g3, %g1
+		bne,pn	%xcc, 1f
+		 sub	%sp, STACKFRAME_SZ+TRACEREG_SZ-STACK_BIAS, %g2
+		wrpr	%g0, 7, %cleanwin
+
+		sethi	%hi(TASK_REGOFF), %g2
+		sethi	%hi(TSTATE_PEF), %g3
+		or	%g2, %lo(TASK_REGOFF), %g2
+		and	%g1, %g3, %g3
+		brnz,pn	%g3, 1f
+		 add	%g6, %g2, %g2
+		wr	%g0, 0, %fprs
+1:		rdpr	%tpc, %g3
+
+		stx	%g1, [%g2 + STACKFRAME_SZ + PT_V9_TSTATE]
+		rdpr	%tnpc, %g1
+		stx	%g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC]
+		rd	%y, %g3
+		stx	%g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC]
+		st	%g3, [%g2 + STACKFRAME_SZ + PT_V9_Y]
+		save	%g2, -STACK_BIAS, %sp	! Ordering here is critical
+		mov	%g6, %l6
+
+		bne,pn	%xcc, 3f
+		 mov	PRIMARY_CONTEXT, %l4
+		rdpr	%canrestore, %g3
+		rdpr	%wstate, %g2
+		wrpr	%g0, 0, %canrestore
+		sll	%g2, 3, %g2
+		mov	1, %l5
+		stb	%l5, [%l6 + TI_FPDEPTH]
+
+		wrpr	%g3, 0, %otherwin
+		wrpr	%g2, 0, %wstate
+		stxa	%g0, [%l4] ASI_DMMU
+		flush	%l6
+		wr	%g0, ASI_AIUS, %asi
+2:		wrpr	%g0, 0x0, %tl
+		mov	%g4, %l4
+		mov	%g5, %l5
+
+		mov	%g7, %l2
+		wrpr	%g0, ETRAP_PSTATE1, %pstate
+		stx	%g1, [%sp + PTREGS_OFF + PT_V9_G1]
+		stx	%g2, [%sp + PTREGS_OFF + PT_V9_G2]
+		stx	%g3, [%sp + PTREGS_OFF + PT_V9_G3]
+		stx	%g4, [%sp + PTREGS_OFF + PT_V9_G4]
+		stx	%g5, [%sp + PTREGS_OFF + PT_V9_G5]
+		stx	%g6, [%sp + PTREGS_OFF + PT_V9_G6]
+
+		stx	%g7, [%sp + PTREGS_OFF + PT_V9_G7]
+		stx	%i0, [%sp + PTREGS_OFF + PT_V9_I0]
+		stx	%i1, [%sp + PTREGS_OFF + PT_V9_I1]
+		stx	%i2, [%sp + PTREGS_OFF + PT_V9_I2]
+		stx	%i3, [%sp + PTREGS_OFF + PT_V9_I3]
+		stx	%i4, [%sp + PTREGS_OFF + PT_V9_I4]
+		stx	%i5, [%sp + PTREGS_OFF + PT_V9_I5]
+
+		stx	%i6, [%sp + PTREGS_OFF + PT_V9_I6]
+		stx	%i7, [%sp + PTREGS_OFF + PT_V9_I7]
+		wrpr	%g0, ETRAP_PSTATE2, %pstate
+		mov	%l6, %g6
+		jmpl	%l2 + 0x4, %g0
+		 ldx	[%g6 + TI_TASK], %g4
 		nop
 		nop
 		nop
 
-3:		ldub	[%l6 + TI_FPDEPTH], %l5					! Load		Group
-		add	%l6, TI_FPSAVED + 1, %l4				! IEU0
-		srl	%l5, 1, %l3						! IEU0		Group
-		add	%l5, 2, %l5						! IEU1
-		stb	%l5, [%l6 + TI_FPDEPTH]					! Store
-		ba,pt	%xcc, 2b						! CTI
-		 stb	%g0, [%l4 + %l3]					! Store		Group
+3:		ldub	[%l6 + TI_FPDEPTH], %l5
+		add	%l6, TI_FPSAVED + 1, %l4
+		srl	%l5, 1, %l3
+		add	%l5, 2, %l5
+		stb	%l5, [%l6 + TI_FPDEPTH]
+		ba,pt	%xcc, 2b
+		 stb	%g0, [%l4 + %l3]
 		nop
 
 etraptl1:	/* Save tstate/tpc/tnpc of TL 1-->4 and the tl register itself.
-		 * We place this right after pt_regs on the trap stack.  The layout
-		 * is:
+		 * We place this right after pt_regs on the trap stack.
+		 * The layout is:
 		 *	0x00	TL1's TSTATE
 		 *	0x08	TL1's TPC
 		 *	0x10	TL1's TNPC
@@ -166,81 +167,81 @@ etraptl1:	/* Save tstate/tpc/tnpc of TL 1-->4 and the tl register itself.
 		wrpr	%g1, %tl
 		stx	%g1, [%g2 + STACK_BIAS + 0x80]
 
-		rdpr	%tstate, %g1						! Single	Group+4bubbles
-		sub	%g2, STACKFRAME_SZ + TRACEREG_SZ - STACK_BIAS, %g2	! IEU1
-		ba,pt	%xcc, 1b						! CTI		Group
-		 andcc	%g1, TSTATE_PRIV, %g0					! IEU0
+		rdpr	%tstate, %g1
+		sub	%g2, STACKFRAME_SZ + TRACEREG_SZ - STACK_BIAS, %g2
+		ba,pt	%xcc, 1b
+		 andcc	%g1, TSTATE_PRIV, %g0
 
 		.align	64
 		.globl	scetrap
-scetrap:	rdpr	%pil, %g2						! Single 	Group
-		rdpr	%tstate, %g1						! Single 	Group
-		sllx	%g2, 20, %g3						! IEU0		Group
-		andcc	%g1, TSTATE_PRIV, %g0					! IEU1
-		or	%g1, %g3, %g1						! IEU0		Group
-		bne,pn	%xcc, 1f						! CTI
-		 sub	%sp, (STACKFRAME_SZ+TRACEREG_SZ-STACK_BIAS), %g2	! IEU1
-		wrpr	%g0, 7, %cleanwin					! Single	Group+4bubbles
-
-		sllx	%g1, 51, %g3						! IEU0		Group
-		sethi	%hi(TASK_REGOFF), %g2					! IEU1
-		or	%g2, %lo(TASK_REGOFF), %g2				! IEU0		Group
-		brlz,pn	%g3, 1f							! CTI+IEU1
-		 add	%g6, %g2, %g2						! IEU0		Group
-		wr	%g0, 0, %fprs						! Single	Group+4bubbles
-1:		rdpr	%tpc, %g3						! Single	Group
-		stx	%g1, [%g2 + STACKFRAME_SZ + PT_V9_TSTATE]		! Store		Group
-
-		rdpr	%tnpc, %g1						! Single	Group
-		stx	%g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC]			! Store		Group
-		stx	%g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC]			! Store		Group
-		save	%g2, -STACK_BIAS, %sp	! Ordering here is critical	! Single	Group
-		mov	%g6, %l6						! IEU0		Group
-		bne,pn	%xcc, 2f						! CTI		
-		 mov	ASI_P, %l7						! IEU1
-		rdpr	%canrestore, %g3					! Single	Group+4bubbles
-
-		rdpr	%wstate, %g2						! Single	Group+4bubbles
-		wrpr	%g0, 0, %canrestore					! Single	Group+4bubbles
-		sll	%g2, 3, %g2						! IEU0		Group
-		mov	PRIMARY_CONTEXT, %l4					! IEU1
-		wrpr	%g3, 0, %otherwin					! Single	Group+4bubbles
-		wrpr	%g2, 0, %wstate						! Single	Group+4bubbles
-		stxa	%g0, [%l4] ASI_DMMU					! Store
-		flush	%l6							! Single	Group+9bubbles
-
-		mov	ASI_AIUS, %l7						! IEU0		Group
-2:		mov	%g4, %l4						! IEU1
-		mov	%g5, %l5						! IEU0		Group
-		add	%g7, 0x4, %l2						! IEU1
-		wrpr	%g0, ETRAP_PSTATE1, %pstate				! Single	Group+4bubbles
-		stx	%g1, [%sp + PTREGS_OFF + PT_V9_G1]			! Store		Group
-		stx	%g2, [%sp + PTREGS_OFF + PT_V9_G2]			! Store		Group
-		sllx	%l7, 24, %l7						! IEU0
-
-		stx	%g3, [%sp + PTREGS_OFF + PT_V9_G3]			! Store		Group
-		rdpr	%cwp, %l0						! Single	Group
-		stx	%g4, [%sp + PTREGS_OFF + PT_V9_G4]			! Store		Group
-		stx	%g5, [%sp + PTREGS_OFF + PT_V9_G5]			! Store		Group
-		stx	%g6, [%sp + PTREGS_OFF + PT_V9_G6]			! Store		Group
-		stx	%g7, [%sp + PTREGS_OFF + PT_V9_G7]			! Store		Group
-		or	%l7, %l0, %l7						! IEU0
-		sethi	%hi(TSTATE_RMO | TSTATE_PEF), %l0			! IEU1
-
-		or	%l7, %l0, %l7						! IEU0		Group
-		wrpr	%l2, %tnpc						! Single	Group+4bubbles
-		wrpr	%l7, (TSTATE_PRIV | TSTATE_IE), %tstate			! Single	Group+4bubbles
-		stx	%i0, [%sp + PTREGS_OFF + PT_V9_I0]			! Store		Group
-		stx	%i1, [%sp + PTREGS_OFF + PT_V9_I1]			! Store		Group
-		stx	%i2, [%sp + PTREGS_OFF + PT_V9_I2]			! Store		Group
-		stx	%i3, [%sp + PTREGS_OFF + PT_V9_I3]			! Store		Group
-		stx	%i4, [%sp + PTREGS_OFF + PT_V9_I4]			! Store		Group
-
-		stx	%i5, [%sp + PTREGS_OFF + PT_V9_I5]			! Store		Group
-		stx	%i6, [%sp + PTREGS_OFF + PT_V9_I6]			! Store		Group
-		mov	%l6, %g6						! IEU1
-		stx	%i7, [%sp + PTREGS_OFF + PT_V9_I7]			! Store		Group
-		ldx	[%g6 + TI_TASK], %g4					! Load		Group
+scetrap:	rdpr	%pil, %g2
+		rdpr	%tstate, %g1
+		sllx	%g2, 20, %g3
+		andcc	%g1, TSTATE_PRIV, %g0
+		or	%g1, %g3, %g1
+		bne,pn	%xcc, 1f
+		 sub	%sp, (STACKFRAME_SZ+TRACEREG_SZ-STACK_BIAS), %g2
+		wrpr	%g0, 7, %cleanwin
+
+		sllx	%g1, 51, %g3
+		sethi	%hi(TASK_REGOFF), %g2
+		or	%g2, %lo(TASK_REGOFF), %g2
+		brlz,pn	%g3, 1f
+		 add	%g6, %g2, %g2
+		wr	%g0, 0, %fprs
+1:		rdpr	%tpc, %g3
+		stx	%g1, [%g2 + STACKFRAME_SZ + PT_V9_TSTATE]
+
+		rdpr	%tnpc, %g1
+		stx	%g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC]
+		stx	%g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC]
+		save	%g2, -STACK_BIAS, %sp	! Ordering here is critical
+		mov	%g6, %l6
+		bne,pn	%xcc, 2f
+		 mov	ASI_P, %l7
+		rdpr	%canrestore, %g3
+
+		rdpr	%wstate, %g2
+		wrpr	%g0, 0, %canrestore
+		sll	%g2, 3, %g2
+		mov	PRIMARY_CONTEXT, %l4
+		wrpr	%g3, 0, %otherwin
+		wrpr	%g2, 0, %wstate
+		stxa	%g0, [%l4] ASI_DMMU
+		flush	%l6
+
+		mov	ASI_AIUS, %l7
+2:		mov	%g4, %l4
+		mov	%g5, %l5
+		add	%g7, 0x4, %l2
+		wrpr	%g0, ETRAP_PSTATE1, %pstate
+		stx	%g1, [%sp + PTREGS_OFF + PT_V9_G1]
+		stx	%g2, [%sp + PTREGS_OFF + PT_V9_G2]
+		sllx	%l7, 24, %l7
+
+		stx	%g3, [%sp + PTREGS_OFF + PT_V9_G3]
+		rdpr	%cwp, %l0
+		stx	%g4, [%sp + PTREGS_OFF + PT_V9_G4]
+		stx	%g5, [%sp + PTREGS_OFF + PT_V9_G5]
+		stx	%g6, [%sp + PTREGS_OFF + PT_V9_G6]
+		stx	%g7, [%sp + PTREGS_OFF + PT_V9_G7]
+		or	%l7, %l0, %l7
+		sethi	%hi(TSTATE_RMO | TSTATE_PEF), %l0
+
+		or	%l7, %l0, %l7
+		wrpr	%l2, %tnpc
+		wrpr	%l7, (TSTATE_PRIV | TSTATE_IE), %tstate
+		stx	%i0, [%sp + PTREGS_OFF + PT_V9_I0]
+		stx	%i1, [%sp + PTREGS_OFF + PT_V9_I1]
+		stx	%i2, [%sp + PTREGS_OFF + PT_V9_I2]
+		stx	%i3, [%sp + PTREGS_OFF + PT_V9_I3]
+		stx	%i4, [%sp + PTREGS_OFF + PT_V9_I4]
+
+		stx	%i5, [%sp + PTREGS_OFF + PT_V9_I5]
+		stx	%i6, [%sp + PTREGS_OFF + PT_V9_I6]
+		mov	%l6, %g6
+		stx	%i7, [%sp + PTREGS_OFF + PT_V9_I7]
+		ldx	[%g6 + TI_TASK], %g4
 		done
 		nop
 		nop
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index 01c8869a7..4a286a800 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -50,6 +50,7 @@ bootup_user_stack:
  */
         .global root_flags, ram_flags, root_dev
         .global sparc_ramdisk_image, sparc_ramdisk_size
+	.global sparc_ramdisk_image64
 
         .ascii  "HdrS"
         .word   LINUX_VERSION_CODE
@@ -60,7 +61,7 @@ bootup_user_stack:
 	 * 0x0202 : Supports kernel params string
 	 * 0x0201 : Supports reboot_command
 	 */
-	.half   0x0300          /* HdrS version */
+	.half   0x0301          /* HdrS version */
 
 root_flags:
         .half   1
@@ -74,6 +75,8 @@ sparc_ramdisk_size:
         .word   0
         .xword  reboot_command
 	.xword	bootstr_info
+sparc_ramdisk_image64:
+	.xword	0
 	.word	_end
 
 	/* We must be careful, 32-bit OpenBOOT will get confused if it
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index d52b84291..3162b2ed1 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -33,7 +33,6 @@
 #include <asm/oplib.h>
 #include <asm/timer.h>
 #include <asm/smp.h>
-#include <asm/hardirq.h>
 #include <asm/starfire.h>
 #include <asm/uaccess.h>
 #include <asm/cache.h>
@@ -791,16 +790,24 @@ void handler_irq(int irq, struct pt_regs *regs)
 #endif
 			if ((flags & IBF_MULTI) == 0) {
 				struct irqaction *ap = bp->irq_info;
-				ap->handler(__irq(bp), ap->dev_id, regs);
-				random |= ap->flags & SA_SAMPLE_RANDOM;
+				int ret;
+
+				ret = ap->handler(__irq(bp), ap->dev_id, regs);
+				if (ret == IRQ_HANDLED)
+					random |= ap->flags;
 			} else {
 				void **vector = (void **)bp->irq_info;
 				int ent;
 				for (ent = 0; ent < 4; ent++) {
 					struct irqaction *ap = vector[ent];
 					if (ap != NULL) {
-						ap->handler(__irq(bp), ap->dev_id, regs);
-						random |= ap->flags & SA_SAMPLE_RANDOM;
+						int ret;
+
+						ret = ap->handler(__irq(bp),
+								  ap->dev_id,
+								  regs);
+						if (ret == IRQ_HANDLED)
+							random |= ap->flags;
 					}
 				}
 			}
@@ -813,8 +820,9 @@ void handler_irq(int irq, struct pt_regs *regs)
 				}
 #endif
 				upa_writel(ICLR_IDLE, bp->iclr);
+
 				/* Test and add entropy */
-				if (random)
+				if (random & SA_SAMPLE_RANDOM)
 					add_interrupt_randomness(irq);
 			}
 		} else
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index 31cc686de..75032d0e2 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -41,7 +41,6 @@ asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn,
 #else
 
 /* List of all PCI controllers found in the system. */
-spinlock_t pci_controller_lock = SPIN_LOCK_UNLOCKED;
 struct pci_controller_info *pci_controller_root = NULL;
 
 /* Each PCI controller found gets a unique index. */
@@ -298,12 +297,9 @@ static void __init pci_controller_probe(void)
 static void __init pci_scan_each_controller_bus(void)
 {
 	struct pci_controller_info *p;
-	unsigned long flags;
 
-	spin_lock_irqsave(&pci_controller_lock, flags);
 	for (p = pci_controller_root; p; p = p->next)
 		p->scan_bus(p);
-	spin_unlock_irqrestore(&pci_controller_lock, flags);
 }
 
 /* Reorder the pci_dev chain, so that onboard devices come first
@@ -351,10 +347,6 @@ static int __init pcibios_init(void)
 
 subsys_initcall(pcibios_init);
 
-struct pci_fixup pcibios_fixups[] = {
-	{ 0 }
-};
-
 void pcibios_fixup_bus(struct pci_bus *pbus)
 {
 	struct pci_pbm_info *pbm = pbus->sysdata;
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
index fda652414..58310aace 100644
--- a/arch/sparc64/kernel/pci_common.c
+++ b/arch/sparc64/kernel/pci_common.c
@@ -15,18 +15,13 @@
  */
 void __init pci_fixup_host_bridge_self(struct pci_bus *pbus)
 {
-	struct list_head *walk = &pbus->devices;
-
-	walk = walk->next;
-	while (walk != &pbus->devices) {
-		struct pci_dev *pdev = pci_dev_b(walk);
+	struct pci_dev *pdev;
 
+	list_for_each_entry(pdev, &pbus->devices, bus_list) {
 		if (pdev->class >> 8 == PCI_CLASS_BRIDGE_HOST) {
 			pbus->self = pdev;
 			return;
 		}
-
-		walk = walk->next;
 	}
 
 	prom_printf("PCI: Critical error, cannot find host bridge PDEV.\n");
@@ -217,31 +212,18 @@ void __init pci_fill_in_pbm_cookies(struct pci_bus *pbus,
 				    struct pci_pbm_info *pbm,
 				    int prom_node)
 {
-	struct list_head *walk = &pbus->devices;
-
-	/* This loop is coded like this because the cookie
-	 * fillin routine can delete devices from the tree.
-	 */
-	walk = walk->next;
-	while (walk != &pbus->devices) {
-		struct pci_dev *pdev = pci_dev_b(walk);
-		struct list_head *walk_next = walk->next;
+	struct pci_dev *pdev, *pdev_next;
+	struct pci_bus *this_pbus, *pbus_next;
 
+	/* This must be _safe because the cookie fillin
+	   routine can delete devices from the tree.  */
+	list_for_each_entry_safe(pdev, pdev_next, &pbus->devices, bus_list)
 		pdev_cookie_fillin(pbm, pdev, prom_node);
 
-		walk = walk_next;
-	}
-
-	walk = &pbus->children;
-	walk = walk->next;
-	while (walk != &pbus->children) {
-		struct pci_bus *this_pbus = pci_bus_b(walk);
+	list_for_each_entry_safe(this_pbus, pbus_next, &pbus->children, node) {
 		struct pcidev_cookie *pcp = this_pbus->self->sysdata;
-		struct list_head *walk_next = walk->next;
 
 		pci_fill_in_pbm_cookies(this_pbus, pbm, pcp->prom_node);
-
-		walk = walk_next;
 	}
 }
 
@@ -431,14 +413,14 @@ static void __init pdev_record_assignments(struct pci_pbm_info *pbm,
 void __init pci_record_assignments(struct pci_pbm_info *pbm,
 				   struct pci_bus *pbus)
 {
-	struct list_head *walk = &pbus->devices;
+	struct pci_dev *dev;
+	struct pci_bus *bus;
 
-	for (walk = walk->next; walk != &pbus->devices; walk = walk->next)
-		pdev_record_assignments(pbm, pci_dev_b(walk));
+	list_for_each_entry(dev, &pbus->devices, bus_list)
+		pdev_record_assignments(pbm, dev);
 
-	walk = &pbus->children;
-	for (walk = walk->next; walk != &pbus->children; walk = walk->next)
-		pci_record_assignments(pbm, pci_bus_b(walk));
+	list_for_each_entry(bus, &pbus->children, node)
+		pci_record_assignments(pbm, bus);
 }
 
 /* Return non-zero if PDEV has implicit I/O resources even
@@ -549,14 +531,14 @@ static void __init pdev_assign_unassigned(struct pci_pbm_info *pbm,
 void __init pci_assign_unassigned(struct pci_pbm_info *pbm,
 				  struct pci_bus *pbus)
 {
-	struct list_head *walk = &pbus->devices;
+	struct pci_dev *dev;
+	struct pci_bus *bus;
 
-	for (walk = walk->next; walk != &pbus->devices; walk = walk->next)
-		pdev_assign_unassigned(pbm, pci_dev_b(walk));
+	list_for_each_entry(dev, &pbus->devices, bus_list)
+		pdev_assign_unassigned(pbm, dev);
 
-	walk = &pbus->children;
-	for (walk = walk->next; walk != &pbus->children; walk = walk->next)
-		pci_assign_unassigned(pbm, pci_bus_b(walk));
+	list_for_each_entry(bus, &pbus->children, node)
+		pci_assign_unassigned(pbm, bus);
 }
 
 static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt)
@@ -797,14 +779,14 @@ have_irq:
 void __init pci_fixup_irq(struct pci_pbm_info *pbm,
 			  struct pci_bus *pbus)
 {
-	struct list_head *walk = &pbus->devices;
+	struct pci_dev *dev;
+	struct pci_bus *bus;
 
-	for (walk = walk->next; walk != &pbus->devices; walk = walk->next)
-		pdev_fixup_irq(pci_dev_b(walk));
+	list_for_each_entry(dev, &pbus->devices, bus_list)
+		pdev_fixup_irq(dev);
 
-	walk = &pbus->children;
-	for (walk = walk->next; walk != &pbus->children; walk = walk->next)
-		pci_fixup_irq(pbm, pci_bus_b(walk));
+	list_for_each_entry(bus, &pbus->children, node)
+		pci_fixup_irq(pbm, bus);
 }
 
 static void pdev_setup_busmastering(struct pci_dev *pdev, int is_66mhz)
@@ -897,7 +879,7 @@ static void pdev_setup_busmastering(struct pci_dev *pdev, int is_66mhz)
 void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm,
 				     struct pci_bus *pbus)
 {
-	struct list_head *walk;
+	struct pci_dev *pdev;
 	int all_are_66mhz;
 	u16 status;
 
@@ -906,11 +888,8 @@ void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm,
 		goto out;
 	}
 
-	walk = &pbus->devices;
 	all_are_66mhz = 1;
-	for (walk = walk->next; walk != &pbus->devices; walk = walk->next) {
-		struct pci_dev *pdev = pci_dev_b(walk);
-
+	list_for_each_entry(pdev, &pbus->devices, bus_list) {
 		pci_read_config_word(pdev, PCI_STATUS, &status);
 		if (!(status & PCI_STATUS_66MHZ)) {
 			all_are_66mhz = 0;
@@ -929,17 +908,17 @@ out:
 void pci_setup_busmastering(struct pci_pbm_info *pbm,
 			    struct pci_bus *pbus)
 {
-	struct list_head *walk = &pbus->devices;
+	struct pci_dev *dev;
+	struct pci_bus *bus;
 	int is_66mhz;
 
 	is_66mhz = pbm->is_66mhz_capable && pbm->all_devs_66mhz;
 
-	for (walk = walk->next; walk != &pbus->devices; walk = walk->next)
-		pdev_setup_busmastering(pci_dev_b(walk), is_66mhz);
+	list_for_each_entry(dev, &pbus->devices, bus_list)
+		pdev_setup_busmastering(dev, is_66mhz);
 
-	walk = &pbus->children;
-	for (walk = walk->next; walk != &pbus->children; walk = walk->next)
-		pci_setup_busmastering(pbm, pci_bus_b(walk));
+	list_for_each_entry(bus, &pbus->children, node)
+		pci_setup_busmastering(pbm, bus);
 }
 
 void pci_register_legacy_regions(struct resource *io_res,
@@ -987,10 +966,10 @@ void pci_scan_for_target_abort(struct pci_controller_info *p,
 			       struct pci_pbm_info *pbm,
 			       struct pci_bus *pbus)
 {
-	struct list_head *walk = &pbus->devices;
+	struct pci_dev *pdev;
+	struct pci_bus *bus;
 
-	for (walk = walk->next; walk != &pbus->devices; walk = walk->next) {
-		struct pci_dev *pdev = pci_dev_b(walk);
+	list_for_each_entry(pdev, &pbus->devices, bus_list) {
 		u16 status, error_bits;
 
 		pci_read_config_word(pdev, PCI_STATUS, &status);
@@ -1005,19 +984,18 @@ void pci_scan_for_target_abort(struct pci_controller_info *p,
 		}
 	}
 
-	walk = &pbus->children;
-	for (walk = walk->next; walk != &pbus->children; walk = walk->next)
-		pci_scan_for_target_abort(p, pbm, pci_bus_b(walk));
+	list_for_each_entry(bus, &pbus->children, node)
+		pci_scan_for_target_abort(p, pbm, bus);
 }
 
 void pci_scan_for_master_abort(struct pci_controller_info *p,
 			       struct pci_pbm_info *pbm,
 			       struct pci_bus *pbus)
 {
-	struct list_head *walk = &pbus->devices;
+	struct pci_dev *pdev;
+	struct pci_bus *bus;
 
-	for (walk = walk->next; walk != &pbus->devices; walk = walk->next) {
-		struct pci_dev *pdev = pci_dev_b(walk);
+	list_for_each_entry(pdev, &pbus->devices, bus_list) {
 		u16 status, error_bits;
 
 		pci_read_config_word(pdev, PCI_STATUS, &status);
@@ -1031,19 +1009,18 @@ void pci_scan_for_master_abort(struct pci_controller_info *p,
 		}
 	}
 
-	walk = &pbus->children;
-	for (walk = walk->next; walk != &pbus->children; walk = walk->next)
-		pci_scan_for_master_abort(p, pbm, pci_bus_b(walk));
+	list_for_each_entry(bus, &pbus->children, node)
+		pci_scan_for_master_abort(p, pbm, bus);
 }
 
 void pci_scan_for_parity_error(struct pci_controller_info *p,
 			       struct pci_pbm_info *pbm,
 			       struct pci_bus *pbus)
 {
-	struct list_head *walk = &pbus->devices;
+	struct pci_dev *pdev;
+	struct pci_bus *bus;
 
-	for (walk = walk->next; walk != &pbus->devices; walk = walk->next) {
-		struct pci_dev *pdev = pci_dev_b(walk);
+	list_for_each_entry(pdev, &pbus->devices, bus_list) {
 		u16 status, error_bits;
 
 		pci_read_config_word(pdev, PCI_STATUS, &status);
@@ -1058,7 +1035,6 @@ void pci_scan_for_parity_error(struct pci_controller_info *p,
 		}
 	}
 
-	walk = &pbus->children;
-	for (walk = walk->next; walk != &pbus->children; walk = walk->next)
-		pci_scan_for_parity_error(p, pbm, pci_bus_b(walk));
+	list_for_each_entry(bus, &pbus->children, node)
+		pci_scan_for_parity_error(p, pbm, bus);
 }
diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h
index 302a0a2ce..6c3205962 100644
--- a/arch/sparc64/kernel/pci_impl.h
+++ b/arch/sparc64/kernel/pci_impl.h
@@ -11,7 +11,6 @@
 #include <linux/spinlock.h>
 #include <asm/io.h>
 
-extern spinlock_t pci_controller_lock;
 extern struct pci_controller_info *pci_controller_root;
 
 extern int pci_num_controllers;
diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c
index cca82a12e..94a52983c 100644
--- a/arch/sparc64/kernel/pci_iommu.c
+++ b/arch/sparc64/kernel/pci_iommu.c
@@ -56,6 +56,39 @@ static void __iommu_flushall(struct pci_iommu *iommu)
 	}
 }
 
+#define IOPTE_CONSISTENT(CTX) \
+	(IOPTE_VALID | IOPTE_CACHE | \
+	 (((CTX) << 47) & IOPTE_CONTEXT))
+
+#define IOPTE_STREAMING(CTX) \
+	(IOPTE_CONSISTENT(CTX) | IOPTE_STBUF)
+
+/* Existing mappings are never marked invalid, instead they
+ * are pointed to a dummy page.
+ */
+#define IOPTE_IS_DUMMY(iommu, iopte)	\
+	((iopte_val(*iopte) & IOPTE_PAGE) == (iommu)->dummy_page_pa)
+
+static void inline iopte_make_dummy(struct pci_iommu *iommu, iopte_t *iopte)
+{
+	unsigned long val = iopte_val(*iopte);
+
+	val &= ~IOPTE_PAGE;
+	val |= iommu->dummy_page_pa;
+
+	iopte_val(*iopte) = val;
+}
+
+void pci_iommu_table_init(struct pci_iommu *iommu, int tsbsize)
+{
+	int i;
+
+	tsbsize /= sizeof(iopte_t);
+
+	for (i = 0; i < tsbsize; i++)
+		iopte_make_dummy(iommu, &iommu->page_table[i]);
+}
+
 static iopte_t *alloc_streaming_cluster(struct pci_iommu *iommu, unsigned long npages)
 {
 	iopte_t *iopte, *limit, *first;
@@ -79,7 +112,7 @@ static iopte_t *alloc_streaming_cluster(struct pci_iommu *iommu, unsigned long n
 	
 	first = iopte;
 	for (;;) {
-		if (iopte_val(*iopte) == 0UL) {
+		if (IOPTE_IS_DUMMY(iommu, iopte)) {
 			if ((iopte + (1 << cnum)) >= limit)
 				ent = 0;
 			else
@@ -142,12 +175,12 @@ static iopte_t *alloc_consistent_cluster(struct pci_iommu *iommu, unsigned long
 	iopte = iommu->page_table + (1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS));
 	while (iopte > iommu->page_table) {
 		iopte--;
-		if (!(iopte_val(*iopte) & IOPTE_VALID)) {
+		if (IOPTE_IS_DUMMY(iommu, iopte)) {
 			unsigned long tmp = npages;
 
 			while (--tmp) {
 				iopte--;
-				if (iopte_val(*iopte) & IOPTE_VALID)
+				if (!IOPTE_IS_DUMMY(iommu, iopte))
 					break;
 			}
 			if (tmp == 0) {
@@ -162,15 +195,6 @@ static iopte_t *alloc_consistent_cluster(struct pci_iommu *iommu, unsigned long
 	return NULL;
 }
 
-#define IOPTE_CONSISTENT(CTX) \
-	(IOPTE_VALID | IOPTE_CACHE | \
-	 (((CTX) << 47) & IOPTE_CONTEXT))
-
-#define IOPTE_STREAMING(CTX) \
-	(IOPTE_CONSISTENT(CTX) | IOPTE_STBUF)
-
-#define IOPTE_INVALID	0UL
-
 /* Allocate and map kernel buffer of size SIZE using consistent mode
  * DMA for PCI device PDEV.  Return non-NULL cpu-side address if
  * successful and set *DMA_ADDRP to the PCI side dma address.
@@ -261,7 +285,7 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_
 		limit = (iommu->page_table +
 			 (1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS)));
 		while (walk < limit) {
-			if (iopte_val(*walk) != IOPTE_INVALID)
+			if (!IOPTE_IS_DUMMY(iommu, walk))
 				break;
 			walk++;
 		}
@@ -280,7 +304,7 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_
 		ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL;
 
 	for (i = 0; i < npages; i++, iopte++)
-		iopte_val(*iopte) = IOPTE_INVALID;
+		iopte_make_dummy(iommu, iopte);
 
 	if (iommu->iommu_ctxflush) {
 		pci_iommu_write(iommu->iommu_ctxflush, ctx);
@@ -376,7 +400,7 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
 	base = iommu->page_table +
 		((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
 #ifdef DEBUG_PCI_IOMMU
-	if (iopte_val(*base) == IOPTE_INVALID)
+	if (IOPTE_IS_DUMMY(iommu, base))
 		printk("pci_unmap_single called on non-mapped region %08x,%08x from %016lx\n",
 		       bus_addr, sz, __builtin_return_address(0));
 #endif
@@ -415,7 +439,7 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
 	}
 
 	/* Step 2: Clear out first TSB entry. */
-	iopte_val(*base) = IOPTE_INVALID;
+	iopte_make_dummy(iommu, base);
 
 	free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base,
 			       npages, ctx);
@@ -611,7 +635,7 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems,
 		((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
 
 #ifdef DEBUG_PCI_IOMMU
-	if (iopte_val(*base) == IOPTE_INVALID)
+	if (IOPTE_IS_DUMMY(iommu, base))
 		printk("pci_unmap_sg called on non-mapped region %016lx,%d from %016lx\n", sglist->dma_address, nelems, __builtin_return_address(0));
 #endif
 
@@ -648,7 +672,7 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems,
 	}
 
 	/* Step 2: Clear out first TSB entry. */
-	iopte_val(*base) = IOPTE_INVALID;
+	iopte_make_dummy(iommu, base);
 
 	free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base,
 			       npages, ctx);
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
index dc4d63084..2dacbd780 100644
--- a/arch/sparc64/kernel/pci_psycho.c
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -1076,17 +1076,17 @@ static void __init psycho_register_error_handlers(struct pci_controller_info *p)
 	 * bits for each PBM.
 	 */
 	tmp = psycho_read(base + PSYCHO_PCIA_CTRL);
-	tmp |= (PSYCHO_PCICTRL_SBH_ERR |
-		PSYCHO_PCICTRL_SERR |
-		PSYCHO_PCICTRL_SBH_INT |
+	tmp |= (PSYCHO_PCICTRL_SERR |
+		PSYCHO_PCICTRL_SBH_ERR |
 		PSYCHO_PCICTRL_EEN);
+	tmp &= ~(PSYCHO_PCICTRL_SBH_INT);
 	psycho_write(base + PSYCHO_PCIA_CTRL, tmp);
 		     
 	tmp = psycho_read(base + PSYCHO_PCIB_CTRL);
-	tmp |= (PSYCHO_PCICTRL_SBH_ERR |
-		PSYCHO_PCICTRL_SERR |
-		PSYCHO_PCICTRL_SBH_INT |
+	tmp |= (PSYCHO_PCICTRL_SERR |
+		PSYCHO_PCICTRL_SBH_ERR |
 		PSYCHO_PCICTRL_EEN);
+	tmp &= ~(PSYCHO_PCICTRL_SBH_INT);
 	psycho_write(base + PSYCHO_PCIB_CTRL, tmp);
 }
 
@@ -1241,6 +1241,14 @@ static void __init psycho_iommu_init(struct pci_controller_info *p)
 	 * in pci_iommu.c
 	 */
 
+	iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0);
+	if (!iommu->dummy_page) {
+		prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n");
+		prom_halt();
+	}
+	memset((void *)iommu->dummy_page, 0, PAGE_SIZE);
+	iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page);
+
 	/* Using assumed page size 8K with 128K entries we need 1MB iommu page
 	 * table (128K ioptes * 8 bytes per iopte).  This is
 	 * page order 7 on UltraSparc.
@@ -1254,7 +1262,7 @@ static void __init psycho_iommu_init(struct pci_controller_info *p)
 	iommu->page_table_sz_bits = 17;
 	iommu->page_table_map_base = 0xc0000000;
 	iommu->dma_addr_mask = 0xffffffff;
-	memset((char *)tsbbase, 0, IO_TSB_SIZE);
+	pci_iommu_table_init(iommu, IO_TSB_SIZE);
 
 	/* We start with no consistent mappings. */
 	iommu->lowest_consistent_map =
@@ -1479,22 +1487,18 @@ void __init psycho_init(int node, char *model_name)
 	struct linux_prom64_registers pr_regs[3];
 	struct pci_controller_info *p;
 	struct pci_iommu *iommu;
-	unsigned long flags;
 	u32 upa_portid;
 	int is_pbm_a, err;
 
 	upa_portid = prom_getintdefault(node, "upa-portid", 0xff);
 
-	spin_lock_irqsave(&pci_controller_lock, flags);
 	for(p = pci_controller_root; p; p = p->next) {
 		if (p->pbm_A.portid == upa_portid) {
-			spin_unlock_irqrestore(&pci_controller_lock, flags);
 			is_pbm_a = (p->pbm_A.prom_node == 0);
 			psycho_pbm_init(p, node, is_pbm_a);
 			return;
 		}
 	}
-	spin_unlock_irqrestore(&pci_controller_lock, flags);
 
 	p = kmalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
 	if (!p) {
@@ -1510,10 +1514,8 @@ void __init psycho_init(int node, char *model_name)
 	memset(iommu, 0, sizeof(*iommu));
 	p->pbm_A.iommu = p->pbm_B.iommu = iommu;
 
-	spin_lock_irqsave(&pci_controller_lock, flags);
 	p->next = pci_controller_root;
 	pci_controller_root = p;
-	spin_unlock_irqrestore(&pci_controller_lock, flags);
 
 	p->pbm_A.portid = upa_portid;
 	p->pbm_B.portid = upa_portid;
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index 6a266a7bf..2bf247792 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -1113,10 +1113,9 @@ static void __init sabre_base_address_update(struct pci_dev *pdev, int resource)
 
 static void __init apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus)
 {
-	struct list_head *walk = &sabre_bus->devices;
+	struct pci_dev *pdev;
 
-	for (walk = walk->next; walk != &sabre_bus->devices; walk = walk->next) {
-		struct pci_dev *pdev = pci_dev_b(walk);
+	list_for_each_entry(pdev, &sabre_bus->devices, bus_list) {
 
 		if (pdev->vendor == PCI_VENDOR_ID_SUN &&
 		    pdev->device == PCI_DEVICE_ID_SUN_SIMBA) {
@@ -1178,10 +1177,9 @@ static struct pcidev_cookie *alloc_bridge_cookie(struct pci_pbm_info *pbm)
 static void __init sabre_scan_bus(struct pci_controller_info *p)
 {
 	static int once;
-	struct pci_bus *sabre_bus;
+	struct pci_bus *sabre_bus, *pbus;
 	struct pci_pbm_info *pbm;
 	struct pcidev_cookie *cookie;
-	struct list_head *walk;
 	int sabres_scanned;
 
 	/* The APB bridge speaks to the Sabre host PCI bridge
@@ -1217,9 +1215,7 @@ static void __init sabre_scan_bus(struct pci_controller_info *p)
 
 	sabres_scanned = 0;
 
-	walk = &sabre_bus->children;
-	for (walk = walk->next; walk != &sabre_bus->children; walk = walk->next) {
-		struct pci_bus *pbus = pci_bus_b(walk);
+	list_for_each_entry(pbus, &sabre_bus->children, node) {
 
 		if (pbus->number == p->pbm_A.pci_first_busno) {
 			pbm = &p->pbm_A;
@@ -1293,6 +1289,14 @@ static void __init sabre_iommu_init(struct pci_controller_info *p,
 	 * in pci_iommu.c
 	 */
 
+	iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0);
+	if (!iommu->dummy_page) {
+		prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n");
+		prom_halt();
+	}
+	memset((void *)iommu->dummy_page, 0, PAGE_SIZE);
+	iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page);
+
 	tsbbase = __get_free_pages(GFP_KERNEL, order = get_order(tsbsize * 1024 * 8));
 	if (!tsbbase) {
 		prom_printf("SABRE_IOMMU: Error, gfp(tsb) failed.\n");
@@ -1301,7 +1305,7 @@ static void __init sabre_iommu_init(struct pci_controller_info *p,
 	iommu->page_table = (iopte_t *)tsbbase;
 	iommu->page_table_map_base = dvma_offset;
 	iommu->dma_addr_mask = dma_mask;
-	memset((char *)tsbbase, 0, PAGE_SIZE << order);
+	pci_iommu_table_init(iommu, PAGE_SIZE << order);
 
 	sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase));
 
@@ -1546,7 +1550,6 @@ void __init sabre_init(int pnode, char *model_name)
 	struct linux_prom64_registers pr_regs[2];
 	struct pci_controller_info *p;
 	struct pci_iommu *iommu;
-	unsigned long flags;
 	int tsbsize, err;
 	u32 busrange[2];
 	u32 vdma[2];
@@ -1594,10 +1597,8 @@ void __init sabre_init(int pnode, char *model_name)
 
 	upa_portid = prom_getintdefault(pnode, "upa-portid", 0xff);
 
-	spin_lock_irqsave(&pci_controller_lock, flags);
 	p->next = pci_controller_root;
 	pci_controller_root = p;
-	spin_unlock_irqrestore(&pci_controller_lock, flags);
 
 	p->pbm_A.portid = upa_portid;
 	p->pbm_B.portid = upa_portid;
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
index be6fa906a..f72da320b 100644
--- a/arch/sparc64/kernel/pci_schizo.c
+++ b/arch/sparc64/kernel/pci_schizo.c
@@ -1171,7 +1171,7 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
 		prom_halt();
 	}
 	bucket = __bucket(irq);
-	tmp = readl(bucket->imap);
+	tmp = upa_readl(bucket->imap);
 	upa_writel(tmp, (pbm->pbm_regs +
 			 schizo_imap_offset(SCHIZO_UE_INO) + 4));
 
@@ -1309,7 +1309,7 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
 		prom_halt();
 	}
 	bucket = __bucket(irq);
-	tmp = readl(bucket->imap);
+	tmp = upa_readl(bucket->imap);
 	upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4));
 
 	pbm = pbm_for_ino(p, SCHIZO_CE_INO);
@@ -1372,10 +1372,10 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
 		    SCHIZO_PCICTRL_RTRY_ERR |
 		    SCHIZO_PCICTRL_SBH_ERR |
 		    SCHIZO_PCICTRL_SERR |
-		    SCHIZO_PCICTRL_SBH_INT |
 		    SCHIZO_PCICTRL_EEN);
 
-	err_no_mask = SCHIZO_PCICTRL_DTO_ERR;
+	err_no_mask = (SCHIZO_PCICTRL_DTO_ERR |
+		       SCHIZO_PCICTRL_SBH_INT);
 
 	/* Enable PCI Error interrupts and clear error
 	 * bits for each PBM.
@@ -1766,6 +1766,14 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
 	 * in pci_iommu.c
 	 */
 
+	iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0);
+	if (!iommu->dummy_page) {
+		prom_printf("PSYCHO_IOMMU: Error, gfp(dummy_page) failed.\n");
+		prom_halt();
+	}
+	memset((void *)iommu->dummy_page, 0, PAGE_SIZE);
+	iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page);
+
 	/* Using assumed page size 8K with 128K entries we need 1MB iommu page
 	 * table (128K ioptes * 8 bytes per iopte).  This is
 	 * page order 7 on UltraSparc.
@@ -1780,7 +1788,7 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
 	iommu->page_table = (iopte_t *)tsbbase;
 	iommu->page_table_map_base = vdma[0];
 	iommu->dma_addr_mask = dma_mask;
-	memset((char *)tsbbase, 0, PAGE_SIZE << order);
+	pci_iommu_table_init(iommu, PAGE_SIZE << order);
 
 	switch (tsbsize) {
 	case 64:
@@ -2073,13 +2081,11 @@ static void __init __schizo_init(int node, char *model_name, int chip_type)
 {
 	struct pci_controller_info *p;
 	struct pci_iommu *iommu;
-	unsigned long flags;
 	int is_pbm_a;
 	u32 portid;
 
 	portid = prom_getintdefault(node, "portid", 0xff);
 
-	spin_lock_irqsave(&pci_controller_lock, flags);
 	for(p = pci_controller_root; p; p = p->next) {
 		struct pci_pbm_info *pbm;
 
@@ -2091,13 +2097,11 @@ static void __init __schizo_init(int node, char *model_name, int chip_type)
 		       &p->pbm_B);
 
 		if (portid_compare(pbm->portid, portid, chip_type)) {
-			spin_unlock_irqrestore(&pci_controller_lock, flags);
 			is_pbm_a = (p->pbm_A.prom_node == 0);
 			schizo_pbm_init(p, node, portid, chip_type);
 			return;
 		}
 	}
-	spin_unlock_irqrestore(&pci_controller_lock, flags);
 
 	p = kmalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
 	if (!p) {
@@ -2122,10 +2126,8 @@ static void __init __schizo_init(int node, char *model_name, int chip_type)
 	memset(iommu, 0, sizeof(*iommu));
 	p->pbm_B.iommu = iommu;
 
-	spin_lock_irqsave(&pci_controller_lock, flags);
 	p->next = pci_controller_root;
 	pci_controller_root = p;
-	spin_unlock_irqrestore(&pci_controller_lock, flags);
 
 	p->index = pci_num_controllers++;
 	p->pbms_same_domain = 0;
diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c
index 006a562dc..52f14e399 100644
--- a/arch/sparc64/kernel/power.c
+++ b/arch/sparc64/kernel/power.c
@@ -27,7 +27,7 @@
 int scons_pwroff = 1; 
 
 #ifdef CONFIG_PCI
-static unsigned long power_reg = 0UL;
+static void __iomem *power_reg;
 
 static DECLARE_WAIT_QUEUE_HEAD(powerd_wait);
 static int button_pressed;
@@ -52,7 +52,7 @@ void machine_power_off(void)
 {
 	if (!serial_console || scons_pwroff) {
 #ifdef CONFIG_PCI
-		if (power_reg != 0UL) {
+		if (power_reg) {
 			/* Both register bits seem to have the
 			 * same effect, so until I figure out
 			 * what the difference is...
@@ -130,8 +130,8 @@ void __init power_init(void)
 	return;
 
 found:
-	power_reg = (unsigned long)ioremap(edev->resource[0].start, 0x4);
-	printk("power: Control reg at %016lx ... ", power_reg);
+	power_reg = ioremap(edev->resource[0].start, 0x4);
+	printk("power: Control reg at %p ... ", power_reg);
 	poweroff_method = machine_halt;  /* able to use the standard halt */
 	if (has_button_interrupt(edev)) {
 		if (kernel_thread(powerd, NULL, CLONE_FS) < 0) {
@@ -141,8 +141,7 @@ found:
 		printk("powerd running.\n");
 
 		if (request_irq(edev->irqs[0],
-				power_handler, SA_SHIRQ, "power",
-				(void *) power_reg) < 0)
+				power_handler, SA_SHIRQ, "power", NULL) < 0)
 			printk("power: Error, cannot register IRQ handler.\n");
 	} else {
 		printk("not using powerd.\n");
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 145ce7c73..f3e3c657e 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -588,8 +588,6 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags,
 {
 	int __user *parent_tid_ptr, *child_tid_ptr;
 
-	clone_flags &= ~CLONE_IDLETASK;
-
 #ifdef CONFIG_COMPAT
 	if (test_thread_flag(TIF_32BIT)) {
 		parent_tid_ptr = compat_ptr(regs->u_regs[UREG_I2]);
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
index 8e5e09832..f6073b01d 100644
--- a/arch/sparc64/kernel/ptrace.c
+++ b/arch/sparc64/kernel/ptrace.c
@@ -631,11 +631,8 @@ asmlinkage void syscall_trace(void)
 		return;
 	if (!(current->ptrace & PT_PTRACED))
 		return;
-	current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-					? 0x80 : 0);
-	current->state = TASK_STOPPED;
-	notify_parent(current, SIGCHLD);
-	schedule();
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+				 ? 0x80 : 0));
 
 	/*
 	 * this isn't the same as continuing with a signal, but it will do
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index 438e373ce..51e762bcd 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -43,7 +43,6 @@
 #include <asm/idprom.h>
 #include <asm/head.h>
 #include <asm/starfire.h>
-#include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 #include <asm/timer.h>
 #include <asm/sections.h>
diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
index ba3fcb4b2..d81bfab51 100644
--- a/arch/sparc64/kernel/signal.c
+++ b/arch/sparc64/kernel/signal.c
@@ -84,8 +84,8 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs)
 	regs->tnpc = npc;
 	err |= __get_user(regs->y, &((*grp)[MC_Y]));
 	err |= __get_user(tstate, &((*grp)[MC_TSTATE]));
-	regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
-	regs->tstate |= (tstate & (TSTATE_ICC | TSTATE_XCC));
+	regs->tstate &= ~(TSTATE_ASI | TSTATE_ICC | TSTATE_XCC);
+	regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC));
 	err |= __get_user(regs->u_regs[UREG_G1], (&(*grp)[MC_G1]));
 	err |= __get_user(regs->u_regs[UREG_G2], (&(*grp)[MC_G2]));
 	err |= __get_user(regs->u_regs[UREG_G3], (&(*grp)[MC_G3]));
@@ -135,7 +135,7 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs)
 
 	return;
 do_sigsegv:
-	do_exit(SIGSEGV);
+	force_sig(SIGSEGV, current);
 }
 
 asmlinkage void sparc64_get_context(struct pt_regs *regs)
@@ -226,7 +226,7 @@ asmlinkage void sparc64_get_context(struct pt_regs *regs)
 
 	return;
 do_sigsegv:
-	do_exit(SIGSEGV);
+	force_sig(SIGSEGV, current);
 }
 
 struct rt_signal_frame {
@@ -408,9 +408,9 @@ void do_rt_sigreturn(struct pt_regs *regs)
 	err |= __get_user(tstate, &sf->regs.tstate);
 	err |= copy_from_user(regs->u_regs, sf->regs.u_regs, sizeof(regs->u_regs));
 
-	/* User can only change condition codes in %tstate. */
-	regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
-	regs->tstate |= (tstate & (TSTATE_ICC | TSTATE_XCC));
+	/* User can only change condition codes and %asi in %tstate. */
+	regs->tstate &= ~(TSTATE_ASI | TSTATE_ICC | TSTATE_XCC);
+	regs->tstate |= (tstate & (TSTATE_ASI | TSTATE_ICC | TSTATE_XCC));
 
 	err |= __get_user(fpu_save, &sf->fpu_save);
 	if (fpu_save)
@@ -439,7 +439,7 @@ void do_rt_sigreturn(struct pt_regs *regs)
 	spin_unlock_irq(&current->sighand->siglock);
 	return;
 segv:
-	send_sig(SIGSEGV, current, 1);
+	force_sig(SIGSEGV, current);
 }
 
 /* Checks if the fp is valid */
@@ -545,6 +545,12 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
 	regs->u_regs[UREG_I0] = signo;
 	regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
 
+	/* The sigcontext is passed in this way because of how it
+	 * is defined in GLIBC's /usr/include/bits/sigcontext.h
+	 * for sparc64.  It includes the 128 bytes of siginfo_t.
+	 */
+	regs->u_regs[UREG_I2] = (unsigned long) &sf->info;
+
 	/* 5. signal handler */
 	regs->tpc = (unsigned long) ka->sa.sa_handler;
 	regs->tnpc = (regs->tpc + 4);
@@ -559,7 +565,7 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
 sigill:
 	do_exit(SIGILL);
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signo, current);
 }
 
 static inline void handle_signal(unsigned long signr, struct k_sigaction *ka,
@@ -568,8 +574,6 @@ static inline void handle_signal(unsigned long signr, struct k_sigaction *ka,
 {
 	setup_rt_frame(ka, regs, signr, oldset,
 		       (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
 	if (!(ka->sa.sa_flags & SA_NOMASK)) {
 		spin_lock_irq(&current->sighand->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -609,6 +613,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs * regs,
 {
 	siginfo_t info;
 	struct signal_deliver_cookie cookie;
+	struct k_sigaction ka;
 	int signr;
 	
 	cookie.restart_syscall = restart_syscall;
@@ -626,15 +631,11 @@ static int do_signal(sigset_t *oldset, struct pt_regs * regs,
 	}
 #endif	
 
-	signr = get_signal_to_deliver(&info, regs, &cookie);
+	signr = get_signal_to_deliver(&info, &ka, regs, &cookie);
 	if (signr > 0) {
-		struct k_sigaction *ka;
-
-		ka = &current->sighand->action[signr-1];
-
 		if (cookie.restart_syscall)
-			syscall_restart(orig_i0, regs, &ka->sa);
-		handle_signal(signr, ka, &info, oldset, regs);
+			syscall_restart(orig_i0, regs, &ka.sa);
+		handle_signal(signr, &ka, &info, oldset, regs);
 		return 1;
 	}
 	if (cookie.restart_syscall &&
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
index a9a5b31a3..63d9cec39 100644
--- a/arch/sparc64/kernel/signal32.c
+++ b/arch/sparc64/kernel/signal32.c
@@ -59,6 +59,16 @@ struct signal_sframe32 {
 	unsigned int extramask[_COMPAT_NSIG_WORDS - 1];
 };
 
+/* This magic should be in g_upper[0] for all upper parts
+ * to be valid.
+ */
+#define SIGINFO_EXTRA_V8PLUS_MAGIC	0x130e269
+typedef struct {
+	unsigned int g_upper[8];
+	unsigned int o_upper[8];
+	unsigned int asi;
+} siginfo_extra_v8plus_t;
+
 /* 
  * And the new one, intended to be used for Linux applications only
  * (we have enough in there to work with clone).
@@ -76,9 +86,61 @@ struct new_signal_frame32 {
 	__siginfo_fpu_t		fpu_state;
 };
 
+struct siginfo32 {
+	int si_signo;
+	int si_errno;
+	int si_code;
+
+	union {
+		int _pad[SI_PAD_SIZE32];
+
+		/* kill() */
+		struct {
+			compat_pid_t _pid;		/* sender's pid */
+			unsigned int _uid;		/* sender's uid */
+		} _kill;
+
+		/* POSIX.1b timers */
+		struct {
+			timer_t _tid;			/* timer id */
+			int _overrun;			/* overrun count */
+			sigval_t32 _sigval;		/* same as below */
+			int _sys_private;		/* not to be passed to user */
+		} _timer;
+
+		/* POSIX.1b signals */
+		struct {
+			compat_pid_t _pid;		/* sender's pid */
+			unsigned int _uid;		/* sender's uid */
+			sigval_t32 _sigval;
+		} _rt;
+
+		/* SIGCHLD */
+		struct {
+			compat_pid_t _pid;		/* which child */
+			unsigned int _uid;		/* sender's uid */
+			int _status;			/* exit code */
+			compat_clock_t _utime;
+			compat_clock_t _stime;
+		} _sigchld;
+
+		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
+		struct {
+			u32 _addr; /* faulting insn/memory ref. */
+			int _trapno;
+		} _sigfault;
+
+		/* SIGPOLL */
+		struct {
+			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
+			int _fd;
+		} _sigpoll;
+	} _sifields;
+};
+
 struct rt_signal_frame32 {
 	struct sparc_stackf32	ss;
-	siginfo_t32		info;
+	struct siginfo32	info;
 	struct pt_regs32	regs;
 	compat_sigset_t		mask;
 	/* __siginfo_fpu32_t * */ u32 fpu_save;
@@ -95,11 +157,11 @@ struct rt_signal_frame32 {
 #define NF_ALIGNEDSZ  (((sizeof(struct new_signal_frame32) + 7) & (~7)))
 #define RT_ALIGNEDSZ  (((sizeof(struct rt_signal_frame32) + 7) & (~7)))
 
-int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from)
+int copy_siginfo_to_user32(struct siginfo32 __user *to, siginfo_t *from)
 {
 	int err;
 
-	if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t32)))
+	if (!access_ok(VERIFY_WRITE, to, sizeof(struct siginfo32)))
 		return -EFAULT;
 
 	/* If you change siginfo_t structure, please be sure
@@ -119,7 +181,7 @@ int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from)
 		case __SI_TIMER >> 16:
 			err |= __put_user(from->si_tid, &to->si_tid);
 			err |= __put_user(from->si_overrun, &to->si_overrun);
-			err |= __put_user((u32)(u64)from->si_ptr, &to->si_ptr);
+			err |= __put_user(from->si_int, &to->si_int);
 			break;
 		case __SI_CHLD >> 16:
 			err |= __put_user(from->si_utime, &to->si_utime);
@@ -145,6 +207,22 @@ int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from)
 	return err;
 }
 
+/* CAUTION: This is just a very minimalist implementation for the
+ *          sake of compat_sys_rt_sigqueueinfo()
+ */
+int copy_siginfo_to_kernel32(siginfo_t *to, struct siginfo32 __user *from)
+{
+	if (!access_ok(VERIFY_WRITE, from, sizeof(struct siginfo32)))
+		return -EFAULT;
+
+	if (copy_from_user(to, from, 3*sizeof(int)) ||
+	    copy_from_user(to->_sifields._pad, from->_sifields._pad,
+			   SI_PAD_SIZE))
+		return -EFAULT;
+
+	return 0;
+}
+
 /*
  * atomically swap in the new signal mask, and wait for a signal.
  * This is really tricky on the Sparc, watch out...
@@ -299,8 +377,13 @@ void do_new_sigreturn32(struct pt_regs *regs)
 	if ((psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS) {
 		err |= __get_user(i, &sf->v8plus.g_upper[0]);
 		if (i == SIGINFO_EXTRA_V8PLUS_MAGIC) {
+			unsigned long asi;
+
 			for (i = UREG_G1; i <= UREG_I7; i++)
 				err |= __get_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]);
+			err |= __get_user(asi, &sf->v8plus.asi);
+			regs->tstate &= ~TSTATE_ASI;
+			regs->tstate |= ((asi & 0xffUL) << 24UL);
 		}
 	}
 
@@ -330,7 +413,7 @@ void do_new_sigreturn32(struct pt_regs *regs)
 	return;
 
 segv:
-	do_exit(SIGSEGV);
+	force_sig(SIGSEGV, current);
 }
 
 asmlinkage void do_sigreturn32(struct pt_regs *regs)
@@ -400,7 +483,7 @@ asmlinkage void do_sigreturn32(struct pt_regs *regs)
 	return;
 
 segv:
-	do_exit(SIGSEGV);
+	force_sig(SIGSEGV, current);
 }
 
 asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
@@ -447,8 +530,13 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
 	if ((psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS) {
 		err |= __get_user(i, &sf->v8plus.g_upper[0]);
 		if (i == SIGINFO_EXTRA_V8PLUS_MAGIC) {
+			unsigned long asi;
+
 			for (i = UREG_G1; i <= UREG_I7; i++)
 				err |= __get_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]);
+			err |= __get_user(asi, &sf->v8plus.asi);
+			regs->tstate &= ~TSTATE_ASI;
+			regs->tstate |= ((asi & 0xffUL) << 24UL);
 		}
 	}
 
@@ -487,7 +575,7 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
 	spin_unlock_irq(&current->sighand->siglock);
 	return;
 segv:
-	do_exit(SIGSEGV);
+	force_sig(SIGSEGV, current);
 }
 
 /* Checks if the fp is valid */
@@ -648,7 +736,7 @@ setup_frame32(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *o
 	return;
 
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signr, current);
 }
 
 
@@ -715,7 +803,10 @@ static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
 	err |= __put_user(sizeof(siginfo_extra_v8plus_t), &sf->extra_size);
 	err |= __put_user(SIGINFO_EXTRA_V8PLUS_MAGIC, &sf->v8plus.g_upper[0]);
 	for (i = 1; i < 16; i++)
-		err |= __put_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]);
+		err |= __put_user(((u32 *)regs->u_regs)[2*i],
+				  &sf->v8plus.g_upper[i]);
+	err |= __put_user((regs->tstate & TSTATE_ASI) >> 24UL,
+			  &sf->v8plus.asi);
 
 	if (psr & PSR_EF) {
 		err |= save_fpu_state32(regs, &sf->fpu_state);
@@ -749,6 +840,7 @@ static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
 	regs->u_regs[UREG_FP] = (unsigned long) sf;
 	regs->u_regs[UREG_I0] = signo;
 	regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
+	regs->u_regs[UREG_I2] = (unsigned long) &sf->info;
 
 	/* 4. signal handler */
 	regs->tpc = (unsigned long) ka->sa.sa_handler;
@@ -795,7 +887,7 @@ static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
 sigill:
 	do_exit(SIGILL);
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signo, current);
 }
 
 /* Setup a Solaris stack frame */
@@ -919,7 +1011,7 @@ setup_svr4_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc,
 	return;
 
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signr, current);
 }
 
 asmlinkage int
@@ -1070,7 +1162,7 @@ asmlinkage int svr4_setcontext(svr4_ucontext_t __user *c, struct pt_regs *regs)
 
 	return -EINTR;
 sigsegv:
-	do_exit(SIGSEGV);
+	return -EFAULT;
 }
 
 static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
@@ -1119,6 +1211,8 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
 	for (i = 1; i < 16; i++)
 		err |= __put_user(((u32 *)regs->u_regs)[2*i],
 				  &sf->v8plus.g_upper[i]);
+	err |= __put_user((regs->tstate & TSTATE_ASI) >> 24UL,
+			  &sf->v8plus.asi);
 
 	if (psr & PSR_EF) {
 		err |= save_fpu_state32(regs, &sf->fpu_state);
@@ -1157,6 +1251,7 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
 	regs->u_regs[UREG_FP] = (unsigned long) sf;
 	regs->u_regs[UREG_I0] = signr;
 	regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
+	regs->u_regs[UREG_I2] = (unsigned long) &sf->regs;
 
 	/* 4. signal handler */
 	regs->tpc = (unsigned long) ka->sa.sa_handler;
@@ -1206,7 +1301,7 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
 sigill:
 	do_exit(SIGILL);
 sigsegv:
-	do_exit(SIGSEGV);
+	force_sigsegv(signr, current);
 }
 
 static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
@@ -1225,8 +1320,6 @@ static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
 		else
 			setup_frame32(&ka->sa, regs, signr, oldset, info);
 	}
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
 	if (!(ka->sa.sa_flags & SA_NOMASK)) {
 		spin_lock_irq(&current->sighand->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -1266,21 +1359,19 @@ int do_signal32(sigset_t *oldset, struct pt_regs * regs,
 {
 	siginfo_t info;
 	struct signal_deliver_cookie cookie;
+	struct k_sigaction ka;
 	int signr;
 	int svr4_signal = current->personality == PER_SVR4;
 	
 	cookie.restart_syscall = restart_syscall;
 	cookie.orig_i0 = orig_i0;
 
-	signr = get_signal_to_deliver(&info, regs, &cookie);
+	signr = get_signal_to_deliver(&info, &ka, regs, &cookie);
 	if (signr > 0) {
-		struct k_sigaction *ka;
-
-		ka = &current->sighand->action[signr-1];
-
 		if (cookie.restart_syscall)
-			syscall_restart32(orig_i0, regs, &ka->sa);
-		handle_signal32(signr, ka, &info, oldset, regs, svr4_signal);
+			syscall_restart32(orig_i0, regs, &ka.sa);
+		handle_signal32(signr, &ka, &info, oldset,
+				regs, svr4_signal);
 		return 1;
 	}
 	if (cookie.restart_syscall &&
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index abc65dc6d..f2bbaafd8 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -19,6 +19,7 @@
 #include <linux/seq_file.h>
 #include <linux/cache.h>
 #include <linux/jiffies.h>
+#include <linux/profile.h>
 
 #include <asm/head.h>
 #include <asm/ptrace.h>
@@ -31,7 +32,6 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/oplib.h>
-#include <asm/hardirq.h>
 #include <asm/uaccess.h>
 #include <asm/timer.h>
 #include <asm/starfire.h>
@@ -303,14 +303,7 @@ static int __devinit smp_boot_one_cpu(unsigned int cpu)
 	struct task_struct *p;
 	int timeout, ret, cpu_node;
 
-	kernel_thread(NULL, NULL, CLONE_IDLETASK);
-
-	p = prev_task(&init_task);
-
-	init_idle(p, cpu);
-
-	unhash_process(p);
-
+	p = fork_idle(cpu);
 	callin_flag = 0;
 	cpu_new_thread = p->thread_info;
 	cpu_set(cpu, cpu_callout_map);
@@ -981,8 +974,6 @@ void smp_promstop_others(void)
 	smp_cross_call(&xcall_promstop, 0, 0, 0);
 }
 
-extern void sparc64_do_profile(struct pt_regs *regs);
-
 #define prof_multiplier(__cpu)		cpu_data(__cpu).multiplier
 #define prof_counter(__cpu)		cpu_data(__cpu).counter
 
@@ -1008,7 +999,7 @@ void smp_percpu_timer_interrupt(struct pt_regs *regs)
 	}
 
 	do {
-		sparc64_do_profile(regs);
+		profile_tick(CPU_PROFILING, regs);
 		if (!--prof_counter(cpu)) {
 			irq_enter();
 
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 5eafadd28..3864b4b6e 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -34,7 +34,6 @@
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/hardirq.h>
 #include <asm/idprom.h>
 #include <asm/svr4.h>
 #include <asm/elf.h>
@@ -74,8 +73,6 @@ extern void *__bzero(void *, size_t);
 extern void *__memscan_zero(void *, size_t);
 extern void *__memscan_generic(void *, int, size_t);
 extern int __memcmp(const void *, const void *, __kernel_size_t);
-extern int __strncmp(const char *, const char *, __kernel_size_t);
-extern __kernel_size_t __strlen(const char *);
 extern __kernel_size_t strlen(const char *);
 extern void linux_sparc_syscall(void);
 extern void rtrap(void);
@@ -144,7 +141,7 @@ EXPORT_SYMBOL(synchronize_irq);
 
 #if defined(CONFIG_MCOUNT)
 extern void _mcount(void);
-EXPORT_SYMBOL_NOVERS(_mcount);
+EXPORT_SYMBOL(_mcount);
 #endif
 
 /* CPU online map and active count.  */
@@ -187,8 +184,6 @@ EXPORT_SYMBOL(atomic_dec_and_lock);
 EXPORT_SYMBOL(___test_and_set_bit);
 EXPORT_SYMBOL(___test_and_clear_bit);
 EXPORT_SYMBOL(___test_and_change_bit);
-EXPORT_SYMBOL(___test_and_set_le_bit);
-EXPORT_SYMBOL(___test_and_clear_le_bit);
 
 /* Bit searching */
 EXPORT_SYMBOL(find_next_bit);
@@ -295,7 +290,6 @@ EXPORT_SYMBOL(__prom_getchild);
 EXPORT_SYMBOL(__prom_getsibling);
 
 /* sparc library symbols */
-EXPORT_SYMBOL(__strlen);
 EXPORT_SYMBOL(strlen);
 EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(__strlen_user);
@@ -334,7 +328,6 @@ EXPORT_SYMBOL(sys_close);
 #endif
 
 /* Special internal versions of library functions. */
-EXPORT_SYMBOL(__memset);
 EXPORT_SYMBOL(_clear_page);
 EXPORT_SYMBOL(clear_user_page);
 EXPORT_SYMBOL(copy_user_page);
@@ -342,8 +335,7 @@ EXPORT_SYMBOL(__bzero);
 EXPORT_SYMBOL(__memscan_zero);
 EXPORT_SYMBOL(__memscan_generic);
 EXPORT_SYMBOL(__memcmp);
-EXPORT_SYMBOL(__strncmp);
-EXPORT_SYMBOL(__memmove);
+EXPORT_SYMBOL(__memset);
 EXPORT_SYMBOL(memchr);
 
 EXPORT_SYMBOL(csum_partial);
@@ -351,9 +343,12 @@ EXPORT_SYMBOL(csum_partial_copy_sparc64);
 EXPORT_SYMBOL(ip_fast_csum);
 
 /* Moving data to/from/in userspace. */
-EXPORT_SYMBOL(__copy_to_user);
-EXPORT_SYMBOL(__copy_from_user);
-EXPORT_SYMBOL(__copy_in_user);
+EXPORT_SYMBOL(___copy_to_user);
+EXPORT_SYMBOL(___copy_from_user);
+EXPORT_SYMBOL(___copy_in_user);
+EXPORT_SYMBOL(copy_to_user_fixup);
+EXPORT_SYMBOL(copy_from_user_fixup);
+EXPORT_SYMBOL(copy_in_user_fixup);
 EXPORT_SYMBOL(__strncpy_from_user);
 EXPORT_SYMBOL(__bzero_noasi);
 
@@ -367,17 +362,24 @@ EXPORT_SYMBOL(pfn_to_page);
 /* No version information on this, heavily used in inline asm,
  * and will always be 'void __ret_efault(void)'.
  */
-EXPORT_SYMBOL_NOVERS(__ret_efault);
+EXPORT_SYMBOL(__ret_efault);
 
 /* No version information on these, as gcc produces such symbols. */
-EXPORT_SYMBOL_NOVERS(memcmp);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(memmove);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(strncmp);
+
+/* Delay routines. */
+EXPORT_SYMBOL(__udelay);
+EXPORT_SYMBOL(__ndelay);
+EXPORT_SYMBOL(__const_udelay);
+EXPORT_SYMBOL(__delay);
 
 void VISenter(void);
 /* RAID code needs this */
-EXPORT_SYMBOL_NOVERS(VISenter);
+EXPORT_SYMBOL(VISenter);
 
 /* for input/keybdev */
 EXPORT_SYMBOL(sun_do_break);
diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S
index 7a5d4f4e5..f978c13f5 100644
--- a/arch/sparc64/kernel/sys32.S
+++ b/arch/sparc64/kernel/sys32.S
@@ -120,7 +120,7 @@ SIGN1(sys32_setgroups, sys_setgroups, %o0)
 SIGN2(sys32_setpgid, sys_setpgid, %o0, %o1)
 SIGN3(sys32_setpriority, sys_setpriority, %o0, %o1, %o2)
 SIGN1(sys32_ssetmask, sys_ssetmask, %o0)
-SIGN2(sys32_syslog, sys_syslog, %o0, %o1)
+SIGN2(sys32_syslog, sys_syslog, %o0, %o2)
 SIGN1(sys32_umask, sys_umask, %o0)
 SIGN3(sys32_tgkill, sys_tgkill, %o0, %o1, %o2)
 SIGN1(sys32_sendto, sys_sendto, %o0)
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 56e277383..b81f15521 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -1045,7 +1045,7 @@ asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set,
 }
 
 asmlinkage long sys32_rt_sigtimedwait(compat_sigset_t __user *uthese,
-				      siginfo_t32 __user *uinfo,
+				      struct siginfo32 __user *uinfo,
 				      struct compat_timespec __user *uts,
 				      compat_size_t sigsetsize)
 {
@@ -1130,15 +1130,15 @@ asmlinkage long sys32_rt_sigtimedwait(compat_sigset_t __user *uthese,
 }
 
 asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig,
-					   siginfo_t32 __user *uinfo)
+					   struct siginfo32 __user *uinfo)
 {
 	siginfo_t info;
 	int ret;
 	mm_segment_t old_fs = get_fs();
 	
-	if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
-	    copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
+	if (copy_siginfo_to_kernel32(&info, uinfo))
 		return -EFAULT;
+
 	set_fs (KERNEL_DS);
 	ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);
 	set_fs (old_fs);
@@ -1736,3 +1736,33 @@ sys32_timer_create(u32 clock, struct sigevent32 __user *se32,
 	return err;
 }
 
+asmlinkage long compat_sys_waitid(u32 which, u32 pid,
+				  struct siginfo32 __user *uinfo, u32 options,
+				  struct compat_rusage __user *uru)
+{
+	siginfo_t info;
+	struct rusage ru;
+	long ret;
+	mm_segment_t old_fs = get_fs();
+
+	memset(&info, 0, sizeof(info));
+
+	set_fs (KERNEL_DS);
+	ret = sys_waitid(which, pid, (siginfo_t __user *) &info,
+			 options,
+			 uru ? (struct rusage __user *) &ru : NULL);
+	set_fs (old_fs);
+
+	if (ret < 0 || info.si_signo == 0)
+		return ret;
+
+	if (uru) {
+		ret = put_compat_rusage(&ru, uru);
+		if (ret)
+			return ret;
+	}
+
+	BUG_ON(info.si_code & __SI_MASK);
+	info.si_code |= __SI_CHLD;
+	return copy_siginfo_to_user32(uinfo, &info);
+}
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 4aee27656..1c6807c78 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -75,7 +75,7 @@ sys_call_table32:
 /*260*/	.word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_timer_gettime, sys_timer_getoverrun
 	.word sys_timer_delete, sys32_timer_create, sys_vserver, compat_sys_io_setup, sys_io_destroy
 /*270*/	.word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
-	.word sys_mq_timedsend, sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, sys_ni_syscall
+	.word sys_mq_timedsend, sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
 /*280*/	.word sys_ni_syscall, sys_ni_syscall, sys_ni_syscall
 
 #endif /* CONFIG_COMPAT */
@@ -141,7 +141,7 @@ sys_call_table:
 /*260*/	.word sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
 	.word sys_timer_delete, sys_timer_create, sys_vserver, sys_io_setup, sys_io_destroy
 /*270*/	.word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
-	.word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_ni_syscall
+	.word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
 /*280*/	.word sys_ni_syscall, sys_ni_syscall, sys_ni_syscall
 
 #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index f961a0d3b..b50e16d49 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -29,6 +29,7 @@
 #include <linux/jiffies.h>
 #include <linux/cpufreq.h>
 #include <linux/percpu.h>
+#include <linux/profile.h>
 
 #include <asm/oplib.h>
 #include <asm/mostek.h>
@@ -67,6 +68,18 @@ struct sparc64_tick_ops *tick_ops;
 
 #define TICK_PRIV_BIT	(1UL << 63)
 
+#ifdef CONFIG_SMP
+unsigned long profile_pc(struct pt_regs *regs)
+{
+	unsigned long pc = instruction_pointer(regs);
+
+	if (in_lock_functions(pc))
+		return regs->u_regs[UREG_RETPC];
+	return pc;
+}
+EXPORT_SYMBOL(profile_pc);
+#endif
+
 static void tick_disable_protection(void)
 {
 	/* Set things up so user can access tick register for profiling
@@ -418,7 +431,6 @@ static struct sparc64_tick_ops hbtick_operations = {
 unsigned long timer_tick_offset;
 unsigned long timer_tick_compare;
 
-static unsigned long timer_ticks_per_usec_quotient;
 static unsigned long timer_ticks_per_nsec_quotient;
 
 #define TICK_SIZE (tick_nsec / 1000)
@@ -441,28 +453,6 @@ static inline void timer_check_rtc(void)
 	}
 }
 
-void sparc64_do_profile(struct pt_regs *regs)
-{
-	unsigned long pc;
-
-	profile_hook(regs);
-
-	if (user_mode(regs))
-		return;
-
-	if (!prof_buffer)
-		return;
-
-	pc = regs->tpc;
-
-	pc -= (unsigned long) _stext;
-	pc >>= prof_shift;
-
-	if(pc >= prof_len)
-		pc = prof_len - 1;
-	atomic_inc((atomic_t *)&prof_buffer[pc]);
-}
-
 static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	unsigned long ticks, pstate;
@@ -471,7 +461,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 
 	do {
 #ifndef CONFIG_SMP
-		sparc64_do_profile(regs);
+		profile_tick(CPU_PROFILING, regs);
 #endif
 		do_timer(regs);
 
@@ -920,10 +910,10 @@ try_isa_clock:
 }
 
 /* This is gets the master TICK_INT timer going. */
-static unsigned long sparc64_init_timers(irqreturn_t (*cfunc)(int, void *, struct pt_regs *))
+static unsigned long sparc64_init_timers(void)
 {
-	unsigned long pstate, clock;
-	int node, err;
+	unsigned long clock;
+	int node;
 #ifdef CONFIG_SMP
 	extern void smp_tick_init(void);
 #endif
@@ -956,6 +946,14 @@ static unsigned long sparc64_init_timers(irqreturn_t (*cfunc)(int, void *, struc
 	smp_tick_init();
 #endif
 
+	return clock;
+}
+
+static void sparc64_start_timers(irqreturn_t (*cfunc)(int, void *, struct pt_regs *))
+{
+	unsigned long pstate;
+	int err;
+
 	/* Register IRQ handler. */
 	err = request_irq(build_irq(0, 0, 0UL, 0UL), cfunc, SA_STATIC_ALLOC,
 			  "timer", NULL);
@@ -981,8 +979,6 @@ static unsigned long sparc64_init_timers(irqreturn_t (*cfunc)(int, void *, struc
 			     : "r" (pstate));
 
 	local_irq_enable();
-
-	return clock;
 }
 
 struct freq_table {
@@ -1034,18 +1030,27 @@ static int sparc64_cpufreq_notifier(struct notifier_block *nb, unsigned long val
 static struct notifier_block sparc64_cpufreq_notifier_block = {
 	.notifier_call	= sparc64_cpufreq_notifier
 };
-#endif
+
+#endif /* CONFIG_CPU_FREQ */
+
+static struct time_interpolator sparc64_cpu_interpolator = {
+	.source		=	TIME_SOURCE_CPU,
+	.shift		=	16,
+};
 
 /* The quotient formula is taken from the IA64 port. */
-#define SPARC64_USEC_PER_CYC_SHIFT	30UL
 #define SPARC64_NSEC_PER_CYC_SHIFT	30UL
 void __init time_init(void)
 {
-	unsigned long clock = sparc64_init_timers(timer_interrupt);
+	unsigned long clock = sparc64_init_timers();
 
-	timer_ticks_per_usec_quotient =
-		(((1000000UL << SPARC64_USEC_PER_CYC_SHIFT) +
-		  (clock / 2)) / clock);
+	sparc64_cpu_interpolator.frequency = clock;
+	register_time_interpolator(&sparc64_cpu_interpolator);
+
+	/* Now that the interpolator is registered, it is
+	 * safe to start the timer ticking.
+	 */
+	sparc64_start_timers(timer_interrupt);
 
 	timer_ticks_per_nsec_quotient =
 		(((NSEC_PER_SEC << SPARC64_NSEC_PER_CYC_SHIFT) +
@@ -1057,17 +1062,6 @@ void __init time_init(void)
 #endif
 }
 
-static __inline__ unsigned long do_gettimeoffset(void)
-{
-	unsigned long ticks = tick_ops->get_tick();
-
-	ticks += timer_tick_offset;
-	ticks -= timer_tick_compare;
-
-	return (ticks * timer_ticks_per_usec_quotient)
-		>> SPARC64_USEC_PER_CYC_SHIFT;
-}
-
 unsigned long long sched_clock(void)
 {
 	unsigned long ticks = tick_ops->get_tick();
@@ -1076,100 +1070,6 @@ unsigned long long sched_clock(void)
 		>> SPARC64_NSEC_PER_CYC_SHIFT;
 }
 
-int do_settimeofday(struct timespec *tv)
-{
-	time_t wtm_sec, sec = tv->tv_sec;
-	long wtm_nsec, nsec = tv->tv_nsec;
-
-	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-		return -EINVAL;
-
-	if (this_is_starfire)
-		return 0;
-
-	write_seqlock_irq(&xtime_lock);
-	/*
-	 * This is revolting. We need to set "xtime" correctly. However, the
-	 * value in this location is the value at the most recent update of
-	 * wall time.  Discover what correction gettimeofday() would have
-	 * made, and then undo it!
-	 */
-	nsec -= do_gettimeoffset() * 1000;
-	nsec -= (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ);
-
-	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
-	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
-
-	set_normalized_timespec(&xtime, sec, nsec);
-	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
-	time_adjust = 0;		/* stop active adjtime() */
-	time_status |= STA_UNSYNC;
-	time_maxerror = NTP_PHASE_LIMIT;
-	time_esterror = NTP_PHASE_LIMIT;
-	write_sequnlock_irq(&xtime_lock);
-	clock_was_set();
-	return 0;
-}
-
-EXPORT_SYMBOL(do_settimeofday);
-
-/* Ok, my cute asm atomicity trick doesn't work anymore.
- * There are just too many variables that need to be protected
- * now (both members of xtime, wall_jiffies, et al.)
- */
-void do_gettimeofday(struct timeval *tv)
-{
-	unsigned long seq;
-	unsigned long usec, sec;
-	unsigned long max_ntp_tick = tick_usec - tickadj;
-
-	do {
-		unsigned long lost;
-
-		seq = read_seqbegin(&xtime_lock);
-		usec = do_gettimeoffset();
-		lost = jiffies - wall_jiffies;
-
-		/*
-		 * If time_adjust is negative then NTP is slowing the clock
-		 * so make sure not to go into next possible interval.
-		 * Better to lose some accuracy than have time go backwards..
-		 */
-		if (unlikely(time_adjust < 0)) {
-			usec = min(usec, max_ntp_tick);
-
-			if (lost)
-				usec += lost * max_ntp_tick;
-		}
-		else if (unlikely(lost))
-			usec += lost * tick_usec;
-
-		sec = xtime.tv_sec;
-
-		/* Believe it or not, this divide shows up on
-		 * kernel profiles.  The problem is that it is
-		 * both 64-bit and signed.  Happily, 32-bits
-		 * of precision is all we really need and in
-		 * doing so gcc ends up emitting a cheap multiply.
-		 *
-		 * XXX Why is tv_nsec 'long' and 'signed' in
-		 * XXX the first place, can it even be negative?
-		 */
-		usec += ((unsigned int) xtime.tv_nsec / 1000U);
-	} while (read_seqretry(&xtime_lock, seq));
-
-	while (usec >= 1000000) {
-		usec -= 1000000;
-		sec++;
-	}
-
-	tv->tv_sec = sec;
-	tv->tv_usec = usec;
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
-
 static int set_rtc_mmss(unsigned long nowtime)
 {
 	int real_seconds, real_minutes, chip_minutes;
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 473901974..7519f39c5 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -36,10 +36,24 @@
 #include <asm/psrcompat.h>
 #include <asm/processor.h>
 #include <asm/timer.h>
+#include <asm/kdebug.h>
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 #endif
 
+struct notifier_block *sparc64die_chain;
+static spinlock_t die_notifier_lock = SPIN_LOCK_UNLOCKED;
+
+int register_die_notifier(struct notifier_block *nb)
+{
+	int err = 0;
+	unsigned long flags;
+	spin_lock_irqsave(&die_notifier_lock, flags);
+	err = notifier_chain_register(&sparc64die_chain, nb);
+	spin_unlock_irqrestore(&die_notifier_lock, flags);
+	return err;
+}
+
 /* When an irrecoverable trap occurs at tl > 0, the trap entry
  * code logs the trap state registers at every level in the trap
  * stack.  It is found at (pt_regs + sizeof(pt_regs)) and the layout
@@ -71,11 +85,20 @@ static void dump_tl1_traplog(struct tl1_traplog *p)
 	}
 }
 
-void bad_trap (struct pt_regs *regs, long lvl)
+void do_call_debug(struct pt_regs *regs) 
+{ 
+	notify_die(DIE_CALL, "debug call", regs, 0, 255, SIGINT); 
+}
+
+void bad_trap(struct pt_regs *regs, long lvl)
 {
 	char buffer[32];
 	siginfo_t info;
 
+	if (notify_die(DIE_TRAP, "bad trap", regs,
+		       0, lvl, SIGTRAP) == NOTIFY_STOP)
+		return;
+
 	if (lvl < 0x100) {
 		sprintf(buffer, "Bad hw trap %lx at tl0\n", lvl);
 		die_if_kernel(buffer, regs);
@@ -84,7 +107,7 @@ void bad_trap (struct pt_regs *regs, long lvl)
 	lvl -= 0x100;
 	if (regs->tstate & TSTATE_PRIV) {
 		sprintf(buffer, "Kernel bad sw trap %lx", lvl);
-		die_if_kernel (buffer, regs);
+		die_if_kernel(buffer, regs);
 	}
 	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
@@ -98,10 +121,14 @@ void bad_trap (struct pt_regs *regs, long lvl)
 	force_sig_info(SIGILL, &info, current);
 }
 
-void bad_trap_tl1 (struct pt_regs *regs, long lvl)
+void bad_trap_tl1(struct pt_regs *regs, long lvl)
 {
 	char buffer[32];
 	
+	if (notify_die(DIE_TRAP_TL1, "bad trap tl1", regs,
+		       0, lvl, SIGTRAP) == NOTIFY_STOP)
+		return;
+
 	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
 
 	sprintf (buffer, "Bad trap %lx at tl>0", lvl);
@@ -121,6 +148,10 @@ void instruction_access_exception(struct pt_regs *regs,
 {
 	siginfo_t info;
 
+	if (notify_die(DIE_TRAP, "instruction access exception", regs,
+		       0, 0x8, SIGTRAP) == NOTIFY_STOP)
+		return;
+
 	if (regs->tstate & TSTATE_PRIV) {
 		printk("instruction_access_exception: SFSR[%016lx] SFAR[%016lx], going.\n",
 		       sfsr, sfar);
@@ -141,15 +172,23 @@ void instruction_access_exception(struct pt_regs *regs,
 void instruction_access_exception_tl1(struct pt_regs *regs,
 				      unsigned long sfsr, unsigned long sfar)
 {
+	if (notify_die(DIE_TRAP_TL1, "instruction access exception tl1", regs,
+		       0, 0x8, SIGTRAP) == NOTIFY_STOP)
+		return;
+
 	dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
 	instruction_access_exception(regs, sfsr, sfar);
 }
 
-void data_access_exception (struct pt_regs *regs,
-			    unsigned long sfsr, unsigned long sfar)
+void data_access_exception(struct pt_regs *regs,
+			   unsigned long sfsr, unsigned long sfar)
 {
 	siginfo_t info;
 
+	if (notify_die(DIE_TRAP, "data access exception", regs,
+		       0, 0x30, SIGTRAP) == NOTIFY_STOP)
+		return;
+
 	if (regs->tstate & TSTATE_PRIV) {
 		/* Test if this comes from uaccess places. */
 		unsigned long fixup;
@@ -220,6 +259,10 @@ void do_iae(struct pt_regs *regs)
 
 	spitfire_clean_and_reenable_l1_caches();
 
+	if (notify_die(DIE_TRAP, "instruction access exception", regs,
+		       0, 0x8, SIGTRAP) == NOTIFY_STOP)
+		return;
+
 	info.si_signo = SIGBUS;
 	info.si_errno = 0;
 	info.si_code = BUS_OBJERR;
@@ -230,6 +273,8 @@ void do_iae(struct pt_regs *regs)
 
 void do_dae(struct pt_regs *regs)
 {
+	siginfo_t info;
+
 #ifdef CONFIG_PCI
 	if (pci_poke_in_progress && pci_poke_cpu == smp_processor_id()) {
 		spitfire_clean_and_reenable_l1_caches();
@@ -244,7 +289,18 @@ void do_dae(struct pt_regs *regs)
 		return;
 	}
 #endif
-	do_iae(regs);
+	spitfire_clean_and_reenable_l1_caches();
+
+	if (notify_die(DIE_TRAP, "data access exception", regs,
+		       0, 0x30, SIGTRAP) == NOTIFY_STOP)
+		return;
+
+	info.si_signo = SIGBUS;
+	info.si_errno = 0;
+	info.si_code = BUS_OBJERR;
+	info.si_addr = (void *)0;
+	info.si_trapno = 0;
+	force_sig_info(SIGBUS, &info, current);
 }
 
 static char ecc_syndrome_table[] = {
@@ -1638,6 +1694,10 @@ void do_fpe_common(struct pt_regs *regs)
 
 void do_fpieee(struct pt_regs *regs)
 {
+	if (notify_die(DIE_TRAP, "fpu exception ieee", regs,
+		       0, 0x24, SIGFPE) == NOTIFY_STOP)
+		return;
+
 	do_fpe_common(regs);
 }
 
@@ -1648,6 +1708,10 @@ void do_fpother(struct pt_regs *regs)
 	struct fpustate *f = FPUSTATE;
 	int ret = 0;
 
+	if (notify_die(DIE_TRAP, "fpu exception other", regs,
+		       0, 0x25, SIGFPE) == NOTIFY_STOP)
+		return;
+
 	switch ((current_thread_info()->xfsr[0] & 0x1c000)) {
 	case (2 << 14): /* unfinished_FPop */
 	case (3 << 14): /* unimplemented_FPop */
@@ -1663,6 +1727,10 @@ void do_tof(struct pt_regs *regs)
 {
 	siginfo_t info;
 
+	if (notify_die(DIE_TRAP, "tagged arithmetic overflow", regs,
+		       0, 0x26, SIGEMT) == NOTIFY_STOP)
+		return;
+
 	if (regs->tstate & TSTATE_PRIV)
 		die_if_kernel("Penguin overflow trap from kernel mode", regs);
 	if (test_thread_flag(TIF_32BIT)) {
@@ -1681,6 +1749,10 @@ void do_div0(struct pt_regs *regs)
 {
 	siginfo_t info;
 
+	if (notify_die(DIE_TRAP, "integer division by zero", regs,
+		       0, 0x28, SIGFPE) == NOTIFY_STOP)
+		return;
+
 	if (regs->tstate & TSTATE_PRIV)
 		die_if_kernel("TL0: Kernel divide by zero.", regs);
 	if (test_thread_flag(TIF_32BIT)) {
@@ -1771,6 +1843,37 @@ void dump_stack(void)
 
 EXPORT_SYMBOL(dump_stack);
 
+static inline int is_kernel_stack(struct task_struct *task,
+				  struct reg_window *rw)
+{
+	unsigned long rw_addr = (unsigned long) rw;
+	unsigned long thread_base, thread_end;
+
+	if (rw_addr < PAGE_OFFSET) {
+		if (task != &init_task)
+			return 0;
+	}
+
+	thread_base = (unsigned long) task->thread_info;
+	thread_end = thread_base + sizeof(union thread_union);
+	if (rw_addr >= thread_base &&
+	    rw_addr < thread_end &&
+	    !(rw_addr & 0x7UL))
+		return 1;
+
+	return 0;
+}
+
+static inline struct reg_window *kernel_stack_up(struct reg_window *rw)
+{
+	unsigned long fp = rw->ins[6];
+
+	if (!fp)
+		return NULL;
+
+	return (struct reg_window *) (fp + STACK_BIAS);
+}
+
 void die_if_kernel(char *str, struct pt_regs *regs)
 {
 	static int die_counter;
@@ -1786,6 +1889,7 @@ void die_if_kernel(char *str, struct pt_regs *regs)
 "                 \\__U_/\n");
 
 	printk("%s(%d): %s [#%d]\n", current->comm, current->pid, str, ++die_counter);
+	notify_die(DIE_OOPS, str, regs, 0, 255, SIGSEGV);
 	__asm__ __volatile__("flushw");
 	__show_regs(regs);
 	if (regs->tstate & TSTATE_PRIV) {
@@ -1795,17 +1899,14 @@ void die_if_kernel(char *str, struct pt_regs *regs)
 		/* Stop the back trace when we hit userland or we
 		 * find some badly aligned kernel stack.
 		 */
-		while (rw					&&
-		       count++ < 30				&&
-		       (((unsigned long) rw) >= PAGE_OFFSET)	&&
-		       (char *) rw < ((char *) current)
-		       + sizeof (union thread_union) 		&&
-		       !(((unsigned long) rw) & 0x7)) {
+		while (rw &&
+		       count++ < 30&&
+		       is_kernel_stack(current, rw)) {
 			printk("Caller[%016lx]", rw->ins[7]);
 			print_symbol(": %s", rw->ins[7]);
 			printk("\n");
-			rw = (struct reg_window *)
-				(rw->ins[6] + STACK_BIAS);
+
+			rw = kernel_stack_up(rw);
 		}
 		instruction_dump ((unsigned int *) regs->tpc);
 	} else {
@@ -1834,6 +1935,10 @@ void do_illegal_instruction(struct pt_regs *regs)
 	u32 insn;
 	siginfo_t info;
 
+	if (notify_die(DIE_TRAP, "illegal instruction", regs,
+		       0, 0x10, SIGILL) == NOTIFY_STOP)
+		return;
+
 	if (tstate & TSTATE_PRIV)
 		die_if_kernel("Kernel illegal instruction", regs);
 	if (test_thread_flag(TIF_32BIT))
@@ -1859,6 +1964,10 @@ void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned lo
 {
 	siginfo_t info;
 
+	if (notify_die(DIE_TRAP, "memory address unaligned", regs,
+		       0, 0x34, SIGSEGV) == NOTIFY_STOP)
+		return;
+
 	if (regs->tstate & TSTATE_PRIV) {
 		extern void kernel_unaligned_trap(struct pt_regs *regs,
 						  unsigned int insn, 
@@ -1881,6 +1990,10 @@ void do_privop(struct pt_regs *regs)
 {
 	siginfo_t info;
 
+	if (notify_die(DIE_TRAP, "privileged operation", regs,
+		       0, 0x11, SIGILL) == NOTIFY_STOP)
+		return;
+
 	if (test_thread_flag(TIF_32BIT)) {
 		regs->tpc &= 0xffffffff;
 		regs->tnpc &= 0xffffffff;
diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S
index 40f7919aa..491bb3681 100644
--- a/arch/sparc64/kernel/ttable.S
+++ b/arch/sparc64/kernel/ttable.S
@@ -158,7 +158,7 @@ tl0_resv164:	BTRAP(0x164) BTRAP(0x165) BTRAP(0x166) BTRAP(0x167) BTRAP(0x168)
 tl0_resv169:	BTRAP(0x169) BTRAP(0x16a) BTRAP(0x16b) BTRAP(0x16c)
 tl0_linux64:	LINUX_64BIT_SYSCALL_TRAP
 tl0_gsctx:	TRAP(sparc64_get_context) TRAP(sparc64_set_context)
-tl0_resv170:	BTRAP(0x170) BTRAP(0x171) BTRAP(0x172)
+tl0_resv170:	KPROBES_TRAP(0x170) KPROBES_TRAP(0x171) BTRAP(0x172)
 tl0_resv173:	BTRAP(0x173) BTRAP(0x174) BTRAP(0x175) BTRAP(0x176) BTRAP(0x177)
 tl0_resv178:	BTRAP(0x178) BTRAP(0x179) BTRAP(0x17a) BTRAP(0x17b) BTRAP(0x17c)
 tl0_resv17d:	BTRAP(0x17d) BTRAP(0x17e) BTRAP(0x17f)
diff --git a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S
index 8faeee09f..a710d38d1 100644
--- a/arch/sparc64/kernel/vmlinux.lds.S
+++ b/arch/sparc64/kernel/vmlinux.lds.S
@@ -16,6 +16,7 @@ SECTIONS
   {
     *(.text)
     SCHED_TEXT
+    LOCK_TEXT
     *(.gnu.warning)
   } =0
   _etext = .;
@@ -52,9 +53,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : {
 	*(.initcall1.init) 
diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile
index 2da5af9a1..7dd001f52 100644
--- a/arch/sparc64/lib/Makefile
+++ b/arch/sparc64/lib/Makefile
@@ -7,11 +7,12 @@ EXTRA_CFLAGS := -Werror
 
 lib-y := PeeCeeI.o copy_page.o clear_page.o strlen.o strncmp.o \
 	 memscan.o strncpy_from_user.o strlen_user.o memcmp.o checksum.o \
-	 VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o \
-	 VIScsumcopyusr.o VISsave.o atomic.o rwlock.o bitops.o \
-	 U3memcpy.o U3copy_from_user.o U3copy_to_user.o \
-	 U3copy_in_user.o mcount.o ipcsum.o rwsem.o xor.o splock.o \
-	 find_bit.o
+	 VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o \
+	 VIScsumcopyusr.o VISsave.o atomic.o bitops.o \
+	 U1memcpy.o U1copy_from_user.o U1copy_to_user.o \
+	 U3memcpy.o U3copy_from_user.o U3copy_to_user.o U3patch.o \
+	 copy_in_user.o user_fixup.o memmove.o \
+	 mcount.o ipcsum.o rwsem.o xor.o find_bit.o delay.o iomap.o
 
 lib-$(CONFIG_DEBUG_SPINLOCK) += debuglocks.o
 lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
diff --git a/arch/sparc64/lib/PeeCeeI.c b/arch/sparc64/lib/PeeCeeI.c
index b64aee993..3008d536e 100644
--- a/arch/sparc64/lib/PeeCeeI.c
+++ b/arch/sparc64/lib/PeeCeeI.c
@@ -7,7 +7,7 @@
 #include <asm/io.h>
 #include <asm/byteorder.h>
 
-void outsb(unsigned long addr, const void *src, unsigned long count)
+void outsb(void __iomem *addr, const void *src, unsigned long count)
 {
 	const u8 *p = src;
 
@@ -15,7 +15,7 @@ void outsb(unsigned long addr, const void *src, unsigned long count)
 		outb(*p++, addr);
 }
 
-void outsw(unsigned long addr, const void *src, unsigned long count)
+void outsw(void __iomem *addr, const void *src, unsigned long count)
 {
 	if(count) {
 		u16 *ps = (u16 *)src;
@@ -44,7 +44,7 @@ void outsw(unsigned long addr, const void *src, unsigned long count)
 	}
 }
 
-void outsl(unsigned long addr, const void *src, unsigned long count)
+void outsl(void __iomem *addr, const void *src, unsigned long count)
 {
 	if(count) {
 		if((((u64)src) & 0x3) == 0) {
@@ -119,7 +119,7 @@ void outsl(unsigned long addr, const void *src, unsigned long count)
 	}
 }
 
-void insb(unsigned long addr, void *dst, unsigned long count)
+void insb(void __iomem *addr, void *dst, unsigned long count)
 {
 	if(count) {
 		u32 *pi;
@@ -144,7 +144,7 @@ void insb(unsigned long addr, void *dst, unsigned long count)
 	}
 }
 
-void insw(unsigned long addr, void *dst, unsigned long count)
+void insw(void __iomem *addr, void *dst, unsigned long count)
 {
 	if(count) {
 		u16 *ps = dst;
@@ -169,7 +169,7 @@ void insw(unsigned long addr, void *dst, unsigned long count)
 	}
 }
 
-void insl(unsigned long addr, void *dst, unsigned long count)
+void insl(void __iomem *addr, void *dst, unsigned long count)
 {
 	if(count) {
 		if((((unsigned long)dst) & 0x3) == 0) {
diff --git a/arch/sparc64/lib/U3copy_from_user.S b/arch/sparc64/lib/U3copy_from_user.S
index 46b446b14..df600b667 100644
--- a/arch/sparc64/lib/U3copy_from_user.S
+++ b/arch/sparc64/lib/U3copy_from_user.S
@@ -3,410 +3,20 @@
  * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
  */
 
-#include <asm/visasm.h>
-#include <asm/asi.h>
-#include <asm/dcu.h>
-#include <asm/spitfire.h>
-
-#define XCC xcc
-
-#define EXNV_RAW(x,y,a,b)		\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	ba U3cfu_fixup;			\
-	 a, b, %o1;			\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXNV(x,y,a,b)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	add %o1, %o3, %o0;		\
-	ba U3cfu_fixup;			\
-	 a, b, %o1;			\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXNV4(x,y,a,b)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	add %o1, %o3, %o0;		\
-	a, b, %o1;			\
-	ba U3cfu_fixup;			\
-	 add %o1, 4, %o1;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXNV8(x,y,a,b)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	add %o1, %o3, %o0;		\
-	a, b, %o1;			\
-	ba U3cfu_fixup;			\
-	 add %o1, 8, %o1;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EX(x,y,a,b)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	ba U3cfu_fixup;			\
-	 a, b, %o1;			\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EX2(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	and %o2, (0x40 - 1), %o1;	\
-	add %o1, %o4, %o1;		\
-	ba U3cfu_fixup;			\
-	 add %o1, 0x1c0, %o1;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EX3(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	and %o2, (0x40 - 1), %o1;	\
-	sll %g3, 6, %g3;		\
-	add %o1, 0x80, %o1;		\
-	ba U3cfu_fixup;			\
-	 add %o1, %g3, %o1;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EX4(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	and %o2, (0x40 - 1), %o1;	\
-	add %o1, 0x40, %o1;		\
-	ba U3cfu_fixup;			\
-	 add %o1, %g3, %o1;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-
-	.register	%g2,#scratch
-	.register	%g3,#scratch
-
-	/* Special/non-trivial issues of this code:
-	 *
-	 * 1) %o5 is preserved from VISEntryHalf to VISExitHalf
-	 * 2) Only low 32 FPU registers are used so that only the
-	 *    lower half of the FPU register set is dirtied by this
-	 *    code.  This is especially important in the kernel.
-	 * 3) This code never prefetches cachelines past the end
-	 *    of the source buffer.
-	 */
-
-	.text
-	.align	32
-
-	/* The cheetah's flexible spine, oversized liver, enlarged heart,
-	 * slender muscular body, and claws make it the swiftest hunter
-	 * in Africa and the fastest animal on land.  Can reach speeds
-	 * of up to 2.4GB per second.
-	 */
-
-	.globl	U3copy_from_user
-U3copy_from_user:	/* %o0=dst, %o1=src, %o2=len */
-	cmp		%o2, 0
-	be,pn		%XCC, 85f
-	 or		%o0, %o1, %o3
-	cmp		%o2, 16
-	bleu,a,pn	%XCC, 80f
-	 or		%o3, %o2, %o3
-
-	cmp		%o2, 256
-	blu,pt		%XCC, 70f
-	 andcc		%o3, 0x7, %g0
-
-	ba,pt		%xcc, 1f
-	 andcc		%o0, 0x3f, %g2
-
-	/* Here len >= 256 and condition codes reflect execution
-	 * of "andcc %o0, 0x7, %g2", done by caller.
-	 */
-	.align		64
-1:
-	/* Is 'dst' already aligned on an 64-byte boundary? */
-	be,pt		%XCC, 2f
-
-	/* Compute abs((dst & 0x3f) - 0x40) into %g2.  This is the number
-	 * of bytes to copy to make 'dst' 64-byte aligned.  We pre-
-	 * subtract this from 'len'.
-	 */
-	 sub		%g2, 0x40, %g2
-	sub		%g0, %g2, %g2
-	sub		%o2, %g2, %o2
-
-	/* Copy %g2 bytes from src to dst, one byte at a time. */
-1:	EXNV_RAW(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)
-	add		%o1, 0x1, %o1
-	add		%o0, 0x1, %o0
-	subcc		%g2, 0x1, %g2
-
-	bg,pt		%XCC, 1b
-	 stb		%o3, [%o0 + -1]
-
-2:	VISEntryHalf
-	and		%o1, 0x7, %g1
-	ba,pt		%xcc, 1f
-	 alignaddr	%o1, %g0, %o1
-
-	.align		64
-1:
-	membar		#StoreLoad | #StoreStore | #LoadStore
-	prefetcha	[%o1 + 0x000] %asi, #one_read
-	prefetcha	[%o1 + 0x040] %asi, #one_read
-	andn		%o2, (0x40 - 1), %o4
-	prefetcha	[%o1 + 0x080] %asi, #one_read
-	prefetcha	[%o1 + 0x0c0] %asi, #one_read
-	EX(ldda [%o1 + 0x000] %asi, %f0, add %o2, %g0)
-	prefetcha	[%o1 + 0x100] %asi, #one_read
-	EX(ldda [%o1 + 0x008] %asi, %f2, add %o2, %g0)
-	prefetcha	[%o1 + 0x140] %asi, #one_read
-	EX(ldda [%o1 + 0x010] %asi, %f4, add %o2, %g0)
-	prefetcha	[%o1 + 0x180] %asi, #one_read
-	faligndata	%f0, %f2, %f16
-	EX(ldda [%o1 + 0x018] %asi, %f6, add %o2, %g0)
-	faligndata	%f2, %f4, %f18
-	EX(ldda [%o1 + 0x020] %asi, %f8, add %o2, %g0)
-	faligndata	%f4, %f6, %f20
-	EX(ldda [%o1 + 0x028] %asi, %f10, add %o2, %g0)
-	faligndata	%f6, %f8, %f22
-
-	EX(ldda [%o1 + 0x030] %asi, %f12, add %o2, %g0)
-	faligndata	%f8, %f10, %f24
-	EX(ldda [%o1 + 0x038] %asi, %f14, add %o2, %g0)
-	faligndata	%f10, %f12, %f26
-	EX(ldda [%o1 + 0x040] %asi, %f0, add %o2, %g0)
-
-	sub		%o4, 0x80, %o4
-	add		%o1, 0x40, %o1
-	ba,pt		%xcc, 1f
-	 srl		%o4, 6, %o3
-
-	.align		64
-1:
-	EX3(ldda [%o1 + 0x008] %asi, %f2)
-	faligndata	%f12, %f14, %f28
-	EX3(ldda [%o1 + 0x010] %asi, %f4)
-	faligndata	%f14, %f0, %f30
-	stda		%f16, [%o0] ASI_BLK_P
-	EX3(ldda [%o1 + 0x018] %asi, %f6)
-	faligndata	%f0, %f2, %f16
-
-	EX3(ldda [%o1 + 0x020] %asi, %f8)
-	faligndata	%f2, %f4, %f18
-	EX3(ldda [%o1 + 0x028] %asi, %f10)
-	faligndata	%f4, %f6, %f20
-	EX3(ldda [%o1 + 0x030] %asi, %f12)
-	faligndata	%f6, %f8, %f22
-	EX3(ldda [%o1 + 0x038] %asi, %f14)
-	faligndata	%f8, %f10, %f24
-
-	EX3(ldda [%o1 + 0x040] %asi, %f0)
-	prefetcha	[%o1 + 0x180] %asi, #one_read
-	faligndata	%f10, %f12, %f26
-	subcc		%o3, 0x01, %o3
-	add		%o1, 0x40, %o1
-	bg,pt		%XCC, 1b
-	 add		%o0, 0x40, %o0
-
-	/* Finally we copy the last full 64-byte block. */
-	EX3(ldda [%o1 + 0x008] %asi, %f2)
-	faligndata	%f12, %f14, %f28
-	EX3(ldda [%o1 + 0x010] %asi, %f4)
-	faligndata	%f14, %f0, %f30
-	stda		%f16, [%o0] ASI_BLK_P
-	EX3(ldda [%o1 + 0x018] %asi, %f6)
-	faligndata	%f0, %f2, %f16
-	EX3(ldda [%o1 + 0x020] %asi, %f8)
-	faligndata	%f2, %f4, %f18
-	EX3(ldda [%o1 + 0x028] %asi, %f10)
-	faligndata	%f4, %f6, %f20
-	EX3(ldda [%o1 + 0x030] %asi, %f12)
-	faligndata	%f6, %f8, %f22
-	EX3(ldda [%o1 + 0x038] %asi, %f14)
-	faligndata	%f8, %f10, %f24
-	cmp		%g1, 0
-	be,pt		%XCC, 1f
-	 add		%o0, 0x40, %o0
-	EX4(ldda [%o1 + 0x040] %asi, %f0)
-1:	faligndata	%f10, %f12, %f26
-	faligndata	%f12, %f14, %f28
-	faligndata	%f14, %f0, %f30
-	stda		%f16, [%o0] ASI_BLK_P
-	add		%o0, 0x40, %o0
-	add		%o1, 0x40, %o1
-
-	membar		#Sync
-
-	/* Now we copy the (len modulo 64) bytes at the end.
-	 * Note how we borrow the %f0 loaded above.
-	 *
-	 * Also notice how this code is careful not to perform a
-	 * load past the end of the src buffer.
-	 */
-	and		%o2, 0x3f, %o2
-	andcc		%o2, 0x38, %g2
-	be,pn		%XCC, 10f
-	 subcc		%g2, 0x8, %g2
-	be,pn		%XCC, 10f
-	 cmp		%g1, 0
-
-	be,a,pt		%XCC, 1f
-	 EX(ldda [%o1 + 0x00] %asi, %f0, add %o2, %g0)
-
-1:	EX(ldda [%o1 + 0x08] %asi, %f2, add %o2, %g0)
-	add		%o1, 0x8, %o1
-	sub		%o2, 0x8, %o2
-	subcc		%g2, 0x8, %g2
-	faligndata	%f0, %f2, %f8
-	std		%f8, [%o0 + 0x00]
-	be,pn		%XCC, 10f
-	 add		%o0, 0x8, %o0
-	EX(ldda [%o1 + 0x08] %asi, %f0, add %o2, %g0)
-	add		%o1, 0x8, %o1
-	sub		%o2, 0x8, %o2
-	subcc		%g2, 0x8, %g2
-	faligndata	%f2, %f0, %f8
-	std		%f8, [%o0 + 0x00]
-	bne,pn		%XCC, 1b
-	 add		%o0, 0x8, %o0
-
-	/* If anything is left, we copy it one byte at a time.
-	 * Note that %g1 is (src & 0x3) saved above before the
-	 * alignaddr was performed.
-	 */
-10:
-	cmp		%o2, 0
-	add		%o1, %g1, %o1
-	VISExitHalf
-	be,pn		%XCC, 85f
-	 sub		%o0, %o1, %o3
-
-	andcc		%g1, 0x7, %g0
-	bne,pn		%icc, 90f
-	 andcc		%o2, 0x8, %g0
-	be,pt		%icc, 1f
-	 nop
-	EXNV(ldxa [%o1] %asi, %o5, add %o2, %g0)
-	stx		%o5, [%o1 + %o3]
-	add		%o1, 0x8, %o1
-
-1:	andcc		%o2, 0x4, %g0
-	be,pt		%icc, 1f
-	 nop
-	EXNV(lduwa [%o1] %asi, %o5, and %o2, 0x7)
-	stw		%o5, [%o1 + %o3]
-	add		%o1, 0x4, %o1
-
-1:	andcc		%o2, 0x2, %g0
-	be,pt		%icc, 1f
-	 nop
-	EXNV(lduha [%o1] %asi, %o5, and %o2, 0x3)
-	sth		%o5, [%o1 + %o3]
-	add		%o1, 0x2, %o1
-
-1:	andcc		%o2, 0x1, %g0
-	be,pt		%icc, 85f
-	 nop
-	EXNV(lduba [%o1] %asi, %o5, and %o2, 0x1)
-	ba,pt		%xcc, 85f
-	 stb		%o5, [%o1 + %o3]
-
-70: /* 16 < len <= 64 */
-	bne,pn		%XCC, 90f
-	 sub		%o0, %o1, %o3
-
-	andn		%o2, 0x7, %o4
-	and		%o2, 0x7, %o2
-1:	subcc		%o4, 0x8, %o4
-	EXNV8(ldxa [%o1] %asi, %o5, add %o2, %o4)
-	stx		%o5, [%o1 + %o3]
-	bgu,pt		%XCC, 1b
-	 add		%o1, 0x8, %o1
-	andcc		%o2, 0x4, %g0
-	be,pt		%XCC, 1f
-	 nop
-	sub		%o2, 0x4, %o2
-	EXNV4(lduwa [%o1] %asi, %o5, add %o2, %g0)
-	stw		%o5, [%o1 + %o3]
-	add		%o1, 0x4, %o1
-1:	cmp		%o2, 0
-	be,pt		%XCC, 85f
-	 nop
-	ba,pt		%xcc, 90f
-	 nop
-
-80: /* 0 < len <= 16 */
-	andcc		%o3, 0x3, %g0
-	bne,pn		%XCC, 90f
-	 sub		%o0, %o1, %o3
-
-1:
-	subcc		%o2, 4, %o2
-	EXNV(lduwa [%o1] %asi, %g1, add %o2, %g0)
-	stw		%g1, [%o1 + %o3]
-	bgu,pt		%XCC, 1b
-	 add		%o1, 4, %o1
-
-85:	retl
-	 clr		%o0
-
-	.align	32
-90:
-	subcc		%o2, 1, %o2
-	EXNV(lduba [%o1] %asi, %g1, add %o2, %g0)
-	stb		%g1, [%o1 + %o3]
-	bgu,pt		%XCC, 90b
-	 add		%o1, 1, %o1
-	retl
-	 clr		%o0
-
-U3cfu_fixup:
-	/* Since this is copy_from_user(), zero out the rest of the
-	 * kernel buffer.
-	 */
-	cmp		%o1, 0
-	ble,pn		%icc, 2f
-	 mov		%o1, %g2
-
-1:	subcc		%g2, 1, %g2
-	stb		%g0, [%o0]
-	bne,pt		%icc, 1b
-	 add		%o0, 1, %o0
-
-2:	retl
-	 mov		%o1, %o0
+#define EX_LD(x)		\
+98:	x;			\
+	.section .fixup;	\
+	.align 4;		\
+99:	retl;			\
+	 mov	1, %o0;		\
+	.section __ex_table;	\
+	.align 4;		\
+	.word 98b, 99b;		\
+	.text;			\
+	.align 4;
+
+#define FUNC_NAME		U3copy_from_user
+#define LOAD(type,addr,dest)	type##a [addr] %asi, dest
+#define EX_RETVAL(x)		0
+
+#include "U3memcpy.S"
diff --git a/arch/sparc64/lib/U3copy_to_user.S b/arch/sparc64/lib/U3copy_to_user.S
index 715227156..f337f22ed 100644
--- a/arch/sparc64/lib/U3copy_to_user.S
+++ b/arch/sparc64/lib/U3copy_to_user.S
@@ -1,415 +1,33 @@
-/* U3copy_to_user.S: UltraSparc-III optimized memcpy.
+/* U3copy_to_user.S: UltraSparc-III optimized copy to userspace.
  *
  * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
  */
 
-#include <asm/visasm.h>
-#include <asm/asi.h>
-#include <asm/dcu.h>
-#include <asm/spitfire.h>
-
-#define XCC xcc
-
-#define EXNV(x,y,a,b)	\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	retl;				\
-	 a, b, %o0;			\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXNV2(x,y,a,b)	\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	a, b, %o0;			\
-	retl;				\
-	 add %o0, 1, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXNV3(x,y,a,b)	\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	a, b, %o0;			\
-	retl;				\
-	 add %o0, 4, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXNV4(x,y,a,b)	\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	a, b, %o0;			\
-	retl;				\
-	 add %o0, 8, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EX(x,y,a,b)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	retl;				\
-	 a, b, %o0;			\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
+#define EX_ST(x)		\
+98:	x;			\
+	.section .fixup;	\
+	.align 4;		\
+99:	retl;			\
+	 mov	1, %o0;		\
+	.section __ex_table;	\
+	.align 4;		\
+	.word 98b, 99b;		\
+	.text;			\
 	.align 4;
-#define EXBLK1(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	add %o4, 0x1c0, %o1;		\
-	and %o2, (0x40 - 1), %o2;	\
-	retl;				\
-	 add %o1, %o2, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXBLK2(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	sll %o3, 6, %o3;		\
-	and %o2, (0x40 - 1), %o2;	\
-	add %o3, 0x80, %o1;		\
-	retl;				\
-	 add %o1, %o2, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXBLK3(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	and %o2, (0x40 - 1), %o2;	\
-	retl;				\
-	 add %o2, 0x80, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-#define EXBLK4(x,y)			\
-98:	x,y;				\
-	.section .fixup;		\
-	.align 4;			\
-99:	VISExitHalf;			\
-	and %o2, (0x40 - 1), %o2;	\
-	retl;				\
-	 add %o2, 0x40, %o0;		\
-	.section __ex_table;		\
-	.align 4;			\
-	.word 98b, 99b;			\
-	.text;				\
-	.align 4;
-
-	.register	%g2,#scratch
-	.register	%g3,#scratch
-
-	/* Special/non-trivial issues of this code:
-	 *
-	 * 1) %o5 is preserved from VISEntryHalf to VISExitHalf
-	 * 2) Only low 32 FPU registers are used so that only the
-	 *    lower half of the FPU register set is dirtied by this
-	 *    code.  This is especially important in the kernel.
-	 * 3) This code never prefetches cachelines past the end
-	 *    of the source buffer.
-	 */
-
-	.text
-	.align	32
 
-	/* The cheetah's flexible spine, oversized liver, enlarged heart,
-	 * slender muscular body, and claws make it the swiftest hunter
-	 * in Africa and the fastest animal on land.  Can reach speeds
-	 * of up to 2.4GB per second.
-	 */
+#define FUNC_NAME		U3copy_to_user
+#define STORE(type,src,addr)	type##a src, [addr] ASI_AIUS
+#define STORE_BLK(src,addr)	stda src, [addr] ASI_BLK_AIUS
+#define EX_RETVAL(x)		0
 
-	.globl	U3copy_to_user
-U3copy_to_user:	/* %o0=dst, %o1=src, %o2=len */
 	/* Writing to %asi is _expensive_ so we hardcode it.
 	 * Reading %asi to check for KERNEL_DS is comparatively
 	 * cheap.
 	 */
-	rd		%asi, %g1
-	cmp		%g1, ASI_AIUS
-	bne,pn		%icc, U3memcpy_user_stub
-	 nop
-
-	cmp		%o2, 0
-	be,pn		%XCC, 85f
-	 or		%o0, %o1, %o3
-	cmp		%o2, 16
-	bleu,a,pn	%XCC, 80f
-	 or		%o3, %o2, %o3
-
-	cmp		%o2, 256
-	blu,pt		%XCC, 70f
-	 andcc		%o3, 0x7, %g0
-
-	ba,pt		%xcc, 1f
-	 andcc		%o0, 0x3f, %g2
-
-	/* Here len >= 256 and condition codes reflect execution
-	 * of "andcc %o0, 0x7, %g2", done by caller.
-	 */
-	.align		64
-1:
-	/* Is 'dst' already aligned on an 64-byte boundary? */
-	be,pt		%XCC, 2f
-
-	/* Compute abs((dst & 0x3f) - 0x40) into %g2.  This is the number
-	 * of bytes to copy to make 'dst' 64-byte aligned.  We pre-
-	 * subtract this from 'len'.
-	 */
-	 sub		%g2, 0x40, %g2
-	sub		%g0, %g2, %g2
-	sub		%o2, %g2, %o2
-
-	/* Copy %g2 bytes from src to dst, one byte at a time. */
-1:	ldub		[%o1 + 0x00], %o3
-	add		%o1, 0x1, %o1
-	add		%o0, 0x1, %o0
-	subcc		%g2, 0x1, %g2
-
-	bg,pt		%XCC, 1b
-	 EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2)
-
-2:	VISEntryHalf
-	and		%o1, 0x7, %g1
-	ba,pt		%xcc, 1f
-	 alignaddr	%o1, %g0, %o1
-
-	.align		64
-1:
-	membar		#StoreLoad | #StoreStore | #LoadStore
-	prefetch	[%o1 + 0x000], #one_read
-	prefetch	[%o1 + 0x040], #one_read
-	andn		%o2, (0x40 - 1), %o4
-	prefetch	[%o1 + 0x080], #one_read
-	prefetch	[%o1 + 0x0c0], #one_read
-	ldd		[%o1 + 0x000], %f0
-	prefetch	[%o1 + 0x100], #one_read
-	ldd		[%o1 + 0x008], %f2
-	prefetch	[%o1 + 0x140], #one_read
-	ldd		[%o1 + 0x010], %f4
-	prefetch	[%o1 + 0x180], #one_read
-	faligndata	%f0, %f2, %f16
-	ldd		[%o1 + 0x018], %f6
-	faligndata	%f2, %f4, %f18
-	ldd		[%o1 + 0x020], %f8
-	faligndata	%f4, %f6, %f20
-	ldd		[%o1 + 0x028], %f10
-	faligndata	%f6, %f8, %f22
-
-	ldd		[%o1 + 0x030], %f12
-	faligndata	%f8, %f10, %f24
-	ldd		[%o1 + 0x038], %f14
-	faligndata	%f10, %f12, %f26
-	ldd		[%o1 + 0x040], %f0
-
-	sub		%o4, 0x80, %o4
-	add		%o1, 0x40, %o1
-	ba,pt		%xcc, 1f
-	 srl		%o4, 6, %o3
-
-	.align		64
-1:
-	ldd		[%o1 + 0x008], %f2
-	faligndata	%f12, %f14, %f28
-	ldd		[%o1 + 0x010], %f4
-	faligndata	%f14, %f0, %f30
-	EXBLK2(stda %f16, [%o0] ASI_BLK_AIUS)
-	ldd		[%o1 + 0x018], %f6
-	faligndata	%f0, %f2, %f16
-
-	ldd		[%o1 + 0x020], %f8
-	faligndata	%f2, %f4, %f18
-	ldd		[%o1 + 0x028], %f10
-	faligndata	%f4, %f6, %f20
-	ldd		[%o1 + 0x030], %f12
-	faligndata	%f6, %f8, %f22
-	ldd		[%o1 + 0x038], %f14
-	faligndata	%f8, %f10, %f24
-
-	ldd		[%o1 + 0x040], %f0
-	prefetch	[%o1 + 0x180], #one_read
-	faligndata	%f10, %f12, %f26
-	subcc		%o3, 0x01, %o3
-	add		%o1, 0x40, %o1
-	bg,pt		%XCC, 1b
-	 add		%o0, 0x40, %o0
-
-	/* Finally we copy the last full 64-byte block. */
-	ldd		[%o1 + 0x008], %f2
-	faligndata	%f12, %f14, %f28
-	ldd		[%o1 + 0x010], %f4
-	faligndata	%f14, %f0, %f30
-	EXBLK3(stda %f16, [%o0] ASI_BLK_AIUS)
-	ldd		[%o1 + 0x018], %f6
-	faligndata	%f0, %f2, %f16
-	ldd		[%o1 + 0x020], %f8
-	faligndata	%f2, %f4, %f18
-	ldd		[%o1 + 0x028], %f10
-	faligndata	%f4, %f6, %f20
-	ldd		[%o1 + 0x030], %f12
-	faligndata	%f6, %f8, %f22
-	ldd		[%o1 + 0x038], %f14
-	faligndata	%f8, %f10, %f24
-	cmp		%g1, 0
-	be,pt		%XCC, 1f
-	 add		%o0, 0x40, %o0
-	ldd		[%o1 + 0x040], %f0
-1:	faligndata	%f10, %f12, %f26
-	faligndata	%f12, %f14, %f28
-	faligndata	%f14, %f0, %f30
-	EXBLK4(stda %f16, [%o0] ASI_BLK_AIUS)
-	add		%o0, 0x40, %o0
-	add		%o1, 0x40, %o1
-
-	membar		#Sync
-
-	/* Now we copy the (len modulo 64) bytes at the end.
-	 * Note how we borrow the %f0 loaded above.
-	 *
-	 * Also notice how this code is careful not to perform a
-	 * load past the end of the src buffer.
-	 */
-	and		%o2, 0x3f, %o2
-	andcc		%o2, 0x38, %g2
-	be,pn		%XCC, 2f
-	 subcc		%g2, 0x8, %g2
-	be,pn		%XCC, 2f
-	 cmp		%g1, 0
-
-	be,a,pt		%XCC, 1f
-	 ldd		[%o1 + 0x00], %f0
-
-1:	ldd		[%o1 + 0x08], %f2
-	add		%o1, 0x8, %o1
-	sub		%o2, 0x8, %o2
-	subcc		%g2, 0x8, %g2
-	faligndata	%f0, %f2, %f8
-	EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8)
-	be,pn		%XCC, 2f
-	 add		%o0, 0x8, %o0
-	ldd		[%o1 + 0x08], %f0
-	add		%o1, 0x8, %o1
-	sub		%o2, 0x8, %o2
-	subcc		%g2, 0x8, %g2
-	faligndata	%f2, %f0, %f8
-	EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8)
-	bne,pn		%XCC, 1b
-	 add		%o0, 0x8, %o0
-
-	/* If anything is left, we copy it one byte at a time.
-	 * Note that %g1 is (src & 0x3) saved above before the
-	 * alignaddr was performed.
-	 */
-2:
-	cmp		%o2, 0
-	add		%o1, %g1, %o1
-	VISExitHalf
-	be,pn		%XCC, 85f
-	 sub		%o0, %o1, %o3
-
-	andcc		%g1, 0x7, %g0
-	bne,pn		%icc, 90f
-	 andcc		%o2, 0x8, %g0
-	be,pt		%icc, 1f
-	 nop
-	ldx		[%o1], %o5
-	EXNV(stxa %o5, [%o1 + %o3] ASI_AIUS, add %o2, %g0)
-	add		%o1, 0x8, %o1
-
-1:	andcc		%o2, 0x4, %g0
-	be,pt		%icc, 1f
-	 nop
-	lduw		[%o1], %o5
-	EXNV(stwa %o5, [%o1 + %o3] ASI_AIUS, and %o2, 0x7)
-	add		%o1, 0x4, %o1
-
-1:	andcc		%o2, 0x2, %g0
-	be,pt		%icc, 1f
-	 nop
-	lduh		[%o1], %o5
-	EXNV(stha %o5, [%o1 + %o3] ASI_AIUS, and %o2, 0x3)
-	add		%o1, 0x2, %o1
-
-1:	andcc		%o2, 0x1, %g0
-	be,pt		%icc, 85f
-	 nop
-	ldub		[%o1], %o5
-	ba,pt		%xcc, 85f
-	 EXNV(stba %o5, [%o1 + %o3] ASI_AIUS, and %o2, 0x1)
-
-70: /* 16 < len <= 64 */
-	bne,pn		%XCC, 90f
-	 sub		%o0, %o1, %o3
-
-	andn		%o2, 0x7, %o4
-	and		%o2, 0x7, %o2
-1:	subcc		%o4, 0x8, %o4
-	ldx		[%o1], %o5
-	EXNV4(stxa %o5, [%o1 + %o3] ASI_AIUS, add %o2, %o4)
-	bgu,pt		%XCC, 1b
-	 add		%o1, 0x8, %o1
-	andcc		%o2, 0x4, %g0
-	be,pt		%XCC, 1f
-	 nop
-	sub		%o2, 0x4, %o2
-	lduw		[%o1], %o5
-	EXNV3(stwa %o5, [%o1 + %o3] ASI_AIUS, add %o2, %g0)
-	add		%o1, 0x4, %o1
-1:	cmp		%o2, 0
-	be,pt		%XCC, 85f
-	 nop
-	ba,pt		%xcc, 90f
-	 nop
-
-80: /* 0 < len <= 16 */
-	andcc		%o3, 0x3, %g0
-	bne,pn		%XCC, 90f
-	 sub		%o0, %o1, %o3
-
-1:
-	subcc		%o2, 4, %o2
-	lduw		[%o1], %g1
-	EXNV3(stwa %g1, [%o1 + %o3] ASI_AIUS, add %o2, %g0)
-	bgu,pt		%XCC, 1b
-	 add		%o1, 4, %o1
-
-85:	retl
-	 clr		%o0
+#define PREAMBLE					\
+	rd		%asi, %g1;			\
+	cmp		%g1, ASI_AIUS;			\
+	bne,pn		%icc, memcpy_user_stub;		\
+	 nop;						\
 
-	.align	32
-90:
-	subcc		%o2, 1, %o2
-	ldub		[%o1], %g1
-	EXNV2(stba %g1, [%o1 + %o3] ASI_AIUS, add %o2, %g0)
-	bgu,pt		%XCC, 90b
-	 add		%o1, 1, %o1
-	retl
-	 clr		%o0
+#include "U3memcpy.S"
diff --git a/arch/sparc64/lib/U3memcpy.S b/arch/sparc64/lib/U3memcpy.S
index e9982deef..5cde95446 100644
--- a/arch/sparc64/lib/U3memcpy.S
+++ b/arch/sparc64/lib/U3memcpy.S
@@ -6,14 +6,50 @@
 #ifdef __KERNEL__
 #include <asm/visasm.h>
 #include <asm/asi.h>
-#include <asm/dcu.h>
-#include <asm/spitfire.h>
 #else
 #define ASI_BLK_P 0xf0
 #define FPRS_FEF  0x04
+#ifdef MEMCPY_DEBUG
+#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs; \
+		     clr %g1; clr %g2; clr %g3; subcc %g0, %g0, %g0;
+#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
+#else
 #define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs
 #define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
 #endif
+#endif
+
+#ifndef EX_LD
+#define EX_LD(x)	x
+#endif
+
+#ifndef EX_ST
+#define EX_ST(x)	x
+#endif
+
+#ifndef EX_RETVAL
+#define EX_RETVAL(x)	x
+#endif
+
+#ifndef LOAD
+#define LOAD(type,addr,dest)	type [addr], dest
+#endif
+
+#ifndef STORE
+#define STORE(type,src,addr)	type src, [addr]
+#endif
+
+#ifndef STORE_BLK
+#define STORE_BLK(src,addr)	stda src, [addr] ASI_BLK_P
+#endif
+
+#ifndef FUNC_NAME
+#define FUNC_NAME	U3memcpy
+#endif
+
+#ifndef PREAMBLE
+#define PREAMBLE
+#endif
 
 #ifndef XCC
 #define XCC xcc
@@ -33,7 +69,7 @@
 	 */
 
 	.text
-	.align	32
+	.align		64
 
 	/* The cheetah's flexible spine, oversized liver, enlarged heart,
 	 * slender muscular body, and claws make it the swiftest hunter
@@ -41,137 +77,158 @@
 	 * of up to 2.4GB per second.
 	 */
 
-	.globl	U3memcpy
-U3memcpy:	/* %o0=dst, %o1=src, %o2=len */
+	.globl	FUNC_NAME
+	.type	FUNC_NAME,#function
+FUNC_NAME:	/* %o0=dst, %o1=src, %o2=len */
+	PREAMBLE
 	mov		%o0, %g5
 	cmp		%o2, 0
 	be,pn		%XCC, 85f
 	 or		%o0, %o1, %o3
 	cmp		%o2, 16
-	bleu,a,pn	%XCC, 70f
+	blu,a,pn	%XCC, 80f
 	 or		%o3, %o2, %o3
 
-	cmp		%o2, 256
-	blu,pt		%XCC, 80f
+	cmp		%o2, (3 * 64)
+	blu,pt		%XCC, 70f
 	 andcc		%o3, 0x7, %g0
 
-	ba,pt		%xcc, 1f
-	 andcc		%o0, 0x3f, %g2
-
-	/* Here len >= 256 and condition codes reflect execution
-	 * of "andcc %o0, 0x7, %g2", done by caller.
+	/* Clobbers o5/g1/g2/g3/g7/icc/xcc.  We must preserve
+	 * o5 from here until we hit VISExitHalf.
 	 */
-	.align		64
-1:
+	VISEntryHalf
+
 	/* Is 'dst' already aligned on an 64-byte boundary? */
+	andcc		%o0, 0x3f, %g2
 	be,pt		%XCC, 2f
 
 	/* Compute abs((dst & 0x3f) - 0x40) into %g2.  This is the number
 	 * of bytes to copy to make 'dst' 64-byte aligned.  We pre-
 	 * subtract this from 'len'.
 	 */
-	 sub		%g2, 0x40, %g2
+	 sub		%o0, %o1, %o4
+	sub		%g2, 0x40, %g2
 	sub		%g0, %g2, %g2
 	sub		%o2, %g2, %o2
+	andcc		%g2, 0x7, %g1
+	be,pt		%icc, 2f
+	 and		%g2, 0x38, %g2
 
-	/* Copy %g2 bytes from src to dst, one byte at a time. */
-1:	ldub		[%o1 + 0x00], %o3
-	add		%o1, 0x1, %o1
-	add		%o0, 0x1, %o0
-	subcc		%g2, 0x1, %g2
+1:	subcc		%g1, 0x1, %g1
+	EX_LD(LOAD(ldub, %o1 + 0x00, %o3))
+	EX_ST(STORE(stb, %o3, %o1 + %o4))
+	bgu,pt		%XCC, 1b
+	 add		%o1, 0x1, %o1
 
-	bg,pt		%XCC, 1b
-	 stb		%o3, [%o0 + -1]
+	add		%o1, %o4, %o0
 
-2:	VISEntryHalf
+2:	cmp		%g2, 0x0
 	and		%o1, 0x7, %g1
-	ba,pt		%xcc, 1f
+	be,pt		%icc, 3f
 	 alignaddr	%o1, %g0, %o1
 
-	.align		64
-1:
-	membar		#StoreLoad | #StoreStore | #LoadStore
-	prefetch	[%o1 + 0x000], #one_read
-	prefetch	[%o1 + 0x040], #one_read
+	EX_LD(LOAD(ldd, %o1, %f4))
+1:	EX_LD(LOAD(ldd, %o1 + 0x8, %f6))
+	add		%o1, 0x8, %o1
+	subcc		%g2, 0x8, %g2
+	faligndata	%f4, %f6, %f0
+	EX_ST(STORE(std, %f0, %o0))
+	be,pn		%icc, 3f
+	 add		%o0, 0x8, %o0
+
+	EX_LD(LOAD(ldd, %o1 + 0x8, %f4))
+	add		%o1, 0x8, %o1
+	subcc		%g2, 0x8, %g2
+	faligndata	%f6, %f4, %f2
+	EX_ST(STORE(std, %f2, %o0))
+	bne,pt		%icc, 1b
+	 add		%o0, 0x8, %o0
+
+3:	LOAD(prefetch, %o1 + 0x000, #one_read)
+	LOAD(prefetch, %o1 + 0x040, #one_read)
 	andn		%o2, (0x40 - 1), %o4
-	prefetch	[%o1 + 0x080], #one_read
-	prefetch	[%o1 + 0x0c0], #one_read
-	ldd		[%o1 + 0x000], %f0
-	prefetch	[%o1 + 0x100], #one_read
-	ldd		[%o1 + 0x008], %f2
-	prefetch	[%o1 + 0x140], #one_read
-	ldd		[%o1 + 0x010], %f4
-	prefetch	[%o1 + 0x180], #one_read
+	LOAD(prefetch, %o1 + 0x080, #one_read)
+	LOAD(prefetch, %o1 + 0x0c0, #one_read)
+	LOAD(prefetch, %o1 + 0x100, #one_read)
+	EX_LD(LOAD(ldd, %o1 + 0x000, %f0))
+	LOAD(prefetch, %o1 + 0x140, #one_read)
+	EX_LD(LOAD(ldd, %o1 + 0x008, %f2))
+	LOAD(prefetch, %o1 + 0x180, #one_read)
+	EX_LD(LOAD(ldd, %o1 + 0x010, %f4))
+	LOAD(prefetch, %o1 + 0x1c0, #one_read)
 	faligndata	%f0, %f2, %f16
-	ldd		[%o1 + 0x018], %f6
+	EX_LD(LOAD(ldd, %o1 + 0x018, %f6))
 	faligndata	%f2, %f4, %f18
-	ldd		[%o1 + 0x020], %f8
+	EX_LD(LOAD(ldd, %o1 + 0x020, %f8))
 	faligndata	%f4, %f6, %f20
-	ldd		[%o1 + 0x028], %f10
+	EX_LD(LOAD(ldd, %o1 + 0x028, %f10))
 	faligndata	%f6, %f8, %f22
 
-	ldd		[%o1 + 0x030], %f12
+	EX_LD(LOAD(ldd, %o1 + 0x030, %f12))
 	faligndata	%f8, %f10, %f24
-	ldd		[%o1 + 0x038], %f14
+	EX_LD(LOAD(ldd, %o1 + 0x038, %f14))
 	faligndata	%f10, %f12, %f26
-	ldd		[%o1 + 0x040], %f0
+	EX_LD(LOAD(ldd, %o1 + 0x040, %f0))
 
-	sub		%o4, 0x80, %o4
+	subcc		%o4, 0x80, %o4
 	add		%o1, 0x40, %o1
-	ba,pt		%xcc, 1f
+	bgu,pt		%XCC, 1f
 	 srl		%o4, 6, %o3
+	ba,pt		%xcc, 2f
+	 nop
 
 	.align		64
 1:
-	ldd		[%o1 + 0x008], %f2
+	EX_LD(LOAD(ldd, %o1 + 0x008, %f2))
 	faligndata	%f12, %f14, %f28
-	ldd		[%o1 + 0x010], %f4
+	EX_LD(LOAD(ldd, %o1 + 0x010, %f4))
 	faligndata	%f14, %f0, %f30
-	stda		%f16, [%o0] ASI_BLK_P
-	ldd		[%o1 + 0x018], %f6
+	EX_ST(STORE_BLK(%f16, %o0))
+	EX_LD(LOAD(ldd, %o1 + 0x018, %f6))
 	faligndata	%f0, %f2, %f16
+	add		%o0, 0x40, %o0
 
-	ldd		[%o1 + 0x020], %f8
+	EX_LD(LOAD(ldd, %o1 + 0x020, %f8))
 	faligndata	%f2, %f4, %f18
-	ldd		[%o1 + 0x028], %f10
+	EX_LD(LOAD(ldd, %o1 + 0x028, %f10))
 	faligndata	%f4, %f6, %f20
-	ldd		[%o1 + 0x030], %f12
+	EX_LD(LOAD(ldd, %o1 + 0x030, %f12))
+	subcc		%o3, 0x01, %o3
 	faligndata	%f6, %f8, %f22
-	ldd		[%o1 + 0x038], %f14
-	faligndata	%f8, %f10, %f24
+	EX_LD(LOAD(ldd, %o1 + 0x038, %f14))
 
-	ldd		[%o1 + 0x040], %f0
-	prefetch	[%o1 + 0x180], #one_read
+	faligndata	%f8, %f10, %f24
+	EX_LD(LOAD(ldd, %o1 + 0x040, %f0))
+	LOAD(prefetch, %o1 + 0x1c0, #one_read)
 	faligndata	%f10, %f12, %f26
-	subcc		%o3, 0x01, %o3
-	add		%o1, 0x40, %o1
 	bg,pt		%XCC, 1b
-	 add		%o0, 0x40, %o0
+	 add		%o1, 0x40, %o1
 
 	/* Finally we copy the last full 64-byte block. */
-	ldd		[%o1 + 0x008], %f2
+2:
+	EX_LD(LOAD(ldd, %o1 + 0x008, %f2))
 	faligndata	%f12, %f14, %f28
-	ldd		[%o1 + 0x010], %f4
+	EX_LD(LOAD(ldd, %o1 + 0x010, %f4))
 	faligndata	%f14, %f0, %f30
-	stda		%f16, [%o0] ASI_BLK_P
-	ldd		[%o1 + 0x018], %f6
+	EX_ST(STORE_BLK(%f16, %o0))
+	EX_LD(LOAD(ldd, %o1 + 0x018, %f6))
 	faligndata	%f0, %f2, %f16
-	ldd		[%o1 + 0x020], %f8
+	EX_LD(LOAD(ldd, %o1 + 0x020, %f8))
 	faligndata	%f2, %f4, %f18
-	ldd		[%o1 + 0x028], %f10
+	EX_LD(LOAD(ldd, %o1 + 0x028, %f10))
 	faligndata	%f4, %f6, %f20
-	ldd		[%o1 + 0x030], %f12
+	EX_LD(LOAD(ldd, %o1 + 0x030, %f12))
 	faligndata	%f6, %f8, %f22
-	ldd		[%o1 + 0x038], %f14
+	EX_LD(LOAD(ldd, %o1 + 0x038, %f14))
 	faligndata	%f8, %f10, %f24
 	cmp		%g1, 0
 	be,pt		%XCC, 1f
 	 add		%o0, 0x40, %o0
-	ldd		[%o1 + 0x040], %f0
+	EX_LD(LOAD(ldd, %o1 + 0x040, %f0))
 1:	faligndata	%f10, %f12, %f26
 	faligndata	%f12, %f14, %f28
 	faligndata	%f14, %f0, %f30
-	stda		%f16, [%o0] ASI_BLK_P
+	EX_ST(STORE_BLK(%f16, %o0))
 	add		%o0, 0x40, %o0
 	add		%o1, 0x40, %o1
 	membar		#Sync
@@ -189,23 +246,22 @@ U3memcpy:	/* %o0=dst, %o1=src, %o2=len */
 	be,pn		%XCC, 2f
 	 cmp		%g1, 0
 
+	sub		%o2, %g2, %o2
 	be,a,pt		%XCC, 1f
-	 ldd		[%o1 + 0x00], %f0
+	 EX_LD(LOAD(ldd, %o1 + 0x00, %f0))
 
-1:	ldd		[%o1 + 0x08], %f2
+1:	EX_LD(LOAD(ldd, %o1 + 0x08, %f2))
 	add		%o1, 0x8, %o1
-	sub		%o2, 0x8, %o2
 	subcc		%g2, 0x8, %g2
 	faligndata	%f0, %f2, %f8
-	std		%f8, [%o0 + 0x00]
+	EX_ST(STORE(std, %f8, %o0))
 	be,pn		%XCC, 2f
 	 add		%o0, 0x8, %o0
-	ldd		[%o1 + 0x08], %f0
+	EX_LD(LOAD(ldd, %o1 + 0x08, %f0))
 	add		%o1, 0x8, %o1
-	sub		%o2, 0x8, %o2
 	subcc		%g2, 0x8, %g2
 	faligndata	%f2, %f0, %f8
-	std		%f8, [%o0 + 0x00]
+	EX_ST(STORE(std, %f8, %o0))
 	bne,pn		%XCC, 1b
 	 add		%o0, 0x8, %o0
 
@@ -225,48 +281,60 @@ U3memcpy:	/* %o0=dst, %o1=src, %o2=len */
 	 andcc		%o2, 0x8, %g0
 	be,pt		%icc, 1f
 	 nop
-	ldx		[%o1], %o5
-	stx		%o5, [%o1 + %o3]
+	EX_LD(LOAD(ldx, %o1, %o5))
+	EX_ST(STORE(stx, %o5, %o1 + %o3))
 	add		%o1, 0x8, %o1
 
 1:	andcc		%o2, 0x4, %g0
 	be,pt		%icc, 1f
 	 nop
-	lduw		[%o1], %o5
-	stw		%o5, [%o1 + %o3]
+	EX_LD(LOAD(lduw, %o1, %o5))
+	EX_ST(STORE(stw, %o5, %o1 + %o3))
 	add		%o1, 0x4, %o1
 
 1:	andcc		%o2, 0x2, %g0
 	be,pt		%icc, 1f
 	 nop
-	lduh		[%o1], %o5
-	sth		%o5, [%o1 + %o3]
+	EX_LD(LOAD(lduh, %o1, %o5))
+	EX_ST(STORE(sth, %o5, %o1 + %o3))
 	add		%o1, 0x2, %o1
 
 1:	andcc		%o2, 0x1, %g0
 	be,pt		%icc, 85f
 	 nop
-	ldub		[%o1], %o5
+	EX_LD(LOAD(ldub, %o1, %o5))
 	ba,pt		%xcc, 85f
-	 stb		%o5, [%o1 + %o3]
+	 EX_ST(STORE(stb, %o5, %o1 + %o3))
 
+	.align		64
 70: /* 16 < len <= 64 */
-	bne,pn		%XCC, 90f
+	bne,pn		%XCC, 75f
 	 sub		%o0, %o1, %o3
 
-	andn		%o2, 0x7, %o4
-	and		%o2, 0x7, %o2
-1:	subcc		%o4, 0x8, %o4
-	ldx		[%o1], %o5
-	stx		%o5, [%o1 + %o3]
+72:
+	andn		%o2, 0xf, %o4
+	and		%o2, 0xf, %o2
+1:	subcc		%o4, 0x10, %o4
+	EX_LD(LOAD(ldx, %o1 + 0x00, %o5))
+	EX_LD(LOAD(ldx, %o1 + 0x08, %g1))
+	EX_ST(STORE(stx, %o5, %o1 + %o3))
+	add		%o1, 0x8, %o1
+	EX_ST(STORE(stx, %g1, %o1 + %o3))
 	bgu,pt		%XCC, 1b
 	 add		%o1, 0x8, %o1
-	andcc		%o2, 0x4, %g0
+73:	andcc		%o2, 0x8, %g0
+	be,pt		%XCC, 1f
+	 nop
+	sub		%o2, 0x8, %o2
+	EX_LD(LOAD(ldx, %o1, %o5))
+	EX_ST(STORE(stx, %o5, %o1 + %o3))
+	add		%o1, 0x8, %o1
+1:	andcc		%o2, 0x4, %g0
 	be,pt		%XCC, 1f
 	 nop
 	sub		%o2, 0x4, %o2
-	lduw		[%o1], %o5
-	stw		%o5, [%o1 + %o3]
+	EX_LD(LOAD(lduw, %o1, %o5))
+	EX_ST(STORE(stw, %o5, %o1 + %o3))
 	add		%o1, 0x4, %o1
 1:	cmp		%o2, 0
 	be,pt		%XCC, 85f
@@ -274,6 +342,53 @@ U3memcpy:	/* %o0=dst, %o1=src, %o2=len */
 	ba,pt		%xcc, 90f
 	 nop
 
+75:
+	andcc		%o0, 0x7, %g1
+	sub		%g1, 0x8, %g1
+	be,pn		%icc, 2f
+	 sub		%g0, %g1, %g1
+	sub		%o2, %g1, %o2
+
+1:	subcc		%g1, 1, %g1
+	EX_LD(LOAD(ldub, %o1, %o5))
+	EX_ST(STORE(stb, %o5, %o1 + %o3))
+	bgu,pt		%icc, 1b
+	 add		%o1, 1, %o1
+
+2:	add		%o1, %o3, %o0
+	andcc		%o1, 0x7, %g1
+	bne,pt		%icc, 8f
+	 sll		%g1, 3, %g1
+
+	cmp		%o2, 16
+	bgeu,pt		%icc, 72b
+	 nop
+	ba,a,pt		%xcc, 73b
+
+8:	mov		64, %o3
+	andn		%o1, 0x7, %o1
+	EX_LD(LOAD(ldx, %o1, %g2))
+	sub		%o3, %g1, %o3
+	andn		%o2, 0x7, %o4
+	sllx		%g2, %g1, %g2
+1:	EX_LD(LOAD(ldx, %o1 + 0x8, %g3))
+	subcc		%o4, 0x8, %o4
+	add		%o1, 0x8, %o1
+	srlx		%g3, %o3, %o5
+	or		%o5, %g2, %o5
+	EX_ST(STORE(stx, %o5, %o0))
+	add		%o0, 0x8, %o0
+	bgu,pt		%icc, 1b
+	 sllx		%g3, %g1, %g2
+
+	srl		%g1, 3, %g1
+	andcc		%o2, 0x7, %o2
+	be,pn		%icc, 85f
+	 add		%o1, %g1, %o1
+	ba,pt		%xcc, 90f
+	 sub		%o0, %o1, %o3
+
+	.align		64
 80: /* 0 < len <= 16 */
 	andcc		%o3, 0x3, %g0
 	bne,pn		%XCC, 90f
@@ -281,34 +396,22 @@ U3memcpy:	/* %o0=dst, %o1=src, %o2=len */
 
 1:
 	subcc		%o2, 4, %o2
-	lduw		[%o1], %g1
-	stw		%g1, [%o1 + %o3]
+	EX_LD(LOAD(lduw, %o1, %g1))
+	EX_ST(STORE(stw, %g1, %o1 + %o3))
 	bgu,pt		%XCC, 1b
 	 add		%o1, 4, %o1
 
 85:	retl
-	 mov		%g5, %o0
+	 mov		EX_RETVAL(%g5), %o0
 
-	.align	32
+	.align		32
 90:
 	subcc		%o2, 1, %o2
-	ldub		[%o1], %g1
-	stb		%g1, [%o1 + %o3]
+	EX_LD(LOAD(ldub, %o1, %g1))
+	EX_ST(STORE(stb, %g1, %o1 + %o3))
 	bgu,pt		%XCC, 90b
 	 add		%o1, 1, %o1
 	retl
-	 mov		%g5, %o0
+	 mov		EX_RETVAL(%g5), %o0
 
-	/* Act like copy_{to,in}_user(), ie. return zero instead
-	 * of original destination pointer.  This is invoked when
-	 * copy_{to,in}_user() finds that %asi is kernel space.
-	 */
-	.globl	U3memcpy_user_stub
-U3memcpy_user_stub:
-	save		%sp, -192, %sp
-	mov		%i0, %o0
-	mov		%i1, %o1
-	call		U3memcpy
-	 mov		%i2, %o2
-	ret
-	 restore	%g0, %g0, %o0
+	.size		FUNC_NAME, .-FUNC_NAME
diff --git a/arch/sparc64/lib/atomic.S b/arch/sparc64/lib/atomic.S
index a0d6d8ac3..26463d8a4 100644
--- a/arch/sparc64/lib/atomic.S
+++ b/arch/sparc64/lib/atomic.S
@@ -10,6 +10,7 @@
 	.align	64
 
 	.globl	__atomic_add
+	.type	__atomic_add,#function
 __atomic_add: /* %o0 = increment, %o1 = atomic_ptr */
 	lduw	[%o1], %g5
 	add	%g5, %o0, %g7
@@ -19,8 +20,10 @@ __atomic_add: /* %o0 = increment, %o1 = atomic_ptr */
 	 membar	#StoreLoad | #StoreStore
 	retl
 	 add	%g7, %o0, %o0
+	.size	__atomic_add, .-__atomic_add
 
 	.globl	__atomic_sub
+	.type	__atomic_sub,#function
 __atomic_sub: /* %o0 = increment, %o1 = atomic_ptr */
 	lduw	[%o1], %g5
 	sub	%g5, %o0, %g7
@@ -30,8 +33,10 @@ __atomic_sub: /* %o0 = increment, %o1 = atomic_ptr */
 	 membar	#StoreLoad | #StoreStore
 	retl
 	 sub	%g7, %o0, %o0
+	.size	__atomic_sub, .-__atomic_sub
 
 	.globl	__atomic64_add
+	.type	__atomic64_add,#function
 __atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */
 	ldx	[%o1], %g5
 	add	%g5, %o0, %g7
@@ -41,8 +46,10 @@ __atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */
 	 membar	#StoreLoad | #StoreStore
 	retl
 	 add	%g7, %o0, %o0
+	.size	__atomic64_add, .-__atomic64_add
 
 	.globl	__atomic64_sub
+	.type	__atomic64_sub,#function
 __atomic64_sub: /* %o0 = increment, %o1 = atomic_ptr */
 	ldx	[%o1], %g5
 	sub	%g5, %o0, %g7
@@ -52,4 +59,4 @@ __atomic64_sub: /* %o0 = increment, %o1 = atomic_ptr */
 	 membar	#StoreLoad | #StoreStore
 	retl
 	 sub	%g7, %o0, %o0
-
+	.size	__atomic64_sub, .-__atomic64_sub
diff --git a/arch/sparc64/lib/bitops.S b/arch/sparc64/lib/bitops.S
index 0c2aacc83..c1e370068 100644
--- a/arch/sparc64/lib/bitops.S
+++ b/arch/sparc64/lib/bitops.S
@@ -9,6 +9,7 @@
 	.text
 	.align	64
 	.globl	___test_and_set_bit
+	.type	___test_and_set_bit,#function
 ___test_and_set_bit:	/* %o0=nr, %o1=addr */
 	srlx	%o0, 6, %g1
 	mov	1, %g5
@@ -26,8 +27,10 @@ ___test_and_set_bit:	/* %o0=nr, %o1=addr */
 	 ldx	[%o1], %g7
 2:	retl
 	 membar	#StoreLoad | #StoreStore
+	.size	___test_and_set_bit, .-___test_and_set_bit
 
 	.globl	___test_and_clear_bit
+	.type	___test_and_clear_bit,#function
 ___test_and_clear_bit:	/* %o0=nr, %o1=addr */
 	srlx	%o0, 6, %g1
 	mov	1, %g5
@@ -45,8 +48,10 @@ ___test_and_clear_bit:	/* %o0=nr, %o1=addr */
 	 ldx	[%o1], %g7
 2:	retl
 	 membar	#StoreLoad | #StoreStore
+	.size	___test_and_clear_bit, .-___test_and_clear_bit
 
 	.globl	___test_and_change_bit
+	.type	___test_and_change_bit,#function
 ___test_and_change_bit:	/* %o0=nr, %o1=addr */
 	srlx	%o0, 6, %g1
 	mov	1, %g5
@@ -64,41 +69,4 @@ ___test_and_change_bit:	/* %o0=nr, %o1=addr */
 2:	retl
 	 membar	#StoreLoad | #StoreStore
 	nop
-
-	.globl	___test_and_set_le_bit
-___test_and_set_le_bit:	/* %o0=nr, %o1=addr */
-	srlx	%o0, 5, %g1
-	mov	1, %g5
-	sllx	%g1, 2, %g3
-	and	%o0, 31, %g2
-	sllx	%g5, %g2, %g5
-	add	%o1, %g3, %o1
-	lduwa	[%o1] ASI_PL, %g7
-1:	andcc	%g7, %g5, %o0
-	bne,pn	%icc, 2f
-	 xor	%g7, %g5, %g1
-	casa	[%o1] ASI_PL, %g7, %g1
-	cmp	%g7, %g1
-	bne,a,pn %icc, 1b
-	 lduwa	[%o1] ASI_PL, %g7
-2:	retl
-	 membar	#StoreLoad | #StoreStore
-
-	.globl	___test_and_clear_le_bit
-___test_and_clear_le_bit:	/* %o0=nr, %o1=addr */
-	srlx	%o0, 5, %g1
-	mov	1, %g5
-	sllx	%g1, 2, %g3
-	and	%o0, 31, %g2
-	sllx	%g5, %g2, %g5
-	add	%o1, %g3, %o1
-	lduwa	[%o1] ASI_PL, %g7
-1:	andcc	%g7, %g5, %o0
-	be,pn	%icc, 2f
-	 xor	%g7, %g5, %g1
-	casa	[%o1] ASI_PL, %g7, %g1
-	cmp	%g7, %g1
-	bne,a,pn %icc, 1b
-	 lduwa	[%o1] ASI_PL, %g7
-2:	retl
-	 membar	#StoreLoad | #StoreStore
+	.size	___test_and_change_bit, .-___test_and_change_bit
diff --git a/arch/sparc64/lib/copy_page.S b/arch/sparc64/lib/copy_page.S
index 862eefb17..23ebf2c97 100644
--- a/arch/sparc64/lib/copy_page.S
+++ b/arch/sparc64/lib/copy_page.S
@@ -45,6 +45,7 @@
 
 	.align		32
 	.globl		copy_user_page
+	.type		copy_user_page,#function
 copy_user_page:		/* %o0=dest, %o1=src, %o2=vaddr */
 	lduw		[%g6 + TI_PRE_COUNT], %o4
 	sethi		%uhi(PAGE_OFFSET), %g2
@@ -237,3 +238,5 @@ copy_user_page:		/* %o0=dest, %o1=src, %o2=vaddr */
 
 	retl
 	 stw		%o4, [%g6 + TI_PRE_COUNT]
+
+	.size		copy_user_page, .-copy_user_page
diff --git a/arch/sparc64/lib/debuglocks.c b/arch/sparc64/lib/debuglocks.c
index 9e083e27d..9fb4dedc8 100644
--- a/arch/sparc64/lib/debuglocks.c
+++ b/arch/sparc64/lib/debuglocks.c
@@ -84,7 +84,7 @@ again:
 	put_cpu();
 }
 
-int _spin_trylock(spinlock_t *lock)
+int _do_spin_trylock(spinlock_t *lock)
 {
 	unsigned long val, caller;
 	int cpu = get_cpu();
diff --git a/arch/sparc64/lib/ipcsum.S b/arch/sparc64/lib/ipcsum.S
index e7d349fac..58ca5b9a8 100644
--- a/arch/sparc64/lib/ipcsum.S
+++ b/arch/sparc64/lib/ipcsum.S
@@ -1,6 +1,7 @@
 	.text
-	.align		32
-	.globl		ip_fast_csum
+	.align	32
+	.globl	ip_fast_csum
+	.type	ip_fast_csum,#function
 ip_fast_csum:	/* %o0 = iph, %o1 = ihl */
 	sub	%o1, 4, %g7
 	lduw	[%o0 + 0x00], %o2
@@ -30,3 +31,4 @@ ip_fast_csum:	/* %o0 = iph, %o1 = ihl */
 	set	0xffff, %o1
 	retl
 	 and	%o2, %o1, %o0
+	.size	ip_fast_csum, .-ip_fast_csum
diff --git a/arch/sparc64/lib/strlen.S b/arch/sparc64/lib/strlen.S
index 55527f639..066ec1ed7 100644
--- a/arch/sparc64/lib/strlen.S
+++ b/arch/sparc64/lib/strlen.S
@@ -9,9 +9,9 @@
 #define HI_MAGIC 0x80808080
 
 	.align	32
-	.global strlen, __strlen
+	.globl	strlen
+	.type	strlen,#function
 strlen:
-__strlen:
 	mov	%o0, %o1
 	andcc	%o0, 3, %g0
 	be,pt	%icc, 9f
@@ -76,3 +76,5 @@ __strlen:
 13:
 	retl
 	 mov	2, %o0
+
+	.size	strlen, .-strlen
diff --git a/arch/sparc64/lib/strncmp.S b/arch/sparc64/lib/strncmp.S
index 474ba7296..6f14f53db 100644
--- a/arch/sparc64/lib/strncmp.S
+++ b/arch/sparc64/lib/strncmp.S
@@ -7,9 +7,9 @@
 #include <asm/asi.h>
 
 	.text
-	.align 4
-	.global __strncmp, strncmp
-__strncmp:
+	.align	32
+	.globl	strncmp
+	.type	strncmp,#function
 strncmp:
 	brlez,pn %o2, 3f
 	 lduba	[%o0] (ASI_PNF), %o3
@@ -29,3 +29,4 @@ strncmp:
 3:
 	retl
 	 clr	%o0
+	.size	strncmp, .-strncmp
diff --git a/arch/sparc64/lib/strncpy_from_user.S b/arch/sparc64/lib/strncpy_from_user.S
index 9abb371e4..93d600a31 100644
--- a/arch/sparc64/lib/strncpy_from_user.S
+++ b/arch/sparc64/lib/strncpy_from_user.S
@@ -12,7 +12,7 @@
 0:	.xword	0x0101010101010101
 
 	.text
-	.align	4
+	.align	32
 
 	/* Must return:
 	 *
@@ -31,6 +31,7 @@
 	 */
 
 	.globl	__strncpy_from_user
+	.type	__strncpy_from_user,#function
 __strncpy_from_user:
 	/* %o0=dest, %o1=src, %o2=count */
 	sethi	%hi(0b), %o5		! IEU0	Group
@@ -122,6 +123,7 @@ __strncpy_from_user:
 	 mov	%o2, %o0
 2:	retl
 	 add	%o2, %o3, %o0
+	.size	__strncpy_from_user, .-__strncpy_from_user
 
 	.section .fixup,#alloc,#execinstr
 	.align	4
diff --git a/arch/sparc64/lib/xor.S b/arch/sparc64/lib/xor.S
index 8eeba353d..f748fd6bb 100644
--- a/arch/sparc64/lib/xor.S
+++ b/arch/sparc64/lib/xor.S
@@ -18,8 +18,9 @@
  *	!(len & 127) && len >= 256
  */
 	.text
-	.globl xor_vis_2
-	.type xor_vis_2,@function
+	.align	32
+	.globl	xor_vis_2
+	.type	xor_vis_2,#function
 xor_vis_2:
 	rd	%fprs, %o5
 	andcc	%o5, FPRS_FEF|FPRS_DU, %g0
@@ -87,11 +88,10 @@ xor_vis_2:
 	wr	%g1, %g0, %asi
 	retl
 	  wr	%g0, 0, %fprs
-	.size xor_vis_2, .-xor_vis_2
+	.size	xor_vis_2, .-xor_vis_2
 
-
-	.globl xor_vis_3
-	.type xor_vis_3,@function
+	.globl	xor_vis_3
+	.type	xor_vis_3,#function
 xor_vis_3:
 	rd	%fprs, %o5
 	andcc	%o5, FPRS_FEF|FPRS_DU, %g0
@@ -156,11 +156,10 @@ xor_vis_3:
 	wr	%g1, %g0, %asi
 	retl
 	 wr	%g0, 0, %fprs
-	.size xor_vis_3, .-xor_vis_3
-
+	.size	xor_vis_3, .-xor_vis_3
 
-	.globl xor_vis_4
-	.type xor_vis_4,@function
+	.globl	xor_vis_4
+	.type	xor_vis_4,#function
 xor_vis_4:
 	rd	%fprs, %o5
 	andcc	%o5, FPRS_FEF|FPRS_DU, %g0
@@ -244,11 +243,10 @@ xor_vis_4:
 	wr	%g1, %g0, %asi
 	retl
 	 wr	%g0, 0, %fprs
-	.size xor_vis_4, .-xor_vis_4
-
+	.size	xor_vis_4, .-xor_vis_4
 
-	.globl xor_vis_5
-	.type xor_vis_5,@function
+	.globl	xor_vis_5
+	.type	xor_vis_5,#function
 xor_vis_5:
 	mov	%o5, %g5
 	rd	%fprs, %o5
@@ -353,4 +351,4 @@ xor_vis_5:
 	wr	%g1, %g0, %asi
 	retl
 	 wr	%g0, 0, %fprs
-	.size xor_vis_5, .-xor_vis_5
+	.size	xor_vis_5, .-xor_vis_5
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index 49c3dd29a..63b989f3f 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -27,6 +27,7 @@
 #include <asm/asi.h>
 #include <asm/lsu.h>
 #include <asm/sections.h>
+#include <asm/kdebug.h>
 
 #define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0]))
 
@@ -147,6 +148,9 @@ static void unhandled_fault(unsigned long address, struct task_struct *tsk,
 	printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %016lx\n",
 	       (tsk->mm ? (unsigned long) tsk->mm->pgd :
 		          (unsigned long) tsk->active_mm->pgd));
+	if (notify_die(DIE_GPF, "general protection fault", regs,
+		       0, 0, SIGSEGV) == NOTIFY_STOP)
+		return;
 	die_if_kernel("Oops", regs);
 }
 
@@ -318,8 +322,13 @@ asmlinkage void do_sparc64_fault(struct pt_regs *regs)
 	int si_code, fault_code;
 	unsigned long address;
 
-	si_code = SEGV_MAPERR;
 	fault_code = get_thread_fault_code();
+
+	if (notify_die(DIE_PAGE_FAULT, "page_fault", regs,
+		       fault_code, 0, SIGSEGV) == NOTIFY_STOP)
+		return;
+
+	si_code = SEGV_MAPERR;
 	address = current_thread_info()->fault_address;
 
 	if ((fault_code & FAULT_CODE_ITLB) &&
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 60308cead..a82492650 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -68,6 +68,7 @@ unsigned long mmu_context_bmap[CTX_BMAP_SLOTS];
 extern char  _start[], _end[];
 
 /* Initial ramdisk setup */
+extern unsigned long sparc_ramdisk_image64;
 extern unsigned int sparc_ramdisk_image;
 extern unsigned int sparc_ramdisk_size;
 
@@ -1279,10 +1280,12 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* Now have to check initial ramdisk, so that bootmap does not overwrite it */
-	if (sparc_ramdisk_image) {
-		if (sparc_ramdisk_image >= (unsigned long)_end - 2 * PAGE_SIZE)
-			sparc_ramdisk_image -= KERNBASE;
-		initrd_start = sparc_ramdisk_image + phys_base;
+	if (sparc_ramdisk_image || sparc_ramdisk_image64) {
+		unsigned long ramdisk_image = sparc_ramdisk_image ?
+			sparc_ramdisk_image : sparc_ramdisk_image64;
+		if (ramdisk_image >= (unsigned long)_end - 2 * PAGE_SIZE)
+			ramdisk_image -= KERNBASE;
+		initrd_start = ramdisk_image + phys_base;
 		initrd_end = initrd_start + sparc_ramdisk_size;
 		if (initrd_end > end_of_phys_memory) {
 			printk(KERN_CRIT "initrd extends beyond end of memory "
@@ -1325,6 +1328,10 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
 		size = initrd_end - initrd_start;
 
 		/* Resert the initrd image area. */
+#ifdef CONFIG_DEBUG_BOOTMEM
+		prom_printf("reserve_bootmem(initrd): base[%llx] size[%lx]\n",
+			initrd_start, initrd_end);
+#endif
 		reserve_bootmem(initrd_start, size);
 		*pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
 
@@ -1377,7 +1384,7 @@ void __init paging_init(void)
 	if ((real_end > ((unsigned long)KERNBASE + 0x400000)))
 		bigkernel = 1;
 #ifdef CONFIG_BLK_DEV_INITRD
-	if (sparc_ramdisk_image)
+	if (sparc_ramdisk_image || sparc_ramdisk_image64)
 		real_end = (PAGE_ALIGN(real_end) + PAGE_ALIGN(sparc_ramdisk_size));
 #endif
 
@@ -1502,7 +1509,7 @@ void __init paging_init(void)
 		zones_size[ZONE_DMA] = npages;
 		zholes_size[ZONE_DMA] = npages - pages_avail;
 
-		free_area_init_node(0, &contig_page_data, NULL, zones_size,
+		free_area_init_node(0, &contig_page_data, zones_size,
 				    phys_base >> PAGE_SHIFT, zholes_size);
 		mem_map = contig_page_data.node_mem_map;
 	}
diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
index 4a3db02e1..15b4cfe07 100644
--- a/arch/sparc64/solaris/misc.c
+++ b/arch/sparc64/solaris/misc.c
@@ -137,21 +137,34 @@ asmlinkage int solaris_brk(u32 brk)
 	return sunos_brk(brk);
 }
 
-#define set_utsfield(to, from, dotchop, countfrom) {			\
-	char *p; 							\
-	int i, len = (countfrom) ? 					\
-		((sizeof(to) > sizeof(from) ? 				\
-			sizeof(from) : sizeof(to))) : sizeof(to); 	\
-	if (copy_to_user(to, from, len))				\
-		return -EFAULT;						\
-	if (dotchop) 							\
-		for (p=from,i=0; *p && *p != '.' && --len; p++,i++); 	\
-	else 								\
-		i = len - 1; 						\
-	if (__put_user('\0', (char __user *)((to)+i)))			\
-		return -EFAULT;						\
+static int __set_utsfield(char __user *to, int to_size,
+			  const char *from, int from_size,
+			  int dotchop, int countfrom)
+{
+	int len = countfrom ? (to_size > from_size ?
+			       from_size : to_size) : to_size;
+	int off;
+
+	if (copy_to_user(to, from, len))
+		return -EFAULT;
+
+	off = len < to_size? len: len - 1;
+	if (dotchop) {
+		const char *p = strnchr(from, len, '.');
+		if (p) off = p - from;
+	}
+
+	if (__put_user('\0', to + off))
+		return -EFAULT;
+
+	return 0;
 }
 
+#define set_utsfield(to, from, dotchop, countfrom) \
+	__set_utsfield((to), sizeof(to), \
+		       (from), sizeof(from), \
+		       (dotchop), (countfrom))
+
 struct sol_uname {
 	char sysname[9];
 	char nodename[9];
@@ -219,17 +232,20 @@ static char *serial(char *buffer)
 asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2)
 {
 	struct sol_uname __user *v = A(buf);
+	int err;
+
 	switch (which) {
 	case 0:	/* old uname */
 		/* Let's cheat */
-		set_utsfield(v->sysname, "SunOS", 1, 0);
+		err  = set_utsfield(v->sysname, "SunOS", 1, 0);
 		down_read(&uts_sem);
-		set_utsfield(v->nodename, system_utsname.nodename, 1, 1);
+		err |= set_utsfield(v->nodename, system_utsname.nodename,
+				    1, 1);
 		up_read(&uts_sem);
-		set_utsfield(v->release, "2.6", 0, 0);
-		set_utsfield(v->version, "Generic", 0, 0);
-		set_utsfield(v->machine, machine(), 0, 0);
-		return 0;
+		err |= set_utsfield(v->release, "2.6", 0, 0);
+		err |= set_utsfield(v->version, "Generic", 0, 0);
+		err |= set_utsfield(v->machine, machine(), 0, 0);
+		return (err ? -EFAULT : 0);
 	case 2: /* ustat */
 		return -ENOSYS;
 	case 3: /* fusers */
@@ -242,15 +258,18 @@ asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2)
 asmlinkage int solaris_utsname(u32 buf)
 {
 	struct sol_utsname __user *v = A(buf);
+	int err;
+
 	/* Why should we not lie a bit? */
 	down_read(&uts_sem);
-	set_utsfield(v->sysname, "SunOS", 0, 0);
-	set_utsfield(v->nodename, system_utsname.nodename, 1, 1);
-	set_utsfield(v->release, "5.6", 0, 0);
-	set_utsfield(v->version, "Generic", 0, 0);
-	set_utsfield(v->machine, machine(), 0, 0);
+	err  = set_utsfield(v->sysname, "SunOS", 0, 0);
+	err |= set_utsfield(v->nodename, system_utsname.nodename, 1, 1);
+	err |= set_utsfield(v->release, "5.6", 0, 0);
+	err |= set_utsfield(v->version, "Generic", 0, 0);
+	err |= set_utsfield(v->machine, machine(), 0, 0);
 	up_read(&uts_sem);
-	return 0;
+
+	return (err ? -EFAULT : 0);
 }
 
 #define SI_SYSNAME		1       /* return name of operating system */
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index 7ef333e57..98915ada2 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -34,7 +34,7 @@ config MODE_TT
 	help
 	This option controls whether tracing thread support is compiled
 	into UML.  Normally, this should be set to Y.  If you intend to
-	use only skas mode (and the host has the skas patch applied to it), 
+	use only skas mode (and the host has the skas patch applied to it),
 	then it is OK to say N here.
 
 config STATIC_LINK
@@ -45,7 +45,7 @@ config STATIC_LINK
 	If CONFIG_MODE_TT is disabled, then this option gives you the ability
 	to force a static link of UML.  Normally, if only skas mode is built
 	in to UML, it will be linked as a shared binary.  This is inconvenient
-	for use in a chroot jail.  So, if you intend to run UML inside a 
+	for use in a chroot jail.  So, if you intend to run UML inside a
 	chroot, and you disable CONFIG_MODE_TT, you probably want to say Y
 	here.
 
@@ -61,6 +61,20 @@ config MODE_SKAS
 
 config NET
 	bool "Networking support"
+	help
+	Unless you really know what you are doing, you should say Y here.
+	The reason is that some programs need kernel networking support even
+	when running on a stand-alone machine that isn't connected to any
+	other computer. If you are upgrading from an older kernel, you
+	should consider updating your networking tools too because changes
+	in the kernel and the tools often go hand in hand. The tools are
+	contained in the package net-tools, the location and version number
+	of which are given in Documentation/Changes.
+
+	For a general introduction to Linux networking, it is highly
+	recommended to read the NET-HOWTO, available from
+	<http://www.tldp.org/docs.html#howto>.
+
 
 source "fs/Kconfig.binfmt"
 
@@ -82,9 +96,22 @@ config HOSTFS
         For more information, see
         <http://user-mode-linux.sourceforge.net/hostfs.html>.
 
-        If you'd like to be able to work with files stored on the host, 
+        If you'd like to be able to work with files stored on the host,
         say Y or M here; otherwise say N.
 
+config HPPFS
+	tristate "HoneyPot ProcFS"
+	help
+	hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
+	entries to be overridden, removed, or fabricated from the host.
+	Its purpose is to allow a UML to appear to be a physical machine
+	by removing or changing anything in /proc which gives away the
+	identity of a UML.
+
+	See http://user-mode-linux.sf.net/hppfs.html for more information.
+
+	You only need this if you are setting up a UML honeypot.  Otherwise,
+	it is safe to say 'N' here.
 
 config MCONSOLE
 	bool "Management console"
@@ -102,15 +129,12 @@ config MCONSOLE
 
         It is safe to say 'Y' here.
 
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on MCONSOLE
-
 config HOST_2G_2G
 	bool "2G/2G host address space split"
 
-config UML_SMP
+config SMP
 	bool "Symmetric multi-processing support"
+	default n
 	help
         This option enables UML SMP support.  UML implements virtual SMP by
         allowing as many processes to run simultaneously on the host as
@@ -119,13 +143,8 @@ config UML_SMP
         will appear to be running simultaneously.  If the host is a
         multiprocessor, then UML processes may run simultaneously, depending
         on the host scheduler.
-        CONFIG_SMP will be set to whatever this option is set to.
         It is safe to leave this unchanged.
 
-config SMP
-	bool
-	default UML_SMP
-
 config NR_CPUS
 	int "Maximum number of CPUs (2-32)"
 	range 2 32
@@ -140,11 +159,11 @@ config NEST_LEVEL
         in.  Normally, this is zero, meaning that it will run directly on the
         host.  Setting it to one will build a UML that can run inside a UML
         that is running on the host.  Generally, if you intend this UML to run
-        inside another UML, set CONFIG_NEST_LEVEL to one more than the host 
+        inside another UML, set CONFIG_NEST_LEVEL to one more than the host
         UML.
 
-        Note that if the hosting UML has its CONFIG_KERNEL_HALF_GIGS set to 
-        greater than one, then the guest UML should have its CONFIG_NEST_LEVEL 
+        Note that if the hosting UML has its CONFIG_KERNEL_HALF_GIGS set to
+        greater than one, then the guest UML should have its CONFIG_NEST_LEVEL
         set to the host's CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS.
         Only change this if you are running nested UMLs.
 
@@ -159,6 +178,7 @@ config KERNEL_HALF_GIGS
 
 config HIGHMEM
 	bool "Highmem support"
+	depends on BROKEN
 
 config KERNEL_STACK_ORDER
 	int "Kernel stack size order"
@@ -168,6 +188,17 @@ config KERNEL_STACK_ORDER
 	be 1 << order pages.  The default is OK unless you're running Valgrind
 	on UML, in which case, set this to 3.
 
+config UML_REAL_TIME_CLOCK
+	bool "Real-time Clock"
+	default y
+	help
+	This option makes UML time deltas match wall clock deltas.  This should
+	normally be enabled.  The exception would be if you are debugging with
+	UML and spend long times with UML stopped at a breakpoint.  In this
+	case, when UML is restarted, it will call the timer enough times to make
+	up for the time spent at the breakpoint.  This could result in a
+	noticable lag.  If this is a problem, then disable this option.
+
 endmenu
 
 source "init/Kconfig"
@@ -197,6 +228,7 @@ source "crypto/Kconfig"
 source "lib/Kconfig"
 
 menu "SCSI support"
+depends on BROKEN
 
 config SCSI
 	tristate "SCSI support"
@@ -213,61 +245,8 @@ endmenu
 
 source "drivers/md/Kconfig"
 
-source "drivers/mtd/Kconfig"
-
-
-menu "Kernel hacking"
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-
-config DEBUG_SPINLOCK
-	bool "Debug spinlocks usage"
-
-config DEBUG_INFO
-	bool "Enable kernel debugging symbols"
-	help
-        When this is enabled, the User-Mode Linux binary will include
-        debugging symbols.  This enlarges the binary by a few megabytes,
-        but aids in tracking down kernel problems in UML.  It is required
-        if you intend to do any kernel development.
-
-        If you're truly short on disk space or don't expect to report any
-        bugs back to the UML developers, say N, otherwise say Y.
-
-config FRAME_POINTER
-	bool
-	default y if DEBUG_INFO
-
-config PT_PROXY
-	bool "Enable ptrace proxy"
-	depends on XTERM_CHAN && DEBUG_INFO
-
-config GPROF
-	bool "Enable gprof support"
-	depends on DEBUG_INFO
-	help
-        This allows profiling of a User-Mode Linux kernel with the gprof
-        utility.
-
-        See <http://user-mode-linux.sourceforge.net/gprof.html> for more
-        details.
-
-        If you're involved in UML kernel development and want to use gprof,
-        say Y.  If you're unsure, say N.
-
-config GCOV
-	bool "Enable gcov support"
-	depends on DEBUG_INFO
-	help
-        This option allows developers to retrieve coverage data from a UML
-        session.
-
-        See <http://user-mode-linux.sourceforge.net/gprof.html> for more
-        details.
-
-        If you're involved in UML kernel development and want to use gcov,
-        say Y.  If you're unsure, say N.
-
-endmenu
+if BROKEN
+	source "drivers/mtd/Kconfig"
+endif
 
+source "arch/um/Kconfig.debug"
diff --git a/arch/um/Kconfig_block b/arch/um/Kconfig_block
index fba53d9bb..8f2ba090c 100644
--- a/arch/um/Kconfig_block
+++ b/arch/um/Kconfig_block
@@ -29,6 +29,10 @@ config BLK_DEV_UBD_SYNC
         wise choice too.  In all other cases (for example, if you're just
         playing around with User-Mode Linux) you can choose N.
 
+config BLK_DEV_COW_COMMON
+	bool
+	default BLK_DEV_UBD
+
 config BLK_DEV_LOOP
 	tristate "Loopback device support"
 
@@ -50,6 +54,7 @@ config BLK_DEV_INITRD
 
 config MMAPPER
 	tristate "Example IO memory driver"
+	depends on BROKEN
 	help
         The User-Mode Linux port can provide support for IO Memory
         emulation with this option.  This allows a host file to be
diff --git a/arch/um/Kconfig_char b/arch/um/Kconfig_char
index a21cbbc7e..09f47388c 100644
--- a/arch/um/Kconfig_char
+++ b/arch/um/Kconfig_char
@@ -72,6 +72,10 @@ config XTERM_CHAN
         well, since UML's gdb currently requires an xterm.
         It is safe to say 'Y' here.
 
+config NOCONFIG_CHAN
+	bool
+	default !(XTERM_CHAN && TTY_CHAN && PTY_CHAN && PORT_CHAN && FD_CHAN && NULL_CHAN)
+
 config CON_ZERO_CHAN
 	string "Default main console channel initialization"
 	default "fd:0,fd:1"
@@ -108,11 +112,55 @@ config SSL_CHAN
 
 config UNIX98_PTYS
 	bool "Unix98 PTY support"
-
-config UNIX98_PTY_COUNT
-	int "Maximum number of Unix98 PTYs in use (0-2048)"
-	depends on UNIX98_PTYS
+	---help---
+	  A pseudo terminal (PTY) is a software device consisting of two
+	  halves: a master and a slave. The slave device behaves identical to
+	  a physical terminal; the master device is used by a process to
+	  read data from and write data to the slave, thereby emulating a
+	  terminal. Typical programs for the master side are telnet servers
+	  and xterms.
+
+	  Linux has traditionally used the BSD-like names /dev/ptyxx for
+	  masters and /dev/ttyxx for slaves of pseudo terminals. This scheme
+	  has a number of problems. The GNU C library glibc 2.1 and later,
+	  however, supports the Unix98 naming standard: in order to acquire a
+	  pseudo terminal, a process opens /dev/ptmx; the number of the pseudo
+	  terminal is then made available to the process and the pseudo
+	  terminal slave can be accessed as /dev/pts/<number>. What was
+	  traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
+
+	  All modern Linux systems use the Unix98 ptys.  Say Y unless
+	  you're on an embedded system and want to conserve memory.
+
+config LEGACY_PTYS
+	bool "Legacy (BSD) PTY support"
+	default y
+	---help---
+	  A pseudo terminal (PTY) is a software device consisting of two
+	  halves: a master and a slave. The slave device behaves identical to
+	  a physical terminal; the master device is used by a process to
+	  read data from and write data to the slave, thereby emulating a
+	  terminal. Typical programs for the master side are telnet servers
+	  and xterms.
+
+	  Linux has traditionally used the BSD-like names /dev/ptyxx
+	  for masters and /dev/ttyxx for slaves of pseudo
+	  terminals. This scheme has a number of problems, including
+	  security.  This option enables these legacy devices; on most
+	  systems, it is safe to say N.
+
+
+config LEGACY_PTY_COUNT
+	int "Maximum number of legacy PTY in use"
+	depends on LEGACY_PTYS
 	default "256"
+	---help---
+	  The maximum number of legacy PTYs that can be used at any one time.
+	  The default is 256, and should be more than enough.  Embedded
+	  systems may want to reduce this to save memory.
+
+	  When not in use, each legacy PTY occupies 12 bytes on 32-bit
+	  architectures and 24 bytes on 64-bit architectures.
 
 config WATCHDOG
 	bool "Watchdog Timer Support"
diff --git a/arch/um/Kconfig_net b/arch/um/Kconfig_net
index 443a74bd6..1c2f9a70d 100644
--- a/arch/um/Kconfig_net
+++ b/arch/um/Kconfig_net
@@ -1,5 +1,5 @@
 
-menu "Network Devices"
+menu "UML Network Devices"
 	depends on NET
 
 # UML virtual driver
@@ -135,7 +135,7 @@ config UML_NET_MCAST
 
 config UML_NET_PCAP
 	bool "pcap transport"
-	depends on UML_NET
+	depends on UML_NET && BROKEN
 	help
 	The pcap transport makes a pcap packet stream on the host look
 	like an ethernet device inside UML.  This is useful for making 
@@ -176,73 +176,5 @@ config UML_NET_SLIRP
 	
         Startup example: "eth0=slirp,FE:FD:01:02:03:04,/usr/local/bin/slirp"
 
-
-# Below are hardware-independent drivers mirrored from
-# drivers/net/Config.in. It would be nice if Linux
-# had HW independent drivers separated from the other
-# but it does not. Until then each non-ISA/PCI arch
-# needs to provide it's own menu of network drivers
-config DUMMY
-	tristate "Dummy net driver support"
-
-config BONDING
-	tristate "Bonding driver support"
-
-config EQUALIZER
-	tristate "EQL (serial line load balancing) support"
-
-config TUN
-	tristate "Universal TUN/TAP device driver support"
-
-config ETHERTAP
-	tristate "Ethertap network tap (OBSOLETE)"
-	depends on EXPERIMENTAL && NETLINK
-
-config PPP
-	tristate "PPP (point-to-point protocol) support"
-
-config PPP_MULTILINK
-	bool "PPP multilink support (EXPERIMENTAL)"
-	depends on PPP && EXPERIMENTAL
-
-config PPP_FILTER
-	bool "PPP filtering"
-	depends on PPP && FILTER
-
-config PPP_ASYNC
-	tristate "PPP support for async serial ports"
-	depends on PPP
-
-config PPP_SYNC_TTY
-	tristate "PPP support for sync tty ports"
-	depends on PPP
-
-config PPP_DEFLATE
-	tristate "PPP Deflate compression"
-	depends on PPP
-
-config PPP_BSDCOMP
-	tristate "PPP BSD-Compress compression"
-	depends on PPP
-
-config PPPOE
-	tristate "PPP over Ethernet (EXPERIMENTAL)"
-	depends on PPP && EXPERIMENTAL
-
-config SLIP
-	tristate "SLIP (serial line) support"
-
-config SLIP_COMPRESSED
-	bool "CSLIP compressed headers"
-	depends on SLIP=y
-
-config SLIP_SMART
-	bool "Keepalive and linefill"
-	depends on SLIP=y
-
-config SLIP_MODE_SLIP6
-	bool "Six bit SLIP encapsulation"
-	depends on SLIP=y
-
 endmenu
 
diff --git a/arch/um/Makefile b/arch/um/Makefile
index bb7d3f6ba..0406c1a90 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -5,35 +5,25 @@
 
 ARCH_DIR = arch/um
 OS := $(shell uname -s)
+#We require it or things break.
+SHELL := /bin/bash
 
-# Recalculate MODLIB to reflect the EXTRAVERSION changes (via KERNELRELEASE)
-# The way the toplevel Makefile is written EXTRAVERSION is not supposed
-# to be changed outside the toplevel Makefile, but recalculating MODLIB is
-# a sufficient workaround until we no longer need architecture dependent
-# EXTRAVERSION...
-MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
+filechk_gen_header = $<
 
-ifeq ($(CONFIG_DEBUG_INFO),y)
-CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS))
-endif
-
-core-y			+= $(ARCH_DIR)/kernel/		 \
-			   $(ARCH_DIR)/drivers/          \
+core-y			+= $(ARCH_DIR)/kernel/		\
+			   $(ARCH_DIR)/drivers/		\
 			   $(ARCH_DIR)/sys-$(SUBARCH)/
 
 # Have to precede the include because the included Makefiles reference them.
-SYMLINK_HEADERS = include/asm-um/archparam.h include/asm-um/system.h \
-	include/asm-um/sigcontext.h include/asm-um/processor.h \
-	include/asm-um/ptrace.h include/asm-um/arch-signal.h
+SYMLINK_HEADERS = archparam.h system.h sigcontext.h processor.h ptrace.h \
+	arch-signal.h module.h
+SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header))
 
 ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \
 	$(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h
 
 GEN_HEADERS += $(ARCH_DIR)/include/task.h $(ARCH_DIR)/include/kern_constants.h
 
-include $(ARCH_DIR)/Makefile-$(SUBARCH)
-include $(ARCH_DIR)/Makefile-os-$(OS)
-
 MAKEFILE-$(CONFIG_MODE_TT) += Makefile-tt
 MAKEFILE-$(CONFIG_MODE_SKAS) += Makefile-skas
 
@@ -41,9 +31,11 @@ ifneq ($(MAKEFILE-y),)
   include $(addprefix $(ARCH_DIR)/,$(MAKEFILE-y))
 endif
 
-EXTRAVERSION := $(EXTRAVERSION)-1um
+ARCH_INCLUDE	:= -I$(ARCH_DIR)/include
+SYS_DIR		:= $(ARCH_DIR)/include/sysdep-$(SUBARCH)
 
-ARCH_INCLUDE = -I$(ARCH_DIR)/include
+include $(ARCH_DIR)/Makefile-$(SUBARCH)
+include $(ARCH_DIR)/Makefile-os-$(OS)
 
 # -Derrno=kernel_errno - This turns all kernel references to errno into
 # kernel_errno to separate them from the libc errno.  This allows -fno-common
@@ -52,32 +44,32 @@ ARCH_INCLUDE = -I$(ARCH_DIR)/include
 
 CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
 	-D_LARGEFILE64_SOURCE $(ARCH_INCLUDE) -Derrno=kernel_errno \
-	$(MODE_INCLUDE)
+	-Dsigprocmask=kernel_sigprocmask $(MODE_INCLUDE)
+
+CFLAGS += $(call cc-option,-fno-unit-at-a-time,)
 
 LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
 
+# These are needed for clean and mrproper, since in that case .config is not
+# included; the values here are meaningless
+
+CONFIG_NEST_LEVEL ?= 0
+CONFIG_KERNEL_HALF_GIGS ?= 0
+
 SIZE = (($(CONFIG_NEST_LEVEL) + $(CONFIG_KERNEL_HALF_GIGS)) * 0x20000000)
 
 ifeq ($(CONFIG_MODE_SKAS), y)
-$(SYS_HEADERS) : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h
+$(SYS_HEADERS) : $(ARCH_DIR)/include/skas_ptregs.h
 endif
 
-include/linux/version.h: arch/$(ARCH)/Makefile
-
-$(ARCH_DIR)/vmlinux.lds.S :
-	touch $@
-
-prepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS)
-
-LDFLAGS_vmlinux = -r
-
-vmlinux: $(ARCH_DIR)/main.o 
+prepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS) \
+	$(ARCH_DIR)/kernel/vmlinux.lds.S
 
 # These aren't in Makefile-tt because they are needed in the !CONFIG_MODE_TT +
 # CONFIG_MODE_SKAS + CONFIG_STATIC_LINK case.
 
 LINK_TT = -static
-LD_SCRIPT_TT := uml.lds.s
+LD_SCRIPT_TT := uml.lds.S
 
 ifeq ($(CONFIG_STATIC_LINK),y)
   LINK-y += $(LINK_TT)
@@ -98,82 +90,99 @@ CPP_MODE_TT := $(shell [ "$(CONFIG_MODE_TT)" = "y" ] && echo -DMODE_TT)
 CONFIG_KERNEL_STACK_ORDER ?= 2
 STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] )
 
-AFLAGS_vmlinux.lds.o = -U$(SUBARCH) \
-	-DSTART=$$(($(TOP_ADDR) - $(SIZE))) -DELF_ARCH=$(ELF_ARCH) \
-	-DELF_FORMAT=\"$(ELF_FORMAT)\" $(CPP_MODE_TT) \
-	-DKERNEL_STACK_SIZE=$(STACK_SIZE)
-
-AFLAGS_$(LD_SCRIPT-y:.s=).o = $(AFLAGS_vmlinux.lds.o) -P -C -Uum
-
-LD_SCRIPT-y := $(ARCH_DIR)/$(LD_SCRIPT-y)
+ifndef START
+  START = $$(($(TOP_ADDR) - $(SIZE)))
+endif
 
-$(LD_SCRIPT-y) : $(LD_SCRIPT-y:.s=.S) scripts FORCE
-	$(call if_changed_dep,as_s_S)
+CPPFLAGS_vmlinux.lds = $(shell echo -U$(SUBARCH) \
+	-DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \
+	-DELF_FORMAT=\"$(ELF_FORMAT)\" $(CPP_MODE_TT) \
+	-DKERNEL_STACK_SIZE=$(STACK_SIZE))
 
-linux: vmlinux $(LD_SCRIPT-y)
-	$(CC) -Wl,-T,$(LD_SCRIPT-y) $(LINK-y) $(LINK_WRAPS) \
-		-o linux $(ARCH_DIR)/main.o vmlinux -L/usr/lib -lutil
+CFLAGS_vmlinux = $(LINK-y) $(LINK_WRAPS)
+define cmd_vmlinux__
+	$(CC) $(CFLAGS_vmlinux) -o $@ \
+	-Wl,-T,$(vmlinux-lds) $(vmlinux-init) \
+	-Wl,--start-group $(vmlinux-main) -Wl,--end-group \
+	-L/usr/lib -lutil \
+	$(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE ,$^)
+endef
 
 USER_CFLAGS := $(patsubst -I%,,$(CFLAGS))
 USER_CFLAGS := $(patsubst -Derrno=kernel_errno,,$(USER_CFLAGS))
+USER_CFLAGS := $(patsubst -Dsigprocmask=kernel_sigprocmask,,$(USER_CFLAGS))
 USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \
 	$(MODE_INCLUDE)
 
 # To get a definition of F_SETSIG
 USER_CFLAGS += -D_GNU_SOURCE
 
-CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/uml.lds.s \
-	$(ARCH_DIR)/dyn_link.ld.s $(GEN_HEADERS)
+#When cleaning we don't include .config, so we don't include
+#TT or skas makefiles and don't clean skas_ptregs.h.
+CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/include/uml-config.h \
+	$(GEN_HEADERS) $(ARCH_DIR)/include/skas_ptregs.h
 
-$(ARCH_DIR)/main.o: $(ARCH_DIR)/main.c
-	$(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
+MRPROPER_FILES += $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) \
+	$(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS)) $(ARCH_DIR)/os
 
 archmrproper:
-	for d in $(ARCH_SUBDIRS) $(ARCH_DIR)/util; \
-	do \
-		$(MAKE) -C $$d archmrproper; \
-	done
-	rm -f $(CLEAN_FILES) $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) include/asm \
-		$(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS))
-
-archclean: sysclean
-	for d in $(ARCH_SUBDIRS) $(ARCH_DIR)/util; \
-	do \
-		$(MAKE) -C $$d clean; \
-	done
-	find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
+	@:
+
+archclean:
+	$(Q)$(MAKE) $(clean)=$(ARCH_DIR)/util
+	@find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
 		-o -name '*.gcov' \) -type f -print | xargs rm -f
-	rm -f linux x.i gmon.out $(ARCH_DIR)/link.ld $(GEN_HEADERS)
 
-archdep: 
-	for d in $(ARCH_SUBDIRS); do $(MAKE) -C $$d fastdep; done
+#We need to re-preprocess this when the symlink dest changes.
+#So we touch it.
+$(ARCH_DIR)/kernel/vmlinux.lds.S: FORCE
+	@echo '  SYMLINK $@'
+	$(Q)ln -sf $(LD_SCRIPT-y) $@
+	$(Q)touch $@
 
 $(SYMLINK_HEADERS):
-	cd $(TOPDIR)/$(dir $@) ; \
+	@echo '  SYMLINK $@'
+	$(Q)cd $(TOPDIR)/$(dir $@) ; \
 	ln -sf $(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $(notdir $@)
 
 include/asm-um/arch:
-	cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch
+	@echo '  SYMLINK $@'
+	$(Q)cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch
 
 $(ARCH_DIR)/include/sysdep:
-	cd $(ARCH_DIR)/include && ln -sf sysdep-$(SUBARCH) sysdep
+	@echo '  SYMLINK $@'
+	$(Q)cd $(ARCH_DIR)/include && ln -sf sysdep-$(SUBARCH) sysdep
 
 $(ARCH_DIR)/os:
-	cd $(ARCH_DIR) && ln -sf os-$(OS) os
+	@echo '  SYMLINK $@'
+	$(Q)cd $(ARCH_DIR) && ln -sf os-$(OS) os
+
+# Generated files
+define filechk_umlconfig
+	sed 's/ CONFIG/ UML_CONFIG/'
+endef
+
+$(ARCH_DIR)/include/uml-config.h : include/linux/autoconf.h
+	$(call filechk,umlconfig)
+
+$(ARCH_DIR)/include/task.h: $(ARCH_DIR)/util/mk_task
+	$(call filechk,gen_header)
+
+$(ARCH_DIR)/include/kern_constants.h: $(ARCH_DIR)/util/mk_constants
+	$(call filechk,gen_header)
 
-$(ARCH_DIR)/include/uml-config.h :
-	sed 's/ CONFIG/ UML_CONFIG/' $(TOPDIR)/include/linux/autoconf.h > $@
+$(ARCH_DIR)/include/skas_ptregs.h: $(ARCH_DIR)/kernel/skas/util/mk_ptregs
+	$(call filechk,gen_header)
 
-$(ARCH_DIR)/include/task.h : $(ARCH_DIR)/util/mk_task
-	$< > $@
+$(ARCH_DIR)/util/mk_task $(ARCH_DIR)/util/mk_constants: $(ARCH_DIR)/util \
+	FORCE ;
 
-$(ARCH_DIR)/include/kern_constants.h : $(ARCH_DIR)/util/mk_constants
-	$< > $@
+$(ARCH_DIR)/kernel/skas/util/mk_ptregs: $(ARCH_DIR)/kernel/skas/util FORCE ;
 
-$(ARCH_DIR)/util/mk_task : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h \
-	$(ARCH_DIR)/util FORCE ;
+$(ARCH_DIR)/util: scripts_basic $(SYS_DIR)/sc.h FORCE
+	$(Q)$(MAKE) $(build)=$@
 
-$(ARCH_DIR)/util: FORCE
-	@$(call descend,$@,)
+$(ARCH_DIR)/kernel/skas/util: scripts_basic FORCE
+	$(Q)$(MAKE) $(build)=$@
 
 export SUBARCH USER_CFLAGS OS
diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386
index 3bd90fbdb..9a6cf6e5b 100644
--- a/arch/um/Makefile-i386
+++ b/arch/um/Makefile-i386
@@ -1,37 +1,45 @@
 ifeq ($(CONFIG_HOST_2G_2G), y)
-TOP_ADDR = 0x80000000
+TOP_ADDR := 0x80000000
 else
-TOP_ADDR = 0xc0000000
+TOP_ADDR := 0xc0000000
+endif
+
+ifeq ($(CONFIG_MODE_SKAS),y)
+  ifneq ($(CONFIG_MODE_TT),y)
+     START := 0x8048000
+  endif
 endif
 
 CFLAGS += -U__$(SUBARCH)__ -U$(SUBARCH)
-ELF_ARCH = $(SUBARCH)
-ELF_FORMAT = elf32-$(SUBARCH)
+
+ifneq ($(CONFIG_GPROF),y)
+ARCH_CFLAGS += -DUM_FASTCALL
+endif
+
+ELF_ARCH := $(SUBARCH)
+ELF_FORMAT := elf32-$(SUBARCH)
 
 OBJCOPYFLAGS  := -O binary -R .note -R .comment -S
-LDFLAGS_BLOB	:= --format binary --oformat elf32-i386
 
-SYS_DIR		:= $(ARCH_DIR)/include/sysdep-i386
 SYS_UTIL_DIR	:= $(ARCH_DIR)/sys-i386/util
 
-SYS_HEADERS = $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h
+SYS_HEADERS := $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h
 
 prepare: $(SYS_HEADERS)
 
 $(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc
-	$< > $@
+	$(call filechk,gen_header)
 
 $(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread 
-	$< > $@
+	$(call filechk,gen_header)
 
-$(SYS_UTIL_DIR)/mk_sc: FORCE ; 
-	@$(call descend,$(SYS_UTIL_DIR),$@)
+$(SYS_UTIL_DIR)/mk_sc: scripts_basic FORCE
+	$(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
 
-$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE ; 
-	@$(call descend,$(SYS_UTIL_DIR),$@)
+$(SYS_UTIL_DIR)/mk_thread: scripts_basic $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE
+	$(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
 
-$(SYS_UTIL_DIR): include/asm FORCE
-	@$(call descend,$@,)
+$(SYS_UTIL_DIR): scripts_basic include/asm FORCE
+	$(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR)
 
-sysclean :
-	rm -f $(SYS_HEADERS)
+CLEAN_FILES += $(SYS_HEADERS)
diff --git a/arch/um/Makefile-skas b/arch/um/Makefile-skas
index b9dfec5f7..fb3050ff9 100644
--- a/arch/um/Makefile-skas
+++ b/arch/um/Makefile-skas
@@ -9,12 +9,9 @@ CFLAGS-$(CONFIG_GCOV) += -fprofile-arcs -ftest-coverage
 CFLAGS-$(CONFIG_GPROF) += $(PROFILE)
 LINK-$(CONFIG_GPROF) += $(PROFILE)
 
-MODE_INCLUDE += -I$(TOPDIR)/$(ARCH_DIR)/kernel/skas/include
+MODE_INCLUDE += -I$(srctree)/$(ARCH_DIR)/kernel/skas/include
 
 LINK_SKAS = -Wl,-rpath,/lib 
-LD_SCRIPT_SKAS = dyn.lds.s
+LD_SCRIPT_SKAS = dyn.lds.S
 
-GEN_HEADERS += $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h
-
-$(ARCH_DIR)/kernel/skas/include/skas_ptregs.h :
-	$(MAKE) -C $(ARCH_DIR)/kernel/skas include/skas_ptregs.h
+GEN_HEADERS += $(ARCH_DIR)/include/skas_ptregs.h
diff --git a/arch/um/Makefile-tt b/arch/um/Makefile-tt
index 8d58a3083..eed367d9c 100644
--- a/arch/um/Makefile-tt
+++ b/arch/um/Makefile-tt
@@ -3,5 +3,4 @@
 # Licensed under the GPL
 #
 
-MODE_INCLUDE += -I$(TOPDIR)/$(ARCH_DIR)/kernel/tt/include
-
+MODE_INCLUDE += -I$(srctree)/$(ARCH_DIR)/kernel/tt/include
diff --git a/arch/um/config.release b/arch/um/config.release
index 6d32bc20c..fc68bcb92 100644
--- a/arch/um/config.release
+++ b/arch/um/config.release
@@ -227,7 +227,6 @@ CONFIG_ROMFS_FS=m
 CONFIG_EXT2_FS=y
 CONFIG_SYSV_FS=m
 CONFIG_UDF_FS=m
-# CONFIG_UDF_RW is not set
 CONFIG_UFS_FS=m
 # CONFIG_UFS_FS_WRITE is not set
 
diff --git a/arch/um/defconfig b/arch/um/defconfig
index 412d006b9..84547f12f 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -1,47 +1,79 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2-mm1
+# Thu Sep 16 23:44:48 2004
 #
 CONFIG_USERMODE=y
 CONFIG_MMU=y
-CONFIG_SWAP=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_CONFIG_LOG_BUF_SHIFT=14
 
 #
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General Setup
+# UML-specific options
 #
 CONFIG_MODE_TT=y
 CONFIG_MODE_SKAS=y
 CONFIG_NET=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-CONFIG_BINFMT_AOUT=y
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
 CONFIG_HOSTFS=y
+CONFIG_HPPFS=y
 CONFIG_MCONSOLE=y
-CONFIG_MAGIC_SYSRQ=y
 # CONFIG_HOST_2G_2G is not set
-# CONFIG_UML_SMP is not set
 # CONFIG_SMP is not set
 CONFIG_NEST_LEVEL=0
 CONFIG_KERNEL_HALF_GIGS=1
 # CONFIG_HIGHMEM is not set
-CONFIG_PROC_MM=y
 CONFIG_KERNEL_STACK_ORDER=2
+CONFIG_UML_REAL_TIME_CLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
 #
-CONFIG_MODULES=y
-# CONFIG_KMOD is not set
+# CONFIG_MODULES is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
 
 #
 # Character Devices
@@ -58,7 +90,8 @@ CONFIG_CON_ZERO_CHAN="fd:0,fd:1"
 CONFIG_CON_CHAN="xterm"
 CONFIG_SSL_CHAN="pty"
 CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_WATCHDOG is not set
 CONFIG_UML_SOUND=y
 CONFIG_SOUND=y
@@ -69,6 +102,7 @@ CONFIG_HOSTAUDIO=y
 #
 CONFIG_BLK_DEV_UBD=y
 # CONFIG_BLK_DEV_UBD_SYNC is not set
+CONFIG_BLK_DEV_COW_COMMON=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=y
 CONFIG_BLK_DEV_RAM=y
@@ -78,7 +112,7 @@ CONFIG_BLK_DEV_INITRD=y
 CONFIG_NETDEVICES=y
 
 #
-# Network Devices
+# UML Network Devices
 #
 CONFIG_UML_NET=y
 CONFIG_UML_NET_ETHERTAP=y
@@ -88,22 +122,6 @@ CONFIG_UML_NET_DAEMON=y
 CONFIG_UML_NET_MCAST=y
 # CONFIG_UML_NET_PCAP is not set
 CONFIG_UML_NET_SLIRP=y
-CONFIG_DUMMY=y
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=y
-# CONFIG_ETHERTAP is not set
-CONFIG_PPP=y
-# CONFIG_PPP_MULTILINK 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_PPPOE is not set
-CONFIG_SLIP=y
-# CONFIG_SLIP_COMPRESSED is not set
-# CONFIG_SLIP_SMART is not set
-# CONFIG_SLIP_MODE_SLIP6 is not set
 
 #
 # Networking support
@@ -115,8 +133,6 @@ CONFIG_SLIP=y
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
 # CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -126,23 +142,25 @@ CONFIG_INET=y
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
-# CONFIG_XFRM_USER is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
 # CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
 
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
 # CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_NET_DIVERT is not set
@@ -154,11 +172,24 @@ CONFIG_IPV6_SCTP__=y
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_KGDBOE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=y
 
 #
 # Ethernet (10 or 100Mbit)
@@ -170,83 +201,130 @@ CONFIG_IPV6_SCTP__=y
 #
 
 #
-# Wireless LAN (non-hamradio)
+# Ethernet (10000 Mbit)
 #
-# CONFIG_NET_RADIO is not set
 
 #
-# Token Ring devices (depends on LLC=y)
+# Token Ring devices
 #
-# CONFIG_SHAPER is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
 
 #
 # Wan interfaces
 #
 # CONFIG_WAN is not set
+CONFIG_PPP=y
+# 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_PPPOE is not set
+CONFIG_SLIP=y
+# CONFIG_SLIP_COMPRESSED is not set
+# CONFIG_SLIP_SMART is not set
+# CONFIG_SLIP_MODE_SLIP6 is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
 
 #
 # File systems
 #
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+CONFIG_REISER4_FS=y
+CONFIG_REISER4_LARGE_KEY=y
+# CONFIG_REISER4_CHECK is not set
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+CONFIG_MINIX_FS=y
+# CONFIG_ROMFS_FS is not set
 CONFIG_QUOTA=y
 # CONFIG_QFMT_V1 is not set
 # CONFIG_QFMT_V2 is not set
 CONFIG_QUOTACTL=y
-CONFIG_AUTOFS_FS=m
-CONFIG_AUTOFS4_FS=m
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# Caches
+#
+# CONFIG_CACHEFS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_EXT3_FS is not set
-# CONFIG_JBD is not set
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
 # CONFIG_EFS_FS is not set
 CONFIG_JFFS_FS=y
 CONFIG_JFFS_FS_VERBOSE=0
-CONFIG_JFFS_PROC_FS=y
+# CONFIG_JFFS_PROC_FS is not set
 # CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-CONFIG_ISO9660_FS=m
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_MINIX_FS=m
 # CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
 # CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
 # CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_XFS_FS is not set
 
 #
 # Network File Systems
 #
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
 # CONFIG_NFS_FS is not set
 # CONFIG_NFSD is not set
 # CONFIG_EXPORTFS is not set
-# CONFIG_CIFS is not set
 # CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
 
 #
@@ -254,11 +332,11 @@ CONFIG_EXT2_FS=y
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-CONFIG_NLS=y
 
 #
 # Native Language Support
 #
+CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_CODEPAGE_437 is not set
 # CONFIG_NLS_CODEPAGE_737 is not set
@@ -283,6 +361,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
 # CONFIG_NLS_ISO8859_1 is not set
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
@@ -301,6 +380,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
@@ -311,33 +391,14 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 #
 # Library routines
 #
+# CONFIG_CRC_CCITT is not set
 # CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
 
 #
 # SCSI support
 #
-CONFIG_SCSI=y
-CONFIG_GENERIC_ISA_DMA=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_SD_EXTRA_DEVS=40
-CONFIG_CHR_DEV_ST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_SR_EXTRA_DEVS=2
-CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-CONFIG_SCSI_DEBUG_QUEUES=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_DEBUG=y
+# CONFIG_SCSI is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -359,34 +420,46 @@ CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
 
 #
 # RAM/ROM/Flash chip drivers
 #
 # CONFIG_MTD_CFI is not set
 # CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
 #
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
 
 #
 # Self-contained MTD device drivers
 #
 # CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-CONFIG_MTD_BLKMTD=m
+CONFIG_MTD_BLKMTD=y
 
 #
 # Disk-On-Chip Device Drivers
 #
-# CONFIG_MTD_DOC1000 is not set
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
 
 #
 # NAND Flash Device Drivers
@@ -396,6 +469,7 @@ CONFIG_MTD_BLKMTD=m
 #
 # Kernel hacking
 #
+CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_INFO=y
diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile
index 8ea9ada4a..127bb4d07 100644
--- a/arch/um/drivers/Makefile
+++ b/arch/um/drivers/Makefile
@@ -1,5 +1,5 @@
 # 
-# Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
+# Copyright (C) 2000, 2002, 2003 Jeff Dike (jdike@karaya.com)
 # Licensed under the GPL
 #
 
@@ -15,7 +15,7 @@ mcast-objs := mcast_kern.o mcast_user.o
 #pcap-objs := pcap_kern.o pcap_user.o $(PCAP)
 net-objs := net_kern.o net_user.o
 mconsole-objs := mconsole_kern.o mconsole_user.o
-hostaudio-objs := hostaudio_kern.o hostaudio_user.o
+hostaudio-objs := hostaudio_kern.o
 ubd-objs := ubd_kern.o ubd_user.o
 port-objs := port_kern.o port_user.o
 harddog-objs := harddog_kern.o harddog_user.o
@@ -39,6 +39,7 @@ obj-$(CONFIG_PTY_CHAN) += pty.o
 obj-$(CONFIG_TTY_CHAN) += tty.o 
 obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o
 obj-$(CONFIG_UML_WATCHDOG) += harddog.o
+obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o
 
 obj-y += stdio_console.o $(CHAN_OBJS)
 
@@ -46,18 +47,7 @@ USER_SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs))
 
 USER_OBJS := $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) fd.o \
 	null.o pty.o tty.o xterm.o
-USER_OBJS := $(foreach file,$(USER_OBJS),arch/um/drivers/$(file))
+USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
 
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean:
-
-modules:
-
-fastdep:
-
-dep:
-
-archmrproper: clean
-
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 9e45a082e..7a8d75086 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -8,6 +8,7 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/tty.h>
+#include <linux/string.h>
 #include <linux/tty_flip.h>
 #include <asm/irq.h>
 #include "chan_kern.h"
@@ -16,7 +17,9 @@
 #include "irq_user.h"
 #include "sigio.h"
 #include "line.h"
+#include "os.h"
 
+#ifdef CONFIG_NOCONFIG_CHAN
 static void *not_configged_init(char *str, int device, struct chan_opts *opts)
 {
 	printk(KERN_ERR "Using a channel type which is configured out of "
@@ -85,6 +88,55 @@ static struct chan_ops not_configged_ops = {
 	.free		= not_configged_free,
 	.winch		= 0,
 };
+#endif /* CONFIG_NOCONFIG_CHAN */
+
+void generic_close(int fd, void *unused)
+{
+	os_close_file(fd);
+}
+
+int generic_read(int fd, char *c_out, void *unused)
+{
+	int n;
+
+	n = os_read_file(fd, c_out, sizeof(*c_out));
+
+	if(n == -EAGAIN)
+		return(0);
+	else if(n == 0)
+		return(-EIO);
+	return(n);
+}
+
+/* XXX Trivial wrapper around os_write_file */
+
+int generic_write(int fd, const char *buf, int n, void *unused)
+{
+	return(os_write_file(fd, buf, n));
+}
+
+int generic_window_size(int fd, void *unused, unsigned short *rows_out,
+			unsigned short *cols_out)
+{
+	int rows, cols;
+	int ret;
+
+	ret = os_window_size(fd, &rows, &cols);
+	if(ret < 0)
+		return(ret);
+
+	ret = ((*rows_out != rows) || (*cols_out != cols));
+
+	*rows_out = rows;
+	*cols_out = cols;
+
+	return(ret);
+}
+
+void generic_free(void *data)
+{
+	kfree(data);
+}
 
 static void tty_receive_char(struct tty_struct *tty, char ch)
 {
@@ -265,6 +317,11 @@ static int one_chan_config_string(struct chan *chan, char *str, int size,
 {
 	int n = 0;
 
+	if(chan == NULL){
+		CONFIG_CHUNK(str, size, n, "none", 1);
+		return(n);
+	}
+
 	CONFIG_CHUNK(str, size, n, chan->ops->type, 0);
 
 	if(chan->dev == NULL){
@@ -420,7 +477,8 @@ int parse_chan_pair(char *str, struct list_head *chans, int pri, int device,
 		INIT_LIST_HEAD(chans);
 	}
 
-	if((out = strchr(str, ',')) != NULL){
+	out = strchr(str, ',');
+	if(out != NULL){
 		in = str;
 		*out = '\0';
 		out++;
@@ -475,12 +533,15 @@ void chan_interrupt(struct list_head *chans, struct work_struct *task,
 				goto out;
 			}
 			err = chan->ops->read(chan->fd, &c, chan->data);
-			if(err > 0) tty_receive_char(tty, c);
+			if(err > 0)
+				tty_receive_char(tty, c);
 		} while(err > 0);
+
 		if(err == 0) reactivate_fd(chan->fd, irq);
 		if(err == -EIO){
 			if(chan->primary){
-				if(tty != NULL) tty_hangup(tty);
+				if(tty != NULL)
+					tty_hangup(tty);
 				line_disable(dev, irq);
 				close_chan(chans);
 				free_chan(chans);
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index 714bace49..8a5180a77 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -7,7 +7,6 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <termios.h>
-#include <fcntl.h>
 #include <string.h>
 #include <signal.h>
 #include <sys/stat.h>
@@ -22,33 +21,6 @@
 #include "choose-mode.h"
 #include "mode.h"
 
-void generic_close(int fd, void *unused)
-{
-	close(fd);
-}
-
-int generic_read(int fd, char *c_out, void *unused)
-{
-	int n;
-
-	n = read(fd, c_out, sizeof(*c_out));
-	if(n < 0){
-		if(errno == EAGAIN) return(0);
-		return(-errno);
-	}
-	else if(n == 0) return(-EIO);
-	return(1);
-}
-
-int generic_write(int fd, const char *buf, int n, void *unused)
-{
-	int count;
-
-	count = write(fd, buf, n);
-	if(count < 0) return(-errno);
-	return(count);
-}
-
 int generic_console_write(int fd, const char *buf, int n, void *unused)
 {
 	struct termios save, new;
@@ -65,26 +37,6 @@ int generic_console_write(int fd, const char *buf, int n, void *unused)
 	return(err);
 }
 
-int generic_window_size(int fd, void *unused, unsigned short *rows_out,
-			unsigned short *cols_out)
-{
-	struct winsize size;
-	int ret = 0;
-
-	if(ioctl(fd, TIOCGWINSZ, &size) == 0){
-		ret = ((*rows_out != size.ws_row) || 
-		       (*cols_out != size.ws_col));
-		*rows_out = size.ws_row;
-		*cols_out = size.ws_col;
-	}
-	return(ret);
-}
-
-void generic_free(void *data)
-{
-	kfree(data);
-}
-
 static void winch_handler(int sig)
 {
 }
@@ -100,14 +52,16 @@ static int winch_thread(void *arg)
 	struct winch_data *data = arg;
 	sigset_t sigs;
 	int pty_fd, pipe_fd;
+	int count, err;
 	char c = 1;
 
-	close(data->close_me);
+	os_close_file(data->close_me);
 	pty_fd = data->pty_fd;
 	pipe_fd = data->pipe_fd;
-	if(write(pipe_fd, &c, sizeof(c)) != sizeof(c))
+	count = os_write_file(pipe_fd, &c, sizeof(c));
+	if(count != sizeof(c))
 		printk("winch_thread : failed to write synchronization "
-		       "byte, errno = %d\n", errno);
+		       "byte, err = %d\n", -count);
 
 	signal(SIGWINCH, winch_handler);
 	sigfillset(&sigs);
@@ -123,26 +77,24 @@ static int winch_thread(void *arg)
 		exit(1);
 	}
 
-	if(ioctl(pty_fd, TIOCSCTTY, 0) < 0){
-		printk("winch_thread : TIOCSCTTY failed, errno = %d\n", errno);
-		exit(1);
-	}
-	if(tcsetpgrp(pty_fd, os_getpid()) < 0){
-		printk("winch_thread : tcsetpgrp failed, errno = %d\n", errno);
+	err = os_new_tty_pgrp(pty_fd, os_getpid());
+	if(err < 0){
+		printk("winch_thread : new_tty_pgrp failed, err = %d\n", -err);
 		exit(1);
 	}
 
-	if(read(pipe_fd, &c, sizeof(c)) != sizeof(c))
+	count = os_read_file(pipe_fd, &c, sizeof(c));
+	if(count != sizeof(c))
 		printk("winch_thread : failed to read synchronization byte, "
-		       "errno = %d\n", errno);
+		       "err = %d\n", -count);
 
 	while(1){
 		pause();
 
-		if(write(pipe_fd, &c, sizeof(c)) != sizeof(c)){
-			printk("winch_thread : write failed, errno = %d\n",
-			       errno);
-		}
+		count = os_write_file(pipe_fd, &c, sizeof(c));
+		if(count != sizeof(c))
+			printk("winch_thread : write failed, err = %d\n",
+			       -count);
 	}
 }
 
@@ -154,8 +106,8 @@ static int winch_tramp(int fd, void *device_data, int *fd_out)
 	char c;
 
 	err = os_pipe(fds, 1, 1);
-	if(err){
-		printk("winch_tramp : os_pipe failed, errno = %d\n", -err);
+	if(err < 0){
+		printk("winch_tramp : os_pipe failed, err = %d\n", -err);
 		return(err);
 	}
 
@@ -168,12 +120,12 @@ static int winch_tramp(int fd, void *device_data, int *fd_out)
 		return(pid);
 	}
 
-	close(fds[1]);
+	os_close_file(fds[1]);
 	*fd_out = fds[0];
-	n = read(fds[0], &c, sizeof(c));
+	n = os_read_file(fds[0], &c, sizeof(c));
 	if(n != sizeof(c)){
 		printk("winch_tramp : failed to read synchronization byte\n");
-		printk("read returned %d, errno = %d\n", n, errno);
+		printk("read failed, err = %d\n", -n);
 		printk("fd %d will not support SIGWINCH\n", fd);
 		*fd_out = -1;
 	}
@@ -183,20 +135,24 @@ static int winch_tramp(int fd, void *device_data, int *fd_out)
 void register_winch(int fd, void *device_data)
 {
 	int pid, thread, thread_fd;
+	int count;
 	char c = 1;
 
-	if(!isatty(fd)) return;
+	if(!isatty(fd))
+		return;
 
 	pid = tcgetpgrp(fd);
-	if(!CHOOSE_MODE(is_tracer_winch(pid, fd, device_data), 0) && 
-	   (pid == -1)){
+	if(!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd,
+			     device_data) && (pid == -1)){
 		thread = winch_tramp(fd, device_data, &thread_fd);
 		if(fd != -1){
 			register_winch_irq(thread_fd, fd, thread, device_data);
 
-			if(write(thread_fd, &c, sizeof(c)) != sizeof(c))
+			count = os_write_file(thread_fd, &c, sizeof(c));
+			if(count != sizeof(c))
 				printk("register_winch : failed to write "
-				       "synchronization byte\n");
+				       "synchronization byte, err = %d\n",
+					-count);
 		}
 	}
 }
diff --git a/arch/um/drivers/cow.h b/arch/um/drivers/cow.h
index d875d0435..19517312a 100644
--- a/arch/um/drivers/cow.h
+++ b/arch/um/drivers/cow.h
@@ -13,22 +13,22 @@
 #error "__BYTE_ORDER not defined"
 #endif
 
-extern int init_cow_file(int fd, char *cow_file, char *backing_file, 
-			 int sectorsize, int alignment, int *bitmap_offset_out, 
+extern int init_cow_file(int fd, char *cow_file, char *backing_file,
+			 int sectorsize, int alignment, int *bitmap_offset_out,
 			 unsigned long *bitmap_len_out, int *data_offset_out);
 
 extern int file_reader(__u64 offset, char *buf, int len, void *arg);
-extern int read_cow_header(int (*reader)(__u64, char *, int, void *), 
-			   void *arg, __u32 *version_out, 
-			   char **backing_file_out, time_t *mtime_out, 
-			   __u64 *size_out, int *sectorsize_out, 
+extern int read_cow_header(int (*reader)(__u64, char *, int, void *),
+			   void *arg, __u32 *version_out,
+			   char **backing_file_out, time_t *mtime_out,
+			   __u64 *size_out, int *sectorsize_out,
 			   __u32 *align_out, int *bitmap_offset_out);
 
-extern int write_cow_header(char *cow_file, int fd, char *backing_file, 
+extern int write_cow_header(char *cow_file, int fd, char *backing_file,
 			    int sectorsize, int alignment, long long *size);
 
 extern void cow_sizes(int version, __u64 size, int sectorsize, int align,
-		      int bitmap_offset, unsigned long *bitmap_len_out, 
+		      int bitmap_offset, unsigned long *bitmap_len_out,
 		      int *data_offset_out);
 
 #endif
diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c
index 014c2c853..d3fad2486 100644
--- a/arch/um/drivers/cow_user.c
+++ b/arch/um/drivers/cow_user.c
@@ -27,20 +27,20 @@ struct cow_header_v1 {
 #define PATH_LEN_V2 MAXPATHLEN
 
 struct cow_header_v2 {
-	unsigned long magic;
-	unsigned long version;
+	__u32 magic;
+	__u32 version;
 	char backing_file[PATH_LEN_V2];
 	time_t mtime;
 	__u64 size;
 	int sectorsize;
 };
 
-/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in 
+/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in
  * case other systems have different values for MAXPATHLEN
  */
 #define PATH_LEN_V3 4096
 
-/* Changes from V2 - 
+/* Changes from V2 -
  *	PATH_LEN_V3 as described above
  *	Explicitly specify field bit lengths for systems with different
  *		lengths for the usual C types.  Not sure whether char or
@@ -90,15 +90,15 @@ union cow_header {
 #define DIV_ROUND(x, len) (((x) + (len) - 1) / (len))
 #define ROUND_UP(x, align) DIV_ROUND(x, align) * (align)
 
-void cow_sizes(int version, __u64 size, int sectorsize, int align, 
-	       int bitmap_offset, unsigned long *bitmap_len_out, 
+void cow_sizes(int version, __u64 size, int sectorsize, int align,
+	       int bitmap_offset, unsigned long *bitmap_len_out,
 	       int *data_offset_out)
 {
 	if(version < 3){
 		*bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
 
 		*data_offset_out = bitmap_offset + *bitmap_len_out;
-		*data_offset_out = (*data_offset_out + sectorsize - 1) / 
+		*data_offset_out = (*data_offset_out + sectorsize - 1) /
 			sectorsize;
 		*data_offset_out *= sectorsize;
 	}
@@ -117,7 +117,7 @@ static int absolutize(char *to, int size, char *from)
 	int remaining;
 
 	if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
-		cow_printf("absolutize : unable to get cwd - errno = %d\n", 
+		cow_printf("absolutize : unable to get cwd - errno = %d\n",
 			   errno);
 		return(-1);
 	}
@@ -126,7 +126,7 @@ static int absolutize(char *to, int size, char *from)
 		*slash = '\0';
 		if(chdir(from)){
 			*slash = '/';
-			cow_printf("absolutize : Can't cd to '%s' - " 
+			cow_printf("absolutize : Can't cd to '%s' - "
 				   "errno = %d\n", from, errno);
 			return(-1);
 		}
@@ -158,7 +158,7 @@ static int absolutize(char *to, int size, char *from)
 	return(0);
 }
 
-int write_cow_header(char *cow_file, int fd, char *backing_file, 
+int write_cow_header(char *cow_file, int fd, char *backing_file,
 		     int sectorsize, int alignment, long long *size)
 {
 	struct cow_header_v3 *header;
@@ -183,12 +183,12 @@ int write_cow_header(char *cow_file, int fd, char *backing_file,
 	err = -EINVAL;
 	if(strlen(backing_file) > sizeof(header->backing_file) - 1){
 		cow_printf("Backing file name \"%s\" is too long - names are "
-			   "limited to %d characters\n", backing_file, 
+			   "limited to %d characters\n", backing_file,
 			   sizeof(header->backing_file) - 1);
 		goto out_free;
 	}
 
-	if(absolutize(header->backing_file, sizeof(header->backing_file), 
+	if(absolutize(header->backing_file, sizeof(header->backing_file),
 		      backing_file))
 		goto out_free;
 
@@ -234,10 +234,10 @@ int file_reader(__u64 offset, char *buf, int len, void *arg)
 
 /* XXX Need to sanity-check the values read from the header */
 
-int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, 
-		    __u32 *version_out, char **backing_file_out, 
-		    time_t *mtime_out, __u64 *size_out, 
-		    int *sectorsize_out, __u32 *align_out, 
+int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
+		    __u32 *version_out, char **backing_file_out,
+		    time_t *mtime_out, __u64 *size_out,
+		    int *sectorsize_out, __u32 *align_out,
 		    int *bitmap_offset_out)
 {
 	union cow_header *header;
@@ -310,7 +310,7 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
 	}
 	else {
 		cow_printf("read_cow_header - invalid COW version\n");
-		goto out;		
+		goto out;
 	}
 	err = -ENOMEM;
 	*backing_file_out = cow_strdup(file);
@@ -326,18 +326,18 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
 }
 
 int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize,
-		  int alignment, int *bitmap_offset_out, 
+		  int alignment, int *bitmap_offset_out,
 		  unsigned long *bitmap_len_out, int *data_offset_out)
 {
 	__u64 size, offset;
 	char zero = 0;
 	int err;
 
-	err = write_cow_header(cow_file, fd, backing_file, sectorsize, 
+	err = write_cow_header(cow_file, fd, backing_file, sectorsize,
 			       alignment, &size);
-	if(err) 
+	if(err)
 		goto out;
-	
+
 	*bitmap_offset_out = ROUND_UP(sizeof(struct cow_header_v3), alignment);
 	cow_sizes(COW_VERSION, size, sectorsize, alignment, *bitmap_offset_out,
 		  bitmap_len_out, data_offset_out);
@@ -349,9 +349,9 @@ int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize,
 		goto out;
 	}
 
-	/* does not really matter how much we write it is just to set EOF 
+	/* does not really matter how much we write it is just to set EOF
 	 * this also sets the entire COW bitmap
-	 * to zero without having to allocate it 
+	 * to zero without having to allocate it
 	 */
 	err = cow_write_file(fd, &zero, sizeof(zero));
 	if(err != sizeof(zero)){
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c
index de71aec2d..cf15b4a8b 100644
--- a/arch/um/drivers/daemon_user.c
+++ b/arch/um/drivers/daemon_user.c
@@ -53,7 +53,8 @@ static int connect_to_switch(struct daemon_data *pri)
 	struct request_v3 req;
 	int fd, n, err;
 
-	if((pri->control = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){
+	pri->control = socket(AF_UNIX, SOCK_STREAM, 0);
+	if(pri->control < 0){
 		printk("daemon_open : control socket failed, errno = %d\n", 
 		       errno);		
 		return(-errno);
@@ -67,7 +68,8 @@ static int connect_to_switch(struct daemon_data *pri)
 		goto out;
 	}
 
-	if((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0){
+	fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+	if(fd < 0){
 		printk("daemon_open : data socket failed, errno = %d\n", 
 		       errno);
 		err = -errno;
@@ -91,18 +93,18 @@ static int connect_to_switch(struct daemon_data *pri)
 	req.version = SWITCH_VERSION;
 	req.type = REQ_NEW_CONTROL;
 	req.sock = *local_addr;
-	n = write(pri->control, &req, sizeof(req));
+	n = os_write_file(pri->control, &req, sizeof(req));
 	if(n != sizeof(req)){
-		printk("daemon_open : control setup request returned %d, "
-		       "errno = %d\n", n, errno);
+		printk("daemon_open : control setup request failed, err = %d\n",
+		       -n);
 		err = -ENOTCONN;
 		goto out;		
 	}
 
-	n = read(pri->control, sun, sizeof(*sun));
+	n = os_read_file(pri->control, sun, sizeof(*sun));
 	if(n != sizeof(*sun)){
-		printk("daemon_open : read of data socket returned %d, "
-		       "errno = %d\n", n, errno);
+		printk("daemon_open : read of data socket failed, err = %d\n",
+		       -n);
 		err = -ENOTCONN;
 		goto out_close;		
 	}
@@ -111,9 +113,9 @@ static int connect_to_switch(struct daemon_data *pri)
 	return(fd);
 
  out_close:
-	close(fd);
+	os_close_file(fd);
  out:
-	close(pri->control);
+	os_close_file(pri->control);
 	return(err);
 }
 
@@ -153,8 +155,8 @@ static void daemon_remove(void *data)
 {
 	struct daemon_data *pri = data;
 
-	close(pri->fd);
-	close(pri->control);
+	os_close_file(pri->fd);
+	os_close_file(pri->control);
 	if(pri->data_addr != NULL) kfree(pri->data_addr);
 	if(pri->ctl_addr != NULL) kfree(pri->ctl_addr);
 	if(pri->local_addr != NULL) kfree(pri->local_addr);
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c
index 4ac314c1a..1c6daad92 100644
--- a/arch/um/drivers/fd.c
+++ b/arch/um/drivers/fd.c
@@ -7,6 +7,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <termios.h>
+#include <errno.h>
 #include "user.h"
 #include "user_util.h"
 #include "chan_user.h"
@@ -35,7 +36,8 @@ void *fd_init(char *str, int device, struct chan_opts *opts)
 		printk("fd_init : couldn't parse file descriptor '%s'\n", str);
 		return(NULL);
 	}
-	if((data = um_kmalloc(sizeof(*data))) == NULL) return(NULL);
+	data = um_kmalloc(sizeof(*data));
+	if(data == NULL) return(NULL);
 	*data = ((struct fd_chan) { .fd  	= n,
 				    .raw  	= opts->raw });
 	return(data);
@@ -44,10 +46,16 @@ void *fd_init(char *str, int device, struct chan_opts *opts)
 int fd_open(int input, int output, int primary, void *d, char **dev_out)
 {
 	struct fd_chan *data = d;
+	int err;
 
 	if(data->raw && isatty(data->fd)){
-		tcgetattr(data->fd, &data->tt);
-		raw(data->fd, 0);
+		CATCH_EINTR(err = tcgetattr(data->fd, &data->tt));
+		if(err)
+			return(err);
+
+		err = raw(data->fd);
+		if(err)
+			return(err);
 	}
 	sprintf(data->str, "%d", data->fd);
 	*dev_out = data->str;
@@ -57,9 +65,13 @@ int fd_open(int input, int output, int primary, void *d, char **dev_out)
 void fd_close(int fd, void *d)
 {
 	struct fd_chan *data = d;
+	int err;
 
 	if(data->raw && isatty(fd)){
-		tcsetattr(fd, TCSAFLUSH, &data->tt);
+		CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &data->tt));
+		if(err)
+			printk("Failed to restore terminal state - "
+			       "errno = %d\n", -err);
 		data->raw = 0;
 	}
 }
diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c
index cbbf41b5f..d934181b8 100644
--- a/arch/um/drivers/harddog_user.c
+++ b/arch/um/drivers/harddog_user.c
@@ -27,10 +27,10 @@ static void pre_exec(void *d)
 	dup2(data->stdin, 0);
 	dup2(data->stdout, 1);
 	dup2(data->stdout, 2);
-	close(data->stdin);
-	close(data->stdout);
-	close(data->close_me[0]);
-	close(data->close_me[1]);
+	os_close_file(data->stdin);
+	os_close_file(data->stdout);
+	os_close_file(data->close_me[0]);
+	os_close_file(data->close_me[1]);
 }
 
 int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
@@ -44,15 +44,15 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
 	char **args = NULL;
 
 	err = os_pipe(in_fds, 1, 0);
-	if(err){
-		printk("harddog_open - os_pipe failed, errno = %d\n", -err);
-		return(err);
+	if(err < 0){
+		printk("harddog_open - os_pipe failed, err = %d\n", -err);
+		goto out;
 	}
 
 	err = os_pipe(out_fds, 1, 0);
-	if(err){
-		printk("harddog_open - os_pipe failed, errno = %d\n", -err);
-		return(err);
+	if(err < 0){
+		printk("harddog_open - os_pipe failed, err = %d\n", -err);
+		goto out_close_in;
 	}
 
 	data.stdin = out_fds[0];
@@ -72,42 +72,47 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
 
 	pid = run_helper(pre_exec, &data, args, NULL);
 
-	close(out_fds[0]);
-	close(in_fds[1]);
+	os_close_file(out_fds[0]);
+	os_close_file(in_fds[1]);
 
 	if(pid < 0){
 		err = -pid;
-		printk("harddog_open - run_helper failed, errno = %d\n", err);
-		goto out;
+		printk("harddog_open - run_helper failed, errno = %d\n", -err);
+		goto out_close_out;
 	}
 
-	n = read(in_fds[0], &c, sizeof(c));
+	n = os_read_file(in_fds[0], &c, sizeof(c));
 	if(n == 0){
 		printk("harddog_open - EOF on watchdog pipe\n");
 		helper_wait(pid);
 		err = -EIO;
-		goto out;
+		goto out_close_out;
 	}
 	else if(n < 0){
 		printk("harddog_open - read of watchdog pipe failed, "
-		       "errno = %d\n", errno);
+		       "err = %d\n", -n);
 		helper_wait(pid);
-		err = -errno;
-		goto out;
+		err = n;
+		goto out_close_out;
 	}
 	*in_fd_ret = in_fds[0];
 	*out_fd_ret = out_fds[1];
 	return(0);
+
+ out_close_in:
+	os_close_file(in_fds[0]);
+	os_close_file(in_fds[1]);
+ out_close_out:
+	os_close_file(out_fds[0]);
+	os_close_file(out_fds[1]);
  out:
-	close(out_fds[1]);
-	close(in_fds[0]);
 	return(err);
 }
 
 void stop_watchdog(int in_fd, int out_fd)
 {
-	close(in_fd);
-	close(out_fd);
+	os_close_file(in_fd);
+	os_close_file(out_fd);
 }
 
 int ping_watchdog(int fd)
@@ -115,11 +120,12 @@ int ping_watchdog(int fd)
 	int n;
 	char c = '\n';
 
-	n = write(fd, &c, sizeof(c));
-	if(n < sizeof(c)){
-		printk("ping_watchdog - write failed, errno = %d\n",
-		       errno);
-		return(-errno);
+	n = os_write_file(fd, &c, sizeof(c));
+	if(n != sizeof(c)){
+		printk("ping_watchdog - write failed, err = %d\n", -n);
+		if(n < 0)
+			return(n);
+		return(-EIO);
 	}
 	return 1;
 
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c
index b512783a4..d5742783e 100644
--- a/arch/um/drivers/hostaudio_kern.c
+++ b/arch/um/drivers/hostaudio_kern.c
@@ -5,44 +5,64 @@
 
 #include "linux/config.h"
 #include "linux/module.h"
-#include "linux/version.h"
 #include "linux/init.h"
 #include "linux/slab.h"
 #include "linux/fs.h"
 #include "linux/sound.h"
 #include "linux/soundcard.h"
+#include "asm/uaccess.h"
 #include "kern_util.h"
 #include "init.h"
-#include "hostaudio.h"
+#include "os.h"
+
+struct hostaudio_state {
+  int fd;
+};
+
+struct hostmixer_state {
+  int fd;
+};
+
+#define HOSTAUDIO_DEV_DSP "/dev/sound/dsp"
+#define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer"
 
 /* Only changed from linux_main at boot time */
 char *dsp = HOSTAUDIO_DEV_DSP;
 char *mixer = HOSTAUDIO_DEV_MIXER;
 
+#define DSP_HELP \
+"    This is used to specify the host dsp device to the hostaudio driver.\n" \
+"    The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n"
+
+#define MIXER_HELP \
+"    This is used to specify the host mixer device to the hostaudio driver.\n"\
+"    The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n"
+
 #ifndef MODULE
 static int set_dsp(char *name, int *add)
 {
-	dsp = uml_strdup(name);
+	dsp = name;
 	return(0);
 }
 
-__uml_setup("dsp=", set_dsp,
-"dsp=<dsp device>\n"
-"    This is used to specify the host dsp device to the hostaudio driver.\n"
-"    The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n"
-);
+__uml_setup("dsp=", set_dsp, "dsp=<dsp device>\n" DSP_HELP);
 
 static int set_mixer(char *name, int *add)
 {
-	mixer = uml_strdup(name);
+	mixer = name;
 	return(0);
 }
 
-__uml_setup("mixer=", set_mixer,
-"mixer=<mixer device>\n"
-"    This is used to specify the host mixer device to the hostaudio driver.\n"
-"    The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n"
-);
+__uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP);
+
+#else /*MODULE*/
+
+MODULE_PARM(dsp, "s");
+MODULE_PARM_DESC(dsp, DSP_HELP);
+
+MODULE_PARM(mixer, "s");
+MODULE_PARM_DESC(mixer, MIXER_HELP);
+
 #endif
 
 /* /dev/dsp file operations */
@@ -51,23 +71,56 @@ static ssize_t hostaudio_read(struct file *file, char *buffer, size_t count,
 			      loff_t *ppos)
 {
         struct hostaudio_state *state = file->private_data;
+	void *kbuf;
+	int err;
 
 #ifdef DEBUG
         printk("hostaudio: read called, count = %d\n", count);
 #endif
 
-        return(hostaudio_read_user(state, buffer, count, ppos));
+	kbuf = kmalloc(count, GFP_KERNEL);
+	if(kbuf == NULL)
+		return(-ENOMEM);
+
+	err = os_read_file(state->fd, kbuf, count);
+	if(err < 0)
+		goto out;
+
+	if(copy_to_user(buffer, kbuf, err))
+		err = -EFAULT;
+
+ out:
+	kfree(kbuf);
+	return(err);
 }
 
 static ssize_t hostaudio_write(struct file *file, const char *buffer, 
 			       size_t count, loff_t *ppos)
 {
         struct hostaudio_state *state = file->private_data;
+	void *kbuf;
+	int err;
 
 #ifdef DEBUG
         printk("hostaudio: write called, count = %d\n", count);
 #endif
-        return(hostaudio_write_user(state, buffer, count, ppos));
+
+	kbuf = kmalloc(count, GFP_KERNEL);
+	if(kbuf == NULL)
+		return(-ENOMEM);
+
+	err = -EFAULT;
+	if(copy_from_user(kbuf, buffer, count))
+		goto out;
+
+	err = os_write_file(state->fd, kbuf, count);
+	if(err < 0)
+		goto out;
+	*ppos += err;
+
+ out:
+	kfree(kbuf);
+	return(err);
 }
 
 static unsigned int hostaudio_poll(struct file *file, 
@@ -86,12 +139,43 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file,
 			   unsigned int cmd, unsigned long arg)
 {
         struct hostaudio_state *state = file->private_data;
+	unsigned long data = 0;
+	int err;
 
 #ifdef DEBUG
         printk("hostaudio: ioctl called, cmd = %u\n", cmd);
 #endif
-
-        return(hostaudio_ioctl_user(state, cmd, arg));
+	switch(cmd){
+	case SNDCTL_DSP_SPEED:
+	case SNDCTL_DSP_STEREO:
+	case SNDCTL_DSP_GETBLKSIZE:
+	case SNDCTL_DSP_CHANNELS:
+	case SNDCTL_DSP_SUBDIVIDE:
+	case SNDCTL_DSP_SETFRAGMENT:
+		if(get_user(data, (int *) arg))
+			return(-EFAULT);
+		break;
+	default:
+		break;
+	}
+
+	err = os_ioctl_generic(state->fd, cmd, (unsigned long) &data);
+
+	switch(cmd){
+	case SNDCTL_DSP_SPEED:
+	case SNDCTL_DSP_STEREO:
+	case SNDCTL_DSP_GETBLKSIZE:
+	case SNDCTL_DSP_CHANNELS:
+	case SNDCTL_DSP_SUBDIVIDE:
+	case SNDCTL_DSP_SETFRAGMENT:
+		if(put_user(data, (int *) arg))
+			return(-EFAULT);
+		break;
+	default:
+		break;
+	}
+
+	return(err);
 }
 
 static int hostaudio_open(struct inode *inode, struct file *file)
@@ -105,17 +189,19 @@ static int hostaudio_open(struct inode *inode, struct file *file)
 #endif
 
         state = kmalloc(sizeof(struct hostaudio_state), GFP_KERNEL);
-        if(state == NULL) return(-ENOMEM);
+        if(state == NULL)
+		return(-ENOMEM);
 
         if(file->f_mode & FMODE_READ) r = 1;
         if(file->f_mode & FMODE_WRITE) w = 1;
 
-        ret = hostaudio_open_user(state, r, w, dsp);
+	ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
         if(ret < 0){
 		kfree(state);
 		return(ret);
         }
 
+	state->fd = ret;
         file->private_data = state;
         return(0);
 }
@@ -123,16 +209,15 @@ static int hostaudio_open(struct inode *inode, struct file *file)
 static int hostaudio_release(struct inode *inode, struct file *file)
 {
         struct hostaudio_state *state = file->private_data;
-        int ret;
 
 #ifdef DEBUG
         printk("hostaudio: release called\n");
 #endif
 
-        ret = hostaudio_release_user(state);
+		os_close_file(state->fd);
         kfree(state);
 
-        return(ret);
+	return(0);
 }
 
 /* /dev/mixer file operations */
@@ -146,7 +231,7 @@ static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file,
         printk("hostmixer: ioctl called\n");
 #endif
 
-        return(hostmixer_ioctl_mixdev_user(state, cmd, arg));
+	return(os_ioctl_generic(state->fd, cmd, arg));
 }
 
 static int hostmixer_open_mixdev(struct inode *inode, struct file *file)
@@ -165,9 +250,11 @@ static int hostmixer_open_mixdev(struct inode *inode, struct file *file)
         if(file->f_mode & FMODE_READ) r = 1;
         if(file->f_mode & FMODE_WRITE) w = 1;
 
-        ret = hostmixer_open_mixdev_user(state, r, w, mixer);
+	ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
         
         if(ret < 0){
+		printk("hostaudio_open_mixdev failed to open '%s', err = %d\n",
+		       dsp, -ret);
 		kfree(state);
 		return(ret);
         }
@@ -179,16 +266,15 @@ static int hostmixer_open_mixdev(struct inode *inode, struct file *file)
 static int hostmixer_release(struct inode *inode, struct file *file)
 {
         struct hostmixer_state *state = file->private_data;
-	int ret;
 
 #ifdef DEBUG
         printk("hostmixer: release called\n");
 #endif
 
-        ret = hostmixer_release_mixdev_user(state);
+		os_close_file(state->fd);
         kfree(state);
 
-        return(ret);
+	return(0);
 }
 
 
@@ -225,7 +311,8 @@ MODULE_LICENSE("GPL");
 
 static int __init hostaudio_init_module(void)
 {
-        printk(KERN_INFO "UML Audio Relay\n");
+        printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n",
+	       dsp, mixer);
 
 	module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1);
         if(module_data.dev_audio < 0){
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 92efc73ca..c6b77fccd 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -6,8 +6,8 @@
 #include "linux/sched.h"
 #include "linux/slab.h"
 #include "linux/list.h"
+#include "linux/interrupt.h"
 #include "linux/devfs_fs_kernel.h"
-#include "asm/irq.h"
 #include "asm/uaccess.h"
 #include "chan_kern.h"
 #include "irq_user.h"
@@ -16,38 +16,55 @@
 #include "user_util.h"
 #include "kern_util.h"
 #include "os.h"
+#include "irq_kern.h"
 
 #define LINE_BUFSIZE 4096
 
-void line_interrupt(int irq, void *data, struct pt_regs *unused)
+static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused)
 {
 	struct line *dev = data;
 
 	if(dev->count > 0) 
 		chan_interrupt(&dev->chan_list, &dev->task, dev->tty, irq, 
 			       dev);
+	return IRQ_HANDLED;
 }
 
-void line_timer_cb(void *arg)
+static void line_timer_cb(void *arg)
 {
 	struct line *dev = arg;
 
 	line_interrupt(dev->driver->read_irq, dev, NULL);
 }
 
-static void buffer_data(struct line *line, const char *buf, int len)
+static int write_room(struct line *dev)
 {
-	int end;
+	int n;
+
+	if(dev->buffer == NULL) return(LINE_BUFSIZE - 1);
+
+	n = dev->head - dev->tail;
+	if(n <= 0) n = LINE_BUFSIZE + n;
+	return(n - 1);
+}
+
+static int buffer_data(struct line *line, const char *buf, int len)
+{
+	int end, room;
 
 	if(line->buffer == NULL){
 		line->buffer = kmalloc(LINE_BUFSIZE, GFP_ATOMIC);
 		if(line->buffer == NULL){
 			printk("buffer_data - atomic allocation failed\n");
-			return;
+			return(0);
 		}
 		line->head = line->buffer;
 		line->tail = line->buffer;
 	}
+
+	room = write_room(line);
+	len = (len > room) ? room : len;
+
 	end = line->buffer + LINE_BUFSIZE - line->tail;
 	if(len < end){
 		memcpy(line->tail, buf, len);
@@ -56,10 +73,11 @@ static void buffer_data(struct line *line, const char *buf, int len)
 	else {
 		memcpy(line->tail, buf, end);
 		buf += end;
-		len -= end;
-		memcpy(line->buffer, buf, len);
-		line->tail = line->buffer + len;
+		memcpy(line->buffer, buf, len - end);
+		line->tail = line->buffer + len - end;
 	}
+
+	return(len);
 }
 
 static int flush_buffer(struct line *line)
@@ -95,7 +113,7 @@ int line_write(struct line *lines, struct tty_struct *tty, int from_user,
 	struct line *line;
 	char *new;
 	unsigned long flags;
-	int n, err, i;
+	int n, err, i, ret = 0;
 
 	if(tty->stopped) return 0;
 
@@ -104,9 +122,13 @@ int line_write(struct line *lines, struct tty_struct *tty, int from_user,
 		if(new == NULL)
 			return(0);
 		n = copy_from_user(new, buf, len);
-		if(n == len)
-			return(-EFAULT);
 		buf = new;
+		if(n == len){
+			len = -EFAULT;
+			goto out_free;
+		}
+
+		len -= n;
 	}
 
 	i = tty->index;
@@ -115,41 +137,50 @@ int line_write(struct line *lines, struct tty_struct *tty, int from_user,
 	down(&line->sem);
 	if(line->head != line->tail){
 		local_irq_save(flags);
-		buffer_data(line, buf, len);
+		ret += buffer_data(line, buf, len);
 		err = flush_buffer(line);
 		local_irq_restore(flags);
 		if(err <= 0)
-			goto out;
+			goto out_up;
 	}
 	else {
 		n = write_chan(&line->chan_list, buf, len, 
 			       line->driver->write_irq);
 		if(n < 0){
-			len = n;
-			goto out;
+			ret = n;
+			goto out_up;
 		}
-		if(n < len)
-			buffer_data(line, buf + n, len - n);
+
+		len -= n;
+		ret += n;
+		if(len > 0)
+			ret += buffer_data(line, buf + n, len);
 	}
- out:
+ out_up:
 	up(&line->sem);
-	return(len);
+ out_free:
+	if(from_user)
+		kfree(buf);
+	return(ret);
 }
 
-void line_write_interrupt(int irq, void *data, struct pt_regs *unused)
+static irqreturn_t line_write_interrupt(int irq, void *data,
+					struct pt_regs *unused)
 {
 	struct line *dev = data;
 	struct tty_struct *tty = dev->tty;
 	int err;
 
 	err = flush_buffer(dev);
-	if(err == 0) return;
+	if(err == 0)
+		return(IRQ_NONE);
 	else if(err < 0){
 		dev->head = dev->buffer;
 		dev->tail = dev->buffer;
 	}
 
-	if(tty == NULL) return;
+	if(tty == NULL)
+		return(IRQ_NONE);
 
 	if(test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
 	   (tty->ldisc.write_wakeup != NULL))
@@ -161,21 +192,9 @@ void line_write_interrupt(int irq, void *data, struct pt_regs *unused)
 	 * writes.
 	 */
 
-	if (waitqueue_active(&tty->write_wait))
+	if(waitqueue_active(&tty->write_wait))
 		wake_up_interruptible(&tty->write_wait);
-
-}
-
-int line_write_room(struct tty_struct *tty)
-{
-	struct line *dev = tty->driver_data;
-	int n;
-
-	if(dev->buffer == NULL) return(LINE_BUFSIZE - 1);
-
-	n = dev->head - dev->tail;
-	if(n <= 0) n = LINE_BUFSIZE + n;
-	return(n - 1);
+	return(IRQ_HANDLED);
 }
 
 int line_setup_irq(int fd, int input, int output, void *data)
@@ -305,20 +324,20 @@ int line_setup(struct line *lines, int num, char *init, int all_allowed)
 		if(*end != '='){
 			printk(KERN_ERR "line_setup failed to parse \"%s\"\n", 
 			       init);
-			return(1);
+			return(0);
 		}
 		init = end;
 	}
 	init++;
 	if((n >= 0) && (n >= num)){
 		printk("line_setup - %d out of range ((0 ... %d) allowed)\n",
-		       n, num);
-		return(1);
+		       n, num - 1);
+		return(0);
 	}
 	else if(n >= 0){
 		if(lines[n].count > 0){
 			printk("line_setup - device %d is open\n", n);
-			return(1);
+			return(0);
 		}
 		if(lines[n].init_pri <= INIT_ONE){
 			lines[n].init_pri = INIT_ONE;
@@ -332,7 +351,7 @@ int line_setup(struct line *lines, int num, char *init, int all_allowed)
 	else if(!all_allowed){
 		printk("line_setup - can't configure all devices from "
 		       "mconsole\n");
-		return(1);
+		return(0);
 	}
 	else {
 		for(i = 0; i < num; i++){
@@ -346,7 +365,7 @@ int line_setup(struct line *lines, int num, char *init, int all_allowed)
 			}
 		}
 	}
-	return(0);
+	return(1);
 }
 
 int line_config(struct line *lines, int num, char *str)
@@ -357,7 +376,7 @@ int line_config(struct line *lines, int num, char *str)
 		printk("line_config - uml_strdup failed\n");
 		return(-ENOMEM);
 	}
-	return(line_setup(lines, num, new, 0));
+	return(!line_setup(lines, num, new, 0));
 }
 
 int line_get_config(char *name, struct line *lines, int num, char *str, 
@@ -369,7 +388,7 @@ int line_get_config(char *name, struct line *lines, int num, char *str,
 
 	dev = simple_strtoul(name, &end, 0);
 	if((*end != '\0') || (end == name)){
-		*error_out = "line_setup failed to parse device number";
+		*error_out = "line_get_config failed to parse device number";
 		return(0);
 	}
 
@@ -379,15 +398,15 @@ int line_get_config(char *name, struct line *lines, int num, char *str,
 	}
 
 	line = &lines[dev];
+
 	down(&line->sem);
-	
 	if(!line->valid)
 		CONFIG_CHUNK(str, size, n, "none", 1);
 	else if(line->count == 0)
 		CONFIG_CHUNK(str, size, n, line->init_str, 1);
 	else n = chan_config_string(&line->chan_list, str, size, error_out);
-
 	up(&line->sem);
+
 	return(n);
 }
 
@@ -396,7 +415,14 @@ int line_remove(struct line *lines, int num, char *str)
 	char config[sizeof("conxxxx=none\0")];
 
 	sprintf(config, "%s=none", str);
-	return(line_setup(lines, num, config, 0));
+	return(!line_setup(lines, num, config, 0));
+}
+
+int line_write_room(struct tty_struct *tty)
+{
+	struct line *dev = tty->driver_data;
+
+	return(write_room(dev));
 }
 
 struct tty_driver *line_register_devfs(struct lines *set,
@@ -412,7 +438,8 @@ struct tty_driver *line_register_devfs(struct lines *set,
 		return NULL;
 
 	driver->driver_name = line_driver->name;
-	driver->name = line_driver->devfs_name;
+	driver->name = line_driver->device_name;
+	driver->devfs_name = line_driver->devfs_name;
 	driver->major = line_driver->major;
 	driver->minor_start = line_driver->minor_start;
 	driver->type = line_driver->type;
@@ -432,7 +459,7 @@ struct tty_driver *line_register_devfs(struct lines *set,
 
 	for(i = 0; i < nlines; i++){
 		if(!lines[i].valid) 
-			tty_unregister_devfs(driver, i);
+			tty_unregister_device(driver, i);
 	}
 
 	mconsole_register_dev(&line_driver->mc);
@@ -465,24 +492,25 @@ struct winch {
 	struct line *line;
 };
 
-void winch_interrupt(int irq, void *data, struct pt_regs *unused)
+irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
 {
 	struct winch *winch = data;
 	struct tty_struct *tty;
 	int err;
 	char c;
 
-	err = generic_read(winch->fd, &c, NULL);
-	if(err < 0){
-		if(err != -EAGAIN){
-			printk("winch_interrupt : read failed, errno = %d\n", 
-			       -err);
-			printk("fd %d is losing SIGWINCH support\n", 
-			       winch->tty_fd);
-			free_irq(irq, data);
-			return;
+	if(winch->fd != -1){
+		err = generic_read(winch->fd, &c, NULL);
+		if(err < 0){
+			if(err != -EAGAIN){
+				printk("winch_interrupt : read failed, "
+				       "errno = %d\n", -err);
+				printk("fd %d is losing SIGWINCH support\n",
+				       winch->tty_fd);
+				return(IRQ_HANDLED);
+			}
+			goto out;
 		}
-		goto out;
 	}
 	tty = winch->line->tty;
 	if(tty != NULL){
@@ -492,7 +520,9 @@ void winch_interrupt(int irq, void *data, struct pt_regs *unused)
 		kill_pg(tty->pgrp, SIGWINCH, 1);
 	}
  out:
-	reactivate_fd(winch->fd, WINCH_IRQ);
+	if(winch->fd != -1)
+		reactivate_fd(winch->fd, WINCH_IRQ);
+	return(IRQ_HANDLED);
 }
 
 DECLARE_MUTEX(winch_handler_sem);
@@ -529,7 +559,10 @@ static void winch_cleanup(void)
 
 	list_for_each(ele, &winch_handlers){
 		winch = list_entry(ele, struct winch, list);
-		close(winch->fd);
+		if(winch->fd != -1){
+			deactivate_fd(winch->fd, WINCH_IRQ);
+			os_close_file(winch->fd);
+		}
 		if(winch->pid != -1) 
 			os_kill_process(winch->pid, 1);
 	}
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c
index 58e5db630..0fe1d9fa9 100644
--- a/arch/um/drivers/mcast_user.c
+++ b/arch/um/drivers/mcast_user.c
@@ -23,6 +23,7 @@
 #include "kern_util.h"
 #include "user_util.h"
 #include "user.h"
+#include "os.h"
 
 #define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
 
@@ -62,7 +63,8 @@ static int mcast_open(void *data)
 		goto out;
 	}
 
-	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (fd < 0){
 		printk("mcast_open : data socket failed, errno = %d\n", 
 		       errno);
 		fd = -ENOMEM;
@@ -72,7 +74,7 @@ static int mcast_open(void *data)
 	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
 		printk("mcast_open: SO_REUSEADDR failed, errno = %d\n",
 			errno);
-		close(fd);
+		os_close_file(fd);
 		fd = -EINVAL;
 		goto out;
 	}
@@ -82,7 +84,7 @@ static int mcast_open(void *data)
 		       sizeof(pri->ttl)) < 0) {
 		printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n",
 			errno);
-		close(fd);
+		os_close_file(fd);
 		fd = -EINVAL;
 		goto out;
 	}
@@ -91,7 +93,7 @@ static int mcast_open(void *data)
 	if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
 		printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n",
 			errno);
-		close(fd);
+		os_close_file(fd);
 		fd = -EINVAL;
 		goto out;
 	}
@@ -99,7 +101,7 @@ static int mcast_open(void *data)
 	/* bind socket to mcast address */
 	if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) {
 		printk("mcast_open : data bind failed, errno = %d\n", errno);
-		close(fd);
+		os_close_file(fd);
 		fd = -EINVAL;
 		goto out;
 	}		
@@ -115,7 +117,7 @@ static int mcast_open(void *data)
 		       "interface on the host.\n");
 		printk("eth0 should be configured in order to use the "
 		       "multicast transport.\n");
-		close(fd);
+		os_close_file(fd);
 		fd = -EINVAL;
 	}
 
@@ -137,7 +139,7 @@ static void mcast_close(int fd, void *data)
 			errno);
 	}
 
-	close(fd);
+	os_close_file(fd);
 }
 
 int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri)
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index b12cb189d..9076c0603 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -15,6 +15,9 @@
 #include "linux/sysrq.h"
 #include "linux/workqueue.h"
 #include "linux/module.h"
+#include "linux/file.h"
+#include "linux/fs.h"
+#include "linux/namei.h"
 #include "linux/proc_fs.h"
 #include "asm/irq.h"
 #include "asm/uaccess.h"
@@ -27,6 +30,7 @@
 #include "init.h"
 #include "os.h"
 #include "umid.h"
+#include "irq_kern.h"
 
 static int do_unlink_socket(struct notifier_block *notifier, 
 			    unsigned long what, void *data)
@@ -47,27 +51,26 @@ static struct notifier_block reboot_notifier = {
 
 LIST_HEAD(mc_requests);
 
-void mc_work_proc(void *unused)
+static void mc_work_proc(void *unused)
 {
 	struct mconsole_entry *req;
 	unsigned long flags;
-	int done;
 
-	do {
+	while(!list_empty(&mc_requests)){
 		local_save_flags(flags);
 		req = list_entry(mc_requests.next, struct mconsole_entry, 
 				 list);
 		list_del(&req->list);
-		done = list_empty(&mc_requests);
 		local_irq_restore(flags);
 		req->request.cmd->handler(&req->request);
 		kfree(req);
-	} while(!done);
+	}
 }
 
 DECLARE_WORK(mconsole_work, mc_work_proc, NULL);
 
-void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t mconsole_interrupt(int irq, void *dev_id,
+				      struct pt_regs *regs)
 {
 	int fd;
 	struct mconsole_entry *new;
@@ -75,9 +78,10 @@ void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
 	fd = (int) dev_id;
 	while (mconsole_get_request(fd, &req)){
-		if(req.cmd->as_interrupt) (*req.cmd->handler)(&req);
+		if(req.cmd->context == MCONSOLE_INTR)
+			(*req.cmd->handler)(&req);
 		else {
-			new = kmalloc(sizeof(req), GFP_ATOMIC);
+			new = kmalloc(sizeof(*new), GFP_ATOMIC);
 			if(new == NULL)
 				mconsole_reply(&req, "Out of memory", 1, 0);
 			else {
@@ -86,8 +90,10 @@ void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 			}
 		}
 	}
-	if(!list_empty(&mc_requests)) schedule_work(&mconsole_work);
+	if(!list_empty(&mc_requests))
+		schedule_work(&mconsole_work);
 	reactivate_fd(fd, MCONSOLE_IRQ);
+	return(IRQ_HANDLED);
 }
 
 void mconsole_version(struct mc_request *req)
@@ -100,20 +106,109 @@ void mconsole_version(struct mc_request *req)
 	mconsole_reply(req, version, 0, 0);
 }
 
+void mconsole_log(struct mc_request *req)
+{
+	int len;
+	char *ptr = req->request.data;
+
+	ptr += strlen("log ");
+
+	len = req->len - (ptr - req->request.data);
+	printk("%.*s", len, ptr);
+	mconsole_reply(req, "", 0, 0);
+}
+
+void mconsole_proc(struct mc_request *req)
+{
+	struct nameidata nd;
+	struct file_system_type *proc;
+	struct super_block *super;
+	struct file *file;
+	int n, err;
+	char *ptr = req->request.data, *buf;
+
+	ptr += strlen("proc");
+	while(isspace(*ptr)) ptr++;
+
+	proc = get_fs_type("proc");
+	if(proc == NULL){
+		mconsole_reply(req, "procfs not registered", 1, 0);
+		goto out;
+	}
+
+	super = (*proc->get_sb)(proc, 0, NULL, NULL);
+	put_filesystem(proc);
+	if(super == NULL){
+		mconsole_reply(req, "Failed to get procfs superblock", 1, 0);
+		goto out;
+	}
+	up_write(&super->s_umount);
+
+	nd.dentry = super->s_root;
+	nd.mnt = NULL;
+	nd.flags = O_RDONLY + 1;
+	nd.last_type = LAST_ROOT;
+
+	err = link_path_walk(ptr, &nd);
+	if(err){
+		mconsole_reply(req, "Failed to look up file", 1, 0);
+		goto out_kill;
+	}
+
+	file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
+	if(IS_ERR(file)){
+		mconsole_reply(req, "Failed to open file", 1, 0);
+		goto out_kill;
+	}
+
+	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if(buf == NULL){
+		mconsole_reply(req, "Failed to allocate buffer", 1, 0);
+		goto out_fput;
+	}
+
+	if((file->f_op != NULL) && (file->f_op->read != NULL)){
+		do {
+			n = (*file->f_op->read)(file, buf, PAGE_SIZE - 1,
+						&file->f_pos);
+			if(n >= 0){
+				buf[n] = '\0';
+				mconsole_reply(req, buf, 0, (n > 0));
+			}
+			else {
+				mconsole_reply(req, "Read of file failed",
+					       1, 0);
+				goto out_free;
+			}
+		} while(n > 0);
+	}
+	else mconsole_reply(req, "", 0, 0);
+
+ out_free:
+	kfree(buf);
+ out_fput:
+	fput(file);
+ out_kill:
+	deactivate_super(super);
+ out: ;
+}
+
 #define UML_MCONSOLE_HELPTEXT \
-"Commands:
-    version - Get kernel version
-    help - Print this message
-    halt - Halt UML
-    reboot - Reboot UML
-    config <dev>=<config> - Add a new device to UML; 
-	same syntax as command line
-    config <dev> - Query the configuration of a device
-    remove <dev> - Remove a device from UML
-    sysrq <letter> - Performs the SysRq action controlled by the letter
-    cad - invoke the Ctl-Alt-Del handler
-    stop - pause the UML; it will do nothing until it receives a 'go'
-    go - continue the UML after a 'stop'
+"Commands: \n\
+    version - Get kernel version \n\
+    help - Print this message \n\
+    halt - Halt UML \n\
+    reboot - Reboot UML \n\
+    config <dev>=<config> - Add a new device to UML;  \n\
+	same syntax as command line \n\
+    config <dev> - Query the configuration of a device \n\
+    remove <dev> - Remove a device from UML \n\
+    sysrq <letter> - Performs the SysRq action controlled by the letter \n\
+    cad - invoke the Ctl-Alt-Del handler \n\
+    stop - pause the UML; it will do nothing until it receives a 'go' \n\
+    go - continue the UML after a 'stop' \n\
+    log <string> - make UML enter <string> into the kernel log\n\
+    proc <file> - returns the contents of the UML's /proc/<file>\n\
 "
 
 void mconsole_help(struct mc_request *req)
@@ -279,8 +374,8 @@ void mconsole_sysrq(struct mc_request *req)
 	ptr += strlen("sysrq");
 	while(isspace(*ptr)) ptr++;
 
-	handle_sysrq(*ptr, &current->thread.regs, NULL);
 	mconsole_reply(req, "", 0, 0);
+	handle_sysrq(*ptr, &current->thread.regs, NULL);
 }
 #else
 void mconsole_sysrq(struct mc_request *req)
@@ -302,7 +397,7 @@ int mconsole_init(void)
 	if(umid_file_name("mconsole", file, sizeof(file))) return(-1);
 	snprintf(mconsole_socket_name, sizeof(file), "%s", file);
 
-	sock = create_unix_socket(file, sizeof(file));
+	sock = os_create_unix_socket(file, sizeof(file), 1);
 	if (sock < 0){
 		printk("Failed to initialize management console\n");
 		return(1);
@@ -344,11 +439,16 @@ static int write_proc_mconsole(struct file *file, const char *buffer,
 	if(buf == NULL) 
 		return(-ENOMEM);
 
-	if(copy_from_user(buf, buffer, count))
-		return(-EFAULT);
+	if(copy_from_user(buf, buffer, count)){
+		count = -EFAULT;
+		goto out;
+	}
+
 	buf[count] = '\0';
 
 	mconsole_notify(notify_socket, MCONSOLE_USER_NOTIFY, buf, count);
+ out:
+	kfree(buf);
 	return(count);
 }
 
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index 11b09a96f..fe5afb132 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -18,16 +18,18 @@
 #include "umid.h"
 
 static struct mconsole_command commands[] = {
-	{ "version", mconsole_version, 1 },
-	{ "halt", mconsole_halt, 0 },
-	{ "reboot", mconsole_reboot, 0 },
-	{ "config", mconsole_config, 0 },
-	{ "remove", mconsole_remove, 0 },
-	{ "sysrq", mconsole_sysrq, 1 },
-	{ "help", mconsole_help, 1 },
-	{ "cad", mconsole_cad, 1 },
-	{ "stop", mconsole_stop, 0 },
-	{ "go", mconsole_go, 1 },
+	{ "version", mconsole_version, MCONSOLE_INTR },
+	{ "halt", mconsole_halt, MCONSOLE_PROC },
+	{ "reboot", mconsole_reboot, MCONSOLE_PROC },
+	{ "config", mconsole_config, MCONSOLE_PROC },
+	{ "remove", mconsole_remove, MCONSOLE_PROC },
+	{ "sysrq", mconsole_sysrq, MCONSOLE_INTR },
+	{ "help", mconsole_help, MCONSOLE_INTR },
+	{ "cad", mconsole_cad, MCONSOLE_INTR },
+	{ "stop", mconsole_stop, MCONSOLE_PROC },
+	{ "go", mconsole_go, MCONSOLE_INTR },
+	{ "log", mconsole_log, MCONSOLE_INTR },
+	{ "proc", mconsole_proc, MCONSOLE_PROC },
 };
 
 /* Initialized in mconsole_init, which is an initcall */
@@ -139,6 +141,7 @@ int mconsole_reply(struct mc_request *req, char *str, int err, int more)
 		memcpy(reply.data, str, len);
 		reply.data[len] = '\0';
 		total -= len;
+		str += len;
 		reply.len = len + 1;
 
 		len = sizeof(reply) + reply.len - sizeof(reply.data);
diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c
index 628d8f804..1862691b9 100644
--- a/arch/um/drivers/mmapper_kern.c
+++ b/arch/um/drivers/mmapper_kern.c
@@ -120,7 +120,10 @@ static int __init mmapper_init(void)
 	printk(KERN_INFO "Mapper v0.1\n");
 
 	v_buf = (char *) find_iomem("mmapper", &mmapper_size);
-	if(mmapper_size == 0) return(0);
+	if(mmapper_size == 0){
+		printk(KERN_ERR "mmapper_init - find_iomem failed\n");
+		return(0);
+	}
 
 	p_buf = __pa(v_buf);
 
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index a52b79dfd..c686a39ea 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -19,6 +19,8 @@
 #include "linux/inetdevice.h"
 #include "linux/ctype.h"
 #include "linux/bootmem.h"
+#include "linux/ethtool.h"
+#include "asm/uaccess.h"
 #include "user_util.h"
 #include "kern_util.h"
 #include "net_kern.h"
@@ -26,6 +28,7 @@
 #include "mconsole_kern.h"
 #include "init.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 
 static spinlock_t opened_lock = SPIN_LOCK_UNLOCKED;
 LIST_HEAD(opened);
@@ -37,7 +40,8 @@ static int uml_net_rx(struct net_device *dev)
 	struct sk_buff *skb;
 
 	/* If we can't allocate memory, try again next round. */
-	if ((skb = dev_alloc_skb(dev->mtu)) == NULL) {
+	skb = dev_alloc_skb(dev->mtu);
+	if (skb == NULL) {
 		lp->stats.rx_dropped++;
 		return 0;
 	}
@@ -61,14 +65,14 @@ static int uml_net_rx(struct net_device *dev)
 	return pkt_len;
 }
 
-void uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_id;
 	struct uml_net_private *lp = dev->priv;
 	int err;
 
 	if(!netif_running(dev))
-		return;
+		return(IRQ_NONE);
 
 	spin_lock(&lp->lock);
 	while((err = uml_net_rx(dev)) > 0) ;
@@ -83,6 +87,7 @@ void uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
  out:
 	spin_unlock(&lp->lock);
+	return(IRQ_HANDLED);
 }
 
 static int uml_net_open(struct net_device *dev)
@@ -124,6 +129,13 @@ static int uml_net_open(struct net_device *dev)
 	spin_lock(&opened_lock);
 	list_add(&lp->list, &opened);
 	spin_unlock(&opened_lock);
+
+	/* clear buffer - it can happen that the host side of the interface
+	 * is full when we get here.  In this case, new data is never queued,
+	 * SIGIOs never arrive, and the net never works.
+	 */
+	while((err = uml_net_rx(dev)) > 0) ;
+
  out:
 	spin_unlock(&lp->lock);
 	return(err);
@@ -237,7 +249,30 @@ static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
 
 static int uml_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-	return(-EINVAL);
+	static const struct ethtool_drvinfo info = {
+		.cmd     = ETHTOOL_GDRVINFO,
+		.driver  = "uml virtual ethernet",
+		.version = "42",
+	};
+	void *useraddr;
+	u32 ethcmd;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		useraddr = ifr->ifr_data;
+		if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
+			return -EFAULT;
+		switch (ethcmd) {
+		case ETHTOOL_GDRVINFO:
+			if (copy_to_user(useraddr, &info, sizeof(info)))
+				return -EFAULT;
+			return 0;
+		default:
+			return -EOPNOTSUPP;
+		}
+	default:
+		return -EINVAL;
+	}
 }
 
 void uml_net_user_timer_expire(unsigned long _conn)
@@ -250,37 +285,6 @@ void uml_net_user_timer_expire(unsigned long _conn)
 #endif
 }
 
-/*
- * default do nothing hard header packet routines for struct net_device init.
- * real ethernet transports will overwrite with real routines.
- */
-static int uml_net_hard_header(struct sk_buff *skb, struct net_device *dev,
-                 unsigned short type, void *daddr, void *saddr, unsigned len)
-{
-	return(0); /* no change */
-}
-
-static int uml_net_rebuild_header(struct sk_buff *skb)
-{
-	return(0); /* ignore */ 
-}
-
-static int uml_net_header_cache(struct neighbour *neigh, struct hh_cache *hh)
-{
-	return(-1); /* fail */
-}
-
-static void uml_net_header_cache_update(struct hh_cache *hh,
-                 struct net_device *dev, unsigned char * haddr)
-{
-	/* ignore */
-}
-
-static int uml_net_header_parse(struct sk_buff *skb, unsigned char *haddr)
-{
-	return(0); /* nothing */
-}
-
 static spinlock_t devices_lock = SPIN_LOCK_UNLOCKED;
 static struct list_head devices = LIST_HEAD_INIT(devices);
 
@@ -290,7 +294,7 @@ static int eth_configure(int n, void *init, char *mac,
 	struct uml_net *device;
 	struct net_device *dev;
 	struct uml_net_private *lp;
-	int err, size;
+	int save, err, size;
 
 	size = transport->private_size + sizeof(struct uml_net_private) + 
 		sizeof(((struct uml_net_private *) 0)->user);
@@ -332,12 +336,6 @@ static int eth_configure(int n, void *init, char *mac,
 	snprintf(dev->name, sizeof(dev->name), "eth%d", n);
 	device->dev = dev;
 
-        dev->hard_header = uml_net_hard_header;
-        dev->rebuild_header = uml_net_rebuild_header;
-        dev->hard_header_cache = uml_net_header_cache;
-        dev->header_cache_update= uml_net_header_cache_update;
-        dev->hard_header_parse = uml_net_header_parse;
-
 	(*transport->kern->init)(dev, init);
 
 	dev->mtu = transport->user->max_packet;
@@ -364,21 +362,29 @@ static int eth_configure(int n, void *init, char *mac,
 	}
 	lp = dev->priv;
 
-	INIT_LIST_HEAD(&lp->list);
-	spin_lock_init(&lp->lock);
-	lp->dev = dev;
-	lp->fd = -1;
-	lp->mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0 };
-	lp->have_mac = device->have_mac;
-	lp->protocol = transport->kern->protocol;
-	lp->open = transport->user->open;
-	lp->close = transport->user->close;
-	lp->remove = transport->user->remove;
-	lp->read = transport->kern->read;
-	lp->write = transport->kern->write;
-	lp->add_address = transport->user->add_address;
-	lp->delete_address = transport->user->delete_address;
-	lp->set_mtu = transport->user->set_mtu;
+	/* lp.user is the first four bytes of the transport data, which
+	 * has already been initialized.  This structure assignment will
+	 * overwrite that, so we make sure that .user gets overwritten with
+	 * what it already has.
+	 */
+	save = lp->user[0];
+	*lp = ((struct uml_net_private)
+		{ .list  		= LIST_HEAD_INIT(lp->list),
+		  .lock 		= SPIN_LOCK_UNLOCKED,
+		  .dev 			= dev,
+		  .fd 			= -1,
+		  .mac 			= { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0},
+		  .have_mac 		= device->have_mac,
+		  .protocol 		= transport->kern->protocol,
+		  .open 		= transport->user->open,
+		  .close 		= transport->user->close,
+		  .remove 		= transport->user->remove,
+		  .read 		= transport->kern->read,
+		  .write 		= transport->kern->write,
+		  .add_address 		= transport->user->add_address,
+		  .delete_address  	= transport->user->delete_address,
+		  .set_mtu 		= transport->user->set_mtu,
+		  .user  		= { save } });
 
 	init_timer(&lp->tl);
 	lp->tl.function = uml_net_user_timer_expire;
@@ -611,7 +617,8 @@ static int net_remove(char *str)
 	unregister_netdev(dev);
 
 	list_del(&device->list);
-	free_netdev(device);
+	kfree(device);
+	free_netdev(dev);
 	return(0);
 }
 
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 75a83e9e1..2e4e1d49f 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -26,8 +26,7 @@ int tap_open_common(void *dev, char *gate_addr)
 	if(gate_addr == NULL) return(0);
 	if(sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], 
 		  &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4){
-		printk("Invalid tap IP address - '%s'\n", 
-		       gate_addr);
+		printk("Invalid tap IP address - '%s'\n", gate_addr);
 		return(-EINVAL);
 	}
 	return(0);
@@ -60,18 +59,18 @@ void read_output(int fd, char *output, int len)
 	}
 		
 	*output = '\0';
-	if(read(fd, &remain, sizeof(remain)) != sizeof(remain)){
-		printk("read_output - read of length failed, errno = %d\n",
-		       errno);
+	n = os_read_file(fd, &remain, sizeof(remain));
+	if(n != sizeof(remain)){
+		printk("read_output - read of length failed, err = %d\n", -n);
 		return;
 	}
 
 	while(remain != 0){
 		n = (remain < len) ? remain : len;
-		actual = read(fd, output, n);
+		actual = os_read_file(fd, output, n);
 		if(actual != n){
 			printk("read_output - read of data failed, "
-			       "errno = %d\n", errno);
+			       "err = %d\n", -actual);
 			return;
 		}
 		remain -= actual;
@@ -83,13 +82,12 @@ int net_read(int fd, void *buf, int len)
 {
 	int n;
 
-	while(((n = read(fd,  buf,  len)) < 0) && (errno == EINTR)) ;
+	n = os_read_file(fd,  buf,  len);
 
-	if(n < 0){
-		if(errno == EAGAIN) return(0);
-		return(-errno);
-	}
-	else if(n == 0) return(-ENOTCONN);
+	if(n == -EAGAIN)
+		return(0);
+	else if(n == 0)
+		return(-ENOTCONN);
 	return(n);
 }
 
@@ -112,13 +110,13 @@ int net_write(int fd, void *buf, int len)
 {
 	int n;
 
-	while(((n = write(fd, buf, len)) < 0) && (errno == EINTR)) ;
-	if(n < 0){
-		if(errno == EAGAIN) return(0);
-		return(-errno);
-	}
-	else if(n == 0) return(-ENOTCONN);
-	return(n);	
+	n = os_write_file(fd, buf, len);
+
+	if(n == -EAGAIN)
+		return(0);
+	else if(n == 0)
+		return(-ENOTCONN);
+	return(n);
 }
 
 int net_send(int fd, void *buf, int len)
@@ -157,7 +155,7 @@ static void change_pre_exec(void *arg)
 {
 	struct change_pre_exec_data *data = arg;
 
-	close(data->close_me);
+	os_close_file(data->close_me);
 	dup2(data->stdout, 1);
 }
 
@@ -167,17 +165,18 @@ static int change_tramp(char **argv, char *output, int output_len)
 	struct change_pre_exec_data pe_data;
 
 	err = os_pipe(fds, 1, 0);
-	if(err){
-		printk("change_tramp - pipe failed, errno = %d\n", -err);
+	if(err < 0){
+		printk("change_tramp - pipe failed, err = %d\n", -err);
 		return(err);
 	}
 	pe_data.close_me = fds[0];
 	pe_data.stdout = fds[1];
 	pid = run_helper(change_pre_exec, &pe_data, argv, NULL);
 
-	close(fds[1]);
+	os_close_file(fds[1]);
 	read_output(fds[0], output, output_len);
-	waitpid(pid, NULL, 0);	
+
+	CATCH_EINTR(err = waitpid(pid, NULL, 0));
 	return(pid);
 }
 
diff --git a/arch/um/drivers/null.c b/arch/um/drivers/null.c
index d361554eb..66b2fbe3d 100644
--- a/arch/um/drivers/null.c
+++ b/arch/um/drivers/null.c
@@ -5,7 +5,6 @@
 
 #include <stdlib.h>
 #include <errno.h>
-#include <fcntl.h>
 #include "chan_user.h"
 #include "os.h"
 
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
index 3c4463019..4044053cd 100644
--- a/arch/um/drivers/port_kern.c
+++ b/arch/um/drivers/port_kern.c
@@ -6,6 +6,7 @@
 #include "linux/list.h"
 #include "linux/sched.h"
 #include "linux/slab.h"
+#include "linux/interrupt.h"
 #include "linux/irq.h"
 #include "linux/spinlock.h"
 #include "linux/errno.h"
@@ -14,6 +15,7 @@
 #include "kern_util.h"
 #include "kern.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 #include "port.h"
 #include "init.h"
 #include "os.h"
@@ -38,21 +40,21 @@ struct port_dev {
 struct connection {
 	struct list_head list;
 	int fd;
- 	int helper_pid;
+	int helper_pid;
 	int socket[2];
 	int telnetd_pid;
 	struct port_list *port;
 };
 
-static void pipe_interrupt(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t pipe_interrupt(int irq, void *data, struct pt_regs *regs)
 {
 	struct connection *conn = data;
 	int fd;
 
- 	fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
+	fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
 	if(fd < 0){
 		if(fd == -EAGAIN)
-			return;
+			return(IRQ_NONE);
 
 		printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", 
 		       -fd);
@@ -65,6 +67,7 @@ static void pipe_interrupt(int irq, void *data, struct pt_regs *regs)
 	list_add(&conn->list, &conn->port->connections);
 
 	up(&conn->port->sem);
+	return(IRQ_HANDLED);
 }
 
 static int port_accept(struct port_list *port)
@@ -102,8 +105,7 @@ static int port_accept(struct port_list *port)
 	}
 
 	list_add(&conn->list, &port->pending);
-	ret = 1;
-	goto out;
+	return(1);
 
  out_free:
 	kfree(conn);
@@ -138,12 +140,13 @@ void port_work_proc(void *unused)
 
 DECLARE_WORK(port_work, port_work_proc, NULL);
 
-static void port_interrupt(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t port_interrupt(int irq, void *data, struct pt_regs *regs)
 {
 	struct port_list *port = data;
 
 	port->has_connection = 1;
 	schedule_work(&port_work);
+	return(IRQ_HANDLED);
 } 
 
 void *port_data(int port_num)
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index 7a37cf6a2..1e8592ec1 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -47,10 +47,12 @@ void *port_init(char *str, int device, struct chan_opts *opts)
 		return(NULL);
 	}
 
-	if((kern_data = port_data(port)) == NULL) 
+	kern_data = port_data(port);
+	if(kern_data == NULL)
 		return(NULL);
 
-	if((data = um_kmalloc(sizeof(*data))) == NULL) 
+	data = um_kmalloc(sizeof(*data));
+	if(data == NULL)
 		goto err;
 
 	*data = ((struct port_chan) { .raw  		= opts->raw,
@@ -74,12 +76,17 @@ void port_free(void *d)
 int port_open(int input, int output, int primary, void *d, char **dev_out)
 {
 	struct port_chan *data = d;
-	int fd;
+	int fd, err;
 
 	fd = port_wait(data->kernel_data);
 	if((fd >= 0) && data->raw){
-		tcgetattr(fd, &data->tt);
-		raw(fd, 0);
+		CATCH_EINTR(err = tcgetattr(fd, &data->tt));
+		if(err)
+			return(err);
+
+		err = raw(fd);
+		if(err)
+			return(err);
 	}
 	*dev_out = data->dev;
 	return(fd);
@@ -90,7 +97,7 @@ void port_close(int fd, void *d)
 	struct port_chan *data = d;
 
 	port_remove_dev(data->kernel_data);
-	close(fd);
+	os_close_file(fd);
 }
 
 int port_console_write(int fd, const char *buf, int n, void *d)
@@ -130,11 +137,15 @@ int port_listen_fd(int port)
 		goto out;
 	}
   
-	if((listen(fd, 1) < 0) || (os_set_fd_block(fd, 0))){
+	if(listen(fd, 1) < 0){
 		err = -errno;
 		goto out;
 	}
 
+	err = os_set_fd_block(fd, 0);
+	if(err < 0)
+		goto out;
+
 	return(fd);
  out:
 	os_close_file(fd);
@@ -153,10 +164,10 @@ void port_pre_exec(void *arg)
 	dup2(data->sock_fd, 0);
 	dup2(data->sock_fd, 1);
 	dup2(data->sock_fd, 2);
-	close(data->sock_fd);
+	os_close_file(data->sock_fd);
 	dup2(data->pipe_fd, 3);
 	os_shutdown_socket(3, 1, 0);
-	close(data->pipe_fd);
+	os_close_file(data->pipe_fd);
 }
 
 int port_connection(int fd, int *socket, int *pid_out)
@@ -166,11 +177,12 @@ int port_connection(int fd, int *socket, int *pid_out)
 			 "/usr/lib/uml/port-helper", NULL };
 	struct port_pre_exec_data data;
 
-	if((new = os_accept_connection(fd)) < 0)
-		return(-errno);
+	new = os_accept_connection(fd);
+	if(new < 0)
+		return(new);
 
 	err = os_pipe(socket, 0, 0);
-	if(err) 
+	if(err < 0)
 		goto out_close;
 
 	data = ((struct port_pre_exec_data)
@@ -186,11 +198,11 @@ int port_connection(int fd, int *socket, int *pid_out)
 
  out_shutdown:
 	os_shutdown_socket(socket[0], 1, 1);
-	close(socket[0]);
+	os_close_file(socket[0]);
 	os_shutdown_socket(socket[1], 1, 1);	
-	close(socket[1]);
+	os_close_file(socket[1]);
  out_close:
-	close(new);
+	os_close_file(new);
 	return(err);
 }
 
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c
index 027405386..c4634b500 100644
--- a/arch/um/drivers/pty.c
+++ b/arch/um/drivers/pty.c
@@ -7,12 +7,12 @@
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <termios.h>
 #include "chan_user.h"
 #include "user.h"
 #include "user_util.h"
 #include "kern_util.h"
+#include "os.h"
 
 struct pty_chan {
 	void (*announce)(char *dev_name, int dev);
@@ -26,7 +26,8 @@ void *pty_chan_init(char *str, int device, struct chan_opts *opts)
 {
 	struct pty_chan *data;
 
-	if((data = um_kmalloc(sizeof(*data))) == NULL) return(NULL);
+	data = um_kmalloc(sizeof(*data));
+	if(data == NULL) return(NULL);
 	*data = ((struct pty_chan) { .announce  	= opts->announce, 
 				     .dev  		= device,
 				     .raw  		= opts->raw });
@@ -37,15 +38,21 @@ int pts_open(int input, int output, int primary, void *d, char **dev_out)
 {
 	struct pty_chan *data = d;
 	char *dev;
-	int fd;
+	int fd, err;
 
-	if((fd = get_pty()) < 0){
+	fd = get_pty();
+	if(fd < 0){
 		printk("open_pts : Failed to open pts\n");
 		return(-errno);
 	}
 	if(data->raw){
-		tcgetattr(fd, &data->tt);
-		raw(fd, 0);
+		CATCH_EINTR(err = tcgetattr(fd, &data->tt));
+		if(err)
+			return(err);
+
+		err = raw(fd);
+		if(err)
+			return(err);
 	}
 
 	dev = ptsname(fd);
@@ -57,29 +64,27 @@ int pts_open(int input, int output, int primary, void *d, char **dev_out)
 
 int getmaster(char *line)
 {
-	struct stat stb;
 	char *pty, *bank, *cp;
-	int master;
+	int master, err;
 
 	pty = &line[strlen("/dev/ptyp")];
 	for (bank = "pqrs"; *bank; bank++) {
 		line[strlen("/dev/pty")] = *bank;
 		*pty = '0';
-		if (stat(line, &stb) < 0)
+		if (os_stat_file(line, NULL) < 0)
 			break;
 		for (cp = "0123456789abcdef"; *cp; cp++) {
 			*pty = *cp;
-			master = open(line, O_RDWR);
+			master = os_open_file(line, of_rdwr(OPENFLAGS()), 0);
 			if (master >= 0) {
 				char *tp = &line[strlen("/dev/")];
-				int ok;
 
 				/* verify slave side is usable */
 				*tp = 't';
-				ok = access(line, R_OK|W_OK) == 0;
+				err = os_access(line, OS_ACC_RW_OK);
 				*tp = 'p';
-				if (ok) return(master);
-				(void) close(master);
+				if(err == 0) return(master);
+				(void) os_close_file(master);
 			}
 		}
 	}
@@ -89,13 +94,19 @@ int getmaster(char *line)
 int pty_open(int input, int output, int primary, void *d, char **dev_out)
 {
 	struct pty_chan *data = d;
-	int fd;
+	int fd, err;
 	char dev[sizeof("/dev/ptyxx\0")] = "/dev/ptyxx";
 
 	fd = getmaster(dev);
-	if(fd < 0) return(-errno);
+	if(fd < 0)
+		return(-errno);
+
+	if(data->raw){
+		err = raw(fd);
+		if(err)
+			return(err);
+	}
 	
-	if(data->raw) raw(fd, 0);
 	if(data->announce) (*data->announce)(dev, data->dev);
 
 	sprintf(data->dev_name, "%s", dev);
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index 782cf522b..3d8d4ca36 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -4,11 +4,9 @@
 #include <stddef.h>
 #include <sched.h>
 #include <string.h>
-#include <sys/fcntl.h>
-#include <sys/errno.h>
+#include <errno.h>
 #include <sys/termios.h>
 #include <sys/wait.h>
-#include <sys/ioctl.h>
 #include <sys/signal.h>
 #include "user_util.h"
 #include "kern_util.h"
@@ -65,9 +63,9 @@ static void slip_pre_exec(void *arg)
 {
 	struct slip_pre_exec_data *data = arg;
 
-	if(data->stdin != -1) dup2(data->stdin, 0);
+	if(data->stdin >= 0) dup2(data->stdin, 0);
 	dup2(data->stdout, 1);
-	if(data->close_me != -1) close(data->close_me);
+	if(data->close_me >= 0) os_close_file(data->close_me);
 }
 
 static int slip_tramp(char **argv, int fd)
@@ -77,8 +75,8 @@ static int slip_tramp(char **argv, int fd)
 	int status, pid, fds[2], err, output_len;
 
 	err = os_pipe(fds, 1, 0);
-	if(err){
-		printk("slip_tramp : pipe failed, errno = %d\n", -err);
+	if(err < 0){
+		printk("slip_tramp : pipe failed, err = %d\n", -err);
 		return(err);
 	}
 
@@ -96,16 +94,18 @@ static int slip_tramp(char **argv, int fd)
 			printk("slip_tramp : failed to allocate output "
 			       "buffer\n");
 
-		close(fds[1]);
+		os_close_file(fds[1]);
 		read_output(fds[0], output, output_len);
 		if(output != NULL){
 			printk("%s", output);
 			kfree(output);
 		}
-		if(waitpid(pid, &status, 0) < 0) err = errno;
+		CATCH_EINTR(err = waitpid(pid, &status, 0));
+		if(err < 0)
+			err = errno;
 		else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)){
 			printk("'%s' didn't exit with status 0\n", argv[0]);
-			err = EINVAL;
+			err = -EINVAL;
 		}
 	}
 	return(err);
@@ -118,15 +118,17 @@ static int slip_open(void *data)
 	char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
 	char *argv[] = { "uml_net", version_buf, "slip", "up", gate_buf, 
 			 NULL };
-	int sfd, mfd, disc, sencap, err;
+	int sfd, mfd, err;
 
-	if((mfd = get_pty()) < 0){
-		printk("umn : Failed to open pty\n");
-		return(-1);
+	mfd = get_pty();
+	if(mfd < 0){
+		printk("umn : Failed to open pty, err = %d\n", -mfd);
+		return(mfd);
 	}
-	if((sfd = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0)) < 0){
-		printk("Couldn't open tty for slip line\n");
-		return(-1);
+	sfd = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0);
+	if(sfd < 0){
+		printk("Couldn't open tty for slip line, err = %d\n", -sfd);
+		return(sfd);
 	}
 	if(set_up_tty(sfd)) return(-1);
 	pri->slave = sfd;
@@ -138,28 +140,23 @@ static int slip_open(void *data)
 
 		err = slip_tramp(argv, sfd);
 
-		if(err != 0){
-			printk("slip_tramp failed - errno = %d\n", err);
-			return(-err);
+		if(err < 0){
+			printk("slip_tramp failed - err = %d\n", -err);
+			return(err);
 		}
-		if(ioctl(pri->slave, SIOCGIFNAME, pri->name) < 0){
-			printk("SIOCGIFNAME failed, errno = %d\n", errno);
-			return(-errno);
+		err = os_get_ifname(pri->slave, pri->name);
+		if(err < 0){
+			printk("get_ifname failed, err = %d\n", -err);
+			return(err);
 		}
 		iter_addresses(pri->dev, open_addr, pri->name);
 	}
 	else {
-		disc = N_SLIP;
-		if(ioctl(sfd, TIOCSETD, &disc) < 0){
-			printk("Failed to set slip line discipline - "
-			       "errno = %d\n", errno);
-			return(-errno);
-		}
-		sencap = 0;
-		if(ioctl(sfd, SIOCSIFENCAP, &sencap) < 0){
-			printk("Failed to set slip encapsulation - "
-			       "errno = %d\n", errno);
-			return(-errno);
+		err = os_set_slip(sfd);
+		if(err < 0){
+			printk("Failed to set slip discipline encapsulation - "
+			       "err = %d\n", -err);
+			return(err);
 		}
 	}
 	return(mfd);
@@ -181,9 +178,9 @@ static void slip_close(int fd, void *data)
 	err = slip_tramp(argv, -1);
 
 	if(err != 0)
-		printk("slip_tramp failed - errno = %d\n", err);
-	close(fd);
-	close(pri->slave);
+		printk("slip_tramp failed - errno = %d\n", -err);
+	os_close_file(fd);
+	os_close_file(pri->slave);
 	pri->slave = -1;
 }
 
@@ -243,7 +240,7 @@ static void slip_add_addr(unsigned char *addr, unsigned char *netmask,
 {
 	struct slip_data *pri = data;
 
-	if(pri->slave == -1) return;
+	if(pri->slave < 0) return;
 	open_addr(addr, netmask, pri->name);
 }
 
@@ -252,7 +249,7 @@ static void slip_del_addr(unsigned char *addr, unsigned char *netmask,
 {
 	struct slip_data *pri = data;
 
-	if(pri->slave == -1) return;
+	if(pri->slave < 0) return;
 	close_addr(addr, netmask, pri->name);
 }
 
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index cbdbb65c3..c322515c7 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -4,8 +4,7 @@
 #include <stddef.h>
 #include <sched.h>
 #include <string.h>
-#include <sys/fcntl.h>
-#include <sys/errno.h>
+#include <errno.h>
 #include <sys/wait.h>
 #include <sys/signal.h>
 #include "user_util.h"
@@ -48,15 +47,15 @@ static int slirp_tramp(char **argv, int fd)
 
 	return(pid);
 }
- 
+
+/* XXX This is just a trivial wrapper around os_pipe */
 static int slirp_datachan(int *mfd, int *sfd)
 {
 	int fds[2], err;
 
 	err = os_pipe(fds, 1, 1);
-	if(err){
-		printk("slirp_datachan: Failed to open pipe, errno = %d\n",
-		       -err);
+	if(err < 0){
+		printk("slirp_datachan: Failed to open pipe, err = %d\n", -err);
 		return(err);
 	}
 
@@ -77,7 +76,7 @@ static int slirp_open(void *data)
 	pid = slirp_tramp(pri->argw.argv, sfd);
 
 	if(pid < 0){
-		printk("slirp_tramp failed - errno = %d\n", pid);
+		printk("slirp_tramp failed - errno = %d\n", -pid);
 		os_close_file(sfd);	
 		os_close_file(mfd);	
 		return(pid);
@@ -97,8 +96,8 @@ static void slirp_close(int fd, void *data)
 	struct slirp_data *pri = data;
 	int status,err;
 
-	close(fd);
-	close(pri->slave);
+	os_close_file(fd);
+	os_close_file(pri->slave);
 
 	pri->slave = -1;
 
@@ -114,13 +113,13 @@ static void slirp_close(int fd, void *data)
 	}
 #endif
 
-	err = waitpid(pri->pid, &status, WNOHANG);
-	if(err<0) {
+	CATCH_EINTR(err = waitpid(pri->pid, &status, WNOHANG));
+	if(err < 0) {
 		printk("slirp_close: waitpid returned %d\n", errno);
 		return;
 	}
 
-	if(err==0) {
+	if(err == 0) {
 		printk("slirp_close: process %d has not exited\n");
 		return;
 	}
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index 826a77c8c..4a3586f0d 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -10,6 +10,7 @@
 #include "linux/major.h"
 #include "linux/mm.h"
 #include "linux/init.h"
+#include "linux/console.h"
 #include "asm/termbits.h"
 #include "asm/irq.h"
 #include "line.h"
@@ -53,8 +54,9 @@ static int ssl_remove(char *str);
 
 static struct line_driver driver = {
 	.name 			= "UML serial line",
-	.devfs_name 		= "tts/%d",
-	.major 			= TTYAUX_MAJOR,
+	.device_name 		= "ttS",
+	.devfs_name 		= "tts/",
+	.major 			= TTY_MAJOR,
 	.minor_start 		= 64,
 	.type 		 	= TTY_DRIVER_TYPE_SERIAL,
 	.subtype 	 	= 0,
@@ -149,6 +151,9 @@ static int ssl_ioctl(struct tty_struct *tty, struct file * file,
 	case TCSETSW:
 	case TCGETA:
 	case TIOCMGET:
+	case TCSBRK:
+	case TCSBRKP:
+	case TIOCMSET:
 		ret = -ENOIOCTLCMD;
 		break;
 	default:
@@ -212,6 +217,37 @@ static struct tty_operations ssl_ops = {
  */
 static int ssl_init_done = 0;
 
+static void ssl_console_write(struct console *c, const char *string,
+			      unsigned len)
+{
+	struct line *line = &serial_lines[c->index];
+	if(ssl_init_done)
+		down(&line->sem);
+	console_write_chan(&line->chan_list, string, len);
+	if(ssl_init_done)
+		up(&line->sem);
+}
+
+static struct tty_driver *ssl_console_device(struct console *c, int *index)
+{
+	*index = c->index;
+	return ssl_driver;
+}
+
+static int ssl_console_setup(struct console *co, char *options)
+{
+	return(0);
+}
+
+static struct console ssl_cons = {
+	name:		"ttyS",
+	write:		ssl_console_write,
+	device:		ssl_console_device,
+	setup:		ssl_console_setup,
+	flags:		CON_PRINTBUFFER,
+	index:		-1,
+};
+
 int ssl_init(void)
 {
 	char *new_title;
@@ -227,17 +263,18 @@ int ssl_init(void)
 	new_title = add_xterm_umid(opts.xterm_title);
 	if(new_title != NULL) opts.xterm_title = new_title;
 
+	register_console(&ssl_cons);
 	ssl_init_done = 1;
 	return(0);
 }
 
-__initcall(ssl_init);
+late_initcall(ssl_init);
 
 static int ssl_chan_setup(char *str)
 {
-	line_setup(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0]),
-		   str, 1);
-	return(1);
+	return(line_setup(serial_lines,
+			  sizeof(serial_lines)/sizeof(serial_lines[0]),
+			  str, 1));
 }
 
 __setup("ssl", ssl_chan_setup);
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 3ae795edf..54e6a57c8 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -17,8 +17,8 @@
 #include "linux/init.h"
 #include "linux/interrupt.h"
 #include "linux/slab.h"
+#include "linux/hardirq.h"
 #include "asm/current.h"
-#include "asm/hardirq.h"
 #include "asm/irq.h"
 #include "stdio_console.h"
 #include "line.h"
@@ -83,7 +83,8 @@ static int con_remove(char *str);
 
 static struct line_driver driver = {
 	.name 			= "UML console",
-	.devfs_name 		= "vc/%d",
+	.device_name 		= "tty",
+	.devfs_name 		= "vc/",
 	.major 			= TTY_MAJOR,
 	.minor_start 		= 0,
 	.type 		 	= TTY_DRIVER_TYPE_CONSOLE,
@@ -159,6 +160,15 @@ static int chars_in_buffer(struct tty_struct *tty)
 
 static int con_init_done = 0;
 
+static struct tty_operations console_ops = {
+	.open 	 		= con_open,
+	.close 	 		= con_close,
+	.write 	 		= con_write,
+	.chars_in_buffer 	= chars_in_buffer,
+	.set_termios 		= set_termios,
+	.write_room		= line_write_room,
+};
+
 int stdio_init(void)
 {
 	char *new_title;
@@ -166,7 +176,8 @@ int stdio_init(void)
 	printk(KERN_INFO "Initializing stdio console driver\n");
 
 	console_driver = line_register_devfs(&console_lines, &driver,
-				&console_ops, vts, sizeof(vts)/sizeof(vts[0]));
+					     &console_ops, vts,
+					     sizeof(vts)/sizeof(vts[0]));
 
 	lines_init(vts, sizeof(vts)/sizeof(vts[0]));
 
@@ -178,52 +189,53 @@ int stdio_init(void)
 	return(0);
 }
 
-__initcall(stdio_init);
+late_initcall(stdio_init);
 
-static void console_write(struct console *console, const char *string, 
+static void uml_console_write(struct console *console, const char *string,
 			  unsigned len)
 {
-	if(con_init_done) down(&vts[console->index].sem);
-	console_write_chan(&vts[console->index].chan_list, string, len);
-	if(con_init_done) up(&vts[console->index].sem);
-}
+	struct line *line = &vts[console->index];
 
-static struct tty_operations console_ops = {
-	.open 	 		= con_open,
-	.close 	 		= con_close,
-	.write 	 		= con_write,
-	.chars_in_buffer 	= chars_in_buffer,
-	.set_termios 		= set_termios,
-	.write_room		= line_write_room,
-};
+	if(con_init_done)
+		down(&line->sem);
+	console_write_chan(&line->chan_list, string, len);
+	if(con_init_done)
+		up(&line->sem);
+}
 
-static struct tty_driver *console_device(struct console *c, int *index)
+static struct tty_driver *uml_console_device(struct console *c, int *index)
 {
 	*index = c->index;
 	return console_driver;
 }
 
-static int console_setup(struct console *co, char *options)
+static int uml_console_setup(struct console *co, char *options)
 {
 	return(0);
 }
 
-static struct console stdiocons = INIT_CONSOLE("tty", console_write, 
-					       console_device, console_setup,
-					       CON_PRINTBUFFER);
+static struct console stdiocons = {
+	name:		"tty",
+	write:		uml_console_write,
+	device:		uml_console_device,
+	setup:		uml_console_setup,
+	flags:		CON_PRINTBUFFER,
+	index:		-1,
+};
 
-static void __init stdio_console_init(void)
+static int __init stdio_console_init(void)
 {
 	INIT_LIST_HEAD(&vts[0].chan_list);
 	list_add(&init_console_chan.list, &vts[0].chan_list);
 	register_console(&stdiocons);
+	return(0);
 }
+
 console_initcall(stdio_console_init);
 
 static int console_chan_setup(char *str)
 {
-	line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1);
-	return(1);
+	return(line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1));
 }
 
 __setup("con", console_chan_setup);
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c
index e9eb9e362..dd008aa8f 100644
--- a/arch/um/drivers/tty.c
+++ b/arch/um/drivers/tty.c
@@ -5,7 +5,6 @@
 
 #include <stdio.h>
 #include <termios.h>
-#include <fcntl.h>
 #include <errno.h>
 #include <unistd.h>
 #include "chan_user.h"
@@ -30,7 +29,8 @@ void *tty_chan_init(char *str, int device, struct chan_opts *opts)
 	}
 	str++;
 
-	if((data = um_kmalloc(sizeof(*data))) == NULL) 
+	data = um_kmalloc(sizeof(*data));
+	if(data == NULL)
 		return(NULL);
 	*data = ((struct tty_chan) { .dev 	= str,
 				     .raw 	= opts->raw });
@@ -41,13 +41,18 @@ void *tty_chan_init(char *str, int device, struct chan_opts *opts)
 int tty_open(int input, int output, int primary, void *d, char **dev_out)
 {
 	struct tty_chan *data = d;
-	int fd;
+	int fd, err;
 
 	fd = os_open_file(data->dev, of_set_rw(OPENFLAGS(), input, output), 0);
 	if(fd < 0) return(fd);
 	if(data->raw){
-		tcgetattr(fd, &data->tt);
-		raw(fd, 0);
+		CATCH_EINTR(err = tcgetattr(fd, &data->tt));
+		if(err)
+			return(err);
+
+		err = raw(fd);
+		if(err)
+			return(err);
 	}
 
 	*dev_out = data->dev;
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 0c3890b3e..53fba09ad 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -8,6 +8,13 @@
  * old style ubd by setting UBD_SHIFT to 0
  * 2002-09-27...2002-10-18 massive tinkering for 2.5
  * partitions have changed in 2.5
+ * 2003-01-29 more tinkering for 2.5.59-1
+ * This should now address the sysfs problems and has
+ * the symlink for devfs to allow for booting with
+ * the common /dev/ubd/discX/... names rather than
+ * only /dev/ubdN/discN this version also has lots of
+ * clean ups preparing for ubd-many.
+ * James McMechan
  */
 
 #define MAJOR_NR UBD_MAJOR
@@ -40,9 +47,12 @@
 #include "mconsole_kern.h"
 #include "init.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 #include "ubd_user.h"
 #include "2_5compat.h"
 #include "os.h"
+#include "mem.h"
+#include "mem_kern.h"
 
 static spinlock_t ubd_io_lock = SPIN_LOCK_UNLOCKED;
 static spinlock_t ubd_lock = SPIN_LOCK_UNLOCKED;
@@ -56,6 +66,10 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
 
 #define MAX_DEV (8)
 
+/* Changed in early boot */
+static int ubd_do_mmap = 0;
+#define UBD_MMAP_BLOCK_SIZE PAGE_SIZE
+
 static struct block_device_operations ubd_blops = {
         .owner		= THIS_MODULE,
         .open		= ubd_open,
@@ -67,7 +81,7 @@ static struct block_device_operations ubd_blops = {
 static request_queue_t *ubd_queue;
 
 /* Protected by ubd_lock */
-static int fake_major = 0;
+static int fake_major = MAJOR_NR;
 
 static struct gendisk *ubd_gendisk[MAX_DEV];
 static struct gendisk *fake_gendisk[MAX_DEV];
@@ -96,13 +110,19 @@ struct cow {
 
 struct ubd {
 	char *file;
-	int is_dir;
 	int count;
 	int fd;
 	__u64 size;
 	struct openflags boot_openflags;
 	struct openflags openflags;
+	int no_cow;
 	struct cow cow;
+
+	int map_writes;
+	int map_reads;
+	int nomap_writes;
+	int nomap_reads;
+	int write_maps;
 };
 
 #define DEFAULT_COW { \
@@ -115,21 +135,28 @@ struct ubd {
 
 #define DEFAULT_UBD { \
 	.file = 		NULL, \
-	.is_dir =		0, \
 	.count =		0, \
 	.fd =			-1, \
 	.size =			-1, \
 	.boot_openflags =	OPEN_FLAGS, \
 	.openflags =		OPEN_FLAGS, \
+        .no_cow =               0, \
         .cow =			DEFAULT_COW, \
+	.map_writes		= 0, \
+	.map_reads		= 0, \
+	.nomap_writes		= 0, \
+	.nomap_reads		= 0, \
+	.write_maps		= 0, \
 }
 
 struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD };
 
 static int ubd0_init(void)
 {
-	if(ubd_dev[0].file == NULL)
-		ubd_dev[0].file = "root_fs";
+	struct ubd *dev = &ubd_dev[0];
+
+	if(dev->file == NULL)
+		dev->file = "root_fs";
 	return(0);
 }
 
@@ -196,19 +223,46 @@ __uml_help(fake_ide_setup,
 "    Create ide0 entries that map onto ubd devices.\n\n"
 );
 
+static int parse_unit(char **ptr)
+{
+	char *str = *ptr, *end;
+	int n = -1;
+
+	if(isdigit(*str)) {
+		n = simple_strtoul(str, &end, 0);
+		if(end == str)
+			return(-1);
+		*ptr = end;
+	}
+	else if (('a' <= *str) && (*str <= 'h')) {
+		n = *str - 'a';
+		str++;
+		*ptr = str;
+	}
+	return(n);
+}
+
 static int ubd_setup_common(char *str, int *index_out)
 {
+	struct ubd *dev;
 	struct openflags flags = global_openflags;
 	char *backing_file;
 	int n, err;
 
 	if(index_out) *index_out = -1;
-	n = *str++;
+	n = *str;
 	if(n == '='){
-		static int fake_major_allowed = 1;
 		char *end;
 		int major;
 
+		str++;
+		if(!strcmp(str, "mmap")){
+			CHOOSE_MODE(printk("mmap not supported by the ubd "
+					   "driver in tt mode\n"),
+				    ubd_do_mmap = 1);
+			return(0);
+		}
+
 		if(!strcmp(str, "sync")){
 			global_openflags.s = 1;
 			return(0);
@@ -220,20 +274,14 @@ static int ubd_setup_common(char *str, int *index_out)
 			return(1);
 		}
 
-		if(!fake_major_allowed){
-			printk(KERN_ERR "Can't assign a fake major twice\n");
-			return(1);
-		}
-
 		err = 1;
  		spin_lock(&ubd_lock);
- 		if(!fake_major_allowed){
+ 		if(fake_major != MAJOR_NR){
  			printk(KERN_ERR "Can't assign a fake major twice\n");
  			goto out1;
  		}
  
  		fake_major = major;
-		fake_major_allowed = 0;
 
 		printk(KERN_INFO "Setting extra ubd major number to %d\n",
 		       major);
@@ -243,25 +291,23 @@ static int ubd_setup_common(char *str, int *index_out)
 		return(err);
 	}
 
-	if(n < '0'){
-		printk(KERN_ERR "ubd_setup : index out of range\n"); }
-
-	if((n >= '0') && (n <= '9')) n -= '0';
-	else if((n >= 'a') && (n <= 'z')) n -= 'a';
-	else {
-		printk(KERN_ERR "ubd_setup : device syntax invalid\n");
+	n = parse_unit(&str);
+	if(n < 0){
+		printk(KERN_ERR "ubd_setup : couldn't parse unit number "
+		       "'%s'\n", str);
 		return(1);
 	}
 	if(n >= MAX_DEV){
-		printk(KERN_ERR "ubd_setup : index out of range "
-		       "(%d devices)\n", MAX_DEV);	
+		printk(KERN_ERR "ubd_setup : index %d out of range "
+		       "(%d devices, from 0 to %d)\n", n, MAX_DEV, MAX_DEV - 1);
 		return(1);
 	}
 
 	err = 1;
 	spin_lock(&ubd_lock);
 
-	if(ubd_dev[n].file != NULL){
+	dev = &ubd_dev[n];
+	if(dev->file != NULL){
 		printk(KERN_ERR "ubd_setup : device already configured\n");
 		goto out2;
 	}
@@ -276,6 +322,11 @@ static int ubd_setup_common(char *str, int *index_out)
 		flags.s = 1;
 		str++;
 	}
+	if (*str == 'd'){
+		dev->no_cow = 1;
+		str++;
+	}
+
 	if(*str++ != '='){
 		printk(KERN_ERR "ubd_setup : Expected '='\n");
 		goto out2;
@@ -284,14 +335,17 @@ static int ubd_setup_common(char *str, int *index_out)
 	err = 0;
 	backing_file = strchr(str, ',');
 	if(backing_file){
-		*backing_file = '\0';
-		backing_file++;
-	}
-	ubd_dev[n].file = str;
-	if(ubd_is_dir(ubd_dev[n].file))
-		ubd_dev[n].is_dir = 1;
-	ubd_dev[n].cow.file = backing_file;
-	ubd_dev[n].boot_openflags = flags;
+		if(dev->no_cow)
+			printk(KERN_ERR "Can't specify both 'd' and a "
+			       "cow file\n");
+		else {
+			*backing_file = '\0';
+			backing_file++;
+		}
+	}
+	dev->file = str;
+	dev->cow.file = backing_file;
+	dev->boot_openflags = flags;
  out2:
 	spin_unlock(&ubd_lock);
 	return(err);
@@ -321,8 +375,7 @@ __uml_help(ubd_setup,
 static int fakehd_set = 0;
 static int fakehd(char *str)
 {
-	printk(KERN_INFO 
-	       "fakehd : Changing ubd name to \"hd\".\n");
+	printk(KERN_INFO "fakehd : Changing ubd name to \"hd\".\n");
 	fakehd_set = 1;
 	return 1;
 }
@@ -343,14 +396,13 @@ int thread_fd = -1;
  */
 int intr_count = 0;
 
-static void ubd_finish(struct request *req, int error)
+/* call ubd_finish if you need to serialize */
+static void __ubd_finish(struct request *req, int error)
 {
 	int nsect;
 
 	if(error){
- 		spin_lock(&ubd_io_lock);
 		end_request(req, 0);
- 		spin_unlock(&ubd_io_lock);
 		return;
 	}
 	nsect = req->current_nr_sectors;
@@ -359,41 +411,57 @@ static void ubd_finish(struct request *req, int error)
 	req->errors = 0;
 	req->nr_sectors -= nsect;
 	req->current_nr_sectors = 0;
-	spin_lock(&ubd_io_lock);
 	end_request(req, 1);
+}
+
+static inline void ubd_finish(struct request *req, int error)
+{
+ 	spin_lock(&ubd_io_lock);
+	__ubd_finish(req, error);
 	spin_unlock(&ubd_io_lock);
 }
 
+/* Called without ubd_io_lock held */
 static void ubd_handler(void)
 {
 	struct io_thread_req req;
 	struct request *rq = elv_next_request(ubd_queue);
-	int n;
+	int n, err;
 
 	do_ubd = NULL;
 	intr_count++;
 	n = read_ubd_fs(thread_fd, &req, sizeof(req));
 	if(n != sizeof(req)){
 		printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, "
-		       "errno = %d\n", os_getpid(), -n);
+		       "err = %d\n", os_getpid(), -n);
 		spin_lock(&ubd_io_lock);
 		end_request(rq, 0);
 		spin_unlock(&ubd_io_lock);
 		return;
 	}
         
-        if((req.offset != ((__u64) (rq->sector)) << 9) ||
-	   (req.length != (rq->current_nr_sectors) << 9))
+	if((req.op != UBD_MMAP) &&
+	   ((req.offset != ((__u64) (rq->sector)) << 9) ||
+	    (req.length != (rq->current_nr_sectors) << 9)))
 		panic("I/O op mismatch");
 	
+	if(req.map_fd != -1){
+		err = physmem_subst_mapping(req.buffer, req.map_fd,
+					    req.map_offset, 1);
+		if(err)
+			printk("ubd_handler - physmem_subst_mapping failed, "
+			       "err = %d\n", -err);
+	}
+
 	ubd_finish(rq, req.error);
 	reactivate_fd(thread_fd, UBD_IRQ);	
 	do_ubd_request(ubd_queue);
 }
 
-static void ubd_intr(int irq, void *dev, struct pt_regs *unused)
+static irqreturn_t ubd_intr(int irq, void *dev, struct pt_regs *unused)
 {
 	ubd_handler();
+	return(IRQ_HANDLED);
 }
 
 /* Only changed by ubd_init, which is an initcall. */
@@ -417,10 +485,14 @@ static int ubd_file_size(struct ubd *dev, __u64 *size_out)
 
 static void ubd_close(struct ubd *dev)
 {
+	if(ubd_do_mmap)
+		physmem_forget_descriptor(dev->fd);
 	os_close_file(dev->fd);
 	if(dev->cow.file == NULL)
 		return;
 
+	if(ubd_do_mmap)
+		physmem_forget_descriptor(dev->cow.fd);
 	os_close_file(dev->cow.fd);
 	vfree(dev->cow.bitmap);
 	dev->cow.bitmap = NULL;
@@ -429,18 +501,20 @@ static void ubd_close(struct ubd *dev)
 static int ubd_open_dev(struct ubd *dev)
 {
 	struct openflags flags;
-	int err, n, create_cow, *create_ptr;
+	char **back_ptr;
+	int err, create_cow, *create_ptr;
 
+	dev->openflags = dev->boot_openflags;
 	create_cow = 0;
 	create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL;
-	dev->fd = open_ubd_file(dev->file, &dev->openflags, &dev->cow.file,
+	back_ptr = dev->no_cow ? NULL : &dev->cow.file;
+	dev->fd = open_ubd_file(dev->file, &dev->openflags, back_ptr,
 				&dev->cow.bitmap_offset, &dev->cow.bitmap_len, 
 				&dev->cow.data_offset, create_ptr);
 
 	if((dev->fd == -ENOENT) && create_cow){
-		n = dev - ubd_dev;
 		dev->fd = create_cow_file(dev->file, dev->cow.file, 
-					  dev->openflags, 1 << 9,
+					  dev->openflags, 1 << 9, PAGE_SIZE,
 					  &dev->cow.bitmap_offset, 
 					  &dev->cow.bitmap_len,
 					  &dev->cow.data_offset);
@@ -455,13 +529,17 @@ static int ubd_open_dev(struct ubd *dev)
 	if(dev->cow.file != NULL){
 		err = -ENOMEM;
 		dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len);
-		if(dev->cow.bitmap == NULL) goto error;
+		if(dev->cow.bitmap == NULL){
+			printk(KERN_ERR "Failed to vmalloc COW bitmap\n");
+			goto error;
+		}
 		flush_tlb_kernel_vm();
 
 		err = read_cow_bitmap(dev->fd, dev->cow.bitmap, 
 				      dev->cow.bitmap_offset, 
 				      dev->cow.bitmap_len);
-		if(err) goto error;
+		if(err < 0)
+			goto error;
 
 		flags = dev->openflags;
 		flags.w = 0;
@@ -481,17 +559,31 @@ static int ubd_new_disk(int major, u64 size, int unit,
 			
 {
 	struct gendisk *disk;
+	char from[sizeof("ubd/nnnnn\0")], to[sizeof("discnnnnn/disc\0")];
+	int err;
 
 	disk = alloc_disk(1 << UBD_SHIFT);
-	if (!disk)
-		return -ENOMEM;
+	if(disk == NULL)
+		return(-ENOMEM);
 
 	disk->major = major;
 	disk->first_minor = unit << UBD_SHIFT;
 	disk->fops = &ubd_blops;
 	set_capacity(disk, size / 512);
-	sprintf(disk->disk_name, "ubd");
-	sprintf(disk->devfs_name, "ubd/disc%d", unit);
+	if(major == MAJOR_NR){
+		sprintf(disk->disk_name, "ubd%c", 'a' + unit);
+		sprintf(disk->devfs_name, "ubd/disc%d", unit);
+		sprintf(from, "ubd/%d", unit);
+		sprintf(to, "disc%d/disc", unit);
+		err = devfs_mk_symlink(from, to);
+		if(err)
+			printk("ubd_new_disk failed to make link from %s to "
+			       "%s, error = %d\n", from, to, err);
+	}
+	else {
+		sprintf(disk->disk_name, "ubd_fake%d", unit);
+		sprintf(disk->devfs_name, "ubd_fake/disc%d", unit);
+	}
 
 	disk->private_data = &ubd_dev[unit];
 	disk->queue = ubd_queue;
@@ -506,24 +598,21 @@ static int ubd_add(int n)
 	struct ubd *dev = &ubd_dev[n];
 	int err;
 
-	if(dev->is_dir)
-		return(-EISDIR);
-
-	if (!dev->file)
+	if(dev->file == NULL)
 		return(-ENODEV);
 
 	if (ubd_open_dev(dev))
 		return(-ENODEV);
 
 	err = ubd_file_size(dev, &dev->size);
-	if(err)
+	if(err < 0)
 		return(err);
 
 	err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]);
 	if(err) 
 		return(err);
  
-	if(fake_major)
+	if(fake_major != MAJOR_NR)
 		ubd_new_disk(fake_major, dev->size, n, 
 			     &fake_gendisk[n]);
 
@@ -561,42 +650,42 @@ static int ubd_config(char *str)
 	return(err);
 }
 
-static int ubd_get_config(char *dev, char *str, int size, char **error_out)
+static int ubd_get_config(char *name, char *str, int size, char **error_out)
 {
-	struct ubd *ubd;
+	struct ubd *dev;
 	char *end;
-	int major, n = 0;
+	int n, len = 0;
 
-	major = simple_strtoul(dev, &end, 0);
-	if((*end != '\0') || (end == dev)){
-		*error_out = "ubd_get_config : didn't parse major number";
+	n = simple_strtoul(name, &end, 0);
+	if((*end != '\0') || (end == name)){
+		*error_out = "ubd_get_config : didn't parse device number";
 		return(-1);
 	}
 
-	if((major >= MAX_DEV) || (major < 0)){
-		*error_out = "ubd_get_config : major number out of range";
+	if((n >= MAX_DEV) || (n < 0)){
+		*error_out = "ubd_get_config : device number out of range";
 		return(-1);
 	}
 
-	ubd = &ubd_dev[major];
+	dev = &ubd_dev[n];
 	spin_lock(&ubd_lock);
 
-	if(ubd->file == NULL){
-		CONFIG_CHUNK(str, size, n, "", 1);
+	if(dev->file == NULL){
+		CONFIG_CHUNK(str, size, len, "", 1);
 		goto out;
 	}
 
-	CONFIG_CHUNK(str, size, n, ubd->file, 0);
+	CONFIG_CHUNK(str, size, len, dev->file, 0);
 
-	if(ubd->cow.file != NULL){
-		CONFIG_CHUNK(str, size, n, ",", 0);
-		CONFIG_CHUNK(str, size, n, ubd->cow.file, 1);
+	if(dev->cow.file != NULL){
+		CONFIG_CHUNK(str, size, len, ",", 0);
+		CONFIG_CHUNK(str, size, len, dev->cow.file, 1);
 	}
-	else CONFIG_CHUNK(str, size, n, "", 1);
+	else CONFIG_CHUNK(str, size, len, "", 1);
 
  out:
 	spin_unlock(&ubd_lock);
-	return(n);
+	return(len);
 }
 
 static int ubd_remove(char *str)
@@ -604,11 +693,9 @@ static int ubd_remove(char *str)
 	struct ubd *dev;
 	int n, err = -ENODEV;
 
-	if(!isdigit(*str))
-		return(err);	/* it should be a number 0-7/a-h */
+	n = parse_unit(&str);
 
-	n = *str - '0';
-	if(n >= MAX_DEV) 
+	if((n < 0) || (n >= MAX_DEV))
 		return(err);
 
 	dev = &ubd_dev[n];
@@ -667,9 +754,7 @@ int ubd_init(void)
 		return -1;
 	}
 		
-	elevator_init(ubd_queue, &elevator_noop);
-
-	if (fake_major != 0) {
+	if (fake_major != MAJOR_NR) {
 		char name[sizeof("ubd_nnn\0")];
 
 		snprintf(name, sizeof(name), "ubd_%d", fake_major);
@@ -688,9 +773,11 @@ int ubd_driver_init(void){
 	unsigned long stack;
 	int err;
 
+	/* Set by CONFIG_BLK_DEV_UBD_SYNC or ubd=sync.*/
 	if(global_openflags.s){
-		printk(KERN_INFO "ubd : Synchronous mode\n");
-		return(0);
+		printk(KERN_INFO "ubd: Synchronous mode\n");
+		/* Letting ubd=sync be like using ubd#s= instead of ubd#= is
+		 * enough. So use anyway the io thread. */
 	}
 	stack = alloc_stack(0, 0);
 	io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *), 
@@ -699,12 +786,13 @@ int ubd_driver_init(void){
 		printk(KERN_ERR 
 		       "ubd : Failed to start I/O thread (errno = %d) - "
 		       "falling back to synchronous I/O\n", -io_pid);
+		io_pid = -1;
 		return(0);
 	}
 	err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, 
 			     SA_INTERRUPT, "ubd", ubd_dev);
-	if(err != 0) printk(KERN_ERR 
-			    "um_request_irq failed - errno = %d\n", -err);
+	if(err != 0)
+		printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err);
 	return(err);
 }
 
@@ -714,15 +802,9 @@ static int ubd_open(struct inode *inode, struct file *filp)
 {
 	struct gendisk *disk = inode->i_bdev->bd_disk;
 	struct ubd *dev = disk->private_data;
-	int err = -EISDIR;
-
-	if(dev->is_dir == 1)
-		goto out;
+	int err = 0;
 
-	err = 0;
 	if(dev->count == 0){
-		dev->openflags = dev->boot_openflags;
-
 		err = ubd_open_dev(dev);
 		if(err){
 			printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n",
@@ -749,91 +831,211 @@ static int ubd_release(struct inode * inode, struct file * file)
 	return(0);
 }
 
-void cowify_req(struct io_thread_req *req, struct ubd *dev)
+static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask,
+			  __u64 *cow_offset, unsigned long *bitmap,
+			  __u64 bitmap_offset, unsigned long *bitmap_words,
+			  __u64 bitmap_len)
+{
+	__u64 sector = io_offset >> 9;
+	int i, update_bitmap = 0;
+
+	for(i = 0; i < length >> 9; i++){
+		if(cow_mask != NULL)
+			ubd_set_bit(i, (unsigned char *) cow_mask);
+		if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
+			continue;
+
+		update_bitmap = 1;
+		ubd_set_bit(sector + i, (unsigned char *) bitmap);
+	}
+
+	if(!update_bitmap)
+		return;
+
+	*cow_offset = sector / (sizeof(unsigned long) * 8);
+
+	/* This takes care of the case where we're exactly at the end of the
+	 * device, and *cow_offset + 1 is off the end.  So, just back it up
+	 * by one word.  Thanks to Lynn Kerby for the fix and James McMechan
+	 * for the original diagnosis.
+	 */
+	if(*cow_offset == ((bitmap_len + sizeof(unsigned long) - 1) /
+			   sizeof(unsigned long) - 1))
+		(*cow_offset)--;
+
+	bitmap_words[0] = bitmap[*cow_offset];
+	bitmap_words[1] = bitmap[*cow_offset + 1];
+
+	*cow_offset *= sizeof(unsigned long);
+	*cow_offset += bitmap_offset;
+}
+
+static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
+		       __u64 bitmap_offset, __u64 bitmap_len)
 {
-        int i, update_bitmap, sector = req->offset >> 9;
+	__u64 sector = req->offset >> 9;
+	int i;
 
 	if(req->length > (sizeof(req->sector_mask) * 8) << 9)
 		panic("Operation too long");
+
 	if(req->op == UBD_READ) {
 		for(i = 0; i < req->length >> 9; i++){
-			if(ubd_test_bit(sector + i, (unsigned char *) 
-					dev->cow.bitmap)){
+			if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
 				ubd_set_bit(i, (unsigned char *) 
 					    &req->sector_mask);
-			}
                 }
-        } 
-        else {
-		update_bitmap = 0;
-		for(i = 0; i < req->length >> 9; i++){
-			ubd_set_bit(i, (unsigned char *) 
-				    &req->sector_mask);
-			if(!ubd_test_bit(sector + i, (unsigned char *) 
-					 dev->cow.bitmap))
-				update_bitmap = 1;
-			ubd_set_bit(sector + i, (unsigned char *) 
-				    dev->cow.bitmap);
-		}
-		if(update_bitmap){
-			req->cow_offset = sector / (sizeof(unsigned long) * 8);
-			req->bitmap_words[0] = 
-				dev->cow.bitmap[req->cow_offset];
-			req->bitmap_words[1] = 
-				dev->cow.bitmap[req->cow_offset + 1];
-			req->cow_offset *= sizeof(unsigned long);
-			req->cow_offset += dev->cow.bitmap_offset;
+	}
+	else cowify_bitmap(req->offset, req->length, &req->sector_mask,
+			   &req->cow_offset, bitmap, bitmap_offset,
+			   req->bitmap_words, bitmap_len);
+}
+
+static int mmap_fd(struct request *req, struct ubd *dev, __u64 offset)
+{
+	__u64 sector;
+	unsigned char *bitmap;
+	int bit, i;
+
+	/* mmap must have been requested on the command line */
+	if(!ubd_do_mmap)
+		return(-1);
+
+	/* The buffer must be page aligned */
+	if(((unsigned long) req->buffer % UBD_MMAP_BLOCK_SIZE) != 0)
+		return(-1);
+
+	/* The request must be a page long */
+	if((req->current_nr_sectors << 9) != PAGE_SIZE)
+		return(-1);
+
+	if(dev->cow.file == NULL)
+		return(dev->fd);
+
+	sector = offset >> 9;
+	bitmap = (unsigned char *) dev->cow.bitmap;
+	bit = ubd_test_bit(sector, bitmap);
+
+	for(i = 1; i < req->current_nr_sectors; i++){
+		if(ubd_test_bit(sector + i, bitmap) != bit)
+			return(-1);
+	}
+
+	if(bit || (rq_data_dir(req) == WRITE))
+		offset += dev->cow.data_offset;
+
+	/* The data on disk must be page aligned */
+	if((offset % UBD_MMAP_BLOCK_SIZE) != 0)
+		return(-1);
+
+	return(bit ? dev->fd : dev->cow.fd);
+}
+
+static int prepare_mmap_request(struct ubd *dev, int fd, __u64 offset,
+				struct request *req,
+				struct io_thread_req *io_req)
+{
+	int err;
+
+	if(rq_data_dir(req) == WRITE){
+		/* Writes are almost no-ops since the new data is already in the
+		 * host page cache
+		 */
+		dev->map_writes++;
+		if(dev->cow.file != NULL)
+			cowify_bitmap(io_req->offset, io_req->length,
+				      &io_req->sector_mask, &io_req->cow_offset,
+				      dev->cow.bitmap, dev->cow.bitmap_offset,
+				      io_req->bitmap_words,
+				      dev->cow.bitmap_len);
+	}
+	else {
+		int w;
+
+		if((dev->cow.file != NULL) && (fd == dev->cow.fd))
+			w = 0;
+		else w = dev->openflags.w;
+
+		if((dev->cow.file != NULL) && (fd == dev->fd))
+			offset += dev->cow.data_offset;
+
+		err = physmem_subst_mapping(req->buffer, fd, offset, w);
+		if(err){
+			printk("physmem_subst_mapping failed, err = %d\n",
+			       -err);
+			return(1);
 		}
+		dev->map_reads++;
 	}
+	io_req->op = UBD_MMAP;
+	io_req->buffer = req->buffer;
+	return(0);
 }
 
+/* Called with ubd_io_lock held */
 static int prepare_request(struct request *req, struct io_thread_req *io_req)
 {
 	struct gendisk *disk = req->rq_disk;
 	struct ubd *dev = disk->private_data;
-	__u64 block;
-	int nsect;
+	__u64 offset;
+	int len, fd;
 
 	if(req->rq_status == RQ_INACTIVE) return(1);
 
-	if(dev->is_dir){
-		strcpy(req->buffer, "HOSTFS:");
-		strcat(req->buffer, dev->file);
- 		spin_lock(&ubd_io_lock);
-		end_request(req, 1);
- 		spin_unlock(&ubd_io_lock);
-		return(1);
-	}
-
 	if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
 		printk("Write attempted on readonly ubd device %s\n", 
 		       disk->disk_name);
- 		spin_lock(&ubd_io_lock);
 		end_request(req, 0);
- 		spin_unlock(&ubd_io_lock);
 		return(1);
 	}
 
-        block = req->sector;
-        nsect = req->current_nr_sectors;
+	offset = ((__u64) req->sector) << 9;
+	len = req->current_nr_sectors << 9;
 
-	io_req->op = rq_data_dir(req) == READ ? UBD_READ : UBD_WRITE;
 	io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd;
 	io_req->fds[1] = dev->fd;
+	io_req->map_fd = -1;
+	io_req->cow_offset = -1;
+	io_req->offset = offset;
+	io_req->length = len;
+	io_req->error = 0;
+	io_req->sector_mask = 0;
+
+	fd = mmap_fd(req, dev, io_req->offset);
+	if(fd > 0){
+		/* If mmapping is otherwise OK, but the first access to the
+		 * page is a write, then it's not mapped in yet.  So we have
+		 * to write the data to disk first, then we can map the disk
+		 * page in and continue normally from there.
+		 */
+		if((rq_data_dir(req) == WRITE) && !is_remapped(req->buffer)){
+			io_req->map_fd = dev->fd;
+			io_req->map_offset = io_req->offset +
+				dev->cow.data_offset;
+			dev->write_maps++;
+		}
+		else return(prepare_mmap_request(dev, fd, io_req->offset, req,
+						 io_req));
+	}
+
+	if(rq_data_dir(req) == READ)
+		dev->nomap_reads++;
+	else dev->nomap_writes++;
+
+	io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE;
 	io_req->offsets[0] = 0;
 	io_req->offsets[1] = dev->cow.data_offset;
-	io_req->offset = ((__u64) block) << 9;
-	io_req->length = nsect << 9;
 	io_req->buffer = req->buffer;
 	io_req->sectorsize = 1 << 9;
-	io_req->sector_mask = 0;
-	io_req->cow_offset = -1;
-	io_req->error = 0;
 
-        if(dev->cow.file != NULL) cowify_req(io_req, dev);
+	if(dev->cow.file != NULL)
+		cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset,
+			   dev->cow.bitmap_len);
+
 	return(0);
 }
 
+/* Called with ubd_io_lock held */
 static void do_ubd_request(request_queue_t *q)
 {
 	struct io_thread_req io_req;
@@ -841,18 +1043,17 @@ static void do_ubd_request(request_queue_t *q)
 	int err, n;
 
 	if(thread_fd == -1){
-		while(!list_empty(&q->queue_head)){
-			req = elv_next_request(q);
+		while((req = elv_next_request(q)) != NULL){
 			err = prepare_request(req, &io_req);
 			if(!err){
 				do_io(&io_req);
-				ubd_finish(req, io_req.error);
+				__ubd_finish(req, io_req.error);
 			}
 		}
 	}
 	else {
-		if(do_ubd || list_empty(&q->queue_head)) return;
-		req = elv_next_request(q);
+		if(do_ubd || (req = elv_next_request(q)) == NULL)
+			return;
 		err = prepare_request(req, &io_req);
 		if(!err){
 			do_ubd = ubd_handler;
@@ -870,7 +1071,6 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
 {
 	struct hd_geometry *loc = (struct hd_geometry *) arg;
 	struct ubd *dev = inode->i_bdev->bd_disk->private_data;
-	int err;
 	struct hd_driveid ubd_id = {
 		.cyls		= 0,
 		.heads		= 128,
@@ -885,35 +1085,9 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
 		g.heads = 128;
 		g.sectors = 32;
 		g.cylinders = dev->size / (128 * 32 * 512);
-		g.start = 2;
+		g.start = get_start_sect(inode->i_bdev);
 		return(copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0);
 
-	case HDIO_SET_UNMASKINTR:
-		if(!capable(CAP_SYS_ADMIN)) return(-EACCES);
-		if((arg > 1) || (inode->i_bdev->bd_contains != inode->i_bdev))
-			return(-EINVAL);
-		return(0);
-
-	case HDIO_GET_UNMASKINTR:
-		if(!arg)  return(-EINVAL);
-		err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
-		if(err)
-			return(err);
-		return(0);
-
-	case HDIO_GET_MULTCOUNT:
-		if(!arg)  return(-EINVAL);
-		err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
-		if(err)
-			return(err);
-		return(0);
-
-	case HDIO_SET_MULTCOUNT:
-		if(!capable(CAP_SYS_ADMIN)) return(-EACCES);
-		if(inode->i_bdev->bd_contains != inode->i_bdev)
-			return(-EINVAL);
-		return(0);
-
 	case HDIO_GET_IDENTITY:
 		ubd_id.cyls = dev->size / (128 * 32 * 512);
 		if(copy_to_user((char *) arg, (char *) &ubd_id, 
@@ -935,6 +1109,142 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
 	return(-EINVAL);
 }
 
+static int ubd_check_remapped(int fd, unsigned long address, int is_write,
+			      __u64 offset)
+{
+	__u64 bitmap_offset;
+	unsigned long new_bitmap[2];
+	int i, err, n;
+
+	/* If it's not a write access, we can't do anything about it */
+	if(!is_write)
+		return(0);
+
+	/* We have a write */
+	for(i = 0; i < sizeof(ubd_dev) / sizeof(ubd_dev[0]); i++){
+		struct ubd *dev = &ubd_dev[i];
+
+		if((dev->fd != fd) && (dev->cow.fd != fd))
+			continue;
+
+		/* It's a write to a ubd device */
+
+		if(!dev->openflags.w){
+			/* It's a write access on a read-only device - probably
+			 * shouldn't happen.  If the kernel is trying to change
+			 * something with no intention of writing it back out,
+			 * then this message will clue us in that this needs
+			 * fixing
+			 */
+			printk("Write access to mapped page from readonly ubd "
+			       "device %d\n", i);
+			return(0);
+		}
+
+		/* It's a write to a writeable ubd device - it must be COWed
+		 * because, otherwise, the page would have been mapped in
+		 * writeable
+		 */
+
+		if(!dev->cow.file)
+			panic("Write fault on writeable non-COW ubd device %d",
+			      i);
+
+		/* It should also be an access to the backing file since the
+		 * COW pages should be mapped in read-write
+		 */
+
+		if(fd == dev->fd)
+			panic("Write fault on a backing page of ubd "
+			      "device %d\n", i);
+
+		/* So, we do the write, copying the backing data to the COW
+		 * file...
+		 */
+
+		err = os_seek_file(dev->fd, offset + dev->cow.data_offset);
+		if(err < 0)
+			panic("Couldn't seek to %lld in COW file of ubd "
+			      "device %d, err = %d",
+			      offset + dev->cow.data_offset, i, -err);
+
+		n = os_write_file(dev->fd, (void *) address, PAGE_SIZE);
+		if(n != PAGE_SIZE)
+			panic("Couldn't copy data to COW file of ubd "
+			      "device %d, err = %d", i, -n);
+
+		/* ... updating the COW bitmap... */
+
+		cowify_bitmap(offset, PAGE_SIZE, NULL, &bitmap_offset,
+			      dev->cow.bitmap, dev->cow.bitmap_offset,
+			      new_bitmap, dev->cow.bitmap_len);
+
+		err = os_seek_file(dev->fd, bitmap_offset);
+		if(err < 0)
+			panic("Couldn't seek to %lld in COW file of ubd "
+			      "device %d, err = %d", bitmap_offset, i, -err);
+
+		n = os_write_file(dev->fd, new_bitmap, sizeof(new_bitmap));
+		if(n != sizeof(new_bitmap))
+			panic("Couldn't update bitmap  of ubd device %d, "
+			      "err = %d", i, -n);
+
+		/* Maybe we can map the COW page in, and maybe we can't.  If
+		 * it is a pre-V3 COW file, we can't, since the alignment will
+		 * be wrong.  If it is a V3 or later COW file which has been
+		 * moved to a system with a larger page size, then maybe we
+		 * can't, depending on the exact location of the page.
+		 */
+
+		offset += dev->cow.data_offset;
+
+		/* Remove the remapping, putting the original anonymous page
+		 * back.  If the COW file can be mapped in, that is done.
+		 * Otherwise, the COW page is read in.
+		 */
+
+		if(!physmem_remove_mapping((void *) address))
+			panic("Address 0x%lx not remapped by ubd device %d",
+			      address, i);
+		if((offset % UBD_MMAP_BLOCK_SIZE) == 0)
+			physmem_subst_mapping((void *) address, dev->fd,
+					      offset, 1);
+		else {
+			err = os_seek_file(dev->fd, offset);
+			if(err < 0)
+				panic("Couldn't seek to %lld in COW file of "
+				      "ubd device %d, err = %d", offset, i,
+				      -err);
+
+			n = os_read_file(dev->fd, (void *) address, PAGE_SIZE);
+			if(n != PAGE_SIZE)
+				panic("Failed to read page from offset %llx of "
+				      "COW file of ubd device %d, err = %d",
+				      offset, i, -n);
+		}
+
+		return(1);
+	}
+
+	/* It's not a write on a ubd device */
+	return(0);
+}
+
+static struct remapper ubd_remapper = {
+	.list	= LIST_HEAD_INIT(ubd_remapper.list),
+	.proc	= ubd_check_remapped,
+};
+
+static int ubd_remapper_setup(void)
+{
+	if(ubd_do_mmap)
+		register_remapper(&ubd_remapper);
+
+	return(0);
+}
+
+__initcall(ubd_remapper_setup);
+
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
index 93b6f3e90..882d2f7c1 100644
--- a/arch/um/drivers/ubd_user.c
+++ b/arch/um/drivers/ubd_user.c
@@ -11,11 +11,8 @@
 #include <signal.h>
 #include <string.h>
 #include <netinet/in.h>
-#include <sys/stat.h>
 #include <sys/time.h>
-#include <sys/fcntl.h>
 #include <sys/socket.h>
-#include <string.h>
 #include <sys/mman.h>
 #include <sys/param.h>
 #include "asm/types.h"
@@ -24,146 +21,30 @@
 #include "user.h"
 #include "ubd_user.h"
 #include "os.h"
+#include "cow.h"
 
 #include <endian.h>
 #include <byteswap.h>
-#if __BYTE_ORDER == __BIG_ENDIAN
-# define ntohll(x) (x)
-# define htonll(x) (x)
-#elif __BYTE_ORDER == __LITTLE_ENDIAN
-# define ntohll(x)  bswap_64(x)
-# define htonll(x)  bswap_64(x)
-#else
-#error "__BYTE_ORDER not defined"
-#endif
-
-#define PATH_LEN_V1 256
-
-struct cow_header_v1 {
-	int magic;
-	int version;
-	char backing_file[PATH_LEN_V1];
-	time_t mtime;
-	__u64 size;
-	int sectorsize;
-};
-
-#define PATH_LEN_V2 MAXPATHLEN
-
-struct cow_header_v2 {
-	unsigned long magic;
-	unsigned long version;
-	char backing_file[PATH_LEN_V2];
-	time_t mtime;
-	__u64 size;
-	int sectorsize;
-};
-
-union cow_header {
-	struct cow_header_v1 v1;
-	struct cow_header_v2 v2;
-};
-
-#define COW_MAGIC 0x4f4f4f4d  /* MOOO */
-#define COW_VERSION 2
-
-static void sizes(__u64 size, int sectorsize, int bitmap_offset, 
-		  unsigned long *bitmap_len_out, int *data_offset_out)
-{
-	*bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
-
-	*data_offset_out = bitmap_offset + *bitmap_len_out;
-	*data_offset_out = (*data_offset_out + sectorsize - 1) / sectorsize;
-	*data_offset_out *= sectorsize;
-}
-
-static int read_cow_header(int fd, int *magic_out, char **backing_file_out, 
-			   time_t *mtime_out, __u64 *size_out, 
-			   int *sectorsize_out, int *bitmap_offset_out)
-{
-	union cow_header *header;
-	char *file;
-	int err, n;
-	unsigned long version, magic;
-
-	header = um_kmalloc(sizeof(*header));
-	if(header == NULL){
-		printk("read_cow_header - Failed to allocate header\n");
-		return(-ENOMEM);
-	}
-	err = -EINVAL;
-	n = read(fd, header, sizeof(*header));
-	if(n < offsetof(typeof(header->v1), backing_file)){
-		printk("read_cow_header - short header\n");
-		goto out;
-	}
-
-	magic = header->v1.magic;
-	if(magic == COW_MAGIC) {
-		version = header->v1.version;
-	}
-	else if(magic == ntohl(COW_MAGIC)){
-		version = ntohl(header->v1.version);
-	}
-	else goto out;
-
-	*magic_out = COW_MAGIC;
-
-	if(version == 1){
-		if(n < sizeof(header->v1)){
-			printk("read_cow_header - failed to read V1 header\n");
-			goto out;
-		}
-		*mtime_out = header->v1.mtime;
-		*size_out = header->v1.size;
-		*sectorsize_out = header->v1.sectorsize;
-		*bitmap_offset_out = sizeof(header->v1);
-		file = header->v1.backing_file;
-	}
-	else if(version == 2){
-		if(n < sizeof(header->v2)){
-			printk("read_cow_header - failed to read V2 header\n");
-			goto out;
-		}
-		*mtime_out = ntohl(header->v2.mtime);
-		*size_out = ntohll(header->v2.size);
-		*sectorsize_out = ntohl(header->v2.sectorsize);
-		*bitmap_offset_out = sizeof(header->v2);
-		file = header->v2.backing_file;
-	}
-	else {
-		printk("read_cow_header - invalid COW version\n");
-		goto out;
-	}
-	err = -ENOMEM;
-	*backing_file_out = uml_strdup(file);
-	if(*backing_file_out == NULL){
-		printk("read_cow_header - failed to allocate backing file\n");
-		goto out;
-	}
-	err = 0;
- out:
-	kfree(header);
-	return(err);
-}
 
 static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
 {
-	struct stat buf1, buf2;
+	struct uml_stat buf1, buf2;
+	int err;
 
 	if(from_cmdline == NULL) return(1);
 	if(!strcmp(from_cmdline, from_cow)) return(1);
 
-	if(stat(from_cmdline, &buf1) < 0){
-		printk("Couldn't stat '%s', errno = %d\n", from_cmdline, 
-		       errno);
+	err = os_stat_file(from_cmdline, &buf1);
+	if(err < 0){
+		printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err);
 		return(1);
 	}
-	if(stat(from_cow, &buf2) < 0){
-		printk("Couldn't stat '%s', errno = %d\n", from_cow, errno);
+	err = os_stat_file(from_cow, &buf2);
+	if(err < 0){
+		printk("Couldn't stat '%s', err = %d\n", from_cow, -err);
 		return(1);
 	}
-	if((buf1.st_dev == buf2.st_dev) && (buf1.st_ino == buf2.st_ino))
+	if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino))
 		return(1);
 
 	printk("Backing file mismatch - \"%s\" requested,\n"
@@ -174,20 +55,21 @@ static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
 
 static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
 {
-	struct stat64 buf;
+	unsigned long modtime;
 	long long actual;
 	int err;
 
-  	if(stat64(file, &buf) < 0){
-		printk("Failed to stat backing file \"%s\", errno = %d\n",
-		       file, errno);
-		return(-errno);
+	err = os_file_modtime(file, &modtime);
+	if(err < 0){
+		printk("Failed to get modification time of backing file "
+		       "\"%s\", err = %d\n", file, -err);
+		return(err);
 	}
 
 	err = os_file_size(file, &actual);
-	if(err){
+	if(err < 0){
 		printk("Failed to get size of backing file \"%s\", "
-		       "errno = %d\n", file, -err);
+		       "err = %d\n", file, -err);
 		return(err);
 	}
 
@@ -196,9 +78,9 @@ static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
 		       "file\n", size, actual);
 		return(-EINVAL);
 	}
-	if(buf.st_mtime != mtime){
+	if(modtime != mtime){
 		printk("mtime mismatch (%ld vs %ld) of COW header vs backing "
-		       "file\n", mtime, buf.st_mtime);
+		       "file\n", mtime, modtime);
 		return(-EINVAL);
 	}
 	return(0);
@@ -209,124 +91,16 @@ int read_cow_bitmap(int fd, void *buf, int offset, int len)
 	int err;
 
 	err = os_seek_file(fd, offset);
-	if(err != 0) return(-errno);
-	err = read(fd, buf, len);
-	if(err < 0) return(-errno);
-	return(0);
-}
+	if(err < 0)
+		return(err);
 
-static int absolutize(char *to, int size, char *from)
-{
-	char save_cwd[256], *slash;
-	int remaining;
+	err = os_read_file(fd, buf, len);
+	if(err < 0)
+		return(err);
 
-	if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
-		printk("absolutize : unable to get cwd - errno = %d\n", errno);
-		return(-1);
-	}
-	slash = strrchr(from, '/');
-	if(slash != NULL){
-		*slash = '\0';
-		if(chdir(from)){
-			*slash = '/';
-			printk("absolutize : Can't cd to '%s' - errno = %d\n",
-			       from, errno);
-			return(-1);
-		}
-		*slash = '/';
-		if(getcwd(to, size) == NULL){
-			printk("absolutize : unable to get cwd of '%s' - "
-			       "errno = %d\n", from, errno);
-			return(-1);
-		}
-		remaining = size - strlen(to);
-		if(strlen(slash) + 1 > remaining){
-			printk("absolutize : unable to fit '%s' into %d "
-			       "chars\n", from, size);
-			return(-1);
-		}
-		strcat(to, slash);
-	}
-	else {
-		if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){
-			printk("absolutize : unable to fit '%s' into %d "
-			       "chars\n", from, size);
-			return(-1);
-		}
-		strcpy(to, save_cwd);
-		strcat(to, "/");
-		strcat(to, from);
-	}
-	chdir(save_cwd);
 	return(0);
 }
 
-static int write_cow_header(char *cow_file, int fd, char *backing_file, 
-			    int sectorsize, long long *size)
-{
-        struct cow_header_v2 *header;
-	struct stat64 buf;
-	int err;
-
-	err = os_seek_file(fd, 0);
-	if(err != 0){
-		printk("write_cow_header - lseek failed, errno = %d\n", errno);
-		return(-errno);
-	}
-
-	err = -ENOMEM;
-	header = um_kmalloc(sizeof(*header));
-	if(header == NULL){
-		printk("Failed to allocate COW V2 header\n");
-		goto out;
-	}
-	header->magic = htonl(COW_MAGIC);
-	header->version = htonl(COW_VERSION);
-
-	err = -EINVAL;
-	if(strlen(backing_file) > sizeof(header->backing_file) - 1){
-		printk("Backing file name \"%s\" is too long - names are "
-		       "limited to %d characters\n", backing_file, 
-		       sizeof(header->backing_file) - 1);
-		goto out_free;
-	}
-
-	if(absolutize(header->backing_file, sizeof(header->backing_file), 
-		      backing_file))
-		goto out_free;
-
-	err = stat64(header->backing_file, &buf);
-	if(err < 0){
-		printk("Stat of backing file '%s' failed, errno = %d\n",
-		       header->backing_file, errno);
-		err = -errno;
-		goto out_free;
-	}
-
-	err = os_file_size(header->backing_file, size);
-	if(err){
-		printk("Couldn't get size of backing file '%s', errno = %d\n",
-		       header->backing_file, -*size);
-		goto out_free;
-	}
-
-	header->mtime = htonl(buf.st_mtime);
-	header->size = htonll(*size);
-	header->sectorsize = htonl(sectorsize);
-
-	err = write(fd, header, sizeof(*header));
-	if(err != sizeof(*header)){
-		printk("Write of header to new COW file '%s' failed, "
-		       "errno = %d\n", cow_file, errno);
-		goto out_free;
-	}
-	err = 0;
- out_free:
-	kfree(header);
- out:
-	return(err);
-}
-
 int open_ubd_file(char *file, struct openflags *openflags, 
 		  char **backing_file_out, int *bitmap_offset_out, 
 		  unsigned long *bitmap_len_out, int *data_offset_out, 
@@ -334,26 +108,36 @@ int open_ubd_file(char *file, struct openflags *openflags,
 {
 	time_t mtime;
 	__u64 size;
+	__u32 version, align;
 	char *backing_file;
-        int fd, err, sectorsize, magic, same, mode = 0644;
+	int fd, err, sectorsize, same, mode = 0644;
 
-        if((fd = os_open_file(file, *openflags, mode)) < 0){
+	fd = os_open_file(file, *openflags, mode);
+	if(fd < 0){
 		if((fd == -ENOENT) && (create_cow_out != NULL))
 			*create_cow_out = 1;
                 if(!openflags->w ||
                    ((errno != EROFS) && (errno != EACCES))) return(-errno);
 		openflags->w = 0;
-                if((fd = os_open_file(file, *openflags, mode)) < 0) 
+		fd = os_open_file(file, *openflags, mode);
+		if(fd < 0)
 			return(fd);
         }
+
+	err = os_lock_file(fd, openflags->w);
+	if(err < 0){
+		printk("Failed to lock '%s', err = %d\n", file, -err);
+		goto out_close;
+	}
+
 	if(backing_file_out == NULL) return(fd);
 
-	err = read_cow_header(fd, &magic, &backing_file, &mtime, &size, 
-			      &sectorsize, bitmap_offset_out);
+	err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
+			      &size, &sectorsize, &align, bitmap_offset_out);
 	if(err && (*backing_file_out != NULL)){
 		printk("Failed to read COW header from COW file \"%s\", "
-		       "errno = %d\n", file, err);
-		goto error;
+		       "errno = %d\n", file, -err);
+		goto out_close;
 	}
 	if(err) return(fd);
 
@@ -363,36 +147,33 @@ int open_ubd_file(char *file, struct openflags *openflags,
 
 	if(!same && !backing_file_mismatch(*backing_file_out, size, mtime)){
 		printk("Switching backing file to '%s'\n", *backing_file_out);
-		err = write_cow_header(file, fd, *backing_file_out, 
-				       sectorsize, &size);
+		err = write_cow_header(file, fd, *backing_file_out,
+				       sectorsize, align, &size);
 		if(err){
-			printk("Switch failed, errno = %d\n", err);
+			printk("Switch failed, errno = %d\n", -err);
 			return(err);
 		}
 	}
 	else {
 		*backing_file_out = backing_file;
 		err = backing_file_mismatch(*backing_file_out, size, mtime);
-		if(err) goto error;
+		if(err) goto out_close;
 	}
 
-	sizes(size, sectorsize, *bitmap_offset_out, bitmap_len_out, 
-	      data_offset_out);
+	cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
+		  bitmap_len_out, data_offset_out);
 
         return(fd);
- error:
-	close(fd);
+ out_close:
+	os_close_file(fd);
 	return(err);
 }
 
 int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
-		    int sectorsize, int *bitmap_offset_out, 
+		    int sectorsize, int alignment, int *bitmap_offset_out,
 		    unsigned long *bitmap_len_out, int *data_offset_out)
 {
-	__u64 blocks;
-	long zero;
-	int err, fd, i;
-	long long size;
+	int err, fd;
 
 	flags.c = 1;
 	fd = open_ubd_file(cow_file, &flags, NULL, NULL, NULL, NULL, NULL);
@@ -403,57 +184,49 @@ int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
 		goto out;
 	}
 
-	err = write_cow_header(cow_file, fd, backing_file, sectorsize, &size);
-	if(err) goto out_close;
-
-	blocks = (size + sectorsize - 1) / sectorsize;
-	blocks = (blocks + sizeof(long) * 8 - 1) / (sizeof(long) * 8);
-	zero = 0;
-	for(i = 0; i < blocks; i++){
-		err = write(fd, &zero, sizeof(zero));
-		if(err != sizeof(zero)){
-			printk("Write of bitmap to new COW file '%s' failed, "
-			       "errno = %d\n", cow_file, errno);
-			goto out_close;
-		}
-	}
-
-	sizes(size, sectorsize, sizeof(struct cow_header_v2), 
-	      bitmap_len_out, data_offset_out);
-	*bitmap_offset_out = sizeof(struct cow_header_v2);
-
-	return(fd);
-
- out_close:
-	close(fd);
+	err = init_cow_file(fd, cow_file, backing_file, sectorsize, alignment,
+			    bitmap_offset_out, bitmap_len_out,
+			    data_offset_out);
+	if(!err)
+		return(fd);
+	os_close_file(fd);
  out:
 	return(err);
 }
 
+/* XXX Just trivial wrappers around os_read_file and os_write_file */
 int read_ubd_fs(int fd, void *buffer, int len)
 {
-	int n;
-
-	n = read(fd, buffer, len);
-	if(n < 0) return(-errno);
-	else return(n);
+	return(os_read_file(fd, buffer, len));
 }
 
 int write_ubd_fs(int fd, char *buffer, int len)
 {
-	int n;
-
-	n = write(fd, buffer, len);
-	if(n < 0) return(-errno);
-	else return(n);
+	return(os_write_file(fd, buffer, len));
 }
 
-int ubd_is_dir(char *file)
+static int update_bitmap(struct io_thread_req *req)
 {
-	struct stat64 buf;
+	int n;
+
+	if(req->cow_offset == -1)
+		return(0);
+
+	n = os_seek_file(req->fds[1], req->cow_offset);
+	if(n < 0){
+		printk("do_io - bitmap lseek failed : err = %d\n", -n);
+		return(1);
+	}
 
-	if(stat64(file, &buf) < 0) return(0);
-	return(S_ISDIR(buf.st_mode));
+	n = os_write_file(req->fds[1], &req->bitmap_words,
+		          sizeof(req->bitmap_words));
+	if(n != sizeof(req->bitmap_words)){
+		printk("do_io - bitmap update failed, err = %d fd = %d\n", -n,
+		       req->fds[1]);
+		return(1);
+	}
+
+	return(0);
 }
 
 void do_io(struct io_thread_req *req)
@@ -461,8 +234,18 @@ void do_io(struct io_thread_req *req)
 	char *buf;
 	unsigned long len;
 	int n, nsectors, start, end, bit;
+	int err;
 	__u64 off;
 
+	if(req->op == UBD_MMAP){
+		/* Touch the page to force the host to do any necessary IO to
+		 * get it into memory
+		 */
+		n = *((volatile int *) req->buffer);
+		req->error = update_bitmap(req);
+		return;
+	}
+
 	nsectors = req->length / req->sectorsize;
 	start = 0;
 	do {
@@ -473,15 +256,14 @@ void do_io(struct io_thread_req *req)
 				    &req->sector_mask) == bit))
 			end++;
 
-		if(end != nsectors)
-			printk("end != nsectors\n");
 		off = req->offset + req->offsets[bit] + 
 			start * req->sectorsize;
 		len = (end - start) * req->sectorsize;
 		buf = &req->buffer[start * req->sectorsize];
 
-		if(os_seek_file(req->fds[bit], off) != 0){
-			printk("do_io - lseek failed : errno = %d\n", errno);
+		err = os_seek_file(req->fds[bit], off);
+		if(err < 0){
+			printk("do_io - lseek failed : err = %d\n", -err);
 			req->error = 1;
 			return;
 		}
@@ -490,11 +272,10 @@ void do_io(struct io_thread_req *req)
 			do {
 				buf = &buf[n];
 				len -= n;
-				n = read(req->fds[bit], buf, len);
+				n = os_read_file(req->fds[bit], buf, len);
 				if (n < 0) {
-					printk("do_io - read returned %d : "
-					       "errno = %d fd = %d\n", n,
-					       errno, req->fds[bit]);
+					printk("do_io - read failed, err = %d "
+					       "fd = %d\n", -n, req->fds[bit]);
 					req->error = 1;
 					return;
 				}
@@ -502,11 +283,10 @@ void do_io(struct io_thread_req *req)
 			if (n < len) memset(&buf[n], 0, len - n);
 		}
 		else {
-			n = write(req->fds[bit], buf, len);
+			n = os_write_file(req->fds[bit], buf, len);
 			if(n != len){
-				printk("do_io - write returned %d : "
-				       "errno = %d fd = %d\n", n, 
-				       errno, req->fds[bit]);
+				printk("do_io - write failed err = %d "
+				       "fd = %d\n", -n, req->fds[bit]);
 				req->error = 1;
 				return;
 			}
@@ -515,24 +295,7 @@ void do_io(struct io_thread_req *req)
 		start = end;
 	} while(start < nsectors);
 
-	if(req->cow_offset != -1){
-		if(os_seek_file(req->fds[1], req->cow_offset) != 0){
-			printk("do_io - bitmap lseek failed : errno = %d\n",
-			       errno);
-			req->error = 1;
-			return;
-		}
-		n = write(req->fds[1], &req->bitmap_words, 
-			  sizeof(req->bitmap_words));
-		if(n != sizeof(req->bitmap_words)){
-			printk("do_io - bitmap update returned %d : "
-			       "errno = %d fd = %d\n", n, errno, req->fds[1]);
-			req->error = 1;
-			return;
-		}
-	}
-	req->error = 0;
-	return;
+	req->error = update_bitmap(req);
 }
 
 /* Changed in start_io_thread, which is serialized by being called only
@@ -550,19 +313,23 @@ int io_thread(void *arg)
 
 	signal(SIGWINCH, SIG_IGN);
 	while(1){
-		n = read(kernel_fd, &req, sizeof(req));
-		if(n < 0) printk("io_thread - read returned %d, errno = %d\n",
-				 n, errno);
-		else if(n < sizeof(req)){
-			printk("io_thread - short read : length = %d\n", n);
+		n = os_read_file(kernel_fd, &req, sizeof(req));
+		if(n != sizeof(req)){
+			if(n < 0)
+				printk("io_thread - read failed, fd = %d, "
+				       "err = %d\n", kernel_fd, -n);
+			else {
+				printk("io_thread - short read, fd = %d, "
+				       "length = %d\n", kernel_fd, n);
+			}
 			continue;
 		}
 		io_count++;
 		do_io(&req);
-		n = write(kernel_fd, &req, sizeof(req));
+		n = os_write_file(kernel_fd, &req, sizeof(req));
 		if(n != sizeof(req))
-			printk("io_thread - write failed, errno = %d\n",
-			       errno);
+			printk("io_thread - write failed, fd = %d, err = %d\n",
+			       kernel_fd, -n);
 	}
 }
 
@@ -571,10 +338,11 @@ int start_io_thread(unsigned long sp, int *fd_out)
 	int pid, fds[2], err;
 
 	err = os_pipe(fds, 1, 1);
-	if(err){
-		printk("start_io_thread - os_pipe failed, errno = %d\n", -err);
-		return(-1);
+	if(err < 0){
+		printk("start_io_thread - os_pipe failed, err = %d\n", -err);
+		goto out;
 	}
+
 	kernel_fd = fds[0];
 	*fd_out = fds[1];
 
@@ -582,32 +350,20 @@ int start_io_thread(unsigned long sp, int *fd_out)
 		    NULL);
 	if(pid < 0){
 		printk("start_io_thread - clone failed : errno = %d\n", errno);
-		return(-errno);
-	}
-	return(pid);
-}
-
-#ifdef notdef
-int start_io_thread(unsigned long sp, int *fd_out)
-{
-	int pid;
-
-	if((kernel_fd = get_pty()) < 0) return(-1);
-	raw(kernel_fd, 0);
-	if((*fd_out = open(ptsname(kernel_fd), O_RDWR)) < 0){
-		printk("Couldn't open tty for IO\n");
-		return(-1);
+		err = -errno;
+		goto out_close;
 	}
 
-	pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD,
-		    NULL);
-	if(pid < 0){
-		printk("start_io_thread - clone failed : errno = %d\n", errno);
-		return(-errno);
-	}
 	return(pid);
+
+ out_close:
+	os_close_file(fds[0]);
+	os_close_file(fds[1]);
+	kernel_fd = -1;
+	*fd_out = -1;
+ out:
+	return(err);
 }
-#endif
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index 59c4ba89f..f417b3b66 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -8,7 +8,6 @@
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <termios.h>
 #include <signal.h>
 #include <sched.h>
@@ -36,7 +35,8 @@ void *xterm_init(char *str, int device, struct chan_opts *opts)
 {
 	struct xterm_chan *data;
 
-	if((data = malloc(sizeof(*data))) == NULL) return(NULL);
+	data = malloc(sizeof(*data));
+	if(data == NULL) return(NULL);
 	*data = ((struct xterm_chan) { .pid 		= -1, 
 				       .helper_pid 	= -1,
 				       .device 		= device, 
@@ -83,6 +83,7 @@ __uml_setup("xterm=", xterm_setup,
 "    are 'xterm=gnome-terminal,-t,-x'.\n\n"
 );
 
+/* XXX This badly needs some cleaning up in the error paths */
 int xterm_open(int input, int output, int primary, void *d, char **dev_out)
 {
 	struct xterm_chan *data = d;
@@ -93,7 +94,7 @@ int xterm_open(int input, int output, int primary, void *d, char **dev_out)
 			 "/usr/lib/uml/port-helper", "-uml-socket",
 			 file, NULL };
 
-	if(access(argv[4], X_OK))
+	if(os_access(argv[4], OS_ACC_X_OK) < 0)
 		argv[4] = "port-helper";
 
 	fd = mkstemp(file);
@@ -106,13 +107,13 @@ int xterm_open(int input, int output, int primary, void *d, char **dev_out)
 		printk("xterm_open : unlink failed, errno = %d\n", errno);
 		return(-errno);
 	}
-	close(fd);
+	os_close_file(fd);
 
-	fd = create_unix_socket(file, sizeof(file));
+	fd = os_create_unix_socket(file, sizeof(file), 1);
 	if(fd < 0){
 		printk("xterm_open : create_unix_socket failed, errno = %d\n", 
 		       -fd);
-		return(-fd);
+		return(fd);
 	}
 
 	sprintf(title, data->title, data->device);
@@ -128,20 +129,32 @@ int xterm_open(int input, int output, int primary, void *d, char **dev_out)
 	if(data->direct_rcv)
 		new = os_rcv_fd(fd, &data->helper_pid);
 	else {
-		if((err = os_set_fd_block(fd, 0)) != 0){
+		err = os_set_fd_block(fd, 0);
+		if(err < 0){
 			printk("xterm_open : failed to set descriptor "
-			       "non-blocking, errno = %d\n", err);
+			       "non-blocking, err = %d\n", -err);
 			return(err);
 		}
 		new = xterm_fd(fd, &data->helper_pid);
 	}
 	if(new < 0){
-		printk("xterm_open : os_rcv_fd failed, errno = %d\n", -new);
+		printk("xterm_open : os_rcv_fd failed, err = %d\n", -new);
 		goto out;
 	}
 
-	tcgetattr(new, &data->tt);
-	if(data->raw) raw(new, 0);
+	CATCH_EINTR(err = tcgetattr(new, &data->tt));
+	if(err){
+		new = err;
+		goto out;
+	}
+
+	if(data->raw){
+		err = raw(new);
+		if(err){
+			new = err;
+			goto out;
+		}
+	}
 
 	data->pid = pid;
 	*dev_out = NULL;
@@ -160,7 +173,7 @@ void xterm_close(int fd, void *d)
 	if(data->helper_pid != -1) 
 		os_kill_process(data->helper_pid, 0);
 	data->helper_pid = -1;
-	close(fd);
+	os_close_file(fd);
 }
 
 void xterm_free(void *d)
diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
index 1b4683fe3..a94813fce 100644
--- a/arch/um/drivers/xterm_kern.c
+++ b/arch/um/drivers/xterm_kern.c
@@ -5,9 +5,12 @@
 
 #include "linux/errno.h"
 #include "linux/slab.h"
+#include "linux/signal.h"
+#include "linux/interrupt.h"
 #include "asm/semaphore.h"
 #include "asm/irq.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 #include "kern_util.h"
 #include "os.h"
 #include "xterm.h"
@@ -19,17 +22,18 @@ struct xterm_wait {
 	int new_fd;
 };
 
-static void xterm_interrupt(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t xterm_interrupt(int irq, void *data, struct pt_regs *regs)
 {
 	struct xterm_wait *xterm = data;
 	int fd;
 
 	fd = os_rcv_fd(xterm->fd, &xterm->pid);
 	if(fd == -EAGAIN)
-		return;
+		return(IRQ_NONE);
 
 	xterm->new_fd = fd;
 	up(&xterm->sem);
+	return(IRQ_HANDLED);
 }
 
 int xterm_fd(int socket, int *pid_out)
@@ -54,7 +58,8 @@ int xterm_fd(int socket, int *pid_out)
 	if(err){
 		printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, "
 		       "err = %d\n",  err);
-		return(err);
+		ret = err;
+		goto out;
 	}
 	down(&data->sem);
 
@@ -62,6 +67,7 @@ int xterm_fd(int socket, int *pid_out)
 
 	ret = data->new_fd;
 	*pid_out = data->pid;
+ out:
 	kfree(data);
 
 	return(ret);
diff --git a/arch/um/include/2_5compat.h b/arch/um/include/2_5compat.h
index 6d36d9c30..abdb015a4 100644
--- a/arch/um/include/2_5compat.h
+++ b/arch/um/include/2_5compat.h
@@ -6,20 +6,6 @@
 #ifndef __2_5_COMPAT_H__
 #define __2_5_COMPAT_H__
 
-#include "linux/version.h"
-
-#define INIT_CONSOLE(dev_name, write_proc, device_proc, setup_proc, f) { \
-	name :		dev_name, \
-	write :		write_proc, \
-	read :		NULL, \
-	device :	device_proc, \
-	setup :		setup_proc, \
-	flags :		f, \
-	index :		-1, \
-	cflag :		0, \
-	next :		NULL \
-}
-
 #define INIT_HARDSECT(arr, maj, sizes)
 
 #define SET_PRI(task) do ; while(0)
diff --git a/arch/um/include/irq_kern.h b/arch/um/include/irq_kern.h
index 4bcb829d7..3af52a634 100644
--- a/arch/um/include/irq_kern.h
+++ b/arch/um/include/irq_kern.h
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
@@ -9,7 +9,7 @@
 #include "linux/interrupt.h"
 
 extern int um_request_irq(unsigned int irq, int fd, int type,
-			  irqreturn_t (*handler)(int, void *, 
+			  irqreturn_t (*handler)(int, void *,
 						 struct pt_regs *),
 			  unsigned long irqflags,  const char * devname,
 			  void *dev_id);
diff --git a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h
index 087bd39d0..0df4076ac 100644
--- a/arch/um/include/irq_user.h
+++ b/arch/um/include/irq_user.h
@@ -14,6 +14,7 @@ extern void free_irq_by_irq_and_dev(int irq, void *dev_id);
 extern void free_irq_by_fd(int fd);
 extern void reactivate_fd(int fd, int irqnum);
 extern void deactivate_fd(int fd, int irqnum);
+extern int deactivate_all_fds(void);
 extern void forward_interrupts(int pid);
 extern void init_irq_signals(int on_sigstack);
 extern void forward_ipi(int fd, int pid);
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 09e76a308..eace6b208 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -60,12 +60,11 @@ extern void finish_fork(void);
 extern void paging_init(void);
 extern void init_flush_vm(void);
 extern void *syscall_sp(void *t);
-extern void syscall_trace(void);
+extern void syscall_trace(union uml_pt_regs *regs, int entryexit);
 extern int hz(void);
-extern void idle_timer(void);
+extern void uml_idle_timer(void);
 extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs);
 extern int external_pid(void *t);
-extern int pid_to_processor_id(int pid);
 extern void boot_timer_handler(int sig);
 extern void interrupt_end(void);
 extern void initial_thread_cb(void (*proc)(void *), void *arg);
@@ -89,9 +88,7 @@ extern int remove_gdb(void);
 extern char *uml_strdup(char *string);
 extern void unprotect_kernel_mem(void);
 extern void protect_kernel_mem(void);
-extern void set_kmem_end(unsigned long);
 extern void uml_cleanup(void);
-extern int pid_to_processor_id(int pid);
 extern void set_current(void *t);
 extern void lock_signalled_task(void *t);
 extern void IPI_handler(int cpu);
@@ -100,7 +97,9 @@ extern void *get_init_task(void);
 extern int clear_user_proc(void *buf, int size);
 extern int copy_to_user_proc(void *to, void *from, int size);
 extern int copy_from_user_proc(void *to, void *from, int size);
+extern int strlen_user_proc(char *str);
 extern void bus_handler(int sig, union uml_pt_regs *regs);
+extern void winch(int sig, union uml_pt_regs *regs);
 extern long execute_syscall(void *r);
 extern int smp_sigio_handler(void);
 extern void *get_current(void);
@@ -111,6 +110,8 @@ extern void arch_switch(void);
 extern void free_irq(unsigned int, void *);
 extern int um_in_interrupt(void);
 extern int cpu(void);
+extern unsigned long long time_stamp(void);
+
 #endif
 
 /*
diff --git a/arch/um/include/line.h b/arch/um/include/line.h
index e9783dc16..31911329f 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -9,12 +9,14 @@
 #include "linux/list.h"
 #include "linux/workqueue.h"
 #include "linux/tty.h"
+#include "linux/interrupt.h"
 #include "asm/semaphore.h"
 #include "chan_user.h"
 #include "mconsole_kern.h"
 
 struct line_driver {
 	char *name;
+	char *device_name;
 	char *devfs_name;
 	short major;
 	short minor_start;
@@ -67,8 +69,6 @@ struct lines {
 
 #define LINES_INIT(n) {  num :		n }
 
-extern void line_interrupt(int irq, void *data, struct pt_regs *unused);
-extern void line_write_interrupt(int irq, void *data, struct pt_regs *unused);
 extern void line_close(struct line *lines, struct tty_struct *tty);
 extern int line_open(struct line *lines, struct tty_struct *tty, 
 		     struct chan_opts *opts);
diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h
index 7eea2fac0..9fbe3083f 100644
--- a/arch/um/include/mconsole.h
+++ b/arch/um/include/mconsole.h
@@ -41,11 +41,13 @@ struct mconsole_notify {
 
 struct mc_request;
 
+enum mc_context { MCONSOLE_INTR, MCONSOLE_PROC };
+
 struct mconsole_command
 {
 	char *command;
 	void (*handler)(struct mc_request *req);
-	int as_interrupt;
+	enum mc_context context;
 };
 
 struct mc_request
@@ -77,6 +79,8 @@ extern void mconsole_sysrq(struct mc_request *req);
 extern void mconsole_cad(struct mc_request *req);
 extern void mconsole_stop(struct mc_request *req);
 extern void mconsole_go(struct mc_request *req);
+extern void mconsole_log(struct mc_request *req);
+extern void mconsole_proc(struct mc_request *req);
 
 extern int mconsole_get_request(int fd, struct mc_request *req);
 extern int mconsole_notify(char *sock_name, int type, const void *data, 
diff --git a/arch/um/include/mem.h b/arch/um/include/mem.h
index bad6b30b8..10c46c389 100644
--- a/arch/um/include/mem.h
+++ b/arch/um/include/mem.h
@@ -1,19 +1,18 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002, 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
 #ifndef __MEM_H__
 #define __MEM_H__
 
-struct vm_reserved {
-	struct list_head list;
-	unsigned long start;
-	unsigned long end;
-};
+#include "linux/types.h"
 
-extern void set_usable_vm(unsigned long start, unsigned long end);
-extern void set_kmem_end(unsigned long new);
+extern int phys_mapping(unsigned long phys, __u64 *offset_out);
+extern int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w);
+extern int is_remapped(void *virt);
+extern int physmem_remove_mapping(void *virt);
+extern void physmem_forget_descriptor(int fd);
 
 #endif
 
diff --git a/arch/um/include/mem_kern.h b/arch/um/include/mem_kern.h
index b39f03d94..cb7e196d3 100644
--- a/arch/um/include/mem_kern.h
+++ b/arch/um/include/mem_kern.h
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
diff --git a/arch/um/include/mem_user.h b/arch/um/include/mem_user.h
index d80ac354b..f530ac3f8 100644
--- a/arch/um/include/mem_user.h
+++ b/arch/um/include/mem_user.h
@@ -32,43 +32,38 @@
 #ifndef _MEM_USER_H
 #define _MEM_USER_H
 
-struct mem_region {
+struct iomem_region {
+	struct iomem_region *next;
 	char *driver;
-	unsigned long start_pfn;
-	unsigned long start;
-	unsigned long len;
-	void *mem_map;
 	int fd;
+	int size;
+	unsigned long phys;
+	unsigned long virt;
 };
 
-extern struct mem_region *regions[];
-extern struct mem_region physmem_region;
+extern struct iomem_region *iomem_regions;
+extern int iomem_size;
 
 #define ROUND_4M(n) ((((unsigned long) (n)) + (1 << 22)) & ~((1 << 22) - 1))
 
 extern unsigned long host_task_size;
 extern unsigned long task_size;
 
+extern void check_devanon(void);
 extern int init_mem_user(void);
 extern int create_mem_file(unsigned long len);
-extern void setup_range(int fd, char *driver, unsigned long start,
-			unsigned long pfn, unsigned long total, int need_vm, 
-			struct mem_region *region, void *reserved);
 extern void setup_memory(void *entry);
 extern unsigned long find_iomem(char *driver, unsigned long *len_out);
-extern int init_maps(struct mem_region *region);
-extern int nregions(void);
-extern int reserve_vm(unsigned long start, unsigned long end, void *e);
+extern int init_maps(unsigned long physmem, unsigned long iomem,
+		     unsigned long highmem);
 extern unsigned long get_vm(unsigned long len);
 extern void setup_physmem(unsigned long start, unsigned long usable,
-			  unsigned long len);
-extern int setup_region(struct mem_region *region, void *entry);
+			  unsigned long len, unsigned long highmem);
 extern void add_iomem(char *name, int fd, unsigned long size);
-extern struct mem_region *phys_region(unsigned long phys);
 extern unsigned long phys_offset(unsigned long phys);
 extern void unmap_physmem(void);
-extern int map_memory(unsigned long virt, unsigned long phys, 
-		      unsigned long len, int r, int w, int x);
+extern void map_memory(unsigned long virt, unsigned long phys,
+		       unsigned long len, int r, int w, int x);
 extern int protect_memory(unsigned long addr, unsigned long len, 
 			  int r, int w, int x, int must_succeed);
 extern unsigned long get_kmem_end(void);
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index b9b1f0c1d..8c4011265 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -17,6 +17,32 @@
 #define OS_TYPE_FIFO 6
 #define OS_TYPE_SOCK 7
 
+/* os_access() flags */
+#define OS_ACC_F_OK    0       /* Test for existence.  */
+#define OS_ACC_X_OK    1       /* Test for execute permission.  */
+#define OS_ACC_W_OK    2       /* Test for write permission.  */
+#define OS_ACC_R_OK    4       /* Test for read permission.  */
+#define OS_ACC_RW_OK   (OS_ACC_W_OK | OS_ACC_R_OK) /* Test for RW permission */
+
+/*
+ * types taken from stat_file() in hostfs_user.c
+ * (if they are wrong here, they are wrong there...).
+ */
+struct uml_stat {
+	int                ust_dev;        /* device */
+	unsigned long long ust_ino;        /* inode */
+	int                ust_mode;       /* protection */
+	int                ust_nlink;      /* number of hard links */
+	int                ust_uid;        /* user ID of owner */
+	int                ust_gid;        /* group ID of owner */
+	unsigned long long ust_size;       /* total size, in bytes */
+	int                ust_blksize;    /* blocksize for filesystem I/O */
+	unsigned long long ust_blocks;     /* number of blocks allocated */
+	unsigned long      ust_atime;      /* time of last access */
+	unsigned long      ust_mtime;      /* time of last modification */
+	unsigned long      ust_ctime;      /* time of last change */
+};
+
 struct openflags {
 	unsigned int r : 1;
 	unsigned int w : 1;
@@ -84,29 +110,48 @@ static inline struct openflags of_excl(struct openflags flags)
 	flags.e = 1; 
 	return(flags); 
 }
- 
+
 static inline struct openflags of_cloexec(struct openflags flags)
 { 
 	flags.cl = 1; 
 	return(flags); 
 }
   
+extern int os_stat_file(const char *file_name, struct uml_stat *buf);
+extern int os_stat_fd(const int fd, struct uml_stat *buf);
+extern int os_access(const char *file, int mode);
+extern void os_print_error(int error, const char* str);
+extern int os_get_exec_close(int fd, int *close_on_exec);
+extern int os_set_exec_close(int fd, int close_on_exec);
+extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg);
+extern int os_window_size(int fd, int *rows, int *cols);
+extern int os_new_tty_pgrp(int fd, int pid);
+extern int os_get_ifname(int fd, char *namebuf);
+extern int os_set_slip(int fd);
+extern int os_set_owner(int fd, int pid);
+extern int os_sigio_async(int master, int slave);
+extern int os_mode_fd(int fd, int mode);
+
 extern int os_seek_file(int fd, __u64 offset);
 extern int os_open_file(char *file, struct openflags flags, int mode);
 extern int os_read_file(int fd, void *buf, int len);
-extern int os_write_file(int fd, void *buf, int count);
+extern int os_write_file(int fd, const void *buf, int count);
 extern int os_file_size(char *file, long long *size_out);
+extern int os_file_modtime(char *file, unsigned long *modtime);
 extern int os_pipe(int *fd, int stream, int close_on_exec);
 extern int os_set_fd_async(int fd, int owner);
+extern int os_clear_fd_async(int fd);
 extern int os_set_fd_block(int fd, int blocking);
 extern int os_accept_connection(int fd);
+extern int os_create_unix_socket(char *file, int len, int close_on_exec);
 extern int os_shutdown_socket(int fd, int r, int w);
 extern void os_close_file(int fd);
 extern int os_rcv_fd(int fd, int *helper_pid_out);
-extern int create_unix_socket(char *file, int len);
+extern int create_unix_socket(char *file, int len, int close_on_exec);
 extern int os_connect_socket(char *name);
 extern int os_file_type(char *file);
 extern int os_file_mode(char *file, struct openflags *mode_out);
+extern int os_lock_file(int fd, int excl);
 
 extern unsigned long os_process_pc(int pid);
 extern int os_process_parent(int pid);
@@ -115,11 +160,13 @@ extern void os_kill_process(int pid, int reap_child);
 extern void os_usr1_process(int pid);
 extern int os_getpid(void);
 
-extern int os_map_memory(void *virt, int fd, unsigned long off, 
+extern int os_map_memory(void *virt, int fd, unsigned long long off,
 			 unsigned long len, int r, int w, int x);
 extern int os_protect_memory(void *addr, unsigned long len, 
 			     int r, int w, int x);
 extern int os_unmap_memory(void *addr, int len);
+extern void os_flush_stdout(void);
+extern unsigned long long os_usecs(void);
 
 #endif
 
diff --git a/arch/um/include/signal_user.h b/arch/um/include/signal_user.h
index adaea4d5a..b075e543d 100644
--- a/arch/um/include/signal_user.h
+++ b/arch/um/include/signal_user.h
@@ -11,6 +11,8 @@ extern int signal_stack_size;
 extern int change_sig(int signal, int on);
 extern void set_sigstack(void *stack, int size);
 extern void set_handler(int sig, void (*handler)(int), int flags, ...);
+extern int set_signals(int enable);
+extern int get_signals(void);
 
 #endif
 
diff --git a/arch/um/include/skas_ptrace.h b/arch/um/include/skas_ptrace.h
index 7cd983d88..cfb5fb4f5 100644
--- a/arch/um/include/skas_ptrace.h
+++ b/arch/um/include/skas_ptrace.h
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
 
diff --git a/arch/um/include/sysdep-i386/checksum.h b/arch/um/include/sysdep-i386/checksum.h
index d1ca652a7..bb6b343f1 100644
--- a/arch/um/include/sysdep-i386/checksum.h
+++ b/arch/um/include/sysdep-i386/checksum.h
@@ -5,6 +5,7 @@
 #ifndef __UM_SYSDEP_CHECKSUM_H
 #define __UM_SYSDEP_CHECKSUM_H
 
+#include "linux/in6.h"
 #include "linux/string.h"
 
 /*
@@ -102,7 +103,8 @@ static inline unsigned short ip_fast_csum(unsigned char * iph,
 	   are modified, we must also specify them as outputs, or gcc
 	   will assume they contain their original values. */
 	: "=r" (sum), "=r" (iph), "=r" (ihl)
-	: "1" (iph), "2" (ihl));
+	: "1" (iph), "2" (ihl)
+	: "memory");
 	return(sum);
 }
 
diff --git a/arch/um/include/sysdep-i386/frame_user.h b/arch/um/include/sysdep-i386/frame_user.h
index b4065b235..13faf079a 100644
--- a/arch/um/include/sysdep-i386/frame_user.h
+++ b/arch/um/include/sysdep-i386/frame_user.h
@@ -56,26 +56,26 @@ static inline void setup_arch_frame(struct arch_frame_data_raw *in,
  * it would have to be __builtin_frame_address(1).
  */
 
-static inline unsigned long frame_restorer(void)
-{
-	unsigned long *fp;
-
-	fp = __builtin_frame_address(0);
-	return((unsigned long) (fp + 1));
-}
+#define frame_restorer() \
+({ \
+	unsigned long *fp; \
+\
+	fp = __builtin_frame_address(0); \
+	((unsigned long) (fp + 1)); \
+})
 
 /* Similarly, this returns the value of sp when the handler was first
  * entered.  This is used to calculate the proper sp when delivering
  * signals.
  */
 
-static inline unsigned long frame_sp(void)
-{
-	unsigned long *fp;
-
-	fp = __builtin_frame_address(0);
-	return((unsigned long) (fp + 1));
-}
+#define frame_sp() \
+({ \
+	unsigned long *fp; \
+\
+	fp = __builtin_frame_address(0); \
+	((unsigned long) (fp + 1)); \
+})
 
 #endif
 
diff --git a/arch/um/include/sysdep-i386/sigcontext.h b/arch/um/include/sysdep-i386/sigcontext.h
index 26c70cf8b..887fdb61e 100644
--- a/arch/um/include/sysdep-i386/sigcontext.h
+++ b/arch/um/include/sysdep-i386/sigcontext.h
@@ -28,8 +28,8 @@
  */
 #define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0)
 
-/* These are General Protection and Page Fault */
-#define SEGV_IS_FIXABLE(trap) ((trap == 13) || (trap == 14))
+/* This is Page Fault */
+#define SEGV_IS_FIXABLE(trap) (trap == 14)
 
 #define SC_SEGV_IS_FIXABLE(sc) (SEGV_IS_FIXABLE(SC_TRAPNO(sc)))
 
diff --git a/arch/um/include/sysdep-i386/syscalls.h b/arch/um/include/sysdep-i386/syscalls.h
index 08d7c1323..47687dcf2 100644
--- a/arch/um/include/sysdep-i386/syscalls.h
+++ b/arch/um/include/sysdep-i386/syscalls.h
@@ -11,39 +11,34 @@ typedef long syscall_handler_t(struct pt_regs);
 #define EXECUTE_SYSCALL(syscall, regs) \
 	((long (*)(struct syscall_args)) (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
 
-extern syscall_handler_t sys_modify_ldt;
-extern syscall_handler_t old_mmap_i386;
-extern syscall_handler_t old_select;
-extern syscall_handler_t sys_ni_syscall;
-
 #define ARCH_SYSCALLS \
-	[ __NR_mmap ] = old_mmap_i386, \
-	[ __NR_select ] = old_select, \
-	[ __NR_vm86old ] = sys_ni_syscall, \
-        [ __NR_modify_ldt ] = sys_modify_ldt, \
-	[ __NR_lchown32 ] = sys_lchown, \
-	[ __NR_getuid32 ] = sys_getuid, \
-	[ __NR_getgid32 ] = sys_getgid, \
-	[ __NR_geteuid32 ] = sys_geteuid, \
-	[ __NR_getegid32 ] = sys_getegid, \
-	[ __NR_setreuid32 ] = sys_setreuid, \
-	[ __NR_setregid32 ] = sys_setregid, \
-	[ __NR_getgroups32 ] = sys_getgroups, \
-	[ __NR_setgroups32 ] = sys_setgroups, \
-	[ __NR_fchown32 ] = sys_fchown, \
-	[ __NR_setresuid32 ] = sys_setresuid, \
-	[ __NR_getresuid32 ] = sys_getresuid, \
-	[ __NR_setresgid32 ] = sys_setresgid, \
-	[ __NR_getresgid32 ] = sys_getresgid, \
-	[ __NR_chown32 ] = sys_chown, \
-	[ __NR_setuid32 ] = sys_setuid, \
-	[ __NR_setgid32 ] = sys_setgid, \
-	[ __NR_setfsuid32 ] = sys_setfsuid, \
-	[ __NR_setfsgid32 ] = sys_setfsgid, \
-	[ __NR_pivot_root ] = sys_pivot_root, \
-	[ __NR_mincore ] = sys_mincore, \
-	[ __NR_madvise ] = sys_madvise, \
-        [ 222 ] = sys_ni_syscall, 
+	[ __NR_mmap ] = (syscall_handler_t *) old_mmap_i386, \
+	[ __NR_select ] = (syscall_handler_t *) old_select, \
+	[ __NR_vm86old ] = (syscall_handler_t *) sys_ni_syscall, \
+        [ __NR_modify_ldt ] = (syscall_handler_t *) sys_modify_ldt, \
+	[ __NR_lchown32 ] = (syscall_handler_t *) sys_lchown, \
+	[ __NR_getuid32 ] = (syscall_handler_t *) sys_getuid, \
+	[ __NR_getgid32 ] = (syscall_handler_t *) sys_getgid, \
+	[ __NR_geteuid32 ] = (syscall_handler_t *) sys_geteuid, \
+	[ __NR_getegid32 ] = (syscall_handler_t *) sys_getegid, \
+	[ __NR_setreuid32 ] = (syscall_handler_t *) sys_setreuid, \
+	[ __NR_setregid32 ] = (syscall_handler_t *) sys_setregid, \
+	[ __NR_getgroups32 ] = (syscall_handler_t *) sys_getgroups, \
+	[ __NR_setgroups32 ] = (syscall_handler_t *) sys_setgroups, \
+	[ __NR_fchown32 ] = (syscall_handler_t *) sys_fchown, \
+	[ __NR_setresuid32 ] = (syscall_handler_t *) sys_setresuid, \
+	[ __NR_getresuid32 ] = (syscall_handler_t *) sys_getresuid, \
+	[ __NR_setresgid32 ] = (syscall_handler_t *) sys_setresgid, \
+	[ __NR_getresgid32 ] = (syscall_handler_t *) sys_getresgid, \
+	[ __NR_chown32 ] = (syscall_handler_t *) sys_chown, \
+	[ __NR_setuid32 ] = (syscall_handler_t *) sys_setuid, \
+	[ __NR_setgid32 ] = (syscall_handler_t *) sys_setgid, \
+	[ __NR_setfsuid32 ] = (syscall_handler_t *) sys_setfsuid, \
+	[ __NR_setfsgid32 ] = (syscall_handler_t *) sys_setfsgid, \
+	[ __NR_pivot_root ] = (syscall_handler_t *) sys_pivot_root, \
+	[ __NR_mincore ] = (syscall_handler_t *) sys_mincore, \
+	[ __NR_madvise ] = (syscall_handler_t *) sys_madvise, \
+        [ 222 ] = (syscall_handler_t *) sys_ni_syscall,
         
 /* 222 doesn't yet have a name in include/asm-i386/unistd.h */
 
diff --git a/arch/um/include/time_user.h b/arch/um/include/time_user.h
index 9ddb749f7..6793a2fcd 100644
--- a/arch/um/include/time_user.h
+++ b/arch/um/include/time_user.h
@@ -11,6 +11,7 @@ extern void switch_timers(int to_real);
 extern void set_interval(int timer_type);
 extern void idle_sleep(int secs);
 extern void enable_timer(void);
+extern void disable_timer(void);
 extern unsigned long time_lock(void);
 extern void time_unlock(unsigned long);
 
diff --git a/arch/um/include/ubd_user.h b/arch/um/include/ubd_user.h
index b28beaf58..9bac59c4c 100644
--- a/arch/um/include/ubd_user.h
+++ b/arch/um/include/ubd_user.h
@@ -9,7 +9,7 @@
 
 #include "os.h"
 
-enum ubd_req { UBD_READ, UBD_WRITE };
+enum ubd_req { UBD_READ, UBD_WRITE, UBD_MMAP };
 
 struct io_thread_req {
 	enum ubd_req op;
@@ -20,8 +20,10 @@ struct io_thread_req {
 	char *buffer;
 	int sectorsize;
 	unsigned long sector_mask;
-	unsigned long cow_offset;
+	unsigned long long cow_offset;
 	unsigned long bitmap_words[2];
+	int map_fd;
+	unsigned long long map_offset;
 	int error;
 };
 
@@ -31,7 +33,7 @@ extern int open_ubd_file(char *file, struct openflags *openflags,
 			 int *create_cow_out);
 extern int create_cow_file(char *cow_file, char *backing_file, 
 			   struct openflags flags, int sectorsize, 
-			   int *bitmap_offset_out, 
+			   int alignment, int *bitmap_offset_out,
 			   unsigned long *bitmap_len_out,
 			   int *data_offset_out);
 extern int read_cow_bitmap(int fd, void *buf, int offset, int len);
@@ -39,7 +41,6 @@ extern int read_ubd_fs(int fd, void *buffer, int len);
 extern int write_ubd_fs(int fd, char *buffer, int len);
 extern int start_io_thread(unsigned long sp, int *fds_out);
 extern void do_io(struct io_thread_req *req);
-extern int ubd_is_dir(char *file);
 
 static inline int ubd_test_bit(__u64 bit, unsigned char *data)
 {
diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h
index 41afa3a8f..c9b3574c6 100644
--- a/arch/um/include/um_uaccess.h
+++ b/arch/um/include/um_uaccess.h
@@ -38,22 +38,73 @@ static inline int copy_to_user(void *to, const void *from, int n)
 				from, n));
 }
 
+/*
+ * strncpy_from_user: - Copy a NUL terminated string from userspace.
+ * @dst:   Destination address, in kernel space.  This buffer must be at
+ *         least @count bytes long.
+ * @src:   Source address, in user space.
+ * @count: Maximum number of bytes to copy, including the trailing NUL.
+ *
+ * Copies a NUL-terminated string from userspace to kernel space.
+ *
+ * On success, returns the length of the string (not including the trailing
+ * NUL).
+ *
+ * If access to userspace fails, returns -EFAULT (some data may have been
+ * copied).
+ *
+ * If @count is smaller than the length of the string, copies @count bytes
+ * and returns @count.
+ */
+
 static inline int strncpy_from_user(char *dst, const char *src, int count)
 {
 	return(CHOOSE_MODE_PROC(strncpy_from_user_tt, strncpy_from_user_skas,
 				dst, src, count));
 }
 
+/*
+ * __clear_user: - Zero a block of memory in user space, with less checking.
+ * @to:   Destination address, in user space.
+ * @n:    Number of bytes to zero.
+ *
+ * Zero a block of memory in user space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be cleared.
+ * On success, this will be zero.
+ */
 static inline int __clear_user(void *mem, int len)
 {
 	return(CHOOSE_MODE_PROC(__clear_user_tt, __clear_user_skas, mem, len));
 }
 
+/*
+ * clear_user: - Zero a block of memory in user space.
+ * @to:   Destination address, in user space.
+ * @n:    Number of bytes to zero.
+ *
+ * Zero a block of memory in user space.
+ *
+ * Returns number of bytes that could not be cleared.
+ * On success, this will be zero.
+ */
 static inline int clear_user(void *mem, int len)
 {
 	return(CHOOSE_MODE_PROC(clear_user_tt, clear_user_skas, mem, len));
 }
 
+/*
+ * strlen_user: - Get the size of a string in user space.
+ * @str: The string to measure.
+ * @n:   The maximum valid length
+ *
+ * Get the size of a NUL-terminated string in user space.
+ *
+ * Returns the size of the string INCLUDING the terminating NUL.
+ * On exception, returns 0.
+ * If the string is too long, returns a value greater than @n.
+ */
 static inline int strnlen_user(const void *str, int len)
 {
 	return(CHOOSE_MODE_PROC(strnlen_user_tt, strnlen_user_skas, str, len));
diff --git a/arch/um/include/user.h b/arch/um/include/user.h
index 6f009be0f..57ee9e261 100644
--- a/arch/um/include/user.h
+++ b/arch/um/include/user.h
@@ -14,6 +14,9 @@ extern void *um_kmalloc_atomic(int size);
 extern void kfree(void *ptr);
 extern int in_aton(char *str);
 extern int open_gdb_chan(void);
+extern int strlcpy(char *, const char *, int);
+extern void *um_vmalloc(int size);
+extern void vfree(void *ptr);
 
 #endif
 
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index e87b8fcb0..ab089d7a7 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -8,14 +8,14 @@
 
 #include "sysdep/ptrace.h"
 
+#define CATCH_EINTR(expr) while (((expr) < 0) && (errno == EINTR))
+
 extern int mode_tt;
 
 extern int grantpt(int __fd);
 extern int unlockpt(int __fd);
 extern char *ptsname(int __fd);
 
-enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
-
 struct cpu_task {
 	int pid;
 	void *task;
@@ -59,13 +59,11 @@ extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
 extern void *add_signal_handler(int sig, void (*handler)(int));
 extern int start_fork_tramp(void *arg, unsigned long temp_stack, 
 			    int clone_flags, int (*tramp)(void *));
-extern int clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags);
 extern int linux_main(int argc, char **argv);
 extern void set_cmdline(char *cmd);
 extern void input_cb(void (*proc)(void *), void *arg, int arg_len);
 extern int get_pty(void);
 extern void *um_kmalloc(int size);
-extern int raw(int fd, int complain);
 extern int switcheroo(int fd, int prot, void *from, void *to, int size);
 extern void setup_machinename(char *machine_out);
 extern void setup_hostinfo(void);
@@ -76,7 +74,6 @@ extern void do_exec(int old_pid, int new_pid);
 extern void tracer_panic(char *msg, ...);
 extern char *get_umid(int only_if_set);
 extern void do_longjmp(void *p, int val);
-extern void suspend_new_thread(int fd);
 extern int detach(int pid, int sig);
 extern int attach(int pid);
 extern void kill_child_dead(int pid);
@@ -86,11 +83,15 @@ extern void check_sigio(void);
 extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr);
 extern void write_sigio_workaround(void);
 extern void arch_check_bugs(void);
+extern int cpu_feature(char *what, char *buf, int len);
 extern int arch_handle_signal(int sig, union uml_pt_regs *regs);
 extern int arch_fixup(unsigned long address, void *sc_ptr);
 extern void forward_pending_sigio(int target);
 extern int can_do_skas(void);
- 
+extern void arch_init_thread(void);
+extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
+extern int raw(int fd);
+
 #endif
 
 /*
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 0f13dd4c7..9fa9711ec 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -3,15 +3,16 @@
 # Licensed under the GPL
 #
 
-extra-y := vmlinux.lds.s
+extra-y := vmlinux.lds
+clean-files := vmlinux.lds.S
 
 obj-y = checksum.o config.o exec_kern.o exitcode.o frame_kern.o frame.o \
-	helper.o init_task.o irq.o irq_user.o ksyms.o mem.o mem_user.o \
-	process.o process_kern.o ptrace.o reboot.o resource.o sigio_user.o \
-	sigio_kern.o signal_kern.o signal_user.o smp.o syscall_kern.o \
-	syscall_user.o sysrq.o sys_call_table.o tempfile.o time.o \
-	time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o \
-	umid.o user_syms.o user_util.o
+	helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o mem_user.o \
+	physmem.o process.o process_kern.o ptrace.o reboot.o resource.o \
+	sigio_user.o sigio_kern.o signal_kern.o signal_user.o smp.o \
+	syscall_kern.o syscall_user.o sysrq.o sys_call_table.o tempfile.o \
+	time.o time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o \
+	um_arch.o umid.o user_util.o
 
 obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o
 obj-$(CONFIG_GPROF)	+= gprof_syms.o
@@ -24,43 +25,19 @@ obj-$(CONFIG_MODE_SKAS) += skas/
 user-objs-$(CONFIG_TTY_LOG) += tty_log.o
 
 USER_OBJS := $(filter %_user.o,$(obj-y))  $(user-objs-y) config.o helper.o \
-	process.o tempfile.o time.o tty_log.o umid.o user_util.o user_syms.o
+	main.o process.o tempfile.o time.o tty_log.o umid.o user_util.o frame.o
 USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
 
-DMODULES-$(CONFIG_MODULES) = -D__CONFIG_MODULES__
-DMODVERSIONS-$(CONFIG_MODVERSIONS) = -D__CONFIG_MODVERSIONS__
-
-
-CFLAGS_user_syms.o = -D__AUTOCONF_INCLUDED__ $(DMODULES-y) $(DMODVERSIONS-y) \
-	-I/usr/include -I../include
-
-CFLAGS_frame.o := $(patsubst -fomit-frame-pointer,,$(USER_CFLAGS))
+CFLAGS_frame.o := -fno-omit-frame-pointer
 
 $(USER_OBJS) : %.o: %.c
-	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-# This has to be separate because it needs be compiled with frame pointers
-# regardless of how the rest of the kernel is built.
-
-$(obj)/frame.o: $(src)/frame.c
-	$(CC) $(CFLAGS_$(notdir $@)) -c -o $@ $<
-
-QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; while(<STDIN>) { $$_ =~ s/CONFIG/$$config/; print $$_ }'
-
-$(obj)/config.c : $(src)/config.c.in $(TOPDIR)/.config
-	$(PERL) -e $(QUOTE) < $(src)/config.c.in > $@
-
-$(obj)/config.o : $(obj)/config.c
-
-clean:
-	rm -f config.c
-	for dir in $(subdir-y) ; do $(MAKE) -C $$dir clean; done
-
-modules:
-
-fastdep:
+	$(CC) $(USER_CFLAGS) $(CFLAGS_$(notdir $@)) -c -o $@ $<
 
-dep:
+QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; $$config =~ s/\n/\\n"\n"/g ; while(<STDIN>) { $$_ =~ s/CONFIG/$$config/; print $$_ }'
 
-archmrproper: clean
+quiet_cmd_quote = QUOTE   $@
+cmd_quote = $(PERL) -e $(QUOTE) < $< > $@
 
+targets += config.c
+$(obj)/config.c : $(src)/config.c.in $(TOPDIR)/.config FORCE
+	$(call if_changed,quote)
diff --git a/arch/um/kernel/config.c.in b/arch/um/kernel/config.c.in
index f6c96b955..c062cbfe3 100644
--- a/arch/um/kernel/config.c.in
+++ b/arch/um/kernel/config.c.in
@@ -7,9 +7,7 @@
 #include <stdlib.h>
 #include "init.h"
 
-static __initdata char *config = "
-CONFIG
-";
+static __initdata char *config = "CONFIG";
 
 static int __init print_config(char *line, int *add)
 {
diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c
index a6be6b542..a5f21283d 100644
--- a/arch/um/kernel/exec_kern.c
+++ b/arch/um/kernel/exec_kern.c
@@ -32,10 +32,15 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
 	CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp);
 }
 
+extern void log_exec(char **argv, void *tty);
+
 static int execve1(char *file, char **argv, char **env)
 {
         int error;
 
+#ifdef CONFIG_TTY_LOG
+	log_exec(argv, current->tty);
+#endif
         error = do_execve(file, argv, env, &current->thread.regs);
         if (error == 0){
                 current->ptrace &= ~PT_DTRACE;
diff --git a/arch/um/kernel/frame.c b/arch/um/kernel/frame.c
index d8993f293..4b349f207 100644
--- a/arch/um/kernel/frame.c
+++ b/arch/um/kernel/frame.c
@@ -21,6 +21,7 @@
 #include "sysdep/sigcontext.h"
 #include "frame_user.h"
 #include "kern_util.h"
+#include "user_util.h"
 #include "ptrace_user.h"
 #include "os.h"
 
@@ -40,7 +41,7 @@ static int capture_stack(int (*child)(void *arg), void *arg, void *sp,
 	/* Wait for it to stop itself and continue it with a SIGUSR1 to force 
 	 * it into the signal handler.
 	 */
-	n = waitpid(pid, &status, WUNTRACED);
+	CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
 	if(n < 0){
 		printf("capture_stack : waitpid failed - errno = %d\n", errno);
 		exit(1);
@@ -60,7 +61,7 @@ static int capture_stack(int (*child)(void *arg), void *arg, void *sp,
 	 * At this point, the handler has stuffed the addresses of
 	 * sig, sc, and SA_RESTORER in raw.
 	 */
-	n = waitpid(pid, &status, WUNTRACED);
+	CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
 	if(n < 0){
 		printf("capture_stack : waitpid failed - errno = %d\n", errno);
 		exit(1);
@@ -82,7 +83,8 @@ static int capture_stack(int (*child)(void *arg), void *arg, void *sp,
 		       errno);
 		exit(1);
 	}
-	if(waitpid(pid, &status, 0) < 0){
+	CATCH_EINTR(n = waitpid(pid, &status, 0));
+	if(n < 0){
 		printf("capture_stack : waitpid failed - errno = %d\n", errno);
 		exit(1);
 	}
@@ -279,7 +281,7 @@ void capture_signal_stack(void)
 	struct sc_frame_raw raw_sc;
 	struct si_frame_raw raw_si;
 	void *stack, *sigstack;
-	unsigned long top, sig_top, base;
+	unsigned long top, base;
 
 	stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
 		     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
@@ -292,7 +294,6 @@ void capture_signal_stack(void)
 	}
 
 	top = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
-	sig_top = (unsigned long) sigstack + PAGE_SIZE;
 
 	/* Get the sigcontext, no sigrestorer layout */
 	raw_sc.restorer = 0;
diff --git a/arch/um/kernel/frame_kern.c b/arch/um/kernel/frame_kern.c
index 9ff437466..809002dad 100644
--- a/arch/um/kernel/frame_kern.c
+++ b/arch/um/kernel/frame_kern.c
@@ -6,7 +6,6 @@
 #include "asm/ptrace.h"
 #include "asm/uaccess.h"
 #include "asm/signal.h"
-#include "asm/uaccess.h"
 #include "asm/ucontext.h"
 #include "frame_kern.h"
 #include "sigcontext.h"
@@ -29,12 +28,15 @@ static int copy_restorer(void (*restorer)(void), unsigned long start,
 			    sizeof(restorer)));
 }
 
+extern int userspace_pid[];
+
 static int copy_sc_to_user(void *to, void *fp, struct pt_regs *from, 
 			   struct arch_frame_data *arch)
 {
 	return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), 
 					      arch),
-			   copy_sc_to_user_skas(to, fp, &from->regs,
+			   copy_sc_to_user_skas(userspace_pid[0], to, fp,
+						&from->regs,
 						current->thread.cr2,
 						current->thread.err)));
 }
diff --git a/arch/um/kernel/helper.c b/arch/um/kernel/helper.c
index 5c4b27942..0e3d409d9 100644
--- a/arch/um/kernel/helper.c
+++ b/arch/um/kernel/helper.c
@@ -7,12 +7,12 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <sched.h>
 #include <sys/signal.h>
 #include <sys/wait.h>
 #include "user.h"
 #include "kern_util.h"
+#include "user_util.h"
 #include "os.h"
 
 struct helper_data {
@@ -33,6 +33,7 @@ static int helper_child(void *arg)
 {
 	struct helper_data *data = arg;
 	char **argv = data->argv;
+	int errval;
 
 	if(helper_pause){
 		signal(SIGHUP, helper_hup);
@@ -41,8 +42,9 @@ static int helper_child(void *arg)
 	if(data->pre_exec != NULL)
 		(*data->pre_exec)(data->pre_data);
 	execvp(argv[0], argv);
+	errval = errno;
 	printk("execvp of '%s' failed - errno = %d\n", argv[0], errno);
-	write(data->fd, &errno, sizeof(errno));
+	os_write_file(data->fd, &errval, sizeof(errval));
 	os_kill_process(os_getpid(), 0);
 	return(0);
 }
@@ -59,17 +61,20 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
 	if((stack_out != NULL) && (*stack_out != 0))
 		stack = *stack_out;
 	else stack = alloc_stack(0, um_in_interrupt());
-	if(stack == 0) return(-ENOMEM);
+	if(stack == 0)
+		return(-ENOMEM);
 
 	err = os_pipe(fds, 1, 0);
-	if(err){
-		printk("run_helper : pipe failed, errno = %d\n", -err);
-		return(err);
+	if(err < 0){
+		printk("run_helper : pipe failed, err = %d\n", -err);
+		goto out_free;
 	}
-	if(fcntl(fds[1], F_SETFD, 1) != 0){
-		printk("run_helper : setting FD_CLOEXEC failed, errno = %d\n",
-		       errno);
-		return(-errno);
+
+	err = os_set_exec_close(fds[1], 1);
+	if(err < 0){
+		printk("run_helper : setting FD_CLOEXEC failed, err = %d\n",
+		       -err);
+		goto out_close;
 	}
 
 	sp = stack + page_size() - sizeof(void *);
@@ -80,23 +85,34 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
 	pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
 	if(pid < 0){
 		printk("run_helper : clone failed, errno = %d\n", errno);
-		return(-errno);
+		err = -errno;
+		goto out_close;
 	}
-	close(fds[1]);
-	n = read(fds[0], &err, sizeof(err));
+
+	os_close_file(fds[1]);
+	n = os_read_file(fds[0], &err, sizeof(err));
 	if(n < 0){
-		printk("run_helper : read on pipe failed, errno = %d\n", 
-		       errno);
-		return(-errno);
+		printk("run_helper : read on pipe failed, err = %d\n", -n);
+		err = n;
+		goto out_kill;
 	}
 	else if(n != 0){
-		waitpid(pid, NULL, 0);
-		pid = -err;
+		CATCH_EINTR(n = waitpid(pid, NULL, 0));
+		pid = -errno;
 	}
 
 	if(stack_out == NULL) free_stack(stack, 0);
         else *stack_out = stack;
 	return(pid);
+
+ out_kill:
+	os_kill_process(pid, 1);
+ out_close:
+	os_close_file(fds[0]);
+	os_close_file(fds[1]);
+ out_free:
+	free_stack(stack, 0);
+	return(err);
 }
 
 int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, 
@@ -116,10 +132,12 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
 		return(-errno);
 	}
 	if(stack_out == NULL){
-		pid = waitpid(pid, &status, 0);
-		if(pid < 0)
+		CATCH_EINTR(pid = waitpid(pid, &status, 0));
+		if(pid < 0){
 			printk("run_helper_thread - wait failed, errno = %d\n",
-			       pid);
+			       errno);
+			pid = -errno;
+		}
 		if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
 			printk("run_helper_thread - thread returned status "
 			       "0x%x\n", status);
@@ -133,7 +151,7 @@ int helper_wait(int pid, int block)
 {
 	int ret;
 
-	ret = waitpid(pid, NULL, WNOHANG);
+	CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG));
 	if(ret < 0){
 		printk("helper_wait : waitpid failed, errno = %d\n", errno);
 		return(-errno);
diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c
index be82cafe9..cd7c85be0 100644
--- a/arch/um/kernel/init_task.c
+++ b/arch/um/kernel/init_task.c
@@ -8,7 +8,6 @@
 #include "linux/module.h"
 #include "linux/sched.h"
 #include "linux/init_task.h"
-#include "linux/version.h"
 #include "linux/mqueue.h"
 #include "asm/uaccess.h"
 #include "asm/pgtable.h"
@@ -19,7 +18,7 @@ static struct fs_struct init_fs = INIT_FS;
 struct mm_struct init_mm = INIT_MM(init_mm);
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
 EXPORT_SYMBOL(init_mm);
 
 /*
@@ -44,26 +43,12 @@ union thread_union init_thread_union
 __attribute__((__section__(".data.init_task"))) = 
 { INIT_THREAD_INFO(init_task) };
 
-struct task_struct *alloc_task_struct(void)
-{
-	return((struct task_struct *) 
-	       __get_free_pages(GFP_KERNEL, CONFIG_KERNEL_STACK_ORDER));
-}
-
 void unprotect_stack(unsigned long stack)
 {
 	protect_memory(stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE, 
 		       1, 1, 0, 1);
 }
 
-void free_task_struct(struct task_struct *task)
-{
-	/* free_pages decrements the page counter and only actually frees
-	 * the pages if they are now not accessed by anything.
-	 */
-	free_pages((unsigned long) task, CONFIG_KERNEL_STACK_ORDER);
-}
-
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/kernel/initrd_user.c b/arch/um/kernel/initrd_user.c
index 944c734ca..57d5b41db 100644
--- a/arch/um/kernel/initrd_user.c
+++ b/arch/um/kernel/initrd_user.c
@@ -6,7 +6,6 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <fcntl.h>
 #include <errno.h>
 
 #include "user_util.h"
@@ -19,13 +18,15 @@ int load_initrd(char *filename, void *buf, int size)
 {
 	int fd, n;
 
-	if((fd = os_open_file(filename, of_read(OPENFLAGS()), 0)) < 0){
-		printk("Opening '%s' failed - errno = %d\n", filename, errno);
+	fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
+	if(fd < 0){
+		printk("Opening '%s' failed - err = %d\n", filename, -fd);
 		return(-1);
 	}
-	if((n = read(fd, buf, size)) != size){
-		printk("Read of %d bytes from '%s' returned %d, errno = %d\n",
-		       size, filename, n, errno);
+	n = os_read_file(fd, buf, size);
+	if(n != size){
+		printk("Read of %d bytes from '%s' failed, err = %d\n", size,
+		       filename, -n);
 		return(-1);
 	}
 	return(0);
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 0e968bb11..2b8250955 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -18,9 +18,10 @@
 #include "linux/proc_fs.h"
 #include "linux/init.h"
 #include "linux/seq_file.h"
+#include "linux/profile.h"
+#include "linux/hardirq.h"
 #include "asm/irq.h"
 #include "asm/hw_irq.h"
-#include "asm/hardirq.h"
 #include "asm/atomic.h"
 #include "asm/signal.h"
 #include "asm/system.h"
@@ -29,6 +30,7 @@
 #include "user_util.h"
 #include "kern_util.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 
 static void register_irq_proc (unsigned int irq);
 
@@ -83,65 +85,55 @@ struct hw_interrupt_type no_irq_type = {
 	end_none
 };
 
-/* Not changed */
-volatile unsigned long irq_err_count;
-
 /*
  * Generic, controller-independent functions:
  */
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
-	int i, j;
-	unsigned long flags;
+	int i = *(loff_t *) v, j;
 	struct irqaction * action;
-	char *p = buf;
+	unsigned long flags;
 
-	p += sprintf(p, "           ");
-	for (j=0; j<num_online_cpus(); j++)
-		p += sprintf(p, "CPU%d       ",j);
-	*p++ = '\n';
+	if (i == 0) {
+		seq_printf(p, "           ");
+		for (j=0; j<NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "CPU%d       ",j);
+		seq_putc(p, '\n');
+	}
 
-	for (i = 0 ; i < NR_IRQS ; i++) {
+	if (i < NR_IRQS) {
 		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
 		if (!action) 
-			goto end;
-		p += sprintf(p, "%3d: ",i);
+			goto skip;
+		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
-		p += sprintf(p, "%10u ", kstat_irqs(i));
+		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
-		for (j = 0; j < num_online_cpus(); j++)
-			p += sprintf(p, "%10u ",
-				kstat_cpu(cpu_logical_map(j)).irqs[i]);
+		for (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
-		p += sprintf(p, " %14s", irq_desc[i].handler->typename);
-		p += sprintf(p, "  %s", action->name);
+		seq_printf(p, " %14s", irq_desc[i].handler->typename);
+		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
-			p += sprintf(p, ", %s", action->name);
-		*p++ = '\n';
-	end:
+			seq_printf(p, ", %s", action->name);
+
+		seq_putc(p, '\n');
+skip:
 		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+	} else if (i == NR_IRQS) {
+		seq_printf(p, "NMI: ");
+		for (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "%10u ", nmi_count(j));
+		seq_putc(p, '\n');
 	}
-	p += sprintf(p, "\n");
-#ifdef notdef
-#ifdef CONFIG_SMP
-	p += sprintf(p, "LOC: ");
-	for (j = 0; j < num_online_cpus(); j++)
-		p += sprintf(p, "%10u ",
-			apic_timer_irqs[cpu_logical_map(j)]);
-	p += sprintf(p, "\n");
-#endif
-#endif
-	p += sprintf(p, "ERR: %10lu\n", irq_err_count);
-	return p - buf;
-}
 
-
-int show_interrupts(struct seq_file *p, void *v)
-{
-	return(0);
+	return 0;
 }
 
 /*
@@ -155,13 +147,16 @@ int handle_IRQ_event(unsigned int irq, struct pt_regs * regs,
 		     struct irqaction * action)
 {
 	int status = 1;	/* Force the "do bottom halves" bit */
+	int ret, retval = 0;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
-		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
+		retval |= ret;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
@@ -169,7 +164,7 @@ int handle_IRQ_event(unsigned int irq, struct pt_regs * regs,
 
 	local_irq_disable();
 
-	return status;
+	return retval;
 }
 
 /*
@@ -282,13 +277,12 @@ unsigned int do_IRQ(int irq, union uml_pt_regs *regs)
 	 * 0 return value means that this irq is already being
 	 * handled by some other CPU. (or is disabled)
 	 */
-	int cpu = smp_processor_id();
 	irq_desc_t *desc = irq_desc + irq;
 	struct irqaction * action;
 	unsigned int status;
 
 	irq_enter();
-	kstat_cpu(cpu).irqs[irq]++;
+	kstat_this_cpu.irqs[irq]++;
 	spin_lock(&desc->lock);
 	desc->handler->ack(irq);
 	/*
@@ -385,7 +379,7 @@ out:
  */
  
 int request_irq(unsigned int irq,
-		void (*handler)(int, void *, struct pt_regs *),
+		irqreturn_t (*handler)(int, void *, struct pt_regs *),
 		unsigned long irqflags, 
 		const char * devname,
 		void *dev_id)
@@ -433,16 +427,22 @@ int request_irq(unsigned int irq,
 EXPORT_SYMBOL(request_irq);
 
 int um_request_irq(unsigned int irq, int fd, int type,
-		   void (*handler)(int, void *, struct pt_regs *),
+		   irqreturn_t (*handler)(int, void *, struct pt_regs *),
 		   unsigned long irqflags, const char * devname,
 		   void *dev_id)
 {
-	int retval;
+	int err;
+
+	err = request_irq(irq, handler, irqflags, devname, dev_id);
+	if(err)
+		return(err);
 
-	retval = request_irq(irq, handler, irqflags, devname, dev_id);
-	if(retval) return(retval);
-	return(activate_fd(irq, fd, type, dev_id));
+	if(fd != -1)
+		err = activate_fd(irq, fd, type, dev_id);
+	return(err);
 }
+EXPORT_SYMBOL(um_request_irq);
+EXPORT_SYMBOL(reactivate_fd);
 
 /* this was setup_x86_irq but it seems pretty generic */
 int setup_irq(unsigned int irq, struct irqaction * new)
@@ -474,7 +474,8 @@ int setup_irq(unsigned int irq, struct irqaction * new)
 	 */
 	spin_lock_irqsave(&desc->lock,flags);
 	p = &desc->action;
-	if ((old = *p) != NULL) {
+	old = *p;
+	if (old != NULL) {
 		/* Can't share interrupts unless both agree to */
 		if (!(old->flags & new->flags & SA_SHIRQ)) {
 			spin_unlock_irqrestore(&desc->lock,flags);
@@ -586,12 +587,14 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer,
 					unsigned long count, void *data)
 {
 	int irq = (long) data, full_count = count, err;
-	cpumask_t new_value, tmp;
+	cpumask_t new_value;
 
 	if (!irq_desc[irq].handler->set_affinity)
 		return -EIO;
 
 	err = cpumask_parse(buffer, count, new_value);
+	if(err)
+		return(err);
 
 #ifdef CONFIG_SMP
 	/*
@@ -599,9 +602,11 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer,
 	 * way to make the system unusable accidentally :-) At least
 	 * one online CPU still has to be targeted.
 	 */
-	cpus_and(tmp, new_value, cpu_online_map);
-	if (cpus_empty(tmp))
-		return -EINVAL;
+	{ cpumask_t tmp;
+	  cpus_and(tmp, new_value, cpu_online_map);
+	  if (cpus_empty(tmp))
+		  return -EINVAL;
+	}
 #endif
 
 	irq_affinity[irq] = new_value;
@@ -610,30 +615,6 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer,
 	return full_count;
 }
 
-static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
-	if (count - len < 2)
-		return -EINVAL;
-	len += sprintf(page + len, "\n");
-	return len;
-}
-
-static int prof_cpu_mask_write_proc (struct file *file, const char *buffer,
-					unsigned long count, void *data)
-{
-	cpumask_t *mask = (cpumask_t *)data, new_value;
-	unsigned long full_count = count, err;
-
-	err = cpumask_parse(buffer, count, new_value);
-	if (err)
-		return err;
-
-	*mask = new_value;
-	return full_count;
-}
-
 #define MAX_NAMELEN 10
 
 static void register_irq_proc (unsigned int irq)
@@ -662,24 +643,15 @@ static void register_irq_proc (unsigned int irq)
 	smp_affinity_entry[irq] = entry;
 }
 
-/* Read and written as a long */
-cpumask_t prof_cpu_mask = CPU_MASK_ALL;
-
 void __init init_irq_proc (void)
 {
-	struct proc_dir_entry *entry;
 	int i;
 
 	/* create /proc/irq */
 	root_irq_dir = proc_mkdir("irq", 0);
 
 	/* create /proc/irq/prof_cpu_mask */
-	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
-
-	entry->nlink = 1;
-	entry->data = (void *)&prof_cpu_mask;
-	entry->read_proc = prof_cpu_mask_read_proc;
-	entry->write_proc = prof_cpu_mask_write_proc;
+	create_prof_cpu_mask(root_irq_dir);
 
 	/*
 	 * Create entries for all existing IRQs.
diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
index 57fe9bb72..38e66ac84 100644
--- a/arch/um/kernel/irq_user.c
+++ b/arch/um/kernel/irq_user.c
@@ -6,7 +6,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <signal.h>
 #include <string.h>
 #include <sys/poll.h>
@@ -49,7 +48,8 @@ void sigio_handler(int sig, union uml_pt_regs *regs)
 
 	if(smp_sigio_handler()) return;
 	while(1){
-		if((n = poll(pollfds, pollfds_num, 0)) < 0){
+		n = poll(pollfds, pollfds_num, 0);
+		if(n < 0){
 			if(errno == EINTR) continue;
 			printk("sigio_handler : poll returned %d, "
 			       "errno = %d\n", n, errno);
@@ -364,36 +364,47 @@ void deactivate_fd(int fd, int irqnum)
 	irq_unlock(flags);
 }
 
-void forward_ipi(int fd, int pid)
+int deactivate_all_fds(void)
 {
-	if(fcntl(fd, F_SETOWN, pid) < 0){
-		int save_errno = errno;
-		if(fcntl(fd, F_GETOWN, 0) != pid){
-			printk("forward_ipi: F_SETOWN failed, fd = %d, "
-			       "me = %d, target = %d, errno = %d\n", fd, 
-			       os_getpid(), pid, save_errno);
-		}
+	struct irq_fd *irq;
+	int err;
+
+	for(irq=active_fds;irq != NULL;irq = irq->next){
+		err = os_clear_fd_async(irq->fd);
+		if(err)
+			return(err);
 	}
+
+	return(0);
+}
+
+void forward_ipi(int fd, int pid)
+{
+	int err;
+
+	err = os_set_owner(fd, pid);
+	if(err < 0)
+		printk("forward_ipi: set_owner failed, fd = %d, me = %d, "
+		       "target = %d, err = %d\n", fd, os_getpid(), pid, -err);
 }
 
 void forward_interrupts(int pid)
 {
 	struct irq_fd *irq;
 	unsigned long flags;
+	int err;
 
 	flags = irq_lock();
 	for(irq=active_fds;irq != NULL;irq = irq->next){
-		if(fcntl(irq->fd, F_SETOWN, pid) < 0){
-			int save_errno = errno;
-			if(fcntl(irq->fd, F_GETOWN, 0) != pid){
-				/* XXX Just remove the irq rather than
-				 * print out an infinite stream of these
-				 */
-				printk("Failed to forward %d to pid %d, "
-				       "errno = %d\n", irq->fd, pid, 
-				       save_errno);
-			}
+		err = os_set_owner(irq->fd, pid);
+		if(err < 0){
+			/* XXX Just remove the irq rather than
+			 * print out an infinite stream of these
+			 */
+			printk("Failed to forward %d to pid %d, err = %d\n",
+			       irq->fd, pid, -err);
 		}
+
 		irq->pid = pid;
 	}
 	irq_unlock(flags);
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index 1f82ad73a..a867e18c6 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2004 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -8,7 +8,7 @@
 #include "linux/string.h"
 #include "linux/smp_lock.h"
 #include "linux/spinlock.h"
-#include <linux/highmem.h>
+#include "linux/highmem.h"
 #include "asm/current.h"
 #include "asm/delay.h"
 #include "asm/processor.h"
@@ -19,6 +19,7 @@
 #include "asm/tlbflush.h"
 #include "kern_util.h"
 #include "user_util.h"
+#include "mem_user.h"
 #include "os.h"
 #include "helper.h"
 
@@ -34,34 +35,67 @@ EXPORT_SYMBOL(task_size);
 EXPORT_SYMBOL(flush_tlb_range);
 EXPORT_SYMBOL(host_task_size);
 EXPORT_SYMBOL(arch_validate);
+EXPORT_SYMBOL(get_kmem_end);
 
-EXPORT_SYMBOL(region_pa);
-EXPORT_SYMBOL(region_va);
-EXPORT_SYMBOL(phys_mem_map);
-EXPORT_SYMBOL(page_mem_map);
 EXPORT_SYMBOL(page_to_phys);
 EXPORT_SYMBOL(phys_to_page);
 EXPORT_SYMBOL(high_physmem);
 EXPORT_SYMBOL(empty_zero_page);
 EXPORT_SYMBOL(um_virt_to_phys);
+EXPORT_SYMBOL(__virt_to_page);
+EXPORT_SYMBOL(to_phys);
+EXPORT_SYMBOL(to_virt);
 EXPORT_SYMBOL(mode_tt);
 EXPORT_SYMBOL(handle_page_fault);
+EXPORT_SYMBOL(find_iomem);
 
+#ifdef CONFIG_MODE_TT
+EXPORT_SYMBOL(strncpy_from_user_tt);
+EXPORT_SYMBOL(copy_from_user_tt);
+EXPORT_SYMBOL(copy_to_user_tt);
+#endif
+
+#ifdef CONFIG_MODE_SKAS
+EXPORT_SYMBOL(strncpy_from_user_skas);
+EXPORT_SYMBOL(copy_to_user_skas);
+EXPORT_SYMBOL(copy_from_user_skas);
+#endif
+EXPORT_SYMBOL(uml_strdup);
+
+EXPORT_SYMBOL(os_stat_fd);
+EXPORT_SYMBOL(os_stat_file);
+EXPORT_SYMBOL(os_access);
+EXPORT_SYMBOL(os_print_error);
+EXPORT_SYMBOL(os_get_exec_close);
+EXPORT_SYMBOL(os_set_exec_close);
 EXPORT_SYMBOL(os_getpid);
 EXPORT_SYMBOL(os_open_file);
 EXPORT_SYMBOL(os_read_file);
 EXPORT_SYMBOL(os_write_file);
 EXPORT_SYMBOL(os_seek_file);
+EXPORT_SYMBOL(os_lock_file);
+EXPORT_SYMBOL(os_ioctl_generic);
 EXPORT_SYMBOL(os_pipe);
 EXPORT_SYMBOL(os_file_type);
+EXPORT_SYMBOL(os_file_mode);
+EXPORT_SYMBOL(os_file_size);
+EXPORT_SYMBOL(os_flush_stdout);
 EXPORT_SYMBOL(os_close_file);
+EXPORT_SYMBOL(os_set_fd_async);
+EXPORT_SYMBOL(os_set_fd_block);
 EXPORT_SYMBOL(helper_wait);
 EXPORT_SYMBOL(os_shutdown_socket);
+EXPORT_SYMBOL(os_create_unix_socket);
 EXPORT_SYMBOL(os_connect_socket);
+EXPORT_SYMBOL(os_accept_connection);
+EXPORT_SYMBOL(os_rcv_fd);
 EXPORT_SYMBOL(run_helper);
 EXPORT_SYMBOL(start_thread);
 EXPORT_SYMBOL(dump_thread);
 
+EXPORT_SYMBOL(do_gettimeofday);
+EXPORT_SYMBOL(do_settimeofday);
+
 /* This is here because UML expands open to sys_open, not to a system
  * call instruction.
  */
@@ -75,10 +109,10 @@ EXPORT_SYMBOL(sys_wait4);
 /* required for SMP */
 
 extern void FASTCALL( __write_lock_failed(rwlock_t *rw));
-EXPORT_SYMBOL_NOVERS(__write_lock_failed);
+EXPORT_SYMBOL(__write_lock_failed);
 
 extern void FASTCALL( __read_lock_failed(rwlock_t *rw));
-EXPORT_SYMBOL_NOVERS(__read_lock_failed);
+EXPORT_SYMBOL(__read_lock_failed);
 
 #endif
 
@@ -90,3 +124,13 @@ EXPORT_SYMBOL(kunmap_atomic);
 EXPORT_SYMBOL(kmap_atomic_to_page);
 #endif
 
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 84a895c2a..09add571c 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -1,74 +1,66 @@
 /* 
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
-#include "linux/config.h"
-#include "linux/module.h"
-#include "linux/types.h"
+#include "linux/stddef.h"
+#include "linux/kernel.h"
 #include "linux/mm.h"
-#include "linux/fs.h"
-#include "linux/init.h"
 #include "linux/bootmem.h"
 #include "linux/swap.h"
-#include "linux/slab.h"
-#include "linux/vmalloc.h"
 #include "linux/highmem.h"
+#include "linux/gfp.h"
 #include "asm/page.h"
-#include "asm/pgtable.h"
+#include "asm/fixmap.h"
 #include "asm/pgalloc.h"
-#include "asm/bitops.h"
-#include "asm/uaccess.h"
-#include "asm/tlb.h"
 #include "user_util.h"
 #include "kern_util.h"
-#include "mem_user.h"
-#include "mem.h"
 #include "kern.h"
-#include "init.h"
-#include "os.h"
-#include "mode_kern.h"
+#include "mem_user.h"
 #include "uml_uaccess.h"
+#include "os.h"
+
+extern char __binary_start;
 
 /* Changed during early boot */
-pgd_t swapper_pg_dir[1024];
-unsigned long high_physmem;
-unsigned long vm_start;
-unsigned long vm_end;
-unsigned long highmem;
 unsigned long *empty_zero_page = NULL;
 unsigned long *empty_bad_page = NULL;
-
-/* Not modified */
-const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n";
-
-extern char __init_begin, __init_end;
-extern long physmem_size;
-
-/* Not changed by UML */
-DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
-
-/* Changed during early boot */
+pgd_t swapper_pg_dir[1024];
+unsigned long highmem;
 int kmalloc_ok = 0;
 
-#define NREGIONS (phys_region_index(0xffffffff) - phys_region_index(0x0) + 1)
-struct mem_region *regions[NREGIONS] = { [ 0 ... NREGIONS - 1 ] = NULL };
-#define REGION_SIZE ((0xffffffff & ~REGION_MASK) + 1)
-
-/* Changed during early boot */
 static unsigned long brk_end;
 
+void unmap_physmem(void)
+{
+	os_unmap_memory((void *) brk_end, uml_reserved - brk_end);
+}
+
 static void map_cb(void *unused)
 {
 	map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
 }
 
-void unmap_physmem(void)
+#ifdef CONFIG_HIGHMEM
+static void setup_highmem(unsigned long highmem_start,
+			  unsigned long highmem_len)
 {
-	os_unmap_memory((void *) brk_end, uml_reserved - brk_end);
-}
+	struct page *page;
+	unsigned long highmem_pfn;
+	int i;
 
-extern char __binary_start;
+	highmem_start_page = virt_to_page(highmem_start);
+
+	highmem_pfn = __pa(highmem_start) >> PAGE_SHIFT;
+	for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){
+		page = &mem_map[highmem_pfn + i];
+		ClearPageReserved(page);
+		set_bit(PG_highmem, &page->flags);
+		set_page_count(page, 1);
+		__free_page(page);
+	}
+}
+#endif
 
 void mem_init(void)
 {
@@ -103,50 +95,15 @@ void mem_init(void)
 	totalhigh_pages = highmem >> PAGE_SHIFT;
 	totalram_pages += totalhigh_pages;
 	num_physpages = totalram_pages;
-	max_mapnr = totalram_pages;
 	max_pfn = totalram_pages;
 	printk(KERN_INFO "Memory: %luk available\n", 
 	       (unsigned long) nr_free_pages() << (PAGE_SHIFT-10));
 	kmalloc_ok = 1;
-}
-
-/* Changed during early boot */
-static unsigned long kmem_top = 0;
-
-unsigned long get_kmem_end(void)
-{
-	if(kmem_top == 0)
-		kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas);
-	return(kmem_top);
-}
-
-void set_kmem_end(unsigned long new)
-{
-	kmem_top = new;
-}
 
 #ifdef CONFIG_HIGHMEM
-/* Changed during early boot */
-pte_t *kmap_pte;
-pgprot_t kmap_prot;
-
-EXPORT_SYMBOL(kmap_prot);
-EXPORT_SYMBOL(kmap_pte);
-
-#define kmap_get_fixmap_pte(vaddr)					\
-	pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
-
-void __init kmap_init(void)
-{
-	unsigned long kmap_vstart;
-
-	/* cache the first kmap pte */
-	kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
-	kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
-
-	kmap_prot = PAGE_KERNEL;
+	setup_highmem(end_iomem, highmem);
+#endif
 }
-#endif /* CONFIG_HIGHMEM */
 
 static void __init fixrange_init(unsigned long start, unsigned long end, 
 				 pgd_t *pgd_base)
@@ -178,76 +135,24 @@ static void __init fixrange_init(unsigned long start, unsigned long end,
 	}
 }
 
-int init_maps(struct mem_region *region)
-{
-	struct page *p, *map;
-	int i, n, len;
-
-	if(region == &physmem_region){
-		region->mem_map = mem_map;
-		return(0);
-	}
-	else if(region->mem_map != NULL) return(0);
-
-	n = region->len >> PAGE_SHIFT;
-	len = n * sizeof(struct page);
-	if(kmalloc_ok){
-		map = kmalloc(len, GFP_KERNEL);
-		if(map == NULL) map = vmalloc(len);
-	}
-	else map = alloc_bootmem_low_pages(len);
-
-	if(map == NULL)
-		return(-ENOMEM);
-	for(i = 0; i < n; i++){
-		p = &map[i];
-		set_page_count(p, 0);
-		SetPageReserved(p);
-		INIT_LIST_HEAD(&p->list);
-	}
-	region->mem_map = map;
-	return(0);
-}
+#if CONFIG_HIGHMEM
+pte_t *kmap_pte;
+pgprot_t kmap_prot;
 
-DECLARE_MUTEX(regions_sem);
+#define kmap_get_fixmap_pte(vaddr)					\
+	pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
 
-static int setup_one_range(int fd, char *driver, unsigned long start, 
-			   unsigned long pfn, int len, 
-			   struct mem_region *region)
+void __init kmap_init(void)
 {
-	int i;
-
-	down(&regions_sem);
-	for(i = 0; i < NREGIONS; i++){
-		if(regions[i] == NULL) break;		
-	}
-	if(i == NREGIONS){
-		printk("setup_range : no free regions\n");
-		i = -1;
-		goto out;
-	}
-
-	if(fd == -1)
-		fd = create_mem_file(len);
+	unsigned long kmap_vstart;
 
-	if(region == NULL){
-		region = alloc_bootmem_low_pages(sizeof(*region));
-		if(region == NULL)
-			panic("Failed to allocating mem_region");
-	}
+	/* cache the first kmap pte */
+	kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
+	kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
 
-	*region = ((struct mem_region) { .driver 	= driver,
-					 .start_pfn 	= pfn,
-					 .start 	= start, 
-					 .len 		= len, 
-					 .fd 		= fd } );
-	regions[i] = region;
- out:
-	up(&regions_sem);
-	return(i);
+	kmap_prot = PAGE_KERNEL;
 }
 
-#ifdef CONFIG_HIGHMEM
 static void init_highmem(void)
 {
 	pgd_t *pgd;
@@ -268,63 +173,20 @@ static void init_highmem(void)
 
 	kmap_init();
 }
-
-void setup_highmem(unsigned long len)
-{
-	struct mem_region *region;
-	struct page *page, *map;
-	unsigned long phys;
-	int i, cur, index;
-
-	phys = physmem_size;
-	do {
-		cur = min(len, (unsigned long) REGION_SIZE);
-		i = setup_one_range(-1, NULL, -1, phys >> PAGE_SHIFT, cur, 
-				    NULL);
-		if(i == -1){
-			printk("setup_highmem - setup_one_range failed\n");
-			return;
-		}
-		region = regions[i];
-		index = phys / PAGE_SIZE;
-		region->mem_map = &mem_map[index];
-
-		map = region->mem_map;
-		for(i = 0; i < (cur >> PAGE_SHIFT); i++){
-			page = &map[i];
-			ClearPageReserved(page);
-			set_bit(PG_highmem, &page->flags);
-			set_page_count(page, 1);
-			__free_page(page);
-		}
-		phys += cur;
-		len -= cur;
-	} while(len > 0);
-}
-#endif
+#endif /* CONFIG_HIGHMEM */
 
 void paging_init(void)
 {
-	struct mem_region *region;
-	unsigned long zones_size[MAX_NR_ZONES], start, end, vaddr;
-	int i, index;
+	unsigned long zones_size[MAX_NR_ZONES], vaddr;
+	int i;
 
 	empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
 	empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
 	for(i=0;i<sizeof(zones_size)/sizeof(zones_size[0]);i++) 
 		zones_size[i] = 0;
-	zones_size[0] = (high_physmem >> PAGE_SHIFT) - 
-		(uml_physmem >> PAGE_SHIFT);
+	zones_size[0] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT);
 	zones_size[2] = highmem >> PAGE_SHIFT;
 	free_area_init(zones_size);
-	start = phys_region_index(__pa(uml_physmem));
-	end = phys_region_index(__pa(high_physmem - 1));
-	for(i = start; i <= end; i++){
-		region = regions[i];
-		index = (region->start - uml_physmem) / PAGE_SIZE;
-		region->mem_map = &mem_map[index];
-		if(i > start) free_bootmem(__pa(region->start), region->len);
-	}
 
 	/*
 	 * Fixed mappings, only the page table structure has to be
@@ -335,15 +197,33 @@ void paging_init(void)
 
 #ifdef CONFIG_HIGHMEM
 	init_highmem();
-	setup_highmem(highmem);
 #endif
 }
 
-pte_t __bad_page(void)
+struct page *arch_validate(struct page *page, int mask, int order)
 {
-	clear_page(empty_bad_page);
-        return pte_mkdirty(mk_pte((struct page *) empty_bad_page, 
-				  PAGE_SHARED));
+	unsigned long addr, zero = 0;
+	int i;
+
+ again:
+	if(page == NULL) return(page);
+	if(PageHighMem(page)) return(page);
+
+	addr = (unsigned long) page_address(page);
+	for(i = 0; i < (1 << order); i++){
+		current->thread.fault_addr = (void *) addr;
+		if(__do_copy_to_user((void *) addr, &zero,
+				     sizeof(zero),
+				     &current->thread.fault_addr,
+				     &current->thread.fault_catcher)){
+			if(!(mask & __GFP_WAIT)) return(NULL);
+			else break;
+		}
+		addr += PAGE_SIZE;
+	}
+	if(i == (1 << order)) return(page);
+	page = alloc_pages(mask, order);
+	goto again;
 }
 
 /* This can't do anything because nothing in the kernel image can be freed
@@ -401,395 +281,6 @@ void show_mem(void)
         printk("%d pages swap cached\n", cached);
 }
 
-static int __init uml_mem_setup(char *line, int *add)
-{
-	char *retptr;
-	physmem_size = memparse(line,&retptr);
-	return 0;
-}
-__uml_setup("mem=", uml_mem_setup,
-"mem=<Amount of desired ram>\n"
-"    This controls how much \"physical\" memory the kernel allocates\n"
-"    for the system. The size is specified as a number followed by\n"
-"    one of 'k', 'K', 'm', 'M', which have the obvious meanings.\n"
-"    This is not related to the amount of memory in the physical\n"
-"    machine. It can be more, and the excess, if it's ever used, will\n"
-"    just be swapped out.\n        Example: mem=64M\n\n"
-);
-
-struct page *arch_validate(struct page *page, int mask, int order)
-{
-	unsigned long addr, zero = 0;
-	int i;
-
- again:
-	if(page == NULL) return(page);
-	if(PageHighMem(page)) return(page);
-
-	addr = (unsigned long) page_address(page);
-	for(i = 0; i < (1 << order); i++){
-		current->thread.fault_addr = (void *) addr;
-		if(__do_copy_to_user((void *) addr, &zero, 
-				     sizeof(zero),
-				     &current->thread.fault_addr,
-				     &current->thread.fault_catcher)){
-			if(!(mask & __GFP_WAIT)) return(NULL);
-			else break;
-		}
-		addr += PAGE_SIZE;
-	}
-	if(i == (1 << order)) return(page);
-	page = alloc_pages(mask, order);
-	goto again;
-}
-
-DECLARE_MUTEX(vm_reserved_sem);
-static struct list_head vm_reserved = LIST_HEAD_INIT(vm_reserved);
-
-/* Static structures, linked in to the list in early boot */
-static struct vm_reserved head = {
-	.list 		= LIST_HEAD_INIT(head.list),
-	.start 		= 0,
-	.end 		= 0xffffffff
-};
-
-static struct vm_reserved tail = {
-	.list 		= LIST_HEAD_INIT(tail.list),
-	.start 		= 0,
-	.end 		= 0xffffffff
-};
-
-void set_usable_vm(unsigned long start, unsigned long end)
-{
-	list_add(&head.list, &vm_reserved);
-	list_add(&tail.list, &head.list);
-	head.end = start;
-	tail.start = end;
-}
-
-int reserve_vm(unsigned long start, unsigned long end, void *e)
-	       
-{
-	struct vm_reserved *entry = e, *reserved, *prev;
-	struct list_head *ele;
-	int err;
-
-	down(&vm_reserved_sem);
-	list_for_each(ele, &vm_reserved){
-		reserved = list_entry(ele, struct vm_reserved, list);
-		if(reserved->start >= end) goto found;
-	}
-	panic("Reserved vm out of range");
- found:
-	prev = list_entry(ele->prev, struct vm_reserved, list);
-	if(prev->end > start)
-		panic("Can't reserve vm");
-	if(entry == NULL)
-		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
-	if(entry == NULL){
-		printk("reserve_vm : Failed to allocate entry\n");
-		err = -ENOMEM;
-		goto out;
-	}
-	*entry = ((struct vm_reserved) 
-		{ .list 	= LIST_HEAD_INIT(entry->list),
-		  .start 	= start,
-		  .end 		= end });
-	list_add(&entry->list, &prev->list);
-	err = 0;
- out:
-	up(&vm_reserved_sem);
-	return(0);
-}
-
-unsigned long get_vm(unsigned long len)
-{
-	struct vm_reserved *this, *next;
-	struct list_head *ele;
-	unsigned long start;
-	int err;
-	
-	down(&vm_reserved_sem);
-	list_for_each(ele, &vm_reserved){
-		this = list_entry(ele, struct vm_reserved, list);
-		next = list_entry(ele->next, struct vm_reserved, list);
-		if((this->start < next->start) && 
-		   (this->end + len + PAGE_SIZE <= next->start))
-			goto found;
-	}
-	up(&vm_reserved_sem);
-	return(0);
- found:
-	up(&vm_reserved_sem);
-	start = (unsigned long) UML_ROUND_UP(this->end) + PAGE_SIZE;
-	err = reserve_vm(start, start + len, NULL);
-	if(err) return(0);
-	return(start);
-}
-
-int nregions(void)
-{
-	return(NREGIONS);
-}
-
-void setup_range(int fd, char *driver, unsigned long start, unsigned long pfn,
-		 unsigned long len, int need_vm, struct mem_region *region, 
-		 void *reserved)
-{
-	int i, cur;
-
-	do {
-		cur = min(len, (unsigned long) REGION_SIZE);
-		i = setup_one_range(fd, driver, start, pfn, cur, region);
-		region = regions[i];
-		if(need_vm && setup_region(region, reserved)){
-			kfree(region);
-			regions[i] = NULL;
-			return;
-		}
-		start += cur;
-		if(pfn != -1) pfn += cur;
-		len -= cur;
-	} while(len > 0);
-}
-
-struct iomem {
-	char *name;
-	int fd;
-	unsigned long size;
-};
-
-/* iomem regions can only be added on the command line at the moment.  
- * Locking will be needed when they can be added via mconsole.
- */
-
-struct iomem iomem_regions[NREGIONS] = { [ 0 ... NREGIONS - 1 ] =
-					 { .name  	= NULL,
-					   .fd  	= -1,
-					   .size 	= 0 } };
-
-int num_iomem_regions = 0;
-
-void add_iomem(char *name, int fd, unsigned long size)
-{
-	if(num_iomem_regions == sizeof(iomem_regions)/sizeof(iomem_regions[0]))
-		return;
-	size = (size + PAGE_SIZE - 1) & PAGE_MASK;
-	iomem_regions[num_iomem_regions++] = 
-		((struct iomem) { .name 	= name,
-				  .fd 		= fd,
-				  .size 	= size } );
-}
-
-int setup_iomem(void)
-{
-	struct iomem *iomem;
-	int i;
-
-	for(i = 0; i < num_iomem_regions; i++){
-		iomem = &iomem_regions[i];
-		setup_range(iomem->fd, iomem->name, -1, -1, iomem->size, 1, 
-			    NULL, NULL);
-	}
-	return(0);
-}
-
-__initcall(setup_iomem);
-
-#define PFN_UP(x)	(((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x)	((x) >> PAGE_SHIFT)
-
-/* Changed during early boot */
-static struct mem_region physmem_region;
-static struct vm_reserved physmem_reserved;
-
-void setup_physmem(unsigned long start, unsigned long reserve_end,
-		   unsigned long len)
-{
-	struct mem_region *region = &physmem_region;
-	struct vm_reserved *reserved = &physmem_reserved;
-	unsigned long cur, pfn = 0;
-	int do_free = 1, bootmap_size;
-
-	do {
-		cur = min(len, (unsigned long) REGION_SIZE);
-		if(region == NULL) 
-			region = alloc_bootmem_low_pages(sizeof(*region));
-		if(reserved == NULL) 
-			reserved = alloc_bootmem_low_pages(sizeof(*reserved));
-		if((region == NULL) || (reserved == NULL))
-			panic("Couldn't allocate physmem region or vm "
-			      "reservation\n");
-		setup_range(-1, NULL, start, pfn, cur, 1, region, reserved);
-
-		if(do_free){
-			unsigned long reserve = reserve_end - start;
-			int pfn = PFN_UP(__pa(reserve_end));
-			int delta = (len - reserve) >> PAGE_SHIFT;
-
-			bootmap_size = init_bootmem(pfn, pfn + delta);
-			free_bootmem(__pa(reserve_end) + bootmap_size,
-				     cur - bootmap_size - reserve);
-			do_free = 0;
-		}
-		start += cur;
-		pfn += cur >> PAGE_SHIFT;
-		len -= cur;
-		region = NULL;
-		reserved = NULL;
-	} while(len > 0);
-}
-
-struct mem_region *phys_region(unsigned long phys)
-{
-	unsigned int n = phys_region_index(phys);
-
-	if(regions[n] == NULL) 
-		panic("Physical address in uninitialized region");
-	return(regions[n]);
-}
-
-unsigned long phys_offset(unsigned long phys)
-{
-	return(phys_addr(phys));
-}
-
-struct page *phys_mem_map(unsigned long phys)
-{
-	return((struct page *) phys_region(phys)->mem_map);
-}
-
-struct page *pte_mem_map(pte_t pte)
-{
-	return(phys_mem_map(pte_val(pte)));
-}
-
-struct mem_region *page_region(struct page *page, int *index_out)
-{
-	int i;
-	struct mem_region *region;
-	struct page *map;
-
-	for(i = 0; i < NREGIONS; i++){
-		region = regions[i];
-		if(region == NULL) continue;
-		map = region->mem_map;
-		if((page >= map) && (page < &map[region->len >> PAGE_SHIFT])){
-			if(index_out != NULL) *index_out = i;
-			return(region);
-		}
-	}
-	panic("No region found for page");
-	return(NULL);
-}
-
-unsigned long page_to_pfn(struct page *page)
-{
-	struct mem_region *region = page_region(page, NULL);
-
-	return(region->start_pfn + (page - (struct page *) region->mem_map));
-}
-
-struct mem_region *pfn_to_region(unsigned long pfn, int *index_out)
-{
-	struct mem_region *region;
-	int i;
-
-	for(i = 0; i < NREGIONS; i++){
-		region = regions[i];
-		if(region == NULL)
-			continue;
-
-		if((region->start_pfn <= pfn) &&
-		   (region->start_pfn + (region->len >> PAGE_SHIFT) > pfn)){
-			if(index_out != NULL) 
-				*index_out = i;
-			return(region);
-		}
-	}
-	return(NULL);
-}
-
-struct page *pfn_to_page(unsigned long pfn)
-{
-	struct mem_region *region = pfn_to_region(pfn, NULL);
-	struct page *mem_map = (struct page *) region->mem_map;
-
-	return(&mem_map[pfn - region->start_pfn]);
-}
-
-unsigned long phys_to_pfn(unsigned long p)
-{
-	struct mem_region *region = regions[phys_region_index(p)];
-
-	return(region->start_pfn + (phys_addr(p) >> PAGE_SHIFT));
-}
-
-unsigned long pfn_to_phys(unsigned long pfn)
-{
-	int n;
-	struct mem_region *region = pfn_to_region(pfn, &n);
-
-	return(mk_phys((pfn - region->start_pfn) << PAGE_SHIFT, n));
-}
-
-struct page *page_mem_map(struct page *page)
-{
-	return((struct page *) page_region(page, NULL)->mem_map);
-}
-
-extern unsigned long region_pa(void *virt)
-{
-	struct mem_region *region;
-	unsigned long addr = (unsigned long) virt;
-	int i;
-
-	for(i = 0; i < NREGIONS; i++){
-		region = regions[i];
-		if(region == NULL) continue;
-		if((region->start <= addr) && 
-		   (addr <= region->start + region->len))
-			return(mk_phys(addr - region->start, i));
-	}
-	panic("region_pa : no region for virtual address");
-	return(0);
-}
-
-extern void *region_va(unsigned long phys)
-{
-	return((void *) (phys_region(phys)->start + phys_addr(phys)));
-}
-
-unsigned long page_to_phys(struct page *page)
-{
-	int n;
-	struct mem_region *region = page_region(page, &n);
-	struct page *map = region->mem_map;
-	return(mk_phys((page - map) << PAGE_SHIFT, n));
-}
-
-struct page *phys_to_page(unsigned long phys)
-{
-	struct page *mem_map;
-
-	mem_map = phys_mem_map(phys);
-	return(mem_map + (phys_offset(phys) >> PAGE_SHIFT));
-}
-
-static int setup_mem_maps(void)
-{
-	struct mem_region *region;
-	int i;
-
-	for(i = 0; i < NREGIONS; i++){
-		region = regions[i];
-		if((region != NULL) && (region->fd > 0)) init_maps(region);
-	}
-	return(0);
-}
-
-__initcall(setup_mem_maps);
-
 /*
  * Allocate and free page tables.
  */
diff --git a/arch/um/kernel/mem_user.c b/arch/um/kernel/mem_user.c
index d90345b5f..ec15ba43d 100644
--- a/arch/um/kernel/mem_user.c
+++ b/arch/um/kernel/mem_user.c
@@ -34,10 +34,9 @@
 #include <stddef.h>
 #include <stdarg.h>
 #include <unistd.h>
-#include <fcntl.h>
 #include <errno.h>
 #include <string.h>
-#include <sys/stat.h>
+#include <fcntl.h>
 #include <sys/types.h>
 #include <sys/mman.h>
 #include "kern_util.h"
@@ -47,105 +46,147 @@
 #include "init.h"
 #include "os.h"
 #include "tempfile.h"
+#include "kern_constants.h"
 
 extern struct mem_region physmem_region;
 
 #define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
 
-int create_mem_file(unsigned long len)
+static int create_tmp_file(unsigned long len)
 {
-	int fd;
+	int fd, err;
 	char zero;
 
 	fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1);
-	if (fchmod(fd, 0777) < 0){
-		perror("fchmod");
+	if(fd < 0) {
+		os_print_error(fd, "make_tempfile");
+		exit(1);
+	}
+
+	err = os_mode_fd(fd, 0777);
+	if(err < 0){
+		os_print_error(err, "os_mode_fd");
 		exit(1);
 	}
-	if(os_seek_file(fd, len) < 0){
-		perror("lseek");
+	err = os_seek_file(fd, len);
+	if(err < 0){
+		os_print_error(err, "os_seek_file");
 		exit(1);
 	}
 	zero = 0;
-	if(write(fd, &zero, 1) != 1){
-		perror("write");
+	err = os_write_file(fd, &zero, 1);
+	if(err != 1){
+		os_print_error(err, "os_write_file");
 		exit(1);
 	}
-	if(fcntl(fd, F_SETFD, 1) != 0)
-		perror("Setting FD_CLOEXEC failed");
+
 	return(fd);
 }
 
-int setup_region(struct mem_region *region, void *entry)
+static int have_devanon = 0;
+
+void check_devanon(void)
 {
-	void *loc, *start;
-	char *driver;
-	int err, offset;
-
-	if(region->start != -1){
-		err = reserve_vm(region->start, 
-				 region->start + region->len, entry);
-		if(err){
-			printk("setup_region : failed to reserve "
-			       "0x%x - 0x%x for driver '%s'\n",
-			       region->start, 
-			       region->start + region->len,
-			       region->driver);
-			return(-1);
-		}
-	}
-	else region->start = get_vm(region->len);
-	if(region->start == 0){
-		if(region->driver == NULL) driver = "physmem";
-		else driver = region->driver;
-		printk("setup_region : failed to find vm for "
-		       "driver '%s' (length %d)\n", driver, region->len);
-		return(-1);
-	}
-	if(region->start == uml_physmem){
-		start = (void *) uml_reserved;
-		offset = uml_reserved - uml_physmem;
+	int fd;
+
+	printk("Checking for /dev/anon on the host...");
+	fd = open("/dev/anon", O_RDWR);
+	if(fd < 0){
+		printk("Not available (open failed with errno %d)\n", errno);
+		return;
 	}
-	else {
-		start = (void *) region->start;
-		offset = 0;
+
+	printk("OK\n");
+	have_devanon = 1;
+}
+
+static int create_anon_file(unsigned long len)
+{
+	void *addr;
+	int fd;
+
+	fd = open("/dev/anon", O_RDWR);
+	if(fd < 0) {
+		os_print_error(fd, "opening /dev/anon");
+		exit(1);
 	}
 
-	loc = mmap(start, region->len - offset, PROT_READ | PROT_WRITE, 
-		   MAP_SHARED | MAP_FIXED, region->fd, offset);
-	if(loc != start){
-		perror("Mapping memory");
+	addr = mmap(NULL, len, PROT_READ | PROT_WRITE , MAP_PRIVATE, fd, 0);
+	if(addr == MAP_FAILED){
+		os_print_error((int) addr, "mapping physmem file");
 		exit(1);
 	}
-	return(0);
+	munmap(addr, len);
+
+	return(fd);
+}
+
+int create_mem_file(unsigned long len)
+{
+	int err, fd;
+
+	if(have_devanon)
+		fd = create_anon_file(len);
+	else fd = create_tmp_file(len);
+
+	err = os_set_exec_close(fd, 1);
+	if(err < 0)
+		os_print_error(err, "exec_close");
+	return(fd);
 }
 
+struct iomem_region *iomem_regions = NULL;
+int iomem_size = 0;
+
 static int __init parse_iomem(char *str, int *add)
 {
-	struct stat buf;
+	struct iomem_region *new;
+	struct uml_stat buf;
 	char *file, *driver;
-	int fd;
+	int fd, err, size;
 
 	driver = str;
 	file = strchr(str,',');
 	if(file == NULL){
-		printk("parse_iomem : failed to parse iomem\n");
-		return(1);
+		printf("parse_iomem : failed to parse iomem\n");
+		goto out;
 	}
 	*file = '\0';
 	file++;
 	fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0);
 	if(fd < 0){
-		printk("parse_iomem - Couldn't open io file, errno = %d\n", 
-		       errno);
-		return(1);
+		os_print_error(fd, "parse_iomem - Couldn't open io file");
+		goto out;
+	}
+
+	err = os_stat_fd(fd, &buf);
+	if(err < 0){
+		os_print_error(err, "parse_iomem - cannot stat_fd file");
+		goto out_close;
 	}
-	if(fstat(fd, &buf) < 0) {
-		printk("parse_iomem - cannot fstat file, errno = %d\n", errno);
-		return(1);
+
+	new = malloc(sizeof(*new));
+	if(new == NULL){
+		perror("Couldn't allocate iomem_region struct");
+		goto out_close;
 	}
-	add_iomem(driver, fd, buf.st_size);
+
+	size = (buf.ust_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1);
+
+	*new = ((struct iomem_region) { .next		= iomem_regions,
+					.driver		= driver,
+					.fd		= fd,
+					.size		= size,
+					.phys		= 0,
+					.virt		= 0 });
+	iomem_regions = new;
+	iomem_size += new->size + UM_KERN_PAGE_SIZE;
+
 	return(0);
+ out_close:
+	os_close_file(fd);
+ out:
+	return(1);
 }
 
 __uml_setup("iomem=", parse_iomem,
@@ -153,73 +194,20 @@ __uml_setup("iomem=", parse_iomem,
 "    Configure <file> as an IO memory region named <name>.\n\n"
 );
 
-#ifdef notdef
-int logging = 0;
-int logging_fd = -1;
-
-int logging_line = 0;
-char logging_buf[256];
-
-void log(char *fmt, ...)
-{
-	va_list ap;
-	struct timeval tv;
-	struct openflags flags;
-
-	if(logging == 0) return;
-	if(logging_fd < 0){
-		flags = of_create(of_trunc(of_rdrw(OPENFLAGS())));
-		logging_fd = os_open_file("log", flags, 0644);
-	}
-	gettimeofday(&tv, NULL);
-	sprintf(logging_buf, "%d\t %u.%u  ", logging_line++, tv.tv_sec, 
-		tv.tv_usec);
-	va_start(ap, fmt);
-	vsprintf(&logging_buf[strlen(logging_buf)], fmt, ap);
-	va_end(ap);
-	write(logging_fd, logging_buf, strlen(logging_buf));
-}
-#endif
-
-int map_memory(unsigned long virt, unsigned long phys, unsigned long len, 
-	       int r, int w, int x)
-{
-	struct mem_region *region = phys_region(phys);
-
-	return(os_map_memory((void *) virt, region->fd, phys_offset(phys), len,
-			     r, w, x));
-}
-
 int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x,
 		   int must_succeed)
 {
-	if(os_protect_memory((void *) addr, len, r, w, x) < 0){
+	int err;
+
+	err = os_protect_memory((void *) addr, len, r, w, x);
+	if(err < 0){
                 if(must_succeed)
-                        panic("protect failed, errno = %d", errno);
-                else return(-errno);
+			panic("protect failed, err = %d", -err);
+		else return(err);
 	}
 	return(0);
 }
 
-unsigned long find_iomem(char *driver, unsigned long *len_out)
-{
-	struct mem_region *region;
-	int i, n;
-
-	n = nregions();
-	for(i = 0; i < n; i++){
-		region = regions[i];
-		if(region == NULL) continue;
-		if((region->driver != NULL) &&
-		   !strcmp(region->driver, driver)){
-			*len_out = region->len;
-			return(region->start);
-		}
-	}
-	*len_out = 0;
-	return 0;
-}
-
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index d0e0f50dc..3253bc0e3 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -1,13 +1,14 @@
-/* 
+/*
  * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
 #include "linux/mm.h"
-#include "linux/ghash.h"
+#include "linux/rbtree.h"
 #include "linux/slab.h"
 #include "linux/vmalloc.h"
 #include "linux/bootmem.h"
+#include "linux/module.h"
 #include "asm/types.h"
 #include "asm/pgtable.h"
 #include "kern_util.h"
@@ -19,36 +20,8 @@
 #include "kern.h"
 #include "init.h"
 
-#if 0
-static pgd_t physmem_pgd[PTRS_PER_PGD];
-
-static struct phys_desc *lookup_mapping(void *addr)
-{
-	pgd = &physmem_pgd[pgd_index(addr)];
-	if(pgd_none(pgd))
-		return(NULL);
-
-	pmd = pmd_offset(pgd, addr);
-	if(pmd_none(pmd))
-		return(NULL);
-
-	pte = pte_offset_kernel(pmd, addr);
-	return((struct phys_desc *) pte_val(pte));
-}
-
-static struct add_mapping(void *addr, struct phys_desc *new)
-{
-}
-#endif
-
-#define PHYS_HASHSIZE (8192)
-
-struct phys_desc;
-
-DEF_HASH_STRUCTS(virtmem, PHYS_HASHSIZE, struct phys_desc);
-
 struct phys_desc {
-	struct virtmem_ptrs virt_ptrs;
+	struct rb_node rb;
 	int fd;
 	__u64 offset;
 	void *virt;
@@ -56,21 +29,48 @@ struct phys_desc {
 	struct list_head list;
 };
 
-struct virtmem_table virtmem_hash;
+static struct rb_root phys_mappings = RB_ROOT;
 
-static int virt_cmp(void *virt1, void *virt2)
+static struct rb_node **find_rb(void *virt)
 {
-	return(virt1 != virt2);
+	struct rb_node **n = &phys_mappings.rb_node;
+	struct phys_desc *d;
+
+	while(*n != NULL){
+		d = rb_entry(*n, struct phys_desc, rb);
+		if(d->virt == virt)
+			return(n);
+
+		if(d->virt > virt)
+			n = &(*n)->rb_left;
+		else
+			n = &(*n)->rb_right;
+	}
+
+	return(n);
 }
 
-static int virt_hash(void *virt)
+static struct phys_desc *find_phys_mapping(void *virt)
 {
-	unsigned long addr = ((unsigned long) virt) >> PAGE_SHIFT;
-	return(addr % PHYS_HASHSIZE);
+	struct rb_node **n = find_rb(virt);
+
+	if(*n == NULL)
+		return(NULL);
+
+	return(rb_entry(*n, struct phys_desc, rb));
 }
 
-DEF_HASH(static, virtmem, struct phys_desc, virt_ptrs, void *, virt, virt_cmp, 
-	 virt_hash);
+static void insert_phys_mapping(struct phys_desc *desc)
+{
+	struct rb_node **n = find_rb(desc->virt);
+
+	if(*n != NULL)
+		panic("Physical remapping for %p already present",
+		      desc->virt);
+
+	rb_link_node(&desc->rb, (*n)->rb_parent, n);
+	rb_insert_color(&desc->rb, &phys_mappings);
+}
 
 LIST_HEAD(descriptor_mappings);
 
@@ -106,7 +106,7 @@ static struct desc_mapping *descriptor_mapping(int fd)
 	if(desc == NULL)
 		return(NULL);
 
-	*desc = ((struct desc_mapping) 
+	*desc = ((struct desc_mapping)
 		{ .fd =		fd,
 		  .list =	LIST_HEAD_INIT(desc->list),
 		  .pages =	LIST_HEAD_INIT(desc->pages) });
@@ -127,7 +127,8 @@ int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w)
 		return(-ENOMEM);
 
 	phys = __pa(virt);
-	if(find_virtmem_hash(&virtmem_hash, virt) != NULL)
+	desc = find_phys_mapping(virt);
+  	if(desc != NULL)
 		panic("Address 0x%p is already substituted\n", virt);
 
 	err = -ENOMEM;
@@ -135,14 +136,13 @@ int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w)
 	if(desc == NULL)
 		goto out;
 
-	*desc = ((struct phys_desc) 
-		{ .virt_ptrs =	{ NULL, NULL },
-		  .fd =		fd,
+	*desc = ((struct phys_desc)
+		{ .fd =			fd,
 		  .offset =		offset,
 		  .virt =		virt,
 		  .phys =		__pa(virt),
 		  .list = 		LIST_HEAD_INIT(desc->list) });
-	insert_virtmem_hash(&virtmem_hash, desc);
+	insert_phys_mapping(desc);
 
 	list_add(&desc->list, &fd_maps->pages);
 
@@ -151,7 +151,7 @@ int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w)
 	if(!err)
 		goto out;
 
-	remove_virtmem_hash(&virtmem_hash, desc);
+	rb_erase(&desc->rb, &phys_mappings);
 	kfree(desc);
  out:
 	return(err);
@@ -164,7 +164,7 @@ static void remove_mapping(struct phys_desc *desc)
 	void *virt = desc->virt;
 	int err;
 
-	remove_virtmem_hash(&virtmem_hash, desc);
+	rb_erase(&desc->rb, &phys_mappings);
 	list_del(&desc->list);
 	kfree(desc);
 
@@ -179,7 +179,7 @@ int physmem_remove_mapping(void *virt)
 	struct phys_desc *desc;
 
 	virt = (void *) ((unsigned long) virt & PAGE_MASK);
-	desc = find_virtmem_hash(&virtmem_hash, virt);
+	desc = find_phys_mapping(virt);
 	if(desc == NULL)
 		return(0);
 
@@ -221,6 +221,10 @@ void physmem_forget_descriptor(int fd)
 	kfree(desc);
 }
 
+EXPORT_SYMBOL(physmem_forget_descriptor);
+EXPORT_SYMBOL(physmem_remove_mapping);
+EXPORT_SYMBOL(physmem_subst_mapping);
+
 void arch_free_page(struct page *page, int order)
 {
 	void *virt;
@@ -234,7 +238,9 @@ void arch_free_page(struct page *page, int order)
 
 int is_remapped(void *virt)
 {
-	return(find_virtmem_hash(&virtmem_hash, virt) != NULL);
+  	struct phys_desc *desc = find_phys_mapping(virt);
+
+	return(desc != NULL);
 }
 
 /* Changed during early boot */
@@ -273,7 +279,7 @@ int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem)
 
 	if(kmalloc_ok){
 		map = kmalloc(total_len, GFP_KERNEL);
-		if(map == NULL) 
+		if(map == NULL)
 			map = vmalloc(total_len);
 	}
 	else map = alloc_bootmem_low_pages(total_len);
@@ -322,12 +328,12 @@ static unsigned long kmem_top = 0;
 
 unsigned long get_kmem_end(void)
 {
-	if(kmem_top == 0) 
+	if(kmem_top == 0)
 		kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas);
 	return(kmem_top);
 }
 
-void map_memory(unsigned long virt, unsigned long phys, unsigned long len, 
+void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
 		int r, int w, int x)
 {
 	__u64 offset;
@@ -335,9 +341,14 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
 
 	fd = phys_mapping(phys, &offset);
 	err = os_map_memory((void *) virt, fd, offset, len, r, w, x);
-	if(err)
+	if(err) {
+		if(err == -ENOMEM)
+			printk("try increasing the host's "
+			       "/proc/sys/vm/max_map_count to <physical "
+			       "memory size>/4096\n");
 		panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, "
 		      "err = %d\n", virt, fd, offset, len, r, w, x, err);
+	}
 }
 
 #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
@@ -353,7 +364,7 @@ void setup_physmem(unsigned long start, unsigned long reserve_end,
 	physmem_fd = create_mem_file(len + highmem);
 
 	offset = uml_reserved - uml_physmem;
-	err = os_map_memory((void *) uml_reserved, physmem_fd, offset, 
+	err = os_map_memory((void *) uml_reserved, physmem_fd, offset,
 			    len - offset, 1, 1, 0);
 	if(err < 0){
 		os_print_error(err, "Mapping memory");
@@ -367,8 +378,7 @@ void setup_physmem(unsigned long start, unsigned long reserve_end,
 
 int phys_mapping(unsigned long phys, __u64 *offset_out)
 {
-	struct phys_desc *desc = find_virtmem_hash(&virtmem_hash, 
-						   __va(phys & PAGE_MASK));
+	struct phys_desc *desc = find_phys_mapping(__va(phys & PAGE_MASK));
 	int fd = -1;
 
 	if(desc != NULL){
@@ -381,9 +391,9 @@ int phys_mapping(unsigned long phys, __u64 *offset_out)
 	}
 	else if(phys < __pa(end_iomem)){
 		struct iomem_region *region = iomem_regions;
-	
+
 		while(region != NULL){
-			if((phys >= region->phys) && 
+			if((phys >= region->phys) &&
 			   (phys < region->phys + region->size)){
 				fd = region->fd;
 				*offset_out = phys - region->phys;
@@ -419,7 +429,7 @@ __uml_setup("mem=", uml_mem_setup,
 unsigned long find_iomem(char *driver, unsigned long *len_out)
 {
 	struct iomem_region *region = iomem_regions;
-	
+
 	while(region != NULL){
 		if(!strcmp(region->driver, driver)){
 			*len_out = region->size;
@@ -437,7 +447,7 @@ int setup_iomem(void)
 	int err;
 
 	while(region != NULL){
-		err = os_map_memory((void *) iomem_start, region->fd, 0, 
+		err = os_map_memory((void *) iomem_start, region->fd, 0,
 				    region->size, 1, 1, 0);
 		if(err)
 			printk("Mapping iomem region for driver '%s' failed, "
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 4c3aa4535..4468f2440 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -9,18 +9,17 @@
 #include <sched.h>
 #include <errno.h>
 #include <stdarg.h>
-#include <fcntl.h>
 #include <stdlib.h>
 #include <setjmp.h>
 #include <sys/time.h>
 #include <sys/ptrace.h>
-#include <sys/ioctl.h>
 #include <sys/wait.h>
 #include <sys/mman.h>
 #include <asm/ptrace.h>
 #include <asm/sigcontext.h>
 #include <asm/unistd.h>
 #include <asm/page.h>
+#include <asm/user.h>
 #include "user_util.h"
 #include "kern_util.h"
 #include "user.h"
@@ -47,7 +46,7 @@ void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
 	int flags = 0, pages;
 
 	if(sig_stack != NULL){
-		pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2;
+		pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER);
 		set_sigstack(sig_stack, pages * page_size());
 		flags = SA_ONSTACK;
 	}
@@ -71,8 +70,7 @@ void init_new_thread_signals(int altstack)
 	set_handler(SIGWINCH, (__sighandler_t) sig_handler, flags, 
 		    SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
 	set_handler(SIGUSR2, (__sighandler_t) sig_handler, 
-		    SA_NOMASK | flags, -1);
-	(void) CHOOSE_MODE(signal(SIGCHLD, SIG_IGN), (void *) 0);
+		    flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
 	signal(SIGHUP, SIG_IGN);
 
 	init_irq_signals(altstack);
@@ -122,24 +120,19 @@ int start_fork_tramp(void *thread_arg, unsigned long temp_stack,
 
 	/* Start the process and wait for it to kill itself */
 	new_pid = clone(outer_tramp, (void *) sp, clone_flags, &arg);
-	if(new_pid < 0) return(-errno);
-	while((err = waitpid(new_pid, &status, 0) < 0) && (errno == EINTR)) ;
-	if(err < 0) panic("Waiting for outer trampoline failed - errno = %d", 
-			  errno);
-	if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL))
-		panic("outer trampoline didn't exit with SIGKILL");
-
-	return(arg.pid);
-}
+	if(new_pid < 0)
+		return(new_pid);
 
-void suspend_new_thread(int fd)
-{
-	char c;
+	CATCH_EINTR(err = waitpid(new_pid, &status, 0));
+	if(err < 0)
+		panic("Waiting for outer trampoline failed - errno = %d",
+		      errno);
 
-	os_stop_process(os_getpid());
+	if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL))
+		panic("outer trampoline didn't exit with SIGKILL, "
+		      "status = %d", status);
 
-	if(read(fd, &c, sizeof(c)) != sizeof(c))
-		panic("read failed in suspend_new_thread");
+	return(arg.pid);
 }
 
 static int ptrace_child(void *arg)
@@ -168,7 +161,7 @@ static int start_ptraced_child(void **stack_out)
 	pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL);
 	if(pid < 0)
 		panic("check_ptrace : clone failed, errno = %d", errno);
-	n = waitpid(pid, &status, WUNTRACED);
+	CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
 	if(n < 0)
 		panic("check_ptrace : wait failed, errno = %d", errno);
 	if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
@@ -185,7 +178,7 @@ static void stop_ptraced_child(int pid, void *stack, int exitcode)
 
 	if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
 		panic("check_ptrace : ptrace failed, errno = %d", errno);
-	n = waitpid(pid, &status, 0);
+	CATCH_EINTR(n = waitpid(pid, &status, 0));
 	if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode))
 		panic("check_ptrace : child exited with status 0x%x", status);
 
@@ -193,6 +186,66 @@ static void stop_ptraced_child(int pid, void *stack, int exitcode)
 		panic("check_ptrace : munmap failed, errno = %d", errno);
 }
 
+static int force_sysemu_disabled = 0;
+
+static int __init nosysemu_cmd_param(char *str, int* add)
+{
+	force_sysemu_disabled = 1;
+	return 0;
+}
+
+__uml_setup("nosysemu", nosysemu_cmd_param,
+		"nosysemu\n"
+		"    Turns off syscall emulation patch for ptrace (SYSEMU) on.\n"
+		"    SYSEMU is a performance-patch introduced by Laurent Vivier. It changes\n"
+		"    behaviour of ptrace() and helps reducing host context switch rate.\n"
+		"    To make it working, you need a kernel patch for your host, too.\n"
+		"    See http://perso.wanadoo.fr/laurent.vivier/UML/ for further information.\n");
+
+static void __init check_sysemu(void)
+{
+	void *stack;
+	int pid, n, status;
+
+	if (mode_tt)
+		return;
+
+	printk("Checking syscall emulation patch for ptrace...");
+	sysemu_supported = 0;
+	pid = start_ptraced_child(&stack);
+	if(ptrace(PTRACE_SYSEMU, pid, 0, 0) >= 0) {
+		struct user_regs_struct regs;
+
+		CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
+		if (n < 0)
+			panic("check_ptrace : wait failed, errno = %d", errno);
+		if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
+			panic("check_ptrace : expected SIGTRAP, "
+			      "got status = %d", status);
+
+		if (ptrace(PTRACE_GETREGS, pid, 0, &regs) < 0)
+			panic("check_ptrace : failed to read child "
+			      "registers, errno = %d", errno);
+		regs.orig_eax = pid;
+		if (ptrace(PTRACE_SETREGS, pid, 0, &regs) < 0)
+			panic("check_ptrace : failed to modify child "
+			      "registers, errno = %d", errno);
+
+		stop_ptraced_child(pid, stack, 0);
+
+		sysemu_supported = 1;
+		printk("found\n");
+	}
+	else
+	{
+		stop_ptraced_child(pid, stack, 1);
+		sysemu_supported = 0;
+		printk("missing\n");
+	}
+
+	set_using_sysemu(!force_sysemu_disabled);
+}
+
 void __init check_ptrace(void)
 {
 	void *stack;
@@ -205,7 +258,7 @@ void __init check_ptrace(void)
 		if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
 			panic("check_ptrace : ptrace failed, errno = %d", 
 			      errno);
-		n = waitpid(pid, &status, WUNTRACED);
+		CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
 		if(n < 0)
 			panic("check_ptrace : wait failed, errno = %d", errno);
 		if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
@@ -225,15 +278,16 @@ void __init check_ptrace(void)
 	}
 	stop_ptraced_child(pid, stack, 0);
 	printk("OK\n");
+	check_sysemu();
 }
 
 int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
 {
-	jmp_buf buf;
+	sigjmp_buf buf;
 	int n;
 
 	*jmp_ptr = &buf;
-	n = setjmp(buf);
+	n = sigsetjmp(buf, 1);
 	if(n != 0)
 		return(n);
 	(*fn)(arg);
@@ -273,7 +327,7 @@ int can_do_skas(void)
 	stop_ptraced_child(pid, stack, 1);
 
 	printf("Checking for /proc/mm...");
-	if(access("/proc/mm", W_OK)){
+	if(os_access("/proc/mm", OS_ACC_W_OK) < 0){
 		printf("not found\n");
 		ret = 0;
 	}
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index e17600a9b..c571d5fcf 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -16,6 +16,10 @@
 #include "linux/module.h"
 #include "linux/init.h"
 #include "linux/capability.h"
+#include "linux/vmalloc.h"
+#include "linux/spinlock.h"
+#include "linux/vs_cvirt.h"
+
 #include "asm/unistd.h"
 #include "asm/mman.h"
 #include "asm/segment.h"
@@ -23,7 +27,6 @@
 #include "asm/pgtable.h"
 #include "asm/processor.h"
 #include "asm/tlbflush.h"
-#include "asm/spinlock.h"
 #include "asm/uaccess.h"
 #include "asm/user.h"
 #include "user_util.h"
@@ -52,17 +55,12 @@ struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
 
 struct task_struct *get_task(int pid, int require)
 {
-        struct task_struct *task, *ret;
+        struct task_struct *ret;
 
-        ret = NULL;
         read_lock(&tasklist_lock);
-        for_each_process(task){
-                if(task->pid == pid){
-                        ret = task;
-                        break;
-                }
-        }
+	ret = find_task_by_pid(pid);
         read_unlock(&tasklist_lock);
+
         if(require && (ret == NULL)) panic("get_task couldn't find a task\n");
         return(ret);
 }
@@ -95,7 +93,8 @@ unsigned long alloc_stack(int order, int atomic)
 	int flags = GFP_KERNEL;
 
 	if(atomic) flags |= GFP_ATOMIC;
-	if((page = __get_free_pages(flags, order)) == 0)
+	page = __get_free_pages(flags, order);
+	if(page == 0)
 		return(0);
 	stack_protections(page);
 	return(page);
@@ -103,22 +102,25 @@ unsigned long alloc_stack(int order, int atomic)
 
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {
-	struct task_struct *p;
+	int pid;
 
 	current->thread.request.u.thread.proc = fn;
 	current->thread.request.u.thread.arg = arg;
-	p = do_fork(CLONE_VM | flags, 0, NULL, 0, NULL, NULL);
-	if(IS_ERR(p)) panic("do_fork failed in kernel_thread");
-	return(p->pid);
+	pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, NULL, 0, NULL,
+		      NULL);
+	if(pid < 0)
+		panic("do_fork failed in kernel_thread, errno = %d", pid);
+	return(pid);
 }
 
 void switch_mm(struct mm_struct *prev, struct mm_struct *next, 
 	       struct task_struct *tsk)
 {
-	unsigned cpu = smp_processor_id();
+	int cpu = smp_processor_id();
+
 	if (prev != next) 
-		clear_bit(cpu, &prev->cpu_vm_mask);
-	set_bit(cpu, &next->cpu_vm_mask);
+		cpu_clear(cpu, prev->cpu_vm_mask);
+	cpu_set(cpu, next->cpu_vm_mask);
 }
 
 void set_current(void *t)
@@ -129,7 +131,7 @@ void set_current(void *t)
 		{ external_pid(task), task });
 }
 
-void *switch_to(void *prev, void *next, void *last)
+void *_switch_to(void *prev, void *next, void *last)
 {
 	return(CHOOSE_MODE(switch_to_tt(prev, next), 
 			   switch_to_skas(prev, next)));
@@ -149,7 +151,7 @@ void release_thread(struct task_struct *task)
 void exit_thread(void)
 {
 	CHOOSE_MODE(exit_thread_tt(), exit_thread_skas());
-	unprotect_stack((unsigned long) current->thread_info);
+	unprotect_stack((unsigned long) current_thread);
 }
  
 void *get_current(void)
@@ -157,13 +159,15 @@ void *get_current(void)
 	return(current);
 }
 
+void prepare_to_copy(struct task_struct *tsk)
+{
+}
+
 int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
 		unsigned long stack_top, struct task_struct * p, 
 		struct pt_regs *regs)
 {
 	p->thread = (struct thread_struct) INIT_THREAD;
-	p->thread.kernel_stack = 
-		(unsigned long) p->thread_info + 2 * PAGE_SIZE;
 	return(CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr, 
 				clone_flags, sp, stack_top, p, regs));
 }
@@ -190,7 +194,7 @@ int current_pid(void)
 
 void default_idle(void)
 {
-	idle_timer();
+	uml_idle_timer();
 
 	atomic_inc(&init_mm.mm_count);
 	current->mm = &init_mm;
@@ -299,6 +303,11 @@ void *um_kmalloc_atomic(int size)
 	return(kmalloc(size, GFP_ATOMIC));
 }
 
+void *um_vmalloc(int size)
+{
+	return(vmalloc(size));
+}
+
 unsigned long get_fault_addr(void)
 {
 	return((unsigned long) current->thread.fault_addr);
@@ -318,8 +327,7 @@ int user_context(unsigned long sp)
 	unsigned long stack;
 
 	stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER);
-	stack += 2 * PAGE_SIZE;
-	return(stack != current->thread.kernel_stack);
+	return(stack != (unsigned long) current_thread);
 }
 
 extern void remove_umid_dir(void);
@@ -367,10 +375,15 @@ int clear_user_proc(void *buf, int size)
 	return(clear_user(buf, size));
 }
 
+int strlen_user_proc(char *str)
+{
+	return(strlen_user(str));
+}
+
 int smp_sigio_handler(void)
 {
 #ifdef CONFIG_SMP
-	int cpu = current->thread_info->cpu;
+	int cpu = current_thread->cpu;
 	IPI_handler(cpu);
 	if(cpu != 0)
 		return(1);
@@ -385,7 +398,7 @@ int um_in_interrupt(void)
 
 int cpu(void)
 {
-	return(current->thread_info->cpu);
+	return(current_thread->cpu);
 }
 
 /*
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 90f8d2861..0005a9b84 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -24,11 +24,6 @@ void ptrace_disable(struct task_struct *child)
 { 
 }
 
-extern long do_mmap2(struct task_struct *task, unsigned long addr, 
-		     unsigned long len, unsigned long prot, 
-		     unsigned long flags, unsigned long fd,
-		     unsigned long pgoff);
-
 int sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
@@ -294,7 +289,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
 	}
 #endif
 	default:
-		ret = -EIO;
+		ret = ptrace_request(child, request, addr, data);
 		break;
 	}
  out_tsk:
@@ -304,8 +299,17 @@ int sys_ptrace(long request, long pid, long addr, long data)
 	return ret;
 }
 
-void syscall_trace(void)
+void syscall_trace(union uml_pt_regs *regs, int entryexit)
 {
+	if (unlikely(current->audit_context)) {
+		if (!entryexit)
+			audit_syscall_entry(current, regs->orig_eax,
+					    regs->ebx, regs->ecx,
+					    regs->edx, regs->esi);
+		else
+			audit_syscall_exit(current, regs->eax);
+	}
+
 	if (!test_thread_flag(TIF_SYSCALL_TRACE))
 		return;
 	if (!(current->ptrace & PT_PTRACED))
@@ -313,11 +317,8 @@ void syscall_trace(void)
 
 	/* the 0x80 provides a way for the tracing parent to distinguish
 	   between a syscall stop and SIGTRAP delivery */
- 	current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
- 					? 0x80 : 0);
-	current->state = TASK_STOPPED;
-	notify_parent(current, SIGCHLD);
-	schedule();
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+				 ? 0x80 : 0));
 
 	/*
 	 * this isn't the same as continuing with a signal, but it will do
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 3e4ab2963..207f89d74 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -15,6 +15,7 @@
 #ifdef CONFIG_SMP
 static void kill_idlers(int me)
 {
+#ifdef CONFIG_MODE_TT
 	struct task_struct *p;
 	int i;
 
@@ -23,6 +24,7 @@ static void kill_idlers(int me)
 		if((p != NULL) && (p->thread.mode.tt.extern_pid != me))
 			os_kill_process(p->thread.mode.tt.extern_pid, 0);
 	}
+#endif
 }
 #endif
 
diff --git a/arch/um/kernel/sigio_kern.c b/arch/um/kernel/sigio_kern.c
index 02272e623..fbffae415 100644
--- a/arch/um/kernel/sigio_kern.c
+++ b/arch/um/kernel/sigio_kern.c
@@ -6,26 +6,33 @@
 #include "linux/kernel.h"
 #include "linux/list.h"
 #include "linux/slab.h"
-#include "asm/irq.h"
+#include "linux/signal.h"
+#include "linux/interrupt.h"
 #include "init.h"
 #include "sigio.h"
 #include "irq_user.h"
+#include "irq_kern.h"
 
 /* Protected by sigio_lock() called from write_sigio_workaround */
 static int sigio_irq_fd = -1;
 
-void sigio_interrupt(int irq, void *data, struct pt_regs *unused)
+static irqreturn_t sigio_interrupt(int irq, void *data, struct pt_regs *unused)
 {
 	read_sigio_fd(sigio_irq_fd);
 	reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ);
+	return(IRQ_HANDLED);
 }
 
 int write_sigio_irq(int fd)
 {
-	if(um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt,
+	int err;
+
+	err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt,
 			  SA_INTERRUPT | SA_SAMPLE_RANDOM, "write sigio", 
-			  NULL)){
-		printk("write_sigio_irq : um_request_irq failed\n");
+			     NULL);
+	if(err){
+		printk("write_sigio_irq : um_request_irq failed, err = %d\n",
+		       err);
 		return(-1);
 	}
 	sigio_irq_fd = fd;
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
index b5ce13d55..82d19b451 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/kernel/sigio_user.c
@@ -7,7 +7,6 @@
 #include <stdlib.h>
 #include <termios.h>
 #include <pty.h>
-#include <fcntl.h>
 #include <signal.h>
 #include <errno.h>
 #include <string.h>
@@ -17,6 +16,7 @@
 #include "init.h"
 #include "user.h"
 #include "kern_util.h"
+#include "user_util.h"
 #include "sigio.h"
 #include "helper.h"
 #include "os.h"
@@ -26,7 +26,7 @@ int pty_output_sigio = 0;
 int pty_close_sigio = 0;
 
 /* Used as a flag during SIGIO testing early in boot */
-static int got_sigio = 0;
+static volatile int got_sigio = 0;
 
 void __init handler(int sig)
 {
@@ -45,19 +45,18 @@ static void openpty_cb(void *arg)
 
 	info->err = 0;
 	if(openpty(&info->master, &info->slave, NULL, NULL, NULL))
-		info->err = errno;
+		info->err = -errno;
 }
 
 void __init check_one_sigio(void (*proc)(int, int))
 {
 	struct sigaction old, new;
-	struct termios tt;
 	struct openpty_arg pty = { .master = -1, .slave = -1 };
-	int master, slave, flags;
+	int master, slave, err;
 
 	initial_thread_cb(openpty_cb, &pty);
 	if(pty.err){
-		printk("openpty failed, errno = %d\n", pty.err);
+		printk("openpty failed, errno = %d\n", -pty.err);
 		return;
 	}
 
@@ -69,23 +68,14 @@ void __init check_one_sigio(void (*proc)(int, int))
 		return;
 	}
 
-	if(tcgetattr(master, &tt) < 0)
-		panic("check_sigio : tcgetattr failed, errno = %d\n", errno);
-	cfmakeraw(&tt);
-	if(tcsetattr(master, TCSADRAIN, &tt) < 0)
-		panic("check_sigio : tcsetattr failed, errno = %d\n", errno);
+	/* Not now, but complain so we now where we failed. */
+	err = raw(master);
+	if (err < 0)
+		panic("check_sigio : __raw failed, errno = %d\n", -err);
 
-	if((flags = fcntl(master, F_GETFL)) < 0)
-		panic("tty_fds : fcntl F_GETFL failed, errno = %d\n", errno);
-
-	if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
-	   (fcntl(master, F_SETOWN, os_getpid()) < 0))
-		panic("check_sigio : fcntl F_SETFL or F_SETOWN failed, "
-		      "errno = %d\n", errno);
-
-	if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
-		panic("check_sigio : fcntl F_SETFL failed, errno = %d\n", 
-		      errno);
+	err = os_sigio_async(master, slave);
+	if(err < 0)
+		panic("tty_fds : sigio_async failed, err = %d\n", -err);
 
 	if(sigaction(SIGIO, NULL, &old) < 0)
 		panic("check_sigio : sigaction 1 failed, errno = %d\n", errno);
@@ -97,8 +87,8 @@ void __init check_one_sigio(void (*proc)(int, int))
 	got_sigio = 0;
 	(*proc)(master, slave);
 		
-	close(master);
-	close(slave);
+	os_close_file(master);
+	os_close_file(slave);
 
 	if(sigaction(SIGIO, &old, NULL) < 0)
 		panic("check_sigio : sigaction 3 failed, errno = %d\n", errno);
@@ -112,25 +102,25 @@ static void tty_output(int master, int slave)
 	printk("Checking that host ptys support output SIGIO...");
 
 	memset(buf, 0, sizeof(buf));
-	while(write(master, buf, sizeof(buf)) > 0) ;
+
+	while(os_write_file(master, buf, sizeof(buf)) > 0) ;
 	if(errno != EAGAIN)
 		panic("check_sigio : write failed, errno = %d\n", errno);
-
-	while(((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
+	while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
 
 	if(got_sigio){
 		printk("Yes\n");
 		pty_output_sigio = 1;
 	}
-	else if(errno == EAGAIN) printk("No, enabling workaround\n");
-	else panic("check_sigio : read failed, errno = %d\n", errno);
+	else if(n == -EAGAIN) printk("No, enabling workaround\n");
+	else panic("check_sigio : read failed, err = %d\n", n);
 }
 
 static void tty_close(int master, int slave)
 {
 	printk("Checking that host ptys support SIGIO on close...");
 
-	close(slave);
+	os_close_file(slave);
 	if(got_sigio){
 		printk("Yes\n");
 		pty_close_sigio = 1;
@@ -140,7 +130,8 @@ static void tty_close(int master, int slave)
 
 void __init check_sigio(void)
 {
-	if(access("/dev/ptmx", R_OK) && access("/dev/ptyp0", R_OK)){
+	if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) &&
+	   (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){
 		printk("No pseudo-terminals available - skipping pty SIGIO "
 		       "check\n");
 		return;
@@ -201,11 +192,10 @@ static int write_sigio_thread(void *unused)
 			p = &fds->poll[i];
 			if(p->revents == 0) continue;
 			if(p->fd == sigio_private[1]){
-				n = read(sigio_private[1], &c, sizeof(c));
+				n = os_read_file(sigio_private[1], &c, sizeof(c));
 				if(n != sizeof(c))
 					printk("write_sigio_thread : "
-					       "read failed, errno = %d\n",
-					       errno);
+					       "read failed, err = %d\n", -n);
 				tmp = current_poll;
 				current_poll = next_poll;
 				next_poll = tmp;
@@ -218,10 +208,10 @@ static int write_sigio_thread(void *unused)
 					(fds->used - i) * sizeof(*fds->poll));
 			}
 
-			n = write(respond_fd, &c, sizeof(c));
+			n = os_write_file(respond_fd, &c, sizeof(c));
 			if(n != sizeof(c))
 				printk("write_sigio_thread : write failed, "
-				       "errno = %d\n", errno);
+				       "err = %d\n", -n);
 		}
 	}
 }
@@ -252,15 +242,15 @@ static void update_thread(void)
 	char c;
 
 	flags = set_signals(0);
-	n = write(sigio_private[0], &c, sizeof(c));
+	n = os_write_file(sigio_private[0], &c, sizeof(c));
 	if(n != sizeof(c)){
-		printk("update_thread : write failed, errno = %d\n", errno);
+		printk("update_thread : write failed, err = %d\n", -n);
 		goto fail;
 	}
 
-	n = read(sigio_private[0], &c, sizeof(c));
+	n = os_read_file(sigio_private[0], &c, sizeof(c));
 	if(n != sizeof(c)){
-		printk("update_thread : read failed, errno = %d\n", errno);
+		printk("update_thread : read failed, err = %d\n", -n);
 		goto fail;
 	}
 
@@ -271,10 +261,10 @@ static void update_thread(void)
 	if(write_sigio_pid != -1) 
 		os_kill_process(write_sigio_pid, 1);
 	write_sigio_pid = -1;
-	close(sigio_private[0]);
-	close(sigio_private[1]);	
-	close(write_sigio_fds[0]);
-	close(write_sigio_fds[1]);
+	os_close_file(sigio_private[0]);
+	os_close_file(sigio_private[1]);
+	os_close_file(write_sigio_fds[0]);
+	os_close_file(write_sigio_fds[1]);
 	sigio_unlock();
 	set_signals(flags);
 }
@@ -369,15 +359,15 @@ void write_sigio_workaround(void)
 		goto out;
 
 	err = os_pipe(write_sigio_fds, 1, 1);
-	if(err){
+	if(err < 0){
 		printk("write_sigio_workaround - os_pipe 1 failed, "
-		       "errno = %d\n", -err);
+		       "err = %d\n", -err);
 		goto out;
 	}
 	err = os_pipe(sigio_private, 1, 1);
-	if(err){
+	if(err < 0){
 		printk("write_sigio_workaround - os_pipe 2 failed, "
-		       "errno = %d\n", -err);
+		       "err = %d\n", -err);
 		goto out_close1;
 	}
 	if(setup_initial_poll(sigio_private[1]))
@@ -399,11 +389,11 @@ void write_sigio_workaround(void)
 	os_kill_process(write_sigio_pid, 1);
 	write_sigio_pid = -1;
  out_close2:
-	close(sigio_private[0]);
-	close(sigio_private[1]);	
+	os_close_file(sigio_private[0]);
+	os_close_file(sigio_private[1]);
  out_close1:
-	close(write_sigio_fds[0]);
-	close(write_sigio_fds[1]);
+	os_close_file(write_sigio_fds[0]);
+	os_close_file(write_sigio_fds[1]);
 	sigio_unlock();
 }
 
@@ -412,10 +402,16 @@ int read_sigio_fd(int fd)
 	int n;
 	char c;
 
-	n = read(fd, &c, sizeof(c));
+	n = os_read_file(fd, &c, sizeof(c));
 	if(n != sizeof(c)){
-		printk("read_sigio_fd - read failed, errno = %d\n", errno);
-		return(-errno);
+		if(n < 0) {
+			printk("read_sigio_fd - read failed, err = %d\n", -n);
+			return(n);
+		}
+		else {
+			printk("read_sigio_fd - short read, bytes = %d\n", n);
+			return(-EIO);
+		}
 	}
 	return(n);
 }
diff --git a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c
index 6e13847ed..23aefcbea 100644
--- a/arch/um/kernel/signal_kern.c
+++ b/arch/um/kernel/signal_kern.c
@@ -31,17 +31,6 @@
 EXPORT_SYMBOL(block_signals);
 EXPORT_SYMBOL(unblock_signals);
 
-static void force_segv(int sig)
-{
-	if(sig == SIGSEGV){
-		struct k_sigaction *ka;
-
-		ka = &current->sig->action[SIGSEGV - 1];
-		ka->sa.sa_handler = SIG_DFL;
-	}
-	force_sig(SIGSEGV, current);
-}
-
 #define _S(nr) (1<<((nr)-1))
 
 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
@@ -60,10 +49,10 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
 	int err, ret;
 
 	ret = 0;
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
 	switch(error){
 	case -ERESTART_RESTARTBLOCK:
-		current_thread_info()->restart_block.fn = 
-			do_no_restart_syscall;
 	case -ERESTARTNOHAND:
 		ret = -EINTR;
 		break;
@@ -124,27 +113,27 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
 
 	return(0);
  segv:
-	force_segv(signr);
+	force_sigsegv(signr, current);
 	return(1);
 }
 
 static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset, int error)
 {
+	struct k_sigaction ka_copy;
 	siginfo_t info;
-	struct k_sigaction *ka;
 	int err, sig;
 
 	if (!oldset)
 		oldset = &current->blocked;
 
-	sig = get_signal_to_deliver(&info, regs, NULL);
+	sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL);
 	if(sig == 0)
 		return(0);
 
 	/* Whee!  Actually deliver the signal.  */
-	ka = &current->sig->action[sig -1 ];
-	err = handle_signal(regs, sig, ka, &info, oldset, error);
-	if(!err) return(1);
+	err = handle_signal(regs, sig, &ka_copy, &info, oldset, error);
+	if(!err)
+		return(1);
 
 	/* Did we come from a system call? */
 	if(PT_REGS_SYSCALL_NR(regs) >= 0){
@@ -201,7 +190,7 @@ int sys_sigsuspend(int history0, int history1, old_sigset_t mask)
 	}
 }
 
-int sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize)
+int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
 {
 	sigset_t saveset, newset;
 
@@ -227,20 +216,59 @@ int sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize)
 	}
 }
 
+int sys_sigaction(int sig, const struct old_sigaction __user *act,
+			 struct old_sigaction __user *oact)
+{
+	struct k_sigaction new_ka, old_ka;
+	int ret;
+
+	if (act) {
+		old_sigset_t mask;
+		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+			return -EFAULT;
+		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
+		__get_user(mask, &act->sa_mask);
+		siginitset(&new_ka.sa.sa_mask, mask);
+	}
+
+	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+	if (!ret && oact) {
+		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+			return -EFAULT;
+		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+	}
+
+	return ret;
+}
+
+int sys_sigaltstack(const stack_t *uss, stack_t *uoss)
+{
+	return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
+}
+
+extern int userspace_pid[];
+
 static int copy_sc_from_user(struct pt_regs *to, void *from, 
 			     struct arch_frame_data *arch)
 {
 	int ret;
 
 	ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, arch),
-			  copy_sc_from_user_skas(&to->regs, from));
+			  copy_sc_from_user_skas(userspace_pid[0],
+						 &to->regs, from));
 	return(ret);
 }
 
 int sys_sigreturn(struct pt_regs regs)
 {
-	void *sc = sp_to_sc(PT_REGS_SP(&current->thread.regs));
-	void *mask = sp_to_mask(PT_REGS_SP(&current->thread.regs));
+	void __user *sc = sp_to_sc(PT_REGS_SP(&current->thread.regs));
+	void __user *mask = sp_to_mask(PT_REGS_SP(&current->thread.regs));
 	int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
 
 	spin_lock_irq(&current->sighand->siglock);
@@ -257,8 +285,8 @@ int sys_sigreturn(struct pt_regs regs)
 
 int sys_rt_sigreturn(struct pt_regs regs)
 {
-	struct ucontext *uc = sp_to_uc(PT_REGS_SP(&current->thread.regs));
-	void *fp;
+	unsigned long sp = PT_REGS_SP(&current->thread.regs);
+	struct ucontext __user *uc = sp_to_uc(sp);
 	int sig_size = _NSIG_WORDS * sizeof(unsigned long);
 
 	spin_lock_irq(&current->sighand->siglock);
@@ -266,7 +294,6 @@ int sys_rt_sigreturn(struct pt_regs regs)
 	sigdelsetmask(&current->blocked, ~_BLOCKABLE);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
-	fp = (void *) (((unsigned long) uc) + sizeof(struct ucontext));
 	copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext,
 			  &signal_frame_si.common.arch);
 	return(PT_REGS_SYSCALL_RET(&current->thread.regs));
diff --git a/arch/um/kernel/signal_user.c b/arch/um/kernel/signal_user.c
index 52cfd60a1..74a69e491 100644
--- a/arch/um/kernel/signal_user.c
+++ b/arch/um/kernel/signal_user.c
@@ -80,6 +80,12 @@ void unblock_signals(void)
 	change_signals(SIG_UNBLOCK);
 }
 
+/* These are the asynchronous signals.  SIGVTALRM and SIGARLM are handled
+ * together under SIGVTALRM_BIT.  SIGPROF is excluded because we want to
+ * be able to profile all of UML, not just the non-critical sections.  If
+ * profiling is not thread-safe, then that is not my problem.  We can disable
+ * profiling when SMP is enabled in that case.
+ */
 #define SIGIO_BIT 0
 #define SIGVTALRM_BIT 1
 
@@ -114,6 +120,11 @@ int set_signals(int enable)
 		sigaddset(&mask, SIGVTALRM);
 		sigaddset(&mask, SIGALRM);
 	}
+
+	/* This is safe - sigprocmask is guaranteed to copy locally the
+	 * value of new_set, do his work and then, at the end, write to
+	 * old_set.
+	 */
 	if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
 		panic("Failed to enable signals");
 	ret = enable_mask(&mask);
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index 72c79956f..37d3f7e97 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -3,22 +3,14 @@
 # Licensed under the GPL
 #
 
-obj-y = exec_kern.o exec_user.o mem.o mem_user.o mmu.o process.o \
+obj-y := exec_kern.o exec_user.o mem.o mem_user.o mmu.o process.o \
 	process_kern.o syscall_kern.o syscall_user.o time.o tlb.o trap_user.o \
-	sys-$(SUBARCH)/
+	uaccess.o sys-$(SUBARCH)/
+
+subdir-y := util
 
 USER_OBJS = $(filter %_user.o,$(obj-y)) process.o time.o
 USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
 
-include/skas_ptregs.h : util/mk_ptregs
-	util/mk_ptregs > $@
-
-util/mk_ptregs :
-	$(MAKE) -C util
-
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean :
-	$(MAKE) -C util clean
-	$(RM) -f include/skas_ptregs.h
diff --git a/arch/um/kernel/skas/exec_user.c b/arch/um/kernel/skas/exec_user.c
index c9942b6fc..d50633a70 100644
--- a/arch/um/kernel/skas/exec_user.c
+++ b/arch/um/kernel/skas/exec_user.c
@@ -11,6 +11,7 @@
 #include <sys/ptrace.h>
 #include "user.h"
 #include "kern_util.h"
+#include "user_util.h"
 #include "os.h"
 #include "time_user.h"
 
@@ -26,7 +27,7 @@ static int user_thread_tramp(void *arg)
 
 int user_thread(unsigned long stack, int flags)
 {
-	int pid, status;
+	int pid, status, err;
 
 	pid = clone(user_thread_tramp, (void *) stack_sp(stack), 
 		    flags | CLONE_FILES | SIGCHLD, NULL);
@@ -35,7 +36,8 @@ int user_thread(unsigned long stack, int flags)
 		return(pid);
 	}
 
-	if(waitpid(pid, &status, WUNTRACED) < 0){
+	CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
+	if(err < 0){
 		printk("user_thread - waitpid failed, errno = %d\n", errno);
 		return(-errno);
 	}
diff --git a/arch/um/kernel/skas/include/mode.h b/arch/um/kernel/skas/include/mode.h
index 7516206cc..285edc50a 100644
--- a/arch/um/kernel/skas/include/mode.h
+++ b/arch/um/kernel/skas/include/mode.h
@@ -12,14 +12,16 @@ extern unsigned long exec_fpx_regs[];
 extern int have_fpx_regs;
 
 extern void user_time_init_skas(void);
-extern int copy_sc_from_user_skas(union uml_pt_regs *regs, void *from_ptr);
-extern int copy_sc_to_user_skas(void *to_ptr, void *fp, 
+extern int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs,
+				  void *from_ptr);
+extern int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp,
 				union uml_pt_regs *regs, 
 				unsigned long fault_addr, int fault_type);
 extern void sig_handler_common_skas(int sig, void *sc_ptr);
 extern void halt_skas(void);
 extern void reboot_skas(void);
 extern void kill_off_processes_skas(void);
+extern int is_skas_winch(int pid, int fd, void *data);
 
 #endif
 
diff --git a/arch/um/kernel/skas/include/ptrace-skas.h b/arch/um/kernel/skas/include/ptrace-skas.h
index f5c5268cc..be043e8f7 100644
--- a/arch/um/kernel/skas/include/ptrace-skas.h
+++ b/arch/um/kernel/skas/include/ptrace-skas.h
@@ -10,6 +10,16 @@
 
 #ifdef UML_CONFIG_MODE_SKAS
 
+/* syscall emulation path in ptrace */
+
+#ifndef PTRACE_SYSEMU
+#define PTRACE_SYSEMU 31
+#endif
+
+void set_using_sysemu(int value);
+int get_using_sysemu(void);
+extern int sysemu_supported;
+
 #include "skas_ptregs.h"
 
 #define HOST_FRAME_SIZE 17
diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
index d9614f6cd..0bbc97540 100644
--- a/arch/um/kernel/skas/include/skas.h
+++ b/arch/um/kernel/skas/include/skas.h
@@ -8,7 +8,7 @@
 
 #include "sysdep/ptrace.h"
 
-extern int userspace_pid;
+extern int userspace_pid[];
 
 extern void switch_threads(void *me, void *next);
 extern void thread_wait(void *sw, void *fb);
@@ -32,7 +32,7 @@ extern int singlestepping_skas(void);
 extern int new_mm(int from);
 extern void save_registers(union uml_pt_regs *regs);
 extern void restore_registers(union uml_pt_regs *regs);
-extern void start_userspace(void);
+extern void start_userspace(int cpu);
 extern void init_registers(int pid);
 
 #endif
diff --git a/arch/um/kernel/skas/include/uaccess.h b/arch/um/kernel/skas/include/uaccess.h
index d28c4b1de..0d6f30bf7 100644
--- a/arch/um/kernel/skas/include/uaccess.h
+++ b/arch/um/kernel/skas/include/uaccess.h
@@ -6,20 +6,12 @@
 #ifndef __SKAS_UACCESS_H
 #define __SKAS_UACCESS_H
 
-#include "linux/string.h"
-#include "linux/sched.h"
-#include "linux/err.h"
-#include "asm/processor.h"
-#include "asm/pgtable.h"
 #include "asm/errno.h"
-#include "asm/current.h"
-#include "asm/a.out.h"
-#include "kern_util.h"
 
 #define access_ok_skas(type, addr, size) \
 	((segment_eq(get_fs(), KERNEL_DS)) || \
 	 (((unsigned long) (addr) < TASK_SIZE) && \
-	  ((unsigned long) (addr) + (size) < TASK_SIZE)))
+	  ((unsigned long) (addr) + (size) <= TASK_SIZE)))
 
 static inline int verify_area_skas(int type, const void * addr, 
 				   unsigned long size)
@@ -27,197 +19,12 @@ static inline int verify_area_skas(int type, const void * addr,
 	return(access_ok_skas(type, addr, size) ? 0 : -EFAULT);
 }
 
-static inline unsigned long maybe_map(unsigned long virt, int is_write)
-{
-	pte_t pte;
-
-	void *phys = um_virt_to_phys(current, virt, &pte);
-	int dummy_code;
-
-	if(IS_ERR(phys) || (is_write && !pte_write(pte))){
-		if(handle_page_fault(virt, 0, is_write, 0, &dummy_code))
-			return(0);
-		phys = um_virt_to_phys(current, virt, NULL);
-	}
-	return((unsigned long) __va((unsigned long) phys));
-}
-
-static inline int buffer_op(unsigned long addr, int len, 
-			    int (*op)(unsigned long addr, int len, void *arg),
-			    void *arg)
-{
-	int size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len);
-	int remain = len, n;
-
-	n = (*op)(addr, size, arg);
-	if(n != 0)
-		return(n < 0 ? remain : 0);
-
-	addr += size;
-	remain -= size;
-	if(remain == 0) 
-		return(0);
-
-	while(addr < ((addr + remain) & PAGE_MASK)){
-		n = (*op)(addr, PAGE_SIZE, arg);
-		if(n != 0)
-			return(n < 0 ? remain : 0);
-
-		addr += PAGE_SIZE;
-		remain -= PAGE_SIZE;
-	}
-	if(remain == 0)
-		return(0);
-
-	n = (*op)(addr, remain, arg);
-	if(n != 0)
-		return(n < 0 ? remain : 0);
-	return(0);
-}
-
-static inline int copy_chunk_from_user(unsigned long from, int len, void *arg)
-{
-	unsigned long *to_ptr = arg, to = *to_ptr;
-
-	from = maybe_map(from, 0);
-	if(from == 0)
-		return(-1);
-
-	memcpy((void *) to, (void *) from, len);
-	*to_ptr += len;
-	return(0);
-}
-
-static inline int copy_from_user_skas(void *to, const void *from, int n)
-{
-	if(segment_eq(get_fs(), KERNEL_DS)){
-		memcpy(to, from, n);
-		return(0);
-	}
-
-	return(access_ok_skas(VERIFY_READ, from, n) ?
-	       buffer_op((unsigned long) from, n, copy_chunk_from_user, &to) :
-	       n);
-}
-
-static inline int copy_chunk_to_user(unsigned long to, int len, void *arg)
-{
-	unsigned long *from_ptr = arg, from = *from_ptr;
-
-	to = maybe_map(to, 1);
-	if(to == 0)
-		return(-1);
-
-	memcpy((void *) to, (void *) from, len);
-	*from_ptr += len;
-	return(0);
-}
-
-static inline int copy_to_user_skas(void *to, const void *from, int n)
-{
-	if(segment_eq(get_fs(), KERNEL_DS)){
-		memcpy(to, from, n);
-		return(0);
-	}
-
-	return(access_ok_skas(VERIFY_WRITE, to, n) ?
-	       buffer_op((unsigned long) to, n, copy_chunk_to_user, &from) :
-	       n);
-}
-
-static inline int strncpy_chunk_from_user(unsigned long from, int len, 
-					  void *arg)
-{
-        char **to_ptr = arg, *to = *to_ptr;
-	int n;
-
-	from = maybe_map(from, 0);
-	if(from == 0)
-		return(-1);
-
-	strncpy(to, (void *) from, len);
-	n = strnlen(to, len);
-	*to_ptr += n;
-
-	if(n < len) 
-	        return(1);
-	return(0);
-}
-
-static inline int strncpy_from_user_skas(char *dst, const char *src, int count)
-{
-	int n;
-	char *ptr = dst;
-
-	if(segment_eq(get_fs(), KERNEL_DS)){
-		strncpy(dst, src, count);
-		return(strnlen(dst, count));
-	}
-
-	if(!access_ok_skas(VERIFY_READ, src, 1))
-		return(-EFAULT);
-
-	n = buffer_op((unsigned long) src, count, strncpy_chunk_from_user, 
-		      &ptr);
-	if(n != 0)
-		return(-EFAULT);
-	return(strnlen(dst, count));
-}
-
-static inline int clear_chunk(unsigned long addr, int len, void *unused)
-{
-	addr = maybe_map(addr, 1);
-	if(addr == 0) 
-		return(-1);
-
-	memset((void *) addr, 0, len);
-	return(0);
-}
-
-static inline int __clear_user_skas(void *mem, int len)
-{
-	return(buffer_op((unsigned long) mem, len, clear_chunk, NULL));
-}
-
-static inline int clear_user_skas(void *mem, int len)
-{
-	if(segment_eq(get_fs(), KERNEL_DS)){
-		memset(mem, 0, len);
-		return(0);
-	}
-
-	return(access_ok_skas(VERIFY_WRITE, mem, len) ? 
-	       buffer_op((unsigned long) mem, len, clear_chunk, NULL) : len);
-}
-
-static inline int strnlen_chunk(unsigned long str, int len, void *arg)
-{
-	int *len_ptr = arg, n;
-
-	str = maybe_map(str, 0);
-	if(str == 0) 
-		return(-1);
-
-	n = strnlen((void *) str, len);
-	*len_ptr += n;
-
-	if(n < len)
-		return(1);
-	return(0);
-}
-
-static inline int strnlen_user_skas(const void *str, int len)
-{
-	int count = 0, n;
-
-	if(segment_eq(get_fs(), KERNEL_DS))
-		return(strnlen(str, len) + 1);
-
-	n = buffer_op((unsigned long) str, len, strnlen_chunk, &count);
-	if(n == 0)
-		return(count + 1);
-	return(-EFAULT);
-}
+extern int copy_from_user_skas(void *to, const void *from, int n);
+extern int copy_to_user_skas(void *to, const void *from, int n);
+extern int strncpy_from_user_skas(char *dst, const char *src, int count);
+extern int __clear_user_skas(void *mem, int len);
+extern int clear_user_skas(void *mem, int len);
+extern int strnlen_user_skas(const void *str, int len);
 
 #endif
 
diff --git a/arch/um/kernel/skas/mem_user.c b/arch/um/kernel/skas/mem_user.c
index d163090c0..cfcfa0d60 100644
--- a/arch/um/kernel/skas/mem_user.c
+++ b/arch/um/kernel/skas/mem_user.c
@@ -7,6 +7,7 @@
 #include <sys/mman.h>
 #include <sys/ptrace.h>
 #include "mem_user.h"
+#include "mem.h"
 #include "user.h"
 #include "os.h"
 #include "proc_mm.h"
@@ -15,12 +16,12 @@ void map(int fd, unsigned long virt, unsigned long phys, unsigned long len,
 	 int r, int w, int x)
 {
 	struct proc_mm_op map;
-	struct mem_region *region;
-	int prot, n;
+	__u64 offset;
+	int prot, n, phys_fd;
 
 	prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | 
 		(x ? PROT_EXEC : 0);
-	region = phys_region(phys);
+	phys_fd = phys_mapping(phys, &offset);
 
 	map = ((struct proc_mm_op) { .op 	= MM_MMAP,
 				     .u 	= 
@@ -30,12 +31,12 @@ void map(int fd, unsigned long virt, unsigned long phys, unsigned long len,
 					 .prot		= prot,
 					 .flags		= MAP_SHARED | 
 					                  MAP_FIXED,
-					 .fd		= region->fd,
-					 .offset	= phys_offset(phys)
+					 .fd		= phys_fd,
+					 .offset	= offset
 				       } } } );
 	n = os_write_file(fd, &map, sizeof(map));
 	if(n != sizeof(map)) 
-		printk("map : /proc/mm map failed, errno = %d\n", errno);
+		printk("map : /proc/mm map failed, err = %d\n", -n);
 }
 
 int unmap(int fd, void *addr, int len)
@@ -49,8 +50,13 @@ int unmap(int fd, void *addr, int len)
 					 { .addr 	= (unsigned long) addr,
 					   .len		= len } } } );
 	n = os_write_file(fd, &unmap, sizeof(unmap));
-	if((n != 0) && (n != sizeof(unmap)))
-		return(-errno);
+	if(n != sizeof(unmap)) {
+		if(n < 0)
+			return(n);
+		else if(n > 0)
+			return(-EIO);
+	}
+
 	return(0);
 }
 
@@ -71,11 +77,15 @@ int protect(int fd, unsigned long addr, unsigned long len, int r, int w,
 					   .prot	= prot } } } );
 
 	n = os_write_file(fd, &protect, sizeof(protect));
-	if((n != 0) && (n != sizeof(protect))){
+	if(n != sizeof(protect)) {
+		if(n == 0) return(0);
+
 		if(must_succeed)
-			panic("protect failed, errno = %d", errno);
-		return(-errno);
+			panic("protect failed, err = %d", -n);
+
+		return(-EIO);
 	}
+
 	return(0);
 }
 
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 5911cdd0c..6cb9a6d02 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -22,9 +22,11 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
 	else from = -1;
 
 	mm->context.skas.mm_fd = new_mm(from);
-	if(mm->context.skas.mm_fd < 0)
-		panic("init_new_context_skas - new_mm failed, errno = %d\n",
-		      mm->context.skas.mm_fd);
+	if(mm->context.skas.mm_fd < 0){
+		printk("init_new_context_skas - new_mm failed, errno = %d\n",
+		       mm->context.skas.mm_fd);
+		return(mm->context.skas.mm_fd);
+	}
 
 	return(0);
 }
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index cb91f8cd1..cb748f85d 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -4,6 +4,7 @@
  */
 
 #include <stdlib.h>
+#include <unistd.h>
 #include <errno.h>
 #include <signal.h>
 #include <setjmp.h>
@@ -24,6 +25,19 @@
 #include "os.h"
 #include "proc_mm.h"
 #include "skas_ptrace.h"
+#include "chan_user.h"
+#include "signal_user.h"
+
+int is_skas_winch(int pid, int fd, void *data)
+{
+	if(pid != getpid())
+		return(0);
+
+	register_winch_irq(-1, fd, -1, data);
+	return(1);
+}
+
+/* These are set once at boot time and not changed thereafter */
 
 unsigned long exec_regs[FRAME_SIZE];
 unsigned long exec_fp_regs[HOST_FP_SIZE];
@@ -43,37 +57,39 @@ static void handle_segv(int pid)
 	segv(fault.addr, 0, FAULT_WRITE(fault.is_write), 1, NULL);
 }
 
-static void handle_trap(int pid, union uml_pt_regs *regs)
+/*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/
+static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu)
 {
 	int err, syscall_nr, status;
 
 	syscall_nr = PT_SYSCALL_NR(regs->skas.regs);
+	UPT_SYSCALL_NR(regs) = syscall_nr;
 	if(syscall_nr < 1){
 		relay_signal(SIGTRAP, regs);
 		return;
 	}
-	UPT_SYSCALL_NR(regs) = syscall_nr;
 
-	err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
-	if(err < 0)
-	        panic("handle_trap - nullifying syscall failed errno = %d\n", 
-		      errno);
+	if (!local_using_sysemu)
+	{
+		err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
+		if(err < 0)
+			panic("handle_trap - nullifying syscall failed errno = %d\n",
+			      errno);
 
-	err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
-	if(err < 0)
-	        panic("handle_trap - continuing to end of syscall failed, "
-		      "errno = %d\n", errno);
+		err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
+		if(err < 0)
+			panic("handle_trap - continuing to end of syscall failed, "
+			      "errno = %d\n", errno);
 
-	err = waitpid(pid, &status, WUNTRACED);
-	if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
-		panic("handle_trap - failed to wait at end of syscall, "
-		      "errno = %d, status = %d\n", errno, status);
+		CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
+		if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
+			panic("handle_trap - failed to wait at end of syscall, "
+			      "errno = %d, status = %d\n", errno, status);
+	}
 
 	handle_syscall(regs);
 }
 
-int userspace_pid;
-
 static int userspace_tramp(void *arg)
 {
 	init_new_thread_signals(0);
@@ -83,7 +99,11 @@ static int userspace_tramp(void *arg)
 	return(0);
 }
 
-void start_userspace(void)
+/* Each element set once, and only accessed by a single processor anyway */
+#define NR_CPUS 1
+int userspace_pid[NR_CPUS];
+
+void start_userspace(int cpu)
 {
 	void *stack;
 	unsigned long sp;
@@ -101,7 +121,7 @@ void start_userspace(void)
 		panic("start_userspace : clone failed, errno = %d", errno);
 
 	do {
-		n = waitpid(pid, &status, WUNTRACED);
+		CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
 		if(n < 0)
 			panic("start_userspace : wait failed, errno = %d", 
 			      errno);
@@ -114,21 +134,27 @@ void start_userspace(void)
 	if(munmap(stack, PAGE_SIZE) < 0)
 		panic("start_userspace : munmap failed, errno = %d\n", errno);
 
-	userspace_pid = pid;
+	userspace_pid[cpu] = pid;
 }
 
 void userspace(union uml_pt_regs *regs)
 {
-	int err, status, op;
+	int err, status, op, pid = userspace_pid[0];
+	int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/
 
 	restore_registers(regs);
 		
-	err = ptrace(PTRACE_SYSCALL, userspace_pid, 0, 0);
+	local_using_sysemu = get_using_sysemu();
+
+	if (local_using_sysemu)
+		err = ptrace(PTRACE_SYSEMU, pid, 0, 0);
+	else
+		err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
 	if(err)
-		panic("userspace - PTRACE_SYSCALL failed, errno = %d\n", 
-		       errno);
+		panic("userspace - PTRACE_%s failed, errno = %d\n",
+		       local_using_sysemu ? "SYSEMU" : "SYSCALL", errno);
 	while(1){
-		err = waitpid(userspace_pid, &status, WUNTRACED);
+		CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
 		if(err < 0)
 			panic("userspace - waitpid failed, errno = %d\n", 
 			      errno);
@@ -139,16 +165,17 @@ void userspace(union uml_pt_regs *regs)
 		if(WIFSTOPPED(status)){
 		  	switch(WSTOPSIG(status)){
 			case SIGSEGV:
-				handle_segv(userspace_pid);
+				handle_segv(pid);
 				break;
 			case SIGTRAP:
-			        handle_trap(userspace_pid, regs);
+			        handle_trap(pid, regs, local_using_sysemu);
 				break;
 			case SIGIO:
 			case SIGVTALRM:
 			case SIGILL:
 			case SIGBUS:
 			case SIGFPE:
+			case SIGWINCH:
 				user_signal(WSTOPSIG(status), regs);
 				break;
 			default:
@@ -160,45 +187,66 @@ void userspace(union uml_pt_regs *regs)
 
 		restore_registers(regs);
 
-		op = singlestepping_skas() ? PTRACE_SINGLESTEP : 
-			PTRACE_SYSCALL;
-		err = ptrace(op, userspace_pid, 0, 0);
+		/*Now we ended the syscall, so re-read local_using_sysemu.*/
+		local_using_sysemu = get_using_sysemu();
+
+		if (local_using_sysemu)
+			op = singlestepping_skas() ? PTRACE_SINGLESTEP :
+				PTRACE_SYSEMU;
+		else
+			op = singlestepping_skas() ? PTRACE_SINGLESTEP :
+				PTRACE_SYSCALL;
+
+		err = ptrace(op, pid, 0, 0);
 		if(err)
-			panic("userspace - PTRACE_SYSCALL failed, "
-			      "errno = %d\n", errno);
+			panic("userspace - PTRACE_%s failed, "
+			      "errno = %d\n",
+			      local_using_sysemu ? "SYSEMU" : "SYSCALL", errno);
 	}
 }
 
 void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
 		void (*handler)(int))
 {
-	jmp_buf switch_buf, fork_buf;
+	unsigned long flags;
+	sigjmp_buf switch_buf, fork_buf;
 
 	*switch_buf_ptr = &switch_buf;
 	*fork_buf_ptr = &fork_buf;
 
-	if(setjmp(fork_buf) == 0)
+	/* Somewhat subtle - siglongjmp restores the signal mask before doing
+	 * the longjmp.  This means that when jumping from one stack to another
+	 * when the target stack has interrupts enabled, an interrupt may occur
+	 * on the source stack.  This is bad when starting up a process because
+	 * it's not supposed to get timer ticks until it has been scheduled.
+	 * So, we disable interrupts around the sigsetjmp to ensure that
+	 * they can't happen until we get back here where they are safe.
+	 */
+	flags = get_signals();
+	block_signals();
+	if(sigsetjmp(fork_buf, 1) == 0)
 		new_thread_proc(stack, handler);
+	set_signals(flags);
 
 	remove_sigstack();
 }
 
 void thread_wait(void *sw, void *fb)
 {
-	jmp_buf buf, **switch_buf = sw, *fork_buf;
+	sigjmp_buf buf, **switch_buf = sw, *fork_buf;
 
 	*switch_buf = &buf;
 	fork_buf = fb;
-	if(setjmp(buf) == 0)
-		longjmp(*fork_buf, 1);
+	if(sigsetjmp(buf, 1) == 0)
+		siglongjmp(*fork_buf, 1);
 }
 
-static int move_registers(int int_op, int fp_op, union uml_pt_regs *regs,
-			  unsigned long *fp_regs)
+static int move_registers(int pid, int int_op, int fp_op,
+			  union uml_pt_regs *regs, unsigned long *fp_regs)
 {
-	if(ptrace(int_op, userspace_pid, 0, regs->skas.regs) < 0)
+	if(ptrace(int_op, pid, 0, regs->skas.regs) < 0)
 		return(-errno);
-	if(ptrace(fp_op, userspace_pid, 0, fp_regs) < 0)
+	if(ptrace(fp_op, pid, 0, fp_regs) < 0)
 		return(-errno);
 	return(0);
 }
@@ -217,10 +265,11 @@ void save_registers(union uml_pt_regs *regs)
 		fp_regs = regs->skas.fp;
 	}
 
-	err = move_registers(PTRACE_GETREGS, fp_op, regs, fp_regs);
+	err = move_registers(userspace_pid[0], PTRACE_GETREGS, fp_op, regs,
+			     fp_regs);
 	if(err)
 		panic("save_registers - saving registers failed, errno = %d\n",
-		      err);
+		      -err);
 }
 
 void restore_registers(union uml_pt_regs *regs)
@@ -237,42 +286,43 @@ void restore_registers(union uml_pt_regs *regs)
 		fp_regs = regs->skas.fp;
 	}
 
-	err = move_registers(PTRACE_SETREGS, fp_op, regs, fp_regs);
+	err = move_registers(userspace_pid[0], PTRACE_SETREGS, fp_op, regs,
+			     fp_regs);
 	if(err)
 		panic("restore_registers - saving registers failed, "
-		      "errno = %d\n", err);
+		      "errno = %d\n", -err);
 }
 
 void switch_threads(void *me, void *next)
 {
-	jmp_buf my_buf, **me_ptr = me, *next_buf = next;
+	sigjmp_buf my_buf, **me_ptr = me, *next_buf = next;
 	
 	*me_ptr = &my_buf;
-	if(setjmp(my_buf) == 0)
-		longjmp(*next_buf, 1);
+	if(sigsetjmp(my_buf, 1) == 0)
+		siglongjmp(*next_buf, 1);
 }
 
-static jmp_buf initial_jmpbuf;
+static sigjmp_buf initial_jmpbuf;
 
 /* XXX Make these percpu */
 static void (*cb_proc)(void *arg);
 static void *cb_arg;
-static jmp_buf *cb_back;
+static sigjmp_buf *cb_back;
 
 int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
 {
-	jmp_buf **switch_buf = switch_buf_ptr;
+	sigjmp_buf **switch_buf = switch_buf_ptr;
 	int n;
 
 	*fork_buf_ptr = &initial_jmpbuf;
-	n = setjmp(initial_jmpbuf);
+	n = sigsetjmp(initial_jmpbuf, 1);
 	if(n == 0)
 		new_thread_proc((void *) stack, new_thread_handler);
 	else if(n == 1)
 		remove_sigstack();
 	else if(n == 2){
 		(*cb_proc)(cb_arg);
-		longjmp(*cb_back, 1);
+		siglongjmp(*cb_back, 1);
 	}
 	else if(n == 3){
 		kmalloc_ok = 0;
@@ -282,7 +332,7 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
 		kmalloc_ok = 0;
 		return(1);
 	}
-	longjmp(**switch_buf, 1);
+	siglongjmp(**switch_buf, 1);
 }
 
 void remove_sigstack(void)
@@ -297,15 +347,15 @@ void remove_sigstack(void)
 
 void initial_thread_cb_skas(void (*proc)(void *), void *arg)
 {
-	jmp_buf here;
+	sigjmp_buf here;
 
 	cb_proc = proc;
 	cb_arg = arg;
 	cb_back = &here;
 
 	block_signals();
-	if(setjmp(here) == 0)
-		longjmp(initial_jmpbuf, 2);
+	if(sigsetjmp(here, 1) == 0)
+		siglongjmp(initial_jmpbuf, 2);
 	unblock_signals();
 
 	cb_proc = NULL;
@@ -316,40 +366,21 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
 void halt_skas(void)
 {
 	block_signals();
-	longjmp(initial_jmpbuf, 3);
+	siglongjmp(initial_jmpbuf, 3);
 }
 
 void reboot_skas(void)
 {
 	block_signals();
-	longjmp(initial_jmpbuf, 4);
-}
-
-int new_mm(int from)
-{
-	struct proc_mm_op copy;
-	int n, fd = os_open_file("/proc/mm", of_write(OPENFLAGS()), 0);
-
-	if(fd < 0)
-		return(-errno);
-
-	if(from != -1){
-		copy = ((struct proc_mm_op) { .op 	= MM_COPY_SEGMENTS,
-					      .u 	= 
-					      { .copy_segments	= from } } );
-		n = os_write_file(fd, &copy, sizeof(copy));
-		if(n != sizeof(copy)) 
-			printk("new_mm : /proc/mm copy_segments failed, "
-			       "errno = %d\n", errno);
-	}
-	return(fd);
+	siglongjmp(initial_jmpbuf, 4);
 }
 
 void switch_mm_skas(int mm_fd)
 {
 	int err;
 
-	err = ptrace(PTRACE_SWITCH_MM, userspace_pid, 0, mm_fd);
+#warning need cpu pid in switch_mm_skas
+	err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_fd);
 	if(err)
 		panic("switch_mm_skas - PTRACE_SWITCH_MM failed, errno = %d\n",
 		      errno);
@@ -357,7 +388,8 @@ void switch_mm_skas(int mm_fd)
 
 void kill_off_processes_skas(void)
 {
-	os_kill_process(userspace_pid, 1);
+#warning need to loop over userspace_pids in kill_off_processes_skas
+	os_kill_process(userspace_pid[0], 1);
 }
 
 void init_registers(int pid)
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index 128146c80..5418f0862 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -6,6 +6,12 @@
 #include "linux/sched.h"
 #include "linux/slab.h"
 #include "linux/ptrace.h"
+#include "linux/proc_fs.h"
+#include "linux/file.h"
+#include "linux/errno.h"
+#include "linux/init.h"
+#include "asm/uaccess.h"
+#include "asm/atomic.h"
 #include "kern_util.h"
 #include "time_user.h"
 #include "signal_user.h"
@@ -16,6 +22,62 @@
 #include "frame.h"
 #include "kern.h"
 #include "mode.h"
+#include "proc_mm.h"
+
+static atomic_t using_sysemu;
+int sysemu_supported;
+
+void set_using_sysemu(int value)
+{
+	atomic_set(&using_sysemu, sysemu_supported && value);
+}
+
+int get_using_sysemu(void)
+{
+	return atomic_read(&using_sysemu);
+}
+
+int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data)
+{
+	if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/
+		*eof = 1;
+
+	return strlen(buf);
+}
+
+int proc_write_sysemu(struct file *file,const char *buf, unsigned long count,void *data)
+{
+	char tmp[2];
+
+	if (copy_from_user(tmp, buf, 1))
+		return -EFAULT;
+
+	if (tmp[0] == '0' || tmp[0] == '1')
+		set_using_sysemu(tmp[0] - '0');
+	return count; /*We use the first char, but pretend to write everything*/
+}
+
+int __init make_proc_sysemu(void)
+{
+	struct proc_dir_entry *ent;
+	if (mode_tt || !sysemu_supported)
+		return 0;
+
+	ent = create_proc_entry("sysemu", 0600, &proc_root);
+
+	if (ent == NULL)
+	{
+		printk("Failed to register /proc/sysemu\n");
+		return(0);
+	}
+
+	ent->read_proc  = proc_read_sysemu;
+	ent->write_proc = proc_write_sysemu;
+
+	return 0;
+}
+
+late_initcall(make_proc_sysemu);
 
 int singlestepping_skas(void)
 {
@@ -61,11 +123,13 @@ void new_thread_handler(int sig)
 	thread_wait(&current->thread.mode.skas.switch_buf, 
 		    current->thread.mode.skas.fork_buf);
 
-#ifdef CONFIG_SMP
-	schedule_tail(NULL);
-#endif
+	if(current->thread.prev_sched != NULL)
+		schedule_tail(current->thread.prev_sched);
 	current->thread.prev_sched = NULL;
 
+	/* The return value is 1 if the kernel thread execs a process,
+	 * 0 if it just exits
+	 */
 	n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
 	if(n == 1)
 		userspace(&current->thread.regs.regs);
@@ -93,11 +157,11 @@ void fork_handler(int sig)
 		    current->thread.mode.skas.fork_buf);
   	
 	force_flush_all();
-#ifdef CONFIG_SMP
+	if(current->thread.prev_sched == NULL)
+		panic("blech");
+
 	schedule_tail(current->thread.prev_sched);
-#endif
 	current->thread.prev_sched = NULL;
-	unblock_signals();
 
 	userspace(&current->thread.regs.regs);
 }
@@ -128,15 +192,36 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
 		handler = new_thread_handler;
 	}
 
-	new_thread((void *) p->thread.kernel_stack, 
-		   &p->thread.mode.skas.switch_buf, 
+	new_thread(p->thread_info, &p->thread.mode.skas.switch_buf,
 		   &p->thread.mode.skas.fork_buf, handler);
 	return(0);
 }
 
+int new_mm(int from)
+{
+	struct proc_mm_op copy;
+	int n, fd;
+
+	fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
+	if(fd < 0)
+		return(fd);
+
+	if(from != -1){
+		copy = ((struct proc_mm_op) { .op 	= MM_COPY_SEGMENTS,
+					      .u 	=
+					      { .copy_segments	= from } } );
+		n = os_write_file(fd, &copy, sizeof(copy));
+		if(n != sizeof(copy))
+			printk("new_mm : /proc/mm copy_segments failed, "
+			       "err = %d\n", -n);
+	}
+
+	return(fd);
+}
+
 void init_idle_skas(void)
 {
-	cpu_tasks[current->thread_info->cpu].pid = os_getpid();
+	cpu_tasks[current_thread->cpu].pid = os_getpid();
 	default_idle();
 }
 
@@ -160,27 +245,29 @@ static int start_kernel_proc(void *unused)
 
 int start_uml_skas(void)
 {
-	start_userspace();
+	start_userspace(0);
 	capture_signal_stack();
 
 	init_new_thread_signals(1);
-	idle_timer();
+	uml_idle_timer();
 
 	init_task.thread.request.u.thread.proc = start_kernel_proc;
 	init_task.thread.request.u.thread.arg = NULL;
-	return(start_idle_thread((void *) init_task.thread.kernel_stack,
+	return(start_idle_thread(init_task.thread_info,
 				 &init_task.thread.mode.skas.switch_buf,
 				 &init_task.thread.mode.skas.fork_buf));
 }
 
 int external_pid_skas(struct task_struct *task)
 {
-	return(userspace_pid);
+#warning Need to look up userspace_pid by cpu
+	return(userspace_pid[0]);
 }
 
 int thread_pid_skas(struct task_struct *task)
 {
-	return(userspace_pid);
+#warning Need to look up userspace_pid by cpu
+	return(userspace_pid[0]);
 }
 
 /*
diff --git a/arch/um/kernel/skas/sys-i386/Makefile b/arch/um/kernel/skas/sys-i386/Makefile
index 2ad8271c6..3eeea057c 100644
--- a/arch/um/kernel/skas/sys-i386/Makefile
+++ b/arch/um/kernel/skas/sys-i386/Makefile
@@ -10,5 +10,3 @@ USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
 
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean :
diff --git a/arch/um/kernel/skas/sys-i386/sigcontext.c b/arch/um/kernel/skas/sys-i386/sigcontext.c
index 5f340e102..b015d1960 100644
--- a/arch/um/kernel/skas/sys-i386/sigcontext.c
+++ b/arch/um/kernel/skas/sys-i386/sigcontext.c
@@ -12,10 +12,9 @@
 #include "kern_util.h"
 #include "user.h"
 #include "sigcontext.h"
+#include "mode.h"
 
-extern int userspace_pid;
-
-int copy_sc_from_user_skas(union uml_pt_regs *regs, void *from_ptr)
+int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs, void *from_ptr)
 {
   	struct sigcontext sc, *from = from_ptr;
 	unsigned long fpregs[FP_FRAME_SIZE];
@@ -41,13 +40,12 @@ int copy_sc_from_user_skas(union uml_pt_regs *regs, void *from_ptr)
 	regs->skas.regs[EIP] = sc.eip;
 	regs->skas.regs[CS] = sc.cs;
 	regs->skas.regs[EFL] = sc.eflags;
-	regs->skas.regs[UESP] = sc.esp_at_signal;
 	regs->skas.regs[SS] = sc.ss;
 	regs->skas.fault_addr = sc.cr2;
 	regs->skas.fault_type = FAULT_WRITE(sc.err);
 	regs->skas.trap_type = sc.trapno;
 
-	err = ptrace(PTRACE_SETFPREGS, userspace_pid, 0, fpregs);
+	err = ptrace(PTRACE_SETFPREGS, pid, 0, fpregs);
 	if(err < 0){
 	  	printk("copy_sc_to_user - PTRACE_SETFPREGS failed, "
 		       "errno = %d\n", errno);
@@ -57,8 +55,9 @@ int copy_sc_from_user_skas(union uml_pt_regs *regs, void *from_ptr)
 	return(0);
 }
 
-int copy_sc_to_user_skas(void *to_ptr, void *fp, union uml_pt_regs *regs, 
-			 unsigned long fault_addr, int fault_type)
+int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp,
+			 union uml_pt_regs *regs, unsigned long fault_addr,
+			 int fault_type)
 {
   	struct sigcontext sc, *to = to_ptr;
 	struct _fpstate *to_fp;
@@ -86,7 +85,7 @@ int copy_sc_to_user_skas(void *to_ptr, void *fp, union uml_pt_regs *regs,
 	sc.err = TO_SC_ERR(fault_type);
 	sc.trapno = regs->skas.trap_type;
 
-	err = ptrace(PTRACE_GETFPREGS, userspace_pid, 0, fpregs);
+	err = ptrace(PTRACE_GETFPREGS, pid, 0, fpregs);
 	if(err < 0){
 	  	printk("copy_sc_to_user - PTRACE_GETFPREGS failed, "
 		       "errno = %d\n", errno);
diff --git a/arch/um/kernel/skas/syscall_kern.c b/arch/um/kernel/skas/syscall_kern.c
index bc837a77e..1d7eca5a8 100644
--- a/arch/um/kernel/skas/syscall_kern.c
+++ b/arch/um/kernel/skas/syscall_kern.c
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
diff --git a/arch/um/kernel/skas/syscall_user.c b/arch/um/kernel/skas/syscall_user.c
index caccb772b..34fd5f94e 100644
--- a/arch/um/kernel/skas/syscall_user.c
+++ b/arch/um/kernel/skas/syscall_user.c
@@ -22,7 +22,7 @@ void handle_syscall(union uml_pt_regs *regs)
 
 	index = record_syscall_start(UPT_SYSCALL_NR(regs));
 
-	syscall_trace();
+	syscall_trace(regs, 1);
 	result = execute_syscall(regs);
 
 	REGS_SET_SYSCALL_RETURN(regs->skas.regs, result);
@@ -30,7 +30,7 @@ void handle_syscall(union uml_pt_regs *regs)
 	   (result == -ERESTARTNOINTR))
 		do_signal(result);
 
-	syscall_trace();
+	syscall_trace(regs, 0);
 	record_syscall_end(index, result);
 }
 
diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c
index ed3d6bcd5..02e3e06bb 100644
--- a/arch/um/kernel/skas/tlb.c
+++ b/arch/um/kernel/skas/tlb.c
@@ -77,7 +77,7 @@ void flush_tlb_kernel_range_skas(unsigned long start, unsigned long end)
 	int updated = 0, err;
 
 	mm = &init_mm;
-	for(addr = start_vm; addr < end_vm;){
+	for(addr = start; addr < end;){
 		pgd = pgd_offset(mm, addr);
 		pmd = pmd_offset(pgd, addr);
 		if(pmd_present(*pmd)){
diff --git a/arch/um/kernel/skas/trap_user.c b/arch/um/kernel/skas/trap_user.c
index 0906f65b8..96593709a 100644
--- a/arch/um/kernel/skas/trap_user.c
+++ b/arch/um/kernel/skas/trap_user.c
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -19,8 +19,10 @@ void sig_handler_common_skas(int sig, void *sc_ptr)
 	struct skas_regs *r;
 	struct signal_info *info;
 	int save_errno = errno;
+	int save_user;
 
 	r = &TASK_REGS(get_current())->skas;
+	save_user = r->is_user;
 	r->is_user = 0;
 	r->fault_addr = SC_FAULT_ADDR(sc);
 	r->fault_type = SC_FAULT_TYPE(sc);
@@ -33,16 +35,13 @@ void sig_handler_common_skas(int sig, void *sc_ptr)
 	(*info->handler)(sig, (union uml_pt_regs *) r);
 
 	errno = save_errno;
+	r->is_user = save_user;
 }
 
-extern int missed_ticks[];
-
 void user_signal(int sig, union uml_pt_regs *regs)
 {
 	struct signal_info *info;
 
-	if(sig == SIGVTALRM)
-		missed_ticks[cpu()]++;
 	regs->skas.is_user = 1;
 	regs->skas.fault_addr = 0;
 	regs->skas.fault_type = 0;
diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
index ea82f19b2..77048cd67 100644
--- a/arch/um/kernel/skas/uaccess.c
+++ b/arch/um/kernel/skas/uaccess.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
@@ -12,8 +12,9 @@
 #include "asm/pgtable.h"
 #include "asm/uaccess.h"
 #include "kern_util.h"
+#include "user_util.h"
 
-extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr, 
+extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
 			     pte_t *pte_out);
 
 static unsigned long maybe_map(unsigned long virt, int is_write)
@@ -25,7 +26,7 @@ static unsigned long maybe_map(unsigned long virt, int is_write)
 	int dummy_code;
 
 	if(IS_ERR(phys) || (is_write && !pte_write(pte))){
-		err = handle_page_fault(virt, 0, is_write, 0, &dummy_code);
+		err = handle_page_fault(virt, 0, is_write, 1, &dummy_code);
 		if(err)
 			return(0);
 		phys = um_virt_to_phys(current, virt, NULL);
@@ -33,7 +34,7 @@ static unsigned long maybe_map(unsigned long virt, int is_write)
 	return((unsigned long) phys);
 }
 
-static int do_op(unsigned long addr, int len, int is_write, 
+static int do_op(unsigned long addr, int len, int is_write,
 		 int (*op)(unsigned long addr, int len, void *arg), void *arg)
 {
 	struct page *page;
@@ -51,37 +52,67 @@ static int do_op(unsigned long addr, int len, int is_write,
 	return(n);
 }
 
-static int buffer_op(unsigned long addr, int len, int is_write,
-		     int (*op)(unsigned long addr, int len, void *arg),
-		     void *arg)
+static void do_buffer_op(void *jmpbuf, void *arg_ptr)
 {
+	va_list args = *((va_list *) arg_ptr);
+	unsigned long addr = va_arg(args, unsigned long);
+	int len = va_arg(args, int);
+	int is_write = va_arg(args, int);
+	int (*op)(unsigned long, int, void *) = va_arg(args, void *);
+	void *arg = va_arg(args, void *);
+	int *res = va_arg(args, int *);
 	int size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len);
 	int remain = len, n;
 
+	current->thread.fault_catcher = jmpbuf;
 	n = do_op(addr, size, is_write, op, arg);
-	if(n != 0)
-		return(n < 0 ? remain : 0);
+	if(n != 0){
+		*res = (n < 0 ? remain : 0);
+		goto out;
+	}
 
 	addr += size;
 	remain -= size;
-	if(remain == 0) 
-		return(0);
+	if(remain == 0){
+		*res = 0;
+		goto out;
+	}
 
 	while(addr < ((addr + remain) & PAGE_MASK)){
 		n = do_op(addr, PAGE_SIZE, is_write, op, arg);
-		if(n != 0)
-			return(n < 0 ? remain : 0);
+		if(n != 0){
+			*res = (n < 0 ? remain : 0);
+			goto out;
+		}
 
 		addr += PAGE_SIZE;
 		remain -= PAGE_SIZE;
 	}
-	if(remain == 0)
-		return(0);
+	if(remain == 0){
+		*res = 0;
+		goto out;
+	}
 
 	n = do_op(addr, remain, is_write, op, arg);
 	if(n != 0)
-		return(n < 0 ? remain : 0);
-	return(0);
+		*res = (n < 0 ? remain : 0);
+	else *res = 0;
+ out:
+	current->thread.fault_catcher = NULL;
+}
+
+static int buffer_op(unsigned long addr, int len, int is_write,
+		     int (*op)(unsigned long addr, int len, void *arg),
+		     void *arg)
+{
+	int faulted, res;
+
+	faulted = setjmp_wrapper(do_buffer_op, addr, len, is_write, op, arg,
+				 &res);
+	if(!faulted)
+		return(res);
+
+	return(addr + len - (unsigned long) current->thread.fault_addr);
 }
 
 static int copy_chunk_from_user(unsigned long from, int len, void *arg)
@@ -135,7 +166,7 @@ static int strncpy_chunk_from_user(unsigned long from, int len, void *arg)
 	n = strnlen(to, len);
 	*to_ptr += n;
 
-	if(n < len) 
+	if(n < len)
 	        return(1);
 	return(0);
 }
@@ -153,7 +184,7 @@ int strncpy_from_user_skas(char *dst, const char *src, int count)
 	if(!access_ok_skas(VERIFY_READ, src, 1))
 		return(-EFAULT);
 
-	n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, 
+	n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user,
 		      &ptr);
 	if(n != 0)
 		return(-EFAULT);
@@ -178,7 +209,7 @@ int clear_user_skas(void *mem, int len)
 		return(0);
 	}
 
-	return(access_ok_skas(VERIFY_WRITE, mem, len) ? 
+	return(access_ok_skas(VERIFY_WRITE, mem, len) ?
 	       buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len);
 }
 
diff --git a/arch/um/kernel/skas/util/Makefile b/arch/um/kernel/skas/util/Makefile
index e62dc253e..a26e0c34a 100644
--- a/arch/um/kernel/skas/util/Makefile
+++ b/arch/um/kernel/skas/util/Makefile
@@ -1,10 +1,2 @@
-all: mk_ptregs
-
-mk_ptregs : mk_ptregs.o
-	$(CC) -o mk_ptregs mk_ptregs.o
-
-mk_ptregs.o : mk_ptregs.c
-	$(CC) -c $< 
-
-clean : 
-	$(RM) -f mk_ptregs *.o *~
+hostprogs-y		:= mk_ptregs
+always			:= $(hostprogs-y)
diff --git a/arch/um/kernel/skas/util/mk_ptregs.c b/arch/um/kernel/skas/util/mk_ptregs.c
index 658791017..116f74d2c 100644
--- a/arch/um/kernel/skas/util/mk_ptregs.c
+++ b/arch/um/kernel/skas/util/mk_ptregs.c
@@ -1,3 +1,4 @@
+#include <stdio.h>
 #include <asm/ptrace.h>
 #include <asm/user.h>
 
diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c
index b8158556c..b5e66b291 100644
--- a/arch/um/kernel/smp.c
+++ b/arch/um/kernel/smp.c
@@ -1,9 +1,15 @@
 /* 
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
 #include "linux/config.h"
+#include "linux/percpu.h"
+#include "asm/pgalloc.h"
+#include "asm/tlb.h"
+
+/* For some reason, mmu_gathers are referenced when CONFIG_SMP is off. */
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
 #ifdef CONFIG_SMP
 
@@ -12,10 +18,10 @@
 #include "linux/threads.h"
 #include "linux/interrupt.h"
 #include "linux/err.h"
+#include "linux/hardirq.h"
 #include "asm/smp.h"
 #include "asm/processor.h"
 #include "asm/spinlock.h"
-#include "asm/hardirq.h"
 #include "user_util.h"
 #include "kern_util.h"
 #include "kern.h"
@@ -23,9 +29,11 @@
 #include "os.h"
 
 /* CPU online map, set by smp_boot_cpus */
-unsigned long cpu_online_map = cpumask_of_cpu(0);
+cpumask_t cpu_online_map = CPU_MASK_NONE;
+cpumask_t cpu_possible_map = CPU_MASK_NONE;
 
 EXPORT_SYMBOL(cpu_online_map);
+EXPORT_SYMBOL(cpu_possible_map);
 
 /* Per CPU bogomips and other parameters
  * The only piece used here is the ipi pipe, which is set before SMP is
@@ -33,14 +41,6 @@ EXPORT_SYMBOL(cpu_online_map);
  */
 struct cpuinfo_um cpu_data[NR_CPUS];
 
-spinlock_t um_bh_lock = SPIN_LOCK_UNLOCKED;
-
-atomic_t global_bh_count;
-
-/* Not used by UML */
-unsigned char global_irq_holder = NO_PROC_ID;
-unsigned volatile long global_irq_lock;
-
 /* Set when the idlers are all forked */
 int smp_threads_ready = 0;
 
@@ -55,80 +55,44 @@ struct task_struct *idle_threads[NR_CPUS];
 
 void smp_send_reschedule(int cpu)
 {
-	write(cpu_data[cpu].ipi_pipe[1], "R", 1);
+	os_write_file(cpu_data[cpu].ipi_pipe[1], "R", 1);
 	num_reschedules_sent++;
 }
 
-static void show(char * str)
-{
-	int cpu = smp_processor_id();
-
-	printk(KERN_INFO "\n%s, CPU %d:\n", str, cpu);
-}
-	
-#define MAXCOUNT 100000000
-
-static inline void wait_on_bh(void)
-{
-	int count = MAXCOUNT;
-	do {
-		if (!--count) {
-			show("wait_on_bh");
-			count = ~0;
-		}
-		/* nothing .. wait for the other bh's to go away */
-	} while (atomic_read(&global_bh_count) != 0);
-}
-
-/*
- * This is called when we want to synchronize with
- * bottom half handlers. We need to wait until
- * no other CPU is executing any bottom half handler.
- *
- * Don't wait if we're already running in an interrupt
- * context or are inside a bh handler. 
- */
-void synchronize_bh(void)
-{
-	if (atomic_read(&global_bh_count) && !in_interrupt())
-		wait_on_bh();
-}
-
 void smp_send_stop(void)
 {
 	int i;
 
 	printk(KERN_INFO "Stopping all CPUs...");
 	for(i = 0; i < num_online_cpus(); i++){
-		if(i == current->thread_info->cpu)
+		if(i == current_thread->cpu)
 			continue;
-		write(cpu_data[i].ipi_pipe[1], "S", 1);
+		os_write_file(cpu_data[i].ipi_pipe[1], "S", 1);
 	}
 	printk("done\n");
 }
 
-static cpumask_t smp_commenced_mask;
-static cpumask_t smp_callin_map = CPU_MASK_NONE;
+static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
+static cpumask_t cpu_callin_map = CPU_MASK_NONE;
 
 static int idle_proc(void *cpup)
 {
 	int cpu = (int) cpup, err;
 
 	err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1);
-	if(err)
-		panic("CPU#%d failed to create IPI pipe, errno = %d", cpu, 
-		      -err);
+	if(err < 0)
+		panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err);
 
 	activate_ipi(cpu_data[cpu].ipi_pipe[0], 
 		     current->thread.mode.tt.extern_pid);
  
 	wmb();
-	if (cpu_test_and_set(cpu, &smp_callin_map)) {
+	if (cpu_test_and_set(cpu, cpu_callin_map)) {
 		printk("huh, CPU#%d already present??\n", cpu);
 		BUG();
 	}
 
-	while (!cpu_isset(cpu, &smp_commenced_mask))
+	while (!cpu_isset(cpu, smp_commenced_mask))
 		cpu_relax();
 
 	cpu_set(cpu, cpu_online_map);
@@ -143,14 +107,16 @@ static struct task_struct *idle_thread(int cpu)
 
         current->thread.request.u.thread.proc = idle_proc;
         current->thread.request.u.thread.arg = (void *) cpu;
-	new_task = do_fork(CLONE_VM | CLONE_IDLETASK, 0, NULL, 0, NULL, NULL);
-	if(IS_ERR(new_task)) panic("do_fork failed in idle_thread");
+	new_task = fork_idle(cpu);
+	if(IS_ERR(new_task))
+		panic("copy_process failed in idle_thread, error = %ld",
+		      PTR_ERR(new_task));
 
 	cpu_tasks[cpu] = ((struct cpu_task) 
 		          { .pid = 	new_task->thread.mode.tt.extern_pid,
 			    .task = 	new_task } );
 	idle_threads[cpu] = new_task;
-	CHOOSE_MODE(write(new_task->thread.mode.tt.switch_pipe[1], &c, 
+	CHOOSE_MODE(os_write_file(new_task->thread.mode.tt.switch_pipe[1], &c,
 			  sizeof(c)),
 		    ({ panic("skas mode doesn't support SMP"); }));
 	return(new_task);
@@ -160,15 +126,21 @@ void smp_prepare_cpus(unsigned int maxcpus)
 {
 	struct task_struct *idle;
 	unsigned long waittime;
-	int err, cpu;
+	int err, cpu, me = smp_processor_id();
+	int i;
+
+	for (i = 0; i < ncpus; ++i)
+		cpu_set(i, cpu_possible_map);
 
-	cpu_set(0, cpu_online_map);
-	cpu_set(0, smp_callin_map);
+	cpu_clear(me, cpu_online_map);
+	cpu_set(me, cpu_online_map);
+	cpu_set(me, cpu_callin_map);
 
-	err = os_pipe(cpu_data[0].ipi_pipe, 1, 1);
-	if(err)	panic("CPU#0 failed to create IPI pipe, errno = %d", -err);
+	err = os_pipe(cpu_data[me].ipi_pipe, 1, 1);
+	if(err < 0)
+		panic("CPU#0 failed to create IPI pipe, errno = %d", -err);
 
-	activate_ipi(cpu_data[0].ipi_pipe[0], 
+	activate_ipi(cpu_data[me].ipi_pipe[0],
 		     current->thread.mode.tt.extern_pid);
 
 	for(cpu = 1; cpu < ncpus; cpu++){
@@ -180,10 +152,10 @@ void smp_prepare_cpus(unsigned int maxcpus)
 		unhash_process(idle);
 
 		waittime = 200000000;
-		while (waittime-- && !cpu_isset(cpu, smp_callin_map))
+		while (waittime-- && !cpu_isset(cpu, cpu_callin_map))
 			cpu_relax();
 
-		if (cpu_isset(cpu, smp_callin_map))
+		if (cpu_isset(cpu, cpu_callin_map))
 			printk("done\n");
 		else printk("failed\n");
 	}
@@ -216,7 +188,7 @@ void IPI_handler(int cpu)
 	int fd;
 
 	fd = cpu_data[cpu].ipi_pipe[0];
-	while (read(fd, &c, 1) == 1) {
+	while (os_read_file(fd, &c, 1) == 1) {
 		switch (c) {
 		case 'C':
 			smp_call_function_slave(cpu);
@@ -276,9 +248,9 @@ int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic,
 	info = _info;
 
 	for (i=0;i<NR_CPUS;i++)
-		if((i != current->thread_info->cpu) && 
+		if((i != current_thread->cpu) &&
 		   cpu_isset(i, cpu_online_map))
-			write(cpu_data[i].ipi_pipe[1], "C", 1);
+			os_write_file(cpu_data[i].ipi_pipe[1], "C", 1);
 
 	while (atomic_read(&scf_started) != cpus)
 		barrier();
diff --git a/arch/um/kernel/sys_call_table.c b/arch/um/kernel/sys_call_table.c
index 3948719dc..f1ad68ecc 100644
--- a/arch/um/kernel/sys_call_table.c
+++ b/arch/um/kernel/sys_call_table.c
@@ -5,7 +5,6 @@
 
 #include "linux/config.h"
 #include "linux/unistd.h"
-#include "linux/version.h"
 #include "linux/sys.h"
 #include "linux/swap.h"
 #include "linux/syscalls.h"
@@ -14,253 +13,50 @@
 #include "sysdep/syscalls.h"
 #include "kern_util.h"
 
-extern syscall_handler_t sys_restart_syscall;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_exit;
+#ifdef CONFIG_NFSD
+#define NFSSERVCTL sys_nfsservctl
+#else
+#define NFSSERVCTL sys_ni_syscall
+#endif
+
+#define LAST_GENERIC_SYSCALL __NR_vserver
+
+#if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL
+#define LAST_SYSCALL LAST_GENERIC_SYSCALL
+#else
+#define LAST_SYSCALL LAST_ARCH_SYSCALL
+#endif
+
 extern syscall_handler_t sys_fork;
-extern syscall_handler_t sys_creat;
-extern syscall_handler_t sys_link;
-extern syscall_handler_t sys_unlink;
-extern syscall_handler_t sys_chdir;
-extern syscall_handler_t sys_mknod;
-extern syscall_handler_t sys_chmod;
-extern syscall_handler_t sys_lchown16;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_stat;
-extern syscall_handler_t sys_getpid;
-extern syscall_handler_t sys_oldumount;
-extern syscall_handler_t sys_setuid16;
-extern syscall_handler_t sys_getuid16;
+extern syscall_handler_t sys_execve;
+extern syscall_handler_t um_time;
+extern syscall_handler_t um_mount;
+extern syscall_handler_t um_stime;
 extern syscall_handler_t sys_ptrace;
-extern syscall_handler_t sys_alarm;
-extern syscall_handler_t sys_fstat;
-extern syscall_handler_t sys_pause;
-extern syscall_handler_t sys_utime;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_access;
-extern syscall_handler_t sys_nice;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_sync;
-extern syscall_handler_t sys_kill;
-extern syscall_handler_t sys_rename;
-extern syscall_handler_t sys_mkdir;
-extern syscall_handler_t sys_rmdir;
 extern syscall_handler_t sys_pipe;
-extern syscall_handler_t sys_times;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_brk;
-extern syscall_handler_t sys_setgid16;
-extern syscall_handler_t sys_getgid16;
-extern syscall_handler_t sys_signal;
-extern syscall_handler_t sys_geteuid16;
-extern syscall_handler_t sys_getegid16;
-extern syscall_handler_t sys_acct;
-extern syscall_handler_t sys_umount;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_ioctl;
-extern syscall_handler_t sys_fcntl;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_setpgid;
-extern syscall_handler_t sys_ni_syscall;
 extern syscall_handler_t sys_olduname;
-extern syscall_handler_t sys_umask;
-extern syscall_handler_t sys_chroot;
-extern syscall_handler_t sys_ustat;
-extern syscall_handler_t sys_dup2;
-extern syscall_handler_t sys_getppid;
-extern syscall_handler_t sys_getpgrp;
 extern syscall_handler_t sys_sigaction;
-extern syscall_handler_t sys_sgetmask;
-extern syscall_handler_t sys_ssetmask;
-extern syscall_handler_t sys_setreuid16;
-extern syscall_handler_t sys_setregid16;
 extern syscall_handler_t sys_sigsuspend;
-extern syscall_handler_t sys_sigpending;
-extern syscall_handler_t sys_sethostname;
-extern syscall_handler_t sys_setrlimit;
-extern syscall_handler_t sys_old_getrlimit;
-extern syscall_handler_t sys_getrusage;
-extern syscall_handler_t sys_gettimeofday;
-extern syscall_handler_t sys_settimeofday;
-extern syscall_handler_t sys_getgroups16;
-extern syscall_handler_t sys_setgroups16;
-extern syscall_handler_t sys_symlink;
-extern syscall_handler_t sys_lstat;
-extern syscall_handler_t sys_readlink;
-extern syscall_handler_t sys_swapon;
-extern syscall_handler_t sys_uselib;
-extern syscall_handler_t sys_reboot;
 extern syscall_handler_t old_readdir;
-extern syscall_handler_t sys_munmap;
-extern syscall_handler_t sys_truncate;
-extern syscall_handler_t sys_ftruncate;
-extern syscall_handler_t sys_fchmod;
-extern syscall_handler_t sys_fchown16;
-extern syscall_handler_t sys_getpriority;
-extern syscall_handler_t sys_setpriority;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_statfs;
-extern syscall_handler_t sys_fstatfs;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_socketcall;
-extern syscall_handler_t sys_syslog;
-extern syscall_handler_t sys_setitimer;
-extern syscall_handler_t sys_getitimer;
-extern syscall_handler_t sys_newstat;
-extern syscall_handler_t sys_newlstat;
-extern syscall_handler_t sys_newfstat;
 extern syscall_handler_t sys_uname;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_vhangup;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_swapoff;
-extern syscall_handler_t sys_sysinfo;
 extern syscall_handler_t sys_ipc;
-extern syscall_handler_t sys_fsync;
 extern syscall_handler_t sys_sigreturn;
-extern syscall_handler_t sys_rt_sigreturn;
 extern syscall_handler_t sys_clone;
-extern syscall_handler_t sys_setdomainname;
-extern syscall_handler_t sys_newuname;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_adjtimex;
-extern syscall_handler_t sys_mprotect;
-extern syscall_handler_t sys_sigprocmask;
-extern syscall_handler_t sys_init_module;
-extern syscall_handler_t sys_delete_module;
-extern syscall_handler_t sys_quotactl;
-extern syscall_handler_t sys_getpgid;
-extern syscall_handler_t sys_fchdir;
-extern syscall_handler_t sys_bdflush;
-extern syscall_handler_t sys_sysfs;
-extern syscall_handler_t sys_personality;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_setfsuid16;
-extern syscall_handler_t sys_setfsgid16;
-extern syscall_handler_t sys_llseek;
-extern syscall_handler_t sys_getdents;
-extern syscall_handler_t sys_flock;
-extern syscall_handler_t sys_msync;
-extern syscall_handler_t sys_readv;
-extern syscall_handler_t sys_writev;
-extern syscall_handler_t sys_getsid;
-extern syscall_handler_t sys_fdatasync;
-extern syscall_handler_t sys_mlock;
-extern syscall_handler_t sys_munlock;
-extern syscall_handler_t sys_mlockall;
-extern syscall_handler_t sys_munlockall;
-extern syscall_handler_t sys_sched_setparam;
-extern syscall_handler_t sys_sched_getparam;
-extern syscall_handler_t sys_sched_setscheduler;
-extern syscall_handler_t sys_sched_getscheduler;
-extern syscall_handler_t sys_sched_get_priority_max;
-extern syscall_handler_t sys_sched_get_priority_min;
-extern syscall_handler_t sys_sched_rr_get_interval;
-extern syscall_handler_t sys_nanosleep;
-extern syscall_handler_t sys_mremap;
-extern syscall_handler_t sys_setresuid16;
-extern syscall_handler_t sys_getresuid16;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_poll;
-extern syscall_handler_t sys_nfsservctl;
-extern syscall_handler_t sys_setresgid16;
-extern syscall_handler_t sys_getresgid16;
-extern syscall_handler_t sys_prctl;
-extern syscall_handler_t sys_ni_syscall;
+extern syscall_handler_t sys_rt_sigreturn;
 extern syscall_handler_t sys_rt_sigaction;
-extern syscall_handler_t sys_rt_sigprocmask;
-extern syscall_handler_t sys_rt_sigpending;
-extern syscall_handler_t sys_rt_sigtimedwait;
-extern syscall_handler_t sys_rt_sigqueueinfo;
-extern syscall_handler_t sys_rt_sigsuspend;
-extern syscall_handler_t sys_pread64;
-extern syscall_handler_t sys_pwrite64;
-extern syscall_handler_t sys_chown16;
-extern syscall_handler_t sys_getcwd;
-extern syscall_handler_t sys_capget;
-extern syscall_handler_t sys_capset;
 extern syscall_handler_t sys_sigaltstack;
-extern syscall_handler_t sys_sendfile;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_ni_syscall;
 extern syscall_handler_t sys_vfork;
-extern syscall_handler_t sys_getrlimit;
 extern syscall_handler_t sys_mmap2;
-extern syscall_handler_t sys_truncate64;
-extern syscall_handler_t sys_ftruncate64;
-extern syscall_handler_t sys_stat64;
-extern syscall_handler_t sys_lstat64;
-extern syscall_handler_t sys_fstat64;
-extern syscall_handler_t sys_lchown;
-extern syscall_handler_t sys_getuid;
-extern syscall_handler_t sys_getgid;
-extern syscall_handler_t sys_geteuid;
-extern syscall_handler_t sys_getegid;
-extern syscall_handler_t sys_setreuid;
-extern syscall_handler_t sys_setregid;
-extern syscall_handler_t sys_getgroups;
-extern syscall_handler_t sys_setgroups;
-extern syscall_handler_t sys_fchown;
-extern syscall_handler_t sys_setresuid;
-extern syscall_handler_t sys_getresuid;
-extern syscall_handler_t sys_setresgid;
-extern syscall_handler_t sys_getresgid;
-extern syscall_handler_t sys_chown;
-extern syscall_handler_t sys_setuid;
-extern syscall_handler_t sys_setgid;
-extern syscall_handler_t sys_setfsuid;
-extern syscall_handler_t sys_setfsgid;
-extern syscall_handler_t sys_pivot_root;
-extern syscall_handler_t sys_mincore;
-extern syscall_handler_t sys_madvise;
-extern syscall_handler_t sys_fcntl64;
-extern syscall_handler_t sys_getdents64;
-extern syscall_handler_t sys_gettid;
-extern syscall_handler_t sys_readahead;
-extern syscall_handler_t sys_tkill;
-extern syscall_handler_t sys_sendfile64;
-extern syscall_handler_t sys_futex;
-extern syscall_handler_t sys_sched_setaffinity;
-extern syscall_handler_t sys_sched_getaffinity;
-extern syscall_handler_t sys_io_setup;
-extern syscall_handler_t sys_io_destroy;
-extern syscall_handler_t sys_io_getevents;
-extern syscall_handler_t sys_io_submit;
-extern syscall_handler_t sys_io_cancel;
-extern syscall_handler_t sys_exit_group;
-extern syscall_handler_t sys_lookup_dcookie;
-extern syscall_handler_t sys_epoll_create;
-extern syscall_handler_t sys_epoll_ctl;
-extern syscall_handler_t sys_epoll_wait;
-extern syscall_handler_t sys_remap_file_pages;
-extern syscall_handler_t sys_set_tid_address;
-
+extern syscall_handler_t old_mmap_i386;
+extern syscall_handler_t old_select;
+extern syscall_handler_t sys_modify_ldt;
+extern syscall_handler_t sys_rt_sigsuspend;
 extern syscall_handler_t sys_vserver;
 
-#ifdef CONFIG_NFSD
-#define NFSSERVCTL sys_nfsservctl
-#else
-#define NFSSERVCTL sys_ni_syscall
-#endif
-
-extern syscall_handler_t um_mount;
-extern syscall_handler_t um_time;
-extern syscall_handler_t um_stime;
-
-#define LAST_GENERIC_SYSCALL __NR_set_tid_address
-
-#if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL
-#define LAST_SYSCALL LAST_GENERIC_SYSCALL
-#else
-#define LAST_SYSCALL LAST_ARCH_SYSCALL
-#endif
-
 syscall_handler_t *sys_call_table[] = {
-	[ __NR_restart_syscall ] = sys_restart_syscall,
-	[ __NR_exit ] = sys_exit,
-	[ __NR_fork ] = sys_fork,
+	[ __NR_restart_syscall ] = (syscall_handler_t *) sys_restart_syscall,
+	[ __NR_exit ] (syscall_handler_t *) sys_exit,
+	[ __NR_fork ] (syscall_handler_t *) sys_fork,
 	[ __NR_read ] = (syscall_handler_t *) sys_read,
 	[ __NR_write ] = (syscall_handler_t *) sys_write,
 
@@ -268,230 +64,249 @@ syscall_handler_t *sys_call_table[] = {
 	[ __NR_open ] = (syscall_handler_t *) sys_open,
 	[ __NR_close ] = (syscall_handler_t *) sys_close,
 	[ __NR_waitpid ] = (syscall_handler_t *) sys_waitpid,
-	[ __NR_creat ] = sys_creat,
-	[ __NR_link ] = sys_link,
-	[ __NR_unlink ] = sys_unlink,
+	[ __NR_creat ] (syscall_handler_t *) sys_creat,
+	[ __NR_link ] (syscall_handler_t *) sys_link,
+	[ __NR_unlink ] (syscall_handler_t *) sys_unlink,
 	[ __NR_execve ] = (syscall_handler_t *) sys_execve,
 
 	/* declared differently in kern_util.h */
-	[ __NR_chdir ] = sys_chdir,
+	[ __NR_chdir ] (syscall_handler_t *) sys_chdir,
 	[ __NR_time ] = um_time,
-	[ __NR_mknod ] = sys_mknod,
-	[ __NR_chmod ] = sys_chmod,
-	[ __NR_lchown ] = sys_lchown16,
-	[ __NR_break ] = sys_ni_syscall,
-	[ __NR_oldstat ] = sys_stat,
+	[ __NR_mknod ] (syscall_handler_t *) sys_mknod,
+	[ __NR_chmod ] (syscall_handler_t *) sys_chmod,
+	[ __NR_lchown ] (syscall_handler_t *) sys_lchown16,
+	[ __NR_break ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_oldstat ] (syscall_handler_t *) sys_stat,
 	[ __NR_lseek ] = (syscall_handler_t *) sys_lseek,
-	[ __NR_getpid ] = sys_getpid,
+	[ __NR_getpid ] (syscall_handler_t *) sys_getpid,
 	[ __NR_mount ] = um_mount,
-	[ __NR_umount ] = sys_oldumount,
-	[ __NR_setuid ] = sys_setuid16,
-	[ __NR_getuid ] = sys_getuid16,
+	[ __NR_umount ] (syscall_handler_t *) sys_oldumount,
+	[ __NR_setuid ] (syscall_handler_t *) sys_setuid16,
+	[ __NR_getuid ] (syscall_handler_t *) sys_getuid16,
 	[ __NR_stime ] = um_stime,
-	[ __NR_ptrace ] = sys_ptrace,
-	[ __NR_alarm ] = sys_alarm,
-	[ __NR_oldfstat ] = sys_fstat,
-	[ __NR_pause ] = sys_pause,
-	[ __NR_utime ] = sys_utime,
-	[ __NR_stty ] = sys_ni_syscall,
-	[ __NR_gtty ] = sys_ni_syscall,
-	[ __NR_access ] = sys_access,
-	[ __NR_nice ] = sys_nice,
-	[ __NR_ftime ] = sys_ni_syscall,
-	[ __NR_sync ] = sys_sync,
-	[ __NR_kill ] = sys_kill,
-	[ __NR_rename ] = sys_rename,
-	[ __NR_mkdir ] = sys_mkdir,
-	[ __NR_rmdir ] = sys_rmdir,
+	[ __NR_ptrace ] (syscall_handler_t *) sys_ptrace,
+	[ __NR_alarm ] (syscall_handler_t *) sys_alarm,
+	[ __NR_oldfstat ] (syscall_handler_t *) sys_fstat,
+	[ __NR_pause ] (syscall_handler_t *) sys_pause,
+	[ __NR_utime ] (syscall_handler_t *) sys_utime,
+	[ __NR_stty ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_gtty ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_access ] (syscall_handler_t *) sys_access,
+	[ __NR_nice ] (syscall_handler_t *) sys_nice,
+	[ __NR_ftime ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_sync ] (syscall_handler_t *) sys_sync,
+	[ __NR_kill ] (syscall_handler_t *) sys_kill,
+	[ __NR_rename ] (syscall_handler_t *) sys_rename,
+	[ __NR_mkdir ] (syscall_handler_t *) sys_mkdir,
+	[ __NR_rmdir ] (syscall_handler_t *) sys_rmdir,
 
 	/* Declared differently in asm/unistd.h */
 	[ __NR_dup ] = (syscall_handler_t *) sys_dup,
-	[ __NR_pipe ] = sys_pipe,
-	[ __NR_times ] = sys_times,
-	[ __NR_prof ] = sys_ni_syscall,
-	[ __NR_brk ] = sys_brk,
-	[ __NR_setgid ] = sys_setgid16,
-	[ __NR_getgid ] = sys_getgid16,
-	[ __NR_signal ] = sys_signal,
-	[ __NR_geteuid ] = sys_geteuid16,
-	[ __NR_getegid ] = sys_getegid16,
-	[ __NR_acct ] = sys_acct,
-	[ __NR_umount2 ] = sys_umount,
-	[ __NR_lock ] = sys_ni_syscall,
-	[ __NR_ioctl ] = sys_ioctl,
-	[ __NR_fcntl ] = sys_fcntl,
-	[ __NR_mpx ] = sys_ni_syscall,
-	[ __NR_setpgid ] = sys_setpgid,
-	[ __NR_ulimit ] = sys_ni_syscall,
-	[ __NR_oldolduname ] = sys_olduname,
-	[ __NR_umask ] = sys_umask,
-	[ __NR_chroot ] = sys_chroot,
-	[ __NR_ustat ] = sys_ustat,
-	[ __NR_dup2 ] = sys_dup2,
-	[ __NR_getppid ] = sys_getppid,
-	[ __NR_getpgrp ] = sys_getpgrp,
+	[ __NR_pipe ] (syscall_handler_t *) sys_pipe,
+	[ __NR_times ] (syscall_handler_t *) sys_times,
+	[ __NR_prof ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_brk ] (syscall_handler_t *) sys_brk,
+	[ __NR_setgid ] (syscall_handler_t *) sys_setgid16,
+	[ __NR_getgid ] (syscall_handler_t *) sys_getgid16,
+	[ __NR_signal ] (syscall_handler_t *) sys_signal,
+	[ __NR_geteuid ] (syscall_handler_t *) sys_geteuid16,
+	[ __NR_getegid ] (syscall_handler_t *) sys_getegid16,
+	[ __NR_acct ] (syscall_handler_t *) sys_acct,
+	[ __NR_umount2 ] (syscall_handler_t *) sys_umount,
+	[ __NR_lock ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_ioctl ] (syscall_handler_t *) sys_ioctl,
+	[ __NR_fcntl ] (syscall_handler_t *) sys_fcntl,
+	[ __NR_mpx ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_setpgid ] (syscall_handler_t *) sys_setpgid,
+	[ __NR_ulimit ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_oldolduname ] (syscall_handler_t *) sys_olduname,
+	[ __NR_umask ] (syscall_handler_t *) sys_umask,
+	[ __NR_chroot ] (syscall_handler_t *) sys_chroot,
+	[ __NR_ustat ] (syscall_handler_t *) sys_ustat,
+	[ __NR_dup2 ] (syscall_handler_t *) sys_dup2,
+	[ __NR_getppid ] (syscall_handler_t *) sys_getppid,
+	[ __NR_getpgrp ] (syscall_handler_t *) sys_getpgrp,
 	[ __NR_setsid ] = (syscall_handler_t *) sys_setsid,
-	[ __NR_sigaction ] = sys_sigaction,
-	[ __NR_sgetmask ] = sys_sgetmask,
-	[ __NR_ssetmask ] = sys_ssetmask,
-	[ __NR_setreuid ] = sys_setreuid16,
-	[ __NR_setregid ] = sys_setregid16,
-	[ __NR_sigsuspend ] = sys_sigsuspend,
-	[ __NR_sigpending ] = sys_sigpending,
-	[ __NR_sethostname ] = sys_sethostname,
-	[ __NR_setrlimit ] = sys_setrlimit,
-	[ __NR_getrlimit ] = sys_old_getrlimit,
-	[ __NR_getrusage ] = sys_getrusage,
-	[ __NR_gettimeofday ] = sys_gettimeofday,
-	[ __NR_settimeofday ] = sys_settimeofday,
-	[ __NR_getgroups ] = sys_getgroups16,
-	[ __NR_setgroups ] = sys_setgroups16,
-	[ __NR_symlink ] = sys_symlink,
-	[ __NR_oldlstat ] = sys_lstat,
-	[ __NR_readlink ] = sys_readlink,
-	[ __NR_uselib ] = sys_uselib,
+	[ __NR_sigaction ] (syscall_handler_t *) sys_sigaction,
+	[ __NR_sgetmask ] (syscall_handler_t *) sys_sgetmask,
+	[ __NR_ssetmask ] (syscall_handler_t *) sys_ssetmask,
+	[ __NR_setreuid ] (syscall_handler_t *) sys_setreuid16,
+	[ __NR_setregid ] (syscall_handler_t *) sys_setregid16,
+	[ __NR_sigsuspend ] (syscall_handler_t *) sys_sigsuspend,
+	[ __NR_sigpending ] (syscall_handler_t *) sys_sigpending,
+	[ __NR_sethostname ] (syscall_handler_t *) sys_sethostname,
+	[ __NR_setrlimit ] (syscall_handler_t *) sys_setrlimit,
+	[ __NR_getrlimit ] (syscall_handler_t *) sys_old_getrlimit,
+	[ __NR_getrusage ] (syscall_handler_t *) sys_getrusage,
+	[ __NR_gettimeofday ] (syscall_handler_t *) sys_gettimeofday,
+	[ __NR_settimeofday ] (syscall_handler_t *) sys_settimeofday,
+	[ __NR_getgroups ] (syscall_handler_t *) sys_getgroups16,
+	[ __NR_setgroups ] (syscall_handler_t *) sys_setgroups16,
+	[ __NR_symlink ] (syscall_handler_t *) sys_symlink,
+	[ __NR_oldlstat ] (syscall_handler_t *) sys_lstat,
+	[ __NR_readlink ] (syscall_handler_t *) sys_readlink,
+	[ __NR_uselib ] (syscall_handler_t *) sys_uselib,
 	[ __NR_swapon ] = (syscall_handler_t *) sys_swapon,
-	[ __NR_reboot ] = sys_reboot,
+	[ __NR_reboot ] (syscall_handler_t *) sys_reboot,
 	[ __NR_readdir ] = old_readdir,
-	[ __NR_munmap ] = sys_munmap,
-	[ __NR_truncate ] = sys_truncate,
-	[ __NR_ftruncate ] = sys_ftruncate,
-	[ __NR_fchmod ] = sys_fchmod,
-	[ __NR_fchown ] = sys_fchown16,
-	[ __NR_getpriority ] = sys_getpriority,
-	[ __NR_setpriority ] = sys_setpriority,
-	[ __NR_profil ] = sys_ni_syscall,
-	[ __NR_statfs ] = sys_statfs,
-	[ __NR_fstatfs ] = sys_fstatfs,
-	[ __NR_ioperm ] = sys_ni_syscall,
-	[ __NR_socketcall ] = sys_socketcall,
-	[ __NR_syslog ] = sys_syslog,
-	[ __NR_setitimer ] = sys_setitimer,
-	[ __NR_getitimer ] = sys_getitimer,
-	[ __NR_stat ] = sys_newstat,
-	[ __NR_lstat ] = sys_newlstat,
-	[ __NR_fstat ] = sys_newfstat,
-	[ __NR_olduname ] = sys_uname,
-	[ __NR_iopl ] = sys_ni_syscall,
-	[ __NR_vhangup ] = sys_vhangup,
-	[ __NR_idle ] = sys_ni_syscall,
+	[ __NR_munmap ] (syscall_handler_t *) sys_munmap,
+	[ __NR_truncate ] (syscall_handler_t *) sys_truncate,
+	[ __NR_ftruncate ] (syscall_handler_t *) sys_ftruncate,
+	[ __NR_fchmod ] (syscall_handler_t *) sys_fchmod,
+	[ __NR_fchown ] (syscall_handler_t *) sys_fchown16,
+	[ __NR_getpriority ] (syscall_handler_t *) sys_getpriority,
+	[ __NR_setpriority ] (syscall_handler_t *) sys_setpriority,
+	[ __NR_profil ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_statfs ] (syscall_handler_t *) sys_statfs,
+	[ __NR_fstatfs ] (syscall_handler_t *) sys_fstatfs,
+	[ __NR_ioperm ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_socketcall ] (syscall_handler_t *) sys_socketcall,
+	[ __NR_syslog ] (syscall_handler_t *) sys_syslog,
+	[ __NR_setitimer ] (syscall_handler_t *) sys_setitimer,
+	[ __NR_getitimer ] (syscall_handler_t *) sys_getitimer,
+	[ __NR_stat ] (syscall_handler_t *) sys_newstat,
+	[ __NR_lstat ] (syscall_handler_t *) sys_newlstat,
+	[ __NR_fstat ] (syscall_handler_t *) sys_newfstat,
+	[ __NR_olduname ] (syscall_handler_t *) sys_uname,
+	[ __NR_iopl ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_vhangup ] (syscall_handler_t *) sys_vhangup,
+	[ __NR_idle ] (syscall_handler_t *) sys_ni_syscall,
 	[ __NR_wait4 ] = (syscall_handler_t *) sys_wait4,
 	[ __NR_swapoff ] = (syscall_handler_t *) sys_swapoff,
-	[ __NR_sysinfo ] = sys_sysinfo,
-	[ __NR_ipc ] = sys_ipc,
-	[ __NR_fsync ] = sys_fsync,
-	[ __NR_sigreturn ] = sys_sigreturn,
-	[ __NR_clone ] = sys_clone,
-	[ __NR_setdomainname ] = sys_setdomainname,
-	[ __NR_uname ] = sys_newuname,
-	[ __NR_adjtimex ] = sys_adjtimex,
-	[ __NR_mprotect ] = sys_mprotect,
-	[ __NR_sigprocmask ] = sys_sigprocmask,
-	[ __NR_create_module ] = sys_ni_syscall,
-	[ __NR_init_module ] = sys_init_module,
-	[ __NR_delete_module ] = sys_delete_module,
-	[ __NR_get_kernel_syms ] = sys_ni_syscall,
-	[ __NR_quotactl ] = sys_quotactl,
-	[ __NR_getpgid ] = sys_getpgid,
-	[ __NR_fchdir ] = sys_fchdir,
-	[ __NR_bdflush ] = sys_bdflush,
-	[ __NR_sysfs ] = sys_sysfs,
-	[ __NR_personality ] = sys_personality,
-	[ __NR_afs_syscall ] = sys_ni_syscall,
-	[ __NR_setfsuid ] = sys_setfsuid16,
-	[ __NR_setfsgid ] = sys_setfsgid16,
-	[ __NR__llseek ] = sys_llseek,
-	[ __NR_getdents ] = sys_getdents,
+	[ __NR_sysinfo ] (syscall_handler_t *) sys_sysinfo,
+	[ __NR_ipc ] (syscall_handler_t *) sys_ipc,
+	[ __NR_fsync ] (syscall_handler_t *) sys_fsync,
+	[ __NR_sigreturn ] (syscall_handler_t *) sys_sigreturn,
+	[ __NR_clone ] (syscall_handler_t *) sys_clone,
+	[ __NR_setdomainname ] (syscall_handler_t *) sys_setdomainname,
+	[ __NR_uname ] (syscall_handler_t *) sys_newuname,
+	[ __NR_adjtimex ] (syscall_handler_t *) sys_adjtimex,
+	[ __NR_mprotect ] (syscall_handler_t *) sys_mprotect,
+	[ __NR_sigprocmask ] (syscall_handler_t *) sys_sigprocmask,
+	[ __NR_create_module ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_init_module ] (syscall_handler_t *) sys_init_module,
+	[ __NR_delete_module ] (syscall_handler_t *) sys_delete_module,
+	[ __NR_get_kernel_syms ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_quotactl ] (syscall_handler_t *) sys_quotactl,
+	[ __NR_getpgid ] (syscall_handler_t *) sys_getpgid,
+	[ __NR_fchdir ] (syscall_handler_t *) sys_fchdir,
+	[ __NR_bdflush ] (syscall_handler_t *) sys_bdflush,
+	[ __NR_sysfs ] (syscall_handler_t *) sys_sysfs,
+	[ __NR_personality ] (syscall_handler_t *) sys_personality,
+	[ __NR_afs_syscall ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_setfsuid ] (syscall_handler_t *) sys_setfsuid16,
+	[ __NR_setfsgid ] (syscall_handler_t *) sys_setfsgid16,
+	[ __NR__llseek ] (syscall_handler_t *) sys_llseek,
+	[ __NR_getdents ] (syscall_handler_t *) sys_getdents,
 	[ __NR__newselect ] = (syscall_handler_t *) sys_select,
-	[ __NR_flock ] = sys_flock,
-	[ __NR_msync ] = sys_msync,
-	[ __NR_readv ] = sys_readv,
-	[ __NR_writev ] = sys_writev,
-	[ __NR_getsid ] = sys_getsid,
-	[ __NR_fdatasync ] = sys_fdatasync,
+	[ __NR_flock ] (syscall_handler_t *) sys_flock,
+	[ __NR_msync ] (syscall_handler_t *) sys_msync,
+	[ __NR_readv ] (syscall_handler_t *) sys_readv,
+	[ __NR_writev ] (syscall_handler_t *) sys_writev,
+	[ __NR_getsid ] (syscall_handler_t *) sys_getsid,
+	[ __NR_fdatasync ] (syscall_handler_t *) sys_fdatasync,
 	[ __NR__sysctl ] = (syscall_handler_t *) sys_sysctl,
-	[ __NR_mlock ] = sys_mlock,
-	[ __NR_munlock ] = sys_munlock,
-	[ __NR_mlockall ] = sys_mlockall,
-	[ __NR_munlockall ] = sys_munlockall,
-	[ __NR_sched_setparam ] = sys_sched_setparam,
-	[ __NR_sched_getparam ] = sys_sched_getparam,
-	[ __NR_sched_setscheduler ] = sys_sched_setscheduler,
-	[ __NR_sched_getscheduler ] = sys_sched_getscheduler,
+	[ __NR_mlock ] (syscall_handler_t *) sys_mlock,
+	[ __NR_munlock ] (syscall_handler_t *) sys_munlock,
+	[ __NR_mlockall ] (syscall_handler_t *) sys_mlockall,
+	[ __NR_munlockall ] (syscall_handler_t *) sys_munlockall,
+	[ __NR_sched_setparam ] (syscall_handler_t *) sys_sched_setparam,
+	[ __NR_sched_getparam ] (syscall_handler_t *) sys_sched_getparam,
+	[ __NR_sched_setscheduler ] (syscall_handler_t *) sys_sched_setscheduler,
+	[ __NR_sched_getscheduler ] (syscall_handler_t *) sys_sched_getscheduler,
 	[ __NR_sched_yield ] = (syscall_handler_t *) yield,
-	[ __NR_sched_get_priority_max ] = sys_sched_get_priority_max,
-	[ __NR_sched_get_priority_min ] = sys_sched_get_priority_min,
-	[ __NR_sched_rr_get_interval ] = sys_sched_rr_get_interval,
-	[ __NR_nanosleep ] = sys_nanosleep,
-	[ __NR_mremap ] = sys_mremap,
-	[ __NR_setresuid ] = sys_setresuid16,
-	[ __NR_getresuid ] = sys_getresuid16,
-	[ __NR_vm86 ] = sys_ni_syscall,
-	[ __NR_query_module ] = sys_ni_syscall,
-	[ __NR_poll ] = sys_poll,
-	[ __NR_nfsservctl ] = NFSSERVCTL,
-	[ __NR_setresgid ] = sys_setresgid16,
-	[ __NR_getresgid ] = sys_getresgid16,
-	[ __NR_prctl ] = sys_prctl,
-	[ __NR_rt_sigreturn ] = sys_rt_sigreturn,
-	[ __NR_rt_sigaction ] = sys_rt_sigaction,
-	[ __NR_rt_sigprocmask ] = sys_rt_sigprocmask,
-	[ __NR_rt_sigpending ] = sys_rt_sigpending,
-	[ __NR_rt_sigtimedwait ] = sys_rt_sigtimedwait,
-	[ __NR_rt_sigqueueinfo ] = sys_rt_sigqueueinfo,
-	[ __NR_rt_sigsuspend ] = sys_rt_sigsuspend,
-	[ __NR_pread64 ] = sys_pread64,
-	[ __NR_pwrite64 ] = sys_pwrite64,
-	[ __NR_chown ] = sys_chown16,
-	[ __NR_getcwd ] = sys_getcwd,
-	[ __NR_capget ] = sys_capget,
-	[ __NR_capset ] = sys_capset,
-	[ __NR_sigaltstack ] = sys_sigaltstack,
-	[ __NR_sendfile ] = sys_sendfile,
-	[ __NR_getpmsg ] = sys_ni_syscall,
-	[ __NR_putpmsg ] = sys_ni_syscall,
-	[ __NR_vfork ] = sys_vfork,
-	[ __NR_ugetrlimit ] = sys_getrlimit,
-	[ __NR_mmap2 ] = sys_mmap2,
-	[ __NR_truncate64 ] = sys_truncate64,
-	[ __NR_ftruncate64 ] = sys_ftruncate64,
-	[ __NR_stat64 ] = sys_stat64,
-	[ __NR_lstat64 ] = sys_lstat64,
-	[ __NR_fstat64 ] = sys_fstat64,
-	[ __NR_fcntl64 ] = sys_fcntl64,
-	[ __NR_getdents64 ] = sys_getdents64,
-	[ __NR_gettid ] = sys_gettid,
-	[ __NR_readahead ] = sys_readahead,
-	[ __NR_setxattr ] = sys_ni_syscall,
-	[ __NR_lsetxattr ] = sys_ni_syscall,
-	[ __NR_fsetxattr ] = sys_ni_syscall,
-	[ __NR_getxattr ] = sys_ni_syscall,
-	[ __NR_lgetxattr ] = sys_ni_syscall,
-	[ __NR_fgetxattr ] = sys_ni_syscall,
-	[ __NR_listxattr ] = sys_ni_syscall,
-	[ __NR_llistxattr ] = sys_ni_syscall,
-	[ __NR_flistxattr ] = sys_ni_syscall,
-	[ __NR_removexattr ] = sys_ni_syscall,
-	[ __NR_lremovexattr ] = sys_ni_syscall,
-	[ __NR_fremovexattr ] = sys_ni_syscall,
-	[ __NR_tkill ] = sys_tkill,
-	[ __NR_sendfile64 ] = sys_sendfile64,
-	[ __NR_futex ] = sys_futex,
-	[ __NR_sched_setaffinity ] = sys_sched_setaffinity,
-	[ __NR_sched_getaffinity ] = sys_sched_getaffinity,
-	[ __NR_io_setup ] = sys_io_setup,
-	[ __NR_io_destroy ] = sys_io_destroy,
-	[ __NR_io_getevents ] = sys_io_getevents,
-	[ __NR_io_submit ] = sys_io_submit,
-	[ __NR_io_cancel ] = sys_io_cancel,
-	[ __NR_exit_group ] = sys_exit_group,
-	[ __NR_lookup_dcookie ] = sys_lookup_dcookie,
-	[ __NR_epoll_create ] = sys_epoll_create,
-	[ __NR_epoll_ctl ] = sys_epoll_ctl,
-	[ __NR_epoll_wait ] = sys_epoll_wait,
-        [ __NR_remap_file_pages ] = sys_remap_file_pages,
-        [ __NR_set_tid_address ] = sys_set_tid_address,
-        [ __NR_vserver ] = sys_vserver,
+	[ __NR_sched_get_priority_max ] (syscall_handler_t *) sys_sched_get_priority_max,
+	[ __NR_sched_get_priority_min ] (syscall_handler_t *) sys_sched_get_priority_min,
+	[ __NR_sched_rr_get_interval ] (syscall_handler_t *) sys_sched_rr_get_interval,
+	[ __NR_nanosleep ] (syscall_handler_t *) sys_nanosleep,
+	[ __NR_mremap ] (syscall_handler_t *) sys_mremap,
+	[ __NR_setresuid ] (syscall_handler_t *) sys_setresuid16,
+	[ __NR_getresuid ] (syscall_handler_t *) sys_getresuid16,
+	[ __NR_vm86 ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_query_module ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_poll ] (syscall_handler_t *) sys_poll,
+	[ __NR_nfsservctl ] = (syscall_handler_t *) NFSSERVCTL,
+	[ __NR_setresgid ] (syscall_handler_t *) sys_setresgid16,
+	[ __NR_getresgid ] (syscall_handler_t *) sys_getresgid16,
+	[ __NR_prctl ] (syscall_handler_t *) sys_prctl,
+	[ __NR_rt_sigreturn ] (syscall_handler_t *) sys_rt_sigreturn,
+	[ __NR_rt_sigaction ] (syscall_handler_t *) sys_rt_sigaction,
+	[ __NR_rt_sigprocmask ] (syscall_handler_t *) sys_rt_sigprocmask,
+	[ __NR_rt_sigpending ] (syscall_handler_t *) sys_rt_sigpending,
+	[ __NR_rt_sigtimedwait ] (syscall_handler_t *) sys_rt_sigtimedwait,
+	[ __NR_rt_sigqueueinfo ] (syscall_handler_t *) sys_rt_sigqueueinfo,
+	[ __NR_rt_sigsuspend ] (syscall_handler_t *) sys_rt_sigsuspend,
+	[ __NR_pread64 ] (syscall_handler_t *) sys_pread64,
+	[ __NR_pwrite64 ] (syscall_handler_t *) sys_pwrite64,
+	[ __NR_chown ] (syscall_handler_t *) sys_chown16,
+	[ __NR_getcwd ] (syscall_handler_t *) sys_getcwd,
+	[ __NR_capget ] (syscall_handler_t *) sys_capget,
+	[ __NR_capset ] (syscall_handler_t *) sys_capset,
+	[ __NR_sigaltstack ] (syscall_handler_t *) sys_sigaltstack,
+	[ __NR_sendfile ] (syscall_handler_t *) sys_sendfile,
+	[ __NR_getpmsg ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_putpmsg ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_vfork ] (syscall_handler_t *) sys_vfork,
+	[ __NR_ugetrlimit ] (syscall_handler_t *) sys_getrlimit,
+	[ __NR_mmap2 ] (syscall_handler_t *) sys_mmap2,
+	[ __NR_truncate64 ] (syscall_handler_t *) sys_truncate64,
+	[ __NR_ftruncate64 ] (syscall_handler_t *) sys_ftruncate64,
+	[ __NR_stat64 ] (syscall_handler_t *) sys_stat64,
+	[ __NR_lstat64 ] (syscall_handler_t *) sys_lstat64,
+	[ __NR_fstat64 ] (syscall_handler_t *) sys_fstat64,
+	[ __NR_getdents64 ] (syscall_handler_t *) sys_getdents64,
+	[ __NR_fcntl64 ] (syscall_handler_t *) sys_fcntl64,
+	[ 223 ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_gettid ] (syscall_handler_t *) sys_gettid,
+	[ __NR_readahead ] (syscall_handler_t *) sys_readahead,
+	[ __NR_setxattr ] (syscall_handler_t *) sys_setxattr,
+	[ __NR_lsetxattr ] (syscall_handler_t *) sys_lsetxattr,
+	[ __NR_fsetxattr ] (syscall_handler_t *) sys_fsetxattr,
+	[ __NR_getxattr ] (syscall_handler_t *) sys_getxattr,
+	[ __NR_lgetxattr ] (syscall_handler_t *) sys_lgetxattr,
+	[ __NR_fgetxattr ] (syscall_handler_t *) sys_fgetxattr,
+	[ __NR_listxattr ] (syscall_handler_t *) sys_listxattr,
+	[ __NR_llistxattr ] (syscall_handler_t *) sys_llistxattr,
+	[ __NR_flistxattr ] (syscall_handler_t *) sys_flistxattr,
+	[ __NR_removexattr ] (syscall_handler_t *) sys_removexattr,
+	[ __NR_lremovexattr ] (syscall_handler_t *) sys_lremovexattr,
+	[ __NR_fremovexattr ] (syscall_handler_t *) sys_fremovexattr,
+	[ __NR_tkill ] (syscall_handler_t *) sys_tkill,
+	[ __NR_sendfile64 ] (syscall_handler_t *) sys_sendfile64,
+	[ __NR_futex ] (syscall_handler_t *) sys_futex,
+	[ __NR_sched_setaffinity ] (syscall_handler_t *) sys_sched_setaffinity,
+	[ __NR_sched_getaffinity ] (syscall_handler_t *) sys_sched_getaffinity,
+	[ __NR_set_thread_area ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_get_thread_area ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_io_setup ] (syscall_handler_t *) sys_io_setup,
+	[ __NR_io_destroy ] (syscall_handler_t *) sys_io_destroy,
+	[ __NR_io_getevents ] (syscall_handler_t *) sys_io_getevents,
+	[ __NR_io_submit ] (syscall_handler_t *) sys_io_submit,
+	[ __NR_io_cancel ] (syscall_handler_t *) sys_io_cancel,
+	[ __NR_fadvise64 ] (syscall_handler_t *) sys_fadvise64,
+	[ 251 ] (syscall_handler_t *) sys_ni_syscall,
+	[ __NR_exit_group ] (syscall_handler_t *) sys_exit_group,
+	[ __NR_lookup_dcookie ] (syscall_handler_t *) sys_lookup_dcookie,
+	[ __NR_epoll_create ] (syscall_handler_t *) sys_epoll_create,
+	[ __NR_epoll_ctl ] (syscall_handler_t *) sys_epoll_ctl,
+	[ __NR_epoll_wait ] (syscall_handler_t *) sys_epoll_wait,
+        [ __NR_remap_file_pages ] (syscall_handler_t *) sys_remap_file_pages,
+        [ __NR_set_tid_address ] (syscall_handler_t *) sys_set_tid_address,
+	[ __NR_timer_create ] (syscall_handler_t *) sys_timer_create,
+	[ __NR_timer_settime ] (syscall_handler_t *) sys_timer_settime,
+	[ __NR_timer_gettime ] (syscall_handler_t *) sys_timer_gettime,
+	[ __NR_timer_getoverrun ] (syscall_handler_t *) sys_timer_getoverrun,
+	[ __NR_timer_delete ] (syscall_handler_t *) sys_timer_delete,
+	[ __NR_clock_settime ] (syscall_handler_t *) sys_clock_settime,
+	[ __NR_clock_gettime ] (syscall_handler_t *) sys_clock_gettime,
+	[ __NR_clock_getres ] (syscall_handler_t *) sys_clock_getres,
+	[ __NR_clock_nanosleep ] (syscall_handler_t *) sys_clock_nanosleep,
+	[ __NR_statfs64 ] (syscall_handler_t *) sys_statfs64,
+	[ __NR_fstatfs64 ] (syscall_handler_t *) sys_fstatfs64,
+	[ __NR_tgkill ] (syscall_handler_t *) sys_tgkill,
+	[ __NR_utimes ] (syscall_handler_t *) sys_utimes,
+	[ __NR_fadvise64_64 ] (syscall_handler_t *) sys_fadvise64_64,
+	[ __NR_vserver ] (syscall_handler_t *) sys_vserver,
 
 	ARCH_SYSCALLS
 	[ LAST_SYSCALL + 1 ... NR_syscalls ] = 
diff --git a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c
index 4592e3fac..6094be04b 100644
--- a/arch/um/kernel/syscall_kern.c
+++ b/arch/um/kernel/syscall_kern.c
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -38,32 +38,23 @@ long um_mount(char * dev_name, char * dir_name, char * type,
 
 long sys_fork(void)
 {
-	struct task_struct *p;
+	long ret;
 
 	current->thread.forking = 1;
-        p = do_fork(SIGCHLD, 0, NULL, 0, NULL, NULL);
+        ret = do_fork(SIGCHLD, 0, NULL, 0, NULL, NULL);
 	current->thread.forking = 0;
-	return(IS_ERR(p) ? PTR_ERR(p) : p->pid);
-}
-
-long sys_clone(unsigned long clone_flags, unsigned long newsp)
-{
-	struct task_struct *p;
-
-	current->thread.forking = 1;
-	p = do_fork(clone_flags, newsp, NULL, 0, NULL, NULL);
-	current->thread.forking = 0;
-	return(IS_ERR(p) ? PTR_ERR(p) : p->pid);
+	return(ret);
 }
 
 long sys_vfork(void)
 {
-	struct task_struct *p;
+	long ret;
 
 	current->thread.forking = 1;
-	p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL, NULL);
+	ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL,
+		      NULL);
 	current->thread.forking = 0;
-	return(IS_ERR(p) ? PTR_ERR(p) : p->pid);
+	return(ret);
 }
 
 /* common code for old and new mmaps */
@@ -138,43 +129,12 @@ int sys_pipe(unsigned long * fildes)
 
         error = do_pipe(fd);
         if (!error) {
-                if (copy_to_user(fildes, fd, 2*sizeof(int)))
+		if (copy_to_user(fildes, fd, sizeof(fd)))
                         error = -EFAULT;
         }
         return error;
 }
 
-int sys_sigaction(int sig, const struct old_sigaction *act,
-			 struct old_sigaction *oact)
-{
-	struct k_sigaction new_ka, old_ka;
-	int ret;
-
-	if (act) {
-		old_sigset_t mask;
-		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
-		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
-		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
-			return -EFAULT;
-		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
-		__get_user(mask, &act->sa_mask);
-		siginitset(&new_ka.sa.sa_mask, mask);
-	}
-
-	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
-
-	if (!ret && oact) {
-		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
-		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
-		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
-			return -EFAULT;
-		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
-		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
-	}
-
-	return ret;
-}
-
 /*
  * sys_ipc() is the de-multiplexer for the SysV IPC calls..
  *
@@ -256,7 +216,7 @@ int sys_ipc (uint call, int first, int second,
 		return sys_shmctl (first, second,
 				   (struct shmid_ds *) ptr);
 	default:
-		return -EINVAL;
+		return -ENOSYS;
 	}
 }
 
@@ -307,11 +267,6 @@ int sys_olduname(struct oldold_utsname * name)
 	return error;
 }
 
-int sys_sigaltstack(const stack_t *uss, stack_t *uoss)
-{
-	return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
-}
-
 long execute_syscall(void *r)
 {
 	return(CHOOSE_MODE_PROC(execute_syscall_tt, execute_syscall_skas, r));
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
index b43c21466..80b84700f 100644
--- a/arch/um/kernel/sysrq.c
+++ b/arch/um/kernel/sysrq.c
@@ -44,6 +44,11 @@ void dump_stack(void)
 }
 EXPORT_SYMBOL(dump_stack);
 
+void show_stack(struct task_struct *task, unsigned long *sp)
+{
+	show_trace(sp);
+}
+
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/kernel/tempfile.c b/arch/um/kernel/tempfile.c
index 3fd42081d..b1674bc13 100644
--- a/arch/um/kernel/tempfile.c
+++ b/arch/um/kernel/tempfile.c
@@ -28,6 +28,7 @@ static void __init find_tempdir(void)
 	}
 	if((dir == NULL) || (*dir == '\0')) 
 		dir = "/tmp";
+
 	tempdir = malloc(strlen(dir) + 2);
 	if(tempdir == NULL){
 		fprintf(stderr, "Failed to malloc tempdir, "
@@ -49,7 +50,8 @@ int make_tempfile(const char *template, char **out_tempname, int do_unlink)
 	else
 		*tempname = 0;
 	strcat(tempname, template);
-	if((fd = mkstemp(tempname)) < 0){
+	fd = mkstemp(tempname);
+	if(fd < 0){
 		fprintf(stderr, "open - cannot create %s: %s\n", tempname, 
 			strerror(errno));
 		return -1;
@@ -59,7 +61,8 @@ int make_tempfile(const char *template, char **out_tempname, int do_unlink)
 		return -1;
 	}
 	if(out_tempname){
-		if((*out_tempname = strdup(tempname)) == NULL){
+		*out_tempname = strdup(tempname);
+		if(*out_tempname == NULL){
 			perror("strdup");
 			return -1;
 		}
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 6f0d7573e..96691a0df 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -4,24 +4,33 @@
  */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <unistd.h>
 #include <time.h>
 #include <sys/time.h>
 #include <signal.h>
 #include <errno.h>
-#include "linux/module.h"
 #include "user_util.h"
 #include "kern_util.h"
 #include "user.h"
 #include "process.h"
 #include "signal_user.h"
 #include "time_user.h"
+#include "kern_constants.h"
+
+/* XXX This really needs to be declared and initialized in a kernel file since
+ * it's in <linux/time.h>
+ */
+extern struct timespec wall_to_monotonic;
 
 extern struct timeval xtime;
 
+struct timeval local_offset = { 0, 0 };
+
 void timer(void)
 {
 	gettimeofday(&xtime, NULL);
+	timeradd(&xtime, &local_offset, &xtime);
 }
 
 void set_interval(int timer_type)
@@ -44,6 +53,15 @@ void enable_timer(void)
 		       errno);
 }
 
+void disable_timer(void)
+{
+	struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
+	if((setitimer(ITIMER_VIRTUAL, &disable, NULL) < 0) ||
+	   (setitimer(ITIMER_REAL, &disable, NULL) < 0))
+		printk("disnable_timer - setitimer failed, errno = %d\n",
+		       errno);
+}
+
 void switch_timers(int to_real)
 {
 	struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
@@ -66,7 +84,7 @@ void switch_timers(int to_real)
 		       errno);
 }
 
-void idle_timer(void)
+void uml_idle_timer(void)
 {
 	if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR)
 		panic("Couldn't unset SIGVTALRM handler");
@@ -76,14 +94,23 @@ void idle_timer(void)
 	set_interval(ITIMER_REAL);
 }
 
+extern int do_posix_clock_monotonic_gettime(struct timespec *tp);
+
 void time_init(void)
 {
+	struct timespec now;
+
 	if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR)
 		panic("Couldn't set SIGVTALRM handler");
 	set_interval(ITIMER_VIRTUAL);
+
+	do_posix_clock_monotonic_gettime(&now);
+	wall_to_monotonic.tv_sec = -now.tv_sec;
+	wall_to_monotonic.tv_nsec = -now.tv_nsec;
 }
 
-struct timeval local_offset = { 0, 0 };
+/* Declared in linux/time.h, which can't be included here */
+extern void clock_was_set(void);
 
 void do_gettimeofday(struct timeval *tv)
 {
@@ -96,15 +123,13 @@ void do_gettimeofday(struct timeval *tv)
 	clock_was_set();
 }
 
-EXPORT_SYMBOL(do_gettimeofday);
-
 int do_settimeofday(struct timespec *tv)
 {
 	struct timeval now;
 	unsigned long flags;
 	struct timeval tv_in;
 
-	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+	if ((unsigned long) tv->tv_nsec >= UM_NSEC_PER_SEC)
 		return -EINVAL;
 
 	tv_in.tv_sec = tv->tv_sec;
@@ -114,9 +139,9 @@ int do_settimeofday(struct timespec *tv)
 	gettimeofday(&now, NULL);
 	timersub(&tv_in, &now, &local_offset);
 	time_unlock(flags);
-}
 
-EXPORT_SYMBOL(do_settimeofday);
+	return(0);
+}
 
 void idle_sleep(int secs)
 {
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
index 752fd03f2..5ce566882 100644
--- a/arch/um/kernel/time_kern.c
+++ b/arch/um/kernel/time_kern.c
@@ -20,6 +20,7 @@
 #include "user_util.h"
 #include "time_user.h"
 #include "mode.h"
+#include "os.h"
 
 u64 jiffies_64;
 
@@ -30,22 +31,63 @@ int hz(void)
 	return(HZ);
 }
 
+/*
+ * Scheduler clock - returns current time in nanosec units.
+ */
+unsigned long long sched_clock(void)
+{
+	return (unsigned long long)jiffies_64 * (1000000000 / HZ);
+}
+
 /* Changed at early boot */
 int timer_irq_inited = 0;
 
-/* missed_ticks will be modified after kernel memory has been 
- * write-protected, so this puts it in a section which will be left 
- * write-enabled.
- */
-int __attribute__ ((__section__ (".unprotected"))) missed_ticks[NR_CPUS];
+static int first_tick;
+static unsigned long long prev_usecs;
+#ifdef CONFIG_UML_REAL_TIME_CLOCK
+static long long delta;   		/* Deviation per interval */
+#endif
+
+#define MILLION 1000000
 
 void timer_irq(union uml_pt_regs *regs)
 {
-	int cpu = current->thread_info->cpu, ticks = missed_ticks[cpu];
+	unsigned long long ticks = 0;
+
+	if(!timer_irq_inited){
+		/* This is to ensure that ticks don't pile up when
+		 * the timer handler is suspended */
+		first_tick = 0;
+		return;
+	}
+
+	if(first_tick){
+#ifdef CONFIG_UML_REAL_TIME_CLOCK
+		/* We've had 1 tick */
+		unsigned long long usecs = os_usecs();
 
-        if(!timer_irq_inited) return;
-	missed_ticks[cpu] = 0;
-	while(ticks--) do_IRQ(TIMER_IRQ, regs);
+		delta += usecs - prev_usecs;
+		prev_usecs = usecs;
+
+		/* Protect against the host clock being set backwards */
+		if(delta < 0)
+			delta = 0;
+
+		ticks += (delta * HZ) / MILLION;
+		delta -= (ticks * MILLION) / HZ;
+#else
+		ticks = 1;
+#endif
+	}
+	else {
+		prev_usecs = os_usecs();
+		first_tick = 1;
+	}
+
+	while(ticks > 0){
+		do_IRQ(TIMER_IRQ, regs);
+		ticks--;
+	}
 }
 
 void boot_timer_handler(int sig)
@@ -58,12 +100,15 @@ void boot_timer_handler(int sig)
 	do_timer(&regs);
 }
 
-void um_timer(int irq, void *dev, struct pt_regs *regs)
+irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs)
 {
+	unsigned long flags;
+
 	do_timer(regs);
-	write_seqlock(&xtime_lock);
+	write_seqlock_irqsave(&xtime_lock, flags);
 	timer();
-	write_sequnlock(&xtime_lock);
+	write_sequnlock_irqrestore(&xtime_lock, flags);
+	return(IRQ_HANDLED);
 }
 
 long um_time(int * tloc)
@@ -81,12 +126,12 @@ long um_time(int * tloc)
 long um_stime(int * tptr)
 {
 	int value;
-	struct timeval new;
+	struct timespec new;
 
 	if (get_user(value, tptr))
                 return -EFAULT;
 	new.tv_sec = value;
-	new.tv_usec = 0;
+	new.tv_nsec = 0;
 	do_settimeofday(&new);
 	return 0;
 }
@@ -110,7 +155,7 @@ void __udelay(um_udelay_t usecs)
 {
 	int i, n;
 
-	n = (loops_per_jiffy * HZ * usecs) / 1000000;
+	n = (loops_per_jiffy * HZ * usecs) / MILLION;
 	for(i=0;i<n;i++) ;
 }
 
@@ -118,16 +163,18 @@ void __const_udelay(um_udelay_t usecs)
 {
 	int i, n;
 
-	n = (loops_per_jiffy * HZ * usecs) / 1000000;
+	n = (loops_per_jiffy * HZ * usecs) / MILLION;
 	for(i=0;i<n;i++) ;
 }
 
 void timer_handler(int sig, union uml_pt_regs *regs)
 {
 #ifdef CONFIG_SMP
+	local_irq_disable();
 	update_process_times(user_context(UPT_SP(regs)));
+	local_irq_enable();
 #endif
-	if(current->thread_info->cpu == 0)
+	if(current_thread->cpu == 0)
 		timer_irq(regs);
 }
 
@@ -136,6 +183,7 @@ static spinlock_t timer_spinlock = SPIN_LOCK_UNLOCKED;
 unsigned long time_lock(void)
 {
 	unsigned long flags;
+
 	spin_lock_irqsave(&timer_spinlock, flags);
 	return(flags);
 }
@@ -150,8 +198,8 @@ int __init timer_init(void)
 	int err;
 
 	CHOOSE_MODE(user_time_init_tt(), user_time_init_skas());
-	if((err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer", 
-			      NULL)) != 0)
+	err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer", NULL);
+	if(err != 0)
 		printk(KERN_ERR "timer_init : request_irq failed - "
 		       "errno = %d\n", -err);
 	timer_irq_inited = 1;
@@ -160,7 +208,6 @@ int __init timer_init(void)
 
 __initcall(timer_init);
 
-
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
index 7925dc459..cba33ef6d 100644
--- a/arch/um/kernel/trap_kern.c
+++ b/arch/um/kernel/trap_kern.c
@@ -16,12 +16,15 @@
 #include "asm/tlbflush.h"
 #include "asm/a.out.h"
 #include "asm/current.h"
+#include "asm/irq.h"
 #include "user_util.h"
 #include "kern_util.h"
 #include "kern.h"
 #include "chan_kern.h"
 #include "mconsole_kern.h"
 #include "2_5compat.h"
+#include "mem.h"
+#include "mem_kern.h"
 
 int handle_page_fault(unsigned long address, unsigned long ip, 
 		      int is_write, int is_user, int *code_out)
@@ -51,12 +54,10 @@ int handle_page_fault(unsigned long address, unsigned long ip,
 	if(is_write && !(vma->vm_flags & VM_WRITE)) 
 		goto out;
 	page = address & PAGE_MASK;
-	if(page == (unsigned long) current->thread_info + PAGE_SIZE)
-		panic("Kernel stack overflow");
 	pgd = pgd_offset(mm, page);
 	pmd = pmd_offset(pgd, page);
- survive:
 	do {
+ survive:
 		switch (handle_mm_fault(mm, vma, address, is_write)){
 		case VM_FAULT_MINOR:
 			current->min_flt++;
@@ -75,10 +76,10 @@ int handle_page_fault(unsigned long address, unsigned long ip,
 		}
 		pte = pte_offset_kernel(pmd, page);
 	} while(!pte_present(*pte));
+	err = 0;
 	*pte = pte_mkyoung(*pte);
 	if(pte_write(*pte)) *pte = pte_mkdirty(*pte);
 	flush_tlb_page(vma, page);
-	err = 0;
  out:
 	up_read(&mm->mmap_sem);
 	return(err);
@@ -94,10 +95,36 @@ out_of_memory:
 		down_read(&mm->mmap_sem);
 		goto survive;
 	}
-	err = -ENOMEM;
 	goto out;
 }
 
+LIST_HEAD(physmem_remappers);
+
+void register_remapper(struct remapper *info)
+{
+	list_add(&info->list, &physmem_remappers);
+}
+
+static int check_remapped_addr(unsigned long address, int is_write)
+{
+	struct remapper *remapper;
+	struct list_head *ele;
+	__u64 offset;
+	int fd;
+
+	fd = phys_mapping(__pa(address), &offset);
+	if(fd == -1)
+		return(0);
+
+	list_for_each(ele, &physmem_remappers){
+		remapper = list_entry(ele, struct remapper, list);
+		if((*remapper->proc)(fd, address, is_write, offset))
+			return(1);
+	}
+
+	return(0);
+}
+
 unsigned long segv(unsigned long address, unsigned long ip, int is_write, 
 		   int is_user, void *sc)
 {
@@ -109,7 +136,9 @@ unsigned long segv(unsigned long address, unsigned long ip, int is_write,
                 flush_tlb_kernel_vm();
                 return(0);
         }
-        if(current->mm == NULL)
+	else if(check_remapped_addr(address & PAGE_MASK, is_write))
+		return(0);
+	else if(current->mm == NULL)
 		panic("Segfault with no mm");
 	err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
 
@@ -120,9 +149,8 @@ unsigned long segv(unsigned long address, unsigned long ip, int is_write,
 		current->thread.fault_addr = (void *) address;
 		do_longjmp(catcher, 1);
 	} 
-	else if(current->thread.fault_addr != NULL){
+	else if(current->thread.fault_addr != NULL)
 		panic("fault_addr set but no fault catcher");
-	}
 	else if(arch_fixup(ip, sc))
 		return(0);
 
@@ -155,8 +183,6 @@ void bad_segv(unsigned long address, unsigned long ip, int is_write)
 {
 	struct siginfo si;
 
-	printk(KERN_ERR "Unfixable SEGV in '%s' (pid %d) at 0x%lx "
-	       "(ip 0x%lx)\n", current->comm, current->pid, address, ip);
 	si.si_signo = SIGSEGV;
 	si.si_code = SEGV_ACCERR;
 	si.si_addr = (void *) address;
@@ -180,6 +206,11 @@ void bus_handler(int sig, union uml_pt_regs *regs)
 	else relay_signal(sig, regs);
 }
 
+void winch(int sig, union uml_pt_regs *regs)
+{
+	do_IRQ(WINCH_IRQ, regs);
+}
+
 void trap_init(void)
 {
 }
diff --git a/arch/um/kernel/trap_user.c b/arch/um/kernel/trap_user.c
index 63812e597..d12eac64a 100644
--- a/arch/um/kernel/trap_user.c
+++ b/arch/um/kernel/trap_user.c
@@ -5,11 +5,9 @@
 
 #include <stdlib.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <setjmp.h>
 #include <signal.h>
 #include <sys/time.h>
-#include <sys/ioctl.h>
 #include <sys/ptrace.h>
 #include <sys/wait.h>
 #include <asm/page.h>
@@ -34,7 +32,14 @@ void kill_child_dead(int pid)
 {
 	kill(pid, SIGKILL);
 	kill(pid, SIGCONT);
-	while(waitpid(pid, NULL, 0) > 0) kill(pid, SIGCONT);
+	do {
+		int n;
+		CATCH_EINTR(n = waitpid(pid, NULL, 0));
+		if (n > 0)
+			kill(pid, SIGCONT);
+		else
+			break;
+	} while(1);
 }
 
 /* Unlocked - don't care if this is a bit off */
@@ -82,6 +87,8 @@ struct signal_info sig_info[] = {
 		     .is_irq 		= 0 },
 	[ SIGILL ] { .handler 		= relay_signal,
 		     .is_irq 		= 0 },
+	[ SIGWINCH ] { .handler		= winch,
+		       .is_irq		= 1 },
 	[ SIGBUS ] { .handler 		= bus_handler,
 		     .is_irq 		= 0 },
 	[ SIGSEGV] { .handler 		= segv_handler,
@@ -102,12 +109,11 @@ void sig_handler(int sig, struct sigcontext sc)
 			 sig, &sc);
 }
 
-extern int timer_irq_inited, missed_ticks[];
+extern int timer_irq_inited;
 
 void alarm_handler(int sig, struct sigcontext sc)
 {
 	if(!timer_irq_inited) return;
-	missed_ticks[cpu()]++;
 
 	if(sig == SIGALRM)
 		switch_timers(0);
@@ -121,9 +127,9 @@ void alarm_handler(int sig, struct sigcontext sc)
 
 void do_longjmp(void *b, int val)
 {
-	jmp_buf *buf = b;
+	sigjmp_buf *buf = b;
 
-	longjmp(*buf, val);
+	siglongjmp(*buf, val);
 }
 
 /*
diff --git a/arch/um/kernel/tt/Makefile b/arch/um/kernel/tt/Makefile
index 439688b0d..33416e889 100644
--- a/arch/um/kernel/tt/Makefile
+++ b/arch/um/kernel/tt/Makefile
@@ -1,5 +1,5 @@
 # 
-# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+# Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
 # Licensed under the GPL
 #
 
@@ -7,7 +7,7 @@ extra-y := unmap_fin.o
 
 obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \
 	syscall_kern.o syscall_user.o time.o tlb.o tracer.o trap_user.o \
-	uaccess_user.o sys-$(SUBARCH)/
+	uaccess.o uaccess_user.o sys-$(SUBARCH)/
 
 obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/
 
@@ -27,5 +27,3 @@ $(obj)/unmap.o: $(src)/unmap.c
 
 $(obj)/unmap_fin.o : $(src)/unmap.o
 	ld -r -o $@ $< -lc -L/usr/lib
-
-clean :
diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c
index afd94713d..065b504a6 100644
--- a/arch/um/kernel/tt/exec_kern.c
+++ b/arch/um/kernel/tt/exec_kern.c
@@ -14,9 +14,11 @@
 #include "kern_util.h"
 #include "irq_user.h"
 #include "time_user.h"
+#include "signal_user.h"
 #include "mem_user.h"
 #include "os.h"
 #include "tlb.h"
+#include "mode.h"
 
 static int exec_tramp(void *sig_stack)
 {
@@ -38,8 +40,7 @@ void flush_thread_tt(void)
 		do_exit(SIGKILL);
 	}
 		
-	new_pid = start_fork_tramp((void *) current->thread.kernel_stack,
-				   stack, 0, exec_tramp);
+	new_pid = start_fork_tramp(current->thread_info, stack, 0, exec_tramp);
 	if(new_pid < 0){
 		printk(KERN_ERR 
 		       "flush_thread : new thread failed, errno = %d\n",
@@ -47,17 +48,19 @@ void flush_thread_tt(void)
 		do_exit(SIGKILL);
 	}
 
-	if(current->thread_info->cpu == 0)
+	if(current_thread->cpu == 0)
 		forward_interrupts(new_pid);
 	current->thread.request.op = OP_EXEC;
 	current->thread.request.u.exec.pid = new_pid;
-	unprotect_stack((unsigned long) current->thread_info);
+	unprotect_stack((unsigned long) current_thread);
 	os_usr1_process(os_getpid());
+	change_sig(SIGUSR1, 1);
 
+	change_sig(SIGUSR1, 0);
 	enable_timer();
 	free_page(stack);
 	protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1);
-	task_protections((unsigned long) current->thread_info);
+	task_protections((unsigned long) current_thread);
 	force_flush_all();
 	unblock_signals();
 }
diff --git a/arch/um/kernel/tt/exec_user.c b/arch/um/kernel/tt/exec_user.c
index 35d108266..6d5fa825a 100644
--- a/arch/um/kernel/tt/exec_user.c
+++ b/arch/um/kernel/tt/exec_user.c
@@ -19,13 +19,18 @@
 void do_exec(int old_pid, int new_pid)
 {
 	unsigned long regs[FRAME_SIZE];
+	int err;
 
 	if((ptrace(PTRACE_ATTACH, new_pid, 0, 0) < 0) ||
-	   (ptrace(PTRACE_CONT, new_pid, 0, 0) < 0) ||
-	   (waitpid(new_pid, 0, WUNTRACED) < 0))
+	   (ptrace(PTRACE_CONT, new_pid, 0, 0) < 0))
 		tracer_panic("do_exec failed to attach proc - errno = %d",
 			     errno);
 
+	CATCH_EINTR(err = waitpid(new_pid, 0, WUNTRACED));
+	if (err < 0)
+		tracer_panic("do_exec failed to attach proc in waitpid - errno = %d",
+			     errno);
+
 	if(ptrace_getregs(old_pid, regs) < 0)
 		tracer_panic("do_exec failed to get registers - errno = %d",
 			     errno);
diff --git a/arch/um/kernel/tt/include/mode.h b/arch/um/kernel/tt/include/mode.h
index 83d94abb9..1a64e753e 100644
--- a/arch/um/kernel/tt/include/mode.h
+++ b/arch/um/kernel/tt/include/mode.h
@@ -8,6 +8,8 @@
 
 #include "sysdep/ptrace.h"
 
+enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
+
 extern int tracing_pid;
 
 extern int tracer(int (*init_proc)(void *), void *sp);
diff --git a/arch/um/kernel/tt/include/uaccess.h b/arch/um/kernel/tt/include/uaccess.h
index 42425a225..7399836cb 100644
--- a/arch/um/kernel/tt/include/uaccess.h
+++ b/arch/um/kernel/tt/include/uaccess.h
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -43,65 +43,19 @@ extern unsigned long get_fault_addr(void);
 
 extern int __do_copy_from_user(void *to, const void *from, int n,
 			       void **fault_addr, void **fault_catcher);
-
-static inline int copy_from_user_tt(void *to, const void *from, int n)
-{
-	return(access_ok_tt(VERIFY_READ, from, n) ?
-	       __do_copy_from_user(to, from, n, 
-				   &current->thread.fault_addr,
-				   &current->thread.fault_catcher) : n);
-}
-
-static inline int copy_to_user_tt(void *to, const void *from, int n)
-{
-	return(access_ok_tt(VERIFY_WRITE, to, n) ?
-	       __do_copy_to_user(to, from, n, 
-				   &current->thread.fault_addr,
-				   &current->thread.fault_catcher) : n);
-}
-
 extern int __do_strncpy_from_user(char *dst, const char *src, size_t n,
 				  void **fault_addr, void **fault_catcher);
-
-static inline int strncpy_from_user_tt(char *dst, const char *src, int count)
-{
-	int n;
-
-	if(!access_ok_tt(VERIFY_READ, src, 1)) return(-EFAULT);
-	n = __do_strncpy_from_user(dst, src, count, 
-				   &current->thread.fault_addr,
-				   &current->thread.fault_catcher);
-	if(n < 0) return(-EFAULT);
-	return(n);
-}
-
 extern int __do_clear_user(void *mem, size_t len, void **fault_addr,
 			   void **fault_catcher);
-
-static inline int __clear_user_tt(void *mem, int len)
-{
-	return(__do_clear_user(mem, len,
-			       &current->thread.fault_addr,
-			       &current->thread.fault_catcher));
-}
-
-static inline int clear_user_tt(void *mem, int len)
-{
-	return(access_ok_tt(VERIFY_WRITE, mem, len) ? 
-	       __do_clear_user(mem, len, 
-			       &current->thread.fault_addr,
-			       &current->thread.fault_catcher) : len);
-}
-
 extern int __do_strnlen_user(const char *str, unsigned long n,
 			     void **fault_addr, void **fault_catcher);
 
-static inline int strnlen_user_tt(const void *str, int len)
-{
-	return(__do_strnlen_user(str, len,
-				 &current->thread.fault_addr,
-				 &current->thread.fault_catcher));
-}
+extern int copy_from_user_tt(void *to, const void *from, int n);
+extern int copy_to_user_tt(void *to, const void *from, int n);
+extern int strncpy_from_user_tt(char *dst, const char *src, int count);
+extern int __clear_user_tt(void *mem, int len);
+extern int clear_user_tt(void *mem, int len);
+extern int strnlen_user_tt(const void *str, int len);
 
 #endif
 
diff --git a/arch/um/kernel/tt/mem.c b/arch/um/kernel/tt/mem.c
index 0c39b2663..34090b8d2 100644
--- a/arch/um/kernel/tt/mem.c
+++ b/arch/um/kernel/tt/mem.c
@@ -18,7 +18,7 @@ void before_mem_tt(unsigned long brk_start)
 	if(!jail || debug)
 		remap_data(UML_ROUND_DOWN(&_stext), UML_ROUND_UP(&_etext), 1);
 	remap_data(UML_ROUND_DOWN(&_sdata), UML_ROUND_UP(&_edata), 1);
-	remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(brk_start), 1);
+	remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(&_end), 1);
 }
 
 #ifdef CONFIG_HOST_2G_2G
diff --git a/arch/um/kernel/tt/mem_user.c b/arch/um/kernel/tt/mem_user.c
index e10db3f1f..308526745 100644
--- a/arch/um/kernel/tt/mem_user.c
+++ b/arch/um/kernel/tt/mem_user.c
@@ -25,14 +25,13 @@ void remap_data(void *segment_start, void *segment_end, int w)
 	size = (unsigned long) segment_end - 
 		(unsigned long) segment_start;
 	data = create_mem_file(size);
-	if((addr = mmap(NULL, size, PROT_WRITE | PROT_READ, 
-			MAP_SHARED, data, 0)) == MAP_FAILED){
+	addr = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, data, 0);
+	if(addr == MAP_FAILED){
 		perror("mapping new data segment");
 		exit(1);
 	}
 	memcpy(addr, segment_start, size);
-	if(switcheroo(data, prot, addr, segment_start, 
-		      size) < 0){
+	if(switcheroo(data, prot, addr, segment_start, size) < 0){
 		printf("switcheroo failed\n");
 		exit(1);
 	}
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
index 7a2f330a3..6224afcd8 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -28,7 +28,7 @@
 
 void *switch_to_tt(void *prev, void *next, void *last)
 {
-	struct task_struct *from, *to;
+	struct task_struct *from, *to, *prev_sched;
 	unsigned long flags;
 	int err, vtalrm, alrm, prof, cpu;
 	char c;
@@ -62,7 +62,7 @@ void *switch_to_tt(void *prev, void *next, void *last)
 	reading = 0;
 	err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c));
 	if(err != sizeof(c))
-		panic("write of switch_pipe failed, errno = %d", -err);
+		panic("write of switch_pipe failed, err = %d", -err);
 
 	reading = 1;
 	if((from->state == TASK_ZOMBIE) || (from->state == TASK_DEAD))
@@ -72,6 +72,18 @@ void *switch_to_tt(void *prev, void *next, void *last)
 	if(err != sizeof(c))
 		panic("read of switch_pipe failed, errno = %d", -err);
 
+	/* If the process that we have just scheduled away from has exited,
+	 * then it needs to be killed here.  The reason is that, even though
+	 * it will kill itself when it next runs, that may be too late.  Its
+	 * stack will be freed, possibly before then, and if that happens,
+	 * we have a use-after-free situation.  So, it gets killed here
+	 * in case it has not already killed itself.
+	 */
+	prev_sched = current->thread.prev_sched;
+	if((prev_sched->state == TASK_ZOMBIE) ||
+	   (prev_sched->state == TASK_DEAD))
+		os_kill_process(prev_sched->thread.mode.tt.extern_pid, 1);
+
 	/* This works around a nasty race with 'jail'.  If we are switching
 	 * between two threads of a threaded app and the incoming process 
 	 * runs before the outgoing process reaches the read, and it makes
@@ -104,50 +116,92 @@ void *switch_to_tt(void *prev, void *next, void *last)
 
 void release_thread_tt(struct task_struct *task)
 {
-	os_kill_process(task->thread.mode.tt.extern_pid, 0);
+	int pid = task->thread.mode.tt.extern_pid;
+
+	if(os_getpid() != pid)
+		os_kill_process(pid, 0);
 }
 
 void exit_thread_tt(void)
 {
-	close(current->thread.mode.tt.switch_pipe[0]);
-	close(current->thread.mode.tt.switch_pipe[1]);
+	os_close_file(current->thread.mode.tt.switch_pipe[0]);
+	os_close_file(current->thread.mode.tt.switch_pipe[1]);
+}
+
+void suspend_new_thread(int fd)
+{
+	int err;
+	char c;
+
+	os_stop_process(os_getpid());
+	err = os_read_file(fd, &c, sizeof(c));
+	if(err != sizeof(c))
+		panic("read failed in suspend_new_thread, err = %d", -err);
 }
 
 void schedule_tail(task_t *prev);
 
 static void new_thread_handler(int sig)
 {
+	unsigned long disable;
 	int (*fn)(void *);
 	void *arg;
 
 	fn = current->thread.request.u.thread.proc;
 	arg = current->thread.request.u.thread.arg;
+
 	UPT_SC(&current->thread.regs.regs) = (void *) (&sig + 1);
+	disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) |
+		(1 << (SIGIO - 1)) | (1 << (SIGPROF - 1));
+	SC_SIGMASK(UPT_SC(&current->thread.regs.regs)) &= ~disable;
+
 	suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
 
-	block_signals();
+	force_flush_all();
+	if(current->thread.prev_sched != NULL)
+		schedule_tail(current->thread.prev_sched);
+	current->thread.prev_sched = NULL;
+
 	init_new_thread_signals(1);
-#ifdef CONFIG_SMP
-	schedule_tail(current->thread.prev_sched);
-#endif
 	enable_timer();
 	free_page(current->thread.temp_stack);
 	set_cmdline("(kernel thread)");
-	force_flush_all();
 
-	current->thread.prev_sched = NULL;
 	change_sig(SIGUSR1, 1);
 	change_sig(SIGVTALRM, 1);
 	change_sig(SIGPROF, 1);
-	unblock_signals();
+	local_irq_enable();
 	if(!run_kernel_thread(fn, arg, &current->thread.exec_buf))
 		do_exit(0);
+
+	/* XXX No set_user_mode here because a newly execed process will
+	 * immediately segfault on its non-existent IP, coming straight back
+	 * to the signal handler, which will call set_user_mode on its way
+	 * out.  This should probably change since it's confusing.
+	 */
 }
 
 static int new_thread_proc(void *stack)
 {
+	/* local_irq_disable is needed to block out signals until this thread is
+	 * properly scheduled.  Otherwise, the tracing thread will get mighty
+	 * upset about any signals that arrive before that.
+	 * This has the complication that it sets the saved signal mask in
+	 * the sigcontext to block signals.  This gets restored when this
+	 * thread (or a descendant, since they get a copy of this sigcontext)
+	 * returns to userspace.
+	 * So, this is compensated for elsewhere.
+	 * XXX There is still a small window until local_irq_disable() actually
+	 * finishes where signals are possible - shouldn't be a problem in
+	 * practice since SIGIO hasn't been forwarded here yet, and the
+	 * local_irq_disable should finish before a SIGVTALRM has time to be
+	 * delivered.
+	 */
+
+	local_irq_disable();
 	init_new_thread_stack(stack, new_thread_handler);
 	os_usr1_process(os_getpid());
+	change_sig(SIGUSR1, 1);
 	return(0);
 }
 
@@ -156,7 +210,7 @@ static int new_thread_proc(void *stack)
  * itself with a SIGUSR1.  set_user_mode has to be run with SIGUSR1 off,
  * so it is blocked before it's called.  They are re-enabled on sigreturn
  * despite the fact that they were blocked when the SIGUSR1 was issued because
- * copy_thread copies the parent's signcontext, including the signal mask
+ * copy_thread copies the parent's sigcontext, including the signal mask
  * onto the signal frame.
  */
 
@@ -165,35 +219,33 @@ void finish_fork_handler(int sig)
  	UPT_SC(&current->thread.regs.regs) = (void *) (&sig + 1);
 	suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
 
-#ifdef CONFIG_SMP	
-	schedule_tail(NULL);
-#endif
+	force_flush_all();
+	if(current->thread.prev_sched != NULL)
+		schedule_tail(current->thread.prev_sched);
+	current->thread.prev_sched = NULL;
+
 	enable_timer();
 	change_sig(SIGVTALRM, 1);
 	local_irq_enable();
-	force_flush_all();
 	if(current->mm != current->parent->mm)
 		protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 
 			       1, 0, 1);
-	task_protections((unsigned long) current->thread_info);
-
-	current->thread.prev_sched = NULL;
+	task_protections((unsigned long) current_thread);
 
 	free_page(current->thread.temp_stack);
+	local_irq_disable();
 	change_sig(SIGUSR1, 0);
 	set_user_mode(current);
 }
 
-static int sigusr1 = SIGUSR1;
-
 int fork_tramp(void *stack)
 {
-	int sig = sigusr1;
-
 	local_irq_disable();
+	arch_init_thread();
 	init_new_thread_stack(stack, finish_fork_handler);
 
-	kill(os_getpid(), sig);
+	os_usr1_process(os_getpid());
+	change_sig(SIGUSR1, 1);
 	return(0);
 }
 
@@ -213,8 +265,8 @@ int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
 	}
 
 	err = os_pipe(p->thread.mode.tt.switch_pipe, 1, 1);
-	if(err){
-		printk("copy_thread : pipe failed, errno = %d\n", -err);
+	if(err < 0){
+		printk("copy_thread : pipe failed, err = %d\n", -err);
 		return(err);
 	}
 
@@ -227,8 +279,7 @@ int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
 
 	clone_flags &= CLONE_VM;
 	p->thread.temp_stack = stack;
-	new_pid = start_fork_tramp((void *) p->thread.kernel_stack, stack,
-				   clone_flags, tramp);
+	new_pid = start_fork_tramp(p->thread_info, stack, clone_flags, tramp);
 	if(new_pid < 0){
 		printk(KERN_ERR "copy_thread : clone failed - errno = %d\n", 
 		       -new_pid);
@@ -246,19 +297,30 @@ int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
 	current->thread.request.op = OP_FORK;
 	current->thread.request.u.fork.pid = new_pid;
 	os_usr1_process(os_getpid());
-	return(0);
+
+	/* Enable the signal and then disable it to ensure that it is handled
+	 * here, and nowhere else.
+	 */
+	change_sig(SIGUSR1, 1);
+
+	change_sig(SIGUSR1, 0);
+	err = 0;
+ out:
+	return(err);
 }
 
 void reboot_tt(void)
 {
 	current->thread.request.op = OP_REBOOT;
 	os_usr1_process(os_getpid());
+	change_sig(SIGUSR1, 1);
 }
 
 void halt_tt(void)
 {
 	current->thread.request.op = OP_HALT;
 	os_usr1_process(os_getpid());
+	change_sig(SIGUSR1, 1);
 }
 
 void kill_off_processes_tt(void)
@@ -285,6 +347,9 @@ void initial_thread_cb_tt(void (*proc)(void *), void *arg)
 		current->thread.request.u.cb.proc = proc;
 		current->thread.request.u.cb.arg = arg;
 		os_usr1_process(os_getpid());
+		change_sig(SIGUSR1, 1);
+
+		change_sig(SIGUSR1, 0);
 	}
 }
 
@@ -377,8 +442,8 @@ static void mprotect_kernel_mem(int w)
 
 	pages = (1 << CONFIG_KERNEL_STACK_ORDER);
 
-	start = (unsigned long) current->thread_info + PAGE_SIZE;
-	end = (unsigned long) current + PAGE_SIZE * pages;
+	start = (unsigned long) current_thread + PAGE_SIZE;
+	end = (unsigned long) current_thread + PAGE_SIZE * pages;
 	protect_memory(uml_reserved, start - uml_reserved, 1, w, 1, 1);
 	protect_memory(end, high_physmem - end, 1, w, 1, 1);
 
@@ -454,8 +519,9 @@ void set_init_pid(int pid)
 
 	init_task.thread.mode.tt.extern_pid = pid;
 	err = os_pipe(init_task.thread.mode.tt.switch_pipe, 1, 1);
-	if(err)	panic("Can't create switch pipe for init_task, errno = %d", 
-		      err);
+	if(err)
+		panic("Can't create switch pipe for init_task, errno = %d",
+		      -err);
 }
 
 int singlestepping_tt(void *t)
@@ -479,9 +545,9 @@ int start_uml_tt(void)
 	void *sp;
 	int pages;
 
-	pages = (1 << CONFIG_KERNEL_STACK_ORDER) - 2;
-	sp = (void *) init_task.thread.kernel_stack + pages * PAGE_SIZE - 
-		sizeof(unsigned long);
+	pages = (1 << CONFIG_KERNEL_STACK_ORDER);
+	sp = (void *) ((unsigned long) init_task.thread_info) +
+		pages * PAGE_SIZE - sizeof(unsigned long);
 	return(tracer(start_kernel_proc, sp));
 }
 
diff --git a/arch/um/kernel/tt/ptproxy/Makefile b/arch/um/kernel/tt/ptproxy/Makefile
index 97d4f0bc1..9f9daf5c1 100644
--- a/arch/um/kernel/tt/ptproxy/Makefile
+++ b/arch/um/kernel/tt/ptproxy/Makefile
@@ -9,5 +9,3 @@ USER_OBJS := $(foreach file,$(obj-y),$(src)/$(file))
 
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean:
diff --git a/arch/um/kernel/tt/ptproxy/proxy.c b/arch/um/kernel/tt/ptproxy/proxy.c
index 65504f8c6..458ecf9a4 100644
--- a/arch/um/kernel/tt/ptproxy/proxy.c
+++ b/arch/um/kernel/tt/ptproxy/proxy.c
@@ -15,7 +15,6 @@ Jeff Dike (jdike@karaya.com) : Modified for integration into uml
 #include <unistd.h>
 #include <signal.h>
 #include <string.h>
-#include <fcntl.h>
 #include <termios.h>
 #include <sys/wait.h>
 #include <sys/types.h>
@@ -273,7 +272,7 @@ void fake_child_exit(void)
 
 	child_proxy(1, W_EXITCODE(0, 0));
 	while(debugger.waiting == 1){
-		pid = waitpid(debugger.pid, &status, WUNTRACED);
+		CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED));
 		if(pid != debugger.pid){
 			printk("fake_child_exit - waitpid failed, "
 			       "errno = %d\n", errno);
@@ -281,7 +280,7 @@ void fake_child_exit(void)
 		}
 		debugger_proxy(status, debugger.pid);
 	}
-	pid = waitpid(debugger.pid, &status, WUNTRACED);
+	CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED));
 	if(pid != debugger.pid){
 		printk("fake_child_exit - waitpid failed, "
 		       "errno = %d\n", errno);
@@ -293,10 +292,10 @@ void fake_child_exit(void)
 }
 
 char gdb_init_string[] = 
-"att 1
-b panic
-b stop
-handle SIGWINCH nostop noprint pass
+"att 1 \n\
+b panic \n\
+b stop \n\
+handle SIGWINCH nostop noprint pass \n\
 ";
 
 int start_debugger(char *prog, int startup, int stop, int *fd_out)
@@ -304,7 +303,8 @@ int start_debugger(char *prog, int startup, int stop, int *fd_out)
 	int slave, child;
 
 	slave = open_gdb_chan();
-	if((child = fork()) == 0){
+	child = fork();
+	if(child == 0){
 		char *tempname = NULL;
 		int fd;
 
@@ -327,18 +327,19 @@ int start_debugger(char *prog, int startup, int stop, int *fd_out)
 			exit(1);
 #endif
 		}
-		if((fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0)) < 0){
-			printk("start_debugger : make_tempfile failed, errno = %d\n",
-			       errno);
+		fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0);
+		if(fd < 0){
+			printk("start_debugger : make_tempfile failed,"
+			       "err = %d\n", -fd);
 			exit(1);
 		}
-		write(fd, gdb_init_string, sizeof(gdb_init_string) - 1);
+		os_write_file(fd, gdb_init_string, sizeof(gdb_init_string) - 1);
 		if(startup){
 			if(stop){
-				write(fd, "b start_kernel\n",
+				os_write_file(fd, "b start_kernel\n",
 				      strlen("b start_kernel\n"));
 			}
-			write(fd, "c\n", strlen("c\n"));
+			os_write_file(fd, "c\n", strlen("c\n"));
 		}
 		if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){
 			printk("start_debugger :  PTRACE_TRACEME failed, "
diff --git a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c
index 50a120d5e..c42855aed 100644
--- a/arch/um/kernel/tt/ptproxy/sysdep.c
+++ b/arch/um/kernel/tt/ptproxy/sysdep.c
@@ -9,6 +9,7 @@ terms and conditions.
 #include <string.h>
 #include <stdlib.h>
 #include <signal.h>
+#include <errno.h>
 #include <sys/types.h>
 #include <sys/ptrace.h>
 #include <asm/ptrace.h>
diff --git a/arch/um/kernel/tt/ptproxy/wait.c b/arch/um/kernel/tt/ptproxy/wait.c
index aad7e4b62..86ef67653 100644
--- a/arch/um/kernel/tt/ptproxy/wait.c
+++ b/arch/um/kernel/tt/ptproxy/wait.c
@@ -56,21 +56,23 @@ int parent_wait_return(struct debugger *debugger, pid_t unused)
 int real_wait_return(struct debugger *debugger)
 {
 	unsigned long ip;
-	int err, pid;
+	int pid;
 
 	pid = debugger->pid;
+
 	ip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0);
-	ip = IP_RESTART_SYSCALL(ip);
-	err = ptrace(PTRACE_POKEUSER, pid, PT_IP_OFFSET, ip);
+	IP_RESTART_SYSCALL(ip);
+
 	if(ptrace(PTRACE_POKEUSER, pid, PT_IP_OFFSET, ip) < 0)
 		tracer_panic("real_wait_return : Failed to restart system "
-			     "call, errno = %d\n");
+			     "call, errno = %d\n", errno);
+
 	if((ptrace(PTRACE_SYSCALL, debugger->pid, 0, SIGCHLD) < 0) ||
 	   (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) ||
 	   (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) ||
 	   debugger_normal_return(debugger, -1))
 		tracer_panic("real_wait_return : gdb failed to wait, "
-			     "errno = %d\n");
+			     "errno = %d\n", errno);
 	return(0);
 }
 
diff --git a/arch/um/kernel/tt/sys-i386/Makefile b/arch/um/kernel/tt/sys-i386/Makefile
index 2ad8271c6..3eeea057c 100644
--- a/arch/um/kernel/tt/sys-i386/Makefile
+++ b/arch/um/kernel/tt/sys-i386/Makefile
@@ -10,5 +10,3 @@ USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
 
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean :
diff --git a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c
index 1b71f9ce5..555ffd0ee 100644
--- a/arch/um/kernel/tt/syscall_kern.c
+++ b/arch/um/kernel/tt/syscall_kern.c
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
diff --git a/arch/um/kernel/tt/syscall_user.c b/arch/um/kernel/tt/syscall_user.c
index f7c845d99..1cabbd866 100644
--- a/arch/um/kernel/tt/syscall_user.c
+++ b/arch/um/kernel/tt/syscall_user.c
@@ -33,7 +33,7 @@ void syscall_handler_tt(int sig, union uml_pt_regs *regs)
 	SC_START_SYSCALL(sc);
 
 	index = record_syscall_start(syscall);
-	syscall_trace();
+	syscall_trace(regs, 1);
 	result = execute_syscall(regs);
 
 	/* regs->sc may have changed while the system call ran (there may
@@ -46,7 +46,7 @@ void syscall_handler_tt(int sig, union uml_pt_regs *regs)
 	   (result == -ERESTARTNOINTR))
 		do_signal(result);
 
-	syscall_trace();
+	syscall_trace(regs, 0);
 	record_syscall_end(index, result);
 }
 
diff --git a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c
index 32ac316de..d8ad334cf 100644
--- a/arch/um/kernel/tt/tlb.c
+++ b/arch/um/kernel/tt/tlb.c
@@ -10,6 +10,7 @@
 #include "asm/page.h"
 #include "asm/pgtable.h"
 #include "asm/uaccess.h"
+#include "asm/tlbflush.h"
 #include "user_util.h"
 #include "mem_user.h"
 #include "os.h"
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c
index 6a6322a3e..deef43bb5 100644
--- a/arch/um/kernel/tt/tracer.c
+++ b/arch/um/kernel/tt/tracer.c
@@ -39,16 +39,17 @@ int is_tracer_winch(int pid, int fd, void *data)
 		return(0);
 
 	register_winch_irq(tracer_winch[0], fd, -1, data);
-	return(0);
+	return(1);
 }
 
 static void tracer_winch_handler(int sig)
 {
+	int n;
 	char c = 1;
 
-	if(write(tracer_winch[1], &c, sizeof(c)) != sizeof(c))
-		printk("tracer_winch_handler - write failed, errno = %d\n",
-		       errno);
+	n = os_write_file(tracer_winch[1], &c, sizeof(c));
+	if(n != sizeof(c))
+		printk("tracer_winch_handler - write failed, err = %d\n", -n);
 }
 
 /* Called only by the tracing thread during initialization */
@@ -58,9 +59,8 @@ static void setup_tracer_winch(void)
 	int err;
 
 	err = os_pipe(tracer_winch, 1, 1);
-	if(err){
-		printk("setup_tracer_winch : os_pipe failed, errno = %d\n", 
-		       -err);
+	if(err < 0){
+		printk("setup_tracer_winch : os_pipe failed, err = %d\n", -err);
 		return;
 	}
 	signal(SIGWINCH, tracer_winch_handler);
@@ -130,8 +130,8 @@ static void sleeping_process_signal(int pid, int sig)
 	case SIGTSTP:
 		if(ptrace(PTRACE_CONT, pid, 0, sig) < 0)
 			tracer_panic("sleeping_process_signal : Failed to "
-				     "continue pid %d, errno = %d\n", pid,
-				     sig);
+				     "continue pid %d, signal = %d, "
+				     "errno = %d\n", pid, sig, errno);
 		break;
 
 	/* This happens when the debugger (e.g. strace) is doing system call 
@@ -145,7 +145,7 @@ static void sleeping_process_signal(int pid, int sig)
 		if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
 			tracer_panic("sleeping_process_signal : Failed to "
 				     "PTRACE_SYSCALL pid %d, errno = %d\n",
-				     pid, sig);
+				     pid, errno);
 		break;
 	case SIGSTOP:
 		break;
@@ -192,7 +192,7 @@ int tracer(int (*init_proc)(void *), void *sp)
 	printf("tracing thread pid = %d\n", tracing_pid);
 
 	pid = clone(signal_tramp, sp, CLONE_FILES | SIGCHLD, init_proc);
-	n = waitpid(pid, &status, WUNTRACED);
+	CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
 	if(n < 0){
 		printf("waitpid on idle thread failed, errno = %d\n", errno);
 		exit(1);
@@ -218,7 +218,7 @@ int tracer(int (*init_proc)(void *), void *sp)
 			err = attach(debugger_parent);
 			if(err){
 				printf("Failed to attach debugger parent %d, "
-				       "errno = %d\n", debugger_parent, err);
+				       "errno = %d\n", debugger_parent, -err);
 				debugger_parent = -1;
 			}
 			else {
@@ -233,7 +233,8 @@ int tracer(int (*init_proc)(void *), void *sp)
 	}
 	set_cmdline("(tracing thread)");
 	while(1){
-		if((pid = waitpid(-1, &status, WUNTRACED)) <= 0){
+		CATCH_EINTR(pid = waitpid(-1, &status, WUNTRACED));
+		if(pid <= 0){
 			if(errno != ECHILD){
 				printf("wait failed - errno = %d\n", errno);
 			}
@@ -329,7 +330,8 @@ int tracer(int (*init_proc)(void *), void *sp)
 					continue;
 				}
 				tracing = 0;
-				if(do_syscall(task, pid)) sig = SIGUSR2;
+				if(do_syscall(task, pid))
+					sig = SIGUSR2;
 				else clear_singlestep(task);
 				break;
 			case SIGPROF:
@@ -401,7 +403,7 @@ static int __init uml_debug_setup(char *line, int *add)
 		
 		if(!strcmp(line, "go"))	debug_stop = 0;
 		else if(!strcmp(line, "parent")) debug_parent = 1;
-		else printk("Unknown debug option : '%s'\n", line);
+		else printf("Unknown debug option : '%s'\n", line);
 
 		line = next;
 	}
diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c
index 7a6dbf5f9..00bacacfc 100644
--- a/arch/um/kernel/tt/trap_user.c
+++ b/arch/um/kernel/tt/trap_user.c
@@ -23,6 +23,13 @@ void sig_handler_common_tt(int sig, void *sc_ptr)
 
 	unprotect_kernel_mem();
 
+	/* This is done because to allow SIGSEGV to be delivered inside a SEGV
+	 * handler.  This can happen in copy_user, and if SEGV is disabled,
+	 * the process will die.
+	 */
+	if(sig == SIGSEGV)
+		change_sig(SIGSEGV, 1);
+
 	r = &TASK_REGS(get_current())->tt;
 	save_regs = *r;
 	is_user = user_context(SC_SP(sc));
@@ -30,7 +37,6 @@ void sig_handler_common_tt(int sig, void *sc_ptr)
 	if(sig != SIGUSR2) 
 		r->syscall = -1;
 
-	change_sig(SIGUSR1, 1);
 	info = &sig_info[sig];
 	if(!info->is_irq) unblock_signals();
 
@@ -39,7 +45,6 @@ void sig_handler_common_tt(int sig, void *sc_ptr)
 	if(is_user){
 		interrupt_end();
 		block_signals();
-		change_sig(SIGUSR1, 0);
 		set_user_mode(NULL);
 	}
 	*r = save_regs;
diff --git a/arch/um/kernel/tt/uaccess.c b/arch/um/kernel/tt/uaccess.c
index 9c8401120..040971893 100644
--- a/arch/um/kernel/tt/uaccess.c
+++ b/arch/um/kernel/tt/uaccess.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
@@ -8,7 +8,7 @@
 
 int copy_from_user_tt(void *to, const void *from, int n)
 {
-	if(!access_ok_tt(VERIFY_READ, from, n)) 
+	if(!access_ok_tt(VERIFY_READ, from, n))
 		return(n);
 
 	return(__do_copy_from_user(to, from, n, &current->thread.fault_addr,
@@ -19,7 +19,7 @@ int copy_to_user_tt(void *to, const void *from, int n)
 {
 	if(!access_ok_tt(VERIFY_WRITE, to, n))
 		return(n);
-		
+
 	return(__do_copy_to_user(to, from, n, &current->thread.fault_addr,
 				 &current->thread.fault_catcher));
 }
@@ -28,10 +28,10 @@ int strncpy_from_user_tt(char *dst, const char *src, int count)
 {
 	int n;
 
-	if(!access_ok_tt(VERIFY_READ, src, 1)) 
+	if(!access_ok_tt(VERIFY_READ, src, 1))
 		return(-EFAULT);
 
-	n = __do_strncpy_from_user(dst, src, count, 
+	n = __do_strncpy_from_user(dst, src, count,
 				   &current->thread.fault_addr,
 				   &current->thread.fault_catcher);
 	if(n < 0) return(-EFAULT);
diff --git a/arch/um/kernel/tt/uaccess_user.c b/arch/um/kernel/tt/uaccess_user.c
index 537ee9fba..f01475512 100644
--- a/arch/um/kernel/tt/uaccess_user.c
+++ b/arch/um/kernel/tt/uaccess_user.c
@@ -8,15 +8,20 @@
 #include <string.h>
 #include "user_util.h"
 #include "uml_uaccess.h"
+#include "task.h"
+#include "kern_util.h"
 
 int __do_copy_from_user(void *to, const void *from, int n,
 			void **fault_addr, void **fault_catcher)
 {
+	struct tt_regs save = TASK_REGS(get_current())->tt;
 	unsigned long fault;
 	int faulted;
 
 	fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
 			       __do_copy, &faulted);
+	TASK_REGS(get_current())->tt = save;
+
 	if(!faulted) return(0);
 	else return(n - (fault - (unsigned long) from));
 }
@@ -29,11 +34,14 @@ static void __do_strncpy(void *dst, const void *src, int count)
 int __do_strncpy_from_user(char *dst, const char *src, unsigned long count,
 			   void **fault_addr, void **fault_catcher)
 {
+	struct tt_regs save = TASK_REGS(get_current())->tt;
 	unsigned long fault;
 	int faulted;
 
 	fault = __do_user_copy(dst, src, count, fault_addr, fault_catcher,
 			       __do_strncpy, &faulted);
+	TASK_REGS(get_current())->tt = save;
+
 	if(!faulted) return(strlen(dst));
 	else return(-1);
 }
@@ -46,11 +54,14 @@ static void __do_clear(void *to, const void *from, int n)
 int __do_clear_user(void *mem, unsigned long len,
 		    void **fault_addr, void **fault_catcher)
 {
+	struct tt_regs save = TASK_REGS(get_current())->tt;
 	unsigned long fault;
 	int faulted;
 
 	fault = __do_user_copy(mem, NULL, len, fault_addr, fault_catcher,
 			       __do_clear, &faulted);
+	TASK_REGS(get_current())->tt = save;
+
 	if(!faulted) return(0);
 	else return(len - (fault - (unsigned long) mem));
 }
@@ -58,19 +69,20 @@ int __do_clear_user(void *mem, unsigned long len,
 int __do_strnlen_user(const char *str, unsigned long n,
 		      void **fault_addr, void **fault_catcher)
 {
+	struct tt_regs save = TASK_REGS(get_current())->tt;
 	int ret;
 	unsigned long *faddrp = (unsigned long *)fault_addr;
-	jmp_buf jbuf;
+	sigjmp_buf jbuf;
 
 	*fault_catcher = &jbuf;
-	if(setjmp(jbuf) == 0){
+	if(sigsetjmp(jbuf, 1) == 0)
 		ret = strlen(str) + 1;
-	} 
-	else {
-		ret = *faddrp - (unsigned long) str;
-	}
+	else ret = *faddrp - (unsigned long) str;
+
 	*fault_addr = NULL;
 	*fault_catcher = NULL;
+
+	TASK_REGS(get_current())->tt = save;
 	return ret;
 }
 
diff --git a/arch/um/kernel/tt/unmap.c b/arch/um/kernel/tt/unmap.c
index 36d3e6992..3f7aecdbe 100644
--- a/arch/um/kernel/tt/unmap.c
+++ b/arch/um/kernel/tt/unmap.c
@@ -3,10 +3,7 @@
  * Licensed under the GPL
  */
 
-#include <stdio.h>
-#include <errno.h>
 #include <sys/mman.h>
-#include "user.h"
 
 int switcheroo(int fd, int prot, void *from, void *to, int size)
 {
diff --git a/arch/um/kernel/tty_log.c b/arch/um/kernel/tty_log.c
index 61c4cc3af..0a70c5e66 100644
--- a/arch/um/kernel/tty_log.c
+++ b/arch/um/kernel/tty_log.c
@@ -9,10 +9,10 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <fcntl.h>
 #include <sys/time.h>
 #include "init.h"
 #include "user.h"
+#include "kern_util.h"
 #include "os.h"
 
 #define TTY_LOG_DIR "./"
@@ -24,29 +24,40 @@ static int tty_log_fd = -1;
 #define TTY_LOG_OPEN 1
 #define TTY_LOG_CLOSE 2
 #define TTY_LOG_WRITE 3
+#define TTY_LOG_EXEC 4
+
+#define TTY_READ 1
+#define TTY_WRITE 2
 
 struct tty_log_buf {
 	int what;
 	unsigned long tty;
 	int len;
+	int direction;
+	unsigned long sec;
+	unsigned long usec;
 };
 
-int open_tty_log(void *tty)
+int open_tty_log(void *tty, void *current_tty)
 {
 	struct timeval tv;
 	struct tty_log_buf data;
 	char buf[strlen(tty_log_dir) + sizeof("01234567890-01234567\0")];
 	int fd;
 
+	gettimeofday(&tv, NULL);
 	if(tty_log_fd != -1){
-		data = ((struct tty_log_buf) { what :	TTY_LOG_OPEN,
-					       tty : (unsigned long) tty,
-					       len : 0 });
-		write(tty_log_fd, &data, sizeof(data));
+		data = ((struct tty_log_buf) { .what 	= TTY_LOG_OPEN,
+					       .tty  = (unsigned long) tty,
+					       .len  = sizeof(current_tty),
+					       .direction = 0,
+					       .sec = tv.tv_sec,
+					       .usec = tv.tv_usec } );
+		os_write_file(tty_log_fd, &data, sizeof(data));
+		os_write_file(tty_log_fd, &current_tty, data.len);
 		return(tty_log_fd);
 	}
 
-	gettimeofday(&tv, NULL);
 	sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec, 
  		(unsigned int) tv.tv_usec);
 
@@ -62,30 +73,117 @@ int open_tty_log(void *tty)
 void close_tty_log(int fd, void *tty)
 {
 	struct tty_log_buf data;
+	struct timeval tv;
 
 	if(tty_log_fd != -1){
-		data = ((struct tty_log_buf) { what :	TTY_LOG_CLOSE,
-					       tty : (unsigned long) tty,
-					       len : 0 });
-		write(tty_log_fd, &data, sizeof(data));
+		gettimeofday(&tv, NULL);
+		data = ((struct tty_log_buf) { .what 	= TTY_LOG_CLOSE,
+					       .tty  = (unsigned long) tty,
+					       .len  = 0,
+					       .direction = 0,
+					       .sec = tv.tv_sec,
+					       .usec = tv.tv_usec } );
+		os_write_file(tty_log_fd, &data, sizeof(data));
 		return;
 	}
-	close(fd);
+	os_close_file(fd);
 }
 
-int write_tty_log(int fd, char *buf, int len, void *tty)
+static int log_chunk(int fd, const char *buf, int len)
 {
+	int total = 0, try, missed, n;
+	char chunk[64];
+
+	while(len > 0){
+		try = (len > sizeof(chunk)) ? sizeof(chunk) : len;
+		missed = copy_from_user_proc(chunk, (char *) buf, try);
+		try -= missed;
+		n = os_write_file(fd, chunk, try);
+		if(n != try) {
+			if(n < 0)
+				return(n);
+			return(-EIO);
+		}
+		if(missed != 0)
+			return(-EFAULT);
+
+		len -= try;
+		total += try;
+		buf += try;
+	}
+
+	return(total);
+}
+
+int write_tty_log(int fd, const char *buf, int len, void *tty, int is_read)
+{
+	struct timeval tv;
 	struct tty_log_buf data;
+	int direction;
 
 	if(fd == tty_log_fd){
-		data = ((struct tty_log_buf) { what :	TTY_LOG_WRITE,
-					       tty : (unsigned long) tty,
-					       len : len });
-		write(tty_log_fd, &data, sizeof(data));
+		gettimeofday(&tv, NULL);
+		direction = is_read ? TTY_READ : TTY_WRITE;
+		data = ((struct tty_log_buf) { .what 	= TTY_LOG_WRITE,
+					       .tty  = (unsigned long) tty,
+					       .len  = len,
+					       .direction = direction,
+					       .sec = tv.tv_sec,
+					       .usec = tv.tv_usec } );
+		os_write_file(tty_log_fd, &data, sizeof(data));
 	}
-	return(write(fd, buf, len));
+
+	return(log_chunk(fd, buf, len));
 }
 
+void log_exec(char **argv, void *tty)
+{
+	struct timeval tv;
+	struct tty_log_buf data;
+	char **ptr,*arg;
+	int len;
+
+	if(tty_log_fd == -1) return;
+
+	gettimeofday(&tv, NULL);
+
+	len = 0;
+	for(ptr = argv; ; ptr++){
+		if(copy_from_user_proc(&arg, ptr, sizeof(arg)))
+			return;
+		if(arg == NULL) break;
+		len += strlen_user_proc(arg);
+	}
+
+	data = ((struct tty_log_buf) { .what 	= TTY_LOG_EXEC,
+				       .tty  = (unsigned long) tty,
+				       .len  = len,
+				       .direction = 0,
+				       .sec = tv.tv_sec,
+				       .usec = tv.tv_usec } );
+	os_write_file(tty_log_fd, &data, sizeof(data));
+
+	for(ptr = argv; ; ptr++){
+		if(copy_from_user_proc(&arg, ptr, sizeof(arg)))
+			return;
+		if(arg == NULL) break;
+		log_chunk(tty_log_fd, arg, strlen_user_proc(arg));
+	}
+}
+
+extern void register_tty_logger(int (*opener)(void *, void *),
+				int (*writer)(int, const char *, int,
+					      void *, int),
+				void (*closer)(int, void *));
+
+static int register_logger(void)
+{
+	register_tty_logger(open_tty_log, write_tty_log, close_tty_log);
+	return(0);
+}
+
+__uml_initcall(register_logger);
+
 static int __init set_tty_log_dir(char *name, int *add)
 {
 	tty_log_dir = name;
@@ -104,7 +202,7 @@ static int __init set_tty_log_fd(char *name, int *add)
 
 	tty_log_fd = strtoul(name, &end, 0);
 	if((*end != '\0') || (end == name)){
-		printk("set_tty_log_fd - strtoul failed on '%s'\n", name);
+		printf("set_tty_log_fd - strtoul failed on '%s'\n", name);
 		tty_log_fd = -1;
 	}
 	return 0;
diff --git a/arch/um/kernel/uaccess_user.c b/arch/um/kernel/uaccess_user.c
index eb9be24ce..d035257ed 100644
--- a/arch/um/kernel/uaccess_user.c
+++ b/arch/um/kernel/uaccess_user.c
@@ -18,9 +18,9 @@ unsigned long __do_user_copy(void *to, const void *from, int n,
 {
 	unsigned long *faddrp = (unsigned long *) fault_addr, ret;
 
-	jmp_buf jbuf;
+	sigjmp_buf jbuf;
 	*fault_catcher = &jbuf;
-	if(setjmp(jbuf) == 0){
+	if(sigsetjmp(jbuf, 1) == 0){
 		(*op)(to, from, n);
 		ret = 0;
 		*faulted_out = 0;
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index e8f0cacc1..9146c11e5 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -27,7 +27,6 @@
 #include "user_util.h"
 #include "kern_util.h"
 #include "kern.h"
-#include "mprot.h"
 #include "mem_user.h"
 #include "mem.h"
 #include "umid.h"
@@ -38,13 +37,18 @@
 #include "mode_kern.h"
 #include "mode.h"
 
-#define DEFAULT_COMMAND_LINE "root=6200"
+#define DEFAULT_COMMAND_LINE "root=98:0"
 
 struct cpuinfo_um boot_cpu_data = { 
 	.loops_per_jiffy	= 0,
 	.ipi_pipe		= { -1, -1 }
 };
 
+/* Placeholder to make UML link until the vsyscall stuff is actually
+ * implemented
+ */
+void *__kernel_vsyscall;
+
 unsigned long thread_saved_pc(struct task_struct *task)
 {
 	return(os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas,
@@ -53,18 +57,22 @@ unsigned long thread_saved_pc(struct task_struct *task)
 
 static int show_cpuinfo(struct seq_file *m, void *v)
 {
-	int index;
+	int index = 0;
 
-	index = (struct cpuinfo_um *)v - cpu_data;
 #ifdef CONFIG_SMP
+	index = (struct cpuinfo_um *) v - cpu_data;
 	if (!cpu_online(index))
 		return 0;
 #endif
 
-	seq_printf(m, "bogomips\t: %lu.%02lu\n",
+	seq_printf(m, "processor\t: %d\n", index);
+	seq_printf(m, "vendor_id\t: User Mode Linux\n");
+	seq_printf(m, "model name\t: UML\n");
+	seq_printf(m, "mode\t\t: %s\n", CHOOSE_MODE("tt", "skas"));
+	seq_printf(m, "host\t\t: %s\n", host_info);
+	seq_printf(m, "bogomips\t: %lu.%02lu\n\n",
 		   loops_per_jiffy/(500000/HZ),
 		   (loops_per_jiffy/(5000/HZ)) % 100);
-	seq_printf(m, "host\t\t: %s\n", host_info);
 
 	return(0);
 }
@@ -134,12 +142,12 @@ void set_cmdline(char *cmd)
 	if(umid != NULL){
 		snprintf(argv1_begin, 
 			 (argv1_end - argv1_begin) * sizeof(*ptr), 
-			 "(%s)", umid);
+			 "(%s) ", umid);
 		ptr = &argv1_begin[strlen(argv1_begin)];
 	}
 	else ptr = argv1_begin;
 
-	snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), " [%s]", cmd);
+	snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), "[%s]", cmd);
 	memset(argv1_begin + strlen(argv1_begin), '\0', 
 	       argv1_end - argv1_begin - strlen(argv1_begin));
 #endif
@@ -179,7 +187,7 @@ __uml_setup("root=", uml_root_setup,
 static int __init uml_ncpus_setup(char *line, int *add)
 {
        if (!sscanf(line, "%d", &ncpus)) {
-               printk("Couldn't parse [%s]\n", line);
+               printf("Couldn't parse [%s]\n", line);
                return -1;
        }
 
@@ -210,7 +218,7 @@ static int __init mode_tt_setup(char *line, int *add)
 
 static int __init mode_tt_setup(char *line, int *add)
 {
-	printk("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n");
+	printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n");
 	return(0);
 }
 
@@ -221,7 +229,7 @@ static int __init mode_tt_setup(char *line, int *add)
 
 static int __init mode_tt_setup(char *line, int *add)
 {
-	printk("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n");
+	printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n");
 	return(0);
 }
 
@@ -291,15 +299,15 @@ static void __init uml_postsetup(void)
 
 /* Set during early boot */
 unsigned long brk_start;
-static struct vm_reserved kernel_vm_reserved;
+unsigned long end_iomem;
 
 #define MIN_VMALLOC (32 * 1024 * 1024)
 
 int linux_main(int argc, char **argv)
 {
-	unsigned long avail;
+	unsigned long avail, diff;
 	unsigned long virtmem_size, max_physmem;
-	unsigned int i, add, err;
+	unsigned int i, add;
 
 	for (i = 1; i < argc; i++){
 		if((i == 1) && (argv[i][0] == ' ')) continue;
@@ -315,6 +323,16 @@ int linux_main(int argc, char **argv)
 
 	brk_start = (unsigned long) sbrk(0);
 	CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start);
+	/* Increase physical memory size for exec-shield users
+	so they actually get what they asked for. This should
+	add zero for non-exec shield users */
+
+	diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
+	if(diff > 1024 * 1024){
+		printf("Adding %ld bytes to physical memory to account for "
+		       "exec-shield gap\n", diff);
+		physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end);
+	}
 
 	uml_physmem = uml_start;
 
@@ -328,12 +346,16 @@ int linux_main(int argc, char **argv)
 	argv1_end = &argv[1][strlen(argv[1])];
 #endif
   
-	set_usable_vm(uml_physmem, get_kmem_end());
-
 	highmem = 0;
-	max_physmem = get_kmem_end() - uml_physmem - MIN_VMALLOC;
-	if(physmem_size > max_physmem){
-		highmem = physmem_size - max_physmem;
+	iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
+	max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC;
+
+	/* Zones have to begin on a 1 << MAX_ORDER page boundary,
+	 * so this makes sure that's true for highmem
+	 */
+	max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1);
+	if(physmem_size + iomem_size > max_physmem){
+		highmem = physmem_size + iomem_size - max_physmem;
 		physmem_size -= highmem;
 #ifndef CONFIG_HIGHMEM
 		highmem = 0;
@@ -343,11 +365,19 @@ int linux_main(int argc, char **argv)
 	}
 
 	high_physmem = uml_physmem + physmem_size;
-	high_memory = (void *) high_physmem;
+	end_iomem = high_physmem + iomem_size;
+	high_memory = (void *) end_iomem;
 
 	start_vm = VMALLOC_START;
 
-	setup_physmem(uml_physmem, uml_reserved, physmem_size);
+	setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
+	if(init_maps(physmem_size, iomem_size, highmem)){
+		printf("Failed to allocate mem_map for %ld bytes of physical "
+		       "memory and %ld bytes of highmem\n", physmem_size,
+		       highmem);
+		exit(1);
+	}
+
 	virtmem_size = physmem_size;
 	avail = get_kmem_end() - start_vm;
 	if(physmem_size > avail) virtmem_size = avail;
@@ -357,28 +387,23 @@ int linux_main(int argc, char **argv)
 		printf("Kernel virtual memory size shrunk to %ld bytes\n",
 		       virtmem_size);
 
-	err = reserve_vm(high_physmem, end_vm, &kernel_vm_reserved);
-	if(err){
-		printf("Failed to reserve VM area for kernel VM\n");
-		exit(1);
-	}
-
   	uml_postsetup();
 
-	init_task.thread.kernel_stack = (unsigned long) &init_thread_info + 
-		2 * PAGE_SIZE;
-
 	task_protections((unsigned long) &init_thread_info);
+	os_flush_stdout();
 
 	return(CHOOSE_MODE(start_uml_tt(), start_uml_skas()));
 }
 
+extern int uml_exitcode;
+
 static int panic_exit(struct notifier_block *self, unsigned long unused1,
 		      void *unused2)
 {
 #ifdef CONFIG_MAGIC_SYSRQ
-	handle_sysrq('p', &current->thread.regs, NULL, NULL);
+	handle_sysrq('p', &current->thread.regs, NULL);
 #endif
+	uml_exitcode = 1;
 	machine_halt();
 	return(0);
 }
@@ -403,6 +428,11 @@ void __init check_bugs(void)
 	arch_check_bugs();
 	check_ptrace();
 	check_sigio();
+	check_devanon();
+}
+
+void apply_alternatives(void *start, void *end)
+{
 }
 
 /*
diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c
index 1da1a0d66..78c8dc45c 100644
--- a/arch/um/kernel/umid.c
+++ b/arch/um/kernel/umid.c
@@ -5,7 +5,6 @@
 
 #include <stdio.h>
 #include <unistd.h>
-#include <fcntl.h>
 #include <errno.h>
 #include <string.h>
 #include <stdlib.h>
@@ -33,18 +32,19 @@ static char *uml_dir = UML_DIR;
 static int umid_is_random = 1;
 static int umid_inited = 0;
 
-static int make_umid(void);
+static int make_umid(int (*printer)(const char *fmt, ...));
 
-static int __init set_umid(char *name, int is_random)
+static int __init set_umid(char *name, int is_random,
+			   int (*printer)(const char *fmt, ...))
 {
 	if(umid_inited){
-		printk("Unique machine name can't be set twice\n");
+		(*printer)("Unique machine name can't be set twice\n");
 		return(-1);
 	}
 
 	if(strlen(name) > UMID_LEN - 1)
-		printk("Unique machine name is being truncated to %s "
-		       "characters\n", UMID_LEN);
+		(*printer)("Unique machine name is being truncated to %d "
+			   "characters\n", UMID_LEN);
 	strlcpy(umid, name, sizeof(umid));
 
 	umid_is_random = is_random;
@@ -54,7 +54,7 @@ static int __init set_umid(char *name, int is_random)
 
 static int __init set_umid_arg(char *name, int *add)
 {
-	return(set_umid(name, 0));
+	return(set_umid(name, 0, printf));
 }
 
 __uml_setup("umid=", set_umid_arg,
@@ -67,7 +67,7 @@ int __init umid_file_name(char *name, char *buf, int len)
 {
 	int n;
 
-	if(!umid_inited && make_umid()) return(-1);
+	if(!umid_inited && make_umid(printk)) return(-1);
 
 	n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1;
 	if(n > len){
@@ -85,22 +85,23 @@ static int __init create_pid_file(void)
 {
 	char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
 	char pid[sizeof("nnnnn\0")];
-	int fd;
+	int fd, n;
 
 	if(umid_file_name("pid", file, sizeof(file))) return 0;
 
 	fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))), 
 			  0644);
 	if(fd < 0){
-		printk("Open of machine pid file \"%s\" failed - "
-		       "errno = %d\n", file, -fd);
+		printf("Open of machine pid file \"%s\" failed - "
+		       "err = %d\n", file, -fd);
 		return 0;
 	}
 
 	sprintf(pid, "%d\n", os_getpid());
-	if(write(fd, pid, strlen(pid)) != strlen(pid))
-		printk("Write of pid file failed - errno = %d\n", errno);
-	close(fd);
+	n = os_write_file(fd, pid, strlen(pid));
+	if(n != strlen(pid))
+		printf("Write of pid file failed - err = %d\n", -n);
+	os_close_file(fd);
 	return 0;
 }
 
@@ -111,7 +112,8 @@ static int actually_do_remove(char *dir)
 	int len;
 	char file[256];
 
-	if((directory = opendir(dir)) == NULL){
+	directory = opendir(dir);
+	if(directory == NULL){
 		printk("actually_do_remove : couldn't open directory '%s', "
 		       "errno = %d\n", dir, errno);
 		return(1);
@@ -160,22 +162,24 @@ int not_dead_yet(char *dir)
 {
 	char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
 	char pid[sizeof("nnnnn\0")], *end;
-	int dead, fd, p;
+	int dead, fd, p, n;
 
 	sprintf(file, "%s/pid", dir);
 	dead = 0;
-	if((fd = os_open_file(file, of_read(OPENFLAGS()), 0)) < 0){
+	fd = os_open_file(file, of_read(OPENFLAGS()), 0);
+	if(fd < 0){
 		if(fd != -ENOENT){
 			printk("not_dead_yet : couldn't open pid file '%s', "
-			       "errno = %d\n", file, -fd);
+			       "err = %d\n", file, -fd);
 			return(1);
 		}
 		dead = 1;
 	}
 	if(fd > 0){
-		if(read(fd, pid, sizeof(pid)) < 0){
+		n = os_read_file(fd, pid, sizeof(pid));
+		if(n < 0){
 			printk("not_dead_yet : couldn't read pid file '%s', "
-			       "errno = %d\n", file, errno);
+			       "err = %d\n", file, -n);
 			return(1);
 		}
 		p = strtoul(pid, &end, 0);
@@ -195,17 +199,20 @@ int not_dead_yet(char *dir)
 static int __init set_uml_dir(char *name, int *add)
 {
 	if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){
-		uml_dir = malloc(strlen(name) + 1);
+		uml_dir = malloc(strlen(name) + 2);
 		if(uml_dir == NULL){
-			printk("Failed to malloc uml_dir - error = %d\n",
+			printf("Failed to malloc uml_dir - error = %d\n",
 			       errno);
 			uml_dir = name;
+			/* Return 0 here because do_initcalls doesn't look at
+			 * the return value.
+			 */
 			return(0);
 		}
 		sprintf(uml_dir, "%s/", name);
 	}
 	else uml_dir = name;
-	return 0;
+	return(0);
 }
 
 static int __init make_uml_dir(void)
@@ -217,7 +224,7 @@ static int __init make_uml_dir(void)
 		char *home = getenv("HOME");
 
 		if(home == NULL){
-			printk("make_uml_dir : no value in environment for "
+			printf("make_uml_dir : no value in environment for "
 			       "$HOME\n");
 			exit(1);
 		}
@@ -232,57 +239,59 @@ static int __init make_uml_dir(void)
 		dir[len + 1] = '\0';
 	}
 
-	if((uml_dir = malloc(strlen(dir) + 1)) == NULL){
+	uml_dir = malloc(strlen(dir) + 1);
+	if(uml_dir == NULL){
 		printf("make_uml_dir : malloc failed, errno = %d\n", errno);
 		exit(1);
 	}
 	strcpy(uml_dir, dir);
 	
 	if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){
-	        printk("Failed to mkdir %s - errno = %i\n", uml_dir, errno);
+	        printf("Failed to mkdir %s - errno = %i\n", uml_dir, errno);
 		return(-1);
 	}
 	return 0;
 }
 
-static int __init make_umid(void)
+static int __init make_umid(int (*printer)(const char *fmt, ...))
 {
 	int fd, err;
 	char tmp[strlen(uml_dir) + UMID_LEN + 1];
 
 	strlcpy(tmp, uml_dir, sizeof(tmp));
 
-	if(*umid == 0){
+	if(!umid_inited){
 		strcat(tmp, "XXXXXX");
 		fd = mkstemp(tmp);
 		if(fd < 0){
-			printk("make_umid - mkstemp failed, errno = %d\n",
-			       errno);
+			(*printer)("make_umid - mkstemp failed, errno = %d\n",
+				   errno);
 			return(1);
 		}
 
-		close(fd);
+		os_close_file(fd);
 		/* There's a nice tiny little race between this unlink and
 		 * the mkdir below.  It'd be nice if there were a mkstemp
 		 * for directories.
 		 */
 		unlink(tmp);
-		set_umid(&tmp[strlen(uml_dir)], 1);
+		set_umid(&tmp[strlen(uml_dir)], 1, printer);
 	}
 	
 	sprintf(tmp, "%s%s", uml_dir, umid);
 
-	if((err = mkdir(tmp, 0777)) < 0){
+	err = mkdir(tmp, 0777);
+	if(err < 0){
 		if(errno == EEXIST){
 			if(not_dead_yet(tmp)){
-				printk("umid '%s' is in use\n", umid);
+				(*printer)("umid '%s' is in use\n", umid);
 				return(-1);
 			}
 			err = mkdir(tmp, 0777);
 		}
 	}
 	if(err < 0){
-		printk("Failed to create %s - errno = %d\n", umid, errno);
+		(*printer)("Failed to create %s - errno = %d\n", umid, errno);
 		return(-1);
 	}
 
@@ -295,7 +304,13 @@ __uml_setup("uml_dir=", set_uml_dir,
 );
 
 __uml_postsetup(make_uml_dir);
-__uml_postsetup(make_umid);
+
+static int __init make_umid_setup(void)
+{
+	return(make_umid(printf));
+}
+
+__uml_postsetup(make_umid_setup);
 __uml_postsetup(create_pid_file);
 
 /*
diff --git a/arch/um/kernel/user_util.c b/arch/um/kernel/user_util.c
index 9e4fbae93..b2c7c5d2e 100644
--- a/arch/um/kernel/user_util.c
+++ b/arch/um/kernel/user_util.c
@@ -5,10 +5,10 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <fcntl.h>
 #include <unistd.h>
 #include <limits.h>
-#include <sys/mman.h> 
+#include <setjmp.h>
+#include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/ptrace.h>
 #include <sys/utsname.h>
@@ -81,19 +81,19 @@ int wait_for_stop(int pid, int sig, int cont_type, void *relay)
 	int status, ret;
 
 	while(1){
-		if(((ret = waitpid(pid, &status, WUNTRACED)) < 0) ||
+		CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED));
+		if((ret < 0) ||
 		   !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){
 			if(ret < 0){
-				if(errno == EINTR) continue;
 				printk("wait failed, errno = %d\n",
 				       errno);
 			}
 			else if(WIFEXITED(status)) 
-				printk("process exited with status %d\n", 
-				       WEXITSTATUS(status));
+				printk("process %d exited with status %d\n",
+				       pid, WEXITSTATUS(status));
 			else if(WIFSIGNALED(status))
-				printk("process exited with signal %d\n", 
-				       WTERMSIG(status));
+				printk("process %d exited with signal %d\n",
+				       pid, WTERMSIG(status));
 			else if((WSTOPSIG(status) == SIGVTALRM) ||
 				(WSTOPSIG(status) == SIGALRM) ||
 				(WSTOPSIG(status) == SIGIO) ||
@@ -109,8 +109,8 @@ int wait_for_stop(int pid, int sig, int cont_type, void *relay)
 				ptrace(cont_type, pid, 0, WSTOPSIG(status));
 				continue;
 			}
-			else printk("process stopped with signal %d\n", 
-				    WSTOPSIG(status));
+			else printk("process %d stopped with signal %d\n",
+				    pid, WSTOPSIG(status));
 			panic("wait_for_stop failed to wait for %d to stop "
 			      "with %d\n", pid, sig);
 		}
@@ -118,29 +118,27 @@ int wait_for_stop(int pid, int sig, int cont_type, void *relay)
 	}
 }
 
-int clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags)
-{
-	int pid;
-
-	pid = clone(fn, sp, flags, arg);
- 	if(pid < 0) return(-1);
-	wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL);
-	ptrace(PTRACE_CONT, pid, 0, 0);
-	return(pid);
-}
-
-int raw(int fd, int complain)
+int raw(int fd)
 {
 	struct termios tt;
 	int err;
 
-	tcgetattr(fd, &tt);
+	CATCH_EINTR(err = tcgetattr(fd, &tt));
+	if (err < 0) {
+			printk("tcgetattr failed, errno = %d\n", errno);
+		return(-errno);
+	}
+
 	cfmakeraw(&tt);
-	err = tcsetattr(fd, TCSANOW, &tt);
-	if((err < 0) && complain){
-		printk("tcsetattr failed, errno = %d\n", errno);
+
+ 	CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt));
+	if (err < 0) {
+			printk("tcsetattr failed, errno = %d\n", errno);
 		return(-errno);
 	}
+
+	/* XXX tcsetattr could have applied only some changes
+	 * (and cfmakeraw() is a set of changes) */
 	return(0);
 }
 
@@ -163,6 +161,21 @@ void setup_hostinfo(void)
 		host.release, host.version, host.machine);
 }
 
+int setjmp_wrapper(void (*proc)(void *, void *), ...)
+{
+        va_list args;
+	sigjmp_buf buf;
+	int n;
+
+	n = sigsetjmp(buf, 1);
+	if(n == 0){
+		va_start(args, proc);
+		(*proc)(&buf, &args);
+	}
+	va_end(args);
+	return(n);
+}
+
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index 37eea4a32..ff94c8f61 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -3,13 +3,9 @@
 # Licensed under the GPL
 #
 
-obj-y = file.o process.o tty.o drivers/
+obj-y = file.o process.o time.o tty.o user_syms.o drivers/
 
-USER_OBJS := $(foreach file,file.o process.o tty.o,$(obj)/$(file))
+USER_OBJS := $(foreach file,file.o process.o time.o tty.o,$(obj)/$(file))
 
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean :
-
-archmrproper:
diff --git a/arch/um/os-Linux/drivers/ethertap_kern.c b/arch/um/os-Linux/drivers/ethertap_kern.c
index 17f156104..6ae4b19d9 100644
--- a/arch/um/os-Linux/drivers/ethertap_kern.c
+++ b/arch/um/os-Linux/drivers/ethertap_kern.c
@@ -8,7 +8,6 @@
 #include "linux/init.h"
 #include "linux/netdevice.h"
 #include "linux/etherdevice.h"
-#include "linux/init.h"
 #include "net_kern.h"
 #include "net_user.h"
 #include "etap.h"
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index e27592985..cd4d6544d 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -8,7 +8,6 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <stddef.h>
-#include <fcntl.h>
 #include <stdlib.h>
 #include <sys/errno.h>
 #include <sys/socket.h>
@@ -17,6 +16,7 @@
 #include <net/if.h>
 #include "user.h"
 #include "kern_util.h"
+#include "user_util.h"
 #include "net_user.h"
 #include "etap.h"
 #include "helper.h"
@@ -42,13 +42,14 @@ static void etap_change(int op, unsigned char *addr, unsigned char *netmask,
 {
 	struct addr_change change;
 	void *output;
+	int n;
 
 	change.what = op;
 	memcpy(change.addr, addr, sizeof(change.addr));
 	memcpy(change.netmask, netmask, sizeof(change.netmask));
-	if(write(fd, &change, sizeof(change)) != sizeof(change))
-		printk("etap_change - request failed, errno = %d\n",
-		       errno);
+	n = os_write_file(fd, &change, sizeof(change));
+	if(n != sizeof(change))
+		printk("etap_change - request failed, err = %d\n", -n);
 	output = um_kmalloc(page_size());
 	if(output == NULL)
 		printk("etap_change : Failed to allocate output buffer\n");
@@ -82,15 +83,15 @@ static void etap_pre_exec(void *arg)
 	struct etap_pre_exec_data *data = arg;
 
 	dup2(data->control_remote, 1);
-	close(data->data_me);
-	close(data->control_me);
+	os_close_file(data->data_me);
+	os_close_file(data->control_me);
 }
 
 static int etap_tramp(char *dev, char *gate, int control_me, 
 		      int control_remote, int data_me, int data_remote)
 {
 	struct etap_pre_exec_data pe_data;
-	int pid, status, err;
+	int pid, status, err, n;
 	char version_buf[sizeof("nnnnn\0")];
 	char data_fd_buf[sizeof("nnnnnn\0")];
 	char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
@@ -114,21 +115,22 @@ static int etap_tramp(char *dev, char *gate, int control_me,
 	pe_data.data_me = data_me;
 	pid = run_helper(etap_pre_exec, &pe_data, args, NULL);
 
-	if(pid < 0) err = errno;
-	close(data_remote);
-	close(control_remote);
-	if(read(control_me, &c, sizeof(c)) != sizeof(c)){
-		printk("etap_tramp : read of status failed, errno = %d\n",
-		       errno);
-		return(EINVAL);
+	if(pid < 0) err = pid;
+	os_close_file(data_remote);
+	os_close_file(control_remote);
+	n = os_read_file(control_me, &c, sizeof(c));
+	if(n != sizeof(c)){
+		printk("etap_tramp : read of status failed, err = %d\n", -n);
+		return(-EINVAL);
 	}
 	if(c != 1){
 		printk("etap_tramp : uml_net failed\n");
-		err = EINVAL;
-		if(waitpid(pid, &status, 0) < 0) err = errno;
-		else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1)){
+		err = -EINVAL;
+		CATCH_EINTR(n = waitpid(pid, &status, 0));
+		if(n < 0)
+			err = -errno;
+		else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1))
 			printk("uml_net didn't exit with status 1\n");
-		}
 	}
 	return(err);
 }
@@ -143,14 +145,14 @@ static int etap_open(void *data)
 	if(err) return(err);
 
 	err = os_pipe(data_fds, 0, 0);
-	if(err){
-		printk("data os_pipe failed - errno = %d\n", -err);
+	if(err < 0){
+		printk("data os_pipe failed - err = %d\n", -err);
 		return(err);
 	}
 
 	err = os_pipe(control_fds, 1, 0);
-	if(err){
-		printk("control os_pipe failed - errno = %d\n", -err);
+	if(err < 0){
+		printk("control os_pipe failed - err = %d\n", -err);
 		return(err);
 	}
 	
@@ -167,9 +169,9 @@ static int etap_open(void *data)
 		kfree(output);
 	}
 
-	if(err != 0){
-		printk("etap_tramp failed - errno = %d\n", err);
-		return(-err);
+	if(err < 0){
+		printk("etap_tramp failed - err = %d\n", -err);
+		return(err);
 	}
 
 	pri->data_fd = data_fds[0];
@@ -183,11 +185,11 @@ static void etap_close(int fd, void *data)
 	struct ethertap_data *pri = data;
 
 	iter_addresses(pri->dev, etap_close_addr, &pri->control_fd);
-	close(fd);
+	os_close_file(fd);
 	os_shutdown_socket(pri->data_fd, 1, 1);
-	close(pri->data_fd);
+	os_close_file(pri->data_fd);
 	pri->data_fd = -1;
-	close(pri->control_fd);
+	os_close_file(pri->control_fd);
 	pri->control_fd = -1;
 }
 
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index c858f1160..4b83c6c3f 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -8,7 +8,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <sys/wait.h>
 #include <sys/socket.h>
 #include <sys/un.h>
@@ -19,6 +18,7 @@
 #include "net_user.h"
 #include "tuntap.h"
 #include "kern_util.h"
+#include "user_util.h"
 #include "user.h"
 #include "helper.h"
 #include "os.h"
@@ -61,7 +61,7 @@ static void tuntap_pre_exec(void *arg)
 	struct tuntap_pre_exec_data *data = arg;
 	
 	dup2(data->stdout, 1);
-	close(data->close_me);
+	os_close_file(data->close_me);
 }
 
 static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
@@ -86,7 +86,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
 
 	if(pid < 0) return(-pid);
 
-	close(remote);
+	os_close_file(remote);
 
 	msg.msg_name = NULL;
 	msg.msg_namelen = 0;
@@ -107,19 +107,19 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
 	if(n < 0){
 		printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", 
 		       errno);
-		return(errno);
+		return(-errno);
 	}
-	waitpid(pid, NULL, 0);
+	CATCH_EINTR(waitpid(pid, NULL, 0));
 
 	cmsg = CMSG_FIRSTHDR(&msg);
 	if(cmsg == NULL){
 		printk("tuntap_open_tramp : didn't receive a message\n");
-		return(EINVAL);
+		return(-EINVAL);
 	}
 	if((cmsg->cmsg_level != SOL_SOCKET) || 
 	   (cmsg->cmsg_type != SCM_RIGHTS)){
 		printk("tuntap_open_tramp : didn't receive a descriptor\n");
-		return(EINVAL);
+		return(-EINVAL);
 	}
 	*fd_out = ((int *) CMSG_DATA(cmsg))[0];
 	return(0);
@@ -133,27 +133,29 @@ static int tuntap_open(void *data)
 	int err, fds[2], len, used;
 
 	err = tap_open_common(pri->dev, pri->gate_addr);
-	if(err) return(err);
+	if(err < 0)
+		return(err);
 
 	if(pri->fixed_config){
-		if((pri->fd = open("/dev/net/tun", O_RDWR)) < 0){
-			printk("Failed to open /dev/net/tun, errno = %d\n",
-			       errno);
-			return(-errno);
+		pri->fd = os_open_file("/dev/net/tun", of_rdwr(OPENFLAGS()), 0);
+		if(pri->fd < 0){
+			printk("Failed to open /dev/net/tun, err = %d\n",
+			       -pri->fd);
+			return(pri->fd);
 		}
 		memset(&ifr, 0, sizeof(ifr));
-		ifr.ifr_flags = IFF_TAP;
+		ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
 		strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name));
 		if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){
-			printk("TUNSETIFF failed, errno = %d", errno);
-			close(pri->fd);
+			printk("TUNSETIFF failed, errno = %d\n", errno);
+			os_close_file(pri->fd);
 			return(-errno);
 		}
 	}
 	else {
 		err = os_pipe(fds, 0, 0);
-		if(err){
-			printk("tuntap_open : os_pipe failed - errno = %d\n",
+		if(err < 0){
+			printk("tuntap_open : os_pipe failed - err = %d\n",
 			       -err);
 			return(err);
 		}
@@ -166,19 +168,19 @@ static int tuntap_open(void *data)
 					fds[1], buffer, len, &used);
 
 		output = buffer;
-		if(err == 0){
-			pri->dev_name = uml_strdup(buffer);
-			output += IFNAMSIZ;
-			printk(output);
-			free_output_buffer(buffer);
-		}
-		else {
-			printk(output);
+		if(err < 0) {
+			printk("%s", output);
 			free_output_buffer(buffer);
-			printk("tuntap_open_tramp failed - errno = %d\n", err);
-			return(-err);
+			printk("tuntap_open_tramp failed - err = %d\n", -err);
+			return(err);
 		}
-		close(fds[0]);
+
+		pri->dev_name = uml_strdup(buffer);
+		output += IFNAMSIZ;
+		printk("%s", output);
+		free_output_buffer(buffer);
+
+		os_close_file(fds[0]);
 		iter_addresses(pri->dev, open_addr, pri->dev_name);
 	}
 
@@ -191,7 +193,7 @@ static void tuntap_close(int fd, void *data)
 
 	if(!pri->fixed_config) 
 		iter_addresses(pri->dev, close_addr, pri->dev_name);
-	close(fd);
+	os_close_file(fd);
 	pri->fd = -1;
 }
 
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index e622db007..514ab984c 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -8,6 +8,8 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <sys/ioctl.h>
@@ -17,33 +19,236 @@
 #include "user.h"
 #include "kern_util.h"
 
-int os_file_type(char *file)
+static void copy_stat(struct uml_stat *dst, struct stat64 *src)
+{
+	*dst = ((struct uml_stat) {
+		.ust_dev     = src->st_dev,     /* device */
+		.ust_ino     = src->st_ino,     /* inode */
+		.ust_mode    = src->st_mode,    /* protection */
+		.ust_nlink   = src->st_nlink,   /* number of hard links */
+		.ust_uid     = src->st_uid,     /* user ID of owner */
+		.ust_gid     = src->st_gid,     /* group ID of owner */
+		.ust_size    = src->st_size,    /* total size, in bytes */
+		.ust_blksize = src->st_blksize, /* blocksize for filesys I/O */
+		.ust_blocks  = src->st_blocks,  /* number of blocks allocated */
+		.ust_atime   = src->st_atime,   /* time of last access */
+		.ust_mtime   = src->st_mtime,   /* time of last modification */
+		.ust_ctime   = src->st_ctime,   /* time of last change */
+	});
+}
+
+int os_stat_fd(const int fd, struct uml_stat *ubuf)
+{
+	struct stat64 sbuf;
+	int err;
+
+	do {
+		err = fstat64(fd, &sbuf);
+	} while((err < 0) && (errno == EINTR)) ;
+
+	if(err < 0)
+		return(-errno);
+
+	if(ubuf != NULL)
+		copy_stat(ubuf, &sbuf);
+	return(err);
+}
+
+int os_stat_file(const char *file_name, struct uml_stat *ubuf)
+{
+	struct stat64 sbuf;
+	int err;
+
+	do {
+		err = stat64(file_name, &sbuf);
+	} while((err < 0) && (errno == EINTR)) ;
+
+	if(err < 0)
+		return(-errno);
+
+	if(ubuf != NULL)
+		copy_stat(ubuf, &sbuf);
+	return(err);
+}
+
+int os_access(const char* file, int mode)
+{
+	int amode, err;
+
+	amode=(mode&OS_ACC_R_OK ? R_OK : 0) | (mode&OS_ACC_W_OK ? W_OK : 0) |
+	      (mode&OS_ACC_X_OK ? X_OK : 0) | (mode&OS_ACC_F_OK ? F_OK : 0) ;
+
+	err = access(file, amode);
+	if(err < 0)
+		return(-errno);
+
+	return(0);
+}
+
+void os_print_error(int error, const char* str)
+{
+	errno = error < 0 ? -error : error;
+
+	perror(str);
+}
+
+/* FIXME? required only by hostaudio (because it passes ioctls verbatim) */
+int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
+{
+	int err;
+
+	err = ioctl(fd, cmd, arg);
+	if(err < 0)
+		return(-errno);
+
+	return(err);
+}
+
+int os_window_size(int fd, int *rows, int *cols)
+{
+	struct winsize size;
+
+	if(ioctl(fd, TIOCGWINSZ, &size) < 0)
+		return(-errno);
+
+	*rows = size.ws_row;
+	*cols = size.ws_col;
+
+	return(0);
+}
+
+int os_new_tty_pgrp(int fd, int pid)
+{
+	if(ioctl(fd, TIOCSCTTY, 0) < 0){
+		printk("TIOCSCTTY failed, errno = %d\n", errno);
+		return(-errno);
+	}
+
+	if(tcsetpgrp(fd, pid) < 0){
+		printk("tcsetpgrp failed, errno = %d\n", errno);
+		return(-errno);
+	}
+
+	return(0);
+}
+
+/* FIXME: ensure namebuf in os_get_if_name is big enough */
+int os_get_ifname(int fd, char* namebuf)
+{
+	if(ioctl(fd, SIOCGIFNAME, namebuf) < 0)
+		return(-errno);
+
+	return(0);
+}
+
+int os_set_slip(int fd)
+{
+	int disc, sencap;
+
+	disc = N_SLIP;
+	if(ioctl(fd, TIOCSETD, &disc) < 0){
+		printk("Failed to set slip line discipline - "
+		       "errno = %d\n", errno);
+		return(-errno);
+	}
+
+	sencap = 0;
+	if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0){
+		printk("Failed to set slip encapsulation - "
+		       "errno = %d\n", errno);
+		return(-errno);
+	}
+
+	return(0);
+}
+
+int os_set_owner(int fd, int pid)
+{
+	if(fcntl(fd, F_SETOWN, pid) < 0){
+		int save_errno = errno;
+
+		if(fcntl(fd, F_GETOWN, 0) != pid)
+			return(-save_errno);
+	}
+
+	return(0);
+}
+
+/* FIXME? moved wholesale from sigio_user.c to get fcntls out of that file */
+int os_sigio_async(int master, int slave)
 {
-	struct stat64 buf;
+	int flags;
 
-	if(stat64(file, &buf) == -1)
+	flags = fcntl(master, F_GETFL);
+	if(flags < 0) {
+		printk("fcntl F_GETFL failed, errno = %d\n", errno);
 		return(-errno);
+	}
+
+	if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
+	   (fcntl(master, F_SETOWN, os_getpid()) < 0)){
+		printk("fcntl F_SETFL or F_SETOWN failed, errno = %d\n",
+		       errno);
+		return(-errno);
+	}
+
+	if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)){
+		printk("fcntl F_SETFL failed, errno = %d\n", errno);
+		return(-errno);
+	}
+
+	return(0);
+}
 
-	if(S_ISDIR(buf.st_mode)) return(OS_TYPE_DIR);
-	else if(S_ISLNK(buf.st_mode)) return(OS_TYPE_SYMLINK);
-	else if(S_ISCHR(buf.st_mode)) return(OS_TYPE_CHARDEV);
-	else if(S_ISBLK(buf.st_mode)) return(OS_TYPE_BLOCKDEV);
-	else if(S_ISFIFO(buf.st_mode)) return(OS_TYPE_FIFO);
-	else if(S_ISSOCK(buf.st_mode)) return(OS_TYPE_SOCK);
+int os_mode_fd(int fd, int mode)
+{
+	int err;
+
+	do {
+		err = fchmod(fd, mode);
+	} while((err < 0) && (errno==EINTR)) ;
+
+	if(err < 0)
+		return(-errno);
+
+	return(0);
+}
+
+int os_file_type(char *file)
+{
+	struct uml_stat buf;
+	int err;
+
+	err = os_stat_file(file, &buf);
+	if(err < 0)
+		return(err);
+
+	if(S_ISDIR(buf.ust_mode)) return(OS_TYPE_DIR);
+	else if(S_ISLNK(buf.ust_mode)) return(OS_TYPE_SYMLINK);
+	else if(S_ISCHR(buf.ust_mode)) return(OS_TYPE_CHARDEV);
+	else if(S_ISBLK(buf.ust_mode)) return(OS_TYPE_BLOCKDEV);
+	else if(S_ISFIFO(buf.ust_mode)) return(OS_TYPE_FIFO);
+	else if(S_ISSOCK(buf.ust_mode)) return(OS_TYPE_SOCK);
 	else return(OS_TYPE_FILE);
 }
 
 int os_file_mode(char *file, struct openflags *mode_out)
 {
+	int err;
+
 	*mode_out = OPENFLAGS();
 
-	if(!access(file, W_OK)) *mode_out = of_write(*mode_out);
-	else if(errno != EACCES) 
-		return(-errno);
+	err = os_access(file, OS_ACC_W_OK);
+	if((err < 0) && (err != -EACCES))
+		return(err);
 
-	if(!access(file, R_OK)) *mode_out = of_read(*mode_out);
-	else if(errno != EACCES) 
-		return(-errno);
+	*mode_out = of_write(*mode_out);
+
+	err = os_access(file, OS_ACC_R_OK);
+	if((err < 0) && (err != -EACCES))
+		return(err);
+
+	*mode_out = of_read(*mode_out);
 
 	return(0);
 }
@@ -63,16 +268,14 @@ int os_open_file(char *file, struct openflags flags, int mode)
 	if(flags.e) f |= O_EXCL;
 
 	fd = open64(file, f, mode);
-	if(fd < 0) return(-errno);
-	
-	if(flags.cl){
-		if(fcntl(fd, F_SETFD, 1)){
-			close(fd);
-			return(-errno);
-		}
+	if(fd < 0)
+		return(-errno);
+
+	if(flags.cl && fcntl(fd, F_SETFD, 1)){
+		os_close_file(fd);
+		return(-errno);
 	}
 
- 	return(fd);
 	return(fd);
 }
 
@@ -90,7 +293,7 @@ int os_connect_socket(char *name)
 
 	err = connect(fd, (struct sockaddr *) &sock, sizeof(sock));
 	if(err)
-		return(err);
+		return(-errno);
 
 	return(fd);
 }
@@ -109,88 +312,162 @@ int os_seek_file(int fd, __u64 offset)
 	return(0);
 }
 
-int os_read_file(int fd, void *buf, int len)
+static int fault_buffer(void *start, int len,
+			int (*copy_proc)(void *addr, void *buf, int len))
 {
-	int n;
+	int page = getpagesize(), i;
+	char c;
 
-	/* Force buf into memory if it's not already. */
+	for(i = 0; i < len; i += page){
+		if((*copy_proc)(start + i, &c, sizeof(c)))
+			return(-EFAULT);
+	}
+	if((len % page) != 0){
+		if((*copy_proc)(start + len - 1, &c, sizeof(c)))
+			return(-EFAULT);
+	}
+	return(0);
+}
 
-	/* XXX This fails if buf is kernel memory */
-#ifdef notdef
-	if(copy_to_user_proc(buf, &c, sizeof(c)))
-		return(-EFAULT);
-#endif
+static int file_io(int fd, void *buf, int len,
+		   int (*io_proc)(int fd, void *buf, int len),
+		   int (*copy_user_proc)(void *addr, void *buf, int len))
+{
+	int n, err;
+
+	do {
+		n = (*io_proc)(fd, buf, len);
+		if((n < 0) && (errno == EFAULT)){
+			err = fault_buffer(buf, len, copy_user_proc);
+			if(err)
+				return(err);
+			n = (*io_proc)(fd, buf, len);
+		}
+	} while((n < 0) && (errno == EINTR));
 
-	n = read(fd, buf, len);
 	if(n < 0)
 		return(-errno);
 	return(n);
 }
 
-int os_write_file(int fd, void *buf, int count)
+int os_read_file(int fd, void *buf, int len)
 {
-	int n;
-
-	/* Force buf into memory if it's not already. */
-	
-	/* XXX This fails if buf is kernel memory */
-#ifdef notdef
-	if(copy_to_user_proc(buf, buf, buf[0]))
-		return(-EFAULT);
-#endif
+	return(file_io(fd, buf, len, (int (*)(int, void *, int)) read,
+		       copy_from_user_proc));
+}
 
-	n = write(fd, buf, count);
-	if(n < 0)
-		return(-errno);
-	return(n);
+int os_write_file(int fd, const void *buf, int len)
+{
+	return(file_io(fd, (void *) buf, len,
+		       (int (*)(int, void *, int)) write, copy_to_user_proc));
 }
 
 int os_file_size(char *file, long long *size_out)
 {
-	struct stat64 buf;
+	struct uml_stat buf;
+	int err;
 
-	if(stat64(file, &buf) == -1){
-		printk("Couldn't stat \"%s\" : errno = %d\n", file, errno);
-		return(-errno);
+	err = os_stat_file(file, &buf);
+	if(err < 0){
+		printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
+		return(err);
 	}
-	if(S_ISBLK(buf.st_mode)){
+
+	if(S_ISBLK(buf.ust_mode)){
 		int fd, blocks;
 
-		if((fd = open64(file, O_RDONLY)) < 0){
-			printk("Couldn't open \"%s\", errno = %d\n", file,
-			       errno);
-			return(-errno);
+		fd = os_open_file(file, of_read(OPENFLAGS()), 0);
+		if(fd < 0){
+			printk("Couldn't open \"%s\", errno = %d\n", file, -fd);
+			return(fd);
 		}
 		if(ioctl(fd, BLKGETSIZE, &blocks) < 0){
 			printk("Couldn't get the block size of \"%s\", "
 			       "errno = %d\n", file, errno);
-			close(fd);
-			return(-errno);
+			err = -errno;
+			os_close_file(fd);
+			return(err);
 		}
 		*size_out = ((long long) blocks) * 512;
-		close(fd);
+		os_close_file(fd);
 		return(0);
 	}
-	*size_out = buf.st_size;
+	*size_out = buf.ust_size;
+	return(0);
+}
+
+int os_file_modtime(char *file, unsigned long *modtime)
+{
+	struct uml_stat buf;
+	int err;
+
+	err = os_stat_file(file, &buf);
+	if(err < 0){
+		printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
+		return(err);
+	}
+
+	*modtime = buf.ust_mtime;
 	return(0);
 }
 
+int os_get_exec_close(int fd, int* close_on_exec)
+{
+	int ret;
+
+	do {
+		ret = fcntl(fd, F_GETFD);
+	} while((ret < 0) && (errno == EINTR)) ;
+
+	if(ret < 0)
+		return(-errno);
+
+	*close_on_exec = (ret&FD_CLOEXEC) ? 1 : 0;
+	return(ret);
+}
+
+int os_set_exec_close(int fd, int close_on_exec)
+{
+	int flag, err;
+
+	if(close_on_exec) flag = FD_CLOEXEC;
+	else flag = 0;
+
+	do {
+		err = fcntl(fd, F_SETFD, flag);
+	} while((err < 0) && (errno == EINTR)) ;
+
+	if(err < 0)
+		return(-errno);
+	return(err);
+}
+
 int os_pipe(int *fds, int stream, int close_on_exec)
 {
 	int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
 
 	err = socketpair(AF_UNIX, type, 0, fds);
-	if(err) 
+	if(err < 0)
 		return(-errno);
 
 	if(!close_on_exec)
 		return(0);
 
-	if((fcntl(fds[0], F_SETFD, 1) < 0) || (fcntl(fds[1], F_SETFD, 1) < 0))
-		printk("os_pipe : Setting FD_CLOEXEC failed, errno = %d", 
-		       errno);
+	err = os_set_exec_close(fds[0], 1);
+	if(err < 0)
+		goto error;
+
+	err = os_set_exec_close(fds[1], 1);
+	if(err < 0)
+		goto error;
 
 	return(0);
+
+ error:
+	printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err);
+	os_close_file(fds[1]);
+	os_close_file(fds[0]);
+	return(err);
 }
 
 int os_set_fd_async(int fd, int owner)
@@ -219,6 +496,16 @@ int os_set_fd_async(int fd, int owner)
 	return(0);
 }
 
+int os_clear_fd_async(int fd)
+{
+	int flags = fcntl(fd, F_GETFL);
+
+	flags &= ~(O_ASYNC | O_NONBLOCK);
+	if(fcntl(fd, F_SETFL, flags) < 0)
+		return(-errno);
+	return(0);
+}
+
 int os_set_fd_block(int fd, int blocking)
 {
 	int flags;
@@ -270,7 +557,7 @@ int os_shutdown_socket(int fd, int r, int w)
 		return(-EINVAL);
 	}
 	err = shutdown(fd, what);
-	if(err)
+	if(err < 0)
 		return(-errno);
 	return(0);
 }
@@ -315,7 +602,7 @@ int os_rcv_fd(int fd, int *helper_pid_out)
 	return(new);
 }
 
-int create_unix_socket(char *file, int len)
+int os_create_unix_socket(char *file, int len, int close_on_exec)
 {
 	struct sockaddr_un addr;
 	int sock, err;
@@ -327,6 +614,13 @@ int create_unix_socket(char *file, int len)
 		return(-errno);
 	}
 
+	if(close_on_exec) {
+		err = os_set_exec_close(sock, 1);
+		if(err < 0)
+			printk("create_unix_socket : close_on_exec failed, "
+		       "err = %d", -err);
+	}
+
 	addr.sun_family = AF_UNIX;
 
 	/* XXX Be more careful about overflow */
@@ -334,14 +628,45 @@ int create_unix_socket(char *file, int len)
 
 	err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
 	if (err < 0){
-		printk("create_listening_socket - bind failed, errno = %d\n",
-		       errno);
+		printk("create_listening_socket at '%s' - bind failed, "
+		       "errno = %d\n", file, errno);
 		return(-errno);
 	}
 
 	return(sock);
 }
 
+void os_flush_stdout(void)
+{
+	fflush(stdout);
+}
+
+int os_lock_file(int fd, int excl)
+{
+	int type = excl ? F_WRLCK : F_RDLCK;
+	struct flock lock = ((struct flock) { .l_type	= type,
+					      .l_whence	= SEEK_SET,
+					      .l_start	= 0,
+					      .l_len	= 0 } );
+	int err, save;
+
+	err = fcntl(fd, F_SETLK, &lock);
+	if(!err)
+		goto out;
+
+	save = -errno;
+	err = fcntl(fd, F_GETLK, &lock);
+	if(err){
+		err = -errno;
+		goto out;
+	}
+
+	printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid);
+	err = save;
+ out:
+	return(err);
+}
+
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index a97778f31..ec4617b42 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -7,35 +7,44 @@
 #include <stdio.h>
 #include <errno.h>
 #include <signal.h>
+#include <linux/unistd.h>
 #include <sys/mman.h>
 #include <sys/wait.h>
 #include "os.h"
 #include "user.h"
+#include "user_util.h"
+
+#define ARBITRARY_ADDR -1
+#define FAILURE_PID    -1
+
+#define STAT_PATH_LEN sizeof("/proc/#######/stat\0")
+#define COMM_SCANF "%*[^)])"
 
 unsigned long os_process_pc(int pid)
 {
-	char proc_stat[sizeof("/proc/#####/stat\0")], buf[256];
+	char proc_stat[STAT_PATH_LEN], buf[256];
 	unsigned long pc;
-	int fd;
+	int fd, err;
 
 	sprintf(proc_stat, "/proc/%d/stat", pid);
 	fd = os_open_file(proc_stat, of_read(OPENFLAGS()), 0);
 	if(fd < 0){
-		printk("os_process_pc - couldn't open '%s', errno = %d\n", 
-		       proc_stat, errno);
-		return(-1);
+		printk("os_process_pc - couldn't open '%s', err = %d\n",
+		       proc_stat, -fd);
+		return(ARBITRARY_ADDR);
 	}
-	if(read(fd, buf, sizeof(buf)) < 0){
-		printk("os_process_pc - couldn't read '%s', errno = %d\n", 
-		       proc_stat, errno);
-		close(fd);
-		return(-1);
+	err = os_read_file(fd, buf, sizeof(buf));
+	if(err < 0){
+		printk("os_process_pc - couldn't read '%s', err = %d\n",
+		       proc_stat, -err);
+		os_close_file(fd);
+		return(ARBITRARY_ADDR);
 	}
-	close(fd);
-	pc = -1;
-	if(sscanf(buf, "%*d %*s %*c %*d %*d %*d %*d %*d %*d %*d %*d "
+	os_close_file(fd);
+	pc = ARBITRARY_ADDR;
+	if(sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d "
 		  "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
-		  "%*d %*d %*d %*d %ld", &pc) != 1){
+		  "%*d %*d %*d %*d %*d %lu", &pc) != 1){
 		printk("os_process_pc - couldn't find pc in '%s'\n", buf);
 	}
 	return(pc);
@@ -43,7 +52,7 @@ unsigned long os_process_pc(int pid)
 
 int os_process_parent(int pid)
 {
-	char stat[sizeof("/proc/nnnnn/stat\0")];
+	char stat[STAT_PATH_LEN];
 	char data[256];
 	int parent, n, fd;
 
@@ -52,22 +61,22 @@ int os_process_parent(int pid)
 	snprintf(stat, sizeof(stat), "/proc/%d/stat", pid);
 	fd = os_open_file(stat, of_read(OPENFLAGS()), 0);
 	if(fd < 0){
-		printk("Couldn't open '%s', errno = %d\n", stat, -fd);
-		return(-1);
+		printk("Couldn't open '%s', err = %d\n", stat, -fd);
+		return(FAILURE_PID);
 	}
 
-	n = read(fd, data, sizeof(data));
-	close(fd);
+	n = os_read_file(fd, data, sizeof(data));
+	os_close_file(fd);
 
 	if(n < 0){
-		printk("Couldn't read '%s', errno = %d\n", stat);
-		return(-1);
+		printk("Couldn't read '%s', err = %d\n", stat, -n);
+		return(FAILURE_PID);
 	}
 
-	parent = -1;
-	/* XXX This will break if there is a space in the command */
-	n = sscanf(data, "%*d %*s %*c %d", &parent);
-	if(n != 1) printk("Failed to scan '%s'\n", data);
+	parent = FAILURE_PID;
+	n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent);
+	if(n != 1)
+		printk("Failed to scan '%s'\n", data);
 
 	return(parent);
 }
@@ -81,7 +90,7 @@ void os_kill_process(int pid, int reap_child)
 {
 	kill(pid, SIGKILL);
 	if(reap_child)
-		waitpid(pid, NULL, 0);
+		CATCH_EINTR(waitpid(pid, NULL, 0));
 		
 }
 
@@ -95,7 +104,7 @@ int os_getpid(void)
 	return(getpid());
 }
 
-int os_map_memory(void *virt, int fd, unsigned long off, unsigned long len, 
+int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len,
 		  int r, int w, int x)
 {
 	void *loc;
@@ -104,8 +113,8 @@ int os_map_memory(void *virt, int fd, unsigned long off, unsigned long len,
 	prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | 
 		(x ? PROT_EXEC : 0);
 
-	loc = mmap((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, 
-		   fd, off);
+	loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED,
+		     fd, off);
 	if(loc == MAP_FAILED)
 		return(-errno);
 	return(0);
@@ -126,7 +135,8 @@ int os_unmap_memory(void *addr, int len)
         int err;
 
         err = munmap(addr, len);
-        if(err < 0) return(-errno);
+	if(err < 0)
+		return(-errno);
         return(0);
 }
 
diff --git a/arch/um/os-Linux/tty.c b/arch/um/os-Linux/tty.c
index 2866ddbc9..4cfdd18ea 100644
--- a/arch/um/os-Linux/tty.c
+++ b/arch/um/os-Linux/tty.c
@@ -28,10 +28,10 @@ int get_pty(void)
 	struct grantpt_info info;
 	int fd;
 
-	if((fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0)) < 0){
-		printk("get_pty : Couldn't open /dev/ptmx - errno = %d\n",
-		       errno);
-		return(-1);
+	fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0);
+	if(fd < 0){
+		printk("get_pty : Couldn't open /dev/ptmx - err = %d\n", -fd);
+		return(fd);
 	}
 
 	info.fd = fd;
@@ -39,7 +39,7 @@ int get_pty(void)
 
 	if(info.res < 0){
 		printk("get_pty : Couldn't grant pty - errno = %d\n", 
-		       info.err);
+		       -info.err);
 		return(-1);
 	}
 	if(unlockpt(fd) < 0){
diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c
index ef0fb71e4..2433c9e68 100644
--- a/arch/um/os-Linux/user_syms.c
+++ b/arch/um/os-Linux/user_syms.c
@@ -14,18 +14,20 @@
 
 extern size_t strlen(const char *);
 extern void *memcpy(void *, const void *, size_t);
+extern void *memmove(void *, const void *, size_t);
 extern void *memset(void *, int, size_t);
 extern int printf(const char *, ...);
 
 EXPORT_SYMBOL(strlen);
 EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memmove);
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(printf);
 
 EXPORT_SYMBOL(strstr);
 
 /* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms.
- * However, the modules will use the CRC defined *here*, no matter if it is 
+ * However, the modules will use the CRC defined *here*, no matter if it is
  * good; so the versions of these symbols will always match
  */
 #define EXPORT_SYMBOL_PROTO(sym)       \
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index 7525859c5..0f65a9259 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -1,14 +1,21 @@
-obj-y = bugs.o checksum.o extable.o fault.o ksyms.o ldt.o module.o \
-	ptrace.o ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o
+obj-y = bitops.o bugs.o checksum.o fault.o ksyms.o ldt.o ptrace.o \
+	ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o
 
 obj-$(CONFIG_HIGHMEM) += highmem.o
+obj-$(CONFIG_MODULES) += module.o
 
 USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o
 USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
 
-SYMLINKS = semaphore.c highmem.c module.c
+SYMLINKS = bitops.c semaphore.c highmem.c module.c
+
+# this needs to be before the foreach, because clean-files does not accept
+# complete paths like $(src)/$f.
+clean-files := $(SYMLINKS)
+
 SYMLINKS := $(foreach f,$(SYMLINKS),$(src)/$f)
 
+bitops.c-dir = lib
 semaphore.c-dir = kernel
 highmem.c-dir = mm
 module.c-dir = kernel
@@ -24,19 +31,4 @@ $(USER_OBJS) : %.o: %.c
 $(SYMLINKS): 
 	$(call make_link,$@)
 
-clean:
-	$(MAKE) -C util clean
-
-fastdep:
-
-dep:
-
-archmrproper:
-	rm -f $(SYMLINKS)
-
-archclean:
-
-archdep:
-
-modules:
-
+subdir- := util
diff --git a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c
index 3905bab88..41b0ab2fe 100644
--- a/arch/um/sys-i386/bugs.c
+++ b/arch/um/sys-i386/bugs.c
@@ -4,20 +4,21 @@
  */
 
 #include <unistd.h>
-#include <fcntl.h>
 #include <errno.h>
 #include <string.h>
 #include <sys/signal.h>
+#include <asm/ldt.h>
 #include "kern_util.h"
 #include "user.h"
 #include "sysdep/ptrace.h"
 #include "task.h"
+#include "os.h"
 
 #define MAXTOKEN 64
 
 /* Set during early boot */
-int cpu_has_cmov = 1;
-int cpu_has_xmm = 0;
+int host_has_cmov = 1;
+int host_has_xmm = 0;
 
 static char token(int fd, char *buf, int len, char stop)
 {
@@ -27,13 +28,15 @@ static char token(int fd, char *buf, int len, char stop)
 	ptr = buf;
 	end = &buf[len];
 	do {
-		n = read(fd, ptr, sizeof(*ptr));
+		n = os_read_file(fd, ptr, sizeof(*ptr));
 		c = *ptr++;
-		if(n == 0) return(0);
-		else if(n != sizeof(*ptr)){
-			printk("Reading /proc/cpuinfo failed, "
-			       "errno = %d\n", errno);
-			return(-errno);
+		if(n != sizeof(*ptr)){
+			if(n == 0) return(0);
+			printk("Reading /proc/cpuinfo failed, err = %d\n", -n);
+			if(n < 0)
+				return(n);
+			else
+				return(-EIO);
 		}
 	} while((c != '\n') && (c != stop) && (ptr < end));
 
@@ -45,45 +48,79 @@ static char token(int fd, char *buf, int len, char stop)
 	return(c);
 }
 
-static int check_cpu_feature(char *feature, int *have_it)
+static int find_cpuinfo_line(int fd, char *key, char *scratch, int len)
 {
-	char buf[MAXTOKEN], c;
-	int fd, len = sizeof(buf)/sizeof(buf[0]), n;
-
-	printk("Checking for host processor %s support...", feature);
-	fd = open("/proc/cpuinfo", O_RDONLY);
-	if(fd < 0){
-		printk("Couldn't open /proc/cpuinfo, errno = %d\n", errno);
-		return(0);
-	}
+	int n;
+	char c;
 
-	*have_it = 0;
-	buf[len - 1] = '\0';
+	scratch[len - 1] = '\0';
 	while(1){
-		c = token(fd, buf, len - 1, ':');
-		if(c <= 0) goto out;
+		c = token(fd, scratch, len - 1, ':');
+		if(c <= 0)
+			return(0);
 		else if(c != ':'){
 			printk("Failed to find ':' in /proc/cpuinfo\n");
-			goto out;
+			return(0);
 		}
 
-		if(!strncmp(buf, "flags", strlen("flags"))) break;
+		if(!strncmp(scratch, key, strlen(key)))
+			return(1);
 
 		do {
-			n = read(fd, &c, sizeof(c));
+			n = os_read_file(fd, &c, sizeof(c));
 			if(n != sizeof(c)){
 				printk("Failed to find newline in "
-				       "/proc/cpuinfo, n = %d, errno = %d\n",
-				       n, errno);
-				goto out;
+				       "/proc/cpuinfo, err = %d\n", -n);
+				return(0);
 			}
 		} while(c != '\n');
 	}
+	return(0);
+}
+
+int cpu_feature(char *what, char *buf, int len)
+{
+	int fd, ret = 0;
+
+	fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
+	if(fd < 0){
+		printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd);
+		return(0);
+	}
+
+	if(!find_cpuinfo_line(fd, what, buf, len)){
+		printk("Couldn't find '%s' line in /proc/cpuinfo\n", what);
+		goto out_close;
+	}
+
+	token(fd, buf, len, '\n');
+	ret = 1;
+
+ out_close:
+	os_close_file(fd);
+	return(ret);
+}
+
+static int check_cpu_flag(char *feature, int *have_it)
+{
+	char buf[MAXTOKEN], c;
+	int fd, len = sizeof(buf)/sizeof(buf[0]);
+
+	printk("Checking for host processor %s support...", feature);
+	fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
+	if(fd < 0){
+		printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd);
+		return(0);
+	}
+
+	*have_it = 0;
+	if(!find_cpuinfo_line(fd, "flags", buf, sizeof(buf) / sizeof(buf[0])))
+		goto out;
 
 	c = token(fd, buf, len - 1, ' ');
 	if(c < 0) goto out;
 	else if(c != ' '){
-		printk("Failed to find ':' in /proc/cpuinfo\n");
+		printk("Failed to find ' ' in /proc/cpuinfo\n");
 		goto out;
 	}
 
@@ -100,48 +137,76 @@ static int check_cpu_feature(char *feature, int *have_it)
  out:
 	if(*have_it == 0) printk("No\n");
 	else if(*have_it == 1) printk("Yes\n");
-	close(fd);
+	os_close_file(fd);
 	return(1);
 }
 
+#if 0 /* This doesn't work in tt mode, plus it's causing compilation problems
+       * for some people.
+       */
+static void disable_lcall(void)
+{
+	struct modify_ldt_ldt_s ldt;
+	int err;
+
+	bzero(&ldt, sizeof(ldt));
+	ldt.entry_number = 7;
+	ldt.base_addr = 0;
+	ldt.limit = 0;
+	err = modify_ldt(1, &ldt, sizeof(ldt));
+	if(err)
+		printk("Failed to disable lcall7 - errno = %d\n", errno);
+}
+#endif
+
+void arch_init_thread(void)
+{
+#if 0
+	disable_lcall();
+#endif
+}
+
 void arch_check_bugs(void)
 {
 	int have_it;
 
-	if(access("/proc/cpuinfo", R_OK)){
+	if(os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0){
 		printk("/proc/cpuinfo not available - skipping CPU capability "
 		       "checks\n");
 		return;
 	}
-	if(check_cpu_feature("cmov", &have_it)) cpu_has_cmov = have_it;
-	if(check_cpu_feature("xmm", &have_it)) cpu_has_xmm = have_it;
+	if(check_cpu_flag("cmov", &have_it))
+		host_has_cmov = have_it;
+	if(check_cpu_flag("xmm", &have_it))
+		host_has_xmm = have_it;
 }
 
 int arch_handle_signal(int sig, union uml_pt_regs *regs)
 {
-	unsigned long ip;
+	unsigned char tmp[2];
 
 	/* This is testing for a cmov (0x0f 0x4x) instruction causing a
 	 * SIGILL in init.
 	 */
 	if((sig != SIGILL) || (TASK_PID(get_current()) != 1)) return(0);
 
-	ip = UPT_IP(regs);
-	if((*((char *) ip) != 0x0f) || ((*((char *) (ip + 1)) & 0xf0) != 0x40))
+	if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2))
+		panic("SIGILL in init, could not read instructions!\n");
+	if((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40))
 		return(0);
 
-	if(cpu_has_cmov == 0)
+	if(host_has_cmov == 0)
 		panic("SIGILL caused by cmov, which this processor doesn't "
 		      "implement, boot a filesystem compiled for older "
 		      "processors");
-	else if(cpu_has_cmov == 1)
+	else if(host_has_cmov == 1)
 		panic("SIGILL caused by cmov, which this processor claims to "
 		      "implement");
-	else if(cpu_has_cmov == -1)
+	else if(host_has_cmov == -1)
 		panic("SIGILL caused by cmov, couldn't tell if this processor "
 		      "implements it, boot a filesystem compiled for older "
 		      "processors");
-	else panic("Bad value for cpu_has_cmov (%d)", cpu_has_cmov);
+	else panic("Bad value for host_has_cmov (%d)", host_has_cmov);
 	return(0);
 }
 
diff --git a/arch/um/sys-i386/fault.c b/arch/um/sys-i386/fault.c
index 6a0ec334c..d0bbcdfdb 100644
--- a/arch/um/sys-i386/fault.c
+++ b/arch/um/sys-i386/fault.c
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -7,16 +7,24 @@
 #include "sysdep/ptrace.h"
 #include "sysdep/sigcontext.h"
 
-extern unsigned long search_exception_table(unsigned long addr);
+/* These two are from asm-um/uaccess.h and linux/module.h, check them. */
+struct exception_table_entry
+{
+	unsigned long insn;
+	unsigned long fixup;
+};
 
+const struct exception_table_entry *search_exception_tables(unsigned long add);
+
+/* Compare this to arch/i386/mm/extable.c:fixup_exception() */
 int arch_fixup(unsigned long address, void *sc_ptr)
 {
 	struct sigcontext *sc = sc_ptr;
-	unsigned long fixup;
+	const struct exception_table_entry *fixup;
 
 	fixup = search_exception_tables(address);
 	if(fixup != 0){
-		sc->eip = fixup;
+		sc->eip = fixup->fixup;
 		return(1);
 	}
 	return(0);
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index 33e302160..ba77ccaa8 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -13,6 +13,8 @@
 #ifdef CONFIG_MODE_TT
 extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
 
+/* XXX this needs copy_to_user and copy_from_user */
+
 int sys_modify_ldt_tt(int func, void *ptr, unsigned long bytecount)
 {
 	if(verify_area(VERIFY_READ, ptr, bytecount)) return(-EFAULT);
diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c
index 70da62313..b1021e82b 100644
--- a/arch/um/sys-i386/ptrace_user.c
+++ b/arch/um/sys-i386/ptrace_user.c
@@ -39,10 +39,11 @@ static void write_debugregs(int pid, unsigned long *regs)
 	nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]);
 	for(i = 0; i < nregs; i++){
 		if((i == 4) || (i == 5)) continue;
-		if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i],
+		if(ptrace(PTRACE_POKEUSER, pid, &dummy->u_debugreg[i],
 			  regs[i]) < 0)
-			printk("write_debugregs - ptrace failed, "
-			       "errno = %d\n", errno);
+			printk("write_debugregs - ptrace failed on "
+			       "register %d, value = 0x%x, errno = %d\n", i,
+			       regs[i], errno);
 	}
 }
 
@@ -54,7 +55,7 @@ static void read_debugregs(int pid, unsigned long *regs)
 	dummy = NULL;
 	nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]);
 	for(i = 0; i < nregs; i++){
-		regs[i] = ptrace(PTRACE_PEEKUSR, pid, 
+		regs[i] = ptrace(PTRACE_PEEKUSER, pid,
 				 &dummy->u_debugreg[i], 0);
 	}
 }
diff --git a/arch/um/sys-i386/syscalls.c b/arch/um/sys-i386/syscalls.c
index 751549bd7..6ad31749b 100644
--- a/arch/um/sys-i386/syscalls.c
+++ b/arch/um/sys-i386/syscalls.c
@@ -3,6 +3,7 @@
  * Licensed under the GPL
  */
 
+#include "linux/sched.h"
 #include "asm/mman.h"
 #include "asm/uaccess.h"
 #include "asm/unistd.h"
@@ -56,6 +57,27 @@ int old_select(struct sel_arg_struct *arg)
 	return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
 }
 
+/* The i386 version skips reading from %esi, the fourth argument. So we must do
+ * this, too.
+ */
+int sys_clone(unsigned long clone_flags, unsigned long newsp, int *parent_tid,
+	      int unused, int *child_tid)
+{
+	long ret;
+
+	/* XXX: normal arch do here this pass, and also pass the regs to
+	 * do_fork, instead of NULL. Currently the arch-independent code
+	 * ignores these values, while the UML code (actually it's
+	 * copy_thread) does the right thing. But this should change,
+	 probably. */
+	/*if (!newsp)
+		newsp = UPT_SP(current->thread.regs);*/
+	current->thread.forking = 1;
+	ret = do_fork(clone_flags, newsp, NULL, 0, parent_tid, child_tid);
+	current->thread.forking = 0;
+	return(ret);
+}
+
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/sys-i386/util/Makefile b/arch/um/sys-i386/util/Makefile
index a3eca5f22..34860f9ca 100644
--- a/arch/um/sys-i386/util/Makefile
+++ b/arch/um/sys-i386/util/Makefile
@@ -1,17 +1,8 @@
 
-host-progs	:= mk_sc
-always		:= $(host-progs) mk_thread
-targets		:= mk_thread_kern.o mk_thread_user.o
+hostprogs-y	:= mk_sc mk_thread
+always		:= $(hostprogs-y)
 
-mk_sc-objs	:= mk_sc.o
+mk_thread-objs	:= mk_thread_kern.o mk_thread_user.o
 
-$(obj)/mk_thread : $(obj)/mk_thread_kern.o $(obj)/mk_thread_user.o
-	$(CC) $(CFLAGS) -o $@ $^
-
-$(obj)/mk_thread_user.o : $(src)/mk_thread_user.c
-	$(CC) $(USER_CFLAGS) -c -o $@ $<
-
-clean :
-	$(RM) -f $(build-targets)
-
-archmrproper : clean
+HOSTCFLAGS_mk_thread_kern.o	:= $(CFLAGS) $(CPPFLAGS)
+HOSTCFLAGS_mk_thread_user.o	:= $(USER_CFLAGS)
diff --git a/arch/um/sys-i386/util/mk_sc.c b/arch/um/sys-i386/util/mk_sc.c
index 224b6ad75..85cbd3039 100644
--- a/arch/um/sys-i386/util/mk_sc.c
+++ b/arch/um/sys-i386/util/mk_sc.c
@@ -38,6 +38,7 @@ int main(int argc, char **argv)
   SC_OFFSET("SC_ERR", err);
   SC_OFFSET("SC_CR2", cr2);
   SC_OFFSET("SC_FPSTATE", fpstate);
+  SC_OFFSET("SC_SIGMASK", oldmask);
   SC_FP_OFFSET("SC_FP_CW", cw);
   SC_FP_OFFSET("SC_FP_SW", sw);
   SC_FP_OFFSET("SC_FP_TAG", tag);
diff --git a/arch/um/sys-ia64/Makefile b/arch/um/sys-ia64/Makefile
index 4dd735320..d02f4c265 100644
--- a/arch/um/sys-ia64/Makefile
+++ b/arch/um/sys-ia64/Makefile
@@ -7,18 +7,5 @@ all: $(OBJ)
 $(OBJ): $(OBJS)
 	rm -f $@
 	$(LD) $(LINKFLAGS) --start-group $^ --end-group -o $@
-clean:
-	rm -f $(OBJS)
 
-fastdep:
-
-archmrproper:
-
-archclean:
-	rm -f link.ld
-	@$(MAKEBOOT) clean
-
-archdep:
-	@$(MAKEBOOT) dep
-
-modules:
+clean-files := $(OBJS) link.ld
diff --git a/arch/um/sys-ppc/Makefile b/arch/um/sys-ppc/Makefile
index 3767c2583..af200268f 100644
--- a/arch/um/sys-ppc/Makefile
+++ b/arch/um/sys-ppc/Makefile
@@ -66,13 +66,4 @@ misc.o: misc.S ppc_defs.h
 	$(CC) $(EXTRA_AFLAGS) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
 	rm -f asm
 
-clean:
-	rm -f $(OBJS)
-	rm -f ppc_defs.h
-	rm -f checksum.S semaphore.c mk_defs.c
-
-fastdep:
-
-dep:
-
-modules:
+clean-files := $(OBJS) ppc_defs.h checksum.S semaphore.c mk_defs.c
diff --git a/arch/um/util/Makefile b/arch/um/util/Makefile
index defd03861..e2ab71209 100644
--- a/arch/um/util/Makefile
+++ b/arch/um/util/Makefile
@@ -1,23 +1,8 @@
-always		:= mk_task mk_constants
-targets		:= mk_task_user.o mk_task_kern.o \
-		   mk_constants_user.o mk_constants_kern.o
+hostprogs-y		:= mk_task mk_constants
+always			:= $(hostprogs-y)
 
-$(obj)/mk_task: $(obj)/mk_task_user.o $(obj)/mk_task_kern.o
-	$(CC) -o $@ $^
+mk_task-objs		:= mk_task_user.o mk_task_kern.o
+mk_constants-objs	:= mk_constants_user.o mk_constants_kern.o
 
-$(obj)/mk_task_user.o: $(src)/mk_task_user.c
-	$(CC) -o $@ -c $< 
-
-$(obj)/mk_constants : $(obj)/mk_constants_user.o $(obj)/mk_constants_kern.o
-	$(CC) -o $@ $^
-
-$(obj)/mk_constants_user.o : $(src)/mk_constants_user.c
-	$(CC) -c $< -o $@
-
-$(obj)/mk_constants_kern.o : $(src)/mk_constants_kern.c
-	$(CC) $(CFLAGS) -c $< -o $@
-
-clean:
-	$(RM) $(build-targets)
-
-archmrproper:
+HOSTCFLAGS_mk_task_kern.o	:= $(CFLAGS) $(CPPFLAGS)
+HOSTCFLAGS_mk_constants_kern.o	:= $(CFLAGS) $(CPPFLAGS)
diff --git a/arch/um/util/mk_constants_kern.c b/arch/um/util/mk_constants_kern.c
index 7e7493431..cdcb1232a 100644
--- a/arch/um/util/mk_constants_kern.c
+++ b/arch/um/util/mk_constants_kern.c
@@ -1,5 +1,6 @@
 #include "linux/kernel.h"
 #include "linux/stringify.h"
+#include "linux/time.h"
 #include "asm/page.h"
 
 extern void print_head(void);
@@ -11,6 +12,7 @@ int main(int argc, char **argv)
 {
   print_head();
   print_constant_int("UM_KERN_PAGE_SIZE", PAGE_SIZE);
+
   print_constant_str("UM_KERN_EMERG", KERN_EMERG);
   print_constant_str("UM_KERN_ALERT", KERN_ALERT);
   print_constant_str("UM_KERN_CRIT", KERN_CRIT);
@@ -19,6 +21,8 @@ int main(int argc, char **argv)
   print_constant_str("UM_KERN_NOTICE", KERN_NOTICE);
   print_constant_str("UM_KERN_INFO", KERN_INFO);
   print_constant_str("UM_KERN_DEBUG", KERN_DEBUG);
+
+  print_constant_int("UM_NSEC_PER_SEC", NSEC_PER_SEC);
   print_tail();
   return(0);
 }
diff --git a/arch/v850/Kconfig b/arch/v850/Kconfig
index 994e4f859..5775f4fa7 100644
--- a/arch/v850/Kconfig
+++ b/arch/v850/Kconfig
@@ -68,7 +68,6 @@ menu "Processor type and features"
       	     bool "Anna"
    endchoice
 
-
    #### V850E processor-specific config
 
    # All CPUs currently supported use the v850e architecture
@@ -153,7 +152,6 @@ menu "Processor type and features"
    	  bool
 	  default RTE_MB_A_PCI
 
-
    #### Some feature-specific configs
 
    # Everything except for the GDB simulator uses the same interrupt controller
@@ -181,7 +179,6 @@ menu "Processor type and features"
    	  bool
 	  default !V850E_CACHE && !V850E2_CACHE
 
-
    #### Misc config
 
    config ROM_KERNEL
@@ -305,34 +302,7 @@ source "sound/Kconfig"
 
 source "drivers/usb/Kconfig"
 
-
-menu "Kernel hacking"
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  If you don't debug the kernel, you can say N.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	depends on DEBUG_KERNEL
-	help
-	  Enables console device to interprent special characters as
-	  commands to dump state information.
-
-config NO_KERNEL_MSG
-	bool "Suppress Kernel BUG Messages"
-	help
-	  Do not output any debug BUG messages within the kernel.
-
-endmenu
+source "arch/v850/Kconfig.debug"
 
 source "kernel/vserver/Kconfig"
 
diff --git a/arch/v850/kernel/Makefile b/arch/v850/kernel/Makefile
index 117bcaaa0..3930482bd 100644
--- a/arch/v850/kernel/Makefile
+++ b/arch/v850/kernel/Makefile
@@ -9,7 +9,7 @@
 # for more details.
 #
 
-extra-y := head.o init_task.o vmlinux.lds.s
+extra-y := head.o init_task.o vmlinux.lds
 
 obj-y += intv.o entry.o process.o syscalls.o time.o semaphore.o setup.o \
 	 signal.o irq.o mach.o ptrace.o bug.o
diff --git a/arch/v850/kernel/asm-consts.c b/arch/v850/kernel/asm-consts.c
index 666930d9c..24f291369 100644
--- a/arch/v850/kernel/asm-consts.c
+++ b/arch/v850/kernel/asm-consts.c
@@ -12,8 +12,8 @@
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <linux/ptrace.h>
+#include <linux/hardirq.h>
 #include <asm/irq.h>
-#include <asm/hardirq.h>
 #include <asm/errno.h>
 
 #define DEFINE(sym, val) \
diff --git a/arch/v850/kernel/irq.c b/arch/v850/kernel/irq.c
index 89809fb98..336cbf21d 100644
--- a/arch/v850/kernel/irq.c
+++ b/arch/v850/kernel/irq.c
@@ -141,13 +141,15 @@ skip:
 int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
 {
 	int status = 1; /* Force the "do bottom halves" bit */
+	int ret;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
-		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
diff --git a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c
index 7d2554774..bf43ea660 100644
--- a/arch/v850/kernel/ptrace.c
+++ b/arch/v850/kernel/ptrace.c
@@ -149,14 +149,8 @@ int sys_ptrace(long request, long pid, long addr, long data)
 		rval = ptrace_attach(child);
 		goto out_tsk;
 	}
-	rval = -ESRCH;
-	if (!(child->ptrace & PT_PTRACED))
-		goto out_tsk;
-	if (child->state != TASK_STOPPED) {
-		if (request != PTRACE_KILL)
-			goto out_tsk;
-	}
-	if (child->parent != current)
+	ret = ptrace_check_attach(child, request == PTRACE_KILL);
+	if (ret < 0)
 		goto out_tsk;
 
 	switch (request) {
@@ -271,11 +265,8 @@ asmlinkage void syscall_trace(void)
 		return;
 	/* The 0x80 provides a way for the tracing parent to distinguish
 	   between a syscall stop and SIGTRAP delivery */
-	current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-					? 0x80 : 0);
-	current->state = TASK_STOPPED;
-	notify_parent(current, SIGCHLD);
-	schedule();
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+				 ? 0x80 : 0));
 	/*
 	 * this isn't the same as continuing with a signal, but it will do
 	 * for normal use.  strace only continues with a signal if the
diff --git a/arch/v850/kernel/rte_mb_a_pci.c b/arch/v850/kernel/rte_mb_a_pci.c
index da39beb8e..551c41ba0 100644
--- a/arch/v850/kernel/rte_mb_a_pci.c
+++ b/arch/v850/kernel/rte_mb_a_pci.c
@@ -322,8 +322,6 @@ pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
 
 /* Stubs for things we don't use.  */
 
-struct pci_fixup pcibios_fixups[] = { { 0 } };
-
 /* Called after each bus is probed, but before its children are examined. */
 void pcibios_fixup_bus(struct pci_bus *b)
 {
diff --git a/arch/v850/kernel/setup.c b/arch/v850/kernel/setup.c
index 8e8bf5ddc..dacc9b331 100644
--- a/arch/v850/kernel/setup.c
+++ b/arch/v850/kernel/setup.c
@@ -280,8 +280,8 @@ init_mem_alloc (unsigned long ram_start, unsigned long ram_len)
 #if ((PAGE_OFFSET >> PAGE_SHIFT) & ((1UL << (MAX_ORDER - 1)) - 1))
 #error MAX_ORDER is too large for given PAGE_OFFSET (use CONFIG_FORCE_MAX_ZONEORDER to change it)
 #endif
-
-	free_area_init_node (0, NODE_DATA(0), 0, zones_size,
+	NODE_DATA(0)->node_mem_map = NULL;
+	free_area_init_node (0, NODE_DATA(0), zones_size,
 			     ADDR_TO_PAGE (PAGE_OFFSET), 0);
 	mem_map = NODE_DATA(0)->node_mem_map;
 }
diff --git a/arch/v850/kernel/signal.c b/arch/v850/kernel/signal.c
index caa9e3a04..60098e4f0 100644
--- a/arch/v850/kernel/signal.c
+++ b/arch/v850/kernel/signal.c
@@ -344,9 +344,7 @@ static void setup_frame(int sig, struct k_sigaction *ka,
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -421,9 +419,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 }
 
 /*
diff --git a/arch/v850/kernel/time.c b/arch/v850/kernel/time.c
index 74067adea..d0266de06 100644
--- a/arch/v850/kernel/time.c
+++ b/arch/v850/kernel/time.c
@@ -40,24 +40,6 @@ unsigned long long sched_clock(void)
 	return (unsigned long long)jiffies * (1000000000 / HZ);
 }
 
-static inline void do_profile (unsigned long pc)
-{
-	if (prof_buffer && current->pid) {
-		extern int _stext;
-		pc -= (unsigned long) &_stext;
-		pc >>= prof_shift;
-		if (pc < prof_len)
-			++prof_buffer[pc];
-		else
-		/*
-		 * Don't ignore out-of-bounds PC values silently,
-		 * put them into the last histogram slot, so if
-		 * present, they will show up as a sharp peak.
-		 */
-			++prof_buffer[prof_len-1];
-	}
-}
-
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
@@ -74,10 +56,7 @@ static irqreturn_t timer_interrupt (int irq, void *dummy, struct pt_regs *regs)
 	  mach_tick ();
 
 	do_timer (regs);
-
-	if (! user_mode (regs))
-		do_profile (regs->pc);
-
+	profile_tick(CPU_PROFILING, regs);
 #if 0
 	/*
 	 * If we have an externally synchronized Linux clock, then update
diff --git a/arch/v850/kernel/v850_ksyms.c b/arch/v850/kernel/v850_ksyms.c
index 2336da438..0ca64900d 100644
--- a/arch/v850/kernel/v850_ksyms.c
+++ b/arch/v850/kernel/v850_ksyms.c
@@ -14,7 +14,6 @@
 #include <asm/io.h>
 #include <asm/semaphore.h>
 #include <asm/checksum.h>
-#include <asm/hardirq.h>
 #include <asm/current.h>
 
 
@@ -37,29 +36,29 @@ EXPORT_SYMBOL (ip_compute_csum);
 EXPORT_SYMBOL (ip_fast_csum);
 
 /* string / mem functions */
-EXPORT_SYMBOL_NOVERS (strcpy);
-EXPORT_SYMBOL_NOVERS (strncpy);
-EXPORT_SYMBOL_NOVERS (strcat);
-EXPORT_SYMBOL_NOVERS (strncat);
-EXPORT_SYMBOL_NOVERS (strcmp);
-EXPORT_SYMBOL_NOVERS (strncmp);
-EXPORT_SYMBOL_NOVERS (strchr);
-EXPORT_SYMBOL_NOVERS (strlen);
-EXPORT_SYMBOL_NOVERS (strnlen);
-EXPORT_SYMBOL_NOVERS (strpbrk);
-EXPORT_SYMBOL_NOVERS (strrchr);
-EXPORT_SYMBOL_NOVERS (strstr);
-EXPORT_SYMBOL_NOVERS (memset);
-EXPORT_SYMBOL_NOVERS (memcpy);
-EXPORT_SYMBOL_NOVERS (memmove);
-EXPORT_SYMBOL_NOVERS (memcmp);
-EXPORT_SYMBOL_NOVERS (memscan);
+EXPORT_SYMBOL (strcpy);
+EXPORT_SYMBOL (strncpy);
+EXPORT_SYMBOL (strcat);
+EXPORT_SYMBOL (strncat);
+EXPORT_SYMBOL (strcmp);
+EXPORT_SYMBOL (strncmp);
+EXPORT_SYMBOL (strchr);
+EXPORT_SYMBOL (strlen);
+EXPORT_SYMBOL (strnlen);
+EXPORT_SYMBOL (strpbrk);
+EXPORT_SYMBOL (strrchr);
+EXPORT_SYMBOL (strstr);
+EXPORT_SYMBOL (memset);
+EXPORT_SYMBOL (memcpy);
+EXPORT_SYMBOL (memmove);
+EXPORT_SYMBOL (memcmp);
+EXPORT_SYMBOL (memscan);
 
 /* semaphores */
-EXPORT_SYMBOL_NOVERS (__down);
-EXPORT_SYMBOL_NOVERS (__down_interruptible);
-EXPORT_SYMBOL_NOVERS (__down_trylock);
-EXPORT_SYMBOL_NOVERS (__up);
+EXPORT_SYMBOL (__down);
+EXPORT_SYMBOL (__down_interruptible);
+EXPORT_SYMBOL (__down_trylock);
+EXPORT_SYMBOL (__up);
 
 /*
  * libgcc functions - functions that are used internally by the
@@ -72,8 +71,8 @@ extern void __lshrdi3 (void);
 extern void __muldi3 (void);
 extern void __negdi2 (void);
 
-EXPORT_SYMBOL_NOVERS (__ashldi3);
-EXPORT_SYMBOL_NOVERS (__ashrdi3);
-EXPORT_SYMBOL_NOVERS (__lshrdi3);
-EXPORT_SYMBOL_NOVERS (__muldi3);
-EXPORT_SYMBOL_NOVERS (__negdi2);
+EXPORT_SYMBOL (__ashldi3);
+EXPORT_SYMBOL (__ashrdi3);
+EXPORT_SYMBOL (__lshrdi3);
+EXPORT_SYMBOL (__muldi3);
+EXPORT_SYMBOL (__negdi2);
diff --git a/arch/v850/kernel/vmlinux.lds.S b/arch/v850/kernel/vmlinux.lds.S
index 71669f7a9..bab351c37 100644
--- a/arch/v850/kernel/vmlinux.lds.S
+++ b/arch/v850/kernel/vmlinux.lds.S
@@ -111,9 +111,6 @@
 			*(.init.setup)	/* 2.5 convention */		      \
 			*(.setup.init)	/* 2.4 convention */		      \
 		___setup_end = . ;					      \
-		___start___param = . ;					      \
-			*(__param)					      \
-		___stop___param = . ;					      \
 		___initcall_start = . ;					      \
 			*(.initcall.init)				      \
 			*(.initcall1.init)				      \
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 1c07776ac..7bb22c5d1 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -4,7 +4,7 @@
 #
 # Note: ISA is disabled and will hopefully never be enabled.
 # If you managed to buy an ISA x86-64 box you'll have to fix all the
-# ISA drivers you need yourself. 
+# ISA drivers you need yourself.
 #
 
 mainmenu "Linux Kernel Configuration"
@@ -57,7 +57,7 @@ config EARLY_PRINTK
 	  it is not recommended because it looks ugly and doesn't cooperate
 	  with klogd/syslogd or the X server. You should normally N here,
 	  unless you want to debug such a crash.
-	  
+
 config HPET_TIMER
 	bool
 	default y
@@ -78,6 +78,10 @@ config GENERIC_ISA_DMA
 	bool
 	default y
 
+config GENERIC_IOMAP
+	bool
+	default y
+
 source "init/Kconfig"
 
 
@@ -90,14 +94,14 @@ choice
 config MK8
 	bool "AMD-Opteron/Athlon64"
 	help
-	  Optimize for AMD Opteron/Athlon64/Hammer/K8 CPUs. 
+	  Optimize for AMD Opteron/Athlon64/Hammer/K8 CPUs.
 
 config MPSC
-       bool "Intel x86-64" 
+       bool "Intel x86-64"
        help
 	  Optimize for Intel IA32 with 64bit extension CPUs
 	  (Prescott/Nocona/Potomac)
-       
+
 config GENERIC_CPU
 	bool "Generic-x86-64"
 	help
@@ -130,8 +134,8 @@ config MICROCODE
 	tristate "/dev/cpu/microcode - Intel CPU microcode support"
 	---help---
 	  If you say Y here the 'File systems' section, you will be
-	  able to update the microcode on Intel processors. You will 
-	  obviously need the actual microcode binary data itself which is 
+	  able to update the microcode on Intel processors. You will
+	  obviously need the actual microcode binary data itself which is
 	  not shipped with the Linux kernel.
 
 	  For latest news and information on obtaining all the required
@@ -165,7 +169,7 @@ config X86_HT
 	bool
 	depends on SMP && !MK8
 	default y
-       
+
 config MATH_EMULATION
 	bool
 
@@ -231,13 +235,13 @@ config PREEMPT
 	  be preempted even if it is in kernel mode executing a system call.
 	  This allows applications to run more reliably even when the system is
 	  under load. On contrary it may also break your drivers and add
-	  priority inheritance problems to your system. Don't select it if 
+	  priority inheritance problems to your system. Don't select it if
 	  you rely on a stable system or have slightly obscure hardware.
 	  It's also not very well tested on x86-64 currently.
 	  You have been warned.
 
-	  Say Y here if you are feeling brave and building a kernel for a 
-	  desktop, embedded or real-time system.  Say N if you are unsure. 
+	  Say Y here if you are feeling brave and building a kernel for a
+	  desktop, embedded or real-time system.  Say N if you are unsure.
 
 config SCHED_SMT
 	bool "SMT (Hyperthreading) scheduler support"
@@ -297,7 +301,7 @@ config GART_IOMMU
 	  properly with 32-bit PCI devices that do not support DAC (Double Address
 	  Cycle). The IOMMU can be turned off at runtime with the iommu=off parameter.
 	  Normally the kernel will take the right choice by itself.
-	  If unsure say Y 
+	  If unsure, say Y.
 
 # need this always enabled with GART_IOMMU for the VIA workaround
 config SWIOTLB
@@ -310,13 +314,18 @@ config DUMMY_IOMMU
 	depends on !GART_IOMMU && !SWIOTLB
 	default y
 	help
-	  Don't use IOMMU code. This will cause problems when you have more than 4GB 
+	  Don't use IOMMU code. This will cause problems when you have more than 4GB
 	  of memory and any 32-bit devices. Don't turn on unless you know what you
 	  are doing.
 
 config X86_MCE
-	bool
+	bool "Machine check support" if EMBEDDED
 	default y
+	help
+	   Include a machine check error handler to report hardware errors.
+	   This version will require the mcelog utility to decode some
+	   machine check error logs. See
+	   ftp://ftp.x86-64.org/pub/linux/tools/mcelog
 
 endmenu
 
@@ -336,17 +345,27 @@ menu "Bus options (PCI etc.)"
 config PCI
 	bool "PCI support"
 
-# x86-64 doesn't support PCI BIOS access from long mode so always go direct. 
+# x86-64 doesn't support PCI BIOS access from long mode so always go direct.
 config PCI_DIRECT
 	bool
 	depends on PCI
 	default y
 
-config PCI_MMCONFIG 
-	bool "Support mmconfig PCI config space access" 
+config PCI_MMCONFIG
+	bool "Support mmconfig PCI config space access"
 	depends on PCI
 	select ACPI_BOOT
 
+config UNORDERED_IO
+       bool "Unordered IO mapping access"
+       depends on EXPERIMENTAL
+       help
+         Use unordered stores to access IO memory mappings in device drivers.
+	 Still very experimental. When a driver works on IA64/ppc64/pa-risc it should
+	 work with this option, but it makes the drivers behave differently
+	 from i386. Requires that the driver writer used memory barriers
+	 properly.
+
 source "drivers/pci/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
@@ -398,106 +417,7 @@ source fs/Kconfig
 
 source "arch/x86_64/oprofile/Kconfig"
 
-menu "Kernel hacking"
-
-config DEBUG_KERNEL
-	bool "Kernel debugging"
-	help
-	  Say Y here if you are developing drivers or trying to debug and
-	  identify kernel problems.
-
-config DEBUG_SLAB
-	bool "Debug memory allocations"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here to have the kernel do limited verification on memory
-	  allocation as well as poisoning memory on free to catch use of freed
-	  memory.
-
-config MAGIC_SYSRQ
-	bool "Magic SysRq key"
-	help
-	  If you say Y here, you will have some control over the system even
-	  if the system crashes for example during kernel debugging (e.g., you
-	  will be able to flush the buffer cache to disk, reboot the system
-	  immediately or dump some status information). This is accomplished
-	  by pressing various keys while holding SysRq (Alt+PrintScreen). It
-	  also works on a serial console (on PC hardware at least), if you
-	  send a BREAK and then within 5 seconds a command keypress. The
-	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
-	  unless you really know what this hack does.
-
-config DEBUG_SPINLOCK
-	bool "Spinlock debugging"
-	depends on DEBUG_KERNEL
-	help
-	  Say Y here and build SMP to catch missing spinlock initialization
-	  and certain other kinds of spinlock errors commonly made.  This is
-	  best used in conjunction with the NMI watchdog so that spinlock
-	  deadlocks are also debuggable.
-
-# !SMP for now because the context switch early causes GPF in segment reloading
-# and the GS base checking does the wrong thing then, causing a hang.
-config CHECKING
-	bool "Additional run-time checks"
-	depends on DEBUG_KERNEL && !SMP
-	help
-	  Enables some internal consistency checks for kernel debugging.
-	  You should normally say N.
-
-config INIT_DEBUG
-	bool "Debug __init statements"
-	depends on DEBUG_KERNEL
-	help
-	  Fill __init and __initdata at the end of boot. This helps debugging
-	  illegal uses of __init and __initdata after initialization.	  
-
-config DEBUG_INFO
-	bool "Compile the kernel with debug info"
-	depends on DEBUG_KERNEL
-	help
-          If you say Y here the resulting kernel image will include
-	  debugging info resulting in a larger kernel image.
-	  Say Y here only if you plan to use gdb to debug the kernel.
-	  Please note that this option requires new binutils.
-	  If you don't debug the kernel, you can say N.
-	  
-config FRAME_POINTER
-       bool "Compile the kernel with frame pointers"
-       help
-	 Compile the kernel with frame pointers. This may help for some 
-	 debugging with external debuggers. Note the standard oops backtracer 
-	 doesn't make use of this  and the x86-64 kernel doesn't ensure an consistent
-	 frame pointer through inline assembly (semaphores etc.)
-	 Normally you should say N.
-
-config IOMMU_DEBUG
-       depends on GART_IOMMU && DEBUG_KERNEL
-       bool "Enable IOMMU debugging"
-       help
-         Force the IOMMU to on even when you have less than 4GB of
-	 memory and add debugging code. On overflow always panic. And
-	 allow to enable IOMMU leak tracing. Can be disabled at boot
-	 time with iommu=noforce. This will also enable scatter gather
-	 list merging.  Currently not recommended for production
-	 code. When you use it make sure you have a big enough
-	 IOMMU/AGP aperture.  Most of the options enabled by this can
-	 be set more finegrained using the iommu= command line
-	 options. See Documentation/x86_64/boot-options.txt for more
-	 details.
-
-config IOMMU_LEAK
-       bool "IOMMU leak tracing"
-       depends on DEBUG_KERNEL
-       depends on IOMMU_DEBUG
-       help
-         Add a simple leak tracer to the IOMMU code. This is useful when you
-	 are debugging a buggy device driver that leaks IOMMU mappings.
-       
-#config X86_REMOTE_DEBUG
-#       bool "kgdb debugging stub"
-
-endmenu
+source "arch/x86_64/Kconfig.debug"
 
 source "kernel/vserver/Kconfig"
 
@@ -506,4 +426,3 @@ source "security/Kconfig"
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
-
diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile
index 9b9a504ef..a69f7bcdf 100644
--- a/arch/x86_64/Makefile
+++ b/arch/x86_64/Makefile
@@ -37,10 +37,10 @@ LDFLAGS		:= -m elf_x86_64
 OBJCOPYFLAGS	:= -O binary -R .note -R .comment -S
 LDFLAGS_vmlinux := -e stext
 
-CHECK           := $(CHECK) -D__x86_64__=1
+CHECKFLAGS      += -D__x86_64__ -m64
 
-cflags-$(CONFIG_MK8) += $(call check_gcc,-march=k8,)
-cflags-$(CONFIG_MPSC) += $(call check_gcc,-march=nocona,)
+cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
+cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona)
 CFLAGS += $(cflags-y)
 
 CFLAGS += -mno-red-zone
@@ -54,11 +54,11 @@ ifneq ($(CONFIG_DEBUG_INFO),y)
 CFLAGS += -fno-asynchronous-unwind-tables
 # -fweb shrinks the kernel a bit, but the difference is very small
 # it also messes up debugging, so don't use it for now.
-#CFLAGS += $(call check_gcc,-fweb,)
+#CFLAGS += $(call cc-option,-fweb)
 endif
 # -funit-at-a-time shrinks the kernel .text considerably
 # unfortunately it makes reading oopses harder.
-CFLAGS += $(call check_gcc,-funit-at-a-time,)
+CFLAGS += $(call cc-option,-funit-at-a-time)
 
 head-y := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o
 
@@ -77,6 +77,7 @@ boot := arch/x86_64/boot
 all: bzImage
 
 BOOTIMAGE                     := arch/x86_64/boot/bzImage
+KBUILD_IMAGE                  := $(BOOTIMAGE)
 
 bzImage: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $(BOOTIMAGE)
diff --git a/arch/x86_64/boot/Makefile b/arch/x86_64/boot/Makefile
index 1c2d3cbca..99b790439 100644
--- a/arch/x86_64/boot/Makefile
+++ b/arch/x86_64/boot/Makefile
@@ -30,7 +30,7 @@ targets		:= vmlinux.bin bootsect bootsect.o \
 
 EXTRA_CFLAGS := -m32
 
-host-progs	:= tools/build
+hostprogs-y	:= tools/build
 subdir-		:= compressed/	#Let make clean descend in compressed/
 # ---------------------------------------------------------------------------
 
diff --git a/arch/x86_64/boot/video.S b/arch/x86_64/boot/video.S
index 5d4cdc1ab..fd0cc734a 100644
--- a/arch/x86_64/boot/video.S
+++ b/arch/x86_64/boot/video.S
@@ -66,6 +66,7 @@
 #define VIDEO_80x30 0x0f05
 #define VIDEO_80x34 0x0f06
 #define VIDEO_80x60 0x0f07
+#define VIDEO_GFX_HACK 0x0f08
 #define VIDEO_LAST_SPECIAL 0x0f09
 
 /* Video modes given by resolution */
@@ -97,7 +98,6 @@
 #define PARAM_LFB_PAGES		0x32
 #define PARAM_VESA_ATTRIB	0x34
 
-
 /* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
 #ifdef CONFIG_VIDEO_RETAIN
 #define DO_STORE call store_screen
@@ -133,6 +133,7 @@ vid1:
 #ifdef CONFIG_VIDEO_RETAIN
 	call	restore_screen			# Restore screen contents
 #endif /* CONFIG_VIDEO_RETAIN */
+	call	store_edid
 #endif /* CONFIG_VIDEO_SELECT */
 	call	mode_params			# Store mode parameters
 	popw	%ds				# Restore original DS
@@ -231,6 +232,41 @@ mopar_gr:
 	xorl	%eax, %eax
 	movw	18(%di), %ax
 	movl	%eax, %fs:(PARAM_LFB_SIZE)
+
+# switching the DAC to 8-bit is for <= 8 bpp only
+	movw	%fs:(PARAM_LFB_DEPTH), %ax
+	cmpw	$8, %ax
+	jg	dac_done
+
+# get DAC switching capability
+	xorl	%eax, %eax
+	movb	10(%di), %al
+	testb	$1, %al
+	jz	dac_set
+
+# attempt to switch DAC to 8-bit
+	movw	$0x4f08, %ax
+	movw	$0x0800, %bx
+	int	$0x10
+	cmpw	$0x004f, %ax
+	jne     dac_set
+	movb    %bh, dac_size		# store actual DAC size
+
+dac_set:
+# set color size to DAC size
+	movb	dac_size, %al
+	movb	%al, %fs:(PARAM_LFB_COLORS+0)
+	movb	%al, %fs:(PARAM_LFB_COLORS+2)
+	movb	%al, %fs:(PARAM_LFB_COLORS+4)
+	movb	%al, %fs:(PARAM_LFB_COLORS+6)
+
+# set color offsets to 0
+	movb	$0, %fs:(PARAM_LFB_COLORS+1)
+	movb	$0, %fs:(PARAM_LFB_COLORS+3)
+	movb	$0, %fs:(PARAM_LFB_COLORS+5)
+	movb	$0, %fs:(PARAM_LFB_COLORS+7)
+
+dac_done:
 # get protected mode interface informations
 	movw	$0x4f0a, %ax
 	xorw	%bx, %bx
@@ -440,7 +476,7 @@ setalias:
 
 # Setting of user mode (AX=mode ID) => CF=success
 mode_set:
-       	movw    %ax, %fs:(0x01fa)
+	movw	%ax, %fs:(0x01fa)		# Store mode for use in acpi_wakeup.S
 	movw	%ax, %bx
 	cmpb	$0xff, %ah
 	jz	setalias
@@ -744,7 +780,15 @@ set_80x60:
 	movw	$0x503c, force_size
 	jmp	setvde
 
+# Special hack for ThinkPad graphics
 set_gfx:
+#ifdef CONFIG_VIDEO_GFX_HACK
+	movw	$VIDEO_GFX_BIOS_AX, %ax
+	movw	$VIDEO_GFX_BIOS_BX, %bx
+	int	$0x10
+	movw	$VIDEO_GFX_DUMMY_RESOLUTION, force_size
+	stc
+#endif
 	ret
 
 #ifdef CONFIG_VIDEO_RETAIN
@@ -969,6 +1013,10 @@ vga_modes:
 	.word	0x5022				# 80x34
 	.word	VIDEO_80x60
 	.word	0x503c				# 80x60
+#ifdef CONFIG_VIDEO_GFX_HACK
+	.word	VIDEO_GFX_HACK
+	.word	VIDEO_GFX_DUMMY_RESOLUTION
+#endif
 
 vga_modes_end:
 # Detect VESA modes.
@@ -1875,6 +1923,39 @@ skip10:	movb	%ah, %al
 	popw	%ax
 	ret
 
+store_edid:
+	pushw	%es				# just save all registers
+	pushw	%ax
+	pushw	%bx
+	pushw   %cx
+	pushw	%dx
+	pushw   %di
+
+	pushw	%fs
+	popw    %es
+
+	movl	$0x13131313, %eax		# memset block with 0x13
+	movw    $32, %cx
+	movw	$0x440, %di
+	cld
+	rep
+	stosl
+
+	movw	$0x4f15, %ax                    # do VBE/DDC
+	movw	$0x01, %bx
+	movw	$0x00, %cx
+	movw    $0x01, %dx
+	movw	$0x440, %di
+	int	$0x10
+
+	popw	%di				# restore all registers
+	popw	%dx
+	popw	%cx
+	popw	%bx
+	popw	%ax
+	popw	%es
+	ret
+
 # VIDEO_SELECT-only variables
 mt_end:		.word	0	# End of video mode table if built
 edit_buf:	.space	6	# Line editor buffer
@@ -1883,6 +1964,7 @@ scanning:	.byte	0	# Performing mode scan
 do_restore:	.byte	0	# Screen contents altered during mode change
 svga_prefix:	.byte	VIDEO_FIRST_BIOS>>8	# Default prefix for BIOS modes
 graphic_mode:	.byte	0	# Graphic mode with a linear frame buffer
+dac_size:	.byte	6	# DAC bit depth
 
 # Status messages
 keymsg:		.ascii	"Press <RETURN> to see video modes available, "
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index bf6969fa0..ae2f4bfea 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,5 +1,7 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc1-bk19
+# Sun Sep 12 23:13:23 2004
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -17,11 +19,11 @@ CONFIG_GENERIC_ISA_DMA=y
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
@@ -35,6 +37,7 @@ CONFIG_IKCONFIG_PROC=y
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_IOSCHED_NOOP=y
@@ -42,6 +45,8 @@ CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -123,6 +128,8 @@ CONFIG_ACPI_SYSTEM=y
 CONFIG_PCI=y
 CONFIG_PCI_DIRECT=y
 CONFIG_PCI_MMCONFIG=y
+CONFIG_UNORDERED_IO=y
+CONFIG_PCI_MSI=y
 # CONFIG_PCI_LEGACY_PROC is not set
 # CONFIG_PCI_NAMES is not set
 
@@ -144,6 +151,8 @@ CONFIG_UID16=y
 #
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_DEBUG_DRIVER is not set
 
 #
@@ -171,7 +180,8 @@ CONFIG_BLK_DEV_FD=y
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_CARMEL 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_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
@@ -186,10 +196,10 @@ 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_IDEDISK_STROKE is not set
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -273,16 +283,24 @@ CONFIG_BLK_DEV_SD=y
 # SCSI low-level drivers
 #
 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 is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_MEGARAID is not set
+CONFIG_SCSI_AIC79XX=y
+CONFIG_AIC79XX_CMDS_PER_DEVICE=32
+CONFIG_AIC79XX_RESET_DELAY_MS=4000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
 CONFIG_SCSI_SATA=y
 # CONFIG_SCSI_SATA_SVW is not set
 CONFIG_SCSI_ATA_PIIX=y
+# CONFIG_SCSI_SATA_NV is not set
 # CONFIG_SCSI_SATA_PROMISE is not set
 # CONFIG_SCSI_SATA_SX4 is not set
 # CONFIG_SCSI_SATA_SIL is not set
@@ -290,7 +308,6 @@ CONFIG_SCSI_ATA_PIIX=y
 CONFIG_SCSI_SATA_VIA=y
 # CONFIG_SCSI_SATA_VITESSE is not set
 # CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_PIO is not set
@@ -324,7 +341,6 @@ CONFIG_SCSI_QLA2XXX=y
 #
 CONFIG_FUSION=y
 CONFIG_FUSION_MAX_SGE=40
-# CONFIG_FUSION_ISENSE is not set
 # CONFIG_FUSION_CTL is not set
 
 #
@@ -362,11 +378,13 @@ CONFIG_IP_MULTICAST=y
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
 CONFIG_IPV6=y
 # CONFIG_IPV6_PRIVACY is not set
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_IPV6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
@@ -392,6 +410,7 @@ CONFIG_IPV6=y
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
@@ -452,6 +471,7 @@ CONFIG_8139TOO=m
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -575,7 +595,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
 
 #
 # IPMI
@@ -602,6 +621,9 @@ CONFIG_AGP_AMD64=y
 # CONFIG_DRM is not set
 # CONFIG_MWAVE is not set
 CONFIG_RAW_DRIVER=y
+CONFIG_HPET=y
+# CONFIG_HPET_RTC_IRQ is not set
+CONFIG_HPET_MMAP=y
 CONFIG_MAX_RAW_DEVS=256
 CONFIG_HANGCHECK_TIMER=y
 
@@ -610,6 +632,11 @@ CONFIG_HANGCHECK_TIMER=y
 #
 # CONFIG_I2C is not set
 
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
 #
 # Misc devices
 #
@@ -635,7 +662,6 @@ CONFIG_HANGCHECK_TIMER=y
 # Console display driver support
 #
 CONFIG_VGA_CONSOLE=y
-# CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 
 #
@@ -686,6 +712,8 @@ CONFIG_USB=y
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
 
 #
 # USB Host Controller Drivers
@@ -706,6 +734,7 @@ CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_PRINTER=y
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_RW_DETECT is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
@@ -830,7 +859,8 @@ CONFIG_ISO9660_FS=y
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
 # CONFIG_NTFS_FS is not set
 
 #
@@ -879,6 +909,7 @@ CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
@@ -906,12 +937,14 @@ CONFIG_OPROFILE=y
 # Kernel hacking
 #
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SLAB is not set
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_INIT_DEBUG is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_FRAME_POINTER is not set
+# CONFIG_INIT_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
 # CONFIG_IOMMU_DEBUG is not set
 
 #
@@ -927,5 +960,6 @@ CONFIG_MAGIC_SYSRQ=y
 #
 # Library routines
 #
+# CONFIG_CRC_CCITT is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
index 7ac15ab78..0992f5934 100644
--- a/arch/x86_64/ia32/ia32_binfmt.c
+++ b/arch/x86_64/ia32/ia32_binfmt.c
@@ -301,6 +301,9 @@ MODULE_AUTHOR("Eric Youngdale, Andi Kleen");
 
 #define elf_addr_t __u32
 
+#undef TASK_SIZE
+#define TASK_SIZE 0xffffffff
+
 static void elf32_init(struct pt_regs *);
 
 #include "../../../fs/binfmt_elf.c" 
@@ -368,9 +371,9 @@ int setup_arg_pages(struct linux_binprm *bprm, int executable_stack)
  		mpnt->vm_page_prot = (mpnt->vm_flags & VM_EXEC) ? 
  			PAGE_COPY_EXEC : PAGE_COPY;
 		insert_vm_struct(mm, mpnt);
-		// mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
-		vx_vmpages_sub(mm, mm->total_vm -
-			((mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT));
+		// mm->stack_vm = mm->total_vm = vma_pages(mpnt);
+		vx_vmpages_sub(mm, mm->total_vm - vma_pages(mpnt));
+		mm->stack_vm = mm->total_vm;
 	} 
 
 	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
diff --git a/arch/x86_64/ia32/ia32_ioctl.c b/arch/x86_64/ia32/ia32_ioctl.c
index 8c6964245..d259f8a6f 100644
--- a/arch/x86_64/ia32/ia32_ioctl.c
+++ b/arch/x86_64/ia32/ia32_ioctl.c
@@ -171,23 +171,8 @@ struct ioctl_trans ioctl_start[] = {
 COMPATIBLE_IOCTL(HDIO_SET_KEEPSETTINGS)
 COMPATIBLE_IOCTL(HDIO_SCAN_HWIF)
 COMPATIBLE_IOCTL(BLKRASET)
-COMPATIBLE_IOCTL(BLKFRASET)
 COMPATIBLE_IOCTL(0x4B50)   /* KDGHWCLK - not in the kernel, but don't complain */
 COMPATIBLE_IOCTL(0x4B51)   /* KDSHWCLK - not in the kernel, but don't complain */
-COMPATIBLE_IOCTL(RTC_AIE_ON)
-COMPATIBLE_IOCTL(RTC_AIE_OFF)
-COMPATIBLE_IOCTL(RTC_UIE_ON)
-COMPATIBLE_IOCTL(RTC_UIE_OFF)
-COMPATIBLE_IOCTL(RTC_PIE_ON)
-COMPATIBLE_IOCTL(RTC_PIE_OFF)
-COMPATIBLE_IOCTL(RTC_WIE_ON)
-COMPATIBLE_IOCTL(RTC_WIE_OFF)
-COMPATIBLE_IOCTL(RTC_ALM_SET)
-COMPATIBLE_IOCTL(RTC_ALM_READ)
-COMPATIBLE_IOCTL(RTC_RD_TIME)
-COMPATIBLE_IOCTL(RTC_SET_TIME)
-COMPATIBLE_IOCTL(RTC_WKALM_SET)
-COMPATIBLE_IOCTL(RTC_WKALM_RD)
 COMPATIBLE_IOCTL(FIOQSIZE)
 
 /* And these ioctls need translation */
diff --git a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c
index 5716c8bec..5fb7d173b 100644
--- a/arch/x86_64/ia32/ia32_signal.c
+++ b/arch/x86_64/ia32/ia32_signal.c
@@ -115,7 +115,8 @@ int ia32_copy_siginfo_from_user(siginfo_t *to, siginfo_t32 __user *from)
 }
 
 asmlinkage long
-sys32_sigsuspend(int history0, int history1, old_sigset_t mask, struct pt_regs regs)
+sys32_sigsuspend(int history0, int history1, old_sigset_t mask,
+		 struct pt_regs *regs)
 {
 	sigset_t saveset;
 
@@ -126,11 +127,11 @@ sys32_sigsuspend(int history0, int history1, old_sigset_t mask, struct pt_regs r
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
-	regs.rax = -EINTR;
+	regs->rax = -EINTR;
 	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();
-		if (do_signal(&regs, &saveset))
+		if (do_signal(regs, &saveset))
 			return -EINTR;
 	}
 }
@@ -138,7 +139,7 @@ sys32_sigsuspend(int history0, int history1, old_sigset_t mask, struct pt_regs r
 asmlinkage long
 sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
 		  stack_ia32_t __user *uoss_ptr, 
-		  struct pt_regs regs)
+		  struct pt_regs *regs)
 {
 	stack_t uss,uoss; 
 	int ret;
@@ -155,7 +156,7 @@ sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
 	}
 	seg = get_fs(); 
 	set_fs(KERNEL_DS); 
-	ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs.rsp);
+	ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->rsp);
 	set_fs(seg); 
 	if (ret >= 0 && uoss_ptr)  {
 		if (!access_ok(VERIFY_WRITE,uoss_ptr,sizeof(stack_ia32_t)) ||
@@ -274,9 +275,9 @@ badframe:
 	return 1;
 }
 
-asmlinkage long sys32_sigreturn(struct pt_regs regs)
+asmlinkage long sys32_sigreturn(struct pt_regs *regs)
 {
-	struct sigframe __user *frame = (struct sigframe __user *)(regs.rsp-8);
+	struct sigframe __user *frame = (struct sigframe __user *)(regs->rsp-8);
 	sigset_t set;
 	unsigned int eax;
 
@@ -294,20 +295,23 @@ asmlinkage long sys32_sigreturn(struct pt_regs regs)
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 	
-	if (ia32_restore_sigcontext(&regs, &frame->sc, &eax))
+	if (ia32_restore_sigcontext(regs, &frame->sc, &eax))
 		goto badframe;
 	return eax;
 
 badframe:
-	signal_fault(&regs, frame, "32bit sigreturn"); 
+	signal_fault(regs, frame, "32bit sigreturn");
 	return 0;
 }	
 
-asmlinkage long sys32_rt_sigreturn(struct pt_regs regs)
+asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
 {
-	struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(regs.rsp - 4);
+	struct rt_sigframe __user *frame;
 	sigset_t set;
 	unsigned int eax;
+	struct pt_regs tregs;
+
+	frame = (struct rt_sigframe __user *)(regs->rsp - 4);
 
 	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
@@ -320,16 +324,17 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs regs)
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 	
-	if (ia32_restore_sigcontext(&regs, &frame->uc.uc_mcontext, &eax))
+	if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &eax))
 		goto badframe;
 
-	if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, regs) == -EFAULT)
+	tregs = *regs;
+	if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
 		goto badframe;
 
 	return eax;
 
 badframe:
-	signal_fault(&regs,frame,"32bit rt sigreturn");
+	signal_fault(regs,frame,"32bit rt sigreturn");
 	return 0;
 }	
 
@@ -342,6 +347,7 @@ ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __
 		 struct pt_regs *regs, unsigned int mask)
 {
 	int tmp, err = 0;
+	u32 eflags;
 
 	tmp = 0;
 	__asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
@@ -366,7 +372,11 @@ ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __
 	err |= __put_user(current->thread.trap_no, &sc->trapno);
 	err |= __put_user(current->thread.error_code, &sc->err);
 	err |= __put_user((u32)regs->rip, &sc->eip);
-	err |= __put_user((u32)regs->eflags, &sc->eflags);
+	eflags = regs->eflags;
+	if (current->ptrace & PT_PTRACED) {
+		eflags &= ~TF_MASK;
+	}
+	err |= __put_user((u32)eflags, &sc->eflags);
 	err |= __put_user((u32)regs->rsp, &sc->esp_at_signal);
 
 	tmp = save_i387_ia32(current, fpstate, regs, 0);
@@ -484,7 +494,13 @@ void ia32_setup_frame(int sig, struct k_sigaction *ka,
 	regs->ss = __USER32_DS; 
 
 	set_fs(USER_DS);
-	regs->eflags &= ~TF_MASK;
+	if (regs->eflags & TF_MASK) {
+		if (current->ptrace & PT_PTRACED) {
+			ptrace_notify(SIGTRAP);
+		} else {
+			regs->eflags &= ~TF_MASK;
+		}
+	}
 
 #if DEBUG_SIG
 	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
@@ -494,9 +510,7 @@ void ia32_setup_frame(int sig, struct k_sigaction *ka,
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	signal_fault(regs,frame,"32bit signal deliver");
+	force_sigsegv(sig, current);
 }
 
 void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -580,7 +594,13 @@ void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	regs->ss = __USER32_DS; 
 
 	set_fs(USER_DS);
-	regs->eflags &= ~TF_MASK;
+	if (regs->eflags & TF_MASK) {
+		if (current->ptrace & PT_PTRACED) {
+			ptrace_notify(SIGTRAP);
+		} else {
+			regs->eflags &= ~TF_MASK;
+		}
+	}
 
 #if DEBUG_SIG
 	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
@@ -590,8 +610,6 @@ void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	signal_fault(regs, frame, "32bit rt signal setup"); 
+	force_sigsegv(sig, current);
 }
 
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 805e98057..b7660caca 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -270,35 +270,32 @@ quiet_ni_syscall:
 	ret
 	CFI_ENDPROC
 	
-	.macro PTREGSCALL label, func
+	.macro PTREGSCALL label, func, arg
 	.globl \label
 \label:
 	leaq \func(%rip),%rax
+	leaq -ARGOFFSET+8(%rsp),\arg	/* 8 for return address */
 	jmp  ia32_ptregs_common	
 	.endm
 
-	PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn
-	PTREGSCALL stub32_sigreturn, sys32_sigreturn
-	PTREGSCALL stub32_sigaltstack, sys32_sigaltstack
-	PTREGSCALL stub32_sigsuspend, sys32_sigsuspend
-	PTREGSCALL stub32_execve, sys32_execve
-	PTREGSCALL stub32_fork, sys_fork
-	PTREGSCALL stub32_clone, sys32_clone
-	PTREGSCALL stub32_vfork, sys_vfork
-	PTREGSCALL stub32_iopl, sys_iopl
-	PTREGSCALL stub32_rt_sigsuspend, sys_rt_sigsuspend
+	PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi
+	PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi
+	PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx
+	PTREGSCALL stub32_sigsuspend, sys32_sigsuspend, %rcx
+	PTREGSCALL stub32_execve, sys32_execve, %rcx
+	PTREGSCALL stub32_fork, sys_fork, %rdi
+	PTREGSCALL stub32_clone, sys32_clone, %rdx
+	PTREGSCALL stub32_vfork, sys_vfork, %rdi
+	PTREGSCALL stub32_iopl, sys_iopl, %rsi
+	PTREGSCALL stub32_rt_sigsuspend, sys_rt_sigsuspend, %rdx
 
 ENTRY(ia32_ptregs_common)
 	CFI_STARTPROC
 	popq %r11
 	SAVE_REST
-	movq %r11, %r15
 	call *%rax
-	movq %r15, %r11
 	RESTORE_REST
-	leaq ia32_sysret(%rip),%r11
-	pushq %r11
-	ret
+	jmp  ia32_sysret	/* misbalances the return cache */
 	CFI_ENDPROC
 
 	.data
@@ -332,7 +329,7 @@ ia32_sys_call_table:
 	.quad sys_getuid16
 	.quad sys_stime		/* stime */		/* 25 */
 	.quad sys32_ptrace	/* ptrace */
-	.quad sys_alarm		/* XXX sign extension??? */ 
+	.quad sys_alarm
 	.quad sys_fstat	/* (old)fstat */
 	.quad sys_pause
 	.quad compat_sys_utime	/* 30 */
@@ -558,7 +555,7 @@ ia32_sys_call_table:
 	.quad sys_fadvise64		/* 250 */
 	.quad quiet_ni_syscall 	/* free_huge_pages */
 	.quad sys_exit_group
-	.quad sys_lookup_dcookie
+	.quad sys32_lookup_dcookie
 	.quad sys_epoll_create
 	.quad sys_epoll_ctl		/* 255 */
 	.quad sys_epoll_wait
@@ -589,6 +586,7 @@ ia32_sys_call_table:
 	.quad compat_sys_mq_notify
 	.quad compat_sys_mq_getsetattr
 	.quad quiet_ni_syscall		/* reserved for kexec */
+	.quad sys32_waitid
 	/* don't forget to change IA32_NR_syscalls */
 ia32_syscall_end:		
 	.rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8
diff --git a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c
index 01202b792..4445da812 100644
--- a/arch/x86_64/ia32/ptrace32.c
+++ b/arch/x86_64/ia32/ptrace32.c
@@ -249,8 +249,8 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
 	case PTRACE_GETFPREGS:
 	case PTRACE_SETFPXREGS:
 	case PTRACE_GETFPXREGS:
+	case PTRACE_GETEVENTMSG:
 		break;
-		
 	} 
 
 	child = find_target(request, pid, &ret);
@@ -363,6 +363,10 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
 		break;
 	}
 
+	case PTRACE_GETEVENTMSG:
+		ret = put_user(child->ptrace_message,(unsigned int __user *)(u64)data);
+		break;
+
 	default:
 		ret = -EINVAL;
 		break;
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
index 8b4734252..267a4a8e9 100644
--- a/arch/x86_64/ia32/sys_ia32.c
+++ b/arch/x86_64/ia32/sys_ia32.c
@@ -61,7 +61,6 @@
 #include <linux/ptrace.h>
 #include <linux/highuid.h>
 #include <linux/vmalloc.h>
-#include <linux/vs_cvirt.h>
 #include <asm/mman.h>
 #include <asm/types.h>
 #include <asm/uaccess.h>
@@ -1128,7 +1127,7 @@ long sys32_ustat(unsigned dev, struct ustat32 __user *u32p)
 } 
 
 asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv,
-			     compat_uptr_t __user *envp, struct pt_regs regs)
+			     compat_uptr_t __user *envp, struct pt_regs *regs)
 {
 	long error;
 	char * filename;
@@ -1137,21 +1136,47 @@ asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv,
 	error = PTR_ERR(filename);
 	if (IS_ERR(filename))
 		return error;
-	error = compat_do_execve(filename, argv, envp, &regs);
+	error = compat_do_execve(filename, argv, envp, regs);
 	if (error == 0)
 		current->ptrace &= ~PT_DTRACE;
 	putname(filename);
 	return error;
 }
 
-asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp, struct pt_regs regs)
+asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp,
+			    struct pt_regs *regs)
 {
-	void __user *parent_tid = (void __user *)regs.rdx;
-	void __user *child_tid = (void __user *)regs.rdi; 
+	void __user *parent_tid = (void __user *)regs->rdx;
+	void __user *child_tid = (void __user *)regs->rdi;
 	if (!newsp)
-		newsp = regs.rsp;
-        return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0, 
-		    parent_tid, child_tid);
+		newsp = regs->rsp;
+        return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
+}
+
+asmlinkage long sys32_waitid(int which, compat_pid_t pid,
+			     siginfo_t32 __user *uinfo, int options,
+			     struct compat_rusage __user *uru)
+{
+	siginfo_t info;
+	struct rusage ru;
+	long ret;
+	mm_segment_t old_fs = get_fs();
+
+	info.si_signo = 0;
+	set_fs (KERNEL_DS);
+	ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options,
+			 uru ? &ru : NULL);
+	set_fs (old_fs);
+
+	if (ret < 0 || info.si_signo == 0)
+		return ret;
+
+	if (uru && (ret = put_compat_rusage(&ru, uru)))
+		return ret;
+
+	BUG_ON(info.si_code & __SI_MASK);
+	info.si_code |= __SI_CHLD;
+	return ia32_copy_siginfo_to_user(uinfo, &info);
 }
 
 /*
@@ -1265,7 +1290,7 @@ asmlinkage long sys32_open(const char __user * filename, int flags, int mode)
 		if (fd >= 0) {
 			struct file *f = filp_open(tmp, flags, mode);
 			error = PTR_ERR(f);
-			if (unlikely(IS_ERR(f))) {
+			if (IS_ERR(f)) {
 				put_unused_fd(fd); 
 				fd = error;
 			} else
@@ -1340,6 +1365,12 @@ long sys32_quotactl(void)
 	return -ENOSYS;
 } 
 
+long sys32_lookup_dcookie(u32 addr_low, u32 addr_high,
+			  char __user * buf, size_t len)
+{
+	return sys_lookup_dcookie(((u64)addr_high << 32) | addr_low, buf, len);
+}
+
 cond_syscall(sys32_ipc)
 
 static int __init ia32_init (void)
diff --git a/arch/x86_64/ia32/syscall32.c b/arch/x86_64/ia32/syscall32.c
index 1806bff66..f82aeae6f 100644
--- a/arch/x86_64/ia32/syscall32.c
+++ b/arch/x86_64/ia32/syscall32.c
@@ -30,16 +30,20 @@ extern int sysctl_vsyscall32;
 char *syscall32_page; 
 static int use_sysenter __initdata = -1;
 
-/* RED-PEN: This knows too much about high level VM */ 
-/* Alternative would be to generate a vma with appropriate backing options
-   and let it be handled by generic VM */ 
-int map_syscall32(struct mm_struct *mm, unsigned long address) 
+/*
+ * Map the 32bit vsyscall page on demand.
+ *
+ * RED-PEN: This knows too much about high level VM.
+ *
+ * Alternative would be to generate a vma with appropriate backing options
+ * and let it be handled by generic VM.
+ */
+int __map_syscall32(struct mm_struct *mm, unsigned long address)
 { 
 	pte_t *pte;
 	pmd_t *pmd;
 	int err = 0;
 
-	down_read(&mm->mmap_sem);
 	spin_lock(&mm->page_table_lock); 
 	pmd = pmd_alloc(mm, pgd_offset(mm, address), address); 
 	if (pmd && (pte = pte_alloc_map(mm, pmd, address)) != NULL) { 
@@ -54,6 +58,14 @@ int map_syscall32(struct mm_struct *mm, unsigned long address)
 	} else
 		err = -ENOMEM; 
 	spin_unlock(&mm->page_table_lock);
+	return err;
+}
+
+int map_syscall32(struct mm_struct *mm, unsigned long address)
+{
+	int err;
+	down_read(&mm->mmap_sem);
+	err = __map_syscall32(mm, address);
 	up_read(&mm->mmap_sem);
 	return err;
 }
@@ -76,7 +88,8 @@ static int __init init_syscall32(void)
 	
 __initcall(init_syscall32); 
 
-void __init syscall32_cpu_init(void)
+/* May not be __init: called during resume */
+void syscall32_cpu_init(void)
 {
 	if (use_sysenter < 0)
  		use_sysenter = (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL);
diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
index dc6f2695e..e70de986a 100644
--- a/arch/x86_64/kernel/Makefile
+++ b/arch/x86_64/kernel/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-extra-y 	:= head.o head64.o init_task.o vmlinux.lds.s
+extra-y 	:= head.o head64.o init_task.o vmlinux.lds
 EXTRA_AFLAGS	:= -traditional
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o \
 		ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_x86_64.o \
@@ -25,7 +25,6 @@ obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 obj-$(CONFIG_GART_IOMMU)	+= pci-gart.o aperture.o
 obj-$(CONFIG_DUMMY_IOMMU)	+= pci-nommu.o pci-dma.o
 obj-$(CONFIG_SWIOTLB)		+= swiotlb.o
-obj-$(CONFIG_SCHED_SMT)		+= domain.o
 
 obj-$(CONFIG_MODULES)		+= module.o
 
diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c
index 164b6d078..1d8b3912c 100644
--- a/arch/x86_64/kernel/aperture.c
+++ b/arch/x86_64/kernel/aperture.c
@@ -31,6 +31,8 @@ int iommu_aperture_allowed __initdata = 0;
 int fallback_aper_order __initdata = 1; /* 64MB */
 int fallback_aper_force __initdata = 0; 
 
+int fix_aperture __initdata = 1;
+
 /* This code runs before the PCI subsystem is initialized, so just 
    access the northbridge directly. */
 
@@ -202,7 +204,7 @@ void __init iommu_hole_init(void)
 	u64 aper_base; 
 	int valid_agp = 0;
 
-	if (iommu_aperture_disabled)
+	if (iommu_aperture_disabled || !fix_aperture)
 		return;
 
 	printk("Checking aperture...\n"); 
@@ -241,20 +243,15 @@ void __init iommu_hole_init(void)
 		/* Got the aperture from the AGP bridge */
 	} else if ((!no_iommu && end_pfn >= 0xffffffff>>PAGE_SHIFT) ||
 		   force_iommu ||
-		   valid_agp || 
+		   valid_agp ||
 		   fallback_aper_force) { 
-		/* When there is a AGP bridge in the system assume the
-		   user wants to use the AGP driver too and needs an
-		   aperture.  However this case (AGP but no good
-		   aperture) should only happen with a more broken than
-		   usual BIOS, because it would even break Windows. */
-
-	printk("Your BIOS doesn't leave a aperture memory hole\n");
-	printk("Please enable the IOMMU option in the BIOS setup\n"); 
-		printk("This costs you %d MB of RAM\n", 32 << fallback_aper_order); 
- 
+		printk("Your BIOS doesn't leave a aperture memory hole\n");
+		printk("Please enable the IOMMU option in the BIOS setup\n");
+		printk("This costs you %d MB of RAM\n",
+		       32 << fallback_aper_order);
+
 		aper_order = fallback_aper_order;
-	aper_alloc = allocate_aperture(); 
+		aper_alloc = allocate_aperture();
 		if (!aper_alloc) { 
 			/* Could disable AGP and IOMMU here, but it's probably
 			   not worth it. But the later users cannot deal with
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index 6fb84e2c7..ddd8aac2a 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -33,6 +33,8 @@
 #include <asm/mpspec.h>
 #include <asm/pgalloc.h>
 
+int apic_verbosity;
+
 int disable_apic_timer __initdata;
 
 /* Using APIC to generate smp_local_timer_interrupt? */
@@ -123,7 +125,7 @@ void __init connect_bsp_APIC(void)
 		 * PIC mode, enable APIC mode in the IMCR, i.e.
 		 * connect BSP's local APIC to INT and NMI lines.
 		 */
-		printk(KERN_INFO "leaving PIC mode, enabling APIC mode.\n");
+		apic_printk(APIC_VERBOSE, "leaving PIC mode, enabling APIC mode.\n");
 		outb(0x70, 0x22);
 		outb(0x01, 0x23);
 	}
@@ -138,7 +140,7 @@ void disconnect_bsp_APIC(void)
 		 * interrupts, including IPIs, won't work beyond
 		 * this point!  The only exception are INIT IPIs.
 		 */
-		printk(KERN_INFO "disabling APIC mode, entering PIC mode.\n");
+		apic_printk(APIC_QUIET, "disabling APIC mode, entering PIC mode.\n");
 		outb(0x70, 0x22);
 		outb(0x00, 0x23);
 	}
@@ -172,10 +174,10 @@ int __init verify_local_APIC(void)
 	 * The version register is read-only in a real APIC.
 	 */
 	reg0 = apic_read(APIC_LVR);
-	Dprintk("Getting VERSION: %x\n", reg0);
+	apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg0);
 	apic_write(APIC_LVR, reg0 ^ APIC_LVR_MASK);
 	reg1 = apic_read(APIC_LVR);
-	Dprintk("Getting VERSION: %x\n", reg1);
+	apic_printk(APIC_DEBUG, "Getting VERSION: %x\n", reg1);
 
 	/*
 	 * The two version reads above should print the same
@@ -199,10 +201,10 @@ int __init verify_local_APIC(void)
 	 * The ID register is read/write in a real APIC.
 	 */
 	reg0 = apic_read(APIC_ID);
-	Dprintk("Getting ID: %x\n", reg0);
+	apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg0);
 	apic_write(APIC_ID, reg0 ^ APIC_ID_MASK);
 	reg1 = apic_read(APIC_ID);
-	Dprintk("Getting ID: %x\n", reg1);
+	apic_printk(APIC_DEBUG, "Getting ID: %x\n", reg1);
 	apic_write(APIC_ID, reg0);
 	if (reg1 != (reg0 ^ APIC_ID_MASK))
 		return 0;
@@ -213,9 +215,9 @@ int __init verify_local_APIC(void)
 	 * compatibility mode, but most boxes are anymore.
 	 */
 	reg0 = apic_read(APIC_LVT0);
-	Dprintk("Getting LVT0: %x\n", reg0);
+	apic_printk(APIC_DEBUG,"Getting LVT0: %x\n", reg0);
 	reg1 = apic_read(APIC_LVT1);
-	Dprintk("Getting LVT1: %x\n", reg1);
+	apic_printk(APIC_DEBUG, "Getting LVT1: %x\n", reg1);
 
 	return 1;
 }
@@ -227,7 +229,7 @@ void __init sync_Arb_IDs(void)
 	 */
 	apic_wait_icr_idle();
 
-	Dprintk("Synchronizing Arb IDs.\n");
+	apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n");
 	apic_write_around(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG
 				| APIC_DM_INIT);
 }
@@ -388,10 +390,10 @@ void __init setup_local_APIC (void)
 	value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
 	if (!smp_processor_id() && (pic_mode || !value)) {
 		value = APIC_DM_EXTINT;
-		Dprintk(KERN_INFO "enabled ExtINT on CPU#%d\n", smp_processor_id());
+		apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", smp_processor_id());
 	} else {
 		value = APIC_DM_EXTINT | APIC_LVT_MASKED;
-		Dprintk(KERN_INFO "masked ExtINT on CPU#%d\n", smp_processor_id());
+		apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", smp_processor_id());
 	}
 	apic_write_around(APIC_LVT0, value);
 
@@ -407,12 +409,11 @@ void __init setup_local_APIC (void)
 	apic_write_around(APIC_LVT1, value);
 
 	if (APIC_INTEGRATED(ver) && !esr_disable) {		/* !82489DX */
+		unsigned oldvalue;
 		maxlvt = get_maxlvt();
 		if (maxlvt > 3)		/* Due to the Pentium erratum 3AP. */
 			apic_write(APIC_ESR, 0);
-		value = apic_read(APIC_ESR);
-		Dprintk("ESR value before enabling vector: %08x\n", value);
-
+		oldvalue = apic_read(APIC_ESR);
 		value = ERROR_APIC_VECTOR;      // enables sending errors
 		apic_write_around(APIC_LVTERR, value);
 		/*
@@ -421,7 +422,10 @@ void __init setup_local_APIC (void)
 		if (maxlvt > 3)
 			apic_write(APIC_ESR, 0);
 		value = apic_read(APIC_ESR);
-		Dprintk("ESR value after enabling vector: %08x\n", value);
+		if (value != oldvalue)
+			apic_printk(APIC_VERBOSE,
+			"ESR value after enabling vector: %08x, after %08x\n",
+			oldvalue, value);
 	} else {
 		if (esr_disable)	
 			/* 
@@ -430,9 +434,9 @@ void __init setup_local_APIC (void)
 			 * ESR disabled - we can't do anything useful with the
 			 * errors anyway - mbligh
 			 */
-			printk("Leaving ESR disabled.\n");
+			apic_printk(APIC_DEBUG, "Leaving ESR disabled.\n");
 		else 
-			printk("No ESR for 82489DX.\n");
+			apic_printk(APIC_DEBUG, "No ESR for 82489DX.\n");
 	}
 
 	nmi_watchdog_default();
@@ -564,6 +568,21 @@ static void apic_pm_activate(void) { }
 
 #endif	/* CONFIG_PM */
 
+static int __init apic_set_verbosity(char *str)
+{
+	if (strcmp("debug", str) == 0)
+		apic_verbosity = APIC_DEBUG;
+	else if (strcmp("verbose", str) == 0)
+		apic_verbosity = APIC_VERBOSE;
+	else
+		printk(KERN_WARNING "APIC Verbosity level %s not recognised"
+				" use apic=verbose or apic=debug", str);
+
+	return 0;
+}
+
+__setup("apic=", apic_set_verbosity);
+
 /*
  * Detect and enable local APICs on non-SMP boards.
  * Original code written by Keir Fraser.
@@ -599,7 +618,7 @@ void __init init_apic_mappings(void)
 		apic_phys = mp_lapic_addr;
 
 	set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
-	Dprintk("mapped APIC to %16lx (%16lx)\n", APIC_BASE, apic_phys);
+	apic_printk(APIC_VERBOSE,"mapped APIC to %16lx (%16lx)\n", APIC_BASE, apic_phys);
 
 	/*
 	 * Fetch the APIC ID of the BSP in case we have a
@@ -621,7 +640,7 @@ void __init init_apic_mappings(void)
 				ioapic_phys = __pa(ioapic_phys);
 			}
 			set_fixmap_nocache(idx, ioapic_phys);
-			Dprintk("mapped IOAPIC to %016lx (%016lx)\n",
+			apic_printk(APIC_VERBOSE,"mapped IOAPIC to %016lx (%016lx)\n",
 					__fix_to_virt(idx), ioapic_phys);
 			idx++;
 		}
@@ -836,8 +855,7 @@ void smp_local_timer_interrupt(struct pt_regs *regs)
 {
 	int cpu = smp_processor_id();
 
-	x86_do_profile(regs);
-
+	profile_tick(CPU_PROFILING, regs);
 	if (--per_cpu(prof_counter, cpu) <= 0) {
 		/*
 		 * The multiplier may have changed since the last time we got
@@ -962,7 +980,7 @@ asmlinkage void smp_error_interrupt(void)
 	   6: Received illegal vector
 	   7: Illegal register address
 	*/
-	printk (KERN_INFO "APIC error on CPU%d: %02x(%02x)\n",
+	printk (KERN_DEBUG "APIC error on CPU%d: %02x(%02x)\n",
 	        smp_processor_id(), v , v1);
 	irq_exit();
 }
diff --git a/arch/x86_64/kernel/asm-offsets.c b/arch/x86_64/kernel/asm-offsets.c
index 757f55078..37d12fa5e 100644
--- a/arch/x86_64/kernel/asm-offsets.c
+++ b/arch/x86_64/kernel/asm-offsets.c
@@ -7,8 +7,8 @@
 #include <linux/sched.h> 
 #include <linux/stddef.h>
 #include <linux/errno.h> 
+#include <linux/hardirq.h>
 #include <asm/pda.h>
-#include <asm/hardirq.h>
 #include <asm/processor.h>
 #include <asm/segment.h>
 #include <asm/thread_info.h>
diff --git a/arch/x86_64/kernel/cpufreq/Kconfig b/arch/x86_64/kernel/cpufreq/Kconfig
index 1b3aefc8d..dcb518eb2 100644
--- a/arch/x86_64/kernel/cpufreq/Kconfig
+++ b/arch/x86_64/kernel/cpufreq/Kconfig
@@ -41,4 +41,58 @@ config X86_POWERNOW_K8
 
 	  If in doubt, say N.
 
+config X86_POWERNOW_K8_ACPI
+	bool
+	depends on ((X86_POWERNOW_K8 = "m" && ACPI_PROCESSOR) || (X86_POWERNOW_K8 = "y" && ACPI_PROCESSOR = "y"))
+	default y
+
+config X86_SPEEDSTEP_CENTRINO
+	tristate "Intel Enhanced SpeedStep"
+	depends on CPU_FREQ_TABLE
+	help
+	  This adds the CPUFreq driver for Enhanced SpeedStep enabled
+	  mobile CPUs.  This means Intel Pentium M (Centrino) CPUs
+	  or 64bit enabled Intel Xeons.
+
+	  For details, take a look at <file:Documentation/cpu-freq/>.
+
+	  If in doubt, say N.
+
+config X86_SPEEDSTEP_CENTRINO_TABLE
+	bool
+	depends on X86_SPEEDSTEP_CENTRINO
+	default y
+
+config X86_SPEEDSTEP_CENTRINO_ACPI
+	bool "Use ACPI tables to decode valid frequency/voltage pairs (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	depends on ((X86_SPEEDSTEP_CENTRINO = "m" && ACPI_PROCESSOR) || (X86_SPEEDSTEP_CENTRINO = "y" && ACPI_PROCESSOR = "y"))
+	help
+	  Use primarily the information provided in the BIOS ACPI tables
+	  to determine valid CPU frequency and voltage pairings.
+
+	  If in doubt, say Y.
+
+config X86_ACPI_CPUFREQ
+	tristate "ACPI Processor P-States driver"
+	depends on CPU_FREQ_TABLE && ACPI_PROCESSOR
+	help
+	  This driver adds a CPUFreq driver which utilizes the ACPI
+	  Processor Performance States.
+
+	  For details, take a look at <file:Documentation/cpu-freq/>.
+
+	  If in doubt, say N.
+
+config X86_ACPI_CPUFREQ_PROC_INTF
+        bool "/proc/acpi/processor/../performance interface (deprecated)"
+	depends on X86_ACPI_CPUFREQ && PROC_FS
+	help
+	  This enables the deprecated /proc/acpi/processor/../performance
+	  interface. While it is helpful for debugging, the generic,
+	  cross-architecture cpufreq interfaces should be used.
+
+	  If in doubt, say N.
+
 endmenu
+
diff --git a/arch/x86_64/kernel/cpufreq/Makefile b/arch/x86_64/kernel/cpufreq/Makefile
index f02ed52be..d0f0b2cf3 100644
--- a/arch/x86_64/kernel/cpufreq/Makefile
+++ b/arch/x86_64/kernel/cpufreq/Makefile
@@ -2,6 +2,12 @@
 # Reuse the i386 cpufreq drivers
 #
 
+SRCDIR := ../../../i386/kernel/cpu/cpufreq
+
 obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o
+obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o
+obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi.o
 
-powernow-k8-objs := ../../../i386/kernel/cpu/cpufreq/powernow-k8.o
+powernow-k8-objs := ${SRCDIR}/powernow-k8.o
+speedstep-centrino-objs := ${SRCDIR}/speedstep-centrino.o
+acpi-objs := ${SRCDIR}/acpi.o
diff --git a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c
index 98041f50e..600ec815a 100644
--- a/arch/x86_64/kernel/early_printk.c
+++ b/arch/x86_64/kernel/early_printk.c
@@ -8,7 +8,7 @@
 /* Simple VGA output */
 
 #ifdef __i386__
-#define VGABASE		__pa(__PAGE_OFFSET + 0xb8000UL)
+#define VGABASE		(__ISA_IO_base + 0xb8000)
 #else
 #define VGABASE		0xffffffff800b8000UL
 #endif
@@ -99,18 +99,17 @@ static void early_serial_write(struct console *con, const char *s, unsigned n)
 
 #define DEFAULT_BAUD 9600
 
-static __init void early_serial_init(char *opt)
+static __init void early_serial_init(char *s)
 {
 	unsigned char c; 
 	unsigned divisor;
 	unsigned baud = DEFAULT_BAUD;
-	char *s, *e;
+	char *e;
 
-	if (*opt == ',') 
-		++opt;
+	if (*s == ',')
+		++s;
 
-	s = strsep(&opt, ","); 
-	if (s != NULL) { 
+	if (*s) {
 		unsigned port; 
 		if (!strncmp(s,"0x",2)) {
 			early_serial_base = simple_strtoul(s, &e, 16);
@@ -124,6 +123,9 @@ static __init void early_serial_init(char *opt)
 				port = 0;
 			early_serial_base = bases[port];
 		}
+		s += strcspn(s, ",");
+		if (*s == ',')
+			s++;
 	}
 
 	outb(0x3, early_serial_base + LCR);	/* 8n1 */
@@ -131,8 +133,7 @@ static __init void early_serial_init(char *opt)
 	outb(0, early_serial_base + FCR);	/* no fifo */
 	outb(0x3, early_serial_base + MCR);	/* DTR + RTS */
 
-	s = strsep(&opt, ","); 
-	if (s != NULL) { 
+	if (*s) {
 		baud = simple_strtoul(s, &e, 0); 
 		if (baud == 0 || s == e) 
 			baud = DEFAULT_BAUD;
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index 89f74f738..17d74eb66 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -297,7 +297,7 @@ int_very_careful:
 	sti
 	SAVE_REST
 	/* Check for syscall exit trace */	
-	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),%edx
+	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edx
 	jz int_signal
 	pushq %rdi
 	leaq 8(%rsp),%rdi	# &ptregs -> arg1	
@@ -305,6 +305,7 @@ int_very_careful:
 	popq %rdi
 	btr  $TIF_SYSCALL_TRACE,%edi
 	btr  $TIF_SYSCALL_AUDIT,%edi
+	btr  $TIF_SINGLESTEP,%edi
 	jmp int_restore_rest
 	
 int_signal:
@@ -323,19 +324,20 @@ int_restore_rest:
  * Certain special system calls that need to save a complete full stack frame.
  */ 								
 	
-	.macro PTREGSCALL label,func
+	.macro PTREGSCALL label,func,arg
 	.globl \label
 \label:
 	leaq	\func(%rip),%rax
+	leaq    -ARGOFFSET+8(%rsp),\arg /* 8 for return address */
 	jmp	ptregscall_common
 	.endm
 
-	PTREGSCALL stub_clone, sys_clone
-	PTREGSCALL stub_fork, sys_fork
-	PTREGSCALL stub_vfork, sys_vfork
-	PTREGSCALL stub_rt_sigsuspend, sys_rt_sigsuspend
-	PTREGSCALL stub_sigaltstack, sys_sigaltstack
-	PTREGSCALL stub_iopl, sys_iopl
+	PTREGSCALL stub_clone, sys_clone, %r8
+	PTREGSCALL stub_fork, sys_fork, %rdi
+	PTREGSCALL stub_vfork, sys_vfork, %rdi
+	PTREGSCALL stub_rt_sigsuspend, sys_rt_sigsuspend, %rdx
+	PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx
+	PTREGSCALL stub_iopl, sys_iopl, %rsi
 
 ENTRY(ptregscall_common)
 	CFI_STARTPROC
@@ -385,6 +387,7 @@ ENTRY(stub_rt_sigreturn)
 	CFI_STARTPROC
 	addq $8, %rsp		
 	SAVE_REST
+	movq %rsp,%rdi
 	FIXUP_TOP_OF_STACK %r11
 	call sys_rt_sigreturn
 	movq %rax,RAX(%rsp) # fixme, this could be done at the higher layer
diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c
index c52b859c9..f5d084a99 100644
--- a/arch/x86_64/kernel/i8259.c
+++ b/arch/x86_64/kernel/i8259.c
@@ -329,7 +329,7 @@ spurious_8259A_irq:
 		 * lets ACK and report it. [once per IRQ]
 		 */
 		if (!(spurious_irq_mask & irqmask)) {
-			printk("spurious 8259A interrupt: IRQ%d.\n", irq);
+			printk(KERN_DEBUG "spurious 8259A interrupt: IRQ%d.\n", irq);
 			spurious_irq_mask |= irqmask;
 		}
 		atomic_inc(&irq_err_count);
@@ -342,7 +342,7 @@ spurious_8259A_irq:
 	}
 }
 
-void __init init_8259A(int auto_eoi)
+void init_8259A(int auto_eoi)
 {
 	unsigned long flags;
 
@@ -385,6 +385,57 @@ void __init init_8259A(int auto_eoi)
 	spin_unlock_irqrestore(&i8259A_lock, flags);
 }
 
+static char irq_trigger[2];
+/**
+ * ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ
+ */
+static void restore_ELCR(char *trigger)
+{
+	outb(trigger[0], 0x4d0);
+	outb(trigger[1], 0x4d1);
+}
+
+static void save_ELCR(char *trigger)
+{
+	/* IRQ 0,1,2,8,13 are marked as reserved */
+	trigger[0] = inb(0x4d0) & 0xF8;
+	trigger[1] = inb(0x4d1) & 0xDE;
+}
+
+static int i8259A_resume(struct sys_device *dev)
+{
+	init_8259A(0);
+	restore_ELCR(irq_trigger);
+	return 0;
+}
+
+static int i8259A_suspend(struct sys_device *dev, u32 state)
+{
+	save_ELCR(irq_trigger);
+	return 0;
+}
+
+static struct sysdev_class i8259_sysdev_class = {
+	set_kset_name("i8259"),
+	.suspend = i8259A_suspend,
+	.resume = i8259A_resume,
+};
+
+static struct sys_device device_i8259A = {
+	.id	= 0,
+	.cls	= &i8259_sysdev_class,
+};
+
+static int __init i8259A_init_sysfs(void)
+{
+	int error = sysdev_class_register(&i8259_sysdev_class);
+	if (!error)
+		error = sysdev_register(&device_i8259A);
+	return error;
+}
+
+device_initcall(i8259A_init_sysfs);
+
 /*
  * IRQ2 is cascade interrupt to second interrupt controller
  */
diff --git a/arch/x86_64/kernel/init_task.c b/arch/x86_64/kernel/init_task.c
index 33185ca33..8bc4becb8 100644
--- a/arch/x86_64/kernel/init_task.c
+++ b/arch/x86_64/kernel/init_task.c
@@ -44,8 +44,7 @@ EXPORT_SYMBOL(init_task);
  * section. Since TSS's are completely CPU-local, we want them
  * on exact cacheline boundaries, to eliminate cacheline ping-pong.
  */ 
-struct tss_struct init_tss[NR_CPUS] __cacheline_aligned;
-
+DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_maxaligned_in_smp;
 
 #define ALIGN_TO_4K __attribute__((section(".data.init_task")))
 
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 6cb45b7eb..c309cb0f8 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -30,12 +30,15 @@
 #include <linux/smp_lock.h>
 #include <linux/mc146818rtc.h>
 #include <linux/acpi.h>
+#include <linux/sysdev.h>
 
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/desc.h>
 #include <asm/proto.h>
 
+#define __apicdebuginit  __init
+
 int sis_apic_bug; /* not actually supported, dummy for compile */
 
 #undef APIC_LOCKUP_DEBUG
@@ -292,13 +295,13 @@ static int __init ioapic_pirq_setup(char *str)
 		pirq_entries[i] = -1;
 
 	pirqs_enabled = 1;
-	printk(KERN_INFO "PIRQ redirection, working around broken MP-BIOS.\n");
+	apic_printk(APIC_VERBOSE, "PIRQ redirection, working around broken MP-BIOS.\n");
 	max = MAX_PIRQS;
 	if (ints[0] < MAX_PIRQS)
 		max = ints[0];
 
 	for (i = 0; i < max; i++) {
-		printk(KERN_DEBUG "... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
+		apic_printk(APIC_VERBOSE, "... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
 		/*
 		 * PIRQs are mapped upside down, usually.
 		 */
@@ -357,10 +360,10 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
 {
 	int apic, i, best_guess = -1;
 
-	Dprintk("querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
+	apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
 		bus, slot, pin);
 	if (mp_bus_id_to_pci_bus[bus] == -1) {
-		printk(KERN_WARNING "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
+		apic_printk(APIC_VERBOSE, "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
 		return -1;
 	}
 	for (i = 0; i < mp_irq_entries; i++) {
@@ -402,7 +405,7 @@ static int __init EISA_ELCR(unsigned int irq)
 		unsigned int port = 0x4d0 + (irq >> 3);
 		return (inb(port) >> (irq & 7)) & 1;
 	}
-	printk(KERN_INFO "Broken MPtable reports ISA irq %d\n", irq);
+	apic_printk(APIC_VERBOSE, "Broken MPtable reports ISA irq %d\n", irq);
 	return 0;
 }
 
@@ -625,10 +628,10 @@ static int pin_2_irq(int idx, int apic, int pin)
 	if ((pin >= 16) && (pin <= 23)) {
 		if (pirq_entries[pin-16] != -1) {
 			if (!pirq_entries[pin-16]) {
-				printk(KERN_DEBUG "disabling PIRQ%d\n", pin-16);
+				apic_printk(APIC_VERBOSE, "disabling PIRQ%d\n", pin-16);
 			} else {
 				irq = pirq_entries[pin-16];
-				printk(KERN_DEBUG "using PIRQ%d -> IRQ %d\n",
+				apic_printk(APIC_VERBOSE, "using PIRQ%d -> IRQ %d\n",
 						pin-16, irq);
 			}
 		}
@@ -719,7 +722,7 @@ void __init setup_IO_APIC_irqs(void)
 	int apic, pin, idx, irq, first_notcon = 1, vector;
 	unsigned long flags;
 
-	printk(KERN_DEBUG "init IO_APIC IRQs\n");
+	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
 
 	for (apic = 0; apic < nr_ioapics; apic++) {
 	for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
@@ -732,15 +735,15 @@ void __init setup_IO_APIC_irqs(void)
 		entry.delivery_mode = dest_LowestPrio;
 		entry.dest_mode = INT_DELIVERY_MODE;
 		entry.mask = 0;				/* enable IRQ */
-		entry.dest.logical.logical_dest = TARGET_CPUS;
+		entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
 
 		idx = find_irq_entry(apic,pin,mp_INT);
 		if (idx == -1) {
 			if (first_notcon) {
-				printk(KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mpc_apicid, pin);
+				apic_printk(APIC_VERBOSE, KERN_DEBUG " IO-APIC (apicid-pin) %d-%d", mp_ioapics[apic].mpc_apicid, pin);
 				first_notcon = 0;
 			} else
-				printk(", %d-%d", mp_ioapics[apic].mpc_apicid, pin);
+				apic_printk(APIC_VERBOSE, ", %d-%d", mp_ioapics[apic].mpc_apicid, pin);
 			continue;
 		}
 
@@ -750,7 +753,7 @@ void __init setup_IO_APIC_irqs(void)
 		if (irq_trigger(idx)) {
 			entry.trigger = 1;
 			entry.mask = 1;
-			entry.dest.logical.logical_dest = TARGET_CPUS;
+			entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
 		}
 
 		irq = pin_2_irq(idx, apic, pin);
@@ -775,7 +778,7 @@ void __init setup_IO_APIC_irqs(void)
 	}
 
 	if (!first_notcon)
-		printk(" not connected.\n");
+		apic_printk(APIC_VERBOSE," not connected.\n");
 }
 
 /*
@@ -800,7 +803,7 @@ void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
 	 */
 	entry.dest_mode = INT_DELIVERY_MODE;
 	entry.mask = 0;					/* unmask IRQ now */
-	entry.dest.logical.logical_dest = TARGET_CPUS;
+	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
 	entry.delivery_mode = dest_LowestPrio;
 	entry.polarity = 0;
 	entry.trigger = 0;
@@ -825,13 +828,9 @@ void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
 
 void __init UNEXPECTED_IO_APIC(void)
 {
-#if 0
-	printk(KERN_WARNING " WARNING: unexpected IO-APIC, please mail\n");
-	printk(KERN_WARNING "          to linux-smp@vger.kernel.org\n");
-#endif
 }
 
-void __init print_IO_APIC(void)
+void __apicdebuginit print_IO_APIC(void)
 {
 	int apic, i;
 	union IO_APIC_reg_00 reg_00;
@@ -839,7 +838,10 @@ void __init print_IO_APIC(void)
 	union IO_APIC_reg_02 reg_02;
 	unsigned long flags;
 
- 	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
+	printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
 	for (i = 0; i < nr_ioapics; i++)
 		printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n",
 		       mp_ioapics[i].mpc_apicid, nr_ioapic_registers[i]);
@@ -955,11 +957,14 @@ void __init print_IO_APIC(void)
 	return;
 }
 
-static void print_APIC_bitfield (int base)
+static __apicdebuginit void print_APIC_bitfield (int base)
 {
 	unsigned int v;
 	int i, j;
 
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
 	printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG);
 	for (i = 0; i < 8; i++) {
 		v = apic_read(base + i*0x10);
@@ -973,10 +978,13 @@ static void print_APIC_bitfield (int base)
 	}
 }
 
-void /*__init*/ print_local_APIC(void * dummy)
+void __apicdebuginit print_local_APIC(void * dummy)
 {
 	unsigned int v, ver, maxlvt;
 
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
 	printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
 		smp_processor_id(), hard_smp_processor_id());
 	v = apic_read(APIC_ID);
@@ -1058,12 +1066,15 @@ void print_all_local_APICs (void)
 	on_each_cpu(print_local_APIC, NULL, 1, 1);
 }
 
-void /*__init*/ print_PIC(void)
+void __apicdebuginit print_PIC(void)
 {
 	extern spinlock_t i8259A_lock;
 	unsigned int v;
 	unsigned long flags;
 
+	if (apic_verbosity == APIC_QUIET)
+		return;
+
 	printk(KERN_DEBUG "\nprinting PIC contents\n");
 
 	spin_lock_irqsave(&i8259A_lock, flags);
@@ -1160,9 +1171,9 @@ static void __init setup_ioapic_ids_from_mpc (void)
 		old_id = mp_ioapics[apic].mpc_apicid;
 
 		if (mp_ioapics[apic].mpc_apicid >= 0xf) {
-			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
+			apic_printk(APIC_QUIET,KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
 				apic, mp_ioapics[apic].mpc_apicid);
-			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
+			apic_printk(APIC_QUIET,KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
 				reg_00.bits.ID);
 			mp_ioapics[apic].mpc_apicid = reg_00.bits.ID;
 		}
@@ -1205,7 +1216,7 @@ static void __init setup_ioapic_ids_from_mpc (void)
 		 * Read the right value from the MPC table and
 		 * write it into the ID register.
 	 	 */
-		printk(KERN_INFO "...changing IO-APIC physical APIC ID to %d ...",
+		apic_printk(APIC_VERBOSE,KERN_INFO "...changing IO-APIC physical APIC ID to %d ...",
 				mp_ioapics[apic].mpc_apicid);
 
 		reg_00.bits.ID = mp_ioapics[apic].mpc_apicid;
@@ -1220,9 +1231,9 @@ static void __init setup_ioapic_ids_from_mpc (void)
 		reg_00.raw = io_apic_read(apic, 0);
 		spin_unlock_irqrestore(&ioapic_lock, flags);
 		if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid)
-			panic("could not set ID!\n");
+			printk("could not set ID!\n");
 		else
-			printk(" ok.\n");
+			apic_printk(APIC_VERBOSE," ok.\n");
 	}
 }
 
@@ -1671,7 +1682,7 @@ static inline void check_timer(void)
 	pin1 = find_isa_irq_pin(0, mp_INT);
 	pin2 = find_isa_irq_pin(0, mp_ExtINT);
 
-	printk(KERN_INFO "..TIMER: vector=0x%02X pin1=%d pin2=%d\n", vector, pin1, pin2);
+	apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X pin1=%d pin2=%d\n", vector, pin1, pin2);
 
 	if (pin1 != -1) {
 		/*
@@ -1689,12 +1700,12 @@ static inline void check_timer(void)
 			return;
 		}
 		clear_IO_APIC_pin(0, pin1);
-		printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC\n");
+		apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: 8254 timer not connected to IO-APIC\n");
 	}
 
-	printk(KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... ");
+	apic_printk(APIC_VERBOSE,KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... ");
 	if (pin2 != -1) {
-		printk("\n..... (found pin %d) ...", pin2);
+		apic_printk(APIC_VERBOSE,"\n..... (found pin %d) ...", pin2);
 		/*
 		 * legacy devices should be connected to IO APIC #0
 		 */
@@ -1720,7 +1731,7 @@ static inline void check_timer(void)
 		nmi_watchdog = 0;
 	}
 
-	printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
+	apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as Virtual Wire IRQ...");
 
 	disable_8259A_irq(0);
 	irq_desc[0].handler = &lapic_irq_type;
@@ -1728,13 +1739,13 @@ static inline void check_timer(void)
 	enable_8259A_irq(0);
 
 	if (timer_irq_works()) {
-		printk(" works.\n");
+		apic_printk(APIC_QUIET, " works.\n");
 		return;
 	}
 	apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
-	printk(" failed.\n");
+	apic_printk(APIC_VERBOSE," failed.\n");
 
-	printk(KERN_INFO "...trying to set up timer as ExtINT IRQ...");
+	apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as ExtINT IRQ...");
 
 	init_8259A(0);
 	make_8259A_irq(0);
@@ -1743,10 +1754,10 @@ static inline void check_timer(void)
 	unlock_ExtINT_logic();
 
 	if (timer_irq_works()) {
-		printk(" works.\n");
+		apic_printk(APIC_VERBOSE," works.\n");
 		return;
 	}
-	printk(" failed :(.\n");
+	apic_printk(APIC_VERBOSE," failed :(.\n");
 	panic("IO-APIC + timer doesn't work! Try using the 'noapic' kernel parameter\n");
 }
 
@@ -1768,7 +1779,7 @@ void __init setup_IO_APIC(void)
 	else
 		io_apic_irqs = ~PIC_IRQS;
 
-	printk("ENABLING IO-APIC IRQs\n");
+	apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
 
 	/*
 	 * Set up the IO-APIC IRQ routing table.
@@ -1783,6 +1794,98 @@ void __init setup_IO_APIC(void)
 		print_IO_APIC();
 }
 
+struct sysfs_ioapic_data {
+	struct sys_device dev;
+	struct IO_APIC_route_entry entry[0];
+};
+static struct sysfs_ioapic_data * mp_ioapic_data[MAX_IO_APICS];
+
+static int ioapic_suspend(struct sys_device *dev, u32 state)
+{
+	struct IO_APIC_route_entry *entry;
+	struct sysfs_ioapic_data *data;
+	unsigned long flags;
+	int i;
+
+	data = container_of(dev, struct sysfs_ioapic_data, dev);
+	entry = data->entry;
+	spin_lock_irqsave(&ioapic_lock, flags);
+	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
+		*(((int *)entry) + 1) = io_apic_read(dev->id, 0x11 + 2 * i);
+		*(((int *)entry) + 0) = io_apic_read(dev->id, 0x10 + 2 * i);
+	}
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	return 0;
+}
+
+static int ioapic_resume(struct sys_device *dev)
+{
+	struct IO_APIC_route_entry *entry;
+	struct sysfs_ioapic_data *data;
+	unsigned long flags;
+	union IO_APIC_reg_00 reg_00;
+	int i;
+
+	data = container_of(dev, struct sysfs_ioapic_data, dev);
+	entry = data->entry;
+
+	spin_lock_irqsave(&ioapic_lock, flags);
+	reg_00.raw = io_apic_read(dev->id, 0);
+	if (reg_00.bits.ID != mp_ioapics[dev->id].mpc_apicid) {
+		reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid;
+		io_apic_write(dev->id, 0, reg_00.raw);
+	}
+	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
+		io_apic_write(dev->id, 0x11+2*i, *(((int *)entry)+1));
+		io_apic_write(dev->id, 0x10+2*i, *(((int *)entry)+0));
+	}
+	spin_unlock_irqrestore(&ioapic_lock, flags);
+
+	return 0;
+}
+
+static struct sysdev_class ioapic_sysdev_class = {
+	set_kset_name("ioapic"),
+	.suspend = ioapic_suspend,
+	.resume = ioapic_resume,
+};
+
+static int __init ioapic_init_sysfs(void)
+{
+	struct sys_device * dev;
+	int i, size, error = 0;
+
+	error = sysdev_class_register(&ioapic_sysdev_class);
+	if (error)
+		return error;
+
+	for (i = 0; i < nr_ioapics; i++ ) {
+		size = sizeof(struct sys_device) + nr_ioapic_registers[i]
+			* sizeof(struct IO_APIC_route_entry);
+		mp_ioapic_data[i] = kmalloc(size, GFP_KERNEL);
+		if (!mp_ioapic_data[i]) {
+			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
+			continue;
+		}
+		memset(mp_ioapic_data[i], 0, size);
+		dev = &mp_ioapic_data[i]->dev;
+		dev->id = i;
+		dev->cls = &ioapic_sysdev_class;
+		error = sysdev_register(dev);
+		if (error) {
+			kfree(mp_ioapic_data[i]);
+			mp_ioapic_data[i] = NULL;
+			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
+			continue;
+		}
+	}
+
+	return 0;
+}
+
+device_initcall(ioapic_init_sysfs);
+
 /* --------------------------------------------------------------------------
                           ACPI-based IOAPIC Configuration
    -------------------------------------------------------------------------- */
@@ -1815,7 +1918,7 @@ int __init io_apic_get_unique_id (int ioapic, int apic_id)
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 
 	if (apic_id >= IO_APIC_MAX_ID) {
-		printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
+		apic_printk(APIC_QUIET, KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
 			"%d\n", ioapic, apic_id, reg_00.bits.ID);
 		apic_id = reg_00.bits.ID;
 	}
@@ -1834,7 +1937,7 @@ int __init io_apic_get_unique_id (int ioapic, int apic_id)
 		if (i == IO_APIC_MAX_ID)
 			panic("Max apic_id exceeded!\n");
 
-		printk(KERN_WARNING "IOAPIC[%d]: apic_id %d already used, "
+		apic_printk(APIC_VERBOSE, KERN_WARNING "IOAPIC[%d]: apic_id %d already used, "
 			"trying %d\n", ioapic, apic_id, i);
 
 		apic_id = i;
@@ -1855,7 +1958,7 @@ int __init io_apic_get_unique_id (int ioapic, int apic_id)
 			panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic);
 	}
 
-	printk(KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
+	apic_printk(APIC_VERBOSE,KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
 
 	return apic_id;
 }
@@ -1893,7 +1996,7 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
 	unsigned long flags;
 
 	if (!IO_APIC_IRQ(irq)) {
-		printk(KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
+		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
 			ioapic);
 		return -EINVAL;
 	}
@@ -1908,7 +2011,7 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
 
 	entry.delivery_mode = dest_LowestPrio;
 	entry.dest_mode = INT_DELIVERY_MODE;
-	entry.dest.logical.logical_dest = TARGET_CPUS;
+	entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
 	entry.trigger = edge_level;
 	entry.polarity = active_high_low;
 	entry.mask = 1;					 /* Disabled (masked) */
@@ -1921,20 +2024,12 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
 
 	entry.vector = assign_irq_vector(irq);
 
-	printk(KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> "
+	apic_printk(APIC_VERBOSE,KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> "
 		"IRQ %d Mode:%i Active:%i)\n", ioapic, 
 	       mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq,
 	       edge_level, active_high_low);
 
- 	if (use_pci_vector() && !platform_legacy_irq(irq))
-		irq = IO_APIC_VECTOR(irq);
-	if (edge_level) {
-		irq_desc[irq].handler = &ioapic_level_type;
-	} else {
-		irq_desc[irq].handler = &ioapic_edge_type;
-	}
-
-	set_intr_gate(entry.vector, interrupt[irq]);
+	ioapic_register_intr(irq, entry.vector, edge_level);
 
 	if (!ioapic && (irq < 16))
 		disable_8259A_irq(irq);
@@ -1966,3 +2061,28 @@ void send_IPI_self(int vector)
 	apic_write_around(APIC_ICR, cfg);
 }
 #endif
+
+
+/*
+ * This function currently is only a helper for the i386 smp boot process where
+ * we need to reprogram the ioredtbls to cater for the cpus which have come online
+ * so mask in all cases should simply be TARGET_CPUS
+ */
+void __init setup_ioapic_dest(void)
+{
+	int pin, ioapic, irq, irq_entry;
+
+	if (skip_ioapic_setup == 1)
+		return;
+
+	for (ioapic = 0; ioapic < nr_ioapics; ioapic++) {
+		for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) {
+			irq_entry = find_irq_entry(ioapic, pin, mp_INT);
+			if (irq_entry == -1)
+				continue;
+			irq = pin_2_irq(irq_entry, ioapic, pin);
+			set_ioapic_affinity_irq(irq, TARGET_CPUS);
+		}
+
+	}
+}
diff --git a/arch/x86_64/kernel/ioport.c b/arch/x86_64/kernel/ioport.c
index 0a90fd08f..cde0e868e 100644
--- a/arch/x86_64/kernel/ioport.c
+++ b/arch/x86_64/kernel/ioport.c
@@ -28,12 +28,12 @@ static void set_bitmap(unsigned long *bitmap, unsigned int base, unsigned int ex
 			clear_bit(i, bitmap); 
 }
 
-
 /*
  * this changes the io permissions bitmap in the current task.
  */
 asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
 {
+	unsigned int i, max_long, bytes, bytes_updated;
 	struct thread_struct * t = &current->thread;
 	struct tss_struct * tss;
 	unsigned long *bitmap;
@@ -59,16 +59,34 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
 
 	/*
 	 * do it in the per-thread copy and in the TSS ...
+	 *
+	 * Disable preemption via get_cpu() - we must not switch away
+	 * because the ->io_bitmap_max value must match the bitmap
+	 * contents:
 	 */
+	tss = &per_cpu(init_tss, get_cpu());
+
 	set_bitmap(t->io_bitmap_ptr, from, num, !turn_on);
-	tss = init_tss + get_cpu();
-	if (tss->io_bitmap_base == IO_BITMAP_OFFSET) { /* already active? */
-		set_bitmap(tss->io_bitmap, from, num, !turn_on);
-	} else {
-		memcpy(tss->io_bitmap, t->io_bitmap_ptr, IO_BITMAP_BYTES);
-		tss->io_bitmap_base = IO_BITMAP_OFFSET; /* Activate it in the TSS */
-	}
+
+	/*
+	 * Search for a (possibly new) maximum. This is simple and stupid,
+	 * to keep it obviously correct:
+	 */
+	max_long = 0;
+	for (i = 0; i < IO_BITMAP_LONGS; i++)
+		if (t->io_bitmap_ptr[i] != ~0UL)
+			max_long = i;
+
+	bytes = (max_long + 1) * sizeof(long);
+	bytes_updated = max(bytes, t->io_bitmap_max);
+
+	t->io_bitmap_max = bytes;
+
+	/* Update the TSS: */
+	memcpy(tss->io_bitmap, t->io_bitmap_ptr, bytes_updated);
+
 	put_cpu();
+
 	return 0;
 }
 
@@ -83,9 +101,9 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
  * code.
  */
 
-asmlinkage long sys_iopl(unsigned int level, struct pt_regs regs)
+asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs)
 {
-	unsigned int old = (regs.eflags >> 12) & 3;
+	unsigned int old = (regs->eflags >> 12) & 3;
 
 	if (level > 3)
 		return -EINVAL;
@@ -94,6 +112,6 @@ asmlinkage long sys_iopl(unsigned int level, struct pt_regs regs)
 		if (!capable(CAP_SYS_RAWIO))
 			return -EPERM;
 	}
-	regs.eflags = (regs.eflags &~ 0x3000UL) | (level << 12);
+	regs->eflags = (regs->eflags &~ 0x3000UL) | (level << 12);
 	return 0;
 }
diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c
index 189418294..bf6459e58 100644
--- a/arch/x86_64/kernel/irq.c
+++ b/arch/x86_64/kernel/irq.c
@@ -213,13 +213,15 @@ inline void synchronize_irq(unsigned int irq)
 int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
 {
 	int status = 1; /* Force the "do bottom halves" bit */
+	int ret;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
 	do {
-		status |= action->flags;
-		action->handler(irq, action->dev_id, regs);
+		ret = action->handler(irq, action->dev_id, regs);
+		if (ret == IRQ_HANDLED)
+			status |= action->flags;
 		action = action->next;
 	} while (action);
 	if (status & SA_SAMPLE_RANDOM)
@@ -862,31 +864,6 @@ static int irq_affinity_write_proc (struct file *file,
 
 #endif
 
-static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
-	if (count - len < 2)
-		return -EINVAL;
-	len += sprintf(page + len, "\n");
-	return len;
-}
-
-static int prof_cpu_mask_write_proc (struct file *file,
-					const char __user *buffer,
-					unsigned long count, void *data)
-{
-	unsigned long full_count = count, err;
-	cpumask_t new_value, *mask = (cpumask_t *)data;
-
-	err = cpumask_parse(buffer, count, new_value);
-	if (err)
-		return err;
-
-	*mask = new_value;
-	return full_count;
-}
-
 #define MAX_NAMELEN 10
 
 static void register_irq_proc (unsigned int irq)
@@ -922,26 +899,15 @@ static void register_irq_proc (unsigned int irq)
 #endif
 }
 
-unsigned long prof_cpu_mask = -1;
-
 void init_irq_proc (void)
 {
-	struct proc_dir_entry *entry;
 	int i;
 
 	/* create /proc/irq */
 	root_irq_dir = proc_mkdir("irq", NULL);
 
 	/* create /proc/irq/prof_cpu_mask */
-	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
-
-	if (!entry)
-	    return;
-
-	entry->nlink = 1;
-	entry->data = (void *)&prof_cpu_mask;
-	entry->read_proc = prof_cpu_mask_read_proc;
-	entry->write_proc = prof_cpu_mask_write_proc;
+	create_prof_cpu_mask(root_irq_dir);
 
 	/*
 	 * Create entries for all existing IRQs.
@@ -949,4 +915,3 @@ void init_irq_proc (void)
 	for (i = 0; i < NR_IRQS; i++)
 		register_irq_proc(i);
 }
-
diff --git a/arch/x86_64/kernel/ldt.c b/arch/x86_64/kernel/ldt.c
index c7d7dac04..d7e5d0cf4 100644
--- a/arch/x86_64/kernel/ldt.c
+++ b/arch/x86_64/kernel/ldt.c
@@ -135,6 +135,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
 		return 0;
 	if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
 		bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
+
 	down(&mm->context.sem);
 	size = mm->context.size*LDT_ENTRY_SIZE;
 	if (size > bytecount)
@@ -145,12 +146,17 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
 		err = -EFAULT;
 	up(&mm->context.sem);
 	if (err < 0)
-	return err;
+		goto error_return;
 	if (size != bytecount) {
 		/* zero-fill the rest */
-		clear_user(ptr+size, bytecount-size);
+		if (clear_user(ptr+size, bytecount-size) != 0) {
+			err = -EFAULT;
+			goto error_return;
+		}
 	}
 	return bytecount;
+error_return:
+	return err;
 }
 
 static int read_default_ldt(void __user * ptr, unsigned long bytecount)
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index 3bb678f1e..cf1fe8b7f 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -24,7 +24,8 @@
 #define MISC_MCELOG_MINOR 227
 #define NR_BANKS 5
 
-static int mce_disabled __initdata;
+static int mce_dont_init;
+
 /* 0: always panic, 1: panic if deadlock possible, 2: try to avoid panic,
    3: never panic or exit (for testing only) */
 static int tolerant = 1;
@@ -48,8 +49,7 @@ static void mce_log(struct mce *mce)
 	mce->finished = 0;
 	smp_wmb();
 	for (;;) {
-		entry = mcelog.next;
-		read_barrier_depends();
+		entry = rcu_dereference(mcelog.next);
 		/* When the buffer fills up discard new entries. Assume 
 		   that the earlier errors are the more interesting. */
 		if (entry >= MCE_LOG_LEN) {
@@ -72,7 +72,8 @@ static void mce_log(struct mce *mce)
 
 static void print_mce(struct mce *m)
 {
-	printk(KERN_EMERG 
+	printk(KERN_EMERG "\n"
+	       KERN_EMERG
 	       "CPU %d: Machine Check Exception: %16Lx Bank %d: %016Lx\n",
 	       m->cpu, m->mcgstatus, m->bank, m->status);
 	if (m->rip) {
@@ -101,7 +102,7 @@ static void mce_panic(char *msg, struct mce *backup, unsigned long start)
 		if (time_before(tsc, start))
 			continue;
 		print_mce(&mcelog.entry[i]); 
-		if (mcelog.entry[i].tsc == backup->tsc)
+		if (backup && mcelog.entry[i].tsc == backup->tsc)
 			backup = NULL;
 	}
 	if (backup)
@@ -114,9 +115,8 @@ static void mce_panic(char *msg, struct mce *backup, unsigned long start)
 
 static int mce_available(struct cpuinfo_x86 *c)
 {
-	return !mce_disabled && 
-		test_bit(X86_FEATURE_MCE, &c->x86_capability) &&
-		test_bit(X86_FEATURE_MCA, &c->x86_capability);
+	return test_bit(X86_FEATURE_MCE, &c->x86_capability) &&
+	       test_bit(X86_FEATURE_MCA, &c->x86_capability);
 }
 
 /* 
@@ -128,8 +128,9 @@ void do_machine_check(struct pt_regs * regs, long error_code)
 	struct mce m, panicm;
 	int nowayout = (tolerant < 1); 
 	int kill_it = 0;
-	u64 mcestart;
+	u64 mcestart = 0;
 	int i;
+	int panicm_found = 0;
 
 	if (regs)
 		notify_die(DIE_NMI, "machine check", regs, error_code, 255, SIGKILL);
@@ -139,17 +140,11 @@ void do_machine_check(struct pt_regs * regs, long error_code)
 	memset(&m, 0, sizeof(struct mce));
 	m.cpu = hard_smp_processor_id();
 	rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus);
-	if (!regs && (m.mcgstatus & MCG_STATUS_MCIP))
-		return;
 	if (!(m.mcgstatus & MCG_STATUS_RIPV))
 		kill_it = 1;
-	if (regs) {
-		m.rip = regs->rip;
-		m.cs = regs->cs;
-	}
 	
 	rdtscll(mcestart);
-	mb();
+	barrier();
 
 	for (i = 0; i < banks; i++) {
 		if (!bank[i])
@@ -157,52 +152,62 @@ void do_machine_check(struct pt_regs * regs, long error_code)
 		
 		m.misc = 0; 
 		m.addr = 0;
+		m.bank = i;
+		m.tsc = 0;
 
 		rdmsrl(MSR_IA32_MC0_STATUS + i*4, m.status);
 		if ((m.status & MCI_STATUS_VAL) == 0)
 			continue;
-		/* Should be implied by the banks check above, but
-		   check it anyways */
-		if ((m.status & MCI_STATUS_EN) == 0)
-			continue;
 
-		/* Did this bank cause the exception? */
-		/* Assume that the bank with uncorrectable errors did it,
-		   and that there is only a single one. */
-		if (m.status & MCI_STATUS_UC) {
-			panicm = m;
-		} else {
-			m.rip = 0;
-			m.cs = 0;
+		if (m.status & MCI_STATUS_EN) {
+			/* In theory _OVER could be a nowayout too, but
+			   assume any overflowed errors were no fatal. */
+			nowayout |= !!(m.status & MCI_STATUS_PCC);
+			kill_it |= !!(m.status & MCI_STATUS_UC);
 		}
 
-		/* In theory _OVER could be a nowayout too, but
-		   assume any overflowed errors were no fatal. */
-		nowayout |= !!(m.status & MCI_STATUS_PCC);
-		kill_it |= !!(m.status & MCI_STATUS_UC);
-		m.bank = i;
-
 		if (m.status & MCI_STATUS_MISCV)
 			rdmsrl(MSR_IA32_MC0_MISC + i*4, m.misc);
 		if (m.status & MCI_STATUS_ADDRV)
 			rdmsrl(MSR_IA32_MC0_ADDR + i*4, m.addr);
 
-		rdtscll(m.tsc);
+		if (regs && (m.mcgstatus & MCG_STATUS_RIPV)) {
+			m.rip = regs->rip;
+			m.cs = regs->cs;
+		} else {
+			m.rip = 0;
+			m.cs = 0;
+		}
+
+		if (error_code != -1)
+			rdtscll(m.tsc);
 		wrmsrl(MSR_IA32_MC0_STATUS + i*4, 0);
 		mce_log(&m);
+
+		/* Did this bank cause the exception? */
+		/* Assume that the bank with uncorrectable errors did it,
+		   and that there is only a single one. */
+		if ((m.status & MCI_STATUS_UC) && (m.status & MCI_STATUS_EN)) {
+			panicm = m;
+			panicm_found = 1;
+		}
 	}
-	wrmsrl(MSR_IA32_MCG_STATUS, 0);
 
 	/* Never do anything final in the polling timer */
 	if (!regs)
-		return;
+		goto out;
+
+	/* If we didn't find an uncorrectable error, pick
+	   the last one (shouldn't happen, just being safe). */
+	if (!panicm_found)
+		panicm = m;
 	if (nowayout)
-		mce_panic("Machine check", &m, mcestart);
+		mce_panic("Machine check", &panicm, mcestart);
 	if (kill_it) {
 		int user_space = 0;
 
 		if (m.mcgstatus & MCG_STATUS_RIPV)
-			user_space = m.rip && (m.cs & 3);
+			user_space = panicm.rip && (panicm.cs & 3);
 		
 		/* When the machine was in user space and the CPU didn't get
 		   confused it's normally not necessary to panic, unless you 
@@ -215,18 +220,15 @@ void do_machine_check(struct pt_regs * regs, long error_code)
 		    (unsigned)current->pid <= 1)
 			mce_panic("Uncorrected machine check", &panicm, mcestart);
 
-		/* do_exit takes an awful lot of locks and has as slight risk 
-		   of deadlocking. If you don't want that don't set tolerant >= 2 */
+		/* do_exit takes an awful lot of locks and has as
+		   slight risk of deadlocking. If you don't want that
+		   don't set tolerant >= 2 */
 		if (tolerant < 3)
 			do_exit(SIGBUS);
 	}
-}
 
-static void mce_clear_all(void)
-{
-	int i;
-	for (i = 0; i < banks; i++)
-		wrmsrl(MSR_IA32_MC0_STATUS + i*4, 0);
+ out:
+	/* Last thing done in the machine check exception to clear state. */
 	wrmsrl(MSR_IA32_MCG_STATUS, 0);
 }
 
@@ -269,22 +271,25 @@ static void mce_init(void *dummy)
 	int i;
 
 	rdmsrl(MSR_IA32_MCG_CAP, cap);
-	if (cap & MCG_CTL_P)
-		wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
-
 	banks = cap & 0xff;
 	if (banks > NR_BANKS) { 
 		printk(KERN_INFO "MCE: warning: using only %d banks\n", banks);
 		banks = NR_BANKS; 
 	}
 
-	mce_clear_all(); 
+	/* Log the machine checks left over from the previous reset.
+	   This also clears all registers */
+	do_machine_check(NULL, -1);
+
+	set_in_cr4(X86_CR4_MCE);
+
+	if (cap & MCG_CTL_P)
+		wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff);
+
 	for (i = 0; i < banks; i++) {
 		wrmsrl(MSR_IA32_MC0_CTL+4*i, bank[i]);
 		wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
 	}	
-
-	set_in_cr4(X86_CR4_MCE);
 }
 
 /* Add per CPU specific workarounds here */
@@ -308,7 +313,9 @@ void __init mcheck_init(struct cpuinfo_x86 *c)
 
 	mce_cpu_quirks(c); 
 
-	if (test_and_set_bit(smp_processor_id(), &mce_cpus) || !mce_available(c))
+	if (mce_dont_init ||
+	    test_and_set_bit(smp_processor_id(), &mce_cpus) ||
+	    !mce_available(c))
 		return;
 
 	mce_init(NULL);
@@ -333,9 +340,8 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, loff
 	int i, err;
 
 	down(&mce_read_sem); 
-	next = mcelog.next;
-	read_barrier_depends();
-		
+	next = rcu_dereference(mcelog.next);
+
 	/* Only supports full reads right now */
 	if (*off != 0 || usize < MCE_LOG_LEN*sizeof(struct mce)) { 
 		up(&mce_read_sem);
@@ -412,15 +418,16 @@ static struct miscdevice mce_log_device = {
 
 static int __init mcheck_disable(char *str)
 {
-	mce_disabled = 1;
+	mce_dont_init = 1;
 	return 0;
 }
 
-/* mce=off disable machine check */
+/* mce=off disables machine check. Note you can reenable it later
+   using sysfs */
 static int __init mcheck_enable(char *str)
 {
 	if (!strcmp(str, "off"))
-		mce_disabled = 1;
+		mce_dont_init = 1;
 	else
 		printk("mce= argument %s ignored. Please use /sys", str); 
 	return 0;
@@ -436,7 +443,6 @@ __setup("mce", mcheck_enable);
 /* On resume clear all MCE state. Don't want to see leftovers from the BIOS. */
 static int mce_resume(struct sys_device *dev)
 {
-	mce_clear_all();
 	on_each_cpu(mce_init, NULL, 1, 1);
 	return 0;
 }
@@ -465,7 +471,7 @@ static struct sys_device device_mce = {
 /* Why are there no generic functions for this? */
 #define ACCESSOR(name, var, start) \
 	static ssize_t show_ ## name(struct sys_device *s, char *buf) { 	   	   \
-		return sprintf(buf, "%lu\n", (unsigned long)var);		   \
+		return sprintf(buf, "%lx\n", (unsigned long)var);		   \
 	} 									   \
 	static ssize_t set_ ## name(struct sys_device *s,const char *buf,size_t siz) { \
 		char *end; 							   \
@@ -494,7 +500,7 @@ static __init int mce_init_device(void)
 	if (!err)
 		err = sysdev_register(&device_mce);
 	if (!err) { 
-		/* could create per CPU objects, but is not worth it. */
+		/* could create per CPU objects, but it is not worth it. */
 		sysdev_create_file(&device_mce, &attr_bank0ctl); 
 		sysdev_create_file(&device_mce, &attr_bank1ctl); 
 		sysdev_create_file(&device_mce, &attr_bank2ctl); 
diff --git a/arch/x86_64/kernel/msr.c b/arch/x86_64/kernel/msr.c
index 654e4578d..89ad3e729 100644
--- a/arch/x86_64/kernel/msr.c
+++ b/arch/x86_64/kernel/msr.c
@@ -46,234 +46,229 @@
 
 static inline int wrmsr_eio(u32 reg, u32 eax, u32 edx)
 {
-  int err;
-
-  asm volatile(
-	       "1:	wrmsr\n"
-	       "2:\n"
-	       ".section .fixup,\"ax\"\n"
-	       "3:	movl %4,%0\n"
-	       "	jmp 2b\n"
-	       ".previous\n"
-	       ".section __ex_table,\"a\"\n"
-	       "	.align 8\n"
-	       "	.quad 1b,3b\n"
-	       ".previous"
-	       : "=&bDS" (err)
-	       : "a" (eax), "d" (edx), "c" (reg), "i" (-EIO), "0" (0));
-
-  return err;
+	int err;
+
+	asm volatile ("1:	wrmsr\n"
+		      "2:\n"
+		      ".section .fixup,\"ax\"\n"
+		      "3:	movl %4,%0\n"
+		      "	jmp 2b\n"
+		      ".previous\n"
+		      ".section __ex_table,\"a\"\n"
+		      "	.align 8\n" "	.quad 1b,3b\n" ".previous":"=&bDS" (err)
+		      :"a"(eax), "d"(edx), "c"(reg), "i"(-EIO), "0"(0));
+
+	return err;
 }
 
 static inline int rdmsr_eio(u32 reg, u32 *eax, u32 *edx)
 {
-  int err;
-
-  asm volatile(
-	       "1:	rdmsr\n"
-	       "2:\n"
-	       ".section .fixup,\"ax\"\n"
-	       "3:	movl %4,%0\n"
-	       "	jmp 2b\n"
-	       ".previous\n"
-	       ".section __ex_table,\"a\"\n"
-	       "	.align 8\n"
-	       "	.quad 1b,3b\n"
-	       ".previous"
-	       : "=&bDS" (err), "=a" (*eax), "=d" (*edx)
-	       : "c" (reg), "i" (-EIO), "0" (0));
-
-  return err;
+	int err;
+
+	asm volatile ("1:	rdmsr\n"
+		      "2:\n"
+		      ".section .fixup,\"ax\"\n"
+		      "3:	movl %4,%0\n"
+		      "	jmp 2b\n"
+		      ".previous\n"
+		      ".section __ex_table,\"a\"\n"
+		      "	.align 8\n"
+		      "	.quad 1b,3b\n"
+		      ".previous":"=&bDS" (err), "=a"(*eax), "=d"(*edx)
+		      :"c"(reg), "i"(-EIO), "0"(0));
+
+	return err;
 }
 
 #ifdef CONFIG_SMP
 
 struct msr_command {
-  int cpu;
-  int err;
-  u32 reg;
-  u32 data[2];
+	int cpu;
+	int err;
+	u32 reg;
+	u32 data[2];
 };
 
 static void msr_smp_wrmsr(void *cmd_block)
 {
-  struct msr_command *cmd = (struct msr_command *) cmd_block;
-  
-  if ( cmd->cpu == smp_processor_id() )
-    cmd->err = wrmsr_eio(cmd->reg, cmd->data[0], cmd->data[1]);
+	struct msr_command *cmd = (struct msr_command *)cmd_block;
+
+	if (cmd->cpu == smp_processor_id())
+		cmd->err = wrmsr_eio(cmd->reg, cmd->data[0], cmd->data[1]);
 }
 
 static void msr_smp_rdmsr(void *cmd_block)
 {
-  struct msr_command *cmd = (struct msr_command *) cmd_block;
-  
-  if ( cmd->cpu == smp_processor_id() )
-    cmd->err = rdmsr_eio(cmd->reg, &cmd->data[0], &cmd->data[1]);
+	struct msr_command *cmd = (struct msr_command *)cmd_block;
+
+	if (cmd->cpu == smp_processor_id())
+		cmd->err = rdmsr_eio(cmd->reg, &cmd->data[0], &cmd->data[1]);
 }
 
 static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx)
 {
-  struct msr_command cmd;
-  int ret;
-
-  preempt_disable();
-  if ( cpu == smp_processor_id() ) {
-    ret = wrmsr_eio(reg, eax, edx);
-  } else {
-    cmd.cpu = cpu;
-    cmd.reg = reg;
-    cmd.data[0] = eax;
-    cmd.data[1] = edx;
-    
-    smp_call_function(msr_smp_wrmsr, &cmd, 1, 1);
-    ret = cmd.err;
-  }
-  preempt_enable();
-  return ret;
+	struct msr_command cmd;
+	int ret;
+
+	preempt_disable();
+	if (cpu == smp_processor_id()) {
+		ret = wrmsr_eio(reg, eax, edx);
+	} else {
+		cmd.cpu = cpu;
+		cmd.reg = reg;
+		cmd.data[0] = eax;
+		cmd.data[1] = edx;
+
+		smp_call_function(msr_smp_wrmsr, &cmd, 1, 1);
+		ret = cmd.err;
+	}
+	preempt_enable();
+	return ret;
 }
 
-static inline int do_rdmsr(int cpu, u32 reg, u32 *eax, u32 *edx)
+static inline int do_rdmsr(int cpu, u32 reg, u32 * eax, u32 * edx)
 {
-  struct msr_command cmd;
-  int ret;
-
-  preempt_disable();
-  if ( cpu == smp_processor_id() ) {
-    ret = rdmsr_eio(reg, eax, edx);
-  } else {
-    cmd.cpu = cpu;
-    cmd.reg = reg;
-
-    smp_call_function(msr_smp_rdmsr, &cmd, 1, 1);
-    
-    *eax = cmd.data[0];
-    *edx = cmd.data[1];
-
-    ret = cmd.err;
-  }
-  preempt_enable();
-  return ret;
+	struct msr_command cmd;
+	int ret;
+
+	preempt_disable();
+	if (cpu == smp_processor_id()) {
+		ret = rdmsr_eio(reg, eax, edx);
+	} else {
+		cmd.cpu = cpu;
+		cmd.reg = reg;
+
+		smp_call_function(msr_smp_rdmsr, &cmd, 1, 1);
+
+		*eax = cmd.data[0];
+		*edx = cmd.data[1];
+
+		ret = cmd.err;
+	}
+	preempt_enable();
+	return ret;
 }
 
-#else /* ! CONFIG_SMP */
+#else				/* ! CONFIG_SMP */
 
 static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx)
 {
-  return wrmsr_eio(reg, eax, edx);
+	return wrmsr_eio(reg, eax, edx);
 }
 
 static inline int do_rdmsr(int cpu, u32 reg, u32 *eax, u32 *edx)
 {
-  return rdmsr_eio(reg, eax, edx);
+	return rdmsr_eio(reg, eax, edx);
 }
 
-#endif /* ! CONFIG_SMP */
+#endif				/* ! CONFIG_SMP */
 
 static loff_t msr_seek(struct file *file, loff_t offset, int orig)
 {
-  loff_t ret = -EINVAL;
-  lock_kernel();
-  switch (orig) {
-  case 0:
-    file->f_pos = offset;
-    ret = file->f_pos;
-    break;
-  case 1:
-    file->f_pos += offset;
-    ret = file->f_pos;
-  }
-  unlock_kernel();
-  return ret;
+	loff_t ret = -EINVAL;
+
+	lock_kernel();
+	switch (orig) {
+	case 0:
+		file->f_pos = offset;
+		ret = file->f_pos;
+		break;
+	case 1:
+		file->f_pos += offset;
+		ret = file->f_pos;
+	}
+	unlock_kernel();
+	return ret;
 }
 
-static ssize_t msr_read(struct file * file, char __user * buf,
-			size_t count, loff_t *ppos)
+static ssize_t msr_read(struct file *file, char __user * buf,
+			size_t count, loff_t * ppos)
 {
-  char __user *tmp = buf;
-  u32 data[2];
-  size_t rv;
-  u32 reg = *ppos;
-  int cpu = iminor(file->f_dentry->d_inode);
-  int err;
-
-  if ( count % 8 )
-    return -EINVAL; /* Invalid chunk size */
-  
-  for ( rv = 0 ; count ; count -= 8 ) {
-    err = do_rdmsr(cpu, reg, &data[0], &data[1]);
-    if ( err )
-      return err;
-    if ( copy_to_user(tmp,&data,8) )
-      return -EFAULT;
-    tmp += 8;
-  }
-
-  return tmp - buf;
+	u32 __user *tmp = (u32 __user *) buf;
+	u32 data[2];
+	size_t rv;
+	u32 reg = *ppos;
+	int cpu = iminor(file->f_dentry->d_inode);
+	int err;
+
+	if (count % 8)
+		return -EINVAL;	/* Invalid chunk size */
+
+	for (rv = 0; count; count -= 8) {
+		err = do_rdmsr(cpu, reg, &data[0], &data[1]);
+		if (err)
+			return err;
+		if (copy_to_user(tmp, &data, 8))
+			return -EFAULT;
+		tmp += 2;
+	}
+
+	return ((char __user *)tmp) - buf;
 }
 
-static ssize_t msr_write(struct file * file, const char __user * buf,
+static ssize_t msr_write(struct file *file, const char __user *buf,
 			 size_t count, loff_t *ppos)
 {
-  const char __user *tmp = buf;
-  u32 data[2];
-  size_t rv;
-  u32 reg = *ppos;
-  int cpu = iminor(file->f_dentry->d_inode);
-  int err;
-
-  if ( count % 8 )
-    return -EINVAL; /* Invalid chunk size */
-  
-  for ( rv = 0 ; count ; count -= 8 ) {
-    if ( copy_from_user(&data,tmp,8) )
-      return -EFAULT;
-    err = do_wrmsr(cpu, reg, data[0], data[1]);
-    if ( err )
-      return err;
-    tmp += 8;
-  }
-
-  return tmp - buf;
+	const u32 __user *tmp = (const u32 __user *)buf;
+	u32 data[2];
+	size_t rv;
+	u32 reg = *ppos;
+	int cpu = iminor(file->f_dentry->d_inode);
+	int err;
+
+	if (count % 8)
+		return -EINVAL;	/* Invalid chunk size */
+
+	for (rv = 0; count; count -= 8) {
+		if (copy_from_user(&data, tmp, 8))
+			return -EFAULT;
+		err = do_wrmsr(cpu, reg, data[0], data[1]);
+		if (err)
+			return err;
+		tmp += 2;
+	}
+
+	return ((char __user *)tmp) - buf;
 }
 
 static int msr_open(struct inode *inode, struct file *file)
 {
-  int cpu = iminor(file->f_dentry->d_inode);
-  struct cpuinfo_x86 *c = &(cpu_data)[cpu];
-  
-  if (cpu >= NR_CPUS || !cpu_online(cpu))
-    return -ENXIO;		/* No such CPU */
-  if ( !cpu_has(c, X86_FEATURE_MSR) )
-    return -EIO;		/* MSR not supported */
-  
-  return 0;
+	unsigned int cpu = iminor(file->f_dentry->d_inode);
+	struct cpuinfo_x86 *c = &(cpu_data)[cpu];
+
+	if (cpu >= NR_CPUS || !cpu_online(cpu))
+		return -ENXIO;	/* No such CPU */
+	if (!cpu_has(c, X86_FEATURE_MSR))
+		return -EIO;	/* MSR not supported */
+
+	return 0;
 }
 
 /*
  * File operations we support
  */
 static struct file_operations msr_fops = {
-  .owner =	THIS_MODULE,
-  .llseek =	msr_seek,
-  .read =	msr_read,
-  .write =	msr_write,
-  .open =	msr_open,
+	.owner = THIS_MODULE,
+	.llseek = msr_seek,
+	.read = msr_read,
+	.write = msr_write,
+	.open = msr_open,
 };
 
 int __init msr_init(void)
 {
-  if (register_chrdev(MSR_MAJOR, "cpu/msr", &msr_fops)) {
-    printk(KERN_ERR "msr: unable to get major %d for msr\n",
-	   MSR_MAJOR);
-    return -EBUSY;
-  }
-  
-  return 0;
+	if (register_chrdev(MSR_MAJOR, "cpu/msr", &msr_fops)) {
+		printk(KERN_ERR "msr: unable to get major %d for msr\n",
+		       MSR_MAJOR);
+		return -EBUSY;
+	}
+
+	return 0;
 }
 
 void __exit msr_exit(void)
 {
-  unregister_chrdev(MSR_MAJOR, "cpu/msr");
+	unregister_chrdev(MSR_MAJOR, "cpu/msr");
 }
 
 module_init(msr_init);
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index 35dd5dfc0..4920c8df7 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -390,7 +390,8 @@ void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason)
 		 */
 		alert_counter[cpu]++;
 		if (alert_counter[cpu] == 5*nmi_hz) {
-			if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_BAD) { 
+			if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT)
+							== NOTIFY_STOP) {
 				alert_counter[cpu] = 0; 
 				return;
 			} 
diff --git a/arch/x86_64/kernel/pci-dma.c b/arch/x86_64/kernel/pci-dma.c
index 7eb3fc72a..cab471cf3 100644
--- a/arch/x86_64/kernel/pci-dma.c
+++ b/arch/x86_64/kernel/pci-dma.c
@@ -1,5 +1,5 @@
 /*
- * Dynamic DMA mapping support. Common code
+ * Dynamic DMA mapping support.
  */
 
 #include <linux/types.h>
@@ -24,38 +24,37 @@
  * Device ownership issues as mentioned above for pci_map_single are
  * the same here.
  */
-int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-			     int nents, int direction)
+int dma_map_sg(struct device *hwdev, struct scatterlist *sg,
+	       int nents, int direction)
 {
 	int i;
 
-	BUG_ON(direction == PCI_DMA_NONE);
+	BUG_ON(direction == DMA_NONE);
  	for (i = 0; i < nents; i++ ) {
 		struct scatterlist *s = &sg[i];
 		BUG_ON(!s->page); 
-			s->dma_address = pci_map_page(hwdev, s->page, s->offset, 
-						      s->length, direction); 
+		s->dma_address = virt_to_bus(page_address(s->page) +s->offset);
 		s->dma_length = s->length;
 	}
 	return nents;
 }
 
-EXPORT_SYMBOL(pci_map_sg);
+EXPORT_SYMBOL(dma_map_sg);
 
 /* Unmap a set of streaming mode DMA translations.
  * Again, cpu read rules concerning calls here are the same as for
  * pci_unmap_single() above.
  */
-void pci_unmap_sg(struct pci_dev *dev, struct scatterlist *sg, 
-				  int nents, int dir)
+void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+		  int nents, int dir)
 {
 	int i;
 	for (i = 0; i < nents; i++) { 
 		struct scatterlist *s = &sg[i];
 		BUG_ON(s->page == NULL); 
 		BUG_ON(s->dma_address == 0); 
-		pci_unmap_single(dev, s->dma_address, s->dma_length, dir); 
+		dma_unmap_single(dev, s->dma_address, s->dma_length, dir);
 	} 
 }
 
-EXPORT_SYMBOL(pci_unmap_sg);
+EXPORT_SYMBOL(dma_unmap_sg);
diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c
index 09fde74cb..ca608a2a0 100644
--- a/arch/x86_64/kernel/pci-gart.c
+++ b/arch/x86_64/kernel/pci-gart.c
@@ -31,12 +31,6 @@
 #include <asm/cacheflush.h>
 #include <asm/kdebug.h>
 
-#ifdef CONFIG_PREEMPT
-#define preempt_atomic() in_atomic()
-#else
-#define preempt_atomic() 1
-#endif
-
 dma_addr_t bad_dma_address;
 
 unsigned long iommu_bus_base;	/* GART remapping area (physical) */
@@ -54,7 +48,7 @@ int force_iommu = 1;
 int panic_on_overflow = 0;
 int force_iommu = 0;
 #endif
-int iommu_merge = 0; 
+int iommu_merge = 1;
 int iommu_sac_force = 0; 
 
 /* If this is disabled the IOMMU will use an optimized flushing strategy
@@ -64,6 +58,10 @@ int iommu_sac_force = 0;
    also seen with Qlogic at least). */
 int iommu_fullflush = 1;
 
+/* This tells the BIO block layer to assume merging. Default to off
+   because we cannot guarantee merging later. */
+int iommu_bio_merge = 0;
+
 #define MAX_NB 8
 
 /* Allocation bitmap for the remapping area */ 
@@ -104,8 +102,16 @@ AGPEXTERN __u32 *agp_gatt_table;
 
 static unsigned long next_bit;  /* protected by iommu_bitmap_lock */
 static int need_flush; 		/* global flush state. set for each gart wrap */
-static dma_addr_t pci_map_area(struct pci_dev *dev, unsigned long phys_mem, 
-			       size_t size, int dir);
+static dma_addr_t dma_map_area(struct device *dev, unsigned long phys_mem,
+			       size_t size, int dir, int do_panic);
+
+/* Dummy device used for NULL arguments (normally ISA). Better would
+   be probably a smaller DMA mask, but this is bug-to-bug compatible to i386. */
+static struct device fallback_dev = {
+	.bus_id = "fallback device",
+	.coherent_dma_mask = 0xffffffff,
+	.dma_mask = &fallback_dev.coherent_dma_mask,
+};
 
 static unsigned long alloc_iommu(int size) 
 { 	
@@ -146,25 +152,31 @@ static void free_iommu(unsigned long offset, int size)
 /* 
  * Use global flush state to avoid races with multiple flushers.
  */
-static void flush_gart(struct pci_dev *dev)
+static void flush_gart(struct device *dev)
 { 
 	unsigned long flags;
 	int flushed = 0;
-	int i;
+	int i, max;
 
 	spin_lock_irqsave(&iommu_bitmap_lock, flags);
 	if (need_flush) { 
+		max = 0;
 		for (i = 0; i < MAX_NB; i++) {
-			u32 w;
 			if (!northbridges[i]) 
 				continue;
 			pci_write_config_dword(northbridges[i], 0x9c, 
 					       northbridge_flush_word[i] | 1); 
+			flushed++;
+			max = i;
+		}
+		for (i = 0; i <= max; i++) {
+			u32 w;
+			if (!northbridges[i])
+				continue;
 			/* Make sure the hardware actually executed the flush. */
 			do { 
 				pci_read_config_dword(northbridges[i], 0x9c, &w);
 			} while (w & 1);
-			flushed++;
 		} 
 		if (!flushed) 
 			printk("nothing to flush?\n");
@@ -173,31 +185,47 @@ static void flush_gart(struct pci_dev *dev)
 	spin_unlock_irqrestore(&iommu_bitmap_lock, flags);
 } 
 
+/* Allocate DMA memory on node near device */
+noinline
+static void *dma_alloc_pages(struct device *dev, unsigned gfp, unsigned order)
+{
+	struct page *page;
+	int node;
+	if (dev->bus == &pci_bus_type) {
+		cpumask_t mask;
+		mask = pcibus_to_cpumask(to_pci_dev(dev)->bus->number);
+		node = cpu_to_node(first_cpu(mask));
+	} else
+		node = numa_node_id();
+	page = alloc_pages_node(node, gfp, order);
+	return page ? page_address(page) : NULL;
+}
+
 /* 
- * Allocate memory for a consistent mapping.
+ * Allocate memory for a coherent mapping.
  */
-void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
-			   dma_addr_t *dma_handle)
+void *
+dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+		   unsigned gfp)
 {
 	void *memory;
-	int gfp = preempt_atomic() ? GFP_ATOMIC : GFP_KERNEL; 
 	unsigned long dma_mask = 0;
 	u64 bus;
 
-	if (hwdev) 
-		dma_mask = hwdev->dev.coherent_dma_mask;
+	if (!dev)
+		dev = &fallback_dev;
+	dma_mask = dev->coherent_dma_mask;
 	if (dma_mask == 0) 
 		dma_mask = 0xffffffff; 
 
 	/* Kludge to make it bug-to-bug compatible with i386. i386
-	   uses the normal dma_mask for alloc_consistent. */
-	if (hwdev)
-	dma_mask &= hwdev->dma_mask;
+	   uses the normal dma_mask for alloc_coherent. */
+	dma_mask &= *dev->dma_mask;
 
  again:
-	memory = (void *)__get_free_pages(gfp, get_order(size));
+	memory = dma_alloc_pages(dev, gfp, get_order(size));
 	if (memory == NULL)
-		return NULL; 
+		return NULL;
 
 	{
 		int high, mmu;
@@ -223,28 +251,29 @@ void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
 		}
 	} 
 
-	*dma_handle = pci_map_area(hwdev, bus, size, PCI_DMA_BIDIRECTIONAL);
+	*dma_handle = dma_map_area(dev, bus, size, PCI_DMA_BIDIRECTIONAL, 0);
 	if (*dma_handle == bad_dma_address)
 		goto error; 
-	flush_gart(hwdev);	
+	flush_gart(dev);
 	return memory; 
 	
 error:
 	if (panic_on_overflow)
-		panic("pci_alloc_consistent: overflow %lu bytes\n", size); 
+		panic("dma_alloc_coherent: IOMMU overflow by %lu bytes\n", size);
 free:
 	free_pages((unsigned long)memory, get_order(size)); 
+	/* XXX Could use the swiotlb pool here too */
 	return NULL; 
 }
 
 /* 
- * Unmap consistent memory.
+ * Unmap coherent memory.
  * The caller must ensure that the device has finished accessing the mapping.
  */
-void pci_free_consistent(struct pci_dev *hwdev, size_t size,
+void dma_free_coherent(struct device *dev, size_t size,
 			 void *vaddr, dma_addr_t bus)
 {
-	pci_unmap_single(hwdev, bus, size, 0);
+	dma_unmap_single(dev, bus, size, 0);
 	free_pages((unsigned long)vaddr, get_order(size)); 		
 }
 
@@ -280,7 +309,7 @@ void dump_leak(void)
 #define CLEAR_LEAK(x)
 #endif
 
-static void iommu_full(struct pci_dev *dev, size_t size, int dir)
+static void iommu_full(struct device *dev, size_t size, int dir, int do_panic)
 {
 	/* 
 	 * Ran out of IOMMU space for this operation. This is very bad.
@@ -293,14 +322,14 @@ static void iommu_full(struct pci_dev *dev, size_t size, int dir)
 	 */ 
 	
 	printk(KERN_ERR 
-  "PCI-DMA: Out of IOMMU space for %lu bytes at device %s[%s]\n",
-	       size, dev ? pci_pretty_name(dev) : "", dev ? dev->slot_name : "?");
+  "PCI-DMA: Out of IOMMU space for %lu bytes at device %s\n",
+	       size, dev->bus_id);
 
-	if (size > PAGE_SIZE*EMERGENCY_PAGES) {
+	if (size > PAGE_SIZE*EMERGENCY_PAGES && do_panic) {
 		if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL)
-			panic("PCI-DMA: Memory will be corrupted\n");
+			panic("PCI-DMA: Memory would be corrupted\n");
 		if (dir == PCI_DMA_TODEVICE || dir == PCI_DMA_BIDIRECTIONAL) 
-			panic("PCI-DMA: Random memory will be DMAed\n"); 
+			panic("PCI-DMA: Random memory would be DMAed\n");
 	} 
 
 #ifdef CONFIG_IOMMU_LEAK
@@ -308,9 +337,9 @@ static void iommu_full(struct pci_dev *dev, size_t size, int dir)
 #endif
 } 
 
-static inline int need_iommu(struct pci_dev *dev, unsigned long addr, size_t size)
+static inline int need_iommu(struct device *dev, unsigned long addr, size_t size)
 { 
-	u64 mask = dev ? dev->dma_mask : 0xffffffff;
+	u64 mask = *dev->dma_mask;
 	int high = addr + size >= mask;
 	int mmu = high;
 	if (force_iommu) 
@@ -323,9 +352,9 @@ static inline int need_iommu(struct pci_dev *dev, unsigned long addr, size_t siz
 	return mmu; 
 }
 
-static inline int nonforced_iommu(struct pci_dev *dev, unsigned long addr, size_t size)
+static inline int nonforced_iommu(struct device *dev, unsigned long addr, size_t size)
 { 
-	u64 mask = dev ? dev->dma_mask : 0xffffffff;
+	u64 mask = *dev->dma_mask;
 	int high = addr + size >= mask;
 	int mmu = high;
 	if (no_iommu) { 
@@ -339,8 +368,8 @@ static inline int nonforced_iommu(struct pci_dev *dev, unsigned long addr, size_
 /* Map a single continuous physical area into the IOMMU.
  * Caller needs to check if the iommu is needed and flush.
  */
-static dma_addr_t pci_map_area(struct pci_dev *dev, unsigned long phys_mem, 
-				size_t size, int dir)
+static dma_addr_t dma_map_area(struct device *dev, unsigned long phys_mem,
+				size_t size, int dir, int do_panic)
 { 
 	unsigned long npages = to_pages(phys_mem, size);
 	unsigned long iommu_page = alloc_iommu(npages);
@@ -349,8 +378,8 @@ static dma_addr_t pci_map_area(struct pci_dev *dev, unsigned long phys_mem,
 		if (!nonforced_iommu(dev, phys_mem, size))
 			return phys_mem; 
 		if (panic_on_overflow)
-			panic("pci_map_area overflow %lu bytes\n", size);
-		iommu_full(dev, size, dir);
+			panic("dma_map_area overflow %lu bytes\n", size);
+		iommu_full(dev, size, dir, do_panic);
 		return bad_dma_address;
 	}
 
@@ -363,44 +392,44 @@ static dma_addr_t pci_map_area(struct pci_dev *dev, unsigned long phys_mem,
 }
 
 /* Map a single area into the IOMMU */
-dma_addr_t pci_map_single(struct pci_dev *dev, void *addr, size_t size, int dir)
-{ 
+dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size, int dir)
+{
 	unsigned long phys_mem, bus;
 
-	BUG_ON(dir == PCI_DMA_NONE);
+	BUG_ON(dir == DMA_NONE);
 
-#ifdef CONFIG_SWIOTLB
 	if (swiotlb)
-		return swiotlb_map_single(&dev->dev,addr,size,dir);
-#endif
+		return swiotlb_map_single(dev,addr,size,dir);
+	if (!dev)
+		dev = &fallback_dev;
 
 	phys_mem = virt_to_phys(addr); 
 	if (!need_iommu(dev, phys_mem, size))
 		return phys_mem; 
 
-	bus = pci_map_area(dev, phys_mem, size, dir);
+	bus = dma_map_area(dev, phys_mem, size, dir, 1);
 	flush_gart(dev); 
 	return bus; 
 } 
 
-/* Fallback for pci_map_sg in case of overflow */ 
-static int pci_map_sg_nonforce(struct pci_dev *dev, struct scatterlist *sg,
+/* Fallback for dma_map_sg in case of overflow */
+static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
 			       int nents, int dir)
 {
 	int i;
 
 #ifdef CONFIG_IOMMU_DEBUG
-	printk(KERN_DEBUG "pci_map_sg overflow\n");
+	printk(KERN_DEBUG "dma_map_sg overflow\n");
 #endif
 
  	for (i = 0; i < nents; i++ ) {
 		struct scatterlist *s = &sg[i];
 		unsigned long addr = page_to_phys(s->page) + s->offset; 
 		if (nonforced_iommu(dev, addr, s->length)) { 
-			addr = pci_map_area(dev, addr, s->length, dir); 
+			addr = dma_map_area(dev, addr, s->length, dir, 0);
 			if (addr == bad_dma_address) { 
 				if (i > 0) 
-					pci_unmap_sg(dev, sg, i, dir); 
+					dma_unmap_sg(dev, sg, i, dir);
 				nents = 0; 
 				sg[0].dma_length = 0;
 				break;
@@ -414,7 +443,7 @@ static int pci_map_sg_nonforce(struct pci_dev *dev, struct scatterlist *sg,
 }
 
 /* Map multiple scatterlist entries continuous into the first. */
-static int __pci_map_cont(struct scatterlist *sg, int start, int stopat, 
+static int __dma_map_cont(struct scatterlist *sg, int start, int stopat,
 		      struct scatterlist *sout, unsigned long pages)
 {
 	unsigned long iommu_start = alloc_iommu(pages);
@@ -452,7 +481,7 @@ static int __pci_map_cont(struct scatterlist *sg, int start, int stopat,
 	return 0;
 }
 
-static inline int pci_map_cont(struct scatterlist *sg, int start, int stopat, 
+static inline int dma_map_cont(struct scatterlist *sg, int start, int stopat,
 		      struct scatterlist *sout,
 		      unsigned long pages, int need)
 {
@@ -462,14 +491,14 @@ static inline int pci_map_cont(struct scatterlist *sg, int start, int stopat,
 		sout->dma_length = sg[start].length; 
 		return 0;
 	} 
-	return __pci_map_cont(sg, start, stopat, sout, pages);
+	return __dma_map_cont(sg, start, stopat, sout, pages);
 }
 		
 /*
  * DMA map all entries in a scatterlist.
  * Merge chunks that have page aligned sizes into a continuous mapping. 
-		 */
-int pci_map_sg(struct pci_dev *dev, struct scatterlist *sg, int nents, int dir)
+ */
+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
 {
 	int i;
 	int out;
@@ -477,19 +506,14 @@ int pci_map_sg(struct pci_dev *dev, struct scatterlist *sg, int nents, int dir)
 	unsigned long pages = 0;
 	int need = 0, nextneed;
 
-#ifdef CONFIG_SWIOTLB
-	if (swiotlb)
-		return swiotlb_map_sg(&dev->dev,sg,nents,dir);
-#endif
-
-	BUG_ON(dir == PCI_DMA_NONE);
+	BUG_ON(dir == DMA_NONE);
 	if (nents == 0) 
 		return 0;
 
-#ifdef CONFIG_SWIOTLB
 	if (swiotlb)
-		return swiotlb_map_sg(&dev->dev,sg,nents,dir);
-#endif
+		return swiotlb_map_sg(dev,sg,nents,dir);
+	if (!dev)
+		dev = &fallback_dev;
 
 	out = 0;
 	start = 0;
@@ -508,19 +532,19 @@ int pci_map_sg(struct pci_dev *dev, struct scatterlist *sg, int nents, int dir)
 			   boundary and the new one doesn't have an offset. */
 			if (!iommu_merge || !nextneed || !need || s->offset ||
 			    (ps->offset + ps->length) % PAGE_SIZE) { 
-				if (pci_map_cont(sg, start, i, sg+out, pages, 
+				if (dma_map_cont(sg, start, i, sg+out, pages,
 						 need) < 0)
 					goto error;
 				out++;
 				pages = 0;
 				start = i;	
 			}
-	}
+		}
 
 		need = nextneed;
 		pages += to_pages(s->offset, s->length);
 	}
-	if (pci_map_cont(sg, start, i, sg+out, pages, need) < 0)
+	if (dma_map_cont(sg, start, i, sg+out, pages, need) < 0)
 		goto error;
 	out++;
 	flush_gart(dev);
@@ -530,34 +554,32 @@ int pci_map_sg(struct pci_dev *dev, struct scatterlist *sg, int nents, int dir)
 
 error:
 	flush_gart(NULL);
-	pci_unmap_sg(dev, sg, nents, dir);
+	dma_unmap_sg(dev, sg, nents, dir);
 	/* When it was forced try again unforced */
 	if (force_iommu) 
-		return pci_map_sg_nonforce(dev, sg, nents, dir);
+		return dma_map_sg_nonforce(dev, sg, nents, dir);
 	if (panic_on_overflow)
-		panic("pci_map_sg: overflow on %lu pages\n", pages); 
-	iommu_full(dev, pages << PAGE_SHIFT, dir);
+		panic("dma_map_sg: overflow on %lu pages\n", pages);
+	iommu_full(dev, pages << PAGE_SHIFT, dir, 0);
 	for (i = 0; i < nents; i++)
 		sg[i].dma_address = bad_dma_address;
 	return 0;
 } 
 
 /*
- * Free a PCI mapping.
+ * Free a DMA mapping.
  */ 
-void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
+void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
 		      size_t size, int direction)
 {
 	unsigned long iommu_page; 
 	int npages;
 	int i;
 
-#ifdef CONFIG_SWIOTLB
 	if (swiotlb) {
-		swiotlb_unmap_single(&hwdev->dev,dma_addr,size,direction);
+		swiotlb_unmap_single(dev,dma_addr,size,direction);
 		return;
 	}
-#endif
 
 	if (dma_addr < iommu_bus_base + EMERGENCY_PAGES*PAGE_SIZE || 
 	    dma_addr >= iommu_bus_base + iommu_size)
@@ -574,22 +596,25 @@ void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
 /* 
  * Wrapper for pci_unmap_single working with scatterlists.
  */ 
-void pci_unmap_sg(struct pci_dev *dev, struct scatterlist *sg, int nents, 
-		  int dir)
+void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
 {
 	int i;
+	if (swiotlb) {
+		swiotlb_unmap_sg(dev,sg,nents,dir);
+		return;
+	}
 	for (i = 0; i < nents; i++) { 
 		struct scatterlist *s = &sg[i];
 		if (!s->dma_length || !s->length) 
 			break;
-		pci_unmap_single(dev, s->dma_address, s->dma_length, dir);
+		dma_unmap_single(dev, s->dma_address, s->dma_length, dir);
 	}
 }
 
-int pci_dma_supported(struct pci_dev *dev, u64 mask)
+int dma_supported(struct device *dev, u64 mask)
 {
 	/* Copied from i386. Doesn't make much sense, because it will 
-	   only work for pci_alloc_consistent. 
+	   only work for pci_alloc_coherent.
 	   The caller just has to use GFP_DMA in this case. */
         if (mask < 0x00ffffff)
                 return 0;
@@ -605,22 +630,31 @@ int pci_dma_supported(struct pci_dev *dev, u64 mask)
 	   Assume all masks <= 40 bits are of this type. Normally this doesn't
 	   make any difference, but gives more gentle handling of IOMMU overflow. */
 	if (iommu_sac_force && (mask >= 0xffffffffffULL)) { 
-		printk(KERN_INFO "%s: Force SAC with mask %Lx\n", dev->slot_name,mask);
+		printk(KERN_INFO "%s: Force SAC with mask %Lx\n", dev->bus_id,mask);
 		return 0; 
 	}
 
 	return 1;
 } 
 
-EXPORT_SYMBOL(pci_unmap_sg);
-EXPORT_SYMBOL(pci_map_sg);
-EXPORT_SYMBOL(pci_map_single);
-EXPORT_SYMBOL(pci_unmap_single);
-EXPORT_SYMBOL(pci_dma_supported);
+int dma_get_cache_alignment(void)
+{
+	return boot_cpu_data.x86_clflush_size;
+}
+
+EXPORT_SYMBOL(dma_unmap_sg);
+EXPORT_SYMBOL(dma_map_sg);
+EXPORT_SYMBOL(dma_map_single);
+EXPORT_SYMBOL(dma_unmap_single);
+EXPORT_SYMBOL(dma_supported);
 EXPORT_SYMBOL(no_iommu);
 EXPORT_SYMBOL(force_iommu); 
 EXPORT_SYMBOL(bad_dma_address);
-EXPORT_SYMBOL(iommu_merge);
+EXPORT_SYMBOL(iommu_bio_merge);
+EXPORT_SYMBOL(iommu_sac_force);
+EXPORT_SYMBOL(dma_get_cache_alignment);
+EXPORT_SYMBOL(dma_alloc_coherent);
+EXPORT_SYMBOL(dma_free_coherent);
 
 static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size)
 { 
@@ -747,7 +781,7 @@ static int __init pci_iommu_init(void)
 
 	if (swiotlb) { 
 		no_iommu = 1;
-		printk(KERN_INFO "PCI-DMA: Using software bounce buffering for  IO (SWIOTLB)\n"); 
+		printk(KERN_INFO "PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n");
 		return -1; 
 	} 
 	
@@ -851,7 +885,7 @@ static int __init pci_iommu_init(void)
 fs_initcall(pci_iommu_init);
 
 /* iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,merge]
-         [,forcesac][,fullflush][,nomerge]
+         [,forcesac][,fullflush][,nomerge][,biomerge]
    size  set size of iommu (in bytes) 
    noagp don't initialize the AGP driver and use full aperture.
    off   don't use the IOMMU
@@ -859,60 +893,73 @@ fs_initcall(pci_iommu_init);
    memaper[=order] allocate an own aperture over RAM with size 32MB^order.  
    noforce don't force IOMMU usage. Default.
    force  Force IOMMU.
-   merge  Do SG merging. Implies force (experimental)  
+   merge  Do lazy merging. This may improve performance on some block devices.
+          Implies force (experimental)
+   biomerge Do merging at the BIO layer. This is more efficient than merge,
+            but should be only done with very big IOMMUs. Implies merge,force.
    nomerge Don't do SG merging.
    forcesac For SAC mode for masks <40bits  (experimental)
    fullflush Flush IOMMU on each allocation (default) 
    nofullflush Don't use IOMMU fullflush
    allowed  overwrite iommu off workarounds for specific chipsets.
    soft	 Use software bounce buffering (default for Intel machines)
+   noaperture Don't touch the aperture for AGP.
 */
-__init int iommu_setup(char *opt) 
+__init int iommu_setup(char *p)
 { 
     int arg;
-    char *p = opt;
-    
-    for (;;) { 
-	    if (!memcmp(p,"noagp", 5))
+
+    while (*p) {
+	    if (!strncmp(p,"noagp",5))
 		    no_agp = 1;
-	    if (!memcmp(p,"off", 3))
+	    if (!strncmp(p,"off",3))
 		    no_iommu = 1;
-	    if (!memcmp(p,"force", 5)) {
+	    if (!strncmp(p,"force",5)) {
 		    force_iommu = 1;
 		    iommu_aperture_allowed = 1;
 	    }
-	    if (!memcmp(p,"allowed",7))
+	    if (!strncmp(p,"allowed",7))
 		    iommu_aperture_allowed = 1;
-	    if (!memcmp(p,"noforce", 7)) { 
+	    if (!strncmp(p,"noforce",7)) {
 		    iommu_merge = 0;
 		    force_iommu = 0;
 	    }
-	    if (!memcmp(p, "memaper", 7)) { 
+	    if (!strncmp(p, "memaper", 7)) {
 		    fallback_aper_force = 1; 
 		    p += 7; 
-		    if (*p == '=' && get_option(&p, &arg))
-			    fallback_aper_order = arg;
+		    if (*p == '=') {
+			    ++p;
+			    if (get_option(&p, &arg))
+				    fallback_aper_order = arg;
+		    }
 	    } 
-	    if (!memcmp(p, "panic", 5))
+	    if (!strncmp(p, "biomerge",8)) {
+		    iommu_bio_merge = 4096;
+		    iommu_merge = 1;
+		    force_iommu = 1;
+	    }
+	    if (!strncmp(p, "panic",5))
 		    panic_on_overflow = 1;
-	    if (!memcmp(p, "nopanic", 7))
+	    if (!strncmp(p, "nopanic",7))
 		    panic_on_overflow = 0;	    
-	    if (!memcmp(p, "merge", 5)) { 
+	    if (!strncmp(p, "merge",5)) {
 		    iommu_merge = 1;
 		    force_iommu = 1; 
 	    }
-	    if (!memcmp(p, "nomerge", 7))
+	    if (!strncmp(p, "nomerge",7))
 		    iommu_merge = 0;
-	    if (!memcmp(p, "forcesac", 8))
+	    if (!strncmp(p, "forcesac",8))
 		    iommu_sac_force = 1;
-	    if (!memcmp(p, "fullflush", 9))
+	    if (!strncmp(p, "fullflush",8))
 		    iommu_fullflush = 1;
-	    if (!memcmp(p, "nofullflush", 11))
+	    if (!strncmp(p, "nofullflush",11))
 		    iommu_fullflush = 0;
-	    if (!memcmp(p, "soft", 4))
+	    if (!strncmp(p, "soft",4))
 		    swiotlb = 1;
+	    if (!strncmp(p, "noaperture",10))
+		    fix_aperture = 0;
 #ifdef CONFIG_IOMMU_LEAK
-	    if (!memcmp(p,"leak", 4)) { 
+	    if (!strncmp(p,"leak",4)) {
 		    leak_trace = 1;
 		    p += 4; 
 		    if (*p == '=') ++p;
@@ -922,10 +969,9 @@ __init int iommu_setup(char *opt)
 #endif
 	    if (isdigit(*p) && get_option(&p, &arg)) 
 		    iommu_size = arg;
-	    do {
-		    if (*p == ' ' || *p == 0) 
-			    return 0; 
-	    } while (*p++ != ','); 
+	    p += strcspn(p, ",");
+	    if (*p == ',')
+		    ++p;
     }
     return 1;
 } 
diff --git a/arch/x86_64/kernel/pci-nommu.c b/arch/x86_64/kernel/pci-nommu.c
index 00fb2645c..67d90b89a 100644
--- a/arch/x86_64/kernel/pci-nommu.c
+++ b/arch/x86_64/kernel/pci-nommu.c
@@ -1,8 +1,11 @@
+/* Fallback functions when the main IOMMU code is not compiled in. This
+   code is roughly equivalent to i386. */
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/string.h>
 #include <asm/proto.h>
+#include <asm/processor.h>
 
 int iommu_merge = 0;
 EXPORT_SYMBOL(iommu_merge);
@@ -10,57 +13,80 @@ EXPORT_SYMBOL(iommu_merge);
 dma_addr_t bad_dma_address;
 EXPORT_SYMBOL(bad_dma_address);
 
+int iommu_bio_merge = 0;
+EXPORT_SYMBOL(iommu_bio_merge);
+
+int iommu_sac_force = 0;
+EXPORT_SYMBOL(iommu_sac_force);
+
 /* 
  * Dummy IO MMU functions
  */
 
-void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
-			   dma_addr_t *dma_handle)
+void *dma_alloc_coherent(struct device *hwdev, size_t size,
+			 dma_addr_t *dma_handle, unsigned gfp)
 {
 	void *ret;
-	int gfp = GFP_ATOMIC;
-	
-	if (hwdev == NULL ||
-	    end_pfn > (hwdev->dma_mask>>PAGE_SHIFT) ||  /* XXX */
-	    (u32)hwdev->dma_mask < 0xffffffff)
-		gfp |= GFP_DMA;
-	ret = (void *)__get_free_pages(gfp, get_order(size));
+	u64 mask;
+	int order = get_order(size);
 
-	if (ret != NULL) {
-		memset(ret, 0, size);
+	if (hwdev)
+		mask = hwdev->coherent_dma_mask & *hwdev->dma_mask;
+	else
+		mask = 0xffffffff;
+	for (;;) {
+		ret = (void *)__get_free_pages(gfp, order);
+		if (ret == NULL)
+			return NULL;
 		*dma_handle = virt_to_bus(ret);
+		if ((*dma_handle & ~mask) == 0)
+			break;
+		free_pages((unsigned long)ret, order);
+		if (gfp & GFP_DMA)
+			return NULL;
+		gfp |= GFP_DMA;
 	}
+
+	memset(ret, 0, size);
 	return ret;
 }
+EXPORT_SYMBOL(dma_alloc_coherent);
 
-void pci_free_consistent(struct pci_dev *hwdev, size_t size,
+void dma_free_coherent(struct device *hwdev, size_t size,
 			 void *vaddr, dma_addr_t dma_handle)
 {
 	free_pages((unsigned long)vaddr, get_order(size));
 }
+EXPORT_SYMBOL(dma_free_coherent);
 
-int pci_dma_supported(struct pci_dev *hwdev, u64 mask)
+int dma_supported(struct device *hwdev, u64 mask)
 {
         /*
          * we fall back to GFP_DMA when the mask isn't all 1s,
          * so we can't guarantee allocations that must be
          * within a tighter range than GFP_DMA..
-		 * RED-PEN this won't work for pci_map_single. Caller has to
-		 * use GFP_DMA in the first place.
+	 * RED-PEN this won't work for pci_map_single. Caller has to
+	 * use GFP_DMA in the first place.
          */
         if (mask < 0x00ffffff)
                 return 0;
 
 	return 1;
 } 
+EXPORT_SYMBOL(dma_supported);
 
-EXPORT_SYMBOL(pci_dma_supported);
+int dma_get_cache_alignment(void)
+{
+	return boot_cpu_data.x86_clflush_size;
+}
+EXPORT_SYMBOL(dma_get_cache_alignment);
 
 static int __init check_ram(void) 
 { 
 	if (end_pfn >= 0xffffffff>>PAGE_SHIFT) { 
-		printk(KERN_ERR "WARNING more than 4GB of memory but no IOMMU.\n"
-		       KERN_ERR "WARNING 32bit PCI may malfunction.\n"); 
+		printk(
+		KERN_ERR "WARNING more than 4GB of memory but IOMMU not compiled in.\n"
+		KERN_ERR "WARNING 32bit PCI may malfunction.\n");
 	} 
 	return 0;
 } 
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index f7d3cf3ca..6e835be5f 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -130,11 +130,20 @@ void cpu_idle (void)
 {
 	/* endless idle loop with no priority at all */
 	while (1) {
-		void (*idle)(void) = pm_idle;
-		if (!idle)
-			idle = default_idle;
-		while (!need_resched())
+		while (!need_resched()) {
+			void (*idle)(void);
+			/*
+			 * Mark this as an RCU critical section so that
+			 * synchronize_kernel() in the unload path waits
+			 * for our completion.
+			 */
+			rcu_read_lock();
+			idle = pm_idle;
+			if (!idle)
+				idle = default_idle;
 			idle();
+			rcu_read_unlock();
+		}
 		schedule();
 	}
 }
@@ -168,9 +177,7 @@ void __init select_idle_routine(const struct cpuinfo_x86 *c)
 	if (cpu_has(c, X86_FEATURE_MWAIT)) {
 		/*
 		 * Skip, if setup has overridden idle.
-		 * Also, take care of system with asymmetric CPUs.
-		 * Use, mwait_idle only if all cpus support it.
-		 * If not, we fallback to default_idle()
+		 * One CPU supports mwait => All CPUs supports mwait
 		 */
 		if (!pm_idle) {
 			if (!printed) {
@@ -179,10 +186,7 @@ void __init select_idle_routine(const struct cpuinfo_x86 *c)
 			}
 			pm_idle = mwait_idle;
 		}
-		return;
 	}
-	pm_idle = default_idle;
-	return;
 }
 
 static int __init idle_setup (char *str)
@@ -255,11 +259,17 @@ void show_regs(struct pt_regs *regs)
 void exit_thread(void)
 {
 	struct task_struct *me = current;
+	struct thread_struct *t = &me->thread;
 	if (me->thread.io_bitmap_ptr) { 
-		struct tss_struct *tss = init_tss + get_cpu();
-		kfree(me->thread.io_bitmap_ptr); 
-		me->thread.io_bitmap_ptr = NULL;
-		tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
+		struct tss_struct *tss = &per_cpu(init_tss, get_cpu());
+
+		kfree(t->io_bitmap_ptr);
+		t->io_bitmap_ptr = NULL;
+		/*
+		 * Careful, clear this in the TSS too:
+		 */
+		memset(tss->io_bitmap, 0xff, t->io_bitmap_max);
+		t->io_bitmap_max = 0;
 		put_cpu();
 	}
 }
@@ -367,8 +377,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp,
 
 	if (unlikely(me->thread.io_bitmap_ptr != NULL)) { 
 		p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
-		if (!p->thread.io_bitmap_ptr) 
+		if (!p->thread.io_bitmap_ptr) {
+			p->thread.io_bitmap_max = 0;
 			return -ENOMEM;
+		}
 		memcpy(p->thread.io_bitmap_ptr, me->thread.io_bitmap_ptr, IO_BITMAP_BYTES);
 	} 
 
@@ -387,8 +399,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp,
 	}
 	err = 0;
 out:
-	if (err && p->thread.io_bitmap_ptr)
+	if (err && p->thread.io_bitmap_ptr) {
 		kfree(p->thread.io_bitmap_ptr);
+		p->thread.io_bitmap_max = 0;
+	}
 	return err;
 }
 
@@ -409,7 +423,7 @@ struct task_struct *__switch_to(struct task_struct *prev_p, struct task_struct *
 	struct thread_struct *prev = &prev_p->thread,
 				 *next = &next_p->thread;
 	int cpu = smp_processor_id();  
-	struct tss_struct *tss = init_tss + cpu;
+	struct tss_struct *tss = &per_cpu(init_tss, cpu);
 
 	unlazy_fpu(prev_p);
 
@@ -495,22 +509,18 @@ struct task_struct *__switch_to(struct task_struct *prev_p, struct task_struct *
 	 * Handle the IO bitmap 
 	 */ 
 	if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) {
-		if (next->io_bitmap_ptr) {
+		if (next->io_bitmap_ptr)
 			/*
-			 * 2 cachelines copy ... not good, but not that
-			 * bad either. Anyone got something better?
-			 * This only affects processes which use ioperm().
-			 */
-			memcpy(tss->io_bitmap, next->io_bitmap_ptr, IO_BITMAP_BYTES);
-			tss->io_bitmap_base = IO_BITMAP_OFFSET;
-		} else {
+			 * Copy the relevant range of the IO bitmap.
+			 * Normally this is 128 bytes or less:
+ 			 */
+			memcpy(tss->io_bitmap, next->io_bitmap_ptr,
+				max(prev->io_bitmap_max, next->io_bitmap_max));
+		else {
 			/*
-			 * a bitmap offset pointing outside of the TSS limit
-			 * causes a nicely controllable SIGSEGV if a process
-			 * tries to use a port IO instruction. The first
-			 * sys_ioperm() call sets up the bitmap properly.
+			 * Clear any possible leftover bits:
 			 */
-			tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
+			memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
 		}
 	}
 
@@ -546,17 +556,16 @@ void set_personality_64bit(void)
 	clear_thread_flag(TIF_IA32); 
 }
 
-asmlinkage long sys_fork(struct pt_regs regs)
+asmlinkage long sys_fork(struct pt_regs *regs)
 {
-	return do_fork(SIGCHLD, regs.rsp, &regs, 0, NULL, NULL);
+	return do_fork(SIGCHLD, regs->rsp, regs, 0, NULL, NULL);
 }
 
-asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, void __user *parent_tid, void __user *child_tid, struct pt_regs regs)
+asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, void __user *parent_tid, void __user *child_tid, struct pt_regs *regs)
 {
 	if (!newsp)
-		newsp = regs.rsp;
-	return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0, 
-		    parent_tid, child_tid);
+		newsp = regs->rsp;
+	return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
 }
 
 /*
@@ -569,9 +578,9 @@ asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, void _
  * do not have enough call-clobbered registers to hold all
  * the information you need.
  */
-asmlinkage long sys_vfork(struct pt_regs regs)
+asmlinkage long sys_vfork(struct pt_regs *regs)
 {
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.rsp, &regs, 0, 
+	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->rsp, regs, 0,
 		    NULL, NULL);
 }
 
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index d07a45b01..672637d53 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -88,6 +88,7 @@ void ptrace_disable(struct task_struct *child)
 { 
 	long tmp;
 
+	clear_tsk_thread_flag(child, TIF_SINGLESTEP);
 	tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
 	put_stack_long(child, EFL_OFFSET, tmp);
 }
@@ -346,6 +347,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
 			set_tsk_thread_flag(child,TIF_SYSCALL_TRACE);
 		else
 			clear_tsk_thread_flag(child,TIF_SYSCALL_TRACE);
+		clear_tsk_thread_flag(child, TIF_SINGLESTEP);
 		child->exit_code = data;
 	/* make sure the single step bit is not set. */
 		tmp = get_stack_long(child, EFL_OFFSET);
@@ -397,6 +399,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
 		ret = 0;
 		if (child->state == TASK_ZOMBIE)	/* already dead */
 			break;
+		clear_tsk_thread_flag(child, TIF_SINGLESTEP);
 		child->exit_code = SIGKILL;
 		/* make sure the single step bit is not set. */
 		tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
@@ -418,6 +421,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
 		}
 		tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG;
 		put_stack_long(child, EFL_OFFSET, tmp);
+		set_tsk_thread_flag(child, TIF_SINGLESTEP);
 		child->exit_code = data;
 		/* give it a chance to run. */
 		wake_up_process(child);
@@ -431,30 +435,32 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
 		break;
 
 	case PTRACE_GETREGS: { /* Get all gp regs from the child. */
-	  	if (!access_ok(VERIFY_WRITE, (unsigned __user *)data, FRAME_SIZE)) {
+	  	if (!access_ok(VERIFY_WRITE, (unsigned __user *)data,
+			       sizeof(struct user_regs_struct))) {
 			ret = -EIO;
 			break;
 		}
+		ret = 0;
 		for (ui = 0; ui < sizeof(struct user_regs_struct); ui += sizeof(long)) {
-			__put_user(getreg(child, ui),(unsigned long __user *) data);
+			ret |= __put_user(getreg(child, ui),(unsigned long __user *) data);
 			data += sizeof(long);
 		}
-		ret = 0;
 		break;
 	}
 
 	case PTRACE_SETREGS: { /* Set all gp regs in the child. */
 		unsigned long tmp;
-	  	if (!access_ok(VERIFY_READ, (unsigned __user *)data, FRAME_SIZE)) {
+	  	if (!access_ok(VERIFY_READ, (unsigned __user *)data,
+			       sizeof(struct user_regs_struct))) {
 			ret = -EIO;
 			break;
 		}
+		ret = 0;
 		for (ui = 0; ui < sizeof(struct user_regs_struct); ui += sizeof(long)) {
-			__get_user(tmp, (unsigned long __user *) data);
+			ret |= __get_user(tmp, (unsigned long __user *) data);
 			putreg(child, ui, tmp);
 			data += sizeof(long);
 		}
-		ret = 0;
 		break;
 	}
 
@@ -530,7 +536,8 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs)
 	if (unlikely(current->audit_context))
 		audit_syscall_exit(current, regs->rax);
 
-	if (test_thread_flag(TIF_SYSCALL_TRACE)
+	if ((test_thread_flag(TIF_SYSCALL_TRACE)
+	     || test_thread_flag(TIF_SINGLESTEP))
 	    && (current->ptrace & PT_PTRACED))
 		syscall_trace(regs);
 }
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index c0d3c8dfa..108cf17c4 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -71,7 +71,7 @@ EXPORT_SYMBOL(acpi_disabled);
 #ifdef	CONFIG_ACPI_BOOT
 extern int __initdata acpi_ht;
 extern acpi_interrupt_flags	acpi_sci_flags;
-/* int __initdata acpi_force = 0; */
+int __initdata acpi_force = 0;
 #endif
 
 /* For PCI or other memory-mapped resources */
@@ -79,8 +79,10 @@ unsigned long pci_mem_start = 0x10000000;
 
 unsigned long saved_video_mode;
 
+#ifdef CONFIG_SWIOTLB
 int swiotlb;
 EXPORT_SYMBOL(swiotlb);
+#endif
 
 /*
  * Setup options
@@ -105,7 +107,8 @@ char command_line[COMMAND_LINE_SIZE];
 struct resource standard_io_resources[] = {
 	{ "dma1", 0x00, 0x1f, IORESOURCE_BUSY | IORESOURCE_IO },
 	{ "pic1", 0x20, 0x21, IORESOURCE_BUSY | IORESOURCE_IO },
-	{ "timer", 0x40, 0x5f, IORESOURCE_BUSY | IORESOURCE_IO },
+	{ "timer0", 0x40, 0x43, IORESOURCE_BUSY | IORESOURCE_IO },
+	{ "timer1", 0x50, 0x53, IORESOURCE_BUSY | IORESOURCE_IO },
 	{ "keyboard", 0x60, 0x6f, IORESOURCE_BUSY | IORESOURCE_IO },
 	{ "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY | IORESOURCE_IO },
 	{ "pic2", 0xa0, 0xa1, IORESOURCE_BUSY | IORESOURCE_IO },
@@ -248,14 +251,14 @@ static __init void parse_cmdline_early (char ** cmdline_p)
 
 		if (!memcmp(from, "acpi=force", 10)) { 
 			/* add later when we do DMI horrors: */
-			/* acpi_force = 1; */	
+			acpi_force = 1;
 			acpi_disabled = 0;
 		}
 
 		/* acpi=ht just means: do ACPI MADT parsing 
 		   at bootup, but don't enable the full ACPI interpreter */
 		if (!memcmp(from, "acpi=ht", 7)) { 
-			/* if (!acpi_force) */
+			if (!acpi_force)
 				disable_acpi();
 			acpi_ht = 1; 
 		}
@@ -423,6 +426,20 @@ static inline void copy_edd(void)
 }
 #endif
 
+#define EBDA_ADDR_POINTER 0x40E
+static void __init reserve_ebda_region(void)
+{
+	unsigned int addr;
+	/** 
+	 * there is a real-mode segmented pointer pointing to the 
+	 * 4K EBDA area at 0x40E
+	 */
+	addr = *(unsigned short *)phys_to_virt(EBDA_ADDR_POINTER);
+	addr <<= 4;
+	if (addr)
+		reserve_bootmem_generic(addr, PAGE_SIZE);
+}
+
 void __init setup_arch(char **cmdline_p)
 {
 	unsigned long low_mem_size;
@@ -487,6 +504,9 @@ void __init setup_arch(char **cmdline_p)
 	 */
 	reserve_bootmem_generic(0, PAGE_SIZE);
 
+	/* reserve ebda region */
+	reserve_ebda_region();
+
 #ifdef CONFIG_SMP
 	/*
 	 * But first pinch a few for the stack/trampoline stuff
@@ -662,6 +682,26 @@ static int __init init_amd(struct cpuinfo_x86 *c)
 		} 
 	} 
 	display_cacheinfo(c);
+
+	if (c->cpuid_level >= 0x80000008) {
+		c->x86_num_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
+		if (c->x86_num_cores & (c->x86_num_cores - 1))
+			c->x86_num_cores = 1;
+
+#ifdef CONFIG_NUMA
+		/* On a dual core setup the lower bits of apic id
+		   distingush the cores. Fix up the CPU<->node mappings
+		   here based on that.
+		   Assumes number of cores is a power of two. */
+		if (c->x86_num_cores > 1) {
+			int cpu = c->x86_apicid;
+			cpu_to_node[cpu] = cpu >> hweight32(c->x86_num_cores - 1);
+			printk(KERN_INFO "CPU %d -> Node %d\n",
+			       cpu, cpu_to_node[cpu]);
+		}
+#endif
+	}
+
 	return r;
 }
 
@@ -705,7 +745,7 @@ static void __init detect_ht(struct cpuinfo_x86 *c)
 		}
 		if (index_lsb != index_msb )
 			index_msb++;
-		initial_apic_id = ebx >> 24 & 0xff;
+		initial_apic_id = hard_smp_processor_id();
 		phys_proc_id[cpu] = initial_apic_id >> index_msb;
 		
 		printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
@@ -748,6 +788,7 @@ static struct _cache_table cache_table[] __initdata =
 	{ 0x43, LVL_2,      512 },
 	{ 0x44, LVL_2,      1024 },
 	{ 0x45, LVL_2,      2048 },
+	{ 0x60, LVL_1_DATA, 16 },
 	{ 0x66, LVL_1_DATA, 8 },
 	{ 0x67, LVL_1_DATA, 16 },
 	{ 0x68, LVL_1_DATA, 32 },
@@ -885,6 +926,8 @@ void __init early_identify_cpu(struct cpuinfo_x86 *c)
 	c->x86_model_id[0] = '\0';  /* Unset */
 	c->x86_clflush_size = 64;
 	c->x86_cache_alignment = c->x86_clflush_size;
+	c->x86_num_cores = 1;
+	c->x86_apicid = c == &boot_cpu_data ? 0 : c - cpu_data;
 	memset(&c->x86_capability, 0, sizeof c->x86_capability);
 
 	/* Get vendor name */
@@ -912,6 +955,7 @@ void __init early_identify_cpu(struct cpuinfo_x86 *c)
 		} 
 		if (c->x86_capability[0] & (1<<19)) 
 			c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
+		c->x86_apicid = misc >> 24;
 	} else {
 		/* Have CPUID level 0 only - unheard of */
 		c->x86 = 4;
@@ -931,8 +975,10 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
 	/* AMD-defined flags: level 0x80000001 */
 	xlvl = cpuid_eax(0x80000000);
 	if ( (xlvl & 0xffff0000) == 0x80000000 ) {
-		if ( xlvl >= 0x80000001 )
+		if ( xlvl >= 0x80000001 ) {
 			c->x86_capability[1] = cpuid_edx(0x80000001);
+			c->x86_capability[5] = cpuid_ecx(0x80000001);
+		}
 		if ( xlvl >= 0x80000004 )
 			get_model_name(c); /* Default name */
 	}
@@ -1042,8 +1088,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
 		/* Intel-defined (#2) */
-		"pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "tm2",
-		"est", NULL, "cid", NULL, NULL, "cmpxchg16b", NULL, NULL,
+		"pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "est",
+		"tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	};
@@ -1132,6 +1178,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 			}
 	}
 
+	if (c->x86_num_cores > 1)
+		seq_printf(m, "cpu cores\t: %d\n", c->x86_num_cores);
+
 	seq_printf(m, "\n\n"); 
 
 	return 0;
diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
index 9d3137a55..b83680afe 100644
--- a/arch/x86_64/kernel/setup64.c
+++ b/arch/x86_64/kernel/setup64.c
@@ -60,12 +60,12 @@ noforce (default) Don't enable by default for heap/stack/data,
 */ 
 static int __init nonx_setup(char *str)
 {
-	if (!strncmp(str, "on",3)) { 
+	if (!strcmp(str, "on")) {
                 __supported_pte_mask |= _PAGE_NX; 
  		do_not_nx = 0; 
  		vm_data_default_flags &= ~VM_EXEC; 
  		vm_stack_flags &= ~VM_EXEC;  
-	} else if (!strncmp(str, "noforce",7) || !strncmp(str,"off",3)) { 
+	} else if (!strcmp(str, "noforce") || !strcmp(str, "off")) {
 		do_not_nx = (str[0] == 'o');
 		if (do_not_nx)
 			__supported_pte_mask &= ~_PAGE_NX; 
@@ -91,26 +91,28 @@ Valid options:
    compat    (default) Imply PROT_EXEC for PROT_READ
 
 */
- static int __init nonx32_setup(char *str)
+ static int __init nonx32_setup(char *s)
  {
-	char *s;
-	while ((s = strsep(&str, ",")) != NULL) { 
-		if (!strcmp(s, "all") || !strcmp(s,"on")) {
+	 while (*s) {
+		if (!strncmp(s, "all", 3) || !strncmp(s,"on",2)) {
 			vm_data_default_flags32 &= ~VM_EXEC; 
 			vm_stack_flags32 &= ~VM_EXEC;  
-		} else if (!strcmp(s, "off")) { 
+		} else if (!strncmp(s, "off",3)) {
 			vm_data_default_flags32 |= VM_EXEC; 
 			vm_stack_flags32 |= VM_EXEC;  
-		} else if (!strcmp(s, "stack")) { 
+		} else if (!strncmp(s, "stack", 5)) {
 			vm_data_default_flags32 |= VM_EXEC; 
 			vm_stack_flags32 &= ~VM_EXEC;  		
-		} else if (!strcmp(s, "force")) { 
+		} else if (!strncmp(s, "force",5)) {
 			vm_force_exec32 = 0; 
-		} else if (!strcmp(s, "compat")) { 
+		} else if (!strncmp(s, "compat",5)) {
 			vm_force_exec32 = PROT_EXEC;
 		} 
-	} 
- 	return 1;
+		s += strcspn(s, ",");
+		if (*s == ',')
+			++s;
+	 }
+	 return 1;
 } 
 
 __setup("noexec32=", nonx32_setup); 
@@ -193,7 +195,8 @@ void pda_init(int cpu)
 char boot_exception_stacks[N_EXCEPTION_STACKS * EXCEPTION_STKSZ] 
 __attribute__((section(".bss.page_aligned")));
 
-void __init syscall_init(void)
+/* May not be marked __init: used by software suspend */
+void syscall_init(void)
 {
 	/* 
 	 * LSTAR and STAR live in a bit strange symbiosis.
@@ -235,10 +238,11 @@ void __init cpu_init (void)
 #else
 	int cpu = smp_processor_id();
 #endif
-	struct tss_struct * t = &init_tss[cpu];
+	struct tss_struct *t = &per_cpu(init_tss, cpu);
 	unsigned long v; 
 	char *estacks = NULL; 
 	struct task_struct *me;
+	int i;
 
 	/* CPU 0 is initialised in head64.c */
 	if (cpu != 0) {
@@ -302,12 +306,13 @@ void __init cpu_init (void)
 		t->ist[v] = (unsigned long)estacks;
 	}
 
-	t->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
+	t->io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
 	/*
-	 * This is required because the CPU will access up to
+	 * <= is required because the CPU will access up to
 	 * 8 bits beyond the end of the IO permission bitmap.
 	 */
-	t->io_bitmap[IO_BITMAP_LONGS] = ~0UL;
+	for (i = 0; i <= IO_BITMAP_LONGS; i++)
+		t->io_bitmap[i] = ~0UL;
 
 	atomic_inc(&init_mm.mm_count);
 	me->active_mm = &init_mm;
diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c
index f6eb0e337..99bcd7275 100644
--- a/arch/x86_64/kernel/signal.c
+++ b/arch/x86_64/kernel/signal.c
@@ -40,7 +40,7 @@ void ia32_setup_frame(int sig, struct k_sigaction *ka,
             sigset_t *set, struct pt_regs * regs); 
 
 asmlinkage long
-sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs regs)
+sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
 {
 	sigset_t saveset, newset;
 
@@ -59,21 +59,22 @@ sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs re
 	spin_unlock_irq(&current->sighand->siglock);
 #ifdef DEBUG_SIG
 	printk("rt_sigsuspend savset(%lx) newset(%lx) regs(%p) rip(%lx)\n",
-		saveset, newset, &regs, regs.rip);
+		saveset, newset, regs, regs->rip);
 #endif 
-	regs.rax = -EINTR;
+	regs->rax = -EINTR;
 	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();
-		if (do_signal(&regs, &saveset))
+		if (do_signal(regs, &saveset))
 			return -EINTR;
 	}
 }
 
 asmlinkage long
-sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, struct pt_regs regs)
+sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
+		struct pt_regs *regs)
 {
-	return do_sigaltstack(uss, uoss, regs.rsp);
+	return do_sigaltstack(uss, uoss, regs->rsp);
 }
 
 
@@ -134,13 +135,13 @@ badframe:
 	return 1;
 }
 
-asmlinkage long sys_rt_sigreturn(struct pt_regs regs)
+asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame;
 	sigset_t set;
 	long eax;
 
-	frame = (struct rt_sigframe __user *)(regs.rsp - 8);
+	frame = (struct rt_sigframe __user *)(regs->rsp - 8);
 	if (verify_area(VERIFY_READ, frame, sizeof(*frame))) { 
 		goto badframe;
 	} 
@@ -154,7 +155,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs regs)
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 	
-	if (restore_sigcontext(&regs, &frame->uc.uc_mcontext, &eax)) { 
+	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &eax)) {
 		goto badframe;
 	} 
 
@@ -162,13 +163,13 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs regs)
 	printk("%d sigreturn rip:%lx rsp:%lx frame:%p rax:%lx\n",current->pid,regs.rip,regs.rsp,frame,eax);
 #endif
 
-	if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs.rsp) == -EFAULT)
+	if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->rsp) == -EFAULT)
 		goto badframe;
 
 	return eax;
 
 badframe:
-	signal_fault(&regs,frame,"sigreturn");
+	signal_fault(regs,frame,"sigreturn");
 	return 0;
 }	
 
@@ -180,6 +181,7 @@ static inline int
 setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned long mask, struct task_struct *me)
 {
 	int err = 0;
+	unsigned long eflags;
 
 	err |= __put_user(0, &sc->gs);
 	err |= __put_user(0, &sc->fs);
@@ -203,7 +205,11 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned lo
 	err |= __put_user(me->thread.trap_no, &sc->trapno);
 	err |= __put_user(me->thread.error_code, &sc->err);
 	err |= __put_user(regs->rip, &sc->rip);
-	err |= __put_user(regs->eflags, &sc->eflags);
+	eflags = regs->eflags;
+	if (current->ptrace & PT_PTRACED) {
+		eflags &= ~TF_MASK;
+	}
+	err |= __put_user(eflags, &sc->eflags);
 	err |= __put_user(mask, &sc->oldmask);
 	err |= __put_user(me->thread.cr2, &sc->cr2);
 
@@ -287,7 +293,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	if (ka->sa.sa_flags & SA_RESTORER) {
 		err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
 	} else {
-		printk("%s forgot to set SA_RESTORER for signal %d.\n", me->comm, sig); 
+		/* could use a vstub here */
 		goto give_sigsegv; 
 	}
 
@@ -318,7 +324,13 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	regs->rsp = (unsigned long)frame;
 
 	set_fs(USER_DS);
-	regs->eflags &= ~TF_MASK;
+	if (regs->eflags & TF_MASK) {
+		if (current->ptrace & PT_PTRACED) {
+			ptrace_notify(SIGTRAP);
+		} else {
+			regs->eflags &= ~TF_MASK;
+		}
+	}
 
 #ifdef DEBUG_SIG
 	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
@@ -328,9 +340,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	return;
 
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	signal_fault(regs,frame,"signal deliver");
+	force_sigsegv(sig, current);
 }
 
 /*
@@ -338,11 +348,9 @@ give_sigsegv:
  */	
 
 static void
-handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
-	struct pt_regs * regs)
+handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
+		sigset_t *oldset, struct pt_regs *regs)
 {
-	struct k_sigaction *ka = &current->sighand->action[sig-1];
-
 #ifdef DEBUG_SIG
 	printk("handle_signal pid:%d sig:%lu rip:%lx rsp:%lx regs=%p\n", current->pid, sig, 
 		regs->rip, regs->rsp, regs);
@@ -379,9 +387,6 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
 #endif
 	setup_rt_frame(sig, ka, info, oldset, regs);
 
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
-
 	if (!(ka->sa.sa_flags & SA_NODEFER)) {
 		spin_lock_irq(&current->sighand->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -398,6 +403,7 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
  */
 int do_signal(struct pt_regs *regs, sigset_t *oldset)
 {
+	struct k_sigaction ka;
 	siginfo_t info;
 	int signr;
 
@@ -419,7 +425,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
 	if (!oldset)
 		oldset = &current->blocked;
 
-	signr = get_signal_to_deliver(&info, regs, NULL);
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
 		/* Reenable any watchpoints before delivering the
 		 * signal to user space. The processor register will
@@ -430,7 +436,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
 			asm volatile("movq %0,%%db7"	: : "r" (current->thread.debugreg7));
 
 		/* Whee!  Actually deliver the signal.  */
-		handle_signal(signr, &info, oldset, regs);
+		handle_signal(signr, &info, &ka, oldset, regs);
 		return 1;
 	}
 
diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c
index 409460ebc..269ef092f 100644
--- a/arch/x86_64/kernel/smp.c
+++ b/arch/x86_64/kernel/smp.c
@@ -382,30 +382,14 @@ static struct call_data_struct * call_data;
  * this function sends a 'generic call function' IPI to all other CPUs
  * in the system.
  */
-
-int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
-			int wait)
-/*
- * [SUMMARY] Run a function on all other CPUs.
- * <func> The function to run. This must be fast and non-blocking.
- * <info> An arbitrary pointer to pass to the function.
- * <nonatomic> currently unused.
- * <wait> If true, wait (atomically) until function has completed on other CPUs.
- * [RETURNS] 0 on success, else a negative status code. Does not return until
- * remote CPUs are nearly ready to execute <<func>> or are or have executed.
- *
- * You must not call this function with disabled interrupts or from a
- * hardware interrupt handler or from a bottom half handler.
- */
+static void __smp_call_function (void (*func) (void *info), void *info,
+				int nonatomic, int wait)
 {
 	struct call_data_struct data;
 	int cpus = num_online_cpus()-1;
 
 	if (!cpus)
-		return 0;
-
-	/* Can deadlock when called with interrupts disabled */
-	WARN_ON(irqs_disabled());
+		return;
 
 	data.func = func;
 	data.info = info;
@@ -414,7 +398,6 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
 	if (wait)
 		atomic_set(&data.finished, 0);
 
-	spin_lock(&call_lock);
 	call_data = &data;
 	wmb();
 	/* Send a message to all other CPUs and wait for them to respond */
@@ -427,8 +410,29 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
 	if (wait)
 		while (atomic_read(&data.finished) != cpus)
 			barrier();
-	spin_unlock(&call_lock);
+}
 
+/*
+ * smp_call_function - run a function on all other CPUs.
+ * @func: The function to run. This must be fast and non-blocking.
+ * @info: An arbitrary pointer to pass to the function.
+ * @nonatomic: currently unused.
+ * @wait: If true, wait (atomically) until function has completed on other
+ *        CPUs.
+ *
+ * Returns 0 on success, else a negative status code. Does not return until
+ * remote CPUs are nearly ready to execute func or are or have executed.
+ *
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler or from a bottom half handler.
+ * Actually there are a few legal cases, like panic.
+ */
+int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
+			int wait)
+{
+	spin_lock(&call_lock);
+	__smp_call_function(func,info,nonatomic,wait);
+	spin_unlock(&call_lock);
 	return 0;
 }
 
@@ -452,7 +456,16 @@ static void smp_really_stop_cpu(void *dummy)
 
 void smp_send_stop(void)
 {
-	smp_call_function(smp_really_stop_cpu, NULL, 1, 0);
+	int nolock = 0;
+	/* Don't deadlock on the call lock in panic */
+	if (!spin_trylock(&call_lock)) {
+		udelay(100);
+		/* ignore locking because we have paniced anyways */
+		nolock = 1;
+	}
+	__smp_call_function(smp_really_stop_cpu, NULL, 1, 0);
+	if (!nolock)
+		spin_unlock(&call_lock);
 	smp_stop_cpu();
 }
 
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index 29f2578bf..dc0f40fea 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -43,6 +43,7 @@
 #include <linux/irq.h>
 #include <linux/bootmem.h>
 #include <linux/thread_info.h>
+#include <linux/module.h>
 
 #include <linux/delay.h>
 #include <linux/mc146818rtc.h>
@@ -62,6 +63,7 @@ cpumask_t cpu_online_map;
 
 /* which logical CPU number maps to which CPU (physical APIC ID) */
 volatile char x86_cpu_to_apicid[NR_CPUS];
+EXPORT_SYMBOL(x86_cpu_to_apicid);
 
 static cpumask_t cpu_callin_map;
 cpumask_t cpu_callout_map;
@@ -390,16 +392,6 @@ void __init start_secondary(void)
 extern volatile unsigned long init_rsp; 
 extern void (*initial_code)(void);
 
-static struct task_struct * __init fork_by_hand(void)
-{
-	struct pt_regs regs;
-	/*
-	 * don't care about the eip and regs settings since
-	 * we'll never reschedule the forked task.
-	 */
-	return copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
-}
-
 #if APIC_DEBUG
 static inline void inquire_remote_apic(int apicid)
 {
@@ -573,26 +565,17 @@ static void __init do_boot_cpu (int apicid)
 	 * We can't use kernel_thread since we must avoid to
 	 * reschedule the child.
 	 */
-	idle = fork_by_hand();
+	idle = fork_idle(cpu);
 	if (IS_ERR(idle))
 		panic("failed fork for CPU %d", cpu);
-	wake_up_forked_process(idle);	
 	x86_cpu_to_apicid[cpu] = apicid;
 
-	/*
-	 * We remove it from the pidhash and the runqueue
-	 * once we got the process:
-	 */
-	init_idle(idle,cpu);
-
-	unhash_process(idle);
-
 	cpu_pda[cpu].pcurrent = idle;
 
 	start_rip = setup_trampoline();
 
 	init_rsp = idle->thread.rsp; 
-	init_tss[cpu].rsp0 = init_rsp;
+	per_cpu(init_tss,cpu).rsp0 = init_rsp;
 	initial_code = start_secondary;
 	clear_ti_thread_flag(idle->thread_info, TIF_FORK);
 
@@ -967,6 +950,9 @@ int __devinit __cpu_up(unsigned int cpu)
 
 void __init smp_cpus_done(unsigned int max_cpus)
 {
+#ifdef CONFIG_X86_IO_APIC
+	setup_ioapic_dest();
+#endif
 	zap_low_mappings();
 }
 
diff --git a/arch/x86_64/kernel/suspend.c b/arch/x86_64/kernel/suspend.c
index 751982df5..ebaa1e37d 100644
--- a/arch/x86_64/kernel/suspend.c
+++ b/arch/x86_64/kernel/suspend.c
@@ -129,7 +129,7 @@ void restore_processor_state(void)
 void fix_processor_context(void)
 {
 	int cpu = smp_processor_id();
-	struct tss_struct * t = init_tss + cpu;
+	struct tss_struct *t = &per_cpu(init_tss, cpu);
 
 	set_tss_desc(cpu,t);	/* This just modifies memory; should not be neccessary. But... This is neccessary, because 386 hardware has concept of busy TSS or some similar stupidity. */
 
diff --git a/arch/x86_64/kernel/suspend_asm.S b/arch/x86_64/kernel/suspend_asm.S
index 99a1adf86..8a3999810 100644
--- a/arch/x86_64/kernel/suspend_asm.S
+++ b/arch/x86_64/kernel/suspend_asm.S
@@ -1,22 +1,18 @@
-/* originally gcc generated, but now changed. don't overwrite. */
+/* Originally gcc generated, modified by hand
+ *
+ * This may not use any stack, nor any variable that is not "NoSave":
+ *
+ * Its rewriting one kernel image with another. What is stack in "old"
+ * image could very well be data page in "new" image, and overwriting
+ * your own stack under you is bad idea.
+ */
 	
 	.text
 #include <linux/linkage.h>
 #include <asm/segment.h>
 #include <asm/page.h>
 
-/* Input:
- * rdi	resume flag 
- */	
-			
-ENTRY(do_magic)
-.LFB5:
-	subq	$8, %rsp
-.LCFI2:
-	testl	%edi, %edi
-	jne	.L90
-	call	do_magic_suspend_1
-	call	save_processor_state
+ENTRY(swsusp_arch_suspend)
 
 	movq %rsp, saved_context_esp(%rip)
 	movq %rax, saved_context_eax(%rip)
@@ -36,36 +32,35 @@ ENTRY(do_magic)
 	movq %r15, saved_context_r15(%rip)
 	pushfq ; popq saved_context_eflags(%rip)
 
-	addq	$8, %rsp
-	jmp	do_magic_suspend_2
-.L90:
+	call swsusp_save
+	ret
+
+ENTRY(swsusp_arch_resume)
 	/* set up cr3 */	
 	leaq	init_level4_pgt(%rip),%rax
 	subq	$__START_KERNEL_map,%rax
-	movq %rax,%cr3
+	movq	%rax,%cr3
 
 	movq	mmu_cr4_features(%rip), %rax
 	movq	%rax, %rdx
-	
 	andq	$~(1<<7), %rdx	# PGE
-	movq %rdx, %cr4;  # turn off PGE     
-	movq %cr3, %rcx;  # flush TLB        
-	movq %rcx, %cr3;                     
-	movq %rax, %cr4;  # turn PGE back on 
+	movq	%rdx, %cr4;  # turn off PGE
+	movq	%cr3, %rcx;  # flush TLB
+	movq	%rcx, %cr3;
+	movq	%rax, %cr4;  # turn PGE back on
 
-	call	do_magic_resume_1
 	movl	nr_copy_pages(%rip), %eax
 	xorl	%ecx, %ecx
-	movq	$0, loop(%rip)
+	movq	$0, %r10
 	testl	%eax, %eax
-	je	.L108
+	jz	done
 .L105:
 	xorl	%esi, %esi
-	movq	$0, loop2(%rip)
+	movq	$0, %r11
 	jmp	.L104
 	.p2align 4,,7
-.L111:
-	movq	loop(%rip), %rcx
+copy_one_page:
+	movq	%r10, %rcx
 .L104:
 	movq	pagedir_nosave(%rip), %rdx
 	movq	%rcx, %rax
@@ -75,27 +70,26 @@ ENTRY(do_magic)
 	movzbl	(%rsi,%rax), %eax
 	movb	%al, (%rsi,%rcx)
 
-	movq %cr3, %rax;  # flush TLB 
-	movq %rax, %cr3;              
+	movq	%cr3, %rax;  # flush TLB
+	movq	%rax, %cr3;
 
-	movq	loop2(%rip), %rax
+	movq	%r11, %rax
 	incq	%rax
 	cmpq	$4095, %rax
 	movq	%rax, %rsi
-	movq	%rax, loop2(%rip)
-	jbe	.L111
-	movq	loop(%rip), %rax
+	movq	%rax, %r11
+	jbe	copy_one_page
+	movq	%r10, %rax
 	incq	%rax
 	movq	%rax, %rcx
-	movq	%rax, loop(%rip)
+	movq	%rax, %r10
 	mov	nr_copy_pages(%rip), %eax
 	cmpq	%rax, %rcx
 	jb	.L105
-.L108:
-	.align 4
+done:
 	movl	$24, %eax
+	movl	%eax, %ds
 
-	movl %eax, %ds
 	movq saved_context_esp(%rip), %rsp
 	movq saved_context_ebp(%rip), %rbp
 	movq saved_context_eax(%rip), %rax
@@ -113,13 +107,5 @@ ENTRY(do_magic)
 	movq saved_context_r14(%rip), %r14
 	movq saved_context_r15(%rip), %r15
 	pushq saved_context_eflags(%rip) ; popfq
-	call	restore_processor_state
-	addq	$8, %rsp
-	jmp	do_magic_resume_2
-
-	.section .data.nosave
-loop:
-	.quad 0
-loop2:	
-	.quad 0		
-	.previous
+	call	swsusp_restore
+	ret
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 10c511f50..ee941842d 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -11,7 +11,6 @@
  *  Copyright (c) 2002  Vojtech Pavlik
  *  Copyright (c) 2003  Andi Kleen
  *  RTC support code taken from arch/i386/kernel/timers/time_hpet.c
- *
  */
 
 #include <linux/kernel.h>
@@ -33,6 +32,7 @@
 #include <asm/timex.h>
 #include <asm/proto.h>
 #include <asm/hpet.h>
+#include <asm/sections.h>
 #include <linux/cpufreq.h>
 #ifdef CONFIG_X86_LOCAL_APIC
 #include <asm/apic.h>
@@ -42,6 +42,10 @@ u64 jiffies_64 = INITIAL_JIFFIES;
 
 EXPORT_SYMBOL(jiffies_64);
 
+#ifdef CONFIG_CPU_FREQ
+static void cpufreq_delayed_get(void);
+#endif
+
 extern int using_apic_timer;
 
 spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
@@ -82,7 +86,7 @@ static inline void rdtscll_sync(unsigned long *tsc)
  * timer interrupt has happened already, but vxtime.trigger wasn't updated yet.
  * This is not a problem, because jiffies hasn't updated either. They are bound
  * together by xtime_lock.
-         */
+ */
 
 static inline unsigned int do_gettimeoffset_tsc(void)
 {
@@ -119,7 +123,7 @@ void do_gettimeofday(struct timeval *tv)
 		usec = xtime.tv_nsec / 1000;
 
 		/* i386 does some correction here to keep the clock 
-		   monotonus even when ntpd is fixing drift.
+		   monotonous even when ntpd is fixing drift.
 		   But they didn't work for me, there is a non monotonic
 		   clock anyways with ntp.
 		   I dropped all corrections now until a real solution can
@@ -176,6 +180,28 @@ int do_settimeofday(struct timespec *tv)
 
 EXPORT_SYMBOL(do_settimeofday);
 
+unsigned long profile_pc(struct pt_regs *regs)
+{
+	unsigned long pc = instruction_pointer(regs);
+
+	/* Assume the lock function has either no stack frame or only a single word.
+	   This checks if the address on the stack looks like a kernel text address.
+	   There is a small window for false hits, but in that case the tick
+	   is just accounted to the spinlock function.
+	   Better would be to write these functions in assembler again
+	   and check exactly. */
+	if (in_lock_functions(pc)) {
+		char *v = *(char **)regs->rsp;
+		if ((v >= _stext && v <= _etext) ||
+			(v >= _sinittext && v <= _einittext) ||
+			(v >= (char *)MODULES_VADDR  && v <= (char *)MODULES_END))
+			return (unsigned long)v;
+		return ((unsigned long *)regs->rsp)[1];
+	}
+	return pc;
+}
+EXPORT_SYMBOL(profile_pc);
+
 /*
  * In order to set the CMOS clock precisely, set_rtc_mmss has to be called 500
  * ms after the second nowtime has started, because when nowtime is written
@@ -214,7 +240,7 @@ static void set_rtc_mmss(unsigned long nowtime)
  * overflow. This avoids messing with unknown time zones but requires your RTC
  * not to be off by more than 15 minutes. Since we're calling it only when
  * our clock is externally synchronized using NTP, this shouldn't be a problem.
-	 */
+ */
 
 	real_seconds = nowtime % 60;
 	real_minutes = nowtime / 60;
@@ -293,19 +319,56 @@ unsigned long long monotonic_clock(void)
 }
 EXPORT_SYMBOL(monotonic_clock);
 
+static noinline void handle_lost_ticks(int lost, struct pt_regs *regs)
+{
+    static long lost_count;
+    static int warned;
+
+    if (report_lost_ticks) {
+	    printk(KERN_WARNING "time.c: Lost %d timer "
+		   "tick(s)! ", lost);
+	    print_symbol("rip %s)\n", regs->rip);
+    }
+
+    if (lost_count == 100 && !warned) {
+	    printk(KERN_WARNING
+		   "warning: many lost ticks.\n"
+		   KERN_WARNING "Your time source seems to be instable or "
+		   		"some driver is hogging interupts\n");
+	    print_symbol("rip %s\n", regs->rip);
+	    if (vxtime.mode == VXTIME_TSC && vxtime.hpet_address) {
+		    printk(KERN_WARNING "Falling back to HPET\n");
+		    vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
+		    vxtime.mode = VXTIME_HPET;
+		    do_gettimeoffset = do_gettimeoffset_hpet;
+	    }
+	    /* else should fall back to PIT, but code missing. */
+	    warned = 1;
+    } else
+	    lost_count++;
+
+#ifdef CONFIG_CPU_FREQ
+    /* In some cases the CPU can change frequency without us noticing
+       (like going into thermal throttle)
+       Give cpufreq a change to catch up. */
+    if ((lost_count+1) % 25 == 0) {
+	    cpufreq_delayed_get();
+    }
+#endif
+}
 
 static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	static unsigned long rtc_update = 0;
-	unsigned long tsc, lost = 0;
-	int delay, offset = 0;
+	unsigned long tsc;
+	int delay, offset = 0, lost = 0;
 
 /*
  * Here we are in the timer irq handler. We have irqs locally disabled (so we
  * don't need spin_lock_irqsave()) but we don't know if the timer_bh is running
  * on the other CPU, so we need a lock. We also need to lock the vsyscall
  * variables, because both do_timer() and us change them -arca+vojtech
-	 */
+ */
 
 	write_seqlock(&xtime_lock);
 
@@ -354,12 +417,8 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 				(((long) offset << 32) / vxtime.tsc_quot) - 1;
 	}
 
-	if (lost) {
-		if (report_lost_ticks) {
-			printk(KERN_WARNING "time.c: Lost %ld timer "
-			       "tick(s)! ", lost);
-			print_symbol("rip %s)\n", regs->rip);
-		}
+	if (lost > 0) {
+		handle_lost_ticks(lost, regs);
 		jiffies += lost;
 	}
 
@@ -376,7 +435,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  */
 
 #ifndef CONFIG_X86_LOCAL_APIC
-	x86_do_profile(regs);
+	profile_tick(CPU_PROFILING, regs);
 #else
 	if (!using_apic_timer)
 		smp_local_timer_interrupt(regs);
@@ -509,6 +568,38 @@ unsigned long get_cmos_time(void)
    Should fix up last_tsc too. Currently gettimeofday in the
    first tick after the change will be slightly wrong. */
 
+#include <linux/workqueue.h>
+
+static unsigned int cpufreq_delayed_issched = 0;
+static unsigned int cpufreq_init = 0;
+static struct work_struct cpufreq_delayed_get_work;
+
+static void handle_cpufreq_delayed_get(void *v)
+{
+	unsigned int cpu;
+	for_each_online_cpu(cpu) {
+		cpufreq_get(cpu);
+	}
+	cpufreq_delayed_issched = 0;
+}
+
+/* if we notice lost ticks, schedule a call to cpufreq_get() as it tries
+ * to verify the CPU frequency the timing core thinks the CPU is running
+ * at is still correct.
+ */
+static void cpufreq_delayed_get(void)
+{
+	static int warned;
+	if (cpufreq_init && !cpufreq_delayed_issched) {
+		cpufreq_delayed_issched = 1;
+		if (!warned) {
+			warned = 1;
+			printk(KERN_DEBUG "Losing some ticks... checking if CPU frequency changed.\n");
+		}
+		schedule_work(&cpufreq_delayed_get_work);
+	}
+}
+
 static unsigned int  ref_freq = 0;
 static unsigned long loops_per_jiffy_ref = 0;
 
@@ -518,14 +609,18 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
 				 void *data)
 {
         struct cpufreq_freqs *freq = data;
-	unsigned long *lpj;
+	unsigned long *lpj, dummy;
 
+	lpj = &dummy;
+	if (!(freq->flags & CPUFREQ_CONST_LOOPS))
 #ifdef CONFIG_SMP
 	lpj = &cpu_data[freq->cpu].loops_per_jiffy;
 #else
 	lpj = &boot_cpu_data.loops_per_jiffy;
 #endif
 
+
+
 	if (!ref_freq) {
 		ref_freq = freq->old;
 		loops_per_jiffy_ref = *lpj;
@@ -538,7 +633,8 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
 		cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new);
 
 		cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new);
-		vxtime.tsc_quot = (1000L << 32) / cpu_khz;
+		if (!(freq->flags & CPUFREQ_CONST_LOOPS))
+			vxtime.tsc_quot = (1000L << 32) / cpu_khz;
 	}
 	
 	set_cyc2ns_scale(cpu_khz_ref / 1000);
@@ -549,6 +645,18 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
 static struct notifier_block time_cpufreq_notifier_block = {
          .notifier_call  = time_cpufreq_notifier
 };
+
+static int __init cpufreq_tsc(void)
+{
+	INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL);
+	if (!cpufreq_register_notifier(&time_cpufreq_notifier_block,
+				       CPUFREQ_TRANSITION_NOTIFIER))
+		cpufreq_init = 1;
+	return 0;
+}
+
+core_initcall(cpufreq_tsc);
+
 #endif
 
 /*
@@ -705,9 +813,9 @@ void __init time_init(void)
                 outl(0x800038a0, 0xcf8);
                 outl(0xff000001, 0xcfc);
                 outl(0x800038a0, 0xcf8);
-                hpet_address = inl(0xcfc) & 0xfffffffe;
+                vxtime.hpet_address = inl(0xcfc) & 0xfffffffe;
 		printk(KERN_WARNING "time.c: WARNING: Enabled HPET "
-		       "at %#lx.\n", hpet_address);
+		       "at %#lx.\n", vxtime.hpet_address);
         }
 #endif
 	if (nohpet)
@@ -725,8 +833,8 @@ void __init time_init(void)
 		cpu_khz = hpet_calibrate_tsc();
 		timename = "HPET";
 	} else {
-	pit_init();
-	cpu_khz = pit_calibrate_tsc();
+		pit_init();
+		cpu_khz = pit_calibrate_tsc();
 		timename = "PIT";
 	}
 
@@ -742,11 +850,6 @@ void __init time_init(void)
 	setup_irq(0, &irq0);
 
 	set_cyc2ns_scale(cpu_khz / 1000);
-
-#ifdef CONFIG_CPU_FREQ
-	cpufreq_register_notifier(&time_cpufreq_notifier_block, 
-				  CPUFREQ_TRANSITION_NOTIFIER);
-#endif
 }
 
 void __init time_init_smp(void)
@@ -781,11 +884,12 @@ static int time_suspend(struct sys_device *dev, u32 state)
 
 static int time_resume(struct sys_device *dev)
 {
+	unsigned long flags;
 	unsigned long sec = get_cmos_time() + clock_cmos_diff;
-	write_seqlock_irq(&xtime_lock);
+	write_seqlock_irqsave(&xtime_lock,flags);
 	xtime.tv_sec = sec;
 	xtime.tv_nsec = 0;
-	write_sequnlock_irq(&xtime_lock);
+	write_sequnlock_irqrestore(&xtime_lock,flags);
 	return 0;
 }
 
@@ -1038,6 +1142,8 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 }
 #endif
 
+
+
 static int __init nohpet_setup(char *s) 
 { 
 	nohpet = 1;
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 99d0ec2ab..c0a31a4ad 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -110,9 +110,10 @@ unsigned long *in_exception_stack(int cpu, unsigned long stack)
 { 
 	int k;
 	for (k = 0; k < N_EXCEPTION_STACKS; k++) {
-		unsigned long end = init_tss[cpu].ist[k] + EXCEPTION_STKSZ; 
+		struct tss_struct *tss = &per_cpu(init_tss, cpu);
+		unsigned long end = tss->ist[k] + EXCEPTION_STKSZ;
 
-		if (stack >= init_tss[cpu].ist[k]  && stack <= end) 
+		if (stack >= tss->ist[k]  && stack <= end)
 			return (unsigned long *)end;
 	}
 	return NULL;
@@ -352,7 +353,7 @@ void __die(const char * str, struct pt_regs * regs, long err)
 #ifdef CONFIG_DEBUG_PAGEALLOC
 	printk("DEBUG_PAGEALLOC");
 #endif
-		printk("\n");
+	printk("\n");
 	notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV);
 	show_registers(regs);
 	/* Executive summary in case the oops scrolled away */
@@ -436,7 +437,8 @@ static void do_trap(int trapnr, int signr, char *str,
 #define DO_ERROR(trapnr, signr, str, name) \
 asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
 { \
-	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) == NOTIFY_BAD) \
+	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+							== NOTIFY_STOP) \
 		return; \
 	do_trap(trapnr, signr, str, regs, error_code, NULL); \
 }
@@ -449,7 +451,8 @@ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
 	info.si_errno = 0; \
 	info.si_code = sicode; \
 	info.si_addr = (void __user *)siaddr; \
-	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) == NOTIFY_BAD) \
+	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+							== NOTIFY_STOP) \
 		return; \
 	do_trap(trapnr, signr, str, regs, error_code, &info); \
 }
@@ -463,14 +466,15 @@ DO_ERROR( 7, SIGSEGV, "device not available", device_not_available)
 DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun)
 DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
 DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
-DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, get_cr2())
+DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
 DO_ERROR(18, SIGSEGV, "reserved", reserved)
 
 #define DO_ERROR_STACK(trapnr, signr, str, name) \
 asmlinkage void *do_##name(struct pt_regs * regs, long error_code) \
 { \
 	struct pt_regs *pr = ((struct pt_regs *)(current->thread.rsp0))-1; \
-	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) == NOTIFY_BAD) \
+	if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \
+							== NOTIFY_STOP) \
 		return regs; \
 	if (regs->cs & 3) { \
 		memcpy(pr, regs, sizeof(struct pt_regs)); \
@@ -513,7 +517,7 @@ asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
 		tsk->thread.error_code = error_code;
 		tsk->thread.trap_no = 13;
 		force_sig(SIGSEGV, tsk);
-	return;
+		return;
 	} 
 
 	/* kernel gp */
@@ -564,7 +568,8 @@ asmlinkage void default_do_nmi(struct pt_regs * regs)
 	unsigned char reason = inb(0x61);
 
 	if (!(reason & 0xc0)) {
-		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT) == NOTIFY_BAD)
+		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT)
+								== NOTIFY_STOP)
 			return;
 #ifdef CONFIG_X86_LOCAL_APIC
 		/*
@@ -579,7 +584,7 @@ asmlinkage void default_do_nmi(struct pt_regs * regs)
 		unknown_nmi_error(reason, regs);
 		return;
 	}
-	if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_BAD)
+	if (notify_die(DIE_NMI, "nmi", regs, reason, 0, SIGINT) == NOTIFY_STOP)
 		return; 
 	if (reason & 0x80)
 		mem_parity_error(reason, regs);
@@ -670,27 +675,53 @@ clear_dr7:
 	return regs;
 
 clear_TF_reenable:
-	printk("clear_tf_reenable\n");
 	set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
 
 clear_TF:
 	/* RED-PEN could cause spurious errors */
 	if (notify_die(DIE_DEBUG, "debug2", regs, condition, 1, SIGTRAP) 
-	    != NOTIFY_BAD)
+								!= NOTIFY_STOP)
 	regs->eflags &= ~TF_MASK;
 	return regs;	
 }
 
+static int kernel_math_error(struct pt_regs *regs, char *str)
+{
+	const struct exception_table_entry *fixup;
+	fixup = search_exception_tables(regs->rip);
+	if (fixup) {
+		regs->rip = fixup->fixup;
+		return 1;
+	}
+	notify_die(DIE_GPF, str, regs, 0, 16, SIGFPE);
+#if 0
+	/* This should be a die, but warn only for now */
+	die(str, regs, 0);
+#else
+	printk(KERN_DEBUG "%s: %s at ", current->comm, str);
+	printk_address(regs->rip);
+	printk("\n");
+#endif
+	return 0;
+}
+
 /*
  * Note that we play around with the 'TS' bit in an attempt to get
  * the correct behaviour even in the presence of the asynchronous
  * IRQ13 behaviour
  */
-void math_error(void __user *rip)
+asmlinkage void do_coprocessor_error(struct pt_regs *regs)
 {
+	void __user *rip = (void __user *)(regs->rip);
 	struct task_struct * task;
 	siginfo_t info;
 	unsigned short cwd, swd;
+
+	conditional_sti(regs);
+	if ((regs->cs & 3) == 0 &&
+	    kernel_math_error(regs, "kernel x87 math error"))
+		return;
+
 	/*
 	 * Save the info for the exception handler and clear the error.
 	 */
@@ -740,23 +771,23 @@ void math_error(void __user *rip)
 	force_sig_info(SIGFPE, &info, task);
 }
 
-asmlinkage void do_coprocessor_error(struct pt_regs * regs)
-{
-	conditional_sti(regs);
-	math_error((void __user *)regs->rip);
-}
-
 asmlinkage void bad_intr(void)
 {
 	printk("bad interrupt"); 
 }
 
-static inline void simd_math_error(void __user *rip)
+asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs)
 {
+	void __user *rip = (void __user *)(regs->rip);
 	struct task_struct * task;
 	siginfo_t info;
 	unsigned short mxcsr;
 
+	conditional_sti(regs);
+	if ((regs->cs & 3) == 0 &&
+        	kernel_math_error(regs, "simd math error"))
+		return;
+
 	/*
 	 * Save the info for the exception handler and clear the error.
 	 */
@@ -799,12 +830,6 @@ static inline void simd_math_error(void __user *rip)
 	force_sig_info(SIGFPE, &info, task);
 }
 
-asmlinkage void do_simd_coprocessor_error(struct pt_regs * regs)
-{
-	conditional_sti(regs);
-		simd_math_error((void __user *)regs->rip);
-}
-
 asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs)
 {
 }
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
index 21383547b..f656f197b 100644
--- a/arch/x86_64/kernel/vmlinux.lds.S
+++ b/arch/x86_64/kernel/vmlinux.lds.S
@@ -16,6 +16,7 @@ SECTIONS
   .text : {
 	*(.text)
 	SCHED_TEXT
+	LOCK_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x9090
@@ -91,9 +92,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
   __initcall_start = .;
   .initcall.init : {
 	*(.initcall1.init) 
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
index 1fb138482..6e3acce42 100644
--- a/arch/x86_64/kernel/x8664_ksyms.c
+++ b/arch/x86_64/kernel/x8664_ksyms.c
@@ -21,7 +21,6 @@
 #include <asm/uaccess.h>
 #include <asm/checksum.h>
 #include <asm/io.h>
-#include <asm/hardirq.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
 #include <asm/mmx.h>
@@ -63,10 +62,10 @@ EXPORT_SYMBOL(pm_idle);
 EXPORT_SYMBOL(pm_power_off);
 EXPORT_SYMBOL(get_cmos_time);
 
-EXPORT_SYMBOL_NOVERS(__down_failed);
-EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
-EXPORT_SYMBOL_NOVERS(__down_failed_trylock);
-EXPORT_SYMBOL_NOVERS(__up_wakeup);
+EXPORT_SYMBOL(__down_failed);
+EXPORT_SYMBOL(__down_failed_interruptible);
+EXPORT_SYMBOL(__down_failed_trylock);
+EXPORT_SYMBOL(__up_wakeup);
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial_copy_nocheck);
 EXPORT_SYMBOL(ip_compute_csum);
@@ -76,14 +75,14 @@ EXPORT_SYMBOL(__ndelay);
 EXPORT_SYMBOL(__delay);
 EXPORT_SYMBOL(__const_udelay);
 
-EXPORT_SYMBOL_NOVERS(__get_user_1);
-EXPORT_SYMBOL_NOVERS(__get_user_2);
-EXPORT_SYMBOL_NOVERS(__get_user_4);
-EXPORT_SYMBOL_NOVERS(__get_user_8);
-EXPORT_SYMBOL_NOVERS(__put_user_1);
-EXPORT_SYMBOL_NOVERS(__put_user_2);
-EXPORT_SYMBOL_NOVERS(__put_user_4);
-EXPORT_SYMBOL_NOVERS(__put_user_8);
+EXPORT_SYMBOL(__get_user_1);
+EXPORT_SYMBOL(__get_user_2);
+EXPORT_SYMBOL(__get_user_4);
+EXPORT_SYMBOL(__get_user_8);
+EXPORT_SYMBOL(__put_user_1);
+EXPORT_SYMBOL(__put_user_2);
+EXPORT_SYMBOL(__put_user_4);
+EXPORT_SYMBOL(__put_user_8);
 
 EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strstr);
@@ -108,18 +107,15 @@ EXPORT_SYMBOL(pcibios_penalize_isa_irq);
 EXPORT_SYMBOL(pci_mem_start);
 #endif
 
-#ifdef CONFIG_X86_USE_3DNOW
-EXPORT_SYMBOL(_mmx_memcpy);
-EXPORT_SYMBOL(mmx_clear_page);
-EXPORT_SYMBOL(mmx_copy_page);
-#endif
+EXPORT_SYMBOL(copy_page);
+EXPORT_SYMBOL(clear_page);
 
 EXPORT_SYMBOL(cpu_pda);
 #ifdef CONFIG_SMP
 EXPORT_SYMBOL(cpu_data);
 EXPORT_SYMBOL(cpu_online_map);
-EXPORT_SYMBOL_NOVERS(__write_lock_failed);
-EXPORT_SYMBOL_NOVERS(__read_lock_failed);
+EXPORT_SYMBOL(__write_lock_failed);
+EXPORT_SYMBOL(__read_lock_failed);
 
 EXPORT_SYMBOL(synchronize_irq);
 EXPORT_SYMBOL(smp_call_function);
@@ -164,28 +160,35 @@ extern void * __memcpy(void *,const void *,__kernel_size_t);
 extern char * strcat(char *, const char *);
 extern int memcmp(const void * cs,const void * ct,size_t count);
 
-EXPORT_SYMBOL_NOVERS(memset);
-EXPORT_SYMBOL_NOVERS(strlen);
-EXPORT_SYMBOL_NOVERS(memmove);
-EXPORT_SYMBOL_NOVERS(strcpy);
-EXPORT_SYMBOL_NOVERS(strncmp);
-EXPORT_SYMBOL_NOVERS(strncpy);
-EXPORT_SYMBOL_NOVERS(strchr);
-EXPORT_SYMBOL_NOVERS(strcmp); 
-EXPORT_SYMBOL_NOVERS(strcat);
-EXPORT_SYMBOL_NOVERS(strncat);
-EXPORT_SYMBOL_NOVERS(memchr);
-EXPORT_SYMBOL_NOVERS(strrchr);
-EXPORT_SYMBOL_NOVERS(strnlen);
-EXPORT_SYMBOL_NOVERS(memscan);
-EXPORT_SYMBOL_NOVERS(memcpy);
-EXPORT_SYMBOL_NOVERS(__memcpy);
-EXPORT_SYMBOL_NOVERS(memcmp);
-
-/* syscall export needed for misdesigned sound drivers. */
-EXPORT_SYMBOL(sys_read);
-EXPORT_SYMBOL(sys_lseek);
-EXPORT_SYMBOL(sys_open);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(strcpy);
+EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(strncpy);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strncat);
+EXPORT_SYMBOL(memchr);
+EXPORT_SYMBOL(strrchr);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(__memcpy);
+EXPORT_SYMBOL(memcmp);
+
+#ifdef CONFIG_RWSEM_XCHGADD_ALGORITHM
+/* prototypes are wrong, these are assembly with custom calling functions */
+extern void rwsem_down_read_failed_thunk(void);
+extern void rwsem_wake_thunk(void);
+extern void rwsem_downgrade_thunk(void);
+extern void rwsem_down_write_failed_thunk(void);
+EXPORT_SYMBOL(rwsem_down_read_failed_thunk);
+EXPORT_SYMBOL(rwsem_wake_thunk);
+EXPORT_SYMBOL(rwsem_downgrade_thunk);
+EXPORT_SYMBOL(rwsem_down_write_failed_thunk);
+#endif
 
 EXPORT_SYMBOL(empty_zero_page);
 
@@ -201,7 +204,7 @@ EXPORT_SYMBOL(smp_num_siblings);
 #endif
 
 extern void do_softirq_thunk(void);
-EXPORT_SYMBOL_NOVERS(do_softirq_thunk);
+EXPORT_SYMBOL(do_softirq_thunk);
 
 void out_of_line_bug(void);
 EXPORT_SYMBOL(out_of_line_bug);
@@ -211,10 +214,9 @@ EXPORT_SYMBOL(init_level4_pgt);
 extern unsigned long __supported_pte_mask;
 EXPORT_SYMBOL(__supported_pte_mask);
 
-EXPORT_SYMBOL(clear_page);
-
 #ifdef CONFIG_SMP
 EXPORT_SYMBOL(flush_tlb_page);
 EXPORT_SYMBOL_GPL(flush_tlb_all);
 #endif
 
+EXPORT_SYMBOL(cpu_khz);
diff --git a/arch/x86_64/lib/Makefile b/arch/x86_64/lib/Makefile
index 32b206440..6b26a1c1e 100644
--- a/arch/x86_64/lib/Makefile
+++ b/arch/x86_64/lib/Makefile
@@ -8,7 +8,7 @@ obj-y := io.o
 
 lib-y := csum-partial.o csum-copy.o csum-wrappers.o delay.o \
 	usercopy.o getuser.o putuser.o  \
-	thunk.o clear_page.o copy_page.o bitstr.o
+	thunk.o clear_page.o copy_page.o bitstr.o bitops.o
 lib-y += memcpy.o memmove.o memset.o copy_user.o
 
 lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
diff --git a/arch/x86_64/lib/bitstr.c b/arch/x86_64/lib/bitstr.c
index 598d79de8..e7ce82a0a 100644
--- a/arch/x86_64/lib/bitstr.c
+++ b/arch/x86_64/lib/bitstr.c
@@ -1,3 +1,4 @@
+#include <linux/module.h>
 #include <asm/bitops.h>
 
 /* Find string of zero bits in a bitmap */ 
@@ -23,3 +24,5 @@ find_next_zero_string(unsigned long *bitmap, long start, long nbits, int len)
 	}
 	return n;
 }
+
+EXPORT_SYMBOL(find_next_zero_string);
diff --git a/arch/x86_64/lib/csum-wrappers.c b/arch/x86_64/lib/csum-wrappers.c
index c5b166224..18abae985 100644
--- a/arch/x86_64/lib/csum-wrappers.c
+++ b/arch/x86_64/lib/csum-wrappers.c
@@ -22,6 +22,7 @@ unsigned int
 csum_partial_copy_from_user(const char __user *src, char *dst, 
 			    int len, unsigned int isum, int *errp)
 { 
+	might_sleep();
 	*errp = 0;
 	if (likely(access_ok(VERIFY_READ,src, len))) { 
 		/* Why 6, not 7? To handle odd addresses aligned we
@@ -69,6 +70,7 @@ unsigned int
 csum_partial_copy_to_user(const char *src, char __user *dst, 
 			  int len, unsigned int isum, int *errp)
 { 
+	might_sleep();
 	if (unlikely(!access_ok(VERIFY_WRITE, dst, len))) {
 		*errp = -EFAULT;
 		return 0; 
diff --git a/arch/x86_64/lib/memmove.c b/arch/x86_64/lib/memmove.c
index 12cac5ba7..e93d5255f 100644
--- a/arch/x86_64/lib/memmove.c
+++ b/arch/x86_64/lib/memmove.c
@@ -10,18 +10,10 @@ void *memmove(void * dest,const void *src,size_t count)
 	if (dest < src) { 
 		__inline_memcpy(dest,src,count);
 	} else {
-		/* Could be more clever and move longs */
-		unsigned long d0, d1, d2;
-		__asm__ __volatile__(
-			"std\n\t"
-			"rep\n\t"
-			"movsb\n\t"
-			"cld"
-			: "=&c" (d0), "=&S" (d1), "=&D" (d2)
-			:"0" (count),
-			"1" (count-1+(const char *)src),
-			"2" (count-1+(char *)dest)
-			:"memory");
+		char *p = (char *) dest + count;
+		char *s = (char *) src + count;
+		while (count--)
+			*--p = *--s;
 	}
 	return dest;
 } 
diff --git a/arch/x86_64/lib/usercopy.c b/arch/x86_64/lib/usercopy.c
index a17c85c5b..db8abba1a 100644
--- a/arch/x86_64/lib/usercopy.c
+++ b/arch/x86_64/lib/usercopy.c
@@ -14,6 +14,7 @@
 #define __do_strncpy_from_user(dst,src,count,res)			   \
 do {									   \
 	long __d0, __d1, __d2;						   \
+	might_sleep();							   \
 	__asm__ __volatile__(						   \
 		"	testq %1,%1\n"					   \
 		"	jz 2f\n"					   \
@@ -63,6 +64,7 @@ strncpy_from_user(char *dst, const char __user *src, long count)
 unsigned long __clear_user(void __user *addr, unsigned long size)
 {
 	long __d0;
+	might_sleep();
 	/* no memory constraint because it doesn't change any memory gcc knows
 	   about */
 	asm volatile(
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
index 32a1d0ce9..4e12a56c9 100644
--- a/arch/x86_64/mm/fault.c
+++ b/arch/x86_64/mm/fault.c
@@ -27,7 +27,6 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
-#include <asm/hardirq.h>
 #include <asm/smp.h>
 #include <asm/tlbflush.h>
 #include <asm/proto.h>
@@ -58,16 +57,17 @@ void bust_spinlocks(int yes)
 /* Sometimes the CPU reports invalid exceptions on prefetch.
    Check that here and ignore.
    Opcode checker based on code by Richard Brunner */
-static int is_prefetch(struct pt_regs *regs, unsigned long addr)
+static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr,
+				unsigned long error_code)
 { 
 	unsigned char *instr = (unsigned char *)(regs->rip);
 	int scan_more = 1;
 	int prefetch = 0; 
 	unsigned char *max_instr = instr + 15;
 
-	/* Avoid recursive faults for this common case */
-	if (regs->rip == addr)
-		return 0; 
+	/* If it was a exec fault ignore */
+	if (error_code & (1<<4))
+		return 0;
 	
 	/* Code segments in LDT could have a non zero base. Don't check
 	   when that's possible */
@@ -218,6 +218,18 @@ int unhandled_signal(struct task_struct *tsk, int sig)
 		(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)
+{
+	oops_begin();
+	printk(KERN_ALERT "%s: Corrupted page table at address %lx\n",
+	       current->comm, address);
+	dump_pagetable(address);
+	__die("Bad pagetable", regs, error_code);
+	oops_end();
+	do_exit(SIGKILL);
+}
+
 int page_fault_trace; 
 int exception_trace = 1;
 
@@ -268,11 +280,32 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
 	mm = tsk->mm;
 	info.si_code = SEGV_MAPERR;
 
-	/* 5 => page not present and from supervisor mode */
-	if (unlikely(!(error_code & 5) &&
-		     ((address >= VMALLOC_START && address <= VMALLOC_END) ||
-		      (address >= MODULES_VADDR && address <= MODULES_END))))
-		goto vmalloc_fault;
+
+	/*
+	 * We fault-in kernel-space virtual memory on-demand. The
+	 * 'reference' page table is init_mm.pgd.
+	 *
+	 * NOTE! We MUST NOT take any locks for this case. We may
+	 * be in an interrupt or a critical region, and should
+	 * only copy the information from the master page table,
+	 * nothing more.
+	 *
+	 * This verifies that the fault happens in kernel space
+	 * (error_code & 4) == 0, and that the fault was not a
+	 * protection error (error_code & 1) == 0.
+	 */
+	if (unlikely(address >= TASK_SIZE)) {
+		if (!(error_code & 5))
+			goto vmalloc_fault;
+		/*
+		 * Don't take the mm semaphore here. If we fixup a prefetch
+		 * fault we could otherwise deadlock.
+		 */
+		goto bad_area_nosemaphore;
+	}
+
+	if (unlikely(error_code & (1 << 3)))
+		goto page_table_corruption;
 
 	/*
 	 * If we're in an interrupt or have no user
@@ -282,7 +315,27 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
 		goto bad_area_nosemaphore;
 
  again:
-	down_read(&mm->mmap_sem);
+	/* When running in the kernel we expect faults to occur only to
+	 * addresses in user space.  All other faults represent errors in the
+	 * kernel and should generate an OOPS.  Unfortunatly, in the case of an
+	 * erroneous fault occuring in a code path which already holds mmap_sem
+	 * we will deadlock attempting to validate the fault against the
+	 * address space.  Luckily the kernel only validly references user
+	 * space from well defined areas of code, which are listed in the
+	 * exceptions table.
+	 *
+	 * As the vast majority of faults will be valid we will only perform
+	 * the source reference check when there is a possibilty of a deadlock.
+	 * Attempt to lock the address space, if we cannot we then validate the
+	 * source.  If this is invalid we can skip the address space check,
+	 * thus avoiding the deadlock.
+	 */
+	if (!down_read_trylock(&mm->mmap_sem)) {
+		if ((error_code & 4) == 0 &&
+		    !search_exception_tables(regs->rip))
+			goto bad_area_nosemaphore;
+		down_read(&mm->mmap_sem);
+	}
 
 	vma = find_vma(mm, address);
 	if (!vma)
@@ -351,18 +404,18 @@ bad_area:
 bad_area_nosemaphore:
 
 #ifdef CONFIG_IA32_EMULATION
-		/* 32bit vsyscall. map on demand. */
-		if (test_thread_flag(TIF_IA32) && 
+	/* 32bit vsyscall. map on demand. */
+	if (test_thread_flag(TIF_IA32) &&
 	    address >= 0xffffe000 && address < 0xffffe000 + PAGE_SIZE) { 
-			if (map_syscall32(mm, address) < 0) 
-				goto out_of_memory2;
-			return;
-		} 			
+		if (map_syscall32(mm, address) < 0)
+			goto out_of_memory2;
+		return;
+	}
 #endif
 
 	/* User mode accesses just cause a SIGSEGV */
 	if (error_code & 4) {
-		if (is_prefetch(regs, address))
+		if (is_prefetch(regs, address, error_code))
 			return;
 
 		/* Work around K8 erratum #100 K8 in compat mode
@@ -376,7 +429,7 @@ bad_area_nosemaphore:
 			return;
 
 		if (exception_trace && unhandled_signal(tsk, SIGSEGV)) {
-		printk(KERN_INFO 
+			printk(KERN_INFO
 		       "%s[%d]: segfault at %016lx rip %016lx rsp %016lx error %lx\n",
 					tsk->comm, tsk->pid, address, regs->rip,
 					regs->rsp, error_code);
@@ -407,7 +460,7 @@ no_context:
 	 * Hall of shame of CPU/BIOS bugs.
 	 */
 
- 	if (is_prefetch(regs, address))
+ 	if (is_prefetch(regs, address, error_code))
  		return;
 
 	if (is_errata93(regs, address))
@@ -481,10 +534,8 @@ vmalloc_fault:
 		 * is really there and when yes flush the local TLB. 
 		 */
 		pgd = pgd_offset_k(address);
-		if (pgd != current_pgd_offset_k(address)) 
-			BUG(); 
 		if (!pgd_present(*pgd))
-				goto bad_area_nosemaphore;
+			goto bad_area_nosemaphore;
 		pmd = pmd_offset(pgd, address);
 		if (!pmd_present(*pmd))
 			goto bad_area_nosemaphore;
@@ -495,4 +546,7 @@ vmalloc_fault:
 		__flush_tlb_all();		
 		return;
 	}
+
+page_table_corruption:
+	pgtable_bad(address, regs, error_code);
 }
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index f393e3355..e13acb6ab 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -41,6 +41,10 @@
 #define Dprintk(x...)
 #endif
 
+#ifdef CONFIG_GART_IOMMU
+extern int swiotlb;
+#endif
+
 extern char _stext[];
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
@@ -396,6 +400,8 @@ static inline int page_is_ram (unsigned long pagenr)
 	return 0;
 }
 
+extern int swiotlb_force;
+
 static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules,
 			 kcore_vsyscall;
 
@@ -405,7 +411,10 @@ void __init mem_init(void)
 	int tmp;
 
 #ifdef CONFIG_SWIOTLB
-	if (!iommu_aperture && end_pfn >= 0xffffffff>>PAGE_SHIFT)
+	if (swiotlb_force)
+		swiotlb = 1;
+	if (!iommu_aperture &&
+	    (end_pfn >= 0xffffffff>>PAGE_SHIFT || force_iommu))
 	       swiotlb = 1;
 	if (swiotlb)
 		swiotlb_init();	
@@ -596,7 +605,16 @@ static struct vm_area_struct gate32_vma = {
 
 struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
 {
-	return test_tsk_thread_flag(tsk, TIF_IA32) ? &gate32_vma : &gate_vma;
+#ifdef CONFIG_IA32_EMULATION
+	if (test_tsk_thread_flag(tsk, TIF_IA32)) {
+		/* lookup code assumes the pages are present. set them up
+		   now */
+		if (__map_syscall32(tsk->mm, 0xfffe000) < 0)
+			return NULL;
+		return &gate32_vma;
+	}
+#endif
+	return &gate_vma;
 }
 
 int in_gate_area(struct task_struct *task, unsigned long addr)
diff --git a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c
index 0cc4a612f..9fc032b99 100644
--- a/arch/x86_64/mm/ioremap.c
+++ b/arch/x86_64/mm/ioremap.c
@@ -111,7 +111,7 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr,
  * have to convert them into an offset in a page-aligned mapping, but the
  * caller shouldn't need to know that small detail.
  */
-void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
 {
 	void * addr;
 	struct vm_struct * area;
@@ -126,7 +126,7 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
 	 * Don't remap the low PCI/ISA area, it's always mapped..
 	 */
 	if (phys_addr >= 0xA0000 && last_addr < 0x100000)
-		return phys_to_virt(phys_addr);
+		return (__force void __iomem *)phys_to_virt(phys_addr);
 
 	/*
 	 * Don't allow anybody to remap normal RAM that we're using..
@@ -164,7 +164,7 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
 		vunmap(addr);
 		return NULL;
 	}
-	return (void *) (offset + (char *)addr);
+	return (__force void __iomem *) (offset + (char *)addr);
 }
 
 /**
@@ -189,9 +189,9 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
  * Must be freed with iounmap.
  */
 
-void *ioremap_nocache (unsigned long phys_addr, unsigned long size)
+void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
 {
-	void *p = __ioremap(phys_addr, size, _PAGE_PCD);
+	void __iomem *p = __ioremap(phys_addr, size, _PAGE_PCD);
 	if (!p) 
 		return p; 
 
@@ -212,7 +212,7 @@ void *ioremap_nocache (unsigned long phys_addr, unsigned long size)
 	return p;					
 }
 
-void iounmap(void *addr)
+void iounmap(void __iomem *addr)
 {
 	struct vm_struct *p;
 	if (addr <= high_memory) 
diff --git a/arch/x86_64/mm/k8topology.c b/arch/x86_64/mm/k8topology.c
index 0ec22c11c..0825e37fd 100644
--- a/arch/x86_64/mm/k8topology.c
+++ b/arch/x86_64/mm/k8topology.c
@@ -100,8 +100,8 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
 		limit <<= 24; 
 		limit |= (1<<24)-1;
 
-		if (limit > end_pfn_map << PAGE_SHIFT) 
-			limit = end_pfn_map << PAGE_SHIFT; 
+		if (limit > end_pfn << PAGE_SHIFT)
+			limit = end_pfn << PAGE_SHIFT;
 		if (limit <= base)
 			continue; 
 			
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
index 598a35c19..e6746a26b 100644
--- a/arch/x86_64/mm/numa.c
+++ b/arch/x86_64/mm/numa.c
@@ -135,7 +135,7 @@ void __init setup_node_zones(int nodeid)
 		zones[ZONE_NORMAL] = end_pfn - start_pfn; 
 	} 
     
-	free_area_init_node(nodeid, NODE_DATA(nodeid), NULL, zones, 
+	free_area_init_node(nodeid, NODE_DATA(nodeid), zones,
 			    start_pfn, NULL); 
 } 
 
@@ -162,10 +162,58 @@ void __init numa_init_array(void)
 	set_bit(0, &node_to_cpumask[cpu_to_node(0)]);
 }
 
+int numa_fake __initdata = 0;
+
+/* Numa emulation */
+static int numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
+{
+ 	int i;
+ 	struct node nodes[MAXNODE];
+ 	unsigned long sz = ((end_pfn - start_pfn)<<PAGE_SHIFT) / numa_fake;
+
+ 	/* Kludge needed for the hash function */
+ 	if (hweight64(sz) > 1) {
+ 		unsigned long x = 1;
+ 		while ((x << 1) < sz)
+ 			x <<= 1;
+ 		if (x < sz/2)
+ 			printk("Numa emulation unbalanced. Complain to maintainer\n");
+ 		sz = x;
+ 	}
+
+ 	memset(&nodes,0,sizeof(nodes));
+ 	for (i = 0; i < numa_fake; i++) {
+ 		nodes[i].start = (start_pfn<<PAGE_SHIFT) + i*sz;
+ 		if (i == numa_fake-1)
+ 			sz = (end_pfn<<PAGE_SHIFT) - nodes[i].start;
+ 		nodes[i].end = nodes[i].start + sz;
+ 		if (i != numa_fake-1)
+ 			nodes[i].end--;
+ 		printk(KERN_INFO "Faking node %d at %016Lx-%016Lx (%LuMB)\n",
+ 		       i,
+ 		       nodes[i].start, nodes[i].end,
+ 		       (nodes[i].end - nodes[i].start) >> 20);
+ 	}
+ 	numnodes = numa_fake;
+ 	memnode_shift = compute_hash_shift(nodes);
+ 	if (memnode_shift < 0) {
+ 		memnode_shift = 0;
+ 		printk(KERN_ERR "No NUMA hash function found. Emulation disabled.\n");
+ 		return -1;
+ 	}
+ 	for (i = 0; i < numa_fake; i++)
+ 		setup_node_bootmem(i, nodes[i].start, nodes[i].end);
+ 	numa_init_array();
+ 	return 0;
+}
+
 void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
 { 
 	int i;
 
+	if (numa_fake && !numa_emulation(start_pfn, end_pfn))
+ 		return;
+
 #ifdef CONFIG_K8_NUMA
 	if (!numa_off && !k8_scan_nodes(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT))
 		return;
@@ -214,8 +262,13 @@ void __init paging_init(void)
 /* [numa=off] */
 __init int numa_setup(char *opt) 
 { 
-	if (!strncmp(opt,"off",3))
+	if (!strcmp(opt,"off"))
 		numa_off = 1;
+	if(!strncmp(opt, "fake=", 5)) {
+		numa_fake = simple_strtoul(opt+5,NULL,0); ;
+		if (numa_fake >= MAX_NUMNODES)
+			numa_fake = MAX_NUMNODES;
+	}
 	return 1;
 } 
 
diff --git a/arch/x86_64/pci/Makefile b/arch/x86_64/pci/Makefile
index 291985f0d..37c92e841 100644
--- a/arch/x86_64/pci/Makefile
+++ b/arch/x86_64/pci/Makefile
@@ -3,7 +3,7 @@
 #
 # Reuse the i386 PCI subsystem
 #
-CFLAGS += -I arch/i386/pci
+CFLAGS += -Iarch/i386/pci
 
 obj-y		:= i386.o
 obj-$(CONFIG_PCI_DIRECT)+= direct.o
@@ -13,6 +13,8 @@ obj-y			+= legacy.o irq.o common.o
 # mmconfig has a 64bit special
 obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o
 
+obj-$(CONFIG_NUMA)	+= k8-bus.o
+
 direct-y += ../../i386/pci/direct.o
 acpi-y   += ../../i386/pci/acpi.o
 legacy-y += ../../i386/pci/legacy.o
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 12429ef28..9916a1830 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -67,6 +67,18 @@ config CRYPTO_SHA512
 	  This code also includes SHA-384, a 384 bit hash with 192 bits
 	  of security against collision attacks.
 
+config CRYPTO_WP512
+	tristate "Whirlpool digest algorithms"
+	depends on CRYPTO
+	help
+	  Whirlpool hash algorithm 512, 384 and 256-bit hashes
+
+	  Whirlpool-512 is part of the NESSIE cryptographic primtives.
+	  Whirlpool will be part of the ISO/IEC 10118-3:2003(E) standard
+
+	  See also:
+	  http://planeta.terra.com.br/informatica/paulobarreto/WhirlpoolPage.html
+
 config CRYPTO_DES
 	tristate "DES and Triple DES EDE cipher algorithms"
 	depends on CRYPTO
@@ -182,7 +194,7 @@ config CRYPTO_TEA
 	  many rounds for security.  It is very fast and uses
 	  little memory.
 
-	  Xtendend Tiny Encryption Algorithm is a modifcation to
+	  Xtendend Tiny Encryption Algorithm is a modification to
 	  the TEA algorithm to address a potential key weakness
 	  in the TEA algorithm.
 
diff --git a/crypto/Makefile b/crypto/Makefile
index 04428a655..0c9d42bfb 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_CRYPTO_MD5) += md5.o
 obj-$(CONFIG_CRYPTO_SHA1) += sha1.o
 obj-$(CONFIG_CRYPTO_SHA256) += sha256.o
 obj-$(CONFIG_CRYPTO_SHA512) += sha512.o
+obj-$(CONFIG_CRYPTO_WP512) += wp512.o
 obj-$(CONFIG_CRYPTO_DES) += des.o
 obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
 obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o
diff --git a/crypto/aes.c b/crypto/aes.c
index 13b6daa37..94b89a9c7 100644
--- a/crypto/aes.c
+++ b/crypto/aes.c
@@ -102,10 +102,10 @@ struct aes_ctx {
 #define E_KEY ctx->E
 #define D_KEY ctx->D
 
-static u8 pow_tab[256];
-static u8 log_tab[256];
-static u8 sbx_tab[256];
-static u8 isb_tab[256];
+static u8 pow_tab[256] __initdata;
+static u8 log_tab[256] __initdata;
+static u8 sbx_tab[256] __initdata;
+static u8 isb_tab[256] __initdata;
 static u32 rco_tab[10];
 static u32 ft_tab[4][256];
 static u32 it_tab[4][256];
@@ -113,7 +113,7 @@ static u32 it_tab[4][256];
 static u32 fl_tab[4][256];
 static u32 il_tab[4][256];
 
-static inline u8
+static inline u8 __init
 f_mult (u8 a, u8 b)
 {
 	u8 aa = log_tab[a], cc = aa + log_tab[b];
@@ -153,14 +153,14 @@ f_mult (u8 a, u8 b)
              il_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
              il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
 
-static void
+static void __init
 gen_tabs (void)
 {
 	u32 i, t;
 	u8 p, q;
 
 	/* log and power tables for GF(2**8) finite field with
-	   0x011b as modular polynomial - the simplest prmitive
+	   0x011b as modular polynomial - the simplest primitive
 	   root is 0x03, used here to generate the tables */
 
 	for (i = 0, p = 1; i < 256; ++i) {
diff --git a/crypto/api.c b/crypto/api.c
index 6f0e62571..394169a85 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -155,8 +155,12 @@ out:
 
 void crypto_free_tfm(struct crypto_tfm *tfm)
 {
+	struct crypto_alg *alg = tfm->__crt_alg;
+	int size = sizeof(*tfm) + alg->cra_ctxsize;
+
 	crypto_exit_ops(tfm);
-	crypto_alg_put(tfm->__crt_alg);
+	crypto_alg_put(alg);
+	memset(tfm, 0, size);
 	kfree(tfm);
 }
 
diff --git a/crypto/arc4.c b/crypto/arc4.c
index b66eb1f0d..9efbcaae8 100644
--- a/crypto/arc4.c
+++ b/crypto/arc4.c
@@ -3,7 +3,7 @@
  *
  * ARC4 Cipher Algorithm
  *
- * Jon Oberheide <jon@focalhost.com>
+ * Jon Oberheide <jon@oberheide.org>
  *
  * 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
@@ -100,4 +100,4 @@ module_exit(arc4_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("ARC4 Cipher Algorithm");
-MODULE_AUTHOR("Jon Oberheide <jon@focalhost.com>");
+MODULE_AUTHOR("Jon Oberheide <jon@oberheide.org>");
diff --git a/crypto/blowfish.c b/crypto/blowfish.c
index 8fd18dcdb..b6bea821c 100644
--- a/crypto/blowfish.c
+++ b/crypto/blowfish.c
@@ -3,9 +3,9 @@
  *
  * Blowfish Cipher Algorithm, by Bruce Schneier.
  * http://www.counterpane.com/blowfish.html
- * 
- * Adapated from Kerneli implementation.
- * 
+ *
+ * Adapted from Kerneli implementation.
+ *
  * Copyright (c) Herbert Valerio Riedel <hvr@hvrlab.org>
  * Copyright (c) Kyle McMartin <kyle@debian.org>
  * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
diff --git a/crypto/internal.h b/crypto/internal.h
index b51fad1f9..e68e43886 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -17,7 +17,6 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/kmod.h>
-#include <asm/hardirq.h>
 #include <asm/kmap_types.h>
 
 extern enum km_type crypto_km_types[];
diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c
index 540dd9ac1..f6a5c9e5b 100644
--- a/crypto/scatterwalk.c
+++ b/crypto/scatterwalk.c
@@ -70,7 +70,7 @@ static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
 {
 	/* walk->data may be pointing the first byte of the next page;
 	   however, we know we transfered at least one byte.  So,
-	   walk->data - 1 will be a virutual address in the mapped page. */
+	   walk->data - 1 will be a virtual address in the mapped page. */
 
 	if (out)
 		flush_dcache_page(walk->page);
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index f1e631b9c..c23d5ee69 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -24,6 +24,7 @@
 #include <linux/string.h>
 #include <linux/crypto.h>
 #include <linux/highmem.h>
+#include <linux/moduleparam.h>
 #include "tcrypt.h"
 
 /*
@@ -61,7 +62,8 @@ static char *tvmem;
 static char *check[] = {
 	"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
 	"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", 
-	"arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea", NULL
+	"arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea", 
+	"wp512", "wp384", "wp256", NULL
 };
 
 static void
@@ -680,6 +682,9 @@ do_test(void)
 
 		test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
 		test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
+		test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS);
+		test_hash("wp384", wp384_tv_template, WP384_TEST_VECTORS);
+		test_hash("wp256", wp256_tv_template, WP256_TEST_VECTORS);
 		test_deflate();
 		test_crc32c();
 #ifdef CONFIG_CRYPTO_HMAC
@@ -791,6 +796,19 @@ do_test(void)
 		test_cipher ("khazad", MODE_ECB, DECRYPT, khazad_dec_tv_template, KHAZAD_DEC_TEST_VECTORS);
 		break;
 
+	case 22:
+		test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS);
+		break;
+
+	case 23:
+		test_hash("wp384", wp384_tv_template, WP384_TEST_VECTORS);
+		break;
+
+	case 24:
+		test_hash("wp256", wp256_tv_template, WP256_TEST_VECTORS);
+		break;
+
+
 #ifdef CONFIG_CRYPTO_HMAC
 	case 100:
 		test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
@@ -846,7 +864,7 @@ static void __exit fini(void) { }
 module_init(init);
 module_exit(fini);
 
-MODULE_PARM(mode, "i");
+module_param(mode, int, 0);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Quick & dirty crypto testing module");
diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
index 56a825d65..18370befc 100644
--- a/crypto/tcrypt.h
+++ b/crypto/tcrypt.h
@@ -301,6 +301,259 @@ struct hash_testvec sha512_tv_template[] = {
 	},
 };
 
+
+/*
+ * WHIRLPOOL test vectors from Whirlpool package 
+ * by Vincent Rijmen and Paulo S. L. M. Barreto as part of the NESSIE
+ * submission
+ */
+#define WP512_TEST_VECTORS	8
+
+struct hash_testvec wp512_tv_template[] = {
+	{ 
+		.plaintext = "",
+		.psize	= 0,
+		.digest	= { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66,
+			    0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26,
+			    0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8,
+			    0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7,
+			    0x3E, 0x83, 0xBE, 0x69, 0x8B, 0x28, 0x8F, 0xEB,
+			    0xCF, 0x88, 0xE3, 0xE0, 0x3C, 0x4F, 0x07, 0x57,
+			    0xEA, 0x89, 0x64, 0xE5, 0x9B, 0x63, 0xD9, 0x37,
+			    0x08, 0xB1, 0x38, 0xCC, 0x42, 0xA6, 0x6E, 0xB3 },
+
+
+	}, {
+		.plaintext = "a",
+		.psize	= 1,
+		.digest	= { 0x8A, 0xCA, 0x26, 0x02, 0x79, 0x2A, 0xEC, 0x6F,
+			    0x11, 0xA6, 0x72, 0x06, 0x53, 0x1F, 0xB7, 0xD7,
+			    0xF0, 0xDF, 0xF5, 0x94, 0x13, 0x14, 0x5E, 0x69,
+			    0x73, 0xC4, 0x50, 0x01, 0xD0, 0x08, 0x7B, 0x42,
+			    0xD1, 0x1B, 0xC6, 0x45, 0x41, 0x3A, 0xEF, 0xF6,
+			    0x3A, 0x42, 0x39, 0x1A, 0x39, 0x14, 0x5A, 0x59,
+			    0x1A, 0x92, 0x20, 0x0D, 0x56, 0x01, 0x95, 0xE5,
+			    0x3B, 0x47, 0x85, 0x84, 0xFD, 0xAE, 0x23, 0x1A },
+	}, {
+		.plaintext = "abc",
+		.psize	= 3,
+		.digest	= { 0x4E, 0x24, 0x48, 0xA4, 0xC6, 0xF4, 0x86, 0xBB,
+			    0x16, 0xB6, 0x56, 0x2C, 0x73, 0xB4, 0x02, 0x0B,
+			    0xF3, 0x04, 0x3E, 0x3A, 0x73, 0x1B, 0xCE, 0x72,
+			    0x1A, 0xE1, 0xB3, 0x03, 0xD9, 0x7E, 0x6D, 0x4C,
+			    0x71, 0x81, 0xEE, 0xBD, 0xB6, 0xC5, 0x7E, 0x27,
+			    0x7D, 0x0E, 0x34, 0x95, 0x71, 0x14, 0xCB, 0xD6,
+			    0xC7, 0x97, 0xFC, 0x9D, 0x95, 0xD8, 0xB5, 0x82,
+			    0xD2, 0x25, 0x29, 0x20, 0x76, 0xD4, 0xEE, 0xF5 },
+	}, {
+		.plaintext = "message digest",
+		.psize	= 14,
+		.digest	= { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6, 
+			    0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC, 
+			    0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C, 
+			    0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B, 
+			    0x84, 0x21, 0x55, 0x76, 0x59, 0xEF, 0x55, 0xC1, 
+			    0x06, 0xB4, 0xB5, 0x2A, 0xC5, 0xA4, 0xAA, 0xA6, 
+			    0x92, 0xED, 0x92, 0x00, 0x52, 0x83, 0x8F, 0x33, 
+			    0x62, 0xE8, 0x6D, 0xBD, 0x37, 0xA8, 0x90, 0x3E },
+	}, {
+		.plaintext = "abcdefghijklmnopqrstuvwxyz",
+		.psize	= 26,
+		.digest	= { 0xF1, 0xD7, 0x54, 0x66, 0x26, 0x36, 0xFF, 0xE9,
+			    0x2C, 0x82, 0xEB, 0xB9, 0x21, 0x2A, 0x48, 0x4A,
+			    0x8D, 0x38, 0x63, 0x1E, 0xAD, 0x42, 0x38, 0xF5,
+			    0x44, 0x2E, 0xE1, 0x3B, 0x80, 0x54, 0xE4, 0x1B,
+			    0x08, 0xBF, 0x2A, 0x92, 0x51, 0xC3, 0x0B, 0x6A,
+			    0x0B, 0x8A, 0xAE, 0x86, 0x17, 0x7A, 0xB4, 0xA6,
+			    0xF6, 0x8F, 0x67, 0x3E, 0x72, 0x07, 0x86, 0x5D,
+			    0x5D, 0x98, 0x19, 0xA3, 0xDB, 0xA4, 0xEB, 0x3B },
+	}, {
+		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+			     "abcdefghijklmnopqrstuvwxyz0123456789",
+		.psize	= 62,
+		.digest	= { 0xDC, 0x37, 0xE0, 0x08, 0xCF, 0x9E, 0xE6, 0x9B,
+			    0xF1, 0x1F, 0x00, 0xED, 0x9A, 0xBA, 0x26, 0x90,
+			    0x1D, 0xD7, 0xC2, 0x8C, 0xDE, 0xC0, 0x66, 0xCC,
+			    0x6A, 0xF4, 0x2E, 0x40, 0xF8, 0x2F, 0x3A, 0x1E,
+			    0x08, 0xEB, 0xA2, 0x66, 0x29, 0x12, 0x9D, 0x8F,
+			    0xB7, 0xCB, 0x57, 0x21, 0x1B, 0x92, 0x81, 0xA6,
+			    0x55, 0x17, 0xCC, 0x87, 0x9D, 0x7B, 0x96, 0x21,
+			    0x42, 0xC6, 0x5F, 0x5A, 0x7A, 0xF0, 0x14, 0x67 },
+	}, {
+		.plaintext = "1234567890123456789012345678901234567890"
+			     "1234567890123456789012345678901234567890",
+		.psize	= 80,
+		.digest	= { 0x46, 0x6E, 0xF1, 0x8B, 0xAB, 0xB0, 0x15, 0x4D,
+			    0x25, 0xB9, 0xD3, 0x8A, 0x64, 0x14, 0xF5, 0xC0,
+			    0x87, 0x84, 0x37, 0x2B, 0xCC, 0xB2, 0x04, 0xD6,
+			    0x54, 0x9C, 0x4A, 0xFA, 0xDB, 0x60, 0x14, 0x29,
+			    0x4D, 0x5B, 0xD8, 0xDF, 0x2A, 0x6C, 0x44, 0xE5,
+			    0x38, 0xCD, 0x04, 0x7B, 0x26, 0x81, 0xA5, 0x1A,
+			    0x2C, 0x60, 0x48, 0x1E, 0x88, 0xC5, 0xA2, 0x0B,
+			    0x2C, 0x2A, 0x80, 0xCF, 0x3A, 0x9A, 0x08, 0x3B },
+	}, {
+		.plaintext = "abcdbcdecdefdefgefghfghighijhijk",
+		.psize	= 32,
+		.digest	= { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61, 
+			    0xF5, 0xD6, 0xF0, 0xA0, 0xE4, 0x64, 0x4F, 0x48,
+			    0x8A, 0x7A, 0x5A, 0x52, 0xDE, 0xEE, 0x65, 0x62,
+			    0x07, 0xC5, 0x62, 0xF9, 0x88, 0xE9, 0x5C, 0x69,
+			    0x16, 0xBD, 0xC8, 0x03, 0x1B, 0xC5, 0xBE, 0x1B,
+			    0x7B, 0x94, 0x76, 0x39, 0xFE, 0x05, 0x0B, 0x56,
+			    0x93, 0x9B, 0xAA, 0xA0, 0xAD, 0xFF, 0x9A, 0xE6,
+			    0x74, 0x5B, 0x7B, 0x18, 0x1C, 0x3B, 0xE3, 0xFD },
+	},
+};
+
+#define WP384_TEST_VECTORS	8
+
+struct hash_testvec wp384_tv_template[] = {
+	{ 
+		.plaintext = "",
+		.psize	= 0,
+		.digest	= { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66,
+			    0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26,
+			    0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8,
+			    0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7,
+			    0x3E, 0x83, 0xBE, 0x69, 0x8B, 0x28, 0x8F, 0xEB,
+			    0xCF, 0x88, 0xE3, 0xE0, 0x3C, 0x4F, 0x07, 0x57 },
+
+
+	}, {
+		.plaintext = "a",
+		.psize	= 1,
+		.digest	= { 0x8A, 0xCA, 0x26, 0x02, 0x79, 0x2A, 0xEC, 0x6F,
+			    0x11, 0xA6, 0x72, 0x06, 0x53, 0x1F, 0xB7, 0xD7,
+			    0xF0, 0xDF, 0xF5, 0x94, 0x13, 0x14, 0x5E, 0x69,
+			    0x73, 0xC4, 0x50, 0x01, 0xD0, 0x08, 0x7B, 0x42,
+			    0xD1, 0x1B, 0xC6, 0x45, 0x41, 0x3A, 0xEF, 0xF6,
+			    0x3A, 0x42, 0x39, 0x1A, 0x39, 0x14, 0x5A, 0x59 },
+	}, {
+		.plaintext = "abc",
+		.psize	= 3,
+		.digest	= { 0x4E, 0x24, 0x48, 0xA4, 0xC6, 0xF4, 0x86, 0xBB,
+			    0x16, 0xB6, 0x56, 0x2C, 0x73, 0xB4, 0x02, 0x0B,
+			    0xF3, 0x04, 0x3E, 0x3A, 0x73, 0x1B, 0xCE, 0x72,
+			    0x1A, 0xE1, 0xB3, 0x03, 0xD9, 0x7E, 0x6D, 0x4C,
+			    0x71, 0x81, 0xEE, 0xBD, 0xB6, 0xC5, 0x7E, 0x27,
+			    0x7D, 0x0E, 0x34, 0x95, 0x71, 0x14, 0xCB, 0xD6 },
+	}, {
+		.plaintext = "message digest",
+		.psize	= 14,
+		.digest	= { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6, 
+			    0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC, 
+			    0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C, 
+			    0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B, 
+			    0x84, 0x21, 0x55, 0x76, 0x59, 0xEF, 0x55, 0xC1, 
+			    0x06, 0xB4, 0xB5, 0x2A, 0xC5, 0xA4, 0xAA, 0xA6 },
+	}, {
+		.plaintext = "abcdefghijklmnopqrstuvwxyz",
+		.psize	= 26,
+		.digest	= { 0xF1, 0xD7, 0x54, 0x66, 0x26, 0x36, 0xFF, 0xE9,
+			    0x2C, 0x82, 0xEB, 0xB9, 0x21, 0x2A, 0x48, 0x4A,
+			    0x8D, 0x38, 0x63, 0x1E, 0xAD, 0x42, 0x38, 0xF5,
+			    0x44, 0x2E, 0xE1, 0x3B, 0x80, 0x54, 0xE4, 0x1B,
+			    0x08, 0xBF, 0x2A, 0x92, 0x51, 0xC3, 0x0B, 0x6A,
+			    0x0B, 0x8A, 0xAE, 0x86, 0x17, 0x7A, 0xB4, 0xA6 },
+	}, {
+		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+			     "abcdefghijklmnopqrstuvwxyz0123456789",
+		.psize	= 62,
+		.digest	= { 0xDC, 0x37, 0xE0, 0x08, 0xCF, 0x9E, 0xE6, 0x9B,
+			    0xF1, 0x1F, 0x00, 0xED, 0x9A, 0xBA, 0x26, 0x90,
+			    0x1D, 0xD7, 0xC2, 0x8C, 0xDE, 0xC0, 0x66, 0xCC,
+			    0x6A, 0xF4, 0x2E, 0x40, 0xF8, 0x2F, 0x3A, 0x1E,
+			    0x08, 0xEB, 0xA2, 0x66, 0x29, 0x12, 0x9D, 0x8F,
+			    0xB7, 0xCB, 0x57, 0x21, 0x1B, 0x92, 0x81, 0xA6 },
+	}, {
+		.plaintext = "1234567890123456789012345678901234567890"
+			     "1234567890123456789012345678901234567890",
+		.psize	= 80,
+		.digest	= { 0x46, 0x6E, 0xF1, 0x8B, 0xAB, 0xB0, 0x15, 0x4D,
+			    0x25, 0xB9, 0xD3, 0x8A, 0x64, 0x14, 0xF5, 0xC0,
+			    0x87, 0x84, 0x37, 0x2B, 0xCC, 0xB2, 0x04, 0xD6,
+			    0x54, 0x9C, 0x4A, 0xFA, 0xDB, 0x60, 0x14, 0x29,
+			    0x4D, 0x5B, 0xD8, 0xDF, 0x2A, 0x6C, 0x44, 0xE5,
+			    0x38, 0xCD, 0x04, 0x7B, 0x26, 0x81, 0xA5, 0x1A },
+	}, {
+		.plaintext = "abcdbcdecdefdefgefghfghighijhijk",
+		.psize	= 32,
+		.digest	= { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61, 
+			    0xF5, 0xD6, 0xF0, 0xA0, 0xE4, 0x64, 0x4F, 0x48,
+			    0x8A, 0x7A, 0x5A, 0x52, 0xDE, 0xEE, 0x65, 0x62,
+			    0x07, 0xC5, 0x62, 0xF9, 0x88, 0xE9, 0x5C, 0x69,
+			    0x16, 0xBD, 0xC8, 0x03, 0x1B, 0xC5, 0xBE, 0x1B,
+			    0x7B, 0x94, 0x76, 0x39, 0xFE, 0x05, 0x0B, 0x56 },
+	},
+};
+
+#define WP256_TEST_VECTORS	8
+
+struct hash_testvec wp256_tv_template[] = {
+	{ 
+		.plaintext = "",
+		.psize	= 0,
+		.digest	= { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66,
+			    0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26,
+			    0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8,
+			    0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7 },
+
+
+	}, {
+		.plaintext = "a",
+		.psize	= 1,
+		.digest	= { 0x8A, 0xCA, 0x26, 0x02, 0x79, 0x2A, 0xEC, 0x6F,
+			    0x11, 0xA6, 0x72, 0x06, 0x53, 0x1F, 0xB7, 0xD7,
+			    0xF0, 0xDF, 0xF5, 0x94, 0x13, 0x14, 0x5E, 0x69,
+			    0x73, 0xC4, 0x50, 0x01, 0xD0, 0x08, 0x7B, 0x42 },
+	}, {
+		.plaintext = "abc",
+		.psize	= 3,
+		.digest	= { 0x4E, 0x24, 0x48, 0xA4, 0xC6, 0xF4, 0x86, 0xBB,
+			    0x16, 0xB6, 0x56, 0x2C, 0x73, 0xB4, 0x02, 0x0B,
+			    0xF3, 0x04, 0x3E, 0x3A, 0x73, 0x1B, 0xCE, 0x72,
+			    0x1A, 0xE1, 0xB3, 0x03, 0xD9, 0x7E, 0x6D, 0x4C },
+	}, {
+		.plaintext = "message digest",
+		.psize	= 14,
+		.digest	= { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6, 
+			    0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC, 
+			    0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C, 
+			    0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B },
+	}, {
+		.plaintext = "abcdefghijklmnopqrstuvwxyz",
+		.psize	= 26,
+		.digest	= { 0xF1, 0xD7, 0x54, 0x66, 0x26, 0x36, 0xFF, 0xE9,
+			    0x2C, 0x82, 0xEB, 0xB9, 0x21, 0x2A, 0x48, 0x4A,
+			    0x8D, 0x38, 0x63, 0x1E, 0xAD, 0x42, 0x38, 0xF5,
+			    0x44, 0x2E, 0xE1, 0x3B, 0x80, 0x54, 0xE4, 0x1B },
+	}, {
+		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+			     "abcdefghijklmnopqrstuvwxyz0123456789",
+		.psize	= 62,
+		.digest	= { 0xDC, 0x37, 0xE0, 0x08, 0xCF, 0x9E, 0xE6, 0x9B,
+			    0xF1, 0x1F, 0x00, 0xED, 0x9A, 0xBA, 0x26, 0x90,
+			    0x1D, 0xD7, 0xC2, 0x8C, 0xDE, 0xC0, 0x66, 0xCC,
+			    0x6A, 0xF4, 0x2E, 0x40, 0xF8, 0x2F, 0x3A, 0x1E },
+	}, {
+		.plaintext = "1234567890123456789012345678901234567890"
+			     "1234567890123456789012345678901234567890",
+		.psize	= 80,
+		.digest	= { 0x46, 0x6E, 0xF1, 0x8B, 0xAB, 0xB0, 0x15, 0x4D,
+			    0x25, 0xB9, 0xD3, 0x8A, 0x64, 0x14, 0xF5, 0xC0,
+			    0x87, 0x84, 0x37, 0x2B, 0xCC, 0xB2, 0x04, 0xD6,
+			    0x54, 0x9C, 0x4A, 0xFA, 0xDB, 0x60, 0x14, 0x29 },
+	}, {
+		.plaintext = "abcdbcdecdefdefgefghfghighijhijk",
+		.psize	= 32,
+		.digest	= { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61, 
+			    0xF5, 0xD6, 0xF0, 0xA0, 0xE4, 0x64, 0x4F, 0x48,
+			    0x8A, 0x7A, 0x5A, 0x52, 0xDE, 0xEE, 0x65, 0x62,
+			    0x07, 0xC5, 0x62, 0xF9, 0x88, 0xE9, 0x5C, 0x69 },
+	},
+};
+
+
 #ifdef CONFIG_CRYPTO_HMAC
 /*
  * HMAC-MD5 test vectors from RFC2202
@@ -1186,7 +1439,7 @@ struct cipher_testvec tf_cbc_dec_tv_template[] = {
 
 /*
  * Serpent test vectors.  These are backwards because Serpent writes
- * octect sequences in right-to-left mode.
+ * octet sequences in right-to-left mode.
  */
 #define SERPENT_ENC_TEST_VECTORS	4
 #define SERPENT_DEC_TEST_VECTORS	4
diff --git a/crypto/tea.c b/crypto/tea.c
index bf943294d..588a143c1 100644
--- a/crypto/tea.c
+++ b/crypto/tea.c
@@ -154,7 +154,7 @@ static void xtea_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
 
 	while (sum != limit) {
 		y += (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum&3]; 
-		sum += TEA_DELTA;
+		sum += XTEA_DELTA;
 		z += (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 &3]; 
 	}
 	
diff --git a/crypto/twofish.c b/crypto/twofish.c
index 5d6d02c1a..4efff8cf9 100644
--- a/crypto/twofish.c
+++ b/crypto/twofish.c
@@ -1,7 +1,7 @@
 /*
  * Twofish for CryptoAPI
  *
- * Originaly Twofish for GPG
+ * Originally Twofish for GPG
  * By Matthew Skala <mskala@ansuz.sooke.bc.ca>, July 26, 1998
  * 256-bit key length added March 20, 1999
  * Some modifications to reduce the text size by Werner Koch, April, 1998
@@ -514,7 +514,7 @@ static const u8 calc_sb_tbl[512] = {
  * preprocessed through q0 and q1 respectively; for longer keys they are the
  * output of previous stages.  j is the index of the first key byte to use.
  * CALC_K computes a pair of subkeys for 128-bit Twofish, by calling CALC_K_2
- * twice, doing the Psuedo-Hadamard Transform, and doing the necessary
+ * twice, doing the Pseudo-Hadamard Transform, and doing the necessary
  * rotations.  Its parameters are: a, the array to write the results into,
  * j, the index of the first output entry, k and l, the preprocessed indices
  * for index 2i, and m and n, the preprocessed indices for index 2i+1.
diff --git a/drivers/Makefile b/drivers/Makefile
index 847d2c1ed..dfaafd02f 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -7,6 +7,7 @@
 
 obj-$(CONFIG_PCI)		+= pci/
 obj-$(CONFIG_PARISC)		+= parisc/
+obj-y				+= video/
 obj-$(CONFIG_ACPI_BOOT)		+= acpi/
 # PnP must come after ACPI since it will eventually need to check if acpi
 # was used and do nothing if so
@@ -15,6 +16,13 @@ obj-$(CONFIG_PNP)		+= pnp/
 # char/ comes before serial/ etc so that the VT console is the boot-time
 # default.
 obj-y				+= char/
+
+# i810fb depends on char/agp/
+obj-$(CONFIG_FB_I810)           += video/i810/
+
+# we also need input/serio early so serio bus is initialized by the time
+# serial drivers start registering their serio ports
+obj-$(CONFIG_SERIO)		+= input/serio/
 obj-y				+= serial/
 obj-$(CONFIG_PARPORT)		+= parport/
 obj-y				+= base/ block/ misc/ net/ media/
@@ -26,7 +34,7 @@ obj-$(CONFIG_FC4)		+= fc4/
 obj-$(CONFIG_SCSI)		+= scsi/
 obj-$(CONFIG_FUSION)		+= message/
 obj-$(CONFIG_IEEE1394)		+= ieee1394/
-obj-y				+= cdrom/ video/
+obj-y				+= cdrom/
 obj-$(CONFIG_MTD)		+= mtd/
 obj-$(CONFIG_PCMCIA)		+= pcmcia/
 obj-$(CONFIG_DIO)		+= dio/
@@ -39,7 +47,6 @@ obj-$(CONFIG_USB)		+= usb/
 obj-$(CONFIG_USB_GADGET)	+= usb/gadget/
 obj-$(CONFIG_INPUT)		+= input/
 obj-$(CONFIG_GAMEPORT)		+= input/gameport/
-obj-$(CONFIG_SERIO)		+= input/serio/
 obj-$(CONFIG_I2O)		+= message/
 obj-$(CONFIG_I2C)		+= i2c/
 obj-$(CONFIG_W1)		+= w1/
@@ -50,4 +57,5 @@ obj-$(CONFIG_ISDN)		+= isdn/
 obj-$(CONFIG_MCA)		+= mca/
 obj-$(CONFIG_EISA)		+= eisa/
 obj-$(CONFIG_CPU_FREQ)		+= cpufreq/
+obj-$(CONFIG_MMC)		+= mmc/
 obj-y				+= firmware/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index a742764db..96e4fafb0 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -204,6 +204,32 @@ config ACPI_TOSHIBA
 	  If you have a legacy free Toshiba laptop (such as the Libretto L1
 	  series), say Y.
 
+config ACPI_CUSTOM_DSDT
+	bool "Include Custom DSDT"
+	depends on X86 && ACPI_INTERPRETER && !STANDALONE
+	default n 
+	help
+	  Thist option is to load a custom ACPI DSDT
+	  If you don't know what that is, say N.
+
+config ACPI_CUSTOM_DSDT_FILE
+	string "Custom DSDT Table file to include"
+	depends on ACPI_CUSTOM_DSDT
+	default ""
+	help
+	  Enter the full path name to the file wich includes the AmlCode declaration.
+
+config ACPI_BLACKLIST_YEAR
+	int "Disable ACPI for systems before Jan 1st this year"
+	default 0
+	help
+	  enter a 4-digit year, eg. 2001 to disable ACPI by default
+	  on platforms with DMI BIOS date before January 1st that year.
+	  "acpi=force" can be used to override this mechanism.
+
+	  Enter 0 to disable this mechanism and allow ACPI to
+	  run by default no matter what the year.  (default)
+
 config ACPI_DEBUG
 	bool "Debug Statements"
 	depends on ACPI_INTERPRETER
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index beb93c60d..bcc35ca79 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -47,4 +47,4 @@ obj-$(CONFIG_ACPI_DEBUG)	+= debug.o
 obj-$(CONFIG_ACPI_NUMA)		+= numa.o
 obj-$(CONFIG_ACPI_ASUS)		+= asus_acpi.o
 obj-$(CONFIG_ACPI_TOSHIBA)	+= toshiba_acpi.o
-obj-$(CONFIG_ACPI_BUS)		+= scan.o 
+obj-$(CONFIG_ACPI_BUS)		+= scan.o motherboard.o
diff --git a/drivers/acpi/acpi_ksyms.c b/drivers/acpi/acpi_ksyms.c
index c918088a4..a267b8b3b 100644
--- a/drivers/acpi/acpi_ksyms.c
+++ b/drivers/acpi/acpi_ksyms.c
@@ -84,6 +84,8 @@ EXPORT_SYMBOL(acpi_resource_to_address64);
 EXPORT_SYMBOL(acpi_enable_event);
 EXPORT_SYMBOL(acpi_disable_event);
 EXPORT_SYMBOL(acpi_clear_event);
+EXPORT_SYMBOL(acpi_set_gpe_type);
+EXPORT_SYMBOL(acpi_enable_gpe);
 EXPORT_SYMBOL(acpi_get_timer_duration);
 EXPORT_SYMBOL(acpi_get_timer);
 EXPORT_SYMBOL(acpi_get_sleep_type_data);
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
index c884d4aaa..f2ca51bef 100644
--- a/drivers/acpi/asus_acpi.c
+++ b/drivers/acpi/asus_acpi.c
@@ -42,7 +42,7 @@
 #include <acpi/acpi_bus.h>
 #include <asm/uaccess.h>
 
-#define ASUS_ACPI_VERSION "0.28"
+#define ASUS_ACPI_VERSION "0.29"
 
 #define PROC_ASUS       "asus"	//the directory
 #define PROC_MLED       "mled"
@@ -123,14 +123,18 @@ struct asus_hotk {
 		L3C,      //L3800C
 		L3D,      //L3400D
 		L3H,      //L3H, but also L2000E
+		L4R,      //L4500R
 		L5x,      //L5800C 
 		L8L,      //L8400L
 		M1A,      //M1300A
 		M2E,      //M2400E, L4400L
+		M6N,      //M6800N
+		M6R,      //M6700R
 		P30,	  //Samsung P30
 		S1x,      //S1300A, but also L1400B and M2400A (L84F)
 		S2x,      //S200 (J1 reported), Victor MP-XP7210
-		xxN,      //M2400N, M3700N, M6800N, S1300N, S5200N (Centrino)
+		xxN,      //M2400N, M3700N, M5200N, S1300N, S5200N, W1OOON
+			  //(Centrino)
 		END_MODEL
 	} model;              //Models currently supported
 	u16 event_count[128]; //count for each event TODO make this better
@@ -246,6 +250,19 @@ static struct model_data model_conf[END_MODEL] = {
 		.display_get       = "\\INFB"
 	},
 
+	{
+		.name              = "L4R",
+		.mt_mled           = "MLED",
+		.mt_wled           = "WLED",
+		.wled_status       = "\\_SB.PCI0.SBRG.SG13",
+		.mt_lcd_switch     = xxN_PREFIX "_Q10",
+		.lcd_status        = "\\_SB.PCI0.SBSM.SEO4",
+		.brightness_set    = "SPLV",
+		.brightness_get    = "GPLV", 
+		.display_set       = "SDSP",
+		.display_get       = "\\_SB.PCI0.P0P1.VGA.GETD"
+	},
+
 	{
 		.name              = "L5x",
 		.mt_mled           = "MLED",
@@ -288,6 +305,31 @@ static struct model_data model_conf[END_MODEL] = {
 		.display_get       = "\\INFB"
 	},
 
+	{
+		.name              = "M6N",
+		.mt_mled           = "MLED",
+		.mt_wled           = "WLED",
+		.wled_status       = "\\_SB.PCI0.SBRG.SG13",
+		.mt_lcd_switch     = xxN_PREFIX "_Q10",
+		.lcd_status        = "\\_SB.BKLT",
+		.brightness_set    = "SPLV",
+		.brightness_get    = "GPLV",
+		.display_set       = "SDSP",
+		.display_get       = "\\SSTE"
+	},
+	{
+		.name              = "M6R",
+		.mt_mled           = "MLED",
+		.mt_wled           = "WLED",
+		.mt_lcd_switch     = xxN_PREFIX "_Q10",
+		.lcd_status        = "\\_SB.PCI0.SBSM.SEO4",
+		.brightness_set    = "SPLV",
+		.brightness_get    = "GPLV",
+		.display_set       = "SDSP",
+		.display_get       = "\\SSTE"
+	},
+
+
 	{
 		.name              = "P30",
 		.mt_wled           = "WLED",
@@ -344,6 +386,9 @@ static struct proc_dir_entry *asus_proc_dir;
  */
 static struct acpi_table_header *asus_info;
 
+/* The actual device the driver binds to */
+static struct asus_hotk *hotk;
+
 /*
  * The hotkey driver declaration
  */
@@ -408,7 +453,6 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
 {
 	int len = 0;
 	int temp;
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
 	char buf[16];		//enough for all info
 	/*
 	 * We use the easy way, we don't care of off and count, so we don't set eof
@@ -428,7 +472,7 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
 		len += sprintf(page + len, "SFUN value         : 0x%04x\n", temp);
 	/*
 	 * Another value for userspace: the ASYM method returns 0x02 for
-	 * battery low and 0x04 for battery critical, it's readings tend to be
+	 * battery low and 0x04 for battery critical, its readings tend to be
 	 * more accurate than those provided by _BST. 
 	 * Note: since not all the laptops provide this method, errors are
 	 * silently ignored.
@@ -467,7 +511,7 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof,
 
 /* Generic LED functions */
 static int
-read_led(struct asus_hotk *hotk, const char *ledname, int ledmask)
+read_led(const char *ledname, int ledmask)
 {
 	if (ledname) {
 		int led_status;
@@ -498,7 +542,7 @@ static int parse_arg(const char __user *buf, unsigned long count, int *val)
 
 /* FIXME: kill extraneous args so it can be called independently */
 static int
-write_led(const char __user *buffer, unsigned long count, struct asus_hotk *hotk, 
+write_led(const char __user *buffer, unsigned long count,
           char *ledname, int ledmask, int invert)
 {
 	int value;
@@ -528,8 +572,7 @@ static int
 proc_read_mled(char *page, char **start, off_t off, int count, int *eof,
 	       void *data)
 {
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
-	return sprintf(page, "%d\n", read_led(hotk, hotk->methods->mled_status, MLED_ON));
+	return sprintf(page, "%d\n", read_led(hotk->methods->mled_status, MLED_ON));
 }
 
 
@@ -537,8 +580,7 @@ static int
 proc_write_mled(struct file *file, const char __user *buffer,
 		unsigned long count, void *data)
 {
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
-	return write_led(buffer, count, hotk, hotk->methods->mt_mled, MLED_ON, 1);
+	return write_led(buffer, count, hotk->methods->mt_mled, MLED_ON, 1);
 }
 
 /*
@@ -548,16 +590,14 @@ static int
 proc_read_wled(char *page, char **start, off_t off, int count, int *eof,
 	       void *data)
 {
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
-	return sprintf(page, "%d\n", read_led(hotk, hotk->methods->wled_status, WLED_ON));
+	return sprintf(page, "%d\n", read_led(hotk->methods->wled_status, WLED_ON));
 }
 
 static int
 proc_write_wled(struct file *file, const char __user *buffer,
 		unsigned long count, void *data)
 {
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
-	return write_led(buffer, count, hotk, hotk->methods->mt_wled, WLED_ON, 0);
+	return write_led(buffer, count, hotk->methods->mt_wled, WLED_ON, 0);
 }
 
 /*
@@ -567,21 +607,18 @@ static int
 proc_read_tled(char *page, char **start, off_t off, int count, int *eof,
 	       void *data)
 {
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
-	return sprintf(page, "%d\n", read_led(hotk, hotk->methods->tled_status, TLED_ON));
+	return sprintf(page, "%d\n", read_led(hotk->methods->tled_status, TLED_ON));
 }
 
 static int
 proc_write_tled(struct file *file, const char __user *buffer,
 		unsigned long count, void *data)
 {
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
-	return write_led(buffer, count, hotk, hotk->methods->mt_tled, TLED_ON, 0);
+	return write_led(buffer, count, hotk->methods->mt_tled, TLED_ON, 0);
 }
 
 
-
-static int get_lcd_state(struct asus_hotk *hotk)
+static int get_lcd_state(void)
 {
 	int lcd = 0;
 
@@ -622,13 +659,13 @@ static int get_lcd_state(struct asus_hotk *hotk)
 	return (lcd & 1);
 }
 
-static int set_lcd_state(struct asus_hotk *hotk, int value)
+static int set_lcd_state(int value)
 {
 	int lcd = 0;
 	acpi_status status = 0;
 
 	lcd = value ? 1 : 0;
-	if (lcd != get_lcd_state(hotk)) {
+	if (lcd != get_lcd_state()) {
 		/* switch */
 		if (hotk->model != L3H) {
 			status =
@@ -651,7 +688,7 @@ static int
 proc_read_lcd(char *page, char **start, off_t off, int count, int *eof,
 	      void *data)
 {
-	return sprintf(page, "%d\n", get_lcd_state((struct asus_hotk *) data));
+	return sprintf(page, "%d\n", get_lcd_state());
 }
 
 
@@ -660,16 +697,15 @@ proc_write_lcd(struct file *file, const char __user *buffer,
 	       unsigned long count, void *data)
 {
 	int value;
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
 	
 	count = parse_arg(buffer, count, &value);
 	if (count > 0)
-		set_lcd_state(hotk, value);
+		set_lcd_state(value);
 	return count;
 }
 
 
-static int read_brightness(struct asus_hotk *hotk)
+static int read_brightness(void)
 {
 	int value;
 	
@@ -689,7 +725,7 @@ static int read_brightness(struct asus_hotk *hotk)
 /*
  * Change the brightness level
  */
-static void set_brightness(int value, struct asus_hotk *hotk)
+static void set_brightness(int value)
 {
 	acpi_status status = 0;
 
@@ -702,7 +738,7 @@ static void set_brightness(int value, struct asus_hotk *hotk)
 	}
 
 	/* No SPLV method if we are here, act as appropriate */
-	value -= read_brightness(hotk);
+	value -= read_brightness();
 	while (value != 0) {
 		status = acpi_evaluate_object(NULL, (value > 0) ? 
 					      hotk->methods->brightness_up : 
@@ -719,8 +755,7 @@ static int
 proc_read_brn(char *page, char **start, off_t off, int count, int *eof,
 	      void *data)
 {
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
-	return sprintf(page, "%d\n", read_brightness(hotk));
+	return sprintf(page, "%d\n", read_brightness());
 }
 
 static int
@@ -728,13 +763,12 @@ proc_write_brn(struct file *file, const char __user *buffer,
 	       unsigned long count, void *data)
 {
 	int value;
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
 
 	count = parse_arg(buffer, count, &value);
 	if (count > 0) {
 		value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
 			/* 0 <= value <= 15 */
-		set_brightness(value, hotk);
+		set_brightness(value);
 	} else if (count < 0) {
 		printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
 	}
@@ -742,7 +776,7 @@ proc_write_brn(struct file *file, const char __user *buffer,
 	return count;
 }
 
-static void set_display(int value, struct asus_hotk *hotk)
+static void set_display(int value)
 {
 	/* no sanity check needed for now */
 	if (!write_acpi_int(hotk->handle, hotk->methods->display_set, 
@@ -760,10 +794,10 @@ proc_read_disp(char *page, char **start, off_t off, int count, int *eof,
 	      void *data)
 {
 	int value = 0;
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
 	
 	if (!read_acpi_int(hotk->handle, hotk->methods->display_get, &value))
 		printk(KERN_WARNING "Asus ACPI: Error reading display status\n");
+	value &= 0x07; /* needed for some models, shouldn't hurt others */
 	return sprintf(page, "%d\n", value);
 }
 
@@ -778,11 +812,10 @@ proc_write_disp(struct file *file, const char __user *buffer,
 	       unsigned long count, void *data)
 {
 	int value;
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
 
 	count = parse_arg(buffer, count, &value);
 	if (count > 0)
-		set_display(value, hotk);
+		set_display(value);
 	else if (count < 0)
 		printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
 
@@ -817,7 +850,6 @@ __init asus_proc_add(char *name, proc_writefunc *writefunc,
 static int __init asus_hotk_add_fs(struct acpi_device *device)
 {
 	struct proc_dir_entry *proc;
-	struct asus_hotk *hotk = acpi_driver_data(device);
 	mode_t mode;
 	
 	/*
@@ -869,13 +901,12 @@ static int __init asus_hotk_add_fs(struct acpi_device *device)
 	}
 	
 	if ((hotk->methods->brightness_up && hotk->methods->brightness_down) ||
-	    (hotk->methods->brightness_get && hotk->methods->brightness_get)) {
+	    (hotk->methods->brightness_get && hotk->methods->brightness_set)) {
 		asus_proc_add(PROC_BRN, &proc_write_brn, &proc_read_brn, mode, device);
 	}
 
 	if (hotk->methods->display_set) {
 		asus_proc_add(PROC_DISP, &proc_write_disp, &proc_read_disp, mode, device);
-
 	}
 
 	return 0;
@@ -883,10 +914,7 @@ static int __init asus_hotk_add_fs(struct acpi_device *device)
 
 static int asus_hotk_remove_fs(struct acpi_device* device)
 {
-	struct asus_hotk* hotk = acpi_driver_data(device);
-
-
-	if(acpi_device_dir(device)){
+	if(acpi_device_dir(device)) {
 		remove_proc_entry(PROC_INFO,acpi_device_dir(device));
 		if (hotk->methods->mt_wled)
 			remove_proc_entry(PROC_WLED,acpi_device_dir(device));
@@ -894,11 +922,12 @@ static int asus_hotk_remove_fs(struct acpi_device* device)
 			remove_proc_entry(PROC_MLED,acpi_device_dir(device));
 		if (hotk->methods->mt_tled)
 			remove_proc_entry(PROC_TLED,acpi_device_dir(device));
-		if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) 
+		if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status)
 			remove_proc_entry(PROC_LCD, acpi_device_dir(device));
-		if ((hotk->methods->brightness_up && hotk->methods->brightness_down) || (hotk->methods->brightness_get && hotk->methods->brightness_get)) 
+		if ((hotk->methods->brightness_up && hotk->methods->brightness_down) ||
+		    (hotk->methods->brightness_get && hotk->methods->brightness_set))
 			remove_proc_entry(PROC_BRN, acpi_device_dir(device));
-		if (hotk->methods->display_set) 
+		if (hotk->methods->display_set)
 			remove_proc_entry(PROC_DISP, acpi_device_dir(device));
 	}
 	return 0;
@@ -907,11 +936,7 @@ static int asus_hotk_remove_fs(struct acpi_device* device)
 
 static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
 {
-	/* TODO Find a better way to handle events count. Here, in data, we receive
-	 * the hotk, so we can do anything!
-	 */
-	struct asus_hotk *hotk = (struct asus_hotk *) data;
-
+	/* TODO Find a better way to handle events count.*/
 	if (!hotk)
 		return;
 
@@ -931,7 +956,7 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
  * This function is used to initialize the hotk with right values. In this
  * method, we can make all the detection we want, and modify the hotk struct
  */
-static int __init asus_hotk_get_info(struct asus_hotk *hotk)
+static int __init asus_hotk_get_info(void)
 {
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 	struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -998,11 +1023,19 @@ static int __init asus_hotk_get_info(struct asus_hotk *hotk)
 		hotk->model = L3C;
 	else if (strncmp(model->string.pointer, "L8L", 3) == 0)
 		hotk->model = L8L;
+	else if (strncmp(model->string.pointer, "L4R", 3) == 0)
+		hotk->model = L4R;
+	else if (strncmp(model->string.pointer, "M6N", 3) == 0)
+		hotk->model = M6N;
+	else if (strncmp(model->string.pointer, "M6R", 3) == 0)
+		hotk->model = M6R;
 	else if (strncmp(model->string.pointer, "M2N", 3) == 0 ||
 		 strncmp(model->string.pointer, "M3N", 3) == 0 ||
+		 strncmp(model->string.pointer, "M5N", 3) == 0 ||
 		 strncmp(model->string.pointer, "M6N", 3) == 0 ||
 		 strncmp(model->string.pointer, "S1N", 3) == 0 ||
-		 strncmp(model->string.pointer, "S5N", 3) == 0)
+		 strncmp(model->string.pointer, "S5N", 3) == 0 ||
+                 strncmp(model->string.pointer, "W1N", 3) == 0)
 		hotk->model = xxN;
 	else if (strncmp(model->string.pointer, "M1", 2) == 0)
 		hotk->model = M1A;
@@ -1025,7 +1058,6 @@ static int __init asus_hotk_get_info(struct asus_hotk *hotk)
 		hotk->model = L5x;
 
 	if (hotk->model == END_MODEL) {
-		/* By default use the same values, as I don't know others */
 		printk("unsupported, trying default values, supply the "
 		       "developers with your DSDT\n");
 		hotk->model = M2E;
@@ -1040,16 +1072,14 @@ static int __init asus_hotk_get_info(struct asus_hotk *hotk)
 		hotk->methods->lcd_status = NULL; 
 	/* L2B is similar enough to L3C to use its settings, with this only 
 	   exception */
-	else if (strncmp(model->string.pointer, "S5N", 3) == 0)
+	else if (strncmp(model->string.pointer, "S5N", 3) == 0 ||
+		 strncmp(model->string.pointer, "M5N", 3) == 0)
 		hotk->methods->mt_mled = NULL; 
-	/* S5N has no MLED */
-	else if (strncmp(model->string.pointer, "M6N", 3) == 0) {
-		hotk->methods->display_get = NULL; //TODO
-		hotk->methods->lcd_status = "\\_SB.BKLT";
-		hotk->methods->mt_wled = "WLED";
-		hotk->methods->wled_status = "\\_SB.PCI0.SBRG.SG13";
-	/* M6N differs slightly and has a usable WLED */
-	}
+	/* S5N and M5N have no MLED */
+	else if (strncmp(model->string.pointer, "M2N", 3) == 0 ||
+		 strncmp(model->string.pointer, "W1N", 3) == 0)
+		hotk->methods->mt_wled = "WLED"; 
+	/* M2N and W1N have a usable WLED */
 	else if (asus_info) {
 		if (strncmp(asus_info->oem_table_id, "L1", 2) == 0)
 			hotk->methods->mled_status = NULL;
@@ -1062,20 +1092,16 @@ static int __init asus_hotk_get_info(struct asus_hotk *hotk)
 }
 
 
-
-static int __init asus_hotk_check(struct asus_hotk *hotk)
+static int __init asus_hotk_check(void)
 {
 	int result = 0;
 
-	if (!hotk)
-		return(-EINVAL);
-
 	result = acpi_bus_get_status(hotk->device);
 	if (result)
 		return(result);
 
 	if (hotk->device->status.present) {
-		result = asus_hotk_get_info(hotk);
+		result = asus_hotk_get_info();
 	} else {
 		printk(KERN_ERR "  Hotkey device not present, aborting\n");
 		return(-EINVAL);
@@ -1085,10 +1111,8 @@ static int __init asus_hotk_check(struct asus_hotk *hotk)
 }
 
 
-
 static int __init asus_hotk_add(struct acpi_device *device)
 {
-	struct asus_hotk *hotk = NULL;
 	acpi_status status = AE_OK;
 	int result;
 
@@ -1111,7 +1135,7 @@ static int __init asus_hotk_add(struct acpi_device *device)
 	hotk->device = device;
 
 
-	result = asus_hotk_check(hotk);
+	result = asus_hotk_check();
 	if (result)
 		goto end;
 
@@ -1152,16 +1176,14 @@ static int __init asus_hotk_add(struct acpi_device *device)
 	return(result);
 }
 
+
 static int asus_hotk_remove(struct acpi_device *device, int type)
 {
 	acpi_status status = 0;
-	struct asus_hotk *hotk = NULL;
 
 	if (!device || !acpi_driver_data(device))
 		return(-EINVAL);
 
-	hotk = (struct asus_hotk *) acpi_driver_data(device);
-
 	status = acpi_remove_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY,
 					    asus_hotk_notify);
 	if (ACPI_FAILURE(status))
@@ -1179,20 +1201,24 @@ static int __init asus_acpi_init(void)
 {
 	int result;
 
+	if (acpi_disabled)
+		return -ENODEV;
+
 	asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir);
 	if (!asus_proc_dir) {
 		printk(KERN_ERR "Asus ACPI: Unable to create /proc entry\n");
-		return(-ENODEV);
+		return -ENODEV;
 	}
 	asus_proc_dir->owner = THIS_MODULE;
 
 	result = acpi_bus_register_driver(&asus_hotk_driver);
-	if (result < 0) {
+	if (result < 1) {
+		acpi_bus_unregister_driver(&asus_hotk_driver);
 		remove_proc_entry(PROC_ASUS, acpi_root_dir);
-		return(-ENODEV);
+		return -ENODEV;
 	}
 
-	return(0);
+	return 0;
 }
 
 
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index 9cf61ba9d..4c010e7f1 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -2,7 +2,9 @@
  *  blacklist.c
  *
  *  Check to see if the given machine has a known bad ACPI BIOS
+ *  or if the BIOS is too old.
  *
+ *  Copyright (C) 2004 Len Brown <len.brown@intel.com>
  *  Copyright (C) 2002 Andy Grover <andrew.grover@intel.com>
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -30,6 +32,7 @@
 #include <linux/init.h>
 #include <linux/acpi.h>
 #include <acpi/acpi_bus.h>
+#include <linux/dmi.h>
 
 enum acpi_blacklist_predicates
 {
@@ -56,20 +59,6 @@ struct acpi_blacklist_item
  */
 static struct acpi_blacklist_item acpi_blacklist[] __initdata =
 {
-	/* Portege 7020, BIOS 8.10 */
-	{"TOSHIB", "7020CT  ", 0x19991112, ACPI_DSDT, all_versions, "Implicit Return", 0},
-	/* Portege 4030 */
-	{"TOSHIB", "4030    ", 0x19991112, ACPI_DSDT, all_versions, "Implicit Return", 0},
-	/* Portege 310/320, BIOS 7.1 */
-	{"TOSHIB", "310     ", 0x19990511, ACPI_DSDT, all_versions, "Implicit Return", 0},
-	/* Seattle 2, old bios rev. */
-	{"INTEL ", "440BX   ", 0x00001000, ACPI_DSDT, less_than_or_equal, "Field beyond end of region", 0},
-	/* ASUS K7M */
-	{"ASUS  ", "K7M     ", 0x00001000, ACPI_DSDT, less_than_or_equal, "Field beyond end of region", 0},
-	/* Intel 810 Motherboard? */
-	{"MNTRAL", "MO81010A", 0x00000012, ACPI_DSDT, less_than_or_equal, "Field beyond end of region", 0},
-	/* Compaq Presario 711FR */
-	{"COMAPQ", "EAGLES", 0x06040000, ACPI_DSDT, less_than_or_equal, "SCI issues (C2 disabled)", 0},
 	/* Compaq Presario 1700 */
 	{"PTLTD ", "  DSDT  ", 0x06040000, ACPI_DSDT, less_than_or_equal, "Multiple problems", 1},
 	/* Sony FX120, FX140, FX150? */
@@ -84,6 +73,45 @@ static struct acpi_blacklist_item acpi_blacklist[] __initdata =
 };
 
 
+#if	CONFIG_ACPI_BLACKLIST_YEAR
+
+static int __init
+blacklist_by_year(void)
+{
+	int year;
+	char *s = dmi_get_system_info(DMI_BIOS_DATE);
+
+	if (!s)
+		return 0;
+	if (!*s)
+		return 0;
+
+	s = strrchr(s, '/');
+	if (!s)
+		return 0;
+
+	s += 1;
+
+	year = simple_strtoul(s,NULL,0); 
+
+	if (year < 100) {		/* 2-digit year */
+		year += 1900;
+		if (year < 1996)	/* no dates < spec 1.0 */
+			year += 100;
+	}
+
+	if (year < CONFIG_ACPI_BLACKLIST_YEAR) {
+		printk(KERN_ERR PREFIX "BIOS age (%d) fails cutoff (%d), " 
+			"acpi=force is required to enable ACPI\n",
+			year, CONFIG_ACPI_BLACKLIST_YEAR);
+		return 1;
+	}
+	return 0;
+}
+#else
+static inline int blacklist_by_year(void) { return 0; }
+#endif
+
 int __init
 acpi_blacklisted(void)
 {
@@ -134,6 +162,8 @@ acpi_blacklisted(void)
 		}
 	}
 
+	blacklisted += blacklist_by_year();
+
 	return blacklisted;
 }
 
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 51362331a..4c303e19e 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -590,14 +590,20 @@ acpi_bus_init_irq (void)
 }
 
 
-static int __init
-acpi_bus_init (void)
+void __init
+acpi_early_init (void)
 {
-	int			result = 0;
 	acpi_status		status = AE_OK;
 	struct acpi_buffer	buffer = {sizeof(acpi_fadt), &acpi_fadt};
 
-	ACPI_FUNCTION_TRACE("acpi_bus_init");
+	ACPI_FUNCTION_TRACE("acpi_early_init");
+
+	if (acpi_disabled)
+		return;
+
+	/* enable workarounds, unless strict ACPI spec. compliance */
+	if (!acpi_strict)
+		acpi_gbl_enable_interpreter_slack = TRUE;
 
 	status = acpi_initialize_subsystem();
 	if (ACPI_FAILURE(status)) {
@@ -617,7 +623,7 @@ acpi_bus_init (void)
 	status = acpi_get_table(ACPI_TABLE_FADT, 1, &buffer);
 	if (ACPI_FAILURE(status)) {
 		printk(KERN_ERR PREFIX "Unable to get the FADT\n");
-		goto error1;
+		goto error0;
 	}
 
 #ifdef CONFIG_X86
@@ -640,12 +646,40 @@ acpi_bus_init (void)
 	}
 #endif
 
-	status = acpi_enable_subsystem(ACPI_FULL_INITIALIZATION);
+	status = acpi_enable_subsystem(~(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE));
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_ERR PREFIX "Unable to enable ACPI\n");
+		goto error0;
+	}
+
+	return;
+
+error0:
+	disable_acpi();
+	return;
+}
+
+static int __init
+acpi_bus_init (void)
+{
+	int			result = 0;
+	acpi_status		status = AE_OK;
+	extern acpi_status	acpi_os_initialize1(void);
+
+	ACPI_FUNCTION_TRACE("acpi_bus_init");
+
+	status = acpi_os_initialize1();
+
+	status = acpi_enable_subsystem(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE);
 	if (ACPI_FAILURE(status)) {
 		printk(KERN_ERR PREFIX "Unable to start the ACPI Interpreter\n");
 		goto error1;
 	}
 
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_ERR PREFIX "Unable to initialize ACPI OS objects\n");
+		goto error1;
+	}
 #ifdef CONFIG_ACPI_EC
 	/*
 	 * ACPI 2.0 requires the EC driver to be loaded and work before
@@ -693,7 +727,6 @@ acpi_bus_init (void)
 	/* Mimic structured exception handling */
 error1:
 	acpi_terminate();
-error0:
 	return_VALUE(-ENODEV);
 }
 
@@ -708,9 +741,6 @@ static int __init acpi_init (void)
 	printk(KERN_INFO PREFIX "Subsystem revision %08x\n",
 		ACPI_CA_VERSION);
 
-	/* Initial core debug level excludes drivers, so include them now */
-	acpi_set_debug(ACPI_DEBUG_LOW);
-
 	if (acpi_disabled) {
 		printk(KERN_INFO PREFIX "Interpreter disabled.\n");
 		return -ENODEV;
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index a5b45095d..b632b93af 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -456,6 +456,15 @@ acpi_button_add (
 		goto end;
 	}
 
+	if (device->wakeup.flags.valid) {
+		/* Button's GPE is run-wake GPE */
+		acpi_set_gpe_type(device->wakeup.gpe_device, 
+			device->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN);
+		acpi_enable_gpe(device->wakeup.gpe_device, 
+			device->wakeup.gpe_number, ACPI_NOT_ISR);
+		device->wakeup.state.enabled = 1;
+	}
+
 	printk(KERN_INFO PREFIX "%s [%s]\n", 
 		acpi_device_name(device), acpi_device_bid(device));
 
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c
index 585f59db4..9fb8caedb 100644
--- a/drivers/acpi/debug.c
+++ b/drivers/acpi/debug.c
@@ -4,6 +4,7 @@
 
 #include <linux/proc_fs.h>
 #include <linux/init.h>
+#include <linux/moduleparam.h>
 #include <asm/uaccess.h>
 #include <acpi/acpi_drivers.h>
 
@@ -13,6 +14,81 @@ ACPI_MODULE_NAME		("debug")
 #define ACPI_SYSTEM_FILE_DEBUG_LAYER	"debug_layer"
 #define ACPI_SYSTEM_FILE_DEBUG_LEVEL	"debug_level"
 
+#ifdef MODULE_PARAM_PREFIX
+#undef MODULE_PARAM_PREFIX
+#endif
+
+#define MODULE_PARAM_PREFIX
+module_param(acpi_dbg_layer, uint, 0400);
+module_param(acpi_dbg_level, uint, 0400);
+
+struct acpi_dlayer {
+	const char *name;
+	unsigned long value;
+};
+struct acpi_dlevel {
+	const char *name;
+	unsigned long value;
+};
+#define ACPI_DEBUG_INIT(v)	{ .name = #v, .value = v }
+
+const struct acpi_dlayer acpi_debug_layers[] =
+{
+	ACPI_DEBUG_INIT(ACPI_UTILITIES),
+	ACPI_DEBUG_INIT(ACPI_HARDWARE),
+	ACPI_DEBUG_INIT(ACPI_EVENTS),
+	ACPI_DEBUG_INIT(ACPI_TABLES),
+	ACPI_DEBUG_INIT(ACPI_NAMESPACE),
+	ACPI_DEBUG_INIT(ACPI_PARSER),
+	ACPI_DEBUG_INIT(ACPI_DISPATCHER),
+	ACPI_DEBUG_INIT(ACPI_EXECUTER),
+	ACPI_DEBUG_INIT(ACPI_RESOURCES),
+	ACPI_DEBUG_INIT(ACPI_CA_DEBUGGER),
+	ACPI_DEBUG_INIT(ACPI_OS_SERVICES),
+	ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER),
+	ACPI_DEBUG_INIT(ACPI_COMPILER),
+	ACPI_DEBUG_INIT(ACPI_TOOLS),
+};
+
+const struct acpi_dlevel acpi_debug_levels[] =
+{
+	ACPI_DEBUG_INIT(ACPI_LV_ERROR),
+	ACPI_DEBUG_INIT(ACPI_LV_WARN),
+	ACPI_DEBUG_INIT(ACPI_LV_INIT),
+	ACPI_DEBUG_INIT(ACPI_LV_DEBUG_OBJECT),
+	ACPI_DEBUG_INIT(ACPI_LV_INFO),
+
+	ACPI_DEBUG_INIT(ACPI_LV_INIT_NAMES),
+	ACPI_DEBUG_INIT(ACPI_LV_PARSE),
+	ACPI_DEBUG_INIT(ACPI_LV_LOAD),
+	ACPI_DEBUG_INIT(ACPI_LV_DISPATCH),
+	ACPI_DEBUG_INIT(ACPI_LV_EXEC),
+	ACPI_DEBUG_INIT(ACPI_LV_NAMES),
+	ACPI_DEBUG_INIT(ACPI_LV_OPREGION),
+	ACPI_DEBUG_INIT(ACPI_LV_BFIELD),
+	ACPI_DEBUG_INIT(ACPI_LV_TABLES),
+	ACPI_DEBUG_INIT(ACPI_LV_VALUES),
+	ACPI_DEBUG_INIT(ACPI_LV_OBJECTS),
+	ACPI_DEBUG_INIT(ACPI_LV_RESOURCES),
+	ACPI_DEBUG_INIT(ACPI_LV_USER_REQUESTS),
+	ACPI_DEBUG_INIT(ACPI_LV_PACKAGE),
+
+	ACPI_DEBUG_INIT(ACPI_LV_ALLOCATIONS),
+	ACPI_DEBUG_INIT(ACPI_LV_FUNCTIONS),
+	ACPI_DEBUG_INIT(ACPI_LV_OPTIMIZATIONS),
+
+	ACPI_DEBUG_INIT(ACPI_LV_MUTEX),
+	ACPI_DEBUG_INIT(ACPI_LV_THREADS),
+	ACPI_DEBUG_INIT(ACPI_LV_IO),
+	ACPI_DEBUG_INIT(ACPI_LV_INTERRUPTS),
+
+	ACPI_DEBUG_INIT(ACPI_LV_AML_DISASSEMBLE),
+	ACPI_DEBUG_INIT(ACPI_LV_VERBOSE_INFO),
+	ACPI_DEBUG_INIT(ACPI_LV_FULL_TABLES),
+	ACPI_DEBUG_INIT(ACPI_LV_EVENTS),             
+};
+#define NUM_OF(v)	( sizeof(v)/sizeof(v[0]) )
+
 static int
 acpi_system_read_debug (
 	char			*page,
@@ -24,16 +100,41 @@ acpi_system_read_debug (
 {
 	char			*p = page;
 	int 			size = 0;
+	int			i;
 
 	if (off != 0)
 		goto end;
 
+	p += sprintf(p, "%-25s\tHex        SET\n", "Description");
+
 	switch ((unsigned long) data) {
 	case 0:
-		p += sprintf(p, "0x%08x\n", acpi_dbg_layer);
+		for (i = 0; i < NUM_OF(acpi_debug_layers); i++) {
+			p += sprintf(p, "%-25s\t0x%08lX [%c]\n",
+				acpi_debug_layers[i].name,
+				acpi_debug_layers[i].value,
+				(acpi_dbg_layer & acpi_debug_layers[i].value) ?
+				'*' : ' ');
+		}
+		p += sprintf(p, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS",
+			ACPI_ALL_DRIVERS,
+			(acpi_dbg_layer & ACPI_ALL_DRIVERS) == ACPI_ALL_DRIVERS?
+			'*' : (acpi_dbg_layer & ACPI_ALL_DRIVERS) == 0 ?
+			' ' : '-');
+		p += sprintf(p,
+			"--\ndebug_layer = 0x%08X (* = enabled, - = partial)\n",
+			acpi_dbg_layer);
 		break;
 	case 1:
-		p += sprintf(p, "0x%08x\n", acpi_dbg_level);
+		for (i = 0; i < NUM_OF(acpi_debug_levels); i++) {
+			p += sprintf(p, "%-25s\t0x%08lX [%c]\n",
+				acpi_debug_levels[i].name,
+				acpi_debug_levels[i].value,
+				(acpi_dbg_level & acpi_debug_levels[i].value) ?
+				'*' : ' ');
+		}
+		p += sprintf(p, "--\ndebug_level = 0x%08X (* = enabled)\n",
+				acpi_dbg_level);
 		break;
 	default:
 		p += sprintf(p, "Invalid debug option\n");
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
index 360fbe5e8..4fd369018 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -58,15 +58,12 @@
  *
  * FUNCTION:    acpi_ds_parse_method
  *
- * PARAMETERS:  obj_handle      - Node of the method
- *              Level           - Current nesting level
- *              Context         - Points to a method counter
- *              return_value    - Not used
+ * PARAMETERS:  obj_handle      - Method node
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Call the parser and parse the AML that is
- *              associated with the method.
+ * DESCRIPTION: Call the parser and parse the AML that is associated with the
+ *              method.
  *
  * MUTEX:       Assumes parser is locked
  *
@@ -145,8 +142,9 @@ acpi_ds_parse_method (
 		return_ACPI_STATUS (AE_NO_MEMORY);
 	}
 
-	status = acpi_ds_init_aml_walk (walk_state, op, node, obj_desc->method.aml_start,
-			  obj_desc->method.aml_length, NULL, NULL, 1);
+	status = acpi_ds_init_aml_walk (walk_state, op, node,
+			  obj_desc->method.aml_start,
+			  obj_desc->method.aml_length, NULL, 1);
 	if (ACPI_FAILURE (status)) {
 		acpi_ds_delete_walk_state (walk_state);
 		return_ACPI_STATUS (status);
@@ -190,8 +188,6 @@ acpi_ds_parse_method (
  *              increments the thread count, and waits at the method semaphore
  *              for clearance to execute.
  *
- * MUTEX:       Locks/unlocks parser.
- *
  ******************************************************************************/
 
 acpi_status
@@ -250,7 +246,8 @@ acpi_ds_begin_method_execution (
  *
  * FUNCTION:    acpi_ds_call_control_method
  *
- * PARAMETERS:  walk_state          - Current state of the walk
+ * PARAMETERS:  Thread              - Info for this thread
+ *              this_walk_state     - Current walk state
  *              Op                  - Current Op to be walked
  *
  * RETURN:      Status
@@ -267,8 +264,9 @@ acpi_ds_call_control_method (
 {
 	acpi_status                     status;
 	struct acpi_namespace_node      *method_node;
-	union acpi_operand_object       *obj_desc;
 	struct acpi_walk_state          *next_walk_state;
+	union acpi_operand_object       *obj_desc;
+	struct acpi_parameter_info      info;
 	u32                             i;
 
 
@@ -309,7 +307,6 @@ acpi_ds_call_control_method (
 			return_ACPI_STATUS (AE_NO_MEMORY);
 		}
 
-
 		/* Create and init a Root Node */
 
 		op = acpi_ps_create_scope_op ();
@@ -320,7 +317,7 @@ acpi_ds_call_control_method (
 
 		status = acpi_ds_init_aml_walk (next_walk_state, op, method_node,
 				  obj_desc->method.aml_start, obj_desc->method.aml_length,
-				  NULL, NULL, 1);
+				  NULL, 1);
 		if (ACPI_FAILURE (status)) {
 			acpi_ds_delete_walk_state (next_walk_state);
 			goto cleanup;
@@ -348,9 +345,12 @@ acpi_ds_call_control_method (
 	 */
 	this_walk_state->operands [this_walk_state->num_operands] = NULL;
 
+	info.parameters = &this_walk_state->operands[0];
+	info.parameter_type = ACPI_PARAM_ARGS;
+
 	status = acpi_ds_init_aml_walk (next_walk_state, NULL, method_node,
 			  obj_desc->method.aml_start, obj_desc->method.aml_length,
-			  &this_walk_state->operands[0], NULL, 3);
+			  &info, 3);
 	if (ACPI_FAILURE (status)) {
 		goto cleanup;
 	}
@@ -382,7 +382,7 @@ acpi_ds_call_control_method (
 	/* On error, we must delete the new walk state */
 
 cleanup:
-	if (next_walk_state->method_desc) {
+	if (next_walk_state && (next_walk_state->method_desc)) {
 		/* Decrement the thread count on the method parse tree */
 
 	   next_walk_state->method_desc->method.thread_count--;
@@ -397,12 +397,13 @@ cleanup:
  *
  * FUNCTION:    acpi_ds_restart_control_method
  *
- * PARAMETERS:  walk_state          - State of the method when it was preempted
- *              Op                  - Pointer to new current op
+ * PARAMETERS:  walk_state          - State for preempted method (caller)
+ *              return_desc         - Return value from the called method
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Restart a method that was preempted
+ * DESCRIPTION: Restart a method that was preempted by another (nested) method
+ *              invocation.  Handle the return value (if any) from the callee.
  *
  ******************************************************************************/
 
@@ -417,17 +418,35 @@ acpi_ds_restart_control_method (
 	ACPI_FUNCTION_TRACE_PTR ("ds_restart_control_method", walk_state);
 
 
+	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+		"****Restart [%4.4s] Op %p return_value_from_callee %p\n",
+		(char *) &walk_state->method_node->name, walk_state->method_call_op,
+		return_desc));
+
+	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+		"    return_from_this_method_used?=%X res_stack %p Walk %p\n",
+		walk_state->return_used,
+		walk_state->results, walk_state));
+
+	/* Did the called method return a value? */
+
 	if (return_desc) {
+		/* Are we actually going to use the return value? */
+
 		if (walk_state->return_used) {
-			/*
-			 * Get the return value (if any) from the previous method.
-			 * NULL if no return value
-			 */
+			/* Save the return value from the previous method */
+
 			status = acpi_ds_result_push (return_desc, walk_state);
 			if (ACPI_FAILURE (status)) {
 				acpi_ut_remove_reference (return_desc);
 				return_ACPI_STATUS (status);
 			}
+
+			/*
+			 * Save as THIS method's return value in case it is returned
+			 * immediately to yet another method
+			 */
+			walk_state->return_desc = return_desc;
 		}
 		else {
 			/*
@@ -438,11 +457,6 @@ acpi_ds_restart_control_method (
 		}
 	}
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
-		"Method=%p Return=%p return_used?=%X res_stack=%p State=%p\n",
-		walk_state->method_call_op, return_desc, walk_state->return_used,
-		walk_state->results, walk_state));
-
 	return_ACPI_STATUS (AE_OK);
 }
 
diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c
index e1926534b..befe750a7 100644
--- a/drivers/acpi/dispatcher/dsmthdat.c
+++ b/drivers/acpi/dispatcher/dsmthdat.c
@@ -656,11 +656,13 @@ acpi_ds_store_object_to_local (
 						new_obj_desc, current_obj_desc));
 
 				/*
-				 * Store this object to the Node
-				 * (perform the indirect store)
+				 * Store this object to the Node (perform the indirect store)
+				 * NOTE: No implicit conversion is performed, as per the ACPI
+				 * specification rules on storing to Locals/Args.
 				 */
 				status = acpi_ex_store_object_to_node (new_obj_desc,
-						 current_obj_desc->reference.object, walk_state);
+						 current_obj_desc->reference.object, walk_state,
+						 ACPI_NO_IMPLICIT_CONVERSION);
 
 				/* Remove local reference if we copied the object above */
 
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c
index e0a313f57..68084760e 100644
--- a/drivers/acpi/dispatcher/dsopcode.c
+++ b/drivers/acpi/dispatcher/dsopcode.c
@@ -79,7 +79,6 @@ acpi_ds_execute_arguments (
 	acpi_status                     status;
 	union acpi_parse_object         *op;
 	struct acpi_walk_state          *walk_state;
-	union acpi_parse_object         *arg;
 
 
 	ACPI_FUNCTION_TRACE ("ds_execute_arguments");
@@ -105,7 +104,7 @@ acpi_ds_execute_arguments (
 	}
 
 	status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start,
-			  aml_length, NULL, NULL, 1);
+			  aml_length, NULL, 1);
 	if (ACPI_FAILURE (status)) {
 		acpi_ds_delete_walk_state (walk_state);
 		return_ACPI_STATUS (status);
@@ -126,9 +125,7 @@ acpi_ds_execute_arguments (
 
 	/* Get and init the Op created above */
 
-	arg = op->common.value.arg;
 	op->common.node = node;
-	arg->common.node = node;
 	acpi_ps_delete_parse_tree (op);
 
 	/* Evaluate the deferred arguments */
@@ -150,7 +147,7 @@ acpi_ds_execute_arguments (
 	/* Execute the opcode and arguments */
 
 	status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start,
-			  aml_length, NULL, NULL, 3);
+			  aml_length, NULL, 3);
 	if (ACPI_FAILURE (status)) {
 		acpi_ds_delete_walk_state (walk_state);
 		return_ACPI_STATUS (status);
diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c
index 5c6a37e05..24462789a 100644
--- a/drivers/acpi/dispatcher/dsutils.c
+++ b/drivers/acpi/dispatcher/dsutils.c
@@ -60,11 +60,10 @@
  *
  * FUNCTION:    acpi_ds_is_result_used
  *
- * PARAMETERS:  Op
- *              result_obj
- *              walk_state
+ * PARAMETERS:  Op                  - Current Op
+ *              walk_state          - Current State
  *
- * RETURN:      Status
+ * RETURN:      TRUE if result is used, FALSE otherwise
  *
  * DESCRIPTION: Check if a result object will be used by the parent
  *
@@ -89,18 +88,39 @@ acpi_ds_is_result_used (
 	}
 
 	/*
-	 * If there is no parent, the result can't possibly be used!
-	 * (An executing method typically has no parent, since each
-	 * method is parsed separately)  However, a method that is
-	 * invoked from another method has a parent.
+	 * If there is no parent, we are executing at the method level.
+	 * An executing method typically has no parent, since each method
+	 * is parsed separately.
 	 */
 	if (!op->common.parent) {
+		/*
+		 * If this is the last statement in the method, we know it is not a
+		 * Return() operator (would not come here.) The following code is the
+		 * optional support for a so-called "implicit return". Some AML code
+		 * assumes that the last value of the method is "implicitly" returned
+		 * to the caller. Just save the last result as the return value.
+		 * NOTE: this is optional because the ASL language does not actually
+		 * support this behavior.
+		 */
+		if ((acpi_gbl_enable_interpreter_slack) &&
+			(walk_state->parser_state.aml >= walk_state->parser_state.aml_end)) {
+			ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+					"Result of [%s] will be implicitly returned\n",
+					acpi_ps_get_opcode_name (op->common.aml_opcode)));
+
+			/* Use the top of the result stack as the implicit return value */
+
+			walk_state->return_desc = walk_state->results->results.obj_desc[0];
+			return_VALUE (TRUE);
+		}
+
+		/* No parent, the return value cannot possibly be used */
+
 		return_VALUE (FALSE);
 	}
 
-	/*
-	 * Get info on the parent.  The root Op is AML_SCOPE
-	 */
+	/* Get info on the parent. The root_op is AML_SCOPE */
+
 	parent_info = acpi_ps_get_opcode_info (op->common.parent->common.aml_opcode);
 	if (parent_info->class == AML_CLASS_UNKNOWN) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown parent opcode. Op=%p\n", op));
@@ -204,9 +224,9 @@ result_not_used:
  *
  * FUNCTION:    acpi_ds_delete_result_if_not_used
  *
- * PARAMETERS:  Op
- *              result_obj
- *              walk_state
+ * PARAMETERS:  Op              - Current parse Op
+ *              result_obj      - Result of the operation
+ *              walk_state      - Current state
  *
  * RETURN:      Status
  *
@@ -338,8 +358,9 @@ acpi_ds_clear_operands (
  *
  * FUNCTION:    acpi_ds_create_operand
  *
- * PARAMETERS:  walk_state
- *              Arg
+ * PARAMETERS:  walk_state      - Current walk state
+ *              Arg             - Parse object for the argument
+ *              arg_index       - Which argument (zero based)
  *
  * RETURN:      Status
  *
diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c
index 409aa6e95..9c0d99e09 100644
--- a/drivers/acpi/dispatcher/dswload.c
+++ b/drivers/acpi/dispatcher/dswload.c
@@ -50,6 +50,9 @@
 #include <acpi/acnamesp.h>
 #include <acpi/acevents.h>
 
+#ifdef _ACPI_ASL_COMPILER
+#include <acpi/acdisasm.h>
+#endif
 
 #define _COMPONENT          ACPI_DISPATCHER
 	 ACPI_MODULE_NAME    ("dswload")
@@ -180,7 +183,17 @@ acpi_ds_load1_begin_op (
 		status = acpi_ns_lookup (walk_state->scope_info, path, object_type,
 				  ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node));
 		if (ACPI_FAILURE (status)) {
+#ifdef _ACPI_ASL_COMPILER
+			if (status == AE_NOT_FOUND) {
+				acpi_dm_add_to_external_list (path);
+				status = AE_OK;
+			}
+			else {
+				ACPI_REPORT_NSERROR (path, status);
+			}
+#else
 			ACPI_REPORT_NSERROR (path, status);
+#endif
 			return (status);
 		}
 
@@ -529,7 +542,16 @@ acpi_ds_load2_begin_op (
 		status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type,
 				  ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node));
 		if (ACPI_FAILURE (status)) {
+#ifdef _ACPI_ASL_COMPILER
+			if (status == AE_NOT_FOUND) {
+				status = AE_OK;
+			}
+			else {
+				ACPI_REPORT_NSERROR (buffer_ptr, status);
+			}
+#else
 			ACPI_REPORT_NSERROR (buffer_ptr, status);
+#endif
 			return_ACPI_STATUS (status);
 		}
 		/*
diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c
index 2b3956226..81c6b46ac 100644
--- a/drivers/acpi/dispatcher/dswstate.c
+++ b/drivers/acpi/dispatcher/dswstate.c
@@ -906,8 +906,7 @@ acpi_ds_init_aml_walk (
 	struct acpi_namespace_node      *method_node,
 	u8                              *aml_start,
 	u32                             aml_length,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_obj_desc,
+	struct acpi_parameter_info      *info,
 	u32                             pass_number)
 {
 	acpi_status                     status;
@@ -926,8 +925,17 @@ acpi_ds_init_aml_walk (
 	/* The next_op of the next_walk will be the beginning of the method */
 
 	walk_state->next_op             = NULL;
-	walk_state->params              = params;
-	walk_state->caller_return_desc  = return_obj_desc;
+
+	if (info) {
+		if (info->parameter_type == ACPI_PARAM_GPE) {
+			walk_state->gpe_event_info = ACPI_CAST_PTR (struct acpi_gpe_event_info,
+					   info->parameters);
+		}
+		else {
+			walk_state->params              = info->parameters;
+			walk_state->caller_return_desc  = &info->return_object;
+		}
+	}
 
 	status = acpi_ps_init_scope (&walk_state->parser_state, op);
 	if (ACPI_FAILURE (status)) {
@@ -949,7 +957,7 @@ acpi_ds_init_aml_walk (
 
 		/* Init the method arguments */
 
-		status = acpi_ds_method_data_init_args (params, ACPI_METHOD_NUM_ARGS, walk_state);
+		status = acpi_ds_method_data_init_args (walk_state->params, ACPI_METHOD_NUM_ARGS, walk_state);
 		if (ACPI_FAILURE (status)) {
 			return_ACPI_STATUS (status);
 		}
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 56bb801e2..d1419145e 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -381,7 +381,7 @@ end:
 	acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
 }
 
-static void
+static u32
 acpi_ec_gpe_handler (
 	void			*data)
 {
@@ -389,12 +389,17 @@ acpi_ec_gpe_handler (
 	struct acpi_ec		*ec = (struct acpi_ec *) data;
 
 	if (!ec)
-		return;
+		return ACPI_INTERRUPT_NOT_HANDLED;
 
 	acpi_disable_gpe(NULL, ec->gpe_bit, ACPI_ISR);
 
 	status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
 		acpi_ec_gpe_query, ec);
+
+	if (status == AE_OK)
+		return ACPI_INTERRUPT_HANDLED;
+	else
+		return ACPI_INTERRUPT_NOT_HANDLED;
 }
 
 /* --------------------------------------------------------------------------
@@ -729,6 +734,8 @@ acpi_ec_start (
 	if (ACPI_FAILURE(status)) {
 		return_VALUE(-ENODEV);
 	}
+	acpi_set_gpe_type (NULL, ec->gpe_bit, ACPI_GPE_TYPE_RUNTIME);
+	acpi_enable_gpe (NULL, ec->gpe_bit, ACPI_NOT_ISR);
 
 	status = acpi_install_address_space_handler (ec->handle,
 			ACPI_ADR_SPACE_EC, &acpi_ec_space_handler,
@@ -814,6 +821,8 @@ acpi_ec_ecdt_probe (void)
 	if (ACPI_FAILURE(status)) {
 		goto error;
 	}
+	acpi_set_gpe_type (NULL, ec_ecdt->gpe_bit, ACPI_GPE_TYPE_RUNTIME);
+	acpi_enable_gpe (NULL, ec_ecdt->gpe_bit, ACPI_NOT_ISR);
 
 	status = acpi_install_address_space_handler (ACPI_ROOT_OBJECT,
 			ACPI_ADR_SPACE_EC, &acpi_ec_space_handler,
diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c
index abdb3a5a2..558ec7b33 100644
--- a/drivers/acpi/events/evevent.c
+++ b/drivers/acpi/events/evevent.c
@@ -50,7 +50,7 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ev_initialize
+ * FUNCTION:    acpi_ev_initialize_events
  *
  * PARAMETERS:  None
  *
@@ -61,13 +61,13 @@
  ******************************************************************************/
 
 acpi_status
-acpi_ev_initialize (
+acpi_ev_initialize_events (
 	void)
 {
 	acpi_status                     status;
 
 
-	ACPI_FUNCTION_TRACE ("ev_initialize");
+	ACPI_FUNCTION_TRACE ("ev_initialize_events");
 
 
 	/* Make sure we have ACPI tables */
@@ -104,7 +104,7 @@ acpi_ev_initialize (
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ev_handler_initialize
+ * FUNCTION:    acpi_ev_install_xrupt_handlers
  *
  * PARAMETERS:  None
  *
@@ -115,13 +115,13 @@ acpi_ev_initialize (
  ******************************************************************************/
 
 acpi_status
-acpi_ev_handler_initialize (
+acpi_ev_install_xrupt_handlers (
 	void)
 {
 	acpi_status                     status;
 
 
-	ACPI_FUNCTION_TRACE ("ev_handler_initialize");
+	ACPI_FUNCTION_TRACE ("ev_install_xrupt_handlers");
 
 
 	/* Install the SCI handler */
diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c
index 221dca54d..afb36886b 100644
--- a/drivers/acpi/events/evgpe.c
+++ b/drivers/acpi/events/evgpe.c
@@ -49,6 +49,253 @@
 	 ACPI_MODULE_NAME    ("evgpe")
 
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_set_gpe_type
+ *
+ * PARAMETERS:  gpe_event_info          - GPE to set
+ *              Type                    - New type
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Sets the new type for the GPE (wake, run, or wake/run)
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_set_gpe_type (
+	struct acpi_gpe_event_info      *gpe_event_info,
+	u8                              type)
+{
+	acpi_status                     status;
+
+
+	ACPI_FUNCTION_TRACE ("ev_set_gpe_type");
+
+
+	/* Validate type and update register enable masks */
+
+	switch (type) {
+	case ACPI_GPE_TYPE_WAKE:
+	case ACPI_GPE_TYPE_RUNTIME:
+	case ACPI_GPE_TYPE_WAKE_RUN:
+		break;
+
+	default:
+		return_ACPI_STATUS (AE_BAD_PARAMETER);
+	}
+
+	/* Disable the GPE if currently enabled */
+
+	status = acpi_ev_disable_gpe (gpe_event_info);
+
+	/* Type was validated above */
+
+	gpe_event_info->flags &= ~ACPI_GPE_TYPE_MASK; /* Clear type bits */
+	gpe_event_info->flags |= type;              /* Insert type */
+	return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_update_gpe_enable_masks
+ *
+ * PARAMETERS:  gpe_event_info          - GPE to update
+ *              Type                    - What to do: ACPI_GPE_DISABLE or
+ *                                        ACPI_GPE_ENABLE
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Updates GPE register enable masks based on the GPE type
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_update_gpe_enable_masks (
+	struct acpi_gpe_event_info      *gpe_event_info,
+	u8                              type)
+{
+	struct acpi_gpe_register_info   *gpe_register_info;
+	u8                              register_bit;
+
+
+	ACPI_FUNCTION_TRACE ("ev_update_gpe_enable_masks");
+
+
+	gpe_register_info = gpe_event_info->register_info;
+	if (!gpe_register_info) {
+		return_ACPI_STATUS (AE_NOT_EXIST);
+	}
+	register_bit = gpe_event_info->register_bit;
+
+	/* 1) Disable case.  Simply clear all enable bits */
+
+	if (type == ACPI_GPE_DISABLE) {
+		ACPI_CLEAR_BIT (gpe_register_info->enable_for_wake, register_bit);
+		ACPI_CLEAR_BIT (gpe_register_info->enable_for_run, register_bit);
+		return_ACPI_STATUS (AE_OK);
+	}
+
+	/* 2) Enable case.  Set/Clear the appropriate enable bits */
+
+	switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
+	case ACPI_GPE_TYPE_WAKE:
+		ACPI_SET_BIT   (gpe_register_info->enable_for_wake, register_bit);
+		ACPI_CLEAR_BIT (gpe_register_info->enable_for_run, register_bit);
+		break;
+
+	case ACPI_GPE_TYPE_RUNTIME:
+		ACPI_CLEAR_BIT (gpe_register_info->enable_for_wake, register_bit);
+		ACPI_SET_BIT   (gpe_register_info->enable_for_run, register_bit);
+		break;
+
+	case ACPI_GPE_TYPE_WAKE_RUN:
+		ACPI_SET_BIT   (gpe_register_info->enable_for_wake, register_bit);
+		ACPI_SET_BIT   (gpe_register_info->enable_for_run, register_bit);
+		break;
+
+	default:
+		return_ACPI_STATUS (AE_BAD_PARAMETER);
+	}
+
+	return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_enable_gpe
+ *
+ * PARAMETERS:  gpe_event_info          - GPE to enable
+ *              write_to_hardware       - Enable now, or just mark data structs
+ *                                        (WAKE GPEs should be deferred)
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Enable a GPE based on the GPE type
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_enable_gpe (
+	struct acpi_gpe_event_info      *gpe_event_info,
+	u8                              write_to_hardware)
+{
+	acpi_status                     status;
+
+
+	ACPI_FUNCTION_TRACE ("ev_enable_gpe");
+
+
+	/* Make sure HW enable masks are updated */
+
+	status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_ENABLE);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+
+	/* Mark wake-enabled or HW enable, or both */
+
+	switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
+	case ACPI_GPE_TYPE_WAKE:
+
+		ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
+		break;
+
+	case ACPI_GPE_TYPE_WAKE_RUN:
+
+		ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
+
+		/*lint -fallthrough */
+
+	case ACPI_GPE_TYPE_RUNTIME:
+
+		ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
+
+		if (write_to_hardware) {
+			/* Clear the GPE (of stale events), then enable it */
+
+			status = acpi_hw_clear_gpe (gpe_event_info);
+			if (ACPI_FAILURE (status)) {
+				return_ACPI_STATUS (status);
+			}
+
+			/* Enable the requested runtime GPE */
+
+			status = acpi_hw_write_gpe_enable_reg (gpe_event_info);
+		}
+		break;
+
+	default:
+		return_ACPI_STATUS (AE_BAD_PARAMETER);
+	}
+
+	return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_disable_gpe
+ *
+ * PARAMETERS:  gpe_event_info          - GPE to disable
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Disable a GPE based on the GPE type
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_disable_gpe (
+	struct acpi_gpe_event_info      *gpe_event_info)
+{
+	acpi_status                     status;
+
+
+	ACPI_FUNCTION_TRACE ("ev_disable_gpe");
+
+
+	if (!(gpe_event_info->flags & ACPI_GPE_ENABLE_MASK)) {
+		return_ACPI_STATUS (AE_OK);
+	}
+
+	/* Make sure HW enable masks are updated */
+
+	status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_DISABLE);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+
+	/* Mark wake-disabled or HW disable, or both */
+
+	switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
+	case ACPI_GPE_TYPE_WAKE:
+		ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
+		break;
+
+	case ACPI_GPE_TYPE_WAKE_RUN:
+		ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
+
+		/*lint -fallthrough */
+
+	case ACPI_GPE_TYPE_RUNTIME:
+
+		/* Disable the requested runtime GPE */
+
+		ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
+		status = acpi_hw_write_gpe_enable_reg (gpe_event_info);
+		break;
+
+	default:
+		return_ACPI_STATUS (AE_BAD_PARAMETER);
+	}
+
+	return_ACPI_STATUS (AE_OK);
+}
+
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ev_get_gpe_event_info
@@ -139,11 +386,12 @@ acpi_ev_gpe_detect (
 	u32                             int_status = ACPI_INTERRUPT_NOT_HANDLED;
 	u8                              enabled_status_byte;
 	struct acpi_gpe_register_info   *gpe_register_info;
-	u32                             in_value;
+	u32                             status_reg;
+	u32                             enable_reg;
 	acpi_status                     status;
 	struct acpi_gpe_block_info      *gpe_block;
-	u32                             i;
-	u32                             j;
+	acpi_native_uint                i;
+	acpi_native_uint                j;
 
 
 	ACPI_FUNCTION_NAME ("ev_gpe_detect");
@@ -171,33 +419,32 @@ acpi_ev_gpe_detect (
 
 			/* Read the Status Register */
 
-			status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value,
+			status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &status_reg,
 					 &gpe_register_info->status_address);
-			gpe_register_info->status = (u8) in_value;
 			if (ACPI_FAILURE (status)) {
 				goto unlock_and_exit;
 			}
 
 			/* Read the Enable Register */
 
-			status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value,
+			status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &enable_reg,
 					 &gpe_register_info->enable_address);
-			gpe_register_info->enable = (u8) in_value;
 			if (ACPI_FAILURE (status)) {
 				goto unlock_and_exit;
 			}
 
 			ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
 				"GPE pair: Status %8.8X%8.8X = %02X, Enable %8.8X%8.8X = %02X\n",
-				ACPI_FORMAT_UINT64 (gpe_register_info->status_address.address),
-				gpe_register_info->status,
-				ACPI_FORMAT_UINT64 (gpe_register_info->enable_address.address),
-				gpe_register_info->enable));
+				ACPI_FORMAT_UINT64 (
+					gpe_register_info->status_address.address),
+					status_reg,
+				ACPI_FORMAT_UINT64 (
+					gpe_register_info->enable_address.address),
+					enable_reg));
 
 			/* First check if there is anything active at all in this register */
 
-			enabled_status_byte = (u8) (gpe_register_info->status &
-					   gpe_register_info->enable);
+			enabled_status_byte = (u8) (status_reg & enable_reg);
 			if (!enabled_status_byte) {
 				/* No active GPEs in this register, move on */
 
@@ -216,7 +463,7 @@ acpi_ev_gpe_detect (
 					 */
 					int_status |= acpi_ev_gpe_dispatch (
 							  &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j],
-							  j + gpe_register_info->base_gpe_number);
+							  (u32) j + gpe_register_info->base_gpe_number);
 				}
 			}
 		}
@@ -255,6 +502,7 @@ acpi_ev_asynch_execute_gpe_method (
 	u32                             gpe_number = 0;
 	acpi_status                     status;
 	struct acpi_gpe_event_info      local_gpe_event_info;
+	struct acpi_parameter_info      info;
 
 
 	ACPI_FUNCTION_TRACE ("ev_asynch_execute_gpe_method");
@@ -272,6 +520,10 @@ acpi_ev_asynch_execute_gpe_method (
 		return_VOID;
 	}
 
+	/* Set the GPE flags for return to enabled state */
+
+	(void) acpi_ev_enable_gpe (gpe_event_info, FALSE);
+
 	/*
 	 * Take a snapshot of the GPE info for this level - we copy the
 	 * info to prevent a race condition with remove_handler/remove_block.
@@ -283,23 +535,33 @@ acpi_ev_asynch_execute_gpe_method (
 		return_VOID;
 	}
 
-	if (local_gpe_event_info.method_node) {
+	/*
+	 * Must check for control method type dispatch one more
+	 * time to avoid race with ev_gpe_install_handler
+	 */
+	if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) {
 		/*
-		 * Invoke the GPE Method (_Lxx, _Exx):
-		 * (Evaluate the _Lxx/_Exx control method that corresponds to this GPE.)
+		 * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
+		 * control method that corresponds to this GPE
 		 */
-		status = acpi_ns_evaluate_by_handle (local_gpe_event_info.method_node, NULL, NULL);
+		info.node = local_gpe_event_info.dispatch.method_node;
+		info.parameters = ACPI_CAST_PTR (union acpi_operand_object *, gpe_event_info);
+		info.parameter_type = ACPI_PARAM_GPE;
+
+		status = acpi_ns_evaluate_by_handle (&info);
 		if (ACPI_FAILURE (status)) {
-			ACPI_REPORT_ERROR (("%s while evaluating method [%4.4s] for GPE[%2X]\n",
+			ACPI_REPORT_ERROR ((
+				"%s while evaluating method [%4.4s] for GPE[%2X]\n",
 				acpi_format_exception (status),
-				acpi_ut_get_node_name (local_gpe_event_info.method_node), gpe_number));
+				acpi_ut_get_node_name (local_gpe_event_info.dispatch.method_node),
+				gpe_number));
 		}
 	}
 
 	if ((local_gpe_event_info.flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_LEVEL_TRIGGERED) {
 		/*
-		 * GPE is level-triggered, we clear the GPE status bit after handling
-		 * the event.
+		 * GPE is level-triggered, we clear the GPE status bit after
+		 * handling the event.
 		 */
 		status = acpi_hw_clear_gpe (&local_gpe_event_info);
 		if (ACPI_FAILURE (status)) {
@@ -309,7 +571,7 @@ acpi_ev_asynch_execute_gpe_method (
 
 	/* Enable this GPE */
 
-	(void) acpi_hw_enable_gpe (&local_gpe_event_info);
+	(void) acpi_hw_write_gpe_enable_reg (&local_gpe_event_info);
 	return_VOID;
 }
 
@@ -354,6 +616,15 @@ acpi_ev_gpe_dispatch (
 		}
 	}
 
+	/* Save current system state */
+
+	if (acpi_gbl_system_awake_and_running) {
+		ACPI_SET_BIT (gpe_event_info->flags, ACPI_GPE_SYSTEM_RUNNING);
+	}
+	else {
+		ACPI_CLEAR_BIT (gpe_event_info->flags, ACPI_GPE_SYSTEM_RUNNING);
+	}
+
 	/*
 	 * Dispatch the GPE to either an installed handler, or the control
 	 * method associated with this GPE (_Lxx or _Exx).
@@ -361,10 +632,15 @@ acpi_ev_gpe_dispatch (
 	 * If there is neither a handler nor a method, we disable the level to
 	 * prevent further events from coming in here.
 	 */
-	if (gpe_event_info->handler) {
-		/* Invoke the installed handler (at interrupt level) */
+	switch (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) {
+	case ACPI_GPE_DISPATCH_HANDLER:
 
-		gpe_event_info->handler (gpe_event_info->context);
+		/*
+		 * Invoke the installed handler (at interrupt level)
+		 * Ignore return status for now.  TBD: leave GPE disabled on error?
+		 */
+		(void) gpe_event_info->dispatch.handler->address (
+				  gpe_event_info->dispatch.handler->context);
 
 		/* It is now safe to clear level-triggered events. */
 
@@ -377,13 +653,15 @@ acpi_ev_gpe_dispatch (
 				return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
 			}
 		}
-	}
-	else if (gpe_event_info->method_node) {
+		break;
+
+	case ACPI_GPE_DISPATCH_METHOD:
+
 		/*
 		 * Disable GPE, so it doesn't keep firing before the method has a
 		 * chance to run.
 		 */
-		status = acpi_hw_disable_gpe (gpe_event_info);
+		status = acpi_ev_disable_gpe (gpe_event_info);
 		if (ACPI_FAILURE (status)) {
 			ACPI_REPORT_ERROR ((
 				"acpi_ev_gpe_dispatch: Unable to disable GPE[%2X]\n",
@@ -402,8 +680,10 @@ acpi_ev_gpe_dispatch (
 				"acpi_ev_gpe_dispatch: Unable to queue handler for GPE[%2X], event is disabled\n",
 				gpe_number));
 		}
-	}
-	else {
+		break;
+
+	default:
+
 		/* No handler or method to run! */
 
 		ACPI_REPORT_ERROR ((
@@ -414,15 +694,68 @@ acpi_ev_gpe_dispatch (
 		 * Disable the GPE.  The GPE will remain disabled until the ACPI
 		 * Core Subsystem is restarted, or a handler is installed.
 		 */
-		status = acpi_hw_disable_gpe (gpe_event_info);
+		status = acpi_ev_disable_gpe (gpe_event_info);
 		if (ACPI_FAILURE (status)) {
 			ACPI_REPORT_ERROR ((
 				"acpi_ev_gpe_dispatch: Unable to disable GPE[%2X]\n",
 				gpe_number));
 			return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
 		}
+		break;
 	}
 
 	return_VALUE (ACPI_INTERRUPT_HANDLED);
 }
 
+
+#ifdef ACPI_GPE_NOTIFY_CHECK
+
+/*******************************************************************************
+ * TBD: NOT USED, PROTOTYPE ONLY AND WILL PROBABLY BE REMOVED
+ *
+ * FUNCTION:    acpi_ev_check_for_wake_only_gpe
+ *
+ * PARAMETERS:  gpe_event_info  - info for this GPE
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Determine if a a GPE is "wake-only".
+ *
+ *              Called from Notify() code in interpreter when a "device_wake"
+ *              Notify comes in.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_check_for_wake_only_gpe (
+	struct acpi_gpe_event_info      *gpe_event_info)
+{
+	acpi_status                     status;
+
+
+	ACPI_FUNCTION_TRACE ("ev_check_for_wake_only_gpe");
+
+
+	if ((gpe_event_info) &&  /* Only >0 for _Lxx/_Exx */
+	   ((gpe_event_info->flags & ACPI_GPE_SYSTEM_MASK) == ACPI_GPE_SYSTEM_RUNNING)) /* System state at GPE time */ {
+		/* This must be a wake-only GPE, disable it */
+
+		status = acpi_ev_disable_gpe (gpe_event_info);
+
+		/* Set GPE to wake-only.  Do not change wake disabled/enabled status */
+
+		acpi_ev_set_gpe_type (gpe_event_info, ACPI_GPE_TYPE_WAKE);
+
+		ACPI_REPORT_INFO (("GPE %p was updated from wake/run to wake-only\n",
+				gpe_event_info));
+
+		/* This was a wake-only GPE */
+
+		return_ACPI_STATUS (AE_WAKE_ONLY_GPE);
+	}
+
+	return_ACPI_STATUS (AE_OK);
+}
+#endif
+
+
diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c
index b1fbf7dec..1913f4efe 100644
--- a/drivers/acpi/events/evgpeblk.c
+++ b/drivers/acpi/events/evgpeblk.c
@@ -53,7 +53,7 @@
  *
  * FUNCTION:    acpi_ev_valid_gpe_event
  *
- * PARAMETERS:  gpe_event_info - Info for this GPE
+ * PARAMETERS:  gpe_event_info              - Info for this GPE
  *
  * RETURN:      TRUE if the gpe_event is valid
  *
@@ -105,17 +105,18 @@ acpi_ev_valid_gpe_event (
  * FUNCTION:    acpi_ev_walk_gpe_list
  *
  * PARAMETERS:  gpe_walk_callback   - Routine called for each GPE block
+ *              Flags               - ACPI_NOT_ISR or ACPI_ISR
  *
  * RETURN:      Status
  *
  * DESCRIPTION: Walk the GPE lists.
- *              FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
  *
  ******************************************************************************/
 
 acpi_status
 acpi_ev_walk_gpe_list (
-	ACPI_GPE_CALLBACK       gpe_walk_callback)
+	ACPI_GPE_CALLBACK       gpe_walk_callback,
+	u32                             flags)
 {
 	struct acpi_gpe_block_info      *gpe_block;
 	struct acpi_gpe_xrupt_info      *gpe_xrupt_info;
@@ -125,7 +126,7 @@ acpi_ev_walk_gpe_list (
 	ACPI_FUNCTION_TRACE ("ev_walk_gpe_list");
 
 
-	acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_ISR);
+	acpi_os_acquire_lock (acpi_gbl_gpe_lock, flags);
 
 	/* Walk the interrupt level descriptor list */
 
@@ -149,11 +150,58 @@ acpi_ev_walk_gpe_list (
 	}
 
 unlock_and_exit:
-	acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_ISR);
+	acpi_os_release_lock (acpi_gbl_gpe_lock, flags);
 	return_ACPI_STATUS (status);
 }
 
 
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_delete_gpe_handlers
+ *
+ * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
+ *              gpe_block           - Gpe Block info
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Delete all Handler objects found in the GPE data structs.
+ *              Used only prior to termination.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_delete_gpe_handlers (
+	struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
+	struct acpi_gpe_block_info      *gpe_block)
+{
+	struct acpi_gpe_event_info      *gpe_event_info;
+	acpi_native_uint                i;
+	acpi_native_uint                j;
+
+
+	ACPI_FUNCTION_TRACE ("ev_delete_gpe_handlers");
+
+
+	/* Examine each GPE Register within the block */
+
+	for (i = 0; i < gpe_block->register_count; i++) {
+		/* Now look at the individual GPEs in this byte register */
+
+		for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
+			gpe_event_info = &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
+
+			if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) {
+				ACPI_MEM_FREE (gpe_event_info->dispatch.handler);
+				gpe_event_info->dispatch.handler = NULL;
+				gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK;
+			}
+		}
+	}
+
+	return_ACPI_STATUS (AE_OK);
+}
+
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ev_save_method_info
@@ -188,6 +236,7 @@ acpi_ev_save_method_info (
 	u32                             gpe_number;
 	char                            name[ACPI_NAME_SIZE + 1];
 	u8                              type;
+	acpi_status                     status;
 
 
 	ACPI_FUNCTION_TRACE ("ev_save_method_info");
@@ -206,16 +255,16 @@ acpi_ev_save_method_info (
 	 * 2) Edge/Level determination is based on the 2nd character
 	 *    of the method name
 	 *
-	 * NOTE: Default GPE type is RUNTIME.  May be changed later to WAKE if a
-	 * _PRW object is found that points to this GPE.
+	 * NOTE: Default GPE type is RUNTIME.  May be changed later to WAKE
+	 * if a _PRW object is found that points to this GPE.
 	 */
 	switch (name[1]) {
 	case 'L':
-		type = ACPI_GPE_LEVEL_TRIGGERED | ACPI_GPE_TYPE_RUNTIME;
+		type = ACPI_GPE_LEVEL_TRIGGERED;
 		break;
 
 	case 'E':
-		type = ACPI_GPE_EDGE_TRIGGERED | ACPI_GPE_TYPE_RUNTIME;
+		type = ACPI_GPE_EDGE_TRIGGERED;
 		break;
 
 	default:
@@ -253,27 +302,35 @@ acpi_ev_save_method_info (
 
 	/*
 	 * Now we can add this information to the gpe_event_info block
-	 * for use during dispatch of this GPE.
+	 * for use during dispatch of this GPE.  Default type is RUNTIME, although
+	 * this may change when the _PRW methods are executed later.
 	 */
 	gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
 
-	gpe_event_info->flags    = type;
-	gpe_event_info->method_node = (struct acpi_namespace_node *) obj_handle;
+	gpe_event_info->flags = (u8) (type | ACPI_GPE_DISPATCH_METHOD |
+			   ACPI_GPE_TYPE_RUNTIME);
+
+	gpe_event_info->dispatch.method_node = (struct acpi_namespace_node *) obj_handle;
+
+	/* Update enable mask, but don't enable the HW GPE as of yet */
+
+	status = acpi_ev_enable_gpe (gpe_event_info, FALSE);
 
 	ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
 		"Registered GPE method %s as GPE number 0x%.2X\n",
 		name, gpe_number));
-	return_ACPI_STATUS (AE_OK);
+	return_ACPI_STATUS (status);
 }
 
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ev_get_gpe_type
+ * FUNCTION:    acpi_ev_match_prw_and_gpe
  *
  * PARAMETERS:  Callback from walk_namespace
  *
- * RETURN:      Status
+ * RETURN:      Status.  NOTE: We ignore errors so that the _PRW walk is
+ *              not aborted on a single _PRW failure.
  *
  * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a
  *              Device.  Run the _PRW method.  If present, extract the GPE
@@ -282,7 +339,7 @@ acpi_ev_save_method_info (
  ******************************************************************************/
 
 static acpi_status
-acpi_ev_get_gpe_type (
+acpi_ev_match_prw_and_gpe (
 	acpi_handle                     obj_handle,
 	u32                             level,
 	void                            *info,
@@ -299,19 +356,18 @@ acpi_ev_get_gpe_type (
 	acpi_status                     status;
 
 
-	ACPI_FUNCTION_TRACE ("ev_get_gpe_type");
+	ACPI_FUNCTION_TRACE ("ev_match_prw_and_gpe");
 
 
 	/* Check for a _PRW method under this device */
 
 	status = acpi_ut_evaluate_object (obj_handle, METHOD_NAME__PRW,
 			 ACPI_BTYPE_PACKAGE, &pkg_desc);
-	if (status == AE_NOT_FOUND) {
+	if (ACPI_FAILURE (status)) {
+		/* Ignore all errors from _PRW, we don't want to abort the subsystem */
+
 		return_ACPI_STATUS (AE_OK);
 	}
-	else if (ACPI_FAILURE (status)) {
-		return_ACPI_STATUS (status);
-	}
 
 	/* The returned _PRW package must have at least two elements */
 
@@ -370,16 +426,21 @@ acpi_ev_get_gpe_type (
 	if ((gpe_device == target_gpe_device) &&
 		(gpe_number >= gpe_block->block_base_number) &&
 		(gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) {
-		/* Mark GPE for WAKE but DISABLED (even for wake) */
-
 		gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
-		gpe_event_info->flags |= ACPI_GPE_TYPE_WAKE;
+
+		/* Mark GPE for WAKE-ONLY but WAKE_DISABLED */
+
+		gpe_event_info->flags &= ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED);
+		status = acpi_ev_set_gpe_type (gpe_event_info, ACPI_GPE_TYPE_WAKE);
+		if (ACPI_FAILURE (status)) {
+			goto cleanup;
+		}
+		status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_DISABLE);
 	}
 
 cleanup:
 	acpi_ut_remove_reference (pkg_desc);
-
-	return_ACPI_STATUS (status);
+	return_ACPI_STATUS (AE_OK);
 }
 
 
@@ -742,7 +803,7 @@ acpi_ev_create_gpe_info_blocks (
 		/* Init the event_info for each GPE within this register */
 
 		for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
-			this_event->bit_mask = acpi_gbl_decode_to8bit[j];
+			this_event->register_bit = acpi_gbl_decode_to8bit[j];
 			this_event->register_info = this_register;
 			this_event++;
 		}
@@ -817,6 +878,7 @@ acpi_ev_create_gpe_block (
 	acpi_status                     status;
 	struct acpi_gpe_walk_info       gpe_info;
 
+
 	ACPI_FUNCTION_TRACE ("ev_create_gpe_block");
 
 
@@ -835,6 +897,7 @@ acpi_ev_create_gpe_block (
 
 	gpe_block->register_count = register_count;
 	gpe_block->block_base_number = gpe_block_base_number;
+	gpe_block->node           = gpe_device;
 
 	ACPI_MEMCPY (&gpe_block->block_address, gpe_block_address, sizeof (struct acpi_generic_address));
 
@@ -854,18 +917,6 @@ acpi_ev_create_gpe_block (
 		return_ACPI_STATUS (status);
 	}
 
-	/* Dump info about this GPE block */
-
-	ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
-		"GPE %02d to %02d [%4.4s] %d regs at %8.8X%8.8X on int %d\n",
-		gpe_block->block_base_number,
-		(u32) (gpe_block->block_base_number +
-				((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)),
-		gpe_device->name.ascii,
-		gpe_block->register_count,
-		ACPI_FORMAT_UINT64 (gpe_block->block_address.address),
-		interrupt_level));
-
 	/* Find all GPE methods (_Lxx, _Exx) for this block */
 
 	status = acpi_ns_walk_namespace (ACPI_TYPE_METHOD, gpe_device,
@@ -873,27 +924,28 @@ acpi_ev_create_gpe_block (
 			  gpe_block, NULL);
 
 	/*
-	 * Runtime option: Should Wake GPEs be enabled at runtime?  The default is
-	 * No,they should only be enabled just as the machine goes to sleep.
+	 * Runtime option: Should Wake GPEs be enabled at runtime?  The default
+	 * is No,they should only be enabled just as the machine goes to sleep.
 	 */
 	if (acpi_gbl_leave_wake_gpes_disabled) {
 		/*
-		 * Differentiate RUNTIME vs WAKE GPEs, via the _PRW control methods. (Each
-		 * GPE that has one or more _PRWs that reference it is by definition a
-		 * WAKE GPE and will not be enabled while the machine is running.)
+		 * Differentiate RUNTIME vs WAKE GPEs, via the _PRW control methods.
+		 * (Each GPE that has one or more _PRWs that reference it is by
+		 * definition a WAKE GPE and will not be enabled while the machine
+		 * is running.)
 		 */
 		gpe_info.gpe_block = gpe_block;
 		gpe_info.gpe_device = gpe_device;
 
 		status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
-				  ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, acpi_ev_get_gpe_type,
+				  ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, acpi_ev_match_prw_and_gpe,
 				  &gpe_info, NULL);
 	}
 
 	/*
-	 * Enable all GPEs in this block that are 1) "runtime" GPEs, and 2) have
-	 * a corresponding _Lxx or _Exx method.  All other GPEs must be enabled via
-	 * the acpi_enable_gpe() external interface.
+	 * Enable all GPEs in this block that are 1) "runtime" or "run/wake" GPEs,
+	 * and 2) have a corresponding _Lxx or _Exx method.  All other GPEs must
+	 * be enabled via the acpi_enable_gpe() external interface.
 	 */
 	wake_gpe_count = 0;
 	gpe_enabled_count = 0;
@@ -903,23 +955,35 @@ acpi_ev_create_gpe_block (
 			/* Get the info block for this particular GPE */
 
 			gpe_event_info = &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
-			if ((gpe_event_info->method_node) &&
-			   ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == ACPI_GPE_TYPE_RUNTIME)) {
-				/* Enable this GPE, it is 1) RUNTIME and 2) has an _Lxx or _Exx method */
-
-				status = acpi_hw_enable_gpe (gpe_event_info);
-				if (ACPI_FAILURE (status)) {
-					return_ACPI_STATUS (status);
-				}
+
+			if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) &&
+				 (gpe_event_info->flags & ACPI_GPE_TYPE_RUNTIME)) {
 				gpe_enabled_count++;
 			}
 
-			if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == ACPI_GPE_TYPE_WAKE) {
+			if (gpe_event_info->flags & ACPI_GPE_TYPE_WAKE) {
 				wake_gpe_count++;
 			}
 		}
 	}
 
+	/* Dump info about this GPE block */
+
+	ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
+		"GPE %02X to %02X [%4.4s] %u regs at %8.8X%8.8X on int 0x%X\n",
+		(u32) gpe_block->block_base_number,
+		(u32) (gpe_block->block_base_number +
+				((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)),
+		gpe_device->name.ascii,
+		gpe_block->register_count,
+		ACPI_FORMAT_UINT64 (gpe_block->block_address.address),
+		interrupt_level));
+
+
+	/* Enable all valid GPEs found above */
+
+	status = acpi_hw_enable_runtime_gpe_block (NULL, gpe_block);
+
 	ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
 			"Found %u Wake, Enabled %u Runtime GPEs in this block\n",
 			wake_gpe_count, gpe_enabled_count));
@@ -1056,7 +1120,8 @@ acpi_ev_gpe_initialize (
 	if ((register_count0 + register_count1) == 0) {
 		/* GPEs are not required by ACPI, this is OK */
 
-		ACPI_REPORT_INFO (("There are no GPE blocks defined in the FADT\n"));
+		ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
+				"There are no GPE blocks defined in the FADT\n"));
 		status = AE_OK;
 		goto cleanup;
 	}
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
index 1bfb10df3..35e61d522 100644
--- a/drivers/acpi/events/evmisc.c
+++ b/drivers/acpi/events/evmisc.c
@@ -88,9 +88,10 @@ acpi_ev_is_notify_object (
  *
  * FUNCTION:    acpi_ev_queue_notify_request
  *
- * PARAMETERS:
+ * PARAMETERS:  Node            - NS node for the notified object
+ *              notify_value    - Value from the Notify() request
  *
- * RETURN:      None.
+ * RETURN:      Status
  *
  * DESCRIPTION: Dispatch a device notification event to a previously
  *              installed handler.
@@ -139,14 +140,12 @@ acpi_ev_queue_notify_request (
 				acpi_notify_value_names[notify_value]));
 	}
 	else {
-		ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
-				"notify value: 0x%2.2x **Device Specific**\n",
+		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: 0x%2.2X **Device Specific**\n",
 				notify_value));
 	}
 
-	/*
-	 * Get the notify object attached to the NS Node
-	 */
+	/* Get the notify object attached to the NS Node */
+
 	obj_desc = acpi_ns_get_attached_object (node);
 	if (obj_desc) {
 		/* We have the notify object, Get the right handler */
@@ -194,11 +193,13 @@ acpi_ev_queue_notify_request (
 	}
 
 	if (!handler_obj) {
-		/* There is no per-device notify handler for this device */
-
+		/*
+		 * There is no per-device notify handler for this device.
+		 * This may or may not be a problem.
+		 */
 		ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
-			"No notify handler for [%4.4s] node %p\n",
-			acpi_ut_get_node_name (node), node));
+			"No notify handler for Notify(%4.4s, %X) node %p\n",
+			acpi_ut_get_node_name (node), notify_value, node));
 	}
 
 	return (status);
@@ -209,7 +210,7 @@ acpi_ev_queue_notify_request (
  *
  * FUNCTION:    acpi_ev_notify_dispatch
  *
- * PARAMETERS:
+ * PARAMETERS:  Context         - To be passsed to the notify handler
  *
  * RETURN:      None.
  *
@@ -276,6 +277,8 @@ acpi_ev_notify_dispatch (
  *
  * FUNCTION:    acpi_ev_global_lock_thread
  *
+ * PARAMETERS:  Context         - From thread interface, not used
+ *
  * RETURN:      None
  *
  * DESCRIPTION: Invoked by SCI interrupt handler upon acquisition of the
@@ -309,7 +312,9 @@ acpi_ev_global_lock_thread (
  *
  * FUNCTION:    acpi_ev_global_lock_handler
  *
- * RETURN:      Status
+ * PARAMETERS:  Context         - From thread interface, not used
+ *
+ * RETURN:      ACPI_INTERRUPT_HANDLED or ACPI_INTERRUPT_NOT_HANDLED
  *
  * DESCRIPTION: Invoked directly from the SCI handler when a global lock
  *              release interrupt occurs.  Grab the global lock and queue
@@ -356,6 +361,8 @@ acpi_ev_global_lock_handler (
  *
  * FUNCTION:    acpi_ev_init_global_lock_handler
  *
+ * PARAMETERS:  None
+ *
  * RETURN:      Status
  *
  * DESCRIPTION: Install a handler for the global lock release event
@@ -395,6 +402,8 @@ acpi_ev_init_global_lock_handler (void)
  *
  * FUNCTION:    acpi_ev_acquire_global_lock
  *
+ * PARAMETERS:  Timeout         - Max time to wait for the lock, in millisec.
+ *
  * RETURN:      Status
  *
  * DESCRIPTION: Attempt to gain ownership of the Global Lock.
@@ -462,6 +471,10 @@ acpi_ev_acquire_global_lock (
  *
  * FUNCTION:    acpi_ev_release_global_lock
  *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status
+ *
  * DESCRIPTION: Releases ownership of the Global Lock.
  *
  ******************************************************************************/
@@ -548,7 +561,7 @@ acpi_ev_terminate (void)
 
 		/* Disable all GPEs in all GPE blocks */
 
-		status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block);
+		status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block, ACPI_NOT_ISR);
 
 		/* Remove SCI handler */
 
@@ -558,6 +571,10 @@ acpi_ev_terminate (void)
 		}
 	}
 
+	/* Deallocate all handler objects installed within GPE info structs */
+
+	status = acpi_ev_walk_gpe_list (acpi_ev_delete_gpe_handlers, ACPI_NOT_ISR);
+
 	/* Return to original mode if necessary */
 
 	if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) {
diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c
index ec81e587f..b7ff3b162 100644
--- a/drivers/acpi/events/evregion.c
+++ b/drivers/acpi/events/evregion.c
@@ -61,7 +61,7 @@ static u8                   acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPA
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ev_init_address_spaces
+ * FUNCTION:    acpi_ev_install_region_handlers
  *
  * PARAMETERS:  None
  *
@@ -72,15 +72,20 @@ static u8                   acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPA
  ******************************************************************************/
 
 acpi_status
-acpi_ev_init_address_spaces (
+acpi_ev_install_region_handlers (
 	void) {
 	acpi_status                     status;
 	acpi_native_uint                i;
 
 
-	ACPI_FUNCTION_TRACE ("ev_init_address_spaces");
+	ACPI_FUNCTION_TRACE ("ev_install_region_handlers");
 
 
+	status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+
 	/*
 	 * All address spaces (PCI Config, EC, SMBus) are scope dependent
 	 * and registration must occur for a specific device.
@@ -99,9 +104,8 @@ acpi_ev_init_address_spaces (
 	 * has already been installed (via acpi_install_address_space_handler).
 	 * Similar for AE_SAME_HANDLER.
 	 */
-
 	for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
-		status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node,
+		status = acpi_ev_install_space_handler (acpi_gbl_root_node,
 				  acpi_gbl_default_address_spaces[i],
 				  ACPI_DEFAULT_HANDLER, NULL, NULL);
 		switch (status) {
@@ -111,15 +115,63 @@ acpi_ev_init_address_spaces (
 
 			/* These exceptions are all OK */
 
+			status = AE_OK;
 			break;
 
 		default:
 
-			return_ACPI_STATUS (status);
+			goto unlock_and_exit;
 		}
 	}
 
-	return_ACPI_STATUS (AE_OK);
+unlock_and_exit:
+	(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+	return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_initialize_op_regions
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Execute _REG methods for all Operation Regions that have
+ *              an installed default region handler.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_initialize_op_regions (
+	void)
+{
+	acpi_status                     status;
+	acpi_native_uint                i;
+
+
+	ACPI_FUNCTION_TRACE ("ev_initialize_op_regions");
+
+
+	status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+
+	/*
+	 * Run the _REG methods for op_regions in each default address space
+	 */
+	for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
+		/* TBD: Make sure handler is the DEFAULT handler, otherwise
+		 * _REG will have already been run.
+		 */
+		status = acpi_ev_execute_reg_methods (acpi_gbl_root_node,
+				  acpi_gbl_default_address_spaces[i]);
+	}
+
+	(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+	return_ACPI_STATUS (status);
 }
 
 
@@ -128,7 +180,7 @@ acpi_ev_init_address_spaces (
  * FUNCTION:    acpi_ev_execute_reg_method
  *
  * PARAMETERS:  region_obj          - Object structure
- *              Function            - On (1) or Off (0)
+ *              Function            - Passed to _REG:  On (1) or Off (0)
  *
  * RETURN:      Status
  *
@@ -138,11 +190,12 @@ acpi_ev_init_address_spaces (
 
 acpi_status
 acpi_ev_execute_reg_method (
-	union acpi_operand_object      *region_obj,
+	union acpi_operand_object       *region_obj,
 	u32                             function)
 {
-	union acpi_operand_object      *params[3];
-	union acpi_operand_object      *region_obj2;
+	struct acpi_parameter_info      info;
+	union acpi_operand_object       *params[3];
+	union acpi_operand_object       *region_obj2;
 	acpi_status                     status;
 
 
@@ -159,10 +212,11 @@ acpi_ev_execute_reg_method (
 	}
 
 	/*
-	 * _REG method has two arguments
-	 * Arg0:   Integer: Operation region space ID
+	 * The _REG method has two arguments:
+	 *
+	 * Arg0, Integer: Operation region space ID
 	 *          Same value as region_obj->Region.space_id
-	 * Arg1:   Integer: connection status
+	 * Arg1, Integer: connection status
 	 *          1 for connecting the handler,
 	 *          0 for disconnecting the handler
 	 *          Passed as a parameter
@@ -178,16 +232,21 @@ acpi_ev_execute_reg_method (
 		goto cleanup;
 	}
 
-	/* Set up the parameter objects */
+	/* Setup the parameter objects */
 
 	params[0]->integer.value = region_obj->region.space_id;
 	params[1]->integer.value = function;
 	params[2] = NULL;
 
+	info.node = region_obj2->extra.method_REG;
+	info.parameters = params;
+	info.parameter_type = ACPI_PARAM_ARGS;
+
 	/* Execute the method, no return value */
 
-	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, region_obj2->extra.method_REG, NULL));
-	status = acpi_ns_evaluate_by_handle (region_obj2->extra.method_REG, params, NULL);
+	ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (
+			   ACPI_TYPE_METHOD, info.node, NULL));
+	status = acpi_ns_evaluate_by_handle (&info);
 
 	acpi_ut_remove_reference (params[1]);
 
@@ -203,7 +262,6 @@ cleanup:
  * FUNCTION:    acpi_ev_address_space_dispatch
  *
  * PARAMETERS:  region_obj          - Internal region object
- *              space_id            - ID of the address space (0-255)
  *              Function            - Read or Write operation
  *              Address             - Where in the space to read or write
  *              bit_width           - Field width in bits (8, 16, 32, or 64)
@@ -326,7 +384,7 @@ acpi_ev_address_space_dispatch (
 		ACPI_FORMAT_UINT64 (address),
 		acpi_ut_get_region_name (region_obj->region.space_id)));
 
-	if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
+	if (!(handler_desc->address_space.hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
 		/*
 		 * For handlers other than the default (supplied) handlers, we must
 		 * exit the interpreter because the handler *might* block -- we don't
@@ -347,7 +405,7 @@ acpi_ev_address_space_dispatch (
 			acpi_format_exception (status)));
 	}
 
-	if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
+	if (!(handler_desc->address_space.hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
 		/*
 		 * We just returned from a non-default handler, we must re-enter the
 		 * interpreter
@@ -366,8 +424,8 @@ acpi_ev_address_space_dispatch (
  *
  * FUNCTION:    acpi_ev_detach_region
  *
- * PARAMETERS:  region_obj      - Region Object
- *              acpi_ns_is_locked - Namespace Region Already Locked?
+ * PARAMETERS:  region_obj          - Region Object
+ *              acpi_ns_is_locked   - Namespace Region Already Locked?
  *
  * RETURN:      None
  *
@@ -501,9 +559,9 @@ acpi_ev_detach_region(
  *
  * FUNCTION:    acpi_ev_attach_region
  *
- * PARAMETERS:  handler_obj     - Handler Object
- *              region_obj      - Region Object
- *              acpi_ns_is_locked - Namespace Region Already Locked?
+ * PARAMETERS:  handler_obj         - Handler Object
+ *              region_obj          - Region Object
+ *              acpi_ns_is_locked   - Namespace Region Already Locked?
  *
  * RETURN:      None
  *
@@ -676,6 +734,273 @@ acpi_ev_install_handler (
 	return (status);
 }
 
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_install_space_handler
+ *
+ * PARAMETERS:  Node            - Namespace node for the device
+ *              space_id        - The address space ID
+ *              Handler         - Address of the handler
+ *              Setup           - Address of the setup function
+ *              Context         - Value passed to the handler on each access
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Install a handler for all op_regions of a given space_id.
+ *              Assumes namespace is locked
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_install_space_handler (
+	struct acpi_namespace_node      *node,
+	acpi_adr_space_type             space_id,
+	acpi_adr_space_handler          handler,
+	acpi_adr_space_setup            setup,
+	void                            *context)
+{
+	union acpi_operand_object       *obj_desc;
+	union acpi_operand_object       *handler_obj;
+	acpi_status                     status;
+	acpi_object_type                type;
+	u16                             flags = 0;
+
+
+	ACPI_FUNCTION_TRACE ("ev_install_space_handler");
+
+
+	/*
+	 * This registration is valid for only the types below
+	 * and the root.  This is where the default handlers
+	 * get placed.
+	 */
+	if ((node->type != ACPI_TYPE_DEVICE)     &&
+		(node->type != ACPI_TYPE_PROCESSOR)  &&
+		(node->type != ACPI_TYPE_THERMAL)    &&
+		(node != acpi_gbl_root_node)) {
+		status = AE_BAD_PARAMETER;
+		goto unlock_and_exit;
+	}
+
+	if (handler == ACPI_DEFAULT_HANDLER) {
+		flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
+
+		switch (space_id) {
+		case ACPI_ADR_SPACE_SYSTEM_MEMORY:
+			handler = acpi_ex_system_memory_space_handler;
+			setup   = acpi_ev_system_memory_region_setup;
+			break;
+
+		case ACPI_ADR_SPACE_SYSTEM_IO:
+			handler = acpi_ex_system_io_space_handler;
+			setup   = acpi_ev_io_space_region_setup;
+			break;
+
+		case ACPI_ADR_SPACE_PCI_CONFIG:
+			handler = acpi_ex_pci_config_space_handler;
+			setup   = acpi_ev_pci_config_region_setup;
+			break;
+
+		case ACPI_ADR_SPACE_CMOS:
+			handler = acpi_ex_cmos_space_handler;
+			setup   = acpi_ev_cmos_region_setup;
+			break;
+
+		case ACPI_ADR_SPACE_PCI_BAR_TARGET:
+			handler = acpi_ex_pci_bar_space_handler;
+			setup   = acpi_ev_pci_bar_region_setup;
+			break;
+
+		case ACPI_ADR_SPACE_DATA_TABLE:
+			handler = acpi_ex_data_table_space_handler;
+			setup   = NULL;
+			break;
+
+		default:
+			status = AE_BAD_PARAMETER;
+			goto unlock_and_exit;
+		}
+	}
+
+	/* If the caller hasn't specified a setup routine, use the default */
+
+	if (!setup) {
+		setup = acpi_ev_default_region_setup;
+	}
+
+	/* Check for an existing internal object */
+
+	obj_desc = acpi_ns_get_attached_object (node);
+	if (obj_desc) {
+		/*
+		 * The attached device object already exists.
+		 * Make sure the handler is not already installed.
+		 */
+		handler_obj = obj_desc->device.handler;
+
+		/* Walk the handler list for this device */
+
+		while (handler_obj) {
+			/* Same space_id indicates a handler already installed */
+
+			if (handler_obj->address_space.space_id == space_id) {
+				if (handler_obj->address_space.handler == handler) {
+					/*
+					 * It is (relatively) OK to attempt to install the SAME
+					 * handler twice. This can easily happen with PCI_Config space.
+					 */
+					status = AE_SAME_HANDLER;
+					goto unlock_and_exit;
+				}
+				else {
+					/* A handler is already installed */
+
+					status = AE_ALREADY_EXISTS;
+				}
+				goto unlock_and_exit;
+			}
+
+			/* Walk the linked list of handlers */
+
+			handler_obj = handler_obj->address_space.next;
+		}
+	}
+	else {
+		ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
+			"Creating object on Device %p while installing handler\n", node));
+
+		/* obj_desc does not exist, create one */
+
+		if (node->type == ACPI_TYPE_ANY) {
+			type = ACPI_TYPE_DEVICE;
+		}
+		else {
+			type = node->type;
+		}
+
+		obj_desc = acpi_ut_create_internal_object (type);
+		if (!obj_desc) {
+			status = AE_NO_MEMORY;
+			goto unlock_and_exit;
+		}
+
+		/* Init new descriptor */
+
+		obj_desc->common.type = (u8) type;
+
+		/* Attach the new object to the Node */
+
+		status = acpi_ns_attach_object (node, obj_desc, type);
+
+		/* Remove local reference to the object */
+
+		acpi_ut_remove_reference (obj_desc);
+
+		if (ACPI_FAILURE (status)) {
+			goto unlock_and_exit;
+		}
+	}
+
+	ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
+		"Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
+		acpi_ut_get_region_name (space_id), space_id,
+		acpi_ut_get_node_name (node), node, obj_desc));
+
+	/*
+	 * Install the handler
+	 *
+	 * At this point there is no existing handler.
+	 * Just allocate the object for the handler and link it
+	 * into the list.
+	 */
+	handler_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
+	if (!handler_obj) {
+		status = AE_NO_MEMORY;
+		goto unlock_and_exit;
+	}
+
+	/* Init handler obj */
+
+	handler_obj->address_space.space_id  = (u8) space_id;
+	handler_obj->address_space.hflags    = flags;
+	handler_obj->address_space.region_list = NULL;
+	handler_obj->address_space.node      = node;
+	handler_obj->address_space.handler   = handler;
+	handler_obj->address_space.context   = context;
+	handler_obj->address_space.setup     = setup;
+
+	/* Install at head of Device.address_space list */
+
+	handler_obj->address_space.next      = obj_desc->device.handler;
+
+	/*
+	 * The Device object is the first reference on the handler_obj.
+	 * Each region that uses the handler adds a reference.
+	 */
+	obj_desc->device.handler = handler_obj;
+
+	/*
+	 * Walk the namespace finding all of the regions this
+	 * handler will manage.
+	 *
+	 * Start at the device and search the branch toward
+	 * the leaf nodes until either the leaf is encountered or
+	 * a device is detected that has an address handler of the
+	 * same type.
+	 *
+	 * In either case, back up and search down the remainder
+	 * of the branch
+	 */
+	status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
+			  ACPI_NS_WALK_UNLOCK, acpi_ev_install_handler,
+			  handler_obj, NULL);
+
+unlock_and_exit:
+	return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_execute_reg_methods
+ *
+ * PARAMETERS:  Node            - Namespace node for the device
+ *              space_id        - The address space ID
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Run all _REG methods for the input Space ID;
+ *              Note: assumes namespace is locked, or system init time.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ev_execute_reg_methods (
+	struct acpi_namespace_node      *node,
+	acpi_adr_space_type             space_id)
+{
+	acpi_status                     status;
+
+
+	ACPI_FUNCTION_TRACE ("ev_execute_reg_methods");
+
+
+	/*
+	 * Run all _REG methods for all Operation Regions for this
+	 * space ID.  This is a separate walk in order to handle any
+	 * interdependencies between regions and _REG methods.  (i.e. handlers
+	 * must be installed for all regions of this Space ID before we
+	 * can run any _REG methods)
+	 */
+	status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
+			  ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
+			  &space_id, NULL);
+
+	return_ACPI_STATUS (status);
+}
+
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ev_reg_run
@@ -693,19 +1018,13 @@ acpi_ev_reg_run (
 	void                            *context,
 	void                            **return_value)
 {
-	union acpi_operand_object       *handler_obj;
 	union acpi_operand_object       *obj_desc;
 	struct acpi_namespace_node      *node;
+	acpi_adr_space_type             space_id;
 	acpi_status                     status;
 
 
-	handler_obj = (union acpi_operand_object   *) context;
-
-	/* Parameter validation */
-
-	if (!handler_obj) {
-		return (AE_OK);
-	}
+	space_id = *ACPI_CAST_PTR (acpi_adr_space_type, context);
 
 	/* Convert and validate the device handle */
 
@@ -732,10 +1051,9 @@ acpi_ev_reg_run (
 		return (AE_OK);
 	}
 
-
 	/* Object is a Region */
 
-	if (obj_desc->region.space_id != handler_obj->address_space.space_id) {
+	if (obj_desc->region.space_id != space_id) {
 		/*
 		 * This region is for a different address space
 		 * -- just ignore it
diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c
index 2e480d301..e19d82297 100644
--- a/drivers/acpi/events/evrgnini.c
+++ b/drivers/acpi/events/evrgnini.c
@@ -54,7 +54,7 @@
  *
  * FUNCTION:    acpi_ev_system_memory_region_setup
  *
- * PARAMETERS:  region_obj          - Region we are interested in
+ * PARAMETERS:  Handle              - Region we are interested in
  *              Function            - Start or stop
  *              handler_context     - Address space handler context
  *              region_context      - Region specific context
@@ -108,7 +108,7 @@ acpi_ev_system_memory_region_setup (
  *
  * FUNCTION:    acpi_ev_io_space_region_setup
  *
- * PARAMETERS:  region_obj          - Region we are interested in
+ * PARAMETERS:  Handle              - Region we are interested in
  *              Function            - Start or stop
  *              handler_context     - Address space handler context
  *              region_context      - Region specific context
@@ -144,7 +144,7 @@ acpi_ev_io_space_region_setup (
  *
  * FUNCTION:    acpi_ev_pci_config_region_setup
  *
- * PARAMETERS:  region_obj          - Region we are interested in
+ * PARAMETERS:  Handle             - Region we are interested in
  *              Function            - Start or stop
  *              handler_context     - Address space handler context
  *              region_context      - Region specific context
@@ -317,7 +317,7 @@ acpi_ev_pci_config_region_setup (
  *
  * FUNCTION:    acpi_ev_pci_bar_region_setup
  *
- * PARAMETERS:  region_obj          - Region we are interested in
+ * PARAMETERS:  Handle              - Region we are interested in
  *              Function            - Start or stop
  *              handler_context     - Address space handler context
  *              region_context      - Region specific context
@@ -348,7 +348,7 @@ acpi_ev_pci_bar_region_setup (
  *
  * FUNCTION:    acpi_ev_cmos_region_setup
  *
- * PARAMETERS:  region_obj          - Region we are interested in
+ * PARAMETERS:  Handle              - Region we are interested in
  *              Function            - Start or stop
  *              handler_context     - Address space handler context
  *              region_context      - Region specific context
@@ -379,7 +379,7 @@ acpi_ev_cmos_region_setup (
  *
  * FUNCTION:    acpi_ev_default_region_setup
  *
- * PARAMETERS:  region_obj          - Region we are interested in
+ * PARAMETERS:  Handle              - Region we are interested in
  *              Function            - Start or stop
  *              handler_context     - Address space handler context
  *              region_context      - Region specific context
diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c
index d33b99057..26e9b0e41 100644
--- a/drivers/acpi/events/evxface.c
+++ b/drivers/acpi/events/evxface.c
@@ -188,6 +188,7 @@ acpi_remove_fixed_event_handler (
  *              handler_type    - The type of handler:
  *                                  ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
  *                                  ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
+ *                                  ACPI_ALL_NOTIFY:  both system and device
  *              Handler         - Address of the handler
  *              Context         - Value passed to the handler on each GPE
  *
@@ -243,20 +244,21 @@ acpi_install_notify_handler (
 	if (device == ACPI_ROOT_OBJECT) {
 		/* Make sure the handler is not already installed */
 
-		if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
-				acpi_gbl_system_notify.handler)        ||
-			((handler_type == ACPI_DEVICE_NOTIFY) &&
+		if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
+				acpi_gbl_system_notify.handler)     ||
+			((handler_type & ACPI_DEVICE_NOTIFY) &&
 				acpi_gbl_device_notify.handler)) {
 			status = AE_ALREADY_EXISTS;
 			goto unlock_and_exit;
 		}
 
-		if (handler_type == ACPI_SYSTEM_NOTIFY) {
+		if (handler_type & ACPI_SYSTEM_NOTIFY) {
 			acpi_gbl_system_notify.node  = node;
 			acpi_gbl_system_notify.handler = handler;
 			acpi_gbl_system_notify.context = context;
 		}
-		else /* ACPI_DEVICE_NOTIFY */ {
+
+		if (handler_type & ACPI_DEVICE_NOTIFY) {
 			acpi_gbl_device_notify.node  = node;
 			acpi_gbl_device_notify.handler = handler;
 			acpi_gbl_device_notify.context = context;
@@ -284,9 +286,9 @@ acpi_install_notify_handler (
 		if (obj_desc) {
 			/* Object exists - make sure there's no handler */
 
-			if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
+			if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
 					obj_desc->common_notify.system_notify) ||
-				((handler_type == ACPI_DEVICE_NOTIFY) &&
+				((handler_type & ACPI_DEVICE_NOTIFY) &&
 					obj_desc->common_notify.device_notify)) {
 				status = AE_ALREADY_EXISTS;
 				goto unlock_and_exit;
@@ -308,7 +310,6 @@ acpi_install_notify_handler (
 			/* Remove local reference to the object */
 
 			acpi_ut_remove_reference (obj_desc);
-
 			if (ACPI_FAILURE (status)) {
 				goto unlock_and_exit;
 			}
@@ -326,12 +327,19 @@ acpi_install_notify_handler (
 		notify_obj->notify.handler = handler;
 		notify_obj->notify.context = context;
 
-		if (handler_type == ACPI_SYSTEM_NOTIFY) {
+		if (handler_type & ACPI_SYSTEM_NOTIFY) {
 			obj_desc->common_notify.system_notify = notify_obj;
 		}
-		else /* ACPI_DEVICE_NOTIFY */ {
+
+		if (handler_type & ACPI_DEVICE_NOTIFY) {
 			obj_desc->common_notify.device_notify = notify_obj;
 		}
+
+		if (handler_type == ACPI_ALL_NOTIFY) {
+			/* Extra ref if installed in both */
+
+			acpi_ut_add_reference (notify_obj);
+		}
 	}
 
 
@@ -349,7 +357,9 @@ unlock_and_exit:
  *              handler_type    - The type of handler:
  *                                  ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
  *                                  ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
+ *                                  ACPI_ALL_NOTIFY:  both system and device
  *              Handler         - Address of the handler
+ *
  * RETURN:      Status
  *
  * DESCRIPTION: Remove a handler for notifies on an ACPI device
@@ -392,15 +402,14 @@ acpi_remove_notify_handler (
 		goto unlock_and_exit;
 	}
 
-	/*
-	 * Root Object
-	 */
+	/* Root Object */
+
 	if (device == ACPI_ROOT_OBJECT) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Removing notify handler for ROOT object.\n"));
 
-		if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
-			  !acpi_gbl_system_notify.handler) ||
-			((handler_type == ACPI_DEVICE_NOTIFY) &&
+		if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
+			  !acpi_gbl_system_notify.handler)      ||
+			((handler_type & ACPI_DEVICE_NOTIFY) &&
 			  !acpi_gbl_device_notify.handler)) {
 			status = AE_NOT_EXIST;
 			goto unlock_and_exit;
@@ -415,21 +424,21 @@ acpi_remove_notify_handler (
 			return_ACPI_STATUS (status);
  		}
 
-		if (handler_type == ACPI_SYSTEM_NOTIFY) {
+		if (handler_type & ACPI_SYSTEM_NOTIFY) {
 			acpi_gbl_system_notify.node  = NULL;
 			acpi_gbl_system_notify.handler = NULL;
 			acpi_gbl_system_notify.context = NULL;
 		}
-		else {
+
+		if (handler_type & ACPI_DEVICE_NOTIFY) {
 			acpi_gbl_device_notify.node  = NULL;
 			acpi_gbl_device_notify.handler = NULL;
 			acpi_gbl_device_notify.context = NULL;
 		}
 	}
 
-	/*
-	 * All Other Objects
-	 */
+	/* All Other Objects */
+
 	else {
 		/* Notifies allowed on this object? */
 
@@ -448,38 +457,47 @@ acpi_remove_notify_handler (
 
 		/* Object exists - make sure there's an existing handler */
 
-		if (handler_type == ACPI_SYSTEM_NOTIFY) {
+		if (handler_type & ACPI_SYSTEM_NOTIFY) {
 			notify_obj = obj_desc->common_notify.system_notify;
-		}
-		else {
-			notify_obj = obj_desc->common_notify.device_notify;
-		}
+			if ((!notify_obj) ||
+				 (notify_obj->notify.handler != handler)) {
+				status = AE_BAD_PARAMETER;
+				goto unlock_and_exit;
+			}
+			/* Make sure all deferred tasks are completed */
 
-		if ((!notify_obj) ||
-			(notify_obj->notify.handler != handler)) {
-			status = AE_BAD_PARAMETER;
-			goto unlock_and_exit;
-		}
+			(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+			acpi_os_wait_events_complete(NULL);
+			status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+			if (ACPI_FAILURE (status)) {
+				return_ACPI_STATUS (status);
+ 			}
 
-		/* Make sure all deferred tasks are completed */
+			/* Remove the handler */
+			obj_desc->common_notify.system_notify = NULL;
+			acpi_ut_remove_reference (notify_obj);
+		}
 
-		(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
-		acpi_os_wait_events_complete(NULL);
-		status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
-		if (ACPI_FAILURE (status)) {
-			return_ACPI_STATUS (status);
- 		}
+		if (handler_type & ACPI_DEVICE_NOTIFY) {
+			notify_obj = obj_desc->common_notify.device_notify;
+			if ((!notify_obj) ||
+				 (notify_obj->notify.handler != handler)) {
+				status = AE_BAD_PARAMETER;
+				goto unlock_and_exit;
+			}
+			/* Make sure all deferred tasks are completed */
 
-		/* Remove the handler */
+			(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+			acpi_os_wait_events_complete(NULL);
+			status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+			if (ACPI_FAILURE (status)) {
+				return_ACPI_STATUS (status);
+ 			}
 
-		if (handler_type == ACPI_SYSTEM_NOTIFY) {
-			obj_desc->common_notify.system_notify = NULL;
-		}
-		else {
+			/* Remove the handler */
 			obj_desc->common_notify.device_notify = NULL;
+			acpi_ut_remove_reference (notify_obj);
 		}
-
-		acpi_ut_remove_reference (notify_obj);
 	}
 
 
@@ -497,7 +515,7 @@ unlock_and_exit:
  *              gpe_block       - GPE block (NULL == FADT GPEs)
  *              Type            - Whether this GPE should be treated as an
  *                                edge- or level-triggered interrupt.
- *              Handler         - Address of the handler
+ *              Address         - Address of the handler
  *              Context         - Value passed to the handler on each GPE
  *
  * RETURN:      Status
@@ -511,11 +529,12 @@ acpi_install_gpe_handler (
 	acpi_handle                     gpe_device,
 	u32                             gpe_number,
 	u32                             type,
-	acpi_gpe_handler                handler,
+	acpi_event_handler              address,
 	void                            *context)
 {
-	acpi_status                     status;
 	struct acpi_gpe_event_info      *gpe_event_info;
+	struct acpi_handler_info        *handler;
+	acpi_status                     status;
 
 
 	ACPI_FUNCTION_TRACE ("acpi_install_gpe_handler");
@@ -523,7 +542,7 @@ acpi_install_gpe_handler (
 
 	/* Parameter validation */
 
-	if (!handler) {
+	if ((!address) || (type > ACPI_GPE_XRUPT_TYPE_MASK)) {
 		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
 
@@ -542,27 +561,41 @@ acpi_install_gpe_handler (
 
 	/* Make sure that there isn't a handler there already */
 
-	if (gpe_event_info->handler) {
+	if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) {
 		status = AE_ALREADY_EXISTS;
 		goto unlock_and_exit;
 	}
 
-	/* Install the handler */
+	/* Allocate and init handler object */
 
-	acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
-	gpe_event_info->handler = handler;
-	gpe_event_info->context = context;
-	gpe_event_info->flags = (u8) type;
-	acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+	handler = ACPI_MEM_CALLOCATE (sizeof (struct acpi_handler_info));
+	if (!handler) {
+		status = AE_NO_MEMORY;
+		goto unlock_and_exit;
+	}
 
-	/* Clear the GPE (of stale events), the enable it */
+	handler->address    = address;
+	handler->context    = context;
+	handler->method_node = gpe_event_info->dispatch.method_node;
 
-	status = acpi_hw_clear_gpe (gpe_event_info);
+	/* Disable the GPE before installing the handler */
+
+	status = acpi_ev_disable_gpe (gpe_event_info);
 	if (ACPI_FAILURE (status)) {
 		goto unlock_and_exit;
 	}
 
-	status = acpi_hw_enable_gpe (gpe_event_info);
+	/* Install the handler */
+
+	acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
+	gpe_event_info->dispatch.handler = handler;
+
+	/* Setup up dispatch flags to indicate handler (vs. method) */
+
+	gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); /* Clear bits */
+	gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER);
+
+	acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
 
 
 unlock_and_exit:
@@ -577,7 +610,7 @@ unlock_and_exit:
  *
  * PARAMETERS:  gpe_number      - The event to remove a handler
  *              gpe_block       - GPE block (NULL == FADT GPEs)
- *              Handler         - Address of the handler
+ *              Address         - Address of the handler
  *
  * RETURN:      Status
  *
@@ -589,10 +622,11 @@ acpi_status
 acpi_remove_gpe_handler (
 	acpi_handle                     gpe_device,
 	u32                             gpe_number,
-	acpi_gpe_handler                handler)
+	acpi_event_handler              address)
 {
-	acpi_status                     status;
 	struct acpi_gpe_event_info      *gpe_event_info;
+	struct acpi_handler_info        *handler;
+	acpi_status                     status;
 
 
 	ACPI_FUNCTION_TRACE ("acpi_remove_gpe_handler");
@@ -600,7 +634,7 @@ acpi_remove_gpe_handler (
 
 	/* Parameter validation */
 
-	if (!handler) {
+	if (!address) {
 		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
 
@@ -617,21 +651,27 @@ acpi_remove_gpe_handler (
 		goto unlock_and_exit;
 	}
 
-	/* Disable the GPE before removing the handler */
+	/* Make sure that a handler is indeed installed */
 
-	status = acpi_hw_disable_gpe (gpe_event_info);
-	if (ACPI_FAILURE (status)) {
+	if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) != ACPI_GPE_DISPATCH_HANDLER) {
+		status = AE_NOT_EXIST;
 		goto unlock_and_exit;
 	}
 
 	/* Make sure that the installed handler is the same */
 
-	if (gpe_event_info->handler != handler) {
-		(void) acpi_hw_enable_gpe (gpe_event_info);
+	if (gpe_event_info->dispatch.handler->address != address) {
 		status = AE_BAD_PARAMETER;
 		goto unlock_and_exit;
 	}
 
+	/* Disable the GPE before removing the handler */
+
+	status = acpi_ev_disable_gpe (gpe_event_info);
+	if (ACPI_FAILURE (status)) {
+		goto unlock_and_exit;
+	}
+
 	/* Make sure all deferred tasks are completed */
 
 	(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
@@ -644,10 +684,21 @@ acpi_remove_gpe_handler (
 	/* Remove the handler */
 
 	acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
-	gpe_event_info->handler = NULL;
-	gpe_event_info->context = NULL;
+	handler = gpe_event_info->dispatch.handler;
+
+	/* Restore Method node (if any), set dispatch flags */
+
+	gpe_event_info->dispatch.method_node = handler->method_node;
+	gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK; /* Clear bits */
+	if (handler->method_node) {
+		gpe_event_info->flags |= ACPI_GPE_DISPATCH_METHOD;
+	}
 	acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
 
+	/* Now we can free the handler object */
+
+	ACPI_MEM_FREE (handler);
+
 
 unlock_and_exit:
 	(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c
index 640f51fb0..e941678ce 100644
--- a/drivers/acpi/events/evxfevnt.c
+++ b/drivers/acpi/events/evxfevnt.c
@@ -204,12 +204,11 @@ acpi_enable_event (
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_enable_gpe
+ * FUNCTION:    acpi_set_gpe_type
  *
  * PARAMETERS:  gpe_device      - Parent GPE Device
  *              gpe_number      - GPE level within the GPE block
- *              Flags           - Just enable, or also wake enable?
- *                                Called from ISR or not
+ *              Type            - New GPE type
  *
  * RETURN:      Status
  *
@@ -218,26 +217,17 @@ acpi_enable_event (
  ******************************************************************************/
 
 acpi_status
-acpi_enable_gpe (
+acpi_set_gpe_type (
 	acpi_handle                     gpe_device,
 	u32                             gpe_number,
-	u32                             flags)
+	u8                              type)
 {
 	acpi_status                     status = AE_OK;
 	struct acpi_gpe_event_info      *gpe_event_info;
 
 
-	ACPI_FUNCTION_TRACE ("acpi_enable_gpe");
-
+	ACPI_FUNCTION_TRACE ("acpi_set_gpe_type");
 
-	/* Use semaphore lock if not executing at interrupt level */
-
-	if (flags & ACPI_NOT_ISR) {
-		status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
-		if (ACPI_FAILURE (status)) {
-			return_ACPI_STATUS (status);
-		}
-	}
 
 	/* Ensure that we have a valid GPE number */
 
@@ -247,91 +237,72 @@ acpi_enable_gpe (
 		goto unlock_and_exit;
 	}
 
-	/* Check for Wake vs Runtime GPE */
-
-	if (flags & ACPI_EVENT_WAKE_ENABLE) {
-		/* Ensure the requested wake GPE is disabled */
-
-		status = acpi_hw_disable_gpe (gpe_event_info);
-		if (ACPI_FAILURE (status)) {
-			goto unlock_and_exit;
-		}
-
-		/* Defer Enable of Wake GPE until sleep time */
-
-		acpi_hw_enable_gpe_for_wakeup (gpe_event_info);
+	if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == type) {
+		return_ACPI_STATUS (AE_OK);
 	}
-	else {
-		/* Enable the requested runtime GPE  */
 
-		status = acpi_hw_enable_gpe (gpe_event_info);
-		if (ACPI_FAILURE (status)) {
-			goto unlock_and_exit;
-		}
-	}
+	/* Set the new type (will disable GPE if currently enabled) */
 
+	status = acpi_ev_set_gpe_type (gpe_event_info, type);
 
 unlock_and_exit:
-	if (flags & ACPI_NOT_ISR) {
-		(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
-	}
 	return_ACPI_STATUS (status);
 }
 
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_disable_event
+ * FUNCTION:    acpi_enable_gpe
  *
- * PARAMETERS:  Event           - The fixed eventto be enabled
- *              Flags           - Reserved
+ * PARAMETERS:  gpe_device      - Parent GPE Device
+ *              gpe_number      - GPE level within the GPE block
+ *              Flags           - Just enable, or also wake enable?
+ *                                Called from ISR or not
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Disable an ACPI event (fixed)
+ * DESCRIPTION: Enable an ACPI event (general purpose)
  *
  ******************************************************************************/
 
 acpi_status
-acpi_disable_event (
-	u32                             event,
+acpi_enable_gpe (
+	acpi_handle                     gpe_device,
+	u32                             gpe_number,
 	u32                             flags)
 {
 	acpi_status                     status = AE_OK;
-	u32                             value;
+	struct acpi_gpe_event_info      *gpe_event_info;
 
 
-	ACPI_FUNCTION_TRACE ("acpi_disable_event");
+	ACPI_FUNCTION_TRACE ("acpi_enable_gpe");
 
 
-	/* Decode the Fixed Event */
+	/* Use semaphore lock if not executing at interrupt level */
 
-	if (event > ACPI_EVENT_MAX) {
-		return_ACPI_STATUS (AE_BAD_PARAMETER);
+	if (flags & ACPI_NOT_ISR) {
+		status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
+		if (ACPI_FAILURE (status)) {
+			return_ACPI_STATUS (status);
+		}
 	}
 
-	/*
-	 * Disable the requested fixed event (by writing a zero to the
-	 * enable register bit)
-	 */
-	status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
-			 0, ACPI_MTX_LOCK);
-	if (ACPI_FAILURE (status)) {
-		return_ACPI_STATUS (status);
-	}
+	/* Ensure that we have a valid GPE number */
 
-	status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id,
-			 &value, ACPI_MTX_LOCK);
-	if (ACPI_FAILURE (status)) {
-		return_ACPI_STATUS (status);
+	gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
+	if (!gpe_event_info) {
+		status = AE_BAD_PARAMETER;
+		goto unlock_and_exit;
 	}
 
-	if (value != 0) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
-			"Could not disable %s events\n", acpi_ut_get_event_name (event)));
-		return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
-	}
+	/* Perform the enable */
+
+	status = acpi_ev_enable_gpe (gpe_event_info, TRUE);
 
+unlock_and_exit:
+	if (flags & ACPI_NOT_ISR) {
+		(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+	}
 	return_ACPI_STATUS (status);
 }
 
@@ -342,7 +313,7 @@ acpi_disable_event (
  *
  * PARAMETERS:  gpe_device      - Parent GPE Device
  *              gpe_number      - GPE level within the GPE block
- *              Flags           - Just enable, or also wake enable?
+ *              Flags           - Just disable, or also wake disable?
  *                                Called from ISR or not
  *
  * RETURN:      Status
@@ -381,21 +352,69 @@ acpi_disable_gpe (
 		goto unlock_and_exit;
 	}
 
+	status = acpi_ev_disable_gpe (gpe_event_info);
+
+unlock_and_exit:
+	if (flags & ACPI_NOT_ISR) {
+		(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+	}
+	return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_disable_event
+ *
+ * PARAMETERS:  Event           - The fixed eventto be enabled
+ *              Flags           - Reserved
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Disable an ACPI event (fixed)
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_disable_event (
+	u32                             event,
+	u32                             flags)
+{
+	acpi_status                     status = AE_OK;
+	u32                             value;
+
+
+	ACPI_FUNCTION_TRACE ("acpi_disable_event");
+
+
+	/* Decode the Fixed Event */
+
+	if (event > ACPI_EVENT_MAX) {
+		return_ACPI_STATUS (AE_BAD_PARAMETER);
+	}
+
 	/*
-	 * Only disable the requested GPE number for wake if specified.
-	 * Otherwise, turn it totally off
+	 * Disable the requested fixed event (by writing a zero to the
+	 * enable register bit)
 	 */
-	if (flags & ACPI_EVENT_WAKE_DISABLE) {
-		acpi_hw_disable_gpe_for_wakeup (gpe_event_info);
+	status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
+			 0, ACPI_MTX_LOCK);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
 	}
-	else {
-		status = acpi_hw_disable_gpe (gpe_event_info);
+
+	status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id,
+			 &value, ACPI_MTX_LOCK);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
 	}
 
-unlock_and_exit:
-	if (flags & ACPI_NOT_ISR) {
-		(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
+	if (value != 0) {
+		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+			"Could not disable %s events\n", acpi_ut_get_event_name (event)));
+		return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
 	}
+
 	return_ACPI_STATUS (status);
 }
 
diff --git a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c
index b31d4fdfe..8eeb938f7 100644
--- a/drivers/acpi/events/evxfregn.c
+++ b/drivers/acpi/events/evxfregn.c
@@ -46,7 +46,6 @@
 #include <acpi/acpi.h>
 #include <acpi/acnamesp.h>
 #include <acpi/acevents.h>
-#include <acpi/acinterp.h>
 
 #define _COMPONENT          ACPI_EVENTS
 	 ACPI_MODULE_NAME    ("evxfregn")
@@ -76,12 +75,8 @@ acpi_install_address_space_handler (
 	acpi_adr_space_setup            setup,
 	void                            *context)
 {
-	union acpi_operand_object       *obj_desc;
-	union acpi_operand_object       *handler_obj;
 	struct acpi_namespace_node      *node;
 	acpi_status                     status;
-	acpi_object_type                type;
-	u16                             flags = 0;
 
 
 	ACPI_FUNCTION_TRACE ("acpi_install_address_space_handler");
@@ -106,202 +101,16 @@ acpi_install_address_space_handler (
 		goto unlock_and_exit;
 	}
 
-	/*
-	 * This registration is valid for only the types below
-	 * and the root.  This is where the default handlers
-	 * get placed.
-	 */
-	if ((node->type != ACPI_TYPE_DEVICE)     &&
-		(node->type != ACPI_TYPE_PROCESSOR)  &&
-		(node->type != ACPI_TYPE_THERMAL)    &&
-		(node != acpi_gbl_root_node)) {
-		status = AE_BAD_PARAMETER;
-		goto unlock_and_exit;
-	}
-
-	if (handler == ACPI_DEFAULT_HANDLER) {
-		flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
-
-		switch (space_id) {
-		case ACPI_ADR_SPACE_SYSTEM_MEMORY:
-			handler = acpi_ex_system_memory_space_handler;
-			setup   = acpi_ev_system_memory_region_setup;
-			break;
-
-		case ACPI_ADR_SPACE_SYSTEM_IO:
-			handler = acpi_ex_system_io_space_handler;
-			setup   = acpi_ev_io_space_region_setup;
-			break;
-
-		case ACPI_ADR_SPACE_PCI_CONFIG:
-			handler = acpi_ex_pci_config_space_handler;
-			setup   = acpi_ev_pci_config_region_setup;
-			break;
-
-		case ACPI_ADR_SPACE_CMOS:
-			handler = acpi_ex_cmos_space_handler;
-			setup   = acpi_ev_cmos_region_setup;
-			break;
-
-		case ACPI_ADR_SPACE_PCI_BAR_TARGET:
-			handler = acpi_ex_pci_bar_space_handler;
-			setup   = acpi_ev_pci_bar_region_setup;
-			break;
-
-		case ACPI_ADR_SPACE_DATA_TABLE:
-			handler = acpi_ex_data_table_space_handler;
-			setup   = NULL;
-			break;
-
-		default:
-			status = AE_BAD_PARAMETER;
-			goto unlock_and_exit;
-		}
-	}
-
-	/* If the caller hasn't specified a setup routine, use the default */
-
-	if (!setup) {
-		setup = acpi_ev_default_region_setup;
-	}
-
-	/* Check for an existing internal object */
-
-	obj_desc = acpi_ns_get_attached_object (node);
-	if (obj_desc) {
-		/*
-		 * The attached device object already exists.
-		 * Make sure the handler is not already installed.
-		 */
-		handler_obj = obj_desc->device.handler;
-
-		/* Walk the handler list for this device */
-
-		while (handler_obj) {
-			/* Same space_id indicates a handler already installed */
-
-			if(handler_obj->address_space.space_id == space_id) {
-				if (handler_obj->address_space.handler == handler) {
-					/*
-					 * It is (relatively) OK to attempt to install the SAME
-					 * handler twice. This can easily happen with PCI_Config space.
-					 */
-					status = AE_SAME_HANDLER;
-					goto unlock_and_exit;
-				}
-				else {
-					/* A handler is already installed */
-
-					status = AE_ALREADY_EXISTS;
-				}
-				goto unlock_and_exit;
-			}
-
-			/* Walk the linked list of handlers */
-
-			handler_obj = handler_obj->address_space.next;
-		}
-	}
-	else {
-		ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
-			"Creating object on Device %p while installing handler\n", node));
-
-		/* obj_desc does not exist, create one */
-
-		if (node->type == ACPI_TYPE_ANY) {
-			type = ACPI_TYPE_DEVICE;
-		}
-		else {
-			type = node->type;
-		}
-
-		obj_desc = acpi_ut_create_internal_object (type);
-		if (!obj_desc) {
-			status = AE_NO_MEMORY;
-			goto unlock_and_exit;
-		}
-
-		/* Init new descriptor */
-
-		obj_desc->common.type = (u8) type;
-
-		/* Attach the new object to the Node */
+	/* Install the handler for all Regions for this Space ID */
 
-		status = acpi_ns_attach_object (node, obj_desc, type);
-
-		/* Remove local reference to the object */
-
-		acpi_ut_remove_reference (obj_desc);
-
-		if (ACPI_FAILURE (status)) {
-			goto unlock_and_exit;
-		}
-	}
-
-	ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
-		"Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
-		acpi_ut_get_region_name (space_id), space_id,
-		acpi_ut_get_node_name (node), node, obj_desc));
-
-	/*
-	 * Install the handler
-	 *
-	 * At this point there is no existing handler.
-	 * Just allocate the object for the handler and link it
-	 * into the list.
-	 */
-	handler_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
-	if (!handler_obj) {
-		status = AE_NO_MEMORY;
+	status = acpi_ev_install_space_handler (node, space_id, handler, setup, context);
+	if (ACPI_FAILURE (status)) {
 		goto unlock_and_exit;
 	}
 
-	/* Init handler obj */
-
-	handler_obj->address_space.space_id  = (u8) space_id;
-	handler_obj->address_space.hflags    = flags;
-	handler_obj->address_space.region_list = NULL;
-	handler_obj->address_space.node      = node;
-	handler_obj->address_space.handler   = handler;
-	handler_obj->address_space.context   = context;
-	handler_obj->address_space.setup     = setup;
-
-	/* Install at head of Device.address_space list */
-
-	handler_obj->address_space.next      = obj_desc->device.handler;
-
-	/*
-	 * The Device object is the first reference on the handler_obj.
-	 * Each region that uses the handler adds a reference.
-	 */
-	obj_desc->device.handler = handler_obj;
-
-	/*
-	 * Walk the namespace finding all of the regions this
-	 * handler will manage.
-	 *
-	 * Start at the device and search the branch toward
-	 * the leaf nodes until either the leaf is encountered or
-	 * a device is detected that has an address handler of the
-	 * same type.
-	 *
-	 * In either case, back up and search down the remainder
-	 * of the branch
-	 */
-	status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, device, ACPI_UINT32_MAX,
-			  ACPI_NS_WALK_UNLOCK, acpi_ev_install_handler,
-			  handler_obj, NULL);
-
-	/*
-	 * Now we can run the _REG methods for all Regions for this
-	 * space ID.  This is a separate walk in order to handle any
-	 * interdependencies between regions and _REG methods.  (i.e. handlers
-	 * must be installed for all regions of this Space ID before we
-	 * can run any _REG methods.
-	 */
-	status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, device, ACPI_UINT32_MAX,
-			  ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
-			  handler_obj, NULL);
+	/* Run all _REG methods for this address space */
+
+	status = acpi_ev_execute_reg_methods (node, space_id);
 
 unlock_and_exit:
 	(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c
index dfe7e0463..1e6a89805 100644
--- a/drivers/acpi/executer/exconfig.c
+++ b/drivers/acpi/executer/exconfig.c
@@ -48,6 +48,7 @@
 #include <acpi/acnamesp.h>
 #include <acpi/acevents.h>
 #include <acpi/actables.h>
+#include <acpi/acdispat.h>
 
 
 #define _COMPONENT          ACPI_EXECUTER
@@ -285,7 +286,7 @@ acpi_ex_load_op (
 	union acpi_operand_object       *ddb_handle;
 	union acpi_operand_object       *buffer_desc = NULL;
 	struct acpi_table_header        *table_ptr = NULL;
-	u8                              *table_data_ptr;
+	acpi_physical_address           address;
 	struct acpi_table_header        table_header;
 	u32                             i;
 
@@ -300,18 +301,39 @@ acpi_ex_load_op (
 		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Load from Region %p %s\n",
 			obj_desc, acpi_ut_get_object_type_name (obj_desc)));
 
-		/* Get the table header */
+		/*
+		 * If the Region Address and Length have not been previously evaluated,
+		 * evaluate them now and save the results.
+		 */
+		if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
+			status = acpi_ds_get_region_arguments (obj_desc);
+			if (ACPI_FAILURE (status)) {
+				return_ACPI_STATUS (status);
+			}
+		}
+
+		/* Get the base physical address of the region */
+
+		address = obj_desc->region.address;
+
+		/* Get the table length from the table header */
 
 		table_header.length = 0;
-		for (i = 0; i < sizeof (struct acpi_table_header); i++) {
+		for (i = 0; i < 8; i++) {
 			status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ,
-					   (acpi_physical_address) i, 8,
+					   (acpi_physical_address) (i + address), 8,
 					   ((u8 *) &table_header) + i);
 			if (ACPI_FAILURE (status)) {
 				return_ACPI_STATUS (status);
 			}
 		}
 
+		/* Sanity check the table length */
+
+		if (table_header.length < sizeof (struct acpi_table_header)) {
+			return_ACPI_STATUS (AE_BAD_HEADER);
+		}
+
 		/* Allocate a buffer for the entire table */
 
 		table_ptr = ACPI_MEM_ALLOCATE (table_header.length);
@@ -319,17 +341,12 @@ acpi_ex_load_op (
 			return_ACPI_STATUS (AE_NO_MEMORY);
 		}
 
-		/* Copy the header to the buffer */
-
-		ACPI_MEMCPY (table_ptr, &table_header, sizeof (struct acpi_table_header));
-		table_data_ptr = ACPI_PTR_ADD (u8, table_ptr, sizeof (struct acpi_table_header));
-
-		/* Get the table from the op region */
+		/* Get the entire table from the op region */
 
 		for (i = 0; i < table_header.length; i++) {
 			status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ,
-					   (acpi_physical_address) i, 8,
-					   ((u8 *) table_data_ptr + i));
+					   (acpi_physical_address) (i + address), 8,
+					   ((u8 *) table_ptr + i));
 			if (ACPI_FAILURE (status)) {
 				goto cleanup;
 			}
@@ -355,6 +372,12 @@ acpi_ex_load_op (
 		}
 
 		table_ptr = ACPI_CAST_PTR (struct acpi_table_header, buffer_desc->buffer.pointer);
+
+		 /* Sanity check the table length */
+
+		if (table_ptr->length < sizeof (struct acpi_table_header)) {
+			return_ACPI_STATUS (AE_BAD_HEADER);
+		}
 		break;
 
 
diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c
index 4ce49b9bf..03ccfb9e1 100644
--- a/drivers/acpi/executer/exfldio.c
+++ b/drivers/acpi/executer/exfldio.c
@@ -130,6 +130,21 @@ acpi_ex_setup_region (
 	if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset
 			   + field_datum_byte_offset
 			   + obj_desc->common_field.access_byte_width)) {
+		if (acpi_gbl_enable_interpreter_slack) {
+			/*
+			 * Slack mode only:  We will go ahead and allow access to this
+			 * field if it is within the region length rounded up to the next
+			 * access width boundary.
+			 */
+			if (ACPI_ROUND_UP (rgn_desc->region.length,
+					   obj_desc->common_field.access_byte_width) >=
+				(obj_desc->common_field.base_byte_offset +
+				 obj_desc->common_field.access_byte_width +
+				 field_datum_byte_offset)) {
+				return_ACPI_STATUS (AE_OK);
+			}
+		}
+
 		if (rgn_desc->region.length < obj_desc->common_field.access_byte_width) {
 			/*
 			 * This is the case where the access_type (acc_word, etc.) is wider
@@ -154,40 +169,7 @@ acpi_ex_setup_region (
 			field_datum_byte_offset, obj_desc->common_field.access_byte_width,
 			acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length));
 
-		if (!acpi_strict) {
-			/*
-			 * Allow access to the field if it is within the region size
-			 * rounded up to a multiple of the access byte width.  This
-			 * overcomes "off-by-one" programming errors in the AML often
-			 * found in Toshiba laptops.  These errors were allowed by
-			 * the Microsoft ASL compiler.
-			 */
-			u32 rounded_length = ACPI_ROUND_UP(rgn_desc->region.length,
-									obj_desc->common_field.access_byte_width);
-
-			if (rounded_length < (obj_desc->common_field.base_byte_offset
-						+ field_datum_byte_offset
-						+ obj_desc->common_field.access_byte_width)) {
-				return_ACPI_STATUS (AE_AML_REGION_LIMIT);
-			} else {
-				static int	warn_once = 1;
-				if (warn_once) {
-					// Could also associate a flag with each field, and
-					// warn once for each field.
-					ACPI_REPORT_WARNING((
-						"The ACPI AML in your computer contains errors, "
-						"please nag the manufacturer to correct it.\n"));
-					ACPI_REPORT_WARNING((
-						"Allowing relaxed access to fields; "
-						"turn on CONFIG_ACPI_DEBUG for details.\n"));
-					warn_once = 0;
-				}
-				return_ACPI_STATUS (AE_OK);
-			}
-		}
-		else {
-			return_ACPI_STATUS (AE_AML_REGION_LIMIT);
-		}
+		return_ACPI_STATUS (AE_AML_REGION_LIMIT);
 	}
 
 	return_ACPI_STATUS (AE_OK);
@@ -277,7 +259,7 @@ acpi_ex_access_region (
 				rgn_desc->region.space_id));
 		}
 		else if (status == AE_NOT_EXIST) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+			ACPI_REPORT_ERROR ((
 				"Region %s(%X) has no handler\n",
 				acpi_ut_get_region_name (rgn_desc->region.space_id),
 				rgn_desc->region.space_id));
@@ -764,16 +746,85 @@ acpi_ex_set_buffer_datum (
 }
 
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ex_common_buffer_setup
+ *
+ * PARAMETERS:  obj_desc            - Field object
+ *              buffer_length       - Length of caller's buffer
+ *              datum_count         - Where the datum_count is returned
+ *
+ * RETURN:      Status, datum_count
+ *
+ * DESCRIPTION: Common code to validate the incoming buffer size and compute
+ *              the number of field "datums" that must be read or written.
+ *              A "datum" is the smallest unit that can be read or written
+ *              to the field, it is either 1,2,4, or 8 bytes.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ex_common_buffer_setup (
+	union acpi_operand_object       *obj_desc,
+	u32                             buffer_length,
+	u32                             *datum_count)
+{
+	u32                             byte_field_length;
+	u32                             actual_byte_field_length;
+
+
+	ACPI_FUNCTION_TRACE ("ex_common_buffer_setup");
+
+
+	/*
+	 * Incoming buffer must be at least as long as the field, we do not
+	 * allow "partial" field reads/writes.  We do not care if the buffer is
+	 * larger than the field, this typically happens when an integer is
+	 * read/written to a field that is actually smaller than an integer.
+	 */
+	byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (
+			 obj_desc->common_field.bit_length);
+	if (byte_field_length > buffer_length) {
+		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+			"Field size %X (bytes) is too large for buffer (%X)\n",
+			byte_field_length, buffer_length));
+
+		return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
+	}
+
+	/*
+	 * Create "actual" field byte count (minimum number of bytes that
+	 * must be read), then convert to datum count (minimum number
+	 * of datum-sized units that must be read)
+	 */
+	actual_byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (
+			  obj_desc->common_field.start_field_bit_offset +
+			  obj_desc->common_field.bit_length);
+
+
+	*datum_count = ACPI_ROUND_UP_TO (actual_byte_field_length,
+			   obj_desc->common_field.access_byte_width);
+
+	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
+		"buffer_bytes %X, actual_bytes %X, Datums %X, byte_gran %X\n",
+		byte_field_length, actual_byte_field_length,
+		*datum_count, obj_desc->common_field.access_byte_width));
+
+	return_ACPI_STATUS (AE_OK);
+}
+
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ex_extract_from_field
  *
- * PARAMETERS:  *obj_desc           - Field to be read
- *              *Value              - Where to store value
+ * PARAMETERS:  obj_desc            - Field to be read
+ *              Buffer              - Where to store the field data
+ *              buffer_length       - Length of Buffer
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Retrieve the value of the given field
+ * DESCRIPTION: Retrieve the current value of the given field
  *
  ******************************************************************************/
 
@@ -789,7 +840,6 @@ acpi_ex_extract_from_field (
 	acpi_integer                    previous_raw_datum = 0;
 	acpi_integer                    this_raw_datum = 0;
 	acpi_integer                    merged_datum = 0;
-	u32                             byte_field_length;
 	u32                             datum_count;
 	u32                             i;
 
@@ -797,39 +847,13 @@ acpi_ex_extract_from_field (
 	ACPI_FUNCTION_TRACE ("ex_extract_from_field");
 
 
-	/*
-	 * The field must fit within the caller's buffer
-	 */
-	byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->common_field.bit_length);
-	if (byte_field_length > buffer_length) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
-			"Field size %X (bytes) too large for buffer (%X)\n",
-			byte_field_length, buffer_length));
-
-		return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
-	}
-
-	/* Convert field byte count to datum count, round up if necessary */
-
-	datum_count = ACPI_ROUND_UP_TO (byte_field_length,
-			   obj_desc->common_field.access_byte_width);
+	/* Validate buffer, compute number of datums */
 
-	/*
-	 * If the field is not aligned on a datum boundary and does not
-	 * fit within a single datum, we must read an extra datum.
-	 *
-	 * We could just split the aligned and non-aligned cases since the
-	 * aligned case is so very simple, but this would require more code.
-	 */
-	if ((obj_desc->common_field.end_field_valid_bits != 0)    &&
-		(!(obj_desc->common_field.flags & AOPOBJ_SINGLE_DATUM))) {
-		datum_count++;
+	status = acpi_ex_common_buffer_setup (obj_desc, buffer_length, &datum_count);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
 	}
 
-	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
-		"byte_len %X, datum_len %X, byte_gran %X\n",
-		byte_field_length, datum_count,obj_desc->common_field.access_byte_width));
-
 	/*
 	 * Clear the caller's buffer (the whole buffer length as given)
 	 * This is very important, especially in the cases where the buffer
@@ -942,12 +966,13 @@ acpi_ex_extract_from_field (
  *
  * FUNCTION:    acpi_ex_insert_into_field
  *
- * PARAMETERS:  *obj_desc           - Field to be set
- *              Buffer              - Value to store
+ * PARAMETERS:  obj_desc            - Field to be written
+ *              Buffer              - Data to be written
+ *              buffer_length       - Length of Buffer
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Store the value into the given field
+ * DESCRIPTION: Store the Buffer contents into the given field
  *
  ******************************************************************************/
 
@@ -964,42 +989,19 @@ acpi_ex_insert_into_field (
 	acpi_integer                    merged_datum;
 	acpi_integer                    previous_raw_datum;
 	acpi_integer                    this_raw_datum;
-	u32                             byte_field_length;
 	u32                             datum_count;
 
 
 	ACPI_FUNCTION_TRACE ("ex_insert_into_field");
 
 
-	/*
-	 * Incoming buffer must be at least as long as the field, we do not
-	 * allow "partial" field writes.  We do not care if the buffer is
-	 * larger than the field, this typically happens when an integer is
-	 * written to a field that is actually smaller than an integer.
-	 */
-	byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (
-			 obj_desc->common_field.bit_length);
-	if (buffer_length < byte_field_length) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
-			"Buffer length %X too small for field %X\n",
-			buffer_length, byte_field_length));
+	/* Validate buffer, compute number of datums */
 
-		return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
+	status = acpi_ex_common_buffer_setup (obj_desc, buffer_length, &datum_count);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
 	}
 
-	byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (
-			 obj_desc->common_field.start_field_bit_offset +
-			 obj_desc->common_field.bit_length);
-
-	/* Convert byte count to datum count, round up if necessary */
-
-	datum_count = ACPI_ROUND_UP_TO (byte_field_length,
-			  obj_desc->common_field.access_byte_width);
-
-	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
-		"Bytes %X, Datums %X, byte_gran %X\n",
-		byte_field_length, datum_count, obj_desc->common_field.access_byte_width));
-
 	/*
 	 * Break the request into up to three parts (similar to an I/O request):
 	 * 1) non-aligned part at start
diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c
index 74fd68491..961a949e9 100644
--- a/drivers/acpi/executer/exmisc.c
+++ b/drivers/acpi/executer/exmisc.c
@@ -389,6 +389,8 @@ acpi_ex_do_math_op (
 	acpi_integer                    operand1)
 {
 
+	ACPI_FUNCTION_ENTRY ();
+
 
 	switch (opcode) {
 	case AML_ADD_OP:                /* Add (Operand0, Operand1, Result) */
@@ -452,15 +454,17 @@ acpi_ex_do_math_op (
  * FUNCTION:    acpi_ex_do_logical_op
  *
  * PARAMETERS:  Opcode              - AML opcode
- *              Operand0            - Integer operand #0
- *              Operand1            - Integer operand #1
+ *              obj_desc0           - operand #0
+ *              obj_desc1           - operand #1
  *
  * RETURN:      TRUE/FALSE result of the operation
  *
  * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
  *              functions here is to prevent a lot of pointer dereferencing
  *              to obtain the operands and to simplify the generation of the
- *              logical value.
+ *              logical value.  Both operands must already be validated as
+ *              1) Both the same type, and
+ *              2) Either Integer, Buffer, or String type.
  *
  *              Note: cleanest machine code seems to be produced by the code
  *              below, rather than using statements of the form:
@@ -471,54 +475,137 @@ acpi_ex_do_math_op (
 u8
 acpi_ex_do_logical_op (
 	u16                             opcode,
-	acpi_integer                    operand0,
-	acpi_integer                    operand1)
+	union acpi_operand_object       *obj_desc0,
+	union acpi_operand_object       *obj_desc1)
 {
+	acpi_integer                    operand0;
+	acpi_integer                    operand1;
+	u8                              *ptr0;
+	u8                              *ptr1;
+	u32                             length0;
+	u32                             length1;
+	u32                             i;
 
 
-	switch (opcode) {
+	ACPI_FUNCTION_ENTRY ();
 
-	case AML_LAND_OP:               /* LAnd (Operand0, Operand1) */
 
-		if (operand0 && operand1) {
-			return (TRUE);
-		}
-		break;
+	if (ACPI_GET_OBJECT_TYPE (obj_desc0) == ACPI_TYPE_INTEGER) {
+		/* Both operands are of type integer */
 
+		operand0 = obj_desc0->integer.value;
+		operand1 = obj_desc1->integer.value;
 
-	case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
+		switch (opcode) {
+		case AML_LAND_OP:               /* LAnd (Operand0, Operand1) */
 
-		if (operand0 == operand1) {
-			return (TRUE);
-		}
-		break;
+			if (operand0 && operand1) {
+				return (TRUE);
+			}
+			break;
 
+		case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
 
-	case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
+			if (operand0 == operand1) {
+				return (TRUE);
+			}
+			break;
 
-		if (operand0 > operand1) {
-			return (TRUE);
-		}
-		break;
+		case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
+
+			if (operand0 > operand1) {
+				return (TRUE);
+			}
+			break;
+
+		case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
 
+			if (operand0 < operand1) {
+				return (TRUE);
+			}
+			break;
 
-	case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
+		case AML_LOR_OP:                 /* LOr (Operand0, Operand1) */
 
-		if (operand0 < operand1) {
-			return (TRUE);
+			if (operand0 || operand1) {
+				return (TRUE);
+			}
+			break;
+
+		default:
+			break;
 		}
-		break;
+	}
+	else {
+		/*
+		 * Case for Buffer/String objects.
+		 * NOTE: takes advantage of common Buffer/String object fields
+		 */
+		length0 = obj_desc0->buffer.length;
+		ptr0    = obj_desc0->buffer.pointer;
+
+		length1 = obj_desc1->buffer.length;
+		ptr1    = obj_desc1->buffer.pointer;
+
+		switch (opcode) {
+		case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
 
+			/* Length and all bytes must be equal */
 
-	case AML_LOR_OP:                 /* LOr (Operand0, Operand1) */
+			if (length0 != length1) {
+				return (FALSE);
+			}
 
-		if (operand0 || operand1) {
+			for (i = 0; i < length0; i++) {
+				if (ptr0[i] != ptr1[i]) {
+					return (FALSE);
+				}
+			}
 			return (TRUE);
-		}
-		break;
 
-	default:
-		break;
+		case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
+
+			/* Lexicographic compare:  Scan the 1-to-1 data */
+
+			for (i = 0; (i < length0) && (i < length1); i++) {
+				if (ptr0[i] > ptr1[i]) {
+					return (TRUE);
+				}
+			}
+
+			/* Bytes match, now check lengths */
+
+			if (length0 > length1) {
+				return (TRUE);
+			}
+
+			/* Length0 <= Length1 */
+
+			return (FALSE);
+
+		case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
+
+			/* Lexicographic compare:  Scan the 1-to-1 data */
+
+			for (i = 0; (i < length0) && (i < length1); i++) {
+				if (ptr0[i] < ptr1[i]) {
+					return (TRUE);
+				}
+			}
+
+			/* Bytes match, now check lengths */
+
+			if (length0 < length1) {
+				return (TRUE);
+			}
+
+			/* Length0 >= Length1 */
+
+			return (FALSE);
+
+		default:
+			break;
+		}
 	}
 
 	return (FALSE);
diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c
index cee2c126e..c709ed2f5 100644
--- a/drivers/acpi/executer/exmutex.c
+++ b/drivers/acpi/executer/exmutex.c
@@ -54,7 +54,7 @@
  *
  * FUNCTION:    acpi_ex_unlink_mutex
  *
- * PARAMETERS:  *obj_desc           - The mutex to be unlinked
+ * PARAMETERS:  obj_desc            - The mutex to be unlinked
  *
  * RETURN:      Status
  *
@@ -73,6 +73,8 @@ acpi_ex_unlink_mutex (
 		return;
 	}
 
+	/* Doubly linked list */
+
 	if (obj_desc->mutex.next) {
 		(obj_desc->mutex.next)->mutex.prev = obj_desc->mutex.prev;
 	}
@@ -90,8 +92,8 @@ acpi_ex_unlink_mutex (
  *
  * FUNCTION:    acpi_ex_link_mutex
  *
- * PARAMETERS:  *obj_desc           - The mutex to be linked
- *              *list_head          - head of the "acquired_mutex" list
+ * PARAMETERS:  obj_desc            - The mutex to be linked
+ *              list_head           - head of the "acquired_mutex" list
  *
  * RETURN:      Status
  *
@@ -130,8 +132,8 @@ acpi_ex_link_mutex (
  *
  * FUNCTION:    acpi_ex_acquire_mutex
  *
- * PARAMETERS:  *time_desc          - The 'time to delay' object descriptor
- *              *obj_desc           - The object descriptor for this op
+ * PARAMETERS:  time_desc           - The 'time to delay' object descriptor
+ *              obj_desc            - The object descriptor for this op
  *
  * RETURN:      Status
  *
@@ -173,9 +175,8 @@ acpi_ex_acquire_mutex (
 		return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
 	}
 
-	/*
-	 * Support for multiple acquires by the owning thread
-	 */
+	/* Support for multiple acquires by the owning thread */
+
 	if (obj_desc->mutex.owner_thread) {
 		/* Special case for Global Lock, allow all threads */
 
@@ -199,10 +200,11 @@ acpi_ex_acquire_mutex (
 		return_ACPI_STATUS (status);
 	}
 
-	/* Have the mutex, update mutex and walk info */
+	/* Have the mutex: update mutex and walk info and save the sync_level */
 
-	obj_desc->mutex.owner_thread    = walk_state->thread;
+	obj_desc->mutex.owner_thread     = walk_state->thread;
 	obj_desc->mutex.acquisition_depth = 1;
+	obj_desc->mutex.original_sync_level = walk_state->thread->current_sync_level;
 
 	walk_state->thread->current_sync_level = obj_desc->mutex.sync_level;
 
@@ -218,7 +220,7 @@ acpi_ex_acquire_mutex (
  *
  * FUNCTION:    acpi_ex_release_mutex
  *
- * PARAMETERS:  *obj_desc           - The object descriptor for this op
+ * PARAMETERS:  obj_desc            - The object descriptor for this op
  *
  * RETURN:      Status
  *
@@ -281,9 +283,8 @@ acpi_ex_release_mutex (
 		return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
 	}
 
-	/*
-	 * Match multiple Acquires with multiple Releases
-	 */
+	/* Match multiple Acquires with multiple Releases */
+
 	obj_desc->mutex.acquisition_depth--;
 	if (obj_desc->mutex.acquisition_depth != 0) {
 		/* Just decrement the depth and return */
@@ -299,10 +300,10 @@ acpi_ex_release_mutex (
 
 	status = acpi_ex_system_release_mutex (obj_desc);
 
-	/* Update the mutex and walk state */
+	/* Update the mutex and walk state, restore sync_level before acquire */
 
 	obj_desc->mutex.owner_thread = NULL;
-	walk_state->thread->current_sync_level = obj_desc->mutex.sync_level;
+	walk_state->thread->current_sync_level = obj_desc->mutex.original_sync_level;
 
 	return_ACPI_STATUS (status);
 }
@@ -312,7 +313,7 @@ acpi_ex_release_mutex (
  *
  * FUNCTION:    acpi_ex_release_all_mutexes
  *
- * PARAMETERS:  *mutex_list           - Head of the mutex list
+ * PARAMETERS:  mutex_list            - Head of the mutex list
  *
  * RETURN:      Status
  *
@@ -332,9 +333,8 @@ acpi_ex_release_all_mutexes (
 	ACPI_FUNCTION_ENTRY ();
 
 
-	/*
-	 * Traverse the list of owned mutexes, releasing each one.
-	 */
+	/* Traverse the list of owned mutexes, releasing each one */
+
 	while (next) {
 		this = next;
 		next = this->mutex.next;
@@ -352,7 +352,11 @@ acpi_ex_release_all_mutexes (
 
 		/* Mark mutex unowned */
 
-		this->mutex.owner_thread     = NULL;
+		this->mutex.owner_thread = NULL;
+
+		/* Update Thread sync_level (Last mutex is the important one) */
+
+		thread->current_sync_level = this->mutex.original_sync_level;
 	}
 }
 
diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c
index 70602ad44..0b6f86a91 100644
--- a/drivers/acpi/executer/exoparg2.c
+++ b/drivers/acpi/executer/exoparg2.c
@@ -97,6 +97,7 @@ acpi_ex_opcode_2A_0T_0R (
 {
 	union acpi_operand_object       **operand = &walk_state->operands[0];
 	struct acpi_namespace_node      *node;
+	u32                             value;
 	acpi_status                     status = AE_OK;
 
 
@@ -113,16 +114,46 @@ acpi_ex_opcode_2A_0T_0R (
 
 		node = (struct acpi_namespace_node *) operand[0];
 
+		/* Second value is the notify value */
+
+		value = (u32) operand[1]->integer.value;
+
 		/* Notifies allowed on this object? */
 
 		if (!acpi_ev_is_notify_object (node)) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unexpected notify object type [%s]\n",
+			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+					"Unexpected notify object type [%s]\n",
 					acpi_ut_get_type_name (node->type)));
 
 			status = AE_AML_OPERAND_TYPE;
 			break;
 		}
 
+#ifdef ACPI_GPE_NOTIFY_CHECK
+		/*
+		 * GPE method wake/notify check.  Here, we want to ensure that we
+		 * don't receive any "device_wake" Notifies from a GPE _Lxx or _Exx
+		 * GPE method during system runtime.  If we do, the GPE is marked
+		 * as "wake-only" and disabled.
+		 *
+		 * 1) Is the Notify() value == device_wake?
+		 * 2) Is this a GPE deferred method?  (An _Lxx or _Exx method)
+		 * 3) Did the original GPE happen at system runtime?
+		 *    (versus during wake)
+		 *
+		 * If all three cases are true, this is a wake-only GPE that should
+		 * be disabled at runtime.
+		 */
+		if (value == 2)     /* device_wake */ {
+			status = acpi_ev_check_for_wake_only_gpe (walk_state->gpe_event_info);
+			if (ACPI_FAILURE (status)) {
+				/* AE_WAKE_ONLY_GPE only error, means ignore this notify */
+
+				return_ACPI_STATUS (AE_OK)
+			}
+		}
+#endif
+
 		/*
 		 * Dispatch the notify to the appropriate handler
 		 * NOTE: the request is queued for execution after this method
@@ -130,8 +161,7 @@ acpi_ex_opcode_2A_0T_0R (
 		 * from this thread -- because handlers may in turn run other
 		 * control methods.
 		 */
-		status = acpi_ev_queue_notify_request (node,
-				  (u32) operand[1]->integer.value);
+		status = acpi_ev_queue_notify_request (node, value);
 		break;
 
 
@@ -543,9 +573,17 @@ acpi_ex_opcode_2A_0T_1R (
 	 * Execute the Opcode
 	 */
 	if (walk_state->op_info->flags & AML_LOGICAL) /* logical_op (Operand0, Operand1) */ {
+		/* Both operands must be of the same type */
+
+		if (ACPI_GET_OBJECT_TYPE (operand[0]) !=
+			ACPI_GET_OBJECT_TYPE (operand[1])) {
+			status = AE_AML_OPERAND_TYPE;
+			goto cleanup;
+		}
+
 		logical_result = acpi_ex_do_logical_op (walk_state->opcode,
-				 operand[0]->integer.value,
-				 operand[1]->integer.value);
+				 operand[0],
+				 operand[1]);
 		goto store_logical_result;
 	}
 
diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c
index e998da7cd..504d53f4a 100644
--- a/drivers/acpi/executer/exresolv.c
+++ b/drivers/acpi/executer/exresolv.c
@@ -187,15 +187,15 @@ acpi_ex_resolve_object_to_value (
 				return_ACPI_STATUS (status);
 			}
 
+			ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Arg/Local %X] value_obj is %p\n",
+				stack_desc->reference.offset, obj_desc));
+
 			/*
 			 * Now we can delete the original Reference Object and
-			 * replace it with the resolve value
+			 * replace it with the resolved value
 			 */
 			acpi_ut_remove_reference (stack_desc);
 			*stack_ptr = obj_desc;
-
-			ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Arg/Local %d] value_obj is %p\n",
-				stack_desc->reference.offset, obj_desc));
 			break;
 
 
diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c
index 8c884652c..25464f751 100644
--- a/drivers/acpi/executer/exstore.c
+++ b/drivers/acpi/executer/exstore.c
@@ -102,7 +102,8 @@ acpi_ex_store (
 		 * Storing an object into a Named node.
 		 */
 		status = acpi_ex_store_object_to_node (source_desc,
-				 (struct acpi_namespace_node *) dest_desc, walk_state);
+				 (struct acpi_namespace_node *) dest_desc, walk_state,
+				 ACPI_IMPLICIT_CONVERSION);
 
 		return_ACPI_STATUS (status);
 	}
@@ -153,7 +154,7 @@ acpi_ex_store (
 		/* Storing an object into a Name "container" */
 
 		status = acpi_ex_store_object_to_node (source_desc, ref_desc->reference.object,
-				  walk_state);
+				  walk_state, ACPI_IMPLICIT_CONVERSION);
 		break;
 
 
@@ -399,6 +400,7 @@ acpi_ex_store_object_to_index (
  * PARAMETERS:  source_desc             - Value to be stored
  *              Node                    - Named object to receive the value
  *              walk_state              - Current walk state
+ *              implicit_conversion     - Perform implicit conversion (yes/no)
  *
  * RETURN:      Status
  *
@@ -421,7 +423,8 @@ acpi_status
 acpi_ex_store_object_to_node (
 	union acpi_operand_object       *source_desc,
 	struct acpi_namespace_node      *node,
-	struct acpi_walk_state          *walk_state)
+	struct acpi_walk_state          *walk_state,
+	u8                              implicit_conversion)
 {
 	acpi_status                     status = AE_OK;
 	union acpi_operand_object       *target_desc;
@@ -451,6 +454,14 @@ acpi_ex_store_object_to_node (
 		return_ACPI_STATUS (status);
 	}
 
+	/* If no implicit conversion, drop into the default case below */
+
+	if (!implicit_conversion) {
+		/* Force execution of default (no implicit conversion) */
+
+		target_type = ACPI_TYPE_ANY;
+	}
+
 	/*
 	 * Do the actual store operation
 	 */
diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c
index f3fddc274..3910b5ec9 100644
--- a/drivers/acpi/hardware/hwgpe.c
+++ b/drivers/acpi/hardware/hwgpe.c
@@ -51,104 +51,24 @@
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_hw_enable_gpe
+ * FUNCTION:    acpi_hw_write_gpe_enable_reg
  *
  * PARAMETERS:  gpe_event_info      - Info block for the GPE to be enabled
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Enable a single GPE.
+ * DESCRIPTION: Write a GPE enable register.  Note: The bit for this GPE must
+ *              already be cleared or set in the parent register
+ *              enable_for_run mask.
  *
  ******************************************************************************/
 
 acpi_status
-acpi_hw_enable_gpe (
-	struct acpi_gpe_event_info      *gpe_event_info)
-{
-	u32                             in_byte;
-	acpi_status                     status;
-
-
-	ACPI_FUNCTION_ENTRY ();
-
-
-	/*
-	 * Read the current value of the register, set the appropriate bit
-	 * to enable the GPE, and write out the new register.
-	 */
-	status = acpi_hw_low_level_read (8, &in_byte,
-			  &gpe_event_info->register_info->enable_address);
-	if (ACPI_FAILURE (status)) {
-		return (status);
-	}
-
-	/* Write with the new GPE bit enabled */
-
-	status = acpi_hw_low_level_write (8, (in_byte | gpe_event_info->bit_mask),
-			  &gpe_event_info->register_info->enable_address);
-
-	return (status);
-}
-
-
-/******************************************************************************
- *
- * FUNCTION:    acpi_hw_enable_gpe_for_wakeup
- *
- * PARAMETERS:  gpe_event_info      - Info block for the GPE to be enabled
- *
- * RETURN:      None
- *
- * DESCRIPTION: Keep track of which GPEs the OS has requested not be
- *              disabled when going to sleep.
- *
- ******************************************************************************/
-
-void
-acpi_hw_enable_gpe_for_wakeup (
+acpi_hw_write_gpe_enable_reg (
 	struct acpi_gpe_event_info      *gpe_event_info)
 {
 	struct acpi_gpe_register_info   *gpe_register_info;
-
-
-	ACPI_FUNCTION_ENTRY ();
-
-
-	/* Get the info block for the entire GPE register */
-
-	gpe_register_info = gpe_event_info->register_info;
-	if (!gpe_register_info) {
-		return;
-	}
-
-	/*
-	 * Set the bit so we will not enable this GPE when sleeping (and disable
-	 * it upon wake)
-	 */
-	gpe_register_info->wake_enable |= gpe_event_info->bit_mask;
-	gpe_event_info->flags |= (ACPI_GPE_TYPE_WAKE | ACPI_GPE_ENABLED);
-}
-
-
-/******************************************************************************
- *
- * FUNCTION:    acpi_hw_disable_gpe
- *
- * PARAMETERS:  gpe_event_info      - Info block for the GPE to be disabled
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Disable a single GPE.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_hw_disable_gpe (
-	struct acpi_gpe_event_info      *gpe_event_info)
-{
-	u32                             in_byte;
 	acpi_status                     status;
-	struct acpi_gpe_register_info   *gpe_register_info;
 
 
 	ACPI_FUNCTION_ENTRY ();
@@ -158,67 +78,15 @@ acpi_hw_disable_gpe (
 
 	gpe_register_info = gpe_event_info->register_info;
 	if (!gpe_register_info) {
-		return (AE_BAD_PARAMETER);
-	}
-
-	/*
-	 * Read the current value of the register, clear the appropriate bit,
-	 * and write out the new register value to disable the GPE.
-	 */
-	status = acpi_hw_low_level_read (8, &in_byte,
-			  &gpe_register_info->enable_address);
-	if (ACPI_FAILURE (status)) {
-		return (status);
+		return (AE_NOT_EXIST);
 	}
 
-	/* Write the byte with this GPE bit cleared */
+	/* Write the entire GPE (runtime) enable register */
 
-	status = acpi_hw_low_level_write (8, (in_byte & ~(gpe_event_info->bit_mask)),
+	status = acpi_hw_low_level_write (8, gpe_register_info->enable_for_run,
 			  &gpe_register_info->enable_address);
-	if (ACPI_FAILURE (status)) {
-		return (status);
-	}
-
-	/* Make sure this GPE is disabled for wake, also */
-
-	acpi_hw_disable_gpe_for_wakeup (gpe_event_info);
-	return (AE_OK);
-}
-
-
-/******************************************************************************
- *
- * FUNCTION:    acpi_hw_disable_gpe_for_wakeup
- *
- * PARAMETERS:  gpe_event_info      - Info block for the GPE to be disabled
- *
- * RETURN:      None
- *
- * DESCRIPTION: Keep track of which GPEs the OS has requested not be
- *              disabled when going to sleep.
- *
- ******************************************************************************/
 
-void
-acpi_hw_disable_gpe_for_wakeup (
-	struct acpi_gpe_event_info      *gpe_event_info)
-{
-	struct acpi_gpe_register_info   *gpe_register_info;
-
-
-	ACPI_FUNCTION_ENTRY ();
-
-
-	/* Get the info block for the entire GPE register */
-
-	gpe_register_info = gpe_event_info->register_info;
-	if (!gpe_register_info) {
-		return;
-	}
-
-	/* Clear the bit so we will disable this when sleeping */
-
-	gpe_register_info->wake_enable &= ~(gpe_event_info->bit_mask);
+	return (status);
 }
 
 
@@ -228,7 +96,7 @@ acpi_hw_disable_gpe_for_wakeup (
  *
  * PARAMETERS:  gpe_event_info      - Info block for the GPE to be cleared
  *
- * RETURN:      status_status
+ * RETURN:      Status
  *
  * DESCRIPTION: Clear the status bit for a single GPE.
  *
@@ -248,7 +116,7 @@ acpi_hw_clear_gpe (
 	 * Write a one to the appropriate bit in the status register to
 	 * clear this GPE.
 	 */
-	status = acpi_hw_low_level_write (8, gpe_event_info->bit_mask,
+	status = acpi_hw_low_level_write (8, gpe_event_info->register_bit,
 			  &gpe_event_info->register_info->status_address);
 
 	return (status);
@@ -274,7 +142,7 @@ acpi_hw_get_gpe_status (
 	acpi_event_status               *event_status)
 {
 	u32                             in_byte;
-	u8                              bit_mask;
+	u8                              register_bit;
 	struct acpi_gpe_register_info   *gpe_register_info;
 	acpi_status                     status;
 	acpi_event_status               local_event_status = 0;
@@ -293,33 +161,28 @@ acpi_hw_get_gpe_status (
 
 	/* Get the register bitmask for this GPE */
 
-	bit_mask = gpe_event_info->bit_mask;
-
-	/* GPE Enabled? */
+	register_bit = gpe_event_info->register_bit;
 
-	status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->enable_address);
-	if (ACPI_FAILURE (status)) {
-		goto unlock_and_exit;
-	}
+	/* GPE currently enabled? (enabled for runtime?) */
 
-	if (bit_mask & in_byte) {
+	if (register_bit & gpe_register_info->enable_for_run) {
 		local_event_status |= ACPI_EVENT_FLAG_ENABLED;
 	}
 
-	/* GPE Enabled for wake? */
+	/* GPE enabled for wake? */
 
-	if (bit_mask & gpe_register_info->wake_enable) {
+	if (register_bit & gpe_register_info->enable_for_wake) {
 		local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED;
 	}
 
-	/* GPE active (set)? */
+	/* GPE currently active (status bit == 1)? */
 
 	status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->status_address);
 	if (ACPI_FAILURE (status)) {
 		goto unlock_and_exit;
 	}
 
-	if (bit_mask & in_byte) {
+	if (register_bit & in_byte) {
 		local_event_status |= ACPI_EVENT_FLAG_SET;
 	}
 
@@ -411,64 +274,43 @@ acpi_hw_clear_gpe_block (
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_hw_prepare_gpe_block_for_sleep
+ * FUNCTION:    acpi_hw_enable_runtime_gpe_block
  *
  * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
  *              gpe_block           - Gpe Block info
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Disable all runtime GPEs and enable all wakeup GPEs -- within
- *              a single GPE block
+ * DESCRIPTION: Enable all "runtime" GPEs within a GPE block. (Includes
+ *              combination wake/run GPEs.)
  *
  ******************************************************************************/
 
-static acpi_status
-acpi_hw_prepare_gpe_block_for_sleep (
+acpi_status
+acpi_hw_enable_runtime_gpe_block (
 	struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
 	struct acpi_gpe_block_info      *gpe_block)
 {
 	u32                             i;
-	struct acpi_gpe_register_info   *gpe_register_info;
-	u32                             in_value;
 	acpi_status                     status;
 
 
-	/* Get the register info for the entire GPE block */
-
-	gpe_register_info = gpe_block->register_info;
+	/* NOTE: assumes that all GPEs are currently disabled */
 
 	/* Examine each GPE Register within the block */
 
 	for (i = 0; i < gpe_block->register_count; i++) {
-		/*
-		 * Read the enabled/disabled status of all GPEs. We
-		 * will be using it to restore all the GPEs later.
-		 *
-		 * NOTE:  Wake GPEs are are ALL disabled at this time, so when we wake
-		 * and restore this register, they will be automatically disabled.
-		 */
-		status = acpi_hw_low_level_read (8, &in_value,
-				 &gpe_register_info->enable_address);
-		if (ACPI_FAILURE (status)) {
-			return (status);
+		if (!gpe_block->register_info[i].enable_for_run) {
+			continue;
 		}
 
-		gpe_register_info->enable = (u8) in_value;
+		/* Enable all "runtime" GPEs in this register */
 
-		/*
-		 * 1) Disable all runtime GPEs
-		 * 2) Enable all wakeup GPEs
-		 */
-		status = acpi_hw_low_level_write (8, gpe_register_info->wake_enable,
-				&gpe_register_info->enable_address);
+		status = acpi_hw_low_level_write (8, gpe_block->register_info[i].enable_for_run,
+				 &gpe_block->register_info[i].enable_address);
 		if (ACPI_FAILURE (status)) {
 			return (status);
 		}
-
-		/* Point to next GPE register */
-
-		gpe_register_info++;
 	}
 
 	return (AE_OK);
@@ -477,122 +319,125 @@ acpi_hw_prepare_gpe_block_for_sleep (
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_hw_prepare_gpes_for_sleep
+ * FUNCTION:    acpi_hw_enable_wakeup_gpe_block
  *
- * PARAMETERS:  None
+ * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
+ *              gpe_block           - Gpe Block info
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Disable all runtime GPEs, enable all wake GPEs.
- *              Called with interrupts disabled. The interrupt handler also
- *              modifies gpe_register_info->Enable, so it should not be
- *              given the chance to run until after the runtime GPEs are
- *              re-enabled.
+ * DESCRIPTION: Enable all "wake" GPEs within a GPE block.  (Includes
+ *              combination wake/run GPEs.)
  *
  ******************************************************************************/
 
 acpi_status
-acpi_hw_prepare_gpes_for_sleep (
-	void)
+acpi_hw_enable_wakeup_gpe_block (
+	struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
+	struct acpi_gpe_block_info      *gpe_block)
 {
+	u32                             i;
 	acpi_status                     status;
 
 
-	ACPI_FUNCTION_ENTRY ();
+	/* Examine each GPE Register within the block */
 
+	for (i = 0; i < gpe_block->register_count; i++) {
+		if (!gpe_block->register_info[i].enable_for_wake) {
+			continue;
+		}
 
-	status = acpi_ev_walk_gpe_list (acpi_hw_prepare_gpe_block_for_sleep);
-	return (status);
+		/* Enable all "wake" GPEs in this register */
+
+		status = acpi_hw_low_level_write (8, gpe_block->register_info[i].enable_for_wake,
+				 &gpe_block->register_info[i].enable_address);
+		if (ACPI_FAILURE (status)) {
+			return (status);
+		}
+	}
+
+	return (AE_OK);
 }
 
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_hw_restore_gpe_block_on_wake
+ * FUNCTION:    acpi_hw_disable_all_gpes
  *
- * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
- *              gpe_block           - Gpe Block info
+ * PARAMETERS:  Flags           - ACPI_NOT_ISR or ACPI_ISR
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Enable all runtime GPEs and disable all wake GPEs -- in one
- *              GPE block
+ * DESCRIPTION: Disable and clear all GPEs
  *
  ******************************************************************************/
 
-static acpi_status
-acpi_hw_restore_gpe_block_on_wake (
-	struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
-	struct acpi_gpe_block_info      *gpe_block)
+acpi_status
+acpi_hw_disable_all_gpes (
+	u32                             flags)
 {
-	u32                             i;
-	struct acpi_gpe_register_info   *gpe_register_info;
 	acpi_status                     status;
 
 
-	/* This callback processes one entire GPE block */
+	ACPI_FUNCTION_TRACE ("hw_disable_all_gpes");
 
-	/* Get the register info for the entire GPE block */
 
-	gpe_register_info = gpe_block->register_info;
+	status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block, flags);
+	status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block, flags);
+	return_ACPI_STATUS (status);
+}
 
-	/* Examine each GPE register within the block */
 
-	for (i = 0; i < gpe_block->register_count; i++) {
-		/* Clear the entire status register */
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_hw_enable_all_runtime_gpes
+ *
+ * PARAMETERS:  Flags           - ACPI_NOT_ISR or ACPI_ISR
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Enable all GPEs of the given type
+ *
+ ******************************************************************************/
 
-		status = acpi_hw_low_level_write (8, 0xFF,
-				 &gpe_block->register_info[i].status_address);
-		if (ACPI_FAILURE (status)) {
-			return (status);
-		}
+acpi_status
+acpi_hw_enable_all_runtime_gpes (
+	u32                             flags)
+{
+	acpi_status                     status;
 
-		/*
-		 * Restore the GPE Enable register, which will do the following:
-		 *
-		 * 1) Disable all wakeup GPEs
-		 * 2) Enable all runtime GPEs
-		 *
-		 *  (On sleep, we saved the enabled status of all GPEs)
-		 */
-		status = acpi_hw_low_level_write (8, gpe_register_info->enable,
-				 &gpe_register_info->enable_address);
-		if (ACPI_FAILURE (status)) {
-			return (status);
-		}
 
-		/* Point to next GPE register */
+	ACPI_FUNCTION_TRACE ("hw_enable_all_runtime_gpes");
 
-		gpe_register_info++;
-	}
 
-	return (AE_OK);
+	status = acpi_ev_walk_gpe_list (acpi_hw_enable_runtime_gpe_block, flags);
+	return_ACPI_STATUS (status);
 }
 
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_hw_restore_gpes_on_wake
+ * FUNCTION:    acpi_hw_enable_all_wakeup_gpes
  *
- * PARAMETERS:  None
+ * PARAMETERS:  Flags           - ACPI_NOT_ISR or ACPI_ISR
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Enable all runtime GPEs and disable all wake GPEs -- in all
- *              GPE blocks
+ * DESCRIPTION: Enable all GPEs of the given type
  *
  ******************************************************************************/
 
 acpi_status
-acpi_hw_restore_gpes_on_wake (
-	void)
+acpi_hw_enable_all_wakeup_gpes (
+	u32                             flags)
 {
 	acpi_status                     status;
 
 
-	ACPI_FUNCTION_ENTRY ();
+	ACPI_FUNCTION_TRACE ("hw_enable_all_wakeup_gpes");
 
 
-	status = acpi_ev_walk_gpe_list (acpi_hw_restore_gpe_block_on_wake);
-	return (status);
+	status = acpi_ev_walk_gpe_list (acpi_hw_enable_wakeup_gpe_block, flags);
+	return_ACPI_STATUS (status);
 }
+
diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c
index a7c651316..cb998fe9e 100644
--- a/drivers/acpi/hardware/hwregs.c
+++ b/drivers/acpi/hardware/hwregs.c
@@ -61,6 +61,7 @@
  * RETURN:      none
  *
  * DESCRIPTION: Clears all fixed and general purpose status bits
+ *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
  *
  ******************************************************************************/
 
@@ -103,7 +104,7 @@ acpi_hw_clear_acpi_status (
 
 	/* Clear the GPE Bits in all GPE registers in all GPE blocks */
 
-	status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block);
+	status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block, ACPI_ISR);
 
 unlock_and_exit:
 	if (flags & ACPI_MTX_LOCK) {
@@ -135,7 +136,7 @@ acpi_get_sleep_type_data (
 	u8                              *sleep_type_b)
 {
 	acpi_status                     status = AE_OK;
-	union acpi_operand_object       *obj_desc;
+	struct acpi_parameter_info      info;
 
 
 	ACPI_FUNCTION_TRACE ("acpi_get_sleep_type_data");
@@ -152,8 +153,9 @@ acpi_get_sleep_type_data (
 	/*
 	 * Evaluate the namespace object containing the values for this state
 	 */
+	info.parameters = NULL;
 	status = acpi_ns_evaluate_by_name ((char *) acpi_gbl_sleep_state_names[sleep_state],
-			  NULL, &obj_desc);
+			  &info);
 	if (ACPI_FAILURE (status)) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s while evaluating sleep_state [%s]\n",
 			acpi_format_exception (status), acpi_gbl_sleep_state_names[sleep_state]));
@@ -163,48 +165,50 @@ acpi_get_sleep_type_data (
 
 	/* Must have a return object */
 
-	if (!obj_desc) {
+	if (!info.return_object) {
 		ACPI_REPORT_ERROR (("Missing Sleep State object\n"));
 		status = AE_NOT_EXIST;
 	}
 
 	/* It must be of type Package */
 
-	else if (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_PACKAGE) {
+	else if (ACPI_GET_OBJECT_TYPE (info.return_object) != ACPI_TYPE_PACKAGE) {
 		ACPI_REPORT_ERROR (("Sleep State object not a Package\n"));
 		status = AE_AML_OPERAND_TYPE;
 	}
 
 	/* The package must have at least two elements */
 
-	else if (obj_desc->package.count < 2) {
+	else if (info.return_object->package.count < 2) {
 		ACPI_REPORT_ERROR (("Sleep State package does not have at least two elements\n"));
 		status = AE_AML_NO_OPERAND;
 	}
 
 	/* The first two elements must both be of type Integer */
 
-	else if ((ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[0]) != ACPI_TYPE_INTEGER) ||
-			 (ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[1]) != ACPI_TYPE_INTEGER)) {
+	else if ((ACPI_GET_OBJECT_TYPE (info.return_object->package.elements[0]) != ACPI_TYPE_INTEGER) ||
+			 (ACPI_GET_OBJECT_TYPE (info.return_object->package.elements[1]) != ACPI_TYPE_INTEGER)) {
 		ACPI_REPORT_ERROR (("Sleep State package elements are not both Integers (%s, %s)\n",
-			acpi_ut_get_object_type_name (obj_desc->package.elements[0]),
-			acpi_ut_get_object_type_name (obj_desc->package.elements[1])));
+			acpi_ut_get_object_type_name (info.return_object->package.elements[0]),
+			acpi_ut_get_object_type_name (info.return_object->package.elements[1])));
 		status = AE_AML_OPERAND_TYPE;
 	}
 	else {
 		/*
 		 * Valid _Sx_ package size, type, and value
 		 */
-		*sleep_type_a = (u8) (obj_desc->package.elements[0])->integer.value;
-		*sleep_type_b = (u8) (obj_desc->package.elements[1])->integer.value;
+		*sleep_type_a = (u8) (info.return_object->package.elements[0])->integer.value;
+		*sleep_type_b = (u8) (info.return_object->package.elements[1])->integer.value;
 	}
 
 	if (ACPI_FAILURE (status)) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "While evaluating sleep_state [%s], bad Sleep object %p type %s\n",
-			acpi_gbl_sleep_state_names[sleep_state], obj_desc, acpi_ut_get_object_type_name (obj_desc)));
+		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+			"While evaluating sleep_state [%s], bad Sleep object %p type %s\n",
+			acpi_gbl_sleep_state_names[sleep_state], info.return_object,
+			acpi_ut_get_object_type_name (info.return_object)));
 	}
 
-	acpi_ut_remove_reference (obj_desc);
+	acpi_ut_remove_reference (info.return_object);
 	return_ACPI_STATUS (status);
 }
 
@@ -245,8 +249,8 @@ acpi_hw_get_bit_register_info (
  *              return_value    - Value that was read from the register
  *              Flags           - Lock the hardware or not
  *
- * RETURN:      Value is read from specified Register.  Value returned is
- *              normalized to bit0 (is shifted all the way right)
+ * RETURN:      Status and the value read from specified Register.  Value
+ *              returned is normalized to bit0 (is shifted all the way right)
  *
  * DESCRIPTION: ACPI bit_register read function.
  *
@@ -280,6 +284,8 @@ acpi_get_register (
 		}
 	}
 
+	/* Read from the register */
+
 	status = acpi_hw_register_read (ACPI_MTX_DO_NOT_LOCK,
 			  bit_reg_info->parent_register, &register_value);
 
@@ -309,10 +315,10 @@ acpi_get_register (
  *
  * PARAMETERS:  register_id     - ID of ACPI bit_register to access
  *              Value           - (only used on write) value to write to the
- *                                Register, NOT pre-normalized to the bit pos.
+ *                                Register, NOT pre-normalized to the bit pos
  *              Flags           - Lock the hardware or not
  *
- * RETURN:      None
+ * RETURN:      Status
  *
  * DESCRIPTION: ACPI Bit Register write function.
  *
@@ -457,10 +463,11 @@ unlock_and_exit:
  *
  * FUNCTION:    acpi_hw_register_read
  *
- * PARAMETERS:  use_lock               - Mutex hw access.
- *              register_id            - register_iD + Offset.
+ * PARAMETERS:  use_lock            - Mutex hw access
+ *              register_id         - register_iD + Offset
+ *              return_value        - Value that was read from the register
  *
- * RETURN:      Value read or written.
+ * RETURN:      Status and the value read.
  *
  * DESCRIPTION: Acpi register read function.  Registers are read at the
  *              given offset.
@@ -568,10 +575,11 @@ unlock_and_exit:
  *
  * FUNCTION:    acpi_hw_register_write
  *
- * PARAMETERS:  use_lock               - Mutex hw access.
- *              register_id            - register_iD + Offset.
+ * PARAMETERS:  use_lock            - Mutex hw access
+ *              register_id         - register_iD + Offset
+ *              Value               - The value to write
  *
- * RETURN:      Value read or written.
+ * RETURN:      Status
  *
  * DESCRIPTION: Acpi register Write function.  Registers are written at the
  *              given offset.
@@ -687,11 +695,11 @@ unlock_and_exit:
  *
  * PARAMETERS:  Width               - 8, 16, or 32
  *              Value               - Where the value is returned
- *              Register            - GAS register structure
+ *              Reg                 - GAS register structure
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Read from either memory, IO, or PCI config space.
+ * DESCRIPTION: Read from either memory or IO space.
  *
  ******************************************************************************/
 
@@ -701,8 +709,6 @@ acpi_hw_low_level_read (
 	u32                             *value,
 	struct acpi_generic_address     *reg)
 {
-	struct acpi_pci_id              pci_id;
-	u16                             pci_register;
 	acpi_status                     status;
 
 
@@ -721,8 +727,8 @@ acpi_hw_low_level_read (
 	*value = 0;
 
 	/*
-	 * Three address spaces supported:
-	 * Memory, IO, or PCI_Config.
+	 * Two address spaces supported: Memory or IO.
+	 * PCI_Config is not supported here because the GAS struct is insufficient
 	 */
 	switch (reg->address_space_id) {
 	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
@@ -740,19 +746,6 @@ acpi_hw_low_level_read (
 		break;
 
 
-	case ACPI_ADR_SPACE_PCI_CONFIG:
-
-		pci_id.segment = 0;
-		pci_id.bus     = 0;
-		pci_id.device  = ACPI_PCI_DEVICE (reg->address);
-		pci_id.function = ACPI_PCI_FUNCTION (reg->address);
-		pci_register   = (u16) ACPI_PCI_REGISTER (reg->address);
-
-		status = acpi_os_read_pci_configuration (&pci_id, pci_register,
-				 value, width);
-		break;
-
-
 	default:
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
 			"Unsupported address space: %X\n", reg->address_space_id));
@@ -774,11 +767,11 @@ acpi_hw_low_level_read (
  *
  * PARAMETERS:  Width               - 8, 16, or 32
  *              Value               - To be written
- *              Register            - GAS register structure
+ *              Reg                 - GAS register structure
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Write to either memory, IO, or PCI config space.
+ * DESCRIPTION: Write to either memory or IO space.
  *
  ******************************************************************************/
 
@@ -788,8 +781,6 @@ acpi_hw_low_level_write (
 	u32                             value,
 	struct acpi_generic_address     *reg)
 {
-	struct acpi_pci_id              pci_id;
-	u16                             pci_register;
 	acpi_status                     status;
 
 
@@ -807,8 +798,8 @@ acpi_hw_low_level_write (
 	}
 
 	/*
-	 * Three address spaces supported:
-	 * Memory, IO, or PCI_Config.
+	 * Two address spaces supported: Memory or IO.
+	 * PCI_Config is not supported here because the GAS struct is insufficient
 	 */
 	switch (reg->address_space_id) {
 	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
@@ -826,19 +817,6 @@ acpi_hw_low_level_write (
 		break;
 
 
-	case ACPI_ADR_SPACE_PCI_CONFIG:
-
-		pci_id.segment = 0;
-		pci_id.bus     = 0;
-		pci_id.device  = ACPI_PCI_DEVICE (reg->address);
-		pci_id.function = ACPI_PCI_FUNCTION (reg->address);
-		pci_register   = (u16) ACPI_PCI_REGISTER (reg->address);
-
-		status = acpi_os_write_pci_configuration (&pci_id, pci_register,
-				 (acpi_integer) value, width);
-		break;
-
-
 	default:
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
 			"Unsupported address space: %X\n", reg->address_space_id));
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
index f0c04149f..6ffa80ba2 100644
--- a/drivers/acpi/hardware/hwsleep.c
+++ b/drivers/acpi/hardware/hwsleep.c
@@ -265,19 +265,21 @@ acpi_enter_sleep_state (
 	sleep_type_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_TYPE_A);
 	sleep_enable_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_ENABLE);
 
-	if (sleep_state != ACPI_STATE_S5) {
-		/* Clear wake status */
+	/* Clear wake status */
 
-		status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
-		if (ACPI_FAILURE (status)) {
-			return_ACPI_STATUS (status);
-		}
+	status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
 
-		status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK);
-		if (ACPI_FAILURE (status)) {
-			return_ACPI_STATUS (status);
-		}
+	/* Clear all fixed and general purpose status bits */
 
+	status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+
+	if (sleep_state != ACPI_STATE_S5) {
 		/* Disable BM arbitration */
 
 		status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK);
@@ -287,10 +289,16 @@ acpi_enter_sleep_state (
 	}
 
 	/*
-	 * 1) Disable all runtime GPEs
+	 * 1) Disable/Clear all GPEs
 	 * 2) Enable all wakeup GPEs
 	 */
-	status = acpi_hw_prepare_gpes_for_sleep ();
+	status = acpi_hw_disable_all_gpes (ACPI_ISR);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+	acpi_gbl_system_awake_and_running = FALSE;
+
+	status = acpi_hw_enable_all_wakeup_gpes (ACPI_ISR);
 	if (ACPI_FAILURE (status)) {
 		return_ACPI_STATUS (status);
 	}
@@ -420,10 +428,16 @@ acpi_enter_sleep_state_s4bios (
 	}
 
 	/*
-	 * 1) Disable all runtime GPEs
+	 * 1) Disable/Clear all GPEs
 	 * 2) Enable all wakeup GPEs
 	 */
-	status = acpi_hw_prepare_gpes_for_sleep ();
+	status = acpi_hw_disable_all_gpes (ACPI_ISR);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+	acpi_gbl_system_awake_and_running = FALSE;
+
+	status = acpi_hw_enable_all_wakeup_gpes (ACPI_ISR);
 	if (ACPI_FAILURE (status)) {
 		return_ACPI_STATUS (status);
 	}
@@ -453,6 +467,7 @@ acpi_enter_sleep_state_s4bios (
  * RETURN:      Status
  *
  * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
+ *              Called with interrupts ENABLED.
  *
  ******************************************************************************/
 
@@ -540,19 +555,25 @@ acpi_leave_sleep_state (
 
 	/*
 	 * Restore the GPEs:
-	 * 1) Disable all wakeup GPEs
+	 * 1) Disable/Clear all GPEs
 	 * 2) Enable all runtime GPEs
 	 */
-	status = acpi_hw_restore_gpes_on_wake ();
+	status = acpi_hw_disable_all_gpes (ACPI_NOT_ISR);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
+	acpi_gbl_system_awake_and_running = TRUE;
+
+	status = acpi_hw_enable_all_runtime_gpes (ACPI_NOT_ISR);
 	if (ACPI_FAILURE (status)) {
 		return_ACPI_STATUS (status);
 	}
 
 	/* Enable power button */
 
-	acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].enable_register_id,
+	(void) acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].enable_register_id,
 			1, ACPI_MTX_DO_NOT_LOCK);
-	acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].status_register_id,
+	(void) acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].status_register_id,
 			1, ACPI_MTX_DO_NOT_LOCK);
 
 	/* Enable BM arbitration */
diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c
index 8878aff9d..1f94d6ffa 100644
--- a/drivers/acpi/hardware/hwtimer.c
+++ b/drivers/acpi/hardware/hwtimer.c
@@ -52,11 +52,11 @@
  *
  * FUNCTION:    acpi_get_timer_resolution
  *
- * PARAMETERS:  none
+ * PARAMETERS:  Resolution          - Where the resolution is returned
  *
- * RETURN:      Number of bits of resolution in the PM Timer (24 or 32).
+ * RETURN:      Status and timer resolution
  *
- * DESCRIPTION: Obtains resolution of the ACPI PM Timer.
+ * DESCRIPTION: Obtains resolution of the ACPI PM Timer (24 or 32 bits).
  *
  ******************************************************************************/
 
@@ -86,11 +86,11 @@ acpi_get_timer_resolution (
  *
  * FUNCTION:    acpi_get_timer
  *
- * PARAMETERS:  none
+ * PARAMETERS:  Ticks               - Where the timer value is returned
  *
- * RETURN:      Current value of the ACPI PM Timer (in ticks).
+ * RETURN:      Status and current ticks
  *
- * DESCRIPTION: Obtains current value of ACPI PM Timer.
+ * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks).
  *
  ******************************************************************************/
 
@@ -118,11 +118,11 @@ acpi_get_timer (
  *
  * FUNCTION:    acpi_get_timer_duration
  *
- * PARAMETERS:  start_ticks
- *              end_ticks
- *              time_elapsed
+ * PARAMETERS:  start_ticks         - Starting timestamp
+ *              end_ticks           - End timestamp
+ *              time_elapsed        - Where the elapsed time is returned
  *
- * RETURN:      time_elapsed
+ * RETURN:      Status and time_elapsed
  *
  * DESCRIPTION: Computes the time elapsed (in microseconds) between two
  *              PM Timer time stamps, taking into account the possibility of
@@ -136,7 +136,7 @@ acpi_get_timer (
  *              Note that this function accommodates only a single timer
  *              rollover.  Thus for 24-bit timers, this function should only
  *              be used for calculating durations less than ~4.6 seconds
- *              (~20 minutes for 32-bit timers) -- calculations below
+ *              (~20 minutes for 32-bit timers) -- calculations below:
  *
  *              2**24 Ticks / 3,600,000 Ticks/Sec = 4.66 sec
  *              2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes
@@ -164,7 +164,6 @@ acpi_get_timer_duration (
 
 	/*
 	 * Compute Tick Delta:
-	 * -------------------
 	 * Handle (max one) timer rollovers on 24- versus 32-bit timers.
 	 */
 	if (start_ticks < end_ticks) {
@@ -188,10 +187,7 @@ acpi_get_timer_duration (
 	}
 
 	/*
-	 * Compute Duration:
-	 * -----------------
-	 *
-	 * Requires a 64-bit divide:
+	 * Compute Duration (Requires a 64-bit divide):
 	 *
 	 * time_elapsed = (delta_ticks * 1000000) / PM_TIMER_FREQUENCY;
 	 */
diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c
index 23baf93bf..765217be4 100644
--- a/drivers/acpi/namespace/nsaccess.c
+++ b/drivers/acpi/namespace/nsaccess.c
@@ -193,7 +193,7 @@ acpi_ns_root_initialize (void)
 			case ACPI_TYPE_MUTEX:
 
 				obj_desc->mutex.node = new_node;
-				obj_desc->mutex.sync_level = (u16) ACPI_STRTOUL
+				obj_desc->mutex.sync_level = (u8) ACPI_STRTOUL
 						  (val, NULL, 10);
 
 				if (ACPI_STRCMP (init_val->name, "_GL_") == 0) {
diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c
index c9dd49ff7..89b997717 100644
--- a/drivers/acpi/namespace/nsalloc.c
+++ b/drivers/acpi/namespace/nsalloc.c
@@ -267,7 +267,7 @@ acpi_ns_install_node (
 	else {
 #ifdef ACPI_ALPHABETIC_NAMESPACE
 		/*
-		 * Walk the list whilst searching for the the correct
+		 * Walk the list whilst searching for the correct
 		 * alphabetic placement.
 		 */
 		previous_child_node = NULL;
diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c
index b054b365c..418f03ee2 100644
--- a/drivers/acpi/namespace/nseval.c
+++ b/drivers/acpi/namespace/nseval.c
@@ -77,13 +77,10 @@
 
 acpi_status
 acpi_ns_evaluate_relative (
-	struct acpi_namespace_node      *handle,
 	char                            *pathname,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_object)
+	struct acpi_parameter_info      *info)
 {
 	acpi_status                     status;
-	struct acpi_namespace_node      *prefix_node;
 	struct acpi_namespace_node      *node = NULL;
 	union acpi_generic_state        *scope_info;
 	char                            *internal_path = NULL;
@@ -95,7 +92,7 @@ acpi_ns_evaluate_relative (
 	/*
 	 * Must have a valid object handle
 	 */
-	if (!handle) {
+	if (!info || !info->node) {
 		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
 
@@ -118,8 +115,8 @@ acpi_ns_evaluate_relative (
 		goto cleanup;
 	}
 
-	prefix_node = acpi_ns_map_handle_to_node (handle);
-	if (!prefix_node) {
+	info->node = acpi_ns_map_handle_to_node (info->node);
+	if (!info->node) {
 		(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
 		status = AE_BAD_PARAMETER;
 		goto cleanup;
@@ -127,7 +124,7 @@ acpi_ns_evaluate_relative (
 
 	/* Lookup the name in the namespace */
 
-	scope_info->scope.node = prefix_node;
+	scope_info->scope.node = info->node;
 	status = acpi_ns_lookup (scope_info, internal_path, ACPI_TYPE_ANY,
 			 ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
 			 &node);
@@ -147,7 +144,8 @@ acpi_ns_evaluate_relative (
 	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
 		pathname, node, acpi_ns_get_attached_object (node)));
 
-	status = acpi_ns_evaluate_by_handle (node, params, return_object);
+	info->node = node;
+	status = acpi_ns_evaluate_by_handle (info);
 
 	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
 		pathname));
@@ -166,6 +164,7 @@ cleanup1:
  * FUNCTION:    acpi_ns_evaluate_by_name
  *
  * PARAMETERS:  Pathname            - Fully qualified pathname to the object
+ *              Info                - Contains:
  *              return_object       - Where to put method's return value (if
  *                                    any).  If NULL, no value is returned.
  *              Params              - List of parameters to pass to the method,
@@ -184,11 +183,9 @@ cleanup1:
 acpi_status
 acpi_ns_evaluate_by_name (
 	char                            *pathname,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_object)
+	struct acpi_parameter_info      *info)
 {
 	acpi_status                     status;
-	struct acpi_namespace_node      *node = NULL;
 	char                            *internal_path = NULL;
 
 
@@ -211,7 +208,7 @@ acpi_ns_evaluate_by_name (
 
 	status = acpi_ns_lookup (NULL, internal_path, ACPI_TYPE_ANY,
 			 ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
-			 &node);
+			 &info->node);
 
 	(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
 
@@ -226,9 +223,9 @@ acpi_ns_evaluate_by_name (
 	 * to evaluate it.
 	 */
 	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
-		pathname, node, acpi_ns_get_attached_object (node)));
+		pathname, info->node, acpi_ns_get_attached_object (info->node)));
 
-	status = acpi_ns_evaluate_by_handle (node, params, return_object);
+	status = acpi_ns_evaluate_by_handle (info);
 
 	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
 		pathname));
@@ -254,6 +251,7 @@ cleanup:
  *              Params              - List of parameters to pass to the method,
  *                                    terminated by NULL.  Params itself may be
  *                                    NULL if no parameters are being passed.
+ *              param_type          - Type of Parameter list
  *              return_object       - Where to put method's return value (if
  *                                    any).  If NULL, no value is returned.
  *
@@ -267,13 +265,9 @@ cleanup:
 
 acpi_status
 acpi_ns_evaluate_by_handle (
-	struct acpi_namespace_node      *handle,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_object)
+	struct acpi_parameter_info      *info)
 {
-	struct acpi_namespace_node      *node;
 	acpi_status                     status;
-	union acpi_operand_object       *local_return_object;
 
 
 	ACPI_FUNCTION_TRACE ("ns_evaluate_by_handle");
@@ -287,15 +281,13 @@ acpi_ns_evaluate_by_handle (
 
 	/* Parameter Validation */
 
-	if (!handle) {
+	if (!info) {
 		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
 
-	if (return_object) {
-		/* Initialize the return value to an invalid object */
+	/* Initialize the return value to an invalid object */
 
-		*return_object = NULL;
-	}
+	info->return_object = NULL;
 
 	/* Get the prefix handle and Node */
 
@@ -304,8 +296,8 @@ acpi_ns_evaluate_by_handle (
 		return_ACPI_STATUS (status);
 	}
 
-	node = acpi_ns_map_handle_to_node (handle);
-	if (!node) {
+	info->node = acpi_ns_map_handle_to_node (info->node);
+	if (!info->node) {
 		(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
 		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
@@ -315,8 +307,8 @@ acpi_ns_evaluate_by_handle (
 	 * so that proper scoping context will be established
 	 * before execution.
 	 */
-	if (acpi_ns_get_type (node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
-		node = ACPI_CAST_PTR (struct acpi_namespace_node, node->object);
+	if (acpi_ns_get_type (info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
+		info->node = ACPI_CAST_PTR (struct acpi_namespace_node, info->node->object);
 	}
 
 	/*
@@ -328,19 +320,18 @@ acpi_ns_evaluate_by_handle (
 	 * In both cases, the namespace is unlocked by the
 	 *  acpi_ns* procedure
 	 */
-	if (acpi_ns_get_type (node) == ACPI_TYPE_METHOD) {
+	if (acpi_ns_get_type (info->node) == ACPI_TYPE_METHOD) {
 		/*
 		 * Case 1) We have an actual control method to execute
 		 */
-		status = acpi_ns_execute_control_method (node, params,
-				 &local_return_object);
+		status = acpi_ns_execute_control_method (info);
 	}
 	else {
 		/*
 		 * Case 2) Object is NOT a method, just return its
 		 * current value
 		 */
-		status = acpi_ns_get_object_value (node, &local_return_object);
+		status = acpi_ns_get_object_value (info);
 	}
 
 	/*
@@ -348,20 +339,6 @@ acpi_ns_evaluate_by_handle (
 	 * be dealt with
 	 */
 	if (status == AE_CTRL_RETURN_VALUE) {
-		/*
-		 * If the Method returned a value and the caller
-		 * provided a place to store a returned value, Copy
-		 * the returned value to the object descriptor provided
-		 * by the caller.
-		 */
-		if (return_object) {
-			/*
-			 * Valid return object, copy the pointer to
-			 * the returned object
-			 */
-			*return_object = local_return_object;
-		}
-
 		/* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */
 
 		status = AE_OK;
@@ -396,9 +373,7 @@ acpi_ns_evaluate_by_handle (
 
 acpi_status
 acpi_ns_execute_control_method (
-	struct acpi_namespace_node      *method_node,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_obj_desc)
+	struct acpi_parameter_info      *info)
 {
 	acpi_status                     status;
 	union acpi_operand_object       *obj_desc;
@@ -409,7 +384,7 @@ acpi_ns_execute_control_method (
 
 	/* Verify that there is a method associated with this object */
 
-	obj_desc = acpi_ns_get_attached_object (method_node);
+	obj_desc = acpi_ns_get_attached_object (info->node);
 	if (!obj_desc) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No attached method object\n"));
 
@@ -417,7 +392,7 @@ acpi_ns_execute_control_method (
 		return_ACPI_STATUS (AE_NULL_OBJECT);
 	}
 
-	ACPI_DUMP_PATHNAME (method_node, "Execute Method:",
+	ACPI_DUMP_PATHNAME (info->node, "Execute Method:",
 		ACPI_LV_INFO, _COMPONENT);
 
 	ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Method at AML address %p Length %X\n",
@@ -444,7 +419,7 @@ acpi_ns_execute_control_method (
 		return_ACPI_STATUS (status);
 	}
 
-	status = acpi_psx_execute (method_node, params, return_obj_desc);
+	status = acpi_psx_execute (info);
 	acpi_ex_exit_interpreter ();
 
 	return_ACPI_STATUS (status);
@@ -468,11 +443,10 @@ acpi_ns_execute_control_method (
 
 acpi_status
 acpi_ns_get_object_value (
-	struct acpi_namespace_node      *node,
-	union acpi_operand_object       **return_obj_desc)
+	struct acpi_parameter_info      *info)
 {
 	acpi_status                     status = AE_OK;
-	struct acpi_namespace_node      *resolved_node = node;
+	struct acpi_namespace_node      *resolved_node = info->node;
 
 
 	ACPI_FUNCTION_TRACE ("ns_get_object_value");
@@ -518,9 +492,9 @@ acpi_ns_get_object_value (
 
 		if (ACPI_SUCCESS (status)) {
 			status = AE_CTRL_RETURN_VALUE;
-			*return_obj_desc = ACPI_CAST_PTR (union acpi_operand_object, resolved_node);
+			info->return_object = ACPI_CAST_PTR (union acpi_operand_object, resolved_node);
 			ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returning object %p [%s]\n",
-				*return_obj_desc, acpi_ut_get_object_type_name (*return_obj_desc)));
+				info->return_object, acpi_ut_get_object_type_name (info->return_object)));
 		}
 	}
 
diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c
index c8e9317ab..861787520 100644
--- a/drivers/acpi/namespace/nsinit.c
+++ b/drivers/acpi/namespace/nsinit.c
@@ -149,7 +149,7 @@ acpi_ns_initialize_devices (
 		return_ACPI_STATUS (status);
 	}
 
-	/* Walk namespace for all objects of type Device or Processor */
+	/* Walk namespace for all objects */
 
 	status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
 			  ACPI_UINT32_MAX, TRUE, acpi_ns_init_one_device, &info, NULL);
@@ -337,25 +337,29 @@ acpi_ns_init_one_device (
 	void                            *context,
 	void                            **return_value)
 {
-	acpi_status                     status;
-	struct acpi_namespace_node     *node;
-	u32                             flags;
 	struct acpi_device_walk_info   *info = (struct acpi_device_walk_info *) context;
+	struct acpi_parameter_info      pinfo;
+	u32                             flags;
+	acpi_status                     status;
 
 
 	ACPI_FUNCTION_TRACE ("ns_init_one_device");
 
 
-	node = acpi_ns_map_handle_to_node (obj_handle);
-	if (!node) {
+	pinfo.parameters = NULL;
+	pinfo.parameter_type = ACPI_PARAM_ARGS;
+
+	pinfo.node = acpi_ns_map_handle_to_node (obj_handle);
+	if (!pinfo.node) {
 		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
 
 	/*
-	 * We will run _STA/_INI on Devices and Processors only
+	 * We will run _STA/_INI on Devices, Processors and thermal_zones only
 	 */
-	if ((node->type != ACPI_TYPE_DEVICE) &&
-		(node->type != ACPI_TYPE_PROCESSOR)) {
+	if ((pinfo.node->type != ACPI_TYPE_DEVICE)      &&
+		(pinfo.node->type != ACPI_TYPE_PROCESSOR)   &&
+		(pinfo.node->type != ACPI_TYPE_THERMAL)) {
 		return_ACPI_STATUS (AE_OK);
 	}
 
@@ -368,17 +372,17 @@ acpi_ns_init_one_device (
 	/*
 	 * Run _STA to determine if we can run _INI on the device.
 	 */
-	ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, node, "_STA"));
-	status = acpi_ut_execute_STA (node, &flags);
+	ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, pinfo.node, "_STA"));
+	status = acpi_ut_execute_STA (pinfo.node, &flags);
 
 	if (ACPI_FAILURE (status)) {
-		if (node->type == ACPI_TYPE_DEVICE) {
+		if (pinfo.node->type == ACPI_TYPE_DEVICE) {
 			/* Ignore error and move on to next device */
 
 			return_ACPI_STATUS (AE_OK);
 		}
 
-		/* _STA is not required for Processor objects */
+		/* _STA is not required for Processor or thermal_zone objects */
 	}
 	else {
 		info->num_STA++;
@@ -393,22 +397,22 @@ acpi_ns_init_one_device (
 	/*
 	 * The device is present. Run _INI.
 	 */
-	ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, obj_handle, "_INI"));
-	status = acpi_ns_evaluate_relative (obj_handle, "_INI", NULL, NULL);
+	ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, pinfo.node, "_INI"));
+	status = acpi_ns_evaluate_relative ("_INI", &pinfo);
 	if (ACPI_FAILURE (status)) {
 		/* No _INI (AE_NOT_FOUND) means device requires no initialization */
 
 		if (status != AE_NOT_FOUND) {
 			/* Ignore error and move on to next device */
 
-	#ifdef ACPI_DEBUG_OUTPUT
-			char                *scope_name = acpi_ns_get_external_pathname (obj_handle);
+#ifdef ACPI_DEBUG_OUTPUT
+			char                *scope_name = acpi_ns_get_external_pathname (pinfo.node);
 
 			ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%s._INI failed: %s\n",
 					scope_name, acpi_format_exception (status)));
 
 			ACPI_MEM_FREE (scope_name);
-	#endif
+#endif
 		}
 
 		status = AE_OK;
@@ -422,7 +426,7 @@ acpi_ns_init_one_device (
 	if (acpi_gbl_init_handler) {
 		/* External initialization handler is present, call it */
 
-		status = acpi_gbl_init_handler (obj_handle, ACPI_INIT_DEVICE_INI);
+		status = acpi_gbl_init_handler (pinfo.node, ACPI_INIT_DEVICE_INI);
 	}
 
 
diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c
index f550ce5c1..530982a38 100644
--- a/drivers/acpi/namespace/nsparse.c
+++ b/drivers/acpi/namespace/nsparse.c
@@ -94,8 +94,9 @@ acpi_ns_one_complete_parse (
 		return_ACPI_STATUS (AE_NO_MEMORY);
 	}
 
-	status = acpi_ds_init_aml_walk (walk_state, parse_root, NULL, table_desc->aml_start,
-			  table_desc->aml_length, NULL, NULL, pass_number);
+	status = acpi_ds_init_aml_walk (walk_state, parse_root, NULL,
+			  table_desc->aml_start, table_desc->aml_length,
+			  NULL, pass_number);
 	if (ACPI_FAILURE (status)) {
 		acpi_ds_delete_walk_state (walk_state);
 		return_ACPI_STATUS (status);
diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c
index 312835443..8e916b5e2 100644
--- a/drivers/acpi/namespace/nsxfeval.c
+++ b/drivers/acpi/namespace/nsxfeval.c
@@ -174,8 +174,7 @@ acpi_evaluate_object (
 {
 	acpi_status                     status;
 	acpi_status                     status2;
-	union acpi_operand_object       **internal_params = NULL;
-	union acpi_operand_object       *internal_return_obj = NULL;
+	struct acpi_parameter_info      info;
 	acpi_size                       buffer_space_needed;
 	u32                             i;
 
@@ -183,6 +182,11 @@ acpi_evaluate_object (
 	ACPI_FUNCTION_TRACE ("acpi_evaluate_object");
 
 
+	info.node = handle;
+	info.parameters = NULL;
+	info.return_object = NULL;
+	info.parameter_type = ACPI_PARAM_ARGS;
+
 	/*
 	 * If there are parameters to be passed to the object
 	 * (which must be a control method), the external objects
@@ -193,9 +197,10 @@ acpi_evaluate_object (
 		 * Allocate a new parameter block for the internal objects
 		 * Add 1 to count to allow for null terminated internal list
 		 */
-		internal_params = ACPI_MEM_CALLOCATE (((acpi_size) external_params->count + 1) *
-				  sizeof (void *));
-		if (!internal_params) {
+		info.parameters = ACPI_MEM_CALLOCATE (
+				 ((acpi_size) external_params->count + 1) *
+				 sizeof (void *));
+		if (!info.parameters) {
 			return_ACPI_STATUS (AE_NO_MEMORY);
 		}
 
@@ -205,15 +210,16 @@ acpi_evaluate_object (
 		 */
 		for (i = 0; i < external_params->count; i++) {
 			status = acpi_ut_copy_eobject_to_iobject (&external_params->pointer[i],
-					  &internal_params[i]);
+					  &info.parameters[i]);
 			if (ACPI_FAILURE (status)) {
-				acpi_ut_delete_internal_object_list (internal_params);
+				acpi_ut_delete_internal_object_list (info.parameters);
 				return_ACPI_STATUS (status);
 			}
 		}
-		internal_params[external_params->count] = NULL;
+		info.parameters[external_params->count] = NULL;
 	}
 
+
 	/*
 	 * Three major cases:
 	 * 1) Fully qualified pathname
@@ -225,8 +231,7 @@ acpi_evaluate_object (
 		/*
 		 *  The path is fully qualified, just evaluate by name
 		 */
-		status = acpi_ns_evaluate_by_name (pathname, internal_params,
-				 &internal_return_obj);
+		status = acpi_ns_evaluate_by_name (pathname, &info);
 	}
 	else if (!handle) {
 		/*
@@ -256,15 +261,13 @@ acpi_evaluate_object (
 			 * The null pathname case means the handle is for
 			 * the actual object to be evaluated
 			 */
-			status = acpi_ns_evaluate_by_handle (handle, internal_params,
-					  &internal_return_obj);
+			status = acpi_ns_evaluate_by_handle (&info);
 		}
 		else {
 		   /*
 			* Both a Handle and a relative Pathname
 			*/
-			status = acpi_ns_evaluate_relative (handle, pathname, internal_params,
-					  &internal_return_obj);
+			status = acpi_ns_evaluate_relative (pathname, &info);
 		}
 	}
 
@@ -274,11 +277,11 @@ acpi_evaluate_object (
 	 * copy the return value to an external object.
 	 */
 	if (return_buffer) {
-		if (!internal_return_obj) {
+		if (!info.return_object) {
 			return_buffer->length = 0;
 		}
 		else {
-			if (ACPI_GET_DESCRIPTOR_TYPE (internal_return_obj) == ACPI_DESC_TYPE_NAMED) {
+			if (ACPI_GET_DESCRIPTOR_TYPE (info.return_object) == ACPI_DESC_TYPE_NAMED) {
 				/*
 				 * If we received a NS Node as a return object, this means that
 				 * the object we are evaluating has nothing interesting to
@@ -288,7 +291,7 @@ acpi_evaluate_object (
 				 * support for various types at a later date if necessary.
 				 */
 				status = AE_TYPE;
-				internal_return_obj = NULL; /* No need to delete a NS Node */
+				info.return_object = NULL;  /* No need to delete a NS Node */
 				return_buffer->length = 0;
 			}
 
@@ -297,7 +300,7 @@ acpi_evaluate_object (
 				 * Find out how large a buffer is needed
 				 * to contain the returned object
 				 */
-				status = acpi_ut_get_object_size (internal_return_obj,
+				status = acpi_ut_get_object_size (info.return_object,
 						   &buffer_space_needed);
 				if (ACPI_SUCCESS (status)) {
 					/* Validate/Allocate/Clear caller buffer */
@@ -309,13 +312,14 @@ acpi_evaluate_object (
 						 */
 						ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
 							"Needed buffer size %X, %s\n",
-							(u32) buffer_space_needed, acpi_format_exception (status)));
+							(u32) buffer_space_needed,
+							acpi_format_exception (status)));
 					}
 					else {
 						/*
 						 *  We have enough space for the object, build it
 						 */
-						status = acpi_ut_copy_iobject_to_eobject (internal_return_obj,
+						status = acpi_ut_copy_iobject_to_eobject (info.return_object,
 								  return_buffer);
 					}
 				}
@@ -323,7 +327,7 @@ acpi_evaluate_object (
 		}
 	}
 
-	if (internal_return_obj) {
+	if (info.return_object) {
 		/*
 		 * Delete the internal return object.  NOTE: Interpreter
 		 * must be locked to avoid race condition.
@@ -334,7 +338,7 @@ acpi_evaluate_object (
 			 * Delete the internal return object. (Or at least
 			 * decrement the reference count by one)
 			 */
-			acpi_ut_remove_reference (internal_return_obj);
+			acpi_ut_remove_reference (info.return_object);
 			acpi_ex_exit_interpreter ();
 		}
 	}
@@ -342,10 +346,10 @@ acpi_evaluate_object (
 	/*
 	 * Free the input parameter list (if we created one),
 	 */
-	if (internal_params) {
+	if (info.parameters) {
 		/* Free the allocated parameter block */
 
-		acpi_ut_delete_internal_object_list (internal_params);
+		acpi_ut_delete_internal_object_list (info.parameters);
 	}
 
 	return_ACPI_STATUS (status);
diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c
index a1acb9f12..0508b4d79 100644
--- a/drivers/acpi/namespace/nsxfname.c
+++ b/drivers/acpi/namespace/nsxfname.c
@@ -281,7 +281,7 @@ acpi_get_object_info (
 	if (info.type == ACPI_TYPE_DEVICE) {
 		/*
 		 * Get extra info for ACPI Devices objects only:
-		 * Run the Device _HID, _UID, _CID, _STA, and _ADR methods.
+		 * Run the Device _HID, _UID, _CID, _STA, _ADR and _sx_d methods.
 		 *
 		 * Note: none of these methods are required, so they may or may
 		 * not be present for this device.  The Info.Valid bitfield is used
@@ -330,7 +330,7 @@ acpi_get_object_info (
 
 		status = acpi_ut_execute_sxds (node, info.highest_dstates);
 		if (ACPI_SUCCESS (status)) {
-			info.valid |= ACPI_VALID_STA;
+			info.valid |= ACPI_VALID_SXDS;
 		}
 
 		status = AE_OK;
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 0646b2955..1f63b4d71 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -51,6 +51,7 @@ acpi_table_print_srat_entry (
 	switch (header->type) {
 
 	case ACPI_SRAT_PROCESSOR_AFFINITY:
+#ifdef ACPI_DEBUG_OUTPUT
 	{
 		struct acpi_table_processor_affinity *p =
 			(struct acpi_table_processor_affinity*) header;
@@ -58,9 +59,11 @@ acpi_table_print_srat_entry (
 		       p->apic_id, p->lsapic_eid, p->proximity_domain,
 		       p->flags.enabled?"enabled":"disabled"));
 	}
+#endif /* ACPI_DEBUG_OUTPUT */
 		break;
 
 	case ACPI_SRAT_MEMORY_AFFINITY:
+#ifdef ACPI_DEBUG_OUTPUT
 	{
 		struct acpi_table_memory_affinity *p =
 			(struct acpi_table_memory_affinity*) header;
@@ -70,6 +73,7 @@ acpi_table_print_srat_entry (
 		       p->flags.enabled ? "enabled" : "disabled",
 		       p->flags.hot_pluggable ? " hot-pluggable" : ""));
 	}
+#endif /* ACPI_DEBUG_OUTPUT */
 		break;
 
 	default:
@@ -94,8 +98,6 @@ acpi_parse_slit (unsigned long phys_addr, unsigned long size)
 	/* downcast just for %llu vs %lu for i386/ia64  */
 	localities = (u32) slit->localities;
 
-	printk(KERN_INFO PREFIX "SLIT localities %ux%u\n", localities, localities);
-
 	acpi_numa_slit_init(slit);
 
 	return 0;
@@ -103,7 +105,9 @@ acpi_parse_slit (unsigned long phys_addr, unsigned long size)
 
 
 static int __init
-acpi_parse_processor_affinity (acpi_table_entry_header *header)
+acpi_parse_processor_affinity (
+	acpi_table_entry_header *header,
+	const unsigned long end)
 {
 	struct acpi_table_processor_affinity *processor_affinity;
 
@@ -121,7 +125,9 @@ acpi_parse_processor_affinity (acpi_table_entry_header *header)
 
 
 static int __init
-acpi_parse_memory_affinity (acpi_table_entry_header *header)
+acpi_parse_memory_affinity (
+	acpi_table_entry_header *header,
+	const unsigned long end)
 {
 	struct acpi_table_memory_affinity *memory_affinity;
 
@@ -148,8 +154,6 @@ acpi_parse_srat (unsigned long phys_addr, unsigned long size)
 
 	srat = (struct acpi_table_srat *) __va(phys_addr);
 
-	printk(KERN_INFO PREFIX "SRAT revision %d\n", srat->table_revision);
-
 	return 0;
 }
 
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 433fdd701..a7c4fdfcb 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -51,10 +51,13 @@ ACPI_MODULE_NAME	("osl")
 
 struct acpi_os_dpc
 {
-    OSD_EXECUTION_CALLBACK  function;
+    acpi_osd_exec_callback  function;
     void		    *context;
 };
 
+#ifdef CONFIG_ACPI_CUSTOM_DSDT
+#include CONFIG_ACPI_CUSTOM_DSDT_FILE
+#endif
 
 #ifdef ENABLE_DEBUGGER
 #include <linux/kdb.h>
@@ -64,12 +67,18 @@ extern char line_buf[80];
 #endif /*ENABLE_DEBUGGER*/
 
 static unsigned int acpi_irq_irq;
-static OSD_HANDLER acpi_irq_handler;
+static acpi_osd_handler acpi_irq_handler;
 static void *acpi_irq_context;
 static struct workqueue_struct *kacpid_wq;
 
 acpi_status
 acpi_os_initialize(void)
+{
+	return AE_OK;
+}
+
+acpi_status
+acpi_os_initialize1(void)
 {
 	/*
 	 * Initialize PCI configuration space access, as we'll need to access
@@ -165,11 +174,11 @@ acpi_os_get_root_pointer(u32 flags, struct acpi_pointer *addr)
 }
 
 acpi_status
-acpi_os_map_memory(acpi_physical_address phys, acpi_size size, void **virt)
+acpi_os_map_memory(acpi_physical_address phys, acpi_size size, void __iomem **virt)
 {
 	if (efi_enabled) {
 		if (EFI_MEMORY_WB & efi_mem_attributes(phys)) {
-			*virt = phys_to_virt(phys);
+			*virt = (void __iomem *) phys_to_virt(phys);
 		} else {
 			*virt = ioremap(phys, size);
 		}
@@ -191,7 +200,7 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size, void **virt)
 }
 
 void
-acpi_os_unmap_memory(void *virt, acpi_size size)
+acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
 {
 	iounmap(virt);
 }
@@ -235,7 +244,14 @@ acpi_os_table_override (struct acpi_table_header *existing_table,
 	if (!existing_table || !new_table)
 		return AE_BAD_PARAMETER;
 
+#ifdef CONFIG_ACPI_CUSTOM_DSDT
+	if (strncmp(existing_table->signature, "DSDT", 4) == 0)
+		*new_table = (struct acpi_table_header*)AmlCode;
+	else
+		*new_table = NULL;
+#else
 	*new_table = NULL;
+#endif
 	return AE_OK;
 }
 
@@ -246,7 +262,7 @@ acpi_irq(int irq, void *dev_id, struct pt_regs *regs)
 }
 
 acpi_status
-acpi_os_install_interrupt_handler(u32 gsi, OSD_HANDLER handler, void *context)
+acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, void *context)
 {
 	unsigned int irq;
 
@@ -274,7 +290,7 @@ acpi_os_install_interrupt_handler(u32 gsi, OSD_HANDLER handler, void *context)
 }
 
 acpi_status
-acpi_os_remove_interrupt_handler(u32 irq, OSD_HANDLER handler)
+acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
 {
 	if (irq) {
 		free_irq(irq, acpi_irq);
@@ -370,30 +386,31 @@ acpi_os_read_memory(
 	u32			width)
 {
 	u32			dummy;
-	void			*virt_addr;
+	void __iomem		*virt_addr;
 	int			iomem = 0;
 
 	if (efi_enabled) {
 		if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
-			virt_addr = phys_to_virt(phys_addr);
+			/* HACK ALERT! We can use readb/w/l on real memory too.. */
+			virt_addr = (void __iomem *) phys_to_virt(phys_addr);
 		} else {
 			iomem = 1;
 			virt_addr = ioremap(phys_addr, width);
 		}
 	} else
-		virt_addr = phys_to_virt(phys_addr);
+		virt_addr = (void __iomem *) phys_to_virt(phys_addr);
 	if (!value)
 		value = &dummy;
 
 	switch (width) {
 	case 8:
-		*(u8*) value = *(u8*) virt_addr;
+		*(u8*) value = readb(virt_addr);
 		break;
 	case 16:
-		*(u16*) value = *(u16*) virt_addr;
+		*(u16*) value = readw(virt_addr);
 		break;
 	case 32:
-		*(u32*) value = *(u32*) virt_addr;
+		*(u32*) value = readl(virt_addr);
 		break;
 	default:
 		BUG();
@@ -413,28 +430,29 @@ acpi_os_write_memory(
 	u32			value,
 	u32			width)
 {
-	void			*virt_addr;
+	void __iomem		*virt_addr;
 	int			iomem = 0;
 
 	if (efi_enabled) {
 		if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
-			virt_addr = phys_to_virt(phys_addr);
+			/* HACK ALERT! We can use writeb/w/l on real memory too */
+			virt_addr = (void __iomem *) phys_to_virt(phys_addr);
 		} else {
 			iomem = 1;
 			virt_addr = ioremap(phys_addr, width);
 		}
 	} else
-		virt_addr = phys_to_virt(phys_addr);
+		virt_addr = (void __iomem *) phys_to_virt(phys_addr);
 
 	switch (width) {
 	case 8:
-		*(u8*) virt_addr = value;
+		writeb(value, virt_addr);
 		break;
 	case 16:
-		*(u16*) virt_addr = value;
+		writew(value, virt_addr);
 		break;
 	case 32:
-		*(u32*) virt_addr = value;
+		writel(value, virt_addr);
 		break;
 	default:
 		BUG();
@@ -470,6 +488,8 @@ acpi_os_read_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, void *value
 		return AE_ERROR;
 	}
 
+	BUG_ON(!raw_pci_ops);
+
 	result = raw_pci_ops->read(pci_id->segment, pci_id->bus,
 				PCI_DEVFN(pci_id->device, pci_id->function),
 				reg, size, value);
@@ -496,6 +516,8 @@ acpi_os_write_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, acpi_integ
 		return AE_ERROR;
 	}
 
+	BUG_ON(!raw_pci_ops);
+
 	result = raw_pci_ops->write(pci_id->segment, pci_id->bus,
 				PCI_DEVFN(pci_id->device, pci_id->function),
 				reg, size, value);
@@ -624,7 +646,7 @@ acpi_os_execute_deferred (
 acpi_status
 acpi_os_queue_for_execution(
 	u32			priority,
-	OSD_EXECUTION_CALLBACK	function,
+	acpi_osd_exec_callback	function,
 	void			*context)
 {
 	acpi_status 		status = AE_OK;
@@ -952,7 +974,7 @@ acpi_os_readable(void *ptr, acpi_size len)
 {
 #if defined(__i386__) || defined(__x86_64__) 
 	char tmp;
-	return !__get_user(tmp, (char *)ptr) && !__get_user(tmp, (char *)ptr + len - 1);
+	return !__get_user(tmp, (char __user *)ptr) && !__get_user(tmp, (char __user *)ptr + len - 1);
 #endif
 	return 1;
 }
@@ -1066,15 +1088,15 @@ __setup("acpi_serialize", acpi_serialize_setup);
  * Run-time events on the same GPE this flag is available
  * to tell Linux to keep the wake-time GPEs enabled at run-time.
  */
-static int __init
-acpi_leave_gpes_disabled_setup(char *str)
+int __init
+acpi_wake_gpes_always_on_setup(char *str)
 {
-	printk(KERN_INFO PREFIX "leave wake GPEs disabled\n");
+	printk(KERN_INFO PREFIX "wake GPEs not disabled\n");
 
-	acpi_gbl_leave_wake_gpes_disabled = TRUE;
+	acpi_gbl_leave_wake_gpes_disabled = FALSE;
 
 	return 1;
 }
 
-__setup("acpi_leave_gpes_disabled", acpi_leave_gpes_disabled_setup);
+__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);
 
diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c
index 198e2206b..30620375b 100644
--- a/drivers/acpi/parser/psopcode.c
+++ b/drivers/acpi/parser/psopcode.c
@@ -251,7 +251,7 @@
 #define ARGI_CREATE_FIELD_OP            ARGI_LIST4 (ARGI_BUFFER,     ARGI_INTEGER,       ARGI_INTEGER,      ARGI_REFERENCE)
 #define ARGI_CREATE_QWORD_FIELD_OP      ARGI_LIST3 (ARGI_BUFFER,     ARGI_INTEGER,       ARGI_REFERENCE)
 #define ARGI_CREATE_WORD_FIELD_OP       ARGI_LIST3 (ARGI_BUFFER,     ARGI_INTEGER,       ARGI_REFERENCE)
-#define ARGI_DATA_REGION_OP             ARGI_LIST3 (ARGI_STRING,     ARGI_STRING,       ARGI_STRING)
+#define ARGI_DATA_REGION_OP             ARGI_LIST3 (ARGI_STRING,     ARGI_STRING,        ARGI_STRING)
 #define ARGI_DEBUG_OP                   ARG_NONE
 #define ARGI_DECREMENT_OP               ARGI_LIST1 (ARGI_INTEGER_REF)
 #define ARGI_DEREF_OF_OP                ARGI_LIST1 (ARGI_REF_OR_STRING)
@@ -270,10 +270,10 @@
 #define ARGI_INDEX_FIELD_OP             ARGI_INVALID_OPCODE
 #define ARGI_INDEX_OP                   ARGI_LIST3 (ARGI_COMPLEXOBJ, ARGI_INTEGER,       ARGI_TARGETREF)
 #define ARGI_LAND_OP                    ARGI_LIST2 (ARGI_INTEGER,    ARGI_INTEGER)
-#define ARGI_LEQUAL_OP                  ARGI_LIST2 (ARGI_INTEGER,    ARGI_INTEGER)
-#define ARGI_LGREATER_OP                ARGI_LIST2 (ARGI_INTEGER,    ARGI_INTEGER)
+#define ARGI_LEQUAL_OP                  ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA)
+#define ARGI_LGREATER_OP                ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA)
 #define ARGI_LGREATEREQUAL_OP           ARGI_INVALID_OPCODE
-#define ARGI_LLESS_OP                   ARGI_LIST2 (ARGI_INTEGER,    ARGI_INTEGER)
+#define ARGI_LLESS_OP                   ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA)
 #define ARGI_LLESSEQUAL_OP              ARGI_INVALID_OPCODE
 #define ARGI_LNOT_OP                    ARGI_LIST1 (ARGI_INTEGER)
 #define ARGI_LNOTEQUAL_OP               ARGI_INVALID_OPCODE
diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c
index b7917cfdc..9281f6aec 100644
--- a/drivers/acpi/parser/psxface.c
+++ b/drivers/acpi/parser/psxface.c
@@ -57,7 +57,7 @@
  *
  * FUNCTION:    acpi_psx_execute
  *
- * PARAMETERS:  method_node         - A method object containing both the AML
+ * PARAMETERS:  Info->Node          - A method object containing both the AML
  *                                    address and length.
  *              **Params            - List of parameters to pass to method,
  *                                    terminated by NULL. Params itself may be
@@ -73,9 +73,7 @@
 
 acpi_status
 acpi_psx_execute (
-	struct acpi_namespace_node      *method_node,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_obj_desc)
+	struct acpi_parameter_info      *info)
 {
 	acpi_status                     status;
 	union acpi_operand_object       *obj_desc;
@@ -89,29 +87,30 @@ acpi_psx_execute (
 
 	/* Validate the Node and get the attached object */
 
-	if (!method_node) {
+	if (!info || !info->node) {
 		return_ACPI_STATUS (AE_NULL_ENTRY);
 	}
 
-	obj_desc = acpi_ns_get_attached_object (method_node);
+	obj_desc = acpi_ns_get_attached_object (info->node);
 	if (!obj_desc) {
 		return_ACPI_STATUS (AE_NULL_OBJECT);
 	}
 
 	/* Init for new method, wait on concurrency semaphore */
 
-	status = acpi_ds_begin_method_execution (method_node, obj_desc, NULL);
+	status = acpi_ds_begin_method_execution (info->node, obj_desc, NULL);
 	if (ACPI_FAILURE (status)) {
 		return_ACPI_STATUS (status);
 	}
 
-	if (params) {
+	if ((info->parameter_type == ACPI_PARAM_ARGS) &&
+		(info->parameters)) {
 		/*
 		 * The caller "owns" the parameters, so give each one an extra
 		 * reference
 		 */
-		for (i = 0; params[i]; i++) {
-			acpi_ut_add_reference (params[i]);
+		for (i = 0; info->parameters[i]; i++) {
+			acpi_ut_add_reference (info->parameters[i]);
 		}
 	}
 
@@ -121,7 +120,7 @@ acpi_psx_execute (
 	 */
 	ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
 		"**** Begin Method Parse **** Entry=%p obj=%p\n",
-		method_node, obj_desc));
+		info->node, obj_desc));
 
 	/* Create and init a Root Node */
 
@@ -147,8 +146,9 @@ acpi_psx_execute (
 		goto cleanup2;
 	}
 
-	status = acpi_ds_init_aml_walk (walk_state, op, method_node, obj_desc->method.aml_start,
-			  obj_desc->method.aml_length, NULL, NULL, 1);
+	status = acpi_ds_init_aml_walk (walk_state, op, info->node,
+			  obj_desc->method.aml_start,
+			  obj_desc->method.aml_length, NULL, 1);
 	if (ACPI_FAILURE (status)) {
 		goto cleanup3;
 	}
@@ -159,7 +159,6 @@ acpi_psx_execute (
 	acpi_ps_delete_parse_tree (op);
 	if (ACPI_FAILURE (status)) {
 		goto cleanup1; /* Walk state is already deleted */
-
 	}
 
 	/*
@@ -167,7 +166,7 @@ acpi_psx_execute (
 	 */
 	ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
 		"**** Begin Method Execution **** Entry=%p obj=%p\n",
-		method_node, obj_desc));
+		info->node, obj_desc));
 
 	/* Create and init a Root Node */
 
@@ -179,8 +178,8 @@ acpi_psx_execute (
 
 	/* Init new op with the method name and pointer back to the NS node */
 
-	acpi_ps_set_name (op, method_node->name.integer);
-	op->common.node = method_node;
+	acpi_ps_set_name (op, info->node->name.integer);
+	op->common.node = info->node;
 
 	/* Create and initialize a new walk state */
 
@@ -190,8 +189,9 @@ acpi_psx_execute (
 		goto cleanup2;
 	}
 
-	status = acpi_ds_init_aml_walk (walk_state, op, method_node, obj_desc->method.aml_start,
-			  obj_desc->method.aml_length, params, return_obj_desc, 3);
+	status = acpi_ds_init_aml_walk (walk_state, op, info->node,
+			  obj_desc->method.aml_start,
+			  obj_desc->method.aml_length, info, 3);
 	if (ACPI_FAILURE (status)) {
 		goto cleanup3;
 	}
@@ -210,13 +210,14 @@ cleanup2:
 	acpi_ps_delete_parse_tree (op);
 
 cleanup1:
-	if (params) {
+	if ((info->parameter_type == ACPI_PARAM_ARGS) &&
+		(info->parameters)) {
 		/* Take away the extra reference that we gave the parameters above */
 
-		for (i = 0; params[i]; i++) {
+		for (i = 0; info->parameters[i]; i++) {
 			/* Ignore errors, just do them all */
 
-			(void) acpi_ut_update_object_reference (params[i], REF_DECREMENT);
+			(void) acpi_ut_update_object_reference (info->parameters[i], REF_DECREMENT);
 		}
 	}
 
@@ -228,10 +229,10 @@ cleanup1:
 	 * If the method has returned an object, signal this to the caller with
 	 * a control exception code
 	 */
-	if (*return_obj_desc) {
+	if (info->return_object) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned obj_desc=%p\n",
-			*return_obj_desc));
-		ACPI_DUMP_STACK_ENTRY (*return_obj_desc);
+			info->return_object));
+		ACPI_DUMP_STACK_ENTRY (info->return_object);
 
 		status = AE_CTRL_RETURN_VALUE;
 	}
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 13e922551..86e8a0ca0 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -29,6 +29,7 @@
  *	   for IRQ management (e.g. start()->_SRS).
  */
 
+#include <linux/sysdev.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -71,7 +72,7 @@ struct acpi_pci_link_irq {
 	u8			active;			/* Current IRQ */
 	u8			edge_level;		/* All IRQs */
 	u8			active_high_low;	/* All IRQs */
-	u8			setonboot;
+	u8			initialized;
 	u8			resource_type;
 	u8			possible_count;
 	u8			possible[ACPI_PCI_LINK_MAX_POSSIBLE];
@@ -447,7 +448,7 @@ acpi_pci_link_set (
 #define PIRQ_PENALTY_ISA_USED		(16*16*16*16*16)
 #define PIRQ_PENALTY_ISA_ALWAYS		(16*16*16*16*16*16)
 
-static int __initdata acpi_irq_penalty[ACPI_MAX_IRQS] = {
+static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
 	PIRQ_PENALTY_ISA_ALWAYS,	/* IRQ0 timer */
 	PIRQ_PENALTY_ISA_ALWAYS,	/* IRQ1 keyboard */
 	PIRQ_PENALTY_ISA_ALWAYS,	/* IRQ2 cascade */
@@ -467,7 +468,7 @@ static int __initdata acpi_irq_penalty[ACPI_MAX_IRQS] = {
 			/* >IRQ15 */
 };
 
-int
+int __init
 acpi_irq_penalty_init(void)
 {
 	struct list_head	*node = NULL;
@@ -517,7 +518,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link* link) {
 
 	ACPI_FUNCTION_TRACE("acpi_pci_link_allocate");
 
-	if (link->irq.setonboot)
+	if (link->irq.initialized)
 		return_VALUE(0);
 
 	/*
@@ -571,7 +572,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link* link) {
 			acpi_device_bid(link->device), link->irq.active);
 	}
 
-	link->irq.setonboot = 1;
+	link->irq.initialized = 1;
 
 	return_VALUE(0);
 }
@@ -694,6 +695,42 @@ end:
 }
 
 
+static int
+acpi_pci_link_resume (
+	struct acpi_pci_link	*link)
+{
+	ACPI_FUNCTION_TRACE("acpi_pci_link_resume");
+	
+	if (link->irq.active && link->irq.initialized)
+		return_VALUE(acpi_pci_link_set(link, link->irq.active));
+	else
+		return_VALUE(0);
+}
+
+
+static int
+irqrouter_resume(
+	struct sys_device *dev)
+{
+	struct list_head        *node = NULL;
+	struct acpi_pci_link    *link = NULL;
+
+	ACPI_FUNCTION_TRACE("irqrouter_resume");
+
+	list_for_each(node, &acpi_link.entries) {
+
+		link = list_entry(node, struct acpi_pci_link, node);
+		if (!link) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n"));
+			continue;
+		}
+
+		acpi_pci_link_resume(link);
+	}
+	return_VALUE(0);
+}
+
+
 static int
 acpi_pci_link_remove (
 	struct acpi_device	*device,
@@ -786,11 +823,42 @@ int __init acpi_irq_balance_set(char *str)
 __setup("acpi_irq_balance", acpi_irq_balance_set);
 
 
+static struct sysdev_class irqrouter_sysdev_class = {
+        set_kset_name("irqrouter"),
+        .resume = irqrouter_resume,
+};
+
+
+static struct sys_device device_irqrouter = {
+	.id     = 0,
+	.cls    = &irqrouter_sysdev_class,
+};
+
+
+static int __init irqrouter_init_sysfs(void)
+{
+	int error;
+
+	ACPI_FUNCTION_TRACE("irqrouter_init_sysfs");
+
+	if (acpi_disabled || acpi_noirq)
+		return_VALUE(0);
+
+	error = sysdev_class_register(&irqrouter_sysdev_class);
+	if (!error)
+		error = sysdev_register(&device_irqrouter);
+
+	return_VALUE(error);
+}                                        
+
+device_initcall(irqrouter_init_sysfs);
+
+
 static int __init acpi_pci_link_init (void)
 {
 	ACPI_FUNCTION_TRACE("acpi_pci_link_init");
 
-	if (acpi_pci_disabled)
+	if (acpi_noirq)
 		return_VALUE(0);
 
 	acpi_link.count = 0;
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 657ddef48..4c3d2a7d2 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -288,6 +288,86 @@ acpi_power_off_device (
 	return_VALUE(0);
 }
 
+/*
+ * Prepare a wakeup device, two steps (Ref ACPI 2.0:P229):
+ * 1. Power on the power resources required for the wakeup device 
+ * 2. Enable _PSW (power state wake) for the device if present
+ */
+int acpi_enable_wakeup_device_power (struct acpi_device *dev)
+{
+	union acpi_object 		arg = {ACPI_TYPE_INTEGER};
+	struct acpi_object_list	arg_list = {1, &arg};
+	acpi_status			status = AE_OK;
+	int					i;
+	int 					ret = 0;
+
+	ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device_power");
+	if (!dev || !dev->wakeup.flags.valid)
+		return -1;
+
+	arg.integer.value = 1;
+	/* Open power resource */
+	for (i = 0; i < dev->wakeup.resources.count; i++) {
+		ret = acpi_power_on(dev->wakeup.resources.handles[i]);
+		if (ret) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+				"Error transition power state\n"));
+			dev->wakeup.flags.valid = 0;
+			return -1;
+		}
+	}
+
+	/* Execute PSW */
+	status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL);
+	if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluate _PSW\n"));
+		dev->wakeup.flags.valid = 0;
+		ret = -1;
+	}
+
+	return ret;
+}
+
+/*
+ * Shutdown a wakeup device, counterpart of above method
+ * 1. Disable _PSW (power state wake)
+ * 2. Shutdown down the power resources
+ */
+int acpi_disable_wakeup_device_power (struct acpi_device *dev)
+{
+	union acpi_object 		arg = {ACPI_TYPE_INTEGER};
+	struct acpi_object_list	arg_list = {1, &arg};
+	acpi_status			status = AE_OK;
+	int					i;
+	int 					ret = 0;
+
+	ACPI_FUNCTION_TRACE("acpi_disable_wakeup_device_power");
+
+	if (!dev || !dev->wakeup.flags.valid)
+		return -1;
+
+	arg.integer.value = 0;	
+	/* Execute PSW */
+	status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL);
+	if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluate _PSW\n"));
+		dev->wakeup.flags.valid = 0;
+		return -1;
+	}
+
+	/* Close power resource */
+	for (i = 0; i < dev->wakeup.resources.count; i++) {
+		ret = acpi_power_off_device(dev->wakeup.resources.handles[i]);
+		if (ret) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+				"Error transition power state\n"));
+			dev->wakeup.flags.valid = 0;
+			return -1;
+		}
+	}
+
+	return ret;
+}
 
 /* --------------------------------------------------------------------------
                              Device Power Management
diff --git a/drivers/acpi/processor.c b/drivers/acpi/processor.c
index 8d7b78df6..83fb743aa 100644
--- a/drivers/acpi/processor.c
+++ b/drivers/acpi/processor.c
@@ -44,6 +44,9 @@
 #include <asm/system.h>
 #include <asm/delay.h>
 #include <asm/uaccess.h>
+#include <asm/processor.h>
+#include <asm/smp.h>
+#include <asm/acpi.h>
 
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
@@ -859,7 +862,6 @@ static void acpi_processor_ppc_exit(void) {
  * _PCT and _PSS structures are read out and written into struct
  * acpi_processor_performance.
  */
-
 static int acpi_processor_set_pdc (struct acpi_processor *pr)
 {
 	acpi_status             status = AE_OK;
@@ -1047,6 +1049,8 @@ acpi_processor_get_performance_info (
 	if (!pr || !pr->performance || !pr->handle)
 		return_VALUE(-EINVAL);
 
+	acpi_processor_set_pdc(pr);
+
 	status = acpi_get_handle(pr->handle, "_PCT", &handle);
 	if (ACPI_FAILURE(status)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
@@ -1054,8 +1058,6 @@ acpi_processor_get_performance_info (
 		return_VALUE(-ENODEV);
 	}
 
-	acpi_processor_set_pdc(pr);
-
 	result = acpi_processor_get_performance_control(pr);
 	if (result)
 		return_VALUE(result);
@@ -1121,7 +1123,7 @@ static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file)
 						PDE(inode)->data);
 }
 
-static int
+static ssize_t
 acpi_processor_write_performance (
         struct file		*file,
         const char		__user *buffer,
@@ -2146,6 +2148,37 @@ acpi_processor_remove_fs (
 	return_VALUE(0);
 }
 
+/* Use the acpiid in MADT to map cpus in case of SMP */
+#ifndef CONFIG_SMP
+#define convert_acpiid_to_cpu(acpi_id) (0xff)
+#else
+
+#ifdef CONFIG_IA64
+#define arch_acpiid_to_apicid 	ia64_acpiid_to_sapicid
+#define arch_cpu_to_apicid 	ia64_cpu_to_sapicid
+#define ARCH_BAD_APICID		(0xffff)
+#else
+#define arch_acpiid_to_apicid 	x86_acpiid_to_apicid
+#define arch_cpu_to_apicid 	x86_cpu_to_apicid
+#define ARCH_BAD_APICID		(0xff)
+#endif
+
+static u8 convert_acpiid_to_cpu(u8 acpi_id)
+{
+	u16 apic_id;
+	int i;
+	
+	apic_id = arch_acpiid_to_apicid[acpi_id];
+	if (apic_id == ARCH_BAD_APICID)
+		return -1;
+
+	for (i = 0; i < NR_CPUS; i++) {
+		if (arch_cpu_to_apicid[i] == apic_id)
+			return i;
+	}
+	return -1;
+}
+#endif
 
 /* --------------------------------------------------------------------------
                                  Driver Interface
@@ -2158,7 +2191,8 @@ acpi_processor_get_info (
 	acpi_status		status = 0;
 	union acpi_object	object = {0};
 	struct acpi_buffer	buffer = {sizeof(union acpi_object), &object};
-	static int		cpu_index = 0;
+	u8			cpu_index;
+	static int		cpu0_initialized;
 
 	ACPI_FUNCTION_TRACE("acpi_processor_get_info");
 
@@ -2168,13 +2202,6 @@ acpi_processor_get_info (
 	if (num_online_cpus() > 1)
 		errata.smp = TRUE;
 
-	/*
-	 *  Extra Processor objects may be enumerated on MP systems with
-	 *  less than the max # of CPUs. They should be ignored.
-	 */
-	if ((cpu_index + 1) > num_online_cpus())
-		return_VALUE(-ENODEV);
-
 	acpi_processor_errata(pr);
 
 	/*
@@ -2206,9 +2233,27 @@ acpi_processor_get_info (
 	 * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
 	 *	>>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c
 	 */
-	pr->id = cpu_index++;
 	pr->acpi_id = object.processor.proc_id;
 
+	cpu_index = convert_acpiid_to_cpu(pr->acpi_id);
+
+	if ( !cpu0_initialized && (cpu_index == 0xff)) {
+		/* Handle UP system running SMP kernel, with no LAPIC in MADT */
+		cpu_index = 0;
+	} else if (cpu_index > num_online_cpus()) {
+		/*
+		 *  Extra Processor objects may be enumerated on MP systems with
+		 *  less than the max # of CPUs. They should be ignored.
+		 */
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+			"Error getting cpuindex for acpiid 0x%x\n",
+			pr->acpi_id));
+		return_VALUE(-ENODEV);
+	}
+	cpu0_initialized = 1;
+
+	pr->id = cpu_index;
+
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id, 
 		pr->acpi_id));
 
@@ -2234,7 +2279,6 @@ acpi_processor_get_info (
 		 * (In particular, allocating the IO range for Cardbus)
 		 */
 		request_region(pr->throttling.address, 6, "ACPI CPU throttle");
-		request_region(acpi_fadt.xpm_tmr_blk.address, 4, "ACPI timer");
 	}
 
 	acpi_processor_get_power_info(pr);
@@ -2373,8 +2417,15 @@ acpi_processor_remove (
 	pr = (struct acpi_processor *) acpi_driver_data(device);
 
 	/* Unregister the idle handler when processor #0 is removed. */
-	if (pr->id == 0)
+	if (pr->id == 0) {
 		pm_idle = pm_idle_save;
+		/*
+		 * 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.
+		 */
+		synchronize_kernel();
+	}
 
 	status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, 
 		acpi_processor_notify);
diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c
index eaf77c635..01dea9b94 100644
--- a/drivers/acpi/resources/rsutils.c
+++ b/drivers/acpi/resources/rsutils.c
@@ -289,6 +289,7 @@ acpi_rs_set_srs_method_data (
 	acpi_handle                     handle,
 	struct acpi_buffer              *in_buffer)
 {
+	struct acpi_parameter_info      info;
 	union acpi_operand_object       *params[2];
 	acpi_status                     status;
 	struct acpi_buffer              buffer;
@@ -329,10 +330,14 @@ acpi_rs_set_srs_method_data (
 	params[0]->common.flags   = AOPOBJ_DATA_VALID;
 	params[1] = NULL;
 
+	info.node = handle;
+	info.parameters = params;
+	info.parameter_type = ACPI_PARAM_ARGS;
+
 	/*
 	 * Execute the method, no return value
 	 */
-	status = acpi_ns_evaluate_relative (handle, "_SRS", params, NULL);
+	status = acpi_ns_evaluate_relative ("_SRS", &info);
 
 	/*
 	 * Clean up and return the status from acpi_ns_evaluate_relative
diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c
index 362f6252b..d02aa1df3 100644
--- a/drivers/acpi/resources/rsxface.c
+++ b/drivers/acpi/resources/rsxface.c
@@ -259,7 +259,8 @@ acpi_walk_resources (
 	/* Setup pointers */
 
 	resource  = (struct acpi_resource *) buffer.pointer;
-	buffer_end = (struct acpi_resource *) ((u8 *) buffer.pointer + buffer.length);
+	buffer_end = ACPI_CAST_PTR (struct acpi_resource,
+			  ((u8 *) buffer.pointer + buffer.length));
 
 	/* Walk the resource list */
 
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index be148f489..4e46eeddf 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -23,7 +23,8 @@ extern struct acpi_device		*acpi_root;
 #define ACPI_BUS_DEVICE_NAME		"System Bus"
 
 static LIST_HEAD(acpi_device_list);
-static spinlock_t acpi_device_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t acpi_device_lock = SPIN_LOCK_UNLOCKED;
+LIST_HEAD(acpi_wakeup_device_list);
 
 static void acpi_device_release(struct kobject * kobj)
 {
@@ -115,9 +116,6 @@ acpi_bus_get_power_flags (
 	status = acpi_get_handle(device->handle, "_IRC", &handle);
 	if (ACPI_SUCCESS(status))
 		device->power.flags.inrush_current = 1;
-	status = acpi_get_handle(device->handle, "_PRW", &handle);
-	if (ACPI_SUCCESS(status))
-		device->power.flags.wake_capable = 1;
 
 	/*
 	 * Enumerate supported power management states
@@ -163,6 +161,127 @@ acpi_bus_get_power_flags (
 	return 0;
 }
 
+static int
+acpi_match_ids (
+	struct acpi_device	*device,
+	char			*ids)
+{
+	int error = 0;
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+
+	if (device->flags.hardware_id)
+		if (strstr(ids, device->pnp.hardware_id))
+			goto Done;
+
+	if (device->flags.compatible_ids) {
+		struct acpi_compatible_id_list *cid_list = device->pnp.cid_list;
+		int i;
+
+		/* compare multiple _CID entries against driver ids */
+		for (i = 0; i < cid_list->count; i++)
+		{
+			if (strstr(ids, cid_list->id[i].value))
+				goto Done;
+		}
+	}
+	error = -ENOENT;
+
+ Done:
+	if (buffer.pointer)
+		acpi_os_free(buffer.pointer);
+	return error;
+}
+
+static acpi_status
+acpi_bus_extract_wakeup_device_power_package (
+	struct acpi_device	*device,
+	union acpi_object	*package)
+{
+	int 	 i = 0;
+	union acpi_object	*element = NULL;
+
+	if (!device || !package || (package->package.count < 2))
+		return AE_BAD_PARAMETER;
+
+	element = &(package->package.elements[0]);
+	if (!element)
+		return AE_BAD_PARAMETER;
+	if (element->type == ACPI_TYPE_PACKAGE) {
+		if ((element->package.count < 2) ||
+			(element->package.elements[0].type != ACPI_TYPE_LOCAL_REFERENCE) ||
+			(element->package.elements[1].type != ACPI_TYPE_INTEGER))
+			return AE_BAD_DATA;
+		device->wakeup.gpe_device = element->package.elements[0].reference.handle;
+		device->wakeup.gpe_number = (u32)element->package.elements[1].integer.value;
+	}else if (element->type == ACPI_TYPE_INTEGER) {
+		device->wakeup.gpe_number = element->integer.value;
+	}else
+		return AE_BAD_DATA;
+
+	element = &(package->package.elements[1]);
+	if (element->type != ACPI_TYPE_INTEGER) {
+		return AE_BAD_DATA;
+	}
+	device->wakeup.sleep_state = element->integer.value;
+
+	if ((package->package.count - 2) > ACPI_MAX_HANDLES) {
+		return AE_NO_MEMORY;
+	}
+	device->wakeup.resources.count = package->package.count - 2;
+	for (i=0; i < device->wakeup.resources.count; i++) {
+		element = &(package->package.elements[i + 2]);
+		if (element->type != ACPI_TYPE_ANY ) {
+			return AE_BAD_DATA;
+		}
+
+		device->wakeup.resources.handles[i] = element->reference.handle;
+	}
+
+	return AE_OK;
+}
+
+static int
+acpi_bus_get_wakeup_device_flags (
+	struct acpi_device	*device)
+{
+	acpi_status	status = 0;
+	struct acpi_buffer	buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	union acpi_object	*package = NULL;
+
+	ACPI_FUNCTION_TRACE("acpi_bus_get_wakeup_flags");
+
+	/* _PRW */
+	status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer);
+	if (ACPI_FAILURE(status)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _PRW\n"));
+		goto end;
+	}
+
+	package = (union acpi_object *) buffer.pointer;
+	status = acpi_bus_extract_wakeup_device_power_package(device, package);
+	if (ACPI_FAILURE(status)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _PRW package\n"));
+		goto end;
+	}
+
+	acpi_os_free(buffer.pointer);
+
+	device->wakeup.flags.valid = 1;
+	/* Power button, Lid switch always enable wakeup*/
+	if (!acpi_match_ids(device, "PNP0C0D,PNP0C0C,PNP0C0E"))
+		device->wakeup.flags.run_wake = 1;
+
+	/* TBD: lock */
+	INIT_LIST_HEAD(&device->wakeup_list);
+	spin_lock(&acpi_device_lock);
+	list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list);
+	spin_unlock(&acpi_device_lock);
+
+end:
+	if (ACPI_FAILURE(status))
+		device->flags.wake_capable = 0;
+	return 0;
+}
 
 /* --------------------------------------------------------------------------
                               Performance Management
@@ -195,30 +314,7 @@ acpi_bus_match (
 	struct acpi_device	*device,
 	struct acpi_driver	*driver)
 {
-	int error = 0;
-	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
-
-	if (device->flags.hardware_id)
-		if (strstr(driver->ids, device->pnp.hardware_id))
-			goto Done;
-
-	if (device->flags.compatible_ids) {
-		struct acpi_compatible_id_list *cid_list = device->pnp.cid_list;
-		int i;
-
-		/* compare multiple _CID entries against driver ids */
-		for (i = 0; i < cid_list->count; i++)
-		{
-			if (strstr(driver->ids, cid_list->id[i].value))
-				goto Done;
-		}
-	}
-	error = -ENOENT;
-
- Done:
-	if (buffer.pointer)
-		acpi_os_free(buffer.pointer);
-	return error;
+	return acpi_match_ids(device, driver->ids);
 }
 
 
@@ -276,6 +372,7 @@ acpi_bus_driver_init (
 static int acpi_driver_attach(struct acpi_driver * drv)
 {
 	struct list_head * node, * next;
+	int count = 0;
 
 	ACPI_FUNCTION_TRACE("acpi_driver_attach");
 
@@ -290,6 +387,7 @@ static int acpi_driver_attach(struct acpi_driver * drv)
 		if (!acpi_bus_match(dev, drv)) {
 			if (!acpi_bus_driver_init(dev, drv)) {
 				atomic_inc(&drv->references);
+				count++;
 				ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n",
 						  drv->name, dev->pnp.bus_id));
 			}
@@ -297,7 +395,7 @@ static int acpi_driver_attach(struct acpi_driver * drv)
 		spin_lock(&acpi_device_lock);
 	}
 	spin_unlock(&acpi_device_lock);
-	return_VALUE(0);
+	return_VALUE(count);
 }
 
 static int acpi_driver_detach(struct acpi_driver * drv)
@@ -328,28 +426,30 @@ static int acpi_driver_detach(struct acpi_driver * drv)
  * acpi_bus_register_driver 
  * ------------------------ 
  * Registers a driver with the ACPI bus.  Searches the namespace for all
- * devices that match the driver's criteria and binds.
+ * devices that match the driver's criteria and binds.  Returns the
+ * number of devices that were claimed by the driver, or a negative
+ * error status for failure.
  */
 int
 acpi_bus_register_driver (
 	struct acpi_driver	*driver)
 {
-	int error = 0;
+	int count;
 
 	ACPI_FUNCTION_TRACE("acpi_bus_register_driver");
 
 	if (acpi_disabled)
 		return_VALUE(-ENODEV);
 
-	if (driver) {
-		spin_lock(&acpi_device_lock);
-		list_add_tail(&driver->node, &acpi_bus_drivers);
-		spin_unlock(&acpi_device_lock);
-		acpi_driver_attach(driver);
-	} else
-		error = -EINVAL;
+	if (!driver)
+		return_VALUE(-EINVAL);
 
-	return_VALUE(error);
+	spin_lock(&acpi_device_lock);
+	list_add_tail(&driver->node, &acpi_bus_drivers);
+	spin_unlock(&acpi_device_lock);
+	count = acpi_driver_attach(driver);
+
+	return_VALUE(count);
 }
 
 
@@ -469,6 +569,11 @@ acpi_bus_get_flags (
 	if (ACPI_SUCCESS(status))
 		device->flags.power_manageable = 1;
 
+	/* Presence of _PRW indicates wake capable */
+	status = acpi_get_handle(device->handle, "_PRW", &temp);
+	if (ACPI_SUCCESS(status))
+		device->flags.wake_capable = 1;
+
 	/* TBD: Peformance management */
 
 	return_VALUE(0);
@@ -740,6 +845,16 @@ acpi_bus_add (
 			goto end;
 	}
 
+ 	/*
+	 * Wakeup device management
+	 *-----------------------
+	 */
+	if (device->flags.wake_capable) {
+		result = acpi_bus_get_wakeup_device_flags(device);
+		if (result)
+			goto end;
+	}
+
 	/*
 	 * Performance Management
 	 * ----------------------
diff --git a/drivers/acpi/sleep/Makefile b/drivers/acpi/sleep/Makefile
index 975d03d59..bb52f85d0 100644
--- a/drivers/acpi/sleep/Makefile
+++ b/drivers/acpi/sleep/Makefile
@@ -1,5 +1,5 @@
 obj-y					:= poweroff.o
-obj-$(CONFIG_ACPI_SLEEP)		+= main.o
+obj-$(CONFIG_ACPI_SLEEP)		+= main.o wakeup.o
 obj-$(CONFIG_ACPI_SLEEP_PROC_FS)	+= proc.o
 
 EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index c7b17e7fa..847a90ed5 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -35,16 +35,16 @@ static int init_8259A_after_S1;
 
 /**
  *	acpi_pm_prepare - Do preliminary suspend work.
- *	@state:		suspend state we're entering.
+ *	@pm_state:		suspend state we're entering.
  *
  *	Make sure we support the state. If we do, and we need it, set the
  *	firmware waking vector and do arch-specific nastiness to get the 
  *	wakeup code to the waking vector. 
  */
 
-static int acpi_pm_prepare(u32 state)
+static int acpi_pm_prepare(u32 pm_state)
 {
-	u32 acpi_state = acpi_suspend_states[state];
+	u32 acpi_state = acpi_suspend_states[pm_state];
 
 	if (!sleep_states[acpi_state])
 		return -EPERM;
@@ -52,13 +52,14 @@ static int acpi_pm_prepare(u32 state)
 	/* do we have a wakeup address for S2 and S3? */
 	/* Here, we support only S4BIOS, those we set the wakeup address */
 	/* S4OS is only supported for now via swsusp.. */
-	if (state == PM_SUSPEND_MEM || state == PM_SUSPEND_DISK) {
+	if (pm_state == PM_SUSPEND_MEM || pm_state == PM_SUSPEND_DISK) {
 		if (!acpi_wakeup_address)
 			return -EFAULT;
 		acpi_set_firmware_waking_vector(
 			(acpi_physical_address) acpi_wakeup_address);
 	}
 	ACPI_FLUSH_CPU_CACHE();
+	acpi_enable_wakeup_device_prep(acpi_state);
 	acpi_enter_sleep_state_prep(acpi_state);
 	return 0;
 }
@@ -66,23 +67,23 @@ static int acpi_pm_prepare(u32 state)
 
 /**
  *	acpi_pm_enter - Actually enter a sleep state.
- *	@state:		State we're entering.
+ *	@pm_state:		State we're entering.
  *
  *	Flush caches and go to sleep. For STR or STD, we have to call 
  *	arch-specific assembly, which in turn call acpi_enter_sleep_state().
  *	It's unfortunate, but it works. Please fix if you're feeling frisky.
  */
 
-static int acpi_pm_enter(u32 state)
+static int acpi_pm_enter(u32 pm_state)
 {
 	acpi_status status = AE_OK;
 	unsigned long flags = 0;
-	u32 acpi_state = acpi_suspend_states[state];
+	u32 acpi_state = acpi_suspend_states[pm_state];
 
 	ACPI_FLUSH_CPU_CACHE();
 
 	/* Do arch specific saving of state. */
-	if (state > PM_SUSPEND_STANDBY) {
+	if (pm_state > PM_SUSPEND_STANDBY) {
 		int error = acpi_save_state_mem();
 		if (error)
 			return error;
@@ -90,7 +91,8 @@ static int acpi_pm_enter(u32 state)
 
 
 	local_irq_save(flags);
-	switch (state)
+	acpi_enable_wakeup_device(acpi_state);
+	switch (pm_state)
 	{
 	case PM_SUSPEND_STANDBY:
 		barrier();
@@ -118,7 +120,7 @@ static int acpi_pm_enter(u32 state)
 	 * And, in the case of the latter, the memory image should have already
 	 * been loaded from disk.
 	 */
-	if (state > PM_SUSPEND_STANDBY)
+	if (pm_state > PM_SUSPEND_STANDBY)
 		acpi_restore_state_mem();
 
 
@@ -128,15 +130,18 @@ static int acpi_pm_enter(u32 state)
 
 /**
  *	acpi_pm_finish - Finish up suspend sequence.
- *	@state:		State we're coming out of.
+ *	@pm_state:		State we're coming out of.
  *
  *	This is called after we wake back up (or if entering the sleep state
  *	failed). 
  */
 
-static int acpi_pm_finish(u32 state)
+static int acpi_pm_finish(u32 pm_state)
 {
-	acpi_leave_sleep_state(state);
+	u32 acpi_state = acpi_suspend_states[pm_state];
+
+	acpi_leave_sleep_state(acpi_state);
+	acpi_disable_wakeup_device(acpi_state);
 
 	/* reset firmware waking vector */
 	acpi_set_firmware_waking_vector((acpi_physical_address) 0);
@@ -199,7 +204,7 @@ static int __init acpi_sleep_init(void)
 		return 0;
 
 	printk(KERN_INFO PREFIX "(supports");
-	for (i=0; i<ACPI_S_STATE_COUNT; i++) {
+	for (i=0; i < ACPI_S_STATE_COUNT; i++) {
 		acpi_status status;
 		u8 type_a, type_b;
 		status = acpi_get_sleep_type_data(i, &type_a, &type_b);
@@ -212,7 +217,8 @@ static int __init acpi_sleep_init(void)
 				sleep_states[i] = 1;
 				printk(" S4bios");
 				acpi_pm_ops.pm_disk_mode = PM_DISK_FIRMWARE;
-			} else if (sleep_states[i])
+			}
+			if (sleep_states[i])
 				acpi_pm_ops.pm_disk_mode = PM_DISK_PLATFORM;
 		}
 	}
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c
index 7eb206096..666498e38 100644
--- a/drivers/acpi/sleep/proc.c
+++ b/drivers/acpi/sleep/proc.c
@@ -15,6 +15,7 @@
 
 #define ACPI_SYSTEM_FILE_SLEEP		"sleep"
 #define ACPI_SYSTEM_FILE_ALARM		"alarm"
+#define ACPI_SYSTEM_FILE_WAKEUP_DEVICE   "wakeup"
 
 #define _COMPONENT		ACPI_SYSTEM_COMPONENT
 ACPI_MODULE_NAME		("sleep")
@@ -352,6 +353,84 @@ end:
 	return_VALUE(result ? result : count);
 }
 
+extern struct list_head	acpi_wakeup_device_list;
+extern spinlock_t acpi_device_lock;
+
+static int
+acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
+{
+	struct list_head * node, * next;
+
+	seq_printf(seq, "Device	Sleep state	Status\n");
+
+	spin_lock(&acpi_device_lock);
+	list_for_each_safe(node, next, &acpi_wakeup_device_list) {
+		struct acpi_device * dev = container_of(node, struct acpi_device, wakeup_list);
+
+		if (!dev->wakeup.flags.valid)
+			continue;
+		spin_unlock(&acpi_device_lock);
+		if (dev->wakeup.flags.run_wake)
+			seq_printf(seq, "%4s	%4d		%8s\n",
+				dev->pnp.bus_id, (u32) dev->wakeup.sleep_state,
+				dev->wakeup.state.enabled ? "*enabled" : "*disabled");
+		else
+			seq_printf(seq, "%4s	%4d		%8s\n",
+				dev->pnp.bus_id, (u32) dev->wakeup.sleep_state,
+				dev->wakeup.state.enabled ? "enabled" : "disabled");
+		spin_lock(&acpi_device_lock);
+	}
+	spin_unlock(&acpi_device_lock);
+	return 0;
+}
+
+static ssize_t
+acpi_system_write_wakeup_device (
+	struct file		*file,
+	const char __user	*buffer,
+	size_t			count,
+	loff_t			*ppos)
+{
+	struct list_head * node, * next;
+	char		strbuf[5];
+	char		str[5] = "";
+	int 		len = count;
+
+	if (len > 4) len = 4;
+
+	if (copy_from_user(strbuf, buffer, len))
+		return -EFAULT;
+	strbuf[len] = '\0';
+	sscanf(strbuf, "%s", str);
+
+	spin_lock(&acpi_device_lock);
+	list_for_each_safe(node, next, &acpi_wakeup_device_list) {
+		struct acpi_device * dev = container_of(node, struct acpi_device, wakeup_list);
+		if (!dev->wakeup.flags.valid)
+			continue;
+
+		if (!strncmp(dev->pnp.bus_id, str, 4)) {
+			dev->wakeup.state.enabled = dev->wakeup.state.enabled ? 0:1;
+			break;
+		}
+	}
+	spin_unlock(&acpi_device_lock);
+	return count;
+}
+
+static int
+acpi_system_wakeup_device_open_fs(struct inode *inode, struct file *file)
+{
+	return single_open(file, acpi_system_wakeup_device_seq_show, PDE(inode)->data);
+}
+
+static struct file_operations acpi_system_wakeup_device_fops = {
+	.open		= acpi_system_wakeup_device_open_fs,
+	.read		= seq_read,
+	.write		= acpi_system_write_wakeup_device,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
 
 static struct file_operations acpi_system_sleep_fops = {
 	.open		= acpi_system_sleep_open_fs,
@@ -388,6 +467,13 @@ static int acpi_sleep_proc_init(void)
 		S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir);
 	if (entry)
 		entry->proc_fops = &acpi_system_alarm_fops;
+
+	/* 'wakeup device' [R/W]*/
+	entry = create_proc_entry(ACPI_SYSTEM_FILE_WAKEUP_DEVICE,
+				  S_IFREG|S_IRUGO|S_IWUSR, acpi_root_dir);
+	if (entry)
+		entry->proc_fops = &acpi_system_wakeup_device_fops;
+
 	return 0;
 }
 
diff --git a/drivers/acpi/sleep/sleep.h b/drivers/acpi/sleep/sleep.h
index ad38f4153..cfaf8f5b0 100644
--- a/drivers/acpi/sleep/sleep.h
+++ b/drivers/acpi/sleep/sleep.h
@@ -2,3 +2,6 @@
 extern u8 sleep_states[];
 extern int acpi_suspend (u32 state);
 
+extern void acpi_enable_wakeup_device_prep(u8 sleep_state);
+extern void acpi_enable_wakeup_device(u8 sleep_state);
+extern void acpi_disable_wakeup_device(u8 sleep_state);
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index e7480822b..fb64bd5d2 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -101,7 +101,7 @@ acpi_table_print (
 	else
 		name = header->signature;
 
-	printk(KERN_INFO PREFIX "%.4s (v%3.3d %6.6s %8.8s 0x%08x %.4s 0x%08x) @ 0x%p\n",
+	printk(KERN_DEBUG PREFIX "%.4s (v%3.3d %6.6s %8.8s 0x%08x %.4s 0x%08x) @ 0x%p\n",
 		name, header->revision, header->oem_id,
 		header->oem_table_id, header->oem_revision,
 		header->asl_compiler_id, header->asl_compiler_revision,
@@ -587,7 +587,7 @@ acpi_table_init (void)
 		return -ENODEV;
 	}
 
-	printk(KERN_INFO PREFIX "RSDP (v%3.3d %6.6s                                    ) @ 0x%p\n",
+	printk(KERN_DEBUG PREFIX "RSDP (v%3.3d %6.6s                                ) @ 0x%p\n",
 		rsdp->revision, rsdp->oem_id, (void *) rsdp_phys);
 
 	if (rsdp->revision < 2)
diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c
index b7328345d..4a9669590 100644
--- a/drivers/acpi/tables/tbxfroot.c
+++ b/drivers/acpi/tables/tbxfroot.c
@@ -115,17 +115,14 @@ acpi_tb_find_table (
  *              Instance        - the non zero instance of the table, allows
  *                                support for multiple tables of the same type
  *              Flags           - Physical/Virtual support
- *              ret_buffer      - pointer to a structure containing a buffer to
- *                                receive the table
+ *              table_pointer   - Where a buffer containing the table is
+ *                                returned
  *
  * RETURN:      Status
  *
- * DESCRIPTION: This function is called to get an ACPI table.  The caller
- *              supplies an out_buffer large enough to contain the entire ACPI
- *              table.  Upon completion
- *              the out_buffer->Length field will indicate the number of bytes
- *              copied into the out_buffer->buf_ptr buffer. This table will be
- *              a complete table including the header.
+ * DESCRIPTION: This function is called to get an ACPI table. A buffer is
+ *              allocated for the table and returned in table_pointer.
+ *              This table will be a complete table including the header.
  *
  ******************************************************************************/
 
@@ -136,12 +133,11 @@ acpi_get_firmware_table (
 	u32                             flags,
 	struct acpi_table_header        **table_pointer)
 {
-	struct acpi_pointer             rsdp_address;
-	struct acpi_pointer             address;
 	acpi_status                     status;
-	struct acpi_table_header        header;
-	struct acpi_table_desc          table_info;
-	struct acpi_table_desc          rsdt_info;
+	struct acpi_pointer             address;
+	struct acpi_table_header        *header = NULL;
+	struct acpi_table_desc          *table_info = NULL;
+	struct acpi_table_desc          *rsdt_info;
 	u32                             table_count;
 	u32                             i;
 	u32                             j;
@@ -152,45 +148,41 @@ acpi_get_firmware_table (
 
 	/*
 	 * Ensure that at least the table manager is initialized.  We don't
-	 * require that the entire ACPI subsystem is up for this interface
-	 */
-
-	/*
-	 *  If we have a buffer, we must have a length too
+	 * require that the entire ACPI subsystem is up for this interface.
+	 * If we have a buffer, we must have a length too
 	 */
-	if ((instance == 0)                 ||
-		(!signature)                    ||
+	if ((instance == 0)     ||
+		(!signature)        ||
 		(!table_pointer)) {
 		return_ACPI_STATUS (AE_BAD_PARAMETER);
 	}
 
-	rsdt_info.pointer = NULL;
+	/* Ensure that we have a RSDP */
 
 	if (!acpi_gbl_RSDP) {
 		/* Get the RSDP */
 
-		status = acpi_os_get_root_pointer (flags, &rsdp_address);
+		status = acpi_os_get_root_pointer (flags, &address);
 		if (ACPI_FAILURE (status)) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP  not found\n"));
+			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP not found\n"));
 			return_ACPI_STATUS (AE_NO_ACPI_TABLES);
 		}
 
 		/* Map and validate the RSDP */
 
 		if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
-			status = acpi_os_map_memory (rsdp_address.pointer.physical, sizeof (struct rsdp_descriptor),
+			status = acpi_os_map_memory (address.pointer.physical, sizeof (struct rsdp_descriptor),
 					  (void *) &acpi_gbl_RSDP);
 			if (ACPI_FAILURE (status)) {
 				return_ACPI_STATUS (status);
 			}
 		}
 		else {
-			acpi_gbl_RSDP = rsdp_address.pointer.logical;
+			acpi_gbl_RSDP = address.pointer.logical;
 		}
 
-		/*
-		 *  The signature and checksum must both be correct
-		 */
+		/* The signature and checksum must both be correct */
+
 		if (ACPI_STRNCMP ((char *) acpi_gbl_RSDP, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) {
 			/* Nope, BAD Signature */
 
@@ -204,10 +196,9 @@ acpi_get_firmware_table (
 		}
 	}
 
-	/* Get the RSDT and validate it */
+	/* Get the RSDT address via the RSDP */
 
 	acpi_tb_get_rsdt_address (&address);
-
 	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
 		"RSDP located at %p, RSDT physical=%8.8X%8.8X \n",
 		acpi_gbl_RSDP,
@@ -217,20 +208,40 @@ acpi_get_firmware_table (
 
 	address.pointer_type |= flags;
 
-	status = acpi_tb_get_table (&address, &rsdt_info);
+	/* Get and validate the RSDT */
+
+	rsdt_info = ACPI_MEM_CALLOCATE (sizeof (struct acpi_table_desc));
+	if (!rsdt_info) {
+		return_ACPI_STATUS (AE_NO_MEMORY);
+	}
+
+	status = acpi_tb_get_table (&address, rsdt_info);
 	if (ACPI_FAILURE (status)) {
-		return_ACPI_STATUS (status);
+		goto cleanup;
 	}
 
-	status = acpi_tb_validate_rsdt (rsdt_info.pointer);
+	status = acpi_tb_validate_rsdt (rsdt_info->pointer);
 	if (ACPI_FAILURE (status)) {
 		goto cleanup;
 	}
 
-	/* Get the number of table pointers within the RSDT */
+	/* Allocate a scratch table header and table descriptor */
+
+	header = ACPI_MEM_ALLOCATE (sizeof (struct acpi_table_header));
+	if (!header) {
+		status = AE_NO_MEMORY;
+		goto cleanup;
+	}
+
+	table_info = ACPI_MEM_ALLOCATE (sizeof (struct acpi_table_desc));
+	if (!table_info) {
+		status = AE_NO_MEMORY;
+		goto cleanup;
+	}
 
-	table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, rsdt_info.pointer);
+	/* Get the number of table pointers within the RSDT */
 
+	table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, rsdt_info->pointer);
 	address.pointer_type = acpi_gbl_table_flags | flags;
 
 	/*
@@ -241,35 +252,36 @@ acpi_get_firmware_table (
 		/* Get the next table pointer, handle RSDT vs. XSDT */
 
 		if (acpi_gbl_RSDP->revision < 2) {
-			address.pointer.value = (ACPI_CAST_PTR (RSDT_DESCRIPTOR, rsdt_info.pointer))->table_offset_entry[i];
+			address.pointer.value = (ACPI_CAST_PTR (
+				RSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i];
 		}
 		else {
-			address.pointer.value =
-				(ACPI_CAST_PTR (XSDT_DESCRIPTOR, rsdt_info.pointer))->table_offset_entry[i];
+			address.pointer.value = (ACPI_CAST_PTR (
+				XSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i];
 		}
 
 		/* Get the table header */
 
-		status = acpi_tb_get_table_header (&address, &header);
+		status = acpi_tb_get_table_header (&address, header);
 		if (ACPI_FAILURE (status)) {
 			goto cleanup;
 		}
 
 		/* Compare table signatures and table instance */
 
-		if (!ACPI_STRNCMP (header.signature, signature, ACPI_NAME_SIZE)) {
+		if (!ACPI_STRNCMP (header->signature, signature, ACPI_NAME_SIZE)) {
 			/* An instance of the table was found */
 
 			j++;
 			if (j >= instance) {
 				/* Found the correct instance, get the entire table */
 
-				status = acpi_tb_get_table_body (&address, &header, &table_info);
+				status = acpi_tb_get_table_body (&address, header, table_info);
 				if (ACPI_FAILURE (status)) {
 					goto cleanup;
 				}
 
-				*table_pointer = table_info.pointer;
+				*table_pointer = table_info->pointer;
 				goto cleanup;
 			}
 		}
@@ -281,7 +293,15 @@ acpi_get_firmware_table (
 
 
 cleanup:
-	acpi_os_unmap_memory (rsdt_info.pointer, (acpi_size) rsdt_info.pointer->length);
+	acpi_os_unmap_memory (rsdt_info->pointer, (acpi_size) rsdt_info->pointer->length);
+	ACPI_MEM_FREE (rsdt_info);
+
+	if (header) {
+		ACPI_MEM_FREE (header);
+	}
+	if (table_info) {
+		ACPI_MEM_FREE (table_info);
+	}
 	return_ACPI_STATUS (status);
 }
 
@@ -389,14 +409,17 @@ acpi_tb_scan_memory_for_rsdp (
  *              Flags                   - Current memory mode (logical vs.
  *                                        physical addressing)
  *
- * RETURN:      Status
+ * RETURN:      Status, RSDP physical address
  *
  * DESCRIPTION: search lower 1_mbyte of memory for the root system descriptor
  *              pointer structure.  If it is found, set *RSDP to point to it.
  *
- *              NOTE: The RSDp must be either in the first 1_k of the Extended
- *              BIOS Data Area or between E0000 and FFFFF (ACPI 1.0 section
- *              5.2.2; assertion #421).
+ *              NOTE1: The RSDp must be either in the first 1_k of the Extended
+ *              BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.)
+ *              Only a 32-bit physical address is necessary.
+ *
+ *              NOTE2: This function is always available, regardless of the
+ *              initialization state of the rest of ACPI.
  *
  ******************************************************************************/
 
@@ -407,8 +430,8 @@ acpi_tb_find_rsdp (
 {
 	u8                              *table_ptr;
 	u8                              *mem_rover;
-	u64                             phys_addr;
-	acpi_status                     status = AE_OK;
+	u32                             physical_address;
+	acpi_status                     status;
 
 
 	ACPI_FUNCTION_TRACE ("tb_find_rsdp");
@@ -419,36 +442,57 @@ acpi_tb_find_rsdp (
 	 */
 	if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
 		/*
-		 * 1) Search EBDA (low memory) paragraphs
+		 * 1a) Get the location of the EBDA
 		 */
-		status = acpi_os_map_memory ((u64) ACPI_LO_RSDP_WINDOW_BASE, ACPI_LO_RSDP_WINDOW_SIZE,
+		status = acpi_os_map_memory ((acpi_physical_address) ACPI_EBDA_PTR_LOCATION,
+				  ACPI_EBDA_PTR_LENGTH,
 				  (void *) &table_ptr);
 		if (ACPI_FAILURE (status)) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %X for length %X\n",
-				ACPI_LO_RSDP_WINDOW_BASE, ACPI_LO_RSDP_WINDOW_SIZE));
+			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %8.8X for length %X\n",
+				ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH));
 			return_ACPI_STATUS (status);
 		}
 
-		mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, ACPI_LO_RSDP_WINDOW_SIZE);
-		acpi_os_unmap_memory (table_ptr, ACPI_LO_RSDP_WINDOW_SIZE);
+		ACPI_MOVE_16_TO_32 (&physical_address, table_ptr);
+		physical_address <<= 4;                 /* Convert segment to physical address */
+		acpi_os_unmap_memory (table_ptr, ACPI_EBDA_PTR_LENGTH);
 
-		if (mem_rover) {
-			/* Found it, return the physical address */
+		/* EBDA present? */
 
-			phys_addr = ACPI_LO_RSDP_WINDOW_BASE;
-			phys_addr += ACPI_PTR_DIFF (mem_rover,table_ptr);
+		if (physical_address > 0x400) {
+			/*
+			 * 1b) Search EBDA paragraphs (EBDa is required to be a minimum of 1_k length)
+			 */
+			status = acpi_os_map_memory ((acpi_physical_address) physical_address,
+					  ACPI_EBDA_WINDOW_SIZE,
+					  (void *) &table_ptr);
+			if (ACPI_FAILURE (status)) {
+				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %8.8X for length %X\n",
+					physical_address, ACPI_EBDA_WINDOW_SIZE));
+				return_ACPI_STATUS (status);
+			}
 
-			table_info->physical_address = phys_addr;
-			return_ACPI_STATUS (AE_OK);
+			mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, ACPI_EBDA_WINDOW_SIZE);
+			acpi_os_unmap_memory (table_ptr, ACPI_EBDA_WINDOW_SIZE);
+
+			if (mem_rover) {
+				/* Found it, return the physical address */
+
+				physical_address += ACPI_PTR_DIFF (mem_rover, table_ptr);
+
+				table_info->physical_address = (acpi_physical_address) physical_address;
+				return_ACPI_STATUS (AE_OK);
+			}
 		}
 
 		/*
-		 * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h
+		 * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
 		 */
-		status = acpi_os_map_memory ((u64) ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE,
+		status = acpi_os_map_memory ((acpi_physical_address) ACPI_HI_RSDP_WINDOW_BASE,
+				  ACPI_HI_RSDP_WINDOW_SIZE,
 				  (void *) &table_ptr);
 		if (ACPI_FAILURE (status)) {
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %X for length %X\n",
+			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %8.8X for length %X\n",
 				ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE));
 			return_ACPI_STATUS (status);
 		}
@@ -459,10 +503,9 @@ acpi_tb_find_rsdp (
 		if (mem_rover) {
 			/* Found it, return the physical address */
 
-			phys_addr = ACPI_HI_RSDP_WINDOW_BASE;
-			phys_addr += ACPI_PTR_DIFF (mem_rover, table_ptr);
+			physical_address = ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF (mem_rover, table_ptr);
 
-			table_info->physical_address = phys_addr;
+			table_info->physical_address = (acpi_physical_address) physical_address;
 			return_ACPI_STATUS (AE_OK);
 		}
 	}
@@ -472,19 +515,29 @@ acpi_tb_find_rsdp (
 	 */
 	else {
 		/*
-		 * 1) Search EBDA (low memory) paragraphs
+		 * 1a) Get the location of the EBDA
 		 */
-		mem_rover = acpi_tb_scan_memory_for_rsdp (ACPI_PHYSADDR_TO_PTR (ACPI_LO_RSDP_WINDOW_BASE),
-				  ACPI_LO_RSDP_WINDOW_SIZE);
-		if (mem_rover) {
-			/* Found it, return the physical address */
-
-			table_info->physical_address = ACPI_TO_INTEGER (mem_rover);
-			return_ACPI_STATUS (AE_OK);
+		ACPI_MOVE_16_TO_32 (&physical_address, ACPI_EBDA_PTR_LOCATION);
+		physical_address <<= 4;     /* Convert segment to physical address */
+
+		/* EBDA present? */
+
+		if (physical_address > 0x400) {
+			/*
+			 * 1b) Search EBDA paragraphs (EBDa is required to be a minimum of 1_k length)
+			 */
+			mem_rover = acpi_tb_scan_memory_for_rsdp (ACPI_PHYSADDR_TO_PTR (physical_address),
+					  ACPI_EBDA_WINDOW_SIZE);
+			if (mem_rover) {
+				/* Found it, return the physical address */
+
+				table_info->physical_address = ACPI_TO_INTEGER (mem_rover);
+				return_ACPI_STATUS (AE_OK);
+			}
 		}
 
 		/*
-		 * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h
+		 * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
 		 */
 		mem_rover = acpi_tb_scan_memory_for_rsdp (ACPI_PHYSADDR_TO_PTR (ACPI_HI_RSDP_WINDOW_BASE),
 				  ACPI_HI_RSDP_WINDOW_SIZE);
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 7b94ac081..05388672d 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -60,6 +60,7 @@
 #define ACPI_THERMAL_NOTIFY_HOT		0xF1
 #define ACPI_THERMAL_MODE_ACTIVE	0x00
 #define ACPI_THERMAL_MODE_PASSIVE	0x01
+#define ACPI_THERMAL_MODE_CRT   	0xff
 #define ACPI_THERMAL_PATH_POWEROFF	"/sbin/poweroff"
 
 #define ACPI_THERMAL_MAX_ACTIVE	10
@@ -160,6 +161,7 @@ struct acpi_thermal {
 	unsigned long		last_temperature;
 	unsigned long		polling_frequency;
 	u8			cooling_mode;
+	volatile u8		zombie;
 	struct acpi_thermal_flags flags;
 	struct acpi_thermal_state state;
 	struct acpi_thermal_trips trips;
@@ -289,13 +291,6 @@ acpi_thermal_set_cooling_mode (
 	status = acpi_get_handle(tz->handle, "_SCP", &handle);
 	if (ACPI_FAILURE(status)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n"));
-		status = acpi_get_handle(tz->handle, "_PSV", &handle);
-		if(!ACPI_FAILURE(status)) {
-			tz->cooling_mode = 1;
-			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling mode [%s]\n", 
-				mode?"passive":"active"));
-			return_VALUE(0);
-		}
 		return_VALUE(-ENODEV);
 	}
 
@@ -653,7 +648,10 @@ static void
 acpi_thermal_run (
 	unsigned long		data)
 {
-	acpi_os_queue_for_execution(OSD_PRIORITY_GPE,  acpi_thermal_check, (void *) data);
+	struct acpi_thermal *tz = (struct acpi_thermal *)data;
+	if (!tz->zombie)
+		acpi_os_queue_for_execution(OSD_PRIORITY_GPE,  
+			acpi_thermal_check, (void *) data);
 }
 
 
@@ -665,7 +663,7 @@ acpi_thermal_check (
 	struct acpi_thermal	*tz = (struct acpi_thermal *) data;
 	unsigned long		sleep_time = 0;
 	int			i = 0;
-	struct acpi_thermal_state state = tz->state;
+	struct acpi_thermal_state state;
 
 	ACPI_FUNCTION_TRACE("acpi_thermal_check");
 
@@ -674,6 +672,8 @@ acpi_thermal_check (
 		return_VOID;
 	}
 
+	state = tz->state;
+
 	result = acpi_thermal_get_temperature(tz);
 	if (result)
 		return_VOID;
@@ -899,8 +899,10 @@ acpi_thermal_write_trip_points (
 	struct seq_file		*m = (struct seq_file *)file->private_data;
 	struct acpi_thermal	*tz = (struct acpi_thermal *)m->private;
 
-	char			limit_string[25] = {'\0'};
-	int			critical, hot, passive, active0, active1;
+	char			limit_string[65] = {'\0'};
+	int			num, critical, hot, passive;
+	int			active[ACPI_THERMAL_MAX_ACTIVE];
+	int			i = 0;
 
 	ACPI_FUNCTION_TRACE("acpi_thermal_write_trip_points");
 
@@ -916,7 +918,11 @@ acpi_thermal_write_trip_points (
 	
 	limit_string[count] = '\0';
 
-	if (sscanf(limit_string, "%d:%d:%d:%d:%d", &critical, &hot, &passive, &active0, &active1) != 5) {
+	num = sscanf(limit_string, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+				&critical, &hot, &passive,
+				&active[0], &active[1], &active[2], &active[3], &active[4],
+				&active[5], &active[6], &active[7], &active[8], &active[9]);
+	if(!(num >=5 && num < (ACPI_THERMAL_MAX_ACTIVE + 3))) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n"));
 		return_VALUE(-EINVAL);
 	}
@@ -924,8 +930,11 @@ acpi_thermal_write_trip_points (
 	tz->trips.critical.temperature = CELSIUS_TO_KELVIN(critical);
 	tz->trips.hot.temperature = CELSIUS_TO_KELVIN(hot);
 	tz->trips.passive.temperature = CELSIUS_TO_KELVIN(passive);
-	tz->trips.active[0].temperature = CELSIUS_TO_KELVIN(active0);
-	tz->trips.active[1].temperature = CELSIUS_TO_KELVIN(active1);
+	for (i = 0; i < num - 3; i++) {
+		if (!(tz->trips.active[i].flags.valid))
+			break;
+		tz->trips.active[i].temperature = CELSIUS_TO_KELVIN(active[i]);
+	}
 	
 	return_VALUE(count);
 }
@@ -941,12 +950,14 @@ static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset)
 		goto end;
 
 	if (!tz->flags.cooling_mode) {
-		seq_puts(seq, "<not supported>\n");
-		goto end;
+		seq_puts(seq, "<setting not supported>\n");
 	}
 
-	seq_printf(seq, "cooling mode:            %s\n",
-		tz->cooling_mode?"passive":"active");
+	if ( tz->cooling_mode == ACPI_THERMAL_MODE_CRT )
+		seq_printf(seq, "cooling mode:	critical\n");
+	else
+		seq_printf(seq, "cooling mode:	%s\n",
+			tz->cooling_mode?"passive":"active");
 
 end:
 	return 0;
@@ -988,6 +999,8 @@ acpi_thermal_write_cooling_mode (
 	if (result)
 		return_VALUE(result);
 
+	acpi_thermal_check(tz);
+
 	return_VALUE(count);
 }
 
@@ -1225,16 +1238,34 @@ acpi_thermal_get_info (
 	if (result)
 		return_VALUE(result);
 
-	/* Set the cooling mode [_SCP] to active cooling (default) */
-	result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE);
-	if (!result)
-		tz->flags.cooling_mode = 1;
-
 	/* Get trip points [_CRT, _PSV, etc.] (required) */
 	result = acpi_thermal_get_trip_points(tz);
 	if (result)
 		return_VALUE(result);
 
+	/* Set the cooling mode [_SCP] to active cooling (default) */
+	result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE);
+	if (!result) 
+		tz->flags.cooling_mode = 1;
+	else { 
+		/* Oh,we have not _SCP method.
+		   Generally show cooling_mode by _ACx, _PSV,spec 12.2*/
+		tz->flags.cooling_mode = 0;
+		if ( tz->trips.active[0].flags.valid && tz->trips.passive.flags.valid ) {
+			if ( tz->trips.passive.temperature > tz->trips.active[0].temperature )
+				tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE;
+			else 
+				tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE;
+		} else if ( !tz->trips.active[0].flags.valid && tz->trips.passive.flags.valid ) {
+			tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE;
+		} else if ( tz->trips.active[0].flags.valid && !tz->trips.passive.flags.valid ) {
+			tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE;
+		} else {
+			/* _ACx and _PSV are optional, but _CRT is required */
+			tz->cooling_mode = ACPI_THERMAL_MODE_CRT;
+		}
+	}
+
 	/* Get default polling frequency [_TZP] (optional) */
 	if (tzp)
 		tz->polling_frequency = tzp;
@@ -1324,8 +1355,14 @@ acpi_thermal_remove (
 
 	tz = (struct acpi_thermal *) acpi_driver_data(device);
 
-	if (timer_pending(&(tz->timer)))
-		del_timer(&(tz->timer));
+	/* avoid timer adding new defer task */
+	tz->zombie = 1;
+	/* wait for running timer (on other CPUs) finish */
+	del_timer_sync(&(tz->timer));
+	/* synchronize deferred task */
+	acpi_os_wait_events_complete(NULL);
+	/* deferred task may reinsert timer */
+	del_timer_sync(&(tz->timer));
 
 	status = acpi_remove_notify_handler(tz->handle,
 		ACPI_DEVICE_NOTIFY, acpi_thermal_notify);
@@ -1347,6 +1384,7 @@ acpi_thermal_remove (
 
 	acpi_thermal_remove_fs(device);
 
+	kfree(tz);
 	return_VALUE(0);
 }
 
diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c
index 2050d238d..58ec6733e 100644
--- a/drivers/acpi/utilities/utalloc.c
+++ b/drivers/acpi/utilities/utalloc.c
@@ -259,8 +259,8 @@ acpi_ut_validate_buffer (
  *
  * FUNCTION:    acpi_ut_initialize_buffer
  *
- * PARAMETERS:  required_length     - Length needed
- *              Buffer              - Buffer to be validated
+ * PARAMETERS:  Buffer              - Buffer to be validated
+ *              required_length     - Length needed
  *
  * RETURN:      Status
  *
@@ -603,7 +603,8 @@ acpi_ut_free_and_track (
  *
  * FUNCTION:    acpi_ut_find_allocation
  *
- * PARAMETERS:  Allocation             - Address of allocated memory
+ * PARAMETERS:  list_id                 - Memory list to search
+ *              Allocation              - Address of allocated memory
  *
  * RETURN:      A list element if found; NULL otherwise.
  *
@@ -646,7 +647,8 @@ acpi_ut_find_allocation (
  *
  * FUNCTION:    acpi_ut_track_allocation
  *
- * PARAMETERS:  Allocation          - Address of allocated memory
+ * PARAMETERS:  list_id             - Memory list to search
+ *              Allocation          - Address of allocated memory
  *              Size                - Size of the allocation
  *              alloc_type          - MEM_MALLOC or MEM_CALLOC
  *              Component           - Component type of caller
@@ -733,7 +735,8 @@ unlock_and_exit:
  *
  * FUNCTION:    acpi_ut_remove_allocation
  *
- * PARAMETERS:  Allocation          - Address of allocated memory
+ * PARAMETERS:  list_id             - Memory list to search
+ *              Allocation          - Address of allocated memory
  *              Component           - Component type of caller
  *              Module              - Source file name of caller
  *              Line                - Line number of caller
diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c
index c3f5900b6..0aa1fde7e 100644
--- a/drivers/acpi/utilities/uteval.c
+++ b/drivers/acpi/utilities/uteval.c
@@ -133,7 +133,7 @@ acpi_ut_evaluate_object (
 	u32                             expected_return_btypes,
 	union acpi_operand_object       **return_desc)
 {
-	union acpi_operand_object       *obj_desc;
+	struct acpi_parameter_info      info;
 	acpi_status                     status;
 	u32                             return_btype;
 
@@ -141,9 +141,13 @@ acpi_ut_evaluate_object (
 	ACPI_FUNCTION_TRACE ("ut_evaluate_object");
 
 
+	info.node = prefix_node;
+	info.parameters = NULL;
+	info.parameter_type = ACPI_PARAM_ARGS;
+
 	/* Evaluate the object/method */
 
-	status = acpi_ns_evaluate_relative (prefix_node, path, NULL, &obj_desc);
+	status = acpi_ns_evaluate_relative (path, &info);
 	if (ACPI_FAILURE (status)) {
 		if (status == AE_NOT_FOUND) {
 			ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s.%s] was not found\n",
@@ -159,7 +163,7 @@ acpi_ut_evaluate_object (
 
 	/* Did we get a return object? */
 
-	if (!obj_desc) {
+	if (!info.return_object) {
 		if (expected_return_btypes) {
 			ACPI_REPORT_METHOD_ERROR ("No object was returned from",
 				prefix_node, path, AE_NOT_EXIST);
@@ -172,7 +176,7 @@ acpi_ut_evaluate_object (
 
 	/* Map the return object type to the bitmapped type */
 
-	switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+	switch (ACPI_GET_OBJECT_TYPE (info.return_object)) {
 	case ACPI_TYPE_INTEGER:
 		return_btype = ACPI_BTYPE_INTEGER;
 		break;
@@ -202,17 +206,17 @@ acpi_ut_evaluate_object (
 
 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
 			"Type returned from %s was incorrect: %X\n",
-			path, ACPI_GET_OBJECT_TYPE (obj_desc)));
+			path, ACPI_GET_OBJECT_TYPE (info.return_object)));
 
 		/* On error exit, we must delete the return object */
 
-		acpi_ut_remove_reference (obj_desc);
+		acpi_ut_remove_reference (info.return_object);
 		return_ACPI_STATUS (AE_TYPE);
 	}
 
 	/* Object type is OK, return it */
 
-	*return_desc = obj_desc;
+	*return_desc = info.return_object;
 	return_ACPI_STATUS (AE_OK);
 }
 
diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c
index e1d19936e..f42848ab7 100644
--- a/drivers/acpi/utilities/utglobal.c
+++ b/drivers/acpi/utilities/utglobal.c
@@ -142,16 +142,11 @@ unknown:
  */
 
 /* Debug switch - level and trace mask */
-
-#ifdef ACPI_DEBUG_OUTPUT
-u32                                 acpi_dbg_level = ACPI_DEBUG_DEFAULT;
-#else
-u32                                 acpi_dbg_level = ACPI_NORMAL_DEFAULT;
-#endif
+u32                                 acpi_dbg_level = 0;
 
 /* Debug switch - layer (component) mask */
 
-u32                                 acpi_dbg_layer = ACPI_COMPONENT_DEFAULT;
+u32                                 acpi_dbg_layer = 0;
 u32                                 acpi_gbl_nesting_level = 0;
 
 
@@ -171,27 +166,40 @@ u8                                  acpi_gbl_shutdown = TRUE;
 
 const u8                            acpi_gbl_decode_to8bit [8] = {1,2,4,8,16,32,64,128};
 
-const char                          *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = {
-			  "\\_S0_",
-			  "\\_S1_",
-			  "\\_S2_",
-			  "\\_S3_",
-			  "\\_S4_",
-			  "\\_S5_"};
-
-const char                          *acpi_gbl_highest_dstate_names[4] = {
-					   "_S1D",
-					   "_S2D",
-					   "_S3D",
-					   "_S4D"};
+const char                          *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] =
+{
+	"\\_S0_",
+	"\\_S1_",
+	"\\_S2_",
+	"\\_S3_",
+	"\\_S4_",
+	"\\_S5_"
+};
 
-/* Strings supported by the _OSI predefined (internal) method */
+const char                          *acpi_gbl_highest_dstate_names[4] =
+{
+	"_S1D",
+	"_S2D",
+	"_S3D",
+	"_S4D"
+};
 
-const char                          *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] = {
-							 "Linux",
-							 "Windows 2000",
-							 "Windows 2001",
-							 "Windows 2001.1"};
+/*
+ * Strings supported by the _OSI predefined (internal) method.
+ * When adding strings, be sure to update ACPI_NUM_OSI_STRINGS.
+ */
+const char                          *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] =
+{
+	"Linux",
+	"Windows 2000",
+	"Windows 2001",
+	"Windows 2001.1",
+	"Windows 2001 SP0",
+	"Windows 2001 SP1",
+	"Windows 2001 SP2",
+	"Windows 2001 SP3",
+	"Windows 2001 SP4"
+};
 
 
 /******************************************************************************
@@ -213,7 +221,7 @@ const struct acpi_predefined_names      acpi_gbl_pre_defined_names[] =
 	{"_PR_",    ACPI_TYPE_LOCAL_SCOPE,      NULL},
 	{"_SB_",    ACPI_TYPE_DEVICE,           NULL},
 	{"_SI_",    ACPI_TYPE_LOCAL_SCOPE,      NULL},
-	{"_TZ_",    ACPI_TYPE_LOCAL_SCOPE,      NULL},
+	{"_TZ_",    ACPI_TYPE_THERMAL,          NULL},
 	{"_REV",    ACPI_TYPE_INTEGER,          "2"},
 	{"_OS_",    ACPI_TYPE_STRING,           ACPI_OS_NAME},
 	{"_GL_",    ACPI_TYPE_MUTEX,            "0"},
@@ -561,26 +569,37 @@ acpi_ut_get_node_name (
 	struct acpi_namespace_node      *node = (struct acpi_namespace_node *) object;
 
 
+	/* Must return a string of exactly 4 characters == ACPI_NAME_SIZE */
+
 	if (!object)
 	{
-		return ("NULL NODE");
+		return ("NULL");
 	}
 
-	if (object == ACPI_ROOT_OBJECT)
+	/* Check for Root node */
+
+	if ((object == ACPI_ROOT_OBJECT) ||
+		(object == acpi_gbl_root_node))
 	{
-		node = acpi_gbl_root_node;
+		return ("\"\\\" ");
 	}
 
+	/* Descriptor must be a namespace node */
+
 	if (node->descriptor != ACPI_DESC_TYPE_NAMED)
 	{
-		return ("****");
+		return ("####");
 	}
 
+	/* Name must be a valid ACPI name */
+
 	if (!acpi_ut_valid_acpi_name (* (u32 *) node->name.ascii))
 	{
-		return ("----");
+		return ("????");
 	}
 
+	/* Return the name */
+
 	return (node->name.ascii);
 }
 
@@ -783,10 +802,6 @@ acpi_ut_init_globals (
 
 	ACPI_FUNCTION_TRACE ("ut_init_globals");
 
-	/* Runtime configuration */
-
-	acpi_gbl_create_osi_method = TRUE;
-	acpi_gbl_all_methods_serialized = FALSE;
 
 	/* Memory allocation and cache lists */
 
@@ -880,6 +895,7 @@ acpi_ut_init_globals (
 	/* Hardware oriented */
 
 	acpi_gbl_events_initialized         = FALSE;
+	acpi_gbl_system_awake_and_running   = TRUE;
 
 	/* Namespace */
 
diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c
index 5cbd93eef..45c14f9ef 100644
--- a/drivers/acpi/utilities/utxface.c
+++ b/drivers/acpi/utilities/utxface.c
@@ -157,9 +157,8 @@ acpi_enable_subsystem (
 		}
 	}
 
-	/*
-	 * Enable ACPI mode
-	 */
+	/* Enable ACPI mode */
+
 	if (!(flags & ACPI_NO_ACPI_ENABLE)) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Going into ACPI mode\n"));
 
@@ -173,7 +172,21 @@ acpi_enable_subsystem (
 	}
 
 	/*
-	 * Initialize ACPI Event handling
+	 * Install the default op_region handlers. These are installed unless
+	 * other handlers have already been installed via the
+	 * install_address_space_handler interface.
+	 */
+	if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
+		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing default address space handlers\n"));
+
+		status = acpi_ev_install_region_handlers ();
+		if (ACPI_FAILURE (status)) {
+			return_ACPI_STATUS (status);
+		}
+	}
+
+	/*
+	 * Initialize ACPI Event handling (Fixed and General Purpose)
 	 *
 	 * NOTE: We must have the hardware AND events initialized before we can execute
 	 * ANY control methods SAFELY.  Any control method can require ACPI hardware
@@ -182,18 +195,18 @@ acpi_enable_subsystem (
 	if (!(flags & ACPI_NO_EVENT_INIT)) {
 		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI events\n"));
 
-		status = acpi_ev_initialize ();
+		status = acpi_ev_initialize_events ();
 		if (ACPI_FAILURE (status)) {
 			return_ACPI_STATUS (status);
 		}
 	}
 
-	/* Install the SCI handler, Global Lock handler, and GPE handlers */
+	/* Install the SCI handler and Global Lock handler */
 
 	if (!(flags & ACPI_NO_HANDLER_INIT)) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing SCI/GL/GPE handlers\n"));
+		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing SCI/GL handlers\n"));
 
-		status = acpi_ev_handler_initialize ();
+		status = acpi_ev_install_xrupt_handlers ();
 		if (ACPI_FAILURE (status)) {
 			return_ACPI_STATUS (status);
 		}
@@ -226,18 +239,16 @@ acpi_initialize_objects (
 
 
 	/*
-	 * Install the default op_region handlers. These are installed unless
-	 * other handlers have already been installed via the
-	 * install_address_space_handler interface.
+	 * Run all _REG methods
 	 *
-	 * NOTE: This will cause _REG methods to be run.  Any objects accessed
+	 * NOTE: Any objects accessed
 	 * by the _REG methods will be automatically initialized, even if they
 	 * contain executable AML (see call to acpi_ns_initialize_objects below).
 	 */
 	if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing default address space handlers\n"));
+		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Executing _REG op_region methods\n"));
 
-		status = acpi_ev_init_address_spaces ();
+		status = acpi_ev_initialize_op_regions ();
 		if (ACPI_FAILURE (status)) {
 			return_ACPI_STATUS (status);
 		}
@@ -249,7 +260,7 @@ acpi_initialize_objects (
 	 * objects: operation_regions, buffer_fields, Buffers, and Packages.
 	 */
 	if (!(flags & ACPI_NO_OBJECT_INIT)) {
-		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI Objects\n"));
+		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Completing Initialization of ACPI Objects\n"));
 
 		status = acpi_ns_initialize_objects ();
 		if (ACPI_FAILURE (status)) {
diff --git a/drivers/atm/Makefile b/drivers/atm/Makefile
index bcd60fb8d..907c5933a 100644
--- a/drivers/atm/Makefile
+++ b/drivers/atm/Makefile
@@ -3,7 +3,7 @@
 #
 
 fore_200e-objs	:= fore200e.o
-host-progs	:= fore200e_mkfirm
+hostprogs-y	:= fore200e_mkfirm
 
 # Files generated that shall be removed upon make clean
 clean-files := atmsar11.bin atmsar11.bin1 atmsar11.bin2 pca200e.bin \
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
index fe809480e..9be4013f5 100644
--- a/drivers/atm/ambassador.c
+++ b/drivers/atm/ambassador.c
@@ -2291,11 +2291,10 @@ static int __init do_pci_device(struct pci_dev *pci_dev)
 
 	// read resources from PCI configuration space
 	u8 irq = pci_dev->irq;
-	u32 * membase = bus_to_virt (pci_resource_start (pci_dev, 0));
-	u32 iobase = pci_resource_start (pci_dev, 1);
 
 	PRINTD (DBG_INFO, "found Madge ATM adapter (amb) at"
-		" IO %x, IRQ %u, MEM %p", iobase, irq, membase);
+		" IO %x, IRQ %u, MEM %p", pci_resource_start(pci_dev, 1),
+		irq, bus_to_virt(pci_resource_start(pci_dev, 0)));
 
 	// check IO region
 	err = pci_request_region(pci_dev, 1, DEV_LABEL);
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index 8b137034d..81127d178 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -173,7 +173,7 @@ static void dump_mem(struct eni_dev *eni_dev)
 	int i;
 
 	for (i = 0; i < eni_dev->free_len; i++)
-		printk(KERN_DEBUG "  %d: 0x%lx %d\n",i,
+		printk(KERN_DEBUG "  %d: %p %d\n",i,
 		    eni_dev->free_list[i].start,
 		    1 << eni_dev->free_list[i].order);
 }
@@ -191,19 +191,19 @@ static void dump(struct atm_dev *dev)
 	printk(KERN_NOTICE "TX buffers\n");
 	for (i = 0; i < NR_CHAN; i++)
 		if (eni_dev->tx[i].send)
-			printk(KERN_NOTICE "  TX %d @ 0x%lx: %ld\n",i,
+			printk(KERN_NOTICE "  TX %d @ %p: %ld\n",i,
 			    eni_dev->tx[i].send,eni_dev->tx[i].words*4);
 	printk(KERN_NOTICE "RX buffers\n");
 	for (i = 0; i < 1024; i++)
 		if (eni_dev->rx_map[i] && ENI_VCC(eni_dev->rx_map[i])->rx)
-			printk(KERN_NOTICE "  RX %d @ 0x%lx: %ld\n",i,
+			printk(KERN_NOTICE "  RX %d @ %p: %ld\n",i,
 			    ENI_VCC(eni_dev->rx_map[i])->recv,
 			    ENI_VCC(eni_dev->rx_map[i])->words*4);
 	printk(KERN_NOTICE "----\n");
 }
 
 
-static void eni_put_free(struct eni_dev *eni_dev,unsigned long start,
+static void eni_put_free(struct eni_dev *eni_dev, void __iomem *start,
     unsigned long size)
 {
 	struct eni_free *list;
@@ -215,17 +215,17 @@ static void eni_put_free(struct eni_dev *eni_dev,unsigned long start,
 	len = eni_dev->free_len;
 	while (size) {
 		if (len >= eni_dev->free_list_size) {
-			printk(KERN_CRIT "eni_put_free overflow (0x%lx,%ld)\n",
+			printk(KERN_CRIT "eni_put_free overflow (%p,%ld)\n",
 			    start,size);
 			break;
 		}
-		for (order = 0; !((start | size) & (1 << order)); order++);
+		for (order = 0; !(((unsigned long)start | size) & (1 << order)); order++);
 		if (MID_MIN_BUF_SIZE > (1 << order)) {
 			printk(KERN_CRIT "eni_put_free: order %d too small\n",
 			    order);
 			break;
 		}
-		list[len].start = start;
+		list[len].start = (void __iomem *) start;
 		list[len].order = order;
 		len++;
 		start += 1 << order;
@@ -236,10 +236,10 @@ static void eni_put_free(struct eni_dev *eni_dev,unsigned long start,
 }
 
 
-static unsigned long eni_alloc_mem(struct eni_dev *eni_dev,unsigned long *size)
+static void __iomem *eni_alloc_mem(struct eni_dev *eni_dev, unsigned long *size)
 {
 	struct eni_free *list;
-	unsigned long start;
+	void __iomem *start;
 	int len,i,order,best_order,index;
 
 	list = eni_dev->free_list;
@@ -273,7 +273,7 @@ static unsigned long eni_alloc_mem(struct eni_dev *eni_dev,unsigned long *size)
 }
 
 
-static void eni_free_mem(struct eni_dev *eni_dev,unsigned long start,
+static void eni_free_mem(struct eni_dev *eni_dev, void __iomem *start,
     unsigned long size)
 {
 	struct eni_free *list;
@@ -283,20 +283,20 @@ static void eni_free_mem(struct eni_dev *eni_dev,unsigned long start,
 	list = eni_dev->free_list;
 	len = eni_dev->free_len;
 	for (order = -1; size; order++) size >>= 1;
-	DPRINTK("eni_free_mem: 0x%lx+0x%lx (order %d)\n",start,size,order);
+	DPRINTK("eni_free_mem: %p+0x%lx (order %d)\n",start,size,order);
 	for (i = 0; i < len; i++)
-		if (list[i].start == (start^(1 << order)) &&
+		if (((unsigned long) list[i].start) == ((unsigned long)start^(1 << order)) &&
 		    list[i].order == order) {
 			DPRINTK("match[%d]: 0x%lx/0x%lx(0x%x), %d/%d\n",i,
 			    list[i].start,start,1 << order,list[i].order,order);
 			list[i] = list[--len];
-			start &= ~(unsigned long) (1 << order);
+			start = (void __iomem *) ((unsigned long) start & ~(unsigned long) (1 << order));
 			order++;
 			i = -1;
 			continue;
 		}
 	if (len >= eni_dev->free_list_size) {
-		printk(KERN_ALERT "eni_free_mem overflow (0x%lx,%d)\n",start,
+		printk(KERN_ALERT "eni_free_mem overflow (%p,%d)\n",start,
 		    order);
 		return;
 	}
@@ -333,7 +333,7 @@ static void rx_ident_err(struct atm_vcc *vcc)
 	printk(KERN_ALERT "  host descr 0x%lx, rx pos 0x%lx, descr value "
 	    "0x%x\n",eni_vcc->descr,eni_vcc->rx_pos,
 	    (unsigned) readl(eni_vcc->recv+eni_vcc->descr*4));
-	printk(KERN_ALERT "  last 0x%p, servicing %d\n",eni_vcc->last,
+	printk(KERN_ALERT "  last %p, servicing %d\n",eni_vcc->last,
 	    eni_vcc->servicing);
 	EVENT("---dump ends here---\n",0,0);
 	printk(KERN_NOTICE "---recent events---\n");
@@ -617,7 +617,8 @@ static int rx_aal5(struct atm_vcc *vcc)
 
 static inline int rx_vcc(struct atm_vcc *vcc)
 {
-	unsigned long vci_dsc,tmp;
+	void __iomem *vci_dsc;
+	unsigned long tmp;
 	struct eni_vcc *eni_vcc;
 
 	eni_vcc = ENI_VCC(vcc);
@@ -728,7 +729,7 @@ static void dequeue_rx(struct atm_dev *dev)
 	struct eni_vcc *eni_vcc;
 	struct atm_vcc *vcc;
 	struct sk_buff *skb;
-	unsigned long vci_dsc;
+	void __iomem *vci_dsc;
 	int first;
 
 	eni_dev = ENI_DEV(dev);
@@ -808,7 +809,7 @@ static int open_rx_first(struct atm_vcc *vcc)
 
 static int open_rx_second(struct atm_vcc *vcc)
 {
-	unsigned long here;
+	void __iomem *here;
 	struct eni_dev *eni_dev;
 	struct eni_vcc *eni_vcc;
 	unsigned long size;
@@ -840,7 +841,7 @@ static int open_rx_second(struct atm_vcc *vcc)
 static void close_rx(struct atm_vcc *vcc)
 {
 	DECLARE_WAITQUEUE(wait,current);
-	unsigned long here;
+	void __iomem *here;
 	struct eni_dev *eni_dev;
 	struct eni_vcc *eni_vcc;
 
@@ -1289,7 +1290,8 @@ static int reserve_or_set_tx(struct atm_vcc *vcc,struct atm_trafprm *txtp,
 	struct eni_dev *eni_dev = ENI_DEV(vcc->dev);
 	struct eni_vcc *eni_vcc = ENI_VCC(vcc);
 	struct eni_tx *tx;
-	unsigned long size,mem;
+	unsigned long size;
+	void __iomem *mem;
 	int rate,ubr,unlimited,new_tx;
 	int pre,res,order;
 	int error;
@@ -1687,9 +1689,9 @@ static int __devinit get_esi_asic(struct atm_dev *dev)
 #undef GET_SEPROM
 
 
-static int __devinit get_esi_fpga(struct atm_dev *dev,unsigned long base)
+static int __devinit get_esi_fpga(struct atm_dev *dev, void __iomem *base)
 {
-	unsigned long mac_base;
+	void __iomem *mac_base;
 	int i;
 
 	mac_base = base+EPROM_SIZE-sizeof(struct midway_eprom);
@@ -1703,7 +1705,8 @@ static int __devinit eni_do_init(struct atm_dev *dev)
 	struct midway_eprom *eprom;
 	struct eni_dev *eni_dev;
 	struct pci_dev *pci_dev;
-	unsigned long real_base,base;
+	unsigned long real_base;
+	void __iomem *base;
 	unsigned char revision;
 	int error,i,last;
 
@@ -1730,13 +1733,13 @@ static int __devinit eni_do_init(struct atm_dev *dev)
 	}
 	printk(KERN_NOTICE DEV_LABEL "(itf %d): rev.%d,base=0x%lx,irq=%d,",
 	    dev->number,revision,real_base,eni_dev->irq);
-	if (!(base = (unsigned long) ioremap_nocache(real_base,MAP_MAX_SIZE))) {
+	if (!(base = ioremap_nocache(real_base,MAP_MAX_SIZE))) {
 		printk("\n");
 		printk(KERN_ERR DEV_LABEL "(itf %d): can't set up page "
 		    "mapping\n",dev->number);
 		return error;
 	}
-	eni_dev->base_diff = real_base-base;
+	eni_dev->base_diff = real_base - (unsigned long) base;
 	/* id may not be present in ASIC Tonga boards - check this @@@ */
 	if (!eni_dev->asic) {
 		eprom = (struct midway_eprom *) (base+EPROM_SIZE-sizeof(struct
@@ -1790,7 +1793,9 @@ static int __devinit eni_do_init(struct atm_dev *dev)
 static int __devinit eni_start(struct atm_dev *dev)
 {
 	struct eni_dev *eni_dev;
-	unsigned long buf,buffer_mem;
+	
+	void __iomem *buf;
+	unsigned long buffer_mem;
 	int error;
 
 	DPRINTK(">eni_start\n");
@@ -1828,7 +1833,7 @@ static int __devinit eni_start(struct atm_dev *dev)
 	tasklet_init(&eni_dev->task,eni_tasklet,(unsigned long) dev);
 	eni_dev->events = 0;
 	/* initialize memory management */
-	buffer_mem = eni_dev->mem-(buf-eni_dev->ram);
+	buffer_mem = eni_dev->mem - (buf - eni_dev->ram);
 	eni_dev->free_list_size = buffer_mem/MID_MIN_BUF_SIZE/2;
 	eni_dev->free_list = (struct eni_free *) kmalloc(
 	    sizeof(struct eni_free)*(eni_dev->free_list_size+1),GFP_KERNEL);
@@ -1955,7 +1960,7 @@ static int eni_change_qos(struct atm_vcc *vcc,struct atm_qos *qos,int flgs)
 	 */
 	tasklet_disable(&eni_dev->task);
 	skb_queue_walk(&eni_dev->tx_queue, skb) {
-		unsigned long dsc;
+		void __iomem *dsc;
 
 		if (ATM_SKB(skb)->vcc != vcc) continue;
 		dsc = tx->send+ENI_PRV_POS(skb)*4;
@@ -2136,9 +2141,9 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page)
 
 		if (!tx->send) continue;
 		if (!--left) {
-			return sprintf(page,"tx[%d]:    0x%06lx-0x%06lx "
+			return sprintf(page,"tx[%d]:    0x%ld-0x%ld "
 			    "(%6ld bytes), rsv %d cps, shp %d cps%s\n",i,
-			    tx->send-eni_dev->ram,
+			    (unsigned long) (tx->send - eni_dev->ram),
 			    tx->send-eni_dev->ram+tx->words*4-1,tx->words*4,
 			    tx->reserved,tx->shaping,
 			    tx == eni_dev->ubr ? " (UBR)" : "");
@@ -2162,9 +2167,9 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page)
 			if (--left) continue;
 			length = sprintf(page,"vcc %4d: ",vcc->vci);
 			if (eni_vcc->rx) {
-				length += sprintf(page+length,"0x%06lx-0x%06lx "
+				length += sprintf(page+length,"0x%ld-0x%ld "
 				    "(%6ld bytes)",
-				    eni_vcc->recv-eni_dev->ram,
+				    (unsigned long) (eni_vcc->recv - eni_dev->ram),
 				    eni_vcc->recv-eni_dev->ram+eni_vcc->words*4-1,
 				    eni_vcc->words*4);
 				if (eni_vcc->tx) length += sprintf(page+length,", ");
@@ -2183,8 +2188,8 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page)
 		unsigned long offset;
 
 		if (--left) continue;
-		offset = eni_dev->ram+eni_dev->base_diff;
-		return sprintf(page,"free      0x%06lx-0x%06lx (%6d bytes)\n",
+		offset = (unsigned long) eni_dev->ram+eni_dev->base_diff;
+		return sprintf(page,"free      %p-%p (%6d bytes)\n",
 		    fe->start-offset,fe->start-offset+(1 << fe->order)-1,
 		    1 << fe->order);
 	}
diff --git a/drivers/atm/eni.h b/drivers/atm/eni.h
index e7af66bd8..385090c2a 100644
--- a/drivers/atm/eni.h
+++ b/drivers/atm/eni.h
@@ -33,12 +33,12 @@
 
 
 struct eni_free {
-	unsigned long start;		/* counting in bytes */
+	void __iomem *start;		/* counting in bytes */
 	int order;
 };
 
 struct eni_tx {
-	unsigned long send;		/* base, 0 if unused */
+	void __iomem *send;		/* base, 0 if unused */
 	int prescaler;			/* shaping prescaler */
 	int resolution;			/* shaping divider */
 	unsigned long tx_pos;		/* current TX write position */
@@ -51,7 +51,7 @@ struct eni_tx {
 
 struct eni_vcc {
 	int (*rx)(struct atm_vcc *vcc);	/* RX function, NULL if none */
-	unsigned long recv;		/* receive buffer */
+	void __iomem *recv;		/* receive buffer */
 	unsigned long words;		/* its size in words */
 	unsigned long descr;		/* next descriptor (RX) */
 	unsigned long rx_pos;		/* current RX descriptor pos */
@@ -72,13 +72,13 @@ struct eni_dev {
 	u32 events;			/* pending events */
 	/*-------------------------------- base pointers into Midway address
 					   space */
-	unsigned long phy;		/* PHY interface chip registers */
-	unsigned long reg;		/* register base */
-	unsigned long ram;		/* RAM base */
-	unsigned long vci;		/* VCI table */
-	unsigned long rx_dma;		/* RX DMA queue */
-	unsigned long tx_dma;		/* TX DMA queue */
-	unsigned long service;		/* service list */
+	void __iomem *phy;		/* PHY interface chip registers */
+	void __iomem *reg;		/* register base */
+	void __iomem *ram;		/* RAM base */
+	void __iomem *vci;		/* VCI table */
+	void __iomem *rx_dma;		/* RX DMA queue */
+	void __iomem *tx_dma;		/* TX DMA queue */
+	void __iomem *service;		/* service list */
 	/*-------------------------------- TX part */
 	struct eni_tx tx[NR_CHAN];	/* TX channels */
 	struct eni_tx *ubr;		/* UBR channel */
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
index 91b85a95d..68919a710 100644
--- a/drivers/atm/firestream.c
+++ b/drivers/atm/firestream.c
@@ -1667,7 +1667,7 @@ static int __devinit fs_init (struct fs_dev *dev)
 
 	dev->hw_base = pci_resource_start(pci_dev, 0);
 
-	dev->base = (ulong) ioremap(dev->hw_base, 0x1000);
+	dev->base = ioremap(dev->hw_base, 0x1000);
 
 	reset_chip (dev);
   
@@ -1704,8 +1704,7 @@ static int __devinit fs_init (struct fs_dev *dev)
 		}
 
 		/* Try again after 10ms. */
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout ((HZ+99)/100);
+		msleep(10);
 	}
 
 	if (!to) {
diff --git a/drivers/atm/firestream.h b/drivers/atm/firestream.h
index 8ef266cc8..49e783e35 100644
--- a/drivers/atm/firestream.h
+++ b/drivers/atm/firestream.h
@@ -477,7 +477,7 @@ struct fs_dev {
 	struct timer_list timer;
 
 	unsigned long hw_base;		/* mem base address */
-	unsigned long base;             /* Mapping of base address */
+	void __iomem *base;             /* Mapping of base address */
 	int channo;
 	unsigned long channel_mask;
 
diff --git a/drivers/atm/fore200e.h b/drivers/atm/fore200e.h
index aca550b66..420216561 100644
--- a/drivers/atm/fore200e.h
+++ b/drivers/atm/fore200e.h
@@ -565,7 +565,7 @@ typedef struct host_cmdq_entry {
 typedef struct chunk {
     void* alloc_addr;    /* base address of allocated chunk */
     void* align_addr;    /* base address of aligned chunk   */
-    u32   dma_addr;      /* DMA address of aligned chunk    */
+    dma_addr_t dma_addr; /* DMA address of aligned chunk    */
     int   direction;     /* direction of DMA mapping        */
     u32   alloc_size;    /* length of allocated chunk       */
     u32   align_size;    /* length of aligned chunk         */
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index 71e5b5146..74b490bc4 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -1007,6 +1007,7 @@ he_start(struct atm_dev *dev)
 {
 	struct he_dev *he_dev;
 	struct pci_dev *pci_dev;
+	unsigned long membase;
 
 	u16 command;
 	u32 gen_cntl_0, host_cntl, lb_swap;
@@ -1019,8 +1020,8 @@ he_start(struct atm_dev *dev)
 	he_dev = HE_DEV(dev);
 	pci_dev = he_dev->pci_dev;
 
-	he_dev->membase = pci_dev->resource[0].start;
-	HPRINTK("membase = 0x%lx  irq = %d.\n", he_dev->membase, pci_dev->irq);
+	membase = pci_resource_start(pci_dev, 0);
+	HPRINTK("membase = 0x%lx  irq = %d.\n", membase, pci_dev->irq);
 
 	/*
 	 * pci bus controller initialization 
@@ -1080,7 +1081,7 @@ he_start(struct atm_dev *dev)
 			hprintk("can't set latency timer to %d\n", timer);
 	}
 
-	if (!(he_dev->membase = (unsigned long) ioremap(he_dev->membase, HE_REGMAP_SIZE))) {
+	if (!(he_dev->membase = ioremap(membase, HE_REGMAP_SIZE))) {
 		hprintk("can't set up page mapping\n");
 		return -EINVAL;
 	}
@@ -1962,7 +1963,7 @@ he_service_tbrq(struct he_dev *he_dev, int group)
 	struct he_tpd *tpd;
 	int slot, updated = 0;
 #ifdef USE_TPD_POOL
-	struct list_head *p;
+	struct he_tpd *__tpd;
 #endif
 
 	/* 2.1.6 transmit buffer return queue */
@@ -1977,8 +1978,7 @@ he_service_tbrq(struct he_dev *he_dev, int group)
 			TBRQ_MULTIPLE(he_dev->tbrq_head) ? " MULTIPLE" : "");
 #ifdef USE_TPD_POOL
 		tpd = NULL;
-		list_for_each(p, &he_dev->outstanding_tpds) {
-			struct he_tpd *__tpd = list_entry(p, struct he_tpd, entry);
+		list_for_each_entry(__tpd, &he_dev->outstanding_tpds, entry) {
 			if (TPD_ADDR(__tpd->status) == TBRQ_TPD(he_dev->tbrq_head)) {
 				tpd = __tpd;
 				list_del(&__tpd->entry);
@@ -2595,9 +2595,8 @@ he_close(struct atm_vcc *vcc)
 
 		while (((tx_inuse = atomic_read(&vcc->sk->sk_wmem_alloc)) > 0) &&
 		       (retry < MAX_RETRY)) {
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			(void) schedule_timeout(sleep);
-			if (sleep < HZ)
+			msleep(sleep);
+			if (sleep < 250)
 				sleep = sleep * 2;
 
 			++retry;
diff --git a/drivers/atm/he.h b/drivers/atm/he.h
index 0a4adaf4b..7075ef4aa 100644
--- a/drivers/atm/he.h
+++ b/drivers/atm/he.h
@@ -265,7 +265,7 @@ struct he_cs_stper
 struct he_dev {
 	unsigned int number;
 	unsigned int irq;
-	unsigned long membase;
+	void __iomem *membase;
 
 	char prod_id[30];
 	char mac_addr[6];
diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
index b2bede540..3959cf83e 100644
--- a/drivers/atm/idt77252.c
+++ b/drivers/atm/idt77252.c
@@ -2516,7 +2516,7 @@ idt77252_close(struct atm_vcc *vcc)
 	struct vc_map *vc = vcc->dev_data;
 	unsigned long flags;
 	unsigned long addr;
-	int timeout;
+	unsigned long timeout;
 
 	down(&card->mutex);
 
@@ -2566,9 +2566,9 @@ done:
 		}
 		spin_unlock_irqrestore(&vc->lock, flags);
 
-		timeout = 5 * HZ;
+		timeout = 5 * 1000;
 		while (atomic_read(&vc->scq->used) > 0) {
-			timeout = schedule_timeout(timeout);
+			timeout = msleep_interruptible(timeout);
 			if (!timeout)
 				break;
 		}
@@ -3164,7 +3164,7 @@ deinit_card(struct idt77252_dev *card)
 
 	for (i = 0; i < 4; i++) {
 		if (card->fbq[i])
-			iounmap((void *) card->fbq[i]);
+			iounmap(card->fbq[i]);
 	}
 
 	if (card->membase)
@@ -3681,18 +3681,25 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
 	struct idt77252_dev *card;
 	struct atm_dev *dev;
 	ushort revision = 0;
-	int i;
+	int i, err;
+
 
+	if (pci_enable_device(pcidev)) {
+		printk("idt77252: can't enable PCI device at %s\n", pci_name(pcidev));
+		return -ENODEV;
+	}
 
 	if (pci_read_config_word(pcidev, PCI_REVISION_ID, &revision)) {
 		printk("idt77252-%d: can't read PCI_REVISION_ID\n", index);
-		return -ENODEV;
+		err = -ENODEV;
+		goto err_out_disable_pdev;
 	}
 
 	card = kmalloc(sizeof(struct idt77252_dev), GFP_KERNEL);
 	if (!card) {
 		printk("idt77252-%d: can't allocate private data\n", index);
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto err_out_disable_pdev;
 	}
 	memset(card, 0, sizeof(struct idt77252_dev));
 
@@ -3715,26 +3722,24 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
 	card->tst_timer.function = tst_timer;
 
 	/* Do the I/O remapping... */
-	card->membase = (unsigned long) ioremap(membase, 1024);
+	card->membase = ioremap(membase, 1024);
 	if (!card->membase) {
 		printk("%s: can't ioremap() membase\n", card->name);
-		kfree(card);
-		return -EIO;
+		err = -EIO;
+		goto err_out_free_card;
 	}
 
 	if (idt77252_preset(card)) {
 		printk("%s: preset failed\n", card->name);
-		iounmap((void *) card->membase);
-		kfree(card);
-		return -EIO;
+		err = -EIO;
+		goto err_out_iounmap;
 	}
 
 	dev = atm_dev_register("idt77252", &idt77252_ops, -1, NULL);
 	if (!dev) {
 		printk("%s: can't register atm device\n", card->name);
-		iounmap((void *) card->membase);
-		kfree(card);
-		return -EIO;
+		err = -EIO;
+		goto err_out_iounmap;
 	}
 	dev->dev_data = card;
 	card->atmdev = dev;
@@ -3743,22 +3748,19 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
 	suni_init(dev);
 	if (!dev->phy) {
 		printk("%s: can't init SUNI\n", card->name);
-		deinit_card(card);
-		kfree(card);
-		return -EIO;
+		err = -EIO;
+		goto err_out_deinit_card;
 	}
 #endif	/* CONFIG_ATM_IDT77252_USE_SUNI */
 
 	card->sramsize = probe_sram(card);
 
 	for (i = 0; i < 4; i++) {
-		card->fbq[i] = (unsigned long)
-			    ioremap(srambase | 0x200000 | (i << 18), 4);
+		card->fbq[i] = ioremap(srambase | 0x200000 | (i << 18), 4);
 		if (!card->fbq[i]) {
 			printk("%s: can't ioremap() FBQ%d\n", card->name, i);
-			deinit_card(card);
-			kfree(card);
-			return -EIO;
+			err = -EIO;
+			goto err_out_deinit_card;
 		}
 	}
 
@@ -3769,9 +3771,8 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
 
 	if (init_card(dev)) {
 		printk("%s: init_card failed\n", card->name);
-		deinit_card(card);
-		kfree(card);
-		return -EIO;
+		err = -EIO;
+		goto err_out_deinit_card;
 	}
 
 	dev->ci_range.vpi_bits = card->vpibits;
@@ -3783,12 +3784,8 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
 
 	if (idt77252_dev_open(card)) {
 		printk("%s: dev_open failed\n", card->name);
-
-		if (dev->phy->stop)
-			dev->phy->stop(dev);
-		deinit_card(card);
-		kfree(card);
-		return -EIO;
+		err = -EIO;
+		goto err_out_stop;
 	}
 
 	*last = card;
@@ -3796,6 +3793,23 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
 	index++;
 
 	return 0;
+
+err_out_stop:
+	if (dev->phy->stop)
+		dev->phy->stop(dev);
+
+err_out_deinit_card:
+	deinit_card(card);
+
+err_out_iounmap:
+	iounmap((void *) card->membase);
+
+err_out_free_card:
+	kfree(card);
+
+err_out_disable_pdev:
+	pci_disable_device(pcidev);
+	return err;
 }
 
 static struct pci_device_id idt77252_pci_tbl[] =
@@ -3848,6 +3862,7 @@ static void __exit idt77252_exit(void)
 		if (dev->phy->stop)
 			dev->phy->stop(dev);
 		deinit_card(card);
+		pci_disable_device(card->pcidev);
 		kfree(card);
 	}
 
diff --git a/drivers/atm/idt77252.h b/drivers/atm/idt77252.h
index 5a087c4e9..cfdd15e7d 100644
--- a/drivers/atm/idt77252.h
+++ b/drivers/atm/idt77252.h
@@ -355,9 +355,9 @@ struct idt77252_dev
 	struct pci_dev		*pcidev;	/* PCI handle (desriptor) */
 	struct atm_dev		*atmdev;	/* ATM device desriptor */
 
-	unsigned long		membase;	/* SAR's memory base address */
+	void __iomem		*membase;	/* SAR's memory base address */
 	unsigned long		srambase;	/* SAR's sram  base address */
-	unsigned long		fbq[4];		/* FBQ fill addresses */
+	void __iomem		*fbq[4];	/* FBQ fill addresses */
 
 	struct semaphore	mutex;
 	spinlock_t		cmd_lock;	/* for r/w utility/sram */
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c
index 53f6d29c5..e23d3f714 100644
--- a/drivers/atm/lanai.c
+++ b/drivers/atm/lanai.c
@@ -191,7 +191,7 @@
 #define LANAI_EEPROM_SIZE	(128)
 
 typedef int vci_t;
-typedef unsigned long bus_addr_t;
+typedef void __iomem *bus_addr_t;
 
 /* DMA buffer in host memory for TX, RX, or service list. */
 struct lanai_buffer {
@@ -471,7 +471,7 @@ enum lanai_register {
 static inline bus_addr_t reg_addr(const struct lanai_dev *lanai,
 	enum lanai_register reg)
 {
-	return lanai->base + (bus_addr_t) reg;
+	return lanai->base + reg;
 }
 
 static inline u32 reg_read(const struct lanai_dev *lanai,
@@ -651,7 +651,7 @@ static inline u32 cardvcc_read(const struct lanai_vcc *lvcc,
 {
 	u32 val;
 	APRINTK(lvcc->vbase != 0, "cardvcc_read: unbound vcc!\n");
-	val= readl(lvcc->vbase + (bus_addr_t) offset);
+	val= readl(lvcc->vbase + offset);
 	RWDEBUG("VR vci=%04d 0x%02X = 0x%08X\n",
 	    lvcc->vci, (int) offset, val);
 	return val;
@@ -666,7 +666,7 @@ static inline void cardvcc_write(const struct lanai_vcc *lvcc,
 	    (unsigned int) val, lvcc->vci, (unsigned int) offset);
 	RWDEBUG("VW vci=%04d 0x%02X > 0x%08X\n",
 	    lvcc->vci, (unsigned int) offset, (unsigned int) val);
-	writel(val, lvcc->vbase + (bus_addr_t) offset);
+	writel(val, lvcc->vbase + offset);
 }
 
 /* -------------------- COMPUTE SIZE OF AN AAL5 PDU: */
@@ -813,7 +813,7 @@ static void lanai_shutdown_tx_vci(struct lanai_dev *lanai,
 			DPRINTK("read, write = %d, %d\n", read, write);
 			break;
 		}
-		schedule_timeout(HZ / 25);
+		msleep(40);
 	}
 	/* 15.2.2 - clear out all tx registers */
 	cardvcc_write(lvcc, 0, vcc_txreadptr);
@@ -2177,7 +2177,7 @@ static int __init lanai_dev_open(struct atm_dev *atmdev)
 	/* 3.2: PCI initialization */
 	if ((result = lanai_pci_start(lanai)) != 0)
 		goto error;
-	raw_base = (bus_addr_t) lanai->pci->resource[0].start;
+	raw_base = lanai->pci->resource[0].start;
 	lanai->base = (bus_addr_t) ioremap(raw_base, LANAI_MAPPING_SIZE);
 	if (lanai->base == 0) {
 		printk(KERN_ERR DEV_LABEL ": couldn't remap I/O space\n");
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
index b63669c1f..3f18782bd 100644
--- a/drivers/atm/nicstar.c
+++ b/drivers/atm/nicstar.c
@@ -467,6 +467,7 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
    u32 u32d[4];
    u32 ns_cfg_rctsize;
    int bcount;
+   unsigned long membase;
 
    error = 0;
 
@@ -494,8 +495,8 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
    card->index = i;
    card->atmdev = NULL;
    card->pcidev = pcidev;
-   card->membase = pci_resource_start(pcidev, 1);
-   card->membase = (unsigned long) ioremap(card->membase, NS_IOREMAP_SIZE);
+   membase = pci_resource_start(pcidev, 1);
+   card->membase = ioremap(membase, NS_IOREMAP_SIZE);
    if (card->membase == 0)
    {
       printk("nicstar%d: can't ioremap() membase.\n",i);
diff --git a/drivers/atm/nicstar.h b/drivers/atm/nicstar.h
index f762abcf2..a7eaee736 100644
--- a/drivers/atm/nicstar.h
+++ b/drivers/atm/nicstar.h
@@ -763,7 +763,7 @@ typedef struct ns_dev
 {
    int index;				/* Card ID to the device driver */
    int sram_size;			/* In k x 32bit words. 32 or 128 */
-   unsigned long membase;			/* Card's memory base address */
+   void __iomem *membase;		/* Card's memory base address */
    unsigned long max_pcr;
    int rct_size;			/* Number of entries */
    int vpibits;
diff --git a/drivers/atm/nicstarmac.c b/drivers/atm/nicstarmac.c
index ef6b0c9f8..7a842ef71 100644
--- a/drivers/atm/nicstarmac.c
+++ b/drivers/atm/nicstarmac.c
@@ -162,7 +162,7 @@ nicstar_read_eprom_status( virt_addr_t base )
  */
  
 static u_int8_t 
-read_eprom_byte(u_int32_t base, u_int8_t offset)
+read_eprom_byte(virt_addr_t base, u_int8_t offset)
 {
    u_int32_t val = 0;
    int i,j=0;
diff --git a/drivers/atm/nicstarmac.h b/drivers/atm/nicstarmac.h
index 0592daee4..80beec52f 100644
--- a/drivers/atm/nicstarmac.h
+++ b/drivers/atm/nicstarmac.h
@@ -7,7 +7,7 @@
  ******************************************************************************/
 
 
-typedef unsigned int virt_addr_t;
+typedef void __iomem *virt_addr_t;
 
 u_int32_t nicstar_read_eprom_status( virt_addr_t base );
 void nicstar_init_eprom( virt_addr_t base );
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 2693bb545..70be97450 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -349,14 +349,19 @@ void class_device_initialize(struct class_device *class_dev)
 
 int class_device_add(struct class_device *class_dev)
 {
-	struct class * parent;
+	struct class * parent = NULL;
 	struct class_interface * class_intf;
 	int error;
 
 	class_dev = class_device_get(class_dev);
-	if (!class_dev || !strlen(class_dev->class_id))
+	if (!class_dev)
 		return -EINVAL;
 
+	if (!strlen(class_dev->class_id)) {
+		error = -EINVAL;
+		goto register_done;
+	}
+
 	parent = class_get(class_dev->class);
 
 	pr_debug("CLASS: registering class device: ID = '%s'\n",
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index a57ba84eb..6e17867db 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -12,7 +12,7 @@
 #include <linux/init.h>
 #include <linux/timer.h>
 #include <linux/vmalloc.h>
-#include <asm/hardirq.h>
+#include <linux/interrupt.h>
 #include <linux/bitops.h>
 #include <asm/semaphore.h>
 
@@ -235,6 +235,8 @@ firmware_data_write(struct kobject *kobj,
 	struct firmware *fw;
 	ssize_t retval;
 
+	if (!capable(CAP_SYS_RAWIO))
+		return -EPERM;
 	down(&fw_lock);
 	fw = fw_priv->fw;
 	if (test_bit(FW_STATUS_DONE, &fw_priv->status)) {
diff --git a/drivers/base/node.c b/drivers/base/node.c
index c1187363f..df74785ef 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -19,7 +19,7 @@ static struct sysdev_class node_class = {
 static ssize_t node_read_cpumap(struct sys_device * dev, char * buf)
 {
 	struct node *node_dev = to_node(dev);
-	cpumask_t mask = node_dev->cpumap;
+	cpumask_t mask = node_to_cpumask(node_dev->sysdev.id);
 	int len;
 
 	/* 2004/06/03: buf currently PAGE_SIZE, need > 1 char per 4 bits. */
@@ -38,11 +38,19 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
 	int n;
 	int nid = dev->id;
 	struct sysinfo i;
+	unsigned long inactive;
+	unsigned long active;
+	unsigned long free;
+
 	si_meminfo_node(&i, nid);
+	__get_zone_counts(&active, &inactive, &free, NODE_DATA(nid));
+
 	n = sprintf(buf, "\n"
 		       "Node %d MemTotal:     %8lu kB\n"
 		       "Node %d MemFree:      %8lu kB\n"
 		       "Node %d MemUsed:      %8lu kB\n"
+		       "Node %d Active:       %8lu kB\n"
+		       "Node %d Inactive:     %8lu kB\n"
 		       "Node %d HighTotal:    %8lu kB\n"
 		       "Node %d HighFree:     %8lu kB\n"
 		       "Node %d LowTotal:     %8lu kB\n"
@@ -50,6 +58,8 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
 		       nid, K(i.totalram),
 		       nid, K(i.freeram),
 		       nid, K(i.totalram - i.freeram),
+		       nid, K(active),
+		       nid, K(inactive),
 		       nid, K(i.totalhigh),
 		       nid, K(i.freehigh),
 		       nid, K(i.totalram - i.totalhigh),
@@ -111,7 +121,6 @@ int __init register_node(struct node *node, int num, struct node *parent)
 {
 	int error;
 
-	node->cpumap = node_to_cpumask(num);
 	node->sysdev.id = num;
 	node->sysdev.cls = &node_class;
 	error = sysdev_register(&node->sysdev);
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 56b9ce97c..48c3e6399 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -288,12 +288,17 @@ static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller)
 		Controller->PCIDevice,
 	DAC960_V2_ScatterGatherLimit * sizeof(DAC960_V2_ScatterGatherSegment_T),
 	sizeof(DAC960_V2_ScatterGatherSegment_T), 0);
+      if (ScatterGatherPool == NULL)
+	    return DAC960_Failure(Controller,
+			"AUXILIARY STRUCTURE CREATION (SG)");
       RequestSensePool = pci_pool_create("DAC960_V2_RequestSense",
 		Controller->PCIDevice, sizeof(DAC960_SCSI_RequestSense_T),
 		sizeof(int), 0);
-      if (ScatterGatherPool == NULL || RequestSensePool == NULL)
+      if (RequestSensePool == NULL) {
+	    pci_pool_destroy(ScatterGatherPool);
 	    return DAC960_Failure(Controller,
 			"AUXILIARY STRUCTURE CREATION (SG)");
+      }
       Controller->ScatterGatherPool = ScatterGatherPool;
       Controller->V2.RequestSensePool = RequestSensePool;
     }
@@ -535,7 +540,7 @@ static void DAC960_WaitForCommand(DAC960_Controller_T *Controller)
 static void DAC960_BA_QueueCommand(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
   DAC960_V2_CommandMailbox_T *NextCommandMailbox =
     Controller->V2.NextCommandMailbox;
@@ -560,7 +565,7 @@ static void DAC960_BA_QueueCommand(DAC960_Command_T *Command)
 static void DAC960_LP_QueueCommand(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
   DAC960_V2_CommandMailbox_T *NextCommandMailbox =
     Controller->V2.NextCommandMailbox;
@@ -586,7 +591,7 @@ static void DAC960_LP_QueueCommand(DAC960_Command_T *Command)
 static void DAC960_LA_QueueCommandDualMode(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
   DAC960_V1_CommandMailbox_T *NextCommandMailbox =
     Controller->V1.NextCommandMailbox;
@@ -612,7 +617,7 @@ static void DAC960_LA_QueueCommandDualMode(DAC960_Command_T *Command)
 static void DAC960_LA_QueueCommandSingleMode(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
   DAC960_V1_CommandMailbox_T *NextCommandMailbox =
     Controller->V1.NextCommandMailbox;
@@ -638,7 +643,7 @@ static void DAC960_LA_QueueCommandSingleMode(DAC960_Command_T *Command)
 static void DAC960_PG_QueueCommandDualMode(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
   DAC960_V1_CommandMailbox_T *NextCommandMailbox =
     Controller->V1.NextCommandMailbox;
@@ -664,7 +669,7 @@ static void DAC960_PG_QueueCommandDualMode(DAC960_Command_T *Command)
 static void DAC960_PG_QueueCommandSingleMode(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
   DAC960_V1_CommandMailbox_T *NextCommandMailbox =
     Controller->V1.NextCommandMailbox;
@@ -689,7 +694,7 @@ static void DAC960_PG_QueueCommandSingleMode(DAC960_Command_T *Command)
 static void DAC960_PD_QueueCommand(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
   CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier;
   while (DAC960_PD_MailboxFullP(ControllerBaseAddress))
@@ -706,7 +711,7 @@ static void DAC960_PD_QueueCommand(DAC960_Command_T *Command)
 static void DAC960_P_QueueCommand(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
   CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier;
   switch (CommandMailbox->Common.CommandOpcode)
@@ -1127,7 +1132,7 @@ static boolean DAC960_V2_DeviceOperation(DAC960_Controller_T *Controller,
 static boolean DAC960_V1_EnableMemoryMailboxInterface(DAC960_Controller_T
 						      *Controller)
 {
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_HardwareType_T hw_type = Controller->HardwareType;
   struct pci_dev *PCI_Device = Controller->PCIDevice;
   struct dma_loaf *DmaPages = &Controller->DmaPages;
@@ -1333,7 +1338,7 @@ skip_mailboxes:
 static boolean DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T
 						      *Controller)
 {
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   struct pci_dev *PCI_Device = Controller->PCIDevice;
   struct dma_loaf *DmaPages = &Controller->DmaPages;
   size_t DmaPagesSize;
@@ -2674,7 +2679,7 @@ DAC960_DetectController(struct pci_dev *PCI_Device,
   unsigned char DeviceFunction = PCI_Device->devfn;
   unsigned char ErrorStatus, Parameter0, Parameter1;
   unsigned int IRQ_Channel = PCI_Device->irq;
-  void *BaseAddress;
+  void __iomem *BaseAddress;
   int i;
 
   Controller = (DAC960_Controller_T *)
@@ -5196,7 +5201,7 @@ static irqreturn_t DAC960_BA_InterruptHandler(int IRQ_Channel,
 				       struct pt_regs *InterruptRegisters)
 {
   DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V2_StatusMailbox_T *NextStatusMailbox;
   unsigned long flags;
 
@@ -5239,7 +5244,7 @@ static irqreturn_t DAC960_LP_InterruptHandler(int IRQ_Channel,
 				       struct pt_regs *InterruptRegisters)
 {
   DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V2_StatusMailbox_T *NextStatusMailbox;
   unsigned long flags;
 
@@ -5282,7 +5287,7 @@ static irqreturn_t DAC960_LA_InterruptHandler(int IRQ_Channel,
 				       struct pt_regs *InterruptRegisters)
 {
   DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_StatusMailbox_T *NextStatusMailbox;
   unsigned long flags;
 
@@ -5321,7 +5326,7 @@ static irqreturn_t DAC960_PG_InterruptHandler(int IRQ_Channel,
 				       struct pt_regs *InterruptRegisters)
 {
   DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_StatusMailbox_T *NextStatusMailbox;
   unsigned long flags;
 
@@ -5360,7 +5365,7 @@ static irqreturn_t DAC960_PD_InterruptHandler(int IRQ_Channel,
 				       struct pt_regs *InterruptRegisters)
 {
   DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   unsigned long flags;
 
   spin_lock_irqsave(&Controller->queue_lock, flags);
@@ -5399,7 +5404,7 @@ static irqreturn_t DAC960_P_InterruptHandler(int IRQ_Channel,
 				      struct pt_regs *InterruptRegisters)
 {
   DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   unsigned long flags;
 
   spin_lock_irqsave(&Controller->queue_lock, flags);
diff --git a/drivers/block/DAC960.h b/drivers/block/DAC960.h
index be8f8992a..d5e8e7190 100644
--- a/drivers/block/DAC960.h
+++ b/drivers/block/DAC960.h
@@ -2282,8 +2282,8 @@ DAC960_Command_T;
 
 typedef struct DAC960_Controller
 {
-  void *BaseAddress;
-  void *MemoryMappedAddress;
+  void __iomem *BaseAddress;
+  void __iomem *MemoryMappedAddress;
   DAC960_FirmwareType_T FirmwareType;
   DAC960_HardwareType_T HardwareType;
   DAC960_IO_Address_T IO_Address;
@@ -2527,7 +2527,7 @@ DAC960_Controller_T;
  * dma_addr_t.
  */
 static inline
-void dma_addr_writeql(dma_addr_t addr, void *write_address)
+void dma_addr_writeql(dma_addr_t addr, void __iomem *write_address)
 {
 	union {
 		u64 wq;
@@ -2643,7 +2643,7 @@ DAC960_BA_ErrorStatusRegister_T;
 */
 
 static inline
-void DAC960_BA_HardwareMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_BA_HardwareMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2653,7 +2653,7 @@ void DAC960_BA_HardwareMailboxNewCommand(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_BA_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
+void DAC960_BA_AcknowledgeHardwareMailboxStatus(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2663,7 +2663,7 @@ void DAC960_BA_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_BA_GenerateInterrupt(void *ControllerBaseAddress)
+void DAC960_BA_GenerateInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2673,7 +2673,7 @@ void DAC960_BA_GenerateInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_BA_ControllerReset(void *ControllerBaseAddress)
+void DAC960_BA_ControllerReset(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2683,7 +2683,7 @@ void DAC960_BA_ControllerReset(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_BA_MemoryMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_BA_MemoryMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2693,7 +2693,7 @@ void DAC960_BA_MemoryMailboxNewCommand(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_BA_HardwareMailboxFullP(void *ControllerBaseAddress)
+boolean DAC960_BA_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -2702,7 +2702,7 @@ boolean DAC960_BA_HardwareMailboxFullP(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_BA_InitializationInProgressP(void *ControllerBaseAddress)
+boolean DAC960_BA_InitializationInProgressP(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -2711,7 +2711,7 @@ boolean DAC960_BA_InitializationInProgressP(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_BA_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_BA_AcknowledgeHardwareMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -2721,7 +2721,7 @@ void DAC960_BA_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_BA_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_BA_AcknowledgeMemoryMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -2731,7 +2731,7 @@ void DAC960_BA_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_BA_AcknowledgeInterrupt(void *ControllerBaseAddress)
+void DAC960_BA_AcknowledgeInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -2742,7 +2742,7 @@ void DAC960_BA_AcknowledgeInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_BA_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_BA_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -2751,7 +2751,7 @@ boolean DAC960_BA_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_BA_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_BA_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -2760,7 +2760,7 @@ boolean DAC960_BA_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_BA_EnableInterrupts(void *ControllerBaseAddress)
+void DAC960_BA_EnableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0xFF;
@@ -2771,7 +2771,7 @@ void DAC960_BA_EnableInterrupts(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_BA_DisableInterrupts(void *ControllerBaseAddress)
+void DAC960_BA_DisableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0xFF;
@@ -2782,7 +2782,7 @@ void DAC960_BA_DisableInterrupts(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_BA_InterruptsEnabledP(void *ControllerBaseAddress)
+boolean DAC960_BA_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
 {
   DAC960_BA_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All =
@@ -2805,7 +2805,7 @@ void DAC960_BA_WriteCommandMailbox(DAC960_V2_CommandMailbox_T
 
 
 static inline
-void DAC960_BA_WriteHardwareMailbox(void *ControllerBaseAddress,
+void DAC960_BA_WriteHardwareMailbox(void __iomem *ControllerBaseAddress,
 				    dma_addr_t CommandMailboxDMA)
 {
 	dma_addr_writeql(CommandMailboxDMA,
@@ -2814,19 +2814,19 @@ void DAC960_BA_WriteHardwareMailbox(void *ControllerBaseAddress,
 }
 
 static inline DAC960_V2_CommandIdentifier_T
-DAC960_BA_ReadCommandIdentifier(void *ControllerBaseAddress)
+DAC960_BA_ReadCommandIdentifier(void __iomem *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_BA_CommandStatusOffset);
 }
 
 static inline DAC960_V2_CommandStatus_T
-DAC960_BA_ReadCommandStatus(void *ControllerBaseAddress)
+DAC960_BA_ReadCommandStatus(void __iomem *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_BA_CommandStatusOffset + 2);
 }
 
 static inline boolean
-DAC960_BA_ReadErrorStatus(void *ControllerBaseAddress,
+DAC960_BA_ReadErrorStatus(void __iomem *ControllerBaseAddress,
 			  unsigned char *ErrorStatus,
 			  unsigned char *Parameter0,
 			  unsigned char *Parameter1)
@@ -2948,7 +2948,7 @@ DAC960_LP_ErrorStatusRegister_T;
 */
 
 static inline
-void DAC960_LP_HardwareMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_LP_HardwareMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2958,7 +2958,7 @@ void DAC960_LP_HardwareMailboxNewCommand(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LP_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
+void DAC960_LP_AcknowledgeHardwareMailboxStatus(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2968,7 +2968,7 @@ void DAC960_LP_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LP_GenerateInterrupt(void *ControllerBaseAddress)
+void DAC960_LP_GenerateInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2978,7 +2978,7 @@ void DAC960_LP_GenerateInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LP_ControllerReset(void *ControllerBaseAddress)
+void DAC960_LP_ControllerReset(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2988,7 +2988,7 @@ void DAC960_LP_ControllerReset(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LP_MemoryMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_LP_MemoryMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -2998,7 +2998,7 @@ void DAC960_LP_MemoryMailboxNewCommand(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_LP_HardwareMailboxFullP(void *ControllerBaseAddress)
+boolean DAC960_LP_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3007,7 +3007,7 @@ boolean DAC960_LP_HardwareMailboxFullP(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_LP_InitializationInProgressP(void *ControllerBaseAddress)
+boolean DAC960_LP_InitializationInProgressP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3016,7 +3016,7 @@ boolean DAC960_LP_InitializationInProgressP(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LP_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_LP_AcknowledgeHardwareMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3026,7 +3026,7 @@ void DAC960_LP_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LP_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_LP_AcknowledgeMemoryMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3036,7 +3036,7 @@ void DAC960_LP_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LP_AcknowledgeInterrupt(void *ControllerBaseAddress)
+void DAC960_LP_AcknowledgeInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3047,7 +3047,7 @@ void DAC960_LP_AcknowledgeInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_LP_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_LP_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3056,7 +3056,7 @@ boolean DAC960_LP_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_LP_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_LP_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3065,7 +3065,7 @@ boolean DAC960_LP_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LP_EnableInterrupts(void *ControllerBaseAddress)
+void DAC960_LP_EnableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0xFF;
@@ -3075,7 +3075,7 @@ void DAC960_LP_EnableInterrupts(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LP_DisableInterrupts(void *ControllerBaseAddress)
+void DAC960_LP_DisableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0xFF;
@@ -3085,7 +3085,7 @@ void DAC960_LP_DisableInterrupts(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_LP_InterruptsEnabledP(void *ControllerBaseAddress)
+boolean DAC960_LP_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LP_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All =
@@ -3107,7 +3107,7 @@ void DAC960_LP_WriteCommandMailbox(DAC960_V2_CommandMailbox_T
 }
 
 static inline
-void DAC960_LP_WriteHardwareMailbox(void *ControllerBaseAddress,
+void DAC960_LP_WriteHardwareMailbox(void __iomem *ControllerBaseAddress,
 				    dma_addr_t CommandMailboxDMA)
 {
 	dma_addr_writeql(CommandMailboxDMA,
@@ -3116,19 +3116,19 @@ void DAC960_LP_WriteHardwareMailbox(void *ControllerBaseAddress,
 }
 
 static inline DAC960_V2_CommandIdentifier_T
-DAC960_LP_ReadCommandIdentifier(void *ControllerBaseAddress)
+DAC960_LP_ReadCommandIdentifier(void __iomem *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_LP_CommandStatusOffset);
 }
 
 static inline DAC960_V2_CommandStatus_T
-DAC960_LP_ReadCommandStatus(void *ControllerBaseAddress)
+DAC960_LP_ReadCommandStatus(void __iomem *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_LP_CommandStatusOffset + 2);
 }
 
 static inline boolean
-DAC960_LP_ReadErrorStatus(void *ControllerBaseAddress,
+DAC960_LP_ReadErrorStatus(void __iomem *ControllerBaseAddress,
 			  unsigned char *ErrorStatus,
 			  unsigned char *Parameter0,
 			  unsigned char *Parameter1)
@@ -3262,7 +3262,7 @@ DAC960_LA_ErrorStatusRegister_T;
 */
 
 static inline
-void DAC960_LA_HardwareMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_LA_HardwareMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3272,7 +3272,7 @@ void DAC960_LA_HardwareMailboxNewCommand(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LA_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
+void DAC960_LA_AcknowledgeHardwareMailboxStatus(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3282,7 +3282,7 @@ void DAC960_LA_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LA_GenerateInterrupt(void *ControllerBaseAddress)
+void DAC960_LA_GenerateInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3292,7 +3292,7 @@ void DAC960_LA_GenerateInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LA_ControllerReset(void *ControllerBaseAddress)
+void DAC960_LA_ControllerReset(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3302,7 +3302,7 @@ void DAC960_LA_ControllerReset(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LA_MemoryMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_LA_MemoryMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3312,7 +3312,7 @@ void DAC960_LA_MemoryMailboxNewCommand(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_LA_HardwareMailboxFullP(void *ControllerBaseAddress)
+boolean DAC960_LA_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3321,7 +3321,7 @@ boolean DAC960_LA_HardwareMailboxFullP(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_LA_InitializationInProgressP(void *ControllerBaseAddress)
+boolean DAC960_LA_InitializationInProgressP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3330,7 +3330,7 @@ boolean DAC960_LA_InitializationInProgressP(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LA_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_LA_AcknowledgeHardwareMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3340,7 +3340,7 @@ void DAC960_LA_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LA_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_LA_AcknowledgeMemoryMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3350,7 +3350,7 @@ void DAC960_LA_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LA_AcknowledgeInterrupt(void *ControllerBaseAddress)
+void DAC960_LA_AcknowledgeInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3361,7 +3361,7 @@ void DAC960_LA_AcknowledgeInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_LA_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_LA_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3370,7 +3370,7 @@ boolean DAC960_LA_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_LA_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_LA_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3379,7 +3379,7 @@ boolean DAC960_LA_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LA_EnableInterrupts(void *ControllerBaseAddress)
+void DAC960_LA_EnableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0xFF;
@@ -3389,7 +3389,7 @@ void DAC960_LA_EnableInterrupts(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_LA_DisableInterrupts(void *ControllerBaseAddress)
+void DAC960_LA_DisableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0xFF;
@@ -3399,7 +3399,7 @@ void DAC960_LA_DisableInterrupts(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_LA_InterruptsEnabledP(void *ControllerBaseAddress)
+boolean DAC960_LA_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
 {
   DAC960_LA_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All =
@@ -3422,7 +3422,7 @@ void DAC960_LA_WriteCommandMailbox(DAC960_V1_CommandMailbox_T
 }
 
 static inline
-void DAC960_LA_WriteHardwareMailbox(void *ControllerBaseAddress,
+void DAC960_LA_WriteHardwareMailbox(void __iomem *ControllerBaseAddress,
 				    DAC960_V1_CommandMailbox_T *CommandMailbox)
 {
   writel(CommandMailbox->Words[0],
@@ -3436,20 +3436,20 @@ void DAC960_LA_WriteHardwareMailbox(void *ControllerBaseAddress,
 }
 
 static inline DAC960_V1_CommandIdentifier_T
-DAC960_LA_ReadStatusCommandIdentifier(void *ControllerBaseAddress)
+DAC960_LA_ReadStatusCommandIdentifier(void __iomem *ControllerBaseAddress)
 {
   return readb(ControllerBaseAddress
 	       + DAC960_LA_StatusCommandIdentifierRegOffset);
 }
 
 static inline DAC960_V1_CommandStatus_T
-DAC960_LA_ReadStatusRegister(void *ControllerBaseAddress)
+DAC960_LA_ReadStatusRegister(void __iomem *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_LA_StatusRegisterOffset);
 }
 
 static inline boolean
-DAC960_LA_ReadErrorStatus(void *ControllerBaseAddress,
+DAC960_LA_ReadErrorStatus(void __iomem *ControllerBaseAddress,
 			  unsigned char *ErrorStatus,
 			  unsigned char *Parameter0,
 			  unsigned char *Parameter1)
@@ -3583,7 +3583,7 @@ DAC960_PG_ErrorStatusRegister_T;
 */
 
 static inline
-void DAC960_PG_HardwareMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_PG_HardwareMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3593,7 +3593,7 @@ void DAC960_PG_HardwareMailboxNewCommand(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PG_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
+void DAC960_PG_AcknowledgeHardwareMailboxStatus(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3603,7 +3603,7 @@ void DAC960_PG_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PG_GenerateInterrupt(void *ControllerBaseAddress)
+void DAC960_PG_GenerateInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3613,7 +3613,7 @@ void DAC960_PG_GenerateInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PG_ControllerReset(void *ControllerBaseAddress)
+void DAC960_PG_ControllerReset(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3623,7 +3623,7 @@ void DAC960_PG_ControllerReset(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PG_MemoryMailboxNewCommand(void *ControllerBaseAddress)
+void DAC960_PG_MemoryMailboxNewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3633,7 +3633,7 @@ void DAC960_PG_MemoryMailboxNewCommand(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_PG_HardwareMailboxFullP(void *ControllerBaseAddress)
+boolean DAC960_PG_HardwareMailboxFullP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3642,7 +3642,7 @@ boolean DAC960_PG_HardwareMailboxFullP(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_PG_InitializationInProgressP(void *ControllerBaseAddress)
+boolean DAC960_PG_InitializationInProgressP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3651,7 +3651,7 @@ boolean DAC960_PG_InitializationInProgressP(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PG_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_PG_AcknowledgeHardwareMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3661,7 +3661,7 @@ void DAC960_PG_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PG_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
+void DAC960_PG_AcknowledgeMemoryMailboxInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3671,7 +3671,7 @@ void DAC960_PG_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PG_AcknowledgeInterrupt(void *ControllerBaseAddress)
+void DAC960_PG_AcknowledgeInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3682,7 +3682,7 @@ void DAC960_PG_AcknowledgeInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_PG_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_PG_HardwareMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3691,7 +3691,7 @@ boolean DAC960_PG_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_PG_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_PG_MemoryMailboxStatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3700,7 +3700,7 @@ boolean DAC960_PG_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PG_EnableInterrupts(void *ControllerBaseAddress)
+void DAC960_PG_EnableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0;
@@ -3712,7 +3712,7 @@ void DAC960_PG_EnableInterrupts(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PG_DisableInterrupts(void *ControllerBaseAddress)
+void DAC960_PG_DisableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All = 0;
@@ -3724,7 +3724,7 @@ void DAC960_PG_DisableInterrupts(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_PG_InterruptsEnabledP(void *ControllerBaseAddress)
+boolean DAC960_PG_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PG_InterruptMaskRegister_T InterruptMaskRegister;
   InterruptMaskRegister.All =
@@ -3747,7 +3747,7 @@ void DAC960_PG_WriteCommandMailbox(DAC960_V1_CommandMailbox_T
 }
 
 static inline
-void DAC960_PG_WriteHardwareMailbox(void *ControllerBaseAddress,
+void DAC960_PG_WriteHardwareMailbox(void __iomem *ControllerBaseAddress,
 				    DAC960_V1_CommandMailbox_T *CommandMailbox)
 {
   writel(CommandMailbox->Words[0],
@@ -3761,20 +3761,20 @@ void DAC960_PG_WriteHardwareMailbox(void *ControllerBaseAddress,
 }
 
 static inline DAC960_V1_CommandIdentifier_T
-DAC960_PG_ReadStatusCommandIdentifier(void *ControllerBaseAddress)
+DAC960_PG_ReadStatusCommandIdentifier(void __iomem *ControllerBaseAddress)
 {
   return readb(ControllerBaseAddress
 	       + DAC960_PG_StatusCommandIdentifierRegOffset);
 }
 
 static inline DAC960_V1_CommandStatus_T
-DAC960_PG_ReadStatusRegister(void *ControllerBaseAddress)
+DAC960_PG_ReadStatusRegister(void __iomem *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_PG_StatusRegisterOffset);
 }
 
 static inline boolean
-DAC960_PG_ReadErrorStatus(void *ControllerBaseAddress,
+DAC960_PG_ReadErrorStatus(void __iomem *ControllerBaseAddress,
 			  unsigned char *ErrorStatus,
 			  unsigned char *Parameter0,
 			  unsigned char *Parameter1)
@@ -3903,7 +3903,7 @@ DAC960_PD_ErrorStatusRegister_T;
 */
 
 static inline
-void DAC960_PD_NewCommand(void *ControllerBaseAddress)
+void DAC960_PD_NewCommand(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3913,7 +3913,7 @@ void DAC960_PD_NewCommand(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PD_AcknowledgeStatus(void *ControllerBaseAddress)
+void DAC960_PD_AcknowledgeStatus(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3923,7 +3923,7 @@ void DAC960_PD_AcknowledgeStatus(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PD_GenerateInterrupt(void *ControllerBaseAddress)
+void DAC960_PD_GenerateInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3933,7 +3933,7 @@ void DAC960_PD_GenerateInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PD_ControllerReset(void *ControllerBaseAddress)
+void DAC960_PD_ControllerReset(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All = 0;
@@ -3943,7 +3943,7 @@ void DAC960_PD_ControllerReset(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_PD_MailboxFullP(void *ControllerBaseAddress)
+boolean DAC960_PD_MailboxFullP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3952,7 +3952,7 @@ boolean DAC960_PD_MailboxFullP(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_PD_InitializationInProgressP(void *ControllerBaseAddress)
+boolean DAC960_PD_InitializationInProgressP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
@@ -3961,7 +3961,7 @@ boolean DAC960_PD_InitializationInProgressP(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PD_AcknowledgeInterrupt(void *ControllerBaseAddress)
+void DAC960_PD_AcknowledgeInterrupt(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All = 0;
@@ -3971,7 +3971,7 @@ void DAC960_PD_AcknowledgeInterrupt(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_PD_StatusAvailableP(void *ControllerBaseAddress)
+boolean DAC960_PD_StatusAvailableP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_OutboundDoorBellRegister_T OutboundDoorBellRegister;
   OutboundDoorBellRegister.All =
@@ -3980,7 +3980,7 @@ boolean DAC960_PD_StatusAvailableP(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PD_EnableInterrupts(void *ControllerBaseAddress)
+void DAC960_PD_EnableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InterruptEnableRegister_T InterruptEnableRegister;
   InterruptEnableRegister.All = 0;
@@ -3990,7 +3990,7 @@ void DAC960_PD_EnableInterrupts(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PD_DisableInterrupts(void *ControllerBaseAddress)
+void DAC960_PD_DisableInterrupts(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InterruptEnableRegister_T InterruptEnableRegister;
   InterruptEnableRegister.All = 0;
@@ -4000,7 +4000,7 @@ void DAC960_PD_DisableInterrupts(void *ControllerBaseAddress)
 }
 
 static inline
-boolean DAC960_PD_InterruptsEnabledP(void *ControllerBaseAddress)
+boolean DAC960_PD_InterruptsEnabledP(void __iomem *ControllerBaseAddress)
 {
   DAC960_PD_InterruptEnableRegister_T InterruptEnableRegister;
   InterruptEnableRegister.All =
@@ -4009,7 +4009,7 @@ boolean DAC960_PD_InterruptsEnabledP(void *ControllerBaseAddress)
 }
 
 static inline
-void DAC960_PD_WriteCommandMailbox(void *ControllerBaseAddress,
+void DAC960_PD_WriteCommandMailbox(void __iomem *ControllerBaseAddress,
 				   DAC960_V1_CommandMailbox_T *CommandMailbox)
 {
   writel(CommandMailbox->Words[0],
@@ -4023,20 +4023,20 @@ void DAC960_PD_WriteCommandMailbox(void *ControllerBaseAddress,
 }
 
 static inline DAC960_V1_CommandIdentifier_T
-DAC960_PD_ReadStatusCommandIdentifier(void *ControllerBaseAddress)
+DAC960_PD_ReadStatusCommandIdentifier(void __iomem *ControllerBaseAddress)
 {
   return readb(ControllerBaseAddress
 	       + DAC960_PD_StatusCommandIdentifierRegOffset);
 }
 
 static inline DAC960_V1_CommandStatus_T
-DAC960_PD_ReadStatusRegister(void *ControllerBaseAddress)
+DAC960_PD_ReadStatusRegister(void __iomem *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_PD_StatusRegisterOffset);
 }
 
 static inline boolean
-DAC960_PD_ReadErrorStatus(void *ControllerBaseAddress,
+DAC960_PD_ReadErrorStatus(void __iomem *ControllerBaseAddress,
 			  unsigned char *ErrorStatus,
 			  unsigned char *Parameter0,
 			  unsigned char *Parameter1)
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index c44f27f24..a1d50242b 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -166,7 +166,7 @@ config BLK_CPQ_CISS_DA
 
 config CISS_SCSI_TAPE
 	bool "SCSI tape drive support for Smart Array 5xxx"
-	depends on BLK_CPQ_CISS_DA && SCSI
+	depends on BLK_CPQ_CISS_DA && SCSI && PROC_FS
 	help
 	  When enabled (Y), this option allows SCSI tape drives and SCSI medium
 	  changers (tape robots) to be accessed via a Compaq 5xxx array 
@@ -301,6 +301,15 @@ config BLK_DEV_SX8
 
 	  Use devices /dev/sx8/$N and /dev/sx8/$Np$M.
 
+config BLK_DEV_UB
+	tristate "Low Performance USB Block driver"
+	depends on USB
+	help
+	  This driver supports certain USB attached storage devices
+	  such as flash keys.
+
+	  If unsure, say N.
+
 config BLK_DEV_RAM
 	tristate "RAM disk support"
 	---help---
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 2654b5b76..c8fbbf14c 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -42,4 +42,5 @@ obj-$(CONFIG_BLK_DEV_CRYPTOLOOP) += cryptoloop.o
 
 obj-$(CONFIG_VIODASD)		+= viodasd.o
 obj-$(CONFIG_BLK_DEV_SX8)	+= sx8.o
+obj-$(CONFIG_BLK_DEV_UB)	+= ub.o
 
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 42c1e5663..62e3a7ed3 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -386,16 +386,6 @@ static void fd_motor_off(unsigned long drive)
 	fd_select(drive);
 	udelay (1);
 	fd_deselect(drive);
-
-#ifdef MODULE
-/*
-  this is the last interrupt for any drive access, happens after
-  release (from floppy_off). So we have to wait until now to decrease
-  the use count.
-*/
-	if (decusecount)
-		MOD_DEC_USE_COUNT;
-#endif
 }
 
 static void floppy_off (unsigned int nr)
@@ -1590,10 +1580,6 @@ static int floppy_open(struct inode *inode, struct file *filp)
 	local_irq_save(flags);
 	fd_ref[drive]++;
 	fd_device[drive] = system;
-#ifdef MODULE
-	if (unit[drive].motor == 0)
-		MOD_INC_USE_COUNT;
-#endif
 	local_irq_restore(flags);
 
 	unit[drive].dtype=&data_types[system];
@@ -1839,6 +1825,7 @@ int init_module(void)
 	return amiga_floppy_init();
 }
 
+#if 0 /* not safe to unload */
 void cleanup_module(void)
 {
 	int i;
@@ -1860,3 +1847,4 @@ void cleanup_module(void)
 	unregister_blkdev(FLOPPY_MAJOR, "fd");
 }
 #endif
+#endif
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 5509e5620..ccdcfa13b 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -46,14 +46,14 @@
 #include <linux/completion.h>
 
 #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
-#define DRIVER_NAME "Compaq CISS Driver (v 2.6.2)"
+#define DRIVER_NAME "HP CISS Driver (v 2.6.2)"
 #define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,2)
 
 /* Embedded module documentation macros - see modules.h */
 MODULE_AUTHOR("Hewlett-Packard Company");
 MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.2");
 MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400"
-			" SA6i");
+			" SA6i V100");
 MODULE_LICENSE("GPL");
 
 #include "cciss_cmd.h"
@@ -82,7 +82,7 @@ const struct pci_device_id cciss_pci_device_id[] = {
 		0x0E11, 0x4091, 0, 0, 0},
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC,
 		0x0E11, 0x409E, 0, 0, 0},
-	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC,
+	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISS,
 		0x103C, 0x3211, 0, 0, 0},
 	{0,}
 };
@@ -115,7 +115,7 @@ static struct board_type products[] = {
 /*define how many times we will try a command because of bus resets */
 #define MAX_CMD_RETRIES 3
 
-#define READ_AHEAD 	 256
+#define READ_AHEAD 	 1024
 #define NR_CMDS		 384 /* #commands that can be outstanding */
 #define MAX_CTLR 8
 
@@ -192,10 +192,10 @@ static inline CommandList_struct *removeQ(CommandList_struct **Qptr,
 /*
  * Report information about this controller.
  */
-#define ENG_GIG 1048576000
+#define ENG_GIG 1000000000
 #define ENG_GIG_FACTOR (ENG_GIG/512)
 #define RAID_UNKNOWN 6
-static const char *raid_label[] = {"0","4","1(0+1)","5","5+1","ADG",
+static const char *raid_label[] = {"0","4","1(1+0)","5","5+1","ADG",
 	                                   "UNKNOWN"};
 
 static struct proc_dir_entry *proc_cciss;
@@ -209,7 +209,7 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
         ctlr_info_t *h = (ctlr_info_t*)data;
         drive_info_struct *drv;
 	unsigned long flags;
-	unsigned int vol_sz, vol_sz_frac;
+        sector_t vol_sz, vol_sz_frac;
 
         ctlr = h->ctlr;
 
@@ -246,32 +246,21 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
         pos += size; len += size;
 	cciss_proc_tape_report(ctlr, buffer, &pos, &len);
 	for(i=0; i<=h->highest_lun; i++) {
-		sector_t tmp;
 
                 drv = &h->drv[i];
 		if (drv->block_size == 0)
 			continue;
-		vol_sz = drv->nr_blocks;
-		sector_div(vol_sz, ENG_GIG_FACTOR);
-
-		/*
-		 * Awkwardly do this:
-		 * vol_sz_frac =
-		 *     (drv->nr_blocks%ENG_GIG_FACTOR)*100/ENG_GIG_FACTOR;
-		 */
-		tmp = drv->nr_blocks;
-		vol_sz_frac = sector_div(tmp, ENG_GIG_FACTOR);
-
-		/* Now, vol_sz_frac = (drv->nr_blocks%ENG_GIG_FACTOR) */
 
+		vol_sz = drv->nr_blocks;
+		vol_sz_frac = sector_div(vol_sz, ENG_GIG_FACTOR);
 		vol_sz_frac *= 100;
 		sector_div(vol_sz_frac, ENG_GIG_FACTOR);
 
 		if (drv->raid_level > 5)
 			drv->raid_level = RAID_UNKNOWN;
 		size = sprintf(buffer+len, "cciss/c%dd%d:"
-				"\t%4d.%02dGB\tRAID %s\n",
-				ctlr, i, vol_sz,vol_sz_frac,
+				"\t%4u.%02uGB\tRAID %s\n",
+				ctlr, i, (int)vol_sz, (int)vol_sz_frac,
 				raid_label[drv->raid_level]);
                 pos += size; len += size;
         }
@@ -578,7 +567,7 @@ int cciss_ioctl32_passthru(unsigned int fd, unsigned cmd, unsigned long arg,
 	err = sys_ioctl(fd, CCISS_PASSTHRU, (unsigned long) p);
 	if (err)
 		return err;
-	err |= copy_in_user(&arg32->error_info, &p->error_info, sizeof(&arg32->error_info));
+	err |= copy_in_user(&arg32->error_info, &p->error_info, sizeof(arg32->error_info));
 	if (err)
 		return -EFAULT;
 	return err;
@@ -610,7 +599,7 @@ int cciss_ioctl32_big_passthru(unsigned int fd, unsigned cmd, unsigned long arg,
 	err = sys_ioctl(fd, CCISS_BIG_PASSTHRU, (unsigned long) p);
 	if (err)
 		return err;
-	err |= copy_in_user(&arg32->error_info, &p->error_info, sizeof(&arg32->error_info));
+	err |= copy_in_user(&arg32->error_info, &p->error_info, sizeof(arg32->error_info));
 	if (err)
 		return -EFAULT;
 	return err;
@@ -866,6 +855,8 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
 				kfree(buff);
 				return -EFAULT;
 			}
+		} else {
+			memset(buff, 0, iocommand.buf_size);
 		}
 		if ((c = cmd_alloc(host , 0)) == NULL)
 		{
@@ -1012,6 +1003,8 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
 				copy_from_user(buff[sg_used], data_ptr, sz)) {
 					status = -ENOMEM;
 					goto cleanup1;			
+			} else {
+				memset(buff[sg_used], 0, sz);
 			}
 			left -= sz;
 			data_ptr += sz;
@@ -1477,12 +1470,19 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
 			drv->sectors = 32; // Sectors per track
 			drv->cylinders = total_size / 255 / 32;
 		} else {
+			unsigned int t;
+
 			drv->block_size = block_size;
 			drv->nr_blocks = total_size;
 			drv->heads = inq_buff->data_byte[6];
 			drv->sectors = inq_buff->data_byte[7];
 			drv->cylinders = (inq_buff->data_byte[4] & 0xff) << 8;
 			drv->cylinders += inq_buff->data_byte[5];
+			drv->raid_level = inq_buff->data_byte[8];
+			t = drv->heads * drv->sectors;
+			if (t > 1) {
+				drv->cylinders = total_size/t;
+			}
 		}
 	} else { /* Get geometry failed */
 		printk(KERN_WARNING "cciss: reading geometry failed, "
@@ -1509,8 +1509,8 @@ cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
 		return_code = sendcmd(CCISS_READ_CAPACITY,
 			ctlr, buf, sizeof(*buf), 1, logvol, 0, NULL, TYPE_CMD);
 	if (return_code == IO_OK) {
-		*total_size = be32_to_cpu(*((__u32 *) &buf->total_size[0]))+1;
-		*block_size = be32_to_cpu(*((__u32 *) &buf->block_size[0]));
+		*total_size = be32_to_cpu(*((__be32 *) &buf->total_size[0]))+1;
+		*block_size = be32_to_cpu(*((__be32 *) &buf->block_size[0]));
 	} else { /* read capacity command failed */
 		printk(KERN_WARNING "cciss: read capacity failed\n");
 		*total_size = 0;
@@ -1844,13 +1844,13 @@ cleanup1:
 /*
  * Map (physical) PCI mem into (virtual) kernel space
  */
-static ulong remap_pci_mem(ulong base, ulong size)
+static void __iomem *remap_pci_mem(ulong base, ulong size)
 {
         ulong page_base        = ((ulong) base) & PAGE_MASK;
         ulong page_offs        = ((ulong) base) - page_base;
-        ulong page_remapped    = (ulong) ioremap(page_base, page_offs+size);
+        void __iomem *page_remapped = ioremap(page_base, page_offs+size);
 
-        return (ulong) (page_remapped ? (page_remapped + page_offs) : 0UL);
+        return page_remapped ? (page_remapped + page_offs) : NULL;
 }
 
 /* 
@@ -2300,7 +2300,6 @@ static int find_PCI_BAR_index(struct pci_dev *pdev,
 static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
 {
 	ushort subsystem_vendor_id, subsystem_device_id, command;
-	unchar irq = pdev->irq;
 	__u32 board_id, scratchpad = 0;
 	__u64 cfg_offset;
 	__u32 cfg_base_addr;
@@ -2359,11 +2358,11 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
 
 #ifdef CCISS_DEBUG
 	printk("command = %x\n", command);
-	printk("irq = %x\n", irq);
+	printk("irq = %x\n", pdev->irq);
 	printk("board_id = %x\n", board_id);
 #endif /* CCISS_DEBUG */ 
 
-	c->intr = irq;
+	c->intr = pdev->irq;
 
 	/*
 	 * Memory base addr is first addr , the second points to the config
@@ -2411,9 +2410,9 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
 #ifdef CCISS_DEBUG
 	printk("cfg offset = %x\n", cfg_offset);
 #endif /* CCISS_DEBUG */
-	c->cfgtable = (CfgTable_struct *) 
-		remap_pci_mem(pci_resource_start(pdev, cfg_base_addr_index)
-				+ cfg_offset, sizeof(CfgTable_struct));
+	c->cfgtable =  remap_pci_mem(pci_resource_start(pdev,
+				cfg_base_addr_index) + cfg_offset,
+				sizeof(CfgTable_struct));
 	c->board_id = board_id;
 
 #ifdef CCISS_DEBUG
@@ -2825,7 +2824,7 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev)
 	}
 	free_irq(hba[i]->intr, hba[i]);
 	pci_set_drvdata(pdev, NULL);
-	iounmap((void*)hba[i]->vaddr);
+	iounmap(hba[i]->vaddr);
 	cciss_unregister_scsi(i);  /* unhook from SCSI subsystem */
 	unregister_blkdev(COMPAQ_CISS_MAJOR+i, hba[i]->devname);
 	remove_proc_entry(hba[i]->devname, proc_cciss);	
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index 825855cd4..8ab689c21 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -43,12 +43,12 @@ struct ctlr_info
 	char	firm_ver[4]; // Firmware version 
 	struct pci_dev *pdev;
 	__u32	board_id;
-	unsigned long vaddr;
+	void __iomem *vaddr;
 	unsigned long paddr;
 	unsigned long io_mem_addr;
 	unsigned long io_mem_length;
-	CfgTable_struct *cfgtable;
-	int	intr;
+	CfgTable_struct __iomem *cfgtable;
+	unsigned int intr;
 	int	interrupts_enabled;
 	int 	max_commands;
 	int	commands_outstanding;
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index b42a8d33f..204b31829 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -138,7 +138,7 @@ static struct gendisk *ida_gendisk[MAX_CTLR][NWD];
 
 int cpqarray_init_step2(void);
 static int cpqarray_pci_init(ctlr_info_t *c, struct pci_dev *pdev);
-static void *remap_pci_mem(ulong base, ulong size);
+static void __iomem *remap_pci_mem(ulong base, ulong size);
 static int cpqarray_eisa_detect(void);
 static int pollcomplete(int ctlr);
 static void getgeometry(int ctlr);
@@ -551,10 +551,10 @@ static int __init cpqarray_init_one( struct pci_dev *pdev,
 }
 
 static struct pci_driver cpqarray_pci_driver = {
-	name:   "cpqarray",
-	probe:  cpqarray_init_one,
-	remove:  __devexit_p(cpqarray_remove_one_pci),
-	id_table:  cpqarray_pci_device_id,
+	.name = "cpqarray",
+	.probe = cpqarray_init_one,
+	.remove = __devexit_p(cpqarray_remove_one_pci),
+	.id_table = cpqarray_pci_device_id,
 };
 
 /*
@@ -722,11 +722,11 @@ DBGINFO(
 /*
  * Map (physical) PCI mem into (virtual) kernel space
  */
-static void *remap_pci_mem(ulong base, ulong size)
+static void __iomem *remap_pci_mem(ulong base, ulong size)
 {
         ulong page_base        = ((ulong) base) & PAGE_MASK;
         ulong page_offs        = ((ulong) base) - page_base;
-        void *page_remapped    = ioremap(page_base, page_offs+size);
+        void __iomem *page_remapped    = ioremap(page_base, page_offs+size);
 
         return (page_remapped ? (page_remapped + page_offs) : NULL);
 }
diff --git a/drivers/block/cpqarray.h b/drivers/block/cpqarray.h
index 112e39422..6a9ded054 100644
--- a/drivers/block/cpqarray.h
+++ b/drivers/block/cpqarray.h
@@ -90,7 +90,7 @@ struct ctlr_info {
 	__u32	board_id;
 	char	*product_name;	
 
-	void *vaddr;
+	void __iomem *vaddr;
 	unsigned long paddr;
 	unsigned long io_mem_addr;
 	unsigned long io_mem_length;
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index e82caa224..c68215b35 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -365,7 +365,9 @@ static ssize_t disk_size_read(struct gendisk * disk, char *page)
 
 static ssize_t disk_stats_read(struct gendisk * disk, char *page)
 {
+	preempt_disable();
 	disk_round_stats(disk);
+	preempt_enable();
 	return sprintf(page,
 		"%8u %8u %8llu %8u "
 		"%8u %8u %8llu %8u "
@@ -494,7 +496,9 @@ static int diskstats_show(struct seq_file *s, void *v)
 				"\n\n");
 	*/
  
+	preempt_disable();
 	disk_round_stats(gp);
+	preempt_enable();
 	seq_printf(s, "%4d %4d %s %u %u %llu %u %u %u %llu %u %u %u %u\n",
 		gp->major, n + gp->first_minor, disk_name(gp, n, buf),
 		disk_stat_read(gp, reads), disk_stat_read(gp, read_merges),
diff --git a/drivers/block/ioctl.c b/drivers/block/ioctl.c
index 283a9f2fa..43ff0c6ed 100644
--- a/drivers/block/ioctl.c
+++ b/drivers/block/ioctl.c
@@ -194,7 +194,8 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
 			return -EACCES;
 		if (disk->fops->ioctl) {
 			ret = disk->fops->ioctl(inode, file, cmd, arg);
-			if (ret != -EINVAL)
+			/* -EINVAL to handle old uncorrected drivers */
+			if (ret != -EINVAL && ret != -ENOTTY)
 				return ret;
 		}
 		fsync_bdev(bdev);
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 17c403ebd..26fdf6be6 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -154,6 +154,8 @@ struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev)
 	return ret;
 }
 
+EXPORT_SYMBOL(blk_get_backing_dev_info);
+
 void blk_queue_activity_fn(request_queue_t *q, activity_fn *fn, void *data)
 {
 	q->activity_fn = fn;
@@ -262,6 +264,45 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
 
 EXPORT_SYMBOL(blk_queue_make_request);
 
+/**
+ * blk_queue_ordered - does this queue support ordered writes
+ * @q:     the request queue
+ * @flag:  see below
+ *
+ * Description:
+ *   For journalled file systems, doing ordered writes on a commit
+ *   block instead of explicitly doing wait_on_buffer (which is bad
+ *   for performance) can be a big win. Block drivers supporting this
+ *   feature should call this function and indicate so.
+ *
+ **/
+void blk_queue_ordered(request_queue_t *q, int flag)
+{
+	if (flag)
+		set_bit(QUEUE_FLAG_ORDERED, &q->queue_flags);
+	else
+		clear_bit(QUEUE_FLAG_ORDERED, &q->queue_flags);
+}
+
+EXPORT_SYMBOL(blk_queue_ordered);
+
+/**
+ * blk_queue_issue_flush_fn - set function for issuing a flush
+ * @q:     the request queue
+ * @iff:   the function to be called issuing the flush
+ *
+ * Description:
+ *   If a driver supports issuing a flush command, the support is notified
+ *   to the block layer by defining it through this call.
+ *
+ **/
+void blk_queue_issue_flush_fn(request_queue_t *q, issue_flush_fn *iff)
+{
+	q->issue_flush_fn = iff;
+}
+
+EXPORT_SYMBOL(blk_queue_issue_flush_fn);
+
 /**
  * blk_queue_bounce_limit - set bounce buffer limit for queue
  * @q:  the request queue for the device
@@ -311,7 +352,7 @@ void blk_queue_max_sectors(request_queue_t *q, unsigned short max_sectors)
 		printk("%s: set to minimum %d\n", __FUNCTION__, max_sectors);
 	}
 
-	q->max_sectors = max_sectors;
+	q->max_sectors = q->max_hw_sectors = max_sectors;
 }
 
 EXPORT_SYMBOL(blk_queue_max_sectors);
@@ -413,7 +454,8 @@ EXPORT_SYMBOL(blk_queue_hardsect_size);
 void blk_queue_stack_limits(request_queue_t *t, request_queue_t *b)
 {
 	/* zero is "infinity" */
-	t->max_sectors = min_not_zero(t->max_sectors,b->max_sectors);
+	t->max_sectors = t->max_hw_sectors =
+		min_not_zero(t->max_sectors,b->max_sectors);
 
 	t->max_phys_segments = min(t->max_phys_segments,b->max_phys_segments);
 	t->max_hw_segments = min(t->max_hw_segments,b->max_hw_segments);
@@ -482,15 +524,14 @@ struct request *blk_queue_find_tag(request_queue_t *q, int tag)
 EXPORT_SYMBOL(blk_queue_find_tag);
 
 /**
- * blk_queue_free_tags - release tag maintenance info
+ * __blk_queue_free_tags - release tag maintenance info
  * @q:  the request queue for the device
  *
  *  Notes:
  *    blk_cleanup_queue() will take care of calling this function, if tagging
- *    has been used. So there's usually no need to call this directly, unless
- *    tagging is just being disabled but the queue remains in function.
+ *    has been used. So there's no need to call this directly.
  **/
-void blk_queue_free_tags(request_queue_t *q)
+static void __blk_queue_free_tags(request_queue_t *q)
 {
 	struct blk_queue_tag *bqt = q->queue_tags;
 
@@ -514,12 +555,27 @@ void blk_queue_free_tags(request_queue_t *q)
 	q->queue_flags &= ~(1 << QUEUE_FLAG_QUEUED);
 }
 
+/**
+ * blk_queue_free_tags - release tag maintenance info
+ * @q:  the request queue for the device
+ *
+ *  Notes:
+ *	This is used to disabled tagged queuing to a device, yet leave
+ *	queue in function.
+ **/
+void blk_queue_free_tags(request_queue_t *q)
+{
+	clear_bit(QUEUE_FLAG_QUEUED, &q->queue_flags);
+}
+
 EXPORT_SYMBOL(blk_queue_free_tags);
 
 static int
 init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth)
 {
 	int bits, i;
+	struct request **tag_index;
+	unsigned long *tag_map;
 
 	if (depth > q->nr_requests * 2) {
 		depth = q->nr_requests * 2;
@@ -527,32 +583,31 @@ init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth)
 				__FUNCTION__, depth);
 	}
 
-	tags->tag_index = kmalloc(depth * sizeof(struct request *), GFP_ATOMIC);
-	if (!tags->tag_index)
+	tag_index = kmalloc(depth * sizeof(struct request *), GFP_ATOMIC);
+	if (!tag_index)
 		goto fail;
 
 	bits = (depth / BLK_TAGS_PER_LONG) + 1;
-	tags->tag_map = kmalloc(bits * sizeof(unsigned long), GFP_ATOMIC);
-	if (!tags->tag_map)
+	tag_map = kmalloc(bits * sizeof(unsigned long), GFP_ATOMIC);
+	if (!tag_map)
 		goto fail;
 
-	memset(tags->tag_index, 0, depth * sizeof(struct request *));
-	memset(tags->tag_map, 0, bits * sizeof(unsigned long));
+	memset(tag_index, 0, depth * sizeof(struct request *));
+	memset(tag_map, 0, bits * sizeof(unsigned long));
 	tags->max_depth = depth;
 	tags->real_max_depth = bits * BITS_PER_LONG;
+	tags->tag_index = tag_index;
+	tags->tag_map = tag_map;
 
 	/*
 	 * set the upper bits if the depth isn't a multiple of the word size
 	 */
 	for (i = depth; i < bits * BLK_TAGS_PER_LONG; i++)
-		__set_bit(i, tags->tag_map);
+		__set_bit(i, tag_map);
 
-	INIT_LIST_HEAD(&tags->busy_list);
-	tags->busy = 0;
-	atomic_set(&tags->refcnt, 1);
 	return 0;
 fail:
-	kfree(tags->tag_index);
+	kfree(tag_index);
 	return -ENOMEM;
 }
 
@@ -564,13 +619,26 @@ fail:
 int blk_queue_init_tags(request_queue_t *q, int depth,
 			struct blk_queue_tag *tags)
 {
-	if (!tags) {
+	int rc;
+
+	BUG_ON(tags && q->queue_tags && tags != q->queue_tags);
+
+	if (!tags && !q->queue_tags) {
 		tags = kmalloc(sizeof(struct blk_queue_tag), GFP_ATOMIC);
 		if (!tags)
 			goto fail;
 
 		if (init_tag_map(q, tags, depth))
 			goto fail;
+
+		INIT_LIST_HEAD(&tags->busy_list);
+		tags->busy = 0;
+		atomic_set(&tags->refcnt, 1);
+	} else if (q->queue_tags) {
+		if ((rc = blk_queue_resize_tags(q, depth)))
+			return rc;
+		set_bit(QUEUE_FLAG_QUEUED, &q->queue_flags);
+		return 0;
 	} else
 		atomic_inc(&tags->refcnt);
 
@@ -1335,8 +1403,8 @@ void blk_cleanup_queue(request_queue_t * q)
 	if (rl->rq_pool)
 		mempool_destroy(rl->rq_pool);
 
-	if (blk_queue_tagged(q))
-		blk_queue_free_tags(q);
+	if (q->queue_tags)
+		__blk_queue_free_tags(q);
 
 	kmem_cache_free(requestq_cachep, q);
 }
@@ -1925,10 +1993,11 @@ int blk_execute_rq(request_queue_t *q, struct gendisk *bd_disk,
 	}
 
 	rq->flags |= REQ_NOMERGE;
-	rq->waiting = &wait;
+	if (!rq->waiting)
+		rq->waiting = &wait;
 	elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1);
 	generic_unplug_device(q);
-	wait_for_completion(&wait);
+	wait_for_completion(rq->waiting);
 	rq->waiting = NULL;
 
 	if (rq->errors)
@@ -1939,6 +2008,72 @@ int blk_execute_rq(request_queue_t *q, struct gendisk *bd_disk,
 
 EXPORT_SYMBOL(blk_execute_rq);
 
+/**
+ * blkdev_issue_flush - queue a flush
+ * @bdev:	blockdev to issue flush for
+ * @error_sector:	error sector
+ *
+ * Description:
+ *    Issue a flush for the block device in question. Caller can supply
+ *    room for storing the error offset in case of a flush error, if they
+ *    wish to.  Caller must run wait_for_completion() on its own.
+ */
+int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector)
+{
+	request_queue_t *q;
+
+	if (bdev->bd_disk == NULL)
+		return -ENXIO;
+
+	q = bdev_get_queue(bdev);
+	if (!q)
+		return -ENXIO;
+	if (!q->issue_flush_fn)
+		return -EOPNOTSUPP;
+
+	return q->issue_flush_fn(q, bdev->bd_disk, error_sector);
+}
+
+EXPORT_SYMBOL(blkdev_issue_flush);
+
+/**
+ * blkdev_scsi_issue_flush_fn - issue flush for SCSI devices
+ * @q:		device queue
+ * @disk:	gendisk
+ * @error_sector:	error offset
+ *
+ * Description:
+ *    Devices understanding the SCSI command set, can use this function as
+ *    a helper for issuing a cache flush. Note: driver is required to store
+ *    the error offset (in case of error flushing) in ->sector of struct
+ *    request.
+ */
+int blkdev_scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
+			       sector_t *error_sector)
+{
+	struct request *rq = blk_get_request(q, WRITE, __GFP_WAIT);
+	int ret;
+
+	rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER;
+	rq->sector = 0;
+	memset(rq->cmd, 0, sizeof(rq->cmd));
+	rq->cmd[0] = 0x35;
+	rq->cmd_len = 12;
+	rq->data = NULL;
+	rq->data_len = 0;
+	rq->timeout = 60 * HZ;
+
+	ret = blk_execute_rq(q, disk, rq);
+
+	if (ret && error_sector)
+		*error_sector = rq->sector;
+
+	blk_put_request(rq);
+	return ret;
+}
+
+EXPORT_SYMBOL(blkdev_scsi_issue_flush_fn);
+
 void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
 {
 	int rw = rq_data_dir(rq);
@@ -2192,7 +2327,7 @@ EXPORT_SYMBOL(__blk_attempt_remerge);
 static int __make_request(request_queue_t *q, struct bio *bio)
 {
 	struct request *req, *freereq = NULL;
-	int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, ra;
+	int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, err;
 	sector_t sector;
 
 	sector = bio->bi_sector;
@@ -2210,9 +2345,11 @@ static int __make_request(request_queue_t *q, struct bio *bio)
 
 	spin_lock_prefetch(q->queue_lock);
 
-	barrier = test_bit(BIO_RW_BARRIER, &bio->bi_rw);
-
-	ra = bio->bi_rw & (1 << BIO_RW_AHEAD);
+	barrier = bio_barrier(bio);
+	if (barrier && !(q->queue_flags & (1 << QUEUE_FLAG_ORDERED))) {
+		err = -EOPNOTSUPP;
+		goto end_io;
+	}
 
 again:
 	spin_lock_irq(q->queue_lock);
@@ -2292,7 +2429,8 @@ get_rq:
 			/*
 			 * READA bit set
 			 */
-			if (ra)
+			err = -EWOULDBLOCK;
+			if (bio_rw_ahead(bio))
 				goto end_io;
 	
 			freereq = get_request_wait(q, rw);
@@ -2303,10 +2441,9 @@ get_rq:
 	req->flags |= REQ_CMD;
 
 	/*
-	 * inherit FAILFAST from bio and don't stack up
-	 * retries for read ahead
+	 * inherit FAILFAST from bio (for read-ahead, and explicit FAILFAST)
 	 */
-	if (ra || test_bit(BIO_RW_FAILFAST, &bio->bi_rw))	
+	if (bio_rw_ahead(bio) || bio_failfast(bio))
 		req->flags |= REQ_FAILFAST;
 
 	/*
@@ -2340,7 +2477,7 @@ out:
 	return 0;
 
 end_io:
-	bio_endio(bio, nr_sectors << 9, -EWOULDBLOCK);
+	bio_endio(bio, nr_sectors << 9, err);
 	return 0;
 }
 
@@ -2399,6 +2536,7 @@ void generic_make_request(struct bio *bio)
 	sector_t maxsector;
 	int ret, nr_sectors = bio_sectors(bio);
 
+	might_sleep();
 	/* Test device or partition size, when known. */
 	maxsector = bio->bi_bdev->bd_inode->i_size >> 9;
 	if (maxsector) {
@@ -2446,11 +2584,11 @@ end_io:
 			break;
 		}
 
-		if (unlikely(bio_sectors(bio) > q->max_sectors)) {
+		if (unlikely(bio_sectors(bio) > q->max_hw_sectors)) {
 			printk("bio too big device %s (%u > %u)\n", 
 				bdevname(bio->bi_bdev, b),
 				bio_sectors(bio),
-				q->max_sectors);
+				q->max_hw_sectors);
 			goto end_io;
 		}
 
@@ -2647,9 +2785,16 @@ void blk_recalc_rq_sectors(struct request *rq, int nsect)
 static int __end_that_request_first(struct request *req, int uptodate,
 				    int nr_bytes)
 {
-	int total_bytes, bio_nbytes, error = 0, next_idx = 0;
+	int total_bytes, bio_nbytes, error, next_idx = 0;
 	struct bio *bio;
 
+	/*
+	 * extend uptodate bool to allow < 0 value to be direct io error
+	 */
+	error = 0;
+	if (end_io_error(uptodate))
+		error = !uptodate ? -EIO : uptodate;
+
 	/*
 	 * for a REQ_BLOCK_PC request, we want to carry any eventual
 	 * sense key with us all the way through
@@ -2658,7 +2803,6 @@ static int __end_that_request_first(struct request *req, int uptodate,
 		req->errors = 0;
 
 	if (!uptodate) {
-		error = -EIO;
 		if (blk_fs_request(req) && !(req->flags & REQ_QUIET))
 			printk("end_request: I/O error, dev %s, sector %llu\n",
 				req->rq_disk ? req->rq_disk->disk_name : "?",
@@ -2741,7 +2885,7 @@ static int __end_that_request_first(struct request *req, int uptodate,
 /**
  * end_that_request_first - end I/O on a request
  * @req:      the request being processed
- * @uptodate: 0 for I/O error
+ * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error
  * @nr_sectors: number of sectors to end I/O on
  *
  * Description:
@@ -2762,7 +2906,7 @@ EXPORT_SYMBOL(end_that_request_first);
 /**
  * end_that_request_chunk - end I/O on a request
  * @req:      the request being processed
- * @uptodate: 0 for I/O error
+ * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error
  * @nr_bytes: number of bytes to complete
  *
  * Description:
@@ -3063,13 +3207,61 @@ queue_ra_store(struct request_queue *q, const char *page, size_t count)
 	unsigned long ra_kb;
 	ssize_t ret = queue_var_store(&ra_kb, page, count);
 
+	spin_lock_irq(q->queue_lock);
 	if (ra_kb > (q->max_sectors >> 1))
 		ra_kb = (q->max_sectors >> 1);
 
 	q->backing_dev_info.ra_pages = ra_kb >> (PAGE_CACHE_SHIFT - 10);
+	spin_unlock_irq(q->queue_lock);
+
 	return ret;
 }
 
+static ssize_t queue_max_sectors_show(struct request_queue *q, char *page)
+{
+	int max_sectors_kb = q->max_sectors >> 1;
+
+	return queue_var_show(max_sectors_kb, (page));
+}
+
+static ssize_t
+queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
+{
+	unsigned long max_sectors_kb,
+			max_hw_sectors_kb = q->max_hw_sectors >> 1,
+			page_kb = 1 << (PAGE_CACHE_SHIFT - 10);
+	ssize_t ret = queue_var_store(&max_sectors_kb, page, count);
+	int ra_kb;
+
+	if (max_sectors_kb > max_hw_sectors_kb || max_sectors_kb < page_kb)
+		return -EINVAL;
+	/*
+	 * Take the queue lock to update the readahead and max_sectors
+	 * values synchronously:
+	 */
+	spin_lock_irq(q->queue_lock);
+	/*
+	 * Trim readahead window as well, if necessary:
+	 */
+	ra_kb = q->backing_dev_info.ra_pages << (PAGE_CACHE_SHIFT - 10);
+	if (ra_kb > max_sectors_kb)
+		q->backing_dev_info.ra_pages =
+				max_sectors_kb >> (PAGE_CACHE_SHIFT - 10);
+
+	q->max_sectors = max_sectors_kb << 1;
+	spin_unlock_irq(q->queue_lock);
+
+	return ret;
+}
+
+static ssize_t queue_max_hw_sectors_show(struct request_queue *q, char *page)
+{
+	int max_hw_sectors_kb = q->max_hw_sectors >> 1;
+
+	return queue_var_show(max_hw_sectors_kb, (page));
+}
+
+
 static struct queue_sysfs_entry queue_requests_entry = {
 	.attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR },
 	.show = queue_requests_show,
@@ -3082,9 +3274,22 @@ static struct queue_sysfs_entry queue_ra_entry = {
 	.store = queue_ra_store,
 };
 
+static struct queue_sysfs_entry queue_max_sectors_entry = {
+	.attr = {.name = "max_sectors_kb", .mode = S_IRUGO | S_IWUSR },
+	.show = queue_max_sectors_show,
+	.store = queue_max_sectors_store,
+};
+
+static struct queue_sysfs_entry queue_max_hw_sectors_entry = {
+	.attr = {.name = "max_hw_sectors_kb", .mode = S_IRUGO },
+	.show = queue_max_hw_sectors_show,
+};
+
 static struct attribute *default_attrs[] = {
 	&queue_requests_entry.attr,
 	&queue_ra_entry.attr,
+	&queue_max_hw_sectors_entry.attr,
+	&queue_max_sectors_entry.attr,
 	NULL,
 };
 
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index b98b70b8f..75ad39dc6 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -128,23 +128,11 @@ static void nbd_end_request(struct request *req)
 {
 	int uptodate = (req->errors == 0) ? 1 : 0;
 	request_queue_t *q = req->q;
-	struct nbd_device *lo = req->rq_disk->private_data;
 	unsigned long flags;
 
 	dprintk(DBG_BLKDEV, "%s: request %p: %s\n", req->rq_disk->disk_name,
 			req, uptodate? "done": "failed");
 
-	spin_lock(&lo->queue_lock);
-	while (req->ref_count > 1) { /* still in send */
-		spin_unlock(&lo->queue_lock);
-		printk(KERN_DEBUG "%s: request %p still in use (%d), waiting\n",
-		    lo->disk->disk_name, req, req->ref_count);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ); /* wait a second */
-		spin_lock(&lo->queue_lock);
-	}
-	spin_unlock(&lo->queue_lock);
-
 	spin_lock_irqsave(q->queue_lock, flags);
 	if (!end_that_request_first(req, uptodate, req->nr_sectors)) {
 		end_that_request_last(req);
@@ -228,7 +216,7 @@ static inline int sock_send_bvec(struct socket *sock, struct bio_vec *bvec,
 	return result;
 }
 
-void nbd_send_req(struct nbd_device *lo, struct request *req)
+static int nbd_send_req(struct nbd_device *lo, struct request *req)
 {
 	int result, i, flags;
 	struct nbd_request request;
@@ -288,11 +276,11 @@ void nbd_send_req(struct nbd_device *lo, struct request *req)
 		}
 	}
 	up(&lo->tx_lock);
-	return;
+	return 0;
 
 error_out:
 	up(&lo->tx_lock);
-	req->errors++;
+	return 1;
 }
 
 static struct request *nbd_find_request(struct nbd_device *lo, char *handle)
@@ -477,26 +465,19 @@ static void do_nbd_request(request_queue_t * q)
 		}
 
 		list_add(&req->queuelist, &lo->queue_head);
-		req->ref_count++; /* make sure req does not get freed */
 		spin_unlock(&lo->queue_lock);
 
-		nbd_send_req(lo, req);
-
-		if (req->errors) {
+		if (nbd_send_req(lo, req) != 0) {
 			printk(KERN_ERR "%s: Request send failed\n",
 					lo->disk->disk_name);
-			spin_lock(&lo->queue_lock);
-			list_del_init(&req->queuelist);
-			req->ref_count--;
-			spin_unlock(&lo->queue_lock);
-			nbd_end_request(req);
-			spin_lock_irq(q->queue_lock);
-			continue;
+			if (nbd_find_request(lo, (char *)&req) != NULL) {
+				/* we still own req */
+				req->errors++;
+				nbd_end_request(req);
+			} else /* we're racing with nbd_clear_que */
+				printk(KERN_DEBUG "nbd: can't find req\n");
 		}
 
-		spin_lock(&lo->queue_lock);
-		req->ref_count--;
-		spin_unlock(&lo->queue_lock);
 		spin_lock_irq(q->queue_lock);
 		continue;
 
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index fe8332e34..b3c7f07c1 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -349,13 +349,17 @@ static int rd_open(struct inode *inode, struct file *filp)
 	if (rd_bdev[unit] == NULL) {
 		struct block_device *bdev = inode->i_bdev;
 		struct address_space *mapping;
+		unsigned bsize;
 		int gfp_mask;
 
 		inode = igrab(bdev->bd_inode);
 		rd_bdev[unit] = bdev;
 		bdev->bd_openers++;
-		bdev->bd_block_size = rd_blocksize;
-		inode->i_size = get_capacity(rd_disks[unit])<<9;
+		bsize = bdev_hardsect_size(bdev);
+		bdev->bd_block_size = bsize;
+		inode->i_blkbits = blksize_bits(bsize);
+		inode->i_size = get_capacity(bdev->bd_disk)<<9;
+
 		mapping = inode->i_mapping;
 		mapping->a_ops = &ramdisk_aops;
 		mapping->backing_dev_info = &rd_backing_dev_info;
@@ -449,6 +453,7 @@ static int __init rd_init(void)
 			goto out_queue;
 
 		blk_queue_make_request(rd_queue[i], &rd_make_request);
+		blk_queue_hardsect_size(rd_queue[i], rd_blocksize);
 
 		/* rd_size is given in kB */
 		disk->major = RAMDISK_MAJOR;
diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c
index 41d023931..f8fb5322f 100644
--- a/drivers/block/scsi_ioctl.c
+++ b/drivers/block/scsi_ioctl.c
@@ -127,12 +127,16 @@ static int verify_command(struct file *file, unsigned char *cmd)
 		safe_for_read(MODE_SENSE),
 		safe_for_read(MODE_SENSE_10),
 		safe_for_read(START_STOP),
+		safe_for_read(GPCMD_VERIFY_10),
+		safe_for_read(VERIFY_16),
+		safe_for_read(READ_BUFFER),
 
 		/* Audio CD commands */
 		safe_for_read(GPCMD_PLAY_CD),
 		safe_for_read(GPCMD_PLAY_AUDIO_10),
 		safe_for_read(GPCMD_PLAY_AUDIO_MSF),
 		safe_for_read(GPCMD_PLAY_AUDIO_TI),
+		safe_for_read(GPCMD_PAUSE_RESUME),
 
 		/* CD/DVD data reading */
 		safe_for_read(GPCMD_READ_CD),
@@ -146,6 +150,12 @@ static int verify_command(struct file *file, unsigned char *cmd)
 		safe_for_read(GPCMD_READ_TOC_PMA_ATIP),
 		safe_for_read(GPCMD_REPORT_KEY),
 		safe_for_read(GPCMD_SCAN),
+		safe_for_read(GPCMD_GET_CONFIGURATION),
+		safe_for_read(GPCMD_READ_FORMAT_CAPACITIES),
+		safe_for_read(GPCMD_GET_EVENT_STATUS_NOTIFICATION),
+		safe_for_read(GPCMD_GET_PERFORMANCE),
+		safe_for_read(GPCMD_SEEK),
+		safe_for_read(GPCMD_STOP_PLAY_SCAN),
 
 		/* Basic writing commands */
 		safe_for_write(WRITE_6),
@@ -154,8 +164,25 @@ static int verify_command(struct file *file, unsigned char *cmd)
 		safe_for_write(WRITE_12),
 		safe_for_write(WRITE_VERIFY_12),
 		safe_for_write(WRITE_16),
-		safe_for_write(WRITE_BUFFER),
 		safe_for_write(WRITE_LONG),
+		safe_for_write(ERASE),
+		safe_for_write(GPCMD_MODE_SELECT_10),
+		safe_for_write(MODE_SELECT),
+		safe_for_write(GPCMD_BLANK),
+		safe_for_write(GPCMD_CLOSE_TRACK),
+		safe_for_write(GPCMD_FLUSH_CACHE),
+		safe_for_write(GPCMD_FORMAT_UNIT),
+		safe_for_write(GPCMD_REPAIR_RZONE_TRACK),
+		safe_for_write(GPCMD_RESERVE_RZONE_TRACK),
+		safe_for_write(GPCMD_SEND_DVD_STRUCTURE),
+		safe_for_write(GPCMD_SEND_EVENT),
+		safe_for_write(GPCMD_SEND_KEY),
+		safe_for_write(GPCMD_SEND_OPC),
+		safe_for_write(GPCMD_SEND_CUE_SHEET),
+		safe_for_write(GPCMD_SET_SPEED),
+		safe_for_write(GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL),
+		safe_for_write(GPCMD_LOAD_UNLOAD),
+		safe_for_write(GPCMD_SET_STREAMING),
 	};
 	unsigned char type = cmd_type[cmd[0]];
 
@@ -511,6 +538,7 @@ int scsi_cmd_ioctl(struct file *file, struct gendisk *bd_disk, unsigned int cmd,
 		 * old junk scsi send command ioctl
 		 */
 		case SCSI_IOCTL_SEND_COMMAND:
+			printk(KERN_WARNING "program %s is using a deprecated SCSI ioctl, please convert it to SG_IO\n", current->comm);
 			err = -EINVAL;
 			if (!arg)
 				break;
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index 0a0234129..02a541ae7 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -242,7 +242,7 @@ struct carm_request {
 
 struct carm_host {
 	unsigned long			flags;
-	void				*mmio;
+	void				__iomem *mmio;
 	void				*shm;
 	dma_addr_t			shm_dma;
 
@@ -283,13 +283,13 @@ struct carm_host {
 };
 
 struct carm_response {
-	u32 ret_handle;
-	u32 status;
+	__le32 ret_handle;
+	__le32 status;
 }  __attribute__((packed));
 
 struct carm_msg_sg {
-	u32 start;
-	u32 len;
+	__le32 start;
+	__le32 len;
 }  __attribute__((packed));
 
 struct carm_msg_rw {
@@ -297,10 +297,10 @@ struct carm_msg_rw {
 	u8 id;
 	u8 sg_count;
 	u8 sg_type;
-	u32 handle;
-	u32 lba;
-	u16 lba_count;
-	u16 lba_high;
+	__le32 handle;
+	__le32 lba;
+	__le16 lba_count;
+	__le16 lba_high;
 	struct carm_msg_sg sg[32];
 }  __attribute__((packed));
 
@@ -309,15 +309,15 @@ struct carm_msg_allocbuf {
 	u8 subtype;
 	u8 n_sg;
 	u8 sg_type;
-	u32 handle;
-	u32 addr;
-	u32 len;
-	u32 evt_pool;
-	u32 n_evt;
-	u32 rbuf_pool;
-	u32 n_rbuf;
-	u32 msg_pool;
-	u32 n_msg;
+	__le32 handle;
+	__le32 addr;
+	__le32 len;
+	__le32 evt_pool;
+	__le32 n_evt;
+	__le32 rbuf_pool;
+	__le32 n_rbuf;
+	__le32 msg_pool;
+	__le32 n_msg;
 	struct carm_msg_sg sg[8];
 }  __attribute__((packed));
 
@@ -326,8 +326,8 @@ struct carm_msg_ioctl {
 	u8 subtype;
 	u8 array_id;
 	u8 reserved1;
-	u32 handle;
-	u32 data_addr;
+	__le32 handle;
+	__le32 data_addr;
 	u32 reserved2;
 }  __attribute__((packed));
 
@@ -335,48 +335,48 @@ struct carm_msg_sync_time {
 	u8 type;
 	u8 subtype;
 	u16 reserved1;
-	u32 handle;
+	__le32 handle;
 	u32 reserved2;
-	u32 timestamp;
+	__le32 timestamp;
 }  __attribute__((packed));
 
 struct carm_msg_get_fw_ver {
 	u8 type;
 	u8 subtype;
 	u16 reserved1;
-	u32 handle;
-	u32 data_addr;
+	__le32 handle;
+	__le32 data_addr;
 	u32 reserved2;
 }  __attribute__((packed));
 
 struct carm_fw_ver {
-	u32 version;
+	__le32 version;
 	u8 features;
 	u8 reserved1;
 	u16 reserved2;
 }  __attribute__((packed));
 
 struct carm_array_info {
-	u32 size;
+	__le32 size;
 
-	u16 size_hi;
-	u16 stripe_size;
+	__le16 size_hi;
+	__le16 stripe_size;
 
-	u32 mode;
+	__le32 mode;
 
-	u16 stripe_blk_sz;
-	u16 reserved1;
+	__le16 stripe_blk_sz;
+	__le16 reserved1;
 
-	u16 cyl;
-	u16 head;
+	__le16 cyl;
+	__le16 head;
 
-	u16 sect;
+	__le16 sect;
 	u8 array_id;
 	u8 reserved2;
 
 	char name[40];
 
-	u32 array_status;
+	__le32 array_status;
 
 	/* device list continues beyond this point? */
 }  __attribute__((packed));
@@ -451,7 +451,7 @@ static inline int carm_lookup_bucket(u32 msg_size)
 	return -ENOENT;
 }
 
-static void carm_init_buckets(void *mmio)
+static void carm_init_buckets(void __iomem *mmio)
 {
 	unsigned int i;
 
@@ -474,7 +474,7 @@ static inline dma_addr_t carm_ref_msg_dma(struct carm_host *host,
 static int carm_send_msg(struct carm_host *host,
 			 struct carm_request *crq)
 {
-	void *mmio = host->mmio;
+	void __iomem *mmio = host->mmio;
 	u32 msg = (u32) carm_ref_msg_dma(host, crq->tag);
 	u32 cm_bucket = crq->msg_bucket;
 	u32 tmp;
@@ -965,7 +965,7 @@ static void carm_handle_array_info(struct carm_host *host,
 	port = &host->port[cur_port];
 
 	lo = (u64) le32_to_cpu(desc->size);
-	hi = (u64) le32_to_cpu(desc->size_hi);
+	hi = (u64) le16_to_cpu(desc->size_hi);
 
 	port->capacity = lo | (hi << 32);
 	port->dev_geom_head = le16_to_cpu(desc->head);
@@ -1060,7 +1060,7 @@ static inline void carm_handle_rw(struct carm_host *host,
 }
 
 static inline void carm_handle_resp(struct carm_host *host,
-				    u32 ret_handle_le, u32 status)
+				    __le32 ret_handle_le, u32 status)
 {
 	u32 handle = le32_to_cpu(ret_handle_le);
 	unsigned int msg_idx;
@@ -1158,7 +1158,7 @@ err_out:
 
 static inline void carm_handle_responses(struct carm_host *host)
 {
-	void *mmio = host->mmio;
+	void __iomem *mmio = host->mmio;
 	struct carm_response *resp = (struct carm_response *) host->shm;
 	unsigned int work = 0;
 	unsigned int idx = host->resp_idx % RMSG_Q_LEN;
@@ -1176,7 +1176,7 @@ static inline void carm_handle_responses(struct carm_host *host)
 		else if ((status & (1 << 31)) == 0) {
 			VPRINTK("handling msg response on index %u\n", idx);
 			carm_handle_resp(host, resp[idx].ret_handle, status);
-			resp[idx].status = 0xffffffff;
+			resp[idx].status = cpu_to_le32(0xffffffff);
 		}
 
 		/* asynchronous events the hardware throws our way */
@@ -1185,7 +1185,7 @@ static inline void carm_handle_responses(struct carm_host *host)
 			u8 evt_type = *evt_type_ptr;
 			printk(KERN_WARNING DRV_NAME "(%s): unhandled event type %d\n",
 			       pci_name(host->pdev), (int) evt_type);
-			resp[idx].status = 0xffffffff;
+			resp[idx].status = cpu_to_le32(0xffffffff);
 		}
 
 		idx = NEXT_RESP(idx);
@@ -1199,7 +1199,7 @@ static inline void carm_handle_responses(struct carm_host *host)
 static irqreturn_t carm_interrupt(int irq, void *__host, struct pt_regs *regs)
 {
 	struct carm_host *host = __host;
-	void *mmio;
+	void __iomem *mmio;
 	u32 mask;
 	int handled = 0;
 	unsigned long flags;
@@ -1364,7 +1364,7 @@ static void carm_fsm_task (void *_data)
 		schedule_work(&host->fsm_task);
 }
 
-static int carm_init_wait(void *mmio, u32 bits, unsigned int test_bit)
+static int carm_init_wait(void __iomem *mmio, u32 bits, unsigned int test_bit)
 {
 	unsigned int i;
 
@@ -1390,19 +1390,19 @@ static int carm_init_wait(void *mmio, u32 bits, unsigned int test_bit)
 
 static void carm_init_responses(struct carm_host *host)
 {
-	void *mmio = host->mmio;
+	void __iomem *mmio = host->mmio;
 	unsigned int i;
 	struct carm_response *resp = (struct carm_response *) host->shm;
 
 	for (i = 0; i < RMSG_Q_LEN; i++)
-		resp[i].status = 0xffffffff;
+		resp[i].status = cpu_to_le32(0xffffffff);
 
 	writel(0, mmio + CARM_RESP_IDX);
 }
 
 static int carm_init_host(struct carm_host *host)
 {
-	void *mmio = host->mmio;
+	void __iomem *mmio = host->mmio;
 	u32 tmp;
 	u8 tmp8;
 	int rc;
@@ -1414,7 +1414,7 @@ static int carm_init_host(struct carm_host *host)
 	tmp8 = readb(mmio + CARM_INITC);
 	if (tmp8 & 0x01) {
 		tmp8 &= ~0x01;
-		writeb(tmp8, CARM_INITC);
+		writeb(tmp8, mmio + CARM_INITC);
 		readb(mmio + CARM_INITC);	/* flush */
 
 		DPRINTK("snooze...\n");
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index 2b126d8d2..db7083a0c 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -108,11 +108,11 @@ struct cardinfo {
 	int		irq;
 
 	unsigned long	csr_base;
-	unsigned char	*csr_remap;
+	unsigned char	__iomem *csr_remap;
 	unsigned long	csr_len;
 #ifdef CONFIG_MM_MAP_MEMORY
 	unsigned long	mem_base;
-	unsigned char	*mem_remap;
+	unsigned char	__iomem *mem_remap;
 	unsigned long	mem_len;
 #endif
 
@@ -926,7 +926,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i
 		goto failed_req_mem;
 	}
 
-	if (!(card->mem_remap = (unsigned char *)ioremap(card->mem_base, cards->mem_len))) {
+	if (!(card->mem_remap = ioremap(card->mem_base, cards->mem_len))) {
 		printk(KERN_ERR "MM%d: Unable to remap memory region\n", card->card_number);
 		ret = -ENOMEM;
 
@@ -1107,12 +1107,12 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i
 				    card->mm_pages[1].page_dma);
  failed_magic:
 #ifdef CONFIG_MM_MAP_MEMORY
-	iounmap((void *) card->mem_remap);
+	iounmap(card->mem_remap);
  failed_remap_mem:
 	release_mem_region(card->mem_base, card->mem_len);
  failed_req_mem:
 #endif
-	iounmap((void *) card->csr_remap);
+	iounmap(card->csr_remap);
  failed_remap_csr:
 	release_mem_region(card->csr_base, card->csr_len);
  failed_req_csr:
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 5ba134216..fb990ec38 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -188,9 +188,7 @@ static int hci_uart_flush(struct hci_dev *hdev)
 	}
 
 	/* Flush any pending characters in the driver and discipline. */
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
-
+	tty_ldisc_flush(tty);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
 
@@ -280,7 +278,9 @@ static int hci_uart_tty_open(struct tty_struct *tty)
 
 	spin_lock_init(&hu->rx_lock);
 
-	/* Flush any pending characters in the driver and line discipline */
+	/* Flush any pending characters in the driver and line discipline. */
+	/* FIXME: why is this needed. Note don't use ldisc_ref here as the
+	   open path is before the ldisc is referencable */
 	if (tty->ldisc.flush_buffer)
 		tty->ldisc.flush_buffer(tty);
 
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index 9babb21df..bca968310 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -96,7 +96,7 @@ static struct usb_device_id blacklist_ids[] = {
 	{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE },
 
 	/* Broadcom BCM2035 */
-	{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = HCI_RESET },
+	{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = HCI_RESET | HCI_BROKEN_ISOC },
 
 	/* ISSC Bluetooth Adapter v3.1 */
 	{ USB_DEVICE(0x1131, 0x1001), .driver_info = HCI_RESET },
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 2e1ee63d1..e57d19031 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -354,6 +354,19 @@ static void cdrom_sysctl_register(void);
 #endif /* CONFIG_SYSCTL */ 
 static struct cdrom_device_info *topCdromPtr;
 
+static int cdrom_dummy_generic_packet(struct cdrom_device_info *cdi,
+				      struct packet_command *cgc)
+{
+	if (cgc->sense) {
+		cgc->sense->sense_key = 0x05;
+		cgc->sense->asc = 0x20;
+		cgc->sense->ascq = 0x00;
+	}
+
+	cgc->stat = -EIO;
+	return -EIO;
+}
+
 /* This macro makes sure we don't have to check on cdrom_device_ops
  * existence in the run-time routines below. Change_capability is a
  * hack to have the capability flags defined const, while we can still
@@ -411,6 +424,9 @@ int register_cdrom(struct cdrom_device_info *cdi)
 	else
 		cdi->cdda_method = CDDA_OLD;
 
+	if (!cdo->generic_packet)
+		cdo->generic_packet = cdrom_dummy_generic_packet;
+
 	cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
 	spin_lock(&cdrom_lock);
 	cdi->next = topCdromPtr; 	
@@ -472,6 +488,9 @@ int cdrom_get_media_event(struct cdrom_device_info *cdi,
 	if (be16_to_cpu(eh->data_len) < sizeof(*med))
 		return 1;
 
+	if (eh->nea || eh->notification_class != 0x4)
+		return 1;
+
 	memcpy(med, &buffer[sizeof(*eh)], sizeof(*med));
 	return 0;
 }
@@ -605,13 +624,16 @@ static int cdrom_flush_cache(struct cdrom_device_info *cdi)
 static int cdrom_mrw_exit(struct cdrom_device_info *cdi)
 {
 	disc_information di;
-	int ret = 0;
+	int ret;
 
-	if (cdrom_get_disc_info(cdi, &di))
+	ret = cdrom_get_disc_info(cdi, &di);
+	if (ret < 0 || ret < (int)offsetof(typeof(di),disc_type))
 		return 1;
 
+	ret = 0;
 	if (di.mrw_status == CDM_MRW_BGFORMAT_ACTIVE) {
-		printk(KERN_INFO "cdrom: issuing MRW back ground format suspend\n");
+		printk(KERN_INFO "cdrom: issuing MRW back ground "
+				"format suspend\n");
 		ret = cdrom_mrw_bgformat_susp(cdi, 0);
 	}
 
@@ -715,8 +737,10 @@ int cdrom_is_random_writable(struct cdrom_device_info *cdi, int *write)
 static int cdrom_media_erasable(struct cdrom_device_info *cdi)
 {
 	disc_information di;
+	int ret;
 
-	if (cdrom_get_disc_info(cdi, &di))
+	ret = cdrom_get_disc_info(cdi, &di);
+	if (ret < 0 || ret < offsetof(typeof(di), n_first_track))
 		return -1;
 
 	return di.erasable;
@@ -752,7 +776,8 @@ static int cdrom_mrw_open_write(struct cdrom_device_info *cdi)
 		return 1;
 	}
 
-	if (cdrom_get_disc_info(cdi, &di))
+	ret = cdrom_get_disc_info(cdi, &di);
+	if (ret < 0 || ret < offsetof(typeof(di),disc_type))
 		return 1;
 
 	if (!di.erasable)
@@ -766,10 +791,12 @@ static int cdrom_mrw_open_write(struct cdrom_device_info *cdi)
 	 * 3	-	MRW formatting complete
 	 */
 	ret = 0;
-	printk(KERN_INFO "cdrom open: mrw_status '%s'\n", mrw_format_status[di.mrw_status]);
+	printk(KERN_INFO "cdrom open: mrw_status '%s'\n",
+			mrw_format_status[di.mrw_status]);
 	if (!di.mrw_status)
 		ret = 1;
-	else if (di.mrw_status == CDM_MRW_BGFORMAT_INACTIVE && mrw_format_restart)
+	else if (di.mrw_status == CDM_MRW_BGFORMAT_INACTIVE &&
+			mrw_format_restart)
 		ret = cdrom_mrw_bgformat(cdi, 1);
 
 	return ret;
@@ -1922,7 +1949,8 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf,
 			       int lba, int nframes)
 {
 	struct packet_command cgc;
-	int nr, ret;
+	int ret = 0;
+	int nr;
 
 	cdi->last_sense = 0;
 
@@ -1944,8 +1972,8 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf,
 		return -ENOMEM;
 
 	if (!access_ok(VERIFY_WRITE, ubuf, nframes * CD_FRAMESIZE_RAW)) {
-		kfree(cgc.buffer);
-		return -EFAULT;
+		ret = -EFAULT;
+		goto out;
 	}
 
 	cgc.data_direction = CGC_DATA_READ;
@@ -1956,13 +1984,17 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf,
 		ret = cdrom_read_block(cdi, &cgc, lba, nr, 1, CD_FRAMESIZE_RAW);
 		if (ret)
 			break;
-		__copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr);
+		if (__copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr)) {
+			ret = -EFAULT;
+			break;
+		}
 		ubuf += CD_FRAMESIZE_RAW * nr;
 		nframes -= nr;
 		lba += nr;
 	}
+out:
 	kfree(cgc.buffer);
-	return 0;
+	return ret;
 }
 
 static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
@@ -2504,7 +2536,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
 	struct cdrom_device_ops *cdo = cdi->ops;
 	struct packet_command cgc;
 	struct request_sense sense;
-	char buffer[32];
+	unsigned char buffer[32];
 	int ret = 0;
 
 	memset(&cgc, 0, sizeof(cgc));
@@ -2631,8 +2663,9 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
 	case CDROMVOLCTRL:
 	case CDROMVOLREAD: {
 		struct cdrom_volctrl volctrl;
-		char mask[32];
+		char mask[sizeof(buffer)];
 		unsigned short offset;
+
 		cdinfo(CD_DO_IOCTL, "entering CDROMVOLUME\n");
 
 		IOCTL_IN(arg, struct cdrom_volctrl, volctrl);
@@ -2642,17 +2675,27 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
 		if ((ret = cdrom_mode_sense(cdi, &cgc, GPMODE_AUDIO_CTL_PAGE, 0)))
 		    return ret;
 		
-		/* some drives have longer pages, adjust and reread. */
-		if (buffer[1] > cgc.buflen) {
-			cgc.buflen = buffer[1] + 2;
-			if ((ret = cdrom_mode_sense(cdi, &cgc, 
-					GPMODE_AUDIO_CTL_PAGE, 0))) 
-			    return ret;
+		/* originally the code depended on buffer[1] to determine
+		   how much data is available for transfer. buffer[1] is
+		   unfortunately ambigious and the only reliable way seem
+		   to be to simply skip over the block descriptor... */
+		offset = 8 + be16_to_cpu(*(unsigned short *)(buffer+6));
+
+		if (offset + 16 > sizeof(buffer))
+			return -E2BIG;
+
+		if (offset + 16 > cgc.buflen) {
+			cgc.buflen = offset+16;
+			ret = cdrom_mode_sense(cdi, &cgc,
+						GPMODE_AUDIO_CTL_PAGE, 0);
+			if (ret)
+				return ret;
 		}
-		
-		/* get the offset from the length of the page. length
-		   is measure from byte 2 an on, thus the 14. */
-		offset = buffer[1] - 14;
+
+		/* sanity check */
+		if ((buffer[offset] & 0x3f) != GPMODE_AUDIO_CTL_PAGE ||
+				buffer[offset+1] < 14)
+			return -EINVAL;
 
 		/* now we have the current volume settings. if it was only
 		   a CDROMVOLREAD, return these values */
@@ -2677,7 +2720,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
 		buffer[offset+15] = volctrl.channel3 & mask[offset+15];
 
 		/* set volume */
-		cgc.buffer = buffer;
+		cgc.buffer = buffer + offset - 8;
+		memset(cgc.buffer, 0, 8);
 		return cdrom_mode_select(cdi, &cgc);
 		}
 
@@ -2760,7 +2804,7 @@ static int cdrom_get_track_info(struct cdrom_device_info *cdi, __u16 track, __u8
 {
 	struct cdrom_device_ops *cdo = cdi->ops;
 	struct packet_command cgc;
-	int ret;
+	int ret, buflen;
 
 	init_cdrom_command(&cgc, ti, 8, CGC_DATA_READ);
 	cgc.cmd[0] = GPCMD_READ_TRACK_RZONE_INFO;
@@ -2773,14 +2817,18 @@ static int cdrom_get_track_info(struct cdrom_device_info *cdi, __u16 track, __u8
 	if ((ret = cdo->generic_packet(cdi, &cgc)))
 		return ret;
 	
-	cgc.buflen = be16_to_cpu(ti->track_information_length) +
+	buflen = be16_to_cpu(ti->track_information_length) +
 		     sizeof(ti->track_information_length);
 
-	if (cgc.buflen > sizeof(track_information))
-		cgc.buflen = sizeof(track_information);
+	if (buflen > sizeof(track_information))
+		buflen = sizeof(track_information);
 
-	cgc.cmd[8] = cgc.buflen;
-	return cdo->generic_packet(cdi, &cgc);
+	cgc.cmd[8] = cgc.buflen = buflen;
+	if ((ret = cdo->generic_packet(cdi, &cgc)))
+		return ret;
+
+	/* return actual fill size */
+	return buflen;
 }
 
 /* requires CD R/RW */
@@ -2788,7 +2836,7 @@ static int cdrom_get_disc_info(struct cdrom_device_info *cdi, disc_information *
 {
 	struct cdrom_device_ops *cdo = cdi->ops;
 	struct packet_command cgc;
-	int ret;
+	int ret, buflen;
 
 	/* set up command and get the disc info */
 	init_cdrom_command(&cgc, di, sizeof(*di), CGC_DATA_READ);
@@ -2802,14 +2850,18 @@ static int cdrom_get_disc_info(struct cdrom_device_info *cdi, disc_information *
 	/* not all drives have the same disc_info length, so requeue
 	 * packet with the length the drive tells us it can supply
 	 */
-	cgc.buflen = be16_to_cpu(di->disc_information_length) +
+	buflen = be16_to_cpu(di->disc_information_length) +
 		     sizeof(di->disc_information_length);
 
-	if (cgc.buflen > sizeof(disc_information))
-		cgc.buflen = sizeof(disc_information);
+	if (buflen > sizeof(disc_information))
+		buflen = sizeof(disc_information);
 
-	cgc.cmd[8] = cgc.buflen;
-	return cdo->generic_packet(cdi, &cgc);
+	cgc.cmd[8] = cgc.buflen = buflen;
+	if ((ret = cdo->generic_packet(cdi, &cgc)))
+		return ret;
+
+	/* return actual fill size */
+	return buflen;
 }
 
 /* return the last written block on the CD-R media. this is for the udf
@@ -2820,27 +2872,37 @@ int cdrom_get_last_written(struct cdrom_device_info *cdi, long *last_written)
 	disc_information di;
 	track_information ti;
 	__u32 last_track;
-	int ret = -1;
+	int ret = -1, ti_size;
 
 	if (!CDROM_CAN(CDC_GENERIC_PACKET))
 		goto use_toc;
 
-	if ((ret = cdrom_get_disc_info(cdi, &di)))
+	ret = cdrom_get_disc_info(cdi, &di);
+	if (ret < (int)(offsetof(typeof(di), last_track_lsb)
+			+ sizeof(di.last_track_lsb)))
 		goto use_toc;
 
+	/* if unit didn't return msb, it's zeroed by cdrom_get_disc_info */
 	last_track = (di.last_track_msb << 8) | di.last_track_lsb;
-	if ((ret = cdrom_get_track_info(cdi, last_track, 1, &ti)))
+	ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti);
+	if (ti_size < (int)offsetof(typeof(ti), track_start))
 		goto use_toc;
 
 	/* if this track is blank, try the previous. */
 	if (ti.blank) {
-		last_track--;
-		if ((ret = cdrom_get_track_info(cdi, last_track, 1, &ti)))
+		if (last_track==1)
 			goto use_toc;
+		last_track--;
+		ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti);
 	}
 
+	if (ti_size < (int)(offsetof(typeof(ti), track_size)
+				+ sizeof(ti.track_size)))
+		goto use_toc;
+
 	/* if last recorded field is valid, return it. */
-	if (ti.lra_v) {
+	if (ti.lra_v && ti_size >= (int)(offsetof(typeof(ti), last_rec_address)
+				+ sizeof(ti.last_rec_address))) {
 		*last_written = be32_to_cpu(ti.last_rec_address);
 	} else {
 		/* make it up instead */
@@ -2853,11 +2915,12 @@ int cdrom_get_last_written(struct cdrom_device_info *cdi, long *last_written)
 
 	/* this is where we end up if the drive either can't do a
 	   GPCMD_READ_DISC_INFO or GPCMD_READ_TRACK_RZONE_INFO or if
-	   it fails. then we return the toc contents. */
+	   it doesn't give enough information or fails. then we return
+	   the toc contents. */
 use_toc:
 	toc.cdte_format = CDROM_MSF;
 	toc.cdte_track = CDROM_LEADOUT;
-	if (cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &toc))
+	if ((ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &toc)))
 		return ret;
 	sanitize_format(&toc.cdte_addr, &toc.cdte_format, CDROM_LBA);
 	*last_written = toc.cdte_addr.lba;
@@ -2870,32 +2933,38 @@ static int cdrom_get_next_writable(struct cdrom_device_info *cdi, long *next_wri
 	disc_information di;
 	track_information ti;
 	__u16 last_track;
-	int ret = -1;
+	int ret, ti_size;
 
 	if (!CDROM_CAN(CDC_GENERIC_PACKET))
 		goto use_last_written;
 
-	if ((ret = cdrom_get_disc_info(cdi, &di)))
+	ret = cdrom_get_disc_info(cdi, &di);
+	if (ret < 0 || ret < offsetof(typeof(di), last_track_lsb)
+				+ sizeof(di.last_track_lsb))
 		goto use_last_written;
 
+	/* if unit didn't return msb, it's zeroed by cdrom_get_disc_info */
 	last_track = (di.last_track_msb << 8) | di.last_track_lsb;
-	if ((ret = cdrom_get_track_info(cdi, last_track, 1, &ti)))
+	ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti);
+	if (ti_size < 0 || ti_size < offsetof(typeof(ti), track_start))
 		goto use_last_written;
 
         /* if this track is blank, try the previous. */
 	if (ti.blank) {
+		if (last_track == 1)
+			goto use_last_written;
 		last_track--;
-		if ((ret = cdrom_get_track_info(cdi, last_track, 1, &ti)))
+		ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti);
+		if (ti_size < 0)
 			goto use_last_written;
 	}
 
 	/* if next recordable address field is valid, use it. */
-	if (ti.nwa_v)
+	if (ti.nwa_v && ti_size >= offsetof(typeof(ti), next_writable)
+				+ sizeof(ti.next_writable)) {
 		*next_writable = be32_to_cpu(ti.next_writable);
-	else
-		goto use_last_written;
-
-	return 0;
+		return 0;
+	}
 
 use_last_written:
 	if ((ret = cdrom_get_last_written(cdi, next_writable))) {
diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
index cbe336429..09873fa1b 100644
--- a/drivers/cdrom/cdu31a.c
+++ b/drivers/cdrom/cdu31a.c
@@ -729,8 +729,7 @@ static void restart_on_error(void)
 		       res_reg[1]);
 	}
 
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(2 * HZ);
+	msleep(2000);
 
 	sony_get_toc();
 }
@@ -960,8 +959,7 @@ retry_cd_operation:
 	if (((result_buffer[0] & 0xf0) == 0x20)
 	    && (num_retries < MAX_CDU31A_RETRIES)) {
 		num_retries++;
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(HZ / 10);	/* Wait .1 seconds on retries */
+		msleep(100);
 		goto retry_cd_operation;
 	}
 
diff --git a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c
index 4cb0fb491..b4f5e0295 100644
--- a/drivers/cdrom/mcd.c
+++ b/drivers/cdrom/mcd.c
@@ -1021,10 +1021,9 @@ static int mcd_open(struct cdrom_device_info *cdi, int purpose)
 		st = statusCmd();	/* check drive status */
 		if (st == -1)
 			goto err_out;	/* drive doesn't respond */
-		if ((st & MST_READY) == 0) {	/* no disk? wait a sec... */
-			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(HZ);
-		}
+		if ((st & MST_READY) == 0) 	/* no disk? wait a sec... */
+			msleep(1000);
+
 	} while (((st & MST_READY) == 0) && count++ < MCD_RETRY_ATTEMPTS);
 
 	if (updateToc() < 0)
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index 3a2acc0fb..0509ae21e 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -121,7 +121,10 @@ struct capability_entry {
 };
 
 static struct capability_entry capability_table[] __initdata = {
-	{ "6330", CDC_LOCK | CDC_DVD_RAM },
+	{ "6330", CDC_LOCK | CDC_DVD_RAM | CDC_RAM },
+	{ "6331", CDC_LOCK | CDC_DVD_RAM | CDC_RAM },
+	{ "6333", CDC_LOCK | CDC_DVD_RAM | CDC_RAM },
+	{ "632A", CDC_LOCK | CDC_DVD_RAM | CDC_RAM },
 	{ "6321", CDC_LOCK },
 	{ "632B", 0 },
 	{ NULL  , CDC_LOCK },
@@ -332,10 +335,19 @@ static int send_request(struct request *req)
 	struct disk_info *diskinfo = req->rq_disk->private_data;
 	u64 len;
 	dma_addr_t dmaaddr;
+	int direction;
+	u16 cmd;
 	struct scatterlist sg;
 
 	BUG_ON(req->nr_phys_segments > 1);
-	BUG_ON(rq_data_dir(req) != READ);
+
+	if (rq_data_dir(req) == READ) {
+		direction = DMA_FROM_DEVICE;
+		cmd = viomajorsubtype_cdio | viocdread;
+	} else {
+		direction = DMA_TO_DEVICE;
+		cmd = viomajorsubtype_cdio | viocdwrite;
+	}
 
         if (blk_rq_map_sg(req->q, req, &sg) == 0) {
 		printk(VIOCD_KERN_WARNING
@@ -343,7 +355,7 @@ static int send_request(struct request *req)
 		return -1;
 	}
 
-	if (dma_map_sg(diskinfo->dev, &sg, 1, DMA_FROM_DEVICE) == 0) {
+	if (dma_map_sg(diskinfo->dev, &sg, 1, direction) == 0) {
 		printk(VIOCD_KERN_WARNING "error allocating sg tce\n");
 		return -1;
 	}
@@ -351,8 +363,7 @@ static int send_request(struct request *req)
 	len = sg_dma_len(&sg);
 
 	hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
-			HvLpEvent_Type_VirtualIo,
-			viomajorsubtype_cdio | viocdread,
+			HvLpEvent_Type_VirtualIo, cmd,
 			HvLpEvent_AckInd_DoAck,
 			HvLpEvent_AckType_ImmediateAck,
 			viopath_sourceinst(viopath_hostLp),
@@ -457,6 +468,41 @@ static int viocd_lock_door(struct cdrom_device_info *cdi, int locking)
 	return 0;
 }
 
+static int viocd_packet(struct cdrom_device_info *cdi,
+		struct packet_command *cgc)
+{
+	unsigned int buflen = cgc->buflen;
+	int ret = -EIO;
+
+	switch (cgc->cmd[0]) {
+	case GPCMD_READ_DISC_INFO:
+		{
+			disc_information *di = (disc_information *)cgc->buffer;
+
+			if (buflen >= 2) {
+				di->disc_information_length = cpu_to_be16(1);
+				ret = 0;
+			}
+			if (buflen >= 3)
+				di->erasable =
+					(cdi->ops->capability & ~cdi->mask
+					 & (CDC_DVD_RAM | CDC_RAM)) != 0;
+		}
+		break;
+	default:
+		if (cgc->sense) {
+			/* indicate Unknown code */
+			cgc->sense->sense_key = 0x05;
+			cgc->sense->asc = 0x20;
+			cgc->sense->ascq = 0x00;
+		}
+		break;
+	}
+
+	cgc->stat = ret;
+	return ret;
+}
+
 /* This routine handles incoming CD LP events */
 static void vio_handle_cd_event(struct HvLpEvent *event)
 {
@@ -510,6 +556,7 @@ return_complete:
 	case viocdclose:
 		break;
 
+	case viocdwrite:
 	case viocdread:
 		/*
 		 * Since this is running in interrupt mode, we need to
@@ -518,7 +565,8 @@ return_complete:
 		di = &viocd_diskinfo[bevent->disk];
 		spin_lock_irqsave(&viocd_reqlock, flags);
 		dma_unmap_single(di->dev, bevent->token, bevent->len,
-				DMA_FROM_DEVICE);
+				((event->xSubtype & VIOMINOR_SUBTYPE_MASK) == viocdread)
+				?  DMA_FROM_DEVICE : DMA_TO_DEVICE);
 		req = (struct request *)bevent->event.xCorrelationToken;
 		rwreq--;
 
@@ -555,7 +603,8 @@ static struct cdrom_device_ops viocd_dops = {
 	.release = viocd_release,
 	.media_changed = viocd_media_changed,
 	.lock_door = viocd_lock_door,
-	.capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_GENERIC_PACKET | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM
+	.generic_packet = viocd_packet,
+	.capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_GENERIC_PACKET | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_RAM
 };
 
 static int __init find_capability(const char *type)
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 37e067351..f7bfe2059 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -59,7 +59,7 @@ config VT_CONSOLE
 
 config HW_CONSOLE
 	bool
-	depends on VT && !S390 && !UM
+	depends on VT && !S390 && !USERMODE
 	default y
 
 config SERIAL_NONSTANDARD
@@ -424,6 +424,14 @@ config A2232
 	  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 SGI_SNSC
+	bool "SGI Altix system controller communication support"
+	depends on (IA64_SGI_SN2 || IA64_GENERIC)
+	help
+	  If you have an SGI Altix and you want to enable system
+	  controller communication from user space (you want this!),
+	  say Y.  Otherwise, say N.
+
 source "drivers/serial/Kconfig"
 
 config UNIX98_PTYS
@@ -587,39 +595,6 @@ config HVCS
 	  which will also be compiled when this driver is built as a
 	  module.
 
-config QIC02_TAPE
-	tristate "QIC-02 tape support"
-	help
-	  If you have a non-SCSI tape drive like that, say Y.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called tpqic02.
-
-config QIC02_DYNCONF
-	bool "Do you want runtime configuration for QIC-02"
-	depends on QIC02_TAPE
-	help
-	  You can either configure this driver once and for all by editing a
-	  header file (<file:include/linux/tpqic02.h>), in which case you
-	  should say N, or you can fetch a program via anonymous FTP which is
-	  able to configure this driver during runtime.  The program to do
-	  this is called 'qic02conf' and it is part of the
-	  tpqic02-support-X.Y.tar.gz support package.
-
-	  If you want to use the qic02conf program, say Y.
-
-comment "Edit configuration parameters in ./include/linux/tpqic02.h!"
-	depends on QIC02_TAPE && !QIC02_DYNCONF
-
-comment "Setting runtime QIC-02 configuration is done with qic02conf"
-	depends on QIC02_TAPE && QIC02_DYNCONF
-
-comment "from the tpqic02-support package.  It is available at"
-	depends on QIC02_TAPE && QIC02_DYNCONF
-
-comment "metalab.unc.edu or ftp://titus.cfw.com/pub/Linux/util/"
-	depends on QIC02_TAPE && QIC02_DYNCONF
-
 source "drivers/char/ipmi/Kconfig"
 
 source "drivers/char/watchdog/Kconfig"
@@ -778,7 +753,7 @@ config SGI_IP27_RTC
 
 config GEN_RTC
 	tristate "Generic /dev/rtc emulation"
-	depends on RTC!=y && !IA64
+	depends on RTC!=y && !IA64 && !ARM
 	---help---
 	  If you say Y here and create a character special file /dev/rtc with
 	  major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -1006,5 +981,13 @@ config HANGCHECK_TIMER
 	  out to lunch past a certain margin.  It can reboot the system
 	  or merely print a warning.
 
+config MMTIMER
+	tristate "MMTIMER Memory mapped RTC for SGI Altix"
+	depends on IA64_GENERIC || IA64_SGI_SN2
+	default y
+	help
+	  The mmtimer device allows direct userspace access to the
+	  Altix system timer.
+
 endmenu
 
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index b927c16bb..c95223457 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -7,8 +7,11 @@
 #
 FONTMAPFILE = cp437.uni
 
-obj-y	 += mem.o random.o tty_io.o n_tty.o tty_ioctl.o pty.o misc.o
+obj-y	 += mem.o random.o tty_io.o n_tty.o tty_ioctl.o
 
+obj-$(CONFIG_LEGACY_PTYS)	+= pty.o
+obj-$(CONFIG_UNIX98_PTYS)	+= pty.o
+obj-y				+= misc.o
 obj-$(CONFIG_VT)		+= vt_ioctl.o vc_screen.o consolemap.o \
 				   consolemap_deftbl.o selection.o keyboard.o
 obj-$(CONFIG_HW_CONSOLE)	+= vt.o defkeymap.o
@@ -39,8 +42,10 @@ obj-$(CONFIG_N_HDLC)		+= n_hdlc.o
 obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
 obj-$(CONFIG_SX)		+= sx.o generic_serial.o
 obj-$(CONFIG_RIO)		+= rio/ generic_serial.o
-obj-$(CONFIG_HVC_CONSOLE)	+= hvc_console.o
+obj-$(CONFIG_HVC_CONSOLE)	+= hvc_console.o hvsi.o
 obj-$(CONFIG_RAW_DRIVER)	+= raw.o
+obj-$(CONFIG_SGI_SNSC)		+= snsc.o
+obj-$(CONFIG_MMTIMER)		+= mmtimer.o
 obj-$(CONFIG_VIOCONS) += viocons.o
 obj-$(CONFIG_VIOTAPE)		+= viotape.o
 obj-$(CONFIG_HVCS)		+= hvcs.o
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index 773279d48..d9b4a6e7f 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -1,5 +1,5 @@
 config AGP
-	tristate "/dev/agpgart (AGP Support)" if !GART_IOMMU && !M68K
+	tristate "/dev/agpgart (AGP Support)" if !GART_IOMMU && !M68K && !ARM
 	default y if GART_IOMMU
 	---help---
 	  AGP (Accelerated Graphics Port) is a bus system mainly used to
@@ -130,7 +130,7 @@ config AGP_VIA
 	depends on AGP && X86 && !X86_64
 	help
 	  This option gives you AGP support for the GLX component of
-	  XFree86 4.x on VIA MPV3/Apollo Pro chipsets.
+	  XFree86 4.x on VIA MVP3/Apollo Pro chipsets.
 
 	  You should say Y here if you use XFree86 3.3.6 or 4.x and want to
 	  use GLX or DRI.  If unsure, say N.
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index 2128374e7..f83e3e342 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -123,7 +123,7 @@ struct agp_bridge_data {
 	void *current_size;
 	void *dev_private_data;
 	struct pci_dev *dev;
-	u32 *gatt_table;
+	u32 __iomem *gatt_table;
 	u32 *gatt_table_real;
 	unsigned long scratch_page;
 	unsigned long scratch_page_real;
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index f1db2f86a..a45d36c3b 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -24,11 +24,11 @@ static struct pci_device_id agp_amdk7_pci_table[];
 
 struct amd_page_map {
 	unsigned long *real;
-	unsigned long *remapped;
+	unsigned long __iomem *remapped;
 };
 
 static struct _amd_irongate_private {
-	volatile u8 *registers;
+	volatile u8 __iomem *registers;
 	struct amd_page_map **gatt_pages;
 	int num_tables;
 } amd_irongate_private;
@@ -54,7 +54,7 @@ static int amd_create_page_map(struct amd_page_map *page_map)
 	global_cache_flush();
 
 	for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++)
-		page_map->remapped[i] = agp_bridge->scratch_page;
+		writel(agp_bridge->scratch_page, page_map->remapped+i);
 
 	return 0;
 }
@@ -151,7 +151,7 @@ static int amd_create_gatt_table(void)
 	}
 
 	agp_bridge->gatt_table_real = (u32 *)page_dir.real;
-	agp_bridge->gatt_table = (u32 *)page_dir.remapped;
+	agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped;
 	agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
 
 	/* Get the address for the gart region.
@@ -165,9 +165,8 @@ static int amd_create_gatt_table(void)
 
 	/* Calculate the agp offset */
 	for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
-		page_dir.remapped[GET_PAGE_DIR_OFF(addr)] =
-			virt_to_phys(amd_irongate_private.gatt_pages[i]->real);
-		page_dir.remapped[GET_PAGE_DIR_OFF(addr)] |= 0x00000001;
+		writel(virt_to_phys(amd_irongate_private.gatt_pages[i]->real) | 1,
+			page_dir.remapped+GET_PAGE_DIR_OFF(addr));
 	}
 
 	return 0;
@@ -178,7 +177,7 @@ static int amd_free_gatt_table(void)
 	struct amd_page_map page_dir;
 
 	page_dir.real = (unsigned long *)agp_bridge->gatt_table_real;
-	page_dir.remapped = (unsigned long *)agp_bridge->gatt_table;
+	page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table;
 
 	amd_free_gatt_pages();
 	amd_free_page_map(&page_dir);
@@ -218,7 +217,7 @@ static int amd_irongate_configure(void)
 	/* Get the memory mapped registers */
 	pci_read_config_dword(agp_bridge->dev, AMD_MMBASE, &temp);
 	temp = (temp & PCI_BASE_ADDRESS_MEM_MASK);
-	amd_irongate_private.registers = (volatile u8 *) ioremap(temp, 4096);
+	amd_irongate_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096);
 
 	/* Write out the address of the gatt table */
 	OUTREG32(amd_irongate_private.registers, AMD_ATTBASE,
@@ -263,7 +262,7 @@ static void amd_irongate_cleanup(void)
 	pci_read_config_dword(agp_bridge->dev, AMD_APSIZE, &temp);
 	temp = ((temp & ~(0x0000000f)) | previous_size->size_value);
 	pci_write_config_dword(agp_bridge->dev, AMD_APSIZE, temp);
-	iounmap((void *) amd_irongate_private.registers);
+	iounmap((void __iomem *) amd_irongate_private.registers);
 }
 
 /*
@@ -282,7 +281,7 @@ static void amd_irongate_tlbflush(struct agp_memory *temp)
 static int amd_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
 {
 	int i, j, num_entries;
-	unsigned long *cur_gatt;
+	unsigned long __iomem *cur_gatt;
 	unsigned long addr;
 
 	num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
@@ -297,7 +296,7 @@ static int amd_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
 	while (j < (pg_start + mem->page_count)) {
 		addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = GET_GATT(addr);
-		if (!PGE_EMPTY(agp_bridge, cur_gatt[GET_GATT_OFF(addr)]))
+		if (!PGE_EMPTY(agp_bridge, readl(cur_gatt+GET_GATT_OFF(addr))))
 			return -EBUSY;
 		j++;
 	}
@@ -310,8 +309,7 @@ static int amd_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = GET_GATT(addr);
-		cur_gatt[GET_GATT_OFF(addr)] =
-			agp_generic_mask_memory(mem->memory[i], mem->type);
+		writel(agp_generic_mask_memory(mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
 	}
 	amd_irongate_tlbflush(mem);
 	return 0;
@@ -320,7 +318,7 @@ static int amd_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
 static int amd_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
 {
 	int i;
-	unsigned long *cur_gatt;
+	unsigned long __iomem *cur_gatt;
 	unsigned long addr;
 
 	if (type != 0 || mem->type != 0)
@@ -329,8 +327,7 @@ static int amd_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
 	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
 		addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = GET_GATT(addr);
-		cur_gatt[GET_GATT_OFF(addr)] = 
-			(unsigned long) agp_bridge->scratch_page;
+		writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr));
 	}
 
 	amd_irongate_tlbflush(mem);
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 924ffc3db..2e8b2aee9 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -73,7 +73,7 @@ static void amd64_tlbflush(struct agp_memory *temp)
 static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
 {
 	int i, j, num_entries;
-	long tmp;
+	long long tmp;
 	u32 pte;
 
 	num_entries = agp_num_entries();
@@ -90,7 +90,7 @@ static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
 
 	/* gatt table should be empty. */
 	while (j < (pg_start + mem->page_count)) {
-		if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j]))
+		if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j)))
 			return -EBUSY;
 		j++;
 	}
@@ -108,7 +108,7 @@ static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
 		pte |=(tmp & 0x00000000fffff000ULL);
 		pte |= GPTE_VALID | GPTE_COHERENT;
 
-		agp_bridge->gatt_table[j] = pte;
+		writel(pte, agp_bridge->gatt_table+j);
 	}
 	amd64_tlbflush(mem);
 	return 0;
@@ -675,4 +675,4 @@ module_exit(agp_amd64_cleanup);
 
 MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>, Andi Kleen");
 MODULE_PARM(agp_try_unsupported, "1i");
-MODULE_LICENSE("GPL and additional rights");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index bc88d6991..8bf71c182 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -42,11 +42,11 @@ static struct gatt_mask ati_generic_masks[] =
 
 typedef struct _ati_page_map {
 	unsigned long *real;
-        unsigned long *remapped;
+	unsigned long __iomem *remapped;
 } ati_page_map;
 
 static struct _ati_generic_private {
-	volatile u8 *registers;
+	volatile u8 __iomem *registers;
 	ati_page_map **gatt_pages;
 	int num_tables;
 } ati_generic_private;
@@ -76,7 +76,7 @@ static int ati_create_page_map(ati_page_map *page_map)
 	global_cache_flush();
 
 	for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++)
-		page_map->remapped[i] = agp_bridge->scratch_page;
+		writel(agp_bridge->scratch_page, page_map->remapped+i);
 
 	return 0;
 }
@@ -206,7 +206,7 @@ static void ati_cleanup(void)
 		temp = ((temp & ~(0x0000000f)) | previous_size->size_value);
 		pci_write_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, temp);
 	}
-	iounmap((void *) ati_generic_private.registers);
+	iounmap((volatile u8 __iomem *)ati_generic_private.registers);
 }
 
 
@@ -217,7 +217,7 @@ static int ati_configure(void)
 	/* Get the memory mapped registers */
 	pci_read_config_dword(agp_bridge->dev, ATI_GART_MMBASE_ADDR, &temp);
 	temp = (temp & 0xfffff000);
-	ati_generic_private.registers = (volatile u8 *) ioremap(temp, 4096);
+	ati_generic_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096);
 
 	if (is_r200())
        	pci_write_config_dword(agp_bridge->dev, ATI_RS100_IG_AGPMODE, 0x20000);
@@ -261,7 +261,7 @@ static int ati_insert_memory(struct agp_memory * mem,
 			     off_t pg_start, int type)
 {
 	int i, j, num_entries;
-	unsigned long *cur_gatt;
+	unsigned long __iomem *cur_gatt;
 	unsigned long addr;
 
 	num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
@@ -276,7 +276,7 @@ static int ati_insert_memory(struct agp_memory * mem,
 	while (j < (pg_start + mem->page_count)) {
 		addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = GET_GATT(addr);
-		if (!PGE_EMPTY(agp_bridge,cur_gatt[GET_GATT_OFF(addr)]))
+		if (!PGE_EMPTY(agp_bridge,readl(cur_gatt+GET_GATT_OFF(addr))))
 			return -EBUSY;
 		j++;
 	}
@@ -290,8 +290,7 @@ static int ati_insert_memory(struct agp_memory * mem,
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = GET_GATT(addr);
-		cur_gatt[GET_GATT_OFF(addr)] =
-			agp_bridge->driver->mask_memory(mem->memory[i], mem->type);
+		writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
 	}
 	agp_bridge->driver->tlb_flush(mem);
 	return 0;
@@ -301,7 +300,7 @@ static int ati_remove_memory(struct agp_memory * mem, off_t pg_start,
 			     int type)
 {
 	int i;
-	unsigned long *cur_gatt;
+	unsigned long __iomem *cur_gatt;
 	unsigned long addr;
 
 	if (type != 0 || mem->type != 0) {
@@ -310,8 +309,7 @@ static int ati_remove_memory(struct agp_memory * mem, off_t pg_start,
 	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
 		addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = GET_GATT(addr);
-		cur_gatt[GET_GATT_OFF(addr)] =
-			(unsigned long) agp_bridge->scratch_page;
+		writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr));
 	}
 
 	agp_bridge->driver->tlb_flush(mem);
@@ -340,7 +338,7 @@ static int ati_create_gatt_table(void)
 	}
 
 	agp_bridge->gatt_table_real = (u32 *)page_dir.real;
-	agp_bridge->gatt_table = (u32 *)page_dir.remapped;
+	agp_bridge->gatt_table = (u32 __iomem *) page_dir.remapped;
 	agp_bridge->gatt_bus_addr = virt_to_bus(page_dir.real);
 
 	/* Write out the size register */
@@ -371,9 +369,8 @@ static int ati_create_gatt_table(void)
 
 	/* Calculate the agp offset */
 	for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
-		page_dir.remapped[GET_PAGE_DIR_OFF(addr)] =
-			virt_to_bus(ati_generic_private.gatt_pages[i]->real);
-		page_dir.remapped[GET_PAGE_DIR_OFF(addr)] |= 0x00000001;
+		writel(virt_to_bus(ati_generic_private.gatt_pages[i]->real) | 1,
+			page_dir.remapped+GET_PAGE_DIR_OFF(addr));
 	}
 
 	return 0;
@@ -384,7 +381,7 @@ static int ati_free_gatt_table(void)
 	ati_page_map page_dir;
 
 	page_dir.real = (unsigned long *)agp_bridge->gatt_table_real;
-	page_dir.remapped = (unsigned long *)agp_bridge->gatt_table;
+	page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table;
 
 	ati_free_gatt_pages();
 	ati_free_page_map(&page_dir);
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index f65662437..83498820c 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -35,6 +35,7 @@
 #include <linux/pm.h>
 #include <linux/agp_backend.h>
 #include <linux/vmalloc.h>
+#include <asm/io.h>
 #include "agp.h"
 
 __u32 *agp_gatt_table;
@@ -737,7 +738,7 @@ int agp_generic_create_gatt_table(void)
 
 	/* AK: bogus, should encode addresses > 4GB */
 	for (i = 0; i < num_entries; i++)
-		agp_bridge->gatt_table[i] = (unsigned long) agp_bridge->scratch_page;
+		writel(agp_bridge->scratch_page, agp_bridge->gatt_table+i);
 
 	return 0;
 }
@@ -843,9 +844,8 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
 	j = pg_start;
 
 	while (j < (pg_start + mem->page_count)) {
-		if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j])) {
+		if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j)))
 			return -EBUSY;
-		}
 		j++;
 	}
 
@@ -855,9 +855,7 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
 	}
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++)
-		agp_bridge->gatt_table[j] =
-				agp_bridge->driver->mask_memory(
-						mem->memory[i], mem->type);
+		writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), agp_bridge->gatt_table+j);
 
 	agp_bridge->driver->tlb_flush(mem);
 	return 0;
@@ -875,10 +873,8 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
 	}
 
 	/* AK: bogus, should encode addresses > 4GB */
-	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
-		agp_bridge->gatt_table[i] =
-		    (unsigned long) agp_bridge->scratch_page;
-	}
+	for (i = pg_start; i < (mem->page_count + pg_start); i++)
+		writel(agp_bridge->scratch_page, agp_bridge->gatt_table+i);
 
 	agp_bridge->driver->tlb_flush(mem);
 	return 0;
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
index 5fd2adc96..323a6b68d 100644
--- a/drivers/char/agp/hp-agp.c
+++ b/drivers/char/agp/hp-agp.c
@@ -59,8 +59,8 @@ static struct gatt_mask hp_zx1_masks[] =
 };
 
 static struct _hp_private {
-	volatile u8 *ioc_regs;
-	volatile u8 *lba_regs;
+	volatile u8 __iomem *ioc_regs;
+	volatile u8 __iomem *lba_regs;
 	int lba_cap_offset;
 	u64 *io_pdir;		// PDIR for entire IOVA
 	u64 *gatt;		// PDIR just for GART (subset of above)
@@ -97,7 +97,7 @@ static int __init hp_zx1_ioc_shared(void)
 		default:
 			printk(KERN_ERR PFX "Invalid IOTLB page size "
 			       "configuration 0x%x\n", hp->io_tlb_ps);
-			hp->gatt = 0;
+			hp->gatt = NULL;
 			hp->gatt_entries = 0;
 			return -ENODEV;
 	}
@@ -115,7 +115,7 @@ static int __init hp_zx1_ioc_shared(void)
 
 	if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) {
 		/* Normal case when no AGP device in system */
-	    	hp->gatt = 0;
+	    	hp->gatt = NULL;
 		hp->gatt_entries = 0;
 		printk(KERN_ERR PFX "No reserved IO PDIR entry found; "
 		       "GART disabled\n");
@@ -183,7 +183,7 @@ hp_zx1_ioc_init (u64 hpa)
 }
 
 static int
-hp_zx1_lba_find_capability (volatile u8 *hpa, int cap)
+hp_zx1_lba_find_capability (volatile u8 __iomem *hpa, int cap)
 {
 	u16 status;
 	u8 pos, id;
@@ -267,10 +267,10 @@ hp_zx1_cleanup (void)
 	if (hp->ioc_regs) {
 		if (hp->io_pdir_owner)
 			OUTREG64(hp->ioc_regs, HP_ZX1_IBASE, 0);
-		iounmap((void *) hp->ioc_regs);
+		iounmap(hp->ioc_regs);
 	}
 	if (hp->lba_regs)
-		iounmap((void *) hp->lba_regs);
+		iounmap(hp->lba_regs);
 }
 
 static void
@@ -294,7 +294,7 @@ hp_zx1_create_gatt_table (void)
 		if (!hp->io_pdir) {
 			printk(KERN_ERR PFX "Couldn't allocate contiguous "
 				"memory for I/O PDIR\n");
-			hp->gatt = 0;
+			hp->gatt = NULL;
 			hp->gatt_entries = 0;
 			return -ENOMEM;
 		}
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index f04527540..7bec505ad 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -69,7 +69,7 @@ static struct gatt_mask intel_i810_masks[] =
 
 static struct _intel_i810_private {
 	struct pci_dev *i810_dev;	/* device one */
-	volatile u8 *registers;
+	volatile u8 __iomem *registers;
 	int num_dcache_entries;
 } intel_i810_private;
 
@@ -111,7 +111,7 @@ static int intel_i810_configure(void)
 	pci_read_config_dword(intel_i810_private.i810_dev, I810_MMADDR, &temp);
 	temp &= 0xfff80000;
 
-	intel_i810_private.registers = (volatile u8 *) ioremap(temp, 128 * 4096);
+	intel_i810_private.registers = ioremap(temp, 128 * 4096);
 	if (!intel_i810_private.registers) {
 		printk(KERN_ERR PFX "Unable to remap memory.\n");
 		return -ENOMEM;
@@ -142,7 +142,7 @@ static int intel_i810_configure(void)
 static void intel_i810_cleanup(void)
 {
 	OUTREG32(intel_i810_private.registers, I810_PGETBL_CTL, 0);
-	iounmap((void *) intel_i810_private.registers);
+	iounmap(intel_i810_private.registers);
 }
 
 static void intel_i810_tlbflush(struct agp_memory *mem)
@@ -162,11 +162,11 @@ static void *i8xx_alloc_pages(void)
 
 	page = alloc_pages(GFP_KERNEL, 2);
 	if (page == NULL) {
-		return 0;
+		return NULL;
 	}
 	if (change_page_attr(page, 4, PAGE_KERNEL_NOCACHE) < 0) {
-		__free_page(page); 
-		return 0;
+		__free_page(page);
+		return NULL;
 	}
 	get_page(page);
 	SetPageLocked(page);
@@ -180,7 +180,7 @@ static void i8xx_destroy_pages(void *addr)
 
 	if (addr == NULL)
 		return;
-	
+
 	page = virt_to_page(addr);
 	change_page_attr(page, 4, PAGE_KERNEL);
 	put_page(page);
@@ -202,7 +202,7 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
 		return -EINVAL;
 	}
 	for (j = pg_start; j < (pg_start + mem->page_count); j++) {
-		if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j]))
+		if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j)))
 			return -EBUSY;
 	}
 
@@ -330,7 +330,7 @@ static void intel_i810_free_by_type(struct agp_memory *curr)
 		if (curr->page_count == 4)
 			i8xx_destroy_pages(phys_to_virt(curr->memory[0]));
 		else
-	   		agp_bridge->driver->agp_destroy_page(
+			agp_bridge->driver->agp_destroy_page(
 				 phys_to_virt(curr->memory[0]));
 		vfree(curr->memory);
 	}
@@ -353,8 +353,8 @@ static struct aper_size_info_fixed intel_i830_sizes[] =
 
 static struct _intel_i830_private {
 	struct pci_dev *i830_dev;		/* device one */
-	volatile u8 *registers;
-	volatile u32 *gtt;		/* I915G */
+	volatile u8 __iomem *registers;
+	volatile u32 __iomem *gtt;		/* I915G */
 	int gtt_entries;
 } intel_i830_private;
 
@@ -371,7 +371,7 @@ static void intel_i830_init_gtt_entries(void)
 
 	/* We obtain the size of the GTT, which is also stored (for some
 	 * reason) at the top of stolen memory. Then we add 4KB to that
- 	 * for the video BIOS popup, which is also stored in there. */
+	 * for the video BIOS popup, which is also stored in there. */
 	size = agp_bridge->driver->fetch_size() + 4;
 
 	if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
@@ -461,7 +461,7 @@ static int intel_i830_create_gatt_table(void)
 	pci_read_config_dword(intel_i830_private.i830_dev,I810_MMADDR,&temp);
 	temp &= 0xfff80000;
 
-	intel_i830_private.registers = (volatile u8 *) ioremap(temp,128 * 4096);
+	intel_i830_private.registers = ioremap(temp,128 * 4096);
 	if (!intel_i830_private.registers)
 		return (-ENOMEM);
 
@@ -544,7 +544,7 @@ static int intel_i830_configure(void)
 
 static void intel_i830_cleanup(void)
 {
-	iounmap((void *) intel_i830_private.registers);
+	iounmap(intel_i830_private.registers);
 }
 
 static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start,
@@ -649,8 +649,8 @@ static int intel_i915_configure(void)
 
 static void intel_i915_cleanup(void)
 {
-	iounmap((void *) intel_i830_private.gtt);
-	iounmap((void *) intel_i830_private.registers);
+	iounmap(intel_i830_private.gtt);
+	iounmap(intel_i830_private.registers);
 }
 
 static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
@@ -746,18 +746,18 @@ static int intel_i915_create_gatt_table(void)
 	size = agp_bridge->current_size;
 	page_order = size->page_order;
 	num_entries = size->num_entries;
-	agp_bridge->gatt_table_real = 0;
+	agp_bridge->gatt_table_real = NULL;
 
 	pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADDR, &temp);
 	pci_read_config_dword(intel_i830_private.i830_dev, I915_PTEADDR,&temp2);
 
-	intel_i830_private.gtt = (volatile u32 *) ioremap(temp2, 256 * 1024);
-	if (!intel_i830_private.gtt) 
+	intel_i830_private.gtt = ioremap(temp2, 256 * 1024);
+	if (!intel_i830_private.gtt)
 		return (-ENOMEM);
 
 	temp &= 0xfff80000;
 
-	intel_i830_private.registers = (volatile u8 *) ioremap(temp,128 * 4096);
+	intel_i830_private.registers = ioremap(temp,128 * 4096);
 	if (!intel_i830_private.registers)
 		return (-ENOMEM);
 
@@ -921,7 +921,7 @@ static int intel_815_configure(void)
 
 	/* aperture size */
 	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE,
-			current_size->size_value); 
+			current_size->size_value);
 
 	/* address to map to */
 	pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
@@ -933,7 +933,7 @@ static int intel_815_configure(void)
 	pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, addr);
 
 	/* agpctrl */
-	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); 
+	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
 
 	/* apcont */
 	pci_read_config_byte(agp_bridge->dev, INTEL_815_APCONT, &temp2);
@@ -956,7 +956,7 @@ static void intel_820_cleanup(void)
 
 	previous_size = A_SIZE_8(agp_bridge->previous_size);
 	pci_read_config_byte(agp_bridge->dev, INTEL_I820_RDCR, &temp);
-	pci_write_config_byte(agp_bridge->dev, INTEL_I820_RDCR, 
+	pci_write_config_byte(agp_bridge->dev, INTEL_I820_RDCR,
 			temp & ~(1 << 1));
 	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE,
 			previous_size->size_value);
@@ -966,23 +966,23 @@ static void intel_820_cleanup(void)
 static int intel_820_configure(void)
 {
 	u32 temp;
- 	u8 temp2; 
+	u8 temp2;
 	struct aper_size_info_8 *current_size;
 
 	current_size = A_SIZE_8(agp_bridge->current_size);
 
 	/* aperture size */
-	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); 
+	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
 
 	/* address to map to */
 	pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
 	agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
 
 	/* attbase - aperture base */
-	pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr); 
+	pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
 
 	/* agpctrl */
-	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); 
+	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
 
 	/* global enable aperture access */
 	/* This flag is not accessed through MCHCFG register as in */
@@ -990,7 +990,7 @@ static int intel_820_configure(void)
 	pci_read_config_byte(agp_bridge->dev, INTEL_I820_RDCR, &temp2);
 	pci_write_config_byte(agp_bridge->dev, INTEL_I820_RDCR, temp2 | (1 << 1));
 	/* clear any possible AGP-related error conditions */
-	pci_write_config_word(agp_bridge->dev, INTEL_I820_ERRSTS, 0x001c); 
+	pci_write_config_word(agp_bridge->dev, INTEL_I820_ERRSTS, 0x001c);
 	return 0;
 }
 
@@ -1003,23 +1003,23 @@ static int intel_840_configure(void)
 	current_size = A_SIZE_8(agp_bridge->current_size);
 
 	/* aperture size */
-	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); 
+	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
 
 	/* address to map to */
 	pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
 	agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
 
 	/* attbase - aperture base */
-	pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr); 
+	pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
 
 	/* agpctrl */
-	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); 
+	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
 
 	/* mcgcfg */
 	pci_read_config_word(agp_bridge->dev, INTEL_I840_MCHCFG, &temp2);
 	pci_write_config_word(agp_bridge->dev, INTEL_I840_MCHCFG, temp2 | (1 << 9));
 	/* clear any possible error conditions */
-	pci_write_config_word(agp_bridge->dev, INTEL_I840_ERRSTS, 0xc000); 
+	pci_write_config_word(agp_bridge->dev, INTEL_I840_ERRSTS, 0xc000);
 	return 0;
 }
 
@@ -1032,23 +1032,23 @@ static int intel_845_configure(void)
 	current_size = A_SIZE_8(agp_bridge->current_size);
 
 	/* aperture size */
-	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); 
+	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
 
 	/* address to map to */
 	pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
 	agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
 
 	/* attbase - aperture base */
-	pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr); 
+	pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
 
 	/* agpctrl */
-	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); 
+	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
 
 	/* agpm */
 	pci_read_config_byte(agp_bridge->dev, INTEL_I845_AGPM, &temp2);
 	pci_write_config_byte(agp_bridge->dev, INTEL_I845_AGPM, temp2 | (1 << 1));
 	/* clear any possible error conditions */
-	pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c); 
+	pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c);
 	return 0;
 }
 
@@ -1061,23 +1061,23 @@ static int intel_850_configure(void)
 	current_size = A_SIZE_8(agp_bridge->current_size);
 
 	/* aperture size */
-	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); 
+	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
 
 	/* address to map to */
 	pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
 	agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
 
 	/* attbase - aperture base */
-	pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr); 
+	pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
 
 	/* agpctrl */
-	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); 
+	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000);
 
 	/* mcgcfg */
 	pci_read_config_word(agp_bridge->dev, INTEL_I850_MCHCFG, &temp2);
 	pci_write_config_word(agp_bridge->dev, INTEL_I850_MCHCFG, temp2 | (1 << 9));
 	/* clear any possible AGP-related error conditions */
-	pci_write_config_word(agp_bridge->dev, INTEL_I850_ERRSTS, 0x001c); 
+	pci_write_config_word(agp_bridge->dev, INTEL_I850_ERRSTS, 0x001c);
 	return 0;
 }
 
@@ -1163,7 +1163,7 @@ static int intel_7505_configure(void)
 	/* mchcfg */
 	pci_read_config_word(agp_bridge->dev, INTEL_I7505_MCHCFG, &temp2);
 	pci_write_config_word(agp_bridge->dev, INTEL_I7505_MCHCFG, temp2 | (1 << 9));
-	
+
 	return 0;
 }
 
@@ -1178,7 +1178,7 @@ static struct aper_size_info_8 intel_815_sizes[2] =
 	{64, 16384, 4, 0},
 	{32, 8192, 3, 8},
 };
-	
+
 static struct aper_size_info_8 intel_8xx_sizes[7] =
 {
 	{256, 65536, 6, 0},
@@ -1201,7 +1201,7 @@ static struct aper_size_info_16 intel_generic_sizes[7] =
 	{4, 1024, 0, 63}
 };
 
-static struct aper_size_info_8 intel_830mp_sizes[4] = 
+static struct aper_size_info_8 intel_830mp_sizes[4] =
 {
 	{256, 65536, 6, 0},
 	{128, 32768, 5, 32},
@@ -1283,7 +1283,7 @@ static struct agp_bridge_driver intel_830_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= intel_i830_sizes,
 	.size_type		= FIXED_APER_SIZE,
-	.num_aperture_sizes 	= 3,
+	.num_aperture_sizes	= 3,
 	.needs_scratch_page	= TRUE,
 	.configure		= intel_i830_configure,
 	.fetch_size		= intel_i830_fetch_size,
@@ -1445,7 +1445,7 @@ static struct agp_bridge_driver intel_915_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= intel_i830_sizes,
 	.size_type		= FIXED_APER_SIZE,
-	.num_aperture_sizes 	= 3,
+	.num_aperture_sizes	= 3,
 	.needs_scratch_page	= TRUE,
 	.configure		= intel_i915_configure,
 	.fetch_size		= intel_i915_fetch_size,
@@ -1489,18 +1489,13 @@ static struct agp_bridge_driver intel_7505_driver = {
 	.agp_destroy_page	= agp_generic_destroy_page,
 };
 
-static int find_i810(u16 device, const char *name)
+static int find_i810(u16 device)
 {
 	struct pci_dev *i810_dev;
 
 	i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, device, NULL);
-	if (!i810_dev) {
-		printk(KERN_ERR PFX "Detected an Intel %s Chipset, "
-				"but could not find the secondary device.\n",
-				name);
+	if (!i810_dev)
 		return 0;
-	}
-
 	intel_i810_private.i810_dev = i810_dev;
 	return 1;
 }
@@ -1550,29 +1545,29 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
 		name = "440GX";
 		break;
 	case PCI_DEVICE_ID_INTEL_82810_MC1:
-		if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG1, "i810"))
+		name = "i810";
+		if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG1))
 			goto fail;
 		bridge->driver = &intel_810_driver;
-		name = "i810";
 		break;
 	case PCI_DEVICE_ID_INTEL_82810_MC3:
-		if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG3, "i810 DC100"))
+		name = "i810 DC100";
+		if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG3))
 			goto fail;
 		bridge->driver = &intel_810_driver;
-		name = "i810 DC100";
 		break;
 	case PCI_DEVICE_ID_INTEL_82810E_MC:
-		if (!find_i810(PCI_DEVICE_ID_INTEL_82810E_IG, "i810 E"))
+		name = "i810 E";
+		if (!find_i810(PCI_DEVICE_ID_INTEL_82810E_IG))
 			goto fail;
 		bridge->driver = &intel_810_driver;
-		name = "i810 E";
 		break;
 	 case PCI_DEVICE_ID_INTEL_82815_MC:
 		/*
 		 * The i815 can operate either as an i810 style
 		 * integrated device, or as an AGP4X motherboard.
 		 */
-		if (find_i810(PCI_DEVICE_ID_INTEL_82815_CGC, "i815"))
+		if (find_i810(PCI_DEVICE_ID_INTEL_82815_CGC))
 			bridge->driver = &intel_810_driver;
 		else
 			bridge->driver = &intel_815_driver;
@@ -1708,7 +1703,10 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
 
 	pci_set_drvdata(pdev, bridge);
 	return agp_add_bridge(bridge);
- fail:
+
+fail:
+	printk(KERN_ERR PFX "Detected an Intel %s chipset, "
+		"but could not find the secondary device.\n", name);
 	agp_put_bridge(bridge);
 	return -ENODEV;
 }
@@ -1724,7 +1722,7 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev)
 static int agp_intel_resume(struct pci_dev *pdev)
 {
 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
-	
+
 	pci_restore_state(pdev, pdev->saved_config_space);
 
 	if (bridge->driver == &intel_generic_driver)
@@ -1741,7 +1739,7 @@ static int agp_intel_resume(struct pci_dev *pdev)
 
 static struct pci_device_id agp_intel_pci_table[] = {
 #define ID(x)						\
-	{ 						\
+	{						\
 	.class		= (PCI_CLASS_BRIDGE_HOST << 8),	\
 	.class_mask	= ~0,				\
 	.vendor		= PCI_VENDOR_ID_INTEL,		\
@@ -1769,7 +1767,8 @@ static struct pci_device_id agp_intel_pci_table[] = {
 	ID(PCI_DEVICE_ID_INTEL_82865_HB),
 	ID(PCI_DEVICE_ID_INTEL_82875_HB),
 	ID(PCI_DEVICE_ID_INTEL_7505_0),
-	ID(PCI_DEVICE_ID_INTEL_7205_0),	
+	ID(PCI_DEVICE_ID_INTEL_7205_0),
+	ID(PCI_DEVICE_ID_INTEL_82915G_HB),
 	{ }
 };
 
@@ -1779,7 +1778,7 @@ static struct pci_driver agp_intel_pci_driver = {
 	.name		= "agpgart-intel",
 	.id_table	= agp_intel_pci_table,
 	.probe		= agp_intel_probe,
-	.remove		= agp_intel_remove,
+	.remove		= __devexit_p(agp_intel_remove),
 	.resume		= agp_intel_resume,
 };
 
diff --git a/drivers/char/agp/intel-mch-agp.c b/drivers/char/agp/intel-mch-agp.c
index c8f230acc..fd1d1ac1a 100644
--- a/drivers/char/agp/intel-mch-agp.c
+++ b/drivers/char/agp/intel-mch-agp.c
@@ -84,7 +84,7 @@ static struct aper_size_info_fixed intel_i830_sizes[] =
 
 static struct _intel_i830_private {
 	struct pci_dev *i830_dev;		/* device one */
-	volatile u8 *registers;
+	volatile u8 __iomem *registers;
 	int gtt_entries;
 } intel_i830_private;
 
@@ -172,7 +172,7 @@ static int intel_i830_create_gatt_table(void)
 	pci_read_config_dword(intel_i830_private.i830_dev,I810_MMADDR,&temp);
 	temp &= 0xfff80000;
 
-	intel_i830_private.registers = (volatile u8 *) ioremap(temp,128 * 4096);
+	intel_i830_private.registers = (volatile u8 __iomem*) ioremap(temp,128 * 4096);
 	if (!intel_i830_private.registers)
 		return (-ENOMEM);
 
@@ -255,7 +255,7 @@ static int intel_i830_configure(void)
 
 static void intel_i830_cleanup(void)
 {
-	iounmap((void *) intel_i830_private.registers);
+	iounmap((void __iomem *) intel_i830_private.registers);
 }
 
 static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start,
@@ -633,5 +633,5 @@ module_init(agp_intelmch_init);
 module_exit(agp_intelmch_cleanup);
 
 MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
-MODULE_LICENSE("GPL and additional rights");
+MODULE_LICENSE("GPL");
 
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
index 28e7fc4bc..16d8bdcb4 100644
--- a/drivers/char/agp/nvidia-agp.c
+++ b/drivers/char/agp/nvidia-agp.c
@@ -28,7 +28,7 @@ static struct _nvidia_private {
 	struct pci_dev *dev_1;
 	struct pci_dev *dev_2;
 	struct pci_dev *dev_3;
-	volatile u32 *aperture;
+	volatile u32 __iomem *aperture;
 	int num_active_entries;
 	off_t pg_offset;
 	u32 wbc_mask;
@@ -154,7 +154,7 @@ static int nvidia_configure(void)
 
 	/* map aperture */
 	nvidia_private.aperture =
-		(volatile u32 *) ioremap(apbase, 33 * PAGE_SIZE);
+		(volatile u32 __iomem *) ioremap(apbase, 33 * PAGE_SIZE);
 
 	return 0;
 }
@@ -173,7 +173,7 @@ static void nvidia_cleanup(void)
 	pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_GARTCTRL, temp & ~(0x11));
 
 	/* unmap aperture */
-	iounmap((void *) nvidia_private.aperture);
+	iounmap((void __iomem *) nvidia_private.aperture);
 
 	/* restore previous aperture size */
 	previous_size = A_SIZE_8(agp_bridge->previous_size);
@@ -206,7 +206,7 @@ static int nvidia_insert_memory(struct agp_memory *mem, off_t pg_start, int type
 		return -EINVAL;
 	
 	for(j = pg_start; j < (pg_start + mem->page_count); j++) {
-		if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[nvidia_private.pg_offset + j]))
+		if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+nvidia_private.pg_offset+j)))
 			return -EBUSY;
 	}
 
@@ -215,9 +215,8 @@ static int nvidia_insert_memory(struct agp_memory *mem, off_t pg_start, int type
 		mem->is_flushed = TRUE;
 	}
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++)
-		agp_bridge->gatt_table[nvidia_private.pg_offset + j] =
-				agp_bridge->driver->mask_memory(mem->memory[i], mem->type);
-
+		writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type),
+			agp_bridge->gatt_table+nvidia_private.pg_offset+j);
 	agp_bridge->driver->tlb_flush(mem);
 	return 0;
 }
@@ -229,11 +228,9 @@ static int nvidia_remove_memory(struct agp_memory *mem, off_t pg_start, int type
 
 	if ((type != 0) || (mem->type != 0))
 		return -EINVAL;
-	
-	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
-		agp_bridge->gatt_table[nvidia_private.pg_offset + i] =
-		    (unsigned long) agp_bridge->scratch_page;
-	}
+
+	for (i = pg_start; i < (mem->page_count + pg_start); i++)
+		writel(agp_bridge->scratch_page, agp_bridge->gatt_table+nvidia_private.pg_offset+i);
 
 	agp_bridge->driver->tlb_flush(mem);
 	return 0;
@@ -265,9 +262,9 @@ static void nvidia_tlbflush(struct agp_memory *mem)
 
 	/* flush TLB entries */
 	for(i = 0; i < 32 + 1; i++)
-		temp = nvidia_private.aperture[i * PAGE_SIZE / sizeof(u32)];
+		temp = readl(nvidia_private.aperture+(i * PAGE_SIZE / sizeof(u32)));
 	for(i = 0; i < 32 + 1; i++)
-		temp = nvidia_private.aperture[i * PAGE_SIZE / sizeof(u32)];
+		temp = readl(nvidia_private.aperture+(i * PAGE_SIZE / sizeof(u32)));
 }
 
 
diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
index 2a99c738f..019a31c36 100644
--- a/drivers/char/agp/sis-agp.c
+++ b/drivers/char/agp/sis-agp.c
@@ -168,6 +168,10 @@ static struct agp_device_ids sis_agp_device_ids[] __devinitdata =
 		.device_id	= PCI_DEVICE_ID_SI_630,
 		.chipset_name	= "630",
 	},
+	{
+		.device_id	= PCI_DEVICE_ID_SI_635,
+		.chipset_name	= "635",
+	},
 	{
 		.device_id	= PCI_DEVICE_ID_SI_645,
 		.chipset_name	= "645",
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index 44e11acbc..ae20fcaa4 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -27,12 +27,12 @@
 
 struct serverworks_page_map {
 	unsigned long *real;
-	unsigned long *remapped;
+	unsigned long __iomem *remapped;
 };
 
 static struct _serverworks_private {
 	struct pci_dev *svrwrks_dev;	/* device one */
-	volatile u8 *registers;
+	volatile u8 __iomem *registers;
 	struct serverworks_page_map **gatt_pages;
 	int num_tables;
 	struct serverworks_page_map scratch_dir;
@@ -61,9 +61,8 @@ static int serverworks_create_page_map(struct serverworks_page_map *page_map)
 	}
 	global_cache_flush();
 
-	for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) {
-		page_map->remapped[i] = agp_bridge->scratch_page;
-	}
+	for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++)
+		writel(agp_bridge->scratch_page, page_map->remapped+i);
 
 	return 0;
 }
@@ -162,10 +161,8 @@ static int serverworks_create_gatt_table(void)
 	}
 	/* Create a fake scratch directory */
 	for(i = 0; i < 1024; i++) {
-		serverworks_private.scratch_dir.remapped[i] = (unsigned long) agp_bridge->scratch_page;
-		page_dir.remapped[i] =
-			virt_to_phys(serverworks_private.scratch_dir.real);
-		page_dir.remapped[i] |= 0x00000001;
+		writel(agp_bridge->scratch_page, serverworks_private.scratch_dir.remapped+i);
+		writel(virt_to_phys(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i);
 	}
 
 	retval = serverworks_create_gatt_pages(value->num_entries / 1024);
@@ -176,7 +173,7 @@ static int serverworks_create_gatt_table(void)
 	}
 
 	agp_bridge->gatt_table_real = (u32 *)page_dir.real;
-	agp_bridge->gatt_table = (u32 *)page_dir.remapped;
+	agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped;
 	agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
 
 	/* Get the address for the gart region.
@@ -189,11 +186,8 @@ static int serverworks_create_gatt_table(void)
 
 	/* Calculate the agp offset */	
 
-	for(i = 0; i < value->num_entries / 1024; i++) {
-		page_dir.remapped[i] =
-			virt_to_phys(serverworks_private.gatt_pages[i]->real);
-		page_dir.remapped[i] |= 0x00000001;
-	}
+	for(i = 0; i < value->num_entries / 1024; i++)
+		writel(virt_to_phys(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i);
 
 	return 0;
 }
@@ -203,7 +197,7 @@ static int serverworks_free_gatt_table(void)
 	struct serverworks_page_map page_dir;
    
 	page_dir.real = (unsigned long *)agp_bridge->gatt_table_real;
-	page_dir.remapped = (unsigned long *)agp_bridge->gatt_table;
+	page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table;
 
 	serverworks_free_gatt_pages();
 	serverworks_free_page_map(&page_dir);
@@ -269,7 +263,7 @@ static int serverworks_configure(void)
 	/* Get the memory mapped registers */
 	pci_read_config_dword(agp_bridge->dev, serverworks_private.mm_addr_ofs, &temp);
 	temp = (temp & PCI_BASE_ADDRESS_MEM_MASK);
-	serverworks_private.registers = (volatile u8 *) ioremap(temp, 4096);
+	serverworks_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096);
 	if (!serverworks_private.registers) {
 		printk (KERN_ERR PFX "Unable to ioremap() memory.\n");
 		return -ENOMEM;
@@ -311,14 +305,14 @@ static int serverworks_configure(void)
 
 static void serverworks_cleanup(void)
 {
-	iounmap((void *) serverworks_private.registers);
+	iounmap((void __iomem *) serverworks_private.registers);
 }
 
 static int serverworks_insert_memory(struct agp_memory *mem,
 			     off_t pg_start, int type)
 {
 	int i, j, num_entries;
-	unsigned long *cur_gatt;
+	unsigned long __iomem *cur_gatt;
 	unsigned long addr;
 
 	num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
@@ -334,9 +328,8 @@ static int serverworks_insert_memory(struct agp_memory *mem,
 	while (j < (pg_start + mem->page_count)) {
 		addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = SVRWRKS_GET_GATT(addr);
-		if (!PGE_EMPTY(agp_bridge, cur_gatt[GET_GATT_OFF(addr)])) {
+		if (!PGE_EMPTY(agp_bridge, readl(cur_gatt+GET_GATT_OFF(addr))))
 			return -EBUSY;
-		}
 		j++;
 	}
 
@@ -348,8 +341,7 @@ static int serverworks_insert_memory(struct agp_memory *mem,
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = SVRWRKS_GET_GATT(addr);
-		cur_gatt[GET_GATT_OFF(addr)] =
-			agp_bridge->driver->mask_memory(mem->memory[i], mem->type);
+		writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
 	}
 	serverworks_tlbflush(mem);
 	return 0;
@@ -359,7 +351,7 @@ static int serverworks_remove_memory(struct agp_memory *mem, off_t pg_start,
 			     int type)
 {
 	int i;
-	unsigned long *cur_gatt;
+	unsigned long __iomem *cur_gatt;
 	unsigned long addr;
 
 	if (type != 0 || mem->type != 0) {
@@ -372,8 +364,7 @@ static int serverworks_remove_memory(struct agp_memory *mem, off_t pg_start,
 	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
 		addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = SVRWRKS_GET_GATT(addr);
-		cur_gatt[GET_GATT_OFF(addr)] = 
-			(unsigned long) agp_bridge->scratch_page;
+		writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr));
 	}
 
 	serverworks_tlbflush(mem);
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
index c619722e5..bcaea8ec3 100644
--- a/drivers/char/agp/via-agp.c
+++ b/drivers/char/agp/via-agp.c
@@ -438,6 +438,33 @@ static void __devexit agp_via_remove(struct pci_dev *pdev)
 	agp_put_bridge(bridge);
 }
 
+#ifdef CONFIG_PM
+
+static int agp_via_suspend(struct pci_dev *pdev, u32 state)
+{
+	pci_save_state (pdev, pdev->saved_config_space);
+	pci_set_power_state (pdev, 3);
+
+	return 0;
+}
+
+static int agp_via_resume(struct pci_dev *pdev)
+{
+	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
+
+	pci_set_power_state (pdev, 0);
+	pci_restore_state(pdev, pdev->saved_config_space);
+
+	if (bridge->driver == &via_agp3_driver)
+		return via_configure_agp3();
+	else if (bridge->driver == &via_driver)
+		return via_configure();
+
+	return 0;
+}
+
+#endif /* CONFIG_PM */
+
 /* must be the same order as name table above */
 static struct pci_device_id agp_via_pci_table[] = {
 #define ID(x) \
@@ -487,6 +514,10 @@ static struct pci_driver agp_via_pci_driver = {
 	.id_table	= agp_via_pci_table,
 	.probe		= agp_via_probe,
 	.remove		= agp_via_remove,
+#ifdef CONFIG_PM
+	.suspend	= agp_via_suspend,
+	.resume		= agp_via_resume,
+#endif
 };
 
 
@@ -503,5 +534,5 @@ static void __exit agp_via_cleanup(void)
 module_init(agp_via_init);
 module_exit(agp_via_cleanup);
 
-MODULE_LICENSE("GPL and additional rights");
+MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 3dc61d41b..f11cf4ea0 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -118,10 +118,6 @@ static struct serial_state rs_table[1];
 
 #define NR_PORTS	(sizeof(rs_table)/sizeof(struct serial_state))
 
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
 /*
  * tmp_buf is used as a temporary buffer by serial_write.  We need to
  * lock it in case the copy_from_user blocks while swapping in a page,
@@ -430,7 +426,7 @@ static _INLINE_ void check_modem_status(struct async_struct *info)
 
 	if ((info->flags & ASYNC_CHECK_CD) && (dstatus & SER_DCD)) {
 #if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
-		printk("ttyS%02d CD now %s...", info->line,
+		printk("ttyS%d CD now %s...", info->line,
 		       (!(status & SER_DCD)) ? "on" : "off");
 #endif
 		if (!(status & SER_DCD))
@@ -557,9 +553,7 @@ static void do_softint(unsigned long private_)
 		return;
 
 	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
+		tty_wakeup(tty);
 		wake_up_interruptible(&tty->write_wait);
 	}
 }
@@ -1023,9 +1017,7 @@ static void rs_flush_buffer(struct tty_struct *tty)
 	info->xmit.head = info->xmit.tail = 0;
 	local_irq_restore(flags);
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /*
@@ -1564,8 +1556,8 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
 	shutdown(info);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+		
+	tty_ldisc_flush(tty);
 	tty->closing = 0;
 	info->event = 0;
 	info->tty = 0;
@@ -1610,7 +1602,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
 	if (char_time == 0)
 		char_time = 1;
 	if (timeout)
-	  char_time = MIN(char_time, timeout);
+	  char_time = min_t(unsigned long, char_time, timeout);
 	/*
 	 * If the transmitter hasn't cleared in twice the approximate
 	 * amount of time to send the entire FIFO, it probably won't
@@ -2095,7 +2087,7 @@ static int __init rs_init(void)
 	  continue;
 	*/
 
-	printk(KERN_INFO "ttyS%02d is the amiga builtin serial port\n",
+	printk(KERN_INFO "ttyS%d is the amiga builtin serial port\n",
 		       state->line);
 
 	/* Hardware set up */
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index 0b2c40e94..148ea2932 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -89,7 +89,7 @@ MODULE_SUPPORTED_DEVICE("ac");
 
 static struct applicom_board {
 	unsigned long PhysIO;
-	unsigned long RamIO;
+	void __iomem *RamIO;
 	wait_queue_head_t FlagSleepSend;
 	long irq;
 	spinlock_t mutex;
@@ -127,7 +127,7 @@ static struct miscdevice ac_miscdev = {
 
 static int dummy;	/* dev_id for request_irq() */
 
-static int ac_register_board(unsigned long physloc, unsigned long loc, 
+static int ac_register_board(unsigned long physloc, void __iomem *loc, 
 		      unsigned char boardno)
 {
 	volatile unsigned char byte_reset_it;
@@ -179,11 +179,11 @@ void cleanup_module(void)
 
 		if (!apbs[i].RamIO)
 			continue;
-		
-		iounmap((void *) apbs[i].RamIO);
 
 		if (apbs[i].irq)
 			free_irq(apbs[i].irq, &dummy);
+
+		iounmap(apbs[i].RamIO);
 	}
 }
 
@@ -193,7 +193,7 @@ int __init applicom_init(void)
 {
 	int i, numisa = 0;
 	struct pci_dev *dev = NULL;
-	void *RamIO;
+	void __iomem *RamIO;
 	int boardno;
 
 	printk(KERN_INFO "Applicom driver: $Id: ac.c,v 1.30 2000/03/22 16:03:57 dwmw2 Exp $\n");
@@ -223,8 +223,8 @@ int __init applicom_init(void)
 		       applicom_pci_devnames[dev->device-1], dev->resource[0].start, 
 		       dev->irq);
 
-		if (!(boardno = ac_register_board(dev->resource[0].start,
-						  (unsigned long)RamIO,0))) {
+		boardno = ac_register_board(dev->resource[0].start, RamIO,0);
+		if (!boardno) {
 			printk(KERN_INFO "ac.o: PCI Applicom device doesn't have correct signature.\n");
 			iounmap(RamIO);
 			pci_disable_device(dev);
@@ -235,7 +235,7 @@ int __init applicom_init(void)
 			printk(KERN_INFO "Could not allocate IRQ %d for PCI Applicom device.\n", dev->irq);
 			iounmap(RamIO);
 			pci_disable_device(dev);
-			apbs[boardno - 1].RamIO = 0;
+			apbs[boardno - 1].RamIO = NULL;
 			continue;
 		}
 
@@ -270,7 +270,7 @@ int __init applicom_init(void)
 		}
 
 		if (!(boardno = ac_register_board((unsigned long)mem+ (LEN_RAM_IO*i),
-						  (unsigned long)RamIO,i+1))) {
+						  RamIO,i+1))) {
 			iounmap(RamIO);
 			continue;
 		}
@@ -280,8 +280,8 @@ int __init applicom_init(void)
 		if (!numisa) {
 			if (request_irq(irq, &ac_interrupt, SA_SHIRQ, "Applicom ISA", &dummy)) {
 				printk(KERN_WARNING "Could not allocate IRQ %d for ISA Applicom device.\n", irq);
-				iounmap((void *) RamIO);
-				apbs[boardno - 1].RamIO = 0;
+				iounmap(RamIO);
+				apbs[boardno - 1].RamIO = NULL;
 			}
 			else
 				apbs[boardno - 1].irq = irq;
@@ -449,7 +449,7 @@ static ssize_t ac_write(struct file *file, const char __user *buf, size_t count,
 	   because it works with 2.2 still */
 	{
 		unsigned char *from = (unsigned char *) &tmpmailbox;
-		unsigned long to = (unsigned long) apbs[IndexCard].RamIO + RAM_FROM_PC;
+		void __iomem *to = apbs[IndexCard].RamIO + RAM_FROM_PC;
 		int c;
 
 		for (c = 0; c < sizeof(struct mailbox); c++)
@@ -470,7 +470,7 @@ static ssize_t ac_write(struct file *file, const char __user *buf, size_t count,
 static int do_ac_read(int IndexCard, char __user *buf,
 		struct st_ram_io *st_loc, struct mailbox *mailbox)
 {
-	unsigned long from = (unsigned long)apbs[IndexCard].RamIO + RAM_TO_PC;
+	void __iomem *from = apbs[IndexCard].RamIO + RAM_TO_PC;
 	unsigned char *to = (unsigned char *)&mailbox;
 #ifdef DEBUG
 	int c;
@@ -685,7 +685,7 @@ static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
 {				/* @ ADG ou ATO selon le cas */
 	int i;
 	unsigned char IndexCard;
-	unsigned long pmem;
+	void __iomem *pmem;
 	int ret = 0;
 	volatile unsigned char byte_reset_it;
 	struct st_ram_io *adgl;
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index e69dc6d00..6ceaee64b 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -682,13 +682,13 @@ static void cy_send_xchar (struct tty_struct *tty, char ch);
 #define IS_CYC_Z(card) ((card).num_chips == -1)
 
 #define Z_FPGA_CHECK(card) \
-    ((cy_readl(&((struct RUNTIME_9060 *) \
+    ((cy_readl(&((struct RUNTIME_9060 __iomem *) \
 		 ((card).ctl_addr))->init_ctrl) & (1<<17)) != 0)
 
-#define ISZLOADED(card)	(((ZO_V1==cy_readl(&((struct RUNTIME_9060 *) \
+#define ISZLOADED(card)	(((ZO_V1==cy_readl(&((struct RUNTIME_9060 __iomem *) \
 			((card).ctl_addr))->mail_box_0)) || \
 			Z_FPGA_CHECK(card)) && \
-			(ZFIRM_ID==cy_readl(&((struct FIRM_ID *) \
+			(ZFIRM_ID==cy_readl(&((struct FIRM_ID __iomem *) \
 			((card).base_addr+ID_ADDRESS))->signature)))
 
 #ifndef SERIAL_XMIT_SIZE
@@ -712,16 +712,16 @@ static struct tty_driver *cy_serial_driver;
    boot options line.  The form is "cyclades=address,address..."
 */
 
-static unsigned char *cy_isa_addresses[] = {
-        (unsigned char *) 0xD0000,
-        (unsigned char *) 0xD2000,
-        (unsigned char *) 0xD4000,
-        (unsigned char *) 0xD6000,
-        (unsigned char *) 0xD8000,
-        (unsigned char *) 0xDA000,
-        (unsigned char *) 0xDC000,
-        (unsigned char *) 0xDE000,
-        NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
+static unsigned int cy_isa_addresses[] = {
+        0xD0000,
+        0xD2000,
+        0xD4000,
+        0xD6000,
+        0xD8000,
+        0xDA000,
+        0xDC000,
+        0xDE000,
+        0,0,0,0,0,0,0,0
 };
 #define NR_ISA_ADDRS (sizeof(cy_isa_addresses)/sizeof(unsigned char*))
 
@@ -854,7 +854,7 @@ static void cy_start(struct tty_struct *);
 static void set_line_char(struct cyclades_port *);
 static int cyz_issue_cmd(struct cyclades_card *, uclong, ucchar, uclong);
 #ifdef CONFIG_ISA
-static unsigned detect_isa_irq (volatile ucchar *);
+static unsigned detect_isa_irq(void __iomem *);
 #endif /* CONFIG_ISA */
 
 static int cyclades_get_proc_info(char *, char **, off_t , int , int *, void *);
@@ -970,10 +970,7 @@ do_softint(void *private_)
 	wake_up_interruptible(&info->delta_msr_wait);
     }
     if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) {
-        if((tty->flags & (1<< TTY_DO_WRITE_WAKEUP))
-        && tty->ldisc.write_wakeup){
-            (tty->ldisc.write_wakeup)(tty);
-        }
+        tty_wakeup(tty);
         wake_up_interruptible(&tty->write_wait);
     }
 #ifdef Z_WAKE
@@ -995,7 +992,7 @@ do_softint(void *private_)
    This function is only called from inside spinlock-protected code.
  */
 static int
-cyy_issue_cmd(volatile ucchar *base_addr, u_char cmd, int index)
+cyy_issue_cmd(void __iomem *base_addr, u_char cmd, int index)
 {
   volatile int  i;
 
@@ -1011,7 +1008,7 @@ cyy_issue_cmd(volatile ucchar *base_addr, u_char cmd, int index)
     if (i == 100)	return (-1);
 
     /* Issue the new command */
-    cy_writeb((u_long)base_addr+(CyCCR<<index), cmd);
+    cy_writeb(base_addr+(CyCCR<<index), cmd);
 
     return(0);
 } /* cyy_issue_cmd */
@@ -1019,7 +1016,7 @@ cyy_issue_cmd(volatile ucchar *base_addr, u_char cmd, int index)
 #ifdef CONFIG_ISA
 /* ISA interrupt detection code */
 static unsigned 
-detect_isa_irq (volatile ucchar *address)
+detect_isa_irq(void __iomem *address)
 {
   int irq;
   unsigned long irqs, flags;
@@ -1030,7 +1027,7 @@ detect_isa_irq (volatile ucchar *address)
     irq = probe_irq_off(probe_irq_on());
 
     /* Clear interrupts on the board first */
-    cy_writeb((u_long)address + (Cy_ClrIntr<<index), 0);
+    cy_writeb(address + (Cy_ClrIntr<<index), 0);
 			      /* Cy_ClrIntr is 0x1800 */
 
     irqs = probe_irq_on();
@@ -1039,11 +1036,11 @@ detect_isa_irq (volatile ucchar *address)
 
     /* Enable the Tx interrupts on the CD1400 */
     local_irq_save(flags);
-	cy_writeb((u_long)address + (CyCAR<<index), 0);
+	cy_writeb(address + (CyCAR<<index), 0);
 	cyy_issue_cmd(address, CyCHAN_CTL|CyENB_XMTR, index);
 
-	cy_writeb((u_long)address + (CyCAR<<index), 0);
-	cy_writeb((u_long)address + (CySRER<<index), 
+	cy_writeb(address + (CyCAR<<index), 0);
+	cy_writeb(address + (CySRER<<index), 
 		cy_readb(address + (CySRER<<index)) | CyTxRdy);
     local_irq_restore(flags);
 
@@ -1056,12 +1053,12 @@ detect_isa_irq (volatile ucchar *address)
     /* Clean up */
     save_xir = (u_char) cy_readb(address + (CyTIR<<index));
     save_car = cy_readb(address + (CyCAR<<index));
-    cy_writeb((u_long)address + (CyCAR<<index), (save_xir & 0x3));
-    cy_writeb((u_long)address + (CySRER<<index),
+    cy_writeb(address + (CyCAR<<index), (save_xir & 0x3));
+    cy_writeb(address + (CySRER<<index),
 	cy_readb(address + (CySRER<<index)) & ~CyTxRdy);
-    cy_writeb((u_long)address + (CyTIR<<index), (save_xir & 0x3f));
-    cy_writeb((u_long)address + (CyCAR<<index), (save_car));
-    cy_writeb((u_long)address + (Cy_ClrIntr<<index), 0);
+    cy_writeb(address + (CyTIR<<index), (save_xir & 0x3f));
+    cy_writeb(address + (CyCAR<<index), (save_car));
+    cy_writeb(address + (Cy_ClrIntr<<index), 0);
 			      /* Cy_ClrIntr is 0x1800 */
 
     return (irq > 0)? irq : 0;
@@ -1079,7 +1076,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
   int status;
   struct cyclades_card *cinfo;
   struct cyclades_port *info;
-  volatile unsigned char *base_addr, *card_base_addr;
+  void __iomem *base_addr, *card_base_addr;
   int chip;
   int save_xir, channel, save_car;
   char data;
@@ -1098,7 +1095,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
         return IRQ_NONE; /* spurious interrupt */
     }
 
-    card_base_addr = (unsigned char *)cinfo->base_addr;
+    card_base_addr = cinfo->base_addr;
     index = cinfo->bus_index;
 
 
@@ -1110,8 +1107,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
     do{
         had_work = 0;
         for ( chip = 0 ; chip < cinfo->num_chips ; chip ++) {
-            base_addr = (unsigned char *)
-		       (cinfo->base_addr + (cy_chip_offset[chip]<<index));
+            base_addr = cinfo->base_addr + (cy_chip_offset[chip]<<index);
             too_many = 0;
             while ( (status = cy_readb(base_addr+(CySVRR<<index))) != 0x00) {
                 had_work++;
@@ -1135,7 +1131,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                     info = &cy_port[i];
                     info->last_active = jiffies;
                     save_car = cy_readb(base_addr+(CyCAR<<index));
-                    cy_writeb((u_long)base_addr+(CyCAR<<index), save_xir);
+                    cy_writeb(base_addr+(CyCAR<<index), save_xir);
 
                     /* if there is nowhere to put the data, discard it */
                     if(info->tty == 0){
@@ -1264,8 +1260,8 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                         schedule_delayed_work(&tty->flip.work, 1);
                     }
                     /* end of service */
-                    cy_writeb((u_long)base_addr+(CyRIR<<index), (save_xir & 0x3f));
-                    cy_writeb((u_long)base_addr+(CyCAR<<index), (save_car));
+                    cy_writeb(base_addr+(CyRIR<<index), (save_xir & 0x3f));
+                    cy_writeb(base_addr+(CyCAR<<index), (save_car));
 		    spin_unlock(&cinfo->card_lock);
                 }
 
@@ -1284,18 +1280,18 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                     channel = (u_short ) (save_xir & CyIRChannel);
                     i = channel + chip * 4 + cinfo->first_line;
                     save_car = cy_readb(base_addr+(CyCAR<<index));
-                    cy_writeb((u_long)base_addr+(CyCAR<<index), save_xir);
+                    cy_writeb(base_addr+(CyCAR<<index), save_xir);
 
                     /* validate the port# (as configured and open) */
                     if( (i < 0) || (NR_PORTS <= i) ){
-                        cy_writeb((u_long)base_addr+(CySRER<<index),
+                        cy_writeb(base_addr+(CySRER<<index),
                              cy_readb(base_addr+(CySRER<<index)) & ~CyTxRdy);
                         goto txend;
                     }
                     info = &cy_port[i];
                     info->last_active = jiffies;
                     if(info->tty == 0){
-                        cy_writeb((u_long)base_addr+(CySRER<<index),
+                        cy_writeb(base_addr+(CySRER<<index),
                              cy_readb(base_addr+(CySRER<<index)) & ~CyTxRdy);
                         goto txdone;
                     }
@@ -1305,7 +1301,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
                     if(info->x_char) { /* send special char */
                         outch = info->x_char;
-                        cy_writeb((u_long)base_addr+(CyTDR<<index), outch);
+                        cy_writeb(base_addr+(CyTDR<<index), outch);
                         char_count--;
 			info->icount.tx++;
                         info->x_char = 0;
@@ -1313,14 +1309,14 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
                     if (info->breakon || info->breakoff) {
 			if (info->breakon) {
-			    cy_writeb((u_long)base_addr + (CyTDR<<index), 0); 
-			    cy_writeb((u_long)base_addr + (CyTDR<<index), 0x81);
+			    cy_writeb(base_addr + (CyTDR<<index), 0); 
+			    cy_writeb(base_addr + (CyTDR<<index), 0x81);
 			    info->breakon = 0;
                             char_count -= 2;
 			}
 			if (info->breakoff) {
-			    cy_writeb((u_long)base_addr + (CyTDR<<index), 0); 
-			    cy_writeb((u_long)base_addr + (CyTDR<<index), 0x83);
+			    cy_writeb(base_addr + (CyTDR<<index), 0); 
+			    cy_writeb(base_addr + (CyTDR<<index), 0x83);
 			    info->breakoff = 0;
                             char_count -= 2;
 			}
@@ -1329,11 +1325,11 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                     while (char_count-- > 0){
 			if (!info->xmit_cnt){
 			    if (cy_readb(base_addr+(CySRER<<index))&CyTxMpty) {
-				cy_writeb((u_long)base_addr+(CySRER<<index),
+				cy_writeb(base_addr+(CySRER<<index),
 					  cy_readb(base_addr+(CySRER<<index)) &
 					  ~CyTxMpty);
 			    } else {
-				cy_writeb((u_long)base_addr+(CySRER<<index),
+				cy_writeb(base_addr+(CySRER<<index),
 					  ((cy_readb(base_addr+(CySRER<<index))
 					    & ~CyTxRdy)
 					   | CyTxMpty));
@@ -1341,13 +1337,13 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 			    goto txdone;
 			}
 			if (info->xmit_buf == 0){
-                            cy_writeb((u_long)base_addr+(CySRER<<index),
+                            cy_writeb(base_addr+(CySRER<<index),
 				cy_readb(base_addr+(CySRER<<index)) & 
 					~CyTxRdy);
                             goto txdone;
 			}
 			if (info->tty->stopped || info->tty->hw_stopped){
-                            cy_writeb((u_long)base_addr+(CySRER<<index),
+                            cy_writeb(base_addr+(CySRER<<index),
 				cy_readb(base_addr+(CySRER<<index)) & 
 					~CyTxRdy);
                             goto txdone;
@@ -1368,16 +1364,16 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                             info->xmit_cnt--;
                             info->xmit_tail = (info->xmit_tail + 1)
                                                       & (SERIAL_XMIT_SIZE - 1);
-                            cy_writeb((u_long)base_addr+(CyTDR<<index), outch);
+                            cy_writeb(base_addr+(CyTDR<<index), outch);
 			    info->icount.tx++;
                         }else{
                             if(char_count > 1){
                                 info->xmit_cnt--;
                                 info->xmit_tail = (info->xmit_tail + 1)
 						      & (SERIAL_XMIT_SIZE - 1);
-                                cy_writeb((u_long)base_addr+(CyTDR<<index), 
+                                cy_writeb(base_addr+(CyTDR<<index), 
 					  outch);
-                                cy_writeb((u_long)base_addr+(CyTDR<<index), 0);
+                                cy_writeb(base_addr+(CyTDR<<index), 0);
 				info->icount.tx++;
                                 char_count--;
                             }else{
@@ -1391,9 +1387,9 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                     }
         txend:
                     /* end of service */
-                    cy_writeb((u_long)base_addr+(CyTIR<<index), 
+                    cy_writeb(base_addr+(CyTIR<<index), 
 			      (save_xir & 0x3f));
-                    cy_writeb((u_long)base_addr+(CyCAR<<index), (save_car));
+                    cy_writeb(base_addr+(CyCAR<<index), (save_car));
 		    spin_unlock(&cinfo->card_lock);
                 }
 
@@ -1407,7 +1403,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 		                           + cinfo->first_line];
                     info->last_active = jiffies;
                     save_car = cy_readb(base_addr+(CyCAR<<index));
-                    cy_writeb((u_long)base_addr+(CyCAR<<index), save_xir);
+                    cy_writeb(base_addr+(CyCAR<<index), save_xir);
 
                     mdm_change = cy_readb(base_addr+(CyMISR<<index));
                     mdm_status = cy_readb(base_addr+(CyMSVR1<<index));
@@ -1442,7 +1438,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                                     /* cy_start isn't used
 				         because... !!! */
                                     info->tty->hw_stopped = 0;
-                                  cy_writeb((u_long)base_addr+(CySRER<<index),
+                                  cy_writeb(base_addr+(CySRER<<index),
                                        cy_readb(base_addr+(CySRER<<index)) | 
                                        CyTxRdy);
                                     cy_sched_event(info,
@@ -1453,7 +1449,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                                     /* cy_stop isn't used
 				         because ... !!! */
                                     info->tty->hw_stopped = 1;
-                                  cy_writeb((u_long)base_addr+(CySRER<<index),
+                                  cy_writeb(base_addr+(CySRER<<index),
                                        cy_readb(base_addr+(CySRER<<index)) & 
                                        ~CyTxRdy);
                                 }
@@ -1465,9 +1461,9 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                         }
                     }
                     /* end of service */
-                    cy_writeb((u_long)base_addr+(CyMIR<<index), 
+                    cy_writeb(base_addr+(CyMIR<<index), 
 			      (save_xir & 0x3f));
-                    cy_writeb((u_long)base_addr+(CyCAR<<index), save_car);
+                    cy_writeb(base_addr+(CyCAR<<index), save_car);
 		    spin_unlock(&cinfo->card_lock);
                 }
             }          /* end while status != 0 */
@@ -1476,7 +1472,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
    /* clear interrupts */
    spin_lock(&cinfo->card_lock);
-   cy_writeb((u_long)card_base_addr + (Cy_ClrIntr<<index), 0);
+   cy_writeb(card_base_addr + (Cy_ClrIntr<<index), 0);
                                 /* Cy_ClrIntr is 0x1800 */
    spin_unlock(&cinfo->card_lock);
    return IRQ_HANDLED;
@@ -1491,27 +1487,25 @@ static int
 cyz_fetch_msg( struct cyclades_card *cinfo,
 	    uclong *channel, ucchar *cmd, uclong *param)
 {
-  struct FIRM_ID *firm_id;
-  struct ZFW_CTRL *zfw_ctrl;
-  struct BOARD_CTRL *board_ctrl;
+  struct FIRM_ID __iomem *firm_id;
+  struct ZFW_CTRL __iomem *zfw_ctrl;
+  struct BOARD_CTRL __iomem *board_ctrl;
   unsigned long loc_doorbell;
 
-    firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);
+    firm_id = cinfo->base_addr + ID_ADDRESS;
     if (!ISZLOADED(*cinfo)){
 	return (-1);
     }
-    zfw_ctrl = (struct ZFW_CTRL *)
-		(cinfo->base_addr + 
-		 (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
+    zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
     board_ctrl = &zfw_ctrl->board_ctrl;
 
-    loc_doorbell = cy_readl(&((struct RUNTIME_9060 *)
+    loc_doorbell = cy_readl(&((struct RUNTIME_9060 __iomem *)
                      (cinfo->ctl_addr))->loc_doorbell);
     if (loc_doorbell){
 	*cmd = (char)(0xff & loc_doorbell);
 	*channel = cy_readl(&board_ctrl->fwcmd_channel);
 	*param = (uclong)cy_readl(&board_ctrl->fwcmd_param);
-	cy_writel(&((struct RUNTIME_9060 *)(cinfo->ctl_addr))->loc_doorbell, 
+	cy_writel(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->loc_doorbell, 
                  0xffffffff);
 	return 1;
     }
@@ -1522,40 +1516,38 @@ static int
 cyz_issue_cmd( struct cyclades_card *cinfo,
 	    uclong channel, ucchar cmd, uclong param)
 {
-  struct FIRM_ID *firm_id;
-  struct ZFW_CTRL *zfw_ctrl;
-  struct BOARD_CTRL *board_ctrl;
-  volatile uclong *pci_doorbell;
+  struct FIRM_ID __iomem *firm_id;
+  struct ZFW_CTRL __iomem *zfw_ctrl;
+  struct BOARD_CTRL __iomem *board_ctrl;
+  unsigned long __iomem *pci_doorbell;
   int index;
 
-    firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);
+    firm_id = cinfo->base_addr + ID_ADDRESS;
     if (!ISZLOADED(*cinfo)){
 	return (-1);
     }
-    zfw_ctrl = (struct ZFW_CTRL *)
-		(cinfo->base_addr + 
-		 (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
+    zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
     board_ctrl = &zfw_ctrl->board_ctrl;
 
     index = 0;
-    pci_doorbell = (uclong *)(&((struct RUNTIME_9060 *)
-                               (cinfo->ctl_addr))->pci_doorbell);
+    pci_doorbell = &((struct RUNTIME_9060 __iomem *) (cinfo->ctl_addr))->pci_doorbell;
     while( (cy_readl(pci_doorbell) & 0xff) != 0){
         if (index++ == 1000){
 	    return((int)(cy_readl(pci_doorbell) & 0xff));
         }
 	udelay(50L);
     }
-    cy_writel((u_long)&board_ctrl->hcmd_channel, channel);
-    cy_writel((u_long)&board_ctrl->hcmd_param , param);
-    cy_writel((u_long)pci_doorbell, (long)cmd);
+    cy_writel(&board_ctrl->hcmd_channel, channel);
+    cy_writel(&board_ctrl->hcmd_param , param);
+    cy_writel(pci_doorbell, (long)cmd);
 
     return(0);
 } /* cyz_issue_cmd */
 
 static void
-cyz_handle_rx(struct cyclades_port *info, volatile struct CH_CTRL *ch_ctrl,
-	      volatile struct BUF_CTRL *buf_ctrl)
+cyz_handle_rx(struct cyclades_port *info,
+	      volatile struct CH_CTRL __iomem *ch_ctrl,
+	      volatile struct BUF_CTRL __iomem *buf_ctrl)
 {
   struct cyclades_card *cinfo = &cy_card[info->card];
   struct tty_struct *tty = info->tty;
@@ -1652,8 +1644,9 @@ cyz_handle_rx(struct cyclades_port *info, volatile struct CH_CTRL *ch_ctrl,
 }
 
 static void
-cyz_handle_tx(struct cyclades_port *info, volatile struct CH_CTRL *ch_ctrl,
-	      volatile struct BUF_CTRL *buf_ctrl)
+cyz_handle_tx(struct cyclades_port *info,
+	      volatile struct CH_CTRL __iomem *ch_ctrl,
+	      volatile struct BUF_CTRL __iomem *buf_ctrl)
 {
   struct cyclades_card *cinfo = &cy_card[info->card];
   struct tty_struct *tty = info->tty;
@@ -1740,11 +1733,11 @@ cyz_handle_cmd(struct cyclades_card *cinfo)
 {
   struct tty_struct *tty;
   struct cyclades_port *info;
-  static volatile struct FIRM_ID *firm_id;
-  static volatile struct ZFW_CTRL *zfw_ctrl;
-  static volatile struct BOARD_CTRL *board_ctrl;
-  static volatile struct CH_CTRL *ch_ctrl;
-  static volatile struct BUF_CTRL *buf_ctrl;
+  static volatile struct FIRM_ID __iomem *firm_id;
+  static volatile struct ZFW_CTRL __iomem *zfw_ctrl;
+  static volatile struct BOARD_CTRL __iomem *board_ctrl;
+  static volatile struct CH_CTRL __iomem *ch_ctrl;
+  static volatile struct BUF_CTRL __iomem *buf_ctrl;
   uclong channel;
   ucchar cmd;
   uclong param;
@@ -1752,13 +1745,11 @@ cyz_handle_cmd(struct cyclades_card *cinfo)
   int special_count;
   int delta_count;
 
-    firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);
-    zfw_ctrl = (struct ZFW_CTRL *)
-		(cinfo->base_addr + 
-		 (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
-    board_ctrl = &(zfw_ctrl->board_ctrl);
+    firm_id = cinfo->base_addr + ID_ADDRESS;
+    zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+    board_ctrl = &zfw_ctrl->board_ctrl;
     fw_ver = cy_readl(&board_ctrl->fw_version);
-    hw_ver = cy_readl(&((struct RUNTIME_9060 *)(cinfo->ctl_addr))->mail_box_0);
+    hw_ver = cy_readl(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->mail_box_0);
 
 
     while(cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) {
@@ -1925,10 +1916,8 @@ cyz_poll(unsigned long arg)
 	if (!IS_CYC_Z(*cinfo)) continue;
 	if (!ISZLOADED(*cinfo)) continue;
 
-	firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);
-	zfw_ctrl = (struct ZFW_CTRL *)
-		    (cinfo->base_addr + 
-		     (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
+	firm_id = cinfo->base_addr + ID_ADDRESS;
+	zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
 	board_ctrl = &(zfw_ctrl->board_ctrl);
 
 	/* Skip first polling cycle to avoid racing conditions with the FW */
@@ -1972,7 +1961,7 @@ startup(struct cyclades_port * info)
 {
   unsigned long flags;
   int retval = 0;
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int card,chip,channel,index;
   unsigned long page;
 
@@ -2011,8 +2000,7 @@ startup(struct cyclades_port * info)
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cy_card[card].bus_index;
-	base_addr = (unsigned char*)
-		   (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 #ifdef CY_DEBUG_OPEN
 	printk("cyc startup card %d, chip %d, channel %d, base_addr %lx\n",
@@ -2021,16 +2009,16 @@ startup(struct cyclades_port * info)
 
 	CY_LOCK(info, flags);
 
-	cy_writeb((ulong)base_addr+(CyCAR<<index), (u_char)channel);
+	cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
 
-	cy_writeb((ulong)base_addr+(CyRTPR<<index), (info->default_timeout
+	cy_writeb(base_addr+(CyRTPR<<index), (info->default_timeout
 		 ? info->default_timeout : 0x02)); /* 10ms rx timeout */
 
 	cyy_issue_cmd(base_addr,CyCHAN_CTL|CyENB_RCVR|CyENB_XMTR,index);
 
-	cy_writeb((ulong)base_addr+(CyCAR<<index), (u_char)channel);
-	cy_writeb((ulong)base_addr+(CyMSVR1<<index), CyRTS);
-	cy_writeb((ulong)base_addr+(CyMSVR2<<index), CyDTR);
+	cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
+	cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
+	cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
 
 #ifdef CY_DEBUG_DTR
 	printk("cyc:startup raising DTR\n");
@@ -2039,7 +2027,7 @@ startup(struct cyclades_port * info)
                 cy_readb(base_addr+(CyMSVR2<<index)));
 #endif
 
-	cy_writeb((u_long)base_addr+(CySRER<<index),
+	cy_writeb(base_addr+(CySRER<<index),
 		cy_readb(base_addr+(CySRER<<index)) | CyRxData);
 	info->flags |= ASYNC_INITIALIZED;
 
@@ -2056,22 +2044,20 @@ startup(struct cyclades_port * info)
 	CY_UNLOCK(info, flags);
 
     } else {
-      struct FIRM_ID *firm_id;
-      struct ZFW_CTRL *zfw_ctrl;
-      struct BOARD_CTRL *board_ctrl;
-      struct CH_CTRL *ch_ctrl;
+      struct FIRM_ID __iomem *firm_id;
+      struct ZFW_CTRL __iomem *zfw_ctrl;
+      struct BOARD_CTRL __iomem *board_ctrl;
+      struct CH_CTRL __iomem *ch_ctrl;
       int retval;
 
-	base_addr = (unsigned char*) (cy_card[card].base_addr);
+	base_addr = cy_card[card].base_addr;
 
-        firm_id = (struct FIRM_ID *) (base_addr + ID_ADDRESS);
+        firm_id = base_addr + ID_ADDRESS;
         if (!ISZLOADED(cy_card[card])){
 	    return -ENODEV;
 	}
 
-	zfw_ctrl = (struct ZFW_CTRL *)
-		    (cy_card[card].base_addr + 
-		     (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
+	zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
 	board_ctrl = &zfw_ctrl->board_ctrl;
 	ch_ctrl = zfw_ctrl->ch_ctrl;
 
@@ -2163,7 +2149,7 @@ static void
 start_xmit( struct cyclades_port *info )
 {
   unsigned long flags;
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int card,chip,channel,index;
 
     card = info->card;
@@ -2172,13 +2158,11 @@ start_xmit( struct cyclades_port *info )
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cy_card[card].bus_index;
-	base_addr = (unsigned char*)
-		       (cy_card[card].base_addr
-		       + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 	CY_LOCK(info, flags);
-	    cy_writeb((u_long)base_addr+(CyCAR<<index), channel);
-	    cy_writeb((u_long)base_addr+(CySRER<<index), 
+	    cy_writeb(base_addr+(CyCAR<<index), channel);
+	    cy_writeb(base_addr+(CySRER<<index), 
                cy_readb(base_addr+(CySRER<<index)) | CyTxRdy);
 	CY_UNLOCK(info, flags);
     } else {
@@ -2206,7 +2190,7 @@ static void
 shutdown(struct cyclades_port * info)
 {
   unsigned long flags;
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int card,chip,channel,index;
 
     if (!(info->flags & ASYNC_INITIALIZED)){
@@ -2219,9 +2203,7 @@ shutdown(struct cyclades_port * info)
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cy_card[card].bus_index;
-	base_addr = (unsigned char*)
-		       (cy_card[card].base_addr
-		       + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 #ifdef CY_DEBUG_OPEN
     printk("cyc shutdown Y card %d, chip %d, channel %d, base_addr %lx\n",
@@ -2239,10 +2221,10 @@ shutdown(struct cyclades_port * info)
 		info->xmit_buf = NULL;
 		free_page((unsigned long) temp);
 	    }
-	    cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
+	    cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
 	    if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
-		cy_writeb((u_long)base_addr+(CyMSVR1<<index), ~CyRTS);
-		cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
+		cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS);
+		cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR);
 #ifdef CY_DEBUG_DTR
 		printk("cyc shutdown dropping DTR\n");
 		printk("     status: 0x%x, 0x%x\n",
@@ -2260,27 +2242,25 @@ shutdown(struct cyclades_port * info)
 	    info->flags &= ~ASYNC_INITIALIZED;
 	CY_UNLOCK(info, flags);
     } else {
-      struct FIRM_ID *firm_id;
-      struct ZFW_CTRL *zfw_ctrl;
-      struct BOARD_CTRL *board_ctrl;
-      struct CH_CTRL *ch_ctrl;
+      struct FIRM_ID __iomem *firm_id;
+      struct ZFW_CTRL __iomem *zfw_ctrl;
+      struct BOARD_CTRL __iomem *board_ctrl;
+      struct CH_CTRL __iomem *ch_ctrl;
       int retval;
 
-	base_addr = (unsigned char*) (cy_card[card].base_addr);
+	base_addr = cy_card[card].base_addr;
 #ifdef CY_DEBUG_OPEN
     printk("cyc shutdown Z card %d, channel %d, base_addr %lx\n",
 		card, channel, (long)base_addr);
 #endif
 
-        firm_id = (struct FIRM_ID *) (base_addr + ID_ADDRESS);
+        firm_id = base_addr + ID_ADDRESS;
         if (!ISZLOADED(cy_card[card])) {
 	    return;
 	}
 
-	zfw_ctrl = (struct ZFW_CTRL *)
-		    (cy_card[card].base_addr + 
-		     (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
-	board_ctrl = &(zfw_ctrl->board_ctrl);
+	zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+	board_ctrl = &zfw_ctrl->board_ctrl;
 	ch_ctrl = zfw_ctrl->ch_ctrl;
 
 	CY_LOCK(info, flags);
@@ -2293,7 +2273,7 @@ shutdown(struct cyclades_port * info)
 	    }
 	    
 	    if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
-		cy_writel((u_long)&ch_ctrl[channel].rs_control,
+		cy_writel(&ch_ctrl[channel].rs_control,
                    (uclong)(cy_readl(&ch_ctrl[channel].rs_control) & 
                    ~(C_RS_RTS | C_RS_DTR)));
 		retval = cyz_issue_cmd(&cy_card[info->card],
@@ -2337,7 +2317,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
   unsigned long flags;
   int chip, channel,index;
   int retval;
-  char *base_addr;
+  void __iomem *base_addr;
 
     cinfo = &cy_card[info->card];
     channel = info->line - cinfo->first_line;
@@ -2390,15 +2370,14 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cinfo->bus_index;
-	base_addr = (char *)(cinfo->base_addr
-			    + (cy_chip_offset[chip]<<index));
+	base_addr = cinfo->base_addr + (cy_chip_offset[chip]<<index);
 
 	while (1) {
 	    CY_LOCK(info, flags);
 		if ((tty->termios->c_cflag & CBAUD)){
-		    cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
-		    cy_writeb((u_long)base_addr+(CyMSVR1<<index), CyRTS);
-		    cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
+		    cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
+		    cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
+		    cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
 #ifdef CY_DEBUG_DTR
 		    printk("cyc:block_til_ready raising DTR\n");
 		    printk("     status: 0x%x, 0x%x\n",
@@ -2417,7 +2396,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
 	    }
 
 	    CY_LOCK(info, flags);
-		cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
+		cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
 		if (!(info->flags & ASYNC_CLOSING)
 		&& (C_CLOCAL(tty)
 		    || (cy_readb(base_addr+(CyMSVR1<<index)) & CyDCD))) {
@@ -2437,23 +2416,21 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
 	    schedule();
 	}
     } else {
-      struct FIRM_ID *firm_id;
-      struct ZFW_CTRL *zfw_ctrl;
-      struct BOARD_CTRL *board_ctrl;
-      struct CH_CTRL *ch_ctrl;
+      struct FIRM_ID __iomem *firm_id;
+      struct ZFW_CTRL __iomem *zfw_ctrl;
+      struct BOARD_CTRL __iomem *board_ctrl;
+      struct CH_CTRL __iomem *ch_ctrl;
       int retval;
 
-	base_addr = (char *)(cinfo->base_addr);
-	firm_id = (struct FIRM_ID *)
-			(base_addr + ID_ADDRESS);
+	base_addr = cinfo->base_addr;
+	firm_id = base_addr + ID_ADDRESS;
         if (!ISZLOADED(*cinfo)){
             current->state = TASK_RUNNING;
 	    remove_wait_queue(&info->open_wait, &wait);
 	    return -EINVAL;
 	}
 
-	zfw_ctrl = (struct ZFW_CTRL *)
-		    (base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
+	zfw_ctrl = base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
 	board_ctrl = &zfw_ctrl->board_ctrl;
 	ch_ctrl = zfw_ctrl->ch_ctrl;
 
@@ -2543,11 +2520,10 @@ cy_open(struct tty_struct *tty, struct file * filp)
     */
     if (IS_CYC_Z(cy_card[info->card])) {
 	struct cyclades_card *cinfo = &cy_card[info->card];
-	struct FIRM_ID *firm_id = (struct FIRM_ID *)
-        	(cinfo->base_addr + ID_ADDRESS);
+	struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS;
 
         if (!ISZLOADED(*cinfo)) {
-	    if (((ZE_V1 ==cy_readl(&((struct RUNTIME_9060 *)
+	    if (((ZE_V1 ==cy_readl(&((struct RUNTIME_9060 __iomem *)
 		(cinfo->ctl_addr))->mail_box_0)) &&
 		Z_FPGA_CHECK (*cinfo)) &&
 		(ZFIRM_HLT == cy_readl (&firm_id->signature)))
@@ -2564,12 +2540,10 @@ cy_open(struct tty_struct *tty, struct file * filp)
 	       interrupts should be enabled as soon as the first open happens 
 	       to one of its ports. */
             if (!cinfo->intr_enabled) {
-		struct ZFW_CTRL *zfw_ctrl;
-		struct BOARD_CTRL *board_ctrl;
+		struct ZFW_CTRL __iomem *zfw_ctrl;
+		struct BOARD_CTRL __iomem *board_ctrl;
 
-		zfw_ctrl = (struct ZFW_CTRL *)
-		 (cinfo->base_addr +
-		  (cy_readl (&firm_id->zfwctrl_addr) & 0xfffff));
+		zfw_ctrl = cinfo->base_addr + (cy_readl (&firm_id->zfwctrl_addr) & 0xfffff);
 
 		board_ctrl = &zfw_ctrl->board_ctrl;
 
@@ -2661,7 +2635,7 @@ static void
 cy_wait_until_sent(struct tty_struct *tty, int timeout)
 {
   struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int card,chip,channel,index;
   unsigned long orig_jiffies;
   int char_time;
@@ -2711,8 +2685,7 @@ cy_wait_until_sent(struct tty_struct *tty, int timeout)
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cy_card[card].bus_index;
-	base_addr = (unsigned char *)
-		(cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 	while (cy_readb(base_addr+(CySRER<<index)) & CyTxRdy) {
 #ifdef CY_DEBUG_WAIT_UNTIL_SENT
 	    printk("Not clean (jiff=%lu)...", jiffies);
@@ -2805,13 +2778,11 @@ cy_close(struct tty_struct *tty, struct file *filp)
     if (!IS_CYC_Z(cy_card[info->card])) {
 	int channel = info->line - cy_card[info->card].first_line;
 	int index = cy_card[info->card].bus_index;
-	unsigned char *base_addr = (unsigned char *)
-			(cy_card[info->card].base_addr +
-			 (cy_chip_offset[channel>>2] <<index));
+	void __iomem *base_addr = cy_card[info->card].base_addr + (cy_chip_offset[channel>>2] << index);
 	/* Stop accepting input */
 	channel &= 0x03;
-	cy_writeb((ulong)base_addr+(CyCAR<<index), (u_char)channel);
-	cy_writeb((u_long)base_addr+(CySRER<<index),
+	cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
+	cy_writeb(base_addr+(CySRER<<index),
 			cy_readb(base_addr+(CySRER<<index)) & ~CyRxData);
 	if (info->flags & ASYNC_INITIALIZED) {
 	    /* Waiting for on-board buffers to be empty before closing 
@@ -2823,12 +2794,10 @@ cy_close(struct tty_struct *tty, struct file *filp)
     } else {
 #ifdef Z_WAKE
 	/* Waiting for on-board buffers to be empty before closing the port */
-	unsigned char *base_addr = (unsigned char *) 
-					cy_card[info->card].base_addr;
-	struct FIRM_ID *firm_id = (struct FIRM_ID *) (base_addr + ID_ADDRESS);
-	struct ZFW_CTRL *zfw_ctrl = (struct ZFW_CTRL *)
-		(base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
-	struct CH_CTRL *ch_ctrl = zfw_ctrl->ch_ctrl;
+	void __iomem *base_addr = cy_card[info->card].base_addr;
+	struct FIRM_ID __iomem *firm_id = base_addr + ID_ADDRESS;
+	struct ZFW_CTRL __iomem *zfw_ctrl = base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
+	struct CH_CTRL __iomem *ch_ctrl = zfw_ctrl->ch_ctrl;
 	int channel = info->line - cy_card[info->card].first_line;
 	int retval;
 
@@ -2850,8 +2819,7 @@ cy_close(struct tty_struct *tty, struct file *filp)
     shutdown(info);
     if (tty->driver->flush_buffer)
         tty->driver->flush_buffer(tty);
-    if (tty->ldisc.flush_buffer)
-        tty->ldisc.flush_buffer(tty);
+    tty_ldisc_flush(tty);        
     CY_LOCK(info, flags);
 
     tty->closing = 0;
@@ -3088,10 +3056,8 @@ cy_chars_in_buffer(struct tty_struct *tty)
 	int char_count;
 	volatile uclong tx_put, tx_get, tx_bufsize;
 
-	firm_id = (struct FIRM_ID *)(cy_card[card].base_addr + ID_ADDRESS);
-	zfw_ctrl = (struct ZFW_CTRL *)
-		    (cy_card[card].base_addr + 
-		     (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
+	firm_id = cy_card[card].base_addr + ID_ADDRESS;
+	zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
 	ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
 	buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
 
@@ -3151,7 +3117,7 @@ static void
 set_line_char(struct cyclades_port * info)
 {
   unsigned long flags;
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int card,chip,channel,index;
   unsigned cflag, iflag;
   unsigned short chip_number;
@@ -3303,76 +3269,74 @@ set_line_char(struct cyclades_port * info)
 
 	chip = channel>>2;
 	channel &= 0x03;
-	base_addr = (unsigned char*)
-		       (cy_card[card].base_addr
-		       + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 	CY_LOCK(info, flags);
-	    cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
+	    cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
 
 	   /* tx and rx baud rate */
 
-	    cy_writeb((u_long)base_addr+(CyTCOR<<index), info->tco);
-	    cy_writeb((u_long)base_addr+(CyTBPR<<index), info->tbpr);
-	    cy_writeb((u_long)base_addr+(CyRCOR<<index), info->rco);
-	    cy_writeb((u_long)base_addr+(CyRBPR<<index), info->rbpr);
+	    cy_writeb(base_addr+(CyTCOR<<index), info->tco);
+	    cy_writeb(base_addr+(CyTBPR<<index), info->tbpr);
+	    cy_writeb(base_addr+(CyRCOR<<index), info->rco);
+	    cy_writeb(base_addr+(CyRBPR<<index), info->rbpr);
 
 	    /* set line characteristics  according configuration */
 
-	    cy_writeb((u_long)base_addr+(CySCHR1<<index), 
+	    cy_writeb(base_addr+(CySCHR1<<index), 
 		      START_CHAR(info->tty));
-	    cy_writeb((u_long)base_addr+(CySCHR2<<index), 
+	    cy_writeb(base_addr+(CySCHR2<<index), 
 		      STOP_CHAR(info->tty));
-	    cy_writeb((u_long)base_addr+(CyCOR1<<index), info->cor1);
-	    cy_writeb((u_long)base_addr+(CyCOR2<<index), info->cor2);
-	    cy_writeb((u_long)base_addr+(CyCOR3<<index), info->cor3);
-	    cy_writeb((u_long)base_addr+(CyCOR4<<index), info->cor4);
-	    cy_writeb((u_long)base_addr+(CyCOR5<<index), info->cor5);
+	    cy_writeb(base_addr+(CyCOR1<<index), info->cor1);
+	    cy_writeb(base_addr+(CyCOR2<<index), info->cor2);
+	    cy_writeb(base_addr+(CyCOR3<<index), info->cor3);
+	    cy_writeb(base_addr+(CyCOR4<<index), info->cor4);
+	    cy_writeb(base_addr+(CyCOR5<<index), info->cor5);
 
 	    cyy_issue_cmd(base_addr,
 		     CyCOR_CHANGE|CyCOR1ch|CyCOR2ch|CyCOR3ch,index);
 
-	    cy_writeb((u_long)base_addr+(CyCAR<<index), 
+	    cy_writeb(base_addr+(CyCAR<<index), 
 		      (u_char)channel); /* !!! Is this needed? */
-	    cy_writeb((u_long)base_addr+(CyRTPR<<index), (info->default_timeout
+	    cy_writeb(base_addr+(CyRTPR<<index), (info->default_timeout
 					         ? info->default_timeout
 					         : 0x02)); /* 10ms rx timeout */
 
 	    if (C_CLOCAL(info->tty)) {
 		/* without modem intr */
-		cy_writeb((u_long)base_addr+(CySRER<<index),
+		cy_writeb(base_addr+(CySRER<<index),
                    cy_readb(base_addr+(CySRER<<index)) | CyMdmCh); 
 					/* act on 1->0 modem transitions */
                 if ((cflag & CRTSCTS) && info->rflow) {
-                        cy_writeb((u_long)base_addr+(CyMCOR1<<index), 
+                        cy_writeb(base_addr+(CyMCOR1<<index), 
                                   (CyCTS|rflow_thr[i]));
                 } else {
-                        cy_writeb((u_long)base_addr+(CyMCOR1<<index), CyCTS);
+                        cy_writeb(base_addr+(CyMCOR1<<index), CyCTS);
                 }
 					/* act on 0->1 modem transitions */
-		cy_writeb((u_long)base_addr+(CyMCOR2<<index), CyCTS);
+		cy_writeb(base_addr+(CyMCOR2<<index), CyCTS);
 	    } else {
 		/* without modem intr */
-		cy_writeb((u_long)base_addr+(CySRER<<index),
+		cy_writeb(base_addr+(CySRER<<index),
                    cy_readb(base_addr+(CySRER<<index)) | CyMdmCh); 
 					/* act on 1->0 modem transitions */
                 if ((cflag & CRTSCTS) && info->rflow) {
-			cy_writeb((u_long)base_addr+(CyMCOR1<<index), 
+			cy_writeb(base_addr+(CyMCOR1<<index), 
         	                  (CyDSR|CyCTS|CyRI|CyDCD|rflow_thr[i]));
                 } else {
-			cy_writeb((u_long)base_addr+(CyMCOR1<<index), 
+			cy_writeb(base_addr+(CyMCOR1<<index), 
                                   CyDSR|CyCTS|CyRI|CyDCD);
                 }
 					/* act on 0->1 modem transitions */
-		cy_writeb((u_long)base_addr+(CyMCOR2<<index), 
+		cy_writeb(base_addr+(CyMCOR2<<index), 
 			  CyDSR|CyCTS|CyRI|CyDCD);
 	    }
 
 	    if(i == 0){ /* baud rate is zero, turn off line */
 	        if (info->rtsdtr_inv) {
-			cy_writeb((u_long)base_addr+(CyMSVR1<<index), ~CyRTS);
+			cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS);
 		} else {
-                        cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
+                        cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR);
 		}
 #ifdef CY_DEBUG_DTR
 		printk("cyc:set_line_char dropping DTR\n");
@@ -3382,9 +3346,9 @@ set_line_char(struct cyclades_port * info)
 #endif
 	    }else{
                 if (info->rtsdtr_inv) {
-			cy_writeb((u_long)base_addr+(CyMSVR1<<index), CyRTS);
+			cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
                 } else {
-			cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
+			cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
                 }
 #ifdef CY_DEBUG_DTR
 		printk("cyc:set_line_char raising DTR\n");
@@ -3400,23 +3364,20 @@ set_line_char(struct cyclades_port * info)
 	CY_UNLOCK(info, flags);
 
     } else {
-      struct FIRM_ID *firm_id;
-      struct ZFW_CTRL *zfw_ctrl;
-      struct BOARD_CTRL *board_ctrl;
-      struct CH_CTRL *ch_ctrl;
-      struct BUF_CTRL *buf_ctrl;
+      struct FIRM_ID __iomem *firm_id;
+      struct ZFW_CTRL __iomem *zfw_ctrl;
+      struct BOARD_CTRL __iomem *board_ctrl;
+      struct CH_CTRL __iomem *ch_ctrl;
+      struct BUF_CTRL __iomem *buf_ctrl;
       uclong sw_flow;
       int retval;
 
-        firm_id = (struct FIRM_ID *)
-			(cy_card[card].base_addr + ID_ADDRESS);
+        firm_id = cy_card[card].base_addr + ID_ADDRESS;
         if (!ISZLOADED(cy_card[card])) {
 	    return;
 	}
 
-	zfw_ctrl = (struct ZFW_CTRL *)
-		    (cy_card[card].base_addr + 
-		     (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
+	zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
 	board_ctrl = &zfw_ctrl->board_ctrl;
 	ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
 	buf_ctrl = &zfw_ctrl->buf_ctrl[channel];
@@ -3617,7 +3578,7 @@ static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value)
     unsigned char status;
     unsigned int result;
     unsigned long flags;
-    unsigned char *base_addr;
+    void __iomem *base_addr;
 
     card = info->card;
     channel = (info->line) - (cy_card[card].first_line);
@@ -3625,8 +3586,7 @@ static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value)
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cy_card[card].bus_index;
-	base_addr = (unsigned char *)
-		     (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 	CY_LOCK(info, flags);
 	status = cy_readb(base_addr+(CySRER<<index)) & (CyTxRdy|CyTxMpty);
@@ -3644,15 +3604,15 @@ cy_tiocmget(struct tty_struct *tty, struct file *file)
 {
   struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
   int card,chip,channel,index;
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   unsigned long flags;
   unsigned char status;
   unsigned long lstatus;
   unsigned int result;
-  struct FIRM_ID *firm_id;
-  struct ZFW_CTRL *zfw_ctrl;
-  struct BOARD_CTRL *board_ctrl;
-  struct CH_CTRL *ch_ctrl;
+  struct FIRM_ID __iomem *firm_id;
+  struct ZFW_CTRL __iomem *zfw_ctrl;
+  struct BOARD_CTRL __iomem *board_ctrl;
+  struct CH_CTRL __iomem *ch_ctrl;
 
     if (serial_paranoia_check(info, tty->name, __FUNCTION__))
 	return -ENODEV;
@@ -3663,12 +3623,10 @@ cy_tiocmget(struct tty_struct *tty, struct file *file)
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cy_card[card].bus_index;
-	base_addr = (unsigned char*)
-		       (cy_card[card].base_addr
-		       + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 	CY_LOCK(info, flags);
-	    cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
+	    cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
 	    status = cy_readb(base_addr+(CyMSVR1<<index));
 	    status |= cy_readb(base_addr+(CyMSVR2<<index));
 	CY_UNLOCK(info, flags);
@@ -3685,18 +3643,15 @@ cy_tiocmget(struct tty_struct *tty, struct file *file)
 		 | ((status  & CyDSR) ? TIOCM_DSR : 0)
 		 | ((status  & CyCTS) ? TIOCM_CTS : 0);
     } else {
-	base_addr = (unsigned char*) (cy_card[card].base_addr);
+	base_addr = cy_card[card].base_addr;
 
         if (cy_card[card].num_chips != -1){
 	    return -EINVAL;
 	}
 
-	firm_id = (struct FIRM_ID *)
-		    (cy_card[card].base_addr + ID_ADDRESS);
+	firm_id = cy_card[card].base_addr + ID_ADDRESS;
         if (ISZLOADED(cy_card[card])) {
-	    zfw_ctrl = (struct ZFW_CTRL *)
-			(cy_card[card].base_addr + 
-			 (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
+	    zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
 	    board_ctrl = &zfw_ctrl->board_ctrl;
 	    ch_ctrl = zfw_ctrl->ch_ctrl;
 	    lstatus = cy_readl(&ch_ctrl[channel].rs_status);
@@ -3722,12 +3677,12 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
 {
   struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
   int card,chip,channel,index;
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   unsigned long flags;
-  struct FIRM_ID *firm_id;
-  struct ZFW_CTRL *zfw_ctrl;
-  struct BOARD_CTRL *board_ctrl;
-  struct CH_CTRL *ch_ctrl;
+  struct FIRM_ID __iomem *firm_id;
+  struct ZFW_CTRL __iomem *zfw_ctrl;
+  struct BOARD_CTRL __iomem *board_ctrl;
+  struct CH_CTRL __iomem *ch_ctrl;
   int retval;
 
     if (serial_paranoia_check(info, tty->name, __FUNCTION__))
@@ -3739,37 +3694,35 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cy_card[card].bus_index;
-	base_addr = (unsigned char*)
-		       (cy_card[card].base_addr
-		       + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 	if (set & TIOCM_RTS){
 		CY_LOCK(info, flags);
-	        cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
+	        cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
                 if (info->rtsdtr_inv) {
-			cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
+			cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
                 } else {
-			cy_writeb((u_long)base_addr+(CyMSVR1<<index), CyRTS);
+			cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
                 }
 		CY_UNLOCK(info, flags);
 	}
 	if (clear & TIOCM_RTS) {
 		CY_LOCK(info, flags);
-		cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
+		cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
                 if (info->rtsdtr_inv) {
-			cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
+			cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR);
                 } else {
-			cy_writeb((u_long)base_addr+(CyMSVR1<<index), ~CyRTS);
+			cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS);
                 }
 		CY_UNLOCK(info, flags);
 	}
 	if (set & TIOCM_DTR){
 		CY_LOCK(info, flags);
-		cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
+		cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
                 if (info->rtsdtr_inv) {
-			cy_writeb((u_long)base_addr+(CyMSVR1<<index), CyRTS);
+			cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
                 } else {
-			cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
+			cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
                 }
 #ifdef CY_DEBUG_DTR
 		printk("cyc:set_modem_info raising DTR\n");
@@ -3781,11 +3734,11 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
 	}
 	if (clear & TIOCM_DTR) {
 		CY_LOCK(info, flags);
-		cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
+		cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
                 if (info->rtsdtr_inv) {
-			cy_writeb((u_long)base_addr+(CyMSVR1<<index), ~CyRTS);
+			cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS);
                 } else {
-			cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
+			cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR);
                 }
 
 #ifdef CY_DEBUG_DTR
@@ -3797,14 +3750,11 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
 		CY_UNLOCK(info, flags);
 	}
     } else {
-	base_addr = (unsigned char*) (cy_card[card].base_addr);
+	base_addr = cy_card[card].base_addr;
 
-	firm_id = (struct FIRM_ID *)
-		    (cy_card[card].base_addr + ID_ADDRESS);
+	firm_id = cy_card[card].base_addr + ID_ADDRESS;
         if (ISZLOADED(cy_card[card])) {
-	    zfw_ctrl = (struct ZFW_CTRL *)
-			(cy_card[card].base_addr + 
-			 (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff));
+	    zfw_ctrl = cy_card[card].base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff);
 	    board_ctrl = &zfw_ctrl->board_ctrl;
 	    ch_ctrl = zfw_ctrl->ch_ctrl;
 
@@ -3930,7 +3880,7 @@ get_mon_info(struct cyclades_port * info, struct cyclades_monitor __user * mon)
 static int
 set_threshold(struct cyclades_port * info, unsigned long value)
 {
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int card,channel,chip,index;
   unsigned long flags;
    
@@ -3940,15 +3890,13 @@ set_threshold(struct cyclades_port * info, unsigned long value)
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cy_card[card].bus_index;
-	base_addr = (unsigned char*)
-		       (cy_card[card].base_addr
-		       + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 	info->cor3 &= ~CyREC_FIFO;
 	info->cor3 |= value & CyREC_FIFO;
 
 	CY_LOCK(info, flags);
-	    cy_writeb((u_long)base_addr+(CyCOR3<<index), info->cor3);
+	    cy_writeb(base_addr+(CyCOR3<<index), info->cor3);
 	    cyy_issue_cmd(base_addr,CyCOR_CHANGE|CyCOR3ch,index);
 	CY_UNLOCK(info, flags);
     } else {
@@ -3961,7 +3909,7 @@ set_threshold(struct cyclades_port * info, unsigned long value)
 static int
 get_threshold(struct cyclades_port * info, unsigned long __user *value)
 {
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int card,channel,chip,index;
   unsigned long tmp;
    
@@ -3971,9 +3919,7 @@ get_threshold(struct cyclades_port * info, unsigned long __user *value)
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cy_card[card].bus_index;
-	base_addr = (unsigned char*)
-		       (cy_card[card].base_addr
-		       + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 	tmp = cy_readb(base_addr+(CyCOR3<<index)) & CyREC_FIFO;
 	return put_user(tmp,value);
@@ -4002,7 +3948,7 @@ get_default_threshold(struct cyclades_port * info, unsigned long __user *value)
 static int
 set_timeout(struct cyclades_port * info, unsigned long value)
 {
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int card,channel,chip,index;
   unsigned long flags;
    
@@ -4012,12 +3958,10 @@ set_timeout(struct cyclades_port * info, unsigned long value)
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cy_card[card].bus_index;
-	base_addr = (unsigned char*)
-		       (cy_card[card].base_addr
-		       + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 	CY_LOCK(info, flags);
-	    cy_writeb((u_long)base_addr+(CyRTPR<<index), value & 0xff);
+	    cy_writeb(base_addr+(CyRTPR<<index), value & 0xff);
 	CY_UNLOCK(info, flags);
     } else {
 	// Nothing to do!
@@ -4029,7 +3973,7 @@ set_timeout(struct cyclades_port * info, unsigned long value)
 static int
 get_timeout(struct cyclades_port * info, unsigned long __user *value)
 {
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int card,channel,chip,index;
   unsigned long tmp;
    
@@ -4039,9 +3983,7 @@ get_timeout(struct cyclades_port * info, unsigned long __user *value)
 	chip = channel>>2;
 	channel &= 0x03;
 	index = cy_card[card].bus_index;
-	base_addr = (unsigned char*)
-		       (cy_card[card].base_addr
-		       + (cy_chip_offset[chip]<<index));
+	base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 	tmp = cy_readb(base_addr+(CyRTPR<<index));
 	return put_user(tmp,value);
@@ -4329,7 +4271,7 @@ cy_throttle(struct tty_struct * tty)
 {
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
   unsigned long flags;
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int card,chip,channel,index;
 
 #ifdef CY_DEBUG_THROTTLE
@@ -4359,16 +4301,14 @@ cy_throttle(struct tty_struct * tty)
             chip = channel>>2;
             channel &= 0x03;
             index = cy_card[card].bus_index;
-            base_addr = (unsigned char*)
-             (cy_card[card].base_addr
-               + (cy_chip_offset[chip]<<index));
+            base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
             CY_LOCK(info, flags);
-            cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
+            cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
             if (info->rtsdtr_inv) {
-                cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
+                cy_writeb(base_addr+(CyMSVR2<<index), ~CyDTR);
              } else {
-                cy_writeb((u_long)base_addr+(CyMSVR1<<index), ~CyRTS);
+                cy_writeb(base_addr+(CyMSVR1<<index), ~CyRTS);
 	     }
 	    CY_UNLOCK(info, flags);
 	} else {
@@ -4390,7 +4330,7 @@ cy_unthrottle(struct tty_struct * tty)
 {
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
   unsigned long flags;
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int card,chip,channel,index;
 
 #ifdef CY_DEBUG_THROTTLE
@@ -4419,16 +4359,14 @@ cy_unthrottle(struct tty_struct * tty)
 	    chip = channel>>2;
 	    channel &= 0x03;
 	    index = cy_card[card].bus_index;
-	    base_addr = (unsigned char*)
-         	       (cy_card[card].base_addr
-		       + (cy_chip_offset[chip]<<index));
+	    base_addr = cy_card[card].base_addr + (cy_chip_offset[chip]<<index);
 
 	    CY_LOCK(info, flags);
-	    cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
+	    cy_writeb(base_addr+(CyCAR<<index), (u_char)channel);
 	    if (info->rtsdtr_inv) {
-		    cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
+		    cy_writeb(base_addr+(CyMSVR2<<index), CyDTR);
 	    } else {
-		    cy_writeb((u_long)base_addr+(CyMSVR1<<index), CyRTS);
+		    cy_writeb(base_addr+(CyMSVR1<<index), CyRTS);
 	    }
 	    CY_UNLOCK(info, flags);
         } else {
@@ -4448,7 +4386,7 @@ cy_stop(struct tty_struct *tty)
 {
   struct cyclades_card *cinfo;
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int chip,channel,index;
   unsigned long flags;
 
@@ -4465,14 +4403,12 @@ cy_stop(struct tty_struct *tty)
         index = cinfo->bus_index;
         chip = channel>>2;
         channel &= 0x03;
-        base_addr = (unsigned char*)
-                   (cy_card[info->card].base_addr
-                           + (cy_chip_offset[chip]<<index));
+        base_addr = cy_card[info->card].base_addr + (cy_chip_offset[chip]<<index);
 
 	CY_LOCK(info, flags);
-            cy_writeb((u_long)base_addr+(CyCAR<<index),
+            cy_writeb(base_addr+(CyCAR<<index),
 	       (u_char)(channel & 0x0003)); /* index channel */
-            cy_writeb((u_long)base_addr+(CySRER<<index), 
+            cy_writeb(base_addr+(CySRER<<index), 
                cy_readb(base_addr+(CySRER<<index)) & ~CyTxRdy);
 	CY_UNLOCK(info, flags);
     } else {
@@ -4488,7 +4424,7 @@ cy_start(struct tty_struct *tty)
 {
   struct cyclades_card *cinfo;
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  unsigned char *base_addr;
+  void __iomem *base_addr;
   int chip,channel,index;
   unsigned long flags;
 
@@ -4505,14 +4441,12 @@ cy_start(struct tty_struct *tty)
     if (!IS_CYC_Z(*cinfo)) {
         chip = channel>>2;
         channel &= 0x03;
-        base_addr = (unsigned char*)
-                       (cy_card[info->card].base_addr
-		       + (cy_chip_offset[chip]<<index));
+        base_addr = cy_card[info->card].base_addr + (cy_chip_offset[chip]<<index);
 
 	CY_LOCK(info, flags);
-            cy_writeb((u_long)base_addr+(CyCAR<<index),
+            cy_writeb(base_addr+(CyCAR<<index),
 	       (u_char)(channel & 0x0003)); /* index channel */
-            cy_writeb((u_long)base_addr+(CySRER<<index), 
+            cy_writeb(base_addr+(CySRER<<index), 
                cy_readb(base_addr+(CySRER<<index)) | CyTxRdy);
 	CY_UNLOCK(info, flags);
     } else {
@@ -4554,10 +4488,8 @@ cy_flush_buffer(struct tty_struct *tty)
 	}
 	CY_UNLOCK(info, flags);
     }
+    tty_wakeup(tty);
     wake_up_interruptible(&tty->write_wait);
-    if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
-	&& tty->ldisc.write_wakeup)
-	    (tty->ldisc.write_wakeup)(tty);
 } /* cy_flush_buffer */
 
 
@@ -4600,20 +4532,19 @@ cy_hangup(struct tty_struct *tty)
 /* initialize chips on Cyclom-Y card -- return number of valid
    chips (which is number of ports/4) */
 static unsigned short __init
-cyy_init_card(volatile ucchar *true_base_addr,int index)
+cyy_init_card(void __iomem *true_base_addr,int index)
 {
   unsigned int chip_number;
-  volatile ucchar* base_addr;
+  void __iomem *base_addr;
 
-    cy_writeb((u_long)true_base_addr+(Cy_HwReset<<index), 0); 
+    cy_writeb(true_base_addr+(Cy_HwReset<<index), 0); 
 						/* Cy_HwReset is 0x1400 */
-    cy_writeb((u_long)true_base_addr+(Cy_ClrIntr<<index), 0); 
+    cy_writeb(true_base_addr+(Cy_ClrIntr<<index), 0); 
 						/* Cy_ClrIntr is 0x1800 */
     udelay(500L);
 
     for(chip_number=0; chip_number<CyMAX_CHIPS_PER_CARD; chip_number++){
-        base_addr = true_base_addr
-	               + (cy_chip_offset[chip_number]<<index);
+        base_addr = true_base_addr + (cy_chip_offset[chip_number]<<index);
         mdelay(1);
         if(cy_readb(base_addr+(CyCCR<<index)) != 0x00){
             /*************
@@ -4623,7 +4554,7 @@ cyy_init_card(volatile ucchar *true_base_addr,int index)
             return chip_number;
         }
 
-        cy_writeb((u_long)base_addr+(CyGFRCR<<index), 0);
+        cy_writeb(base_addr+(CyGFRCR<<index), 0);
         udelay(10L);
 
         /* The Cyclom-16Y does not decode address bit 9 and therefore
@@ -4639,7 +4570,7 @@ cyy_init_card(volatile ucchar *true_base_addr,int index)
             return chip_number;
         }
 
-        cy_writeb((u_long)base_addr+(CyCCR<<index), CyCHIP_RESET);
+        cy_writeb(base_addr+(CyCCR<<index), CyCHIP_RESET);
         mdelay(1);
 
         if(cy_readb(base_addr+(CyGFRCR<<index)) == 0x00){
@@ -4658,15 +4589,15 @@ cyy_init_card(volatile ucchar *true_base_addr,int index)
             */
             return chip_number;
         }
-        cy_writeb((u_long)base_addr+(CyGCR<<index), CyCH0_SERIAL);
+        cy_writeb(base_addr+(CyGCR<<index), CyCH0_SERIAL);
         if (cy_readb(base_addr+(CyGFRCR<<index)) >= CD1400_REV_J){
 	    /* It is a CD1400 rev. J or later */
 	    /* Impossible to reach 5ms with this chip. 
 	       Changed to 2ms instead (f = 500 Hz). */
-	    cy_writeb((u_long)base_addr+(CyPPR<<index), CyCLOCK_60_2MS);
+	    cy_writeb(base_addr+(CyPPR<<index), CyCLOCK_60_2MS);
 	} else {
 	    /* f = 200 Hz */
-	    cy_writeb((u_long)base_addr+(CyPPR<<index), CyCLOCK_25_5MS);
+	    cy_writeb(base_addr+(CyPPR<<index), CyCLOCK_25_5MS);
 	}
 
     /*
@@ -4689,7 +4620,7 @@ cy_detect_isa(void)
 {
 #ifdef CONFIG_ISA
   unsigned short	cy_isa_irq,nboard;
-  volatile ucchar	*cy_isa_address;
+  void __iomem		*cy_isa_address;
   unsigned short	i,j,cy_isa_nchan;
 #ifdef MODULE
   int isparam = 0;
@@ -4702,7 +4633,7 @@ cy_detect_isa(void)
 	for(i = 0 ; i < NR_CARDS; i++) {
 	    if (maddr[i] || i) {
 		isparam = 1;
-		cy_isa_addresses[i] = (ucchar *)maddr[i];
+		cy_isa_addresses[i] = maddr[i];
 	    }
 	    if (!maddr[i])
 		break;
@@ -4711,15 +4642,13 @@ cy_detect_isa(void)
 
         /* scan the address table probing for Cyclom-Y/ISA boards */
         for (i = 0 ; i < NR_ISA_ADDRS ; i++) {
-                cy_isa_address = cy_isa_addresses[i];
-                if (cy_isa_address  == 0x0000) {
+        	unsigned int isa_address = cy_isa_addresses[i];
+                if (isa_address  == 0x0000) {
                         return(nboard);
                 }
 
                 /* probe for CD1400... */
-#if !defined(__alpha__)
-		cy_isa_address = ioremap((ulong)cy_isa_address, CyISA_Ywin);
-#endif
+		cy_isa_address = ioremap(isa_address, CyISA_Ywin);
                 cy_isa_nchan = CyPORTS_PER_CHIP * 
                      cyy_init_card(cy_isa_address,0);
                 if (cy_isa_nchan == 0) {
@@ -4771,8 +4700,8 @@ cy_detect_isa(void)
                 }
 
                 /* set cy_card */
-                cy_card[j].base_addr = (u_long) cy_isa_address;
-                cy_card[j].ctl_addr = 0;
+                cy_card[j].base_addr = cy_isa_address;
+                cy_card[j].ctl_addr = NULL;
                 cy_card[j].irq = (int) cy_isa_irq;
                 cy_card[j].bus_index = 0;
                 cy_card[j].first_line = cy_next_channel;
@@ -4795,7 +4724,7 @@ cy_detect_isa(void)
 } /* cy_detect_isa */
 
 static void 
-plx_init(uclong addr, uclong initctl)
+plx_init(void __iomem *addr, uclong initctl)
 {
     /* Reset PLX */
     cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x40000000);
@@ -4823,11 +4752,12 @@ cy_detect_pci(void)
   unsigned char		cyy_rev_id;
   unsigned char		cy_pci_irq = 0;
   uclong		cy_pci_phys0, cy_pci_phys2;
-  uclong		cy_pci_addr0, cy_pci_addr2;
+  void __iomem		*cy_pci_addr0, *cy_pci_addr2;
   unsigned short	i,j,cy_pci_nchan, plx_ver;
   unsigned short	device_id,dev_index = 0;
   uclong		mailbox;
-  uclong		Ze_addr0[NR_CARDS], Ze_addr2[NR_CARDS], ZeIndex = 0;
+  uclong		ZeIndex = 0;
+  void __iomem		*Ze_addr0[NR_CARDS], *Ze_addr2[NR_CARDS];
   uclong		Ze_phys0[NR_CARDS], Ze_phys2[NR_CARDS];
   unsigned char		Ze_irq[NR_CARDS];
   struct pci_dev	*Ze_pdev[NR_CARDS];
@@ -4896,15 +4826,15 @@ cy_detect_pci(void)
 	            continue;
                 }
 #endif
-		cy_pci_addr0 = (ulong)ioremap(cy_pci_phys0, CyPCI_Yctl);
-		cy_pci_addr2 = (ulong)ioremap(cy_pci_phys2, CyPCI_Ywin);
+		cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Yctl);
+		cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Ywin);
 
 #ifdef CY_PCI_DEBUG
             printk("Cyclom-Y/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n",
 		(u_long)cy_pci_addr2, (u_long)cy_pci_addr0);
 #endif
                 cy_pci_nchan = (unsigned short)(CyPORTS_PER_CHIP * 
-                       cyy_init_card((volatile ucchar *)cy_pci_addr2, 1));
+                       cyy_init_card(cy_pci_addr2, 1));
                 if(cy_pci_nchan == 0) {
                         printk("Cyclom-Y PCI host card with ");
                         printk("no Serial-Modules at 0x%lx.\n",
@@ -4945,8 +4875,8 @@ cy_detect_pci(void)
                 /* set cy_card */
                 cy_card[j].base_phys = (ulong)cy_pci_phys2;
                 cy_card[j].ctl_phys = (ulong)cy_pci_phys0;
-                cy_card[j].base_addr = (ulong)cy_pci_addr2;
-                cy_card[j].ctl_addr = (ulong)cy_pci_addr0;
+                cy_card[j].base_addr = cy_pci_addr2;
+                cy_card[j].ctl_addr = cy_pci_addr0;
                 cy_card[j].irq = (int) cy_pci_irq;
                 cy_card[j].bus_index = 1;
                 cy_card[j].first_line = cy_next_channel;
@@ -5006,7 +4936,7 @@ cy_detect_pci(void)
             printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n",
                 (ulong)cy_pci_phys2, (ulong)cy_pci_phys0);
 #endif
-		cy_pci_addr0 = (ulong)ioremap(cy_pci_phys0, CyPCI_Zctl);
+		cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Zctl);
 
 		/* Disable interrupts on the PLX before resetting it */
 		cy_writew(cy_pci_addr0+0x68,
@@ -5019,7 +4949,7 @@ cy_detect_pci(void)
 		   This will remain here until we find a permanent fix. */
 		pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, cy_pci_irq);
 
-		mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 *) 
+		mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *) 
 			   cy_pci_addr0)->mail_box_0);
 
 		if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) {
@@ -5037,7 +4967,7 @@ cy_detect_pci(void)
 		}
 	
 		if (mailbox == ZE_V1) {
-		    cy_pci_addr2 = (ulong)ioremap(cy_pci_phys2, CyPCI_Ze_win);
+		    cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Ze_win);
 		    if (ZeIndex == NR_CARDS) {
 			printk("Cyclades-Ze/PCI found at 0x%lx ",
 				(ulong)cy_pci_phys2);
@@ -5055,7 +4985,7 @@ cy_detect_pci(void)
 		    i--;
 		    continue;
 		} else {
-		    cy_pci_addr2 = (ulong)ioremap(cy_pci_phys2, CyPCI_Zwin);
+		    cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Zwin);
 		}
 
 #ifdef CY_PCI_DEBUG
@@ -5082,7 +5012,7 @@ cy_detect_pci(void)
 	     */
 		PAUSE
 		if ((mailbox == ZO_V1) || (mailbox == ZO_V2))
-		    cy_writel((ulong)(cy_pci_addr2+ID_ADDRESS), 0L);
+		    cy_writel(cy_pci_addr2 + ID_ADDRESS, 0L);
 
                 /* This must be a Cyclades-8Zo/PCI.  The extendable
                    version will have a different device_id and will
@@ -5172,7 +5102,7 @@ cy_detect_pci(void)
 		Ze_pdev[j] = Ze_pdev[j+1];
 	    }
 	    ZeIndex--;
-		mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 *) 
+		mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *) 
 					   cy_pci_addr0)->mail_box_0);
 #ifdef CY_PCI_DEBUG
             printk("Cyclades-Z/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n",
@@ -5413,7 +5343,7 @@ cy_init(void)
 
     for (i = 0; i < NR_CARDS; i++) {
             /* base_addr=0 indicates board not found */
-            cy_card[i].base_addr = 0;
+            cy_card[i].base_addr = NULL;
     }
 
     /* the code below is responsible to find the boards. Each different
@@ -5435,7 +5365,7 @@ cy_init(void)
     for (i = 0 ; i < NR_CARDS ; i++) {
         if (cy_card[i].base_addr == 0) {
                 cy_card[i].first_line = -1;
-                cy_card[i].ctl_addr = 0;
+                cy_card[i].ctl_addr = NULL;
                 cy_card[i].irq = 0;
                 cy_card[i].bus_index = 0;
                 cy_card[i].first_line = 0;
@@ -5453,7 +5383,7 @@ cy_init(void)
             cinfo = &cy_card[board];
             if (cinfo->num_chips == -1) { /* Cyclades-Z */
 		number_z_boards++;
-		mailbox = cy_readl(&((struct RUNTIME_9060 *)
+		mailbox = cy_readl(&((struct RUNTIME_9060 __iomem *)
 			     cy_card[board].ctl_addr)->mail_box_0);
 		nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8;
 		cinfo->intr_enabled = 0;
@@ -5623,10 +5553,10 @@ cy_cleanup_module(void)
     put_tty_driver(cy_serial_driver);
 
     for (i = 0; i < NR_CARDS; i++) {
-        if (cy_card[i].base_addr != 0) {
-	    iounmap((void *)cy_card[i].base_addr);
-	    if (cy_card[i].ctl_addr != 0)
-		iounmap((void *)cy_card[i].ctl_addr);
+        if (cy_card[i].base_addr) {
+	    iounmap(cy_card[i].base_addr);
+	    if (cy_card[i].ctl_addr)
+		iounmap(cy_card[i].ctl_addr);
 	    if (cy_card[i].irq
 #ifndef CONFIG_CYZ_INTR
 		&& cy_card[i].num_chips != -1 /* not a Z card */
diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig
index 13797ca0c..0f210ceaf 100644
--- a/drivers/char/drm/Kconfig
+++ b/drivers/char/drm/Kconfig
@@ -24,14 +24,14 @@ config DRM_TDFX
 
 config DRM_GAMMA
 	tristate "3dlabs GMX 2000"
-	depends on DRM
+	depends on DRM && BROKEN
 	help
 	  This is the old gamma driver, please tell me if it might actually
 	  work.
 
 config DRM_R128
 	tristate "ATI Rage 128"
-	depends on DRM
+	depends on DRM && PCI
 	help
 	  Choose this option if you have an ATI Rage 128 graphics card.  If M
 	  is selected, the module will be called r128.  AGP support for
@@ -39,7 +39,7 @@ config DRM_R128
 
 config DRM_RADEON
 	tristate "ATI Radeon"
-	depends on DRM
+	depends on DRM && PCI
 	help
 	  Choose this option if you have an ATI Radeon graphics card.  There
 	  are both PCI and AGP versions.  You don't need to choose this to
@@ -55,14 +55,29 @@ config DRM_I810
 	  selected, the module will be called i810.  AGP support is required
 	  for this driver to work.
 
-config DRM_I830
-	tristate "Intel 830M, 845G, 852GM, 855GM, 865G"
+choice
+	prompt "Intel 830M, 845G, 852GM, 855GM, 865G"
 	depends on DRM && AGP && AGP_INTEL
+	optional
+
+config DRM_I830
+	tristate "i830 driver"
 	help
 	  Choose this option if you have a system that has Intel 830M, 845G,
 	  852GM, 855GM or 865G integrated graphics.  If M is selected, the
 	  module will be called i830.  AGP support is required for this driver
-	  to work.
+	  to work. This driver will eventually be replaced by the i915 one.
+
+config DRM_I915
+	tristate "i915 driver"
+	help
+	  Choose this option if you have a system that has Intel 830M, 845G,
+	  852GM, 855GM 865G or 915G integrated graphics.  If M is selected, the
+	  module will be called i915.  AGP support is required for this driver
+	  to work. This driver will eventually replace the I830 driver, when
+	  later release of X start to use the new DDX and DRI.
+	
+endchoice
 
 config DRM_MGA
 	tristate "Matrox g200/g400"
diff --git a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile
index f0acc5e48..d59102e2e 100644
--- a/drivers/char/drm/Makefile
+++ b/drivers/char/drm/Makefile
@@ -8,6 +8,7 @@ r128-objs   := r128_drv.o r128_cce.o r128_state.o r128_irq.o
 mga-objs    := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
 i810-objs   := i810_drv.o i810_dma.o
 i830-objs   := i830_drv.o i830_dma.o i830_irq.o
+i915-objs   := i915_drv.o i915_dma.o i915_irq.o i915_mem.o
 radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o
 ffb-objs    := ffb_drv.o ffb_context.o
 sis-objs    := sis_drv.o sis_ds.o sis_mm.o
@@ -19,6 +20,7 @@ obj-$(CONFIG_DRM_RADEON)+= radeon.o
 obj-$(CONFIG_DRM_MGA)	+= mga.o
 obj-$(CONFIG_DRM_I810)	+= i810.o
 obj-$(CONFIG_DRM_I830)	+= i830.o
+obj-$(CONFIG_DRM_I915)  += i915.o
 obj-$(CONFIG_DRM_FFB)   += ffb.o
 obj-$(CONFIG_DRM_SIS)   += sis.o
 
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 88886cbf9..65351d518 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -73,42 +73,26 @@
 #include <asm/pgalloc.h>
 #include "drm.h"
 
-#include "drm_os_linux.h"
+#define __OS_HAS_AGP (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE)))
+#define __OS_HAS_MTRR (defined(CONFIG_MTRR))
 
+#include "drm_os_linux.h"
 
 /***********************************************************************/
 /** \name DRM template customization defaults */
 /*@{*/
 
-#ifndef __HAVE_AGP
-#define __HAVE_AGP		0
-#endif
-#ifndef __HAVE_MTRR
-#define __HAVE_MTRR		0
-#endif
-#ifndef __HAVE_CTX_BITMAP
-#define __HAVE_CTX_BITMAP	0
-#endif
-#ifndef __HAVE_DMA
-#define __HAVE_DMA		0
-#endif
-#ifndef __HAVE_IRQ
-#define __HAVE_IRQ		0
-#endif
-#ifndef __HAVE_DMA_WAITLIST
-#define __HAVE_DMA_WAITLIST	0
-#endif
-#ifndef __HAVE_DMA_FREELIST
-#define __HAVE_DMA_FREELIST	0
-#endif
-
-#define __REALLY_HAVE_AGP	(__HAVE_AGP && (defined(CONFIG_AGP) || \
-						defined(CONFIG_AGP_MODULE)))
-#define __REALLY_HAVE_MTRR	(__HAVE_MTRR && defined(CONFIG_MTRR))
-#define __REALLY_HAVE_SG	(__HAVE_SG)
-
-/*@}*/
-
+/* driver capabilities and requirements mask */
+#define DRIVER_USE_AGP     0x1
+#define DRIVER_REQUIRE_AGP 0x2
+#define DRIVER_USE_MTRR    0x4
+#define DRIVER_PCI_DMA     0x8
+#define DRIVER_SG          0x10
+#define DRIVER_HAVE_DMA    0x20
+#define DRIVER_HAVE_IRQ    0x40
+#define DRIVER_IRQ_SHARED  0x80
+#define DRIVER_IRQ_VBL     0x100
+#define DRIVER_DMA_QUEUE   0x200
 
 /***********************************************************************/
 /** \name Begin the DRM... */
@@ -265,54 +249,6 @@ static inline struct page * vmalloc_to_page(void * vmalloc_addr)
 /*@}*/
 
 
-/***********************************************************************/
-/** \name Mapping helper macros */
-/*@{*/
-
-#define DRM_IOREMAP(map, dev)							\
-	(map)->handle = DRM(ioremap)( (map)->offset, (map)->size, (dev) )
-
-#define DRM_IOREMAP_NOCACHE(map, dev)						\
-	(map)->handle = DRM(ioremap_nocache)((map)->offset, (map)->size, (dev))
-
-#define DRM_IOREMAPFREE(map, dev)						\
-	do {									\
-		if ( (map)->handle && (map)->size )				\
-			DRM(ioremapfree)( (map)->handle, (map)->size, (dev) );	\
-	} while (0)
-
-/**
- * Find mapping.
- *
- * \param _map matching mapping if found, untouched otherwise.
- * \param _o offset.
- *
- * Expects the existence of a local variable named \p dev pointing to the
- * drm_device structure.
- */
-#define DRM_FIND_MAP(_map, _o)								\
-do {											\
-	struct list_head *_list;							\
-	list_for_each( _list, &dev->maplist->head ) {					\
-		drm_map_list_t *_entry = list_entry( _list, drm_map_list_t, head );	\
-		if ( _entry->map &&							\
-		     _entry->map->offset == (_o) ) {					\
-			(_map) = _entry->map;						\
-			break;								\
- 		}									\
-	}										\
-} while(0)
-
-/**
- * Drop mapping.
- *
- * \sa #DRM_FIND_MAP.
- */
-#define DRM_DROP_MAP(_map)
-
-/*@}*/
-
-
 /***********************************************************************/
 /** \name Internal types and structures */
 /*@{*/
@@ -473,9 +409,7 @@ typedef struct drm_file {
 	struct drm_device *dev;
 	int 		  remove_auth_on_close;
 	unsigned long     lock_count;
-#ifdef DRIVER_FILE_FIELDS
-	DRIVER_FILE_FIELDS;
-#endif
+	void              *driver_priv;
 } drm_file_t;
 
 /** Wait queue */
@@ -524,16 +458,8 @@ typedef struct drm_device_dma {
 		_DRM_DMA_USE_SG  = 0x02
 	} flags;
 
-	/** \name DMA support */
-	/*@{*/
-	drm_buf_t	  *this_buffer;	/**< Buffer being sent */
-	drm_buf_t	  *next_buffer; /**< Selected buffer to send */
-	drm_queue_t	  *next_queue;	/**< Queue from which buffer selected*/
-	wait_queue_head_t waiting;	/**< Processes waiting on free bufs */
-	/*@}*/
 } drm_device_dma_t;
 
-#if __REALLY_HAVE_AGP
 /** 
  * AGP memory entry.  Stored as a doubly linked list.
  */
@@ -562,7 +488,6 @@ typedef struct drm_agp_head {
 	int		   cant_use_aperture;
 	unsigned long	   page_mask;
 } drm_agp_head_t;
-#endif
 
 /**
  * Scatter-gather memory.
@@ -599,7 +524,6 @@ typedef struct drm_ctx_list {
 	drm_file_t		*tag;   /**< associated fd private data */
 } drm_ctx_list_t;
 
-#ifdef __HAVE_VBL_IRQ
 
 typedef struct drm_vbl_sig {
 	struct list_head	head;
@@ -608,8 +532,40 @@ typedef struct drm_vbl_sig {
 	struct task_struct	*task;
 } drm_vbl_sig_t;
 
-#endif
 
+/** 
+ * DRM device functions structure
+ */
+struct drm_device;
+
+struct drm_driver_fn {
+	int (*preinit)(struct drm_device *);
+	int (*postinit)(struct drm_device *);
+	void (*prerelease)(struct drm_device *, struct file *filp);
+	void (*pretakedown)(struct drm_device *);
+	int (*postcleanup)(struct drm_device *);
+	int (*presetup)(struct drm_device *);
+	int (*postsetup)(struct drm_device *);
+	int (*open_helper)(struct drm_device *, drm_file_t *);
+	void (*free_filp_priv)(struct drm_device *, drm_file_t *);
+	void (*release)(struct drm_device *, struct file *filp);
+	void (*dma_ready)(struct drm_device *);
+	int (*dma_quiescent)(struct drm_device *);
+	int (*context_ctor)(struct drm_device *dev, int context);
+ 	int (*context_dtor)(struct drm_device *dev, int context);
+ 	int (*kernel_context_switch)(struct drm_device *dev, int old, int new);
+	void (*kernel_context_switch_unlock)(struct drm_device *dev, drm_lock_t *lock);
+	int (*vblank_wait)(struct drm_device *dev, unsigned int *sequence);
+	/* these have to be filled in */
+	irqreturn_t (*irq_handler)( DRM_IRQ_ARGS );
+ 	void (*irq_preinstall)(struct drm_device *dev);
+ 	void (*irq_postinstall)(struct drm_device *dev);
+ 	void (*irq_uninstall)(struct drm_device *dev);
+	void (*reclaim_buffers)(struct file *filp);
+	unsigned long (*get_map_ofs)(drm_map_t *map);
+	unsigned long (*get_reg_ofs)(struct drm_device *dev);
+	void (*set_version)(struct drm_device *dev, drm_set_version_t *sv);
+};
 /**
  * DRM device structure.
  */
@@ -698,13 +654,13 @@ typedef struct drm_device {
 	struct work_struct	work;
 	/** \name VBLANK IRQ support */
 	/*@{*/
-#ifdef __HAVE_VBL_IRQ
+
    	wait_queue_head_t vbl_queue;	/**< VBLANK wait queue */
    	atomic_t          vbl_received;
 	spinlock_t        vbl_lock;
 	drm_vbl_sig_t     vbl_sigs;	/**< signal list to send on VBLANK */
 	unsigned int      vbl_pending;
-#endif
+
 	/*@}*/
 	cycles_t	  ctx_start;
 	cycles_t	  lck_start;
@@ -717,9 +673,7 @@ typedef struct drm_device {
 	wait_queue_head_t buf_readers;	/**< Processes waiting to read */
 	wait_queue_head_t buf_writers;	/**< Processes waiting to ctx switch */
 
-#if __REALLY_HAVE_AGP
 	drm_agp_head_t    *agp;	/**< AGP data */
-#endif
 
 	struct pci_dev    *pdev;	/**< PCI device structure */
 	int               pci_domain;	/**< PCI bus domain number */
@@ -738,8 +692,37 @@ typedef struct drm_device {
 	void		  *dev_private; /**< device private data */
 	drm_sigdata_t     sigdata; /**< For block_all_signals */
 	sigset_t          sigmask;
+
+	struct            drm_driver_fn fn_tbl;
+	drm_local_map_t   *agp_buffer_map;
+	int               dev_priv_size;
+	u32               driver_features;
 } drm_device_t;
 
+static __inline__ int drm_core_check_feature(struct drm_device *dev, int feature)
+{
+	return ((dev->driver_features & feature) ? 1 : 0);
+}
+
+#if __OS_HAS_AGP
+static inline int drm_core_has_AGP(struct drm_device *dev)
+{
+  return drm_core_check_feature(dev, DRIVER_USE_AGP);
+}
+#else
+#define drm_core_has_AGP(dev) (0)
+#endif
+
+#if __OS_HAS_MTRR
+static inline int drm_core_has_MTRR(struct drm_device *dev)
+{
+  return drm_core_check_feature(dev, DRIVER_USE_MTRR);
+}
+#else
+#define drm_core_has_MTRR(dev) (0)
+#endif
+
+extern void DRM(driver_register_fns)(struct drm_device *dev);
 
 /******************************************************************/
 /** \name Internal function definitions */
@@ -795,12 +778,10 @@ extern void	     *DRM(ioremap_nocache)(unsigned long offset, unsigned long size,
 					   drm_device_t *dev);
 extern void	     DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev);
 
-#if __REALLY_HAVE_AGP
 extern DRM_AGP_MEM   *DRM(alloc_agp)(int pages, u32 type);
 extern int           DRM(free_agp)(DRM_AGP_MEM *handle, int pages);
 extern int           DRM(bind_agp)(DRM_AGP_MEM *handle, unsigned int start);
 extern int           DRM(unbind_agp)(DRM_AGP_MEM *handle);
-#endif
 
 				/* Misc. IOCTL support (drm_ioctl.h) */
 extern int	     DRM(irq_by_busid)(struct inode *inode, struct file *filp,
@@ -837,10 +818,8 @@ extern int	     DRM(rmctx)( struct inode *inode, struct file *filp,
 extern int	     DRM(context_switch)(drm_device_t *dev, int old, int new);
 extern int	     DRM(context_switch_complete)(drm_device_t *dev, int new);
 
-#if __HAVE_CTX_BITMAP
 extern int	     DRM(ctxbitmap_init)( drm_device_t *dev );
 extern void	     DRM(ctxbitmap_cleanup)( drm_device_t *dev );
-#endif
 
 extern int	     DRM(setsareactx)( struct inode *inode, struct file *filp,
 				       unsigned int cmd, unsigned long arg );
@@ -884,7 +863,6 @@ extern int	     DRM(addmap)( struct inode *inode, struct file *filp,
 				  unsigned int cmd, unsigned long arg );
 extern int	     DRM(rmmap)( struct inode *inode, struct file *filp,
 				 unsigned int cmd, unsigned long arg );
-#if __HAVE_DMA
 extern int	     DRM(addbufs)( struct inode *inode, struct file *filp,
 				   unsigned int cmd, unsigned long arg );
 extern int	     DRM(infobufs)( struct inode *inode, struct file *filp,
@@ -901,33 +879,22 @@ extern int	     DRM(dma_setup)(drm_device_t *dev);
 extern void	     DRM(dma_takedown)(drm_device_t *dev);
 extern void	     DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf);
 extern void	     DRM(reclaim_buffers)( struct file *filp );
-#endif /* __HAVE_DMA */
 
 				/* IRQ support (drm_irq.h) */
-#if __HAVE_IRQ || __HAVE_DMA
 extern int           DRM(control)( struct inode *inode, struct file *filp,
 				   unsigned int cmd, unsigned long arg );
-#endif
-#if __HAVE_IRQ
 extern int           DRM(irq_install)( drm_device_t *dev );
 extern int           DRM(irq_uninstall)( drm_device_t *dev );
 extern irqreturn_t   DRM(irq_handler)( DRM_IRQ_ARGS );
 extern void          DRM(driver_irq_preinstall)( drm_device_t *dev );
 extern void          DRM(driver_irq_postinstall)( drm_device_t *dev );
 extern void          DRM(driver_irq_uninstall)( drm_device_t *dev );
-#ifdef __HAVE_VBL_IRQ
+
 extern int           DRM(wait_vblank)(struct inode *inode, struct file *filp,
 				      unsigned int cmd, unsigned long arg);
 extern int           DRM(vblank_wait)(drm_device_t *dev, unsigned int *vbl_seq);
 extern void          DRM(vbl_send_signals)( drm_device_t *dev );
-#endif
-#ifdef __HAVE_IRQ_BH
-extern void          DRM(irq_immediate_bh)( void *dev );
-#endif
-#endif
 
-
-#if __REALLY_HAVE_AGP
 				/* AGP/GART support (drm_agpsupport.h) */
 extern drm_agp_head_t *DRM(agp_init)(void);
 extern void           DRM(agp_uninit)(void);
@@ -952,7 +919,6 @@ extern DRM_AGP_MEM    *DRM(agp_allocate_memory)(size_t pages, u32 type);
 extern int            DRM(agp_free_memory)(DRM_AGP_MEM *handle);
 extern int            DRM(agp_bind_memory)(DRM_AGP_MEM *handle, off_t start);
 extern int            DRM(agp_unbind_memory)(DRM_AGP_MEM *handle);
-#endif
 
 				/* Stub support (drm_stub.h) */
 int                   DRM(stub_register)(const char *name,
@@ -969,14 +935,12 @@ extern int            DRM(proc_cleanup)(int minor,
 					struct proc_dir_entry *root,
 					struct proc_dir_entry *dev_root);
 
-#ifdef __HAVE_SG
 				/* Scatter Gather Support (drm_scatter.h) */
 extern void           DRM(sg_cleanup)(drm_sg_mem_t *entry);
 extern int            DRM(sg_alloc)(struct inode *inode, struct file *filp,
 				    unsigned int cmd, unsigned long arg);
 extern int            DRM(sg_free)(struct inode *inode, struct file *filp,
 				   unsigned int cmd, unsigned long arg);
-#endif
 
                                /* ATI PCIGART support (ati_pcigart.h) */
 extern int            DRM(ati_pcigart_init)(drm_device_t *dev,
@@ -986,7 +950,44 @@ extern int            DRM(ati_pcigart_cleanup)(drm_device_t *dev,
 					       unsigned long addr,
 					       dma_addr_t bus_addr);
 
+
+/* Inline replacements for DRM_IOREMAP macros */
+static __inline__ void drm_core_ioremap(struct drm_map *map, struct drm_device *dev)
+{
+	map->handle = DRM(ioremap)( map->offset, map->size, dev );
+}
+
+static __inline__ void drm_core_ioremap_nocache(struct drm_map *map, struct drm_device *dev)
+{
+	map->handle = DRM(ioremap_nocache)(map->offset, map->size, dev);
+}
+
+static __inline__ void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev)
+{
+	if ( map->handle && map->size )
+		DRM(ioremapfree)( map->handle, map->size, dev );
+}
+
+static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, unsigned long offset)
+{
+	struct list_head *_list;
+	list_for_each( _list, &dev->maplist->head ) {
+		drm_map_list_t *_entry = list_entry( _list, drm_map_list_t, head );
+		if ( _entry->map &&
+		     _entry->map->offset == offset ) {
+			return _entry->map;
+		}
+	}
+	return NULL;
+}
+
+static __inline__ void drm_core_dropmap(struct drm_map *map)
+{
+}
 /*@}*/
 
+extern unsigned long DRM(core_get_map_ofs)(drm_map_t *map);
+extern unsigned long DRM(core_get_reg_ofs)(struct drm_device *dev);
+
 #endif /* __KERNEL__ */
 #endif
diff --git a/drivers/char/drm/drm_agpsupport.h b/drivers/char/drm/drm_agpsupport.h
index 491c3051c..81b595e0e 100644
--- a/drivers/char/drm/drm_agpsupport.h
+++ b/drivers/char/drm/drm_agpsupport.h
@@ -34,8 +34,7 @@
 #include "drmP.h"
 #include <linux/module.h>
 
-#if __REALLY_HAVE_AGP
-
+#if __OS_HAS_AGP
 
 #define DRM_AGP_GET (drm_agp_t *)inter_module_get("drm_agp")
 #define DRM_AGP_PUT inter_module_put("drm_agp")
@@ -466,4 +465,4 @@ int DRM(agp_unbind_memory)(DRM_AGP_MEM *handle)
 	return drm_agp->unbind_memory(handle);
 }
 
-#endif /* __REALLY_HAVE_AGP */
+#endif /* __OS_HAS_AGP */
diff --git a/drivers/char/drm/drm_bufs.h b/drivers/char/drm/drm_bufs.h
index 6fa862372..19695693f 100644
--- a/drivers/char/drm/drm_bufs.h
+++ b/drivers/char/drm/drm_bufs.h
@@ -36,26 +36,6 @@
 #include <linux/vmalloc.h>
 #include "drmP.h"
 
-#ifndef __HAVE_PCI_DMA
-#define __HAVE_PCI_DMA		0
-#endif
-
-#ifndef __HAVE_SG
-#define __HAVE_SG		0
-#endif
-
-#ifndef DRIVER_BUF_PRIV_T
-#define DRIVER_BUF_PRIV_T		u32
-#endif
-#ifndef DRIVER_AGP_BUFFERS_MAP
-#if __HAVE_AGP && __HAVE_DMA
-#error "You must define DRIVER_AGP_BUFFERS_MAP()"
-#else
-#define DRIVER_AGP_BUFFERS_MAP( dev )	NULL
-#endif
-#endif
-
-
 /**
  * Compute size order.  Returns the exponent of the smaller power of two which
  * is greater or equal to given number.
@@ -142,13 +122,13 @@ int DRM(addmap)( struct inode *inode, struct file *filp,
 #ifdef __alpha__
 		map->offset += dev->hose->mem_space->start;
 #endif
-#if __REALLY_HAVE_MTRR
-		if ( map->type == _DRM_FRAME_BUFFER ||
-		     (map->flags & _DRM_WRITE_COMBINING) ) {
-			map->mtrr = mtrr_add( map->offset, map->size,
-					      MTRR_TYPE_WRCOMB, 1 );
+		if (drm_core_has_MTRR(dev)) {
+			if ( map->type == _DRM_FRAME_BUFFER ||
+			     (map->flags & _DRM_WRITE_COMBINING) ) {
+				map->mtrr = mtrr_add( map->offset, map->size,
+						      MTRR_TYPE_WRCOMB, 1 );
+			}
 		}
-#endif
 		if (map->type == _DRM_REGISTERS)
 			map->handle = DRM(ioremap)( map->offset, map->size,
 						    dev );
@@ -174,15 +154,15 @@ int DRM(addmap)( struct inode *inode, struct file *filp,
 			dev->lock.hw_lock = map->handle; /* Pointer to lock */
 		}
 		break;
-#if __REALLY_HAVE_AGP
 	case _DRM_AGP:
+		if (drm_core_has_AGP(dev)) {
 #ifdef __alpha__
-		map->offset += dev->hose->mem_space->start;
+			map->offset += dev->hose->mem_space->start;
 #endif
-		map->offset += dev->agp->base;
-		map->mtrr   = dev->agp->agp_mtrr; /* for getmap */
+			map->offset += dev->agp->base;
+			map->mtrr   = dev->agp->agp_mtrr; /* for getmap */
+		}
 		break;
-#endif
 	case _DRM_SCATTER_GATHER:
 		if (!dev->sg) {
 			DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
@@ -282,15 +262,15 @@ int DRM(rmmap)(struct inode *inode, struct file *filp,
 		switch (map->type) {
 		case _DRM_REGISTERS:
 		case _DRM_FRAME_BUFFER:
-#if __REALLY_HAVE_MTRR
-			if (map->mtrr >= 0) {
-				int retcode;
-				retcode = mtrr_del(map->mtrr,
-						   map->offset,
-						   map->size);
-				DRM_DEBUG("mtrr_del = %d\n", retcode);
+		  if (drm_core_has_MTRR(dev)) {
+				if (map->mtrr >= 0) {
+					int retcode;
+					retcode = mtrr_del(map->mtrr,
+							   map->offset,
+							   map->size);
+					DRM_DEBUG("mtrr_del = %d\n", retcode);
+				}
 			}
-#endif
 			DRM(ioremapfree)(map->handle, map->size, dev);
 			break;
 		case _DRM_SHM:
@@ -306,8 +286,6 @@ int DRM(rmmap)(struct inode *inode, struct file *filp,
 	return 0;
 }
 
-#if __HAVE_DMA
-
 /**
  * Cleanup after an error on one of the addbufs() functions.
  *
@@ -348,15 +326,11 @@ static void DRM(cleanup_buf_error)(drm_buf_entry_t *entry)
 			  sizeof(*entry->buflist),
 			  DRM_MEM_BUFS);
 
-#if __HAVE_DMA_FREELIST
-	   	DRM(freelist_destroy)(&entry->freelist);
-#endif
-
 		entry->buf_count = 0;
 	}
 }
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 /**
  * Add AGP buffers for DMA transfers (ioctl).
  *
@@ -473,8 +447,8 @@ int DRM(addbufs_agp)( struct inode *inode, struct file *filp,
 		init_waitqueue_head( &buf->dma_wait );
 		buf->filp    = NULL;
 
-		buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T);
-		buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T),
+		buf->dev_priv_size = dev->dev_priv_size;
+		buf->dev_private = DRM(alloc)( buf->dev_priv_size,
 					       DRM_MEM_BUFS );
 		if(!buf->dev_private) {
 			/* Set count correctly so we free the proper amount. */
@@ -520,12 +494,6 @@ int DRM(addbufs_agp)( struct inode *inode, struct file *filp,
 	DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
 	DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
 
-#if __HAVE_DMA_FREELIST
-	DRM(freelist_create)( &entry->freelist, entry->buf_count );
-	for ( i = 0 ; i < entry->buf_count ; i++ ) {
-		DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] );
-	}
-#endif
 	up( &dev->struct_sem );
 
 	request.count = entry->buf_count;
@@ -539,9 +507,8 @@ int DRM(addbufs_agp)( struct inode *inode, struct file *filp,
 	atomic_dec( &dev->buf_alloc );
 	return 0;
 }
-#endif /* __REALLY_HAVE_AGP */
+#endif /* __OS_HAS_AGP */
 
-#if __HAVE_PCI_DMA
 int DRM(addbufs_pci)( struct inode *inode, struct file *filp,
 		      unsigned int cmd, unsigned long arg )
 {
@@ -566,6 +533,7 @@ int DRM(addbufs_pci)( struct inode *inode, struct file *filp,
 	drm_buf_t **temp_buflist;
 	drm_buf_desc_t __user *argp = (void __user *)arg;
 
+	if (!drm_core_check_feature(dev, DRIVER_PCI_DMA)) return -EINVAL;
 	if ( !dma ) return -EINVAL;
 
 	if ( copy_from_user( &request, argp, sizeof(request) ) )
@@ -697,8 +665,8 @@ int DRM(addbufs_pci)( struct inode *inode, struct file *filp,
 			init_waitqueue_head( &buf->dma_wait );
 			buf->filp    = NULL;
 
-			buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T);
-			buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T),
+			buf->dev_priv_size = dev->dev_priv_size;
+			buf->dev_private = DRM(alloc)( dev->dev_priv_size,
 						       DRM_MEM_BUFS );
 			if(!buf->dev_private) {
 				/* Set count correctly so we free the proper amount. */
@@ -758,12 +726,6 @@ int DRM(addbufs_pci)( struct inode *inode, struct file *filp,
 	dma->page_count += entry->seg_count << page_order;
 	dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order);
 
-#if __HAVE_DMA_FREELIST
-	DRM(freelist_create)( &entry->freelist, entry->buf_count );
-	for ( i = 0 ; i < entry->buf_count ; i++ ) {
-		DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] );
-	}
-#endif
 	up( &dev->struct_sem );
 
 	request.count = entry->buf_count;
@@ -776,9 +738,7 @@ int DRM(addbufs_pci)( struct inode *inode, struct file *filp,
 	return 0;
 
 }
-#endif /* __HAVE_PCI_DMA */
 
-#if __HAVE_SG
 int DRM(addbufs_sg)( struct inode *inode, struct file *filp,
                      unsigned int cmd, unsigned long arg )
 {
@@ -801,6 +761,8 @@ int DRM(addbufs_sg)( struct inode *inode, struct file *filp,
 	int i;
 	drm_buf_t **temp_buflist;
 
+	if (!drm_core_check_feature(dev, DRIVER_SG)) return -EINVAL;
+	
 	if ( !dma ) return -EINVAL;
 
 	if ( copy_from_user( &request, argp, sizeof(request) ) )
@@ -881,8 +843,8 @@ int DRM(addbufs_sg)( struct inode *inode, struct file *filp,
 		init_waitqueue_head( &buf->dma_wait );
 		buf->filp    = NULL;
 
-		buf->dev_priv_size = sizeof(DRIVER_BUF_PRIV_T);
-		buf->dev_private = DRM(alloc)( sizeof(DRIVER_BUF_PRIV_T),
+		buf->dev_priv_size = dev->dev_priv_size;
+		buf->dev_private = DRM(alloc)( dev->dev_priv_size,
 					       DRM_MEM_BUFS );
 		if(!buf->dev_private) {
 			/* Set count correctly so we free the proper amount. */
@@ -929,12 +891,6 @@ int DRM(addbufs_sg)( struct inode *inode, struct file *filp,
 	DRM_DEBUG( "dma->buf_count : %d\n", dma->buf_count );
 	DRM_DEBUG( "entry->buf_count : %d\n", entry->buf_count );
 
-#if __HAVE_DMA_FREELIST
-	DRM(freelist_create)( &entry->freelist, entry->buf_count );
-	for ( i = 0 ; i < entry->buf_count ; i++ ) {
-		DRM(freelist_put)( dev, &entry->freelist, &entry->buflist[i] );
-	}
-#endif
 	up( &dev->struct_sem );
 
 	request.count = entry->buf_count;
@@ -948,7 +904,6 @@ int DRM(addbufs_sg)( struct inode *inode, struct file *filp,
 	atomic_dec( &dev->buf_alloc );
 	return 0;
 }
-#endif /* __HAVE_SG */
 
 /**
  * Add buffers for DMA transfers (ioctl).
@@ -968,26 +923,25 @@ int DRM(addbufs)( struct inode *inode, struct file *filp,
 		  unsigned int cmd, unsigned long arg )
 {
 	drm_buf_desc_t request;
+	drm_file_t *priv = filp->private_data;
+	drm_device_t *dev = priv->dev;
+	
+	if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+		return -EINVAL;
 
 	if ( copy_from_user( &request, (drm_buf_desc_t __user *)arg,
 			     sizeof(request) ) )
 		return -EFAULT;
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	if ( request.flags & _DRM_AGP_BUFFER )
 		return DRM(addbufs_agp)( inode, filp, cmd, arg );
 	else
 #endif
-#if __HAVE_SG
 	if ( request.flags & _DRM_SG_BUFFER )
 		return DRM(addbufs_sg)( inode, filp, cmd, arg );
 	else
-#endif
-#if __HAVE_PCI_DMA
 		return DRM(addbufs_pci)( inode, filp, cmd, arg );
-#else
-		return -EINVAL;
-#endif
 }
 
 
@@ -1019,6 +973,9 @@ int DRM(infobufs)( struct inode *inode, struct file *filp,
 	int i;
 	int count;
 
+	if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+		return -EINVAL;
+
 	if ( !dma ) return -EINVAL;
 
 	spin_lock( &dev->count_lock );
@@ -1100,6 +1057,9 @@ int DRM(markbufs)( struct inode *inode, struct file *filp,
 	int order;
 	drm_buf_entry_t *entry;
 
+	if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+		return -EINVAL;
+
 	if ( !dma ) return -EINVAL;
 
 	if ( copy_from_user( &request,
@@ -1147,6 +1107,9 @@ int DRM(freebufs)( struct inode *inode, struct file *filp,
 	int idx;
 	drm_buf_t *buf;
 
+	if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+		return -EINVAL;
+
 	if ( !dma ) return -EINVAL;
 
 	if ( copy_from_user( &request,
@@ -1204,6 +1167,9 @@ int DRM(mapbufs)( struct inode *inode, struct file *filp,
 	drm_buf_map_t request;
 	int i;
 
+	if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+		return -EINVAL;
+
 	if ( !dma ) return -EINVAL;
 
 	spin_lock( &dev->count_lock );
@@ -1218,9 +1184,9 @@ int DRM(mapbufs)( struct inode *inode, struct file *filp,
 		return -EFAULT;
 
 	if ( request.count >= dma->buf_count ) {
-		if ( (__HAVE_AGP && (dma->flags & _DRM_DMA_USE_AGP)) ||
-		     (__HAVE_SG && (dma->flags & _DRM_DMA_USE_SG)) ) {
-			drm_map_t *map = DRIVER_AGP_BUFFERS_MAP( dev );
+		if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP)) ||
+		    (drm_core_check_feature(dev, DRIVER_SG) && (dma->flags & _DRM_DMA_USE_SG)) ) {
+			drm_map_t *map = dev->agp_buffer_map;
 
 			if ( !map ) {
 				retcode = -EINVAL;
@@ -1301,4 +1267,3 @@ int DRM(mapbufs)( struct inode *inode, struct file *filp,
 	return retcode;
 }
 
-#endif /* __HAVE_DMA */
diff --git a/drivers/char/drm/drm_context.h b/drivers/char/drm/drm_context.h
index d8000cfbf..b99c99475 100644
--- a/drivers/char/drm/drm_context.h
+++ b/drivers/char/drm/drm_context.h
@@ -42,11 +42,6 @@
 
 #include "drmP.h"
 
-#if !__HAVE_CTX_BITMAP
-#error "__HAVE_CTX_BITMAP must be defined"
-#endif
-
-
 /******************************************************************/
 /** \name Context bitmap support */
 /*@{*/
@@ -419,10 +414,13 @@ int DRM(addctx)( struct inode *inode, struct file *filp,
 				/* Should this return -EBUSY instead? */
 		return -ENOMEM;
 	}
-#ifdef DRIVER_CTX_CTOR
+
 	if ( ctx.handle != DRM_KERNEL_CONTEXT )
-		DRIVER_CTX_CTOR(ctx.handle); /* XXX: also pass dev ? */
-#endif
+	{
+		if (dev->fn_tbl.context_ctor)
+			dev->fn_tbl.context_ctor(dev, ctx.handle);
+	}
+
 	ctx_entry = DRM(alloc)( sizeof(*ctx_entry), DRM_MEM_CTXLIST );
 	if ( !ctx_entry ) {
 		DRM_DEBUG("out of memory\n");
@@ -554,9 +552,8 @@ int DRM(rmctx)( struct inode *inode, struct file *filp,
 		priv->remove_auth_on_close = 1;
 	}
 	if ( ctx.handle != DRM_KERNEL_CONTEXT ) {
-#ifdef DRIVER_CTX_DTOR
-		DRIVER_CTX_DTOR(ctx.handle); /* XXX: also pass dev ? */
-#endif
+		if (dev->fn_tbl.context_dtor)
+			dev->fn_tbl.context_dtor(dev, ctx.handle);
 		DRM(ctxbitmap_free)( dev, ctx.handle );
 	}
 
@@ -578,3 +575,4 @@ int DRM(rmctx)( struct inode *inode, struct file *filp,
 }
 
 /*@}*/
+
diff --git a/drivers/char/drm/drm_dma.h b/drivers/char/drm/drm_dma.h
index 72122754d..5cbdc9315 100644
--- a/drivers/char/drm/drm_dma.h
+++ b/drivers/char/drm/drm_dma.h
@@ -35,16 +35,6 @@
 
 #include "drmP.h"
 
-
-#ifndef __HAVE_DMA_WAITQUEUE
-#define __HAVE_DMA_WAITQUEUE	0
-#endif
-#ifndef __HAVE_DMA_RECLAIM
-#define __HAVE_DMA_RECLAIM	0
-#endif
-
-#if __HAVE_DMA
-
 /**
  * Initialize the DMA data.
  * 
@@ -116,9 +106,6 @@ void DRM(dma_takedown)(drm_device_t *dev)
 				  dma->bufs[i].buf_count *
 				  sizeof(*dma->bufs[0].buflist),
 				  DRM_MEM_BUFS);
-#if __HAVE_DMA_FREELIST
-		   	DRM(freelist_destroy)(&dma->bufs[i].freelist);
-#endif
 		}
 	}
 
@@ -155,22 +142,11 @@ void DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf)
 	buf->filp     = NULL;
 	buf->used     = 0;
 
-	if ( __HAVE_DMA_WAITQUEUE && waitqueue_active(&buf->dma_wait)) {
+	if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && waitqueue_active(&buf->dma_wait)) {
 		wake_up_interruptible(&buf->dma_wait);
 	}
-#if __HAVE_DMA_FREELIST
-	else {
-		drm_device_dma_t *dma = dev->dma;
-				/* If processes are waiting, the last one
-				   to wake will put the buffer on the free
-				   list.  If no processes are waiting, we
-				   put the buffer on the freelist here. */
-		DRM(freelist_put)(dev, &dma->bufs[buf->order].freelist, buf);
-	}
-#endif
 }
 
-#if !__HAVE_DMA_RECLAIM
 /**
  * Reclaim the buffers.
  *
@@ -178,7 +154,7 @@ void DRM(free_buffer)(drm_device_t *dev, drm_buf_t *buf)
  *
  * Frees each buffer associated with \p filp not already on the hardware.
  */
-void DRM(reclaim_buffers)( struct file *filp )
+void DRM(core_reclaim_buffers)( struct file *filp )
 {
 	drm_file_t    *priv   = filp->private_data;
 	drm_device_t  *dev    = priv->dev;
@@ -202,29 +178,4 @@ void DRM(reclaim_buffers)( struct file *filp )
 		}
 	}
 }
-#endif
-
-#if !__HAVE_IRQ
-/* This stub DRM_IOCTL_CONTROL handler is for the drivers that used to require
- * IRQs for DMA but no longer do.  It maintains compatibility with the X Servers
- * that try to use the control ioctl by simply returning success.
- */
-int DRM(control)( struct inode *inode, struct file *filp,
-		  unsigned int cmd, unsigned long arg )
-{
-	drm_control_t ctl;
-
-	if ( copy_from_user( &ctl, (drm_control_t __user *)arg, sizeof(ctl) ) )
-		return -EFAULT;
-
-	switch ( ctl.func ) {
-	case DRM_INST_HANDLER:
-	case DRM_UNINST_HANDLER:
-		return 0;
-	default:
-		return -EINVAL;
-	}
-}
-#endif
 
-#endif /* __HAVE_DMA */
diff --git a/drivers/char/drm/drm_drv.h b/drivers/char/drm/drm_drv.h
index 389fc7ef2..ebba185a7 100644
--- a/drivers/char/drm/drm_drv.h
+++ b/drivers/char/drm/drm_drv.h
@@ -52,97 +52,9 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef __MUST_HAVE_AGP
-#define __MUST_HAVE_AGP			0
-#endif
-#ifndef __HAVE_CTX_BITMAP
-#define __HAVE_CTX_BITMAP		0
-#endif
-#ifndef __HAVE_IRQ
-#define __HAVE_IRQ			0
-#endif
-#ifndef __HAVE_DMA_QUEUE
-#define __HAVE_DMA_QUEUE		0
-#endif
-#ifndef __HAVE_MULTIPLE_DMA_QUEUES
-#define __HAVE_MULTIPLE_DMA_QUEUES	0
-#endif
-#ifndef __HAVE_DMA_SCHEDULE
-#define __HAVE_DMA_SCHEDULE		0
-#endif
-#ifndef __HAVE_DMA_FLUSH
-#define __HAVE_DMA_FLUSH		0
-#endif
-#ifndef __HAVE_DMA_READY
-#define __HAVE_DMA_READY		0
-#endif
-#ifndef __HAVE_DMA_QUIESCENT
-#define __HAVE_DMA_QUIESCENT		0
-#endif
-#ifndef __HAVE_RELEASE
-#define __HAVE_RELEASE			0
-#endif
-#ifndef __HAVE_COUNTERS
-#define __HAVE_COUNTERS			0
-#endif
-#ifndef __HAVE_SG
-#define __HAVE_SG			0
-#endif
-/* __HAVE_KERNEL_CTX_SWITCH isn't used by any of the drm modules in
- * the DRI cvs tree, but it is required by the kernel tree's sparc
- * driver.
- */
-#ifndef __HAVE_KERNEL_CTX_SWITCH
-#define __HAVE_KERNEL_CTX_SWITCH	0
-#endif
-#ifndef __HAVE_DRIVER_FOPS_READ
-#define __HAVE_DRIVER_FOPS_READ		0
-#endif
-#ifndef __HAVE_DRIVER_FOPS_POLL
-#define __HAVE_DRIVER_FOPS_POLL		0
-#endif
-
-#ifndef DRIVER_PREINIT
-#define DRIVER_PREINIT()
-#endif
-#ifndef DRIVER_POSTINIT
-#define DRIVER_POSTINIT()
-#endif
-#ifndef DRIVER_PRERELEASE
-#define DRIVER_PRERELEASE()
-#endif
-#ifndef DRIVER_PRETAKEDOWN
-#define DRIVER_PRETAKEDOWN()
-#endif
-#ifndef DRIVER_POSTCLEANUP
-#define DRIVER_POSTCLEANUP()
-#endif
-#ifndef DRIVER_PRESETUP
-#define DRIVER_PRESETUP()
-#endif
-#ifndef DRIVER_POSTSETUP
-#define DRIVER_POSTSETUP()
-#endif
 #ifndef DRIVER_IOCTLS
 #define DRIVER_IOCTLS
 #endif
-#ifndef DRIVER_OPEN_HELPER
-#define DRIVER_OPEN_HELPER( priv, dev )
-#endif
-#ifndef DRIVER_FOPS
-#define DRIVER_FOPS				\
-static struct file_operations	DRM(fops) = {	\
-	.owner   = THIS_MODULE,			\
-	.open	 = DRM(open),			\
-	.flush	 = DRM(flush),			\
-	.release = DRM(release),		\
-	.ioctl	 = DRM(ioctl),			\
-	.mmap	 = DRM(mmap),			\
-	.fasync  = DRM(fasync),			\
-	.poll	 = DRM(poll),			\
-	.read	 = DRM(read),			\
-}
-#endif
 
 #ifndef MODULE
 /** Use an additional macro to avoid preprocessor troubles */
@@ -166,16 +78,24 @@ __setup( DRIVER_NAME "=", DRM_OPTIONS_FUNC );
 static drm_device_t	DRM(device)[MAX_DEVICES];
 static int		DRM(numdevs) = 0;
 
-DRIVER_FOPS;
+struct file_operations	DRM(fops) = {
+	.owner   = THIS_MODULE,
+	.open	 = DRM(open),
+	.flush	 = DRM(flush),
+	.release = DRM(release),
+	.ioctl	 = DRM(ioctl),
+	.mmap	 = DRM(mmap),
+	.fasync  = DRM(fasync),
+	.poll	 = DRM(poll),
+	.read	 = DRM(read),
+};
 
 /** Ioctl table */
-static drm_ioctl_desc_t		  DRM(ioctls)[] = {
+drm_ioctl_desc_t		  DRM(ioctls)[] = {
 	[DRM_IOCTL_NR(DRM_IOCTL_VERSION)]       = { DRM(version),     0, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)]    = { DRM(getunique),   0, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)]     = { DRM(getmagic),    0, 0 },
-#if __HAVE_IRQ
 	[DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)]     = { DRM(irq_by_busid), 0, 1 },
-#endif
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)]       = { DRM(getmap),      0, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)]    = { DRM(getclient),   0, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)]     = { DRM(getstats),    0, 0 },
@@ -189,10 +109,8 @@ static drm_ioctl_desc_t		  DRM(ioctls)[] = {
 	[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)]       = { DRM(addmap),      1, 1 },
 	[DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)]        = { DRM(rmmap),       1, 0 },
 
-#if __HAVE_CTX_BITMAP
 	[DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = { DRM(setsareactx), 1, 1 },
 	[DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = { DRM(getsareactx), 1, 0 },
-#endif
 
 	[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)]       = { DRM(addctx),      1, 1 },
 	[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)]        = { DRM(rmctx),       1, 1 },
@@ -208,26 +126,18 @@ static drm_ioctl_desc_t		  DRM(ioctls)[] = {
 	[DRM_IOCTL_NR(DRM_IOCTL_LOCK)]	        = { DRM(lock),        1, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)]        = { DRM(unlock),      1, 0 },
 
-#if __HAVE_DMA_FLUSH
-	/* Gamma only, really */
-	[DRM_IOCTL_NR(DRM_IOCTL_FINISH)]        = { DRM(finish),      1, 0 },
-#else
 	[DRM_IOCTL_NR(DRM_IOCTL_FINISH)]        = { DRM(noop),      1, 0 },
-#endif
 
-#if __HAVE_DMA
 	[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)]      = { DRM(addbufs),     1, 1 },
 	[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)]     = { DRM(markbufs),    1, 1 },
 	[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)]     = { DRM(infobufs),    1, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)]      = { DRM(mapbufs),     1, 0 },
 	[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)]     = { DRM(freebufs),    1, 0 },
 	/* The DRM_IOCTL_DMA ioctl should be defined by the driver. */
-#endif
-#if __HAVE_IRQ || __HAVE_DMA
+
 	[DRM_IOCTL_NR(DRM_IOCTL_CONTROL)]       = { DRM(control),     1, 1 },
-#endif
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)]   = { DRM(agp_acquire), 1, 1 },
 	[DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)]   = { DRM(agp_release), 1, 1 },
 	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)]    = { DRM(agp_enable),  1, 1 },
@@ -238,14 +148,10 @@ static drm_ioctl_desc_t		  DRM(ioctls)[] = {
 	[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)]    = { DRM(agp_unbind),  1, 1 },
 #endif
 
-#if __HAVE_SG
 	[DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)]      = { DRM(sg_alloc),    1, 1 },
 	[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)]       = { DRM(sg_free),     1, 1 },
-#endif
 
-#ifdef __HAVE_VBL_IRQ
 	[DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)]   = { DRM(wait_vblank), 0, 0 },
-#endif
 
 	DRIVER_IOCTLS
 };
@@ -264,56 +170,26 @@ MODULE_LICENSE("GPL and additional rights");
 static int DRM(setup)( drm_device_t *dev )
 {
 	int i;
+	int ret;
+
+	if (dev->fn_tbl.presetup)
+	{
+		ret=dev->fn_tbl.presetup(dev);
+		if (ret!=0) 
+			return ret;
+	}
 
-	DRIVER_PRESETUP();
 	atomic_set( &dev->ioctl_count, 0 );
 	atomic_set( &dev->vma_count, 0 );
 	dev->buf_use = 0;
 	atomic_set( &dev->buf_alloc, 0 );
 
-#if __HAVE_DMA
-	i = DRM(dma_setup)( dev );
-	if ( i < 0 )
-		return i;
-#endif
-
-	dev->counters  = 6 + __HAVE_COUNTERS;
-	dev->types[0]  = _DRM_STAT_LOCK;
-	dev->types[1]  = _DRM_STAT_OPENS;
-	dev->types[2]  = _DRM_STAT_CLOSES;
-	dev->types[3]  = _DRM_STAT_IOCTLS;
-	dev->types[4]  = _DRM_STAT_LOCKS;
-	dev->types[5]  = _DRM_STAT_UNLOCKS;
-#ifdef __HAVE_COUNTER6
-	dev->types[6]  = __HAVE_COUNTER6;
-#endif
-#ifdef __HAVE_COUNTER7
-	dev->types[7]  = __HAVE_COUNTER7;
-#endif
-#ifdef __HAVE_COUNTER8
-	dev->types[8]  = __HAVE_COUNTER8;
-#endif
-#ifdef __HAVE_COUNTER9
-	dev->types[9]  = __HAVE_COUNTER9;
-#endif
-#ifdef __HAVE_COUNTER10
-	dev->types[10] = __HAVE_COUNTER10;
-#endif
-#ifdef __HAVE_COUNTER11
-	dev->types[11] = __HAVE_COUNTER11;
-#endif
-#ifdef __HAVE_COUNTER12
-	dev->types[12] = __HAVE_COUNTER12;
-#endif
-#ifdef __HAVE_COUNTER13
-	dev->types[13] = __HAVE_COUNTER13;
-#endif
-#ifdef __HAVE_COUNTER14
-	dev->types[14] = __HAVE_COUNTER14;
-#endif
-#ifdef __HAVE_COUNTER15
-	dev->types[14] = __HAVE_COUNTER14;
-#endif
+	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+	{
+		i = DRM(dma_setup)( dev );
+		if ( i < 0 )
+			return i;
+	}
 
 	for ( i = 0 ; i < DRM_ARRAY_SIZE(dev->counts) ; i++ )
 		atomic_set( &dev->counts[i], 0 );
@@ -371,7 +247,9 @@ static int DRM(setup)( drm_device_t *dev )
 	 * drm_select_queue fails between the time the interrupt is
 	 * initialized and the time the queues are initialized.
 	 */
-	DRIVER_POSTSETUP();
+	if (dev->fn_tbl.postsetup)
+		dev->fn_tbl.postsetup(dev);
+
 	return 0;
 }
 
@@ -396,10 +274,10 @@ static int DRM(takedown)( drm_device_t *dev )
 
 	DRM_DEBUG( "\n" );
 
-	DRIVER_PRETAKEDOWN();
-#if __HAVE_IRQ
+	if (dev->fn_tbl.pretakedown)
+	  dev->fn_tbl.pretakedown(dev);
+
 	if ( dev->irq_enabled ) DRM(irq_uninstall)( dev );
-#endif
 
 	down( &dev->struct_sem );
 	del_timer( &dev->timer );
@@ -425,9 +303,8 @@ static int DRM(takedown)( drm_device_t *dev )
 		dev->magiclist[i].head = dev->magiclist[i].tail = NULL;
 	}
 
-#if __REALLY_HAVE_AGP
 				/* Clear AGP information */
-	if ( dev->agp ) {
+	if (drm_core_has_AGP(dev) && dev->agp) {
 		drm_agp_mem_t *entry;
 		drm_agp_mem_t *nexte;
 
@@ -446,7 +323,6 @@ static int DRM(takedown)( drm_device_t *dev )
 		dev->agp->acquired = 0;
 		dev->agp->enabled  = 0;
 	}
-#endif
 
 				/* Clear vma list (only built for debugging) */
 	if ( dev->vmalist ) {
@@ -465,15 +341,15 @@ static int DRM(takedown)( drm_device_t *dev )
 				switch ( map->type ) {
 				case _DRM_REGISTERS:
 				case _DRM_FRAME_BUFFER:
-#if __REALLY_HAVE_MTRR
-					if ( map->mtrr >= 0 ) {
-						int retcode;
-						retcode = mtrr_del( map->mtrr,
-								    map->offset,
-								    map->size );
-						DRM_DEBUG( "mtrr_del=%d\n", retcode );
+					if (drm_core_has_MTRR(dev)) {
+						if ( map->mtrr >= 0 ) {
+							int retcode;
+							retcode = mtrr_del( map->mtrr,
+									    map->offset,
+									    map->size );
+							DRM_DEBUG( "mtrr_del=%d\n", retcode );
+						}
 					}
-#endif
 					DRM(ioremapfree)( map->handle, map->size, dev );
 					break;
 				case _DRM_SHM:
@@ -486,15 +362,11 @@ static int DRM(takedown)( drm_device_t *dev )
 					 */
 					break;
 				case _DRM_SCATTER_GATHER:
-					/* Handle it, but do nothing, if HAVE_SG
-					 * isn't defined.
-					 */
-#if __HAVE_SG
-					if(dev->sg) {
+					/* Handle it */
+					if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg) {
 						DRM(sg_cleanup)(dev->sg);
 						dev->sg = NULL;
 					}
-#endif
 					break;
 				}
 				DRM(free)(map, sizeof(*map), DRM_MEM_MAPS);
@@ -506,12 +378,8 @@ static int DRM(takedown)( drm_device_t *dev )
 		dev->maplist = NULL;
  	}
 
-#if __HAVE_DMA_QUEUE || __HAVE_MULTIPLE_DMA_QUEUES
-	if ( dev->queuelist ) {
+	if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) && dev->queuelist ) {
 		for ( i = 0 ; i < dev->queue_count ; i++ ) {
-#if __HAVE_DMA_WAITLIST
-			DRM(waitlist_destroy)( &dev->queuelist[i]->waitlist );
-#endif
 			if ( dev->queuelist[i] ) {
 				DRM(free)( dev->queuelist[i],
 					  sizeof(*dev->queuelist[0]),
@@ -525,11 +393,10 @@ static int DRM(takedown)( drm_device_t *dev )
 		dev->queuelist = NULL;
 	}
 	dev->queue_count = 0;
-#endif
 
-#if __HAVE_DMA
-	DRM(dma_takedown)( dev );
-#endif
+	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+		DRM(dma_takedown)( dev );
+
 	if ( dev->lock.hw_lock ) {
 		dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */
 		dev->lock.filp = NULL;
@@ -540,6 +407,13 @@ static int DRM(takedown)( drm_device_t *dev )
 	return 0;
 }
 
+static void DRM(init_fn_table)(struct drm_device *dev)
+{
+	dev->fn_tbl.reclaim_buffers = DRM(core_reclaim_buffers);
+	dev->fn_tbl.get_map_ofs = DRM(core_get_map_ofs);
+	dev->fn_tbl.get_reg_ofs = DRM(core_get_reg_ofs);
+}
+
 #include "drm_pciids.h"
 
 static struct pci_device_id DRM(pciidlist)[] = {
@@ -549,9 +423,7 @@ static struct pci_device_id DRM(pciidlist)[] = {
 static int DRM(probe)(struct pci_dev *pdev)
 {
 	drm_device_t *dev;
-#if __HAVE_CTX_BITMAP
 	int retcode;
-#endif
 	int i;
 	int is_compat = 0;
 
@@ -569,6 +441,9 @@ static int DRM(probe)(struct pci_dev *pdev)
 	if (DRM(numdevs) >= MAX_DEVICES)
 		return -ENODEV;
 
+	if ((retcode=pci_enable_device(pdev)))
+		return retcode;
+
 	dev = &(DRM(device)[DRM(numdevs)]);
 
 	memset( (void *)dev, 0, sizeof(*dev) );
@@ -594,36 +469,51 @@ static int DRM(probe)(struct pci_dev *pdev)
 	dev->pci_func = PCI_FUNC(pdev->devfn);
 	dev->irq = pdev->irq;
 
-	DRIVER_PREINIT();
+	/* dev_priv_size can be changed by a driver in driver_register_fns */
+	dev->dev_priv_size = sizeof(u32);
 
-#if __REALLY_HAVE_AGP
-	dev->agp = DRM(agp_init)();
-#if __MUST_HAVE_AGP
-	if ( dev->agp == NULL ) {
-		DRM_ERROR( "Cannot initialize the agpgart module.\n" );
-		DRM(stub_unregister)(dev->minor);
-		DRM(takedown)( dev );
-		return -EINVAL;
+	/* the DRM has 6 basic counters - drivers add theirs in register_fns */
+	dev->counters = 6;
+	dev->types[0]  = _DRM_STAT_LOCK;
+	dev->types[1]  = _DRM_STAT_OPENS;
+	dev->types[2]  = _DRM_STAT_CLOSES;
+	dev->types[3]  = _DRM_STAT_IOCTLS;
+	dev->types[4]  = _DRM_STAT_LOCKS;
+	dev->types[5]  = _DRM_STAT_UNLOCKS;
+
+	DRM(init_fn_table)(dev);
+
+	DRM(driver_register_fns)(dev);
+
+	if (dev->fn_tbl.preinit)
+	  dev->fn_tbl.preinit(dev);
+
+	if (drm_core_has_AGP(dev))
+	{
+		dev->agp = DRM(agp_init)();
+		if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && (dev->agp == NULL)) {
+			DRM_ERROR( "Cannot initialize the agpgart module.\n" );
+			DRM(stub_unregister)(dev->minor);
+			DRM(takedown)( dev );
+			return -EINVAL;
+		}
+		if (drm_core_has_MTRR(dev)) {
+			if (dev->agp)
+				dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base,
+							       dev->agp->agp_info.aper_size*1024*1024,
+							       MTRR_TYPE_WRCOMB,
+							       1 );
+		}
 	}
-#endif
-#if __REALLY_HAVE_MTRR
-	if (dev->agp)
-		dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base,
-					dev->agp->agp_info.aper_size*1024*1024,
-					MTRR_TYPE_WRCOMB,
-					1 );
-#endif
-#endif
 
-#if __HAVE_CTX_BITMAP
 	retcode = DRM(ctxbitmap_init)( dev );
 	if( retcode ) {
 		DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
 		DRM(stub_unregister)(dev->minor);
 		DRM(takedown)( dev );
 		return retcode;
- 	}
-#endif
+	}
+
 	DRM(numdevs)++; /* no errors, mark it reserved */
 	
 	DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d: %s\n",
@@ -635,7 +525,8 @@ static int DRM(probe)(struct pci_dev *pdev)
 		dev->minor,
 		pci_pretty_name(pdev));
 
-	DRIVER_POSTINIT();
+	if (dev->fn_tbl.postinit)
+	  dev->fn_tbl.postinit(dev);
 
 	return 0;
 }
@@ -695,31 +586,30 @@ static void __exit drm_cleanup( void )
 				DRM_INFO( "Module unloaded\n" );
 			}
 		}
-#if __HAVE_CTX_BITMAP
+
 		DRM(ctxbitmap_cleanup)( dev );
-#endif
 
-#if __REALLY_HAVE_AGP && __REALLY_HAVE_MTRR
-		if ( dev->agp && dev->agp->agp_mtrr >= 0) {
+		if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
+		    dev->agp && dev->agp->agp_mtrr >= 0) {
 			int retval;
 			retval = mtrr_del( dev->agp->agp_mtrr,
 				   dev->agp->agp_info.aper_base,
 				   dev->agp->agp_info.aper_size*1024*1024 );
 			DRM_DEBUG( "mtrr_del=%d\n", retval );
 		}
-#endif
 
 		DRM(takedown)( dev );
 
-#if __REALLY_HAVE_AGP
-		if ( dev->agp ) {
+		if (drm_core_has_AGP(dev) && dev->agp ) {
 			DRM(agp_uninit)();
 			DRM(free)( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
 			dev->agp = NULL;
 		}
-#endif
+
+		if (dev->fn_tbl.postcleanup)
+		  dev->fn_tbl.postcleanup(dev);
+
 	}
-	DRIVER_POSTCLEANUP();
 	DRM(numdevs) = 0;
 }
 
@@ -834,7 +724,8 @@ int DRM(release)( struct inode *inode, struct file *filp )
 
 	DRM_DEBUG( "open_count = %d\n", dev->open_count );
 
-	DRIVER_PRERELEASE();
+	if (dev->fn_tbl.prerelease)
+		dev->fn_tbl.prerelease(dev, filp);
 
 	/* ========================================================
 	 * Begin inline drm_release
@@ -849,9 +740,10 @@ int DRM(release)( struct inode *inode, struct file *filp )
 		DRM_DEBUG( "File %p released, freeing lock for context %d\n",
 			filp,
 			_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) );
-#if __HAVE_RELEASE
-		DRIVER_RELEASE();
-#endif
+		
+		if (dev->fn_tbl.release)
+			dev->fn_tbl.release(dev, filp);
+
 		DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
 				_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) );
 
@@ -860,14 +752,13 @@ int DRM(release)( struct inode *inode, struct file *filp )
                                    processed via a callback to the X
                                    server. */
 	}
-#if __HAVE_RELEASE
-	else if ( priv->lock_count && dev->lock.hw_lock ) {
+	else if ( dev->fn_tbl.release && priv->lock_count && dev->lock.hw_lock ) {
 		/* The lock is required to reclaim buffers */
 		DECLARE_WAITQUEUE( entry, current );
 
 		add_wait_queue( &dev->lock.lock_queue, &entry );
 		for (;;) {
-			current->state = TASK_INTERRUPTIBLE;
+			__set_current_state(TASK_INTERRUPTIBLE);
 			if ( !dev->lock.hw_lock ) {
 				/* Device has been unregistered */
 				retcode = -EINTR;
@@ -887,17 +778,20 @@ int DRM(release)( struct inode *inode, struct file *filp )
 				break;
 			}
 		}
-		current->state = TASK_RUNNING;
+		__set_current_state(TASK_RUNNING);
 		remove_wait_queue( &dev->lock.lock_queue, &entry );
 		if( !retcode ) {
-			DRIVER_RELEASE();
+			if (dev->fn_tbl.release)
+				dev->fn_tbl.release(dev, filp);
 			DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
 					DRM_KERNEL_CONTEXT );
 		}
 	}
-#elif __HAVE_DMA
-	DRM(reclaim_buffers)( filp );
-#endif
+	
+	if (drm_core_check_feature(dev, DRIVER_HAVE_DMA))
+	{
+		dev->fn_tbl.reclaim_buffers(filp);
+	}
 
 	DRM(fasync)( -1, filp, 0 );
 
@@ -908,14 +802,14 @@ int DRM(release)( struct inode *inode, struct file *filp )
 		list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) {
 			if ( pos->tag == priv &&
 			     pos->handle != DRM_KERNEL_CONTEXT ) {
-#ifdef DRIVER_CTX_DTOR
-				DRIVER_CTX_DTOR(pos->handle);
-#endif
-#if __HAVE_CTX_BITMAP
+				if (dev->fn_tbl.context_dtor)
+					dev->fn_tbl.context_dtor(dev, pos->handle);
+
 				DRM(ctxbitmap_free)( dev, pos->handle );
-#endif
+
 				list_del( &pos->head );
 				DRM(free)( pos, sizeof(*pos), DRM_MEM_CTXLIST );
+				--dev->ctx_count;
 			}
 		}
 	}
@@ -941,6 +835,9 @@ int DRM(release)( struct inode *inode, struct file *filp )
 	}
 	up( &dev->struct_sem );
 	
+	if (dev->fn_tbl.free_filp_priv)
+		dev->fn_tbl.free_filp_priv(dev, priv);
+
 	DRM(free)( priv, sizeof(*priv), DRM_MEM_FILES );
 
 	/* ========================================================
@@ -1039,9 +936,6 @@ int DRM(lock)( struct inode *inode, struct file *filp,
         DECLARE_WAITQUEUE( entry, current );
         drm_lock_t lock;
         int ret = 0;
-#if __HAVE_MULTIPLE_DMA_QUEUES
-	drm_queue_t *q;
-#endif
 
 	++priv->lock_count;
 
@@ -1058,83 +952,61 @@ int DRM(lock)( struct inode *inode, struct file *filp,
 		   lock.context, current->pid,
 		   dev->lock.hw_lock->lock, lock.flags );
 
-#if __HAVE_DMA_QUEUE
-        if ( lock.context < 0 )
-                return -EINVAL;
-#elif __HAVE_MULTIPLE_DMA_QUEUES
-        if ( lock.context < 0 || lock.context >= dev->queue_count )
-                return -EINVAL;
-	q = dev->queuelist[lock.context];
-#endif
+	if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE))
+		if ( lock.context < 0 )
+			return -EINVAL;
 
-#if __HAVE_DMA_FLUSH
-	ret = DRM(flush_block_and_flush)( dev, lock.context, lock.flags );
-#endif
-        if ( !ret ) {
-                add_wait_queue( &dev->lock.lock_queue, &entry );
-                for (;;) {
-                        current->state = TASK_INTERRUPTIBLE;
-                        if ( !dev->lock.hw_lock ) {
-                                /* Device has been unregistered */
-                                ret = -EINTR;
-                                break;
-                        }
-                        if ( DRM(lock_take)( &dev->lock.hw_lock->lock,
-					     lock.context ) ) {
-                                dev->lock.filp      = filp;
-                                dev->lock.lock_time = jiffies;
-                                atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
-                                break;  /* Got lock */
-                        }
-
-                                /* Contention */
-                        schedule();
-                        if ( signal_pending( current ) ) {
-                                ret = -ERESTARTSYS;
-                                break;
-                        }
-                }
-                current->state = TASK_RUNNING;
-                remove_wait_queue( &dev->lock.lock_queue, &entry );
-        }
-
-#if __HAVE_DMA_FLUSH
-	DRM(flush_unblock)( dev, lock.context, lock.flags ); /* cleanup phase */
-#endif
-
-        if ( !ret ) {
-		sigemptyset( &dev->sigmask );
-		sigaddset( &dev->sigmask, SIGSTOP );
-		sigaddset( &dev->sigmask, SIGTSTP );
-		sigaddset( &dev->sigmask, SIGTTIN );
-		sigaddset( &dev->sigmask, SIGTTOU );
-		dev->sigdata.context = lock.context;
-		dev->sigdata.lock    = dev->lock.hw_lock;
-		block_all_signals( DRM(notifier),
-				   &dev->sigdata, &dev->sigmask );
-
-#if __HAVE_DMA_READY
-                if ( lock.flags & _DRM_LOCK_READY ) {
-			DRIVER_DMA_READY();
+	add_wait_queue( &dev->lock.lock_queue, &entry );
+	for (;;) {
+		__set_current_state(TASK_INTERRUPTIBLE);
+		if ( !dev->lock.hw_lock ) {
+			/* Device has been unregistered */
+			ret = -EINTR;
+			break;
 		}
-#endif
-#if __HAVE_DMA_QUIESCENT
-                if ( lock.flags & _DRM_LOCK_QUIESCENT ) {
-			DRIVER_DMA_QUIESCENT();
+		if ( DRM(lock_take)( &dev->lock.hw_lock->lock,
+				     lock.context ) ) {
+			dev->lock.filp      = filp;
+			dev->lock.lock_time = jiffies;
+			atomic_inc( &dev->counts[_DRM_STAT_LOCKS] );
+			break;  /* Got lock */
 		}
-#endif
-		/* __HAVE_KERNEL_CTX_SWITCH isn't used by any of the
-		 * drm modules in the DRI cvs tree, but it is required
-		 * by the Sparc driver.
-		 */
-#if __HAVE_KERNEL_CTX_SWITCH
-		if ( dev->last_context != lock.context ) {
-			DRM(context_switch)(dev, dev->last_context,
-					    lock.context);
+		
+		/* Contention */
+		schedule();
+		if ( signal_pending( current ) ) {
+			ret = -ERESTARTSYS;
+			break;
 		}
-#endif
-        }
-
+	}
+	__set_current_state(TASK_RUNNING);
+	remove_wait_queue( &dev->lock.lock_queue, &entry );
+
+	sigemptyset( &dev->sigmask );
+	sigaddset( &dev->sigmask, SIGSTOP );
+	sigaddset( &dev->sigmask, SIGTSTP );
+	sigaddset( &dev->sigmask, SIGTTIN );
+	sigaddset( &dev->sigmask, SIGTTOU );
+	dev->sigdata.context = lock.context;
+	dev->sigdata.lock    = dev->lock.hw_lock;
+	block_all_signals( DRM(notifier),
+			   &dev->sigdata, &dev->sigmask );
+	
+	if (dev->fn_tbl.dma_ready && (lock.flags & _DRM_LOCK_READY))
+		dev->fn_tbl.dma_ready(dev);
+	
+	if ( dev->fn_tbl.dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT ))
+		return dev->fn_tbl.dma_quiescent(dev);
+	
+	/* dev->fn_tbl.kernel_context_switch isn't used by any of the x86 
+	 *  drivers but is used by the Sparc driver.
+	 */
+	
+	if (dev->fn_tbl.kernel_context_switch && 
+	    dev->last_context != lock.context) {
+	  dev->fn_tbl.kernel_context_switch(dev, dev->last_context, 
+					    lock.context);
+	}
         DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" );
 
         return ret;
@@ -1169,40 +1041,20 @@ int DRM(unlock)( struct inode *inode, struct file *filp,
 
 	atomic_inc( &dev->counts[_DRM_STAT_UNLOCKS] );
 
-	/* __HAVE_KERNEL_CTX_SWITCH isn't used by any of the drm
-	 * modules in the DRI cvs tree, but it is required by the
-	 * Sparc driver.
-	 */
-#if __HAVE_KERNEL_CTX_SWITCH
-	/* We no longer really hold it, but if we are the next
-	 * agent to request it then we should just be able to
-	 * take it immediately and not eat the ioctl.
+	/* kernel_context_switch isn't used by any of the x86 drm
+	 * modules but is required by the Sparc driver.
 	 */
-	dev->lock.filp = NULL;
-	{
-		__volatile__ unsigned int *plock = &dev->lock.hw_lock->lock;
-		unsigned int old, new, prev, ctx;
-
-		ctx = lock.context;
-		do {
-			old  = *plock;
-			new  = ctx;
-			prev = cmpxchg(plock, old, new);
-		} while (prev != old);
-	}
-	wake_up_interruptible(&dev->lock.lock_queue);
-#else
-	DRM(lock_transfer)( dev, &dev->lock.hw_lock->lock,
-			    DRM_KERNEL_CONTEXT );
-#if __HAVE_DMA_SCHEDULE
-	DRM(dma_schedule)( dev, 1 );
-#endif
-
-	if ( DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
-			     DRM_KERNEL_CONTEXT ) ) {
-		DRM_ERROR( "\n" );
+	if (dev->fn_tbl.kernel_context_switch_unlock)
+		dev->fn_tbl.kernel_context_switch_unlock(dev, &lock);
+	else {
+		DRM(lock_transfer)( dev, &dev->lock.hw_lock->lock, 
+				    DRM_KERNEL_CONTEXT );
+		
+		if ( DRM(lock_free)( dev, &dev->lock.hw_lock->lock,
+				     DRM_KERNEL_CONTEXT ) ) {
+			DRM_ERROR( "\n" );
+		}
 	}
-#endif /* !__HAVE_KERNEL_CTX_SWITCH */
 
 	unblock_all_signals();
 	return 0;
diff --git a/drivers/char/drm/drm_fops.h b/drivers/char/drm/drm_fops.h
index 0aa02444a..0e91190a3 100644
--- a/drivers/char/drm/drm_fops.h
+++ b/drivers/char/drm/drm_fops.h
@@ -53,6 +53,7 @@ int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
 {
 	int	     minor = iminor(inode);
 	drm_file_t   *priv;
+	int ret;
 
 	if (filp->f_flags & O_EXCL)   return -EBUSY; /* No exclusive opens */
 	if (!DRM(cpu_valid)())        return -EINVAL;
@@ -72,7 +73,11 @@ int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
 	priv->authenticated = capable(CAP_SYS_ADMIN);
 	priv->lock_count    = 0;
 
-	DRIVER_OPEN_HELPER( priv, dev );
+	if (dev->fn_tbl.open_helper) {
+		ret=dev->fn_tbl.open_helper(dev, priv);
+		if (ret < 0)
+			goto out_free;
+	}
 
 	down(&dev->struct_sem);
 	if (!dev->file_last) {
@@ -104,6 +109,10 @@ int DRM(open_helper)(struct inode *inode, struct file *filp, drm_device_t *dev)
 #endif
 
 	return 0;
+out_free:
+	DRM(free)(priv, sizeof(*priv), DRM_MEM_FILES);
+	filp->private_data=NULL;
+	return ret;
 }
 
 /** No-op. */
@@ -130,19 +139,15 @@ int DRM(fasync)(int fd, struct file *filp, int on)
 	return 0;
 }
 
-#if !__HAVE_DRIVER_FOPS_POLL
 /** No-op. */
 unsigned int DRM(poll)(struct file *filp, struct poll_table_struct *wait)
 {
 	return 0;
 }
-#endif
 
 
-#if !__HAVE_DRIVER_FOPS_READ
 /** No-op. */
 ssize_t DRM(read)(struct file *filp, char __user *buf, size_t count, loff_t *off)
 {
 	return 0;
 }
-#endif
diff --git a/drivers/char/drm/drm_ioctl.h b/drivers/char/drm/drm_ioctl.h
index ef6532a31..d1271c166 100644
--- a/drivers/char/drm/drm_ioctl.h
+++ b/drivers/char/drm/drm_ioctl.h
@@ -341,9 +341,9 @@ int DRM(setversion)(DRM_IOCTL_ARGS)
 		if (sv.drm_dd_major != DRIVER_MAJOR ||
 		    sv.drm_dd_minor < 0 || sv.drm_dd_minor > DRIVER_MINOR)
 			return EINVAL;
-#ifdef DRIVER_SETVERSION
-		DRIVER_SETVERSION(dev, &sv);
-#endif
+
+		if (dev->fn_tbl.set_version)
+			dev->fn_tbl.set_version(dev, &sv);
 	}
 	return 0;
 }
diff --git a/drivers/char/drm/drm_irq.h b/drivers/char/drm/drm_irq.h
index 04bb0ac11..d26c999fe 100644
--- a/drivers/char/drm/drm_irq.h
+++ b/drivers/char/drm/drm_irq.h
@@ -37,16 +37,6 @@
 
 #include <linux/interrupt.h>	/* For task queue support */
 
-#ifndef __HAVE_SHARED_IRQ
-#define __HAVE_SHARED_IRQ	0
-#endif
-
-#if __HAVE_SHARED_IRQ
-#define DRM_IRQ_TYPE		SA_SHIRQ
-#else
-#define DRM_IRQ_TYPE		0
-#endif
-
 /**
  * Get interrupt from bus id.
  * 
@@ -68,6 +58,9 @@ int DRM(irq_by_busid)(struct inode *inode, struct file *filp,
 	drm_irq_busid_t __user *argp = (void __user *)arg;
 	drm_irq_busid_t p;
 
+	if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+		return -EINVAL;
+
 	if (copy_from_user(&p, argp, sizeof(p)))
 		return -EFAULT;
 
@@ -86,8 +79,6 @@ int DRM(irq_by_busid)(struct inode *inode, struct file *filp,
 	return 0;
 }
 
-#if __HAVE_IRQ
-
 /**
  * Install IRQ handler.
  *
@@ -101,7 +92,11 @@ int DRM(irq_by_busid)(struct inode *inode, struct file *filp,
 int DRM(irq_install)( drm_device_t *dev )
 {
 	int ret;
- 
+	unsigned long sh_flags=0;
+
+	if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+		return -EINVAL;
+
 	if ( dev->irq == 0 )
 		return -EINVAL;
 
@@ -122,32 +117,25 @@ int DRM(irq_install)( drm_device_t *dev )
 
 	DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
 
-#if __HAVE_DMA
-	dev->dma->next_buffer = NULL;
-	dev->dma->next_queue = NULL;
-	dev->dma->this_buffer = NULL;
-#endif
-
-#ifdef __HAVE_IRQ_BH
-	INIT_WORK(&dev->work, DRM(irq_immediate_bh), dev);
-#endif
-
-#ifdef __HAVE_VBL_IRQ
-	init_waitqueue_head(&dev->vbl_queue);
-
-	spin_lock_init( &dev->vbl_lock );
-
-	INIT_LIST_HEAD( &dev->vbl_sigs.head );
-
-	dev->vbl_pending = 0;
-#endif
+	if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
+		init_waitqueue_head(&dev->vbl_queue);
+		
+		spin_lock_init( &dev->vbl_lock );
+		
+		INIT_LIST_HEAD( &dev->vbl_sigs.head );
+		
+		dev->vbl_pending = 0;
+	}
 
 				/* Before installing handler */
-	DRM(driver_irq_preinstall)(dev);
+	dev->fn_tbl.irq_preinstall(dev);
 
 				/* Install handler */
-	ret = request_irq( dev->irq, DRM(irq_handler),
-			   DRM_IRQ_TYPE, dev->devname, dev );
+	if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED))
+		sh_flags = SA_SHIRQ;
+	
+	ret = request_irq( dev->irq, dev->fn_tbl.irq_handler,
+			   sh_flags, dev->devname, dev );
 	if ( ret < 0 ) {
 		down( &dev->struct_sem );
 		dev->irq_enabled = 0;
@@ -156,7 +144,7 @@ int DRM(irq_install)( drm_device_t *dev )
 	}
 
 				/* After installing handler */
-	DRM(driver_irq_postinstall)(dev);
+	dev->fn_tbl.irq_postinstall(dev);
 
 	return 0;
 }
@@ -172,6 +160,9 @@ int DRM(irq_uninstall)( drm_device_t *dev )
 {
 	int irq_enabled;
 
+	if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+		return -EINVAL;
+
 	down( &dev->struct_sem );
 	irq_enabled = dev->irq_enabled;
 	dev->irq_enabled = 0;
@@ -182,7 +173,7 @@ int DRM(irq_uninstall)( drm_device_t *dev )
 
 	DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq );
 
-	DRM(driver_irq_uninstall)( dev );
+	dev->fn_tbl.irq_uninstall(dev);
 
 	free_irq( dev->irq, dev );
 
@@ -206,25 +197,29 @@ int DRM(control)( struct inode *inode, struct file *filp,
 	drm_file_t *priv = filp->private_data;
 	drm_device_t *dev = priv->dev;
 	drm_control_t ctl;
+	
+	/* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */
 
 	if ( copy_from_user( &ctl, (drm_control_t __user *)arg, sizeof(ctl) ) )
 		return -EFAULT;
 
 	switch ( ctl.func ) {
 	case DRM_INST_HANDLER:
+		if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+			return 0;
 		if (dev->if_version < DRM_IF_VERSION(1, 2) &&
 		    ctl.irq != dev->irq)
 			return -EINVAL;
 		return DRM(irq_install)( dev );
 	case DRM_UNINST_HANDLER:
+		if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+			return 0;
 		return DRM(irq_uninstall)( dev );
 	default:
 		return -EINVAL;
 	}
 }
 
-#ifdef __HAVE_VBL_IRQ
-
 /**
  * Wait for VBLANK.
  *
@@ -254,6 +249,9 @@ int DRM(wait_vblank)( DRM_IOCTL_ARGS )
 	int ret = 0;
 	unsigned int flags;
 
+	if (!drm_core_check_feature(dev, DRIVER_IRQ_VBL))
+		return -EINVAL;
+
 	if (!dev->irq)
 		return -EINVAL;
 
@@ -318,7 +316,8 @@ int DRM(wait_vblank)( DRM_IOCTL_ARGS )
 
 		spin_unlock_irqrestore( &dev->vbl_lock, irqflags );
 	} else {
-		ret = DRM(vblank_wait)( dev, &vblwait.request.sequence );
+		if (dev->fn_tbl.vblank_wait)
+			ret = dev->fn_tbl.vblank_wait( dev, &vblwait.request.sequence );
 
 		do_gettimeofday( &now );
 		vblwait.reply.tval_sec = now.tv_sec;
@@ -366,6 +365,4 @@ void DRM(vbl_send_signals)( drm_device_t *dev )
 	spin_unlock_irqrestore( &dev->vbl_lock, flags );
 }
 
-#endif	/* __HAVE_VBL_IRQ */
 
-#endif /* __HAVE_IRQ */
diff --git a/drivers/char/drm/drm_memory.h b/drivers/char/drm/drm_memory.h
index 9adfe790d..c68e8d5eb 100644
--- a/drivers/char/drm/drm_memory.h
+++ b/drivers/char/drm/drm_memory.h
@@ -44,7 +44,7 @@
  */
 #define DEBUG_MEMORY 0
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 
 #include <linux/vmalloc.h>
 
@@ -130,46 +130,56 @@ drm_follow_page (void *vaddr)
 	return pte_pfn(*ptep) << PAGE_SHIFT;
 }
 
-#endif /* __REALLY_HAVE_AGP */
+#else /* __OS_HAS_AGP */
+
+static inline drm_map_t *drm_lookup_map(unsigned long offset, unsigned long size, drm_device_t *dev)
+{
+  return NULL;
+}
+
+static inline void *agp_remap(unsigned long offset, unsigned long size, drm_device_t *dev)
+{
+  return NULL;
+}
+
+static inline unsigned long drm_follow_page (void *vaddr)
+{
+  return 0;
+}
+
+#endif
 
 static inline void *drm_ioremap(unsigned long offset, unsigned long size, drm_device_t *dev)
 {
-#if __REALLY_HAVE_AGP
-	if (dev->agp && dev->agp->cant_use_aperture) {
+	if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
 		drm_map_t *map = drm_lookup_map(offset, size, dev);
 
 		if (map && map->type == _DRM_AGP)
 			return agp_remap(offset, size, dev);
 	}
-#endif
-
 	return ioremap(offset, size);
 }
 
 static inline void *drm_ioremap_nocache(unsigned long offset, unsigned long size,
 					drm_device_t *dev)
 {
-#if __REALLY_HAVE_AGP
-	if (dev->agp && dev->agp->cant_use_aperture) {
+	if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
 		drm_map_t *map = drm_lookup_map(offset, size, dev);
 
 		if (map && map->type == _DRM_AGP)
 			return agp_remap(offset, size, dev);
 	}
-#endif
-
 	return ioremap_nocache(offset, size);
 }
 
 static inline void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev)
 {
-#if __REALLY_HAVE_AGP
 	/*
 	 * This is a bit ugly.  It would be much cleaner if the DRM API would use separate
 	 * routines for handling mappings in the AGP space.  Hopefully this can be done in
 	 * a future revision of the interface...
 	 */
-	if (dev->agp && dev->agp->cant_use_aperture
+	if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture
 	    && ((unsigned long) pt >= VMALLOC_START && (unsigned long) pt < VMALLOC_END))
 	{
 		unsigned long offset;
@@ -182,11 +192,11 @@ static inline void drm_ioremapfree(void *pt, unsigned long size, drm_device_t *d
 			return;
 		}
 	}
-#endif
 
 	iounmap(pt);
 }
 
+
 #if DEBUG_MEMORY
 #include "drm_memory_debug.h"
 #else
@@ -331,7 +341,7 @@ void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev)
 	drm_ioremapfree(pt, size, dev);
 }
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 /** Wrapper around agp_allocate_memory() */
 DRM_AGP_MEM *DRM(alloc_agp)(int pages, u32 type)
 {
diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h
index 74d3c499e..0053679a8 100644
--- a/drivers/char/drm/drm_memory_debug.h
+++ b/drivers/char/drm/drm_memory_debug.h
@@ -352,7 +352,7 @@ void DRM(ioremapfree)(void *pt, unsigned long size, drm_device_t *dev)
 	}
 }
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 
 DRM_AGP_MEM *DRM(alloc_agp)(int pages, u32 type)
 {
diff --git a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h
index 6b69f0aa3..242e311a2 100644
--- a/drivers/char/drm/drm_os_linux.h
+++ b/drivers/char/drm/drm_os_linux.h
@@ -16,13 +16,17 @@
 #define DRM_CURRENTPID			current->pid
 #define DRM_UDELAY(d)			udelay(d)
 /** Read a byte from a MMIO region */
-#define DRM_READ8(map, offset)		readb(((unsigned long)(map)->handle) + (offset))
+#define DRM_READ8(map, offset)		readb(((void __iomem *)(map)->handle) + (offset))
+/** Read a word from a MMIO region */
+#define DRM_READ16(map, offset)         readw(((void __iomem *)(map)->handle) + (offset))
 /** Read a dword from a MMIO region */
-#define DRM_READ32(map, offset)		readl(((unsigned long)(map)->handle) + (offset))
+#define DRM_READ32(map, offset)		readl(((void __iomem *)(map)->handle) + (offset))
 /** Write a byte into a MMIO region */
-#define DRM_WRITE8(map, offset, val)	writeb(val, ((unsigned long)(map)->handle) + (offset))
+#define DRM_WRITE8(map, offset, val)	writeb(val, ((void __iomem *)(map)->handle) + (offset))
+/** Write a word into a MMIO region */
+#define DRM_WRITE16(map, offset, val)   writew(val, ((void __iomem *)(map)->handle) + (offset))
 /** Write a dword into a MMIO region */
-#define DRM_WRITE32(map, offset, val)	writel(val, ((unsigned long)(map)->handle) + (offset))
+#define DRM_WRITE32(map, offset, val)	writel(val, ((void __iomem *)(map)->handle) + (offset))
 /** Read memory barrier */
 #define DRM_READMEMORYBARRIER()		rmb()
 /** Write memory barrier */
@@ -37,8 +41,34 @@
 #define DRM_IRQ_ARGS		int irq, void *arg, struct pt_regs *regs
 
 /** AGP types */
+#if __OS_HAS_AGP
 #define DRM_AGP_MEM		struct agp_memory
 #define DRM_AGP_KERN		struct agp_kern_info
+#else
+/* define some dummy types for non AGP supporting kernels */
+struct no_agp_kern {
+  unsigned long aper_base;
+  unsigned long aper_size;
+};
+#define DRM_AGP_MEM             int
+#define DRM_AGP_KERN            struct no_agp_kern
+#endif
+
+#if !(__OS_HAS_MTRR)
+static __inline__ int mtrr_add (unsigned long base, unsigned long size,
+                                unsigned int type, char increment)
+{
+	return -ENODEV;
+}
+
+static __inline__ int mtrr_del (int reg, unsigned long base,
+                                unsigned long size)
+{
+	return -ENODEV;
+}
+#define MTRR_TYPE_WRCOMB     1
+
+#endif
 
 /** Task queue handler arguments */
 #define DRM_TASKQUEUE_ARGS	void *arg
@@ -104,7 +134,7 @@ do {								\
 	add_wait_queue(&(queue), &entry);			\
 								\
 	for (;;) {						\
-		current->state = TASK_INTERRUPTIBLE;		\
+		__set_current_state(TASK_INTERRUPTIBLE);	\
 		if (condition)					\
 			break;					\
 		if (time_after_eq(jiffies, end)) {		\
@@ -117,7 +147,7 @@ do {								\
 			break;					\
 		}						\
 	}							\
-	current->state = TASK_RUNNING;				\
+	__set_current_state(TASK_RUNNING);			\
 	remove_wait_queue(&(queue), &entry);			\
 } while (0)
 
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
index 3b5f8d3a2..768c131d2 100644
--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -201,3 +201,11 @@
 #define ffb_PCI_IDS \
 	{0, 0, 0}
 
+#define i915_PCI_IDS \
+	{0x8086, 0x3577, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+	{0x8086, 0x2562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+	{0x8086, 0x3582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+	{0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+	{0x8086, 0x2582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+	{0, 0, 0}
+
diff --git a/drivers/char/drm/drm_scatter.h b/drivers/char/drm/drm_scatter.h
index e5d829367..436a0170e 100644
--- a/drivers/char/drm/drm_scatter.h
+++ b/drivers/char/drm/drm_scatter.h
@@ -73,6 +73,9 @@ int DRM(sg_alloc)( struct inode *inode, struct file *filp,
 
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
+	if (!drm_core_check_feature(dev, DRIVER_SG))
+		return -EINVAL;
+
 	if ( dev->sg )
 		return -EINVAL;
 
@@ -206,6 +209,9 @@ int DRM(sg_free)( struct inode *inode, struct file *filp,
 	drm_scatter_gather_t request;
 	drm_sg_mem_t *entry;
 
+	if (!drm_core_check_feature(dev, DRIVER_SG))
+		return -EINVAL;
+
 	if ( copy_from_user( &request,
 			     (drm_scatter_gather_t __user *)arg,
 			     sizeof(request) ) )
diff --git a/drivers/char/drm/drm_vm.h b/drivers/char/drm/drm_vm.h
index d7dce3ae9..1601447d8 100644
--- a/drivers/char/drm/drm_vm.h
+++ b/drivers/char/drm/drm_vm.h
@@ -46,10 +46,10 @@
  * Find the right map and if it's AGP memory find the real physical page to
  * map, get the page, increment the use count and return it.
  */
+#if __OS_HAS_AGP
 static __inline__ struct page *DRM(do_vm_nopage)(struct vm_area_struct *vma,
 						 unsigned long address)
 {
-#if __REALLY_HAVE_AGP
 	drm_file_t *priv  = vma->vm_file->private_data;
 	drm_device_t *dev = priv->dev;
 	drm_map_t *map    = NULL;
@@ -59,6 +59,8 @@ static __inline__ struct page *DRM(do_vm_nopage)(struct vm_area_struct *vma,
 	/*
          * Find the right map
          */
+	if (!drm_core_has_AGP(dev))
+		goto vm_nopage_error;
 
 	if(!dev->agp || !dev->agp->cant_use_aperture) goto vm_nopage_error;
 
@@ -107,10 +109,15 @@ static __inline__ struct page *DRM(do_vm_nopage)(struct vm_area_struct *vma,
 		return page;
         }
 vm_nopage_error:
-#endif /* __REALLY_HAVE_AGP */
-
 	return NOPAGE_SIGBUS;		/* Disallow mremap */
 }
+#else /* __OS_HAS_AGP */
+static __inline__ struct page *DRM(do_vm_nopage)(struct vm_area_struct *vma,
+						 unsigned long address)
+{
+	return NOPAGE_SIGBUS;
+}
+#endif /* __OS_HAS_AGP */
 
 /**
  * \c nopage method for shared virtual memory.
@@ -201,15 +208,13 @@ void DRM(vm_shm_close)(struct vm_area_struct *vma)
 			switch (map->type) {
 			case _DRM_REGISTERS:
 			case _DRM_FRAME_BUFFER:
-#if __REALLY_HAVE_MTRR
-				if (map->mtrr >= 0) {
+				if (drm_core_has_MTRR(dev) && map->mtrr >= 0) {
 					int retcode;
 					retcode = mtrr_del(map->mtrr,
 							   map->offset,
 							   map->size);
 					DRM_DEBUG("mtrr_del = %d\n", retcode);
 				}
-#endif
 				DRM(ioremapfree)(map->handle, map->size, dev);
 				break;
 			case _DRM_SHM:
@@ -488,18 +493,19 @@ int DRM(mmap_dma)(struct file *filp, struct vm_area_struct *vma)
 	return 0;
 }
 
-#ifndef DRIVER_GET_MAP_OFS
-#define DRIVER_GET_MAP_OFS()	(map->offset)
-#endif
+unsigned long DRM(core_get_map_ofs)(drm_map_t *map)
+{
+	return map->offset;
+}
 
-#ifndef DRIVER_GET_REG_OFS
+unsigned long DRM(core_get_reg_ofs)(struct drm_device *dev)
+{
 #ifdef __alpha__
-#define DRIVER_GET_REG_OFS()	(dev->hose->dense_mem_base -	\
-				 dev->hose->mem_space->start)
+	return dev->hose->dense_mem_base - dev->hose->mem_space->start;
 #else
-#define DRIVER_GET_REG_OFS()	0
-#endif
+	return 0;
 #endif
+}
 
 /**
  * mmap DMA memory.
@@ -533,7 +539,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
 	 * --BenH.
 	 */
 	if (!VM_OFFSET(vma)
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	    && (!dev->agp || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE)
 #endif
 	    )
@@ -552,7 +558,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
 		r_list = list_entry(list, drm_map_list_t, head);
 		map = r_list->map;
 		if (!map) continue;
-		off = DRIVER_GET_MAP_OFS();
+		off = dev->fn_tbl.get_map_ofs(map);
 		if (off == VM_OFFSET(vma)) break;
 	}
 
@@ -577,8 +583,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
 
 	switch (map->type) {
         case _DRM_AGP:
-#if __REALLY_HAVE_AGP
-	  if (dev->agp->cant_use_aperture) {
+	  if (drm_core_has_AGP(dev) && dev->agp->cant_use_aperture) {
                 /*
                  * On some platforms we can't talk to bus dma address from the CPU, so for
                  * memory of type DRM_AGP, we'll deal with sorting out the real physical
@@ -590,7 +595,6 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
                 vma->vm_ops = &DRM(vm_ops);
                 break;
 	  }
-#endif
                 /* fall through to _DRM_FRAME_BUFFER... */        
 	case _DRM_FRAME_BUFFER:
 	case _DRM_REGISTERS:
@@ -609,7 +613,7 @@ int DRM(mmap)(struct file *filp, struct vm_area_struct *vma)
 		if (map->type != _DRM_AGP)
 			vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
 #endif
-		offset = DRIVER_GET_REG_OFS();
+		offset = dev->fn_tbl.get_reg_ofs(dev);
 #ifdef __sparc__
 		if (io_remap_page_range(DRM_RPR_ARG(vma) vma->vm_start,
 					VM_OFFSET(vma) + offset,
diff --git a/drivers/char/drm/ffb.h b/drivers/char/drm/ffb.h
index af35783b2..3691c8652 100644
--- a/drivers/char/drm/ffb.h
+++ b/drivers/char/drm/ffb.h
@@ -8,9 +8,5 @@
  */
 #define DRM(x) ffb_##x
 
-/* General customization:
- */
-#define __HAVE_KERNEL_CTX_SWITCH	1
-#define __HAVE_RELEASE			1
 #endif
 
diff --git a/drivers/char/drm/ffb_context.c b/drivers/char/drm/ffb_context.c
index 6fae05c8b..f51812078 100644
--- a/drivers/char/drm/ffb_context.c
+++ b/drivers/char/drm/ffb_context.c
@@ -354,7 +354,7 @@ static void FFBWait(ffb_fbcPtr ffb)
 	} while (--limit);
 }
 
-int DRM(context_switch)(drm_device_t *dev, int old, int new)
+int ffb_driver_context_switch(drm_device_t *dev, int old, int new)
 {
 	ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
 
@@ -380,7 +380,7 @@ int DRM(context_switch)(drm_device_t *dev, int old, int new)
         return 0;
 }
 
-int DRM(resctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+int ffb_driver_resctx(struct inode *inode, struct file *filp, unsigned int cmd,
 		unsigned long arg)
 {
 	drm_ctx_res_t	res;
@@ -407,7 +407,7 @@ int DRM(resctx)(struct inode *inode, struct file *filp, unsigned int cmd,
 }
 
 
-int DRM(addctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+int ffb_driver_addctx(struct inode *inode, struct file *filp, unsigned int cmd,
 		unsigned long arg)
 {
 	drm_file_t	*priv	= filp->private_data;
@@ -428,7 +428,7 @@ int DRM(addctx)(struct inode *inode, struct file *filp, unsigned int cmd,
 	return 0;
 }
 
-int DRM(modctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+int ffb_driver_modctx(struct inode *inode, struct file *filp, unsigned int cmd,
 		unsigned long arg)
 {
 	drm_file_t	*priv	= filp->private_data;
@@ -457,7 +457,7 @@ int DRM(modctx)(struct inode *inode, struct file *filp, unsigned int cmd,
 	return 0;
 }
 
-int DRM(getctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+int ffb_driver_getctx(struct inode *inode, struct file *filp, unsigned int cmd,
 		unsigned long arg)
 {
 	drm_file_t	*priv	= filp->private_data;
@@ -489,7 +489,7 @@ int DRM(getctx)(struct inode *inode, struct file *filp, unsigned int cmd,
 	return 0;
 }
 
-int DRM(switchctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+int ffb_driver_switchctx(struct inode *inode, struct file *filp, unsigned int cmd,
 		   unsigned long arg)
 {
 	drm_file_t	*priv	= filp->private_data;
@@ -499,10 +499,10 @@ int DRM(switchctx)(struct inode *inode, struct file *filp, unsigned int cmd,
 	if (copy_from_user(&ctx, (drm_ctx_t  __user *)arg, sizeof(ctx)))
 		return -EFAULT;
 	DRM_DEBUG("%d\n", ctx.handle);
-	return DRM(context_switch)(dev, dev->last_context, ctx.handle);
+	return ffb_driver_context_switch(dev, dev->last_context, ctx.handle);
 }
 
-int DRM(newctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+int ffb_driver_newctx(struct inode *inode, struct file *filp, unsigned int cmd,
 		unsigned long arg)
 {
 	drm_ctx_t	ctx;
@@ -514,7 +514,7 @@ int DRM(newctx)(struct inode *inode, struct file *filp, unsigned int cmd,
 	return 0;
 }
 
-int DRM(rmctx)(struct inode *inode, struct file *filp, unsigned int cmd,
+int ffb_driver_rmctx(struct inode *inode, struct file *filp, unsigned int cmd,
 	       unsigned long arg)
 {
 	drm_ctx_t	ctx;
@@ -537,3 +537,15 @@ int DRM(rmctx)(struct inode *inode, struct file *filp, unsigned int cmd,
 	}
 	return 0;
 }
+
+void ffb_set_context_ioctls(void)
+{
+	DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)].func = ffb_driver_addctx;
+	DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)].func = ffb_driver_rmctx;
+	DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)].func = ffb_driver_modctx;
+	DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)].func = ffb_driver_getctx;
+	DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)].func = ffb_driver_switchctx;
+	DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)].func = ffb_driver_newctx;
+	DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)].func = ffb_driver_resctx;
+
+}
diff --git a/drivers/char/drm/ffb_drv.c b/drivers/char/drm/ffb_drv.c
index 765355999..2e1522e7c 100644
--- a/drivers/char/drm/ffb_drv.c
+++ b/drivers/char/drm/ffb_drv.c
@@ -26,58 +26,6 @@
 #define DRIVER_MINOR		0
 #define DRIVER_PATCHLEVEL	1
 
-#define DRIVER_FOPS						\
-static struct file_operations	DRM(fops) = {			\
-	.owner   		= THIS_MODULE,			\
-	.open	 		= DRM(open),			\
-	.flush	 		= DRM(flush),			\
-	.release 		= DRM(release),			\
-	.ioctl	 		= DRM(ioctl),			\
-	.mmap	 		= DRM(mmap),			\
-	.read	 		= DRM(read),			\
-	.fasync	 		= DRM(fasync),			\
-	.poll	 		= DRM(poll),			\
-	.get_unmapped_area	= ffb_get_unmapped_area,		\
-}
-
-#define DRIVER_COUNT_CARDS()	ffb_count_card_instances()
-/* Allocate private structure and fill it */
-#define DRIVER_PRESETUP()	do {		\
-	int _ret;				\
-	_ret = ffb_presetup(dev);		\
-	if (_ret != 0) return _ret;		\
-} while(0)
-
-/* Free private structure */
-#define DRIVER_PRETAKEDOWN()	do {				\
-	if (dev->dev_private) kfree(dev->dev_private);		\
-} while(0)
-
-#define DRIVER_POSTCLEANUP()	do {				\
-	if (ffb_position != NULL) kfree(ffb_position);		\
-} while(0)
-
-/* We have to free up the rogue hw context state holding error or 
- * else we will leak it.
- */
-#define DRIVER_RELEASE()	do {					\
-	ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;	\
-	int context = _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock);	\
-	int idx;							\
-									\
-	idx = context - 1;						\
-	if (fpriv &&							\
-	    context != DRM_KERNEL_CONTEXT &&				\
-	    fpriv->hw_state[idx] != NULL) {				\
-		kfree(fpriv->hw_state[idx]);				\
-		fpriv->hw_state[idx] = NULL;				\
-	}								\
-} while(0)
-
-/* For mmap customization */
-#define DRIVER_GET_MAP_OFS()	(map->offset & 0xffffffff)
-#define DRIVER_GET_REG_OFS()	ffb_get_reg_offset(dev)
-
 typedef struct _ffb_position_t {
 	int node;
 	int root;
@@ -192,63 +140,6 @@ static int ffb_init_one(drm_device_t *dev, int prom_node, int parent_node,
 	return 0;
 }
 
-static int __init ffb_count_siblings(int root)
-{
-	int node, child, count = 0;
-
-	child = prom_getchild(root);
-	for (node = prom_searchsiblings(child, "SUNW,ffb"); node;
-	     node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb"))
-		count++;
-
-	return count;
-}
-
-static int __init ffb_scan_siblings(int root, int instance)
-{
-	int node, child;
-
-	child = prom_getchild(root);
-	for (node = prom_searchsiblings(child, "SUNW,ffb"); node;
-	     node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb")) {
-		ffb_position[instance].node = node;
-		ffb_position[instance].root = root;
-		instance++;
-	}
-
-	return instance;
-}
-
-static int ffb_presetup(drm_device_t *);
-
-static int __init ffb_count_card_instances(void)
-{
-	int root, total, instance;
-
-	total = ffb_count_siblings(prom_root_node);
-	root = prom_getchild(prom_root_node);
-	for (root = prom_searchsiblings(root, "upa"); root;
-	     root = prom_searchsiblings(prom_getsibling(root), "upa"))
-		total += ffb_count_siblings(root);
-
-	ffb_position = kmalloc(sizeof(ffb_position_t) * total, GFP_KERNEL);
-
-	/* Actual failure will be caught during ffb_presetup b/c we can't catch
-	 * it easily here.
-	 */
-	if (!ffb_position)
-		return -ENOMEM;
-
-	instance = ffb_scan_siblings(prom_root_node, 0);
-
-	root = prom_getchild(prom_root_node);
-	for (root = prom_searchsiblings(root, "upa"); root;
-	     root = prom_searchsiblings(prom_getsibling(root), "upa"))
-		instance = ffb_scan_siblings(root, instance);
-
-	return total;
-}
-
 static drm_map_t *ffb_find_map(struct file *filp, unsigned long off)
 {
 	drm_file_t	*priv	= filp->private_data;
@@ -275,11 +166,11 @@ static drm_map_t *ffb_find_map(struct file *filp, unsigned long off)
 	return NULL;
 }
 
-static unsigned long ffb_get_unmapped_area(struct file *filp,
-					   unsigned long hint,
-					   unsigned long len,
-					   unsigned long pgoff,
-					   unsigned long flags)
+unsigned long ffb_get_unmapped_area(struct file *filp,
+				    unsigned long hint,
+				    unsigned long len,
+				    unsigned long pgoff,
+				    unsigned long flags)
 {
 	drm_map_t *map = ffb_find_map(filp, pgoff << PAGE_SHIFT);
 	unsigned long addr = -ENOMEM;
@@ -319,21 +210,7 @@ static unsigned long ffb_get_unmapped_area(struct file *filp,
 	return addr;
 }
 
-static unsigned long ffb_get_reg_offset(drm_device_t *dev)
-{
-	ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *)dev->dev_private;
-
-	if (ffb_priv)
-		return ffb_priv->card_phys_base;
-
-	return 0;
-}
-
-#include "drm_auth.h"
-#include "drm_bufs.h"
-#include "drm_dma.h"
-#include "drm_drawable.h"
-#include "drm_drv.h"
+#include "drm_core.h"
 
 /* This functions must be here since it references DRM(numdevs)
  * which drm_drv.h declares.
@@ -372,11 +249,74 @@ static int ffb_presetup(drm_device_t *dev)
 	return ret;
 }
 
-#include "drm_fops.h"
-#include "drm_init.h"
-#include "drm_ioctl.h"
-#include "drm_lock.h"
-#include "drm_memory.h"
-#include "drm_proc.h"
-#include "drm_vm.h"
-#include "drm_stub.h"
+static void ffb_driver_release(drm_device_t *dev, struct file *filp)
+{
+	ffb_dev_priv_t *fpriv = (ffb_dev_priv_t *) dev->dev_private;
+	int context = _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock);
+	int idx;
+
+	idx = context - 1;
+	if (fpriv &&
+	    context != DRM_KERNEL_CONTEXT &&
+	    fpriv->hw_state[idx] != NULL) {
+		kfree(fpriv->hw_state[idx]);
+		fpriv->hw_state[idx] = NULL;
+	}	
+}
+
+static void ffb_driver_pretakedown(drm_device_t *dev)
+{
+	if (dev->dev_private) kfree(dev->dev_private);
+}
+
+static int ffb_driver_postcleanup(drm_device_t *dev)
+{
+	if (ffb_position != NULL) kfree(ffb_position);
+	return 0;
+}
+
+static void ffb_driver_kernel_context_switch_unlock(struct drm_device *dev, drm_lock_t *lock)
+{
+	dev->lock.filp = 0;
+	{
+		__volatile__ unsigned int *plock = &dev->lock.hw_lock->lock;
+		unsigned int old, new, prev, ctx;
+		
+		ctx = lock->context;
+		do {
+			old  = *plock;
+			new  = ctx;
+			prev = cmpxchg(plock, old, new);
+		} while (prev != old);
+	}
+	wake_up_interruptible(&dev->lock.lock_queue);
+}
+
+static unsigned long ffb_driver_get_map_ofs(drm_map_t *map)
+{
+	return (map->offset & 0xffffffff);
+}
+
+static unsigned long ffb_driver_get_reg_ofs(drm_device_t *dev)
+{
+       ffb_dev_priv_t *ffb_priv = (ffb_dev_priv_t *)dev->dev_private;
+       
+       if (ffb_priv)
+               return ffb_priv->card_phys_base;
+       
+       return 0;
+}
+
+void ffb_driver_register_fns(drm_device_t *dev)
+{
+	ffb_set_context_ioctls();
+	DRM(fops).get_unmapped_area = ffb_get_unmapped_area;
+	dev->fn_tbl.release = ffb_driver_release;
+	dev->fn_tbl.presetup = ffb_presetup;
+	dev->fn_tbl.pretakedown = ffb_driver_pretakedown;
+	dev->fn_tbl.postcleanup = ffb_driver_postcleanup;
+	dev->fn_tbl.kernel_context_switch = ffb_context_switch;
+	dev->fn_tbl.kernel_context_switch_unlock = ffb_driver_kernel_context_switch_unlock;
+	dev->fn_tbl.get_map_ofs = ffb_driver_get_map_ofs;
+	dev->fn_tbl.get_reg_ofs = ffb_driver_get_reg_ofs;
+}
diff --git a/drivers/char/drm/ffb_drv.h b/drivers/char/drm/ffb_drv.h
index 094bbce09..3b3546715 100644
--- a/drivers/char/drm/ffb_drv.h
+++ b/drivers/char/drm/ffb_drv.h
@@ -274,3 +274,13 @@ typedef struct ffb_dev_priv {
 	/* Context table. */
 	struct ffb_hw_context	*hw_state[FFB_MAX_CTXS];
 } ffb_dev_priv_t;
+
+extern struct file_operations DRM(fops);
+extern unsigned long ffb_get_unmapped_area(struct file *filp,
+					   unsigned long hint,
+					   unsigned long len,
+					   unsigned long pgoff,
+					   unsigned long flags);
+extern void ffb_set_context_ioctls(void);
+extern drm_ioctl_desc_t DRM(ioctls)[];
+
diff --git a/drivers/char/drm/gamma.h b/drivers/char/drm/gamma.h
index dcd649048..cabd4b311 100644
--- a/drivers/char/drm/gamma.h
+++ b/drivers/char/drm/gamma.h
@@ -36,8 +36,6 @@
 
 /* General customization:
  */
-#define __HAVE_MTRR			1
-
 #define DRIVER_AUTHOR		"VA Linux Systems Inc."
 
 #define DRIVER_NAME		"gamma"
@@ -71,44 +69,9 @@
 
 /* DMA customization:
  */
-#define __HAVE_DMA			1
-#define __HAVE_AGP			1
-#define __MUST_HAVE_AGP			0
-#define __HAVE_OLD_DMA			1
-#define __HAVE_PCI_DMA			1
-
-#define __HAVE_DRIVER_FOPS_READ		1
-#define __HAVE_DRIVER_FOPS_POLL		1
-
 #define __HAVE_MULTIPLE_DMA_QUEUES	1
 #define __HAVE_DMA_WAITQUEUE		1
 
-#define __HAVE_DMA_WAITLIST		1
-#define __HAVE_DMA_FREELIST		1
-
-#define __HAVE_DMA_FLUSH		1
-#define __HAVE_DMA_SCHEDULE		1
-
-#define __HAVE_DMA_READY		1
-#define DRIVER_DMA_READY() do {						\
-	gamma_dma_ready(dev);						\
-} while (0)
-
-#define __HAVE_DMA_QUIESCENT		1
-#define DRIVER_DMA_QUIESCENT() do {					\
-	drm_gamma_private_t *dev_priv =					\
-		(drm_gamma_private_t *)dev->dev_private;		\
-	if (dev_priv->num_rast == 2)					\
-		gamma_dma_quiescent_dual(dev);				\
-	else gamma_dma_quiescent_single(dev);				\
-	return 0;							\
-} while (0)
-
-#define __HAVE_IRQ			1
-#define __HAVE_IRQ_BH			1
-
-#define DRIVER_AGP_BUFFERS_MAP( dev )					\
-	((drm_gamma_private_t *)((dev)->dev_private))->buffers
-
+/* removed from DRM HAVE_DMA_FREELIST & HAVE_DMA_SCHEDULE */
 
 #endif /* __GAMMA_H__ */
diff --git a/drivers/char/drm/gamma_context.h b/drivers/char/drm/gamma_context.h
index d3c8c29c2..d11b507f8 100644
--- a/drivers/char/drm/gamma_context.h
+++ b/drivers/char/drm/gamma_context.h
@@ -42,7 +42,7 @@
    the circular buffer), is based on Alessandro Rubini's LINUX DEVICE
    DRIVERS (Cambridge: O'Reilly, 1998), pages 111-113. */
 
-ssize_t DRM(read)(struct file *filp, char __user *buf, size_t count, loff_t *off)
+ssize_t gamma_fops_read(struct file *filp, char __user *buf, size_t count, loff_t *off)
 {
 	drm_file_t    *priv   = filp->private_data;
 	drm_device_t  *dev    = priv->dev;
@@ -128,7 +128,7 @@ int DRM(write_string)(drm_device_t *dev, const char *s)
 	return 0;
 }
 
-unsigned int DRM(poll)(struct file *filp, struct poll_table_struct *wait)
+unsigned int gamma_fops_poll(struct file *filp, struct poll_table_struct *wait)
 {
 	drm_file_t   *priv = filp->private_data;
 	drm_device_t *dev  = priv->dev;
diff --git a/drivers/char/drm/gamma_dma.c b/drivers/char/drm/gamma_dma.c
index 7802f5156..7e01ca182 100644
--- a/drivers/char/drm/gamma_dma.c
+++ b/drivers/char/drm/gamma_dma.c
@@ -116,7 +116,7 @@ static inline int gamma_dma_is_ready(drm_device_t *dev)
 	return (!GAMMA_READ(GAMMA_DMACOUNT));
 }
 
-irqreturn_t gamma_irq_handler( DRM_IRQ_ARGS )
+irqreturn_t gamma_driver_irq_handler( DRM_IRQ_ARGS )
 {
 	drm_device_t	 *dev = (drm_device_t *)arg;
 	drm_device_dma_t *dma = dev->dma;
@@ -639,12 +639,12 @@ static int gamma_do_init_dma( drm_device_t *dev, drm_gamma_init_t *init )
  			break;
  		}
  	}
-
-	DRM_FIND_MAP( dev_priv->mmio0, init->mmio0 );
-	DRM_FIND_MAP( dev_priv->mmio1, init->mmio1 );
-	DRM_FIND_MAP( dev_priv->mmio2, init->mmio2 );
-	DRM_FIND_MAP( dev_priv->mmio3, init->mmio3 );
-
+	
+	dev_priv->mmio0 = drm_core_findmap(dev, init->mmio0);
+	dev_priv->mmio1 = drm_core_findmap(dev, init->mmio1);
+	dev_priv->mmio2 = drm_core_findmap(dev, init->mmio2);
+	dev_priv->mmio3 = drm_core_findmap(dev, init->mmio3);
+	
 	dev_priv->sarea_priv = (drm_gamma_sarea_t *)
 		((u8 *)dev_priv->sarea->handle +
 		 init->sarea_priv_offset);
@@ -661,9 +661,8 @@ static int gamma_do_init_dma( drm_device_t *dev, drm_gamma_init_t *init )
 
 		buf = dma->buflist[GLINT_DRI_BUF_COUNT];
 	} else {
-		DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
-
-		DRM_IOREMAP( dev_priv->buffers, dev );
+		dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+		drm_core_ioremap( dev->agp_buffer_map, dev);
 
 		buf = dma->buflist[GLINT_DRI_BUF_COUNT];
 		pgt = buf->address;
@@ -690,19 +689,18 @@ int gamma_do_cleanup_dma( drm_device_t *dev )
 {
 	DRM_DEBUG( "%s\n", __FUNCTION__ );
 
-#if __HAVE_IRQ
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
 	 * is freed, it's too late.
 	 */
-	if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
-#endif
+	if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
+		if ( dev->irq_enabled ) 
+			DRM(irq_uninstall)(dev);
 
 	if ( dev->dev_private ) {
-		drm_gamma_private_t *dev_priv = dev->dev_private;
 
-		if ( dev_priv->buffers != NULL )
-			DRM_IOREMAPFREE( dev_priv->buffers, dev );
+		if ( dev->agp_buffer_map != NULL )
+			drm_core_ioremapfree( dev->agp_buffer_map, dev );
 
 		DRM(free)( dev->dev_private, sizeof(drm_gamma_private_t),
 			   DRM_MEM_DRIVER );
@@ -868,7 +866,7 @@ int gamma_setsareactx(struct inode *inode, struct file *filp,
 	return 0;
 }
 
-void DRM(driver_irq_preinstall)( drm_device_t *dev ) {
+void gamma_driver_irq_preinstall( drm_device_t *dev ) {
 	drm_gamma_private_t *dev_priv =
 				(drm_gamma_private_t *)dev->dev_private;
 
@@ -879,7 +877,7 @@ void DRM(driver_irq_preinstall)( drm_device_t *dev ) {
 	GAMMA_WRITE( GAMMA_GDMACONTROL,		0x00000000 );
 }
 
-void DRM(driver_irq_postinstall)( drm_device_t *dev ) {
+void gamma_driver_irq_postinstall( drm_device_t *dev ) {
 	drm_gamma_private_t *dev_priv =
 				(drm_gamma_private_t *)dev->dev_private;
 
@@ -891,7 +889,7 @@ void DRM(driver_irq_postinstall)( drm_device_t *dev ) {
 	GAMMA_WRITE( GAMMA_GDELAYTIMER,		0x00039090 );
 }
 
-void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
+void gamma_driver_irq_uninstall( drm_device_t *dev ) {
 	drm_gamma_private_t *dev_priv =
 				(drm_gamma_private_t *)dev->dev_private;
 	if (!dev_priv)
@@ -904,3 +902,45 @@ void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
 	GAMMA_WRITE( GAMMA_COMMANDINTENABLE,	0x00000000 );
 	GAMMA_WRITE( GAMMA_GINTENABLE,		0x00000000 );
 }
+
+extern drm_ioctl_desc_t DRM(ioctls)[];
+
+static int gamma_driver_preinit(drm_device_t *dev)
+{
+	/* reset the finish ioctl */
+	DRM(ioctls)[DRM_IOCTL_NR(DRM_IOCTL_FINISH)].func = DRM(finish);
+	return 0;
+}
+
+static void gamma_driver_pretakedown(drm_device_t *dev)
+{
+	gamma_do_cleanup_dma(dev);
+}
+
+static void gamma_driver_dma_ready(drm_device_t *dev)
+{
+	gamma_dma_ready(dev);
+}
+
+static int gamma_driver_dma_quiescent(drm_device_t *dev)
+{
+	drm_gamma_private_t *dev_priv =	(
+		drm_gamma_private_t *)dev->dev_private;
+	if (dev_priv->num_rast == 2)
+		gamma_dma_quiescent_dual(dev);
+	else gamma_dma_quiescent_single(dev);
+	return 0;
+}
+
+void gamma_driver_register_fns(drm_device_t *dev)
+{
+	dev->driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ;
+	DRM(fops).read = gamma_fops_read;
+	DRM(fops).poll = gamma_fops_poll;
+	dev->fn_tbl.preinit = gamma_driver_preinit;
+	dev->fn_tbl.pretakedown = gamma_driver_pretakedown;
+	dev->fn_tbl.dma_ready = gamma_driver_dma_ready;
+	dev->fn_tbl.dma_quiescent = gamma_driver_dma_quiescent;
+	dev->fn_tbl.dma_flush_block_and_flush = gamma_flush_block_and_flush;
+	dev->fn_tbl.dma_flush_unblock = gamma_flush_unblock;
+}
diff --git a/drivers/char/drm/gamma_drv.c b/drivers/char/drm/gamma_drv.c
index b1fb05055..e7e64b627 100644
--- a/drivers/char/drm/gamma_drv.c
+++ b/drivers/char/drm/gamma_drv.c
@@ -56,3 +56,4 @@
 #include "drm_proc.h"
 #include "drm_vm.h"
 #include "drm_stub.h"
+#include "drm_scatter.h"
diff --git a/drivers/char/drm/gamma_drv.h b/drivers/char/drm/gamma_drv.h
index fc78a11a3..146fcc625 100644
--- a/drivers/char/drm/gamma_drv.h
+++ b/drivers/char/drm/gamma_drv.h
@@ -35,7 +35,6 @@
 typedef struct drm_gamma_private {
 	drm_gamma_sarea_t *sarea_priv;
 	drm_map_t *sarea;
-	drm_map_t *buffers;
 	drm_map_t *mmio0;
 	drm_map_t *mmio1;
 	drm_map_t *mmio2;
@@ -91,6 +90,10 @@ extern int	     DRM(freelist_put)(drm_device_t *dev, drm_freelist_t *bl,
 				       drm_buf_t *buf);
 extern drm_buf_t     *DRM(freelist_get)(drm_freelist_t *bl, int block);
 
+/* externs for gamma changes to the ops */
+extern struct file_operations DRM(fops);
+extern unsigned int gamma_fops_poll(struct file *filp, struct poll_table_struct *wait);
+extern ssize_t gamma_fops_read(struct file *filp, char __user *buf, size_t count, loff_t *off);
 
 
 #define GLINT_DRI_BUF_COUNT 256
diff --git a/drivers/char/drm/i810.h b/drivers/char/drm/i810.h
index aee2efff1..2ea83be82 100644
--- a/drivers/char/drm/i810.h
+++ b/drivers/char/drm/i810.h
@@ -36,10 +36,6 @@
 
 /* General customization:
  */
-#define __HAVE_AGP		1
-#define __MUST_HAVE_AGP		1
-#define __HAVE_MTRR		1
-#define __HAVE_CTX_BITMAP	1
 
 #define DRIVER_AUTHOR		"VA Linux Systems Inc."
 
@@ -78,47 +74,4 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_I810_RSTATUS)] = { i810_rstatus,    1, 0 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_I810_FLIP)] =    { i810_flip_bufs,  1, 0 }
 
-#define __HAVE_COUNTERS         4
-#define __HAVE_COUNTER6         _DRM_STAT_IRQ
-#define __HAVE_COUNTER7         _DRM_STAT_PRIMARY
-#define __HAVE_COUNTER8         _DRM_STAT_SECONDARY
-#define __HAVE_COUNTER9         _DRM_STAT_DMA
-
-/* Driver customization:
- */
-#define __HAVE_RELEASE		1
-#define DRIVER_RELEASE() do {						\
-	i810_reclaim_buffers( filp );					\
-} while (0)
-
-#define DRIVER_PRETAKEDOWN() do {					\
-	i810_dma_cleanup( dev );					\
-} while (0)
-
-/* DMA customization:
- */
-#define __HAVE_DMA		1
-#define __HAVE_DMA_QUEUE	1
-#define __HAVE_DMA_WAITLIST	0
-#define __HAVE_DMA_RECLAIM	1
-
-#define __HAVE_DMA_QUIESCENT	1
-#define DRIVER_DMA_QUIESCENT() do {					\
-	i810_dma_quiescent( dev );					\
-} while (0)
-
-/* Don't need an irq any more.  The template code will make sure that
- * a noop stub is generated for compatibility.
- */
-/* XXX: Add vblank support? */
-#define __HAVE_IRQ		0
-
-/* Buffer customization:
- */
-
-#define DRIVER_BUF_PRIV_T	drm_i810_buf_priv_t
-
-#define DRIVER_AGP_BUFFERS_MAP( dev )					\
-	((drm_i810_private_t *)((dev)->dev_private))->buffer_map
-
 #endif
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index 42220efe7..d9348ac71 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -232,13 +232,12 @@ int i810_dma_cleanup(drm_device_t *dev)
 {
 	drm_device_dma_t *dma = dev->dma;
 
-#if __HAVE_IRQ
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
 	 * is freed, it's too late.
 	 */
-	if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
-#endif
+	if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ) && dev->irq_enabled)
+		DRM(irq_uninstall)(dev);
 
 	if (dev->dev_private) {
 		int i;
@@ -364,15 +363,15 @@ static int i810_dma_initialize(drm_device_t *dev,
 	   	DRM_ERROR("can not find sarea!\n");
 	   	return -EINVAL;
 	}
-	DRM_FIND_MAP( dev_priv->mmio_map, init->mmio_offset );
+	dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
 	if (!dev_priv->mmio_map) {
 		dev->dev_private = (void *)dev_priv;
 	   	i810_dma_cleanup(dev);
 	   	DRM_ERROR("can not find mmio map!\n");
 	   	return -EINVAL;
 	}
-	DRM_FIND_MAP( dev_priv->buffer_map, init->buffers_offset );
-	if (!dev_priv->buffer_map) {
+	dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+	if (!dev->agp_buffer_map) {
 		dev->dev_private = (void *)dev_priv;
 	   	i810_dma_cleanup(dev);
 	   	DRM_ERROR("can not find dma buffer map!\n");
@@ -844,13 +843,10 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev,
 	if (buf_priv->currently_mapped == I810_BUF_MAPPED) {
 		unsigned int prim = (sarea_priv->vertex_prim & PR_MASK);
 
-		put_user((GFX_OP_PRIMITIVE | prim |
-					     ((used/4)-2)),
-		(u32 __user *)buf_priv->virtual);
+		*(u32 *)buf_priv->kernel_virtual = ((GFX_OP_PRIMITIVE | prim | ((used/4)-2)));
 
 		if (used & 4) {
-			put_user(0,
-			(u32 __user *)((u32)buf_priv->virtual + used));
+			*(u32 *)((u32)buf_priv->kernel_virtual + used) = 0;
 			used += 4;
 		}
 
@@ -1391,3 +1387,36 @@ int i810_flip_bufs(struct inode *inode, struct file *filp,
 	i810_dma_dispatch_flip( dev );
    	return 0;
 }
+
+static void i810_driver_pretakedown(drm_device_t *dev)
+{
+	i810_dma_cleanup( dev );
+}
+
+static void i810_driver_release(drm_device_t *dev, struct file *filp)
+{
+	i810_reclaim_buffers(filp);
+}
+
+static int i810_driver_dma_quiescent(drm_device_t *dev)
+{
+	i810_dma_quiescent( dev );
+	return 0;
+}
+
+void i810_driver_register_fns(drm_device_t *dev)
+{
+	dev->driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE;
+	dev->dev_priv_size = sizeof(drm_i810_buf_priv_t);
+	dev->fn_tbl.pretakedown = i810_driver_pretakedown;
+	dev->fn_tbl.release = i810_driver_release;
+	dev->fn_tbl.dma_quiescent = i810_driver_dma_quiescent;
+	dev->fn_tbl.reclaim_buffers = i810_reclaim_buffers;
+
+	dev->counters += 4;
+	dev->types[6] = _DRM_STAT_IRQ;
+	dev->types[7] = _DRM_STAT_PRIMARY;
+	dev->types[8] = _DRM_STAT_SECONDARY;
+	dev->types[9] = _DRM_STAT_DMA;
+}
+
diff --git a/drivers/char/drm/i810_drv.c b/drivers/char/drm/i810_drv.c
index 0bc793864..00ca55166 100644
--- a/drivers/char/drm/i810_drv.c
+++ b/drivers/char/drm/i810_drv.c
@@ -37,19 +37,4 @@
 #include "i810_drm.h"
 #include "i810_drv.h"
 
-#include "drm_agpsupport.h"
-#include "drm_auth.h"
-#include "drm_bufs.h"
-#include "drm_context.h"
-#include "drm_dma.h"
-#include "drm_drawable.h"
-#include "drm_drv.h"
-
-#include "drm_fops.h"
-#include "drm_init.h"
-#include "drm_ioctl.h"
-#include "drm_lock.h"
-#include "drm_memory.h"
-#include "drm_proc.h"
-#include "drm_vm.h"
-#include "drm_stub.h"
+#include "drm_core.h"
diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h
index 736c20d76..67c5c88bf 100644
--- a/drivers/char/drm/i810_drv.h
+++ b/drivers/char/drm/i810_drv.h
@@ -53,7 +53,6 @@ typedef struct _drm_i810_ring_buffer{
 
 typedef struct drm_i810_private {
 	drm_map_t *sarea_map;
-	drm_map_t *buffer_map;
 	drm_map_t *mmio_map;
 
 	drm_i810_sarea_t *sarea_priv;
diff --git a/drivers/char/drm/i830.h b/drivers/char/drm/i830.h
index b4a361bf0..85a1ac204 100644
--- a/drivers/char/drm/i830.h
+++ b/drivers/char/drm/i830.h
@@ -36,10 +36,6 @@
 
 /* General customization:
  */
-#define __HAVE_AGP		1
-#define __MUST_HAVE_AGP		1
-#define __HAVE_MTRR		1
-#define __HAVE_CTX_BITMAP	1
 
 #define DRIVER_AUTHOR		"VA Linux Systems Inc."
 
@@ -77,36 +73,6 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_I830_GETPARAM)] = { i830_getparam,  1, 0 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_I830_SETPARAM)] = { i830_setparam,  1, 0 } 
 
-#define __HAVE_COUNTERS         4
-#define __HAVE_COUNTER6         _DRM_STAT_IRQ
-#define __HAVE_COUNTER7         _DRM_STAT_PRIMARY
-#define __HAVE_COUNTER8         _DRM_STAT_SECONDARY
-#define __HAVE_COUNTER9         _DRM_STAT_DMA
-
-/* Driver customization:
- */
-#define __HAVE_RELEASE		1
-#define DRIVER_RELEASE() do {						\
-	i830_reclaim_buffers( filp );					\
-} while (0)
-
-#define DRIVER_PRETAKEDOWN() do {					\
-	i830_dma_cleanup( dev );					\
-} while (0)
-
-/* DMA customization:
- */
-#define __HAVE_DMA		1
-#define __HAVE_DMA_QUEUE	1
-#define __HAVE_DMA_WAITLIST	0
-#define __HAVE_DMA_RECLAIM	1
-
-#define __HAVE_DMA_QUIESCENT	1
-#define DRIVER_DMA_QUIESCENT() do {					\
-	i830_dma_quiescent( dev );					\
-} while (0)
-
-
 /* Driver will work either way: IRQ's save cpu time when waiting for
  * the card, but are subject to subtle interactions between bios,
  * hardware and the driver.
@@ -114,20 +80,4 @@
 /* XXX: Add vblank support? */
 #define USE_IRQS 0
 
-#if USE_IRQS
-#define __HAVE_IRQ		1
-#define __HAVE_SHARED_IRQ	1
-#else
-#define __HAVE_IRQ          0
-#endif
-
-
-/* Buffer customization:
- */
-
-#define DRIVER_BUF_PRIV_T	drm_i830_buf_priv_t
-
-#define DRIVER_AGP_BUFFERS_MAP( dev )					\
-	((drm_i830_private_t *)((dev)->dev_private))->buffer_map
-
 #endif
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
index 856dc81f8..084e9da08 100644
--- a/drivers/char/drm/i830_dma.c
+++ b/drivers/char/drm/i830_dma.c
@@ -233,13 +233,11 @@ int i830_dma_cleanup(drm_device_t *dev)
 {
 	drm_device_dma_t *dma = dev->dma;
 
-#if __HAVE_IRQ
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
 	 * is freed, it's too late.
 	 */
 	if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
-#endif
 
 	if (dev->dev_private) {
 		int i;
@@ -371,15 +369,15 @@ static int i830_dma_initialize(drm_device_t *dev,
 		DRM_ERROR("can not find sarea!\n");
 		return -EINVAL;
 	}
-	DRM_FIND_MAP( dev_priv->mmio_map, init->mmio_offset );
+	dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
 	if(!dev_priv->mmio_map) {
 		dev->dev_private = (void *)dev_priv;
 		i830_dma_cleanup(dev);
 		DRM_ERROR("can not find mmio map!\n");
 		return -EINVAL;
 	}
-	DRM_FIND_MAP( dev_priv->buffer_map, init->buffers_offset );
-	if(!dev_priv->buffer_map) {
+	dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+	if(!dev->agp_buffer_map) {
 		dev->dev_private = (void *)dev_priv;
 		i830_dma_cleanup(dev);
 		DRM_ERROR("can not find dma buffer map!\n");
@@ -1166,19 +1164,19 @@ static void i830_dma_dispatch_vertex(drm_device_t *dev,
    	DRM_DEBUG(  "start + used - 4 : %ld\n", start + used - 4);
 
 	if (buf_priv->currently_mapped == I830_BUF_MAPPED) {
-		u32  __user *vp = buf_priv->virtual;
+		u32 *vp = buf_priv->kernel_virtual;
 
-		put_user( (GFX_OP_PRIMITIVE |
-			 sarea_priv->vertex_prim |
-			  ((used/4)-2)), &vp[0]);
+		vp[0] = (GFX_OP_PRIMITIVE |
+			sarea_priv->vertex_prim |
+			((used/4)-2));
 
 		if (dev_priv->use_mi_batchbuffer_start) {
-			put_user(MI_BATCH_BUFFER_END, &vp[used/4]);
+			vp[used/4] = MI_BATCH_BUFFER_END;
 			used += 4; 
 		}
 		
 		if (used & 4) {
-			put_user(0, &vp[used/4]);
+			vp[used/4] = 0;
 			used += 4;
 		}
 
@@ -1582,3 +1580,45 @@ int i830_setparam( struct inode *inode, struct file *filp, unsigned int cmd,
 
 	return 0;
 }
+
+
+static void i830_driver_pretakedown(drm_device_t *dev)
+{
+	i830_dma_cleanup( dev );
+}
+
+static void i830_driver_release(drm_device_t *dev, struct file *filp)
+{
+	i830_reclaim_buffers(filp);
+}
+
+static int i830_driver_dma_quiescent(drm_device_t *dev)
+{
+	i830_dma_quiescent( dev );
+	return 0;
+}
+
+void i830_driver_register_fns(drm_device_t *dev)
+{
+	dev->driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE;
+#if USE_IRQS
+	dev->driver_features |= DRIVER_HAVE_IRQ | DRIVER_SHARED_IRQ;
+#endif
+	dev->dev_priv_size = sizeof(drm_i830_buf_priv_t);
+	dev->fn_tbl.pretakedown = i830_driver_pretakedown;
+	dev->fn_tbl.release = i830_driver_release;
+	dev->fn_tbl.dma_quiescent = i830_driver_dma_quiescent;
+	dev->fn_tbl.reclaim_buffers = i830_reclaim_buffers;
+#if USE_IRQS
+	dev->fn_tbl.irq_preinstall = i830_driver_irq_preinstall;
+	dev->fn_tbl.irq_postinstall = i830_driver_irq_postinstall;
+	dev->fn_tbl.irq_uninstall = i830_driver_irq_uninstall;
+	dev->fn_tbl.irq_handler = i830_driver_irq_handler;
+#endif
+	dev->counters += 4;
+	dev->types[6] = _DRM_STAT_IRQ;
+	dev->types[7] = _DRM_STAT_PRIMARY;
+	dev->types[8] = _DRM_STAT_SECONDARY;
+	dev->types[9] = _DRM_STAT_DMA;
+}
+
diff --git a/drivers/char/drm/i830_drv.c b/drivers/char/drm/i830_drv.c
index 2f4e81572..eb45b2726 100644
--- a/drivers/char/drm/i830_drv.c
+++ b/drivers/char/drm/i830_drv.c
@@ -39,20 +39,4 @@
 #include "i830_drm.h"
 #include "i830_drv.h"
 
-#include "drm_agpsupport.h"
-#include "drm_auth.h"
-#include "drm_bufs.h"
-#include "drm_context.h"
-#include "drm_dma.h"
-#include "drm_drawable.h"
-#include "drm_drv.h"
-
-#include "drm_fops.h"
-#include "drm_init.h"
-#include "drm_ioctl.h"
-#include "drm_irq.h"
-#include "drm_lock.h"
-#include "drm_memory.h"
-#include "drm_proc.h"
-#include "drm_vm.h"
-#include "drm_stub.h"
+#include "drm_core.h"
diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h
index c6d805fc7..c3cab2d83 100644
--- a/drivers/char/drm/i830_drv.h
+++ b/drivers/char/drm/i830_drv.h
@@ -53,7 +53,6 @@ typedef struct _drm_i830_ring_buffer{
 
 typedef struct drm_i830_private {
 	drm_map_t *sarea_map;
-	drm_map_t *buffer_map;
 	drm_map_t *mmio_map;
 
 	drm_i830_sarea_t *sarea_priv;
@@ -137,6 +136,10 @@ extern int i830_irq_wait( struct inode *inode, struct file *filp,
 extern int i830_wait_irq(drm_device_t *dev, int irq_nr);
 extern int i830_emit_irq(drm_device_t *dev);
 
+extern irqreturn_t i830_driver_irq_handler( DRM_IRQ_ARGS );
+extern void i830_driver_irq_preinstall( drm_device_t *dev );
+extern void i830_driver_irq_postinstall( drm_device_t *dev );
+extern void i830_driver_irq_uninstall( drm_device_t *dev );
 
 #define I830_BASE(reg)		((unsigned long) \
 				dev_priv->mmio_map->handle)
diff --git a/drivers/char/drm/i830_irq.c b/drivers/char/drm/i830_irq.c
index 362d66ef1..6a0e25c26 100644
--- a/drivers/char/drm/i830_irq.c
+++ b/drivers/char/drm/i830_irq.c
@@ -35,7 +35,7 @@
 #include <linux/delay.h>
 
 
-irqreturn_t DRM(irq_handler)( DRM_IRQ_ARGS )
+irqreturn_t i830_driver_irq_handler( DRM_IRQ_ARGS )
 {
 	drm_device_t	 *dev = (drm_device_t *)arg;
       	drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
@@ -92,7 +92,7 @@ int i830_wait_irq(drm_device_t *dev, int irq_nr)
 	add_wait_queue(&dev_priv->irq_queue, &entry);
 
 	for (;;) {
-		current->state = TASK_INTERRUPTIBLE;
+		__set_current_state(TASK_INTERRUPTIBLE);
 	   	if (atomic_read(&dev_priv->irq_received) >= irq_nr) 
 		   break;
 		if((signed)(end - jiffies) <= 0) {
@@ -112,7 +112,7 @@ int i830_wait_irq(drm_device_t *dev, int irq_nr)
 		}
 	}
 
-	current->state = TASK_RUNNING;
+	__set_current_state(TASK_RUNNING);
 	remove_wait_queue(&dev_priv->irq_queue, &entry);
 	return ret;
 }
@@ -178,7 +178,7 @@ int i830_irq_wait( struct inode *inode, struct file *filp, unsigned int cmd,
 
 /* drm_dma.h hooks
 */
-void DRM(driver_irq_preinstall)( drm_device_t *dev ) {
+void i830_driver_irq_preinstall( drm_device_t *dev ) {
 	drm_i830_private_t *dev_priv =
 		(drm_i830_private_t *)dev->dev_private;
 
@@ -190,14 +190,14 @@ void DRM(driver_irq_preinstall)( drm_device_t *dev ) {
 	init_waitqueue_head(&dev_priv->irq_queue);
 }
 
-void DRM(driver_irq_postinstall)( drm_device_t *dev ) {
+void i830_driver_irq_postinstall( drm_device_t *dev ) {
 	drm_i830_private_t *dev_priv =
 		(drm_i830_private_t *)dev->dev_private;
 
 	I830_WRITE16( I830REG_INT_ENABLE_R, 0x2 );
 }
 
-void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
+void i830_driver_irq_uninstall( drm_device_t *dev ) {
 	drm_i830_private_t *dev_priv =
 		(drm_i830_private_t *)dev->dev_private;
 	if (!dev_priv)
diff --git a/drivers/char/drm/mga.h b/drivers/char/drm/mga.h
index 702857a32..5356519e5 100644
--- a/drivers/char/drm/mga.h
+++ b/drivers/char/drm/mga.h
@@ -36,10 +36,6 @@
 
 /* General customization:
  */
-#define __HAVE_AGP		1
-#define __MUST_HAVE_AGP		1
-#define __HAVE_MTRR		1
-#define __HAVE_CTX_BITMAP	1
 
 #define DRIVER_AUTHOR		"Gareth Hughes, VA Linux Systems Inc."
 
@@ -64,35 +60,4 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_MGA_BLIT)]    = { mga_dma_blit,    1, 0 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_MGA_GETPARAM)]= { mga_getparam,    1, 0 },
 
-#define __HAVE_COUNTERS         3
-#define __HAVE_COUNTER6         _DRM_STAT_IRQ
-#define __HAVE_COUNTER7         _DRM_STAT_PRIMARY
-#define __HAVE_COUNTER8         _DRM_STAT_SECONDARY
-
-/* Driver customization:
- */
-#define DRIVER_PRETAKEDOWN() do {					\
-	mga_do_cleanup_dma( dev );					\
-} while (0)
-
-/* DMA customization:
- */
-#define __HAVE_DMA		1
-#define __HAVE_IRQ		1
-#define __HAVE_VBL_IRQ		1
-#define __HAVE_SHARED_IRQ       1
-
-#define __HAVE_DMA_QUIESCENT	1
-#define DRIVER_DMA_QUIESCENT() do {					\
-	drm_mga_private_t *dev_priv = dev->dev_private;			\
-	return mga_do_wait_for_idle( dev_priv );			\
-} while (0)
-
-/* Buffer customization:
- */
-#define DRIVER_BUF_PRIV_T	drm_mga_buf_priv_t
-
-#define DRIVER_AGP_BUFFERS_MAP( dev )					\
-	((drm_mga_private_t *)((dev)->dev_private))->buffers
-
 #endif
diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c
index 76fbf714b..54b64c782 100644
--- a/drivers/char/drm/mga_dma.c
+++ b/drivers/char/drm/mga_dma.c
@@ -500,7 +500,7 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
 		return DRM_ERR(EINVAL);
 	}
 
-	DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
+	dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
 	if(!dev_priv->mmio) {
 		DRM_ERROR( "failed to find mmio region!\n" );
 		/* Assign dev_private so we can do cleanup. */
@@ -508,7 +508,7 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
 		mga_do_cleanup_dma( dev );
 		return DRM_ERR(EINVAL);
 	}
-	DRM_FIND_MAP( dev_priv->status, init->status_offset );
+	dev_priv->status = drm_core_findmap(dev, init->status_offset);
 	if(!dev_priv->status) {
 		DRM_ERROR( "failed to find status page!\n" );
 		/* Assign dev_private so we can do cleanup. */
@@ -516,8 +516,7 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
 		mga_do_cleanup_dma( dev );
 		return DRM_ERR(EINVAL);
 	}
-
-	DRM_FIND_MAP( dev_priv->warp, init->warp_offset );
+	dev_priv->warp = drm_core_findmap(dev, init->warp_offset);
 	if(!dev_priv->warp) {
 		DRM_ERROR( "failed to find warp microcode region!\n" );
 		/* Assign dev_private so we can do cleanup. */
@@ -525,7 +524,7 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
 		mga_do_cleanup_dma( dev );
 		return DRM_ERR(EINVAL);
 	}
-	DRM_FIND_MAP( dev_priv->primary, init->primary_offset );
+	dev_priv->primary = drm_core_findmap(dev, init->primary_offset);
 	if(!dev_priv->primary) {
 		DRM_ERROR( "failed to find primary dma region!\n" );
 		/* Assign dev_private so we can do cleanup. */
@@ -533,8 +532,8 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
 		mga_do_cleanup_dma( dev );
 		return DRM_ERR(EINVAL);
 	}
-	DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
-	if(!dev_priv->buffers) {
+	dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+	if(!dev->agp_buffer_map) {
 		DRM_ERROR( "failed to find dma buffer region!\n" );
 		/* Assign dev_private so we can do cleanup. */
 		dev->dev_private = (void *)dev_priv;
@@ -546,13 +545,13 @@ static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
 		(drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle +
 				    init->sarea_priv_offset);
 
-	DRM_IOREMAP( dev_priv->warp, dev );
-	DRM_IOREMAP( dev_priv->primary, dev );
-	DRM_IOREMAP( dev_priv->buffers, dev );
+	drm_core_ioremap( dev_priv->warp, dev );
+	drm_core_ioremap( dev_priv->primary, dev );
+	drm_core_ioremap( dev->agp_buffer_map, dev );
 
 	if(!dev_priv->warp->handle ||
 	   !dev_priv->primary->handle ||
-	   !dev_priv->buffers->handle ) {
+	   !dev->agp_buffer_map->handle ) {
 		DRM_ERROR( "failed to ioremap agp regions!\n" );
 		/* Assign dev_private so we can do cleanup. */
 		dev->dev_private = (void *)dev_priv;
@@ -631,23 +630,21 @@ int mga_do_cleanup_dma( drm_device_t *dev )
 {
 	DRM_DEBUG( "\n" );
 
-#if __HAVE_IRQ
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
 	 * is freed, it's too late.
 	 */
 	if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
-#endif
 
 	if ( dev->dev_private ) {
 		drm_mga_private_t *dev_priv = dev->dev_private;
 
 		if ( dev_priv->warp != NULL )
-			DRM_IOREMAPFREE( dev_priv->warp, dev );
+			drm_core_ioremapfree( dev_priv->warp, dev );
 		if ( dev_priv->primary != NULL )
-			DRM_IOREMAPFREE( dev_priv->primary, dev );
-		if ( dev_priv->buffers != NULL )
-			DRM_IOREMAPFREE( dev_priv->buffers, dev );
+			drm_core_ioremapfree( dev_priv->primary, dev );
+		if ( dev->agp_buffer_map != NULL )
+			drm_core_ioremapfree( dev->agp_buffer_map, dev );
 
 		if ( dev_priv->head != NULL ) {
 			mga_freelist_cleanup( dev );
@@ -800,3 +797,31 @@ int mga_dma_buffers( DRM_IOCTL_ARGS )
 
 	return ret;
 }
+
+static void mga_driver_pretakedown(drm_device_t *dev)
+{
+	mga_do_cleanup_dma( dev );
+}
+
+static int mga_driver_dma_quiescent(drm_device_t *dev)
+{
+	drm_mga_private_t *dev_priv = dev->dev_private;
+	return mga_do_wait_for_idle( dev_priv );
+}
+
+void mga_driver_register_fns(drm_device_t *dev)
+{
+	dev->driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL;
+	dev->fn_tbl.pretakedown = mga_driver_pretakedown;
+	dev->fn_tbl.dma_quiescent = mga_driver_dma_quiescent;
+	dev->fn_tbl.vblank_wait = mga_driver_vblank_wait;
+	dev->fn_tbl.irq_preinstall = mga_driver_irq_preinstall;
+	dev->fn_tbl.irq_postinstall = mga_driver_irq_postinstall;
+	dev->fn_tbl.irq_uninstall = mga_driver_irq_uninstall;
+	dev->fn_tbl.irq_handler = mga_driver_irq_handler;
+	
+	dev->counters += 3;
+	dev->types[6] = _DRM_STAT_IRQ;
+	dev->types[7] = _DRM_STAT_PRIMARY;
+	dev->types[8] = _DRM_STAT_SECONDARY;
+}
diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c
index 6bcad048f..aa27a2c4b 100644
--- a/drivers/char/drm/mga_drv.c
+++ b/drivers/char/drm/mga_drv.c
@@ -35,19 +35,4 @@
 #include "drm.h"
 #include "mga_drm.h"
 #include "mga_drv.h"
-#include "drm_agpsupport.h"
-#include "drm_auth.h"
-#include "drm_bufs.h"
-#include "drm_context.h"
-#include "drm_dma.h"
-#include "drm_drawable.h"
-#include "drm_drv.h"
-#include "drm_fops.h"
-#include "drm_init.h"
-#include "drm_ioctl.h"
-#include "drm_irq.h"
-#include "drm_lock.h"
-#include "drm_memory.h"
-#include "drm_proc.h"
-#include "drm_vm.h"
-#include "drm_stub.h"
+#include "drm_core.h"
diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
index 65847165c..75dcb0e93 100644
--- a/drivers/char/drm/mga_drv.h
+++ b/drivers/char/drm/mga_drv.h
@@ -130,6 +130,12 @@ extern int  mga_getparam( DRM_IOCTL_ARGS );
 extern int mga_warp_install_microcode( drm_mga_private_t *dev_priv );
 extern int mga_warp_init( drm_mga_private_t *dev_priv );
 
+extern int mga_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
+extern irqreturn_t mga_driver_irq_handler( DRM_IRQ_ARGS );
+extern void mga_driver_irq_preinstall( drm_device_t *dev );
+extern void mga_driver_irq_postinstall( drm_device_t *dev );
+extern void mga_driver_irq_uninstall( drm_device_t *dev );
+
 #define mga_flush_write_combine()	DRM_WRITEMEMORYBARRIER()
 
 #if defined(__linux__) && defined(__alpha__)
diff --git a/drivers/char/drm/mga_irq.c b/drivers/char/drm/mga_irq.c
index e486618b2..c3185b0b8 100644
--- a/drivers/char/drm/mga_irq.c
+++ b/drivers/char/drm/mga_irq.c
@@ -36,7 +36,7 @@
 #include "mga_drm.h"
 #include "mga_drv.h"
 
-irqreturn_t mga_irq_handler( DRM_IRQ_ARGS )
+irqreturn_t mga_driver_irq_handler( DRM_IRQ_ARGS )
 {
 	drm_device_t *dev = (drm_device_t *) arg;
 	drm_mga_private_t *dev_priv = 
@@ -56,7 +56,7 @@ irqreturn_t mga_irq_handler( DRM_IRQ_ARGS )
 	return IRQ_NONE;
 }
 
-int mga_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+int mga_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
 {
 	unsigned int cur_vblank;
 	int ret = 0;
diff --git a/drivers/char/drm/r128.h b/drivers/char/drm/r128.h
index 9dfe18974..1df7042a2 100644
--- a/drivers/char/drm/r128.h
+++ b/drivers/char/drm/r128.h
@@ -36,13 +36,6 @@
 
 /* General customization:
  */
-#define __HAVE_AGP		1
-#define __MUST_HAVE_AGP		0
-#define __HAVE_MTRR		1
-#define __HAVE_CTX_BITMAP	1
-#define __HAVE_SG		1
-#define __HAVE_PCI_DMA		1
-
 #define DRIVER_AUTHOR		"Gareth Hughes, VA Linux Systems Inc."
 
 #define DRIVER_NAME		"r128"
@@ -79,42 +72,4 @@
    [DRM_IOCTL_NR(DRM_IOCTL_R128_INDIRECT)]   = { r128_cce_indirect, 1, 1 }, \
    [DRM_IOCTL_NR(DRM_IOCTL_R128_GETPARAM)]   = { r128_getparam, 1, 0 },
 
-/* Driver customization:
- */
-#define DRIVER_PRERELEASE() do {					\
-	if ( dev->dev_private ) {					\
-		drm_r128_private_t *dev_priv = dev->dev_private;	\
-		if ( dev_priv->page_flipping ) {			\
-			r128_do_cleanup_pageflip( dev );		\
-		}							\
-	}								\
-} while (0)
-
-#define DRIVER_PRETAKEDOWN() do {					\
-	r128_do_cleanup_cce( dev );					\
-} while (0)
-
-/* DMA customization:
- */
-#define __HAVE_DMA		1
-#define __HAVE_IRQ		1
-#define __HAVE_VBL_IRQ		1
-#define __HAVE_SHARED_IRQ       1
-
-#if 0
-/* GH: Remove this for now... */
-#define __HAVE_DMA_QUIESCENT	1
-#define DRIVER_DMA_QUIESCENT() do {					\
-	drm_r128_private_t *dev_priv = dev->dev_private;		\
-	return r128_do_cce_idle( dev_priv );				\
-} while (0)
-#endif
-
-/* Buffer customization:
- */
-#define DRIVER_BUF_PRIV_T	drm_r128_buf_priv_t
-
-#define DRIVER_AGP_BUFFERS_MAP( dev )					\
-	((drm_r128_private_t *)((dev)->dev_private))->buffers
-
 #endif
diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c
index 22d38b70c..5fbea8ca6 100644
--- a/drivers/char/drm/r128_cce.c
+++ b/drivers/char/drm/r128_cce.c
@@ -322,7 +322,7 @@ static void r128_cce_init_ring_buffer( drm_device_t *dev,
 	/* The manual (p. 2) says this address is in "VM space".  This
 	 * means it's an offset from the start of AGP space.
 	 */
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	if ( !dev_priv->is_pci )
 		ring_start = dev_priv->cce_ring->offset - dev->agp->base;
 	else
@@ -467,29 +467,29 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
 		return DRM_ERR(EINVAL);
 	}
 
-	DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
+	dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
 	if(!dev_priv->mmio) {
 		DRM_ERROR("could not find mmio region!\n");
 		dev->dev_private = (void *)dev_priv;
 		r128_do_cleanup_cce( dev );
 		return DRM_ERR(EINVAL);
 	}
-	DRM_FIND_MAP( dev_priv->cce_ring, init->ring_offset );
+	dev_priv->cce_ring = drm_core_findmap(dev, init->ring_offset);
 	if(!dev_priv->cce_ring) {
 		DRM_ERROR("could not find cce ring region!\n");
 		dev->dev_private = (void *)dev_priv;
 		r128_do_cleanup_cce( dev );
 		return DRM_ERR(EINVAL);
 	}
-	DRM_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );
+	dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
 	if(!dev_priv->ring_rptr) {
 		DRM_ERROR("could not find ring read pointer!\n");
 		dev->dev_private = (void *)dev_priv;
 		r128_do_cleanup_cce( dev );
 		return DRM_ERR(EINVAL);
 	}
-	DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
-	if(!dev_priv->buffers) {
+	dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+	if(!dev->agp_buffer_map) {
 		DRM_ERROR("could not find dma buffer region!\n");
 		dev->dev_private = (void *)dev_priv;
 		r128_do_cleanup_cce( dev );
@@ -497,8 +497,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
 	}
 
 	if ( !dev_priv->is_pci ) {
-		DRM_FIND_MAP( dev_priv->agp_textures,
-			      init->agp_textures_offset );
+		dev_priv->agp_textures = drm_core_findmap(dev, init->agp_textures_offset);
 		if(!dev_priv->agp_textures) {
 			DRM_ERROR("could not find agp texture region!\n");
 			dev->dev_private = (void *)dev_priv;
@@ -511,14 +510,14 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
 		(drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle +
 				     init->sarea_priv_offset);
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	if ( !dev_priv->is_pci ) {
-		DRM_IOREMAP( dev_priv->cce_ring, dev );
-		DRM_IOREMAP( dev_priv->ring_rptr, dev );
-		DRM_IOREMAP( dev_priv->buffers, dev );
+		drm_core_ioremap( dev_priv->cce_ring, dev );
+		drm_core_ioremap( dev_priv->ring_rptr, dev );
+		drm_core_ioremap( dev->agp_buffer_map, dev );
 		if(!dev_priv->cce_ring->handle ||
 		   !dev_priv->ring_rptr->handle ||
-		   !dev_priv->buffers->handle) {
+		   !dev->agp_buffer_map->handle) {
 			DRM_ERROR("Could not ioremap agp regions!\n");
 			dev->dev_private = (void *)dev_priv;
 			r128_do_cleanup_cce( dev );
@@ -531,10 +530,10 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
 			(void *)dev_priv->cce_ring->offset;
 		dev_priv->ring_rptr->handle =
 			(void *)dev_priv->ring_rptr->offset;
-		dev_priv->buffers->handle = (void *)dev_priv->buffers->offset;
+		dev->agp_buffer_map->handle = (void *)dev->agp_buffer_map->offset;
 	}
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	if ( !dev_priv->is_pci )
 		dev_priv->cce_buffers_offset = dev->agp->base;
 	else
@@ -559,7 +558,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
 	R128_WRITE( R128_LAST_DISPATCH_REG,
 		    dev_priv->sarea_priv->last_dispatch );
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	if ( dev_priv->is_pci ) {
 #endif
 		if (!DRM(ati_pcigart_init)( dev, &dev_priv->phys_pci_gart,
@@ -570,7 +569,7 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
 			return DRM_ERR(ENOMEM);
 		}
 		R128_WRITE( R128_PCI_GART_PAGE, dev_priv->bus_pci_gart );
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	}
 #endif
 
@@ -587,25 +586,23 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
 int r128_do_cleanup_cce( drm_device_t *dev )
 {
 
-#if __HAVE_IRQ
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
 	 * is freed, it's too late.
 	 */
 	if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
-#endif
 
 	if ( dev->dev_private ) {
 		drm_r128_private_t *dev_priv = dev->dev_private;
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 		if ( !dev_priv->is_pci ) {
 			if ( dev_priv->cce_ring != NULL )
-				DRM_IOREMAPFREE( dev_priv->cce_ring, dev );
+				drm_core_ioremapfree( dev_priv->cce_ring, dev );
 			if ( dev_priv->ring_rptr != NULL )
-				DRM_IOREMAPFREE( dev_priv->ring_rptr, dev );
-			if ( dev_priv->buffers != NULL )
-				DRM_IOREMAPFREE( dev_priv->buffers, dev );
+				drm_core_ioremapfree( dev_priv->ring_rptr, dev );
+			if ( dev->agp_buffer_map != NULL )
+				drm_core_ioremapfree( dev->agp_buffer_map, dev );
 		} else
 #endif
 		{
diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c
index 1dee16159..8cfc9966c 100644
--- a/drivers/char/drm/r128_drv.c
+++ b/drivers/char/drm/r128_drv.c
@@ -37,20 +37,4 @@
 #include "r128_drv.h"
 #include "ati_pcigart.h"
 
-#include "drm_agpsupport.h"
-#include "drm_auth.h"
-#include "drm_bufs.h"
-#include "drm_context.h"
-#include "drm_dma.h"
-#include "drm_drawable.h"
-#include "drm_drv.h"
-#include "drm_fops.h"
-#include "drm_init.h"
-#include "drm_ioctl.h"
-#include "drm_irq.h"
-#include "drm_lock.h"
-#include "drm_memory.h"
-#include "drm_proc.h"
-#include "drm_vm.h"
-#include "drm_stub.h"
-#include "drm_scatter.h"
+#include "drm_core.h"
diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
index 9df32e566..5b91256c1 100644
--- a/drivers/char/drm/r128_drv.h
+++ b/drivers/char/drm/r128_drv.h
@@ -100,7 +100,6 @@ typedef struct drm_r128_private {
 	drm_local_map_t *mmio;
 	drm_local_map_t *cce_ring;
 	drm_local_map_t *ring_rptr;
-	drm_local_map_t *buffers;
 	drm_local_map_t *agp_textures;
 } drm_r128_private_t;
 
@@ -143,6 +142,12 @@ extern int r128_cce_depth( DRM_IOCTL_ARGS );
 extern int r128_cce_stipple( DRM_IOCTL_ARGS );
 extern int r128_cce_indirect( DRM_IOCTL_ARGS );
 
+extern int r128_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
+
+extern irqreturn_t r128_driver_irq_handler( DRM_IRQ_ARGS );
+extern void r128_driver_irq_preinstall( drm_device_t *dev );
+extern void r128_driver_irq_postinstall( drm_device_t *dev );
+extern void r128_driver_irq_uninstall( drm_device_t *dev );
 
 /* Register definitions, register access macros and drmAddMap constants
  * for Rage 128 kernel driver.
diff --git a/drivers/char/drm/r128_irq.c b/drivers/char/drm/r128_irq.c
index e77a5538b..be1b9dac6 100644
--- a/drivers/char/drm/r128_irq.c
+++ b/drivers/char/drm/r128_irq.c
@@ -36,7 +36,7 @@
 #include "r128_drm.h"
 #include "r128_drv.h"
 
-irqreturn_t r128_irq_handler( DRM_IRQ_ARGS )
+irqreturn_t r128_driver_irq_handler( DRM_IRQ_ARGS )
 {
 	drm_device_t *dev = (drm_device_t *) arg;
 	drm_r128_private_t *dev_priv = 
@@ -56,7 +56,7 @@ irqreturn_t r128_irq_handler( DRM_IRQ_ARGS )
 	return IRQ_NONE;
 }
 
-int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence)
+int r128_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
 {
 	unsigned int cur_vblank;
 	int ret = 0;
diff --git a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c
index 34ebcae1f..adc326698 100644
--- a/drivers/char/drm/r128_state.c
+++ b/drivers/char/drm/r128_state.c
@@ -667,7 +667,7 @@ static void r128_cce_dispatch_indirect( drm_device_t *dev,
 		 */
 		if ( dwords & 1 ) {
 			u32 *data = (u32 *)
-				((char *)dev_priv->buffers->handle
+				((char *)dev->agp_buffer_map->handle
 				 + buf->offset + start);
 			data[dwords++] = cpu_to_le32( R128_CCE_PACKET2 );
 		}
@@ -713,7 +713,7 @@ static void r128_cce_dispatch_indices( drm_device_t *dev,
 	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
 	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	int format = sarea_priv->vc_format;
-	int offset = dev_priv->buffers->offset - dev_priv->cce_buffers_offset;
+	int offset = dev->agp_buffer_map->offset - dev_priv->cce_buffers_offset;
 	int prim = buf_priv->prim;
 	u32 *data;
 	int dwords;
@@ -733,7 +733,7 @@ static void r128_cce_dispatch_indices( drm_device_t *dev,
 
 		dwords = (end - start + 3) / sizeof(u32);
 
-		data = (u32 *)((char *)dev_priv->buffers->handle
+		data = (u32 *)((char *)dev->agp_buffer_map->handle
 			       + buf->offset + start);
 
 		data[0] = cpu_to_le32( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM,
@@ -857,7 +857,7 @@ static int r128_cce_dispatch_blit( DRMFILE filp,
 
 	dwords = (blit->width * blit->height) >> dword_shift;
 
-	data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset);
+	data = (u32 *)((char *)dev->agp_buffer_map->handle + buf->offset);
 
 	data[0] = cpu_to_le32( CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, dwords + 6 ) );
 	data[1] = cpu_to_le32( (R128_GMC_DST_PITCH_OFFSET_CNTL |
@@ -1694,3 +1694,31 @@ int r128_getparam( DRM_IOCTL_ARGS )
 	
 	return 0;
 }
+
+static void r128_driver_prerelease(drm_device_t *dev, DRMFILE filp)
+{
+	if ( dev->dev_private ) {
+		drm_r128_private_t *dev_priv = dev->dev_private;
+		if ( dev_priv->page_flipping ) {
+			r128_do_cleanup_pageflip( dev );
+		}
+	}			
+}
+
+static void r128_driver_pretakedown(drm_device_t *dev)
+{
+	r128_do_cleanup_cce( dev );
+}
+
+void r128_driver_register_fns(drm_device_t *dev)
+{
+	dev->driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL;
+	dev->dev_priv_size = sizeof(drm_r128_buf_priv_t);
+	dev->fn_tbl.prerelease = r128_driver_prerelease;
+	dev->fn_tbl.pretakedown = r128_driver_pretakedown;
+	dev->fn_tbl.vblank_wait = r128_driver_vblank_wait;
+	dev->fn_tbl.irq_preinstall = r128_driver_irq_preinstall;
+	dev->fn_tbl.irq_postinstall = r128_driver_irq_postinstall;
+	dev->fn_tbl.irq_uninstall = r128_driver_irq_uninstall;
+	dev->fn_tbl.irq_handler = r128_driver_irq_handler;
+}
diff --git a/drivers/char/drm/radeon.h b/drivers/char/drm/radeon.h
index 83902f869..43723d53e 100644
--- a/drivers/char/drm/radeon.h
+++ b/drivers/char/drm/radeon.h
@@ -37,12 +37,6 @@
 
 /* General customization:
  */
-#define __HAVE_AGP		1
-#define __MUST_HAVE_AGP		0
-#define __HAVE_MTRR		1
-#define __HAVE_CTX_BITMAP	1
-#define __HAVE_SG		1
-#define __HAVE_PCI_DMA		1
 
 #define DRIVER_AUTHOR		"Gareth Hughes, Keith Whitwell, others."
 
@@ -115,59 +109,4 @@
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)]   = { radeon_irq_wait,    1, 0 }, \
  [DRM_IOCTL_NR(DRM_IOCTL_RADEON_SETPARAM)]   = { radeon_cp_setparam, 1, 0 }, \
 
-#define DRIVER_FILE_FIELDS						\
-	int64_t radeon_fb_delta;					\
-
-#define DRIVER_OPEN_HELPER( filp_priv, dev )				\
-do {									\
-	drm_radeon_private_t *dev_priv = dev->dev_private;		\
-	if ( dev_priv )							\
-		filp_priv->radeon_fb_delta = dev_priv->fb_location;	\
-	else								\
-		filp_priv->radeon_fb_delta = 0;				\
-} while( 0 )
-
-/* When a client dies:
- *    - Check for and clean up flipped page state
- *    - Free any alloced GART memory.
- *
- * DRM infrastructure takes care of reclaiming dma buffers.
- */
-#define DRIVER_PRERELEASE() 						\
-do {									\
-	if ( dev->dev_private ) {					\
-		drm_radeon_private_t *dev_priv = dev->dev_private;	\
-		if ( dev_priv->page_flipping ) {			\
-			radeon_do_cleanup_pageflip( dev );		\
-		}							\
-		radeon_mem_release( filp, dev_priv->gart_heap );	\
-		radeon_mem_release( filp, dev_priv->fb_heap );		\
-	}								\
-} while (0)
-
-/* When the last client dies, shut down the CP and free dev->dev_priv.
- */
-/* #define __HAVE_RELEASE 1 */
-#define DRIVER_PRETAKEDOWN()			\
-do {						\
-    radeon_do_release( dev );			\
-} while (0)
-
-
-
-/* DMA customization:
- */
-#define __HAVE_DMA		1
-#define __HAVE_IRQ		1
-#define __HAVE_VBL_IRQ		1
-#define __HAVE_SHARED_IRQ       1
-
-
-/* Buffer customization:
- */
-#define DRIVER_BUF_PRIV_T	drm_radeon_buf_priv_t
-
-#define DRIVER_AGP_BUFFERS_MAP( dev )				\
-	((drm_radeon_private_t *)((dev)->dev_private))->buffers
-
 #endif
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
index f6964908a..43834b906 100644
--- a/drivers/char/drm/radeon_cp.c
+++ b/drivers/char/drm/radeon_cp.c
@@ -858,7 +858,7 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev,
 		      ( ( dev_priv->gart_vm_start - 1 ) & 0xffff0000 )
 		    | ( dev_priv->fb_location >> 16 ) );
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	if ( !dev_priv->is_pci ) {
 		RADEON_WRITE( RADEON_MC_AGP_LOCATION,
 			      (((dev_priv->gart_vm_start - 1 +
@@ -885,7 +885,7 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev,
 	SET_RING_HEAD( dev_priv, cur_read_ptr );
 	dev_priv->ring.tail = cur_read_ptr;
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	if ( !dev_priv->is_pci ) {
 		RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR,
 			      dev_priv->ring_rptr->offset
@@ -1118,29 +1118,29 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
 		return DRM_ERR(EINVAL);
 	}
 
-	DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
+	dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
 	if(!dev_priv->mmio) {
 		DRM_ERROR("could not find mmio region!\n");
 		dev->dev_private = (void *)dev_priv;
 		radeon_do_cleanup_cp(dev);
 		return DRM_ERR(EINVAL);
 	}
-	DRM_FIND_MAP( dev_priv->cp_ring, init->ring_offset );
+	dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset);
 	if(!dev_priv->cp_ring) {
 		DRM_ERROR("could not find cp ring region!\n");
 		dev->dev_private = (void *)dev_priv;
 		radeon_do_cleanup_cp(dev);
 		return DRM_ERR(EINVAL);
 	}
-	DRM_FIND_MAP( dev_priv->ring_rptr, init->ring_rptr_offset );
+	dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
 	if(!dev_priv->ring_rptr) {
 		DRM_ERROR("could not find ring read pointer!\n");
 		dev->dev_private = (void *)dev_priv;
 		radeon_do_cleanup_cp(dev);
 		return DRM_ERR(EINVAL);
 	}
-	DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
-	if(!dev_priv->buffers) {
+	dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+	if(!dev->agp_buffer_map) {
 		DRM_ERROR("could not find dma buffer region!\n");
 		dev->dev_private = (void *)dev_priv;
 		radeon_do_cleanup_cp(dev);
@@ -1148,7 +1148,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
 	}
 
 	if ( init->gart_textures_offset ) {
-		DRM_FIND_MAP( dev_priv->gart_textures, init->gart_textures_offset );
+		dev_priv->gart_textures = drm_core_findmap(dev, init->gart_textures_offset);
 		if ( !dev_priv->gart_textures ) {
 			DRM_ERROR("could not find GART texture region!\n");
 			dev->dev_private = (void *)dev_priv;
@@ -1161,14 +1161,14 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
 		(drm_radeon_sarea_t *)((u8 *)dev_priv->sarea->handle +
 				       init->sarea_priv_offset);
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	if ( !dev_priv->is_pci ) {
-		DRM_IOREMAP( dev_priv->cp_ring, dev );
-		DRM_IOREMAP( dev_priv->ring_rptr, dev );
-		DRM_IOREMAP( dev_priv->buffers, dev );
+		drm_core_ioremap( dev_priv->cp_ring, dev );
+		drm_core_ioremap( dev_priv->ring_rptr, dev );
+		drm_core_ioremap( dev->agp_buffer_map, dev );
 		if(!dev_priv->cp_ring->handle ||
 		   !dev_priv->ring_rptr->handle ||
-		   !dev_priv->buffers->handle) {
+		   !dev->agp_buffer_map->handle) {
 			DRM_ERROR("could not find ioremap agp regions!\n");
 			dev->dev_private = (void *)dev_priv;
 			radeon_do_cleanup_cp(dev);
@@ -1181,14 +1181,14 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
 			(void *)dev_priv->cp_ring->offset;
 		dev_priv->ring_rptr->handle =
 			(void *)dev_priv->ring_rptr->offset;
-		dev_priv->buffers->handle = (void *)dev_priv->buffers->offset;
+		dev->agp_buffer_map->handle = (void *)dev->agp_buffer_map->offset;
 
 		DRM_DEBUG( "dev_priv->cp_ring->handle %p\n",
 			   dev_priv->cp_ring->handle );
 		DRM_DEBUG( "dev_priv->ring_rptr->handle %p\n",
 			   dev_priv->ring_rptr->handle );
-		DRM_DEBUG( "dev_priv->buffers->handle %p\n",
-			   dev_priv->buffers->handle );
+		DRM_DEBUG( "dev->agp_buffer_map->handle %p\n",
+			   dev->agp_buffer_map->handle );
 	}
 
 	dev_priv->fb_location = ( RADEON_READ( RADEON_MC_FB_LOCATION )
@@ -1211,14 +1211,14 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
 	dev_priv->gart_vm_start = dev_priv->fb_location
 				+ RADEON_READ( RADEON_CONFIG_APER_SIZE );
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	if ( !dev_priv->is_pci )
-		dev_priv->gart_buffers_offset = (dev_priv->buffers->offset
+		dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
 						- dev->agp->base
 						+ dev_priv->gart_vm_start);
 	else
 #endif
-		dev_priv->gart_buffers_offset = (dev_priv->buffers->offset
+		dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
 						- dev->sg->handle
 						+ dev_priv->gart_vm_start);
 
@@ -1240,7 +1240,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init )
 
 	dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	if ( !dev_priv->is_pci ) {
 		/* Turn off PCI GART */
 		radeon_set_pcigart( dev_priv, 0 );
@@ -1275,25 +1275,23 @@ int radeon_do_cleanup_cp( drm_device_t *dev )
 {
 	DRM_DEBUG( "\n" );
 
-#if __HAVE_IRQ
 	/* Make sure interrupts are disabled here because the uninstall ioctl
 	 * may not have been called from userspace and after dev_private
 	 * is freed, it's too late.
 	 */
 	if ( dev->irq_enabled ) DRM(irq_uninstall)(dev);
-#endif
 
 	if ( dev->dev_private ) {
 		drm_radeon_private_t *dev_priv = dev->dev_private;
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 		if ( !dev_priv->is_pci ) {
 			if ( dev_priv->cp_ring != NULL )
-				DRM_IOREMAPFREE( dev_priv->cp_ring, dev );
+				drm_core_ioremapfree( dev_priv->cp_ring, dev );
 			if ( dev_priv->ring_rptr != NULL )
-				DRM_IOREMAPFREE( dev_priv->ring_rptr, dev );
-			if ( dev_priv->buffers != NULL )
-				DRM_IOREMAPFREE( dev_priv->buffers, dev );
+				drm_core_ioremapfree( dev_priv->ring_rptr, dev );
+			if ( dev->agp_buffer_map != NULL )
+				drm_core_ioremapfree( dev->agp_buffer_map, dev );
 		} else
 #endif
 		{
@@ -1329,7 +1327,7 @@ static int radeon_do_resume_cp( drm_device_t *dev )
 
 	DRM_DEBUG("Starting radeon_do_resume_cp()\n");
 
-#if __REALLY_HAVE_AGP
+#if __OS_HAS_AGP
 	if ( !dev_priv->is_pci ) {
 		/* Turn off PCI GART */
 		radeon_set_pcigart( dev_priv, 0 );
diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
index 74e32df01..965abc449 100644
--- a/drivers/char/drm/radeon_drv.c
+++ b/drivers/char/drm/radeon_drv.c
@@ -38,20 +38,4 @@
 #include "radeon_drv.h"
 #include "ati_pcigart.h"
 
-#include "drm_agpsupport.h"
-#include "drm_auth.h"
-#include "drm_bufs.h"
-#include "drm_context.h"
-#include "drm_dma.h"
-#include "drm_drawable.h"
-#include "drm_drv.h"
-#include "drm_fops.h"
-#include "drm_init.h"
-#include "drm_ioctl.h"
-#include "drm_irq.h"
-#include "drm_lock.h"
-#include "drm_memory.h"
-#include "drm_proc.h"
-#include "drm_vm.h"
-#include "drm_stub.h"
-#include "drm_scatter.h"
+#include "drm_core.h"
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index e24e0ec09..5df72332e 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -60,6 +60,9 @@ typedef struct drm_radeon_depth_clear_t {
 	u32 se_cntl;
 } drm_radeon_depth_clear_t;
 
+struct drm_radeon_driver_file_fields {
+	int64_t radeon_fb_delta;
+};
 
 struct mem_block {
 	struct mem_block *next;
@@ -138,7 +141,6 @@ typedef struct drm_radeon_private {
 	drm_local_map_t *mmio;
 	drm_local_map_t *cp_ring;
 	drm_local_map_t *ring_rptr;
-	drm_local_map_t *buffers;
 	drm_local_map_t *gart_textures;
 
 	struct mem_block *gart_heap;
@@ -203,6 +205,11 @@ extern int radeon_wait_irq(drm_device_t *dev, int swi_nr);
 extern int radeon_emit_irq(drm_device_t *dev);
 
 extern void radeon_do_release(drm_device_t *dev);
+extern int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
+extern irqreturn_t radeon_driver_irq_handler( DRM_IRQ_ARGS );
+extern void radeon_driver_irq_preinstall( drm_device_t *dev );
+extern void radeon_driver_irq_postinstall( drm_device_t *dev );
+extern void radeon_driver_irq_uninstall( drm_device_t *dev );
 
 /* Flags for stats.boxes
  */
diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
index 51d194935..bdb3cc168 100644
--- a/drivers/char/drm/radeon_irq.c
+++ b/drivers/char/drm/radeon_irq.c
@@ -54,7 +54,7 @@
  * tied to dma at all, this is just a hangover from dri prehistory.
  */
 
-irqreturn_t DRM(irq_handler)( DRM_IRQ_ARGS )
+irqreturn_t radeon_driver_irq_handler( DRM_IRQ_ARGS )
 {
 	drm_device_t *dev = (drm_device_t *) arg;
 	drm_radeon_private_t *dev_priv = 
@@ -141,7 +141,7 @@ int radeon_emit_and_wait_irq(drm_device_t *dev)
 }
 
 
-int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence)
+int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
 {
   	drm_radeon_private_t *dev_priv = 
 	   (drm_radeon_private_t *)dev->dev_private;
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index 984d74589..f3cc86eea 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -43,12 +43,14 @@ static __inline__ int radeon_check_and_fixup_offset( drm_radeon_private_t *dev_p
 						     drm_file_t *filp_priv,
 						     u32 *offset ) {
 	u32 off = *offset;
+	struct drm_radeon_driver_file_fields *radeon_priv;
 
 	if ( off >= dev_priv->fb_location &&
 	     off < ( dev_priv->gart_vm_start + dev_priv->gart_size ) )
 		return 0;
 
-	off += filp_priv->radeon_fb_delta;
+	radeon_priv = filp_priv->driver_priv;
+	off += radeon_priv->radeon_fb_delta;
 
 	DRM_DEBUG( "offset fixed up to 0x%x\n", off );
 
@@ -1247,7 +1249,7 @@ static void radeon_cp_dispatch_indirect( drm_device_t *dev,
 		 */
 		if ( dwords & 1 ) {
 			u32 *data = (u32 *)
-				((char *)dev_priv->buffers->handle
+				((char *)dev->agp_buffer_map->handle
 				 + buf->offset + start);
 			data[dwords++] = RADEON_CP_PACKET2;
 		}
@@ -1301,7 +1303,7 @@ static void radeon_cp_dispatch_indices( drm_device_t *dev,
 
 	dwords = (prim->finish - prim->start + 3) / sizeof(u32);
 
-	data = (u32 *)((char *)dev_priv->buffers->handle +
+	data = (u32 *)((char *)dev->agp_buffer_map->handle +
 		       elt_buf->offset + prim->start);
 
 	data[0] = CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 );
@@ -1445,7 +1447,7 @@ static int radeon_cp_dispatch_texture( DRMFILE filp,
 
 		/* Dispatch the indirect buffer.
 		 */
-		buffer = (u32*)((char*)dev_priv->buffers->handle + buf->offset);
+		buffer = (u32*)((char*)dev->agp_buffer_map->handle + buf->offset);
 		dwords = size / 4;
 		buffer[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 );
 		buffer[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL |
@@ -1665,11 +1667,6 @@ int radeon_cp_vertex( DRM_IOCTL_ARGS )
 
 	LOCK_TEST_WITH_RETURN( dev, filp );
 
-	if ( !dev_priv ) {
-		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
-		return DRM_ERR(EINVAL);
-	}
-
 	DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
 
 	DRM_COPY_FROM_USER_IOCTL( vertex, (drm_radeon_vertex_t __user *)data,
@@ -2525,6 +2522,7 @@ int radeon_cp_setparam( DRM_IOCTL_ARGS ) {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_file_t *filp_priv;
 	drm_radeon_setparam_t sp;
+	struct drm_radeon_driver_file_fields *radeon_priv;
 
 	if ( !dev_priv ) {
 		DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
@@ -2538,7 +2536,8 @@ int radeon_cp_setparam( DRM_IOCTL_ARGS ) {
 
 	switch( sp.param ) {
 	case RADEON_SETPARAM_FB_LOCATION:
-		filp_priv->radeon_fb_delta = dev_priv->fb_location - sp.value;
+		radeon_priv = filp_priv->driver_priv;
+		radeon_priv->radeon_fb_delta = dev_priv->fb_location - sp.value;
 		break;
 	default:
 		DRM_DEBUG( "Invalid parameter %d\n", sp.param );
@@ -2547,3 +2546,67 @@ int radeon_cp_setparam( DRM_IOCTL_ARGS ) {
 
 	return 0;
 }
+
+/* When a client dies:
+ *    - Check for and clean up flipped page state
+ *    - Free any alloced GART memory.
+ *
+ * DRM infrastructure takes care of reclaiming dma buffers.
+ */
+static void radeon_driver_prerelease(drm_device_t *dev, DRMFILE filp)
+{
+	if ( dev->dev_private ) {				
+		drm_radeon_private_t *dev_priv = dev->dev_private; 
+		if ( dev_priv->page_flipping ) {		
+			radeon_do_cleanup_pageflip( dev );	
+		}						
+		radeon_mem_release( filp, dev_priv->gart_heap ); 
+		radeon_mem_release( filp, dev_priv->fb_heap );	
+	}				
+}
+
+static void radeon_driver_pretakedown(drm_device_t *dev)
+{
+	radeon_do_release(dev);
+}
+
+static int radeon_driver_open_helper(drm_device_t *dev, drm_file_t *filp_priv)
+{
+	drm_radeon_private_t *dev_priv = dev->dev_private;
+	struct drm_radeon_driver_file_fields *radeon_priv;
+	
+	radeon_priv = (struct drm_radeon_driver_file_fields *)DRM(alloc)(sizeof(*radeon_priv), DRM_MEM_FILES);
+	
+	if (!radeon_priv)
+		return -ENOMEM;
+
+	filp_priv->driver_priv = radeon_priv;
+	if ( dev_priv )
+		radeon_priv->radeon_fb_delta = dev_priv->fb_location;
+	else
+		radeon_priv->radeon_fb_delta = 0;
+	return 0;
+}
+
+
+static void radeon_driver_free_filp_priv(drm_device_t *dev, drm_file_t *filp_priv)
+{
+	 struct drm_radeon_driver_file_fields *radeon_priv = filp_priv->driver_priv;
+	 
+	 DRM(free)(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES);
+}
+
+void radeon_driver_register_fns(struct drm_device *dev)
+{	
+	dev->driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL;
+	dev->dev_priv_size = sizeof(drm_radeon_buf_priv_t);
+	dev->fn_tbl.prerelease = radeon_driver_prerelease;
+	dev->fn_tbl.pretakedown = radeon_driver_pretakedown;
+	dev->fn_tbl.open_helper = radeon_driver_open_helper;
+	dev->fn_tbl.free_filp_priv = radeon_driver_free_filp_priv;
+	dev->fn_tbl.vblank_wait = radeon_driver_vblank_wait;
+ 	dev->fn_tbl.irq_preinstall = radeon_driver_irq_preinstall;
+ 	dev->fn_tbl.irq_postinstall = radeon_driver_irq_postinstall;
+ 	dev->fn_tbl.irq_uninstall = radeon_driver_irq_uninstall;
+ 	dev->fn_tbl.irq_handler = radeon_driver_irq_handler;
+}
diff --git a/drivers/char/drm/sis.h b/drivers/char/drm/sis.h
index 7bdc99c0a..838e360df 100644
--- a/drivers/char/drm/sis.h
+++ b/drivers/char/drm/sis.h
@@ -41,10 +41,6 @@
 
 /* General customization:
  */
-#define __HAVE_AGP		1
-#define __MUST_HAVE_AGP		0
-#define __HAVE_MTRR		1
-#define __HAVE_CTX_BITMAP	1
 
 #define DRIVER_AUTHOR		"SIS"
 #define DRIVER_NAME		"sis"
@@ -62,17 +58,4 @@
 	[DRM_IOCTL_NR(DRM_IOCTL_SIS_AGP_FREE)]	= { sis_ioctl_agp_free,	1, 0 }, \
 	[DRM_IOCTL_NR(DRM_IOCTL_SIS_FB_INIT)]	= { sis_fb_init,	1, 1 }
 
-#define __HAVE_COUNTERS		5
-
-/* Buffer customization:
- */
-#define DRIVER_AGP_BUFFERS_MAP( dev )					\
-	((drm_sis_private_t *)((dev)->dev_private))->buffers
-
-extern int sis_init_context(int context);
-extern int sis_final_context(int context);
-
-#define DRIVER_CTX_CTOR sis_init_context
-#define DRIVER_CTX_DTOR sis_final_context
-
 #endif
diff --git a/drivers/char/drm/sis_drv.c b/drivers/char/drm/sis_drv.c
index 3dd075d30..f05734374 100644
--- a/drivers/char/drm/sis_drv.c
+++ b/drivers/char/drm/sis_drv.c
@@ -31,18 +31,4 @@
 #include "sis_drm.h"
 #include "sis_drv.h"
 
-#include "drm_auth.h"
-#include "drm_agpsupport.h"
-#include "drm_bufs.h"
-#include "drm_context.h"
-#include "drm_dma.h"
-#include "drm_drawable.h"
-#include "drm_drv.h"
-#include "drm_fops.h"
-#include "drm_init.h"
-#include "drm_ioctl.h"
-#include "drm_lock.h"
-#include "drm_memory.h"
-#include "drm_proc.h"
-#include "drm_vm.h"
-#include "drm_stub.h"
+#include "drm_core.h"
diff --git a/drivers/char/drm/sis_drv.h b/drivers/char/drm/sis_drv.h
index 40e7f463e..a87001819 100644
--- a/drivers/char/drm/sis_drv.h
+++ b/drivers/char/drm/sis_drv.h
@@ -31,8 +31,6 @@
 #include "sis_ds.h"
 
 typedef struct drm_sis_private {
-	drm_map_t *buffers;
-
 	memHeap_t *AGPHeap;
 	memHeap_t *FBHeap;
 } drm_sis_private_t;
diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c
index 5d29b40be..244471647 100644
--- a/drivers/char/drm/sis_mm.c
+++ b/drivers/char/drm/sis_mm.c
@@ -90,9 +90,10 @@ int sis_fb_alloc( DRM_IOCTL_ARGS )
 {
 	drm_sis_mem_t fb;
 	struct sis_memreq req;
+	drm_sis_mem_t __user *argp = (void __user *)data;
 	int retval = 0;
 
-	DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb));
+	DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb));
 
 	req.size = fb.size;
 	sis_malloc(&req);
@@ -111,7 +112,7 @@ int sis_fb_alloc( DRM_IOCTL_ARGS )
 		fb.free = 0;
 	}
 
-	DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, fb, sizeof(fb));
+	DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb));
 
 	DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, req.offset);
 
@@ -123,7 +124,7 @@ int sis_fb_free( DRM_IOCTL_ARGS )
 	drm_sis_mem_t fb;
 	int retval = 0;
 
-	DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb));
+	DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *)data, sizeof(fb));
 
 	if (!fb.free)
 		return DRM_ERR(EINVAL);
@@ -325,7 +326,7 @@ int sis_ioctl_agp_free( DRM_IOCTL_ARGS )
 	return 0;
 }
 
-int sis_init_context(int context)
+int sis_init_context(struct drm_device *dev, int context)
 {
 	int i;
 
@@ -357,7 +358,7 @@ int sis_init_context(int context)
 	return 1;
 }
 
-int sis_final_context(int context)
+int sis_final_context(struct drm_device *dev, int context)
 {
 	int i;
 
@@ -403,3 +404,10 @@ int sis_final_context(int context)
 	
 	return 1;
 }
+
+void DRM(driver_register_fns)(drm_device_t *dev)
+{
+	dev->driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR;
+	dev->fn_tbl.context_ctor = sis_init_context;
+	dev->fn_tbl.context_dtor = sis_final_context;
+}
diff --git a/drivers/char/drm/tdfx.h b/drivers/char/drm/tdfx.h
index 6b067db78..a582a3db4 100644
--- a/drivers/char/drm/tdfx.h
+++ b/drivers/char/drm/tdfx.h
@@ -36,8 +36,6 @@
 
 /* General customization:
  */
-#define __HAVE_MTRR		1
-#define __HAVE_CTX_BITMAP	1
 
 #define DRIVER_AUTHOR		"VA Linux Systems Inc."
 
diff --git a/drivers/char/drm/tdfx_drv.c b/drivers/char/drm/tdfx_drv.c
index fafa1f922..d13144438 100644
--- a/drivers/char/drm/tdfx_drv.c
+++ b/drivers/char/drm/tdfx_drv.c
@@ -34,18 +34,10 @@
 #include "tdfx.h"
 #include "drmP.h"
 
-#include "drm_auth.h"
-#include "drm_bufs.h"
-#include "drm_context.h"
-#include "drm_dma.h"
-#include "drm_drawable.h"
-#include "drm_drv.h"
+#include "drm_core.h"
+
+void DRM(driver_register_fns)(drm_device_t *dev)
+{
+	dev->driver_features = DRIVER_USE_MTRR;
+}
 
-#include "drm_fops.h"
-#include "drm_init.h"
-#include "drm_ioctl.h"
-#include "drm_lock.h"
-#include "drm_memory.h"
-#include "drm_proc.h"
-#include "drm_vm.h"
-#include "drm_stub.h"
diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c
index e2c4ecac7..7def6ad51 100644
--- a/drivers/char/ds1620.c
+++ b/drivers/char/ds1620.c
@@ -373,8 +373,7 @@ static int __init ds1620_init(void)
 	th_start.hi = 1;
 	ds1620_write_state(&th_start);
 
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout(2*HZ);
+	msleep(2000);
 
 	ds1620_write_state(&th);
 
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index b022aca3d..37d664901 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -58,12 +58,6 @@
 #define DSP56K_TRANSMIT		(dsp56k_host_interface.isr & DSP56K_ISR_TXDE)
 #define DSP56K_RECEIVE		(dsp56k_host_interface.isr & DSP56K_ISR_RXDF)
 
-#define wait_some(n) \
-{ \
-	set_current_state(TASK_INTERRUPTIBLE); \
-	schedule_timeout(n); \
-}
-
 #define handshake(count, maxio, timeout, ENABLE, f) \
 { \
 	long i, t, m; \
@@ -71,13 +65,13 @@
 		m = min_t(unsigned long, count, maxio); \
 		for (i = 0; i < m; i++) { \
 			for (t = 0; t < timeout && !ENABLE; t++) \
-				wait_some(HZ/50); \
+				msleep(20); \
 			if(!ENABLE) \
 				return -EIO; \
 			f; \
 		} \
 		count -= m; \
-		if (m == maxio) wait_some(HZ/50); \
+		if (m == maxio) msleep(20); \
 	} \
 }
 
@@ -85,7 +79,7 @@
 { \
 	int t; \
 	for(t = 0; t < n && !DSP56K_TRANSMIT; t++) \
-		wait_some(HZ/100); \
+		msleep(10); \
 	if(!DSP56K_TRANSMIT) { \
 		return -EIO; \
 	} \
@@ -95,7 +89,7 @@
 { \
 	int t; \
 	for(t = 0; t < n && !DSP56K_RECEIVE; t++) \
-		wait_some(HZ/100); \
+		msleep(10); \
 	if(!DSP56K_RECEIVE) { \
 		return -EIO; \
 	} \
diff --git a/drivers/char/ec3104_keyb.c b/drivers/char/ec3104_keyb.c
index 933282df5..b3289d9d2 100644
--- a/drivers/char/ec3104_keyb.c
+++ b/drivers/char/ec3104_keyb.c
@@ -412,7 +412,7 @@ static void ec3104_keyb_clear_state(void)
 	k->last_msr = 0;
 
 	for (;;) {
-		schedule_timeout(HZ/10);
+		msleep(100);
 
 		msr = ctrl_inb(EC3104_SER4_MSR);
 	
diff --git a/drivers/char/efirtc.c b/drivers/char/efirtc.c
index 6d0b81298..1845739ee 100644
--- a/drivers/char/efirtc.c
+++ b/drivers/char/efirtc.c
@@ -155,7 +155,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	efi_time_t	eft;
 	efi_time_cap_t	cap;
 	struct rtc_time	wtime;
-	struct rtc_wkalrm *ewp;
+	struct rtc_wkalrm __user *ewp;
 	unsigned char	enabled, pending;
 
 	switch (cmd) {
@@ -189,13 +189,15 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
 			convert_from_efi_time(&eft, &wtime);
 
- 			return copy_to_user((void *)arg, &wtime, sizeof (struct rtc_time)) ? - EFAULT : 0;
+ 			return copy_to_user((void __user *)arg, &wtime,
+					    sizeof (struct rtc_time)) ? - EFAULT : 0;
 
 		case RTC_SET_TIME:
 
 			if (!capable(CAP_SYS_TIME)) return -EACCES;
 
-			if (copy_from_user(&wtime, (struct rtc_time *)arg, sizeof(struct rtc_time)) )
+			if (copy_from_user(&wtime, (struct rtc_time __user *)arg,
+					   sizeof(struct rtc_time)) )
 				return -EFAULT;
 
 			convert_to_efi_time(&wtime, &eft);
@@ -212,19 +214,19 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
 			if (!capable(CAP_SYS_TIME)) return -EACCES;
 
-			ewp = (struct rtc_wkalrm *)arg;
+			ewp = (struct rtc_wkalrm __user *)arg;
 
 			if (  get_user(enabled, &ewp->enabled)
 			   || copy_from_user(&wtime, &ewp->time, sizeof(struct rtc_time)) )
 				return -EFAULT;
 
 			convert_to_efi_time(&wtime, &eft);
-			
+
 			spin_lock_irqsave(&efi_rtc_lock, flags);
 			/*
 			 * XXX Fixme:
 			 * As of EFI 0.92 with the firmware I have on my
-			 * machine this call does not seem to work quite 
+			 * machine this call does not seem to work quite
 			 * right
 			 */
 			status = efi.set_wakeup_time((efi_bool_t)enabled, &eft);
@@ -243,14 +245,15 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
 			if (status != EFI_SUCCESS) return -EINVAL;
 
-			ewp = (struct rtc_wkalrm *)arg;
+			ewp = (struct rtc_wkalrm __user *)arg;
 
 			if (  put_user(enabled, &ewp->enabled)
 			   || put_user(pending, &ewp->pending)) return -EFAULT;
 
 			convert_from_efi_time(&eft, &wtime);
 
-			return copy_to_user((void *)&ewp->time, &wtime, sizeof(struct rtc_time)) ? -EFAULT : 0;
+			return copy_to_user(&ewp->time, &wtime,
+					    sizeof(struct rtc_time)) ? -EFAULT : 0;
 	}
 	return -EINVAL;
 }
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index 854d16a39..0f13bef97 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -74,7 +74,6 @@
 #define DIGIINFOMAJOR       35  /* For Digi specific ioctl */ 
 
 
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
 #define MAXCARDS 7
 #define epcaassert(x, msg)  if (!(x)) epca_error(__LINE__, msg)
 
@@ -551,9 +550,7 @@ static void pc_close(struct tty_struct * tty, struct file * filp)
 		if (tty->driver->flush_buffer)
 			tty->driver->flush_buffer(tty);
 
-		if (tty->ldisc.flush_buffer)
-			tty->ldisc.flush_buffer(tty);
-
+		tty_ldisc_flush(tty);
 		shutdown(ch);
 		tty->closing = 0;
 		ch->event = 0;
@@ -657,10 +654,7 @@ static void pc_hangup(struct tty_struct *tty)
 		cli();
 		if (tty->driver->flush_buffer)
 			tty->driver->flush_buffer(tty);
-
-		if (tty->ldisc.flush_buffer)
-			tty->ldisc.flush_buffer(tty);
-
+		tty_ldisc_flush(tty);
 		shutdown(ch);
 
 		ch->tty   = NULL;
@@ -826,7 +820,7 @@ static int pc_write(struct tty_struct * tty, int from_user,
 			bytesAvailable will then take on this newly calculated value.
 		---------------------------------------------------------------------- */
 
-		bytesAvailable = MIN(dataLen, bytesAvailable);
+		bytesAvailable = min(dataLen, bytesAvailable);
 
 		/* First we read the data in from the file system into a temp buffer */
 
@@ -912,7 +906,7 @@ static int pc_write(struct tty_struct * tty, int from_user,
 			space; reduce the amount of data to fit the space.
 	---------------------------------------------------------------------- */
 
-	bytesAvailable = MIN(remain, bytesAvailable);
+	bytesAvailable = min(remain, bytesAvailable);
 
 	txwinon(ch);
 	while (bytesAvailable > 0) 
@@ -923,7 +917,7 @@ static int pc_write(struct tty_struct * tty, int from_user,
 			data copy fills to the end of card buffer.
 		------------------------------------------------------------------- */
 
-		dataLen = MIN(bytesAvailable, dataLen);
+		dataLen = min(bytesAvailable, dataLen);
 		memcpy(ch->txptr + head, buf, dataLen);
 		buf += dataLen;
 		head += dataLen;
@@ -1120,8 +1114,7 @@ static void pc_flush_buffer(struct tty_struct *tty)
 	restore_flags(flags);
 
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 
 } /* End pc_flush_buffer */
 
@@ -2262,9 +2255,7 @@ static void doevent(int crd)
 				{ /* Begin if LOWWAIT */
 
 					ch->statusflags &= ~LOWWAIT;
-					if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-						  tty->ldisc.write_wakeup)
-						(tty->ldisc.write_wakeup)(tty);
+					tty_wakeup(tty);
 					wake_up_interruptible(&tty->write_wait);
 
 				} /* End if LOWWAIT */
@@ -2281,9 +2272,7 @@ static void doevent(int crd)
 				{ /* Begin if EMPTYWAIT */
 
 					ch->statusflags &= ~EMPTYWAIT;
-					if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-						  tty->ldisc.write_wakeup)
-						(tty->ldisc.write_wakeup)(tty);
+					tty_wakeup(tty);
 
 					wake_up_interruptible(&tty->write_wait);
 
@@ -3136,6 +3125,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
 			}
 			else 
 			{
+				/* ldisc lock already held in ioctl */
 				if (tty->ldisc.flush_buffer)
 					tty->ldisc.flush_buffer(tty);
 			}
@@ -3307,7 +3297,6 @@ static void do_softint(void *private_)
 		}
 
 	} /* End EPCA_MAGIC */
-	MOD_DEC_USE_COUNT;
 } /* End do_softint */
 
 /* ------------------------------------------------------------
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 663a1e24f..d67098c45 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -19,7 +19,7 @@
  *
  *  rs_set_termios fixed to look also for changes of the input
  *      flags INPCK, BRKINT, PARMRK, IGNPAR and IGNBRK.
- *                                            Bernd Anhäupl 05/17/96.
+ *                                            Bernd Anh�pl 05/17/96.
  *
  * --- End of notices from serial.c ---
  *
@@ -140,7 +140,7 @@ static struct esp_struct *ports;
 
 static void change_speed(struct esp_struct *info);
 static void rs_wait_until_sent(struct tty_struct *, int);
-	
+
 /*
  * The ESP card has a clock rate of 14.7456 MHz (that is, 2**ESPC_SCALE
  * times the normal 1.8432 Mhz clock of most serial boards).
@@ -150,10 +150,6 @@ static void rs_wait_until_sent(struct tty_struct *, int);
 /* Standard COM flags (except for COM4, because of the 8514 problem) */
 #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
 
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
 /*
  * tmp_buf is used as a temporary buffer by serial_write.  We need to
  * lock it in case the memcpy_fromfs blocks while swapping in a page,
@@ -762,10 +758,7 @@ static void do_softint(void *private_)
 		return;
 
 	if (test_and_clear_bit(ESP_EVENT_WRITE_WAKEUP, &info->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
+		tty_wakeup(tty);
 	}
 }
 
@@ -1370,10 +1363,7 @@ static void rs_flush_buffer(struct tty_struct *tty)
 	cli();
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 	sti();
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /*
@@ -2069,8 +2059,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
 	shutdown(info);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
 	tty->closing = 0;
 	info->event = 0;
 	info->tty = NULL;
diff --git a/drivers/char/ftape/lowlevel/ftape-calibr.c b/drivers/char/ftape/lowlevel/ftape-calibr.c
index 34f0e69d3..956b2586e 100644
--- a/drivers/char/ftape/lowlevel/ftape-calibr.c
+++ b/drivers/char/ftape/lowlevel/ftape-calibr.c
@@ -31,7 +31,10 @@
 #include <asm/io.h>
 #if defined(__alpha__)
 # include <asm/hwrpb.h>
-#elif defined(__i386__) || defined(__x86_64__)
+#elif defined(__x86_64__)
+# include <asm/msr.h>
+# include <asm/timex.h>
+#elif defined(__i386__)
 # include <linux/timex.h>
 #endif
 #include <linux/ftape.h>
@@ -45,7 +48,7 @@
 # error Ftape is not implemented for this architecture!
 #endif
 
-#if defined(__alpha__)
+#if defined(__alpha__) || defined(__x86_64__)
 static unsigned long ps_per_cycle = 0;
 #endif
 
@@ -72,7 +75,18 @@ unsigned int ftape_timestamp(void)
 
 	asm volatile ("rpcc %0" : "=r" (r));
 	return r;
-#elif defined(__i386__) || defined(__x86_64__)
+#elif defined(__x86_64__)
+	unsigned long r;
+	rdtscl(r);
+	return r;
+#elif defined(__i386__)
+
+/*
+ * Note that there is some time between counter underflowing and jiffies
+ * increasing, so the code below won't always give correct output.
+ * -Vojtech
+ */
+
 	unsigned long flags;
 	__u16 lo;
 	__u16 hi;
@@ -89,9 +103,9 @@ unsigned int ftape_timestamp(void)
 
 static unsigned int short_ftape_timestamp(void)
 {
-#if defined(__alpha__)
+#if defined(__alpha__) || defined(__x86_64__)
 	return ftape_timestamp();
-#elif defined(__i386__) || defined(__x86_64__)
+#elif defined(__i386__)
 	unsigned int count;
  	unsigned long flags;
  
@@ -106,9 +120,9 @@ static unsigned int short_ftape_timestamp(void)
 
 static unsigned int diff(unsigned int t0, unsigned int t1)
 {
-#if defined(__alpha__)
-	return (t1 <= t0) ? t1 + (1UL << 32) - t0 : t1 - t0;
-#elif defined(__i386__) || defined(__x86_64__)
+#if defined(__alpha__) || defined(__x86_64__)
+	return (t1 - t0);
+#elif defined(__i386__)
 	/*
 	 * This is tricky: to work for both short and full ftape_timestamps
 	 * we'll have to discriminate between these.
@@ -122,9 +136,9 @@ static unsigned int diff(unsigned int t0, unsigned int t1)
 
 static unsigned int usecs(unsigned int count)
 {
-#if defined(__alpha__)
+#if defined(__alpha__) || defined(__x86_64__)
 	return (ps_per_cycle * count) / 1000000UL;
-#elif defined(__i386__) || defined(__x86_64__)
+#elif defined(__i386__)
 	return (10000 * count) / ((CLOCK_TICK_RATE + 50) / 100);
 #endif
 }
@@ -163,38 +177,13 @@ static void time_inb(void)
 
 static void init_clock(void)
 {
-#if defined(__i386__) || defined(__x86_64__)
-	unsigned int t;
-	int i;
 	TRACE_FUN(ft_t_any);
 
-	/*  Haven't studied on why, but there sometimes is a problem
-	 *  with the tick timer readout. The two bytes get swapped.
-	 *  This hack solves that problem by doing one extra input.
-	 */
-	for (i = 0; i < 1000; ++i) {
-		t = short_ftape_timestamp();
-		if (t > LATCH) {
-			inb_p(0x40);	/* get in sync again */
-			TRACE(ft_t_warn, "clock counter fixed");
-			break;
-		}
-	}
+#if defined(__x86_64__)
+	ps_per_cycle = 1000000000UL / cpu_khz;
 #elif defined(__alpha__)
-#if CONFIG_FT_ALPHA_CLOCK == 0
-#error You must define and set CONFIG_FT_ALPHA_CLOCK in 'make config' !
-#endif
 	extern struct hwrpb_struct *hwrpb;
-	TRACE_FUN(ft_t_any);
-
-	if (hwrpb->cycle_freq != 0) {
-		ps_per_cycle = (1000*1000*1000*1000UL) / hwrpb->cycle_freq;
-	} else {
-		/*
-		 * HELP:  Linux 2.0.x doesn't set cycle_freq on my noname !
-		 */
-		ps_per_cycle = (1000*1000*1000*1000UL) / CONFIG_FT_ALPHA_CLOCK;
-	}
+	ps_per_cycle = (1000*1000*1000*1000UL) / hwrpb->cycle_freq;
 #endif
 	TRACE_EXIT;
 }
@@ -213,7 +202,7 @@ void ftape_calibrate(char *name,
 	unsigned int tc = 0;
 	unsigned int count;
 	unsigned int time;
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__)
 	unsigned int old_tc = 0;
 	unsigned int old_count = 1;
 	unsigned int old_time = 1;
@@ -255,7 +244,7 @@ void ftape_calibrate(char *name,
 		tc = (1000 * time) / (count - 1);
 		TRACE(ft_t_any, "once:%3d us,%6d times:%6d us, TC:%5d ns",
 			usecs(once), count - 1, usecs(multiple), tc);
-#if defined(__alpha__)
+#if defined(__alpha__) || defined(__x86_64__)
 		/*
 		 * Increase the calibration count exponentially until the
 		 * calibration time exceeds 100 ms.
@@ -263,7 +252,7 @@ void ftape_calibrate(char *name,
 		if (time >= 100*1000) {
 			break;
 		}
-#elif defined(__i386__) || defined(__x86_64__)
+#elif defined(__i386__)
 		/*
 		 * increase the count until the resulting time nears 2/HZ,
 		 * then the tc will drop sharply because we lose LATCH counts.
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
index 1027eb7c6..45bc1be63 100644
--- a/drivers/char/generic_serial.c
+++ b/drivers/char/generic_serial.c
@@ -436,9 +436,7 @@ void gs_flush_buffer(struct tty_struct *tty)
 	restore_flags(flags);
 
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 	func_exit ();
 }
 
@@ -578,9 +576,7 @@ void gs_do_softint(void *private_)
 	if (!tty) return;
 
 	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
+		tty_wakeup(tty);
 		wake_up_interruptible(&tty->write_wait);
 	}
 	func_exit ();
@@ -694,7 +690,7 @@ void gs_close(struct tty_struct * tty, struct file * filp)
 {
 	unsigned long flags;
 	struct gs_port *port;
-
+	
 	func_enter ();
 
 	if (!tty) return;
@@ -760,8 +756,8 @@ void gs_close(struct tty_struct * tty, struct file * filp)
 
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+		
+	tty_ldisc_flush(tty);
 	tty->closing = 0;
 
 	port->event = 0;
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 5e8c47244..22d46cdac 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -60,8 +60,8 @@ static spinlock_t hpet_task_lock = SPIN_LOCK_UNLOCKED;
 
 struct hpet_dev {
 	struct hpets *hd_hpets;
-	struct hpet *hd_hpet;
-	struct hpet_timer *hd_timer;
+	struct hpet __iomem *hd_hpet;
+	struct hpet_timer __iomem *hd_timer;
 	unsigned long hd_ireqfreq;
 	unsigned long hd_irqdata;
 	wait_queue_head_t hd_waitqueue;
@@ -75,7 +75,7 @@ struct hpet_dev {
 
 struct hpets {
 	struct hpets *hp_next;
-	struct hpet *hp_hpet;
+	struct hpet __iomem *hp_hpet;
 	unsigned long hp_period;
 	unsigned long hp_delta;
 	unsigned int hp_ntimer;
@@ -98,14 +98,14 @@ static struct hpets *hpets;
 #endif
 
 #ifndef readq
-static unsigned long long __inline readq(void *addr)
+static unsigned long long __inline readq(void __iomem *addr)
 {
 	return readl(addr) | (((unsigned long long)readl(addr + 4)) << 32LL);
 }
 #endif
 
 #ifndef writeq
-static void __inline writeq(unsigned long long v, void *addr)
+static void __inline writeq(unsigned long long v, void __iomem *addr)
 {
 	writel(v & 0xffffffff, addr);
 	writel(v >> 32, addr + 4);
@@ -300,7 +300,7 @@ static int hpet_fasync(int fd, struct file *file, int on)
 static int hpet_release(struct inode *inode, struct file *file)
 {
 	struct hpet_dev *devp;
-	struct hpet_timer *timer;
+	struct hpet_timer __iomem *timer;
 	int irq = 0;
 
 	devp = file->private_data;
@@ -352,8 +352,8 @@ hpet_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
 static int hpet_ioctl_ieon(struct hpet_dev *devp)
 {
-	struct hpet_timer *timer;
-	struct hpet *hpet;
+	struct hpet_timer __iomem *timer;
+	struct hpet __iomem *hpet;
 	struct hpets *hpetp;
 	int irq;
 	unsigned long g, v, t, m;
@@ -435,8 +435,8 @@ static inline unsigned long hpet_time_div(unsigned long dis)
 static int
 hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
 {
-	struct hpet_timer *timer;
-	struct hpet *hpet;
+	struct hpet_timer __iomem *timer;
+	struct hpet __iomem *hpet;
 	struct hpets *hpetp;
 	int err;
 	unsigned long v;
@@ -547,7 +547,7 @@ int hpet_register(struct hpet_task *tp, int periodic)
 {
 	unsigned int i;
 	u64 mask;
-	struct hpet_timer *timer;
+	struct hpet_timer __iomem *timer;
 	struct hpet_dev *devp;
 	struct hpets *hpetp;
 
@@ -615,7 +615,7 @@ static inline int hpet_tpcheck(struct hpet_task *tp)
 int hpet_unregister(struct hpet_task *tp)
 {
 	struct hpet_dev *devp;
-	struct hpet_timer *timer;
+	struct hpet_timer __iomem *timer;
 	int err;
 
 	if ((err = hpet_tpcheck(tp)))
@@ -662,40 +662,9 @@ int hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg)
 
 #ifdef	CONFIG_TIME_INTERPOLATION
 
-static unsigned long hpet_offset, last_wall_hpet;
-static long hpet_nsecs_per_cycle, hpet_cycles_per_sec;
-
-static unsigned long hpet_getoffset(void)
-{
-	return hpet_offset + (read_counter(&hpets->hp_hpet->hpet_mc) -
-			      last_wall_hpet) * hpet_nsecs_per_cycle;
-}
-
-static void hpet_update(long delta)
-{
-	unsigned long mc;
-	unsigned long offset;
-
-	mc = read_counter(&hpets->hp_hpet->hpet_mc);
-	offset = hpet_offset + (mc - last_wall_hpet) * hpet_nsecs_per_cycle;
-
-	if (delta < 0 || (unsigned long)delta < offset)
-		hpet_offset = offset - delta;
-	else
-		hpet_offset = 0;
-	last_wall_hpet = mc;
-}
-
-static void hpet_reset(void)
-{
-	hpet_offset = 0;
-	last_wall_hpet = read_counter(&hpets->hp_hpet->hpet_mc);
-}
-
 static struct time_interpolator hpet_interpolator = {
-	.get_offset = hpet_getoffset,
-	.update = hpet_update,
-	.reset = hpet_reset
+	.source = TIME_SOURCE_MMIO64,
+	.shift = 10
 };
 
 #endif
@@ -745,11 +714,11 @@ static struct ctl_table_header *sysctl_header;
 
 static unsigned long __init hpet_calibrate(struct hpets *hpetp)
 {
-	struct hpet_timer *timer = NULL;
+	struct hpet_timer __iomem *timer = NULL;
 	unsigned long t, m, count, i, flags, start;
 	struct hpet_dev *devp;
 	int j;
-	struct hpet *hpet;
+	struct hpet __iomem *hpet;
 
 	for (j = 0, devp = hpetp->hp_dev; j < hpetp->hp_ntimer; j++, devp++)
 		if ((devp->hd_flags & HPET_OPEN) == 0) {
@@ -787,8 +756,9 @@ int __init hpet_alloc(struct hpet_data *hdp)
 	u32 i, ntimer;
 	struct hpets *hpetp;
 	size_t siz;
-	struct hpet *hpet;
+	struct hpet __iomem *hpet;
 	static struct hpets *last __initdata = (struct hpets *)0;
+	unsigned long ns;
 
 	/*
 	 * hpet_alloc can be called by platform dependent code.
@@ -796,7 +766,7 @@ int __init hpet_alloc(struct hpet_data *hdp)
 	 * ACPI also reports hpet, then we catch it here.
 	 */
 	for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
-		if (hpetp->hp_hpet == (struct hpet *)(hdp->hd_address))
+		if (hpetp->hp_hpet == hdp->hd_address)
 			return 0;
 
 	siz = sizeof(struct hpets) + ((hdp->hd_nirqs - 1) *
@@ -810,7 +780,7 @@ int __init hpet_alloc(struct hpet_data *hdp)
 	memset(hpetp, 0, siz);
 
 	hpetp->hp_which = hpet_nhpet++;
-	hpetp->hp_hpet = (struct hpet *)hdp->hd_address;
+	hpetp->hp_hpet = hdp->hd_address;
 
 	hpetp->hp_ntimer = hdp->hd_nirqs;
 
@@ -840,6 +810,18 @@ int __init hpet_alloc(struct hpet_data *hdp)
 	hpetp->hp_period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >>
 	    HPET_COUNTER_CLK_PERIOD_SHIFT;
 
+	printk(KERN_INFO "hpet%d: at MMIO 0x%p, IRQ%s",
+		hpetp->hp_which, hpet, hpetp->hp_ntimer > 1 ? "s" : "");
+	for (i = 0; i < hpetp->hp_ntimer; i++)
+		printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
+	printk("\n");
+
+	ns = hpetp->hp_period;	/* femptoseconds, 10^-15 */
+	do_div(ns, 1000000);	/* convert to nanoseconds, 10^-9 */
+	printk(KERN_INFO "hpet%d: %ldns tick, %d %d-bit timers\n",
+		hpetp->hp_which, ns, hpetp->hp_ntimer,
+		cap & HPET_COUNTER_SIZE_MASK ? 64 : 32);
+
 	mcfg = readq(&hpet->hpet_config);
 	if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) {
 		write_counter(0L, &hpet->hpet_mc);
@@ -850,7 +832,7 @@ int __init hpet_alloc(struct hpet_data *hdp)
 	for (i = 0, devp = hpetp->hp_dev; i < hpetp->hp_ntimer;
 	     i++, hpet_ntimer++, devp++) {
 		unsigned long v;
-		struct hpet_timer *timer;
+		struct hpet_timer __iomem *timer;
 
 		timer = &hpet->hpet_timers[devp - hpetp->hp_dev];
 		v = readq(&timer->hpet_config);
@@ -891,11 +873,10 @@ static acpi_status __init hpet_resources(struct acpi_resource *res, void *data)
 		unsigned long size;
 
 		size = addr.max_address_range - addr.min_address_range + 1;
-		hdp->hd_address =
-		    (unsigned long)ioremap(addr.min_address_range, size);
+		hdp->hd_address = ioremap(addr.min_address_range, size);
 
 		for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next)
-			if (hpetp->hp_hpet == (struct hpet *)(hdp->hd_address))
+			if (hpetp->hp_hpet == hdp->hd_address)
 				return -EBUSY;
 	} else if (res->id == ACPI_RSTYPE_EXT_IRQ) {
 		struct acpi_resource_ext_irq *irqp;
@@ -944,9 +925,8 @@ static int __init hpet_acpi_remove(struct acpi_device *device, int type)
 	return 0;
 }
 
-static struct acpi_driver hpet_acpi_driver __initdata = {
+static struct acpi_driver hpet_acpi_driver = {
 	.name = "hpet",
-	.class = "",
 	.ids = "PNP0103",
 	.ops = {
 		.add = hpet_acpi_add,
@@ -971,11 +951,10 @@ static int __init hpet_init(void)
 			struct hpet *hpet;
 
 			hpet = hpets->hp_hpet;
-			hpet_cycles_per_sec = hpet_time_div(hpets->hp_period);
-			hpet_interpolator.frequency = hpet_cycles_per_sec;
-			hpet_interpolator.drift = hpet_cycles_per_sec *
+			hpet_interpolator.addr = &hpets->hp_hpet->hpet_mc;
+			hpet_interpolator.frequency = hpet_time_div(hpets->hp_period);
+			hpet_interpolator.drift = hpet_interpolator.frequency *
 			    HPET_DRIFT / 1000000;
-			hpet_nsecs_per_cycle = 1000000000 / hpet_cycles_per_sec;
 			register_time_interpolator(&hpet_interpolator);
 		}
 #endif
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index d4bf205fd..3c0af2cad 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -1,6 +1,11 @@
 /*
  * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
  * Copyright (C) 2001 Paul Mackerras <paulus@au.ibm.com>, IBM
+ * Copyright (C) 2004 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Additional Author(s):
+ *  Ryan S. Arnold <rsa@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
@@ -17,38 +22,51 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
+#include <linux/console.h>
+#include <linux/cpumask.h>
 #include <linux/init.h>
+#include <linux/kbd_kern.h>
+#include <linux/kernel.h>
+#include <linux/kobject.h>
+#include <linux/kthread.h>
+#include <linux/list.h>
 #include <linux/module.h>
-#include <linux/console.h>
 #include <linux/major.h>
-#include <linux/kernel.h>
 #include <linux/sysrq.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/sched.h>
-#include <linux/kbd_kern.h>
-#include <asm/uaccess.h>
 #include <linux/spinlock.h>
-#include <linux/cpumask.h>
-
-extern int hvc_count(int *);
-extern int hvc_get_chars(int index, char *buf, int count);
-extern int hvc_put_chars(int index, const char *buf, int count);
+#include <asm/uaccess.h>
+#include <asm/hvconsole.h>
+#include <asm/vio.h>
 
 #define HVC_MAJOR	229
 #define HVC_MINOR	0
 
-#define MAX_NR_HVC_CONSOLES	4
-
 #define TIMEOUT		((HZ + 99) / 100)
 
+/*
+ * Wait this long per iteration while trying to push buffered data to the
+ * hypervisor before allowing the tty to complete a close operation.
+ */
+#define HVC_CLOSE_WAIT (HZ/100) /* 1/10 of a second */
+
+/*
+ * The Linux TTY code does not support dynamic addition of tty derived devices
+ * so we need to know how many tty devices we might need when space is allocated
+ * for the tty device.  Since this driver supports hotplug of vty adapters we
+ * need to make sure we have enough allocated.
+ */
+#define HVC_ALLOC_TTY_ADAPTERS	8
+
 static struct tty_driver *hvc_driver;
-static int hvc_offset;
 #ifdef CONFIG_MAGIC_SYSRQ
 static int sysrq_pressed;
 #endif
 
 #define N_OUTBUF	16
+#define N_INBUF		16
 
 #define __ALIGNED__	__attribute__((__aligned__(8)))
 
@@ -60,59 +78,249 @@ struct hvc_struct {
 	int do_wakeup;
 	char outbuf[N_OUTBUF] __ALIGNED__;
 	int n_outbuf;
+	uint32_t vtermno;
+	int irq_requested;
+	int irq;
+	struct list_head next;
+	struct kobject kobj; /* ref count & hvc_struct lifetime */
+	struct vio_dev *vdev;
 };
 
-struct hvc_struct hvc_struct[MAX_NR_HVC_CONSOLES];
+/* dynamic list of hvc_struct instances */
+static struct list_head hvc_structs = LIST_HEAD_INIT(hvc_structs);
+
+/*
+ * Protect the list of hvc_struct instances from inserts and removals during
+ * list traversal.
+ */
+static spinlock_t hvc_structs_lock = SPIN_LOCK_UNLOCKED;
+
+/*
+ * Initial console vtermnos for console API usage prior to full console
+ * initialization.  Any vty adapter outside this range will not have usable
+ * console interfaces but can still be used as a tty device.  This has to be
+ * static because kmalloc will not work during early console init.
+ */
+static uint32_t vtermnos[MAX_NR_HVC_CONSOLES];
+
+/* Used for accounting purposes */
+static int num_vterms = 0;
+
+static struct task_struct *hvc_task;
+
+/*
+ * This value is used to associate a tty->index value to a hvc_struct based
+ * upon order of exposure via hvc_probe().
+ */
+static int hvc_count = -1;
+
+/* Picks up late kicks after list walk but before schedule() */
+static int hvc_kicked;
+
+/* Wake the sleeping khvcd */
+static void hvc_kick(void)
+{
+	hvc_kicked = 1;
+	wake_up_process(hvc_task);
+}
+
+/*
+ * NOTE: This API isn't used if the console adapter doesn't support interrupts.
+ * In this case the console is poll driven.
+ */
+static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+{
+	hvc_kick();
+	return IRQ_HANDLED;
+}
+
+static void hvc_unthrottle(struct tty_struct *tty)
+{
+	hvc_kick();
+}
+
+/*
+ * Do not call this function with either the hvc_strucst_lock or the hvc_struct
+ * lock held.  If successful, this function increments the kobject reference
+ * count against the target hvc_struct so it should be released when finished.
+ */
+struct hvc_struct *hvc_get_by_index(int index)
+{
+	struct hvc_struct *hp;
+	unsigned long flags;
+
+	spin_lock(&hvc_structs_lock);
 
+	list_for_each_entry(hp, &hvc_structs, next) {
+		spin_lock_irqsave(&hp->lock, flags);
+		if (hp->index == index) {
+			kobject_get(&hp->kobj);
+			spin_unlock_irqrestore(&hp->lock, flags);
+			spin_unlock(&hvc_structs_lock);
+			return hp;
+		}
+		spin_unlock_irqrestore(&hp->lock, flags);
+	}
+	hp = NULL;
+
+	spin_unlock(&hvc_structs_lock);
+	return hp;
+}
+
+/*
+ * The TTY interface won't be used until after the vio layer has exposed the vty
+ * adapter to the kernel.
+ */
 static int hvc_open(struct tty_struct *tty, struct file * filp)
 {
-	int line = tty->index;
 	struct hvc_struct *hp;
 	unsigned long flags;
+	int irq = NO_IRQ;
+	int rc = 0;
+	struct kobject *kobjp;
 
-	if (line < 0 || line >= MAX_NR_HVC_CONSOLES)
+	/* Auto increments kobject reference if found. */
+	if (!(hp = hvc_get_by_index(tty->index))) {
+		printk(KERN_WARNING "hvc_console: tty open failed, no vty associated with tty.\n");
 		return -ENODEV;
-	hp = &hvc_struct[line];
+	}
 
-	tty->driver_data = hp;
 	spin_lock_irqsave(&hp->lock, flags);
+	/* Check and then increment for fast path open. */
+	if (hp->count++ > 0) {
+		spin_unlock_irqrestore(&hp->lock, flags);
+		hvc_kick();
+		return 0;
+	} /* else count == 0 */
+
+	tty->driver_data = hp;
 	hp->tty = tty;
-	hp->count++;
+	/* Save for request_irq outside of spin_lock. */
+	irq = hp->irq;
+	if (irq != NO_IRQ)
+		hp->irq_requested = 1;
+
+	kobjp = &hp->kobj;
+
 	spin_unlock_irqrestore(&hp->lock, flags);
+	/* check error, fallback to non-irq */
+	if (irq != NO_IRQ)
+		rc = request_irq(irq, hvc_handle_interrupt, SA_INTERRUPT, "hvc_console", hp);
+
+	/*
+	 * If the request_irq() fails and we return an error.  The tty layer
+	 * will call hvc_close() after a failed open but we don't want to clean
+	 * up there so we'll clean up here and clear out the previously set
+	 * tty fields and return the kobject reference.
+	 */
+	if (rc) {
+		spin_lock_irqsave(&hp->lock, flags);
+		hp->tty = NULL;
+		hp->irq_requested = 0;
+		spin_unlock_irqrestore(&hp->lock, flags);
+		tty->driver_data = NULL;
+		kobject_put(kobjp);
+	}
+	/* Force wakeup of the polling thread */
+	hvc_kick();
 
-	return 0;
+	return rc;
 }
 
 static void hvc_close(struct tty_struct *tty, struct file * filp)
 {
-	struct hvc_struct *hp = tty->driver_data;
+	struct hvc_struct *hp;
+	struct kobject *kobjp;
+	int irq = NO_IRQ;
 	unsigned long flags;
 
 	if (tty_hung_up_p(filp))
 		return;
+
+	/*
+	 * No driver_data means that this close was issued after a failed
+	 * hvcs_open by the tty layer's release_dev() function and we can just
+	 * exit cleanly because the kobject reference wasn't made.
+	 */
+	if (!tty->driver_data)
+		return;
+
+	hp = tty->driver_data;
 	spin_lock_irqsave(&hp->lock, flags);
-	if (--hp->count == 0)
+
+	kobjp = &hp->kobj;
+	if (--hp->count == 0) {
+		if (hp->irq_requested)
+			irq = hp->irq;
+		hp->irq_requested = 0;
+
+		/* We are done with the tty pointer now. */
 		hp->tty = NULL;
-	else if (hp->count < 0)
-		printk(KERN_ERR "hvc_close %lu: oops, count is %d\n",
-		       hp - hvc_struct, hp->count);
-	spin_unlock_irqrestore(&hp->lock, flags);
+		spin_unlock_irqrestore(&hp->lock, flags);
+
+		/*
+		 * Chain calls chars_in_buffer() and returns immediately if
+		 * there is no buffered data otherwise sleeps on a wait queue
+		 * waking periodically to check chars_in_buffer().
+		 */
+		tty_wait_until_sent(tty, HVC_CLOSE_WAIT);
+
+		/*
+		 * Since the line disc doesn't block writes during tty close
+		 * operations we'll set driver_data to NULL and then make sure
+		 * to check tty->driver_data for NULL in hvc_write().
+		 */
+		tty->driver_data = NULL;
+
+		if (irq != NO_IRQ)
+			free_irq(irq, hp);
+
+	} else {
+		if (hp->count < 0)
+			printk(KERN_ERR "hvc_close %X: oops, count is %d\n",
+				hp->vtermno, hp->count);
+		spin_unlock_irqrestore(&hp->lock, flags);
+	}
+
+	kobject_put(kobjp);
 }
 
 static void hvc_hangup(struct tty_struct *tty)
 {
 	struct hvc_struct *hp = tty->driver_data;
+	unsigned long flags;
+	int irq = NO_IRQ;
+	int temp_open_count;
+	struct kobject *kobjp;
 
+	spin_lock_irqsave(&hp->lock, flags);
+	kobjp = &hp->kobj;
+	temp_open_count = hp->count;
 	hp->count = 0;
+	hp->n_outbuf = 0;
 	hp->tty = NULL;
+	if (hp->irq_requested)
+		/* Saved for use outside of spin_lock. */
+		irq = hp->irq;
+	hp->irq_requested = 0;
+	spin_unlock_irqrestore(&hp->lock, flags);
+	if (irq != NO_IRQ)
+		free_irq(irq, hp);
+	while(temp_open_count) {
+		--temp_open_count;
+		kobject_put(kobjp);
+	}
 }
 
-/* called with hp->lock held */
+/*
+ * Push buffered characters whether they were just recently buffered or waiting
+ * on a blocked hypervisor.  Call this function with hp->lock held.
+ */
 static void hvc_push(struct hvc_struct *hp)
 {
 	int n;
 
-	n = hvc_put_chars(hp->index + hvc_offset, hp->outbuf, hp->n_outbuf);
+	n = hvc_put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf);
 	if (n <= 0) {
 		if (n == 0)
 			return;
@@ -127,77 +335,126 @@ static void hvc_push(struct hvc_struct *hp)
 		hp->do_wakeup = 1;
 }
 
-static int hvc_write(struct tty_struct *tty, int from_user,
-		     const unsigned char *buf, int count)
+static inline int __hvc_write_user(struct hvc_struct *hp,
+				   const unsigned char *buf, int count)
 {
-	struct hvc_struct *hp = tty->driver_data;
 	char *tbuf, *p;
 	int tbsize, rsize, written = 0;
 	unsigned long flags;
 
-	if (from_user) {
-		tbsize = min(count, (int)PAGE_SIZE);
-		if (!(tbuf = kmalloc(tbsize, GFP_KERNEL)))
-			return -ENOMEM;
-
-		while ((rsize = count - written) > 0) {
-			int wsize;
-			if (rsize > tbsize)
-				rsize = tbsize;
-
-			p = tbuf;
-			rsize -= copy_from_user(p, buf, rsize);
-			if (!rsize) {
-				if (written == 0)
-					written = -EFAULT;
-				break;
-			}
-			buf += rsize;
-			written += rsize;
-
-			spin_lock_irqsave(&hp->lock, flags);
-			for (wsize = N_OUTBUF - hp->n_outbuf; rsize && wsize;
-					wsize = N_OUTBUF - hp->n_outbuf) {
-				if (wsize > rsize)
-					wsize = rsize;
-				memcpy(hp->outbuf + hp->n_outbuf, p, wsize);
-				hp->n_outbuf += wsize;
-				hvc_push(hp);
-				rsize -= wsize;
-				p += wsize;
-			}
-			spin_unlock_irqrestore(&hp->lock, flags);
-
-			if (rsize)
-				break;
+	tbsize = min(count, (int)PAGE_SIZE);
+	if (!(tbuf = kmalloc(tbsize, GFP_KERNEL)))
+		return -ENOMEM;
 
-			if (count < tbsize)
-				tbsize = count;
+	while ((rsize = count - written) > 0) {
+		int wsize;
+		if (rsize > tbsize)
+			rsize = tbsize;
+
+		p = tbuf;
+		rsize -= copy_from_user(p, buf, rsize);
+		if (!rsize) {
+			if (written == 0)
+				written = -EFAULT;
+			break;
 		}
+		buf += rsize;
 
-		kfree(tbuf);
-	} else {
 		spin_lock_irqsave(&hp->lock, flags);
-		while (count > 0 && (rsize = N_OUTBUF - hp->n_outbuf) > 0) {
-			if (rsize > count)
-				rsize = count;
-			memcpy(hp->outbuf + hp->n_outbuf, buf, rsize);
-			count -= rsize;
-			buf += rsize;
-			hp->n_outbuf += rsize;
-			written += rsize;
+
+		/* Push pending writes: make some room in buffer */
+		if (hp->n_outbuf > 0)
 			hvc_push(hp);
+
+		for (wsize = N_OUTBUF - hp->n_outbuf; rsize && wsize;
+		     wsize = N_OUTBUF - hp->n_outbuf) {
+			if (wsize > rsize)
+				wsize = rsize;
+			memcpy(hp->outbuf + hp->n_outbuf, p, wsize);
+			hp->n_outbuf += wsize;
+			hvc_push(hp);
+			rsize -= wsize;
+			p += wsize;
+			written += wsize;
 		}
 		spin_unlock_irqrestore(&hp->lock, flags);
+
+		if (rsize)
+			break;
+
+		if (count < tbsize)
+			tbsize = count;
+	}
+
+	kfree(tbuf);
+
+	return written;
+}
+
+static inline int __hvc_write_kernel(struct hvc_struct *hp,
+				   const unsigned char *buf, int count)
+{
+	unsigned long flags;
+	int rsize, written = 0;
+
+	spin_lock_irqsave(&hp->lock, flags);
+
+	/* Push pending writes */
+	if (hp->n_outbuf > 0)
+		hvc_push(hp);
+
+	while (count > 0 && (rsize = N_OUTBUF - hp->n_outbuf) > 0) {
+		if (rsize > count)
+			rsize = count;
+		memcpy(hp->outbuf + hp->n_outbuf, buf, rsize);
+		count -= rsize;
+		buf += rsize;
+		hp->n_outbuf += rsize;
+		written += rsize;
+		hvc_push(hp);
 	}
+	spin_unlock_irqrestore(&hp->lock, flags);
+
+	return written;
+}
+static int hvc_write(struct tty_struct *tty, int from_user,
+		     const unsigned char *buf, int count)
+{
+	struct hvc_struct *hp = tty->driver_data;
+	int written;
+
+	/* This write was probably executed during a tty close. */
+	if (!hp)
+		return -EPIPE;
+
+	if (from_user)
+		written = __hvc_write_user(hp, buf, count);
+	else
+		written = __hvc_write_kernel(hp, buf, count);
+
+	/*
+	 * Racy, but harmless, kick thread if there is still pending data.
+	 * There really is nothing wrong with kicking the thread, even if there
+	 * is no buffered data.
+	 */
+	if (hp->n_outbuf)
+		hvc_kick();
 
 	return written;
 }
 
+/*
+ * This is actually a contract between the driver and the tty layer outlining
+ * how much write room the driver can guarentee will be sent OR BUFFERED.  This
+ * driver MUST honor the return value.
+ */
 static int hvc_write_room(struct tty_struct *tty)
 {
 	struct hvc_struct *hp = tty->driver_data;
 
+	if (!hp)
+		return -1;
+
 	return N_OUTBUF - hp->n_outbuf;
 }
 
@@ -205,57 +462,108 @@ static int hvc_chars_in_buffer(struct tty_struct *tty)
 {
 	struct hvc_struct *hp = tty->driver_data;
 
+	if (!hp)
+		return -1;
 	return hp->n_outbuf;
 }
 
-static void hvc_poll(int index)
+#define HVC_POLL_READ	0x00000001
+#define HVC_POLL_WRITE	0x00000002
+#define HVC_POLL_QUICK	0x00000004
+
+static int hvc_poll(struct hvc_struct *hp)
 {
-	struct hvc_struct *hp = &hvc_struct[index];
 	struct tty_struct *tty;
-	int i, n;
-	char buf[16] __ALIGNED__;
+	int i, n, poll_mask = 0;
+	char buf[N_INBUF] __ALIGNED__;
 	unsigned long flags;
+	int read_total = 0;
 
 	spin_lock_irqsave(&hp->lock, flags);
 
+	/* Push pending writes */
 	if (hp->n_outbuf > 0)
 		hvc_push(hp);
+	/* Reschedule us if still some write pending */
+	if (hp->n_outbuf > 0)
+		poll_mask |= HVC_POLL_WRITE;
 
+	/* No tty attached, just skip */
 	tty = hp->tty;
-	if (tty) {
-		for (;;) {
-			if (TTY_FLIPBUF_SIZE - tty->flip.count < sizeof(buf))
-				break;
-			n = hvc_get_chars(index + hvc_offset, buf, sizeof(buf));
-			if (n <= 0)
-				break;
-			for (i = 0; i < n; ++i) {
-#ifdef CONFIG_MAGIC_SYSRQ		/* Handle the SysRq Hack */
-				if (buf[i] == '\x0f') {	/* ^O -- should support a sequence */
-					sysrq_pressed = 1;
-					continue;
-				} else if (sysrq_pressed) {
-					handle_sysrq(buf[i], NULL, tty);
-					sysrq_pressed = 0;
-					continue;
-				}
-#endif
-				tty_insert_flip_char(tty, buf[i], 0);
+	if (tty == NULL)
+		goto bail;
+
+	/* Now check if we can get data (are we throttled ?) */
+	if (test_bit(TTY_THROTTLED, &tty->flags))
+		goto throttled;
+
+	/* If we aren't interrupt driven and aren't throttled, we always
+	 * request a reschedule
+	 */
+	if (hp->irq == NO_IRQ)
+		poll_mask |= HVC_POLL_READ;
+
+	/* Read data if any */
+	for (;;) {
+		int count = N_INBUF;
+		if (count > (TTY_FLIPBUF_SIZE - tty->flip.count))
+			count = TTY_FLIPBUF_SIZE - tty->flip.count;
+
+		/* If flip is full, just reschedule a later read */
+		if (count == 0) {
+			poll_mask |= HVC_POLL_READ;
+			break;
+		}
+
+		n = hvc_get_chars(hp->vtermno, buf, count);
+		if (n <= 0) {
+			/* Hangup the tty when disconnected from host */
+			if (n == -EPIPE) {
+				spin_unlock_irqrestore(&hp->lock, flags);
+				tty_hangup(tty);
+				spin_lock_irqsave(&hp->lock, flags);
 			}
+			break;
 		}
+		for (i = 0; i < n; ++i) {
+#ifdef CONFIG_MAGIC_SYSRQ
+			/* Handle the SysRq Hack */
+			if (buf[i] == '\x0f') {	/* ^O -- should support a sequence */
+				sysrq_pressed = 1;
+				continue;
+			} else if (sysrq_pressed) {
+				handle_sysrq(buf[i], NULL, tty);
+				sysrq_pressed = 0;
+				continue;
+			}
+#endif /* CONFIG_MAGIC_SYSRQ */
+			tty_insert_flip_char(tty, buf[i], 0);
+		}
+
 		if (tty->flip.count)
 			tty_schedule_flip(tty);
 
-		if (hp->do_wakeup) {
-			hp->do_wakeup = 0;
-			if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
-			    && tty->ldisc.write_wakeup)
-				(tty->ldisc.write_wakeup)(tty);
-			wake_up_interruptible(&tty->write_wait);
+		/*
+		 * Account for the total amount read in one loop, and if above
+		 * 64 bytes, we do a quick schedule loop to let the tty grok the
+		 * data and eventually throttle us.
+		 */
+		read_total += n;
+		if (read_total >= 64) {
+			poll_mask |= HVC_POLL_QUICK;
+			break;
 		}
 	}
-
+ throttled:
+	/* Wakeup write queue if necessary */
+	if (hp->do_wakeup) {
+		hp->do_wakeup = 0;
+		tty_wakeup(tty);
+	}
+ bail:
 	spin_unlock_irqrestore(&hp->lock, flags);
+
+	return poll_mask;
 }
 
 #if defined(CONFIG_XMON) && defined(CONFIG_SMP)
@@ -264,21 +572,47 @@ extern cpumask_t cpus_in_xmon;
 static const cpumask_t cpus_in_xmon = CPU_MASK_NONE;
 #endif
 
-
+/*
+ * This kthread is either polling or interrupt driven.  This is determined by
+ * calling hvc_poll() who determines whether a console adapter support
+ * interrupts.
+ */
 int khvcd(void *unused)
 {
-	int i;
-
-	daemonize("khvcd");
+	int poll_mask;
+	struct hvc_struct *hp;
 
-	for (;;) {
+	__set_current_state(TASK_RUNNING);
+	do {
+		poll_mask = 0;
+		hvc_kicked = 0;
+		wmb();
 		if (cpus_empty(cpus_in_xmon)) {
-			for (i = 0; i < MAX_NR_HVC_CONSOLES; ++i)
-				hvc_poll(i);
+			spin_lock(&hvc_structs_lock);
+			list_for_each_entry(hp, &hvc_structs, next) {
+				/*hp = list_entry(node, struct hvc_struct, * next); */
+				poll_mask |= hvc_poll(hp);
+			}
+			spin_unlock(&hvc_structs_lock);
+		} else
+			poll_mask |= HVC_POLL_READ;
+		if (hvc_kicked)
+			continue;
+		if (poll_mask & HVC_POLL_QUICK) {
+			yield();
+			continue;
 		}
 		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(TIMEOUT);
-	}
+		if (!hvc_kicked) {
+			if (poll_mask == 0)
+				schedule();
+			else
+				schedule_timeout(TIMEOUT);
+		}
+		__set_current_state(TASK_RUNNING);
+	} while (!kthread_should_stop());
+
+	return 0;
 }
 
 static struct tty_operations hvc_ops = {
@@ -286,19 +620,124 @@ static struct tty_operations hvc_ops = {
 	.close = hvc_close,
 	.write = hvc_write,
 	.hangup = hvc_hangup,
+	.unthrottle = hvc_unthrottle,
 	.write_room = hvc_write_room,
 	.chars_in_buffer = hvc_chars_in_buffer,
 };
 
-int __init hvc_init(void)
+char hvc_driver_name[] = "hvc_console";
+
+static struct vio_device_id hvc_driver_table[] __devinitdata= {
+	{"serial", "hvterm1"},
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(vio, hvc_driver_table);
+
+/* callback when the kboject ref count reaches zero. */
+static void destroy_hvc_struct(struct kobject *kobj)
 {
-	int num = hvc_count(&hvc_offset);
-	int i;
+	struct hvc_struct *hp = container_of(kobj, struct hvc_struct, kobj);
+	unsigned long flags;
 
-	if (num > MAX_NR_HVC_CONSOLES)
-		num = MAX_NR_HVC_CONSOLES;
+	spin_lock(&hvc_structs_lock);
 
-	hvc_driver = alloc_tty_driver(num);
+	spin_lock_irqsave(&hp->lock, flags);
+	list_del(&(hp->next));
+	spin_unlock_irqrestore(&hp->lock, flags);
+
+	spin_unlock(&hvc_structs_lock);
+
+	kfree(hp);
+}
+
+static struct kobj_type hvc_kobj_type = {
+	.release = destroy_hvc_struct,
+};
+
+static int __devinit hvc_probe(
+		struct vio_dev *dev,
+		const struct vio_device_id *id)
+{
+	struct hvc_struct *hp;
+
+	/* probed with invalid parameters. */
+	if (!dev || !id)
+		return -EPERM;
+
+	hp = kmalloc(sizeof(*hp), GFP_KERNEL);
+	if (!hp)
+		return -ENOMEM;
+
+	memset(hp, 0x00, sizeof(*hp));
+	hp->vtermno = dev->unit_address;
+	hp->vdev = dev;
+	hp->vdev->dev.driver_data = hp;
+	hp->irq = dev->irq;
+
+	kobject_init(&hp->kobj);
+	hp->kobj.ktype = &hvc_kobj_type;
+
+	hp->lock = SPIN_LOCK_UNLOCKED;
+	spin_lock(&hvc_structs_lock);
+	hp->index = ++hvc_count;
+	list_add_tail(&(hp->next), &hvc_structs);
+	spin_unlock(&hvc_structs_lock);
+
+	return 0;
+}
+
+static int __devexit hvc_remove(struct vio_dev *dev)
+{
+	struct hvc_struct *hp = dev->dev.driver_data;
+	unsigned long flags;
+	struct kobject *kobjp;
+	struct tty_struct *tty;
+
+	spin_lock_irqsave(&hp->lock, flags);
+	tty = hp->tty;
+	kobjp = &hp->kobj;
+
+	if (hp->index < MAX_NR_HVC_CONSOLES)
+		vtermnos[hp->index] = -1;
+
+	/* Don't whack hp->irq because tty_hangup() will need to free the irq. */
+
+	spin_unlock_irqrestore(&hp->lock, flags);
+
+	/*
+	 * We 'put' the instance that was grabbed when the kobject instance
+	 * was intialized using kobject_init().  Let the last holder of this
+	 * kobject cause it to be removed, which will probably be the tty_hangup
+	 * below.
+	 */
+	kobject_put(kobjp);
+
+	/*
+	 * This function call will auto chain call hvc_hangup.  The tty should
+	 * always be valid at this time unless a simultaneous tty close already
+	 * cleaned up the hvc_struct.
+	 */
+	if (tty)
+		tty_hangup(tty);
+	return 0;
+}
+
+static struct vio_driver hvc_vio_driver = {
+	.name		= hvc_driver_name,
+	.id_table	= hvc_driver_table,
+	.probe		= hvc_probe,
+	.remove		= hvc_remove,
+};
+
+/* Driver initialization.  Follow console initialization.  This is where the TTY
+ * interfaces start to become available. */
+int __init hvc_init(void)
+{
+	int rc;
+
+	/* We need more than num_vterms adapters due to hotplug additions. */
+	hvc_driver = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS);
+	/* hvc_driver = alloc_tty_driver(num_vterms); */
 	if (!hvc_driver)
 		return -ENOMEM;
 
@@ -312,31 +751,73 @@ int __init hvc_init(void)
 	hvc_driver->init_termios = tty_std_termios;
 	hvc_driver->flags = TTY_DRIVER_REAL_RAW;
 	tty_set_operations(hvc_driver, &hvc_ops);
-	for (i = 0; i < num; i++) {
-		hvc_struct[i].lock = SPIN_LOCK_UNLOCKED;
-		hvc_struct[i].index = i;
-	}
 
 	if (tty_register_driver(hvc_driver))
 		panic("Couldn't register hvc console driver\n");
 
-	if (num > 0)
-		kernel_thread(khvcd, NULL, CLONE_KERNEL);
+	/* Always start the kthread because there can be hotplug vty adapters
+	 * added later. */
+	hvc_task = kthread_run(khvcd, NULL, "khvcd");
+	if (IS_ERR(hvc_task)) {
+		panic("Couldn't create kthread for console.\n");
+		put_tty_driver(hvc_driver);
+		return -EIO;
+	}
+
+	/* Register as a vio device to receive callbacks */
+	rc = vio_register_driver(&hvc_vio_driver);
 
-	return 0;
+	return rc;
 }
 
+/* This isn't particularily necessary due to this being a console driver but it
+ * is nice to be thorough */
 static void __exit hvc_exit(void)
 {
+	kthread_stop(hvc_task);
+
+	vio_unregister_driver(&hvc_vio_driver);
+	tty_unregister_driver(hvc_driver);
+	/* return tty_struct instances allocated in hvc_init(). */
+	put_tty_driver(hvc_driver);
+}
+
+/*
+ * Console APIs, NOT TTY.  These APIs are available immediately when
+ * hvc_console_setup() finds adapters.
+ */
+
+/*
+ * hvc_instantiate() is an early console discovery method which locates consoles
+ * prior to the vio subsystem discovering them.  Hotplugged vty adapters do NOT
+ * get an hvc_instantiate() callback since the appear after early console init.
+ */
+int hvc_instantiate(uint32_t vtermno, int index)
+{
+	if (index < 0 || index >= MAX_NR_HVC_CONSOLES)
+		return -1;
+
+	if (vtermnos[index] != -1)
+		return -1;
+
+	vtermnos[index] = vtermno;
+	return 0;
 }
 
 void hvc_console_print(struct console *co, const char *b, unsigned count)
 {
 	char c[16] __ALIGNED__;
-	unsigned i, n;
+	unsigned i = 0, n = 0;
 	int r, donecr = 0;
 
-	i = n = 0;
+	/* Console access attempt outside of acceptable console range. */
+	if (co->index >= MAX_NR_HVC_CONSOLES)
+		return;
+
+	/* This console adapter was removed so it is not useable. */
+	if (vtermnos[co->index] < 0)
+		return;
+
 	while (count > 0 || i > 0) {
 		if (count > 0 && i < sizeof(c)) {
 			if (b[n] == '\n' && !donecr) {
@@ -348,7 +829,7 @@ void hvc_console_print(struct console *co, const char *b, unsigned count)
 				--count;
 			}
 		} else {
-			r = hvc_put_chars(co->index + hvc_offset, c, i);
+			r = hvc_put_chars(vtermnos[co->index], c, i);
 			if (r < 0) {
 				/* throw away chars on error */
 				i = 0;
@@ -369,9 +850,6 @@ static struct tty_driver *hvc_console_device(struct console *c, int *index)
 
 static int __init hvc_console_setup(struct console *co, char *options)
 {
-	if (co->index < 0 || co->index >= MAX_NR_HVC_CONSOLES
-	    || co->index >= hvc_count(&hvc_offset))
-		return -1;
 	return 0;
 }
 
@@ -384,8 +862,14 @@ struct console hvc_con_driver = {
 	.index		= -1,
 };
 
+/* Early console initialization.  Preceeds driver initialization. */
 static int __init hvc_console_init(void)
 {
+	int i;
+
+	for (i=0; i<MAX_NR_HVC_CONSOLES; i++)
+		vtermnos[i] = -1;
+	num_vterms = hvc_find_vtys();
 	register_console(&hvc_con_driver);
 	return 0;
 }
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
index 96ca634ca..15b1d8cbc 100644
--- a/drivers/char/hvcs.c
+++ b/drivers/char/hvcs.c
@@ -88,37 +88,59 @@
 #include <asm/vio.h>
 
 /*
- * 1.0.0 -> 1.1.0 Added kernel_thread scheduling methodology to driver to
- * replace wait_task constructs.
+ * 1.3.0 -> 1.3.1 In hvcs_open memset(..,0x00,..) instead of memset(..,0x3F,00).
+ * Removed braces around single statements following conditionals.  Removed '=
+ * 0' after static int declarations since these default to zero.  Removed
+ * list_for_each_safe() and replaced with list_for_each_entry() in
+ * hvcs_get_by_index().  The 'safe' version is un-needed now that the driver is
+ * using spinlocks.  Changed spin_lock_irqsave() to spin_lock() when locking
+ * hvcs_structs_lock and hvcs_pi_lock since these are not touched in an int
+ * handler.  Initialized hvcs_structs_lock and hvcs_pi_lock to
+ * SPIN_LOCK_UNLOCKED at declaration time rather than in hvcs_module_init().
+ * Added spin_lock around list_del() in destroy_hvcs_struct() to protect the
+ * list traversals from a deletion.  Removed '= NULL' from pointer declaration
+ * statements since they are initialized NULL by default.  Removed wmb()
+ * instances from hvcs_try_write().  They probably aren't needed with locking in
+ * place.  Added check and cleanup for hvcs_pi_buff = kmalloc() in
+ * hvcs_module_init().  Exposed hvcs_struct.index via a sysfs attribute so that
+ * the coupling between /dev/hvcs* and a vty-server can be automatically
+ * determined.  Moved kobject_put() in hvcs_open outside of the
+ * spin_unlock_irqrestore().
  *
- * 1.1.0 -> 1.2.0 Moved pi_buff initialization out of arch code into driver code
- * and added locking to share this buffer between hvcs_struct instances.  This
- * is because the page_size kmalloc can't be done with a spin_lock held.
+ * 1.3.1 -> 1.3.2 Changed method for determining hvcs_struct->index and had it
+ * align with how the tty layer always assigns the lowest index available.  This
+ * change resulted in a list of ints that denotes which indexes are available.
+ * Device additions and removals use the new hvcs_get_index() and
+ * hvcs_return_index() helper functions.  The list is created with
+ * hvsc_alloc_index_list() and it is destroyed with hvcs_free_index_list().
+ * Without these fixes hotplug vty-server adapter support goes crazy with this
+ * driver if the user removes a vty-server adapter.  Moved free_irq() outside of
+ * the hvcs_final_close() function in order to get it out of the spinlock.
+ * Rearranged hvcs_close().  Cleaned up some printks and did some housekeeping
+ * on the changelog.  Removed local CLC_LENGTH and used HVCS_CLC_LENGTH from
+ * arch/ppc64/hvcserver.h.
  *
- * Also added sysfs attribute to manually disconnect the vty-server from the vty
- * due to stupid firmware behavior when opening the connection then sending data
- * then then quickly closing the connection would cause data loss on the
- * receiving side.  This required some reordering of the termination code.
- *
- * Fixed the hangup scenario and fixed memory leaks on module_exit.
- *
- * 1.2.0 -> 1.3.0 Moved from manual kernel thread creation & execution to
- * kthread construct which replaced in-kernel IPC for thread termination with
- * kthread_stop and kthread_should_stop.  Explicit wait_queue handling was
- * removed because kthread handles this.  Minor bug fix to postpone partner_info
- * clearing on hvcs_close until adapter removal to preserve context data for
- * printk on partner connection free.  Added lock to protect hvcs_structs so
- * that hvcs_struct instances aren't added or removed during list traversal.
- * Cleaned up comment style, added spaces after commas, and broke function
- * declaration lines to be under 80 columns.
+ * 1.3.2 -> 1.3.3 Replaced yield() in hvcs_close() with tty_wait_until_sent() to
+ * prevent possible lockup with realtime scheduling as similarily pointed out by
+ * akpm in hvc_console.  Changed resulted in the removal of hvcs_final_close()
+ * to reorder cleanup operations and prevent discarding of pending data during
+ * an hvcs_close().  Removed spinlock protection of hvcs_struct data members in
+ * hvcs_write_room() and hvcs_chars_in_buffer() because they aren't needed.
  */
-#define HVCS_DRIVER_VERSION "1.3.0"
+
+#define HVCS_DRIVER_VERSION "1.3.3"
 
 MODULE_AUTHOR("Ryan S. Arnold <rsa@us.ibm.com>");
 MODULE_DESCRIPTION("IBM hvcs (Hypervisor Virtual Console Server) Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(HVCS_DRIVER_VERSION);
 
+/*
+ * Wait this long per iteration while trying to push buffered data to the
+ * hypervisor before allowing the tty to complete a close operation.
+ */
+#define HVCS_CLOSE_WAIT (HZ/100) /* 1/10 of a second */
+
 /*
  * Since the Linux TTY code does not currently (2-04-2004) support dynamic
  * addition of tty derived devices and we shouldn't allocate thousands of
@@ -138,9 +160,9 @@ MODULE_VERSION(HVCS_DRIVER_VERSION);
 
 /*
  * We let Linux assign us a major number and we start the minors at zero.  There
- * is no intuitive mapping between minor number and the target partition.  The
- * mapping of minor number is related to the order the vty-servers are exposed
- * to this driver via the hvcs_probe function.
+ * is no intuitive mapping between minor number and the target vty-server
+ * adapter except that each new vty-server adapter is always assigned to the
+ * smallest minor number available.
  */
 #define HVCS_MINOR_START	0
 
@@ -152,9 +174,6 @@ MODULE_VERSION(HVCS_DRIVER_VERSION);
  */
 #define __ALIGNED__	__attribute__((__aligned__(8)))
 
-/* Converged location code string length + 1 null terminator */
-#define CLC_LENGTH		80
-
 /*
  * How much data can firmware send with each hvc_put_chars()?  Maybe this
  * should be moved into an architecture specific area.
@@ -194,27 +213,41 @@ char hvcs_driver_string[]
 	= "IBM hvcs (Hypervisor Virtual Console Server) Driver";
 
 /* Status of partner info rescan triggered via sysfs. */
-static int hvcs_rescan_status = 0;
+static int hvcs_rescan_status;
 
 static struct tty_driver *hvcs_tty_driver;
 
 /*
- * This is used to associate a vty-server, as it is exposed to this driver, with
- * a preallocated tty_struct.index.  The dev node and hvcs index numbers are not
- * re-used after device removal otherwise removing and adding a new one would
- * link a /dev/hvcs* entry to a different vty-server than it did before the
- * removal.  Incidentally, a newly exposed vty-server will always map to an
- * incrementally higher /dev/hvcs* entry than the last exposed vty-server.
+ * In order to be somewhat sane this driver always associates the hvcs_struct
+ * index element with the numerically equal tty->index.  This means that a
+ * hotplugged vty-server adapter will always map to the lowest index valued
+ * device node.  If vty-servers were hotplug removed from the system and then
+ * new ones added the new vty-server may have the largest slot number of all
+ * the vty-server adapters in the partition but it may have the lowest dev node
+ * index of all the adapters due to the hole left by the hotplug removed
+ * adapter.  There are a set of functions provided to get the lowest index for
+ * a new device as well as return the index to the list.  This list is allocated
+ * with a number of elements equal to the number of device nodes requested when
+ * the module was inserted.
+ */
+static int *hvcs_index_list;
+
+/*
+ * How large is the list?  This is kept for traversal since the list is
+ * dynamically created.
  */
-static int hvcs_struct_count = -1;
+static int hvcs_index_count;
 
 /*
  * Used by the khvcsd to pick up I/O operations when the kernel_thread is
  * already awake but potentially shifted to TASK_INTERRUPTIBLE state.
  */
-static int hvcs_kicked = 0;
+static int hvcs_kicked;
 
-/* Used the the kthread construct for task operations */
+/*
+ * Use by the kthread construct for task operations like waking the sleeping
+ * thread and stopping the kthread.
+ */
 static struct task_struct *hvcs_task;
 
 /*
@@ -223,7 +256,8 @@ static struct task_struct *hvcs_task;
  */
 static unsigned long *hvcs_pi_buff;
 
-static spinlock_t hvcs_pi_lock;
+/* Only allow one hvcs_struct to use the hvcs_pi_buff at a time. */
+static spinlock_t hvcs_pi_lock = SPIN_LOCK_UNLOCKED;
 
 /* One vty-server per hvcs_struct */
 struct hvcs_struct {
@@ -263,9 +297,9 @@ struct hvcs_struct {
 	 */
 	struct kobject kobj; /* ref count & hvcs_struct lifetime */
 	int connected; /* is the vty-server currently connected to a vty? */
-	unsigned int p_unit_address; /* partner unit address */
-	unsigned int p_partition_ID; /* partner partition ID */
-	char p_location_code[CLC_LENGTH];
+	uint32_t p_unit_address; /* partner unit address */
+	uint32_t p_partition_ID; /* partner partition ID */
+	char p_location_code[HVCS_CLC_LENGTH + 1]; /* CLC + Null Term */
 	struct list_head next; /* list management */
 	struct vio_dev *vdev;
 };
@@ -274,7 +308,7 @@ struct hvcs_struct {
 #define from_kobj(kobj) container_of(kobj, struct hvcs_struct, kobj)
 
 static struct list_head hvcs_structs = LIST_HEAD_INIT(hvcs_structs);
-static spinlock_t hvcs_structs_lock;
+static spinlock_t hvcs_structs_lock = SPIN_LOCK_UNLOCKED;
 
 static void hvcs_unthrottle(struct tty_struct *tty);
 static void hvcs_throttle(struct tty_struct *tty);
@@ -297,7 +331,6 @@ static void hvcs_partner_free(struct hvcs_struct *hvcsd);
 
 static int hvcs_enable_device(struct hvcs_struct *hvcsd,
 		uint32_t unit_address, unsigned int irq, struct vio_dev *dev);
-static void hvcs_final_close(struct hvcs_struct *hvcsd);
 
 static void destroy_hvcs_struct(struct kobject *kobj);
 static int hvcs_open(struct tty_struct *tty, struct file *filp);
@@ -357,12 +390,11 @@ static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance,
 		struct pt_regs *regs)
 {
 	struct hvcs_struct *hvcsd = dev_instance;
-	unsigned long flags;
 
-	spin_lock_irqsave(&hvcsd->lock, flags);
+	spin_lock(&hvcsd->lock);
 	vio_disable_interrupts(hvcsd->vdev);
 	hvcsd->todo_mask |= HVCS_SCHED_READ;
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
+	spin_unlock(&hvcsd->lock);
 	hvcs_kick();
 
 	return IRQ_HANDLED;
@@ -371,7 +403,7 @@ static irqreturn_t hvcs_handle_interrupt(int irq, void *dev_instance,
 /* This function must be called with the hvcsd->lock held */
 static void hvcs_try_write(struct hvcs_struct *hvcsd)
 {
-	unsigned int unit_address = hvcsd->vdev->unit_address;
+	uint32_t unit_address = hvcsd->vdev->unit_address;
 	struct tty_struct *tty = hvcsd->tty;
 	int sent;
 
@@ -382,9 +414,9 @@ static void hvcs_try_write(struct hvcs_struct *hvcsd)
 				hvcsd->chars_in_buffer );
 		if (sent > 0) {
 			hvcsd->chars_in_buffer = 0;
-			wmb();
+			/* wmb(); */
 			hvcsd->todo_mask &= ~(HVCS_TRY_WRITE);
-			wmb();
+			/* wmb(); */
 
 			/*
 			 * We are still obligated to deliver the data to the
@@ -393,10 +425,7 @@ static void hvcs_try_write(struct hvcs_struct *hvcsd)
 			 * a non-existent tty.
 			 */
 			if (tty) {
-				if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
-						&& tty->ldisc.write_wakeup)
-					(tty->ldisc.write_wakeup) (tty);
-				wake_up_interruptible(&tty->write_wait);
+				tty_wakeup(tty);
 			}
 		}
 	}
@@ -404,11 +433,11 @@ static void hvcs_try_write(struct hvcs_struct *hvcsd)
 
 static int hvcs_io(struct hvcs_struct *hvcsd)
 {
-	unsigned int unit_address;
+	uint32_t unit_address;
 	struct tty_struct *tty;
 	char buf[HVCS_BUFF_LEN] __ALIGNED__;
 	unsigned long flags;
-	int got;
+	int got = 0;
 	int i;
 
 	spin_lock_irqsave(&hvcsd->lock, flags);
@@ -461,11 +490,8 @@ static int hvcs_io(struct hvcs_struct *hvcsd)
 
 static int khvcsd(void *unused)
 {
-	struct hvcs_struct *hvcsd = NULL;
-	struct list_head *element;
-	struct list_head *safe_temp;
+	struct hvcs_struct *hvcsd;
 	int hvcs_todo_mask;
-	unsigned long structs_flags;
 
 	__set_current_state(TASK_RUNNING);
 
@@ -474,12 +500,11 @@ static int khvcsd(void *unused)
 		hvcs_kicked = 0;
 		wmb();
 
-		spin_lock_irqsave(&hvcs_structs_lock, structs_flags);
-		list_for_each_safe(element, safe_temp, &hvcs_structs) {
-			hvcsd = list_entry(element, struct hvcs_struct, next);
-				hvcs_todo_mask |= hvcs_io(hvcsd);
+		spin_lock(&hvcs_structs_lock);
+		list_for_each_entry(hvcsd, &hvcs_structs, next) {
+			hvcs_todo_mask |= hvcs_io(hvcsd);
 		}
-		spin_unlock_irqrestore(&hvcs_structs_lock, structs_flags);
+		spin_unlock(&hvcs_structs_lock);
 
 		/*
 		 * If any of the hvcs adapters want to try a write or quick read
@@ -506,6 +531,19 @@ static struct vio_device_id hvcs_driver_table[] __devinitdata= {
 };
 MODULE_DEVICE_TABLE(vio, hvcs_driver_table);
 
+static void hvcs_return_index(int index)
+{
+	/* Paranoia check */
+	if (!hvcs_index_list)
+		return;
+	if (index < 0 || index >= hvcs_index_count)
+		return;
+	if (hvcs_index_list[index] == -1)
+		return;
+	else
+		hvcs_index_list[index] = -1;
+}
+
 /* callback when the kboject ref count reaches zero */
 static void destroy_hvcs_struct(struct kobject *kobj)
 {
@@ -513,6 +551,7 @@ static void destroy_hvcs_struct(struct kobject *kobj)
 	struct vio_dev *vdev;
 	unsigned long flags;
 
+	spin_lock(&hvcs_structs_lock);
 	spin_lock_irqsave(&hvcsd->lock, flags);
 
 	/* the list_del poisons the pointers */
@@ -524,7 +563,7 @@ static void destroy_hvcs_struct(struct kobject *kobj)
 				" partner vty@%X:%d connection.\n",
 				hvcsd->vdev->unit_address,
 				hvcsd->p_unit_address,
-				(unsigned int)hvcsd->p_partition_ID);
+				(uint32_t)hvcsd->p_partition_ID);
 	}
 	printk(KERN_INFO "HVCS: Destroyed hvcs_struct for vty-server@%X.\n",
 			hvcsd->vdev->unit_address);
@@ -534,55 +573,60 @@ static void destroy_hvcs_struct(struct kobject *kobj)
 
 	hvcsd->p_unit_address = 0;
 	hvcsd->p_partition_ID = 0;
-	memset(&hvcsd->p_location_code[0], 0x00, CLC_LENGTH);
+	hvcs_return_index(hvcsd->index);
+	memset(&hvcsd->p_location_code[0], 0x00, HVCS_CLC_LENGTH + 1);
 
 	spin_unlock_irqrestore(&hvcsd->lock, flags);
+	spin_unlock(&hvcs_structs_lock);
 
 	hvcs_remove_device_attrs(vdev);
 
 	kfree(hvcsd);
 }
 
-/* This function must be called with hvcsd->lock held. */
-static void hvcs_final_close(struct hvcs_struct *hvcsd)
-{
-	vio_disable_interrupts(hvcsd->vdev);
-	free_irq(hvcsd->vdev->irq, hvcsd);
-
-	hvcsd->todo_mask = 0;
-
-	/* These two may be redundant if the operation was a close. */
-	if (hvcsd->tty) {
-		hvcsd->tty->driver_data = NULL;
-		hvcsd->tty = NULL;
-	}
-
-	hvcsd->open_count = 0;
-
-	memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN);
-	hvcsd->chars_in_buffer = 0;
-}
-
 static struct kobj_type hvcs_kobj_type = {
 	.release = destroy_hvcs_struct,
 };
 
+static int hvcs_get_index(void)
+{
+	int i;
+	/* Paranoia check */
+	if (!hvcs_index_list) {
+		printk(KERN_ERR "HVCS: hvcs_index_list NOT valid!.\n");
+		return -EFAULT;
+	}
+	/* Find the numerically lowest first free index. */
+	for(i = 0; i < hvcs_index_count; i++) {
+		if (hvcs_index_list[i] == -1) {
+			hvcs_index_list[i] = 0;
+			return i;
+		}
+	}
+	return -1;
+}
+
 static int __devinit hvcs_probe(
 	struct vio_dev *dev,
 	const struct vio_device_id *id)
 {
 	struct hvcs_struct *hvcsd;
-	unsigned long structs_flags;
+	int index;
 
 	if (!dev || !id) {
 		printk(KERN_ERR "HVCS: probed with invalid parameter.\n");
 		return -EPERM;
 	}
 
+	/* early to avoid cleanup on failure */
+	index = hvcs_get_index();
+	if (index < 0) {
+		return -EFAULT;
+	}
+
 	hvcsd = kmalloc(sizeof(*hvcsd), GFP_KERNEL);
-	if (!hvcsd) {
+	if (!hvcsd)
 		return -ENODEV;
-	}
 
 	/* hvcsd->tty is zeroed out with the memset */
 	memset(hvcsd, 0x00, sizeof(*hvcsd));
@@ -596,7 +640,9 @@ static int __devinit hvcs_probe(
 	hvcsd->vdev = dev;
 	dev->dev.driver_data = hvcsd;
 
-	hvcsd->index = ++hvcs_struct_count;
+	hvcsd->index = index;
+
+	/* hvcsd->index = ++hvcs_struct_count; */
 	hvcsd->chars_in_buffer = 0;
 	hvcsd->todo_mask = 0;
 	hvcsd->connected = 0;
@@ -617,15 +663,15 @@ static int __devinit hvcs_probe(
 	 * will get -ENODEV.
 	 */
 
-	spin_lock_irqsave(&hvcs_structs_lock, structs_flags);
+	spin_lock(&hvcs_structs_lock);
 
 	list_add_tail(&(hvcsd->next), &hvcs_structs);
 
-	spin_unlock_irqrestore(&hvcs_structs_lock, structs_flags);
+	spin_unlock(&hvcs_structs_lock);
 
 	hvcs_create_device_attrs(hvcsd);
 
-	printk(KERN_INFO "HVCS: Added vty-server@%X.\n", dev->unit_address);
+	printk(KERN_INFO "HVCS: vty-server@%X added to the vio bus.\n", dev->unit_address);
 
 	/*
 	 * DON'T enable interrupts here because there is no user to receive the
@@ -688,8 +734,8 @@ static void hvcs_set_pi(struct hvcs_partner_info *pi, struct hvcs_struct *hvcsd)
 	hvcsd->p_unit_address = pi->unit_address;
 	hvcsd->p_partition_ID  = pi->partition_ID;
 	clclength = strlen(&pi->location_code[0]);
-	if (clclength > CLC_LENGTH - 1)
-		clclength = CLC_LENGTH - 1;
+	if (clclength > HVCS_CLC_LENGTH)
+		clclength = HVCS_CLC_LENGTH;
 
 	/* copy the null-term char too */
 	strncpy(&hvcsd->p_location_code[0],
@@ -711,20 +757,18 @@ static void hvcs_set_pi(struct hvcs_partner_info *pi, struct hvcs_struct *hvcsd)
  */
 static int hvcs_get_pi(struct hvcs_struct *hvcsd)
 {
-	/* struct hvcs_partner_info *head_pi = NULL; */
-	struct hvcs_partner_info *pi = NULL;
-	unsigned int unit_address = hvcsd->vdev->unit_address;
+	struct hvcs_partner_info *pi;
+	uint32_t unit_address = hvcsd->vdev->unit_address;
 	struct list_head head;
-	unsigned long flags;
 	int retval;
 
-	spin_lock_irqsave(&hvcs_pi_lock, flags);
+	spin_lock(&hvcs_pi_lock);
 	if (!hvcs_pi_buff) {
-		spin_unlock_irqrestore(&hvcs_pi_lock, flags);
+		spin_unlock(&hvcs_pi_lock);
 		return -EFAULT;
 	}
 	retval = hvcs_get_partner_info(unit_address, &head, hvcs_pi_buff);
-	spin_unlock_irqrestore(&hvcs_pi_lock, flags);
+	spin_unlock(&hvcs_pi_lock);
 	if (retval) {
 		printk(KERN_ERR "HVCS: Failed to fetch partner"
 			" info for vty-server@%x.\n", unit_address);
@@ -748,11 +792,10 @@ static int hvcs_get_pi(struct hvcs_struct *hvcsd)
  */
 static int hvcs_rescan_devices_list(void)
 {
-	struct hvcs_struct *hvcsd = NULL;
+	struct hvcs_struct *hvcsd;
 	unsigned long flags;
-	unsigned long structs_flags;
 
-	spin_lock_irqsave(&hvcs_structs_lock, structs_flags);
+	spin_lock(&hvcs_structs_lock);
 
 	list_for_each_entry(hvcsd, &hvcs_structs, next) {
 		spin_lock_irqsave(&hvcsd->lock, flags);
@@ -760,7 +803,7 @@ static int hvcs_rescan_devices_list(void)
 		spin_unlock_irqrestore(&hvcsd->lock, flags);
 	}
 
-	spin_unlock_irqrestore(&hvcs_structs_lock, structs_flags);
+	spin_unlock(&hvcs_structs_lock);
 
 	return 0;
 }
@@ -848,13 +891,14 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address,
 		unsigned int irq, struct vio_dev *vdev)
 {
 	unsigned long flags;
+	int rc;
 
 	/*
 	 * It is possible that the vty-server was removed between the time that
 	 * the conn was registered and now.
 	 */
-	if (!request_irq(irq, &hvcs_handle_interrupt,
-				SA_INTERRUPT, "ibmhvcs", hvcsd)) {
+	if (!(rc = request_irq(irq, &hvcs_handle_interrupt,
+				SA_INTERRUPT, "ibmhvcs", hvcsd))) {
 		/*
 		 * It is possible the vty-server was removed after the irq was
 		 * requested but before we have time to enable interrupts.
@@ -874,7 +918,7 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address,
 	hvcs_partner_free(hvcsd);
 	spin_unlock_irqrestore(&hvcsd->lock, flags);
 
-	return -ENODEV;
+	return rc;
 
 }
 
@@ -888,22 +932,17 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address,
 struct hvcs_struct *hvcs_get_by_index(int index)
 {
 	struct hvcs_struct *hvcsd = NULL;
-	struct list_head *element;
-	struct list_head *safe_temp;
 	unsigned long flags;
-	unsigned long structs_flags;
 
-	spin_lock_irqsave(&hvcs_structs_lock, structs_flags);
+	spin_lock(&hvcs_structs_lock);
 	/* We can immediately discard OOB requests */
 	if (index >= 0 && index < HVCS_MAX_SERVER_ADAPTERS) {
-		list_for_each_safe(element, safe_temp, &hvcs_structs) {
-			hvcsd = list_entry(element, struct hvcs_struct, next);
+		list_for_each_entry(hvcsd, &hvcs_structs, next) {
 			spin_lock_irqsave(&hvcsd->lock, flags);
 			if (hvcsd->index == index) {
 				kobject_get(&hvcsd->kobj);
 				spin_unlock_irqrestore(&hvcsd->lock, flags);
-				spin_unlock_irqrestore(&hvcs_structs_lock,
-						structs_flags);
+				spin_unlock(&hvcs_structs_lock);
 				return hvcsd;
 			}
 			spin_unlock_irqrestore(&hvcsd->lock, flags);
@@ -911,7 +950,7 @@ struct hvcs_struct *hvcs_get_by_index(int index)
 		hvcsd = NULL;
 	}
 
-	spin_unlock_irqrestore(&hvcs_structs_lock, structs_flags);
+	spin_unlock(&hvcs_structs_lock);
 	return hvcsd;
 }
 
@@ -921,12 +960,13 @@ struct hvcs_struct *hvcs_get_by_index(int index)
  */
 static int hvcs_open(struct tty_struct *tty, struct file *filp)
 {
-	struct hvcs_struct *hvcsd = NULL;
-	int retval = 0;
+	struct hvcs_struct *hvcsd;
+	int rc, retval = 0;
 	unsigned long flags;
 	unsigned int irq;
 	struct vio_dev *vdev;
 	unsigned long unit_address;
+	struct kobject *kobjp;
 
 	if (tty->driver_data)
 		goto fast_open;
@@ -936,7 +976,8 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
 	 * This function increments the kobject index.
 	 */
 	if (!(hvcsd = hvcs_get_by_index(tty->index))) {
-		printk(KERN_WARNING "HVCS: open failed, no index.\n");
+		printk(KERN_WARNING "HVCS: open failed, no device associated"
+				" with tty->index %d.\n", tty->index);
 		return -ENODEV;
 	}
 
@@ -959,7 +1000,7 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
 	 */
 	tty->low_latency = 1;
 
-	memset(&hvcsd->buffer[0], 0x3F, HVCS_BUFF_LEN);
+	memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN);
 
 	/*
 	 * Save these in the spinlock for the enable operations that need them
@@ -974,12 +1015,12 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
 
 	/*
 	 * This must be done outside of the spinlock because it requests irqs
-	 * and will grab the spinlcok and free the connection if it fails.
+	 * and will grab the spinlock and free the connection if it fails.
 	 */
-	if ((hvcs_enable_device(hvcsd, unit_address, irq, vdev))) {
+	if (((rc = hvcs_enable_device(hvcsd, unit_address, irq, vdev)))) {
 		kobject_put(&hvcsd->kobj);
 		printk(KERN_WARNING "HVCS: enable device failed.\n");
-		return -ENODEV;
+		return rc;
 	}
 
 	goto open_success;
@@ -1002,16 +1043,17 @@ fast_open:
 open_success:
 	hvcs_kick();
 
-	printk(KERN_INFO "HVCS: vty-server@%X opened.\n",
+	printk(KERN_INFO "HVCS: vty-server@%X connection opened.\n",
 		hvcsd->vdev->unit_address );
 
 	return 0;
 
 error_release:
+	kobjp = &hvcsd->kobj;
 	spin_unlock_irqrestore(&hvcsd->lock, flags);
 	kobject_put(&hvcsd->kobj);
 
-	printk(KERN_WARNING "HVCS: HVCS partner connect failed.\n");
+	printk(KERN_WARNING "HVCS: partner connect failed.\n");
 	return retval;
 }
 
@@ -1020,6 +1062,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
 	struct hvcs_struct *hvcsd;
 	unsigned long flags;
 	struct kobject *kobjp;
+	int irq = NO_IRQ;
 
 	/*
 	 * Is someone trying to close the file associated with this device after
@@ -1039,14 +1082,10 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
 	hvcsd = tty->driver_data;
 
 	spin_lock_irqsave(&hvcsd->lock, flags);
+	kobjp = &hvcsd->kobj;
 	if (--hvcsd->open_count == 0) {
 
-		/*
-		 * This line is important because it tells hvcs_open that this
-		 * device needs to be re-configured the next time hvcs_open is
-		 * called.
-		 */
-		hvcsd->tty->driver_data = NULL;
+		vio_disable_interrupts(hvcsd->vdev);
 
 		/*
 		 * NULL this early so that the kernel_thread doesn't try to
@@ -1055,34 +1094,28 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
 		 */
 		hvcsd->tty = NULL;
 
-		/*
-		 * Block the close until all the buffered data has been
-		 * delivered.
-		 */
-		while(hvcsd->chars_in_buffer) {
-			spin_unlock_irqrestore(&hvcsd->lock, flags);
+		irq = hvcsd->vdev->irq;
+		spin_unlock_irqrestore(&hvcsd->lock, flags);
 
-			/*
-			 * Give the kernel thread the hvcs_struct so that it can
-			 * try to deliver the remaining data but block the close
-			 * operation by spinning in this function so that other
-			 * tty operations have to wait.
-			 */
-			yield();
-			spin_lock_irqsave(&hvcsd->lock, flags);
-		}
+		tty_wait_until_sent(tty, HVCS_CLOSE_WAIT);
 
-		hvcs_final_close(hvcsd);
+		/*
+		 * This line is important because it tells hvcs_open that this
+		 * device needs to be re-configured the next time hvcs_open is
+		 * called.
+		 */
+		tty->driver_data = NULL;
 
+		free_irq(irq, hvcsd);
+		kobject_put(kobjp);
+		return;
 	} else if (hvcsd->open_count < 0) {
 		printk(KERN_ERR "HVCS: vty-server@%X open_count: %d"
 				" is missmanaged.\n",
-			hvcsd->vdev->unit_address, hvcsd->open_count);
+		hvcsd->vdev->unit_address, hvcsd->open_count);
 	}
-	kobjp = &hvcsd->kobj;
 
 	spin_unlock_irqrestore(&hvcsd->lock, flags);
-
 	kobject_put(kobjp);
 }
 
@@ -1092,6 +1125,7 @@ static void hvcs_hangup(struct tty_struct * tty)
 	unsigned long flags;
 	int temp_open_count;
 	struct kobject *kobjp;
+	int irq = NO_IRQ;
 
 	spin_lock_irqsave(&hvcsd->lock, flags);
 	/* Preserve this so that we know how many kobject refs to put */
@@ -1101,15 +1135,31 @@ static void hvcs_hangup(struct tty_struct * tty)
 	 * Don't kobject put inside the spinlock because the destruction
 	 * callback may use the spinlock and it may get called before the
 	 * spinlock has been released.  Get a pointer to the kobject and
-	 * kobject_put on that instead.
+	 * kobject_put on that after releasing the spinlock.
 	 */
 	kobjp = &hvcsd->kobj;
 
-	/* Calling this will drop any buffered data on the floor. */
-	hvcs_final_close(hvcsd);
+	vio_disable_interrupts(hvcsd->vdev);
+
+	hvcsd->todo_mask = 0;
+
+	/* I don't think the tty needs the hvcs_struct pointer after a hangup */
+	hvcsd->tty->driver_data = NULL;
+	hvcsd->tty = NULL;
+
+	hvcsd->open_count = 0;
+
+	/* This will drop any buffered data on the floor which is OK in a hangup
+	 * scenario. */
+	memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN);
+	hvcsd->chars_in_buffer = 0;
+
+	irq = hvcsd->vdev->irq;
 
 	spin_unlock_irqrestore(&hvcsd->lock, flags);
 
+	free_irq(irq, hvcsd);
+
 	/*
 	 * We need to kobject_put() for every open_count we have since the
 	 * tty_hangup() function doesn't invoke a close per open connection on a
@@ -1259,28 +1309,18 @@ static int hvcs_write(struct tty_struct *tty, int from_user,
 static int hvcs_write_room(struct tty_struct *tty)
 {
 	struct hvcs_struct *hvcsd = tty->driver_data;
-	unsigned long flags;
-	int retval;
 
 	if (!hvcsd || hvcsd->open_count <= 0)
 		return 0;
 
-	spin_lock_irqsave(&hvcsd->lock, flags);
-	retval = HVCS_BUFF_LEN - hvcsd->chars_in_buffer;
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-	return retval;
+	return HVCS_BUFF_LEN - hvcsd->chars_in_buffer;
 }
 
 static int hvcs_chars_in_buffer(struct tty_struct *tty)
 {
 	struct hvcs_struct *hvcsd = tty->driver_data;
-	unsigned long flags;
-	int retval;
 
-	spin_lock_irqsave(&hvcsd->lock, flags);
-	retval = hvcsd->chars_in_buffer;
-	spin_unlock_irqrestore(&hvcsd->lock, flags);
-	return retval;
+	return hvcsd->chars_in_buffer;
 }
 
 static struct tty_operations hvcs_ops = {
@@ -1294,6 +1334,28 @@ static struct tty_operations hvcs_ops = {
 	.throttle = hvcs_throttle,
 };
 
+static int hvcs_alloc_index_list(int n)
+{
+	int i;
+	hvcs_index_list = kmalloc(n * sizeof(hvcs_index_count),GFP_KERNEL);
+	if (!hvcs_index_list)
+		return -ENOMEM;
+	hvcs_index_count = n;
+	for(i = 0; i < hvcs_index_count; i++)
+		hvcs_index_list[i] = -1;
+	return 0;
+}
+
+static void hvcs_free_index_list(void)
+{
+	/* Paranoia check to be thorough. */
+	if (hvcs_index_list) {
+		kfree(hvcs_index_list);
+		hvcs_index_list = NULL;
+		hvcs_index_count = 0;
+	}
+}
+
 static int __init hvcs_module_init(void)
 {
 	int rc;
@@ -1312,6 +1374,9 @@ static int __init hvcs_module_init(void)
 	if (!hvcs_tty_driver)
 		return -ENOMEM;
 
+	if (hvcs_alloc_index_list(num_ttys_to_alloc))
+		return -ENOMEM;
+
 	hvcs_tty_driver->owner = THIS_MODULE;
 
 	hvcs_tty_driver->driver_name = hvcs_driver_name;
@@ -1342,19 +1407,25 @@ static int __init hvcs_module_init(void)
 	if (tty_register_driver(hvcs_tty_driver)) {
 		printk(KERN_ERR "HVCS: registration "
 			" as a tty driver failed.\n");
+		hvcs_free_index_list();
 		put_tty_driver(hvcs_tty_driver);
-		return rc;
+		return -EIO;
 	}
 
-	hvcs_structs_lock = SPIN_LOCK_UNLOCKED;
-
-	hvcs_pi_lock = SPIN_LOCK_UNLOCKED;
 	hvcs_pi_buff = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!hvcs_pi_buff) {
+		tty_unregister_driver(hvcs_tty_driver);
+		hvcs_free_index_list();
+		put_tty_driver(hvcs_tty_driver);
+		return -ENOMEM;
+	}
 
 	hvcs_task = kthread_run(khvcsd, NULL, "khvcsd");
 	if (IS_ERR(hvcs_task)) {
-		printk("khvcsd creation failed.  Driver not loaded.\n");
+		printk(KERN_ERR "HVCS: khvcsd creation failed.  Driver not loaded.\n");
 		kfree(hvcs_pi_buff);
+		tty_unregister_driver(hvcs_tty_driver);
+		hvcs_free_index_list();
 		put_tty_driver(hvcs_tty_driver);
 		return -EIO;
 	}
@@ -1374,8 +1445,6 @@ static int __init hvcs_module_init(void)
 
 static void __exit hvcs_module_exit(void)
 {
-	unsigned long flags;
-
 	/*
 	 * This driver receives hvcs_remove callbacks for each device upon
 	 * module removal.
@@ -1387,10 +1456,10 @@ static void __exit hvcs_module_exit(void)
 	 */
 	kthread_stop(hvcs_task);
 
-	spin_lock_irqsave(&hvcs_pi_lock, flags);
+	spin_lock(&hvcs_pi_lock);
 	kfree(hvcs_pi_buff);
 	hvcs_pi_buff = NULL;
-	spin_unlock_irqrestore(&hvcs_pi_lock, flags);
+	spin_unlock(&hvcs_pi_lock);
 
 	hvcs_remove_driver_attrs();
 
@@ -1398,6 +1467,8 @@ static void __exit hvcs_module_exit(void)
 
 	tty_unregister_driver(hvcs_tty_driver);
 
+	hvcs_free_index_list();
+
 	put_tty_driver(hvcs_tty_driver);
 
 	printk(KERN_INFO "HVCS: driver module removed.\n");
@@ -1499,7 +1570,7 @@ static ssize_t hvcs_vterm_state_store(struct device *dev, const char *buf,
 			" partner vty@%X:%d connection.\n",
 			hvcsd->vdev->unit_address,
 			hvcsd->p_unit_address,
-			(unsigned int)hvcsd->p_partition_ID);
+			(uint32_t)hvcsd->p_partition_ID);
 
 	spin_unlock_irqrestore(&hvcsd->lock, flags);
 	return count;
@@ -1520,11 +1591,27 @@ static ssize_t hvcs_vterm_state_show(struct device *dev, char *buf)
 static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR,
 		hvcs_vterm_state_show, hvcs_vterm_state_store);
 
+static ssize_t hvcs_index_show(struct device *dev, char *buf)
+{
+	struct vio_dev *viod = to_vio_dev(dev);
+	struct hvcs_struct *hvcsd = from_vio_dev(viod);
+	unsigned long flags;
+	int retval;
+
+	spin_lock_irqsave(&hvcsd->lock, flags);
+	retval = sprintf(buf, "%d\n", hvcsd->index);
+	spin_unlock_irqrestore(&hvcsd->lock, flags);
+	return retval;
+}
+
+static DEVICE_ATTR(index, S_IRUGO, hvcs_index_show, NULL);
+
 static struct attribute *hvcs_attrs[] = {
 	&dev_attr_partner_vtys.attr,
 	&dev_attr_partner_clcs.attr,
 	&dev_attr_current_vty.attr,
 	&dev_attr_vterm_state.attr,
+	&dev_attr_index.attr,
 	NULL,
 };
 
diff --git a/drivers/char/ip2/ip2types.h b/drivers/char/ip2/ip2types.h
index 8d2b37999..9d67b260b 100644
--- a/drivers/char/ip2/ip2types.h
+++ b/drivers/char/ip2/ip2types.h
@@ -49,6 +49,9 @@ typedef struct
 	short irq[IP2_MAX_BOARDS]; 
 	unsigned short addr[IP2_MAX_BOARDS];
 	int type[IP2_MAX_BOARDS];
+#ifdef CONFIG_PCI
+	struct pci_dev *pci_dev[IP2_MAX_BOARDS];
+#endif
 } ip2config_t;
 
 #endif
diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c
index ac97e617a..fa3ca6eb5 100644
--- a/drivers/char/ip2main.c
+++ b/drivers/char/ip2main.c
@@ -440,6 +440,12 @@ cleanup_module(void)
 	// free memory
 	for (i = 0; i < IP2_MAX_BOARDS; i++) {
 		void *pB;
+#ifdef CONFIG_PCI
+		if (ip2config.type[i] == PCI && ip2config.pci_dev[i]) {
+			pci_disable_device(ip2config.pci_dev[i]);
+			ip2config.pci_dev[i] = NULL;
+		}
+#endif
 		if ((pB = i2BoardPtrTable[i]) != 0 ) {
 			kfree ( pB );
 			i2BoardPtrTable[i] = NULL;
@@ -594,9 +600,14 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
 							  PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i);
 				if (pci_dev_i != NULL) {
 					unsigned int addr;
-					unsigned char pci_irq;
 
+					if (pci_enable_device(pci_dev_i)) {
+						printk( KERN_ERR "IP2: can't enable PCI device at %s\n",
+							pci_name(pci_dev_i));
+						break;
+					}
 					ip2config.type[i] = PCI;
+					ip2config.pci_dev[i] = pci_dev_i;
 					status =
 					pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr);
 					if ( addr & 1 ) {
@@ -604,8 +615,6 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
 					} else {
 						printk( KERN_ERR "IP2: PCI I/O address error\n");
 					}
-					status =
-					pci_read_config_byte(pci_dev_i, PCI_INTERRUPT_LINE, &pci_irq);
 
 //		If the PCI BIOS assigned it, lets try and use it.  If we
 //		can't acquire it or it screws up, deal with it then.
@@ -614,7 +623,7 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
 //						printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq);
 //						pci_irq = 0;
 //					}
-					ip2config.irq[i] = pci_irq;
+					ip2config.irq[i] = pci_dev_i->irq;
 				} else {	// ann error
 					ip2config.addr[i] = 0;
 					if (status == PCIBIOS_DEVICE_NOT_FOUND) {
diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig
index b632538ff..655a17219 100644
--- a/drivers/char/ipmi/Kconfig
+++ b/drivers/char/ipmi/Kconfig
@@ -57,4 +57,11 @@ config IPMI_WATCHDOG
        help
          This enables the IPMI watchdog timer.
 
+config IPMI_POWEROFF
+       tristate 'IPMI Poweroff'
+       depends on IPMI_HANDLER
+       help
+         This enables a function to power off the system with IPMI if
+	 the IPMI management controller is capable of this.
+
 endmenu
diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile
index b7d823072..553f0a408 100644
--- a/drivers/char/ipmi/Makefile
+++ b/drivers/char/ipmi/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o
 obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o
 obj-$(CONFIG_IPMI_SI) += ipmi_si.o
 obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o
+obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o
 
 ipmi_si.o:	$(ipmi_si-objs)
 	$(LD) -r -o $@ $(ipmi_si-objs)
diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c
index 7295bc559..225b33011 100644
--- a/drivers/char/ipmi/ipmi_bt_sm.c
+++ b/drivers/char/ipmi/ipmi_bt_sm.c
@@ -31,7 +31,7 @@
 #include <linux/ipmi_msgdefs.h>		/* for completion codes */
 #include "ipmi_si_sm.h"
 
-#define IPMI_BT_VERSION "v32"
+#define IPMI_BT_VERSION "v33"
 
 static int bt_debug = 0x00;	/* Production value 0, see following flags */
 
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index 8d1a08bcc..49d67f538 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -45,7 +45,7 @@
 #include <asm/semaphore.h>
 #include <linux/init.h>
 
-#define IPMI_DEVINTF_VERSION "v32"
+#define IPMI_DEVINTF_VERSION "v33"
 
 struct ipmi_file_private
 {
diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c
index d155f9a58..48cce2432 100644
--- a/drivers/char/ipmi/ipmi_kcs_sm.c
+++ b/drivers/char/ipmi/ipmi_kcs_sm.c
@@ -42,7 +42,7 @@
 #include <linux/ipmi_msgdefs.h>		/* for completion codes */
 #include "ipmi_si_sm.h"
 
-#define IPMI_KCS_VERSION "v32"
+#define IPMI_KCS_VERSION "v33"
 
 /* Set this if you want a printout of why the state machine was hosed
    when it gets hosed. */
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 83ae6f530..4191db290 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -46,7 +46,8 @@
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 
-#define IPMI_MSGHANDLER_VERSION "v32"
+#define PFX "IPMI message handler: "
+#define IPMI_MSGHANDLER_VERSION "v33"
 
 struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
 static int ipmi_init_msghandler(void);
@@ -895,6 +896,12 @@ int ipmi_unregister_for_cmd(ipmi_user_t   user,
 	return rv;
 }
 
+void ipmi_user_set_run_to_completion(ipmi_user_t user, int val)
+{
+	user->intf->handlers->set_run_to_completion(user->intf->send_info,
+						    val);
+}
+
 static unsigned char
 ipmb_checksum(unsigned char *data, int size)
 {
@@ -1686,8 +1693,8 @@ channel_handler(ipmi_smi_t intf, struct ipmi_smi_msg *msg)
 			intf->curr_channel = IPMI_MAX_CHANNELS;
 			wake_up(&intf->waitq);
 
-			printk(KERN_WARNING "ipmi_msghandler: Error sending"
-			       "channel information: %d\n",
+			printk(KERN_WARNING PFX
+			       "Error sending channel information: %d\n",
 			       rv);
 		}
 	}
@@ -2351,7 +2358,7 @@ static int handle_read_event_rsp(ipmi_smi_t          intf,
 	} else {
 		/* There's too many things in the queue, discard this
 		   message. */
-		printk(KERN_WARNING "ipmi: Event queue full, discarding an"
+		printk(KERN_WARNING PFX "Event queue full, discarding an"
 		       " incoming event\n");
 	}
 
@@ -2433,10 +2440,34 @@ static int handle_new_recv_msg(ipmi_smi_t          intf,
 #endif
 	if (msg->rsp_size < 2) {
 		/* Message is too small to be correct. */
-		requeue = 0;
-	} else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2))
-		   && (msg->rsp[1] == IPMI_SEND_MSG_CMD)
-		   && (msg->user_data != NULL))
+		printk(KERN_WARNING PFX "BMC returned to small a message"
+		       " for netfn %x cmd %x, got %d bytes\n",
+		       (msg->data[0] >> 2) | 1, msg->data[1], msg->rsp_size);
+
+		/* Generate an error response for the message. */
+		msg->rsp[0] = msg->data[0] | (1 << 2);
+		msg->rsp[1] = msg->data[1];
+		msg->rsp[2] = IPMI_ERR_UNSPECIFIED;
+		msg->rsp_size = 3;
+	} else if (((msg->rsp[0] >> 2) != ((msg->data[0] >> 2) | 1))/* Netfn */
+		   || (msg->rsp[1] != msg->data[1]))		  /* Command */
+	{
+		/* The response is not even marginally correct. */
+		printk(KERN_WARNING PFX "BMC returned incorrect response,"
+		       " expected netfn %x cmd %x, got netfn %x cmd %x\n",
+		       (msg->data[0] >> 2) | 1, msg->data[1],
+		       msg->rsp[0] >> 2, msg->rsp[1]);
+
+		/* Generate an error response for the message. */
+		msg->rsp[0] = msg->data[0] | (1 << 2);
+		msg->rsp[1] = msg->data[1];
+		msg->rsp[2] = IPMI_ERR_UNSPECIFIED;
+		msg->rsp_size = 3;
+	}
+
+	if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2))
+	    && (msg->rsp[1] == IPMI_SEND_MSG_CMD)
+	    && (msg->user_data != NULL))
 	{
 		/* It's a response to a response we sent.  For this we
 		   deliver a send message response to the user. */
@@ -2502,7 +2533,9 @@ static int handle_new_recv_msg(ipmi_smi_t          intf,
 			requeue = 0;
 		}
 
-	} else if (msg->rsp[1] == IPMI_READ_EVENT_MSG_BUFFER_CMD) {
+	} else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2))
+		   && (msg->rsp[1] == IPMI_READ_EVENT_MSG_BUFFER_CMD))
+	{
 		/* It's an asyncronous event. */
 		requeue = handle_read_event_rsp(intf, msg);
 	} else {
@@ -3114,7 +3147,7 @@ static int ipmi_init_msghandler(void)
 
 	proc_ipmi_root = proc_mkdir("ipmi", NULL);
 	if (!proc_ipmi_root) {
-	    printk("Unable to create IPMI proc dir");
+	    printk(KERN_ERR PFX "Unable to create IPMI proc dir");
 	    return -ENOMEM;
 	}
 
@@ -3166,11 +3199,11 @@ static __exit void cleanup_ipmi(void)
 	/* Check for buffer leaks. */
 	count = atomic_read(&smi_msg_inuse_count);
 	if (count != 0)
-		printk("ipmi_msghandler: SMI message count %d at exit\n",
+		printk(KERN_WARNING PFX "SMI message count %d at exit\n",
 		       count);
 	count = atomic_read(&recv_msg_inuse_count);
 	if (count != 0)
-		printk("ipmi_msghandler: recv message count %d at exit\n",
+		printk(KERN_WARNING PFX "recv message count %d at exit\n",
 		       count);
 }
 module_exit(cleanup_ipmi);
@@ -3207,3 +3240,4 @@ EXPORT_SYMBOL(ipmi_get_my_address);
 EXPORT_SYMBOL(ipmi_set_my_LUN);
 EXPORT_SYMBOL(ipmi_get_my_LUN);
 EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
+EXPORT_SYMBOL(ipmi_user_set_run_to_completion);
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index ea330f3ff..835d6a431 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -76,7 +76,7 @@ static inline void add_usec_to_timer(struct timer_list *t, long v)
 #include "ipmi_si_sm.h"
 #include <linux/init.h>
 
-#define IPMI_SI_VERSION "v32"
+#define IPMI_SI_VERSION "v33"
 
 /* Measure times between events in the driver. */
 #undef DEBUG_TIMING
@@ -146,6 +146,11 @@ struct smi_info
 	/* The I/O port of an SI interface. */
 	int                 port;
 
+	/* The space between start addresses of the two ports.  For
+	   instance, if the first port is 0xca2 and the spacing is 4, then
+	   the second port is 0xca6. */
+	unsigned int        spacing;
+
 	/* zero if no irq; */
 	int                 irq;
 
@@ -452,14 +457,20 @@ static void handle_transaction_done(struct smi_info *smi_info)
 
 			/* Take off the event flag. */
 			smi_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
+			handle_flags(smi_info);
 		} else {
 			spin_lock(&smi_info->count_lock);
 			smi_info->events++;
 			spin_unlock(&smi_info->count_lock);
 
+			/* Do this before we deliver the message
+			   because delivering the message releases the
+			   lock and something else can mess with the
+			   state. */
+			handle_flags(smi_info);
+
 			deliver_recv_msg(smi_info, msg);
 		}
-		handle_flags(smi_info);
 		break;
 	}
 
@@ -482,14 +493,20 @@ static void handle_transaction_done(struct smi_info *smi_info)
 
 			/* Take off the msg flag. */
 			smi_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
+			handle_flags(smi_info);
 		} else {
 			spin_lock(&smi_info->count_lock);
 			smi_info->incoming_messages++;
 			spin_unlock(&smi_info->count_lock);
 
+			/* Do this before we deliver the message
+			   because delivering the message releases the
+			   lock and something else can mess with the
+			   state. */
+			handle_flags(smi_info);
+
 			deliver_recv_msg(smi_info, msg);
 		}
-		handle_flags(smi_info);
 		break;
 	}
 
@@ -568,6 +585,9 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
 		smi_info->hosed_count++;
 		spin_unlock(&smi_info->count_lock);
 
+		/* Do the before return_hosed_msg, because that
+		   releases the lock. */
+		smi_info->si_state = SI_NORMAL;
 		if (smi_info->curr_msg != NULL) {
 			/* If we were handling a user message, format
                            a response to send to the upper layer to
@@ -575,7 +595,6 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
 			return_hosed_msg(smi_info);
 		}
 		si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0);
-		smi_info->si_state = SI_NORMAL;
 	}
 
 	/* We prefer handling attn over new messages. */
@@ -872,9 +891,10 @@ static struct smi_info *smi_infos[SI_MAX_DRIVERS] =
 
 #define DEVICE_NAME "ipmi_si"
 
-#define DEFAULT_KCS_IO_PORT 0xca2
-#define DEFAULT_SMIC_IO_PORT 0xca9
-#define DEFAULT_BT_IO_PORT   0xe4
+#define DEFAULT_KCS_IO_PORT	0xca2
+#define DEFAULT_SMIC_IO_PORT	0xca9
+#define DEFAULT_BT_IO_PORT	0xe4
+#define DEFAULT_REGSPACING	1
 
 static int           si_trydefaults = 1;
 static char          *si_type[SI_MAX_PARMS] = { NULL, NULL, NULL, NULL };
@@ -886,6 +906,12 @@ static unsigned int  ports[SI_MAX_PARMS] = { 0, 0, 0, 0 };
 static int num_ports = 0;
 static int           irqs[SI_MAX_PARMS] = { 0, 0, 0, 0 };
 static int num_irqs = 0;
+static int           regspacings[SI_MAX_PARMS] = { 0, 0, 0, 0 };
+static int num_regspacings = 0;
+static int           regsizes[SI_MAX_PARMS] = { 0, 0, 0, 0 };
+static int num_regsizes = 0;
+static int           regshifts[SI_MAX_PARMS] = { 0, 0, 0, 0 };
+static int num_regshifts = 0;
 
 
 module_param_named(trydefaults, si_trydefaults, bool, 0);
@@ -912,6 +938,23 @@ MODULE_PARM_DESC(irqs, "Sets the interrupt of each interface, the"
 		 " addresses separated by commas.  Only use if an interface"
 		 " has an interrupt.  Otherwise, set it to zero or leave"
 		 " it blank.");
+module_param_array(regspacings, int, num_regspacings, 0);
+MODULE_PARM_DESC(regspacings, "The number of bytes between the start address"
+		 " and each successive register used by the interface.  For"
+		 " instance, if the start address is 0xca2 and the spacing"
+		 " is 2, then the second address is at 0xca4.  Defaults"
+		 " to 1.");
+module_param_array(regsizes, int, num_regsizes, 0);
+MODULE_PARM_DESC(regsizes, "The size of the specific IPMI register in bytes."
+		 " This should generally be 1, 2, 4, or 8 for an 8-bit,"
+		 " 16-bit, 32-bit, or 64-bit register.  Use this if you"
+		 " the 8-bit IPMI register has to be read from a larger"
+		 " register.");
+module_param_array(regshifts, int, num_regshifts, 0);
+MODULE_PARM_DESC(regshifts, "The amount to shift the data read from the."
+		 " IPMI register, in bits.  For instance, if the data"
+		 " is read from a 32-bit word and the IPMI data is in"
+		 " bit 8-15, then the shift would be 8");
 
 #define IPMI_MEM_ADDR_SPACE 1
 #define IPMI_IO_ADDR_SPACE  2
@@ -977,7 +1020,7 @@ static unsigned char port_inb(struct si_sm_io *io, unsigned int offset)
 {
 	unsigned int *addr = io->info;
 
-	return inb((*addr)+offset);
+	return inb((*addr)+(offset*io->regspacing));
 }
 
 static void port_outb(struct si_sm_io *io, unsigned int offset,
@@ -985,30 +1028,97 @@ static void port_outb(struct si_sm_io *io, unsigned int offset,
 {
 	unsigned int *addr = io->info;
 
-	outb(b, (*addr)+offset);
+	outb(b, (*addr)+(offset * io->regspacing));
 }
 
-static int port_setup(struct smi_info *info)
+static unsigned char port_inw(struct si_sm_io *io, unsigned int offset)
 {
-	unsigned int *addr = info->io.info;
+	unsigned int *addr = io->info;
 
-	if (!addr || (!*addr))
-		return -ENODEV;
+	return (inw((*addr)+(offset * io->regspacing)) >> io->regshift) & 0xff;
+}
 
-	if (request_region(*addr, info->io_size, DEVICE_NAME) == NULL)
-		return -EIO;
-	return 0;
+static void port_outw(struct si_sm_io *io, unsigned int offset,
+		      unsigned char b)
+{
+	unsigned int *addr = io->info;
+
+	outw(b << io->regshift, (*addr)+(offset * io->regspacing));
+}
+
+static unsigned char port_inl(struct si_sm_io *io, unsigned int offset)
+{
+	unsigned int *addr = io->info;
+
+	return (inl((*addr)+(offset * io->regspacing)) >> io->regshift) & 0xff;
+}
+
+static void port_outl(struct si_sm_io *io, unsigned int offset,
+		      unsigned char b)
+{
+	unsigned int *addr = io->info;
+
+	outl(b << io->regshift, (*addr)+(offset * io->regspacing));
 }
 
 static void port_cleanup(struct smi_info *info)
 {
 	unsigned int *addr = info->io.info;
+	int           mapsize;
 
-	if (addr && (*addr))
-		release_region (*addr, info->io_size);
+	if (addr && (*addr)) {
+		mapsize = ((info->io_size * info->io.regspacing)
+			   - (info->io.regspacing - info->io.regsize));
+
+		release_region (*addr, mapsize);
+	}
 	kfree(info);
 }
 
+static int port_setup(struct smi_info *info)
+{
+	unsigned int *addr = info->io.info;
+	int           mapsize;
+
+	if (!addr || (!*addr))
+		return -ENODEV;
+
+	info->io_cleanup = port_cleanup;
+
+	/* Figure out the actual inb/inw/inl/etc routine to use based
+	   upon the register size. */
+	switch (info->io.regsize) {
+	case 1:
+		info->io.inputb = port_inb;
+		info->io.outputb = port_outb;
+		break;
+	case 2:
+		info->io.inputb = port_inw;
+		info->io.outputb = port_outw;
+		break;
+	case 4:
+		info->io.inputb = port_inl;
+		info->io.outputb = port_outl;
+		break;
+	default:
+		printk("ipmi_si: Invalid register size: %d\n",
+		       info->io.regsize);
+		return -EINVAL;
+	}
+
+	/* Calculate the total amount of memory to claim.  This is an
+	 * unusual looking calculation, but it avoids claiming any
+	 * more memory than it has to.  It will claim everything
+	 * between the first address to the end of the last full
+	 * register. */
+	mapsize = ((info->io_size * info->io.regspacing)
+		   - (info->io.regspacing - info->io.regsize));
+
+	if (request_region(*addr, mapsize, DEVICE_NAME) == NULL)
+		return -EIO;
+	return 0;
+}
+
 static int try_init_port(int intf_num, struct smi_info **new_info)
 {
 	struct smi_info *info;
@@ -1028,11 +1138,15 @@ static int try_init_port(int intf_num, struct smi_info **new_info)
 	memset(info, 0, sizeof(*info));
 
 	info->io_setup = port_setup;
-	info->io_cleanup = port_cleanup;
-	info->io.inputb = port_inb;
-	info->io.outputb = port_outb;
 	info->io.info = &(ports[intf_num]);
 	info->io.addr = NULL;
+	info->io.regspacing = regspacings[intf_num];
+	if (!info->io.regspacing)
+		info->io.regspacing = DEFAULT_REGSPACING;
+	info->io.regsize = regsizes[intf_num];
+	if (!info->io.regsize)
+		info->io.regsize = DEFAULT_REGSPACING;
+	info->io.regshift = regshifts[intf_num];
 	info->irq = 0;
 	info->irq_setup = NULL;
 	*new_info = info;
@@ -1047,44 +1161,125 @@ static int try_init_port(int intf_num, struct smi_info **new_info)
 
 static unsigned char mem_inb(struct si_sm_io *io, unsigned int offset)
 {
-	return readb((io->addr)+offset);
+	return readb((io->addr)+(offset * io->regspacing));
 }
 
 static void mem_outb(struct si_sm_io *io, unsigned int offset,
 		     unsigned char b)
 {
-	writeb(b, (io->addr)+offset);
+	writeb(b, (io->addr)+(offset * io->regspacing));
 }
 
-static int mem_setup(struct smi_info *info)
+static unsigned char mem_inw(struct si_sm_io *io, unsigned int offset)
 {
-	unsigned long *addr = info->io.info;
+	return (readw((io->addr)+(offset * io->regspacing)) >> io->regshift)
+		&& 0xff;
+}
 
-	if (!addr || (!*addr))
-		return -ENODEV;
+static void mem_outw(struct si_sm_io *io, unsigned int offset,
+		     unsigned char b)
+{
+	writeb(b << io->regshift, (io->addr)+(offset * io->regspacing));
+}
 
-	if (request_mem_region(*addr, info->io_size, DEVICE_NAME) == NULL)
-		return -EIO;
+static unsigned char mem_inl(struct si_sm_io *io, unsigned int offset)
+{
+	return (readl((io->addr)+(offset * io->regspacing)) >> io->regshift)
+		&& 0xff;
+}
 
-	info->io.addr = ioremap(*addr, info->io_size);
-	if (info->io.addr == NULL) {
-		release_mem_region(*addr, info->io_size);
-		return -EIO;
-	}
-	return 0;
+static void mem_outl(struct si_sm_io *io, unsigned int offset,
+		     unsigned char b)
+{
+	writel(b << io->regshift, (io->addr)+(offset * io->regspacing));
 }
 
+#ifdef readq
+static unsigned char mem_inq(struct si_sm_io *io, unsigned int offset)
+{
+	return (readq((io->addr)+(offset * io->regspacing)) >> io->regshift)
+		&& 0xff;
+}
+
+static void mem_outq(struct si_sm_io *io, unsigned int offset,
+		     unsigned char b)
+{
+	writeq(b << io->regshift, (io->addr)+(offset * io->regspacing));
+}
+#endif
+
 static void mem_cleanup(struct smi_info *info)
 {
 	unsigned long *addr = info->io.info;
+	int           mapsize;
 
 	if (info->io.addr) {
 		iounmap(info->io.addr);
-		release_mem_region(*addr, info->io_size);
+
+		mapsize = ((info->io_size * info->io.regspacing)
+			   - (info->io.regspacing - info->io.regsize));
+
+		release_mem_region(*addr, mapsize);
 	}
 	kfree(info);
 }
 
+static int mem_setup(struct smi_info *info)
+{
+	unsigned long *addr = info->io.info;
+	int           mapsize;
+
+	if (!addr || (!*addr))
+		return -ENODEV;
+
+	info->io_cleanup = mem_cleanup;
+
+	/* Figure out the actual readb/readw/readl/etc routine to use based
+	   upon the register size. */
+	switch (info->io.regsize) {
+	case 1:
+		info->io.inputb = mem_inb;
+		info->io.outputb = mem_outb;
+		break;
+	case 2:
+		info->io.inputb = mem_inw;
+		info->io.outputb = mem_outw;
+		break;
+	case 4:
+		info->io.inputb = mem_inl;
+		info->io.outputb = mem_outl;
+		break;
+#ifdef readq
+	case 8:
+		info->io.inputb = mem_inq;
+		info->io.outputb = mem_outq;
+		break;
+#endif
+	default:
+		printk("ipmi_si: Invalid register size: %d\n",
+		       info->io.regsize);
+		return -EINVAL;
+	}
+
+	/* Calculate the total amount of memory to claim.  This is an
+	 * unusual looking calculation, but it avoids claiming any
+	 * more memory than it has to.  It will claim everything
+	 * between the first address to the end of the last full
+	 * register. */
+	mapsize = ((info->io_size * info->io.regspacing)
+		   - (info->io.regspacing - info->io.regsize));
+
+	if (request_mem_region(*addr, mapsize, DEVICE_NAME) == NULL)
+		return -EIO;
+
+	info->io.addr = ioremap(*addr, mapsize);
+	if (info->io.addr == NULL) {
+		release_mem_region(*addr, mapsize);
+		return -EIO;
+	}
+	return 0;
+}
+
 static int try_init_mem(int intf_num, struct smi_info **new_info)
 {
 	struct smi_info *info;
@@ -1104,11 +1299,15 @@ static int try_init_mem(int intf_num, struct smi_info **new_info)
 	memset(info, 0, sizeof(*info));
 
 	info->io_setup = mem_setup;
-	info->io_cleanup = mem_cleanup;
-	info->io.inputb = mem_inb;
-	info->io.outputb = mem_outb;
 	info->io.info = (void *) addrs[intf_num];
 	info->io.addr = NULL;
+	info->io.regspacing = regspacings[intf_num];
+	if (!info->io.regspacing)
+		info->io.regspacing = DEFAULT_REGSPACING;
+	info->io.regsize = regsizes[intf_num];
+	if (!info->io.regsize)
+		info->io.regsize = DEFAULT_REGSPACING;
+	info->io.regshift = regshifts[intf_num];
 	info->irq = 0;
 	info->irq_setup = NULL;
 	*new_info = info;
@@ -1132,7 +1331,7 @@ static int try_init_mem(int intf_num, struct smi_info **new_info)
 static int acpi_failure = 0;
 
 /* For GPE-type interrupts. */
-void ipmi_acpi_gpe(void *context)
+u32 ipmi_acpi_gpe(void *context)
 {
 	struct smi_info *smi_info = context;
 	unsigned long   flags;
@@ -1156,6 +1355,8 @@ void ipmi_acpi_gpe(void *context)
 	smi_event_handler(smi_info, 0);
  out:
 	spin_unlock_irqrestore(&(smi_info->si_lock), flags);
+
+	return ACPI_INTERRUPT_HANDLED;
 }
 
 static int acpi_gpe_irq_setup(struct smi_info *info)
@@ -1182,7 +1383,6 @@ static int acpi_gpe_irq_setup(struct smi_info *info)
 		printk("  Using ACPI GPE %d\n", info->irq);
 		return 0;
 	}
-
 }
 
 static void acpi_gpe_irq_cleanup(struct smi_info *info)
@@ -1310,21 +1510,22 @@ static int try_init_acpi(int intf_num, struct smi_info **new_info)
 		info->irq_setup = NULL;
 	}
 
+	regspacings[intf_num] = spmi->addr.register_bit_width / 8;
+	info->io.regspacing = spmi->addr.register_bit_width / 8;
+	regsizes[intf_num] = regspacings[intf_num];
+	info->io.regsize = regsizes[intf_num];
+	regshifts[intf_num] = spmi->addr.register_bit_offset;
+	info->io.regshift = regshifts[intf_num];
+
 	if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
 		io_type = "memory";
 		info->io_setup = mem_setup;
-		info->io_cleanup = mem_cleanup;
 		addrs[intf_num] = spmi->addr.address;
-		info->io.inputb = mem_inb;
-		info->io.outputb = mem_outb;
 		info->io.info = &(addrs[intf_num]);
 	} else if (spmi->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
 		io_type = "I/O";
 		info->io_setup = port_setup;
-		info->io_cleanup = port_cleanup;
 		ports[intf_num] = spmi->addr.address;
-		info->io.inputb = port_inb;
-		info->io.outputb = port_outb;
 		info->io.info = &(ports[intf_num]);
 	} else {
 		kfree(info);
@@ -1348,6 +1549,7 @@ typedef struct dmi_ipmi_data
 	u8   		addr_space;
 	unsigned long	base_addr;
 	u8   		irq;
+	u8              offset;
 }dmi_ipmi_data_t;
 
 typedef struct dmi_header
@@ -1361,6 +1563,7 @@ static int decode_dmi(dmi_header_t *dm, dmi_ipmi_data_t *ipmi_data)
 {
 	u8		*data = (u8 *)dm;
 	unsigned long  	base_addr;
+	u8		reg_spacing;
 
 	ipmi_data->type = data[0x04];
 
@@ -1375,7 +1578,27 @@ static int decode_dmi(dmi_header_t *dm, dmi_ipmi_data_t *ipmi_data)
 		ipmi_data->addr_space = IPMI_MEM_ADDR_SPACE;
 	}
 
-	ipmi_data->base_addr = base_addr;
+	/* The top two bits of byte 0x10 hold the register spacing. */
+	reg_spacing = (data[0x10] & 0xC0) >> 6;
+	switch(reg_spacing){
+	case 0x00: /* Byte boundaries */
+		ipmi_data->offset = 1;
+		break;
+	case 0x01: /* 32-bit boundaries */
+		ipmi_data->offset = 4;
+		break;
+	case 0x02: /* 16-bit boundaries */
+		ipmi_data->offset = 2;
+	default:
+		printk("ipmi_si: Unknown SMBIOS IPMI Base Addr"
+		       " Modifier: 0x%x\n", reg_spacing);
+		return -EIO;
+	}
+
+	/* If bit 4 of byte 0x10 is set, then the lsb for the address
+	   is odd. */
+	ipmi_data->base_addr = base_addr | ((data[0x10] & 0x10) >> 4);
+
 	ipmi_data->irq = data[0x11];
 
 	if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr))
@@ -1500,18 +1723,12 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info)
 	if (ipmi_data.addr_space == 1) {
 		io_type = "memory";
 		info->io_setup = mem_setup;
-		info->io_cleanup = mem_cleanup;
 		addrs[intf_num] = ipmi_data.base_addr;
-		info->io.inputb = mem_inb;
-		info->io.outputb = mem_outb;
 		info->io.info = &(addrs[intf_num]);
 	} else if (ipmi_data.addr_space == 2) {
 		io_type = "I/O";
 		info->io_setup = port_setup;
-		info->io_cleanup = port_cleanup;
 		ports[intf_num] = ipmi_data.base_addr;
-		info->io.inputb = port_inb;
-		info->io.outputb = port_outb;
 		info->io.info = &(ports[intf_num]);
 	} else {
 		kfree(info);
@@ -1519,6 +1736,13 @@ static int try_init_smbios(int intf_num, struct smi_info **new_info)
 		return -EIO;
 	}
 
+	regspacings[intf_num] = ipmi_data.offset;
+	info->io.regspacing = regspacings[intf_num];
+	if (!info->io.regspacing)
+		info->io.regspacing = DEFAULT_REGSPACING;
+	info->io.regsize = DEFAULT_REGSPACING;
+	info->io.regshift = regshifts[intf_num];
+
 	irqs[intf_num] = ipmi_data.irq;
 
 	*new_info = info;
@@ -1596,11 +1820,13 @@ static int find_pci_smic(int intf_num, struct smi_info **new_info)
 	memset(info, 0, sizeof(*info));
 
 	info->io_setup = port_setup;
-	info->io_cleanup = port_cleanup;
 	ports[intf_num] = base_addr;
-	info->io.inputb = port_inb;
-	info->io.outputb = port_outb;
 	info->io.info = &(ports[intf_num]);
+	info->io.regspacing = regspacings[intf_num];
+	if (!info->io.regspacing)
+		info->io.regspacing = DEFAULT_REGSPACING;
+	info->io.regsize = DEFAULT_REGSPACING;
+	info->io.regshift = regshifts[intf_num];
 
 	*new_info = info;
 
@@ -1860,6 +2086,13 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
 	new_smi->timer_stopped = 0;
 	new_smi->stop_operation = 0;
 
+	/* Start clearing the flags before we enable interrupts or the
+	   timer to avoid racing with the timer. */
+	start_clear_flags(new_smi);
+	/* IRQ is defined to be set when non-zero. */
+	if (new_smi->irq)
+		new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ;
+
 	/* The ipmi_register_smi() code does some operations to
 	   determine the channel information, so we must be ready to
 	   handle operations before it is called.  This means we have
@@ -1903,12 +2136,6 @@ static int init_one_smi(int intf_num, struct smi_info **smi)
 		goto out_err_stop_timer;
 	}
 
-	start_clear_flags(new_smi);
-
-	/* IRQ is defined to be set when non-zero. */
-	if (new_smi->irq)
-		new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ;
-
 	*smi = new_smi;
 
 	printk(" IPMI %s interface initialized\n", si_type[intf_num]);
@@ -2052,6 +2279,13 @@ void __exit cleanup_one_si(struct smi_info *to_clean)
 		schedule_timeout(1);
 	}
 
+	/* Interrupts and timeouts are stopped, now make sure the
+	   interface is in a clean state. */
+	while ((to_clean->curr_msg) || (to_clean->si_state != SI_NORMAL)) {
+		poll(to_clean);
+		schedule_timeout(1);
+	}
+
 	rv = ipmi_unregister_smi(to_clean->intf);
 	if (rv) {
 		printk(KERN_ERR
diff --git a/drivers/char/ipmi/ipmi_si_sm.h b/drivers/char/ipmi/ipmi_si_sm.h
index f3506552c..a0212b004 100644
--- a/drivers/char/ipmi/ipmi_si_sm.h
+++ b/drivers/char/ipmi/ipmi_si_sm.h
@@ -52,6 +52,9 @@ struct si_sm_io
            state machine shouldn't touch these. */
 	void *info;
 	void *addr;
+	int  regspacing;
+	int  regsize;
+	int  regshift;
 };
 
 /* Results of SMI events. */
diff --git a/drivers/char/ipmi/ipmi_smic_sm.c b/drivers/char/ipmi/ipmi_smic_sm.c
index b5c08d6e0..ae18747e6 100644
--- a/drivers/char/ipmi/ipmi_smic_sm.c
+++ b/drivers/char/ipmi/ipmi_smic_sm.c
@@ -46,7 +46,7 @@
 #include <linux/ipmi_msgdefs.h>		/* for completion codes */
 #include "ipmi_si_sm.h"
 
-#define IPMI_SMIC_VERSION "v32"
+#define IPMI_SMIC_VERSION "v33"
 
 /* smic_debug is a bit-field
  *	SMIC_DEBUG_ENABLE -	turned on for now
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index fb8492490..db2cf9cb5 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -51,7 +51,9 @@
 #include <asm/apic.h>
 #endif
 
-#define IPMI_WATCHDOG_VERSION "v32"
+#define	PFX "IPMI Watchdog: "
+
+#define IPMI_WATCHDOG_VERSION "v33"
 
 /*
  * The IPMI command/response information for the watchdog timer.
@@ -160,6 +162,7 @@ static char data_to_read = 0;
 static DECLARE_WAIT_QUEUE_HEAD(read_q);
 static struct fasync_struct *fasync_q = NULL;
 static char pretimeout_since_last_heartbeat = 0;
+static char expect_close;
 
 /* If true, the driver will start running as soon as it is configured
    and ready. */
@@ -191,7 +194,7 @@ static unsigned char ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
 static int ipmi_ignore_heartbeat = 0;
 
 /* Is someone using the watchdog?  Only one user is allowed. */
-static int ipmi_wdog_open = 0;
+static unsigned long ipmi_wdog_open = 0;
 
 /* If set to 1, the heartbeat command will set the state to reset and
    start the timer.  The timer doesn't normally run when the driver is
@@ -287,7 +290,7 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg  *smi_msg,
 				      recv_msg,
 				      1);
 	if (rv) {
-		printk(KERN_WARNING "IPMI Watchdog, set timeout error: %d\n",
+		printk(KERN_WARNING PFX "set timeout error: %d\n",
 		       rv);
 	}
 
@@ -464,7 +467,7 @@ static int ipmi_heartbeat(void)
 				      1);
 	if (rv) {
 		up(&heartbeat_lock);
-		printk(KERN_WARNING "IPMI Watchdog, heartbeat failure: %d\n",
+		printk(KERN_WARNING PFX "heartbeat failure: %d\n",
 		       rv);
 		return rv;
 	}
@@ -599,6 +602,21 @@ static ssize_t ipmi_write(struct file *file,
 	int rv;
 
 	if (len) {
+	    	if (!nowayout) {
+		    	size_t i;
+
+			/* In case it was set long ago */
+			expect_close = 0;
+
+    			for (i = 0; i != len; i++) {
+				char c;
+
+				if (get_user(c, buf + i))
+					return -EFAULT;
+				if (c == 'V')
+					expect_close = 42;
+			}
+		}
 		rv = ipmi_heartbeat();
 		if (rv)
 			return rv;
@@ -662,11 +680,9 @@ static int ipmi_open(struct inode *ino, struct file *filep)
         switch (iminor(ino))
         {
                 case WATCHDOG_MINOR:
-                    if (ipmi_wdog_open)
+		    if(test_and_set_bit(0, &ipmi_wdog_open))
                         return -EBUSY;
 
-                    ipmi_wdog_open = 1;
-
 		    /* Don't start the timer now, let it start on the
 		       first heartbeat. */
 		    ipmi_start_timer_on_heartbeat = 1;
@@ -704,14 +720,18 @@ static int ipmi_close(struct inode *ino, struct file *filep)
 {
 	if (iminor(ino)==WATCHDOG_MINOR)
 	{
-		if (!nowayout) {
+		if (expect_close == 42) {
 			ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
 			ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
+			clear_bit(0, &ipmi_wdog_open);
+		} else {
+			printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+			ipmi_heartbeat();
 		}
-	        ipmi_wdog_open = 0;
 	}
 
 	ipmi_fasync (-1, filep, 0);
+	expect_close = 0;
 
 	return 0;
 }
@@ -739,7 +759,7 @@ static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg,
 				  void                 *handler_data)
 {
 	if (msg->msg.data[0] != 0) {
-		printk(KERN_ERR "IPMI Watchdog response: Error %x on cmd %x\n",
+		printk(KERN_ERR PFX "response: Error %x on cmd %x\n",
 		       msg->msg.data[0],
 		       msg->msg.cmd);
 	}
@@ -784,7 +804,7 @@ static void ipmi_register_watchdog(int ipmi_intf)
 
 	rv = ipmi_create_user(ipmi_intf, &ipmi_hndlrs, NULL, &watchdog_user);
 	if (rv < 0) {
-		printk("IPMI watchdog: Unable to register with ipmi\n");
+		printk(KERN_CRIT PFX "Unable to register with ipmi\n");
 		goto out;
 	}
 
@@ -796,7 +816,7 @@ static void ipmi_register_watchdog(int ipmi_intf)
 	if (rv < 0) {
 		ipmi_destroy_user(watchdog_user);
 		watchdog_user = NULL;
-		printk("IPMI watchdog: Unable to register misc device\n");
+		printk(KERN_CRIT PFX "Unable to register misc device\n");
 	}
 
  out:
@@ -807,7 +827,7 @@ static void ipmi_register_watchdog(int ipmi_intf)
 		start_now = 0; /* Disable this function after first startup. */
 		ipmi_watchdog_state = action_val;
 		ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB);
-		printk("Starting IPMI Watchdog now!\n");
+		printk(KERN_INFO PFX "Starting now!\n");
 	}
 }
 
@@ -818,7 +838,7 @@ ipmi_nmi(void *dev_id, struct pt_regs *regs, int cpu, int handled)
 	/* If no one else handled the NMI, we assume it was the IPMI
            watchdog. */
 	if ((!handled) && (preop_val == WDOG_PREOP_PANIC))
-		panic("IPMI watchdog pre-timeout");
+		panic(PFX "pre-timeout");
 
 	/* On some machines, the heartbeat will give
 	   an error and not work unless we re-enable
@@ -924,7 +944,7 @@ static int __init ipmi_wdog_init(void)
 {
 	int rv;
 
-	printk(KERN_INFO "IPMI watchdog driver version "
+	printk(KERN_INFO PFX "driver version "
 	       IPMI_WATCHDOG_VERSION "\n");
 
 	if (strcmp(action, "reset") == 0) {
@@ -937,7 +957,7 @@ static int __init ipmi_wdog_init(void)
 		action_val = WDOG_TIMEOUT_POWER_DOWN;
 	} else {
 		action_val = WDOG_TIMEOUT_RESET;
-		printk("ipmi_watchdog: Unknown action '%s', defaulting to"
+		printk(KERN_INFO PFX "Unknown action '%s', defaulting to"
 		       " reset\n", action);
 	}
 
@@ -953,7 +973,7 @@ static int __init ipmi_wdog_init(void)
 		preaction_val = WDOG_PRETIMEOUT_MSG_INT;
 	} else {
 		preaction_val = WDOG_PRETIMEOUT_NONE;
-		printk("ipmi_watchdog: Unknown preaction '%s', defaulting to"
+		printk(KERN_INFO PFX "Unknown preaction '%s', defaulting to"
 		       " none\n", preaction);
 	}
 
@@ -965,23 +985,21 @@ static int __init ipmi_wdog_init(void)
 		preop_val = WDOG_PREOP_GIVE_DATA;
 	} else {
 		preop_val = WDOG_PREOP_NONE;
-		printk("ipmi_watchdog: Unknown preop '%s', defaulting to"
+		printk(KERN_INFO PFX "Unknown preop '%s', defaulting to"
 		       " none\n", preop);
 	}
 
 #ifdef HAVE_NMI_HANDLER
 	if (preaction_val == WDOG_PRETIMEOUT_NMI) {
 		if (preop_val == WDOG_PREOP_GIVE_DATA) {
-			printk(KERN_WARNING
-			       "ipmi_watchdog: Pretimeout op is to give data"
+			printk(KERN_WARNING PFX "Pretimeout op is to give data"
 			       " but NMI pretimeout is enabled, setting"
 			       " pretimeout op to none\n");
 			preop_val = WDOG_PREOP_NONE;
 		}
 #ifdef CONFIG_X86_LOCAL_APIC
 		if (nmi_watchdog == NMI_IO_APIC) {
-			printk(KERN_WARNING
-			       "ipmi_watchdog: nmi_watchdog is set to IO APIC"
+			printk(KERN_WARNING PFX "nmi_watchdog is set to IO APIC"
 			       " mode (value is %d), that is incompatible"
 			       " with using NMI in the IPMI watchdog."
 			       " Disabling IPMI nmi pretimeout.\n",
@@ -991,8 +1009,7 @@ static int __init ipmi_wdog_init(void)
 #endif
 		rv = request_nmi(&ipmi_nmi_handler);
 		if (rv) {
-			printk(KERN_WARNING
-			       "ipmi_watchdog: Can't register nmi handler\n");
+			printk(KERN_WARNING PFX "Can't register nmi handler\n");
 			return rv;
 		}
 #ifdef CONFIG_X86_LOCAL_APIC
@@ -1007,8 +1024,7 @@ static int __init ipmi_wdog_init(void)
 		if (preaction_val == WDOG_PRETIMEOUT_NMI)
 			release_nmi(&ipmi_nmi_handler);
 #endif
-		printk(KERN_WARNING
-		       "ipmi_watchdog: can't register smi watcher\n");
+		printk(KERN_WARNING PFX "can't register smi watcher\n");
 		return rv;
 	}
 
@@ -1053,8 +1069,7 @@ static __exit void ipmi_unregister_watchdog(void)
 	/* Disconnect from IPMI. */
 	rv = ipmi_destroy_user(watchdog_user);
 	if (rv) {
-		printk(KERN_WARNING
-		       "IPMI Watchdog, error unlinking from IPMI: %d\n",
+		printk(KERN_WARNING PFX "error unlinking from IPMI: %d\n",
 		       rv);
 	}
 	watchdog_user = NULL;
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index e8650449f..b454bf208 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -48,6 +48,7 @@
 #include <linux/miscdevice.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
+#include <linux/delay.h>
 #include <linux/ioport.h>
 
 #include <asm/uaccess.h>
@@ -389,7 +390,7 @@ static void isicom_tx(unsigned long _data)
 		
 		tty = port->tty;
 		save_flags(flags); cli();
-		txcount = MIN(TX_SIZE, port->xmit_cnt);
+		txcount = min_t(short, TX_SIZE, port->xmit_cnt);
 		if ((txcount <= 0) || tty->stopped || tty->hw_stopped) {
 			restore_flags(flags);
 			continue;
@@ -421,7 +422,7 @@ static void isicom_tx(unsigned long _data)
 		residue = NO;
 		wrd = 0;			
 		while (1) {
-			cnt = MIN(txcount, (SERIAL_XMIT_SIZE - port->xmit_tail));
+			cnt = min_t(int, txcount, (SERIAL_XMIT_SIZE - port->xmit_tail));
 			if (residue == YES) {
 				residue = NO;
 				if (cnt > 0) {
@@ -484,10 +485,8 @@ static void isicom_bottomhalf(void * data)
 	
 	if (!tty)
 		return;
-	
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+
+	tty_wakeup(tty);	
 	wake_up_interruptible(&tty->write_wait);
 } 		
  		
@@ -650,7 +649,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id,
 		}	 
 	}
 	else {				/* Data   Packet */
-		count = MIN(byte_count, (TTY_FLIPBUF_SIZE - tty->flip.count));
+		count = min_t(unsigned short, byte_count, (TTY_FLIPBUF_SIZE - tty->flip.count));
 #ifdef ISICOM_DEBUG
 		printk(KERN_DEBUG "ISICOM: Intr: Can rx %d of %d bytes.\n", 
 					count, byte_count);
@@ -1119,8 +1118,8 @@ static void isicom_close(struct tty_struct * tty, struct file * filp)
 	isicom_shutdown_port(port);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+		
+	tty_ldisc_flush(tty);
 	tty->closing = 0;
 	port->tty = NULL;
 	if (port->blocked_open) {
@@ -1163,8 +1162,8 @@ static int isicom_write(struct tty_struct * tty, int from_user,
 	save_flags(flags);
 	while(1) {	
 		cli();
-		cnt = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-			SERIAL_XMIT_SIZE - port->xmit_head));
+		cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+					    SERIAL_XMIT_SIZE - port->xmit_head));
 		if (cnt <= 0) 
 			break;
 		
@@ -1180,8 +1179,8 @@ static int isicom_write(struct tty_struct * tty, int from_user,
 				return -EFAULT;
 			}
 			cli();
-			cnt = MIN(cnt, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-			SERIAL_XMIT_SIZE - port->xmit_head));
+			cnt = min_t(int, cnt, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+						  SERIAL_XMIT_SIZE - port->xmit_head));
 			memcpy(port->xmit_buf + port->xmit_head, tmp_buf, cnt);
 		}	
 		else
@@ -1563,9 +1562,7 @@ static void isicom_flush_buffer(struct tty_struct * tty)
 	restore_flags(flags);
 	
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 
@@ -1906,8 +1903,7 @@ int init_module(void)
 void cleanup_module(void)
 {
 	re_schedule = 0;
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout(HZ);
+	msleep(1000);
 
 #ifdef ISICOM_DEBUG	
 	printk("ISICOM: isicom_tx tx_count = %ld.\n", tx_count);
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 4a8b7d51e..9460f6d0b 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -749,17 +749,13 @@ static void	stli_stalreset(stlibrd_t *brdp);
 
 static stliport_t *stli_getport(int brdnr, int panelnr, int portnr);
 
-static inline int	stli_initbrds(void);
-static inline int	stli_initecp(stlibrd_t *brdp);
-static inline int	stli_initonb(stlibrd_t *brdp);
-static inline int	stli_findeisabrds(void);
-static inline int	stli_eisamemprobe(stlibrd_t *brdp);
-static inline int	stli_initports(stlibrd_t *brdp);
-static inline int	stli_getbrdnr(void);
+static int	stli_initecp(stlibrd_t *brdp);
+static int	stli_initonb(stlibrd_t *brdp);
+static int	stli_eisamemprobe(stlibrd_t *brdp);
+static int	stli_initports(stlibrd_t *brdp);
 
 #ifdef	CONFIG_PCI
-static inline int	stli_findpcibrds(void);
-static inline int	stli_initpcibrd(int brdtype, struct pci_dev *devp);
+static int	stli_initpcibrd(int brdtype, struct pci_dev *devp);
 #endif
 
 /*****************************************************************************/
@@ -2751,7 +2747,7 @@ static void stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd,
  *	more chars to unload.
  */
 
-static inline void stli_read(stlibrd_t *brdp, stliport_t *portp)
+static void stli_read(stlibrd_t *brdp, stliport_t *portp)
 {
 	volatile cdkasyrq_t	*rp;
 	volatile char		*shbuf;
@@ -2819,7 +2815,7 @@ static inline void stli_read(stlibrd_t *brdp, stliport_t *portp)
  *	difficult to deal with them here.
  */
 
-static inline void stli_dodelaycmd(stliport_t *portp, volatile cdkctrl_t *cp)
+static void stli_dodelaycmd(stliport_t *portp, volatile cdkctrl_t *cp)
 {
 	int	cmd;
 
@@ -2867,7 +2863,7 @@ static inline void stli_dodelaycmd(stliport_t *portp, volatile cdkctrl_t *cp)
  *	then port is still busy, otherwise no longer busy.
  */
 
-static inline int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp)
+static int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp)
 {
 	volatile cdkasy_t	*ap;
 	volatile cdkctrl_t	*cp;
@@ -3026,7 +3022,7 @@ static inline int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp)
  *	at the cdk header structure.
  */
 
-static inline void stli_brdpoll(stlibrd_t *brdp, volatile cdkhdr_t *hdrp)
+static void stli_brdpoll(stlibrd_t *brdp, volatile cdkhdr_t *hdrp)
 {
 	stliport_t	*portp;
 	unsigned char	hostbits[(STL_MAXCHANS / 8) + 1];
@@ -3299,7 +3295,7 @@ static long stli_mktiocm(unsigned long sigvalue)
  *	we need to do here is set up the appropriate per port data structures.
  */
 
-static inline int stli_initports(stlibrd_t *brdp)
+static int stli_initports(stlibrd_t *brdp)
 {
 	stliport_t	*portp;
 	int		i, panelnr, panelport;
@@ -3911,7 +3907,7 @@ static void stli_stalreset(stlibrd_t *brdp)
  *	board types.
  */
 
-static inline int stli_initecp(stlibrd_t *brdp)
+static int stli_initecp(stlibrd_t *brdp)
 {
 	cdkecpsig_t	sig;
 	cdkecpsig_t	*sigsp;
@@ -4072,7 +4068,7 @@ static inline int stli_initecp(stlibrd_t *brdp)
  *	This handles only these board types.
  */
 
-static inline int stli_initonb(stlibrd_t *brdp)
+static int stli_initonb(stlibrd_t *brdp)
 {
 	cdkonbsig_t	sig;
 	cdkonbsig_t	*sigsp;
@@ -4414,7 +4410,7 @@ static int __init stli_brdinit(stlibrd_t *brdp)
  *	might be. This is a bit if hack, but it is the best we can do.
  */
 
-static inline int stli_eisamemprobe(stlibrd_t *brdp)
+static int stli_eisamemprobe(stlibrd_t *brdp)
 {
 	cdkecpsig_t	ecpsig, *ecpsigp;
 	cdkonbsig_t	onbsig, *onbsigp;
@@ -4506,7 +4502,7 @@ static inline int stli_eisamemprobe(stlibrd_t *brdp)
 	return(0);
 }
 
-static inline int stli_getbrdnr(void)
+static int stli_getbrdnr(void)
 {
 	int i;
 
@@ -4532,7 +4528,7 @@ static inline int stli_getbrdnr(void)
  *	do is go probing around in the usual places hoping we can find it.
  */
 
-static inline int stli_findeisabrds(void)
+static int stli_findeisabrds(void)
 {
 	stlibrd_t	*brdp;
 	unsigned int	iobase, eid;
@@ -4616,7 +4612,7 @@ static inline int stli_findeisabrds(void)
  *	configuration space.
  */
 
-static inline int stli_initpcibrd(int brdtype, struct pci_dev *devp)
+static int stli_initpcibrd(int brdtype, struct pci_dev *devp)
 {
 	stlibrd_t	*brdp;
 
@@ -4662,7 +4658,7 @@ static inline int stli_initpcibrd(int brdtype, struct pci_dev *devp)
  *	one as it is found.
  */
 
-static inline int stli_findpcibrds(void)
+static int stli_findpcibrds(void)
 {
 	struct pci_dev	*dev = NULL;
 	int		rc;
@@ -4711,7 +4707,7 @@ static stlibrd_t *stli_allocbrd(void)
  *	can find.
  */
 
-static inline int stli_initbrds(void)
+static int stli_initbrds(void)
 {
 	stlibrd_t	*brdp, *nxtbrdp;
 	stlconf_t	*confp;
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 3ad30ba46..313789840 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -123,7 +123,7 @@ int shift_state = 0;
  */
 
 static struct input_handler kbd_handler;
-static unsigned long key_down[256/BITS_PER_LONG];	/* keyboard key bitmap */
+static unsigned long key_down[NBITS(KEY_MAX)];		/* keyboard key bitmap */
 static unsigned char shift_down[NR_SHIFT];		/* shift state counters.. */
 static int dead_key_next;
 static int npadch = -1;					/* -1 or number assembled on pad */
@@ -142,7 +142,7 @@ static struct ledptr {
 /* Simple translation table for the SysRq keys */
 
 #ifdef CONFIG_MAGIC_SYSRQ
-unsigned char kbd_sysrq_xlate[128] =
+unsigned char kbd_sysrq_xlate[KEY_MAX] =
         "\000\0331234567890-=\177\t"                    /* 0x00 - 0x0f */
         "qwertyuiop[]\r\000as"                          /* 0x10 - 0x1f */
         "dfghjkl;'`\000\\zxcv"                          /* 0x20 - 0x2f */
@@ -941,6 +941,9 @@ void kbd_refresh_leds(struct input_handle *handle)
 
 #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64) || defined(CONFIG_PARISC) || defined(CONFIG_SUPERH)
 
+#define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\
+			((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001))
+
 static unsigned short x86_keycodes[256] =
 	{ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
 	 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
@@ -1007,6 +1010,8 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode,
 
 #else
 
+#define HW_RAW(dev)	0
+
 #warning "Cannot generate rawmode keyboard for your architecture yet."
 
 static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag)
@@ -1019,7 +1024,15 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char u
 }
 #endif
 
-void kbd_keycode(unsigned int keycode, int down, struct pt_regs *regs)
+void kbd_rawcode(unsigned char data)
+{
+	struct vc_data *vc = vc_cons[fg_console].d;
+	kbd = kbd_table + fg_console;
+	if (kbd->kbdmode == VC_RAW)
+		put_queue(vc, data);
+}
+
+void kbd_keycode(unsigned int keycode, int down, int hw_raw, struct pt_regs *regs)
 {
 	struct vc_data *vc = vc_cons[fg_console].d;
 	unsigned short keysym, *key_map;
@@ -1053,7 +1066,7 @@ void kbd_keycode(unsigned int keycode, int down, struct pt_regs *regs)
 		return;
 #endif /* CONFIG_MAC_EMUMOUSEBTN */
 
-	if ((raw_mode = (kbd->kbdmode == VC_RAW)))
+	if ((raw_mode = (kbd->kbdmode == VC_RAW)) && !hw_raw)
 		if (emulate_raw(vc, keycode, !down << 7))
 			if (keycode < BTN_MISC)
 				printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode);
@@ -1119,6 +1132,9 @@ void kbd_keycode(unsigned int keycode, int down, struct pt_regs *regs)
 		return;
 	}
 
+	if (keycode > NR_KEYS)
+		return;
+
 	keysym = key_map[keycode];
 	type = KTYP(keysym);
 
@@ -1148,11 +1164,12 @@ void kbd_keycode(unsigned int keycode, int down, struct pt_regs *regs)
 }
 
 static void kbd_event(struct input_handle *handle, unsigned int event_type, 
-		      unsigned int keycode, int down)
+		      unsigned int event_code, int value)
 {
-	if (event_type != EV_KEY)
-		return;
-	kbd_keycode(keycode, down, handle->dev->regs);
+	if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev))
+		kbd_rawcode(value);
+	if (event_type == EV_KEY)
+		kbd_keycode(event_code, value, HW_RAW(handle->dev), handle->dev->regs);
 	tasklet_schedule(&keyboard_tasklet);
 	do_poke_blanked_console = 1;
 	schedule_console_callback();
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 3274c3a73..9d8dbded2 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -31,9 +31,6 @@
 # include <linux/efi.h>
 #endif
 
-#ifdef CONFIG_FB
-extern void fbmem_init(void);
-#endif
 #if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR)
 extern void tapechar_init(void);
 #endif
@@ -86,7 +83,7 @@ static inline int uncached_access(struct file *file, unsigned long addr)
 	 * above the IO hole... Ah, and of course, XFree86 doesn't pass
 	 * O_SYNC when mapping us to tap IO space. Surprised ?
 	 */
-	return !page_is_ram(addr);
+	return !page_is_ram(addr >> PAGE_SHIFT);
 #else
 	/*
 	 * Accessing memory above the top the kernel knows about or through a file pointer
@@ -416,7 +413,7 @@ static inline size_t read_zero_pagealigned(char __user * buf, size_t size)
 
 		if (vma->vm_start > addr || (vma->vm_flags & VM_WRITE) == 0)
 			goto out_up;
-		if (vma->vm_flags & VM_SHARED)
+		if (vma->vm_flags & (VM_SHARED | VM_HUGETLB))
 			break;
 		count = vma->vm_end - addr;
 		if (count > size)
@@ -730,9 +727,6 @@ static int __init chr_dev_init(void)
 				S_IFCHR | devlist[i].mode, devlist[i].name);
 	}
 	
-#if defined (CONFIG_FB)
-	fbmem_init();
-#endif
 	return 0;
 }
 
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index 0e75a0dc9..d45d381d4 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -618,8 +618,8 @@ static void moxa_close(struct tty_struct *tty, struct file *filp)
 
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
+			
 	tty->closing = 0;
 	ch->event = 0;
 	ch->tty = NULL;
@@ -693,9 +693,7 @@ static void moxa_flush_buffer(struct tty_struct *tty)
 	if (ch == NULL)
 		return;
 	MoxaPortFlushData(ch->port, 1);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup) (tty);
+	tty_wakeup(tty);
 	wake_up_interruptible(&tty->write_wait);
 }
 
@@ -954,9 +952,7 @@ static void moxa_poll(unsigned long ignored)
 				if (MoxaPortTxQueue(ch->port) <= WAKEUP_CHARS) {
 					if (!tp->stopped) {
 						ch->statusflags &= ~LOWWAIT;
-						if ((tp->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-						  tp->ldisc.write_wakeup)
-							(tp->ldisc.write_wakeup) (tp);
+						tty_wakeup(tp);
 						wake_up_interruptible(&tp->write_wait);
 					}
 				}
@@ -1123,9 +1119,7 @@ static void check_xmit_empty(unsigned long data)
 	if (ch->tty && (ch->statusflags & EMPTYWAIT)) {
 		if (MoxaPortTxQueue(ch->port) == 0) {
 			ch->statusflags &= ~EMPTYWAIT;
-			if ((ch->tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-			    ch->tty->ldisc.write_wakeup)
-				(ch->tty->ldisc.write_wakeup) (ch->tty);
+			tty_wakeup(ch->tty);
 			wake_up_interruptible(&ch->tty->write_wait);
 			return;
 		}
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index d4ba62a29..147c1ba2e 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -101,10 +101,6 @@
 
 #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
 
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
 /*
  *    Define the Moxa PCI vendor and device IDs.
  */
@@ -349,10 +345,10 @@ static void mxser_set_termios(struct tty_struct *, struct termios *);
 static void mxser_stop(struct tty_struct *);
 static void mxser_start(struct tty_struct *);
 static void mxser_hangup(struct tty_struct *);
-static irqreturn_t mxser_interrupt(int, void *, struct pt_regs *);
 static inline void mxser_receive_chars(struct mxser_struct *, int *);
 static inline void mxser_transmit_chars(struct mxser_struct *);
 static inline void mxser_check_modem_status(struct mxser_struct *, int);
+static irqreturn_t mxser_interrupt(int, void *, struct pt_regs *);
 static int mxser_block_til_ready(struct tty_struct *, struct file *, struct mxser_struct *);
 static int mxser_startup(struct mxser_struct *);
 static void mxser_shutdown(struct mxser_struct *);
@@ -678,9 +674,7 @@ static void mxser_do_softint(void *private_)
 	tty = info->tty;
 	if (tty) {
 		if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event)) {
-			if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-			    tty->ldisc.write_wakeup)
-				(tty->ldisc.write_wakeup) (tty);
+			tty_wakeup(tty);
 			wake_up_interruptible(&tty->write_wait);
 		}
 		if (test_and_clear_bit(MXSER_EVENT_HANGUP, &info->event)) {
@@ -817,8 +811,8 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
 	mxser_shutdown(info);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
+
 	tty->closing = 0;
 	info->event = 0;
 	info->tty = NULL;
@@ -849,7 +843,7 @@ static int mxser_write(struct tty_struct *tty, int from_user,
 	if (from_user) {
 		down(&mxvar_tmp_buf_sem);
 		while (1) {
-			c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+			c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
 					   SERIAL_XMIT_SIZE - info->xmit_head));
 			if (c <= 0)
 				break;
@@ -862,7 +856,7 @@ static int mxser_write(struct tty_struct *tty, int from_user,
 			}
 
 			cli();
-			c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+			c = min_t(int, c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
 				       SERIAL_XMIT_SIZE - info->xmit_head));
 			memcpy(info->xmit_buf + info->xmit_head, mxvar_tmp_buf, c);
 			info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
@@ -877,7 +871,7 @@ static int mxser_write(struct tty_struct *tty, int from_user,
 	} else {
 		while (1) {
 			cli();
-			c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+			c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
 					   SERIAL_XMIT_SIZE - info->xmit_head));
 			if (c <= 0) {
 				restore_flags(flags);
@@ -976,9 +970,7 @@ static void mxser_flush_buffer(struct tty_struct *tty)
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 	restore_flags(flags);
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup) (tty);
+	tty_wakeup(tty);
 }
 
 static int mxser_ioctl(struct tty_struct *tty, struct file *file,
@@ -1307,69 +1299,6 @@ void mxser_hangup(struct tty_struct *tty)
 	wake_up_interruptible(&info->open_wait);
 }
 
-/*
- * This is the serial driver's generic interrupt routine
- */
-static irqreturn_t mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	int status, i;
-	struct mxser_struct *info;
-	struct mxser_struct *port;
-	int max, irqbits, bits, msr;
-	int pass_counter = 0;
-	int handled = 0;
-
-	port = NULL;
-	for (i = 0; i < MXSER_BOARDS; i++) {
-		if (dev_id == &(mxvar_table[i * MXSER_PORTS_PER_BOARD])) {
-			port = dev_id;
-			break;
-		}
-	}
-
-	if (i == MXSER_BOARDS)
-		return IRQ_NONE;
-	if (port == 0)
-		return IRQ_NONE;
-	max = mxser_numports[mxsercfg[i].board_type];
-
-	while (1) {
-		irqbits = inb(port->vector) & port->vectormask;
-		if (irqbits == port->vectormask)
-			break;
-		handled = 1;
-		for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) {
-			if (irqbits == port->vectormask)
-				break;
-			if (bits & irqbits)
-				continue;
-			info = port + i;
-			if (!info->tty ||
-			  (inb(info->base + UART_IIR) & UART_IIR_NO_INT))
-				continue;
-			status = inb(info->base + UART_LSR) & info->read_status_mask;
-			if (status & UART_LSR_DR)
-				mxser_receive_chars(info, &status);
-			msr = inb(info->base + UART_MSR);
-			if (msr & UART_MSR_ANY_DELTA)
-				mxser_check_modem_status(info, msr);
-			if (status & UART_LSR_THRE) {
-/* 8-2-99 by William
-   if ( info->x_char || (info->xmit_cnt > 0) )
- */
-				mxser_transmit_chars(info);
-			}
-		}
-		if (pass_counter++ > MXSER_ISR_PASS_LIMIT) {
-#if 0
-			printk("MOXA Smartio/Indusrtio family driver interrupt loop break\n");
-#endif
-			break;	/* Prevent infinite loops */
-		}
-	}
-	return IRQ_RETVAL(handled);
-}
-
 static inline void mxser_receive_chars(struct mxser_struct *info,
 					 int *status)
 {
@@ -1490,6 +1419,69 @@ static inline void mxser_check_modem_status(struct mxser_struct *info,
 	}
 }
 
+/*
+ * This is the serial driver's generic interrupt routine
+ */
+static irqreturn_t mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	int status, i;
+	struct mxser_struct *info;
+	struct mxser_struct *port;
+	int max, irqbits, bits, msr;
+	int pass_counter = 0;
+	int handled = 0;
+
+	port = NULL;
+	for (i = 0; i < MXSER_BOARDS; i++) {
+		if (dev_id == &(mxvar_table[i * MXSER_PORTS_PER_BOARD])) {
+			port = dev_id;
+			break;
+		}
+	}
+
+	if (i == MXSER_BOARDS)
+		return IRQ_NONE;
+	if (port == 0)
+		return IRQ_NONE;
+	max = mxser_numports[mxsercfg[i].board_type];
+
+	while (1) {
+		irqbits = inb(port->vector) & port->vectormask;
+		if (irqbits == port->vectormask)
+			break;
+		handled = 1;
+		for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) {
+			if (irqbits == port->vectormask)
+				break;
+			if (bits & irqbits)
+				continue;
+			info = port + i;
+			if (!info->tty ||
+			  (inb(info->base + UART_IIR) & UART_IIR_NO_INT))
+				continue;
+			status = inb(info->base + UART_LSR) & info->read_status_mask;
+			if (status & UART_LSR_DR)
+				mxser_receive_chars(info, &status);
+			msr = inb(info->base + UART_MSR);
+			if (msr & UART_MSR_ANY_DELTA)
+				mxser_check_modem_status(info, msr);
+			if (status & UART_LSR_THRE) {
+/* 8-2-99 by William
+   if ( info->x_char || (info->xmit_cnt > 0) )
+ */
+				mxser_transmit_chars(info);
+			}
+		}
+		if (pass_counter++ > MXSER_ISR_PASS_LIMIT) {
+#if 0
+			printk("MOXA Smartio/Indusrtio family driver interrupt loop break\n");
+#endif
+			break;	/* Prevent infinite loops */
+		}
+	}
+	return IRQ_RETVAL(handled);
+}
+
 static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
 				 struct mxser_struct *info)
 {
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 072197462..5a3be050e 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -99,11 +99,18 @@ static inline void put_tty_queue(unsigned char c, struct tty_struct *tty)
 	spin_unlock_irqrestore(&tty->read_lock, flags);
 }
 
-/* 
- * Check whether to call the driver.unthrottle function.
- * We test the TTY_THROTTLED bit first so that it always
- * indicates the current state.
+/**
+ *	check_unthrottle	-	allow new receive data
+ *	@tty; tty device
+ *
+ *	Check whether to call the driver.unthrottle function.
+ *	We test the TTY_THROTTLED bit first so that it always
+ *	indicates the current state. The decision about whether
+ *	it is worth allowing more input has been taken by the caller.
+ *	Can sleep, may be called under the atomic_read semaphore but
+ *	this is not guaranteed.
  */
+ 
 static void check_unthrottle(struct tty_struct * tty)
 {
 	if (tty->count &&
@@ -112,10 +119,13 @@ static void check_unthrottle(struct tty_struct * tty)
 		tty->driver->unthrottle(tty);
 }
 
-/*
- * Reset the read buffer counters, clear the flags, 
- * and make sure the driver is unthrottled. Called
- * from n_tty_open() and n_tty_flush_buffer().
+/**
+ *	reset_buffer_flags	-	reset buffer state
+ *	@tty: terminal to reset
+ *
+ *	Reset the read buffer counters, clear the flags, 
+ *	and make sure the driver is unthrottled. Called
+ *	from n_tty_open() and n_tty_flush_buffer().
  */
 static void reset_buffer_flags(struct tty_struct *tty)
 {
@@ -129,9 +139,19 @@ static void reset_buffer_flags(struct tty_struct *tty)
 	check_unthrottle(tty);
 }
 
-/*
- * Flush the input buffer
+/**
+ *	n_tty_flush_buffer	-	clean input queue
+ *	@tty:	terminal device
+ *
+ *	Flush the input buffer. Called when the line discipline is
+ *	being closed, when the tty layer wants the buffer flushed (eg
+ *	at hangup) or when the N_TTY line discipline internally has to
+ *	clean the pending queue (for example some signals).
+ *
+ *	FIXME: tty->ctrl_status is not spinlocked and relies on
+ *	lock_kernel() still.
  */
+ 
 void n_tty_flush_buffer(struct tty_struct * tty)
 {
 	/* clear everything and unthrottle the driver */
@@ -146,9 +166,14 @@ void n_tty_flush_buffer(struct tty_struct * tty)
 	}
 }
 
-/*
- * Return number of characters buffered to be delivered to user
+/**
+ *	n_tty_chars_in_buffer	-	report available bytes
+ *	@tty: tty device
+ *
+ *	Report the number of characters buffered to be delivered to user
+ *	at this instant in time. 
  */
+ 
 ssize_t n_tty_chars_in_buffer(struct tty_struct *tty)
 {
 	unsigned long flags;
@@ -166,20 +191,47 @@ ssize_t n_tty_chars_in_buffer(struct tty_struct *tty)
 	return n;
 }
 
+/**
+ *	is_utf8_continuation	-	utf8 multibyte check
+ *	@c: byte to check
+ *
+ *	Returns true if the utf8 character 'c' is a multibyte continuation
+ *	character. We use this to correctly compute the on screen size
+ *	of the character when printing
+ */
+ 
 static inline int is_utf8_continuation(unsigned char c)
 {
 	return (c & 0xc0) == 0x80;
 }
 
+/**
+ *	is_continuation		-	multibyte check
+ *	@c: byte to check
+ *
+ *	Returns true if the utf8 character 'c' is a multibyte continuation
+ *	character and the terminal is in unicode mode.
+ */
+ 
 static inline int is_continuation(unsigned char c, struct tty_struct *tty)
 {
 	return I_IUTF8(tty) && is_utf8_continuation(c);
 }
 
-/*
- * Perform OPOST processing.  Returns -1 when the output device is
- * full and the character must be retried.
+/**
+ *	opost			-	output post processor
+ *	@c: character (or partial unicode symbol)
+ *	@tty: terminal device
+ *
+ *	Perform OPOST processing.  Returns -1 when the output device is
+ *	full and the character must be retried. Note that Linux currently
+ *	ignores TABDLY, CRDLY, VTDLY, FFDLY and NLDLY. They simply aren't
+ *	relevant in the world today. If you ever need them, add them here.
+ *
+ *	Called from both the receive and transmit sides and can be called
+ *	re-entrantly. Relies on lock_kernel() still.
  */
+ 
 static int opost(unsigned char c, struct tty_struct *tty)
 {
 	int	space, spaces;
@@ -239,10 +291,20 @@ static int opost(unsigned char c, struct tty_struct *tty)
 	return 0;
 }
 
-/*
- * opost_block --- to speed up block console writes, among other
- * things.
+/**
+ *	opost_block		-	block postprocess
+ *	@tty: terminal device
+ *	@inbuf: user buffer
+ *	@nr: number of bytes
+ *
+ *	This path is used to speed up block console writes, among other
+ *	things when processing blocks of output data. It handles only
+ *	the simple cases normally found and helps to generate blocks of
+ *	symbols for the console driver and thus improve performance.
+ *
+ *	Called from write_chan under the tty layer write lock.
  */
+ 
 static ssize_t opost_block(struct tty_struct * tty,
 		       const unsigned char __user * inbuf, unsigned int nr)
 {
@@ -304,13 +366,27 @@ break_out:
 }
 
 
-
+/**
+ *	put_char	-	write character to driver
+ *	@c: character (or part of unicode symbol)
+ *	@tty: terminal device
+ *
+ *	Queue a byte to the driver layer for output
+ */
+ 
 static inline void put_char(unsigned char c, struct tty_struct *tty)
 {
 	tty->driver->put_char(tty, c);
 }
 
-/* Must be called only when L_ECHO(tty) is true. */
+/**
+ *	echo_char	-	echo characters
+ *	@c: unicode byte to echo
+ *	@tty: terminal device
+ *
+ *	Echo user input back onto the screen. This must be called only when 
+ *	L_ECHO(tty) is true. Called from the driver receive_buf path.
+ */
 
 static void echo_char(unsigned char c, struct tty_struct *tty)
 {
@@ -331,6 +407,16 @@ static inline void finish_erasing(struct tty_struct *tty)
 	}
 }
 
+/**
+ *	eraser		-	handle erase function
+ *	@c: character input
+ *	@tty: terminal device
+ *
+ *	Perform erase and neccessary output when an erase character is
+ *	present in the stream from the driver layer. Handles the complexities
+ *	of UTF-8 multibyte symbols.
+ */
+ 
 static void eraser(unsigned char c, struct tty_struct *tty)
 {
 	enum { ERASE, WERASE, KILL } kill_type;
@@ -463,6 +549,18 @@ static void eraser(unsigned char c, struct tty_struct *tty)
 		finish_erasing(tty);
 }
 
+/**
+ *	isig		-	handle the ISIG optio
+ *	@sig: signal
+ *	@tty: terminal
+ *	@flush: force flush
+ *
+ *	Called when a signal is being sent due to terminal input. This
+ *	may caus terminal flushing to take place according to the termios
+ *	settings and character used. Called from the driver receive_buf
+ *	path so serialized.
+ */
+ 
 static inline void isig(int sig, struct tty_struct *tty, int flush)
 {
 	if (tty->pgrp > 0)
@@ -474,6 +572,16 @@ static inline void isig(int sig, struct tty_struct *tty, int flush)
 	}
 }
 
+/**
+ *	n_tty_receive_break	-	handle break
+ *	@tty: terminal
+ *
+ *	An RS232 break event has been hit in the incoming bitstream. This
+ *	can cause a variety of events depending upon the termios settings.
+ *
+ *	Called from the receive_buf path so single threaded.
+ */
+ 
 static inline void n_tty_receive_break(struct tty_struct *tty)
 {
 	if (I_IGNBRK(tty))
@@ -490,19 +598,40 @@ static inline void n_tty_receive_break(struct tty_struct *tty)
 	wake_up_interruptible(&tty->read_wait);
 }
 
+/**
+ *	n_tty_receive_overrun	-	handle overrun reporting
+ *	@tty: terminal
+ *
+ *	Data arrived faster than we could process it. While the tty
+ *	driver has flagged this the bits that were missed are gone
+ *	forever.
+ *
+ *	Called from the receive_buf path so single threaded. Does not
+ *	need locking as num_overrun and overrun_time are function
+ *	private.
+ */
+ 
 static inline void n_tty_receive_overrun(struct tty_struct *tty)
 {
 	char buf[64];
 
 	tty->num_overrun++;
 	if (time_before(tty->overrun_time, jiffies - HZ)) {
-		printk("%s: %d input overrun(s)\n", tty_name(tty, buf),
+		printk(KERN_WARNING "%s: %d input overrun(s)\n", tty_name(tty, buf),
 		       tty->num_overrun);
 		tty->overrun_time = jiffies;
 		tty->num_overrun = 0;
 	}
 }
 
+/**
+ *	n_tty_receive_parity_error	-	error notifier
+ *	@tty: terminal device
+ *	@c: character
+ *
+ *	Process a parity error and queue the right data to indicate
+ *	the error case if neccessary. Locking as per n_tty_receive_buf.
+ */
 static inline void n_tty_receive_parity_error(struct tty_struct *tty,
 					      unsigned char c)
 {
@@ -520,6 +649,16 @@ static inline void n_tty_receive_parity_error(struct tty_struct *tty,
 	wake_up_interruptible(&tty->read_wait);
 }
 
+/**
+ *	n_tty_receive_char	-	perform processing
+ *	@tty: terminal device
+ *	@c: character
+ *
+ *	Process an individual character of input received from the driver.
+ *	This is serialized with respect to itself by the rules for the 
+ *	driver above.
+ */
+
 static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
 {
 	unsigned long flags;
@@ -711,6 +850,16 @@ send_signal:
 	put_tty_queue(c, tty);
 }	
 
+/**
+ *	n_tty_receive_room	-	receive space
+ *	@tty: terminal
+ *
+ *	Called by the driver to find out how much data it is
+ *	permitted to feed to the line discipline without any being lost
+ *	and thus to manage flow control. Not serialized. Answers for the
+ *	"instant".
+ */
+ 
 static int n_tty_receive_room(struct tty_struct *tty)
 {
 	int	left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
@@ -729,10 +878,13 @@ static int n_tty_receive_room(struct tty_struct *tty)
 	return 0;
 }
 
-/*
- * Required for the ptys, serial driver etc. since processes
- * that attach themselves to the master and rely on ASYNC
- * IO must be woken up
+/**
+ *	n_tty_write_wakeup	-	asynchronous I/O notifier
+ *	@tty: tty device
+ *
+ *	Required for the ptys, serial driver etc. since processes
+ *	that attach themselves to the master and rely on ASYNC
+ *	IO must be woken up
  */
 
 static void n_tty_write_wakeup(struct tty_struct *tty)
@@ -745,6 +897,19 @@ static void n_tty_write_wakeup(struct tty_struct *tty)
 	return;
 }
 
+/**
+ *	n_tty_receive_buf	-	data receive
+ *	@tty: terminal device
+ *	@cp: buffer
+ *	@fp: flag buffer
+ *	@count: characters
+ *
+ *	Called by the terminal driver when a block of characters has
+ *	been received. This function must be called from soft contexts
+ *	not from interrupt context. The driver is responsible for making
+ *	calls one at a time and in order (or using flush_to_ldisc)
+ */
+ 
 static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
 			      char *fp, int count)
 {
@@ -828,6 +993,18 @@ int is_ignored(int sig)
 	        current->sighand->action[sig-1].sa.sa_handler == SIG_IGN);
 }
 
+/**
+ *	n_tty_set_termios	-	termios data changed
+ *	@tty: terminal
+ *	@old: previous data
+ *
+ *	Called by the tty layer when the user changes termios flags so
+ *	that the line discipline can plan ahead. This function cannot sleep
+ *	and is protected from re-entry by the tty layer. The user is 
+ *	guaranteed that this function will not be re-entered or in progress
+ *	when the ldisc is closed.
+ */
+ 
 static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
 {
 	if (!tty)
@@ -843,7 +1020,6 @@ static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
 	    I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) ||
 	    I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) ||
 	    I_PARMRK(tty)) {
-		local_irq_disable(); // FIXME: is this safe?
 		memset(tty->process_char_map, 0, 256/8);
 
 		if (I_IGNCR(tty) || I_ICRNL(tty))
@@ -879,7 +1055,6 @@ static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
 			set_bit(SUSP_CHAR(tty), tty->process_char_map);
 		}
 		clear_bit(__DISABLED_CHAR, tty->process_char_map);
-		local_irq_enable(); // FIXME: is this safe?
 		tty->raw = 0;
 		tty->real_raw = 0;
 	} else {
@@ -893,6 +1068,16 @@ static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
 	}
 }
 
+/**
+ *	n_tty_close		-	close the ldisc for this tty
+ *	@tty: device
+ *
+ *	Called from the terminal layer when this line discipline is 
+ *	being shut down, either because of a close or becsuse of a 
+ *	discipline change. The function will not be called while other
+ *	ldisc methods are in progress.
+ */
+ 
 static void n_tty_close(struct tty_struct *tty)
 {
 	n_tty_flush_buffer(tty);
@@ -902,11 +1087,22 @@ static void n_tty_close(struct tty_struct *tty)
 	}
 }
 
+/**
+ *	n_tty_open		-	open an ldisc
+ *	@tty: terminal to open
+ *
+ *	Called when this line discipline is being attached to the 
+ *	terminal device. Can sleep. Called serialized so that no
+ *	other events will occur in parallel. No further open will occur
+ *	until a close.
+ */
+
 static int n_tty_open(struct tty_struct *tty)
 {
 	if (!tty)
 		return -EINVAL;
 
+	/* This one is ugly. Currently a malloc failure here can panic */
 	if (!tty->read_buf) {
 		tty->read_buf = alloc_buf();
 		if (!tty->read_buf)
@@ -932,14 +1128,23 @@ static inline int input_available_p(struct tty_struct *tty, int amt)
 	return 0;
 }
 
-/*
- * Helper function to speed up read_chan.  It is only called when
- * ICANON is off; it copies characters straight from the tty queue to
- * user space directly.  It can be profitably called twice; once to
- * drain the space from the tail pointer to the (physical) end of the
- * buffer, and once to drain the space from the (physical) beginning of
- * the buffer to head pointer.
+/**
+ * 	copy_from_read_buf	-	copy read data directly
+ *	@tty: terminal device
+ *	@b: user data
+ *	@nr: size of data
+ *
+ *	Helper function to speed up read_chan.  It is only called when
+ *	ICANON is off; it copies characters straight from the tty queue to
+ *	user space directly.  It can be profitably called twice; once to
+ *	drain the space from the tail pointer to the (physical) end of the
+ *	buffer, and once to drain the space from the (physical) beginning of
+ *	the buffer to head pointer.
+ *
+ *	Called under the tty->atomic_read sem and with TTY_DONT_FLIP set
+ *
  */
+ 
 static inline int copy_from_read_buf(struct tty_struct *tty,
 				      unsigned char __user **b,
 				      size_t *nr)
@@ -970,25 +1175,18 @@ static inline int copy_from_read_buf(struct tty_struct *tty,
 
 extern ssize_t redirected_tty_write(struct file *,const char *,size_t,loff_t *);
 
-static ssize_t read_chan(struct tty_struct *tty, struct file *file,
-			 unsigned char __user *buf, size_t nr)
+/**
+ *	job_control		-	check job control
+ *	@tty: tty
+ *	@file: file handle
+ *
+ *	Perform job control management checks on this file/tty descriptor
+ *	and if appropriate send any needed signals and return a negative 
+ *	error code if action should be taken.
+ */
+ 
+static int job_control(struct tty_struct *tty, struct file *file)
 {
-	unsigned char __user *b = buf;
-	DECLARE_WAITQUEUE(wait, current);
-	int c;
-	int minimum, time;
-	ssize_t retval = 0;
-	ssize_t size;
-	long timeout;
-	unsigned long flags;
-
-do_it_again:
-
-	if (!tty->read_buf) {
-		printk("n_tty_read_chan: called with read_buf == NULL?!?\n");
-		return -EIO;
-	}
-
 	/* Job control check -- must be done at start and after
 	   every sleep (POSIX.1 7.1.1.4). */
 	/* NOTE: not yet done after every sleep pending a thorough
@@ -1006,7 +1204,48 @@ do_it_again:
 			return -ERESTARTSYS;
 		}
 	}
+	return 0;
+}
+ 
+
+/**
+ *	read_chan		-	read function for tty
+ *	@tty: tty device
+ *	@file: file object
+ *	@buf: userspace buffer pointer
+ *	@nr: size of I/O
+ *
+ *	Perform reads for the line discipline. We are guaranteed that the
+ *	line discipline will not be closed under us but we may get multiple
+ *	parallel readers and must handle this ourselves. We may also get
+ *	a hangup. Always called in user context, may sleep.
+ *
+ *	This code must be sure never to sleep through a hangup.
+ */
+ 
+static ssize_t read_chan(struct tty_struct *tty, struct file *file,
+			 unsigned char __user *buf, size_t nr)
+{
+	unsigned char __user *b = buf;
+	DECLARE_WAITQUEUE(wait, current);
+	int c;
+	int minimum, time;
+	ssize_t retval = 0;
+	ssize_t size;
+	long timeout;
+	unsigned long flags;
+
+do_it_again:
+
+	if (!tty->read_buf) {
+		printk("n_tty_read_chan: called with read_buf == NULL?!?\n");
+		return -EIO;
+	}
 
+	c = job_control(tty, file);
+	if(c < 0)
+		return c;
+	
 	minimum = time = 0;
 	timeout = MAX_SCHEDULE_TIMEOUT;
 	if (!tty->icanon) {
@@ -1028,6 +1267,9 @@ do_it_again:
 		}
 	}
 
+	/*
+	 *	Internal serialization of reads.
+	 */
 	if (file->f_flags & O_NONBLOCK) {
 		if (down_trylock(&tty->atomic_read))
 			return -EAGAIN;
@@ -1177,6 +1419,21 @@ do_it_again:
 	return retval;
 }
 
+/**
+ *	write_chan		-	write function for tty
+ *	@tty: tty device
+ *	@file: file object
+ *	@buf: userspace buffer pointer
+ *	@nr: size of I/O
+ *
+ *	Write function of the terminal device. This is serialized with
+ *	respect to other write callers but not to termios changes, reads
+ *	and other such events. We must be careful with N_TTY as the receive
+ *	code will echo characters, thus calling driver write methods.
+ *
+ *	This code must be sure never to sleep through a hangup.
+ */
+ 
 static ssize_t write_chan(struct tty_struct * tty, struct file * file,
 			  const unsigned char __user * buf, size_t nr)
 {
@@ -1246,7 +1503,25 @@ break_out:
 	return (b - buf) ? b - buf : retval;
 }
 
-/* Called without the kernel lock held - fine */
+/**
+ *	normal_poll		-	poll method for N_TTY
+ *	@tty: terminal device
+ *	@file: file accessing it
+ *	@wait: poll table
+ *
+ *	Called when the line discipline is asked to poll() for data or
+ *	for special events. This code is not serialized with respect to
+ *	other events save open/close.
+ *
+ *	This code must be sure never to sleep through a hangup.
+ *	Called without the kernel lock held - fine
+ *
+ *	FIXME: if someone changes the VMIN or discipline settings for the
+ *	terminal while another process is in poll() the poll does not
+ *	recompute the new limits. Possibly set_termios should issue
+ *	a read wakeup to fix this bug.
+ */
+ 
 static unsigned int normal_poll(struct tty_struct * tty, struct file * file, poll_table *wait)
 {
 	unsigned int mask = 0;
@@ -1287,6 +1562,7 @@ struct tty_ldisc tty_ldisc_N_TTY = {
 	n_tty_ioctl,		/* ioctl */
 	n_tty_set_termios,	/* set_termios */
 	normal_poll,		/* poll */
+	NULL,			/* hangup */
 	n_tty_receive_buf,	/* receive_buf */
 	n_tty_receive_room,	/* receive_room */
 	n_tty_write_wakeup	/* write_wakeup */
diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c
index e75381ec1..f344ed315 100644
--- a/drivers/char/nwflash.c
+++ b/drivers/char/nwflash.c
@@ -60,15 +60,6 @@ static DECLARE_MUTEX(nwflash_sem);
 
 extern spinlock_t gpio_lock;
 
-/*
- * the delay routine - it is often required to let the flash "breeze"...
- */
-void flash_wait(int timeout)
-{
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(timeout);
-}
-
 static int get_flash_id(void)
 {
 	volatile unsigned int c1, c2;
@@ -401,7 +392,7 @@ static int erase_block(int nBlock)
 	/*
 	 * wait 10 ms
 	 */
-	flash_wait(HZ / 100);
+	msleep(10);
 
 	/*
 	 * wait while erasing in process (up to 10 sec)
@@ -409,7 +400,7 @@ static int erase_block(int nBlock)
 	timeout = jiffies + 10 * HZ;
 	c1 = 0;
 	while (!(c1 & 0x80) && time_before(jiffies, timeout)) {
-		flash_wait(HZ / 100);
+		msleep(10);
 		/*
 		 * read any address
 		 */
@@ -440,7 +431,7 @@ static int erase_block(int nBlock)
 	/*
 	 * just to make sure - verify if erased OK...
 	 */
-	flash_wait(HZ / 100);
+	msleep(10);
 
 	pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + (nBlock << 16)));
 
@@ -587,7 +578,7 @@ static int write_block(unsigned long p, const char __user *buf, int count)
 				/*
 				 * wait couple ms
 				 */
-				flash_wait(HZ / 100);
+				msleep(10);
 				/*
 				 * red LED == write
 				 */
@@ -612,7 +603,7 @@ static int write_block(unsigned long p, const char __user *buf, int count)
 	leds_event(led_amber_off);
 	leds_event(led_green_on);
 
-	flash_wait(HZ / 100);
+	msleep(10);
 
 	pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + p));
 
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index cb1cfb0af..5d7f21542 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/char/pcmcia/synclink_cs.c
  *
- * $Id: synclink_cs.c,v 4.22 2004/06/01 20:27:46 paulkf Exp $
+ * $Id: synclink_cs.c,v 4.26 2004/08/11 19:30:02 paulkf Exp $
  *
  * Device driver for Microgate SyncLink PC Card
  * multiprotocol serial adapter.
@@ -41,6 +41,7 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
+#include <linux/time.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/tty.h>
@@ -68,6 +69,7 @@
 #include <asm/types.h>
 #include <linux/termios.h>
 #include <linux/workqueue.h>
+#include <linux/hdlc.h>
 
 #include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
@@ -76,12 +78,8 @@
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE
-#define CONFIG_SYNCLINK_SYNCPPP 1
-#endif
-
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-#include <net/syncppp.h>
+#ifdef CONFIG_HDLC_MODULE
+#define CONFIG_HDLC 1
 #endif
 
 #define GET_USER(error,value,addr) error = get_user(value,addr)
@@ -239,12 +237,11 @@ typedef struct _mgslpc_info {
 	int netcount;
 	int dosyncppp;
 	spinlock_t netlock;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-	struct ppp_device pppdev;
-	char netname[10];
+
+#ifdef CONFIG_HDLC
 	struct net_device *netdev;
-	struct net_device_stats netstats;
 #endif
+
 } MGSLPC_INFO;
 
 #define MGSLPC_MAGIC 0x5402
@@ -262,7 +259,7 @@ typedef struct _mgslpc_info {
  *  FIXME: PPC has PVR defined in asm/reg.h.  For now we just undef it.
  */
 #undef PVR
-    
+
 #define RXFIFO  0
 #define TXFIFO  0
 #define STAR    0x20
@@ -398,18 +395,12 @@ static void tx_timeout(unsigned long context);
 
 static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg);
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-/* SPPP/HDLC stuff */
-static void mgslpc_sppp_init(MGSLPC_INFO *info);
-static void mgslpc_sppp_delete(MGSLPC_INFO *info);
-static int  mgslpc_sppp_open(struct net_device *d);
-static int  mgslpc_sppp_close(struct net_device *d);
-static void mgslpc_sppp_tx_timeout(struct net_device *d);
-static int  mgslpc_sppp_tx(struct sk_buff *skb, struct net_device *d);
-static void mgslpc_sppp_rx_done(MGSLPC_INFO *info, char *buf, int size);
-static void mgslpc_sppp_tx_done(MGSLPC_INFO *info);
-static int  mgslpc_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-struct net_device_stats *mgslpc_net_stats(struct net_device *dev);
+#ifdef CONFIG_HDLC
+#define dev_to_port(D) (dev_to_hdlc(D)->priv)
+static void hdlcdev_tx_done(MGSLPC_INFO *info);
+static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size);
+static int  hdlcdev_init(MGSLPC_INFO *info);
+static void hdlcdev_exit(MGSLPC_INFO *info);
 #endif
 
 static void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit);
@@ -453,8 +444,6 @@ static int tx_abort(MGSLPC_INFO *info);
 static int set_rxenable(MGSLPC_INFO *info, int enable);
 static int wait_events(MGSLPC_INFO *info, int __user *mask);
 
-#define jiffies_from_ms(a) ((((a) * HZ)/1000)+1)
-
 static MGSLPC_INFO *mgslpc_device_list = NULL;
 static int mgslpc_device_count = 0;
 
@@ -494,7 +483,7 @@ MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICE_COUNT) "i");
 MODULE_LICENSE("GPL");
 
 static char *driver_name = "SyncLink PC Card driver";
-static char *driver_version = "$Revision: 4.22 $";
+static char *driver_version = "$Revision: 4.26 $";
 
 static struct tty_driver *serial_driver;
 
@@ -504,10 +493,6 @@ static struct tty_driver *serial_driver;
 static void mgslpc_change_params(MGSLPC_INFO *info);
 static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout);
 
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
 /* PCMCIA prototypes */
 
 static void mgslpc_config(dev_link_t *link);
@@ -531,6 +516,40 @@ static void* mgslpc_get_text_ptr(void)
 	return mgslpc_get_text_ptr;
 }
 
+/**
+ * line discipline callback wrappers
+ *
+ * The wrappers maintain line discipline references
+ * while calling into the line discipline.
+ *
+ * ldisc_flush_buffer - flush line discipline receive buffers
+ * ldisc_receive_buf  - pass receive data to line discipline
+ */
+
+static void ldisc_flush_buffer(struct tty_struct *tty)
+{
+	struct tty_ldisc *ld = tty_ldisc_ref(tty);
+	if (ld) {
+		if (ld->flush_buffer)
+			ld->flush_buffer(tty);
+		tty_ldisc_deref(ld);
+	}
+}
+
+static void ldisc_receive_buf(struct tty_struct *tty,
+			      const __u8 *data, char *flags, int count)
+{
+	struct tty_ldisc *ld;
+	if (!tty)
+		return;
+	ld = tty_ldisc_ref(tty);
+	if (ld) {
+		if (ld->receive_buf)
+			ld->receive_buf(tty, data, flags, count);
+		tty_ldisc_deref(ld);
+	}
+}
+
 static dev_link_t *mgslpc_attach(void)
 {
     MGSLPC_INFO *info;
@@ -984,13 +1003,7 @@ void bh_transmit(MGSLPC_INFO *info)
 		printk("bh_transmit() entry on %s\n", info->device_name);
 
 	if (tty) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup) {
-			if ( debug_level >= DEBUG_LEVEL_BH )
-				printk( "%s(%d):calling ldisc.write_wakeup on %s\n",
-					__FILE__,__LINE__,info->device_name);
-			(tty->ldisc.write_wakeup)(tty);
-		}
+		tty_wakeup(tty);
 		wake_up_interruptible(&tty->write_wait);
 	}
 }
@@ -1163,9 +1176,9 @@ void tx_done(MGSLPC_INFO *info)
 		info->drop_rts_on_tx_done = 0;
 	}
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP	
+#ifdef CONFIG_HDLC
 	if (info->netcount)
-		mgslpc_sppp_tx_done(info);
+		hdlcdev_tx_done(info);
 	else 
 #endif
 	{
@@ -1201,7 +1214,7 @@ void tx_ready(MGSLPC_INFO *info)
 		return;
 
 	while (info->tx_count && fifo_count) {
-		c = MIN(2, MIN(fifo_count, MIN(info->tx_count, TXBUFSIZE - info->tx_get)));
+		c = min(2, min_t(int, fifo_count, min(info->tx_count, TXBUFSIZE - info->tx_get)));
 		
 		if (c == 1) {
 			write_reg(info, CHA + TXFIFO, *(info->tx_buf + info->tx_get));
@@ -1271,13 +1284,13 @@ void dcd_change(MGSLPC_INFO *info)
 	info->icount.dcd++;
 	if (info->serial_signals & SerialSignal_DCD) {
 		info->input_signal_events.dcd_up++;
-#ifdef CONFIG_SYNCLINK_SYNCPPP	
-		if (info->netcount)
-			sppp_reopen(info->netdev);
-#endif
 	}
 	else
 		info->input_signal_events.dcd_down++;
+#ifdef CONFIG_HDLC
+	if (info->netcount)
+		hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, info->netdev);
+#endif
 	wake_up_interruptible(&info->status_event_wait_q);
 	wake_up_interruptible(&info->event_wait_q);
 
@@ -1764,8 +1777,8 @@ static int mgslpc_write(struct tty_struct * tty, int from_user,
 	}
 
 	for (;;) {
-		c = MIN(count,
-			MIN(TXBUFSIZE - info->tx_count - 1,
+		c = min(count,
+			min(TXBUFSIZE - info->tx_count - 1,
 			    TXBUFSIZE - info->tx_put));
 		if (c <= 0)
 			break;
@@ -1875,11 +1888,9 @@ static void mgslpc_flush_buffer(struct tty_struct *tty)
 	info->tx_count = info->tx_put = info->tx_get = 0;
 	del_timer(&info->tx_timer);	
 	spin_unlock_irqrestore(&info->lock,flags);
-	
+
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /* Send a high-priority XON/XOFF character
@@ -2588,9 +2599,8 @@ static void mgslpc_close(struct tty_struct *tty, struct file * filp)
 
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-		
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+
+	ldisc_flush_buffer(tty);
 		
 	shutdown(info);
 	
@@ -2651,7 +2661,7 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout)
 		char_time = 1;
 		
 	if (timeout)
-		char_time = MIN(char_time, timeout);
+		char_time = min_t(unsigned long, char_time, timeout);
 		
 	if (info->params.mode == MGSL_MODE_HDLC) {
 		while (info->tx_active) {
@@ -2876,7 +2886,7 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
 cleanup:			
 	if (retval) {
 		if (tty->count == 1)
-			info->tty = NULL;/* tty layer will release tty struct */
+			info->tty = NULL; /* tty layer will release tty struct */
 		if(info->count)
 			info->count--;
 	}
@@ -2931,7 +2941,7 @@ static inline int line_info(char *buf, MGSLPC_INFO *info)
 		if (info->icount.rxover)
 			ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover);
 		if (info->icount.rxcrc)
-			ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxcrc);
+			ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc);
 	} else {
 		ret += sprintf(buf+ret, " ASYNC tx:%d rx:%d",
 			      info->icount.tx, info->icount.rx);
@@ -3070,12 +3080,8 @@ void mgslpc_add_device(MGSLPC_INFO *info)
 	printk( "SyncLink PC Card %s:IO=%04X IRQ=%d\n",
 		info->device_name, info->io_base, info->irq_level);
 
-
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-#ifdef MODULE
-	if (info->dosyncppp)
-#endif
-		mgslpc_sppp_init(info);
+#ifdef CONFIG_HDLC
+	hdlcdev_init(info);
 #endif
 }
 
@@ -3090,9 +3096,8 @@ void mgslpc_remove_device(MGSLPC_INFO *remove_info)
 				last->next_device = info->next_device;
 			else
 				mgslpc_device_list = info->next_device;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-			if (info->dosyncppp)
-				mgslpc_sppp_delete(info);
+#ifdef CONFIG_HDLC
+			hdlcdev_exit(info);
 #endif
 			release_resources(info);
 			kfree(info);
@@ -3669,7 +3674,7 @@ void tx_start(MGSLPC_INFO *info)
 		} else {
 			info->tx_active = 1;
 			tx_ready(info);
-			info->tx_timer.expires = jiffies + jiffies_from_ms(5000);
+			info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
 			add_timer(&info->tx_timer);	
 		}
 	}
@@ -4021,9 +4026,12 @@ int rx_get_frame(MGSLPC_INFO *info)
 				return_frame = 1;
 		}
 		framesize = 0;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-		info->netstats.rx_errors++;
-		info->netstats.rx_frame_errors++;
+#ifdef CONFIG_HDLC
+		{
+			struct net_device_stats *stats = hdlc_stats(info->netdev);
+			stats->rx_errors++;
+			stats->rx_frame_errors++;
+		}
 #endif
 	} else
 		return_frame = 1;
@@ -4052,18 +4060,12 @@ int rx_get_frame(MGSLPC_INFO *info)
 				++framesize;
 			}
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-			if (info->netcount) {
-				/* pass frame to syncppp device */
-				mgslpc_sppp_rx_done(info, buf->data, framesize);
-			} 
+#ifdef CONFIG_HDLC
+			if (info->netcount)
+				hdlcdev_rx(info, buf->data, framesize);
 			else
 #endif
-			{
-				/* Call the line discipline receive callback directly. */
-				if (tty && tty->ldisc.receive_buf)
-					tty->ldisc.receive_buf(tty, buf->data, info->flag_buf, framesize);
-			}
+				ldisc_receive_buf(tty, buf->data, info->flag_buf, framesize);
 		}
 	}
 
@@ -4128,7 +4130,7 @@ BOOLEAN irq_test(MGSLPC_INFO *info)
 	end_time=100;
 	while(end_time-- && !info->irq_occurred) {
 		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(jiffies_from_ms(10));
+		schedule_timeout(msecs_to_jiffies(10));
 	}
 	
 	info->testing_irq = FALSE;
@@ -4215,88 +4217,134 @@ void tx_timeout(unsigned long context)
 
 	spin_unlock_irqrestore(&info->lock,flags);
 	
-#ifdef CONFIG_SYNCLINK_SYNCPPP
+#ifdef CONFIG_HDLC
 	if (info->netcount)
-		mgslpc_sppp_tx_done(info);
+		hdlcdev_tx_done(info);
 	else
 #endif
 		bh_transmit(info);
 }
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-/* syncppp net device routines
+#ifdef CONFIG_HDLC
+
+/**
+ * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
+ * set encoding and frame check sequence (FCS) options
+ *
+ * dev       pointer to network device structure
+ * encoding  serial encoding setting
+ * parity    FCS setting
+ *
+ * returns 0 if success, otherwise error code
  */
- 
-static void mgslpc_setup(struct net_device *dev)
+static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
+			  unsigned short parity)
 {
-	dev->open = mgslpc_sppp_open;
-	dev->stop = mgslpc_sppp_close;
-	dev->hard_start_xmit = mgslpc_sppp_tx;
-	dev->do_ioctl = mgslpc_sppp_ioctl;
-	dev->get_stats = mgslpc_net_stats;
-	dev->tx_timeout = mgslpc_sppp_tx_timeout;
-	dev->watchdog_timeo = 10*HZ;
-}
+	MGSLPC_INFO *info = dev_to_port(dev);
+	unsigned char  new_encoding;
+	unsigned short new_crctype;
 
-void mgslpc_sppp_init(MGSLPC_INFO *info)
-{
-	struct net_device *d;
+	/* return error if TTY interface open */
+	if (info->count)
+		return -EBUSY;
 
-	sprintf(info->netname,"mgslp%d",info->line);
- 
-	d = alloc_netdev(0, info->netname, mgslpc_setup);
-	if (!d) {
-		printk(KERN_WARNING "%s: alloc_netdev failed.\n",
-						info->netname);
-		return;
+	switch (encoding)
+	{
+	case ENCODING_NRZ:        new_encoding = HDLC_ENCODING_NRZ; break;
+	case ENCODING_NRZI:       new_encoding = HDLC_ENCODING_NRZI_SPACE; break;
+	case ENCODING_FM_MARK:    new_encoding = HDLC_ENCODING_BIPHASE_MARK; break;
+	case ENCODING_FM_SPACE:   new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break;
+	case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break;
+	default: return -EINVAL;
 	}
 
-	info->if_ptr = &info->pppdev;
-	info->netdev = info->pppdev.dev = d;
-
-	d->base_addr = info->io_base;
-	d->irq = info->irq_level;
-	d->priv = info;
+	switch (parity)
+	{
+	case PARITY_NONE:            new_crctype = HDLC_CRC_NONE; break;
+	case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break;
+	case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break;
+	default: return -EINVAL;
+	}
 
-	sppp_attach(&info->pppdev);
-	mgslpc_setup(d);
+	info->params.encoding = new_encoding;
+	info->params.crc_type = new_crctype;;
 
-	if (register_netdev(d)) {
-		printk(KERN_WARNING "%s: register_netdev failed.\n", d->name);
-		sppp_detach(info->netdev);
-		info->netdev = NULL;
-		info->pppdev.dev = NULL;
-		free_netdev(d);
-		return;
-	}
+	/* if network interface up, reprogram hardware */
+	if (info->netcount)
+		mgslpc_program_hw(info);
 
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgslpc_sppp_init()\n");	
+	return 0;
 }
 
-void mgslpc_sppp_delete(MGSLPC_INFO *info)
+/**
+ * called by generic HDLC layer to send frame
+ *
+ * skb  socket buffer containing HDLC frame
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev)
 {
+	MGSLPC_INFO *info = dev_to_port(dev);
+	struct net_device_stats *stats = hdlc_stats(dev);
+	unsigned long flags;
+
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgslpc_sppp_delete(%s)\n",info->netname);	
-	unregister_netdev(info->netdev);
-	sppp_detach(info->netdev);
-	free_netdev(info->netdev);
-	info->netdev = NULL;
-	info->pppdev.dev = NULL;
+		printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name);
+
+	/* stop sending until this frame completes */
+	netif_stop_queue(dev);
+
+	/* copy data to device buffers */
+	memcpy(info->tx_buf, skb->data, skb->len);
+	info->tx_get = 0;
+	info->tx_put = info->tx_count = skb->len;
+
+	/* update network statistics */
+	stats->tx_packets++;
+	stats->tx_bytes += skb->len;
+
+	/* done with socket buffer, so free it */
+	dev_kfree_skb(skb);
+
+	/* save start time for transmit timeout detection */
+	dev->trans_start = jiffies;
+
+	/* start hardware transmitter if necessary */
+	spin_lock_irqsave(&info->lock,flags);
+	if (!info->tx_active)
+	 	tx_start(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	return 0;
 }
 
-int mgslpc_sppp_open(struct net_device *d)
+/**
+ * called by network layer when interface enabled
+ * claim resources and initialize hardware
+ *
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_open(struct net_device *dev)
 {
-	MGSLPC_INFO *info = d->priv;
-	int err;
+	MGSLPC_INFO *info = dev_to_port(dev);
+	int rc;
 	unsigned long flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgslpc_sppp_open(%s)\n",info->netname);	
+		printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name);
+
+	/* generic HDLC layer open processing */
+	if ((rc = hdlc_open(dev)))
+		return rc;
 
+	/* arbitrate between network and tty opens */
 	spin_lock_irqsave(&info->netlock, flags);
 	if (info->count != 0 || info->netcount != 0) {
-		printk(KERN_WARNING "%s: sppp_open returning busy\n", info->netname);
+		printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name);
 		spin_unlock_irqrestore(&info->netlock, flags);
 		return -EBUSY;
 	}
@@ -4304,142 +4352,297 @@ int mgslpc_sppp_open(struct net_device *d)
 	spin_unlock_irqrestore(&info->netlock, flags);
 
 	/* claim resources and init adapter */
-	if ((err = startup(info)) != 0)
-		goto open_fail;
-
-	/* allow syncppp module to do open processing */
-	if ((err = sppp_open(d)) != 0) {
-		shutdown(info);
-		goto open_fail;
+	if ((rc = startup(info)) != 0) {
+		spin_lock_irqsave(&info->netlock, flags);
+		info->netcount=0;
+		spin_unlock_irqrestore(&info->netlock, flags);
+		return rc;
 	}
 
+	/* assert DTR and RTS, apply hardware settings */
 	info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
 	mgslpc_program_hw(info);
 
-	d->trans_start = jiffies;
-	netif_start_queue(d);
-	return 0;
+	/* enable network layer transmit */
+	dev->trans_start = jiffies;
+	netif_start_queue(dev);
 
-open_fail:
-	spin_lock_irqsave(&info->netlock, flags);
-	info->netcount=0;
-	spin_unlock_irqrestore(&info->netlock, flags);
-	return err;
+	/* inform generic HDLC layer of current DCD status */
+	spin_lock_irqsave(&info->lock, flags);
+	get_signals(info);
+	spin_unlock_irqrestore(&info->lock, flags);
+	hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, dev);
+
+	return 0;
 }
 
-void mgslpc_sppp_tx_timeout(struct net_device *dev)
+/**
+ * called by network layer when interface is disabled
+ * shutdown hardware and release resources
+ *
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_close(struct net_device *dev)
 {
-	MGSLPC_INFO *info = dev->priv;
+	MGSLPC_INFO *info = dev_to_port(dev);
 	unsigned long flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgslpc_sppp_tx_timeout(%s)\n",info->netname);	
+		printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name);
 
-	info->netstats.tx_errors++;
-	info->netstats.tx_aborted_errors++;
+	netif_stop_queue(dev);
 
-	spin_lock_irqsave(&info->lock,flags);
-	tx_stop(info);
-	spin_unlock_irqrestore(&info->lock,flags);
+	/* shutdown adapter and release resources */
+	shutdown(info);
 
-	netif_wake_queue(dev);
+	hdlc_close(dev);
+
+	spin_lock_irqsave(&info->netlock, flags);
+	info->netcount=0;
+	spin_unlock_irqrestore(&info->netlock, flags);
+
+	return 0;
 }
 
-int mgslpc_sppp_tx(struct sk_buff *skb, struct net_device *dev)
+/**
+ * called by network layer to process IOCTL call to network device
+ *
+ * dev  pointer to network device structure
+ * ifr  pointer to network interface request structure
+ * cmd  IOCTL command code
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-	MGSLPC_INFO *info = dev->priv;
-	unsigned long flags;
+	const size_t size = sizeof(sync_serial_settings);
+	sync_serial_settings new_line;
+	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
+	MGSLPC_INFO *info = dev_to_port(dev);
+	unsigned int flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgslpc_sppp_tx(%s)\n",info->netname);	
+		printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name);
 
-	netif_stop_queue(dev);
+	/* return error if TTY interface open */
+	if (info->count)
+		return -EBUSY;
 
-	info->tx_count = skb->len;
+	if (cmd != SIOCWANDEV)
+		return hdlc_ioctl(dev, ifr, cmd);
 
-	memcpy(info->tx_buf, skb->data, skb->len);
-	info->tx_get = 0;
-	info->tx_put = info->tx_count = skb->len;
+	switch(ifr->ifr_settings.type) {
+	case IF_GET_IFACE: /* return current sync_serial_settings */
 
-	info->netstats.tx_packets++;
-	info->netstats.tx_bytes += skb->len;
-	dev_kfree_skb(skb);
+		ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
+		if (ifr->ifr_settings.size < size) {
+			ifr->ifr_settings.size = size; /* data size wanted */
+			return -ENOBUFS;
+		}
 
-	dev->trans_start = jiffies;
+		flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
+
+		switch (flags){
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
+		case (HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_INT; break;
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_TXINT; break;
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break;
+		default: new_line.clock_type = CLOCK_DEFAULT;
+		}
 
-	spin_lock_irqsave(&info->lock,flags);
-	if (!info->tx_active)
-	 	tx_start(info);
-	spin_unlock_irqrestore(&info->lock,flags);
+		new_line.clock_rate = info->params.clock_speed;
+		new_line.loopback   = info->params.loopback ? 1:0;
 
-	return 0;
+		if (copy_to_user(line, &new_line, size))
+			return -EFAULT;
+		return 0;
+
+	case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */
+
+		if(!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (copy_from_user(&new_line, line, size))
+			return -EFAULT;
+
+		switch (new_line.clock_type)
+		{
+		case CLOCK_EXT:      flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break;
+		case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break;
+		case CLOCK_INT:      flags = HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG;    break;
+		case CLOCK_TXINT:    flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG;    break;
+		case CLOCK_DEFAULT:  flags = info->params.flags &
+					     (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN); break;
+		default: return -EINVAL;
+		}
+
+		if (new_line.loopback != 0 && new_line.loopback != 1)
+			return -EINVAL;
+
+		info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
+		info->params.flags |= flags;
+
+		info->params.loopback = new_line.loopback;
+
+		if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG))
+			info->params.clock_speed = new_line.clock_rate;
+		else
+			info->params.clock_speed = 0;
+
+		/* if network interface up, reprogram hardware */
+		if (info->netcount)
+			mgslpc_program_hw(info);
+		return 0;
+
+	default:
+		return hdlc_ioctl(dev, ifr, cmd);
+	}
 }
 
-int mgslpc_sppp_close(struct net_device *d)
+/**
+ * called by network layer when transmit timeout is detected
+ *
+ * dev  pointer to network device structure
+ */
+static void hdlcdev_tx_timeout(struct net_device *dev)
 {
-	MGSLPC_INFO *info = d->priv;
+	MGSLPC_INFO *info = dev_to_port(dev);
+	struct net_device_stats *stats = hdlc_stats(dev);
 	unsigned long flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgslpc_sppp_close(%s)\n",info->netname);	
+		printk("hdlcdev_tx_timeout(%s)\n",dev->name);
 
-	/* shutdown adapter and release resources */
-	shutdown(info);
+	stats->tx_errors++;
+	stats->tx_aborted_errors++;
 
-	/* allow syncppp to do close processing */
-	sppp_close(d);
-	netif_stop_queue(d);
+	spin_lock_irqsave(&info->lock,flags);
+	tx_stop(info);
+	spin_unlock_irqrestore(&info->lock,flags);
 
-	spin_lock_irqsave(&info->netlock, flags);
-	info->netcount=0;
-	spin_unlock_irqrestore(&info->netlock, flags);
-	return 0;
+	netif_wake_queue(dev);
 }
 
-void mgslpc_sppp_rx_done(MGSLPC_INFO *info, char *buf, int size)
+/**
+ * called by device driver when transmit completes
+ * reenable network layer transmit if stopped
+ *
+ * info  pointer to device instance information
+ */
+static void hdlcdev_tx_done(MGSLPC_INFO *info)
+{
+	if (netif_queue_stopped(info->netdev))
+		netif_wake_queue(info->netdev);
+}
+
+/**
+ * called by device driver when frame received
+ * pass frame to network layer
+ *
+ * info  pointer to device instance information
+ * buf   pointer to buffer contianing frame data
+ * size  count of data bytes in buf
+ */
+static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size)
 {
 	struct sk_buff *skb = dev_alloc_skb(size);
+	struct net_device *dev = info->netdev;
+	struct net_device_stats *stats = hdlc_stats(dev);
+
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgslpc_sppp_rx_done(%s)\n",info->netname);	
+		printk("hdlcdev_rx(%s)\n",dev->name);
+
 	if (skb == NULL) {
-		printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n",
-			info->netname);
-		info->netstats.rx_dropped++;
+		printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", dev->name);
+		stats->rx_dropped++;
 		return;
 	}
 
 	memcpy(skb_put(skb, size),buf,size);
 
-	skb->protocol = htons(ETH_P_WAN_PPP);
-	skb->dev = info->netdev;
-	skb->mac.raw = skb->data;
-	info->netstats.rx_packets++;
-	info->netstats.rx_bytes += size;
+	skb->dev      = info->netdev;
+	skb->mac.raw  = skb->data;
+	skb->protocol = hdlc_type_trans(skb, skb->dev);
+
+	stats->rx_packets++;
+	stats->rx_bytes += size;
+
 	netif_rx(skb);
-	info->netdev->trans_start = jiffies;
-}
 
-void mgslpc_sppp_tx_done(MGSLPC_INFO *info)
-{
-	if (netif_queue_stopped(info->netdev))
-	    netif_wake_queue(info->netdev);
+	info->netdev->last_rx = jiffies;
 }
 
-struct net_device_stats *mgslpc_net_stats(struct net_device *dev)
+/**
+ * called by device driver when adding device instance
+ * do generic HDLC initialization
+ *
+ * info  pointer to device instance information
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_init(MGSLPC_INFO *info)
 {
-	MGSLPC_INFO *info = dev->priv;
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgslpc_net_stats(%s)\n",info->netname);	
-	return &info->netstats;
+	int rc;
+	struct net_device *dev;
+	hdlc_device *hdlc;
+
+	/* allocate and initialize network and HDLC layer objects */
+
+	if (!(dev = alloc_hdlcdev(info))) {
+		printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__);
+		return -ENOMEM;
+	}
+
+	/* for network layer reporting purposes only */
+	dev->base_addr = info->io_base;
+	dev->irq       = info->irq_level;
+
+	/* network layer callbacks and settings */
+	dev->do_ioctl       = hdlcdev_ioctl;
+	dev->open           = hdlcdev_open;
+	dev->stop           = hdlcdev_close;
+	dev->tx_timeout     = hdlcdev_tx_timeout;
+	dev->watchdog_timeo = 10*HZ;
+	dev->tx_queue_len   = 50;
+
+	/* generic HDLC layer callbacks and settings */
+	hdlc         = dev_to_hdlc(dev);
+	hdlc->attach = hdlcdev_attach;
+	hdlc->xmit   = hdlcdev_xmit;
+
+	/* register objects with HDLC layer */
+	if ((rc = register_hdlc_device(dev))) {
+		printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
+		free_netdev(dev);
+		return rc;
+	}
+
+	info->netdev = dev;
+	return 0;
 }
 
-int mgslpc_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+/**
+ * called by device driver when removing device instance
+ * do generic HDLC cleanup
+ *
+ * info  pointer to device instance information
+ */
+static void hdlcdev_exit(MGSLPC_INFO *info)
 {
-	MGSLPC_INFO *info = dev->priv;
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
-			info->netname, cmd );
-	return sppp_do_ioctl(dev, ifr, cmd);
+	unregister_hdlc_device(info->netdev);
+	free_netdev(info->netdev);
+	info->netdev = NULL;
 }
 
-#endif /* ifdef CONFIG_SYNCLINK_SYNCPPP */
+#endif /* CONFIG_HDLC */
+
diff --git a/drivers/char/pcxx.c b/drivers/char/pcxx.c
index e804fdc73..061237bb0 100644
--- a/drivers/char/pcxx.c
+++ b/drivers/char/pcxx.c
@@ -130,7 +130,6 @@ static struct channel    *digi_channels;
 int pcxx_ncook=sizeof(pcxx_cook);
 int pcxx_nbios=sizeof(pcxx_bios);
 
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
 #define pcxxassert(x, msg)  if(!(x)) pcxx_error(__LINE__, msg)
 
 #define FEPTIMEOUT 200000  
@@ -206,7 +205,7 @@ static void __exit pcxe_cleanup(void)
 {
 
 	unsigned long	flags;
-	int e1, e2;
+	int e1;
 
 	printk(KERN_NOTICE "Unloading PC/Xx version %s\n", VERSION);
 
@@ -223,12 +222,6 @@ static void __exit pcxe_cleanup(void)
 	restore_flags(flags);
 }
 
-/*
- * pcxe_init() is our init_module():
- */
-module_init(pcxe_init);
-module_cleanup(pcxe_cleanup);
-
 static inline struct channel *chan(register struct tty_struct *tty)
 {
 	if (tty) {
@@ -538,28 +531,11 @@ static void pcxe_close(struct tty_struct * tty, struct file * filp)
 	
 		if(tty->driver->flush_buffer)
 			tty->driver->flush_buffer(tty);
-		if(tty->ldisc.flush_buffer)
-			tty->ldisc.flush_buffer(tty);
+		tty_ldisc_flush(tty);
 		shutdown(info);
 		tty->closing = 0;
 		info->event = 0;
 		info->tty = NULL;
-#ifndef MODULE
-/* ldiscs[] is not available in a MODULE
-** worth noting that while I'm not sure what this hunk of code is supposed
-** to do, it is not present in the serial.c driver.  Hmmm.  If you know,
-** please send me a note.  brian@ilinx.com
-** Don't know either what this is supposed to do christoph@lameter.com.
-*/
-		if(tty->ldisc.num != ldiscs[N_TTY].num) {
-			if(tty->ldisc.close)
-				(tty->ldisc.close)(tty);
-			tty->ldisc = ldiscs[N_TTY];
-			tty->termios->c_line = N_TTY;
-			if(tty->ldisc.open)
-				(tty->ldisc.open)(tty);
-		}
-#endif
 		if(info->blocked_open) {
 			if(info->close_delay) {
 				current->state = TASK_INTERRUPTIBLE;
@@ -626,7 +602,7 @@ static int pcxe_write(struct tty_struct * tty, int from_user, const unsigned cha
 		
 		tail &= (size - 1);
 		stlen = (head >= tail) ? (size - (head - tail) - 1) : (tail - head - 1);
-		count = MIN(stlen, count);
+		count = min(stlen, count);
 		memoff(ch);
 		restore_flags(flags);
 
@@ -658,11 +634,11 @@ static int pcxe_write(struct tty_struct * tty, int from_user, const unsigned cha
 		remain = tail - head - 1;
 		stlen = remain;
 	}
-	count = MIN(remain, count);
+	count = min(remain, count);
 
 	txwinon(ch);
 	while (count > 0) {
-		stlen = MIN(count, stlen);
+		stlen = min(count, stlen);
 		memcpy(ch->txptr + head, buf, stlen);
 		buf += stlen;
 		count -= stlen;
@@ -800,9 +776,7 @@ static void pcxe_flush_buffer(struct tty_struct *tty)
 	memoff(ch);
 	restore_flags(flags);
 
-	wake_up_interruptible(&tty->write_wait);
-	if((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 static void pcxe_flush_chars(struct tty_struct *tty)
@@ -1013,9 +987,6 @@ void __init pcxx_setup(char *str, int *ints)
 }
 #endif
 
-module_init(pcxe_init)
-module_exit(pcxe_exit)
-
 static struct tty_operations pcxe_ops = {
 	.open = pcxe_open,
 	.close = pcxe_close,
@@ -1561,6 +1532,8 @@ cleanup_boards:
 	return ret;
 }
 
+module_init(pcxe_init)
+module_exit(pcxe_cleanup)
 
 static void pcxxpoll(unsigned long dummy)
 {
@@ -1675,10 +1648,7 @@ static void doevent(int crd)
 			if (event & LOWTX_IND) {
 				if (ch->statusflags & LOWWAIT) {
 					ch->statusflags &= ~LOWWAIT;
-					if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-						tty->ldisc.write_wakeup)
-						(tty->ldisc.write_wakeup)(tty);
-					wake_up_interruptible(&tty->write_wait);
+					tty_wakeup(tty);
 				}
 			}
 
@@ -1686,10 +1656,7 @@ static void doevent(int crd)
 				ch->statusflags &= ~TXBUSY;
 				if (ch->statusflags & EMPTYWAIT) {
 					ch->statusflags &= ~EMPTYWAIT;
-					if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-						tty->ldisc.write_wakeup)
-						(tty->ldisc.write_wakeup)(tty);
-					wake_up_interruptible(&tty->write_wait);
+					tty_wakeup(tty);
 				}
 			}
 		}
@@ -1995,6 +1962,7 @@ static int pcxe_tiocmget(struct tty_struct *tty, struct file *file)
 	volatile struct board_chan *bc;
 	unsigned long flags;
 	int mflag = 0;
+	int mstat;
 
 	if(ch)
 		bc = ch->brdchan;
@@ -2069,6 +2037,7 @@ static int pcxe_tiocmset(struct tty_struct *tty, struct file *file,
 	pcxxparam(tty,ch);
 	memoff(ch);
 	restore_flags(flags);
+	return 0;
 }
 
 
@@ -2165,8 +2134,7 @@ static int pcxe_ioctl(struct tty_struct *tty, struct file * file,
 				tty_wait_until_sent(tty, 0);
 			}
 			else {
-				if(tty->ldisc.flush_buffer)
-					tty->ldisc.flush_buffer(tty);
+				tty_ldisc_flush(tty);
 			}
 
 			/* Fall Thru */
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index fcbb32547..9826bbd0f 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -32,12 +32,6 @@
 #include <asm/bitops.h>
 #include <linux/devpts_fs.h>
 
-#if defined(CONFIG_LEGACY_PTYS) || defined(CONFIG_UNIX98_PTYS)
-
-#ifdef CONFIG_LEGACY_PTYS
-static struct tty_driver *pty_driver, *pty_slave_driver;
-#endif
-
 /* These are global because they are accessed in tty_io.c */
 #ifdef CONFIG_UNIX98_PTYS
 struct tty_driver *ptm_driver;
@@ -91,10 +85,7 @@ static void pty_unthrottle(struct tty_struct * tty)
 	if (!o_tty)
 		return;
 
-	if ((o_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    o_tty->ldisc.write_wakeup)
-		(o_tty->ldisc.write_wakeup)(o_tty);
-	wake_up_interruptible(&o_tty->write_wait);
+	tty_wakeup(o_tty);
 	set_bit(TTY_THROTTLED, &tty->flags);
 }
 
@@ -107,6 +98,10 @@ static void pty_unthrottle(struct tty_struct * tty)
  *   (2) avoid redundant copying for cases where count >> receive_room
  * N.B. Calls from user space may now return an error code instead of
  * a count.
+ *
+ * FIXME: Our pty_write method is called with our ldisc lock held but
+ * not our partners. We can't just take the other one blindly without
+ * risking deadlocks.  There is also the small matter of TTY_DONT_FLIP
  */
 static int pty_write(struct tty_struct * tty, int from_user,
 		       const unsigned char *buf, int count)
@@ -205,19 +200,6 @@ static int pty_chars_in_buffer(struct tty_struct *tty)
 	return ((count < N_TTY_BUF_SIZE/2) ? 0 : count);
 }
 
-/* 
- * Return the device number of a Unix98 PTY (only!).  This lets us open a
- * master pty with the multi-headed ptmx device, then find out which
- * one we got after it is open, with an ioctl.
- */
-#ifdef CONFIG_UNIX98_PTYS
-static int pty_get_device_number(struct tty_struct *tty, unsigned __user *value)
-{
-	unsigned int result = tty->index;
-	return put_user(result, value);
-}
-#endif
-
 /* Set the lock flag on a pty */
 static int pty_set_lock(struct tty_struct *tty, int __user * arg)
 {
@@ -231,41 +213,6 @@ static int pty_set_lock(struct tty_struct *tty, int __user * arg)
 	return 0;
 }
 
-#ifdef CONFIG_LEGACY_PTYS
-static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file,
-			 unsigned int cmd, unsigned long arg)
-{
-	if (!tty) {
-		printk("pty_ioctl called with NULL tty!\n");
-		return -EIO;
-	}
-	switch(cmd) {
-	case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
-		return pty_set_lock(tty, (int __user *) arg);
-	}
-	return -ENOIOCTLCMD;
-}
-#endif
-
-#ifdef CONFIG_UNIX98_PTYS
-static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file,
-			    unsigned int cmd, unsigned long arg)
-{
-	if (!tty) {
-		printk("pty_unix98_ioctl called with NULL tty!\n");
-		return -EIO;
-	}
-	switch(cmd) {
-	case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
-		return pty_set_lock(tty, (int __user *)arg);
-	case TIOCGPTN: /* Get PT Number */
-		return pty_get_device_number(tty, (unsigned int __user *)arg);
-	}
-
-	return -ENOIOCTLCMD;
-}
-#endif
-
 static void pty_flush_buffer(struct tty_struct *tty)
 {
 	struct tty_struct *to = tty->link;
@@ -322,42 +269,22 @@ static struct tty_operations pty_ops = {
 	.set_termios = pty_set_termios,
 };
 
-/* sysctl support for setting limits on the number of Unix98 ptys allocated.
-   Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly. */
-#ifdef CONFIG_UNIX98_PTYS
-int pty_limit = NR_UNIX98_PTY_DEFAULT;
-static int pty_limit_min = 0;
-static int pty_limit_max = NR_UNIX98_PTY_MAX;
+/* Traditional BSD devices */
+#ifdef CONFIG_LEGACY_PTYS
+static struct tty_driver *pty_driver, *pty_slave_driver;
 
-ctl_table pty_table[] = {
-	{
-		.ctl_name	= PTY_MAX,
-		.procname	= "max",
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.data		= &pty_limit,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
-		.extra1		= &pty_limit_min,
-		.extra2		= &pty_limit_max,
-	}, {
-		.ctl_name	= PTY_NR,
-		.procname	= "nr",
-		.maxlen		= sizeof(int),
-		.mode		= 0444,
-		.proc_handler	= &proc_dointvec,
-	}, {
-		.ctl_name	= 0
+static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file,
+			 unsigned int cmd, unsigned long arg)
+{
+	switch (cmd) {
+	case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
+		return pty_set_lock(tty, (int __user *) arg);
 	}
-};
-#endif
-
-/* Initialization */
+	return -ENOIOCTLCMD;
+}
 
-static int __init pty_init(void)
+static void __init legacy_pty_init(void)
 {
-#ifdef CONFIG_LEGACY_PTYS
-	/* Traditional BSD devices */
 
 	pty_driver = alloc_tty_driver(NR_PTYS);
 	if (!pty_driver)
@@ -404,11 +331,58 @@ static int __init pty_init(void)
 		panic("Couldn't register pty driver");
 	if (tty_register_driver(pty_slave_driver))
 		panic("Couldn't register pty slave driver");
+}
+#else
+static inline void legacy_pty_init(void) { }
+#endif
 
-#endif /* CONFIG_LEGACY_PTYS */
-
+/* Unix98 devices */
 #ifdef CONFIG_UNIX98_PTYS
-	/* Unix98 devices */
+/*
+ * sysctl support for setting limits on the number of Unix98 ptys allocated.
+ * Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly.
+ */
+int pty_limit = NR_UNIX98_PTY_DEFAULT;
+static int pty_limit_min = 0;
+static int pty_limit_max = NR_UNIX98_PTY_MAX;
+
+ctl_table pty_table[] = {
+	{
+		.ctl_name	= PTY_MAX,
+		.procname	= "max",
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.data		= &pty_limit,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &pty_limit_min,
+		.extra2		= &pty_limit_max,
+	}, {
+		.ctl_name	= PTY_NR,
+		.procname	= "nr",
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= &proc_dointvec,
+	}, {
+		.ctl_name	= 0
+	}
+};
+
+static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file,
+			    unsigned int cmd, unsigned long arg)
+{
+	switch (cmd) {
+	case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
+		return pty_set_lock(tty, (int __user *)arg);
+	case TIOCGPTN: /* Get PT Number */
+		return put_user(tty->index, (unsigned int __user *)arg);
+	}
+
+	return -ENOIOCTLCMD;
+}
+
+static void __init unix98_pty_init(void)
+{
 	devfs_mk_dir("pts");
 	ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX);
 	if (!ptm_driver)
@@ -455,10 +429,15 @@ static int __init pty_init(void)
 		panic("Couldn't register Unix98 pts driver");
 
 	pty_table[1].data = &ptm_driver->refcount;
-#endif /* CONFIG_UNIX98_PTYS */
+}
+#else
+static inline void unix98_pty_init(void) { }
+#endif
 
+static int __init pty_init(void)
+{
+	legacy_pty_init();
+	unix98_pty_init();
 	return 0;
 }
 module_init(pty_init);
-
-#endif /* CONFIG_LEGACY_PTYS || CONFIG_UNIX98_PTYS */
diff --git a/drivers/char/random.c b/drivers/char/random.c
index e39179f50..295e3f718 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -401,6 +401,7 @@ static struct poolinfo {
  */
 static struct entropy_store *random_state; /* The default global store */
 static struct entropy_store *sec_random_state; /* secondary store */
+static struct entropy_store *urandom_state; /* For urandom */
 static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
 static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
 
@@ -493,6 +494,7 @@ struct entropy_store {
 	/* mostly-read data: */
 	struct poolinfo poolinfo;
 	__u32		*pool;
+	const char	*name;
 
 	/* read-write data: */
 	spinlock_t lock ____cacheline_aligned_in_smp;
@@ -507,7 +509,8 @@ struct entropy_store {
  *
  * Returns an negative error if there is a problem.
  */
-static int create_entropy_store(int size, struct entropy_store **ret_bucket)
+static int create_entropy_store(int size, const char *name,
+				struct entropy_store **ret_bucket)
 {
 	struct	entropy_store	*r;
 	struct	poolinfo	*p;
@@ -538,6 +541,7 @@ static int create_entropy_store(int size, struct entropy_store **ret_bucket)
 	}
 	memset(r->pool, 0, POOLBYTES);
 	r->lock = SPIN_LOCK_UNLOCKED;
+	r->name = name;
 	*ret_bucket = r;
 	return 0;
 }
@@ -643,12 +647,8 @@ static void credit_entropy_store(struct entropy_store *r, int nbits)
 	} else {
 		r->entropy_count += nbits;
 		if (nbits)
-			DEBUG_ENT("%04d %04d : added %d bits to %s\n",
-				  random_state->entropy_count,
-				  sec_random_state->entropy_count,
-				  nbits,
-				  r == sec_random_state ? "secondary" :
-				  r == random_state ? "primary" : "unknown");
+			DEBUG_ENT("Added %d entropy credits to %s, now %d\n",
+				  nbits, r->name, r->entropy_count);
 	}
 
 	spin_unlock_irqrestore(&r->lock, flags);
@@ -781,9 +781,9 @@ static void batch_entropy_process(void *private_)
 
 /* There is one of these per entropy source */
 struct timer_rand_state {
-	__u32		last_time;
-	__s32		last_delta,last_delta2;
-	int		dont_count_entropy:1;
+	cycles_t	last_time;
+	long		last_delta,last_delta2;
+	unsigned	dont_count_entropy:1;
 };
 
 static struct timer_rand_state keyboard_timer_state;
@@ -799,37 +799,31 @@ static struct timer_rand_state *irq_timer_state[NR_IRQS];
  * The number "num" is also added to the pool - it should somehow describe
  * the type of event which just happened.  This is currently 0-255 for
  * keyboard scan codes, and 256 upwards for interrupts.
- * On the i386, this is assumed to be at most 16 bits, and the high bits
- * are used for a high-resolution timer.
  *
  */
 static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
 {
-	__u32		time;
-	__s32		delta, delta2, delta3;
+	cycles_t	time;
+	long		delta, delta2, delta3;
 	int		entropy = 0;
 
+	preempt_disable();
 	/* if over the trickle threshold, use only 1 in 4096 samples */
 	if ( random_state->entropy_count > trickle_thresh &&
 	     (__get_cpu_var(trickle_count)++ & 0xfff))
-		return;
+		goto out;
 
-#if defined (__i386__) || defined (__x86_64__)
-	if (cpu_has_tsc) {
-		__u32 high;
-		rdtsc(time, high);
-		num ^= high;
+	/*
+	 * Use get_cycles() if implemented, otherwise fall back to
+	 * jiffies.
+	 */
+	time = get_cycles();
+	if (time != 0) {
+		if (sizeof(time) > 4)
+			num ^= (u32)(time >> 32);
 	} else {
 		time = jiffies;
 	}
-#elif defined (__sparc_v9__)
-	unsigned long tick = tick_ops->get_tick();
-
-	time = (unsigned int) tick;
-	num ^= (tick >> 32UL);
-#else
-	time = jiffies;
-#endif
 
 	/*
 	 * Calculate number of bits of randomness we probably added.
@@ -868,6 +862,8 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
 		entropy = int_ln_12bits(delta);
 	}
 	batch_entropy_store(num, time, entropy);
+out:
+	preempt_enable();
 }
 
 void add_keyboard_randomness(unsigned char scancode)
@@ -1328,8 +1324,7 @@ static inline void xfer_secondary_pool(struct entropy_store *r,
 			  "(%d of %d requested)\n",
 			  random_state->entropy_count,
 			  sec_random_state->entropy_count,
-			  r == sec_random_state ? "secondary" : "unknown",
-			  bytes * 8, nbytes * 8, r->entropy_count);
+			  r->name, bytes * 8, nbytes * 8, r->entropy_count);
 
 		bytes=extract_entropy(random_state, tmp, bytes,
 				      EXTRACT_ENTROPY_LIMIT);
@@ -1373,9 +1368,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void * buf,
 	DEBUG_ENT("%04d %04d : trying to extract %d bits from %s\n",
 		  random_state->entropy_count,
 		  sec_random_state->entropy_count,
-		  nbytes * 8,
-		  r == sec_random_state ? "secondary" :
-		  r == random_state ? "primary" : "unknown");
+		  nbytes * 8, r->name);
 
 	if (flags & EXTRACT_ENTROPY_LIMIT && nbytes >= r->entropy_count / 8)
 		nbytes = r->entropy_count / 8;
@@ -1388,12 +1381,8 @@ static ssize_t extract_entropy(struct entropy_store *r, void * buf,
 	if (r->entropy_count < random_write_wakeup_thresh)
 		wake_up_interruptible(&random_write_wait);
 
-	DEBUG_ENT("%04d %04d : debiting %d bits from %s%s\n",
-		  random_state->entropy_count,
-		  sec_random_state->entropy_count,
-		  nbytes * 8,
-		  r == sec_random_state ? "secondary" :
-		  r == random_state ? "primary" : "unknown",
+	DEBUG_ENT("Debiting %d entropy credits from %s%s\n",
+		  nbytes * 8, r->name,
 		  flags & EXTRACT_ENTROPY_LIMIT ? "" : " (unlimited)");
 
 	spin_unlock_irqrestore(&r->lock, cpuflags);
@@ -1482,14 +1471,21 @@ static ssize_t extract_entropy(struct entropy_store *r, void * buf,
  */
 void get_random_bytes(void *buf, int nbytes)
 {
-	if (sec_random_state)  
-		extract_entropy(sec_random_state, (char *) buf, nbytes, 
-				EXTRACT_ENTROPY_SECONDARY);
-	else if (random_state)
-		extract_entropy(random_state, (char *) buf, nbytes, 0);
-	else
+	struct entropy_store *r = urandom_state;
+	int flags = EXTRACT_ENTROPY_SECONDARY;
+
+	if (!r)
+		r = sec_random_state;
+	if (!r) {
+		r = random_state;
+		flags = 0;
+	}
+	if (!r) {
 		printk(KERN_NOTICE "get_random_bytes called before "
 				   "random driver initialization\n");
+		return;
+	}
+	extract_entropy(r, (char *) buf, nbytes, flags);
 }
 
 EXPORT_SYMBOL(get_random_bytes);
@@ -1533,15 +1529,22 @@ static int __init rand_initialize(void)
 {
 	int i;
 
-	if (create_entropy_store(DEFAULT_POOL_SIZE, &random_state))
+	if (create_entropy_store(DEFAULT_POOL_SIZE, "primary", &random_state))
 		goto err;
 	if (batch_entropy_init(BATCH_ENTROPY_SIZE, random_state))
 		goto err;
-	if (create_entropy_store(SECONDARY_POOL_SIZE, &sec_random_state))
+	if (create_entropy_store(SECONDARY_POOL_SIZE, "secondary",
+				 &sec_random_state))
+		goto err;
+	if (create_entropy_store(SECONDARY_POOL_SIZE, "urandom",
+				 &urandom_state))
 		goto err;
 	clear_entropy_store(random_state);
 	clear_entropy_store(sec_random_state);
+	clear_entropy_store(urandom_state);
 	init_std_data(random_state);
+	init_std_data(sec_random_state);
+	init_std_data(urandom_state);
 #ifdef CONFIG_SYSCTL
 	sysctl_init_random(random_state);
 #endif
@@ -1674,9 +1677,15 @@ static ssize_t
 urandom_read(struct file * file, char __user * buf,
 		      size_t nbytes, loff_t *ppos)
 {
-	return extract_entropy(sec_random_state, buf, nbytes,
-			       EXTRACT_ENTROPY_USER |
-			       EXTRACT_ENTROPY_SECONDARY);
+	int flags = EXTRACT_ENTROPY_USER;
+	unsigned long cpuflags;
+
+	spin_lock_irqsave(&random_state->lock, cpuflags);
+	if (random_state->entropy_count > random_state->poolinfo.POOLBITS)
+		flags |= EXTRACT_ENTROPY_SECONDARY;
+	spin_unlock_irqrestore(&random_state->lock, cpuflags);
+
+	return extract_entropy(urandom_state, buf, nbytes, flags);
 }
 
 static unsigned int
@@ -1730,10 +1739,9 @@ static int
 random_ioctl(struct inode * inode, struct file * file,
 	     unsigned int cmd, unsigned long arg)
 {
-	int *tmp, size, ent_count;
+	int size, ent_count;
 	int __user *p = (int __user *)arg;
 	int retval;
-	unsigned long flags;
 	
 	switch (cmd) {
 	case RNDGETENTCNT:
@@ -1754,40 +1762,6 @@ random_ioctl(struct inode * inode, struct file * file,
 		if (random_state->entropy_count >= random_read_wakeup_thresh)
 			wake_up_interruptible(&random_read_wait);
 		return 0;
-	case RNDGETPOOL:
-		if (!capable(CAP_SYS_ADMIN))
-			return -EPERM;
-		if (get_user(size, p) ||
-		    put_user(random_state->poolinfo.poolwords, p++))
-			return -EFAULT;
-		if (size < 0)
-			return -EFAULT;
-		if (size > random_state->poolinfo.poolwords)
-			size = random_state->poolinfo.poolwords;
-
-		/* prepare to atomically snapshot pool */
-
-		tmp = kmalloc(size * sizeof(__u32), GFP_KERNEL);
-
-		if (!tmp)
-			return -ENOMEM;
-
-		spin_lock_irqsave(&random_state->lock, flags);
-		ent_count = random_state->entropy_count;
-		memcpy(tmp, random_state->pool, size * sizeof(__u32));
-		spin_unlock_irqrestore(&random_state->lock, flags);
-
-		if (!copy_to_user(p, tmp, size * sizeof(__u32))) {
-			kfree(tmp);
-			return -EFAULT;
-		}
-
-		kfree(tmp);
-
-		if(put_user(ent_count, p++))
-			return -EFAULT;
-
-		return 0;
 	case RNDADDENTROPY:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
@@ -1884,7 +1858,8 @@ static int change_poolsize(int poolsize)
 	struct entropy_store	*new_store, *old_store;
 	int			ret;
 	
-	if ((ret = create_entropy_store(poolsize, &new_store)))
+	if ((ret = create_entropy_store(poolsize, random_state->name,
+					&new_store)))
 		return ret;
 
 	add_entropy_words(new_store, random_state->pool,
@@ -2212,7 +2187,7 @@ static __u32 twothirdsMD4Transform (__u32 const buf[4], __u32 const in[12])
 #undef K3
 
 /* This should not be decreased so low that ISNs wrap too fast. */
-#define REKEY_INTERVAL	300
+#define REKEY_INTERVAL	(300*HZ)
 /*
  * Bit layout of the tcp sequence numbers (before adding current time):
  * bit 24-31: increased after every key exchange
@@ -2238,43 +2213,55 @@ static __u32 twothirdsMD4Transform (__u32 const buf[4], __u32 const in[12])
 #define HASH_MASK	( (1<<HASH_BITS)-1 )
 
 static struct keydata {
-	time_t rekey_time;
 	__u32	count;		// already shifted to the final position
 	__u32	secret[12];
 } ____cacheline_aligned ip_keydata[2];
 
-static spinlock_t ip_lock = SPIN_LOCK_UNLOCKED;
 static unsigned int ip_cnt;
 
-static struct keydata *__check_and_rekey(time_t time)
+static void rekey_seq_generator(void *private_);
+
+static DECLARE_WORK(rekey_work, rekey_seq_generator, NULL);
+
+/*
+ * Lock avoidance:
+ * The ISN generation runs lockless - it's just a hash over random data.
+ * State changes happen every 5 minutes when the random key is replaced.
+ * Synchronization is performed by having two copies of the hash function
+ * state and rekey_seq_generator always updates the inactive copy.
+ * The copy is then activated by updating ip_cnt.
+ * The implementation breaks down if someone blocks the thread
+ * that processes SYN requests for more than 5 minutes. Should never
+ * happen, and even if that happens only a not perfectly compliant
+ * ISN is generated, nothing fatal.
+ */
+static void rekey_seq_generator(void *private_)
 {
-	struct keydata *keyptr;
-	spin_lock_bh(&ip_lock);
-	keyptr = &ip_keydata[ip_cnt&1];
-	if (!keyptr->rekey_time || (time - keyptr->rekey_time) > REKEY_INTERVAL) {
-		keyptr = &ip_keydata[1^(ip_cnt&1)];
-		keyptr->rekey_time = time;
-		get_random_bytes(keyptr->secret, sizeof(keyptr->secret));
-		keyptr->count = (ip_cnt&COUNT_MASK)<<HASH_BITS;
-		mb();
-		ip_cnt++;
-	}
-	spin_unlock_bh(&ip_lock);
-	return keyptr;
+	struct keydata *keyptr = &ip_keydata[1^(ip_cnt&1)];
+
+	get_random_bytes(keyptr->secret, sizeof(keyptr->secret));
+	keyptr->count = (ip_cnt&COUNT_MASK)<<HASH_BITS;
+	smp_wmb();
+	ip_cnt++;
+	schedule_delayed_work(&rekey_work, REKEY_INTERVAL);
 }
 
-static inline struct keydata *check_and_rekey(time_t time)
+static inline struct keydata *get_keyptr(void)
 {
 	struct keydata *keyptr = &ip_keydata[ip_cnt&1];
 
-	rmb();
-	if (!keyptr->rekey_time || (time - keyptr->rekey_time) > REKEY_INTERVAL) {
-		keyptr = __check_and_rekey(time);
-	}
+	smp_rmb();
 
 	return keyptr;
 }
 
+static __init int seqgen_init(void)
+{
+	rekey_seq_generator(NULL);
+	return 0;
+}
+late_initcall(seqgen_init);
+
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
 				   __u16 sport, __u16 dport)
@@ -2282,14 +2269,12 @@ __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
 	struct timeval 	tv;
 	__u32		seq;
 	__u32		hash[12];
-	struct keydata *keyptr;
+	struct keydata *keyptr = get_keyptr();
 
 	/* The procedure is the same as for IPv4, but addresses are longer.
 	 * Thus we must use twothirdsMD4Transform.
 	 */
 
-	do_gettimeofday(&tv);	/* We need the usecs below... */
-	keyptr = check_and_rekey(tv.tv_sec);
 
 	memcpy(hash, saddr, 16);
 	hash[4]=(sport << 16) + dport;
@@ -2297,38 +2282,22 @@ __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
 
 	seq = twothirdsMD4Transform(daddr, hash) & HASH_MASK;
 	seq += keyptr->count;
+
+	do_gettimeofday(&tv);
 	seq += tv.tv_usec + tv.tv_sec*1000000;
 
 	return seq;
 }
 EXPORT_SYMBOL(secure_tcpv6_sequence_number);
-
-__u32 secure_ipv6_id(__u32 *daddr)
-{
-	struct keydata *keyptr;
-
-	keyptr = check_and_rekey(get_seconds());
-
-	return halfMD4Transform(daddr, keyptr->secret);
-}
-
-EXPORT_SYMBOL(secure_ipv6_id);
 #endif
 
-
 __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
 				 __u16 sport, __u16 dport)
 {
 	struct timeval 	tv;
 	__u32		seq;
 	__u32	hash[4];
-	struct keydata *keyptr;
-
-	/*
-	 * Pick a random secret every REKEY_INTERVAL seconds.
-	 */
-	do_gettimeofday(&tv);	/* We need the usecs below... */
-	keyptr = check_and_rekey(tv.tv_sec);
+	struct keydata *keyptr = get_keyptr();
 
 	/*
 	 *  Pick a unique starting offset for each TCP connection endpoints
@@ -2351,6 +2320,7 @@ __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
 	 *	That's funny, Linux has one built in!  Use it!
 	 *	(Networks are faster now - should this be increased?)
 	 */
+	do_gettimeofday(&tv);
 	seq += tv.tv_usec + tv.tv_sec*1000000;
 #if 0
 	printk("init_seq(%lx, %lx, %d, %d) = %d\n",
@@ -2369,7 +2339,7 @@ __u32 secure_ip_id(__u32 daddr)
 	struct keydata *keyptr;
 	__u32 hash[4];
 
-	keyptr = check_and_rekey(get_seconds());
+	keyptr = get_keyptr();
 
 	/*
 	 *  Pick a unique starting offset for each IP destination.
diff --git a/drivers/char/rio/linux_compat.h b/drivers/char/rio/linux_compat.h
index 26063cb6a..d53843abe 100644
--- a/drivers/char/rio/linux_compat.h
+++ b/drivers/char/rio/linux_compat.h
@@ -16,7 +16,7 @@
  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <asm/hardirq.h>
+#include <linux/interrupt.h>
 
 
 #define disable(oldspl) save_flags (oldspl)
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index a11fafbab..0cc02371a 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -1138,8 +1138,8 @@ static int __init rio_init(void)
       hp->Ivec = pdev->irq;
       if (((1 << hp->Ivec) & rio_irqmask) == 0)
               hp->Ivec = 0;
-      hp->CardP	= (struct DpRam *)
       hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+      hp->CardP	= (struct DpRam *) hp->Caddr;
       hp->Type  = RIO_PCI;
       hp->Copy  = rio_pcicopy; 
       hp->Mode  = RIO_PCI_BOOT_FROM_RAM;
@@ -1196,8 +1196,8 @@ static int __init rio_init(void)
       if (((1 << hp->Ivec) & rio_irqmask) == 0) 
       	hp->Ivec = 0;
       hp->Ivec |= 0x8000; /* Mark as non-sharable */
-      hp->CardP	= (struct DpRam *)
       hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+      hp->CardP	= (struct DpRam *) hp->Caddr;
       hp->Type  = RIO_PCI;
       hp->Copy  = rio_pcicopy;
       hp->Mode  = RIO_PCI_BOOT_FROM_RAM;
@@ -1242,8 +1242,8 @@ static int __init rio_init(void)
     hp->PaddrP = rio_probe_addrs[i];
     /* There was something about the IRQs of these cards. 'Forget what.--REW */
     hp->Ivec = 0;
-    hp->CardP = (struct DpRam *)
     hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+    hp->CardP = (struct DpRam *) hp->Caddr;
     hp->Type = RIO_AT;
     hp->Copy = rio_pcicopy; /* AT card PCI???? - PVDL
                              * -- YES! this is now a normal copy. Only the 
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index 69108ceea..a35ea03a3 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -75,10 +75,6 @@
 	 ASYNC_SPD_HI       | ASYNC_SPEED_VHI    | ASYNC_SESSION_LOCKOUT | \
 	 ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP)
 
-#ifndef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
 #define RS_EVENT_WRITE_WAKEUP	0
 
 static struct riscom_board * IRQ_to_board[16];
@@ -107,7 +103,7 @@ static struct riscom_board rc_board[RC_NBOARD] =  {
 };
 
 static struct riscom_port rc_port[RC_NBOARD * RC_NPORT];
-		
+
 /* RISCom/8 I/O ports addresses (without address translation) */
 static unsigned short rc_ioport[] =  {
 #if 1	
@@ -483,7 +479,7 @@ static inline void rc_transmit(struct riscom_board const * bp)
 				rc_out(bp, CD180_TDR, CD180_C_SBRK);
 				port->COR2 &= ~COR2_ETC;
 			}
-			count = MIN(port->break_length, 0xff);
+			count = min_t(int, port->break_length, 0xff);
 			rc_out(bp, CD180_TDR, CD180_C_ESC);
 			rc_out(bp, CD180_TDR, CD180_C_DELAY);
 			rc_out(bp, CD180_TDR, count);
@@ -1127,8 +1123,8 @@ static void rc_close(struct tty_struct * tty, struct file * filp)
 	rc_shutdown_port(bp, port);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
+
 	tty->closing = 0;
 	port->event = 0;
 	port->tty = NULL;
@@ -1165,8 +1161,8 @@ static int rc_write(struct tty_struct * tty, int from_user,
 		down(&tmp_buf_sem);
 		while (1) {
 			cli();		
-			c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-					   SERIAL_XMIT_SIZE - port->xmit_head));
+			c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+						  SERIAL_XMIT_SIZE - port->xmit_head));
 			if (c <= 0)
 				break;
 
@@ -1178,8 +1174,8 @@ static int rc_write(struct tty_struct * tty, int from_user,
 			}
 
 			cli();
-			c = MIN(c, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-				       SERIAL_XMIT_SIZE - port->xmit_head));
+			c = min_t(int, c, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+					 SERIAL_XMIT_SIZE - port->xmit_head));
 			memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c);
 			port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
 			port->xmit_cnt += c;
@@ -1193,8 +1189,8 @@ static int rc_write(struct tty_struct * tty, int from_user,
 	} else {
 		while (1) {
 			cli();		
-			c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-					   SERIAL_XMIT_SIZE - port->xmit_head));
+			c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+						  SERIAL_XMIT_SIZE - port->xmit_head));
 			if (c <= 0) {
 				restore_flags(flags);
 				break;
@@ -1301,9 +1297,7 @@ static void rc_flush_buffer(struct tty_struct *tty)
 	restore_flags(flags);
 	
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 static int rc_tiocmget(struct tty_struct *tty, struct file *file)
@@ -1644,9 +1638,7 @@ static void do_softint(void *private_)
 		return;
 
 	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
+		tty_wakeup(tty);
 		wake_up_interruptible(&tty->write_wait);
 	}
 }
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 129b8ccd8..72af1bec9 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -250,12 +250,16 @@ static void rp_do_receive(struct r_port *info,
 			  CHANNEL_t * cp, unsigned int ChanStatus)
 {
 	unsigned int CharNStat;
-	int ToRecv, wRecv, space, count;
+	int ToRecv, wRecv, space = 0, count;
 	unsigned char *cbuf;
 	char *fbuf;
+	struct tty_ldisc *ld;
+
+	ld = tty_ldisc_ref(tty);
 
 	ToRecv = sGetRxCnt(cp);
-	space = tty->ldisc.receive_room(tty);
+	if (ld)
+		space = ld->receive_room(tty);
 	if (space > 2 * TTY_FLIPBUF_SIZE)
 		space = 2 * TTY_FLIPBUF_SIZE;
 	cbuf = tty->flip.char_buf;
@@ -354,7 +358,8 @@ static void rp_do_receive(struct r_port *info,
 		count += ToRecv;
 	}
 	/*  Push the data up to the tty layer */
-	tty->ldisc.receive_buf(tty, tty->flip.char_buf, tty->flip.flag_buf, count);
+	ld->receive_buf(tty, tty->flip.char_buf, tty->flip.flag_buf, count);
+	tty_ldisc_deref(ld);
 }
 
 /*
@@ -389,7 +394,7 @@ static void rp_do_transmit(struct r_port *info)
 	while (1) {
 		if (tty->stopped || tty->hw_stopped)
 			break;
-		c = MIN(info->xmit_fifo_room, MIN(info->xmit_cnt, XMIT_BUF_SIZE - info->xmit_tail));
+		c = min(info->xmit_fifo_room, min(info->xmit_cnt, XMIT_BUF_SIZE - info->xmit_tail));
 		if (c <= 0 || info->xmit_fifo_room <= 0)
 			break;
 		sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) (info->xmit_buf + info->xmit_tail), c / 2);
@@ -408,8 +413,7 @@ static void rp_do_transmit(struct r_port *info)
 		clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
 
 	if (info->xmit_cnt < WAKEUP_CHARS) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup) (tty);
+		tty_wakeup(tty);
 		wake_up_interruptible(&tty->write_wait);
 #ifdef ROCKETPORT_HAVE_POLL_WAIT
 		wake_up_interruptible(&tty->poll_wait);
@@ -1022,7 +1026,7 @@ static void rp_close(struct tty_struct *tty, struct file *filp)
 	unsigned long flags;
 	int timeout;
 	CHANNEL_t *cp;
-
+	
 	if (rocket_paranoia_check(info, "rp_close"))
 		return;
 
@@ -1101,8 +1105,8 @@ static void rp_close(struct tty_struct *tty, struct file *filp)
 
 	if (TTY_DRIVER_FLUSH_BUFFER_EXISTS(tty))
 		TTY_DRIVER_FLUSH_BUFFER(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+		
+	tty_ldisc_flush(tty);
 
 	clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
 
@@ -1283,11 +1287,7 @@ static int set_config(struct r_port *info, struct rocket_config __user *new_info
 	if (copy_from_user(&new_serial, new_info, sizeof (new_serial)))
 		return -EFAULT;
 
-#ifdef CAP_SYS_ADMIN
 	if (!capable(CAP_SYS_ADMIN))
-#else
-	if (!suser())
-#endif
 	{
 		if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK))
 			return -EPERM;
@@ -1662,7 +1662,7 @@ static int rp_write(struct tty_struct *tty, int from_user,
 	 *  into FIFO.  Use the write queue for temp storage.
          */
 	if (!tty->stopped && !tty->hw_stopped && info->xmit_cnt == 0 && info->xmit_fifo_room > 0) {
-		c = MIN(count, info->xmit_fifo_room);
+		c = min(count, info->xmit_fifo_room);
 		b = buf;
 		if (from_user) {
 			if (copy_from_user(info->xmit_buf, buf, c)) {
@@ -1672,7 +1672,7 @@ static int rp_write(struct tty_struct *tty, int from_user,
 			if (info->tty == 0)
 				goto end;
 			b = info->xmit_buf;
-			c = MIN(c, info->xmit_fifo_room);
+			c = min(c, info->xmit_fifo_room);
 		}
 
 		/*  Push data into FIFO, 2 bytes at a time */
@@ -1700,7 +1700,7 @@ static int rp_write(struct tty_struct *tty, int from_user,
 		if (info->tty == 0)	/*   Seemingly obligatory check... */
 			goto end;
 
-		c = MIN(count, MIN(XMIT_BUF_SIZE - info->xmit_cnt - 1, XMIT_BUF_SIZE - info->xmit_head));
+		c = min(count, min(XMIT_BUF_SIZE - info->xmit_cnt - 1, XMIT_BUF_SIZE - info->xmit_head));
 		if (c <= 0)
 			break;
 
@@ -1731,8 +1731,7 @@ end_intr:
 	
 end:
  	if (info->xmit_cnt < WAKEUP_CHARS) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))  && tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup) (tty);
+ 		tty_wakeup(tty);
 		wake_up_interruptible(&tty->write_wait);
 #ifdef ROCKETPORT_HAVE_POLL_WAIT
 		wake_up_interruptible(&tty->poll_wait);
@@ -1806,8 +1805,7 @@ static void rp_flush_buffer(struct tty_struct *tty)
 #ifdef ROCKETPORT_HAVE_POLL_WAIT
 	wake_up_interruptible(&tty->poll_wait);
 #endif
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup) (tty);
+	tty_wakeup(tty);
 
 	cp = &info->channel;
 	sFlushTxFIFO(cp);
diff --git a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h
index 9380ff53f..802687290 100644
--- a/drivers/char/rocket_int.h
+++ b/drivers/char/rocket_int.h
@@ -1241,10 +1241,6 @@ struct r_port {
 #define TTY_ROCKET_MAJOR	46
 #define CUA_ROCKET_MAJOR	47
 
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
 #ifdef PCI_VENDOR_ID_RP
 #undef PCI_VENDOR_ID_RP
 #undef PCI_DEVICE_ID_RP8OCTA
diff --git a/drivers/char/selection.c b/drivers/char/selection.c
index 598f60110..4675eda44 100644
--- a/drivers/char/selection.c
+++ b/drivers/char/selection.c
@@ -26,10 +26,6 @@
 #include <linux/tiocl.h>
 #include <linux/console.h>
 
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
 /* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */
 #define isspace(c)	((c) == ' ')
 
@@ -281,12 +277,15 @@ int paste_selection(struct tty_struct *tty)
 {
 	struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
 	int	pasted = 0, count;
+	struct  tty_ldisc *ld;
 	DECLARE_WAITQUEUE(wait, current);
 
 	acquire_console_sem();
 	poke_blanked_console();
 	release_console_sem();
 
+	ld = tty_ldisc_ref_wait(tty);
+	
 	add_wait_queue(&vt->paste_wait, &wait);
 	while (sel_buffer && sel_buffer_lth > pasted) {
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -295,12 +294,14 @@ int paste_selection(struct tty_struct *tty)
 			continue;
 		}
 		count = sel_buffer_lth - pasted;
-		count = MIN(count, tty->ldisc.receive_room(tty));
+		count = min(count, tty->ldisc.receive_room(tty));
 		tty->ldisc.receive_buf(tty, sel_buffer + pasted, NULL, count);
 		pasted += count;
 	}
 	remove_wait_queue(&vt->paste_wait, &wait);
 	current->state = TASK_RUNNING;
+
+	tty_ldisc_deref(ld);
 	return 0;
 }
 
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c
index f0b966876..6b4e9d155 100644
--- a/drivers/char/ser_a2232.c
+++ b/drivers/char/ser_a2232.c
@@ -599,10 +599,7 @@ int ch, err, n, p;
 					
 				/* WakeUp if output buffer runs low */
 				if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) {
-					if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && port->gs.tty->ldisc.write_wakeup){
-						(port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
-					}
-					wake_up_interruptible(&port->gs.tty->write_wait);
+					tty_wakeup(port->gs.tty);
 				}
 			} // if the port is used
 		} // for every port on the board
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
index 1b51eecfb..885621edb 100644
--- a/drivers/char/serial167.c
+++ b/drivers/char/serial167.c
@@ -83,10 +83,6 @@
 #undef  CYCLOM_16Y_HACK
 #define  CYCLOM_ENABLE_MONITORING
 
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
 #define WAKEUP_CHARS 256
 
 #define STD_COM_FLAGS (0)
@@ -760,11 +756,7 @@ do_softint(void *private_)
 	wake_up_interruptible(&info->open_wait);
     }
     if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) {
-	if((tty->flags & (1<< TTY_DO_WRITE_WAKEUP))
-	&& tty->ldisc.write_wakeup){
-	    (tty->ldisc.write_wakeup)(tty);
-	}
-	wake_up_interruptible(&tty->write_wait);
+    	tty_wakeup(tty);
     }
 } /* do_softint */
 
@@ -1238,8 +1230,8 @@ cy_write(struct tty_struct * tty, int from_user,
     if (from_user) {
 	    down(&tmp_buf_sem);
 	    while (1) {
-		    c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-				       SERIAL_XMIT_SIZE - info->xmit_head));
+		    c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+					      SERIAL_XMIT_SIZE - info->xmit_head));
 		    if (c <= 0)
 			    break;
 
@@ -1251,8 +1243,8 @@ cy_write(struct tty_struct * tty, int from_user,
 		    }
 
 		    local_irq_save(flags);
-		    c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-				   SERIAL_XMIT_SIZE - info->xmit_head));
+		    c = min_t(int, c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+					  SERIAL_XMIT_SIZE - info->xmit_head));
 		    memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
 		    info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
 		    info->xmit_cnt += c;
@@ -1266,8 +1258,8 @@ cy_write(struct tty_struct * tty, int from_user,
     } else {
 	    while (1) {
 		    local_irq_save(flags);
-		    c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-				       SERIAL_XMIT_SIZE - info->xmit_head));
+		    c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+					      SERIAL_XMIT_SIZE - info->xmit_head));
 		    if (c <= 0) {
 			    local_irq_restore(flags);
 			    break;
@@ -1343,10 +1335,7 @@ cy_flush_buffer(struct tty_struct *tty)
     local_irq_save(flags);
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
     local_irq_restore(flags);
-    wake_up_interruptible(&tty->write_wait);
-    if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
-    && tty->ldisc.write_wakeup)
-	(tty->ldisc.write_wakeup)(tty);
+    tty_wakeup(tty);
 } /* cy_flush_buffer */
 
 
@@ -1846,18 +1835,9 @@ cy_close(struct tty_struct * tty, struct file * filp)
     shutdown(info);
     if (tty->driver->flush_buffer)
 	tty->driver->flush_buffer(tty);
-    if (tty->ldisc.flush_buffer)
-	tty->ldisc.flush_buffer(tty);
+    tty_ldisc_flush(tty);
     info->event = 0;
     info->tty = 0;
-    if (tty->ldisc.num != ldiscs[N_TTY].num) {
-	if (tty->ldisc.close)
-	    (tty->ldisc.close)(tty);
-	tty->ldisc = ldiscs[N_TTY];
-	tty->termios->c_line = N_TTY;
-	if (tty->ldisc.open)
-	    (tty->ldisc.open)(tty);
-    }
     if (info->blocked_open) {
 	if (info->close_delay) {
 	    current->state = TASK_INTERRUPTIBLE;
@@ -2379,7 +2359,7 @@ scrn[1] = '\0';
                                        | CyPARITY| CyFRAME| CyOVERRUN;
 		/* info->timeout */
 
-		printk("ttyS%1d ", info->line);
+		printk("ttyS%d ", info->line);
 		port_num++;info++;
 		if(!(port_num & 7)){
 		    printk("\n               ");
diff --git a/drivers/char/serial_tx3912.c b/drivers/char/serial_tx3912.c
index 39717ed68..50ed6dfec 100644
--- a/drivers/char/serial_tx3912.c
+++ b/drivers/char/serial_tx3912.c
@@ -191,12 +191,9 @@ static inline void transmit_char_pio(struct rs_port *port)
 	}
 	
         if (port->gs.xmit_cnt <= port->gs.wakeup_chars) {
-                if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-                    port->gs.tty->ldisc.write_wakeup)
-                        (port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
+        	tty_wakeup(port->gs.tty);
                 rs_dprintk (TX3912_UART_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
                             port->gs.wakeup_chars); 
-                wake_up_interruptible(&port->gs.tty->write_wait);
        	}	
 }
 
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 28418d57f..aa7c91d6f 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -50,12 +50,13 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
+static int verbose; /* = 0 */
+
 #include "sonypi.h"
 #include <linux/sonypi.h>
 
 static struct sonypi_device sonypi_device;
 static int minor = -1;
-static int verbose; /* = 0 */
 static int fnkeyinit; /* = 0 */
 static int camera; /* = 0 */
 static int compat; /* = 0 */
@@ -66,7 +67,7 @@ static unsigned long mask = 0xffffffff;
 static inline void sonypi_initq(void) {
         sonypi_device.queue.head = sonypi_device.queue.tail = 0;
 	sonypi_device.queue.len = 0;
-	sonypi_device.queue.s_lock = (spinlock_t)SPIN_LOCK_UNLOCKED;
+	sonypi_device.queue.s_lock = SPIN_LOCK_UNLOCKED;
 	init_waitqueue_head(&sonypi_device.queue.proc_list);
 }
 
diff --git a/drivers/char/sonypi.h b/drivers/char/sonypi.h
index 0eb8f46ab..58bbf385b 100644
--- a/drivers/char/sonypi.h
+++ b/drivers/char/sonypi.h
@@ -401,8 +401,6 @@ struct sonypi_device {
 #define SONYPI_ACPI_ACTIVE 0
 #endif /* CONFIG_ACPI */
 
-extern int verbose;
-
 static inline int sonypi_ec_write(u8 addr, u8 value) {
 #ifdef CONFIG_ACPI_EC
 	if (SONYPI_ACPI_ACTIVE)
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index 0d3763dc6..bf82f06d4 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -135,10 +135,6 @@
 	 ASYNC_SPD_HI       | ASYNC_SPEED_VHI    | ASYNC_SESSION_LOCKOUT | \
 	 ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP)
 
-#ifndef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
 #undef RS_EVENT_WRITE_WAKEUP
 #define RS_EVENT_WRITE_WAKEUP	0
 
@@ -159,7 +155,7 @@ static struct specialix_board sx_board[SX_NBOARD] =  {
 };
 
 static struct specialix_port sx_port[SX_NBOARD * SX_NPORT];
-		
+
 
 #ifdef SPECIALIX_TIMER
 static struct timer_list missed_irq_timer;
@@ -715,7 +711,7 @@ static inline void sx_transmit(struct specialix_board * bp)
 				sx_out(bp, CD186x_TDR, CD186x_C_SBRK);
 				port->COR2 &= ~COR2_ETC;
 			}
-			count = MIN(port->break_length, 0xff);
+			count = min_t(int, port->break_length, 0xff);
 			sx_out(bp, CD186x_TDR, CD186x_C_ESC);
 			sx_out(bp, CD186x_TDR, CD186x_C_DELAY);
 			sx_out(bp, CD186x_TDR, count);
@@ -1468,8 +1464,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
 	sx_shutdown_port(bp, port);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
 	tty->closing = 0;
 	port->event = 0;
 	port->tty = NULL;
@@ -1506,7 +1501,7 @@ static int sx_write(struct tty_struct * tty, int from_user,
 	if (from_user) {
 		down(&tmp_buf_sem);
 		while (1) {
-			c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+			c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
 					   SERIAL_XMIT_SIZE - port->xmit_head));
 			if (c <= 0)
 				break;
@@ -1519,7 +1514,7 @@ static int sx_write(struct tty_struct * tty, int from_user,
 			}
 
 			cli();
-			c = MIN(c, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+			c = min_t(int, c, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
 				       SERIAL_XMIT_SIZE - port->xmit_head));
 			memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c);
 			port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
@@ -1534,7 +1529,7 @@ static int sx_write(struct tty_struct * tty, int from_user,
 	} else {
 		while (1) {
 			cli();
-			c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+			c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
 					   SERIAL_XMIT_SIZE - port->xmit_head));
 			if (c <= 0) {
 				restore_flags(flags);
@@ -1646,10 +1641,8 @@ static void sx_flush_buffer(struct tty_struct *tty)
 	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
 	restore_flags(flags);
 	
+	tty_wakeup(tty);
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
 }
 
 
@@ -2052,12 +2045,8 @@ static void do_softint(void *private_)
 	if(!(tty = port->tty)) 
 		return;
 
-	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
-	}
+	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event))
+		tty_wakeup(tty);
 }
 
 static struct tty_operations sx_ops = {
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index a0b3ba7b0..90018ce17 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -1197,8 +1197,7 @@ static void stl_close(struct tty_struct *tty, struct file *filp)
 		portp->tx.tail = (char *) NULL;
 	}
 	set_bit(TTY_IO_ERROR, &tty->flags);
-	if (tty->ldisc.flush_buffer)
-		(tty->ldisc.flush_buffer)(tty);
+	tty_ldisc_flush(tty);
 
 	tty->closing = 0;
 	portp->tty = (struct tty_struct *) NULL;
@@ -1809,10 +1808,7 @@ static void stl_flushbuffer(struct tty_struct *tty)
 		return;
 
 	stl_flush(portp);
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /*****************************************************************************/
@@ -2193,10 +2189,7 @@ static void stl_offintr(void *private)
 
 	lock_kernel();
 	if (test_bit(ASYI_TXLOW, &portp->istate)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
+		tty_wakeup(tty);
 	}
 	if (test_bit(ASYI_DCDCHANGE, &portp->istate)) {
 		clear_bit(ASYI_DCDCHANGE, &portp->istate);
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 1ca3d2543..a990eb7aa 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -1046,12 +1046,9 @@ static void sx_transmit_chars (struct sx_port *port)
 	}
 
 	if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) {
-		if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    port->gs.tty->ldisc.write_wakeup)
-			(port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
+		tty_wakeup(port->gs.tty);
 		sx_dprintk (SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
 		            port->gs.wakeup_chars); 
-		wake_up_interruptible(&port->gs.tty->write_wait);
 	}
 
 	clear_bit (SX_PORT_TRANSMIT_LOCK, &port->locks);
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 78d4efe6f..0a1cc1d36 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/char/synclink.c
  *
- * $Id: synclink.c,v 4.24 2004/06/03 14:50:09 paulkf Exp $
+ * $Id: synclink.c,v 4.28 2004/08/11 19:30:01 paulkf Exp $
  *
  * Device driver for Microgate SyncLink ISA and PCI
  * high speed multiprotocol serial adapters.
@@ -100,13 +100,10 @@
 #include <asm/types.h>
 #include <linux/termios.h>
 #include <linux/workqueue.h>
+#include <linux/hdlc.h>
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE
-#define CONFIG_SYNCLINK_SYNCPPP 1
-#endif
-
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-#include <net/syncppp.h>
+#ifdef CONFIG_HDLC_MODULE
+#define CONFIG_HDLC 1
 #endif
 
 #define GET_USER(error,value,addr) error = get_user(value,addr)
@@ -187,7 +184,6 @@ struct tx_holding_buffer {
  */
  
 struct mgsl_struct {
-	void *if_ptr;	/* General purpose pointer (used by SPPP) */
 	int			magic;
 	int			flags;
 	int			count;		/* count of opens */
@@ -318,15 +314,13 @@ struct mgsl_struct {
 	
 	struct	_input_signal_events	input_signal_events;
 
-	/* SPPP/Cisco HDLC device parts */
+	/* generic HDLC device parts */
 	int netcount;
 	int dosyncppp;
 	spinlock_t netlock;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-	struct ppp_device pppdev;
-	char netname[10];
+
+#ifdef CONFIG_HDLC
 	struct net_device *netdev;
-	struct net_device_stats netstats;
 #endif
 };
 
@@ -734,18 +728,12 @@ int usc_loopmode_send_active( struct mgsl_struct * info );
 
 int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg);
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-/* SPPP/HDLC stuff */
-static void mgsl_sppp_init(struct mgsl_struct *info);
-static void mgsl_sppp_delete(struct mgsl_struct *info);
-int mgsl_sppp_open(struct net_device *d);
-int mgsl_sppp_close(struct net_device *d);
-void mgsl_sppp_tx_timeout(struct net_device *d);
-int mgsl_sppp_tx(struct sk_buff *skb, struct net_device *d);
-void mgsl_sppp_rx_done(struct mgsl_struct *info, char *buf, int size);
-void mgsl_sppp_tx_done(struct mgsl_struct *info);
-int mgsl_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-struct net_device_stats *mgsl_net_stats(struct net_device *dev);
+#ifdef CONFIG_HDLC
+#define dev_to_port(D) (dev_to_hdlc(D)->priv)
+static void hdlcdev_tx_done(struct mgsl_struct *info);
+static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size);
+static int  hdlcdev_init(struct mgsl_struct *info);
+static void hdlcdev_exit(struct mgsl_struct *info);
 #endif
 
 /*
@@ -863,8 +851,6 @@ static int mgsl_rxenable(struct mgsl_struct * info, int enable);
 static int mgsl_wait_event(struct mgsl_struct * info, int __user *mask);
 static int mgsl_loopmode_send_done( struct mgsl_struct * info );
 
-#define jiffies_from_ms(a) ((((a) * HZ)/1000)+1)
-
 /* set non-zero on successful registration with PCI subsystem */
 static int pci_registered;
 
@@ -911,7 +897,7 @@ MODULE_PARM(txdmabufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i");
 MODULE_PARM(txholdbufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i");
 
 static char *driver_name = "SyncLink serial driver";
-static char *driver_version = "$Revision: 4.24 $";
+static char *driver_version = "$Revision: 4.28 $";
 
 static int synclink_init_one (struct pci_dev *dev,
 				     const struct pci_device_id *ent);
@@ -942,10 +928,6 @@ static struct tty_driver *serial_driver;
 static void mgsl_change_params(struct mgsl_struct *info);
 static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout);
 
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
 /*
  * 1st function defined in .text section. Calling this function in
  * init_module() followed by a breakpoint allows a remote debugger
@@ -993,6 +975,29 @@ static inline int mgsl_paranoia_check(struct mgsl_struct *info,
 	return 0;
 }
 
+/**
+ * line discipline callback wrappers
+ *
+ * The wrappers maintain line discipline references
+ * while calling into the line discipline.
+ *
+ * ldisc_receive_buf  - pass receive data to line discipline
+ */
+
+static void ldisc_receive_buf(struct tty_struct *tty,
+			      const __u8 *data, char *flags, int count)
+{
+	struct tty_ldisc *ld;
+	if (!tty)
+		return;
+	ld = tty_ldisc_ref(tty);
+	if (ld) {
+		if (ld->receive_buf)
+			ld->receive_buf(tty, data, flags, count);
+		tty_ldisc_deref(ld);
+	}
+}
+
 /* mgsl_stop()		throttle (stop) transmitter
  * 	
  * Arguments:		tty	pointer to tty info structure
@@ -1153,13 +1158,7 @@ void mgsl_bh_transmit(struct mgsl_struct *info)
 			__FILE__,__LINE__,info->device_name);
 
 	if (tty) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup) {
-			if ( debug_level >= DEBUG_LEVEL_BH )
-				printk( "%s(%d):calling ldisc.write_wakeup on %s\n",
-					__FILE__,__LINE__,info->device_name);
-			(tty->ldisc.write_wakeup)(tty);
-		}
+		tty_wakeup(tty);
 		wake_up_interruptible(&tty->write_wait);
 	}
 
@@ -1289,9 +1288,9 @@ void mgsl_isr_transmit_status( struct mgsl_struct *info )
 		info->drop_rts_on_tx_done = 0;
 	}
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP	
+#ifdef CONFIG_HDLC
 	if (info->netcount)
-		mgsl_sppp_tx_done(info);
+		hdlcdev_tx_done(info);
 	else 
 #endif
 	{
@@ -1352,12 +1351,12 @@ void mgsl_isr_io_pin( struct mgsl_struct *info )
 			icount->dcd++;
 			if (status & MISCSTATUS_DCD) {
 				info->input_signal_events.dcd_up++;
-#ifdef CONFIG_SYNCLINK_SYNCPPP	
-				if (info->netcount)
-					sppp_reopen(info->netdev);
-#endif
 			} else
 				info->input_signal_events.dcd_down++;
+#ifdef CONFIG_HDLC
+			if (info->netcount)
+				hdlc_set_carrier(status & MISCSTATUS_DCD, info->netdev);
+#endif
 		}
 		if (status & MISCSTATUS_CTS_LATCHED)
 		{
@@ -2258,8 +2257,8 @@ static int mgsl_write(struct tty_struct * tty, int from_user,
 		if (from_user) {
 			down(&tmp_buf_sem);
 			while (1) {
-				c = MIN(count,
-					MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				c = min_t(int, count,
+					min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
 					    SERIAL_XMIT_SIZE - info->xmit_head));
 				if (c <= 0)
 					break;
@@ -2272,7 +2271,7 @@ static int mgsl_write(struct tty_struct * tty, int from_user,
 					break;
 				}
 				spin_lock_irqsave(&info->irq_spinlock,flags);
-				c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				c = min_t(int, c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
 					       SERIAL_XMIT_SIZE - info->xmit_head));
 				memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
 				info->xmit_head = ((info->xmit_head + c) &
@@ -2287,8 +2286,8 @@ static int mgsl_write(struct tty_struct * tty, int from_user,
 		} else {
 			while (1) {
 				spin_lock_irqsave(&info->irq_spinlock,flags);
-				c = MIN(count,
-					MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				c = min_t(int, count,
+					min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
 					    SERIAL_XMIT_SIZE - info->xmit_head));
 				if (c <= 0) {
 					spin_unlock_irqrestore(&info->irq_spinlock,flags);
@@ -2415,11 +2414,8 @@ static void mgsl_flush_buffer(struct tty_struct *tty)
 	spin_unlock_irqrestore(&info->irq_spinlock,flags);
 	
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
-		
-}	/* end of mgsl_flush_buffer() */
+	tty_wakeup(tty);
+}
 
 /* mgsl_send_xchar()
  *
@@ -3253,9 +3249,8 @@ static void mgsl_close(struct tty_struct *tty, struct file * filp)
 
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-		
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+
+	tty_ldisc_flush(tty);
 		
 	shutdown(info);
 	
@@ -3326,7 +3321,7 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout)
 		char_time = 1;
 		
 	if (timeout)
-		char_time = MIN(char_time, timeout);
+		char_time = min_t(unsigned long, char_time, timeout);
 		
 	if ( info->params.mode == MGSL_MODE_HDLC ||
 		info->params.mode == MGSL_MODE_RAW ) {
@@ -3592,7 +3587,7 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp)
 cleanup:			
 	if (retval) {
 		if (tty->count == 1)
-			info->tty = NULL;/* tty layer will release tty struct */
+			info->tty = NULL; /* tty layer will release tty struct */
 		if(info->count)
 			info->count--;
 	}
@@ -4187,7 +4182,7 @@ int load_next_tx_holding_buffer(struct mgsl_struct *info)
 				info->get_tx_holding_index=0;
 
 			/* restart transmit timer */
-			mod_timer(&info->tx_timer, jiffies + jiffies_from_ms(5000));
+			mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(5000));
 
 			ret = 1;
 		}
@@ -4415,12 +4410,10 @@ void mgsl_add_device( struct mgsl_struct *info )
 		     	info->max_frame_size );
 	}
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-#ifdef MODULE
-	if (info->dosyncppp)
-#endif
-		mgsl_sppp_init(info);
+#ifdef CONFIG_HDLC
+	hdlcdev_init(info);
 #endif
+
 }	/* end of mgsl_add_device() */
 
 /* mgsl_allocate_device()
@@ -4575,9 +4568,8 @@ static void synclink_cleanup(void)
 
 	info = mgsl_device_list;
 	while(info) {
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-		if (info->dosyncppp)
-			mgsl_sppp_delete(info);
+#ifdef CONFIG_HDLC
+		hdlcdev_exit(info);
 #endif
 		mgsl_release_resources(info);
 		tmp = info;
@@ -5819,7 +5811,7 @@ void usc_start_transmitter( struct mgsl_struct *info )
 			
 			usc_TCmd( info, TCmd_SendFrame );
 			
-			info->tx_timer.expires = jiffies + jiffies_from_ms(5000);
+			info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
 			add_timer(&info->tx_timer);	
 		}
 		info->tx_active = 1;
@@ -6750,9 +6742,12 @@ int mgsl_get_rx_frame(struct mgsl_struct *info)
 				return_frame = 1;
 		}
 		framesize = 0;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-		info->netstats.rx_errors++;
-		info->netstats.rx_frame_errors++;
+#ifdef CONFIG_HDLC
+		{
+			struct net_device_stats *stats = hdlc_stats(info->netdev);
+			stats->rx_errors++;
+			stats->rx_frame_errors++;
+		}
 #endif
 	} else
 		return_frame = 1;
@@ -6779,7 +6774,7 @@ int mgsl_get_rx_frame(struct mgsl_struct *info)
 			
 	if ( debug_level >= DEBUG_LEVEL_DATA )
 		mgsl_trace_block(info,info->rx_buffer_list[StartIndex].virt_addr,
-			MIN(framesize,DMABUFFERSIZE),0);	
+			min_t(int, framesize, DMABUFFERSIZE),0);
 		
 	if (framesize) {
 		if ( ( (info->params.crc_type & HDLC_CRC_RETURN_EX) &&
@@ -6823,18 +6818,12 @@ int mgsl_get_rx_frame(struct mgsl_struct *info)
 						*ptmp);
 			}
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-			if (info->netcount) {
-				/* pass frame to syncppp device */
-				mgsl_sppp_rx_done(info,info->intermediate_rxbuffer,framesize);
-			} 
+#ifdef CONFIG_HDLC
+			if (info->netcount)
+				hdlcdev_rx(info,info->intermediate_rxbuffer,framesize);
 			else
 #endif
-			{
-				/* Call the line discipline receive callback directly. */
-				if ( tty && tty->ldisc.receive_buf )
-				tty->ldisc.receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
-			}
+				ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
 		}
 	}
 	/* Free the buffers used by this frame. */
@@ -6996,7 +6985,7 @@ int mgsl_get_raw_rx_frame(struct mgsl_struct *info)
 
 		if ( debug_level >= DEBUG_LEVEL_DATA )
 			mgsl_trace_block(info,info->rx_buffer_list[CurrentIndex].virt_addr,
-				MIN(framesize,DMABUFFERSIZE),0);
+				min_t(int, framesize, DMABUFFERSIZE),0);
 
 		if (framesize) {
 			/* copy dma buffer(s) to contiguous intermediate buffer */
@@ -7006,9 +6995,7 @@ int mgsl_get_raw_rx_frame(struct mgsl_struct *info)
 			memcpy( info->intermediate_rxbuffer, pBufEntry->virt_addr, framesize);
 			info->icount.rxok++;
 
-			/* Call the line discipline receive callback directly. */
-			if ( tty && tty->ldisc.receive_buf )
-				tty->ldisc.receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
+			ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
 		}
 
 		/* Free the buffers used by this frame. */
@@ -7056,7 +7043,7 @@ void mgsl_load_tx_dma_buffer(struct mgsl_struct *info, const char *Buffer,
 	DMABUFFERENTRY *pBufEntry;
 	
 	if ( debug_level >= DEBUG_LEVEL_DATA )
-		mgsl_trace_block(info,Buffer, MIN(BufferSize,DMABUFFERSIZE), 1);	
+		mgsl_trace_block(info,Buffer, min_t(int, BufferSize, DMABUFFERSIZE), 1);
 
 	if (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) {
 		/* set CMR:13 to start transmit when
@@ -7214,7 +7201,7 @@ BOOLEAN mgsl_irq_test( struct mgsl_struct *info )
 	EndTime=100;
 	while( EndTime-- && !info->irq_occurred ) {
 		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(jiffies_from_ms(10));
+		schedule_timeout(msecs_to_jiffies(10));
 	}
 	
 	spin_lock_irqsave(&info->irq_spinlock,flags);
@@ -7353,7 +7340,7 @@ BOOLEAN mgsl_dma_test( struct mgsl_struct *info )
 	/*************************************************************/
 
 	/* Wait 100ms for interrupt. */
-	EndTime = jiffies + jiffies_from_ms(100);
+	EndTime = jiffies + msecs_to_jiffies(100);
 
 	for(;;) {
 		if (time_after(jiffies, EndTime)) {
@@ -7409,7 +7396,7 @@ BOOLEAN mgsl_dma_test( struct mgsl_struct *info )
 	/**********************************/
 	
 	/* Wait 100ms */
-	EndTime = jiffies + jiffies_from_ms(100);
+	EndTime = jiffies + msecs_to_jiffies(100);
 
 	for(;;) {
 		if (time_after(jiffies, EndTime)) {
@@ -7451,7 +7438,7 @@ BOOLEAN mgsl_dma_test( struct mgsl_struct *info )
 		/******************************/
 
 		/* Wait 100ms */
-		EndTime = jiffies + jiffies_from_ms(100);
+		EndTime = jiffies + msecs_to_jiffies(100);
 
 		/* While timer not expired wait for transmit complete */
 
@@ -7482,7 +7469,7 @@ BOOLEAN mgsl_dma_test( struct mgsl_struct *info )
 		/* WAIT FOR RECEIVE COMPLETE */
 
 		/* Wait 100ms */
-		EndTime = jiffies + jiffies_from_ms(100);
+		EndTime = jiffies + msecs_to_jiffies(100);
 
 		/* Wait for 16C32 to write receive status to buffer entry. */
 		status=info->rx_buffer_list[0].status;
@@ -7736,9 +7723,9 @@ void mgsl_tx_timeout(unsigned long context)
 
 	spin_unlock_irqrestore(&info->irq_spinlock,flags);
 	
-#ifdef CONFIG_SYNCLINK_SYNCPPP
+#ifdef CONFIG_HDLC
 	if (info->netcount)
-		mgsl_sppp_tx_done(info);
+		hdlcdev_tx_done(info);
 	else
 #endif
 		mgsl_bh_transmit(info);
@@ -7819,79 +7806,125 @@ int usc_loopmode_send_active( struct mgsl_struct * info )
 	return usc_InReg( info, CCSR ) & BIT6 ? 1 : 0 ;
 }			  
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-/* syncppp net device routines
- */
-static void mgsl_setup(struct net_device *dev)
-{
-	dev->open = mgsl_sppp_open;
-	dev->stop = mgsl_sppp_close;
-	dev->hard_start_xmit = mgsl_sppp_tx;
-	dev->do_ioctl = mgsl_sppp_ioctl;
-	dev->get_stats = mgsl_net_stats;
-	dev->tx_timeout = mgsl_sppp_tx_timeout;
-	dev->watchdog_timeo = 10*HZ;
-}
+#ifdef CONFIG_HDLC
 
-static void mgsl_sppp_init(struct mgsl_struct *info)
+/**
+ * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
+ * set encoding and frame check sequence (FCS) options
+ *
+ * dev       pointer to network device structure
+ * encoding  serial encoding setting
+ * parity    FCS setting
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
+			  unsigned short parity)
 {
-	struct net_device *d;
+	struct mgsl_struct *info = dev_to_port(dev);
+	unsigned char  new_encoding;
+	unsigned short new_crctype;
 
-	sprintf(info->netname,"mgsl%d",info->line);
+	/* return error if TTY interface open */
+	if (info->count)
+		return -EBUSY;
 
-	d = alloc_netdev(0, info->netname, mgsl_setup);
-	if (!d) {
-		printk(KERN_WARNING "%s: alloc_netdev failed.\n",
-						info->netname);
-		return;
+	switch (encoding)
+	{
+	case ENCODING_NRZ:        new_encoding = HDLC_ENCODING_NRZ; break;
+	case ENCODING_NRZI:       new_encoding = HDLC_ENCODING_NRZI_SPACE; break;
+	case ENCODING_FM_MARK:    new_encoding = HDLC_ENCODING_BIPHASE_MARK; break;
+	case ENCODING_FM_SPACE:   new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break;
+	case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break;
+	default: return -EINVAL;
 	}
 
-	info->if_ptr = &info->pppdev;
-	info->netdev = info->pppdev.dev = d;
-
-	d->base_addr = info->io_base;
-	d->irq = info->irq_level;
-	d->dma = info->dma_level;
-	d->priv = info;
+	switch (parity)
+	{
+	case PARITY_NONE:            new_crctype = HDLC_CRC_NONE; break;
+	case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break;
+	case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break;
+	default: return -EINVAL;
+	}
 
-	sppp_attach(&info->pppdev);
-	mgsl_setup(d);
+	info->params.encoding = new_encoding;
+	info->params.crc_type = new_crctype;;
 
-	if (register_netdev(d)) {
-		printk(KERN_WARNING "%s: register_netdev failed.\n", d->name);
-		sppp_detach(info->netdev);
-		info->netdev = NULL;
-		free_netdev(d);
-		return;
-	}
+	/* if network interface up, reprogram hardware */
+	if (info->netcount)
+		mgsl_program_hw(info);
 
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgsl_sppp_init()\n");	
+	return 0;
 }
 
-void mgsl_sppp_delete(struct mgsl_struct *info)
+/**
+ * called by generic HDLC layer to send frame
+ *
+ * skb  socket buffer containing HDLC frame
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev)
 {
+	struct mgsl_struct *info = dev_to_port(dev);
+	struct net_device_stats *stats = hdlc_stats(dev);
+	unsigned long flags;
+
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgsl_sppp_delete(%s)\n",info->netname);	
-	unregister_netdev(info->netdev);
-	sppp_detach(info->netdev);
-	free_netdev(info->netdev);
-	info->netdev = NULL;
-	info->pppdev.dev = NULL;
+		printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name);
+
+	/* stop sending until this frame completes */
+	netif_stop_queue(dev);
+
+	/* copy data to device buffers */
+	info->xmit_cnt = skb->len;
+	mgsl_load_tx_dma_buffer(info, skb->data, skb->len);
+
+	/* update network statistics */
+	stats->tx_packets++;
+	stats->tx_bytes += skb->len;
+
+	/* done with socket buffer, so free it */
+	dev_kfree_skb(skb);
+
+	/* save start time for transmit timeout detection */
+	dev->trans_start = jiffies;
+
+	/* start hardware transmitter if necessary */
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	if (!info->tx_active)
+	 	usc_start_transmitter(info);
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+	return 0;
 }
 
-int mgsl_sppp_open(struct net_device *d)
+/**
+ * called by network layer when interface enabled
+ * claim resources and initialize hardware
+ *
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_open(struct net_device *dev)
 {
-	struct mgsl_struct *info = d->priv;
-	int err;
+	struct mgsl_struct *info = dev_to_port(dev);
+	int rc;
 	unsigned long flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgsl_sppp_open(%s)\n",info->netname);	
+		printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name);
 
+	/* generic HDLC layer open processing */
+	if ((rc = hdlc_open(dev)))
+		return rc;
+
+	/* arbitrate between network and tty opens */
 	spin_lock_irqsave(&info->netlock, flags);
 	if (info->count != 0 || info->netcount != 0) {
-		printk(KERN_WARNING "%s: sppp_open returning busy\n", info->netname);
+		printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name);
 		spin_unlock_irqrestore(&info->netlock, flags);
 		return -EBUSY;
 	}
@@ -7899,141 +7932,301 @@ int mgsl_sppp_open(struct net_device *d)
 	spin_unlock_irqrestore(&info->netlock, flags);
 
 	/* claim resources and init adapter */
-	if ((err = startup(info)) != 0)
-		goto open_fail;
-
-	/* allow syncppp module to do open processing */
-	if ((err = sppp_open(d)) != 0) {
-		shutdown(info);
-		goto open_fail;
+	if ((rc = startup(info)) != 0) {
+		spin_lock_irqsave(&info->netlock, flags);
+		info->netcount=0;
+		spin_unlock_irqrestore(&info->netlock, flags);
+		return rc;
 	}
 
+	/* assert DTR and RTS, apply hardware settings */
 	info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
 	mgsl_program_hw(info);
 
-	d->trans_start = jiffies;
-	netif_start_queue(d);
-	return 0;
+	/* enable network layer transmit */
+	dev->trans_start = jiffies;
+	netif_start_queue(dev);
 
-open_fail:
-	spin_lock_irqsave(&info->netlock, flags);
-	info->netcount=0;
-	spin_unlock_irqrestore(&info->netlock, flags);
-	return err;
+	/* inform generic HDLC layer of current DCD status */
+	spin_lock_irqsave(&info->irq_spinlock, flags);
+	usc_get_serial_signals(info);
+	spin_unlock_irqrestore(&info->irq_spinlock, flags);
+	hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, dev);
+
+	return 0;
 }
 
-void mgsl_sppp_tx_timeout(struct net_device *dev)
+/**
+ * called by network layer when interface is disabled
+ * shutdown hardware and release resources
+ *
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_close(struct net_device *dev)
 {
-	struct mgsl_struct *info = dev->priv;
+	struct mgsl_struct *info = dev_to_port(dev);
 	unsigned long flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgsl_sppp_tx_timeout(%s)\n",info->netname);	
+		printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name);
 
-	info->netstats.tx_errors++;
-	info->netstats.tx_aborted_errors++;
+	netif_stop_queue(dev);
 
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	usc_stop_transmitter(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	/* shutdown adapter and release resources */
+	shutdown(info);
 
-	netif_wake_queue(dev);
+	hdlc_close(dev);
+
+	spin_lock_irqsave(&info->netlock, flags);
+	info->netcount=0;
+	spin_unlock_irqrestore(&info->netlock, flags);
+
+	return 0;
 }
 
-int mgsl_sppp_tx(struct sk_buff *skb, struct net_device *dev)
+/**
+ * called by network layer to process IOCTL call to network device
+ *
+ * dev  pointer to network device structure
+ * ifr  pointer to network interface request structure
+ * cmd  IOCTL command code
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-	struct mgsl_struct *info = dev->priv;
-	unsigned long flags;
+	const size_t size = sizeof(sync_serial_settings);
+	sync_serial_settings new_line;
+	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
+	struct mgsl_struct *info = dev_to_port(dev);
+	unsigned int flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgsl_sppp_tx(%s)\n",info->netname);	
+		printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name);
 
-	netif_stop_queue(dev);
+	/* return error if TTY interface open */
+	if (info->count)
+		return -EBUSY;
 
-	info->xmit_cnt = skb->len;
-	mgsl_load_tx_dma_buffer(info, skb->data, skb->len);
-	info->netstats.tx_packets++;
-	info->netstats.tx_bytes += skb->len;
-	dev_kfree_skb(skb);
+	if (cmd != SIOCWANDEV)
+		return hdlc_ioctl(dev, ifr, cmd);
 
-	dev->trans_start = jiffies;
+	switch(ifr->ifr_settings.type) {
+	case IF_GET_IFACE: /* return current sync_serial_settings */
 
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	if (!info->tx_active)
-	 	usc_start_transmitter(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+		ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
+		if (ifr->ifr_settings.size < size) {
+			ifr->ifr_settings.size = size; /* data size wanted */
+			return -ENOBUFS;
+		}
 
-	return 0;
+		flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
+
+		switch (flags){
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
+		case (HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_INT; break;
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_TXINT; break;
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break;
+		default: new_line.clock_type = CLOCK_DEFAULT;
+		}
+
+		new_line.clock_rate = info->params.clock_speed;
+		new_line.loopback   = info->params.loopback ? 1:0;
+
+		if (copy_to_user(line, &new_line, size))
+			return -EFAULT;
+		return 0;
+
+	case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */
+
+		if(!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (copy_from_user(&new_line, line, size))
+			return -EFAULT;
+
+		switch (new_line.clock_type)
+		{
+		case CLOCK_EXT:      flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break;
+		case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break;
+		case CLOCK_INT:      flags = HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG;    break;
+		case CLOCK_TXINT:    flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG;    break;
+		case CLOCK_DEFAULT:  flags = info->params.flags &
+					     (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN); break;
+		default: return -EINVAL;
+		}
+
+		if (new_line.loopback != 0 && new_line.loopback != 1)
+			return -EINVAL;
+
+		info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
+		info->params.flags |= flags;
+
+		info->params.loopback = new_line.loopback;
+
+		if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG))
+			info->params.clock_speed = new_line.clock_rate;
+		else
+			info->params.clock_speed = 0;
+
+		/* if network interface up, reprogram hardware */
+		if (info->netcount)
+			mgsl_program_hw(info);
+		return 0;
+
+	default:
+		return hdlc_ioctl(dev, ifr, cmd);
+	}
 }
 
-int mgsl_sppp_close(struct net_device *d)
+/**
+ * called by network layer when transmit timeout is detected
+ *
+ * dev  pointer to network device structure
+ */
+static void hdlcdev_tx_timeout(struct net_device *dev)
 {
-	struct mgsl_struct *info = d->priv;
+	struct mgsl_struct *info = dev_to_port(dev);
+	struct net_device_stats *stats = hdlc_stats(dev);
 	unsigned long flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgsl_sppp_close(%s)\n",info->netname);	
+		printk("hdlcdev_tx_timeout(%s)\n",dev->name);
 
-	/* shutdown adapter and release resources */
-	shutdown(info);
+	stats->tx_errors++;
+	stats->tx_aborted_errors++;
 
-	/* allow syncppp to do close processing */
-	sppp_close(d);
-	netif_stop_queue(d);
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	usc_stop_transmitter(info);
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
 
-	spin_lock_irqsave(&info->netlock, flags);
-	info->netcount=0;
-	spin_unlock_irqrestore(&info->netlock, flags);
-	return 0;
+	netif_wake_queue(dev);
+}
+
+/**
+ * called by device driver when transmit completes
+ * reenable network layer transmit if stopped
+ *
+ * info  pointer to device instance information
+ */
+static void hdlcdev_tx_done(struct mgsl_struct *info)
+{
+	if (netif_queue_stopped(info->netdev))
+		netif_wake_queue(info->netdev);
 }
 
-void mgsl_sppp_rx_done(struct mgsl_struct *info, char *buf, int size)
+/**
+ * called by device driver when frame received
+ * pass frame to network layer
+ *
+ * info  pointer to device instance information
+ * buf   pointer to buffer contianing frame data
+ * size  count of data bytes in buf
+ */
+static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size)
 {
 	struct sk_buff *skb = dev_alloc_skb(size);
+	struct net_device *dev = info->netdev;
+	struct net_device_stats *stats = hdlc_stats(dev);
+
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgsl_sppp_rx_done(%s)\n",info->netname);	
+		printk("hdlcdev_rx(%s)\n",dev->name);
+
 	if (skb == NULL) {
-		printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n",
-			info->netname);
-		info->netstats.rx_dropped++;
+		printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", dev->name);
+		stats->rx_dropped++;
 		return;
 	}
 
 	memcpy(skb_put(skb, size),buf,size);
 
-	skb->protocol = htons(ETH_P_WAN_PPP);
-	skb->dev = info->netdev;
-	skb->mac.raw = skb->data;
-	info->netstats.rx_packets++;
-	info->netstats.rx_bytes += size;
+	skb->dev      = info->netdev;
+	skb->mac.raw  = skb->data;
+	skb->protocol = hdlc_type_trans(skb, skb->dev);
+
+	stats->rx_packets++;
+	stats->rx_bytes += size;
+
 	netif_rx(skb);
-	info->netdev->trans_start = jiffies;
-}
 
-void mgsl_sppp_tx_done(struct mgsl_struct *info)
-{
-	if (netif_queue_stopped(info->netdev))
-	    netif_wake_queue(info->netdev);
+	info->netdev->last_rx = jiffies;
 }
 
-struct net_device_stats *mgsl_net_stats(struct net_device *dev)
+/**
+ * called by device driver when adding device instance
+ * do generic HDLC initialization
+ *
+ * info  pointer to device instance information
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_init(struct mgsl_struct *info)
 {
-	struct mgsl_struct *info = dev->priv;
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("mgsl_net_stats(%s)\n",info->netname);	
-	return &info->netstats;
+	int rc;
+	struct net_device *dev;
+	hdlc_device *hdlc;
+
+	/* allocate and initialize network and HDLC layer objects */
+
+	if (!(dev = alloc_hdlcdev(info))) {
+		printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__);
+		return -ENOMEM;
+	}
+
+	/* for network layer reporting purposes only */
+	dev->base_addr = info->io_base;
+	dev->irq       = info->irq_level;
+	dev->dma       = info->dma_level;
+
+	/* network layer callbacks and settings */
+	dev->do_ioctl       = hdlcdev_ioctl;
+	dev->open           = hdlcdev_open;
+	dev->stop           = hdlcdev_close;
+	dev->tx_timeout     = hdlcdev_tx_timeout;
+	dev->watchdog_timeo = 10*HZ;
+	dev->tx_queue_len   = 50;
+
+	/* generic HDLC layer callbacks and settings */
+	hdlc         = dev_to_hdlc(dev);
+	hdlc->attach = hdlcdev_attach;
+	hdlc->xmit   = hdlcdev_xmit;
+
+	/* register objects with HDLC layer */
+	if ((rc = register_hdlc_device(dev))) {
+		printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
+		free_netdev(dev);
+		return rc;
+	}
+
+	info->netdev = dev;
+	return 0;
 }
 
-int mgsl_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+/**
+ * called by device driver when removing device instance
+ * do generic HDLC cleanup
+ *
+ * info  pointer to device instance information
+ */
+static void hdlcdev_exit(struct mgsl_struct *info)
 {
-	struct mgsl_struct *info = dev->priv;
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
-			info->netname, cmd );
-	return sppp_do_ioctl(dev, ifr, cmd);
+	unregister_hdlc_device(info->netdev);
+	free_netdev(info->netdev);
+	info->netdev = NULL;
 }
 
-#endif /* ifdef CONFIG_SYNCLINK_SYNCPPP */
+#endif /* CONFIG_HDLC */
+
 
 static int __devinit synclink_init_one (struct pci_dev *dev,
 					const struct pci_device_id *ent)
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index 1361ea041..5648ed355 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -1,5 +1,5 @@
 /*
- * $Id: synclinkmp.c,v 4.22 2004/06/03 14:50:10 paulkf Exp $
+ * $Id: synclinkmp.c,v 4.29 2004/08/27 20:06:41 paulkf Exp $
  *
  * Device driver for Microgate SyncLink Multiport
  * high speed multiprotocol serial adapter.
@@ -67,13 +67,10 @@
 #include <asm/types.h>
 #include <linux/termios.h>
 #include <linux/workqueue.h>
+#include <linux/hdlc.h>
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE
-#define CONFIG_SYNCLINK_SYNCPPP 1
-#endif
-
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-#include <net/syncppp.h>
+#ifdef CONFIG_HDLC_MODULE
+#define CONFIG_HDLC 1
 #endif
 
 #define GET_USER(error,value,addr) error = get_user(value,addr)
@@ -284,12 +281,11 @@ typedef struct _synclinkmp_info {
 	int netcount;
 	int dosyncppp;
 	spinlock_t netlock;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-	struct ppp_device pppdev;
-	char netname[10];
+
+#ifdef CONFIG_HDLC
 	struct net_device *netdev;
-	struct net_device_stats netstats;
 #endif
+
 } SLMP_INFO;
 
 #define MGSL_MAGIC 0x5401
@@ -361,12 +357,7 @@ typedef struct _synclinkmp_info {
 #define TMCS	0x64
 #define TEPR	0x65
 
-/*
- *  FIXME: DAR here clashed with asm-ppc/reg.h and asm-sh/.../dma.h
- */
-#undef DAR
 /* DMA Controller Register macros */
-#define DAR	0x80
 #define DARL	0x80
 #define DARH	0x81
 #define DARB	0x82
@@ -462,8 +453,6 @@ typedef struct _synclinkmp_info {
 #define CRCE	BIT2
 
 
-#define jiffies_from_ms(a) ((((a) * HZ)/1000)+1)
-
 /*
  * Global linked list of SyncLink devices
  */
@@ -498,7 +487,7 @@ MODULE_PARM(maxframe,"1-" __MODULE_STRING(MAX_DEVICES) "i");
 MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICES) "i");
 
 static char *driver_name = "SyncLink MultiPort driver";
-static char *driver_version = "$Revision: 4.22 $";
+static char *driver_version = "$Revision: 4.29 $";
 
 static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent);
 static void synclinkmp_remove_one(struct pci_dev *dev);
@@ -524,10 +513,6 @@ static struct tty_driver *serial_driver;
 /* number of characters left in xmit buffer before we ask for more */
 #define WAKEUP_CHARS 256
 
-#ifndef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
 
 /* tty callbacks */
 
@@ -553,20 +538,12 @@ static void throttle(struct tty_struct * tty);
 static void unthrottle(struct tty_struct * tty);
 static void set_break(struct tty_struct *tty, int break_state);
 
-/* sppp support and callbacks */
-
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-static void sppp_init(SLMP_INFO *info);
-static void sppp_delete(SLMP_INFO *info);
-static void sppp_rx_done(SLMP_INFO *info, char *buf, int size);
-static void sppp_tx_done(SLMP_INFO *info);
-
-static int  sppp_cb_open(struct net_device *d);
-static int  sppp_cb_close(struct net_device *d);
-static int  sppp_cb_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-static int  sppp_cb_tx(struct sk_buff *skb, struct net_device *dev);
-static void sppp_cb_tx_timeout(struct net_device *dev);
-static struct net_device_stats *sppp_cb_net_stats(struct net_device *dev);
+#ifdef CONFIG_HDLC
+#define dev_to_port(D) (dev_to_hdlc(D)->priv)
+static void hdlcdev_tx_done(SLMP_INFO *info);
+static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size);
+static int  hdlcdev_init(SLMP_INFO *info);
+static void hdlcdev_exit(SLMP_INFO *info);
 #endif
 
 /* ioctl handlers */
@@ -668,7 +645,7 @@ static unsigned char tx_active_fifo_level = 16;	// tx request FIFO activation le
 static unsigned char tx_negate_fifo_level = 32;	// tx request FIFO negation level in bytes
 
 static u32 misc_ctrl_value = 0x007e4040;
-static u32 lcr1_brdr_value = 0x0080002d;
+static u32 lcr1_brdr_value = 0x00800029;
 
 static u32 read_ahead_count = 8;
 
@@ -722,6 +699,29 @@ static inline int sanity_check(SLMP_INFO *info,
 	return 0;
 }
 
+/**
+ * line discipline callback wrappers
+ *
+ * The wrappers maintain line discipline references
+ * while calling into the line discipline.
+ *
+ * ldisc_receive_buf  - pass receive data to line discipline
+ */
+
+static void ldisc_receive_buf(struct tty_struct *tty,
+			      const __u8 *data, char *flags, int count)
+{
+	struct tty_ldisc *ld;
+	if (!tty)
+		return;
+	ld = tty_ldisc_ref(tty);
+	if (ld) {
+		if (ld->receive_buf)
+			ld->receive_buf(tty, data, flags, count);
+		tty_ldisc_deref(ld);
+	}
+}
+
 /* tty callbacks */
 
 /* Called when a port is opened.  Init and enable port.
@@ -800,7 +800,7 @@ static int open(struct tty_struct *tty, struct file *filp)
 cleanup:
 	if (retval) {
 		if (tty->count == 1)
-			info->tty = NULL;/* tty layer will release tty struct */
+			info->tty = NULL; /* tty layer will release tty struct */
 		if(info->count)
 			info->count--;
 	}
@@ -869,8 +869,7 @@ static void close(struct tty_struct *tty, struct file *filp)
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
 
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
 
 	shutdown(info);
 
@@ -1017,8 +1016,8 @@ static int write(struct tty_struct *tty, int from_user,
 	}
 
 	for (;;) {
-		c = MIN(count,
-			MIN(info->max_frame_size - info->tx_count - 1,
+		c = min_t(int, count,
+			min(info->max_frame_size - info->tx_count - 1,
 			    info->max_frame_size - info->tx_put));
 		if (c <= 0)
 			break;
@@ -1161,7 +1160,7 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
 		char_time = 1;
 
 	if (timeout)
-		char_time = MIN(char_time, timeout);
+		char_time = min_t(unsigned long, char_time, timeout);
 
 	if ( info->params.mode == MGSL_MODE_HDLC ) {
 		while (info->tx_active) {
@@ -1275,9 +1274,7 @@ static void flush_buffer(struct tty_struct *tty)
 	spin_unlock_irqrestore(&info->lock,flags);
 
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /* throttle (stop) transmitter
@@ -1627,79 +1624,125 @@ static void set_break(struct tty_struct *tty, int break_state)
 	spin_unlock_irqrestore(&info->lock,flags);
 }
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
+#ifdef CONFIG_HDLC
 
-/* syncppp support and callbacks */
-
-static void cb_setup(struct net_device *dev)
-{
-	dev->open = sppp_cb_open;
-	dev->stop = sppp_cb_close;
-	dev->hard_start_xmit = sppp_cb_tx;
-	dev->do_ioctl = sppp_cb_ioctl;
-	dev->get_stats = sppp_cb_net_stats;
-	dev->tx_timeout = sppp_cb_tx_timeout;
-	dev->watchdog_timeo = 10*HZ;
-}
-
-static void sppp_init(SLMP_INFO *info)
+/**
+ * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
+ * set encoding and frame check sequence (FCS) options
+ *
+ * dev       pointer to network device structure
+ * encoding  serial encoding setting
+ * parity    FCS setting
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
+			  unsigned short parity)
 {
-	struct net_device *d;
+	SLMP_INFO *info = dev_to_port(dev);
+	unsigned char  new_encoding;
+	unsigned short new_crctype;
 
-	sprintf(info->netname,"mgslm%dp%d",info->adapter_num,info->port_num);
+	/* return error if TTY interface open */
+	if (info->count)
+		return -EBUSY;
 
-	d = alloc_netdev(0, info->netname, cb_setup);
-	if (!d) {
-		printk(KERN_WARNING "%s: alloc_netdev failed.\n",
-						info->netname);
-		return;
+	switch (encoding)
+	{
+	case ENCODING_NRZ:        new_encoding = HDLC_ENCODING_NRZ; break;
+	case ENCODING_NRZI:       new_encoding = HDLC_ENCODING_NRZI_SPACE; break;
+	case ENCODING_FM_MARK:    new_encoding = HDLC_ENCODING_BIPHASE_MARK; break;
+	case ENCODING_FM_SPACE:   new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break;
+	case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break;
+	default: return -EINVAL;
 	}
 
-	info->if_ptr = &info->pppdev;
-	info->netdev = info->pppdev.dev = d;
-
-	d->irq = info->irq_level;
-	d->priv = info;
+	switch (parity)
+	{
+	case PARITY_NONE:            new_crctype = HDLC_CRC_NONE; break;
+	case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break;
+	case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break;
+	default: return -EINVAL;
+	}
 
-	sppp_attach(&info->pppdev);
-	cb_setup(d);
+	info->params.encoding = new_encoding;
+	info->params.crc_type = new_crctype;;
 
-	if (register_netdev(d)) {
-		printk(KERN_WARNING "%s: register_netdev failed.\n", d->name);
-		sppp_detach(info->netdev);
-		info->netdev = NULL;
-		info->pppdev.dev = NULL;
-		free_netdev(d);
-		return;
-	}
+	/* if network interface up, reprogram hardware */
+	if (info->netcount)
+		program_hw(info);
 
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("sppp_init(%s)\n",info->netname);
+	return 0;
 }
 
-static void sppp_delete(SLMP_INFO *info)
+/**
+ * called by generic HDLC layer to send frame
+ *
+ * skb  socket buffer containing HDLC frame
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev)
 {
+	SLMP_INFO *info = dev_to_port(dev);
+	struct net_device_stats *stats = hdlc_stats(dev);
+	unsigned long flags;
+
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("sppp_delete(%s)\n",info->netname);
-	unregister_netdev(info->netdev);
-	sppp_detach(info->netdev);
-	free_netdev(info->netdev);
-	info->netdev = NULL;
-	info->pppdev.dev = NULL;
+		printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name);
+
+	/* stop sending until this frame completes */
+	netif_stop_queue(dev);
+
+	/* copy data to device buffers */
+	info->tx_count = skb->len;
+	tx_load_dma_buffer(info, skb->data, skb->len);
+
+	/* update network statistics */
+	stats->tx_packets++;
+	stats->tx_bytes += skb->len;
+
+	/* done with socket buffer, so free it */
+	dev_kfree_skb(skb);
+
+	/* save start time for transmit timeout detection */
+	dev->trans_start = jiffies;
+
+	/* start hardware transmitter if necessary */
+	spin_lock_irqsave(&info->lock,flags);
+	if (!info->tx_active)
+	 	tx_start(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	return 0;
 }
 
-static int sppp_cb_open(struct net_device *d)
+/**
+ * called by network layer when interface enabled
+ * claim resources and initialize hardware
+ *
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_open(struct net_device *dev)
 {
-	SLMP_INFO *info = d->priv;
-	int err;
+	SLMP_INFO *info = dev_to_port(dev);
+	int rc;
 	unsigned long flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("sppp_cb_open(%s)\n",info->netname);
+		printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name);
+
+	/* generic HDLC layer open processing */
+	if ((rc = hdlc_open(dev)))
+		return rc;
 
+	/* arbitrate between network and tty opens */
 	spin_lock_irqsave(&info->netlock, flags);
 	if (info->count != 0 || info->netcount != 0) {
-		printk(KERN_WARNING "%s: sppp_cb_open returning busy\n", info->netname);
+		printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name);
 		spin_unlock_irqrestore(&info->netlock, flags);
 		return -EBUSY;
 	}
@@ -1707,141 +1750,300 @@ static int sppp_cb_open(struct net_device *d)
 	spin_unlock_irqrestore(&info->netlock, flags);
 
 	/* claim resources and init adapter */
-	if ((err = startup(info)) != 0)
-		goto open_fail;
-
-	/* allow syncppp module to do open processing */
-	if ((err = sppp_open(d)) != 0) {
-		shutdown(info);
-		goto open_fail;
+	if ((rc = startup(info)) != 0) {
+		spin_lock_irqsave(&info->netlock, flags);
+		info->netcount=0;
+		spin_unlock_irqrestore(&info->netlock, flags);
+		return rc;
 	}
 
+	/* assert DTR and RTS, apply hardware settings */
 	info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
 	program_hw(info);
 
-	d->trans_start = jiffies;
-	netif_start_queue(d);
-	return 0;
+	/* enable network layer transmit */
+	dev->trans_start = jiffies;
+	netif_start_queue(dev);
 
-open_fail:
-	spin_lock_irqsave(&info->netlock, flags);
-	info->netcount=0;
-	spin_unlock_irqrestore(&info->netlock, flags);
-	return err;
+	/* inform generic HDLC layer of current DCD status */
+	spin_lock_irqsave(&info->lock, flags);
+	get_signals(info);
+	spin_unlock_irqrestore(&info->lock, flags);
+	hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, dev);
+
+	return 0;
 }
 
-static void sppp_cb_tx_timeout(struct net_device *dev)
+/**
+ * called by network layer when interface is disabled
+ * shutdown hardware and release resources
+ *
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_close(struct net_device *dev)
 {
-	SLMP_INFO *info = dev->priv;
+	SLMP_INFO *info = dev_to_port(dev);
 	unsigned long flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("sppp_tx_timeout(%s)\n",info->netname);
+		printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name);
 
-	info->netstats.tx_errors++;
-	info->netstats.tx_aborted_errors++;
+	netif_stop_queue(dev);
 
-	spin_lock_irqsave(&info->lock,flags);
-	tx_stop(info);
-	spin_unlock_irqrestore(&info->lock,flags);
+	/* shutdown adapter and release resources */
+	shutdown(info);
 
-	netif_wake_queue(dev);
+	hdlc_close(dev);
+
+	spin_lock_irqsave(&info->netlock, flags);
+	info->netcount=0;
+	spin_unlock_irqrestore(&info->netlock, flags);
+
+	return 0;
 }
 
-static int sppp_cb_tx(struct sk_buff *skb, struct net_device *dev)
+/**
+ * called by network layer to process IOCTL call to network device
+ *
+ * dev  pointer to network device structure
+ * ifr  pointer to network interface request structure
+ * cmd  IOCTL command code
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-	SLMP_INFO *info = dev->priv;
-	unsigned long flags;
+	const size_t size = sizeof(sync_serial_settings);
+	sync_serial_settings new_line;
+	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
+	SLMP_INFO *info = dev_to_port(dev);
+	unsigned int flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("sppp_tx(%s)\n",info->netname);
+		printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name);
 
-	netif_stop_queue(dev);
+	/* return error if TTY interface open */
+	if (info->count)
+		return -EBUSY;
 
-	info->tx_count = skb->len;
-	tx_load_dma_buffer(info, skb->data, skb->len);
-	info->netstats.tx_packets++;
-	info->netstats.tx_bytes += skb->len;
-	dev_kfree_skb(skb);
+	if (cmd != SIOCWANDEV)
+		return hdlc_ioctl(dev, ifr, cmd);
 
-	dev->trans_start = jiffies;
+	switch(ifr->ifr_settings.type) {
+	case IF_GET_IFACE: /* return current sync_serial_settings */
 
-	spin_lock_irqsave(&info->lock,flags);
-	if (!info->tx_active)
-	 	tx_start(info);
-	spin_unlock_irqrestore(&info->lock,flags);
+		ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
+		if (ifr->ifr_settings.size < size) {
+			ifr->ifr_settings.size = size; /* data size wanted */
+			return -ENOBUFS;
+		}
 
-	return 0;
+		flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
+
+		switch (flags){
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
+		case (HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_INT; break;
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_TXINT; break;
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break;
+		default: new_line.clock_type = CLOCK_DEFAULT;
+		}
+
+		new_line.clock_rate = info->params.clock_speed;
+		new_line.loopback   = info->params.loopback ? 1:0;
+
+		if (copy_to_user(line, &new_line, size))
+			return -EFAULT;
+		return 0;
+
+	case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */
+
+		if(!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (copy_from_user(&new_line, line, size))
+			return -EFAULT;
+
+		switch (new_line.clock_type)
+		{
+		case CLOCK_EXT:      flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break;
+		case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break;
+		case CLOCK_INT:      flags = HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG;    break;
+		case CLOCK_TXINT:    flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG;    break;
+		case CLOCK_DEFAULT:  flags = info->params.flags &
+					     (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN); break;
+		default: return -EINVAL;
+		}
+
+		if (new_line.loopback != 0 && new_line.loopback != 1)
+			return -EINVAL;
+
+		info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
+		info->params.flags |= flags;
+
+		info->params.loopback = new_line.loopback;
+
+		if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG))
+			info->params.clock_speed = new_line.clock_rate;
+		else
+			info->params.clock_speed = 0;
+
+		/* if network interface up, reprogram hardware */
+		if (info->netcount)
+			program_hw(info);
+		return 0;
+
+	default:
+		return hdlc_ioctl(dev, ifr, cmd);
+	}
 }
 
-static int sppp_cb_close(struct net_device *d)
+/**
+ * called by network layer when transmit timeout is detected
+ *
+ * dev  pointer to network device structure
+ */
+static void hdlcdev_tx_timeout(struct net_device *dev)
 {
-	SLMP_INFO *info = d->priv;
+	SLMP_INFO *info = dev_to_port(dev);
+	struct net_device_stats *stats = hdlc_stats(dev);
 	unsigned long flags;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("sppp_cb_close(%s)\n",info->netname);
+		printk("hdlcdev_tx_timeout(%s)\n",dev->name);
 
-	/* shutdown adapter and release resources */
-	shutdown(info);
+	stats->tx_errors++;
+	stats->tx_aborted_errors++;
 
-	/* allow syncppp to do close processing */
-	sppp_close(d);
-	netif_stop_queue(d);
+	spin_lock_irqsave(&info->lock,flags);
+	tx_stop(info);
+	spin_unlock_irqrestore(&info->lock,flags);
 
-	spin_lock_irqsave(&info->netlock, flags);
-	info->netcount=0;
-	spin_unlock_irqrestore(&info->netlock, flags);
-	return 0;
+	netif_wake_queue(dev);
+}
+
+/**
+ * called by device driver when transmit completes
+ * reenable network layer transmit if stopped
+ *
+ * info  pointer to device instance information
+ */
+static void hdlcdev_tx_done(SLMP_INFO *info)
+{
+	if (netif_queue_stopped(info->netdev))
+		netif_wake_queue(info->netdev);
 }
 
-static void sppp_rx_done(SLMP_INFO *info, char *buf, int size)
+/**
+ * called by device driver when frame received
+ * pass frame to network layer
+ *
+ * info  pointer to device instance information
+ * buf   pointer to buffer contianing frame data
+ * size  count of data bytes in buf
+ */
+static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size)
 {
 	struct sk_buff *skb = dev_alloc_skb(size);
+	struct net_device *dev = info->netdev;
+	struct net_device_stats *stats = hdlc_stats(dev);
+
 	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("sppp_rx_done(%s)\n",info->netname);
+		printk("hdlcdev_rx(%s)\n",dev->name);
+
 	if (skb == NULL) {
-		printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n",
-			info->netname);
-		info->netstats.rx_dropped++;
+		printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", dev->name);
+		stats->rx_dropped++;
 		return;
 	}
 
 	memcpy(skb_put(skb, size),buf,size);
 
-	skb->protocol = htons(ETH_P_WAN_PPP);
-	skb->dev = info->netdev;
-	skb->mac.raw = skb->data;
-	info->netstats.rx_packets++;
-	info->netstats.rx_bytes += size;
+	skb->dev      = info->netdev;
+	skb->mac.raw  = skb->data;
+	skb->protocol = hdlc_type_trans(skb, skb->dev);
+
+	stats->rx_packets++;
+	stats->rx_bytes += size;
+
 	netif_rx(skb);
-	info->netdev->trans_start = jiffies;
-}
 
-static void sppp_tx_done(SLMP_INFO *info)
-{
-	if (netif_queue_stopped(info->netdev))
-	    netif_wake_queue(info->netdev);
+	info->netdev->last_rx = jiffies;
 }
 
-static struct net_device_stats *sppp_cb_net_stats(struct net_device *dev)
+/**
+ * called by device driver when adding device instance
+ * do generic HDLC initialization
+ *
+ * info  pointer to device instance information
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_init(SLMP_INFO *info)
 {
-	SLMP_INFO *info = dev->priv;
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("net_stats(%s)\n",info->netname);
-	return &info->netstats;
+	int rc;
+	struct net_device *dev;
+	hdlc_device *hdlc;
+
+	/* allocate and initialize network and HDLC layer objects */
+
+	if (!(dev = alloc_hdlcdev(info))) {
+		printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__);
+		return -ENOMEM;
+	}
+
+	/* for network layer reporting purposes only */
+	dev->mem_start = info->phys_sca_base;
+	dev->mem_end   = info->phys_sca_base + SCA_BASE_SIZE - 1;
+	dev->irq       = info->irq_level;
+
+	/* network layer callbacks and settings */
+	dev->do_ioctl       = hdlcdev_ioctl;
+	dev->open           = hdlcdev_open;
+	dev->stop           = hdlcdev_close;
+	dev->tx_timeout     = hdlcdev_tx_timeout;
+	dev->watchdog_timeo = 10*HZ;
+	dev->tx_queue_len   = 50;
+
+	/* generic HDLC layer callbacks and settings */
+	hdlc         = dev_to_hdlc(dev);
+	hdlc->attach = hdlcdev_attach;
+	hdlc->xmit   = hdlcdev_xmit;
+
+	/* register objects with HDLC layer */
+	if ((rc = register_hdlc_device(dev))) {
+		printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
+		free_netdev(dev);
+		return rc;
+	}
+
+	info->netdev = dev;
+	return 0;
 }
 
-static int sppp_cb_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+/**
+ * called by device driver when removing device instance
+ * do generic HDLC cleanup
+ *
+ * info  pointer to device instance information
+ */
+static void hdlcdev_exit(SLMP_INFO *info)
 {
-	SLMP_INFO *info = dev->priv;
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):ioctl %s cmd=%08X\n", __FILE__,__LINE__,
-			info->netname, cmd );
-	return sppp_do_ioctl(dev, ifr, cmd);
+	unregister_hdlc_device(info->netdev);
+	free_netdev(info->netdev);
+	info->netdev = NULL;
 }
 
-#endif /* ifdef CONFIG_SYNCLINK_SYNCPPP */
+#endif /* CONFIG_HDLC */
 
 
 /* Return next bottom half action to perform.
@@ -1941,13 +2143,7 @@ void bh_transmit(SLMP_INFO *info)
 			__FILE__,__LINE__,info->device_name);
 
 	if (tty) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup) {
-			if ( debug_level >= DEBUG_LEVEL_BH )
-				printk( "%s(%d):%s calling ldisc.write_wakeup\n",
-					__FILE__,__LINE__,info->device_name);
-			(tty->ldisc.write_wakeup)(tty);
-		}
+		tty_wakeup(tty);
 		wake_up_interruptible(&tty->write_wait);
 	}
 }
@@ -1994,16 +2190,15 @@ void isr_rxint(SLMP_INFO * info)
 {
  	struct tty_struct *tty = info->tty;
  	struct	mgsl_icount *icount = &info->icount;
-	unsigned char status = read_reg(info, SR1);
-	unsigned char status2 = read_reg(info, SR2);
+	unsigned char status = read_reg(info, SR1) & info->ie1_value & (FLGD + IDLD + CDCD + BRKD);
+	unsigned char status2 = read_reg(info, SR2) & info->ie2_value & OVRN;
 
 	/* clear status bits */
-	if ( status & (FLGD + IDLD + CDCD + BRKD) )
-		write_reg(info, SR1, 
-				(unsigned char)(status & (FLGD + IDLD + CDCD + BRKD)));
+	if (status)
+		write_reg(info, SR1, status);
 
-	if ( status2 & OVRN )
-		write_reg(info, SR2, (unsigned char)(status2 & OVRN));
+	if (status2)
+		write_reg(info, SR2, status2);
 	
 	if ( debug_level >= DEBUG_LEVEL_ISR )
 		printk("%s(%d):%s isr_rxint status=%02X %02x\n",
@@ -2140,15 +2335,22 @@ void isr_txeom(SLMP_INFO * info, unsigned char status)
 		printk("%s(%d):%s isr_txeom status=%02x\n",
 			__FILE__,__LINE__,info->device_name,status);
 
-	/* disable and clear MSCI interrupts */
-	info->ie1_value &= ~(IDLE + UDRN);
-	write_reg(info, IE1, info->ie1_value);
-	write_reg(info, SR1, (unsigned char)(UDRN + IDLE));
-
 	write_reg(info, TXDMA + DIR, 0x00); /* disable Tx DMA IRQs */
 	write_reg(info, TXDMA + DSR, 0xc0); /* clear IRQs and disable DMA */
 	write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
 
+	if (status & UDRN) {
+		write_reg(info, CMD, TXRESET);
+		write_reg(info, CMD, TXENABLE);
+	} else
+		write_reg(info, CMD, TXBUFCLR);
+
+	/* disable and clear tx interrupts */
+	info->ie0_value &= ~TXRDYE;
+	info->ie1_value &= ~(IDLE + UDRN);
+	write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value));
+	write_reg(info, SR1, (unsigned char)(UDRN + IDLE));
+
 	if ( info->tx_active ) {
 		if (info->params.mode != MGSL_MODE_ASYNC) {
 			if (status & UDRN)
@@ -2168,9 +2370,9 @@ void isr_txeom(SLMP_INFO * info, unsigned char status)
 			set_signals(info);
 		}
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
+#ifdef CONFIG_HDLC
 		if (info->netcount)
-			sppp_tx_done(info);
+			hdlcdev_tx_done(info);
 		else
 #endif
 		{
@@ -2189,10 +2391,10 @@ void isr_txeom(SLMP_INFO * info, unsigned char status)
  */
 void isr_txint(SLMP_INFO * info)
 {
-	unsigned char status = read_reg(info, SR1);
+	unsigned char status = read_reg(info, SR1) & info->ie1_value & (UDRN + IDLE + CCTS);
 
 	/* clear status bits */
-	write_reg(info, SR1, (unsigned char)(status & (UDRN + IDLE + CCTS)));
+	write_reg(info, SR1, status);
 
 	if ( debug_level >= DEBUG_LEVEL_ISR )
 		printk("%s(%d):%s isr_txint status=%02x\n",
@@ -2221,6 +2423,14 @@ void isr_txrdy(SLMP_INFO * info)
 		printk("%s(%d):%s isr_txrdy() tx_count=%d\n",
 			__FILE__,__LINE__,info->device_name,info->tx_count);
 
+	if (info->params.mode != MGSL_MODE_ASYNC) {
+		/* disable TXRDY IRQ, enable IDLE IRQ */
+		info->ie0_value &= ~TXRDYE;
+		info->ie1_value |= IDLE;
+		write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value));
+		return;
+	}
+
 	if (info->tty && (info->tty->stopped || info->tty->hw_stopped)) {
 		tx_stop(info);
 		return;
@@ -2275,13 +2485,6 @@ void isr_rxdmaerror(SLMP_INFO * info)
 
 void isr_txdmaok(SLMP_INFO * info)
 {
-	/* BIT7 = EOT (end of transfer, used for async mode)
-	 * BIT6 = EOM (end of message/frame, used for sync mode)
-	 *
-	 * We don't look at DMA status because only EOT is enabled
-	 * and we always clear and disable all tx DMA IRQs.
-	 */
-//	unsigned char dma_status = read_reg(info,TXDMA + DSR) & 0xc0;
 	unsigned char status_reg1 = read_reg(info, SR1);
 
 	write_reg(info, TXDMA + DIR, 0x00);	/* disable Tx DMA IRQs */
@@ -2292,19 +2495,10 @@ void isr_txdmaok(SLMP_INFO * info)
 		printk("%s(%d):%s isr_txdmaok(), status=%02x\n",
 			__FILE__,__LINE__,info->device_name,status_reg1);
 
-	/* If transmitter already idle, do end of frame processing,
-	 * otherwise enable interrupt for tx IDLE.
-	 */
-	if (status_reg1 & IDLE)
-		isr_txeom(info, IDLE);
-	else {
-		/* disable and clear underrun IRQ, enable IDLE interrupt */
-		info->ie1_value |= IDLE;
-		info->ie1_value &= ~UDRN;
-		write_reg(info, IE1, info->ie1_value);
-
-		write_reg(info, SR1, UDRN);
-	}
+	/* program TXRDY as FIFO empty flag, enable TXRDY IRQ */
+	write_reg16(info, TRC0, 0);
+	info->ie0_value |= TXRDYE;
+	write_reg(info, IE0, info->ie0_value);
 }
 
 void isr_txdmaerror(SLMP_INFO * info)
@@ -2358,12 +2552,12 @@ void isr_io_pin( SLMP_INFO *info, u16 status )
 			icount->dcd++;
 			if (status & SerialSignal_DCD) {
 				info->input_signal_events.dcd_up++;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-				if (info->netcount)
-					sppp_reopen(info->netdev);
-#endif
 			} else
 				info->input_signal_events.dcd_down++;
+#ifdef CONFIG_HDLC
+			if (info->netcount)
+				hdlc_set_carrier(status & SerialSignal_DCD, info->netdev);
+#endif
 		}
 		if (status & MISCSTATUS_CTS_LATCHED)
 		{
@@ -2577,7 +2771,7 @@ static int startup(SLMP_INFO * info)
 
 	change_params(info);
 
-	info->status_timer.expires = jiffies + jiffies_from_ms(10);
+	info->status_timer.expires = jiffies + msecs_to_jiffies(10);
 	add_timer(&info->status_timer);
 
 	if (info->tty)
@@ -2988,7 +3182,7 @@ static int wait_mgsl_event(SLMP_INFO * info, int __user *mask_ptr)
 		unsigned char oldval = info->ie1_value;
 		unsigned char newval = oldval +
 			 (mask & MgslEvent_ExitHuntMode ? FLGD:0) +
-			 (mask & MgslEvent_IdleReceived ? IDLE:0);
+			 (mask & MgslEvent_IdleReceived ? IDLD:0);
 		if ( oldval != newval ) {
 			info->ie1_value = newval;
 			write_reg(info, IE1, info->ie1_value);
@@ -3055,7 +3249,7 @@ static int wait_mgsl_event(SLMP_INFO * info, int __user *mask_ptr)
 		spin_lock_irqsave(&info->lock,flags);
 		if (!waitqueue_active(&info->event_wait_q)) {
 			/* disable enable exit hunt mode/idle rcvd IRQs */
-			info->ie1_value &= ~(FLGD|IDLE);
+			info->ie1_value &= ~(FLGD|IDLD);
 			write_reg(info, IE1, info->ie1_value);
 		}
 		spin_unlock_irqrestore(&info->lock,flags);
@@ -3449,9 +3643,10 @@ void free_tmp_rx_buf(SLMP_INFO *info)
 
 int claim_resources(SLMP_INFO *info)
 {
-	if (request_mem_region(info->phys_memory_base,0x40000,"synclinkmp") == NULL) {
+	if (request_mem_region(info->phys_memory_base,SCA_MEM_SIZE,"synclinkmp") == NULL) {
 		printk( "%s(%d):%s mem addr conflict, Addr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_memory_base);
+		info->init_error = DiagStatus_AddressConflict;
 		goto errout;
 	}
 	else
@@ -3460,22 +3655,25 @@ int claim_resources(SLMP_INFO *info)
 	if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclinkmp") == NULL) {
 		printk( "%s(%d):%s lcr mem addr conflict, Addr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_lcr_base);
+		info->init_error = DiagStatus_AddressConflict;
 		goto errout;
 	}
 	else
 		info->lcr_mem_requested = 1;
 
-	if (request_mem_region(info->phys_sca_base + info->sca_offset,512,"synclinkmp") == NULL) {
+	if (request_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE,"synclinkmp") == NULL) {
 		printk( "%s(%d):%s sca mem addr conflict, Addr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_sca_base);
+		info->init_error = DiagStatus_AddressConflict;
 		goto errout;
 	}
 	else
 		info->sca_base_requested = 1;
 
-	if (request_mem_region(info->phys_statctrl_base + info->statctrl_offset,16,"synclinkmp") == NULL) {
+	if (request_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE,"synclinkmp") == NULL) {
 		printk( "%s(%d):%s stat/ctrl mem addr conflict, Addr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_statctrl_base);
+		info->init_error = DiagStatus_AddressConflict;
 		goto errout;
 	}
 	else
@@ -3485,33 +3683,41 @@ int claim_resources(SLMP_INFO *info)
 	if (!info->memory_base) {
 		printk( "%s(%d):%s Cant map shared memory, MemAddr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_memory_base );
+		info->init_error = DiagStatus_CantAssignPciResources;
 		goto errout;
 	}
 
-	if ( !memory_test(info) ) {
-		printk( "%s(%d):Shared Memory Test failed for device %s MemAddr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->phys_memory_base );
-		goto errout;
-	}
-
-	info->lcr_base = ioremap(info->phys_lcr_base,PAGE_SIZE) + info->lcr_offset;
+	info->lcr_base = ioremap(info->phys_lcr_base,PAGE_SIZE);
 	if (!info->lcr_base) {
 		printk( "%s(%d):%s Cant map LCR memory, MemAddr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_lcr_base );
+		info->init_error = DiagStatus_CantAssignPciResources;
 		goto errout;
 	}
+	info->lcr_base += info->lcr_offset;
 
-	info->sca_base = ioremap(info->phys_sca_base,PAGE_SIZE) + info->sca_offset;
+	info->sca_base = ioremap(info->phys_sca_base,PAGE_SIZE);
 	if (!info->sca_base) {
 		printk( "%s(%d):%s Cant map SCA memory, MemAddr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_sca_base );
+		info->init_error = DiagStatus_CantAssignPciResources;
 		goto errout;
 	}
+	info->sca_base += info->sca_offset;
 
-	info->statctrl_base = ioremap(info->phys_statctrl_base,PAGE_SIZE) + info->statctrl_offset;
+	info->statctrl_base = ioremap(info->phys_statctrl_base,PAGE_SIZE);
 	if (!info->statctrl_base) {
 		printk( "%s(%d):%s Cant map SCA Status/Control memory, MemAddr=%08X\n",
 			__FILE__,__LINE__,info->device_name, info->phys_statctrl_base );
+		info->init_error = DiagStatus_CantAssignPciResources;
+		goto errout;
+	}
+	info->statctrl_base += info->statctrl_offset;
+
+	if ( !memory_test(info) ) {
+		printk( "%s(%d):Shared Memory Test failed for device %s MemAddr=%08X\n",
+			__FILE__,__LINE__,info->device_name, info->phys_memory_base );
+		info->init_error = DiagStatus_MemoryError;
 		goto errout;
 	}
 
@@ -3534,7 +3740,7 @@ void release_resources(SLMP_INFO *info)
 	}
 
 	if ( info->shared_mem_requested ) {
-		release_mem_region(info->phys_memory_base,0x40000);
+		release_mem_region(info->phys_memory_base,SCA_MEM_SIZE);
 		info->shared_mem_requested = 0;
 	}
 	if ( info->lcr_mem_requested ) {
@@ -3542,11 +3748,11 @@ void release_resources(SLMP_INFO *info)
 		info->lcr_mem_requested = 0;
 	}
 	if ( info->sca_base_requested ) {
-		release_mem_region(info->phys_sca_base + info->sca_offset,512);
+		release_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE);
 		info->sca_base_requested = 0;
 	}
 	if ( info->sca_statctrl_requested ) {
-		release_mem_region(info->phys_statctrl_base + info->statctrl_offset,16);
+		release_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE);
 		info->sca_statctrl_requested = 0;
 	}
 
@@ -3616,9 +3822,8 @@ void add_device(SLMP_INFO *info)
 		info->irq_level,
 		info->max_frame_size );
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-	if (info->dosyncppp)
-		sppp_init(info);
+#ifdef CONFIG_HDLC
+	hdlcdev_init(info);
 #endif
 }
 
@@ -3788,7 +3993,6 @@ static struct tty_operations ops = {
 
 static void synclinkmp_cleanup(void)
 {
-	unsigned long flags;
 	int rc;
 	SLMP_INFO *info;
 	SLMP_INFO *tmp;
@@ -3802,34 +4006,24 @@ static void synclinkmp_cleanup(void)
 		put_tty_driver(serial_driver);
 	}
 
+	/* reset devices */
 	info = synclinkmp_device_list;
 	while(info) {
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-		if (info->dosyncppp)
-			sppp_delete(info);
-#endif
 		reset_port(info);
-		if ( info->port_num == 0 ) {
-			if ( info->irq_requested ) {
-				free_irq(info->irq_level, info);
-				info->irq_requested = 0;
-			}
-		}
 		info = info->next_device;
 	}
 
-	/* port 0 of each adapter originally claimed
-	 * all resources, release those now
-	 */
+	/* release devices */
 	info = synclinkmp_device_list;
 	while(info) {
+#ifdef CONFIG_HDLC
+		hdlcdev_exit(info);
+#endif
 		free_dma_bufs(info);
 		free_tmp_rx_buf(info);
 		if ( info->port_num == 0 ) {
-			spin_lock_irqsave(&info->lock,flags);
-			reset_adapter(info);
-			write_reg(info, LPR, 1);		/* set low power mode */
-			spin_unlock_irqrestore(&info->lock,flags);
+			if (info->sca_base)
+				write_reg(info, LPR, 1); /* set low power mode */
 			release_resources(info);
 		}
 		tmp = info;
@@ -4112,6 +4306,9 @@ void tx_start(SLMP_INFO *info)
 				}
 			}
 
+			write_reg16(info, TRC0,
+				(unsigned short)(((tx_negate_fifo_level-1)<<8) + tx_active_fifo_level));
+
 			write_reg(info, TXDMA + DSR, 0); 		/* disable DMA channel */
 			write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
 	
@@ -4123,17 +4320,16 @@ void tx_start(SLMP_INFO *info)
 			write_reg16(info, TXDMA + EDA,
 				info->tx_buf_list_ex[info->last_tx_buf].phys_entry);
 	
-			/* clear IDLE and UDRN status bit */
-			info->ie1_value &= ~(IDLE + UDRN);
-			if (info->params.mode != MGSL_MODE_ASYNC)
-				info->ie1_value |= UDRN;     		/* HDLC, IRQ on underrun */
-			write_reg(info, IE1, info->ie1_value);	/* enable MSCI interrupts */
+			/* enable underrun IRQ */
+			info->ie1_value &= ~IDLE;
+			info->ie1_value |= UDRN;
+			write_reg(info, IE1, info->ie1_value);
 			write_reg(info, SR1, (unsigned char)(IDLE + UDRN));
 	
 			write_reg(info, TXDMA + DIR, 0x40);		/* enable Tx DMA interrupts (EOM) */
 			write_reg(info, TXDMA + DSR, 0xf2);		/* clear Tx DMA IRQs, enable Tx DMA */
 	
-			info->tx_timer.expires = jiffies + jiffies_from_ms(5000);
+			info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
 			add_timer(&info->tx_timer);
 		}
 		else {
@@ -4823,10 +5019,12 @@ CheckAgain:
 			info->icount.rxcrc++;
 
 		framesize = 0;
-
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-		info->netstats.rx_errors++;
-		info->netstats.rx_frame_errors++;
+#ifdef CONFIG_HDLC
+		{
+			struct net_device_stats *stats = hdlc_stats(info->netdev);
+			stats->rx_errors++;
+			stats->rx_frame_errors++;
+		}
 #endif
 	}
 
@@ -4836,7 +5034,7 @@ CheckAgain:
 
 	if ( debug_level >= DEBUG_LEVEL_DATA )
 		trace_block(info,info->rx_buf_list_ex[StartIndex].virt_addr,
-			MIN(framesize,SCABUFSIZE),0);
+			min_t(int, framesize,SCABUFSIZE),0);
 
 	if (framesize) {
 		if (framesize > info->max_frame_size)
@@ -4851,7 +5049,7 @@ CheckAgain:
 			info->icount.rxok++;
 
 			while(copy_count) {
-				int partial_count = MIN(copy_count,SCABUFSIZE);
+				int partial_count = min(copy_count,SCABUFSIZE);
 				memcpy( ptmp,
 					info->rx_buf_list_ex[index].virt_addr,
 					partial_count );
@@ -4862,22 +5060,13 @@ CheckAgain:
 					index = 0;
 			}
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-			if (info->netcount) {
-				/* pass frame to syncppp device */
-				sppp_rx_done(info,info->tmp_rx_buf,framesize);
-			}
+#ifdef CONFIG_HDLC
+			if (info->netcount)
+				hdlcdev_rx(info,info->tmp_rx_buf,framesize);
 			else
 #endif
-			{
-				if ( tty && tty->ldisc.receive_buf ) {
-					/* Call the line discipline receive callback directly. */
-					tty->ldisc.receive_buf(tty,
-						info->tmp_rx_buf,
-						info->flag_buf,
-						framesize);
-				}
-			}
+				ldisc_receive_buf(tty,info->tmp_rx_buf,
+						  info->flag_buf, framesize);
 		}
 	}
 	/* Free the buffers used by this frame. */
@@ -4910,14 +5099,14 @@ void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int count)
 	SCADESC_EX *desc_ex;
 
 	if ( debug_level >= DEBUG_LEVEL_DATA )
-		trace_block(info,buf, MIN(count,SCABUFSIZE), 1);
+		trace_block(info,buf, min_t(int, count,SCABUFSIZE), 1);
 
 	/* Copy source buffer to one or more DMA buffers, starting with
 	 * the first transmit dma buffer.
 	 */
 	for(i=0;;)
 	{
-		copy_count = MIN(count,SCABUFSIZE);
+		copy_count = min_t(unsigned short,count,SCABUFSIZE);
 
 		desc = &info->tx_buf_list[i];
 		desc_ex = &info->tx_buf_list_ex[i];
@@ -5021,7 +5210,7 @@ int irq_test(SLMP_INFO *info)
 	timeout=100;
 	while( timeout-- && !info->irq_occurred ) {
 		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(jiffies_from_ms(10));
+		schedule_timeout(msecs_to_jiffies(10));
 	}
 
 	spin_lock_irqsave(&info->lock,flags);
@@ -5172,7 +5361,7 @@ int loopback_test(SLMP_INFO *info)
 	/* Set a timeout for waiting for interrupt. */
 	for ( timeout = 100; timeout; --timeout ) {
 		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(jiffies_from_ms(10));
+		schedule_timeout(msecs_to_jiffies(10));
 
 		if (rx_get_frame(info)) {
 			rc = TRUE;
@@ -5384,9 +5573,9 @@ void tx_timeout(unsigned long context)
 
 	spin_unlock_irqrestore(&info->lock,flags);
 
-#ifdef CONFIG_SYNCLINK_SYNCPPP
+#ifdef CONFIG_HDLC
 	if (info->netcount)
-		sppp_tx_done(info);
+		hdlcdev_tx_done(info);
 	else
 #endif
 		bh_transmit(info);
@@ -5428,7 +5617,7 @@ void status_timeout(unsigned long context)
 
 	info->status_timer.data = (unsigned long)info;
 	info->status_timer.function = status_timeout;
-	info->status_timer.expires = jiffies + jiffies_from_ms(10);
+	info->status_timer.expires = jiffies + msecs_to_jiffies(10);
 	add_timer(&info->status_timer);
 }
 
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 91f530c61..9691b8ea6 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -92,6 +92,7 @@
 #include <linux/smp_lock.h>
 #include <linux/device.h>
 #include <linux/idr.h>
+#include <linux/wait.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -101,6 +102,7 @@
 #include <linux/vt_kern.h>
 #include <linux/selection.h>
 #include <linux/devfs_fs_kernel.h>
+#include <linux/vs_cvirt.h>
 
 #include <linux/kmod.h>
 
@@ -120,10 +122,14 @@ struct termios tty_std_termios = {	/* for the benefit of tty drivers  */
 
 EXPORT_SYMBOL(tty_std_termios);
 
+/* This list gets poked at by procfs and various bits of boot up code. This
+   could do with some rationalisation such as pulling the tty proc function
+   into this file */
+   
 LIST_HEAD(tty_drivers);			/* linked list of tty drivers */
-struct tty_ldisc ldiscs[NR_LDISCS];	/* line disc dispatch table	*/
 
-/* Semaphore to protect creating and releasing a tty */
+/* Semaphore to protect creating and releasing a tty. This is shared with
+   vt.c for deeply disgusting hack reasons */
 DECLARE_MUTEX(tty_sem);
 
 #ifdef CONFIG_UNIX98_PTYS
@@ -142,6 +148,7 @@ static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *);
 ssize_t redirected_tty_write(struct file *, const char __user *, size_t, loff_t *);
 static unsigned int tty_poll(struct file *, poll_table *);
 static int tty_open(struct inode *, struct file *);
+static int ptmx_open(struct inode *, struct file *);
 static int tty_release(struct inode *, struct file *);
 int tty_ioctl(struct inode * inode, struct file * file,
 	      unsigned int cmd, unsigned long arg);
@@ -223,65 +230,323 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
 	return 0;
 }
 
+/*
+ *	This is probably overkill for real world processors but
+ *	they are not on hot paths so a little discipline won't do 
+ *	any harm.
+ */
+ 
+static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
+{
+	down(&tty->termios_sem);
+	tty->termios->c_line = num;
+	up(&tty->termios_sem);
+}
+
+/*
+ *	This guards the refcounted line discipline lists. The lock
+ *	must be taken with irqs off because there are hangup path
+ *	callers who will do ldisc lookups and cannot sleep.
+ */
+ 
+static spinlock_t tty_ldisc_lock = SPIN_LOCK_UNLOCKED;
+static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
+static struct tty_ldisc tty_ldiscs[NR_LDISCS];	/* line disc dispatch table	*/
+
 int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
 {
+	unsigned long flags;
+	int ret = 0;
+	
 	if (disc < N_TTY || disc >= NR_LDISCS)
 		return -EINVAL;
 	
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
 	if (new_ldisc) {
-		ldiscs[disc] = *new_ldisc;
-		ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
-		ldiscs[disc].num = disc;
-	} else
-		memset(&ldiscs[disc], 0, sizeof(struct tty_ldisc));
+		tty_ldiscs[disc] = *new_ldisc;
+		tty_ldiscs[disc].num = disc;
+		tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
+		tty_ldiscs[disc].refcount = 0;
+	} else {
+		if(tty_ldiscs[disc].refcount)
+			ret = -EBUSY;
+		else
+			tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED;
+	}
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
 	
-	return 0;
+	return ret;
 }
 
 EXPORT_SYMBOL(tty_register_ldisc);
 
-/* Set the discipline of a tty line. */
+struct tty_ldisc *tty_ldisc_get(int disc)
+{
+	unsigned long flags;
+	struct tty_ldisc *ld;
+
+	if (disc < N_TTY || disc >= NR_LDISCS)
+		return NULL;
+	
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
+
+	ld = &tty_ldiscs[disc];
+	/* Check the entry is defined */
+	if(ld->flags & LDISC_FLAG_DEFINED)
+	{
+		/* If the module is being unloaded we can't use it */
+		if (!try_module_get(ld->owner))
+		       	ld = NULL;
+		else /* lock it */
+			ld->refcount++;
+	}
+	else
+		ld = NULL;
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+	return ld;
+}
+
+EXPORT_SYMBOL_GPL(tty_ldisc_get);
+
+void tty_ldisc_put(int disc)
+{
+	struct tty_ldisc *ld;
+	unsigned long flags;
+	
+	if (disc < N_TTY || disc >= NR_LDISCS)
+		BUG();
+		
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	ld = &tty_ldiscs[disc];
+	if(ld->refcount == 0)
+		BUG();
+	ld->refcount --;
+	module_put(ld->owner);
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+}
+	
+EXPORT_SYMBOL_GPL(tty_ldisc_put);
+
+void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
+{
+	tty->ldisc = *ld;
+	tty->ldisc.refcount = 0;
+}
+
+/**
+ *	tty_ldisc_try		-	internal helper
+ *	@tty: the tty
+ *
+ *	Make a single attempt to grab and bump the refcount on
+ *	the tty ldisc. Return 0 on failure or 1 on success. This is
+ *	used to implement both the waiting and non waiting versions
+ *	of tty_ldisc_ref
+ */
+
+static int tty_ldisc_try(struct tty_struct *tty)
+{
+	unsigned long flags;
+	struct tty_ldisc *ld;
+	int ret = 0;
+	
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	ld = &tty->ldisc;
+	if(test_bit(TTY_LDISC, &tty->flags))
+	{
+		ld->refcount++;
+		ret = 1;
+	}
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+	return ret;
+}
+
+/**
+ *	tty_ldisc_ref_wait	-	wait for the tty ldisc
+ *	@tty: tty device
+ *
+ *	Dereference the line discipline for the terminal and take a 
+ *	reference to it. If the line discipline is in flux then 
+ *	wait patiently until it changes.
+ *
+ *	Note: Must not be called from an IRQ/timer context. The caller
+ *	must also be careful not to hold other locks that will deadlock
+ *	against a discipline change, such as an existing ldisc reference
+ *	(which we check for)
+ */
+ 
+struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
+{
+	/* wait_event is a macro */
+	wait_event(tty_ldisc_wait, tty_ldisc_try(tty));
+	if(tty->ldisc.refcount == 0)
+		printk(KERN_ERR "tty_ldisc_ref_wait\n");
+	return &tty->ldisc;
+}
+
+EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
+
+/**
+ *	tty_ldisc_ref		-	get the tty ldisc
+ *	@tty: tty device
+ *
+ *	Dereference the line discipline for the terminal and take a 
+ *	reference to it. If the line discipline is in flux then 
+ *	return NULL. Can be called from IRQ and timer functions.
+ */
+ 
+struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
+{
+	if(tty_ldisc_try(tty))
+		return &tty->ldisc;
+	return NULL;
+}
+
+EXPORT_SYMBOL_GPL(tty_ldisc_ref);
+
+/**
+ *	tty_ldisc_deref		-	free a tty ldisc reference
+ *	@ld: reference to free up
+ *
+ *	Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May
+ *	be called in IRQ context.
+ */
+ 
+void tty_ldisc_deref(struct tty_ldisc *ld)
+{
+	unsigned long flags;
+
+	if(ld == NULL)
+		BUG();
+		
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	if(ld->refcount == 0)
+		printk(KERN_ERR "tty_ldisc_deref: no references.\n");
+	else
+		ld->refcount--;
+	if(ld->refcount == 0)
+		wake_up(&tty_ldisc_wait);
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+}
+
+EXPORT_SYMBOL_GPL(tty_ldisc_deref);
+
+/**
+ *	tty_ldisc_enable	-	allow ldisc use
+ *	@tty: terminal to activate ldisc on
+ *
+ *	Set the TTY_LDISC flag when the line discipline can be called
+ *	again. Do neccessary wakeups for existing sleepers.
+ *
+ *	Note: nobody should set this bit except via this function. Clearing
+ *	directly is allowed.
+ */
+
+static void tty_ldisc_enable(struct tty_struct *tty)
+{
+	set_bit(TTY_LDISC, &tty->flags);
+	wake_up(&tty_ldisc_wait);
+}
+	
+/**
+ *	tty_set_ldisc		-	set line discipline
+ *	@tty: the terminal to set
+ *	@ldisc: the line discipline
+ *
+ *	Set the discipline of a tty line. Must be called from a process
+ *	context.
+ */
+ 
 static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 {
 	int	retval = 0;
 	struct	tty_ldisc o_ldisc;
 	char buf[64];
+	int work;
+	unsigned long flags;
+	struct tty_ldisc *ld;
 
 	if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS))
 		return -EINVAL;
+
+restart:
+
+	if (tty->ldisc.num == ldisc)
+		return 0;	/* We are already in the desired discipline */
+	
+	ld = tty_ldisc_get(ldisc);
 	/* Eduardo Blanco <ejbs@cs.cs.com.uy> */
 	/* Cyrus Durgin <cider@speakeasy.org> */
-	if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED)) {
+	if (ld == NULL) {
 		request_module("tty-ldisc-%d", ldisc);
+		ld = tty_ldisc_get(ldisc);
 	}
-	if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED))
+	if (ld == NULL)
 		return -EINVAL;
 
-	if (tty->ldisc.num == ldisc)
-		return 0;	/* We are already in the desired discipline */
-
-	if (!try_module_get(ldiscs[ldisc].owner))
-	       	return -EINVAL;
-	
 	o_ldisc = tty->ldisc;
 
 	tty_wait_until_sent(tty, 0);
+
+	/*
+	 *	Make sure we don't change while someone holds a
+	 *	reference to the line discipline. The TTY_LDISC bit
+	 *	prevents anyone taking a reference once it is clear.
+	 *	We need the lock to avoid racing reference takers.
+	 */
+	 
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	if(tty->ldisc.refcount)
+	{
+		/* Free the new ldisc we grabbed. Must drop the lock
+		   first. */
+		spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+		tty_ldisc_put(ldisc);
+		/*
+		 * There are several reasons we may be busy, including
+		 * random momentary I/O traffic. We must therefore
+		 * retry. We could distinguish between blocking ops
+		 * and retries if we made tty_ldisc_wait() smarter. That
+		 * is up for discussion.
+		 */
+		if(wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0)
+			return -ERESTARTSYS;			
+		goto restart;
+	}
+	clear_bit(TTY_LDISC, &tty->flags);	
+	clear_bit(TTY_DONT_FLIP, &tty->flags);
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
 	
+	/*
+	 *	From this point on we know nobody has an ldisc
+	 *	usage reference, nor can they obtain one until
+	 *	we say so later on.
+	 */
+	 
+	work = cancel_delayed_work(&tty->flip.work);
+	/*
+	 * Wait for ->hangup_work and ->flip.work handlers to terminate
+	 */
+	 
+	flush_scheduled_work();
 	/* Shutdown the current discipline. */
 	if (tty->ldisc.close)
 		(tty->ldisc.close)(tty);
 
 	/* Now set up the new line discipline. */
-	tty->ldisc = ldiscs[ldisc];
-	tty->termios->c_line = ldisc;
+	tty_ldisc_assign(tty, ld);
+	tty_set_termios_ldisc(tty, ldisc);
 	if (tty->ldisc.open)
 		retval = (tty->ldisc.open)(tty);
 	if (retval < 0) {
-		tty->ldisc = o_ldisc;
-		tty->termios->c_line = tty->ldisc.num;
+		tty_ldisc_put(ldisc);
+		/* There is an outstanding reference here so this is safe */
+		tty_ldisc_assign(tty, tty_ldisc_get(o_ldisc.num));
+		tty_set_termios_ldisc(tty, tty->ldisc.num);
 		if (tty->ldisc.open && (tty->ldisc.open(tty) < 0)) {
-			tty->ldisc = ldiscs[N_TTY];
-			tty->termios->c_line = N_TTY;
+			tty_ldisc_put(o_ldisc.num);
+			/* This driver is always present */
+			tty_ldisc_assign(tty, tty_ldisc_get(N_TTY));
+			tty_set_termios_ldisc(tty, N_TTY);
 			if (tty->ldisc.open) {
 				int r = tty->ldisc.open(tty);
 
@@ -291,12 +556,27 @@ static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 					      tty_name(tty, buf), r);
 			}
 		}
-	} else {
-		module_put(o_ldisc.owner);
 	}
+	/* At this point we hold a reference to the new ldisc and a
+	   a reference to the old ldisc. If we ended up flipping back
+	   to the existing ldisc we have two references to it */
 	
 	if (tty->ldisc.num != o_ldisc.num && tty->driver->set_ldisc)
 		tty->driver->set_ldisc(tty);
+		
+	tty_ldisc_put(o_ldisc.num);
+	
+	/*
+	 *	Allow ldisc referencing to occur as soon as the driver
+	 *	ldisc callback completes.
+	 */
+	 
+	tty_ldisc_enable(tty);
+	
+	/* Restart it in case no characters kick it off. Safe if
+	   already running */
+	if(work)
+		schedule_delayed_work(&tty->flip.work, 1);
 	return retval;
 }
 
@@ -377,6 +657,19 @@ static struct file_operations tty_fops = {
 	.fasync		= tty_fasync,
 };
 
+#ifdef CONFIG_UNIX98_PTYS
+static struct file_operations ptmx_fops = {
+	.llseek		= no_llseek,
+	.read		= tty_read,
+	.write		= tty_write,
+	.poll		= tty_poll,
+	.ioctl		= tty_ioctl,
+	.open		= ptmx_open,
+	.release	= tty_release,
+	.fasync		= tty_fasync,
+};
+#endif
+
 static struct file_operations console_fops = {
 	.llseek		= no_llseek,
 	.read		= tty_read,
@@ -399,6 +692,53 @@ static struct file_operations hung_up_tty_fops = {
 
 static spinlock_t redirect_lock = SPIN_LOCK_UNLOCKED;
 static struct file *redirect;
+
+/**
+ *	tty_wakeup	-	request more data
+ *	@tty: terminal
+ *
+ *	Internal and external helper for wakeups of tty. This function
+ *	informs the line discipline if present that the driver is ready
+ *	to receive more output data.
+ */
+ 
+void tty_wakeup(struct tty_struct *tty)
+{
+	struct tty_ldisc *ld;
+	
+	if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) {
+		ld = tty_ldisc_ref(tty);
+		if(ld) {
+			if(ld->write_wakeup)
+				ld->write_wakeup(tty);
+			tty_ldisc_deref(ld);
+		}
+	}
+	wake_up_interruptible(&tty->write_wait);
+}
+
+EXPORT_SYMBOL_GPL(tty_wakeup);
+
+/**
+ *	tty_ldisc_flush	-	flush line discipline queue
+ *	@tty: tty
+ *
+ *	Flush the line discipline queue (if any) for this tty. If there
+ *	is no line discipline active this is a no-op.
+ */
+ 
+void tty_ldisc_flush(struct tty_struct *tty)
+{
+	struct tty_ldisc *ld = tty_ldisc_ref(tty);
+	if(ld) {
+		if(ld->flush_buffer)
+			ld->flush_buffer(tty);
+		tty_ldisc_deref(ld);
+	}
+}
+
+EXPORT_SYMBOL_GPL(tty_ldisc_flush);
+	
 /*
  * This can be called by the "eventd" kernel thread.  That is process synchronous,
  * but doesn't hold any locks, so we need to make sure we have the appropriate
@@ -410,7 +750,7 @@ void do_tty_hangup(void *data)
 	struct file * cons_filp = NULL;
 	struct file *filp, *f = NULL;
 	struct task_struct *p;
-	struct pid *pid;
+	struct tty_ldisc *ld;
 	int    closecount = 0, n;
 
 	if (!tty)
@@ -428,6 +768,7 @@ void do_tty_hangup(void *data)
 	
 	check_tty_count(tty, "do_tty_hangup");
 	file_list_lock();
+	/* This breaks for file handles being sent over AF_UNIX sockets ? */
 	list_for_each_entry(filp, &tty->tty_files, f_list) {
 		if (filp->f_op->write == redirected_tty_write)
 			cons_filp = filp;
@@ -440,21 +781,25 @@ void do_tty_hangup(void *data)
 	file_list_unlock();
 	
 	/* FIXME! What are the locking issues here? This may me overdoing things..
-	* this question is especially important now that we've removed the irqlock. */
-	{
-		unsigned long flags;
+	 * this question is especially important now that we've removed the irqlock. */
 
-		local_irq_save(flags); // FIXME: is this safe?
-		if (tty->ldisc.flush_buffer)
-			tty->ldisc.flush_buffer(tty);
+	ld = tty_ldisc_ref(tty);
+	if(ld != NULL)	/* We may have no line discipline at this point */
+	{
+		if (ld->flush_buffer)
+			ld->flush_buffer(tty);
 		if (tty->driver->flush_buffer)
 			tty->driver->flush_buffer(tty);
 		if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		local_irq_restore(flags); // FIXME: is this safe?
+		    ld->write_wakeup)
+			ld->write_wakeup(tty);
+		if (ld->hangup)
+			ld->hangup(tty);
 	}
 
+	/* FIXME: Once we trust the LDISC code better we can wait here for
+	   ldisc completion and fix the driver call race */
+	   
 	wake_up_interruptible(&tty->write_wait);
 	wake_up_interruptible(&tty->read_wait);
 
@@ -463,26 +808,21 @@ void do_tty_hangup(void *data)
 	 * N_TTY.
 	 */
 	if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
+	{
+		down(&tty->termios_sem);
 		*tty->termios = tty->driver->init_termios;
-	if (tty->ldisc.num != ldiscs[N_TTY].num) {
-		if (tty->ldisc.close)
-			(tty->ldisc.close)(tty);
-		module_put(tty->ldisc.owner);
-		
-		tty->ldisc = ldiscs[N_TTY];
-		tty->termios->c_line = N_TTY;
-		if (tty->ldisc.open) {
-			int i = (tty->ldisc.open)(tty);
-			if (i < 0)
-				printk(KERN_ERR "do_tty_hangup: N_TTY open: "
-						"error %d\n", -i);
-		}
+		up(&tty->termios_sem);
 	}
 	
+	/* Defer ldisc switch */
+	/* tty_deferred_ldisc_switch(N_TTY);
+	
+	  This should get done automatically when the port closes and
+	  tty_release is called */
+	
 	read_lock(&tasklist_lock);
 	if (tty->session > 0) {
-		struct list_head *l;
-		for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid) {
+		do_each_task_pid(tty->session, PIDTYPE_SID, p) {
 			if (p->signal->tty == tty)
 				p->signal->tty = NULL;
 			if (!p->signal->leader)
@@ -491,7 +831,7 @@ void do_tty_hangup(void *data)
 			send_group_sig_info(SIGCONT, SEND_SIG_PRIV, p);
 			if (tty->pgrp > 0)
 				p->signal->tty_old_pgrp = tty->pgrp;
-		}
+		} while_each_task_pid(tty->session, PIDTYPE_SID, p);
 	}
 	read_unlock(&tasklist_lock);
 
@@ -511,6 +851,17 @@ void do_tty_hangup(void *data)
 				tty->driver->close(tty, cons_filp);
 	} else if (tty->driver->hangup)
 		(tty->driver->hangup)(tty);
+		
+	/* We don't want to have driver/ldisc interactions beyond
+	   the ones we did here. The driver layer expects no
+	   calls after ->hangup() from the ldisc side. However we
+	   can't yet guarantee all that */
+
+	set_bit(TTY_HUPPED, &tty->flags);
+	if (ld) {
+		tty_ldisc_enable(tty);
+		tty_ldisc_deref(ld);
+	}
 	unlock_kernel();
 	if (f)
 		fput(f);
@@ -563,8 +914,6 @@ void disassociate_ctty(int on_exit)
 {
 	struct tty_struct *tty;
 	struct task_struct *p;
-	struct list_head *l;
-	struct pid *pid;
 	int tty_pgrp = -1;
 
 	lock_kernel();
@@ -593,8 +942,9 @@ void disassociate_ctty(int on_exit)
 	tty->pgrp = -1;
 
 	read_lock(&tasklist_lock);
-	for_each_task_pid(current->signal->session, PIDTYPE_SID, p, l, pid)
+	do_each_task_pid(current->signal->session, PIDTYPE_SID, p) {
 		p->signal->tty = NULL;
+	} while_each_task_pid(current->signal->session, PIDTYPE_SID, p);
 	read_unlock(&tasklist_lock);
 	unlock_kernel();
 }
@@ -627,9 +977,9 @@ void start_tty(struct tty_struct *tty)
 	}
 	if (tty->driver->start)
 		(tty->driver->start)(tty);
-	if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+
+	/* If we have a running line discipline it may need kicking */
+	tty_wakeup(tty);
 	wake_up_interruptible(&tty->write_wait);
 }
 
@@ -641,6 +991,7 @@ static ssize_t tty_read(struct file * file, char __user * buf, size_t count,
 	int i;
 	struct tty_struct * tty;
 	struct inode *inode;
+	struct tty_ldisc *ld;
 
 	tty = (struct tty_struct *)file->private_data;
 	inode = file->f_dentry->d_inode;
@@ -649,11 +1000,15 @@ static ssize_t tty_read(struct file * file, char __user * buf, size_t count,
 	if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
 		return -EIO;
 
+	/* We want to wait for the line discipline to sort out in this
+	   situation */
+	ld = tty_ldisc_ref_wait(tty);
 	lock_kernel();
-	if (tty->ldisc.read)
-		i = (tty->ldisc.read)(tty,file,buf,count);
+	if (ld->read)
+		i = (ld->read)(tty,file,buf,count);
 	else
 		i = -EIO;
+	tty_ldisc_deref(ld);
 	unlock_kernel();
 	if (i > 0)
 		inode->i_atime = CURRENT_TIME;
@@ -715,16 +1070,23 @@ static ssize_t tty_write(struct file * file, const char __user * buf, size_t cou
 {
 	struct tty_struct * tty;
 	struct inode *inode = file->f_dentry->d_inode;
-
+	ssize_t ret;
+	struct tty_ldisc *ld;
+	
 	tty = (struct tty_struct *)file->private_data;
 	if (tty_paranoia_check(tty, inode, "tty_write"))
 		return -EIO;
 	if (!tty || !tty->driver->write || (test_bit(TTY_IO_ERROR, &tty->flags)))
 		return -EIO;
-	if (!tty->ldisc.write)
-		return -EIO;
-	return do_tty_write(tty->ldisc.write, tty, file,
+
+	ld = tty_ldisc_ref_wait(tty);		
+	if (!ld->write)
+		ret = -EIO;
+	else
+		ret = do_tty_write(ld->write, tty, file,
 			    (const unsigned char __user *)buf, count);
+	tty_ldisc_deref(ld);
+	return ret;
 }
 
 ssize_t redirected_tty_write(struct file * file, const char __user * buf, size_t count,
@@ -749,6 +1111,17 @@ ssize_t redirected_tty_write(struct file * file, const char __user * buf, size_t
 	return tty_write(file, buf, count, ppos);
 }
 
+static char ptychar[] = "pqrstuvwxyzabcde";
+
+static inline void pty_line_name(struct tty_driver *driver, int index, char *p)
+{
+	int i = index + driver->name_base;
+	/* ->name is initialized to "ttyp", but "tty" is expected */
+	sprintf(p, "%s%c%x",
+			driver->subtype == PTY_TYPE_SLAVE ? "tty" : driver->name,
+			ptychar[i >> 4 & 0xf], i & 0xf);
+}
+
 static inline void tty_line_name(struct tty_driver *driver, int index, char *p)
 {
 	sprintf(p, "%s%d", driver->name, index + driver->name_base);
@@ -910,6 +1283,7 @@ static int init_dev(struct tty_driver *driver, int idx,
 	 * If we fail here just call release_mem to clean up.  No need
 	 * to decrement the use counts, as release_mem doesn't care.
 	 */
+
 	if (tty->ldisc.open) {
 		retval = (tty->ldisc.open)(tty);
 		if (retval)
@@ -922,7 +1296,9 @@ static int init_dev(struct tty_driver *driver, int idx,
 				(tty->ldisc.close)(tty);
 			goto release_mem_out;
 		}
+		tty_ldisc_enable(o_tty);
 	}
+	tty_ldisc_enable(tty);
 	goto success;
 
 	/*
@@ -951,6 +1327,9 @@ fast_track:
 	tty->count++;
 	tty->driver = driver; /* N.B. why do this every time?? */
 
+	/* FIXME */
+	if(!test_bit(TTY_LDISC, &tty->flags))
+		printk(KERN_ERR "init_dev but no ldisc\n");
 success:
 	*ret_tty = tty;
 	
@@ -1054,6 +1433,7 @@ static void release_dev(struct file * filp)
 	int	devpts_master, devpts;
 	int	idx;
 	char	buf[64];
+	unsigned long flags;
 	
 	tty = (struct tty_struct *)filp->private_data;
 	if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "release_dev"))
@@ -1130,7 +1510,6 @@ static void release_dev(struct file * filp)
 		}
 	}
 #endif
-
 	if (tty->driver->close)
 		tty->driver->close(tty, filp);
 
@@ -1235,15 +1614,15 @@ static void release_dev(struct file * filp)
 	 */
 	if (tty_closing || o_tty_closing) {
 		struct task_struct *p;
-		struct list_head *l;
-		struct pid *pid;
 
 		read_lock(&tasklist_lock);
-		for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid)
+		do_each_task_pid(tty->session, PIDTYPE_SID, p) {
 			p->signal->tty = NULL;
+		} while_each_task_pid(tty->session, PIDTYPE_SID, p);
 		if (o_tty)
-			for_each_task_pid(o_tty->session, PIDTYPE_SID, p,l, pid)
+			do_each_task_pid(o_tty->session, PIDTYPE_SID, p) {
 				p->signal->tty = NULL;
+			} while_each_task_pid(o_tty->session, PIDTYPE_SID, p);
 		read_unlock(&tasklist_lock);
 	}
 
@@ -1254,36 +1633,58 @@ static void release_dev(struct file * filp)
 #ifdef TTY_DEBUG_HANGUP
 	printk(KERN_DEBUG "freeing tty structure...");
 #endif
-
 	/*
 	 * Prevent flush_to_ldisc() from rescheduling the work for later.  Then
-	 * kill any delayed work.
+	 * kill any delayed work. As this is the final close it does not
+	 * race with the set_ldisc code path.
 	 */
+	clear_bit(TTY_LDISC, &tty->flags);
 	clear_bit(TTY_DONT_FLIP, &tty->flags);
 	cancel_delayed_work(&tty->flip.work);
 
 	/*
 	 * Wait for ->hangup_work and ->flip.work handlers to terminate
 	 */
+	 
 	flush_scheduled_work();
-
+	
+	/*
+	 * Wait for any short term users (we know they are just driver
+	 * side waiters as the file is closing so user count on the file
+	 * side is zero.
+	 */
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	while(tty->ldisc.refcount)
+	{
+		spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+		wait_event(tty_ldisc_wait, tty->ldisc.refcount == 0);
+		spin_lock_irqsave(&tty_ldisc_lock, flags);
+	}
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
 	/*
 	 * Shutdown the current line discipline, and reset it to N_TTY.
 	 * N.B. why reset ldisc when we're releasing the memory??
+	 *
+	 * FIXME: this MUST get fixed for the new reflocking
 	 */
 	if (tty->ldisc.close)
 		(tty->ldisc.close)(tty);
-	module_put(tty->ldisc.owner);
+	tty_ldisc_put(tty->ldisc.num);
 	
-	tty->ldisc = ldiscs[N_TTY];
-	tty->termios->c_line = N_TTY;
+	/*
+	 *	Switch the line discipline back
+	 */
+	tty_ldisc_assign(tty, tty_ldisc_get(N_TTY));
+	tty_set_termios_ldisc(tty,N_TTY); 
 	if (o_tty) {
+		/* FIXME: could o_tty be in setldisc here ? */
+		clear_bit(TTY_LDISC, &o_tty->flags);
 		if (o_tty->ldisc.close)
 			(o_tty->ldisc.close)(o_tty);
-		module_put(o_tty->ldisc.owner);
-		o_tty->ldisc = ldiscs[N_TTY];
+		tty_ldisc_put(o_tty->ldisc.num);
+		tty_ldisc_assign(o_tty, tty_ldisc_get(N_TTY));
+		tty_set_termios_ldisc(o_tty,N_TTY); 
 	}
-
 	/*
 	 * The release_mem function takes care of the details of clearing
 	 * the slots and preserving the termios structure.
@@ -1323,6 +1724,7 @@ static int tty_open(struct inode * inode, struct file * filp)
 	unsigned short saved_flags = filp->f_flags;
 
 	nonseekable_open(inode, filp);
+	
 retry_open:
 	noctty = filp->f_flags & O_NOCTTY;
 	index  = -1;
@@ -1358,53 +1760,13 @@ retry_open:
 		return -ENODEV;
 	}
 
-#ifdef CONFIG_UNIX98_PTYS
-	if (device == MKDEV(TTYAUX_MAJOR,2)) {
-		int idr_ret;
-
-		/* find a device that is not in use. */
-		down(&allocated_ptys_lock);
-		if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) {
-			up(&allocated_ptys_lock);
-			return -ENOMEM;
-		}
-		idr_ret = idr_get_new(&allocated_ptys, NULL, &index);
-		if (idr_ret < 0) {
-			up(&allocated_ptys_lock);
-			if (idr_ret == -EAGAIN)
-				return -ENOMEM;
-			return -EIO;
-		}
-		if (index >= pty_limit) {
-			idr_remove(&allocated_ptys, index);
-			up(&allocated_ptys_lock);
-			return -EIO;
-		}
-		up(&allocated_ptys_lock);
-
-		driver = ptm_driver;
-		retval = init_dev(driver, index, &tty);
-		if (retval) {
-			down(&allocated_ptys_lock);
-			idr_remove(&allocated_ptys, index);
-			up(&allocated_ptys_lock);
-			return retval;
-		}
-
-		set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
-		if (devpts_pty_new(tty->link))
-			retval = -ENOMEM;
-	} else
-#endif
-	{
-		driver = get_tty_driver(device, &index);
-		if (!driver)
-			return -ENODEV;
+	driver = get_tty_driver(device, &index);
+	if (!driver)
+		return -ENODEV;
 got_driver:
-		retval = init_dev(driver, index, &tty);
-		if (retval)
-			return retval;
-	}
+	retval = init_dev(driver, index, &tty);
+	if (retval)
+		return retval;
 
 	filp->private_data = tty;
 	file_move(filp, &tty->tty_files);
@@ -1431,15 +1793,6 @@ got_driver:
 		printk(KERN_DEBUG "error %d in opening %s...", retval,
 		       tty->name);
 #endif
-
-#ifdef CONFIG_UNIX98_PTYS
-		if (index != -1) {
-			down(&allocated_ptys_lock);
-			idr_remove(&allocated_ptys, index);
-			up(&allocated_ptys_lock);
-		}
-#endif
-
 		release_dev(filp);
 		if (retval != -ERESTARTSYS)
 			return retval;
@@ -1467,6 +1820,62 @@ got_driver:
 	return 0;
 }
 
+#ifdef CONFIG_UNIX98_PTYS
+static int ptmx_open(struct inode * inode, struct file * filp)
+{
+	struct tty_struct *tty;
+	int retval;
+	int index;
+	int idr_ret;
+
+	nonseekable_open(inode, filp);
+
+	/* find a device that is not in use. */
+	down(&allocated_ptys_lock);
+	if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) {
+		up(&allocated_ptys_lock);
+		return -ENOMEM;
+	}
+	idr_ret = idr_get_new(&allocated_ptys, NULL, &index);
+	if (idr_ret < 0) {
+		up(&allocated_ptys_lock);
+		if (idr_ret == -EAGAIN)
+			return -ENOMEM;
+		return -EIO;
+	}
+	if (index >= pty_limit) {
+		idr_remove(&allocated_ptys, index);
+		up(&allocated_ptys_lock);
+		return -EIO;
+	}
+	up(&allocated_ptys_lock);
+
+	retval = init_dev(ptm_driver, index, &tty);
+	if (retval)
+		goto out;
+
+	set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
+	filp->private_data = tty;
+	file_move(filp, &tty->tty_files);
+
+	retval = -ENOMEM;
+	if (devpts_pty_new(tty->link))
+		goto out1;
+
+	check_tty_count(tty, "tty_open");
+	retval = ptm_driver->open(tty, filp);
+	if (!retval)
+		return 0;
+out1:
+	release_dev(filp);
+out:
+	down(&allocated_ptys_lock);
+	idr_remove(&allocated_ptys, index);
+	up(&allocated_ptys_lock);
+	return retval;
+}
+#endif
+
 static int tty_release(struct inode * inode, struct file * filp)
 {
 	lock_kernel();
@@ -1479,14 +1888,18 @@ static int tty_release(struct inode * inode, struct file * filp)
 static unsigned int tty_poll(struct file * filp, poll_table * wait)
 {
 	struct tty_struct * tty;
+	struct tty_ldisc *ld;
+	int ret = 0;
 
 	tty = (struct tty_struct *)filp->private_data;
 	if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_poll"))
 		return 0;
-
-	if (tty->ldisc.poll)
-		return (tty->ldisc.poll)(tty, filp, wait);
-	return 0;
+		
+	ld = tty_ldisc_ref_wait(tty);
+	if (ld->poll)
+		ret = (ld->poll)(tty, filp, wait);
+	tty_ldisc_deref(ld);
+	return ret;
 }
 
 static int tty_fasync(int fd, struct file * filp, int on)
@@ -1518,12 +1931,15 @@ static int tty_fasync(int fd, struct file * filp, int on)
 static int tiocsti(struct tty_struct *tty, char __user *p)
 {
 	char ch, mbz = 0;
-
+	struct tty_ldisc *ld;
+	
 	if ((current->signal->tty != tty) && !capable(CAP_SYS_ADMIN))
 		return -EPERM;
 	if (get_user(ch, p))
 		return -EFAULT;
-	tty->ldisc.receive_buf(tty, &ch, &mbz, 1);
+	ld = tty_ldisc_ref_wait(tty);
+	ld->receive_buf(tty, &ch, &mbz, 1);
+	tty_ldisc_deref(ld);
 	return 0;
 }
 
@@ -1606,8 +2022,6 @@ static int fionbio(struct file *file, int __user *p)
 
 static int tiocsctty(struct tty_struct *tty, int arg)
 {
-	struct list_head *l;
-	struct pid *pid;
 	task_t *p;
 
 	if (current->signal->leader &&
@@ -1630,8 +2044,9 @@ static int tiocsctty(struct tty_struct *tty, int arg)
 			 */
 
 			read_lock(&tasklist_lock);
-			for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid)
+			do_each_task_pid(tty->session, PIDTYPE_SID, p) {
 				p->signal->tty = NULL;
+			} while_each_task_pid(tty->session, PIDTYPE_SID, p);
 			read_unlock(&tasklist_lock);
 		} else
 			return -EPERM;
@@ -1647,13 +2062,16 @@ static int tiocsctty(struct tty_struct *tty, int arg)
 
 static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
 {
+	pid_t pgrp;
 	/*
 	 * (tty == real_tty) is a cheap way of
 	 * testing if the tty is NOT a master pty.
 	 */
 	if (tty == real_tty && current->signal->tty != real_tty)
 		return -ENOTTY;
-	return put_user(real_tty->pgrp, p);
+
+	pgrp = vx_map_pid(real_tty->pgrp);
+	return put_user(pgrp, p);
 }
 
 static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
@@ -1671,6 +2089,8 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
 		return -ENOTTY;
 	if (get_user(pgrp, p))
 		return -EFAULT;
+
+	pgrp = vx_rmap_pid(pgrp);
 	if (pgrp < 0)
 		return -EINVAL;
 	if (session_of_pgrp(pgrp) != current->signal->session)
@@ -1772,6 +2192,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
 	struct tty_struct *tty, *real_tty;
 	void __user *p = (void __user *)arg;
 	int retval;
+	struct tty_ldisc *ld;
 	
 	tty = (struct tty_struct *)file->private_data;
 	if (tty_paranoia_check(tty, inode, "tty_ioctl"))
@@ -1861,6 +2282,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
 		case TIOCGSID:
 			return tiocgsid(tty, real_tty, p);
 		case TIOCGETD:
+			/* FIXME: check this is ok */
 			return put_user(tty->ldisc.num, (int __user *)p);
 		case TIOCSETD:
 			return tiocsetd(tty, p);
@@ -1899,16 +2321,19 @@ int tty_ioctl(struct inode * inode, struct file * file,
 			return tty_tiocmset(tty, file, cmd, p);
 	}
 	if (tty->driver->ioctl) {
-		int retval = (tty->driver->ioctl)(tty, file, cmd, arg);
+		retval = (tty->driver->ioctl)(tty, file, cmd, arg);
 		if (retval != -ENOIOCTLCMD)
 			return retval;
 	}
-	if (tty->ldisc.ioctl) {
-		int retval = (tty->ldisc.ioctl)(tty, file, cmd, arg);
-		if (retval != -ENOIOCTLCMD)
-			return retval;
+	ld = tty_ldisc_ref_wait(tty);
+	retval = -EINVAL;
+	if (ld->ioctl) {
+		retval = ld->ioctl(tty, file, cmd, arg);
+		if (retval == -ENOIOCTLCMD)
+			retval = -EINVAL;
 	}
-	return -EINVAL;
+	tty_ldisc_deref(ld);
+	return retval;
 }
 
 
@@ -1938,21 +2363,26 @@ static void __do_SAK(void *arg)
 #else
 	struct tty_struct *tty = arg;
 	struct task_struct *p;
-	struct list_head *l;
-	struct pid *pid;
 	int session;
 	int		i;
 	struct file	*filp;
+	struct tty_ldisc *disc;
 	
 	if (!tty)
 		return;
 	session  = tty->session;
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	
+	/* We don't want an ldisc switch during this */
+	disc = tty_ldisc_ref(tty);
+	if (disc && disc->flush_buffer)
+		disc->flush_buffer(tty);
+	tty_ldisc_deref(disc);
+
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
+	
 	read_lock(&tasklist_lock);
-	for_each_task_pid(session, PIDTYPE_SID, p, l, pid) {
+	do_each_task_pid(session, PIDTYPE_SID, p) {
 		if (p->signal->tty == tty || session > 0) {
 			printk(KERN_NOTICE "SAK: killed process %d"
 			    " (%s): p->signal->session==tty->session\n",
@@ -1979,7 +2409,7 @@ static void __do_SAK(void *arg)
 			spin_unlock(&p->files->file_lock);
 		}
 		task_unlock(p);
-	}
+	} while_each_task_pid(session, PIDTYPE_SID, p);
 	read_unlock(&tasklist_lock);
 #endif
 }
@@ -2002,24 +2432,29 @@ EXPORT_SYMBOL(do_SAK);
 
 /*
  * This routine is called out of the software interrupt to flush data
- * from the flip buffer to the line discipline.
+ * from the flip buffer to the line discipline. 
  */
+ 
 static void flush_to_ldisc(void *private_)
 {
 	struct tty_struct *tty = (struct tty_struct *) private_;
 	unsigned char	*cp;
 	char		*fp;
 	int		count;
-	unsigned long flags;
+	unsigned long 	flags;
+	struct tty_ldisc *disc;
+
+	disc = tty_ldisc_ref(tty);
+	if (disc == NULL)	/*  !TTY_LDISC */
+		return;
 
 	if (test_bit(TTY_DONT_FLIP, &tty->flags)) {
 		/*
 		 * Do it after the next timer tick:
 		 */
 		schedule_delayed_work(&tty->flip.work, 1);
-		return;
+		goto out;
 	}
-
 	spin_lock_irqsave(&tty->read_lock, flags);
 	if (tty->flip.buf_num) {
 		cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
@@ -2038,7 +2473,31 @@ static void flush_to_ldisc(void *private_)
 	tty->flip.count = 0;
 	spin_unlock_irqrestore(&tty->read_lock, flags);
 
-	tty->ldisc.receive_buf(tty, cp, fp, count);
+	disc->receive_buf(tty, cp, fp, count);
+out:
+	tty_ldisc_deref(disc);
+}
+
+/*
+ *	Call the ldisc flush directly from a driver. This function may
+ *	return an error and need retrying by the user.
+ */
+
+int tty_push_data(struct tty_struct *tty, unsigned char *cp, unsigned char *fp, int count)
+{
+	int ret = 0;
+	struct tty_ldisc *disc;
+	
+	disc = tty_ldisc_ref(tty);
+	if(test_bit(TTY_DONT_FLIP, &tty->flags))
+		ret = -EAGAIN;
+	else if(disc == NULL)
+		ret = -EIO;
+	else
+		disc->receive_buf(tty, cp, fp, count);
+	tty_ldisc_deref(disc);
+	return ret;
+	
 }
 
 /*
@@ -2060,9 +2519,20 @@ static int baud_table[] = {
 
 static int n_baud_table = ARRAY_SIZE(baud_table);
 
+/**
+ *	tty_termios_baud_rate
+ *	@termios: termios structure
+ *
+ *	Convert termios baud rate data into a speed. This should be called
+ *	with the termios lock held if this termios is a terminal termios
+ *	structure. May change the termios data.
+ */
+ 
 int tty_termios_baud_rate(struct termios *termios)
 {
-	unsigned int cbaud = termios->c_cflag & CBAUD;
+	unsigned int cbaud;
+	
+	cbaud = termios->c_cflag & CBAUD;
 
 	if (cbaud & CBAUDEX) {
 		cbaud &= ~CBAUDEX;
@@ -2072,12 +2542,20 @@ int tty_termios_baud_rate(struct termios *termios)
 		else
 			cbaud += 15;
 	}
-
 	return baud_table[cbaud];
 }
 
 EXPORT_SYMBOL(tty_termios_baud_rate);
 
+/**
+ *	tty_get_baud_rate	-	get tty bit rates
+ *	@tty: tty to query
+ *
+ *	Returns the baud rate as an integer for this terminal. The
+ *	termios lock must be held by the caller and the terminal bit
+ *	flags may be updated.
+ */
+ 
 int tty_get_baud_rate(struct tty_struct *tty)
 {
 	int baud = tty_termios_baud_rate(tty->termios);
@@ -2096,6 +2574,17 @@ int tty_get_baud_rate(struct tty_struct *tty)
 
 EXPORT_SYMBOL(tty_get_baud_rate);
 
+/**
+ *	tty_flip_buffer_push	-	terminal
+ *	@tty: tty to push
+ *
+ *	Queue a push of the terminal flip buffers to the line discipline. This
+ *	function must not be called from IRQ context if tty->low_latency is set.
+ *
+ *	In the event of the queue being busy for flipping the work will be
+ *	held off and retried later.
+ */
+
 void tty_flip_buffer_push(struct tty_struct *tty)
 {
 	if (tty->low_latency)
@@ -2113,12 +2602,13 @@ static void initialize_tty_struct(struct tty_struct *tty)
 {
 	memset(tty, 0, sizeof(struct tty_struct));
 	tty->magic = TTY_MAGIC;
-	tty->ldisc = ldiscs[N_TTY];
+	tty_ldisc_assign(tty, tty_ldisc_get(N_TTY));
 	tty->pgrp = -1;
 	tty->flip.char_buf_ptr = tty->flip.char_buf;
 	tty->flip.flag_buf_ptr = tty->flip.flag_buf;
 	INIT_WORK(&tty->flip.work, flush_to_ldisc, tty);
 	init_MUTEX(&tty->flip.pty_sem);
+	init_MUTEX(&tty->termios_sem);
 	init_waitqueue_head(&tty->write_wait);
 	init_waitqueue_head(&tty->read_wait);
 	INIT_WORK(&tty->hangup_work, do_tty_hangup, tty);
@@ -2154,6 +2644,7 @@ static struct class_simple *tty_class;
 void tty_register_device(struct tty_driver *driver, unsigned index,
 			 struct device *device)
 {
+	char name[64];
 	dev_t dev = MKDEV(driver->major, driver->minor_start) + index;
 
 	if (index >= driver->num) {
@@ -2165,13 +2656,11 @@ void tty_register_device(struct tty_driver *driver, unsigned index,
 	devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR,
 			"%s%d", driver->devfs_name, index + driver->name_base);
 
-	/* we don't care about the ptys */
-	/* how nice to hide this behind some crappy interface.. */
-	if (driver->type != TTY_DRIVER_TYPE_PTY) {
-		char name[64];
+	if (driver->type == TTY_DRIVER_TYPE_PTY)
+		pty_line_name(driver, index, name);
+	else
 		tty_line_name(driver, index, name);
-		class_simple_device_add(tty_class, dev, device, name);
-	}
+	class_simple_device_add(tty_class, dev, device, name);
 }
 
 /**
@@ -2441,7 +2930,7 @@ static int __init tty_init(void)
 	class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
 
 #ifdef CONFIG_UNIX98_PTYS
-	cdev_init(&ptmx_cdev, &tty_fops);
+	cdev_init(&ptmx_cdev, &ptmx_fops);
 	if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
 	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
 		panic("Couldn't register /dev/ptmx driver\n");
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index ae924c7cb..830c665a3 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -98,8 +98,17 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios
 {
 	int canon_change;
 	struct termios old_termios = *tty->termios;
+	struct tty_ldisc *ld;
+	
+	/*
+	 *	Perform the actual termios internal changes under lock.
+	 */
+	 
+
+	/* FIXME: we need to decide on some locking/ordering semantics
+	   for the set_termios notification eventually */
+	down(&tty->termios_sem);
 
-	local_irq_disable(); // FIXME: is this safe?
 	*tty->termios = *new_termios;
 	unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
 	canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
@@ -109,12 +118,13 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios
 		tty->canon_data = 0;
 		tty->erasing = 0;
 	}
-	local_irq_enable(); // FIXME: is this safe?
+	
+	
 	if (canon_change && !L_ICANON(tty) && tty->read_cnt)
 		/* Get characters left over from canonical mode. */
 		wake_up_interruptible(&tty->read_wait);
 
-	/* see if packet mode change of state */
+	/* See if packet mode change of state. */
 
 	if (tty->link && tty->link->packet) {
 		int old_flow = ((old_termios.c_iflag & IXON) &&
@@ -132,17 +142,23 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios
 			wake_up_interruptible(&tty->link->read_wait);
 		}
 	}
-
+	   
 	if (tty->driver->set_termios)
 		(*tty->driver->set_termios)(tty, &old_termios);
 
-	if (tty->ldisc.set_termios)
-		(*tty->ldisc.set_termios)(tty, &old_termios);
+	ld = tty_ldisc_ref(tty);
+	if (ld != NULL) {
+		if (ld->set_termios)
+			(ld->set_termios)(tty, &old_termios);
+		tty_ldisc_deref(ld);
+	}
+	up(&tty->termios_sem);
 }
 
 static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
 {
 	struct termios tmp_termios;
+	struct tty_ldisc *ld;
 	int retval = tty_check_change(tty);
 
 	if (retval)
@@ -159,9 +175,14 @@ static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
 			return -EFAULT;
 	}
 
-	if ((opt & TERMIOS_FLUSH) && tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
-
+	ld = tty_ldisc_ref(tty);
+	
+	if (ld != NULL) {
+		if ((opt & TERMIOS_FLUSH) && ld->flush_buffer)
+			ld->flush_buffer(tty);
+		tty_ldisc_deref(ld);
+	}
+	
 	if (opt & TERMIOS_WAIT) {
 		tty_wait_until_sent(tty, 0);
 		if (signal_pending(current))
@@ -226,11 +247,14 @@ static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
 {
 	struct sgttyb tmp;
 
+	down(&tty->termios_sem);
 	tmp.sg_ispeed = 0;
 	tmp.sg_ospeed = 0;
 	tmp.sg_erase = tty->termios->c_cc[VERASE];
 	tmp.sg_kill = tty->termios->c_cc[VKILL];
 	tmp.sg_flags = get_sgflags(tty);
+	up(&tty->termios_sem);
+	
 	return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 }
 
@@ -269,12 +293,16 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
 	retval = tty_check_change(tty);
 	if (retval)
 		return retval;
-	termios =  *tty->termios;
+	
 	if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
 		return -EFAULT;
+
+	down(&tty->termios_sem);		
+	termios =  *tty->termios;
 	termios.c_cc[VERASE] = tmp.sg_erase;
 	termios.c_cc[VKILL] = tmp.sg_kill;
 	set_sgflags(&termios, tmp.sg_flags);
+	up(&tty->termios_sem);
 	change_termios(tty, &termios);
 	return 0;
 }
@@ -365,6 +393,7 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
 	struct tty_struct * real_tty;
 	void __user *p = (void __user *)arg;
 	int retval;
+	struct tty_ldisc *ld;
 
 	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
 	    tty->driver->subtype == PTY_TYPE_MASTER)
@@ -443,22 +472,26 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
 			retval = tty_check_change(tty);
 			if (retval)
 				return retval;
+				
+			ld = tty_ldisc_ref(tty);
 			switch (arg) {
 			case TCIFLUSH:
-				if (tty->ldisc.flush_buffer)
-					tty->ldisc.flush_buffer(tty);
+				if (ld->flush_buffer)
+					ld->flush_buffer(tty);
 				break;
 			case TCIOFLUSH:
-				if (tty->ldisc.flush_buffer)
-					tty->ldisc.flush_buffer(tty);
+				if (ld->flush_buffer)
+					ld->flush_buffer(tty);
 				/* fall through */
 			case TCOFLUSH:
 				if (tty->driver->flush_buffer)
 					tty->driver->flush_buffer(tty);
 				break;
 			default:
+				tty_ldisc_deref(ld);
 				return -EINVAL;
 			}
+			tty_ldisc_deref(ld);
 			return 0;
 		case TIOCOUTQ:
 			return put_user(tty->driver->chars_in_buffer ?
@@ -504,9 +537,11 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
 		case TIOCSSOFTCAR:
 			if (get_user(arg, (unsigned int __user *) arg))
 				return -EFAULT;
+			down(&tty->termios_sem);
 			tty->termios->c_cflag =
 				((tty->termios->c_cflag & ~CLOCAL) |
 				 (arg ? CLOCAL : 0));
+			up(&tty->termios_sem);
 			return 0;
 		default:
 			return -ENOIOCTLCMD;
diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c
index df9d4de9b..dcfcef4be 100644
--- a/drivers/char/viocons.c
+++ b/drivers/char/viocons.c
@@ -422,10 +422,7 @@ static void send_buffers(struct port_info *pi)
 			pi->overflowMessage = 0;
 
 		if (pi->tty) {
-			if ((pi->tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-			    (pi->tty->ldisc.write_wakeup))
-				(pi->tty->ldisc.write_wakeup)(pi->tty);
-			wake_up_interruptible(&pi->tty->write_wait);
+			tty_wakeup(pi->tty);
 		}
 	}
 
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
index 6f7833417..19ba83635 100644
--- a/drivers/char/vme_scc.c
+++ b/drivers/char/vme_scc.c
@@ -544,12 +544,8 @@ static irqreturn_t scc_tx_int(int irq, void *data, struct pt_regs *fp)
 		SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);   /* disable tx_int on next tx underrun? */
 		port->gs.flags &= ~GS_TX_INTEN;
 	}
-	if (port->gs.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) {
-		if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-				port->gs.tty->ldisc.write_wakeup)
-			(port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
-		wake_up_interruptible(&port->gs.tty->write_wait);
-	}
+	if (port->gs.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars)
+		tty_wakeup(port->gs.tty);
 
 	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
 	return IRQ_HANDLED;
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index a204572f5..31da37da5 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -136,9 +136,6 @@ extern void prom_con_init(void);
 #ifdef CONFIG_MDA_CONSOLE
 extern int mda_console_init(void);
 #endif
-#ifdef CONFIG_FRAMEBUFFER_CONSOLE
-extern int fb_console_init(void);
-#endif
 
 struct vc vc_cons [MAX_NR_CONSOLES];
 
@@ -600,6 +597,17 @@ static inline void save_screen(int currcons)
  *	Redrawing of screen
  */
 
+static void clear_buffer_attributes(int currcons)
+{
+	unsigned short *p = (unsigned short *) origin;
+	int count = screenbuf_size/2;
+	int mask = hi_font_mask | 0xff;
+
+	for (; count > 0; count--, p++) {
+		scr_writew((scr_readw(p)&mask) | (video_erase_char&~mask), p);
+	}
+}
+
 void redraw_screen(int new_console, int is_switch)
 {
 	int redraw = 1;
@@ -637,9 +645,21 @@ void redraw_screen(int new_console, int is_switch)
 
 	if (redraw) {
 		int update;
+		int old_was_color = vc_cons[currcons].d->vc_can_do_color;
+
 		set_origin(currcons);
 		update = sw->con_switch(vc_cons[currcons].d);
 		set_palette(currcons);
+		/*
+		 * If console changed from mono<->color, the best we can do
+		 * is to clear the buffer attributes. As it currently stands,
+		 * rebuilding new attributes from the old buffer is not doable
+		 * without overly complex code.
+		 */
+		if (old_was_color != vc_cons[currcons].d->vc_can_do_color) {
+			update_attr(currcons);
+			clear_buffer_attributes(currcons);
+		}
 		if (update && vcmode != KD_GRAPHICS)
 			do_update_region(currcons, origin, screenbuf_size/2);
 	}
@@ -1865,7 +1885,7 @@ static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c)
  * since console_init (and thus con_init) are called before any
  * kernel memory allocation is available.
  */
-char con_buf[PAGE_SIZE];
+char con_buf[CON_BUF_SIZE];
 DECLARE_MUTEX(con_buf_sem);
 
 /* acquires console_sem */
@@ -1958,12 +1978,16 @@ again:
 		hide_cursor(currcons);
 
 	while (!tty->stopped && count) {
-		c = *buf;
+		int orig = *buf;
+		c = orig;
 		buf++;
 		n++;
 		count--;
 
-		if (utf) {
+		/* Do no translation at all in control states */
+		if (vc_state != ESnormal) {
+			tc = c;
+		} else if (utf) {
 		    /* Combine UTF-8 into Unicode */
 		    /* Incomplete characters silently ignored */
 		    if(c > 0x7f) {
@@ -2063,7 +2087,7 @@ again:
 			continue;
 		}
 		FLUSH
-		do_con_trol(tty, currcons, c);
+		do_con_trol(tty, currcons, orig);
 	}
 	FLUSH
 	console_conditional_schedule();
@@ -2645,25 +2669,11 @@ int __init vty_init(void)
 #ifdef CONFIG_MDA_CONSOLE
 	mda_console_init();
 #endif
-#ifdef CONFIG_FRAMEBUFFER_CONSOLE
-	fb_console_init();
-#endif	
 	return 0;
 }
 
 #ifndef VT_SINGLE_DRIVER
 
-static void clear_buffer_attributes(int currcons)
-{
-	unsigned short *p = (unsigned short *) origin;
-	int count = screenbuf_size/2;
-	int mask = hi_font_mask | 0xff;
-
-	for (; count > 0; count--, p++) {
-		scr_writew((scr_readw(p)&mask) | (video_erase_char&~mask), p);
-	}
-}
-
 /*
  *	If we support more console drivers, this function is used
  *	when a driver wants to take over some existing consoles
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index 682b44e9d..dd8e2f781 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -536,8 +536,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
 		  default:
 			return -EINVAL;
 		}
-		if (tty->ldisc.flush_buffer)
-			tty->ldisc.flush_buffer(tty);
+		tty_ldisc_flush(tty);
 		return 0;
 
 	case KDGKBMODE:
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index a9dec9e98..4f109b7d7 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -319,6 +319,12 @@ config MACHZ_WDT
 	  To compile this driver as a module, choose M here: the
 	  module will be called machzwd.
 
+# PowerPC Architecture
+
+config 8xx_WDT
+	tristate "MPC8xx Watchdog Timer"
+	depends on WATCHDOG && 8xx
+
 # MIPS Architecture
 
 config INDYDOG
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index c5f99d332..c43e9990c 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -37,3 +37,4 @@ obj-$(CONFIG_PCIPCWATCHDOG) += pcwd_pci.o
 obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
 obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
 obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
+obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
diff --git a/drivers/char/watchdog/cpu5wdt.c b/drivers/char/watchdog/cpu5wdt.c
index 7e7b653a2..2865dac0a 100644
--- a/drivers/char/watchdog/cpu5wdt.c
+++ b/drivers/char/watchdog/cpu5wdt.c
@@ -134,7 +134,7 @@ static int cpu5wdt_open(struct inode *inode, struct file *file)
 	if ( test_and_set_bit(0, &cpu5wdt_device.inuse) )
 		return -EBUSY;
 
-	return 0;
+	return nonseekable_open(inode, file);
 }
 
 static int cpu5wdt_release(struct inode *inode, struct file *file)
@@ -198,6 +198,7 @@ static ssize_t cpu5wdt_write(struct file *file, const char __user *buf, size_t c
 
 static struct file_operations cpu5wdt_fops = {
 	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
 	.ioctl		= cpu5wdt_ioctl,
 	.open		= cpu5wdt_open,
 	.write		= cpu5wdt_write,
diff --git a/drivers/char/watchdog/ib700wdt.c b/drivers/char/watchdog/ib700wdt.c
index cd6467eb4..d974f16e8 100644
--- a/drivers/char/watchdog/ib700wdt.c
+++ b/drivers/char/watchdog/ib700wdt.c
@@ -263,6 +263,7 @@ ibwdt_notify_sys(struct notifier_block *this, unsigned long code,
 
 static struct file_operations ibwdt_fops = {
 	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
 	.write		= ibwdt_write,
 	.ioctl		= ibwdt_ioctl,
 	.open		= ibwdt_open,
diff --git a/drivers/char/watchdog/indydog.c b/drivers/char/watchdog/indydog.c
index 4e9093b4a..6af2c799b 100644
--- a/drivers/char/watchdog/indydog.c
+++ b/drivers/char/watchdog/indydog.c
@@ -162,6 +162,7 @@ static int indydog_notify_sys(struct notifier_block *this, unsigned long code, v
 
 static struct file_operations indydog_fops = {
 	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
 	.write		= indydog_write,
 	.ioctl		= indydog_ioctl,
 	.open		= indydog_open,
diff --git a/drivers/char/watchdog/ixp4xx_wdt.c b/drivers/char/watchdog/ixp4xx_wdt.c
index b8e3d91d3..a6781dede 100644
--- a/drivers/char/watchdog/ixp4xx_wdt.c
+++ b/drivers/char/watchdog/ixp4xx_wdt.c
@@ -170,6 +170,7 @@ ixp4xx_wdt_release(struct inode *inode, struct file *file)
 static struct file_operations ixp4xx_wdt_fops =
 {
 	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
 	.write		= ixp4xx_wdt_write,
 	.ioctl		= ixp4xx_wdt_ioctl,
 	.open		= ixp4xx_wdt_open,
diff --git a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c
index 3782930e6..6e14abbb4 100644
--- a/drivers/char/watchdog/machzwd.c
+++ b/drivers/char/watchdog/machzwd.c
@@ -425,6 +425,7 @@ static int zf_notify_sys(struct notifier_block *this, unsigned long code,
 
 static struct file_operations zf_fops = {
 	.owner          = THIS_MODULE,
+	.llseek         = no_llseek,
 	.write          = zf_write,
 	.ioctl          = zf_ioctl,
 	.open           = zf_open,
diff --git a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c
index 15a3547f2..3143e4a07 100644
--- a/drivers/char/watchdog/mixcomwd.c
+++ b/drivers/char/watchdog/mixcomwd.c
@@ -197,6 +197,7 @@ static int mixcomwd_ioctl(struct inode *inode, struct file *file,
 static struct file_operations mixcomwd_fops=
 {
 	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
 	.write		= mixcomwd_write,
 	.ioctl		= mixcomwd_ioctl,
 	.open		= mixcomwd_open,
diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c
index 88bdbda92..592dca108 100644
--- a/drivers/char/watchdog/pcwd.c
+++ b/drivers/char/watchdog/pcwd.c
@@ -859,8 +859,7 @@ static int __init pcwd_checkcard(int base_addr)
 		/* Not an 'ff' from a floating bus, so must be a card! */
 		for (i = 0; i < 4; ++i) {
 
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(HZ / 2);
+			msleep(500);
 
 			last_port0 = port0;
 			last_port1 = port1;
diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c
index 1adf09f83..394ee7ac7 100644
--- a/drivers/char/watchdog/sa1100_wdt.c
+++ b/drivers/char/watchdog/sa1100_wdt.c
@@ -27,6 +27,10 @@
 #include <linux/watchdog.h>
 #include <linux/init.h>
 
+#ifdef CONFIG_ARCH_PXA
+#include <asm/arch/pxa-regs.h>
+#endif
+
 #include <asm/hardware.h>
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
@@ -162,6 +166,7 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file,
 static struct file_operations sa1100dog_fops =
 {
 	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
 	.write		= sa1100dog_write,
 	.ioctl		= sa1100dog_ioctl,
 	.open		= sa1100dog_open,
diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c
index 9ddebaebe..d17d485fb 100644
--- a/drivers/char/watchdog/sc1200wdt.c
+++ b/drivers/char/watchdog/sc1200wdt.c
@@ -301,6 +301,7 @@ static struct notifier_block sc1200wdt_notifier =
 static struct file_operations sc1200wdt_fops =
 {
 	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
 	.write		= sc1200wdt_write,
 	.ioctl		= sc1200wdt_ioctl,
 	.open		= sc1200wdt_open,
diff --git a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c
index ed1800cff..983e9e980 100644
--- a/drivers/char/watchdog/scx200_wdt.c
+++ b/drivers/char/watchdog/scx200_wdt.c
@@ -201,6 +201,7 @@ static int scx200_wdt_ioctl(struct inode *inode, struct file *file,
 
 static struct file_operations scx200_wdt_fops = {
 	.owner	 = THIS_MODULE,
+	.llseek	 = no_llseek,
 	.write   = scx200_wdt_write,
 	.ioctl   = scx200_wdt_ioctl,
 	.open    = scx200_wdt_open,
diff --git a/drivers/char/watchdog/wdt285.c b/drivers/char/watchdog/wdt285.c
index d3fced33d..52825a1f1 100644
--- a/drivers/char/watchdog/wdt285.c
+++ b/drivers/char/watchdog/wdt285.c
@@ -180,6 +180,7 @@ watchdog_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
 static struct file_operations watchdog_fops = {
 	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
 	.write		= watchdog_write,
 	.ioctl		= watchdog_ioctl,
 	.open		= watchdog_open,
diff --git a/drivers/char/watchdog/wdt977.c b/drivers/char/watchdog/wdt977.c
index 388c548c2..072e9b214 100644
--- a/drivers/char/watchdog/wdt977.c
+++ b/drivers/char/watchdog/wdt977.c
@@ -392,6 +392,7 @@ static int wdt977_notify_sys(struct notifier_block *this, unsigned long code,
 static struct file_operations wdt977_fops=
 {
 	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
 	.write		= wdt977_write,
 	.ioctl		= wdt977_ioctl,
 	.open		= wdt977_open,
diff --git a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c
index 9d5b5f4e5..7651deda9 100644
--- a/drivers/char/watchdog/wdt_pci.c
+++ b/drivers/char/watchdog/wdt_pci.c
@@ -674,8 +674,8 @@ out:
 out_misc:
 #ifdef CONFIG_WDT_501_PCI
 	misc_deregister(&temp_miscdev);
-#endif /* CONFIG_WDT_501_PCI */
 out_rbt:
+#endif /* CONFIG_WDT_501_PCI */
 	unregister_reboot_notifier(&wdtpci_notifier);
 out_irq:
 	free_irq(irq, &wdtpci_miscdev);
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index 331b5156d..889f243fb 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -69,6 +69,21 @@ config CPU_FREQ_GOV_USERSPACE
 
 	  If in doubt, say Y.
 
+config CPU_FREQ_GOV_ONDEMAND
+	tristate "'ondemand' cpufreq policy governor"
+	depends on CPU_FREQ
+	help
+	  'ondemand' - This driver adds a dynamic cpufreq policy governor.
+	  The governor does a periodic polling and 
+	  changes frequency based on the CPU utilization.
+	  The support for this governor depends on CPU capability to
+	  do fast frequency switching (i.e, very low latency frequency
+	  transitions). 
+
+	  For details, take a look at linux/Documentation/cpu-freq.
+
+	  If in doubt, say N.
+
 config CPU_FREQ_24_API
 	bool "/proc/sys/cpu/ interface (2.4. / OLD)"
 	depends on CPU_FREQ && SYSCTL && CPU_FREQ_GOV_USERSPACE
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 1eebf3c6e..50291abb4 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_CPU_FREQ)			+= cpufreq.o
 obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE)	+= cpufreq_performance.o
 obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE)	+= cpufreq_powersave.o
 obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE)	+= cpufreq_userspace.o
+obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND)	+= cpufreq_ondemand.o
 
 # CPUfreq cross-arch helpers
 obj-$(CONFIG_CPU_FREQ_TABLE)		+= freq_table.o
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index a7fa79f5b..3e14a3a44 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -99,6 +99,85 @@ static void cpufreq_cpu_put(struct cpufreq_policy *data)
 	module_put(cpufreq_driver->owner);
 }
 
+/*********************************************************************
+ *            EXTERNALLY AFFECTING FREQUENCY CHANGES                 *
+ *********************************************************************/
+
+/**
+ * adjust_jiffies - adjust the system "loops_per_jiffy"
+ *
+ * This function alters the system "loops_per_jiffy" for the clock
+ * speed change. Note that loops_per_jiffy cannot be updated on SMP
+ * systems as each CPU might be scaled differently. So, use the arch 
+ * per-CPU loops_per_jiffy value wherever possible.
+ */
+#ifndef CONFIG_SMP
+static unsigned long l_p_j_ref;
+static unsigned int  l_p_j_ref_freq;
+
+static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
+{
+	if (ci->flags & CPUFREQ_CONST_LOOPS)
+		return;
+
+	if (!l_p_j_ref_freq) {
+		l_p_j_ref = loops_per_jiffy;
+		l_p_j_ref_freq = ci->old;
+	}
+	if ((val == CPUFREQ_PRECHANGE  && ci->old < ci->new) ||
+	    (val == CPUFREQ_POSTCHANGE && ci->old > ci->new) ||
+	    (val == CPUFREQ_RESUMECHANGE))
+		loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new);
+}
+#else
+static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { return; }
+#endif
+
+
+/**
+ * cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition
+ *
+ * This function calls the transition notifiers and the "adjust_jiffies" function. It is called
+ * twice on all CPU frequency changes that have external effects. 
+ */
+void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
+{
+	BUG_ON(irqs_disabled());
+
+	freqs->flags = cpufreq_driver->flags;
+
+	down_read(&cpufreq_notifier_rwsem);
+	switch (state) {
+	case CPUFREQ_PRECHANGE:
+		/* detect if the driver reported a value as "old frequency" which
+		 * is not equal to what the cpufreq core thinks is "old frequency".
+		 */
+		if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
+			if ((likely(cpufreq_cpu_data[freqs->cpu])) &&
+			    (likely(cpufreq_cpu_data[freqs->cpu]->cur)) &&
+			    (unlikely(freqs->old != cpufreq_cpu_data[freqs->cpu]->cur)))
+			{
+				printk(KERN_WARNING "Warning: CPU frequency is %u, "
+				       "cpufreq assumed %u kHz.\n", freqs->old, cpufreq_cpu_data[freqs->cpu]->cur);
+				freqs->old = cpufreq_cpu_data[freqs->cpu]->cur;
+			}
+		}
+		notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs);
+		adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
+		break;
+	case CPUFREQ_POSTCHANGE:
+		adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
+		notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs);
+		if (likely(cpufreq_cpu_data[freqs->cpu]))
+			cpufreq_cpu_data[freqs->cpu]->cur = freqs->new;
+		break;
+	}
+	up_read(&cpufreq_notifier_rwsem);
+}
+EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
+
+
+
 /*********************************************************************
  *                          SYSFS INTERFACE                          *
  *********************************************************************/
@@ -521,9 +600,6 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigne
 {
 	struct cpufreq_freqs freqs;
 
-	if (cpufreq_driver->flags & CPUFREQ_PANIC_OUTOFSYNC)
-		panic("CPU Frequency is out of sync.");
-
 	printk(KERN_WARNING "Warning: CPU frequency out of sync: cpufreq and timing "
 	       "core thinks of %u, is %u kHz.\n", old_freq, new_freq);
 
@@ -614,11 +690,8 @@ static int cpufreq_resume(struct sys_device * sysdev)
 		if (unlikely(cur_freq != cpu_policy->cur)) {
 			struct cpufreq_freqs freqs;
 
-			if (cpufreq_driver->flags & CPUFREQ_PANIC_RESUME_OUTOFSYNC)
-				panic("CPU Frequency is out of sync.");
-
-			printk(KERN_WARNING "Warning: CPU frequency out of sync: cpufreq and timing"
-			       "core thinks of %u, is %u kHz.\n", cpu_policy->cur, cur_freq);
+			printk(KERN_WARNING "Warning: CPU frequency is %u, "
+			       "cpufreq assumed %u kHz.\n", cur_freq, cpu_policy->cur);
 
 			freqs.cpu = cpu;
 			freqs.old = cpu_policy->cur;
@@ -626,6 +699,8 @@ static int cpufreq_resume(struct sys_device * sysdev)
 
 			notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_RESUMECHANGE, &freqs);
 			adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs);
+
+			cpu_policy->cur = cur_freq;
 		}
 	}
 
@@ -1005,87 +1080,6 @@ int cpufreq_update_policy(unsigned int cpu)
 EXPORT_SYMBOL(cpufreq_update_policy);
 
 
-/*********************************************************************
- *            EXTERNALLY AFFECTING FREQUENCY CHANGES                 *
- *********************************************************************/
-
-/**
- * adjust_jiffies - adjust the system "loops_per_jiffy"
- *
- * This function alters the system "loops_per_jiffy" for the clock
- * speed change. Note that loops_per_jiffy cannot be updated on SMP
- * systems as each CPU might be scaled differently. So, use the arch 
- * per-CPU loops_per_jiffy value wherever possible.
- */
-#ifndef CONFIG_SMP
-static unsigned long l_p_j_ref;
-static unsigned int  l_p_j_ref_freq;
-
-static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
-{
-	if (ci->flags & CPUFREQ_CONST_LOOPS)
-		return;
-
-	if (!l_p_j_ref_freq) {
-		l_p_j_ref = loops_per_jiffy;
-		l_p_j_ref_freq = ci->old;
-	}
-	if ((val == CPUFREQ_PRECHANGE  && ci->old < ci->new) ||
-	    (val == CPUFREQ_POSTCHANGE && ci->old > ci->new) ||
-	    (val == CPUFREQ_RESUMECHANGE))
-		loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new);
-}
-#else
-static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) { return; }
-#endif
-
-
-/**
- * cpufreq_notify_transition - call notifier chain and adjust_jiffies on frequency transition
- *
- * This function calls the transition notifiers and the "adjust_jiffies" function. It is called
- * twice on all CPU frequency changes that have external effects. 
- */
-void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
-{
-	BUG_ON(irqs_disabled());
-
-	freqs->flags = cpufreq_driver->flags;
-
-	down_read(&cpufreq_notifier_rwsem);
-	switch (state) {
-	case CPUFREQ_PRECHANGE:
-		/* detect if the driver reported a value as "old frequency" which
-		 * is not equal to what the cpufreq core thinks is "old frequency".
-		 */
-		if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
-			if ((likely(cpufreq_cpu_data[freqs->cpu]->cur)) &&
-			    (unlikely(freqs->old != cpufreq_cpu_data[freqs->cpu]->cur)))
-			{
-				if (cpufreq_driver->flags & CPUFREQ_PANIC_OUTOFSYNC)
-					panic("CPU Frequency is out of sync.");
-
-				printk(KERN_WARNING "Warning: CPU frequency out of sync: "
-				       "cpufreq and timing core thinks of %u, is %u kHz.\n", 
-				       cpufreq_cpu_data[freqs->cpu]->cur, freqs->old);
-				freqs->old = cpufreq_cpu_data[freqs->cpu]->cur;
-			}
-		}
-		notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_PRECHANGE, freqs);
-		adjust_jiffies(CPUFREQ_PRECHANGE, freqs);
-		break;
-	case CPUFREQ_POSTCHANGE:
-		adjust_jiffies(CPUFREQ_POSTCHANGE, freqs);
-		notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_POSTCHANGE, freqs);
-		cpufreq_cpu_data[freqs->cpu]->cur = freqs->new;
-		break;
-	}
-	up_read(&cpufreq_notifier_rwsem);
-}
-EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
-
-
-
 /*********************************************************************
  *               REGISTER / UNREGISTER CPUFREQ DRIVER                *
  *********************************************************************/
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index 161e8a27c..558cc9dd0 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -82,6 +82,13 @@ userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
 {
         struct cpufreq_freqs *freq = data;
 
+	/* Don't update cur_freq if CPU is managed and we're
+	 * waking up: else we won't remember what frequency 
+	 * we need to set the CPU to.
+	 */
+	if (cpu_is_managed[freq->cpu] && (val == CPUFREQ_RESUMECHANGE))
+		return 0;
+
 	cpu_cur_freq[freq->cpu] = freq->new;
 
         return 0;
@@ -147,6 +154,9 @@ EXPORT_SYMBOL_GPL(cpufreq_setmax);
 
 #ifdef CONFIG_CPU_FREQ_24_API
 
+#warning The /proc/sys/cpu/ and sysctl interface to cpufreq will be removed from the 2.6. kernel series soon after 2005-01-01
+
+static unsigned int warning_print = 0;
 
 /*********************** cpufreq_sysctl interface ********************/
 static int
@@ -162,6 +172,13 @@ cpufreq_procctl(ctl_table *ctl, int write, struct file *filp,
 		return 0;
 	}
 
+	if (!warning_print) {
+		warning_print++;
+		printk(KERN_INFO "Access to /proc/sys/cpu/ is deprecated and "
+			"will be removed from (new) 2.6. kernels soon "
+			"after 2005-01-01\n");
+	}
+
 	if (write) {
 		unsigned int freq;
 
@@ -197,6 +214,13 @@ cpufreq_sysctl(ctl_table *table, int __user *name, int nlen,
 	if (!cpu_online(cpu))
 		return -EINVAL;
 
+	if (!warning_print) {
+		warning_print++;
+		printk(KERN_INFO "Access to /proc/sys/cpu/ is deprecated and "
+			"will be removed from (new) 2.6. kernels soon "
+			"after 2005-01-01\n");
+	}
+
 	if (oldval && oldlenp) {
 		size_t oldlen;
 
@@ -522,6 +546,9 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
 		else if (policy->min > cpu_cur_freq[cpu])
 			__cpufreq_driver_target(&current_policy[cpu], policy->min, 
 			      CPUFREQ_RELATION_L);
+		else
+			__cpufreq_driver_target(&current_policy[cpu], cpu_cur_freq[cpu],
+			      CPUFREQ_RELATION_L);
 		memcpy (&current_policy[cpu], policy, sizeof(struct cpufreq_policy));
 		up(&userspace_sem);
 		break;
diff --git a/drivers/cpufreq/proc_intf.c b/drivers/cpufreq/proc_intf.c
index a0eaf6f1d..673977899 100644
--- a/drivers/cpufreq/proc_intf.c
+++ b/drivers/cpufreq/proc_intf.c
@@ -12,9 +12,12 @@
 #include <linux/proc_fs.h>
 #include <asm/uaccess.h>
 
+#warning This module will be removed from the 2.6. kernel series soon after 2005-01-01
 
 #define CPUFREQ_ALL_CPUS		((NR_CPUS))
 
+static unsigned int warning_print = 0;
+
 /**
  * cpufreq_parse_policy - parse a policy string
  * @input_string: the string to parse.
@@ -110,6 +113,13 @@ static int cpufreq_proc_read (
 	if (off != 0)
 		goto end;
 
+	if (!warning_print) {
+		warning_print++;
+		printk(KERN_INFO "Access to /proc/cpufreq is deprecated and "
+			"will be removed from (new) 2.6. kernels soon "
+			"after 2005-01-01\n");
+	}
+
 	p += sprintf(p, "          minimum CPU frequency  -  maximum CPU frequency  -  policy\n");
 	for (i=0;i<NR_CPUS;i++) {
 		if (!cpu_online(i))
@@ -179,6 +189,13 @@ static int cpufreq_proc_write (
 	
 	if (copy_from_user(proc_string, buffer, count))
 		return -EFAULT;
+
+	if (!warning_print) {
+		warning_print++;
+		printk(KERN_INFO "Access to /proc/cpufreq is deprecated and "
+			"will be removed from (new) 2.6. kernels soon "
+			"after 2005-01-01\n");
+	}
 	
 	proc_string[count] = '\0';
 
diff --git a/drivers/fc4/soc.h b/drivers/fc4/soc.h
index 7015eb7ba..a48a08732 100644
--- a/drivers/fc4/soc.h
+++ b/drivers/fc4/soc.h
@@ -81,29 +81,29 @@ do {	(s)->imask = (i); \
  * That's why here are the following inline functions...
  */
  
-typedef unsigned long xram_p;
+typedef void __iomem *xram_p;
 
 /* Get 32bit number from XRAM */
-static inline u32 xram_get_32 (xram_p x)
+static inline u32 xram_get_32(xram_p x)
 {
 	return ((sbus_readw(x + 0x00UL) << 16) |
 		(sbus_readw(x + 0x02UL)));
 }
 
 /* Like the above, but when we don't care about the high 16 bits */
-static inline u32 xram_get_32low (xram_p x)
+static inline u32 xram_get_32low(xram_p x)
 {
 	return (u32) sbus_readw(x + 0x02UL);
 }
 
-static inline u16 xram_get_16 (xram_p x)
+static inline u16 xram_get_16(xram_p x)
 {
 	return sbus_readw(x);
 }
 
-static inline u8 xram_get_8 (xram_p x)
+static inline u8 xram_get_8(xram_p x)
 {
-	if (x & (xram_p)0x1) {
+	if ((unsigned long)x & 0x1UL) {
 		x = x - 1;
 		return (u8) sbus_readw(x);
 	} else {
@@ -111,7 +111,7 @@ static inline u8 xram_get_8 (xram_p x)
 	}
 }
 
-static inline void xram_copy_from (void *p, xram_p x, int len)
+static inline void xram_copy_from(void *p, xram_p x, int len)
 {
 	for (len >>= 2; len > 0; len--, x += sizeof(u32)) {
 		u32 val, *p32 = p;
@@ -123,7 +123,7 @@ static inline void xram_copy_from (void *p, xram_p x, int len)
 	}
 }
 
-static inline void xram_copy_to (xram_p x, void *p, int len)
+static inline void xram_copy_to(xram_p x, void *p, int len)
 {
 	for (len >>= 2; len > 0; len--, x += sizeof(u32)) {
 		u32 tmp, *p32 = p;
@@ -135,7 +135,7 @@ static inline void xram_copy_to (xram_p x, void *p, int len)
 	}
 }
 
-static inline void xram_bzero (xram_p x, int len)
+static inline void xram_bzero(xram_p x, int len)
 {
 	for (len >>= 1; len > 0; len--, x += sizeof(u16))
 		sbus_writew(0, x);
@@ -274,7 +274,7 @@ struct soc {
 	soc_cq			req[2]; /* Request CQs */
 	soc_cq			rsp[2]; /* Response CQs */
 	int			soc_no;
-	unsigned long		regs;
+	void __iomem		*regs;
 	xram_p			xram;
 	fc_wwn			wwn;
 	u32			imask;	/* Our copy of regs->imask */
diff --git a/drivers/fc4/socal.c b/drivers/fc4/socal.c
index e158d7d26..5ee4dda53 100644
--- a/drivers/fc4/socal.c
+++ b/drivers/fc4/socal.c
@@ -60,7 +60,7 @@ static char *version =
 #define for_each_socal(s) for (s = socals; s; s = s->next)
 struct socal *socals = NULL;
 
-static void socal_copy_from_xram(void *d, unsigned long xram, long size)
+static void socal_copy_from_xram(void *d, void __iomem *xram, long size)
 {
 	u32 *dp = (u32 *) d;
 	while (size) {
@@ -70,7 +70,7 @@ static void socal_copy_from_xram(void *d, unsigned long xram, long size)
 	}
 }
 
-static void socal_copy_to_xram(unsigned long xram, void *s, long size)
+static void socal_copy_to_xram(void __iomem *xram, void *s, long size)
 {
 	u32 *sp = (u32 *) s;
 	while (size) {
diff --git a/drivers/fc4/socal.h b/drivers/fc4/socal.h
index a853fad92..2ff386b9f 100644
--- a/drivers/fc4/socal.h
+++ b/drivers/fc4/socal.h
@@ -295,9 +295,9 @@ struct socal {
 	socal_cq		req[4]; /* Request CQs */
 	socal_cq		rsp[4]; /* Response CQs */
 	int			socal_no;
-	unsigned long		regs;
-	unsigned long		xram;
-	unsigned long		eeprom;
+	void __iomem		*regs;
+	void __iomem		*xram;
+	void __iomem		*eeprom;
 	fc_wwn			wwn;
 	u32			imask;	/* Our copy of regs->imask */
 	u32			cfg;	/* Our copy of regs->cfg */
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index a6504dbd3..4607ddd46 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -14,8 +14,9 @@ config EDD
 	  Services real mode BIOS calls to determine which disk
 	  BIOS tries boot from.  This information is then exported via sysfs.
 
-	  This option is experimental, but believed to be safe,
-	  and most disk controller BIOS vendors do not yet implement this feature.
+	  This option is experimental and is known to fail to boot on some
+          obscure configurations. Most disk controller BIOS vendors do
+          not yet implement this feature.
 
 config EFI_VARS
 	tristate "EFI Variable Support via sysfs"
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 2b48079f5..cd170395a 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -7,6 +7,9 @@ obj-$(CONFIG_I2C_CHARDEV)	+= i2c-dev.o
 obj-$(CONFIG_I2C_SENSOR)	+= i2c-sensor.o
 obj-y				+= busses/ chips/ algos/
 
+i2c-sensor-objs := i2c-sensor-detect.o i2c-sensor-vid.o
+
+
 ifeq ($(CONFIG_I2C_DEBUG_CORE),y)
 EXTRA_CFLAGS += -DDEBUG
 endif
diff --git a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig
index 88982cd31..cf9832bdc 100644
--- a/drivers/i2c/algos/Kconfig
+++ b/drivers/i2c/algos/Kconfig
@@ -27,6 +27,17 @@ config I2C_ALGOPCF
 	  This support is also available as a module.  If so, the module 
 	  will be called i2c-algo-pcf.
 
+config I2C_ALGOPCA
+	tristate "I2C PCA 9564 interfaces"
+	depends on I2C
+	help
+	  This allows you to use a range of I2C adapters called PCA adapters.
+	  Say Y if you own an I2C adapter belonging to this class and then say
+	  Y to the specific driver for you adapter below.
+
+	  This support is also available as a module.  If so, the module 
+	  will be called i2c-algo-pca.
+
 config I2C_ALGOITE
 	tristate "ITE I2C Algorithm"
 	depends on MIPS_ITE8172 && I2C
diff --git a/drivers/i2c/algos/Makefile b/drivers/i2c/algos/Makefile
index df88f3f01..3545644be 100644
--- a/drivers/i2c/algos/Makefile
+++ b/drivers/i2c/algos/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_I2C_ALGOBIT)	+= i2c-algo-bit.o
 obj-$(CONFIG_I2C_ALGOPCF)	+= i2c-algo-pcf.o
+obj-$(CONFIG_I2C_ALGOPCA)	+= i2c-algo-pca.o
 obj-$(CONFIG_I2C_ALGOITE)	+= i2c-algo-ite.o
 
 ifeq ($(CONFIG_I2C_DEBUG_ALGO),y)
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index afbd48fe8..4ea4c7928 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -565,8 +565,8 @@ MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
 MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(bit_test, "i");
-MODULE_PARM(i2c_debug,"i");
+module_param(bit_test, bool, 0);
+module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
 
 MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck");
 MODULE_PARM_DESC(i2c_debug,
diff --git a/drivers/i2c/algos/i2c-algo-ite.c b/drivers/i2c/algos/i2c-algo-ite.c
index acc7ab6a9..7405aac67 100644
--- a/drivers/i2c/algos/i2c-algo-ite.c
+++ b/drivers/i2c/algos/i2c-algo-ite.c
@@ -52,21 +52,15 @@
 #define	PM_IBSR		IT8172_PCI_IO_BASE + IT_PM_DSR + 0x04 
 #define GPIO_CCR	IT8172_PCI_IO_BASE + IT_GPCCR
 
-/* ----- global defines ----------------------------------------------- */
-#define DEB(x) if (i2c_debug>=1) x
 #define DEB2(x) if (i2c_debug>=2) x
 #define DEB3(x) if (i2c_debug>=3) x /* print several statistical values*/
-#define DEBPROTO(x) if (i2c_debug>=9) x;
- 	/* debug the protocol by showing transferred bits */
 #define DEF_TIMEOUT 16
 
 
-/* ----- global variables ---------------------------------------------	*/
-
 /* module parameters:
  */
-static int i2c_debug=1;
-static int iic_test=0;	/* see if the line-setting functions work	*/
+static int i2c_debug;
+static int iic_test;	/* see if the line-setting functions work	*/
 
 /* --- setting states on the bus with the right timing: ---------------	*/
 
@@ -804,8 +798,8 @@ MODULE_AUTHOR("MontaVista Software <www.mvista.com>");
 MODULE_DESCRIPTION("ITE iic algorithm");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(iic_test, "i");
-MODULE_PARM(i2c_debug,"i");
+module_param(iic_test, bool, 0);
+module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
 
 MODULE_PARM_DESC(iic_test, "Test if the I2C bus is available");
 MODULE_PARM_DESC(i2c_debug,
diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
index b53f65a12..6dc807abc 100644
--- a/drivers/i2c/algos/i2c-algo-pcf.c
+++ b/drivers/i2c/algos/i2c-algo-pcf.c
@@ -38,8 +38,6 @@
 #include "i2c-algo-pcf.h"
 
 
-/* ----- global defines ----------------------------------------------- */
-#define DEB(x) if (i2c_debug>=1) x
 #define DEB2(x) if (i2c_debug>=2) x
 #define DEB3(x) if (i2c_debug>=3) x /* print several statistical values*/
 #define DEBPROTO(x) if (i2c_debug>=9) x;
@@ -48,7 +46,7 @@
 
 /* module parameters:
  */
-static int i2c_debug=0;
+static int i2c_debug;
 
 /* --- setting states on the bus with the right timing: ---------------	*/
 
@@ -101,12 +99,6 @@ static int wait_for_bb(struct i2c_algo_pcf_data *adap) {
 }
 
 
-static inline void pcf_sleep(unsigned long timeout)
-{
-	schedule_timeout( timeout * HZ);
-}
-
-
 static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) {
 
 	int timeout = DEF_TIMEOUT;
@@ -472,6 +464,6 @@ MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
 MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(i2c_debug,"i");
+module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(i2c_debug,
         "debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol");
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 3628b099f..166b9174a 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -164,6 +164,17 @@ config I2C_IXP4XX
 	  This support is also available as a module. If so, the module
 	  will be called i2c-ixp4xx.
 
+config I2C_IXP2000
+	tristate "IXP2000 GPIO-Based I2C Interface"
+	depends on I2C && ARCH_IXP2000
+	select I2C_ALGOBIT
+	help
+	  Say Y here if you have an Intel IXP2000(2400, 2800, 2850) based 
+	  system and are using GPIO lines for an I2C bus.
+
+	  This support is also available as a module. If so, the module
+	  will be called i2c-ixp2000.
+
 config I2C_KEYWEST
 	tristate "Powermac Keywest I2C interface"
 	depends on I2C && PPC_PMAC
@@ -174,6 +185,18 @@ config I2C_KEYWEST
 	  This support is also available as a module.  If so, the module 
 	  will be called i2c-keywest.
 
+config I2C_MPC
+	tristate "MPC107/824x/85xx/52xx"
+	depends on I2C && FSL_OCP
+	help
+	  If you say yes to this option, support will be included for the
+	  built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
+	  MPC85xx family processors. The driver may also work on 52xx
+	  family processors, though interrupts are known not to work.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-mpc.
+
 config I2C_NFORCE2
 	tristate "Nvidia Nforce2"
 	depends on I2C && PCI && EXPERIMENTAL
@@ -396,4 +419,15 @@ config I2C_VOODOO3
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-voodoo3.
 
+config I2C_PCA_ISA
+	tristate "PCA9564 on an ISA bus"
+	depends on I2C
+	select I2C_ALGOPCA
+	help
+	  This driver supports ISA boards using the Philips PCA 9564
+	  Parallel bus to I2C bus controller
+	  
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-pca-isa.
+
 endmenu
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 83391986c..932b00fb6 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -15,11 +15,14 @@ obj-$(CONFIG_I2C_IBM_IIC)	+= i2c-ibm_iic.o
 obj-$(CONFIG_I2C_IOP3XX)	+= i2c-iop3xx.o
 obj-$(CONFIG_I2C_ISA)		+= i2c-isa.o
 obj-$(CONFIG_I2C_ITE)		+= i2c-ite.o
+obj-$(CONFIG_I2C_IXP2000)	+= i2c-ixp2000.o
 obj-$(CONFIG_I2C_IXP4XX)	+= i2c-ixp4xx.o
 obj-$(CONFIG_I2C_KEYWEST)	+= i2c-keywest.o
+obj-$(CONFIG_I2C_MPC)		+= i2c-mpc.o
 obj-$(CONFIG_I2C_NFORCE2)	+= i2c-nforce2.o
 obj-$(CONFIG_I2C_PARPORT)	+= i2c-parport.o
 obj-$(CONFIG_I2C_PARPORT_LIGHT)	+= i2c-parport-light.o
+obj-$(CONFIG_I2C_PCA_ISA)	+= i2c-pca-isa.o
 obj-$(CONFIG_I2C_PIIX4)		+= i2c-piix4.o
 obj-$(CONFIG_I2C_PROSAVAGE)	+= i2c-prosavage.o
 obj-$(CONFIG_I2C_RPXLITE)	+= i2c-rpx.o
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
index f77ae846e..ef6dd420d 100644
--- a/drivers/i2c/busses/i2c-ali1563.c
+++ b/drivers/i2c/busses/i2c-ali1563.c
@@ -395,7 +395,7 @@ static struct pci_device_id __devinitdata ali1563_id_table[] = {
 };
 
 static struct pci_driver ali1563_pci_driver = {
- 	.name		= "i2c-ali1563",
+ 	.name		= "ali1563_i2c",
 	.id_table	= ali1563_id_table,
  	.probe		= ali1563_probe,
 	.remove		= ali1563_remove,
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
index ef4a62524..4e3dfd787 100644
--- a/drivers/i2c/busses/i2c-ali15x3.c
+++ b/drivers/i2c/busses/i2c-ali15x3.c
@@ -126,8 +126,8 @@
 
 /* If force_addr is set to anything different from 0, we forcibly enable
    the device at the given address. */
-static int force_addr = 0;
-MODULE_PARM(force_addr, "i");
+static u16 force_addr = 0;
+module_param(force_addr, ushort, 0);
 MODULE_PARM_DESC(force_addr,
 		 "Initialize the base address of the i2c controller");
 
@@ -509,7 +509,7 @@ static void __devexit ali15x3_remove(struct pci_dev *dev)
 }
 
 static struct pci_driver ali15x3_driver = {
-	.name		= "ali15x3 smbus",
+	.name		= "ali15x3_smbus",
 	.id_table	= ali15x3_ids,
 	.probe		= ali15x3_probe,
 	.remove		= __devexit_p(ali15x3_remove),
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index 4b1151373..22c4a9948 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -394,7 +394,7 @@ static void __devexit amd756_remove(struct pci_dev *dev)
 }
 
 static struct pci_driver amd756_driver = {
-	.name		= "amd756 smbus",
+	.name		= "amd756_smbus",
 	.id_table	= amd756_ids,
 	.probe		= amd756_probe,
 	.remove		= __devexit_p(amd756_remove),
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
index b0e597049..c0ea19e41 100644
--- a/drivers/i2c/busses/i2c-amd8111.c
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -392,7 +392,7 @@ static void __devexit amd8111_remove(struct pci_dev *dev)
 }
 
 static struct pci_driver amd8111_driver = {
-	.name		= "amd8111 smbus 2",
+	.name		= "amd8111_smbus2",
 	.id_table	= amd8111_ids,
 	.probe		= amd8111_probe,
 	.remove		= __devexit_p(amd8111_remove),
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index 768c901a8..f6bd38b06 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -269,11 +269,11 @@ MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
 MODULE_DESCRIPTION("I2C-Bus adapter routines for PCF8584 ISA bus adapter");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(base, "i");
-MODULE_PARM(irq, "i");
-MODULE_PARM(clock, "i");
-MODULE_PARM(own, "i");
-MODULE_PARM(mmapped, "i");
+module_param(base, int, 0);
+module_param(irq, int, 0);
+module_param(clock, int, 0);
+module_param(own, int, 0);
+module_param(mmapped, int, 0);
 
 module_init(i2c_pcfisa_init);
 module_exit(i2c_pcfisa_exit);
diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c
index 7d6d69182..275da79e3 100644
--- a/drivers/i2c/busses/i2c-hydra.c
+++ b/drivers/i2c/busses/i2c-hydra.c
@@ -158,7 +158,7 @@ static void __devexit hydra_remove(struct pci_dev *dev)
 
 
 static struct pci_driver hydra_driver = {
-	.name		= "hydra smbus",
+	.name		= "hydra_smbus",
 	.id_table	= hydra_ids,
 	.probe		= hydra_probe,
 	.remove		= __devexit_p(hydra_remove),
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 4689bd01d..e873ba001 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -98,8 +98,8 @@
 
 /* If force_addr is set to anything different from 0, we forcibly enable
    the I801 at the given address. VERY DANGEROUS! */
-static int force_addr = 0;
-MODULE_PARM(force_addr, "i");
+static u16 force_addr;
+module_param(force_addr, ushort, 0);
 MODULE_PARM_DESC(force_addr,
 		 "Forcibly enable the I801 at the given address. "
 		 "EXTREMELY DANGEROUS!");
@@ -623,7 +623,7 @@ static void __devexit i801_remove(struct pci_dev *dev)
 }
 
 static struct pci_driver i801_driver = {
-	.name		= "i801 smbus",
+	.name		= "i801_smbus",
 	.id_table	= i801_ids,
 	.probe		= i801_probe,
 	.remove		= __devexit_p(i801_remove),
diff --git a/drivers/i2c/busses/i2c-i810.c b/drivers/i2c/busses/i2c-i810.c
index fd11366cc..46bd56660 100644
--- a/drivers/i2c/busses/i2c-i810.c
+++ b/drivers/i2c/busses/i2c-i810.c
@@ -231,7 +231,7 @@ static void __devexit i810_remove(struct pci_dev *dev)
 }
 
 static struct pci_driver i810_driver = {
-	.name		= "i810 smbus",
+	.name		= "i810_smbus",
 	.id_table	= i810_ids,
 	.probe		= i810_probe,
 	.remove		= __devexit_p(i810_remove),
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index a25218dba..fcb525296 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -50,12 +50,12 @@
 MODULE_DESCRIPTION("IBM IIC driver v" DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 
-static int iic_force_poll = 0;
-MODULE_PARM(iic_force_poll, "i");
+static int iic_force_poll;
+module_param(iic_force_poll, bool, 0);
 MODULE_PARM_DESC(iic_force_poll, "Force polling mode");
 
-static int iic_force_fast = 0;
-MODULE_PARM(iic_force_fast, "i");
+static int iic_force_fast;
+module_param(iic_force_fast, bool, 0);
 MODULE_PARM_DESC(iic_fast_poll, "Force fast mode (400 kHz)");
 
 #define DBG_LEVEL 0
diff --git a/drivers/i2c/busses/i2c-ite.c b/drivers/i2c/busses/i2c-ite.c
index 917759c42..da926a619 100644
--- a/drivers/i2c/busses/i2c-ite.c
+++ b/drivers/i2c/busses/i2c-ite.c
@@ -54,10 +54,10 @@
 #define DEFAULT_CLOCK 0x1b0e	/* default 16MHz/(27+14) = 400KHz */
 #define DEFAULT_OWN   0x55
 
-static int base  = 0;
-static int irq   = 0;
-static int clock = 0;
-static int own   = 0;
+static int base;
+static int irq;
+static int clock;
+static int own;
 
 static struct iic_ite gpi;
 static wait_queue_head_t iic_wait;
@@ -102,14 +102,6 @@ static int iic_ite_getclock(void *data)
 }
 
 
-#if 0
-static void iic_ite_sleep(unsigned long timeout)
-{
-	schedule_timeout( timeout * HZ);
-}
-#endif
-
-
 /* Put this process to sleep.  We will wake up when the
  * IIC controller interrupts.
  */
@@ -254,10 +246,10 @@ MODULE_AUTHOR("MontaVista Software <www.mvista.com>");
 MODULE_DESCRIPTION("I2C-Bus adapter routines for ITE IIC bus adapter");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(base, "i");
-MODULE_PARM(irq, "i");
-MODULE_PARM(clock, "i");
-MODULE_PARM(own, "i");
+module_param(base, int, 0);
+module_param(irq, int, 0);
+module_param(clock, int, 0);
+module_param(own, int, 0);
 
 
 /* Called when module is loaded or when kernel is initialized.
diff --git a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c
index 0b606e88d..a5a8c1e79 100644
--- a/drivers/i2c/busses/i2c-keywest.c
+++ b/drivers/i2c/busses/i2c-keywest.c
@@ -88,12 +88,12 @@ static const char *__kw_state_names[] = {
 };
 #endif /* DEBUG */
 
+static int probe;
+
 MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
 MODULE_DESCRIPTION("I2C driver for Apple's Keywest");
 MODULE_LICENSE("GPL");
-MODULE_PARM(probe, "i");
-
-static int probe = 0;
+module_param(probe, bool, 0);
 
 #ifdef POLLED_MODE
 /* Don't schedule, the g5 fan controller is too
@@ -662,8 +662,7 @@ dispose_iface(struct device *dev)
 	spin_lock_irq(&iface->lock);
 	while (iface->state != state_idle) {
 		spin_unlock_irq(&iface->lock);
-		set_task_state(current,TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ/10);
+		msleep(100);
 		spin_lock_irq(&iface->lock);
 	}
 #endif /* POLLED_MODE */
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index 774a7ef52..0cf6a2686 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -244,8 +244,7 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
 		temp = inb_p(NVIDIA_SMB_STS);
 	}
 	if (~temp & NVIDIA_SMB_STS_DONE) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(HZ/100);
+		msleep(10);
 		temp = inb_p(NVIDIA_SMB_STS);
 	}
 
@@ -384,7 +383,7 @@ static void __devexit nforce2_remove(struct pci_dev *dev)
 }
 
 static struct pci_driver nforce2_driver = {
-	.name		= "nForce2 SMBus",
+	.name		= "nForce2_smbus",
 	.id_table	= nforce2_ids,
 	.probe		= nforce2_probe,
 	.remove		= __devexit_p(nforce2_remove),
diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c
index 6798954f0..cb5e72230 100644
--- a/drivers/i2c/busses/i2c-parport-light.c
+++ b/drivers/i2c/busses/i2c-parport-light.c
@@ -36,8 +36,8 @@
 
 #define DEFAULT_BASE 0x378
 
-static int base;
-MODULE_PARM(base, "i");
+static u16 base;
+module_param(base, ushort, 0);
 MODULE_PARM_DESC(base, "Base I/O address");
 
 /* ----- Low-level parallel port access ----------------------------------- */
diff --git a/drivers/i2c/busses/i2c-parport.h b/drivers/i2c/busses/i2c-parport.h
index 284d3f5d3..f63a53779 100644
--- a/drivers/i2c/busses/i2c-parport.h
+++ b/drivers/i2c/busses/i2c-parport.h
@@ -83,7 +83,7 @@ static struct adapter_parm adapter_parm[] = {
 };
 
 static int type;
-MODULE_PARM(type, "i");
+module_param(type, int, 0);
 MODULE_PARM_DESC(type,
 	"Type of adapter:\n"
 	" 0 = Philips adapter\n"
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index e7c0262b0..6dd156fce 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -493,7 +493,7 @@ static void __devexit piix4_remove(struct pci_dev *dev)
 }
 
 static struct pci_driver piix4_driver = {
-	.name		= "piix4-smbus",
+	.name		= "piix4_smbus",
 	.id_table	= piix4_ids,
 	.probe		= piix4_probe,
 	.remove		= __devexit_p(piix4_remove),
diff --git a/drivers/i2c/busses/i2c-prosavage.c b/drivers/i2c/busses/i2c-prosavage.c
index 0aabe49e5..9552e53a3 100644
--- a/drivers/i2c/busses/i2c-prosavage.c
+++ b/drivers/i2c/busses/i2c-prosavage.c
@@ -314,7 +314,7 @@ static struct pci_device_id prosavage_pci_tbl[] = {
 };
 
 static struct pci_driver prosavage_driver = {
-	.name		=	"prosavage-smbus",
+	.name		=	"prosavage_smbus",
 	.id_table	=	prosavage_pci_tbl,
 	.probe		=	prosavage_probe,
 	.remove		=	prosavage_remove,
diff --git a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c
index 33972a779..52d51948a 100644
--- a/drivers/i2c/busses/i2c-savage4.c
+++ b/drivers/i2c/busses/i2c-savage4.c
@@ -178,7 +178,7 @@ static void __devexit savage4_remove(struct pci_dev *dev)
 }
 
 static struct pci_driver savage4_driver = {
-	.name		= "savage4 smbus",
+	.name		= "savage4_smbus",
 	.id_table	= savage4_ids,
 	.probe		= savage4_probe,
 	.remove		= __devexit_p(savage4_remove),
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
index a5040cca3..9469ebf16 100644
--- a/drivers/i2c/busses/i2c-sis5595.c
+++ b/drivers/i2c/busses/i2c-sis5595.c
@@ -124,8 +124,8 @@ static int blacklist[] = {
 
 /* If force_addr is set to anything different from 0, we forcibly enable
    the device at the given address. */
-static int force_addr = 0;
-MODULE_PARM(force_addr, "i");
+static u16 force_addr = 0;
+module_param(force_addr, ushort, 0);
 MODULE_PARM_DESC(force_addr, "Initialize the base address of the i2c controller");
 
 static unsigned short sis5595_base = 0;
@@ -393,7 +393,7 @@ static void __devexit sis5595_remove(struct pci_dev *dev)
 }
 
 static struct pci_driver sis5595_driver = {
-	.name		= "sis5595 smbus",
+	.name		= "sis5595_smbus",
 	.id_table	= sis5595_ids,
 	.probe		= sis5595_probe,
 	.remove		= __devexit_p(sis5595_remove),
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
index 437ee28d3..20e3fb42b 100644
--- a/drivers/i2c/busses/i2c-sis630.c
+++ b/drivers/i2c/busses/i2c-sis630.c
@@ -94,11 +94,11 @@
 #define SIS630_BLOCK_DATA	0x05
 
 /* insmod parameters */
-static int high_clock = 0;
-static int force = 0;
-MODULE_PARM(high_clock, "i");
+static int high_clock;
+static int force;
+module_param(high_clock, bool, 0);
 MODULE_PARM_DESC(high_clock, "Set Host Master Clock to 56KHz (default 14KHz).");
-MODULE_PARM(force, "i");
+module_param(force, bool, 0);
 MODULE_PARM_DESC(force, "Forcibly enable the SIS630. DANGEROUS!");
 
 /* acpi base address */
@@ -145,7 +145,7 @@ static int sis630_transaction_start(struct i2c_adapter *adap, int size, u8 *oldc
 	dev_dbg(&adap->dev, "saved clock 0x%02x\n", *oldclock);
 
 	/* disable timeout interrupt , set Host Master Clock to 56KHz if requested */
-	if (high_clock > 0)
+	if (high_clock)
 		sis630_write(SMB_CNT, 0x20);
 	else
 		sis630_write(SMB_CNT, (*oldclock & ~0x40));
@@ -210,7 +210,7 @@ static void sis630_transaction_end(struct i2c_adapter *adap, u8 oldclock)
 	 * restore old Host Master Clock if high_clock is set
 	 * and oldclock was not 56KHz
 	 */
-	if (high_clock > 0 && !(oldclock & 0x20))
+	if (high_clock && !(oldclock & 0x20))
 		sis630_write(SMB_CNT,(sis630_read(SMB_CNT) & ~0x20));
 
 	dev_dbg(&adap->dev, "SMB_CNT after clock restore 0x%02x\n", sis630_read(SMB_CNT));
@@ -401,7 +401,7 @@ static int sis630_setup(struct pci_dev *sis630_dev)
 	if (dummy) {
 		pci_dev_put(dummy);
 	}
-        else if (force > 0) {
+        else if (force) {
 		dev_err(&sis630_dev->dev, "WARNING: Can't detect SIS630 compatible device, but "
 			"loading because of force option enabled\n");
  	}
@@ -464,6 +464,7 @@ static struct i2c_adapter sis630_adapter = {
 
 static struct pci_device_id sis630_ids[] __devinitdata = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) },
 	{ 0, }
 };
 
@@ -494,7 +495,7 @@ static void __devexit sis630_remove(struct pci_dev *dev)
 
 
 static struct pci_driver sis630_driver = {
-	.name		= "sis630 smbus",
+	.name		= "sis630_smbus",
 	.id_table	= sis630_ids,
 	.probe		= sis630_probe,
 	.remove		= __devexit_p(sis630_remove),
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index c71daa347..d605dee4d 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -339,7 +339,7 @@ static void __devexit sis96x_remove(struct pci_dev *dev)
 }
 
 static struct pci_driver sis96x_driver = {
-	.name		= "sis96x smbus",
+	.name		= "sis96x_smbus",
 	.id_table	= sis96x_ids,
 	.probe		= sis96x_probe,
 	.remove		= __devexit_p(sis96x_remove),
diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c
index fba8f0eae..0497b9d0c 100644
--- a/drivers/i2c/busses/i2c-via.c
+++ b/drivers/i2c/busses/i2c-via.c
@@ -158,7 +158,7 @@ static void __devexit vt586b_remove(struct pci_dev *dev)
 
 
 static struct pci_driver vt586b_driver = {
-	.name		= "vt586b smbus",
+	.name		= "vt586b_smbus",
 	.id_table	= vt586b_ids,
 	.probe		= vt586b_probe,
 	.remove		= __devexit_p(vt586b_remove),
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index fbd4a15d8..396b5ebf1 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -92,13 +92,13 @@ static unsigned short smb_cf_hstcfg = 0xD2;
 /* If force is set to anything different from 0, we forcibly enable the
    VT596. DANGEROUS! */
 static int force;
-MODULE_PARM(force, "i");
+module_param(force, bool, 0);
 MODULE_PARM_DESC(force, "Forcibly enable the SMBus. DANGEROUS!");
 
 /* If force_addr is set to anything different from 0, we forcibly enable
    the VT596 at the given address. VERY DANGEROUS! */
-static int force_addr;
-MODULE_PARM(force_addr, "i");
+static u16 force_addr;
+module_param(force_addr, ushort, 0);
 MODULE_PARM_DESC(force_addr,
 		 "Forcibly enable the SMBus at the given address. "
 		 "EXTREMELY DANGEROUS!");
@@ -455,7 +455,7 @@ static struct pci_device_id vt596_ids[] = {
 };
 
 static struct pci_driver vt596_driver = {
-	.name		= "vt596 smbus",
+	.name		= "vt596_smbus",
 	.id_table	= vt596_ids,
 	.probe		= vt596_probe,
 	.remove		= __devexit_p(vt596_remove),
diff --git a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c
index efb677d24..b91456108 100644
--- a/drivers/i2c/busses/i2c-voodoo3.c
+++ b/drivers/i2c/busses/i2c-voodoo3.c
@@ -224,7 +224,7 @@ static void __devexit voodoo3_remove(struct pci_dev *dev)
 }
 
 static struct pci_driver voodoo3_driver = {
-	.name		= "voodoo3 smbus",
+	.name		= "voodoo3_smbus",
 	.id_table	= voodoo3_ids,
 	.probe		= voodoo3_probe,
 	.remove		= __devexit_p(voodoo3_remove),
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index b3cbbb9ea..62b7614e5 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -32,6 +32,7 @@
 #include <linux/i2c.h>
 #include <linux/smp_lock.h>
 #include <linux/pci.h>
+#include <linux/delay.h>
 #include <asm/io.h>
 
 #include <linux/scx200.h>
@@ -44,7 +45,8 @@ MODULE_LICENSE("GPL");
 
 #define MAX_DEVICES 4
 static int base[MAX_DEVICES] = { 0x820, 0x840 };
-MODULE_PARM(base, "1-4i");
+static int num_base;
+module_param_array(base, int, num_base, 0);
 MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers");
 
 #ifdef DEBUG
@@ -254,7 +256,7 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface)
 			scx200_acb_machine(iface, status);
 			return;
 		}
-		schedule_timeout(HZ/100+1);
+		msleep(10);
 	}
 
 	scx200_acb_timeout(iface);
diff --git a/drivers/i2c/busses/scx200_i2c.c b/drivers/i2c/busses/scx200_i2c.c
index b472fe81a..294ffa2f7 100644
--- a/drivers/i2c/busses/scx200_i2c.c
+++ b/drivers/i2c/busses/scx200_i2c.c
@@ -38,14 +38,14 @@ MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
 MODULE_DESCRIPTION("NatSemi SCx200 I2C Driver");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(scl, "i");
-MODULE_PARM_DESC(scl, "GPIO line for SCL");
-MODULE_PARM(sda, "i");
-MODULE_PARM_DESC(sda, "GPIO line for SDA");
-
 static int scl = CONFIG_SCx200_I2C_SCL;
 static int sda = CONFIG_SCx200_I2C_SDA;
 
+module_param(scl, int, 0);
+MODULE_PARM_DESC(scl, "GPIO line for SCL");
+module_param(sda, int, 0);
+MODULE_PARM_DESC(sda, "GPIO line for SDA");
+
 static void scx200_i2c_setscl(void *data, int state)
 {
 	scx200_gpio_set(scl, state);
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index af8d273d0..d624f4a16 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -149,7 +149,7 @@ config SENSORS_LM80
 
 config SENSORS_LM83
 	tristate "National Semiconductor LM83"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	select I2C_SENSOR
 	help
 	  If you say yes here you get support for National Semiconductor
@@ -191,6 +191,19 @@ config SENSORS_MAX1619
 	  This driver can also be built as a module.  If so, the module
 	  will be called max1619.
 
+config SENSORS_SMSC47M1
+	tristate "SMSC LPC47M10x and compatibles"
+	depends on I2C && EXPERIMENTAL
+	select I2C_SENSOR
+	select I2C_ISA
+	help
+	  If you say yes here you get support for the integrated fan
+	  monitoring and control capabilities of the SMSC LPC47B27x,
+	  LPC47M10x, LPC47M13x and LPC47M14x chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called smsc47m1.
+
 config SENSORS_VIA686A
 	tristate "VIA686A"
 	depends on I2C && PCI && EXPERIMENTAL
@@ -286,4 +299,16 @@ config SENSORS_RTC8564
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-rtc8564.
 
+config ISP1301_OMAP
+	tristate "Philips ISP1301 with OMAP OTG"
+	depends on I2C && ARCH_OMAP_OTG
+	help
+	  If you say yes here you get support for the Philips ISP1301
+	  USB-On-The-Go transceiver working with the OMAP OTG controller.
+	  The ISP1301 is used in products including H2 and H3 development
+	  boards for Texas Instruments OMAP processors.
+	  
+	  This driver can also be built as a module.  If so, the module
+	  will be called isp1301_omap.
+
 endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index f024e71a5..0f051183b 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -26,9 +26,12 @@ obj-$(CONFIG_SENSORS_MAX1619)	+= max1619.o
 obj-$(CONFIG_SENSORS_PCF8574)	+= pcf8574.o
 obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
 obj-$(CONFIG_SENSORS_RTC8564)	+= rtc8564.o
+obj-$(CONFIG_SENSORS_SMSC47M1)	+= smsc47m1.o
 obj-$(CONFIG_SENSORS_VIA686A)	+= via686a.o
 obj-$(CONFIG_SENSORS_W83L785TS)	+= w83l785ts.o
+obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
 
 ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
 EXTRA_CFLAGS += -DDEBUG
 endif
+
diff --git a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
index 73ca01db6..49a431bc7 100644
--- a/drivers/i2c/chips/adm1021.c
+++ b/drivers/i2c/chips/adm1021.c
@@ -418,7 +418,7 @@ MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl> and "
 MODULE_DESCRIPTION("adm1021 driver");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(read_only, "i");
+module_param(read_only, bool, 0);
 MODULE_PARM_DESC(read_only, "Don't set any values, read only mode");
 
 module_init(sensors_adm1021_init)
diff --git a/drivers/i2c/chips/adm1025.c b/drivers/i2c/chips/adm1025.c
index d38336fbc..711eaa21f 100644
--- a/drivers/i2c/chips/adm1025.c
+++ b/drivers/i2c/chips/adm1025.c
@@ -455,7 +455,7 @@ static void adm1025_init_client(struct i2c_client *client)
 	struct adm1025_data *data = i2c_get_clientdata(client);
 	int i;
 
-	data->vrm = 82;
+	data->vrm = i2c_which_vrm();
 
 	/*
 	 * Set high limits
diff --git a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c
index a416e4ee5..e170b2a78 100644
--- a/drivers/i2c/chips/asb100.c
+++ b/drivers/i2c/chips/asb100.c
@@ -63,9 +63,6 @@ static unsigned short normal_i2c_range[] = { 0x28, 0x2f, I2C_CLIENT_END };
 static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
 
-/* default VRM to 9.0 instead of 8.2 */
-#define ASB100_DEFAULT_VRM 90
-
 /* Insmod parameters */
 SENSORS_INSMOD_1(asb100);
 I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
@@ -523,9 +520,9 @@ static ssize_t show_vid(struct device *dev, char *buf)
 	return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
 }
 
-static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid, NULL);
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
 #define device_create_file_vid(client) \
-device_create_file(&client->dev, &dev_attr_in0_ref)
+device_create_file(&client->dev, &dev_attr_cpu0_vid)
 
 /* VRM */
 static ssize_t show_vrm(struct device *dev, char *buf)
@@ -959,7 +956,7 @@ static void asb100_init_client(struct i2c_client *client)
 
 	vid = asb100_read_value(client, ASB100_REG_VID_FANDIV) & 0x0f;
 	vid |= (asb100_read_value(client, ASB100_REG_CHIPID) & 0x01) << 4;
-	data->vrm = ASB100_DEFAULT_VRM;
+	data->vrm = i2c_which_vrm();
 	vid = vid_from_reg(vid, data->vrm);
 
 	/* Start monitoring */
diff --git a/drivers/i2c/chips/ds1621.c b/drivers/i2c/chips/ds1621.c
index bf3e21495..3aa72985e 100644
--- a/drivers/i2c/chips/ds1621.c
+++ b/drivers/i2c/chips/ds1621.c
@@ -37,7 +37,7 @@ static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
 /* Insmod parameters */
 SENSORS_INSMOD_1(ds1621);
 static int polarity = -1;
-MODULE_PARM(polarity, "i");
+module_param(polarity, int, 0);
 MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low");
 
 /* Many DS1621 constants specified below */
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index 6617ff76c..44a17f61e 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -45,7 +45,7 @@ static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
 SENSORS_INSMOD_1(eeprom);
 
 static int checksum = 0;
-MODULE_PARM(checksum, "i");
+module_param(checksum, bool, 0);
 MODULE_PARM_DESC(checksum, "Only accept eeproms whose checksum is correct");
 
 
diff --git a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
index ef6562987..c7c068b82 100644
--- a/drivers/i2c/chips/it87.c
+++ b/drivers/i2c/chips/it87.c
@@ -37,6 +37,7 @@
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
+#include <linux/i2c-vid.h>
 #include <asm/io.h>
 
 
@@ -47,7 +48,7 @@ static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END };
 static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_1(it87);
+SENSORS_INSMOD_2(it87, it8712);
 
 #define	REG	0x2e	/* The register to read/write */
 #define	DEV	0x07	/* Register: Logical device select */
@@ -163,8 +164,6 @@ static inline u8 FAN_TO_REG(long rpm, int div)
 					((val)+500)/1000),-128,127))
 #define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*1000)
 
-#define VID_FROM_REG(val) ((val)==0x1f?0:(val)>=0x10?510-(val)*10:\
-				205-(val)*5)
 #define ALARMS_FROM_REG(val) (val)
 
 static int DIV_TO_REG(int val)
@@ -201,6 +200,7 @@ struct it87_data {
 	u8 sensor;		/* Register value */
 	u8 fan_div[3];		/* Register encoding, shifted right */
 	u8 vid;			/* Register encoding, combined */
+	int vrm;
 	u32 alarms;		/* Register encoding, combined */
 };
 
@@ -543,6 +543,38 @@ static ssize_t show_alarms(struct device *dev, char *buf)
 }
 static DEVICE_ATTR(alarms, S_IRUGO | S_IWUSR, show_alarms, NULL);
 
+static ssize_t
+show_vrm_reg(struct device *dev, char *buf)
+{
+	struct it87_data *data = it87_update_device(dev);
+	return sprintf(buf, "%ld\n", (long) data->vrm);
+}
+static ssize_t
+store_vrm_reg(struct device *dev, const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct it87_data *data = i2c_get_clientdata(client);
+	u32 val;
+
+	val = simple_strtoul(buf, NULL, 10);
+	data->vrm = val;
+
+	return count;
+}
+static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
+#define device_create_file_vrm(client) \
+device_create_file(&client->dev, &dev_attr_vrm)
+
+static ssize_t
+show_vid_reg(struct device *dev, char *buf)
+{
+	struct it87_data *data = it87_update_device(dev);
+	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
+}
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
+#define device_create_file_vid(client) \
+device_create_file(&client->dev, &dev_attr_cpu0_vid)
+
 /* This function is called when:
      * it87_driver is inserted (when this module is loaded), for each
        available adapter
@@ -659,7 +691,11 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
 	if (kind <= 0) {
 		i = it87_read_value(new_client, IT87_REG_CHIPID);
 		if (i == 0x90) {
+			u16 val;
 			kind = it87;
+			val = (superio_inb(DEVID) << 8) |
+			superio_inb(DEVID + 1);
+			if (val == IT8712F_DEVID) kind = it8712;
 		}
 		else {
 			if (kind == 0)
@@ -674,6 +710,8 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
 
 	if (kind == it87) {
 		name = "it87";
+	} else if (kind == it8712) {
+		name = "it8712";
 	}
 
 	/* Fill in the remaining client fields and put it into the global list */
@@ -741,6 +779,12 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
 	device_create_file(&new_client->dev, &dev_attr_fan3_div);
 	device_create_file(&new_client->dev, &dev_attr_alarms);
 
+	if (data->type == it8712) {
+		device_create_file_vrm(new_client);
+		device_create_file_vid(new_client);
+		data->vrm = i2c_which_vrm();
+	}
+
 	return 0;
 
 ERROR2:
@@ -910,7 +954,11 @@ static struct it87_data *it87_update_device(struct device *dev)
 			(it87_read_value(client, IT87_REG_ALARM3) << 16);
 
 		data->sensor = it87_read_value(client, IT87_REG_TEMP_ENABLE);
-
+		/* The 8705 does not have VID capability */
+		if (data->type == it8712) {
+			data->vid = it87_read_value(client, IT87_REG_VID);
+			data->vid &= 0x1f;
+		}
 		data->last_updated = jiffies;
 		data->valid = 1;
 	}
@@ -938,9 +986,9 @@ static void __exit sm_it87_exit(void)
 
 MODULE_AUTHOR("Chris Gauthron <chrisg@0-in.com>");
 MODULE_DESCRIPTION("IT8705F, IT8712F, Sis950 driver");
-MODULE_PARM(update_vbat, "i");
+module_param(update_vbat, bool, 0);
 MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value");
-MODULE_PARM(reset, "i");
+module_param(reset, bool, 0);
 MODULE_PARM_DESC(reset, "Reset the chip's registers, default no");
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/i2c/chips/lm78.c b/drivers/i2c/chips/lm78.c
index 40385ffd8..b3cab5fa9 100644
--- a/drivers/i2c/chips/lm78.c
+++ b/drivers/i2c/chips/lm78.c
@@ -423,7 +423,7 @@ static ssize_t show_vid(struct device *dev, char *buf)
 	struct lm78_data *data = lm78_update_device(dev);
 	return sprintf(buf, "%d\n", VID_FROM_REG(data->vid));
 }
-static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid, NULL);
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
 
 /* Alarms */
 static ssize_t show_alarms(struct device *dev, char *buf)
@@ -615,7 +615,7 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
 	device_create_file(&new_client->dev, &dev_attr_fan3_min);
 	device_create_file(&new_client->dev, &dev_attr_fan3_div);
 	device_create_file(&new_client->dev, &dev_attr_alarms);
-	device_create_file(&new_client->dev, &dev_attr_in0_ref);
+	device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
 
 	return 0;
 
diff --git a/drivers/i2c/chips/lm83.c b/drivers/i2c/chips/lm83.c
index f6023e989..7e4cb6bd7 100644
--- a/drivers/i2c/chips/lm83.c
+++ b/drivers/i2c/chips/lm83.c
@@ -83,8 +83,10 @@ SENSORS_INSMOD_1(lm83);
  * The LM83 uses signed 8-bit values.
  */
 
-#define TEMP_FROM_REG(val)	((val > 127 ? val-256 : val) * 1000)
-#define TEMP_TO_REG(val)	((val < 0 ? val+256 : val) / 1000)
+#define TEMP_FROM_REG(val)	(((val) > 127 ? (val) - 0x100 : (val)) * 1000)
+#define TEMP_TO_REG(val)	((val) <= -50000 ? -50 + 0x100 : (val) >= 127000 ? 127 : \
+				 (val) > -500 ? ((val)+500) / 1000 : \
+				 ((val)-500) / 1000 + 0x100)
 
 static const u8 LM83_REG_R_TEMP[] = {
 	LM83_REG_R_LOCAL_TEMP,
@@ -178,7 +180,7 @@ static ssize_t set_temp_##suffix(struct device *dev, const char *buf, \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
 	struct lm83_data *data = i2c_get_clientdata(client); \
-	data->value = TEMP_TO_REG(simple_strtoul(buf, NULL, 10)); \
+	data->value = TEMP_TO_REG(simple_strtol(buf, NULL, 10)); \
 	i2c_smbus_write_byte_data(client, reg, data->value); \
 	return count; \
 }
@@ -206,8 +208,11 @@ static DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp_high3,
     set_temp_high3);
 static DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp_high4,
     set_temp_high4);
-static DEVICE_ATTR(temp_crit, S_IWUSR | S_IRUGO, show_temp_crit,
+static DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL);
+static DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit, NULL);
+static DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_temp_crit,
     set_temp_crit);
+static DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp_crit, NULL);
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
 /*
@@ -259,6 +264,11 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
 	 * means that the driver was loaded with the force parameter and a
 	 * given kind of chip is requested, so both the detection and the
 	 * identification steps are skipped. */
+
+	/* Default to an LM83 if forced */
+	if (kind == 0)
+		kind = lm83;
+
 	if (kind < 0) { /* detection */
 		if (((i2c_smbus_read_byte_data(new_client, LM83_REG_R_STATUS1)
 		    & 0xA8) != 0x00) ||
@@ -322,7 +332,10 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
 	device_create_file(&new_client->dev, &dev_attr_temp2_max);
 	device_create_file(&new_client->dev, &dev_attr_temp3_max);
 	device_create_file(&new_client->dev, &dev_attr_temp4_max);
-	device_create_file(&new_client->dev, &dev_attr_temp_crit);
+	device_create_file(&new_client->dev, &dev_attr_temp1_crit);
+	device_create_file(&new_client->dev, &dev_attr_temp2_crit);
+	device_create_file(&new_client->dev, &dev_attr_temp3_crit);
+	device_create_file(&new_client->dev, &dev_attr_temp4_crit);
 	device_create_file(&new_client->dev, &dev_attr_alarms);
 
 	return 0;
diff --git a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c
index 11f850431..757520f75 100644
--- a/drivers/i2c/chips/lm85.c
+++ b/drivers/i2c/chips/lm85.c
@@ -308,9 +308,6 @@ static int ZONE_TO_REG( int zone )
  * version of the driver.
  */
 
-/* Typically used with Pentium 4 systems v9.1 VRM spec */
-#define LM85_INIT_VRM  91
-
 /* Chip sampling rates
  *
  * Some sensors are not updated more frequently than once per second
@@ -468,7 +465,7 @@ static ssize_t show_vid_reg(struct device *dev, char *buf)
 	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
 }
 
-static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL);
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
 
 static ssize_t show_vrm_reg(struct device *dev, char *buf)
 {
@@ -832,7 +829,7 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
 		goto ERROR1;
 
 	/* Set the VRM version */
-	data->vrm = LM85_INIT_VRM ;
+	data->vrm = i2c_which_vrm();
 
 	/* Initialize the LM85 chip */
 	lm85_init_client(new_client);
@@ -877,7 +874,7 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
 	device_create_file(&new_client->dev, &dev_attr_temp2_max);
 	device_create_file(&new_client->dev, &dev_attr_temp3_max);
 	device_create_file(&new_client->dev, &dev_attr_vrm);
-	device_create_file(&new_client->dev, &dev_attr_in0_ref);
+	device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
 	device_create_file(&new_client->dev, &dev_attr_alarms);
 
 	return 0;
diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
index 87ad9b973..d63e06d37 100644
--- a/drivers/i2c/chips/pcf8591.c
+++ b/drivers/i2c/chips/pcf8591.c
@@ -36,7 +36,7 @@ static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
 SENSORS_INSMOD_1(pcf8591);
 
 static int input_mode;
-MODULE_PARM(input_mode, "i");
+module_param(input_mode, int, 0);
 MODULE_PARM_DESC(input_mode,
 	"Analog input mode:\n"
 	" 0 = four single ended inputs\n"
diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c
index 0fa55d45e..acfd3f804 100644
--- a/drivers/i2c/chips/rtc8564.c
+++ b/drivers/i2c/chips/rtc8564.c
@@ -56,8 +56,8 @@ static inline u8 _rtc8564_ctrl2(struct i2c_client *client)
 #define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
 #define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
 
-static int debug = 0;
-MODULE_PARM(debug, "i");
+static int debug;;
+module_param(debug, int, S_IRUGO | S_IWUSR);
 
 static struct i2c_driver rtc8564_driver;
 
diff --git a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c
index 3aa334583..851c5b260 100644
--- a/drivers/i2c/chips/via686a.c
+++ b/drivers/i2c/chips/via686a.c
@@ -43,8 +43,8 @@
 
 /* If force_addr is set to anything different from 0, we forcibly enable
    the device at the given address. */
-static int force_addr = 0;
-MODULE_PARM(force_addr, "i");
+static unsigned short force_addr = 0;
+module_param(force_addr, ushort, 0);
 MODULE_PARM_DESC(force_addr,
 		 "Initialize the base address of the sensors");
 
diff --git a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c
index 5d1a31bcb..5c3ade5b6 100644
--- a/drivers/i2c/chips/w83627hf.c
+++ b/drivers/i2c/chips/w83627hf.c
@@ -46,12 +46,12 @@
 #include <asm/io.h>
 #include "lm75.h"
 
-static int force_addr;
-MODULE_PARM(force_addr, "i");
+static u16 force_addr;
+module_param(force_addr, ushort, 0);
 MODULE_PARM_DESC(force_addr,
 		 "Initialize the base address of the sensors");
-static int force_i2c = 0x1f;
-MODULE_PARM(force_i2c, "i");
+static u8 force_i2c = 0x1f;
+module_param(force_i2c, byte, 0);
 MODULE_PARM_DESC(force_i2c,
 		 "Initialize the i2c address of the sensors");
 
@@ -65,7 +65,7 @@ static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
 SENSORS_INSMOD_4(w83627hf, w83627thf, w83697hf, w83637hf);
 
 static int init = 1;
-MODULE_PARM(init, "i");
+module_param(init, bool, 0);
 MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
 
 /* modified from kernel/include/traps.c */
@@ -635,9 +635,9 @@ show_vid_reg(struct device *dev, char *buf)
 	struct w83627hf_data *data = w83627hf_update_device(dev);
 	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
 }
-static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL);
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
 #define device_create_file_vid(client) \
-device_create_file(&client->dev, &dev_attr_in0_ref)
+device_create_file(&client->dev, &dev_attr_cpu0_vid)
 
 static ssize_t
 show_vrm_reg(struct device *dev, char *buf)
@@ -1281,7 +1281,7 @@ static void w83627hf_init_client(struct i2c_client *client)
 		data->vrm = (data->vrm_ovt & 0x01) ? 90 : 82;
 	} else {
 		/* Convert VID to voltage based on default VRM */
-		data->vrm = DEFAULT_VRM;
+		data->vrm = i2c_which_vrm();
 	}
 
 	tmp = w83627hf_read_value(client, W83781D_REG_SCFG1);
diff --git a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
index 785203d39..063d34a0d 100644
--- a/drivers/i2c/chips/w83781d.c
+++ b/drivers/i2c/chips/w83781d.c
@@ -60,7 +60,7 @@ I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
 		    "{bus, clientaddr, subclientaddr1, subclientaddr2}");
 
 static int init = 1;
-MODULE_PARM(init, "i");
+module_param(init, bool, 0);
 MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
 
 /* Constants specified below */
@@ -503,9 +503,9 @@ show_vid_reg(struct device *dev, char *buf)
 }
 
 static
-DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL);
+DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
 #define device_create_file_vid(client) \
-device_create_file(&client->dev, &dev_attr_in0_ref);
+device_create_file(&client->dev, &dev_attr_cpu0_vid);
 static ssize_t
 show_vrm_reg(struct device *dev, char *buf)
 {
@@ -815,8 +815,7 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr)
 		data->sens[nr - 1] = val;
 		break;
 	default:
-		dev_err(&client->dev,
-		       "Invalid sensor type %ld; must be 1, 2, or %d\n",
+		dev_err(dev, "Invalid sensor type %ld; must be 1, 2, or %d\n",
 		       (long) val, W83781D_DEFAULT_BETA);
 		break;
 	}
@@ -1513,7 +1512,7 @@ w83781d_init_client(struct i2c_client *client)
 		w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0);
 	}
 
-	data->vrm = 82;
+	data->vrm = i2c_which_vrm();
 
 	if ((type != w83781d) && (type != as99127f)) {
 		tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
@@ -1593,7 +1592,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
 	if (time_after
 	    (jiffies - data->last_updated, (unsigned long) (HZ + HZ / 2))
 	    || time_before(jiffies, data->last_updated) || !data->valid) {
-		pr_debug("Starting device update\n");
+		dev_dbg(dev, "Starting device update\n");
 
 		for (i = 0; i <= 8; i++) {
 			if ((data->type == w83783s || data->type == w83697hf)
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index f28496bd2..4305f7cc2 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -457,11 +457,6 @@ config IDEDMA_ONLYDISK
 
 	  Generally say N here.
 
-config BLK_DEV_ADMA
-	bool
-	depends on PCI && BLK_DEV_IDEPCI
-	default BLK_DEV_IDEDMA_PCI
-
 config BLK_DEV_AEC62XX
 	tristate "AEC62XX chipset support"
 	help
@@ -835,6 +830,13 @@ config BLK_DEV_IDE_RAPIDE
 	  Say Y here if you want to support the Yellowstone RapIDE controller
 	  manufactured for use with Acorn computers.
 
+config BLK_DEV_IDE_BAST
+	tristate "Simtec BAST / Thorcom VR1000 IDE support"
+	depends on ARM && (ARCH_BAST || MACH_VR100)
+	help
+	  Say Y here if you want to support the onboard IDE channels on the
+	  Simtec BAST or the Thorcom VR1000
+
 config BLK_DEV_GAYLE
 	bool "Amiga Gayle IDE interface support"
 	depends on AMIGA
diff --git a/drivers/ide/arm/Makefile b/drivers/ide/arm/Makefile
index ba897493d..6a78f0755 100644
--- a/drivers/ide/arm/Makefile
+++ b/drivers/ide/arm/Makefile
@@ -1,5 +1,6 @@
 
 obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)	+= icside.o
 obj-$(CONFIG_BLK_DEV_IDE_RAPIDE)	+= rapide.o
+obj-$(CONFIG_BLK_DEV_IDE_BAST)		+= bast-ide.o
 
 EXTRA_CFLAGS	:= -Idrivers/ide
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
index f40a61320..edc9de780 100644
--- a/drivers/ide/arm/icside.c
+++ b/drivers/ide/arm/icside.c
@@ -215,8 +215,6 @@ static void icside_build_sglist(ide_drive_t *drive, struct request *rq)
 	struct scatterlist *sg = hwif->sg_table;
 	int nents;
 
-	BUG_ON(hwif->sg_dma_active);
-
 	if (rq->flags & REQ_DRIVE_TASKFILE) {
 		ide_task_t *args = rq->special;
 
@@ -401,8 +399,6 @@ static int icside_dma_end(ide_drive_t *drive)
 	dma_unmap_sg(state->dev, hwif->sg_table, hwif->sg_nents,
 		     hwif->sg_dma_direction);
 
-	hwif->sg_dma_active = 0;
-
 	return get_dma_residue(hwif->hw.dma) != 0;
 }
 
@@ -454,7 +450,6 @@ icside_dma_common(ide_drive_t *drive, struct request *rq,
 	/*
 	 * We can not enable DMA on both channels.
 	 */
-	BUG_ON(hwif->sg_dma_active);
 	BUG_ON(dma_channel_active(hwif->hw.dma));
 
 	icside_build_sglist(drive, rq);
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index c3d6286eb..cc6b66e34 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -2719,8 +2719,10 @@ int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
 	if (!cdrom_get_media_event(cdi, &med)) {
 		if (med.media_present)
 			return CDS_DISC_OK;
-		if (med.door_open)
+		else if (med.door_open)
 			return CDS_TRAY_OPEN;
+		else
+			return CDS_NO_DISC;
 	}
 
 	if (sense.sense_key == NOT_READY && sense.asc == 0x04 && sense.ascq == 0x04)
@@ -2732,10 +2734,12 @@ int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
 	 * any other way to detect this...
 	 */
 	if (sense.sense_key == NOT_READY) {
-		if (sense.asc == 0x3a && sense.ascq == 1)
-			return CDS_NO_DISC;
-		else
-			return CDS_TRAY_OPEN;
+		if (sense.asc == 0x3a) {
+			if (sense.ascq == 0 || sense.ascq == 1)
+				return CDS_NO_DISC;
+			else if (sense.ascq == 2)
+				return CDS_TRAY_OPEN;
+		}
 	}
 
 	return CDS_DRIVE_NOT_READY;
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 7b3bf05cb..020bb4c11 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -340,12 +340,18 @@ static ide_startstop_t multwrite_intr (ide_drive_t *drive)
 ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
+	unsigned int dma	= drive->using_dma;
 	u8 lba48		= (drive->addressing == 1) ? 1 : 0;
 	task_ioreg_t command	= WIN_NOP;
 	ata_nsector_t		nsectors;
 
 	nsectors.all		= (u16) rq->nr_sectors;
 
+	if (hwif->no_lba48_dma && lba48 && dma) {
+		if (rq->sector + rq->nr_sectors > 1ULL << 28)
+			dma = 0;
+	}
+
 	if (IDE_CONTROL_REG)
 		hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
 
@@ -414,7 +420,7 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector
 	}
 
 	if (rq_data_dir(rq) == READ) {
-		if (drive->using_dma && !hwif->ide_dma_read(drive))
+		if (dma && !hwif->ide_dma_read(drive))
 			return ide_started;
 
 		command = ((drive->mult_count) ?
@@ -425,7 +431,7 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector
 	} else {
 		ide_startstop_t startstop;
 
-		if (drive->using_dma && !(HWIF(drive)->ide_dma_write(drive)))
+		if (dma && !hwif->ide_dma_write(drive))
 			return ide_started;
 
 		command = ((drive->mult_count) ?
@@ -488,31 +494,38 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector
 }
 EXPORT_SYMBOL_GPL(__ide_do_rw_disk);
 
-static u8 get_command(ide_drive_t *drive, int cmd, ide_task_t *task)
+static u8 get_command(ide_drive_t *drive, struct request *rq, ide_task_t *task)
 {
 	unsigned int lba48 = (drive->addressing == 1) ? 1 : 0;
+	unsigned int dma = drive->using_dma;
+
+	if (drive->hwif->no_lba48_dma && lba48 && dma) {
+		if (rq->sector + rq->nr_sectors > 1ULL << 28)
+			dma = 0;
+	}
 
-	if (cmd == READ) {
+	if (rq_data_dir(rq) == READ) {
 		task->command_type = IDE_DRIVE_TASK_IN;
-		if (drive->using_dma)
+		if (dma)
 			return lba48 ? WIN_READDMA_EXT : WIN_READDMA;
+		task->handler = &task_in_intr;
 		if (drive->mult_count) {
-			task->handler = &task_mulin_intr;
+			task->data_phase = TASKFILE_MULTI_IN;
 			return lba48 ? WIN_MULTREAD_EXT : WIN_MULTREAD;
 		}
-		task->handler = &task_in_intr;
+		task->data_phase = TASKFILE_IN;
 		return lba48 ? WIN_READ_EXT : WIN_READ;
 	} else {
 		task->command_type = IDE_DRIVE_TASK_RAW_WRITE;
-		if (drive->using_dma)
+		if (dma)
 			return lba48 ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
+		task->prehandler = &pre_task_out_intr;
+		task->handler = &task_out_intr;
 		if (drive->mult_count) {
-			task->prehandler = &pre_task_mulout_intr;
-			task->handler = &task_mulout_intr;
+			task->data_phase = TASKFILE_MULTI_OUT;
 			return lba48 ? WIN_MULTWRITE_EXT : WIN_MULTWRITE;
 		}
-		task->prehandler = &pre_task_out_intr;
-		task->handler = &task_out_intr;
+		task->data_phase = TASKFILE_OUT;
 		return lba48 ? WIN_WRITE_EXT : WIN_WRITE;
 	}
 }
@@ -541,9 +554,10 @@ static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsi
 	args.tfRegister[IDE_HCYL_OFFSET]	= (cyl>>8);
 	args.tfRegister[IDE_SELECT_OFFSET]	= head;
 	args.tfRegister[IDE_SELECT_OFFSET]	|= drive->select.all;
-	args.tfRegister[IDE_COMMAND_OFFSET]	= get_command(drive, rq_data_dir(rq), &args);
+	args.tfRegister[IDE_COMMAND_OFFSET]	= get_command(drive, rq, &args);
 	args.rq					= (struct request *) rq;
 	rq->special				= (ide_task_t *)&args;
+	drive->hwif->data_phase = args.data_phase;
 	return do_rw_taskfile(drive, &args);
 }
 
@@ -565,9 +579,10 @@ static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, u
 	args.tfRegister[IDE_HCYL_OFFSET]	= (block>>=8);
 	args.tfRegister[IDE_SELECT_OFFSET]	= ((block>>8)&0x0f);
 	args.tfRegister[IDE_SELECT_OFFSET]	|= drive->select.all;
-	args.tfRegister[IDE_COMMAND_OFFSET]	= get_command(drive, rq_data_dir(rq), &args);
+	args.tfRegister[IDE_COMMAND_OFFSET]	= get_command(drive, rq, &args);
 	args.rq					= (struct request *) rq;
 	rq->special				= (ide_task_t *)&args;
+	drive->hwif->data_phase = args.data_phase;
 	return do_rw_taskfile(drive, &args);
 }
 
@@ -595,7 +610,7 @@ static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, u
 	args.tfRegister[IDE_LCYL_OFFSET]	= (block>>=8);	/* mid lba */
 	args.tfRegister[IDE_HCYL_OFFSET]	= (block>>=8);	/* hi  lba */
 	args.tfRegister[IDE_SELECT_OFFSET]	= drive->select.all;
-	args.tfRegister[IDE_COMMAND_OFFSET]	= get_command(drive, rq_data_dir(rq), &args);
+	args.tfRegister[IDE_COMMAND_OFFSET]	= get_command(drive, rq, &args);
 	args.hobRegister[IDE_SECTOR_OFFSET]	= (block>>=8);	/* low lba */
 	args.hobRegister[IDE_LCYL_OFFSET]	= (block>>=8);	/* mid lba */
 	args.hobRegister[IDE_HCYL_OFFSET]	= (block>>=8);	/* hi  lba */
@@ -603,6 +618,7 @@ static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, u
 	args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80);
 	args.rq					= (struct request *) rq;
 	rq->special				= (ide_task_t *)&args;
+	drive->hwif->data_phase = args.data_phase;
 	return do_rw_taskfile(drive, &args);
 }
 
@@ -638,7 +654,6 @@ static u8 idedisk_dump_status (ide_drive_t *drive, const char *msg, u8 stat)
 
 	local_irq_set(flags);
 	printk("%s: %s: status=0x%02x", drive->name, msg, stat);
-#if FANCY_STATUS_DUMPS
 	printk(" { ");
 	if (stat & BUSY_STAT)
 		printk("Busy ");
@@ -652,12 +667,10 @@ static u8 idedisk_dump_status (ide_drive_t *drive, const char *msg, u8 stat)
 		if (stat & ERR_STAT)	printk("Error ");
 	}
 	printk("}");
-#endif	/* FANCY_STATUS_DUMPS */
 	printk("\n");
 	if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
 		err = hwif->INB(IDE_ERROR_REG);
 		printk("%s: %s: error=0x%02x", drive->name, msg, err);
-#if FANCY_STATUS_DUMPS
 		printk(" { ");
 		if (err & ABRT_ERR)	printk("DriveStatusError ");
 		if (err & ICRC_ERR)
@@ -700,8 +713,38 @@ static u8 idedisk_dump_status (ide_drive_t *drive, const char *msg, u8 stat)
 					(unsigned long long)HWGROUP(drive)->rq->sector);
 		}
 	}
-#endif	/* FANCY_STATUS_DUMPS */
 	printk("\n");
+	{
+		struct request *rq;
+		unsigned char opcode = 0;
+		int found = 0;
+
+		spin_lock(&ide_lock);
+		rq = HWGROUP(drive)->rq;
+		spin_unlock(&ide_lock);
+		if (!rq)
+			goto out;
+		if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
+			char *args = rq->buffer;
+			if (args) {
+				opcode = args[0];
+				found = 1;
+			}
+		} else if (rq->flags & REQ_DRIVE_TASKFILE) {
+			ide_task_t *args = rq->special;
+			if (args) {
+				task_struct_t *tf = (task_struct_t *) args->tfRegister;
+				opcode = tf->command;
+				found = 1;
+			}
+		}
+		printk("ide: failed opcode was: ");
+		if (!found)
+			printk("unknown\n");
+		else
+			printk("0x%02x\n", opcode);
+	}
+out:
 	local_irq_restore(flags);
 	return err;
 }
@@ -1117,6 +1160,7 @@ static int get_smart_values(ide_drive_t *drive, u8 *buf)
 	args.tfRegister[IDE_HCYL_OFFSET]	= SMART_HCYL_PASS;
 	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SMART;
 	args.command_type			= IDE_DRIVE_TASK_IN;
+	args.data_phase				= TASKFILE_IN;
 	args.handler				= &task_in_intr;
 	(void) smart_enable(drive);
 	return ide_raw_taskfile(drive, &args, buf);
@@ -1203,6 +1247,42 @@ static ide_proc_entry_t idedisk_proc[] = {
 
 #endif	/* CONFIG_PROC_FS */
 
+static int idedisk_issue_flush(request_queue_t *q, struct gendisk *disk,
+			       sector_t *error_sector)
+{
+	ide_drive_t *drive = q->queuedata;
+	struct request *rq;
+	int ret;
+
+	if (!drive->wcache)
+		return 0;
+
+	rq = blk_get_request(q, WRITE, __GFP_WAIT);
+
+	memset(rq->cmd, 0, sizeof(rq->cmd));
+
+	if (ide_id_has_flush_cache_ext(drive->id) &&
+	    (drive->capacity64 >= (1UL << 28)))
+		rq->cmd[0] = WIN_FLUSH_CACHE_EXT;
+	else
+		rq->cmd[0] = WIN_FLUSH_CACHE;
+
+
+	rq->flags |= REQ_DRIVE_TASK | REQ_SOFTBARRIER;
+	rq->buffer = rq->cmd;
+
+	ret = blk_execute_rq(q, disk, rq);
+
+	/*
+	 * if we failed and caller wants error offset, get it
+	 */
+	if (ret && error_sector)
+		*error_sector = ide_get_error_location(drive, rq->cmd);
+
+	blk_put_request(rq);
+	return ret;
+}
+
 /*
  * This is tightly woven into the driver->do_special can not touch.
  * DON'T do it again until a total personality rewrite is committed.
@@ -1231,16 +1311,10 @@ static int set_nowerr(ide_drive_t *drive, int arg)
 	return 0;
 }
 
-/* check if CACHE FLUSH (EXT) command is supported (bits defined in ATA-6) */
-#define ide_id_has_flush_cache(id)	((id)->cfs_enable_2 & 0x3000)
-
-/* some Maxtor disks have bit 13 defined incorrectly so check bit 10 too */
-#define ide_id_has_flush_cache_ext(id)	\
-	(((id)->cfs_enable_2 & 0x2400) == 0x2400)
-
-static int write_cache (ide_drive_t *drive, int arg)
+static int write_cache(ide_drive_t *drive, int arg)
 {
 	ide_task_t args;
+	int err;
 
 	if (!ide_id_has_flush_cache(drive->id))
 		return 1;
@@ -1251,7 +1325,10 @@ static int write_cache (ide_drive_t *drive, int arg)
 	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SETFEATURES;
 	args.command_type			= IDE_DRIVE_TASK_NO_DATA;
 	args.handler				= &task_no_data_intr;
-	(void) ide_raw_taskfile(drive, &args, NULL);
+
+	err = ide_raw_taskfile(drive, &args, NULL);
+	if (err)
+		return err;
 
 	drive->wcache = arg;
 	return 0;
@@ -1412,6 +1489,7 @@ static void idedisk_setup (ide_drive_t *drive)
 {
 	struct hd_driveid *id = drive->id;
 	unsigned long long capacity;
+	int barrier;
 
 	idedisk_add_settings(drive);
 
@@ -1443,7 +1521,7 @@ static void idedisk_setup (ide_drive_t *drive)
 		blk_queue_max_sectors(drive->queue, max_s);
 	}
 
-	printk("%s: max request size: %dKiB\n", drive->name, drive->queue->max_sectors / 2);
+	printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name, drive->queue->max_sectors / 2);
 
 	/* Extract geometry if we did not already have one for the drive */
 	if (!drive->cyl || !drive->head || !drive->sect) {
@@ -1472,13 +1550,22 @@ static void idedisk_setup (ide_drive_t *drive)
 
 	/* limit drive capacity to 137GB if LBA48 cannot be used */
 	if (drive->addressing == 0 && drive->capacity64 > 1ULL << 28) {
-		printk("%s: cannot use LBA48 - full capacity "
+		printk(KERN_WARNING "%s: cannot use LBA48 - full capacity "
 		       "%llu sectors (%llu MB)\n",
 		       drive->name, (unsigned long long)drive->capacity64,
 		       sectors_to_MB(drive->capacity64));
 		drive->capacity64 = 1ULL << 28;
 	}
 
+	if (drive->hwif->no_lba48_dma && drive->addressing) {
+		if (drive->capacity64 > 1ULL << 28) {
+			printk(KERN_INFO "%s: cannot use LBA48 DMA - PIO mode will"
+					 " be used for accessing sectors > %u\n",
+					 drive->name, 1 << 28);
+		} else
+			drive->addressing = 0;
+	}
+
 	/*
 	 * if possible, give fdisk access to more of the drive,
 	 * by correcting bios_cyls:
@@ -1543,6 +1630,29 @@ static void idedisk_setup (ide_drive_t *drive)
 		drive->wcache = 1;
 
 	write_cache(drive, 1);
+
+	/*
+	 * We must avoid issuing commands a drive does not understand
+	 * or we may crash it. We check flush cache is supported. We also
+	 * check we have the LBA48 flush cache if the drive capacity is
+	 * too large. By this time we have trimmed the drive capacity if
+	 * LBA48 is not available so we don't need to recheck that.
+	 */
+	barrier = 0;
+	if (ide_id_has_flush_cache(id))
+		barrier = 1;
+	if (drive->addressing == 1) {
+		/* Can't issue the correct flush ? */
+		if (capacity > (1ULL << 28) && !ide_id_has_flush_cache_ext(id))
+			barrier = 0;
+	}
+
+	printk(KERN_DEBUG "%s: cache flushes %ssupported\n",
+		drive->name, barrier ? "" : "not ");
+	if (barrier) {
+		blk_queue_ordered(drive->queue, 1);
+		blk_queue_issue_flush_fn(drive->queue, idedisk_issue_flush);
+	}
 }
 
 static void ide_cacheflush_p(ide_drive_t *drive)
@@ -1723,11 +1833,9 @@ static int idedisk_attach(ide_drive_t *drive)
 	if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
 		printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
 			drive->name, drive->head);
-		ide_cacheflush_p(drive);
-		ide_unregister_subdriver(drive);
-		DRIVER(drive)->busy--;
-		goto failed;
-	}
+		drive->attach = 0;
+	} else
+		drive->attach = 1;
 	DRIVER(drive)->busy--;
 	g->minors = 1 << PARTN_BITS;
 	strcpy(g->devfs_name, drive->devfs_name);
@@ -1735,7 +1843,6 @@ static int idedisk_attach(ide_drive_t *drive)
 	g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;
 	set_capacity(g, current_capacity(drive));
 	g->fops = &idedisk_ops;
-	drive->attach = 1;
 	add_disk(g);
 	return 0;
 failed:
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 6ed4de8a5..cd32057b5 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -208,9 +208,6 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq)
 	struct scatterlist *sg = hwif->sg_table;
 	int nents;
 
-	if (hwif->sg_dma_active)
-		BUG();
-
 	nents = blk_rq_map_sg(drive->queue, rq, hwif->sg_table);
 		
 	if (rq_data_dir(rq) == READ)
@@ -366,7 +363,6 @@ use_pio_instead:
 		     hwif->sg_table,
 		     hwif->sg_nents,
 		     hwif->sg_dma_direction);
-	hwif->sg_dma_active = 0;
 	return 0; /* revert to PIO for this request */
 }
 
@@ -390,7 +386,6 @@ void ide_destroy_dmatable (ide_drive_t *drive)
 	int nents = HWIF(drive)->sg_nents;
 
 	pci_unmap_sg(dev, sg, nents, HWIF(drive)->sg_dma_direction);
-	HWIF(drive)->sg_dma_active = 0;
 }
 
 EXPORT_SYMBOL_GPL(ide_destroy_dmatable);
@@ -412,10 +407,6 @@ static int config_drive_for_dma (ide_drive_t *drive)
 	ide_hwif_t *hwif = HWIF(drive);
 
 	if ((id->capability & 1) && hwif->autodma) {
-		/* Consult the list of known "bad" drives */
-		if (__ide_dma_bad_drive(drive))
-			return __ide_dma_off(drive);
-
 		/*
 		 * Enable DMA on any drive that has
 		 * UltraDMA (mode 0/1/2/3/4/5/6) enabled
@@ -569,6 +560,10 @@ EXPORT_SYMBOL(__ide_dma_host_on);
  
 int __ide_dma_on (ide_drive_t *drive)
 {
+	/* consult the list of known "bad" drives */
+	if (__ide_dma_bad_drive(drive))
+		return 1;
+
 	drive->using_dma = 1;
 	ide_toggle_bounce(drive, 1);
 
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index ff5b16a87..d20cd1eb5 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -54,38 +54,77 @@
 #include <asm/io.h>
 #include <asm/bitops.h>
 
-/**
- *	ide_end_request		-	complete an IDE I/O
- *	@drive: IDE device for the I/O
- *	@uptodate: 
- *	@nr_sectors: number of sectors completed
- *
- *	This is our end_request wrapper function. We complete the I/O
- *	update random number input and dequeue the request, which if
- *	it was tagged may be out of order.
+static void ide_fill_flush_cmd(ide_drive_t *drive, struct request *rq)
+{
+	char *buf = rq->cmd;
+
+	/*
+	 * reuse cdb space for ata command
+	 */
+	memset(buf, 0, sizeof(rq->cmd));
+
+	rq->flags |= REQ_DRIVE_TASK | REQ_STARTED;
+	rq->buffer = buf;
+	rq->buffer[0] = WIN_FLUSH_CACHE;
+
+	if (ide_id_has_flush_cache_ext(drive->id) &&
+	    (drive->capacity64 >= (1UL << 28)))
+		rq->buffer[0] = WIN_FLUSH_CACHE_EXT;
+}
+
+/*
+ * preempt pending requests, and store this cache flush for immediate
+ * execution
  */
- 
-int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
+static struct request *ide_queue_flush_cmd(ide_drive_t *drive,
+					   struct request *rq, int post)
 {
-	struct request *rq;
-	unsigned long flags;
-	int ret = 1;
+	struct request *flush_rq = &HWGROUP(drive)->wrq;
 
-	spin_lock_irqsave(&ide_lock, flags);
-	rq = HWGROUP(drive)->rq;
+	/*
+	 * write cache disabled, clear the barrier bit and treat it like
+	 * an ordinary write
+	 */
+	if (!drive->wcache) {
+		rq->flags |= REQ_BAR_PREFLUSH;
+		return rq;
+	}
 
-	BUG_ON(!(rq->flags & REQ_STARTED));
+	ide_init_drive_cmd(flush_rq);
+	ide_fill_flush_cmd(drive, flush_rq);
 
-	if (!nr_sectors)
-		nr_sectors = rq->hard_cur_sectors;
+	flush_rq->special = rq;
+	flush_rq->nr_sectors = rq->nr_sectors;
+
+	if (!post) {
+		drive->doing_barrier = 1;
+		flush_rq->flags |= REQ_BAR_PREFLUSH;
+		blkdev_dequeue_request(rq);
+	} else
+		flush_rq->flags |= REQ_BAR_POSTFLUSH;
+
+	__elv_add_request(drive->queue, flush_rq, ELEVATOR_INSERT_FRONT, 0);
+	HWGROUP(drive)->rq = NULL;
+	return flush_rq;
+}
+
+static int __ide_end_request(ide_drive_t *drive, struct request *rq,
+			     int uptodate, int nr_sectors)
+{
+	int ret = 1;
+
+	BUG_ON(!(rq->flags & REQ_STARTED));
 
 	/*
 	 * if failfast is set on a request, override number of sectors and
 	 * complete the whole request right now
 	 */
-	if (blk_noretry_request(rq) && !uptodate)
+	if (blk_noretry_request(rq) && end_io_error(uptodate))
 		nr_sectors = rq->hard_nr_sectors;
 
+	if (!blk_fs_request(rq) && end_io_error(uptodate) && !rq->errors)
+		rq->errors = -EIO;
+
 	/*
 	 * decide whether to reenable DMA -- 3 is a random magic for now,
 	 * if we DMA timeout more than 3 times, just stay in PIO
@@ -97,15 +136,56 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
 
 	if (!end_that_request_first(rq, uptodate, nr_sectors)) {
 		add_disk_randomness(rq->rq_disk);
+
+		if (blk_rq_tagged(rq))
+			blk_queue_end_tag(drive->queue, rq);
+
 		blkdev_dequeue_request(rq);
 		HWGROUP(drive)->rq = NULL;
 		end_that_request_last(rq);
 		ret = 0;
 	}
-	spin_unlock_irqrestore(&ide_lock, flags);
 	return ret;
 }
 
+/**
+ *	ide_end_request		-	complete an IDE I/O
+ *	@drive: IDE device for the I/O
+ *	@uptodate:
+ *	@nr_sectors: number of sectors completed
+ *
+ *	This is our end_request wrapper function. We complete the I/O
+ *	update random number input and dequeue the request, which if
+ *	it was tagged may be out of order.
+ */
+
+int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors)
+{
+	struct request *rq;
+	unsigned long flags;
+	int ret = 1;
+
+	spin_lock_irqsave(&ide_lock, flags);
+	rq = HWGROUP(drive)->rq;
+
+	if (!nr_sectors)
+		nr_sectors = rq->hard_cur_sectors;
+
+	if (!blk_barrier_rq(rq) || !drive->wcache)
+		ret = __ide_end_request(drive, rq, uptodate, nr_sectors);
+	else {
+		struct request *flush_rq = &HWGROUP(drive)->wrq;
+
+		flush_rq->nr_sectors -= nr_sectors;
+		if (!flush_rq->nr_sectors) {
+			ide_queue_flush_cmd(drive, rq, 1);
+			ret = 0;
+		}
+	}
+
+	spin_unlock_irqrestore(&ide_lock, flags);
+	return ret;
+}
 EXPORT_SYMBOL(ide_end_request);
 
 /**
@@ -137,6 +217,113 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
 	spin_unlock_irqrestore(&ide_lock, flags);
 }
 
+/*
+ * FIXME: probably move this somewhere else, name is bad too :)
+ */
+u64 ide_get_error_location(ide_drive_t *drive, char *args)
+{
+	u32 high, low;
+	u8 hcyl, lcyl, sect;
+	u64 sector;
+
+	high = 0;
+	hcyl = args[5];
+	lcyl = args[4];
+	sect = args[3];
+
+	if (ide_id_has_flush_cache_ext(drive->id)) {
+		low = (hcyl << 16) | (lcyl << 8) | sect;
+		HWIF(drive)->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
+		high = ide_read_24(drive);
+	} else {
+		u8 cur = HWIF(drive)->INB(IDE_SELECT_REG);
+		if (cur & 0x40)
+			low = (hcyl << 16) | (lcyl << 8) | sect;
+		else {
+			low = hcyl * drive->head * drive->sect;
+			low += lcyl * drive->sect;
+			low += sect - 1;
+		}
+	}
+
+	sector = ((u64) high << 24) | low;
+	return sector;
+}
+EXPORT_SYMBOL(ide_get_error_location);
+
+static void ide_complete_barrier(ide_drive_t *drive, struct request *rq,
+				 int error)
+{
+	struct request *real_rq = rq->special;
+	int good_sectors, bad_sectors;
+	sector_t sector;
+
+	if (!error) {
+		if (blk_barrier_postflush(rq)) {
+			/*
+			 * this completes the barrier write
+			 */
+			__ide_end_request(drive, real_rq, 1, real_rq->hard_nr_sectors);
+			drive->doing_barrier = 0;
+		} else {
+			/*
+			 * just indicate that we did the pre flush
+			 */
+			real_rq->flags |= REQ_BAR_PREFLUSH;
+			elv_requeue_request(drive->queue, real_rq);
+		}
+		/*
+		 * all is fine, return
+		 */
+		return;
+	}
+
+	/*
+	 * we need to end real_rq, but it's not on the queue currently.
+	 * put it back on the queue, so we don't have to special case
+	 * anything else for completing it
+	 */
+	if (!blk_barrier_postflush(rq))
+		elv_requeue_request(drive->queue, real_rq);
+
+	/*
+	 * drive aborted flush command, assume FLUSH_CACHE_* doesn't
+	 * work and disable barrier support
+	 */
+	if (error & ABRT_ERR) {
+		printk(KERN_ERR "%s: barrier support doesn't work\n", drive->name);
+		__ide_end_request(drive, real_rq, -EOPNOTSUPP, real_rq->hard_nr_sectors);
+		blk_queue_ordered(drive->queue, 0);
+		blk_queue_issue_flush_fn(drive->queue, NULL);
+	} else {
+		/*
+		 * find out what part of the request failed
+		 */
+		good_sectors = 0;
+		if (blk_barrier_postflush(rq)) {
+			sector = ide_get_error_location(drive, rq->buffer);
+
+			if ((sector >= real_rq->hard_sector) &&
+			    (sector < real_rq->hard_sector + real_rq->hard_nr_sectors))
+				good_sectors = sector - real_rq->hard_sector;
+		} else
+			sector = real_rq->hard_sector;
+
+		bad_sectors = real_rq->hard_nr_sectors - good_sectors;
+		if (good_sectors)
+			__ide_end_request(drive, real_rq, 1, good_sectors);
+		if (bad_sectors)
+			__ide_end_request(drive, real_rq, 0, bad_sectors);
+
+		printk(KERN_ERR "%s: failed barrier write: "
+				"sector=%Lx(good=%d/bad=%d)\n",
+				drive->name, (unsigned long long)sector,
+				good_sectors, bad_sectors);
+	}
+
+	drive->doing_barrier = 0;
+}
+
 /**
  *	ide_end_drive_cmd	-	end an explicit drive command
  *	@drive: command 
@@ -197,6 +384,8 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
 				args->hobRegister[IDE_DATA_OFFSET]	= (data >> 8) & 0xFF;
 			}
 			args->tfRegister[IDE_ERROR_OFFSET]   = err;
+			/* be sure we're looking at the low order bits */
+			hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
 			args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG);
 			args->tfRegister[IDE_SECTOR_OFFSET]  = hwif->INB(IDE_SECTOR_REG);
 			args->tfRegister[IDE_LCYL_OFFSET]    = hwif->INB(IDE_LCYL_REG);
@@ -226,6 +415,10 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
 
 	spin_lock_irqsave(&ide_lock, flags);
 	blkdev_dequeue_request(rq);
+
+	if (blk_barrier_preflush(rq) || blk_barrier_postflush(rq))
+		ide_complete_barrier(drive, rq, err);
+
 	HWGROUP(drive)->rq = NULL;
 	end_that_request_last(rq);
 	spin_unlock_irqrestore(&ide_lock, flags);
@@ -501,7 +694,9 @@ ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq)
  
 		if (!args)
 			goto done;
- 
+
+		hwif->data_phase = args->data_phase;
+
 		if (args->tf_out_flags.all != 0) 
 			return flagged_taskfile(drive, args);
 		return do_rw_taskfile(drive, args);
@@ -712,6 +907,22 @@ static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup)
 repeat:	
 	best = NULL;
 	drive = hwgroup->drive;
+
+	/*
+	 * drive is doing pre-flush, ordered write, post-flush sequence. even
+	 * though that is 3 requests, it must be seen as a single transaction.
+	 * we must not preempt this drive until that is complete
+	 */
+	if (drive->doing_barrier) {
+		/*
+		 * small race where queue could get replugged during
+		 * the 3-request flush cycle, just yank the plug since
+		 * we want it to finish asap
+		 */
+		blk_remove_plug(drive->queue);
+		return drive;
+	}
+
 	do {
 		if ((!drive->sleep || time_after_eq(jiffies, drive->sleep))
 		    && !elv_queue_empty(drive->queue)) {
@@ -867,6 +1078,13 @@ void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
 			break;
 		}
 
+		/*
+		 * if rq is a barrier write, issue pre cache flush if not
+		 * already done
+		 */
+		if (blk_barrier_rq(rq) && !blk_barrier_preflush(rq))
+			rq = ide_queue_flush_cmd(drive, rq, 0);
+
 		/*
 		 * Sanity: don't accept a request that isn't a PM request
 		 * if we are currently power managed. This is very important as
@@ -917,7 +1135,9 @@ EXPORT_SYMBOL(ide_do_request);
  */
 void do_ide_request(request_queue_t *q)
 {
-	ide_do_request(q->queuedata, IDE_NO_IRQ);
+	ide_drive_t *drive = q->queuedata;
+
+	ide_do_request(HWGROUP(drive), IDE_NO_IRQ);
 }
 
 /*
@@ -1286,6 +1506,7 @@ void ide_init_drive_cmd (struct request *rq)
 {
 	memset(rq, 0, sizeof(*rq));
 	rq->flags = REQ_DRIVE_CMD;
+	rq->ref_count = 1;
 }
 
 EXPORT_SYMBOL(ide_init_drive_cmd);
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index b7c47d235..c104120ae 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -112,57 +112,57 @@ EXPORT_SYMBOL(default_hwif_iops);
 
 static u8 ide_mm_inb (unsigned long port)
 {
-	return (u8) readb(port);
+	return (u8) readb((void __iomem *) port);
 }
 
 static u16 ide_mm_inw (unsigned long port)
 {
-	return (u16) readw(port);
+	return (u16) readw((void __iomem *) port);
 }
 
 static void ide_mm_insw (unsigned long port, void *addr, u32 count)
 {
-	__ide_mm_insw(port, addr, count);
+	__ide_mm_insw((void __iomem *) port, addr, count);
 }
 
 static u32 ide_mm_inl (unsigned long port)
 {
-	return (u32) readl(port);
+	return (u32) readl((void __iomem *) port);
 }
 
 static void ide_mm_insl (unsigned long port, void *addr, u32 count)
 {
-	__ide_mm_insl(port, addr, count);
+	__ide_mm_insl((void __iomem *) port, addr, count);
 }
 
 static void ide_mm_outb (u8 value, unsigned long port)
 {
-	writeb(value, port);
+	writeb(value, (void __iomem *) port);
 }
 
 static void ide_mm_outbsync (ide_drive_t *drive, u8 value, unsigned long port)
 {
-	writeb(value, port);	
+	writeb(value, (void __iomem *) port);
 }
 
 static void ide_mm_outw (u16 value, unsigned long port)
 {
-	writew(value, port);
+	writew(value, (void __iomem *) port);
 }
 
 static void ide_mm_outsw (unsigned long port, void *addr, u32 count)
 {
-	__ide_mm_outsw(port, addr, count);
+	__ide_mm_outsw((void __iomem *) port, addr, count);
 }
 
 static void ide_mm_outl (u32 value, unsigned long port)
 {
-	writel(value, port);
+	writel(value, (void __iomem *) port);
 }
 
 static void ide_mm_outsl (unsigned long port, void *addr, u32 count)
 {
-	__ide_mm_outsl(port, addr, count);
+	__ide_mm_outsl((void __iomem *) port, addr, count);
 }
 
 void default_hwif_mmiops (ide_hwif_t *hwif)
@@ -1096,7 +1096,6 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
 			drive->failures = 0;
 		} else {
 			drive->failures++;
-#if FANCY_STATUS_DUMPS
 			printk("master: ");
 			switch (tmp & 0x7f) {
 				case 1: printk("passed");
@@ -1114,9 +1113,6 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
 			if (tmp & 0x80)
 				printk("; slave: failed");
 			printk("\n");
-#else
-			printk("failed\n");
-#endif /* FANCY_STATUS_DUMPS */
 		}
 	}
 	hwgroup->poll_timeout = 0;	/* done polling */
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index 073c3fb82..b2fa5eccd 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -465,7 +465,6 @@ byte ide_dump_atapi_status (ide_drive_t *drive, const char *msg, byte stat)
 	status.all = stat;
 	local_irq_set(flags);
 	printk("%s: %s: status=0x%02x", drive->name, msg, stat);
-#if FANCY_STATUS_DUMPS
 	printk(" { ");
 	if (status.b.bsy)
 		printk("Busy ");
@@ -479,19 +478,16 @@ byte ide_dump_atapi_status (ide_drive_t *drive, const char *msg, byte stat)
 		if (status.b.check)	printk("Error ");
 	}
 	printk("}");
-#endif	/* FANCY_STATUS_DUMPS */
 	printk("\n");
 	if ((status.all & (status.b.bsy|status.b.check)) == status.b.check) {
 		error.all = HWIF(drive)->INB(IDE_ERROR_REG);
 		printk("%s: %s: error=0x%02x", drive->name, msg, error.all);
-#if FANCY_STATUS_DUMPS
 		if (error.b.ili)	printk("IllegalLengthIndication ");
 		if (error.b.eom)	printk("EndOfMedia ");
 		if (error.b.abrt)	printk("Aborted Command ");
 		if (error.b.mcr)	printk("MediaChangeRequested ");
 		if (error.b.sense_key)	printk("LastFailedSense 0x%02x ",
 						error.b.sense_key);
-#endif	/* FANCY_STATUS_DUMPS */
 		printk("\n");
 	}
 	local_irq_restore(flags);
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 4ffaf9016..61c72a700 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -389,15 +389,6 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
 				 */
 				printk("%s: IRQ probe failed (0x%lx)\n",
 					drive->name, cookie);
-#ifdef CONFIG_BLK_DEV_CMD640
-#ifdef CMD640_DUMP_REGS
-				if (hwif->chipset == ide_cmd640) {
-					printk("%s: Hmmm.. probably a driver "
-						"problem.\n", drive->name);
-					CMD640_DUMP_REGS;
-				}
-#endif /* CMD640_DUMP_REGS */
-#endif /* CONFIG_BLK_DEV_CMD640 */
 			}
 		}
 	}
@@ -635,12 +626,11 @@ static void hwif_register (ide_hwif_t *hwif)
 	device_register(&hwif->gendev);
 }
 
-#ifdef CONFIG_PPC
 static int wait_hwif_ready(ide_hwif_t *hwif)
 {
 	int rc;
 
-	printk(KERN_INFO "Probing IDE interface %s...\n", hwif->name);
+	printk(KERN_DEBUG "Probing IDE interface %s...\n", hwif->name);
 
 	/* Let HW settle down a bit from whatever init state we
 	 * come from */
@@ -671,7 +661,6 @@ static int wait_hwif_ready(ide_hwif_t *hwif)
 	
 	return rc;
 }
-#endif
 
 /*
  * This routine only knows how to look for drive units 0 and 1
@@ -717,7 +706,6 @@ static void probe_hwif(ide_hwif_t *hwif)
 
 	local_irq_set(flags);
 
-#ifdef CONFIG_PPC
 	/* This is needed on some PPCs and a bunch of BIOS-less embedded
 	 * platforms. Typical cases are:
 	 * 
@@ -738,8 +726,7 @@ static void probe_hwif(ide_hwif_t *hwif)
 	 *  BenH.
 	 */
 	if (wait_hwif_ready(hwif))
-		printk(KERN_WARNING "%s: Wait for ready failed before probe !\n", hwif->name);
-#endif /* CONFIG_PPC */
+		printk(KERN_DEBUG "%s: Wait for ready failed before probe !\n", hwif->name);
 
 	/*
 	 * Second drive should only exist if first drive was found,
@@ -749,6 +736,18 @@ static void probe_hwif(ide_hwif_t *hwif)
 		ide_drive_t *drive = &hwif->drives[unit];
 		drive->dn = (hwif->channel ? 2 : 0) + unit;
 		(void) probe_for_drive(drive);
+		if (drive->present && hwif->present && unit == 1) {
+			if (strcmp(hwif->drives[0].id->model, drive->id->model) == 0 &&
+			    /* Don't do this for noprobe or non ATA */
+			    strcmp(drive->id->model, "UNKNOWN") &&
+			    /* And beware of confused Maxtor drives that go "M0000000000"
+			      "The SN# is garbage in the ID block..." [Eric] */
+			    strncmp(drive->id->serial_no, "M0000000000000000000", 20) &&
+			    strncmp(hwif->drives[0].id->serial_no, drive->id->serial_no, 20) == 0) {
+				printk(KERN_WARNING "ide-probe: ignoring undecoded slave\n");
+				drive->present = 0;
+			}
+		}
 		if (drive->present && !hwif->present) {
 			hwif->present = 1;
 			if (hwif->chipset != ide_4drives ||
@@ -893,11 +892,15 @@ static int ide_init_queue(ide_drive_t *drive)
 	if (!q)
 		return 1;
 
-	q->queuedata = HWGROUP(drive);
+	q->queuedata = drive;
 	blk_queue_segment_boundary(q, 0xffff);
 
-	if (!hwif->rqsize)
-		hwif->rqsize = hwif->no_lba48 ? 256 : 65536;
+	if (!hwif->rqsize) {
+		if (hwif->no_lba48 || hwif->no_lba48_dma)
+			hwif->rqsize = 256;
+		else
+			hwif->rqsize = 65536;
+	}
 	if (hwif->rqsize < max_sectors)
 		max_sectors = hwif->rqsize;
 	blk_queue_max_sectors(q, max_sectors);
@@ -906,11 +909,11 @@ static int ide_init_queue(ide_drive_t *drive)
 	/* When we have an IOMMU, we may have a problem where pci_map_sg()
 	 * creates segments that don't completely match our boundary
 	 * requirements and thus need to be broken up again. Because it
-	 * doesn't align properly neither, we may actually have to break up
+	 * doesn't align properly either, we may actually have to break up
 	 * to more segments than what was we got in the first place, a max
 	 * worst case is twice as many.
 	 * This will be fixed once we teach pci_map_sg() about our boundary
-	 * requirements, hopefully soon
+	 * requirements, hopefully soon. *FIXME*
 	 */
 	if (!PCI_DMA_BUS_IS_PHYS)
 		max_sg_entries >>= 1;
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index a3ebd9e12..07c989bb1 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -360,27 +360,14 @@ static int proc_ide_read_identify
 	int		err = 0;
 
 	len = sprintf(page, "\n");
-	
-	if (drive)
-	{
+
+	if (drive) {
 		unsigned short *val = (unsigned short *) page;
-		
-		/*
-		 *	The current code can't handle a driverless
-		 *	identify query taskfile. Now the right fix is
-		 *	to add a 'default' driver but that is a bit
-		 *	more work. 
-		 *
-		 *	FIXME: this has to be fixed for hotswap devices
-		 */
-		 
-		if(DRIVER(drive))
-			err = taskfile_lib_get_identify(drive, page);
-		else	/* This relies on the ID changes */
-			val = (unsigned short *)drive->id;
-
-		if(!err)
-		{						
+
+		BUG_ON(!drive->driver);
+
+		err = taskfile_lib_get_identify(drive, page);
+		if (!err) {
 			char *out = ((char *)page) + (SECTOR_WORDS * 4);
 			page = out;
 			do {
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index d19ee543e..9d19fab9c 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -530,7 +530,6 @@ typedef struct os_dat_s {
  */
 #define IDETAPE_DEBUG_INFO		0
 #define IDETAPE_DEBUG_LOG		0
-#define IDETAPE_DEBUG_LOG_VERBOSE	0
 #define IDETAPE_DEBUG_BUGS		1
 
 /*
@@ -1260,70 +1259,6 @@ typedef struct {
  */
 static idetape_chrdev_t idetape_chrdevs[MAX_HWIFS * MAX_DRIVES];
 
-#if IDETAPE_DEBUG_LOG_VERBOSE
-
-/*
- * DO NOT REMOVE, BUILDING A VERBOSE DEBUG SCHEME FOR ATAPI
- */
-
-char *idetape_sense_key_verbose(u8 idetape_sense_key)
-{
-	switch (idetape_sense_key) {
-		default: {
-			char buf[22];
-			sprintf(buf, "IDETAPE_SENSE (0x%02x)", idetape_sense_key);
-			return(buf);
-		}
-
-	}
-}
-
-char *idetape_command_key_verbose(u8 idetape_command_key)
-{
-	switch (idetape_command_key) {
-		case IDETAPE_TEST_UNIT_READY_CMD:
-			return("TEST_UNIT_READY_CMD");
-		case IDETAPE_REWIND_CMD:
-			return("REWIND_CMD");
-		case IDETAPE_REQUEST_SENSE_CMD:
-			return("REQUEST_SENSE_CMD");
-		case IDETAPE_READ_CMD:
-			return("READ_CMD");
-		case IDETAPE_WRITE_CMD:
-			return("WRITE_CMD");
-		case IDETAPE_WRITE_FILEMARK_CMD:
-			return("WRITE_FILEMARK_CMD");
-		case IDETAPE_SPACE_CMD:
-			return("SPACE_CMD");
-		case IDETAPE_INQUIRY_CMD:
-			return("INQUIRY_CMD");
-		case IDETAPE_ERASE_CMD:
-			return("ERASE_CMD");
-		case IDETAPE_MODE_SENSE_CMD:
-			return("MODE_SENSE_CMD");
-		case IDETAPE_MODE_SELECT_CMD:
-			return("MODE_SELECT_CMD");
-		case IDETAPE_LOAD_UNLOAD_CMD:
-			return("LOAD_UNLOAD_CMD");
-		case IDETAPE_PREVENT_CMD:
-			return("PREVENT_CMD");
-		case IDETAPE_LOCATE_CMD:
-			return("LOCATE_CMD");
-		case IDETAPE_READ_POSITION_CMD:
-			return("READ_POSITION_CMD");
-		case IDETAPE_READ_BUFFER_CMD:
-			return("READ_BUFFER_CMD");
-		case IDETAPE_SET_SPEED_CMD:
-			return("SET_SPEED_CMD");
-		default: {
-				char buf[20];
-				sprintf(buf, "CMD (0x%02x)", idetape_command_key);
-				return(buf);
-			}
-	}
-}
-#endif /* IDETAPE_DEBUG_LOG_VERBOSE */
-
 /*
  *      Function declarations
  *
@@ -1507,15 +1442,6 @@ static void idetape_analyze_error (ide_drive_t *drive, idetape_request_sense_res
 			"asc = %x, ascq = %x\n",
 			pc->c[0], result->sense_key,
 			result->asc, result->ascq);
-#if IDETAPE_DEBUG_LOG_VERBOSE
-	if (tape->debug_level >= 1)
-		printk(KERN_INFO "ide-tape: pc = %s, sense key = %x, "
-			"asc = %x, ascq = %x\n",
-			idetape_command_key_verbose((byte) pc->c[0]),
-			result->sense_key,
-			result->asc,
-			result->ascq);
-#endif /* IDETAPE_DEBUG_LOG_VERBOSE */
 #endif /* IDETAPE_DEBUG_LOG */
 
 	/*
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index e83c9a9eb..8de2a111b 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -96,36 +96,13 @@ int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
 	else
 		args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_PIDENTIFY;
 	args.command_type = IDE_DRIVE_TASK_IN;
+	args.data_phase   = TASKFILE_IN;
 	args.handler	  = &task_in_intr;
 	return ide_raw_taskfile(drive, &args, buf);
 }
 
 EXPORT_SYMBOL(taskfile_lib_get_identify);
 
-#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG
-void debug_taskfile (ide_drive_t *drive, ide_task_t *args)
-{
-	printk(KERN_INFO "%s: ", drive->name);
-//	printk("TF.0=x%02x ", args->tfRegister[IDE_DATA_OFFSET]);
-	printk("TF.1=x%02x ", args->tfRegister[IDE_FEATURE_OFFSET]);
-	printk("TF.2=x%02x ", args->tfRegister[IDE_NSECTOR_OFFSET]);
-	printk("TF.3=x%02x ", args->tfRegister[IDE_SECTOR_OFFSET]);
-	printk("TF.4=x%02x ", args->tfRegister[IDE_LCYL_OFFSET]);
-	printk("TF.5=x%02x ", args->tfRegister[IDE_HCYL_OFFSET]);
-	printk("TF.6=x%02x ", args->tfRegister[IDE_SELECT_OFFSET]);
-	printk("TF.7=x%02x\n", args->tfRegister[IDE_COMMAND_OFFSET]);
-	printk(KERN_INFO "%s: ", drive->name);
-//	printk("HTF.0=x%02x ", args->hobRegister[IDE_DATA_OFFSET]);
-	printk("HTF.1=x%02x ", args->hobRegister[IDE_FEATURE_OFFSET]);
-	printk("HTF.2=x%02x ", args->hobRegister[IDE_NSECTOR_OFFSET]);
-	printk("HTF.3=x%02x ", args->hobRegister[IDE_SECTOR_OFFSET]);
-	printk("HTF.4=x%02x ", args->hobRegister[IDE_LCYL_OFFSET]);
-	printk("HTF.5=x%02x ", args->hobRegister[IDE_HCYL_OFFSET]);
-	printk("HTF.6=x%02x ", args->hobRegister[IDE_SELECT_OFFSET]);
-	printk("HTF.7=x%02x\n", args->hobRegister[IDE_CONTROL_OFFSET_HOB]);
-}
-#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */
-
 ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
@@ -133,10 +110,6 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
 	hob_struct_t *hobfile	= (hob_struct_t *) task->hobRegister;
 	u8 HIHI			= (drive->addressing == 1) ? 0xE0 : 0xEF;
 
-#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG
-	void debug_taskfile(drive, task);
-#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */
-
 	/* ALL Command Block Executions SHALL clear nIEN, unless otherwise */
 	if (IDE_CONTROL_REG) {
 		/* clear nIEN */
@@ -367,12 +340,44 @@ static u8 wait_drive_not_busy(ide_drive_t *drive)
 	return stat;
 }
 
+static inline void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
+				     unsigned int write)
+{
+	switch (drive->hwif->data_phase) {
+	case TASKFILE_MULTI_IN:
+	case TASKFILE_MULTI_OUT:
+		task_multi_sectors(drive, rq, write);
+		break;
+	default:
+		task_sectors(drive, rq, 1, write);
+		break;
+	}
+}
+
 #ifdef CONFIG_IDE_TASKFILE_IO
 static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
-				  const char *s, u8 stat, unsigned cur_bad)
+				  const char *s, u8 stat)
 {
 	if (rq->bio) {
-		int sectors = rq->hard_nr_sectors - rq->nr_sectors - cur_bad;
+		int sectors = rq->hard_nr_sectors - rq->nr_sectors;
+
+		switch (drive->hwif->data_phase) {
+		case TASKFILE_IN:
+			if (rq->nr_sectors)
+				break;
+			/* fall through */
+		case TASKFILE_OUT:
+			sectors--;
+			break;
+		case TASKFILE_MULTI_IN:
+			if (rq->nr_sectors)
+				break;
+			/* fall through */
+		case TASKFILE_MULTI_OUT:
+			sectors -= drive->mult_count;
+		default:
+			break;
+		}
 
 		if (sectors > 0)
 			drive->driver->end_request(drive, 1, sectors);
@@ -380,7 +385,7 @@ static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
 	return drive->driver->error(drive, s, stat);
 }
 #else
-# define task_error(d, rq, s, stat, cur_bad) drive->driver->error(d, s, stat)
+# define task_error(d, rq, s, stat) drive->driver->error(d, s, stat)
 #endif
 
 static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
@@ -398,7 +403,7 @@ static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
 }
 
 /*
- * Handler for command with PIO data-in phase (Read).
+ * Handler for command with PIO data-in phase (Read/Read Multiple).
  */
 ide_startstop_t task_in_intr (ide_drive_t *drive)
 {
@@ -407,19 +412,19 @@ ide_startstop_t task_in_intr (ide_drive_t *drive)
 
 	if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
 		if (stat & (ERR_STAT | DRQ_STAT))
-			return task_error(drive, rq, __FUNCTION__, stat, 0);
+			return task_error(drive, rq, __FUNCTION__, stat);
 		/* No data yet, so wait for another IRQ. */
 		ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL);
 		return ide_started;
 	}
 
-	task_sectors(drive, rq, 1, IDE_PIO_IN);
+	ide_pio_datablock(drive, rq, 0);
 
 	/* If it was the last datablock check status and finish transfer. */
 	if (!rq->nr_sectors) {
 		stat = wait_drive_not_busy(drive);
 		if (!OK_STAT(stat, 0, BAD_R_STAT))
-			return task_error(drive, rq, __FUNCTION__, stat, 1);
+			return task_error(drive, rq, __FUNCTION__, stat);
 		task_end_request(drive, rq, stat);
 		return ide_stopped;
 	}
@@ -432,41 +437,7 @@ ide_startstop_t task_in_intr (ide_drive_t *drive)
 EXPORT_SYMBOL(task_in_intr);
 
 /*
- * Handler for command with PIO data-in phase (Read Multiple).
- */
-ide_startstop_t task_mulin_intr (ide_drive_t *drive)
-{
-	struct request *rq = HWGROUP(drive)->rq;
-	u8 stat = HWIF(drive)->INB(IDE_STATUS_REG);
-
-	if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
-		if (stat & (ERR_STAT | DRQ_STAT))
-			return task_error(drive, rq, __FUNCTION__, stat, 0);
-		/* No data yet, so wait for another IRQ. */
-		ide_set_handler(drive, &task_mulin_intr, WAIT_WORSTCASE, NULL);
-		return ide_started;
-	}
-
-	task_multi_sectors(drive, rq, IDE_PIO_IN);
-
-	/* If it was the last datablock check status and finish transfer. */
-	if (!rq->nr_sectors) {
-		stat = wait_drive_not_busy(drive);
-		if (!OK_STAT(stat, 0, BAD_R_STAT))
-			return task_error(drive, rq, __FUNCTION__, stat, drive->mult_count);
-		task_end_request(drive, rq, stat);
-		return ide_stopped;
-	}
-
-	/* Still data left to transfer. */
-	ide_set_handler(drive, &task_mulin_intr, WAIT_WORSTCASE, NULL);
-
-	return ide_started;
-}
-EXPORT_SYMBOL(task_mulin_intr);
-
-/*
- * Handler for command with PIO data-out phase (Write).
+ * Handler for command with PIO data-out phase (Write/Write Multiple).
  */
 ide_startstop_t task_out_intr (ide_drive_t *drive)
 {
@@ -475,11 +446,11 @@ ide_startstop_t task_out_intr (ide_drive_t *drive)
 
 	stat = HWIF(drive)->INB(IDE_STATUS_REG);
 	if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
-		return task_error(drive, rq, __FUNCTION__, stat, 1);
+		return task_error(drive, rq, __FUNCTION__, stat);
 
 	/* Deal with unexpected ATA data phase. */
 	if (((stat & DRQ_STAT) == 0) ^ !rq->nr_sectors)
-		return task_error(drive, rq, __FUNCTION__, stat, 1);
+		return task_error(drive, rq, __FUNCTION__, stat);
 
 	if (!rq->nr_sectors) {
 		task_end_request(drive, rq, stat);
@@ -487,7 +458,7 @@ ide_startstop_t task_out_intr (ide_drive_t *drive)
 	}
 
 	/* Still data left to transfer. */
-	task_sectors(drive, rq, 1, IDE_PIO_OUT);
+	ide_pio_datablock(drive, rq, 1);
 	ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL);
 
 	return ide_started;
@@ -501,8 +472,10 @@ ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
 
 	if (ide_wait_stat(&startstop, drive, DATA_READY,
 			  drive->bad_wstat, WAIT_DRQ)) {
-		printk(KERN_ERR "%s: no DRQ after issuing WRITE%s\n",
-				drive->name, drive->addressing ? "_EXT" : "");
+		printk(KERN_ERR "%s: no DRQ after issuing %sWRITE%s\n",
+				drive->name,
+				drive->hwif->data_phase ? "MULT" : "",
+				drive->addressing ? "_EXT" : "");
 		return startstop;
 	}
 
@@ -510,62 +483,12 @@ ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
 		local_irq_disable();
 
 	ide_set_handler(drive, &task_out_intr, WAIT_WORSTCASE, NULL);
-	task_sectors(drive, rq, 1, IDE_PIO_OUT);
+	ide_pio_datablock(drive, rq, 1);
 
 	return ide_started;
 }
 EXPORT_SYMBOL(pre_task_out_intr);
 
-/*
- * Handler for command with PIO data-out phase (Write Multiple).
- */
-ide_startstop_t task_mulout_intr (ide_drive_t *drive)
-{
-	struct request *rq = HWGROUP(drive)->rq;
-	u8 stat;
-
-	stat = HWIF(drive)->INB(IDE_STATUS_REG);
-	if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
-		return task_error(drive, rq, __FUNCTION__, stat, drive->mult_count);
-
-	/* Deal with unexpected ATA data phase. */
-	if (((stat & DRQ_STAT) == 0) ^ !rq->nr_sectors)
-		return task_error(drive, rq, __FUNCTION__, stat, drive->mult_count);
-
-	if (!rq->nr_sectors) {
-		task_end_request(drive, rq, stat);
-		return ide_stopped;
-	}
-
-	/* Still data left to transfer. */
-	task_multi_sectors(drive, rq, IDE_PIO_OUT);
-	ide_set_handler(drive, &task_mulout_intr, WAIT_WORSTCASE, NULL);
-
-	return ide_started;
-}
-EXPORT_SYMBOL(task_mulout_intr);
-
-ide_startstop_t pre_task_mulout_intr (ide_drive_t *drive, struct request *rq)
-{
-	ide_startstop_t startstop;
-
-	if (ide_wait_stat(&startstop, drive, DATA_READY,
-			  drive->bad_wstat, WAIT_DRQ)) {
-		printk(KERN_ERR "%s: no DRQ after issuing MULTWRITE%s\n",
-				drive->name, drive->addressing ? "_EXT" : "");
-		return startstop;
-	}
-
-	if (!drive->unmask)
-		local_irq_disable();
-
-	ide_set_handler(drive, &task_mulout_intr, WAIT_WORSTCASE, NULL);
-	task_multi_sectors(drive, rq, IDE_PIO_OUT);
-
-	return ide_started;
-}
-EXPORT_SYMBOL(pre_task_mulout_intr);
-
 int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_size, u8 *buf)
 {
 	struct request rq;
@@ -688,19 +611,6 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
 		case TASKFILE_IN_DMA:
 			err = ide_diag_taskfile(drive, &args, taskin, inbuf);
 			break;
-		case TASKFILE_IN_OUT:
-#if 0
-			args.prehandler = &pre_task_out_intr;
-			args.handler = &task_out_intr;
-			err = ide_diag_taskfile(drive, &args, taskout, outbuf);
-			args.prehandler = NULL;
-			args.handler = &task_in_intr;
-			err = ide_diag_taskfile(drive, &args, taskin, inbuf);
-			break;
-#else
-			err = -EFAULT;
-			goto abort;
-#endif
 		case TASKFILE_MULTI_OUT:
 			if (!drive->mult_count) {
 				/* (hs): give up if multcount is not set */
@@ -710,10 +620,7 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
 				err = -EPERM;
 				goto abort;
 			}
-			args.prehandler = &pre_task_mulout_intr;
-			args.handler = &task_mulout_intr;
-			err = ide_diag_taskfile(drive, &args, taskout, outbuf);
-			break;
+			/* fall through */
 		case TASKFILE_OUT:
 			args.prehandler = &pre_task_out_intr;
 			args.handler = &task_out_intr;
@@ -728,9 +635,7 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
 				err = -EPERM;
 				goto abort;
 			}
-			args.handler = &task_mulin_intr;
-			err = ide_diag_taskfile(drive, &args, taskin, inbuf);
-			break;
+			/* fall through */
 		case TASKFILE_IN:
 			args.handler = &task_in_intr;
 			err = ide_diag_taskfile(drive, &args, taskin, inbuf);
@@ -907,11 +812,6 @@ ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task)
 	u8 status;
 #endif
 
-
-#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG
-	void debug_taskfile(drive, task);
-#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */
-
 	if (task->data_phase == TASKFILE_MULTI_IN ||
 	    task->data_phase == TASKFILE_MULTI_OUT) {
 		if (!drive->mult_count) {
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index e99d9ec19..c57bd4cc9 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -320,13 +320,19 @@ static void __init init_ide_data (void)
 #endif
 }
 
-/*
- * ide_system_bus_speed() returns what we think is the system VESA/PCI
- * bus speed (in MHz).  This is used for calculating interface PIO timings.
- * The default is 40 for known PCI systems, 50 otherwise.
- * The "idebus=xx" parameter can be used to override this value.
- * The actual value to be used is computed/displayed the first time through.
+/**
+ *	ide_system_bus_speed	-	guess bus speed
+ *
+ *	ide_system_bus_speed() returns what we think is the system VESA/PCI
+ *	bus speed (in MHz). This is used for calculating interface PIO timings.
+ *	The default is 40 for known PCI systems, 50 otherwise.
+ *	The "idebus=xx" parameter can be used to override this value.
+ *	The actual value to be used is computed/displayed the first time
+ *	through. Drivers should only use this as a last resort.
+ *
+ *	Returns a guessed speed in MHz.
  */
+
 int ide_system_bus_speed (void)
 {
 	if (!system_bus_speed) {
@@ -347,10 +353,15 @@ int ide_system_bus_speed (void)
 	return system_bus_speed;
 }
 
-/*
- * current_capacity() returns the capacity (in sectors) of a drive
- * according to its current geometry/LBA settings.
+/**
+ *	current_capacity	-	drive capacity
+ *	@drive: drive to query
+ *
+ *	Return the current capacity (in sectors) of a drive according to
+ *	its current geometry/LBA settings. Empty removables are reported
+ *	as size zero.
  */
+
 sector_t current_capacity (ide_drive_t *drive)
 {
 	if (!drive->present)
@@ -360,9 +371,17 @@ sector_t current_capacity (ide_drive_t *drive)
 
 EXPORT_SYMBOL(current_capacity);
 
-/*
- * Error reporting, in human readable form (luxurious, but a memory hog).
+/**
+ *	ide_dump_status		-	translate ATA error
+ *	@drive: drive the error occured on
+ *	@msg: information string
+ *	@stat: status byte
+ *
+ *	Error reporting, in human readable form (luxurious, but a memory hog).
+ *	Combines the drive name, message and status byte to provide a
+ *	user understandable explanation of the device error.
  */
+
 u8 ide_dump_status (ide_drive_t *drive, const char *msg, u8 stat)
 {
 	ide_hwif_t *hwif = HWIF(drive);
@@ -371,7 +390,6 @@ u8 ide_dump_status (ide_drive_t *drive, const char *msg, u8 stat)
 
 	local_irq_set(flags);
 	printk(KERN_WARNING "%s: %s: status=0x%02x", drive->name, msg, stat);
-#if FANCY_STATUS_DUMPS
 	printk(" { ");
 	if (stat & BUSY_STAT) {
 		printk("Busy ");
@@ -385,12 +403,10 @@ u8 ide_dump_status (ide_drive_t *drive, const char *msg, u8 stat)
 		if (stat & ERR_STAT)	printk("Error ");
 	}
 	printk("}");
-#endif	/* FANCY_STATUS_DUMPS */
 	printk("\n");
 	if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
 		err = hwif->INB(IDE_ERROR_REG);
 		printk("%s: %s: error=0x%02x", drive->name, msg, err);
-#if FANCY_STATUS_DUMPS
 		if (drive->media == ide_disk) {
 			printk(" { ");
 			if (err & ABRT_ERR)	printk("DriveStatusError ");
@@ -434,9 +450,34 @@ u8 ide_dump_status (ide_drive_t *drive, const char *msg, u8 stat)
 					printk(", sector=%llu", (unsigned long long)HWGROUP(drive)->rq->sector);
 			}
 		}
-#endif	/* FANCY_STATUS_DUMPS */
 		printk("\n");
 	}
+	{
+		struct request *rq;
+		int opcode = 0x100;
+
+		spin_lock(&ide_lock);
+		rq = NULL;
+		if (HWGROUP(drive))
+			rq = HWGROUP(drive)->rq;
+		spin_unlock(&ide_lock);
+		if (!rq)
+			goto out;
+		if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
+			char *args = rq->buffer;
+			if (args)
+				opcode = args[0];
+		} else if (rq->flags & REQ_DRIVE_TASKFILE) {
+			ide_task_t *args = rq->special;
+			if (args) {
+				task_struct_t *tf = (task_struct_t *) args->tfRegister;
+				opcode = tf->command;
+			}
+		}
+
+		printk("ide: failed opcode was %x\n", opcode);
+	}
+out:
 	local_irq_restore(flags);
 	return err;
 }
@@ -448,11 +489,17 @@ static int ide_open (struct inode * inode, struct file * filp)
 	return -ENXIO;
 }
 
+/*
+ *	drives_lock protects the list of drives, drivers_lock the
+ *	list of drivers.  Currently nobody takes both at once.
+ */
+
 static spinlock_t drives_lock = SPIN_LOCK_UNLOCKED;
 static spinlock_t drivers_lock = SPIN_LOCK_UNLOCKED;
 static LIST_HEAD(drivers);
 
-/* Iterator */
+/* Iterator for the driver list. */
+
 static void *m_start(struct seq_file *m, loff_t *pos)
 {
 	struct list_head *p;
@@ -463,22 +510,26 @@ static void *m_start(struct seq_file *m, loff_t *pos)
 			return list_entry(p, ide_driver_t, drivers);
 	return NULL;
 }
+
 static void *m_next(struct seq_file *m, void *v, loff_t *pos)
 {
 	struct list_head *p = ((ide_driver_t *)v)->drivers.next;
 	(*pos)++;
 	return p==&drivers ? NULL : list_entry(p, ide_driver_t, drivers);
 }
+
 static void m_stop(struct seq_file *m, void *v)
 {
 	spin_unlock(&drivers_lock);
 }
+
 static int show_driver(struct seq_file *m, void *v)
 {
 	ide_driver_t *driver = v;
 	seq_printf(m, "%s version %s\n", driver->name, driver->version);
 	return 0;
 }
+
 struct seq_operations ide_drivers_op = {
 	.start	= m_start,
 	.next	= m_next,
@@ -515,6 +566,7 @@ static struct resource* hwif_request_region(ide_hwif_t *hwif,
  *	MMIO leaves it to the controller driver,
  *	PIO will migrate this way over time.
  */
+
 int ide_hwif_request_regions(ide_hwif_t *hwif)
 {
 	unsigned long addr;
@@ -564,6 +616,7 @@ control_region_busy:
  *	importantly our caller should be doing this so we need to 
  *	restructure this as a helper function for drivers.
  */
+
 void ide_hwif_release_regions(ide_hwif_t *hwif)
 {
 	u32 i = 0;
@@ -581,7 +634,15 @@ void ide_hwif_release_regions(ide_hwif_t *hwif)
 			release_region(hwif->io_ports[i], 1);
 }
 
-/* restore hwif to a sane state */
+/**
+ *	ide_hwif_restore	-	restore hwif to template
+ *	@hwif: hwif to update
+ *	@tmp_hwif: template
+ *
+ *	Restore hwif to a previous state by copying most settngs
+ *	from the template.
+ */
+
 static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
 {
 	hwif->hwgroup			= tmp_hwif->hwgroup;
@@ -702,18 +763,13 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
 void ide_unregister(unsigned int index)
 {
 	ide_drive_t *drive;
-	ide_hwif_t *hwif, *g, *tmp_hwif;
+	ide_hwif_t *hwif, *g;
+	static ide_hwif_t tmp_hwif; /* protected by ide_cfg_sem */
 	ide_hwgroup_t *hwgroup;
 	int irq_count = 0, unit, i;
 
 	BUG_ON(index >= MAX_HWIFS);
 
-	tmp_hwif = kmalloc(sizeof(*tmp_hwif), GFP_KERNEL|__GFP_NOFAIL);
-	if (!tmp_hwif) {
-		printk(KERN_ERR "%s: unable to allocate memory\n", __FUNCTION__);
-		return;
-	}
-
 	BUG_ON(in_interrupt());
 	BUG_ON(irqs_disabled());
 	down(&ide_cfg_sem);
@@ -860,19 +916,17 @@ void ide_unregister(unsigned int index)
 	}
 
 	/* copy original settings */
-	*tmp_hwif = *hwif;
+	tmp_hwif = *hwif;
 
 	/* restore hwif data to pristine status */
 	init_hwif_data(hwif, index);
 	init_hwif_default(hwif, index);
 
-	ide_hwif_restore(hwif, tmp_hwif);
+	ide_hwif_restore(hwif, &tmp_hwif);
 
 abort:
 	spin_unlock_irq(&ide_lock);
 	up(&ide_cfg_sem);
-
-	kfree(tmp_hwif);
 }
 
 EXPORT_SYMBOL(ide_unregister);
@@ -931,10 +985,17 @@ void ide_setup_ports (	hw_regs_t *hw,
  */
 }
 
-/*
- * Register an IDE interface, specifying exactly the registers etc
- * Set init=1 iff calling before probes have taken place.
+/**
+ *	ide_register_hw		-	register IDE interface
+ *	@hw: hardware registers
+ *	@hwifp: pointer to returned hwif
+ *
+ *	Register an IDE interface, specifying exactly the registers etc.
+ *	Set init=1 iff calling before probes have taken place.
+ *
+ *	Returns -1 on error.
  */
+
 int ide_register_hw (hw_regs_t *hw, ide_hwif_t **hwifp)
 {
 	int index, retry = 1;
@@ -1188,6 +1249,15 @@ int ide_read_setting (ide_drive_t *drive, ide_settings_t *setting)
 	return val;
 }
 
+/**
+ *	ide_spin_wait_hwgroup	-	wait for group
+ *	@drive: drive in the group
+ *
+ *	Wait for an IDE device group to go non busy and then return
+ *	holding the ide_lock which guards the hwgroup->busy status
+ *	and right to use it.
+ */
+
 int ide_spin_wait_hwgroup (ide_drive_t *drive)
 {
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
@@ -1229,6 +1299,7 @@ EXPORT_SYMBOL(ide_spin_wait_hwgroup);
  *	to the driver to change settings, and then wait on a sema for completion.
  *	The current scheme of polling is kludgy, though safe enough.
  */
+
 int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val)
 {
 	int i;
@@ -1322,22 +1393,14 @@ static int set_xfer_rate (ide_drive_t *drive, int arg)
 	return err;
 }
 
-int ide_atapi_to_scsi (ide_drive_t *drive, int arg)
-{
-	if (drive->media == ide_disk) {
-		drive->scsi = 0;
-		return 0;
-	}
-
-	if (DRIVER(drive)->cleanup(drive)) {
-		drive->scsi = 0;
-		return 0;
-	}
-
-	drive->scsi = (u8) arg;
-	ata_attach(drive);
-	return 0;
-}
+/**
+ *	ide_add_generic_settings	-	generic ide settings
+ *	@drive: drive being configured
+ *
+ *	Add the generic parts of the system settings to the /proc files and
+ *	ioctls for this IDE device. The caller must not be holding the
+ *	ide_setting_sem.
+ */
 
 void ide_add_generic_settings (ide_drive_t *drive)
 {
@@ -1353,10 +1416,15 @@ void ide_add_generic_settings (ide_drive_t *drive)
 	ide_add_setting(drive,	"init_speed",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	70,				1,		1,		&drive->init_speed,		NULL);
 	ide_add_setting(drive,	"current_speed",	SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	70,				1,		1,		&drive->current_speed,		set_xfer_rate);
 	ide_add_setting(drive,	"number",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	3,				1,		1,		&drive->dn,			NULL);
-	if (drive->media != ide_disk)
-		ide_add_setting(drive,	"ide-scsi",		SETTING_RW,					-1,		HDIO_SET_IDE_SCSI,		TYPE_BYTE,	0,	1,				1,		1,		&drive->scsi,			ide_atapi_to_scsi);
 }
 
+/**
+ *	system_bus_clock	-	clock guess
+ *
+ *	External version of the bus clock guess used by very old IDE drivers
+ *	for things like VLB timings. Should not be used.
+ */
+
 int system_bus_clock (void)
 {
 	return((int) ((!system_bus_speed) ? ide_system_bus_speed() : system_bus_speed ));
@@ -1391,6 +1459,22 @@ abort:
 	return 1;
 }
 
+/**
+ *	ata_attach		-	attach an ATA/ATAPI device
+ *	@drive: drive to attach
+ *
+ *	Takes a drive that is as yet not assigned to any midlayer IDE
+ *	driver (or is assigned to the default driver) and figures out
+ *	which driver would like to own it. If nobody claims the drive
+ *	then it is automatically attached to the default driver used for
+ *	unclaimed objects.
+ *
+ *	A return of zero indicates attachment to a driver, of one
+ *	attachment to the default driver.
+ *
+ *	Takes drivers_lock.
+ */
+
 int ata_attach(ide_drive_t *drive)
 {
 	struct list_head *p;
@@ -2199,6 +2283,20 @@ int ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver)
 
 EXPORT_SYMBOL(ide_register_subdriver);
 
+/**
+ *	ide_unregister_subdriver	-	disconnect drive from driver
+ *	@drive: drive to unplug
+ *
+ *	Disconnect a drive from the driver it was attached to and then
+ *	clean up the various proc files and other objects attached to it.
+ *
+ *	Takes ide_setting_sem, ide_lock and drives_lock.
+ *	Caller must hold none of the locks.
+ *
+ *	No locking versus subdriver unload because we are moving to the
+ *	default driver anyway. Wants double checking.
+ */
+
 int ide_unregister_subdriver (ide_drive_t *drive)
 {
 	unsigned long flags;
@@ -2234,6 +2332,17 @@ static int ide_drive_remove(struct device * dev)
 	return 0;
 }
 
+/**
+ *	ide_register_driver	-	register IDE device driver
+ *	@driver: the IDE device driver
+ *
+ *	Register a new device driver and then scan the devices
+ *	on the IDE bus in case any should be attached to the
+ *	driver we have just registered.  If so attach them.
+ *
+ *	Takes drivers_lock and drives_lock.
+ */
+
 int ide_register_driver(ide_driver_t *driver)
 {
 	struct list_head list;
@@ -2265,6 +2374,17 @@ int ide_register_driver(ide_driver_t *driver)
 
 EXPORT_SYMBOL(ide_register_driver);
 
+/**
+ *	ide_unregister_driver	-	unregister IDE device driver
+ *	@driver: the IDE device driver
+ *
+ *	Called when a driver module is being unloaded. We reattach any
+ *	devices to whatever driver claims them next (typically the default
+ *	driver).
+ *
+ *	Takes drivers_lock and called functions will take ide_setting_sem.
+ */
+
 void ide_unregister_driver(ide_driver_t *driver)
 {
 	ide_drive_t *drive;
diff --git a/drivers/ide/legacy/Makefile b/drivers/ide/legacy/Makefile
index ad8ae32b8..c0f353e57 100644
--- a/drivers/ide/legacy/Makefile
+++ b/drivers/ide/legacy/Makefile
@@ -10,6 +10,5 @@ obj-$(CONFIG_BLK_DEV_IDECS)		+= ide-cs.o
 
 # Last of all
 obj-$(CONFIG_BLK_DEV_HD)		+= hd.o
-obj-$(CONFIG_BLK_DEV_HD98)		+= hd98.o
 
 EXTRA_CFLAGS	:= -Idrivers/ide
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
index 3147d9099..dda2a17e0 100644
--- a/drivers/ide/legacy/ide-cs.c
+++ b/drivers/ide/legacy/ide-cs.c
@@ -412,12 +412,6 @@ void ide_release(dev_link_t *link)
 	/* FIXME: if this fails we need to queue the cleanup somehow
 	   -- need to investigate the required PCMCIA magic */
 	ide_unregister(info->hd);
-	/* deal with brain dead IDE resource management */
-	request_region(link->io.BasePort1, link->io.NumPorts1,
-		       info->node.dev_name);
-	if (link->io.NumPorts2)
-	    request_region(link->io.BasePort2, link->io.NumPorts2,
-			   info->node.dev_name);
     }
     info->ndev = 0;
     link->dev = NULL;
diff --git a/drivers/ide/legacy/pdc4030.c b/drivers/ide/legacy/pdc4030.c
index c07d341d1..86219e18f 100644
--- a/drivers/ide/legacy/pdc4030.c
+++ b/drivers/ide/legacy/pdc4030.c
@@ -354,15 +354,6 @@ read_next:
 			  (unsigned long)rq->nr_sectors - nsect);
 #endif /* DEBUG_READ */
 
-#ifdef CONFIG_IDE_TASKFILE_IO
-	task_bio_sectors(drive, rq, nsect, IDE_PIO_IN);
-
-	/* FIXME: can we check status after transfer on pdc4030? */
-	/* Complete previously submitted bios. */
-	while (rq->bio != rq->cbio)
-		if (!DRIVER(drive)->end_request(drive, 1, bio_sectors(rq->bio)))
-			return ide_stopped;
-#else /* CONFIG_IDE_TASKFILE_IO */
 	HWIF(drive)->ata_input_data(drive, rq->buffer, nsect * SECTOR_WORDS);
 	rq->buffer += nsect<<9;
 	rq->sector += nsect;
@@ -370,7 +361,6 @@ read_next:
 	rq->nr_sectors -= nsect;
 	if (!rq->current_nr_sectors)
 		DRIVER(drive)->end_request(drive, 1, 0);
-#endif /* CONFIG_IDE_TASKFILE_IO */
 
 /*
  * Now the data has been read in, do the following:
@@ -421,12 +411,8 @@ read_next:
 static ide_startstop_t promise_complete_pollfunc(ide_drive_t *drive)
 {
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
-#ifdef CONFIG_IDE_TASKFILE_IO
-	struct request *rq = hwgroup->rq;
-#else
 	struct request *rq = &hwgroup->wrq;
 	struct bio *bio = rq->bio;
-#endif
 
 	if ((HWIF(drive)->INB(IDE_STATUS_REG)) & BUSY_STAT) {
 		if (time_before(jiffies, hwgroup->poll_timeout)) {
@@ -450,15 +436,10 @@ static ide_startstop_t promise_complete_pollfunc(ide_drive_t *drive)
 	printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name);
 #endif /* DEBUG_WRITE */
 
-#ifdef CONFIG_IDE_TASKFILE_IO
-	/* Complete previously submitted bios. */
-	while (rq->bio != rq->cbio)
-		(void) DRIVER(drive)->end_request(drive, 1, bio_sectors(rq->bio));
-#else
 	bio->bi_idx = bio->bi_vcnt - rq->nr_cbio_segments;
 	rq = hwgroup->rq;
 	DRIVER(drive)->end_request(drive, 1, rq->hard_nr_sectors);
-#endif
+
 	return ide_stopped;
 }
 
@@ -466,27 +447,6 @@ static ide_startstop_t promise_complete_pollfunc(ide_drive_t *drive)
  * promise_multwrite() transfers a block of up to mcount sectors of data
  * to a drive as part of a disk multiple-sector write operation.
  */
-#ifdef CONFIG_IDE_TASKFILE_IO
-static void promise_multwrite (ide_drive_t *drive, unsigned int msect)
-{
-	struct request* rq = HWGROUP(drive)->rq;
-	unsigned int nsect;
-
-	rq->errors = 0;
-	do {
-		nsect = rq->current_nr_sectors;
-		if (nsect > msect)
-			nsect = msect;
-
-		task_bio_sectors(drive, rq, nsect, IDE_PIO_OUT);
-
-		if (!rq->nr_sectors)
-			msect = 0;
-		else
-			msect -= nsect;
-	} while (msect);
-}
-#else /* CONFIG_IDE_TASKFILE_IO */
 static void promise_multwrite (ide_drive_t *drive, unsigned int mcount)
 {
 	ide_hwgroup_t *hwgroup	= HWGROUP(drive);
@@ -537,7 +497,6 @@ static void promise_multwrite (ide_drive_t *drive, unsigned int mcount)
 		taskfile_output_data(drive, buffer, nsect<<7);
 	} while (mcount);
 }
-#endif
 
 /*
  * promise_write_pollfunc() is the handler for disk write completion polling.
@@ -545,12 +504,8 @@ static void promise_multwrite (ide_drive_t *drive, unsigned int mcount)
 static ide_startstop_t promise_write_pollfunc (ide_drive_t *drive)
 {
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
-#ifdef CONFIG_IDE_TASKFILE_IO
-	struct request *rq = hwgroup->rq;
-#else
 	struct request *rq = &hwgroup->wrq;
 	struct bio *bio = rq->bio;
-#endif
 
 	if (HWIF(drive)->INB(IDE_NSECTOR_REG) != 0) {
 		if (time_before(jiffies, hwgroup->poll_timeout)) {
@@ -564,19 +519,11 @@ static ide_startstop_t promise_write_pollfunc (ide_drive_t *drive)
 		}
 		hwgroup->poll_timeout = 0;
 		printk(KERN_ERR "%s: write timed-out!\n",drive->name);
-#ifndef CONFIG_IDE_TASKFILE_IO
 		bio->bi_idx = bio->bi_vcnt - rq->nr_cbio_segments;
-#endif
 		return DRIVER(drive)->error(drive, "write timeout",
 				HWIF(drive)->INB(IDE_STATUS_REG));
 	}
 
-#ifdef CONFIG_IDE_TASKFILE_IO
-	/* Complete previously submitted bios. */
-	while (rq->bio != rq->cbio)
-		(void) DRIVER(drive)->end_request(drive, 1, bio_sectors(rq->bio));
-#endif
-
 	/*
 	 * Now write out last 4 sectors and poll for not BUSY
 	 */
@@ -602,11 +549,7 @@ static ide_startstop_t promise_write_pollfunc (ide_drive_t *drive)
 static ide_startstop_t promise_write (ide_drive_t *drive)
 {
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
-#ifdef CONFIG_IDE_TASKFILE_IO
-	struct request *rq = hwgroup->rq;
-#else
 	struct request *rq = &hwgroup->wrq;
-#endif
 
 #ifdef DEBUG_WRITE
 	printk(KERN_DEBUG "%s: %s: sectors(%lu-%lu)\n",
@@ -654,39 +597,14 @@ static ide_startstop_t promise_write (ide_drive_t *drive)
  * already set up. It issues a READ or WRITE command to the Promise
  * controller, assuming LBA has been used to set up the block number.
  */
-#ifndef CONFIG_IDE_TASKFILE_IO
 ide_startstop_t do_pdc4030_io (ide_drive_t *drive, struct request *rq)
 {
 	ide_startstop_t startstop;
 	unsigned long timeout;
 	u8 stat = 0;
-#else
-static ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task)
-{
-	struct request *rq	= HWGROUP(drive)->rq;
-	task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
-	ide_startstop_t startstop;
-	unsigned long timeout;
-	u8 stat = 0;
-
-	if (IDE_CONTROL_REG)
-		HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);	/* clear nIEN */
-	SELECT_MASK(drive, 0);
-	HWIF(drive)->OUTB(taskfile->feature, IDE_FEATURE_REG);
-	HWIF(drive)->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
-	/* refers to number of sectors to transfer */
-	HWIF(drive)->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
-	/* refers to sector offset or start sector */
-	HWIF(drive)->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
-	HWIF(drive)->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);
-	HWIF(drive)->OUTB(taskfile->device_head, IDE_SELECT_REG);
-	HWIF(drive)->OUTB(taskfile->command, IDE_COMMAND_REG);
-#endif
 
 	if (rq_data_dir(rq) == READ) {
-#ifndef CONFIG_IDE_TASKFILE_IO
 		HWIF(drive)->OUTB(PROMISE_READ, IDE_COMMAND_REG);
-#endif
 /*
  * The card's behaviour is odd at this point. If the data is
  * available, DRQ will be true, and no interrupt will be
@@ -722,9 +640,7 @@ static ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task)
 				"waiting - Odd!\n", drive->name);
 		return ide_stopped;
 	} else {
-#ifndef CONFIG_IDE_TASKFILE_IO
 		HWIF(drive)->OUTB(PROMISE_WRITE, IDE_COMMAND_REG);
-#endif
 		if (ide_wait_stat(&startstop, drive, DATA_READY,
 				drive->bad_wstat, WAIT_DRQ)) {
 			printk(KERN_ERR "%s: no DRQ after issuing "
@@ -733,9 +649,7 @@ static ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task)
 	    	}
 		if (!drive->unmask)
 			local_irq_disable();
-#ifndef CONFIG_IDE_TASKFILE_IO
 		HWGROUP(drive)->wrq = *rq; /* scratchpad */
-#endif
 		return promise_write(drive);
 	}
 }
@@ -749,14 +663,9 @@ static ide_startstop_t promise_rw_disk (ide_drive_t *drive, struct request *rq,
 	*/
 	ide_hwif_t *hwif = HWIF(drive);
 	int drive_number = (hwif->channel << 1) + drive->select.b.unit;
-#ifdef CONFIG_IDE_TASKFILE_IO
-	struct hd_drive_task_hdr taskfile;
-	ide_task_t args;
-#endif
 
 	BUG_ON(rq->nr_sectors > 127);
 
-#ifndef CONFIG_IDE_TASKFILE_IO
 	if (IDE_CONTROL_REG)
 		hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
 	hwif->OUTB(drive_number, IDE_FEATURE_REG);
@@ -767,27 +676,4 @@ static ide_startstop_t promise_rw_disk (ide_drive_t *drive, struct request *rq,
 	hwif->OUTB(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG);
 
 	return do_pdc4030_io(drive, rq);
-#else /* !CONFIG_IDE_TASKFILE_IO */
-	memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
-
-	taskfile.feature	= drive_number;
-	taskfile.sector_count	= rq->nr_sectors;
-	taskfile.sector_number	= block;
-	taskfile.low_cylinder	= (block>>=8);
-	taskfile.high_cylinder	= (block>>=8);
-	taskfile.device_head	= ((block>>8)&0x0f)|drive->select.all;
-	taskfile.command	= (rq->cmd==READ)?PROMISE_READ:PROMISE_WRITE;
-
-	memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
-	memset(args.hobRegister, 0, sizeof(struct hd_drive_hob_hdr));
-	/*
-	 * Setup the bits of args that we do need.
-	 * Note that we don't use the generic interrupt handlers.
-	 */
-	args.handler		= NULL;
-	args.rq			= (struct request *) rq;
-	rq->special		= (ide_task_t *)&args;
-
-	return do_pdc4030_io(drive, &args);
-#endif /* !CONFIG_IDE_TASKFILE_IO */
 }
diff --git a/drivers/ide/legacy/qd65xx.h b/drivers/ide/legacy/qd65xx.h
index 1557a47ff..603018e44 100644
--- a/drivers/ide/legacy/qd65xx.h
+++ b/drivers/ide/legacy/qd65xx.h
@@ -47,10 +47,10 @@
 /* Drive specific timing taken from DOS driver v3.7 */
 
 struct qd65xx_timing_s {
-	char	offset;   /* ofset from the beginning of Model Number" */
+	s8	offset;   /* ofset from the beginning of Model Number" */
 	char	model[4];    /* 4 chars from Model number, no conversion */
-	short	active;   /* active time */
-	short	recovery; /* recovery time */
+	s16	active;   /* active time */
+	s16	recovery; /* recovery time */
 } qd65xx_timing [] = {
 	{ 30, "2040", 110, 225 },  /* Conner CP30204			*/
 	{ 30, "2045", 135, 225 },  /* Conner CP30254			*/
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index b032d2459..d80959488 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -29,8 +29,6 @@ static u8 aec62xx_proc = 0;
 static struct pci_dev *aec_devs[AEC_MAX_DEVS];
 static int n_aec_devs;
 
-#undef DEBUG_AEC_REGS
-
 static int aec62xx_get_info (char *buffer, char **addr, off_t offset, int count)
 {
 	char *p = buffer;
@@ -44,9 +42,6 @@ static int aec62xx_get_info (char *buffer, char **addr, off_t offset, int count)
 		struct pci_dev *dev	= aec_devs[i];
 		unsigned long iobase = pci_resource_start(dev, 4);
 		u8 c0 = 0, c1 = 0, art	= 0;
-#ifdef DEBUG_AEC_REGS
-		u8 uart			= 0;
-#endif /* DEBUG_AEC_REGS */
 
 		c0 = inb(iobase + 0x02);
 		c1 = inb(iobase + 0x0a);
@@ -83,24 +78,6 @@ static int aec62xx_get_info (char *buffer, char **addr, off_t offset, int count)
 			p += sprintf(p, "           %s(%s)\n",
 				(c1&0x40)?((art&0xc0)?"UDMA":" DMA"):" PIO",
 				(art&0x80)?"2":(art&0x40)?"1":"0");
-#ifdef DEBUG_AEC_REGS
-			(void) pci_read_config_byte(dev, 0x40, &art);
-			p += sprintf(p, "Active:         0x%02x", art);
-			(void) pci_read_config_byte(dev, 0x42, &art);
-			p += sprintf(p, "             0x%02x", art);
-			(void) pci_read_config_byte(dev, 0x44, &art);
-			p += sprintf(p, "            0x%02x", art);
-			(void) pci_read_config_byte(dev, 0x46, &art);
-			p += sprintf(p, "              0x%02x\n", art);
-			(void) pci_read_config_byte(dev, 0x41, &art);
-			p += sprintf(p, "Recovery:       0x%02x", art);
-			(void) pci_read_config_byte(dev, 0x43, &art);
-			p += sprintf(p, "             0x%02x", art);
-			(void) pci_read_config_byte(dev, 0x45, &art);
-			p += sprintf(p, "            0x%02x", art);
-			(void) pci_read_config_byte(dev, 0x47, &art);
-			p += sprintf(p, "              0x%02x\n", art);
-#endif /* DEBUG_AEC_REGS */
 		} else {
 			/*
 			 * case PCI_DEVICE_ID_ARTOP_ATP860:
@@ -146,28 +123,6 @@ static int aec62xx_get_info (char *buffer, char **addr, off_t offset, int count)
 				((art&0x30)==0x30)?"2":
 				((art&0x20)==0x20)?"1":
 				((art&0x10)==0x10)?"0":"?");
-#ifdef DEBUG_AEC_REGS
-			(void) pci_read_config_byte(dev, 0x40, &art);
-			p += sprintf(p, "Active:         0x%02x", HIGH_4(art));
-			(void) pci_read_config_byte(dev, 0x41, &art);
-			p += sprintf(p, "             0x%02x", HIGH_4(art));
-			(void) pci_read_config_byte(dev, 0x42, &art);
-			p += sprintf(p, "            0x%02x", HIGH_4(art));
-			(void) pci_read_config_byte(dev, 0x43, &art);
-			p += sprintf(p, "              0x%02x\n", HIGH_4(art));
-			(void) pci_read_config_byte(dev, 0x40, &art);
-			p += sprintf(p, "Recovery:       0x%02x", LOW_4(art));
-			(void) pci_read_config_byte(dev, 0x41, &art);
-			p += sprintf(p, "             0x%02x", LOW_4(art));
-			(void) pci_read_config_byte(dev, 0x42, &art);
-			p += sprintf(p, "            0x%02x", LOW_4(art));
-			(void) pci_read_config_byte(dev, 0x43, &art);
-			p += sprintf(p, "              0x%02x\n", LOW_4(art));
-			(void) pci_read_config_byte(dev, 0x49, &uart);
-			p += sprintf(p, "reg49h = 0x%02x ", uart);
-			(void) pci_read_config_byte(dev, 0x4a, &uart);
-			p += sprintf(p, "reg4ah = 0x%02x\n", uart);
-#endif /* DEBUG_AEC_REGS */
 		}
 	}
 	/* p - buffer must be less than 4k! */
@@ -240,6 +195,7 @@ static int aec6210_tune_chipset (ide_drive_t *drive, u8 xferspeed)
 	unsigned long flags;
 
 	local_irq_save(flags);
+	/* 0x40|(2*drive->dn): Active, 0x41|(2*drive->dn): Recovery */
 	pci_read_config_word(dev, 0x40|(2*drive->dn), &d_conf);
 	tmp0 = pci_bus_clock_list(speed, BUSCLOCK(dev));
 	SPLIT_BYTE(tmp0,tmp1,tmp2);
@@ -268,6 +224,7 @@ static int aec6260_tune_chipset (ide_drive_t *drive, u8 xferspeed)
 	unsigned long flags;
 
 	local_irq_save(flags);
+	/* high 4-bits: Active, low 4-bits: Recovery */
 	pci_read_config_byte(dev, 0x40|drive->dn, &drive_conf);
 	drive_conf = pci_bus_clock_list(speed, BUSCLOCK(dev));
 	pci_write_config_byte(dev, 0x40|drive->dn, drive_conf);
@@ -540,7 +497,7 @@ static struct pci_device_id aec62xx_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, aec62xx_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "AEC62xx IDE",
+	.name		= "AEC62xx_IDE",
 	.id_table	= aec62xx_pci_tbl,
 	.probe		= aec62xx_init_one,
 };
diff --git a/drivers/ide/pci/aec62xx.h b/drivers/ide/pci/aec62xx.h
index 3f272752c..460d7e365 100644
--- a/drivers/ide/pci/aec62xx.h
+++ b/drivers/ide/pci/aec62xx.h
@@ -53,13 +53,6 @@ struct chipset_bus_clock_list_entry aec6xxx_34_base [] = {
 	{	0,		0x00,	0x00	}
 };
 
-
-#ifndef HIGH_4
-#define HIGH_4(H)		((H)=(H>>4))
-#endif
-#ifndef LOW_4
-#define LOW_4(L)		((L)=(L-((L>>4)<<4)))
-#endif
 #ifndef SPLIT_BYTE
 #define SPLIT_BYTE(B,H,L)	((H)=(B>>4), (L)=(B-((B>>4)<<4)))
 #endif
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index 2a343679a..82a449dc8 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -752,8 +752,8 @@ static void __init init_hwif_common_ali15x3 (ide_hwif_t *hwif)
 	hwif->tuneproc = &ali15x3_tune_drive;
 	hwif->speedproc = &ali15x3_tune_chipset;
 
-	/* Don't use LBA48 on ALi devices before rev 0xC5 */
-	hwif->no_lba48 = (m5229_revision <= 0xC4) ? 1 : 0;
+	/* don't use LBA48 DMA on ALi devices before rev 0xC5 */
+	hwif->no_lba48_dma = (m5229_revision <= 0xC4) ? 1 : 0;
 
 	if (!hwif->dma_base) {
 		hwif->drives[0].autotune = 1;
@@ -893,7 +893,7 @@ static struct pci_device_id alim15x3_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "ALI15x3 IDE",
+	.name		= "ALI15x3_IDE",
 	.id_table	= alim15x3_pci_tbl,
 	.probe		= alim15x3_init_one,
 };
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index 30bdcb3ec..3967254ce 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -416,6 +416,9 @@ static void __init init_hwif_amd74xx(ide_hwif_t *hwif)
 {
 	int i;
 
+	if (!hwif->irq)
+		hwif->irq = hwif->channel ? 15 : 14;
+
 	hwif->autodma = 0;
 
 	hwif->tuneproc = &amd74xx_tune_drive;
@@ -520,7 +523,7 @@ static struct pci_device_id amd74xx_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "AMD IDE",
+	.name		= "AMD_IDE",
 	.id_table	= amd74xx_pci_tbl,
 	.probe		= amd74xx_probe,
 };
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
index bd3708568..5a65d5dc1 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/pci/atiixp.c
@@ -490,7 +490,7 @@ static struct pci_device_id atiixp_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "ATIIXP IDE",
+	.name		= "ATIIXP_IDE",
 	.id_table	= atiixp_pci_tbl,
 	.probe		= atiixp_init_one,
 };
diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c
index 0eac8ee64..92a2b7cae 100644
--- a/drivers/ide/pci/cmd640.c
+++ b/drivers/ide/pci/cmd640.c
@@ -101,6 +101,8 @@
 #undef REALLY_SLOW_IO		/* most systems can safely undef this */
 #define CMD640_PREFETCH_MASKS 1
 
+//#define CMD640_DUMP_REGS
+
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -748,7 +750,7 @@ int __init ide_probe_for_cmd640x (void)
 	put_cmd640_reg(0x5b, 0);
 
 #ifdef CMD640_DUMP_REGS
-	CMD640_DUMP_REGS;
+	cmd640_dump_regs();
 #endif
 
 	/*
@@ -870,7 +872,7 @@ int __init ide_probe_for_cmd640x (void)
 	}
 
 #ifdef CMD640_DUMP_REGS
-	CMD640_DUMP_REGS;
+	cmd640_dump_regs();
 #endif
 	return 1;
 }
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index 06b00a3c3..abea997dc 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -38,8 +38,6 @@ static u8 cmd64x_proc = 0;
 static struct pci_dev *cmd_devs[CMD_MAX_DEVS];
 static int n_cmd_devs;
 
-#undef DEBUG_CMD_REGS
-
 static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index)
 {
 	char *p = buf;
@@ -49,9 +47,6 @@ static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index)
 	u8 reg72 = 0, reg73 = 0;			/* primary */
 	u8 reg7a = 0, reg7b = 0;			/* secondary */
 	u8 reg50 = 0, reg71 = 0;			/* extra */
-#ifdef DEBUG_CMD_REGS
-	u8 hi_byte = 0, lo_byte = 0;
-#endif /* DEBUG_CMD_REGS */
 
 	p += sprintf(p, "\nController: %d\n", index);
 	p += sprintf(p, "CMD%x Chipset.\n", dev->device);
@@ -127,18 +122,6 @@ static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index)
 		(reg71 & MRDMODE_BLK_CH0) ? "blocked" : "enabled",
 		(reg71 & MRDMODE_BLK_CH1) ? "blocked" : "enabled");
 
-#ifdef DEBUG_CMD_REGS
-	SPLIT_BYTE(reg50, hi_byte, lo_byte);
-	p += sprintf(p, "CFR       = 0x%02x, HI = 0x%02x, "
-			"LOW = 0x%02x\n", reg50, hi_byte, lo_byte);
-	SPLIT_BYTE(reg57, hi_byte, lo_byte);
-	p += sprintf(p, "ARTTIM23  = 0x%02x, HI = 0x%02x, "
-			"LOW = 0x%02x\n", reg57, hi_byte, lo_byte);
-	SPLIT_BYTE(reg71, hi_byte, lo_byte);
-	p += sprintf(p, "MRDMODE   = 0x%02x, HI = 0x%02x, "
-			"LOW = 0x%02x\n", reg71, hi_byte, lo_byte);
-#endif /* DEBUG_CMD_REGS */
-
 	return (char *)p;
 }
 
@@ -760,7 +743,7 @@ static struct pci_device_id cmd64x_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, cmd64x_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "CMD64x IDE",
+	.name		= "CMD64x_IDE",
 	.id_table	= cmd64x_pci_tbl,
 	.probe		= cmd64x_init_one,
 };
diff --git a/drivers/ide/pci/cmd64x.h b/drivers/ide/pci/cmd64x.h
index f5dde235a..78490275d 100644
--- a/drivers/ide/pci/cmd64x.h
+++ b/drivers/ide/pci/cmd64x.h
@@ -15,10 +15,6 @@
 #define cmdprintk(x...)
 #endif
 
-#ifndef SPLIT_BYTE
-#define SPLIT_BYTE(B,H,L)	((H)=(B>>4), (L)=(B-((B>>4)<<4)))
-#endif
-
 /*
  * CMD64x specific registers definition.
  */
diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
index 5882693d0..e65dec73c 100644
--- a/drivers/ide/pci/cs5520.c
+++ b/drivers/ide/pci/cs5520.c
@@ -290,7 +290,10 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic
 		return 1;
 	}
 	pci_set_master(dev);
-	pci_set_dma_mask(dev, 0xFFFFFFFF);
+	if (pci_set_dma_mask(dev, 0xFFFFFFFF)) {
+		printk(KERN_WARNING "cs5520: No suitable DMA available.\n");
+		return -ENODEV;
+	}
 	init_chipset_cs5520(dev, d->name);
 
 	index.all = 0xf0f0;
@@ -319,7 +322,7 @@ static struct pci_device_id cs5520_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, cs5520_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "CyrixIDE",
+	.name		= "Cyrix_IDE",
 	.id_table	= cs5520_pci_tbl,
 	.probe		= cs5520_init_one,
 };
diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c
index fe840cbe0..83bfe92d2 100644
--- a/drivers/ide/pci/cy82c693.c
+++ b/drivers/ide/pci/cy82c693.c
@@ -444,7 +444,7 @@ static struct pci_device_id cy82c693_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, cy82c693_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "Cypress IDE",
+	.name		= "Cypress_IDE",
 	.id_table	= cy82c693_pci_tbl,
 	.probe		= cy82c693_init_one,
 };
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
index 2150a18a8..a4154e702 100644
--- a/drivers/ide/pci/generic.c
+++ b/drivers/ide/pci/generic.c
@@ -138,7 +138,7 @@ static struct pci_device_id generic_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, generic_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "PCI IDE",
+	.name		= "PCI_IDE",
 	.id_table	= generic_pci_tbl,
 	.probe		= generic_init_one,
 };
diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
index f9c9ab664..8eb72f446 100644
--- a/drivers/ide/pci/hpt34x.c
+++ b/drivers/ide/pci/hpt34x.c
@@ -44,65 +44,6 @@
 
 #include "hpt34x.h"
 
-#if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 hpt34x_proc = 0;
-
-#define HPT34X_MAX_DEVS		8
-static struct pci_dev *hpt34x_devs[HPT34X_MAX_DEVS];
-static int n_hpt34x_devs;
-
-static int hpt34x_get_info (char *buffer, char **addr, off_t offset, int count)
-{
-	char *p = buffer;
-	int i, len;
-
-	p += sprintf(p, "\n                             "
-			"HPT34X Chipset.\n");
-	for (i = 0; i < n_hpt34x_devs; i++) {
-		struct pci_dev *dev = hpt34x_devs[i];
-		unsigned long bibma = pci_resource_start(dev, 4);
-		u8  c0 = 0, c1 = 0;
-
-		/*
-		 * at that point bibma+0x2 et bibma+0xa are byte registers
-		 * to investigate:
-		 */
-		c0 = inb_p((u16)bibma + 0x02);
-		c1 = inb_p((u16)bibma + 0x0a);
-		p += sprintf(p, "\nController: %d\n", i);
-		p += sprintf(p, "--------------- Primary Channel "
-				"---------------- Secondary Channel "
-				"-------------\n");
-		p += sprintf(p, "                %sabled "
-				"                        %sabled\n",
-				(c0&0x80) ? "dis" : " en",
-				(c1&0x80) ? "dis" : " en");
-		p += sprintf(p, "--------------- drive0 --------- drive1 "
-				"-------- drive0 ---------- drive1 ------\n");
-		p += sprintf(p, "DMA enabled:    %s              %s"
-				"             %s               %s\n",
-				(c0&0x20) ? "yes" : "no ",
-				(c0&0x40) ? "yes" : "no ",
-				(c1&0x20) ? "yes" : "no ",
-				(c1&0x40) ? "yes" : "no " );
-
-		p += sprintf(p, "UDMA\n");
-		p += sprintf(p, "DMA\n");
-		p += sprintf(p, "PIO\n");
-	}
-	p += sprintf(p, "\n");
-
-	/* p - buffer must be less than 4k! */
-	len = (p - buffer) - offset;
-	*addr = buffer + offset;
-	
-	return len > count ? count : len;
-}
-#endif  /* defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) */
-
 static u8 hpt34x_ratemask (ide_drive_t *drive)
 {
 	return 1;
@@ -277,15 +218,6 @@ static unsigned int __devinit init_chipset_hpt34x(struct pci_dev *dev, const cha
 
 	local_irq_restore(flags);
 
-#if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS)
-	hpt34x_devs[n_hpt34x_devs++] = dev;
-
-	if (!hpt34x_proc) {
-		hpt34x_proc = 1;
-		ide_pci_create_host_proc("hpt34x", hpt34x_get_info);
-	}
-#endif /* DISPLAY_HPT34X_TIMINGS && CONFIG_PROC_FS */
-
 	return dev->irq;
 }
 
@@ -339,7 +271,7 @@ static struct pci_device_id hpt34x_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, hpt34x_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "HPT34x IDE",
+	.name		= "HPT34x_IDE",
 	.id_table	= hpt34x_pci_tbl,
 	.probe		= hpt34x_init_one,
 };
diff --git a/drivers/ide/pci/hpt34x.h b/drivers/ide/pci/hpt34x.h
index 465f56715..d1a840034 100644
--- a/drivers/ide/pci/hpt34x.h
+++ b/drivers/ide/pci/hpt34x.h
@@ -11,8 +11,6 @@
 #define SPLIT_BYTE(B,H,L)	((H)=(B>>4), (L)=(B-((B>>4)<<4)))
 #endif
 
-#undef DISPLAY_HPT34X_TIMINGS
-
 static unsigned int init_chipset_hpt34x(struct pci_dev *, const char *);
 static void init_hwif_hpt34x(ide_hwif_t *);
 
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index 5f5bc3b6e..d1e8adbe7 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -777,9 +777,6 @@ static int hpt3xx_tristate (ide_drive_t * drive, int state)
 	u8 reg59h = 0, reset	= (hwif->channel) ? 0x80 : 0x40;
 	u8 regXXh = 0, state_reg= (hwif->channel) ? 0x57 : 0x53;
 
-	if (!hwif)
-		return -EINVAL;
-
 //	hwif->bus_state = state;
 
 	pci_read_config_byte(dev, 0x59, &reg59h);
@@ -813,9 +810,6 @@ static int hpt370_busproc(ide_drive_t * drive, int state)
 	u8 tristate = 0, resetmask = 0, bus_reg = 0;
 	u16 tri_reg;
 
-	if (!hwif)
-		return -EINVAL;
-
 	hwif->bus_state = state;
 
 	if (hwif->channel) { 
@@ -958,7 +952,7 @@ static int __devinit init_hpt37x(struct pci_dev *dev)
 			/* Unsupported */
 		} else if (pll == F_LOW_PCI_50) {
 			if (hpt_minimum_revision(dev,8))
-				pci_set_drvdata(dev, NULL);
+				pci_set_drvdata(dev, (void *) fifty_base_hpt370a);
 			else if (hpt_minimum_revision(dev,5))
 				pci_set_drvdata(dev, (void *) fifty_base_hpt372);
 			else if (hpt_minimum_revision(dev,4))
@@ -991,11 +985,6 @@ static int __devinit init_hpt37x(struct pci_dev *dev)
 	if (pci_get_drvdata(dev)) 
 		goto init_hpt37X_done;
 	
-	if (hpt_minimum_revision(dev,8))
-	{
-		printk(KERN_ERR "HPT374: Only 33MHz PCI timings are supported.\n");
-		return -EOPNOTSUPP;
-	}
 	/*
 	 * adjust PLL based upon PCI clock, enable it, and wait for
 	 * stabilization.
@@ -1403,7 +1392,7 @@ static struct pci_device_id hpt366_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "HPT366 IDE",
+	.name		= "HPT366_IDE",
 	.id_table	= hpt366_pci_tbl,
 	.probe		= hpt366_init_one,
 };
diff --git a/drivers/ide/pci/it8172.c b/drivers/ide/pci/it8172.c
index b65ce0877..3a163fa85 100644
--- a/drivers/ide/pci/it8172.c
+++ b/drivers/ide/pci/it8172.c
@@ -302,7 +302,7 @@ static struct pci_device_id it8172_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, it8172_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "IT8172IDE",
+	.name		= "IT8172_IDE",
 	.id_table	= it8172_pci_tbl,
 	.probe		= it8172_init_one,
 };
diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c
index a5b6e7e5c..44f782492 100644
--- a/drivers/ide/pci/ns87415.c
+++ b/drivers/ide/pci/ns87415.c
@@ -236,7 +236,7 @@ static struct pci_device_id ns87415_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, ns87415_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "NS87415IDE",
+	.name		= "NS87415_IDE",
 	.id_table	= ns87415_pci_tbl,
 	.probe		= ns87415_init_one,
 };
diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c
index 3ca7db7d5..ab76641ae 100644
--- a/drivers/ide/pci/opti621.c
+++ b/drivers/ide/pci/opti621.c
@@ -367,7 +367,7 @@ static struct pci_device_id opti621_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, opti621_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "Opti621 IDE",
+	.name		= "Opti621_IDE",
 	.id_table	= opti621_pci_tbl,
 	.probe		= opti621_init_one,
 };
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index f493b29ce..8f635922a 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -531,7 +531,7 @@ static struct pci_device_id pdc202new_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, pdc202new_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "Promise IDE",
+	.name		= "Promise_IDE",
 	.id_table	= pdc202new_pci_tbl,
 	.probe		= pdc202new_init_one,
 };
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index 3b4379c63..651879a49 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -314,17 +314,6 @@ static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed)
 		pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC);
 	}
 
-#if PDC202XX_DECODE_REGISTER_INFO
-	pci_read_config_byte(dev, (drive_pci), &AP);
-	pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
-	pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
-	pci_read_config_byte(dev, (drive_pci)|0x03, &DP);
-
-	decode_registers(REG_A, AP);
-	decode_registers(REG_B, BP);
-	decode_registers(REG_C, CP);
-	decode_registers(REG_D, DP);
-#endif /* PDC202XX_DECODE_REGISTER_INFO */
 #if PDC202XX_DEBUG_DRIVE_INFO
 	printk(KERN_DEBUG "%s: %s drive%d 0x%08x ",
 		drive->name, ide_xfer_verbose(speed),
@@ -905,7 +894,7 @@ static struct pci_device_id pdc202xx_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, pdc202xx_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "Promise Old IDE",
+	.name		= "Promise_Old_IDE",
 	.id_table	= pdc202xx_pci_tbl,
 	.probe		= pdc202xx_init_one,
 };
diff --git a/drivers/ide/pci/pdc202xx_old.h b/drivers/ide/pci/pdc202xx_old.h
index 95ea2c8aa..6afebd1d2 100644
--- a/drivers/ide/pci/pdc202xx_old.h
+++ b/drivers/ide/pci/pdc202xx_old.h
@@ -10,7 +10,6 @@
 #endif
 
 #define PDC202XX_DEBUG_DRIVE_INFO		0
-#define PDC202XX_DECODE_REGISTER_INFO		0
 
 static const char *pdc_quirk_drives[] = {
 	"QUANTUM FIREBALLlct08 08",
@@ -99,76 +98,6 @@ static inline u8 *pdc202xx_ultra_verbose (u32 drive_pci, u16 slow_cable)
 #define	MC1		0x02	/* DMA"C" timing */
 #define	MC0		0x01	/* DMA"C" timing */
 
-#if PDC202XX_DECODE_REGISTER_INFO
-
-#define REG_A		0x01
-#define REG_B		0x02
-#define REG_C		0x04
-#define REG_D		0x08
-
-static void decode_registers (u8 registers, u8 value)
-{
-	u8	bit = 0, bit1 = 0, bit2 = 0;
-
-	switch(registers) {
-		case REG_A:
-			bit2 = 0;
-			printk("A Register ");
-			if (value & 0x80) printk("SYNC_IN ");
-			if (value & 0x40) printk("ERRDY_EN ");
-			if (value & 0x20) printk("IORDY_EN ");
-			if (value & 0x10) printk("PREFETCH_EN ");
-			if (value & 0x08) { printk("PA3 ");bit2 |= 0x08; }
-			if (value & 0x04) { printk("PA2 ");bit2 |= 0x04; }
-			if (value & 0x02) { printk("PA1 ");bit2 |= 0x02; }
-			if (value & 0x01) { printk("PA0 ");bit2 |= 0x01; }
-			printk("PIO(A) = %d ", bit2);
-			break;
-		case REG_B:
-			bit1 = 0;bit2 = 0;
-			printk("B Register ");
-			if (value & 0x80) { printk("MB2 ");bit1 |= 0x80; }
-			if (value & 0x40) { printk("MB1 ");bit1 |= 0x40; }
-			if (value & 0x20) { printk("MB0 ");bit1 |= 0x20; }
-			printk("DMA(B) = %d ", bit1 >> 5);
-			if (value & 0x10) printk("PIO_FORCED/PB4 ");
-			if (value & 0x08) { printk("PB3 ");bit2 |= 0x08; }
-			if (value & 0x04) { printk("PB2 ");bit2 |= 0x04; }
-			if (value & 0x02) { printk("PB1 ");bit2 |= 0x02; }
-			if (value & 0x01) { printk("PB0 ");bit2 |= 0x01; }
-			printk("PIO(B) = %d ", bit2);
-			break;
-		case REG_C:
-			bit2 = 0;
-			printk("C Register ");
-			if (value & 0x80) printk("DMARQp ");
-			if (value & 0x40) printk("IORDYp ");
-			if (value & 0x20) printk("DMAR_EN ");
-			if (value & 0x10) printk("DMAW_EN ");
-
-			if (value & 0x08) { printk("MC3 ");bit2 |= 0x08; }
-			if (value & 0x04) { printk("MC2 ");bit2 |= 0x04; }
-			if (value & 0x02) { printk("MC1 ");bit2 |= 0x02; }
-			if (value & 0x01) { printk("MC0 ");bit2 |= 0x01; }
-			printk("DMA(C) = %d ", bit2);
-			break;
-		case REG_D:
-			printk("D Register ");
-			break;
-		default:
-			return;
-	}
-	printk("\n        %s ", (registers & REG_D) ? "DP" :
-				(registers & REG_C) ? "CP" :
-				(registers & REG_B) ? "BP" :
-				(registers & REG_A) ? "AP" : "ERROR");
-	for (bit=128;bit>0;bit/=2)
-		printk("%s", (value & bit) ? "1" : "0");
-	printk("\n");
-}
-
-#endif /* PDC202XX_DECODE_REGISTER_INFO */
-
 #define DISPLAY_PDC202XX_TIMINGS
 
 static void init_setup_pdc202ata4(struct pci_dev *dev, ide_pci_device_t *d);
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index 26719f2c7..c4161a5f5 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -561,36 +561,31 @@ static int piix_config_drive_xfer_rate (ide_drive_t *drive)
 	drive->init_speed = 0;
 
 	if ((id->capability & 1) && drive->autodma) {
+
 		/* Consult the list of known "bad" drives */
 		if (__ide_dma_bad_drive(drive))
 			goto fast_ata_pio;
-		if (id->field_valid & 4) {
-			if (id->dma_ultra & hwif->ultra_mask) {
-				/* Force if Capable UltraDMA */
-				if ((id->field_valid & 2) &&
-				    (!piix_config_drive_for_dma(drive)))
-					goto try_dma_modes;
-			}
-		} else if (id->field_valid & 2) {
-try_dma_modes:
-			if ((id->dma_mword & hwif->mwdma_mask) ||
-			    (id->dma_1word & hwif->swdma_mask)) {
-				/* Force if Capable regular DMA modes */
-				if (!piix_config_drive_for_dma(drive))
-					goto no_dma_set;
-			}
-		} else if (__ide_dma_good_drive(drive) &&
-			   (id->eide_dma_time < 150)) {
-			/* Consult the list of known "good" drives */
-			if (!piix_config_drive_for_dma(drive))
-				goto no_dma_set;
-		} else {
-			goto fast_ata_pio;
+
+		/**
+		 * Try to turn DMA on if:
+		 *  - UDMA or EIDE modes are supported or
+		 *  - drive is a known "good" drive
+		 *
+		 * Checks for best mode supported are down later by
+		 * piix_config_drive_for_dma() -> ide_dma_speed()
+		 */
+		if ((id->field_valid & (4 | 2)) ||
+		    (__ide_dma_good_drive(drive) && id->eide_dma_time < 150)) {
+			if (piix_config_drive_for_dma(drive))
+				return hwif->ide_dma_on(drive);
 		}
-		return hwif->ide_dma_on(drive);
+
+		/* For some reason DMA wasn't turned on, so try PIO. */
+		goto fast_ata_pio;
+
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
-no_dma_set:
+		/* Find best PIO mode. */
 		hwif->tuneproc(drive, 255);
 		return hwif->ide_dma_off_quietly(drive);
 	}
@@ -803,7 +798,7 @@ static struct pci_device_id piix_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, piix_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "PIIX IDE",
+	.name		= "PIIX_IDE",
 	.id_table	= piix_pci_tbl,
 	.probe		= piix_init_one,
 };
diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c
index 3405e6a1b..8281e4fa6 100644
--- a/drivers/ide/pci/rz1000.c
+++ b/drivers/ide/pci/rz1000.c
@@ -74,7 +74,7 @@ static struct pci_device_id rz1000_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, rz1000_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "RZ1000 IDE",
+	.name		= "RZ1000_IDE",
 	.id_table	= rz1000_pci_tbl,
 	.probe		= rz1000_init_one,
 };
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
index 902408d18..4cd5d013f 100644
--- a/drivers/ide/pci/sc1200.c
+++ b/drivers/ide/pci/sc1200.c
@@ -565,7 +565,7 @@ static struct pci_device_id sc1200_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, sc1200_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "SC1200 IDE",
+	.name		= "SC1200_IDE",
 	.id_table	= sc1200_pci_tbl,
 	.probe		= sc1200_init_one,
 	.suspend	= sc1200_suspend,
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index 27d907c9b..510ca140c 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -812,7 +812,7 @@ static struct pci_device_id svwks_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, svwks_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "Serverworks IDE",
+	.name		= "Serverworks_IDE",
 	.id_table	= svwks_pci_tbl,
 	.probe		= svwks_init_one,
 #if 0	/* FIXME: implement */
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index 0187aafac..6a3d79b29 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -570,7 +570,6 @@ sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir)
 use_pio_instead:
 	pci_unmap_sg(hwif->pci_dev, hwif->sg_table, hwif->sg_nents,
 		     hwif->sg_dma_direction);
-	hwif->sg_dma_active = 0;
 
 	return 0;		/* revert to PIO for this request */
 }
@@ -702,6 +701,10 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d)
 		       hwif->name, d->name);
 
 	probe_hwif_init(hwif);
+
+	/* Create /proc/ide entries */
+	create_proc_ide_interfaces(); 
+
 	return 0;
 }
 
@@ -782,7 +785,7 @@ static struct pci_device_id sgiioc4_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, sgiioc4_pci_tbl);
 
 static struct pci_driver driver = {
-	.name = "SGI-IOC4 IDE",
+	.name = "SGI-IOC4_IDE",
 	.id_table = sgiioc4_pci_tbl,
 	.probe = sgiioc4_init_one,
 };
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 91b039826..6c874989b 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -727,8 +727,7 @@ static unsigned int setup_mmio_siimage (struct pci_dev *dev, const char *name)
 	unsigned long bar5	= pci_resource_start(dev, 5);
 	unsigned long barsize	= pci_resource_len(dev, 5);
 	u8 tmpbyte	= 0;
-	unsigned long addr;
-	void *ioaddr;
+	void __iomem *ioaddr;
 
 	/*
 	 *	Drop back to PIO if we can't map the mmio. Some
@@ -751,22 +750,21 @@ static unsigned int setup_mmio_siimage (struct pci_dev *dev, const char *name)
 	}
 
 	pci_set_master(dev);
-	pci_set_drvdata(dev, ioaddr);
-	addr = (unsigned long) ioaddr;
+	pci_set_drvdata(dev, (void *) ioaddr);
 
 	if (pdev_is_sata(dev)) {
-		writel(0, addr + 0x148);
-		writel(0, addr + 0x1C8);
+		writel(0, ioaddr + 0x148);
+		writel(0, ioaddr + 0x1C8);
 	}
 
-	writeb(0, addr + 0xB4);
-	writeb(0, addr + 0xF4);
-	tmpbyte = readb(addr + 0x4A);
+	writeb(0, ioaddr + 0xB4);
+	writeb(0, ioaddr + 0xF4);
+	tmpbyte = readb(ioaddr + 0x4A);
 
 	switch(tmpbyte & 0x30) {
 		case 0x00:
 			/* In 100 MHz clocking, try and switch to 133 */
-			writeb(tmpbyte|0x10, addr + 0x4A);
+			writeb(tmpbyte|0x10, ioaddr + 0x4A);
 			break;
 		case 0x10:
 			/* On 133Mhz clocking */
@@ -777,29 +775,29 @@ static unsigned int setup_mmio_siimage (struct pci_dev *dev, const char *name)
 		case 0x30:
 			/* Clocking is disabled */
 			/* 133 clock attempt to force it on */
-			writeb(tmpbyte & ~0x20, addr + 0x4A);
+			writeb(tmpbyte & ~0x20, ioaddr + 0x4A);
 			break;
 	}
 	
-	writeb(      0x72, addr + 0xA1);
-	writew(    0x328A, addr + 0xA2);
-	writel(0x62DD62DD, addr + 0xA4);
-	writel(0x43924392, addr + 0xA8);
-	writel(0x40094009, addr + 0xAC);
-	writeb(      0x72, addr + 0xE1);
-	writew(    0x328A, addr + 0xE2);
-	writel(0x62DD62DD, addr + 0xE4);
-	writel(0x43924392, addr + 0xE8);
-	writel(0x40094009, addr + 0xEC);
+	writeb(      0x72, ioaddr + 0xA1);
+	writew(    0x328A, ioaddr + 0xA2);
+	writel(0x62DD62DD, ioaddr + 0xA4);
+	writel(0x43924392, ioaddr + 0xA8);
+	writel(0x40094009, ioaddr + 0xAC);
+	writeb(      0x72, ioaddr + 0xE1);
+	writew(    0x328A, ioaddr + 0xE2);
+	writel(0x62DD62DD, ioaddr + 0xE4);
+	writel(0x43924392, ioaddr + 0xE8);
+	writel(0x40094009, ioaddr + 0xEC);
 
 	if (pdev_is_sata(dev)) {
-		writel(0xFFFF0000, addr + 0x108);
-		writel(0xFFFF0000, addr + 0x188);
-		writel(0x00680000, addr + 0x148);
-		writel(0x00680000, addr + 0x1C8);
+		writel(0xFFFF0000, ioaddr + 0x108);
+		writel(0xFFFF0000, ioaddr + 0x188);
+		writel(0x00680000, ioaddr + 0x148);
+		writel(0x00680000, ioaddr + 0x1C8);
 	}
 
-	tmpbyte = readb(addr + 0x4A);
+	tmpbyte = readb(ioaddr + 0x4A);
 
 	proc_reports_siimage(dev, (tmpbyte>>4), name);
 	return 1;
@@ -1137,7 +1135,7 @@ static struct pci_device_id siimage_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, siimage_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "SiI IDE",
+	.name		= "SiI_IDE",
 	.id_table	= siimage_pci_tbl,
 	.probe		= siimage_init_one,
 };
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index d06b1fd8c..964f80604 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -788,6 +788,15 @@ static unsigned int __init init_chipset_sis5513 (struct pci_dev *dev, const char
 			if (trueid == 0x5518) {
 				printk(KERN_INFO "SIS5513: SiS 962/963 MuTIOL IDE UDMA133 controller\n");
 				chipset_family = ATA_133;
+
+				/* Check for 5513 compability mapping
+				 * We must use this, else the port enabled code will fail,
+				 * as it expects the enablebits at 0x4a.
+				 */
+				if ((idemisc & 0x40000000) == 0) {
+					pci_write_config_dword(dev, 0x54, idemisc | 0x40000000);
+					printk(KERN_INFO "SIS5513: Switching to 5513 register mapping\n");
+				}
 			}
 	}
 
@@ -963,12 +972,13 @@ static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_devi
 
 static struct pci_device_id sis5513_pci_tbl[] = {
 	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5518, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, sis5513_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "SIS IDE",
+	.name		= "SIS_IDE",
 	.id_table	= sis5513_pci_tbl,
 	.probe		= sis5513_init_one,
 };
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
index 38bd8077b..563c44c7d 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/pci/sl82c105.c
@@ -503,7 +503,7 @@ static struct pci_device_id sl82c105_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, sl82c105_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "W82C105 IDE",
+	.name		= "W82C105_IDE",
 	.id_table	= sl82c105_pci_tbl,
 	.probe		= sl82c105_init_one,
 };
diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
index 1a0183d1b..5a82a5fba 100644
--- a/drivers/ide/pci/slc90e66.c
+++ b/drivers/ide/pci/slc90e66.c
@@ -387,7 +387,7 @@ static struct pci_device_id slc90e66_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, slc90e66_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "SLC90e66 IDE",
+	.name		= "SLC90e66_IDE",
 	.id_table	= slc90e66_pci_tbl,
 	.probe		= slc90e66_init_one,
 };
diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
index 52e088e25..eca0772f2 100644
--- a/drivers/ide/pci/triflex.c
+++ b/drivers/ide/pci/triflex.c
@@ -41,57 +41,6 @@
 #include <linux/ide.h>
 #include <linux/init.h>
 
-static struct pci_dev *triflex_dev;
-
-#ifdef CONFIG_PROC_FS
-static int triflex_get_info(char *buf, char **addr, off_t offset, int count)
-{
-	char *p = buf;
-	int len;
-
-	struct pci_dev *dev	= triflex_dev;
-	unsigned long bibma = pci_resource_start(dev, 4);
-	u8  c0 = 0, c1 = 0;
-	u32 pri_timing, sec_timing;
-
-	p += sprintf(p, "\n                                Compaq Triflex Chipset\n");
-	
-	pci_read_config_dword(dev, 0x70, &pri_timing);
-	pci_read_config_dword(dev, 0x74, &sec_timing);
-
-	/*
-	 * at that point bibma+0x2 et bibma+0xa are byte registers
-	 * to investigate:
-	 */
-	c0 = inb((unsigned short)bibma + 0x02);
-	c1 = inb((unsigned short)bibma + 0x0a);
-
-	p += sprintf(p, "--------------- Primary Channel "
-			"---------------- Secondary Channel "
-			"-------------\n");
-	p += sprintf(p, "                %sabled "
-			"                        %sabled\n",
-			(c0&0x80) ? "dis" : " en",
-			(c1&0x80) ? "dis" : " en");
-	p += sprintf(p, "--------------- drive0 --------- drive1 "
-			"-------- drive0 ---------- drive1 ------\n");
-	p += sprintf(p, "DMA enabled:    %s              %s "
-			"            %s               %s\n",
-			(c0&0x20) ? "yes" : "no ",
-			(c0&0x40) ? "yes" : "no ",
-			(c1&0x20) ? "yes" : "no ",
-			(c1&0x40) ? "yes" : "no " );
-
-	p += sprintf(p, "DMA\n");
-	p += sprintf(p, "PIO\n");
-
-	len = (p - buf) - offset;
-	*addr = buf + offset;
-	
-	return len > count ? count : len;
-}
-#endif
-
 static int triflex_tune_chipset(ide_drive_t *drive, u8 xferspeed)
 {
 	ide_hwif_t *hwif = HWIF(drive);
@@ -206,18 +155,8 @@ static void __init init_hwif_triflex(ide_hwif_t *hwif)
 	hwif->drives[1].autodma = hwif->autodma;
 }
 
-static unsigned int __init init_chipset_triflex(struct pci_dev *dev, 
-		const char *name) 
-{
-#ifdef CONFIG_PROC_FS
-	ide_pci_create_host_proc("triflex", triflex_get_info);
-#endif
-	return 0;	
-}
-
 static ide_pci_device_t triflex_device __devinitdata = {
 	.name		= "TRIFLEX",
-	.init_chipset	= init_chipset_triflex,
 	.init_hwif	= init_hwif_triflex,
 	.channels	= 2,
 	.autodma	= AUTODMA,
@@ -229,7 +168,6 @@ static int __devinit triflex_init_one(struct pci_dev *dev,
 		const struct pci_device_id *id)
 {
 	ide_setup_pci_device(dev, &triflex_device);
-	triflex_dev = dev;
 
 	return 0;
 }
@@ -242,7 +180,7 @@ static struct pci_device_id triflex_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, triflex_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "TRIFLEX IDE",
+	.name		= "TRIFLEX_IDE",
 	.id_table	= triflex_pci_tbl,
 	.probe		= triflex_init_one,
 };
diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c
index d4c753930..bb7de7a96 100644
--- a/drivers/ide/pci/trm290.c
+++ b/drivers/ide/pci/trm290.c
@@ -408,7 +408,7 @@ static struct pci_device_id trm290_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, trm290_pci_tbl);
 
 static struct pci_driver driver = {
-	.name		= "TRM290 IDE",
+	.name		= "TRM290_IDE",
 	.id_table	= trm290_pci_tbl,
 	.probe		= trm290_init_one,
 };
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index 9aa563300..c83d5e5e8 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -632,7 +632,7 @@ static struct pci_device_id via_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, via_pci_tbl);
 
 static struct pci_driver driver = {
-	.name 		= "VIA IDE",
+	.name 		= "VIA_IDE",
 	.id_table 	= via_pci_tbl,
 	.probe 		= via_init_one,
 };
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 7030168e6..3625e38a7 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -62,10 +62,10 @@ typedef struct pmac_ide_hwif {
 	int				irq;
 	int				kind;
 	int				aapl_bus_id;
-	int				cable_80 : 1;
-	int				mediabay : 1;
-	int				broken_dma : 1;
-	int				broken_dma_warn : 1;
+	unsigned			cable_80 : 1;
+	unsigned			mediabay : 1;
+	unsigned			broken_dma : 1;
+	unsigned			broken_dma_warn : 1;
 	struct device_node*		node;
 	struct macio_dev		*mdev;
 	u32				timings[4];
@@ -75,7 +75,7 @@ typedef struct pmac_ide_hwif {
 	 * beeing done by the generic code about the kind of dma controller
 	 * and format of the dma table. This will have to be fixed though.
 	 */
-	volatile struct dbdma_regs*	dma_regs;
+	volatile struct dbdma_regs __iomem *	dma_regs;
 	struct dbdma_cmd*		dma_table_cpu;
 	dma_addr_t			dma_table_dma;
 	struct scatterlist*		sg_table;
@@ -497,6 +497,8 @@ pmac_ide_init_hwif_ports(hw_regs_t *hw,
 		*irq = pmac_ide[ix].irq;
 }
 
+#define PMAC_IDE_REG(x) ((void __iomem *)(IDE_DATA_REG+(x)))
+
 /*
  * Apply the timings of the proper unit (master/slave) to the shared
  * timing register when selecting that unit. This version is for
@@ -511,12 +513,10 @@ pmac_ide_selectproc(ide_drive_t *drive)
 		return;
 
 	if (drive->select.b.unit & 0x01)
-		writel(pmif->timings[1],
-			(unsigned *)(IDE_DATA_REG+IDE_TIMING_CONFIG));
+		writel(pmif->timings[1], PMAC_IDE_REG(IDE_TIMING_CONFIG));
 	else
-		writel(pmif->timings[0],
-			(unsigned *)(IDE_DATA_REG+IDE_TIMING_CONFIG));
-	(void)readl((unsigned *)(IDE_DATA_REG+IDE_TIMING_CONFIG));
+		writel(pmif->timings[0], PMAC_IDE_REG(IDE_TIMING_CONFIG));
+	(void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG));
 }
 
 /*
@@ -533,17 +533,13 @@ pmac_ide_kauai_selectproc(ide_drive_t *drive)
 		return;
 
 	if (drive->select.b.unit & 0x01) {
-		writel(pmif->timings[1],
-		       (unsigned *)(IDE_DATA_REG + IDE_KAUAI_PIO_CONFIG));
-		writel(pmif->timings[3],
-		       (unsigned *)(IDE_DATA_REG + IDE_KAUAI_ULTRA_CONFIG));
+		writel(pmif->timings[1], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG));
+		writel(pmif->timings[3], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG));
 	} else {
-		writel(pmif->timings[0],
-		       (unsigned *)(IDE_DATA_REG + IDE_KAUAI_PIO_CONFIG));
-		writel(pmif->timings[2],
-		       (unsigned *)(IDE_DATA_REG + IDE_KAUAI_ULTRA_CONFIG));
+		writel(pmif->timings[0], PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG));
+		writel(pmif->timings[2], PMAC_IDE_REG(IDE_KAUAI_ULTRA_CONFIG));
 	}
-	(void)readl((unsigned *)(IDE_DATA_REG + IDE_KAUAI_PIO_CONFIG));
+	(void)readl(PMAC_IDE_REG(IDE_KAUAI_PIO_CONFIG));
 }
 
 /*
@@ -568,8 +564,8 @@ pmac_outbsync(ide_drive_t *drive, u8 value, unsigned long port)
 {
 	u32 tmp;
 	
-	writeb(value, port);	
-	tmp = readl((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG));
+	writeb(value, (void __iomem *) port);
+	tmp = readl(PMAC_IDE_REG(IDE_TIMING_CONFIG));
 }
 
 /*
@@ -792,7 +788,7 @@ static int __pmac
 set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2,
 			u8 speed, int drive_cycle_time)
 {
-	int cycleTime, accessTime, recTime;
+	int cycleTime, accessTime = 0, recTime = 0;
 	unsigned accessTicks, recTicks;
 	struct mdma_timings_t* tm = NULL;
 	int i;
@@ -1281,7 +1277,8 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
 static int __devinit
 pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_match *match)
 {
-	unsigned long base, regbase;
+	void __iomem *base;
+	unsigned long regbase;
 	int irq;
 	ide_hwif_t *hwif;
 	pmac_ide_hwif_t *pmif;
@@ -1324,8 +1321,8 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_match *match)
 	} else
 		irq = macio_irq(mdev, 0);
 
-	base =  (unsigned long)ioremap(macio_resource_start(mdev, 0), 0x400);
-	regbase = base;
+	base = ioremap(macio_resource_start(mdev, 0), 0x400);
+	regbase = (unsigned long) base;
 
 	hwif->pci_dev = mdev->bus->pdev;
 	hwif->gendev.parent = &mdev->ofdev.dev;
@@ -1339,8 +1336,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_match *match)
 		if (macio_request_resource(mdev, 1, "ide-pmac (dma)"))
 			printk(KERN_WARNING "ide%d: can't request DMA resource !\n", i);
 		else
-			pmif->dma_regs = (volatile struct dbdma_regs*)
-				ioremap(macio_resource_start(mdev, 1), 0x1000);
+			pmif->dma_regs = ioremap(macio_resource_start(mdev, 1), 0x1000);
 	} else
 		pmif->dma_regs = NULL;
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
@@ -1350,9 +1346,9 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_match *match)
 	if (rc != 0) {
 		/* The inteface is released to the common IDE layer */
 		dev_set_drvdata(&mdev->ofdev.dev, NULL);
-		iounmap((void *)base);
+		iounmap(base);
 		if (pmif->dma_regs)
-			iounmap((void *)pmif->dma_regs);
+			iounmap(pmif->dma_regs);
 		memset(pmif, 0, sizeof(*pmif));
 		macio_release_resource(mdev, 0);
 		if (pmif->dma_regs)
@@ -1401,7 +1397,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
 	ide_hwif_t *hwif;
 	struct device_node *np;
 	pmac_ide_hwif_t *pmif;
-	unsigned long base;
+	void __iomem *base;
 	unsigned long rbase, rlen;
 	int i, rc;
 
@@ -1444,10 +1440,10 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
 	rbase = pci_resource_start(pdev, 0);
 	rlen = pci_resource_len(pdev, 0);
 
-	base = (unsigned long) ioremap(rbase, rlen);
-	pmif->regbase = base + 0x2000;
+	base = ioremap(rbase, rlen);
+	pmif->regbase = (unsigned long) base + 0x2000;
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
-	pmif->dma_regs = (volatile struct dbdma_regs*)(base + 0x1000);
+	pmif->dma_regs = base + 0x1000;
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */	
 
 	/* We use the OF node irq mapping */
@@ -1462,7 +1458,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
 	if (rc != 0) {
 		/* The inteface is released to the common IDE layer */
 		pci_set_drvdata(pdev, NULL);
-		iounmap((void *)base);
+		iounmap(base);
 		memset(pmif, 0, sizeof(*pmif));
 		pci_release_regions(pdev);
 	}
@@ -1578,9 +1574,6 @@ pmac_ide_build_sglist(ide_drive_t *drive, struct request *rq)
 	struct scatterlist *sg = pmif->sg_table;
 	int nents;
 
-	if (hwif->sg_dma_active)
-		BUG();
-		
 	nents = blk_rq_map_sg(drive->queue, rq, sg);
 		
 	if (rq_data_dir(rq) == READ)
@@ -1639,7 +1632,7 @@ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
 	int i, count = 0;
 	ide_hwif_t *hwif = HWIF(drive);
 	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
-	volatile struct dbdma_regs *dma = pmif->dma_regs;
+	volatile struct dbdma_regs __iomem *dma = pmif->dma_regs;
 	struct scatterlist *sg;
 	int wr = (rq_data_dir(rq) == WRITE);
 
@@ -1715,7 +1708,6 @@ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
 		     pmif->sg_table,
 		     pmif->sg_nents,
 		     pmif->sg_dma_direction);
-	hwif->sg_dma_active = 0;
 	return 0; /* revert to PIO for this request */
 }
 
@@ -1731,7 +1723,6 @@ pmac_ide_destroy_dmatable (ide_drive_t *drive)
 	if (nents) {
 		pci_unmap_sg(dev, sg, nents, pmif->sg_dma_direction);
 		pmif->sg_nents = 0;
-		HWIF(drive)->sg_dma_active = 0;
 	}
 }
 
@@ -1912,8 +1903,8 @@ pmac_ide_dma_start(ide_drive_t *drive, int reading)
 	/* Apple adds 60ns to wrDataSetup on reads */
 	if (ata4 && (pmif->timings[unit] & TR_66_UDMA_EN)) {
 		writel(pmif->timings[unit] + (reading ? 0x00800000UL : 0),
-			(unsigned *)(IDE_DATA_REG+IDE_TIMING_CONFIG));
-		(void)readl((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG));
+			PMAC_IDE_REG(IDE_TIMING_CONFIG));
+		(void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG));
 	}
 
 	drive->waiting_for_dma = 1;
@@ -1992,7 +1983,7 @@ static int __pmac
 pmac_ide_dma_begin (ide_drive_t *drive)
 {
 	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
-	volatile struct dbdma_regs *dma;
+	volatile struct dbdma_regs __iomem *dma;
 
 	if (pmif == NULL)
 		return 1;
@@ -2011,7 +2002,7 @@ static int __pmac
 pmac_ide_dma_end (ide_drive_t *drive)
 {
 	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
-	volatile struct dbdma_regs *dma;
+	volatile struct dbdma_regs __iomem *dma;
 	u32 dstat;
 	
 	if (pmif == NULL)
@@ -2039,7 +2030,7 @@ static int __pmac
 pmac_ide_dma_test_irq (ide_drive_t *drive)
 {
 	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
-	volatile struct dbdma_regs *dma;
+	volatile struct dbdma_regs __iomem *dma;
 	unsigned long status, timeout;
 
 	if (pmif == NULL)
@@ -2107,7 +2098,7 @@ static int __pmac
 pmac_ide_dma_lostirq (ide_drive_t *drive)
 {
 	pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
-	volatile struct dbdma_regs *dma;
+	volatile struct dbdma_regs __iomem *dma;
 	unsigned long status;
 
 	if (pmif == NULL)
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index a9709b846..798537f68 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -132,7 +132,7 @@ struct eth1394_node_info {
 };
 
 /* Our ieee1394 highlevel driver */
-#define ETH1394_DRIVER_NAME "ip1394"
+#define ETH1394_DRIVER_NAME "eth1394"
 static const char driver_name[] = ETH1394_DRIVER_NAME;
 
 static kmem_cache_t *packet_task_cache;
@@ -850,7 +850,7 @@ static inline u16 ether1394_type_trans(struct sk_buff *skb,
 
 	skb->mac.raw = skb->data;
 	skb_pull (skb, ETH1394_HLEN);
-	eth = (struct eth1394hdr*)skb->mac.raw;
+	eth = eth1394_hdr(skb);
 
 	if (*eth->h_dest & 1) {
 		if (memcmp(eth->h_dest, dev->broadcast, dev->addr_len)==0)
diff --git a/drivers/ieee1394/eth1394.h b/drivers/ieee1394/eth1394.h
index 015f8178c..ed8f1c4b7 100644
--- a/drivers/ieee1394/eth1394.h
+++ b/drivers/ieee1394/eth1394.h
@@ -81,7 +81,14 @@ struct eth1394hdr {
 	unsigned short	h_proto;		/* packet type ID field	*/
 }  __attribute__((packed));
 
+#ifdef __KERNEL__
+#include <linux/skbuff.h>
 
+static inline struct eth1394hdr *eth1394_hdr(const struct sk_buff *skb)
+{
+	return (struct eth1394hdr *)skb->mac.raw;
+}
+#endif
 
 typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type;
 
diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h
index e2e6194c9..d1758d409 100644
--- a/drivers/ieee1394/ohci1394.h
+++ b/drivers/ieee1394/ohci1394.h
@@ -163,7 +163,7 @@ struct ti_ohci {
 	} init_state;
 
         /* remapped memory spaces */
-        void *registers;
+        void __iomem *registers;
 
 	/* dma buffer for self-id packets */
         quadlet_t *selfid_buf_cpu;
diff --git a/drivers/input/gameport/cs461x.c b/drivers/input/gameport/cs461x.c
index 71fcad10c..8459e05c6 100644
--- a/drivers/input/gameport/cs461x.c
+++ b/drivers/input/gameport/cs461x.c
@@ -312,7 +312,7 @@ static void __devexit cs461x_pci_remove(struct pci_dev *pdev)
 }
 
 static struct pci_driver cs461x_pci_driver = {
-        .name =         "CS461x Gameport",
+        .name =         "CS461x_gameport",
         .id_table =     cs461x_pci_tbl,
         .probe =        cs461x_pci_probe,
         .remove =       __devexit_p(cs461x_pci_remove),
diff --git a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c
index 89d469378..8f1461ad2 100644
--- a/drivers/input/gameport/emu10k1-gp.c
+++ b/drivers/input/gameport/emu10k1-gp.c
@@ -50,8 +50,11 @@ struct emu {
 };
 
 static struct pci_device_id emu_tbl[] = {
+ 
 	{ 0x1102, 0x7002, PCI_ANY_ID, PCI_ANY_ID }, /* SB Live gameport */
 	{ 0x1102, 0x7003, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy gameport */
+	{ 0x1102, 0x7004, PCI_ANY_ID, PCI_ANY_ID }, /* Dell SB Live */
+	{ 0x1102, 0x7005, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy LS gameport */
 	{ 0, }
 };
 
@@ -109,7 +112,7 @@ static void __devexit emu_remove(struct pci_dev *pdev)
 }
 
 static struct pci_driver emu_driver = {
-        .name =         "Emu10k1 Gameport",
+        .name =         "Emu10k1_gameport",
         .id_table =     emu_tbl,
         .probe =        emu_probe,
         .remove =       __devexit_p(emu_remove),
diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c
index ff3b620b8..93849a6cc 100644
--- a/drivers/input/gameport/fm801-gp.c
+++ b/drivers/input/gameport/fm801-gp.c
@@ -137,7 +137,7 @@ static struct pci_device_id fm801_gp_id_table[] = {
 };
 
 static struct pci_driver fm801_gp_driver = {
-	.name =		"FM801 GP",
+	.name =		"FM801_gameport",
 	.id_table =	fm801_gp_id_table,
 	.probe =	fm801_gp_probe,
 	.remove =	__devexit_p(fm801_gp_remove),
diff --git a/drivers/input/gameport/vortex.c b/drivers/input/gameport/vortex.c
index 02c31b779..e0a1c3eb5 100644
--- a/drivers/input/gameport/vortex.c
+++ b/drivers/input/gameport/vortex.c
@@ -55,8 +55,8 @@ MODULE_LICENSE("GPL");
 struct vortex {
 	struct gameport gameport;
 	struct pci_dev *dev;
-        unsigned char *base;
-        unsigned char *io;
+        unsigned char __iomem *base;
+        unsigned char __iomem *io;
 	char phys[32];
 };
 
@@ -166,7 +166,7 @@ static struct pci_device_id vortex_id_table[] =
  { 0 }};
 
 static struct pci_driver vortex_driver = {
-	.name =		"vortex",
+	.name =		"vortex_gameport",
 	.id_table =	vortex_id_table,
 	.probe =	vortex_probe,
 	.remove =	__devexit_p(vortex_remove),
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 5eb884656..3e47218e0 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -232,8 +232,10 @@ static ssize_t joydev_read(struct file *file, char __user *buf, size_t count, lo
 		&& list->head == list->tail && (file->f_flags & O_NONBLOCK))
 			return -EAGAIN;
 
-	retval = wait_event_interruptible(list->joydev->wait, list->joydev->exist
-		&& (list->startup < joydev->nabs + joydev->nkey || list->head != list->tail));
+	retval = wait_event_interruptible(list->joydev->wait,
+		 			  !list->joydev->exist ||
+					  list->startup < joydev->nabs + joydev->nkey ||
+					  list->head != list->tail);
 
 	if (retval)
 		return retval;
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
index 7d506f1f7..8f62f70d0 100644
--- a/drivers/input/joystick/Kconfig
+++ b/drivers/input/joystick/Kconfig
@@ -247,9 +247,9 @@ config JOYSTICK_AMIGA
 	  To compile this driver as a module, choose M here: the
 	  module will be called amijoy.
 
-config INPUT_JOYDUMP
+config JOYSTICK_JOYDUMP
 	tristate "Gameport data dumper"
-	depends on INPUT && INPUT_JOYSTICK
+	depends on INPUT && INPUT_JOYSTICK && GAMEPORT
 	help
 	  Say Y here if you want to dump data from your joystick into the system
 	  log for debugging purposes. Say N if you are making a production
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index 555fb362b..46326b701 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -1,17 +1,14 @@
 /*
- * $Id: gamecon.c,v 1.22 2002/07/01 15:42:25 vojtech Exp $
+ * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux
  *
- *  Copyright (c) 1999-2001 Vojtech Pavlik
+ *  Copyright (c) 1999-2004 	Vojtech Pavlik <vojtech@suse.cz>
+ *  Copyright (c) 2004 		Peter Nelson <rufus-kernel@hackish.org>
  *
  *  Based on the work of:
  *  	Andree Borrmann		John Dahlstrom
  *  	David Kuder		Nathan Hand
  */
 
-/*
- * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux
- */
-
 /*
  * 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
@@ -72,8 +69,9 @@ __obsolete_setup("gc_3=");
 #define GC_MULTI2	5
 #define GC_N64		6
 #define GC_PSX		7
+#define GC_DDR		8
 
-#define GC_MAX		7
+#define GC_MAX		8
 
 #define GC_REFRESH_TIME	HZ/100
 
@@ -91,7 +89,8 @@ static struct gc *gc_base[3];
 static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 };
 
 static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick",
-				"Multisystem 2-button joystick", "N64 controller", "PSX controller" };
+				"Multisystem 2-button joystick", "N64 controller", "PSX controller"
+				"PSX DDR controller" };
 /*
  * N64 support.
  */
@@ -237,7 +236,7 @@ static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data)
 #define GC_PSX_RUMBLE	7		/* Rumble in Red mode */
 
 #define GC_PSX_CLOCK	0x04		/* Pin 4 */
-#define GC_PSX_COMMAND	0x01		/* Pin 1 */
+#define GC_PSX_COMMAND	0x01		/* Pin 2 */
 #define GC_PSX_POWER	0xf8		/* Pins 5-9 */
 #define GC_PSX_SELECT	0x02		/* Pin 3 */
 
@@ -253,25 +252,29 @@ __obsolete_setup("gc_psx_delay=");
 static short gc_psx_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_HAT0X, ABS_HAT0Y };
 static short gc_psx_btn[] = { BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_A, BTN_B, BTN_X, BTN_Y,
 				BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR };
+static short gc_psx_ddr_btn[] = { BTN_0, BTN_1, BTN_2, BTN_3 };
 
 /*
  * gc_psx_command() writes 8bit command and reads 8bit data from
  * the psx pad.
  */
 
-static int gc_psx_command(struct gc *gc, int b)
+static void gc_psx_command(struct gc *gc, int b, unsigned char data[GC_PSX_LENGTH])
 {
-	int i, cmd, data = 0;
+	int i, j, cmd, read;
+	for (i = 0; i < 5; i++)
+		data[i] = 0;
 
 	for (i = 0; i < 8; i++, b >>= 1) {
 		cmd = (b & 1) ? GC_PSX_COMMAND : 0;
 		parport_write_data(gc->pd->port, cmd | GC_PSX_POWER);
 		udelay(gc_psx_delay);
-		data |= ((parport_read_status(gc->pd->port) ^ 0x80) & gc->pads[GC_PSX]) ? (1 << i) : 0;
+		read = parport_read_status(gc->pd->port) ^ 0x80;
+		for (j = 0; j < 5; j++)
+			data[j] |= (read & gc_status_bit[j] & gc->pads[GC_PSX]) ? (1 << i) : 0;
 		parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER);
 		udelay(gc_psx_delay);
 	}
-	return data;
 }
 
 /*
@@ -279,30 +282,39 @@ static int gc_psx_command(struct gc *gc, int b)
  * device identifier code.
  */
 
-static int gc_psx_read_packet(struct gc *gc, unsigned char *data)
+static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_LENGTH], unsigned char id[5])
 {
-	int i, id;
+	int i, j, max_len = 0;
 	unsigned long flags;
+	unsigned char data2[5];
 
 	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);	/* Select pad */
-	udelay(gc_psx_delay * 2);
+	udelay(gc_psx_delay);
 	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_POWER);			/* Deselect, begin command */
-	udelay(gc_psx_delay * 2);
+	udelay(gc_psx_delay);
 
 	local_irq_save(flags);
 
-	gc_psx_command(gc, 0x01);							/* Access pad */
-	id = gc_psx_command(gc, 0x42);							/* Get device id */
-	if (gc_psx_command(gc, 0) == 0x5a) {						/* Okay? */
-		for (i = 0; i < GC_PSX_LEN(id) * 2; i++)
-			data[i] = gc_psx_command(gc, 0);
-	} else id = 0;
+	gc_psx_command(gc, 0x01, data2);						/* Access pad */
+	gc_psx_command(gc, 0x42, id);							/* Get device ids */
+	gc_psx_command(gc, 0, data2);							/* Dump status */
+
+	for (i =0; i < 5; i++)								/* Find the longest pad */
+		if((gc_status_bit[i] & gc->pads[GC_PSX]) && (GC_PSX_LEN(id[i]) > max_len))
+			max_len = GC_PSX_LEN(id[i]);
+
+	for (i = 0; i < max_len * 2; i++) {						/* Read in all the data */
+		gc_psx_command(gc, 0, data2);
+		for (j = 0; j < 5; j++)
+			data[j][i] = data2[j];
+	}
 
 	local_irq_restore(flags);
 
 	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);
 
-	return GC_PSX_ID(id);
+	for(i = 0; i < 5; i++)								/* Set id's to the real value */
+		id[i] = GC_PSX_ID(id[i]);
 }
 
 /*
@@ -316,6 +328,7 @@ static void gc_timer(unsigned long private)
 	struct gc *gc = (void *) private;
 	struct input_dev *dev = gc->dev;
 	unsigned char data[GC_MAX_LENGTH];
+	unsigned char data_psx[5][GC_PSX_LENGTH];
 	int i, j, s;
 
 /*
@@ -412,53 +425,72 @@ static void gc_timer(unsigned long private)
  * PSX controllers
  */
 
-	if (gc->pads[GC_PSX]) {
+	if (gc->pads[GC_PSX] || gc->pads[GC_DDR]) {
 
-		for (i = 0; i < 5; i++)
-	       		if (gc->pads[GC_PSX] & gc_status_bit[i])
-				break;
+		gc_psx_read_packet(gc, data_psx, data);
 
- 		switch (gc_psx_read_packet(gc, data)) {
+		for (i = 0; i < 5; i++) {
+	 		switch (data[i]) {
 
-			case GC_PSX_RUMBLE:
+				case GC_PSX_RUMBLE:
 
-				input_report_key(dev + i, BTN_THUMBL, ~data[0] & 0x04);
-				input_report_key(dev + i, BTN_THUMBR, ~data[0] & 0x02);
-				input_sync(dev + i);
+					input_report_key(dev + i, BTN_THUMBL, ~data_psx[i][0] & 0x04);
+					input_report_key(dev + i, BTN_THUMBR, ~data_psx[i][0] & 0x02);
 
-			case GC_PSX_NEGCON:
-			case GC_PSX_ANALOG:
+				case GC_PSX_NEGCON:
+				case GC_PSX_ANALOG:
 
-				for (j = 0; j < 4; j++)
-					input_report_abs(dev + i, gc_psx_abs[j], data[j + 2]);
+					if(gc->pads[GC_DDR] & gc_status_bit[i]) {
+						for(j = 0; j < 4; j++)
+							input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
+					} else {
+						for (j = 0; j < 4; j++)
+							input_report_abs(dev + i, gc_psx_abs[j+2], data_psx[i][j + 2]);
 
-				input_report_abs(dev + i, ABS_HAT0X, !(data[0] & 0x20) - !(data[0] & 0x80));
-				input_report_abs(dev + i, ABS_HAT0Y, !(data[0] & 0x40) - !(data[0] & 0x10));
+						input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
+						input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
+					}
 
-				for (j = 0; j < 8; j++)
-					input_report_key(dev + i, gc_psx_btn[j], ~data[1] & (1 << j));
+					for (j = 0; j < 8; j++)
+						input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
 
-				input_report_key(dev + i, BTN_START,  ~data[0] & 0x08);
-				input_report_key(dev + i, BTN_SELECT, ~data[0] & 0x01);
+					input_report_key(dev + i, BTN_START,  ~data_psx[i][0] & 0x08);
+					input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01);
 
-				input_sync(dev + i);
+					input_sync(dev + i);
 
-				break;
+					break;
 
-			case GC_PSX_NORMAL:
+				case GC_PSX_NORMAL:
+					if(gc->pads[GC_DDR] & gc_status_bit[i]) {
+						for(j = 0; j < 4; j++)
+							input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
+					} else {
+						input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
+						input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
 
-				input_report_abs(dev + i, ABS_X, 128 + !(data[0] & 0x20) * 127 - !(data[0] & 0x80) * 128);
-				input_report_abs(dev + i, ABS_Y, 128 + !(data[0] & 0x40) * 127 - !(data[0] & 0x10) * 128);
+						/* for some reason if the extra axes are left unset they drift */
+						/* for (j = 0; j < 4; j++)
+							input_report_abs(dev + i, gc_psx_abs[j+2], 128);
+						 * This needs to be debugged properly,
+						 * maybe fuzz processing needs to be done in input_sync()
+						 *				 --vojtech
+						 */
+					}
 
-				for (j = 0; j < 8; j++)
-					input_report_key(dev + i, gc_psx_btn[j], ~data[1] & (1 << j));
+					for (j = 0; j < 8; j++)
+						input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
 
-				input_report_key(dev + i, BTN_START,  ~data[0] & 0x08);
-				input_report_key(dev + i, BTN_SELECT, ~data[0] & 0x01);
+					input_report_key(dev + i, BTN_START,  ~data_psx[i][0] & 0x08);
+					input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01);
 
-				input_sync(dev + i);
+					input_sync(dev + i);
 
-				break;
+					break;
+
+				case 0: /* not a pad, ignore */
+					break;
+			}
 		}
 	}
 
@@ -490,8 +522,7 @@ static struct gc __init *gc_probe(int *config, int nargs)
 {
 	struct gc *gc;
 	struct parport *pp;
-	int i, j, psx;
-	unsigned char data[32];
+	int i, j;
 
 	if (config[0] < 0)
 		return NULL;
@@ -588,43 +619,22 @@ static struct gc __init *gc_probe(int *config, int nargs)
 				break;
 
 			case GC_PSX:
-
-				psx = gc_psx_read_packet(gc, data);
-
-				switch(psx) {
-					case GC_PSX_NEGCON:
-					case GC_PSX_NORMAL:
-					case GC_PSX_ANALOG:
-					case GC_PSX_RUMBLE:
-
-						for (j = 0; j < 6; j++) {
-							psx = gc_psx_abs[j];
-							set_bit(psx, gc->dev[i].absbit);
-							if (j < 4) {
-								gc->dev[i].absmin[psx] = 4;
-								gc->dev[i].absmax[psx] = 252;
-								gc->dev[i].absflat[psx] = 2;
-							} else {
-								gc->dev[i].absmin[psx] = -1;
-								gc->dev[i].absmax[psx] = 1;
-							}
-						}
-
-						for (j = 0; j < 12; j++)
-							set_bit(gc_psx_btn[j], gc->dev[i].keybit);
-
-						break;
-
-					case 0:
-						gc->pads[GC_PSX] &= ~gc_status_bit[i];
-						printk(KERN_ERR "gamecon.c: No PSX controller found.\n");
-						break;
-
-					default:
-						gc->pads[GC_PSX] &= ~gc_status_bit[i];
-						printk(KERN_WARNING "gamecon.c: Unsupported PSX controller %#x,"
-							" please report to <vojtech@ucw.cz>.\n", psx);
+			case GC_DDR:
+				if(config[i + 1] == GC_DDR) {
+					for (j = 0; j < 4; j++)
+						set_bit(gc_psx_ddr_btn[j], gc->dev[i].keybit);
+				} else {
+					for (j = 0; j < 6; j++) {
+						set_bit(gc_psx_abs[j], gc->dev[i].absbit);
+						gc->dev[i].absmin[gc_psx_abs[j]] = 4;
+						gc->dev[i].absmax[gc_psx_abs[j]] = 252;
+						gc->dev[i].absflat[gc_psx_abs[j]] = 2;
+					}
 				}
+
+				for (j = 0; j < 12; j++)
+					set_bit(gc_psx_btn[j], gc->dev[i].keybit);
+
 				break;
 		}
 
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
index 8e1949683..849d0de04 100644
--- a/drivers/input/joystick/grip_mp.c
+++ b/drivers/input/joystick/grip_mp.c
@@ -107,6 +107,8 @@ static const int init_seq[] = {
 
 static int axis_map[] = { 5, 9, 1, 5, 6, 10, 2, 6, 4, 8, 0, 4, 5, 9, 1, 5 };
 
+static void register_slot(int i, struct grip_mp *grip);
+
 /*
  * Returns whether an odd or even number of bits are on in pkt.
  */
@@ -355,7 +357,6 @@ static int get_and_decode_packet(struct grip_mp *grip, int flags)
 	u32 packet;
 	int joytype = 0;
 	int slot = 0;
-	static void register_slot(int i, struct grip_mp *grip);
 
 	/* Get a packet and check for validity */
 
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index 71cb7db75..cf815c7ee 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -524,7 +524,7 @@ static int __init iforce_init(void)
 	usb_register(&iforce_usb_driver);
 #endif
 #ifdef CONFIG_JOYSTICK_IFORCE_232
-	serio_register_device(&iforce_serio_dev);
+	serio_register_driver(&iforce_serio_drv);
 #endif
 	return 0;
 }
@@ -535,7 +535,7 @@ static void __exit iforce_exit(void)
 	usb_deregister(&iforce_usb_driver);
 #endif
 #ifdef CONFIG_JOYSTICK_IFORCE_232
-	serio_unregister_device(&iforce_serio_dev);
+	serio_unregister_driver(&iforce_serio_drv);
 #endif
 }
 
diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c
index 0665b5460..9422407c2 100644
--- a/drivers/input/joystick/iforce/iforce-serio.c
+++ b/drivers/input/joystick/iforce/iforce-serio.c
@@ -124,7 +124,7 @@ out:
 	return IRQ_HANDLED;
 }
 
-static void iforce_serio_connect(struct serio *serio, struct serio_dev *dev)
+static void iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct iforce *iforce;
 	if (serio->type != (SERIO_RS232 | SERIO_IFORCE))
@@ -137,7 +137,7 @@ static void iforce_serio_connect(struct serio *serio, struct serio_dev *dev)
 	iforce->serio = serio;
 	serio->private = iforce;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(iforce);
 		return;
 	}
@@ -158,9 +158,13 @@ static void iforce_serio_disconnect(struct serio *serio)
 	kfree(iforce);
 }
 
-struct serio_dev iforce_serio_dev = {
-	.write_wakeup =	iforce_serio_write_wakeup,
-	.interrupt =	iforce_serio_irq,
-	.connect =	iforce_serio_connect,
-	.disconnect =	iforce_serio_disconnect,
+struct serio_driver iforce_serio_drv = {
+	.driver		= {
+		.name	= "iforce",
+	},
+	.description	= "RS232 I-Force joysticks and wheels driver",
+	.write_wakeup	= iforce_serio_write_wakeup,
+	.interrupt	= iforce_serio_irq,
+	.connect	= iforce_serio_connect,
+	.disconnect	= iforce_serio_disconnect,
 };
diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h
index a8586abf5..bce247bc3 100644
--- a/drivers/input/joystick/iforce/iforce.h
+++ b/drivers/input/joystick/iforce/iforce.h
@@ -187,5 +187,5 @@ int iforce_upload_constant(struct iforce*, struct ff_effect*, int is_update);
 int iforce_upload_condition(struct iforce*, struct ff_effect*, int is_update);
 
 /* Public variables */
-extern struct serio_dev iforce_serio_dev;
+extern struct serio_driver iforce_serio_drv;
 extern struct usb_driver iforce_usb_driver;
diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c
index f326299b4..2b303bac5 100644
--- a/drivers/input/joystick/magellan.c
+++ b/drivers/input/joystick/magellan.c
@@ -35,8 +35,10 @@
 #include <linux/serio.h>
 #include <linux/init.h>
 
+#define DRIVER_DESC	"Magellan and SpaceMouse 6dof controller driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Magellan and SpaceMouse 6dof controller driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -146,7 +148,7 @@ static void magellan_disconnect(struct serio *serio)
  * it as an input device.
  */
 
-static void magellan_connect(struct serio *serio, struct serio_dev *dev)
+static void magellan_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct magellan *magellan;
 	int i, t;
@@ -184,7 +186,7 @@ static void magellan_connect(struct serio *serio, struct serio_dev *dev)
 
 	serio->private = magellan;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(magellan);
 		return;
 	}
@@ -199,10 +201,14 @@ static void magellan_connect(struct serio *serio, struct serio_dev *dev)
  * The serio device structure.
  */
 
-static struct serio_dev magellan_dev = {
-	.interrupt =	magellan_interrupt,
-	.connect =	magellan_connect,
-	.disconnect =	magellan_disconnect,
+static struct serio_driver magellan_drv = {
+	.driver		= {
+		.name	= "magellan",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= magellan_interrupt,
+	.connect	= magellan_connect,
+	.disconnect	= magellan_disconnect,
 };
 
 /*
@@ -211,13 +217,13 @@ static struct serio_dev magellan_dev = {
 
 int __init magellan_init(void)
 {
-	serio_register_device(&magellan_dev);
+	serio_register_driver(&magellan_drv);
 	return 0;
 }
 
 void __exit magellan_exit(void)
 {
-	serio_unregister_device(&magellan_dev);
+	serio_unregister_driver(&magellan_drv);
 }
 
 module_init(magellan_init);
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
index eb5b6f76c..40412528e 100644
--- a/drivers/input/joystick/spaceball.c
+++ b/drivers/input/joystick/spaceball.c
@@ -39,8 +39,10 @@
 #include <linux/input.h>
 #include <linux/serio.h>
 
+#define DRIVER_DESC	"SpaceTec SpaceBall 2003/3003/4000 FLX driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("SpaceTec SpaceBall 2003/3003/4000 FLX driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -201,7 +203,7 @@ static void spaceball_disconnect(struct serio *serio)
  * it as an input device.
  */
 
-static void spaceball_connect(struct serio *serio, struct serio_dev *dev)
+static void spaceball_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct spaceball *spaceball;
 	int i, t, id;
@@ -254,7 +256,7 @@ static void spaceball_connect(struct serio *serio, struct serio_dev *dev)
 
 	serio->private = spaceball;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(spaceball);
 		return;
 	}
@@ -269,10 +271,14 @@ static void spaceball_connect(struct serio *serio, struct serio_dev *dev)
  * The serio device structure.
  */
 
-static struct serio_dev spaceball_dev = {
-	.interrupt =	spaceball_interrupt,
-	.connect =	spaceball_connect,
-	.disconnect =	spaceball_disconnect,
+static struct serio_driver spaceball_drv = {
+	.driver		= {
+		.name	= "spaceball",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= spaceball_interrupt,
+	.connect	= spaceball_connect,
+	.disconnect	= spaceball_disconnect,
 };
 
 /*
@@ -281,13 +287,13 @@ static struct serio_dev spaceball_dev = {
 
 int __init spaceball_init(void)
 {
-	serio_register_device(&spaceball_dev);
+	serio_register_driver(&spaceball_drv);
 	return 0;
 }
 
 void __exit spaceball_exit(void)
 {
-	serio_unregister_device(&spaceball_dev);
+	serio_unregister_driver(&spaceball_drv);
 }
 
 module_init(spaceball_init);
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c
index 00da66c4b..c20091a6e 100644
--- a/drivers/input/joystick/spaceorb.c
+++ b/drivers/input/joystick/spaceorb.c
@@ -38,8 +38,10 @@
 #include <linux/input.h>
 #include <linux/serio.h>
 
+#define DRIVER_DESC	"SpaceTec SpaceOrb 360 and Avenger 6dof controller driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("SpaceTec SpaceOrb 360 and Avenger 6dof controller driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -162,7 +164,7 @@ static void spaceorb_disconnect(struct serio *serio)
  * it as an input device.
  */
 
-static void spaceorb_connect(struct serio *serio, struct serio_dev *dev)
+static void spaceorb_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct spaceorb *spaceorb;
 	int i, t;
@@ -201,7 +203,7 @@ static void spaceorb_connect(struct serio *serio, struct serio_dev *dev)
 
 	serio->private = spaceorb;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(spaceorb);
 		return;
 	}
@@ -213,10 +215,14 @@ static void spaceorb_connect(struct serio *serio, struct serio_dev *dev)
  * The serio device structure.
  */
 
-static struct serio_dev spaceorb_dev = {
-	.interrupt =	spaceorb_interrupt,
-	.connect =	spaceorb_connect,
-	.disconnect =	spaceorb_disconnect,
+static struct serio_driver spaceorb_drv = {
+	.driver		= {
+		.name	= "spaceorb",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= spaceorb_interrupt,
+	.connect	= spaceorb_connect,
+	.disconnect	= spaceorb_disconnect,
 };
 
 /*
@@ -225,13 +231,13 @@ static struct serio_dev spaceorb_dev = {
 
 int __init spaceorb_init(void)
 {
-	serio_register_device(&spaceorb_dev);
+	serio_register_driver(&spaceorb_drv);
 	return 0;
 }
 
 void __exit spaceorb_exit(void)
 {
-	serio_unregister_device(&spaceorb_dev);
+	serio_unregister_driver(&spaceorb_drv);
 }
 
 module_init(spaceorb_init);
diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c
index ce9be4563..580e32375 100644
--- a/drivers/input/joystick/stinger.c
+++ b/drivers/input/joystick/stinger.c
@@ -36,8 +36,10 @@
 #include <linux/serio.h>
 #include <linux/init.h>
 
+#define DRIVER_DESC	"Gravis Stinger gamepad driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Gravis Stinger gamepad driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -134,7 +136,7 @@ static void stinger_disconnect(struct serio *serio)
  * it as an input device.
  */
 
-static void stinger_connect(struct serio *serio, struct serio_dev *dev)
+static void stinger_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct stinger *stinger;
 	int i;
@@ -172,7 +174,7 @@ static void stinger_connect(struct serio *serio, struct serio_dev *dev)
 	stinger->dev.private = stinger;
 	serio->private = stinger;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(stinger);
 		return;
 	}
@@ -187,10 +189,14 @@ static void stinger_connect(struct serio *serio, struct serio_dev *dev)
  * The serio device structure.
  */
 
-static struct serio_dev stinger_dev = {
-	.interrupt =	stinger_interrupt,
-	.connect =	stinger_connect,
-	.disconnect =	stinger_disconnect,
+static struct serio_driver stinger_drv = {
+	.driver		= {
+		.name	= "stinger",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= stinger_interrupt,
+	.connect	= stinger_connect,
+	.disconnect	= stinger_disconnect,
 };
 
 /*
@@ -199,13 +205,13 @@ static struct serio_dev stinger_dev = {
 
 int __init stinger_init(void)
 {
-	serio_register_device(&stinger_dev);
+	serio_register_driver(&stinger_drv);
 	return 0;
 }
 
 void __exit stinger_exit(void)
 {
-	serio_unregister_device(&stinger_dev);
+	serio_unregister_driver(&stinger_drv);
 }
 
 module_init(stinger_init);
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
index 6ed46ec46..e11d29148 100644
--- a/drivers/input/joystick/tmdc.c
+++ b/drivers/input/joystick/tmdc.c
@@ -322,7 +322,7 @@ static void tmdc_connect(struct gameport *gameport, struct gameport_dev *dev)
 			tmdc->dev[j].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
 			for (i = 0; i < models[m].abs && i < TMDC_ABS; i++) {
-				if (tmdc->abs[i] < 0) continue;
+				if (tmdc->abs[j][i] < 0) continue;
 				set_bit(tmdc->abs[j][i], tmdc->dev[j].absbit);
 				tmdc->dev[j].absmin[tmdc->abs[j][i]] = 8;
 				tmdc->dev[j].absmax[tmdc->abs[j][i]] = 248;
diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c
index eb5c935a6..909b6b54a 100644
--- a/drivers/input/joystick/twidjoy.c
+++ b/drivers/input/joystick/twidjoy.c
@@ -187,7 +187,7 @@ static void twidjoy_disconnect(struct serio *serio)
  * it as an input device.
  */
 
-static void twidjoy_connect(struct serio *serio, struct serio_dev *dev)
+static void twidjoy_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct twidjoy_button_spec *bp;
 	struct twidjoy *twidjoy;
@@ -232,7 +232,7 @@ static void twidjoy_connect(struct serio *serio, struct serio_dev *dev)
 	twidjoy->dev.private = twidjoy;
 	serio->private = twidjoy;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(twidjoy);
 		return;
 	}
@@ -246,10 +246,14 @@ static void twidjoy_connect(struct serio *serio, struct serio_dev *dev)
  * The serio device structure.
  */
 
-static struct serio_dev twidjoy_dev = {
-	.interrupt =	twidjoy_interrupt,
-	.connect =	twidjoy_connect,
-	.disconnect =	twidjoy_disconnect,
+static struct serio_driver twidjoy_drv = {
+	.driver		= {
+		.name	= "twidjoy",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= twidjoy_interrupt,
+	.connect	= twidjoy_connect,
+	.disconnect	= twidjoy_disconnect,
 };
 
 /*
@@ -258,13 +262,13 @@ static struct serio_dev twidjoy_dev = {
 
 int __init twidjoy_init(void)
 {
-	serio_register_device(&twidjoy_dev);
+	serio_register_driver(&twidjoy_drv);
 	return 0;
 }
 
 void __exit twidjoy_exit(void)
 {
-	serio_unregister_device(&twidjoy_dev);
+	serio_unregister_driver(&twidjoy_drv);
 }
 
 module_init(twidjoy_init);
diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c
index 32ec90e81..5f19b2a51 100644
--- a/drivers/input/joystick/warrior.c
+++ b/drivers/input/joystick/warrior.c
@@ -35,8 +35,10 @@
 #include <linux/serio.h>
 #include <linux/init.h>
 
+#define DRIVER_DESC	"Logitech WingMan Warrior joystick driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Logitech WingMan Warrior joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -139,7 +141,7 @@ static void warrior_disconnect(struct serio *serio)
  * it as an input device.
  */
 
-static void warrior_connect(struct serio *serio, struct serio_dev *dev)
+static void warrior_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct warrior *warrior;
 	int i;
@@ -185,7 +187,7 @@ static void warrior_connect(struct serio *serio, struct serio_dev *dev)
 
 	serio->private = warrior;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(warrior);
 		return;
 	}
@@ -199,10 +201,14 @@ static void warrior_connect(struct serio *serio, struct serio_dev *dev)
  * The serio device structure.
  */
 
-static struct serio_dev warrior_dev = {
-	.interrupt =	warrior_interrupt,
-	.connect =	warrior_connect,
-	.disconnect =	warrior_disconnect,
+static struct serio_driver warrior_drv = {
+	.driver		= {
+		.name	= "warrior",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= warrior_interrupt,
+	.connect	= warrior_connect,
+	.disconnect	= warrior_disconnect,
 };
 
 /*
@@ -211,13 +217,13 @@ static struct serio_dev warrior_dev = {
 
 int __init warrior_init(void)
 {
-	serio_register_device(&warrior_dev);
+	serio_register_driver(&warrior_drv);
 	return 0;
 }
 
 void __exit warrior_exit(void)
 {
-	serio_unregister_device(&warrior_dev);
+	serio_unregister_driver(&warrior_drv);
 }
 
 module_init(warrior_init);
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 00ec1f86a..ec97ae7d5 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -27,8 +27,10 @@
 #include <linux/serio.h>
 #include <linux/workqueue.h>
 
+#define DRIVER_DESC	"AT and PS/2 keyboard driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("AT and PS/2 keyboard driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 static int atkbd_set = 2;
@@ -47,6 +49,10 @@ static int atkbd_softrepeat;
 module_param_named(softrepeat, atkbd_softrepeat, bool, 0);
 MODULE_PARM_DESC(softrepeat, "Use software keyboard repeat");
 
+static int atkbd_softraw = 1;
+module_param_named(softraw, atkbd_softraw, bool, 0);
+MODULE_PARM_DESC(softraw, "Use software generated rawmode");
+
 static int atkbd_scroll;
 module_param_named(scroll, atkbd_scroll, bool, 0);
 MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards");
@@ -164,36 +170,64 @@ static unsigned char atkbd_scroll_keys[5][2] = {
 	{ ATKBD_SCR_CLICK, 0x60 },
 };
 
+#define ATKBD_FLAG_ACK		0	/* Waiting for ACK/NAK */
+#define ATKBD_FLAG_CMD		1	/* Waiting for command to finish */
+#define ATKBD_FLAG_CMD1		2	/* First byte of command response */
+#define ATKBD_FLAG_ENABLED	3	/* Waining for init to finish */
+
 /*
  * The atkbd control structure
  */
 
 struct atkbd {
-	unsigned char keycode[512];
-	struct input_dev dev;
-	struct serio *serio;
 
+	/* Written only during init */
 	char name[64];
 	char phys[32];
-	unsigned short id;
+	struct serio *serio;
+	struct input_dev dev;
+
 	unsigned char set;
-	unsigned int translated:1;
-	unsigned int extra:1;
-	unsigned int write:1;
+	unsigned short id;
+	unsigned char keycode[512];
+	unsigned char translated;
+	unsigned char extra;
+	unsigned char write;
+
+	/* Protected by FLAG_ACK */
+	unsigned char nak;
 
+	/* Protected by FLAG_CMD */
 	unsigned char cmdbuf[4];
 	unsigned char cmdcnt;
-	volatile signed char ack;
-	unsigned char emul;
-	unsigned int resend:1;
-	unsigned int release:1;
-	unsigned int bat_xl:1;
-	unsigned int enabled:1;
 
+	/* Accessed only from interrupt */
+	unsigned char emul;
+	unsigned char resend;
+	unsigned char release;
+	unsigned char bat_xl;
 	unsigned int last;
 	unsigned long time;
+
+	/* Ensures that only one command is executing at a time */
+	struct semaphore cmd_sem;
+
+	/* Used to signal completion from interrupt handler */
+	wait_queue_head_t wait;
+
+	/* Flags */
+	unsigned long flags;
+};
+
+/* Work structure to schedule execution of a command */
+struct atkbd_work {
+	struct work_struct work;
+	struct atkbd *atkbd;
+	int command;
+	unsigned char param[0];
 };
 
+
 static void atkbd_report_key(struct input_dev *dev, struct pt_regs *regs, int code, int value)
 {
 	input_regs(dev, regs);
@@ -224,7 +258,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
 
 #if !defined(__i386__) && !defined (__x86_64__)
 	if ((flags & (SERIO_FRAME | SERIO_PARITY)) && (~flags & SERIO_TIMEOUT) && !atkbd->resend && atkbd->write) {
-		printk("atkbd.c: frame/parity error: %02x\n", flags);
+		printk(KERN_WARNING "atkbd.c: frame/parity error: %02x\n", flags);
 		serio_write(serio, ATKBD_CMD_RESEND);
 		atkbd->resend = 1;
 		goto out;
@@ -234,24 +268,46 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
 		atkbd->resend = 0;
 #endif
 
-	if (!atkbd->ack)
+	if (test_bit(ATKBD_FLAG_ACK, &atkbd->flags)) {
 		switch (code) {
 			case ATKBD_RET_ACK:
-				atkbd->ack = 1;
-				goto out;
+				atkbd->nak = 0;
+				if (atkbd->cmdcnt) {
+					set_bit(ATKBD_FLAG_CMD, &atkbd->flags);
+					set_bit(ATKBD_FLAG_CMD1, &atkbd->flags);
+				}
+				clear_bit(ATKBD_FLAG_ACK, &atkbd->flags);
+				wake_up_interruptible(&atkbd->wait);
+				break;
 			case ATKBD_RET_NAK:
-				atkbd->ack = -1;
-				goto out;
+				atkbd->nak = 1;
+				clear_bit(ATKBD_FLAG_ACK, &atkbd->flags);
+				wake_up_interruptible(&atkbd->wait);
+				break;
 		}
+		goto out;
+	}
+
+	if (test_bit(ATKBD_FLAG_CMD, &atkbd->flags)) {
+
+		if (atkbd->cmdcnt)
+			atkbd->cmdbuf[--atkbd->cmdcnt] = code;
 
-	if (atkbd->cmdcnt) {
-		atkbd->cmdbuf[--atkbd->cmdcnt] = code;
+		if (test_and_clear_bit(ATKBD_FLAG_CMD1, &atkbd->flags) && atkbd->cmdcnt)
+			wake_up_interruptible(&atkbd->wait);
+
+		if (!atkbd->cmdcnt) {
+			clear_bit(ATKBD_FLAG_CMD, &atkbd->flags);
+			wake_up_interruptible(&atkbd->wait);
+		}
 		goto out;
 	}
 
-	if (!atkbd->enabled)
+	if (!test_bit(ATKBD_FLAG_ENABLED, &atkbd->flags))
 		goto out;
 
+	input_event(&atkbd->dev, EV_MSC, MSC_RAW, code);
+
 	if (atkbd->translated) {
 
 		if (atkbd->emul ||
@@ -270,6 +326,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
 
 	switch (code) {
 		case ATKBD_RET_BAT:
+			clear_bit(ATKBD_FLAG_ENABLED, &atkbd->flags);
 			serio_rescan(atkbd->serio);
 			goto out;
 		case ATKBD_RET_EMUL0:
@@ -300,6 +357,9 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
 		code |= (atkbd->set != 3) ? 0x80 : 0x100;
 	}
 
+	if (atkbd->keycode[code] != ATKBD_KEY_NULL)
+		input_event(&atkbd->dev, EV_MSC, MSC_SCAN, code);
+
 	switch (atkbd->keycode[code]) {
 		case ATKBD_KEY_NULL:
 			break;
@@ -372,83 +432,147 @@ out:
  * acknowledge. It doesn't handle resends according to the keyboard
  * protocol specs, because if these are needed, the keyboard needs
  * replacement anyway, and they only make a mess in the protocol.
+ *
+ * atkbd_sendbyte() can only be called from a process context
  */
 
 static int atkbd_sendbyte(struct atkbd *atkbd, unsigned char byte)
 {
-	int timeout = 20000; /* 200 msec */
-	atkbd->ack = 0;
-
 #ifdef ATKBD_DEBUG
 	printk(KERN_DEBUG "atkbd.c: Sent: %02x\n", byte);
 #endif
-	if (serio_write(atkbd->serio, byte))
-		return -1;
+	atkbd->nak = 1;
+	set_bit(ATKBD_FLAG_ACK, &atkbd->flags);
 
-	while (!atkbd->ack && timeout--) udelay(10);
+	if (serio_write(atkbd->serio, byte) == 0)
+		wait_event_interruptible_timeout(atkbd->wait,
+				!test_bit(ATKBD_FLAG_ACK, &atkbd->flags),
+				msecs_to_jiffies(200));
 
-	return -(atkbd->ack <= 0);
+	clear_bit(ATKBD_FLAG_ACK, &atkbd->flags);
+	return -atkbd->nak;
 }
 
 /*
  * atkbd_command() sends a command, and its parameters to the keyboard,
  * then waits for the response and puts it in the param array.
+ *
+ * atkbd_command() can only be called from a process context
  */
 
 static int atkbd_command(struct atkbd *atkbd, unsigned char *param, int command)
 {
-	int timeout = 500000; /* 500 msec */
+	int timeout;
 	int send = (command >> 12) & 0xf;
 	int receive = (command >> 8) & 0xf;
+	int rc = -1;
 	int i;
 
-	atkbd->cmdcnt = receive;
+	timeout = msecs_to_jiffies(command == ATKBD_CMD_RESET_BAT ? 4000 : 500);
 
-	if (command == ATKBD_CMD_RESET_BAT)
-		timeout = 2000000; /* 2 sec */
+	down(&atkbd->cmd_sem);
+	clear_bit(ATKBD_FLAG_CMD, &atkbd->flags);
 
 	if (receive && param)
 		for (i = 0; i < receive; i++)
 			atkbd->cmdbuf[(receive - 1) - i] = param[i];
 
+	atkbd->cmdcnt = receive;
+
 	if (command & 0xff)
 		if (atkbd_sendbyte(atkbd, command & 0xff))
-			return (atkbd->cmdcnt = 0) - 1;
+			goto out;
 
 	for (i = 0; i < send; i++)
 		if (atkbd_sendbyte(atkbd, param[i]))
-			return (atkbd->cmdcnt = 0) - 1;
-
-	while (atkbd->cmdcnt && timeout--) {
-
-		if (atkbd->cmdcnt == 1 &&
-		    command == ATKBD_CMD_RESET_BAT && timeout > 100000)
-			timeout = 100000;
+			goto out;
 
-		if (atkbd->cmdcnt == 1 && command == ATKBD_CMD_GETID &&
-		    atkbd->cmdbuf[1] != 0xab && atkbd->cmdbuf[1] != 0xac) {
+	timeout = wait_event_interruptible_timeout(atkbd->wait,
+				!test_bit(ATKBD_FLAG_CMD1, &atkbd->flags), timeout);
+
+	if (atkbd->cmdcnt && timeout > 0) {
+		if (command == ATKBD_CMD_RESET_BAT && jiffies_to_msecs(timeout) > 100)
+			timeout = msecs_to_jiffies(100);
+
+		if (command == ATKBD_CMD_GETID &&
+		    atkbd->cmdbuf[receive - 1] != 0xab && atkbd->cmdbuf[receive - 1] != 0xac) {
+			/*
+			 * Device behind the port is not a keyboard
+			 * so we don't need to wait for the 2nd byte
+			 * of ID response.
+			 */
+			clear_bit(ATKBD_FLAG_CMD, &atkbd->flags);
 			atkbd->cmdcnt = 0;
-			break;
 		}
 
-		udelay(1);
+		wait_event_interruptible_timeout(atkbd->wait,
+				!test_bit(ATKBD_FLAG_CMD, &atkbd->flags), timeout);
 	}
 
 	if (param)
 		for (i = 0; i < receive; i++)
 			param[i] = atkbd->cmdbuf[(receive - 1) - i];
 
-	if (command == ATKBD_CMD_RESET_BAT && atkbd->cmdcnt == 1)
-		atkbd->cmdcnt = 0;
+	if (atkbd->cmdcnt && (command != ATKBD_CMD_RESET_BAT || atkbd->cmdcnt != 1))
+		goto out;
+
+	rc = 0;
+
+out:
+	clear_bit(ATKBD_FLAG_CMD, &atkbd->flags);
+	clear_bit(ATKBD_FLAG_CMD1, &atkbd->flags);
+	up(&atkbd->cmd_sem);
+
+	return rc;
+}
+
+/*
+ * atkbd_execute_scheduled_command() sends a command, previously scheduled by
+ * atkbd_schedule_command(), to the keyboard.
+ */
+
+static void atkbd_execute_scheduled_command(void *data)
+{
+	struct atkbd_work *atkbd_work = data;
+
+	atkbd_command(atkbd_work->atkbd, atkbd_work->param, atkbd_work->command);
+
+	kfree(atkbd_work);
+}
+
+/*
+ * atkbd_schedule_command() allows to schedule delayed execution of a keyboard
+ * command and can be used to issue a command from an interrupt or softirq
+ * context.
+ */
+
+static int atkbd_schedule_command(struct atkbd *atkbd, unsigned char *param, int command)
+{
+	struct atkbd_work *atkbd_work;
+	int send = (command >> 12) & 0xf;
+	int receive = (command >> 8) & 0xf;
+
+	if (!test_bit(ATKBD_FLAG_ENABLED, &atkbd->flags))
+		return -1;
+
+	if (!(atkbd_work = kmalloc(sizeof(struct atkbd_work) + max(send, receive), GFP_ATOMIC)))
+		return -1;
+
+	memset(atkbd_work, 0, sizeof(struct atkbd_work));
+	atkbd_work->atkbd = atkbd;
+	atkbd_work->command = command;
+	memcpy(atkbd_work->param, param, send);
+	INIT_WORK(&atkbd_work->work, atkbd_execute_scheduled_command, atkbd_work);
 
-	if (atkbd->cmdcnt) {
-		atkbd->cmdcnt = 0;
+	if (!schedule_work(&atkbd_work->work)) {
+		kfree(atkbd_work);
 		return -1;
 	}
 
 	return 0;
 }
 
+
 /*
  * Event callback from the input module. Events that change the state of
  * the hardware are processed here.
@@ -475,7 +599,7 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
 			param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0)
 			         | (test_bit(LED_NUML,    dev->led) ? 2 : 0)
 			         | (test_bit(LED_CAPSL,   dev->led) ? 4 : 0);
-		        atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS);
+		        atkbd_schedule_command(atkbd, param, ATKBD_CMD_SETLEDS);
 
 			if (atkbd->extra) {
 				param[0] = 0;
@@ -484,7 +608,7 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
 					 | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0)
 				         | (test_bit(LED_MISC,    dev->led) ? 0x10 : 0)
 				         | (test_bit(LED_MUTE,    dev->led) ? 0x20 : 0);
-				atkbd_command(atkbd, param, ATKBD_CMD_EX_SETLEDS);
+				atkbd_schedule_command(atkbd, param, ATKBD_CMD_EX_SETLEDS);
 			}
 
 			return 0;
@@ -500,7 +624,7 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
 			dev->rep[REP_PERIOD] = period[i];
 			dev->rep[REP_DELAY] = delay[j];
 			param[0] = i | (j << 5);
-			atkbd_command(atkbd, param, ATKBD_CMD_SETREP);
+			atkbd_schedule_command(atkbd, param, ATKBD_CMD_SETREP);
 
 			return 0;
 	}
@@ -672,6 +796,11 @@ static void atkbd_cleanup(struct serio *serio)
 static void atkbd_disconnect(struct serio *serio)
 {
 	struct atkbd *atkbd = serio->private;
+
+	clear_bit(ATKBD_FLAG_ENABLED, &atkbd->flags);
+	synchronize_kernel();
+	flush_scheduled_work();
+
 	input_unregister_device(&atkbd->dev);
 	serio_close(serio);
 	kfree(atkbd);
@@ -684,7 +813,7 @@ static void atkbd_disconnect(struct serio *serio)
  * to the input module.
  */
 
-static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
+static void atkbd_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct atkbd *atkbd;
 	int i;
@@ -693,6 +822,9 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
 		return;
 	memset(atkbd, 0, sizeof(struct atkbd));
 
+	init_MUTEX(&atkbd->cmd_sem);
+	init_waitqueue_head(&atkbd->wait);
+
 	switch (serio->type & SERIO_TYPE) {
 
 		case SERIO_8042_XL:
@@ -709,17 +841,22 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
 			return;
 	}
 
+	if (!atkbd->write)
+		atkbd_softrepeat = 1;
+	if (atkbd_softrepeat)
+		atkbd_softraw = 1;
+
 	if (atkbd->write) {
-		atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
+		atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP) | BIT(EV_MSC);
 		atkbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
-	} else  atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+	} else  atkbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_MSC);
+	atkbd->dev.mscbit[0] = atkbd_softraw ? BIT(MSC_SCAN) : BIT(MSC_RAW) | BIT(MSC_SCAN);
 
 	if (!atkbd_softrepeat) {
 		atkbd->dev.rep[REP_DELAY] = 250;
 		atkbd->dev.rep[REP_PERIOD] = 33;
-	}
+	} else atkbd_softraw = 1;
 
-	atkbd->ack = 1;
 	atkbd->serio = serio;
 
 	init_input_dev(&atkbd->dev);
@@ -732,7 +869,7 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
 
 	serio->private = atkbd;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(atkbd);
 		return;
 	}
@@ -754,8 +891,6 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
 		atkbd->id = 0xab00;
 	}
 
-	atkbd->enabled = 1;
-
 	if (atkbd->extra) {
 		atkbd->dev.ledbit[0] |= BIT(LED_COMPOSE) | BIT(LED_SUSPEND) | BIT(LED_SLEEP) | BIT(LED_MUTE) | BIT(LED_MISC);
 		sprintf(atkbd->name, "AT Set 2 Extra keyboard");
@@ -797,6 +932,8 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
 
 	input_register_device(&atkbd->dev);
 
+	set_bit(ATKBD_FLAG_ENABLED, &atkbd->flags);
+
 	printk(KERN_INFO "input: %s on %s\n", atkbd->name, serio->phys);
 }
 
@@ -808,10 +945,10 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
 static int atkbd_reconnect(struct serio *serio)
 {
 	struct atkbd *atkbd = serio->private;
-	struct serio_dev *dev = serio->dev;
+	struct serio_driver *drv = serio->drv;
 	unsigned char param[1];
 
-	if (!dev) {
+	if (!drv) {
 		printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
 		return -1;
 	}
@@ -832,26 +969,32 @@ static int atkbd_reconnect(struct serio *serio)
 			return -1;
 	}
 
+	set_bit(ATKBD_FLAG_ENABLED, &atkbd->flags);
+
 	return 0;
 }
 
-static struct serio_dev atkbd_dev = {
-	.interrupt =	atkbd_interrupt,
-	.connect =	atkbd_connect,
-	.reconnect = 	atkbd_reconnect,
-	.disconnect =	atkbd_disconnect,
-	.cleanup =	atkbd_cleanup,
+static struct serio_driver atkbd_drv = {
+	.driver		= {
+		.name	= "atkbd",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= atkbd_interrupt,
+	.connect	= atkbd_connect,
+	.reconnect	= atkbd_reconnect,
+	.disconnect	= atkbd_disconnect,
+	.cleanup	= atkbd_cleanup,
 };
 
 int __init atkbd_init(void)
 {
-	serio_register_device(&atkbd_dev);
+	serio_register_driver(&atkbd_drv);
 	return 0;
 }
 
 void __exit atkbd_exit(void)
 {
-	serio_unregister_device(&atkbd_dev);
+	serio_unregister_driver(&atkbd_drv);
 }
 
 module_init(atkbd_init);
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c
index 8dc51e296..a04cf3efd 100644
--- a/drivers/input/keyboard/lkkbd.c
+++ b/drivers/input/keyboard/lkkbd.c
@@ -76,8 +76,10 @@
 #include <linux/serio.h>
 #include <linux/workqueue.h>
 
+#define DRIVER_DESC	"LK keyboard driver"
+
 MODULE_AUTHOR ("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
-MODULE_DESCRIPTION ("LK keyboard driver");
+MODULE_DESCRIPTION (DRIVER_DESC);
 MODULE_LICENSE ("GPL");
 
 /*
@@ -622,7 +624,7 @@ lkkbd_reinit (void *data)
  * lkkbd_connect() probes for a LK keyboard and fills the necessary structures.
  */
 static void
-lkkbd_connect (struct serio *serio, struct serio_dev *dev)
+lkkbd_connect (struct serio *serio, struct serio_driver *drv)
 {
 	struct lkkbd *lk;
 	int i;
@@ -665,7 +667,7 @@ lkkbd_connect (struct serio *serio, struct serio_dev *dev)
 
 	serio->private = lk;
 
-	if (serio_open (serio, dev)) {
+	if (serio_open (serio, drv)) {
 		kfree (lk);
 		return;
 	}
@@ -703,10 +705,14 @@ lkkbd_disconnect (struct serio *serio)
 	kfree (lk);
 }
 
-static struct serio_dev lkkbd_dev = {
-	.connect = lkkbd_connect,
-	.disconnect = lkkbd_disconnect,
-	.interrupt = lkkbd_interrupt,
+static struct serio_driver lkkbd_drv = {
+	.driver		= {
+		.name	= "lkkbd",
+	},
+	.description	= DRIVER_DESC,
+	.connect	= lkkbd_connect,
+	.disconnect	= lkkbd_disconnect,
+	.interrupt	= lkkbd_interrupt,
 };
 
 /*
@@ -715,14 +721,14 @@ static struct serio_dev lkkbd_dev = {
 int __init
 lkkbd_init (void)
 {
-	serio_register_device (&lkkbd_dev);
+	serio_register_driver(&lkkbd_drv);
 	return 0;
 }
 
 void __exit
 lkkbd_exit (void)
 {
-	serio_unregister_device (&lkkbd_dev);
+	serio_unregister_driver(&lkkbd_drv);
 }
 
 module_init (lkkbd_init);
diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c
index dc47acb0a..caa92dd8b 100644
--- a/drivers/input/keyboard/newtonkbd.c
+++ b/drivers/input/keyboard/newtonkbd.c
@@ -32,8 +32,10 @@
 #include <linux/init.h>
 #include <linux/serio.h>
 
+#define DRIVER_DESC	"Newton keyboard driver"
+
 MODULE_AUTHOR("Justin Cormack <j.cormack@doc.ic.ac.uk>");
-MODULE_DESCRIPTION("Newton keyboard driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 #define NKBD_KEY	0x7f
@@ -82,7 +84,7 @@ irqreturn_t nkbd_interrupt(struct serio *serio,
 
 }
 
-void nkbd_connect(struct serio *serio, struct serio_dev *dev)
+void nkbd_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct nkbd *nkbd;
 	int i;
@@ -106,7 +108,7 @@ void nkbd_connect(struct serio *serio, struct serio_dev *dev)
 	nkbd->dev.private = nkbd;
 	serio->private = nkbd;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(nkbd);
 		return;
 	}
@@ -138,21 +140,25 @@ void nkbd_disconnect(struct serio *serio)
 	kfree(nkbd);
 }
 
-struct serio_dev nkbd_dev = {
-	.interrupt =	nkbd_interrupt,
-	.connect =	nkbd_connect,
-	.disconnect =	nkbd_disconnect
+struct serio_driver nkbd_drv = {
+	.driver		= {
+		.name	= "newtonkbd",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= nkbd_interrupt,
+	.connect	= nkbd_connect,
+	.disconnect	= nkbd_disconnect,
 };
 
 int __init nkbd_init(void)
 {
-	serio_register_device(&nkbd_dev);
+	serio_register_driver(&nkbd_drv);
 	return 0;
 }
 
 void __exit nkbd_exit(void)
 {
-	serio_unregister_device(&nkbd_dev);
+	serio_unregister_driver(&nkbd_drv);
 }
 
 module_init(nkbd_init);
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index c281e726b..7f0342c56 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -37,8 +37,10 @@
 #include <linux/serio.h>
 #include <linux/workqueue.h>
 
+#define DRIVER_DESC	"Sun keyboard driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Sun keyboard driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 static unsigned char sunkbd_keycode[128] = {
@@ -221,7 +223,7 @@ static void sunkbd_reinit(void *data)
  * sunkbd_connect() probes for a Sun keyboard and fills the necessary structures.
  */
 
-static void sunkbd_connect(struct serio *serio, struct serio_dev *dev)
+static void sunkbd_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct sunkbd *sunkbd;
 	int i;
@@ -257,7 +259,7 @@ static void sunkbd_connect(struct serio *serio, struct serio_dev *dev)
 
 	serio->private = sunkbd;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(sunkbd);
 		return;
 	}
@@ -301,10 +303,14 @@ static void sunkbd_disconnect(struct serio *serio)
 	kfree(sunkbd);
 }
 
-static struct serio_dev sunkbd_dev = {
-	.interrupt =	sunkbd_interrupt,
-	.connect =	sunkbd_connect,
-	.disconnect =	sunkbd_disconnect
+static struct serio_driver sunkbd_drv = {
+	.driver		= {
+		.name	= "sunkbd",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= sunkbd_interrupt,
+	.connect	= sunkbd_connect,
+	.disconnect	= sunkbd_disconnect,
 };
 
 /*
@@ -313,13 +319,13 @@ static struct serio_dev sunkbd_dev = {
 
 int __init sunkbd_init(void)
 {
-	serio_register_device(&sunkbd_dev);
+	serio_register_driver(&sunkbd_drv);
 	return 0;
 }
 
 void __exit sunkbd_exit(void)
 {
-	serio_unregister_device(&sunkbd_dev);
+	serio_unregister_driver(&sunkbd_drv);
 }
 
 module_init(sunkbd_init);
diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c
index 56adfa1cc..eb8a9b72b 100644
--- a/drivers/input/keyboard/xtkbd.c
+++ b/drivers/input/keyboard/xtkbd.c
@@ -34,8 +34,10 @@
 #include <linux/init.h>
 #include <linux/serio.h>
 
+#define DRIVER_DESC	"XT keyboard driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("XT keyboard driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 #define XTKBD_EMUL0	0xe0
@@ -86,7 +88,7 @@ irqreturn_t xtkbd_interrupt(struct serio *serio,
 	return IRQ_HANDLED;
 }
 
-void xtkbd_connect(struct serio *serio, struct serio_dev *dev)
+void xtkbd_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct xtkbd *xtkbd;
 	int i;
@@ -111,7 +113,7 @@ void xtkbd_connect(struct serio *serio, struct serio_dev *dev)
 
 	serio->private = xtkbd;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(xtkbd);
 		return;
 	}
@@ -143,21 +145,25 @@ void xtkbd_disconnect(struct serio *serio)
 	kfree(xtkbd);
 }
 
-struct serio_dev xtkbd_dev = {
-	.interrupt =	xtkbd_interrupt,
-	.connect =	xtkbd_connect,
-	.disconnect =	xtkbd_disconnect
+struct serio_driver xtkbd_drv = {
+	.driver		= {
+		.name	= "xtkbd",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= xtkbd_interrupt,
+	.connect	= xtkbd_connect,
+	.disconnect	= xtkbd_disconnect,
 };
 
 int __init xtkbd_init(void)
 {
-	serio_register_device(&xtkbd_dev);
+	serio_register_driver(&xtkbd_drv);
 	return 0;
 }
 
 void __exit xtkbd_exit(void)
 {
-	serio_unregister_device(&xtkbd_dev);
+	serio_unregister_driver(&xtkbd_drv);
 }
 
 module_init(xtkbd_init);
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index d3e5d841e..a89050e12 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -14,7 +14,7 @@ config INPUT_MISC
 
 config INPUT_PCSPKR
 	tristate "PC Speaker support"
-	depends on (ALPHA || X86 || X86_64 || MIPS) && INPUT && INPUT_MISC
+	depends on (ALPHA || X86 || X86_64 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES) && INPUT && INPUT_MISC
 	help
 	  Say Y here if you want the standard PC Speaker to be used for
 	  bells and whistles.
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index b86acf04d..477579b9e 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -279,6 +279,9 @@ static unsigned int uinput_poll(struct file *file, poll_table *wait)
 {
 	struct uinput_device *udev = file->private_data;
 
+	if (!test_bit(UIST_CREATED, &(udev->state)))
+		return 0;
+
 	poll_wait(file, &udev->waitq, wait);
 
 	if (udev->head != udev->tail)
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 1274cb68b..bd2744fa2 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -30,8 +30,6 @@ config MOUSE_PS2
 	  and a new verion of GPM at:
 		http://www.geocities.com/dt_or/gpm/gpm.html
 	  to take advantage of the advanced features of the touchpad.
-	  If you do not want install specialized drivers but want tapping
-	  working please use option psmouse.proto=imps.
 
 	  If unsure, say Y.
 
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index 0063af037..6af1455fd 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -277,7 +277,7 @@ int ps2pp_init(struct psmouse *psmouse, int set_properties)
 				protocol = PSMOUSE_PS2TPP;
 			}
 
-		} else if (get_model_info(model) != NULL) {
+		} else if (model_info != NULL) {
 
 			param[0] = param[1] = param[2] = 0;
 			ps2pp_cmd(psmouse, param, 0x39); /* Magic knock */
diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c
index 526a11e70..fa8cff3df 100644
--- a/drivers/input/mouse/pc110pad.c
+++ b/drivers/input/mouse/pc110pad.c
@@ -109,9 +109,9 @@ static int pc110pad_open(struct input_dev *dev)
 
 static int __init pc110pad_init(void)
 {
-	if (request_region(pc110pad_io, 4, "pc110pad"))
-	{
-		printk(KERN_ERR "pc110pad: I/O area %#x-%#x in use.\n", pc110pad_io, pc110pad_io + 4);
+	if (!request_region(pc110pad_io, 4, "pc110pad")) {
+		printk(KERN_ERR "pc110pad: I/O area %#x-%#x in use.\n",
+				pc110pad_io, pc110pad_io + 4);
 		return -EBUSY;
 	}
 
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 0b3826724..7fbd926dd 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -22,8 +22,10 @@
 #include "synaptics.h"
 #include "logips2pp.h"
 
+#define DRIVER_DESC	"PS/2 mouse driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("PS/2 mouse driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 static char *psmouse_proto;
@@ -142,37 +144,67 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
 			printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n",
 				flags & SERIO_TIMEOUT ? " timeout" : "",
 				flags & SERIO_PARITY ? " bad parity" : "");
-		if (psmouse->acking) {
-			psmouse->ack = -1;
-			psmouse->acking = 0;
-		}
-		psmouse->pktcnt = 0;
+		psmouse->nak = 1;
+		clear_bit(PSMOUSE_FLAG_ACK, &psmouse->flags);
+		clear_bit(PSMOUSE_FLAG_CMD,  &psmouse->flags);
+		wake_up_interruptible(&psmouse->wait);
 		goto out;
 	}
 
-	if (psmouse->acking) {
+	if (test_bit(PSMOUSE_FLAG_ACK, &psmouse->flags)) {
 		switch (data) {
 			case PSMOUSE_RET_ACK:
-				psmouse->ack = 1;
+				psmouse->nak = 0;
 				break;
+
 			case PSMOUSE_RET_NAK:
-				psmouse->ack = -1;
+				psmouse->nak = 1;
 				break;
+
+			/*
+			 * Workaround for mice which don't ACK the Get ID command.
+			 * These are valid mouse IDs that we recognize.
+			 */
+			case 0x00:
+			case 0x03:
+			case 0x04:
+				if (test_bit(PSMOUSE_FLAG_WAITID, &psmouse->flags)) {
+					psmouse->nak = 0;
+					break;
+				}
+				/* Fall through */
 			default:
-				psmouse->ack = 1;	/* Workaround for mice which don't ACK the Get ID command */
-				if (psmouse->cmdcnt)
-					psmouse->cmdbuf[--psmouse->cmdcnt] = data;
-				break;
+				goto out;
 		}
-		psmouse->acking = 0;
-		goto out;
+
+		if (!psmouse->nak && psmouse->cmdcnt) {
+			set_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
+			set_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags);
+		}
+		clear_bit(PSMOUSE_FLAG_ACK, &psmouse->flags);
+		wake_up_interruptible(&psmouse->wait);
+
+		if (data == PSMOUSE_RET_ACK || data == PSMOUSE_RET_NAK)
+			goto out;
 	}
 
-	if (psmouse->cmdcnt) {
-		psmouse->cmdbuf[--psmouse->cmdcnt] = data;
+	if (test_bit(PSMOUSE_FLAG_CMD, &psmouse->flags)) {
+		if (psmouse->cmdcnt)
+			psmouse->cmdbuf[--psmouse->cmdcnt] = data;
+
+		if (test_and_clear_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags) && psmouse->cmdcnt)
+			wake_up_interruptible(&psmouse->wait);
+
+		if (!psmouse->cmdcnt) {
+			clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
+			wake_up_interruptible(&psmouse->wait);
+		}
 		goto out;
 	}
 
+	if (psmouse->state == PSMOUSE_INITIALIZING)
+		goto out;
+
 	if (psmouse->state == PSMOUSE_ACTIVATED &&
 	    psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) {
 		printk(KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n",
@@ -238,78 +270,96 @@ out:
  * psmouse_sendbyte() sends a byte to the mouse, and waits for acknowledge.
  * It doesn't handle retransmission, though it could - because when there would
  * be need for retransmissions, the mouse has to be replaced anyway.
+ *
+ * psmouse_sendbyte() can only be called from a process context
  */
 
 static int psmouse_sendbyte(struct psmouse *psmouse, unsigned char byte)
 {
-	int timeout = 10000; /* 100 msec */
-	psmouse->ack = 0;
-	psmouse->acking = 1;
-
-	if (serio_write(psmouse->serio, byte)) {
-		psmouse->acking = 0;
-		return -1;
-	}
+	psmouse->nak = 1;
+	set_bit(PSMOUSE_FLAG_ACK, &psmouse->flags);
 
-	while (!psmouse->ack && timeout--) udelay(10);
+	if (serio_write(psmouse->serio, byte) == 0)
+		wait_event_interruptible_timeout(psmouse->wait,
+				!test_bit(PSMOUSE_FLAG_ACK, &psmouse->flags),
+				msecs_to_jiffies(200));
 
-	return -(psmouse->ack <= 0);
+	clear_bit(PSMOUSE_FLAG_ACK, &psmouse->flags);
+	return -psmouse->nak;
 }
 
 /*
  * psmouse_command() sends a command and its parameters to the mouse,
  * then waits for the response and puts it in the param array.
+ *
+ * psmouse_command() can only be called from a process context
  */
 
 int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
 {
-	int timeout = 500000; /* 500 msec */
+	int timeout;
 	int send = (command >> 12) & 0xf;
 	int receive = (command >> 8) & 0xf;
+	int rc = -1;
 	int i;
 
-	psmouse->cmdcnt = receive;
+	timeout = msecs_to_jiffies(command == PSMOUSE_CMD_RESET_BAT ? 4000 : 500);
 
-	if (command == PSMOUSE_CMD_RESET_BAT)
-                timeout = 4000000; /* 4 sec */
+	clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
+	if (command == PSMOUSE_CMD_GETID)
+		set_bit(PSMOUSE_FLAG_WAITID, &psmouse->flags);
 
-	/* initialize cmdbuf with preset values from param */
-	if (receive)
-	   for (i = 0; i < receive; i++)
-		psmouse->cmdbuf[(receive - 1) - i] = param[i];
+	if (receive && param)
+		for (i = 0; i < receive; i++)
+			psmouse->cmdbuf[(receive - 1) - i] = param[i];
+
+	psmouse->cmdcnt = receive;
 
 	if (command & 0xff)
 		if (psmouse_sendbyte(psmouse, command & 0xff))
-			return (psmouse->cmdcnt = 0) - 1;
+			goto out;
 
 	for (i = 0; i < send; i++)
 		if (psmouse_sendbyte(psmouse, param[i]))
-			return (psmouse->cmdcnt = 0) - 1;
-
-	while (psmouse->cmdcnt && timeout--) {
-
-		if (psmouse->cmdcnt == 1 && command == PSMOUSE_CMD_RESET_BAT &&
-				timeout > 100000) /* do not run in a endless loop */
-			timeout = 100000; /* 1 sec */
+			goto out;
 
-		if (psmouse->cmdcnt == 1 && command == PSMOUSE_CMD_GETID &&
-		    psmouse->cmdbuf[1] != 0xab && psmouse->cmdbuf[1] != 0xac) {
+	timeout = wait_event_interruptible_timeout(psmouse->wait,
+				!test_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags), timeout);
+
+	if (psmouse->cmdcnt && timeout > 0) {
+		if (command == PSMOUSE_CMD_RESET_BAT && jiffies_to_msecs(timeout) > 100)
+			timeout = msecs_to_jiffies(100);
+
+		if (command == PSMOUSE_CMD_GETID &&
+		    psmouse->cmdbuf[receive - 1] != 0xab && psmouse->cmdbuf[receive - 1] != 0xac) {
+			/*
+			 * Device behind the port is not a keyboard
+			 * so we don't need to wait for the 2nd byte
+			 * of ID response.
+			 */
+			clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
 			psmouse->cmdcnt = 0;
-			break;
 		}
 
-		udelay(1);
+		wait_event_interruptible_timeout(psmouse->wait,
+				!test_bit(PSMOUSE_FLAG_CMD, &psmouse->flags), timeout);
 	}
 
-	for (i = 0; i < receive; i++)
-		param[i] = psmouse->cmdbuf[(receive - 1) - i];
+	if (param)
+		for (i = 0; i < receive; i++)
+			param[i] = psmouse->cmdbuf[(receive - 1) - i];
 
-	if (psmouse->cmdcnt)
-		return (psmouse->cmdcnt = 0) - 1;
+	if (psmouse->cmdcnt && (command != PSMOUSE_CMD_RESET_BAT || psmouse->cmdcnt != 1))
+		goto out;
 
-	return 0;
-}
+	rc = 0;
 
+out:
+	clear_bit(PSMOUSE_FLAG_CMD, &psmouse->flags);
+	clear_bit(PSMOUSE_FLAG_CMD1, &psmouse->flags);
+	clear_bit(PSMOUSE_FLAG_WAITID, &psmouse->flags);
+	return rc;
+}
 
 /*
  * psmouse_sliced_command() sends an extended PS/2 command to the mouse
@@ -394,6 +444,8 @@ static int im_explorer_detect(struct psmouse *psmouse)
 {
 	unsigned char param[2];
 
+	intellimouse_detect(psmouse);
+
 	param[0] = 200;
 	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
 	param[0] = 200;
@@ -597,6 +649,21 @@ static void psmouse_initialize(struct psmouse *psmouse)
 	psmouse_command(psmouse, param, PSMOUSE_CMD_SETSTREAM);
 }
 
+/*
+ * psmouse_set_state() sets new psmouse state and resets all flags and
+ * counters while holding serio lock so fighting with interrupt handler
+ * is not a concern.
+ */
+
+static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state)
+{
+	serio_pause_rx(psmouse->serio);
+	psmouse->state = new_state;
+	psmouse->pktcnt = psmouse->cmdcnt = psmouse->out_of_sync = 0;
+	psmouse->flags = 0;
+	serio_continue_rx(psmouse->serio);
+}
+
 /*
  * psmouse_activate() enables the mouse so that we get motion reports from it.
  */
@@ -606,9 +673,24 @@ static void psmouse_activate(struct psmouse *psmouse)
 	if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_ENABLE))
 		printk(KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n", psmouse->serio->phys);
 
-	psmouse->state = PSMOUSE_ACTIVATED;
+	psmouse_set_state(psmouse, PSMOUSE_ACTIVATED);
+}
+
+
+/*
+ * psmouse_deactivate() puts the mouse into poll mode so that we don't get motion
+ * reports from it unless we explicitely request it.
+ */
+
+static void psmouse_deactivate(struct psmouse *psmouse)
+{
+	if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_DISABLE))
+		printk(KERN_WARNING "psmouse.c: Failed to deactivate mouse on %s\n", psmouse->serio->phys);
+
+	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
 }
 
+
 /*
  * psmouse_cleanup() resets the mouse into power-on state.
  */
@@ -626,22 +708,21 @@ static void psmouse_cleanup(struct serio *serio)
 
 static void psmouse_disconnect(struct serio *serio)
 {
-	struct psmouse *psmouse = serio->private;
+	struct psmouse *psmouse, *parent;
 
-	psmouse->state = PSMOUSE_CMD_MODE;
+	psmouse = serio->private;
+	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
 
-	if (psmouse->ptport) {
-		if (psmouse->ptport->deactivate)
-			psmouse->ptport->deactivate(psmouse);
-		__serio_unregister_port(&psmouse->ptport->serio); /* we have serio_sem */
-		kfree(psmouse->ptport);
-		psmouse->ptport = NULL;
+	if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) {
+		parent = serio->parent->private;
+		if (parent->pt_deactivate)
+			parent->pt_deactivate(parent);
 	}
 
 	if (psmouse->disconnect)
 		psmouse->disconnect(psmouse);
 
-	psmouse->state = PSMOUSE_IGNORE;
+	psmouse_set_state(psmouse, PSMOUSE_IGNORE);
 
 	input_unregister_device(&psmouse->dev);
 	serio_close(serio);
@@ -652,39 +733,49 @@ static void psmouse_disconnect(struct serio *serio)
  * psmouse_connect() is a callback from the serio module when
  * an unhandled serio port is found.
  */
-static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
+static void psmouse_connect(struct serio *serio, struct serio_driver *drv)
 {
-	struct psmouse *psmouse;
+	struct psmouse *psmouse, *parent = NULL;
 
 	if ((serio->type & SERIO_TYPE) != SERIO_8042 &&
 	    (serio->type & SERIO_TYPE) != SERIO_PS_PSTHRU)
 		return;
 
+	/*
+	 * If this is a pass-through port deactivate parent so the device
+	 * connected to this port can be successfully identified
+	 */
+	if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) {
+		parent = serio->parent->private;
+		psmouse_deactivate(parent);
+	}
+
 	if (!(psmouse = kmalloc(sizeof(struct psmouse), GFP_KERNEL)))
-		return;
+		goto out;
 
 	memset(psmouse, 0, sizeof(struct psmouse));
 
+	init_waitqueue_head(&psmouse->wait);
 	init_input_dev(&psmouse->dev);
 	psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
 	psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
 	psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
-	psmouse->state = PSMOUSE_CMD_MODE;
 	psmouse->serio = serio;
 	psmouse->dev.private = psmouse;
+	psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
 
 	serio->private = psmouse;
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(psmouse);
 		serio->private = NULL;
-		return;
+		goto out;
 	}
 
 	if (psmouse_probe(psmouse) < 0) {
 		serio_close(serio);
 		kfree(psmouse);
 		serio->private = NULL;
-		return;
+		goto out;
 	}
 
 	psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1);
@@ -711,63 +802,88 @@ static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
 
 	printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys);
 
+	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
+
 	psmouse_initialize(psmouse);
 
-	if (psmouse->ptport) {
-		printk(KERN_INFO "serio: %s port at %s\n", psmouse->ptport->serio.name, psmouse->phys);
-		__serio_register_port(&psmouse->ptport->serio); /* we have serio_sem */
-		if (psmouse->ptport->activate)
-			psmouse->ptport->activate(psmouse);
+	if (parent && parent->pt_activate)
+		parent->pt_activate(parent);
+
+	if (serio->child) {
+		/*
+		 * Nothing to be done here, serio core will detect that
+		 * the driver set serio->child and will register it for us.
+		 */
+		printk(KERN_INFO "serio: %s port at %s\n", serio->child->name, psmouse->phys);
 	}
 
 	psmouse_activate(psmouse);
+
+out:
+	/* If this is a pass-through port the parent awaits to be activated */
+	if (parent)
+		psmouse_activate(parent);
 }
 
 
 static int psmouse_reconnect(struct serio *serio)
 {
 	struct psmouse *psmouse = serio->private;
-	struct serio_dev *dev = serio->dev;
+	struct psmouse *parent = NULL;
+	struct serio_driver *drv = serio->drv;
+	int rc = -1;
 
-	if (!dev || !psmouse) {
+	if (!drv || !psmouse) {
 		printk(KERN_DEBUG "psmouse: reconnect request, but serio is disconnected, ignoring...\n");
 		return -1;
 	}
 
-	psmouse->state = PSMOUSE_CMD_MODE;
-	psmouse->acking = psmouse->cmdcnt = psmouse->pktcnt = psmouse->out_of_sync = 0;
+	if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) {
+		parent = serio->parent->private;
+		psmouse_deactivate(parent);
+	}
+
+	psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
+
 	if (psmouse->reconnect) {
 	       if (psmouse->reconnect(psmouse))
-			return -1;
+			goto out;
 	} else if (psmouse_probe(psmouse) < 0 ||
 		   psmouse->type != psmouse_extensions(psmouse, psmouse_max_proto, 0))
-		return -1;
+		goto out;
 
 	/* ok, the device type (and capabilities) match the old one,
 	 * we can continue using it, complete intialization
 	 */
+	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
+
 	psmouse_initialize(psmouse);
 
-	if (psmouse->ptport) {
-       		if (psmouse_reconnect(&psmouse->ptport->serio)) {
-			__serio_unregister_port(&psmouse->ptport->serio);
-			__serio_register_port(&psmouse->ptport->serio);
-			if (psmouse->ptport->activate)
-				psmouse->ptport->activate(psmouse);
-		}
-	}
+	if (parent && parent->pt_activate)
+		parent->pt_activate(parent);
 
 	psmouse_activate(psmouse);
-	return 0;
+	rc = 0;
+
+out:
+	/* If this is a pass-through port the parent waits to be activated */
+	if (parent)
+		psmouse_activate(parent);
+
+	return rc;
 }
 
 
-static struct serio_dev psmouse_dev = {
-	.interrupt =	psmouse_interrupt,
-	.connect =	psmouse_connect,
-	.reconnect =	psmouse_reconnect,
-	.disconnect =	psmouse_disconnect,
-	.cleanup =	psmouse_cleanup,
+static struct serio_driver psmouse_drv = {
+	.driver		= {
+		.name	= "psmouse",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= psmouse_interrupt,
+	.connect	= psmouse_connect,
+	.reconnect	= psmouse_reconnect,
+	.disconnect	= psmouse_disconnect,
+	.cleanup	= psmouse_cleanup,
 };
 
 static inline void psmouse_parse_proto(void)
@@ -787,13 +903,13 @@ static inline void psmouse_parse_proto(void)
 int __init psmouse_init(void)
 {
 	psmouse_parse_proto();
-	serio_register_device(&psmouse_dev);
+	serio_register_driver(&psmouse_drv);
 	return 0;
 }
 
 void __exit psmouse_exit(void)
 {
-	serio_unregister_device(&psmouse_dev);
+	serio_unregister_driver(&psmouse_drv);
 }
 
 module_init(psmouse_init);
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index 47fbc48f6..20bbab42d 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -9,6 +9,7 @@
 #define PSMOUSE_CMD_GETID	0x02f2
 #define PSMOUSE_CMD_SETRATE	0x10f3
 #define PSMOUSE_CMD_ENABLE	0x00f4
+#define PSMOUSE_CMD_DISABLE	0x00f5
 #define PSMOUSE_CMD_RESET_DIS	0x00f6
 #define PSMOUSE_CMD_RESET_BAT	0x02ff
 
@@ -17,10 +18,17 @@
 #define PSMOUSE_RET_ACK		0xfa
 #define PSMOUSE_RET_NAK		0xfe
 
-/* psmouse states */
-#define PSMOUSE_CMD_MODE	0
-#define PSMOUSE_ACTIVATED	1
-#define PSMOUSE_IGNORE		2
+#define PSMOUSE_FLAG_ACK	0	/* Waiting for ACK/NAK */
+#define PSMOUSE_FLAG_CMD	1	/* Waiting for command to finish */
+#define PSMOUSE_FLAG_CMD1	2	/* Waiting for the first byte of command response */
+#define PSMOUSE_FLAG_WAITID	3	/* Command execiting is GET ID */
+
+enum psmouse_state {
+	PSMOUSE_IGNORE,
+	PSMOUSE_INITIALIZING,
+	PSMOUSE_CMD_MODE,
+	PSMOUSE_ACTIVATED,
+};
 
 /* psmouse protocol handler return codes */
 typedef enum {
@@ -29,20 +37,10 @@ typedef enum {
 	PSMOUSE_FULL_PACKET
 } psmouse_ret_t;
 
-struct psmouse;
-
-struct psmouse_ptport {
-	struct serio serio;
-
-	void (*activate)(struct psmouse *parent);
-	void (*deactivate)(struct psmouse *parent);
-};
-
 struct psmouse {
 	void *private;
 	struct input_dev dev;
 	struct serio *serio;
-	struct psmouse_ptport *ptport;
 	char *vendor;
 	char *name;
 	unsigned char cmdbuf[8];
@@ -53,16 +51,22 @@ struct psmouse {
 	unsigned char model;
 	unsigned long last;
 	unsigned long out_of_sync;
-	unsigned char state;
-	char acking;
-	volatile char ack;
+	enum psmouse_state state;
+	unsigned char nak;
 	char error;
 	char devname[64];
 	char phys[32];
+	unsigned long flags;
 
-	psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs); 
+	/* Used to signal completion from interrupt handler */
+	wait_queue_head_t wait;
+
+	psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs);
 	int (*reconnect)(struct psmouse *psmouse);
 	void (*disconnect)(struct psmouse *psmouse);
+
+	void (*pt_activate)(struct psmouse *psmouse);
+	void (*pt_deactivate)(struct psmouse *psmouse);
 };
 
 #define PSMOUSE_PS2		1
diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c
index 9c97a0a40..e1db6e078 100644
--- a/drivers/input/mouse/sermouse.c
+++ b/drivers/input/mouse/sermouse.c
@@ -37,8 +37,10 @@
 #include <linux/serio.h>
 #include <linux/init.h>
 
+#define DRIVER_DESC	"Serial mouse driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Serial mouse driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 static char *sermouse_protocols[] = { "None", "Mouse Systems Mouse", "Sun Mouse", "Microsoft Mouse",
@@ -237,7 +239,7 @@ static void sermouse_disconnect(struct serio *serio)
  * an unhandled serio port is found.
  */
 
-static void sermouse_connect(struct serio *serio, struct serio_dev *dev)
+static void sermouse_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct sermouse *sermouse;
 	unsigned char c;
@@ -279,7 +281,7 @@ static void sermouse_connect(struct serio *serio, struct serio_dev *dev)
 	sermouse->dev.id.product = c;
 	sermouse->dev.id.version = 0x0100;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(sermouse);
 		return;
 	}
@@ -289,21 +291,25 @@ static void sermouse_connect(struct serio *serio, struct serio_dev *dev)
 	printk(KERN_INFO "input: %s on %s\n", sermouse_protocols[sermouse->type], serio->phys);
 }
 
-static struct serio_dev sermouse_dev = {
-	.interrupt =	sermouse_interrupt,
-	.connect =	sermouse_connect,
-	.disconnect =	sermouse_disconnect
+static struct serio_driver sermouse_drv = {
+	.driver		= {
+		.name	= "sermouse",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= sermouse_interrupt,
+	.connect	= sermouse_connect,
+	.disconnect	= sermouse_disconnect,
 };
 
 int __init sermouse_init(void)
 {
-	serio_register_device(&sermouse_dev);
+	serio_register_driver(&sermouse_drv);
 	return 0;
 }
 
 void __exit sermouse_exit(void)
 {
-	serio_unregister_device(&sermouse_dev);
+	serio_unregister_driver(&sermouse_drv);
 }
 
 module_init(sermouse_init);
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 2bd152fe0..101b80947 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -212,9 +212,9 @@ static int synaptics_set_mode(struct psmouse *psmouse, int mode)
 /*****************************************************************************
  *	Synaptics pass-through PS/2 port support
  ****************************************************************************/
-static int synaptics_pt_write(struct serio *port, unsigned char c)
+static int synaptics_pt_write(struct serio *serio, unsigned char c)
 {
-	struct psmouse *parent = port->driver;
+	struct psmouse *parent = serio->parent->private;
 	char rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */
 
 	if (psmouse_sliced_command(parent, c))
@@ -233,22 +233,19 @@ static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet
 {
 	struct psmouse *child = ptport->private;
 
-	if (child) {
-		if (child->state == PSMOUSE_ACTIVATED) {
-			serio_interrupt(ptport, packet[1], 0, NULL);
-			serio_interrupt(ptport, packet[4], 0, NULL);
-			serio_interrupt(ptport, packet[5], 0, NULL);
-			if (child->type >= PSMOUSE_GENPS)
-				serio_interrupt(ptport, packet[2], 0, NULL);
-		} else if (child->state != PSMOUSE_IGNORE) {
-			serio_interrupt(ptport, packet[1], 0, NULL);
-		}
-	}
+	if (child && child->state == PSMOUSE_ACTIVATED) {
+		serio_interrupt(ptport, packet[1], 0, NULL);
+		serio_interrupt(ptport, packet[4], 0, NULL);
+		serio_interrupt(ptport, packet[5], 0, NULL);
+		if (child->type >= PSMOUSE_GENPS)
+			serio_interrupt(ptport, packet[2], 0, NULL);
+	} else
+		serio_interrupt(ptport, packet[1], 0, NULL);
 }
 
 static void synaptics_pt_activate(struct psmouse *psmouse)
 {
-	struct psmouse *child = psmouse->ptport->serio.private;
+	struct psmouse *child = psmouse->serio->child->private;
 
 	/* adjust the touchpad to child's choice of protocol */
 	if (child && child->type >= PSMOUSE_GENPS) {
@@ -259,23 +256,25 @@ static void synaptics_pt_activate(struct psmouse *psmouse)
 
 static void synaptics_pt_create(struct psmouse *psmouse)
 {
-	struct psmouse_ptport *port;
+	struct serio *serio;
 
-	psmouse->ptport = port = kmalloc(sizeof(struct psmouse_ptport), GFP_KERNEL);
-	if (!port) {
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (!serio) {
 		printk(KERN_ERR "synaptics: not enough memory to allocate pass-through port\n");
 		return;
 	}
 
-	memset(port, 0, sizeof(struct psmouse_ptport));
+	memset(serio, 0, sizeof(struct serio));
+
+	serio->type = SERIO_PS_PSTHRU;
+	strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
+	strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name));
+	serio->write = synaptics_pt_write;
+	serio->parent = psmouse->serio;
 
-	port->serio.type = SERIO_PS_PSTHRU;
-	port->serio.name = "Synaptics pass-through";
-	port->serio.phys = "synaptics-pt/serio0";
-	port->serio.write = synaptics_pt_write;
-	port->serio.driver = psmouse;
+	psmouse->pt_activate = synaptics_pt_activate;
 
-	port->activate = synaptics_pt_activate;
+	psmouse->serio->child = serio;
 }
 
 /*****************************************************************************
@@ -470,9 +469,10 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse, struct pt_r
 		if (unlikely(priv->pkt_type == SYN_NEWABS))
 			priv->pkt_type = synaptics_detect_pkt_type(psmouse);
 
-		if (psmouse->ptport && psmouse->ptport->serio.dev && synaptics_is_pt_packet(psmouse->packet))
-			synaptics_pass_pt_packet(&psmouse->ptport->serio, psmouse->packet);
-		else
+		if (SYN_CAP_PASS_THROUGH(priv->capabilities) && synaptics_is_pt_packet(psmouse->packet)) {
+			if (psmouse->serio->child)
+				synaptics_pass_pt_packet(psmouse->serio->child, psmouse->packet);
+		} else
 			synaptics_process_packet(psmouse);
 
 		return PSMOUSE_FULL_PACKET;
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c
index c26d907e8..3845ca458 100644
--- a/drivers/input/mouse/vsxxxaa.c
+++ b/drivers/input/mouse/vsxxxaa.c
@@ -82,8 +82,10 @@
 #include <linux/serio.h>
 #include <linux/init.h>
 
+#define DRIVER_DESC	"Serial DEC VSXXX-AA/GA mouse / DEC tablet driver"
+
 MODULE_AUTHOR ("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
-MODULE_DESCRIPTION ("Serial DEC VSXXX-AA/GA mouse / DEC tablet driver");
+MODULE_DESCRIPTION (DRIVER_DESC);
 MODULE_LICENSE ("GPL");
 
 #undef VSXXXAA_DEBUG
@@ -482,7 +484,7 @@ vsxxxaa_disconnect (struct serio *serio)
 }
 
 static void
-vsxxxaa_connect (struct serio *serio, struct serio_dev *dev)
+vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
 {
 	struct vsxxxaa *mouse;
 
@@ -524,7 +526,7 @@ vsxxxaa_connect (struct serio *serio, struct serio_dev *dev)
 	mouse->dev.id.bustype = BUS_RS232;
 	mouse->serio = serio;
 
-	if (serio_open (serio, dev)) {
+	if (serio_open (serio, drv)) {
 		kfree (mouse);
 		return;
 	}
@@ -540,23 +542,27 @@ vsxxxaa_connect (struct serio *serio, struct serio_dev *dev)
 	printk (KERN_INFO "input: %s on %s\n", mouse->name, mouse->phys);
 }
 
-static struct serio_dev vsxxxaa_dev = {
-	.connect = vsxxxaa_connect,
-	.interrupt = vsxxxaa_interrupt,
-	.disconnect = vsxxxaa_disconnect,
+static struct serio_driver vsxxxaa_drv = {
+	.driver		= {
+		.name	= "vsxxxaa",
+	},
+	.description	= DRIVER_DESC,
+	.connect	= vsxxxaa_connect,
+	.interrupt	= vsxxxaa_interrupt,
+	.disconnect	= vsxxxaa_disconnect,
 };
 
 int __init
 vsxxxaa_init (void)
 {
-	serio_register_device (&vsxxxaa_dev);
+	serio_register_driver(&vsxxxaa_drv);
 	return 0;
 }
 
 void __exit
 vsxxxaa_exit (void)
 {
-	serio_unregister_device (&vsxxxaa_dev);
+	serio_unregister_driver(&vsxxxaa_drv);
 }
 
 module_init (vsxxxaa_init);
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index f266b7ef5..bd1a6d98b 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -48,8 +48,15 @@ static int yres = CONFIG_INPUT_MOUSEDEV_SCREEN_Y;
 module_param(yres, uint, 0);
 MODULE_PARM_DESC(yres, "Vertical screen resolution");
 
-struct mousedev_motion {
+static unsigned tap_time = 200;
+module_param(tap_time, uint, 0);
+MODULE_PARM_DESC(tap_time, "Tap time for touchpads in absolute mode (msecs)");
+
+struct mousedev_hw_data {
 	int dx, dy, dz;
+	int x, y;
+	int abs_event;
+	unsigned long buttons;
 };
 
 struct mousedev {
@@ -61,22 +68,38 @@ struct mousedev {
 	struct list_head list;
 	struct input_handle handle;
 
-	struct mousedev_motion packet;
-	unsigned long buttons;
+	struct mousedev_hw_data packet;
 	unsigned int pkt_count;
 	int old_x[4], old_y[4];
-	unsigned int touch;
+	unsigned long touch;
+};
+
+enum mousedev_emul {
+	MOUSEDEV_EMUL_PS2,
+	MOUSEDEV_EMUL_IMPS,
+	MOUSEDEV_EMUL_EXPS
 };
 
+struct mousedev_motion {
+	int dx, dy, dz;
+	unsigned long buttons;
+};
+
+#define PACKET_QUEUE_LEN	16
 struct mousedev_list {
 	struct fasync_struct *fasync;
 	struct mousedev *mousedev;
 	struct list_head node;
-	int dx, dy, dz;
-	unsigned long buttons;
+
+	struct mousedev_motion packets[PACKET_QUEUE_LEN];
+	unsigned int head, tail;
+	spinlock_t packet_lock;
+	int pos_x, pos_y;
+
 	signed char ps2[6];
 	unsigned char ready, buffer, bufsiz;
-	unsigned char mode, imexseq, impsseq;
+	unsigned char imexseq, impsseq;
+	enum mousedev_emul mode;
 };
 
 #define MOUSEDEV_SEQ_LEN	6
@@ -119,15 +142,19 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev,
 		case ABS_X:
 			size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
 			if (size == 0) size = xres;
-			mousedev->packet.dx = (value * xres - mousedev->old_x[0]) / size;
-			mousedev->old_x[0] = mousedev->packet.dx * size;
+			if (value > dev->absmax[ABS_X]) value = dev->absmax[ABS_X];
+			if (value < dev->absmin[ABS_X]) value = dev->absmin[ABS_X];
+			mousedev->packet.x = ((value - dev->absmin[ABS_X]) * xres) / size;
+			mousedev->packet.abs_event = 1;
 			break;
 
 		case ABS_Y:
 			size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y];
 			if (size == 0) size = yres;
-			mousedev->packet.dy = (value * yres - mousedev->old_y[0]) / size;
-			mousedev->old_y[0] = mousedev->packet.dy * size;
+			if (value > dev->absmax[ABS_Y]) value = dev->absmax[ABS_Y];
+			if (value < dev->absmin[ABS_Y]) value = dev->absmin[ABS_Y];
+			mousedev->packet.y = yres - ((value - dev->absmin[ABS_Y]) * yres) / size;
+			mousedev->packet.abs_event = 1;
 			break;
 	}
 }
@@ -165,30 +192,82 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int
 	}
 
 	if (value) {
-		set_bit(index, &mousedev->buttons);
-		set_bit(index, &mousedev_mix.buttons);
+		set_bit(index, &mousedev->packet.buttons);
+		set_bit(index, &mousedev_mix.packet.buttons);
 	} else {
-		clear_bit(index, &mousedev->buttons);
-		clear_bit(index, &mousedev_mix.buttons);
+		clear_bit(index, &mousedev->packet.buttons);
+		clear_bit(index, &mousedev_mix.packet.buttons);
 	}
 }
 
-static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_motion *packet)
+static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_hw_data *packet)
 {
 	struct mousedev_list *list;
+	struct mousedev_motion *p;
+	unsigned long flags;
 
 	list_for_each_entry(list, &mousedev->list, node) {
-		list->dx += packet->dx;
-		list->dy += packet->dy;
-		list->dz += packet->dz;
-		list->buttons = mousedev->buttons;
+		spin_lock_irqsave(&list->packet_lock, flags);
+
+		p = &list->packets[list->head];
+		if (list->ready && p->buttons != packet->buttons) {
+			unsigned int new_head = (list->head + 1) % PACKET_QUEUE_LEN;
+			if (new_head != list->tail) {
+				p = &list->packets[list->head = new_head];
+				memset(p, 0, sizeof(struct mousedev_motion));
+			}
+		}
+
+		if (packet->abs_event) {
+			p->dx += packet->x - list->pos_x;
+			p->dy += packet->y - list->pos_y;
+			list->pos_x = packet->x;
+			list->pos_y = packet->y;
+		}
+
+		list->pos_x += packet->dx;
+		list->pos_x = list->pos_x < 0 ? 0 : (list->pos_x >= xres ? xres : list->pos_x);
+		list->pos_y += packet->dy;
+		list->pos_y = list->pos_y < 0 ? 0 : (list->pos_y >= yres ? yres : list->pos_y);
+
+		p->dx += packet->dx;
+		p->dy += packet->dy;
+		p->dz += packet->dz;
+		p->buttons = mousedev->packet.buttons;
+
 		list->ready = 1;
+
+		spin_unlock_irqrestore(&list->packet_lock, flags);
 		kill_fasync(&list->fasync, SIGIO, POLL_IN);
 	}
 
 	wake_up_interruptible(&mousedev->wait);
 }
 
+static void mousedev_touchpad_touch(struct mousedev *mousedev, int value)
+{
+	if (!value) {
+		if (mousedev->touch &&
+		    time_before(jiffies, mousedev->touch + msecs_to_jiffies(tap_time))) {
+			/*
+			 * Toggle left button to emulate tap.
+			 * We rely on the fact that mousedev_mix always has 0
+			 * motion packet so we won't mess current position.
+			 */
+			set_bit(0, &mousedev->packet.buttons);
+			set_bit(0, &mousedev_mix.packet.buttons);
+			mousedev_notify_readers(mousedev, &mousedev_mix.packet);
+			mousedev_notify_readers(&mousedev_mix, &mousedev_mix.packet);
+			clear_bit(0, &mousedev->packet.buttons);
+			clear_bit(0, &mousedev_mix.packet.buttons);
+		}
+		mousedev->touch = mousedev->pkt_count = 0;
+	}
+	else
+		if (!mousedev->touch)
+			mousedev->touch = jiffies;
+}
+
 static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
 {
 	struct mousedev *mousedev = handle->private;
@@ -212,12 +291,8 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
 
 		case EV_KEY:
 			if (value != 2) {
-				if (code == BTN_TOUCH && test_bit(BTN_TOOL_FINGER, handle->dev->keybit)) {
-					/* Handle touchpad data */
-					mousedev->touch = value;
-					if (!mousedev->touch)
-						mousedev->pkt_count = 0;
-				}
+				if (code == BTN_TOUCH && test_bit(BTN_TOOL_FINGER, handle->dev->keybit))
+					mousedev_touchpad_touch(mousedev, value);
 				else
 					mousedev_key_event(mousedev, code, value);
 			}
@@ -237,7 +312,8 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
 				mousedev_notify_readers(mousedev, &mousedev->packet);
 				mousedev_notify_readers(&mousedev_mix, &mousedev->packet);
 
-				memset(&mousedev->packet, 0, sizeof(struct mousedev_motion));
+				mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0;
+				mousedev->packet.abs_event = 0;
 			}
 			break;
 	}
@@ -322,6 +398,9 @@ static int mousedev_open(struct inode * inode, struct file * file)
 		return -ENOMEM;
 	memset(list, 0, sizeof(struct mousedev_list));
 
+	spin_lock_init(&list->packet_lock);
+	list->pos_x = xres / 2;
+	list->pos_y = yres / 2;
 	list->mousedev = mousedev_table[i];
 	list_add_tail(&list->node, &mousedev_table[i]->list);
 	file->private_data = list;
@@ -341,32 +420,56 @@ static int mousedev_open(struct inode * inode, struct file * file)
 	return 0;
 }
 
-static void mousedev_packet(struct mousedev_list *list, unsigned char off)
+static inline int mousedev_limit_delta(int delta, int limit)
 {
-	list->ps2[off] = 0x08 | ((list->dx < 0) << 4) | ((list->dy < 0) << 5) | (list->buttons & 0x07);
-	list->ps2[off + 1] = (list->dx > 127 ? 127 : (list->dx < -127 ? -127 : list->dx));
-	list->ps2[off + 2] = (list->dy > 127 ? 127 : (list->dy < -127 ? -127 : list->dy));
-	list->dx -= list->ps2[off + 1];
-	list->dy -= list->ps2[off + 2];
-	list->bufsiz = off + 3;
-
-	if (list->mode == 2) {
-		list->ps2[off + 3] = (list->dz > 7 ? 7 : (list->dz < -7 ? -7 : list->dz));
-		list->dz -= list->ps2[off + 3];
-		list->ps2[off + 3] = (list->ps2[off + 3] & 0x0f) | ((list->buttons & 0x18) << 1);
-		list->bufsiz++;
-	} else {
-		list->ps2[off] |= ((list->buttons & 0x10) >> 3) | ((list->buttons & 0x08) >> 1);
+	return delta > limit ? limit : (delta < -limit ? -limit : delta);
+}
+
+static void mousedev_packet(struct mousedev_list *list, signed char *ps2_data)
+{
+	struct mousedev_motion *p;
+	unsigned long flags;
+
+	spin_lock_irqsave(&list->packet_lock, flags);
+	p = &list->packets[list->tail];
+
+	ps2_data[0] = 0x08 | ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07);
+	ps2_data[1] = mousedev_limit_delta(p->dx, 127);
+	ps2_data[2] = mousedev_limit_delta(p->dy, 127);
+	p->dx -= ps2_data[1];
+	p->dy -= ps2_data[2];
+
+	switch (list->mode) {
+		case MOUSEDEV_EMUL_EXPS:
+			ps2_data[3] = mousedev_limit_delta(p->dz, 127);
+			p->dz -= ps2_data[3];
+			ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1);
+			list->bufsiz = 4;
+			break;
+
+		case MOUSEDEV_EMUL_IMPS:
+			ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
+			ps2_data[3] = mousedev_limit_delta(p->dz, 127);
+			p->dz -= ps2_data[3];
+			list->bufsiz = 4;
+			break;
+
+		case MOUSEDEV_EMUL_PS2:
+		default:
+			ps2_data[0] |= ((p->buttons & 0x10) >> 3) | ((p->buttons & 0x08) >> 1);
+			p->dz = 0;
+			list->bufsiz = 3;
+			break;
 	}
 
-	if (list->mode == 1) {
-		list->ps2[off + 3] = (list->dz > 127 ? 127 : (list->dz < -127 ? -127 : list->dz));
-		list->dz -= list->ps2[off + 3];
-		list->bufsiz++;
+	if (!p->dx && !p->dy && !p->dz) {
+		if (list->tail != list->head)
+			list->tail = (list->tail + 1) % PACKET_QUEUE_LEN;
+		if (list->tail == list->head)
+			list->ready = 0;
 	}
 
-	if (!list->dx && !list->dy && (!list->mode || !list->dz)) list->ready = 0;
-	list->buffer = list->bufsiz;
+	spin_unlock_irqrestore(&list->packet_lock, flags);
 }
 
 
@@ -384,31 +487,31 @@ static ssize_t mousedev_write(struct file * file, const char __user * buffer, si
 		if (c == mousedev_imex_seq[list->imexseq]) {
 			if (++list->imexseq == MOUSEDEV_SEQ_LEN) {
 				list->imexseq = 0;
-				list->mode = 2;
+				list->mode = MOUSEDEV_EMUL_EXPS;
 			}
 		} else list->imexseq = 0;
 
 		if (c == mousedev_imps_seq[list->impsseq]) {
 			if (++list->impsseq == MOUSEDEV_SEQ_LEN) {
 				list->impsseq = 0;
-				list->mode = 1;
+				list->mode = MOUSEDEV_EMUL_IMPS;
 			}
 		} else list->impsseq = 0;
 
 		list->ps2[0] = 0xfa;
-		list->bufsiz = 1;
 
 		switch (c) {
 
 			case 0xeb: /* Poll */
-				mousedev_packet(list, 1);
+				mousedev_packet(list, &list->ps2[1]);
+				list->bufsiz++; /* account for leading ACK */
 				break;
 
 			case 0xf2: /* Get ID */
 				switch (list->mode) {
-					case 0: list->ps2[1] = 0; break;
-					case 1: list->ps2[1] = 3; break;
-					case 2: list->ps2[1] = 4; break;
+					case MOUSEDEV_EMUL_PS2:  list->ps2[1] = 0; break;
+					case MOUSEDEV_EMUL_IMPS: list->ps2[1] = 3; break;
+					case MOUSEDEV_EMUL_EXPS: list->ps2[1] = 4; break;
 				}
 				list->bufsiz = 2;
 				break;
@@ -419,13 +522,15 @@ static ssize_t mousedev_write(struct file * file, const char __user * buffer, si
 				break;
 
 			case 0xff: /* Reset */
-				list->impsseq = 0;
-				list->imexseq = 0;
-				list->mode = 0;
-				list->ps2[1] = 0xaa;
-				list->ps2[2] = 0x00;
+				list->impsseq = list->imexseq = 0;
+				list->mode = MOUSEDEV_EMUL_PS2;
+				list->ps2[1] = 0xaa; list->ps2[2] = 0x00;
 				list->bufsiz = 3;
 				break;
+
+			default:
+				list->bufsiz = 1;
+				break;
 		}
 
 		list->buffer = list->bufsiz;
@@ -446,13 +551,19 @@ static ssize_t mousedev_read(struct file * file, char __user * buffer, size_t co
 	if (!list->ready && !list->buffer && (file->f_flags & O_NONBLOCK))
 		return -EAGAIN;
 
-	retval = wait_event_interruptible(list->mousedev->wait, list->ready || list->buffer);
+	retval = wait_event_interruptible(list->mousedev->wait,
+					  !list->mousedev->exist || list->ready || list->buffer);
 
 	if (retval)
 		return retval;
 
-	if (!list->buffer && list->ready)
-		mousedev_packet(list, 0);
+	if (!list->mousedev->exist)
+		return -ENODEV;
+
+	if (!list->buffer && list->ready) {
+		mousedev_packet(list, list->ps2);
+		list->buffer = list->bufsiz;
+	}
 
 	if (count > list->buffer)
 		count = list->buffer;
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index cd74954bd..db1a8ce43 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -20,7 +20,7 @@ config SERIO_I8042
 	tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86
 	default y
 	select SERIO
-	depends on !PARISC
+	depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST)
 	---help---
 	  i8042 is the chip over which the standard AT keyboard and PS/2
 	  mouse are connected to the computer. If you use these devices,
@@ -130,3 +130,19 @@ config SERIO_MACEPS2
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called maceps2.
+
+config SERIO_RAW
+	tristate "Raw access to serio ports"
+	depends on SERIO
+	help
+	  Say Y here if you want to have raw access to serio ports, such as
+	  AUX ports on i8042 keyboard controller. Each serio port that is
+	  bound to this driver will be accessible via a char device with
+	  major 10 and dynamically allocated minor. The driver will try
+	  allocating minor 1 (that historically corresponds to /dev/psaux)
+	  first. To bind this driver to a serio port use sysfs interface:
+
+	      echo -n "serio_raw" > /sys/bus/serio/devices/serioX/driver
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called serio_raw.
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
index a47dec255..cf52b6141 100644
--- a/drivers/input/serio/Makefile
+++ b/drivers/input/serio/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_SERIO_98KBD)	+= 98kbd-io.o
 obj-$(CONFIG_SERIO_GSCPS2)	+= gscps2.o
 obj-$(CONFIG_SERIO_PCIPS2)	+= pcips2.o
 obj-$(CONFIG_SERIO_MACEPS2)	+= maceps2.o
+obj-$(CONFIG_SERIO_RAW)		+= serio_raw.o
diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c
index 6a780c10f..4b3b5135f 100644
--- a/drivers/input/serio/ambakmi.c
+++ b/drivers/input/serio/ambakmi.c
@@ -29,7 +29,7 @@
 #define KMI_BASE	(kmi->base)
 
 struct amba_kmi_port {
-	struct serio		io;
+	struct serio		*io;
 	struct clk		*clk;
 	unsigned char		*base;
 	unsigned int		irq;
@@ -44,7 +44,7 @@ static irqreturn_t amba_kmi_int(int irq, void *dev_id, struct pt_regs *regs)
 	int handled = IRQ_NONE;
 
 	while (status & KMIIR_RXINTR) {
-		serio_interrupt(&kmi->io, readb(KMIDATA), 0, regs);
+		serio_interrupt(kmi->io, readb(KMIDATA), 0, regs);
 		status = readb(KMIIR);
 		handled = IRQ_HANDLED;
 	}
@@ -54,7 +54,7 @@ static irqreturn_t amba_kmi_int(int irq, void *dev_id, struct pt_regs *regs)
 
 static int amba_kmi_write(struct serio *io, unsigned char val)
 {
-	struct amba_kmi_port *kmi = io->driver;
+	struct amba_kmi_port *kmi = io->port_data;
 	unsigned int timeleft = 10000; /* timeout in 100ms */
 
 	while ((readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && timeleft--)
@@ -68,7 +68,7 @@ static int amba_kmi_write(struct serio *io, unsigned char val)
 
 static int amba_kmi_open(struct serio *io)
 {
-	struct amba_kmi_port *kmi = io->driver;
+	struct amba_kmi_port *kmi = io->port_data;
 	unsigned int divisor;
 	int ret;
 
@@ -105,7 +105,7 @@ static int amba_kmi_open(struct serio *io)
 
 static void amba_kmi_close(struct serio *io)
 {
-	struct amba_kmi_port *kmi = io->driver;
+	struct amba_kmi_port *kmi = io->port_data;
 
 	writeb(0, KMICR);
 
@@ -117,6 +117,7 @@ static void amba_kmi_close(struct serio *io)
 static int amba_kmi_probe(struct amba_device *dev, void *id)
 {
 	struct amba_kmi_port *kmi;
+	struct serio *io;
 	int ret;
 
 	ret = amba_request_regions(dev, NULL);
@@ -124,21 +125,25 @@ static int amba_kmi_probe(struct amba_device *dev, void *id)
 		return ret;
 
 	kmi = kmalloc(sizeof(struct amba_kmi_port), GFP_KERNEL);
-	if (!kmi) {
+	io = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (!kmi || !io) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
 	memset(kmi, 0, sizeof(struct amba_kmi_port));
-
-	kmi->io.type	= SERIO_8042;
-	kmi->io.write	= amba_kmi_write;
-	kmi->io.open	= amba_kmi_open;
-	kmi->io.close	= amba_kmi_close;
-	kmi->io.name	= dev->dev.bus_id;
-	kmi->io.phys	= dev->dev.bus_id;
-	kmi->io.driver	= kmi;
-
+	memset(io, 0, sizeof(struct serio));
+
+	io->type	= SERIO_8042;
+	io->write	= amba_kmi_write;
+	io->open	= amba_kmi_open;
+	io->close	= amba_kmi_close;
+	strlcpy(io->name, dev->dev.bus_id, sizeof(io->name));
+	strlcpy(io->phys, dev->dev.bus_id, sizeof(io->phys));
+	io->port_data	= kmi;
+	io->dev.parent	= &dev->dev;
+
+	kmi->io 	= io;
 	kmi->base	= ioremap(dev->res.start, KMI_SIZE);
 	if (!kmi->base) {
 		ret = -ENOMEM;
@@ -154,13 +159,14 @@ static int amba_kmi_probe(struct amba_device *dev, void *id)
 	kmi->irq = dev->irq[0];
 	amba_set_drvdata(dev, kmi);
 
-	serio_register_port(&kmi->io);
+	serio_register_port(kmi->io);
 	return 0;
 
  unmap:
 	iounmap(kmi->base);
  out:
 	kfree(kmi);
+	kfree(io);
 	amba_release_regions(dev);
 	return ret;
 }
@@ -171,7 +177,7 @@ static int amba_kmi_remove(struct amba_device *dev)
 
 	amba_set_drvdata(dev, NULL);
 
-	serio_unregister_port(&kmi->io);
+	serio_unregister_port(kmi->io);
 	clk_put(kmi->clk);
 	iounmap(kmi->base);
 	kfree(kmi);
@@ -184,7 +190,7 @@ static int amba_kmi_resume(struct amba_device *dev)
 	struct amba_kmi_port *kmi = amba_get_drvdata(dev);
 
 	/* kick the serio layer to rescan this port */
-	serio_rescan(&kmi->io);
+	serio_reconnect(kmi->io);
 
 	return 0;
 }
@@ -214,7 +220,7 @@ static int __init amba_kmi_init(void)
 
 static void __exit amba_kmi_exit(void)
 {
-	return amba_driver_unregister(&ambakmi_driver);
+	amba_driver_unregister(&ambakmi_driver);
 }
 
 module_init(amba_kmi_init);
diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c
index 2234ff39d..ee785460b 100644
--- a/drivers/input/serio/ct82c710.c
+++ b/drivers/input/serio/ct82c710.c
@@ -36,6 +36,7 @@
 #include <linux/interrupt.h>
 #include <linux/serio.h>
 #include <linux/errno.h>
+#include <linux/err.h>
 
 #include <asm/io.h>
 
@@ -43,9 +44,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("82C710 C&T mouse port chip driver");
 MODULE_LICENSE("GPL");
 
-static char ct82c710_name[] = "C&T 82c710 mouse port";
-static char ct82c710_phys[16];
-
 /*
  * ct82c710 interface
  */
@@ -61,10 +59,22 @@ static char ct82c710_phys[16];
 
 #define CT82C710_IRQ          12
 
-static int ct82c710_data;
-static int ct82c710_status;
+#define CT82C710_DATA         ct82c710_iores.start
+#define CT82C710_STATUS       (ct82c710_iores.start + 1)
+
+static struct serio *ct82c710_port;
+static struct platform_device *ct82c710_device;
+static struct resource ct82c710_iores;
+
+/*
+ * Interrupt handler for the 82C710 mouse port. A character
+ * is waiting in the 82C710.
+ */
 
-static irqreturn_t ct82c710_interrupt(int cpl, void *dev_id, struct pt_regs * regs);
+static irqreturn_t ct82c710_interrupt(int cpl, void *dev_id, struct pt_regs * regs)
+{
+	return serio_interrupt(ct82c710_port, inb(CT82C710_DATA), 0, regs);
+}
 
 /*
  * Wait for device to send output char and flush any input char.
@@ -74,10 +84,10 @@ static int ct82c170_wait(void)
 {
 	int timeout = 60000;
 
-	while ((inb(ct82c710_status) & (CT82C710_RX_FULL | CT82C710_TX_IDLE | CT82C710_DEV_IDLE))
+	while ((inb(CT82C710_STATUS) & (CT82C710_RX_FULL | CT82C710_TX_IDLE | CT82C710_DEV_IDLE))
 		       != (CT82C710_DEV_IDLE | CT82C710_TX_IDLE) && timeout) {
 
-		if (inb_p(ct82c710_status) & CT82C710_RX_FULL) inb_p(ct82c710_data);
+		if (inb_p(CT82C710_STATUS) & CT82C710_RX_FULL) inb_p(CT82C710_DATA);
 
 		udelay(1);
 		timeout--;
@@ -91,7 +101,7 @@ static void ct82c710_close(struct serio *serio)
 	if (ct82c170_wait())
 		printk(KERN_WARNING "ct82c710.c: Device busy in close()\n");
 
-	outb_p(inb_p(ct82c710_status) & ~(CT82C710_ENABLE | CT82C710_INTS_ON), ct82c710_status);
+	outb_p(inb_p(CT82C710_STATUS) & ~(CT82C710_ENABLE | CT82C710_INTS_ON), CT82C710_STATUS);
 
 	if (ct82c170_wait())
 		printk(KERN_WARNING "ct82c710.c: Device busy in close()\n");
@@ -106,21 +116,21 @@ static int ct82c710_open(struct serio *serio)
 	if (request_irq(CT82C710_IRQ, ct82c710_interrupt, 0, "ct82c710", NULL))
 		return -1;
 
-	status = inb_p(ct82c710_status);
+	status = inb_p(CT82C710_STATUS);
 
 	status |= (CT82C710_ENABLE | CT82C710_RESET);
-	outb_p(status, ct82c710_status);
+	outb_p(status, CT82C710_STATUS);
 
 	status &= ~(CT82C710_RESET);
-	outb_p(status, ct82c710_status);
+	outb_p(status, CT82C710_STATUS);
 
 	status |= CT82C710_INTS_ON;
-	outb_p(status, ct82c710_status);	/* Enable interrupts */
+	outb_p(status, CT82C710_STATUS);	/* Enable interrupts */
 
 	while (ct82c170_wait()) {
 		printk(KERN_ERR "ct82c710: Device busy in open()\n");
 		status &= ~(CT82C710_ENABLE | CT82C710_INTS_ON);
-		outb_p(status, ct82c710_status);
+		outb_p(status, CT82C710_STATUS);
 		free_irq(CT82C710_IRQ, NULL);
 		return -1;
 	}
@@ -135,30 +145,10 @@ static int ct82c710_open(struct serio *serio)
 static int ct82c710_write(struct serio *port, unsigned char c)
 {
 	if (ct82c170_wait()) return -1;
-	outb_p(c, ct82c710_data);
+	outb_p(c, CT82C710_DATA);
 	return 0;
 }
 
-static struct serio ct82c710_port =
-{
-	.type	= SERIO_8042,
-	.name	= ct82c710_name,
-	.phys	= ct82c710_phys,
-	.write	= ct82c710_write,
-	.open	= ct82c710_open,
-	.close	= ct82c710_close,
-};
-
-/*
- * Interrupt handler for the 82C710 mouse port. A character
- * is waiting in the 82C710.
- */
-
-static irqreturn_t ct82c710_interrupt(int cpl, void *dev_id, struct pt_regs * regs)
-{
-	return serio_interrupt(&ct82c710_port, inb(ct82c710_data), 0, regs);
-}
-
 /*
  * See if we can find a 82C710 device. Read mouse address.
  */
@@ -175,36 +165,60 @@ static int __init ct82c710_probe(void)
 		return -1;				/* No: no 82C710 here */
 
 	outb_p(0x0d, 0x390);				/* Write index */
-	ct82c710_data = inb_p(0x391) << 2;		/* Get mouse I/O address */
-	ct82c710_status = ct82c710_data + 1;
+	ct82c710_iores.start = inb_p(0x391) << 2;	/* Get mouse I/O address */
+	ct82c710_iores.end = ct82c710_iores.start + 1;
+	ct82c710_iores.flags = IORESOURCE_IO;
 	outb_p(0x0f, 0x390);
 	outb_p(0x0f, 0x391);				/* Close config mode */
 
 	return 0;
 }
 
+static struct serio * __init ct82c710_allocate_port(void)
+{
+	struct serio *serio;
+
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (serio) {
+		memset(serio, 0, sizeof(struct serio));
+		serio->type = SERIO_8042;
+		serio->open = ct82c710_open;
+		serio->close = ct82c710_close;
+		serio->write = ct82c710_write;
+		serio->dev.parent = &ct82c710_device->dev;
+		strlcpy(serio->name, "C&T 82c710 mouse port", sizeof(serio->name));
+		snprintf(serio->phys, sizeof(serio->phys), "isa%04lx/serio0", CT82C710_DATA);
+	}
+
+	return serio;
+}
+
 int __init ct82c710_init(void)
 {
 	if (ct82c710_probe())
 		return -ENODEV;
 
-	if (request_region(ct82c710_data, 2, "ct82c710"))
-		return -EBUSY;
+	ct82c710_device = platform_device_register_simple("ct82c710", -1, &ct82c710_iores, 1);
+	if (IS_ERR(ct82c710_device))
+		return PTR_ERR(ct82c710_device);
 
-	sprintf(ct82c710_phys, "isa%04x/serio0", ct82c710_data);
+	if (!(ct82c710_port = ct82c710_allocate_port())) {
+		platform_device_unregister(ct82c710_device);
+		return -ENOMEM;
+	}
 
-	serio_register_port(&ct82c710_port);
+	serio_register_port(ct82c710_port);
 
-	printk(KERN_INFO "serio: C&T 82c710 mouse port at %#x irq %d\n",
-		ct82c710_data, CT82C710_IRQ);
+	printk(KERN_INFO "serio: C&T 82c710 mouse port at %#lx irq %d\n",
+		CT82C710_DATA, CT82C710_IRQ);
 
 	return 0;
 }
 
 void __exit ct82c710_exit(void)
 {
-	serio_unregister_port(&ct82c710_port);
-	release_region(ct82c710_data, 2);
+	serio_unregister_port(ct82c710_port);
+	platform_device_unregister(ct82c710_device);
 }
 
 module_init(ct82c710_init);
diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
index 48a0ad587..cd9f987fb 100644
--- a/drivers/input/serio/gscps2.c
+++ b/drivers/input/serio/gscps2.c
@@ -6,7 +6,7 @@
  * Copyright (c) 2002 Thibaut Varene <varenet@esiee.fr>
  *
  * Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c
- * 	Copyright (c) 1999 Alex deVries <adevries@thepuffingroup.com>
+ * 	Copyright (c) 1999 Alex deVries <alex@onefishtwo.ca>
  *	Copyright (c) 1999-2000 Philipp Rumpf <prumpf@tux.org>
  *	Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr>
  *	Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr>
@@ -91,7 +91,7 @@ static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs);
 struct gscps2port {
 	struct list_head node;
 	struct parisc_device *padev;
-	struct serio port;
+	struct serio *port;
 	spinlock_t lock;
 	char *addr;
 	u8 act, append; /* position in buffer[] */
@@ -100,7 +100,6 @@ struct gscps2port {
 		u8 str;
 	} buffer[BUFFER_SIZE+1];
 	int id;
-	char name[32];
 };
 
 /*
@@ -272,7 +271,7 @@ static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs)
 	    rxflags =	((status & GSC_STAT_TERR) ? SERIO_TIMEOUT : 0 ) |
 			((status & GSC_STAT_PERR) ? SERIO_PARITY  : 0 );
 
-	    serio_interrupt(&ps2port->port, data, rxflags, regs);
+	    serio_interrupt(ps2port->port, data, rxflags, regs);
 
 	  } /* while() */
 
@@ -288,7 +287,7 @@ static irqreturn_t gscps2_interrupt(int irq, void *dev, struct pt_regs *regs)
 
 static int gscps2_write(struct serio *port, unsigned char data)
 {
-	struct gscps2port *ps2port = port->driver;
+	struct gscps2port *ps2port = port->port_data;
 
 	if (!gscps2_writeb_output(ps2port, data)) {
 		printk(KERN_DEBUG PFX "sending byte %#x failed.\n", data);
@@ -304,7 +303,7 @@ static int gscps2_write(struct serio *port, unsigned char data)
 
 static int gscps2_open(struct serio *port)
 {
-	struct gscps2port *ps2port = port->driver;
+	struct gscps2port *ps2port = port->port_data;
 
 	gscps2_reset(ps2port);
 
@@ -319,7 +318,7 @@ static int gscps2_open(struct serio *port)
 
 static void gscps2_close(struct serio *port)
 {
-	struct gscps2port *ps2port = port->driver;
+	struct gscps2port *ps2port = port->port_data;
 	gscps2_enable(ps2port, DISABLE);
 }
 
@@ -343,7 +342,8 @@ static struct serio gscps2_serio_port =
 
 static int __init gscps2_probe(struct parisc_device *dev)
 {
-        struct gscps2port *ps2port;
+	struct gscps2port *ps2port;
+	struct serio *serio;
 	unsigned long hpa = dev->hpa;
 	int ret;
 
@@ -355,34 +355,45 @@ static int __init gscps2_probe(struct parisc_device *dev)
 		hpa += GSC_DINO_OFFSET;
 
 	ps2port = kmalloc(sizeof(struct gscps2port), GFP_KERNEL);
-	if (!ps2port)
-		return -ENOMEM;
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (!ps2port || !serio) {
+		ret = -ENOMEM;
+		goto fail_nomem;
+	}
 
 	dev_set_drvdata(&dev->dev, ps2port);
 
 	memset(ps2port, 0, sizeof(struct gscps2port));
+	memset(serio, 0, sizeof(struct serio));
+	ps2port->port = serio;
 	ps2port->padev = dev;
 	ps2port->addr = ioremap(hpa, GSC_STATUS + 4);
 	spin_lock_init(&ps2port->lock);
 
 	gscps2_reset(ps2port);
-	ps2port->id = readb(ps2port->addr+GSC_ID) & 0x0f;
-	snprintf(ps2port->name, sizeof(ps2port->name)-1, "%s %s",
-		gscps2_serio_port.name,
-		(ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse" );
-
-	memcpy(&ps2port->port, &gscps2_serio_port, sizeof(gscps2_serio_port));
-	ps2port->port.driver = ps2port;
-	ps2port->port.name = ps2port->name;
-	ps2port->port.phys = dev->dev.bus_id;
+	ps2port->id = readb(ps2port->addr + GSC_ID) & 0x0f;
+
+	snprintf(serio->name, sizeof(serio->name), "GSC PS/2 %s",
+		 (ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse");
+	strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
+	serio->idbus		= BUS_GSC;
+	serio->idvendor		= PCI_VENDOR_ID_HP;
+	serio->idproduct	= 0x0001;
+	serio->idversion	= 0x0010;
+	serio->type		= SERIO_8042;
+	serio->write		= gscps2_write;
+	serio->open		= gscps2_open;
+	serio->close		= gscps2_close;
+	serio->port_data	= ps2port;
+	serio->dev.parent	= &dev->dev;
 
 	list_add_tail(&ps2port->node, &ps2port_list);
 
 	ret = -EBUSY;
-	if (request_irq(dev->irq, gscps2_interrupt, SA_SHIRQ, ps2port->name, ps2port))
+	if (request_irq(dev->irq, gscps2_interrupt, SA_SHIRQ, ps2port->port->name, ps2port))
 		goto fail_miserably;
 
-	if ( (ps2port->id != GSC_ID_KEYBOARD) && (ps2port->id != GSC_ID_MOUSE) ) {
+	if (ps2port->id != GSC_ID_KEYBOARD && ps2port->id != GSC_ID_MOUSE) {
 		printk(KERN_WARNING PFX "Unsupported PS/2 port at 0x%08lx (id=%d) ignored\n",
 				hpa, ps2port->id);
 		ret = -ENODEV;
@@ -395,12 +406,12 @@ static int __init gscps2_probe(struct parisc_device *dev)
 #endif
 
 	printk(KERN_INFO "serio: %s port at 0x%p irq %d @ %s\n",
-		ps2port->name,
+		ps2port->port->name,
 		ps2port->addr,
 		ps2port->padev->irq,
-		ps2port->port.phys);
+		ps2port->port->phys);
 
-	serio_register_port(&ps2port->port);
+	serio_register_port(ps2port->port);
 
 	return 0;
 
@@ -411,7 +422,10 @@ fail_miserably:
 	list_del(&ps2port->node);
 	iounmap(ps2port->addr);
 	release_mem_region(dev->hpa, GSC_STATUS + 4);
+
+fail_nomem:
 	kfree(ps2port);
+	kfree(serio);
 	return ret;
 }
 
@@ -424,7 +438,7 @@ static int __devexit gscps2_remove(struct parisc_device *dev)
 {
 	struct gscps2port *ps2port = dev_get_drvdata(&dev->dev);
 
-	serio_unregister_port(&ps2port->port);
+	serio_unregister_port(ps2port->port);
 	free_irq(dev->irq, ps2port);
 	gscps2_flush(ps2port);
 	list_del(&ps2port->node);
diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h
index 2cba08840..b567c116a 100644
--- a/drivers/input/serio/i8042-io.h
+++ b/drivers/input/serio/i8042-io.h
@@ -65,6 +65,31 @@ static inline void i8042_write_command(int val)
 	return;
 }
 
+#if defined(__i386__)
+
+#include <linux/dmi.h>
+
+static struct dmi_system_id __initdata i8042_dmi_table[] = {
+	{
+		.ident = "Compaq Proliant 8500",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
+			DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "8500"),
+		},
+	},
+	{
+		.ident = "Compaq Proliant DL760",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
+			DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "DL760"),
+		},
+	},
+	{ }
+};
+#endif
+
 static inline int i8042_platform_init(void)
 {
 /*
@@ -79,6 +104,12 @@ static inline int i8042_platform_init(void)
 #if !defined(__i386__) && !defined(__x86_64__)
         i8042_reset = 1;
 #endif
+
+#if defined(__i386__)
+	if (dmi_check_system(i8042_dmi_table))
+		i8042_noloop = 1;
+#endif
+
 	return 0;
 }
 
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h
index e0b8f3219..da2a19812 100644
--- a/drivers/input/serio/i8042-sparcio.h
+++ b/drivers/input/serio/i8042-sparcio.h
@@ -18,7 +18,7 @@ static int i8042_aux_irq = -1;
 #define I8042_AUX_PHYS_DESC "sparcps2/serio1"
 #define I8042_MUX_PHYS_DESC "sparcps2/serio%d"
 
-static unsigned long kbd_iobase;
+static void __iomem *kbd_iobase;
 
 #define I8042_COMMAND_REG	(kbd_iobase + 0x64UL)
 #define I8042_DATA_REG		(kbd_iobase + 0x60UL)
@@ -64,7 +64,7 @@ static int i8042_platform_init(void)
 	if (strncmp(prop, "SUNW,JavaStation-1", len) == 0) {
 		/* Hardcoded values for MrCoffee.  */
 		i8042_kbd_irq = i8042_aux_irq = 13 | 0x20;
-		kbd_iobase = (unsigned long) ioremap(0x71300060, 8);
+		kbd_iobase = ioremap(0x71300060, 8);
 		if (!kbd_iobase)
 			return -1;
 	} else {
@@ -85,7 +85,7 @@ static int i8042_platform_init(void)
 			if (!strcmp(child->prom_name, OBP_PS2KBD_NAME1) ||
 			    !strcmp(child->prom_name, OBP_PS2KBD_NAME2)) {
 				i8042_kbd_irq = child->irqs[0];
-				kbd_iobase = (unsigned long)
+				kbd_iobase =
 					ioremap(child->resource[0].start, 8);
 			}
 			if (!strcmp(child->prom_name, OBP_PS2MS_NAME1) ||
@@ -109,7 +109,7 @@ static int i8042_platform_init(void)
 static inline void i8042_platform_exit(void)
 {
 #ifdef CONFIG_PCI
-	iounmap((void *)kbd_iobase);
+	iounmap(kbd_iobase);
 #endif
 }
 
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index e9d8dabd1..151c29ddb 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -1,7 +1,7 @@
 /*
  *  i8042 keyboard and mouse controller driver for Linux
  *
- *  Copyright (c) 1999-2002 Vojtech Pavlik
+ *  Copyright (c) 1999-2004 Vojtech Pavlik
  */
 
 /*
@@ -21,6 +21,7 @@
 #include <linux/sysdev.h>
 #include <linux/pm.h>
 #include <linux/serio.h>
+#include <linux/err.h>
 
 #include <asm/io.h>
 
@@ -52,6 +53,10 @@ static unsigned int i8042_dumbkbd;
 module_param_named(dumbkbd, i8042_dumbkbd, bool, 0);
 MODULE_PARM_DESC(dumbkbd, "Pretend that controller can only read data from keyboard");
 
+static unsigned int i8042_noloop;
+module_param_named(noloop, i8042_noloop, bool, 0);
+MODULE_PARM_DESC(dumbkbd, "Disable the AUX Loopback command while probing for the AUX port");
+
 __obsolete_setup("i8042_noaux");
 __obsolete_setup("i8042_nomux");
 __obsolete_setup("i8042_unlock");
@@ -70,19 +75,35 @@ struct i8042_values {
 	unsigned char irqen;
 	unsigned char exists;
 	signed char mux;
-	unsigned char *name;
-	unsigned char *phys;
+	char name[8];
+};
+
+static struct i8042_values i8042_kbd_values = {
+	.disable	= I8042_CTR_KBDDIS,
+	.irqen 		= I8042_CTR_KBDINT,
+	.mux		= -1,
+	.name		= "KBD",
+};
+
+static struct i8042_values i8042_aux_values = {
+	.disable	= I8042_CTR_AUXDIS,
+	.irqen		= I8042_CTR_AUXINT,
+	.mux		= -1,
+	.name		= "AUX",
 };
 
-static struct serio i8042_kbd_port;
-static struct serio i8042_aux_port;
+static struct i8042_values i8042_mux_values[I8042_NUM_MUX_PORTS];
+
+static struct serio *i8042_kbd_port;
+static struct serio *i8042_aux_port;
+static struct serio *i8042_mux_port[I8042_NUM_MUX_PORTS];
 static unsigned char i8042_initial_ctr;
 static unsigned char i8042_ctr;
 static unsigned char i8042_mux_open;
 static unsigned char i8042_mux_present;
-static unsigned char i8042_sysdev_initialized;
 static struct pm_dev *i8042_pm_dev;
-struct timer_list i8042_timer;
+static struct timer_list i8042_timer;
+static struct platform_device *i8042_platform_device;
 
 /*
  * Shared IRQ's require a device pointer, but this driver doesn't support
@@ -95,6 +116,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 /*
  * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to
  * be ready for reading values from it / writing values to it.
+ * Called always with i8042_lock held.
  */
 
 static int i8042_wait_read(void)
@@ -131,6 +153,7 @@ static int i8042_flush(void)
 	spin_lock_irqsave(&i8042_lock, flags);
 
 	while ((i8042_read_status() & I8042_STR_OBF) && (i++ < I8042_BUFFER_SIZE)) {
+		udelay(50);
 		data = i8042_read_data();
 		dbg("%02x <- i8042 (flush, %s)", data,
 			i8042_read_status() & I8042_STR_AUXDATA ? "aux" : "kbd");
@@ -154,6 +177,9 @@ static int i8042_command(unsigned char *param, int command)
 	unsigned long flags;
 	int retval = 0, i = 0;
 
+	if (i8042_noloop && command == I8042_CMD_AUX_LOOP)
+		return -1;
+
 	spin_lock_irqsave(&i8042_lock, flags);
 
 	retval = i8042_wait_write();
@@ -214,7 +240,7 @@ static int i8042_kbd_write(struct serio *port, unsigned char c)
 
 static int i8042_aux_write(struct serio *port, unsigned char c)
 {
-	struct i8042_values *values = port->driver;
+	struct i8042_values *values = port->port_data;
 	int retval;
 
 /*
@@ -242,7 +268,7 @@ static int i8042_aux_write(struct serio *port, unsigned char c)
 
 static int i8042_activate_port(struct serio *port)
 {
-	struct i8042_values *values = port->driver;
+	struct i8042_values *values = port->port_data;
 
 	i8042_flush();
 
@@ -270,7 +296,7 @@ static int i8042_activate_port(struct serio *port)
 
 static int i8042_open(struct serio *port)
 {
-	struct i8042_values *values = port->driver;
+	struct i8042_values *values = port->port_data;
 
 	if (values->mux != -1)
 		if (i8042_mux_open++)
@@ -309,7 +335,7 @@ irq_fail:
 
 static void i8042_close(struct serio *port)
 {
-	struct i8042_values *values = port->driver;
+	struct i8042_values *values = port->port_data;
 
 	if (values->mux != -1)
 		if (--i8042_mux_open)
@@ -327,52 +353,6 @@ static void i8042_close(struct serio *port)
 	i8042_flush();
 }
 
-/*
- * Structures for registering the devices in the serio.c module.
- */
-
-static struct i8042_values i8042_kbd_values = {
-	.irqen =	I8042_CTR_KBDINT,
-	.disable =	I8042_CTR_KBDDIS,
-	.name =		"KBD",
-	.mux =		-1,
-};
-
-static struct serio i8042_kbd_port =
-{
-	.type =		SERIO_8042_XL,
-	.write =	i8042_kbd_write,
-	.open =		i8042_open,
-	.close =	i8042_close,
-	.driver =	&i8042_kbd_values,
-	.name =		"i8042 Kbd Port",
-	.phys =		I8042_KBD_PHYS_DESC,
-};
-
-static struct i8042_values i8042_aux_values = {
-	.irqen =	I8042_CTR_AUXINT,
-	.disable =	I8042_CTR_AUXDIS,
-	.name =		"AUX",
-	.mux =		-1,
-};
-
-static struct serio i8042_aux_port =
-{
-	.type =		SERIO_8042,
-	.write =	i8042_aux_write,
-	.open =		i8042_open,
-	.close =	i8042_close,
-	.driver =	&i8042_aux_values,
-	.name =		"i8042 Aux Port",
-	.phys =		I8042_AUX_PHYS_DESC,
-};
-
-static struct i8042_values i8042_mux_values[4];
-static struct serio i8042_mux_port[4];
-static char i8042_mux_names[4][32];
-static char i8042_mux_short[4][16];
-static char i8042_mux_phys[4][32];
-
 /*
  * i8042_interrupt() is the most important function in this driver -
  * it handles the interrupts from the i8042, and sends incoming bytes
@@ -384,6 +364,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 	unsigned long flags;
 	unsigned char str, data = 0;
 	unsigned int dfl;
+	unsigned int aux_idx;
 	int ret;
 
 	mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
@@ -400,44 +381,67 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 		goto out;
 	}
 
-	dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) |
-	      ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0);
-
-	if (i8042_mux_values[0].exists && (str & I8042_STR_AUXDATA)) {
+	if (i8042_mux_present && (str & I8042_STR_AUXDATA)) {
+		static unsigned long last_transmit;
+		static unsigned char last_str;
 
+		dfl = 0;
 		if (str & I8042_STR_MUXERR) {
+			dbg("MUX error, status is %02x, data is %02x", str, data);
 			switch (data) {
+				default:
+/*
+ * When MUXERR condition is signalled the data register can only contain
+ * 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately
+ * it is not always the case. Some KBC just get confused which port the
+ * data came from and signal error leaving the data intact. They _do not_
+ * revert to legacy mode (actually I've never seen KBC reverting to legacy
+ * mode yet, when we see one we'll add proper handling).
+ * Anyway, we will assume that the data came from the same serio last byte
+ * was transmitted (if transmission happened not too long ago).
+ */
+					if (time_before(jiffies, last_transmit + HZ/10)) {
+						str = last_str;
+						break;
+					}
+					/* fall through - report timeout */
 				case 0xfd:
-				case 0xfe: dfl = SERIO_TIMEOUT; break;
-				case 0xff: dfl = SERIO_PARITY; break;
+				case 0xfe: dfl = SERIO_TIMEOUT; data = 0xfe; break;
+				case 0xff: dfl = SERIO_PARITY;  data = 0xfe; break;
 			}
-			data = 0xfe;
-		} else dfl = 0;
+		}
+
+		aux_idx = (str >> 6) & 3;
 
 		dbg("%02x <- i8042 (interrupt, aux%d, %d%s%s)",
-			data, (str >> 6), irq,
+			data, aux_idx, irq,
 			dfl & SERIO_PARITY ? ", bad parity" : "",
 			dfl & SERIO_TIMEOUT ? ", timeout" : "");
 
-		serio_interrupt(i8042_mux_port + ((str >> 6) & 3), data, dfl, regs);
+		if (likely(i8042_mux_values[aux_idx].exists))
+			serio_interrupt(i8042_mux_port[aux_idx], data, dfl, regs);
 
+		last_str = str;
+		last_transmit = jiffies;
 		goto irq_ret;
 	}
 
+	dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) |
+	      ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0);
+
 	dbg("%02x <- i8042 (interrupt, %s, %d%s%s)",
 		data, (str & I8042_STR_AUXDATA) ? "aux" : "kbd", irq,
 		dfl & SERIO_PARITY ? ", bad parity" : "",
 		dfl & SERIO_TIMEOUT ? ", timeout" : "");
 
-	if (i8042_aux_values.exists && (str & I8042_STR_AUXDATA)) {
-		serio_interrupt(&i8042_aux_port, data, dfl, regs);
-		goto irq_ret;
-	}
-
-	if (!i8042_kbd_values.exists)
-		goto irq_ret;
 
-	serio_interrupt(&i8042_kbd_port, data, dfl, regs);
+	if (str & I8042_STR_AUXDATA) {
+		if (likely(i8042_aux_values.exists))
+			serio_interrupt(i8042_aux_port, data, dfl, regs);
+	} else {
+		if (likely(i8042_kbd_values.exists))
+			serio_interrupt(i8042_kbd_port, data, dfl, regs);
+	}
 
 irq_ret:
 	ret = 1;
@@ -474,17 +478,8 @@ static int i8042_enable_mux_mode(struct i8042_values *values, unsigned char *mux
 	if (i8042_command(&param, I8042_CMD_AUX_LOOP) || param != 0xa9)
 		return -1;
 	param = 0xa4;
-	if (i8042_command(&param, I8042_CMD_AUX_LOOP) || param == 0x5b) {
-
-/*
- * Do another loop test with the 0x5a value. Doing anything else upsets
- * Profusion/ServerWorks OSB4 chipsets.
- */
-
-		param = 0x5a;
-		i8042_command(&param, I8042_CMD_AUX_LOOP);
+	if (i8042_command(&param, I8042_CMD_AUX_LOOP) || param == 0x5b)
 		return -1;
-	}
 
 	if (mux_version)
 		*mux_version = ~param;
@@ -639,8 +634,10 @@ static int __init i8042_check_aux(struct i8042_values *values)
  * registers it, and reports to the user.
  */
 
-static int __init i8042_port_register(struct i8042_values *values, struct serio *port)
+static int __init i8042_port_register(struct serio *port)
 {
+	struct i8042_values *values = port->port_data;
+
 	values->exists = 1;
 
 	i8042_ctr &= ~values->disable;
@@ -677,6 +674,7 @@ static void i8042_timer_func(unsigned long data)
 
 static int i8042_controller_init(void)
 {
+	unsigned long flags;
 
 /*
  * Test the i8042. We need to know if it thinks it's working correctly
@@ -723,12 +721,14 @@ static int i8042_controller_init(void)
  * Handle keylock.
  */
 
+	spin_lock_irqsave(&i8042_lock, flags);
 	if (~i8042_read_status() & I8042_STR_KEYLOCK) {
 		if (i8042_unlock)
 			i8042_ctr |= I8042_CTR_IGNKEYLOCK;
 		 else
 			printk(KERN_WARNING "i8042.c: Warning: Keylock active.\n");
 	}
+	spin_unlock_irqrestore(&i8042_lock, flags);
 
 /*
  * If the chip is configured into nontranslated mode by the BIOS, don't
@@ -745,10 +745,8 @@ static int i8042_controller_init(void)
  * BIOSes.
  */
 
-	if (i8042_direct) {
+	if (i8042_direct)
 		i8042_ctr &= ~I8042_CTR_XLATE;
-		i8042_kbd_port.type = SERIO_8042;
-	}
 
 /*
  * Write CTR back.
@@ -802,14 +800,14 @@ void i8042_controller_cleanup(void)
  */
 
 	if (i8042_kbd_values.exists)
-		serio_cleanup(&i8042_kbd_port);
+		serio_cleanup(i8042_kbd_port);
 
 	if (i8042_aux_values.exists)
-		serio_cleanup(&i8042_aux_port);
+		serio_cleanup(i8042_aux_port);
 
-	for (i = 0; i < 4; i++)
+	for (i = 0; i < I8042_NUM_MUX_PORTS; i++)
 		if (i8042_mux_values[i].exists)
-			serio_cleanup(i8042_mux_port + i);
+			serio_cleanup(i8042_mux_port[i]);
 
 	i8042_controller_reset();
 }
@@ -851,15 +849,15 @@ static int i8042_controller_resume(void)
  * Reconnect anything that was connected to the ports.
  */
 
-	if (i8042_kbd_values.exists && i8042_activate_port(&i8042_kbd_port) == 0)
-		serio_reconnect(&i8042_kbd_port);
+	if (i8042_kbd_values.exists && i8042_activate_port(i8042_kbd_port) == 0)
+		serio_reconnect(i8042_kbd_port);
 
-	if (i8042_aux_values.exists && i8042_activate_port(&i8042_aux_port) == 0)
-		serio_reconnect(&i8042_aux_port);
+	if (i8042_aux_values.exists && i8042_activate_port(i8042_aux_port) == 0)
+		serio_reconnect(i8042_aux_port);
 
-	for (i = 0; i < 4; i++)
-		if (i8042_mux_values[i].exists && i8042_activate_port(i8042_mux_port + i) == 0)
-			serio_reconnect(i8042_mux_port + i);
+	for (i = 0; i < I8042_NUM_MUX_PORTS; i++)
+		if (i8042_mux_values[i].exists && i8042_activate_port(i8042_mux_port[i]) == 0)
+			serio_reconnect(i8042_mux_port[i]);
 /*
  * Restart timer (for polling "stuck" data)
  */
@@ -882,7 +880,7 @@ static int i8042_notify_sys(struct notifier_block *this, unsigned long code,
         return NOTIFY_DONE;
 }
 
-static struct notifier_block i8042_notifier=
+static struct notifier_block i8042_notifier =
 {
         i8042_notify_sys,
         NULL,
@@ -892,25 +890,27 @@ static struct notifier_block i8042_notifier=
 /*
  * Suspend/resume handlers for the new PM scheme (driver model)
  */
-static int i8042_suspend(struct sys_device *dev, u32 state)
+static int i8042_suspend(struct device *dev, u32 state, u32 level)
 {
-	return i8042_controller_suspend();
+	return level == SUSPEND_DISABLE ? i8042_controller_suspend() : 0;
 }
 
-static int i8042_resume(struct sys_device *dev)
+static int i8042_resume(struct device *dev, u32 level)
 {
-	return i8042_controller_resume();
+	return level == RESUME_ENABLE ? i8042_controller_resume() : 0;
 }
 
-static struct sysdev_class kbc_sysclass = {
-	set_kset_name("i8042"),
-	.suspend = i8042_suspend,
-	.resume = i8042_resume,
-};
+static void i8042_shutdown(struct device *dev)
+{
+	i8042_controller_cleanup();
+}
 
-static struct sys_device device_i8042 = {
-       .id     = 0,
-       .cls    = &kbc_sysclass,
+static struct device_driver i8042_driver = {
+	.name		= "i8042",
+	.bus		= &platform_bus_type,
+	.suspend	= i8042_suspend,
+	.resume		= i8042_resume,
+	.shutdown	= i8042_shutdown,
 };
 
 /*
@@ -929,23 +929,75 @@ static int i8042_pm_callback(struct pm_dev *dev, pm_request_t request, void *dum
 	return 0;
 }
 
-static void __init i8042_init_mux_values(struct i8042_values *values, struct serio *port, int index)
+static struct serio * __init i8042_allocate_kbd_port(void)
+{
+	struct serio *serio;
+
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (serio) {
+		memset(serio, 0, sizeof(struct serio));
+		serio->type		= i8042_direct ? SERIO_8042 : SERIO_8042_XL,
+		serio->write		= i8042_dumbkbd ? NULL : i8042_kbd_write,
+		serio->open		= i8042_open,
+		serio->close		= i8042_close,
+		serio->port_data	= &i8042_kbd_values,
+		serio->dev.parent	= &i8042_platform_device->dev;
+		strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name));
+		strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys));
+	}
+
+	return serio;
+}
+
+static struct serio * __init i8042_allocate_aux_port(void)
 {
-	memcpy(port, &i8042_aux_port, sizeof(struct serio));
-	memcpy(values, &i8042_aux_values, sizeof(struct i8042_values));
-	sprintf(i8042_mux_names[index], "i8042 Aux-%d Port", index);
-	sprintf(i8042_mux_phys[index], I8042_MUX_PHYS_DESC, index + 1);
-	sprintf(i8042_mux_short[index], "AUX%d", index);
-	port->name = i8042_mux_names[index];
-	port->phys = i8042_mux_phys[index];
-	port->driver = values;
-	values->name = i8042_mux_short[index];
-	values->mux = index;
+	struct serio *serio;
+
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (serio) {
+		memset(serio, 0, sizeof(struct serio));
+		serio->type		= SERIO_8042;
+		serio->write		= i8042_aux_write;
+		serio->open		= i8042_open;
+		serio->close		= i8042_close;
+		serio->port_data	= &i8042_aux_values,
+		serio->dev.parent	= &i8042_platform_device->dev;
+		strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name));
+		strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys));
+	}
+
+	return serio;
+}
+
+static struct serio * __init i8042_allocate_mux_port(int index)
+{
+	struct serio *serio;
+	struct i8042_values *values = &i8042_mux_values[index];
+
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (serio) {
+		*values = i8042_aux_values;
+		snprintf(values->name, sizeof(values->name), "AUX%d", index);
+		values->mux = index;
+
+		memset(serio, 0, sizeof(struct serio));
+		serio->type		= SERIO_8042;
+		serio->write		= i8042_aux_write;
+		serio->open		= i8042_open;
+		serio->close		= i8042_close;
+		serio->port_data	= values;
+		serio->dev.parent	= &i8042_platform_device->dev;
+		snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index);
+		snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1);
+	}
+
+	return serio;
 }
 
 int __init i8042_init(void)
 {
 	int i;
+	int err;
 
 	dbg_init();
 
@@ -961,30 +1013,36 @@ int __init i8042_init(void)
 	if (i8042_controller_init())
 		return -ENODEV;
 
-	if (i8042_dumbkbd)
-		i8042_kbd_port.write = NULL;
+	err = driver_register(&i8042_driver);
+	if (err)
+		return err;
+
+	i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0);
+	if (IS_ERR(i8042_platform_device)) {
+		driver_unregister(&i8042_driver);
+		return PTR_ERR(i8042_platform_device);
+	}
 
 	if (!i8042_noaux && !i8042_check_aux(&i8042_aux_values)) {
 		if (!i8042_nomux && !i8042_check_mux(&i8042_aux_values))
-			for (i = 0; i < 4; i++) {
-				i8042_init_mux_values(i8042_mux_values + i, i8042_mux_port + i, i);
-				i8042_port_register(i8042_mux_values + i, i8042_mux_port + i);
+			for (i = 0; i < I8042_NUM_MUX_PORTS; i++) {
+				i8042_mux_port[i] = i8042_allocate_mux_port(i);
+				if (i8042_mux_port[i])
+					i8042_port_register(i8042_mux_port[i]);
 			}
-		else
-			i8042_port_register(&i8042_aux_values, &i8042_aux_port);
+		else {
+			i8042_aux_port = i8042_allocate_aux_port();
+			if (i8042_aux_port)
+				i8042_port_register(i8042_aux_port);
+		}
 	}
 
-	i8042_port_register(&i8042_kbd_values, &i8042_kbd_port);
+	i8042_kbd_port = i8042_allocate_kbd_port();
+	if (i8042_kbd_port)
+		i8042_port_register(i8042_kbd_port);
 
 	mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
 
-        if (sysdev_class_register(&kbc_sysclass) == 0) {
-                if (sysdev_register(&device_i8042) == 0)
-			i8042_sysdev_initialized = 1;
-		else
-			sysdev_class_unregister(&kbc_sysclass);
-        }
-
 	i8042_pm_dev = pm_register(PM_SYS_DEV, PM_SYS_UNKNOWN, i8042_pm_callback);
 
 	register_reboot_notifier(&i8042_notifier);
@@ -1001,24 +1059,23 @@ void __exit i8042_exit(void)
 	if (i8042_pm_dev)
 		pm_unregister(i8042_pm_dev);
 
-	if (i8042_sysdev_initialized) {
-		sysdev_unregister(&device_i8042);
-		sysdev_class_unregister(&kbc_sysclass);
-	}
-
 	i8042_controller_cleanup();
 
 	if (i8042_kbd_values.exists)
-		serio_unregister_port(&i8042_kbd_port);
+		serio_unregister_port(i8042_kbd_port);
 
 	if (i8042_aux_values.exists)
-		serio_unregister_port(&i8042_aux_port);
+		serio_unregister_port(i8042_aux_port);
 
-	for (i = 0; i < 4; i++)
+	for (i = 0; i < I8042_NUM_MUX_PORTS; i++)
 		if (i8042_mux_values[i].exists)
-			serio_unregister_port(i8042_mux_port + i);
+			serio_unregister_port(i8042_mux_port[i]);
+
 	del_timer_sync(&i8042_timer);
 
+	platform_device_unregister(i8042_platform_device);
+	driver_unregister(&i8042_driver);
+
 	i8042_platform_exit();
 }
 
diff --git a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h
index f0f637483..cea24034d 100644
--- a/drivers/input/serio/i8042.h
+++ b/drivers/input/serio/i8042.h
@@ -103,6 +103,13 @@
 
 #define I8042_BUFFER_SIZE	32
 
+/*
+ * Number of AUX ports on controllers supporting active multiplexing
+ * specification
+ */
+
+#define I8042_NUM_MUX_PORTS	4
+
 /*
  * Debug.
  */
diff --git a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c
index c7db1de49..78f4d9b5a 100644
--- a/drivers/input/serio/maceps2.c
+++ b/drivers/input/serio/maceps2.c
@@ -17,6 +17,7 @@
 #include <linux/device.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/err.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -46,15 +47,18 @@ MODULE_LICENSE("GPL");
 #define PS2_CONTROL_RX_CLOCK_ENABLE  BIT(4) /* pause reception if set to 0 */
 #define PS2_CONTROL_RESET            BIT(5) /* reset */
 
-
 struct maceps2_data {
 	struct mace_ps2port *port;
 	int irq;
 };
 
+static struct maceps2_data port_data[2];
+static struct serio *maceps2_port[2];
+static struct platform_device *maceps2_device;
+
 static int maceps2_write(struct serio *dev, unsigned char val)
 {
-	struct mace_ps2port *port = ((struct maceps2_data *)dev->driver)->port;
+	struct mace_ps2port *port = ((struct maceps2_data *)dev->port_data)->port;
 	unsigned int timeout = MACE_PS2_TIMEOUT;
 
 	do {
@@ -68,11 +72,10 @@ static int maceps2_write(struct serio *dev, unsigned char val)
 	return -1;
 }
 
-static irqreturn_t maceps2_interrupt(int irq, void *dev_id,
-				     struct pt_regs *regs)
+static irqreturn_t maceps2_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct serio *dev = dev_id;
-	struct mace_ps2port *port = ((struct maceps2_data *)dev->driver)->port;
+	struct mace_ps2port *port = ((struct maceps2_data *)dev->port_data)->port;
 	unsigned int byte;
 
 	if (mace_read(port->status) & PS2_STATUS_RX_FULL) {
@@ -85,7 +88,7 @@ static irqreturn_t maceps2_interrupt(int irq, void *dev_id,
 
 static int maceps2_open(struct serio *dev)
 {
-	struct maceps2_data *data = (struct maceps2_data *)dev->driver;
+	struct maceps2_data *data = (struct maceps2_data *)dev->port_data;
 
 	if (request_irq(data->irq, maceps2_interrupt, 0, "PS/2 port", dev)) {
 		printk(KERN_ERR "Could not allocate PS/2 IRQ\n");
@@ -106,7 +109,7 @@ static int maceps2_open(struct serio *dev)
 
 static void maceps2_close(struct serio *dev)
 {
-	struct maceps2_data *data = (struct maceps2_data *)dev->driver;
+	struct maceps2_data *data = (struct maceps2_data *)dev->port_data;
 
 	mace_write(PS2_CONTROL_TX_CLOCK_DISABLE | PS2_CONTROL_RESET,
 		   data->port->control);
@@ -114,46 +117,59 @@ static void maceps2_close(struct serio *dev)
 	free_irq(data->irq, dev);
 }
 
-static struct maceps2_data port0_data, port1_data;
 
-static struct serio maceps2_port0 =
+static struct serio * __init maceps2_allocate_port(int idx)
 {
-	.type	= SERIO_8042,
-	.open	= maceps2_open,
-	.close	= maceps2_close,
-	.write	= maceps2_write,
-	.name	= "MACE PS/2 port0",
-	.phys	= "mace/serio0",
-	.driver = &port0_data,
-};
+	struct serio *serio;
+
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (serio) {
+		memset(serio, 0, sizeof(struct serio));
+		serio->type		= SERIO_8042;
+		serio->write		= maceps2_write;
+		serio->open		= maceps2_open;
+		serio->close		= maceps2_close;
+		snprintf(serio->name, sizeof(serio->name), "MACE PS/2 port%d", idx);
+		snprintf(serio->phys, sizeof(serio->phys), "mace/serio%d", idx);
+		serio->port_data	= &port_data[idx];
+		serio->dev.parent	= &maceps2_device->dev;
+	}
+
+	return serio;
+}
 
-static struct serio maceps2_port1 =
-{
-	.type	= SERIO_8042,
-	.open	= maceps2_open,
-	.close	= maceps2_close,
-	.write	= maceps2_write,
-	.name	= "MACE PS/2 port1",
-	.phys	= "mace/serio1",
-	.driver = &port1_data,
-};
 
 static int __init maceps2_init(void)
 {
-	port0_data.port = &mace->perif.ps2.keyb;
-	port0_data.irq  = MACEISA_KEYB_IRQ;
-	port1_data.port = &mace->perif.ps2.mouse;
-	port1_data.irq  = MACEISA_MOUSE_IRQ;
-	serio_register_port(&maceps2_port0);
-	serio_register_port(&maceps2_port1);
+	maceps2_device = platform_device_register_simple("maceps2", -1, NULL, 0);
+	if (IS_ERR(maceps2_device))
+		return PTR_ERR(maceps2_device);
+
+	port_data[0].port = &mace->perif.ps2.keyb;
+	port_data[0].irq  = MACEISA_KEYB_IRQ;
+	port_data[1].port = &mace->perif.ps2.mouse;
+	port_data[1].irq  = MACEISA_MOUSE_IRQ;
+
+	maceps2_port[0] = maceps2_allocate_port(0);
+	maceps2_port[1] = maceps2_allocate_port(1);
+	if (!maceps2_port[0] || !maceps2_port[1]) {
+		kfree(maceps2_port[0]);
+		kfree(maceps2_port[1]);
+		platform_device_unregister(maceps2_device);
+		return -ENOMEM;
+	}
+
+	serio_register_port(maceps2_port[0]);
+	serio_register_port(maceps2_port[1]);
 
 	return 0;
 }
 
 static void __exit maceps2_exit(void)
 {
-	serio_unregister_port(&maceps2_port0);
-	serio_unregister_port(&maceps2_port1);
+	serio_unregister_port(maceps2_port[0]);
+	serio_unregister_port(maceps2_port[1]);
+	platform_device_unregister(maceps2_device);
 }
 
 module_init(maceps2_init);
diff --git a/drivers/input/serio/parkbd.c b/drivers/input/serio/parkbd.c
index 5f25b21be..a859df676 100644
--- a/drivers/input/serio/parkbd.c
+++ b/drivers/input/serio/parkbd.c
@@ -53,9 +53,7 @@ static int parkbd_writing;
 static unsigned long parkbd_start;
 
 static struct pardevice *parkbd_dev;
-
-static char parkbd_name[] = "PARKBD AT/XT keyboard adapter";
-static char parkbd_phys[32];
+static struct serio *parkbd_port;
 
 static int parkbd_readlines(void)
 {
@@ -86,13 +84,6 @@ static int parkbd_write(struct serio *port, unsigned char c)
 	return 0;
 }
 
-static struct serio parkbd_port =
-{
-	.write	= parkbd_write,
-	.name	= parkbd_name,
-	.phys	= parkbd_phys,
-};
-
 static void parkbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 
@@ -125,7 +116,7 @@ static void parkbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 		parkbd_buffer |= (parkbd_readlines() >> 1) << parkbd_counter++;
 
 		if (parkbd_counter == parkbd_mode + 10)
-			serio_interrupt(&parkbd_port, (parkbd_buffer >> (2 - parkbd_mode)) & 0xff, 0, regs);
+			serio_interrupt(parkbd_port, (parkbd_buffer >> (2 - parkbd_mode)) & 0xff, 0, regs);
 	}
 
 	parkbd_last = jiffies;
@@ -163,16 +154,39 @@ static int parkbd_getport(void)
 	return 0;
 }
 
+static struct serio * __init parkbd_allocate_serio(void)
+{
+	struct serio *serio;
+
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (serio) {
+		memset(serio, 0, sizeof(struct serio));
+		serio->type = parkbd_mode;
+		serio->write = parkbd_write,
+		strlcpy(serio->name, "PARKBD AT/XT keyboard adapter", sizeof(serio->name));
+		snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", parkbd_dev->port->name);
+	}
+
+	return serio;
+}
 
 int __init parkbd_init(void)
 {
-	if (parkbd_getport()) return -1;
-	parkbd_writelines(3);
-	parkbd_port.type = parkbd_mode;
+	int err;
+
+	err = parkbd_getport();
+	if (err)
+		return err;
 
-	sprintf(parkbd_phys, "%s/serio0", parkbd_dev->port->name);
+	parkbd_port = parkbd_allocate_serio();
+	if (!parkbd_port) {
+		parport_release(parkbd_dev);
+		return -ENOMEM;
+	}
+
+	parkbd_writelines(3);
 
-	serio_register_port(&parkbd_port);
+	serio_register_port(parkbd_port);
 
 	printk(KERN_INFO "serio: PARKBD %s adapter on %s\n",
                         parkbd_mode ? "AT" : "XT", parkbd_dev->port->name);
@@ -183,7 +197,7 @@ int __init parkbd_init(void)
 void __exit parkbd_exit(void)
 {
 	parport_release(parkbd_dev);
-	serio_unregister_port(&parkbd_port);
+	serio_unregister_port(parkbd_port);
 	parport_unregister_device(parkbd_dev);
 }
 
diff --git a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c
index 2b4acac94..489749e7c 100644
--- a/drivers/input/serio/pcips2.c
+++ b/drivers/input/serio/pcips2.c
@@ -38,14 +38,14 @@
 #define PS2_STAT_TXEMPTY	(1<<7)
 
 struct pcips2_data {
-	struct serio	io;
+	struct serio	*io;
 	unsigned int	base;
 	struct pci_dev	*dev;
 };
 
 static int pcips2_write(struct serio *io, unsigned char val)
 {
-	struct pcips2_data *ps2if = io->driver;
+	struct pcips2_data *ps2if = io->port_data;
 	unsigned int stat;
 
 	do {
@@ -80,7 +80,7 @@ static irqreturn_t pcips2_interrupt(int irq, void *devid, struct pt_regs *regs)
 		if (hweight8(scancode) & 1)
 			flag ^= SERIO_PARITY;
 
-		serio_interrupt(&ps2if->io, scancode, flag, regs);
+		serio_interrupt(ps2if->io, scancode, flag, regs);
 	} while (1);
 	return IRQ_RETVAL(handled);
 }
@@ -101,7 +101,7 @@ static void pcips2_flush_input(struct pcips2_data *ps2if)
 
 static int pcips2_open(struct serio *io)
 {
-	struct pcips2_data *ps2if = io->driver;
+	struct pcips2_data *ps2if = io->port_data;
 	int ret, val = 0;
 
 	outb(PS2_CTRL_ENABLE, ps2if->base);
@@ -119,7 +119,7 @@ static int pcips2_open(struct serio *io)
 
 static void pcips2_close(struct serio *io)
 {
-	struct pcips2_data *ps2if = io->driver;
+	struct pcips2_data *ps2if = io->port_data;
 
 	outb(0, ps2if->base);
 
@@ -129,46 +129,51 @@ static void pcips2_close(struct serio *io)
 static int __devinit pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
 	struct pcips2_data *ps2if;
+	struct serio *serio;
 	int ret;
 
 	ret = pci_enable_device(dev);
 	if (ret)
-		return ret;
+		goto out;
 
-	if (!request_region(pci_resource_start(dev, 0),
-			    pci_resource_len(dev, 0), "pcips2")) {
-		ret = -EBUSY;
+	ret = pci_request_regions(dev, "pcips2");
+	if (ret)
 		goto disable;
-	}
 
 	ps2if = kmalloc(sizeof(struct pcips2_data), GFP_KERNEL);
-	if (!ps2if) {
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (!ps2if || !serio) {
 		ret = -ENOMEM;
 		goto release;
 	}
 
 	memset(ps2if, 0, sizeof(struct pcips2_data));
-
-	ps2if->io.type		= SERIO_8042;
-	ps2if->io.write		= pcips2_write;
-	ps2if->io.open		= pcips2_open;
-	ps2if->io.close		= pcips2_close;
-	ps2if->io.name		= pci_name(dev);
-	ps2if->io.phys		= dev->dev.bus_id;
-	ps2if->io.driver	= ps2if;
+	memset(serio, 0, sizeof(struct serio));
+
+	serio->type		= SERIO_8042;
+	serio->write		= pcips2_write;
+	serio->open		= pcips2_open;
+	serio->close		= pcips2_close;
+	strlcpy(serio->name, pci_name(dev), sizeof(serio->name));
+	strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
+	serio->port_data	= ps2if;
+	serio->dev.parent	= &dev->dev;
+	ps2if->io		= serio;
 	ps2if->dev		= dev;
 	ps2if->base		= pci_resource_start(dev, 0);
 
 	pci_set_drvdata(dev, ps2if);
 
-	serio_register_port(&ps2if->io);
+	serio_register_port(ps2if->io);
 	return 0;
 
  release:
-	release_region(pci_resource_start(dev, 0),
-		       pci_resource_len(dev, 0));
+	kfree(ps2if);
+	kfree(serio);
+	pci_release_regions(dev);
  disable:
 	pci_disable_device(dev);
+ out:
 	return ret;
 }
 
@@ -176,11 +181,10 @@ static void __devexit pcips2_remove(struct pci_dev *dev)
 {
 	struct pcips2_data *ps2if = pci_get_drvdata(dev);
 
-	serio_unregister_port(&ps2if->io);
-	release_region(pci_resource_start(dev, 0),
-		       pci_resource_len(dev, 0));
+	serio_unregister_port(ps2if->io);
 	pci_set_drvdata(dev, NULL);
 	kfree(ps2if);
+	pci_release_regions(dev);
 	pci_disable_device(dev);
 }
 
diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c
index 7f4a26287..7d5ecce92 100644
--- a/drivers/input/serio/q40kbd.c
+++ b/drivers/input/serio/q40kbd.c
@@ -35,6 +35,7 @@
 #include <linux/init.h>
 #include <linux/serio.h>
 #include <linux/interrupt.h>
+#include <linux/err.h>
 
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -47,43 +48,106 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("Q40 PS/2 keyboard controller driver");
 MODULE_LICENSE("GPL");
 
-static struct serio q40kbd_port =
-{
-	.type	= SERIO_8042,
-	.name	= "Q40 kbd port",
-	.phys	= "Q40",
-	.write	= NULL,
-};
-
-static irqreturn_t q40kbd_interrupt(int irq, void *dev_id,
-				    struct pt_regs *regs)
+spinlock_t q40kbd_lock = SPIN_LOCK_UNLOCKED;
+static struct serio *q40kbd_port;
+static struct platform_device *q40kbd_device;
+
+static irqreturn_t q40kbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&q40kbd_lock, flags);
+
 	if (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG))
-		serio_interrupt(&q40kbd_port, master_inb(KEYCODE_REG), 0, regs);
+		serio_interrupt(q40kbd_port, master_inb(KEYCODE_REG), 0, regs);
 
 	master_outb(-1, KEYBOARD_UNLOCK_REG);
+
+	spin_unlock_irqrestore(&q40kbd_lock, flags);
+
 	return IRQ_HANDLED;
 }
 
-static int __init q40kbd_init(void)
+/*
+ * q40kbd_flush() flushes all data that may be in the keyboard buffers
+ */
+
+static void q40kbd_flush(void)
+{
+ 	int maxread = 100;
+	unsigned long flags;
+
+	spin_lock_irqsave(&q40kbd_lock, flags);
+
+ 	while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)))
+ 		master_inb(KEYCODE_REG);
+
+	spin_unlock_irqrestore(&q40kbd_lock, flags);
+}
+
+/*
+ * q40kbd_open() is called when a port is open by the higher layer.
+ * It allocates the interrupt and enables in in the chip.
+ */
+
+static int q40kbd_open(struct serio *port)
 {
-	int maxread = 100;
+	q40kbd_flush();
 
+	if (request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, "q40kbd", NULL)) {
+		printk(KERN_ERR "q40kbd.c: Can't get irq %d.\n", Q40_IRQ_KEYBOARD);
+		return -1;
+	}
+
+ 	/* off we go */
+ 	master_outb(-1, KEYBOARD_UNLOCK_REG);
+ 	master_outb(1, KEY_IRQ_ENABLE_REG);
+
+ 	return 0;
+}
+
+static void q40kbd_close(struct serio *port)
+{
+	master_outb(0, KEY_IRQ_ENABLE_REG);
+	master_outb(-1, KEYBOARD_UNLOCK_REG);
+	free_irq(Q40_IRQ_KEYBOARD, NULL);
+
+	q40kbd_flush();
+}
+
+static struct serio * __init q40kbd_allocate_port(void)
+{
+	struct serio *serio;
+
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (serio) {
+		memset(serio, 0, sizeof(struct serio));
+		serio->type		= SERIO_8042;
+		serio->open		= q40kbd_open;
+		serio->close		= q40kbd_close;
+		serio->dev.parent	= &q40kbd_device->dev;
+		strlcpy(serio->name, "Q40 Kbd Port", sizeof(serio->name));
+		strlcpy(serio->phys, "Q40", sizeof(serio->phys));
+	}
+
+	return serio;
+}
+
+static int __init q40kbd_init(void)
+{
 	if (!MACH_IS_Q40)
 		return -EIO;
 
-	/* allocate the IRQ */
-	request_irq(Q40_IRQ_KEYBOARD, q40kbd_interrupt, 0, "q40kbd", NULL);
-
-	/* flush any pending input */
-	while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)))
-		master_inb(KEYCODE_REG);
+	q40kbd_device = platform_device_register_simple("q40kbd", -1, NULL, 0);
+	if (IS_ERR(q40kbd_device))
+		return PTR_ERR(q40kbd_device);
 
-	/* off we go */
-	master_outb(-1,KEYBOARD_UNLOCK_REG);
-	master_outb(1,KEY_IRQ_ENABLE_REG);
+	if (!(q40kbd_port = q40kbd_allocate_port())) {
+		platform_device_unregister(q40kbd_device);
+		return -ENOMEM;
+	}
 
-	serio_register_port(&q40kbd_port);
+	serio_register_port(q40kbd_port);
 	printk(KERN_INFO "serio: Q40 kbd registered\n");
 
 	return 0;
@@ -91,11 +155,8 @@ static int __init q40kbd_init(void)
 
 static void __exit q40kbd_exit(void)
 {
-	master_outb(0,KEY_IRQ_ENABLE_REG);
-	master_outb(-1,KEYBOARD_UNLOCK_REG);
-
-	serio_unregister_port(&q40kbd_port);
-	free_irq(Q40_IRQ_KEYBOARD, NULL);
+	serio_unregister_port(q40kbd_port);
+	platform_device_unregister(q40kbd_device);
 }
 
 module_init(q40kbd_init);
diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
index a2e4be7ae..b25d2e3b0 100644
--- a/drivers/input/serio/rpckbd.c
+++ b/drivers/input/serio/rpckbd.c
@@ -33,6 +33,7 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/serio.h>
+#include <linux/err.h>
 
 #include <asm/irq.h>
 #include <asm/hardware.h>
@@ -44,6 +45,9 @@ MODULE_AUTHOR("Vojtech Pavlik, Russell King");
 MODULE_DESCRIPTION("Acorn RiscPC PS/2 keyboard controller driver");
 MODULE_LICENSE("GPL");
 
+static struct serio *rpckbd_port;
+static struct platform_device *rpckbd_device;
+
 static int rpckbd_write(struct serio *port, unsigned char val)
 {
 	while (!(iomd_readb(IOMD_KCTRL) & (1 << 7)))
@@ -101,25 +105,49 @@ static void rpckbd_close(struct serio *port)
 	free_irq(IRQ_KEYBOARDTX, port);
 }
 
-static struct serio rpckbd_port =
+/*
+ * Allocate and initialize serio structure for subsequent registration
+ * with serio core.
+ */
+
+static struct serio * __init rpckbd_allocate_port(void)
 {
-	.type	= SERIO_8042,
-	.open	= rpckbd_open,
-	.close	= rpckbd_close,
-	.write	= rpckbd_write,
-	.name	= "RiscPC PS/2 kbd port",
-	.phys	= "rpckbd/serio0",
-};
+	struct serio *serio;
+
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (serio) {
+		memset(serio, 0, sizeof(struct serio));
+		serio->type		= SERIO_8042;
+		serio->write		= rpckbd_write;
+		serio->open		= rpckbd_open;
+		serio->close		= rpckbd_close;
+		serio->dev.parent	= &rpckbd_device->dev;
+		strlcpy(serio->name, "RiscPC PS/2 kbd port", sizeof(serio->name));
+		strlcpy(serio->phys, "rpckbd/serio0", sizeof(serio->phys));
+	}
+
+	return serio;
+}
 
 static int __init rpckbd_init(void)
 {
-	serio_register_port(&rpckbd_port);
+	rpckbd_device = platform_device_register_simple("rpckbd", -1, NULL, 0);
+	if (IS_ERR(rpckbd_device))
+		return PTR_ERR(rpckbd_device);
+
+	if (!(rpckbd_port = rpckbd_allocate_port())) {
+		platform_device_unregister(rpckbd_device);
+		return -ENOMEM;
+	}
+
+	serio_register_port(rpckbd_port);
 	return 0;
 }
 
 static void __exit rpckbd_exit(void)
 {
-	serio_unregister_port(&rpckbd_port);
+	serio_unregister_port(rpckbd_port);
+	platform_device_unregister(rpckbd_device);
 }
 
 module_init(rpckbd_init);
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
index 9beb7575c..62937f5b3 100644
--- a/drivers/input/serio/sa1111ps2.c
+++ b/drivers/input/serio/sa1111ps2.c
@@ -26,7 +26,7 @@
 #include <asm/hardware/sa1111.h>
 
 struct ps2if {
-	struct serio		io;
+	struct serio		*io;
 	struct sa1111_dev	*dev;
 	unsigned long		base;
 	unsigned int		open;
@@ -59,7 +59,7 @@ static irqreturn_t ps2_rxint(int irq, void *dev_id, struct pt_regs *regs)
 		if (hweight8(scancode) & 1)
 			flag ^= SERIO_PARITY;
 
-		serio_interrupt(&ps2if->io, scancode, flag, regs);
+		serio_interrupt(ps2if->io, scancode, flag, regs);
 
 		status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
         }
@@ -95,7 +95,7 @@ static irqreturn_t ps2_txint(int irq, void *dev_id, struct pt_regs *regs)
  */
 static int ps2_write(struct serio *io, unsigned char val)
 {
-	struct ps2if *ps2if = io->driver;
+	struct ps2if *ps2if = io->port_data;
 	unsigned long flags;
 	unsigned int head;
 
@@ -122,7 +122,7 @@ static int ps2_write(struct serio *io, unsigned char val)
 
 static int ps2_open(struct serio *io)
 {
-	struct ps2if *ps2if = io->driver;
+	struct ps2if *ps2if = io->port_data;
 	int ret;
 
 	sa1111_enable_device(ps2if->dev);
@@ -154,7 +154,7 @@ static int ps2_open(struct serio *io)
 
 static void ps2_close(struct serio *io)
 {
-	struct ps2if *ps2if = io->driver;
+	struct ps2if *ps2if = io->port_data;
 
 	sa1111_writel(0, ps2if->base + SA1111_PS2CR);
 
@@ -232,22 +232,28 @@ static int __init ps2_test(struct ps2if *ps2if)
 static int ps2_probe(struct sa1111_dev *dev)
 {
 	struct ps2if *ps2if;
+	struct serio *serio;
 	int ret;
 
 	ps2if = kmalloc(sizeof(struct ps2if), GFP_KERNEL);
-	if (!ps2if) {
-		return -ENOMEM;
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (!ps2if || !serio) {
+		ret = -ENOMEM;
+		goto free;
 	}
 
 	memset(ps2if, 0, sizeof(struct ps2if));
-
-	ps2if->io.type		= SERIO_8042;
-	ps2if->io.write		= ps2_write;
-	ps2if->io.open		= ps2_open;
-	ps2if->io.close		= ps2_close;
-	ps2if->io.name		= dev->dev.bus_id;
-	ps2if->io.phys		= dev->dev.bus_id;
-	ps2if->io.driver	= ps2if;
+	memset(serio, 0, sizeof(struct serio));
+
+	serio->type		= SERIO_8042;
+	serio->write		= ps2_write;
+	serio->open		= ps2_open;
+	serio->close		= ps2_close;
+	strlcpy(serio->name, dev->dev.bus_id, sizeof(serio->name));
+	strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
+	serio->port_data	= ps2if;
+	serio->dev.parent	= &dev->dev;
+	ps2if->io		= serio;
 	ps2if->dev		= dev;
 	sa1111_set_drvdata(dev, ps2if);
 
@@ -292,7 +298,7 @@ static int ps2_probe(struct sa1111_dev *dev)
 	ps2_clear_input(ps2if);
 
 	sa1111_disable_device(ps2if->dev);
-	serio_register_port(&ps2if->io);
+	serio_register_port(ps2if->io);
 	return 0;
 
  out:
@@ -302,6 +308,7 @@ static int ps2_probe(struct sa1111_dev *dev)
  free:
 	sa1111_set_drvdata(dev, NULL);
 	kfree(ps2if);
+	kfree(serio);
 	return ret;
 }
 
@@ -312,7 +319,7 @@ static int ps2_remove(struct sa1111_dev *dev)
 {
 	struct ps2if *ps2if = sa1111_get_drvdata(dev);
 
-	serio_unregister_port(&ps2if->io);
+	serio_unregister_port(ps2if->io);
 	release_mem_region(dev->res.start,
 			   dev->res.end - dev->res.start + 1);
 	sa1111_set_drvdata(dev, NULL);
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 6f003197b..268ca1d63 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -1,11 +1,9 @@
-/*
- * $Id: serio.c,v 1.15 2002/01/22 21:12:03 vojtech Exp $
- *
- *  Copyright (c) 1999-2001 Vojtech Pavlik
- */
-
 /*
  *  The Serio abstraction module
+ *
+ *  Copyright (c) 1999-2004 Vojtech Pavlik
+ *  Copyright (c) 2004 Dmitry Torokhov
+ *  Copyright (c) 2003 Daniele Bellucci
  */
 
 /*
@@ -26,10 +24,6 @@
  * Should you need to contact me, the author, you can do so either by
  * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
  * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
- *
- * Changes:
- * 20 Jul. 2003    Daniele Bellucci <bellucda@tiscali.it>
- *                 Minor cleanups.
  */
 
 #include <linux/stddef.h>
@@ -50,100 +44,178 @@ MODULE_LICENSE("GPL");
 EXPORT_SYMBOL(serio_interrupt);
 EXPORT_SYMBOL(serio_register_port);
 EXPORT_SYMBOL(serio_register_port_delayed);
-EXPORT_SYMBOL(__serio_register_port);
 EXPORT_SYMBOL(serio_unregister_port);
 EXPORT_SYMBOL(serio_unregister_port_delayed);
-EXPORT_SYMBOL(__serio_unregister_port);
-EXPORT_SYMBOL(serio_register_device);
-EXPORT_SYMBOL(serio_unregister_device);
+EXPORT_SYMBOL(serio_register_driver);
+EXPORT_SYMBOL(serio_unregister_driver);
 EXPORT_SYMBOL(serio_open);
 EXPORT_SYMBOL(serio_close);
 EXPORT_SYMBOL(serio_rescan);
 EXPORT_SYMBOL(serio_reconnect);
 
+static DECLARE_MUTEX(serio_sem);	/* protects serio_list and serio_diriver_list */
+static LIST_HEAD(serio_list);
+static LIST_HEAD(serio_driver_list);
+static unsigned int serio_no;
+
+struct bus_type serio_bus = {
+	.name =	"serio",
+};
+
+static void serio_find_driver(struct serio *serio);
+static void serio_create_port(struct serio *serio);
+static void serio_destroy_port(struct serio *serio);
+static void serio_connect_port(struct serio *serio, struct serio_driver *drv);
+static void serio_reconnect_port(struct serio *serio);
+static void serio_disconnect_port(struct serio *serio);
+
+static int serio_bind_driver(struct serio *serio, struct serio_driver *drv)
+{
+	get_driver(&drv->driver);
+
+	drv->connect(serio, drv);
+	if (serio->drv) {
+		down_write(&serio_bus.subsys.rwsem);
+		serio->dev.driver = &drv->driver;
+		device_bind_driver(&serio->dev);
+		up_write(&serio_bus.subsys.rwsem);
+		return 1;
+	}
+
+	put_driver(&drv->driver);
+	return 0;
+}
+
+/* serio_find_driver() must be called with serio_sem down.  */
+static void serio_find_driver(struct serio *serio)
+{
+	struct serio_driver *drv;
+
+	list_for_each_entry(drv, &serio_driver_list, node)
+		if (!drv->manual_bind)
+			if (serio_bind_driver(serio, drv))
+				break;
+}
+
+/*
+ * Serio event processing.
+ */
+
 struct serio_event {
 	int type;
 	struct serio *serio;
 	struct list_head node;
 };
 
-static DECLARE_MUTEX(serio_sem);
-static LIST_HEAD(serio_list);
-static LIST_HEAD(serio_dev_list);
+enum serio_event_type {
+	SERIO_RESCAN,
+	SERIO_RECONNECT,
+	SERIO_REGISTER_PORT,
+	SERIO_UNREGISTER_PORT,
+};
+
+static spinlock_t serio_event_lock = SPIN_LOCK_UNLOCKED;	/* protects serio_event_list */
 static LIST_HEAD(serio_event_list);
+static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
+static DECLARE_COMPLETION(serio_exited);
 static int serio_pid;
 
-static void serio_find_dev(struct serio *serio)
+static void serio_queue_event(struct serio *serio, int event_type)
 {
-	struct serio_dev *dev;
+	unsigned long flags;
+	struct serio_event *event;
 
-	list_for_each_entry(dev, &serio_dev_list, node) {
-		if (serio->dev)
-			break;
-		if (dev->connect)
-			dev->connect(serio, dev);
-	}
-}
+	spin_lock_irqsave(&serio_event_lock, flags);
 
-#define SERIO_RESCAN		1
-#define SERIO_RECONNECT		2
-#define SERIO_REGISTER_PORT	3
-#define SERIO_UNREGISTER_PORT	4
+	if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
+		event->type = event_type;
+		event->serio = serio;
 
-static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
-static DECLARE_COMPLETION(serio_exited);
+		list_add_tail(&event->node, &serio_event_list);
+		wake_up(&serio_wait);
+	}
+
+	spin_unlock_irqrestore(&serio_event_lock, flags);
+}
 
-static void serio_invalidate_pending_events(struct serio *serio)
+static struct serio_event *serio_get_event(void)
 {
 	struct serio_event *event;
+	struct list_head *node;
+	unsigned long flags;
+
+	spin_lock_irqsave(&serio_event_lock, flags);
+
+	if (list_empty(&serio_event_list)) {
+		spin_unlock_irqrestore(&serio_event_lock, flags);
+		return NULL;
+	}
+
+	node = serio_event_list.next;
+	event = container_of(node, struct serio_event, node);
+	list_del_init(node);
+
+	spin_unlock_irqrestore(&serio_event_lock, flags);
 
-	list_for_each_entry(event, &serio_event_list, node)
-		if (event->serio == serio)
-			event->serio = NULL;
+	return event;
 }
 
-void serio_handle_events(void)
+static void serio_handle_events(void)
 {
-	struct list_head *node, *next;
 	struct serio_event *event;
 
-	list_for_each_safe(node, next, &serio_event_list) {
-		event = container_of(node, struct serio_event, node);
+	while ((event = serio_get_event())) {
 
 		down(&serio_sem);
-		if (event->serio == NULL)
-			goto event_done;
 
 		switch (event->type) {
 			case SERIO_REGISTER_PORT :
-				__serio_register_port(event->serio);
+				serio_create_port(event->serio);
+				serio_connect_port(event->serio, NULL);
 				break;
 
 			case SERIO_UNREGISTER_PORT :
-				__serio_unregister_port(event->serio);
+				serio_disconnect_port(event->serio);
+				serio_destroy_port(event->serio);
 				break;
 
 			case SERIO_RECONNECT :
-				if (event->serio->dev && event->serio->dev->reconnect)
-					if (event->serio->dev->reconnect(event->serio) == 0)
-						break;
-				/* reconnect failed - fall through to rescan */
+				serio_reconnect_port(event->serio);
+				break;
 
 			case SERIO_RESCAN :
-				if (event->serio->dev && event->serio->dev->disconnect)
-					event->serio->dev->disconnect(event->serio);
-				serio_find_dev(event->serio);
+				serio_disconnect_port(event->serio);
+				serio_connect_port(event->serio, NULL);
 				break;
 			default:
 				break;
 		}
-event_done:
+
 		up(&serio_sem);
-		list_del_init(node);
 		kfree(event);
 	}
 }
 
+static void serio_remove_pending_events(struct serio *serio)
+{
+	struct list_head *node, *next;
+	struct serio_event *event;
+	unsigned long flags;
+
+	spin_lock_irqsave(&serio_event_lock, flags);
+
+	list_for_each_safe(node, next, &serio_event_list) {
+		event = container_of(node, struct serio_event, node);
+		if (event->serio == serio) {
+			list_del_init(node);
+			kfree(event);
+		}
+	}
+
+	spin_unlock_irqrestore(&serio_event_lock, flags);
+}
+
+
 static int serio_thread(void *nothing)
 {
 	lock_kernel();
@@ -163,52 +235,239 @@ static int serio_thread(void *nothing)
 	complete_and_exit(&serio_exited, 0);
 }
 
-static void serio_queue_event(struct serio *serio, int event_type)
+
+/*
+ * Serio port operations
+ */
+
+static ssize_t serio_show_description(struct device *dev, char *buf)
 {
-	struct serio_event *event;
+	struct serio *serio = to_serio_port(dev);
+	return sprintf(buf, "%s\n", serio->name);
+}
 
-	if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
-		event->type = event_type;
-		event->serio = serio;
+static ssize_t serio_show_driver(struct device *dev, char *buf)
+{
+	return sprintf(buf, "%s\n", dev->driver ? dev->driver->name : "(none)");
+}
 
-		list_add_tail(&event->node, &serio_event_list);
-		wake_up(&serio_wait);
+static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t count)
+{
+	struct serio *serio = to_serio_port(dev);
+	struct device_driver *drv;
+	int retval;
+
+	retval = down_interruptible(&serio_sem);
+	if (retval)
+		return retval;
+
+	retval = count;
+	if (!strncmp(buf, "none", count)) {
+		serio_disconnect_port(serio);
+	} else if (!strncmp(buf, "reconnect", count)) {
+		serio_reconnect_port(serio);
+	} else if (!strncmp(buf, "rescan", count)) {
+		serio_disconnect_port(serio);
+		serio_connect_port(serio, NULL);
+	} else if ((drv = driver_find(buf, &serio_bus)) != NULL) {
+		serio_disconnect_port(serio);
+		serio_connect_port(serio, to_serio_driver(drv));
+		put_driver(drv);
+	} else {
+		retval = -EINVAL;
 	}
+
+	up(&serio_sem);
+
+	return retval;
 }
 
-void serio_rescan(struct serio *serio)
+static ssize_t serio_show_bind_mode(struct device *dev, char *buf)
 {
-	serio_queue_event(serio, SERIO_RESCAN);
+	struct serio *serio = to_serio_port(dev);
+	return sprintf(buf, "%s\n", serio->manual_bind ? "manual" : "auto");
 }
 
-void serio_reconnect(struct serio *serio)
+static ssize_t serio_set_bind_mode(struct device *dev, const char *buf, size_t count)
 {
-	serio_queue_event(serio, SERIO_RECONNECT);
+	struct serio *serio = to_serio_port(dev);
+	int retval;
+
+	retval = count;
+	if (!strncmp(buf, "manual", count)) {
+		serio->manual_bind = 1;
+	} else if (!strncmp(buf, "auto", count)) {
+		serio->manual_bind = 0;
+	} else {
+		retval = -EINVAL;
+	}
+
+	return retval;
 }
 
-irqreturn_t serio_interrupt(struct serio *serio,
-		unsigned char data, unsigned int flags, struct pt_regs *regs)
+static struct device_attribute serio_device_attrs[] = {
+	__ATTR(description, S_IRUGO, serio_show_description, NULL),
+	__ATTR(driver, S_IWUSR | S_IRUGO, serio_show_driver, serio_rebind_driver),
+	__ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode),
+	__ATTR_NULL
+};
+
+
+static void serio_release_port(struct device *dev)
 {
-	irqreturn_t ret = IRQ_NONE;
+	struct serio *serio = to_serio_port(dev);
 
-        if (serio->dev && serio->dev->interrupt) {
-                ret = serio->dev->interrupt(serio, data, flags, regs);
-	} else {
-		if (!flags) {
-			if ((serio->type == SERIO_8042 ||
-				serio->type == SERIO_8042_XL) && (data != 0xaa))
-					return ret;
-			serio_rescan(serio);
-			ret = IRQ_HANDLED;
+	kfree(serio);
+	module_put(THIS_MODULE);
+}
+
+static void serio_create_port(struct serio *serio)
+{
+	try_module_get(THIS_MODULE);
+
+	spin_lock_init(&serio->lock);
+	list_add_tail(&serio->node, &serio_list);
+	snprintf(serio->dev.bus_id, sizeof(serio->dev.bus_id), "serio%d", serio_no++);
+	serio->dev.bus = &serio_bus;
+	serio->dev.release = serio_release_port;
+	if (serio->parent)
+		serio->dev.parent = &serio->parent->dev;
+	device_register(&serio->dev);
+}
+
+/*
+ * serio_destroy_port() completes deregistration process and removes
+ * port from the system
+ */
+static void serio_destroy_port(struct serio *serio)
+{
+	struct serio_driver *drv = serio->drv;
+	unsigned long flags;
+
+	serio_remove_pending_events(serio);
+	list_del_init(&serio->node);
+
+	if (drv) {
+		drv->disconnect(serio);
+		down_write(&serio_bus.subsys.rwsem);
+		device_release_driver(&serio->dev);
+		up_write(&serio_bus.subsys.rwsem);
+		put_driver(&drv->driver);
+	}
+
+	if (serio->parent) {
+		spin_lock_irqsave(&serio->parent->lock, flags);
+		serio->parent->child = NULL;
+		spin_unlock_irqrestore(&serio->parent->lock, flags);
+	}
+
+	device_unregister(&serio->dev);
+}
+
+/*
+ * serio_connect_port() tries to bind the port and possible all its
+ * children to appropriate drivers. If driver passed in the function will not
+ * try otehr drivers when binding parent port.
+ */
+static void serio_connect_port(struct serio *serio, struct serio_driver *drv)
+{
+	WARN_ON(serio->drv);
+	WARN_ON(serio->child);
+
+	if (drv)
+		serio_bind_driver(serio, drv);
+	else if (!serio->manual_bind)
+		serio_find_driver(serio);
+
+	/* Ok, now bind children, if any */
+	while (serio->child) {
+		serio = serio->child;
+
+		WARN_ON(serio->drv);
+		WARN_ON(serio->child);
+
+		serio_create_port(serio);
+
+		if (!serio->manual_bind) {
+			/*
+			 * With children we just _prefer_ passed in driver,
+			 * but we will try other options in case preferred
+			 * is not the one
+			 */
+			if (!drv || !serio_bind_driver(serio, drv))
+				serio_find_driver(serio);
 		}
 	}
-	return ret;
+}
+
+/*
+ *
+ */
+static void serio_reconnect_port(struct serio *serio)
+{
+	do {
+		if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) {
+			serio_disconnect_port(serio);
+			serio_connect_port(serio, NULL);
+			/* Ok, old children are now gone, we are done */
+			break;
+		}
+		serio = serio->child;
+	} while (serio);
+}
+
+/*
+ * serio_disconnect_port() unbinds a port from its driver. As a side effect
+ * all child ports are unbound and destroyed.
+ */
+static void serio_disconnect_port(struct serio *serio)
+{
+	struct serio_driver *drv = serio->drv;
+	struct serio *s;
+
+	if (serio->child) {
+		/*
+		 * Children ports should be disconnected and destroyed
+		 * first, staring with the leaf one, since we don't want
+		 * to do recursion
+		 */
+		do {
+			s = serio->child;
+		} while (s->child);
+
+		while (s != serio) {
+			s = s->parent;
+			serio_destroy_port(s->child);
+		}
+	}
+
+	/*
+	 * Ok, no children left, now disconnect this port
+	 */
+	if (drv) {
+		drv->disconnect(serio);
+		down_write(&serio_bus.subsys.rwsem);
+		device_release_driver(&serio->dev);
+		up_write(&serio_bus.subsys.rwsem);
+		put_driver(&drv->driver);
+	}
+}
+
+void serio_rescan(struct serio *serio)
+{
+	serio_queue_event(serio, SERIO_RESCAN);
+}
+
+void serio_reconnect(struct serio *serio)
+{
+	serio_queue_event(serio, SERIO_RECONNECT);
 }
 
 void serio_register_port(struct serio *serio)
 {
 	down(&serio_sem);
-	__serio_register_port(serio);
+	serio_create_port(serio);
+	serio_connect_port(serio, NULL);
 	up(&serio_sem);
 }
 
@@ -222,21 +481,11 @@ void serio_register_port_delayed(struct serio *serio)
 	serio_queue_event(serio, SERIO_REGISTER_PORT);
 }
 
-/*
- * Should only be called directly if serio_sem has already been taken,
- * for example when unregistering a serio from other input device's
- * connect() function.
- */
-void __serio_register_port(struct serio *serio)
-{
-	list_add_tail(&serio->node, &serio_list);
-	serio_find_dev(serio);
-}
-
 void serio_unregister_port(struct serio *serio)
 {
 	down(&serio_sem);
-	__serio_unregister_port(serio);
+	serio_disconnect_port(serio);
+	serio_destroy_port(serio);
 	up(&serio_sem);
 }
 
@@ -250,82 +499,171 @@ void serio_unregister_port_delayed(struct serio *serio)
 	serio_queue_event(serio, SERIO_UNREGISTER_PORT);
 }
 
+
 /*
- * Should only be called directly if serio_sem has already been taken,
- * for example when unregistering a serio from other input device's
- * disconnect() function.
+ * Serio driver operations
  */
-void __serio_unregister_port(struct serio *serio)
+
+static ssize_t serio_driver_show_description(struct device_driver *drv, char *buf)
 {
-	serio_invalidate_pending_events(serio);
-	list_del_init(&serio->node);
-	if (serio->dev && serio->dev->disconnect)
-		serio->dev->disconnect(serio);
+	struct serio_driver *driver = to_serio_driver(drv);
+	return sprintf(buf, "%s\n", driver->description ? driver->description : "(none)");
+}
+
+static ssize_t serio_driver_show_bind_mode(struct device_driver *drv, char *buf)
+{
+	struct serio_driver *serio_drv = to_serio_driver(drv);
+	return sprintf(buf, "%s\n", serio_drv->manual_bind ? "manual" : "auto");
 }
 
-void serio_register_device(struct serio_dev *dev)
+static ssize_t serio_driver_set_bind_mode(struct device_driver *drv, const char *buf, size_t count)
+{
+	struct serio_driver *serio_drv = to_serio_driver(drv);
+	int retval;
+
+	retval = count;
+	if (!strncmp(buf, "manual", count)) {
+		serio_drv->manual_bind = 1;
+	} else if (!strncmp(buf, "auto", count)) {
+		serio_drv->manual_bind = 0;
+	} else {
+		retval = -EINVAL;
+	}
+
+	return retval;
+}
+
+
+static struct driver_attribute serio_driver_attrs[] = {
+	__ATTR(description, S_IRUGO, serio_driver_show_description, NULL),
+	__ATTR(bind_mode, S_IWUSR | S_IRUGO,
+		serio_driver_show_bind_mode, serio_driver_set_bind_mode),
+	__ATTR_NULL
+};
+
+void serio_register_driver(struct serio_driver *drv)
 {
 	struct serio *serio;
+
 	down(&serio_sem);
-	list_add_tail(&dev->node, &serio_dev_list);
-	list_for_each_entry(serio, &serio_list, node)
-		if (!serio->dev && dev->connect)
-			dev->connect(serio, dev);
+
+	list_add_tail(&drv->node, &serio_driver_list);
+
+	drv->driver.bus = &serio_bus;
+	driver_register(&drv->driver);
+
+	if (drv->manual_bind)
+		goto out;
+
+start_over:
+	list_for_each_entry(serio, &serio_list, node) {
+		if (!serio->drv) {
+			serio_connect_port(serio, drv);
+			/*
+			 * if new child appeared then the list is changed,
+			 * we need to start over
+			 */
+			if (serio->child)
+				goto start_over;
+		}
+	}
+
+out:
 	up(&serio_sem);
 }
 
-void serio_unregister_device(struct serio_dev *dev)
+void serio_unregister_driver(struct serio_driver *drv)
 {
 	struct serio *serio;
 
 	down(&serio_sem);
-	list_del_init(&dev->node);
 
+	list_del_init(&drv->node);
+
+start_over:
 	list_for_each_entry(serio, &serio_list, node) {
-		if (serio->dev == dev && dev->disconnect)
-			dev->disconnect(serio);
-		serio_find_dev(serio);
+		if (serio->drv == drv) {
+			serio_disconnect_port(serio);
+			serio_connect_port(serio, NULL);
+			/* we could've deleted some ports, restart */
+			goto start_over;
+		}
 	}
+
+	driver_unregister(&drv->driver);
+
 	up(&serio_sem);
 }
 
-/* called from serio_dev->connect/disconnect methods under serio_sem */
-int serio_open(struct serio *serio, struct serio_dev *dev)
+/* called from serio_driver->connect/disconnect methods under serio_sem */
+int serio_open(struct serio *serio, struct serio_driver *drv)
 {
-	serio->dev = dev;
+	serio_pause_rx(serio);
+	serio->drv = drv;
+	serio_continue_rx(serio);
+
 	if (serio->open && serio->open(serio)) {
-		serio->dev = NULL;
+		serio_pause_rx(serio);
+		serio->drv = NULL;
+		serio_continue_rx(serio);
 		return -1;
 	}
 	return 0;
 }
 
-/* called from serio_dev->connect/disconnect methods under serio_sem */
+/* called from serio_driver->connect/disconnect methods under serio_sem */
 void serio_close(struct serio *serio)
 {
 	if (serio->close)
 		serio->close(serio);
-	serio->dev = NULL;
+
+	serio_pause_rx(serio);
+	serio->drv = NULL;
+	serio_continue_rx(serio);
 }
 
-static int __init serio_init(void)
+irqreturn_t serio_interrupt(struct serio *serio,
+		unsigned char data, unsigned int dfl, struct pt_regs *regs)
 {
-	int pid;
+	unsigned long flags;
+	irqreturn_t ret = IRQ_NONE;
+
+	spin_lock_irqsave(&serio->lock, flags);
+
+        if (likely(serio->drv)) {
+                ret = serio->drv->interrupt(serio, data, dfl, regs);
+	} else {
+		if (!dfl) {
+			if ((serio->type != SERIO_8042 &&
+			     serio->type != SERIO_8042_XL) || (data == 0xaa)) {
+				serio_rescan(serio);
+				ret = IRQ_HANDLED;
+			}
+		}
+	}
+
+	spin_unlock_irqrestore(&serio->lock, flags);
 
-	pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL);
+	return ret;
+}
 
-	if (!pid) {
+static int __init serio_init(void)
+{
+	if (!(serio_pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL))) {
 		printk(KERN_WARNING "serio: Failed to start kseriod\n");
 		return -1;
 	}
 
-	serio_pid = pid;
+	serio_bus.dev_attrs = serio_device_attrs;
+	serio_bus.drv_attrs = serio_driver_attrs;
+	bus_register(&serio_bus);
 
 	return 0;
 }
 
 static void __exit serio_exit(void)
 {
+	bus_unregister(&serio_bus);
 	kill_proc(serio_pid, SIGTERM, 1);
 	wait_for_completion(&serio_exited);
 }
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
index 19e269249..5582ee822 100644
--- a/drivers/input/serio/serport.c
+++ b/drivers/input/serio/serport.c
@@ -31,28 +31,25 @@ MODULE_ALIAS_LDISC(N_MOUSE);
 struct serport {
 	struct tty_struct *tty;
 	wait_queue_head_t wait;
-	struct serio serio;
+	struct serio *serio;
 	unsigned long flags;
-	char phys[32];
 };
 
-char serport_name[] = "Serial port";
-
 /*
  * Callback functions from the serio code.
  */
 
 static int serport_serio_write(struct serio *serio, unsigned char data)
 {
-	struct serport *serport = serio->driver;
+	struct serport *serport = serio->port_data;
 	return -(serport->tty->driver->write(serport->tty, 0, &data, 1) != 1);
 }
 
 static void serport_serio_close(struct serio *serio)
 {
-	struct serport *serport = serio->driver;
+	struct serport *serport = serio->port_data;
 
-	serport->serio.type = 0;
+	serport->serio->type = 0;
 	wake_up_interruptible(&serport->wait);
 }
 
@@ -64,26 +61,30 @@ static void serport_serio_close(struct serio *serio)
 static int serport_ldisc_open(struct tty_struct *tty)
 {
 	struct serport *serport;
+	struct serio *serio;
 	char name[64];
 
 	serport = kmalloc(sizeof(struct serport), GFP_KERNEL);
-	if (unlikely(!serport))
+	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (unlikely(!serport || !serio)) {
+		kfree(serport);
+		kfree(serio);
 		return -ENOMEM;
-	memset(serport, 0, sizeof(struct serport));
+	}
 
+	memset(serport, 0, sizeof(struct serport));
+	serport->serio = serio;
 	set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
 	serport->tty = tty;
 	tty->disc_data = serport;
 
-	snprintf(serport->phys, sizeof(serport->phys), "%s/serio0", tty_name(tty, name));
-
-	serport->serio.name = serport_name;
-	serport->serio.phys = serport->phys;
-
-	serport->serio.type = SERIO_RS232;
-	serport->serio.write = serport_serio_write;
-	serport->serio.close = serport_serio_close;
-	serport->serio.driver = serport;
+	memset(serio, 0, sizeof(struct serio));
+	strlcpy(serio->name, "Serial port", sizeof(serio->name));
+	snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", tty_name(tty, name));
+	serio->type = SERIO_RS232;
+	serio->write = serport_serio_write;
+	serio->close = serport_serio_close;
+	serio->port_data = serport;
 
 	init_waitqueue_head(&serport->wait);
 
@@ -114,7 +115,7 @@ static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *c
 	struct serport *serport = (struct serport*) tty->disc_data;
 	int i;
 	for (i = 0; i < count; i++)
-		serio_interrupt(&serport->serio, cp[i], 0, NULL);
+		serio_interrupt(serport->serio, cp[i], 0, NULL);
 }
 
 /*
@@ -142,10 +143,10 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
 	if (test_and_set_bit(SERPORT_BUSY, &serport->flags))
 		return -EBUSY;
 
-	serio_register_port(&serport->serio);
+	serio_register_port(serport->serio);
 	printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name));
-	wait_event_interruptible(serport->wait, !serport->serio.type);
-	serio_unregister_port(&serport->serio);
+	wait_event_interruptible(serport->wait, !serport->serio->type);
+	serio_unregister_port(serport->serio);
 
 	clear_bit(SERPORT_BUSY, &serport->flags);
 
@@ -161,7 +162,7 @@ static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsi
 	struct serport *serport = (struct serport*) tty->disc_data;
 
 	if (cmd == SPIOCSTYPE)
-		return get_user(serport->serio.type, (unsigned long __user *) arg);
+		return get_user(serport->serio->type, (unsigned long __user *) arg);
 
 	return -EINVAL;
 }
@@ -170,7 +171,7 @@ static void serport_ldisc_write_wakeup(struct tty_struct * tty)
 {
 	struct serport *sp = (struct serport *) tty->disc_data;
 
-	serio_dev_write_wakeup(&sp->serio);
+	serio_drv_write_wakeup(sp->serio);
 }
 
 /*
diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c
index 775914980..e5e38dd4a 100644
--- a/drivers/input/touchscreen/gunze.c
+++ b/drivers/input/touchscreen/gunze.c
@@ -36,8 +36,10 @@
 #include <linux/serio.h>
 #include <linux/init.h>
 
+#define DRIVER_DESC	"Gunze AHL-51S touchscreen driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Gunze AHL-51S touchscreen driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -111,7 +113,7 @@ static void gunze_disconnect(struct serio *serio)
  * and if yes, registers it as an input device.
  */
 
-static void gunze_connect(struct serio *serio, struct serio_dev *dev)
+static void gunze_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct gunze *gunze;
 
@@ -142,7 +144,7 @@ static void gunze_connect(struct serio *serio, struct serio_dev *dev)
 	gunze->dev.id.product = 0x0051;
 	gunze->dev.id.version = 0x0100;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
 		kfree(gunze);
 		return;
 	}
@@ -156,10 +158,14 @@ static void gunze_connect(struct serio *serio, struct serio_dev *dev)
  * The serio device structure.
  */
 
-static struct serio_dev gunze_dev = {
-	.interrupt =	gunze_interrupt,
-	.connect =	gunze_connect,
-	.disconnect =	gunze_disconnect,
+static struct serio_driver gunze_drv = {
+	.driver		= {
+		.name	= "gunze",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= gunze_interrupt,
+	.connect	= gunze_connect,
+	.disconnect	= gunze_disconnect,
 };
 
 /*
@@ -168,13 +174,13 @@ static struct serio_dev gunze_dev = {
 
 int __init gunze_init(void)
 {
-	serio_register_device(&gunze_dev);
+	serio_register_driver(&gunze_drv);
 	return 0;
 }
 
 void __exit gunze_exit(void)
 {
-	serio_unregister_device(&gunze_dev);
+	serio_unregister_driver(&gunze_drv);
 }
 
 module_init(gunze_init);
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c
index 7b4c16d6f..5d719671c 100644
--- a/drivers/input/touchscreen/h3600_ts_input.c
+++ b/drivers/input/touchscreen/h3600_ts_input.c
@@ -45,8 +45,10 @@
 #include <asm/arch/hardware.h>
 #include <asm/arch/irqs.h>
 
+#define DRIVER_DESC	"H3600 touchscreen driver"
+
 MODULE_AUTHOR("James Simmons <jsimmons@transvirtual.com>");
-MODULE_DESCRIPTION("H3600 touchscreen driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -373,7 +375,7 @@ static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data,
  * new serio device. It looks whether it was registered as a H3600 touchscreen
  * and if yes, registers it as an input device.
  */
-static void h3600ts_connect(struct serio *serio, struct serio_dev *dev)
+static void h3600ts_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct h3600_dev *ts;
 
@@ -441,7 +443,7 @@ static void h3600ts_connect(struct serio *serio, struct serio_dev *dev)
 	ts->dev.id.product = 0x0666;  /* FIXME !!! We can ask the hardware */
 	ts->dev.id.version = 0x0100;
 
-	if (serio_open(serio, dev)) {
+	if (serio_open(serio, drv)) {
         	free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts);
         	free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts);
 		kfree(ts);
@@ -478,10 +480,14 @@ static void h3600ts_disconnect(struct serio *serio)
  * The serio device structure.
  */
 
-static struct serio_dev h3600ts_dev = {
-	.interrupt =	h3600ts_interrupt,
-	.connect =	h3600ts_connect,
-	.disconnect =	h3600ts_disconnect,
+static struct serio_driver h3600ts_drv = {
+	.driver		= {
+		.name	= "h3600ts",
+	},
+	.description	= DRIVER_DESC,
+	.interrupt	= h3600ts_interrupt,
+	.connect	= h3600ts_connect,
+	.disconnect	= h3600ts_disconnect,
 };
 
 /*
@@ -490,13 +496,13 @@ static struct serio_dev h3600ts_dev = {
 
 static int __init h3600ts_init(void)
 {
-	serio_register_device(&h3600ts_dev);
+	serio_register_driver(&h3600ts_drv);
 	return 0;
 }
 
 static void __exit h3600ts_exit(void)
 {
-	serio_unregister_device(&h3600ts_dev);
+	serio_unregister_driver(&h3600ts_drv);
 }
 
 module_init(h3600ts_init);
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index ac072d37c..18c37d8ac 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -3,32 +3,42 @@
  *
  *  Copyright (c) 2001 "Crazy" james Simmons 
  *
- *  Input driver to Touchscreen device driver module.
+ *  Compaq touchscreen protocol driver. The protocol emulated by this driver
+ *  is obsolete; for new programs use the tslib library which can read directly
+ *  from evdev and perform dejittering, variance filtering and calibration -
+ *  all in user space, not at kernel level. The meaning of this driver is
+ *  to allow usage of newer input drivers with old applications that use the
+ *  old /dev/h3600_ts and /dev/h3600_tsraw devices.
  *
- *  Sponsored by Transvirtual Technology
+ *  09-Apr-2004: Andrew Zabolotny <zap@homelink.ru>
+ *      Fixed to actually work, not just output random numbers.
+ *      Added support for both h3600_ts and h3600_tsraw protocol
+ *      emulation.
  */
 
 /*
  * 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 
+ * 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
- * 
+ *
  * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <jsimmons@transvirtual.com>.
+ * e-mail - mail your message to <jsimmons@infradead.org>.
  */
 
 #define TSDEV_MINOR_BASE 	128
 #define TSDEV_MINORS		32
+/* First 16 devices are h3600_ts compatible; second 16 are h3600_tsraw */
+#define TSDEV_MINOR_MASK	15
 #define TSDEV_BUFFER_SIZE	64
 
 #include <linux/slab.h>
@@ -52,48 +62,84 @@
 #define CONFIG_INPUT_TSDEV_SCREEN_Y	320
 #endif
 
+/* This driver emulates both protocols of the old h3600_ts and h3600_tsraw
+ * devices. The first one must output X/Y data in 'cooked' format, e.g.
+ * filtered, dejittered and calibrated. Second device just outputs raw
+ * data received from the hardware.
+ *
+ * This driver doesn't support filtering and dejittering; it supports only
+ * calibration. Filtering and dejittering must be done in the low-level
+ * driver, if needed, because it may gain additional benefits from knowing
+ * the low-level details, the nature of noise and so on.
+ *
+ * The driver precomputes a calibration matrix given the initial xres and
+ * yres values (quite innacurate for most touchscreens) that will result
+ * in a more or less expected range of output values. The driver supports
+ * the TS_SET_CAL ioctl, which will replace the calibration matrix with a
+ * new one, supposedly generated from the values taken from the raw device.
+ */
+
 MODULE_AUTHOR("James Simmons <jsimmons@transvirtual.com>");
 MODULE_DESCRIPTION("Input driver to touchscreen converter");
 MODULE_LICENSE("GPL");
 
 static int xres = CONFIG_INPUT_TSDEV_SCREEN_X;
 module_param(xres, uint, 0);
-MODULE_PARM_DESC(xres, "Horizontal screen resolution");
+MODULE_PARM_DESC(xres, "Horizontal screen resolution (can be negative for X-mirror)");
 
 static int yres = CONFIG_INPUT_TSDEV_SCREEN_Y;
 module_param(yres, uint, 0);
-MODULE_PARM_DESC(yres, "Vertical screen resolution");
+MODULE_PARM_DESC(yres, "Vertical screen resolution (can be negative for Y-mirror)");
+
+/* From Compaq's Touch Screen Specification version 0.2 (draft) */
+struct ts_event {
+	short pressure;
+	short x;
+	short y;
+	short millisecs;
+};
+
+struct ts_calibration {
+	int xscale;
+	int xtrans;
+	int yscale;
+	int ytrans;
+	int xyswap;
+};
 
 struct tsdev {
 	int exist;
 	int open;
 	int minor;
-	char name[16];
+	char name[8];
 	wait_queue_head_t wait;
 	struct list_head list;
 	struct input_handle handle;
+	int x, y, pressure;
+	struct ts_calibration cal;
 };
 
-/* From Compaq's Touch Screen Specification version 0.2 (draft) */
-typedef struct {
-	short pressure;
-	short x;
-	short y;
-	short millisecs;
-} TS_EVENT;
-
 struct tsdev_list {
 	struct fasync_struct *fasync;
 	struct list_head node;
 	struct tsdev *tsdev;
 	int head, tail;
-	int oldx, oldy, pendown;
-	TS_EVENT event[TSDEV_BUFFER_SIZE];
+	struct ts_event event[TSDEV_BUFFER_SIZE];
+	int raw;
 };
 
+/* The following ioctl codes are defined ONLY for backward compatibility.
+ * Don't use tsdev for new developement; use the tslib library instead.
+ * Touchscreen calibration is a fully userspace task.
+ */
+/* Use 'f' as magic number */
+#define IOC_H3600_TS_MAGIC  'f'
+#define TS_GET_CAL	_IOR(IOC_H3600_TS_MAGIC, 10, struct ts_calibration)
+#define TS_SET_CAL	_IOW(IOC_H3600_TS_MAGIC, 11, struct ts_calibration)
+
 static struct input_handler tsdev_handler;
 
-static struct tsdev *tsdev_table[TSDEV_MINORS];
+static struct tsdev *tsdev_table[TSDEV_MINORS/2];
 
 static int tsdev_fasync(int fd, struct file *file, int on)
 {
@@ -109,13 +155,16 @@ static int tsdev_open(struct inode *inode, struct file *file)
 	int i = iminor(inode) - TSDEV_MINOR_BASE;
 	struct tsdev_list *list;
 
-	if (i >= TSDEV_MINORS || !tsdev_table[i])
+	if (i >= TSDEV_MINORS || !tsdev_table[i & TSDEV_MINOR_MASK])
 		return -ENODEV;
 
 	if (!(list = kmalloc(sizeof(struct tsdev_list), GFP_KERNEL)))
 		return -ENOMEM;
 	memset(list, 0, sizeof(struct tsdev_list));
 
+	list->raw = (i >= TSDEV_MINORS/2) ? 1 : 0;
+
+	i &= TSDEV_MINOR_MASK;
 	list->tsdev = tsdev_table[i];
 	list_add_tail(&list->node, &tsdev_table[i]->list);
 	file->private_data = list;
@@ -161,7 +210,7 @@ static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count,
 		return -EAGAIN;
 
 	retval = wait_event_interruptible(list->tsdev->wait,
-		(list->head != list->tail) && list->tsdev->exist);
+			list->head != list->tail || !list->tsdev->exist);
 
 	if (retval)
 		return retval;
@@ -169,11 +218,13 @@ static ssize_t tsdev_read(struct file *file, char __user *buffer, size_t count,
 	if (!list->tsdev->exist)
 		return -ENODEV;
 
-	while (list->head != list->tail && retval + sizeof(TS_EVENT) <= count) {
-		if (copy_to_user (buffer + retval, list->event + list->tail, sizeof(TS_EVENT)))
+	while (list->head != list->tail &&
+	       retval + sizeof (struct ts_event) <= count) {
+		if (copy_to_user (buffer + retval, list->event + list->tail,
+				  sizeof (struct ts_event)))
 			return -EFAULT;
 		list->tail = (list->tail + 1) & (TSDEV_BUFFER_SIZE - 1);
-		retval += sizeof(TS_EVENT);
+		retval += sizeof (struct ts_event);
 	}
 
 	return retval;
@@ -193,22 +244,27 @@ static unsigned int tsdev_poll(struct file *file, poll_table * wait)
 static int tsdev_ioctl(struct inode *inode, struct file *file,
 		       unsigned int cmd, unsigned long arg)
 {
-/*
 	struct tsdev_list *list = file->private_data;
-        struct tsdev *evdev = list->tsdev;
-        struct input_dev *dev = tsdev->handle.dev;
-        int retval;
-	
+	struct tsdev *tsdev = list->tsdev;
+	int retval = 0;
+
 	switch (cmd) {
-		case HHEHE:
-			return 0;
-		case hjff:
-			return 0;
-		default:
-			return 0;
+	case TS_GET_CAL:
+		if (copy_to_user ((void __user *)arg, &tsdev->cal,
+				  sizeof (struct ts_calibration)))
+			retval = -EFAULT;
+		break;
+	case TS_SET_CAL:
+		if (copy_from_user (&tsdev->cal, (void __user *)arg,
+				    sizeof (struct ts_calibration)))
+			retval = -EFAULT;
+		break;
+	default:
+		retval = -EINVAL;
+		break;
 	}
-*/
-	return -EINVAL;
+
+	return retval;
 }
 
 struct file_operations tsdev_fops = {
@@ -227,82 +283,85 @@ static void tsdev_event(struct input_handle *handle, unsigned int type,
 	struct tsdev *tsdev = handle->private;
 	struct tsdev_list *list;
 	struct timeval time;
-	int size;
 
-	list_for_each_entry(list, &tsdev->list, node) {
-		switch (type) {
-		case EV_ABS:
-			switch (code) {
-			case ABS_X:
-				if (!list->pendown)
-					return;
-				size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X];
-				if (size > 0)
-					list->oldx = ((value - handle->dev->absmin[ABS_X]) * xres / size);
-				else
-					list->oldx = ((value - handle->dev->absmin[ABS_X]));
-				break;
-			case ABS_Y:
-				if (!list->pendown)
-					return;
-				size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y];
-				if (size > 0)
-					list->oldy = ((value - handle->dev->absmin[ABS_Y]) * yres / size);
-				else
-					list->oldy = ((value - handle->dev->absmin[ABS_Y]));
-				break;
-			case ABS_PRESSURE:
-				list->pendown = ((value > handle->dev-> absmin[ABS_PRESSURE])) ?
-				    value - handle->dev->absmin[ABS_PRESSURE] : 0;
-				break;
-			}
+	switch (type) {
+	case EV_ABS:
+		switch (code) {
+		case ABS_X:
+			tsdev->x = value;
+			break;
+		case ABS_Y:
+			tsdev->y = value;
 			break;
+		case ABS_PRESSURE:
+			if (value > handle->dev->absmax[ABS_PRESSURE])
+				value = handle->dev->absmax[ABS_PRESSURE];
+			value -= handle->dev->absmin[ABS_PRESSURE];
+			if (value < 0)
+				value = 0;
+			tsdev->pressure = value;
+			break;
+		}
+		break;
+
+	case EV_REL:
+		switch (code) {
+		case REL_X:
+			tsdev->x += value;
+			if (tsdev->x < 0)
+				tsdev->x = 0;
+			else if (tsdev->x > xres)
+				tsdev->x = xres;
+			break;
+		case REL_Y:
+			tsdev->y += value;
+			if (tsdev->y < 0)
+				tsdev->y = 0;
+			else if (tsdev->y > yres)
+				tsdev->y = yres;
+			break;
+		}
+		break;
 
-		case EV_REL:
-			switch (code) {
-			case REL_X:
-				if (!list->pendown)
-					return;
-				list->oldx += value;
-				if (list->oldx < 0)
-					list->oldx = 0;
-				else if (list->oldx > xres)
-					list->oldx = xres;
+	case EV_KEY:
+		if (code == BTN_TOUCH || code == BTN_MOUSE) {
+			switch (value) {
+			case 0:
+				tsdev->pressure = 0;
 				break;
-			case REL_Y:
-				if (!list->pendown)
-					return;
-				list->oldy += value;
-				if (list->oldy < 0)
-					list->oldy = 0;
-				else if (list->oldy > xres)
-					list->oldy = xres;
+			case 1:
+				if (!tsdev->pressure)
+					tsdev->pressure = 1;
 				break;
 			}
-			break;
-
-		case EV_KEY:
-			if (code == BTN_TOUCH || code == BTN_MOUSE) {
-				switch (value) {
-				case 0:
-					list->pendown = 0;
-					break;
-				case 1:
-					if (!list->pendown)
-						list->pendown = 1;
-					break;
-				case 2:
-					return;
-				}
-			} else
-				return;
-			break;
 		}
+		break;
+	}
+
+	if (type != EV_SYN || code != SYN_REPORT)
+		return;
+
+	list_for_each_entry(list, &tsdev->list, node) {
+		int x, y, tmp;
+
 		do_gettimeofday(&time);
 		list->event[list->head].millisecs = time.tv_usec / 100;
-		list->event[list->head].pressure = list->pendown;
-		list->event[list->head].x = list->oldx;
-		list->event[list->head].y = list->oldy;
+		list->event[list->head].pressure = tsdev->pressure;
+
+		x = tsdev->x;
+		y = tsdev->y;
+
+		/* Calibration */
+		if (!list->raw) {
+			x = ((x * tsdev->cal.xscale) >> 8) + tsdev->cal.xtrans;
+			y = ((y * tsdev->cal.yscale) >> 8) + tsdev->cal.ytrans;
+			if (tsdev->cal.xyswap) {
+				tmp = x; x = y; y = tmp;
+			}
+		}
+
+		list->event[list->head].x = x;
+		list->event[list->head].y = y;
 		list->head = (list->head + 1) & (TSDEV_BUFFER_SIZE - 1);
 		kill_fasync(&list->fasync, SIGIO, POLL_IN);
 	}
@@ -314,11 +373,11 @@ static struct input_handle *tsdev_connect(struct input_handler *handler,
 					  struct input_device_id *id)
 {
 	struct tsdev *tsdev;
-	int minor;
+	int minor, delta;
 
-	for (minor = 0; minor < TSDEV_MINORS && tsdev_table[minor];
+	for (minor = 0; minor < TSDEV_MINORS/2 && tsdev_table[minor];
 	     minor++);
-	if (minor == TSDEV_MINORS) {
+	if (minor >= TSDEV_MINORS/2) {
 		printk(KERN_ERR
 		       "tsdev: You have way too many touchscreens\n");
 		return NULL;
@@ -340,10 +399,25 @@ static struct input_handle *tsdev_connect(struct input_handler *handler,
 	tsdev->handle.handler = handler;
 	tsdev->handle.private = tsdev;
 
+	/* Precompute the rough calibration matrix */
+	delta = dev->absmax [ABS_X] - dev->absmin [ABS_X] + 1;
+	if (delta == 0)
+		delta = 1;
+	tsdev->cal.xscale = (xres << 8) / delta;
+	tsdev->cal.xtrans = - ((dev->absmin [ABS_X] * tsdev->cal.xscale) >> 8);
+
+	delta = dev->absmax [ABS_Y] - dev->absmin [ABS_Y] + 1;
+	if (delta == 0)
+		delta = 1;
+	tsdev->cal.yscale = (yres << 8) / delta;
+	tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8);
+
 	tsdev_table[minor] = tsdev;
-	
+
 	devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
 			S_IFCHR|S_IRUGO|S_IWUSR, "input/ts%d", minor);
+	devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor + TSDEV_MINORS/2),
+			S_IFCHR|S_IRUGO|S_IWUSR, "input/tsraw%d", minor);
 	class_simple_device_add(input_class, 
 				MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
 				dev->dev, "ts%d", minor);
@@ -362,6 +436,7 @@ static void tsdev_disconnect(struct input_handle *handle)
 		wake_up_interruptible(&tsdev->wait);
 	} else
 		tsdev_free(tsdev);
+	devfs_remove("input/tsraw%d", tsdev->minor);
 }
 
 static struct input_device_id tsdev_ids[] = {
@@ -379,6 +454,12 @@ static struct input_device_id tsdev_ids[] = {
 	      .absbit	= { BIT(ABS_X) | BIT(ABS_Y) },
 	 },/* A tablet like device, at least touch detection, two absolute axes */
 
+	{
+	      .flags	= INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
+	      .evbit	= { BIT(EV_ABS) },
+	      .absbit	= { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) },
+	 },/* A tablet like device with several gradations of pressure */
+
 	{},/* Terminating entry */
 };
 
diff --git a/drivers/isdn/act2000/act2000_isa.c b/drivers/isdn/act2000/act2000_isa.c
index e84aa5fb3..b363d0976 100644
--- a/drivers/isdn/act2000/act2000_isa.c
+++ b/drivers/isdn/act2000/act2000_isa.c
@@ -434,7 +434,10 @@ act2000_isa_download(act2000_card * card, act2000_ddef __user * cb)
                 l = (length > 1024) ? 1024 : length;
                 c = 0;
                 b = buf;
-                copy_from_user(buf, p, l);
+                if (copy_from_user(buf, p, l)) {
+                        kfree(buf);
+                        return -EFAULT;
+                }
                 while (c < l) {
                         if (act2000_isa_writeb(card, *b++)) {
                                 printk(KERN_WARNING
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 3429d57e2..9370808bb 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -436,51 +436,62 @@ static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
 	struct sk_buff *nskb;
 	int datalen;
 	u16 errcode, datahandle;
-
+	struct tty_ldisc *ld;
+	
 	datalen = skb->len - CAPIMSG_LEN(skb->data);
-	if (mp->tty) {
-		if (mp->tty->ldisc.receive_buf == 0) {
-			printk(KERN_ERR "capi: ldisc has no receive_buf function\n");
-			return -1;
-		}
-		if (mp->ttyinstop) {
+	if (mp->tty == NULL)
+	{
+#ifdef _DEBUG_DATAFLOW
+		printk(KERN_DEBUG "capi: currently no receiver\n");
+#endif
+		return -1;
+	}
+	
+	ld = tty_ldisc_ref(mp->tty);
+	if (ld == NULL)
+		return -1;
+	if (ld->receive_buf == NULL) {
 #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
-			printk(KERN_DEBUG "capi: recv tty throttled\n");
+		printk(KERN_DEBUG "capi: ldisc has no receive_buf function\n");
 #endif
-			return -1;
-		}
-		if (mp->tty->ldisc.receive_room &&
-		    mp->tty->ldisc.receive_room(mp->tty) < datalen) {
+		goto bad;
+	}
+	if (mp->ttyinstop) {
 #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
-			printk(KERN_DEBUG "capi: no room in tty\n");
+		printk(KERN_DEBUG "capi: recv tty throttled\n");
 #endif
-			return -1;
-		}
-		if ((nskb = gen_data_b3_resp_for(mp, skb)) == 0) {
-			printk(KERN_ERR "capi: gen_data_b3_resp failed\n");
-			return -1;
-		}
-		datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4);
-		errcode = capi20_put_message(mp->ap, nskb);
-		if (errcode != CAPI_NOERROR) {
-			printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n",
-					errcode);
-			kfree_skb(nskb);
-			return -1;
-		}
-		(void)skb_pull(skb, CAPIMSG_LEN(skb->data));
-#ifdef _DEBUG_DATAFLOW
-		printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n",
-					datahandle, skb->len);
+		goto bad;
+	}
+	if (ld->receive_room &&
+	    ld->receive_room(mp->tty) < datalen) {
+#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
+		printk(KERN_DEBUG "capi: no room in tty\n");
 #endif
-		mp->tty->ldisc.receive_buf(mp->tty, skb->data, NULL, skb->len);
-		kfree_skb(skb);
-		return 0;
-
+		goto bad;
 	}
+	if ((nskb = gen_data_b3_resp_for(mp, skb)) == 0) {
+		printk(KERN_ERR "capi: gen_data_b3_resp failed\n");
+		goto bad;
+	}
+	datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4);
+	errcode = capi20_put_message(mp->ap, nskb);
+	if (errcode != CAPI_NOERROR) {
+		printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n",
+				errcode);
+		kfree_skb(nskb);
+		goto bad;
+	}
+	(void)skb_pull(skb, CAPIMSG_LEN(skb->data));
 #ifdef _DEBUG_DATAFLOW
-	printk(KERN_DEBUG "capi: currently no receiver\n");
+	printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n",
+				datahandle, skb->len);
 #endif
+	ld->receive_buf(mp->tty, skb->data, NULL, skb->len);
+	kfree_skb(skb);
+	tty_ldisc_deref(ld);
+	return 0;
+bad:
+	tty_ldisc_deref(ld);
 	return -1;
 }
 
@@ -614,6 +625,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
 
 
 	if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) {
+		
 		datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+4+2);
 #ifdef _DEBUG_DATAFLOW
 		printk(KERN_DEBUG "capi_signal: DATA_B3_IND %u len=%d\n",
@@ -633,10 +645,8 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
 #endif
 		kfree_skb(skb);
 		(void)capiminor_del_ack(mp, datahandle);
-		if (mp->tty) {
-			if (mp->tty->ldisc.write_wakeup)
-				mp->tty->ldisc.write_wakeup(mp->tty);
-		}
+		if (mp->tty)
+			tty_wakeup(mp->tty);
 		(void)handle_minor_send(mp);
 
 	} else {
diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
index 150e31d32..44efe1906 100644
--- a/drivers/isdn/capi/capidrv.c
+++ b/drivers/isdn/capi/capidrv.c
@@ -512,7 +512,8 @@ static void send_message(capidrv_contr * card, _cmsg * cmsg)
 	len = CAPIMSG_LEN(cmsg->buf);
 	skb = alloc_skb(len, GFP_ATOMIC);
 	memcpy(skb_put(skb, len), cmsg->buf, len);
-	capi20_put_message(&global.ap, skb);
+	if (capi20_put_message(&global.ap, skb) != CAPI_NOERROR)
+		kfree_skb(skb);
 }
 
 /* -------- state machine -------------------------------------------- */
diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c
index c87516ab2..0c7061d55 100644
--- a/drivers/isdn/hardware/avm/b1.c
+++ b/drivers/isdn/hardware/avm/b1.c
@@ -389,7 +389,7 @@ u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
 					     CAPIMSG_NCCI(skb->data),
 					     CAPIMSG_MSGID(skb->data));
 		if (retval != CAPI_NOERROR) 
-			goto out;
+			return retval;
 
 		dlen = CAPIMSG_DATALEN(skb->data);
 
@@ -399,16 +399,14 @@ u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
 		b1_put_slice(port, skb->data + len, dlen);
 		spin_unlock_irqrestore(&card->lock, flags);
 	} else {
-		retval = CAPI_NOERROR;
-
 	 	spin_lock_irqsave(&card->lock, flags);
 		b1_put_byte(port, SEND_MESSAGE);
 		b1_put_slice(port, skb->data, len);
 		spin_unlock_irqrestore(&card->lock, flags);
 	}
- out:
+
 	dev_kfree_skb_any(skb);
-	return retval;
+	return CAPI_NOERROR;
 }
 
 /* ------------------------------------------------------------- */
diff --git a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c
index d2c69b727..55bed00ca 100644
--- a/drivers/isdn/hardware/avm/b1dma.c
+++ b/drivers/isdn/hardware/avm/b1dma.c
@@ -839,8 +839,6 @@ u16 b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
 	}
 	if (retval == CAPI_NOERROR) 
 		b1dma_queue_tx(card, skb);
-	else
-		dev_kfree_skb_any(skb);
 
 	return retval;
 }
diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c
index 9e1285ca5..72b57d4fb 100644
--- a/drivers/isdn/hardware/avm/c4.c
+++ b/drivers/isdn/hardware/avm/c4.c
@@ -1029,8 +1029,6 @@ static u16 c4_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
 		spin_lock_irqsave(&card->lock, flags);
 		c4_dispatch_tx(card);
 		spin_unlock_irqrestore(&card->lock, flags);
-	} else {
-		dev_kfree_skb_any(skb);
 	}
 	return retval;
 }
diff --git a/drivers/isdn/hardware/avm/t1isa.c b/drivers/isdn/hardware/avm/t1isa.c
index 9d777ebc8..cb9d9cee2 100644
--- a/drivers/isdn/hardware/avm/t1isa.c
+++ b/drivers/isdn/hardware/avm/t1isa.c
@@ -472,7 +472,7 @@ static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
 					     CAPIMSG_NCCI(skb->data),
 					     CAPIMSG_MSGID(skb->data));
 		if (retval != CAPI_NOERROR) 
-			goto out;
+			return retval;
 
 		dlen = CAPIMSG_DATALEN(skb->data);
 
@@ -482,16 +482,15 @@ static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
 		t1_put_slice(port, skb->data + len, dlen);
 		spin_unlock_irqrestore(&card->lock, flags);
 	} else {
-		retval = CAPI_NOERROR;
 
 		spin_lock_irqsave(&card->lock, flags);
 		b1_put_byte(port, SEND_MESSAGE);
 		t1_put_slice(port, skb->data, len);
 		spin_unlock_irqrestore(&card->lock, flags);
 	}
- out:
+
 	dev_kfree_skb_any(skb);
-	return retval;
+	return CAPI_NOERROR;
 }
 /* ------------------------------------------------------------- */
 
diff --git a/drivers/isdn/hardware/eicon/capifunc.c b/drivers/isdn/hardware/eicon/capifunc.c
index 15d081a09..5c138a345 100644
--- a/drivers/isdn/hardware/eicon/capifunc.c
+++ b/drivers/isdn/hardware/eicon/capifunc.c
@@ -1,4 +1,4 @@
-/* $Id: capifunc.c,v 1.61.4.2 2004/05/05 16:09:25 armin Exp $
+/* $Id: capifunc.c,v 1.61.4.5 2004/08/27 20:10:12 armin Exp $
  *
  * ISDN interface module for Eicon active cards DIVA.
  * CAPI Interface common functions
@@ -998,7 +998,8 @@ static u16 diva_send_message(struct capi_ctr *ctrl,
 
       write_end:
 	diva_os_leave_spin_lock(&api_lock, &old_irql, "send message");
-	diva_os_free_message_buffer(dmb);
+	if (retval == CAPI_NOERROR)
+		diva_os_free_message_buffer(dmb);
 	return retval;
 }
 
diff --git a/drivers/isdn/hardware/eicon/capifunc.h b/drivers/isdn/hardware/eicon/capifunc.h
index 13f6ad242..bd256f297 100644
--- a/drivers/isdn/hardware/eicon/capifunc.h
+++ b/drivers/isdn/hardware/eicon/capifunc.h
@@ -1,4 +1,4 @@
-/* $Id: capifunc.h,v 1.11 2004/03/20 17:19:58 armin Exp $
+/* $Id: capifunc.h,v 1.11.4.1 2004/08/28 20:03:53 armin Exp $
  *
  * ISDN interface module for Eicon active cards DIVA.
  * CAPI Interface common functions
@@ -13,8 +13,6 @@
 #ifndef __CAPIFUNC_H__
 #define __CAPIFUNC_H__
 
-#define MAX_DESCRIPTORS  32
-
 #define DRRELMAJOR  2
 #define DRRELMINOR  0
 #define DRRELEXTRA  ""
diff --git a/drivers/isdn/hardware/eicon/debug.c b/drivers/isdn/hardware/eicon/debug.c
index e8e99ad35..6851c6270 100644
--- a/drivers/isdn/hardware/eicon/debug.c
+++ b/drivers/isdn/hardware/eicon/debug.c
@@ -5,6 +5,7 @@
 #include "divasync.h"
 #include "kst_ifc.h"
 #include "maintidi.h"
+#include "man_defs.h"
 
 /*
   LOCALS
@@ -13,17 +14,23 @@
 
 static void DI_register (void *arg);
 static void DI_deregister (pDbgHandle hDbg);
-static void DI_format (int do_lock, word id, int type, char *format, va_list ap);
+static void DI_format (int do_lock, word id, int type, char *format, va_list argument_list);
 static void DI_format_locked   (word id, int type, char *format, va_list argument_list);
 static void DI_format_old (word id, char *format, va_list ap) { }
-static void DiProcessEventLog (word id, dword msgID, va_list ap) { }
+static void DiProcessEventLog (unsigned short id, unsigned long msgID, va_list ap) { }
 static void single_p (byte * P, word * PLength, byte Id);
 static void diva_maint_xdi_cb (ENTITY* e);
 static word SuperTraceCreateReadReq (byte* P, const char* path);
+static int diva_mnt_cmp_nmbr (const char* nmbr);
+static void diva_free_dma_descriptor (IDI_CALL request, int nr);
+static int diva_get_dma_descriptor (IDI_CALL request, dword *dma_magic);
 void diva_mnt_internal_dprintf (dword drv_id, dword type, char* p, ...);
 
 static dword MaxDumpSize = 256 ;
 static dword MaxXlogSize = 2 + 128 ;
+static char  TraceFilter[DIVA_MAX_SELECTIVE_FILTER_LENGTH+1];
+static int TraceFilterIdent   = -1;
+static int TraceFilterChannel = -1;
 
 typedef struct _diva_maint_client {
   dword       sec;
@@ -40,9 +47,10 @@ typedef struct _diva_maint_client {
   BUFFERS     XData;
   char        xbuffer[2048+512];
   byte*       pmem;
-	int         request_pending;
+  int         request_pending;
+  int         dma_handle;
 } diva_maint_client_t;
-static diva_maint_client_t clients[64];
+static diva_maint_client_t clients[MAX_DESCRIPTORS];
 
 static void diva_change_management_debug_mask (diva_maint_client_t* pC, dword old_mask);
 
@@ -201,6 +209,10 @@ int diva_maint_init (byte* base, unsigned long length, int do_init) {
     return (-1);
   }
 
+  TraceFilter[0]     =  0;
+  TraceFilterIdent   = -1;
+  TraceFilterChannel = -1;
+
   dbg_base = base;
 
   diva_os_get_time (&start_sec, &start_usec);
@@ -249,7 +261,6 @@ int diva_maint_init (byte* base, unsigned long length, int do_init) {
 		return (-1);
   }
 
-
   return (0);
 }
 
@@ -302,16 +313,16 @@ diva_dbg_entry_head_t* diva_maint_get_message (word* size,
                                                diva_os_spin_lock_magic_t* old_irql) {
   diva_dbg_entry_head_t*     pmsg = NULL;
 
-  diva_os_enter_spin_lock_hard (&dbg_q_lock, old_irql, "read");
+  diva_os_enter_spin_lock (&dbg_q_lock, old_irql, "read");
   if (dbg_q_busy) {
-    diva_os_leave_spin_lock_hard (&dbg_q_lock, old_irql, "read_busy");
+    diva_os_leave_spin_lock (&dbg_q_lock, old_irql, "read_busy");
     return NULL;
   }
   dbg_q_busy = 1;
 
   if (!(pmsg = (diva_dbg_entry_head_t*)queuePeekMsg (dbg_queue, size))) {
     dbg_q_busy = 0;
-    diva_os_leave_spin_lock_hard (&dbg_q_lock, old_irql, "read_empty");
+    diva_os_leave_spin_lock (&dbg_q_lock, old_irql, "read_empty");
   }
 
   return (pmsg);
@@ -330,7 +341,7 @@ void diva_maint_ack_message (int do_release,
 		queueFreeMsg (dbg_queue);
 	}
 	dbg_q_busy = 0;
-  diva_os_leave_spin_lock_hard (&dbg_q_lock, old_irql, "read_ack");
+  diva_os_leave_spin_lock (&dbg_q_lock, old_irql, "read_ack");
 }
 
 
@@ -378,14 +389,14 @@ static void DI_register (void *arg) {
 		return ;
   }
 
-  diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "register");
+  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "register");
 
   for (id = 1; id < (sizeof(clients)/sizeof(clients[0])); id++) {
     if (clients[id].hDbg == hDbg) {
       /*
         driver already registered
         */
-      diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register");
+      diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
       return;
     }
     if (clients[id].hDbg) { /* slot is busy */
@@ -468,7 +479,7 @@ static void DI_register (void *arg) {
     }
   }
 
-  diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register");
+  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
 }
 
 static void DI_deregister (pDbgHandle hDbg) {
@@ -480,8 +491,8 @@ static void DI_deregister (pDbgHandle hDbg) {
 
   diva_os_get_time (&sec, &usec);
 
-  diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "read");
-  diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "read");
+  diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "read");
+  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read");
 
   for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
     if (clients[i].hDbg == hDbg) {
@@ -543,8 +554,8 @@ static void DI_deregister (pDbgHandle hDbg) {
     }
   }
 
-  diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "read_ack");
-  diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "read_ack");
+  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "read_ack");
+  diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "read_ack");
 
   if (pmem) {
     diva_os_free (0, pmem);
@@ -572,13 +583,22 @@ static void DI_format (int do_lock,
   char          *data;
   unsigned short code;
 
-  if (!format)
+  if (diva_os_in_irq()) {
+    dbg_sequence++;
     return;
+  }
+
+	if ((!format) ||
+			((TraceFilter[0] != 0) && ((TraceFilterIdent < 0) || (TraceFilterChannel < 0)))) {
+		return;
+	}
+
+
   
   diva_os_get_time (&sec, &usec);
 
   if (do_lock) {
-    diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "format");
+    diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "format");
   }
 
   switch (type) {
@@ -703,7 +723,7 @@ static void DI_format (int do_lock,
   }
 
   if (do_lock) {
-    diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "format");
+    diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "format");
   }
 }
 
@@ -720,7 +740,7 @@ int diva_get_driver_info (dword id, byte* data, int data_length) {
     return (-1);
   }
 
-  diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "driver info");
+  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "driver info");
 
   if (clients[id].hDbg) {
     *p++ = 1;
@@ -757,7 +777,7 @@ int diva_get_driver_info (dword id, byte* data, int data_length) {
   }
   *p++ = 0;
 
-  diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "driver info");
+  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "driver info");
 
   return (p - data);
 }
@@ -769,7 +789,7 @@ int diva_get_driver_dbg_mask (dword id, byte* data) {
   if (!data || !id || (id >= (sizeof(clients)/sizeof(clients[0])))) {
     return (-1);
   }
-  diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "driver info");
+  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "driver info");
 
   if (clients[id].hDbg) {
     ret = 4;
@@ -779,7 +799,7 @@ int diva_get_driver_dbg_mask (dword id, byte* data) {
     *data++= (byte)(clients[id].hDbg->dbgMask >> 24);
   }
 
-  diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "driver info");
+  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "driver info");
 
   return (ret);
 }
@@ -793,8 +813,8 @@ int diva_set_driver_dbg_mask (dword id, dword mask) {
     return (-1);
   }
 
-  diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "dbg mask");
-  diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "dbg mask");
+  diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask");
+  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "dbg mask");
 
   if (clients[id].hDbg) {
     dword old_mask = clients[id].hDbg->dbgMask;
@@ -806,14 +826,14 @@ int diva_set_driver_dbg_mask (dword id, dword mask) {
   }
 
 
-  diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "dbg mask");
+  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "dbg mask");
 
   if (clients[id].request_pending) {
     clients[id].request_pending = 0;
     (*(clients[id].request))((ENTITY*)(*(clients[id].pIdiLib->DivaSTraceGetHandle))(clients[id].pIdiLib->hLib));
   }
 
-  diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "dbg mask");
+  diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask");
 
   return (ret);
 }
@@ -851,12 +871,12 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) {
   diva_os_get_time (&sec, &usec);
   diva_get_idi_adapter_info (d->request, &serial, &logical);
   if (serial & 0xff000000) {
-    sprintf (tmp, "ADAPTER:%d SN:%d-%d",
+    sprintf (tmp, "ADAPTER:%d SN:%u-%d",
              (int)logical,
              serial & 0x00ffffff,
              (byte)(((serial & 0xff000000) >> 24) + 1));
   } else {
-    sprintf (tmp, "ADAPTER:%d SN:%d", (int)logical, serial);
+    sprintf (tmp, "ADAPTER:%d SN:%u", (int)logical, serial);
   }
 
   if (!(pmem = diva_os_malloc (0, DivaSTraceGetMemotyRequirement (d->channels)))) {
@@ -864,13 +884,14 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) {
   }
   memset (pmem, 0x00, DivaSTraceGetMemotyRequirement (d->channels));
 
-  diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "register");
-  diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "register");
+  diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
+  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "register");
 
   for (id = 1; id < (sizeof(clients)/sizeof(clients[0])); id++) {
     if (clients[id].hDbg && (clients[id].request == d->request)) {
-      diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register");
-      diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "register");
+      diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
+      diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
+      diva_os_free(0, pmem);
       return;
     }
     if (clients[id].hDbg) { /* slot is busy */
@@ -891,8 +912,8 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) {
   }
 
   if (free_id < 0) {
-    diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register");
-    diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "register");
+    diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
+    diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
     diva_os_free (0, pmem);
     return;
   }
@@ -908,6 +929,7 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) {
   clients[id].Dbg.drvTag[0] = 0;
   clients[id].logical  = (int)logical;
   clients[id].channels = (int)d->channels;
+  clients[id].dma_handle = -1;
 
   clients[id].Dbg.dbgMask    = 0;
   clients[id].dbgMask        = clients[id].Dbg.dbgMask;
@@ -949,8 +971,8 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) {
     clients[id].request = NULL;
     clients[id].request_pending = 0;
     clients[id].hDbg    = NULL;
-    diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register");
-    diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "register");
+    diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
+    diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
     diva_os_free (0, pmem);
     return;
   }
@@ -988,14 +1010,14 @@ void diva_mnt_add_xdi_adapter (const DESCRIPTOR* d) {
   org_mask = clients[id].Dbg.dbgMask;
   clients[id].Dbg.dbgMask = 0;
 
-  diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "register");
+  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "register");
 
   if (clients[id].request_pending) {
     clients[id].request_pending = 0;
     (*(clients[id].request))((ENTITY*)(*(clients[id].pIdiLib->DivaSTraceGetHandle))(clients[id].pIdiLib->hLib));
   }
 
-  diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "register");
+  diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "register");
 
 	diva_set_driver_dbg_mask (id, org_mask);
 }
@@ -1012,8 +1034,8 @@ void diva_mnt_remove_xdi_adapter (const DESCRIPTOR* d) {
 
   diva_os_get_time (&sec, &usec);
 
-  diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "read");
-  diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "read");
+  diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "read");
+  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read");
 
   for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
     if (clients[i].hDbg && (clients[i].request == d->request)) {
@@ -1030,8 +1052,15 @@ void diva_mnt_remove_xdi_adapter (const DESCRIPTOR* d) {
       }
 
       clients[i].hDbg    = NULL;
-      clients[i].request = NULL;
       clients[i].request_pending = 0;
+      if (clients[i].dma_handle >= 0) {
+        /*
+          Free DMA handle
+          */
+        diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle);
+        clients[i].dma_handle = -1;
+      }
+      clients[i].request = NULL;
 
       /*
         Log driver register, MAINT driver ID is '0'
@@ -1069,8 +1098,8 @@ void diva_mnt_remove_xdi_adapter (const DESCRIPTOR* d) {
     }
   }
 
-  diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "read_ack");
-  diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "read_ack");
+  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "read_ack");
+  diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "read_ack");
 
   if (pmem) {
     diva_os_free (0, pmem);
@@ -1142,6 +1171,42 @@ int SuperTraceASSIGN (void* AdapterHandle, byte* data) {
 
   if (pC && pC->pIdiLib && pC->request) {
     ENTITY* e = (ENTITY*)(*(pC->pIdiLib->DivaSTraceGetHandle))(pC->pIdiLib->hLib);
+    IDI_SYNC_REQ* preq;
+    char buffer[((sizeof(preq->xdi_extended_features)+4) > sizeof(ENTITY)) ? (sizeof(preq->xdi_extended_features)+4) : sizeof(ENTITY)];
+    char features[4];
+    word assign_data_length = 1;
+
+    features[0] = 0;
+    pC->xbuffer[0] = 0;
+    preq = (IDI_SYNC_REQ*)&buffer[0];
+    preq->xdi_extended_features.Req = 0;
+    preq->xdi_extended_features.Rc  = IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES;
+    preq->xdi_extended_features.info.buffer_length_in_bytes = sizeof(features);
+    preq->xdi_extended_features.info.features = &features[0];
+
+    (*(pC->request))((ENTITY*)preq);
+
+    if ((features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) &&
+        (features[0] & DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA)) {
+      dword rx_dma_magic;
+      if ((pC->dma_handle = diva_get_dma_descriptor (pC->request, &rx_dma_magic)) >= 0) {
+        pC->xbuffer[0] = LLI;
+        pC->xbuffer[1] = 8;
+        pC->xbuffer[2] = 0x40;
+        pC->xbuffer[3] = (byte)pC->dma_handle;
+        pC->xbuffer[4] = (byte)rx_dma_magic;
+        pC->xbuffer[5] = (byte)(rx_dma_magic >>  8);
+        pC->xbuffer[6] = (byte)(rx_dma_magic >> 16);
+        pC->xbuffer[7] = (byte)(rx_dma_magic >> 24);
+        pC->xbuffer[8] = (byte)DIVA_MAX_MANAGEMENT_TRANSFER_SIZE;
+        pC->xbuffer[9] = (byte)(DIVA_MAX_MANAGEMENT_TRANSFER_SIZE >> 8);
+        pC->xbuffer[10] = 0;
+
+        assign_data_length = 11;
+      }
+    } else {
+      pC->dma_handle = -1;
+    }
 
     e->Id          = MAN_ID;
     e->callback    = diva_maint_xdi_cb;
@@ -1149,9 +1214,8 @@ int SuperTraceASSIGN (void* AdapterHandle, byte* data) {
     e->X           = &pC->XData;
     e->Req         = ASSIGN;
     e->ReqCh       = 0;
-    e->X->PLength  = 1;
+    e->X->PLength  = assign_data_length;
     e->X->P        = (byte*)&pC->xbuffer[0];
-    pC->xbuffer[0] = 0;
 
     pC->request_pending = 1;
 
@@ -1300,16 +1364,25 @@ static void diva_maint_xdi_cb (ENTITY* e) {
   diva_os_spin_lock_magic_t old_irql, old_irql1;
 
 
-  diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "xdi_cb");
-  diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "xdi_cb");
+  diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "xdi_cb");
+  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "xdi_cb");
 
   pC = (diva_maint_client_t*)pLib->hAdapter;
 
-	if ((*(pLib->instance.DivaSTraceMessageInput))(&pLib->instance)) {
-    diva_mnt_internal_dprintf (0, DLI_ERR, "Trace internal library error");
+  if ((e->complete == 255) || (pC->dma_handle < 0)) {
+    if ((*(pLib->instance.DivaSTraceMessageInput))(&pLib->instance)) {
+      diva_mnt_internal_dprintf (0, DLI_ERR, "Trace internal library error");
+    }
+  } else {
+    /*
+      Process combined management interface indication
+      */
+    if ((*(pLib->instance.DivaSTraceMessageInput))(&pLib->instance)) {
+      diva_mnt_internal_dprintf (0, DLI_ERR, "Trace internal library error (DMA mode)");
+    }
   }
 
-  diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "xdi_cb");
+  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "xdi_cb");
 
 
 	if (pC->request_pending) {
@@ -1317,7 +1390,7 @@ static void diva_maint_xdi_cb (ENTITY* e) {
     (*(pC->request))(e);
 	}
 
-  diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "xdi_cb");
+  diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "xdi_cb");
 }
 
 
@@ -1365,8 +1438,42 @@ static void diva_maint_state_change_notify (void* user_context,
   }
 
   switch (notify_subject) {
-    case DIVA_SUPER_TRACE_NOTIFY_LINE_CHANGE:
-      if (pC->hDbg->dbgMask & DIVA_MGT_DBG_LINE_EVENTS) {
+    case DIVA_SUPER_TRACE_NOTIFY_LINE_CHANGE: {
+      int view = (TraceFilter[0] == 0);
+      /*
+        Process selective Trace
+        */
+      if (channel->Line[0] == 'I' && channel->Line[1] == 'd' &&
+          channel->Line[2] == 'l' && channel->Line[3] == 'e') {
+        if ((TraceFilterIdent == pC->hDbg->id) && (TraceFilterChannel == (int)channel->ChannelNumber)) {
+          (*(hLib->DivaSTraceSetBChannel))(hLib, (int)channel->ChannelNumber, 0);
+          (*(hLib->DivaSTraceSetAudioTap))(hLib, (int)channel->ChannelNumber, 0);
+          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, "Selective Trace OFF for Ch=%d",
+                                     (int)channel->ChannelNumber);
+          TraceFilterIdent   = -1;
+          TraceFilterChannel = -1;
+          view = 1;
+        }
+      } else if (TraceFilter[0] && (TraceFilterIdent < 0) && !(diva_mnt_cmp_nmbr (&channel->RemoteAddress[0]) &&
+                                                               diva_mnt_cmp_nmbr (&channel->LocalAddress[0]))) {
+
+        if ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0) { /* Activate B-channel trace */
+          (*(hLib->DivaSTraceSetBChannel))(hLib, (int)channel->ChannelNumber, 1);
+        }
+        if ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0) { /* Activate AudioTap Trace */
+          (*(hLib->DivaSTraceSetAudioTap))(hLib, (int)channel->ChannelNumber, 1);
+        }
+
+        TraceFilterIdent   = pC->hDbg->id;
+        TraceFilterChannel = (int)channel->ChannelNumber;
+
+        if (TraceFilterIdent >= 0) {
+          diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, "Selective Trace ON for Ch=%d",
+                                     (int)channel->ChannelNumber);
+          view = 1;
+        }
+      }
+      if (view && (pC->hDbg->dbgMask & DIVA_MGT_DBG_LINE_EVENTS)) {
         diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Ch     = %d",
                                                                      (int)channel->ChannelNumber);
         diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Status = <%s>", &channel->Line[0]);
@@ -1392,10 +1499,26 @@ static void diva_maint_state_change_notify (void* user_context,
                                                                     channel->LastDisconnecCause);
         diva_mnt_internal_dprintf (pC->hDbg->id, DLI_STAT, "L Owner  = <%s>", &channel->UserID[0]);
       }
-      break;
+
+		} break;
 
     case DIVA_SUPER_TRACE_NOTIFY_MODEM_CHANGE:
       if (pC->hDbg->dbgMask & DIVA_MGT_DBG_MDM_PROGRESS) {
+				{
+					int ch = TraceFilterChannel;
+					int id = TraceFilterIdent;
+
+					if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) &&
+						(clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
+						if (ch != (int)modem->ChannelNumber) {
+							break;
+						}
+					} else if (TraceFilter[0] != 0) {
+						break;
+					}
+				}
+
+
         diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Ch    = %lu",
                                                                      (int)modem->ChannelNumber);
         diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "MDM Event = %lu",     modem->Event);
@@ -1428,6 +1551,20 @@ static void diva_maint_state_change_notify (void* user_context,
 
     case DIVA_SUPER_TRACE_NOTIFY_FAX_CHANGE:
       if (pC->hDbg->dbgMask & DIVA_MGT_DBG_FAX_PROGRESS) {
+				{
+					int ch = TraceFilterChannel;
+					int id = TraceFilterIdent;
+
+					if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) &&
+						(clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
+						if (ch != (int)fax->ChannelNumber) {
+							break;
+						}
+					} else if (TraceFilter[0] != 0) {
+						break;
+					}
+				}
+
         diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Ch    = %lu",(int)fax->ChannelNumber);
         diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Event = %lu",     fax->Event);
         diva_mnt_internal_dprintf(pC->hDbg->id, DLI_STAT, "FAX Pages = %lu",     fax->Page_Counter);
@@ -1660,6 +1797,52 @@ static void diva_maint_trace_notify (void* user_context,
   diva_dbg_entry_head_t* pmsg;
   word size;
   dword sec, usec;
+  int ch = TraceFilterChannel;
+  int id = TraceFilterIdent;
+
+  /*
+    Selective trace
+    */
+  if ((id >= 0) && (ch >= 0) && (id < sizeof(clients)/sizeof(clients[0])) &&
+      (clients[id].Dbg.id == (byte)id) && (clients[id].pIdiLib == hLib)) {
+    const char* p = NULL;
+    int ch_value = -1;
+    MI_XLOG_HDR *TrcData = (MI_XLOG_HDR *)xlog_buffer;
+
+    if (Adapter != clients[id].logical) {
+      return; /* Ignore all trace messages from other adapters */
+    }
+
+    if (TrcData->code == 24) {
+      p = (char*)&TrcData->code;
+      p += 2;
+    }
+
+    /*
+      All L1 messages start as [dsp,ch], so we can filter this information
+      and filter out all messages that use different channel
+      */
+    if (p && p[0] == '[') {
+      if (p[2] == ',') {
+        p += 3;
+        ch_value = *p - '0';
+      } else if (p[3] == ',') {
+        p += 4;
+        ch_value = *p - '0';
+      }
+      if (ch_value >= 0) {
+        if (p[2] == ']') {
+          ch_value = ch_value * 10 + p[1] - '0';
+        }
+        if (ch_value != ch) {
+          return; /* Ignore other channels */
+        }
+      }
+    }
+
+	} else if (TraceFilter[0] != 0) {
+    return; /* Ignore trace if trace filter is activated, but idle */
+  }
 
   diva_os_get_time (&sec, &usec);
 
@@ -1705,18 +1888,20 @@ static void diva_change_management_debug_mask (diva_maint_client_t* pC, dword ol
       (*(pC->pIdiLib->DivaSTraceSetDChannel))(pC->pIdiLib,
                                               (pC->hDbg->dbgMask & DIVA_MGT_DBG_DCHAN) != 0);
     }
-    if (changed & DIVA_MGT_DBG_IFC_BCHANNEL) {
-      int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0);
+    if (!TraceFilter[0]) {
+      if (changed & DIVA_MGT_DBG_IFC_BCHANNEL) {
+        int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0);
 
-      for (i = 0; i < pC->channels; i++) {
-        (*(pC->pIdiLib->DivaSTraceSetBChannel))(pC->pIdiLib, i+1, state);
+        for (i = 0; i < pC->channels; i++) {
+          (*(pC->pIdiLib->DivaSTraceSetBChannel))(pC->pIdiLib, i+1, state);
+        }
       }
-    }
-    if (changed & DIVA_MGT_DBG_IFC_AUDIO) {
-      int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0);
+      if (changed & DIVA_MGT_DBG_IFC_AUDIO) {
+        int i, state = ((pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO) != 0);
 
-      for (i = 0; i < pC->channels; i++) {
-        (*(pC->pIdiLib->DivaSTraceSetAudioTap))(pC->pIdiLib, i+1, state);
+        for (i = 0; i < pC->channels; i++) {
+          (*(pC->pIdiLib->DivaSTraceSetAudioTap))(pC->pIdiLib, i+1, state);
+        }
       }
     }
   }
@@ -1743,8 +1928,8 @@ int diva_mnt_shutdown_xdi_adapters (void) {
   for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
     pmem = NULL;
 
-    diva_os_enter_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "unload");
-    diva_os_enter_spin_lock_hard (&dbg_q_lock, &old_irql, "unload");
+    diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "unload");
+    diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "unload");
 
     if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request) {
       if ((*(clients[i].pIdiLib->DivaSTraceLibraryStop))(clients[i].pIdiLib) == 1) {
@@ -1759,19 +1944,31 @@ int diva_mnt_shutdown_xdi_adapters (void) {
           clients[i].pmem = NULL;
         }
         clients[i].hDbg    = NULL;
-        clients[i].request = NULL;
         clients[i].request_pending = 0;
+
+        if (clients[i].dma_handle >= 0) {
+          /*
+            Free DMA handle
+            */
+          diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle);
+          clients[i].dma_handle = -1;
+				}
+        clients[i].request = NULL;
       } else {
         fret = -1;
       }
     }
 
-    diva_os_leave_spin_lock_hard (&dbg_q_lock, &old_irql, "unload");
+    diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "unload");
     if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request && clients[i].request_pending) {
       clients[i].request_pending = 0;
       (*(clients[i].request))((ENTITY*)(*(clients[i].pIdiLib->DivaSTraceGetHandle))(clients[i].pIdiLib->hLib));
+      if (clients[i].dma_handle >= 0) {
+        diva_free_dma_descriptor (clients[i].request, clients[i].dma_handle);
+        clients[i].dma_handle = -1;
+      }
     }
-    diva_os_leave_spin_lock_hard (&dbg_adapter_lock, &old_irql1, "unload");
+    diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "unload");
 
     if (pmem) {
       diva_os_free (0, pmem);
@@ -1781,3 +1978,156 @@ int diva_mnt_shutdown_xdi_adapters (void) {
   return (fret);
 }
 
+/*
+  Set/Read the trace filter used for selective tracing.
+  Affects B- and Audio Tap trace mask at run time
+  */
+int diva_set_trace_filter (int filter_length, const char* filter) {
+  diva_os_spin_lock_magic_t old_irql, old_irql1;
+  int i, ch, on, client_b_on, client_atap_on;
+
+  diva_os_enter_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask");
+  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "write_filter");
+
+  if (filter_length <= DIVA_MAX_SELECTIVE_FILTER_LENGTH) {
+    memcpy (&TraceFilter[0], filter, filter_length);
+    if (TraceFilter[filter_length]) {
+      TraceFilter[filter_length] = 0;
+    }
+    if (TraceFilter[0] == '*') {
+      TraceFilter[0] = 0;
+    }
+  } else {
+    filter_length = -1;
+  }
+
+  TraceFilterIdent   = -1;
+  TraceFilterChannel = -1;
+
+  on = (TraceFilter[0] == 0);
+
+  for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
+    if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request) {
+      client_b_on    = on && ((clients[i].hDbg->dbgMask & DIVA_MGT_DBG_IFC_BCHANNEL) != 0);
+      client_atap_on = on && ((clients[i].hDbg->dbgMask & DIVA_MGT_DBG_IFC_AUDIO)    != 0);
+      for (ch = 0; ch < clients[i].channels; ch++) {
+        (*(clients[i].pIdiLib->DivaSTraceSetBChannel))(clients[i].pIdiLib->hLib, ch+1, client_b_on);
+        (*(clients[i].pIdiLib->DivaSTraceSetAudioTap))(clients[i].pIdiLib->hLib, ch+1, client_atap_on);
+      }
+    }
+  }
+
+  for (i = 1; i < (sizeof(clients)/sizeof(clients[0])); i++) {
+    if (clients[i].hDbg && clients[i].pIdiLib && clients[i].request && clients[i].request_pending) {
+      diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "write_filter");
+      clients[i].request_pending = 0;
+      (*(clients[i].request))((ENTITY*)(*(clients[i].pIdiLib->DivaSTraceGetHandle))(clients[i].pIdiLib->hLib));
+      diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "write_filter");
+    }
+  }
+
+  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "write_filter");
+  diva_os_leave_spin_lock (&dbg_adapter_lock, &old_irql1, "dbg mask");
+
+  return (filter_length);
+}
+
+int diva_get_trace_filter (int max_length, char* filter) {
+  diva_os_spin_lock_magic_t old_irql;
+  int len;
+
+  diva_os_enter_spin_lock (&dbg_q_lock, &old_irql, "read_filter");
+  len = strlen (&TraceFilter[0]) + 1;
+  if (max_length >= len) {
+    memcpy (filter, &TraceFilter[0], len);
+  }
+  diva_os_leave_spin_lock (&dbg_q_lock, &old_irql, "read_filter");
+
+  return (len);
+}
+
+static int diva_dbg_cmp_key (const char* ref, const char* key) {
+	while (*key && (*ref++ == *key++));
+  return (!*key && !*ref);
+}
+
+/*
+  In case trace filter starts with "C" character then
+  all following characters are interpreted as command.
+  Followings commands are available:
+  - single, trace single call at time, independent from CPN/CiPN
+  */
+static int diva_mnt_cmp_nmbr (const char* nmbr) {
+  const char* ref = &TraceFilter[0];
+  int ref_len = strlen(&TraceFilter[0]), nmbr_len = strlen(nmbr);
+
+  if (ref[0] == 'C') {
+    if (diva_dbg_cmp_key (&ref[1], "single")) {
+      return (0);
+    }
+    return (-1);
+  }
+
+  if (!ref_len || (ref_len > nmbr_len)) {
+    return (-1);
+  }
+
+  nmbr = nmbr + nmbr_len - 1;
+  ref  = ref  + ref_len  - 1;
+
+  while (ref_len--) {
+    if (*nmbr-- != *ref--) {
+      return (-1);
+    }
+  }
+
+  return (0);
+}
+
+static int diva_get_dma_descriptor (IDI_CALL request, dword *dma_magic) {
+  ENTITY e;
+  IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
+
+  if (!request) {
+    return (-1);
+  }
+
+  pReq->xdi_dma_descriptor_operation.Req = 0;
+  pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
+
+  pReq->xdi_dma_descriptor_operation.info.operation =     IDI_SYNC_REQ_DMA_DESCRIPTOR_ALLOC;
+  pReq->xdi_dma_descriptor_operation.info.descriptor_number  = -1;
+  pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
+  pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
+
+  (*request)((ENTITY*)pReq);
+
+  if (!pReq->xdi_dma_descriptor_operation.info.operation &&
+      (pReq->xdi_dma_descriptor_operation.info.descriptor_number >= 0) &&
+      pReq->xdi_dma_descriptor_operation.info.descriptor_magic) {
+    *dma_magic = pReq->xdi_dma_descriptor_operation.info.descriptor_magic;
+    return (pReq->xdi_dma_descriptor_operation.info.descriptor_number);
+  } else {
+    return (-1);
+  }
+}
+
+static void diva_free_dma_descriptor (IDI_CALL request, int nr) {
+  ENTITY e;
+  IDI_SYNC_REQ* pReq = (IDI_SYNC_REQ*)&e;
+
+  if (!request || (nr < 0)) {
+    return;
+  }
+
+  pReq->xdi_dma_descriptor_operation.Req = 0;
+  pReq->xdi_dma_descriptor_operation.Rc = IDI_SYNC_REQ_DMA_DESCRIPTOR_OPERATION;
+
+  pReq->xdi_dma_descriptor_operation.info.operation = IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE;
+  pReq->xdi_dma_descriptor_operation.info.descriptor_number  = nr;
+  pReq->xdi_dma_descriptor_operation.info.descriptor_address = NULL;
+  pReq->xdi_dma_descriptor_operation.info.descriptor_magic   = 0;
+
+  (*request)((ENTITY*)pReq);
+}
+
diff --git a/drivers/isdn/hardware/eicon/debug_if.h b/drivers/isdn/hardware/eicon/debug_if.h
index 0136eea12..4db739d58 100644
--- a/drivers/isdn/hardware/eicon/debug_if.h
+++ b/drivers/isdn/hardware/eicon/debug_if.h
@@ -57,12 +57,18 @@ void diva_mnt_remove_xdi_adapter (const DESCRIPTOR* d);
 void diva_mnt_add_xdi_adapter    (const DESCRIPTOR* d);
 int diva_mnt_shutdown_xdi_adapters (void);
 
+#define DIVA_MAX_SELECTIVE_FILTER_LENGTH 127
+int diva_set_trace_filter (int filter_length, const char* filter);
+int diva_get_trace_filter (int max_length,    char*       filter);
+
 
 #define DITRACE_CMD_GET_DRIVER_INFO   1
 #define DITRACE_READ_DRIVER_DBG_MASK  2
 #define DITRACE_WRITE_DRIVER_DBG_MASK 3
 #define DITRACE_READ_TRACE_ENTRY      4
 #define DITRACE_READ_TRACE_ENTRYS     5
+#define DITRACE_WRITE_SELECTIVE_TRACE_FILTER 6
+#define DITRACE_READ_SELECTIVE_TRACE_FILTER  7
 
 /*
   Trace lavels for debug via management interface
diff --git a/drivers/isdn/hardware/eicon/debuglib.h b/drivers/isdn/hardware/eicon/debuglib.h
index 516d2bd8b..11b3b9edd 100644
--- a/drivers/isdn/hardware/eicon/debuglib.h
+++ b/drivers/isdn/hardware/eicon/debuglib.h
@@ -232,7 +232,7 @@ typedef struct _DbgHandle_ *pDbgHandle ;
 typedef void ( * DbgEnd) (pDbgHandle) ;
 typedef void ( * DbgLog) (unsigned short, int, char *, va_list) ;
 typedef void ( * DbgOld) (unsigned short, char *, va_list) ;
-typedef void ( * DbgEv)  (unsigned short, unsigned int, va_list) ;
+typedef void ( * DbgEv)  (unsigned short, unsigned long, va_list) ;
 typedef void ( * DbgIrq) (unsigned short, int, char *, va_list) ;
 typedef struct _DbgHandle_
 { char    Registered ; /* driver successfull registered */
@@ -259,7 +259,7 @@ typedef struct _DbgHandle_
  void      *pReserved3 ;
 } _DbgHandle_ ;
 extern _DbgHandle_ myDriverDebugHandle ;
-typedef struct
+typedef struct _OldDbgHandle_
 { struct _OldDbgHandle_ *next ;
  void                *pIrp ;
  long    regTime[2] ;
@@ -310,7 +310,7 @@ typedef struct
             unsigned long   B_ChannelMask;
             unsigned long   LogBufferSize;
         } CardTrace;
-    } u1;     
+    }Data;     
 } _DbgExtendedInfo_;
 #ifndef DIVA_NO_DEBUGLIB
 /* -------------------------------------------------------------
diff --git a/drivers/isdn/hardware/eicon/diddfunc.c b/drivers/isdn/hardware/eicon/diddfunc.c
index 33172c1d6..302923417 100644
--- a/drivers/isdn/hardware/eicon/diddfunc.c
+++ b/drivers/isdn/hardware/eicon/diddfunc.c
@@ -1,4 +1,4 @@
-/* $Id: diddfunc.c,v 1.14 2003/08/25 10:06:37 schindler Exp $
+/* $Id: diddfunc.c,v 1.14.6.2 2004/08/28 20:03:53 armin Exp $
  *
  * DIDD Interface module for Eicon active cards.
  * 
@@ -16,8 +16,6 @@
 #include "dadapter.h"
 #include "divasync.h"
 
-#define MAX_DESCRIPTORS  32
-
 #define DBG_MINIMUM  (DL_LOG + DL_FTL + DL_ERR)
 #define DBG_DEFAULT  (DBG_MINIMUM + DL_XLOG + DL_REG)
 
diff --git a/drivers/isdn/hardware/eicon/diva_didd.c b/drivers/isdn/hardware/eicon/diva_didd.c
index 0afd015e0..48b3f15bc 100644
--- a/drivers/isdn/hardware/eicon/diva_didd.c
+++ b/drivers/isdn/hardware/eicon/diva_didd.c
@@ -1,4 +1,4 @@
-/* $Id: diva_didd.c,v 1.13 2003/08/27 10:11:21 schindler Exp $
+/* $Id: diva_didd.c,v 1.13.6.1 2004/08/28 20:03:53 armin Exp $
  *
  * DIDD Interface module for Eicon active cards.
  * 
@@ -23,7 +23,7 @@
 #include "divasync.h"
 #include "did_vers.h"
 
-static char *main_revision = "$Revision: 1.13 $";
+static char *main_revision = "$Revision: 1.13.6.1 $";
 
 static char *DRIVERNAME =
     "Eicon DIVA - DIDD table (http://www.melware.net)";
@@ -37,8 +37,6 @@ MODULE_AUTHOR("Cytronics & Melware, Eicon Networks");
 MODULE_SUPPORTED_DEVICE("Eicon diva drivers");
 MODULE_LICENSE("GPL");
 
-#define MAX_DESCRIPTORS  32
-
 #define DBG_MINIMUM  (DL_LOG + DL_FTL + DL_ERR)
 #define DBG_DEFAULT  (DBG_MINIMUM + DL_XLOG + DL_REG)
 
@@ -50,8 +48,8 @@ extern void DIVA_DIDD_Read(void *, int);
 static struct proc_dir_entry *proc_didd;
 struct proc_dir_entry *proc_net_eicon = NULL;
 
-EXPORT_SYMBOL_NOVERS(DIVA_DIDD_Read);
-EXPORT_SYMBOL_NOVERS(proc_net_eicon);
+EXPORT_SYMBOL(DIVA_DIDD_Read);
+EXPORT_SYMBOL(proc_net_eicon);
 
 static char *getrev(const char *revision)
 {
diff --git a/drivers/isdn/hardware/eicon/divamnt.c b/drivers/isdn/hardware/eicon/divamnt.c
index 6b22a8a5f..989cdef60 100644
--- a/drivers/isdn/hardware/eicon/divamnt.c
+++ b/drivers/isdn/hardware/eicon/divamnt.c
@@ -1,4 +1,4 @@
-/* $Id: divamnt.c,v 1.32 2004/01/15 09:48:13 armin Exp $
+/* $Id: divamnt.c,v 1.32.6.5 2004/08/28 20:03:53 armin Exp $
  *
  * Driver for Eicon DIVA Server ISDN cards.
  * Maint module
@@ -17,8 +17,6 @@
 #include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/poll.h>
-#include <linux/proc_fs.h>
-#include <linux/skbuff.h>
 #include <linux/devfs_fs_kernel.h>
 
 #include "platform.h"
@@ -26,7 +24,7 @@
 #include "divasync.h"
 #include "debug_if.h"
 
-static char *main_revision = "$Revision: 1.32 $";
+static char *main_revision = "$Revision: 1.32.6.5 $";
 
 static int major;
 
@@ -47,8 +45,7 @@ static char *DEVNAME = "DivasMAINT";
 char *DRIVERRELEASE_MNT = "2.0";
 
 static wait_queue_head_t msgwaitq;
-static DECLARE_MUTEX(opened_sem);
-static int opened;
+static unsigned long opened;
 static struct timeval start_time;
 
 extern int mntfunc_init(int *, void **, unsigned long);
@@ -73,20 +70,6 @@ static char *getrev(const char *revision)
 	return rev;
 }
 
-/*
- * buffer alloc
- */
-void *diva_os_malloc_tbuffer(unsigned long flags, unsigned long size)
-{
-	return (kmalloc(size, GFP_KERNEL));
-}
-void diva_os_free_tbuffer(unsigned long flags, void *ptr)
-{
-	if (ptr) {
-		kfree(ptr);
-	}
-}
-
 /*
  * kernel/user space copy functions
  */
@@ -131,154 +114,8 @@ void diva_os_get_time(dword * sec, dword * usec)
 }
 
 /*
- * /proc entries
+ * device node operations
  */
-
-extern struct proc_dir_entry *proc_net_eicon;
-static struct proc_dir_entry *maint_proc_entry = NULL;
-
-/*
-	Read function is provided for compatibility reason - this allows
-  to read unstructured traces, formated as ascii string only
-  */
-static ssize_t
-maint_read(struct file *file, char __user *buf, size_t count, loff_t * off)
-{
-	diva_dbg_entry_head_t *pmsg = NULL;
-	diva_os_spin_lock_magic_t old_irql;
-	word size;
-	char *pstr, *dli_label = "UNK";
-	int str_length;
-	int *str_msg;
-
-	if (!file->private_data) {
-		for (;;) {
-			while (
-			       (pmsg =
-				diva_maint_get_message(&size,
-						       &old_irql))) {
-				if (!(pmsg->facility == MSG_TYPE_STRING)) {
-					diva_maint_ack_message(1,
-							       &old_irql);
-				} else {
-					break;
-				}
-			}
-
-			if (!pmsg) {
-				if (file->f_flags & O_NONBLOCK) {
-					return (-EAGAIN);
-				}
-				interruptible_sleep_on(&msgwaitq);
-				if (signal_pending(current)) {
-					return (-ERESTARTSYS);
-				}
-			} else {
-				break;
-			}
-		}
-		/*
-		   The length of message that shoule be read is:
-		   pmsg->data_length + label(25) + DrvID(2) + byte CR + trailing zero
-		 */
-		if (!
-		    (str_msg =
-		     (int *) diva_os_malloc_tbuffer(0,
-						    pmsg->data_length +
-						    29 + 2 * sizeof(int)))) {
-			diva_maint_ack_message(0, &old_irql);
-			return (-ENOMEM);
-		}
-		pstr = (char *) &str_msg[2];
-
-		switch (pmsg->dli) {
-		case DLI_LOG:
-			dli_label = "LOG";
-			break;
-		case DLI_FTL:
-			dli_label = "FTL";
-			break;
-		case DLI_ERR:
-			dli_label = "ERR";
-			break;
-		case DLI_TRC:
-			dli_label = "TRC";
-			break;
-		case DLI_REG:
-			dli_label = "REG";
-			break;
-		case DLI_MEM:
-			dli_label = "MEM";
-			break;
-		case DLI_SPL:
-			dli_label = "SPL";
-			break;
-		case DLI_IRP:
-			dli_label = "IRP";
-			break;
-		case DLI_TIM:
-			dli_label = "TIM";
-			break;
-		case DLI_TAPI:
-			dli_label = "TAPI";
-			break;
-		case DLI_NDIS:
-			dli_label = "NDIS";
-			break;
-		case DLI_CONN:
-			dli_label = "CONN";
-			break;
-		case DLI_STAT:
-			dli_label = "STAT";
-			break;
-		case DLI_PRV0:
-			dli_label = "PRV0";
-			break;
-		case DLI_PRV1:
-			dli_label = "PRV1";
-			break;
-		case DLI_PRV2:
-			dli_label = "PRV2";
-			break;
-		case DLI_PRV3:
-			dli_label = "PRV3";
-			break;
-		}
-		str_length = sprintf(pstr, "%s %02x %s\n",
-				     dli_label, (byte) pmsg->drv_id,
-				     (char *) &pmsg[1]);
-		str_msg[0] = str_length;
-		str_msg[1] = 0;
-		file->private_data = str_msg;
-		diva_maint_ack_message(1, &old_irql);
-	} else {
-		str_msg = (int *) file->private_data;
-		pstr = (char *) &str_msg[2];
-		pstr += str_msg[1];	/* head + offset */
-		str_length = str_msg[0] - str_msg[1];	/* length - offset */
-	}
-	str_length = MIN(str_length, count);
-
-	if (diva_os_copy_to_user(NULL, buf, pstr, str_length)) {
-		diva_os_free_tbuffer(0, str_msg);
-		file->private_data = NULL;
-		return (-EFAULT);
-	}
-	str_msg[1] += str_length;
-	if ((str_msg[0] - str_msg[1]) <= 0) {
-		diva_os_free_tbuffer(0, str_msg);
-		file->private_data = NULL;
-	}
-
-	return (str_length);
-}
-
-static ssize_t
-maint_write(struct file *file, const char __user *buf, size_t count, loff_t * off)
-{
-	return (-ENODEV);
-}
-
 static unsigned int maint_poll(struct file *file, poll_table * wait)
 {
 	unsigned int mask = 0;
@@ -293,13 +130,10 @@ static unsigned int maint_poll(struct file *file, poll_table * wait)
 
 static int maint_open(struct inode *ino, struct file *filep)
 {
-	down(&opened_sem);
-	if (opened) {
-		up(&opened_sem);
+	/* only one open is allowed, so we test
+	   it atomically */
+	if (test_and_set_bit(0, &opened))
 		return (-EBUSY);
-	}
-	opened++;
-	up(&opened_sem);
 
 	filep->private_data = NULL;
 
@@ -309,54 +143,16 @@ static int maint_open(struct inode *ino, struct file *filep)
 static int maint_close(struct inode *ino, struct file *filep)
 {
 	if (filep->private_data) {
-		diva_os_free_tbuffer(0, filep->private_data);
+		diva_os_free(0, filep->private_data);
 		filep->private_data = NULL;
 	}
 
-	down(&opened_sem);
-	opened--;
-	up(&opened_sem);
+	/* clear 'used' flag */
+	clear_bit(0, &opened);
+	
 	return (0);
 }
 
-/*
- * fops
- */
-static struct file_operations maint_fops = {
-	.owner   = THIS_MODULE,
-	.llseek  = no_llseek,
-	.read    = maint_read,
-	.write   = maint_write,
-	.poll    = maint_poll,
-	.open    = maint_open,
-	.release = maint_close
-};
-
-static int DIVA_INIT_FUNCTION create_maint_proc(void)
-{
-	maint_proc_entry =
-	    create_proc_entry("maint", S_IFREG | S_IRUGO | S_IWUSR,
-			      proc_net_eicon);
-	if (!maint_proc_entry)
-		return (0);
-
-	maint_proc_entry->proc_fops = &maint_fops;
-	maint_proc_entry->owner = THIS_MODULE;
-
-	return (1);
-}
-
-static void remove_maint_proc(void)
-{
-	if (maint_proc_entry) {
-		remove_proc_entry("maint", proc_net_eicon);
-		maint_proc_entry = NULL;
-	}
-}
-
-/*
- * device node operations
- */
 static ssize_t divas_maint_write(struct file *file, const char __user *buf,
 				 size_t count, loff_t * ppos)
 {
@@ -427,18 +223,10 @@ static int DIVA_INIT_FUNCTION maint_init(void)
 		ret = -EIO;
 		goto out;
 	}
-	if (!create_maint_proc()) {
-		printk(KERN_ERR "%s: failed to create proc entry.\n",
-		       DRIVERLNAME);
-		divas_maint_unregister_chrdev();
-		ret = -EIO;
-		goto out;
-	}
 
 	if (!(mntfunc_init(&buffer_length, &buffer, diva_dbg_mem))) {
 		printk(KERN_ERR "%s: failed to connect to DIDD.\n",
 		       DRIVERLNAME);
-		remove_maint_proc();
 		divas_maint_unregister_chrdev();
 		ret = -EIO;
 		goto out;
@@ -457,7 +245,6 @@ static int DIVA_INIT_FUNCTION maint_init(void)
 */
 static void DIVA_EXIT_FUNCTION maint_exit(void)
 {
-	remove_maint_proc();
 	divas_maint_unregister_chrdev();
 	mntfunc_finit();
 
@@ -466,3 +253,4 @@ static void DIVA_EXIT_FUNCTION maint_exit(void)
 
 module_init(maint_init);
 module_exit(maint_exit);
+
diff --git a/drivers/isdn/hardware/eicon/divasfunc.c b/drivers/isdn/hardware/eicon/divasfunc.c
index 4ee56d4bb..df61e510a 100644
--- a/drivers/isdn/hardware/eicon/divasfunc.c
+++ b/drivers/isdn/hardware/eicon/divasfunc.c
@@ -1,4 +1,4 @@
-/* $Id: divasfunc.c,v 1.23 2004/04/08 01:17:57 armin Exp $
+/* $Id: divasfunc.c,v 1.23.4.2 2004/08/28 20:03:53 armin Exp $
  *
  * Low level driver for Eicon DIVA Server ISDN cards.
  *
@@ -27,8 +27,6 @@ extern void DIVA_DIDD_Read(void *, int);
 
 extern PISDN_ADAPTER IoAdapters[MAX_ADAPTER];
 
-#define MAX_DESCRIPTORS  32
-
 extern char *DRIVERRELEASE_DIVAS;
 
 static dword notify_handle;
@@ -76,10 +74,10 @@ void diva_xdi_didd_register_adapter(int card)
 		d.features = IoAdapters[card - 1]->Properties.Features;
 		DBG_TRC(("DIDD register A(%d) channels=%d", card,
 			 d.channels))
-		/* workaround for different Name in structure */
-		strlcpy(IoAdapters[card - 1]->Name,
-			IoAdapters[card - 1]->Properties.Name,
-			sizeof(IoAdapters[card - 1]->Name));
+		    /* workaround for different Name in structure */
+		    strlcpy(IoAdapters[card - 1]->Name,
+			    IoAdapters[card - 1]->Properties.Name,
+			    sizeof(IoAdapters[card - 1]->Name));
 		req.didd_remove_adapter.e.Req = 0;
 		req.didd_add_adapter.e.Rc = IDI_SYNC_REQ_DIDD_ADD_ADAPTER;
 		req.didd_add_adapter.info.descriptor = (void *) &d;
diff --git a/drivers/isdn/hardware/eicon/divasync.h b/drivers/isdn/hardware/eicon/divasync.h
index 81c444828..0a5be7f96 100644
--- a/drivers/isdn/hardware/eicon/divasync.h
+++ b/drivers/isdn/hardware/eicon/divasync.h
@@ -31,33 +31,31 @@
 #define IDI_SYNC_REQ_SET_POSTCALL       0x03
 #define IDI_SYNC_REQ_GET_XLOG           0x04
 #define IDI_SYNC_REQ_GET_FEATURES       0x05
-/* Added for DIVA USB support */
 #define IDI_SYNC_REQ_USB_REGISTER       0x06
 #define IDI_SYNC_REQ_USB_RELEASE        0x07
 #define IDI_SYNC_REQ_USB_ADD_DEVICE     0x08
 #define IDI_SYNC_REQ_USB_START_DEVICE   0x09
 #define IDI_SYNC_REQ_USB_STOP_DEVICE    0x0A
 #define IDI_SYNC_REQ_USB_REMOVE_DEVICE  0x0B
-/* Added for Diva Server Monitor */
 #define IDI_SYNC_REQ_GET_CARDTYPE       0x0C
 #define IDI_SYNC_REQ_GET_DBG_XLOG       0x0D
-#define IDI_SYNC_REQ_GET_LINE_IDX   0x0E
 #define DIVA_USB
 #define DIVA_USB_REQ                    0xAC
 #define DIVA_USB_TEST                   0xAB
 #define DIVA_USB_ADD_ADAPTER            0xAC
 #define DIVA_USB_REMOVE_ADAPTER         0xAD
-/******************************************************************************/
 #define IDI_SYNC_REQ_SERIAL_HOOK        0x80
 #define IDI_SYNC_REQ_XCHANGE_STATUS     0x81
 #define IDI_SYNC_REQ_USB_HOOK           0x82
 #define IDI_SYNC_REQ_PORTDRV_HOOK       0x83
-#define IDI_SYNC_REQ_SLI           (0x84)   /*  SLI request from 3signal modem drivers */
+#define IDI_SYNC_REQ_SLI                0x84   /*  SLI request from 3signal modem drivers */
 #define IDI_SYNC_REQ_RECONFIGURE        0x85
 #define IDI_SYNC_REQ_RESET              0x86
+#define IDI_SYNC_REQ_GET_85X_DEVICE_DATA     0x87
 #define IDI_SYNC_REQ_LOCK_85X                   0x88
+#define IDI_SYNC_REQ_DIVA_85X_USB_DATA_EXCHANGE 0x99
+#define IDI_SYNC_REQ_DIPORT_EXCHANGE_REQ   0x98
 #define IDI_SYNC_REQ_GET_85X_EXT_PORT_TYPE      0xA0
-#define IDI_SYNC_REQ_DIPORT_GET_85X_TX_CTRL_FN  0x98
 /******************************************************************************/
 #define IDI_SYNC_REQ_XDI_GET_EXTENDED_FEATURES  0x92
 /*
@@ -87,6 +85,8 @@ typedef struct _diva_xdi_get_extended_xdi_features {
 #define DIVA_XDI_EXTENDED_FEATURE_CAPI_PRMS       0x08
 #define DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC    0x10
 #define DIVA_XDI_EXTENDED_FEATURE_RX_DMA          0x20
+#define DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA  0x40
+#define DIVA_XDI_EXTENDED_FEATURE_WIDE_ID         0x80
 #define DIVA_XDI_EXTENDED_FEATURES_MAX_SZ    1
 /******************************************************************************/
 #define IDI_SYNC_REQ_XDI_GET_ADAPTER_SDRAM_BAR   0x93
@@ -115,6 +115,7 @@ typedef struct _diva_xdi_get_capi_parameters {
 typedef struct _diva_xdi_get_logical_adapter_number {
   dword logical_adapter_number;
   dword controller;
+  dword total_controllers;
 } diva_xdi_get_logical_adapter_number_s_t;
 /******************************************************************************/
 #define IDI_SYNC_REQ_UP1DM_OPERATION   0x96
@@ -134,6 +135,7 @@ typedef struct _diva_xdi_dma_descriptor_operation {
 #define IDI_SYNC_REQ_DIDD_ADD_ADAPTER               0x03
 #define IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER            0x04
 #define IDI_SYNC_REQ_DIDD_READ_ADAPTER_ARRAY        0x05
+#define IDI_SYNC_REQ_DIDD_GET_CFG_LIB_IFC           0x10
 typedef struct _diva_didd_adapter_notify {
  dword handle; /* Notification handle */
  void   * callback;
@@ -149,6 +151,9 @@ typedef struct _diva_didd_read_adapter_array {
  void   * buffer;
  dword length;
 } diva_didd_read_adapter_array_t;
+typedef struct _diva_didd_get_cfg_lib_ifc {
+ void* ifc;
+} diva_didd_get_cfg_lib_ifc_t;
 /******************************************************************************/
 #define IDI_SYNC_REQ_XDI_GET_STREAM    0x91
 #define DIVA_XDI_SYNCHRONOUS_SERVICE   0x01
@@ -466,6 +471,10 @@ typedef union
   ENTITY             e;
   diva_didd_read_adapter_array_t info;
  } didd_read_adapter_array;
+ struct {
+  ENTITY             e;
+  diva_didd_get_cfg_lib_ifc_t     info;
+ } didd_get_cfg_lib_ifc;
   struct {
     unsigned char Req;
     unsigned char Rc;
diff --git a/drivers/isdn/hardware/eicon/idifunc.c b/drivers/isdn/hardware/eicon/idifunc.c
index 63746f401..4cbc68cf4 100644
--- a/drivers/isdn/hardware/eicon/idifunc.c
+++ b/drivers/isdn/hardware/eicon/idifunc.c
@@ -1,4 +1,4 @@
-/* $Id: idifunc.c,v 1.14.4.2 2004/05/09 16:42:20 armin Exp $
+/* $Id: idifunc.c,v 1.14.4.4 2004/08/28 20:03:53 armin Exp $
  *
  * Driver for Eicon DIVA Server ISDN cards.
  * User Mode IDI Interface 
@@ -25,8 +25,6 @@ extern void DIVA_DIDD_Read(void *, int);
 extern int diva_user_mode_idi_create_adapter(const DESCRIPTOR *, int);
 extern void diva_user_mode_idi_remove_adapter(int);
 
-#define MAX_DESCRIPTORS  32
-
 static dword notify_handle;
 static DESCRIPTOR DAdapter;
 static DESCRIPTOR MAdapter;
diff --git a/drivers/isdn/hardware/eicon/io.c b/drivers/isdn/hardware/eicon/io.c
index 6f94ee932..15bb9c636 100644
--- a/drivers/isdn/hardware/eicon/io.c
+++ b/drivers/isdn/hardware/eicon/io.c
@@ -77,6 +77,7 @@ static byte extended_xdi_features[DIVA_XDI_EXTENDED_FEATURES_MAX_SZ+1] = {
 #if defined(DIVA_IDI_RX_DMA)
   DIVA_XDI_EXTENDED_FEATURE_CMA          |
   DIVA_XDI_EXTENDED_FEATURE_RX_DMA       |
+  DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA |
 #endif
   DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC),
  0
@@ -226,8 +227,10 @@ void request(PISDN_ADAPTER IoAdapter, ENTITY * e)
         if (pI->descriptor_number >= 0) {
           dword dma_magic;
           void* local_addr;
+#if 0
           DBG_TRC(("A(%d) dma_alloc(%d)",
                    IoAdapter->ANum, pI->descriptor_number))
+#endif
           diva_get_dma_map_entry (\
                                (struct _diva_dma_map_entry*)IoAdapter->dma_map,
                                pI->descriptor_number,
@@ -240,7 +243,9 @@ void request(PISDN_ADAPTER IoAdapter, ENTITY * e)
         }
       } else if ((pI->operation == IDI_SYNC_REQ_DMA_DESCRIPTOR_FREE) &&
                  (pI->descriptor_number >= 0)) {
+#if 0
         DBG_TRC(("A(%d) dma_free(%d)", IoAdapter->ANum, pI->descriptor_number))
+#endif
         diva_free_dma_map_entry((struct _diva_dma_map_entry*)IoAdapter->dma_map,
                                 pI->descriptor_number);
         pI->descriptor_number = -1;
@@ -257,6 +262,7 @@ void request(PISDN_ADAPTER IoAdapter, ENTITY * e)
                                      &syncReq->xdi_logical_adapter_number.info;
       pI->logical_adapter_number = IoAdapter->ANum;
       pI->controller = IoAdapter->ControllerNumber;
+      pI->total_controllers = IoAdapter->Properties.Adapters;
     } return;
     case IDI_SYNC_REQ_XDI_GET_CAPI_PARAMS: {
        diva_xdi_get_capi_parameters_t prms, *pI = &syncReq->xdi_capi_prms.info;
@@ -318,6 +324,16 @@ void request(PISDN_ADAPTER IoAdapter, ENTITY * e)
    }
    syncReq->GetSerial.serial = 0 ;
    break ;
+  case IDI_SYNC_REQ_GET_CARDTYPE:
+   if ( IoAdapter )
+   {
+    syncReq->GetCardType.cardtype = IoAdapter->cardType ;
+    DBG_TRC(("xdi: Adapter %d / CardType %ld",
+             IoAdapter->ANum, IoAdapter->cardType))
+    return ;
+   }
+   syncReq->GetCardType.cardtype = 0 ;
+   break ;
   case IDI_SYNC_REQ_GET_XLOG:
    if ( IoAdapter )
    {
@@ -326,6 +342,14 @@ void request(PISDN_ADAPTER IoAdapter, ENTITY * e)
    }
    e->Ind = 0 ;
    break ;
+  case IDI_SYNC_REQ_GET_DBG_XLOG:
+   if ( IoAdapter )
+   {
+    pcm_req (IoAdapter, e) ;
+    return ;
+   }
+   e->Ind = 0 ;
+   break ;
   case IDI_SYNC_REQ_GET_FEATURES:
    if ( IoAdapter )
    {
@@ -345,7 +369,9 @@ void request(PISDN_ADAPTER IoAdapter, ENTITY * e)
   }
   if ( IoAdapter )
   {
+#if 0
    DBG_FTL(("xdi: unknown Req 0 / Rc %d !", e->Rc))
+#endif
    return ;
   }
  }
@@ -496,7 +522,7 @@ pcm_req (PISDN_ADAPTER IoAdapter, ENTITY *e)
   diva_os_enter_spin_lock (&IoAdapter->data_spin_lock,
                &OldIrql,
                "data_pcm_1");
-  IoAdapter->pcm_data = (unsigned long)pcm;
+  IoAdapter->pcm_data = (void *)pcm;
   IoAdapter->pcm_pending = 1;
   diva_os_schedule_soft_isr (&IoAdapter->req_soft_isr);
   diva_os_leave_spin_lock (&IoAdapter->data_spin_lock,
@@ -510,7 +536,7 @@ pcm_req (PISDN_ADAPTER IoAdapter, ENTITY *e)
                  &OldIrql,
                  "data_pcm_3");
     IoAdapter->pcm_pending = 0;
-    IoAdapter->pcm_data   = 0;
+    IoAdapter->pcm_data    = NULL ;
     diva_os_leave_spin_lock (&IoAdapter->data_spin_lock,
                  &OldIrql,
                  "data_pcm_3");
@@ -528,7 +554,7 @@ pcm_req (PISDN_ADAPTER IoAdapter, ENTITY *e)
                &OldIrql,
                "data_pcm_4");
   IoAdapter->pcm_pending = 0;
-  IoAdapter->pcm_data   = 0;
+  IoAdapter->pcm_data    = NULL ;
   diva_os_leave_spin_lock (&IoAdapter->data_spin_lock,
                &OldIrql,
                "data_pcm_4");
@@ -668,7 +694,7 @@ word io_inw(ADAPTER * a, void * adr)
 void io_in_buffer(ADAPTER * a, void * adr, void * buffer, word len)
 {
   byte *Port = (byte*)DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io);
- byte* P = (byte*)buffer;
+  byte* P = (byte*)buffer;
   if ((long)adr & 1) {
     outppw(Port+4, (word)(unsigned long)adr);
     *P = inpp(Port);
@@ -678,7 +704,7 @@ void io_in_buffer(ADAPTER * a, void * adr, void * buffer, word len)
     if (!len) {
 	DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port);
 	return;
-  }
+    }
   }
   outppw(Port+4, (word)(unsigned long)adr);
   inppw_buffer (Port, P, len+1);
@@ -710,7 +736,7 @@ void io_outw(ADAPTER * a, void * adr, word data)
 void io_out_buffer(ADAPTER * a, void * adr, void * buffer, word len)
 {
   byte *Port = (byte*)DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io);
- byte* P = (byte*)buffer;
+  byte* P = (byte*)buffer;
   if ((long)adr & 1) {
     outppw(Port+4, (word)(unsigned long)adr);
     outpp(Port, *P);
@@ -839,21 +865,21 @@ void CALLBACK(ADAPTER * a, ENTITY * e)
 /* --------------------------------------------------------------------------
   routines for aligned reading and writing on RISC
   -------------------------------------------------------------------------- */
-void outp_words_from_buffer (word* adr, byte* P, word len)
+void outp_words_from_buffer (word* adr, byte* P, dword len)
 {
-  word i = 0;
+  dword i = 0;
   word w;
-  while (i < (len & 0xfffe)) {
+  while (i < (len & 0xfffffffe)) {
     w = P[i++];
     w += (P[i++])<<8;
     outppw (adr, w);
   }
 }
-void inp_words_to_buffer (word* adr, byte* P, word len)
+void inp_words_to_buffer (word* adr, byte* P, dword len)
 {
-  word i = 0;
+  dword i = 0;
   word w;
-  while (i < (len & 0xfffe)) {
+  while (i < (len & 0xfffffffe)) {
     w = inppw (adr);
     P[i++] = (byte)(w);
     P[i++] = (byte)(w>>8);
diff --git a/drivers/isdn/hardware/eicon/io.h b/drivers/isdn/hardware/eicon/io.h
index 3e5403983..32ce17dfe 100644
--- a/drivers/isdn/hardware/eicon/io.h
+++ b/drivers/isdn/hardware/eicon/io.h
@@ -39,6 +39,14 @@ typedef struct {
  DEVICE_NAME   DeviceName[4] ;
  PISDN_ADAPTER QuadroAdapter[4] ;
 } ADAPTER_LIST_ENTRY, *PADAPTER_LIST_ENTRY ;
+/* --------------------------------------------------------------------------
+  Special OS memory support structures
+  -------------------------------------------------------------------------- */
+#define MAX_MAPPED_ENTRIES 8
+typedef struct {
+ void  * Address;
+ dword    Length;
+} ADAPTER_MEMORY ;
 /* --------------------------------------------------------------------------
   Configuration of XDI clients carried by XDI
   -------------------------------------------------------------------------- */
@@ -52,6 +60,7 @@ typedef struct _diva_xdi_capi_cfg {
   -------------------------------------------------------------------------- */
 struct _ISDN_ADAPTER {
  void             (* DIRequest)(PISDN_ADAPTER, ENTITY *) ;
+ int                 State ; /* from NT4 1.srv, a good idea, but  a poor achievment */
  int                 Initialized ;
  int         RegisteredWithDidd ;
  int                 Unavailable ;  /* callback function possible? */
@@ -63,6 +72,7 @@ struct _ISDN_ADAPTER {
  /*
   remember mapped memory areas
  */
+ ADAPTER_MEMORY     MappedMemory[MAX_MAPPED_ENTRIES] ;
  CARD_PROPERTIES     Properties ;
  dword               cardType ;
  dword               protocol_id ;       /* configured protocol identifier */
@@ -87,15 +97,15 @@ struct _ISDN_ADAPTER {
  dword               downloadAddrTable[4] ; /* add. for MultiMaster */
  dword               MemoryBase ;
  dword               MemorySize ;
- byte       *Address ;
+ byte                *Address ;
  byte                *Config ;
  byte                *Control ;
- byte       *reset ;
- byte       *port ;
- byte       *ram ;
- byte       *cfg ;
- byte       *prom ;
- byte       *ctlReg ;
+ byte                *reset ;
+ byte                *port ;
+ byte                *ram ;
+ byte                *cfg ;
+ byte                *prom ;
+ byte                *ctlReg ;
  struct pc_maint  *pcm ;
  diva_os_dependent_devica_name_t os_name;
  byte                Name[32] ;
@@ -105,6 +115,7 @@ struct _ISDN_ADAPTER {
  char               *ProtocolSuffix ; /* internal protocolfile table */
  char                Archive[32] ;
  char                Protocol[32] ;
+ char                AddDownload[32] ; /* Dsp- or other additional download files */
  char                Oad1[ISDN_MAX_NUM_LEN] ;
  char                Osa1[ISDN_MAX_NUM_LEN] ;
  char                Oad2[ISDN_MAX_NUM_LEN] ;
@@ -153,8 +164,26 @@ struct _ISDN_ADAPTER {
  byte                ModemCarrierWaitTimeSec;
  byte                ModemCarrierLossWaitTimeTenthSec;
  byte                PiafsLinkTurnaroundInFrames;
+ byte                DiscAfterProgress;
+ byte                AniDniLimiter[3];
+ byte                TxAttenuation;  /* PRI/E1 only: attenuate TX signal */
  word                QsigFeatures;
  dword               GenerateRingtone ;
+ dword               SupplementaryServicesFeatures;
+ dword               R2Dialect;
+ dword               R2CasOptions;
+ dword               FaxV34Options;
+ dword               DisabledDspMask;
+ dword               AdapterTestMask;
+ dword               DspImageLength;
+ word                AlertToIn20mSecTicks;
+ word                ModemEyeSetup;
+ byte                R2CtryLength;
+ byte                CCBSRelTimer;
+ byte               *PcCfgBufferFile;/* flexible parameter via file */
+ byte               *PcCfgBuffer ; /* flexible parameter via multistring */
+ diva_os_dump_file_t dump_file; /* dump memory to file at lowest irq level */
+ diva_os_board_trace_t board_trace ; /* traces from the board */
  diva_os_spin_lock_t isr_spin_lock;
  diva_os_spin_lock_t data_spin_lock;
  diva_os_soft_isr_t req_soft_isr;
@@ -180,15 +209,21 @@ struct _ISDN_ADAPTER {
  void        (* stop)(PISDN_ADAPTER) ;
  void        (* rstFnc)(PISDN_ADAPTER) ;
  void        (* trapFnc)(PISDN_ADAPTER) ;
+ dword            (* DetectDsps)(PISDN_ADAPTER) ;
  void        (* os_trap_nfy_Fnc)(PISDN_ADAPTER, dword) ;
  diva_os_isr_callback_t diva_isr_handler;
- dword               sdram_bar;
+ dword               sdram_bar;  /* must be 32 bit */
  dword               fpga_features;
  volatile int        pcm_pending;
- volatile unsigned long      pcm_data;
+ volatile void *     pcm_data;
  diva_xdi_capi_cfg_t capi_cfg;
  dword               tasks;
- void*               dma_map;
+ void               *dma_map;
+ int             (*DivaAdapterTestProc)(PISDN_ADAPTER);
+ void               *AdapterTestMemoryStart;
+ dword               AdapterTestMemoryLength;
+ const byte* cfg_lib_memory_init;
+ dword       cfg_lib_memory_init_length;
 };
 /* ---------------------------------------------------------------------
   Entity table
@@ -219,8 +254,8 @@ struct s_load {
 /* ---------------------------------------------------------------------
   Functions for port io
    --------------------------------------------------------------------- */
-void outp_words_from_buffer (word* adr, byte* P, word len);
-void inp_words_to_buffer  (word* adr, byte* P, word len);
+void outp_words_from_buffer (word* adr, byte* P, dword len);
+void inp_words_to_buffer    (word* adr, byte* P, dword len);
 /* ---------------------------------------------------------------------
   platform specific conversions
    --------------------------------------------------------------------- */
@@ -240,6 +275,10 @@ void io_out(ADAPTER * a, void * adr, byte data);
 void io_outw(ADAPTER * a, void * adr, word data);
 void io_out_buffer(ADAPTER * a, void * adr, void * P, word length);
 void io_inc(ADAPTER * a, void * adr);
+void bri_in_buffer (PISDN_ADAPTER IoAdapter, dword Pos,
+                    void *Buf, dword Len);
+int bri_out_buffer (PISDN_ADAPTER IoAdapter, dword Pos,
+                    void *Buf, dword Len, int Verify);
 /* ---------------------------------------------------------------------
   ram access functions for memory mapped cards
    --------------------------------------------------------------------- */
diff --git a/drivers/isdn/hardware/eicon/maintidi.c b/drivers/isdn/hardware/eicon/maintidi.c
index 8bef29b8b..a1ed7786d 100644
--- a/drivers/isdn/hardware/eicon/maintidi.c
+++ b/drivers/isdn/hardware/eicon/maintidi.c
@@ -115,7 +115,7 @@ diva_strace_library_interface_t* DivaSTraceLibraryCreateInstance (int Adapter,
 		return NULL;
 	}
 
-  pmem += sizeof(*pLib);
+	pmem += sizeof(*pLib);
 	memset(pLib, 0x00, sizeof(*pLib));
 
 	pLib->Adapter  = Adapter;
@@ -337,13 +337,60 @@ static int SuperTraceMessageInput (void* hLib) {
         pLib->e.RNum       = 1;
         pLib->e.R->P       = (byte*)&pLib->buffer[0];
         pLib->e.R->PLength = (word)(sizeof(pLib->buffer) - 1);
+
       } else {
         /*
           Indication reception complete, process it now
           */
         byte* p = (byte*)&pLib->buffer[0];
         pLib->buffer[pLib->e.R->PLength] = 0; /* terminate I.E. with zero */
+
         switch (Ind) {
+          case MAN_COMBI_IND: {
+            int total_length    = pLib->e.R->PLength;
+            word  this_ind_length;
+
+            while (total_length > 3 && *p) {
+              Ind = *p++;
+              this_ind_length = (word)p[0] | ((word)p[1] << 8);
+              p += 2;
+
+              switch (Ind) {
+                case MAN_INFO_IND:
+                  if (process_idi_info (pLib, (diva_man_var_header_t*)p)) {
+                    return (-1);
+                  }
+                  break;
+      					case MAN_EVENT_IND:
+                  if (process_idi_event (pLib, (diva_man_var_header_t*)p)) {
+                    return (-1);
+                  }
+                  break;
+                case MAN_TRACE_IND:
+                  if (pLib->trace_on == 1) {
+                    /*
+                      Ignore first trace event that is result of
+                      EVENT_ON operation
+                    */
+                    pLib->trace_on++;
+                  } else {
+                    /*
+                      Delivery XLOG buffer to application
+                      */
+                    if (pLib->user_proc_table.trace_proc) {
+                      (*(pLib->user_proc_table.trace_proc))(pLib->user_proc_table.user_context,
+                                                            &pLib->instance, pLib->Adapter,
+                                                            p, this_ind_length);
+                    }
+                  }
+                  break;
+                default:
+                  diva_mnt_internal_dprintf (0, DLI_ERR, "Unknon IDI Ind (DMA mode): %02x", Ind);
+              }
+              p += (this_ind_length+1);
+              total_length -= (4 + this_ind_length);
+            }
+          } break;
           case MAN_INFO_IND:
             if (process_idi_info (pLib, (diva_man_var_header_t*)p)) {
               return (-1);
@@ -806,7 +853,7 @@ static int ScheduleNextTraceRequest (diva_strace_context_t* pLib) {
 }
 
 static int process_idi_event (diva_strace_context_t* pLib,
-															diva_man_var_header_t* pVar) {
+				diva_man_var_header_t* pVar) {
 	const char* path = (char*)&pVar->path_length+1;
 	char name[64];
 	int i;
diff --git a/drivers/isdn/hardware/eicon/maintidi.h b/drivers/isdn/hardware/eicon/maintidi.h
index 184142cdf..4f0629496 100644
--- a/drivers/isdn/hardware/eicon/maintidi.h
+++ b/drivers/isdn/hardware/eicon/maintidi.h
@@ -49,6 +49,8 @@ typedef struct _diva_strace_path2action {
 	void*							 variable; /* Variable that will receive value */
 } diva_strace_path2action_t;
 
+#define DIVA_MAX_MANAGEMENT_TRANSFER_SIZE 4096
+
 typedef struct _diva_strace_context {
 	diva_strace_library_interface_t	instance;
 
@@ -62,7 +64,7 @@ typedef struct _diva_strace_context {
   IDI_CALL request;
   BUFFERS  XData;
   BUFFERS  RData;
-	byte buffer[2048+512+1];
+	byte buffer[DIVA_MAX_MANAGEMENT_TRANSFER_SIZE + 1];
   int removal_state;
   int general_b_ch_event;
   int general_fax_event;
diff --git a/drivers/isdn/hardware/eicon/mntfunc.c b/drivers/isdn/hardware/eicon/mntfunc.c
index c94229904..29492451a 100644
--- a/drivers/isdn/hardware/eicon/mntfunc.c
+++ b/drivers/isdn/hardware/eicon/mntfunc.c
@@ -1,4 +1,4 @@
-/* $Id: mntfunc.c,v 1.19 2004/01/09 21:22:03 armin Exp $
+/* $Id: mntfunc.c,v 1.19.6.2 2004/08/28 20:03:53 armin Exp $
  *
  * Driver for Eicon DIVA Server ISDN cards.
  * Maint module
@@ -23,17 +23,12 @@ extern char *DRIVERRELEASE_MNT;
 
 extern void DIVA_DIDD_Read(void *, int);
 
-#define MAX_DESCRIPTORS  32
-
 static dword notify_handle;
 static DESCRIPTOR DAdapter;
 static DESCRIPTOR MAdapter;
 static DESCRIPTOR MaintDescriptor =
     { IDI_DIMAINT, 0, 0, (IDI_CALL) diva_maint_prtComp };
 
-extern void *diva_os_malloc_tbuffer(unsigned long flags,
-				    unsigned long size);
-extern void diva_os_free_tbuffer(unsigned long flags, void *ptr);
 extern int diva_os_copy_to_user(void *os_handle, void __user *dst,
 				const void *src, int length);
 extern int diva_os_copy_from_user(void *os_handle, void *dst,
@@ -46,16 +41,6 @@ static void no_printf(unsigned char *x, ...)
 
 #include "debuglib.c"
 
-/*
- * stop debug
- */
-static void stop_dbg(void)
-{
-	DbgDeregister();
-	memset(&MAdapter, 0, sizeof(MAdapter));
-	dprintf = no_printf;
-}
-
 /*
  *  DIDD callback function
  */
@@ -66,7 +51,9 @@ static void *didd_callback(void *context, DESCRIPTOR * adapter,
 		DBG_ERR(("cb: Change in DAdapter ? Oops ?."));
 	} else if (adapter->type == IDI_DIMAINT) {
 		if (removal) {
-			stop_dbg();
+			DbgDeregister();
+			memset(&MAdapter, 0, sizeof(MAdapter));
+			dprintf = no_printf;
 		} else {
 			memcpy(&MAdapter, adapter, sizeof(MAdapter));
 			dprintf = (DIVA_DI_PRINTF) MAdapter.request;
@@ -131,8 +118,6 @@ static void DIVA_EXIT_FUNCTION disconnect_didd(void)
 {
 	IDI_SYNC_REQ req;
 
-	stop_dbg();
-
 	req.didd_notify.e.Req = 0;
 	req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
 	req.didd_notify.info.handle = notify_handle;
@@ -193,34 +178,63 @@ int maint_read_write(void __user *buf, int count)
 		}
 		break;
 
+    /*
+       Filter commands will ignore the ID due to fact that filtering affects
+       the B- channel and Audio Tap trace levels only. Also MAINT driver will
+       select the right trace ID by itself
+       */
+	case DITRACE_WRITE_SELECTIVE_TRACE_FILTER:
+		if (!mask) {
+			ret = diva_set_trace_filter (1, "*");
+		} else if (mask < sizeof(data)) {
+			if (copy_from_user(data, (char __user *)buf+12, mask)) {
+				ret = -EFAULT;
+			} else {
+				ret = diva_set_trace_filter ((int)mask, data);
+			}
+		} else {
+			ret = -EINVAL;
+		}
+		break;
+
+	case DITRACE_READ_SELECTIVE_TRACE_FILTER:
+		if ((ret = diva_get_trace_filter (sizeof(data), data)) > 0) {
+			if (copy_to_user (buf, data, ret))
+				ret = -EFAULT;
+		} else {
+			ret = -ENODEV;
+		}
+		break;
+
 	case DITRACE_READ_TRACE_ENTRY:{
 			diva_os_spin_lock_magic_t old_irql;
 			word size;
 			diva_dbg_entry_head_t *pmsg;
 			byte *pbuf;
 
-			if ((pmsg = diva_maint_get_message(&size, &old_irql))) {
+			if (!(pbuf = diva_os_malloc(0, mask))) {
+				return (-ENOMEM);
+			}
+
+			for(;;) {
+				if (!(pmsg =
+				    diva_maint_get_message(&size, &old_irql))) {
+					break;
+				}
 				if (size > mask) {
 					diva_maint_ack_message(0, &old_irql);
 					ret = -EINVAL;
-				} else {
-					if (!(pbuf = diva_os_malloc_tbuffer(0, size)))
-					{
-						diva_maint_ack_message(0, &old_irql);
-						ret = -ENOMEM;
-					} else {
-						ret = size;
-						memcpy(pbuf, pmsg, size);
-						diva_maint_ack_message(1, &old_irql);
-						if ((count < size) || diva_os_copy_to_user (NULL, buf,
-						     (void *) pbuf, size))
-							ret = -EFAULT;
-						diva_os_free_tbuffer(0, pbuf);
-					}
+					break;
 				}
-			} else {
-				ret = 0;
+				ret = size;
+				memcpy(pbuf, pmsg, size);
+				diva_maint_ack_message(1, &old_irql);
+				if ((count < size) ||
+				     diva_os_copy_to_user (NULL, buf, (void *) pbuf, size))
+							ret = -EFAULT;
+				break;
 			}
+			diva_os_free(0, pbuf);
 		}
 		break;
 
@@ -235,7 +249,7 @@ int maint_read_write(void __user *buf, int count)
 				ret = -EINVAL;
 				break;
 			}
-			if (!(pbuf = diva_os_malloc_tbuffer(0, mask))) {
+			if (!(pbuf = diva_os_malloc(0, mask))) {
 				return (-ENOMEM);
 			}
 
@@ -273,7 +287,7 @@ int maint_read_write(void __user *buf, int count)
 			} else {
 				ret = written;
 			}
-			diva_os_free_tbuffer(0, pbuf);
+			diva_os_free(0, pbuf);
 		}
 		break;
 
@@ -302,7 +316,7 @@ int DIVA_INIT_FUNCTION mntfunc_init(int *buffer_length, void **buffer,
 	} else {
 		while ((*buffer_length >= (64 * 1024))
 		       &&
-		       (!(*buffer = diva_os_malloc_tbuffer(0, *buffer_length)))) {
+		       (!(*buffer = diva_os_malloc (0, *buffer_length)))) {
 			*buffer_length -= 1024;
 		}
 
@@ -314,7 +328,7 @@ int DIVA_INIT_FUNCTION mntfunc_init(int *buffer_length, void **buffer,
 
 	if (diva_maint_init(*buffer, *buffer_length, (diva_dbg_mem == 0))) {
 		if (!diva_dbg_mem) {
-			diva_os_free_tbuffer(0, *buffer);
+			diva_os_free (0, *buffer);
 		}
 		DBG_ERR(("init: maint init failed"));
 		return (0);
@@ -324,7 +338,7 @@ int DIVA_INIT_FUNCTION mntfunc_init(int *buffer_length, void **buffer,
 		DBG_ERR(("init: failed to connect to DIDD."));
 		diva_maint_finit();
 		if (!diva_dbg_mem) {
-			diva_os_free_tbuffer(0, *buffer);
+			diva_os_free (0, *buffer);
 		}
 		return (0);
 	}
@@ -339,6 +353,8 @@ void DIVA_EXIT_FUNCTION mntfunc_finit(void)
 	void *buffer;
 	int i = 100;
 
+	DbgDeregister();
+
 	while (diva_mnt_shutdown_xdi_adapters() && i--) {
 		diva_os_sleep(10);
 	}
@@ -346,6 +362,9 @@ void DIVA_EXIT_FUNCTION mntfunc_finit(void)
 	disconnect_didd();
 
 	if ((buffer = diva_maint_finit())) {
-		diva_os_free_tbuffer(0, buffer);
+		diva_os_free (0, buffer);
 	}
+
+	memset(&MAdapter, 0, sizeof(MAdapter));
+	dprintf = no_printf;
 }
diff --git a/drivers/isdn/hardware/eicon/pc.h b/drivers/isdn/hardware/eicon/pc.h
index a65550605..1c6945768 100644
--- a/drivers/isdn/hardware/eicon/pc.h
+++ b/drivers/isdn/hardware/eicon/pc.h
@@ -143,6 +143,7 @@ struct dual
 #define N_DATA_ACK      12      /* data ack ind for D-bit procedure */
 #define N_EDATA_ACK     13      /* data ack ind for INTERRUPT       */
 #define N_XON           15      /* clear RNR state */
+#define N_COMBI_IND     N_XON   /* combined indication              */
 #define N_Q_BIT         0x10    /* Q-bit for req/ind                */
 #define N_M_BIT         0x20    /* M-bit for req/ind                */
 #define N_D_BIT         0x40    /* D-bit for req/ind                */
@@ -228,6 +229,10 @@ struct dual
 #define VSWITCH_IND 66        /* capifunctions for D-CH-switching   */
 #define MWI_POLL 67     /* Message Waiting Status Request fkt */
 #define CALL_PEND_NOTIFY 68 /* notify capi to set new listen        */
+#define DO_NOTHING 69       /* dont do somethin if you get this     */
+#define INT_CT_REJ 70       /* ECT rejected internal command        */
+#define CALL_HOLD_COMPLETE 71 /* In NT Mode indicate hold complete  */
+#define CALL_RETRIEVE_COMPLETE 72 /* In NT Mode indicate retrieve complete  */
 /*------------------------------------------------------------------*/
 /* management service primitives                                    */
 /*------------------------------------------------------------------*/
@@ -241,6 +246,7 @@ struct dual
 #define MAN_INFO_IND    2
 #define MAN_EVENT_IND   3
 #define MAN_TRACE_IND   4
+#define MAN_COMBI_IND   9
 #define MAN_ESC         0x80
 /*------------------------------------------------------------------*/
 /* return code coding                                               */
@@ -265,6 +271,7 @@ struct dual
 /*------------------------------------------------------------------*/
 #define SHIFT 0x90              /* codeset shift                    */
 #define MORE 0xa0               /* more data                        */
+#define SDNCMPL 0xa1            /* sending complete                 */
 #define CL 0xb0                 /* congestion level                 */
         /* codeset 0                                                */
 #define SMSG 0x00               /* segmented message                */
@@ -288,6 +295,8 @@ struct dual
 #define RDX 0x73                /* redirecting number extended      */
 #define RDN 0x74                /* redirecting number               */
 #define RIN 0x76                /* redirection number               */
+#define IUP 0x76                /* VN6 rerouter->PCS (codeset 6)    */
+#define IPU 0x77                /* VN6 PCS->rerouter (codeset 6)    */
 #define RI  0x79                /* restart indicator                */
 #define MIE 0x7a                /* management info element          */
 #define LLC 0x7c                /* low layer compatibility          */
@@ -296,6 +305,8 @@ struct dual
 #define ESC 0x7f                /* escape extension                 */
 #define DLC 0x20                /* data link layer configuration    */
 #define NLC 0x21                /* network layer configuration      */
+#define REDIRECT_IE     0x22    /* redirection request/indication data */
+#define REDIRECT_NET_IE 0x23    /* redirection network override data   */
         /* codeset 6                                                */
 #define SIN 0x01                /* service indicator                */
 #define CIF 0x02                /* charging information             */
@@ -306,6 +317,7 @@ struct dual
 /*------------------------------------------------------------------*/
 #define MSGTYPEIE        0x7a   /* Messagetype info element         */
 #define CRIE             0x7b   /* INFO info element                */
+#define CODESET6IE       0xec   /* Tunnel for Codeset 6 IEs         */
 #define VSWITCHIE        0xed   /* VSwitch info element             */
 #define SSEXTIE          0xee   /* Supplem. Service info element    */
 #define PROFILEIE        0xef   /* Profile info element             */
@@ -344,6 +356,13 @@ struct dual
 #define CCBS_REQUEST              0x32
 #define CCBS_DEACTIVATE           0x33
 #define CCBS_INTERROGATE          0x34
+#define CCBS_STATUS               0x35
+#define CCBS_ERASE                0x36
+#define CCBS_B_FREE               0x37
+#define CCNR_INFO_RETAIN          0x38
+#define CCBS_REMOTE_USER_FREE     0x39
+#define CCNR_REQUEST              0x3a
+#define CCNR_INTERROGATE          0x3b
 #define GET_SUPPORTED_SERVICES    0xff
 #define DIVERSION_PROCEDURE_CFU     0x70
 #define DIVERSION_PROCEDURE_CFB     0x71
@@ -362,6 +381,7 @@ struct dual
 #define SMASK_3PTY                 0x00000008
 #define SMASK_CALL_FORWARDING      0x00000010
 #define SMASK_CALL_DEFLECTION      0x00000020
+#define SMASK_MCID                 0x00000040
 #define SMASK_CCBS                 0x00000080
 #define SMASK_MWI                  0x00000100
 #define SMASK_CCNR                 0x00000200
@@ -406,6 +426,8 @@ struct dual
 #define RTPL2_IN       13       /* RTP layer-2 protocol, incomming  */
 #define RTPL2          14       /* RTP layer-2 protocol             */
 #define V120_V42BIS    15       /* V.120 asynchronous mode supporting V.42bis compression */
+#define LISTENER       27       /* Layer 2 to listen line */
+#define MTP2           28       /* MTP2 Layer 2 */
 #define PIAFS_CRC      29       /* PIAFS Layer 2 with CRC calculation at L2 */
 /* ------------------------------------------------------
    PIAFS DLC DEFINITIONS
@@ -506,6 +528,22 @@ Byte | 8 7 6 5 4 3 2 1
 |                     |      |                        data transfer.   |
 +---------------------+------+-----------------------------------------+
 */
+/* ------------------------------------------------------
+   LISTENER DLC DEFINITIONS
+   ------------------------------------------------------ */
+#define LISTENER_FEATURE_MASK_CUMMULATIVE            0x0001
+/* ------------------------------------------------------
+   LISTENER META-FRAME CODE/PRIMITIVE DEFINITIONS
+   ------------------------------------------------------ */
+#define META_CODE_LL_UDATA_RX 0x01
+#define META_CODE_LL_UDATA_TX 0x02
+#define META_CODE_LL_DATA_RX  0x03
+#define META_CODE_LL_DATA_TX  0x04
+#define META_CODE_LL_MDATA_RX 0x05
+#define META_CODE_LL_MDATA_TX 0x06
+#define META_CODE_EMPTY       0x10
+#define META_CODE_LOST_FRAMES 0x11
+#define META_FLAG_TRUNCATED   0x0001
 /*------------------------------------------------------------------*/
 /* CAPI-like profile to indicate features on LAW_REQ                */
 /*------------------------------------------------------------------*/
@@ -577,6 +615,14 @@ Byte | 8 7 6 5 4 3 2 1
 #define MANUFACTURER_FEATURE_DMACONNECT           0x04000000L
 #define MANUFACTURER_FEATURE_AUDIO_TAP            0x08000000L
 #define MANUFACTURER_FEATURE_FAX_NONSTANDARD      0x10000000L
+#define MANUFACTURER_FEATURE_SS7                  0x20000000L
+#define MANUFACTURER_FEATURE_MADAPTER             0x40000000L
+#define MANUFACTURER_FEATURE_MEASURE              0x80000000L
+#define MANUFACTURER_FEATURE2_LISTENING           0x00000001L
+#define MANUFACTURER_FEATURE2_SS_DIFFCONTPOSSIBLE 0x00000002L
+#define MANUFACTURER_FEATURE2_GENERIC_TONE        0x00000004L
+#define MANUFACTURER_FEATURE2_COLOR_FAX           0x00000008L
+#define MANUFACTURER_FEATURE2_SS_ECT_DIFFCONTPOSSIBLE 0x00000010L
 #define RTP_PRIM_PAYLOAD_PCMU_8000     0
 #define RTP_PRIM_PAYLOAD_1016_8000     1
 #define RTP_PRIM_PAYLOAD_G726_32_8000  2
@@ -624,6 +670,15 @@ Byte | 8 7 6 5 4 3 2 1
 #define VSINVOKEID    4
 #define VSCLMRKS       5
 #define VSTBCTIDENT    6
+#define VSETSILINKID   7
+#define VSSAMECONTROLLER 8
+/* Errorcodes for VSETSILINKID begin */
+#define VSETSILINKIDRRWC      1
+#define VSETSILINKIDREJECT    2
+#define VSETSILINKIDTIMEOUT   3
+#define VSETSILINKIDFAILCOUNT 4
+#define VSETSILINKIDERROR     5
+/* Errorcodes for VSETSILINKID end */
 /* -----------------------------------------------------------**
 ** The PROTOCOL_FEATURE_STRING in feature.h (included         **
 ** in prstart.sx and astart.sx) defines capabilities and      **
@@ -647,5 +702,37 @@ Byte | 8 7 6 5 4 3 2 1
 #define PROTCAP_FREE13    0x2000  /* not used                            */
 #define PROTCAP_FREE14    0x4000  /* not used                            */
 #define PROTCAP_EXTENSION 0x8000  /* used for future extentions          */
+/* -----------------------------------------------------------* */
+/* Onhook data transmission ETS30065901 */
+/* Message Type */
+/*#define RESERVED4                 0x4*/
+#define CALL_SETUP                0x80
+#define MESSAGE_WAITING_INDICATOR 0x82
+/*#define RESERVED84                0x84*/
+/*#define RESERVED85                0x85*/
+#define ADVICE_OF_CHARGE          0x86
+/*1111 0001
+to
+1111 1111
+F1H - Reserved for network operator use
+to
+FFH*/
+/* Parameter Types */
+#define DATE_AND_TIME                                           1
+#define CLI_PARAMETER_TYPE                                      2
+#define CALLED_DIRECTORY_NUMBER_PARAMETER_TYPE                  3
+#define REASON_FOR_ABSENCE_OF_CLI_PARAMETER_TYPE                4
+#define NAME_PARAMETER_TYPE                                     7
+#define REASON_FOR_ABSENCE_OF_CALLING_PARTY_NAME_PARAMETER_TYPE 8
+#define VISUAL_INDICATOR_PARAMETER_TYPE                         0xb
+#define COMPLEMENTARY_CLI_PARAMETER_TYPE                        0x10
+#define CALL_TYPE_PARAMETER_TYPE                                0x11
+#define FIRST_CALLED_LINE_DIRECTORY_NUMBER_PARAMETER_TYPE       0x12
+#define NETWORK_MESSAGE_SYSTEM_STATUS_PARAMETER_TYPE            0x13
+#define FORWARDED_CALL_TYPE_PARAMETER_TYPE                      0x15
+#define TYPE_OF_CALLING_USER_PARAMETER_TYPE                     0x16
+#define REDIRECTING_NUMBER_PARAMETER_TYPE                       0x1a
+#define EXTENSION_FOR_NETWORK_OPERATOR_USE_PARAMETER_TYPE       0xe0
+/* -----------------------------------------------------------* */
 #else
 #endif /* PC_H_INCLUDED  } */
diff --git a/drivers/isdn/hardware/eicon/platform.h b/drivers/isdn/hardware/eicon/platform.h
index 31299feb7..0457682b0 100644
--- a/drivers/isdn/hardware/eicon/platform.h
+++ b/drivers/isdn/hardware/eicon/platform.h
@@ -1,4 +1,4 @@
-/* $Id: platform.h,v 1.37.4.1 2004/07/28 14:47:21 armin Exp $
+/* $Id: platform.h,v 1.37.4.2 2004/08/28 20:03:53 armin Exp $
  *
  * platform.h
  * 
@@ -269,20 +269,6 @@ static __inline__ void diva_os_leave_spin_lock (diva_os_spin_lock_t* a, \
                               diva_os_spin_lock_magic_t* old_irql, \
                               void* dbg) { spin_unlock_bh(a); }
 
-static __inline__ void diva_os_enter_spin_lock_hard (diva_os_spin_lock_t* a, \
-                                   diva_os_spin_lock_magic_t* old_irql, \
-                                   void* dbg) { \
-  unsigned long flags; \
-  spin_lock_irqsave (a, flags); \
-  *old_irql = (diva_os_spin_lock_magic_t)flags; \
-}
-static __inline__ void diva_os_leave_spin_lock_hard (diva_os_spin_lock_t* a, \
-                                   diva_os_spin_lock_magic_t* old_irql, \
-                                   void* dbg) { \
-  unsigned long flags = (unsigned long)*old_irql; \
-	spin_unlock_irqrestore (a, flags); \
-}
-
 #define diva_os_destroy_spin_lock(a,b) do { } while(0)
 
 /*
@@ -347,12 +333,18 @@ diva_os_atomic_decrement(diva_os_atomic_t* pv)
 
 #define DIVA_IDI_RX_DMA 1
 
+/*
+** endian macros
+*/
 #define READ_WORD(addr)   readw(addr)
 #define READ_DWORD(addr)  readl(addr)
 
 #define WRITE_WORD(addr,v)  writew(v,addr)
 #define WRITE_DWORD(addr,v) writel(v,addr)
 
+/*
+** 32/64 bit macors
+*/
 #ifdef BITS_PER_LONG
  #if BITS_PER_LONG > 32 
   #define PLATFORM_GT_32BIT
@@ -360,8 +352,23 @@ diva_os_atomic_decrement(diva_os_atomic_t* pv)
  #endif
 #endif
 
+/*
+** undef os definitions of macros we use
+*/
 #undef ID_MASK
 #undef N_DATA
 #undef ADDR
 
+/*
+** dump file
+*/
+#define diva_os_dump_file_t char
+#define diva_os_board_trace_t char
+#define diva_os_dump_file(__x__) do { } while(0)
+
+/*
+** size of internal arrays
+*/
+#define MAX_DESCRIPTORS 64
+
 #endif	/* __PLATFORM_H__ */
diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
index 235f28a46..3a6acdead 100644
--- a/drivers/isdn/hisax/avm_pci.c
+++ b/drivers/isdn/hisax/avm_pci.c
@@ -752,70 +752,70 @@ setup_avm_pcipnp(struct IsdnCard *card)
 		cs->hw.avm.cfg_reg = card->para[1];
 		cs->irq = card->para[0];
 		cs->subtyp = AVM_FRITZ_PNP;
-	} else {
+		goto ready;
+	}
 #ifdef __ISAPNP__
-		if (isapnp_present()) {
-			struct pnp_dev *pnp_avm_d = NULL;
-			if ((pnp_avm_c = pnp_find_card(
+	if (isapnp_present()) {
+		struct pnp_dev *pnp_avm_d = NULL;
+		if ((pnp_avm_c = pnp_find_card(
+			ISAPNP_VENDOR('A', 'V', 'M'),
+			ISAPNP_FUNCTION(0x0900), pnp_avm_c))) {
+			if ((pnp_avm_d = pnp_find_dev(pnp_avm_c,
 				ISAPNP_VENDOR('A', 'V', 'M'),
-				ISAPNP_FUNCTION(0x0900), pnp_avm_c))) {
-				if ((pnp_avm_d = pnp_find_dev(pnp_avm_c,
-					ISAPNP_VENDOR('A', 'V', 'M'),
-					ISAPNP_FUNCTION(0x0900), pnp_avm_d))) {
-					int err;
-
-					pnp_disable_dev(pnp_avm_d);
-					err = pnp_activate_dev(pnp_avm_d);
-					if (err<0) {
-						printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
-							__FUNCTION__, err);
-						return(0);
-					}
-					cs->hw.avm.cfg_reg =
-						pnp_port_start(pnp_avm_d, 0);
-					cs->irq = pnp_irq(pnp_avm_d, 0);
-					if (!cs->irq) {
-						printk(KERN_ERR "FritzPnP:No IRQ\n");
-						return(0);
-					}
-					if (!cs->hw.avm.cfg_reg) {
-						printk(KERN_ERR "FritzPnP:No IO address\n");
-						return(0);
-					}
-					cs->subtyp = AVM_FRITZ_PNP;
-					goto ready;
+				ISAPNP_FUNCTION(0x0900), pnp_avm_d))) {
+				int err;
+
+				pnp_disable_dev(pnp_avm_d);
+				err = pnp_activate_dev(pnp_avm_d);
+				if (err<0) {
+					printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
+						__FUNCTION__, err);
+					return(0);
+				}
+				cs->hw.avm.cfg_reg =
+					pnp_port_start(pnp_avm_d, 0);
+				cs->irq = pnp_irq(pnp_avm_d, 0);
+				if (!cs->irq) {
+					printk(KERN_ERR "FritzPnP:No IRQ\n");
+					return(0);
 				}
+				if (!cs->hw.avm.cfg_reg) {
+					printk(KERN_ERR "FritzPnP:No IO address\n");
+					return(0);
+				}
+				cs->subtyp = AVM_FRITZ_PNP;
+				goto ready;
 			}
-		} else {
-			printk(KERN_INFO "FritzPnP: no ISA PnP present\n");
 		}
+	} else {
+		printk(KERN_INFO "FritzPnP: no ISA PnP present\n");
+	}
 #endif
 #ifdef CONFIG_PCI
-		if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM,
-			PCI_DEVICE_ID_AVM_A1,  dev_avm))) {
-			cs->irq = dev_avm->irq;
-			if (!cs->irq) {
-				printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n");
-				return(0);
-			}
-			if (pci_enable_device(dev_avm))
-				return(0);
-			cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1);
-			if (!cs->hw.avm.cfg_reg) {
-				printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n");
-				return(0);
-			}
-			cs->subtyp = AVM_FRITZ_PCI;
-		} else {
-			printk(KERN_WARNING "FritzPCI: No PCI card found\n");
+	if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM,
+		PCI_DEVICE_ID_AVM_A1,  dev_avm))) {
+		cs->irq = dev_avm->irq;
+		if (!cs->irq) {
+			printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n");
+			return(0);
+		}
+		if (pci_enable_device(dev_avm))
+			return(0);
+		cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1);
+		if (!cs->hw.avm.cfg_reg) {
+			printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n");
 			return(0);
 		}
-		cs->irq_flags |= SA_SHIRQ;
+		cs->subtyp = AVM_FRITZ_PCI;
+	} else {
+		printk(KERN_WARNING "FritzPCI: No PCI card found\n");
+		return(0);
+	}
+	cs->irq_flags |= SA_SHIRQ;
 #else
-		printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n");
-		return (0);
+	printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n");
+	return (0);
 #endif /* CONFIG_PCI */
-	}
 ready:
 	cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
 	if (!request_region(cs->hw.avm.cfg_reg, 32,
diff --git a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c
index f6a21dffa..f410f628a 100644
--- a/drivers/isdn/hisax/bkm_a4t.c
+++ b/drivers/isdn/hisax/bkm_a4t.c
@@ -265,7 +265,7 @@ setup_bkm_a4t(struct IsdnCard *card)
 	char tmp[64];
 	u_int pci_memaddr = 0, found = 0;
 	I20_REGISTER_FILE *pI20_Regs;
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 #endif
 
 	strcpy(tmp, bkm_a4t_revision);
@@ -275,7 +275,7 @@ setup_bkm_a4t(struct IsdnCard *card)
 	} else
 		return (0);
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 	while ((dev_a4t = pci_find_device(PCI_VENDOR_ID_ZORAN,
 		PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) {
 		u16 sub_sys;
diff --git a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c
index 0c32d3700..94bb83ce7 100644
--- a/drivers/isdn/hisax/bkm_a8.c
+++ b/drivers/isdn/hisax/bkm_a8.c
@@ -21,7 +21,7 @@
 #include <linux/pci.h>
 #include "bkm_ax.h"
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 
 #define	ATTEMPT_PCI_REMAPPING	/* Required for PLX rev 1 */
 
@@ -285,7 +285,7 @@ static u_char pci_irq __initdata = 0;
 int __init
 setup_sct_quadro(struct IsdnCard *card)
 {
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 	u_char pci_rev_id;
diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c
index 2b54e7d6f..394d481e0 100644
--- a/drivers/isdn/hisax/diva.c
+++ b/drivers/isdn/hisax/diva.c
@@ -1027,7 +1027,7 @@ setup_diva(struct IsdnCard *card)
 			}
 		}
 #endif
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 		cs->subtyp = 0;
 		if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON,
 			PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) {
diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
index b33678129..3b526d704 100644
--- a/drivers/isdn/hisax/elsa.c
+++ b/drivers/isdn/hisax/elsa.c
@@ -1022,7 +1022,7 @@ setup_elsa(struct IsdnCard *card)
 		       cs->hw.elsa.base,
 		       cs->irq);
 	} else if (cs->typ == ISDN_CTYPE_ELSA_PCI) {
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 		cs->subtyp = 0;
 		if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA,
 			PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) {
diff --git a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c
index a7acf9bd6..1cc4d11e0 100644
--- a/drivers/isdn/hisax/enternow_pci.c
+++ b/drivers/isdn/hisax/enternow_pci.c
@@ -299,7 +299,7 @@ setup_enternow_pci(struct IsdnCard *card)
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
 #endif
diff --git a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c
index 0d5931798..24a05a43f 100644
--- a/drivers/isdn/hisax/gazel.c
+++ b/drivers/isdn/hisax/gazel.c
@@ -634,7 +634,7 @@ setup_gazel(struct IsdnCard *card)
 			return (0);
 	} else {
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 		if (setup_gazelpci(cs))
 			return (0);
 #else
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index 20042fda8..3946536d1 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -65,7 +65,7 @@ static const PCI_ENTRY id_list[] =
 };
 
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 
 /******************************************/
 /* free hardware resources used by driver */
@@ -1655,7 +1655,7 @@ setup_hfcpci(struct IsdnCard *card)
 #endif
 	strcpy(tmp, hfcpci_revision);
 	printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 	cs->hw.hfcpci.int_s1 = 0;
 	cs->dc.hfcpci.ph_state = 0;
 	cs->hw.hfcpci.fifo = 255;
diff --git a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c
index 88cce430c..cf77d8360 100644
--- a/drivers/isdn/hisax/niccy.c
+++ b/drivers/isdn/hisax/niccy.c
@@ -309,7 +309,7 @@ setup_niccy(struct IsdnCard *card)
 			return (0);
 		}
 	} else {
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 		u_int pci_ioaddr;
 		cs->subtyp = 0;
 		if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM,
diff --git a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c
index 8b5822c42..fd664697f 100644
--- a/drivers/isdn/hisax/nj_s.c
+++ b/drivers/isdn/hisax/nj_s.c
@@ -167,7 +167,7 @@ setup_netjet_s(struct IsdnCard *card)
 		return(0);
 	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 
 	for ( ;; )
 	{
diff --git a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c
index efb5d8fbf..3d6441e96 100644
--- a/drivers/isdn/hisax/nj_u.c
+++ b/drivers/isdn/hisax/nj_u.c
@@ -137,7 +137,7 @@ setup_netjet_u(struct IsdnCard *card)
 	int bytecnt;
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 #endif
 #ifdef __BIG_ENDIAN
 #error "not running on big endian machines now"
@@ -148,7 +148,7 @@ setup_netjet_u(struct IsdnCard *card)
 		return(0);
 	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 
 	for ( ;; )
 	{
diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
index 863bfa50b..3393370ce 100644
--- a/drivers/isdn/hisax/sedlbauer.c
+++ b/drivers/isdn/hisax/sedlbauer.c
@@ -618,7 +618,7 @@ setup_sedlbauer(struct IsdnCard *card)
 		}
 #endif
 /* Probe for Sedlbauer speed pci */
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 		if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET,
 				PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) {
 			if (pci_enable_device(dev_sedl))
diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
index 04f9c5ce2..478b1a17b 100644
--- a/drivers/isdn/hisax/st5481_usb.c
+++ b/drivers/isdn/hisax/st5481_usb.c
@@ -143,9 +143,6 @@ static void usb_ctrl_complete(struct urb *urb, struct pt_regs *regs)
 	if (ctrl_msg->dr.bRequest == USB_REQ_CLEAR_FEATURE) {
 	        /* Special case handling for pipe reset */
 		le16_to_cpus(&ctrl_msg->dr.wIndex);
-		usb_endpoint_running(adapter->usb_dev,
-				     ctrl_msg->dr.wIndex & ~USB_DIR_IN, 
-				     (ctrl_msg->dr.wIndex & USB_DIR_IN) == 0);
 
 		/* toggle is reset on clear */
 		usb_settoggle(adapter->usb_dev, 
diff --git a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c
index 5e305554d..7713c467e 100644
--- a/drivers/isdn/hisax/telespci.c
+++ b/drivers/isdn/hisax/telespci.c
@@ -300,7 +300,7 @@ setup_telespci(struct IsdnCard *card)
 	printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp));
 	if (cs->typ != ISDN_CTYPE_TELESPCI)
 		return (0);
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 	if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) {
 		if (pci_enable_device(dev_tel))
 			return(0);
diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c
index cfe876043..36cfc4a48 100644
--- a/drivers/isdn/hisax/w6692.c
+++ b/drivers/isdn/hisax/w6692.c
@@ -1012,7 +1012,7 @@ setup_w6692(struct IsdnCard *card)
 	printk(KERN_INFO "HiSax: W6692 driver Rev. %s\n", HiSax_getrev(tmp));
 	if (cs->typ != ISDN_CTYPE_W6692)
 		return (0);
-#if CONFIG_PCI
+#ifdef CONFIG_PCI
 	while (id_list[id_idx].vendor_id) {
 		dev_w6692 = pci_find_device(id_list[id_idx].vendor_id,
 					    id_list[id_idx].device_id,
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index 69c6884e9..964d5c975 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -1369,7 +1369,7 @@ isdn_net_type_trans(struct sk_buff *skb, struct net_device *dev)
 
 	skb->mac.raw = skb->data;
 	skb_pull(skb, ETH_HLEN);
-	eth = skb->mac.ethernet;
+	eth = eth_hdr(skb);
 
 	if (*eth->h_dest & 1) {
 		if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index 02b912ab1..921c3c2ab 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -296,10 +296,7 @@ isdn_tty_tint(modem_info * info)
 		info->send_outstanding++;
 		info->msr &= ~UART_MSR_CTS;
 		info->lsr &= ~UART_LSR_TEMT;
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup) (tty);
-		wake_up_interruptible(&tty->write_wait);
+		tty_wakeup(tty);
 		return;
 	}
 	if (slen < 0) {
@@ -1174,10 +1171,7 @@ isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int co
 						/* If DLE decoding results in zero-transmit, but
 						 * c originally was non-zero, do a wakeup.
 						 */
-						if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-						 tty->ldisc.write_wakeup)
-							(tty->ldisc.write_wakeup) (tty);
-						wake_up_interruptible(&tty->write_wait);
+						tty_wakeup(tty);
 						info->msr |= UART_MSR_CTS;
 						info->lsr |= UART_LSR_TEMT;
 					}
@@ -1290,9 +1284,7 @@ isdn_tty_flush_buffer(struct tty_struct *tty)
 	isdn_tty_cleanup_xmit(info);
 	info->xmit_count = 0;
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup) (tty);
+	tty_wakeup(tty);
 }
 
 static void
@@ -1747,10 +1739,10 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp)
 	}
 	dev->modempoll--;
 	isdn_tty_shutdown(info);
+	
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
 	info->tty = NULL;
 	info->ncarrier = 0;
 	tty->closing = 0;
@@ -2681,8 +2673,7 @@ isdn_tty_modem_result(int code, modem_info * info)
 		if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
 			return;
 		}
-		if (info->tty->ldisc.flush_buffer)
-			info->tty->ldisc.flush_buffer(info->tty);
+		tty_ldisc_flush(info->tty);
 		if ((info->flags & ISDN_ASYNC_CHECK_CD) &&
 		    (!((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
 		       (info->flags & ISDN_ASYNC_CALLOUT_NOHUP)))) {
diff --git a/drivers/isdn/tpam/tpam_main.c b/drivers/isdn/tpam/tpam_main.c
index 91392c469..b418d37c7 100644
--- a/drivers/isdn/tpam/tpam_main.c
+++ b/drivers/isdn/tpam/tpam_main.c
@@ -23,7 +23,7 @@
 
 /* Local functions prototypes */
 static int __devinit tpam_probe(struct pci_dev *, const struct pci_device_id *);
-static void __devexit tpam_unregister_card(tpam_card *);
+static void __devexit tpam_unregister_card(struct pci_dev *, tpam_card *);
 static void __devexit tpam_remove(struct pci_dev *);
 static int __init tpam_init(void);
 static void __exit tpam_exit(void);
@@ -86,13 +86,20 @@ u32 tpam_findchannel(tpam_card *card, u32 ncoid) {
  */
 static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) {
 	tpam_card *card, *c;
-	int i;
+	int i, err;
+
+	if (pci_enable_device(dev)) {
+		printk(KERN_ERR "TurboPAM: can't enable PCI device at %s\n",
+			pci_name(dev));
+		return -ENODEV;
+	}
 
 	/* allocate memory for the board structure */
 	if (!(card = (tpam_card *)kmalloc(sizeof(tpam_card), GFP_KERNEL))) {
 		printk(KERN_ERR "TurboPAM: tpam_register_card: "
 		       "kmalloc failed!\n");
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto err_out_disable_dev;
 	}
 
 	memset((char *)card, 0, sizeof(tpam_card));
@@ -106,8 +113,8 @@ static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id
 			card->interface.id, card)) {
 		printk(KERN_ERR "TurboPAM: tpam_register_card: "
 		       "could not request irq %d\n", card->irq);
-		kfree(card);
-		return -EIO;
+		err = -EIO;
+		goto err_out_free_card;
 	}
 
 	/* remap board memory */
@@ -115,9 +122,8 @@ static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id
 						   0x800000))) {
 		printk(KERN_ERR "TurboPAM: tpam_register_card: "
 		       "unable to remap bar0\n");
-		free_irq(card->irq, card);
-		kfree(card);
-		return -EIO;
+		err = -EIO;
+		goto err_out_free_irq;
 	}
 
 	/* reset the board */
@@ -150,10 +156,8 @@ static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id
 	if (!register_isdn(&card->interface)) {
 		printk(KERN_ERR "TurboPAM: tpam_register_card: "
 		       "unable to register %s\n", card->interface.id);
-		free_irq(card->irq, card);
-		iounmap((void *)card->bar0);
-		kfree(card);
-		return -EIO;
+		err = -EIO;
+		goto err_out_iounmap;
 	}
 	card->id = card->interface.channels;
 
@@ -195,6 +199,19 @@ static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id
 	pci_set_drvdata(dev, card);
 
 	return 0;
+
+err_out_iounmap:
+	iounmap((void *)card->bar0);
+
+err_out_free_irq:
+	free_irq(card->irq, card);
+
+err_out_free_card:
+	kfree(card);
+
+err_out_disable_dev:
+	pci_disable_device(dev);
+	return err;
 }
 
 /*
@@ -202,7 +219,7 @@ static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id
  *
  * 	card: the board.
  */
-static void __devexit tpam_unregister_card(tpam_card *card) {
+static void __devexit tpam_unregister_card(struct pci_dev *pcidev, tpam_card *card) {
 	isdn_ctrl cmd;
 
 	/* prevent the ISDN link layer that the driver will be unloaded */
@@ -215,6 +232,8 @@ static void __devexit tpam_unregister_card(tpam_card *card) {
 
 	/* release mapped memory */
 	iounmap((void *)card->bar0);
+
+	pci_disable_device(pcidev);
 }
 
 /*
@@ -235,7 +254,7 @@ static void __devexit tpam_remove(struct pci_dev *pcidev) {
 	}
 	
 	/* unregister each board */
-	tpam_unregister_card(card);
+	tpam_unregister_card(pcidev, card);
 	
 	/* and free the board structure itself */
 	kfree(card);
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index c0ab8589b..d3b8f819e 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -74,15 +74,135 @@ static struct notifier_block adbhid_adb_notifier = {
 #define ADB_KEY_POWER_OLD	0x7e
 #define ADB_KEY_POWER		0x7f
 
-unsigned char adb_to_linux_keycodes[128] = {
-	 30, 31, 32, 33, 35, 34, 44, 45, 46, 47, 86, 48, 16, 17, 18, 19,
-	 21, 20,  2,  3,  4,  5,  7,  6, 13, 10,  8, 12,  9, 11, 27, 24,
-	 22, 26, 23, 25, 28, 38, 36, 40, 37, 39, 43, 51, 53, 49, 50, 52,
-	 15, 57, 41, 14, 96,  1, 29,125, 42, 58, 56,105,106,108,103,  0,
-	  0, 83,  0, 55,  0, 78,  0, 69,  0,  0,  0, 98, 96,  0, 74,  0,
-	  0,117, 82, 79, 80, 81, 75, 76, 77, 71,  0, 72, 73,124, 89,121,
-	 63, 64, 65, 61, 66, 67,123, 87,122, 99,  0, 70,  0, 68,101, 88,
-	  0,119,110,102,104,111, 62,107, 60,109, 59, 54,100, 97,126,116
+u8 adb_to_linux_keycodes[128] = {
+	/* 0x00 */ KEY_A, 		/*  30 */
+	/* 0x01 */ KEY_S, 		/*  31 */
+	/* 0x02 */ KEY_D,		/*  32 */
+	/* 0x03 */ KEY_F,		/*  33 */
+	/* 0x04 */ KEY_H,		/*  35 */
+	/* 0x05 */ KEY_G,		/*  34 */
+	/* 0x06 */ KEY_Z,		/*  44 */
+	/* 0x07 */ KEY_X,		/*  45 */
+	/* 0x08 */ KEY_C,		/*  46 */
+	/* 0x09 */ KEY_V,		/*  47 */
+	/* 0x0a */ KEY_102ND,		/*  86 */
+	/* 0x0b */ KEY_B,		/*  48 */
+	/* 0x0c */ KEY_Q,		/*  16 */
+	/* 0x0d */ KEY_W,		/*  17 */
+	/* 0x0e */ KEY_E,		/*  18 */
+	/* 0x0f */ KEY_R,		/*  19 */
+	/* 0x10 */ KEY_Y,		/*  21 */
+	/* 0x11 */ KEY_T,		/*  20 */
+	/* 0x12 */ KEY_1,		/*   2 */
+	/* 0x13 */ KEY_2,		/*   3 */
+	/* 0x14 */ KEY_3,		/*   4 */
+	/* 0x15 */ KEY_4,		/*   5 */
+	/* 0x16 */ KEY_6,		/*   7 */
+	/* 0x17 */ KEY_5,		/*   6 */
+	/* 0x18 */ KEY_EQUAL,		/*  13 */
+	/* 0x19 */ KEY_9,		/*  10 */
+	/* 0x1a */ KEY_7,		/*   8 */
+	/* 0x1b */ KEY_MINUS,		/*  12 */
+	/* 0x1c */ KEY_8,		/*   9 */
+	/* 0x1d */ KEY_0,		/*  11 */
+	/* 0x1e */ KEY_RIGHTBRACE,	/*  27 */
+	/* 0x1f */ KEY_O,		/*  24 */
+	/* 0x20 */ KEY_U,		/*  22 */
+	/* 0x21 */ KEY_LEFTBRACE,	/*  26 */
+	/* 0x22 */ KEY_I,		/*  23 */
+	/* 0x23 */ KEY_P,		/*  25 */
+	/* 0x24 */ KEY_ENTER,		/*  28 */
+	/* 0x25 */ KEY_L,		/*  38 */
+	/* 0x26 */ KEY_J,		/*  36 */
+	/* 0x27 */ KEY_APOSTROPHE,	/*  40 */
+	/* 0x28 */ KEY_K,		/*  37 */
+	/* 0x29 */ KEY_SEMICOLON,	/*  39 */
+	/* 0x2a */ KEY_BACKSLASH,	/*  43 */
+	/* 0x2b */ KEY_COMMA,		/*  51 */
+	/* 0x2c */ KEY_SLASH,		/*  53 */
+	/* 0x2d */ KEY_N,		/*  49 */
+	/* 0x2e */ KEY_M,		/*  50 */
+	/* 0x2f */ KEY_DOT,		/*  52 */
+	/* 0x30 */ KEY_TAB,		/*  15 */
+	/* 0x31 */ KEY_SPACE,		/*  57 */
+	/* 0x32 */ KEY_GRAVE,		/*  41 */
+	/* 0x33 */ KEY_BACKSPACE,	/*  14 */
+	/* 0x34 */ KEY_KPENTER,		/*  96 */
+	/* 0x35 */ KEY_ESC,		/*   1 */
+	/* 0x36 */ KEY_LEFTCTRL,	/*  29 */
+	/* 0x37 */ KEY_LEFTMETA,	/* 125 */
+	/* 0x38 */ KEY_LEFTSHIFT,	/*  42 */
+	/* 0x39 */ KEY_CAPSLOCK,	/*  58 */
+	/* 0x3a */ KEY_LEFTALT,		/*  56 */
+	/* 0x3b */ KEY_LEFT,		/* 105 */
+	/* 0x3c */ KEY_RIGHT,		/* 106 */
+	/* 0x3d */ KEY_DOWN,		/* 108 */
+	/* 0x3e */ KEY_UP,		/* 103 */
+	/* 0x3f */ 0,
+	/* 0x40 */ 0,
+	/* 0x41 */ KEY_KPDOT,		/*  83 */
+	/* 0x42 */ 0,
+	/* 0x43 */ KEY_KPASTERISK,	/*  55 */
+	/* 0x44 */ 0,
+	/* 0x45 */ KEY_KPPLUS,		/*  78 */
+	/* 0x46 */ 0,
+	/* 0x47 */ KEY_NUMLOCK,		/*  69 */
+	/* 0x48 */ 0,
+	/* 0x49 */ 0,
+	/* 0x4a */ 0,
+	/* 0x4b */ KEY_KPSLASH,		/*  98 */
+	/* 0x4c */ KEY_KPENTER,		/*  96 */
+	/* 0x4d */ 0,
+	/* 0x4e */ KEY_KPMINUS,		/*  74 */
+	/* 0x4f */ 0,
+	/* 0x50 */ 0,
+	/* 0x51 */ KEY_KPEQUAL,		/* 117 */
+	/* 0x52 */ KEY_KP0,		/*  82 */
+	/* 0x53 */ KEY_KP1,		/*  79 */
+	/* 0x54 */ KEY_KP2,		/*  80 */
+	/* 0x55 */ KEY_KP3,		/*  81 */
+	/* 0x56 */ KEY_KP4,		/*  75 */
+	/* 0x57 */ KEY_KP5,		/*  76 */
+	/* 0x58 */ KEY_KP6,		/*  77 */
+	/* 0x59 */ KEY_KP7,		/*  71 */
+	/* 0x5a */ 0,
+	/* 0x5b */ KEY_KP8,		/*  72 */
+	/* 0x5c */ KEY_KP9,		/*  73 */
+	/* 0x5d */ KEY_YEN,		/* 124 */
+	/* 0x5e */ KEY_RO,		/*  89 */
+	/* 0x5f */ KEY_KPCOMMA,		/* 121 */
+	/* 0x60 */ KEY_F5,		/*  63 */
+	/* 0x61 */ KEY_F6,		/*  64 */
+	/* 0x62 */ KEY_F7,		/*  65 */
+	/* 0x63 */ KEY_F3,		/*  61 */
+	/* 0x64 */ KEY_F8,		/*  66 */
+	/* 0x65 */ KEY_F9,		/*  67 */
+	/* 0x66 */ KEY_HANJA,		/* 123 */
+	/* 0x67 */ KEY_F11,		/*  87 */
+	/* 0x68 */ KEY_HANGUEL,		/* 122 */
+	/* 0x69 */ KEY_SYSRQ,		/*  99 */
+	/* 0x6a */ 0,
+	/* 0x6b */ KEY_SCROLLLOCK,	/*  70 */
+	/* 0x6c */ 0,
+	/* 0x6d */ KEY_F10,		/*  68 */
+	/* 0x6e */ KEY_COMPOSE,		/* 127 */
+	/* 0x6f */ KEY_F12,		/*  88 */
+	/* 0x70 */ 0,
+	/* 0x71 */ KEY_PAUSE,		/* 119 */
+	/* 0x72 */ KEY_INSERT,		/* 110 */
+	/* 0x73 */ KEY_HOME,		/* 102 */
+	/* 0x74 */ KEY_PAGEUP,		/* 104 */
+	/* 0x75 */ KEY_DELETE,		/* 111 */
+	/* 0x76 */ KEY_F4,		/*  62 */
+	/* 0x77 */ KEY_END,		/* 107 */
+	/* 0x78 */ KEY_F2,		/*  60 */
+	/* 0x79 */ KEY_PAGEDOWN,	/* 109 */
+	/* 0x7a */ KEY_F1,		/*  59 */
+	/* 0x7b */ KEY_RIGHTSHIFT,	/*  54 */
+	/* 0x7c */ KEY_RIGHTALT,	/* 100 */
+	/* 0x7d */ KEY_RIGHTCTRL,	/*  97 */
+	/* 0x7e */ KEY_RIGHTMETA,	/* 126 */
+	/* 0x7f */ KEY_POWER,		/* 116 */
 };
 
 struct adbhid {
@@ -326,7 +446,7 @@ adbhid_mouse_input(unsigned char *data, int nb, struct pt_regs *regs, int autopo
 	input_report_key(&adbhid[id]->input, BTN_LEFT,   !((data[1] >> 7) & 1));
 	input_report_key(&adbhid[id]->input, BTN_MIDDLE, !((data[2] >> 7) & 1));
 
-	if (nb >= 4)
+	if (nb >= 4 && adbhid[id]->mouse_kind != ADBMOUSE_TRACKPAD)
 		input_report_key(&adbhid[id]->input, BTN_RIGHT,  !((data[3] >> 7) & 1));
 
 	input_report_rel(&adbhid[id]->input, REL_X,
@@ -453,7 +573,7 @@ static spinlock_t leds_lock  = SPIN_LOCK_UNLOCKED;
 
 static void leds_done(struct adb_request *req)
 {
-	int leds, device;
+	int leds = 0, device = 0, pending = 0;
 	unsigned long flags;
 
 	spin_lock_irqsave(&leds_lock, flags);
@@ -464,11 +584,11 @@ static void leds_done(struct adb_request *req)
 		leds_pending[device] = 0;
 		pending_led_start++;
 		pending_led_start = (pending_led_start < 16) ? pending_led_start : 0;
+		pending = leds_req_pending;
 	} else
 		leds_req_pending = 0;
-
 	spin_unlock_irqrestore(&leds_lock, flags);
-	if (leds_req_pending)
+	if (pending)
 		adb_request(&led_request, leds_done, 0, 3,
 			    ADB_WRITEREG(device, KEYB_LEDREG), 0xff, ~leds);
 }
diff --git a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c
index 0e130f598..26bdcd7da 100644
--- a/drivers/macintosh/ans-lcd.c
+++ b/drivers/macintosh/ans-lcd.c
@@ -9,6 +9,8 @@
 #include <linux/fcntl.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/fs.h>
+
 #include <asm/uaccess.h>
 #include <asm/sections.h>
 #include <asm/prom.h>
@@ -154,7 +156,7 @@ anslcd_init(void)
 	retval = misc_register(&anslcd_dev);
 	if(retval < 0){
 		printk(KERN_INFO "LCD: misc_register failed\n");
-		iounmap(anslcd_ptr);
+		iounmap((void *)anslcd_ptr);
 		return retval;
 	}
 
@@ -177,7 +179,7 @@ static void __exit
 anslcd_exit(void)
 {
 	misc_deregister(&anslcd_dev);
-	iounmap(anslcd_ptr);
+	iounmap((void *)anslcd_ptr);
 }
 
 module_init(anslcd_init);
diff --git a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c
index 1d61a9af6..a3a5372f7 100644
--- a/drivers/macintosh/macserial.c
+++ b/drivers/macintosh/macserial.c
@@ -713,12 +713,8 @@ static void do_softint(void *private_)
 	if (!tty)
 		return;
 
-	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
-	}
+	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event))
+		tty_wakeup(tty);
 }
 
 static int startup(struct mac_serial * info)
@@ -1564,10 +1560,7 @@ static void rs_flush_buffer(struct tty_struct *tty)
 	spin_lock_irqsave(&info->lock, flags);
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 	spin_unlock_irqrestore(&info->lock, flags);
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /*
@@ -1994,16 +1987,14 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
 
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
 	tty->closing = 0;
 	info->event = 0;
 	info->tty = 0;
 
 	if (info->blocked_open) {
 		if (info->close_delay) {
-			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(info->close_delay);
+			msleep_interruptible(jiffies_to_msecs(info->close_delay));
 		}
 		wake_up_interruptible(&info->open_wait);
 	}
@@ -2048,8 +2039,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
 	if (timeout)
 		char_time = min_t(unsigned long, char_time, timeout);
 	while ((read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) {
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(char_time);
+		msleep_interruptible(jiffies_to_msecs(char_time));
 		if (signal_pending(current))
 			break;
 		if (timeout && time_after(jiffies, orig_jiffies + timeout))
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index 37f06c81d..8feba3846 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -28,6 +28,7 @@
 #include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/of_device.h>
+#include <linux/kthread.h>
 
 #undef DEBUG
 
@@ -53,7 +54,7 @@ MODULE_DESCRIPTION("Driver for ADT746x thermostat in iBook G4 and Powerbook G4 A
 MODULE_LICENSE("GPL");
 
 MODULE_PARM(limit_adjust,"i");
-MODULE_PARM_DESC(limit_adjust,"Adjust maximum temperatures (50°C cpu, 70°C gpu) by N °C.");
+MODULE_PARM_DESC(limit_adjust,"Adjust maximum temperatures (50 cpu, 70 gpu) by N degrees.");
 MODULE_PARM(fan_speed,"i");
 MODULE_PARM_DESC(fan_speed,"Specify fan speed (0-255) when lim < temp < lim+8 (default 128)");
 
@@ -70,9 +71,7 @@ static enum {ADT7460, ADT7467} therm_type;
 static int therm_bus, therm_address;
 static struct of_device * of_dev;
 static struct thermostat* thermostat;
-static pid_t monitor_thread_id;
-static int monitor_running;
-static struct completion monitor_task_compl;
+static struct task_struct *thread_therm = NULL;
 
 static int attach_one_thermostat(struct i2c_adapter *adapter, int addr, int busno);
 static void write_both_fan_speed(struct thermostat *th, int speed);
@@ -136,13 +135,12 @@ detach_thermostat(struct i2c_adapter *adapter)
 
 	th = thermostat;
 
-	if (monitor_running) {
-		monitor_running = 0;
-		wait_for_completion(&monitor_task_compl);
+	if (thread_therm != NULL) {
+		kthread_stop(thread_therm);
 	}
 		
 	printk(KERN_INFO "adt746x: Putting max temperatures back from %d, %d, %d,"
-		" to %d, %d, %d, (°C)\n", 
+		" to %d, %d, %d\n",
 		th->limits[0], th->limits[1], th->limits[2],
 		th->initial_limits[0], th->initial_limits[1], th->initial_limits[2]);
 	
@@ -178,7 +176,8 @@ static int read_fan_speed(struct thermostat *th, u8 addr)
 	tmp[0] = read_reg(th, addr + 1);
 	
 	res = tmp[1] + (tmp[0] << 8);
-	return (90000*60)/res;
+	/* "a value of 0xffff means that the fan has stopped" */
+	return (res == 0xffff ? 0 : (90000*60)/res);
 }
 
 static void write_both_fan_speed(struct thermostat *th, int speed)
@@ -237,16 +236,9 @@ static int monitor_task(void *arg)
 #ifdef DEBUG
 	int mfan_speed;
 #endif
-	
-	lock_kernel();
-	daemonize("kfand");
-	unlock_kernel();
-	strcpy(current->comm, "thermostat");
-	monitor_running = 1;
-
-	while(monitor_running)
+	while(!kthread_should_stop())
 	{
-		msleep(2000);
+		msleep_interruptible(2000);
 
 		/* Check status */
 		/* local   : chip */
@@ -270,14 +262,14 @@ static int monitor_task(void *arg)
 				int var = temps[i] - lims[i];
 				if (var > 8) {
 					if (th->overriding[fan_number] == 0)
-						printk(KERN_INFO "adt746x: Limit exceeded by %d°C, overriding specified fan speed for %s.\n",
+						printk(KERN_INFO "adt746x: Limit exceeded by %d, overriding specified fan speed for %s.\n",
 							var, fan_number?"GPU":"CPU");
 					th->overriding[fan_number] = 1;
 					write_fan_speed(th, 255, fan_number);
 					started = 1;
 				} else if ((!th->overriding[fan_number] || var < 6) && var > 0) {
 					if (th->overriding[fan_number] == 1)
-						printk(KERN_INFO "adt746x: Limit exceeded by %d°C, setting speed to specified for %s.\n",
+						printk(KERN_INFO "adt746x: Limit exceeded by %d, setting speed to specified for %s.\n",
 							var, fan_number?"GPU":"CPU");					
 					th->overriding[fan_number] = 0;
 					write_fan_speed(th, fan_speed, fan_number);
@@ -308,8 +300,8 @@ static int monitor_task(void *arg)
 		||  temps[1] != th->cached_temp[1]
 		||  temps[2] != th->cached_temp[2]) {
 			printk(KERN_INFO "adt746x: Temperature infos:"
-					 " thermostats: %d,%d,%d °C;"
-					 " limits: %d,%d,%d °C;"
+					 " thermostats: %d,%d,%d;"
+					 " limits: %d,%d,%d;"
 					 " fan speed: %d RPM\n",
 				temps[0], temps[1], temps[2],
 				lims[0],  lims[1],  lims[2],
@@ -321,7 +313,6 @@ static int monitor_task(void *arg)
 #endif		
 	}
 
-	complete_and_exit(&monitor_task_compl, 0);
 	return 0;
 }
 
@@ -380,14 +371,14 @@ attach_one_thermostat(struct i2c_adapter *adapter, int addr, int busno)
 	}
 	
 	printk(KERN_INFO "adt746x: Lowering max temperatures from %d, %d, %d"
-		" to %d, %d, %d (°C)\n", 
+		" to %d, %d, %d\n",
 		th->initial_limits[0], th->initial_limits[1], th->initial_limits[2], 
 		th->limits[0], th->limits[1], th->limits[2]);
 
 	thermostat = th;
 
 	if (i2c_attach_client(&th->clt)) {
-		printk("adt746x: Thermostat failed to attach client !\n");
+		printk(KERN_INFO "adt746x: Thermostat failed to attach client !\n");
 		thermostat = NULL;
 		kfree(th);
 		return -ENODEV;
@@ -403,10 +394,13 @@ attach_one_thermostat(struct i2c_adapter *adapter, int addr, int busno)
 		write_both_fan_speed(th, -1);
 	}
 	
-	init_completion(&monitor_task_compl);
-	
-	monitor_thread_id = kernel_thread(monitor_task, th,
-		SIGCHLD | CLONE_KERNEL);
+	thread_therm = kthread_run(monitor_task, th, "kfand");
+
+	if (thread_therm == ERR_PTR(-ENOMEM)) {
+		printk(KERN_INFO "adt746x: Kthread creation failed\n");
+		thread_therm = NULL;
+		return -ENOMEM;
+	}
 
 	return 0;
 }
@@ -417,17 +411,21 @@ attach_one_thermostat(struct i2c_adapter *adapter, int addr, int busno)
  * choice but implement a bunch of them...
  *
  */
-#define BUILD_SHOW_FUNC_DEG(name, data)				\
-static ssize_t show_##name(struct device *dev, char *buf)	\
-{								\
-	return sprintf(buf, "%d°C\n", data);			\
-}
 #define BUILD_SHOW_FUNC_INT(name, data)				\
 static ssize_t show_##name(struct device *dev, char *buf)	\
 {								\
 	return sprintf(buf, "%d\n", data);			\
 }
 
+#define BUILD_SHOW_FUNC_FAN(name, data)				\
+static ssize_t show_##name(struct device *dev, char *buf)       \
+{								\
+	return sprintf(buf, "%d (%d rpm)\n", 			\
+		thermostat->last_speed[data],			\
+		read_fan_speed(thermostat, FAN_SPEED[data])	\
+		);						\
+}
+
 #define BUILD_STORE_FUNC_DEG(name, data)			\
 static ssize_t store_##name(struct device *dev, const char *buf, size_t n) \
 {								\
@@ -448,19 +446,19 @@ static ssize_t store_##name(struct device *dev, const char *buf, size_t n) \
 	val = simple_strtoul(buf, NULL, 10);			\
 	if (val < 0 || val > 255)				\
 		return -EINVAL;					\
-	printk(KERN_INFO "Setting fan speed to %d\n", val);	\
+	printk(KERN_INFO "Setting specified fan speed to %d\n", val);	\
 	data = val;						\
 	return n;						\
 }
 
-BUILD_SHOW_FUNC_DEG(cpu_temperature,	 (read_reg(thermostat, TEMP_REG[1])))
-BUILD_SHOW_FUNC_DEG(gpu_temperature,	 (read_reg(thermostat, TEMP_REG[2])))
-BUILD_SHOW_FUNC_DEG(cpu_limit,		 thermostat->limits[1])
-BUILD_SHOW_FUNC_DEG(gpu_limit,		 thermostat->limits[2])
+BUILD_SHOW_FUNC_INT(cpu_temperature,	 (read_reg(thermostat, TEMP_REG[1])))
+BUILD_SHOW_FUNC_INT(gpu_temperature,	 (read_reg(thermostat, TEMP_REG[2])))
+BUILD_SHOW_FUNC_INT(cpu_limit,		 thermostat->limits[1])
+BUILD_SHOW_FUNC_INT(gpu_limit,		 thermostat->limits[2])
 
 BUILD_SHOW_FUNC_INT(specified_fan_speed, fan_speed)
-BUILD_SHOW_FUNC_INT(cpu_fan_speed,	 (read_fan_speed(thermostat, FAN_SPEED[0])))
-BUILD_SHOW_FUNC_INT(gpu_fan_speed,	 (read_fan_speed(thermostat, FAN_SPEED[1])))
+BUILD_SHOW_FUNC_FAN(cpu_fan_speed,	 0)
+BUILD_SHOW_FUNC_FAN(gpu_fan_speed,	 1)
 
 BUILD_STORE_FUNC_INT(specified_fan_speed,fan_speed)
 BUILD_SHOW_FUNC_INT(limit_adjust,	 limit_adjust)
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index f4a1777c6..7dbc5cb4d 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -292,8 +292,7 @@ control_loop( void *dummy )
 	while( x.running ) {
 		up( &x.lock );
 
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout( 8*HZ );
+		msleep_interruptible(8000);
 		
 		down( &x.lock );
 		poll_temp();
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 27e14a726..9f4147e3d 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -52,7 +52,6 @@
 #include <asm/system.h>
 #include <asm/sections.h>
 #include <asm/irq.h>
-#include <asm/hardirq.h>
 #include <asm/pmac_feature.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -138,7 +137,6 @@ static int data_len;
 static volatile int adb_int_pending;
 static volatile int disable_poll;
 static struct adb_request bright_req_1, bright_req_2;
-static unsigned long async_req_locks;
 static struct device_node *vias;
 static int pmu_kind = PMU_UNKNOWN;
 static int pmu_fully_inited = 0;
@@ -155,6 +153,7 @@ static int drop_interrupts;
 static int option_lid_wakeup = 1;
 static int sleep_in_progress;
 static int can_sleep;
+static unsigned long async_req_locks;
 #endif /* CONFIG_PMAC_PBOOK */
 static unsigned int pmu_irq_stats[11];
 
@@ -494,12 +493,9 @@ static int __init via_pmu_dev_init(void)
 	/* Create /proc/pmu */
 	proc_pmu_root = proc_mkdir("pmu", NULL);
 	if (proc_pmu_root) {
-		int i;
-		proc_pmu_info = create_proc_read_entry("info", 0, proc_pmu_root,
-					proc_get_info, NULL);
-		proc_pmu_irqstats = create_proc_read_entry("interrupts", 0, proc_pmu_root,
-					proc_get_irqstats, NULL);
 #ifdef CONFIG_PMAC_PBOOK
+		int i;
+
 		for (i=0; i<pmu_battery_count; i++) {
 			char title[16];
 			sprintf(title, "battery_%d", i);
@@ -507,6 +503,11 @@ static int __init via_pmu_dev_init(void)
 						proc_get_batt, (void *)i);
 		}
 #endif /* CONFIG_PMAC_PBOOK */
+
+		proc_pmu_info = create_proc_read_entry("info", 0, proc_pmu_root,
+					proc_get_info, NULL);
+		proc_pmu_irqstats = create_proc_read_entry("interrupts", 0, proc_pmu_root,
+					proc_get_irqstats, NULL);
 		proc_pmu_options = create_proc_entry("options", 0600, proc_pmu_root);
 		if (proc_pmu_options) {
 			proc_pmu_options->nlink = 1;
@@ -746,6 +747,8 @@ done_battery_state_smart(struct adb_request* req)
 		pmu_power_flags &= ~PMU_PWR_AC_PRESENT;
 
 
+	capa = max = amperage = voltage = 0;
+	
 	if (req->reply[1] & 0x04) {
 		bat_flags |= PMU_BATT_PRESENT;
 		switch(req->reply[0]) {
@@ -765,8 +768,7 @@ done_battery_state_smart(struct adb_request* req)
 					req->reply_len, req->reply[0], req->reply[1], req->reply[2], req->reply[3]);
 				break;
 		}
-	} else
-		capa = max = amperage = voltage = 0;
+	}
 
 	if ((req->reply[1] & 0x01) && (amperage > 0))
 		bat_flags |= PMU_BATT_CHARGING;
@@ -1445,7 +1447,7 @@ static struct adb_request* __pmac
 pmu_sr_intr(struct pt_regs *regs)
 {
 	struct adb_request *req;
-	int bite;
+	int bite = 0;
 
 	if (via[B] & TREQ) {
 		printk(KERN_ERR "PMU: spurious SR intr (%x)\n", via[B]);
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index 87261d37f..2bf58c928 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -85,6 +85,24 @@ config MD_RAID1
 
 	  If unsure, say Y.
 
+config MD_RAID10
+	tristate "RAID-10 (mirrored striping) mode (EXPERIMENTAL)"
+	depends on BLK_DEV_MD && EXPERIMENTAL
+	---help---
+	  RAID-10 provides a combination of striping (RAID-0) and
+	  mirroring (RAID-1) with easier configuration and more flexable
+	  layout.
+	  Unlike RAID-0, but like RAID-1, RAID-10 requires all devices to
+	  be the same size (or atleast, only as much as the smallest device
+	  will be used).
+	  RAID-10 provides a variety of layouts that provide different levels
+	  of redundancy and performance.
+
+	  RAID-10 requires mdadm-1.7.0 or later, available at:
+
+	  ftp://ftp.kernel.org/pub/linux/utils/raid/mdadm/
+
+
 config MD_RAID5
 	tristate "RAID-4/RAID-5 mode"
 	depends on BLK_DEV_MD
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index c8feb8346..e1b176505 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -10,7 +10,7 @@ raid6-objs	:= raid6main.o raid6algos.o raid6recov.o raid6tables.o \
 		   raid6int1.o raid6int2.o raid6int4.o \
 		   raid6int8.o raid6int16.o raid6int32.o \
 		   raid6mmx.o raid6sse1.o raid6sse2.o
-host-progs	:= mktables
+hostprogs-y	:= mktables
 
 # Note: link order is important.  All raid personalities
 # and xor.o must come before md.o, as they each initialise 
@@ -20,6 +20,7 @@ host-progs	:= mktables
 obj-$(CONFIG_MD_LINEAR)		+= linear.o
 obj-$(CONFIG_MD_RAID0)		+= raid0.o
 obj-$(CONFIG_MD_RAID1)		+= raid1.o
+obj-$(CONFIG_MD_RAID10)		+= raid10.o
 obj-$(CONFIG_MD_RAID5)		+= raid5.o xor.o
 obj-$(CONFIG_MD_RAID6)		+= raid6.o xor.o
 obj-$(CONFIG_MD_MULTIPATH)	+= multipath.o
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index 7a1c77dee..43a12285d 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -140,6 +140,13 @@ struct log_c {
 
 	int sync_search;
 
+	/* Resync flag */
+	enum sync {
+		DEFAULTSYNC,	/* Synchronize if necessary */
+		NOSYNC,		/* Devices known to be already in sync */
+		FORCESYNC,	/* Force a sync to happen */
+	} sync;
+
 	/*
 	 * Disk log fields
 	 */
@@ -205,7 +212,8 @@ static int read_header(struct log_c *log)
 
 	header_from_disk(&log->header, log->disk_header);
 
-	if (log->header.magic != MIRROR_MAGIC) {
+	/* New log required? */
+	if (log->sync != DEFAULTSYNC || log->header.magic != MIRROR_MAGIC) {
 		log->header.magic = MIRROR_MAGIC;
 		log->header.version = MIRROR_DISK_VERSION;
 		log->header.nr_regions = 0;
@@ -273,22 +281,38 @@ static int write_bits(struct log_c *log)
 }
 
 /*----------------------------------------------------------------
- * constructor/destructor
+ * core log constructor/destructor
+ *
+ * argv contains region_size followed optionally by [no]sync
  *--------------------------------------------------------------*/
 #define BYTE_SHIFT 3
 static int core_ctr(struct dirty_log *log, struct dm_target *ti,
 		    unsigned int argc, char **argv)
 {
+	enum sync sync = DEFAULTSYNC;
+
 	struct log_c *lc;
 	sector_t region_size;
 	unsigned int region_count;
 	size_t bitset_size;
 
-	if (argc != 1) {
-		DMWARN("wrong number of arguments to log_c");
+	if (argc < 1 || argc > 2) {
+		DMWARN("wrong number of arguments to mirror log");
 		return -EINVAL;
 	}
 
+	if (argc > 1) {
+		if (!strcmp(argv[1], "sync"))
+			sync = FORCESYNC;
+		else if (!strcmp(argv[1], "nosync"))
+			sync = NOSYNC;
+		else {
+			DMWARN("unrecognised sync argument to mirror log: %s",
+			       argv[1]);
+			return -EINVAL;
+		}
+	}
+
 	if (sscanf(argv[0], SECTOR_FORMAT, &region_size) != 1) {
 		DMWARN("invalid region size string");
 		return -EINVAL;
@@ -306,6 +330,7 @@ static int core_ctr(struct dirty_log *log, struct dm_target *ti,
 	lc->touched = 0;
 	lc->region_size = region_size;
 	lc->region_count = region_count;
+	lc->sync = sync;
 
 	/*
 	 * Work out how many words we need to hold the bitset.
@@ -330,8 +355,8 @@ static int core_ctr(struct dirty_log *log, struct dm_target *ti,
 		kfree(lc);
 		return -ENOMEM;
 	}
-	memset(lc->sync_bits, 0, bitset_size);
-        lc->sync_count = 0;
+	memset(lc->sync_bits, (sync == NOSYNC) ? -1 : 0, bitset_size);
+	lc->sync_count = (sync == NOSYNC) ? region_count : 0;
 
 	lc->recovering_bits = vmalloc(bitset_size);
 	if (!lc->recovering_bits) {
@@ -356,6 +381,11 @@ static void core_dtr(struct dirty_log *log)
 	kfree(lc);
 }
 
+/*----------------------------------------------------------------
+ * disk log constructor/destructor
+ *
+ * argv contains log_device region_size followed optionally by [no]sync
+ *--------------------------------------------------------------*/
 static int disk_ctr(struct dirty_log *log, struct dm_target *ti,
 		    unsigned int argc, char **argv)
 {
@@ -364,8 +394,8 @@ static int disk_ctr(struct dirty_log *log, struct dm_target *ti,
 	struct log_c *lc;
 	struct dm_dev *dev;
 
-	if (argc != 2) {
-		DMWARN("wrong number of arguments to log_d");
+	if (argc < 2 || argc > 3) {
+		DMWARN("wrong number of arguments to disk mirror log");
 		return -EINVAL;
 	}
 
@@ -452,10 +482,15 @@ static int disk_resume(struct dirty_log *log)
 	if (r)
 		return r;
 
-	/* zero any new bits if the mirror has grown */
-	for (i = lc->header.nr_regions; i < lc->region_count; i++)
-		/* FIXME: amazingly inefficient */
-		log_clear_bit(lc, lc->clean_bits, i);
+	/* set or clear any new bits */
+	if (lc->sync == NOSYNC)
+		for (i = lc->header.nr_regions; i < lc->region_count; i++)
+			/* FIXME: amazingly inefficient */
+			log_set_bit(lc, lc->clean_bits, i);
+	else
+		for (i = lc->header.nr_regions; i < lc->region_count; i++)
+			/* FIXME: amazingly inefficient */
+			log_clear_bit(lc, lc->clean_bits, i);
 
 	/* copy clean across to sync */
 	memcpy(lc->sync_bits, lc->clean_bits, size);
@@ -566,6 +601,51 @@ static region_t core_get_sync_count(struct dirty_log *log)
         return lc->sync_count;
 }
 
+#define	DMEMIT_SYNC \
+	if (lc->sync != DEFAULTSYNC) \
+		DMEMIT("%ssync ", lc->sync == NOSYNC ? "no" : "")
+
+static int core_status(struct dirty_log *log, status_type_t status,
+		       char *result, unsigned int maxlen)
+{
+	int sz = 0;
+	struct log_c *lc = log->context;
+
+	switch(status) {
+	case STATUSTYPE_INFO:
+		break;
+
+	case STATUSTYPE_TABLE:
+		DMEMIT("%s %u " SECTOR_FORMAT " ", log->type->name,
+		       lc->sync == DEFAULTSYNC ? 1 : 2, lc->region_size);
+		DMEMIT_SYNC;
+	}
+
+	return sz;
+}
+
+static int disk_status(struct dirty_log *log, status_type_t status,
+		       char *result, unsigned int maxlen)
+{
+	int sz = 0;
+	char buffer[16];
+	struct log_c *lc = log->context;
+
+	switch(status) {
+	case STATUSTYPE_INFO:
+		break;
+
+	case STATUSTYPE_TABLE:
+		format_dev_t(buffer, lc->log_dev->bdev->bd_dev);
+		DMEMIT("%s %u %s " SECTOR_FORMAT " ", log->type->name,
+		       lc->sync == DEFAULTSYNC ? 2 : 3, buffer,
+		       lc->region_size);
+		DMEMIT_SYNC;
+	}
+
+	return sz;
+}
+
 static struct dirty_log_type _core_type = {
 	.name = "core",
 	.module = THIS_MODULE,
@@ -579,7 +659,8 @@ static struct dirty_log_type _core_type = {
 	.clear_region = core_clear_region,
 	.get_resync_work = core_get_resync_work,
 	.complete_resync_work = core_complete_resync_work,
-        .get_sync_count = core_get_sync_count
+	.get_sync_count = core_get_sync_count,
+	.status = core_status,
 };
 
 static struct dirty_log_type _disk_type = {
@@ -597,7 +678,8 @@ static struct dirty_log_type _disk_type = {
 	.clear_region = core_clear_region,
 	.get_resync_work = core_get_resync_work,
 	.complete_resync_work = core_complete_resync_work,
-        .get_sync_count = core_get_sync_count
+	.get_sync_count = core_get_sync_count,
+	.status = disk_status,
 };
 
 int __init dm_dirty_log_init(void)
diff --git a/drivers/md/dm-log.h b/drivers/md/dm-log.h
index ced4ebacd..05ef594b5 100644
--- a/drivers/md/dm-log.h
+++ b/drivers/md/dm-log.h
@@ -101,6 +101,12 @@ struct dirty_log_type {
 	 * Returns the number of regions that are in sync.
          */
         region_t (*get_sync_count)(struct dirty_log *log);
+
+	/*
+	 * Support function for mirror status requests.
+	 */
+	int (*status)(struct dirty_log *log, status_type_t status_type,
+		      char *result, unsigned int maxlen);
 };
 
 int dm_register_dirty_log_type(struct dirty_log_type *type);
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 92792bb7d..abab26516 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -1009,8 +1009,8 @@ static struct dirty_log *create_dirty_log(struct dm_target *ti,
  * log_type #log_params <log_params>
  * #mirrors [mirror_path offset]{2,}
  *
- * For now, #log_params = 1, log_type = "core"
- *
+ * log_type is "core" or "disk"
+ * #log_params is between 1 and 3
  */
 #define DM_IO_PAGES 64
 static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
@@ -1182,35 +1182,30 @@ static int mirror_status(struct dm_target *ti, status_type_t type,
 			 char *result, unsigned int maxlen)
 {
 	char buffer[32];
-	unsigned int m, sz = 0;
+	unsigned int m, sz;
 	struct mirror_set *ms = (struct mirror_set *) ti->private;
 
-#define EMIT(x...) sz += ((sz >= maxlen) ? \
-			  0 : scnprintf(result + sz, maxlen - sz, x))
+	sz = ms->rh.log->type->status(ms->rh.log, type, result, maxlen);
 
 	switch (type) {
 	case STATUSTYPE_INFO:
-		EMIT("%d ", ms->nr_mirrors);
-
+		DMEMIT("%d ", ms->nr_mirrors);
 		for (m = 0; m < ms->nr_mirrors; m++) {
 			format_dev_t(buffer, ms->mirror[m].dev->bdev->bd_dev);
-			EMIT("%s ", buffer);
+			DMEMIT("%s ", buffer);
 		}
 
-		EMIT(SECTOR_FORMAT "/" SECTOR_FORMAT,
-		     ms->rh.log->type->get_sync_count(ms->rh.log),
-		     ms->nr_regions);
+		DMEMIT(SECTOR_FORMAT "/" SECTOR_FORMAT,
+		       ms->rh.log->type->get_sync_count(ms->rh.log),
+		       ms->nr_regions);
 		break;
 
 	case STATUSTYPE_TABLE:
-		EMIT("%s 1 " SECTOR_FORMAT " %d ",
-		     ms->rh.log->type->name, ms->rh.region_size,
-		     ms->nr_mirrors);
-
+		DMEMIT("%d ", ms->nr_mirrors);
 		for (m = 0; m < ms->nr_mirrors; m++) {
 			format_dev_t(buffer, ms->mirror[m].dev->bdev->bd_dev);
-			EMIT("%s " SECTOR_FORMAT " ",
-			     buffer, ms->mirror[m].offset);
+			DMEMIT("%s " SECTOR_FORMAT " ",
+			       buffer, ms->mirror[m].offset);
 		}
 	}
 
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index b5bacd717..6a3b9454c 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -191,20 +191,17 @@ static int stripe_status(struct dm_target *ti,
 	unsigned int i;
 	char buffer[32];
 
-#define EMIT(x...) sz += ((sz >= maxlen) ? \
-			  0 : scnprintf(result + sz, maxlen - sz, x))
-
 	switch (type) {
 	case STATUSTYPE_INFO:
 		result[0] = '\0';
 		break;
 
 	case STATUSTYPE_TABLE:
-		EMIT("%d " SECTOR_FORMAT, sc->stripes, sc->chunk_mask + 1);
+		DMEMIT("%d " SECTOR_FORMAT, sc->stripes, sc->chunk_mask + 1);
 		for (i = 0; i < sc->stripes; i++) {
 			format_dev_t(buffer, sc->stripe[i].dev->bdev->bd_dev);
-			EMIT(" %s " SECTOR_FORMAT, buffer,
-			     sc->stripe[i].physical_start);
+			DMEMIT(" %s " SECTOR_FORMAT, buffer,
+			       sc->stripe[i].physical_start);
 		}
 		break;
 	}
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index d189f8549..a6c24847d 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -825,7 +825,7 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q)
 	 * Make sure we obey the optimistic sub devices
 	 * restrictions.
 	 */
-	q->max_sectors = t->limits.max_sectors;
+	blk_queue_max_sectors(q, t->limits.max_sectors);
 	q->max_phys_segments = t->limits.max_phys_segments;
 	q->max_hw_segments = t->limits.max_hw_segments;
 	q->hardsect_size = t->limits.hardsect_size;
@@ -900,6 +900,28 @@ void dm_table_unplug_all(struct dm_table *t)
 	}
 }
 
+int dm_table_flush_all(struct dm_table *t)
+{
+	struct list_head *d, *devices = dm_table_get_devices(t);
+	int ret = 0;
+
+	for (d = devices->next; d != devices; d = d->next) {
+		struct dm_dev *dd = list_entry(d, struct dm_dev, list);
+		request_queue_t *q = bdev_get_queue(dd->bdev);
+		int err;
+
+		if (!q->issue_flush_fn)
+			err = -EOPNOTSUPP;
+		else
+			err = q->issue_flush_fn(q, dd->bdev->bd_disk, NULL);
+
+		if (!ret)
+			ret = err;
+	}
+
+	return ret;
+}
+
 EXPORT_SYMBOL(dm_vcalloc);
 EXPORT_SYMBOL(dm_get_device);
 EXPORT_SYMBOL(dm_put_device);
@@ -908,3 +930,4 @@ EXPORT_SYMBOL(dm_table_get_mode);
 EXPORT_SYMBOL(dm_table_put);
 EXPORT_SYMBOL(dm_table_get);
 EXPORT_SYMBOL(dm_table_unplug_all);
+EXPORT_SYMBOL(dm_table_flush_all);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 01794ed39..4d3c1d32a 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -15,15 +15,13 @@
 #include <linux/buffer_head.h>
 #include <linux/mempool.h>
 #include <linux/slab.h>
+#include <linux/idr.h>
 
 static const char *_name = DM_NAME;
 
 static unsigned int major = 0;
 static unsigned int _major = 0;
 
-static int realloc_minor_bits(unsigned long requested_minor);
-static void free_minor_bits(void);
-
 /*
  * One of these is allocated per bio.
  */
@@ -113,19 +111,11 @@ static int __init local_init(void)
 		return -ENOMEM;
 	}
 
-	r = realloc_minor_bits(1024);
-	if (r < 0) {
-		kmem_cache_destroy(_tio_cache);
-		kmem_cache_destroy(_io_cache);
-		return r;
-	}
-
 	_major = major;
 	r = register_blkdev(_major, _name);
 	if (r < 0) {
 		kmem_cache_destroy(_tio_cache);
 		kmem_cache_destroy(_io_cache);
-		free_minor_bits();
 		return r;
 	}
 
@@ -139,7 +129,6 @@ static void local_exit(void)
 {
 	kmem_cache_destroy(_tio_cache);
 	kmem_cache_destroy(_io_cache);
-	free_minor_bits();
 
 	if (unregister_blkdev(_major, _name) < 0)
 		DMERR("devfs_unregister_blkdev failed");
@@ -597,6 +586,21 @@ static int dm_request(request_queue_t *q, struct bio *bio)
 	return 0;
 }
 
+static int dm_flush_all(request_queue_t *q, struct gendisk *disk,
+			sector_t *error_sector)
+{
+	struct mapped_device *md = q->queuedata;
+	struct dm_table *map = dm_get_table(md);
+	int ret = -ENXIO;
+
+	if (map) {
+		ret = dm_table_flush_all(md->map);
+		dm_table_put(map);
+	}
+
+	return ret;
+}
+
 static void dm_unplug_all(request_queue_t *q)
 {
 	struct mapped_device *md = q->queuedata;
@@ -624,59 +628,15 @@ static int dm_any_congested(void *congested_data, int bdi_bits)
 }
 
 /*-----------------------------------------------------------------
- * A bitset is used to keep track of allocated minor numbers.
+ * An IDR is used to keep track of allocated minor numbers.
  *---------------------------------------------------------------*/
 static DECLARE_MUTEX(_minor_lock);
-static unsigned long *_minor_bits = NULL;
-static unsigned long _max_minors = 0;
-
-#define MINORS_SIZE(minors) ((minors / BITS_PER_LONG) * sizeof(unsigned long))
-
-static int realloc_minor_bits(unsigned long requested_minor)
-{
-	unsigned long max_minors;
-	unsigned long *minor_bits, *tmp;
-
-	if (requested_minor < _max_minors)
-		return -EINVAL;
-
-	/* Round up the requested minor to the next power-of-2. */
-	max_minors = 1 << fls(requested_minor - 1);
-	if (max_minors > (1 << MINORBITS))
-		return -EINVAL;
-
-	minor_bits = kmalloc(MINORS_SIZE(max_minors), GFP_KERNEL);
-	if (!minor_bits)
-		return -ENOMEM;
-	memset(minor_bits, 0, MINORS_SIZE(max_minors));
-
-	/* Copy the existing bit-set to the new one. */
-	if (_minor_bits)
-		memcpy(minor_bits, _minor_bits, MINORS_SIZE(_max_minors));
-
-	tmp = _minor_bits;
-	_minor_bits = minor_bits;
-	_max_minors = max_minors;
-	if (tmp)
-		kfree(tmp);
-
-	return 0;
-}
-
-static void free_minor_bits(void)
-{
-	down(&_minor_lock);
-	kfree(_minor_bits);
-	_minor_bits = NULL;
-	_max_minors = 0;
-	up(&_minor_lock);
-}
+static DEFINE_IDR(_minor_idr);
 
 static void free_minor(unsigned int minor)
 {
 	down(&_minor_lock);
-	if (minor < _max_minors)
-		clear_bit(minor, _minor_bits);
+	idr_remove(&_minor_idr, minor);
 	up(&_minor_lock);
 }
 
@@ -685,24 +645,37 @@ static void free_minor(unsigned int minor)
  */
 static int specific_minor(unsigned int minor)
 {
-	int r = 0;
+	int r, m;
 
-	if (minor > (1 << MINORBITS))
+	if (minor >= (1 << MINORBITS))
 		return -EINVAL;
 
 	down(&_minor_lock);
-	if (minor >= _max_minors) {
-		r = realloc_minor_bits(minor);
-		if (r) {
-			up(&_minor_lock);
-			return r;
-		}
+
+	if (idr_find(&_minor_idr, minor)) {
+		r = -EBUSY;
+		goto out;
+	}
+
+	r = idr_pre_get(&_minor_idr, GFP_KERNEL);
+	if (!r) {
+		r = -ENOMEM;
+		goto out;
+	}
+
+	r = idr_get_new_above(&_minor_idr, specific_minor, minor, &m);
+	if (r) {
+		goto out;
 	}
 
-	if (test_and_set_bit(minor, _minor_bits))
+	if (m != minor) {
+		idr_remove(&_minor_idr, m);
 		r = -EBUSY;
-	up(&_minor_lock);
+		goto out;
+	}
 
+out:
+	up(&_minor_lock);
 	return r;
 }
 
@@ -712,21 +685,29 @@ static int next_free_minor(unsigned int *minor)
 	unsigned int m;
 
 	down(&_minor_lock);
-	m = find_first_zero_bit(_minor_bits, _max_minors);
-	if (m >= _max_minors) {
-		r = realloc_minor_bits(_max_minors * 2);
-		if (r) {
-			up(&_minor_lock);
-			return r;
-		}
-		m = find_first_zero_bit(_minor_bits, _max_minors);
+
+	r = idr_pre_get(&_minor_idr, GFP_KERNEL);
+	if (!r) {
+		r = -ENOMEM;
+		goto out;
+	}
+
+	r = idr_get_new(&_minor_idr, next_free_minor, &m);
+	if (r) {
+		goto out;
+	}
+
+	if (m >= (1 << MINORBITS)) {
+		idr_remove(&_minor_idr, m);
+		r = -ENOSPC;
+		goto out;
 	}
 
-	set_bit(m, _minor_bits);
 	*minor = m;
-	up(&_minor_lock);
 
-	return 0;
+out:
+	up(&_minor_lock);
+	return r;
 }
 
 static struct block_device_operations dm_blk_dops;
@@ -764,6 +745,7 @@ static struct mapped_device *alloc_dev(unsigned int minor, int persistent)
 	md->queue->backing_dev_info.congested_data = md;
 	blk_queue_make_request(md->queue, dm_request);
 	md->queue->unplug_fn = dm_unplug_all;
+	md->queue->issue_flush_fn = dm_flush_all;
 
 	md->io_pool = mempool_create(MIN_IOS, mempool_alloc_slab,
 				     mempool_free_slab, _io_cache);
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index b4b915fbd..2daa03332 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -19,6 +19,9 @@
 #define DMERR(f, x...) printk(KERN_ERR DM_NAME ": " f "\n" , ## x)
 #define DMINFO(f, x...) printk(KERN_INFO DM_NAME ": " f "\n" , ## x)
 
+#define DMEMIT(x...) sz += ((sz >= maxlen) ? \
+			  0 : scnprintf(result + sz, maxlen - sz, x))
+
 /*
  * FIXME: I think this should be with the definition of sector_t
  * in types.h.
@@ -113,6 +116,7 @@ void dm_table_suspend_targets(struct dm_table *t);
 void dm_table_resume_targets(struct dm_table *t);
 int dm_table_any_congested(struct dm_table *t, int bdi_bits);
 void dm_table_unplug_all(struct dm_table *t);
+int dm_table_flush_all(struct dm_table *t);
 
 /*-----------------------------------------------------------------
  * A registry of target types.
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index e0aa017a2..0f57e5edd 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -47,7 +47,6 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
 		return hash->dev0;
 }
 
-
 /**
  *	linear_mergeable_bvec -- tell bio layer if a two requests can be merged
  *	@q: request queue
@@ -93,6 +92,27 @@ static void linear_unplug(request_queue_t *q)
 	}
 }
 
+static int linear_issue_flush(request_queue_t *q, struct gendisk *disk,
+			      sector_t *error_sector)
+{
+	mddev_t *mddev = q->queuedata;
+	linear_conf_t *conf = mddev_to_conf(mddev);
+	int i, ret = 0;
+
+	for (i=0; i < mddev->raid_disks; i++) {
+		struct block_device *bdev = conf->disks[i].rdev->bdev;
+		request_queue_t *r_queue = bdev_get_queue(bdev);
+
+		if (!r_queue->issue_flush_fn) {
+			ret = -EOPNOTSUPP;
+			break;
+		}
+		ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
+		if (ret)
+			break;
+	}
+	return ret;
+}
 
 static int linear_run (mddev_t *mddev)
 {
@@ -137,7 +157,7 @@ static int linear_run (mddev_t *mddev)
 		 */
 		if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
 		    mddev->queue->max_sectors > (PAGE_SIZE>>9))
-			mddev->queue->max_sectors = (PAGE_SIZE>>9);
+			blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
 		disk->size = rdev->size;
 		mddev->array_size += rdev->size;
@@ -200,6 +220,7 @@ static int linear_run (mddev_t *mddev)
 
 	blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec);
 	mddev->queue->unplug_fn = linear_unplug;
+	mddev->queue->issue_flush_fn = linear_issue_flush;
 	return 0;
 
 out:
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 77cd6e9f3..745f7e7bd 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -154,6 +154,39 @@ static spinlock_t all_mddevs_lock = SPIN_LOCK_UNLOCKED;
 		tmp = tmp->next;})					\
 		)
 
+int md_flush_mddev(mddev_t *mddev, sector_t *error_sector)
+{
+	struct list_head *tmp;
+	mdk_rdev_t *rdev;
+	int ret = 0;
+
+	/*
+	 * this list iteration is done without any locking in md?!
+	 */
+	ITERATE_RDEV(mddev, rdev, tmp) {
+		request_queue_t *r_queue = bdev_get_queue(rdev->bdev);
+		int err;
+
+		if (!r_queue->issue_flush_fn)
+			err = -EOPNOTSUPP;
+		else
+			err = r_queue->issue_flush_fn(r_queue, rdev->bdev->bd_disk, error_sector);
+
+		if (!ret)
+			ret = err;
+	}
+
+	return ret;
+}
+
+static int md_flush_all(request_queue_t *q, struct gendisk *disk,
+			 sector_t *error_sector)
+{
+	mddev_t *mddev = q->queuedata;
+
+	return md_flush_mddev(mddev, error_sector);
+}
+
 static int md_fail_request (request_queue_t *q, struct bio *bio)
 {
 	bio_io_error(bio, bio->bi_size);
@@ -373,7 +406,7 @@ static int read_disk_sb(mdk_rdev_t * rdev)
 	return 0;
 
 fail:
-	printk(KERN_ERR "md: disabled device %s, could not read superblock.\n",
+	printk(KERN_WARNING "md: disabled device %s, could not read superblock.\n",
 		bdevname(rdev->bdev,b));
 	return -EINVAL;
 }
@@ -439,6 +472,31 @@ static unsigned int calc_sb_csum(mdp_super_t * sb)
 	return csum;
 }
 
+/* csum_partial is not consistent between different architectures.
+ * Some (i386) do a 32bit csum.  Some (alpha) do 16 bit.
+ * This makes it hard for user-space to know what to do.
+ * So we use calc_sb_csum to set the checksum to allow working
+ * with older kernels, but allow calc_sb_csum_common to
+ * be used when checking if a checksum is correct, to
+ * make life easier for user-space tools that might write
+ * a superblock.
+ */
+static unsigned int calc_sb_csum_common(mdp_super_t *super)
+{
+	unsigned int  disk_csum = super->sb_csum;
+	unsigned long long newcsum = 0;
+	unsigned int csum;
+	int i;
+	unsigned int *superc = (int*) super;
+	super->sb_csum = 0;
+
+	for (i=0; i<MD_SB_BYTES/4; i++)
+		newcsum+= superc[i];
+	csum = (newcsum& 0xffffffff) + (newcsum>>32);
+	super->sb_csum = disk_csum;
+	return csum;
+}
+
 /*
  * Handle superblock details.
  * We want to be able to handle multiple superblock formats
@@ -521,7 +579,8 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
 	if (sb->raid_disks <= 0)
 		goto abort;
 
-	if (calc_sb_csum(sb) != sb->sb_csum) {
+	if (calc_sb_csum(sb) != sb->sb_csum &&
+		calc_sb_csum_common(sb) != sb->sb_csum) {
 		printk(KERN_WARNING "md: invalid superblock checksum on %s\n",
 			b);
 		goto abort;
@@ -745,11 +804,21 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
 static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb)
 {
 	unsigned int disk_csum, csum;
+	unsigned long long newcsum;
 	int size = 256 + sb->max_dev*2;
+	unsigned int *isuper = (unsigned int*)sb;
+	int i;
 
 	disk_csum = sb->sb_csum;
 	sb->sb_csum = 0;
-	csum = csum_partial((void *)sb, size, 0);
+	newcsum = 0;
+	for (i=0; size>=4; size -= 4 )
+		newcsum += le32_to_cpu(*isuper++);
+
+	if (size == 2)
+		newcsum += le16_to_cpu(*(unsigned short*) isuper);
+
+	csum = (newcsum & 0xffffffff) + (newcsum >> 32);
 	sb->sb_csum = disk_csum;
 	return csum;
 }
@@ -1042,20 +1111,24 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev)
 /*
  * prevent the device from being mounted, repartitioned or
  * otherwise reused by a RAID array (or any other kernel
- * subsystem), by opening the device. [simply getting an
- * inode is not enough, the SCSI module usage code needs
- * an explicit open() on the device]
+ * subsystem), by bd_claiming the device.
  */
 static int lock_rdev(mdk_rdev_t *rdev, dev_t dev)
 {
 	int err = 0;
 	struct block_device *bdev;
+	char b[BDEVNAME_SIZE];
 
 	bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE);
-	if (IS_ERR(bdev))
+	if (IS_ERR(bdev)) {
+		printk(KERN_ERR "md: could not open %s.\n",
+			__bdevname(dev, b));
 		return PTR_ERR(bdev);
+	}
 	err = bd_claim(bdev, rdev);
 	if (err) {
+		printk(KERN_ERR "md: could not bd_claim %s.\n",
+			bdevname(bdev, b));
 		blkdev_put(bdev);
 		return err;
 	}
@@ -1117,10 +1190,7 @@ static void export_array(mddev_t *mddev)
 
 static void print_desc(mdp_disk_t *desc)
 {
-	char b[BDEVNAME_SIZE];
-
-	printk(" DISK<N:%d,%s(%d,%d),R:%d,S:%d>\n", desc->number,
-		__bdevname(MKDEV(desc->major, desc->minor), b),
+	printk(" DISK<N:%d,(%d,%d),R:%d,S:%d>\n", desc->number,
 		desc->major,desc->minor,desc->raid_disk,desc->state);
 }
 
@@ -1312,8 +1382,7 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi
 
 	rdev = (mdk_rdev_t *) kmalloc(sizeof(*rdev), GFP_KERNEL);
 	if (!rdev) {
-		printk(KERN_ERR "md: could not alloc mem for %s!\n", 
-			__bdevname(newdev, b));
+		printk(KERN_ERR "md: could not alloc mem for new device!\n");
 		return ERR_PTR(-ENOMEM);
 	}
 	memset(rdev, 0, sizeof(*rdev));
@@ -1322,11 +1391,9 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi
 		goto abort_free;
 
 	err = lock_rdev(rdev, newdev);
-	if (err) {
-		printk(KERN_ERR "md: could not lock %s.\n",
-			__bdevname(newdev, b));
+	if (err)
 		goto abort_free;
-	}
+
 	rdev->desc_nr = -1;
 	rdev->faulty = 0;
 	rdev->in_sync = 0;
@@ -1615,6 +1682,8 @@ static int do_md_run(mddev_t * mddev)
 	mddev->pers = pers[pnum];
 	spin_unlock(&pers_lock);
 
+	mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */
+
 	err = mddev->pers->run(mddev);
 	if (err) {
 		printk(KERN_ERR "md: pers->run() failed ...\n");
@@ -1645,6 +1714,7 @@ static int do_md_run(mddev_t * mddev)
 	 */
 	mddev->queue->queuedata = mddev;
 	mddev->queue->make_request_fn = mddev->pers->make_request;
+	mddev->queue->issue_flush_fn = md_flush_all;
 
 	mddev->changed = 1;
 	return 0;
@@ -1881,11 +1951,9 @@ static int autostart_array(dev_t startdev)
 	mdk_rdev_t *start_rdev = NULL, *rdev;
 
 	start_rdev = md_import_device(startdev, 0, 0);
-	if (IS_ERR(start_rdev)) {
-		printk(KERN_WARNING "md: could not import %s!\n",
-			__bdevname(startdev, b));
+	if (IS_ERR(start_rdev))
 		return err;
-	}
+
 
 	/* NOTE: this can only work for 0.90.0 superblocks */
 	sb = (mdp_super_t*)page_address(start_rdev->sb_page);
@@ -1916,12 +1984,9 @@ static int autostart_array(dev_t startdev)
 		if (MAJOR(dev) != desc->major || MINOR(dev) != desc->minor)
 			continue;
 		rdev = md_import_device(dev, 0, 0);
-		if (IS_ERR(rdev)) {
-			printk(KERN_WARNING "md: could not import %s,"
-				" trying to run array nevertheless.\n",
-				__bdevname(dev, b));
+		if (IS_ERR(rdev))
 			continue;
-		}
+
 		list_add(&rdev->same_set, &pending_raid_disks);
 	}
 
@@ -2153,42 +2218,6 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
 	return 0;
 }
 
-static int hot_generate_error(mddev_t * mddev, dev_t dev)
-{
-	char b[BDEVNAME_SIZE];
-	struct request_queue *q;
-	mdk_rdev_t *rdev;
-
-	if (!mddev->pers)
-		return -ENODEV;
-
-	printk(KERN_INFO "md: trying to generate %s error in %s ... \n",
-		__bdevname(dev, b), mdname(mddev));
-
-	rdev = find_rdev(mddev, dev);
-	if (!rdev) {
-		/* MD_BUG(); */ /* like hell - it's not a driver bug */
-		return -ENXIO;
-	}
-
-	if (rdev->desc_nr == -1) {
-		MD_BUG();
-		return -EINVAL;
-	}
-	if (!rdev->in_sync)
-		return -ENODEV;
-
-	q = bdev_get_queue(rdev->bdev);
-	if (!q) {
-		MD_BUG();
-		return -ENODEV;
-	}
-	printk(KERN_INFO "md: okay, generating error!\n");
-//	q->oneshot_error = 1; // disabled for now
-
-	return 0;
-}
-
 static int hot_remove_disk(mddev_t * mddev, dev_t dev)
 {
 	char b[BDEVNAME_SIZE];
@@ -2197,9 +2226,6 @@ static int hot_remove_disk(mddev_t * mddev, dev_t dev)
 	if (!mddev->pers)
 		return -ENODEV;
 
-	printk(KERN_INFO "md: trying to remove %s from %s ... \n",
-		__bdevname(dev, b), mdname(mddev));
-
 	rdev = find_rdev(mddev, dev);
 	if (!rdev)
 		return -ENXIO;
@@ -2227,9 +2253,6 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
 	if (!mddev->pers)
 		return -ENODEV;
 
-	printk(KERN_INFO "md: trying to hot-add %s to %s ... \n",
-		__bdevname(dev, b), mdname(mddev));
-
 	if (mddev->major_version != 0) {
 		printk(KERN_WARNING "%s: HOT_ADD may only be used with"
 			" version-0 superblocks.\n",
@@ -2489,7 +2512,6 @@ static int set_disk_faulty(mddev_t *mddev, dev_t dev)
 static int md_ioctl(struct inode *inode, struct file *file,
 			unsigned int cmd, unsigned long arg)
 {
-	char b[BDEVNAME_SIZE];
 	int err = 0;
 	void __user *argp = (void __user *)arg;
 	struct hd_geometry __user *loc = argp;
@@ -2548,8 +2570,7 @@ static int md_ioctl(struct inode *inode, struct file *file,
 		}
 		err = autostart_array(new_decode_dev(arg));
 		if (err) {
-			printk(KERN_WARNING "md: autostart %s failed!\n",
-				__bdevname(arg, b));
+			printk(KERN_WARNING "md: autostart failed!\n");
 			goto abort;
 		}
 		goto done;
@@ -2690,9 +2711,7 @@ static int md_ioctl(struct inode *inode, struct file *file,
 				err = add_new_disk(mddev, &info);
 			goto done_unlock;
 		}
-		case HOT_GENERATE_ERROR:
-			err = hot_generate_error(mddev, new_decode_dev(arg));
-			goto done_unlock;
+
 		case HOT_REMOVE_DISK:
 			err = hot_remove_disk(mddev, new_decode_dev(arg));
 			goto done_unlock;
@@ -2876,7 +2895,7 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
 	return thread;
 }
 
-void md_interrupt_thread(mdk_thread_t *thread)
+static void md_interrupt_thread(mdk_thread_t *thread)
 {
 	if (!thread->tsk) {
 		MD_BUG();
@@ -2919,6 +2938,7 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
 	if (!mddev->pers->error_handler)
 		return;
 	mddev->pers->error_handler(mddev,rdev);
+	set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 	md_wakeup_thread(mddev->thread);
 }
@@ -2951,7 +2971,11 @@ static void status_resync(struct seq_file *seq, mddev_t * mddev)
 	unsigned long max_blocks, resync, res, dt, db, rt;
 
 	resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active))/2;
-	max_blocks = mddev->size;
+
+	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
+		max_blocks = mddev->resync_max_sectors >> 1;
+	else
+		max_blocks = mddev->size;
 
 	/*
 	 * Should not happen.
@@ -3187,11 +3211,6 @@ int unregister_md_personality(int pnum)
 	return 0;
 }
 
-void md_sync_acct(mdk_rdev_t *rdev, unsigned long nr_sectors)
-{
-	rdev->bdev->bd_contains->bd_disk->sync_io += nr_sectors;
-}
-
 static int is_mddev_idle(mddev_t *mddev)
 {
 	mdk_rdev_t * rdev;
@@ -3204,8 +3223,12 @@ static int is_mddev_idle(mddev_t *mddev)
 		struct gendisk *disk = rdev->bdev->bd_contains->bd_disk;
 		curr_events = disk_stat_read(disk, read_sectors) + 
 				disk_stat_read(disk, write_sectors) - 
-				disk->sync_io;
-		if ((curr_events - rdev->last_events) > 32) {
+				atomic_read(&disk->sync_io);
+		/* Allow some slack between valud of curr_events and last_events,
+		 * as there are some uninteresting races.
+		 * Note: the following is an unsigned comparison.
+		 */
+		if ((curr_events - rdev->last_events + 32) > 64) {
 			rdev->last_events = curr_events;
 			idle = 0;
 		}
@@ -3339,7 +3362,14 @@ static void md_do_sync(mddev_t *mddev)
 		}
 	} while (mddev->curr_resync < 2);
 
-	max_sectors = mddev->size << 1;
+	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
+		/* resync follows the size requested by the personality,
+		 * which default to physical size, but can be virtual size
+		 */
+		max_sectors = mddev->resync_max_sectors;
+	else
+		/* recovery follows the physical size of devices */
+		max_sectors = mddev->size << 1;
 
 	printk(KERN_INFO "md: syncing RAID array %s\n", mdname(mddev));
 	printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed:"
@@ -3697,7 +3727,6 @@ void md_autodetect_dev(dev_t dev)
 
 static void autostart_arrays(int part)
 {
-	char b[BDEVNAME_SIZE];
 	mdk_rdev_t *rdev;
 	int i;
 
@@ -3707,11 +3736,9 @@ static void autostart_arrays(int part)
 		dev_t dev = detected_devices[i];
 
 		rdev = md_import_device(dev,0, 0);
-		if (IS_ERR(rdev)) {
-			printk(KERN_ALERT "md: could not import %s!\n",
-				__bdevname(dev, b));
+		if (IS_ERR(rdev))
 			continue;
-		}
+
 		if (rdev->faulty) {
 			MD_BUG();
 			continue;
@@ -3762,7 +3789,6 @@ module_exit(md_exit)
 EXPORT_SYMBOL(register_md_personality);
 EXPORT_SYMBOL(unregister_md_personality);
 EXPORT_SYMBOL(md_error);
-EXPORT_SYMBOL(md_sync_acct);
 EXPORT_SYMBOL(md_done_sync);
 EXPORT_SYMBOL(md_write_start);
 EXPORT_SYMBOL(md_write_end);
@@ -3771,6 +3797,5 @@ EXPORT_SYMBOL(md_register_thread);
 EXPORT_SYMBOL(md_unregister_thread);
 EXPORT_SYMBOL(md_wakeup_thread);
 EXPORT_SYMBOL(md_print_devices);
-EXPORT_SYMBOL(md_interrupt_thread);
 EXPORT_SYMBOL(md_check_recovery);
 MODULE_LICENSE("GPL");
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index a9df710da..9d79b2aba 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -99,12 +99,12 @@ static void multipath_reschedule_retry (struct multipath_bh *mp_bh)
  * operation and are ready to return a success/failure code to the buffer
  * cache layer.
  */
-static void multipath_end_bh_io (struct multipath_bh *mp_bh, int uptodate)
+static void multipath_end_bh_io (struct multipath_bh *mp_bh, int err)
 {
 	struct bio *bio = mp_bh->master_bio;
 	multipath_conf_t *conf = mddev_to_conf(mp_bh->mddev);
 
-	bio_endio(bio, bio->bi_size, uptodate ? 0 : -EIO);
+	bio_endio(bio, bio->bi_size, err);
 	mempool_free(mp_bh, conf->pool);
 }
 
@@ -119,8 +119,8 @@ int multipath_end_request(struct bio *bio, unsigned int bytes_done, int error)
 		return 1;
 
 	if (uptodate)
-		multipath_end_bh_io(mp_bh, uptodate);
-	else if ((bio->bi_rw & (1 << BIO_RW_AHEAD)) == 0) {
+		multipath_end_bh_io(mp_bh, 0);
+	else if (!bio_rw_ahead(bio)) {
 		/*
 		 * oops, IO error:
 		 */
@@ -131,7 +131,7 @@ int multipath_end_request(struct bio *bio, unsigned int bytes_done, int error)
 		       (unsigned long long)bio->bi_sector);
 		multipath_reschedule_retry(mp_bh);
 	} else
-		multipath_end_bh_io(mp_bh, 0);
+		multipath_end_bh_io(mp_bh, error);
 	rdev_dec_pending(rdev, conf->mddev);
 	return 0;
 }
@@ -217,6 +217,31 @@ static void multipath_status (struct seq_file *seq, mddev_t *mddev)
 	seq_printf (seq, "]");
 }
 
+static int multipath_issue_flush(request_queue_t *q, struct gendisk *disk,
+				 sector_t *error_sector)
+{
+	mddev_t *mddev = q->queuedata;
+	multipath_conf_t *conf = mddev_to_conf(mddev);
+	int i, ret = 0;
+
+	for (i=0; i<mddev->raid_disks; i++) {
+		mdk_rdev_t *rdev = conf->multipaths[i].rdev;
+		if (rdev && !rdev->faulty) {
+			struct block_device *bdev = rdev->bdev;
+			request_queue_t *r_queue = bdev_get_queue(bdev);
+
+			if (!r_queue->issue_flush_fn) {
+				ret = -EOPNOTSUPP;
+				break;
+			}
+
+			ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
+			if (ret)
+				break;
+		}
+	}
+	return ret;
+}
 
 /*
  * Careful, this can execute in IRQ contexts as well!
@@ -300,7 +325,7 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
 		 */
 			if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
 			    mddev->queue->max_sectors > (PAGE_SIZE>>9))
-				mddev->queue->max_sectors = (PAGE_SIZE>>9);
+				blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
 			conf->working_disks++;
 			rdev->raid_disk = path;
@@ -377,7 +402,7 @@ static void multipathd (mddev_t *mddev)
 				" error for block %llu\n",
 				bdevname(bio->bi_bdev,b),
 				(unsigned long long)bio->bi_sector);
-			multipath_end_bh_io(mp_bh, 0);
+			multipath_end_bh_io(mp_bh, -EIO);
 		} else {
 			printk(KERN_ERR "multipath: %s: redirecting sector %llu"
 				" to another IO path\n",
@@ -435,6 +460,8 @@ static int multipath_run (mddev_t *mddev)
 
 	mddev->queue->unplug_fn = multipath_unplug;
 
+	mddev->queue->issue_flush_fn = multipath_issue_flush;
+
 	conf->working_disks = 0;
 	ITERATE_RDEV(mddev,rdev,tmp) {
 		disk_idx = rdev->raid_disk;
@@ -452,7 +479,7 @@ static int multipath_run (mddev_t *mddev)
 		 * a merge_bvec_fn to be involved in multipath */
 		if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
 		    mddev->queue->max_sectors > (PAGE_SIZE>>9))
-			mddev->queue->max_sectors = (PAGE_SIZE>>9);
+			blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
 		if (!rdev->faulty) 
 			conf->working_disks++;
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 5f4b8bfef..ae45ae92a 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -40,6 +40,31 @@ static void raid0_unplug(request_queue_t *q)
 	}
 }
 
+static int raid0_issue_flush(request_queue_t *q, struct gendisk *disk,
+			     sector_t *error_sector)
+{
+	mddev_t *mddev = q->queuedata;
+	raid0_conf_t *conf = mddev_to_conf(mddev);
+	mdk_rdev_t **devlist = conf->strip_zone[0].dev;
+	int i, ret = 0;
+
+	for (i=0; i<mddev->raid_disks; i++) {
+		struct block_device *bdev = devlist[i]->bdev;
+		request_queue_t *r_queue = bdev_get_queue(bdev);
+
+		if (!r_queue->issue_flush_fn) {
+			ret = -EOPNOTSUPP;
+			break;
+		}
+
+		ret =r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
+		if (ret)
+			break;
+	}
+	return ret;
+}
+
+
 static int create_strip_zones (mddev_t *mddev)
 {
 	int i, c, j;
@@ -137,7 +162,7 @@ static int create_strip_zones (mddev_t *mddev)
 
 		if (rdev1->bdev->bd_disk->queue->merge_bvec_fn &&
 		    mddev->queue->max_sectors > (PAGE_SIZE>>9))
-			mddev->queue->max_sectors = (PAGE_SIZE>>9);
+			blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
 		if (!smallest || (rdev1->size <smallest->size))
 			smallest = rdev1;
@@ -219,6 +244,8 @@ static int create_strip_zones (mddev_t *mddev)
 
 	mddev->queue->unplug_fn = raid0_unplug;
 
+	mddev->queue->issue_flush_fn = raid0_issue_flush;
+
 	printk("raid0: done.\n");
 	return 0;
  abort:
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 04b2aef4a..1ed82ea4b 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -24,10 +24,6 @@
 
 #include <linux/raid/raid1.h>
 
-#define MAJOR_NR MD_MAJOR
-#define MD_DRIVER
-#define MD_PERSONALITY
-
 /*
  * Number of guaranteed r1bios in case of extreme VM load:
  */
@@ -44,13 +40,12 @@ static void * r1bio_pool_alloc(int gfp_flags, void *data)
 {
 	struct pool_info *pi = data;
 	r1bio_t *r1_bio;
+	int size = offsetof(r1bio_t, bios[pi->raid_disks]);
 
 	/* allocate a r1bio with room for raid_disks entries in the bios array */
-	r1_bio = kmalloc(sizeof(r1bio_t) + sizeof(struct bio*)*pi->raid_disks,
-			 gfp_flags);
+	r1_bio = kmalloc(size, gfp_flags);
 	if (r1_bio)
-		memset(r1_bio, 0, sizeof(*r1_bio) +
-			       sizeof(struct bio*) * pi->raid_disks);
+		memset(r1_bio, 0, size);
 	else
 		unplug_slaves(pi->mddev);
 
@@ -104,7 +99,7 @@ static void * r1buf_pool_alloc(int gfp_flags, void *data)
 		bio->bi_io_vec[i].bv_page = page;
 	}
 
-	r1_bio->master_bio = bio;
+	r1_bio->master_bio = NULL;
 
 	return r1_bio;
 
@@ -189,32 +184,6 @@ static inline void put_buf(r1bio_t *r1_bio)
 	spin_unlock_irqrestore(&conf->resync_lock, flags);
 }
 
-static int map(mddev_t *mddev, mdk_rdev_t **rdevp)
-{
-	conf_t *conf = mddev_to_conf(mddev);
-	int i, disks = conf->raid_disks;
-
-	/*
-	 * Later we do read balancing on the read side
-	 * now we use the first available disk.
-	 */
-
-	spin_lock_irq(&conf->device_lock);
-	for (i = 0; i < disks; i++) {
-		mdk_rdev_t *rdev = conf->mirrors[i].rdev;
-		if (rdev && rdev->in_sync) {
-			*rdevp = rdev;
-			atomic_inc(&rdev->nr_pending);
-			spin_unlock_irq(&conf->device_lock);
-			return i;
-		}
-	}
-	spin_unlock_irq(&conf->device_lock);
-
-	printk(KERN_ERR "raid1_map(): huh, no more operational devices?\n");
-	return -1;
-}
-
 static void reschedule_retry(r1bio_t *r1_bio)
 {
 	unsigned long flags;
@@ -292,8 +261,9 @@ static int raid1_end_read_request(struct bio *bio, unsigned int bytes_done, int
 		 * oops, read error:
 		 */
 		char b[BDEVNAME_SIZE];
-		printk(KERN_ERR "raid1: %s: rescheduling sector %llu\n",
-		       bdevname(conf->mirrors[mirror].rdev->bdev,b), (unsigned long long)r1_bio->sector);
+		if (printk_ratelimit())
+			printk(KERN_ERR "raid1: %s: rescheduling sector %llu\n",
+			       bdevname(conf->mirrors[mirror].rdev->bdev,b), (unsigned long long)r1_bio->sector);
 		reschedule_retry(r1_bio);
 	}
 
@@ -363,11 +333,11 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
  *
  * The rdev for the device selected will have nr_pending incremented.
  */
-static int read_balance(conf_t *conf, struct bio *bio, r1bio_t *r1_bio)
+static int read_balance(conf_t *conf, r1bio_t *r1_bio)
 {
 	const unsigned long this_sector = r1_bio->sector;
 	int new_disk = conf->last_used, disk = new_disk;
-	const int sectors = bio->bi_size >> 9;
+	const int sectors = r1_bio->sectors;
 	sector_t new_distance, current_distance;
 
 	spin_lock_irq(&conf->device_lock);
@@ -378,14 +348,14 @@ static int read_balance(conf_t *conf, struct bio *bio, r1bio_t *r1_bio)
 	 */
 	if (conf->mddev->recovery_cp < MaxSector &&
 	    (this_sector + sectors >= conf->next_resync)) {
-		/* make sure that disk is operational */
+		/* Choose the first operation device, for consistancy */
 		new_disk = 0;
 
 		while (!conf->mirrors[new_disk].rdev ||
 		       !conf->mirrors[new_disk].rdev->in_sync) {
 			new_disk++;
 			if (new_disk == conf->raid_disks) {
-				new_disk = 0;
+				new_disk = -1;
 				break;
 			}
 		}
@@ -400,7 +370,7 @@ static int read_balance(conf_t *conf, struct bio *bio, r1bio_t *r1_bio)
 			new_disk = conf->raid_disks;
 		new_disk--;
 		if (new_disk == disk) {
-			new_disk = conf->last_used;
+			new_disk = -1;
 			goto rb_out;
 		}
 	}
@@ -440,13 +410,13 @@ static int read_balance(conf_t *conf, struct bio *bio, r1bio_t *r1_bio)
 	} while (disk != conf->last_used);
 
 rb_out:
-	r1_bio->read_disk = new_disk;
-	conf->next_seq_sect = this_sector + sectors;
 
-	conf->last_used = new_disk;
 
-	if (conf->mirrors[new_disk].rdev)
+	if (new_disk >= 0) {
+		conf->next_seq_sect = this_sector + sectors;
+		conf->last_used = new_disk;
 		atomic_inc(&conf->mirrors[new_disk].rdev->nr_pending);
+	}
 	spin_unlock_irq(&conf->device_lock);
 
 	return new_disk;
@@ -481,6 +451,32 @@ static void raid1_unplug(request_queue_t *q)
 	unplug_slaves(q->queuedata);
 }
 
+static int raid1_issue_flush(request_queue_t *q, struct gendisk *disk,
+			     sector_t *error_sector)
+{
+	mddev_t *mddev = q->queuedata;
+	conf_t *conf = mddev_to_conf(mddev);
+	unsigned long flags;
+	int i, ret = 0;
+
+	spin_lock_irqsave(&conf->device_lock, flags);
+	for (i=0; i<mddev->raid_disks; i++) {
+		mdk_rdev_t *rdev = conf->mirrors[i].rdev;
+		if (rdev && !rdev->faulty) {
+			struct block_device *bdev = rdev->bdev;
+			request_queue_t *r_queue = bdev_get_queue(bdev);
+
+			if (r_queue->issue_flush_fn) {
+				ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
+				if (ret)
+					break;
+			}
+		}
+	}
+	spin_unlock_irqrestore(&conf->device_lock, flags);
+	return ret;
+}
+
 /*
  * Throttle resync depth, so that we can both get proper overlapping of
  * requests, but are still able to handle normal requests quickly.
@@ -545,15 +541,26 @@ static int make_request(request_queue_t *q, struct bio * bio)
 	r1_bio->mddev = mddev;
 	r1_bio->sector = bio->bi_sector;
 
+	r1_bio->state = 0;
+
 	if (bio_data_dir(bio) == READ) {
 		/*
 		 * read balancing logic:
 		 */
-		mirror = conf->mirrors + read_balance(conf, bio, r1_bio);
+		int rdisk = read_balance(conf, r1_bio);
+
+		if (rdisk < 0) {
+			/* couldn't find anywhere to read from */
+			raid_end_bio_io(r1_bio);
+			return 0;
+		}
+		mirror = conf->mirrors + rdisk;
+
+		r1_bio->read_disk = rdisk;
 
 		read_bio = bio_clone(bio, GFP_NOIO);
 
-		r1_bio->bios[r1_bio->read_disk] = read_bio;
+		r1_bio->bios[rdisk] = read_bio;
 
 		read_bio->bi_sector = r1_bio->sector + mirror->rdev->data_offset;
 		read_bio->bi_bdev = mirror->rdev->bdev;
@@ -746,7 +753,7 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
 			 */
 			if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
 			    mddev->queue->max_sectors > (PAGE_SIZE>>9))
-				mddev->queue->max_sectors = (PAGE_SIZE>>9);
+				blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
 			p->head_position = 0;
 			rdev->raid_disk = mirror;
@@ -877,7 +884,7 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
 
 		atomic_inc(&conf->mirrors[i].rdev->nr_pending);
 		atomic_inc(&r1_bio->remaining);
-		md_sync_acct(conf->mirrors[i].rdev, wbio->bi_size >> 9);
+		md_sync_acct(conf->mirrors[i].rdev->bdev, wbio->bi_size >> 9);
 		generic_make_request(wbio);
 	}
 
@@ -925,7 +932,7 @@ static void raid1d(mddev_t *mddev)
 		} else {
 			int disk;
 			bio = r1_bio->bios[r1_bio->read_disk];
-			if ((disk=map(mddev, &rdev)) == -1) {
+			if ((disk=read_balance(conf, r1_bio)) == -1) {
 				printk(KERN_ALERT "raid1: %s: unrecoverable I/O"
 				       " read error for block %llu\n",
 				       bdevname(bio->bi_bdev,b),
@@ -935,10 +942,12 @@ static void raid1d(mddev_t *mddev)
 				r1_bio->bios[r1_bio->read_disk] = NULL;
 				r1_bio->read_disk = disk;
 				r1_bio->bios[r1_bio->read_disk] = bio;
-				printk(KERN_ERR "raid1: %s: redirecting sector %llu to"
-				       " another mirror\n",
-				       bdevname(rdev->bdev,b),
-				       (unsigned long long)r1_bio->sector);
+				rdev = conf->mirrors[disk].rdev;
+				if (printk_ratelimit())
+					printk(KERN_ERR "raid1: %s: redirecting sector %llu to"
+					       " another mirror\n",
+					       bdevname(rdev->bdev,b),
+					       (unsigned long long)r1_bio->sector);
 				bio->bi_bdev = rdev->bdev;
 				bio->bi_sector = r1_bio->sector + rdev->data_offset;
 				bio->bi_rw = READ;
@@ -1117,7 +1126,7 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
 	bio = r1_bio->bios[disk];
 	r1_bio->sectors = nr_sectors;
 
-	md_sync_acct(mirror->rdev, nr_sectors);
+	md_sync_acct(mirror->rdev->bdev, nr_sectors);
 
 	generic_make_request(bio);
 
@@ -1168,6 +1177,7 @@ static int run(mddev_t *mddev)
 
 	mddev->queue->unplug_fn = raid1_unplug;
 
+	mddev->queue->issue_flush_fn = raid1_issue_flush;
 
 	ITERATE_RDEV(mddev, rdev, tmp) {
 		disk_idx = rdev->raid_disk;
@@ -1186,7 +1196,7 @@ static int run(mddev_t *mddev)
 		 */
 		if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
 		    mddev->queue->max_sectors > (PAGE_SIZE>>9))
-			mddev->queue->max_sectors = (PAGE_SIZE>>9);
+			blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
 		disk->head_position = 0;
 		if (!rdev->faulty && rdev->in_sync)
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index b28f29005..d1f54a9ad 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -477,8 +477,8 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
 
 	if (!rdev->faulty) {
 		mddev->sb_dirty = 1;
-		conf->working_disks--;
 		if (rdev->in_sync) {
+			conf->working_disks--;
 			mddev->degraded++;
 			conf->failed_disks++;
 			rdev->in_sync = 0;
@@ -1071,7 +1071,8 @@ static void handle_stripe(struct stripe_head *sh)
 					PRINTK("Reading block %d (sync=%d)\n", 
 						i, syncing);
 					if (syncing)
-						md_sync_acct(conf->disks[i].rdev, STRIPE_SECTORS);
+						md_sync_acct(conf->disks[i].rdev->bdev,
+							     STRIPE_SECTORS);
 				}
 			}
 		}
@@ -1256,7 +1257,7 @@ static void handle_stripe(struct stripe_head *sh)
  
 		if (rdev) {
 			if (test_bit(R5_Syncio, &sh->dev[i].flags))
-				md_sync_acct(rdev, STRIPE_SECTORS);
+				md_sync_acct(rdev->bdev, STRIPE_SECTORS);
 
 			bi->bi_bdev = rdev->bdev;
 			PRINTK("for %llu schedule op %ld on disc %d\n",
@@ -1339,6 +1340,39 @@ static void raid5_unplug_device(request_queue_t *q)
 	unplug_slaves(mddev);
 }
 
+static int raid5_issue_flush(request_queue_t *q, struct gendisk *disk,
+			     sector_t *error_sector)
+{
+	mddev_t *mddev = q->queuedata;
+	raid5_conf_t *conf = mddev_to_conf(mddev);
+	int i, ret = 0;
+
+	for (i=0; i<mddev->raid_disks; i++) {
+		mdk_rdev_t *rdev = conf->disks[i].rdev;
+		if (rdev && !rdev->faulty) {
+			struct block_device *bdev = rdev->bdev;
+			request_queue_t *r_queue;
+
+			if (!bdev)
+				continue;
+
+			r_queue = bdev_get_queue(bdev);
+			if (!r_queue)
+				continue;
+
+			if (!r_queue->issue_flush_fn) {
+				ret = -EOPNOTSUPP;
+				break;
+			}
+
+			ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
+			if (ret)
+				break;
+		}
+	}
+	return ret;
+}
+
 static inline void raid5_plug_device(raid5_conf_t *conf)
 {
 	spin_lock_irq(&conf->device_lock);
@@ -1545,6 +1579,7 @@ static int run (mddev_t *mddev)
 	atomic_set(&conf->preread_active_stripes, 0);
 
 	mddev->queue->unplug_fn = raid5_unplug_device;
+	mddev->queue->issue_flush_fn = raid5_issue_flush;
 
 	PRINTK("raid5: run(%s) called.\n", mdname(mddev));
 
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index 1ad99be9c..aea1a1be5 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -498,8 +498,8 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
 
 	if (!rdev->faulty) {
 		mddev->sb_dirty = 1;
-		conf->working_disks--;
 		if (rdev->in_sync) {
+			conf->working_disks--;
 			mddev->degraded++;
 			conf->failed_disks++;
 			rdev->in_sync = 0;
@@ -1208,7 +1208,8 @@ static void handle_stripe(struct stripe_head *sh)
 					PRINTK("Reading block %d (sync=%d)\n",
 						i, syncing);
 					if (syncing)
-						md_sync_acct(conf->disks[i].rdev, STRIPE_SECTORS);
+						md_sync_acct(conf->disks[i].rdev->bdev,
+							     STRIPE_SECTORS);
 				}
 			}
 		}
@@ -1418,7 +1419,7 @@ static void handle_stripe(struct stripe_head *sh)
 
 		if (rdev) {
 			if (test_bit(R5_Syncio, &sh->dev[i].flags))
-				md_sync_acct(rdev, STRIPE_SECTORS);
+				md_sync_acct(rdev->bdev, STRIPE_SECTORS);
 
 			bi->bi_bdev = rdev->bdev;
 			PRINTK("for %llu schedule op %ld on disc %d\n",
@@ -1501,6 +1502,39 @@ static void raid6_unplug_device(request_queue_t *q)
 	unplug_slaves(mddev);
 }
 
+static int raid6_issue_flush(request_queue_t *q, struct gendisk *disk,
+			     sector_t *error_sector)
+{
+	mddev_t *mddev = q->queuedata;
+	raid6_conf_t *conf = mddev_to_conf(mddev);
+	int i, ret = 0;
+
+	for (i=0; i<mddev->raid_disks; i++) {
+		mdk_rdev_t *rdev = conf->disks[i].rdev;
+		if (rdev && !rdev->faulty) {
+			struct block_device *bdev = rdev->bdev;
+			request_queue_t *r_queue;
+
+			if (!bdev)
+				continue;
+
+			r_queue = bdev_get_queue(bdev);
+			if (!r_queue)
+				continue;
+
+			if (!r_queue->issue_flush_fn) {
+				ret = -EOPNOTSUPP;
+				break;
+			}
+
+			ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
+			if (ret)
+				break;
+		}
+	}
+	return ret;
+}
+
 static inline void raid6_plug_device(raid6_conf_t *conf)
 {
 	spin_lock_irq(&conf->device_lock);
@@ -1708,6 +1742,7 @@ static int run (mddev_t *mddev)
 	atomic_set(&conf->preread_active_stripes, 0);
 
 	mddev->queue->unplug_fn = raid6_unplug_device;
+	mddev->queue->issue_flush_fn = raid6_issue_flush;
 
 	PRINTK("raid6: run(%s) called.\n", mdname(mddev));
 
diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c
index 18bc5b671..118cace19 100644
--- a/drivers/media/common/saa7146_i2c.c
+++ b/drivers/media/common/saa7146_i2c.c
@@ -1,13 +1,6 @@
 #include <linux/version.h>
 #include <media/saa7146_vv.h>
 
-/* helper function */
-static void my_wait(struct saa7146_dev *dev, long ms)
-{
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout((((ms+10)/10)*HZ)/1000);
-}
-
 u32 saa7146_i2c_func(struct i2c_adapter *adapter)
 {
 //fm	DEB_I2C(("'%s'.\n", adapter->name));
@@ -136,12 +129,12 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev)
 		/* set "ABORT-OPERATION"-bit (bit 7)*/
 		saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07));
 		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
-		my_wait(dev,SAA7146_I2C_DELAY);
+		msleep(SAA7146_I2C_DELAY);
 
 		/* clear all error-bits pending; this is needed because p.123, note 1 */
 		saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
 		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
-		my_wait(dev,SAA7146_I2C_DELAY);
+		msleep(SAA7146_I2C_DELAY);
  	}
 
 	/* check if any error is (still) present. (this can be necessary because p.123, note 1) */
@@ -155,18 +148,18 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev)
 		   after serious protocol errors caused by e.g. the SAA7740 */
 		saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07));
 		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
-		my_wait(dev,SAA7146_I2C_DELAY);
+		msleep(SAA7146_I2C_DELAY);
 
 		/* clear all error-bits pending */
 		saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
 		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
-		my_wait(dev,SAA7146_I2C_DELAY);
+		msleep(SAA7146_I2C_DELAY);
 
 		/* the data sheet says it might be necessary to clear the status
 		   twice after an abort */
 		saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
 		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
-		my_wait(dev,SAA7146_I2C_DELAY);
+		msleep(SAA7146_I2C_DELAY);
      	}
 
 	/* if any error is still present, a fatal error has occured ... */
@@ -243,7 +236,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
 			if ((++trial < 20) && short_delay)
 				udelay(10);
 			else
-			my_wait(dev,1);
+			msleep(1);
 		}
 	}
 
@@ -345,7 +338,7 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg msgs[], i
 		}
 	        
 	        /* delay a bit before retrying */
-	        my_wait(dev, 10);
+	        msleep(10);
 		
 	} while (err != num && retries--);
 
diff --git a/drivers/media/dvb/b2c2/skystar2.c b/drivers/media/dvb/b2c2/skystar2.c
index 940f6a862..0a8d61c49 100644
--- a/drivers/media/dvb/b2c2/skystar2.c
+++ b/drivers/media/dvb/b2c2/skystar2.c
@@ -2345,7 +2345,7 @@ static struct pci_device_id skystar2_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, skystar2_pci_tbl);
 
 static struct pci_driver skystar2_pci_driver = {
-	.name = "Technisat SkyStar2 driver",
+	.name = "SkyStar2",
 	.id_table = skystar2_pci_tbl,
 	.probe = skystar2_probe,
 	.remove = skystar2_remove,
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c
index 1619f4c3f..7f7ec3314 100644
--- a/drivers/media/dvb/bt8xx/bt878.c
+++ b/drivers/media/dvb/bt8xx/bt878.c
@@ -417,6 +417,8 @@ static int __devinit bt878_probe(struct pci_dev *dev,
 
 	printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n",
 	       bt878_num);
+	if (pci_enable_device(dev))
+		return -EIO;
 
 	bt = &bt878[bt878_num];
 	bt->dev = dev;
@@ -426,11 +428,10 @@ static int __devinit bt878_probe(struct pci_dev *dev,
 	bt->id = dev->device;
 	bt->irq = dev->irq;
 	bt->bt878_adr = pci_resource_start(dev, 0);
-	if (pci_enable_device(dev))
-		return -EIO;
 	if (!request_mem_region(pci_resource_start(dev, 0),
 				pci_resource_len(dev, 0), "bt878")) {
-		return -EBUSY;
+		result = -EBUSY;
+		goto fail0;
 	}
 
 	pci_read_config_byte(dev, PCI_CLASS_REVISION, &bt->revision);
@@ -501,6 +502,8 @@ static int __devinit bt878_probe(struct pci_dev *dev,
       fail1:
 	release_mem_region(pci_resource_start(bt->dev, 0),
 			   pci_resource_len(bt->dev, 0));
+      fail0:
+	pci_disable_device(dev);
 	return result;
 }
 
@@ -517,7 +520,7 @@ static void __devexit bt878_remove(struct pci_dev *pci_dev)
 
 	/* first disable interrupts before unmapping the memory! */
 	btwrite(0, BT878_AINT_MASK);
-	btwrite(~0x0UL, BT878_AINT_STAT);
+	btwrite(~0U, BT878_AINT_STAT);
 
 	/* disable PCI bus-mastering */
 	pci_read_config_byte(bt->dev, PCI_COMMAND, &command);
@@ -540,6 +543,7 @@ static void __devexit bt878_remove(struct pci_dev *pci_dev)
 	bt878_mem_free(bt);
 
 	pci_set_drvdata(pci_dev, NULL);
+	pci_disable_device(pci_dev);
 	return;
 }
 
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index a4c3794a1..e3af0c025 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -1196,7 +1196,7 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file, const char __user *buf
         int status;
         char fragbuf[HOST_LINK_BUF_SIZE];
         int fragpos = 0;
-        int fraglen;
+        size_t fraglen;
         unsigned long timeout;
         int written;
 
@@ -1257,7 +1257,7 @@ static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private* ca, int* resu
         int slot;
         int slot_count = 0;
         int idx;
-        int fraglen;
+        size_t fraglen;
         int connection_id = -1;
         int found = 0;
         u8 hdr[2];
@@ -1484,21 +1484,20 @@ static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table *wait)
 
 
 static struct file_operations dvb_ca_fops = {
-        owner: THIS_MODULE,
-        read: dvb_ca_en50221_io_read,
-        write: dvb_ca_en50221_io_write,
-        ioctl: dvb_ca_en50221_io_ioctl,
-        open: dvb_ca_en50221_io_open,
-        release: dvb_ca_en50221_io_release,
-        poll: dvb_ca_en50221_io_poll,
+        .owner = THIS_MODULE,
+        .read = dvb_ca_en50221_io_read,
+        .write = dvb_ca_en50221_io_write,
+        .ioctl = dvb_ca_en50221_io_ioctl,
+        .open = dvb_ca_en50221_io_open,
+        .release = dvb_ca_en50221_io_release,
+        .poll = dvb_ca_en50221_io_poll,
 };
 
 static struct dvb_device dvbdev_ca = {
-        priv: NULL,
-        users: 1,
-        readers: 1,
-        writers: 1,
-        fops: &dvb_ca_fops,
+        .users = 1,
+        .readers = 1,
+        .writers = 1,
+        .fops = &dvb_ca_fops,
 };
 
 
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index dfa5be4e2..ab18a9193 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -142,7 +142,7 @@ static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb,
 	
 	skb->mac.raw=skb->data;
 	skb_pull(skb,dev->hard_header_len);
-	eth= skb->mac.ethernet;
+	eth = eth_hdr(skb);
 	
 	if (*eth->h_dest & 1) {
 		if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
@@ -563,7 +563,7 @@ static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len,
 	if (buffer2 != 0)
 		printk(KERN_WARNING "buffer2 not 0: %p.\n", buffer2);
 	if (buffer1_len > 32768)
-		printk(KERN_WARNING "length > 32k: %u.\n", buffer1_len);
+		printk(KERN_WARNING "length > 32k: %zu.\n", buffer1_len);
 	/* printk("TS callback: %u bytes, %u TS cells @ %p.\n",
 	          buffer1_len, buffer1_len / TS_SZ, buffer1); */
 	dvb_net_ule(dev, buffer1, buffer1_len);
diff --git a/drivers/media/dvb/frontends/alps_tdlb7.c b/drivers/media/dvb/frontends/alps_tdlb7.c
index cf165f2d5..8ca5b0289 100644
--- a/drivers/media/dvb/frontends/alps_tdlb7.c
+++ b/drivers/media/dvb/frontends/alps_tdlb7.c
@@ -54,9 +54,6 @@ static int debug = 0;
 /* starting point for firmware in file 'Sc_main.mc' */
 #define SP8870_FIRMWARE_OFFSET 0x0A
 
-
-static int errno;
-
 static struct dvb_frontend_info tdlb7_info = {
 	.name			= "Alps TDLB7",
 	.type			= FE_OFDM,
diff --git a/drivers/media/dvb/frontends/dst.c b/drivers/media/dvb/frontends/dst.c
index 431ea9253..4834db951 100644
--- a/drivers/media/dvb/frontends/dst.c
+++ b/drivers/media/dvb/frontends/dst.c
@@ -1145,8 +1145,8 @@ static int dst_attach (struct dvb_i2c_bus *i2c, void **data)
 	}
 
 	dst_init (dst);
-	dprintk("%s: register dst %8.8x bt %8.8x i2c %8.8x\n", __FUNCTION__, 
-			(u32)dst, (u32)(dst->bt), (u32)(dst->i2c));
+	dprintk("%s: register dst %p bt %p i2c %p\n", __FUNCTION__, 
+			dst, dst->bt, dst->i2c);
 
 	info = &dst_info_sat;
 	if (dst->dst_type == DST_TYPE_IS_TERR)
@@ -1162,7 +1162,7 @@ static int dst_attach (struct dvb_i2c_bus *i2c, void **data)
 static void dst_detach (struct dvb_i2c_bus *i2c, void *data)
 {
 	dvb_unregister_frontend (dst_ioctl, i2c);
-	dprintk("%s: unregister dst %8.8x\n", __FUNCTION__, (u32)(data));
+	dprintk("%s: unregister dst %p\n", __FUNCTION__, data);
 	if (data)
 		kfree(data);
 }
diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c
index 53ebf4a69..0aeb8124c 100644
--- a/drivers/media/dvb/frontends/sp887x.c
+++ b/drivers/media/dvb/frontends/sp887x.c
@@ -67,8 +67,6 @@ struct dvb_frontend_info sp887x_info = {
                 FE_CAN_RECOVER
 };
 
-static int errno;
-
 static
 int i2c_writebytes (struct dvb_frontend *fe, u8 addr, u8 *buf, u8 len)
 {
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
index c6a98de01..17c1dd32a 100644
--- a/drivers/media/dvb/frontends/stv0299.c
+++ b/drivers/media/dvb/frontends/stv0299.c
@@ -319,7 +319,7 @@ static int stv0299_readregs (struct dvb_i2c_bus *i2c, u8 reg1, u8 *b, u8 len)
 static int pll_write (struct dvb_i2c_bus *i2c, u8 addr, u8 *data, int len)
 {
 	int ret;
-	struct i2c_msg msg = { addr: addr, .flags = 0, .buf = data, .len = len };
+	struct i2c_msg msg = { .addr = addr, .buf = data, .len = len };
 
 
 	stv0299_writereg(i2c, 0x05, 0xb5);	/*  enable i2c repeater on stv0299  */
@@ -1257,12 +1257,12 @@ static long probe_tuner (struct dvb_i2c_bus *i2c)
         u8 stat [] = { 0 };
 	u8 tda6100_buf [] = { 0, 0 };
 	int ret;
-	struct i2c_msg msg1 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt,  len: 2 },
+	struct i2c_msg msg1 [] = {{ .addr = 0x68, .buf = rpt,  .len = 2 },
 			   { .addr = 0x60, .flags = I2C_M_RD, .buf = stat, .len = 1 }};
-	struct i2c_msg msg2 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt,  len: 2 },
+	struct i2c_msg msg2 [] = {{ .addr = 0x68, .buf = rpt,  .len = 2 },
 			   { .addr = 0x61, .flags = I2C_M_RD, .buf = stat, .len = 1 }};
-	struct i2c_msg msg3 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt,  len: 2 },
-			   { .addr = 0x60, .flags = 0, .buf = tda6100_buf, .len = 2 }};
+	struct i2c_msg msg3 [] = {{ .addr = 0x68, .buf = rpt,  .len = 2 },
+			   { .addr = 0x60, .buf = tda6100_buf, .len = 2 }};
 
 	stv0299_writereg (i2c, 0x01, 0x15);
 	stv0299_writereg (i2c, 0x02, 0x30);
@@ -1271,7 +1271,7 @@ static long probe_tuner (struct dvb_i2c_bus *i2c)
 
 	printk ("%s: try to attach to %s\n", __FUNCTION__, adapter->name);
 
-	if ( strcmp(adapter->name, "Technisat SkyStar2 driver") == 0 )
+	if ( strcmp(adapter->name, "SkyStar2") == 0 )
 	{
 	    printk ("%s: setup for tuner Samsung TBMU24112IMB\n", __FILE__);
 
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index 28dc299a8..deeb8ab70 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -188,8 +188,6 @@ static int tda10045h_fwinfo_count = sizeof(tda10045h_fwinfo) / sizeof(struct fwi
 static struct fwinfo tda10046h_fwinfo[] = { {.file_size = 286720,.fw_offset = 0x3c4f9,.fw_size = 24479} };
 static int tda10046h_fwinfo_count = sizeof(tda10046h_fwinfo) / sizeof(struct fwinfo);
 
-static int errno;
-
 
 static int tda1004x_write_byte(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state, int reg, int data)
 {
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
index 99647b5ff..a5ff5ec02 100644
--- a/drivers/media/dvb/ttpci/Kconfig
+++ b/drivers/media/dvb/ttpci/Kconfig
@@ -1,6 +1,6 @@
 config DVB_AV7110
 	tristate "AV7110 cards"
-	depends on DVB_CORE
+	depends on DVB_CORE && PCI
 	select FW_LOADER
 	select VIDEO_DEV
 	select VIDEO_SAA7146_VV
@@ -45,7 +45,7 @@ config DVB_AV7110_OSD
 
 config DVB_BUDGET
 	tristate "Budget cards"
-	depends on DVB_CORE
+	depends on DVB_CORE && PCI
 	select VIDEO_SAA7146
 	help
 	  Support for simple SAA7146 based DVB cards
@@ -59,7 +59,7 @@ config DVB_BUDGET
 
 config DVB_BUDGET_CI
 	tristate "Budget cards with onboard CI connector"
-	depends on DVB_CORE
+	depends on DVB_CORE && PCI
 	select VIDEO_SAA7146
 	help
 	  Support for simple SAA7146 based DVB cards
@@ -76,7 +76,7 @@ config DVB_BUDGET_CI
 
 config DVB_BUDGET_AV
 	tristate "Budget cards with analog video inputs"
-	depends on DVB_CORE
+	depends on DVB_CORE && PCI
 	select VIDEO_DEV
 	select VIDEO_SAA7146_VV
 	help
diff --git a/drivers/media/dvb/ttpci/Makefile b/drivers/media/dvb/ttpci/Makefile
index 2e8403b89..043468a1d 100644
--- a/drivers/media/dvb/ttpci/Makefile
+++ b/drivers/media/dvb/ttpci/Makefile
@@ -13,7 +13,7 @@ obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o ttpci-eeprom.o
 
 EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/
 
-host-progs	:= fdump
+hostprogs-y	:= fdump
 
 ifdef CONFIG_DVB_AV7110_FIRMWARE
 $(obj)/av7110.o: $(obj)/fdump $(obj)/av7110_firm.h 
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index 5e3f5eacc..cc48a65e8 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -1181,7 +1181,7 @@ static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
 	firmware_size = fw_entry->size;
 
 	if (firmware_size < 60) {
-		printk("%s: firmware size too small for DSP code (%u < 60).\n",
+		printk("%s: firmware size too small for DSP code (%zu < 60).\n",
 			__FUNCTION__, firmware_size);
 		return -1;
 	}
diff --git a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c
index 6b11044e7..df79d5e0a 100644
--- a/drivers/media/radio/miropcm20-rds.c
+++ b/drivers/media/radio/miropcm20-rds.c
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
+#include <linux/delay.h>
 #include <asm/uaccess.h>
 #include "miropcm20-rds-core.h"
 
@@ -60,8 +61,7 @@ static ssize_t rds_f_read(struct file *file, char __user *buffer, size_t length,
 	char c;
 	char bits[8];
 
-	current->state=TASK_UNINTERRUPTIBLE;
-	schedule_timeout(2*HZ);
+	msleep(2000);
 	aci_rds_cmd(RDS_STATUS, &c, 1);
 	print_matrix(&c, bits);
 	if (copy_to_user(buffer, bits, 8))
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index c6e648753..7aab2ed62 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -63,12 +63,7 @@ static void sleep_delay(long n)
 	if(!d)
 		udelay(n);
 	else
-	{
-		/* Yield CPU time */
-		unsigned long x=jiffies;
-		while((jiffies-x)<=d)
-			schedule();
-	}
+		msleep(jiffies_to_msecs(d));
 }
 
 static void rt_decvol(void)
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index 8cc5191ac..abb03c53d 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -69,8 +69,7 @@ static int cadet_getrds(void)
 	outb(inb(io+1)&0x7f,io+1);  /* Reset RDS detection */
 	spin_unlock(&cadet_io_lock);
 	
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ/10);
+	msleep(100);
 
 	spin_lock(&cadet_io_lock);	
         outb(3,io);                 /* Select Decoder Control/Status */
@@ -243,8 +242,7 @@ static void cadet_setfreq(unsigned freq)
 		outb(curvol,io+1);
 		spin_unlock(&cadet_io_lock);
 		
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ/10);
+		msleep(100);
 
 		cadet_gettune();
 		if((tunestat & 0x40) == 0) {   /* Tuned */
diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
index 6a18c0088..b226aa437 100644
--- a/drivers/media/radio/radio-maestro.c
+++ b/drivers/media/radio/radio-maestro.c
@@ -93,27 +93,6 @@ static struct radio_device
 	struct  semaphore lock;
 } radio_unit = {0, 0, 0, 0, };
 
-static void sleep_125ms(void)
-{
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(HZ >> 3);
-}
-
-static void udelay2(void)
-{
-	udelay(2);
-}
-
-static void udelay4(void)
-{
-	udelay(4);
-}
-
-static void udelay16(void)
-{
-	udelay(16);
-}
-
 static __u32 radio_bits_get(struct radio_device *dev)
 {
 	register __u16 io=dev->io, l, rdata;
@@ -122,14 +101,15 @@ static __u32 radio_bits_get(struct radio_device *dev)
 	omask = inw(io + IO_MASK);
 	outw(~(STR_CLK | STR_WREN), io + IO_MASK);
 	outw(0, io);
-	udelay16();
+	udelay(16);
+
 	for (l=24;l--;) {
 		outw(STR_CLK, io);		/* HI state */
-		udelay2();
+		udelay(2);
 		if(!l) 
 			dev->tuned = inw(io) & STR_MOST ? 0 : 0xffff;
 		outw(0, io);			/* LO state */
-		udelay2();
+		udelay(2);
 		data <<= 1;			/* shift data */
 		rdata = inw(io);
 		if(!l)
@@ -138,11 +118,11 @@ static __u32 radio_bits_get(struct radio_device *dev)
 		else
 			if(rdata & STR_DATA)
 				data++;
-		udelay2();
+		udelay(2);
 	}
 	if(dev->muted)
 		outw(STR_WREN, io);
-	udelay4();
+	udelay(4);
 	outw(omask, io + IO_MASK);
 	return data & 0x3ffe;
 }
@@ -155,23 +135,23 @@ static void radio_bits_set(struct radio_device *dev, __u32 data)
 	odir  = (inw(io + IO_DIR) & ~STR_DATA) | (STR_CLK | STR_WREN);
 	outw(odir | STR_DATA, io + IO_DIR);
 	outw(~(STR_DATA | STR_CLK | STR_WREN), io + IO_MASK);
-	udelay16();
+	udelay(16);
 	for (l=25;l;l--) {
 		bits = ((data >> 18) & STR_DATA) | STR_WREN ;
 		data <<= 1;			/* shift data */
 		outw(bits, io);			/* start strobe */
-		udelay2();
+		udelay(2);
 		outw(bits | STR_CLK, io);	/* HI level */
-		udelay2();   
+		udelay(2);
 		outw(bits, io);			/* LO level */
-		udelay4();
+		udelay(4);
 	}
 	if(!dev->muted)
 		outw(0, io);
-	udelay4();
+	udelay(4);
 	outw(omask, io + IO_MASK);
 	outw(odir, io + IO_DIR);
-	sleep_125ms();
+	msleep(125);
 }
 
 inline static int radio_function(struct inode *inode, struct file *file,
@@ -238,9 +218,9 @@ inline static int radio_function(struct inode *inode, struct file *file,
 				outw(~STR_WREN, io + IO_MASK);
 				outw((card->muted = v->flags & VIDEO_AUDIO_MUTE)
 				     ? STR_WREN : 0, io);
-				udelay4();
+				udelay(4);
 				outw(omask, io + IO_MASK);
-				sleep_125ms();
+				msleep(125);
 				return 0;
 			}
 		}
@@ -270,7 +250,7 @@ static int radio_ioctl(struct inode *inode, struct file *file,
 	return ret;
 }
 
-inline static __u16 radio_install(struct pci_dev *pcidev);
+static __u16 radio_install(struct pci_dev *pcidev);
 
 MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl");
 MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio.");
@@ -315,7 +295,7 @@ inline static __u16 radio_power_on(struct radio_device *dev)
 	outw(odir, io + IO_DIR);
 	outw(~(STR_WREN | STR_CLK), io + IO_MASK);
 	outw(dev->muted ? 0 : STR_WREN, io);
-	udelay16();
+	udelay(16);
 	outw(omask, io + IO_MASK);
 	ofreq = radio_bits_get(dev);
 	if((ofreq<FREQ2BITS(FREQ_LO)) || (ofreq>FREQ2BITS(FREQ_HI)))
@@ -324,7 +304,7 @@ inline static __u16 radio_power_on(struct radio_device *dev)
 	return (ofreq == radio_bits_get(dev));
 }
 
-inline static __u16 radio_install(struct pci_dev *pcidev)
+static __u16 radio_install(struct pci_dev *pcidev)
 {
 	if(((pcidev->class >> 8) & 0xffff) != PCI_CLASS_MULTIMEDIA_AUDIO)
 		return 0;
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
index c2fa20d77..c3c62095f 100644
--- a/drivers/media/radio/radio-maxiradio.c
+++ b/drivers/media/radio/radio-maxiradio.c
@@ -104,13 +104,6 @@ static struct radio_device
 } radio_unit = {0, 0, 0, 0, };
 
 
-static void sleep_125ms(void)
-{
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(HZ >> 3);
-}
-
-
 static void outbit(unsigned long bit, __u16 io)
 {
 	if(bit != 0)
@@ -228,7 +221,7 @@ inline static int radio_function(struct inode *inode, struct file *file,
 				return -EINVAL;
 			card->freq = *freq;
 			set_freq(card->io, FREQ2BITS(card->freq));
-			sleep_125ms();
+			msleep(125);
 			return 0;
 		}
 		case VIDIOCGAUDIO: {	
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index 9962c43c7..f0575fb2c 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -89,8 +89,7 @@ static inline int fmi_setfreq(struct fmi_device *dev)
 
 	outbits(16, RSF16_ENCODE(freq), myport);
 	outbits(8, 0xC0, myport);
-	current->state = TASK_UNINTERRUPTIBLE;
-	schedule_timeout(HZ/7);
+	msleep(143);		/* was schedule_timeout(HZ/7) */
 	up(&lock);
 	if (dev->curvol) fmi_unmute(myport);
 	return 0;
@@ -107,8 +106,7 @@ static inline int fmi_getsigstr(struct fmi_device *dev)
 	val = dev->curvol ? 0x08 : 0x00;	/* unmute/mute */
 	outb(val, myport);
 	outb(val | 0x10, myport);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ/7);
+	msleep(143); 		/* was schedule_timeout(HZ/7) */
 	res = (int)inb(myport+1);
 	outb(val, myport);
 	
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index aa49c8e5c..7e980d15f 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -55,19 +55,6 @@ static int radio_nr = -1;
 #define RSF16_MINFREQ 87*16000
 #define RSF16_MAXFREQ 108*16000
 
-/* from radio-aimslab */
-static void sleep_delay(unsigned long n)
-{
-	unsigned d=n/(1000000U/HZ);
-	if (!d)
-		udelay(n);
-	else
-	{
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(d);
-	}
-}
-
 static inline void wait(int n,int port)
 {
 	for (;n;--n) inb(port);
@@ -153,7 +140,7 @@ static int fmr2_setfreq(struct fmr2_device *dev)
 	fmr2_unmute(port);
 
 	/* wait 0.11 sec */
-	sleep_delay(110000LU);
+	msleep(110);
 
 	/* NOTE if mute this stop radio
 	   you must set freq on unmute */
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index db5270b73..d22dd93e5 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -155,7 +155,7 @@ config VIDEO_STRADIS
 
 config VIDEO_ZORAN
 	tristate "Zoran ZR36057/36067 Video For Linux"
-	depends on VIDEO_DEV && PCI && I2C
+	depends on VIDEO_DEV && PCI && I2C_ALGOBIT
 	help
 	  Say Y for support for MJPEG capture cards based on the Zoran
 	  36057/36067 PCI controller chipset. This includes the Iomega
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
index 16bfdb9ec..74fefc2df 100644
--- a/drivers/media/video/adv7175.c
+++ b/drivers/media/video/adv7175.c
@@ -156,6 +156,22 @@ adv7175_write_block (struct i2c_client *client,
 	return ret;
 }
 
+static void
+set_subcarrier_freq (struct i2c_client *client,
+		     int                pass_through)
+{
+	/* for some reason pass_through NTSC needs
+	 * a different sub-carrier freq to remain stable. */
+	if(pass_through)
+		adv7175_write(client, 0x02, 0x00);
+	else
+		adv7175_write(client, 0x02, 0x55);
+
+	adv7175_write(client, 0x03, 0x55);
+	adv7175_write(client, 0x04, 0x55);
+	adv7175_write(client, 0x05, 0x25);
+}
+
 #ifdef ENCODER_DUMP
 static void
 dump (struct i2c_client *client)
@@ -322,6 +338,10 @@ adv7175_command (struct i2c_client *client,
 
 		case 0:
 			adv7175_write(client, 0x01, 0x00);
+
+			if (encoder->norm == VIDEO_MODE_NTSC)
+				set_subcarrier_freq(client, 1);
+
 			adv7175_write(client, 0x0c, TR1CAPT);	/* TR1 */
 			if (encoder->norm == VIDEO_MODE_SECAM)
 				adv7175_write(client, 0x0d, 0x49);	// Disable genlock
@@ -334,6 +354,10 @@ adv7175_command (struct i2c_client *client,
 
 		case 1:
 			adv7175_write(client, 0x01, 0x00);
+
+			if (encoder->norm == VIDEO_MODE_NTSC)
+				set_subcarrier_freq(client, 0);
+
 			adv7175_write(client, 0x0c, TR1PLAY);	/* TR1 */
 			adv7175_write(client, 0x0d, 0x49);
 			adv7175_write(client, 0x07, TR0MODE | TR0RST);
@@ -343,6 +367,10 @@ adv7175_command (struct i2c_client *client,
 
 		case 2:
 			adv7175_write(client, 0x01, 0x80);
+
+			if (encoder->norm == VIDEO_MODE_NTSC)
+				set_subcarrier_freq(client, 0);
+
 			adv7175_write(client, 0x0d, 0x49);
 			adv7175_write(client, 0x07, TR0MODE | TR0RST);
 			adv7175_write(client, 0x07, TR0MODE);
diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c
index 7ea762f35..a5a24309c 100644
--- a/drivers/media/video/bttv-cards.c
+++ b/drivers/media/video/bttv-cards.c
@@ -31,7 +31,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
-#ifdef CONFIG_FW_LOADER
+#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
 # include <linux/firmware.h>
 #endif
 
@@ -74,6 +74,9 @@ static void PXC200_muxsel(struct bttv *btv, unsigned int input);
 static void picolo_tetra_muxsel(struct bttv *btv, unsigned int input);
 static void picolo_tetra_init(struct bttv *btv);
 
+static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input);
+static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input);
+
 static int terratec_active_radio_upgrade(struct bttv *btv);
 static int tea5757_read(struct bttv *btv);
 static int tea5757_write(struct bttv *btv, int value);
@@ -170,6 +173,7 @@ static struct CARD {
 
 	{ 0x6606107d, BTTV_WINFAST2000,   "Leadtek WinFast TV 2000" },
 	{ 0x6607107d, BTTV_WINFASTVC100,  "Leadtek WinFast VC 100" },
+	{ 0x6609107d, BTTV_WINFAST2000,   "Leadtek TV 2000 XP" },
 	{ 0x263610b4, BTTV_STB2,          "STB TV PCI FM, Gateway P/N 6000704" },
 	{ 0x264510b4, BTTV_STB2,          "STB TV PCI FM, Gateway P/N 6000704" },
  	{ 0x402010fc, BTTV_GVBCTV3PCI,    "I-O Data Co. GV-BCTV3/PCI" },
@@ -224,6 +228,7 @@ static struct CARD {
 	{ 0x1431aa00, BTTV_PV143,         "Provideo PV143B" },
 	{ 0x1432aa00, BTTV_PV143,         "Provideo PV143C" },
 	{ 0x1433aa00, BTTV_PV143,         "Provideo PV143D" },
+	{ 0x1433aa03, BTTV_PV143,         "Security Eyes" },
 
 	{ 0x1460aa00, BTTV_PV150,         "Provideo PV150A-1" },
 	{ 0x1461aa01, BTTV_PV150,         "Provideo PV150A-2" },
@@ -265,6 +270,7 @@ static struct CARD {
 	{ 0x01020304, BTTV_XGUARD,        "Grandtec Grand X-Guard" },
 	
 	{ 0x18501851, BTTV_CHRONOS_VS2,   "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" },
+	{ 0xa0501851, BTTV_CHRONOS_VS2,   "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" },
 	{ 0x18511851, BTTV_FLYVIDEO98EZ,  "FlyVideo 98EZ (LR51)/ CyberMail AV" },
 	{ 0x18521852, BTTV_TYPHOON_TVIEW, "FlyVideo 98FM (LR50)/ Typhoon TView TV/FM Tuner" },
 	{ 0x41a0a051, BTTV_FLYVIDEO_98FM, "Lifeview FlyVideo 98 LR50 Rev Q" },
@@ -297,7 +303,7 @@ static struct CARD {
 	
 	// DVB cards (using pci function .1 for mpeg data xfer)
 	{ 0x01010071, BTTV_NEBULA_DIGITV, "Nebula Electronics DigiTV" },
-	{ 0x07611461, BTTV_NEBULA_DIGITV, "AverMedia AverTV DVB-T" },
+	{ 0x07611461, BTTV_AVDVBT_761,    "AverMedia AverTV DVB-T" },
 	{ 0x002611bd, BTTV_TWINHAN_DST,   "Pinnacle PCTV SAT CI" },
 	{ 0x00011822, BTTV_TWINHAN_DST,   "Twinhan VisionPlus DVB-T" },
 	{ 0xfc00270f, BTTV_TWINHAN_DST,   "ChainTech digitop DST-1000 DVB-S" },
@@ -2078,6 +2084,69 @@ struct tvcard bttv_tvcards[] = {
 #if 0 /* untested */
         .has_remote     = 1,
 #endif
+},{
+	/* ---- card 0x7c ---------------------------------- */
+	/* Matt Jesson <dvb@jesson.eclipse.co.uk> */
+	/* Based on the Nebula card data - added remote and new card number - BTTV_AVDVBT_761, see also ir-kbd-gpio.c */
+	.name           = "AverMedia AverTV DVB-T 761",
+	.video_inputs   = 1,
+	.tuner          = -1,
+	.svhs           = -1,
+	.muxsel         = { 2, 3, 1, 0},
+	.no_msp34xx     = 1,
+	.no_tda9875     = 1,
+	.no_tda7432     = 1,
+	.pll            = PLL_28,
+	.tuner_type     = -1,
+	.has_dvb        = 1,
+	.no_gpioirq     = 1,
+	.has_remote     = 1,
+},{
+	/* andre.schwarz@matrix-vision.de */
+	.name             = "MATRIX Vision Sigma-SQ",
+	.video_inputs     = 16,
+	.audio_inputs     = 0,
+	.tuner            = -1,
+	.svhs             = -1,
+	.gpiomask         = 0x0,
+	.muxsel           = { 2, 2, 2, 2, 2, 2, 2, 2,
+			      3, 3, 3, 3, 3, 3, 3, 3 },
+	.muxsel_hook      = sigmaSQ_muxsel,
+	.audiomux         = { 0 },
+	.no_msp34xx       = 1,
+	.pll              = PLL_28,
+	.tuner_type       = -1,
+},{
+	/* andre.schwarz@matrix-vision.de */
+	.name             = "MATRIX Vision Sigma-SLC",
+	.video_inputs     = 4,
+	.audio_inputs     = 0,
+	.tuner            = -1,
+	.svhs             = -1,
+	.gpiomask         = 0x0,
+	.muxsel           = { 2, 2, 2, 2 },
+	.muxsel_hook      = sigmaSLC_muxsel,
+	.audiomux         = { 0 },
+	.no_msp34xx       = 1,
+	.pll              = PLL_28,
+	.tuner_type       = -1,
+},{
+	/* BTTV_APAC_VIEWCOMP */
+	/* Attila Kondoros <attila.kondoros@chello.hu> */
+	/* bt878 TV + FM 0x00000000 subsystem ID */
+	.name           = "APAC Viewcomp 878(AMAX)",
+	.video_inputs   = 2,
+	.audio_inputs   = 1,
+	.tuner          = 0,
+	.svhs           = -1,
+	.gpiomask       = 0xFF,
+	.muxsel         = { 2, 3, 1, 1},
+	.audiomux       = { 2, 0, 0, 0, 10},
+	.needs_tvaudio  = 0,
+	.pll            = PLL_28,
+	.tuner_type     = TUNER_PHILIPS_PAL,
+	.has_remote     = 1,   /* miniremote works, see ir-kbd-gpio.c */
+	.has_radio      = 1,   /* not every card has radio */
 }};
 
 const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
@@ -2405,6 +2474,19 @@ static void init_lmlbt4x(struct bttv *btv)
 	gpio_write(0x000000);
 }
 
+static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input)
+{
+	unsigned int inmux = input % 8;
+	gpio_inout( 0xf, 0xf );
+	gpio_bits( 0xf, inmux );
+}
+
+static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input)
+{
+	unsigned int inmux = input % 4;
+	gpio_inout( 3<<9, 3<<9 );
+	gpio_bits( 3<<9, inmux<<9 );
+}
 
 /* ----------------------------------------------------------------------- */
 
@@ -2859,7 +2941,7 @@ static int __devinit pvr_altera_load(struct bttv *btv, u8 *micro, u32 microlen)
 	return 0;
 }
 
-#ifndef CONFIG_FW_LOADER
+#if !defined(CONFIG_FW_LOADER) && !defined(CONFIG_FW_LOADER_MODULE)
 /* old 2.4.x way -- via soundcore's mod_firmware_load */
    
 static char *firm_altera = "/usr/lib/video4linux/hcwamc.rbf";
@@ -4063,7 +4145,7 @@ static void PXC200_muxsel(struct bttv *btv, unsigned int input)
 	  return;
 	}
 
-	rc=bttv_I2CRead(btv,(PX_I2C_PIC<<1),NULL);
+	rc=bttv_I2CRead(btv,(PX_I2C_PIC<<1),0);
 	if (!(rc & PX_CFG_PXC200F)) {
 	  printk(KERN_DEBUG "bttv%d: PXC200_muxsel: not PXC200F rc:%d \n", btv->c.nr,rc);
 	  return;
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
index e7ffe1841..f0d54c5f2 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bttv-driver.c
@@ -1051,11 +1051,6 @@ static void init_bt848(struct bttv *btv)
 	btwrite(whitecrush_upper, BT848_WC_UP);
 	btwrite(whitecrush_lower, BT848_WC_DOWN);
 
-	bt848_bright(btv,   btv->bright);
-	bt848_hue(btv,      btv->hue);
-	bt848_contrast(btv, btv->contrast);
-	bt848_sat(btv,      btv->saturation);
-
 	if (btv->opt_lumafilter) {
 		btwrite(0, BT848_E_CONTROL);
 		btwrite(0, BT848_O_CONTROL);
@@ -1064,6 +1059,11 @@ static void init_bt848(struct bttv *btv)
 		btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL);
 	}
 
+	bt848_bright(btv,   btv->bright);
+	bt848_hue(btv,      btv->hue);
+	bt848_contrast(btv, btv->contrast);
+	bt848_sat(btv,      btv->saturation);
+
         /* interrupt */
 	init_irqreg(btv);
 }
@@ -1861,6 +1861,8 @@ static int setup_window(struct bttv_fh *fh, struct bttv *btv,
 
 	if (NULL == fh->ovfmt)
 		return -EINVAL;
+	if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED))
+		return -EINVAL;
 	retval = verify_window(&bttv_tvnorms[btv->tvnorm],win,fixup);
 	if (0 != retval)
 		return retval;
@@ -2052,6 +2054,7 @@ static int bttv_try_fmt(struct bttv_fh *fh, struct bttv *btv,
 			f->fmt.pix.width = maxw;
 		if (f->fmt.pix.height > maxh)
 			f->fmt.pix.height = maxh;
+		f->fmt.pix.width &= ~0x03;
 		f->fmt.pix.bytesperline =
 			(f->fmt.pix.width * fmt->depth) >> 3;
 		f->fmt.pix.sizeimage =
diff --git a/drivers/media/video/bttv-gpio.c b/drivers/media/video/bttv-gpio.c
index 01ce7bc32..585f67dde 100644
--- a/drivers/media/video/bttv-gpio.c
+++ b/drivers/media/video/bttv-gpio.c
@@ -106,6 +106,20 @@ void bttv_gpio_irq(struct bttv_core *core)
 	}
 }
 
+void bttv_i2c_info(struct bttv_core *core, struct i2c_client *client, int attach)
+{
+	struct bttv_sub_driver *drv;
+	struct bttv_sub_device *dev;
+	struct list_head *item;
+
+	list_for_each(item,&core->subs) {
+		dev = list_entry(item,struct bttv_sub_device,list);
+		drv = to_bttv_sub_drv(dev->dev.driver);
+		if (drv && drv->i2c_info)
+			drv->i2c_info(dev,client,attach);
+	}
+}
+
 /* ----------------------------------------------------------------------- */
 /* external: sub-driver register/unregister                                */
 
diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c
index c07a0d9c0..5eb88fcad 100644
--- a/drivers/media/video/bttv-i2c.c
+++ b/drivers/media/video/bttv-i2c.c
@@ -40,6 +40,7 @@ static void bttv_inc_use(struct i2c_adapter *adap);
 static void bttv_dec_use(struct i2c_adapter *adap);
 #endif
 static int attach_inform(struct i2c_client *client);
+static int detach_inform(struct i2c_client *client);
 
 static int i2c_debug = 0;
 static int i2c_hw = 0;
@@ -114,6 +115,7 @@ static struct i2c_adapter bttv_i2c_adap_sw_template = {
 	I2C_DEVNAME("bt848"),
 	.id                = I2C_HW_B_BT848,
 	.client_register   = attach_inform,
+	.client_unregister = detach_inform,
 };
 
 /* ----------------------------------------------------------------------- */
@@ -298,6 +300,7 @@ static struct i2c_adapter bttv_i2c_adap_hw_template = {
 	.id            = I2C_ALGO_BIT | I2C_HW_B_BT848 /* FIXME */,
 	.algo          = &bttv_algo,
 	.client_register = attach_inform,
+	.client_unregister = detach_inform,
 };
 
 /* ----------------------------------------------------------------------- */
@@ -324,6 +327,7 @@ static int attach_inform(struct i2c_client *client)
 	if (btv->pinnacle_id != UNSET)
 		bttv_call_i2c_clients(btv,AUDC_CONFIG_PINNACLE,
 				      &btv->pinnacle_id);
+	bttv_i2c_info(&btv->c, client, 1);
 
         if (bttv_debug)
 		printk("bttv%d: i2c attach [client=%s]\n",
@@ -331,6 +335,14 @@ static int attach_inform(struct i2c_client *client)
         return 0;
 }
 
+static int detach_inform(struct i2c_client *client)
+{
+        struct bttv *btv = i2c_get_adapdata(client->adapter);
+
+	bttv_i2c_info(&btv->c, client, 0);
+	return 0;
+}
+
 void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg)
 {
 	if (0 != btv->i2c_rc)
diff --git a/drivers/media/video/bttv-risc.c b/drivers/media/video/bttv-risc.c
index 769c7e365..3731d2c9a 100644
--- a/drivers/media/video/bttv-risc.c
+++ b/drivers/media/video/bttv-risc.c
@@ -55,6 +55,8 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
 	instructions += 2;
 	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*8)) < 0)
 		return rc;
+	dprintk("bttv%d: risc packed: bpl %d lines %d instr %d size %d ptr %p\n",
+		btv->c.nr, bpl, lines, instructions, risc->size, risc->cpu);
 
 	/* sync instruction */
 	rp = risc->cpu;
@@ -99,8 +101,10 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
 			offset += todo;
 		}
 		offset += padding;
+		dprintk("bttv%d: risc packed:   line %d ptr %p\n",
+			btv->c.nr, line, rp);
 	}
-	dprintk("bttv%d: risc planar: %d sglist elems\n", btv->c.nr, (int)(sg-sglist));
+	dprintk("bttv%d: risc packed: %d sglist elems\n", btv->c.nr, (int)(sg-sglist));
 
 	/* save pointer to jmp instruction address */
 	risc->jmp = rp;
@@ -121,6 +125,7 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
 	struct scatterlist *ysg;
 	struct scatterlist *usg;
 	struct scatterlist *vsg;
+	int topfield = (0 == yoffset);
 	int rc;
 
 	/* estimate risc mem: worst case is one write per page border +
@@ -145,11 +150,26 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
 		    (line >= (ylines - VCR_HACK_LINES)))
 			continue;
 		switch (vshift) {
-		case 0:  chroma = 1;           break;
-		case 1:  chroma = !(line & 1); break;
-		case 2:  chroma = !(line & 3); break;
-		default: chroma = 0;
+		case 0:
+			chroma = 1;
+			break;
+		case 1:
+			if (topfield)
+				chroma = (line & 1) == 0;
+			else
+				chroma = (line & 1) == 1;
+			break;
+		case 2:
+			if (topfield)
+				chroma = (line & 3) == 0;
+			else
+				chroma = (line & 3) == 2;
+			break;
+		default:
+			chroma = 0;
+			break;
 		}
+
 		for (todo = ybpl; todo > 0; todo -= ylen) {
 			/* go to next sg entry if needed */
 			while (yoffset && yoffset >= sg_dma_len(ysg)) {
diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h
index 33d56aa9d..5b8199b79 100644
--- a/drivers/media/video/bttv.h
+++ b/drivers/media/video/bttv.h
@@ -126,6 +126,10 @@
 #define BTTV_LMLBT4         0x76
 #define BTTV_PICOLO_TETRA_CHIP 0x79
 #define BTTV_AVDVBT_771     0x7b
+#define BTTV_AVDVBT_761     0x7c
+#define BTTV_MATRIX_VISIONSQ  0x7d
+#define BTTV_MATRIX_VISIONSLC 0x7e
+#define BTTV_APAC_VIEWCOMP  0x7f
 
 /* i2c address list */
 #define I2C_TSA5522        0xc2
@@ -298,6 +302,8 @@ struct bttv_sub_driver {
 	struct device_driver   drv;
 	char                   wanted[BUS_ID_SIZE];
 	void                   (*gpio_irq)(struct bttv_sub_device *sub);
+	void                   (*i2c_info)(struct bttv_sub_device *sub,
+					   struct i2c_client *client, int attach);
 };
 #define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv)
 
diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h
index fae428ea4..943f8136a 100644
--- a/drivers/media/video/bttvp.h
+++ b/drivers/media/video/bttvp.h
@@ -225,6 +225,7 @@ extern struct bus_type bttv_sub_bus_type;
 int bttv_sub_add_device(struct bttv_core *core, char *name);
 int bttv_sub_del_devices(struct bttv_core *core);
 void bttv_gpio_irq(struct bttv_core *core);
+void bttv_i2c_info(struct bttv_core *core, struct i2c_client *client, int attach);
 
 
 /* ---------------------------------------------------------- */
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
index 02c012dbc..21db4b390 100644
--- a/drivers/media/video/cpia.c
+++ b/drivers/media/video/cpia.c
@@ -29,6 +29,7 @@
 #include <linux/config.h>
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/vmalloc.h>
@@ -62,6 +63,15 @@ MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("video");
 #endif
 
+static unsigned short colorspace_conv = 0;
+module_param(colorspace_conv, ushort, 0444);
+MODULE_PARM_DESC(colorspace_conv,
+                 "\n<n> Colorspace conversion:"
+                 "\n0 = disable"
+                 "\n1 = enable"
+                 "\nDefault value is 0"
+                 "\n");
+
 #define ABOUT "V4L-Driver for Vision CPiA based cameras"
 
 #ifndef VID_HARDWARE_CPIA
@@ -1428,14 +1438,19 @@ static void __exit proc_cpia_destroy(void)
 /* supported frame palettes and depths */
 static inline int valid_mode(u16 palette, u16 depth)
 {
-	return (palette == VIDEO_PALETTE_GREY && depth == 8) ||
-	       (palette == VIDEO_PALETTE_RGB555 && depth == 16) ||
-	       (palette == VIDEO_PALETTE_RGB565 && depth == 16) ||
-	       (palette == VIDEO_PALETTE_RGB24 && depth == 24) ||
-	       (palette == VIDEO_PALETTE_RGB32 && depth == 32) ||
-	       (palette == VIDEO_PALETTE_YUV422 && depth == 16) ||
-	       (palette == VIDEO_PALETTE_YUYV && depth == 16) ||
-	       (palette == VIDEO_PALETTE_UYVY && depth == 16);
+	if ((palette == VIDEO_PALETTE_YUV422 && depth == 16) ||
+	    (palette == VIDEO_PALETTE_YUYV && depth == 16))
+		return 1;
+
+	if (colorspace_conv)
+		return (palette == VIDEO_PALETTE_GREY && depth == 8) ||
+		       (palette == VIDEO_PALETTE_RGB555 && depth == 16) ||
+		       (palette == VIDEO_PALETTE_RGB565 && depth == 16) ||
+		       (palette == VIDEO_PALETTE_RGB24 && depth == 24) ||
+		       (palette == VIDEO_PALETTE_RGB32 && depth == 32) ||
+		       (palette == VIDEO_PALETTE_UYVY && depth == 16);
+
+	return 0;
 }
 
 static int match_videosize( int width, int height )
@@ -4040,6 +4055,13 @@ static int __init cpia_init(void)
 {
 	printk(KERN_INFO "%s v%d.%d.%d\n", ABOUT,
 	       CPIA_MAJ_VER, CPIA_MIN_VER, CPIA_PATCH_VER);
+
+	printk(KERN_WARNING "Since in-kernel colorspace conversion is not "
+	       "allowed, it is disabled by default now. Users should fix the "
+	       "applications in case they don't work without conversion "
+	       "reenabled by setting the 'colorspace_conv' module "
+	       "parameter to 1");
+
 #ifdef CONFIG_PROC_FS
 	proc_cpia_create();
 #endif
diff --git a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c
index 3944f3f6a..d54244413 100644
--- a/drivers/media/video/dpc7146.c
+++ b/drivers/media/video/dpc7146.c
@@ -123,6 +123,7 @@ static int dpc_probe(struct saa7146_dev* dev)
 	/* check if all devices are present */
 	if( 0 == dpc->saa7111a ) {
 		DEB_D(("dpc_v4l2.o: dpc_attach failed for this device.\n"));	
+		i2c_del_adapter(&dpc->i2c_adapter);
 		kfree(dpc);
 		return -ENODEV;
 	}
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index 6f3fe234e..a586b1bc9 100644
--- a/drivers/media/video/meye.c
+++ b/drivers/media/video/meye.c
@@ -58,7 +58,7 @@ static int video_nr = -1;
 static inline void meye_initq(struct meye_queue *queue) {
 	queue->head = queue->tail = 0;
 	queue->len = 0;
-	queue->s_lock = (spinlock_t)SPIN_LOCK_UNLOCKED;
+	queue->s_lock = SPIN_LOCK_UNLOCKED;
 	init_waitqueue_head(&queue->proc_list);
 }
 
diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
index 41adfef5c..b60609616 100644
--- a/drivers/media/video/msp3400.c
+++ b/drivers/media/video/msp3400.c
@@ -1552,13 +1552,12 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
 
 /* ----------------------------------------------------------------------- */
 
-static int msp3400_init_module(void)
+static int __init msp3400_init_module(void)
 {
-	i2c_add_driver(&driver);
-	return 0;
+	return i2c_add_driver(&driver);
 }
 
-static void msp3400_cleanup_module(void)
+static void __exit msp3400_cleanup_module(void)
 {
 	i2c_del_driver(&driver);
 }
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
index 3343e4133..092fd358c 100644
--- a/drivers/media/video/saa7134/saa6752hs.c
+++ b/drivers/media/video/saa7134/saa6752hs.c
@@ -387,13 +387,12 @@ static struct i2c_client client_template =
         .driver     = &driver,
 };
 
-static int saa6752hs_init_module(void)
+static int __init saa6752hs_init_module(void)
 {
-	i2c_add_driver(&driver);
-	return 0;
+	return i2c_add_driver(&driver);
 }
 
-static void saa6752hs_cleanup_module(void)
+static void __exit saa6752hs_cleanup_module(void)
 {
 	i2c_del_driver(&driver);
 }
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index 5bb99d716..74b8f0b95 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -154,6 +154,26 @@ struct saa7134_board saa7134_boards[] = {
 			.gpio = 0x8000,
 		},
 	},
+	[SAA7134_BOARD_FLYTVPLATINUM] = {
+		/* "Arnaud Quette" <aquette@free.fr> */
+		.name           = "LifeView FlyTV Platinum",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_SECAM,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		}},
+	},
 	[SAA7134_BOARD_EMPRESS] = {
 		/* "Gert Vervoort" <gert.vervoort@philips.com> */
 		.name		= "EMPRESS",
@@ -177,7 +197,6 @@ struct saa7134_board saa7134_boards[] = {
 			.name = name_radio,
 			.amux = LINE2,
 		},
-		.i2s_rate  = 48000,
 		.has_ts    = 1,
 		.video_out = CCIR656,
 	},
@@ -243,7 +262,7 @@ struct saa7134_board saa7134_boards[] = {
 		.name		= "KNC One TV-Station RDS / Typhoon TV Tuner RDS",
 		.audio_clock	= 0x00200000,
 		.tuner_type	= TUNER_PHILIPS_FM1216ME_MK3,
-		.need_tda9887   = 1,
+		.tda9887_conf   = TDA9887_PRESENT,
 		.inputs         = {{
 			.name = name_tv,
 			.vmux = 1,
@@ -278,7 +297,7 @@ struct saa7134_board saa7134_boards[] = {
 		.name		= "KNC One TV-Station DVR",
 		.audio_clock	= 0x00200000,
 		.tuner_type	= TUNER_PHILIPS_FM1216ME_MK3,
-		.need_tda9887	= 1,
+		.tda9887_conf	= TDA9887_PRESENT,
 		.gpiomask	= 0x820000,
 		.inputs		= {{
 			.name = name_tv,
@@ -302,7 +321,6 @@ struct saa7134_board saa7134_boards[] = {
 			.amux = LINE2,
 			.gpio = 0x20000,
 		},
-		.i2s_rate	= 48000,
 		.has_ts		= 1,
 		.video_out	= CCIR656,
 	},
@@ -333,7 +351,7 @@ struct saa7134_board saa7134_boards[] = {
 		.name           = "Medion 5044",
 		.audio_clock    = 0x00187de7, // was: 0x00200000,
 		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-		.need_tda9887   = 1,
+		.tda9887_conf   = TDA9887_PRESENT,
 		.inputs         = {{
 			.name = name_tv,
 			.vmux = 1,
@@ -414,7 +432,7 @@ struct saa7134_board saa7134_boards[] = {
 		//.audio_clock    = 0x00200000,
 		.audio_clock    = 0x00187de7,
 		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-		.need_tda9887   = 1,
+		.tda9887_conf   = TDA9887_PRESENT,
 		.inputs = {{
 			.name   = name_tv,
 			.vmux   = 1,
@@ -440,7 +458,7 @@ struct saa7134_board saa7134_boards[] = {
 		.name           = "Typhoon TV+Radio 90031",
 		.audio_clock    = 0x00200000,
 		.tuner_type     = TUNER_PHILIPS_PAL,
-		.need_tda9887   = 1,
+		.tda9887_conf   = TDA9887_PRESENT,
 		.inputs         = {{
 			.name   = name_tv,
 			.vmux   = 1,
@@ -503,7 +521,7 @@ struct saa7134_board saa7134_boards[] = {
                 .name           = "ASUS TV-FM 7134",
                 .audio_clock    = 0x00187de7,
                 .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-                .need_tda9887   = 1,
+                .tda9887_conf   = TDA9887_PRESENT,
                 .inputs         = {{
                         .name = name_tv,
                         .vmux = 1,
@@ -607,7 +625,6 @@ struct saa7134_board saa7134_boards[] = {
 			.vmux = 8,
 			.amux = LINE1,
 		}},
-		.i2s_rate  = 48000,
 		.has_ts    = 1,
 		.video_out = CCIR656,
 	},
@@ -666,7 +683,7 @@ struct saa7134_board saa7134_boards[] = {
 		.name           = "AverMedia M156 / Medion 2819",
 		.audio_clock    = 0x00187de7,
 		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-		.need_tda9887   = 1,
+		.tda9887_conf   = TDA9887_PRESENT,
 		.inputs         = {{
 			.name = name_tv,
 			.vmux = 1,
@@ -709,7 +726,6 @@ struct saa7134_board saa7134_boards[] = {
 			.amux = LINE2,
 			.tv   = 1,
 		}},
-		.i2s_rate  = 48000,
 		.has_ts    = 1,
 		.video_out = CCIR656,
         },
@@ -719,7 +735,7 @@ struct saa7134_board saa7134_boards[] = {
 		// probably wrong, the 7133 one is the NTSC version ...
 		// .tuner_type     = TUNER_PHILIPS_FM1236_MK3
                 .tuner_type     = TUNER_LG_NTSC_NEW_TAPC,
-                .need_tda9887   = 1,
+                .tda9887_conf   = TDA9887_PRESENT,
                 .inputs         = {{
                         .name = name_tv,
                         .vmux = 1,
@@ -743,7 +759,7 @@ struct saa7134_board saa7134_boards[] = {
                 .name           = "Pinnacle PCTV Stereo (saa7134)",
                 .audio_clock    = 0x00187de7,
                 .tuner_type     = TUNER_MT2032,
-                .need_tda9887   = 1,
+                .tda9887_conf   = TDA9887_PRESENT,
                 .inputs         = {{
                         .name = name_tv,
                         .vmux = 3,
@@ -957,7 +973,7 @@ struct saa7134_board saa7134_boards[] = {
 		.name           = "AverMedia 305",
 		.audio_clock    = 0x00187de7,
 		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-		.need_tda9887   = 1,
+		.tda9887_conf   = TDA9887_PRESENT,
 		.inputs         = {{
 			.name = name_tv,
 			.vmux = 1,
@@ -989,7 +1005,7 @@ struct saa7134_board saa7134_boards[] = {
   		.name           = "UPMOST PURPLE TV",
   		.audio_clock    = 0x00187de7,
   		.tuner_type     = TUNER_PHILIPS_FM1236_MK3,
-  		.need_tda9887   = 1,
+  		.tda9887_conf   = TDA9887_PRESENT,
   		.inputs         = {{
   			.name = name_tv,
   			.vmux = 7,
@@ -1000,7 +1016,7 @@ struct saa7134_board saa7134_boards[] = {
   			.vmux = 7,
   			.amux = LINE1,
   		}},
-          },
+	},
 	[SAA7134_BOARD_ITEMS_MTV005] = {
 		/* Norman Jonas <normanjonas@arcor.de> */
 		.name           = "Items MuchTV Plus / IT-005",
@@ -1025,6 +1041,56 @@ struct saa7134_board saa7134_boards[] = {
 			.amux = LINE2,
 		},
 	},
+	[SAA7134_BOARD_CINERGY200] = {
+		.name           = "Terratec Cinergy 200 TV",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.inputs         = {{
+       			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2,
+			.gpio = 0x0000,
+			.tv   = 1,
+		}},
+		.mute = {
+			 .name = name_mute,
+			 .amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_VIDEOMATE_TV_PVR] = {
+		/* Alain St-Denis <alain@topaze.homeip.net> */
+		.name           = "Compro VideoMate TV PVR/FM",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_NTSC_M,
+		.gpiomask	= 0x808c0080,
+                .inputs         = {{
+                        .name = name_svideo,
+                        .vmux = 8,
+                        .amux = LINE1,
+			.gpio = 0x00080
+                },{
+                        .name = name_comp1,
+                        .vmux = 3,
+                        .amux = LINE1,
+			.gpio = 0x00080
+                },{
+                        .name = name_tv,
+                        .vmux = 1,
+                        .amux = LINE2,
+                        .tv   = 1,
+			.gpio = 0x00080
+                }},
+		.radio = {
+			 .name = name_radio,
+			 .amux = LINE2,
+			.gpio = 0x80000
+		 },
+		.mute = {
+			.name = name_mute,
+                        .amux = LINE2,
+			.gpio = 0x40000,
+		},
+        },
 };
 const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
 
@@ -1086,6 +1152,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
 		.subvendor    = 0x5168,
 		.subdevice    = 0x0138,
 		.driver_data  = SAA7134_BOARD_FLYVIDEO2000,
+        },{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7135,
+		.subvendor    = 0x5168,
+		.subdevice    = 0x0212,
+		.driver_data  = SAA7134_BOARD_FLYTVPLATINUM,
         },{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -1219,6 +1291,19 @@ struct pci_device_id saa7134_pci_tbl[] = {
                 .subvendor    = 0x12ab,
                 .subdevice    = 0x0800,
  		.driver_data  = SAA7133_BOARD_UPMOST_PURPLE_TV,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x153B,
+		.subdevice    = 0x1152,
+		.driver_data  = SAA7134_BOARD_CINERGY200,
+
+ 	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+                .subvendor    = 0x185b,
+                .subdevice    = 0xc100,
+		.driver_data  = SAA7134_BOARD_VIDEOMATE_TV_PVR,
 		
  	},{
 		/* --- boards without eeprom + subsystem ID --- */
@@ -1297,6 +1382,7 @@ static struct {
 static void board_flyvideo(struct saa7134_dev *dev)
 {
 #if 0
+	/* non-working attempt to detect the correct tuner type ... */
 	u32 value;
 	int index;
 
@@ -1307,6 +1393,10 @@ static void board_flyvideo(struct saa7134_dev *dev)
 	       fly_list[index].tuner_type);
 	dev->tuner_type = fly_list[index].tuner_type;
 #endif
+	printk("%s: there are different flyvideo cards with different tuners\n"
+	       "%s: out there, you might have to use the tuner=<nr> insmod\n"
+	       "%s: option to override the default value.\n",
+	       dev->name, dev->name, dev->name);
 }
 
 /* ----------------------------------------------------------- */
@@ -1321,8 +1411,10 @@ int saa7134_board_init(struct saa7134_dev *dev)
 	switch (dev->board) {
 	case SAA7134_BOARD_FLYVIDEO2000:
 	case SAA7134_BOARD_FLYVIDEO3000:
-		board_flyvideo(dev);
 		dev->has_remote = 1;
+		/* fall throuth */
+	case SAA7134_BOARD_FLYTVPLATINUM:
+		board_flyvideo(dev);
 		break;
 	case SAA7134_BOARD_CINERGY400:
 	case SAA7134_BOARD_CINERGY600:
@@ -1333,6 +1425,12 @@ int saa7134_board_init(struct saa7134_dev *dev)
 	case SAA7134_BOARD_AVACSSMARTTV:
 		dev->has_remote = 1;
 		break;
+	case SAA7134_BOARD_MD5044:
+		printk("%s: seems there are two different versions of the MD5044\n"
+		       "%s: (with the same ID) out there.  If sound doesn't work for\n"
+		       "%s: you try the audio_clock_override=0x200000 insmod option.\n",
+		       dev->name,dev->name,dev->name);
+		break;
 	}
 	return 0;
 }
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index cf87dda32..d5cfa5d5e 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -868,7 +868,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
 		must_configure_manually();
 		dev->board = SAA7134_BOARD_UNKNOWN;
 	}
-	dev->tuner_type = saa7134_boards[dev->board].tuner_type;
+	dev->tuner_type   = saa7134_boards[dev->board].tuner_type;
+	dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf;
 	if (UNSET != tuner[saa7134_devcount])
 		dev->tuner_type = tuner[saa7134_devcount];
         printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
@@ -919,7 +920,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
 	/* load i2c helpers */
 	if (TUNER_ABSENT != dev->tuner_type)
 		request_module("tuner");
-	if (saa7134_boards[dev->board].need_tda9887)
+	if (dev->tda9887_conf)
 		request_module("tda9887");
   	if (card_has_ts(dev))
 		request_module("saa6752hs");
@@ -949,7 +950,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
 			       dev->name);
 			goto fail4;
 		}
-		printk(KERN_INFO "%s: registered device video%d [ts]\n",
+		printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
 		       dev->name,dev->ts_dev->minor & 0x1f);
 	}
 	
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
index 61305cf18..7dc44eaa4 100644
--- a/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/drivers/media/video/saa7134/saa7134-i2c.c
@@ -327,8 +327,10 @@ static int attach_inform(struct i2c_client *client)
 {
         struct saa7134_dev *dev = client->adapter->algo_data;
 	int tuner = dev->tuner_type;
+	int conf  = dev->tda9887_conf;
 
 	saa7134_i2c_call_clients(dev,TUNER_SET_TYPE,&tuner);
+	saa7134_i2c_call_clients(dev,TDA9887_SET_CONFIG,&conf);
         return 0;
 }
 
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index 63b32ab17..1066f4eb1 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -776,8 +776,6 @@ int saa7134_oss_init1(struct saa7134_dev *dev)
 	dev->oss.rate = 32000;
 	if (oss_rate)
 		dev->oss.rate = oss_rate;
-	if (saa7134_boards[dev->board].i2s_rate)
-		dev->oss.rate = saa7134_boards[dev->board].i2s_rate;
 	dev->oss.rate = (dev->oss.rate > 40000) ? 48000 : 32000;
 
 	/* mixer */
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
index 261d92040..bce58a247 100644
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -504,7 +504,8 @@ static int tvaudio_thread(void *data)
 		dprintk("tvaudio thread scan start [%d]\n",dev->thread.scan1);
 		dev->tvaudio  = NULL;
 		tvaudio_init(dev);
-		dev->automute = 1;
+		if (dev->ctl_automute)
+			dev->automute = 1;
 		mute_input_7134(dev);
 
 		/* give the tuner some time */
@@ -924,8 +925,9 @@ int saa7134_tvaudio_init2(struct saa7134_dev *dev)
 	int (*my_thread)(void *data) = NULL;
 
 	/* enable I2S audio output */
-	if (saa7134_boards[dev->board].i2s_rate) {
-		int i2sform = (32000 == saa7134_boards[dev->board].i2s_rate) ? 0x00 : 0x01;
+	if (saa7134_boards[dev->board].has_ts) {
+		int i2sform = (48000 == dev->oss.rate)
+			? 0x01 : 0x00;
 		
 		/* enable I2S output */
 		saa_writeb(SAA7134_I2S_OUTPUT_SELECT,  0x80); 
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index ec4c286df..0cd39439d 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -272,7 +272,8 @@ static struct saa7134_tvnorm tvnorms[] = {
 #define V4L2_CID_PRIVATE_INVERT      (V4L2_CID_PRIVATE_BASE + 0)
 #define V4L2_CID_PRIVATE_Y_ODD       (V4L2_CID_PRIVATE_BASE + 1)
 #define V4L2_CID_PRIVATE_Y_EVEN      (V4L2_CID_PRIVATE_BASE + 2)
-#define V4L2_CID_PRIVATE_LASTP1      (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_PRIVATE_AUTOMUTE    (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_PRIVATE_LASTP1      (V4L2_CID_PRIVATE_BASE + 4)
 
 static const struct v4l2_queryctrl no_ctrl = {
 	.name  = "42",
@@ -356,6 +357,13 @@ static const struct v4l2_queryctrl video_ctrls[] = {
 		.maximum       = 128,
 		.default_value = 0,
 		.type          = V4L2_CTRL_TYPE_INTEGER,
+	},{
+		.id            = V4L2_CID_PRIVATE_AUTOMUTE,
+		.name          = "automute",
+		.minimum       = 0,
+		.maximum       = 1,
+		.default_value = 1,
+		.type          = V4L2_CTRL_TYPE_BOOLEAN,
 	}
 };
 static const unsigned int CTRLS = ARRAY_SIZE(video_ctrls);
@@ -433,10 +441,11 @@ void res_free(struct saa7134_dev *dev, struct saa7134_fh *fh, unsigned int bits)
 
 static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
 {
-	int luma_control,sync_control,mux;
+	int luma_control,sync_control,mux,nosignal;
 
 	dprintk("set tv norm = %s\n",norm->name);
 	dev->tvnorm = norm;
+        nosignal = (0 == (saa_readb(SAA7134_STATUS_VIDEO1) & 0x03));
 
 	mux = card_in(dev,dev->ctl_input).vmux;
 	luma_control = norm->luma_control;
@@ -444,7 +453,7 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
 
 	if (mux > 5)
 		luma_control |= 0x80; /* svideo */
-	if (noninterlaced)
+	if (noninterlaced || nosignal)
 		sync_control |= 0x20;
 
 	/* setup cropping */
@@ -1043,6 +1052,9 @@ static int get_control(struct saa7134_dev *dev, struct v4l2_control *c)
 	case V4L2_CID_PRIVATE_Y_ODD:
 		c->value = dev->ctl_y_odd;
 		break;
+	case V4L2_CID_PRIVATE_AUTOMUTE:
+		c->value = dev->ctl_automute;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -1118,6 +1130,17 @@ static int set_control(struct saa7134_dev *dev, struct saa7134_fh *fh,
 		dev->ctl_y_odd = c->value;
 		restart_overlay = 1;
 		break;
+	case V4L2_CID_PRIVATE_AUTOMUTE:
+		dev->ctl_automute = c->value;
+		if (dev->tda9887_conf) {
+			if (dev->ctl_automute)
+				dev->tda9887_conf |= TDA9887_AUTOMUTE;
+			else
+				dev->tda9887_conf &= ~TDA9887_AUTOMUTE;
+			saa7134_i2c_call_clients(dev, TDA9887_SET_CONFIG,
+						 &dev->tda9887_conf);
+		}
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -1820,7 +1843,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
 		struct v4l2_frequency *f = arg;
 
 		memset(f,0,sizeof(*f));
-		f->type = V4L2_TUNER_ANALOG_TV;
+		f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
 		f->frequency = dev->ctl_freq;
 		return 0;
 	}
@@ -1830,7 +1853,9 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
 
 		if (0 != f->tuner)
 			return -EINVAL;
-		if (V4L2_TUNER_ANALOG_TV != f->type)
+		if (0 == fh->radio && V4L2_TUNER_ANALOG_TV != f->type)
+			return -EINVAL;
+		if (1 == fh->radio && V4L2_TUNER_RADIO != f->type)
 			return -EINVAL;
 		down(&dev->lock);
 		dev->ctl_freq = f->frequency;
@@ -2244,9 +2269,12 @@ int saa7134_video_init1(struct saa7134_dev *dev)
 	dev->ctl_hue        = ctrl_by_id(V4L2_CID_HUE)->default_value;
 	dev->ctl_saturation = ctrl_by_id(V4L2_CID_SATURATION)->default_value;
 	dev->ctl_volume     = ctrl_by_id(V4L2_CID_AUDIO_VOLUME)->default_value;
+	dev->ctl_mute       = ctrl_by_id(V4L2_CID_AUDIO_MUTE)->default_value;
+	dev->ctl_invert     = ctrl_by_id(V4L2_CID_PRIVATE_INVERT)->default_value;
+	dev->ctl_automute   = ctrl_by_id(V4L2_CID_PRIVATE_AUTOMUTE)->default_value;
 
-	dev->ctl_invert     = 0;
-	dev->ctl_mute       = 1;
+	if (dev->tda9887_conf && dev->ctl_automute)
+		dev->tda9887_conf |= TDA9887_AUTOMUTE;
 	dev->automute       = 0;
 
         INIT_LIST_HEAD(&dev->video_q.queue);
@@ -2300,10 +2328,14 @@ void saa7134_irq_video_intl(struct saa7134_dev *dev)
 	if (0 != norm) {
 		/* wake up tvaudio audio carrier scan thread */
 		saa7134_tvaudio_do_scan(dev);
+		if (!noninterlaced)
+			saa_clearb(SAA7134_SYNC_CTRL, 0x20);
 	} else {
 		/* no video signal -> mute audio */
-		dev->automute = 1;
+		if (dev->ctl_automute)
+			dev->automute = 1;
 		saa7134_tvaudio_setmute(dev);
+		saa_setb(SAA7134_SYNC_CTRL, 0x20);
 	}
 }
 
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index f4d346949..b6d738274 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -156,6 +156,9 @@ struct saa7134_format {
 #define SAA7134_BOARD_AVERMEDIA_305    35
 #define SAA7133_BOARD_UPMOST_PURPLE_TV 36
 #define SAA7134_BOARD_ITEMS_MTV005     37
+#define SAA7134_BOARD_CINERGY200       38
+#define SAA7134_BOARD_FLYTVPLATINUM    39
+#define SAA7134_BOARD_VIDEOMATE_TV_PVR 40
 
 #define SAA7134_INPUT_MAX 8
 
@@ -178,13 +181,12 @@ struct saa7134_board {
 	struct saa7134_input    mute;
 	
 	/* peripheral I/O */
-	unsigned int            i2s_rate;
 	unsigned int            has_ts;
 	enum saa7134_video_out  video_out;
 
 	/* i2c chip info */
 	unsigned int            tuner_type;
-	unsigned int            need_tda9887:1;
+	unsigned int            tda9887_conf;
 };
 
 #define card_has_radio(dev)   (NULL != saa7134_boards[dev->board].radio.name)
@@ -362,6 +364,7 @@ struct saa7134_dev {
 	/* config info */
 	unsigned int               board;
 	unsigned int               tuner_type;
+	unsigned int               tda9887_conf;
 	unsigned int               gpio_value;
 
 	/* i2c i/o */
@@ -397,6 +400,7 @@ struct saa7134_dev {
 	int                        ctl_mirror;
 	int                        ctl_y_odd;
 	int                        ctl_y_even;
+	int                        ctl_automute;
 
 	/* crop */
 	struct v4l2_rect           crop_bounds;
diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c
index 4365d9485..20051a00c 100644
--- a/drivers/media/video/tda7432.c
+++ b/drivers/media/video/tda7432.c
@@ -532,17 +532,17 @@ static struct i2c_client client_template =
 	.driver     = &driver, 
 };
 
-static int tda7432_init(void)
+static int __init tda7432_init(void)
 {
 	if ( (loudness < 0) || (loudness > 15) ) {
 		printk(KERN_ERR "tda7432: loudness parameter must be between 0 and 15\n");
 		return -EINVAL;
 	}
-	i2c_add_driver(&driver);
-	return 0;
+
+	return i2c_add_driver(&driver);
 }
 
-static void tda7432_fini(void)
+static void __exit tda7432_fini(void)
 {
 	i2c_del_driver(&driver);
 }
diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
index ae5fd316f..41327c3f7 100644
--- a/drivers/media/video/tda9875.c
+++ b/drivers/media/video/tda9875.c
@@ -403,13 +403,12 @@ static struct i2c_client client_template =
         .driver    = &driver,
 };
 
-static int tda9875_init(void)
+static int __init tda9875_init(void)
 {
-	i2c_add_driver(&driver);
-	return 0;
+	return i2c_add_driver(&driver);
 }
 
-static void tda9875_fini(void)
+static void __exit tda9875_fini(void)
 {
 	i2c_del_driver(&driver);
 }
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index 9768829bd..e46fbdbc4 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -8,6 +8,7 @@
 #include <linux/slab.h>
 
 #include <media/audiochip.h>
+#include <media/tuner.h>
 #include <media/id.h>
 
 /* Chips:
@@ -47,6 +48,7 @@ struct tda9887 {
 	struct i2c_client  client;
 	v4l2_std_id        std;
 	unsigned int       radio;
+	unsigned int       config;
 	unsigned int       pinnacle_id;
 	unsigned int       using_v4l2;
 };
@@ -397,6 +399,36 @@ static int tda9887_set_insmod(struct tda9887 *t, char *buf)
 	return 0;
 }
 
+static int tda9887_set_config(struct tda9887 *t, char *buf)
+{
+	if (t->config & TDA9887_PORT1)
+		buf[1] |= cOutputPort1Inactive;
+	if (t->config & TDA9887_PORT2)
+		buf[1] |= cOutputPort2Inactive;
+	if (t->config & TDA9887_QSS)
+		buf[1] |= cQSS;
+	if (t->config & TDA9887_INTERCARRIER)
+		buf[1] &= ~cQSS;
+
+	if (t->config & TDA9887_AUTOMUTE)
+		buf[1] |= cAutoMuteFmActive;
+	if (t->config & TDA9887_DEEMPHASIS_MASK) {
+		buf[2] &= ~0x60;
+		switch (t->config & TDA9887_DEEMPHASIS_MASK) {
+		case TDA9887_DEEMPHASIS_NONE:
+			buf[2] |= cDeemphasisOFF;
+			break;
+		case TDA9887_DEEMPHASIS_50:
+			buf[2] |= cDeemphasisON | cDeemphasis50;
+			break;
+		case TDA9887_DEEMPHASIS_75:
+			buf[2] |= cDeemphasisON | cDeemphasis75;
+			break;
+		}
+	}
+	return 0;
+}
+
 /* ---------------------------------------------------------------------- */
 
 static int tda9887_set_pinnacle(struct tda9887 *t, char *buf)
@@ -499,6 +531,7 @@ static int tda9887_configure(struct tda9887 *t)
 	if (UNSET != t->pinnacle_id) {
 		tda9887_set_pinnacle(t,buf);
 	}
+	tda9887_set_config(t,buf);
 	tda9887_set_insmod(t,buf);
 
 	dprintk(PREFIX "writing: b=0x%02x c=0x%02x e=0x%02x\n",
@@ -594,6 +627,14 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
 		tda9887_configure(t);
 		break;
 	}
+	case TDA9887_SET_CONFIG:
+	{
+		int *i = arg;
+
+		t->config = *i;
+		tda9887_configure(t);
+		break;
+	}
 	/* --- v4l ioctls --- */
 	/* take care: bttv does userspace copying, we'll get a
 	   kernel pointer here... */
@@ -644,6 +685,25 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
 			t->radio = 1;
 		}
 		tda9887_configure(t);
+		break;
+	}
+	case VIDIOC_G_TUNER:
+	{
+		static int AFC_BITS_2_kHz[] = {
+			-12500,  -37500,  -62500,  -97500,
+			-112500, -137500, -162500, -187500,
+			187500,  162500,  137500,  112500,
+			97500 ,  62500,   37500 ,  12500
+		};
+		struct v4l2_tuner* tuner = arg;
+
+		if (t->radio) {
+			__u8 reg = 0;
+			tuner->afc=0;
+			if (1 == i2c_master_recv(&t->client,&reg,1))
+				tuner->afc = AFC_BITS_2_kHz[(reg>>1)&0x0f];
+		}
+		break;
 	}
 	default:
 		/* nothing */
@@ -670,13 +730,12 @@ static struct i2c_client client_template =
         .driver    = &driver,
 };
 
-static int tda9887_init_module(void)
+static int __init tda9887_init_module(void)
 {
-	i2c_add_driver(&driver);
-	return 0;
+	return i2c_add_driver(&driver);
 }
 
-static void tda9887_cleanup_module(void)
+static void __exit tda9887_cleanup_module(void)
 {
 	i2c_del_driver(&driver);
 }
diff --git a/drivers/media/video/tuner.c b/drivers/media/video/tuner.c
index 18e1118df..bac17a3dc 100644
--- a/drivers/media/video/tuner.c
+++ b/drivers/media/video/tuner.c
@@ -208,7 +208,7 @@ static struct tunertype tuners[] = {
 	{ "Temic PAL* auto + FM (4009 FN5)", TEMIC, PAL,
 	  16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
 	{ "SHARP NTSC_JP (2U5JF5540)", SHARP, NTSC, /* 940=16*58.75 NTSC@Japan */
-	  16*137.25,16*317.25,0x01,0x02,0x08,0x8e,732 }, // Corrected to NTSC=732 (was:940)
+	  16*137.25,16*317.25,0x01,0x02,0x08,0x8e,940 },
 
 	{ "Samsung PAL TCPM9091PD27", Samsung, PAL,  /* from sourceforge v3tv */
           16*169,16*464,0xA0,0x90,0x30,0x8e,623},
@@ -229,7 +229,7 @@ static struct tunertype tuners[] = {
           16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,732},
 
 	{ "HITACHI V7-J180AT", HITACHI, NTSC,
-	  16*170.00, 16*450.00, 0x01,0x02,0x00,0x8e,940 },
+	  16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,940 },
 	{ "Philips PAL_MK (FI1216 MK)", Philips, PAL,
 	  16*140.25,16*463.25,0x01,0xc2,0xcf,0x8e,623},
 	{ "Philips 1236D ATSC/NTSC daul in",Philips,ATSC,
@@ -241,6 +241,13 @@ static struct tunertype tuners[] = {
           16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732},
 	{ "Microtune 4049 FM5",Microtune,PAL,
 	  16*141.00,16*464.00,0xa0,0x90,0x30,0x8e,623},
+	{ "Panasonic VP27s/ENGE4324D", Panasonic, NTSC,
+	  16*160.00,16*454.00,0x01,0x02,0x08,0xce,940},
+        { "LG NTSC (TAPE series)", LGINNOTEK, NTSC,
+          16*170.00, 16*450.00, 0x01,0x02,0x04,0x8e,732 },
+
+        { "Tenna TNF 8831 BGFF)", Philips, PAL,
+          16*161.25,16*463.25,0xa0,0x90,0x30,0x8e,623},
 
 };
 #define TUNERS ARRAY_SIZE(tuners)
@@ -934,6 +941,9 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
 	case TUNER_PHILIPS_FM1236_MK3:
 		buffer[3] = 0x19;
 		break;
+	case TUNER_LG_PAL_FM:
+		buffer[3] = 0xa5;
+		break;
 	default:
 		buffer[3] = 0xa4;
 		break;
@@ -1300,13 +1310,12 @@ static struct i2c_client client_template =
         .driver     = &driver,
 };
 
-static int tuner_init_module(void)
+static int __init tuner_init_module(void)
 {
-	i2c_add_driver(&driver);
-	return 0;
+	return i2c_add_driver(&driver);
 }
 
-static void tuner_cleanup_module(void)
+static void __exit tuner_cleanup_module(void)
 {
 	i2c_del_driver(&driver);
 }
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index bf5017a77..b435bcef9 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -1651,7 +1651,7 @@ static struct i2c_client client_template =
         .driver     = &driver,
 };
 
-static int audiochip_init_module(void)
+static int __init audiochip_init_module(void)
 {
 	struct CHIPDESC  *desc;
 	printk(KERN_INFO "tvaudio: TV audio decoder + audio/video mux driver\n");
@@ -1659,11 +1659,11 @@ static int audiochip_init_module(void)
 	for (desc = chiplist; desc->name != NULL; desc++)
 		printk("%s%s", (desc == chiplist) ? "" : ",",desc->name);
 	printk("\n");
-	i2c_add_driver(&driver);
-	return 0;
+
+	return i2c_add_driver(&driver);
 }
 
-static void audiochip_cleanup_module(void)
+static void __exit audiochip_cleanup_module(void)
 {
 	i2c_del_driver(&driver);
 }
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
index 48b2f822e..20cb7647f 100644
--- a/drivers/media/video/tvmixer.c
+++ b/drivers/media/video/tvmixer.c
@@ -330,17 +330,17 @@ static int tvmixer_clients(struct i2c_client *client)
 
 /* ----------------------------------------------------------------------- */
 
-static int tvmixer_init_module(void)
+static int __init tvmixer_init_module(void)
 {
 	int i;
 	
 	for (i = 0; i < DEV_MAX; i++)
 		devices[i].minor = -1;
-	i2c_add_driver(&driver);
-	return 0;
+
+	return i2c_add_driver(&driver);
 }
 
-static void tvmixer_cleanup_module(void)
+static void __exit tvmixer_cleanup_module(void)
 {
 	int i;
 	
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index fbc5cb1e2..9d4c74f25 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -254,7 +254,7 @@ int video_exclusive_release(struct inode *inode, struct file *file)
 	return 0;
 }
 
-extern struct file_operations video_fops;
+static struct file_operations video_fops;
 
 /**
  *	video_register_device - register video4linux devices
diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c
index 705cff870..a35d518e2 100644
--- a/drivers/media/video/zoran_device.c
+++ b/drivers/media/video/zoran_device.c
@@ -1105,8 +1105,7 @@ zr36057_enable_jpg (struct zoran          *zr,
 			ZR36057_ISR);
 		btand(~ZR36057_JMC_Go_en, ZR36057_JMC);	// \Go_en
 
-		current->state = TASK_UNINTERRUPTIBLE;
-		schedule_timeout(HZ / 20);
+		msleep(50);
 
 		set_videobus_dir(zr, 0);
 		set_frame(zr, 1);	// /FRAME
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
index 28f1a8d05..d6294bd79 100644
--- a/drivers/media/video/zoran_driver.c
+++ b/drivers/media/video/zoran_driver.c
@@ -2265,8 +2265,8 @@ zoran_do_ioctl (struct inode *inode,
 
 		dprintk(3,
 			KERN_DEBUG
-			"%s: VIDIOCSFBUF - base=0x%x, w=%d, h=%d, depth=%d, bpl=%d\n",
-			ZR_DEVNAME(zr), (u32) vbuf->base, vbuf->width,
+			"%s: VIDIOCSFBUF - base=%p, w=%d, h=%d, depth=%d, bpl=%d\n",
+			ZR_DEVNAME(zr), vbuf->base, vbuf->width,
 			vbuf->height, vbuf->depth, vbuf->bytesperline);
 
 		for (i = 0; i < zoran_num_formats; i++)
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig
index aa1c657dd..070abf63d 100644
--- a/drivers/message/fusion/Kconfig
+++ b/drivers/message/fusion/Kconfig
@@ -27,39 +27,6 @@ config FUSION_MAX_SGE
 	  necessary (or recommended) unless the user will be running 
 	  large I/O's via the raw interface.
 
-config FUSION_ISENSE
-	tristate "Enhanced SCSI error reporting"
-	depends on MODULES && FUSION && m
-	---help---
-	  The isense module (roughly stands for Interpret SENSE data) is
-	  completely optional.  It simply provides extra English readable
-	  strings in SCSI Error Report(s) that might be generated from the
-	  Fusion MPT SCSI Host driver, for example when a target device
-	  returns a SCSI check condition on a I/O.  Without this module
-	  loaded you might see:
-
-	  SCSI Error Report =-=-= (ioc0,scsi5:0)
-	  SCSI_Status=02h (CHECK_CONDITION)
-	  Original_CDB[]: 2A 00 00 00 00 41 00 00 02 00
-	  SenseData[12h]: 70 00 02 00 00 00 00 0A 00 00 00 00 04 02 02 00 00 00
-	  SenseKey=2h (NOT READY); FRU=02h
-	  ASC/ASCQ=29h/00h
-
-	  Where otherwise, if this module had been loaded, you would see:
-
-	  SCSI Error Report =-=-= (ioc0,scsi5:0)
-	  SCSI_Status=02h (CHECK_CONDITION)
-	  Original_CDB[]: 2A 00 00 00 00 41 00 00 02 00 - "WRITE(10)"
-	  SenseData[12h]: 70 00 02 00 00 00 00 0A 00 00 00 00 04 02 02 00 00 00
-	  SenseKey=2h (NOT READY); FRU=02h
-	  ASC/ASCQ=29h/00h "LOGICAL UNIT NOT READY, INITIALIZING CMD. REQUIRED"
-
-	  Say M for "Enhanced SCSI error reporting" to compile this optional module,
-	  creating a driver named: isense.
-
-	  NOTE: Support for building this feature into the kernel is not
-	  available, due to kernel size considerations.
-
 config FUSION_CTL
 	tristate "Fusion MPT misc device (ioctl) driver"
 	depends on MODULES && FUSION && m
diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile
index b709839fe..f6fdcaaef 100644
--- a/drivers/message/fusion/Makefile
+++ b/drivers/message/fusion/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the LSI Logic Fusion MPT (Message Passing Technology) drivers.
 #
 # Note! If you want to turn on various debug defines for an extended period of
-# time but don't want them lingering around in the Makefile when you pass it on 
+# time but don't want them lingering around in the Makefile when you pass it on
 # to someone else, use the MPT_CFLAGS env variable (thanks Steve). -nromer
 
 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-{ LSI_LOGIC
@@ -48,6 +48,5 @@ EXTRA_CFLAGS += ${MPT_CFLAGS}
 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC
 
 obj-$(CONFIG_FUSION)		+= mptbase.o mptscsih.o
-obj-$(CONFIG_FUSION_ISENSE)	+= isense.o
 obj-$(CONFIG_FUSION_CTL)	+= mptctl.o
 obj-$(CONFIG_FUSION_LAN)	+= mptlan.o
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 75c07f89e..70a44c9d2 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -139,11 +139,6 @@ struct proc_dir_entry *mpt_proc_root_dir;
 
 DmpServices_t *DmpService;
 
-void *mpt_v_ASCQ_TablePtr;
-const char **mpt_ScsiOpcodesPtr;
-int mpt_ASCQ_TableSz;
-
-
 #define WHOINIT_UNKNOWN		0xAA
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -165,7 +160,6 @@ static struct mpt_pci_driver 	*MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS]
 static int	FusionInitCalled = 0;
 static int	mpt_base_index = -1;
 static int	last_drv_idx = -1;
-static int	isense_idx = -1;
 
 static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq);
 
@@ -177,8 +171,8 @@ static irqreturn_t mpt_interrupt(int irq, void *bus_id, struct pt_regs *r);
 static int	mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply);
 
 static int	mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag);
-static void	mpt_detect_bound_ports(MPT_ADAPTER *this, struct pci_dev *pdev);
-static void	mpt_adapter_disable(MPT_ADAPTER *ioc, int freeup);
+static void	mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev);
+static void	mpt_adapter_disable(MPT_ADAPTER *ioc);
 static void	mpt_adapter_dispose(MPT_ADAPTER *ioc);
 
 static void	MptDisplayIocCapabilities(MPT_ADAPTER *ioc);
@@ -291,7 +285,7 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
 	int		 type;
 	int		 freeme;
 
-	ioc = bus_id;
+	ioc = (MPT_ADAPTER *)bus_id;
 
 	/*
 	 *  Drain the reply FIFO!
@@ -333,8 +327,8 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
 			cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx;
 			mf = MPT_INDEX_2_MFPTR(ioc, req_idx);
 
-			dprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p\n",
-					ioc->name, mr));
+			dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x\n",
+					ioc->name, mr, req_idx));
 			DBG_DUMP_REPLY_FRAME(mr)
 
 			/* NEW!  20010301 -sralston
@@ -358,7 +352,7 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
 			/*
 			 *  Process turbo (context) reply...
 			 */
-			dirqprintk((MYIOC_s_INFO_FMT "Got TURBO reply(=%08x)\n", ioc->name, pa));
+			dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n", ioc->name, pa));
 			type = (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT);
 			if (type == MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET) {
 				cb_idx = mpt_stm_index;
@@ -506,7 +500,7 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
 		results = ProcessEventNotification(ioc, pEvReply, &evHandlers);
 		if (results != evHandlers) {
 			/* CHECKME! Any special handling needed here? */
-			dprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
+			devtprintk((MYIOC_s_WARN_FMT "Called %d event handlers, sum results = %d\n",
 					ioc->name, evHandlers, results));
 		}
 
@@ -659,8 +653,6 @@ mpt_deregister(int cb_idx)
 		MptEvHandlers[cb_idx] = NULL;
 
 		last_drv_idx++;
-		if (isense_idx != -1 && isense_idx <= cb_idx)
-			isense_idx++;
 	}
 }
 
@@ -803,56 +795,60 @@ mpt_device_driver_deregister(int cb_idx)
  *	mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024)
  *	allocated per MPT adapter.
  *	@handle: Handle of registered MPT protocol driver
- *	@iocid: IOC unique identifier (integer)
+ *	@ioc: Pointer to MPT adapter structure
  *
  *	Returns pointer to a MPT request frame or %NULL if none are available
  *	or IOC is not active.
  */
 MPT_FRAME_HDR*
-mpt_get_msg_frame(int handle, MPT_ADAPTER *iocp)
+mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
 {
 	MPT_FRAME_HDR *mf;
 	unsigned long flags;
+	u16	 req_idx;	/* Request index */
+
+	/* validate handle and ioc identifier */
 
 #ifdef MFCNT
-	if (!iocp->active)
+	if (!ioc->active)
 		printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n");
 #endif
 
 	/* If interrupts are not attached, do not return a request frame */
-	if (!iocp->active)
+	if (!ioc->active)
 		return NULL;
 
-	spin_lock_irqsave(&iocp->FreeQlock, flags);
-	if (! Q_IS_EMPTY(&iocp->FreeQ)) {
+	spin_lock_irqsave(&ioc->FreeQlock, flags);
+	if (! Q_IS_EMPTY(&ioc->FreeQ)) {
 		int req_offset;
 
-		mf = iocp->FreeQ.head;
+		mf = ioc->FreeQ.head;
 		Q_DEL_ITEM(&mf->u.frame.linkage);
 		mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;	/* byte */
-		req_offset = (u8 *)mf - (u8 *)iocp->req_frames;
+		req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
 								/* u16! */
-		mf->u.frame.hwhdr.msgctxu.fld.req_idx =
-				cpu_to_le16(req_offset / iocp->req_sz);
+		req_idx = cpu_to_le16(req_offset / ioc->req_sz);
+		mf->u.frame.hwhdr.msgctxu.fld.req_idx = req_idx;
 		mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
+		ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */
 #ifdef MFCNT
-		iocp->mfcnt++;
+		ioc->mfcnt++;
 #endif
 	}
 	else
 		mf = NULL;
-	spin_unlock_irqrestore(&iocp->FreeQlock, flags);
+	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
 #ifdef MFCNT
 	if (mf == NULL)
-		printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", iocp->mfcnt, iocp->req_depth);
+		printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", ioc->mfcnt, ioc->req_depth);
 	mfcounter++;
 	if (mfcounter == PRINT_MF_COUNT)
-		printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", iocp->mfcnt, iocp->req_depth);
+		printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", ioc->mfcnt, ioc->req_depth);
 #endif
 
 	dmfprintk((KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n",
-			iocp->name, handle, iocid, mf));
+			ioc->name, handle, ioc->id, mf));
 	return mf;
 }
 
@@ -861,23 +857,25 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *iocp)
  *	mpt_put_msg_frame - Send a protocol specific MPT request frame
  *	to a IOC.
  *	@handle: Handle of registered MPT protocol driver
- *	@iocid: IOC unique identifier (integer)
+ *	@ioc: Pointer to MPT adapter structure
  *	@mf: Pointer to MPT request frame
  *
  *	This routine posts a MPT request frame to the request post FIFO of a
  *	specific MPT adapter.
  */
 void
-mpt_put_msg_frame(int handle, MPT_ADAPTER *iocp, MPT_FRAME_HDR *mf)
+mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
 {
 	u32 mf_dma_addr;
 	int req_offset;
+	u16	 req_idx;	/* Request index */
 
 	/* ensure values are reset properly! */
 	mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;		/* byte */
-	req_offset = (u8 *)mf - (u8 *)iocp->req_frames;
-									/* u16! */
-	mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_offset / iocp->req_sz);
+	req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
+								/* u16! */
+	req_idx = cpu_to_le16(req_offset / ioc->req_sz);
+	mf->u.frame.hwhdr.msgctxu.fld.req_idx = req_idx;
 	mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
 
 #ifdef MPT_DEBUG_MSG_FRAME
@@ -886,8 +884,8 @@ mpt_put_msg_frame(int handle, MPT_ADAPTER *iocp, MPT_FRAME_HDR *mf)
 		int	 ii, n;
 
 		printk(KERN_INFO MYNAM ": %s: About to Put msg frame @ %p:\n" KERN_INFO " ",
-				iocp->name, m);
-		n = iocp->req_sz/4 - 1;
+				ioc->name, m);
+		n = ioc->req_sz/4 - 1;
 		while (m[n] == 0)
 			n--;
 		for (ii=0; ii<=n; ii++) {
@@ -899,32 +897,33 @@ mpt_put_msg_frame(int handle, MPT_ADAPTER *iocp, MPT_FRAME_HDR *mf)
 	}
 #endif
 
-	mf_dma_addr = iocp->req_frames_low_dma + req_offset;
-	CHIPREG_WRITE32(&iocp->chip->RequestFifo, mf_dma_addr);
+	mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];  
+	dsgprintk((MYIOC_s_INFO_FMT "mf_dma_addr=%x req_idx=%d RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx, ioc->RequestNB[req_idx]));
+	CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *	mpt_free_msg_frame - Place MPT request frame back on FreeQ.
  *	@handle: Handle of registered MPT protocol driver
- *	@iocid: IOC unique identifier (integer)
+ *	@ioc: Pointer to MPT adapter structure
  *	@mf: Pointer to MPT request frame
  *
  *	This routine places a MPT request frame back on the MPT adapter's
  *	FreeQ.
  */
 void
-mpt_free_msg_frame(int handle, MPT_ADAPTER *iocp, MPT_FRAME_HDR *mf)
+mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
 {
 	unsigned long flags;
 
 	/*  Put Request back on FreeQ!  */
-	spin_lock_irqsave(&iocp->FreeQlock, flags);
-	Q_ADD_TAIL(&iocp->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
+	spin_lock_irqsave(&ioc->FreeQlock, flags);
+	Q_ADD_TAIL(&ioc->FreeQ, &mf->u.frame.linkage, MPT_FRAME_HDR);
 #ifdef MFCNT
-	iocp->mfcnt--;
+	ioc->mfcnt--;
 #endif
-	spin_unlock_irqrestore(&iocp->FreeQlock, flags);
+	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -996,7 +995,7 @@ mpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
  *	mpt_send_handshake_request - Send MPT request via doorbell
  *	handshake method.
  *	@handle: Handle of registered MPT protocol driver
- *	@iocid: IOC unique identifier (integer)
+ *	@ioc: Pointer to MPT adapter structure
  *	@reqBytes: Size of the request in bytes
  *	@req: Pointer to MPT request frame
  *	@sleepFlag: Use schedule if CAN_SLEEP else use udelay.
@@ -1010,7 +1009,7 @@ mpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
  *	Returns 0 for success, non-zero for failure.
  */
 int
-mpt_send_handshake_request(int handle, MPT_ADAPTER *iocp, int reqBytes, u32 *req, int sleepFlag)
+mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag)
 {
 	int		 r = 0;
 	u8	*req_as_bytes;
@@ -1026,37 +1025,38 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *iocp, int reqBytes, u32 *req
 	 * setting cb_idx/req_idx.  But ONLY if this request
 	 * is in proper (pre-alloc'd) request buffer range...
 	 */
-	ii = MFPTR_2_MPT_INDEX(iocp,(MPT_FRAME_HDR*)req);
-	if (reqBytes >= 12 && ii >= 0 && ii < iocp->req_depth) {
+	ii = MFPTR_2_MPT_INDEX(ioc,(MPT_FRAME_HDR*)req);
+	if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) {
 		MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req;
 		mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii);
 		mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;
 	}
 
 	/* Make sure there are no doorbells */
-	CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
-	CHIPREG_WRITE32(&iocp->chip->Doorbell,
+	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+	
+	CHIPREG_WRITE32(&ioc->chip->Doorbell,
 			((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
 			 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
 
 	/* Wait for IOC doorbell int */
-	ii = WaitForDoorbellInt(iocp, 5, sleepFlag);
-	if (ii < 0)
+	if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
 		return ii;
+	}
 
 	/* Read doorbell and check for active bit */
-	if (!(CHIPREG_READ32(&iocp->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
+	if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
 		return -5;
 
 	dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
-			iocp->name, ii));
+			ioc->name, ii));
 
-	CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
+	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
 
-	r = WaitForDoorbellAck(iocp, 5, sleepFlag);
-	if (r < 0)
+	if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
 		return -2;
-
+	}
+		
 	/* Send request via doorbell handshake */
 	req_as_bytes = (u8 *) req;
 	for (ii = 0; ii < reqBytes/4; ii++) {
@@ -1066,21 +1066,21 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *iocp, int reqBytes, u32 *req
 			(req_as_bytes[(ii*4) + 1] <<  8) |
 			(req_as_bytes[(ii*4) + 2] << 16) |
 			(req_as_bytes[(ii*4) + 3] << 24));
-		CHIPREG_WRITE32(&iocp->chip->Doorbell, word);
-		r = WaitForDoorbellAck(iocp, 5, sleepFlag);
-		if (r < 0) {
+		CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
+		if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
 			r = -3;
 			break;
 		}
 	}
 
-	if (r >= 0 && WaitForDoorbellInt(iocp, 10, sleepFlag) >= 0)
+	if (r >= 0 && WaitForDoorbellInt(ioc, 10, sleepFlag) >= 0)
 		r = 0;
 	else
 		r = -4;
 
 	/* Make sure there are no doorbells */
-	CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
+	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+	
 	return r;
 }
 
@@ -1141,11 +1141,15 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	u8		 revision;
 	u8		 pcixcmd;
 	static int	 mpt_ids = 0;
+#ifdef CONFIG_PROC_FS
 	struct proc_dir_entry *dent, *ent;
+#endif
 
 	if (pci_enable_device(pdev))
 		return r;
 	
+	dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));
+	
 	if (!pci_set_dma_mask(pdev, mask)) {
 		dprintk((KERN_INFO MYNAM
 			": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
@@ -1170,9 +1174,8 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	ioc->alloc_total = sizeof(MPT_ADAPTER);
 	ioc->req_sz = MPT_DEFAULT_FRAME_SIZE;		/* avoid div by zero! */
 	ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
-
+	
 	ioc->pcidev = pdev;
-
 	ioc->diagPending = 0;
 	spin_lock_init(&ioc->diagLock);
 
@@ -1223,8 +1226,8 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		return -EINVAL;
 	}
 
-	dprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
-	dprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
+	dinitprintk((KERN_INFO MYNAM ": MPT adapter @ %lx, msize=%dd bytes\n", mem_phys, msize));
+	dinitprintk((KERN_INFO MYNAM ": (port i/o @ %lx, psize=%dd bytes)\n", port, psize));
 
 	mem = NULL;
 	/* Get logical ptr for PciMem0 space */
@@ -1236,15 +1239,15 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		return -EINVAL;
 	}
 	ioc->memmap = mem;
-	dprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
+	dinitprintk((KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys));
 
-	dprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
+	dinitprintk((KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n",
 			&ioc->facts, &ioc->pfacts[0]));
 
 	ioc->mem_phys = mem_phys;
 	ioc->chip = (SYSIF_REGS*)mem;
 
-	/* Save Port IO values incase we need to do downloadboot */
+	/* Save Port IO values in case we need to do downloadboot */
 	{
 		u8 *pmem = (u8*)port;
 		ioc->pio_mem_phys = port;
@@ -1314,7 +1317,6 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
 	sprintf(ioc->name, "ioc%d", ioc->id);
 
-	Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR);
 	spin_lock_init(&ioc->FreeQlock);
 
 	/* Disable all! */
@@ -1337,7 +1339,6 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 			printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n",
 					ioc->name, __irq_itoa(pdev->irq));
 #endif
-			Q_DEL_ITEM(ioc);
 			list_del(&ioc->list);
 			iounmap(mem);
 			kfree(ioc);
@@ -1369,7 +1370,6 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		  ": WARNING - %s did not initialize properly! (%d)\n",
 		  ioc->name, r);
 
-		Q_DEL_ITEM(ioc);
 		list_del(&ioc->list);
 		free_irq(ioc->pci_irq, ioc);
 		iounmap(mem);
@@ -1386,6 +1386,7 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		}
 	}
 
+#ifdef CONFIG_PROC_FS
 	/*
 	 *  Create "/proc/mpt/iocN" subdirectory entry for each MPT adapter.
 	 */
@@ -1402,6 +1403,7 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 			ent->data = ioc;
 		}
 	}
+#endif
 
 	return 0;
 }
@@ -1625,7 +1627,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
 	int	 hard_reset_done = 0;
 	int	 alt_ioc_ready = 0;
 	int	 hard;
-	int	 r;
+	int	 rc=0;
 	int	 ii;
 	int	 handlers;
 	int	 ret = 0;
@@ -1675,39 +1677,37 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
 	 * and 1 if a hard reset was performed.
 	 */
 	if (hard_reset_done && reset_alt_ioc_active && ioc->alt_ioc) {
-		if ((r = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
+		if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0)
 			alt_ioc_ready = 1;
 		else
 			printk(KERN_WARNING MYNAM
-					": alt-%s: (%d) Not ready WARNING!\n",
-					ioc->alt_ioc->name, r);
+					": alt-%s: Not ready WARNING!\n",
+					ioc->alt_ioc->name);
 	}
 
 	for (ii=0; ii<5; ii++) {
-		/* Get IOC facts! Allow 1 retry */
-		if ((r = GetIocFacts(ioc, sleepFlag, reason)) != 0) {
-			dinitprintk((MYIOC_s_INFO_FMT 
-			     "ii=%d IocFacts failed r=%x\n", ioc->name, ii, r));
-		} else
+		/* Get IOC facts! Allow 5 retries */
+		if ((rc = GetIocFacts(ioc, sleepFlag, reason)) == 0)
 			break;
 	}
+	
 
-	if (r) {
-		dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed r=%x\n", ioc->name, r));
+	if (ii == 5) {
+		dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc));
 		ret = -2;
 	} else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
 		MptDisplayIocCapabilities(ioc);
 	}
-
+	
 	if (alt_ioc_ready) {
-		if ((r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
-			dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed r=%x\n", ioc->name, r));
+		if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
+			dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc));
 			/* Retry - alt IOC was initialized once
 			 */
-			r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
+			rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
 		}
-		if (r) {
-			dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed r=%x\n", ioc->name, r));
+		if (rc) {
+			dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc));
 			alt_ioc_ready = 0;
 			reset_alt_ioc_active = 0;
 		} else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
@@ -1720,29 +1720,29 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
 	 * init as upper addresses are needed for init.
 	 * If fails, continue with alt-ioc processing
 	 */
-	if ((ret == 0) && ((r = PrimeIocFifos(ioc)) != 0))
+	if ((ret == 0) && ((rc = PrimeIocFifos(ioc)) != 0))
 		ret = -3;
 
 	/* May need to check/upload firmware & data here!
 	 * If fails, continue with alt-ioc processing
 	 */
-	if ((ret == 0) && ((r = SendIocInit(ioc, sleepFlag)) != 0))
+	if ((ret == 0) && ((rc = SendIocInit(ioc, sleepFlag)) != 0))
 		ret = -4;
 // NEW!
-	if (alt_ioc_ready && ((r = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
+	if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) {
 		printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n",
-				ioc->alt_ioc->name, r);
+				ioc->alt_ioc->name, rc);
 		alt_ioc_ready = 0;
 		reset_alt_ioc_active = 0;
 	}
 
 	if (alt_ioc_ready) {
-		if ((r = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
+		if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) {
 			alt_ioc_ready = 0;
 			reset_alt_ioc_active = 0;
 			printk(KERN_WARNING MYNAM
 				": alt-%s: (%d) init failure WARNING!\n",
-					ioc->alt_ioc->name, r);
+					ioc->alt_ioc->name, rc);
 		}
 	}
 
@@ -1754,18 +1754,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
 			/* Controller is not operational, cannot do upload
 			 */
 			if (ret == 0) {
-				r = mpt_do_upload(ioc, sleepFlag);
-				if (r != 0)
-					printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
-			}
-
-			/* Handle the alt IOC too */
-			if ((alt_ioc_ready) && (ioc->alt_ioc->upload_fw)){
-				ddlprintk((MYIOC_s_INFO_FMT
-					"Alt-ioc firmware upload required!\n",
-					ioc->name));
-				r = mpt_do_upload(ioc->alt_ioc, sleepFlag);
-				if (r != 0)
+				rc = mpt_do_upload(ioc, sleepFlag);
+				if (rc != 0)
 					printk(KERN_WARNING MYNAM ": firmware upload failure!\n");
 			}
 		}
@@ -1859,19 +1849,19 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
 	 * MptResetHandlers[] registered yet.
 	 */
 	if (hard_reset_done) {
-		r = handlers = 0;
+		rc = handlers = 0;
 		for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
 			if ((ret == 0) && MptResetHandlers[ii]) {
 				dprintk((MYIOC_s_INFO_FMT "Calling IOC post_reset handler #%d\n",
 						ioc->name, ii));
-				r += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
+				rc += (*(MptResetHandlers[ii]))(ioc, MPT_IOC_POST_RESET);
 				handlers++;
 			}
 
 			if (alt_ioc_ready && MptResetHandlers[ii]) {
 				dprintk((MYIOC_s_INFO_FMT "Calling alt-%s post_reset handler #%d\n",
 						ioc->name, ioc->alt_ioc->name, ii));
-				r += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
+				rc += (*(MptResetHandlers[ii]))(ioc->alt_ioc, MPT_IOC_POST_RESET);
 				handlers++;
 			}
 		}
@@ -1932,84 +1922,90 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
 /*
  *	mpt_adapter_disable - Disable misbehaving MPT adapter.
  *	@this: Pointer to MPT adapter structure
- *	@free: Free up alloc'd reply, request, etc.
  */
 static void
-mpt_adapter_disable(MPT_ADAPTER *this, int freeup)
+mpt_adapter_disable(MPT_ADAPTER *ioc)
 {
-	if (this != NULL) {
-		int sz=0;
-		int ret;
-
-		if (this->cached_fw != NULL) {
-			ddlprintk((KERN_INFO MYNAM ": Pushing FW onto adapter\n"));
+	int sz;
+	int ret;
 
-			if ((ret = mpt_downloadboot(this, NO_SLEEP)) < 0) {
-				printk(KERN_WARNING MYNAM
-					": firmware downloadboot failure (%d)!\n", ret);
-			}
+	if (ioc->cached_fw != NULL) {
+		ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n"));
+		if ((ret = mpt_downloadboot(ioc, NO_SLEEP)) < 0) {
+			printk(KERN_WARNING MYNAM
+				": firmware downloadboot failure (%d)!\n", ret);
 		}
+	}
 
-		/* Disable adapter interrupts! */
-		CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF);
-		this->active = 0;
-		/* Clear any lingering interrupt */
-		CHIPREG_WRITE32(&this->chip->IntStatus, 0);
-
-		if (freeup && this->fifo_pool != NULL) {
-			pci_free_consistent(this->pcidev,
-				this->fifo_pool_sz,
-				this->fifo_pool, this->fifo_pool_dma);
-			this->reply_frames = NULL;
-			this->reply_alloc = NULL;
-			this->req_frames = NULL;
-			this->req_alloc = NULL;
-			this->chain_alloc = NULL;
-			this->fifo_pool = NULL;
-			this->alloc_total -= this->fifo_pool_sz;
-		}
-		if (freeup && this->sense_buf_pool != NULL) {
-			sz = (this->req_depth * MPT_SENSE_BUFFER_ALLOC);
-			pci_free_consistent(this->pcidev, sz,
-					this->sense_buf_pool, this->sense_buf_pool_dma);
-			this->sense_buf_pool = NULL;
-			this->alloc_total -= sz;
-		}
+	/* Disable adapter interrupts! */
+	CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
+	ioc->active = 0;
+	/* Clear any lingering interrupt */
+	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
 
-		if (freeup && this->events != NULL){
-			sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
-			kfree(this->events);
-			this->events = NULL;
-			this->alloc_total -= sz;
-		}
+	if (ioc->alloc != NULL) {
+		sz = ioc->alloc_sz;
+		dexitprintk((KERN_INFO MYNAM ": %s.free  @ %p, sz=%d bytes\n",
+		 	ioc->name, ioc->alloc, ioc->alloc_sz));
+		pci_free_consistent(ioc->pcidev, sz,
+				ioc->alloc, ioc->alloc_dma);
+		ioc->reply_frames = NULL;
+		ioc->req_frames = NULL;
+		ioc->alloc = NULL;
+		ioc->alloc_total -= sz;
+	}
 
-		if (freeup && this->cached_fw != NULL) {
+	if (ioc->sense_buf_pool != NULL) {
+		sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
+		pci_free_consistent(ioc->pcidev, sz,
+				ioc->sense_buf_pool, ioc->sense_buf_pool_dma);
+		ioc->sense_buf_pool = NULL;
+		ioc->alloc_total -= sz;
+	}
 
-			sz = this->facts.FWImageSize;
-			pci_free_consistent(this->pcidev, sz,
-				this->cached_fw, this->cached_fw_dma);
-			this->cached_fw = NULL;
-			this->alloc_total -= sz;
-		}
+	if (ioc->events != NULL){
+		sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS);
+		kfree(ioc->events);
+		ioc->events = NULL;
+		ioc->alloc_total -= sz;
+	}
 
-		if (freeup && this->spi_data.nvram != NULL) {
-			kfree(this->spi_data.nvram);
-			this->spi_data.nvram = NULL;
-		}
+	if (ioc->cached_fw != NULL) {
+		sz = ioc->facts.FWImageSize;
+		pci_free_consistent(ioc->pcidev, sz,
+			ioc->cached_fw, ioc->cached_fw_dma);
+		ioc->cached_fw = NULL;
+		ioc->alloc_total -= sz;
+	}
 
-		if (freeup && this->spi_data.pIocPg3 != NULL) {
-			kfree(this->spi_data.pIocPg3);
-			this->spi_data.pIocPg3 = NULL;
-		}
+	if (ioc->spi_data.nvram != NULL) {
+		kfree(ioc->spi_data.nvram);
+		ioc->spi_data.nvram = NULL;
+	}
 
-		if (freeup && this->spi_data.pIocPg4 != NULL) {
-			sz = this->spi_data.IocPg4Sz;
-			pci_free_consistent(this->pcidev, sz,
-				this->spi_data.pIocPg4,
-				this->spi_data.IocPg4_dma);
-			this->spi_data.pIocPg4 = NULL;
-			this->alloc_total -= sz;
-		}
+	if (ioc->spi_data.pIocPg3 != NULL) {
+		kfree(ioc->spi_data.pIocPg3);
+		ioc->spi_data.pIocPg3 = NULL;
+	}
+
+	if (ioc->spi_data.pIocPg4 != NULL) {
+		sz = ioc->spi_data.IocPg4Sz;
+		pci_free_consistent(ioc->pcidev, sz, 
+			ioc->spi_data.pIocPg4,
+			ioc->spi_data.IocPg4_dma);
+		ioc->spi_data.pIocPg4 = NULL;
+		ioc->alloc_total -= sz;
+	}
+
+	if (ioc->ReqToChain != NULL) {
+		kfree(ioc->ReqToChain);
+		kfree(ioc->RequestNB);
+		ioc->ReqToChain = NULL;
+	}
+
+	if (ioc->ChainToChain != NULL) {
+		kfree(ioc->ChainToChain);
+		ioc->ChainToChain = NULL;
 	}
 }
 
@@ -2017,43 +2013,43 @@ mpt_adapter_disable(MPT_ADAPTER *this, int freeup)
 /*
  *	mpt_adapter_dispose - Free all resources associated with a MPT
  *	adapter.
- *	@this: Pointer to MPT adapter structure
+ *	@ioc: Pointer to MPT adapter structure
  *
  *	This routine unregisters h/w resources and frees all alloc'd memory
  *	associated with a MPT adapter structure.
  */
 static void
-mpt_adapter_dispose(MPT_ADAPTER *this)
+mpt_adapter_dispose(MPT_ADAPTER *ioc)
 {
-	if (this != NULL) {
+	if (ioc != NULL) {
 		int sz_first, sz_last;
 
-		sz_first = this->alloc_total;
+		sz_first = ioc->alloc_total;
 
-		mpt_adapter_disable(this, 1);
+		mpt_adapter_disable(ioc);
 
-		if (this->pci_irq != -1) {
-			free_irq(this->pci_irq, this);
-			this->pci_irq = -1;
+		if (ioc->pci_irq != -1) {
+			free_irq(ioc->pci_irq, ioc);
+			ioc->pci_irq = -1;
 		}
 
-		if (this->memmap != NULL)
-			iounmap((u8 *) this->memmap);
+		if (ioc->memmap != NULL)
+			iounmap((u8 *) ioc->memmap);
 
 #if defined(CONFIG_MTRR) && 0
-		if (this->mtrr_reg > 0) {
-			mtrr_del(this->mtrr_reg, 0, 0);
-			dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", this->name));
+		if (ioc->mtrr_reg > 0) {
+			mtrr_del(ioc->mtrr_reg, 0, 0);
+			dprintk((KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name));
 		}
 #endif
 
 		/*  Zap the adapter lookup ptr!  */
-		list_del(&this->list);
+		list_del(&ioc->list);
 
-		sz_last = this->alloc_total;
+		sz_last = ioc->alloc_total;
 		dprintk((KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n",
-				this->name, sz_first-sz_last+(int)sizeof(*this), sz_first));
-		kfree(this);
+				ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first));
+		kfree(ioc);
 	}
 }
 
@@ -2228,13 +2224,13 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag)
 		ii++; cntdn--;
 		if (!cntdn) {
 			printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n",
-					ioc->name, (ii+5)/HZ);
+					ioc->name, (int)((ii+5)/HZ));
 			return -ETIME;
 		}
 
 		if (sleepFlag == CAN_SLEEP) {
 			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
+			schedule_timeout(1 * HZ / 1000);
 		} else {
 			mdelay (1);	/* 1 msec delay */
 		}
@@ -2292,7 +2288,9 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
 	int			 r;
 	int			 req_sz;
 	int			 reply_sz;
-	u32			 status;
+	int			 sz;
+	u32			 status, vv;
+	u8			 shiftFactor=1;
 
 	/* IOC *must* NOT be in RESET state! */
 	if (ioc->last_state == MPI_IOC_STATE_RESET) {
@@ -2315,7 +2313,9 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
 	get_facts.Function = MPI_FUNCTION_IOC_FACTS;
 	/* Assert: All other get_facts fields are zero! */
 
-	dinitprintk((MYIOC_s_INFO_FMT "Sending get IocFacts request\n", ioc->name));
+	dinitprintk((MYIOC_s_INFO_FMT 
+	    "Sending get IocFacts request req_sz=%d reply_sz=%d\n", 
+	    ioc->name, req_sz, reply_sz));
 
 	/* No non-zero fields in the get_facts request are greater than
 	 * 1 byte in size, so we can just fire it off as is.
@@ -2388,6 +2388,13 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
 			facts->FWImageSize = le32_to_cpu(facts->FWImageSize);
 		}
 
+		sz = facts->FWImageSize;
+		if ( sz & 0x01 )
+			sz += 1;
+		if ( sz & 0x02 )
+			sz += 2;
+		facts->FWImageSize = sz;
+		
 		if (!facts->RequestFrameSize) {
 			/*  Something is wrong!  */
 			printk(MYIOC_s_ERR_FMT "IOC reported invalid 0 request size!\n",
@@ -2395,6 +2402,18 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
 			return -55;
 		}
 
+		r = sz = le32_to_cpu(facts->BlockSize);
+		vv = ((63 / (sz * 4)) + 1) & 0x03;
+		ioc->NB_for_64_byte_frame = vv;
+		while ( sz )
+		{
+			shiftFactor++;
+			sz = sz >> 1;
+		}
+		ioc->NBShiftFactor  = shiftFactor;
+		dinitprintk((MYIOC_s_INFO_FMT "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n",
+					ioc->name, vv, shiftFactor, r));
+    
 		if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
 			/*
 			 * Set values for this IOC's request & reply frame sizes,
@@ -2405,9 +2424,9 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
 			ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
 			ioc->reply_depth = min_t(int, MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth);
 
-			dprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
+			dinitprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n",
 				ioc->name, ioc->reply_sz, ioc->reply_depth));
-			dprintk((MYIOC_s_INFO_FMT "req_sz  =%3d, req_depth  =%4d\n",
+			dinitprintk((MYIOC_s_INFO_FMT "req_sz  =%3d, req_depth  =%4d\n",
 				ioc->name, ioc->req_sz, ioc->req_depth));
 
 			/* Get port facts! */
@@ -2416,7 +2435,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
 		}
 	} else {
 		printk(MYIOC_s_ERR_FMT 
-		     "Invalid IOC facts reply, msgLength=%d offsetof=%d!\n",
+		     "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
 		     ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
 		     RequestFrameSize)/sizeof(u32)));
 		return -66;
@@ -2465,7 +2484,7 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
 	get_pfacts.PortNumber = portnum;
 	/* Assert: All other get_pfacts fields are zero! */
 
-	dprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
+	dinitprintk((MYIOC_s_INFO_FMT "Sending get PortFacts(%d) request\n",
 			ioc->name, portnum));
 
 	/* No non-zero fields in the get_pfacts request are greater than
@@ -2516,24 +2535,18 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
 	memset(&init_reply, 0, sizeof(init_reply));
 
 	ioc_init.WhoInit = MPI_WHOINIT_HOST_DRIVER;
-/*	ioc_init.ChainOffset = 0;			*/
 	ioc_init.Function = MPI_FUNCTION_IOC_INIT;
-/*	ioc_init.Flags = 0;				*/
 
 	/* If we are in a recovery mode and we uploaded the FW image,
 	 * then this pointer is not NULL. Skip the upload a second time.
 	 * Set this flag if cached_fw set for either IOC.
 	 */
-	ioc->upload_fw = 0;
-	ioc_init.Flags = 0;
-	if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) {
-		if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw))
-			ioc_init.Flags = MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE;
-		else
-			ioc->upload_fw = 1;
-	}
-	ddlprintk((MYIOC_s_INFO_FMT "flags %d, upload_fw %d \n",
-		   ioc->name, ioc_init.Flags, ioc->upload_fw));
+	if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)
+		ioc->upload_fw = 1;
+	else
+		ioc->upload_fw = 0;
+	ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n",
+		   ioc->name, ioc->upload_fw, ioc->facts.Flags));
 
 	if ((int)ioc->chip_type <= (int)FC929) {
 		ioc_init.MaxDevices = MPT_MAX_FC_DEVICES;
@@ -2542,17 +2555,13 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
 	}
 	ioc_init.MaxBuses = MPT_MAX_BUS;
 
-/*	ioc_init.MsgFlags = 0;				*/
-/*	ioc_init.MsgContext = cpu_to_le32(0x00000000);	*/
 	ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz);	/* in BYTES */
-		
-	ioc->facts.RequestFrameSize = ioc_init.ReplyFrameSize;
 
 	if (sizeof(dma_addr_t) == sizeof(u64)) {
 		/* Save the upper 32-bits of the request
 		 * (reply) and sense buffers.
 		 */
-		ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->req_frames_dma >> 32));
+		ioc_init.HostMfaHighAddr = cpu_to_le32((u32)((u64)ioc->alloc_dma >> 32));
 		ioc_init.SenseBufferHighAddr = cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32));
 	} else {
 		/* Force 32-bit addressing */
@@ -2591,14 +2600,14 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag)
 	while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
 		if (sleepFlag == CAN_SLEEP) {
 			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
+			schedule_timeout(1 * HZ / 1000);
 		} else {
 			mdelay(1);
 		}
 
 		if (!cntdn) {
 			printk(MYIOC_s_ERR_FMT "Wait IOC_OP state timeout(%d)!\n",
-					ioc->name, (count+5)/HZ);
+					ioc->name, (int)((count+5)/HZ));
 			return -9;
 		}
 
@@ -2644,7 +2653,7 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
 /*	port_enable.MsgFlags = 0;		*/
 /*	port_enable.MsgContext = 0;		*/
 
-	dprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
+	dinitprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
 			ioc->name, portnum, &port_enable));
 
 	/* RAID FW may take a long time to enable
@@ -2668,20 +2677,22 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag)
 }
 
 /*
- * Inputs: size - total FW bytes
- * Outputs: frags - number of fragments needed
- * Return NULL if failed.
+ *	ioc: Pointer to MPT_ADAPTER structure
+ *      size - total FW bytes
  */
 void
 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
 {
-	/* cached_fw
-	 */
-
-	if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
-		ioc->alloc_total += size;
+	if (ioc->cached_fw)
+		return;  /* use already allocated memory */
+	if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) {
+		ioc->cached_fw = ioc->alt_ioc->cached_fw;  /* use alt_ioc's memory */
+		ioc->cached_fw_dma = ioc->alt_ioc->cached_fw_dma;
+	} else {
+		if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
+			ioc->alloc_total += size;
+	}
 }
-
 /*
  * If alt_img is NULL, delete from ioc structure.
  * Else, delete a secondary image in same format.
@@ -2692,6 +2703,8 @@ mpt_free_fw_memory(MPT_ADAPTER *ioc)
 	int sz;
 
 	sz = ioc->facts.FWImageSize;
+	dinitprintk((KERN_WARNING MYNAM "free_fw_memory: FW Image  @ %p[%p], sz=%d[%x] bytes\n",
+		 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
 	pci_free_consistent(ioc->pcidev, sz,
 			ioc->cached_fw, ioc->cached_fw_dma);
 	ioc->cached_fw = NULL;
@@ -2725,30 +2738,24 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
 	int			 sgeoffset;
 	u32			 flagsLength;
 	int			 ii, sz, reply_sz;
-	int			 cmdStatus, freeMem = 0;
+	int			 cmdStatus;
 
-	/* If the image size is 0 or if the pointer is
-	 * not NULL (error), we are done.
+	/* If the image size is 0, we are done.
 	 */
-	if (((sz = ioc->facts.FWImageSize) == 0) || ioc->cached_fw)
+	if ((sz = ioc->facts.FWImageSize) == 0)
 		return 0;
 
-	if ( sz & 0x01 )
-		sz += 1;
-	if ( sz & 0x02 )
-		sz += 2;
-
 	mpt_alloc_fw_memory(ioc, sz);
 
+	dinitprintk((KERN_WARNING MYNAM ": FW Image  @ %p[%p], sz=%d[%x] bytes\n",
+		 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
+	
 	if (ioc->cached_fw == NULL) {
 		/* Major Failure.
 		 */
 		return -ENOMEM;
 	}
 
-	dinitprintk((KERN_WARNING MYNAM ": FW Image  @ %p[%p], sz=%d[%x] bytes\n",
-		 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
-
 	prequest = (FWUpload_t *)&request;
 	preply = (FWUploadReply_t *)&reply;
 
@@ -2797,23 +2804,11 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag)
 	dinitprintk((MYIOC_s_INFO_FMT ": do_upload status %d \n",
 			ioc->name, cmdStatus));
 
-	/* Check to see if we have a copy of this image in
-	 * host memory already.
-	 */
-	if (cmdStatus == 0) {
-		ioc->upload_fw = 0;
-		if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
-			freeMem = 1;
-	}
-
-	/* We already have a copy of this image or
-	 * we had some type of an error  - either the handshake
-	 * failed (i != 0) or the command did not complete successfully.
-	 */
-	if (cmdStatus || freeMem) {
+	
+	if (cmdStatus) {
 
-		ddlprintk((MYIOC_s_INFO_FMT ": do_upload freeing %s image \n",
-			ioc->name, cmdStatus ? "incomplete" : "duplicate"));
+		ddlprintk((MYIOC_s_INFO_FMT ": fw upload failed, freeing image \n",
+			ioc->name));
 		mpt_free_fw_memory(ioc);
 	}
 
@@ -2841,28 +2836,26 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
 	MpiExtImageHeader_t	*pExtImage;
 	u32			 fwSize;
 	u32			 diag0val;
-#ifdef MPT_DEBUG
-	u32			 diag1val = 0;
-#endif
-	int			 count = 0;
+	int			 count;
 	u32			*ptrFw;
 	u32			 diagRwData;
 	u32			 nextImage;
 	u32			 load_addr;
-	u32 			 ioc_state;
+	u32 			 ioc_state=0;
 
 	ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x, ioc FW Ptr %p\n",
 				ioc->name, ioc->facts.FWImageSize, ioc->cached_fw));
 
-	/* Get dma_addr and data transfer size.
-	 */
 	if ( ioc->facts.FWImageSize == 0 )
 		return -1;
 
-	/* Get the DMA from ioc or ioc->alt_ioc */
 	if (ioc->cached_fw == NULL)
 		return -2;
 
+	/* prevent a second downloadboot and memory free with alt_ioc */
+	if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
+		ioc->alt_ioc->cached_fw = NULL;
+	
 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
@@ -2870,18 +2863,17 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
 
-	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-	diag0val |= (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM);
-	CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
+	CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
 
-	/* wait 100 msec */
+	/* wait 1 msec */
 	if (sleepFlag == CAN_SLEEP) {
 		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(100 * HZ / 1000);
+		schedule_timeout(1 * HZ / 1000);
 	} else {
-		mdelay (100);
+		mdelay (1);
 	}
 
+	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
 	CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
 
 	for (count = 0; count < 30; count ++) {
@@ -2894,7 +2886,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
 		/* wait 1 sec */
 		if (sleepFlag == CAN_SLEEP) {
 			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(HZ);
+			schedule_timeout(1000 * HZ / 1000);
 		} else {
 			mdelay (1000);
 		}
@@ -2914,8 +2906,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
 
 	/* Set the DiagRwEn and Disable ARM bits */
-	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-	CHIPREG_WRITE32(&ioc->chip->Diagnostic, (diag0val | MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
+	CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
 
 	pFwHeader = (MpiFwHeader_t *) ioc->cached_fw;
 	fwSize = (pFwHeader->ImageSize + 3)/4;
@@ -2961,15 +2952,6 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
 	ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
 	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
 
-	/* clear the PREVENT_IOC_BOOT bit */
-	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-	ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT\n",
-		ioc->name, diag0val));
-	diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT);
-	ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
-		ioc->name, diag0val));
-	CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
-
 	/* Clear the internal flash bad bit - autoincrementing register,
 	 * so must do two writes.
 	 */
@@ -2980,28 +2962,13 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
 	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
 
 	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-	ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off DISABLE_ARM, RW_ENABLE, RESET_HISTORY\n",
+	ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT, DISABLE_ARM\n",
 		ioc->name, diag0val));
-	diag0val &= ~(MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE | MPI_DIAG_RESET_HISTORY);
+	diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM);
 	ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
 		ioc->name, diag0val));
 	CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
 
-	/* wait 100 msec */
-	if (sleepFlag == CAN_SLEEP) {
-		ddlprintk((MYIOC_s_INFO_FMT "CAN_SLEEP 100 msec before reset the sequencer\n", ioc->name));
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(100 * HZ / 1000);
-	} else {
-		ddlprintk((MYIOC_s_INFO_FMT "mdelay 100 msec before reset the sequencer\n", ioc->name));
-		mdelay (100);
-	}
-
-	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-	if ( diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_DISABLE_ARM) ) {
-		ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed, diag0val=%x FLASH_BAD_SIG | DISABLE_ARM on\n ",
-			ioc->name, diag0val));
-	}
 	/* Write 0xFF to reset the sequencer */
 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
 
@@ -3009,26 +2976,18 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
 		if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
 			ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n",
 					ioc->name, count, ioc_state));
-/*			if ((r = GetIocFacts(ioc, sleepFlag, MPT_HOSTEVENT_IOC_BRINGUP)) != 0) {
-				if ((r = GetIocFacts(ioc, sleepFlag, MPT_HOSTEVENT_IOC_BRINGUP)) != 0) {
-					ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed\n",
-						ioc->name));
-						return -EFAULT;
-				}
-			} */
-			/* wait 2 sec */
-/*			if (sleepFlag == CAN_SLEEP) {
-				set_current_state(TASK_INTERRUPTIBLE);
-				schedule_timeout(5000 * HZ / 1000);
-			} else {
-				mdelay (5000);
-			} */
-
+			if ((SendIocInit(ioc, sleepFlag)) != 0) {
+				ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n",
+					ioc->name));
+				return -EFAULT;
+			}
+			ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit successful\n",
+					ioc->name));
 			return 0;
 		}
 		if (sleepFlag == CAN_SLEEP) {
 			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
+			schedule_timeout(10 * HZ / 1000);
 		} else {
 			mdelay (10);
 		}
@@ -3068,8 +3027,8 @@ static int
 KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
 {
 	int hard_reset_done = 0;
-	u32 ioc_state;
-	int cntdn, cnt = 0;
+	u32 ioc_state=0;
+	int cnt,cntdn;
 
 	dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
 	if ((int)ioc->chip_type > (int)FC929) {
@@ -3080,7 +3039,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
 
 		if (sleepFlag == CAN_SLEEP) {
 			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(HZ);
+			schedule_timeout(1000 * HZ / 1000);
 		} else {
 			mdelay (1000);
 		}
@@ -3090,26 +3049,27 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag)
 	if (hard_reset_done < 0)
 		return hard_reset_done;
 
-	dprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
+	dinitprintk((MYIOC_s_INFO_FMT "Diagnostic reset successful!\n",
 			ioc->name));
 
-	cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 20;	/* 20 seconds */
+	cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2;	/* 2 seconds */
 	for (cnt=0; cnt<cntdn; cnt++) {
-		if ((ioc_state = mpt_GetIocState(ioc, 1)) == MPI_IOC_STATE_READY) {
-			dprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
-					ioc->name, cnt));
+		ioc_state = mpt_GetIocState(ioc, 1);
+		if ((ioc_state == MPI_IOC_STATE_READY) || (ioc_state == MPI_IOC_STATE_OPERATIONAL)) {
+			dinitprintk((MYIOC_s_INFO_FMT "KickStart successful! (cnt=%d)\n",
+ 					ioc->name, cnt));
 			return hard_reset_done;
 		}
 		if (sleepFlag == CAN_SLEEP) {
 			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
+			schedule_timeout(10 * HZ / 1000);
 		} else {
 			mdelay (10);
 		}
 	}
 
-	printk(MYIOC_s_ERR_FMT "Failed to come READY after reset!\n",
-			ioc->name);
+	printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n",
+			ioc->name, ioc_state);
 	return -1;
 }
 
@@ -3199,12 +3159,6 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
 		dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n",
 				ioc->name, diag0val, diag1val));
 #endif
-		/* Write the PreventIocBoot bit */
-		if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw)) {
-			diag0val |= MPI_DIAG_PREVENT_IOC_BOOT;
-			CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
-		}
-
 		/*
 		 * Disable the ARM (Bug fix)
 		 *
@@ -3246,20 +3200,13 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
 			/* FIXME?  Examine results here? */
 		}
 
-		if ((ioc->cached_fw) || (ioc->alt_ioc && ioc->alt_ioc->cached_fw)) {
+		if (ioc->cached_fw) {
 			/* If the DownloadBoot operation fails, the
 			 * IOC will be left unusable. This is a fatal error
 			 * case.  _diag_reset will return < 0
 			 */
 			for (count = 0; count < 30; count ++) {
 				diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-#ifdef MPT_DEBUG
-				if (ioc->alt_ioc)
-					diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
-				dprintk((MYIOC_s_INFO_FMT
-					"DbG2b: diag0=%08x, diag1=%08x\n",
-					ioc->name, diag0val, diag1val));
-#endif
 				if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
 					break;
 				}
@@ -3267,7 +3214,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
 				/* wait 1 sec */
 				if (sleepFlag == CAN_SLEEP) {
 					set_current_state(TASK_INTERRUPTIBLE);
-					schedule_timeout(HZ);
+					schedule_timeout(1000 * HZ / 1000);
 				} else {
 					mdelay (1000);
 				}
@@ -3295,7 +3242,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag)
 				/* wait 1 sec */
 				if (sleepFlag == CAN_SLEEP) {
 					set_current_state(TASK_INTERRUPTIBLE);
-					schedule_timeout(HZ);
+					schedule_timeout(1000 * HZ / 1000);
 				} else {
 					mdelay (1000);
 				}
@@ -3419,13 +3366,13 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
 				count *= 10;
 
 			printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n",
-					ioc->name, (count+5)/HZ);
+					ioc->name, (int)((count+5)/HZ));
 			return -ETIME;
 		}
 
 		if (sleepFlag == CAN_SLEEP) {
 			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
+			schedule_timeout(1 * HZ / 1000);
 		} else {
 			mdelay (1);	/* 1 msec delay */
 		}
@@ -3443,35 +3390,45 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *	PrimeIocFifos - Initialize IOC request and reply FIFOs.
- *	@ioc: Pointer to MPT_ADAPTER structure
- *
- *	This routine allocates memory for the MPT reply and request frame
- *	pools (if necessary), and primes the IOC reply FIFO with
- *	reply frames.
- *
- *	Returns 0 for success, non-zero for failure.
+ *	initChainBuffers - Allocate memory for and initialize
+ *	chain buffers, chain buffer control arrays and spinlock.
+ *	@hd: Pointer to MPT_SCSI_HOST structure
+ *	@init: If set, initialize the spin lock.
  */
 static int
-PrimeIocFifos(MPT_ADAPTER *ioc)
+initChainBuffers(MPT_ADAPTER *ioc)
 {
-	MPT_FRAME_HDR *mf;
-	unsigned long b;
-	unsigned long flags;
-	dma_addr_t aligned_mem_dma;
-	u8 *aligned_mem;
-	int i, sz;
-	int chain_buffer_sz, reply_buffer_sz, request_buffer_sz;
-	int scale, num_sge, num_chain;
+	u8		*mem;
+	int		sz, ii, num_chain;
+	int 		scale, num_sge, numSGE;
 
-	/* request buffer size,  rounding UP to nearest 4-kB boundary */
-	request_buffer_sz = (ioc->req_sz * ioc->req_depth) + 128;
-	request_buffer_sz = ((request_buffer_sz + 0x1000UL - 1UL) / 0x1000) * 0x1000;
+	/* ReqToChain size must equal the req_depth
+	 * index = req_idx
+	 */
+	if (ioc->ReqToChain == NULL) {
+		sz = ioc->req_depth * sizeof(int);
+		mem = kmalloc(sz, GFP_ATOMIC);
+		if (mem == NULL)
+			return -1;
+
+		ioc->ReqToChain = (int *) mem;
+		dinitprintk((KERN_INFO MYNAM ": %s ReqToChain alloc  @ %p, sz=%d bytes\n",
+			 	ioc->name, mem, sz));
+		mem = kmalloc(sz, GFP_ATOMIC);
+		if (mem == NULL)
+			return -1;
 
-	/* reply buffer size */
-	reply_buffer_sz = (ioc->reply_sz * ioc->reply_depth) + 128;
+		ioc->RequestNB = (int *) mem;
+		dinitprintk((KERN_INFO MYNAM ": %s RequestNB alloc  @ %p, sz=%d bytes\n",
+			 	ioc->name, mem, sz));
+	}
+	for (ii = 0; ii < ioc->req_depth; ii++) {
+		ioc->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
+	}
 
-	/* chain buffer size, copied from from mptscsih_initChainBuffers()
+	/* ChainToChain size must equal the total number
+	 * of chain buffers to be allocated.
+	 * index = chain_idx
 	 *
 	 * Calculate the number of chain buffers needed(plus 1) per I/O
 	 * then multiply the the maximum number of simultaneous cmds
@@ -3479,79 +3436,134 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
 	 * num_sge = num sge in request frame + last chain buffer
 	 * scale = num sge per chain buffer if no chain element
 	 */
-
 	scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
 	if (sizeof(dma_addr_t) == sizeof(u64))
 		num_sge =  scale + (ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
 	else
-		num_sge =  1 + scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
+		num_sge =  1+ scale + (ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
+
+	if (sizeof(dma_addr_t) == sizeof(u64)) {
+		numSGE = (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
+			(ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
+	} else {
+		numSGE = 1 + (scale - 1) * (ioc->facts.MaxChainDepth-1) + scale +
+			(ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
+	}
+	dinitprintk((KERN_INFO MYNAM ": %s num_sge=%d numSGE=%d\n",
+		ioc->name, num_sge, numSGE));
+
+	if ( numSGE > MPT_SCSI_SG_DEPTH	)
+		numSGE = MPT_SCSI_SG_DEPTH;
 
 	num_chain = 1;
-	while (MPT_SCSI_SG_DEPTH - num_sge > 0) {
+	while (numSGE - num_sge > 0) {
 		num_chain++;
 		num_sge += (scale - 1);
 	}
 	num_chain++;
 
-	if ((int)ioc->chip_type > (int) FC929)
+	dinitprintk((KERN_INFO MYNAM ": %s Now numSGE=%d num_sge=%d num_chain=%d\n",
+		ioc->name, numSGE, num_sge, num_chain));
+
+	if ((int) ioc->chip_type > (int) FC929)
 		num_chain *= MPT_SCSI_CAN_QUEUE;
 	else
 		num_chain *= MPT_FC_CAN_QUEUE;
 
-	chain_buffer_sz = num_chain * ioc->req_sz;
+	ioc->num_chain = num_chain;
 
-	if(ioc->fifo_pool == NULL) {
+	sz = num_chain * sizeof(int);
+	if (ioc->ChainToChain == NULL) {
+		mem = kmalloc(sz, GFP_ATOMIC);
+		if (mem == NULL)
+			return -1;
 
-		ioc->fifo_pool_sz = request_buffer_sz +
-			reply_buffer_sz + chain_buffer_sz;
+		ioc->ChainToChain = (int *) mem;
+		dinitprintk((KERN_INFO MYNAM ": %s ChainToChain alloc @ %p, sz=%d bytes\n",
+			 	ioc->name, mem, sz));
+	} else {
+		mem = (u8 *) ioc->ChainToChain;
+	}
+	memset(mem, 0xFF, sz);
+	return num_chain;
+}
 
-		ioc->fifo_pool = pci_alloc_consistent(ioc->pcidev,
-		ioc->fifo_pool_sz, &ioc->fifo_pool_dma);
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	PrimeIocFifos - Initialize IOC request and reply FIFOs.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *
+ *	This routine allocates memory for the MPT reply and request frame
+ *	pools (if necessary), and primes the IOC reply FIFO with
+ *	reply frames.
+ *
+ *	Returns 0 for success, non-zero for failure.
+ */
+static int
+PrimeIocFifos(MPT_ADAPTER *ioc)
+{
+	MPT_FRAME_HDR *mf;
+	unsigned long flags;
+	dma_addr_t alloc_dma;
+	u8 *mem;
+	int i, reply_sz, sz, total_size, num_chain;
+
+	/*  Prime reply FIFO...  */
 
-		if( ioc->fifo_pool == NULL)
+	if (ioc->reply_frames == NULL) {
+		if ( (num_chain = initChainBuffers(ioc)) < 0)
+			return -1;
+
+		total_size = reply_sz = (ioc->reply_sz * ioc->reply_depth);
+		dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d bytes, ReplyDepth=%d\n",
+			 	ioc->name, ioc->reply_sz, ioc->reply_depth));
+		dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffer sz=%d[%x] bytes\n",
+			 	ioc->name, reply_sz, reply_sz));
+
+		sz = (ioc->req_sz * ioc->req_depth);
+		dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d bytes, RequestDepth=%d\n",
+			 	ioc->name, ioc->req_sz, ioc->req_depth));
+		dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffer sz=%d[%x] bytes\n",
+			 	ioc->name, sz, sz));
+		total_size += sz;
+
+		sz = num_chain * ioc->req_sz; /* chain buffer pool size */
+		dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d bytes, ChainDepth=%d\n",
+			 	ioc->name, ioc->req_sz, num_chain));
+		dinitprintk((KERN_INFO MYNAM ": %s.ChainBuffer sz=%d[%x] bytes num_chain=%d\n",
+			 	ioc->name, sz, sz, num_chain));
+
+		total_size += sz;
+		mem = pci_alloc_consistent(ioc->pcidev, total_size, &alloc_dma);
+		if (mem == NULL) {
+			printk(MYIOC_s_ERR_FMT "Unable to allocate Reply, Request, Chain Buffers!\n",
+				ioc->name);
 			goto out_fail;
+		}
+
+		dinitprintk((KERN_INFO MYNAM ": %s.Total alloc @ %p[%p], sz=%d[%x] bytes\n",
+			 	ioc->name, mem, (void *)(ulong)alloc_dma, total_size, total_size));
+
+		memset(mem, 0, total_size);
+		ioc->alloc_total += total_size;
+		ioc->alloc = mem;
+		ioc->alloc_dma = alloc_dma;
+		ioc->alloc_sz = total_size;
+		ioc->reply_frames = (MPT_FRAME_HDR *) mem;
+		ioc->reply_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
+
+		alloc_dma += reply_sz;
+		mem += reply_sz;
 
-		ioc->alloc_total += ioc->fifo_pool_sz;
-		memset(ioc->fifo_pool, 0, ioc->fifo_pool_sz);
-
-		/* reply fifo pointers */
-		ioc->reply_alloc = ioc->fifo_pool;
-		ioc->reply_alloc_dma = ioc->fifo_pool_dma;
-		/* request fifo pointers */
-		ioc->req_alloc = ioc->reply_alloc+reply_buffer_sz;
-		ioc->req_alloc_dma = ioc->reply_alloc_dma+reply_buffer_sz;
-		/* chain buffer pointers */
-		ioc->chain_alloc = ioc->req_alloc+request_buffer_sz;
-		ioc->chain_alloc_dma = ioc->req_alloc_dma+request_buffer_sz;
-		ioc->chain_alloc_sz = chain_buffer_sz;
-
-		/*  Prime reply FIFO...  */
-		dprintk((KERN_INFO MYNAM ": %s.reply_alloc  @ %p[%p], sz=%d bytes\n",
-			ioc->name, ioc->reply_alloc, 
-			(void *)(ulong)ioc->reply_alloc_dma, reply_buffer_sz));
-
-		b = (unsigned long) ioc->reply_alloc;
-		b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
-		aligned_mem = (u8 *) b;
-		ioc->reply_frames = (MPT_FRAME_HDR *) aligned_mem;
-		ioc->reply_frames_dma =
-			(ioc->reply_alloc_dma + (aligned_mem - ioc->reply_alloc));
-
-		ioc->reply_frames_low_dma = (u32) (ioc->reply_frames_dma & 0xFFFFFFFF);
-	
 		/*  Request FIFO - WE manage this!  */
-		dprintk((KERN_INFO MYNAM ": %s.req_alloc    @ %p[%p], sz=%d bytes\n",
-			ioc->name, ioc->req_alloc,
-			(void *)(ulong)ioc->req_alloc_dma, request_buffer_sz));
 
-		b = (unsigned long) ioc->req_alloc;
-		b = (b + (0x80UL - 1UL)) & ~(0x80UL - 1UL); /* round up to 128-byte boundary */
-		aligned_mem = (u8 *) b;
-		ioc->req_frames = (MPT_FRAME_HDR *) aligned_mem;
-		ioc->req_frames_dma =
-			(ioc->req_alloc_dma + (aligned_mem - ioc->req_alloc));
+		ioc->req_frames = (MPT_FRAME_HDR *) mem;
+		ioc->req_frames_dma = alloc_dma;
+
+		dinitprintk((KERN_INFO MYNAM ": %s.RequestBuffers @ %p[%p]\n",
+			 	ioc->name, mem, (void *)(ulong)alloc_dma));
 
-		ioc->req_frames_low_dma = (u32) (ioc->req_frames_dma & 0xFFFFFFFF);
+		ioc->req_frames_low_dma = (u32) (alloc_dma & 0xFFFFFFFF);
 
 #if defined(CONFIG_MTRR) && 0
 		/*
@@ -3559,79 +3571,93 @@ PrimeIocFifos(MPT_ADAPTER *ioc)
 		 *  (at least as much as we can; "size and base must be
 		 *  multiples of 4 kiB"
 		 */
-		ioc->mtrr_reg = mtrr_add(ioc->fifo_pool,
-					 ioc->fifo_pool_sz,
+		ioc->mtrr_reg = mtrr_add(ioc->req_frames_dma,
+					 sz,
 					 MTRR_TYPE_WRCOMB, 1);
 		dprintk((MYIOC_s_INFO_FMT "MTRR region registered (base:size=%08x:%x)\n",
-				ioc->name, ioc->fifo_pool, ioc->fifo_pool_sz));
+				ioc->name, ioc->req_frames_dma, sz));
 #endif
 
-	} /* ioc->fifo_pool == NULL */
-	
-	/* Post Reply frames to FIFO
-	 */
-	aligned_mem_dma = ioc->reply_frames_dma;
-	dprintk((KERN_INFO MYNAM ": %s.reply_frames @ %p[%p]\n",
-		 	ioc->name, ioc->reply_frames, (void *)(ulong)aligned_mem_dma));
+		for (i = 0; i < ioc->req_depth; i++) {
+			alloc_dma += ioc->req_sz;
+			mem += ioc->req_sz;
+		}
 
-	for (i = 0; i < ioc->reply_depth; i++) {
-		/*  Write each address to the IOC!  */
-		CHIPREG_WRITE32(&ioc->chip->ReplyFifo, aligned_mem_dma);
-		aligned_mem_dma += ioc->reply_sz;
-	}
+		ioc->ChainBuffer = mem;
+		ioc->ChainBufferDMA = alloc_dma;
 
+		dinitprintk((KERN_INFO MYNAM " :%s.ChainBuffers @ %p(%p)\n",
+			ioc->name, ioc->ChainBuffer, (void *)(ulong)ioc->ChainBufferDMA));
 
-	/* Initialize Request frames linked list
-	 */
-	aligned_mem_dma = ioc->req_frames_dma;
-	aligned_mem = (u8 *) ioc->req_frames;
-	dprintk((KERN_INFO MYNAM ": %s.req_frames   @ %p[%p]\n",
-		 	ioc->name, aligned_mem, (void *)(ulong)aligned_mem_dma));
+		/* Initialize the free chain Q.
+	 	*/
 
-	spin_lock_irqsave(&ioc->FreeQlock, flags);
-	Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR);
-	for (i = 0; i < ioc->req_depth; i++) {
-		mf = (MPT_FRAME_HDR *) aligned_mem;
+		Q_INIT(&ioc->FreeChainQ, MPT_FRAME_HDR);
 
-		/*  Queue REQUESTs *internally*!  */
-		Q_ADD_TAIL(&ioc->FreeQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR);
-		aligned_mem += ioc->req_sz;
-	}
-	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+		/* Post the chain buffers to the FreeChainQ.
+	 	*/
+		mem = (u8 *)ioc->ChainBuffer;
+		for (i=0; i < num_chain; i++) {
+			mf = (MPT_FRAME_HDR *) mem;
+			Q_ADD_TAIL(&ioc->FreeChainQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR);
+			mem += ioc->req_sz;
+		}
 
+		/* Initialize Request frames linked list
+		 */
+		alloc_dma = ioc->req_frames_dma;
+		mem = (u8 *) ioc->req_frames;
+
+		spin_lock_irqsave(&ioc->FreeQlock, flags);
+		Q_INIT(&ioc->FreeQ, MPT_FRAME_HDR);
+		for (i = 0; i < ioc->req_depth; i++) {
+			mf = (MPT_FRAME_HDR *) mem;
+
+			/*  Queue REQUESTs *internally*!  */
+			Q_ADD_TAIL(&ioc->FreeQ.head, &mf->u.frame.linkage, MPT_FRAME_HDR);
+			mem += ioc->req_sz;
+		}
+		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
-	if (ioc->sense_buf_pool == NULL) {
 		sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
 		ioc->sense_buf_pool =
-				pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
-		if (ioc->sense_buf_pool == NULL)
+			pci_alloc_consistent(ioc->pcidev, sz, &ioc->sense_buf_pool_dma);
+		if (ioc->sense_buf_pool == NULL) {
+			printk(MYIOC_s_ERR_FMT "Unable to allocate Sense Buffers!\n",
+				ioc->name);
 			goto out_fail;
+		}
 
 		ioc->sense_buf_low_dma = (u32) (ioc->sense_buf_pool_dma & 0xFFFFFFFF);
 		ioc->alloc_total += sz;
+		dinitprintk((KERN_INFO MYNAM ": %s.SenseBuffers @ %p[%p]\n",
+ 			ioc->name, ioc->sense_buf_pool, (void *)(ulong)ioc->sense_buf_pool_dma));
+
+	}
+
+	/* Post Reply frames to FIFO
+	 */
+	alloc_dma = ioc->alloc_dma;
+	dinitprintk((KERN_INFO MYNAM ": %s.ReplyBuffers @ %p[%p]\n",
+	 	ioc->name, ioc->reply_frames, (void *)(ulong)alloc_dma));
+
+	for (i = 0; i < ioc->reply_depth; i++) {
+		/*  Write each address to the IOC!  */
+		CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
+		alloc_dma += ioc->reply_sz;
 	}
 
 	return 0;
 
 out_fail:
-	if (ioc->fifo_pool != NULL) {
+	if (ioc->alloc != NULL) {
+		sz = ioc->alloc_sz;
 		pci_free_consistent(ioc->pcidev,
-				ioc->fifo_pool_sz,
-				ioc->fifo_pool, ioc->fifo_pool_dma);
+				sz,
+				ioc->alloc, ioc->alloc_dma);
 		ioc->reply_frames = NULL;
-		ioc->reply_alloc = NULL;
 		ioc->req_frames = NULL;
-		ioc->req_alloc = NULL;
-		ioc->chain_alloc = NULL;
-		ioc->fifo_pool = NULL;
-		ioc->alloc_total -= ioc->fifo_pool_sz;
-#if defined(CONFIG_MTRR) && 0
-		if (ioc->mtrr_reg > 0) {
-			mtrr_del(ioc->mtrr_reg, 0, 0);
-			dprintk((MYIOC_s_INFO_FMT "MTRR region de-registered\n",
-					ioc->name));
-		}
-#endif
+		ioc->alloc_total -= sz;
 	}
 	if (ioc->sense_buf_pool != NULL) {
 		sz = (ioc->req_depth * MPT_SENSE_BUFFER_ALLOC);
@@ -3693,8 +3719,8 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
 	if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
 		failcnt++;
 
-	dhsprintk((MYIOC_s_INFO_FMT "HandShake request start, WaitCnt=%d%s\n",
-			ioc->name, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
+	dhsprintk((MYIOC_s_INFO_FMT "HandShake request start reqBytes=%d, WaitCnt=%d%s\n",
+			ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
 
 	/* Read doorbell and check for active bit */
 	if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
@@ -3728,7 +3754,7 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req,
 				failcnt++;
 		}
 
-		dmfprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
+		dhsprintk((KERN_INFO MYNAM ": Handshake request frame (@%p) header\n", req));
 		DBG_DUMP_REQUEST_FRAME_HDR(req)
 
 		dhsprintk((MYIOC_s_INFO_FMT "HandShake request post done, WaitCnt=%d%s\n",
@@ -3783,7 +3809,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
 			if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
 				break;
 			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
+			schedule_timeout(1 * HZ / 1000);
 			count++;
 		}
 	} else {
@@ -3833,7 +3859,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
 			if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
 				break;
 			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(1);
+			schedule_timeout(1 * HZ / 1000);
 			count++;
 		}
 	} else {
@@ -3935,7 +3961,7 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag)
 	}
 #endif
 
-	dmfprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
+	dhsprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
 	DBG_DUMP_REPLY_FRAME(mptReply)
 
 	dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
@@ -4282,9 +4308,11 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
 				pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
 				pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
 
-				if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 )
+				if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) {
 					ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
-
+					dinitprintk((KERN_INFO MYNAM " :%s noQas due to Capabilities=%x\n",
+						ioc->name, pPP0->Capabilities));
+				}
 				ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
 				data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
 				if (data) {
@@ -4907,8 +4935,8 @@ int
 mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
 {
 	ToolboxIstwiReadWriteRequest_t	*pReq;
-	struct pci_dev	*pdev;
 	MPT_FRAME_HDR	*mf;
+	struct pci_dev	*pdev;
 	unsigned long	 flags;
 	int		 rc;
 	u32		 flagsLength;
@@ -5226,12 +5254,6 @@ procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eo
 
 			if (drvname)
 				len += sprintf(buf+len, "  Fusion MPT %s driver\n", drvname);
-			/*
-			 *	Handle isense special case, because it
-			 *	doesn't do a formal mpt_register call.
-			 */
-			if (isense_idx == ii)
-				len += sprintf(buf+len, "  Fusion MPT isense driver\n");
 		}
 	}
 
@@ -5286,7 +5308,7 @@ procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eo
 	len += sprintf(buf+len, "  MinBlockSize = 0x%02x bytes\n", 4*ioc->facts.BlockSize);
 
 	len += sprintf(buf+len, "  RequestFrames @ 0x%p (Dma @ 0x%p)\n",
-					(void *)ioc->req_alloc, (void *)(ulong)ioc->req_alloc_dma);
+					(void *)ioc->req_frames, (void *)(ulong)ioc->req_frames_dma);
 	/*
 	 *  Rounding UP to nearest 4-kB boundary here...
 	 */
@@ -5298,8 +5320,8 @@ procmpt_iocinfo_read(char *buf, char **start, off_t offset, int request, int *eo
 					4*ioc->facts.RequestFrameSize,
 					ioc->facts.GlobalCredits);
 
-	len += sprintf(buf+len, "  ReplyFrames   @ 0x%p (Dma @ 0x%p)\n",
-					(void *)ioc->reply_alloc, (void *)(ulong)ioc->reply_alloc_dma);
+	len += sprintf(buf+len, "  Frames   @ 0x%p (Dma @ 0x%p)\n",
+					(void *)ioc->alloc, (void *)(ulong)ioc->alloc_dma);
 	sz = (ioc->reply_sz * ioc->reply_depth) + 128;
 	len += sprintf(buf+len, "    {CurRepSz=%d} x {CurRepDepth=%d} = %d bytes ^= 0x%x\n",
 					ioc->reply_sz, ioc->reply_depth, ioc->reply_sz*ioc->reply_depth, sz);
@@ -5592,7 +5614,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
 	}
 
 	evStr = EventDescriptionStr(event, evData0);
-	dprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n",
+	devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n",
 			ioc->name,
 			evStr,
 			event));
@@ -5664,7 +5686,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
 	 */
 	for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
 		if (MptEvHandlers[ii]) {
-			dprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
+			devtprintk((MYIOC_s_INFO_FMT "Routing Event to event handler #%d\n",
 					ioc->name, ii));
 			r += (*(MptEvHandlers[ii]))(ioc, pEventReply);
 			handlers++;
@@ -5677,8 +5699,8 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply
 	 */
 	if (pEventReply->AckRequired == MPI_EVENT_NOTIFICATION_ACK_REQUIRED) {
 		if ((ii = SendEventAck(ioc, pEventReply)) != 0) {
-			printk(MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
-					ioc->name, ii);
+			devtprintk((MYIOC_s_WARN_FMT "SendEventAck returned %d\n",
+					ioc->name, ii));
 		}
 	}
 
@@ -5702,9 +5724,8 @@ mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info)
 		"FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
 	};
 	u8 subcl = (log_info >> 24) & 0x7;
-//	u32 SubCl = log_info & 0x27000000;
 
-	printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}",
+	printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}\n",
 			ioc->name, log_info, subcl_str[subcl]);
 }
 
@@ -5907,50 +5928,6 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *	mpt_register_ascqops_strings - Register SCSI ASC/ASCQ and SCSI
- *	OpCode strings from the (optional) isense module.
- *	@ascqTable: Pointer to ASCQ_Table_t structure
- *	@ascqtbl_sz: Number of entries in ASCQ_Table
- *	@opsTable: Pointer to array of SCSI OpCode strings (char pointers)
- *
- *	Specialized driver registration routine for the isense driver.
- */
-int
-mpt_register_ascqops_strings(void *ascqTable, int ascqtbl_sz, const char **opsTable)
-{
-	int r = 0;
-
-	if (ascqTable && ascqtbl_sz && opsTable) {
-		mpt_v_ASCQ_TablePtr = ascqTable;
-		mpt_ASCQ_TableSz = ascqtbl_sz;
-		mpt_ScsiOpcodesPtr = opsTable;
-		printk(KERN_INFO MYNAM ": English readable SCSI-3 strings enabled:-)\n");
-		isense_idx = last_drv_idx;
-		r = 1;
-	}
-	return r;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *	mpt_deregister_ascqops_strings - Deregister SCSI ASC/ASCQ and SCSI
- *	OpCode strings from the isense driver.
- *
- *	Specialized driver deregistration routine for the isense driver.
- */
-void
-mpt_deregister_ascqops_strings(void)
-{
-	mpt_v_ASCQ_TablePtr = NULL;
-	mpt_ASCQ_TableSz = 0;
-	mpt_ScsiOpcodesPtr = NULL;
-	printk(KERN_INFO MYNAM ": English readable SCSI-3 strings disabled)-:\n");
-	isense_idx = -1;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
 EXPORT_SYMBOL(ioc_list);
 EXPORT_SYMBOL(mpt_proc_root_dir);
 EXPORT_SYMBOL(DmpService);
@@ -5982,13 +5959,6 @@ EXPORT_SYMBOL(mpt_read_ioc_pg_3);
 EXPORT_SYMBOL(mpt_alloc_fw_memory);
 EXPORT_SYMBOL(mpt_free_fw_memory);
 
-EXPORT_SYMBOL(mpt_register_ascqops_strings);
-EXPORT_SYMBOL(mpt_deregister_ascqops_strings);
-EXPORT_SYMBOL(mpt_v_ASCQ_TablePtr);
-EXPORT_SYMBOL(mpt_ASCQ_TableSz);
-EXPORT_SYMBOL(mpt_ScsiOpcodesPtr);
-
-
 static struct pci_driver mptbase_driver = {
 	.name		= "mptbase",
 	.id_table	= mptbase_pci_table,
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 8a84b72a3..4b9b4934d 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -60,8 +60,6 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 
-#include "scsi3.h"		/* SCSI defines */
-
 #include "lsi/mpi_type.h"
 #include "lsi/mpi.h"		/* Fusion MPI(nterface) basic defs */
 #include "lsi/mpi_ioc.h"	/* Fusion MPT IOC(ontroller) defs */
@@ -85,8 +83,8 @@
 #define COPYRIGHT	"Copyright (c) 1999-2004 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"3.01.09"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.01.09"
+#define MPT_LINUX_VERSION_COMMON	"3.01.16"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.01.16"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -320,17 +318,6 @@ typedef struct _Q_TRACKER {
 	struct _Q_ITEM	*tail;
 } Q_TRACKER;
 
-typedef struct _MPT_DONE_Q {
-	struct _MPT_DONE_Q	*forw;
-	struct _MPT_DONE_Q	*back;
-	void			*argp;
-} MPT_DONE_Q;
-
-typedef struct _DONE_Q_TRACKER {
-	MPT_DONE_Q	*head;
-	MPT_DONE_Q	*tail;
-} DONE_Q_TRACKER;
-
 /*
  *  Chip-specific stuff... FC929 delineates break between
  *  FC and Parallel SCSI parts. Do NOT re-order.
@@ -403,6 +390,11 @@ typedef struct _ScsiCmndTracker {
 	void			*tail;
 } ScsiCmndTracker;
 
+/* VirtDevice negoFlags field */
+#define MPT_TARGET_NO_NEGO_WIDE		0x01
+#define MPT_TARGET_NO_NEGO_SYNC		0x02
+#define MPT_TARGET_NO_NEGO_QAS		0x04
+#define MPT_TAPE_NEGO_IDP     		0x08
 
 /*
  *	VirtDevice - FC LUN device or SCSI target device
@@ -420,8 +412,8 @@ typedef struct _VirtDevice {
 	u8			 bus_id;
 	u8			 minSyncFactor;	/* 0xFF is async */
 	u8			 maxOffset;	/* 0 if async */
-	u8			 maxWidth;	/* 0 if narrow, 1 if wide*/
-	u8			 negoFlags;	/* bit field, 0 if WDTR/SDTR/QAS allowed */
+	u8			 maxWidth;	/* 0 if narrow, 1 if wide */
+	u8			 negoFlags;	/* bit field, see above */
 	u8			 raidVolume;	/* set, if RAID Volume */
 	u8			 type;		/* byte 0 of Inquiry data */
 	u8			 cflags;	/* controller flags */
@@ -460,10 +452,6 @@ typedef struct _VirtDevice {
 #define MPT_TARGET_FLAGS_VALID_56	0x10
 #define MPT_TARGET_FLAGS_SAF_TE_ISSUED	0x20
 
-#define MPT_TARGET_NO_NEGO_WIDE		0x01
-#define MPT_TARGET_NO_NEGO_SYNC		0x02
-#define MPT_TARGET_NO_NEGO_QAS		0x04
-
 typedef struct _VirtDevTracker {
 	struct _VirtDevice	*head;
 	struct _VirtDevice	*tail;
@@ -523,6 +511,7 @@ typedef struct _MPT_IOCTL {
 	u8			 target;	/* target for reset */
 	void 			*tmPtr;
 	struct timer_list	 TMtimer;	/* timer function for this adapter */
+	struct semaphore	 sem_ioc;
 } MPT_IOCTL;
 
 /*
@@ -592,33 +581,38 @@ typedef struct _MPT_ADAPTER
 	int			 pci_irq;	/* This irq           */
 	char			 name[MPT_NAME_LENGTH];	/* "iocN"             */
 	char			*prod_name;	/* "LSIFC9x9"         */
-	volatile SYSIF_REGS	*chip;		/* == c8817000 (mmap) */
-	volatile SYSIF_REGS	*pio_chip;	/* Programmed IO (downloadboot) */
+	SYSIF_REGS __iomem	*chip;		/* == c8817000 (mmap) */
+	SYSIF_REGS __iomem	*pio_chip;	/* Programmed IO (downloadboot) */
 	u32			 mem_phys;	/* == f4020000 (mmap) */
 	u32			 pio_mem_phys;	/* Programmed IO (downloadboot) */
 	int			 mem_size;	/* mmap memory size */
 	int			 alloc_total;
 	u32			 last_state;
 	int			 active;
-	u8			*fifo_pool;	/* dma pool for fifo's */
-	dma_addr_t		 fifo_pool_dma;
-	int			 fifo_pool_sz;	/* allocated size */
-	u8			*chain_alloc;	/* chain buffer alloc ptr */
-	dma_addr_t		chain_alloc_dma;
-	int			chain_alloc_sz;
-	u8			*reply_alloc;	/* Reply frames alloc ptr */
-	dma_addr_t		 reply_alloc_dma;
+	u8			*alloc;		/* frames alloc ptr */
+	dma_addr_t		 alloc_dma;
+	u32			 alloc_sz;
 	MPT_FRAME_HDR		*reply_frames;	/* Reply msg frames - rounded up! */
-	dma_addr_t		 reply_frames_dma;
 	u32			 reply_frames_low_dma;
 	int			 reply_depth;	/* Num Allocated reply frames */
 	int			 reply_sz;	/* Reply frame size */
+	int			 num_chain;	/* Number of chain buffers */
+		/* Pool of buffers for chaining. ReqToChain
+		 * and ChainToChain track index of chain buffers.
+		 * ChainBuffer (DMA) virt/phys addresses.
+		 * FreeChainQ (lock) locking mechanisms.
+		 */
+	int			*ReqToChain;
+	int			*RequestNB;
+	int			*ChainToChain;
+	u8			*ChainBuffer;
+	dma_addr_t		 ChainBufferDMA;
+	MPT_Q_TRACKER		 FreeChainQ;
+	spinlock_t		 FreeChainQlock;
 	CHIP_TYPE		 chip_type;
 		/* We (host driver) get to manage our own RequestQueue! */
-	u8			*req_alloc;	/* Request frames alloc ptr */
-	dma_addr_t		 req_alloc_dma;
-	MPT_FRAME_HDR		*req_frames;	/* Request msg frames - rounded up! */
 	dma_addr_t		 req_frames_dma;
+	MPT_FRAME_HDR		*req_frames;	/* Request msg frames - rounded up! */
 	u32			 req_frames_low_dma;
 	int			 req_depth;	/* Number of request frames */
 	int			 req_sz;	/* Request frame size (bytes) */
@@ -661,6 +655,7 @@ typedef struct _MPT_ADAPTER
 #else
 	u32			 mfcnt;
 #endif
+	u32			 NB_for_64_byte_frame;       
 	u32			 hs_req[MPT_MAX_FRAME_SIZE/sizeof(u32)];
 	u16			 hs_reply[MPT_MAX_FRAME_SIZE/sizeof(u16)];
 	IOCFactsReply_t		 facts;
@@ -674,8 +669,10 @@ typedef struct _MPT_ADAPTER
 	u8			 FirstWhoInit;
 	u8			 upload_fw;	/* If set, do a fw upload */
 	u8			 reload_fw;	/* Force a FW Reload on next reset */
-	u8			 pad1[5];
+	u8			 NBShiftFactor;  /* NB Shift Factor based on Block Size (Facts)  */     
+	u8			 pad1[4];
 	struct list_head	 list; 
+	struct net_device	*netdev;
 } MPT_ADAPTER;
 
 
@@ -757,10 +754,10 @@ typedef struct _mpt_sge {
 #define dexitprintk(x)
 #endif
 
-#ifdef MPT_DEBUG_RESET
-#define drsprintk(x)  printk x
+#if defined MPT_DEBUG_FAIL || defined (MPT_DEBUG_SG)
+#define dfailprintk(x) printk x
 #else
-#define drsprintk(x)
+#define dfailprintk(x)
 #endif
 
 #ifdef MPT_DEBUG_HANDSHAKE
@@ -769,11 +766,34 @@ typedef struct _mpt_sge {
 #define dhsprintk(x)
 #endif
 
+#ifdef MPT_DEBUG_EVENTS
+#define devtprintk(x)  printk x
+#else
+#define devtprintk(x)
+#endif
+
+#ifdef MPT_DEBUG_RESET
+#define drsprintk(x)  printk x
+#else
+#define drsprintk(x)
+#endif
+
 //#if defined(MPT_DEBUG) || defined(MPT_DEBUG_MSG_FRAME)
 #if defined(MPT_DEBUG_MSG_FRAME)
 #define dmfprintk(x)  printk x
+#define DBG_DUMP_REQUEST_FRAME(mfp) \
+	{	int  i, n = 24;						\
+		u32 *m = (u32 *)(mfp);					\
+		for (i=0; i<n; i++) {					\
+			if (i && ((i%8)==0))				\
+				printk("\n");				\
+			printk("%08x ", le32_to_cpu(m[i]));		\
+		}							\
+		printk("\n");						\
+	}
 #else
 #define dmfprintk(x)
+#define DBG_DUMP_REQUEST_FRAME(mfp)
 #endif
 
 #ifdef MPT_DEBUG_IRQ
@@ -794,13 +814,18 @@ typedef struct _mpt_sge {
 #define ddlprintk(x)
 #endif
 
-
 #ifdef MPT_DEBUG_DV
 #define ddvprintk(x)  printk x
 #else
 #define ddvprintk(x)
 #endif
 
+#ifdef MPT_DEBUG_NEGO
+#define dnegoprintk(x)  printk x
+#else
+#define dnegoprintk(x)
+#endif
+
 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
 #define ddvtprintk(x)  printk x
 #else
@@ -813,10 +838,40 @@ typedef struct _mpt_sge {
 #define dctlprintk(x)
 #endif
 
-#ifdef MPT_DEBUG_RESET
+#ifdef MPT_DEBUG_REPLY
+#define dreplyprintk(x) printk x
+#else
+#define dreplyprintk(x)
+#endif
+
+#ifdef MPT_DEBUG_TM
 #define dtmprintk(x) printk x
+#define DBG_DUMP_TM_REQUEST_FRAME(mfp) \
+	{	u32 *m = (u32 *)(mfp);					\
+		int  i, n = 13;						\
+		printk("TM_REQUEST:\n");				\
+		for (i=0; i<n; i++) {					\
+			if (i && ((i%8)==0))				\
+				printk("\n");				\
+			printk("%08x ", le32_to_cpu(m[i]));		\
+		}							\
+		printk("\n");						\
+	}
+#define DBG_DUMP_TM_REPLY_FRAME(mfp) \
+	{	u32 *m = (u32 *)(mfp);					\
+		int  i, n = (le32_to_cpu(m[0]) & 0x00FF0000) >> 16;	\
+		printk("TM_REPLY MessageLength=%d:\n", n);		\
+		for (i=0; i<n; i++) {					\
+			if (i && ((i%8)==0))				\
+				printk("\n");				\
+			printk(" %08x", le32_to_cpu(m[i]));		\
+		}							\
+		printk("\n");						\
+	}
 #else
 #define dtmprintk(x)
+#define DBG_DUMP_TM_REQUEST_FRAME(mfp)
+#define DBG_DUMP_TM_REPLY_FRAME(mfp)
 #endif
 
 #ifdef MPT_DEBUG_NEH
@@ -907,6 +962,10 @@ typedef struct _mpt_sge {
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
+#define SCSI_STD_SENSE_BYTES    18
+#define SCSI_STD_INQUIRY_BYTES  36
+#define SCSI_MAX_INQUIRY_BYTES  96
+
 /*
  * MPT_SCSI_HOST defines - Used by the IOCTL and the SCSI drivers
  * Private to the driver.
@@ -950,17 +1009,6 @@ typedef struct _MPT_SCSI_HOST {
 	int			  port;
 	u32			  pad0;
 	struct scsi_cmnd	**ScsiLookup;
-		/* Pool of buffers for chaining. ReqToChain
-		 * and ChainToChain track index of chain buffers.
-		 * ChainBuffer (DMA) virt/phys addresses.
-		 * FreeChainQ (lock) locking mechanisms.
-		 */
-	int			 *ReqToChain;
-	int			 *ChainToChain;
-	u8			 *ChainBuffer;
-	dma_addr_t		  ChainBufferDMA;
-	MPT_Q_TRACKER		  FreeChainQ;
-	spinlock_t		  FreeChainQlock;
 	u32			  qtag_tick;
 	VirtDevice		**Targets;
 	MPT_LOCAL_REPLY		 *pLocal;		/* used for internal commands */
@@ -969,23 +1017,15 @@ typedef struct _MPT_SCSI_HOST {
 		/* Pool of memory for holding SCpnts before doing
 		 * OS callbacks. freeQ is the free pool.
 		 */
-	u8			 *memQ;
-	DONE_Q_TRACKER		  freeQ;
-	DONE_Q_TRACKER		  doneQ;		/* Holds Linux formmatted requests */
-	DONE_Q_TRACKER		  pendingQ;		/* Holds MPI formmatted requests */
 	MPT_Q_TRACKER		  taskQ;		/* TM request Q */
-	spinlock_t		  freedoneQlock;
 	int			  taskQcnt;
-	int			  num_chain;		/* Number of chain buffers */
-	int			  max_sge;		/* Max No of SGE*/
-	u8			  numTMrequests;
 	u8			  tmPending;
 	u8			  resetPending;
 	u8			  is_spi;		/* Parallel SCSI i/f */
 	u8			  negoNvram;		/* DV disabled, nego NVRAM */
 	u8			  is_multipath;		/* Multi-path compatible */
 	u8                        tmState;
-	u8			  rsvd[1];
+	u8			  rsvd[2];
 	MPT_FRAME_HDR		 *tmPtr;		/* Ptr to TM request*/
 	MPT_FRAME_HDR		 *cmdPtr;		/* Ptr to nonOS request */
 	struct scsi_cmnd	 *abortSCpnt;
@@ -1055,10 +1095,8 @@ extern int	 mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func);
 extern void	 mpt_reset_deregister(int cb_idx);
 extern int	 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx);
 extern void	 mpt_device_driver_deregister(int cb_idx);
-extern int	 mpt_register_ascqops_strings(void *ascqTable, int ascqtbl_sz, const char **opsTable);
-extern void	 mpt_deregister_ascqops_strings(void);
 extern MPT_FRAME_HDR	*mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc);
-extern void	 mpt_free_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
+extern void	 mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
 extern void	 mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf);
 extern void	 mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr);
 extern void	 mpt_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr);
@@ -1086,10 +1124,6 @@ extern DmpServices_t		*DmpService;
 extern int		  mpt_lan_index;	/* needed by mptlan.c */
 extern int		  mpt_stm_index;	/* needed by mptstm.c */
 
-extern void		 *mpt_v_ASCQ_TablePtr;
-extern const char	**mpt_ScsiOpcodesPtr;
-extern int		  mpt_ASCQ_TableSz;
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 #endif		/* } __KERNEL__ */
 
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index c6163a424..bb608fa5a 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -111,7 +111,6 @@ MODULE_LICENSE("GPL");
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
 static int mptctl_id = -1;
-static struct semaphore mptctl_syscall_sem_ioc[MPT_MAX_ADAPTERS];
 
 static DECLARE_WAIT_QUEUE_HEAD ( mptctl_wait );
 
@@ -140,6 +139,9 @@ static int mptctl_do_reset(unsigned long arg);
 static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd);
 static int mptctl_hp_targetinfo(unsigned long arg);
 
+static int  mptctl_probe(struct pci_dev *, const struct pci_device_id *);
+static void mptctl_remove(struct pci_dev *);
+
 /*
  * Private function calls.
  */
@@ -208,10 +210,10 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock)
 	}
 
 	if (nonblock) {
-		if (down_trylock(&mptctl_syscall_sem_ioc[ioc->id]))
+		if (down_trylock(&ioc->ioctl->sem_ioc))
 			rc = -EAGAIN;
 	} else {
-		if (down_interruptible(&mptctl_syscall_sem_ioc[ioc->id]))
+		if (down_interruptible(&ioc->ioctl->sem_ioc))
 			rc = -ERESTARTSYS;
 	}
 	dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc));
@@ -445,7 +447,7 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl)
 
 		mptctl_free_tm_flags(ioctl->ioc);
 		del_timer(&ioctl->TMtimer);
-		mpt_free_msg_frame(mptctl_id, ioctl->ioc, mf);
+		mpt_free_msg_frame(ioctl->ioc, mf);
 		ioctl->tmPtr = NULL;
 	}
 
@@ -482,7 +484,7 @@ mptctl_free_tm_flags(MPT_ADAPTER *ioc)
 
 	spin_lock_irqsave(&ioc->FreeQlock, flags);
 
-	hd->tmState = TM_STATE_ERROR;
+	hd->tmState = TM_STATE_NONE;
 	hd->tmPending = 0;
 	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
@@ -520,7 +522,7 @@ mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 		if (ioctl && (ioctl->status & MPT_IOCTL_STATUS_TMTIMER_ACTIVE)){
 			ioctl->status &= ~MPT_IOCTL_STATUS_TMTIMER_ACTIVE;
 			del_timer(&ioctl->TMtimer);
-			mpt_free_msg_frame(mptctl_id, ioc, ioctl->tmPtr);
+			mpt_free_msg_frame(ioc, ioctl->tmPtr);
 		}
 
 	} else {
@@ -630,8 +632,7 @@ mptctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned
 	else
 		ret = -EINVAL;
 
-
-	up(&mptctl_syscall_sem_ioc[iocp->id]);
+	up(&iocp->ioctl->sem_ioc);
 
 	return ret;
 }
@@ -1807,7 +1808,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 	struct buflist	bufOut; /* data Out buffer */
 	dma_addr_t	dma_addr_in;
 	dma_addr_t	dma_addr_out;
-	int		dir;	/* PCI data direction */
 	int		sgSize = 0;	/* Num SG elements */
 	int		iocnum, flagsLength;
 	int		sz, rc = 0;
@@ -2117,9 +2117,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 
 		/* Set up the dataOut memory allocation */
 		if (karg.dataOutSize > 0) {
-			dir = PCI_DMA_TODEVICE;
 			if (karg.dataInSize > 0) {
 				flagsLength = ( MPI_SGE_FLAGS_SIMPLE_ELEMENT |
+						MPI_SGE_FLAGS_END_OF_BUFFER |
 						MPI_SGE_FLAGS_DIRECTION |
 						mpt_addr_size() )
 						<< MPI_SGE_FLAGS_SHIFT;
@@ -2158,7 +2158,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 		}
 
 		if (karg.dataInSize > 0) {
-			dir = PCI_DMA_FROMDEVICE;
 			flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
 			flagsLength |= karg.dataInSize;
 
@@ -2196,6 +2195,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 	add_timer(&ioc->ioctl->timer);
 
 	if (hdr->Function == MPI_FUNCTION_SCSI_TASK_MGMT) {
+		DBG_DUMP_TM_REQUEST_FRAME((u32 *)mf);
 		rc = mpt_send_handshake_request(mptctl_id, ioc,
 				sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP);
 		if (rc == 0) {
@@ -2206,7 +2206,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
 			del_timer(&ioc->ioctl->timer);
 			ioc->ioctl->status &= ~MPT_IOCTL_STATUS_TIMER_ACTIVE;
 			ioc->ioctl->status |= MPT_IOCTL_STATUS_TM_FAILED;
-			mpt_free_msg_frame(mptctl_id, ioc, mf);
+			mpt_free_msg_frame(ioc, mf);
 		}
 	} else {
 		mpt_put_msg_frame(mptctl_id, ioc, mf);
@@ -2324,7 +2324,7 @@ done_free_mem:
 	 * otherwise, failure occured after mf acquired.
 	 */
 	if (mf)
-		mpt_free_msg_frame(mptctl_id, ioc, mf);
+		mpt_free_msg_frame(ioc, mf);
 
 	return rc;
 }
@@ -2738,7 +2738,7 @@ compat_mptfwxfer_ioctl(unsigned int fd, unsigned int cmd,
 
 	ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
 
-	up(&mptctl_syscall_sem_ioc[iocp->id]);
+	up(&iocp->ioctl->sem_ioc);
 
 	return ret;
 }
@@ -2792,55 +2792,91 @@ compat_mpt_command(unsigned int fd, unsigned int cmd,
 	 */
 	ret = mptctl_do_mpt_command (karg, &uarg->MF);
 
-	up(&mptctl_syscall_sem_ioc[iocp->id]);
+	up(&iocp->ioctl->sem_ioc);
 
 	return ret;
 }
 
 #endif
 
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-int __init mptctl_init(void)
+/*
+ *	mptctl_probe - Installs ioctl devices per bus.
+ *	@pdev: Pointer to pci_dev structure
+ *
+ *	Returns 0 for success, non-zero for failure.
+ *
+ */
+
+static int
+mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	int err;
-	int i;
-	int where = 1;
 	int sz;
 	u8 *mem;
-	MPT_ADAPTER *ioc = NULL;
-	int iocnum;
+	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
 
-	show_mptmod_ver(my_NAME, my_VERSION);
+	/*
+	 * Allocate and inite a MPT_IOCTL structure
+	*/
+	sz = sizeof (MPT_IOCTL);
+	mem = kmalloc(sz, GFP_KERNEL);
+	if (mem == NULL) {
+		err = -ENOMEM;
+		goto out_fail;
+	}
 
-	for (i=0; i<MPT_MAX_ADAPTERS; i++) {
-		sema_init(&mptctl_syscall_sem_ioc[i], 1);
+	memset(mem, 0, sz);
+	ioc->ioctl = (MPT_IOCTL *) mem;
+	ioc->ioctl->ioc = ioc;
+	init_timer (&ioc->ioctl->timer);
+	ioc->ioctl->timer.data = (unsigned long) ioc->ioctl;
+	ioc->ioctl->timer.function = mptctl_timer_expired;
+	init_timer (&ioc->ioctl->TMtimer);
+	ioc->ioctl->TMtimer.data = (unsigned long) ioc->ioctl;
+	ioc->ioctl->TMtimer.function = mptctl_timer_expired;
+	sema_init(&ioc->ioctl->sem_ioc, 1);
+	return 0;
 
-		ioc = NULL;
-		if (((iocnum = mpt_verify_adapter(i, &ioc)) < 0) ||
-		    (ioc == NULL)) {
-			continue;
-		}
-		else {
-			/* This adapter instance is found.
-			 * Allocate and inite a MPT_IOCTL structure
-			 */
-			sz = sizeof (MPT_IOCTL);
-			mem = kmalloc(sz, GFP_KERNEL);
-			if (mem == NULL) {
-				err = -ENOMEM;
-				goto out_fail;
-			}
+out_fail:
 
-			memset(mem, 0, sz);
-			ioc->ioctl = (MPT_IOCTL *) mem;
-			ioc->ioctl->ioc = ioc;
-			init_timer (&ioc->ioctl->timer);
-			ioc->ioctl->timer.data = (unsigned long) ioc->ioctl;
-			ioc->ioctl->timer.function = mptctl_timer_expired;
-			init_timer (&ioc->ioctl->TMtimer);
-			ioc->ioctl->TMtimer.data = (unsigned long) ioc->ioctl;
-			ioc->ioctl->TMtimer.function = mptctl_timer_expired;
-		}
+	mptctl_remove(pdev);
+	return err;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	mptctl_remove - Removed ioctl devices
+ *	@pdev: Pointer to pci_dev structure
+ *
+ *
+ */
+static void
+mptctl_remove(struct pci_dev *pdev)
+{
+	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+
+	kfree ( ioc->ioctl );
+}
+
+static struct mpt_pci_driver mptctl_driver = {
+  .probe		= mptctl_probe,
+  .remove		= mptctl_remove,
+};
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static int __init mptctl_init(void)
+{
+	int err;
+	int where = 1;
+
+	show_mptmod_ver(my_NAME, my_VERSION);
+
+	if(mpt_device_driver_register(&mptctl_driver,
+	  MPTCTL_DRIVER) != 0 ) {
+		dprintk((KERN_INFO MYNAM
+		": failed to register dd callbacks\n"));
 	}
 
 #ifdef CONFIG_COMPAT
@@ -2922,29 +2958,14 @@ out_fail:
 	unregister_ioctl32_conversion(HP_GETTARGETINFO);
 #endif
 
-	for (i=0; i<MPT_MAX_ADAPTERS; i++) {
-		ioc = NULL;
-		if (((iocnum = mpt_verify_adapter(i, &ioc)) < 0) ||
-		    (ioc == NULL)) {
-			continue;
-		}
-		else {
-			if (ioc->ioctl) {
-				kfree ( ioc->ioctl );
-				ioc->ioctl = NULL;
-			}
-		}
-	}
+	mpt_device_driver_deregister(MPTCTL_DRIVER);
+
 	return err;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-void mptctl_exit(void)
+static void mptctl_exit(void)
 {
-	int i;
-	MPT_ADAPTER *ioc;
-	int iocnum;
-
 	misc_deregister(&mptctl_miscdev);
 	printk(KERN_INFO MYNAM ": Deregistered /dev/%s @ (major,minor=%d,%d)\n",
 			 mptctl_miscdev.name, MISC_MAJOR, mptctl_miscdev.minor);
@@ -2957,6 +2978,8 @@ void mptctl_exit(void)
 	mpt_deregister(mptctl_id);
 	printk(KERN_INFO MYNAM ": Deregistered from Fusion MPT base driver\n");
 
+        mpt_device_driver_deregister(MPTCTL_DRIVER);
+
 #ifdef CONFIG_COMPAT
 	unregister_ioctl32_conversion(MPTIOCINFO);
 	unregister_ioctl32_conversion(MPTIOCINFO1);
@@ -2973,20 +2996,6 @@ void mptctl_exit(void)
 	unregister_ioctl32_conversion(HP_GETTARGETINFO);
 #endif
 
-	/* Free allocated memory */
-	for (i=0; i<MPT_MAX_ADAPTERS; i++) {
-		ioc = NULL;
-		if (((iocnum = mpt_verify_adapter(i, &ioc)) < 0) ||
-		    (ioc == NULL)) {
-			continue;
-		}
-		else {
-			if (ioc->ioctl) {
-				kfree ( ioc->ioctl );
-				ioc->ioctl = NULL;
-			}
-		}
-	}
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
index 80c9b97eb..5327c9215 100644
--- a/drivers/message/fusion/mptlan.c
+++ b/drivers/message/fusion/mptlan.c
@@ -177,11 +177,9 @@ static int LanCtx = -1;
 static u32 max_buckets_out = 127;
 static u32 tx_max_out_p = 127 - 16;
 
-static struct net_device *mpt_landev[MPT_MAX_ADAPTERS+1];
-
 #ifdef QLOGIC_NAA_WORKAROUND
 static struct NAA_Hosed *mpt_bad_naa = NULL;
-rwlock_t bad_naa_lock;
+rwlock_t bad_naa_lock = RW_LOCK_UNLOCKED;
 #endif
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -203,7 +201,7 @@ extern int mpt_lan_index;
 static int
 lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
 {
-	struct net_device *dev = mpt_landev[ioc->id];
+	struct net_device *dev = ioc->netdev;
 	int FreeReqFrame = 0;
 
 	dioprintk((KERN_INFO MYNAM ": %s/%s: Got reply.\n",
@@ -336,7 +334,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
 static int
 mpt_lan_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 {
-	struct net_device *dev = mpt_landev[ioc->id];
+	struct net_device *dev = ioc->netdev;
 	struct mpt_lan_priv *priv = netdev_priv(dev);
 
 	dlprintk((KERN_INFO MYNAM ": IOC %s_reset routed to LAN driver!\n",
@@ -1334,7 +1332,7 @@ mpt_lan_post_receive_buckets(void *dev_id)
 		if (pSimple == NULL) {
 /**/			printk (KERN_WARNING MYNAM "/%s: No buckets posted\n",
 /**/				__FUNCTION__);
-			mpt_free_msg_frame(LanCtx, mpt_dev, mf);
+			mpt_free_msg_frame(mpt_dev, mf);
 			goto out;
 		}
 
@@ -1451,20 +1449,74 @@ mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum)
 	return dev;
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int __init mpt_lan_init (void)
+static int
+mptlan_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
-	struct net_device *dev;
-	MPT_ADAPTER *p;
-	int i, j;
+	MPT_ADAPTER 		*ioc = pci_get_drvdata(pdev);
+	struct net_device	*dev;
+	int			i;
+
+	for (i = 0; i < ioc->facts.NumberOfPorts; i++) {
+		printk(KERN_INFO MYNAM ": %s: PortNum=%x, "
+		       "ProtocolFlags=%02Xh (%c%c%c%c)\n",
+		       ioc->name, ioc->pfacts[i].PortNumber,
+		       ioc->pfacts[i].ProtocolFlags,
+		       MPT_PROTOCOL_FLAGS_c_c_c_c(
+			       ioc->pfacts[i].ProtocolFlags));
+
+		if (!(ioc->pfacts[i].ProtocolFlags &
+					MPI_PORTFACTS_PROTOCOL_LAN)) {
+			printk(KERN_INFO MYNAM ": %s: Hmmm... LAN protocol "
+			       "seems to be disabled on this adapter port!\n",
+			       ioc->name);
+			continue;
+		}
 
-	show_mptmod_ver(LANAME, LANVER);
+		dev = mpt_register_lan_device(ioc, i);
+		if (!dev) {
+			printk(KERN_ERR MYNAM ": %s: Unable to register "
+			       "port%d as a LAN device\n", ioc->name,
+			       ioc->pfacts[i].PortNumber);
+			continue;
+		}
+		
+		printk(KERN_INFO MYNAM ": %s: Fusion MPT LAN device "
+		       "registered as '%s'\n", ioc->name, dev->name);
+		printk(KERN_INFO MYNAM ": %s/%s: "
+		       "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
+		       IOC_AND_NETDEV_NAMES_s_s(dev),
+		       dev->dev_addr[0], dev->dev_addr[1],
+		       dev->dev_addr[2], dev->dev_addr[3],
+		       dev->dev_addr[4], dev->dev_addr[5]);
+	
+		ioc->netdev = dev;
 
-#ifdef QLOGIC_NAA_WORKAROUND
-	/* Init the global r/w lock for the bad_naa list. We want to do this
-	   before any boards are initialized and may be used. */
-	rwlock_init(&bad_naa_lock);
-#endif
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+static void
+mptlan_remove(struct pci_dev *pdev)
+{
+	MPT_ADAPTER 		*ioc = pci_get_drvdata(pdev);
+	struct net_device	*dev = ioc->netdev;
+
+	if(dev != NULL) {
+		unregister_netdev(dev);
+		free_netdev(dev);
+	}
+}
+
+static struct mpt_pci_driver mptlan_driver = {
+	.probe		= mptlan_probe,
+	.remove		= mptlan_remove,
+};
+
+static int __init mpt_lan_init (void)
+{
+	show_mptmod_ver(LANAME, LANVER);
 
 	if ((LanCtx = mpt_register(lan_reply, MPTLAN_DRIVER)) <= 0) {
 		printk (KERN_ERR MYNAM ": Failed to register with MPT base driver\n");
@@ -1476,88 +1528,32 @@ static int __init mpt_lan_init (void)
 
 	dlprintk((KERN_INFO MYNAM ": assigned context of %d\n", LanCtx));
 
-	if (mpt_reset_register(LanCtx, mpt_lan_ioc_reset) == 0) {
-		dlprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n"));
-	} else {
+	if (mpt_reset_register(LanCtx, mpt_lan_ioc_reset)) {
 		printk(KERN_ERR MYNAM ": Eieee! unable to register a reset "
 		       "handler with mptbase! The world is at an end! "
 		       "Everything is fading to black! Goodbye.\n");
 		return -EBUSY;
 	}
 
-	for (j = 0; j < MPT_MAX_ADAPTERS; j++) {
-		mpt_landev[j] = NULL;
-	}
-
-	list_for_each_entry(p, &ioc_list, list) {
-		for (i = 0; i < p->facts.NumberOfPorts; i++) {
-			printk (KERN_INFO MYNAM ": %s: PortNum=%x, ProtocolFlags=%02Xh (%c%c%c%c)\n",
-					p->name,
-					p->pfacts[i].PortNumber,
-					p->pfacts[i].ProtocolFlags,
-					MPT_PROTOCOL_FLAGS_c_c_c_c(p->pfacts[i].ProtocolFlags));
-
-			if (!(p->pfacts[i].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
-				printk (KERN_INFO MYNAM ": %s: Hmmm... LAN protocol seems to be disabled on this adapter port!\n",
-						p->name);
-				continue;
-			}
-
-			dev = mpt_register_lan_device (p, i);
-			if (!dev) {
-				printk (KERN_ERR MYNAM ": %s: Unable to register port%d as a LAN device\n",
-						p->name,
-						p->pfacts[i].PortNumber);
-			}
-			printk (KERN_INFO MYNAM ": %s: Fusion MPT LAN device registered as '%s'\n",
-					p->name, dev->name);
-			printk (KERN_INFO MYNAM ": %s/%s: LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
-					IOC_AND_NETDEV_NAMES_s_s(dev),
-					dev->dev_addr[0], dev->dev_addr[1],
-					dev->dev_addr[2], dev->dev_addr[3],
-					dev->dev_addr[4], dev->dev_addr[5]);
-//					printk (KERN_INFO MYNAM ": %s/%s: Max_TX_outstanding = %d\n",
-//							IOC_AND_NETDEV_NAMES_s_s(dev),
-//							NETDEV_TO_LANPRIV_PTR(dev)->tx_max_out);
-			j = p->id;
-			mpt_landev[j] = dev;
-			dlprintk((KERN_INFO MYNAM "/init: dev_addr=%p, mpt_landev[%d]=%p\n",
-					dev, j,  mpt_landev[j]));
-
-		}
-	}
-
+	dlprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n"));
+	
+	if (mpt_device_driver_register(&mptlan_driver, MPTLAN_DRIVER))
+		dprintk((KERN_INFO MYNAM ": failed to register dd callbacks\n"));
 	return 0;
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static void __exit mpt_lan_exit(void)
 {
-	int i;
-
+	mpt_device_driver_deregister(MPTLAN_DRIVER);
 	mpt_reset_deregister(LanCtx);
 
-	for (i = 0; mpt_landev[i] != NULL; i++) {
-		struct net_device *dev = mpt_landev[i];
-
-		printk (KERN_INFO ": %s/%s: Fusion MPT LAN device unregistered\n",
-			       IOC_AND_NETDEV_NAMES_s_s(dev));
-		unregister_netdev(dev);
-		free_netdev(dev);
-		mpt_landev[i] = NULL;
-	}
-
 	if (LanCtx >= 0) {
 		mpt_deregister(LanCtx);
 		LanCtx = -1;
 		mpt_lan_index = 0;
 	}
-
-	/* deregister any send/receive handler structs. I2Oism? */
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
 module_init(mpt_lan_init);
 module_exit(mpt_lan_exit);
 
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 8c82254b4..38c8fb77d 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -86,7 +86,6 @@
 
 #include "mptbase.h"
 #include "mptscsih.h"
-#include "isense.h"
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 #define my_NAME		"Fusion MPT SCSI Host driver"
@@ -100,6 +99,7 @@ MODULE_LICENSE("GPL");
 /* Set string for command line args from insmod */
 #ifdef MODULE
 char *mptscsih = NULL;
+MODULE_PARM(mptscsih, "s");
 #endif
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -114,6 +114,7 @@ typedef struct _BIG_SENSE_BUF {
 #define MPT_SCANDV_SOME_ERROR		(0x00000004)
 #define MPT_SCANDV_SELECTION_TIMEOUT	(0x00000008)
 #define MPT_SCANDV_ISSUE_SENSE		(0x00000010)
+#define MPT_SCANDV_FALLBACK		(0x00000020)
 
 #define MPT_SCANDV_MAX_RETRIES		(10)
 
@@ -161,15 +162,12 @@ static int	mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *
 static void	mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
 static int	mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
 
-static int	mptscsih_AddSGE(MPT_SCSI_HOST *hd, struct scsi_cmnd *SCpnt,
+static int	mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
 				 SCSIIORequest_t *pReq, int req_idx);
-static void	mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx);
-static int	mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init);
+static void	mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
 static void	copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
 static int	mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
 static u32	SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
-static MPT_FRAME_HDR *mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx);
-static void	post_pendingQ_commands(MPT_SCSI_HOST *hd);
 
 static int	mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag);
 static int	mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout, int sleepFlag);
@@ -178,7 +176,7 @@ static int	mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
 static int	mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
 
 static void	mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen);
-void		mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
+static void	mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
 static void	mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq);
 static void	mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr, int *configurationPtr, u8 flags);
 static void	mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id);
@@ -246,6 +244,7 @@ static struct work_struct	mptscsih_dvTask;
 static DECLARE_WAIT_QUEUE_HEAD (scandv_waitq);
 static int scandv_wait_done = 1;
 
+
 /* Driver default setup
  */
 static struct mptscsih_driver_setup
@@ -323,44 +322,47 @@ mptscsih_add_chain(char *pAddr, u8 next, u16 length, dma_addr_t dma_addr)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *	mptscsih_getFreeChainBuffes - Function to get a free chain
+ *	mptscsih_getFreeChainBuffer - Function to get a free chain
  *	from the MPT_SCSI_HOST FreeChainQ.
- *	@hd: Pointer to the MPT_SCSI_HOST instance
+ *	@ioc: Pointer to MPT_ADAPTER structure
  *	@req_idx: Index of the SCSI IO request frame. (output)
  *
  *	return SUCCESS or FAILED
  */
 static inline int
-mptscsih_getFreeChainBuffer(MPT_SCSI_HOST *hd, int *retIndex)
+mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex)
 {
 	MPT_FRAME_HDR *chainBuf;
 	unsigned long flags;
 	int rc;
 	int chain_idx;
 
-	spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
-	if (!Q_IS_EMPTY(&hd->FreeChainQ)) {
+	dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer called\n",
+			ioc->name));
+	spin_lock_irqsave(&ioc->FreeQlock, flags);
+	if (!Q_IS_EMPTY(&ioc->FreeChainQ)) {
 
 		int offset;
 
-		chainBuf = hd->FreeChainQ.head;
+		chainBuf = ioc->FreeChainQ.head;
 		Q_DEL_ITEM(&chainBuf->u.frame.linkage);
-		offset = (u8 *)chainBuf - (u8 *)hd->ChainBuffer;
-		chain_idx = offset / hd->ioc->req_sz;
+		offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer;
+		chain_idx = offset / ioc->req_sz;
 		rc = SUCCESS;
+		dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%p\n",
+			ioc->name, *retIndex, chainBuf));
 	}
 	else {
 		rc = FAILED;
 		chain_idx = MPT_HOST_NO_CHAIN;
+		dfailprintk((MYIOC_s_ERR_FMT "getFreeChainBuffer failed\n",
+			ioc->name));
 	}
-	spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
 
 	*retIndex = chain_idx;
 
-	dsgprintk((MYIOC_s_INFO_FMT "getFreeChainBuffer (index %d), got buf=%p\n",
-			hd->ioc->name, *retIndex, chainBuf));
-
 	return rc;
 } /* mptscsih_getFreeChainBuffer() */
 
@@ -368,14 +370,14 @@ mptscsih_getFreeChainBuffer(MPT_SCSI_HOST *hd, int *retIndex)
 /*
  *	mptscsih_AddSGE - Add a SGE (plus chain buffers) to the
  *	SCSIIORequest_t Message Frame.
- *	@hd: Pointer to MPT_SCSI_HOST structure
+ *	@ioc: Pointer to MPT_ADAPTER structure
  *	@SCpnt: Pointer to scsi_cmnd structure
  *	@pReq: Pointer to SCSIIORequest_t structure
  *
  *	Returns ...
  */
 static int
-mptscsih_AddSGE(MPT_SCSI_HOST *hd, struct scsi_cmnd *SCpnt,
+mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
 		SCSIIORequest_t *pReq, int req_idx)
 {
 	char 	*psge;
@@ -391,6 +393,7 @@ mptscsih_AddSGE(MPT_SCSI_HOST *hd, struct scsi_cmnd *SCpnt,
 	int	 newIndex;
 	int	 ii;
 	dma_addr_t v2;
+	u32	RequestNB;
 
 	sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;
 	if (sgdir == MPI_SCSIIO_CONTROL_WRITE)  {
@@ -400,25 +403,25 @@ mptscsih_AddSGE(MPT_SCSI_HOST *hd, struct scsi_cmnd *SCpnt,
 	}
 
 	psge = (char *) &pReq->SGL;
-	frm_sz = hd->ioc->req_sz;
+	frm_sz = ioc->req_sz;
 
 	/* Map the data portion, if any.
 	 * sges_left  = 0 if no data transfer.
 	 */
 	if ( (sges_left = SCpnt->use_sg) ) {
-		sges_left = pci_map_sg(hd->ioc->pcidev,
+		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(hd->ioc->pcidev,
+		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",
-				hd->ioc->name, SCpnt, SCpnt->request_bufflen));
+				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);
@@ -493,12 +496,16 @@ nextSGEset:
 			 * Update the chain element
 			 * Offset and Length fields.
 			 */
-			mptscsih_add_chain((char *)chainSge, 0, sgeOffset, hd->ChainBufferDMA + chain_dma_off);
+			mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
 		} else {
 			/* The current buffer is the original MF
 			 * and there is no Chain buffer.
 			 */
 			pReq->ChainOffset = 0;
+			RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor)  + 1) & 0x03;
+			dsgprintk((MYIOC_s_ERR_FMT 
+			    "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
+			ioc->RequestNB[req_idx] = RequestNB;
 		}
 	} else {
 		/* At least one chain buffer is needed.
@@ -513,7 +520,7 @@ nextSGEset:
 		 */
 
 		dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",
-				hd->ioc->name, sg_done));
+				ioc->name, sg_done));
 
 		/* Set LAST_ELEMENT flag for last non-chain element
 		 * in the buffer. Since psge points at the NEXT
@@ -537,13 +544,16 @@ nextSGEset:
 			 */
 			u8 nextChain = (u8) (sgeOffset >> 2);
 			sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));
-			mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, hd->ChainBufferDMA + chain_dma_off);
+			mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);
 		} else {
 			/* The original MF buffer requires a chain buffer -
 			 * set the offset.
 			 * Last element in this MF is a chain element.
 			 */
 			pReq->ChainOffset = (u8) (sgeOffset >> 2);
+			RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor)  + 1) & 0x03;
+			dsgprintk((MYIOC_s_ERR_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));
+			ioc->RequestNB[req_idx] = RequestNB;
 		}
 
 		sges_left -= sg_done;
@@ -552,19 +562,22 @@ nextSGEset:
 		/* NOTE: psge points to the beginning of the chain element
 		 * in current buffer. Get a chain buffer.
 		 */
-		if ((mptscsih_getFreeChainBuffer(hd, &newIndex)) == FAILED)
+		dsgprintk((MYIOC_s_INFO_FMT 
+		    "calling getFreeChainBuffer SCSI cmd=%02x (%p)\n",
+		    ioc->name, pReq->CDB[0], SCpnt));
+		if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED)
 			return FAILED;
 
 		/* Update the tracking arrays.
 		 * If chainSge == NULL, update ReqToChain, else ChainToChain
 		 */
 		if (chainSge) {
-			hd->ChainToChain[chain_idx] = newIndex;
+			ioc->ChainToChain[chain_idx] = newIndex;
 		} else {
-			hd->ReqToChain[req_idx] = newIndex;
+			ioc->ReqToChain[req_idx] = newIndex;
 		}
 		chain_idx = newIndex;
-		chain_dma_off = hd->ioc->req_sz * chain_idx;
+		chain_dma_off = ioc->req_sz * chain_idx;
 
 		/* Populate the chainSGE for the current buffer.
 		 * - Set chain buffer pointer to psge and fill
@@ -576,7 +589,7 @@ nextSGEset:
 
 		/* Start the SGE for the next buffer
 		 */
-		psge = (char *) (hd->ChainBuffer + chain_dma_off);
+		psge = (char *) (ioc->ChainBuffer + chain_dma_off);
 		sgeOffset = 0;
 		sg_done = 0;
 
@@ -631,7 +644,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 			printk(MYIOC_s_ERR_FMT "NULL ScsiCmd ptr!\n",
 			ioc->name);
 
-		mptscsih_freeChainBuffers(hd, req_idx);
+		mptscsih_freeChainBuffers(ioc, req_idx);
 		return 1;
 	}
 
@@ -674,14 +687,15 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 
 		status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
 		scsi_state = pScsiReply->SCSIState;
+		scsi_status = pScsiReply->SCSIStatus;
+		xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
 
-		dprintk((KERN_NOTICE "  Uh-Oh! (%d:%d:%d) mf=%p, mr=%p, sc=%p\n",
+		dreplyprintk((KERN_NOTICE " Reply (%d:%d:%d) mf=%p, mr=%p, sc=%p\n",
 				ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1],
 				mf, mr, sc));
-		dprintk((KERN_NOTICE "  IOCStatus=%04xh, SCSIState=%02xh"
-				", SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
-				status, scsi_state, pScsiReply->SCSIStatus,
-				le32_to_cpu(pScsiReply->IOCLogInfo)));
+		dreplyprintk((KERN_NOTICE "IOCStatus=%04xh SCSIState=%02xh"
+				" SCSIStatus=%02xh xfer_cnt=%08xh\n",
+				status, scsi_state, scsi_status, xfer_cnt));
 
 		if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
 			copy_sense_data(sc, hd, mf, pScsiReply);
@@ -701,7 +715,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 			 * But not: DID_BUS_BUSY lest one risk
 			 * killing interrupt handler:-(
 			 */
-			sc->result = STS_BUSY;
+			sc->result = SAM_STAT_BUSY;
 			break;
 
 		case MPI_IOCSTATUS_SCSI_INVALID_BUS:		/* 0x0041 */
@@ -731,13 +745,22 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 			break;
 
 		case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:	/* 0x0049 */
-			sc->result = (DRIVER_SENSE << 24) | (DID_OK << 16) | 
+			sc->resid = sc->request_bufflen - xfer_cnt;
+			if ( xfer_cnt >= sc->underflow ) {
+				/* Sufficient data transfer occurred */
+				sc->result = (DID_OK << 16) | scsi_status;
+			} else if ( xfer_cnt == 0 ) {
+				/* A CRC Error causes this condition; retry */ 
+				sc->result = (DRIVER_SENSE << 24) | (DID_OK << 16) | 
 					(CHECK_CONDITION << 1);
-			sc->sense_buffer[0] = 0x70;
-			sc->sense_buffer[2] = NO_SENSE;
-			sc->sense_buffer[12] = 0;
-			sc->sense_buffer[13] = 0;
-			dprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target));
+				sc->sense_buffer[0] = 0x70;
+				sc->sense_buffer[2] = NO_SENSE;
+				sc->sense_buffer[12] = 0;
+				sc->sense_buffer[13] = 0;
+			} else {
+				sc->result = DID_SOFT_ERROR << 16;
+			}
+			dreplyprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target));
 			break;
 		
 		case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:		/* 0x0045 */
@@ -745,9 +768,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 			 *  Do upfront check for valid SenseData and give it
 			 *  precedence!
 			 */
-			scsi_status = pScsiReply->SCSIStatus;
 			sc->result = (DID_OK << 16) | scsi_status;
-			xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
 			if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
 				/* Have already saved the status and sense data
 				 */
@@ -769,12 +790,12 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 
 			/* Give report and update residual count.
 			 */
-			dprintk((KERN_NOTICE "  sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
+			dreplyprintk((KERN_NOTICE "  sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
 					sc->underflow));
-			dprintk((KERN_NOTICE "  ActBytesXferd=%02xh\n", xfer_cnt));
+			dreplyprintk((KERN_NOTICE "  ActBytesXferd=%02xh\n", xfer_cnt));
 
 			sc->resid = sc->request_bufflen - xfer_cnt;
-			dprintk((KERN_NOTICE "  SET sc->resid=%02xh\n", sc->resid));
+			dreplyprintk((KERN_NOTICE "  SET sc->resid=%02xh\n", sc->resid));
 			
 			/* Report Queue Full
 			 */
@@ -785,7 +806,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 
 		case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:	/* 0x0040 */
 		case MPI_IOCSTATUS_SUCCESS:			/* 0x0000 */
-			sc->result = (DID_OK << 16) | pScsiReply->SCSIStatus;
+			scsi_status = pScsiReply->SCSIStatus;
+			sc->result = (DID_OK << 16) | scsi_status;
 			if (scsi_state == 0) {
 				;
 			} else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
@@ -851,7 +873,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 
 		}	/* switch(status) */
 
-		dprintk((KERN_NOTICE "  sc->result set to %08xh\n", sc->result));
+		dreplyprintk((KERN_NOTICE "  sc->result is %08xh\n", sc->result));
 	} /* end of address reply case */
 
 	/* Unmap the DMA buffers, if any. */
@@ -868,88 +890,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 	sc->scsi_done(sc);		/* Issue the command callback */
 
 	/* Free Chain buffers */
-	mptscsih_freeChainBuffers(hd, req_idx);
+	mptscsih_freeChainBuffers(ioc, req_idx);
 	return 1;
 }
 
-/*
- * Flush all commands on the doneQ.
- * Lock Q when deleting/adding members
- * Lock io_request_lock for OS callback.
- */
-static void
-flush_doneQ(MPT_SCSI_HOST *hd)
-{
-	MPT_DONE_Q	*buffer;
-	struct scsi_cmnd	*SCpnt;
-	unsigned long	 flags;
-
-	/* Flush the doneQ.
-	 */
-	dtmprintk((KERN_INFO MYNAM ": flush_doneQ called\n"));
-	while (1) {
-		spin_lock_irqsave(&hd->freedoneQlock, flags);
-		if (Q_IS_EMPTY(&hd->doneQ)) {
-			spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-			break;
-		}
-
-		buffer = hd->doneQ.head;
-		/* Delete from Q
-		 */
-		Q_DEL_ITEM(buffer);
-
-		/* Set the struct scsi_cmnd pointer
-		 */
-		SCpnt = (struct scsi_cmnd *) buffer->argp;
-		buffer->argp = NULL;
-
-		/* Add to the freeQ
-		 */
-		Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
-		spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-
-		/* Do the OS callback.
-		 */
-		SCpnt->scsi_done(SCpnt);
-	}
-
-	return;
-}
-
-/*
- * Search the doneQ for a specific command. If found, delete from Q.
- * Calling function will finish processing.
- */
-static void
-search_doneQ_for_cmd(MPT_SCSI_HOST *hd, struct scsi_cmnd *SCpnt)
-{
-	unsigned long	 flags;
-	MPT_DONE_Q	*buffer;
-
-	spin_lock_irqsave(&hd->freedoneQlock, flags);
-	if (!Q_IS_EMPTY(&hd->doneQ)) {
-		buffer = hd->doneQ.head;
-		do {
-			struct scsi_cmnd *sc = (struct scsi_cmnd *) buffer->argp;
-			if (SCpnt == sc) {
-				Q_DEL_ITEM(buffer);
-				SCpnt->result = sc->result;
-
-				/* Set the struct scsi_cmnd pointer
-				 */
-				buffer->argp = NULL;
-
-				/* Add to the freeQ
-				 */
-				Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
-				break;
-			}
-		} while ((buffer = buffer->forw) != (MPT_DONE_Q *) &hd->doneQ);
-	}
-	spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-	return;
-}
 
 /*
  *	mptscsih_flush_running_cmds - For each command found, search
@@ -964,12 +908,11 @@ search_doneQ_for_cmd(MPT_SCSI_HOST *hd, struct scsi_cmnd *SCpnt)
 static void
 mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
 {
+	MPT_ADAPTER *ioc = hd->ioc;
 	struct scsi_cmnd	*SCpnt;
 	MPT_FRAME_HDR	*mf;
-	MPT_DONE_Q	*buffer;
 	int		 ii;
-	int		 max = hd->ioc->req_depth;
-	unsigned long	 flags;
+	int		 max = ioc->req_depth;
 
 	dprintk((KERN_INFO MYNAM ": flush_ScsiLookup called\n"));
 	for (ii= 0; ii < max; ii++) {
@@ -978,16 +921,11 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
 			/* Command found.
 			 */
 
-			/* Search pendingQ, if found,
-			 * delete from Q.
-			 */
-			mptscsih_search_pendingQ(hd, ii);
-
 			/* Null ScsiLookup index
 			 */
 			hd->ScsiLookup[ii] = NULL;
 
-			mf = MPT_INDEX_2_MFPTR(hd->ioc, ii);
+			mf = MPT_INDEX_2_MFPTR(ioc, ii);
 			dmfprintk(( "flush: ScsiDone (mf=%p,sc=%p)\n",
 					mf, SCpnt));
 
@@ -997,12 +935,12 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
 			 */
 			if (scsi_device_online(SCpnt->device)) {
 				if (SCpnt->use_sg) {
-					pci_unmap_sg(hd->ioc->pcidev,
+					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(hd->ioc->pcidev,
+					pci_unmap_single(ioc->pcidev,
 						SCpnt->SCp.dma_handle,
 						SCpnt->request_bufflen,
 						SCpnt->sc_data_direction);
@@ -1012,37 +950,12 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
 			SCpnt->host_scribble = NULL;
 
 			/* Free Chain buffers */
-			mptscsih_freeChainBuffers(hd, ii);
+			mptscsih_freeChainBuffers(ioc, ii);
 
 			/* Free Message frames */
-			mpt_free_msg_frame(ScsiDoneCtx, hd->ioc, mf);
-
-#if 1
-			/* Post to doneQ, do not reply until POST phase
-			 * of reset handler....prevents new commands from
-			 * being queued.
-			 */
-			spin_lock_irqsave(&hd->freedoneQlock, flags);
-			if (!Q_IS_EMPTY(&hd->freeQ)) {
-				buffer = hd->freeQ.head;
-				Q_DEL_ITEM(buffer);
+			mpt_free_msg_frame(ioc, mf);
 
-				/* Set the struct scsi_cmnd pointer
-				 */
-				buffer->argp = (void *)SCpnt;
-
-				/* Add to the doneQ
-				 */
-				Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q);
-				spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-			} else {
-				spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-				SCpnt->scsi_done(SCpnt);
-			}
-#else
 			SCpnt->scsi_done(SCpnt);	/* Issue the command callback */
-#endif
-
 		}
 	}
 
@@ -1087,119 +1000,14 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
 			/* Cleanup
 			 */
 			hd->ScsiLookup[ii] = NULL;
-			mptscsih_freeChainBuffers(hd, ii);
-			mpt_free_msg_frame(ScsiDoneCtx, hd->ioc, (MPT_FRAME_HDR *)mf);
+			mptscsih_freeChainBuffers(hd->ioc, ii);
+			mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf);
 		}
 	}
 
 	return;
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *	mptscsih_initChainBuffers - Allocate memory for and initialize
- *	chain buffers, chain buffer control arrays and spinlock.
- *	@hd: Pointer to MPT_SCSI_HOST structure
- *	@init: If set, initialize the spin lock.
- */
-static int
-mptscsih_initChainBuffers (MPT_SCSI_HOST *hd, int init)
-{
-	MPT_FRAME_HDR	*chain;
-	u8		*mem;
-	unsigned long	flags;
-	int		sz, ii, num_chain;
-	int 		scale, num_sge;
-
-	/* chain buffer allocation done from PrimeIocFifos */	
-	if (hd->ioc->fifo_pool == NULL) 
-		return -1;
-	
-	hd->ChainBuffer = hd->ioc->chain_alloc;
-	hd->ChainBufferDMA = hd->ioc->chain_alloc_dma;
-	
-	dprintk((KERN_INFO "  ChainBuffer    @ %p(%p), sz=%d\n",
-		 hd->ChainBuffer, (void *)(ulong)hd->ChainBufferDMA, hd->ioc->chain_alloc_sz));
-		
-	/* ReqToChain size must equal the req_depth
-	 * index = req_idx
-	 */
-	if (hd->ReqToChain == NULL) {
-		sz = hd->ioc->req_depth * sizeof(int);
-		mem = kmalloc(sz, GFP_ATOMIC);
-		if (mem == NULL)
-			return -1;
-
-		hd->ReqToChain = (int *) mem;
-	}
-	for (ii = 0; ii < hd->ioc->req_depth; ii++)
-		hd->ReqToChain[ii] = MPT_HOST_NO_CHAIN;
-
-	/* ChainToChain size must equal the total number
-	 * of chain buffers to be allocated.
-	 * index = chain_idx
-	 *
-	 * Calculate the number of chain buffers needed(plus 1) per I/O
-	 * then multiply the the maximum number of simultaneous cmds
-	 *
-	 * num_sge = num sge in request frame + last chain buffer
-	 * scale = num sge per chain buffer if no chain element
-	 */
-	scale = hd->ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
-	if (sizeof(dma_addr_t) == sizeof(u64))
-		num_sge =  scale + (hd->ioc->req_sz - 60) / (sizeof(dma_addr_t) + sizeof(u32));
-	else
-		num_sge =  1+ scale + (hd->ioc->req_sz - 64) / (sizeof(dma_addr_t) + sizeof(u32));
-
-	num_chain = 1;
-	while (hd->max_sge - num_sge > 0) {
-		num_chain++;
-		num_sge += (scale - 1);
-	}
-	num_chain++;
-
-	if ((int) hd->ioc->chip_type > (int) FC929)
-		num_chain *= MPT_SCSI_CAN_QUEUE;
-	else
-		num_chain *= MPT_FC_CAN_QUEUE;
-
-	hd->num_chain = num_chain;
-
-	sz = num_chain * sizeof(int);
-	if (hd->ChainToChain == NULL) {
-		mem = kmalloc(sz, GFP_ATOMIC);
-		if (mem == NULL)
-			return -1;
-
-		hd->ChainToChain = (int *) mem;
-	} else {
-		mem = (u8 *) hd->ChainToChain;
-	}
-	memset(mem, 0xFF, sz);
-
-
-	/* Initialize the free chain Q.
-	 */
-	if (init) {
-		spin_lock_init(&hd->FreeChainQlock);
-	}
-
-	spin_lock_irqsave (&hd->FreeChainQlock, flags);
-	Q_INIT(&hd->FreeChainQ, MPT_FRAME_HDR);
-
-	/* Post the chain buffers to the FreeChainQ.
-	 */
-	mem = (u8 *)hd->ChainBuffer;
-	for (ii=0; ii < num_chain; ii++) {
-		chain = (MPT_FRAME_HDR *) mem;
-		Q_ADD_TAIL(&hd->FreeChainQ.head, &chain->u.frame.linkage, MPT_FRAME_HDR);
-		mem += hd->ioc->req_sz;
-	}
-	spin_unlock_irqrestore(&hd->FreeChainQlock, flags);
-
-	return 0;
-}
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *  Hack! It might be nice to report if a device is returning QUEUE_FULL
@@ -1254,7 +1062,6 @@ mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	struct Scsi_Host	*sh;
 	MPT_SCSI_HOST		*hd;
 	MPT_ADAPTER 		*ioc = pci_get_drvdata(pdev);
-	MPT_DONE_Q		*freedoneQ;
 	unsigned long		 flags;
 	int			 sz, ii;
 	int			 numSGE = 0;
@@ -1386,7 +1193,6 @@ mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
 	hd = (MPT_SCSI_HOST *) sh->hostdata;
 	hd->ioc = ioc;
-	hd->max_sge = sh->sg_tablesize;
 
 	if ((int)ioc->chip_type > (int)FC929)
 	hd->is_spi = 1;
@@ -1399,7 +1205,7 @@ mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	/* SCSI needs scsi_cmnd lookup table!
 	 * (with size equal to req_depth*PtrSz!)
 	 */
-	sz = hd->ioc->req_depth * sizeof(void *);
+	sz = ioc->req_depth * sizeof(void *);
 	mem = kmalloc(sz, GFP_ATOMIC);
 	if (mem == NULL) {
 		error = -ENOMEM;
@@ -1412,37 +1218,6 @@ mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
 		 ioc->name, hd->ScsiLookup, sz));
 		
-	if (mptscsih_initChainBuffers(hd, 1) < 0) {
-		error = -EINVAL;
-		goto mptscsih_probe_failed;
-	}
-
-	/* Allocate memory for free and doneQ's
-	 */
-	sz = sh->can_queue * sizeof(MPT_DONE_Q);
-	mem = kmalloc(sz, GFP_ATOMIC);
-	if (mem == NULL) {
-		error = -ENOMEM;
-		goto mptscsih_probe_failed;
-	}
-
-	memset(mem, 0xFF, sz);
-	hd->memQ = mem;
-
-	/* Initialize the free, done and pending Qs.
-	 */
-	Q_INIT(&hd->freeQ, MPT_DONE_Q);
-	Q_INIT(&hd->doneQ, MPT_DONE_Q);
-	Q_INIT(&hd->pendingQ, MPT_DONE_Q);
-	spin_lock_init(&hd->freedoneQlock);
-
-	mem = hd->memQ;
-	for (ii=0; ii < sh->can_queue; ii++) {
-		freedoneQ = (MPT_DONE_Q *) mem;
-		Q_ADD_TAIL(&hd->freeQ.head, freedoneQ, MPT_DONE_Q);
-		mem += sizeof(MPT_DONE_Q);
-	}
-
 	/* Initialize this Scsi_Host
 	 * internal task Q.
 	 */
@@ -1474,8 +1249,7 @@ mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	hd->resetPending = 0;
 	hd->abortSCpnt = NULL;
 	hd->tmPtr = NULL;
-	hd->numTMrequests = 0;
-		
+
 	/* Clear the pointer used to store
 	 * single-threaded commands, i.e., those
 	 * issued during a bus scan, dv and
@@ -1500,10 +1274,10 @@ mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	/* ioc->sh = sh;	*/
 
 #ifdef MPTSCSIH_DBG_TIMEOUT
-	hd->ioc->timeout_hard = 0;
-	hd->ioc->timeout_delta = 30 * HZ;
-	hd->ioc->timeout_maxcnt = 0;
-	hd->ioc->timeout_cnt = 0;
+	ioc->timeout_hard = 0;
+	ioc->timeout_delta = 30 * HZ;
+	ioc->timeout_maxcnt = 0;
+	ioc->timeout_cnt = 0;
 	for (ii=0; ii < 8; ii++)
 		foo_to[ii] = NULL;
 #endif
@@ -1511,47 +1285,41 @@ mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		/* Update with the driver setup
 		 * values.
 		 */
-		if (hd->ioc->spi_data.maxBusWidth >
+		if (ioc->spi_data.maxBusWidth >
 		  driver_setup.max_width) {
-			hd->ioc->spi_data.maxBusWidth =
+			ioc->spi_data.maxBusWidth =
 			  driver_setup.max_width;
 		}
 
-		if (hd->ioc->spi_data.minSyncFactor <
+		if (ioc->spi_data.minSyncFactor <
 		  driver_setup.min_sync_fac) {
-			hd->ioc->spi_data.minSyncFactor =
+			ioc->spi_data.minSyncFactor =
 			  driver_setup.min_sync_fac;
 		}
 
-		if (hd->ioc->spi_data.minSyncFactor == MPT_ASYNC) {
-			hd->ioc->spi_data.maxSyncOffset = 0;
+		if (ioc->spi_data.minSyncFactor == MPT_ASYNC) {
+			ioc->spi_data.maxSyncOffset = 0;
 		}
 
-		hd->ioc->spi_data.Saf_Te = driver_setup.saf_te;
+		ioc->spi_data.Saf_Te = driver_setup.saf_te;
 
 		hd->negoNvram = 0;
 #ifndef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
 		hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
 #endif
-		if (driver_setup.dv == 0) {
-			hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
-		}
-
-		hd->ioc->spi_data.forceDv = 0;
+		ioc->spi_data.forceDv = 0;
 		for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
-			hd->ioc->spi_data.dvStatus[ii] =
+			ioc->spi_data.dvStatus[ii] =
 			  MPT_SCSICFG_NEGOTIATE;
 		}
 
-		if (hd->negoNvram == 0) {
-			for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
-				hd->ioc->spi_data.dvStatus[ii] |=
-				  MPT_SCSICFG_DV_NOT_DONE;
-		}
+		for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
+			ioc->spi_data.dvStatus[ii] |=
+			  MPT_SCSICFG_DV_NOT_DONE;
 
 		ddvprintk((MYIOC_s_INFO_FMT
 			"dv %x width %x factor %x saf_te %x\n",
-			hd->ioc->name, driver_setup.dv,
+			ioc->name, driver_setup.dv,
 			driver_setup.max_width,
 			driver_setup.min_sync_fac,
 			driver_setup.saf_te));
@@ -1620,14 +1388,11 @@ mptscsih_remove(struct pci_dev *pdev)
 
 	hd = (MPT_SCSI_HOST *)host->hostdata;
 	if (hd != NULL) {
-		int sz1, sz2, sz3, sztarget=0;
-		int szr2chain = 0;
-		int szc2chain = 0;
-		int szQ = 0;
+		int sz1, sz3, sztarget=0;
 
 		mptscsih_shutdown(&pdev->dev);
 
-		sz1 = sz2 = sz3 = 0;
+		sz1 = sz3 = 0;
 
 		if (hd->ScsiLookup != NULL) {
 			sz1 = hd->ioc->req_depth * sizeof(void *);
@@ -1635,24 +1400,6 @@ mptscsih_remove(struct pci_dev *pdev)
 			hd->ScsiLookup = NULL;
 		}
 
-		if (hd->ReqToChain != NULL) {
-			szr2chain = hd->ioc->req_depth * sizeof(int);
-			kfree(hd->ReqToChain);
-			hd->ReqToChain = NULL;
-		}
-
-		if (hd->ChainToChain != NULL) {
-			szc2chain = hd->num_chain * sizeof(int);
-			kfree(hd->ChainToChain);
-			hd->ChainToChain = NULL;
-		}
-
-		if (hd->memQ != NULL) {
-			szQ = host->can_queue * sizeof(MPT_DONE_Q);
-			kfree(hd->memQ);
-			hd->memQ = NULL;
-		}
-
 		if (hd->Targets != NULL) {
 			int max, ii;
 
@@ -1680,9 +1427,9 @@ mptscsih_remove(struct pci_dev *pdev)
 			hd->Targets = NULL;
 		}
 
-		dprintk((MYIOC_s_INFO_FMT
-		  "Free'd ScsiLookup (%d) Target (%d+%d) memory\n",
-		  hd->ioc->name, sz1, sz3, sztarget));
+		dprintk((MYIOC_s_INFO_FMT 
+		    "Free'd ScsiLookup (%d) Target (%d+%d) memory\n",
+		    hd->ioc->name, sz1, sz3, sztarget));
 		dprintk(("Free'd done and free Q (%d) memory\n", szQ));
 
 		/* NULL the Scsi_Host pointer
@@ -1802,7 +1549,7 @@ mptscsih_init(void)
 	ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER);
 
 	if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) {
-		dprintk((KERN_INFO MYNAM
+		devtprintk((KERN_INFO MYNAM
 		  ": Registered for IOC event notifications\n"));
 	}
 
@@ -1864,7 +1611,7 @@ mptscsih_exit(void)
  *
  *	Returns pointer to buffer where information was written.
  */
-const char *
+static const char *
 mptscsih_info(struct Scsi_Host *SChost)
 {
 	MPT_SCSI_HOST *h;
@@ -2079,7 +1826,8 @@ static int mptscsih_user_command(MPT_ADAPTER *ioc, char *buffer, int length)
  * 	hostno: scsi host number
  *	func:   if write = 1; if read = 0
  */
-int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
+static int 
+mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
 			int length, int func)
 {
 	MPT_SCSI_HOST	*hd = (MPT_SCSI_HOST *)host->hostdata;
@@ -2114,15 +1862,13 @@ int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t
  *
  *	Returns 0. (rtn value discarded by linux scsi mid-layer)
  */
-int
+static int
 mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 {
 	MPT_SCSI_HOST		*hd;
 	MPT_FRAME_HDR		*mf;
 	SCSIIORequest_t		*pScsiReq;
 	VirtDevice		*pTarget;
-	MPT_DONE_Q		*buffer;
-	unsigned long		 flags;
 	int	 target;
 	int	 lun;
 	u32	 datalen;
@@ -2147,16 +1893,9 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 			(hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done));
 
 	if (hd->resetPending) {
-		/* Prevent new commands from being issued
-		 * while reloading the FW. Reset timer to 60 seconds,
-		 * as the FW can take some time to come ready.
-		 * For New EH, cmds on doneQ posted to FW.
-		 */
-		did_errcode = 1;
-		mod_timer(&SCpnt->eh_timeout, jiffies + (HZ * 60));
 		dtmprintk((MYIOC_s_WARN_FMT "qcmd: SCpnt=%p timeout + 60HZ\n",
 			(hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
-		goto did_error;
+		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
 	/*
@@ -2165,8 +1904,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 	if ((mf = mpt_get_msg_frame(ScsiDoneCtx, hd->ioc)) == NULL) {
 		dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
 				hd->ioc->name));
-		did_errcode = 2;
-		goto did_error;
+		return SCSI_MLQUEUE_HOST_BUSY;
 	}
 
 	pScsiReq = (SCSIIORequest_t *) mf;
@@ -2249,7 +1987,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 			(dma_addr_t) -1);
 	} else {
 		/* Add a 32 or 64 bit SGE */
-		rc = mptscsih_AddSGE(hd, SCpnt, pScsiReq, my_idx);
+		rc = mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx);
 	}
 
 
@@ -2283,7 +2021,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 				}
 
 				/* Trying to do DV to this target, extend timeout.
-				 * Wait to issue intil flag is clear
+				 * Wait to issue until flag is clear
 				 */
 				if (dvStatus & MPT_SCSICFG_DV_PENDING) {
 					mod_timer(&SCpnt->eh_timeout, jiffies + 40 * HZ);
@@ -2314,64 +2052,18 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 			mpt_put_msg_frame(ScsiDoneCtx, hd->ioc, mf);
 			dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
 					hd->ioc->name, SCpnt, mf, my_idx));
-		} else {
-			ddvtprintk((MYIOC_s_INFO_FMT "Pending cmd=%p idx %d\n",
-					hd->ioc->name, SCpnt, my_idx));
-			/* Place this command on the pendingQ if possible */
-			spin_lock_irqsave(&hd->freedoneQlock, flags);
-			if (!Q_IS_EMPTY(&hd->freeQ)) {
-				buffer = hd->freeQ.head;
-				Q_DEL_ITEM(buffer);
-
-				/* Save the mf pointer
-				 */
-				buffer->argp = (void *)mf;
-
-				/* Add to the pendingQ
-				 */
-				Q_ADD_TAIL(&hd->pendingQ.head, buffer, MPT_DONE_Q);
-				spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-			} else {
-				spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-				SCpnt->result = (DID_BUS_BUSY << 16);
-				SCpnt->scsi_done(SCpnt);
-			}
-		}
-	} else {
-		mptscsih_freeChainBuffers(hd, my_idx);
-		mpt_free_msg_frame(ScsiDoneCtx, hd->ioc, mf);
-		did_errcode = 3;
-		goto did_error;
-	}
+			DBG_DUMP_REQUEST_FRAME(mf)
+		} else
+			goto fail;
+	} else
+		goto fail;
 
 	return 0;
 
-did_error:
-	dprintk((MYIOC_s_WARN_FMT "_qcmd did_errcode=%d (sc=%p)\n",
-			hd->ioc->name, did_errcode, SCpnt));
-	/* Just wish OS to issue a retry */
-	SCpnt->result = (DID_BUS_BUSY << 16);
-	spin_lock_irqsave(&hd->freedoneQlock, flags);
-	if (!Q_IS_EMPTY(&hd->freeQ)) {
-		dtmprintk((MYIOC_s_WARN_FMT "SCpnt=%p to doneQ\n",
-			(hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt));
-		buffer = hd->freeQ.head;
-		Q_DEL_ITEM(buffer);
-
-		/* Set the scsi_cmnd pointer
-		 */
-		buffer->argp = (void *)SCpnt;
-
-		/* Add to the doneQ
-		 */
-		Q_ADD_TAIL(&hd->doneQ.head, buffer, MPT_DONE_Q);
-		spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-	} else {
-		spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-		SCpnt->scsi_done(SCpnt);
-	}
-
-	return 0;
+ fail:
+	mptscsih_freeChainBuffers(hd->ioc, my_idx);
+	mpt_free_msg_frame(hd->ioc, mf);
+	return SCSI_MLQUEUE_HOST_BUSY;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2385,7 +2077,7 @@ did_error:
  *	No return.
  */
 static void
-mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx)
+mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx)
 {
 	MPT_FRAME_HDR *chain;
 	unsigned long flags;
@@ -2395,28 +2087,28 @@ mptscsih_freeChainBuffers(MPT_SCSI_HOST *hd, int req_idx)
 	/* Get the first chain index and reset
 	 * tracker state.
 	 */
-	chain_idx = hd->ReqToChain[req_idx];
-	hd->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
+	chain_idx = ioc->ReqToChain[req_idx];
+	ioc->ReqToChain[req_idx] = MPT_HOST_NO_CHAIN;
 
 	while (chain_idx != MPT_HOST_NO_CHAIN) {
 
 		/* Save the next chain buffer index */
-		next = hd->ChainToChain[chain_idx];
+		next = ioc->ChainToChain[chain_idx];
 
 		/* Free this chain buffer and reset
 		 * tracker
 		 */
-		hd->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
+		ioc->ChainToChain[chain_idx] = MPT_HOST_NO_CHAIN;
 
-		chain = (MPT_FRAME_HDR *) (hd->ChainBuffer
-					+ (chain_idx * hd->ioc->req_sz));
-		spin_lock_irqsave(&hd->ioc->FreeQlock, flags);
-		Q_ADD_TAIL(&hd->FreeChainQ.head,
+		chain = (MPT_FRAME_HDR *) (ioc->ChainBuffer
+					+ (chain_idx * ioc->req_sz));
+		spin_lock_irqsave(&ioc->FreeQlock, flags);
+		Q_ADD_TAIL(&ioc->FreeChainQ.head,
 					&chain->u.frame.linkage, MPT_FRAME_HDR);
-		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
+		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 
 		dmfprintk((MYIOC_s_INFO_FMT "FreeChainBuffers (index %d)\n",
-				hd->ioc->name, chain_idx));
+				ioc->name, chain_idx));
 
 		/* handle next */
 		chain_idx = next;
@@ -2480,12 +2172,6 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, in
 	}
 	spin_unlock_irqrestore(&ioc->diagLock, flags);
 
-	/* Do not do a Task Management if there are
-	 * too many failed TMs on this adapter.
-	 */
-	if (hd->numTMrequests > MPT_HOST_TOO_MANY_TM)
-		doTask = 0;
-
 	/*  Wait a fixed amount of time for the TM pending flag to be cleared.
 	 *  If we time out and not bus reset, then we return a FAILED status to the caller.
 	 *  The call to mptscsih_tm_pending_wait() will set the pending flag if we are
@@ -2593,7 +2279,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun
 	/* Return Fail to calling function if no message frames available.
 	 */
 	if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc)) == NULL) {
-		dtmprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!\n",
+		dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
 				hd->ioc->name));
 		//return FAILED;
 		return -999;
@@ -2624,29 +2310,30 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun
 		pScsiTm->Reserved2[ii] = 0;
 
 	pScsiTm->TaskMsgContext = ctx2abort;
-	dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt, ctx2abort (0x%08x), type (%d)\n",
-			hd->ioc->name, ctx2abort, type));
 
 	/* MPI v0.10 requires SCSITaskMgmt requests be sent via Doorbell/handshake
 		mpt_put_msg_frame(hd->ioc->id, mf);
 	* Save the MF pointer in case the request times out.
 	*/
 	hd->tmPtr = mf;
-	hd->numTMrequests++;
 	hd->TMtimer.expires = jiffies + timeout;
 	add_timer(&hd->TMtimer);
 
+	dtmprintk((MYIOC_s_INFO_FMT "IssueTaskMgmt: ctx2abort (0x%08x) type=%d\n",
+			hd->ioc->name, ctx2abort, type));
+
+	DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
+
 	if ((retval = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc,
 				sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, sleepFlag))
 	!= 0) {
-		dtmprintk((MYIOC_s_WARN_FMT "_send_handshake FAILED!"
+		dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
 			" (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, hd->ioc, mf));
-		hd->numTMrequests--;
 		hd->tmPtr = NULL;
 		del_timer(&hd->TMtimer);
-		mpt_free_msg_frame(ScsiTaskCtx, hd->ioc, mf);
+		mpt_free_msg_frame(hd->ioc, mf);
 	}
-
+	
 	return retval;
 }
 
@@ -2659,10 +2346,11 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun
  *
  *	Returns SUCCESS or FAILED.
  */
-int
+static int
 mptscsih_abort(struct scsi_cmnd * SCpnt)
 {
 	MPT_SCSI_HOST	*hd;
+	MPT_ADAPTER	*ioc;
 	MPT_FRAME_HDR	*mf;
 	u32		 ctx2abort;
 	int		 scpnt_idx;
@@ -2673,12 +2361,13 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 	if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) {
 		SCpnt->result = DID_RESET << 16;
 		SCpnt->scsi_done(SCpnt);
-		dtmprintk((KERN_WARNING MYNAM ": mptscsih_abort: "
+		dfailprintk((KERN_WARNING MYNAM ": mptscsih_abort: "
 			   "Can't locate host! (sc=%p)\n",
 			   SCpnt));
 		return FAILED;
 	}
 
+	ioc = hd->ioc;
 	if (hd->resetPending)
 		return FAILED;
 
@@ -2691,11 +2380,9 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 	/* Find this command
 	 */
 	if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) {
-		/* Cmd not found in ScsiLookup. If found in
-		 * doneQ, delete from Q. Do OS callback.
+		/* Cmd not found in ScsiLookup. 
+		 * Do OS callback.
 		 */
-		search_doneQ_for_cmd(hd, SCpnt);
-
 		SCpnt->result = DID_RESET << 16;
 		dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
 			   "Command not in the active list! (sc=%p)\n",
@@ -2703,18 +2390,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 		return SUCCESS;
 	}
 
-	/* If this command is pended, then timeout/hang occurred
-	 * during DV. Post command and flush pending Q
-	 * and then following up with the reset request.
-	 */
-	if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
-		mpt_put_msg_frame(ScsiDoneCtx, hd->ioc, mf);
-		post_pendingQ_commands(hd);
-		dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
-			   "Posting pended cmd! (sc=%p)\n",
-			   hd->ioc->name, SCpnt));
-	}
-
 	/* Most important!  Set TaskMsgContext to SCpnt's MsgContext!
 	 * (the IO to be ABORT'd)
 	 *
@@ -2724,7 +2399,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 	 */
 	mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
 	ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext;
-
+	
 	hd->abortSCpnt = SCpnt;
 
 	spin_unlock_irq(host_lock);
@@ -2743,12 +2418,26 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
 		 */
 		hd->tmPending = 0;
 		hd->tmState = TM_STATE_NONE;
-
+		
 		spin_lock_irq(host_lock);
+
+		/* Unmap the DMA buffers, if any. */
+		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);
+		}
+		hd->ScsiLookup[scpnt_idx] = NULL;
+		SCpnt->result = DID_RESET << 16;
+		SCpnt->scsi_done(SCpnt);		/* Issue the command callback */
+		mptscsih_freeChainBuffers(ioc, scpnt_idx);
+		mpt_free_msg_frame(ioc, mf);
 		return FAILED;
 	}
 	spin_lock_irq(host_lock);
-	return FAILED;
+	return SUCCESS;
 
 }
 
@@ -2761,7 +2450,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
  *
  *	Returns SUCCESS or FAILED.
  */
-int
+static int
 mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
 {
 	MPT_SCSI_HOST	*hd;
@@ -2816,7 +2505,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
  *
  *	Returns SUCCESS or FAILED.
  */
-int
+static int
 mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
 {
 	MPT_SCSI_HOST	*hd;
@@ -2839,9 +2528,6 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
 
 	/* We are now ready to execute the task management request. */
 	spin_unlock_irq(host_lock);
-//	printk("testing start : mptscsih_schedule_reset\n");
-//	mptscsih_schedule_reset(hd);
-//	printk("testing end: mptscsih_schedule_reset\n");
 	if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
 		SCpnt->device->channel, 0, 0, 0, (HZ*5) /* 5 second timeout */, CAN_SLEEP)
 	    < 0){
@@ -2871,7 +2557,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
  *
  *	Returns SUCCESS or FAILED.
  */
-int
+static int
 mptscsih_host_reset(struct scsi_cmnd *SCpnt)
 {
 	MPT_SCSI_HOST *  hd;
@@ -2937,8 +2623,7 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd)
 			break;
 		}
 		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ/4);
+		msleep(250);
 	} while (--loop_count);
 
 	return status;
@@ -2965,9 +2650,10 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
 	SCSITaskMgmt_t		*pScsiTmReq;
 	MPT_SCSI_HOST		*hd;
 	unsigned long		 flags;
-	u8			 tmType = 0;
+	u16			 iocstatus;
+	u8			 tmType;
 
-	dtmprintk((MYIOC_s_INFO_FMT "SCSI TaskMgmt completed (mf=%p,r=%p)\n",
+	dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt completed (mf=%p,mr=%p)\n",
 			ioc->name, mf, mr));
 	if (ioc->sh) {
 		/* Depending on the thread, a timer is activated for
@@ -2978,7 +2664,7 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
 		if (hd->tmPtr) {
 			del_timer(&hd->TMtimer);
 		}
-		dtmprintk((MYIOC_s_INFO_FMT "taskQcnt (%d)\n",
+		dtmprintk((MYIOC_s_WARN_FMT "taskQcnt (%d)\n",
 			ioc->name, hd->taskQcnt));
 	} else {
 		dtmprintk((MYIOC_s_WARN_FMT "TaskMgmt Complete: NULL Scsi Host Ptr\n",
@@ -2997,18 +2683,15 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
 		/* Figure out if this was ABORT_TASK, TARGET_RESET, or BUS_RESET! */
 		tmType = pScsiTmReq->TaskType;
 
-		dtmprintk((KERN_INFO "  TaskType = %d, TerminationCount=%d\n",
-				tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
+		dtmprintk((MYIOC_s_WARN_FMT "  TaskType = %d, TerminationCount=%d\n",
+				ioc->name, tmType, le32_to_cpu(pScsiTmReply->TerminationCount)));
+		DBG_DUMP_TM_REPLY_FRAME((u32 *)pScsiTmReply);
 
+		iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+		dtmprintk((MYIOC_s_WARN_FMT "  SCSI TaskMgmt (%d) IOCStatus=%04x IOCLogInfo=%08x\n",
+			ioc->name, tmType, iocstatus, le32_to_cpu(pScsiTmReply->IOCLogInfo)));
 		/* Error?  (anything non-zero?) */
-		if (*(u32 *)&pScsiTmReply->Reserved2[0]) {
-			u16	 iocstatus;
-
-			iocstatus = le16_to_cpu(pScsiTmReply->IOCStatus) & MPI_IOCSTATUS_MASK;
-			dtmprintk((KERN_INFO "  SCSI TaskMgmt (%d) - Oops!\n", tmType));
-			dtmprintk((KERN_INFO "  IOCStatus = %04xh\n", iocstatus));
-			dtmprintk((KERN_INFO "  IOCLogInfo = %08xh\n",
-				 le32_to_cpu(pScsiTmReply->IOCLogInfo)));
+		if (iocstatus) {
 
 			/* clear flags and continue.
 			 */
@@ -3029,11 +2712,9 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
 				}
 			}
 		} else {
-			dtmprintk((KERN_INFO "  SCSI TaskMgmt SUCCESS!\n"));
+			dtmprintk((MYIOC_s_WARN_FMT " TaskMgmt SUCCESS\n", ioc->name));
 
-			hd->numTMrequests--;
 			hd->abortSCpnt = NULL;
-			flush_doneQ(hd);
 
 		}
 	}
@@ -3051,26 +2732,21 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
 /*
  *	This is anyones guess quite frankly.
  */
-int
+static int
 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
 		sector_t capacity, int geom[])
 {
 	int		heads;
 	int		sectors;
 	sector_t	cylinders;
-#ifdef CONFIG_LBD
 	ulong 		dummy;
-#endif
 
 	heads = 64;
 	sectors = 32;
-#ifdef CONFIG_LBD
+
 	dummy = heads * sectors;
 	cylinders = capacity;
 	sector_div(cylinders,dummy);
-#else
-	cylinders = (ulong)capacity / (heads * sectors);
-#endif
 
 	/*
 	 * Handle extended translation size for logical drives
@@ -3079,13 +2755,9 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
 	if ((ulong)capacity >= 0x200000) {
 		heads = 255;
 		sectors = 63;
-#ifdef CONFIG_LBD
 		dummy = heads * sectors;
 		cylinders = capacity;
 		sector_div(cylinders,dummy);
-#else
-		cylinders = (ulong)capacity / (heads * sectors);
-#endif
 	}
 
 	/* return result */
@@ -3107,7 +2779,7 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
  *	Return non-zero if allocation fails.
  *	Init memory once per id (not LUN).
  */
-int
+static int
 mptscsih_slave_alloc(struct scsi_device *device)
 {
 	struct Scsi_Host	*host = device->host;
@@ -3130,12 +2802,21 @@ mptscsih_slave_alloc(struct scsi_device *device)
 			Q_INIT(&vdev->WaitQ, void);
 			Q_INIT(&vdev->SentQ, void);
 			Q_INIT(&vdev->DoneQ, void);
-			vdev->tflags = 0;
+			vdev->tflags = MPT_TARGET_FLAGS_Q_YES;
 			vdev->ioc_id = hd->ioc->id;
 			vdev->target_id = device->id;
-			vdev->bus_id = hd->port;
-
+			vdev->bus_id = device->channel;
+			vdev->raidVolume = 0;
 			hd->Targets[device->id] = vdev;
+			if (hd->is_spi) {
+				if (hd->ioc->spi_data.isRaid & (1 << device->id)) {
+					vdev->raidVolume = 1;
+					ddvtprintk((KERN_INFO
+					    "RAID Volume @ id %d\n", device->id));
+				}
+			} else {
+				vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
+			}
 		}
 	}
 	vdev->num_luns++;
@@ -3147,7 +2828,7 @@ mptscsih_slave_alloc(struct scsi_device *device)
  *	OS entry point to allow for host driver to free allocated memory
  *	Called if no device present or device being unloaded
  */
-void
+static void
 mptscsih_slave_destroy(struct scsi_device *device)
 {
 	struct Scsi_Host	*host = device->host;
@@ -3176,15 +2857,15 @@ mptscsih_slave_destroy(struct scsi_device *device)
 			kfree(hd->Targets[device->id]);
 			hd->Targets[device->id] = NULL;
 
-			if (!hd->is_spi) 
+			if (!hd->is_spi)
 				return;
 
 			if((hd->ioc->spi_data.isRaid) && (hd->ioc->spi_data.pIocPg3)) {
 			int i;
 				for(i=0;i<hd->ioc->spi_data.pIocPg3->NumPhysDisks &&
 					raid_volume==0;i++)
-						
-					if(device->id == 
+
+					if(device->id ==
 					  hd->ioc->spi_data.pIocPg3->PhysDisk[i].PhysDiskID) {
 						raid_volume=1;
 						hd->ioc->spi_data.forceDv |=
@@ -3202,7 +2883,7 @@ mptscsih_slave_destroy(struct scsi_device *device)
 			}
 		}
 	}
-	
+
 	return;
 }
 
@@ -3212,7 +2893,7 @@ mptscsih_slave_destroy(struct scsi_device *device)
  *	member to 1 if a device does not support Q tags.
  *	Return non-zero if fails.
  */
-int
+static int
 mptscsih_slave_configure(struct scsi_device *device)
 {
 	struct Scsi_Host	*sh = device->host;
@@ -3240,8 +2921,16 @@ mptscsih_slave_configure(struct scsi_device *device)
 	pTarget = hd->Targets[device->id];
 
 	if (pTarget == NULL) {
-		/* error case - don't know about this device */
-		scsi_adjust_queue_depth(device, 0, 1);
+		/* Driver doesn't know about this device.
+		 * Kernel may generate a "Dummy Lun 0" which
+		 * may become a real Lun if a 
+		 * "scsi add-single-device" command is executed
+		 * while the driver is active (hot-plug a 
+		 * device).  LSI Raid controllers need 
+		 * queue_depth set to DEV_HIGH for this reason.
+		 */
+		scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG,
+			MPT_SCSI_CMD_PER_DEV_HIGH);
 		goto slave_configure_exit;
 	}
 
@@ -3302,8 +2991,6 @@ copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSI
 	SCSIIORequest_t	*pReq;
 	u32		 sense_count = le32_to_cpu(pScsiReply->SenseCount);
 	int		 index;
-	char		 devFoo[96];
-	IO_Info_t	 thisIo;
 
 	/* Get target structure
 	 */
@@ -3342,35 +3029,10 @@ copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSI
 				ioc->eventContext++;
 			}
 		}
-
-		/* Print an error report for the user.
-		 */
-		thisIo.cdbPtr = sc->cmnd;
-		thisIo.sensePtr = sc->sense_buffer;
-		thisIo.SCSIStatus = pScsiReply->SCSIStatus;
-		thisIo.DoDisplay = 1;
-		if (hd->is_multipath)
-			sprintf(devFoo, "%d:%d:%d",
-					hd->ioc->id,
-					pReq->TargetID,
-					pReq->LUN[1]);
-		else
-			sprintf(devFoo, "%d:%d:%d", hd->ioc->id, sc->device->id, sc->device->lun);
-		thisIo.DevIDStr = devFoo;
-/* fubar */
-		thisIo.dataPtr = NULL;
-		thisIo.inqPtr = NULL;
-		if (sc->device) {
-			thisIo.inqPtr = sc->device->vendor-8;	/* FIXME!!! */
-		}
-		(void) mpt_ScsiHost_ErrorReport(&thisIo);
-
 	} else {
 		dprintk((MYIOC_s_INFO_FMT "Hmmm... SenseData len=0! (?)\n",
 				hd->ioc->name));
 	}
-
-	return;
 }
 
 static u32
@@ -3390,102 +3052,6 @@ SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
 	return -1;
 }
 
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* Search the pendingQ for a command with specific index.
- * If found, delete and return mf pointer
- * If not found, return NULL
- */
-static MPT_FRAME_HDR *
-mptscsih_search_pendingQ(MPT_SCSI_HOST *hd, int scpnt_idx)
-{
-	unsigned long	 flags;
-	MPT_DONE_Q	*buffer;
-	MPT_FRAME_HDR	*mf = NULL;
-	MPT_FRAME_HDR	*cmdMfPtr;
-
-	ddvtprintk((MYIOC_s_INFO_FMT ": search_pendingQ ...", hd->ioc->name));
-	cmdMfPtr = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx);
-	spin_lock_irqsave(&hd->freedoneQlock, flags);
-	if (!Q_IS_EMPTY(&hd->pendingQ)) {
-		buffer = hd->pendingQ.head;
-		do {
-			mf = (MPT_FRAME_HDR *) buffer->argp;
-			if (mf == cmdMfPtr) {
-				Q_DEL_ITEM(buffer);
-
-				/* clear the arg pointer
-				 */
-				buffer->argp = NULL;
-
-				/* Add to the freeQ
-				 */
-				Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
-				break;
-			}
-			mf = NULL;
-		} while ((buffer = buffer->forw) != (MPT_DONE_Q *) &hd->pendingQ);
-	}
-	spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-	ddvtprintk((" ...return %p\n", mf));
-	return mf;
-}
-
-/* Post all commands on the pendingQ to the FW.
- * Lock Q when deleting/adding members
- * Lock io_request_lock for OS callback.
- */
-static void
-post_pendingQ_commands(MPT_SCSI_HOST *hd)
-{
-	MPT_FRAME_HDR	*mf;
-	MPT_DONE_Q	*buffer;
-	unsigned long	 flags;
-
-	/* Flush the pendingQ.
-	 */
-	ddvtprintk((MYIOC_s_INFO_FMT ": post_pendingQ_commands\n", hd->ioc->name));
-	while (1) {
-		spin_lock_irqsave(&hd->freedoneQlock, flags);
-		if (Q_IS_EMPTY(&hd->pendingQ)) {
-			spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-			break;
-		}
-
-		buffer = hd->pendingQ.head;
-		/* Delete from Q
-		 */
-		Q_DEL_ITEM(buffer);
-
-		mf = (MPT_FRAME_HDR *) buffer->argp;
-		buffer->argp = NULL;
-
-		/* Add to the freeQ
-		 */
-		Q_ADD_TAIL(&hd->freeQ.head, buffer, MPT_DONE_Q);
-		spin_unlock_irqrestore(&hd->freedoneQlock, flags);
-
-		if (!mf) {
-			/* This should never happen */
-			printk(MYIOC_s_WARN_FMT "post_pendingQ_commands: mf %p\n", hd->ioc->name, (void *) mf);
-			continue;
-		}
-
-		mpt_put_msg_frame(ScsiDoneCtx, hd->ioc, mf);
-
-#if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
-		{
-			u16		 req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
-			struct scsi_cmnd	*sc = hd->ScsiLookup[req_idx];
-			printk(MYIOC_s_INFO_FMT "Issued SCSI cmd (sc=%p) idx=%d (mf=%p)\n",
-					hd->ioc->name, sc, req_idx, mf);
-		}
-#endif
-	}
-
-	return;
-}
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static int
 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
@@ -3520,14 +3086,10 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 		dtmprintk((MYIOC_s_WARN_FMT "Pre-Diag Reset\n", ioc->name));
 
 		/* 2. Flush running commands
-		 *	Clean drop test code - if compiled
 		 *	Clean ScsiLookup (and associated memory)
 		 *	AND clean mytaskQ
 		 */
 
-		/* 2a. Drop Test Command.
-		 */
-
 		/* 2b. Reply to OS all known outstanding I/O commands.
 		 */
 		mptscsih_flush_running_cmds(hd);
@@ -3538,7 +3100,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 		 */
 		if (hd->cmdPtr) {
 			del_timer(&hd->timer);
-			mpt_free_msg_frame(ScsiScanDvCtx, ioc, hd->cmdPtr);
+			mpt_free_msg_frame(ioc, hd->cmdPtr);
 		}
 
 		/* 2d. If a task management has not completed,
@@ -3546,7 +3108,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 		 */
 		if (hd->tmPtr) {
 			del_timer(&hd->TMtimer);
-			mpt_free_msg_frame(ScsiTaskCtx, ioc, hd->tmPtr);
+			mpt_free_msg_frame(ioc, hd->tmPtr);
 		}
 
 #ifdef MPTSCSIH_DBG_TIMEOUT
@@ -3573,7 +3135,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 
 		/* 2. Chain Buffer initialization
 		 */
-		mptscsih_initChainBuffers(hd, 0);
 
 		/* 3. tmPtr clear
 		 */
@@ -3583,8 +3144,10 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 
 		/* 4. Renegotiate to all devices, if SCSI
 		 */
-		if (hd->is_spi)
+		if (hd->is_spi) {
+			dnegoprintk(("writeSDP1: ALL_IDS USE_NVRAM\n"));
 			mptscsih_writeSDP1(hd, 0, 0, MPT_SCSICFG_ALL_IDS | MPT_SCSICFG_USE_NVRAM);
+		}
 
 		/* 5. Enable new commands to be posted
 		 */
@@ -3592,7 +3155,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 		hd->tmPending = 0;
 		spin_unlock_irqrestore(&ioc->FreeQlock, flags);
 		hd->resetPending = 0;
-		hd->numTMrequests = 0;
 		hd->tmState = TM_STATE_NONE;
 
 		/* 6. If there was an internal command,
@@ -3609,11 +3171,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 			hd->cmdPtr = NULL;
 		}
 
-		/* 7. Flush doneQ
-		 */
-		flush_doneQ(hd);
-
-		/* 8. Set flag to force DV and re-read IOC Page 3
+		/* 7. Set flag to force DV and re-read IOC Page 3
 		 */
 		if (hd->is_spi) {
 			ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
@@ -3634,7 +3192,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 	MPT_SCSI_HOST *hd;
 	u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
 
-	dprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
+	devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
 			ioc->name, event));
 
 	switch (event) {
@@ -3766,394 +3324,6 @@ static struct scsi_host_template driver_template = {
 	.use_clustering			= ENABLE_CLUSTERING,
 };
 
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *  Private data...
- */
-static ASCQ_Table_t *mptscsih_ASCQ_TablePtr;
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/* old symsense.c stuff... */
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- * Private data...
- * To protect ourselves against those that would pass us bogus pointers
- */
-static u8 dummyInqData[SCSI_STD_INQUIRY_BYTES]
-    = { 0x1F, 0x00, 0x00, 0x00,
-	0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-static u8 dummySenseData[SCSI_STD_SENSE_BYTES]
-    = { 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00 };
-static u8 dummyCDB[16]
-    = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-static u8 dummyScsiData[16]
-    = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
-static char *ScsiStatusString[] = {
-	"GOOD",					/* 00h */
-	NULL,					/* 01h */
-	"CHECK CONDITION",			/* 02h */
-	NULL,					/* 03h */
-	"CONDITION MET",			/* 04h */
-	NULL,					/* 05h */
-	NULL,					/* 06h */
-	NULL,					/* 07h */
-	"BUSY",					/* 08h */
-	NULL,					/* 09h */
-	NULL,					/* 0Ah */
-	NULL,					/* 0Bh */
-	NULL,					/* 0Ch */
-	NULL,					/* 0Dh */
-	NULL,					/* 0Eh */
-	NULL,					/* 0Fh */
-	"INTERMEDIATE",				/* 10h */
-	NULL,					/* 11h */
-	NULL,					/* 12h */
-	NULL,					/* 13h */
-	"INTERMEDIATE-CONDITION MET",		/* 14h */
-	NULL,					/* 15h */
-	NULL,					/* 16h */
-	NULL,					/* 17h */
-	"RESERVATION CONFLICT",			/* 18h */
-	NULL,					/* 19h */
-	NULL,					/* 1Ah */
-	NULL,					/* 1Bh */
-	NULL,					/* 1Ch */
-	NULL,					/* 1Dh */
-	NULL,					/* 1Eh */
-	NULL,					/* 1Fh */
-	NULL,					/* 20h */
-	NULL,					/* 21h */
-	"COMMAND TERMINATED",			/* 22h */
-	NULL,					/* 23h */
-	NULL,					/* 24h */
-	NULL,					/* 25h */
-	NULL,					/* 26h */
-	NULL,					/* 27h */
-	"TASK SET FULL",			/* 28h */
-	NULL,					/* 29h */
-	NULL,					/* 2Ah */
-	NULL,					/* 2Bh */
-	NULL,					/* 2Ch */
-	NULL,					/* 2Dh */
-	NULL,					/* 2Eh */
-	NULL,					/* 2Fh */
-	"ACA ACTIVE",				/* 30h */
-	NULL
-};
-
-static const char *ScsiCommonOpString[] = {
-	"TEST UNIT READY",			/* 00h */
-	"REZERO UNIT (REWIND)",			/* 01h */
-	NULL,					/* 02h */
-	"REQUEST_SENSE",			/* 03h */
-	"FORMAT UNIT (MEDIUM)",			/* 04h */
-	"READ BLOCK LIMITS",			/* 05h */
-	NULL,					/* 06h */
-	"REASSIGN BLOCKS",			/* 07h */
-	"READ(6)",				/* 08h */
-	NULL,					/* 09h */
-	"WRITE(6)",				/* 0Ah */
-	"SEEK(6)",				/* 0Bh */
-	NULL,					/* 0Ch */
-	NULL,					/* 0Dh */
-	NULL,					/* 0Eh */
-	"READ REVERSE",				/* 0Fh */
-	"WRITE_FILEMARKS",			/* 10h */
-	"SPACE(6)",				/* 11h */
-	"INQUIRY",				/* 12h */
-	NULL
-};
-
-static const char *SenseKeyString[] = {
-	"NO SENSE",				/* 0h */
-	"RECOVERED ERROR",			/* 1h */
-	"NOT READY",				/* 2h */
-	"MEDIUM ERROR",				/* 3h */
-	"HARDWARE ERROR",			/* 4h */
-	"ILLEGAL REQUEST",			/* 5h */
-	"UNIT ATTENTION",			/* 6h */
-	"DATA PROTECT",				/* 7h */
-	"BLANK CHECK",				/* 8h */
-	"VENDOR-SPECIFIC",			/* 9h */
-	"ABORTED COPY",				/* Ah */
-	"ABORTED COMMAND",			/* Bh */
-	"EQUAL (obsolete)",			/* Ch */
-	"VOLUME OVERFLOW",			/* Dh */
-	"MISCOMPARE",				/* Eh */
-	"RESERVED",				/* Fh */
-	NULL
-};
-
-#define SPECIAL_ASCQ(c,q) \
-	(((c) == 0x40 && (q) != 0x00) || ((c) == 0x4D) || ((c) == 0x70))
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int dump_cdb(char *foo, unsigned char *cdb)
-{
-	int i, grpCode, cdbLen;
-	int l = 0;
-
-	grpCode = cdb[0] >> 5;
-	if (grpCode < 1)
-		cdbLen = 6;
-	else if (grpCode < 3)
-		cdbLen = 10;
-	else if (grpCode == 5)
-		cdbLen = 12;
-	else
-		cdbLen = 16;
-
-	for (i=0; i < cdbLen; i++)
-		l += sprintf(foo+l, " %02X", cdb[i]);
-
-	return l;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*  Do ASC/ASCQ lookup/grindage to English readable string(s)  */
-static const char * ascq_set_strings_4max(
-		u8 ASC, u8 ASCQ,
-		const char **s1, const char **s2, const char **s3, const char **s4)
-{
-	static const char *asc_04_part1_string = "LOGICAL UNIT ";
-	static const char *asc_04_part2a_string = "NOT READY, ";
-	static const char *asc_04_part2b_string = "IS ";
-	static const char *asc_04_ascq_NN_part3_strings[] = {	/* ASC ASCQ (hex) */
-	  "CAUSE NOT REPORTABLE",				/* 04 00 */
-	  "IN PROCESS OF BECOMING READY",			/* 04 01 */
-	  "INITIALIZING CMD. REQUIRED",				/* 04 02 */
-	  "MANUAL INTERVENTION REQUIRED",			/* 04 03 */
-	  /* Add	" IN PROGRESS" to all the following... */
-	  "FORMAT",						/* 04 04 */
-	  "REBUILD",						/* 04 05 */
-	  "RECALCULATION",					/* 04 06 */
-	  "OPERATION",						/* 04 07 */
-	  "LONG WRITE",						/* 04 08 */
-	  "SELF-TEST",						/* 04 09 */
-	  NULL
-	};
-	static char *asc_04_part4_string = " IN PROGRESS";
-
-	static char *asc_29_ascq_NN_strings[] = {		/* ASC ASCQ (hex) */
-	  "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED",	/* 29 00 */
-	  "POWER ON OCCURRED",					/* 29 01 */
-	  "SCSI BUS RESET OCCURRED",				/* 29 02 */
-	  "BUS DEVICE RESET FUNCTION OCCURRED",			/* 29 03 */
-	  "DEVICE INTERNAL RESET",				/* 29 04 */
-	  "TRANSCEIVER MODE CHANGED TO SINGLE-ENDED",		/* 29 05 */
-	  "TRANSCEIVER MODE CHANGED TO LVD",			/* 29 06 */
-	  NULL
-	};
-	static char *ascq_vendor_uniq = "(Vendor Unique)";
-	static char *ascq_noone = "(no matching ASC/ASCQ description found)";
-	int idx;
-
-	*s1 = *s2 = *s3 = *s4 = "";		/* set'em all to the empty "" string */
-
-	/* CHECKME! Need lock/sem?
-	 *  Update and examine for isense module presense.
-	 */
-	mptscsih_ASCQ_TablePtr = (ASCQ_Table_t *)mpt_v_ASCQ_TablePtr;
-
-	if (mptscsih_ASCQ_TablePtr == NULL) {
-		/* 2nd chances... */
-		if (ASC == 0x04 && (ASCQ < sizeof(asc_04_ascq_NN_part3_strings)/sizeof(char*)-1)) {
-			*s1 = asc_04_part1_string;
-			*s2 = (ASCQ == 0x01) ? asc_04_part2b_string : asc_04_part2a_string;
-			*s3 = asc_04_ascq_NN_part3_strings[ASCQ];
-			/* check for " IN PROGRESS" ones */
-			if (ASCQ >= 0x04)
-				*s4 = asc_04_part4_string;
-		} else if (ASC == 0x29 && (ASCQ < sizeof(asc_29_ascq_NN_strings)/sizeof(char*)-1))
-			*s1 = asc_29_ascq_NN_strings[ASCQ];
-		/*
-		 *	Else { leave all *s[1-4] values pointing to the empty "" string }
-		 */
-		return *s1;
-	}
-
-	/*
-	 * Need to check ASC here; if it is "special," then
-	 * the ASCQ is variable, and indicates failed component number.
-	 * We must treat the ASCQ as a "don't care" while searching the
-	 * mptscsih_ASCQ_Table[] by masking it off, and then restoring it later
-	 * on when we actually need to identify the failed component.
-	 */
-	if (SPECIAL_ASCQ(ASC,ASCQ))
-		ASCQ = 0xFF;
-
-	/* OK, now search mptscsih_ASCQ_Table[] for a matching entry */
-	for (idx = 0; mptscsih_ASCQ_TablePtr && idx < mpt_ASCQ_TableSz; idx++)
-		if ((ASC == mptscsih_ASCQ_TablePtr[idx].ASC) && (ASCQ == mptscsih_ASCQ_TablePtr[idx].ASCQ)) {
-			*s1 = mptscsih_ASCQ_TablePtr[idx].Description;
-			return *s1;
-		}
-
-	if ((ASC >= 0x80) || (ASCQ >= 0x80))
-		*s1 = ascq_vendor_uniq;
-	else
-		*s1 = ascq_noone;
-
-	return *s1;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *  SCSI Information Report; desired output format...
- *---
-SCSI Error: (iocnum:target_id:LUN) Status=02h (CHECK CONDITION)
-  Key=6h (UNIT ATTENTION); FRU=03h
-  ASC/ASCQ=29h/00h, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"
-  CDB: 00 00 00 00 00 00 - TestUnitReady
- *---
- */
-/*
- *  SCSI Error Report; desired output format...
- *---
-SCSI Error Report =-=-=-=-=-=-=-=-=-=-=-=-=-= (ioc0,scsi0:0)
-  SCSI_Status=02h (CHECK CONDITION)
-  Original_CDB[]: 00 00 00 00 00 00 - TestUnitReady
-  SenseData[12h]: 70 00 06 00 00 00 00 0A 00 00 00 00 29 00 03 00 00 00
-  SenseKey=6h (UNIT ATTENTION); FRU=03h
-  ASC/ASCQ=29h/00h, "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"
- *---
- */
-
-int mpt_ScsiHost_ErrorReport(IO_Info_t *ioop)
-{
-	char		 foo[512];
-	char		 buf2[32];
-	char		*statstr;
-	const char	*opstr;
-	int		 sk		= SD_Sense_Key(ioop->sensePtr);
-	const char	*skstr		= SenseKeyString[sk];
-	unsigned char	 asc		= SD_ASC(ioop->sensePtr);
-	unsigned char	 ascq		= SD_ASCQ(ioop->sensePtr);
-	int		 l;
-
-	/* Change the error logging to only report errors on
-	 * read and write commands. Ignore errors on other commands.
-	 * Should this be configurable via proc?
-	 */
-	switch (ioop->cdbPtr[0]) {
-	case READ_6:
-	case WRITE_6:
-	case READ_10:
-	case WRITE_10:
-	case READ_12:
-	case WRITE_12:
-	case READ_16:
-	case WRITE_16:
-		break;
-	default:
-		return 0;
-	}
-
-	/*
-	 *  More quiet mode.
-	 *  Filter out common, repetitive, warning-type errors...  like:
-	 *    POWER ON (06,29/00 or 06,29/01),
-	 *    SPINNING UP (02,04/01),
-	 *    LOGICAL UNIT NOT SUPPORTED (05,25/00), etc.
-	 */
-	if (sk == SK_NO_SENSE) {
-		return 0;
-	}
-
-	if (	(sk==SK_UNIT_ATTENTION	&& asc==0x29 && (ascq==0x00 || ascq==0x01))
-	     || (sk==SK_NOT_READY	&& asc==0x04 && (ascq==0x01 || ascq==0x02))
-	     || (sk==SK_ILLEGAL_REQUEST && asc==0x25 && ascq==0x00)
-	   )
-	{
-		/* Do nothing! */
-		return 0;
-	}
-
-	/* Prevent the system from continually writing to the log
-	 * if a medium is not found: 02 3A 00
-	 * Changer issues: TUR, Read Capacity, Table of Contents continually
-	 */
-	if (sk==SK_NOT_READY && asc==0x3A) {
-		if (ioop->cdbPtr == NULL) {
-			return 0;
-		} else if ((ioop->cdbPtr[0] == CMD_TestUnitReady) ||
-			(ioop->cdbPtr[0] == CMD_ReadCapacity) ||
-			(ioop->cdbPtr[0] == 0x43)) {
-			return 0;
-		}
-	}
-	if (sk==SK_UNIT_ATTENTION) {
-		if (ioop->cdbPtr == NULL)
-			return 0;
-		else if (ioop->cdbPtr[0] == CMD_TestUnitReady)
-			return 0;
-	}
-
-	/*
-	 *  Protect ourselves...
-	 */
-	if (ioop->cdbPtr == NULL)
-		ioop->cdbPtr = dummyCDB;
-	if (ioop->sensePtr == NULL)
-		ioop->sensePtr = dummySenseData;
-	if (ioop->inqPtr == NULL)
-		ioop->inqPtr = dummyInqData;
-	if (ioop->dataPtr == NULL)
-		ioop->dataPtr = dummyScsiData;
-
-	statstr = NULL;
-	if ((ioop->SCSIStatus >= sizeof(ScsiStatusString)/sizeof(char*)-1) ||
-	    ((statstr = (char*)ScsiStatusString[ioop->SCSIStatus]) == NULL)) {
-		(void) sprintf(buf2, "Bad-Reserved-%02Xh", ioop->SCSIStatus);
-		statstr = buf2;
-	}
-
-	opstr = NULL;
-	if (1+ioop->cdbPtr[0] <= sizeof(ScsiCommonOpString)/sizeof(char*))
-		opstr = ScsiCommonOpString[ioop->cdbPtr[0]];
-	else if (mpt_ScsiOpcodesPtr)
-		opstr = mpt_ScsiOpcodesPtr[ioop->cdbPtr[0]];
-
-	l = sprintf(foo, "SCSI Error: (%s) Status=%02Xh (%s)\n",
-			  ioop->DevIDStr,
-			  ioop->SCSIStatus,
-			  statstr);
-	l += sprintf(foo+l, " Key=%Xh (%s); FRU=%02Xh\n ASC/ASCQ=%02Xh/%02Xh",
-		  sk, skstr, SD_FRU(ioop->sensePtr), asc, ascq );
-	{
-		const char	*x1, *x2, *x3, *x4;
-		x1 = x2 = x3 = x4 = "";
-		x1 = ascq_set_strings_4max(asc, ascq, &x1, &x2, &x3, &x4);
-		if (x1 != NULL) {
-			if (x1[0] != '(')
-				l += sprintf(foo+l, " \"%s%s%s%s\"", x1,x2,x3,x4);
-			else
-				l += sprintf(foo+l, " %s%s%s%s", x1,x2,x3,x4);
-		}
-	}
-	l += sprintf(foo+l, "\n CDB:");
-	l += dump_cdb(foo+l, ioop->cdbPtr);
-	if (opstr)
-		l += sprintf(foo+l, " - \"%s\"", opstr);
-	l += sprintf(foo+l, "\n");
-
-	PrintF(("%s\n", foo));
-
-	return l;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *	mptscsih_initTarget - Target, LUN alloc/free functionality.
@@ -4176,48 +3346,33 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *
 {
 	int		indexed_lun, lun_index;
 	VirtDevice	*vdev;
+	ScsiCfgData	*pSpi;
 	char		data_56;
 
-	dprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
+	dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
 			hd->ioc->name, bus_id, target_id, lun, hd));
 
-	/* Is LUN supported? If so, upper 3 bits will be 0
+	/* Is LUN supported? If so, upper 2 bits will be 0
 	* in first byte of inquiry data.
 	*/
 	if (data[0] & 0xe0)
 		return;
 
-	vdev = hd->Targets[target_id];
+	if ((vdev = hd->Targets[target_id]) == NULL) {
+		return;
+	}
 
 	lun_index = (lun >> 5);  /* 32 luns per lun_index */
 	indexed_lun = (lun % 32);
 	vdev->luns[lun_index] |= (1 << indexed_lun);
 
-	vdev->raidVolume = 0;
 	if (hd->is_spi) {
-		if (hd->ioc->spi_data.isRaid & (1 << target_id)) {
-			vdev->raidVolume = 1;
-			ddvtprintk((KERN_INFO "RAID Volume @ id %d\n", target_id));
-		}
-	}
-
-	if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
-		if ( dlen > 8 ) {
-			memcpy (vdev->inq_data, data, 8);
-		} else {
-			memcpy (vdev->inq_data, data, dlen);
-		}
-		vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
-
-		/* If LUN 0, tape and have not done DV, set the DV flag.
-		 */
-		if (hd->is_spi && (lun == 0) && (data[0] == SCSI_TYPE_TAPE)) {
-			ScsiCfgData *pSpi = &hd->ioc->spi_data;
-			if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
-				pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
-		}
-
-		if ( (data[0] == SCSI_TYPE_PROC) &&
+		if ((data[0] == TYPE_PROCESSOR) && (hd->ioc->spi_data.Saf_Te)) {
+			/* Treat all Processors as SAF-TE if
+			 * command line option is set */
+			vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
+			mptscsih_writeIOCPage4(hd, target_id, bus_id);
+		}else if ((data[0] == TYPE_PROCESSOR) &&
 			!(vdev->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
 			if ( dlen > 49 ) {
 				vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
@@ -4230,30 +3385,51 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *
 					vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
 					mptscsih_writeIOCPage4(hd, target_id, bus_id);
 				}
-			} else {
-				/* Treat all Processors as SAF-TE if
-				 * command line option is set */
-				if ( hd->ioc->spi_data.Saf_Te ) {
-					vdev->tflags |= MPT_TARGET_FLAGS_SAF_TE_ISSUED;
-					mptscsih_writeIOCPage4(hd, target_id, bus_id);
-				}
 			}
 		}
+		if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
+			if ( dlen > 8 ) {
+				memcpy (vdev->inq_data, data, 8);
+			} else {
+				memcpy (vdev->inq_data, data, dlen);
+			}
 
-		data_56 = 0x0F;  /* Default to full capabilities if Inq data length is < 57 */
-		if (dlen > 56) {
-			if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
-			/* Update the target capabilities
+			/* If have not done DV, set the DV flag.
 			 */
-				data_56 = data[56];
-				vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
+			pSpi = &hd->ioc->spi_data;
+			if ((data[0] == TYPE_TAPE) || (data[0] == TYPE_PROCESSOR)) {
+				if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
+					pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
+			}
+
+			vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
+
+
+			data_56 = 0x0F;  /* Default to full capabilities if Inq data length is < 57 */
+			if (dlen > 56) {
+				if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
+				/* Update the target capabilities
+				 */
+					data_56 = data[56];
+					vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
+				}
+			}
+			mptscsih_setTargetNegoParms(hd, vdev, data_56);
+		} else {
+			/* Initial Inquiry may not request enough data bytes to
+			 * obtain byte 57.  DV will; if target doesn't return
+			 * at least 57 bytes, data[56] will be zero. */
+			if (dlen > 56) {
+				if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
+				/* Update the target capabilities
+				 */
+					data_56 = data[56];
+					vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
+					mptscsih_setTargetNegoParms(hd, vdev, data_56);
+				}
 			}
 		}
-		mptscsih_setTargetNegoParms(hd, vdev, data_56);
 	}
-
-	dprintk((KERN_INFO "  target = %p\n", vdev));
-	return;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -4262,12 +3438,12 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *
  *  the Inquiry data, adapter capabilities, and NVRAM settings.
  *
  */
-void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
+static void
+mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
 {
 	ScsiCfgData *pspi_data = &hd->ioc->spi_data;
 	int  id = (int) target->target_id;
 	int  nvram;
-	char canQ = 0;
 	VirtDevice	*vdev;
 	int ii;
 	u8 width = MPT_NARROW;
@@ -4276,14 +3452,6 @@ void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byt
 	u8 version, nfactor;
 	u8 noQas = 1;
 
-	if (!hd->is_spi) {
-		if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
-			if (target->inq_data[7] & 0x02)
-				target->tflags |= MPT_TARGET_FLAGS_Q_YES;
-		}
-		return;
-	}
-
 	target->negoFlags = pspi_data->noQas;
 
 	/* noQas == 0 => device supports QAS. Need byte 56 of Inq to determine
@@ -4293,137 +3461,152 @@ void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byt
 
 	/* Set flags based on Inquiry data
 	 */
-	if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
-		version = target->inq_data[2] & 0x07;
-		if (version < 2) {
-			width = 0;
-			factor = MPT_ULTRA2;
-			offset = pspi_data->maxSyncOffset;
-		} else {
-			if (target->inq_data[7] & 0x20) {
-				width = 1;
-			}
+	version = target->inq_data[2] & 0x07;
+	if (version < 2) {
+		width = 0;
+		factor = MPT_ULTRA2;
+		offset = pspi_data->maxSyncOffset;
+		target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
+	} else {
+		if (target->inq_data[7] & 0x20) {
+			width = 1;
+		}
 
-			if (target->inq_data[7] & 0x10) {
-				/* bits 2 & 3 show Clocking support
-				 */
+		if (target->inq_data[7] & 0x10) {
+			factor = pspi_data->minSyncFactor;
+			if (target->tflags & MPT_TARGET_FLAGS_VALID_56) {
+				/* bits 2 & 3 show Clocking support */
 				if ((byte56 & 0x0C) == 0)
 					factor = MPT_ULTRA2;
 				else {
 					if ((byte56 & 0x03) == 0)
 						factor = MPT_ULTRA160;
-					else
+					else {
 						factor = MPT_ULTRA320;
-				}
-				offset = pspi_data->maxSyncOffset;
-
-				/* If RAID, never disable QAS
-				 * else if non RAID, do not disable
-				 *   QAS if bit 1 is set
-				 * bit 1 QAS support, non-raid only
-				 * bit 0 IU support
-				 */
-				if ((target->raidVolume == 1) || (byte56 & 0x02)) {
-					noQas = 0;
+						if (byte56 & 0x02)
+						{
+							ddvtprintk((KERN_INFO "Enabling QAS due to byte56=%02x on id=%d!\n", byte56, id));
+							noQas = 0;
+						}
+						if (target->inq_data[0] == TYPE_TAPE) {
+							if (byte56 & 0x01)
+								target->negoFlags |= MPT_TAPE_NEGO_IDP;
+						}
+					}
 				}
 			} else {
-				factor = MPT_ASYNC;
-				offset = 0;
+				ddvtprintk((KERN_INFO "Enabling QAS on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id));
+				noQas = 0;
 			}
-		}
+				
+			offset = pspi_data->maxSyncOffset;
 
-		if (target->inq_data[7] & 0x02) {
-			canQ = 1;
+			/* If RAID, never disable QAS
+			 * else if non RAID, do not disable
+			 *   QAS if bit 1 is set
+			 * bit 1 QAS support, non-raid only
+			 * bit 0 IU support
+			 */
+			if (target->raidVolume == 1) {
+				noQas = 0;
+			}
+		} else {
+			factor = MPT_ASYNC;
+			offset = 0;
 		}
+	}
 
-		/* Update tflags based on NVRAM settings. (SCSI only)
-		 */
-		if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
-			nvram = pspi_data->nvram[id];
-			nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
+	if ( (target->inq_data[7] & 0x02) == 0) {
+		target->tflags &= ~MPT_TARGET_FLAGS_Q_YES;
+	}
 
-			if (width)
-				width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
+	/* Update tflags based on NVRAM settings. (SCSI only)
+	 */
+	if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) {
+		nvram = pspi_data->nvram[id];
+		nfactor = (nvram & MPT_NVRAM_SYNC_MASK) >> 8;
 
-			if (offset > 0) {
-				/* Ensure factor is set to the
-				 * maximum of: adapter, nvram, inquiry
-				 */
-				if (nfactor) {
-					if (nfactor < pspi_data->minSyncFactor )
-						nfactor = pspi_data->minSyncFactor;
+		if (width)
+			width = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1;
 
-					factor = max(factor, nfactor);
-					if (factor == MPT_ASYNC)
-						offset = 0;
-				} else {
+		if (offset > 0) {
+			/* Ensure factor is set to the
+			 * maximum of: adapter, nvram, inquiry
+			 */
+			if (nfactor) {
+				if (nfactor < pspi_data->minSyncFactor )
+					nfactor = pspi_data->minSyncFactor;
+
+				factor = max(factor, nfactor);
+				if (factor == MPT_ASYNC)
 					offset = 0;
-					factor = MPT_ASYNC;
-				}
 			} else {
+				offset = 0;
 				factor = MPT_ASYNC;
-			}
 		}
-
-		/* Make sure data is consistent
-		 */
-		if ((!width) && (factor < MPT_ULTRA2)) {
-			factor = MPT_ULTRA2;
+		} else {
+			factor = MPT_ASYNC;
 		}
+	}
 
-		/* Save the data to the target structure.
-		 */
-		target->minSyncFactor = factor;
-		target->maxOffset = offset;
-		target->maxWidth = width;
-		if (canQ) {
-			target->tflags |= MPT_TARGET_FLAGS_Q_YES;
-		}
+	/* Make sure data is consistent
+	 */
+	if ((!width) && (factor < MPT_ULTRA2)) {
+		factor = MPT_ULTRA2;
+	}
 
-		target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
+	/* Save the data to the target structure.
+	 */
+	target->minSyncFactor = factor;
+	target->maxOffset = offset;
+	target->maxWidth = width;
 
-		/* Disable unused features.
-		 */
-		if (!width)
-			target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
+	target->tflags |= MPT_TARGET_FLAGS_VALID_NEGO;
 
-		if (!offset)
-			target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
+	/* Disable unused features.
+	 */
+	if (!width)
+		target->negoFlags |= MPT_TARGET_NO_NEGO_WIDE;
 
-		/* GEM, processor WORKAROUND
-		 */
-		if (((target->inq_data[0] & 0x1F) == 0x03)
-			|| ((target->inq_data[0] & 0x1F) > 0x08)) {
-			target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
-			pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
-		} else {
-			if (noQas && (pspi_data->noQas == 0)) {
-				pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
-				target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+	if (!offset)
+		target->negoFlags |= MPT_TARGET_NO_NEGO_SYNC;
 
-				/* Disable QAS in a mixed configuration case
-		 		*/
+	if ( factor > MPT_ULTRA320 )
+		noQas = 0;
 
-				ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
-				for (ii = 0; ii < id; ii++) {
-					if ( (vdev = hd->Targets[ii]) ) {
-						vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
-					}
-				}
+	/* GEM, processor WORKAROUND
+	 */
+	if ((target->inq_data[0] == TYPE_PROCESSOR) || (target->inq_data[0] > 0x08)) {
+		target->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
+		pspi_data->dvStatus[id] |= MPT_SCSICFG_BLK_NEGO;
+	} else {
+		if (noQas && (pspi_data->noQas == 0)) {
+			pspi_data->noQas |= MPT_TARGET_NO_NEGO_QAS;
+			target->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+
+			/* Disable QAS in a mixed configuration case
+	 		*/
+
+			ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
+			for (ii = 0; ii < id; ii++) {
+				if ( (vdev = hd->Targets[ii]) ) {
+					vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
+					mptscsih_writeSDP1(hd, 0, ii, vdev->negoFlags);
+				}	
 			}
 		}
-		
-		/* Write SDP1 on this I/O to this target */
-		if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) {
-			mptscsih_writeSDP1(hd, 0, id, hd->negoNvram);
-			pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE;
-		} else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) {
-			mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO);
-			pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO;
-		}
 	}
 
-	return;
+	/* Write SDP1 on this I/O to this target */
+	if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) {
+		ddvtprintk((KERN_INFO "MPT_SCSICFG_NEGOTIATE on id=%d!\n", id));
+		mptscsih_writeSDP1(hd, 0, id, hd->negoNvram);
+		pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE;
+	} else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) {
+		ddvtprintk((KERN_INFO "MPT_SCSICFG_BLK_NEGO on id=%d!\n", id));
+		mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO);
+		pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO;
+	}
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -4437,14 +3620,18 @@ void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byt
 static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
 {
 	u8 cmd;
+	ScsiCfgData *pSpi;
 
+	ddvtprintk((" set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n", 
+		pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0]));
+	
 	if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
 		return;
 
 	cmd = pReq->CDB[0];
 
 	if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) {
-		ScsiCfgData *pSpi = &hd->ioc->spi_data;
+		pSpi = &hd->ioc->spi_data;
 		if ((pSpi->isRaid & (1 << pReq->TargetID)) && pSpi->pIocPg3) {
 			/* Set NEED_DV for all hidden disks
 			 */
@@ -4510,6 +3697,8 @@ mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *requestedPtr,
 			*requestedPtr |= (MPI_SCSIDEVPAGE1_RP_IU + MPI_SCSIDEVPAGE1_RP_DT);
 			if ((flags & MPT_TARGET_NO_NEGO_QAS) == 0)
 				*requestedPtr |= MPI_SCSIDEVPAGE1_RP_QAS;
+			if (flags & MPT_TAPE_NEGO_IDP)
+				*requestedPtr |= 0x08000000;
 		} else if (factor < MPT_ULTRA2) {
 			*requestedPtr |= MPI_SCSIDEVPAGE1_RP_DT;
 		}
@@ -4624,6 +3813,16 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
 			//negoFlags = MPT_TARGET_NO_NEGO_SYNC;
 		}
 
+		/* If id is not a raid volume, get the updated
+		 * transmission settings from the target structure.
+		 */
+		if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
+			width = pTarget->maxWidth;
+			factor = pTarget->minSyncFactor;
+			offset = pTarget->maxOffset;
+			negoFlags = pTarget->negoFlags;
+		}
+		
 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
 		/* Force to async and narrow if DV has not been executed
 		 * for this ID
@@ -4635,21 +3834,13 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
 		}
 #endif
 
-		/* If id is not a raid volume, get the updated
-		 * transmission settings from the target structure.
-		 */
-		if (hd->Targets && (pTarget = hd->Targets[id]) && !pTarget->raidVolume) {
-			width = pTarget->maxWidth;
-			factor = pTarget->minSyncFactor;
-			offset = pTarget->maxOffset;
-			negoFlags = pTarget->negoFlags;
-		}
-
 		if (flags & MPT_SCSICFG_BLK_NEGO)
 			negoFlags = MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC;
 
 		mptscsih_setDevicePage1Flags(width, factor, offset,
 					&requested, &configuration, negoFlags);
+		dnegoprintk(("writeSDP1: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
+			target_id, width, factor, offset, negoFlags, requested, configuration));
 
 		/* Get a MF for this command.
 		 */
@@ -4754,9 +3945,6 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
 		return -EAGAIN;
 	}
 
-	ddvprintk((MYIOC_s_INFO_FMT "writeIOCPage4 (mf=%p, id=%d)\n",
-		ioc->name, mf, target_id));
-
 	/* Set the request and the data pointers.
 	 * Place data at end of MF.
 	 */
@@ -4793,9 +3981,9 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
 
 	mpt_add_sge((char *)&pReq->PageBufferSGE, flagsLength, dataDma);
 
-	dsprintk((MYIOC_s_INFO_FMT
-		"writeIOCPage4: pgaddr 0x%x\n",
-			ioc->name, (target_id | (bus<<8))));
+	dinitprintk((MYIOC_s_INFO_FMT
+		"writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
+			ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus));
 
 	mpt_put_msg_frame(ScsiDoneCtx, ioc, mf);
 
@@ -4922,13 +4110,15 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 	} else {
 		SCSIIOReply_t	*pReply;
 		u16		 status;
+		u8		 scsi_status;
 
 		pReply = (SCSIIOReply_t *) mr;
 
 		status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK;
+		scsi_status = pReply->SCSIStatus;
 
 		ddvtprintk((KERN_NOTICE "  IOCStatus=%04xh, SCSIState=%02xh, SCSIStatus=%02xh, IOCLogInfo=%08xh\n",
-			     status, pReply->SCSIState, pReply->SCSIStatus,
+			     status, pReply->SCSIState, scsi_status,
 			     le32_to_cpu(pReply->IOCLogInfo)));
 
 		switch(status) {
@@ -4973,7 +4163,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 				/* save sense data in global structure
 				 */
 				completionCode = MPT_SCANDV_SENSE;
-				hd->pLocal->scsiStatus = pReply->SCSIStatus;
+				hd->pLocal->scsiStatus = scsi_status;
 				sense_data = ((u8 *)hd->ioc->sense_buf_pool +
 					(req_idx * MPT_SENSE_BUFFER_ALLOC));
 
@@ -4984,7 +4174,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 				ddvprintk((KERN_NOTICE "  Check Condition, sense ptr %p\n",
 						sense_data));
 			} else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) {
-				if (pReq->CDB[0] == CMD_Inquiry)
+				if (pReq->CDB[0] == INQUIRY)
 					completionCode = MPT_SCANDV_ISSUE_SENSE;
 				else
 					completionCode = MPT_SCANDV_DID_RESET;
@@ -4994,11 +4184,8 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 			else if (pReply->SCSIState & MPI_SCSI_STATE_TERMINATED)
 				completionCode = MPT_SCANDV_DID_RESET;
 			else {
-				/* If no error, this will be equivalent
-				 * to MPT_SCANDV_GOOD
-				 */
 				completionCode = MPT_SCANDV_GOOD;
-				hd->pLocal->scsiStatus = pReply->SCSIStatus;
+				hd->pLocal->scsiStatus = scsi_status;
 			}
 			break;
 
@@ -5025,7 +4212,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 	 */
 wakeup:
 	/* Free Chain buffers (will never chain) in scan or dv */
-	//mptscsih_freeChainBuffers(hd, req_idx);
+	//mptscsih_freeChainBuffers(ioc, req_idx);
 
 	/*
 	 * Wake up the original calling thread
@@ -5197,7 +4384,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 	/* Set command specific information
 	 */
 	switch (cmd) {
-	case CMD_Inquiry:
+	case INQUIRY:
 		cmdLen = 6;
 		dir = MPI_SCSIIO_CONTROL_READ;
 		CDB[0] = cmd;
@@ -5205,13 +4392,13 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 		cmdTimeout = 10;
 		break;
 
-	case CMD_TestUnitReady:
+	case TEST_UNIT_READY:
 		cmdLen = 6;
 		dir = MPI_SCSIIO_CONTROL_READ;
 		cmdTimeout = 10;
 		break;
 
-	case CMD_StartStopUnit:
+	case START_STOP:
 		cmdLen = 6;
 		dir = MPI_SCSIIO_CONTROL_READ;
 		CDB[0] = cmd;
@@ -5219,7 +4406,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 		cmdTimeout = 15;
 		break;
 
-	case CMD_RequestSense:
+	case REQUEST_SENSE:
 		cmdLen = 6;
 		CDB[0] = cmd;
 		CDB[4] = io->size;
@@ -5227,7 +4414,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 		cmdTimeout = 10;
 		break;
 
-	case CMD_ReadBuffer:
+	case READ_BUFFER:
 		cmdLen = 10;
 		dir = MPI_SCSIIO_CONTROL_READ;
 		CDB[0] = cmd;
@@ -5246,7 +4433,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 		cmdTimeout = 10;
 		break;
 
-	case CMD_WriteBuffer:
+	case WRITE_BUFFER:
 		cmdLen = 10;
 		dir = MPI_SCSIIO_CONTROL_WRITE;
 		CDB[0] = cmd;
@@ -5261,21 +4448,21 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 		cmdTimeout = 10;
 		break;
 
-	case CMD_Reserve6:
+	case RESERVE:
 		cmdLen = 6;
 		dir = MPI_SCSIIO_CONTROL_READ;
 		CDB[0] = cmd;
 		cmdTimeout = 10;
 		break;
 
-	case CMD_Release6:
+	case RELEASE:
 		cmdLen = 6;
 		dir = MPI_SCSIIO_CONTROL_READ;
 		CDB[0] = cmd;
 		cmdTimeout = 10;
 		break;
 
-	case CMD_SynchronizeCache:
+	case SYNCHRONIZE_CACHE:
 		cmdLen = 10;
 		dir = MPI_SCSIIO_CONTROL_READ;
 		CDB[0] = cmd;
@@ -5331,7 +4518,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
 	else
 		pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
 
-	if (cmd == CMD_RequestSense) {
+	if (cmd == REQUEST_SENSE) {
 		pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED);
 		ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n",
 			hd->ioc->name, cmd));
@@ -5439,7 +4626,7 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
 	/* Following parameters will not change
 	 * in this routine.
 	 */
-	iocmd.cmd = CMD_SynchronizeCache;
+	iocmd.cmd = SYNCHRONIZE_CACHE;
 	iocmd.flags = 0;
 	iocmd.physDiskNum = -1;
 	iocmd.data = NULL;
@@ -5509,6 +4696,9 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum)
 			/* Force to async, narrow */
 			mptscsih_setDevicePage1Flags(0, MPT_ASYNC, 0, &requested,
 					&configuration, flags);
+			dnegoprintk(("syncronize cache: id=%d width=0 factor=MPT_ASYNC "
+				"offset=0 negoFlags=%x request=%x config=%x\n",
+				id, flags, requested, configuration));
 			pcfg1Data->RequestedParameters = le32_to_cpu(requested);
 			pcfg1Data->Reserved = 0;
 			pcfg1Data->Configuration = le32_to_cpu(configuration);
@@ -5597,8 +4787,7 @@ mptscsih_domainValidation(void *arg)
 			}
 			spin_unlock_irqrestore(&dvtaskQ_lock, flags);
 
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(HZ/4);
+			msleep(250);
 
 			/* DV only to SCSI adapters */
 			if ((int)ioc->chip_type <= (int)FC929)
@@ -5646,8 +4835,7 @@ mptscsih_domainValidation(void *arg)
 					hd->ioc->spi_data.dvStatus[id] |= MPT_SCSICFG_DV_PENDING;
 					hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_NEED_DV;
 
-					set_current_state(TASK_INTERRUPTIBLE);
-					schedule_timeout(HZ/4);
+					msleep(250);
 
 					/* If hidden phys disk, block IO's to all
 					 *	raid volumes
@@ -5681,11 +4869,6 @@ mptscsih_domainValidation(void *arg)
 						}
 					}
 
-					/* Post OS IOs that were pended while
-					 * DV running.
-					 */
-					post_pendingQ_commands(hd);
-
 					if (hd->ioc->spi_data.noQas)
 						mptscsih_qas_check(hd, id);
 				}
@@ -5741,11 +4924,14 @@ static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
 		if ((pTarget != NULL) && (!pTarget->raidVolume)) {
 			if ((pTarget->negoFlags & hd->ioc->spi_data.noQas) == 0) {
 				pTarget->negoFlags |= hd->ioc->spi_data.noQas;
+				dnegoprintk(("writeSDP1: id=%d flags=0\n", id));
 				mptscsih_writeSDP1(hd, 0, ii, 0);
 			}
 		} else {
-			if (mptscsih_is_phys_disk(hd->ioc, ii) == 1)
+			if (mptscsih_is_phys_disk(hd->ioc, ii) == 1) {
+				dnegoprintk(("writeSDP1: id=%d SCSICFG_USE_NVRAM\n", id));
 				mptscsih_writeSDP1(hd, 0, ii, MPT_SCSICFG_USE_NVRAM);
+			}
 		}
 	}
 	return;
@@ -5824,7 +5010,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 	lun = 0;
 	bus = (u8) bus_number;
 	ddvtprintk((MYIOC_s_NOTE_FMT
-			"DV started: bus=%d, id %d dv @ %p\n",
+			"DV started: bus=%d, id=%d dv @ %p\n",
 			ioc->name, bus, id, &dv));
 
 	/* Prep DV structure
@@ -5838,8 +5024,6 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 	 */
 	dv.cmd = MPT_GET_NVRAM_VALS;
 	mptscsih_dv_parms(hd, &dv, NULL);
-	if ((!dv.max.width) && (!dv.max.offset))
-		return 0;
 
 	/* Prep SCSI IO structure
 	 */
@@ -5851,15 +5035,6 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 	iocmd.rsvd = iocmd.rsvd2 = 0;
 
 	pTarget = hd->Targets[id];
-	if (pTarget && (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
-		/* Another GEM workaround. Check peripheral device type,
-		 * if PROCESSOR, quit DV.
-		 */
-		if (((pTarget->inq_data[0] & 0x1F) == 0x03) || ((pTarget->inq_data[0] & 0x1F) > 0x08)) {
-			pTarget->negoFlags |= (MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC);
-			return 0;
-		}
-	}
 
 	/* Use tagged commands if possible.
 	 */
@@ -5959,7 +5134,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 
 	/* Finish iocmd inititialization - hidden or visible disk? */
 	if (ioc->spi_data.pIocPg3) {
-		/* Searc IOC page 3 for matching id
+		/* Search IOC page 3 for matching id
 		 */
 		Ioc3PhysDisk_t *pPDisk =  ioc->spi_data.pIocPg3->PhysDisk;
 		int		numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks;
@@ -6001,7 +5176,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 	 */
 	hd->pLocal = NULL;
 	readPage0 = 0;
-	sz = SCSI_STD_INQUIRY_BYTES;
+	sz = SCSI_MAX_INQUIRY_BYTES;
 	rc = MPT_SCANDV_GOOD;
 	while (1) {
 		ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id));
@@ -6026,7 +5201,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 				((hd->ioc->facts.FWVersion.Word >= 0x01010000) &&
 				(hd->ioc->facts.FWVersion.Word < 0x01010B00)) ) {
 
-				iocmd.cmd = CMD_RequestSense;
+				iocmd.cmd = REQUEST_SENSE;
 				iocmd.data_dma = buf1_dma;
 				iocmd.data = pbuf1;
 				iocmd.size = 0x12;
@@ -6046,10 +5221,11 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 				goto target_done;
 		}
 
-		iocmd.cmd = CMD_Inquiry;
+		iocmd.cmd = INQUIRY;
 		iocmd.data_dma = buf1_dma;
 		iocmd.data = pbuf1;
 		iocmd.size = sz;
+		memset(pbuf1, 0x00, sz);
 		if (mptscsih_do_cmd(hd, &iocmd) < 0)
 			goto target_done;
 		else {
@@ -6057,7 +5233,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 				goto target_done;
 			rc = hd->pLocal->completion;
 			if (rc == MPT_SCANDV_GOOD) {
-				if (hd->pLocal->scsiStatus == STS_BUSY) {
+				if (hd->pLocal->scsiStatus == SAM_STAT_BUSY) {
 					if ((iocmd.flags & MPT_ICFLAG_TAGGED_CMD) == 0)
 						retcode = 1;
 					else
@@ -6087,7 +5263,17 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 		/* Another GEM workaround. Check peripheral device type,
 		 * if PROCESSOR, quit DV.
 		 */
-		if (((pbuf1[0] & 0x1F) == 0x03) || ((pbuf1[0] & 0x1F) > 0x08))
+		if (inq0 == TYPE_PROCESSOR) {
+			mptscsih_initTarget(hd,
+				bus,
+				id,
+				lun,
+				pbuf1,
+				sz);
+			goto target_done;
+		}
+
+		if (inq0 > 0x08)
 			goto target_done;
 
 		if (mptscsih_do_cmd(hd, &iocmd) < 0)
@@ -6111,6 +5297,9 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 				if ((pbuf1[56] & 0x02) == 0) {
 					pTarget->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
 					hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
+					ddvprintk((MYIOC_s_NOTE_FMT 
+					    "DV: Start Basic noQas on id=%d due to pbuf1[56]=%x\n", 
+					    ioc->name, id, pbuf1[56]));
 				}
 			}
 		}
@@ -6127,10 +5316,11 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 		if ((!dv.now.width) && (!dv.now.offset))
 			goto target_done;
 
-		iocmd.cmd = CMD_Inquiry;
+		iocmd.cmd = INQUIRY;
 		iocmd.data_dma = buf2_dma;
 		iocmd.data = pbuf2;
 		iocmd.size = sz;
+		memset(pbuf2, 0x00, sz);
 		if (mptscsih_do_cmd(hd, &iocmd) < 0)
 			goto target_done;
 		else if (hd->pLocal == NULL)
@@ -6183,14 +5373,26 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 					if (memcmp(pbuf1, pbuf2, sz) != 0) {
 						if (!firstPass)
 							doFallback = 1;
-					} else
+					} else {
+						ddvprintk((MYIOC_s_NOTE_FMT 
+						    "DV:Inquiry compared id=%d, calling initTarget\n", ioc->name, id));
+						hd->ioc->spi_data.dvStatus[id] &= ~MPT_SCSICFG_DV_NOT_DONE;
+						mptscsih_initTarget(hd,
+							bus,
+							id,
+							lun,
+							pbuf1,
+							sz);
 						break;	/* test complete */
+					}
 				}
 
 
 			} else if (rc == MPT_SCANDV_ISSUE_SENSE)
 				doFallback = 1;	/* set fallback flag */
-			else if ((rc == MPT_SCANDV_DID_RESET) || (rc == MPT_SCANDV_SENSE))
+			else if ((rc == MPT_SCANDV_DID_RESET) || 
+				 (rc == MPT_SCANDV_SENSE) || 
+				 (rc == MPT_SCANDV_FALLBACK))
 				doFallback = 1;	/* set fallback flag */
 			else
 				goto target_done;
@@ -6199,6 +5401,10 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 		}
 	}
 	ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
+
+	if (driver_setup.dv == 0)
+		goto target_done;
+
 	inq0 = (*pbuf1) & 0x1F;
 
 	/* Continue only for disks
@@ -6222,7 +5428,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 	cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
 	cfg.dir = 1;
 
-	iocmd.cmd = CMD_TestUnitReady;
+	iocmd.cmd = TEST_UNIT_READY;
 	iocmd.data_dma = -1;
 	iocmd.data = NULL;
 	iocmd.size = 0;
@@ -6245,14 +5451,14 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 				"SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
 				ioc->name, skey, asc, ascq));
 
-			if (skey == SK_UNIT_ATTENTION)
+			if (skey == UNIT_ATTENTION)
 				notDone++; /* repeat */
-			else if ((skey == SK_NOT_READY) &&
+			else if ((skey == NOT_READY) &&
 					(asc == 0x04)&&(ascq == 0x01)) {
 				/* wait then repeat */
 				mdelay (2000);
 				notDone++;
-			} else if ((skey == SK_NOT_READY) && (asc == 0x3A)) {
+			} else if ((skey == NOT_READY) && (asc == 0x3A)) {
 				/* no medium, try read test anyway */
 				notDone = 0;
 			} else {
@@ -6266,7 +5472,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 			goto target_done;
 	}
 
-	iocmd.cmd = CMD_ReadBuffer;
+	iocmd.cmd = READ_BUFFER;
 	iocmd.data_dma = buf1_dma;
 	iocmd.data = pbuf1;
 	iocmd.size = 4;
@@ -6314,11 +5520,11 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 					ddvprintk((MYIOC_s_INFO_FMT
 						"SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
 						ioc->name, skey, asc, ascq));
-					if (skey == SK_ILLEGAL_REQUEST) {
+					if (skey == ILLEGAL_REQUEST) {
 						notDone = 0;
-					} else if (skey == SK_UNIT_ATTENTION) {
+					} else if (skey == UNIT_ATTENTION) {
 						notDone++; /* repeat */
-					} else if ((skey == SK_NOT_READY) &&
+					} else if ((skey == NOT_READY) &&
 						(asc == 0x04)&&(ascq == 0x01)) {
 						/* wait then repeat */
 						mdelay (2000);
@@ -6373,14 +5579,14 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 	for (patt = 0; patt < 4; patt++) {
 		ddvprintk(("Pattern %d\n", patt));
 		if ((iocmd.flags & MPT_ICFLAG_RESERVED) && (iocmd.flags & MPT_ICFLAG_DID_RESET)) {
-			iocmd.cmd = CMD_TestUnitReady;
+			iocmd.cmd = TEST_UNIT_READY;
 			iocmd.data_dma = -1;
 			iocmd.data = NULL;
 			iocmd.size = 0;
 			if (mptscsih_do_cmd(hd, &iocmd) < 0)
 				goto target_done;
 
-			iocmd.cmd = CMD_Release6;
+			iocmd.cmd = RELEASE;
 			iocmd.data_dma = -1;
 			iocmd.data = NULL;
 			iocmd.size = 0;
@@ -6402,7 +5608,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 
 		repeat = 5;
 		while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) {
-			iocmd.cmd = CMD_Reserve6;
+			iocmd.cmd = RESERVE;
 			iocmd.data_dma = -1;
 			iocmd.data = NULL;
 			iocmd.size = 0;
@@ -6425,7 +5631,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 					ddvprintk(("SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n",
 							skey, asc, ascq));
 
-					if ((skey == SK_NOT_READY) && (asc == 0x04)&&
+					if ((skey == NOT_READY) && (asc == 0x04)&&
 									(ascq == 0x01)) {
 						/* wait then repeat */
 						mdelay (2000);
@@ -6444,7 +5650,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 		}
 
 		mptscsih_fillbuf(pbuf1, sz, patt, 1);
-		iocmd.cmd = CMD_WriteBuffer;
+		iocmd.cmd = WRITE_BUFFER;
 		iocmd.data_dma = buf1_dma;
 		iocmd.data = pbuf1;
 		iocmd.size = sz;
@@ -6485,10 +5691,10 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 				ddvprintk((MYIOC_s_INFO_FMT
 					"SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
 					hd->pLocal->sense[12], hd->pLocal->sense[13]));
-				if (skey == SK_UNIT_ATTENTION) {
+				if (skey == UNIT_ATTENTION) {
 					patt = -1;
 					continue;
-				} else if (skey == SK_ILLEGAL_REQUEST) {
+				} else if (skey == ILLEGAL_REQUEST) {
 					if (iocmd.flags & MPT_ICFLAG_ECHO) {
 						if (dataBufSize >= bufsize) {
 							iocmd.flags &= ~MPT_ICFLAG_ECHO;
@@ -6506,7 +5712,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 			}
 		}
 
-		iocmd.cmd = CMD_ReadBuffer;
+		iocmd.cmd = READ_BUFFER;
 		iocmd.data_dma = buf2_dma;
 		iocmd.data = pbuf2;
 		iocmd.size = sz;
@@ -6581,7 +5787,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 				ddvprintk((MYIOC_s_INFO_FMT
 					"SenseKey:ASC:ASCQ = (%x:%02x:%02x)\n", ioc->name, skey,
 					hd->pLocal->sense[12], hd->pLocal->sense[13]));
-				if (skey == SK_UNIT_ATTENTION) {
+				if (skey == UNIT_ATTENTION) {
 					patt = -1;
 					continue;
 				}
@@ -6597,7 +5803,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
 
 target_done:
 	if (iocmd.flags & MPT_ICFLAG_RESERVED) {
-		iocmd.cmd = CMD_Release6;
+		iocmd.cmd = RELEASE;
 		iocmd.data_dma = -1;
 		iocmd.data = NULL;
 		iocmd.size = 0;
@@ -6619,8 +5825,11 @@ target_done:
 	if ((cfg.hdr != NULL) && (retcode == 0)){
 		/* If disk, not U320, disable QAS
 		 */
-		if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320))
+		if ((inq0 == 0) && (dv.now.factor > MPT_ULTRA320)) {
 			hd->ioc->spi_data.noQas = MPT_TARGET_NO_NEGO_QAS;
+			ddvprintk((MYIOC_s_NOTE_FMT 
+			    "noQas set due to id=%d has factor=%x\n", ioc->name, id, dv.now.factor));
+		}
 
 		dv.cmd = MPT_SAVE;
 		mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
@@ -6649,8 +5858,8 @@ target_done:
 	if (pDvBuf)
 		pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
 
-	ddvtprintk((MYIOC_s_INFO_FMT "DV Done.\n",
-			ioc->name));
+	ddvtprintk((MYIOC_s_INFO_FMT "DV Done id=%d\n",
+			ioc->name, id));
 
 	return retcode;
 }
@@ -6730,8 +5939,8 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
 		dv->max.offset = offset;
 		dv->max.factor = factor;
 		dv->max.flags = negoFlags;
-		ddvprintk((" width %d, factor %x, offset %x flags %x\n",
-				width, factor, offset, negoFlags));
+		ddvprintk((" id=%d width=%d factor=%x offset=%x flags=%x\n",
+				id, width, factor, offset, negoFlags));
 		break;
 
 	case MPT_UPDATE_MAX:
@@ -6749,8 +5958,8 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
 		dv->now.width = dv->max.width;
 		dv->now.offset = dv->max.offset;
 		dv->now.factor = dv->max.factor;
-		ddvprintk(("width %d, factor %x, offset %x, flags %x\n",
-				dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
+		ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x\n",
+				id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
 		break;
 
 	case MPT_SET_MAX:
@@ -6766,14 +5975,15 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
 		if (pPage1) {
 			mptscsih_setDevicePage1Flags (dv->now.width, dv->now.factor,
 				dv->now.offset, &val, &configuration, dv->now.flags);
+			dnegoprintk(("Setting Max: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
+				id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
 			pPage1->RequestedParameters = le32_to_cpu(val);
 			pPage1->Reserved = 0;
 			pPage1->Configuration = le32_to_cpu(configuration);
-
 		}
 
-		ddvprintk(("width %d, factor %x, offset %x request %x, config %x\n",
-				dv->now.width, dv->now.factor, dv->now.offset, val, configuration));
+		ddvprintk(("id=%d width=%d factor=%x offset=%x flags=%x request=%x configuration=%x\n",
+				id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags, val, configuration));
 		break;
 
 	case MPT_SET_MIN:
@@ -6790,12 +6000,14 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
 		if (pPage1) {
 			mptscsih_setDevicePage1Flags (width, factor,
 				offset, &val, &configuration, negoFlags);
+			dnegoprintk(("Setting Min: id=%d width=%d factor=%x offset=%x negoFlags=%x request=%x config=%x\n",
+				id, width, factor, offset, negoFlags, val, configuration));
 			pPage1->RequestedParameters = le32_to_cpu(val);
 			pPage1->Reserved = 0;
 			pPage1->Configuration = le32_to_cpu(configuration);
 		}
-		ddvprintk(("width %d, factor %x, offset %x request %x config %x\n",
-				width, factor, offset, val, configuration));
+		ddvprintk(("id=%d width=%d factor=%x offset=%x request=%x config=%x negoFlags=%x\n",
+				id, width, factor, offset, val, configuration, negoFlags));
 		break;
 
 	case MPT_FALLBACK:
@@ -6855,6 +6067,7 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
 			factor = MPT_ASYNC;
 		}
 		dv->max.flags |= MPT_TARGET_NO_NEGO_QAS;
+		dv->max.flags &= ~MPT_TAPE_NEGO_IDP;
 
 		dv->now.width = width;
 		dv->now.offset = offset;
@@ -6865,21 +6078,23 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage)
 		if (pPage1) {
 			mptscsih_setDevicePage1Flags (width, factor, offset, &val,
 						&configuration, dv->now.flags);
+			dnegoprintk(("Finish: id=%d width=%d offset=%d factor=%x flags=%x request=%x config=%x\n",
+			     id, width, offset, factor, dv->now.flags, val, configuration));
 
 			pPage1->RequestedParameters = le32_to_cpu(val);
 			pPage1->Reserved = 0;
 			pPage1->Configuration = le32_to_cpu(configuration);
 		}
 
-		ddvprintk(("Finish: offset %d, factor %x, width %d, request %x config %x\n",
-			     dv->now.offset, dv->now.factor, dv->now.width, val, configuration));
+		ddvprintk(("Finish: id=%d offset=%d factor=%x width=%d request=%x config=%x\n",
+			     id, dv->now.offset, dv->now.factor, dv->now.width, val, configuration));
 		break;
 
 	case MPT_SAVE:
 		ddvprintk((MYIOC_s_NOTE_FMT
 			"Saving to Target structure: ", hd->ioc->name));
-		ddvprintk(("offset %d, factor %x, width %d \n",
-			     dv->now.offset, dv->now.factor, dv->now.width));
+		ddvprintk(("id=%d width=%x factor=%x offset=%d flags=%x\n",
+			     id, dv->now.width, dv->now.factor, dv->now.offset, dv->now.flags));
 
 		/* Save these values to target structures
 		 * or overwrite nvram (phys disks only).
diff --git a/drivers/message/i2o/Makefile b/drivers/message/i2o/Makefile
index e3169dbd9..aabc6cdc3 100644
--- a/drivers/message/i2o/Makefile
+++ b/drivers/message/i2o/Makefile
@@ -5,6 +5,7 @@
 # In the future, some of these should be built conditionally.
 #
 
+i2o_core-y		+= iop.o driver.o device.o debug.o pci.o exec-osm.o
 obj-$(CONFIG_I2O)	+= i2o_core.o
 obj-$(CONFIG_I2O_CONFIG)+= i2o_config.o
 obj-$(CONFIG_I2O_BLOCK)	+= i2o_block.o
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index 36dc0e9d1..102fb8316 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -1,463 +1,426 @@
 /*
- * I2O Random Block Storage Class OSM
+ *	Block OSM
  *
- * (C) Copyright 1999-2002 Red Hat
- *	
- * Written by Alan Cox, Building Number Three Ltd
+ * 	Copyright (C) 1999-2002	Red Hat Software
  *
- * 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.
+ *	Written by Alan Cox, Building Number Three Ltd
  *
- * 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.
+ *	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.
  *
- * For the purpose of avoiding doubt the preferred form of the work
- * for making modifications shall be a standards compliant form such
- * gzipped tar and not one requiring a proprietary or patent encumbered
- * tool to unpack.
+ *	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.
  *
- * This is a beta test release. Most of the good code was taken
- * from the nbd driver by Pavel Machek, who in turn took some of it
- * from loop.c. Isn't free software great for reusability 8)
+ *	For the purpose of avoiding doubt the preferred form of the work
+ *	for making modifications shall be a standards compliant form such
+ *	gzipped tar and not one requiring a proprietary or patent encumbered
+ *	tool to unpack.
  *
- * Fixes/additions:
- *	Steve Ralston:	
- *		Multiple device handling error fixes,
- *		Added a queue depth.
- *	Alan Cox:	
- *		FC920 has an rmw bug. Dont or in the end marker.
- *		Removed queue walk, fixed for 64bitness.
- *		Rewrote much of the code over time
- *		Added indirect block lists
- *		Handle 64K limits on many controllers
- *		Don't use indirects on the Promise (breaks)
- *		Heavily chop down the queue depths
- *	Deepak Saxena:
- *		Independent queues per IOP
- *		Support for dynamic device creation/deletion
- *		Code cleanup	
- *    		Support for larger I/Os through merge* functions 
- *       	(taken from DAC960 driver)
- *	Boji T Kannanthanam:
- *		Set the I2O Block devices to be detected in increasing 
- *		order of TIDs during boot.
- *		Search and set the I2O block device that we boot off from  as
- *		the first device to be claimed (as /dev/i2o/hda)
- *		Properly attach/detach I2O gendisk structure from the system
- *		gendisk list. The I2O block devices now appear in 
- * 		/proc/partitions.
- *	Markus Lidel <Markus.Lidel@shadowconnect.com>:
- *		Minor bugfixes for 2.6.
- *
- * To do:
- *	Serial number scanning to find duplicates for FC multipathing
+ *	Fixes/additions:
+ *		Steve Ralston:
+ *			Multiple device handling error fixes,
+ *			Added a queue depth.
+ *		Alan Cox:
+ *			FC920 has an rmw bug. Dont or in the end marker.
+ *			Removed queue walk, fixed for 64bitness.
+ *			Rewrote much of the code over time
+ *			Added indirect block lists
+ *			Handle 64K limits on many controllers
+ *			Don't use indirects on the Promise (breaks)
+ *			Heavily chop down the queue depths
+ *		Deepak Saxena:
+ *			Independent queues per IOP
+ *			Support for dynamic device creation/deletion
+ *			Code cleanup
+ *	    		Support for larger I/Os through merge* functions
+ *			(taken from DAC960 driver)
+ *		Boji T Kannanthanam:
+ *			Set the I2O Block devices to be detected in increasing
+ *			order of TIDs during boot.
+ *			Search and set the I2O block device that we boot off
+ *			from as the first device to be claimed (as /dev/i2o/hda)
+ *			Properly attach/detach I2O gendisk structure from the
+ *			system gendisk list. The I2O block devices now appear in
+ *			/proc/partitions.
+ *		Markus Lidel <Markus.Lidel@shadowconnect.com>:
+ *			Minor bugfixes for 2.6.
  */
 
-#include <linux/major.h>
-
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/pci.h>
-#include <linux/errno.h>
-#include <linux/file.h>
-#include <linux/ioctl.h>
 #include <linux/i2o.h>
+
+#include <linux/mempool.h>
+
+#include <linux/genhd.h>
 #include <linux/blkdev.h>
-#include <linux/blkpg.h>
-#include <linux/slab.h>
 #include <linux/hdreg.h>
-#include <linux/spinlock.h>
-#include <linux/bio.h>
 
-#include <linux/notifier.h>
-#include <linux/reboot.h>
+#include "i2o_block.h"
 
-#include <asm/uaccess.h>
-#include <asm/semaphore.h>
-#include <linux/completion.h>
-#include <asm/io.h>
-#include <linux/smp_lock.h>
-#include <linux/wait.h>
+static struct i2o_driver i2o_block_driver;
 
-#define MAJOR_NR I2O_MAJOR
+/* global Block OSM request mempool */
+static struct i2o_block_mempool i2o_blk_req_pool;
 
-#define MAX_I2OB	16
+/* Block OSM class handling definition */
+static struct i2o_class_id i2o_block_class_id[] = {
+	{I2O_CLASS_RANDOM_BLOCK_STORAGE},
+	{I2O_CLASS_END}
+};
+
+/**
+ *	i2o_block_device_free - free the memory of the I2O Block device
+ *	@dev: I2O Block device, which should be cleaned up
+ *
+ *	Frees the request queue, gendisk and the i2o_block_device structure.
+ */
+static void i2o_block_device_free(struct i2o_block_device *dev)
+{
+	blk_cleanup_queue(dev->gd->queue);
 
-#define MAX_I2OB_DEPTH	8
-#define MAX_I2OB_RETRIES 4
+	put_disk(dev->gd);
 
-//#define DRIVERDEBUG
-#ifdef DRIVERDEBUG
-#define DEBUG( s ) printk( s )
-#else
-#define DEBUG( s )
-#endif
+	kfree(dev);
+};
 
-/*
- * Events that this OSM is interested in
+/**
+ *	i2o_block_remove - remove the I2O Block device from the system again
+ *	@dev: I2O Block device which should be removed
+ *
+ *	Remove gendisk from system and free all allocated memory.
+ *
+ *	Always returns 0.
  */
-#define I2OB_EVENT_MASK		(I2O_EVT_IND_BSA_VOLUME_LOAD |	\
-				 I2O_EVT_IND_BSA_VOLUME_UNLOAD | \
-				 I2O_EVT_IND_BSA_VOLUME_UNLOAD_REQ | \
-				 I2O_EVT_IND_BSA_CAPACITY_CHANGE | \
-				 I2O_EVT_IND_BSA_SCSI_SMART )
+static int i2o_block_remove(struct device *dev)
+{
+	struct i2o_device *i2o_dev = to_i2o_device(dev);
+	struct i2o_block_device *i2o_blk_dev = dev_get_drvdata(dev);
 
+	printk(KERN_INFO "block-osm: Device removed %s\n",
+	       i2o_blk_dev->gd->disk_name);
 
-/*
- *	Some of these can be made smaller later
- */
+	i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0);
 
-static int i2ob_context;
-static struct block_device_operations i2ob_fops;
+	del_gendisk(i2o_blk_dev->gd);
 
-/*
- * I2O Block device descriptor 
+	dev_set_drvdata(dev, NULL);
+
+	i2o_device_claim_release(i2o_dev);
+
+	i2o_block_device_free(i2o_blk_dev);
+
+	return 0;
+};
+
+/**
+ *	i2o_block_device flush - Flush all dirty data of I2O device dev
+ *	@dev: I2O device which should be flushed
+ *
+ *	Flushes all dirty data on device dev.
+ *
+ *	Returns 0 on success or negative error code on failure.
  */
-struct i2ob_device
+static int i2o_block_device_flush(struct i2o_device *dev)
 {
-	struct i2o_controller *controller;
-	struct i2o_device *i2odev;
-	int unit;
-	int tid;
-	int flags;
-	int refcnt;
-	struct request *head, *tail;
-	request_queue_t *req_queue;
-	int max_segments;
-	int max_direct;		/* Not yet used properly */
-	int done_flag;
-	int depth;
-	int rcache;
-	int wcache;
-	int power;
-	int index;
-	int media_change_flag;
-	u32 max_sectors;
-	struct gendisk *gd;
+	struct i2o_message *msg;
+	u32 m;
+
+	m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -ETIMEDOUT;
+
+	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_BLOCK_CFLUSH << 24 | HOST_TID << 12 | dev->lct_data.tid,
+	       &msg->u.head[1]);
+	writel(60 << 16, &msg->body[0]);
+	pr_debug("Flushing...\n");
+
+	return i2o_msg_post_wait(dev->iop, m, 60);
 };
 
-/*
- *	FIXME:
- *	We should cache align these to avoid ping-ponging lines on SMP
- *	boxes under heavy I/O load...
+/**
+ *	i2o_block_device_mount - Mount (load) the media of device dev
+ *	@dev: I2O device which should receive the mount request
+ *	@media_id: Media Identifier
+ *
+ *	Load a media into drive. Identifier should be set to -1, because the
+ *	spec does not support any other value.
+ *
+ *	Returns 0 on success or negative error code on failure.
  */
-
-struct i2ob_request
+static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id)
 {
-	struct i2ob_request *next;
-	struct request *req;
-	int num;
-	int sg_dma_direction;
-	int sg_nents;
-	struct scatterlist sg_table[16];
+	struct i2o_message *msg;
+	u32 m;
+
+	m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -ETIMEDOUT;
+
+	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_BLOCK_MMOUNT << 24 | HOST_TID << 12 | dev->lct_data.tid,
+	       &msg->u.head[1]);
+	writel(-1, &msg->body[0]);
+	writel(0, &msg->body[1]);
+	pr_debug("Mounting...\n");
+
+	return i2o_msg_post_wait(dev->iop, m, 2);
 };
 
-/*
- * Per IOP request queue information
+/**
+ *	i2o_block_device_lock - Locks the media of device dev
+ *	@dev: I2O device which should receive the lock request
+ *	@media_id: Media Identifier
+ *
+ *	Lock media of device dev to prevent removal. The media identifier
+ *	should be set to -1, because the spec does not support any other value.
  *
- * We have a separate request_queue_t per IOP so that a heavilly
- * loaded I2O block device on an IOP does not starve block devices
- * across all I2O controllers.
- * 
+ *	Returns 0 on success or negative error code on failure.
  */
-struct i2ob_iop_queue
+static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id)
 {
-	unsigned int queue_depth;
-	struct i2ob_request request_queue[MAX_I2OB_DEPTH];
-	struct i2ob_request *i2ob_qhead;
-	request_queue_t *req_queue;
-	spinlock_t lock;
+	struct i2o_message *msg;
+	u32 m;
+
+	m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -ETIMEDOUT;
+
+	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_BLOCK_MLOCK << 24 | HOST_TID << 12 | dev->lct_data.tid,
+	       &msg->u.head[1]);
+	writel(-1, &msg->body[0]);
+	pr_debug("Locking...\n");
+
+	return i2o_msg_post_wait(dev->iop, m, 2);
 };
-static struct i2ob_iop_queue *i2ob_queues[MAX_I2O_CONTROLLERS];
 
-/*
- *	Each I2O disk is one of these.
+/**
+ *	i2o_block_device_unlock - Unlocks the media of device dev
+ *	@dev: I2O device which should receive the unlocked request
+ *	@media_id: Media Identifier
+ *
+ *	Unlocks the media in device dev. The media identifier should be set to
+ *	-1, because the spec does not support any other value.
+ *
+ *	Returns 0 on success or negative error code on failure.
  */
+static int i2o_block_device_unlock(struct i2o_device *dev, u32 media_id)
+{
+	struct i2o_message *msg;
+	u32 m;
 
-static struct i2ob_device i2ob_dev[MAX_I2OB];
-static int i2ob_dev_count = 0;
+	m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -ETIMEDOUT;
 
-/*
- * Mutex and spin lock for event handling synchronization
- * evt_msg contains the last event.
- */
-static DECLARE_MUTEX_LOCKED(i2ob_evt_sem);
-static DECLARE_COMPLETION(i2ob_thread_dead);
-static spinlock_t i2ob_evt_lock = SPIN_LOCK_UNLOCKED;
-static u32 evt_msg[MSG_FRAME_SIZE];
-
-static void i2o_block_reply(struct i2o_handler *, struct i2o_controller *,
-	 struct i2o_message *);
-static void i2ob_new_device(struct i2o_controller *, struct i2o_device *);
-static void i2ob_del_device(struct i2o_controller *, struct i2o_device *);
-static void i2ob_reboot_event(void);
-static int i2ob_install_device(struct i2o_controller *, struct i2o_device *, int);
-static void i2ob_end_request(struct request *);
-static void i2ob_request(request_queue_t *);
-static int i2ob_init_iop(unsigned int);
-static int i2ob_query_device(struct i2ob_device *, int, int, void*, int);
-static int i2ob_evt(void *);
-
-static int evt_pid = 0;
-static int evt_running = 0;
-static int scan_unit = 0;
+	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_BLOCK_MUNLOCK << 24 | HOST_TID << 12 | dev->lct_data.tid,
+	       &msg->u.head[1]);
+	writel(media_id, &msg->body[0]);
+	pr_debug("Unlocking...\n");
 
-/*
- * I2O OSM registration structure...keeps getting bigger and bigger :)
+	return i2o_msg_post_wait(dev->iop, m, 2);
+};
+
+/**
+ *	i2o_block_device_power - Power management for device dev
+ *	@dev: I2O device which should receive the power management request
+ *	@operation: Operation which should be send
+ *
+ *	Send a power management request to the device dev.
+ *
+ *	Returns 0 on success or negative error code on failure.
  */
-static struct i2o_handler i2o_block_handler =
+static int i2o_block_device_power(struct i2o_block_device *dev, u8 op)
 {
-	i2o_block_reply,
-	i2ob_new_device,
-	i2ob_del_device,
-	i2ob_reboot_event,
-	"I2O Block OSM",
-	0,
-	I2O_CLASS_RANDOM_BLOCK_STORAGE
+	struct i2o_device *i2o_dev = dev->i2o_dev;
+	struct i2o_controller *c = i2o_dev->iop;
+	struct i2o_message *msg;
+	u32 m;
+	int rc;
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -ETIMEDOUT;
+
+	writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_BLOCK_POWER << 24 | HOST_TID << 12 | i2o_dev->lct_data.
+	       tid, &msg->u.head[1]);
+	writel(op << 24, &msg->body[0]);
+	pr_debug("Power...\n");
+
+	rc = i2o_msg_post_wait(c, m, 60);
+	if (!rc)
+		dev->power = op;
+
+	return rc;
 };
 
 /**
- *	i2ob_get	-	Get an I2O message
- *	@dev:  I2O block device
+ *	i2o_block_request_alloc - Allocate an I2O block request struct
+ *
+ *	Allocates an I2O block request struct and initialize the list.
  *
- *	Get a message from the FIFO used for this block device. The message is returned
- *	or the I2O 'no message' value of 0xFFFFFFFF if nothing is available.
+ *	Returns a i2o_block_request pointer on success or negative error code
+ *	on failure.
  */
+static inline struct i2o_block_request *i2o_block_request_alloc(void)
+{
+	struct i2o_block_request *ireq;
+
+	ireq = mempool_alloc(i2o_blk_req_pool.pool, GFP_ATOMIC);
+	if (!ireq)
+		return ERR_PTR(-ENOMEM);
+
+	INIT_LIST_HEAD(&ireq->queue);
+
+	return ireq;
+};
 
-static u32 i2ob_get(struct i2ob_device *dev)
+/**
+ *	i2o_block_request_free - Frees a I2O block request
+ *	@ireq: I2O block request which should be freed
+ *
+ *	Fres the allocated memory (give it back to the request mempool).
+ */
+static inline void i2o_block_request_free(struct i2o_block_request *ireq)
 {
-	struct i2o_controller *c=dev->controller;
-   	return I2O_POST_READ32(c);
-}
+	mempool_free(ireq, i2o_blk_req_pool.pool);
+};
 
-static int i2ob_build_sglist(struct i2ob_device *dev,  struct i2ob_request *ireq)
+/**
+ *	i2o_block_sglist_alloc - Allocate the SG list and map it
+ *	@ireq: I2O block request
+ *
+ *	Builds the SG list and map it into to be accessable by the controller.
+ *
+ *	Returns the number of elements in the SG list or 0 on failure.
+ */
+static inline int i2o_block_sglist_alloc(struct i2o_block_request *ireq)
 {
-	struct scatterlist *sg = ireq->sg_table;
+	struct device *dev = &ireq->i2o_blk_dev->i2o_dev->iop->pdev->dev;
 	int nents;
 
-	nents = blk_rq_map_sg(dev->req_queue, ireq->req, ireq->sg_table);
-		
+	nents = blk_rq_map_sg(ireq->req->q, ireq->req, ireq->sg_table);
+
 	if (rq_data_dir(ireq->req) == READ)
 		ireq->sg_dma_direction = PCI_DMA_FROMDEVICE;
 	else
 		ireq->sg_dma_direction = PCI_DMA_TODEVICE;
 
-	ireq->sg_nents = pci_map_sg(dev->controller->pdev, sg, nents, ireq->sg_dma_direction);
+	ireq->sg_nents = dma_map_sg(dev, ireq->sg_table, nents,
+				    ireq->sg_dma_direction);
+
 	return ireq->sg_nents;
-}
+};
 
-void i2ob_free_sglist(struct i2ob_device *dev, struct i2ob_request *ireq)
-{
-	struct pci_dev *pdev = dev->controller->pdev;
-	struct scatterlist *sg = ireq->sg_table;
-	int nents = ireq->sg_nents;
-	pci_unmap_sg(pdev, sg, nents, ireq->sg_dma_direction);
-}
- 
 /**
- *	i2ob_send		-	Turn a request into a message and send it
- *	@m: Message offset
- *	@dev: I2O device
- *	@ireq: Request structure
- *	@unit: Device identity
+ *	i2o_block_sglist_free - Frees the SG list
+ *	@ireq: I2O block request from which the SG should be freed
  *
- *	Generate an I2O BSAREAD request. This interface function is called for devices that
- *	appear to explode when they are fed indirect chain pointers (notably right now this
- *	appears to afflict Promise hardwre, so be careful what you feed the hardware
- *
- *	No cleanup is done by this interface. It is done on the interrupt side when the
- *	reply arrives
+ *	Frees the SG list from the I2O block request.
  */
- 
-static int i2ob_send(u32 m, struct i2ob_device *dev, struct i2ob_request *ireq, int unit)
+static inline void i2o_block_sglist_free(struct i2o_block_request *ireq)
 {
-	struct i2o_controller *c = dev->controller;
-	int tid = dev->tid;
-	void *msg;
-	void *mptr;
-	u64 offset;
-	struct request *req = ireq->req;
-	int count = req->nr_sectors<<9;
-	struct scatterlist *sg;
-	int sgnum;
-	int i;
+	struct device *dev = &ireq->i2o_blk_dev->i2o_dev->iop->pdev->dev;
 
-	// printk(KERN_INFO "i2ob_send called\n");
-	/* Map the message to a virtual address */
-	msg = c->msg_virt + m;
-	
-	sgnum = i2ob_build_sglist(dev, ireq);
-	
-	/* FIXME: if we have no resources how should we get out of this */
-	if(sgnum == 0)
-		BUG();
-	
-	/*
-	 * Build the message based on the request.
-	 */
-	i2o_raw_writel(i2ob_context|(unit<<8), msg+8);
-	i2o_raw_writel(ireq->num, msg+12);
-	i2o_raw_writel(req->nr_sectors << 9, msg+20);
+	dma_unmap_sg(dev, ireq->sg_table, ireq->sg_nents,
+		     ireq->sg_dma_direction);
+};
 
-	/* 
-	 * Mask out partitions from now on
-	 */
-		
-	/* This can be optimised later - just want to be sure its right for
-	   starters */
-	offset = ((u64)req->sector) << 9;
-	i2o_raw_writel( offset & 0xFFFFFFFF, msg+24);
-	i2o_raw_writel(offset>>32, msg+28);
-	mptr=msg+32;
-	
-	sg = ireq->sg_table;
-	if(rq_data_dir(req) == READ)
-	{
-		DEBUG("READ\n");
-		i2o_raw_writel(I2O_CMD_BLOCK_READ<<24|HOST_TID<<12|tid, msg+4);
-		for(i = sgnum; i > 0; i--)
-		{
-			if(i != 1)
-				i2o_raw_writel(0x10000000|sg_dma_len(sg), mptr);
-			else
-				i2o_raw_writel(0xD0000000|sg_dma_len(sg), mptr);
-			i2o_raw_writel(sg_dma_address(sg), mptr+4);
-			mptr += 8;	
-			count -= sg_dma_len(sg);
-			sg++;
-		}
-		switch(dev->rcache)
-		{
-			case CACHE_NULL:
-				i2o_raw_writel(0, msg+16);break;
-			case CACHE_PREFETCH:
-				i2o_raw_writel(0x201F0008, msg+16);break;
-			case CACHE_SMARTFETCH:
-				if(req->nr_sectors > 16)
-					i2o_raw_writel(0x201F0008, msg+16);
-				else
-					i2o_raw_writel(0x001F0000, msg+16);
-				break;
-		}				
-				
-//		printk("Reading %d entries %d bytes.\n",
-//			mptr-msg-8, req->nr_sectors<<9);
+/**
+ *	i2o_block_prep_req_fn - Allocates I2O block device specific struct
+ *	@q: request queue for the request
+ *	@req: the request to prepare
+ *
+ *	Allocate the necessary i2o_block_request struct and connect it to
+ *	the request. This is needed that we not loose the SG list later on.
+ *
+ *	Returns BLKPREP_OK on success or BLKPREP_DEFER on failure.
+ */
+static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req)
+{
+	struct i2o_block_device *i2o_blk_dev = q->queuedata;
+	struct i2o_block_request *ireq;
+
+	/* request is already processed by us, so return */
+	if (req->flags & REQ_SPECIAL) {
+		pr_debug("REQ_SPECIAL already set!\n");
+		req->flags |= REQ_DONTPREP;
+		return BLKPREP_OK;
 	}
-	else if(rq_data_dir(req) == WRITE)
-	{
-		DEBUG("WRITE\n");
-		i2o_raw_writel(I2O_CMD_BLOCK_WRITE<<24|HOST_TID<<12|tid, msg+4);
-		for(i = sgnum; i > 0; i--)
-		{
-			if(i != 1)
-				i2o_raw_writel(0x14000000|sg_dma_len(sg), mptr);
-			else
-				i2o_raw_writel(0xD4000000|sg_dma_len(sg), mptr);
-			i2o_raw_writel(sg_dma_address(sg), mptr+4);
-			mptr += 8;	
-			count -= sg_dma_len(sg);
-			sg++;
-		}
 
-		switch(dev->wcache)
-		{
-			case CACHE_NULL:
-				i2o_raw_writel(0, msg+16);break;
-			case CACHE_WRITETHROUGH:
-				i2o_raw_writel(0x001F0008, msg+16);break;
-			case CACHE_WRITEBACK:
-				i2o_raw_writel(0x001F0010, msg+16);break;
-			case CACHE_SMARTBACK:
-				if(req->nr_sectors > 16)
-					i2o_raw_writel(0x001F0004, msg+16);
-				else
-					i2o_raw_writel(0x001F0010, msg+16);
-				break;
-			case CACHE_SMARTTHROUGH:
-				if(req->nr_sectors > 16)
-					i2o_raw_writel(0x001F0004, msg+16);
-				else
-					i2o_raw_writel(0x001F0010, msg+16);
+	/* connect the i2o_block_request to the request */
+	if (!req->special) {
+		ireq = i2o_block_request_alloc();
+		if (unlikely(IS_ERR(ireq))) {
+			pr_debug("unable to allocate i2o_block_request!\n");
+			return BLKPREP_DEFER;
 		}
-				
-//		printk("Writing %d entries %d bytes.\n",
-//			mptr-msg-8, req->nr_sectors<<9);
-	}
-	i2o_raw_writel(I2O_MESSAGE_SIZE(mptr-msg)>>2 | SGL_OFFSET_8, msg);
-	
-	if(count != 0)
-	{
-		printk(KERN_ERR "Request count botched by %d.\n", count);
-	}
 
-	i2o_post_message(c,m);
-	i2ob_queues[c->unit]->queue_depth ++;
+		ireq->i2o_blk_dev = i2o_blk_dev;
+		req->special = ireq;
+		ireq->req = req;
+	} else
+		ireq = req->special;
 
-	return 0;
-}
+	/* do not come back here */
+	req->flags |= REQ_DONTPREP | REQ_SPECIAL;
 
-/*
- *	Remove a request from the _locked_ request list. We update both the
- *	list chain and if this is the last item the tail pointer. Caller
- *	must hold the lock.
- */
- 
-static inline void i2ob_unhook_request(struct i2ob_request *ireq, 
-	unsigned int iop)
-{
-	ireq->next = i2ob_queues[iop]->i2ob_qhead;
-	i2ob_queues[iop]->i2ob_qhead = ireq;
-}
+	return BLKPREP_OK;
+};
 
-/*
- *	Request completion handler
+/**
+ *	i2o_block_delayed_request_fn - delayed request queue function
+ *	delayed_request: the delayed request with the queue to start
+ *
+ *	If the request queue is stopped for a disk, and there is no open
+ *	request, a new event is created, which calls this function to start
+ *	the queue after I2O_BLOCK_REQUEST_TIME. Otherwise the queue will never
+ *	be started again.
  */
- 
-static inline void i2ob_end_request(struct request *req)
+static void i2o_block_delayed_request_fn(void *delayed_request)
 {
-	/* FIXME  - pci unmap the request */
-
-	/*
-	 * Loop until all of the buffers that are linked
-	 * to this request have been marked updated and
-	 * unlocked.
-	 */
-
-	while (end_that_request_first( req, !req->errors, req->hard_cur_sectors ));
+	struct i2o_block_delayed_request *dreq = delayed_request;
+	struct request_queue *q = dreq->queue;
+	unsigned long flags;
 
-	/*
-	 * It is now ok to complete the request.
-	 */
-	end_that_request_last( req );
-	DEBUG("IO COMPLETED\n");
-}
+	spin_lock_irqsave(q->queue_lock, flags);
+	blk_start_queue(q);
+	spin_unlock_irqrestore(q->queue_lock, flags);
+	kfree(dreq);
+};
 
-/*
- *	OSM reply handler. This gets all the message replies
+/**
+ *	i2o_block_reply - Block OSM reply handler.
+ *	@c: I2O controller from which the message arrives
+ *	@m: message id of reply
+ *	qmsg: the actuall I2O message reply
+ *
+ *	This function gets all the message replies.
+ *
  */
-
-static void i2o_block_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *msg)
+static int i2o_block_reply(struct i2o_controller *c, u32 m,
+			   struct i2o_message *msg)
 {
-	unsigned long flags;
-	struct i2ob_request *ireq = NULL;
+	struct i2o_block_request *ireq;
+	struct request *req;
+	struct i2o_block_device *dev;
+	struct request_queue *q;
 	u8 st;
-	u32 *m = (u32 *)msg;
-	u8 unit = m[2]>>8;
-	struct i2ob_device *dev = &i2ob_dev[unit];
+	unsigned long flags;
 
-	/*
-	 * FAILed message
-	 */
-	if(m[0] & (1<<13))
-	{
-		DEBUG("FAIL");
+	/* FAILed message */
+	if (unlikely(readl(&msg->u.head[0]) & (1 << 13))) {
+		struct i2o_message *pmsg;
+		u32 pm;
+
+		printk(KERN_WARNING "FAIL");
 		/*
 		 * FAILed message from controller
 		 * We increment the error count and abort it
@@ -468,65 +431,85 @@ static void i2o_block_reply(struct i2o_handler *h, struct i2o_controller *c, str
 		 * better be on the safe side since no one really follows
 		 * the spec to the book :)
 		 */
-		ireq=&i2ob_queues[c->unit]->request_queue[m[3]];
-		ireq->req->errors++;
-
-		spin_lock_irqsave(dev->req_queue->queue_lock, flags);
-		i2ob_unhook_request(ireq, c->unit);
-		i2ob_end_request(ireq->req);
-		spin_unlock_irqrestore(dev->req_queue->queue_lock, flags);
-	
+		pm = readl(&msg->body[3]);
+		pmsg = c->in_queue.virt + pm;
+
+		req = i2o_cntxt_list_get(c, readl(&pmsg->u.s.tcntxt));
+		if (unlikely(!req)) {
+			printk(KERN_ERR "block-osm: NULL reply received!\n");
+			return -1;
+		}
+
+		ireq = req->special;
+		dev = ireq->i2o_blk_dev;
+		q = dev->gd->queue;
+
+		req->errors++;
+
+		spin_lock_irqsave(q->queue_lock, flags);
+
+		while (end_that_request_chunk(req, !req->errors,
+					      readl(&pmsg->body[1]))) ;
+		end_that_request_last(req);
+
+		dev->open_queue_depth--;
+		list_del(&ireq->queue);
+		blk_start_queue(q);
+
+		spin_unlock_irqrestore(q->queue_lock, flags);
+
 		/* Now flush the message by making it a NOP */
-		m[0]&=0x00FFFFFF;
-		m[0]|=(I2O_CMD_UTIL_NOP)<<24;
-		i2o_post_message(c, (unsigned long) m - (unsigned long) c->msg_virt);
+		i2o_msg_nop(c, pm);
 
-		return;
+		return -1;
 	}
 
-	if(msg->function == I2O_CMD_UTIL_EVT_REGISTER)
-	{
-		spin_lock(&i2ob_evt_lock);
-		memcpy(evt_msg, msg, (m[0]>>16)<<2);
-		spin_unlock(&i2ob_evt_lock);
-		up(&i2ob_evt_sem);
-		return;
+	req = i2o_cntxt_list_get(c, readl(&msg->u.s.tcntxt));
+	if (unlikely(!req)) {
+		printk(KERN_ERR "block-osm: NULL reply received!\n");
+		return -1;
 	}
 
-	if(!dev->i2odev)
-	{
+	ireq = req->special;
+	dev = ireq->i2o_blk_dev;
+	q = dev->gd->queue;
+
+	if (unlikely(!dev->i2o_dev)) {
 		/*
 		 * This is HACK, but Intel Integrated RAID allows user
-		 * to delete a volume that is claimed, locked, and in use 
+		 * to delete a volume that is claimed, locked, and in use
 		 * by the OS. We have to check for a reply from a
-		 * non-existent device and flag it as an error or the system 
+		 * non-existent device and flag it as an error or the system
 		 * goes kaput...
 		 */
-		ireq=&i2ob_queues[c->unit]->request_queue[m[3]];
-		ireq->req->errors++;
-		printk(KERN_WARNING "I2O Block: Data transfer to deleted device!\n");
-		spin_lock_irqsave(dev->req_queue->queue_lock, flags);
-		i2ob_unhook_request(ireq, c->unit);
-		i2ob_end_request(ireq->req);
-		spin_unlock_irqrestore(dev->req_queue->queue_lock, flags);
-		return;
-	}	
+		req->errors++;
+		printk(KERN_WARNING
+		       "I2O Block: Data transfer to deleted device!\n");
+		spin_lock_irqsave(q->queue_lock, flags);
+		while (end_that_request_chunk
+		       (req, !req->errors, readl(&msg->body[1]))) ;
+		end_that_request_last(req);
+
+		dev->open_queue_depth--;
+		list_del(&ireq->queue);
+		blk_start_queue(q);
+
+		spin_unlock_irqrestore(q->queue_lock, flags);
+		return -1;
+	}
 
 	/*
-	 *	Lets see what is cooking. We stuffed the
-	 *	request in the context.
+	 *      Lets see what is cooking. We stuffed the
+	 *      request in the context.
 	 */
-		 
-	ireq=&i2ob_queues[c->unit]->request_queue[m[3]];
-	st=m[4]>>24;
 
-	if(st!=0)
-	{
+	st = readl(&msg->body[0]) >> 24;
+
+	if (st != 0) {
 		int err;
-		char *bsa_errors[] = 
-		{ 
-			"Success", 
-			"Media Error", 
+		char *bsa_errors[] = {
+			"Success",
+			"Media Error",
 			"Failure communicating to device",
 			"Device Failure",
 			"Device is not ready",
@@ -540,61 +523,62 @@ static void i2o_block_reply(struct i2o_handler *h, struct i2o_controller *c, str
 			"Device has reset",
 			"Volume has changed, waiting for acknowledgement"
 		};
-				
-		err = m[4]&0xFFFF;
-		
+
+		err = readl(&msg->body[0]) & 0xffff;
+
 		/*
-		 *	Device not ready means two things. One is that the
-		 *	the thing went offline (but not a removal media)
+		 *      Device not ready means two things. One is that the
+		 *      the thing went offline (but not a removal media)
 		 *
-		 *	The second is that you have a SuperTrak 100 and the
-		 *	firmware got constipated. Unlike standard i2o card
-		 *	setups the supertrak returns an error rather than
-		 *	blocking for the timeout in these cases. 
+		 *      The second is that you have a SuperTrak 100 and the
+		 *      firmware got constipated. Unlike standard i2o card
+		 *      setups the supertrak returns an error rather than
+		 *      blocking for the timeout in these cases.
 		 *
-		 *	Don't stick a supertrak100 into cache aggressive modes
+		 *      Don't stick a supertrak100 into cache aggressive modes
 		 */
-		 
-		
-		printk(KERN_ERR "\n/dev/%s error: %s", dev->i2odev->dev_name, 
-			bsa_errors[m[4]&0XFFFF]);
-		if(m[4]&0x00FF0000)
-			printk(" - DDM attempted %d retries", (m[4]>>16)&0x00FF );
+
+		printk(KERN_ERR "\n/dev/%s error: %s", dev->gd->disk_name,
+		       bsa_errors[readl(&msg->body[0]) & 0xffff]);
+		if (readl(&msg->body[0]) & 0x00ff0000)
+			printk(" - DDM attempted %d retries",
+			       (readl(&msg->body[0]) >> 16) & 0x00ff);
 		printk(".\n");
-		ireq->req->errors++;	
-	}
-	else
-		ireq->req->errors = 0;
+		req->errors++;
+	} else
+		req->errors = 0;
 
-	/*
-	 *	Dequeue the request. We use irqsave locks as one day we
-	 *	may be running polled controllers from a BH...
-	 */
-	
-	i2ob_free_sglist(dev, ireq);
-	spin_lock_irqsave(dev->req_queue->queue_lock, flags);
-	i2ob_unhook_request(ireq, c->unit);
-	i2ob_end_request(ireq->req);
-	i2ob_queues[c->unit]->queue_depth --;
-	
-	/*
-	 *	We may be able to do more I/O
-	 */
-	 
-	i2ob_request(dev->gd->queue);
-	spin_unlock_irqrestore(dev->req_queue->queue_lock, flags);
-}
+	if (!end_that_request_chunk(req, !req->errors, readl(&msg->body[1]))) {
+		add_disk_randomness(req->rq_disk);
+		spin_lock_irqsave(q->queue_lock, flags);
 
-/* 
- * Event handler.  Needs to be a separate thread b/c we may have
- * to do things like scan a partition table, or query parameters
- * which cannot be done from an interrupt or from a bottom half.
- */
-static int i2ob_evt(void *dummy)
+		end_that_request_last(req);
+
+		dev->open_queue_depth--;
+		list_del(&ireq->queue);
+		blk_start_queue(q);
+
+		spin_unlock_irqrestore(q->queue_lock, flags);
+
+		i2o_block_sglist_free(ireq);
+		i2o_block_request_free(ireq);
+	} else
+		printk(KERN_ERR "still remaining chunks\n");
+
+	return 1;
+};
+
+static void i2o_block_event(struct i2o_event *evt)
+{
+	printk(KERN_INFO "block-osm: event received\n");
+};
+
+#if 0
+static int i2o_block_event(void *dummy)
 {
 	unsigned int evt;
 	unsigned long flags;
-	struct i2ob_device *dev;
+	struct i2o_block_device *dev;
 	int unit;
 	//The only event that has data is the SCSI_SMART event.
 	struct i2o_reply {
@@ -604,24 +588,22 @@ static int i2ob_evt(void *dummy)
 		u8 ASCQ;
 		u16 pad;
 		u8 data[16];
-		} *evt_local;
+	} *evt_local;
 
 	daemonize("i2oblock");
 	allow_signal(SIGKILL);
 
 	evt_running = 1;
 
-	while(1)
-	{
-		if(down_interruptible(&i2ob_evt_sem))
-		{
+	while (1) {
+		if (down_interruptible(&i2ob_evt_sem)) {
 			evt_running = 0;
 			printk("exiting...");
 			break;
 		}
 
 		/*
-		 * Keep another CPU/interrupt from overwriting the 
+		 * Keep another CPU/interrupt from overwriting the
 		 * message while we're reading it
 		 *
 		 * We stuffed the unit in the TxContext and grab the event mask
@@ -634,20 +616,19 @@ static int i2ob_evt(void *dummy)
 		unit = le32_to_cpu(evt_local->header[3]);
 		evt = le32_to_cpu(evt_local->evt_indicator);
 
-		dev = &i2ob_dev[unit];
-		switch(evt)
-		{
+		dev = &i2o_blk_dev[unit];
+		switch (evt) {
 			/*
 			 * New volume loaded on same TID, so we just re-install.
 			 * The TID/controller don't change as it is the same
 			 * I2O device.  It's just new media that we have to
 			 * rescan.
 			 */
-			case I2O_EVT_IND_BSA_VOLUME_LOAD:
+		case I2O_EVT_IND_BSA_VOLUME_LOAD:
 			{
-				i2ob_install_device(dev->i2odev->controller,
-					dev->i2odev, unit);
-				add_disk(dev->gd);
+				i2ob_install_device(dev->i2o_device->iop,
+						    dev->i2o_device, unit);
+				add_disk(dev->gendisk);
 				break;
 			}
 
@@ -657,144 +638,108 @@ static int i2ob_evt(void *dummy)
 			 * have media, so we don't want to clear the controller or
 			 * device pointer.
 			 */
-			case I2O_EVT_IND_BSA_VOLUME_UNLOAD:
+		case I2O_EVT_IND_BSA_VOLUME_UNLOAD:
 			{
-				struct gendisk *p = dev->gd;
-				blk_queue_max_sectors(dev->gd->queue, 0);
+				struct gendisk *p = dev->gendisk;
+				blk_queue_max_sectors(dev->gendisk->queue, 0);
 				del_gendisk(p);
 				put_disk(p);
-				dev->gd = NULL;
+				dev->gendisk = NULL;
 				dev->media_change_flag = 1;
 				break;
 			}
 
-			case I2O_EVT_IND_BSA_VOLUME_UNLOAD_REQ:
-				printk(KERN_WARNING "%s: Attempt to eject locked media\n", 
-					dev->i2odev->dev_name);
-				break;
+		case I2O_EVT_IND_BSA_VOLUME_UNLOAD_REQ:
+			printk(KERN_WARNING
+			       "%s: Attempt to eject locked media\n",
+			       dev->i2o_device->dev_name);
+			break;
 
 			/*
 			 * The capacity has changed and we are going to be
-			 * updating the max_sectors and other information 
+			 * updating the max_sectors and other information
 			 * about this disk.  We try a revalidate first. If
 			 * the block device is in use, we don't want to
 			 * do that as there may be I/Os bound for the disk
-			 * at the moment.  In that case we read the size 
+			 * at the moment.  In that case we read the size
 			 * from the device and update the information ourselves
 			 * and the user can later force a partition table
 			 * update through an ioctl.
 			 */
-			case I2O_EVT_IND_BSA_CAPACITY_CHANGE:
+		case I2O_EVT_IND_BSA_CAPACITY_CHANGE:
 			{
 				u64 size;
 
-	  			if(i2ob_query_device(dev, 0x0004, 0, &size, 8) !=0 )
-					i2ob_query_device(dev, 0x0000, 4, &size, 8);
+				if (i2ob_query_device(dev, 0x0004, 0, &size, 8)
+				    != 0)
+					i2ob_query_device(dev, 0x0000, 4, &size,
+							  8);
 
-				spin_lock_irqsave(dev->req_queue->queue_lock, flags);
-				set_capacity(dev->gd, size>>9);
-				spin_unlock_irqrestore(dev->req_queue->queue_lock, flags);
+				spin_lock_irqsave(dev->req_queue->queue_lock,
+						  flags);
+				set_capacity(dev->gendisk, size >> 9);
+				spin_unlock_irqrestore(dev->req_queue->
+						       queue_lock, flags);
 				break;
 			}
 
-			/* 
+			/*
 			 * We got a SCSI SMART event, we just log the relevant
 			 * information and let the user decide what they want
 			 * to do with the information.
 			 */
-			case I2O_EVT_IND_BSA_SCSI_SMART:
+		case I2O_EVT_IND_BSA_SCSI_SMART:
 			{
 				char buf[16];
-				printk(KERN_INFO "I2O Block: %s received a SCSI SMART Event\n",dev->i2odev->dev_name);
-				evt_local->data[16]='\0';
-				sprintf(buf,"%s",&evt_local->data[0]);
-				printk(KERN_INFO "      Disk Serial#:%s\n",buf);
-				printk(KERN_INFO "      ASC 0x%02x \n",evt_local->ASC);
-				printk(KERN_INFO "      ASCQ 0x%02x \n",evt_local->ASCQ);
+				printk(KERN_INFO
+				       "I2O Block: %s received a SCSI SMART Event\n",
+				       dev->i2o_device->dev_name);
+				evt_local->data[16] = '\0';
+				sprintf(buf, "%s", &evt_local->data[0]);
+				printk(KERN_INFO "      Disk Serial#:%s\n",
+				       buf);
+				printk(KERN_INFO "      ASC 0x%02x \n",
+				       evt_local->ASC);
+				printk(KERN_INFO "      ASCQ 0x%02x \n",
+				       evt_local->ASCQ);
 				break;
 			}
-		
+
 			/*
-			 *	Non event
+			 *      Non event
 			 */
-			 
-			case 0:
-				break;
-				
+
+		case 0:
+			break;
+
 			/*
 			 * An event we didn't ask for.  Call the card manufacturer
 			 * and tell them to fix their firmware :)
 			 */
-			 
-			case 0x20:
-				/*
-				 * If a promise card reports 0x20 event then the brown stuff
-				 * hit the fan big time. The card seems to recover but loses
-				 * the pending writes. Deeply ungood except for testing fsck
-				 */
-				if(dev->i2odev->controller->promise)
-					panic("I2O controller firmware failed. Reboot and force a filesystem check.\n");
-			default:
-				printk(KERN_INFO "%s: Received event 0x%X we didn't register for\n"
-					KERN_INFO "   Blame the I2O card manufacturer 8)\n", 
-					dev->i2odev->dev_name, evt);
-				break;
-		}
-	};
-
-	complete_and_exit(&i2ob_thread_dead,0);
-	return 0;
-}
-
-/*
- *	The I2O block driver is listed as one of those that pulls the
- *	front entry off the queue before processing it. This is important
- *	to remember here. If we drop the io lock then CURRENT will change
- *	on us. We must unlink CURRENT in this routine before we return, if
- *	we use it.
- */
-
-static void i2ob_request(request_queue_t *q)
-{
-	struct request *req;
-	struct i2ob_request *ireq;
-	struct i2ob_device *dev;
-	u32 m;
-	
-	while ((req = elv_next_request(q)) != NULL) {
-		dev = req->rq_disk->private_data;
-
-		/* 
-		 *	Queue depths probably belong with some kind of 
-		 *	generic IOP commit control. Certainly it's not right 
-		 *	its global!  
-		 */
-		if(i2ob_queues[dev->unit]->queue_depth >= dev->depth)
-			break;
-		
-		/* Get a message */
-		m = i2ob_get(dev);
 
-		if(m==0xFFFFFFFF)
-		{
-			if(i2ob_queues[dev->unit]->queue_depth == 0)
-				printk(KERN_ERR "i2o_block: message queue and request queue empty!!\n");
+		case 0x20:
+			/*
+			 * If a promise card reports 0x20 event then the brown stuff
+			 * hit the fan big time. The card seems to recover but loses
+			 * the pending writes. Deeply ungood except for testing fsck
+			 */
+			if (dev->i2o_device->iop->promise)
+				panic
+				    ("I2O controller firmware failed. Reboot and force a filesystem check.\n");
+		default:
+			printk(KERN_INFO
+			       "%s: Received event 0x%X we didn't register for\n"
+			       KERN_INFO
+			       "   Blame the I2O card manufacturer 8)\n",
+			       dev->i2o_device->dev_name, evt);
 			break;
 		}
-		/*
-		 * Everything ok, so pull from kernel queue onto our queue
-		 */
-		req->errors = 0;
-		blkdev_dequeue_request(req);	
-		
-		ireq = i2ob_queues[dev->unit]->i2ob_qhead;
-		i2ob_queues[dev->unit]->i2ob_qhead = ireq->next;
-		ireq->req = req;
+	};
 
-		i2ob_send(m, dev, ireq, dev->index);
-	}
+	complete_and_exit(&i2ob_thread_dead, 0);
+	return 0;
 }
-
+#endif
 
 /*
  *	SCSI-CAM for ioctl geometry mapping
@@ -803,8 +748,8 @@ static void i2ob_request(request_queue_t *q)
  *
  * LBA -> CHS mapping table taken from:
  *
- * "Incorporating the I2O Architecture into BIOS for Intel Architecture 
- *  Platforms" 
+ * "Incorporating the I2O Architecture into BIOS for Intel Architecture
+ *  Platforms"
  *
  * This is an I2O document that is only available to I2O members,
  * not developers.
@@ -825,865 +770,647 @@ static void i2ob_request(request_queue_t *q)
 #define	BLOCK_SIZE_42G		8806400
 #define	BLOCK_SIZE_84G		17612800
 
-static void i2o_block_biosparam(
-	unsigned long capacity,
-	unsigned short *cyls,
-	unsigned char *hds,
-	unsigned char *secs) 
-{ 
-	unsigned long heads, sectors, cylinders; 
+static void i2o_block_biosparam(unsigned long capacity, unsigned short *cyls,
+				unsigned char *hds, unsigned char *secs)
+{
+	unsigned long heads, sectors, cylinders;
 
-	sectors = 63L;      			/* Maximize sectors per track */ 
-	if(capacity <= BLOCK_SIZE_528M)
+	sectors = 63L;		/* Maximize sectors per track */
+	if (capacity <= BLOCK_SIZE_528M)
 		heads = 16;
-	else if(capacity <= BLOCK_SIZE_1G)
+	else if (capacity <= BLOCK_SIZE_1G)
 		heads = 32;
-	else if(capacity <= BLOCK_SIZE_21G)
+	else if (capacity <= BLOCK_SIZE_21G)
 		heads = 64;
-	else if(capacity <= BLOCK_SIZE_42G)
+	else if (capacity <= BLOCK_SIZE_42G)
 		heads = 128;
 	else
 		heads = 255;
 
 	cylinders = (unsigned long)capacity / (heads * sectors);
 
-	*cyls = (unsigned short) cylinders;	/* Stuff return values */ 
-	*secs = (unsigned char) sectors; 
-	*hds  = (unsigned char) heads; 
+	*cyls = (unsigned short)cylinders;	/* Stuff return values */
+	*secs = (unsigned char)sectors;
+	*hds = (unsigned char)heads;
 }
 
-/*
- *	Issue device specific ioctl calls.
+/**
+ *	i2o_block_open - Open the block device
+ *
+ *	Power up the device, mount and lock the media. This function is called,
+ *	if the block device is opened for access.
+ *
+ *	Returns 0 on success or negative error code on failure.
  */
-
-static int i2ob_ioctl(struct inode *inode, struct file *file,
-		     unsigned int cmd, unsigned long arg)
+static int i2o_block_open(struct inode *inode, struct file *file)
 {
-	struct gendisk *disk = inode->i_bdev->bd_disk;
-	struct i2ob_device *dev = disk->private_data;
-	void __user *argp = (void __user *)arg;
+	struct i2o_block_device *dev = inode->i_bdev->bd_disk->private_data;
 
-	/* Anyone capable of this syscall can do *real bad* things */
+	if (!dev->i2o_dev)
+		return -ENODEV;
 
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-	switch (cmd) {
-		case HDIO_GETGEO:
-		{
-			struct hd_geometry g;
-			i2o_block_biosparam(get_capacity(disk), 
-					&g.cylinders, &g.heads, &g.sectors);
-			g.start = get_start_sect(inode->i_bdev);
-			return copy_to_user(argp, &g, sizeof(g))?-EFAULT:0;
-		}
-		
-		case BLKI2OGRSTRAT:
-			return put_user(dev->rcache, (int __user *)argp);
-		case BLKI2OGWSTRAT:
-			return put_user(dev->wcache, (int __user *)argp);
-		case BLKI2OSRSTRAT:
-			if(arg<0||arg>CACHE_SMARTFETCH)
-				return -EINVAL;
-			dev->rcache = arg;
-			break;
-		case BLKI2OSWSTRAT:
-			if(arg!=0 && (arg<CACHE_WRITETHROUGH || arg>CACHE_SMARTBACK))
-				return -EINVAL;
-			dev->wcache = arg;
-			break;
-	}
-	return -ENOTTY;
-}
+	if (dev->power > 0x1f)
+		i2o_block_device_power(dev, 0x02);
 
-/*
- *	Close the block device down
+	i2o_block_device_mount(dev->i2o_dev, -1);
+
+	i2o_block_device_lock(dev->i2o_dev, -1);
+
+	pr_debug("Ready.\n");
+
+	return 0;
+};
+
+/**
+ *	i2o_block_release - Release the I2O block device
+ *
+ *	Unlock and unmount the media, and power down the device. Gets called if
+ *	the block device is closed.
+ *
+ *	Returns 0 on success or negative error code on failure.
  */
- 
-static int i2ob_release(struct inode *inode, struct file *file)
+static int i2o_block_release(struct inode *inode, struct file *file)
 {
 	struct gendisk *disk = inode->i_bdev->bd_disk;
-	struct i2ob_device *dev = disk->private_data;
+	struct i2o_block_device *dev = disk->private_data;
+	u8 operation;
 
 	/*
 	 * This is to deail with the case of an application
 	 * opening a device and then the device dissapears while
 	 * it's in use, and then the application tries to release
-	 * it.  ex: Unmounting a deleted RAID volume at reboot. 
+	 * it.  ex: Unmounting a deleted RAID volume at reboot.
 	 * If we send messages, it will just cause FAILs since
 	 * the TID no longer exists.
 	 */
-	if(!dev->i2odev)
+	if (!dev->i2o_dev)
 		return 0;
 
-	if (dev->refcnt <= 0)
-		printk(KERN_ALERT "i2ob_release: refcount(%d) <= 0\n", dev->refcnt);
-	dev->refcnt--;
-	if(dev->refcnt==0)
-	{
-		/*
-		 *	Flush the onboard cache on unmount
-		 */
-		u32 msg[5];
-		int *query_done = &dev->done_flag;
-		msg[0] = (FIVE_WORD_MSG_SIZE|SGL_OFFSET_0);
-		msg[1] = I2O_CMD_BLOCK_CFLUSH<<24|HOST_TID<<12|dev->tid;
-		msg[2] = i2ob_context|0x40000000;
-		msg[3] = (u32)query_done;
-		msg[4] = 60<<16;
-		DEBUG("Flushing...");
-		i2o_post_wait(dev->controller, msg, 20, 60);
+	i2o_block_device_flush(dev->i2o_dev);
 
-		/*
-		 *	Unlock the media
-		 */
-		msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;
-		msg[1] = I2O_CMD_BLOCK_MUNLOCK<<24|HOST_TID<<12|dev->tid;
-		msg[2] = i2ob_context|0x40000000;
-		msg[3] = (u32)query_done;
-		msg[4] = -1;
-		DEBUG("Unlocking...");
-		i2o_post_wait(dev->controller, msg, 20, 2);
-		DEBUG("Unlocked.\n");
-
-		msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
-		msg[1] = I2O_CMD_BLOCK_POWER<<24 | HOST_TID << 12 | dev->tid;
-		if(dev->flags & (1<<3|1<<4))	/* Removable */
-			msg[4] = 0x21 << 24;
-		else
-			msg[4] = 0x24 << 24;
-
-		if(i2o_post_wait(dev->controller, msg, 20, 60)==0)
-			dev->power = 0x24;
+	i2o_block_device_unlock(dev->i2o_dev, -1);
 
-		/*
- 		 * Now unclaim the device.
-		 */
+	if (dev->flags & (1 << 3 | 1 << 4))	/* Removable */
+		operation = 0x21;
+	else
+		operation = 0x24;
+
+	i2o_block_device_power(dev, operation);
 
-		if (i2o_release_device(dev->i2odev, &i2o_block_handler))
-			printk(KERN_ERR "i2ob_release: controller rejected unclaim.\n");
-		
-		DEBUG("Unclaim\n");
-	}
 	return 0;
 }
 
-/*
- *	Open the block device.
+/**
+ *	i2o_block_ioctl - Issue device specific ioctl calls.
+ *	@cmd: ioctl command
+ *	@arg: arg
+ *
+ *	Handles ioctl request for the block device.
+ *
+ *	Return 0 on success or negative error on failure.
  */
- 
-static int i2ob_open(struct inode *inode, struct file *file)
+static int i2o_block_ioctl(struct inode *inode, struct file *file,
+			   unsigned int cmd, unsigned long arg)
 {
 	struct gendisk *disk = inode->i_bdev->bd_disk;
-	struct i2ob_device *dev = disk->private_data;
+	struct i2o_block_device *dev = disk->private_data;
+	void __user *argp = (void __user *)arg;
 
-	if(!dev->i2odev)	
-		return -ENODEV;
-	
-	if(dev->refcnt++==0)
-	{ 
-		u32 msg[6];
-		
-		DEBUG("Claim ");
-		if(i2o_claim_device(dev->i2odev, &i2o_block_handler))
-		{
-			dev->refcnt--;
-			printk(KERN_INFO "I2O Block: Could not open device\n");
-			return -EBUSY;
-		}
-		DEBUG("Claimed ");
-		/*
-	 	 *	Power up if needed
-	 	 */
+	/* Anyone capable of this syscall can do *real bad* things */
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
 
-		if(dev->power > 0x1f)
+	switch (cmd) {
+	case HDIO_GETGEO:
 		{
-			msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
-			msg[1] = I2O_CMD_BLOCK_POWER<<24 | HOST_TID << 12 | dev->tid;
-			msg[4] = 0x02 << 24;
-			if(i2o_post_wait(dev->controller, msg, 20, 60) == 0)
-				dev->power = 0x02;
+			struct hd_geometry g;
+			i2o_block_biosparam(get_capacity(disk),
+					    &g.cylinders, &g.heads, &g.sectors);
+			g.start = get_start_sect(inode->i_bdev);
+			return copy_to_user(argp, &g, sizeof(g)) ? -EFAULT : 0;
 		}
 
-		/*
-		 *	Mount the media if needed. Note that we don't use
-		 *	the lock bit. Since we have to issue a lock if it
-		 *	refuses a mount (quite possible) then we might as
-		 *	well just send two messages out.
-		 */
-		msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;		
-		msg[1] = I2O_CMD_BLOCK_MMOUNT<<24|HOST_TID<<12|dev->tid;
-		msg[4] = -1;
-		msg[5] = 0;
-		DEBUG("Mount ");
-		i2o_post_wait(dev->controller, msg, 24, 2);
-
-		/*
-		 *	Lock the media
-		 */
-		msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;
-		msg[1] = I2O_CMD_BLOCK_MLOCK<<24|HOST_TID<<12|dev->tid;
-		msg[4] = -1;
-		DEBUG("Lock ");
-		i2o_post_wait(dev->controller, msg, 20, 2);
-		DEBUG("Ready.\n");
-	}		
-	return 0;
-}
+	case BLKI2OGRSTRAT:
+		return put_user(dev->rcache, (int __user *)arg);
+	case BLKI2OGWSTRAT:
+		return put_user(dev->wcache, (int __user *)arg);
+	case BLKI2OSRSTRAT:
+		if (arg < 0 || arg > CACHE_SMARTFETCH)
+			return -EINVAL;
+		dev->rcache = arg;
+		break;
+	case BLKI2OSWSTRAT:
+		if (arg != 0
+		    && (arg < CACHE_WRITETHROUGH || arg > CACHE_SMARTBACK))
+			return -EINVAL;
+		dev->wcache = arg;
+		break;
+	}
+	return -ENOTTY;
+};
 
-/*
- *	Issue a device query
+/**
+ *	i2o_block_media_changed - Have we seen a media change?
+ *	@disk: gendisk which should be verified
+ *
+ *	Verifies if the media has changed.
+ *
+ *	Returns 1 if the media was changed or 0 otherwise.
  */
- 
-static int i2ob_query_device(struct i2ob_device *dev, int table, 
-	int field, void *buf, int buflen)
+static int i2o_block_media_changed(struct gendisk *disk)
 {
-	return i2o_query_scalar(dev->controller, dev->tid,
-		table, field, buf, buflen);
-}
+	struct i2o_block_device *p = disk->private_data;
 
+	if (p->media_change_flag) {
+		p->media_change_flag = 0;
+		return 1;
+	}
+	return 0;
+}
 
-/*
- *	Install the I2O block device we found.
+/**
+ *	i2o_block_transfer - Transfer a request to/from the I2O controller
+ *	@req: the request which should be transfered
+ *
+ *	This function converts the request into a I2O message. The necessary
+ *	DMA buffers are allocated and after everything is setup post the message
+ *	to the I2O controller. No cleanup is done by this function. It is done
+ *	on the interrupt side when the reply arrives.
+ *
+ *	Return 0 on success or negative error code on failure.
  */
- 
-static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, int unit)
+static int i2o_block_transfer(struct request *req)
 {
-	u64 size;
-	u32 blocksize;
-	u8 type;
-	u16 power;
-	u32 flags, status;
-	struct i2ob_device *dev=&i2ob_dev[unit];
-	struct gendisk *disk;
-	request_queue_t *q;
-	int segments;
-
+	struct i2o_block_device *dev = req->rq_disk->private_data;
+	struct i2o_controller *c = dev->i2o_dev->iop;
+	int tid = dev->i2o_dev->lct_data.tid;
+	struct i2o_message *msg;
+	void *mptr;
+	struct i2o_block_request *ireq = req->special;
+	struct scatterlist *sg;
+	int sgnum;
+	int i;
+	u32 m;
+	u32 tcntxt;
+	u32 sg_flags;
+	int rc;
+
+	m = i2o_msg_get(c, &msg);
+	if (m == I2O_QUEUE_EMPTY) {
+		rc = -EBUSY;
+		goto exit;
+	}
 
-	/*
-	 * For logging purposes...
-	 */
-	printk(KERN_INFO "i2ob: Installing tid %d device at unit %d\n", 
-			d->lct_data.tid, unit);	
+	tcntxt = i2o_cntxt_list_add(c, req);
+	if (!tcntxt) {
+		rc = -ENOMEM;
+		goto nop_msg;
+	}
 
-	/*
-	 * If this is the first I2O block device found on this IOP,
-	 * we need to initialize all the queue data structures
-	 * before any I/O can be performed. If it fails, this
-	 * device is useless.
-	 */
-	if(!i2ob_queues[c->unit]) {
-		if(i2ob_init_iop(c->unit))
-			return 1;
+	if ((sgnum = i2o_block_sglist_alloc(ireq)) <= 0) {
+		rc = -ENOMEM;
+		goto context_remove;
 	}
 
-	q = i2ob_queues[c->unit]->req_queue;
+	/* Build the message based on the request. */
+	writel(i2o_block_driver.context, &msg->u.s.icntxt);
+	writel(tcntxt, &msg->u.s.tcntxt);
+	writel(req->nr_sectors << 9, &msg->body[1]);
 
-	/*
-	 * This will save one level of lookup/indirection in critical
-	 * code so that we can directly get the queue ptr from the
-	 * device instead of having to go the IOP data structure.
-	 */
-	dev->req_queue = q;
+	writel((((u64) req->sector) << 9) & 0xffffffff, &msg->body[2]);
+	writel(req->sector >> 23, &msg->body[3]);
 
-	/*
-	 * Allocate a gendisk structure and initialize it
-	 */
-	disk = alloc_disk(16);
-	if (!disk)
-		return 1;
+	mptr = &msg->body[4];
 
-	dev->gd = disk;
-	/* initialize gendik structure */
-	disk->major = MAJOR_NR;
-	disk->first_minor = unit<<4;
-	disk->queue = q;
-	disk->fops = &i2ob_fops;
-	sprintf(disk->disk_name, "i2o/hd%c", 'a' + unit);
-	disk->private_data = dev;
+	sg = ireq->sg_table;
 
-	/*
-	 *	Ask for the current media data. If that isn't supported
-	 *	then we ask for the device capacity data
-	 */
-	if(i2ob_query_device(dev, 0x0004, 1, &blocksize, 4) != 0
-	  || i2ob_query_device(dev, 0x0004, 0, &size, 8) !=0 )
-	{
-		i2ob_query_device(dev, 0x0000, 3, &blocksize, 4);
-		i2ob_query_device(dev, 0x0000, 4, &size, 8);
+	if (rq_data_dir(req) == READ) {
+		writel(I2O_CMD_BLOCK_READ << 24 | HOST_TID << 12 | tid,
+		       &msg->u.head[1]);
+		sg_flags = 0x10000000;
+		switch (dev->rcache) {
+		case CACHE_NULL:
+			writel(0, &msg->body[0]);
+			break;
+		case CACHE_PREFETCH:
+			writel(0x201F0008, &msg->body[0]);
+			break;
+		case CACHE_SMARTFETCH:
+			if (req->nr_sectors > 16)
+				writel(0x201F0008, &msg->body[0]);
+			else
+				writel(0x001F0000, &msg->body[0]);
+			break;
+		}
+	} else {
+		writel(I2O_CMD_BLOCK_WRITE << 24 | HOST_TID << 12 | tid,
+		       &msg->u.head[1]);
+		sg_flags = 0x14000000;
+		switch (dev->wcache) {
+		case CACHE_NULL:
+			writel(0, &msg->body[0]);
+			break;
+		case CACHE_WRITETHROUGH:
+			writel(0x001F0008, &msg->body[0]);
+			break;
+		case CACHE_WRITEBACK:
+			writel(0x001F0010, &msg->body[0]);
+			break;
+		case CACHE_SMARTBACK:
+			if (req->nr_sectors > 16)
+				writel(0x001F0004, &msg->body[0]);
+			else
+				writel(0x001F0010, &msg->body[0]);
+			break;
+		case CACHE_SMARTTHROUGH:
+			if (req->nr_sectors > 16)
+				writel(0x001F0004, &msg->body[0]);
+			else
+				writel(0x001F0010, &msg->body[0]);
+		}
 	}
-	
-	if(i2ob_query_device(dev, 0x0000, 2, &power, 2)!=0)
-		power = 0;
-	i2ob_query_device(dev, 0x0000, 5, &flags, 4);
-	i2ob_query_device(dev, 0x0000, 6, &status, 4);
-	set_capacity(disk, size>>9);
 
-	/*
-	 * Max number of Scatter-Gather Elements
-	 */	
-
-	dev->power = power;	/* Save power state in device proper */
-	dev->flags = flags;
-
-	segments = (d->controller->status_block->inbound_frame_size - 7) / 2;
-
-	if(segments > 16)
-		segments = 16;
-
-	dev->power = power;	/* Save power state */
-	dev->flags = flags;	/* Keep the type info */
-		
-	blk_queue_max_sectors(q, 96);	/* 256 might be nicer but many controllers
-						   explode on 65536 or higher */
-	blk_queue_max_phys_segments(q, segments);
-	blk_queue_max_hw_segments(q, segments);
-		
-	dev->rcache = CACHE_SMARTFETCH;
-	dev->wcache = CACHE_WRITETHROUGH;
-		
-	if(d->controller->battery == 0)
-		dev->wcache = CACHE_WRITETHROUGH;
-
-	if(d->controller->promise)
-		dev->wcache = CACHE_WRITETHROUGH;
-
-	if(d->controller->short_req)
-	{
-		blk_queue_max_sectors(q, 8);
-		blk_queue_max_phys_segments(q, 8);
-		blk_queue_max_hw_segments(q, 8);
+	for (i = sgnum; i > 0; i--) {
+		if (i == 1)
+			sg_flags |= 0x80000000;
+		writel(sg_flags | sg_dma_len(sg), mptr);
+		writel(sg_dma_address(sg), mptr + 4);
+		mptr += 8;
+		sg++;
 	}
 
-	strcpy(d->dev_name, disk->disk_name);
-	strcpy(disk->devfs_name, disk->disk_name);
-
-	printk(KERN_INFO "%s: Max segments %d, queue depth %d, byte limit %d.\n",
-		 d->dev_name, dev->max_segments, dev->depth, dev->max_sectors<<9);
+	writel(I2O_MESSAGE_SIZE
+	       (((unsigned long)mptr -
+		 (unsigned long)&msg->u.head[0]) >> 2) | SGL_OFFSET_8,
+	       &msg->u.head[0]);
 
-	i2ob_query_device(dev, 0x0000, 0, &type, 1);
-
-	printk(KERN_INFO "%s: ", d->dev_name);
-	switch(type)
-	{
-		case 0: printk("Disk Storage");break;
-		case 4: printk("WORM");break;
-		case 5: printk("CD-ROM");break;
-		case 7:	printk("Optical device");break;
-		default:
-			printk("Type %d", type);
-	}
-	if(status&(1<<10))
-		printk("(RAID)");
-
-	if((flags^status)&(1<<4|1<<3))	/* Missing media or device */
-	{
-		printk(KERN_INFO " Not loaded.\n");
-		/* Device missing ? */
-		if((flags^status)&(1<<4))
-			return 1;
-	}
-	else
-	{
-		printk(": %dMB, %d byte sectors",
-			(int)(size>>20), blocksize);
-	}
-	if(status&(1<<0))
-	{
-		u32 cachesize;
-		i2ob_query_device(dev, 0x0003, 0, &cachesize, 4);
-		cachesize>>=10;
-		if(cachesize>4095)
-			printk(", %dMb cache", cachesize>>10);
-		else
-			printk(", %dKb cache", cachesize);
-	}
-	printk(".\n");
-	printk(KERN_INFO "%s: Maximum sectors/read set to %d.\n", 
-		d->dev_name, dev->max_sectors);
+	i2o_msg_post(c, m);
 
-	/*
-	 * Register for the events we're interested in and that the
-	 * device actually supports.
-	 */
+	list_add_tail(&ireq->queue, &dev->open_queue);
+	dev->open_queue_depth++;
 
-	i2o_event_register(c, d->lct_data.tid, i2ob_context, unit, 
-		(I2OB_EVENT_MASK & d->lct_data.event_capabilities));
 	return 0;
-}
-
-/*
- * Initialize IOP specific queue structures.  This is called
- * once for each IOP that has a block device sitting behind it.
- */
-static int i2ob_init_iop(unsigned int unit)
-{
-	int i;
 
-	i2ob_queues[unit] = (struct i2ob_iop_queue *) kmalloc(sizeof(struct i2ob_iop_queue), GFP_ATOMIC);
-	if(!i2ob_queues[unit])
-	{
-		printk(KERN_WARNING "Could not allocate request queue for I2O block device!\n");
-		return -1;
-	}
-
-	for(i = 0; i< MAX_I2OB_DEPTH; i++)
-	{
-		i2ob_queues[unit]->request_queue[i].next =  &i2ob_queues[unit]->request_queue[i+1];
-		i2ob_queues[unit]->request_queue[i].num = i;
-	}
-	
-	/* Queue is MAX_I2OB + 1... */
-	i2ob_queues[unit]->request_queue[i].next = NULL;
-	i2ob_queues[unit]->i2ob_qhead = &i2ob_queues[unit]->request_queue[0];
-	i2ob_queues[unit]->queue_depth = 0;
-
-	i2ob_queues[unit]->lock = SPIN_LOCK_UNLOCKED;
-	i2ob_queues[unit]->req_queue = blk_init_queue(i2ob_request, &i2ob_queues[unit]->lock);
-	if (!i2ob_queues[unit]->req_queue) {
-		kfree(i2ob_queues[unit]);
-		return -1;
-	}
+      context_remove:
+	i2o_cntxt_list_remove(c, req);
 
-	i2ob_queues[unit]->req_queue->queuedata = &i2ob_queues[unit];
+      nop_msg:
+	i2o_msg_nop(c, m);
 
-	return 0;
-}
+      exit:
+	return rc;
+};
 
-/*
- * Probe the I2O subsytem for block class devices
+/**
+ *	i2o_block_request_fn - request queue handling function
+ *	q: request queue from which the request could be fetched
+ *
+ *	Takes the next request from the queue, transfers it and if no error
+ *	occurs dequeue it from the queue. On arrival of the reply the message
+ *	will be processed further. If an error occurs requeue the request.
  */
-static void i2ob_scan(int bios)
+static void i2o_block_request_fn(struct request_queue *q)
 {
-	int i;
-	int warned = 0;
-
-	struct i2o_device *d, *b=NULL;
-	struct i2o_controller *c;
-		
-	for(i=0; i< MAX_I2O_CONTROLLERS; i++)
-	{
-		c=i2o_find_controller(i);
-	
-		if(c==NULL)
-			continue;
+	struct request *req;
 
-		/*
-		 *    The device list connected to the I2O Controller is doubly linked
-		 * Here we traverse the end of the list , and start claiming devices
-		 * from that end. This assures that within an I2O controller atleast
-		 * the newly created volumes get claimed after the older ones, thus
-		 * mapping to same major/minor (and hence device file name) after 
-		 * every reboot.
-		 * The exception being: 
-		 * 1. If there was a TID reuse.
-		 * 2. There was more than one I2O controller. 
-		 */
+	while (!blk_queue_plugged(q)) {
+		req = elv_next_request(q);
+		if (!req)
+			break;
 
-		if(!bios)
-		{
-			for (d=c->devices;d!=NULL;d=d->next)
-			if(d->next == NULL)
-				b = d;
-		}
-		else
-			b = c->devices;
+		if (blk_fs_request(req)) {
+			struct i2o_block_delayed_request *dreq;
+			struct i2o_block_request *ireq = req->special;
+			unsigned int queue_depth;
 
-		while(b != NULL)
-		{
-			d=b;
-			if(bios)
-				b = b->next;
-			else
-				b = b->prev;
+			queue_depth = ireq->i2o_blk_dev->open_queue_depth;
 
-			if(d->lct_data.class_id!=I2O_CLASS_RANDOM_BLOCK_STORAGE)
-				continue;
+			if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS)
+				if (!i2o_block_transfer(req)) {
+					blkdev_dequeue_request(req);
+					continue;
+				}
 
-			if(d->lct_data.user_tid != 0xFFF)
-				continue;
+			if (queue_depth)
+				break;
 
-			if(bios)
-			{
-				if(d->lct_data.bios_info != 0x80)
-					continue;
-				printk(KERN_INFO "Claiming as Boot device: Controller %d, TID %d\n", c->unit, d->lct_data.tid);
-			}
-			else
-			{
-				if(d->lct_data.bios_info == 0x80)
-					continue; /*Already claimed on pass 1 */
-			}
+			/* stop the queue and retry later */
+			dreq = kmalloc(sizeof(*dreq), GFP_ATOMIC);
+			if (!dreq)
+				continue;
 
-			if(scan_unit<MAX_I2OB)
-				i2ob_new_device(c, d);
-			else
-			{
-				if(!warned++)
-					printk(KERN_WARNING "i2o_block: too many device, registering only %d.\n", scan_unit);
+			dreq->queue = q;
+			INIT_WORK(&dreq->work, i2o_block_delayed_request_fn,
+				  dreq);
+
+			printk(KERN_INFO "block-osm: transfer error\n");
+			if (!queue_delayed_work(i2o_block_driver.event_queue,
+						&dreq->work,
+						I2O_BLOCK_RETRY_TIME))
+				kfree(dreq);
+			else {
+				blk_stop_queue(q);
+				break;
 			}
-		}
-		i2o_unlock_controller(c);
+		} else
+			end_request(req, 0);
 	}
-}
+};
 
-static void i2ob_probe(void)
+/* I2O Block device operations definition */
+static struct block_device_operations i2o_block_fops = {
+	.owner = THIS_MODULE,
+	.open = i2o_block_open,
+	.release = i2o_block_release,
+	.ioctl = i2o_block_ioctl,
+	.media_changed = i2o_block_media_changed
+};
+
+/**
+ *	i2o_block_device_alloc - Allocate memory for a I2O Block device
+ *
+ *	Allocate memory for the i2o_block_device struct, gendisk and request
+ *	queue and initialize them as far as no additional information is needed.
+ *
+ *	Returns a pointer to the allocated I2O Block device on succes or a
+ *	negative error code on failure.
+ */
+static struct i2o_block_device *i2o_block_device_alloc(void)
 {
-	/*
-	 *      Some overhead/redundancy involved here, while trying to
-	 *      claim the first boot volume encountered as /dev/i2o/hda
-	 *      everytime. All the i2o_controllers are searched and the
-	 *      first i2o block device marked as bootable is claimed
-	 *      If an I2O block device was booted off , the bios sets
-	 *      its bios_info field to 0x80, this what we search for.
-	 *      Assuming that the bootable volume is /dev/i2o/hda
-	 *      everytime will prevent any kernel panic while mounting
-	 *      root partition
-	 */
+	struct i2o_block_device *dev;
+	struct gendisk *gd;
+	struct request_queue *queue;
+	int rc;
+
+	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev) {
+		printk(KERN_ERR "block-osm: Insufficient memory to allocate "
+		       "I2O Block disk.\n");
+		rc = -ENOMEM;
+		goto exit;
+	}
+	memset(dev, 0, sizeof(*dev));
+
+	INIT_LIST_HEAD(&dev->open_queue);
+	spin_lock_init(&dev->lock);
+	dev->rcache = CACHE_PREFETCH;
+	dev->wcache = CACHE_WRITEBACK;
+
+	/* allocate a gendisk with 16 partitions */
+	gd = alloc_disk(16);
+	if (!gd) {
+		printk(KERN_ERR "block-osm: Insufficient memory to allocate "
+		       "gendisk.\n");
+		rc = -ENOMEM;
+		goto cleanup_dev;
+	}
 
-	printk(KERN_INFO "i2o_block: Checking for Boot device...\n");
-	i2ob_scan(1);
+	/* initialize the request queue */
+	queue = blk_init_queue(i2o_block_request_fn, &dev->lock);
+	if (!queue) {
+		printk(KERN_ERR "block-osm: Insufficient memory to allocate "
+		       "request queue.\n");
+		rc = -ENOMEM;
+		goto cleanup_queue;
+	}
 
-	/*
-	 *      Now the remainder.
-	 */
-	printk(KERN_INFO "i2o_block: Checking for I2O Block devices...\n");
-	i2ob_scan(0);
-}
+	blk_queue_prep_rq(queue, i2o_block_prep_req_fn);
 
+	gd->major = I2O_MAJOR;
+	gd->queue = queue;
+	gd->fops = &i2o_block_fops;
+	gd->private_data = dev;
 
-/*
- * New device notification handler.  Called whenever a new
- * I2O block storage device is added to the system.
- * 
- * Should we spin lock around this to keep multiple devs from 
- * getting updated at the same time? 
- * 
+	dev->gd = gd;
+
+	return dev;
+
+      cleanup_queue:
+	put_disk(gd);
+
+      cleanup_dev:
+	kfree(dev);
+
+      exit:
+	return ERR_PTR(rc);
+};
+
+/**
+ *	i2o_block_probe - verify if dev is a I2O Block device and install it
+ *	@dev: device to verify if it is a I2O Block device
+ *
+ *	We only verify if the user_tid of the device is 0xfff and then install
+ *	the device. Otherwise it is used by some other device (e. g. RAID).
+ *
+ *	Returns 0 on success or negative error code on failure.
  */
-void i2ob_new_device(struct i2o_controller *c, struct i2o_device *d)
+static int i2o_block_probe(struct device *dev)
 {
-	struct i2ob_device *dev;
-	int unit = 0;
-
-	printk(KERN_INFO "i2o_block: New device detected\n");
-	printk(KERN_INFO "   Controller %d Tid %d\n",c->unit, d->lct_data.tid);
+	struct i2o_device *i2o_dev = to_i2o_device(dev);
+	struct i2o_block_device *i2o_blk_dev;
+	struct i2o_controller *c = i2o_dev->iop;
+	struct gendisk *gd;
+	struct request_queue *queue;
+	static int unit = 0;
+	int rc;
+	u64 size;
+	u32 blocksize;
+	u16 power;
+	u32 flags, status;
+	int segments;
 
-	/* Check for available space */
-	if(i2ob_dev_count>=MAX_I2OB)
-	{
-		printk(KERN_ERR "i2o_block: No more devices allowed!\n");
-		return;
+	/* skip devices which are used by IOP */
+	if (i2o_dev->lct_data.user_tid != 0xfff) {
+		pr_debug("skipping used device %03x\n", i2o_dev->lct_data.tid);
+		return -ENODEV;
 	}
-	for(unit = 0; unit < MAX_I2OB; unit ++)
-	{
-		if(!i2ob_dev[unit].i2odev)
-			break;
+
+	printk(KERN_INFO "block-osm: New device detected (TID: %03x)\n",
+	       i2o_dev->lct_data.tid);
+
+	if (i2o_device_claim(i2o_dev)) {
+		printk(KERN_WARNING "block-osm: Unable to claim device. "
+		       "Installation aborted\n");
+		rc = -EFAULT;
+		goto exit;
 	}
 
-	if(i2o_claim_device(d, &i2o_block_handler))
-	{
-		printk(KERN_INFO "i2o_block: Unable to claim device. Installation aborted\n");
-		return;
+	i2o_blk_dev = i2o_block_device_alloc();
+	if (IS_ERR(i2o_blk_dev)) {
+		printk(KERN_ERR "block-osm: could not alloc a new I2O block"
+		       "device");
+		rc = PTR_ERR(i2o_blk_dev);
+		goto claim_release;
 	}
 
-	dev = &i2ob_dev[unit];
-	dev->i2odev = d; 
-	dev->controller = c;
-	dev->tid = d->lct_data.tid;
-	dev->unit = c->unit;
+	i2o_blk_dev->i2o_dev = i2o_dev;
+	dev_set_drvdata(dev, i2o_blk_dev);
 
-	if(i2ob_install_device(c,d,unit)) {
-		i2o_release_device(d, &i2o_block_handler);
-		printk(KERN_ERR "i2o_block: Could not install new device\n");
-	}
-	else	
-	{
-		i2o_release_device(d, &i2o_block_handler);
-		add_disk(dev->gd);
-		i2ob_dev_count++;
-		i2o_device_notify_on(d, &i2o_block_handler);
-	}
+	/* setup gendisk */
+	gd = i2o_blk_dev->gd;
+	gd->first_minor = unit << 4;
+	sprintf(gd->disk_name, "i2o/hd%c", 'a' + unit);
+	sprintf(gd->devfs_name, "i2o/hd%c", 'a' + unit);
+	gd->driverfs_dev = &i2o_dev->device;
 
-	return;
-}
+	/* setup request queue */
+	queue = gd->queue;
+	queue->queuedata = i2o_blk_dev;
 
-/*
- * Deleted device notification handler.  Called when a device we
- * are talking to has been deleted by the user or some other
- * mysterious fource outside the kernel.
- */
-void i2ob_del_device(struct i2o_controller *c, struct i2o_device *d)
-{	
-	int unit = 0;
-	unsigned long flags;
-	struct i2ob_device *dev;
+	blk_queue_max_phys_segments(queue, I2O_MAX_SEGMENTS);
+	blk_queue_max_sectors(queue, I2O_MAX_SECTORS);
 
-	for(unit = 0; unit < MAX_I2OB; unit ++)
-	{
-		dev = &i2ob_dev[unit];
-		if(dev->i2odev == d)
-		{
-			printk(KERN_INFO "  /dev/%s: Controller %d Tid %d\n", 
-				d->dev_name, c->unit, d->lct_data.tid);
-			break;
-		}
-	}
+	if (c->short_req)
+		segments = 8;
+	else {
+		i2o_status_block *sb;
 
-	printk(KERN_INFO "I2O Block Device Deleted\n");
+		sb = c->status_block.virt;
 
-	if(unit >= MAX_I2OB)
-	{
-		printk(KERN_ERR "i2ob_del_device called, but not in dev table!\n");
-		return;
+		segments = (sb->inbound_frame_size -
+			    sizeof(struct i2o_message) / 4 - 4) / 2;
 	}
 
-	spin_lock_irqsave(dev->req_queue->queue_lock, flags);
+	blk_queue_max_hw_segments(queue, segments);
 
-	/*
-	 * Need to do this...we somtimes get two events from the IRTOS
-	 * in a row and that causes lots of problems.
-	 */
-	i2o_device_notify_off(d, &i2o_block_handler);
+	pr_debug("max sectors:   %d\n", I2O_MAX_SECTORS);
+	pr_debug("phys segments: %d\n", I2O_MAX_SEGMENTS);
+	pr_debug("hw segments:   %d\n", segments);
 
-	/* 
-	 * This will force errors when i2ob_get_queue() is called
-	 * by the kenrel.
+	/*
+	 *      Ask for the current media data. If that isn't supported
+	 *      then we ask for the device capacity data
 	 */
-	if(dev->gd) {
-		struct gendisk *gd = dev->gd;
-		gd->queue = NULL;
-		del_gendisk(gd);
-		put_disk(gd);
-		dev->gd = NULL;
+	if (i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) != 0
+	    || i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) != 0) {
+		i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4);
+		i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8);
 	}
-	spin_unlock_irqrestore(dev->req_queue->queue_lock, flags);
-	dev->req_queue = NULL;
-	dev->i2odev = NULL;
-	dev->refcnt = 0;
-	dev->tid = 0;
-
-	/* 
-	 * Do we need this?
-	 * The media didn't really change...the device is just gone
-	 */
-	dev->media_change_flag = 1;
+	pr_debug("blocksize:     %d\n", blocksize);
 
-	i2ob_dev_count--;	
-}
+	if (i2o_parm_field_get(i2o_dev, 0x0000, 2, &power, 2))
+		power = 0;
+	i2o_parm_field_get(i2o_dev, 0x0000, 5, &flags, 4);
+	i2o_parm_field_get(i2o_dev, 0x0000, 6, &status, 4);
+
+	set_capacity(gd, size >> 9);
+
+	i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0xffffffff);
+
+	add_disk(gd);
+
+	unit++;
 
-/*
- *	Have we seen a media change ?
- */
-static int i2ob_media_change(struct gendisk *disk)
-{
-	struct i2ob_device *p = disk->private_data;
-	if(p->media_change_flag)
-	{
-		p->media_change_flag=0;
-		return 1;
-	}
 	return 0;
-}
 
-static int i2ob_revalidate(struct gendisk *disk)
-{
-	struct i2ob_device *p = disk->private_data;
-	return i2ob_install_device(p->controller, p->i2odev, p->index);
-}
+      claim_release:
+	i2o_device_claim_release(i2o_dev);
 
-/*
- * Reboot notifier.  This is called by i2o_core when the system
- * shuts down.
- */
-static void i2ob_reboot_event(void)
-{
-	int i;
-	
-	for(i=0;i<MAX_I2OB;i++)
-	{
-		struct i2ob_device *dev=&i2ob_dev[i];
-		
-		if(dev->refcnt!=0)
-		{
-			/*
-			 *	Flush the onboard cache
-			 */
-			u32 msg[5];
-			int *query_done = &dev->done_flag;
-			msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;
-			msg[1] = I2O_CMD_BLOCK_CFLUSH<<24|HOST_TID<<12|dev->tid;
-			msg[2] = i2ob_context|0x40000000;
-			msg[3] = (u32)query_done;
-			msg[4] = 60<<16;
-			
-			DEBUG("Flushing...");
-			i2o_post_wait(dev->controller, msg, 20, 60);
-
-			DEBUG("Unlocking...");
-			/*
-			 *	Unlock the media
-			 */
-			msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;
-			msg[1] = I2O_CMD_BLOCK_MUNLOCK<<24|HOST_TID<<12|dev->tid;
-			msg[2] = i2ob_context|0x40000000;
-			msg[3] = (u32)query_done;
-			msg[4] = -1;
-			i2o_post_wait(dev->controller, msg, 20, 2);
-			
-			DEBUG("Unlocked.\n");
-		}
-	}	
-}
+      exit:
+	return rc;
+};
 
-static struct block_device_operations i2ob_fops =
-{
-	.owner		= THIS_MODULE,
-	.open		= i2ob_open,
-	.release	= i2ob_release,
-	.ioctl		= i2ob_ioctl,
-	.media_changed	= i2ob_media_change,
-	.revalidate_disk= i2ob_revalidate,
+/* Block OSM driver struct */
+static struct i2o_driver i2o_block_driver = {
+	.name = "block-osm",
+	.event = i2o_block_event,
+	.reply = i2o_block_reply,
+	.classes = i2o_block_class_id,
+	.driver = {
+		   .probe = i2o_block_probe,
+		   .remove = i2o_block_remove,
+		   },
 };
 
-/*
- * And here should be modules and kernel interface 
- *  (Just smiley confuses emacs :-)
+/**
+ *	i2o_block_init - Block OSM initialization function
+ *
+ *	Allocate the slab and mempool for request structs, registers i2o_block
+ *	block device and finally register the Block OSM in the I2O core.
+ *
+ *	Returns 0 on success or negative error code on failure.
  */
-
-static int i2o_block_init(void)
+static int __init i2o_block_init(void)
 {
-	int i;
+	int rc;
+	int size;
 
 	printk(KERN_INFO "I2O Block Storage OSM v0.9\n");
 	printk(KERN_INFO "   (c) Copyright 1999-2001 Red Hat Software.\n");
-	
-	/*
-	 *	Register the block device interfaces
-	 */
-	if (register_blkdev(MAJOR_NR, "i2o_block"))
-		return -EIO;
-
-#ifdef MODULE
-	printk(KERN_INFO "i2o_block: registered device at major %d\n", MAJOR_NR);
-#endif
 
-	/*
-	 *	Set up the queue
-	 */
-	for(i = 0; i < MAX_I2O_CONTROLLERS; i++)
-		i2ob_queues[i] = NULL;
-
-	/*
-	 *	Now fill in the boiler plate
-	 */
-	 
-	for (i = 0; i < MAX_I2OB; i++) {
-		struct i2ob_device *dev = &i2ob_dev[i];
-		dev->index = i;
-		dev->refcnt = 0;
-		dev->flags = 0;
-		dev->controller = NULL;
-		dev->i2odev = NULL;
-		dev->tid = 0;
-		dev->head = NULL;
-		dev->tail = NULL;
-		dev->depth = MAX_I2OB_DEPTH;
-		dev->max_sectors = 2;
-		dev->gd = NULL;
+	/* Allocate request mempool and slab */
+	size = sizeof(struct i2o_block_request);
+	i2o_blk_req_pool.slab = kmem_cache_create("i2o_block_req", size, 0,
+						  SLAB_HWCACHE_ALIGN, NULL,
+						  NULL);
+	if (!i2o_blk_req_pool.slab) {
+		printk(KERN_ERR "block-osm: can't init request slab\n");
+		rc = -ENOMEM;
+		goto exit;
 	}
-	
-	/*
-	 *	Register the OSM handler as we will need this to probe for
-	 *	drives, geometry and other goodies.
-	 */
 
-	if(i2o_install_handler(&i2o_block_handler)<0)
-	{
-		unregister_blkdev(MAJOR_NR, "i2o_block");
-		printk(KERN_ERR "i2o_block: unable to register OSM.\n");
-		return -EINVAL;
+	i2o_blk_req_pool.pool = mempool_create(I2O_REQ_MEMPOOL_SIZE,
+					       mempool_alloc_slab,
+					       mempool_free_slab,
+					       i2o_blk_req_pool.slab);
+	if (!i2o_blk_req_pool.pool) {
+		printk(KERN_ERR "block-osm: can't init request mempool\n");
+		rc = -ENOMEM;
+		goto free_slab;
 	}
-	i2ob_context = i2o_block_handler.context;	 
 
-	/*
-	 * Initialize event handling thread
-	 */
-	init_MUTEX_LOCKED(&i2ob_evt_sem);
-	evt_pid = kernel_thread(i2ob_evt, NULL, CLONE_SIGHAND);
-	if(evt_pid < 0)
-	{
-		printk(KERN_ERR "i2o_block: Could not initialize event thread.  Aborting\n");
-		i2o_remove_handler(&i2o_block_handler);
-		return 0;
+	/* Register the block device interfaces */
+	rc = register_blkdev(I2O_MAJOR, "i2o_block");
+	if (rc) {
+		printk(KERN_ERR "block-osm: unable to register block device\n");
+		goto free_mempool;
 	}
+#ifdef MODULE
+	printk(KERN_INFO "block-osm: registered device at major %d\n",
+	       I2O_MAJOR);
+#endif
 
-	i2ob_probe();
+	/* Register Block OSM into I2O core */
+	rc = i2o_driver_register(&i2o_block_driver);
+	if (rc) {
+		printk(KERN_ERR "block-osm: Could not register Block driver\n");
+		goto unregister_blkdev;
+	}
 
 	return 0;
 
-	unregister_blkdev(MAJOR_NR, "i2o_block");
-	return -ENOMEM;
-}
+      unregister_blkdev:
+	unregister_blkdev(I2O_MAJOR, "i2o_block");
 
+      free_mempool:
+	mempool_destroy(i2o_blk_req_pool.pool);
 
-static void i2o_block_exit(void)
-{
-	int i;
-	
-	if(evt_running) {
-		printk(KERN_INFO "Killing I2O block threads...");
-		i = kill_proc(evt_pid, SIGKILL, 1);
-		if(!i) {
-			printk("waiting...\n");
-		}
-		/* Be sure it died */
-		wait_for_completion(&i2ob_thread_dead);
-		printk("done.\n");
-	}
+      free_slab:
+	kmem_cache_destroy(i2o_blk_req_pool.slab);
 
-	/*
-	 * Unregister for updates from any devices..otherwise we still
-	 * get them and the core jumps to random memory :O
-	 */
-	if(i2ob_dev_count) {
-		struct i2o_device *d;
-		for(i = 0; i < MAX_I2OB; i++)
-			if((d = i2ob_dev[i].i2odev))
-				i2ob_del_device(d->controller, d);
-	}
-	
-	/*
-	 *	We may get further callbacks for ourself. The i2o_core
-	 *	code handles this case reasonably sanely. The problem here
-	 *	is we shouldn't get them .. but a couple of cards feel 
-	 *	obliged to tell us stuff we don't care about.
-	 *
-	 *	This isnt ideal at all but will do for now.
-	 */
-	 
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ);
-	
-	/*
-	 *	Flush the OSM
-	 */
+      exit:
+	return rc;
+};
 
-	i2o_remove_handler(&i2o_block_handler);
+/**
+ *	i2o_block_exit - Block OSM exit function
+ *
+ *	Unregisters Block OSM from I2O core, unregisters i2o_block block device
+ *	and frees the mempool and slab.
+ */
+static void __exit i2o_block_exit(void)
+{
+	/* Unregister I2O Block OSM from I2O core */
+	i2o_driver_unregister(&i2o_block_driver);
 
-	/*
-	 *	Return the block device
-	 */
-	if (unregister_blkdev(MAJOR_NR, "i2o_block") != 0)
-		printk("i2o_block: cleanup_module failed\n");
+	/* Unregister block device */
+	unregister_blkdev(I2O_MAJOR, "i2o_block");
 
-	/*
-	 *	release request queue
-	 */
-	for (i = 0; i < MAX_I2O_CONTROLLERS; i ++)
-		if(i2ob_queues[i]) {
-			blk_cleanup_queue(i2ob_queues[i]->req_queue);
-			kfree(i2ob_queues[i]);
-		}
-}
+	/* Free request mempool and slab */
+	mempool_destroy(i2o_blk_req_pool.pool);
+	kmem_cache_destroy(i2o_blk_req_pool.slab);
+};
 
 MODULE_AUTHOR("Red Hat");
 MODULE_DESCRIPTION("I2O Block Device OSM");
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index a28c4423b..4c240102a 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -2,7 +2,7 @@
  * I2O Configuration Interface Driver
  *
  * (C) Copyright 1999-2002  Red Hat
- *	
+ *
  * Written by Alan Cox, Building Number Three Ltd
  *
  * Fixes/additions:
@@ -41,63 +41,53 @@
 #include <linux/mm.h>
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
+#include <linux/ioctl32.h>
+#include <linux/compat.h>
+#include <linux/syscalls.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-static int i2o_cfg_context = -1;
-static void *page_buf;
+extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int);
+
 static spinlock_t i2o_config_lock = SPIN_LOCK_UNLOCKED;
 struct wait_queue *i2o_wait_queue;
 
 #define MODINC(x,y) ((x) = ((x) + 1) % (y))
 
 struct sg_simple_element {
-	u32  flag_count;
+	u32 flag_count;
 	u32 addr_bus;
 };
 
-struct i2o_cfg_info
-{
-	struct file* fp;
+struct i2o_cfg_info {
+	struct file *fp;
 	struct fasync_struct *fasync;
 	struct i2o_evt_info event_q[I2O_EVT_Q_LEN];
-	u16		q_in;		// Queue head index
-	u16		q_out;		// Queue tail index
-	u16		q_len;		// Queue length
-	u16		q_lost;		// Number of lost events
-	u32		q_id;		// Event queue ID...used as tx_context
-	struct	i2o_cfg_info *next;
+	u16 q_in;		// Queue head index
+	u16 q_out;		// Queue tail index
+	u16 q_len;		// Queue length
+	u16 q_lost;		// Number of lost events
+	ulong q_id;		// Event queue ID...used as tx_context
+	struct i2o_cfg_info *next;
 };
 static struct i2o_cfg_info *open_files = NULL;
-static int i2o_cfg_info_id = 0;
-
-static int ioctl_getiops(unsigned long);
-static int ioctl_gethrt(unsigned long);
-static int ioctl_getlct(unsigned long);
-static int ioctl_parms(unsigned long, unsigned int);
-static int ioctl_html(unsigned long);
-static int ioctl_swdl(unsigned long);
-static int ioctl_swul(unsigned long);
-static int ioctl_swdel(unsigned long);
-static int ioctl_validate(unsigned long); 
-static int ioctl_evt_reg(unsigned long, struct file *);
-static int ioctl_evt_get(unsigned long, struct file *);
-static int ioctl_passthru(unsigned long);
-static int cfg_fasync(int, struct file*, int);
+static ulong i2o_cfg_info_id = 0;
 
+#if 0
 /*
  *	This is the callback for any message we have posted. The message itself
  *	will be returned to the message pool when we return from the IRQ
  *
  *	This runs in irq context so be short and sweet.
  */
-static void i2o_cfg_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *m)
+static void i2o_cfg_reply(struct i2o_handler *h, struct i2o_controller *c,
+			  struct i2o_message *m)
 {
-	u32 *msg = (u32 *)m;
+	u32 *msg = (u32 *) m;
 
 	if (msg[0] & MSG_FAIL) {
-		u32 *preserved_msg = (u32*)(c->msg_virt + msg[7]);
+		u32 *preserved_msg = (u32 *) (c->msg_virt + msg[7]);
 
 		printk(KERN_ERR "i2o_config: IOP failed to process the msg.\n");
 
@@ -109,26 +99,25 @@ static void i2o_cfg_reply(struct i2o_handler *h, struct i2o_controller *c, struc
 		i2o_post_message(c, msg[7]);
 	}
 
-	if (msg[4] >> 24)  // ReqStatus != SUCCESS
-		i2o_report_status(KERN_INFO,"i2o_config", msg);
+	if (msg[4] >> 24)	// ReqStatus != SUCCESS
+		i2o_report_status(KERN_INFO, "i2o_config", msg);
 
-	if(m->function == I2O_CMD_UTIL_EVT_REGISTER)
-	{
+	if (m->function == I2O_CMD_UTIL_EVT_REGISTER) {
 		struct i2o_cfg_info *inf;
 
-		for(inf = open_files; inf; inf = inf->next)
-			if(inf->q_id == msg[3])
+		for (inf = open_files; inf; inf = inf->next)
+			if (inf->q_id == i2o_cntxt_list_get(c, msg[3]))
 				break;
 
 		//
 		// If this is the case, it means that we're getting
 		// events for a file descriptor that's been close()'d
 		// w/o the user unregistering for events first.
-		// The code currently assumes that the user will 
+		// The code currently assumes that the user will
 		// take care of unregistering for events before closing
 		// a file.
-		// 
-		// TODO: 
+		//
+		// TODO:
 		// Should we track event registartion and deregister
 		// for events when a file is close()'d so this doesn't
 		// happen? That would get rid of the search through
@@ -137,8 +126,8 @@ static void i2o_cfg_reply(struct i2o_handler *h, struct i2o_controller *c, struc
 		// it would mean having all sorts of tables to track
 		// what each file is registered for...I think the
 		// current method is simpler. - DS
-		//			
-		if(!inf)
+		//
+		if (!inf)
 			return;
 
 		inf->event_q[inf->q_in].id.iop = c->unit;
@@ -149,278 +138,167 @@ static void i2o_cfg_reply(struct i2o_handler *h, struct i2o_controller *c, struc
 		// Data size = msg size - reply header
 		//
 		inf->event_q[inf->q_in].data_size = (m->size - 5) * 4;
-		if(inf->event_q[inf->q_in].data_size)
-			memcpy(inf->event_q[inf->q_in].evt_data, 
-				(unsigned char *)(msg + 5),
-				inf->event_q[inf->q_in].data_size);
+		if (inf->event_q[inf->q_in].data_size)
+			memcpy(inf->event_q[inf->q_in].evt_data,
+			       (unsigned char *)(msg + 5),
+			       inf->event_q[inf->q_in].data_size);
 
 		spin_lock(&i2o_config_lock);
 		MODINC(inf->q_in, I2O_EVT_Q_LEN);
-		if(inf->q_len == I2O_EVT_Q_LEN)
-		{
+		if (inf->q_len == I2O_EVT_Q_LEN) {
 			MODINC(inf->q_out, I2O_EVT_Q_LEN);
 			inf->q_lost++;
-		}
-		else
-		{
+		} else {
 			// Keep I2OEVTGET on another CPU from touching this
 			inf->q_len++;
 		}
 		spin_unlock(&i2o_config_lock);
-		
 
-//		printk(KERN_INFO "File %p w/id %d has %d events\n",
-//			inf->fp, inf->q_id, inf->q_len);	
+//              printk(KERN_INFO "File %p w/id %d has %d events\n",
+//                      inf->fp, inf->q_id, inf->q_len);
 
 		kill_fasync(&inf->fasync, SIGIO, POLL_IN);
 	}
 
 	return;
 }
+#endif
 
 /*
  *	Each of these describes an i2o message handler. They are
  *	multiplexed by the i2o_core code
  */
- 
-struct i2o_handler cfg_handler=
-{
-	i2o_cfg_reply,
-	NULL,
-	NULL,
-	NULL,
-	"Configuration",
-	0,
-	0xffffffff	// All classes
-};
-
-static ssize_t cfg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
-{
-	printk(KERN_INFO "i2o_config write not yet supported\n");
-
-	return 0;
-}
 
+struct i2o_driver i2o_config_driver = {
+	.name = "Config-OSM"
+};
 
-static ssize_t cfg_read(struct file *file, char __user *buf, size_t count, loff_t *ptr)
+static int i2o_cfg_getiops(unsigned long arg)
 {
-	return 0;
-}
-
-/*
- * IOCTL Handler
- */
-static int cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd,
-	unsigned long arg)
-{
-	int ret;
-
-	switch(cmd)
-	{	
-		case I2OGETIOPS:
-			ret = ioctl_getiops(arg);
-			break;
-
-		case I2OHRTGET:
-			ret = ioctl_gethrt(arg);
-			break;
-
-		case I2OLCTGET:
-			ret = ioctl_getlct(arg);
-			break;
-
-		case I2OPARMSET:
-			ret = ioctl_parms(arg, I2OPARMSET);
-			break;
-
-		case I2OPARMGET:
-			ret = ioctl_parms(arg, I2OPARMGET);
-			break;
-
-		case I2OSWDL:
-			ret = ioctl_swdl(arg);
-			break;
-
-		case I2OSWUL:
-			ret = ioctl_swul(arg);
-			break;
-
-		case I2OSWDEL:
-			ret = ioctl_swdel(arg);
-			break;
-
-		case I2OVALIDATE:
-			ret = ioctl_validate(arg);
-			break;
-			
-		case I2OHTML:
-			ret = ioctl_html(arg);
-			break;
-
-		case I2OEVTREG:
-			ret = ioctl_evt_reg(arg, fp);
-			break;
-
-		case I2OEVTGET:
-			ret = ioctl_evt_get(arg, fp);
-			break;
-
-		case I2OPASSTHRU:
-			ret = ioctl_passthru(arg);
-			break;
-
-		default:
-			ret = -EINVAL;
-	}
-
-	return ret;
-}
+	struct i2o_controller *c;
+	u8 __user *user_iop_table = (void __user *)arg;
+	u8 tmp[MAX_I2O_CONTROLLERS];
 
-int ioctl_getiops(unsigned long arg)
-{
-	u8  __user *user_iop_table = (void __user *)arg;
-	struct i2o_controller *c = NULL;
-	int i;
-	u8 foo[MAX_I2O_CONTROLLERS];
+	memset(tmp, 0, MAX_I2O_CONTROLLERS);
 
-	if(!access_ok(VERIFY_WRITE, user_iop_table,  MAX_I2O_CONTROLLERS))
+	if (!access_ok(VERIFY_WRITE, user_iop_table, MAX_I2O_CONTROLLERS))
 		return -EFAULT;
 
-	for(i = 0; i < MAX_I2O_CONTROLLERS; i++)
-	{
-		c = i2o_find_controller(i);
-		if(c)
-		{
-			foo[i] = 1;
-			if(pci_set_dma_mask(c->pdev, 0xffffffff))
-			{
-				printk(KERN_WARNING "i2o_config : No suitable DMA available on controller %d\n", i);
-				i2o_unlock_controller(c);
-				continue;
-			}
-		
-				i2o_unlock_controller(c);
-		}
-		else
-		{
-			foo[i] = 0;
-		}
-	}
+	list_for_each_entry(c, &i2o_controllers, list)
+	    tmp[c->unit] = 1;
+
+	__copy_to_user(user_iop_table, tmp, MAX_I2O_CONTROLLERS);
 
-	__copy_to_user(user_iop_table, foo, MAX_I2O_CONTROLLERS);
 	return 0;
-}
+};
 
-int ioctl_gethrt(unsigned long arg)
+static int i2o_cfg_gethrt(unsigned long arg)
 {
 	struct i2o_controller *c;
-	struct i2o_cmd_hrtlct __user *cmd = (void __user *)arg;
+	struct i2o_cmd_hrtlct __user *cmd = (struct i2o_cmd_hrtlct __user *)arg;
 	struct i2o_cmd_hrtlct kcmd;
 	i2o_hrt *hrt;
 	int len;
 	u32 reslen;
 	int ret = 0;
 
-	if(copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct)))
+	if (copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct)))
 		return -EFAULT;
 
-	if(get_user(reslen, kcmd.reslen) < 0)
+	if (get_user(reslen, kcmd.reslen) < 0)
 		return -EFAULT;
 
-	if(kcmd.resbuf == NULL)
+	if (kcmd.resbuf == NULL)
 		return -EFAULT;
 
-	c = i2o_find_controller(kcmd.iop);
-	if(!c)
+	c = i2o_find_iop(kcmd.iop);
+	if (!c)
 		return -ENXIO;
-		
-	hrt = (i2o_hrt *)c->hrt;
 
-	i2o_unlock_controller(c);
+	hrt = (i2o_hrt *) c->hrt.virt;
 
 	len = 8 + ((hrt->entry_len * hrt->num_entries) << 2);
-	
+
 	/* We did a get user...so assuming mem is ok...is this bad? */
 	put_user(len, kcmd.reslen);
-	if(len > reslen)
-		ret = -ENOBUFS;	
-	if(copy_to_user(kcmd.resbuf, (void*)hrt, len))
+	if (len > reslen)
+		ret = -ENOBUFS;
+	if (copy_to_user(kcmd.resbuf, (void *)hrt, len))
 		ret = -EFAULT;
 
 	return ret;
-}
+};
 
-int ioctl_getlct(unsigned long arg)
+static int i2o_cfg_getlct(unsigned long arg)
 {
 	struct i2o_controller *c;
-	struct i2o_cmd_hrtlct __user *cmd = (void __user *)arg;
+	struct i2o_cmd_hrtlct __user *cmd = (struct i2o_cmd_hrtlct __user *)arg;
 	struct i2o_cmd_hrtlct kcmd;
 	i2o_lct *lct;
 	int len;
 	int ret = 0;
 	u32 reslen;
 
-	if(copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct)))
+	if (copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct)))
 		return -EFAULT;
 
-	if(get_user(reslen, kcmd.reslen) < 0)
+	if (get_user(reslen, kcmd.reslen) < 0)
 		return -EFAULT;
 
-	if(kcmd.resbuf == NULL)
+	if (kcmd.resbuf == NULL)
 		return -EFAULT;
 
-	c = i2o_find_controller(kcmd.iop);
-	if(!c)
+	c = i2o_find_iop(kcmd.iop);
+	if (!c)
 		return -ENXIO;
 
-	lct = (i2o_lct *)c->lct;
-	i2o_unlock_controller(c);
+	lct = (i2o_lct *) c->lct;
 
 	len = (unsigned int)lct->table_size << 2;
 	put_user(len, kcmd.reslen);
-	if(len > reslen)
-		ret = -ENOBUFS;	
-	else if(copy_to_user(kcmd.resbuf, (void*)lct, len))
+	if (len > reslen)
+		ret = -ENOBUFS;
+	else if (copy_to_user(kcmd.resbuf, lct, len))
 		ret = -EFAULT;
 
 	return ret;
-}
+};
 
-static int ioctl_parms(unsigned long arg, unsigned int type)
+static int i2o_cfg_parms(unsigned long arg, unsigned int type)
 {
 	int ret = 0;
 	struct i2o_controller *c;
-	struct i2o_cmd_psetget __user *cmd = (void __user *)arg;
+	struct i2o_device *dev;
+	struct i2o_cmd_psetget __user *cmd =
+	    (struct i2o_cmd_psetget __user *)arg;
 	struct i2o_cmd_psetget kcmd;
 	u32 reslen;
 	u8 *ops;
 	u8 *res;
-	int len;
+	int len = 0;
 
-	u32 i2o_cmd = (type == I2OPARMGET ? 
-				I2O_CMD_UTIL_PARAMS_GET :
-				I2O_CMD_UTIL_PARAMS_SET);
+	u32 i2o_cmd = (type == I2OPARMGET ?
+		       I2O_CMD_UTIL_PARAMS_GET : I2O_CMD_UTIL_PARAMS_SET);
 
-	if(copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_psetget)))
+	if (copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_psetget)))
 		return -EFAULT;
 
-	if(get_user(reslen, kcmd.reslen))
+	if (get_user(reslen, kcmd.reslen))
 		return -EFAULT;
 
-	c = i2o_find_controller(kcmd.iop);
-	if(!c)
+	c = i2o_find_iop(kcmd.iop);
+	if (!c)
+		return -ENXIO;
+
+	dev = i2o_iop_find_device(c, kcmd.tid);
+	if (!dev)
 		return -ENXIO;
 
-	ops = (u8*)kmalloc(kcmd.oplen, GFP_KERNEL);
-	if(!ops)
-	{
-		i2o_unlock_controller(c);
+	ops = (u8 *) kmalloc(kcmd.oplen, GFP_KERNEL);
+	if (!ops)
 		return -ENOMEM;
-	}
 
-	if(copy_from_user(ops, kcmd.opbuf, kcmd.oplen))
-	{
-		i2o_unlock_controller(c);
+	if (copy_from_user(ops, kcmd.opbuf, kcmd.oplen)) {
 		kfree(ops);
 		return -EFAULT;
 	}
@@ -429,404 +307,309 @@ static int ioctl_parms(unsigned long arg, unsigned int type)
 	 * It's possible to have a _very_ large table
 	 * and that the user asks for all of it at once...
 	 */
-	res = (u8*)kmalloc(65536, GFP_KERNEL);
-	if(!res)
-	{
-		i2o_unlock_controller(c);
+	res = (u8 *) kmalloc(65536, GFP_KERNEL);
+	if (!res) {
 		kfree(ops);
 		return -ENOMEM;
 	}
 
-	len = i2o_issue_params(i2o_cmd, c, kcmd.tid, 
-				ops, kcmd.oplen, res, 65536);
-	i2o_unlock_controller(c);
+	len = i2o_parm_issue(dev, i2o_cmd, ops, kcmd.oplen, res, 65536);
 	kfree(ops);
-        
+
 	if (len < 0) {
 		kfree(res);
 		return -EAGAIN;
 	}
 
 	put_user(len, kcmd.reslen);
-	if(len > reslen)
+	if (len > reslen)
 		ret = -ENOBUFS;
-	else if(copy_to_user(kcmd.resbuf, res, len))
+	else if (copy_to_user(kcmd.resbuf, res, len))
 		ret = -EFAULT;
 
 	kfree(res);
 
 	return ret;
-}
-
-int ioctl_html(unsigned long arg)
-{
-	struct i2o_html __user *cmd = (void __user *)arg;
-	struct i2o_html kcmd;
-	struct i2o_controller *c;
-	u8 *res = NULL;
-	void *query = NULL;
-	dma_addr_t query_phys, res_phys;
-	int ret = 0;
-	int token;
-	u32 len;
-	u32 reslen;
-	u32 msg[MSG_FRAME_SIZE];
-
-	if(copy_from_user(&kcmd, cmd, sizeof(struct i2o_html)))
-	{
-		printk(KERN_INFO "i2o_config: can't copy html cmd\n");
-		return -EFAULT;
-	}
-
-	if(get_user(reslen, kcmd.reslen) < 0)
-	{
-		printk(KERN_INFO "i2o_config: can't copy html reslen\n");
-		return -EFAULT;
-	}
-
-	if(!kcmd.resbuf)		
-	{
-		printk(KERN_INFO "i2o_config: NULL html buffer\n");
-		return -EFAULT;
-	}
-
-	c = i2o_find_controller(kcmd.iop);
-	if(!c)
-		return -ENXIO;
-
-	if(kcmd.qlen) /* Check for post data */
-	{
-		query = pci_alloc_consistent(c->pdev, kcmd.qlen, &query_phys);
-		if(!query)
-		{
-			i2o_unlock_controller(c);
-			return -ENOMEM;
-		}
-		if(copy_from_user(query, kcmd.qbuf, kcmd.qlen))
-		{
-			i2o_unlock_controller(c);
-			printk(KERN_INFO "i2o_config: could not get query\n");
-			pci_free_consistent(c->pdev, kcmd.qlen, query, query_phys);
-			return -EFAULT;
-		}
-	}
-
-	res = pci_alloc_consistent(c->pdev, 65536, &res_phys);
-	if(!res)
-	{
-		i2o_unlock_controller(c);
-		pci_free_consistent(c->pdev, kcmd.qlen, query, query_phys);
-		return -ENOMEM;
-	}
-
-	msg[1] = (I2O_CMD_UTIL_CONFIG_DIALOG << 24)|HOST_TID<<12|kcmd.tid;
-	msg[2] = i2o_cfg_context;
-	msg[3] = 0;
-	msg[4] = kcmd.page;
-	msg[5] = 0xD0000000|65536;
-	msg[6] = res_phys;
-	if(!kcmd.qlen) /* Check for post data */
-		msg[0] = SEVEN_WORD_MSG_SIZE|SGL_OFFSET_5;
-	else
-	{
-		msg[0] = NINE_WORD_MSG_SIZE|SGL_OFFSET_5;
-		msg[5] = 0x50000000|65536;
-		msg[7] = 0xD4000000|(kcmd.qlen);
-		msg[8] = query_phys;
-	}
-	/*
-	Wait for a considerable time till the Controller 
-	does its job before timing out. The controller might
-	take more time to process this request if there are
-	many devices connected to it.
-	*/
-	token = i2o_post_wait_mem(c, msg, 9*4, 400, query, res, query_phys, res_phys, kcmd.qlen, 65536);
-	if(token < 0)
-	{
-		printk(KERN_DEBUG "token = %#10x\n", token);
-		i2o_unlock_controller(c);
-		
-		if(token != -ETIMEDOUT)
-		{
-			pci_free_consistent(c->pdev, 65536, res, res_phys);
-			if(kcmd.qlen)
-				pci_free_consistent(c->pdev, kcmd.qlen, query, query_phys);
-		}
-		return token;
-	}
-	i2o_unlock_controller(c);
-
-	len = strnlen(res, 65536);
-	put_user(len, kcmd.reslen);
-	if(len > reslen)
-		ret = -ENOMEM;
-	if(copy_to_user(kcmd.resbuf, res, len))
-		ret = -EFAULT;
-
-	pci_free_consistent(c->pdev, 65536, res, res_phys);
-	if(kcmd.qlen)
-		pci_free_consistent(c->pdev, kcmd.qlen, query, query_phys);
+};
 
-	return ret;
-}
- 
-int ioctl_swdl(unsigned long arg)
+static int i2o_cfg_swdl(unsigned long arg)
 {
 	struct i2o_sw_xfer kxfer;
-	struct i2o_sw_xfer __user *pxfer = (void __user *)arg;
+	struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg;
 	unsigned char maxfrag = 0, curfrag = 1;
-	unsigned char *buffer;
-	u32 msg[9];
+	struct i2o_dma buffer;
+	struct i2o_message *msg;
+	u32 m;
 	unsigned int status = 0, swlen = 0, fragsize = 8192;
 	struct i2o_controller *c;
-	dma_addr_t buffer_phys;
 
-	if(copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer)))
+	if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer)))
 		return -EFAULT;
 
-	if(get_user(swlen, kxfer.swlen) < 0)
+	if (get_user(swlen, kxfer.swlen) < 0)
 		return -EFAULT;
 
-	if(get_user(maxfrag, kxfer.maxfrag) < 0)
+	if (get_user(maxfrag, kxfer.maxfrag) < 0)
 		return -EFAULT;
 
-	if(get_user(curfrag, kxfer.curfrag) < 0)
+	if (get_user(curfrag, kxfer.curfrag) < 0)
 		return -EFAULT;
 
-	if(curfrag==maxfrag) fragsize = swlen-(maxfrag-1)*8192;
+	if (curfrag == maxfrag)
+		fragsize = swlen - (maxfrag - 1) * 8192;
 
-	if(!kxfer.buf || !access_ok(VERIFY_READ, kxfer.buf, fragsize))
+	if (!kxfer.buf || !access_ok(VERIFY_READ, kxfer.buf, fragsize))
 		return -EFAULT;
-	
-	c = i2o_find_controller(kxfer.iop);
-	if(!c)
+
+	c = i2o_find_iop(kxfer.iop);
+	if (!c)
 		return -ENXIO;
 
-	buffer=pci_alloc_consistent(c->pdev, fragsize, &buffer_phys);
-	if (buffer==NULL)
-	{
-		i2o_unlock_controller(c);
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -EBUSY;
+
+	if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) {
+		i2o_msg_nop(c, m);
 		return -ENOMEM;
 	}
-	__copy_from_user(buffer, kxfer.buf, fragsize);
-
-	msg[0]= NINE_WORD_MSG_SIZE | SGL_OFFSET_7;
-	msg[1]= I2O_CMD_SW_DOWNLOAD<<24 | HOST_TID<<12 | ADAPTER_TID;
-	msg[2]= (u32)cfg_handler.context;
-	msg[3]= 0;
-	msg[4]= (((u32)kxfer.flags)<<24) | (((u32)kxfer.sw_type)<<16) |
-		(((u32)maxfrag)<<8) | (((u32)curfrag));
-	msg[5]= swlen;
-	msg[6]= kxfer.sw_id;
-	msg[7]= (0xD0000000 | fragsize);
-	msg[8]= buffer_phys;
-
-//	printk("i2o_config: swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
-	status = i2o_post_wait_mem(c, msg, sizeof(msg), 60, buffer, NULL, buffer_phys, 0, fragsize, 0);
-
-	i2o_unlock_controller(c);
-	if(status != -ETIMEDOUT)
-		pci_free_consistent(c->pdev, fragsize, buffer, buffer_phys);
-	
-	if (status != I2O_POST_WAIT_OK)
-	{
+
+	__copy_from_user(buffer.virt, kxfer.buf, fragsize);
+
+	writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
+	writel(I2O_CMD_SW_DOWNLOAD << 24 | HOST_TID << 12 | ADAPTER_TID,
+	       &msg->u.head[1]);
+	writel(i2o_config_driver.context, &msg->u.head[2]);
+	writel(0, &msg->u.head[3]);
+	writel((((u32) kxfer.flags) << 24) | (((u32) kxfer.sw_type) << 16) |
+	       (((u32) maxfrag) << 8) | (((u32) curfrag)), &msg->body[0]);
+	writel(swlen, &msg->body[1]);
+	writel(kxfer.sw_id, &msg->body[2]);
+	writel(0xD0000000 | fragsize, &msg->body[3]);
+	writel(buffer.phys, &msg->body[4]);
+
+//      printk("i2o_config: swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
+	status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
+
+	if (status != -ETIMEDOUT)
+		i2o_dma_free(&c->pdev->dev, &buffer);
+
+	if (status != I2O_POST_WAIT_OK) {
 		// it fails if you try and send frags out of order
 		// and for some yet unknown reasons too
-		printk(KERN_INFO "i2o_config: swdl failed, DetailedStatus = %d\n", status);
+		printk(KERN_INFO
+		       "i2o_config: swdl failed, DetailedStatus = %d\n",
+		       status);
 		return status;
 	}
 
 	return 0;
-}
+};
 
-int ioctl_swul(unsigned long arg)
+static int i2o_cfg_swul(unsigned long arg)
 {
 	struct i2o_sw_xfer kxfer;
-	struct i2o_sw_xfer __user *pxfer = (void __user *)arg;
+	struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg;
 	unsigned char maxfrag = 0, curfrag = 1;
-	unsigned char *buffer;
-	u32 msg[9];
+	struct i2o_dma buffer;
+	struct i2o_message *msg;
+	u32 m;
 	unsigned int status = 0, swlen = 0, fragsize = 8192;
 	struct i2o_controller *c;
-	dma_addr_t buffer_phys;
-		
-	if(copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer)))
+
+	if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer)))
 		return -EFAULT;
-		
-	if(get_user(swlen, kxfer.swlen) < 0)
+
+	if (get_user(swlen, kxfer.swlen) < 0)
 		return -EFAULT;
-		
-	if(get_user(maxfrag, kxfer.maxfrag) < 0)
+
+	if (get_user(maxfrag, kxfer.maxfrag) < 0)
 		return -EFAULT;
-		
-	if(get_user(curfrag, kxfer.curfrag) < 0)
+
+	if (get_user(curfrag, kxfer.curfrag) < 0)
 		return -EFAULT;
-	
-	if(curfrag==maxfrag) fragsize = swlen-(maxfrag-1)*8192;
-	
-	if(!kxfer.buf || !access_ok(VERIFY_WRITE, kxfer.buf, fragsize))
+
+	if (curfrag == maxfrag)
+		fragsize = swlen - (maxfrag - 1) * 8192;
+
+	if (!kxfer.buf || !access_ok(VERIFY_WRITE, kxfer.buf, fragsize))
 		return -EFAULT;
-		
-	c = i2o_find_controller(kxfer.iop);
-	if(!c)
+
+	c = i2o_find_iop(kxfer.iop);
+	if (!c)
 		return -ENXIO;
-		
-	buffer=pci_alloc_consistent(c->pdev, fragsize, &buffer_phys);
-	if (buffer==NULL)
-	{
-		i2o_unlock_controller(c);
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -EBUSY;
+
+	if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) {
+		i2o_msg_nop(c, m);
 		return -ENOMEM;
 	}
-	
-	msg[0]= NINE_WORD_MSG_SIZE | SGL_OFFSET_7;
-	msg[1]= I2O_CMD_SW_UPLOAD<<24 | HOST_TID<<12 | ADAPTER_TID;
-	msg[2]= (u32)cfg_handler.context;
-	msg[3]= 0;
-	msg[4]= (u32)kxfer.flags<<24|(u32)kxfer.sw_type<<16|(u32)maxfrag<<8|(u32)curfrag;
-	msg[5]= swlen;
-	msg[6]= kxfer.sw_id;
-	msg[7]= (0xD0000000 | fragsize);
-	msg[8]= buffer_phys;
-	
-//	printk("i2o_config: swul frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
-	status = i2o_post_wait_mem(c, msg, sizeof(msg), 60, buffer, NULL, buffer_phys, 0, fragsize, 0);
-	i2o_unlock_controller(c);
-	
-	if (status != I2O_POST_WAIT_OK)
-	{
-		if(status != -ETIMEDOUT)
-			pci_free_consistent(c->pdev, fragsize, buffer, buffer_phys);
-		printk(KERN_INFO "i2o_config: swul failed, DetailedStatus = %d\n", status);
+
+	writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
+	writel(I2O_CMD_SW_UPLOAD << 24 | HOST_TID << 12 | ADAPTER_TID,
+	       &msg->u.head[1]);
+	writel(i2o_config_driver.context, &msg->u.head[2]);
+	writel(0, &msg->u.head[3]);
+	writel((u32) kxfer.flags << 24 | (u32) kxfer.
+	       sw_type << 16 | (u32) maxfrag << 8 | (u32) curfrag,
+	       &msg->body[0]);
+	writel(swlen, &msg->body[1]);
+	writel(kxfer.sw_id, &msg->body[2]);
+	writel(0xD0000000 | fragsize, &msg->body[3]);
+	writel(buffer.phys, &msg->body[4]);
+
+//      printk("i2o_config: swul frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
+	status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
+
+	if (status != I2O_POST_WAIT_OK) {
+		if (status != -ETIMEDOUT)
+			i2o_dma_free(&c->pdev->dev, &buffer);
+
+		printk(KERN_INFO
+		       "i2o_config: swul failed, DetailedStatus = %d\n",
+		       status);
 		return status;
 	}
-	
-	__copy_to_user(kxfer.buf, buffer, fragsize);
-	pci_free_consistent(c->pdev, fragsize, buffer, buffer_phys);
-	
+
+	__copy_to_user(kxfer.buf, buffer.virt, fragsize);
+	i2o_dma_free(&c->pdev->dev, &buffer);
+
 	return 0;
-}
+};
 
-int ioctl_swdel(unsigned long arg)
+static int i2o_cfg_swdel(unsigned long arg)
 {
 	struct i2o_controller *c;
 	struct i2o_sw_xfer kxfer;
-	struct i2o_sw_xfer __user *pxfer = (void __user *)arg;
-	u32 msg[7];
+	struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg;
+	struct i2o_message *msg;
+	u32 m;
 	unsigned int swlen;
 	int token;
-	
+
 	if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer)))
 		return -EFAULT;
-		
+
 	if (get_user(swlen, kxfer.swlen) < 0)
 		return -EFAULT;
-		
-	c = i2o_find_controller(kxfer.iop);
+
+	c = i2o_find_iop(kxfer.iop);
 	if (!c)
 		return -ENXIO;
 
-	msg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0;
-	msg[1] = I2O_CMD_SW_REMOVE<<24 | HOST_TID<<12 | ADAPTER_TID;
-	msg[2] = (u32)i2o_cfg_context;
-	msg[3] = 0;
-	msg[4] = (u32)kxfer.flags<<24 | (u32)kxfer.sw_type<<16;
-	msg[5] = swlen;
-	msg[6] = kxfer.sw_id;
-
-	token = i2o_post_wait(c, msg, sizeof(msg), 10);
-	i2o_unlock_controller(c);
-	
-	if (token != I2O_POST_WAIT_OK)
-	{
-		printk(KERN_INFO "i2o_config: swdel failed, DetailedStatus = %d\n", token);
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -EBUSY;
+
+	writel(SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_SW_REMOVE << 24 | HOST_TID << 12 | ADAPTER_TID,
+	       &msg->u.head[1]);
+	writel(i2o_config_driver.context, &msg->u.head[2]);
+	writel(0, &msg->u.head[3]);
+	writel((u32) kxfer.flags << 24 | (u32) kxfer.sw_type << 16,
+	       &msg->body[0]);
+	writel(swlen, &msg->body[1]);
+	writel(kxfer.sw_id, &msg->body[2]);
+
+	token = i2o_msg_post_wait(c, m, 10);
+
+	if (token != I2O_POST_WAIT_OK) {
+		printk(KERN_INFO
+		       "i2o_config: swdel failed, DetailedStatus = %d\n",
+		       token);
 		return -ETIMEDOUT;
 	}
-	
+
 	return 0;
-}
+};
 
-int ioctl_validate(unsigned long arg)
+static int i2o_cfg_validate(unsigned long arg)
 {
-        int token;
-        int iop = (int)arg;
-        u32 msg[4];
-        struct i2o_controller *c;
-
-        c=i2o_find_controller(iop);
-        if (!c)
-                return -ENXIO;
-
-        msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
-        msg[1] = I2O_CMD_CONFIG_VALIDATE<<24 | HOST_TID<<12 | iop;
-        msg[2] = (u32)i2o_cfg_context;
-        msg[3] = 0;
-
-        token = i2o_post_wait(c, msg, sizeof(msg), 10);
-        i2o_unlock_controller(c);
-
-        if (token != I2O_POST_WAIT_OK)
-        {
-                printk(KERN_INFO "Can't validate configuration, ErrorStatus = %d\n",
-                	token);
-                return -ETIMEDOUT;
-        }
-
-        return 0;
-}   
-
-static int ioctl_evt_reg(unsigned long arg, struct file *fp)
+	int token;
+	int iop = (int)arg;
+	struct i2o_message *msg;
+	u32 m;
+	struct i2o_controller *c;
+
+	c = i2o_find_iop(iop);
+	if (!c)
+		return -ENXIO;
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -EBUSY;
+
+	writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_CONFIG_VALIDATE << 24 | HOST_TID << 12 | iop,
+	       &msg->u.head[1]);
+	writel(i2o_config_driver.context, &msg->u.head[2]);
+	writel(0, &msg->u.head[3]);
+
+	token = i2o_msg_post_wait(c, m, 10);
+
+	if (token != I2O_POST_WAIT_OK) {
+		printk(KERN_INFO "Can't validate configuration, ErrorStatus = "
+		       "%d\n", token);
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+};
+
+static int i2o_cfg_evt_reg(unsigned long arg, struct file *fp)
 {
-	u32 msg[5];
-	struct i2o_evt_id __user *pdesc = (void __user *)arg;
+	struct i2o_message *msg;
+	u32 m;
+	struct i2o_evt_id __user *pdesc = (struct i2o_evt_id __user *)arg;
 	struct i2o_evt_id kdesc;
-	struct i2o_controller *iop;
+	struct i2o_controller *c;
 	struct i2o_device *d;
 
 	if (copy_from_user(&kdesc, pdesc, sizeof(struct i2o_evt_id)))
 		return -EFAULT;
 
 	/* IOP exists? */
-	iop = i2o_find_controller(kdesc.iop);
-	if(!iop)
+	c = i2o_find_iop(kdesc.iop);
+	if (!c)
 		return -ENXIO;
-	i2o_unlock_controller(iop);
 
 	/* Device exists? */
-	for(d = iop->devices; d; d = d->next)
-		if(d->lct_data.tid == kdesc.tid)
-			break;
-
-	if(!d)
+	d = i2o_iop_find_device(c, kdesc.tid);
+	if (!d)
 		return -ENODEV;
 
-	msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
-	msg[1] = I2O_CMD_UTIL_EVT_REGISTER<<24 | HOST_TID<<12 | kdesc.tid;
-	msg[2] = (u32)i2o_cfg_context;
-	msg[3] = (u32)fp->private_data;
-	msg[4] = kdesc.evt_mask;
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -EBUSY;
+
+	writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | kdesc.tid,
+	       &msg->u.head[1]);
+	writel(i2o_config_driver.context, &msg->u.head[2]);
+	writel(i2o_cntxt_list_add(c, fp->private_data), &msg->u.head[3]);
+	writel(kdesc.evt_mask, &msg->body[0]);
 
-	i2o_post_this(iop, msg, 20);
+	i2o_msg_post(c, m);
 
 	return 0;
-}	
+}
 
-static int ioctl_evt_get(unsigned long arg, struct file *fp)
+static int i2o_cfg_evt_get(unsigned long arg, struct file *fp)
 {
-	u32 id = (u32)fp->private_data;
 	struct i2o_cfg_info *p = NULL;
-	struct i2o_evt_get __user *uget = (void __user *)arg;
+	struct i2o_evt_get __user *uget = (struct i2o_evt_get __user *)arg;
 	struct i2o_evt_get kget;
 	unsigned long flags;
 
-	for(p = open_files; p; p = p->next)
-		if(p->q_id == id)
+	for (p = open_files; p; p = p->next)
+		if (p->q_id == (ulong) fp->private_data)
 			break;
 
-	if(!p->q_len)
-	{
+	if (!p->q_len)
 		return -ENOENT;
-		return 0;
-	}
 
 	memcpy(&kget.info, &p->event_q[p->q_out], sizeof(struct i2o_evt_info));
 	MODINC(p->q_out, I2O_EVT_Q_LEN);
@@ -836,16 +619,236 @@ static int ioctl_evt_get(unsigned long arg, struct file *fp)
 	kget.lost = p->q_lost;
 	spin_unlock_irqrestore(&i2o_config_lock, flags);
 
-	if(copy_to_user(uget, &kget, sizeof(struct i2o_evt_get)))
+	if (copy_to_user(uget, &kget, sizeof(struct i2o_evt_get)))
 		return -EFAULT;
 	return 0;
 }
 
-static int ioctl_passthru(unsigned long arg)
+#ifdef CONFIG_COMPAT
+static int i2o_cfg_passthru32(unsigned fd, unsigned cmnd, unsigned long arg,
+			      struct file *file)
 {
-	struct i2o_cmd_passthru __user *cmd = (void __user *) arg;
+	struct i2o_cmd_passthru32 __user *cmd;
+	struct i2o_controller *c;
+	u32 __user *user_msg;
+	u32 *reply = NULL;
+	u32 __user *user_reply = NULL;
+	u32 size = 0;
+	u32 reply_size = 0;
+	u32 rcode = 0;
+	struct i2o_dma sg_list[SG_TABLESIZE];
+	u32 sg_offset = 0;
+	u32 sg_count = 0;
+	u32 i = 0;
+	i2o_status_block *sb;
+	struct i2o_message *msg;
+	u32 m;
+	unsigned int iop;
+
+	cmd = (struct i2o_cmd_passthru32 __user *)arg;
+
+	if (get_user(iop, &cmd->iop) || get_user(i, &cmd->msg))
+		return -EFAULT;
+
+	user_msg = compat_ptr(i);
+
+	c = i2o_find_iop(iop);
+	if (!c) {
+		pr_debug("controller %d not found\n", iop);
+		return -ENXIO;
+	}
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+
+	sb = c->status_block.virt;
+
+	if (get_user(size, &user_msg[0])) {
+		printk(KERN_WARNING "unable to get size!\n");
+		return -EFAULT;
+	}
+	size = size >> 16;
+
+	if (size > sb->inbound_frame_size) {
+		pr_debug("size of message > inbound_frame_size");
+		return -EFAULT;
+	}
+
+	user_reply = &user_msg[size];
+
+	size <<= 2;		// Convert to bytes
+
+	/* Copy in the user's I2O command */
+	if (copy_from_user(msg, user_msg, size)) {
+		printk(KERN_WARNING "unable to copy user message\n");
+		return -EFAULT;
+	}
+	i2o_dump_message(msg);
+
+	if (get_user(reply_size, &user_reply[0]) < 0)
+		return -EFAULT;
+
+	reply_size >>= 16;
+	reply_size <<= 2;
+
+	reply = kmalloc(reply_size, GFP_KERNEL);
+	if (!reply) {
+		printk(KERN_WARNING "%s: Could not allocate reply buffer\n",
+		       c->name);
+		return -ENOMEM;
+	}
+	memset(reply, 0, reply_size);
+
+	sg_offset = (msg->u.head[0] >> 4) & 0x0f;
+
+	writel(i2o_config_driver.context, &msg->u.s.icntxt);
+	writel(i2o_cntxt_list_add(c, reply), &msg->u.s.tcntxt);
+
+	memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE);
+	if (sg_offset) {
+		struct sg_simple_element *sg;
+
+		if (sg_offset * 4 >= size) {
+			rcode = -EFAULT;
+			goto cleanup;
+		}
+		// TODO 64bit fix
+		sg = (struct sg_simple_element *)((&msg->u.head[0]) +
+						  sg_offset);
+		sg_count =
+		    (size - sg_offset * 4) / sizeof(struct sg_simple_element);
+		if (sg_count > SG_TABLESIZE) {
+			printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n",
+			       c->name, sg_count);
+			kfree(reply);
+			return -EINVAL;
+		}
+
+		for (i = 0; i < sg_count; i++) {
+			int sg_size;
+			struct i2o_dma *p;
+
+			if (!(sg[i].flag_count & 0x10000000
+			      /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT */ )) {
+				printk(KERN_DEBUG
+				       "%s:Bad SG element %d - not simple (%x)\n",
+				       c->name, i, sg[i].flag_count);
+				rcode = -EINVAL;
+				goto cleanup;
+			}
+			sg_size = sg[i].flag_count & 0xffffff;
+			p = &(sg_list[i]);
+			/* Allocate memory for the transfer */
+			if (i2o_dma_alloc
+			    (&c->pdev->dev, p, sg_size,
+			     PCI_DMA_BIDIRECTIONAL)) {
+				printk(KERN_DEBUG
+				       "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
+				       c->name, sg_size, i, sg_count);
+				rcode = -ENOMEM;
+				goto cleanup;
+			}
+			/* Copy in the user's SG buffer if necessary */
+			if (sg[i].
+			    flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) {
+				// TODO 64bit fix
+				if (copy_from_user
+				    (p->virt, (void __user *)(unsigned long)sg[i].addr_bus,
+				     sg_size)) {
+					printk(KERN_DEBUG
+					       "%s: Could not copy SG buf %d FROM user\n",
+					       c->name, i);
+					rcode = -EFAULT;
+					goto cleanup;
+				}
+			}
+			//TODO 64bit fix
+			sg[i].addr_bus = (u32) p->phys;
+		}
+	}
+
+	rcode = i2o_msg_post_wait(c, m, 60);
+	if (rcode)
+		goto cleanup;
+
+	if (sg_offset) {
+		u32 msg[128];
+		/* Copy back the Scatter Gather buffers back to user space */
+		u32 j;
+		// TODO 64bit fix
+		struct sg_simple_element *sg;
+		int sg_size;
+		printk(KERN_INFO "sg_offset\n");
+
+		// re-acquire the original message to handle correctly the sg copy operation
+		memset(&msg, 0, MSG_FRAME_SIZE * 4);
+		// get user msg size in u32s
+		if (get_user(size, &user_msg[0])) {
+			rcode = -EFAULT;
+			goto cleanup;
+		}
+		size = size >> 16;
+		size *= 4;
+		/* Copy in the user's I2O command */
+		if (copy_from_user(msg, user_msg, size)) {
+			rcode = -EFAULT;
+			goto cleanup;
+		}
+		sg_count =
+		    (size - sg_offset * 4) / sizeof(struct sg_simple_element);
+
+		// TODO 64bit fix
+		sg = (struct sg_simple_element *)(msg + sg_offset);
+		for (j = 0; j < sg_count; j++) {
+			/* Copy out the SG list to user's buffer if necessary */
+			if (!
+			    (sg[j].
+			     flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR */ )) {
+				sg_size = sg[j].flag_count & 0xffffff;
+				// TODO 64bit fix
+				if (copy_to_user
+				    ((void __user *)(u64) sg[j].addr_bus,
+				     sg_list[j].virt, sg_size)) {
+					printk(KERN_WARNING
+					       "%s: Could not copy %p TO user %x\n",
+					       c->name, sg_list[j].virt,
+					       sg[j].addr_bus);
+					rcode = -EFAULT;
+					goto cleanup;
+				}
+			}
+		}
+	}
+
+	/* Copy back the reply to user space */
+	if (reply_size) {
+		// we wrote our own values for context - now restore the user supplied ones
+		printk(KERN_INFO "reply_size\n");
+		if (copy_from_user(reply + 2, user_msg + 2, sizeof(u32) * 2)) {
+			printk(KERN_WARNING
+			       "%s: Could not copy message context FROM user\n",
+			       c->name);
+			rcode = -EFAULT;
+		}
+		if (copy_to_user(user_reply, reply, reply_size)) {
+			printk(KERN_WARNING
+			       "%s: Could not copy reply TO user\n", c->name);
+			rcode = -EFAULT;
+		}
+	}
+
+      cleanup:
+	kfree(reply);
+	printk(KERN_INFO "rcode: %d\n", rcode);
+	return rcode;
+}
+
+#else
+
+static int i2o_cfg_passthru(unsigned long arg)
+{
+	struct i2o_cmd_passthru __user *cmd =
+	    (struct i2o_cmd_passthru __user *)arg;
 	struct i2o_controller *c;
-	u32 msg[MSG_FRAME_SIZE];
 	u32 __user *user_msg;
 	u32 *reply = NULL;
 	u32 __user *user_reply = NULL;
@@ -858,64 +861,88 @@ static int ioctl_passthru(unsigned long arg)
 	int sg_index = 0;
 	u32 i = 0;
 	void *p = NULL;
+	i2o_status_block *sb;
+	struct i2o_message *msg;
+	u32 m;
 	unsigned int iop;
 
 	if (get_user(iop, &cmd->iop) || get_user(user_msg, &cmd->msg))
 		return -EFAULT;
 
-	c = i2o_find_controller(iop);
-	if (!c)
-                return -ENXIO;
+	c = i2o_find_iop(iop);
+	if (!c) {
+		pr_debug("controller %d not found\n", iop);
+		return -ENXIO;
+	}
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+
+	sb = c->status_block.virt;
 
-	memset(&msg, 0, MSG_FRAME_SIZE*4);
-	if(get_user(size, &user_msg[0]))
+	if (get_user(size, &user_msg[0]))
 		return -EFAULT;
-	size = size>>16;
+	size = size >> 16;
 
-	user_reply = &user_msg[size];
-	if(size > MSG_FRAME_SIZE)
+	if (size > sb->inbound_frame_size) {
+		pr_debug("size of message > inbound_frame_size");
 		return -EFAULT;
-	size *= 4; // Convert to bytes
+	}
+
+	user_reply = &user_msg[size];
+
+	size <<= 2;		// Convert to bytes
 
 	/* Copy in the user's I2O command */
-	if(copy_from_user(msg, user_msg, size))
+	if (copy_from_user(msg, user_msg, size))
 		return -EFAULT;
-	if(get_user(reply_size, &user_reply[0]) < 0)
+
+	if (get_user(reply_size, &user_reply[0]) < 0)
 		return -EFAULT;
 
-	reply_size = reply_size>>16;
-	reply = kmalloc(REPLY_FRAME_SIZE*4, GFP_KERNEL);
-	if(!reply) {
-		printk(KERN_WARNING"%s: Could not allocate reply buffer\n",c->name);
+	reply_size >>= 16;
+	reply_size <<= 2;
+
+	reply = kmalloc(reply_size, GFP_KERNEL);
+	if (!reply) {
+		printk(KERN_WARNING "%s: Could not allocate reply buffer\n",
+		       c->name);
 		return -ENOMEM;
 	}
-	memset(reply, 0, REPLY_FRAME_SIZE*4);
-	sg_offset = (msg[0]>>4)&0x0f;
-	msg[2] = (u32)i2o_cfg_context;
-	msg[3] = (u32)reply;
+	memset(reply, 0, reply_size);
+
+	sg_offset = (msg->u.head[0] >> 4) & 0x0f;
 
-	memset(sg_list,0, sizeof(sg_list[0])*SG_TABLESIZE);
-	if(sg_offset) {
+	writel(i2o_config_driver.context, &msg->u.s.icntxt);
+	writel(i2o_cntxt_list_add(c, reply), &msg->u.s.tcntxt);
+
+	memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE);
+	if (sg_offset) {
 		struct sg_simple_element *sg;
 
-		if(sg_offset * 4 >= size) {
+		if (sg_offset * 4 >= size) {
 			rcode = -EFAULT;
 			goto cleanup;
 		}
 		// TODO 64bit fix
-		sg = (struct sg_simple_element*) (msg+sg_offset);
-		sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element);
+		sg = (struct sg_simple_element *)((&msg->u.head[0]) +
+						  sg_offset);
+		sg_count =
+		    (size - sg_offset * 4) / sizeof(struct sg_simple_element);
 		if (sg_count > SG_TABLESIZE) {
-			printk(KERN_DEBUG"%s:IOCTL SG List too large (%u)\n", c->name,sg_count);
-			kfree (reply);
+			printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n",
+			       c->name, sg_count);
+			kfree(reply);
 			return -EINVAL;
 		}
 
-		for(i = 0; i < sg_count; i++) {
+		for (i = 0; i < sg_count; i++) {
 			int sg_size;
 
-			if (!(sg[i].flag_count & 0x10000000 /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT*/)) {
-				printk(KERN_DEBUG"%s:Bad SG element %d - not simple (%x)\n",c->name,i,  sg[i].flag_count);
+			if (!(sg[i].flag_count & 0x10000000
+			      /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT */ )) {
+				printk(KERN_DEBUG
+				       "%s:Bad SG element %d - not simple (%x)\n",
+				       c->name, i, sg[i].flag_count);
 				rcode = -EINVAL;
 				goto cleanup;
 			}
@@ -923,61 +950,78 @@ static int ioctl_passthru(unsigned long arg)
 			/* Allocate memory for the transfer */
 			p = kmalloc(sg_size, GFP_KERNEL);
 			if (!p) {
-				printk(KERN_DEBUG"%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", c->name,sg_size,i,sg_count);
+				printk(KERN_DEBUG
+				       "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
+				       c->name, sg_size, i, sg_count);
 				rcode = -ENOMEM;
 				goto cleanup;
 			}
-			sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame.
+			sg_list[sg_index++] = p;	// sglist indexed with input frame, not our internal frame.
 			/* Copy in the user's SG buffer if necessary */
-			if(sg[i].flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR*/) {
+			if (sg[i].
+			    flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) {
 				// TODO 64bit fix
-			        if (copy_from_user(p,(void __user *)sg[i].addr_bus, sg_size)) {
-					printk(KERN_DEBUG"%s: Could not copy SG buf %d FROM user\n",c->name,i);
+				if (copy_from_user
+				    (p, (void __user *)sg[i].addr_bus,
+				     sg_size)) {
+					printk(KERN_DEBUG
+					       "%s: Could not copy SG buf %d FROM user\n",
+					       c->name, i);
 					rcode = -EFAULT;
 					goto cleanup;
 				}
 			}
 			//TODO 64bit fix
-			sg[i].addr_bus = (u32)virt_to_bus(p);
+			sg[i].addr_bus = virt_to_bus(p);
 		}
 	}
 
-	rcode = i2o_post_wait(c, msg, size, 60);
-	if(rcode)
+	rcode = i2o_msg_post_wait(c, m, 60);
+	if (rcode)
 		goto cleanup;
 
-	if(sg_offset) {
+	if (sg_offset) {
+		u32 msg[128];
 		/* Copy back the Scatter Gather buffers back to user space */
 		u32 j;
 		// TODO 64bit fix
-		struct sg_simple_element* sg;
+		struct sg_simple_element *sg;
 		int sg_size;
+		printk(KERN_INFO "sg_offset\n");
 
 		// re-acquire the original message to handle correctly the sg copy operation
-		memset(&msg, 0, MSG_FRAME_SIZE*4);
+		memset(&msg, 0, MSG_FRAME_SIZE * 4);
 		// get user msg size in u32s
 		if (get_user(size, &user_msg[0])) {
 			rcode = -EFAULT;
 			goto cleanup;
 		}
-		size = size>>16;
+		size = size >> 16;
 		size *= 4;
 		/* Copy in the user's I2O command */
-		if (copy_from_user (msg, user_msg, size)) {
+		if (copy_from_user(msg, user_msg, size)) {
 			rcode = -EFAULT;
 			goto cleanup;
 		}
-		sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element);
+		sg_count =
+		    (size - sg_offset * 4) / sizeof(struct sg_simple_element);
 
-		 // TODO 64bit fix
-		sg = (struct sg_simple_element*)(msg + sg_offset);
+		// TODO 64bit fix
+		sg = (struct sg_simple_element *)(msg + sg_offset);
 		for (j = 0; j < sg_count; j++) {
 			/* Copy out the SG list to user's buffer if necessary */
-			if (!(sg[j].flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR*/)) {
+			if (!
+			    (sg[j].
+			     flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR */ )) {
 				sg_size = sg[j].flag_count & 0xffffff;
 				// TODO 64bit fix
-				if (copy_to_user((void __user *)sg[j].addr_bus,sg_list[j], sg_size)) {
-					printk(KERN_WARNING"%s: Could not copy %p TO user %x\n",c->name, sg_list[j], sg[j].addr_bus);
+				if (copy_to_user
+				    ((void __user *)sg[j].addr_bus, sg_list[j],
+				     sg_size)) {
+					printk(KERN_WARNING
+					       "%s: Could not copy %p TO user %x\n",
+					       c->name, sg_list[j],
+					       sg[j].addr_bus);
 					rcode = -EFAULT;
 					goto cleanup;
 				}
@@ -986,37 +1030,109 @@ static int ioctl_passthru(unsigned long arg)
 	}
 
 	/* Copy back the reply to user space */
-        if (reply_size) {
+	if (reply_size) {
 		// we wrote our own values for context - now restore the user supplied ones
-		if(copy_from_user(reply+2, user_msg+2, sizeof(u32)*2)) {
-			printk(KERN_WARNING"%s: Could not copy message context FROM user\n",c->name);
+		printk(KERN_INFO "reply_size\n");
+		if (copy_from_user(reply + 2, user_msg + 2, sizeof(u32) * 2)) {
+			printk(KERN_WARNING
+			       "%s: Could not copy message context FROM user\n",
+			       c->name);
 			rcode = -EFAULT;
 		}
-		if(copy_to_user(user_reply, reply, reply_size)) {
-			printk(KERN_WARNING"%s: Could not copy reply TO user\n",c->name);
+		if (copy_to_user(user_reply, reply, reply_size)) {
+			printk(KERN_WARNING
+			       "%s: Could not copy reply TO user\n", c->name);
 			rcode = -EFAULT;
 		}
 	}
 
-cleanup:
+      cleanup:
 	kfree(reply);
-	i2o_unlock_controller(c);
 	return rcode;
 }
+#endif
+
+/*
+ * IOCTL Handler
+ */
+static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd,
+			 unsigned long arg)
+{
+	int ret;
+
+	switch (cmd) {
+	case I2OGETIOPS:
+		ret = i2o_cfg_getiops(arg);
+		break;
+
+	case I2OHRTGET:
+		ret = i2o_cfg_gethrt(arg);
+		break;
+
+	case I2OLCTGET:
+		ret = i2o_cfg_getlct(arg);
+		break;
+
+	case I2OPARMSET:
+		ret = i2o_cfg_parms(arg, I2OPARMSET);
+		break;
+
+	case I2OPARMGET:
+		ret = i2o_cfg_parms(arg, I2OPARMGET);
+		break;
+
+	case I2OSWDL:
+		ret = i2o_cfg_swdl(arg);
+		break;
+
+	case I2OSWUL:
+		ret = i2o_cfg_swul(arg);
+		break;
+
+	case I2OSWDEL:
+		ret = i2o_cfg_swdel(arg);
+		break;
+
+	case I2OVALIDATE:
+		ret = i2o_cfg_validate(arg);
+		break;
+
+	case I2OEVTREG:
+		ret = i2o_cfg_evt_reg(arg, fp);
+		break;
+
+	case I2OEVTGET:
+		ret = i2o_cfg_evt_get(arg, fp);
+		break;
+
+#ifndef CONFIG_COMPAT
+	case I2OPASSTHRU:
+		ret = i2o_cfg_passthru(arg);
+		break;
+#endif
+
+	default:
+		pr_debug("i2o_config: unknown ioctl called!\n");
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
 
 static int cfg_open(struct inode *inode, struct file *file)
 {
-	struct i2o_cfg_info *tmp = 
-		(struct i2o_cfg_info *)kmalloc(sizeof(struct i2o_cfg_info), GFP_KERNEL);
+	struct i2o_cfg_info *tmp =
+	    (struct i2o_cfg_info *)kmalloc(sizeof(struct i2o_cfg_info),
+					   GFP_KERNEL);
 	unsigned long flags;
 
-	if(!tmp)
+	if (!tmp)
 		return -ENOMEM;
 
-	file->private_data = (void*)(i2o_cfg_info_id++);
+	file->private_data = (void *)(i2o_cfg_info_id++);
 	tmp->fp = file;
 	tmp->fasync = NULL;
-	tmp->q_id = (u32)file->private_data;
+	tmp->q_id = (ulong) file->private_data;
 	tmp->q_len = 0;
 	tmp->q_in = 0;
 	tmp->q_out = 0;
@@ -1026,13 +1142,28 @@ static int cfg_open(struct inode *inode, struct file *file)
 	spin_lock_irqsave(&i2o_config_lock, flags);
 	open_files = tmp;
 	spin_unlock_irqrestore(&i2o_config_lock, flags);
-	
+
 	return 0;
 }
 
+static int cfg_fasync(int fd, struct file *fp, int on)
+{
+	ulong id = (ulong) fp->private_data;
+	struct i2o_cfg_info *p;
+
+	for (p = open_files; p; p = p->next)
+		if (p->q_id == id)
+			break;
+
+	if (!p)
+		return -EBADF;
+
+	return fasync_helper(fd, fp, on, &p->fasync);
+}
+
 static int cfg_release(struct inode *inode, struct file *file)
 {
-	u32 id = (u32)file->private_data;
+	ulong id = (ulong) file->private_data;
 	struct i2o_cfg_info *p1, *p2;
 	unsigned long flags;
 
@@ -1040,14 +1171,12 @@ static int cfg_release(struct inode *inode, struct file *file)
 	p1 = p2 = NULL;
 
 	spin_lock_irqsave(&i2o_config_lock, flags);
-	for(p1 = open_files; p1; )
-	{
-		if(p1->q_id == id)
-		{
+	for (p1 = open_files; p1;) {
+		if (p1->q_id == id) {
 
-			if(p1->fasync)
+			if (p1->fasync)
 				cfg_fasync(-1, file, 0);
-			if(p2)
+			if (p2)
 				p2->next = p1->next;
 			else
 				open_files = p1->next;
@@ -1064,83 +1193,55 @@ static int cfg_release(struct inode *inode, struct file *file)
 	return 0;
 }
 
-static int cfg_fasync(int fd, struct file *fp, int on)
-{
-	u32 id = (u32)fp->private_data;
-	struct i2o_cfg_info *p;
-
-	for(p = open_files; p; p = p->next)
-		if(p->q_id == id)
-			break;
-
-	if(!p)
-		return -EBADF;
-
-	return fasync_helper(fd, fp, on, &p->fasync);
-}
-
-static struct file_operations config_fops =
-{
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.read		= cfg_read,
-	.write		= cfg_write,
-	.ioctl		= cfg_ioctl,
-	.open		= cfg_open,
-	.release	= cfg_release,
-	.fasync		= cfg_fasync,
+static struct file_operations config_fops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.ioctl = i2o_cfg_ioctl,
+	.open = cfg_open,
+	.release = cfg_release,
+	.fasync = cfg_fasync,
 };
 
 static struct miscdevice i2o_miscdev = {
 	I2O_MINOR,
 	"i2octl",
 	&config_fops
-};	
+};
 
 static int __init i2o_config_init(void)
 {
 	printk(KERN_INFO "I2O configuration manager v 0.04.\n");
 	printk(KERN_INFO "  (C) Copyright 1999 Red Hat Software\n");
-	
-	if((page_buf = kmalloc(4096, GFP_KERNEL))==NULL)
-	{
-		printk(KERN_ERR "i2o_config: no memory for page buffer.\n");
-		return -ENOBUFS;
-	}
-	if(misc_register(&i2o_miscdev) < 0)
-	{
+
+	if (misc_register(&i2o_miscdev) < 0) {
 		printk(KERN_ERR "i2o_config: can't register device.\n");
-		kfree(page_buf);
 		return -EBUSY;
 	}
 	/*
-	 *	Install our handler
+	 *      Install our handler
 	 */
-	if(i2o_install_handler(&cfg_handler)<0)
-	{
-		kfree(page_buf);
+	if (i2o_driver_register(&i2o_config_driver)) {
 		printk(KERN_ERR "i2o_config: handler register failed.\n");
 		misc_deregister(&i2o_miscdev);
 		return -EBUSY;
 	}
-	/*
-	 *	The low 16bits of the transaction context must match this
-	 *	for everything we post. Otherwise someone else gets our mail
-	 */
-	i2o_cfg_context = cfg_handler.context;
+#ifdef CONFIG_COMPAT
+	register_ioctl32_conversion(I2OPASSTHRU32, i2o_cfg_passthru32);
+	register_ioctl32_conversion(I2OGETIOPS, (void *)sys_ioctl);
+#endif
 	return 0;
 }
 
 static void i2o_config_exit(void)
 {
+#ifdef CONFIG_COMPAT
+	unregister_ioctl32_conversion(I2OPASSTHRU32);
+	unregister_ioctl32_conversion(I2OGETIOPS);
+#endif
 	misc_deregister(&i2o_miscdev);
-	
-	if(page_buf)
-		kfree(page_buf);
-	if(i2o_cfg_context != -1)
-		i2o_remove_handler(&cfg_handler);
+	i2o_driver_unregister(&i2o_config_driver);
 }
- 
+
 MODULE_AUTHOR("Red Hat Software");
 MODULE_DESCRIPTION("I2O Configuration");
 MODULE_LICENSE("GPL");
diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c
index db85e21b9..a535c7a1f 100644
--- a/drivers/message/i2o/i2o_proc.c
+++ b/drivers/message/i2o/i2o_proc.c
@@ -1,39 +1,33 @@
 /*
- *   procfs handler for Linux I2O subsystem
+ *	procfs handler for Linux I2O subsystem
  *
- *   (c) Copyright 1999 Deepak Saxena
- *   
- *   Originally written by Deepak Saxena(deepak@plexity.net)
+ *	(c) Copyright 1999	Deepak Saxena
  *
- *   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.
+ *	Originally written by Deepak Saxena(deepak@plexity.net)
  *
- *   This is an initial test release. The code is based on the design
- *   of the ide procfs system (drivers/block/ide-proc.c). Some code
- *   taken from i2o-core module by Alan Cox.
+ *	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.
  *
- *   DISCLAIMER: This code is still under development/test and may cause
- *   your system to behave unpredictably.  Use at your own discretion.
+ *	This is an initial test release. The code is based on the design of the
+ *	ide procfs system (drivers/block/ide-proc.c). Some code taken from
+ *	i2o-core module by Alan Cox.
  *
- *   LAN entries by Juha Sievänen (Juha.Sievanen@cs.Helsinki.FI),
- *		    Auvo Häkkinen (Auvo.Hakkinen@cs.Helsinki.FI)
- *   University of Helsinki, Department of Computer Science
- */
-
-/*
- * set tabstop=3
- */
-
-/*
- * TODO List
+ *	DISCLAIMER: This code is still under development/test and may cause
+ *	your system to behave unpredictably.  Use at your own discretion.
  *
- * - Add support for any version 2.0 spec changes once 2.0 IRTOS is
- *   is available to test with
- * - Clean up code to use official structure definitions 
+ *
+ *	Fixes/additions:
+ *		Juha Sievänen (Juha.Sievanen@cs.Helsinki.FI),
+ *		Auvo Häkkinen (Auvo.Hakkinen@cs.Helsinki.FI)
+ *		University of Helsinki, Department of Computer Science
+ *			LAN entries
+ *		Markus Lidel <Markus.Lidel@shadowconnect.com>
+ *			Changes for new I2O API
  */
 
+#define I2O_MAX_MODULES 4
 // FIXME!
 #define FMT_U64_HEX "0x%08x%08x"
 #define U64_VAL(pu64) *((u32*)(pu64)+1), *((u32*)(pu64))
@@ -54,188 +48,198 @@
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 
-#include "i2o_lan.h"
-
-/*
- * Structure used to define /proc entries
- */
-typedef struct _i2o_proc_entry_t
-{
-	char *name;			/* entry name */
-	mode_t mode;			/* mode */
-	read_proc_t *read_proc;		/* read func */
-	write_proc_t *write_proc;	/* write func */
-	struct file_operations *fops_proc;	/* file operations func */
+/* Structure used to define /proc entries */
+typedef struct _i2o_proc_entry_t {
+	char *name;		/* entry name */
+	mode_t mode;		/* mode */
+	struct file_operations *fops;	/* open function */
 } i2o_proc_entry;
 
-// #define DRIVERDEBUG
-
-static int i2o_seq_show_lct(struct seq_file *, void *);
-static int i2o_seq_show_hrt(struct seq_file *, void *);
-static int i2o_seq_show_status(struct seq_file *, void *);
-
-static int i2o_proc_read_hw(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_ddm_table(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_driver_store(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_drivers_stored(char *, char **, off_t, int, int *, void *);
-
-static int i2o_proc_read_groups(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_phys_device(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_claimed(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_users(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_priv_msgs(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_authorized_users(char *, char **, off_t, int, int *, void *);
-
-static int i2o_proc_read_dev_name(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_dev_identity(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_ddm_identity(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_uinfo(char *, char **, off_t, int, int *, void *);
-static int i2o_proc_read_sgl_limits(char *, char **, off_t, int, int *, void *);
-
-static int i2o_proc_read_sensors(char *, char **, off_t, int, int *, void *);
-
-static int print_serial_number(char *, int, u8 *, int);
-
-static int i2o_proc_create_entries(void *, i2o_proc_entry *,
-				   struct proc_dir_entry *);
-static void i2o_proc_remove_entries(i2o_proc_entry *, struct proc_dir_entry *);
-static int i2o_proc_add_controller(struct i2o_controller *, 
-				   struct proc_dir_entry * );
-static void i2o_proc_remove_controller(struct i2o_controller *, 
-				       struct proc_dir_entry * );
-static void i2o_proc_add_device(struct i2o_device *, struct proc_dir_entry *);
-static void i2o_proc_remove_device(struct i2o_device *);
-static int create_i2o_procfs(void);
-static int destroy_i2o_procfs(void);
-static void i2o_proc_new_dev(struct i2o_controller *, struct i2o_device *);
-static void i2o_proc_dev_del(struct i2o_controller *, struct i2o_device *);
-
-static int i2o_proc_read_lan_dev_info(char *, char **, off_t, int, int *,
-				      void *);
-static int i2o_proc_read_lan_mac_addr(char *, char **, off_t, int, int *,
-				      void *);
-static int i2o_proc_read_lan_mcast_addr(char *, char **, off_t, int, int *,
-					void *);
-static int i2o_proc_read_lan_batch_control(char *, char **, off_t, int, int *,
-					   void *);
-static int i2o_proc_read_lan_operation(char *, char **, off_t, int, int *,
-				       void *);
-static int i2o_proc_read_lan_media_operation(char *, char **, off_t, int,
-					     int *, void *);
-static int i2o_proc_read_lan_alt_addr(char *, char **, off_t, int, int *,
-				      void *);
-static int i2o_proc_read_lan_tx_info(char *, char **, off_t, int, int *,
-				     void *);
-static int i2o_proc_read_lan_rx_info(char *, char **, off_t, int, int *,
-				     void *);
-static int i2o_proc_read_lan_hist_stats(char *, char **, off_t, int, int *,
-					void *);
-static int i2o_proc_read_lan_eth_stats(char *, char **, off_t, int,
-				       int *, void *);
-static int i2o_proc_read_lan_tr_stats(char *, char **, off_t, int, int *,
-				      void *);
-static int i2o_proc_read_lan_fddi_stats(char *, char **, off_t, int, int *,
-					void *);
-
+/* global I2O /proc/i2o entry */
 static struct proc_dir_entry *i2o_proc_dir_root;
 
-/*
- * I2O OSM descriptor
- */
-static struct i2o_handler i2o_proc_handler =
-{
-	NULL,
-	i2o_proc_new_dev,
-	i2o_proc_dev_del,
-	NULL,
-	"I2O procfs Layer",
-	0,
-	0xffffffff	// All classes
+/* proc OSM driver struct */
+static struct i2o_driver i2o_proc_driver = {
+	.name = "proc-osm",
 };
 
-static int i2o_seq_open_hrt(struct inode *inode, struct file *file)
+static int print_serial_number(struct seq_file *seq, u8 * serialno, int max_len)
 {
-	return single_open(file, i2o_seq_show_hrt, PDE(inode)->data);
-};
+	int i;
 
-struct file_operations i2o_seq_fops_hrt = {
-	.open	= i2o_seq_open_hrt,
-	.read	= seq_read,
-	.llseek	= seq_lseek,
-	.release = single_release
-};
+	/* 19990419 -sralston
+	 *      The I2O v1.5 (and v2.0 so far) "official specification"
+	 *      got serial numbers WRONG!
+	 *      Apparently, and despite what Section 3.4.4 says and
+	 *      Figure 3-35 shows (pg 3-39 in the pdf doc),
+	 *      the convention / consensus seems to be:
+	 *        + First byte is SNFormat
+	 *        + Second byte is SNLen (but only if SNFormat==7 (?))
+	 *        + (v2.0) SCSI+BS may use IEEE Registered (64 or 128 bit) format
+	 */
+	switch (serialno[0]) {
+	case I2O_SNFORMAT_BINARY:	/* Binary */
+		seq_printf(seq, "0x");
+		for (i = 0; i < serialno[1]; i++) {
+			seq_printf(seq, "%02X", serialno[2 + i]);
+		}
+		break;
 
-static int i2o_seq_open_lct(struct inode *inode, struct file *file)
-{
-	return single_open(file, i2o_seq_show_lct, PDE(inode)->data);
-};
+	case I2O_SNFORMAT_ASCII:	/* ASCII */
+		if (serialno[1] < ' ') {	/* printable or SNLen? */
+			/* sanity */
+			max_len =
+			    (max_len < serialno[1]) ? max_len : serialno[1];
+			serialno[1 + max_len] = '\0';
 
-struct file_operations i2o_seq_fops_lct = {
-	.open	= i2o_seq_open_lct,
-	.read	= seq_read,
-	.llseek	= seq_lseek,
-	.release = single_release
-};
+			/* just print it */
+			seq_printf(seq, "%s", &serialno[2]);
+		} else {
+			/* print chars for specified length */
+			for (i = 0; i < serialno[1]; i++) {
+				seq_printf(seq, "%c", serialno[2 + i]);
+			}
+		}
+		break;
 
-static int i2o_seq_open_status(struct inode *inode, struct file *file)
-{
-	return single_open(file, i2o_seq_show_status, PDE(inode)->data);
-};
+	case I2O_SNFORMAT_UNICODE:	/* UNICODE */
+		seq_printf(seq, "UNICODE Format.  Can't Display\n");
+		break;
 
-struct file_operations i2o_seq_fops_status = {
-	.open	= i2o_seq_open_status,
-	.read	= seq_read,
-	.llseek	= seq_lseek,
-	.release = single_release
-};
+	case I2O_SNFORMAT_LAN48_MAC:	/* LAN-48 MAC Address */
+		seq_printf(seq,
+			   "LAN-48 MAC address @ %02X:%02X:%02X:%02X:%02X:%02X",
+			   serialno[2], serialno[3],
+			   serialno[4], serialno[5], serialno[6], serialno[7]);
+		break;
 
-/*
- * IOP specific entries...write field just in case someone 
- * ever wants one.
- */
-static i2o_proc_entry generic_iop_entries[] = 
-{
-	{"hrt", S_IFREG|S_IRUGO, NULL, NULL, &i2o_seq_fops_hrt},
-	{"lct", S_IFREG|S_IRUGO, NULL, NULL, &i2o_seq_fops_lct},
-	{"status", S_IFREG|S_IRUGO, NULL, NULL, &i2o_seq_fops_status},
-	{"hw", S_IFREG|S_IRUGO, i2o_proc_read_hw, NULL, NULL},
-	{"ddm_table", S_IFREG|S_IRUGO, i2o_proc_read_ddm_table, NULL, NULL},
-	{"driver_store", S_IFREG|S_IRUGO, i2o_proc_read_driver_store, NULL, NULL},
-	{"drivers_stored", S_IFREG|S_IRUGO, i2o_proc_read_drivers_stored, NULL, NULL},
-	{NULL, 0, NULL, NULL, NULL}
-};
+	case I2O_SNFORMAT_WAN:	/* WAN MAC Address */
+		/* FIXME: Figure out what a WAN access address looks like?? */
+		seq_printf(seq, "WAN Access Address");
+		break;
 
-/*
- * Device specific entries
- */
-static i2o_proc_entry generic_dev_entries[] = 
-{
-	{"groups", S_IFREG|S_IRUGO, i2o_proc_read_groups, NULL, NULL},
-	{"phys_dev", S_IFREG|S_IRUGO, i2o_proc_read_phys_device, NULL, NULL},
-	{"claimed", S_IFREG|S_IRUGO, i2o_proc_read_claimed, NULL, NULL},
-	{"users", S_IFREG|S_IRUGO, i2o_proc_read_users, NULL, NULL},
-	{"priv_msgs", S_IFREG|S_IRUGO, i2o_proc_read_priv_msgs, NULL, NULL},
-	{"authorized_users", S_IFREG|S_IRUGO, i2o_proc_read_authorized_users, NULL, NULL},
-	{"dev_identity", S_IFREG|S_IRUGO, i2o_proc_read_dev_identity, NULL, NULL},
-	{"ddm_identity", S_IFREG|S_IRUGO, i2o_proc_read_ddm_identity, NULL, NULL},
-	{"user_info", S_IFREG|S_IRUGO, i2o_proc_read_uinfo, NULL, NULL},
-	{"sgl_limits", S_IFREG|S_IRUGO, i2o_proc_read_sgl_limits, NULL, NULL},
-	{"sensors", S_IFREG|S_IRUGO, i2o_proc_read_sensors, NULL, NULL},
-	{NULL, 0, NULL, NULL, NULL}
-};
+/* plus new in v2.0 */
+	case I2O_SNFORMAT_LAN64_MAC:	/* LAN-64 MAC Address */
+		/* FIXME: Figure out what a LAN-64 address really looks like?? */
+		seq_printf(seq,
+			   "LAN-64 MAC address @ [?:%02X:%02X:?] %02X:%02X:%02X:%02X:%02X:%02X",
+			   serialno[8], serialno[9],
+			   serialno[2], serialno[3],
+			   serialno[4], serialno[5], serialno[6], serialno[7]);
+		break;
+
+	case I2O_SNFORMAT_DDM:	/* I2O DDM */
+		seq_printf(seq,
+			   "DDM: Tid=%03Xh, Rsvd=%04Xh, OrgId=%04Xh",
+			   *(u16 *) & serialno[2],
+			   *(u16 *) & serialno[4], *(u16 *) & serialno[6]);
+		break;
+
+	case I2O_SNFORMAT_IEEE_REG64:	/* IEEE Registered (64-bit) */
+	case I2O_SNFORMAT_IEEE_REG128:	/* IEEE Registered (128-bit) */
+		/* FIXME: Figure if this is even close?? */
+		seq_printf(seq,
+			   "IEEE NodeName(hi,lo)=(%08Xh:%08Xh), PortName(hi,lo)=(%08Xh:%08Xh)\n",
+			   *(u32 *) & serialno[2],
+			   *(u32 *) & serialno[6],
+			   *(u32 *) & serialno[10], *(u32 *) & serialno[14]);
+		break;
+
+	case I2O_SNFORMAT_UNKNOWN:	/* Unknown 0    */
+	case I2O_SNFORMAT_UNKNOWN2:	/* Unknown 0xff */
+	default:
+		seq_printf(seq, "Unknown data format (0x%02x)", serialno[0]);
+		break;
+	}
 
-/*
- *  Storage unit specific entries (SCSI Periph, BS) with device names
+	return 0;
+}
+
+/**
+ *	i2o_get_class_name - 	do i2o class name lookup
+ *	@class: class number
+ *
+ *	Return a descriptive string for an i2o class
  */
-static i2o_proc_entry rbs_dev_entries[] = 
+static const char *i2o_get_class_name(int class)
 {
-	{"dev_name", S_IFREG|S_IRUGO, i2o_proc_read_dev_name, NULL, NULL},
-	{NULL, 0, NULL, NULL}
-};
+	int idx = 16;
+	static char *i2o_class_name[] = {
+		"Executive",
+		"Device Driver Module",
+		"Block Device",
+		"Tape Device",
+		"LAN Interface",
+		"WAN Interface",
+		"Fibre Channel Port",
+		"Fibre Channel Device",
+		"SCSI Device",
+		"ATE Port",
+		"ATE Device",
+		"Floppy Controller",
+		"Floppy Device",
+		"Secondary Bus Port",
+		"Peer Transport Agent",
+		"Peer Transport",
+		"Unknown"
+	};
+
+	switch (class & 0xfff) {
+	case I2O_CLASS_EXECUTIVE:
+		idx = 0;
+		break;
+	case I2O_CLASS_DDM:
+		idx = 1;
+		break;
+	case I2O_CLASS_RANDOM_BLOCK_STORAGE:
+		idx = 2;
+		break;
+	case I2O_CLASS_SEQUENTIAL_STORAGE:
+		idx = 3;
+		break;
+	case I2O_CLASS_LAN:
+		idx = 4;
+		break;
+	case I2O_CLASS_WAN:
+		idx = 5;
+		break;
+	case I2O_CLASS_FIBRE_CHANNEL_PORT:
+		idx = 6;
+		break;
+	case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL:
+		idx = 7;
+		break;
+	case I2O_CLASS_SCSI_PERIPHERAL:
+		idx = 8;
+		break;
+	case I2O_CLASS_ATE_PORT:
+		idx = 9;
+		break;
+	case I2O_CLASS_ATE_PERIPHERAL:
+		idx = 10;
+		break;
+	case I2O_CLASS_FLOPPY_CONTROLLER:
+		idx = 11;
+		break;
+	case I2O_CLASS_FLOPPY_DEVICE:
+		idx = 12;
+		break;
+	case I2O_CLASS_BUS_ADAPTER_PORT:
+		idx = 13;
+		break;
+	case I2O_CLASS_PEER_TRANSPORT_AGENT:
+		idx = 14;
+		break;
+	case I2O_CLASS_PEER_TRANSPORT:
+		idx = 15;
+		break;
+	}
+
+	return i2o_class_name[idx];
+}
 
 #define SCSI_TABLE_SIZE	13
-static char *scsi_devices[] = 
-{
+static char *scsi_devices[] = {
 	"Direct-Access Read/Write",
 	"Sequential-Access Storage",
 	"Printer",
@@ -251,307 +255,267 @@ static char *scsi_devices[] =
 	"Array Controller Device"
 };
 
-/* private */
-
-/*
- * Generic LAN specific entries
- * 
- * Should groups with r/w entries have their own subdirectory?
- *
- */
-static i2o_proc_entry lan_entries[] = 
-{
-	{"lan_dev_info", S_IFREG|S_IRUGO, i2o_proc_read_lan_dev_info, NULL, NULL},
-	{"lan_mac_addr", S_IFREG|S_IRUGO, i2o_proc_read_lan_mac_addr, NULL, NULL},
-	{"lan_mcast_addr", S_IFREG|S_IRUGO|S_IWUSR,
-	 i2o_proc_read_lan_mcast_addr, NULL, NULL},
-	{"lan_batch_ctrl", S_IFREG|S_IRUGO|S_IWUSR,
-	 i2o_proc_read_lan_batch_control, NULL, NULL},
-	{"lan_operation", S_IFREG|S_IRUGO, i2o_proc_read_lan_operation, NULL, NULL},
-	{"lan_media_operation", S_IFREG|S_IRUGO,
-	 i2o_proc_read_lan_media_operation, NULL, NULL},
-	{"lan_alt_addr", S_IFREG|S_IRUGO, i2o_proc_read_lan_alt_addr, NULL, NULL},
-	{"lan_tx_info", S_IFREG|S_IRUGO, i2o_proc_read_lan_tx_info, NULL, NULL},
-	{"lan_rx_info", S_IFREG|S_IRUGO, i2o_proc_read_lan_rx_info, NULL, NULL},
-
-	{"lan_hist_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_hist_stats, NULL, NULL},
-	{NULL, 0, NULL, NULL, NULL}
-};
-
-/*
- * Port specific LAN entries
- * 
- */
-static i2o_proc_entry lan_eth_entries[] = 
-{
-	{"lan_eth_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_eth_stats, NULL, NULL},
-	{NULL, 0, NULL, NULL, NULL}
-};
-
-static i2o_proc_entry lan_tr_entries[] = 
-{
-	{"lan_tr_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_tr_stats, NULL, NULL},
-	{NULL, 0, NULL, NULL, NULL}
-};
-
-static i2o_proc_entry lan_fddi_entries[] = 
-{
-	{"lan_fddi_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_fddi_stats, NULL, NULL},
-	{NULL, 0, NULL, NULL, NULL}
-};
-
-
-static char *chtostr(u8 *chars, int n)
+static char *chtostr(u8 * chars, int n)
 {
 	char tmp[256];
 	tmp[0] = 0;
-        return strncat(tmp, (char *)chars, n);
+	return strncat(tmp, (char *)chars, n);
 }
 
-static int i2o_report_query_status(char *buf, int block_status, char *group)
+static int i2o_report_query_status(struct seq_file *seq, int block_status,
+				   char *group)
 {
-	switch (block_status)
-	{
+	switch (block_status) {
 	case -ETIMEDOUT:
-		return sprintf(buf, "Timeout reading group %s.\n",group);
+		return seq_printf(seq, "Timeout reading group %s.\n", group);
 	case -ENOMEM:
-		return sprintf(buf, "No free memory to read the table.\n");
+		return seq_printf(seq, "No free memory to read the table.\n");
 	case -I2O_PARAMS_STATUS_INVALID_GROUP_ID:
-		return sprintf(buf, "Group %s not supported.\n", group);
+		return seq_printf(seq, "Group %s not supported.\n", group);
 	default:
-		return sprintf(buf, "Error reading group %s. BlockStatus 0x%02X\n",
-			       group, -block_status);
+		return seq_printf(seq,
+				  "Error reading group %s. BlockStatus 0x%02X\n",
+				  group, -block_status);
 	}
 }
 
-static char* bus_strings[] = 
-{ 
-	"Local Bus", 
-	"ISA", 
-	"EISA", 
-	"MCA", 
+static char *bus_strings[] = {
+	"Local Bus",
+	"ISA",
+	"EISA",
+	"MCA",
 	"PCI",
-	"PCMCIA", 
-	"NUBUS", 
+	"PCMCIA",
+	"NUBUS",
 	"CARDBUS"
 };
 
-static spinlock_t i2o_proc_lock = SPIN_LOCK_UNLOCKED;
-
 int i2o_seq_show_hrt(struct seq_file *seq, void *v)
 {
 	struct i2o_controller *c = (struct i2o_controller *)seq->private;
-	i2o_hrt *hrt = (i2o_hrt *)c->hrt;
+	i2o_hrt *hrt = (i2o_hrt *) c->hrt.virt;
 	u32 bus;
 	int i;
 
-	if(hrt->hrt_version)
-	{
-		seq_printf(seq, "HRT table for controller is too new a version.\n");
+	if (hrt->hrt_version) {
+		seq_printf(seq,
+			   "HRT table for controller is too new a version.\n");
 		return 0;
 	}
 
 	seq_printf(seq, "HRT has %d entries of %d bytes each.\n",
-		       hrt->num_entries, hrt->entry_len << 2);
+		   hrt->num_entries, hrt->entry_len << 2);
 
-	for(i = 0; i < hrt->num_entries; i++)
-	{
+	for (i = 0; i < hrt->num_entries; i++) {
 		seq_printf(seq, "Entry %d:\n", i);
 		seq_printf(seq, "   Adapter ID: %0#10x\n",
-					hrt->hrt_entry[i].adapter_id);
+			   hrt->hrt_entry[i].adapter_id);
 		seq_printf(seq, "   Controlling tid: %0#6x\n",
-					hrt->hrt_entry[i].parent_tid);
+			   hrt->hrt_entry[i].parent_tid);
 
-		if(hrt->hrt_entry[i].bus_type != 0x80)
-		{
+		if (hrt->hrt_entry[i].bus_type != 0x80) {
 			bus = hrt->hrt_entry[i].bus_type;
-			seq_printf(seq, "   %s Information\n", bus_strings[bus]);
-
-			switch(bus)
-			{
-				case I2O_BUS_LOCAL:
-					seq_printf(seq, "     IOBase: %0#6x,",
-								hrt->hrt_entry[i].bus.local_bus.LbBaseIOPort);
-					seq_printf(seq, " MemoryBase: %0#10x\n",
-								hrt->hrt_entry[i].bus.local_bus.LbBaseMemoryAddress);
-					break;
-
-				case I2O_BUS_ISA:
-					seq_printf(seq, "     IOBase: %0#6x,",
-								hrt->hrt_entry[i].bus.isa_bus.IsaBaseIOPort);
-					seq_printf(seq, " MemoryBase: %0#10x,",
-								hrt->hrt_entry[i].bus.isa_bus.IsaBaseMemoryAddress);
-					seq_printf(seq, " CSN: %0#4x,",
-								hrt->hrt_entry[i].bus.isa_bus.CSN);
-					break;
-
-				case I2O_BUS_EISA:
-					seq_printf(seq, "     IOBase: %0#6x,",
-								hrt->hrt_entry[i].bus.eisa_bus.EisaBaseIOPort);
-					seq_printf(seq, " MemoryBase: %0#10x,",
-								hrt->hrt_entry[i].bus.eisa_bus.EisaBaseMemoryAddress);
-					seq_printf(seq, " Slot: %0#4x,",
-								hrt->hrt_entry[i].bus.eisa_bus.EisaSlotNumber);
-					break;
-			 
-				case I2O_BUS_MCA:
-					seq_printf(seq, "     IOBase: %0#6x,",
-								hrt->hrt_entry[i].bus.mca_bus.McaBaseIOPort);
-					seq_printf(seq, " MemoryBase: %0#10x,",
-								hrt->hrt_entry[i].bus.mca_bus.McaBaseMemoryAddress);
-					seq_printf(seq, " Slot: %0#4x,",
-								hrt->hrt_entry[i].bus.mca_bus.McaSlotNumber);
-					break;
-
-				case I2O_BUS_PCI:
-					seq_printf(seq, "     Bus: %0#4x",
-								hrt->hrt_entry[i].bus.pci_bus.PciBusNumber);
-					seq_printf(seq, " Dev: %0#4x",
-								hrt->hrt_entry[i].bus.pci_bus.PciDeviceNumber);
-					seq_printf(seq, " Func: %0#4x",
-								hrt->hrt_entry[i].bus.pci_bus.PciFunctionNumber);
-					seq_printf(seq, " Vendor: %0#6x",
-								hrt->hrt_entry[i].bus.pci_bus.PciVendorID);
-					seq_printf(seq, " Device: %0#6x\n",
-								hrt->hrt_entry[i].bus.pci_bus.PciDeviceID);
-					break;
-
-				default:
-					seq_printf(seq, "      Unsupported Bus Type\n");
+			seq_printf(seq, "   %s Information\n",
+				   bus_strings[bus]);
+
+			switch (bus) {
+			case I2O_BUS_LOCAL:
+				seq_printf(seq, "     IOBase: %0#6x,",
+					   hrt->hrt_entry[i].bus.local_bus.
+					   LbBaseIOPort);
+				seq_printf(seq, " MemoryBase: %0#10x\n",
+					   hrt->hrt_entry[i].bus.local_bus.
+					   LbBaseMemoryAddress);
+				break;
+
+			case I2O_BUS_ISA:
+				seq_printf(seq, "     IOBase: %0#6x,",
+					   hrt->hrt_entry[i].bus.isa_bus.
+					   IsaBaseIOPort);
+				seq_printf(seq, " MemoryBase: %0#10x,",
+					   hrt->hrt_entry[i].bus.isa_bus.
+					   IsaBaseMemoryAddress);
+				seq_printf(seq, " CSN: %0#4x,",
+					   hrt->hrt_entry[i].bus.isa_bus.CSN);
+				break;
+
+			case I2O_BUS_EISA:
+				seq_printf(seq, "     IOBase: %0#6x,",
+					   hrt->hrt_entry[i].bus.eisa_bus.
+					   EisaBaseIOPort);
+				seq_printf(seq, " MemoryBase: %0#10x,",
+					   hrt->hrt_entry[i].bus.eisa_bus.
+					   EisaBaseMemoryAddress);
+				seq_printf(seq, " Slot: %0#4x,",
+					   hrt->hrt_entry[i].bus.eisa_bus.
+					   EisaSlotNumber);
+				break;
+
+			case I2O_BUS_MCA:
+				seq_printf(seq, "     IOBase: %0#6x,",
+					   hrt->hrt_entry[i].bus.mca_bus.
+					   McaBaseIOPort);
+				seq_printf(seq, " MemoryBase: %0#10x,",
+					   hrt->hrt_entry[i].bus.mca_bus.
+					   McaBaseMemoryAddress);
+				seq_printf(seq, " Slot: %0#4x,",
+					   hrt->hrt_entry[i].bus.mca_bus.
+					   McaSlotNumber);
+				break;
+
+			case I2O_BUS_PCI:
+				seq_printf(seq, "     Bus: %0#4x",
+					   hrt->hrt_entry[i].bus.pci_bus.
+					   PciBusNumber);
+				seq_printf(seq, " Dev: %0#4x",
+					   hrt->hrt_entry[i].bus.pci_bus.
+					   PciDeviceNumber);
+				seq_printf(seq, " Func: %0#4x",
+					   hrt->hrt_entry[i].bus.pci_bus.
+					   PciFunctionNumber);
+				seq_printf(seq, " Vendor: %0#6x",
+					   hrt->hrt_entry[i].bus.pci_bus.
+					   PciVendorID);
+				seq_printf(seq, " Device: %0#6x\n",
+					   hrt->hrt_entry[i].bus.pci_bus.
+					   PciDeviceID);
+				break;
+
+			default:
+				seq_printf(seq, "      Unsupported Bus Type\n");
 			}
-		}
-		else
+		} else
 			seq_printf(seq, "   Unknown Bus Type\n");
 	}
-	
+
 	return 0;
 }
 
 int i2o_seq_show_lct(struct seq_file *seq, void *v)
 {
-	struct i2o_controller *c = (struct i2o_controller*)seq->private;
-	i2o_lct *lct = (i2o_lct *)c->lct;
+	struct i2o_controller *c = (struct i2o_controller *)seq->private;
+	i2o_lct *lct = (i2o_lct *) c->lct;
 	int entries;
 	int i;
 
 #define BUS_TABLE_SIZE 3
-	static char *bus_ports[] =
-	{
+	static char *bus_ports[] = {
 		"Generic Bus",
 		"SCSI Bus",
 		"Fibre Channel Bus"
 	};
 
-	entries = (lct->table_size - 3)/9;
+	entries = (lct->table_size - 3) / 9;
 
 	seq_printf(seq, "LCT contains %d %s\n", entries,
-						entries == 1 ? "entry" : "entries");
-	if(lct->boot_tid)	
+		   entries == 1 ? "entry" : "entries");
+	if (lct->boot_tid)
 		seq_printf(seq, "Boot Device @ ID %d\n", lct->boot_tid);
 
 	seq_printf(seq, "Current Change Indicator: %#10x\n", lct->change_ind);
 
-	for(i = 0; i < entries; i++)
-	{
+	for (i = 0; i < entries; i++) {
 		seq_printf(seq, "Entry %d\n", i);
-		seq_printf(seq, "  Class, SubClass  : %s", i2o_get_class_name(lct->lct_entry[i].class_id));
-	
+		seq_printf(seq, "  Class, SubClass  : %s",
+			   i2o_get_class_name(lct->lct_entry[i].class_id));
+
 		/*
-		 *	Classes which we'll print subclass info for
+		 *      Classes which we'll print subclass info for
 		 */
-		switch(lct->lct_entry[i].class_id & 0xFFF)
-		{
-			case I2O_CLASS_RANDOM_BLOCK_STORAGE:
-				switch(lct->lct_entry[i].sub_class)
-				{
-					case 0x00:
-						seq_printf(seq, ", Direct-Access Read/Write");
-						break;
-
-					case 0x04:
-						seq_printf(seq, ", WORM Drive");
-						break;
-	
-					case 0x05:
-						seq_printf(seq, ", CD-ROM Drive");
-						break;
-
-					case 0x07:
-						seq_printf(seq, ", Optical Memory Device");
-						break;
-
-					default:
-						seq_printf(seq, ", Unknown (0x%02x)",
-							       lct->lct_entry[i].sub_class);
-						break;
-				}
+		switch (lct->lct_entry[i].class_id & 0xFFF) {
+		case I2O_CLASS_RANDOM_BLOCK_STORAGE:
+			switch (lct->lct_entry[i].sub_class) {
+			case 0x00:
+				seq_printf(seq, ", Direct-Access Read/Write");
+				break;
+
+			case 0x04:
+				seq_printf(seq, ", WORM Drive");
 				break;
 
-			case I2O_CLASS_LAN:
-				switch(lct->lct_entry[i].sub_class & 0xFF)
-				{
-					case 0x30:
-						seq_printf(seq, ", Ethernet");
-						break;
-
-					case 0x40:
-						seq_printf(seq, ", 100base VG");
-						break;
-
-					case 0x50:
-						seq_printf(seq, ", IEEE 802.5/Token-Ring");
-						break;
-
-					case 0x60:
-						seq_printf(seq, ", ANSI X3T9.5 FDDI");
-						break;
-		
-					case 0x70:
-						seq_printf(seq, ", Fibre Channel");
-						break;
-
-					default:
-						seq_printf(seq, ", Unknown Sub-Class (0x%02x)",
-							       lct->lct_entry[i].sub_class & 0xFF);
-						break;
-				}
+			case 0x05:
+				seq_printf(seq, ", CD-ROM Drive");
 				break;
 
-			case I2O_CLASS_SCSI_PERIPHERAL:
-				if(lct->lct_entry[i].sub_class < SCSI_TABLE_SIZE)
-					seq_printf(seq, ", %s",
-								scsi_devices[lct->lct_entry[i].sub_class]);
-				else
-					seq_printf(seq, ", Unknown Device Type");
+			case 0x07:
+				seq_printf(seq, ", Optical Memory Device");
 				break;
 
-			case I2O_CLASS_BUS_ADAPTER_PORT:
-				if(lct->lct_entry[i].sub_class < BUS_TABLE_SIZE)
-					seq_printf(seq, ", %s",
-								bus_ports[lct->lct_entry[i].sub_class]);
-				else
-					seq_printf(seq, ", Unknown Bus Type");
+			default:
+				seq_printf(seq, ", Unknown (0x%02x)",
+					   lct->lct_entry[i].sub_class);
 				break;
+			}
+			break;
+
+		case I2O_CLASS_LAN:
+			switch (lct->lct_entry[i].sub_class & 0xFF) {
+			case 0x30:
+				seq_printf(seq, ", Ethernet");
+				break;
+
+			case 0x40:
+				seq_printf(seq, ", 100base VG");
+				break;
+
+			case 0x50:
+				seq_printf(seq, ", IEEE 802.5/Token-Ring");
+				break;
+
+			case 0x60:
+				seq_printf(seq, ", ANSI X3T9.5 FDDI");
+				break;
+
+			case 0x70:
+				seq_printf(seq, ", Fibre Channel");
+				break;
+
+			default:
+				seq_printf(seq, ", Unknown Sub-Class (0x%02x)",
+					   lct->lct_entry[i].sub_class & 0xFF);
+				break;
+			}
+			break;
+
+		case I2O_CLASS_SCSI_PERIPHERAL:
+			if (lct->lct_entry[i].sub_class < SCSI_TABLE_SIZE)
+				seq_printf(seq, ", %s",
+					   scsi_devices[lct->lct_entry[i].
+							sub_class]);
+			else
+				seq_printf(seq, ", Unknown Device Type");
+			break;
+
+		case I2O_CLASS_BUS_ADAPTER_PORT:
+			if (lct->lct_entry[i].sub_class < BUS_TABLE_SIZE)
+				seq_printf(seq, ", %s",
+					   bus_ports[lct->lct_entry[i].
+						     sub_class]);
+			else
+				seq_printf(seq, ", Unknown Bus Type");
+			break;
 		}
 		seq_printf(seq, "\n");
-		
-		seq_printf(seq, "  Local TID        : 0x%03x\n", lct->lct_entry[i].tid);
-		seq_printf(seq, "  User TID         : 0x%03x\n", lct->lct_entry[i].user_tid);
+
+		seq_printf(seq, "  Local TID        : 0x%03x\n",
+			   lct->lct_entry[i].tid);
+		seq_printf(seq, "  User TID         : 0x%03x\n",
+			   lct->lct_entry[i].user_tid);
 		seq_printf(seq, "  Parent TID       : 0x%03x\n",
-					lct->lct_entry[i].parent_tid);
+			   lct->lct_entry[i].parent_tid);
 		seq_printf(seq, "  Identity Tag     : 0x%x%x%x%x%x%x%x%x\n",
-					lct->lct_entry[i].identity_tag[0],
-					lct->lct_entry[i].identity_tag[1],
-					lct->lct_entry[i].identity_tag[2],
-					lct->lct_entry[i].identity_tag[3],
-					lct->lct_entry[i].identity_tag[4],
-					lct->lct_entry[i].identity_tag[5],
-					lct->lct_entry[i].identity_tag[6],
-					lct->lct_entry[i].identity_tag[7]);
+			   lct->lct_entry[i].identity_tag[0],
+			   lct->lct_entry[i].identity_tag[1],
+			   lct->lct_entry[i].identity_tag[2],
+			   lct->lct_entry[i].identity_tag[3],
+			   lct->lct_entry[i].identity_tag[4],
+			   lct->lct_entry[i].identity_tag[5],
+			   lct->lct_entry[i].identity_tag[6],
+			   lct->lct_entry[i].identity_tag[7]);
 		seq_printf(seq, "  Change Indicator : %0#10x\n",
-				lct->lct_entry[i].change_ind);
+			   lct->lct_entry[i].change_ind);
 		seq_printf(seq, "  Event Capab Mask : %0#10x\n",
-				lct->lct_entry[i].device_flags);
+			   lct->lct_entry[i].device_flags);
 	}
 
 	return 0;
@@ -559,17 +523,17 @@ int i2o_seq_show_lct(struct seq_file *seq, void *v)
 
 int i2o_seq_show_status(struct seq_file *seq, void *v)
 {
-	struct i2o_controller *c = (struct i2o_controller*)seq->private;
+	struct i2o_controller *c = (struct i2o_controller *)seq->private;
 	char prodstr[25];
 	int version;
-	
-	i2o_status_get(c); // reread the status block
+	i2o_status_block *sb = c->status_block.virt;
+
+	i2o_status_get(c);	// reread the status block
+
+	seq_printf(seq, "Organization ID        : %0#6x\n", sb->org_id);
 
-	seq_printf(seq, "Organization ID        : %0#6x\n",
-				c->status_block->org_id);
+	version = sb->i2o_version;
 
-	version = c->status_block->i2o_version;
-	
 /* FIXME for Spec 2.0
 	if (version == 0x02) {
 		seq_printf(seq, "Lowest I2O version supported: ");
@@ -599,170 +563,171 @@ int i2o_seq_show_status(struct seq_file *seq, void *v)
 		}
 	}
 */
-	seq_printf(seq, "IOP ID                 : %0#5x\n",
-				c->status_block->iop_id);
-	seq_printf(seq, "Host Unit ID           : %0#6x\n",
-				c->status_block->host_unit_id);
-	seq_printf(seq, "Segment Number         : %0#5x\n",
-				c->status_block->segment_number);
+	seq_printf(seq, "IOP ID                 : %0#5x\n", sb->iop_id);
+	seq_printf(seq, "Host Unit ID           : %0#6x\n", sb->host_unit_id);
+	seq_printf(seq, "Segment Number         : %0#5x\n", sb->segment_number);
 
 	seq_printf(seq, "I2O version            : ");
 	switch (version) {
-		case 0x00:
-			seq_printf(seq, "1.0\n");
-			break;
-		case 0x01:
-			seq_printf(seq, "1.5\n");
-			break;
-		case 0x02:
-			seq_printf(seq, "2.0\n");
-			break;
-		default:
-			seq_printf(seq, "Unknown version\n");
+	case 0x00:
+		seq_printf(seq, "1.0\n");
+		break;
+	case 0x01:
+		seq_printf(seq, "1.5\n");
+		break;
+	case 0x02:
+		seq_printf(seq, "2.0\n");
+		break;
+	default:
+		seq_printf(seq, "Unknown version\n");
 	}
 
 	seq_printf(seq, "IOP State              : ");
-	switch (c->status_block->iop_state) {
-		case 0x01:
-			seq_printf(seq, "INIT\n");
-			break;
+	switch (sb->iop_state) {
+	case 0x01:
+		seq_printf(seq, "INIT\n");
+		break;
 
-		case 0x02:
-			seq_printf(seq, "RESET\n");
-			break;
+	case 0x02:
+		seq_printf(seq, "RESET\n");
+		break;
 
-		case 0x04:
-			seq_printf(seq, "HOLD\n");
-			break;
+	case 0x04:
+		seq_printf(seq, "HOLD\n");
+		break;
 
-		case 0x05:
-			seq_printf(seq, "READY\n");
-			break;
+	case 0x05:
+		seq_printf(seq, "READY\n");
+		break;
 
-		case 0x08:
-			seq_printf(seq, "OPERATIONAL\n");
-			break;
+	case 0x08:
+		seq_printf(seq, "OPERATIONAL\n");
+		break;
 
-		case 0x10:
-			seq_printf(seq, "FAILED\n");
-			break;
+	case 0x10:
+		seq_printf(seq, "FAILED\n");
+		break;
 
-		case 0x11:
-			seq_printf(seq, "FAULTED\n");
-			break;
+	case 0x11:
+		seq_printf(seq, "FAULTED\n");
+		break;
 
-		default:
-			seq_printf(seq, "Unknown\n");
-			break;
+	default:
+		seq_printf(seq, "Unknown\n");
+		break;
 	}
 
 	seq_printf(seq, "Messenger Type         : ");
-	switch (c->status_block->msg_type) { 
-		case 0x00:
-			seq_printf(seq, "Memory mapped\n");
-			break;
-		case 0x01:
-			seq_printf(seq, "Memory mapped only\n");
-			break;
-		case 0x02:
-			seq_printf(seq,"Remote only\n");
-			break;
-		case 0x03:
-			seq_printf(seq, "Memory mapped and remote\n");
-			break;
-		default:
-			seq_printf(seq, "Unknown\n");
+	switch (sb->msg_type) {
+	case 0x00:
+		seq_printf(seq, "Memory mapped\n");
+		break;
+	case 0x01:
+		seq_printf(seq, "Memory mapped only\n");
+		break;
+	case 0x02:
+		seq_printf(seq, "Remote only\n");
+		break;
+	case 0x03:
+		seq_printf(seq, "Memory mapped and remote\n");
+		break;
+	default:
+		seq_printf(seq, "Unknown\n");
 	}
 
 	seq_printf(seq, "Inbound Frame Size     : %d bytes\n",
-				c->status_block->inbound_frame_size<<2);
+		   sb->inbound_frame_size << 2);
 	seq_printf(seq, "Max Inbound Frames     : %d\n",
-				c->status_block->max_inbound_frames);
+		   sb->max_inbound_frames);
 	seq_printf(seq, "Current Inbound Frames : %d\n",
-				c->status_block->cur_inbound_frames);
+		   sb->cur_inbound_frames);
 	seq_printf(seq, "Max Outbound Frames    : %d\n",
-				c->status_block->max_outbound_frames);
+		   sb->max_outbound_frames);
 
 	/* Spec doesn't say if NULL terminated or not... */
-	memcpy(prodstr, c->status_block->product_id, 24);
+	memcpy(prodstr, sb->product_id, 24);
 	prodstr[24] = '\0';
 	seq_printf(seq, "Product ID             : %s\n", prodstr);
 	seq_printf(seq, "Expected LCT Size      : %d bytes\n",
-				c->status_block->expected_lct_size);
+		   sb->expected_lct_size);
 
 	seq_printf(seq, "IOP Capabilities\n");
 	seq_printf(seq, "    Context Field Size Support : ");
-	switch (c->status_block->iop_capabilities & 0x0000003) {
-		case 0:
-			seq_printf(seq, "Supports only 32-bit context fields\n");
-			break;
-		case 1:
-			seq_printf(seq, "Supports only 64-bit context fields\n");
-			break;
-		case 2:
-			seq_printf(seq, "Supports 32-bit and 64-bit context fields, "
-						"but not concurrently\n");
-			break;
-		case 3:
-			seq_printf(seq, "Supports 32-bit and 64-bit context fields "
-						"concurrently\n");
-			break;
-		default:
-			seq_printf(seq, "0x%08x\n",c->status_block->iop_capabilities);
+	switch (sb->iop_capabilities & 0x0000003) {
+	case 0:
+		seq_printf(seq, "Supports only 32-bit context fields\n");
+		break;
+	case 1:
+		seq_printf(seq, "Supports only 64-bit context fields\n");
+		break;
+	case 2:
+		seq_printf(seq, "Supports 32-bit and 64-bit context fields, "
+			   "but not concurrently\n");
+		break;
+	case 3:
+		seq_printf(seq, "Supports 32-bit and 64-bit context fields "
+			   "concurrently\n");
+		break;
+	default:
+		seq_printf(seq, "0x%08x\n", sb->iop_capabilities);
 	}
 	seq_printf(seq, "    Current Context Field Size : ");
-	switch (c->status_block->iop_capabilities & 0x0000000C) {
-		case 0:
-			seq_printf(seq, "not configured\n");
-			break;
-		case 4:
-			seq_printf(seq, "Supports only 32-bit context fields\n");
-			break;
-		case 8:
-			seq_printf(seq, "Supports only 64-bit context fields\n");
-			break;
-		case 12:
-			seq_printf(seq, "Supports both 32-bit or 64-bit context fields "
-						"concurrently\n");
-			break;
-		default:
-			seq_printf(seq, "\n");
+	switch (sb->iop_capabilities & 0x0000000C) {
+	case 0:
+		seq_printf(seq, "not configured\n");
+		break;
+	case 4:
+		seq_printf(seq, "Supports only 32-bit context fields\n");
+		break;
+	case 8:
+		seq_printf(seq, "Supports only 64-bit context fields\n");
+		break;
+	case 12:
+		seq_printf(seq, "Supports both 32-bit or 64-bit context fields "
+			   "concurrently\n");
+		break;
+	default:
+		seq_printf(seq, "\n");
 	}
 	seq_printf(seq, "    Inbound Peer Support       : %s\n",
-			(c->status_block->iop_capabilities & 0x00000010) ? "Supported" : "Not supported");
+		   (sb->
+		    iop_capabilities & 0x00000010) ? "Supported" :
+		   "Not supported");
 	seq_printf(seq, "    Outbound Peer Support      : %s\n",
-			(c->status_block->iop_capabilities & 0x00000020) ? "Supported" : "Not supported");
+		   (sb->
+		    iop_capabilities & 0x00000020) ? "Supported" :
+		   "Not supported");
 	seq_printf(seq, "    Peer to Peer Support       : %s\n",
-			(c->status_block->iop_capabilities & 0x00000040) ? "Supported" : "Not supported");
+		   (sb->
+		    iop_capabilities & 0x00000040) ? "Supported" :
+		   "Not supported");
 
 	seq_printf(seq, "Desired private memory size   : %d kB\n",
-				c->status_block->desired_mem_size>>10);
+		   sb->desired_mem_size >> 10);
 	seq_printf(seq, "Allocated private memory size : %d kB\n",
-				c->status_block->current_mem_size>>10);
+		   sb->current_mem_size >> 10);
 	seq_printf(seq, "Private memory base address   : %0#10x\n",
-				c->status_block->current_mem_base);
+		   sb->current_mem_base);
 	seq_printf(seq, "Desired private I/O size      : %d kB\n",
-				c->status_block->desired_io_size>>10);
+		   sb->desired_io_size >> 10);
 	seq_printf(seq, "Allocated private I/O size    : %d kB\n",
-				c->status_block->current_io_size>>10);
+		   sb->current_io_size >> 10);
 	seq_printf(seq, "Private I/O base address      : %0#10x\n",
-				c->status_block->current_io_base);
+		   sb->current_io_base);
 
 	return 0;
 }
 
-int i2o_proc_read_hw(char *buf, char **start, off_t offset, int len, 
-		     int *eof, void *data)
+int i2o_seq_show_hw(struct seq_file *seq, void *v)
 {
-	struct i2o_controller *c = (struct i2o_controller*)data;
+	struct i2o_controller *c = (struct i2o_controller *)seq->private;
 	static u32 work32[5];
-	static u8 *work8 = (u8*)work32;
-	static u16 *work16 = (u16*)work32;
+	static u8 *work8 = (u8 *) work32;
+	static u16 *work16 = (u16 *) work32;
 	int token;
 	u32 hwcap;
 
-	static char *cpu_table[] =
-	{
+	static char *cpu_table[] = {
 		"Intel 80960 series",
 		"AMD2900 series",
 		"Motorola 68000 series",
@@ -773,397 +738,350 @@ int i2o_proc_read_hw(char *buf, char **start, off_t offset, int len,
 		"Intel x86 series"
 	};
 
-	spin_lock(&i2o_proc_lock);
-
-	len = 0;
-
-	token = i2o_query_scalar(c, ADAPTER_TID, 0x0000, -1, &work32, sizeof(work32));
+	token =
+	    i2o_parm_field_get(c->exec, 0x0000, -1, &work32, sizeof(work32));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0000 IOP Hardware");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		i2o_report_query_status(seq, token, "0x0000 IOP Hardware");
+		return 0;
 	}
 
-	len += sprintf(buf+len, "I2O Vendor ID    : %0#6x\n", work16[0]);
-	len += sprintf(buf+len, "Product ID       : %0#6x\n", work16[1]);
-	len += sprintf(buf+len, "CPU              : ");
-	if(work8[16] > 8)
-		len += sprintf(buf+len, "Unknown\n");
+	seq_printf(seq, "I2O Vendor ID    : %0#6x\n", work16[0]);
+	seq_printf(seq, "Product ID       : %0#6x\n", work16[1]);
+	seq_printf(seq, "CPU              : ");
+	if (work8[16] > 8)
+		seq_printf(seq, "Unknown\n");
 	else
-		len += sprintf(buf+len, "%s\n", cpu_table[work8[16]]);
+		seq_printf(seq, "%s\n", cpu_table[work8[16]]);
 	/* Anyone using ProcessorVersion? */
-	
-	len += sprintf(buf+len, "RAM              : %dkB\n", work32[1]>>10);
-	len += sprintf(buf+len, "Non-Volatile Mem : %dkB\n", work32[2]>>10);
+
+	seq_printf(seq, "RAM              : %dkB\n", work32[1] >> 10);
+	seq_printf(seq, "Non-Volatile Mem : %dkB\n", work32[2] >> 10);
 
 	hwcap = work32[3];
-	len += sprintf(buf+len, "Capabilities : 0x%08x\n", hwcap);
-	len += sprintf(buf+len, "   [%s] Self booting\n",
-			(hwcap&0x00000001) ? "+" : "-");
-	len += sprintf(buf+len, "   [%s] Upgradable IRTOS\n",
-			(hwcap&0x00000002) ? "+" : "-");
-	len += sprintf(buf+len, "   [%s] Supports downloading DDMs\n",
-			(hwcap&0x00000004) ? "+" : "-");
-	len += sprintf(buf+len, "   [%s] Supports installing DDMs\n",
-			(hwcap&0x00000008) ? "+" : "-");
-	len += sprintf(buf+len, "   [%s] Battery-backed RAM\n",
-			(hwcap&0x00000010) ? "+" : "-");
-
-	spin_unlock(&i2o_proc_lock);
-
-	return len;
-}
+	seq_printf(seq, "Capabilities : 0x%08x\n", hwcap);
+	seq_printf(seq, "   [%s] Self booting\n",
+		   (hwcap & 0x00000001) ? "+" : "-");
+	seq_printf(seq, "   [%s] Upgradable IRTOS\n",
+		   (hwcap & 0x00000002) ? "+" : "-");
+	seq_printf(seq, "   [%s] Supports downloading DDMs\n",
+		   (hwcap & 0x00000004) ? "+" : "-");
+	seq_printf(seq, "   [%s] Supports installing DDMs\n",
+		   (hwcap & 0x00000008) ? "+" : "-");
+	seq_printf(seq, "   [%s] Battery-backed RAM\n",
+		   (hwcap & 0x00000010) ? "+" : "-");
 
+	return 0;
+}
 
 /* Executive group 0003h - Executing DDM List (table) */
-int i2o_proc_read_ddm_table(char *buf, char **start, off_t offset, int len, 
-			    int *eof, void *data)
+int i2o_seq_show_ddm_table(struct seq_file *seq, void *v)
 {
-	struct i2o_controller *c = (struct i2o_controller*)data;
+	struct i2o_controller *c = (struct i2o_controller *)seq->private;
 	int token;
 	int i;
 
 	typedef struct _i2o_exec_execute_ddm_table {
 		u16 ddm_tid;
-		u8  module_type;
-		u8  reserved;
+		u8 module_type;
+		u8 reserved;
 		u16 i2o_vendor_id;
 		u16 module_id;
-		u8  module_name_version[28];
+		u8 module_name_version[28];
 		u32 data_size;
 		u32 code_size;
 	} i2o_exec_execute_ddm_table;
 
-	struct
-	{
+	struct {
 		u16 result_count;
 		u16 pad;
 		u16 block_size;
-		u8  block_status;
-		u8  error_info_size;
+		u8 block_status;
+		u8 error_info_size;
 		u16 row_count;
 		u16 more_flag;
-		i2o_exec_execute_ddm_table ddm_table[MAX_I2O_MODULES];
+		i2o_exec_execute_ddm_table ddm_table[I2O_MAX_MODULES];
 	} *result;
 
 	i2o_exec_execute_ddm_table ddm_table;
 
 	result = kmalloc(sizeof(*result), GFP_KERNEL);
-	if(!result)
+	if (!result)
 		return -ENOMEM;
 
-	spin_lock(&i2o_proc_lock);
-	len = 0;
-
-	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				c, ADAPTER_TID, 
-				0x0003, -1,
-				NULL, 0,
-				result, sizeof(*result));
+	token = i2o_parm_table_get(c->exec, I2O_PARAMS_TABLE_GET, 0x0003, -1,
+				   NULL, 0, result, sizeof(*result));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0003 Executing DDM List");
+		i2o_report_query_status(seq, token,
+					"0x0003 Executing DDM List");
 		goto out;
 	}
 
-	len += sprintf(buf+len, "Tid   Module_type     Vendor Mod_id  Module_name             Vrs  Data_size Code_size\n");
-	ddm_table=result->ddm_table[0];
+	seq_printf(seq,
+		   "Tid   Module_type     Vendor Mod_id  Module_name             Vrs  Data_size Code_size\n");
+	ddm_table = result->ddm_table[0];
 
-	for(i=0; i < result->row_count; ddm_table=result->ddm_table[++i])
-	{
-		len += sprintf(buf+len, "0x%03x ", ddm_table.ddm_tid & 0xFFF);
+	for (i = 0; i < result->row_count; ddm_table = result->ddm_table[++i]) {
+		seq_printf(seq, "0x%03x ", ddm_table.ddm_tid & 0xFFF);
 
-		switch(ddm_table.module_type)
-		{
+		switch (ddm_table.module_type) {
 		case 0x01:
-			len += sprintf(buf+len, "Downloaded DDM  ");
-			break;			
+			seq_printf(seq, "Downloaded DDM  ");
+			break;
 		case 0x22:
-			len += sprintf(buf+len, "Embedded DDM    ");
+			seq_printf(seq, "Embedded DDM    ");
 			break;
 		default:
-			len += sprintf(buf+len, "                ");
+			seq_printf(seq, "                ");
 		}
 
-		len += sprintf(buf+len, "%-#7x", ddm_table.i2o_vendor_id);
-		len += sprintf(buf+len, "%-#8x", ddm_table.module_id);
-		len += sprintf(buf+len, "%-29s", chtostr(ddm_table.module_name_version, 28));
-		len += sprintf(buf+len, "%9d  ", ddm_table.data_size);
-		len += sprintf(buf+len, "%8d", ddm_table.code_size);
+		seq_printf(seq, "%-#7x", ddm_table.i2o_vendor_id);
+		seq_printf(seq, "%-#8x", ddm_table.module_id);
+		seq_printf(seq, "%-29s",
+			   chtostr(ddm_table.module_name_version, 28));
+		seq_printf(seq, "%9d  ", ddm_table.data_size);
+		seq_printf(seq, "%8d", ddm_table.code_size);
 
-		len += sprintf(buf+len, "\n");
+		seq_printf(seq, "\n");
 	}
-out:
-	spin_unlock(&i2o_proc_lock);
+      out:
 	kfree(result);
-	return len;
+	return 0;
 }
 
-
 /* Executive group 0004h - Driver Store (scalar) */
-int i2o_proc_read_driver_store(char *buf, char **start, off_t offset, int len, 
-		     int *eof, void *data)
+int i2o_seq_show_driver_store(struct seq_file *seq, void *v)
 {
-	struct i2o_controller *c = (struct i2o_controller*)data;
+	struct i2o_controller *c = (struct i2o_controller *)seq->private;
 	u32 work32[8];
 	int token;
 
-	spin_lock(&i2o_proc_lock);
-
-	len = 0;
-
-	token = i2o_query_scalar(c, ADAPTER_TID, 0x0004, -1, &work32, sizeof(work32));
+	token =
+	    i2o_parm_field_get(c->exec, 0x0004, -1, &work32, sizeof(work32));
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0004 Driver Store");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		i2o_report_query_status(seq, token, "0x0004 Driver Store");
+		return 0;
 	}
 
-	len += sprintf(buf+len, "Module limit  : %d\n"
-				"Module count  : %d\n"
-				"Current space : %d kB\n"
-				"Free space    : %d kB\n", 
-			work32[0], work32[1], work32[2]>>10, work32[3]>>10);
-
-	spin_unlock(&i2o_proc_lock);
+	seq_printf(seq, "Module limit  : %d\n"
+		   "Module count  : %d\n"
+		   "Current space : %d kB\n"
+		   "Free space    : %d kB\n",
+		   work32[0], work32[1], work32[2] >> 10, work32[3] >> 10);
 
-	return len;
+	return 0;
 }
 
-
 /* Executive group 0005h - Driver Store Table (table) */
-int i2o_proc_read_drivers_stored(char *buf, char **start, off_t offset,
-				 int len, int *eof, void *data)
+int i2o_seq_show_drivers_stored(struct seq_file *seq, void *v)
 {
 	typedef struct _i2o_driver_store {
 		u16 stored_ddm_index;
-		u8  module_type;
-		u8  reserved;
+		u8 module_type;
+		u8 reserved;
 		u16 i2o_vendor_id;
 		u16 module_id;
-		u8  module_name_version[28];
-		u8  date[8];
+		u8 module_name_version[28];
+		u8 date[8];
 		u32 module_size;
 		u32 mpb_size;
 		u32 module_flags;
 	} i2o_driver_store_table;
 
-	struct i2o_controller *c = (struct i2o_controller*)data;
+	struct i2o_controller *c = (struct i2o_controller *)seq->private;
 	int token;
 	int i;
 
-	typedef struct
-	{
+	typedef struct {
 		u16 result_count;
 		u16 pad;
 		u16 block_size;
-		u8  block_status;
-		u8  error_info_size;
+		u8 block_status;
+		u8 error_info_size;
 		u16 row_count;
 		u16 more_flag;
-		i2o_driver_store_table dst[MAX_I2O_MODULES];
+		i2o_driver_store_table dst[I2O_MAX_MODULES];
 	} i2o_driver_result_table;
-	
+
 	i2o_driver_result_table *result;
 	i2o_driver_store_table *dst;
 
-
-	len = 0;
-	
 	result = kmalloc(sizeof(i2o_driver_result_table), GFP_KERNEL);
-	if(result == NULL)
+	if (result == NULL)
 		return -ENOMEM;
 
-	spin_lock(&i2o_proc_lock);
-
-	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				c, ADAPTER_TID, 0x0005, -1, NULL, 0, 
-				result, sizeof(*result));
+	token = i2o_parm_table_get(c->exec, I2O_PARAMS_TABLE_GET, 0x0005, -1,
+				   NULL, 0, result, sizeof(*result));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0005 DRIVER STORE TABLE");
-		spin_unlock(&i2o_proc_lock);
+		i2o_report_query_status(seq, token,
+					"0x0005 DRIVER STORE TABLE");
 		kfree(result);
-		return len;
+		return 0;
 	}
 
-	len += sprintf(buf+len, "#  Module_type     Vendor Mod_id  Module_name             Vrs"  
-				"Date     Mod_size Par_size Flags\n");
-	for(i=0, dst=&result->dst[0]; i < result->row_count; dst=&result->dst[++i])
-	{
-		len += sprintf(buf+len, "%-3d", dst->stored_ddm_index);
-		switch(dst->module_type)
-		{
+	seq_printf(seq,
+		   "#  Module_type     Vendor Mod_id  Module_name             Vrs"
+		   "Date     Mod_size Par_size Flags\n");
+	for (i = 0, dst = &result->dst[0]; i < result->row_count;
+	     dst = &result->dst[++i]) {
+		seq_printf(seq, "%-3d", dst->stored_ddm_index);
+		switch (dst->module_type) {
 		case 0x01:
-			len += sprintf(buf+len, "Downloaded DDM  ");
-			break;			
+			seq_printf(seq, "Downloaded DDM  ");
+			break;
 		case 0x22:
-			len += sprintf(buf+len, "Embedded DDM    ");
+			seq_printf(seq, "Embedded DDM    ");
 			break;
 		default:
-			len += sprintf(buf+len, "                ");
+			seq_printf(seq, "                ");
 		}
 
 #if 0
-		if(c->i2oversion == 0x02)
-			len += sprintf(buf+len, "%-d", dst->module_state);
+		if (c->i2oversion == 0x02)
+			seq_printf(seq, "%-d", dst->module_state);
 #endif
 
-		len += sprintf(buf+len, "%-#7x", dst->i2o_vendor_id);
-		len += sprintf(buf+len, "%-#8x", dst->module_id);
-		len += sprintf(buf+len, "%-29s", chtostr(dst->module_name_version,28));
-		len += sprintf(buf+len, "%-9s", chtostr(dst->date,8));
-		len += sprintf(buf+len, "%8d ", dst->module_size);
-		len += sprintf(buf+len, "%8d ", dst->mpb_size);
-		len += sprintf(buf+len, "0x%04x", dst->module_flags);
+		seq_printf(seq, "%-#7x", dst->i2o_vendor_id);
+		seq_printf(seq, "%-#8x", dst->module_id);
+		seq_printf(seq, "%-29s", chtostr(dst->module_name_version, 28));
+		seq_printf(seq, "%-9s", chtostr(dst->date, 8));
+		seq_printf(seq, "%8d ", dst->module_size);
+		seq_printf(seq, "%8d ", dst->mpb_size);
+		seq_printf(seq, "0x%04x", dst->module_flags);
 #if 0
-		if(c->i2oversion == 0x02)
-			len += sprintf(buf+len, "%d",
-				       dst->notification_level);
+		if (c->i2oversion == 0x02)
+			seq_printf(seq, "%d", dst->notification_level);
 #endif
-		len += sprintf(buf+len, "\n");
+		seq_printf(seq, "\n");
 	}
 
-	spin_unlock(&i2o_proc_lock);
 	kfree(result);
-	return len;
+	return 0;
 }
 
-
 /* Generic group F000h - Params Descriptor (table) */
-int i2o_proc_read_groups(char *buf, char **start, off_t offset, int len, 
-			 int *eof, void *data)
+int i2o_seq_show_groups(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
 	int token;
 	int i;
 	u8 properties;
 
-	typedef struct _i2o_group_info
-	{
+	typedef struct _i2o_group_info {
 		u16 group_number;
 		u16 field_count;
 		u16 row_count;
-		u8  properties;
-		u8  reserved;
+		u8 properties;
+		u8 reserved;
 	} i2o_group_info;
 
-	struct
-	{
+	struct {
 		u16 result_count;
 		u16 pad;
 		u16 block_size;
-		u8  block_status;
-		u8  error_info_size;
+		u8 block_status;
+		u8 error_info_size;
 		u16 row_count;
 		u16 more_flag;
 		i2o_group_info group[256];
 	} *result;
 
 	result = kmalloc(sizeof(*result), GFP_KERNEL);
-	if(!result)
+	if (!result)
 		return -ENOMEM;
 
-	spin_lock(&i2o_proc_lock);
-
-	len = 0;
-
-	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				d->controller, d->lct_data.tid, 0xF000, -1, NULL, 0,
-				result, sizeof(*result));
+	token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF000, -1, NULL, 0,
+				   result, sizeof(*result));
 
 	if (token < 0) {
-		len = i2o_report_query_status(buf+len, token, "0xF000 Params Descriptor");
+		i2o_report_query_status(seq, token, "0xF000 Params Descriptor");
 		goto out;
 	}
 
-	len += sprintf(buf+len, "#  Group   FieldCount RowCount Type   Add Del Clear\n");
+	seq_printf(seq,
+		   "#  Group   FieldCount RowCount Type   Add Del Clear\n");
 
-	for (i=0; i < result->row_count; i++)
-	{
-		len += sprintf(buf+len, "%-3d", i);
-		len += sprintf(buf+len, "0x%04X ", result->group[i].group_number);
-		len += sprintf(buf+len, "%10d ", result->group[i].field_count);
-		len += sprintf(buf+len, "%8d ",  result->group[i].row_count);
+	for (i = 0; i < result->row_count; i++) {
+		seq_printf(seq, "%-3d", i);
+		seq_printf(seq, "0x%04X ", result->group[i].group_number);
+		seq_printf(seq, "%10d ", result->group[i].field_count);
+		seq_printf(seq, "%8d ", result->group[i].row_count);
 
 		properties = result->group[i].properties;
-		if (properties & 0x1)	len += sprintf(buf+len, "Table  ");
-				else	len += sprintf(buf+len, "Scalar ");
-		if (properties & 0x2)	len += sprintf(buf+len, " + ");
-				else	len += sprintf(buf+len, " - ");
-		if (properties & 0x4)	len += sprintf(buf+len, "  + ");
-				else	len += sprintf(buf+len, "  - ");
-		if (properties & 0x8)	len += sprintf(buf+len, "  + ");
-				else	len += sprintf(buf+len, "  - ");
-
-		len += sprintf(buf+len, "\n");
+		if (properties & 0x1)
+			seq_printf(seq, "Table  ");
+		else
+			seq_printf(seq, "Scalar ");
+		if (properties & 0x2)
+			seq_printf(seq, " + ");
+		else
+			seq_printf(seq, " - ");
+		if (properties & 0x4)
+			seq_printf(seq, "  + ");
+		else
+			seq_printf(seq, "  - ");
+		if (properties & 0x8)
+			seq_printf(seq, "  + ");
+		else
+			seq_printf(seq, "  - ");
+
+		seq_printf(seq, "\n");
 	}
 
 	if (result->more_flag)
-		len += sprintf(buf+len, "There is more...\n");
-out:
-	spin_unlock(&i2o_proc_lock);
+		seq_printf(seq, "There is more...\n");
+      out:
 	kfree(result);
-	return len;
+	return 0;
 }
 
-
 /* Generic group F001h - Physical Device Table (table) */
-int i2o_proc_read_phys_device(char *buf, char **start, off_t offset, int len,
-			      int *eof, void *data)
+int i2o_seq_show_phys_device(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
 	int token;
 	int i;
 
-	struct
-	{
+	struct {
 		u16 result_count;
 		u16 pad;
 		u16 block_size;
-		u8  block_status;
-		u8  error_info_size;
+		u8 block_status;
+		u8 error_info_size;
 		u16 row_count;
 		u16 more_flag;
 		u32 adapter_id[64];
 	} result;
 
-	spin_lock(&i2o_proc_lock);
-	len = 0;
-
-	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				d->controller, d->lct_data.tid,
-				0xF001, -1, NULL, 0,
-				&result, sizeof(result));
+	token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF001, -1, NULL, 0,
+				   &result, sizeof(result));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0xF001 Physical Device Table");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		i2o_report_query_status(seq, token,
+					"0xF001 Physical Device Table");
+		return 0;
 	}
 
 	if (result.row_count)
-		len += sprintf(buf+len, "#  AdapterId\n");
+		seq_printf(seq, "#  AdapterId\n");
 
-	for (i=0; i < result.row_count; i++)
-	{
-		len += sprintf(buf+len, "%-2d", i);
-		len += sprintf(buf+len, "%#7x\n", result.adapter_id[i]);
+	for (i = 0; i < result.row_count; i++) {
+		seq_printf(seq, "%-2d", i);
+		seq_printf(seq, "%#7x\n", result.adapter_id[i]);
 	}
 
 	if (result.more_flag)
-		len += sprintf(buf+len, "There is more...\n");
+		seq_printf(seq, "There is more...\n");
 
-	spin_unlock(&i2o_proc_lock);
-	return len;
+	return 0;
 }
 
 /* Generic group F002h - Claimed Table (table) */
-int i2o_proc_read_claimed(char *buf, char **start, off_t offset, int len,
-			  int *eof, void *data)
+int i2o_seq_show_claimed(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
 	int token;
 	int i;
 
@@ -1171,434 +1089,356 @@ int i2o_proc_read_claimed(char *buf, char **start, off_t offset, int len,
 		u16 result_count;
 		u16 pad;
 		u16 block_size;
-		u8  block_status;
-		u8  error_info_size;
+		u8 block_status;
+		u8 error_info_size;
 		u16 row_count;
 		u16 more_flag;
 		u16 claimed_tid[64];
 	} result;
 
-	spin_lock(&i2o_proc_lock);
-	len = 0;
-
-	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				d->controller, d->lct_data.tid,
-				0xF002, -1, NULL, 0,
-				&result, sizeof(result));
+	token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF002, -1, NULL, 0,
+				   &result, sizeof(result));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0xF002 Claimed Table");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		i2o_report_query_status(seq, token, "0xF002 Claimed Table");
+		return 0;
 	}
 
 	if (result.row_count)
-		len += sprintf(buf+len, "#  ClaimedTid\n");
+		seq_printf(seq, "#  ClaimedTid\n");
 
-	for (i=0; i < result.row_count; i++)
-	{
-		len += sprintf(buf+len, "%-2d", i);
-		len += sprintf(buf+len, "%#7x\n", result.claimed_tid[i]);
+	for (i = 0; i < result.row_count; i++) {
+		seq_printf(seq, "%-2d", i);
+		seq_printf(seq, "%#7x\n", result.claimed_tid[i]);
 	}
 
 	if (result.more_flag)
-		len += sprintf(buf+len, "There is more...\n");
+		seq_printf(seq, "There is more...\n");
 
-	spin_unlock(&i2o_proc_lock);
-	return len;
+	return 0;
 }
 
 /* Generic group F003h - User Table (table) */
-int i2o_proc_read_users(char *buf, char **start, off_t offset, int len,
-			int *eof, void *data)
+int i2o_seq_show_users(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
 	int token;
 	int i;
 
-	typedef struct _i2o_user_table
-	{
+	typedef struct _i2o_user_table {
 		u16 instance;
 		u16 user_tid;
 		u8 claim_type;
-		u8  reserved1;
-		u16  reserved2;
+		u8 reserved1;
+		u16 reserved2;
 	} i2o_user_table;
 
-	struct
-	{
+	struct {
 		u16 result_count;
 		u16 pad;
 		u16 block_size;
-		u8  block_status;
-		u8  error_info_size;
+		u8 block_status;
+		u8 error_info_size;
 		u16 row_count;
 		u16 more_flag;
 		i2o_user_table user[64];
 	} *result;
 
 	result = kmalloc(sizeof(*result), GFP_KERNEL);
-	if(!result)
+	if (!result)
 		return -ENOMEM;
 
-	spin_lock(&i2o_proc_lock);
-	len = 0;
-
-	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				d->controller, d->lct_data.tid,
-				0xF003, -1, NULL, 0,
-				result, sizeof(*result));
+	token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF003, -1, NULL, 0,
+				   result, sizeof(*result));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0xF003 User Table");
+		i2o_report_query_status(seq, token, "0xF003 User Table");
 		goto out;
 	}
 
-	len += sprintf(buf+len, "#  Instance UserTid ClaimType\n");
+	seq_printf(seq, "#  Instance UserTid ClaimType\n");
 
-	for(i=0; i < result->row_count; i++)
-	{
-		len += sprintf(buf+len, "%-3d", i);
-		len += sprintf(buf+len, "%#8x ", result->user[i].instance);
-		len += sprintf(buf+len, "%#7x ", result->user[i].user_tid);
-		len += sprintf(buf+len, "%#9x\n", result->user[i].claim_type);
+	for (i = 0; i < result->row_count; i++) {
+		seq_printf(seq, "%-3d", i);
+		seq_printf(seq, "%#8x ", result->user[i].instance);
+		seq_printf(seq, "%#7x ", result->user[i].user_tid);
+		seq_printf(seq, "%#9x\n", result->user[i].claim_type);
 	}
 
 	if (result->more_flag)
-		len += sprintf(buf+len, "There is more...\n");
-out:
-	spin_unlock(&i2o_proc_lock);
+		seq_printf(seq, "There is more...\n");
+      out:
 	kfree(result);
-	return len;
+	return 0;
 }
 
 /* Generic group F005h - Private message extensions (table) (optional) */
-int i2o_proc_read_priv_msgs(char *buf, char **start, off_t offset, int len, 
-			    int *eof, void *data)
+int i2o_seq_show_priv_msgs(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
 	int token;
 	int i;
 
-	typedef struct _i2o_private
-	{
+	typedef struct _i2o_private {
 		u16 ext_instance;
 		u16 organization_id;
 		u16 x_function_code;
 	} i2o_private;
 
-	struct
-	{
+	struct {
 		u16 result_count;
 		u16 pad;
 		u16 block_size;
-		u8  block_status;
-		u8  error_info_size;
+		u8 block_status;
+		u8 error_info_size;
 		u16 row_count;
 		u16 more_flag;
 		i2o_private extension[64];
 	} result;
 
-	spin_lock(&i2o_proc_lock);
-
-	len = 0;
-
-	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				d->controller, d->lct_data.tid,
-				0xF000, -1,
-				NULL, 0,
-				&result, sizeof(result));
+	token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF000, -1, NULL, 0,
+				   &result, sizeof(result));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0xF005 Private Message Extensions (optional)");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		i2o_report_query_status(seq, token,
+					"0xF005 Private Message Extensions (optional)");
+		return 0;
 	}
-	
-	len += sprintf(buf+len, "Instance#  OrgId  FunctionCode\n");
 
-	for(i=0; i < result.row_count; i++)
-	{
-		len += sprintf(buf+len, "%0#9x ", result.extension[i].ext_instance);
-		len += sprintf(buf+len, "%0#6x ", result.extension[i].organization_id);
-		len += sprintf(buf+len, "%0#6x",  result.extension[i].x_function_code);
+	seq_printf(seq, "Instance#  OrgId  FunctionCode\n");
 
-		len += sprintf(buf+len, "\n");
-	}
+	for (i = 0; i < result.row_count; i++) {
+		seq_printf(seq, "%0#9x ", result.extension[i].ext_instance);
+		seq_printf(seq, "%0#6x ", result.extension[i].organization_id);
+		seq_printf(seq, "%0#6x", result.extension[i].x_function_code);
 
-	if(result.more_flag)
-		len += sprintf(buf+len, "There is more...\n");
+		seq_printf(seq, "\n");
+	}
 
-	spin_unlock(&i2o_proc_lock);
+	if (result.more_flag)
+		seq_printf(seq, "There is more...\n");
 
-	return len;
+	return 0;
 }
 
-
 /* Generic group F006h - Authorized User Table (table) */
-int i2o_proc_read_authorized_users(char *buf, char **start, off_t offset, int len,
-				   int *eof, void *data)
+int i2o_seq_show_authorized_users(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
 	int token;
 	int i;
 
-	struct
-	{
+	struct {
 		u16 result_count;
 		u16 pad;
 		u16 block_size;
-		u8  block_status;
-		u8  error_info_size;
+		u8 block_status;
+		u8 error_info_size;
 		u16 row_count;
 		u16 more_flag;
 		u32 alternate_tid[64];
 	} result;
 
-	spin_lock(&i2o_proc_lock);
-	len = 0;
-
-	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				d->controller, d->lct_data.tid,
-				0xF006, -1,
-				NULL, 0,
-				&result, sizeof(result));
+	token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF006, -1, NULL, 0,
+				   &result, sizeof(result));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0xF006 Autohorized User Table");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		i2o_report_query_status(seq, token,
+					"0xF006 Autohorized User Table");
+		return 0;
 	}
 
 	if (result.row_count)
-		len += sprintf(buf+len, "#  AlternateTid\n");
+		seq_printf(seq, "#  AlternateTid\n");
 
-	for(i=0; i < result.row_count; i++)
-	{
-		len += sprintf(buf+len, "%-2d", i);
-		len += sprintf(buf+len, "%#7x ", result.alternate_tid[i]);
+	for (i = 0; i < result.row_count; i++) {
+		seq_printf(seq, "%-2d", i);
+		seq_printf(seq, "%#7x ", result.alternate_tid[i]);
 	}
 
 	if (result.more_flag)
-		len += sprintf(buf+len, "There is more...\n");
+		seq_printf(seq, "There is more...\n");
 
-	spin_unlock(&i2o_proc_lock);
-	return len;
+	return 0;
 }
 
-
 /* Generic group F100h - Device Identity (scalar) */
-int i2o_proc_read_dev_identity(char *buf, char **start, off_t offset, int len, 
-			       int *eof, void *data)
+int i2o_seq_show_dev_identity(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u32 work32[128];		// allow for "stuff" + up to 256 byte (max) serial number
-					// == (allow) 512d bytes (max)
-	static u16 *work16 = (u16*)work32;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
+	static u32 work32[128];	// allow for "stuff" + up to 256 byte (max) serial number
+	// == (allow) 512d bytes (max)
+	static u16 *work16 = (u16 *) work32;
 	int token;
 
-	spin_lock(&i2o_proc_lock);
-	
-	len = 0;
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				0xF100,	-1,
-				&work32, sizeof(work32));
+	token = i2o_parm_field_get(d, 0xF100, -1, &work32, sizeof(work32));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token ,"0xF100 Device Identity");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		i2o_report_query_status(seq, token, "0xF100 Device Identity");
+		return 0;
 	}
-	
-	len += sprintf(buf,     "Device Class  : %s\n", i2o_get_class_name(work16[0]));
-	len += sprintf(buf+len, "Owner TID     : %0#5x\n", work16[2]);
-	len += sprintf(buf+len, "Parent TID    : %0#5x\n", work16[3]);
-	len += sprintf(buf+len, "Vendor info   : %s\n", chtostr((u8 *)(work32+2), 16));
-	len += sprintf(buf+len, "Product info  : %s\n", chtostr((u8 *)(work32+6), 16));
-	len += sprintf(buf+len, "Description   : %s\n", chtostr((u8 *)(work32+10), 16));
-	len += sprintf(buf+len, "Product rev.  : %s\n", chtostr((u8 *)(work32+14), 8));
-
-	len += sprintf(buf+len, "Serial number : ");
-	len = print_serial_number(buf, len,
-			(u8*)(work32+16),
-						/* allow for SNLen plus
-						 * possible trailing '\0'
-						 */
-			sizeof(work32)-(16*sizeof(u32))-2
-				);
-	len +=  sprintf(buf+len, "\n");
-
-	spin_unlock(&i2o_proc_lock);
-
-	return len;
-}
 
+	seq_printf(seq, "Device Class  : %s\n", i2o_get_class_name(work16[0]));
+	seq_printf(seq, "Owner TID     : %0#5x\n", work16[2]);
+	seq_printf(seq, "Parent TID    : %0#5x\n", work16[3]);
+	seq_printf(seq, "Vendor info   : %s\n",
+		   chtostr((u8 *) (work32 + 2), 16));
+	seq_printf(seq, "Product info  : %s\n",
+		   chtostr((u8 *) (work32 + 6), 16));
+	seq_printf(seq, "Description   : %s\n",
+		   chtostr((u8 *) (work32 + 10), 16));
+	seq_printf(seq, "Product rev.  : %s\n",
+		   chtostr((u8 *) (work32 + 14), 8));
+
+	seq_printf(seq, "Serial number : ");
+	print_serial_number(seq, (u8 *) (work32 + 16),
+			    /* allow for SNLen plus
+			     * possible trailing '\0'
+			     */
+			    sizeof(work32) - (16 * sizeof(u32)) - 2);
+	seq_printf(seq, "\n");
 
-int i2o_proc_read_dev_name(char *buf, char **start, off_t offset, int len,
-	int *eof, void *data)
-{
-	struct i2o_device *d = (struct i2o_device*)data;
+	return 0;
+}
 
-	if ( d->dev_name[0] == '\0' )
-		return 0;
+int i2o_seq_show_dev_name(struct seq_file *seq, void *v)
+{
+	struct i2o_device *d = (struct i2o_device *)seq->private;
 
-	len = sprintf(buf, "%s\n", d->dev_name);
+	seq_printf(seq, "%s\n", d->device.bus_id);
 
-	return len;
+	return 0;
 }
 
-
 /* Generic group F101h - DDM Identity (scalar) */
-int i2o_proc_read_ddm_identity(char *buf, char **start, off_t offset, int len, 
-			      int *eof, void *data)
+int i2o_seq_show_ddm_identity(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
 	int token;
 
-	struct
-	{
+	struct {
 		u16 ddm_tid;
 		u8 module_name[24];
 		u8 module_rev[8];
 		u8 sn_format;
 		u8 serial_number[12];
-		u8 pad[256]; // allow up to 256 byte (max) serial number
-	} result;	
-
-	spin_lock(&i2o_proc_lock);
-	
-	len = 0;
+		u8 pad[256];	// allow up to 256 byte (max) serial number
+	} result;
 
-	token = i2o_query_scalar(d->controller, d->lct_data.tid, 
-				0xF101,	-1,
-				&result, sizeof(result));
+	token = i2o_parm_field_get(d, 0xF101, -1, &result, sizeof(result));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0xF101 DDM Identity");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		i2o_report_query_status(seq, token, "0xF101 DDM Identity");
+		return 0;
 	}
 
-	len += sprintf(buf,     "Registering DDM TID : 0x%03x\n", result.ddm_tid);
-	len += sprintf(buf+len, "Module name         : %s\n", chtostr(result.module_name, 24));
-	len += sprintf(buf+len, "Module revision     : %s\n", chtostr(result.module_rev, 8));
+	seq_printf(seq, "Registering DDM TID : 0x%03x\n", result.ddm_tid);
+	seq_printf(seq, "Module name         : %s\n",
+		   chtostr(result.module_name, 24));
+	seq_printf(seq, "Module revision     : %s\n",
+		   chtostr(result.module_rev, 8));
 
-	len += sprintf(buf+len, "Serial number       : ");
-	len = print_serial_number(buf, len, result.serial_number, sizeof(result)-36);
-				/* allow for SNLen plus possible trailing '\0' */
+	seq_printf(seq, "Serial number       : ");
+	print_serial_number(seq, result.serial_number, sizeof(result) - 36);
+	/* allow for SNLen plus possible trailing '\0' */
 
-	len += sprintf(buf+len, "\n");
+	seq_printf(seq, "\n");
 
-	spin_unlock(&i2o_proc_lock);
-
-	return len;
+	return 0;
 }
 
 /* Generic group F102h - User Information (scalar) */
-int i2o_proc_read_uinfo(char *buf, char **start, off_t offset, int len, 
-			int *eof, void *data)
+int i2o_seq_show_uinfo(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
 	int token;
 
- 	struct
-	{
+	struct {
 		u8 device_name[64];
 		u8 service_name[64];
 		u8 physical_location[64];
 		u8 instance_number[4];
 	} result;
 
-	spin_lock(&i2o_proc_lock);
-	len = 0;
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				0xF102,	-1,
-				&result, sizeof(result));
+	token = i2o_parm_field_get(d, 0xF102, -1, &result, sizeof(result));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0xF102 User Information");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		i2o_report_query_status(seq, token, "0xF102 User Information");
+		return 0;
 	}
 
-	len += sprintf(buf,     "Device name     : %s\n", chtostr(result.device_name, 64));
-	len += sprintf(buf+len, "Service name    : %s\n", chtostr(result.service_name, 64));
-	len += sprintf(buf+len, "Physical name   : %s\n", chtostr(result.physical_location, 64));
-	len += sprintf(buf+len, "Instance number : %s\n", chtostr(result.instance_number, 4));
+	seq_printf(seq, "Device name     : %s\n",
+		   chtostr(result.device_name, 64));
+	seq_printf(seq, "Service name    : %s\n",
+		   chtostr(result.service_name, 64));
+	seq_printf(seq, "Physical name   : %s\n",
+		   chtostr(result.physical_location, 64));
+	seq_printf(seq, "Instance number : %s\n",
+		   chtostr(result.instance_number, 4));
 
-	spin_unlock(&i2o_proc_lock);
-	return len;
+	return 0;
 }
 
 /* Generic group F103h - SGL Operating Limits (scalar) */
-int i2o_proc_read_sgl_limits(char *buf, char **start, off_t offset, int len, 
-			     int *eof, void *data)
+int i2o_seq_show_sgl_limits(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
 	static u32 work32[12];
-	static u16 *work16 = (u16 *)work32;
-	static u8 *work8 = (u8 *)work32;
+	static u16 *work16 = (u16 *) work32;
+	static u8 *work8 = (u8 *) work32;
 	int token;
 
-	spin_lock(&i2o_proc_lock);
-	
-	len = 0;
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid, 
-				 0xF103, -1,
-				 &work32, sizeof(work32));
+	token = i2o_parm_field_get(d, 0xF103, -1, &work32, sizeof(work32));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0xF103 SGL Operating Limits");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		i2o_report_query_status(seq, token,
+					"0xF103 SGL Operating Limits");
+		return 0;
 	}
 
-	len += sprintf(buf,     "SGL chain size        : %d\n", work32[0]);
-	len += sprintf(buf+len, "Max SGL chain size    : %d\n", work32[1]);
-	len += sprintf(buf+len, "SGL chain size target : %d\n", work32[2]);
-	len += sprintf(buf+len, "SGL frag count        : %d\n", work16[6]);
-	len += sprintf(buf+len, "Max SGL frag count    : %d\n", work16[7]);
-	len += sprintf(buf+len, "SGL frag count target : %d\n", work16[8]);
+	seq_printf(seq, "SGL chain size        : %d\n", work32[0]);
+	seq_printf(seq, "Max SGL chain size    : %d\n", work32[1]);
+	seq_printf(seq, "SGL chain size target : %d\n", work32[2]);
+	seq_printf(seq, "SGL frag count        : %d\n", work16[6]);
+	seq_printf(seq, "Max SGL frag count    : %d\n", work16[7]);
+	seq_printf(seq, "SGL frag count target : %d\n", work16[8]);
 
+/* FIXME
 	if (d->i2oversion == 0x02)
 	{
-		len += sprintf(buf+len, "SGL data alignment    : %d\n", work16[8]);
-		len += sprintf(buf+len, "SGL addr limit        : %d\n", work8[20]);
-		len += sprintf(buf+len, "SGL addr sizes supported : ");
-		if (work8[21] & 0x01)
-			len += sprintf(buf+len, "32 bit ");
-		if (work8[21] & 0x02)
-			len += sprintf(buf+len, "64 bit ");
-		if (work8[21] & 0x04)
-			len += sprintf(buf+len, "96 bit ");
-		if (work8[21] & 0x08)
-			len += sprintf(buf+len, "128 bit ");
-		len += sprintf(buf+len, "\n");
+*/
+	seq_printf(seq, "SGL data alignment    : %d\n", work16[8]);
+	seq_printf(seq, "SGL addr limit        : %d\n", work8[20]);
+	seq_printf(seq, "SGL addr sizes supported : ");
+	if (work8[21] & 0x01)
+		seq_printf(seq, "32 bit ");
+	if (work8[21] & 0x02)
+		seq_printf(seq, "64 bit ");
+	if (work8[21] & 0x04)
+		seq_printf(seq, "96 bit ");
+	if (work8[21] & 0x08)
+		seq_printf(seq, "128 bit ");
+	seq_printf(seq, "\n");
+/*
 	}
+*/
 
-	spin_unlock(&i2o_proc_lock);
-
-	return len;
+	return 0;
 }
 
 /* Generic group F200h - Sensors (scalar) */
-int i2o_proc_read_sensors(char *buf, char **start, off_t offset, int len,
-			  int *eof, void *data)
+int i2o_seq_show_sensors(struct seq_file *seq, void *v)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
+	struct i2o_device *d = (struct i2o_device *)seq->private;
 	int token;
 
-	struct
-	{
+	struct {
 		u16 sensor_instance;
-		u8  component;
+		u8 component;
 		u16 component_instance;
-		u8  sensor_class;
-		u8  sensor_type;
-		u8  scaling_exponent;
+		u8 sensor_class;
+		u8 sensor_type;
+		u8 scaling_exponent;
 		u32 actual_reading;
 		u32 minimum_reading;
 		u32 low2lowcat_treshold;
@@ -1615,1795 +1455,663 @@ int i2o_proc_read_sensors(char *buf, char **start, off_t offset, int len,
 		u32 hicat2high_treshold;
 		u32 hi2hicat_treshold;
 		u32 maximum_reading;
-		u8  sensor_state;
+		u8 sensor_state;
 		u16 event_enable;
 	} result;
-	
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
 
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0xF200, -1,
-				 &result, sizeof(result));
+	token = i2o_parm_field_get(d, 0xF200, -1, &result, sizeof(result));
 
 	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0xF200 Sensors (optional)");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+		i2o_report_query_status(seq, token,
+					"0xF200 Sensors (optional)");
+		return 0;
 	}
-	
-	len += sprintf(buf+len, "Sensor instance       : %d\n", result.sensor_instance);
 
-	len += sprintf(buf+len, "Component             : %d = ", result.component);
-	switch (result.component)
-	{
-	case 0:	len += sprintf(buf+len, "Other");		
+	seq_printf(seq, "Sensor instance       : %d\n", result.sensor_instance);
+
+	seq_printf(seq, "Component             : %d = ", result.component);
+	switch (result.component) {
+	case 0:
+		seq_printf(seq, "Other");
 		break;
-	case 1: len += sprintf(buf+len, "Planar logic Board");
+	case 1:
+		seq_printf(seq, "Planar logic Board");
 		break;
-	case 2: len += sprintf(buf+len, "CPU");
+	case 2:
+		seq_printf(seq, "CPU");
 		break;
-	case 3: len += sprintf(buf+len, "Chassis");
+	case 3:
+		seq_printf(seq, "Chassis");
 		break;
-	case 4: len += sprintf(buf+len, "Power Supply");
+	case 4:
+		seq_printf(seq, "Power Supply");
 		break;
-	case 5: len += sprintf(buf+len, "Storage");
+	case 5:
+		seq_printf(seq, "Storage");
 		break;
-	case 6: len += sprintf(buf+len, "External");
+	case 6:
+		seq_printf(seq, "External");
 		break;
-	}		
-	len += sprintf(buf+len,"\n");
+	}
+	seq_printf(seq, "\n");
 
-	len += sprintf(buf+len, "Component instance    : %d\n", result.component_instance);
-	len += sprintf(buf+len, "Sensor class          : %s\n",
-				result.sensor_class ? "Analog" : "Digital");
-	
-	len += sprintf(buf+len, "Sensor type           : %d = ",result.sensor_type);
-	switch (result.sensor_type)
-	{
-	case 0:	len += sprintf(buf+len, "Other\n");
+	seq_printf(seq, "Component instance    : %d\n",
+		   result.component_instance);
+	seq_printf(seq, "Sensor class          : %s\n",
+		   result.sensor_class ? "Analog" : "Digital");
+
+	seq_printf(seq, "Sensor type           : %d = ", result.sensor_type);
+	switch (result.sensor_type) {
+	case 0:
+		seq_printf(seq, "Other\n");
 		break;
-	case 1: len += sprintf(buf+len, "Thermal\n");
+	case 1:
+		seq_printf(seq, "Thermal\n");
 		break;
-	case 2: len += sprintf(buf+len, "DC voltage (DC volts)\n");
+	case 2:
+		seq_printf(seq, "DC voltage (DC volts)\n");
 		break;
-	case 3: len += sprintf(buf+len, "AC voltage (AC volts)\n");
+	case 3:
+		seq_printf(seq, "AC voltage (AC volts)\n");
 		break;
-	case 4: len += sprintf(buf+len, "DC current (DC amps)\n");
+	case 4:
+		seq_printf(seq, "DC current (DC amps)\n");
 		break;
-	case 5: len += sprintf(buf+len, "AC current (AC volts)\n");
+	case 5:
+		seq_printf(seq, "AC current (AC volts)\n");
 		break;
-	case 6: len += sprintf(buf+len, "Door open\n");
+	case 6:
+		seq_printf(seq, "Door open\n");
 		break;
-	case 7: len += sprintf(buf+len, "Fan operational\n");
+	case 7:
+		seq_printf(seq, "Fan operational\n");
 		break;
- 	}			
+	}
 
-	len += sprintf(buf+len, "Scaling exponent      : %d\n", result.scaling_exponent);
-	len += sprintf(buf+len, "Actual reading        : %d\n", result.actual_reading);
-	len += sprintf(buf+len, "Minimum reading       : %d\n", result.minimum_reading);
-	len += sprintf(buf+len, "Low2LowCat treshold   : %d\n", result.low2lowcat_treshold);
-	len += sprintf(buf+len, "LowCat2Low treshold   : %d\n", result.lowcat2low_treshold);
-	len += sprintf(buf+len, "LowWarn2Low treshold  : %d\n", result.lowwarn2low_treshold);
-	len += sprintf(buf+len, "Low2LowWarn treshold  : %d\n", result.low2lowwarn_treshold);
-	len += sprintf(buf+len, "Norm2LowWarn treshold : %d\n", result.norm2lowwarn_treshold);
-	len += sprintf(buf+len, "LowWarn2Norm treshold : %d\n", result.lowwarn2norm_treshold);
-	len += sprintf(buf+len, "Nominal reading       : %d\n", result.nominal_reading);
-	len += sprintf(buf+len, "HiWarn2Norm treshold  : %d\n", result.hiwarn2norm_treshold);
-	len += sprintf(buf+len, "Norm2HiWarn treshold  : %d\n", result.norm2hiwarn_treshold);
-	len += sprintf(buf+len, "High2HiWarn treshold  : %d\n", result.high2hiwarn_treshold);
-	len += sprintf(buf+len, "HiWarn2High treshold  : %d\n", result.hiwarn2high_treshold);
-	len += sprintf(buf+len, "HiCat2High treshold   : %d\n", result.hicat2high_treshold);
-	len += sprintf(buf+len, "High2HiCat treshold   : %d\n", result.hi2hicat_treshold);
-	len += sprintf(buf+len, "Maximum reading       : %d\n", result.maximum_reading);
+	seq_printf(seq, "Scaling exponent      : %d\n",
+		   result.scaling_exponent);
+	seq_printf(seq, "Actual reading        : %d\n", result.actual_reading);
+	seq_printf(seq, "Minimum reading       : %d\n", result.minimum_reading);
+	seq_printf(seq, "Low2LowCat treshold   : %d\n",
+		   result.low2lowcat_treshold);
+	seq_printf(seq, "LowCat2Low treshold   : %d\n",
+		   result.lowcat2low_treshold);
+	seq_printf(seq, "LowWarn2Low treshold  : %d\n",
+		   result.lowwarn2low_treshold);
+	seq_printf(seq, "Low2LowWarn treshold  : %d\n",
+		   result.low2lowwarn_treshold);
+	seq_printf(seq, "Norm2LowWarn treshold : %d\n",
+		   result.norm2lowwarn_treshold);
+	seq_printf(seq, "LowWarn2Norm treshold : %d\n",
+		   result.lowwarn2norm_treshold);
+	seq_printf(seq, "Nominal reading       : %d\n", result.nominal_reading);
+	seq_printf(seq, "HiWarn2Norm treshold  : %d\n",
+		   result.hiwarn2norm_treshold);
+	seq_printf(seq, "Norm2HiWarn treshold  : %d\n",
+		   result.norm2hiwarn_treshold);
+	seq_printf(seq, "High2HiWarn treshold  : %d\n",
+		   result.high2hiwarn_treshold);
+	seq_printf(seq, "HiWarn2High treshold  : %d\n",
+		   result.hiwarn2high_treshold);
+	seq_printf(seq, "HiCat2High treshold   : %d\n",
+		   result.hicat2high_treshold);
+	seq_printf(seq, "High2HiCat treshold   : %d\n",
+		   result.hi2hicat_treshold);
+	seq_printf(seq, "Maximum reading       : %d\n", result.maximum_reading);
 
-	len += sprintf(buf+len, "Sensor state          : %d = ", result.sensor_state);
-	switch (result.sensor_state)
-	{
-	case 0:	 len += sprintf(buf+len, "Normal\n");
-		 break;
-	case 1:  len += sprintf(buf+len, "Abnormal\n");
-		 break;
-	case 2:  len += sprintf(buf+len, "Unknown\n");
-		 break;
-	case 3:  len += sprintf(buf+len, "Low Catastrophic (LoCat)\n");
-		 break;
-	case 4:  len += sprintf(buf+len, "Low (Low)\n");
-		 break;
-	case 5:  len += sprintf(buf+len, "Low Warning (LoWarn)\n");
-		 break;
-	case 6:  len += sprintf(buf+len, "High Warning (HiWarn)\n");
-		 break;
-	case 7:  len += sprintf(buf+len, "High (High)\n");
-		 break;
-	case 8:  len += sprintf(buf+len, "High Catastrophic (HiCat)\n");
-		 break;
-	}			
-
-	len += sprintf(buf+len, "Event_enable : 0x%02X\n", result.event_enable);
-	len += sprintf(buf+len, "    [%s] Operational state change. \n",
-			(result.event_enable & 0x01) ? "+" : "-" );
-	len += sprintf(buf+len, "    [%s] Low catastrophic. \n",
-			(result.event_enable & 0x02) ? "+" : "-" );
-	len += sprintf(buf+len, "    [%s] Low reading. \n",
-			(result.event_enable & 0x04) ? "+" : "-" );
-	len += sprintf(buf+len, "    [%s] Low warning. \n",
-			(result.event_enable & 0x08) ? "+" : "-" );
-	len += sprintf(buf+len, "    [%s] Change back to normal from out of range state. \n",
-			(result.event_enable & 0x10) ? "+" : "-" );
-	len += sprintf(buf+len, "    [%s] High warning. \n",
-			(result.event_enable & 0x20) ? "+" : "-" );
-	len += sprintf(buf+len, "    [%s] High reading. \n",
-			(result.event_enable & 0x40) ? "+" : "-" );
-	len += sprintf(buf+len, "    [%s] High catastrophic. \n",
-			(result.event_enable & 0x80) ? "+" : "-" );
-
-	spin_unlock(&i2o_proc_lock);
-	return len;
+	seq_printf(seq, "Sensor state          : %d = ", result.sensor_state);
+	switch (result.sensor_state) {
+	case 0:
+		seq_printf(seq, "Normal\n");
+		break;
+	case 1:
+		seq_printf(seq, "Abnormal\n");
+		break;
+	case 2:
+		seq_printf(seq, "Unknown\n");
+		break;
+	case 3:
+		seq_printf(seq, "Low Catastrophic (LoCat)\n");
+		break;
+	case 4:
+		seq_printf(seq, "Low (Low)\n");
+		break;
+	case 5:
+		seq_printf(seq, "Low Warning (LoWarn)\n");
+		break;
+	case 6:
+		seq_printf(seq, "High Warning (HiWarn)\n");
+		break;
+	case 7:
+		seq_printf(seq, "High (High)\n");
+		break;
+	case 8:
+		seq_printf(seq, "High Catastrophic (HiCat)\n");
+		break;
+	}
+
+	seq_printf(seq, "Event_enable : 0x%02X\n", result.event_enable);
+	seq_printf(seq, "    [%s] Operational state change. \n",
+		   (result.event_enable & 0x01) ? "+" : "-");
+	seq_printf(seq, "    [%s] Low catastrophic. \n",
+		   (result.event_enable & 0x02) ? "+" : "-");
+	seq_printf(seq, "    [%s] Low reading. \n",
+		   (result.event_enable & 0x04) ? "+" : "-");
+	seq_printf(seq, "    [%s] Low warning. \n",
+		   (result.event_enable & 0x08) ? "+" : "-");
+	seq_printf(seq,
+		   "    [%s] Change back to normal from out of range state. \n",
+		   (result.event_enable & 0x10) ? "+" : "-");
+	seq_printf(seq, "    [%s] High warning. \n",
+		   (result.event_enable & 0x20) ? "+" : "-");
+	seq_printf(seq, "    [%s] High reading. \n",
+		   (result.event_enable & 0x40) ? "+" : "-");
+	seq_printf(seq, "    [%s] High catastrophic. \n",
+		   (result.event_enable & 0x80) ? "+" : "-");
+
+	return 0;
 }
 
+static int i2o_seq_open_hrt(struct inode *inode, struct file *file)
+{
+	return single_open(file, i2o_seq_show_hrt, PDE(inode)->data);
+};
 
-static int print_serial_number(char *buff, int pos, u8 *serialno, int max_len)
+static int i2o_seq_open_lct(struct inode *inode, struct file *file)
 {
-	int i;
+	return single_open(file, i2o_seq_show_lct, PDE(inode)->data);
+};
 
-	/* 19990419 -sralston
-	 *	The I2O v1.5 (and v2.0 so far) "official specification"
-	 *	got serial numbers WRONG!
-	 *	Apparently, and despite what Section 3.4.4 says and
-	 *	Figure 3-35 shows (pg 3-39 in the pdf doc),
-	 *	the convention / consensus seems to be:
-	 *	  + First byte is SNFormat
-	 *	  + Second byte is SNLen (but only if SNFormat==7 (?))
-	 *	  + (v2.0) SCSI+BS may use IEEE Registered (64 or 128 bit) format
-	 */
-	switch(serialno[0])
-	{
-		case I2O_SNFORMAT_BINARY:		/* Binary */
-			pos += sprintf(buff+pos, "0x");
-			for(i = 0; i < serialno[1]; i++)
-			{
-				pos += sprintf(buff+pos, "%02X", serialno[2+i]);
-			}
-			break;
-	
-		case I2O_SNFORMAT_ASCII:		/* ASCII */
-			if ( serialno[1] < ' ' )	/* printable or SNLen? */
-			{
-				/* sanity */
-				max_len = (max_len < serialno[1]) ? max_len : serialno[1];
-				serialno[1+max_len] = '\0';
-
-				/* just print it */
-				pos += sprintf(buff+pos, "%s", &serialno[2]);
-			}
-			else
-			{
-				/* print chars for specified length */
-				for(i = 0; i < serialno[1]; i++)
-				{
-					pos += sprintf(buff+pos, "%c", serialno[2+i]);
-				}
-			}
-			break;
+static int i2o_seq_open_status(struct inode *inode, struct file *file)
+{
+	return single_open(file, i2o_seq_show_status, PDE(inode)->data);
+};
 
-		case I2O_SNFORMAT_UNICODE:		/* UNICODE */
-			pos += sprintf(buff+pos, "UNICODE Format.  Can't Display\n");
-			break;
+static int i2o_seq_open_hw(struct inode *inode, struct file *file)
+{
+	return single_open(file, i2o_seq_show_hw, PDE(inode)->data);
+};
 
-		case I2O_SNFORMAT_LAN48_MAC:		/* LAN-48 MAC Address */
-			pos += sprintf(buff+pos, 
-						"LAN-48 MAC address @ %02X:%02X:%02X:%02X:%02X:%02X",
-						serialno[2], serialno[3],
-						serialno[4], serialno[5],
-						serialno[6], serialno[7]);
-			break;
+static int i2o_seq_open_ddm_table(struct inode *inode, struct file *file)
+{
+	return single_open(file, i2o_seq_show_ddm_table, PDE(inode)->data);
+};
 
-		case I2O_SNFORMAT_WAN:			/* WAN MAC Address */
-			/* FIXME: Figure out what a WAN access address looks like?? */
-			pos += sprintf(buff+pos, "WAN Access Address");
-			break;
+static int i2o_seq_open_driver_store(struct inode *inode, struct file *file)
+{
+	return single_open(file, i2o_seq_show_driver_store, PDE(inode)->data);
+};
 
-/* plus new in v2.0 */
-		case I2O_SNFORMAT_LAN64_MAC:		/* LAN-64 MAC Address */
-			/* FIXME: Figure out what a LAN-64 address really looks like?? */
-			pos += sprintf(buff+pos, 
-						"LAN-64 MAC address @ [?:%02X:%02X:?] %02X:%02X:%02X:%02X:%02X:%02X",
-						serialno[8], serialno[9],
-						serialno[2], serialno[3],
-						serialno[4], serialno[5],
-						serialno[6], serialno[7]);
-			break;
+static int i2o_seq_open_drivers_stored(struct inode *inode, struct file *file)
+{
+	return single_open(file, i2o_seq_show_drivers_stored, PDE(inode)->data);
+};
 
+static int i2o_seq_open_groups(struct inode *inode, struct file *file)
+{
+	return single_open(file, i2o_seq_show_groups, PDE(inode)->data);
+};
 
-		case I2O_SNFORMAT_DDM:			/* I2O DDM */
-			pos += sprintf(buff+pos, 
-						"DDM: Tid=%03Xh, Rsvd=%04Xh, OrgId=%04Xh",
-						*(u16*)&serialno[2],
-						*(u16*)&serialno[4],
-						*(u16*)&serialno[6]);
-			break;
+static int i2o_seq_open_phys_device(struct inode *inode, struct file *file)
+{
+	return single_open(file, i2o_seq_show_phys_device, PDE(inode)->data);
+};
 
-		case I2O_SNFORMAT_IEEE_REG64:		/* IEEE Registered (64-bit) */
-		case I2O_SNFORMAT_IEEE_REG128:		/* IEEE Registered (128-bit) */
-			/* FIXME: Figure if this is even close?? */
-			pos += sprintf(buff+pos, 
-						"IEEE NodeName(hi,lo)=(%08Xh:%08Xh), PortName(hi,lo)=(%08Xh:%08Xh)\n",
-						*(u32*)&serialno[2],
-						*(u32*)&serialno[6],
-						*(u32*)&serialno[10],
-						*(u32*)&serialno[14]);
-			break;
+static int i2o_seq_open_claimed(struct inode *inode, struct file *file)
+{
+	return single_open(file, i2o_seq_show_claimed, PDE(inode)->data);
+};
 
+static int i2o_seq_open_users(struct inode *inode, struct file *file)
+{
+	return single_open(file, i2o_seq_show_users, PDE(inode)->data);
+};
 
-		case I2O_SNFORMAT_UNKNOWN:		/* Unknown 0    */
-		case I2O_SNFORMAT_UNKNOWN2:		/* Unknown 0xff */
-		default:
-			pos += sprintf(buff+pos, "Unknown data format (0x%02x)",
-				       serialno[0]);
-			break;
-	}
+static int i2o_seq_open_priv_msgs(struct inode *inode, struct file *file)
+{
+	return single_open(file, i2o_seq_show_priv_msgs, PDE(inode)->data);
+};
 
-	return pos;
-}
+static int i2o_seq_open_authorized_users(struct inode *inode, struct file *file)
+{
+	return single_open(file, i2o_seq_show_authorized_users,
+			   PDE(inode)->data);
+};
 
-const char * i2o_get_connector_type(int conn)
+static int i2o_seq_open_dev_identity(struct inode *inode, struct file *file)
 {
-	int idx = 16;
-	static char *i2o_connector_type[] = {
-		"OTHER",
-		"UNKNOWN",
-		"AUI",
-		"UTP",
-		"BNC",
-		"RJ45",
-		"STP DB9",
-		"FIBER MIC",
-		"APPLE AUI",
-		"MII",
-		"DB9",
-		"HSSDC",
-		"DUPLEX SC FIBER",
-		"DUPLEX ST FIBER",
-		"TNC/BNC",
-		"HW DEFAULT"
-	};
+	return single_open(file, i2o_seq_show_dev_identity, PDE(inode)->data);
+};
 
-	switch(conn)
-	{
-	case 0x00000000:
-		idx = 0;
-		break;
-	case 0x00000001:
-		idx = 1;
-		break;
-	case 0x00000002:
-		idx = 2;
-		break;
-	case 0x00000003:
-		idx = 3;
-		break;
-	case 0x00000004:
-		idx = 4;
-		break;
-	case 0x00000005:
-		idx = 5;
-		break;
-	case 0x00000006:
-		idx = 6;
-		break;
-	case 0x00000007:
-		idx = 7;
-		break;
-	case 0x00000008:
-		idx = 8;
-		break;
-	case 0x00000009:
-		idx = 9;
-		break;
-	case 0x0000000A:
-		idx = 10;
-		break;
-	case 0x0000000B:
-		idx = 11;
-		break;
-	case 0x0000000C:
-		idx = 12;
-		break;
-	case 0x0000000D:
-		idx = 13;
-		break;
-	case 0x0000000E:
-		idx = 14;
-		break;
-	case 0xFFFFFFFF:
-		idx = 15;
-		break;
-	}
+static int i2o_seq_open_ddm_identity(struct inode *inode, struct file *file)
+{
+	return single_open(file, i2o_seq_show_ddm_identity, PDE(inode)->data);
+};
 
-	return i2o_connector_type[idx];
-}
+static int i2o_seq_open_uinfo(struct inode *inode, struct file *file)
+{
+	return single_open(file, i2o_seq_show_uinfo, PDE(inode)->data);
+};
 
+static int i2o_seq_open_sgl_limits(struct inode *inode, struct file *file)
+{
+	return single_open(file, i2o_seq_show_sgl_limits, PDE(inode)->data);
+};
 
-const char * i2o_get_connection_type(int conn)
+static int i2o_seq_open_sensors(struct inode *inode, struct file *file)
 {
-	int idx = 0;
-	static char *i2o_connection_type[] = {
-		"Unknown",
-		"AUI",
-		"10BASE5",
-		"FIORL",
-		"10BASE2",
-		"10BROAD36",
-		"10BASE-T",
-		"10BASE-FP",
-		"10BASE-FB",
-		"10BASE-FL",
-		"100BASE-TX",
-		"100BASE-FX",
-		"100BASE-T4",
-		"1000BASE-SX",
-		"1000BASE-LX",
-		"1000BASE-CX",
-		"1000BASE-T",
-		"100VG-ETHERNET",
-		"100VG-TOKEN RING",
-		"4MBIT TOKEN RING",
-		"16 Mb Token Ring",
-		"125 MBAUD FDDI",
-		"Point-to-point",
-		"Arbitrated loop",
-		"Public loop",
-		"Fabric",
-		"Emulation",
-		"Other",
-		"HW default"
-	};
+	return single_open(file, i2o_seq_show_sensors, PDE(inode)->data);
+};
 
-	switch(conn)
-	{
-	case I2O_LAN_UNKNOWN:
-		idx = 0;
-		break;
-	case I2O_LAN_AUI:
-		idx = 1;
-		break;
-	case I2O_LAN_10BASE5:
-		idx = 2;
-		break;
-	case I2O_LAN_FIORL:
-		idx = 3;
-		break;
-	case I2O_LAN_10BASE2:
-		idx = 4;
-		break;
-	case I2O_LAN_10BROAD36:
-		idx = 5;
-		break;
-	case I2O_LAN_10BASE_T:
-		idx = 6;
-		break;
-	case I2O_LAN_10BASE_FP:
-		idx = 7;
-		break;
-	case I2O_LAN_10BASE_FB:
-		idx = 8;
-		break;
-	case I2O_LAN_10BASE_FL:
-		idx = 9;
-		break;
-	case I2O_LAN_100BASE_TX:
-		idx = 10;
-		break;
-	case I2O_LAN_100BASE_FX:
-		idx = 11;
-		break;
-	case I2O_LAN_100BASE_T4:
-		idx = 12;
-		break;
-	case I2O_LAN_1000BASE_SX:
-		idx = 13;
-		break;
-	case I2O_LAN_1000BASE_LX:
-		idx = 14;
-		break;
-	case I2O_LAN_1000BASE_CX:
-		idx = 15;
-		break;
-	case I2O_LAN_1000BASE_T:
-		idx = 16;
-		break;
-	case I2O_LAN_100VG_ETHERNET:
-		idx = 17;
-		break;
-	case I2O_LAN_100VG_TR:
-		idx = 18;
-		break;
-	case I2O_LAN_4MBIT:
-		idx = 19;
-		break;
-	case I2O_LAN_16MBIT:
-		idx = 20;
-		break;
-	case I2O_LAN_125MBAUD:
-		idx = 21;
-		break;
-	case I2O_LAN_POINT_POINT:
-		idx = 22;
-		break;
-	case I2O_LAN_ARB_LOOP:
-		idx = 23;
-		break;
-	case I2O_LAN_PUBLIC_LOOP:
-		idx = 24;
-		break;
-	case I2O_LAN_FABRIC:
-		idx = 25;
-		break;
-	case I2O_LAN_EMULATION:
-		idx = 26;
-		break;
-	case I2O_LAN_OTHER:
-		idx = 27;
-		break;
-	case I2O_LAN_DEFAULT:
-		idx = 28;
-		break;
-	}
-
-	return i2o_connection_type[idx];
-}
-
-
-/* LAN group 0000h - Device info (scalar) */
-int i2o_proc_read_lan_dev_info(char *buf, char **start, off_t offset, int len, 
-			       int *eof, void *data)
-{
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u32 work32[56];
-	static u8 *work8 = (u8*)work32;
-	static u16 *work16 = (u16*)work32;
-	static u64 *work64 = (u64*)work32;
-	int token;
-
-	spin_lock(&i2o_proc_lock);
-	len = 0;
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0000, -1, &work32, 56*4);
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token, "0x0000 LAN Device Info");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
-
-	len += sprintf(buf, "LAN Type            : ");
-	switch (work16[0])
-	{
-	case 0x0030:
-		len += sprintf(buf+len, "Ethernet, ");
-		break;
-	case 0x0040:
-		len += sprintf(buf+len, "100Base VG, ");
-		break;
-	case 0x0050:
-		len += sprintf(buf+len, "Token Ring, ");
-		break;
-	case 0x0060:
-		len += sprintf(buf+len, "FDDI, ");
-		break;
-	case 0x0070:
-		len += sprintf(buf+len, "Fibre Channel, ");
-		break;
-	default:
-		len += sprintf(buf+len, "Unknown type (0x%04x), ", work16[0]);
-		break;
-	}
-
-	if (work16[1]&0x00000001)
-		len += sprintf(buf+len, "emulated LAN, ");
-	else
-		len += sprintf(buf+len, "physical LAN port, ");
-
-	if (work16[1]&0x00000002)
-		len += sprintf(buf+len, "full duplex\n");
-	else
-		len += sprintf(buf+len, "simplex\n");
-
-	len += sprintf(buf+len, "Address format      : ");
-	switch(work8[4]) {
-	case 0x00:
-		len += sprintf(buf+len, "IEEE 48bit\n");
-		break;
-	case 0x01:
-		len += sprintf(buf+len, "FC IEEE\n");
-		break;
-	default:
-		len += sprintf(buf+len, "Unknown (0x%02x)\n", work8[4]);
-		break;
-	}
-
-	len += sprintf(buf+len, "State               : ");
-	switch(work8[5])
-	{
-	case 0x00:
-		len += sprintf(buf+len, "Unknown\n");
-		break;
-	case 0x01:
-		len += sprintf(buf+len, "Unclaimed\n");
-		break;
-	case 0x02:
-		len += sprintf(buf+len, "Operational\n");
-		break;
-	case 0x03:
-		len += sprintf(buf+len, "Suspended\n");
-		break;
-	case 0x04:
-		len += sprintf(buf+len, "Resetting\n");
-		break;
-	case 0x05:
-		len += sprintf(buf+len, "ERROR: ");
-		if(work16[3]&0x0001)
-			len += sprintf(buf+len, "TxCU inoperative ");
-		if(work16[3]&0x0002)
-			len += sprintf(buf+len, "RxCU inoperative ");
-		if(work16[3]&0x0004)
-			len += sprintf(buf+len, "Local mem alloc ");
-		len += sprintf(buf+len, "\n");
-		break;
-	case 0x06:
-		len += sprintf(buf+len, "Operational no Rx\n");
-		break;
-	case 0x07:
-		len += sprintf(buf+len, "Suspended no Rx\n");
-		break;
-	default:
-		len += sprintf(buf+len, "Unspecified\n");
-		break;
-	}
-
-	len += sprintf(buf+len, "Min packet size     : %d\n", work32[2]);
-	len += sprintf(buf+len, "Max packet size     : %d\n", work32[3]);
-	len += sprintf(buf+len, "HW address          : "
-		       "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-		       work8[16],work8[17],work8[18],work8[19],
-		       work8[20],work8[21],work8[22],work8[23]);
-
-	len += sprintf(buf+len, "Max Tx wire speed   : %d bps\n", (int)work64[3]);
-	len += sprintf(buf+len, "Max Rx wire speed   : %d bps\n", (int)work64[4]);
-
-	len += sprintf(buf+len, "Min SDU packet size : 0x%08x\n", work32[10]);
-	len += sprintf(buf+len, "Max SDU packet size : 0x%08x\n", work32[11]);
-
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
-
-/* LAN group 0001h - MAC address table (scalar) */
-int i2o_proc_read_lan_mac_addr(char *buf, char **start, off_t offset, int len, 
-			       int *eof, void *data)
-{
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u32 work32[48];
-	static u8 *work8 = (u8*)work32;
-	int token;
-
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0001, -1, &work32, 48*4);
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0001 LAN MAC Address");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
-
-	len += sprintf(buf,     "Active address          : "
-		       "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-		       work8[0],work8[1],work8[2],work8[3],
-		       work8[4],work8[5],work8[6],work8[7]);
-	len += sprintf(buf+len, "Current address         : "
-		       "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-		       work8[8],work8[9],work8[10],work8[11],
-		       work8[12],work8[13],work8[14],work8[15]);
-	len += sprintf(buf+len, "Functional address mask : "
-		       "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-		       work8[16],work8[17],work8[18],work8[19],
-		       work8[20],work8[21],work8[22],work8[23]);
-
-	len += sprintf(buf+len,"HW/DDM capabilities : 0x%08x\n", work32[7]);
-	len += sprintf(buf+len,"    [%s] Unicast packets supported\n",
-		       (work32[7]&0x00000001)?"+":"-");
-	len += sprintf(buf+len,"    [%s] Promiscuous mode supported\n",
-		       (work32[7]&0x00000002)?"+":"-");
-	len += sprintf(buf+len,"    [%s] Promiscuous multicast mode supported\n",
-		       (work32[7]&0x00000004)?"+":"-");
-	len += sprintf(buf+len,"    [%s] Broadcast reception disabling supported\n",
-		       (work32[7]&0x00000100)?"+":"-");
-	len += sprintf(buf+len,"    [%s] Multicast reception disabling supported\n",
-		       (work32[7]&0x00000200)?"+":"-");
-	len += sprintf(buf+len,"    [%s] Functional address disabling supported\n",
-		       (work32[7]&0x00000400)?"+":"-");
-	len += sprintf(buf+len,"    [%s] MAC reporting supported\n",
-		       (work32[7]&0x00000800)?"+":"-");
-
-	len += sprintf(buf+len,"Filter mask : 0x%08x\n", work32[6]);
-	len += sprintf(buf+len,"    [%s] Unicast packets disable\n",
-		(work32[6]&0x00000001)?"+":"-");
-	len += sprintf(buf+len,"    [%s] Promiscuous mode enable\n",
-		(work32[6]&0x00000002)?"+":"-");
-	len += sprintf(buf+len,"    [%s] Promiscuous multicast mode enable\n",
-		(work32[6]&0x00000004)?"+":"-");	
-	len += sprintf(buf+len,"    [%s] Broadcast packets disable\n",
-		(work32[6]&0x00000100)?"+":"-");
-	len += sprintf(buf+len,"    [%s] Multicast packets disable\n",
-		(work32[6]&0x00000200)?"+":"-");
-	len += sprintf(buf+len,"    [%s] Functional address disable\n",
-		       (work32[6]&0x00000400)?"+":"-");
-		       
-	if (work32[7]&0x00000800) {
-		len += sprintf(buf+len, "    MAC reporting mode : ");
-		if (work32[6]&0x00000800)
-			len += sprintf(buf+len, "Pass only priority MAC packets to user\n");
-		else if (work32[6]&0x00001000)
-			len += sprintf(buf+len, "Pass all MAC packets to user\n");
-		else if (work32[6]&0x00001800)
-			len += sprintf(buf+len, "Pass all MAC packets (promiscuous) to user\n");
-		else
-			len += sprintf(buf+len, "Do not pass MAC packets to user\n");
-	}
-	len += sprintf(buf+len, "Number of multicast addresses : %d\n", work32[8]);
-	len += sprintf(buf+len, "Perfect filtering for max %d multicast addresses\n",
-		       work32[9]);
-	len += sprintf(buf+len, "Imperfect filtering for max %d multicast addresses\n",
-		       work32[10]);
-
-	spin_unlock(&i2o_proc_lock);
-
-	return len;
-}
-
-/* LAN group 0002h - Multicast MAC address table (table) */
-int i2o_proc_read_lan_mcast_addr(char *buf, char **start, off_t offset,
-				 int len, int *eof, void *data)
-{
-	struct i2o_device *d = (struct i2o_device*)data;
-	int token;
-	int i;
-	u8 mc_addr[8];
-
-	struct
-	{
-		u16 result_count;
-		u16 pad;
-		u16 block_size;
-		u8  block_status;
-		u8  error_info_size;
-		u16 row_count;
-		u16 more_flag;
-		u8  mc_addr[256][8];
-	} *result;	
-
-	result = kmalloc(sizeof(*result), GFP_KERNEL);
-	if(!result)
-		return -ENOMEM;
-
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
-
-	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				d->controller, d->lct_data.tid, 0x0002, -1, 
-				NULL, 0, result, sizeof(*result));
-
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x002 LAN Multicast MAC Address");
-		goto out;
-	}
-
-	for (i = 0; i < result->row_count; i++)
-	{
-		memcpy(mc_addr, result->mc_addr[i], 8);
-
-		len += sprintf(buf+len, "MC MAC address[%d]: "
-			       "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-			       i, mc_addr[0], mc_addr[1], mc_addr[2],
-			       mc_addr[3], mc_addr[4], mc_addr[5],
-			       mc_addr[6], mc_addr[7]);
-	}
-out:
-	spin_unlock(&i2o_proc_lock);
-	kfree(result);
-	return len;
-}
-
-/* LAN group 0003h - Batch Control (scalar) */
-int i2o_proc_read_lan_batch_control(char *buf, char **start, off_t offset,
-				    int len, int *eof, void *data)
-{
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u32 work32[9];
-	int token;
-
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0003, -1, &work32, 9*4);
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0003 LAN Batch Control");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
-
-	len += sprintf(buf, "Batch mode ");
-	if (work32[0]&0x00000001)
-		len += sprintf(buf+len, "disabled");
-	else
-		len += sprintf(buf+len, "enabled");
-	if (work32[0]&0x00000002)
-		len += sprintf(buf+len, " (current setting)");
-	if (work32[0]&0x00000004)
-		len += sprintf(buf+len, ", forced");
-	else
-		len += sprintf(buf+len, ", toggle");
-	len += sprintf(buf+len, "\n");
-
-	len += sprintf(buf+len, "Max Rx batch count : %d\n", work32[5]);
-	len += sprintf(buf+len, "Max Rx batch delay : %d\n", work32[6]);
-	len += sprintf(buf+len, "Max Tx batch delay : %d\n", work32[7]);
-	len += sprintf(buf+len, "Max Tx batch count : %d\n", work32[8]);
-
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
-
-/* LAN group 0004h - LAN Operation (scalar) */
-int i2o_proc_read_lan_operation(char *buf, char **start, off_t offset, int len,
-				int *eof, void *data)
-{
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u32 work32[5];
-	int token;
-
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0004, -1, &work32, 20);
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0004 LAN Operation");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
-
-	len += sprintf(buf, "Packet prepadding (32b words) : %d\n", work32[0]);
-	len += sprintf(buf+len, "Transmission error reporting  : %s\n",
-		       (work32[1]&1)?"on":"off");
-	len += sprintf(buf+len, "Bad packet handling           : %s\n",
-				(work32[1]&0x2)?"by host":"by DDM");
-	len += sprintf(buf+len, "Packet orphan limit           : %d\n", work32[2]);
-
-	len += sprintf(buf+len, "Tx modes : 0x%08x\n", work32[3]);
-	len += sprintf(buf+len, "    [%s] HW CRC suppression\n",
-			(work32[3]&0x00000004) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] HW IPv4 checksum\n",
-			(work32[3]&0x00000100) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] HW TCP checksum\n",
-			(work32[3]&0x00000200) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] HW UDP checksum\n",
-			(work32[3]&0x00000400) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] HW RSVP checksum\n",
-			(work32[3]&0x00000800) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] HW ICMP checksum\n",
-			(work32[3]&0x00001000) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] Loopback suppression enable\n",
-			(work32[3]&0x00002000) ? "+" : "-");
-
-	len += sprintf(buf+len, "Rx modes : 0x%08x\n", work32[4]);
-	len += sprintf(buf+len, "    [%s] FCS in payload\n",
-			(work32[4]&0x00000004) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] HW IPv4 checksum validation\n",
-			(work32[4]&0x00000100) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] HW TCP checksum validation\n",
-			(work32[4]&0x00000200) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] HW UDP checksum validation\n",
-			(work32[4]&0x00000400) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] HW RSVP checksum validation\n",
-			(work32[4]&0x00000800) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] HW ICMP checksum validation\n",
-			(work32[4]&0x00001000) ? "+" : "-");
- 
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
-
-/* LAN group 0005h - Media operation (scalar) */
-int i2o_proc_read_lan_media_operation(char *buf, char **start, off_t offset,
-				      int len, int *eof, void *data)
-{
-	struct i2o_device *d = (struct i2o_device*)data;
-	int token;
-
-	struct
-	{
-		u32 connector_type;
-		u32 connection_type;
-		u64 current_tx_wire_speed;
-		u64 current_rx_wire_speed;
-		u8  duplex_mode;
-		u8  link_status;
-		u8  reserved;
-		u8  duplex_mode_target;
-		u32 connector_type_target;
-		u32 connection_type_target;
-	} result;	
-
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0005, -1, &result, sizeof(result));
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token, "0x0005 LAN Media Operation");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
-
-	len += sprintf(buf, "Connector type         : %s\n",
-		       i2o_get_connector_type(result.connector_type));
-	len += sprintf(buf+len, "Connection type        : %s\n",
-		       i2o_get_connection_type(result.connection_type));
-
-	len += sprintf(buf+len, "Current Tx wire speed  : %d bps\n", (int)result.current_tx_wire_speed);
-	len += sprintf(buf+len, "Current Rx wire speed  : %d bps\n", (int)result.current_rx_wire_speed);
-	len += sprintf(buf+len, "Duplex mode            : %s duplex\n",
-			(result.duplex_mode)?"Full":"Half");
-			
-	len += sprintf(buf+len, "Link status            : ");
-	switch (result.link_status)
-	{
-	case 0x00:
-		len += sprintf(buf+len, "Unknown\n");
-		break;
-	case 0x01:
-		len += sprintf(buf+len, "Normal\n");
-		break;
-	case 0x02:
-		len += sprintf(buf+len, "Failure\n");
-		break;
-	case 0x03:
-		len += sprintf(buf+len, "Reset\n");
-		break;
-	default:
-		len += sprintf(buf+len, "Unspecified\n");
-	}
-	
-	len += sprintf(buf+len, "Duplex mode target     : ");
-	switch (result.duplex_mode_target){
-		case 0:
-			len += sprintf(buf+len, "Half duplex\n");
-			break;
-		case 1:
-			len += sprintf(buf+len, "Full duplex\n");
-			break;
-		default:
-			len += sprintf(buf+len, "\n");
-	}
-
-	len += sprintf(buf+len, "Connector type target  : %s\n",
-		       i2o_get_connector_type(result.connector_type_target));
-	len += sprintf(buf+len, "Connection type target : %s\n",
-		       i2o_get_connection_type(result.connection_type_target));
-
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
-
-/* LAN group 0006h - Alternate address (table) (optional) */
-int i2o_proc_read_lan_alt_addr(char *buf, char **start, off_t offset, int len,
-			       int *eof, void *data)
+static int i2o_seq_open_dev_name(struct inode *inode, struct file *file)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
-	int token;
-	int i;
-	u8 alt_addr[8];
-	struct
-	{
-		u16 result_count;
-		u16 pad;
-		u16 block_size;
-		u8  block_status;
-		u8  error_info_size;
-		u16 row_count;
-		u16 more_flag;
-		u8  alt_addr[256][8];
-	} *result;	
-
-	result = kmalloc(sizeof(*result), GFP_KERNEL);
-	if(!result)
-		return -ENOMEM;
-
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
-
-	token = i2o_query_table(I2O_PARAMS_TABLE_GET,
-				d->controller, d->lct_data.tid,
-				0x0006, -1, NULL, 0, result, sizeof(*result));
-
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token, "0x0006 LAN Alternate Address (optional)");
-		goto out;
-	}
-
-	for (i=0; i < result->row_count; i++)
-	{
-		memcpy(alt_addr,result->alt_addr[i],8);
-		len += sprintf(buf+len, "Alternate address[%d]: "
-			       "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
-			       i, alt_addr[0], alt_addr[1], alt_addr[2],
-			       alt_addr[3], alt_addr[4], alt_addr[5],
-			       alt_addr[6], alt_addr[7]);
-	}
-out:
-	spin_unlock(&i2o_proc_lock);
-	kfree(result);
-	return len;
-}
+	return single_open(file, i2o_seq_show_dev_name, PDE(inode)->data);
+};
 
+static struct file_operations i2o_seq_fops_lct = {
+	.open = i2o_seq_open_lct,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-/* LAN group 0007h - Transmit info (scalar) */
-int i2o_proc_read_lan_tx_info(char *buf, char **start, off_t offset, int len, 
-			      int *eof, void *data)
-{
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u32 work32[8];
-	int token;
+static struct file_operations i2o_seq_fops_hrt = {
+	.open = i2o_seq_open_hrt,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
+static struct file_operations i2o_seq_fops_status = {
+	.open = i2o_seq_open_status,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0007, -1, &work32, 8*4);
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0007 LAN Transmit Info");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
+static struct file_operations i2o_seq_fops_hw = {
+	.open = i2o_seq_open_hw,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	len += sprintf(buf,     "Tx Max SG elements per packet : %d\n", work32[0]);
-	len += sprintf(buf+len, "Tx Max SG elements per chain  : %d\n", work32[1]);
-	len += sprintf(buf+len, "Tx Max outstanding packets    : %d\n", work32[2]);
-	len += sprintf(buf+len, "Tx Max packets per request    : %d\n", work32[3]);
-
-	len += sprintf(buf+len, "Tx modes : 0x%08x\n", work32[4]);
-	len += sprintf(buf+len, "    [%s] No DA in SGL\n",
-				(work32[4]&0x00000002) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] CRC suppression\n",
-				(work32[4]&0x00000004) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] MAC insertion\n",
-				(work32[4]&0x00000010) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] RIF insertion\n",
-				(work32[4]&0x00000020) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] IPv4 checksum generation\n",
-				(work32[4]&0x00000100) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] TCP checksum generation\n",
-				(work32[4]&0x00000200) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] UDP checksum generation\n",
-				(work32[4]&0x00000400) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] RSVP checksum generation\n",
-				(work32[4]&0x00000800) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] ICMP checksum generation\n",
-				(work32[4]&0x00001000) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] Loopback enabled\n",
-				(work32[4]&0x00010000) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] Loopback suppression enabled\n",
-				(work32[4]&0x00020000) ? "+" : "-");
-
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
+static struct file_operations i2o_seq_fops_ddm_table = {
+	.open = i2o_seq_open_ddm_table,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-/* LAN group 0008h - Receive info (scalar) */
-int i2o_proc_read_lan_rx_info(char *buf, char **start, off_t offset, int len, 
-			      int *eof, void *data)
-{
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u32 work32[8];
-	int token;
+static struct file_operations i2o_seq_fops_driver_store = {
+	.open = i2o_seq_open_driver_store,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
+static struct file_operations i2o_seq_fops_drivers_stored = {
+	.open = i2o_seq_open_drivers_stored,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0008, -1, &work32, 8*4);
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0008 LAN Receive Info");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
+static struct file_operations i2o_seq_fops_groups = {
+	.open = i2o_seq_open_groups,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	len += sprintf(buf     ,"Rx Max size of chain element : %d\n", work32[0]);
-	len += sprintf(buf+len, "Rx Max Buckets               : %d\n", work32[1]);
-	len += sprintf(buf+len, "Rx Max Buckets in Reply      : %d\n", work32[3]);
-	len += sprintf(buf+len, "Rx Max Packets in Bucket     : %d\n", work32[4]);
-	len += sprintf(buf+len, "Rx Max Buckets in Post       : %d\n", work32[5]);
-
-	len += sprintf(buf+len, "Rx Modes : 0x%08x\n", work32[2]);
-	len += sprintf(buf+len, "    [%s] FCS reception\n",
-				(work32[2]&0x00000004) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] IPv4 checksum validation \n",
-				(work32[2]&0x00000100) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] TCP checksum validation \n",
-				(work32[2]&0x00000200) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] UDP checksum validation \n",
-				(work32[2]&0x00000400) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] RSVP checksum validation \n",
-				(work32[2]&0x00000800) ? "+" : "-");
-	len += sprintf(buf+len, "    [%s] ICMP checksum validation \n",
-				(work32[2]&0x00001000) ? "+" : "-");
-
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
+static struct file_operations i2o_seq_fops_phys_device = {
+	.open = i2o_seq_open_phys_device,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-static int i2o_report_opt_field(char *buf, char *field_name,
-				int field_nbr, int supp_fields, u64 *value)
-{
-	if (supp_fields & (1 << field_nbr))
-		return sprintf(buf, "%-24s : " FMT_U64_HEX "\n", field_name, U64_VAL(value));
-	else	
-		return sprintf(buf, "%-24s : Not supported\n", field_name);	
-}
+static struct file_operations i2o_seq_fops_claimed = {
+	.open = i2o_seq_open_claimed,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-/* LAN group 0100h - LAN Historical statistics (scalar) */
-/* LAN group 0180h - Supported Optional Historical Statistics (scalar) */
-/* LAN group 0182h - Optional Non Media Specific Transmit Historical Statistics (scalar) */
-/* LAN group 0183h - Optional Non Media Specific Receive Historical Statistics (scalar) */
+static struct file_operations i2o_seq_fops_users = {
+	.open = i2o_seq_open_users,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-int i2o_proc_read_lan_hist_stats(char *buf, char **start, off_t offset, int len,
-				 int *eof, void *data)
-{
-	struct i2o_device *d = (struct i2o_device*)data;
-	int token;
+static struct file_operations i2o_seq_fops_priv_msgs = {
+	.open = i2o_seq_open_priv_msgs,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	struct
-	{
-		u64 tx_packets;
-		u64 tx_bytes;
-		u64 rx_packets;
-		u64 rx_bytes;
-		u64 tx_errors;
-		u64 rx_errors;
-		u64 rx_dropped;
-		u64 adapter_resets;
-		u64 adapter_suspends;
-	} stats;			// 0x0100
-
-	static u64 supp_groups[4];	// 0x0180
-
-	struct
-	{
-		u64 tx_retries;
-		u64 tx_directed_bytes;
-		u64 tx_directed_packets;
-		u64 tx_multicast_bytes;
-		u64 tx_multicast_packets;
-		u64 tx_broadcast_bytes;
-		u64 tx_broadcast_packets;
-		u64 tx_group_addr_packets;
-		u64 tx_short_packets;
-	} tx_stats;			// 0x0182
-
-	struct
-	{
-		u64 rx_crc_errors;
-		u64 rx_directed_bytes;
-		u64 rx_directed_packets;
-		u64 rx_multicast_bytes;
-		u64 rx_multicast_packets;
-		u64 rx_broadcast_bytes;
-		u64 rx_broadcast_packets;
-		u64 rx_group_addr_packets;
-		u64 rx_short_packets;
-		u64 rx_long_packets;
-		u64 rx_runt_packets;
-	} rx_stats;			// 0x0183
-
-	struct
-	{
-		u64 ipv4_generate;
-		u64 ipv4_validate_success;
-		u64 ipv4_validate_errors;
-		u64 tcp_generate;
-		u64 tcp_validate_success;
-		u64 tcp_validate_errors;
-		u64 udp_generate;
-		u64 udp_validate_success;
-		u64 udp_validate_errors;
-		u64 rsvp_generate;
-		u64 rsvp_validate_success;
-		u64 rsvp_validate_errors;		
-		u64 icmp_generate;
-		u64 icmp_validate_success;
-		u64 icmp_validate_errors;
-	} chksum_stats;			// 0x0184
-
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0100, -1, &stats, sizeof(stats));
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x100 LAN Statistics");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
+static struct file_operations i2o_seq_fops_authorized_users = {
+	.open = i2o_seq_open_authorized_users,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	len += sprintf(buf+len, "Tx packets       : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.tx_packets));
-	len += sprintf(buf+len, "Tx bytes         : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.tx_bytes));
-	len += sprintf(buf+len, "Rx packets       : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.rx_packets));
-	len += sprintf(buf+len, "Rx bytes         : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.rx_bytes));
-	len += sprintf(buf+len, "Tx errors        : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.tx_errors));
-	len += sprintf(buf+len, "Rx errors        : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.rx_errors));
-	len += sprintf(buf+len, "Rx dropped       : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.rx_dropped));
-	len += sprintf(buf+len, "Adapter resets   : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.adapter_resets));
-	len += sprintf(buf+len, "Adapter suspends : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.adapter_suspends));
-
-	/* Optional statistics follows */
-	/* Get 0x0180 to see which optional groups/fields are supported */
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0180, -1, &supp_groups, sizeof(supp_groups));
-	
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token, "0x180 LAN Supported Optional Statistics");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
+static struct file_operations i2o_seq_fops_dev_name = {
+	.open = i2o_seq_open_dev_name,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	if (supp_groups[1]) /* 0x0182 */
-	{
-		token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 	0x0182, -1, &tx_stats, sizeof(tx_stats));
+static struct file_operations i2o_seq_fops_dev_identity = {
+	.open = i2o_seq_open_dev_identity,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-		if (token < 0) {
-			len += i2o_report_query_status(buf+len, token,"0x182 LAN Optional Tx Historical Statistics");
-			spin_unlock(&i2o_proc_lock);
-			return len;
-		}
+static struct file_operations i2o_seq_fops_ddm_identity = {
+	.open = i2o_seq_open_ddm_identity,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-		len += sprintf(buf+len, "==== Optional TX statistics (group 0182h)\n");
-
-		len += i2o_report_opt_field(buf+len, "Tx RetryCount",
-					0, supp_groups[1], &tx_stats.tx_retries);
-		len += i2o_report_opt_field(buf+len, "Tx DirectedBytes",
-					1, supp_groups[1], &tx_stats.tx_directed_bytes);
-		len += i2o_report_opt_field(buf+len, "Tx DirectedPackets",
-					2, supp_groups[1], &tx_stats.tx_directed_packets);
-		len += i2o_report_opt_field(buf+len, "Tx MulticastBytes",
-					3, supp_groups[1], &tx_stats.tx_multicast_bytes);
-		len += i2o_report_opt_field(buf+len, "Tx MulticastPackets",
-					4, supp_groups[1], &tx_stats.tx_multicast_packets);
-		len += i2o_report_opt_field(buf+len, "Tx BroadcastBytes",
-					5, supp_groups[1], &tx_stats.tx_broadcast_bytes);
-		len += i2o_report_opt_field(buf+len, "Tx BroadcastPackets",
-					6, supp_groups[1], &tx_stats.tx_broadcast_packets);
-		len += i2o_report_opt_field(buf+len, "Tx TotalGroupAddrPackets",
-					7, supp_groups[1], &tx_stats.tx_group_addr_packets);
-		len += i2o_report_opt_field(buf+len, "Tx TotalPacketsTooShort",
-					8, supp_groups[1], &tx_stats.tx_short_packets);
-	}
+static struct file_operations i2o_seq_fops_uinfo = {
+	.open = i2o_seq_open_uinfo,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-	if (supp_groups[2]) /* 0x0183 */
-	{
-		token = i2o_query_scalar(d->controller, d->lct_data.tid,
-					 0x0183, -1, &rx_stats, sizeof(rx_stats));
-		if (token < 0) {
-			len += i2o_report_query_status(buf+len, token,"0x183 LAN Optional Rx Historical Stats");
-			spin_unlock(&i2o_proc_lock);
-			return len;
-		}
+static struct file_operations i2o_seq_fops_sgl_limits = {
+	.open = i2o_seq_open_sgl_limits,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-		len += sprintf(buf+len, "==== Optional RX statistics (group 0183h)\n");
-
-		len += i2o_report_opt_field(buf+len, "Rx CRCErrorCount",
-					0, supp_groups[2], &rx_stats.rx_crc_errors);
-		len += i2o_report_opt_field(buf+len, "Rx DirectedBytes",
-					1, supp_groups[2], &rx_stats.rx_directed_bytes);
-		len += i2o_report_opt_field(buf+len, "Rx DirectedPackets",
-					2, supp_groups[2], &rx_stats.rx_directed_packets);
-		len += i2o_report_opt_field(buf+len, "Rx MulticastBytes",
-					3, supp_groups[2], &rx_stats.rx_multicast_bytes);
-		len += i2o_report_opt_field(buf+len, "Rx MulticastPackets",
-					4, supp_groups[2], &rx_stats.rx_multicast_packets);
-		len += i2o_report_opt_field(buf+len, "Rx BroadcastBytes",
-					5, supp_groups[2], &rx_stats.rx_broadcast_bytes);
-		len += i2o_report_opt_field(buf+len, "Rx BroadcastPackets",
-					6, supp_groups[2], &rx_stats.rx_broadcast_packets);
-		len += i2o_report_opt_field(buf+len, "Rx TotalGroupAddrPackets",
-					7, supp_groups[2], &rx_stats.rx_group_addr_packets);
-		len += i2o_report_opt_field(buf+len, "Rx TotalPacketsTooShort",
-					8, supp_groups[2], &rx_stats.rx_short_packets);
-		len += i2o_report_opt_field(buf+len, "Rx TotalPacketsTooLong",
-					9, supp_groups[2], &rx_stats.rx_long_packets);
-		len += i2o_report_opt_field(buf+len, "Rx TotalPacketsRunt",
-					10, supp_groups[2], &rx_stats.rx_runt_packets);
-	}
-	
-	if (supp_groups[3]) /* 0x0184 */
-	{
-		token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 	0x0184, -1, &chksum_stats, sizeof(chksum_stats));
+static struct file_operations i2o_seq_fops_sensors = {
+	.open = i2o_seq_open_sensors,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
-		if (token < 0) {
-			len += i2o_report_query_status(buf+len, token,"0x184 LAN Optional Chksum Historical Stats");
-			spin_unlock(&i2o_proc_lock);
-			return len;
-		}
+/*
+ * IOP specific entries...write field just in case someone
+ * ever wants one.
+ */
+static i2o_proc_entry i2o_proc_generic_iop_entries[] = {
+	{"hrt", S_IFREG | S_IRUGO, &i2o_seq_fops_hrt},
+	{"lct", S_IFREG | S_IRUGO, &i2o_seq_fops_lct},
+	{"status", S_IFREG | S_IRUGO, &i2o_seq_fops_status},
+	{"hw", S_IFREG | S_IRUGO, &i2o_seq_fops_hw},
+	{"ddm_table", S_IFREG | S_IRUGO, &i2o_seq_fops_ddm_table},
+	{"driver_store", S_IFREG | S_IRUGO, &i2o_seq_fops_driver_store},
+	{"drivers_stored", S_IFREG | S_IRUGO, &i2o_seq_fops_drivers_stored},
+	{NULL, 0, NULL}
+};
 
-		len += sprintf(buf+len, "==== Optional CHKSUM statistics (group 0x0184)\n");
-
-		len += i2o_report_opt_field(buf+len, "IPv4 Generate",
-					0, supp_groups[3], &chksum_stats.ipv4_generate);
-		len += i2o_report_opt_field(buf+len, "IPv4 ValidateSuccess",
-					1, supp_groups[3], &chksum_stats.ipv4_validate_success);
-		len += i2o_report_opt_field(buf+len, "IPv4 ValidateError",
-					2, supp_groups[3], &chksum_stats.ipv4_validate_errors);
-		len += i2o_report_opt_field(buf+len, "TCP  Generate",
-					3, supp_groups[3], &chksum_stats.tcp_generate);
-		len += i2o_report_opt_field(buf+len, "TCP  ValidateSuccess",
-					4, supp_groups[3], &chksum_stats.tcp_validate_success);
-		len += i2o_report_opt_field(buf+len, "TCP  ValidateError",
-					5, supp_groups[3], &chksum_stats.tcp_validate_errors);
-		len += i2o_report_opt_field(buf+len, "UDP  Generate",
-					6, supp_groups[3], &chksum_stats.udp_generate);
-		len += i2o_report_opt_field(buf+len, "UDP  ValidateSuccess",
-					7, supp_groups[3], &chksum_stats.udp_validate_success);
-		len += i2o_report_opt_field(buf+len, "UDP  ValidateError",
-					8, supp_groups[3], &chksum_stats.udp_validate_errors);
-		len += i2o_report_opt_field(buf+len, "RSVP Generate",
-					9, supp_groups[3], &chksum_stats.rsvp_generate);
-		len += i2o_report_opt_field(buf+len, "RSVP ValidateSuccess",
-					10, supp_groups[3], &chksum_stats.rsvp_validate_success);
-		len += i2o_report_opt_field(buf+len, "RSVP ValidateError",
-					11, supp_groups[3], &chksum_stats.rsvp_validate_errors);
-		len += i2o_report_opt_field(buf+len, "ICMP Generate",
-					12, supp_groups[3], &chksum_stats.icmp_generate);
-		len += i2o_report_opt_field(buf+len, "ICMP ValidateSuccess",
-					13, supp_groups[3], &chksum_stats.icmp_validate_success);
-		len += i2o_report_opt_field(buf+len, "ICMP ValidateError",
-					14, supp_groups[3], &chksum_stats.icmp_validate_errors);
-	}
+/*
+ * Device specific entries
+ */
+static i2o_proc_entry generic_dev_entries[] = {
+	{"groups", S_IFREG | S_IRUGO, &i2o_seq_fops_groups},
+	{"phys_dev", S_IFREG | S_IRUGO, &i2o_seq_fops_phys_device},
+	{"claimed", S_IFREG | S_IRUGO, &i2o_seq_fops_claimed},
+	{"users", S_IFREG | S_IRUGO, &i2o_seq_fops_users},
+	{"priv_msgs", S_IFREG | S_IRUGO, &i2o_seq_fops_priv_msgs},
+	{"authorized_users", S_IFREG | S_IRUGO, &i2o_seq_fops_authorized_users},
+	{"dev_identity", S_IFREG | S_IRUGO, &i2o_seq_fops_dev_identity},
+	{"ddm_identity", S_IFREG | S_IRUGO, &i2o_seq_fops_ddm_identity},
+	{"user_info", S_IFREG | S_IRUGO, &i2o_seq_fops_uinfo},
+	{"sgl_limits", S_IFREG | S_IRUGO, &i2o_seq_fops_sgl_limits},
+	{"sensors", S_IFREG | S_IRUGO, &i2o_seq_fops_sensors},
+	{NULL, 0, NULL}
+};
 
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
+/*
+ *  Storage unit specific entries (SCSI Periph, BS) with device names
+ */
+static i2o_proc_entry rbs_dev_entries[] = {
+	{"dev_name", S_IFREG | S_IRUGO, &i2o_seq_fops_dev_name},
+	{NULL, 0, NULL}
+};
 
-/* LAN group 0200h - Required Ethernet Statistics (scalar) */
-/* LAN group 0280h - Optional Ethernet Statistics Supported (scalar) */
-/* LAN group 0281h - Optional Ethernet Historical Statistics (scalar) */
-int i2o_proc_read_lan_eth_stats(char *buf, char **start, off_t offset,
-				int len, int *eof, void *data)
+/**
+ *	i2o_proc_create_entries - Creates proc dir entries
+ *	@dir: proc dir entry under which the entries should be placed
+ *	@i2o_pe: pointer to the entries which should be added
+ *	@data: pointer to I2O controller or device
+ *
+ *	Create proc dir entries for a I2O controller or I2O device.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int i2o_proc_create_entries(struct proc_dir_entry *dir,
+				   i2o_proc_entry * i2o_pe, void *data)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
-	int token;
-
-	struct
-	{
-		u64 rx_align_errors;
-		u64 tx_one_collisions;
-		u64 tx_multiple_collisions;
-		u64 tx_deferred;
-		u64 tx_late_collisions;
-		u64 tx_max_collisions;
-		u64 tx_carrier_lost;
-		u64 tx_excessive_deferrals;
-	} stats;	
-
-	static u64 supp_fields;
-	struct
-	{
-		u64 rx_overrun;
-		u64 tx_underrun;
-		u64 tx_heartbeat_failure;	
-	} hist_stats;
-
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0200, -1, &stats, sizeof(stats));
-
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0200 LAN Ethernet Statistics");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
-
-	len += sprintf(buf+len, "Rx alignment errors    : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.rx_align_errors));
-	len += sprintf(buf+len, "Tx one collisions      : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.tx_one_collisions));
-	len += sprintf(buf+len, "Tx multicollisions     : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.tx_multiple_collisions));
-	len += sprintf(buf+len, "Tx deferred            : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.tx_deferred));
-	len += sprintf(buf+len, "Tx late collisions     : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.tx_late_collisions));
-	len += sprintf(buf+len, "Tx max collisions      : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.tx_max_collisions));
-	len += sprintf(buf+len, "Tx carrier lost        : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.tx_carrier_lost));
-	len += sprintf(buf+len, "Tx excessive deferrals : " FMT_U64_HEX "\n",
-		       U64_VAL(&stats.tx_excessive_deferrals));
-
-	/* Optional Ethernet statistics follows  */
-	/* Get 0x0280 to see which optional fields are supported */
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0280, -1, &supp_fields, sizeof(supp_fields));
-
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0280 LAN Supported Optional Ethernet Statistics");
-		spin_unlock(&i2o_proc_lock);
-		return len;
-	}
+	struct proc_dir_entry *tmp;
 
-	if (supp_fields) /* 0x0281 */
-	{
-		token = i2o_query_scalar(d->controller, d->lct_data.tid,
-					 0x0281, -1, &stats, sizeof(stats));
+	while (i2o_pe->name) {
+		tmp = create_proc_entry(i2o_pe->name, i2o_pe->mode, dir);
+		if (!tmp)
+			return -1;
 
-		if (token < 0) {
-			len += i2o_report_query_status(buf+len, token,"0x0281 LAN Optional Ethernet Statistics");
-			spin_unlock(&i2o_proc_lock);
-			return len;
-		}
+		tmp->data = data;
+		tmp->proc_fops = i2o_pe->fops;
 
-		len += sprintf(buf+len, "==== Optional ETHERNET statistics (group 0x0281)\n");
-
-		len += i2o_report_opt_field(buf+len, "Rx Overrun",
-					0, supp_fields, &hist_stats.rx_overrun);
-		len += i2o_report_opt_field(buf+len, "Tx Underrun",
-					1, supp_fields, &hist_stats.tx_underrun);
-		len += i2o_report_opt_field(buf+len, "Tx HeartbeatFailure",
-					2, supp_fields, &hist_stats.tx_heartbeat_failure);
+		i2o_pe++;
 	}
 
-	spin_unlock(&i2o_proc_lock);
-	return len;
+	return 0;
 }
 
-/* LAN group 0300h - Required Token Ring Statistics (scalar) */
-/* LAN group 0380h, 0381h - Optional Statistics not yet defined (TODO) */
-int i2o_proc_read_lan_tr_stats(char *buf, char **start, off_t offset,
-			       int len, int *eof, void *data)
+/**
+ *	i2o_proc_subdir_remove - Remove child entries from a proc entry
+ *	@dir: proc dir entry from which the childs should be removed
+ *
+ *	Iterate over each i2o proc entry under dir and remove it. If the child
+ *	also has entries, remove them too.
+ */
+static void i2o_proc_subdir_remove(struct proc_dir_entry *dir)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u64 work64[13];
-	int token;
-
-	static char *ring_status[] =
-	{
-		"",
-		"",
-		"",
-		"",
-		"",
-		"Ring Recovery",
-		"Single Station",
-		"Counter Overflow",
-		"Remove Received",
-		"",
-		"Auto-Removal Error 1",
-		"Lobe Wire Fault",
-		"Transmit Beacon",
-		"Soft Error",
-		"Hard Error",
-		"Signal Loss"
-	};
-
-	spin_lock(&i2o_proc_lock);	
-	len = 0;
-
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0300, -1, &work64, sizeof(work64));
-
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0300 Token Ring Statistics");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+	struct proc_dir_entry *pe, *tmp;
+	pe = dir->subdir;
+	while (pe) {
+		tmp = pe->next;
+		i2o_proc_subdir_remove(pe);
+		remove_proc_entry(pe->name, dir);
+		pe = tmp;
 	}
+};
 
-	len += sprintf(buf,     "LineErrors          : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[0]));
-	len += sprintf(buf+len, "LostFrames          : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[1]));
-	len += sprintf(buf+len, "ACError             : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[2]));
-	len += sprintf(buf+len, "TxAbortDelimiter    : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[3]));
-	len += sprintf(buf+len, "BursErrors          : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[4]));
-	len += sprintf(buf+len, "FrameCopiedErrors   : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[5]));
-	len += sprintf(buf+len, "FrequencyErrors     : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[6]));
-	len += sprintf(buf+len, "InternalErrors      : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[7]));
-	len += sprintf(buf+len, "LastRingStatus      : %s\n", ring_status[work64[8]]);
-	len += sprintf(buf+len, "TokenError          : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[9]));
-	len += sprintf(buf+len, "UpstreamNodeAddress : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[10]));
-	len += sprintf(buf+len, "LastRingID          : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[11]));
-	len += sprintf(buf+len, "LastBeaconType      : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[12]));
-
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
-
-/* LAN group 0400h - Required FDDI Statistics (scalar) */
-/* LAN group 0480h, 0481h - Optional Statistics, not yet defined (TODO) */
-int i2o_proc_read_lan_fddi_stats(char *buf, char **start, off_t offset,
-				 int len, int *eof, void *data)
+/**
+ *	i2o_proc_device_add - Add an I2O device to the proc dir
+ *	@dir: proc dir entry to which the device should be added
+ *	@dev: I2O device which should be added
+ *
+ *	Add an I2O device to the proc dir entry dir and create the entries for
+ *	the device depending on the class of the I2O device.
+ */
+static void i2o_proc_device_add(struct proc_dir_entry *dir,
+				struct i2o_device *dev)
 {
-	struct i2o_device *d = (struct i2o_device*)data;
-	static u64 work64[11];
-	int token;
-
-	static char *conf_state[] =
-	{
-		"Isolated",
-		"Local a",
-		"Local b",
-		"Local ab",
-		"Local s",
-		"Wrap a",
-		"Wrap b",
-		"Wrap ab",
-		"Wrap s",
-		"C-Wrap a",
-		"C-Wrap b",
-		"C-Wrap s",
-		"Through",
-	};
-
-	static char *ring_state[] =
-	{
-		"Isolated",
-		"Non-op",
-		"Rind-op",
-		"Detect",
-		"Non-op-Dup",
-		"Ring-op-Dup",
-		"Directed",
-		"Trace"
-	};
-
-	static char *link_state[] =
-	{
-		"Off",
-		"Break",
-		"Trace",
-		"Connect",
-		"Next",
-		"Signal",
-		"Join",
-		"Verify",
-		"Active",
-		"Maintenance"
-	};
+	char buff[10];
+	struct proc_dir_entry *devdir;
+	i2o_proc_entry *i2o_pe = NULL;
 
-	spin_lock(&i2o_proc_lock);
-	len = 0;
+	sprintf(buff, "%03x", dev->lct_data.tid);
 
-	token = i2o_query_scalar(d->controller, d->lct_data.tid,
-				 0x0400, -1, &work64, sizeof(work64));
+	pr_debug("Adding device /proc/i2o/iop%d/%s\n", dev->iop->unit, buff);
 
-	if (token < 0) {
-		len += i2o_report_query_status(buf+len, token,"0x0400 FDDI Required Statistics");
-		spin_unlock(&i2o_proc_lock);
-		return len;
+	devdir = proc_mkdir(buff, dir);
+	if (!devdir) {
+		printk(KERN_WARNING "i2o: Could not allocate procdir!\n");
+		return;
 	}
 
-	len += sprintf(buf+len, "ConfigurationState : %s\n", conf_state[work64[0]]);
-	len += sprintf(buf+len, "UpstreamNode       : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[1]));
-	len += sprintf(buf+len, "DownStreamNode     : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[2]));
-	len += sprintf(buf+len, "FrameErrors        : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[3]));
-	len += sprintf(buf+len, "FramesLost         : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[4]));
-	len += sprintf(buf+len, "RingMgmtState      : %s\n", ring_state[work64[5]]);
-	len += sprintf(buf+len, "LCTFailures        : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[6]));
-	len += sprintf(buf+len, "LEMRejects         : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[7]));
-	len += sprintf(buf+len, "LEMCount           : " FMT_U64_HEX "\n",
-		       U64_VAL(&work64[8]));
-	len += sprintf(buf+len, "LConnectionState   : %s\n",
-		       link_state[work64[9]]);
-
-	spin_unlock(&i2o_proc_lock);
-	return len;
-}
+	devdir->data = dev;
 
-static int i2o_proc_create_entries(void *data, i2o_proc_entry *pentry,
-				   struct proc_dir_entry *parent)
-{
-	struct proc_dir_entry *ent;
-	
-	while(pentry->name != NULL)
-	{
-		ent = create_proc_entry(pentry->name, pentry->mode, parent);
-		if(!ent) return -1;
+	i2o_proc_create_entries(devdir, generic_dev_entries, dev);
 
-		ent->data = data;
-		ent->read_proc = pentry->read_proc;
-		ent->write_proc = pentry->write_proc;
-		if(pentry->fops_proc)
-			ent->proc_fops = pentry->fops_proc;
-
-		ent->nlink = 1;
-
-		pentry++;
-	}
-
-	return 0;
-}
-
-static void i2o_proc_remove_entries(i2o_proc_entry *pentry, 
-				    struct proc_dir_entry *parent)
-{
-	while(pentry->name != NULL)
-	{
-		remove_proc_entry(pentry->name, parent);
-		pentry++;
+	/* Inform core that we want updates about this device's status */
+	switch (dev->lct_data.class_id) {
+	case I2O_CLASS_SCSI_PERIPHERAL:
+	case I2O_CLASS_RANDOM_BLOCK_STORAGE:
+		i2o_pe = rbs_dev_entries;
+		break;
+	default:
+		break;
 	}
+	if (i2o_pe)
+		i2o_proc_create_entries(devdir, i2o_pe, dev);
 }
 
-static int i2o_proc_add_controller(struct i2o_controller *pctrl, 
-				   struct proc_dir_entry *root )
+/**
+ *	i2o_proc_iop_add - Add an I2O controller to the i2o proc tree
+ *	@dir: parent proc dir entry
+ *	@c: I2O controller which should be added
+ *
+ *	Add the entries to the parent proc dir entry. Also each device is added
+ *	to the controllers proc dir entry.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int i2o_proc_iop_add(struct proc_dir_entry *dir,
+			    struct i2o_controller *c)
 {
-	struct proc_dir_entry *dir, *dir1;
+	struct proc_dir_entry *iopdir;
 	struct i2o_device *dev;
 	char buff[10];
 
-	sprintf(buff, "iop%d", pctrl->unit);
+	snprintf(buff, 10, "iop%d", c->unit);
 
-	dir = proc_mkdir(buff, root);
-	if(!dir)
-		return -1;
-
-	pctrl->proc_entry = dir;
+	pr_debug("Adding IOP /proc/i2o/%s\n", buff);
 
-	i2o_proc_create_entries(pctrl, generic_iop_entries, dir);
-	
-	for(dev = pctrl->devices; dev; dev = dev->next)
-	{
-		sprintf(buff, "%0#5x", dev->lct_data.tid);
+	iopdir = proc_mkdir(buff, dir);
+	if (!iopdir)
+		return -1;
 
-		dir1 = proc_mkdir(buff, dir);
-		dev->proc_entry = dir1;
+	iopdir->data = c;
 
-		if(!dir1)
-			printk(KERN_INFO "i2o_proc: Could not allocate proc dir\n");
+	i2o_proc_create_entries(iopdir, i2o_proc_generic_iop_entries, c);
 
-		i2o_proc_add_device(dev, dir1);
-	}
+	list_for_each_entry(dev, &c->devices, list)
+	    i2o_proc_device_add(iopdir, dev);
 
 	return 0;
 }
 
-void i2o_proc_new_dev(struct i2o_controller *c, struct i2o_device *d)
-{
-	char buff[10];
-
-#ifdef DRIVERDEBUG
-	printk(KERN_INFO "Adding new device to /proc/i2o/iop%d\n", c->unit);
-#endif
-	sprintf(buff, "%0#5x", d->lct_data.tid);
-
-	d->proc_entry = proc_mkdir(buff, c->proc_entry);
-
-	if(!d->proc_entry)
-	{
-		printk(KERN_WARNING "i2o: Could not allocate procdir!\n");
-		return;
-	}
-
-	i2o_proc_add_device(d, d->proc_entry);
-}
-
-void i2o_proc_add_device(struct i2o_device *dev, struct proc_dir_entry *dir)
-{	
-	i2o_proc_create_entries(dev, generic_dev_entries, dir);
-
-	/* Inform core that we want updates about this device's status */
-	i2o_device_notify_on(dev, &i2o_proc_handler);
-	switch(dev->lct_data.class_id)
-	{
-		case I2O_CLASS_SCSI_PERIPHERAL:
-		case I2O_CLASS_RANDOM_BLOCK_STORAGE:
-			i2o_proc_create_entries(dev, rbs_dev_entries, dir);
-			break;
-		case I2O_CLASS_LAN:
-			i2o_proc_create_entries(dev, lan_entries, dir);
-			switch(dev->lct_data.sub_class)
-			{
-				case I2O_LAN_ETHERNET:
-					i2o_proc_create_entries(dev, lan_eth_entries, dir);
-					break;
-				case I2O_LAN_FDDI:
-					i2o_proc_create_entries(dev, lan_fddi_entries, dir);
-					break;
-				case I2O_LAN_TR:
-					i2o_proc_create_entries(dev, lan_tr_entries, dir);
-					break;
-				default:
-					break;
-			}
-			break;
-		default:
-			break;
-	}
-}
-
-static void i2o_proc_remove_controller(struct i2o_controller *pctrl, 
-				       struct proc_dir_entry *parent)
-{
-	char buff[10];
-	struct i2o_device *dev;
-
-	/* Remove unused device entries */
-	for(dev=pctrl->devices; dev; dev=dev->next)
-		i2o_proc_remove_device(dev);
-
-	if(!atomic_read(&pctrl->proc_entry->count))
-	{
-		sprintf(buff, "iop%d", pctrl->unit);
-
-		i2o_proc_remove_entries(generic_iop_entries, pctrl->proc_entry);
-		remove_proc_entry(buff, parent);
-		pctrl->proc_entry = NULL;
-	}
-}
-
-void i2o_proc_remove_device(struct i2o_device *dev)
+/**
+ *	i2o_proc_iop_remove - Removes an I2O controller from the i2o proc tree
+ *	@dir: parent proc dir entry
+ *	@c: I2O controller which should be removed
+ *
+ *	Iterate over each i2o proc entry and search controller c. If it is found
+ *	remove it from the tree.
+ */
+static void i2o_proc_iop_remove(struct proc_dir_entry *dir,
+				struct i2o_controller *c)
 {
-	struct proc_dir_entry *de=dev->proc_entry;
-	char dev_id[10];
-
-	sprintf(dev_id, "%0#5x", dev->lct_data.tid);
-
-	i2o_device_notify_off(dev, &i2o_proc_handler);
-	/* Would it be safe to remove _files_ even if they are in use? */
-	if((de) && (!atomic_read(&de->count)))
-	{
-		i2o_proc_remove_entries(generic_dev_entries, de);
-		switch(dev->lct_data.class_id)
-		{
-			case I2O_CLASS_SCSI_PERIPHERAL:
-			case I2O_CLASS_RANDOM_BLOCK_STORAGE:
-				i2o_proc_remove_entries(rbs_dev_entries, de);
-				break;
-			case I2O_CLASS_LAN:
-			{
-				i2o_proc_remove_entries(lan_entries, de);
-				switch(dev->lct_data.sub_class)
-				{
-				case I2O_LAN_ETHERNET:
-					i2o_proc_remove_entries(lan_eth_entries, de);
-					break;
-				case I2O_LAN_FDDI:
-					i2o_proc_remove_entries(lan_fddi_entries, de);
-					break;
-				case I2O_LAN_TR:
-					i2o_proc_remove_entries(lan_tr_entries, de);
-					break;
-				}
-			}
+	struct proc_dir_entry *pe, *tmp;
+
+	pe = dir->subdir;
+	while (pe) {
+		tmp = pe->next;
+		if (pe->data == c) {
+			i2o_proc_subdir_remove(pe);
+			remove_proc_entry(pe->name, dir);
 		}
-		remove_proc_entry(dev_id, dev->controller->proc_entry);
+		pr_debug("Removing IOP /proc/i2o/iop%d\n", c->unit);
+		pe = tmp;
 	}
 }
-	
-void i2o_proc_dev_del(struct i2o_controller *c, struct i2o_device *d)
-{
-#ifdef DRIVERDEBUG
-	printk(KERN_INFO "Deleting device %d from iop%d\n", 
-		d->lct_data.tid, c->unit);
-#endif
-
-	i2o_proc_remove_device(d);
-}
 
-static int create_i2o_procfs(void)
+/**
+ *	i2o_proc_fs_create - Create the i2o proc fs.
+ *
+ *	Iterate over each I2O controller and create the entries for it.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int __init i2o_proc_fs_create(void)
 {
-	struct i2o_controller *pctrl = NULL;
-	int i;
+	struct i2o_controller *c;
 
 	i2o_proc_dir_root = proc_mkdir("i2o", NULL);
-	if(!i2o_proc_dir_root)
+	if (!i2o_proc_dir_root)
 		return -1;
+
 	i2o_proc_dir_root->owner = THIS_MODULE;
 
-	for(i = 0; i < MAX_I2O_CONTROLLERS; i++)
-	{
-		pctrl = i2o_find_controller(i);
-		if(pctrl)
-		{
-			i2o_proc_add_controller(pctrl, i2o_proc_dir_root);
-			i2o_unlock_controller(pctrl);
-		}
-	};
+	list_for_each_entry(c, &i2o_controllers, list)
+	    i2o_proc_iop_add(i2o_proc_dir_root, c);
 
 	return 0;
-}
+};
 
-static int __exit destroy_i2o_procfs(void)
+/**
+ *	i2o_proc_fs_destroy - Cleanup the all i2o proc entries
+ *
+ *	Iterate over each I2O controller and remove the entries for it.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int __exit i2o_proc_fs_destroy(void)
 {
-	struct i2o_controller *pctrl = NULL;
-	int i;
+	struct i2o_controller *c;
 
-	for(i = 0; i < MAX_I2O_CONTROLLERS; i++)
-	{
-		pctrl = i2o_find_controller(i);
-		if(pctrl)
-		{
-			i2o_proc_remove_controller(pctrl, i2o_proc_dir_root);
-			i2o_unlock_controller(pctrl);
-		}
-	}
+	list_for_each_entry(c, &i2o_controllers, list)
+	    i2o_proc_iop_remove(i2o_proc_dir_root, c);
 
-	if(!atomic_read(&i2o_proc_dir_root->count))
-		remove_proc_entry("i2o", NULL);
-	else
-		return -1;
+	remove_proc_entry("i2o", NULL);
 
 	return 0;
-}
+};
 
-int __init i2o_proc_init(void)
+/**
+ *	i2o_proc_init - Init function for procfs
+ *
+ *	Registers Proc OSM and creates procfs entries.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int __init i2o_proc_init(void)
 {
-	if (i2o_install_handler(&i2o_proc_handler) < 0)
-	{
-		printk(KERN_ERR "i2o_proc: Unable to install PROC handler.\n");
-		return 0;
-	}
+	int rc;
+
+	rc = i2o_driver_register(&i2o_proc_driver);
+	if (rc)
+		return rc;
 
-	if(create_i2o_procfs())
-		return -EBUSY;
+	rc = i2o_proc_fs_create();
+	if (rc) {
+		i2o_driver_unregister(&i2o_proc_driver);
+		return rc;
+	}
 
 	return 0;
-}
+};
+
+/**
+ *	i2o_proc_exit - Exit function for procfs
+ *
+ *	Unregisters Proc OSM and removes procfs entries.
+ */
+static void __exit i2o_proc_exit(void)
+{
+	i2o_driver_unregister(&i2o_proc_driver);
+	i2o_proc_fs_destroy();
+};
 
 MODULE_AUTHOR("Deepak Saxena");
 MODULE_DESCRIPTION("I2O procfs Handler");
 MODULE_LICENSE("GPL");
 
-static void __exit i2o_proc_exit(void)
-{
-	destroy_i2o_procfs();
-	i2o_remove_handler(&i2o_proc_handler);
-}
-
-#ifdef MODULE
 module_init(i2o_proc_init);
-#endif
 module_exit(i2o_proc_exit);
-
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index ba121fc85..9be68f380 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * 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
@@ -19,13 +19,13 @@
  *
  *	o	Each (bus,lun) is a logical device in I2O. We keep a map
  *		table. We spoof failed selection for unmapped units
- *	o	Request sense buffers can come back for free. 
+ *	o	Request sense buffers can come back for free.
  *	o	Scatter gather is a bit dynamic. We have to investigate at
  *		setup time.
  *	o	Some of our resources are dynamically shared. The i2o core
  *		needs a message reservation protocol to avoid swap v net
  *		deadlocking. We need to back off queue requests.
- *	
+ *
  *	In general the firmware wants to help. Where its help isn't performance
  *	useful we just ignore the aid. Its not worth the code in truth.
  *
@@ -40,7 +40,6 @@
  *	Fix the resource management problems.
  */
 
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -53,79 +52,229 @@
 #include <linux/proc_fs.h>
 #include <linux/prefetch.h>
 #include <linux/pci.h>
+#include <linux/blkdev.h>
+#include <linux/i2o.h>
+
 #include <asm/dma.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/atomic.h>
-#include <linux/blkdev.h>
-#include <linux/i2o.h>
 
 #include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
-
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_cmnd.h>
 
 #define VERSION_STRING        "Version 0.1.2"
 
-//#define DRIVERDEBUG
+static struct i2o_driver i2o_scsi_driver;
 
-#ifdef DRIVERDEBUG
-#define dprintk(s, args...) printk(s, ## args)
-#else
-#define dprintk(s, args...)
-#endif
+static int i2o_scsi_max_id = 16;
+static int i2o_scsi_max_lun = 8;
+
+struct i2o_scsi_host {
+	struct Scsi_Host *scsi_host;	/* pointer to the SCSI host */
+	struct i2o_controller *iop;	/* pointer to the I2O controller */
+	struct i2o_device *channel[0];	/* channel->i2o_dev mapping table */
+};
+
+static struct scsi_host_template i2o_scsi_host_template;
 
 #define I2O_SCSI_CAN_QUEUE	4
-#define MAXHOSTS		32
 
-struct i2o_scsi_host
-{
-	struct i2o_controller *controller;
-	s16 task[16][8];		/* Allow 16 devices for now */
-	unsigned long tagclock[16][8];	/* Tag clock for queueing */
-	s16 bus_task;		/* The adapter TID */
+/* SCSI OSM class handling definition */
+static struct i2o_class_id i2o_scsi_class_id[] = {
+	{I2O_CLASS_SCSI_PERIPHERAL},
+	{I2O_CLASS_END}
 };
 
-static int scsi_context;
-static int lun_done;
-static int i2o_scsi_hosts;
+static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c)
+{
+	struct i2o_scsi_host *i2o_shost;
+	struct i2o_device *i2o_dev;
+	struct Scsi_Host *scsi_host;
+	int max_channel = 0;
+	u8 type;
+	int i;
+	size_t size;
+	i2o_status_block *sb;
 
-static u32 *retry[32];
-static struct i2o_controller *retry_ctrl[32];
-static struct timer_list retry_timer;
-static spinlock_t retry_lock = SPIN_LOCK_UNLOCKED;
-static int retry_ct = 0;
+	list_for_each_entry(i2o_dev, &c->devices, list)
+	    if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT) {
+		if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) || (type == 1))	/* SCSI bus */
+			max_channel++;
+	}
 
-static atomic_t queue_depth;
+	if (!max_channel) {
+		printk(KERN_WARNING "scsi-osm: no channels found on %s\n",
+		       c->name);
+		return ERR_PTR(-EFAULT);
+	}
 
-/*
- *	SG Chain buffer support...
+	size = max_channel * sizeof(struct i2o_device *)
+	    + sizeof(struct i2o_scsi_host);
+
+	scsi_host = scsi_host_alloc(&i2o_scsi_host_template, size);
+	if (!scsi_host) {
+		printk(KERN_WARNING "scsi-osm: Could not allocate SCSI host\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	scsi_host->max_channel = max_channel - 1;
+	scsi_host->max_id = i2o_scsi_max_id;
+	scsi_host->max_lun = i2o_scsi_max_lun;
+	scsi_host->this_id = c->unit;
+
+	sb = c->status_block.virt;
+
+	scsi_host->sg_tablesize = (sb->inbound_frame_size -
+				   sizeof(struct i2o_message) / 4 - 6) / 2;
+
+	i2o_shost = (struct i2o_scsi_host *)scsi_host->hostdata;
+	i2o_shost->scsi_host = scsi_host;
+	i2o_shost->iop = c;
+
+	i = 0;
+	list_for_each_entry(i2o_dev, &c->devices, list)
+	    if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT) {
+		if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) || (type == 1))	/* only SCSI bus */
+			i2o_shost->channel[i++] = i2o_dev;
+
+		if (i >= max_channel)
+			break;
+	}
+
+	return i2o_shost;
+};
+
+/**
+ *	i2o_scsi_get_host - Get an I2O SCSI host
+ *	@c: I2O controller to for which to get the SCSI host
+ *
+ *	If the I2O controller already exists as SCSI host, the SCSI host
+ *	is returned, otherwise the I2O controller is added to the SCSI
+ *	core.
+ *
+ *	Returns pointer to the I2O SCSI host on success or NULL on failure.
+ */
+static struct i2o_scsi_host *i2o_scsi_get_host(struct i2o_controller *c)
+{
+	return c->driver_data[i2o_scsi_driver.context];
+};
+
+/**
+ *	i2o_scsi_remove - Remove I2O device from SCSI core
+ *	@dev: device which should be removed
+ *
+ *	Removes the I2O device from the SCSI core again.
+ *
+ *	Returns 0 on success.
  */
+static int i2o_scsi_remove(struct device *dev)
+{
+	struct i2o_device *i2o_dev = to_i2o_device(dev);
+	struct i2o_controller *c = i2o_dev->iop;
+	struct i2o_scsi_host *i2o_shost;
+	struct scsi_device *scsi_dev;
+
+	i2o_shost = i2o_scsi_get_host(c);
+
+	shost_for_each_device(scsi_dev, i2o_shost->scsi_host)
+	    if (scsi_dev->hostdata == i2o_dev) {
+		scsi_remove_device(scsi_dev);
+		scsi_device_put(scsi_dev);
+		break;
+	}
 
-#define SG_MAX_FRAGS		64
+	return 0;
+};
 
-/*
- *	FIXME: we should allocate one of these per bus we find as we
- *	locate them not in a lump at boot.
+/**
+ *	i2o_scsi_probe - verify if dev is a I2O SCSI device and install it
+ *	@dev: device to verify if it is a I2O SCSI device
+ *
+ *	Retrieve channel, id and lun for I2O device. If everthing goes well
+ *	register the I2O device as SCSI device on the I2O SCSI controller.
+ *
+ *	Returns 0 on success or negative error code on failure.
  */
- 
-typedef struct _chain_buf
+static int i2o_scsi_probe(struct device *dev)
 {
-	u32 sg_flags_cnt[SG_MAX_FRAGS];
-	u32 sg_buf[SG_MAX_FRAGS];
-} chain_buf;
+	struct i2o_device *i2o_dev = to_i2o_device(dev);
+	struct i2o_controller *c = i2o_dev->iop;
+	struct i2o_scsi_host *i2o_shost;
+	struct Scsi_Host *scsi_host;
+	struct i2o_device *parent;
+	struct scsi_device *scsi_dev;
+	u32 id;
+	u64 lun;
+	int channel = -1;
+	int i;
+
+	i2o_shost = i2o_scsi_get_host(c);
+	if (!i2o_shost)
+		return -EFAULT;
+
+	scsi_host = i2o_shost->scsi_host;
 
-#define SG_CHAIN_BUF_SZ sizeof(chain_buf)
+	if (i2o_parm_field_get(i2o_dev, 0, 3, &id, 4) < 0)
+		return -EFAULT;
+
+	if (id >= scsi_host->max_id) {
+		printk(KERN_WARNING "scsi-osm: SCSI device id (%d) >= max_id "
+		       "of I2O host (%d)", id, scsi_host->max_id);
+		return -EFAULT;
+	}
+
+	if (i2o_parm_field_get(i2o_dev, 0, 4, &lun, 8) < 0)
+		return -EFAULT;
+	if (lun >= scsi_host->max_lun) {
+		printk(KERN_WARNING "scsi-osm: SCSI device id (%d) >= max_lun "
+		       "of I2O host (%d)", (unsigned int)lun,
+		       scsi_host->max_lun);
+		return -EFAULT;
+	}
+
+	parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid);
+	if (!parent) {
+		printk(KERN_WARNING "scsi-osm: can not find parent of device "
+		       "%03x\n", i2o_dev->lct_data.tid);
+		return -EFAULT;
+	}
 
-#define SG_MAX_BUFS		(i2o_num_controllers * I2O_SCSI_CAN_QUEUE)
-#define SG_CHAIN_POOL_SZ	(SG_MAX_BUFS * SG_CHAIN_BUF_SZ)
+	for (i = 0; i <= i2o_shost->scsi_host->max_channel; i++)
+		if (i2o_shost->channel[i] == parent)
+			channel = i;
+
+	if (channel == -1) {
+		printk(KERN_WARNING "scsi-osm: can not find channel of device "
+		       "%03x\n", i2o_dev->lct_data.tid);
+		return -EFAULT;
+	}
+
+	scsi_dev =
+	    __scsi_add_device(i2o_shost->scsi_host, channel, id, lun, i2o_dev);
+
+	if (!scsi_dev) {
+		printk(KERN_WARNING "scsi-osm: can not add SCSI device "
+		       "%03x\n", i2o_dev->lct_data.tid);
+		return -EFAULT;
+	}
+
+	pr_debug("Added new SCSI device %03x (cannel: %d, id: %d, lun: %d)\n",
+		 i2o_dev->lct_data.tid, channel, id, (unsigned int)lun);
+
+	return 0;
+};
 
-static int max_sg_len = 0;
-static chain_buf *sg_chain_pool = NULL;
-static int sg_chain_tag = 0;
-static int sg_max_frags = SG_MAX_FRAGS;
+static const char *i2o_scsi_info(struct Scsi_Host *SChost)
+{
+	struct i2o_scsi_host *hostdata;
+	hostdata = (struct i2o_scsi_host *)SChost->hostdata;
+	return hostdata->iop->name;
+}
 
+#if 0
 /**
  *	i2o_retry_run		-	retry on timeout
  *	@f: unused
@@ -136,16 +285,16 @@ static int sg_max_frags = SG_MAX_FRAGS;
  *	and its default handler should be this in the core, and this
  *	call a 2nd "I give up" handler in the OSM ?
  */
- 
+
 static void i2o_retry_run(unsigned long f)
 {
 	int i;
 	unsigned long flags;
-	
+
 	spin_lock_irqsave(&retry_lock, flags);
-	for(i=0;i<retry_ct;i++)
+	for (i = 0; i < retry_ct; i++)
 		i2o_post_message(retry_ctrl[i], virt_to_bus(retry[i]));
-	retry_ct=0;
+	retry_ct = 0;
 	spin_unlock_irqrestore(&retry_lock, flags);
 }
 
@@ -155,860 +304,507 @@ static void i2o_retry_run(unsigned long f)
  *	Turn each of the pending commands into a NOP and post it back
  *	to the controller to clear it.
  */
- 
+
 static void flush_pending(void)
 {
 	int i;
 	unsigned long flags;
-	
+
 	spin_lock_irqsave(&retry_lock, flags);
-	for(i=0;i<retry_ct;i++)
-	{
-		retry[i][0]&=~0xFFFFFF;
-		retry[i][0]|=I2O_CMD_UTIL_NOP<<24;
-		i2o_post_message(retry_ctrl[i],virt_to_bus(retry[i]));
+	for (i = 0; i < retry_ct; i++) {
+		retry[i][0] &= ~0xFFFFFF;
+		retry[i][0] |= I2O_CMD_UTIL_NOP << 24;
+		i2o_post_message(retry_ctrl[i], virt_to_bus(retry[i]));
 	}
-	retry_ct=0;
+	retry_ct = 0;
 	spin_unlock_irqrestore(&retry_lock, flags);
 }
+#endif
 
 /**
- *	i2o_scsi_reply		-	scsi message reply processor
- *	@h: our i2o handler
+ *	i2o_scsi_reply - SCSI OSM message reply handler
  *	@c: controller issuing the reply
- *	@msg: the message from the controller (mapped)
+ *	@m: message id for flushing
+ *	@msg: the message from the controller
  *
  *	Process reply messages (interrupts in normal scsi controller think).
  *	We can get a variety of messages to process. The normal path is
  *	scsi command completions. We must also deal with IOP failures,
  *	the reply to a bus reset and the reply to a LUN query.
  *
- *	Locks: the queue lock is taken to call the completion handler
+ *	Returns 0 on success and if the reply should not be flushed or > 0
+ *	on success and if the reply should be flushed. Returns negative error
+ *	code on failure and if the reply should be flushed.
  */
-
-static void i2o_scsi_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *msg)
+static int i2o_scsi_reply(struct i2o_controller *c, u32 m,
+			  struct i2o_message *msg)
 {
-	struct scsi_cmnd *current_command;
-	spinlock_t *lock;
-	u32 *m = (u32 *)msg;
-	u8 as,ds,st;
-	unsigned long flags;
+	struct scsi_cmnd *cmd;
+	struct device *dev;
+	u8 as, ds, st;
+
+	cmd = i2o_cntxt_list_get(c, readl(&msg->u.s.tcntxt));
+
+	if (msg->u.head[0] & (1 << 13)) {
+		struct i2o_message *pmsg;	/* preserved message */
+		u32 pm;
+
+		pm = readl(&msg->body[3]);
+
+		pmsg = c->in_queue.virt + pm;
 
-	if(m[0] & (1<<13))
-	{
 		printk("IOP fail.\n");
 		printk("From %d To %d Cmd %d.\n",
-			(m[1]>>12)&0xFFF,
-			m[1]&0xFFF,
-			m[1]>>24);
-		printk("Failure Code %d.\n", m[4]>>24);
-		if(m[4]&(1<<16))
+		       (msg->u.head[1] >> 12) & 0xFFF,
+		       msg->u.head[1] & 0xFFF, msg->u.head[1] >> 24);
+		printk("Failure Code %d.\n", msg->body[0] >> 24);
+		if (msg->body[0] & (1 << 16))
 			printk("Format error.\n");
-		if(m[4]&(1<<17))
+		if (msg->body[0] & (1 << 17))
 			printk("Path error.\n");
-		if(m[4]&(1<<18))
+		if (msg->body[0] & (1 << 18))
 			printk("Path State.\n");
-		if(m[4]&(1<<18))
+		if (msg->body[0] & (1 << 18))
 			printk("Congestion.\n");
-		
-		m=(u32 *)bus_to_virt(m[7]);
-		printk("Failing message is %p.\n", m);
-		
-		/* This isnt a fast path .. */
-		spin_lock_irqsave(&retry_lock, flags);
-		
-		if((m[4]&(1<<18)) && retry_ct < 32)
-		{
-			retry_ctrl[retry_ct]=c;
-			retry[retry_ct]=m;
-			if(!retry_ct++)
-			{
-				retry_timer.expires=jiffies+1;
-				add_timer(&retry_timer);
-			}
-			spin_unlock_irqrestore(&retry_lock, flags);
-		}
-		else
-		{
-			spin_unlock_irqrestore(&retry_lock, flags);
-			/* Create a scsi error for this */
-			current_command = (struct scsi_cmnd *)i2o_context_list_get(m[3], c);
-			if(!current_command)
-				return;
-
-			lock = current_command->device->host->host_lock;
-			printk("Aborted %ld\n", current_command->serial_number);
-
-			spin_lock_irqsave(lock, flags);
-			current_command->result = DID_ERROR << 16;
-			current_command->scsi_done(current_command);
-			spin_unlock_irqrestore(lock, flags);
-			
-			/* Now flush the message by making it a NOP */
-			m[0]&=0x00FFFFFF;
-			m[0]|=(I2O_CMD_UTIL_NOP)<<24;
-			i2o_post_message(c,virt_to_bus(m));
-		}
-		return;
+
+		printk("Failing message is %p.\n", pmsg);
+
+		cmd = i2o_cntxt_list_get(c, readl(&pmsg->u.s.tcntxt));
+		if (!cmd)
+			return 1;
+
+		printk("Aborted %ld\n", cmd->serial_number);
+		cmd->result = DID_ERROR << 16;
+		cmd->scsi_done(cmd);
+
+		/* Now flush the message by making it a NOP */
+		i2o_msg_nop(c, pm);
+
+		return 1;
 	}
-	
-	prefetchw(&queue_depth);
-		
-	
+
 	/*
-	 *	Low byte is device status, next is adapter status,
-	 *	(then one byte reserved), then request status.
+	 *      Low byte is device status, next is adapter status,
+	 *      (then one byte reserved), then request status.
 	 */
-	ds=(u8)le32_to_cpu(m[4]);
-	as=(u8)le32_to_cpu(m[4]>>8);
-	st=(u8)le32_to_cpu(m[4]>>24);
-	
-	dprintk(KERN_INFO "i2o got a scsi reply %08X: ", m[0]);
-	dprintk(KERN_INFO "m[2]=%08X: ", m[2]);
-	dprintk(KERN_INFO "m[4]=%08X\n", m[4]);
- 
-	if(m[2]&0x80000000)
-	{
-		if(m[2]&0x40000000)
-		{
-			dprintk(KERN_INFO "Event.\n");
-			lun_done=1;
-			return;
-		}
-		printk(KERN_INFO "i2o_scsi: bus reset completed.\n");
-		return;
-	}
+	ds = (u8) readl(&msg->body[0]);
+	as = (u8) (readl(&msg->body[0]) >> 8);
+	st = (u8) (readl(&msg->body[0]) >> 24);
 
-	current_command = (struct scsi_cmnd *)i2o_context_list_get(m[3], c);
-	
 	/*
-	 *	Is this a control request coming back - eg an abort ?
+	 *      Is this a control request coming back - eg an abort ?
 	 */
-	 
-	atomic_dec(&queue_depth);
-
-	if(current_command==NULL)
-	{
-		if(st)
-			dprintk(KERN_WARNING "SCSI abort: %08X", m[4]);
-		dprintk(KERN_INFO "SCSI abort completed.\n");
-		return;
-	}
-	
-	dprintk(KERN_INFO "Completed %ld\n", current_command->serial_number);
-	
-	if(st == 0x06)
-	{
-		if(le32_to_cpu(m[5]) < current_command->underflow)
-		{
-			int i;
-			printk(KERN_ERR "SCSI: underflow 0x%08X 0x%08X\n",
-				le32_to_cpu(m[5]), current_command->underflow);
-			printk("Cmd: ");
-			for(i=0;i<15;i++)
-				printk("%02X ", current_command->cmnd[i]);
-			printk(".\n");
-		}
-		else st=0;
-	}
-	
-	if(st)
-	{
-		/* An error has occurred */
 
-		dprintk(KERN_WARNING "SCSI error %08X", m[4]);
-			
-		if (as == 0x0E) 
-			/* SCSI Reset */
-			current_command->result = DID_RESET << 16;
-		else if (as == 0x0F)
-			current_command->result = DID_PARITY << 16;
-		else
-			current_command->result = DID_ERROR << 16;
-	}
-	else
-		/*
-		 *	It worked maybe ?
-		 */		
-		current_command->result = DID_OK << 16 | ds;
-
-	if (current_command->use_sg) {
-		pci_unmap_sg(c->pdev,
-			(struct scatterlist *)current_command->buffer,
-			current_command->use_sg,
-			current_command->sc_data_direction);
-	} else if (current_command->request_bufflen) {
-		pci_unmap_single(c->pdev,
-			(dma_addr_t)((long)current_command->SCp.ptr),
-			current_command->request_bufflen,
-			current_command->sc_data_direction);
+	if (!cmd) {
+		if (st)
+			printk(KERN_WARNING "SCSI abort: %08X",
+			       readl(&msg->body[0]));
+		printk(KERN_INFO "SCSI abort completed.\n");
+		return -EFAULT;
 	}
 
-	lock = current_command->device->host->host_lock;
-	spin_lock_irqsave(lock, flags);
-	current_command->scsi_done(current_command);
-	spin_unlock_irqrestore(lock, flags);
-	return;
-}
+	pr_debug("Completed %ld\n", cmd->serial_number);
 
-struct i2o_handler i2o_scsi_handler = {
-	.reply	= i2o_scsi_reply,
-	.name	= "I2O SCSI OSM",
-	.class	= I2O_CLASS_SCSI_PERIPHERAL,
-};
+	if (st) {
+		u32 count, error;
+		/* An error has occurred */
 
-/**
- *	i2o_find_lun		-	report the lun of an i2o device
- *	@c: i2o controller owning the device
- *	@d: i2o disk device
- *	@target: filled in with target id
- *	@lun: filled in with target lun
- *
- *	Query an I2O device to find out its SCSI lun and target numbering. We
- *	don't currently handle some of the fancy SCSI-3 stuff although our
- *	querying is sufficient to do so.
- */
- 
-static int i2o_find_lun(struct i2o_controller *c, struct i2o_device *d, int *target, int *lun)
-{
-	u8 reply[8];
-	
-	if(i2o_query_scalar(c, d->lct_data.tid, 0, 3, reply, 4)<0)
-		return -1;
-		
-	*target=reply[0];
-	
-	if(i2o_query_scalar(c, d->lct_data.tid, 0, 4, reply, 8)<0)
-		return -1;
-
-	*lun=reply[1];
-
-	dprintk(KERN_INFO "SCSI (%d,%d)\n", *target, *lun);
-	return 0;
-}
+		switch (st) {
+		case 0x06:
+			count = readl(&msg->body[1]);
+			if (count < cmd->underflow) {
+				int i;
+				printk(KERN_ERR "SCSI: underflow 0x%08X 0x%08X"
+				       "\n", count, cmd->underflow);
+				printk("Cmd: ");
+				for (i = 0; i < 15; i++)
+					printk("%02X ", cmd->cmnd[i]);
+				printk(".\n");
+				cmd->result = (DID_ERROR << 16);
+			}
+			break;
 
-/**
- *	i2o_scsi_init		-	initialize an i2o device for scsi
- *	@c: i2o controller owning the device
- *	@d: scsi controller
- *	@shpnt: scsi device we wish it to become
- *
- *	Enumerate the scsi peripheral/fibre channel peripheral class
- *	devices that are children of the controller. From that we build
- *	a translation map for the command queue code. Since I2O works on
- *	its own tid's we effectively have to think backwards to get what
- *	the midlayer wants
- */
- 
-static void i2o_scsi_init(struct i2o_controller *c, struct i2o_device *d, struct Scsi_Host *shpnt)
-{
-	struct i2o_device *unit;
-	struct i2o_scsi_host *h =(struct i2o_scsi_host *)shpnt->hostdata;
-	int lun;
-	int target;
-	
-	h->controller=c;
-	h->bus_task=d->lct_data.tid;
-	
-	for(target=0;target<16;target++)
-		for(lun=0;lun<8;lun++)
-			h->task[target][lun] = -1;
-			
-	for(unit=c->devices;unit!=NULL;unit=unit->next)
-	{
-		dprintk(KERN_INFO "Class %03X, parent %d, want %d.\n",
-			unit->lct_data.class_id, unit->lct_data.parent_tid, d->lct_data.tid);
-			
-		/* Only look at scsi and fc devices */
-		if (    (unit->lct_data.class_id != I2O_CLASS_SCSI_PERIPHERAL)
-		     && (unit->lct_data.class_id != I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL)
-		   )
-			continue;
-
-		/* On our bus ? */
-		dprintk(KERN_INFO "Found a disk (%d).\n", unit->lct_data.tid);
-		if ((unit->lct_data.parent_tid == d->lct_data.tid)
-		     || (unit->lct_data.parent_tid == d->lct_data.parent_tid)
-		   )
-		{
-			u16 limit;
-			dprintk(KERN_INFO "Its ours.\n");
-			if(i2o_find_lun(c, unit, &target, &lun)==-1)
-			{
-				printk(KERN_ERR "i2o_scsi: Unable to get lun for tid %d.\n", unit->lct_data.tid);
-				continue;
+		default:
+			error = readl(&msg->body[0]);
+
+			printk(KERN_ERR "scsi-osm: SCSI error %08x\n", error);
+
+			if ((error & 0xff) == 0x02 /*CHECK_CONDITION */ ) {
+				int i;
+				u32 len = sizeof(cmd->sense_buffer);
+				len = (len > 40) ? 40 : len;
+				// Copy over the sense data
+				memcpy(cmd->sense_buffer, (void *)&msg->body[3],
+				       len);
+				for (i = 0; i <= len; i++)
+					printk(KERN_INFO "%02x\n",
+					       cmd->sense_buffer[i]);
+				if (cmd->sense_buffer[0] == 0x70
+				    && cmd->sense_buffer[2] == DATA_PROTECT) {
+					/* This is to handle an array failed */
+					cmd->result = (DID_TIME_OUT << 16);
+					printk(KERN_WARNING "%s: SCSI Data "
+					       "Protect-Device (%d,%d,%d) "
+					       "hba_status=0x%x, dev_status="
+					       "0x%x, cmd=0x%x\n", c->name,
+					       (u32) cmd->device->channel,
+					       (u32) cmd->device->id,
+					       (u32) cmd->device->lun,
+					       (error >> 8) & 0xff,
+					       error & 0xff, cmd->cmnd[0]);
+				} else
+					cmd->result = (DID_ERROR << 16);
+
+				break;
 			}
-			dprintk(KERN_INFO "Found disk %d %d.\n", target, lun);
-			h->task[target][lun]=unit->lct_data.tid;
-			h->tagclock[target][lun]=jiffies;
-
-			/* Get the max fragments/request */
-			i2o_query_scalar(c, d->lct_data.tid, 0xF103, 3, &limit, 2);
-			
-			/* sanity */
-			if ( limit == 0 )
-			{
-				printk(KERN_WARNING "i2o_scsi: Ignoring unreasonable SG limit of 0 from IOP!\n");
-				limit = 1;
+
+			switch (as) {
+			case 0x0E:
+				/* SCSI Reset */
+				cmd->result = DID_RESET << 16;
+				break;
+
+			case 0x0F:
+				cmd->result = DID_PARITY << 16;
+				break;
+
+			default:
+				cmd->result = DID_ERROR << 16;
+				break;
 			}
-			
-			shpnt->sg_tablesize = limit;
 
-			dprintk(KERN_INFO "i2o_scsi: set scatter-gather to %d.\n",
-				shpnt->sg_tablesize);
+			break;
 		}
-	}		
-}
+
+		cmd->scsi_done(cmd);
+		return 1;
+	}
+
+	cmd->result = DID_OK << 16 | ds;
+
+	cmd->scsi_done(cmd);
+
+	dev = &c->pdev->dev;
+	if (cmd->use_sg)
+		dma_unmap_sg(dev, (struct scatterlist *)cmd->buffer,
+			     cmd->use_sg, cmd->sc_data_direction);
+	else if (cmd->request_bufflen)
+		dma_unmap_single(dev, (dma_addr_t) ((long)cmd->SCp.ptr),
+				 cmd->request_bufflen, cmd->sc_data_direction);
+
+	return 1;
+};
 
 /**
- *	i2o_scsi_detect		-	probe for I2O scsi devices
- *	@tpnt: scsi layer template
+ *	i2o_scsi_notify_controller_add - Retrieve notifications of added
+ *					 controllers
+ *	@c: the controller which was added
  *
- *	I2O is a little odd here. The I2O core already knows what the
- *	devices are. It also knows them by disk and tape as well as
- *	by controller. We register each I2O scsi class object as a
- *	scsi controller and then let the enumeration fake up the rest
+ *	If a I2O controller is added, we catch the notification to add a
+ *	corresponding Scsi_Host.
  */
- 
-static int i2o_scsi_detect(struct scsi_host_template * tpnt)
+void i2o_scsi_notify_controller_add(struct i2o_controller *c)
 {
-	struct Scsi_Host *shpnt = NULL;
-	int i;
-	int count;
+	struct i2o_scsi_host *i2o_shost;
+	int rc;
 
-	printk(KERN_INFO "i2o_scsi.c: %s\n", VERSION_STRING);
-
-	if(i2o_install_handler(&i2o_scsi_handler)<0)
-	{
-		printk(KERN_ERR "i2o_scsi: Unable to install OSM handler.\n");
-		return 0;
-	}
-	scsi_context = i2o_scsi_handler.context;
-	
-	if((sg_chain_pool = kmalloc(SG_CHAIN_POOL_SZ, GFP_KERNEL)) == NULL)
-	{
-		printk(KERN_INFO "i2o_scsi: Unable to alloc %d byte SG chain buffer pool.\n", SG_CHAIN_POOL_SZ);
-		printk(KERN_INFO "i2o_scsi: SG chaining DISABLED!\n");
-		sg_max_frags = 11;
-	}
-	else
-	{
-		printk(KERN_INFO "  chain_pool: %d bytes @ %p\n", SG_CHAIN_POOL_SZ, sg_chain_pool);
-		printk(KERN_INFO "  (%d byte buffers X %d can_queue X %d i2o controllers)\n",
-				SG_CHAIN_BUF_SZ, I2O_SCSI_CAN_QUEUE, i2o_num_controllers);
-		sg_max_frags = SG_MAX_FRAGS;    // 64
-	}
-	
-	init_timer(&retry_timer);
-	retry_timer.data = 0UL;
-	retry_timer.function = i2o_retry_run;
-	
-//	printk("SCSI OSM at %d.\n", scsi_context);
-
-	for (count = 0, i = 0; i < MAX_I2O_CONTROLLERS; i++)
-	{
-		struct i2o_controller *c=i2o_find_controller(i);
-		struct i2o_device *d;
-		/*
-		 *	This controller doesn't exist.
-		 */
-		
-		if(c==NULL)
-			continue;
-			
-		/*
-		 *	Fixme - we need some altered device locking. This
-		 *	is racing with device addition in theory. Easy to fix.
-		 */
-		
-		for(d=c->devices;d!=NULL;d=d->next)
-		{
-			/*
-			 *	bus_adapter, SCSI (obsolete), or FibreChannel busses only
-			 */
-			if(    (d->lct_data.class_id!=I2O_CLASS_BUS_ADAPTER_PORT)	// bus_adapter
-//			    && (d->lct_data.class_id!=I2O_CLASS_FIBRE_CHANNEL_PORT)	// FC_PORT
-			  )
-				continue;
-		
-			shpnt = scsi_register(tpnt, sizeof(struct i2o_scsi_host));
-			if(shpnt==NULL)
-				continue;
-			shpnt->unique_id = (u32)d;
-			shpnt->io_port = 0;
-			shpnt->n_io_port = 0;
-			shpnt->irq = 0;
-			shpnt->this_id = /* Good question */15;
-			i2o_scsi_init(c, d, shpnt);
-			count++;
-		}
-	}
-	i2o_scsi_hosts = count;
-	
-	if(count==0)
-	{
-		if(sg_chain_pool!=NULL)
-		{
-			kfree(sg_chain_pool);
-			sg_chain_pool = NULL;
-		}
-		flush_pending();
-		del_timer(&retry_timer);
-		i2o_remove_handler(&i2o_scsi_handler);
+	i2o_shost = i2o_scsi_host_alloc(c);
+	if (IS_ERR(i2o_shost)) {
+		printk(KERN_ERR "scsi-osm: Could not initialize"
+		       " SCSI host\n");
+		return;
 	}
-	
-	return count;
-}
 
-static int i2o_scsi_release(struct Scsi_Host *host)
-{
-	if(--i2o_scsi_hosts==0)
-	{
-		if(sg_chain_pool!=NULL)
-		{
-			kfree(sg_chain_pool);
-			sg_chain_pool = NULL;
-		}
-		flush_pending();
-		del_timer(&retry_timer);
-		i2o_remove_handler(&i2o_scsi_handler);
+	rc = scsi_add_host(i2o_shost->scsi_host, &c->device);
+	if (rc) {
+		printk(KERN_ERR "scsi-osm: Could not add SCSI "
+		       "host\n");
+		scsi_host_put(i2o_shost->scsi_host);
+		return;
 	}
 
-	scsi_unregister(host);
-
-	return 0;
-}
+	c->driver_data[i2o_scsi_driver.context] = i2o_shost;
 
+	pr_debug("new I2O SCSI host added\n");
+};
 
-static const char *i2o_scsi_info(struct Scsi_Host *SChost)
+/**
+ *	i2o_scsi_notify_controller_remove - Retrieve notifications of removed
+ *					    controllers
+ *	@c: the controller which was removed
+ *
+ *	If a I2O controller is removed, we catch the notification to remove the
+ *	corresponding Scsi_Host.
+ */
+void i2o_scsi_notify_controller_remove(struct i2o_controller *c)
 {
-	struct i2o_scsi_host *hostdata;
-	hostdata = (struct i2o_scsi_host *)SChost->hostdata;
-	return(&hostdata->controller->name[0]);
-}
+	struct i2o_scsi_host *i2o_shost;
+	i2o_shost = i2o_scsi_get_host(c);
+	if (!i2o_shost)
+		return;
+
+	c->driver_data[i2o_scsi_driver.context] = NULL;
+
+	scsi_remove_host(i2o_shost->scsi_host);
+	scsi_host_put(i2o_shost->scsi_host);
+	pr_debug("I2O SCSI host removed\n");
+};
+
+/* SCSI OSM driver struct */
+static struct i2o_driver i2o_scsi_driver = {
+	.name = "scsi-osm",
+	.reply = i2o_scsi_reply,
+	.classes = i2o_scsi_class_id,
+	.notify_controller_add = i2o_scsi_notify_controller_add,
+	.notify_controller_remove = i2o_scsi_notify_controller_remove,
+	.driver = {
+		   .probe = i2o_scsi_probe,
+		   .remove = i2o_scsi_remove,
+		   },
+};
 
 /**
- *	i2o_scsi_queuecommand	-	queue a SCSI command
+ *	i2o_scsi_queuecommand - queue a SCSI command
  *	@SCpnt: scsi command pointer
  *	@done: callback for completion
  *
- *	Issue a scsi comamnd asynchronously. Return 0 on success or 1 if
- *	we hit an error (normally message queue congestion). The only 
+ *	Issue a scsi command asynchronously. Return 0 on success or 1 if
+ *	we hit an error (normally message queue congestion). The only
  *	minor complication here is that I2O deals with the device addressing
  *	so we have to map the bus/dev/lun back to an I2O handle as well
- *	as faking absent devices ourself. 
+ *	as faking absent devices ourself.
  *
  *	Locks: takes the controller lock on error path only
  */
- 
+
 static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
 				 void (*done) (struct scsi_cmnd *))
 {
-	int i;
-	int tid;
 	struct i2o_controller *c;
-	struct scsi_cmnd *current_command;
 	struct Scsi_Host *host;
-	struct i2o_scsi_host *hostdata;
-	u32 *msg, *mptr;
+	struct i2o_device *i2o_dev;
+	struct device *dev;
+	int tid;
+	struct i2o_message *msg;
 	u32 m;
-	u32 *lenptr;
-	int direction;
-	int scsidir;
-	u32 len;
-	u32 reqlen;
-	u32 tag;
-	unsigned long flags;
-	
-	static int max_qd = 1;
-	
+	u32 scsi_flags, sg_flags;
+	u32 *mptr, *lenptr;
+	u32 len, reqlen;
+	int i;
+
 	/*
-	 *	Do the incoming paperwork
+	 *      Do the incoming paperwork
 	 */
-	 
+
+	i2o_dev = SCpnt->device->hostdata;
 	host = SCpnt->device->host;
-	hostdata = (struct i2o_scsi_host *)host->hostdata;
-	 
-	c = hostdata->controller;
-	prefetch(c);
-	prefetchw(&queue_depth);
+	c = i2o_dev->iop;
+	dev = &c->pdev->dev;
 
 	SCpnt->scsi_done = done;
-	
-	if(SCpnt->device->id > 15)
-	{
-		printk(KERN_ERR "i2o_scsi: Wild target %d.\n", SCpnt->device->id);
-		return -1;
-	}
-	
-	tid = hostdata->task[SCpnt->device->id][SCpnt->device->lun];
-	
-	dprintk(KERN_INFO "qcmd: Tid = %d\n", tid);
-	
-	current_command = SCpnt;		/* set current command                */
-	current_command->scsi_done = done;	/* set ptr to done function           */
-
-	/* We don't have such a device. Pretend we did the command 
-	   and that selection timed out */
-	
-	if(tid == -1)
-	{
+
+	if (unlikely(!i2o_dev)) {
+		printk(KERN_WARNING "scsi-osm: no I2O device in request\n");
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
 		return 0;
 	}
-	
-	dprintk(KERN_INFO "Real scsi messages.\n");
+
+	tid = i2o_dev->lct_data.tid;
+
+	pr_debug("qcmd: Tid = %03x\n", tid);
+	pr_debug("Real scsi messages.\n");
 
 	/*
-	 *	Obtain an I2O message. If there are none free then 
-	 *	throw it back to the scsi layer
-	 */	
-	 
-	m = le32_to_cpu(I2O_POST_READ32(c));
-	if(m==0xFFFFFFFF)
-		return 1;
+	 *      Obtain an I2O message. If there are none free then
+	 *      throw it back to the scsi layer
+	 */
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return SCSI_MLQUEUE_HOST_BUSY;
 
-	msg = (u32 *)(c->msg_virt + m);
-	
 	/*
-	 *	Put together a scsi execscb message
+	 *      Put together a scsi execscb message
 	 */
-	
+
 	len = SCpnt->request_bufflen;
-	direction = 0x00000000;			// SGL IN  (osm<--iop)
-	
-	if (SCpnt->sc_data_direction == DMA_NONE) {
-		scsidir = 0x00000000;			// DATA NO XFER
-	} else if (SCpnt->sc_data_direction == DMA_TO_DEVICE) {
-		direction = 0x04000000;	// SGL OUT  (osm-->iop)
-		scsidir = 0x80000000;	// DATA OUT (iop-->dev)
-	} else if(SCpnt->sc_data_direction == DMA_FROM_DEVICE) {
-		scsidir = 0x40000000;	// DATA IN  (iop<--dev)
-	} else {
+
+	switch (SCpnt->sc_data_direction) {
+	case PCI_DMA_NONE:
+		scsi_flags = 0x00000000;	// DATA NO XFER
+		sg_flags = 0x00000000;
+		break;
+
+	case PCI_DMA_TODEVICE:
+		scsi_flags = 0x80000000;	// DATA OUT (iop-->dev)
+		sg_flags = 0x14000000;
+		break;
+
+	case PCI_DMA_FROMDEVICE:
+		scsi_flags = 0x40000000;	// DATA IN  (iop<--dev)
+		sg_flags = 0x10000000;
+		break;
+
+	default:
 		/* Unknown - kill the command */
 		SCpnt->result = DID_NO_CONNECT << 16;
-		
-		/* We must lock the request queue while completing */
-		spin_lock_irqsave(host->host_lock, flags);
 		done(SCpnt);
-		spin_unlock_irqrestore(host->host_lock, flags);
 		return 0;
 	}
 
-	
-	i2o_raw_writel(I2O_CMD_SCSI_EXEC<<24|HOST_TID<<12|tid, &msg[1]);
-	i2o_raw_writel(scsi_context, &msg[2]);	/* So the I2O layer passes to us */
-	i2o_raw_writel(i2o_context_list_add(SCpnt, c), &msg[3]);	/* We want the SCSI control block back */
+	writel(I2O_CMD_SCSI_EXEC << 24 | HOST_TID << 12 | tid, &msg->u.head[1]);
+	writel(i2o_scsi_driver.context, &msg->u.s.icntxt);
+
+	/* We want the SCSI control block back */
+	writel(i2o_cntxt_list_add(c, SCpnt), &msg->u.s.tcntxt);
 
 	/* LSI_920_PCI_QUIRK
 	 *
-	 *	Intermittant observations of msg frame word data corruption
-	 *	observed on msg[4] after:
-	 *	  WRITE, READ-MODIFY-WRITE
-	 *	operations.  19990606 -sralston
+	 *      Intermittant observations of msg frame word data corruption
+	 *      observed on msg[4] after:
+	 *        WRITE, READ-MODIFY-WRITE
+	 *      operations.  19990606 -sralston
 	 *
-	 *	(Hence we build this word via tag. Its good practice anyway
-	 *	 we don't want fetches over PCI needlessly)
+	 *      (Hence we build this word via tag. Its good practice anyway
+	 *       we don't want fetches over PCI needlessly)
 	 */
 
-	tag=0;
-	
+	/* Attach tags to the devices */
 	/*
-	 *	Attach tags to the devices
-	 */	
-	if(SCpnt->device->tagged_supported)
-	{
-		/*
-		 *	Some drives are too stupid to handle fairness issues
-		 *	with tagged queueing. We throw in the odd ordered
-		 *	tag to stop them starving themselves.
-		 */
-		if((jiffies - hostdata->tagclock[SCpnt->device->id][SCpnt->device->lun]) > (5*HZ))
-		{
-			tag=0x01800000;		/* ORDERED! */
-			hostdata->tagclock[SCpnt->device->id][SCpnt->device->lun]=jiffies;
-		}
-		else
-		{
-			/* Hmmm...  I always see value of 0 here,
-			 *  of which {HEAD_OF, ORDERED, SIMPLE} are NOT!  -sralston
-			 */
-			if(SCpnt->tag == HEAD_OF_QUEUE_TAG)
-				tag=0x01000000;
-			else if(SCpnt->tag == ORDERED_QUEUE_TAG)
-				tag=0x01800000;
-		}
-	}
+	   if(SCpnt->device->tagged_supported) {
+	   if(SCpnt->tag == HEAD_OF_QUEUE_TAG)
+	   scsi_flags |= 0x01000000;
+	   else if(SCpnt->tag == ORDERED_QUEUE_TAG)
+	   scsi_flags |= 0x01800000;
+	   }
+	 */
 
 	/* Direction, disconnect ok, tag, CDBLen */
-	i2o_raw_writel(scsidir|0x20000000|SCpnt->cmd_len|tag, &msg[4]);
+	writel(scsi_flags | 0x20200000 | SCpnt->cmd_len, &msg->body[0]);
 
-	mptr=msg+5;
+	mptr = &msg->body[1];
 
-	/* 
-	 *	Write SCSI command into the message - always 16 byte block 
-	 */
-	 
+	/* Write SCSI command into the message - always 16 byte block */
 	memcpy_toio(mptr, SCpnt->cmnd, 16);
-	mptr+=4;
-	lenptr=mptr++;		/* Remember me - fill in when we know */
-	
+	mptr += 4;
+	lenptr = mptr++;	/* Remember me - fill in when we know */
+
 	reqlen = 12;		// SINGLE SGE
-	
-	/*
-	 *	Now fill in the SGList and command 
-	 *
-	 *	FIXME: we need to set the sglist limits according to the 
-	 *	message size of the I2O controller. We might only have room
-	 *	for 6 or so worst case
-	 */
-	
-	if(SCpnt->use_sg)
-	{
-		struct scatterlist *sg = (struct scatterlist *)SCpnt->request_buffer;
+
+	/* Now fill in the SGList and command */
+	if (SCpnt->use_sg) {
+		struct scatterlist *sg;
 		int sg_count;
-		int chain = 0;
-		
+
+		sg = SCpnt->request_buffer;
 		len = 0;
 
-		sg_count = pci_map_sg(c->pdev, sg, SCpnt->use_sg,
-				SCpnt->sc_data_direction);
-
-		/* FIXME: handle fail */
-		if(!sg_count)
-			BUG();
-		
-		if((sg_max_frags > 11) && (SCpnt->use_sg > 11))
-		{
-			chain = 1;
-			/*
-			 *	Need to chain!
-			 */
-			i2o_raw_writel(direction|0xB0000000|(SCpnt->use_sg*2*4), mptr++);
-			i2o_raw_writel(virt_to_bus(sg_chain_pool + sg_chain_tag), mptr);
-			mptr = (u32*)(sg_chain_pool + sg_chain_tag);
-			if (SCpnt->use_sg > max_sg_len)
-			{
-				max_sg_len = SCpnt->use_sg;
-				printk("i2o_scsi: Chain SG! SCpnt=%p, SG_FragCnt=%d, SG_idx=%d\n",
-					SCpnt, SCpnt->use_sg, sg_chain_tag);
-			}
-			if ( ++sg_chain_tag == SG_MAX_BUFS )
-				sg_chain_tag = 0;
-			for(i = 0 ; i < SCpnt->use_sg; i++)
-			{
-				*mptr++=cpu_to_le32(direction|0x10000000|sg_dma_len(sg));
-				len+=sg_dma_len(sg);
-				*mptr++=cpu_to_le32(sg_dma_address(sg));
-				sg++;
-			}
-			mptr[-2]=cpu_to_le32(direction|0xD0000000|sg_dma_len(sg-1));
-		}
-		else
-		{		
-			for(i = 0 ; i < SCpnt->use_sg; i++)
-			{
-				i2o_raw_writel(direction|0x10000000|sg_dma_len(sg), mptr++);
-				len+=sg->length;
-				i2o_raw_writel(sg_dma_address(sg), mptr++);
-				sg++;
-			}
+		sg_count = dma_map_sg(dev, sg, SCpnt->use_sg,
+				      SCpnt->sc_data_direction);
 
-			/* Make this an end of list. Again evade the 920 bug and
-			   unwanted PCI read traffic */
-		
-			i2o_raw_writel(direction|0xD0000000|sg_dma_len(sg-1), &mptr[-2]);
-		}
-		
-		if(!chain)
-			reqlen = mptr - msg;
-		
-		i2o_raw_writel(len, lenptr);
-		
-		if(len != SCpnt->underflow)
-			printk("Cmd len %08X Cmd underflow %08X\n",
-				len, SCpnt->underflow);
-	}
-	else
-	{
-		dprintk(KERN_INFO "non sg for %p, %d\n", SCpnt->request_buffer,
-				SCpnt->request_bufflen);
-		i2o_raw_writel(len = SCpnt->request_bufflen, lenptr);
-		if(len == 0)
-		{
-			reqlen = 9;
+		if (unlikely(sg_count <= 0))
+			return -ENOMEM;
+
+		for (i = SCpnt->use_sg; i > 0; i--) {
+			if (i == 1)
+				sg_flags |= 0xC0000000;
+			writel(sg_flags | sg_dma_len(sg), mptr++);
+			writel(sg_dma_address(sg), mptr++);
+			len += sg_dma_len(sg);
+			sg++;
 		}
-		else
-		{
+
+		reqlen = mptr - &msg->u.head[0];
+		writel(len, lenptr);
+	} else {
+		len = SCpnt->request_bufflen;
+
+		writel(len, lenptr);
+
+		if (len > 0) {
 			dma_addr_t dma_addr;
-			dma_addr = pci_map_single(c->pdev,
-					       SCpnt->request_buffer,
-					       SCpnt->request_bufflen,
-					       SCpnt->sc_data_direction);
-			if(dma_addr == 0)
-				BUG();	/* How to handle ?? */
-			SCpnt->SCp.ptr = (char *)(unsigned long) dma_addr;
-			i2o_raw_writel(0xD0000000|direction|SCpnt->request_bufflen, mptr++);
-			i2o_raw_writel(dma_addr, mptr++);
-		}
+
+			dma_addr = dma_map_single(dev, SCpnt->request_buffer,
+						  SCpnt->request_bufflen,
+						  SCpnt->sc_data_direction);
+			if (!dma_addr)
+				return -ENOMEM;
+
+			SCpnt->SCp.ptr = (void *)(unsigned long)dma_addr;
+			sg_flags |= 0xC0000000;
+			writel(sg_flags | SCpnt->request_bufflen, mptr++);
+			writel(dma_addr, mptr++);
+		} else
+			reqlen = 9;
 	}
-	
-	/*
-	 *	Stick the headers on 
-	 */
 
-	i2o_raw_writel(reqlen<<16 | SGL_OFFSET_10, msg);
-	
+	/* Stick the headers on */
+	writel(reqlen << 16 | SGL_OFFSET_10, &msg->u.head[0]);
+
 	/* Queue the message */
-	i2o_post_message(c,m);
-	
-	atomic_inc(&queue_depth);
-	
-	if(atomic_read(&queue_depth)> max_qd)
-	{
-		max_qd=atomic_read(&queue_depth);
-		printk("Queue depth now %d.\n", max_qd);
-	}
-	
-	mb();
-	dprintk(KERN_INFO "Issued %ld\n", current_command->serial_number);
-	
+	i2o_msg_post(c, m);
+
+	pr_debug("Issued %ld\n", SCpnt->serial_number);
+
 	return 0;
-}
+};
 
 /**
- *	i2o_scsi_abort	-	abort a running command
+ *	i2o_scsi_abort - abort a running command
  *	@SCpnt: command to abort
  *
  *	Ask the I2O controller to abort a command. This is an asynchrnous
- *	process and our callback handler will see the command complete
- *	with an aborted message if it succeeds. 
+ *	process and our callback handler will see the command complete with an
+ *	aborted message if it succeeds.
  *
- *	Locks: no locks are held or needed
+ *	Returns 0 if the command is successfully aborted or negative error code
+ *	on failure.
  */
- 
-static int i2o_scsi_abort(struct scsi_cmnd * SCpnt)
+int i2o_scsi_abort(struct scsi_cmnd *SCpnt)
 {
+	struct i2o_device *i2o_dev;
 	struct i2o_controller *c;
-	struct Scsi_Host *host;
-	struct i2o_scsi_host *hostdata;
-	u32 msg[5];
+	struct i2o_message *msg;
+	u32 m;
 	int tid;
 	int status = FAILED;
-	
-	printk(KERN_WARNING "i2o_scsi: Aborting command block.\n");
-	
-	host = SCpnt->device->host;
-	hostdata = (struct i2o_scsi_host *)host->hostdata;
-	tid = hostdata->task[SCpnt->device->id][SCpnt->device->lun];
-	if(tid==-1)
-	{
-		printk(KERN_ERR "i2o_scsi: Impossible command to abort!\n");
-		return status;
-	}
-	c = hostdata->controller;
-
-	spin_unlock_irq(host->host_lock);
-		
-	msg[0] = FIVE_WORD_MSG_SIZE;
-	msg[1] = I2O_CMD_SCSI_ABORT<<24|HOST_TID<<12|tid;
-	msg[2] = scsi_context;
-	msg[3] = 0;
-	msg[4] = i2o_context_list_remove(SCpnt, c);
-	if(i2o_post_wait(c, msg, sizeof(msg), 240))
-		status = SUCCESS;
-
-	spin_lock_irq(host->host_lock);
-	return status;
-}
-
-/**
- *	i2o_scsi_bus_reset		-	Issue a SCSI reset
- *	@SCpnt: the command that caused the reset
- *
- *	Perform a SCSI bus reset operation. In I2O this is just a message
- *	we pass. I2O can do clever multi-initiator and shared reset stuff
- *	but we don't support this.
- *
- *	Locks: called with no lock held, requires no locks.
- */
- 
-static int i2o_scsi_bus_reset(struct scsi_cmnd * SCpnt)
-{
-	int tid;
-	struct i2o_controller *c;
-	struct Scsi_Host *host;
-	struct i2o_scsi_host *hostdata;
-	u32 m;
-	void *msg;
-	unsigned long timeout;
-
-	
-	/*
-	 *	Find the TID for the bus
-	 */
 
-	
-	host = SCpnt->device->host;
+	printk(KERN_WARNING "i2o_scsi: Aborting command block.\n");
 
-	spin_unlock_irq(host->host_lock);
+	i2o_dev = SCpnt->device->hostdata;
+	c = i2o_dev->iop;
+	tid = i2o_dev->lct_data.tid;
 
-	printk(KERN_WARNING "i2o_scsi: Attempting to reset the bus.\n");
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return SCSI_MLQUEUE_HOST_BUSY;
 
-	hostdata = (struct i2o_scsi_host *)host->hostdata;
-	tid = hostdata->bus_task;
-	c = hostdata->controller;
+	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid,
+	       &msg->u.head[1]);
+	writel(i2o_cntxt_list_get_ptr(c, SCpnt), &msg->body[0]);
 
-	/*
-	 *	Now send a SCSI reset request. Any remaining commands
-	 *	will be aborted by the IOP. We need to catch the reply
-	 *	possibly ?
-	 */
+	if (i2o_msg_post_wait(c, m, I2O_TIMEOUT_SCSI_SCB_ABORT))
+		status = SUCCESS;
 
-	timeout = jiffies+2*HZ;
-	do
-	{
-		m = le32_to_cpu(I2O_POST_READ32(c));
-		if(m != 0xFFFFFFFF)
-			break;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(1);
-		mb();
-	}
-	while(time_before(jiffies, timeout));
-	
-	
-	msg = c->msg_virt + m;
-	i2o_raw_writel(FOUR_WORD_MSG_SIZE|SGL_OFFSET_0, msg);
-	i2o_raw_writel(I2O_CMD_SCSI_BUSRESET<<24|HOST_TID<<12|tid, msg+4);
-	i2o_raw_writel(scsi_context|0x80000000, msg+8);
-	/* We use the top bit to split controller and unit transactions */
-	/* Now store unit,tid so we can tie the completion back to a specific device */
-	__raw_writel(c->unit << 16 | tid, msg+12);
-	wmb();
-
-	/* We want the command to complete after we return */	
-	spin_lock_irq(host->host_lock);
-	i2o_post_message(c,m);
-
-	/* Should we wait for the reset to complete ? */	
-	return SUCCESS;
+	return status;
 }
 
 /**
  *	i2o_scsi_bios_param	-	Invent disk geometry
- *	@sdev: scsi device 
+ *	@sdev: scsi device
  *	@dev: block layer device
  *	@capacity: size in sectors
  *	@ip: geometry array
  *
- *	This is anyones guess quite frankly. We use the same rules everyone 
+ *	This is anyones guess quite frankly. We use the same rules everyone
  *	else appears to and hope. It seems to work.
  */
- 
-static int i2o_scsi_bios_param(struct scsi_device * sdev,
-		struct block_device *dev, sector_t capacity, int *ip)
+
+static int i2o_scsi_bios_param(struct scsi_device *sdev,
+			       struct block_device *dev, sector_t capacity,
+			       int *ip)
 {
 	int size;
 
@@ -1023,25 +819,64 @@ static int i2o_scsi_bios_param(struct scsi_device * sdev,
 	return 0;
 }
 
-MODULE_AUTHOR("Red Hat Software");
-MODULE_LICENSE("GPL");
+static struct scsi_host_template i2o_scsi_host_template = {
+	.proc_name = "SCSI-OSM",
+	.name = "I2O SCSI Peripheral OSM",
+	.info = i2o_scsi_info,
+	.queuecommand = i2o_scsi_queuecommand,
+	.eh_abort_handler = i2o_scsi_abort,
+	.bios_param = i2o_scsi_bios_param,
+	.can_queue = I2O_SCSI_CAN_QUEUE,
+	.sg_tablesize = 8,
+	.cmd_per_lun = 6,
+	.use_clustering = ENABLE_CLUSTERING,
+};
 
+/*
+int
+i2o_scsi_queuecommand(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *))
+{
+	printk(KERN_INFO "queuecommand\n");
+	return SCSI_MLQUEUE_HOST_BUSY;
+};
+*/
 
-static struct scsi_host_template driver_template = {
-	.proc_name		= "i2o_scsi",
-	.name			= "I2O SCSI Layer",
-	.detect			= i2o_scsi_detect,
-	.release		= i2o_scsi_release,
-	.info			= i2o_scsi_info,
-	.queuecommand		= i2o_scsi_queuecommand,
-	.eh_abort_handler	= i2o_scsi_abort,
-	.eh_bus_reset_handler	= i2o_scsi_bus_reset,
-	.bios_param		= i2o_scsi_bios_param,
-	.can_queue		= I2O_SCSI_CAN_QUEUE,
-	.this_id		= 15,
-	.sg_tablesize		= 8,
-	.cmd_per_lun		= 6,
-	.use_clustering		= ENABLE_CLUSTERING,
+/**
+ *	i2o_scsi_init - SCSI OSM initialization function
+ *
+ *	Register SCSI OSM into I2O core.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int __init i2o_scsi_init(void)
+{
+	int rc;
+
+	printk(KERN_INFO "I2O SCSI Peripheral OSM\n");
+
+	/* Register SCSI OSM into I2O core */
+	rc = i2o_driver_register(&i2o_scsi_driver);
+	if (rc) {
+		printk(KERN_ERR "scsi-osm: Could not register SCSI driver\n");
+		return rc;
+	}
+
+	return 0;
 };
 
-#include "../../scsi/scsi_module.c"
+/**
+ *	i2o_scsi_exit - SCSI OSM exit function
+ *
+ *	Unregisters SCSI OSM from I2O core.
+ */
+static void __exit i2o_scsi_exit(void)
+{
+	/* Unregister I2O SCSI OSM from I2O core */
+	i2o_driver_unregister(&i2o_scsi_driver);
+};
+
+MODULE_AUTHOR("Red Hat Software");
+MODULE_LICENSE("GPL");
+
+module_init(i2o_scsi_init);
+module_exit(i2o_scsi_exit);
diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c
index ee29ced87..9dcf33c2a 100644
--- a/drivers/misc/ibmasm/module.c
+++ b/drivers/misc/ibmasm/module.c
@@ -62,10 +62,17 @@ static int __init ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_
 	int result = -ENOMEM;
 	struct service_processor *sp;
 
+	if (pci_enable_device(pdev)) {
+		printk(KERN_ERR "%s: can't enable PCI device at %s\n",
+			DRIVER_NAME, pci_name(pdev));
+		return -ENODEV;
+	}
+
 	sp = kmalloc(sizeof(struct service_processor), GFP_KERNEL);
 	if (sp == NULL) {
 		dev_err(&pdev->dev, "Failed to allocate memory\n");
-		return result;
+		result = -ENOMEM;
+		goto error_kmalloc;
 	}
 	memset(sp, 0, sizeof(struct service_processor));
 
@@ -148,6 +155,8 @@ error_heartbeat:
 	ibmasm_event_buffer_exit(sp);
 error_eventbuffer:
 	kfree(sp);
+error_kmalloc:
+	pci_disable_device(pdev);
 
 	return result;
 }
@@ -166,6 +175,7 @@ static void __exit ibmasm_remove_one(struct pci_dev *pdev)
 	iounmap(sp->base_address);
 	ibmasm_event_buffer_exit(sp);
 	kfree(sp);
+	pci_disable_device(pdev);
 }
 
 static struct pci_device_id ibmasm_pci_table[] =
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index e71624edb..c1e3536c2 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -603,6 +603,8 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad
 				}
 				spin_unlock(&shared->lock);
 			}
+		} else {
+			spin_unlock(&shared->lock);
 		}
 	}
 
@@ -1437,8 +1439,7 @@ static int do_erase_oneblock(struct map_info *map, struct flchip *chip,
 
 	spin_unlock(chip->mutex);
 	INVALIDATE_CACHED_RANGE(map, adr, len);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout((chip->erase_time*HZ)/(2*1000));
+	msleep(chip->erase_time / 2);
 	spin_lock(chip->mutex);
 
 	/* FIXME. Use a timer to check this, and return immediately. */
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
index daf554c00..8fb85f079 100644
--- a/drivers/mtd/chips/jedec_probe.c
+++ b/drivers/mtd/chips/jedec_probe.c
@@ -29,6 +29,7 @@
 #define MANUFACTURER_AMD	0x0001
 #define MANUFACTURER_ATMEL	0x001f
 #define MANUFACTURER_FUJITSU	0x0004
+#define MANUFACTURER_HYUNDAI	0x00AD
 #define MANUFACTURER_INTEL	0x0089
 #define MANUFACTURER_MACRONIX	0x00C2
 #define MANUFACTURER_PMC	0x009D
@@ -56,6 +57,7 @@
 #define AM29F040	0x00A4
 #define AM29LV040B	0x004F
 #define AM29F032B	0x0041
+#define AM29F002T	0x00B0
 
 /* Atmel */
 #define AT49BV512	0x0003
@@ -77,6 +79,8 @@
 #define MBM29LV400TC	0x22B9
 #define MBM29LV400BC	0x22BA
 
+/* Hyundai */
+#define HY29F002T	0x00B0
 
 /* Intel */
 #define I28F004B3T	0x00d4
@@ -106,6 +110,7 @@
 #define MX29LV160T	0x22C4
 #define MX29LV160B	0x2249
 #define MX29F016	0x00AD
+#define MX29F002T	0x00B0
 #define MX29F004T	0x0045
 #define MX29F004B	0x0046
 
@@ -506,6 +511,17 @@ static const struct amd_flash_info jedec_table[] = {
 		.regions	= {
 			ERASEINFO(0x10000,8),
 		}
+	}, {
+		.mfr_id = MANUFACTURER_AMD,
+		.dev_id = AM29F002T,
+		.name = "AMD AM29F002T",
+		.DevSize = SIZE_256KiB,
+		.NumEraseRegions = 4,
+		.regions = {ERASEINFO(0x10000,3),
+			  ERASEINFO(0x08000,1),
+			  ERASEINFO(0x02000,2),
+			  ERASEINFO(0x04000,1)
+		}
 	}, {
 		.mfr_id		= MANUFACTURER_ATMEL,
 		.dev_id		= AT49BV512,
@@ -751,6 +767,17 @@ static const struct amd_flash_info jedec_table[] = {
 			ERASEINFO(0x02000,2),
 			ERASEINFO(0x04000,1)
 		}
+	}, {
+		.mfr_id = MANUFACTURER_HYUNDAI,
+		.dev_id = HY29F002T,
+		.name = "Hyundai HY29F002T",
+		.DevSize = SIZE_256KiB,
+		.NumEraseRegions = 4,
+		.regions = {ERASEINFO(0x10000,3),
+			  ERASEINFO(0x08000,1),
+			  ERASEINFO(0x02000,2),
+			  ERASEINFO(0x04000,1)
+		}
 	}, {
 		.mfr_id		= MANUFACTURER_INTEL,
 		.dev_id		= I28F004B3B,
@@ -1134,6 +1161,17 @@ static const struct amd_flash_info jedec_table[] = {
 			ERASEINFO(0x08000,1),
 			ERASEINFO(0x10000,7),
 		}
+	}, {
+		.mfr_id = MANUFACTURER_MACRONIX,
+		.dev_id = MX29F002T,
+		.name = "Macronix MX29F002T",
+		.DevSize = SIZE_256KiB,
+		.NumEraseRegions = 4,
+		.regions = {ERASEINFO(0x10000,3),
+			  ERASEINFO(0x08000,1),
+			  ERASEINFO(0x02000,2),
+			  ERASEINFO(0x04000,1)
+		}
 	}, {
 		.mfr_id		= MANUFACTURER_PMC,
 		.dev_id		= PM49FL002,
@@ -1209,7 +1247,7 @@ static const struct amd_flash_info jedec_table[] = {
  		.DevSize	= SIZE_256KiB,
  		.CmdSet		= P_ID_SST_PAGE,
  		.NumEraseRegions= 1,
- 		regions: {ERASEINFO(0x01000,64),
+ 		.regions = {ERASEINFO(0x01000,64),
  		}
          }, {
  		.mfr_id		= MANUFACTURER_SST,
@@ -1221,7 +1259,7 @@ static const struct amd_flash_info jedec_table[] = {
  		.DevSize	= SIZE_256KiB,
  		.CmdSet		= P_ID_SST_PAGE,
  		.NumEraseRegions= 1,
- 		regions: {ERASEINFO(0x01000,64),
+ 		.regions = {ERASEINFO(0x01000,64),
  		}
 	}, {
 		.mfr_id		= MANUFACTURER_SST,
@@ -1570,7 +1608,7 @@ static const struct amd_flash_info jedec_table[] = {
 			ERASEINFO(0x02000, 2),
 			ERASEINFO(0x04000, 1),
 		}
-	} 
+	}
 };
 
 
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index cdc5bbd16..7458b68da 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -473,6 +473,15 @@ config MTD_IXP4XX
 	  IXDP425 and Coyote. If you have an IXP4xx based board and
 	  would like to use the flash chips on it, say 'Y'.
 
+config MTD_IXP2000
+	tristate "CFI Flash device mapped on Intel IXP2000 based systems"
+	depends on ARM && MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP2000
+	help
+	  This enables MTD access to flash devices on platforms based
+	  on Intel's IXP2000 family of network processors such as the
+	  IXDP2400 and IXDP2401. If you have an IXP2000 based board and
+	  would like to use the flash chips on it, say 'Y'.
+
 config MTD_EPXA10DB
 	tristate "CFI Flash device mapped on Epxa10db"
 	depends on ARM && MTD_CFI && MTD_PARTITIONS && ARCH_CAMELOT
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index 505178f36..7fa2ae016 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -62,5 +62,6 @@ obj-$(CONFIG_MTD_SBC8240)	+= sbc8240.o
 obj-$(CONFIG_MTD_NOR_TOTO)	+= omap-toto-flash.o
 obj-$(CONFIG_MTD_MPC1211)	+= mpc1211.o
 obj-$(CONFIG_MTD_IXP4XX)	+= ixp4xx.o
+obj-$(CONFIG_MTD_IXP2000)	+= ixp2000.o
 obj-$(CONFIG_MTD_WRSBC8260)	+= wr_sbc82xx_flash.o
 obj-$(CONFIG_MTD_DMV182)	+= dmv182.o
diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c
index 7f3ab3768..b43312731 100644
--- a/drivers/mtd/maps/amd76xrom.c
+++ b/drivers/mtd/maps/amd76xrom.c
@@ -26,7 +26,7 @@
 struct amd76xrom_map_info {
 	struct map_info map;
 	struct mtd_info *mtd;
-	unsigned long window_addr;
+	void __iomem * window_addr;
 	u32 window_start, window_size;
 	struct pci_dev *pdev;
 	struct resource window_rsrc;
@@ -57,7 +57,7 @@ static void amd76xrom_cleanup(struct amd76xrom_map_info *info)
 		del_mtd_device(info->mtd);
 		map_destroy(info->mtd);
 		info->mtd = NULL;
-		info->map.virt = 0;
+		info->map.virt = NULL;
 	}
 	if (info->rom_rsrc.parent)
 		release_resource(&info->rom_rsrc);
@@ -65,8 +65,8 @@ static void amd76xrom_cleanup(struct amd76xrom_map_info *info)
 		release_resource(&info->window_rsrc);
 
 	if (info->window_addr) {
-		iounmap((void *)(info->window_addr));
-		info->window_addr = 0;
+		iounmap(info->window_addr);
+		info->window_addr = NULL;
 	}
 }
 
@@ -136,8 +136,7 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev,
 		printk(KERN_NOTICE MOD_NAME " window : %x at %x\n", 
 		       window->size, window->start);
 		/* For write accesses caches are useless */
-		info->window_addr =
-			(unsigned long)ioremap_nocache(window->start,
+		info->window_addr = ioremap_nocache(window->start,
 						       window->size);
 
 		if (!info->window_addr) {
@@ -163,8 +162,8 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev,
 			}
 			if (info->mtd) goto found_mtd;
 		}
-		iounmap((void *)(info->window_addr));
-		info->window_addr = 0;
+		iounmap(info->window_addr);
+		info->window_addr = NULL;
 
 		/* Disable writes through the rom window */
 		pci_read_config_byte(pdev, 0x40, &byte);
diff --git a/drivers/mtd/maps/ceiva.c b/drivers/mtd/maps/ceiva.c
index 8475505f0..e34420bb1 100644
--- a/drivers/mtd/maps/ceiva.c
+++ b/drivers/mtd/maps/ceiva.c
@@ -103,7 +103,7 @@ struct clps_info {
 	unsigned long base;
 	unsigned long size;
 	int width;
-	void *vbase;
+	void __iomem *vbase;
 	struct map_info *map;
 	struct mtd_info *mtd;
 	struct resource *res;
@@ -150,7 +150,7 @@ static int __init clps_setup_mtd(struct clps_info *clps, int nr, struct mtd_info
 			break;
 		}
 
-		clps[i].map->virt = (unsigned long)clps[i].vbase;
+		clps[i].map->virt = clps[i].vbase;
 		clps[i].map->bankwidth = clps[i].width;
 		clps[i].map->size = clps[i].size;
 
diff --git a/drivers/mtd/maps/edb7312.c b/drivers/mtd/maps/edb7312.c
index 842f1b046..b7fd849dc 100644
--- a/drivers/mtd/maps/edb7312.c
+++ b/drivers/mtd/maps/edb7312.c
@@ -71,14 +71,14 @@ static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
 
 #endif
 
-static int                   mtd_parts_nb = 0;
-static struct mtd_partition *mtd_parts    = 0;
+static int mtd_parts_nb;
+static struct mtd_partition *mtd_parts;
 
 int __init init_edb7312nor(void)
 {
 	static const char *rom_probe_types[] = PROBETYPES;
 	const char **type;
-	const char *part_type = 0;
+	const char *part_type = NULL;
 
        	printk(KERN_NOTICE MSG_PREFIX "0x%08x at 0x%08x\n", 
 	       WINDOW_SIZE, WINDOW_ADDR);
@@ -92,7 +92,7 @@ int __init init_edb7312nor(void)
 	
 	simple_map_init(&edb7312nor_map);
 
-	mymtd = 0;
+	mymtd = NULL;
 	type = rom_probe_types;
 	for(; !mymtd && *type; type++) {
 		mymtd = do_map_probe(*type, &edb7312nor_map);
diff --git a/drivers/mtd/maps/impa7.c b/drivers/mtd/maps/impa7.c
index a05fc01b9..7d2b42436 100644
--- a/drivers/mtd/maps/impa7.c
+++ b/drivers/mtd/maps/impa7.c
@@ -77,7 +77,7 @@ int __init init_impa7(void)
 {
 	static const char *rom_probe_types[] = PROBETYPES;
 	const char **type;
-	const char *part_type = 0;
+	const char *part_type = NULL;
 	int i;
 	static struct { u_long addr; u_long size; } pt[NUM_FLASHBANKS] = {
 	  { WINDOW_ADDR0, WINDOW_SIZE0 },
@@ -99,7 +99,7 @@ int __init init_impa7(void)
 		}
 		simple_map_init(&impa7_map[i]);
 
-		impa7_mtd[i] = 0;
+		impa7_mtd[i] = NULL;
 		type = rom_probe_types;
 		for(; !impa7_mtd[i] && *type; type++) {
 			impa7_mtd[i] = do_map_probe(*type, &impa7_map[i]);
diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c
index 7ebc8cc5b..1770b1acc 100644
--- a/drivers/mtd/maps/ixp4xx.c
+++ b/drivers/mtd/maps/ixp4xx.c
@@ -1,5 +1,5 @@
 /*
- * $Id: ixp4xx.c,v 1.3 2004/07/12 22:38:29 dwmw2 Exp $
+ * $Id: ixp4xx.c,v 1.6 2004/09/17 00:25:06 gleixner Exp $
  *
  * drivers/mtd/maps/ixp4xx.c
  *
@@ -69,9 +69,22 @@ static void ixp4xx_copy_from(struct map_info *map, void *to,
 		dest[len - 1] = BYTE0(src[i]);
 }
 
+/*
+ * Unaligned writes are ignored, causing the 8-bit
+ * probe to fail and proceed to the 16-bit probe (which succeeds).
+ */
+static void ixp4xx_probe_write16(struct map_info *map, map_word d, unsigned long adr)
+{
+	if (!(adr & 1))
+	       *(__u16 *) (map->map_priv_1 + adr) = d.x[0];
+}
+
+/*
+ * Fast write16 function without the probing check above
+ */
 static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr)
 {
-	*(__u16 *) (map->map_priv_1 + adr) = d.x[0];
+       *(__u16 *) (map->map_priv_1 + adr) = d.x[0];
 }
 
 struct ixp4xx_flash_info {
@@ -88,6 +101,7 @@ static int ixp4xx_flash_remove(struct device *_dev)
 	struct platform_device *dev = to_platform_device(_dev);
 	struct flash_platform_data *plat = dev->dev.platform_data;
 	struct ixp4xx_flash_info *info = dev_get_drvdata(&dev->dev);
+	map_word d;
 
 	dev_set_drvdata(&dev->dev, NULL);
 
@@ -97,7 +111,8 @@ static int ixp4xx_flash_remove(struct device *_dev)
 	/*
 	 * This is required for a soft reboot to work.
 	 */
-	ixp4xx_write16(&info->map, 0xff, 0x55 * 0x2);
+	d.x[0] = 0xff;
+	ixp4xx_write16(&info->map, d, 0x55 * 0x2);
 
 	if (info->mtd) {
 		del_mtd_partitions(info->mtd);
@@ -169,7 +184,7 @@ static int ixp4xx_flash_probe(struct device *_dev)
 	info->map.bankwidth = 2;
 	info->map.name = dev->dev.bus_id;
 	info->map.read = ixp4xx_read16,
-	info->map.write = ixp4xx_write16,
+	info->map.write = ixp4xx_probe_write16,
 	info->map.copy_from = ixp4xx_copy_from,
 
 	info->res = request_mem_region(dev->resource->start, 
@@ -182,7 +197,7 @@ static int ixp4xx_flash_probe(struct device *_dev)
 	}
 
 	info->map.map_priv_1 =
-	    (unsigned long) ioremap(dev->resource->start, 
+	    (void __iomem *) ioremap(dev->resource->start,
 				    dev->resource->end - dev->resource->start + 1);
 	if (!info->map.map_priv_1) {
 		printk(KERN_ERR "IXP4XXFlash: Failed to ioremap region\n");
@@ -198,6 +213,9 @@ static int ixp4xx_flash_probe(struct device *_dev)
 	}
 	info->mtd->owner = THIS_MODULE;
 
+	/* Use the fast version */
+	info->map.write = ixp4xx_write16,
+
 	err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
 	if (err > 0) {
 		err = add_mtd_partitions(info->mtd, info->partitions, err);
diff --git a/drivers/mtd/maps/lubbock-flash.c b/drivers/mtd/maps/lubbock-flash.c
index 53e708b2e..881eab984 100644
--- a/drivers/mtd/maps/lubbock-flash.c
+++ b/drivers/mtd/maps/lubbock-flash.c
@@ -1,5 +1,5 @@
 /*
- * $Id: lubbock-flash.c,v 1.15 2004/07/12 21:59:44 dwmw2 Exp $
+ * $Id: lubbock-flash.c,v 1.18 2004/09/28 18:54:40 nico Exp $
  *
  * Map driver for the Lubbock developer platform.
  *
@@ -15,11 +15,13 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/dma-mapping.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
 #include <asm/io.h>
 #include <asm/hardware.h>
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/lubbock.h>
 
 
@@ -82,16 +84,14 @@ static int __init init_lubbock(void)
 	lubbock_maps[flashboot].name = "Lubbock Boot ROM";
 
 	for (i = 0; i < 2; i++) {
-		lubbock_maps[i].virt = (unsigned long)ioremap(lubbock_maps[i].phys, WINDOW_SIZE);
+		lubbock_maps[i].virt = (void __iomem *)ioremap(lubbock_maps[i].phys, WINDOW_SIZE);
 		if (!lubbock_maps[i].virt) {
 			printk(KERN_WARNING "Failed to ioremap %s\n", lubbock_maps[i].name);
 			if (!ret)
 				ret = -ENOMEM;
 			continue;
 		}
-		lubbock_maps[i].cached = __ioremap(lubbock_maps[i].phys,
-						   WINDOW_SIZE,
-						   L_PTE_CACHEABLE, 1);
+		lubbock_maps[i].cached = ioremap_cached(lubbock_maps[i].phys, WINDOW_SIZE);
 		if (!lubbock_maps[i].cached)
 			printk(KERN_WARNING "Failed to ioremap cached %s\n", lubbock_maps[i].name);
 		simple_map_init(&lubbock_maps[i]);
diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c
index e06b07351..38a81462f 100644
--- a/drivers/mtd/maps/nettel.c
+++ b/drivers/mtd/maps/nettel.c
@@ -180,7 +180,7 @@ int nettel_eraseconfig(void)
 	if (mtd) {
 		nettel_erase.mtd = mtd;
 		nettel_erase.callback = nettel_erasecallback;
-		nettel_erase.callback = 0;
+		nettel_erase.callback = NULL;
 		nettel_erase.addr = 0;
 		nettel_erase.len = mtd->size;
 		nettel_erase.priv = (u_long) &wait_q;
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index c42ca6f96..bb9c07780 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -885,7 +885,7 @@ struct sa_info {
 	unsigned long base;
 	unsigned long size;
 	int width;
-	void *vbase;
+	void __iomem *vbase;
         void (*set_vpp)(struct map_info *, int);
 	struct map_info *map;
 	struct mtd_info *mtd;
@@ -932,7 +932,7 @@ static int __init sa1100_setup_mtd(struct sa_info *sa, int nr, struct mtd_info *
 			break;
 		}
 
-		sa[i].map->virt = (unsigned long)sa[i].vbase;
+		sa[i].map->virt = sa[i].vbase;
 		sa[i].map->phys = sa[i].base;
 		sa[i].map->set_vpp = sa[i].set_vpp;
 		sa[i].map->bankwidth = sa[i].width;
diff --git a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c
index 496c9857f..5a10fbaaa 100644
--- a/drivers/mtd/maps/tqm8xxl.c
+++ b/drivers/mtd/maps/tqm8xxl.c
@@ -50,7 +50,7 @@ static struct mtd_info* mtd_banks[FLASH_BANK_MAX];
 static struct map_info* map_banks[FLASH_BANK_MAX];
 static struct mtd_part_def part_banks[FLASH_BANK_MAX];
 static unsigned long num_banks;
-static unsigned long start_scan_addr;
+static void __iomem *start_scan_addr;
 
 /*
  * Here are partition information for all known TQM8xxL series devices.
@@ -121,7 +121,7 @@ int __init init_tqm_mtd(void)
 	flash_size = bd->bi_flashsize;
 
 	//request maximum flash size address space
-	start_scan_addr = (unsigned long)ioremap(flash_addr, flash_size);
+	start_scan_addr = ioremap(flash_addr, flash_size);
 	if (!start_scan_addr) {
 		printk(KERN_WARNING "%s:Failed to ioremap address:0x%x\n", __FUNCTION__, flash_addr);
 		return -EIO;
@@ -231,7 +231,7 @@ error_mem:
 		}
 	}
 error:
-	iounmap((void *)start_scan_addr);
+	iounmap(start_scan_addr);
 	return ret;
 }
 
@@ -250,7 +250,7 @@ static void __exit cleanup_tqm_mtd(void)
 	}
 
 	if (start_scan_addr) {
-		iounmap((void *)start_scan_addr);
+		iounmap(start_scan_addr);
 		start_scan_addr = 0;
 	}
 }
diff --git a/drivers/mtd/maps/uclinux.c b/drivers/mtd/maps/uclinux.c
index c5cd70bdb..baff49bf7 100644
--- a/drivers/mtd/maps/uclinux.c
+++ b/drivers/mtd/maps/uclinux.c
@@ -69,10 +69,9 @@ int __init uclinux_mtd_init(void)
 	printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n",
 	       	(int) mapp->map_priv_2, (int) mapp->size);
 
-	mapp->virt = (unsigned long)
-		ioremap_nocache(mapp->phys, mapp->size);
+	mapp->virt = ioremap_nocache(mapp->phys, mapp->size);
 
-	if (mapp->virt == 0) {
+	if (!mapp->virt) {
 		printk("uclinux[mtd]: ioremap_nocache() failed\n");
 		return(-EIO);
 	}
@@ -82,7 +81,7 @@ int __init uclinux_mtd_init(void)
 	mtd = do_map_probe("map_ram", mapp);
 	if (!mtd) {
 		printk("uclinux[mtd]: failed to find a mapping?\n");
-		iounmap((void *) mapp->virt);
+		iounmap(mapp->virt);
 		return(-ENXIO);
 	}
 		
diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c
index a8a4e1ac8..eee7faa5c 100644
--- a/drivers/mtd/nftlmount.c
+++ b/drivers/mtd/nftlmount.c
@@ -269,7 +269,8 @@ static int memcmpb(void *a, int c, int n)
 static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len, 
 			      int check_oob)
 {
-	int i, retlen;
+	int i;
+	size_t retlen;
 	u8 buf[SECTORSIZE + nftl->mbd.mtd->oobsize];
 
 	for (i = 0; i < len; i += SECTORSIZE) {
@@ -366,7 +367,8 @@ static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_b
 {
 	unsigned int block, i, status;
 	struct nftl_bci bci;
-	int sectors_per_block, retlen;
+	int sectors_per_block;
+	size_t retlen;
 
 	sectors_per_block = nftl->EraseSize / SECTORSIZE;
 	block = first_block;
diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c
index ca0d71d63..4866a09c0 100644
--- a/drivers/net/3c507.c
+++ b/drivers/net/3c507.c
@@ -294,6 +294,7 @@ static void el16_tx_timeout (struct net_device *dev);
 static void hardware_send_packet(struct net_device *dev, void *buf, short length, short pad);
 static void init_82586_mem(struct net_device *dev);
 static struct ethtool_ops netdev_ethtool_ops;
+static void init_rx_bufs(struct net_device *);
 
 static int io = 0x300;
 static int irq;
@@ -612,7 +613,6 @@ static irqreturn_t el16_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 	}
 
 	if ((status & 0x0070) != 0x0040 && netif_running(dev)) {
-		static void init_rx_bufs(struct net_device *);
 		/* The Rx unit is not ready, it must be hung.  Restart the receiver by
 		   initializing the rx buffers, and issuing an Rx start command. */
 		if (net_debug)
diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c
index c6f1995e0..a39c446c3 100644
--- a/drivers/net/3c527.c
+++ b/drivers/net/3c527.c
@@ -751,18 +751,15 @@ static int mc32_load_rx_ring(struct net_device *dev)
 	
 	rx_base=lp->rx_chain;
 
-	for(i=0; i<RX_RING_LEN; i++)
-	{
+	for(i=0; i<RX_RING_LEN; i++) {
 		lp->rx_ring[i].skb=alloc_skb(1532, GFP_KERNEL);
-		skb_reserve(lp->rx_ring[i].skb, 18);  
-
-		if(lp->rx_ring[i].skb==NULL)
-		{
-			for(;i>=0;i--)
+		if (lp->rx_ring[i].skb==NULL) {
+			for (;i>=0;i--)
 				kfree_skb(lp->rx_ring[i].skb);
 			return -ENOBUFS;
 		}
-		
+		skb_reserve(lp->rx_ring[i].skb, 18);
+
 		p=isa_bus_to_virt(lp->base+rx_base);
 				
 		p->control=0;
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index ab2e61a9d..89faad1d2 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -695,7 +695,7 @@ enum Window2 {			/* Window 2. */
 	Wn2_ResetOptions=12,
 };
 enum Window3 {			/* Window 3: MAC/config bits. */
-	Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8,
+	Wn3_Config=0, Wn3_MaxPktSize=4, Wn3_MAC_Ctrl=6, Wn3_Options=8,
 };
 
 #define BFEXT(value, offset, bitcount)  \
@@ -723,7 +723,8 @@ enum Win4_Media_bits {
 	Media_LnkBeat = 0x0800,
 };
 enum Window7 {					/* Window 7: Bus Master control. */
-	Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12,
+	Wn7_MasterAddr = 0, Wn7_VlanEtherType=4, Wn7_MasterLen = 6,
+	Wn7_MasterStatus = 12,
 };
 /* Boomerang bus master control registers. */
 enum MasterCtrl {
@@ -819,7 +820,8 @@ struct vortex_private {
 		pm_state_valid:1,				/* power_state[] has sane contents */
 		open:1,
 		medialock:1,
-		must_free_region:1;				/* Flag: if zero, Cardbus owns the I/O region */
+		must_free_region:1,				/* Flag: if zero, Cardbus owns the I/O region */
+		large_frames:1;			/* accept large frames */
 	int drv_flags;
 	u16 status_enable;
 	u16 intr_enable;
@@ -900,10 +902,14 @@ static void dump_tx_ring(struct net_device *dev);
 static void update_stats(long ioaddr, struct net_device *dev);
 static struct net_device_stats *vortex_get_stats(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
+#ifdef CONFIG_PCI
 static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+#endif
 static void vortex_tx_timeout(struct net_device *dev);
 static void acpi_set_WOL(struct net_device *dev);
 static struct ethtool_ops vortex_ethtool_ops;
+static void set_8021q_mode(struct net_device *dev, int enable);
+
 
 /* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
 /* Option count limit only -- unlimited interfaces are supported. */
@@ -1164,6 +1170,7 @@ static int __devinit vortex_probe1(struct device *gendev,
 	dev->base_addr = ioaddr;
 	dev->irq = irq;
 	dev->mtu = mtu;
+	vp->large_frames = mtu > 1500;
 	vp->drv_flags = vci->drv_flags;
 	vp->has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0;
 	vp->io_size = vci->io_size;
@@ -1290,6 +1297,13 @@ static int __devinit vortex_probe1(struct device *gendev,
 		for (i = 0; i < 6; i++)
 			printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]);
 	}
+	/* Unfortunately an all zero eeprom passes the checksum and this
+	   gets found in the wild in failure cases. Crypto is hard 8) */
+	if (!is_valid_ether_addr(dev->dev_addr)) {
+		retval = -EINVAL;
+		printk(KERN_ERR "*** EEPROM MAC address is invalid.\n");
+		goto free_ring;	/* With every pack */
+	}
 	EL3WINDOW(2);
 	for (i = 0; i < 6; i++)
 		outb(dev->dev_addr[i], ioaddr + i);
@@ -1468,7 +1482,9 @@ static int __devinit vortex_probe1(struct device *gendev,
 
 	dev->stop = vortex_close;
 	dev->get_stats = vortex_get_stats;
+#ifdef CONFIG_PCI
 	dev->do_ioctl = vortex_ioctl;
+#endif
 	dev->ethtool_ops = &vortex_ethtool_ops;
 	dev->set_multicast_list = set_rx_mode;
 	dev->tx_timeout = vortex_tx_timeout;
@@ -1616,7 +1632,7 @@ vortex_up(struct net_device *dev)
 
 	/* Set the full-duplex bit. */
 	outw(	((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) |
-		 	(dev->mtu > 1500 ? 0x40 : 0) |
+		 	(vp->large_frames ? 0x40 : 0) |
 			((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0),
 			ioaddr + Wn3_MAC_Ctrl);
 
@@ -1700,6 +1716,8 @@ vortex_up(struct net_device *dev)
 	}
 	/* Set receiver mode: presumably accept b-case and phys addr only. */
 	set_rx_mode(dev);
+	/* enable 802.1q tagged frames */
+	set_8021q_mode(dev, 1);
 	outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
 
 //	issue_and_wait(dev, SetTxStart|0x07ff);
@@ -1842,7 +1860,7 @@ vortex_timer(unsigned long data)
 						/* Set the full-duplex bit. */
 						EL3WINDOW(3);
 						outw(	(vp->full_duplex ? 0x20 : 0) |
-								(dev->mtu > 1500 ? 0x40 : 0) |
+								(vp->large_frames ? 0x40 : 0) |
 								((vp->full_duplex && vp->flow_ctrl && vp->partner_flow_ctrl) ? 0x100 : 0),
 								ioaddr + Wn3_MAC_Ctrl);
 						if (vortex_debug > 1)
@@ -2068,6 +2086,8 @@ vortex_error(struct net_device *dev, int status)
 			issue_and_wait(dev, RxReset|0x07);
 			/* Set the Rx filter to the current state. */
 			set_rx_mode(dev);
+			/* enable 802.1q VLAN tagged frames */
+			set_8021q_mode(dev, 1);
 			outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
 			outw(AckIntr | HostError, ioaddr + EL3_CMD);
 		}
@@ -2672,6 +2692,9 @@ vortex_down(struct net_device *dev, int final_down)
 	outw(RxDisable, ioaddr + EL3_CMD);
 	outw(TxDisable, ioaddr + EL3_CMD);
 
+	/* Disable receiving 802.1q tagged frames */
+	set_8021q_mode(dev, 0);
+
 	if (dev->if_port == XCVR_10base2)
 		/* Turn off thinnet power.  Green! */
 		outw(StopCoax, ioaddr + EL3_CMD);
@@ -2868,6 +2891,7 @@ static struct ethtool_ops vortex_ethtool_ops = {
 	.get_drvinfo =		vortex_get_drvinfo,
 };
 
+#ifdef CONFIG_PCI
 static int vortex_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct vortex_private *vp = netdev_priv(dev);
@@ -2925,6 +2949,7 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
 	return err;
 }
+#endif
 
 
 /* Pre-Cyclone chips have no documented multicast filter, so the only
@@ -2947,6 +2972,61 @@ static void set_rx_mode(struct net_device *dev)
 	outw(new_mode, ioaddr + EL3_CMD);
 }
 
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+/* Setup the card so that it can receive frames with an 802.1q VLAN tag.
+   Note that this must be done after each RxReset due to some backwards
+   compatibility logic in the Cyclone and Tornado ASICs */
+
+/* The Ethernet Type used for 802.1q tagged frames */
+#define VLAN_ETHER_TYPE 0x8100
+
+static void set_8021q_mode(struct net_device *dev, int enable)
+{
+	struct vortex_private *vp = (struct vortex_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	int old_window = inw(ioaddr + EL3_CMD);
+	int mac_ctrl;
+
+	if ((vp->drv_flags&IS_CYCLONE) || (vp->drv_flags&IS_TORNADO)) {
+		/* cyclone and tornado chipsets can recognize 802.1q
+		 * tagged frames and treat them correctly */
+
+		int max_pkt_size = dev->mtu+14;	/* MTU+Ethernet header */
+		if (enable)
+			max_pkt_size += 4;	/* 802.1Q VLAN tag */
+
+		EL3WINDOW(3);
+		outw(max_pkt_size, ioaddr+Wn3_MaxPktSize);
+
+		/* set VlanEtherType to let the hardware checksumming
+		   treat tagged frames correctly */
+		EL3WINDOW(7);
+		outw(VLAN_ETHER_TYPE, ioaddr+Wn7_VlanEtherType);
+	} else {
+		/* on older cards we have to enable large frames */
+
+		vp->large_frames = dev->mtu > 1500 || enable;
+
+		EL3WINDOW(3);
+		mac_ctrl = inw(ioaddr+Wn3_MAC_Ctrl);
+		if (vp->large_frames)
+			mac_ctrl |= 0x40;
+		else
+			mac_ctrl &= ~0x40;
+		outw(mac_ctrl, ioaddr+Wn3_MAC_Ctrl);
+	}
+
+	EL3WINDOW(old_window);
+}
+#else
+
+static void set_8021q_mode(struct net_device *dev, int enable)
+{
+}
+
+
+#endif
+
 /* MII transceiver control section.
    Read and write the MII registers using software-generated serial
    MDIO protocol.  See the MII specifications or DP83840A data sheet
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 62dd13951..1b18b3aca 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -1698,7 +1698,7 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 	}
 
 	/* Configure DMA attributes. */
-	if ((sizeof(dma_addr_t) > 32) &&
+	if ((sizeof(dma_addr_t) > 4) &&
 	    !pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL) &&
 	    !pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) {
 		pci_using_dac = 1;
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 58290c5bb..2a94719a4 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -593,6 +593,7 @@ struct rtl8139_private {
 	int time_to_die;
 	struct mii_if_info mii;
 	unsigned int regs_len;
+	unsigned long fifo_copy_timeout;
 };
 
 MODULE_AUTHOR ("Jeff Garzik <jgarzik@pobox.com>");
@@ -613,7 +614,7 @@ static int rtl8139_open (struct net_device *dev);
 static int mdio_read (struct net_device *dev, int phy_id, int location);
 static void mdio_write (struct net_device *dev, int phy_id, int location,
 			int val);
-static inline void rtl8139_start_thread(struct net_device *dev);
+static void rtl8139_start_thread(struct net_device *dev);
 static void rtl8139_tx_timeout (struct net_device *dev);
 static void rtl8139_init_ring (struct net_device *dev);
 static int rtl8139_start_xmit (struct sk_buff *skb,
@@ -1643,7 +1644,7 @@ static int rtl8139_thread (void *data)
 	complete_and_exit (&tp->thr_exited, 0);
 }
 
-static inline void rtl8139_start_thread(struct net_device *dev)
+static void rtl8139_start_thread(struct net_device *dev)
 {
 	struct rtl8139_private *tp = dev->priv;
 
@@ -1927,6 +1928,24 @@ static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring,
 }
 #endif
 
+static void rtl8139_isr_ack(struct rtl8139_private *tp)
+{
+	void *ioaddr = tp->mmio_addr;
+	u16 status;
+
+	status = RTL_R16 (IntrStatus) & RxAckBits;
+
+	/* Clear out errors and receive interrupts */
+	if (likely(status != 0)) {
+		if (unlikely(status & (RxFIFOOver | RxOverflow))) {
+			tp->stats.rx_errors++;
+			if (status & RxFIFOOver)
+				tp->stats.rx_fifo_errors++;
+		}
+		RTL_W16_F (IntrStatus, RxAckBits);
+	}
+}
+
 static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
 		      int budget)
 {
@@ -1934,9 +1953,10 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
 	int received = 0;
 	unsigned char *rx_ring = tp->rx_ring;
 	unsigned int cur_rx = tp->cur_rx;
+	unsigned int rx_size = 0;
 
 	DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x,"
-		 " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx,
+		 " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx,
 		 RTL_R16 (RxBufAddr),
 		 RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));
 
@@ -1944,10 +1964,8 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
 	       && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {
 		u32 ring_offset = cur_rx % RX_BUF_LEN;
 		u32 rx_status;
-		unsigned int rx_size;
 		unsigned int pkt_size;
 		struct sk_buff *skb;
-		u16 status;
 
 		rmb();
 
@@ -1976,10 +1994,24 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
 		 * since EarlyRx is disabled.
 		 */
 		if (unlikely(rx_size == 0xfff0)) {
+			if (!tp->fifo_copy_timeout)
+				tp->fifo_copy_timeout = jiffies + 2;
+			else if (time_after(jiffies, tp->fifo_copy_timeout)) {
+				DPRINTK ("%s: hung FIFO. Reset.", dev->name);
+				rx_size = 0;
+				goto no_early_rx;
+			}
+			if (netif_msg_intr(tp)) {
+				printk(KERN_DEBUG "%s: fifo copy in progress.",
+				       dev->name);
+			}
 			tp->xstats.early_rx++;
-			goto done;
+			break;
 		}
 
+no_early_rx:
+		tp->fifo_copy_timeout = 0;
+
 		/* If Rx err or invalid rx_size/rx_status received
 		 * (which happens if we get lost in the ring),
 		 * Rx process gets reset, so we abort any further
@@ -1989,7 +2021,8 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
 			     (rx_size < 8) ||
 			     (!(rx_status & RxStatusOK)))) {
 			rtl8139_rx_err (rx_status, dev, tp, ioaddr);
-			return -1;
+			received = -1;
+			goto out;
 		}
 
 		/* Malloc up new buffer, compatible with net-2e. */
@@ -2025,19 +2058,11 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
 		cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;
 		RTL_W16 (RxBufPtr, (u16) (cur_rx - 16));
 
-		/* Clear out errors and receive interrupts */
-		status = RTL_R16 (IntrStatus) & RxAckBits;
-		if (likely(status != 0)) {
-			if (unlikely(status & (RxFIFOOver | RxOverflow))) {
-				tp->stats.rx_errors++;
-				if (status & RxFIFOOver)
-					tp->stats.rx_fifo_errors++;
-			}
-			RTL_W16_F (IntrStatus, RxAckBits);
-		}
+		rtl8139_isr_ack(tp);
 	}
 
- done:
+	if (unlikely(!received || rx_size == 0xfff0))
+		rtl8139_isr_ack(tp);
 
 #if RTL8139_DEBUG > 1
 	DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x,"
@@ -2047,6 +2072,15 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
 #endif
 
 	tp->cur_rx = cur_rx;
+
+	/*
+	 * The receive buffer should be mostly empty.
+	 * Tell NAPI to reenable the Rx irq.
+	 */
+	if (tp->fifo_copy_timeout)
+		received = budget;
+
+out:
 	return received;
 }
 
diff --git a/drivers/net/8390.c b/drivers/net/8390.c
index 22e7dfb47..04dcacda8 100644
--- a/drivers/net/8390.c
+++ b/drivers/net/8390.c
@@ -41,6 +41,8 @@
 			  module by all drivers that require it.
   Alan Cox		: Spinlocking work, added 'BUG_83C690'
   Paul Gortmaker	: Separate out Tx timeout code from Tx path.
+  Paul Gortmaker	: Remove old unused single Tx buffer code.
+  Hayato Fujiwara	: Add m32r support.
 
   Sources:
   The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
@@ -218,6 +220,15 @@ void ei_tx_timeout(struct net_device *dev)
 	int txsr, isr, tickssofar = jiffies - dev->trans_start;
 	unsigned long flags;
 
+#if defined(CONFIG_M32R) && defined(CONFIG_SMP)
+	unsigned long icucr;
+
+	local_irq_save(flags);
+	icucr = inl(ICUCR1);
+	icucr |= M32R_ICUCR_ISMOD11;
+	outl(icucr, ICUCR1);
+	local_irq_restore(flags);
+#endif
 	ei_local->stat.tx_errors++;
 
 	spin_lock_irqsave(&ei_local->page_lock, flags);
@@ -289,8 +300,6 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	send_length = ETH_ZLEN < length ? length : ETH_ZLEN;
     
-#ifdef EI_PINGPONG
-
 	/*
 	 * We have two Tx slots available for use. Find the first free
 	 * slot, and then perform some sanity checks. With two Tx bufs,
@@ -309,7 +318,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	}
 	else if (ei_local->tx2 == 0) 
 	{
-		output_page = ei_local->tx_start_page + TX_1X_PAGES;
+		output_page = ei_local->tx_start_page + TX_PAGES/2;
 		ei_local->tx2 = send_length;
 		if (ei_debug  &&  ei_local->tx1 > 0)
 			printk(KERN_DEBUG "%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n",
@@ -366,28 +375,6 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	else
 		netif_start_queue(dev);
 
-#else	/* EI_PINGPONG */
-
-	/*
-	 * Only one Tx buffer in use. You need two Tx bufs to come close to
-	 * back-to-back transmits. Expect a 20 -> 25% performance hit on
-	 * reasonable hardware if you only use one Tx buffer.
-	 */
-
-	if (length == send_length)
-		ei_block_output(dev, length, skb->data, ei_local->tx_start_page);
-	else {
-		memset(scratch, 0, ETH_ZLEN);
-		memcpy(scratch, skb->data, skb->len);
-		ei_block_output(dev, ETH_ZLEN, scratch, ei_local->tx_start_page);
-	}
-	ei_local->txing = 1;
-	NS8390_trigger_send(dev, send_length, ei_local->tx_start_page);
-	dev->trans_start = jiffies;
-	netif_stop_queue(dev);
-
-#endif	/* EI_PINGPONG */
-
 	/* Turn 8390 interrupts back on. */
 	ei_local->irqlock = 0;
 	outb_p(ENISR_ALL, e8390_base + EN0_IMR);
@@ -590,8 +577,6 @@ static void ei_tx_intr(struct net_device *dev)
     
 	outb_p(ENISR_TX, e8390_base + EN0_ISR); /* Ack intr. */
 
-#ifdef EI_PINGPONG
-
 	/*
 	 * There are two Tx buffers, see which one finished, and trigger
 	 * the send of another one if it exists.
@@ -634,13 +619,6 @@ static void ei_tx_intr(struct net_device *dev)
 //	else printk(KERN_WARNING "%s: unexpected TX-done interrupt, lasttx=%d.\n",
 //			dev->name, ei_local->lasttx);
 
-#else	/* EI_PINGPONG */
-	/*
-	 *  Single Tx buffer: mark it free so another packet can be loaded.
-	 */
-	ei_local->txing = 0;
-#endif
-
 	/* Minimize Tx latency: update the statistics after we restart TXing. */
 	if (status & ENTSR_COL)
 		ei_local->stat.collisions++;
diff --git a/drivers/net/8390.h b/drivers/net/8390.h
index 58fd65e03..948723b72 100644
--- a/drivers/net/8390.h
+++ b/drivers/net/8390.h
@@ -12,17 +12,7 @@
 #include <linux/ioport.h>
 #include <linux/skbuff.h>
 
-#define TX_2X_PAGES 12
-#define TX_1X_PAGES 6
-
-/* Should always use two Tx slots to get back-to-back transmits. */
-#define EI_PINGPONG
-
-#ifdef EI_PINGPONG
-#define TX_PAGES TX_2X_PAGES
-#else
-#define TX_PAGES TX_1X_PAGES
-#endif
+#define TX_PAGES 12	/* Two Tx slots */
 
 #define ETHER_ADDR_LEN 6
 
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 882837793..967640710 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -200,7 +200,7 @@ source "drivers/net/arm/Kconfig"
 
 config MACE
 	tristate "MACE (Power Mac ethernet) support"
-	depends on NET_ETHERNET && PPC_PMAC
+	depends on NET_ETHERNET && PPC_PMAC && PPC32
 	select CRC32
 	help
 	  Power Macintoshes and clones with Ethernet built-in on the
@@ -223,7 +223,7 @@ config MACE_AAUI_PORT
 
 config BMAC
 	tristate "BMAC (G3 ethernet) support"
-	depends on NET_ETHERNET && PPC_PMAC
+	depends on NET_ETHERNET && PPC_PMAC && PPC32
 	select CRC32
 	help
 	  Say Y for support of BMAC Ethernet interfaces. These are used on G3
@@ -817,7 +817,7 @@ config SMC91X
 	tristate "SMC 91C9x/91C1xxx support"
 	select CRC32
 	select MII
-	depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6)
+	depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6 || M32R)
 	help
 	  This is a driver for SMC's 91x series of Ethernet chipsets,
 	  including the SMC91C94 and the SMC91C111. Say Y if you want it
@@ -1075,7 +1075,7 @@ config ETH16I
 
 config NE2000
 	tristate "NE2000/NE1000 support"
-	depends on NET_ISA || (Q40 && m)
+	depends on NET_ISA || (Q40 && m) || M32R
 	select CRC32
 	---help---
 	  If you have a network (Ethernet) card of this type, say Y and read
@@ -1353,7 +1353,7 @@ config FORCEDETH
 
 config CS89x0
 	tristate "CS89x0 support"
-	depends on NET_PCI && ISA
+	depends on NET_PCI && (ISA || ARCH_IXDP2X01)
 	---help---
 	  Support for CS89x0 chipset based Ethernet cards. If you have a
 	  network (Ethernet) card of this type, say Y and read the
@@ -1746,12 +1746,13 @@ config VIA_VELOCITY
 	tristate "VIA Velocity support"
 	depends on NET_PCI && PCI
 	select CRC32
+	select CRC_CCITT
 	select MII
 	help
 	  If you have a VIA "Velocity" based network card say Y here.
 
 	  To compile this driver as a module, choose M here. The module
-	  will be called via-rhine.
+	  will be called via-velocity.
 
 config LAN_SAA9730
 	bool "Philips SAA9730 Ethernet support (EXPERIMENTAL)"
@@ -2043,6 +2044,23 @@ config R8169
 	  To compile this driver as a module, choose M here: the module
 	  will be called r8169.  This is recommended.
 
+config R8169_NAPI
+	bool "Use Rx and Tx Polling (NAPI) (EXPERIMENTAL)"
+	depends on R8169 && EXPERIMENTAL
+	help
+	  NAPI is a new driver API designed to reduce CPU and interrupt load
+	  when the driver is receiving lots of packets from the card. It is
+	  still somewhat experimental and thus not yet enabled by default.
+
+	  If your estimated Rx load is 10kpps or more, or if the card will be
+	  deployed on potentially unfriendly networks (e.g. in a firewall),
+	  then say Y here.
+
+	  See <file:Documentation/networking/NAPI_HOWTO.txt> for more
+	  information.
+
+	  If in doubt, say N.
+
 config SK98LIN
 	tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support"
 	depends on PCI
@@ -2131,6 +2149,45 @@ config TIGON3
 	  To compile this driver as a module, choose M here: the module
 	  will be called tg3.  This is recommended.
 
+config GIANFAR
+	tristate "Gianfar Ethernet"
+	depends on 85xx
+	help
+	  This driver supports the Gigabit TSEC on the MPC85xx 
+	  family of chips, and the FEC on the 8540
+
+config GFAR_NAPI
+	bool "NAPI Support"
+	depends on GIANFAR
+
+config MV643XX_ETH
+	tristate "MV-643XX Ethernet support"
+	depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX
+	help
+	  This driver supports the gigabit Ethernet on the Marvell MV643XX
+	  chipset which is used in the Momenco Ocelot C and Jaguar ATX.
+
+config MV643XX_ETH_0
+	bool "MV-643XX Port 0"
+	depends on MV643XX_ETH
+	help
+	  This enables support for Port 0 of the Marvell MV643XX Gigabit
+	  Ethernet.
+
+config MV643XX_ETH_1
+	bool "MV-643XX Port 1"
+	depends on MV643XX_ETH
+	help
+	  This enables support for Port 1 of the Marvell MV643XX Gigabit
+	  Ethernet.
+
+config MV643XX_ETH_2
+	bool "MV-643XX Port 2"
+	depends on MV643XX_ETH
+	help
+	  This enables support for Port 2 of the Marvell MV643XX Gigabit
+	  Ethernet.
+
 endmenu
 
 #
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 2ae71cf8b..3fc85500f 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -10,6 +10,9 @@ obj-$(CONFIG_E1000) += e1000/
 obj-$(CONFIG_IBM_EMAC) += ibm_emac/
 obj-$(CONFIG_IXGB) += ixgb/
 obj-$(CONFIG_BONDING) += bonding/
+obj-$(CONFIG_GIANFAR) += gianfar_driver.o
+
+gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_phy.o
 
 #
 # link order important here
@@ -95,6 +98,8 @@ obj-$(CONFIG_B44) += b44.o
 obj-$(CONFIG_FORCEDETH) += forcedeth.o
 obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
 
+obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
+
 obj-$(CONFIG_PPP) += ppp_generic.o slhc.o
 obj-$(CONFIG_PPP_ASYNC) += ppp_async.o
 obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index 90ed3329a..cc56ca3ac 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -52,6 +52,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/version.h>
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -425,13 +426,15 @@ static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1};
 MODULE_AUTHOR("Jes Sorensen <jes@trained-monkey.org>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver");
-MODULE_PARM(link, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(trace, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(tx_coal_tick, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(max_tx_desc, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(rx_coal_tick, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(max_rx_desc, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(tx_ratio, "1-" __MODULE_STRING(8) "i");
+
+static int num_params;
+module_param_array(link, int, num_params, 0);
+module_param_array(trace, int, num_params, 0);
+module_param_array(tx_coal_tick, int, num_params, 0);
+module_param_array(max_tx_desc, int, num_params, 0);
+module_param_array(rx_coal_tick, int, num_params, 0);
+module_param_array(max_rx_desc, int, num_params, 0);
+module_param_array(tx_ratio, int, num_params, 0);
 MODULE_PARM_DESC(link, "AceNIC/3C985/NetGear link state");
 MODULE_PARM_DESC(trace, "AceNIC/3C985/NetGear firmware trace level");
 MODULE_PARM_DESC(tx_coal_tick, "AceNIC/3C985/GA620 max clock ticks to wait from first tx descriptor arrives");
@@ -474,6 +477,7 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev,
 
 	ap = dev->priv;
 	ap->pdev = pdev;
+	ap->name = pci_name(pdev);
 
 	dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
 #if ACENIC_DO_VLAN
@@ -516,7 +520,7 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev,
 	if (!(ap->pci_command & PCI_COMMAND_MEMORY)) {
 		printk(KERN_INFO "%s: Enabling PCI Memory Mapped "
 		       "access - was not enabled by BIOS/Firmware\n",
-		       dev->name);
+		       ap->name);
 		ap->pci_command = ap->pci_command | PCI_COMMAND_MEMORY;
 		pci_write_config_word(ap->pdev, PCI_COMMAND,
 				      ap->pci_command);
@@ -539,55 +543,40 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev,
 	if (!ap->regs) {
 		printk(KERN_ERR "%s:  Unable to map I/O register, "
 		       "AceNIC %i will be disabled.\n",
-		       dev->name, boards_found);
+		       ap->name, boards_found);
 		goto fail_free_netdev;
 	}
 
 	switch(pdev->vendor) {
 	case PCI_VENDOR_ID_ALTEON:
 		if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9100T) {
-			strncpy(ap->name, "Farallon PN9100-T "
-				"Gigabit Ethernet", sizeof (ap->name));
 			printk(KERN_INFO "%s: Farallon PN9100-T ",
-			       dev->name);
+			       ap->name);
 		} else {
-			strncpy(ap->name, "AceNIC Gigabit Ethernet",
-				sizeof (ap->name));
 			printk(KERN_INFO "%s: Alteon AceNIC ",
-			       dev->name);
+			       ap->name);
 		}
 		break;
 	case PCI_VENDOR_ID_3COM:
-		strncpy(ap->name, "3Com 3C985 Gigabit Ethernet",
-			sizeof (ap->name));
-		printk(KERN_INFO "%s: 3Com 3C985 ", dev->name);
+		printk(KERN_INFO "%s: 3Com 3C985 ", ap->name);
 		break;
 	case PCI_VENDOR_ID_NETGEAR:
-		strncpy(ap->name, "NetGear GA620 Gigabit Ethernet",
-			sizeof (ap->name));
-		printk(KERN_INFO "%s: NetGear GA620 ", dev->name);
+		printk(KERN_INFO "%s: NetGear GA620 ", ap->name);
 		break;
 	case PCI_VENDOR_ID_DEC:
 		if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9000SX) {
-			strncpy(ap->name, "Farallon PN9000-SX "
-				"Gigabit Ethernet", sizeof (ap->name));
 			printk(KERN_INFO "%s: Farallon PN9000-SX ",
-			       dev->name);
+			       ap->name);
 			break;
 		}
 	case PCI_VENDOR_ID_SGI:
-		strncpy(ap->name, "SGI AceNIC Gigabit Ethernet",
-			sizeof (ap->name));
-		printk(KERN_INFO "%s: SGI AceNIC ", dev->name);
+		printk(KERN_INFO "%s: SGI AceNIC ", ap->name);
 		break;
 	default:
- 		strncpy(ap->name, "Unknown AceNIC based Gigabit "
-			"Ethernet", sizeof (ap->name));
-		printk(KERN_INFO "%s: Unknown AceNIC ", dev->name);
+		printk(KERN_INFO "%s: Unknown AceNIC ", ap->name);
 		break;
 	}
 
-	ap->name [sizeof (ap->name) - 1] = '\0';
 	printk("Gigabit Ethernet at 0x%08lx, ", dev->base_addr);
 #ifdef __sparc__
 	printk("irq %s\n", __irq_itoa(pdev->irq));
@@ -622,6 +611,7 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev,
 		printk(KERN_ERR "acenic: device registration failed\n");
 		goto fail_uninit;
 	}
+	ap->name = dev->name;
 
 	if (ap->pci_using_dac)
 		dev->features |= NETIF_F_HIGHDMA;
@@ -641,7 +631,7 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev,
 static void __devexit acenic_remove_one(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	struct ace_regs *regs = ap->regs;
 	short i;
 
@@ -752,7 +742,7 @@ module_exit(acenic_exit);
 
 static void ace_free_descriptors(struct net_device *dev)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	int size;
 
 	if (ap->rx_std_ring != NULL) {
@@ -802,7 +792,7 @@ static void ace_free_descriptors(struct net_device *dev)
 
 static int ace_allocate_descriptors(struct net_device *dev)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	int size;
 
 	size = (sizeof(struct rx_desc) *
@@ -873,7 +863,7 @@ static void ace_init_cleanup(struct net_device *dev)
 {
 	struct ace_private *ap;
 
-	ap = dev->priv;
+	ap = netdev_priv(dev);
 
 	ace_free_descriptors(dev);
 
@@ -921,7 +911,7 @@ static int __init ace_init(struct net_device *dev)
 	short i;
 	unsigned char cache_size;
 
-	ap = dev->priv;
+	ap = netdev_priv(dev);
 	regs = ap->regs;
 
 	board_idx = ap->board_idx;
@@ -1387,7 +1377,7 @@ static int __init ace_init(struct net_device *dev)
 	if (board_idx == BOARD_IDX_OVERFLOW) {
 		printk(KERN_WARNING "%s: more than %i NICs detected, "
 		       "ignoring module parameters!\n",
-		       dev->name, ACE_MAX_MOD_PARMS);
+		       ap->name, ACE_MAX_MOD_PARMS);
 	} else if (board_idx >= 0) {
 		if (tx_coal_tick[board_idx])
 			writel(tx_coal_tick[board_idx],
@@ -1426,7 +1416,7 @@ static int __init ace_init(struct net_device *dev)
 
 		if (option & 0x01) {
 			printk(KERN_INFO "%s: Setting half duplex link\n",
-			       dev->name);
+			       ap->name);
 			tmp &= ~LNK_FULL_DUPLEX;
 		}
 		if (option & 0x02)
@@ -1439,7 +1429,7 @@ static int __init ace_init(struct net_device *dev)
 			tmp |= LNK_1000MB;
 		if ((option & 0x70) == 0) {
 			printk(KERN_WARNING "%s: No media speed specified, "
-			       "forcing auto negotiation\n", dev->name);
+			       "forcing auto negotiation\n", ap->name);
 			tmp |= LNK_NEGOTIATE | LNK_1000MB |
 				LNK_100MB | LNK_10MB;
 		}
@@ -1447,12 +1437,12 @@ static int __init ace_init(struct net_device *dev)
 			tmp |= LNK_NEG_FCTL;
 		else
 			printk(KERN_INFO "%s: Disabling flow control "
-			       "negotiation\n", dev->name);
+			       "negotiation\n", ap->name);
 		if (option & 0x200)
 			tmp |= LNK_RX_FLOW_CTL_Y;
 		if ((option & 0x400) && (ap->version >= 2)) {
 			printk(KERN_INFO "%s: Enabling TX flow control\n",
-			       dev->name);
+			       ap->name);
 			tmp |= LNK_TX_FLOW_CTL_Y;
 		}
 	}
@@ -1509,7 +1499,7 @@ static int __init ace_init(struct net_device *dev)
 		cpu_relax();
 
 	if (!ap->fw_running) {
-		printk(KERN_ERR "%s: Firmware NOT running!\n", dev->name);
+		printk(KERN_ERR "%s: Firmware NOT running!\n", ap->name);
 
 		ace_dump_trace(ap);
 		writel(readl(&regs->CpuCtrl) | CPU_HALT, &regs->CpuCtrl);
@@ -1542,13 +1532,13 @@ static int __init ace_init(struct net_device *dev)
 		ace_load_std_rx_ring(ap, RX_RING_SIZE);
 	else
 		printk(KERN_ERR "%s: Someone is busy refilling the RX ring\n",
-		       dev->name);
+		       ap->name);
 	if (ap->version >= 2) {
 		if (!test_and_set_bit(0, &ap->mini_refill_busy))
 			ace_load_mini_rx_ring(ap, RX_MINI_SIZE);
 		else
 			printk(KERN_ERR "%s: Someone is busy refilling "
-			       "the RX mini ring\n", dev->name);
+			       "the RX mini ring\n", ap->name);
 	}
 	return 0;
 
@@ -1564,7 +1554,7 @@ static void ace_set_rxtx_parms(struct net_device *dev, int jumbo)
 	struct ace_regs *regs;
 	int board_idx;
 
-	ap = dev->priv;
+	ap = netdev_priv(dev);
 	regs = ap->regs;
 
 	board_idx = ap->board_idx;
@@ -1604,7 +1594,7 @@ static void ace_set_rxtx_parms(struct net_device *dev, int jumbo)
 static void ace_watchdog(struct net_device *data)
 {
 	struct net_device *dev = data;
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	struct ace_regs *regs = ap->regs;
 
 	/*
@@ -1878,13 +1868,13 @@ static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd)
 {
 	struct ace_private *ap;
 
-	ap = dev->priv;
+	ap = netdev_priv(dev);
 
 	while (evtcsm != evtprd) {
 		switch (ap->evt_ring[evtcsm].evt) {
 		case E_FW_RUNNING:
 			printk(KERN_INFO "%s: Firmware up and running\n",
-			       dev->name);
+			       ap->name);
 			ap->fw_running = 1;
 			wmb();
 			break;
@@ -1899,7 +1889,7 @@ static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd)
 				u32 state = readl(&ap->regs->GigLnkState);
 				printk(KERN_WARNING "%s: Optical link UP "
 				       "(%s Duplex, Flow Control: %s%s)\n",
-				       dev->name,
+				       ap->name,
 				       state & LNK_FULL_DUPLEX ? "Full":"Half",
 				       state & LNK_TX_FLOW_CTL_Y ? "TX " : "",
 				       state & LNK_RX_FLOW_CTL_Y ? "RX" : "");
@@ -1907,15 +1897,15 @@ static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd)
 			}
 			case E_C_LINK_DOWN:
 				printk(KERN_WARNING "%s: Optical link DOWN\n",
-				       dev->name);
+				       ap->name);
 				break;
 			case E_C_LINK_10_100:
 				printk(KERN_WARNING "%s: 10/100BaseT link "
-				       "UP\n", dev->name);
+				       "UP\n", ap->name);
 				break;
 			default:
 				printk(KERN_ERR "%s: Unknown optical link "
-				       "state %02x\n", dev->name, code);
+				       "state %02x\n", ap->name, code);
 			}
 			break;
 		}
@@ -1923,19 +1913,19 @@ static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd)
 			switch(ap->evt_ring[evtcsm].code) {
 			case E_C_ERR_INVAL_CMD:
 				printk(KERN_ERR "%s: invalid command error\n",
-				       dev->name);
+				       ap->name);
 				break;
 			case E_C_ERR_UNIMP_CMD:
 				printk(KERN_ERR "%s: unimplemented command "
-				       "error\n", dev->name);
+				       "error\n", ap->name);
 				break;
 			case E_C_ERR_BAD_CFG:
 				printk(KERN_ERR "%s: bad config error\n",
-				       dev->name);
+				       ap->name);
 				break;
 			default:
 				printk(KERN_ERR "%s: unknown error %02x\n",
-				       dev->name, ap->evt_ring[evtcsm].code);
+				       ap->name, ap->evt_ring[evtcsm].code);
 			}
 			break;
 		case E_RESET_JUMBO_RNG:
@@ -1964,13 +1954,13 @@ static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd)
 			ap->jumbo = 0;
 			ap->rx_jumbo_skbprd = 0;
 			printk(KERN_INFO "%s: Jumbo ring flushed\n",
-			       dev->name);
+			       ap->name);
 			clear_bit(0, &ap->jumbo_refill_busy);
 			break;
 		}
 		default:
 			printk(KERN_ERR "%s: Unhandled event 0x%02x\n",
-			       dev->name, ap->evt_ring[evtcsm].evt);
+			       ap->name, ap->evt_ring[evtcsm].evt);
 		}
 		evtcsm = (evtcsm + 1) % EVT_RING_ENTRIES;
 	}
@@ -1981,7 +1971,7 @@ static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd)
 
 static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	u32 idx;
 	int mini_count = 0, std_count = 0;
 
@@ -2108,7 +2098,7 @@ static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm)
 static inline void ace_tx_int(struct net_device *dev,
 			      u32 txcsm, u32 idx)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 
 	do {
 		struct sk_buff *skb;
@@ -2181,7 +2171,7 @@ static irqreturn_t ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
 	u32 txcsm, rxretcsm, rxretprd;
 	u32 evtcsm, evtprd;
 
-	ap = dev->priv;
+	ap = netdev_priv(dev);
 	regs = ap->regs;
 
 	/*
@@ -2304,7 +2294,7 @@ static irqreturn_t ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
 #if ACENIC_DO_VLAN
 static void ace_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	unsigned long flags;
 
 	local_irq_save(flags);
@@ -2319,7 +2309,7 @@ static void ace_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
 
 static void ace_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	unsigned long flags;
 
 	local_irq_save(flags);
@@ -2340,7 +2330,7 @@ static int ace_open(struct net_device *dev)
 	struct ace_regs *regs;
 	struct cmd cmd;
 
-	ap = dev->priv;
+	ap = netdev_priv(dev);
 	regs = ap->regs;
 
 	if (!(ap->fw_running)) {
@@ -2407,7 +2397,7 @@ static int ace_close(struct net_device *dev)
 	 */
 	netif_stop_queue(dev);
 
-	ap = dev->priv;
+	ap = netdev_priv(dev);
 	regs = ap->regs;
 
 	if (ap->promisc) {
@@ -2522,7 +2512,7 @@ ace_load_tx_bd(struct ace_private *ap, struct tx_desc *desc, u64 addr,
 
 static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	struct ace_regs *regs = ap->regs;
 	struct tx_desc *desc;
 	u32 idx, flagsize;
@@ -2661,7 +2651,7 @@ overflow:
 
 static int ace_change_mtu(struct net_device *dev, int new_mtu)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	struct ace_regs *regs = ap->regs;
 
 	if (new_mtu > ACE_JUMBO_MTU)
@@ -2698,7 +2688,7 @@ static int ace_change_mtu(struct net_device *dev, int new_mtu)
 
 static int ace_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	struct ace_regs *regs = ap->regs;
 	u32 link;
 
@@ -2751,7 +2741,7 @@ static int ace_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 
 static int ace_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	struct ace_regs *regs = ap->regs;
 	u32 link, speed;
 
@@ -2814,7 +2804,7 @@ static int ace_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 static void ace_get_drvinfo(struct net_device *dev, 
 			    struct ethtool_drvinfo *info)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 
 	strlcpy(info->driver, "acenic", sizeof(info->driver));
 	snprintf(info->version, sizeof(info->version), "%i.%i.%i", 
@@ -2844,7 +2834,7 @@ static int ace_set_mac_addr(struct net_device *dev, void *p)
 
 	da = (u8 *)dev->dev_addr;
 
-	regs = ((struct ace_private *)dev->priv)->regs;
+	regs = ((struct ace_private *)netdev_priv(dev))->regs;
 	writel(da[0] << 8 | da[1], &regs->MacAddrHi);
 	writel((da[2] << 24) | (da[3] << 16) | (da[4] << 8) | da[5],
 	       &regs->MacAddrLo);
@@ -2860,7 +2850,7 @@ static int ace_set_mac_addr(struct net_device *dev, void *p)
 
 static void ace_set_multicast_list(struct net_device *dev)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	struct ace_regs *regs = ap->regs;
 	struct cmd cmd;
 
@@ -2914,7 +2904,7 @@ static void ace_set_multicast_list(struct net_device *dev)
 
 static struct net_device_stats *ace_get_stats(struct net_device *dev)
 {
-	struct ace_private *ap = dev->priv;
+	struct ace_private *ap = netdev_priv(dev);
 	struct ace_mac_stats *mac_stats =
 		(struct ace_mac_stats *)ap->regs->Stats;
 
@@ -2997,12 +2987,12 @@ int __init ace_load_firmware(struct net_device *dev)
 	struct ace_private *ap;
 	struct ace_regs *regs;
 
-	ap = dev->priv;
+	ap = netdev_priv(dev);
 	regs = ap->regs;
 
 	if (!(readl(&regs->CpuCtrl) & CPU_HALTED)) {
 		printk(KERN_ERR "%s: trying to download firmware while the "
-		       "CPU is running!\n", dev->name);
+		       "CPU is running!\n", ap->name);
 		return -EFAULT;
 	}
 
@@ -3178,6 +3168,7 @@ static void __init eeprom_stop(struct ace_regs *regs)
 static int __init read_eeprom_byte(struct net_device *dev,
 				   unsigned long offset)
 {
+	struct ace_private *ap;
 	struct ace_regs *regs;
 	unsigned long flags;
 	u32 local;
@@ -3187,10 +3178,11 @@ static int __init read_eeprom_byte(struct net_device *dev,
 	if (!dev) {
 		printk(KERN_ERR "No device!\n");
 		result = -ENODEV;
-		goto eeprom_read_error;
+		goto out;
 	}
 
-	regs = ((struct ace_private *)dev->priv)->regs;
+	ap = netdev_priv(dev);
+	regs = ap->regs;
 
 	/*
 	 * Don't take interrupts on this CPU will bit banging
@@ -3203,7 +3195,7 @@ static int __init read_eeprom_byte(struct net_device *dev,
 	eeprom_prep(regs, EEPROM_WRITE_SELECT);
 	if (eeprom_check_ack(regs)) {
 		local_irq_restore(flags);
-		printk(KERN_ERR "%s: Unable to sync eeprom\n", dev->name);
+		printk(KERN_ERR "%s: Unable to sync eeprom\n", ap->name);
 		result = -EIO;
 		goto eeprom_read_error;
 	}
@@ -3212,7 +3204,7 @@ static int __init read_eeprom_byte(struct net_device *dev,
 	if (eeprom_check_ack(regs)) {
 		local_irq_restore(flags);
 		printk(KERN_ERR "%s: Unable to set address byte 0\n",
-		       dev->name);
+		       ap->name);
 		result = -EIO;
 		goto eeprom_read_error;
 	}
@@ -3221,7 +3213,7 @@ static int __init read_eeprom_byte(struct net_device *dev,
 	if (eeprom_check_ack(regs)) {
 		local_irq_restore(flags);
 		printk(KERN_ERR "%s: Unable to set address byte 1\n",
-		       dev->name);
+		       ap->name);
 		result = -EIO;
 		goto eeprom_read_error;
 	}
@@ -3231,7 +3223,7 @@ static int __init read_eeprom_byte(struct net_device *dev,
 	if (eeprom_check_ack(regs)) {
 		local_irq_restore(flags);
 		printk(KERN_ERR "%s: Unable to set READ_SELECT\n",
-		       dev->name);
+		       ap->name);
 		result = -EIO;
 		goto eeprom_read_error;
 	}
@@ -3288,7 +3280,7 @@ static int __init read_eeprom_byte(struct net_device *dev,
 
  eeprom_read_error:
 	printk(KERN_ERR "%s: Unable to read eeprom byte 0x%02lx\n",
-	       dev->name, offset);
+	       ap->name, offset);
 	goto out;
 }
 
diff --git a/drivers/net/acenic.h b/drivers/net/acenic.h
index c4624b85d..6eb134e7b 100644
--- a/drivers/net/acenic.h
+++ b/drivers/net/acenic.h
@@ -693,7 +693,7 @@ struct ace_private
 	int			board_idx;
 	u16			pci_command;
 	u8			pci_latency;
-	char			name[48];
+	const char		*name;
 #ifdef INDEX_DEBUG
 	spinlock_t		debug_lock
 				__attribute__ ((aligned (SMP_CACHE_BYTES)));
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index ca57a7a53..91fa987dc 100755
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
@@ -719,7 +719,7 @@ static int amd8111e_tx(struct net_device *dev)
 	return 0;
 }
 
-#if CONFIG_AMD8111E_NAPI 
+#ifdef CONFIG_AMD8111E_NAPI
 /* This function handles the driver receive operation in polling mode */
 static int amd8111e_rx_poll(struct net_device *dev, int * budget)
 {
diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c
index 77ff7df32..edcc38761 100644
--- a/drivers/net/arcnet/arc-rimi.c
+++ b/drivers/net/arcnet/arc-rimi.c
@@ -231,7 +231,7 @@ err_free_irq:
 static int arcrimi_reset(struct net_device *dev, int really_reset)
 {
 	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-	void *ioaddr = lp->mem_start + 0x800;
+	void __iomem *ioaddr = lp->mem_start + 0x800;
 
 	BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS());
 
@@ -252,7 +252,7 @@ static int arcrimi_reset(struct net_device *dev, int really_reset)
 static void arcrimi_setmask(struct net_device *dev, int mask)
 {
 	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-	void *ioaddr = lp->mem_start + 0x800;
+	void __iomem *ioaddr = lp->mem_start + 0x800;
 
 	AINTMASK(mask);
 }
@@ -260,7 +260,7 @@ static void arcrimi_setmask(struct net_device *dev, int mask)
 static int arcrimi_status(struct net_device *dev)
 {
 	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-	void *ioaddr = lp->mem_start + 0x800;
+	void __iomem *ioaddr = lp->mem_start + 0x800;
 
 	return ASTATUS();
 }
@@ -268,7 +268,7 @@ static int arcrimi_status(struct net_device *dev)
 static void arcrimi_command(struct net_device *dev, int cmd)
 {
 	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-	void *ioaddr = lp->mem_start + 0x800;
+	void __iomem *ioaddr = lp->mem_start + 0x800;
 
 	ACOMMAND(cmd);
 }
@@ -277,7 +277,7 @@ static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset,
 				 void *buf, int count)
 {
 	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-	void *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
+	void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
 	TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count));
 }
 
@@ -286,7 +286,7 @@ static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offse
 				   void *buf, int count)
 {
 	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-	void *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
+	void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
 	TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
 }
 
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index 5912a24a3..5d304676f 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -401,7 +401,8 @@ static int arcnet_open(struct net_device *dev)
 	lp->rfc1201.sequence = 1;
 
 	/* bring up the hardware driver */
-	lp->hw.open(dev);
+	if (lp->hw.open)
+		lp->hw.open(dev);
 
 	if (dev->dev_addr[0] == 0)
 		BUGMSG(D_NORMAL, "WARNING!  Station address 00 is reserved "
diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c
index 05a832a2f..ba0f8a2eb 100644
--- a/drivers/net/arcnet/com90xx.c
+++ b/drivers/net/arcnet/com90xx.c
@@ -566,7 +566,7 @@ static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset,
 				 void *buf, int count)
 {
 	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-	void *memaddr = lp->mem_start + bufnum * 512 + offset;
+	void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset;
 	TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count));
 }
 
@@ -575,7 +575,7 @@ static void com90xx_copy_from_card(struct net_device *dev, int bufnum, int offse
 				   void *buf, int count)
 {
 	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
-	void *memaddr = lp->mem_start + bufnum * 512 + offset;
+	void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset;
 	TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
 }
 
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index ba1d4fc9a..02d58a237 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -98,13 +98,24 @@ static void b44_halt(struct b44 *);
 static void b44_init_rings(struct b44 *);
 static void b44_init_hw(struct b44 *);
 
+static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
+{
+	return readl(bp->regs + reg);
+}
+
+static inline void bw32(const struct b44 *bp, 
+			unsigned long reg, unsigned long val)
+{
+	writel(val, bp->regs + reg);
+}
+
 static int b44_wait_bit(struct b44 *bp, unsigned long reg,
 			u32 bit, unsigned long timeout, const int clear)
 {
 	unsigned long i;
 
 	for (i = 0; i < timeout; i++) {
-		u32 val = br32(reg);
+		u32 val = br32(bp, reg);
 
 		if (clear && !(val & bit))
 			break;
@@ -168,7 +179,7 @@ static u32 ssb_get_addr(struct b44 *bp, u32 id, u32 instance)
 
 static u32 ssb_get_core_rev(struct b44 *bp)
 {
-	return (br32(B44_SBIDHIGH) & SBIDHIGH_RC_MASK);
+	return (br32(bp, B44_SBIDHIGH) & SBIDHIGH_RC_MASK);
 }
 
 static u32 ssb_pci_setup(struct b44 *bp, u32 cores)
@@ -180,13 +191,13 @@ static u32 ssb_pci_setup(struct b44 *bp, u32 cores)
 			       ssb_get_addr(bp, SBID_REG_PCI, 0));
 	pci_rev = ssb_get_core_rev(bp);
 
-	val = br32(B44_SBINTVEC);
+	val = br32(bp, B44_SBINTVEC);
 	val |= cores;
-	bw32(B44_SBINTVEC, val);
+	bw32(bp, B44_SBINTVEC, val);
 
-	val = br32(SSB_PCI_TRANS_2);
+	val = br32(bp, SSB_PCI_TRANS_2);
 	val |= SSB_PCI_PREF | SSB_PCI_BURST;
-	bw32(SSB_PCI_TRANS_2, val);
+	bw32(bp, SSB_PCI_TRANS_2, val);
 
 	pci_write_config_dword(bp->pdev, SSB_BAR0_WIN, bar_orig);
 
@@ -195,18 +206,18 @@ static u32 ssb_pci_setup(struct b44 *bp, u32 cores)
 
 static void ssb_core_disable(struct b44 *bp)
 {
-	if (br32(B44_SBTMSLOW) & SBTMSLOW_RESET)
+	if (br32(bp, B44_SBTMSLOW) & SBTMSLOW_RESET)
 		return;
 
-	bw32(B44_SBTMSLOW, (SBTMSLOW_REJECT | SBTMSLOW_CLOCK));
+	bw32(bp, B44_SBTMSLOW, (SBTMSLOW_REJECT | SBTMSLOW_CLOCK));
 	b44_wait_bit(bp, B44_SBTMSLOW, SBTMSLOW_REJECT, 100000, 0);
 	b44_wait_bit(bp, B44_SBTMSHIGH, SBTMSHIGH_BUSY, 100000, 1);
-	bw32(B44_SBTMSLOW, (SBTMSLOW_FGC | SBTMSLOW_CLOCK |
+	bw32(bp, B44_SBTMSLOW, (SBTMSLOW_FGC | SBTMSLOW_CLOCK |
 			    SBTMSLOW_REJECT | SBTMSLOW_RESET));
-	br32(B44_SBTMSLOW);
+	br32(bp, B44_SBTMSLOW);
 	udelay(1);
-	bw32(B44_SBTMSLOW, (SBTMSLOW_REJECT | SBTMSLOW_RESET));
-	br32(B44_SBTMSLOW);
+	bw32(bp, B44_SBTMSLOW, (SBTMSLOW_REJECT | SBTMSLOW_RESET));
+	br32(bp, B44_SBTMSLOW);
 	udelay(1);
 }
 
@@ -215,31 +226,31 @@ static void ssb_core_reset(struct b44 *bp)
 	u32 val;
 
 	ssb_core_disable(bp);
-	bw32(B44_SBTMSLOW, (SBTMSLOW_RESET | SBTMSLOW_CLOCK | SBTMSLOW_FGC));
-	br32(B44_SBTMSLOW);
+	bw32(bp, B44_SBTMSLOW, (SBTMSLOW_RESET | SBTMSLOW_CLOCK | SBTMSLOW_FGC));
+	br32(bp, B44_SBTMSLOW);
 	udelay(1);
 
 	/* Clear SERR if set, this is a hw bug workaround.  */
-	if (br32(B44_SBTMSHIGH) & SBTMSHIGH_SERR)
-		bw32(B44_SBTMSHIGH, 0);
+	if (br32(bp, B44_SBTMSHIGH) & SBTMSHIGH_SERR)
+		bw32(bp, B44_SBTMSHIGH, 0);
 
-	val = br32(B44_SBIMSTATE);
+	val = br32(bp, B44_SBIMSTATE);
 	if (val & (SBIMSTATE_IBE | SBIMSTATE_TO))
-		bw32(B44_SBIMSTATE, val & ~(SBIMSTATE_IBE | SBIMSTATE_TO));
+		bw32(bp, B44_SBIMSTATE, val & ~(SBIMSTATE_IBE | SBIMSTATE_TO));
 
-	bw32(B44_SBTMSLOW, (SBTMSLOW_CLOCK | SBTMSLOW_FGC));
-	br32(B44_SBTMSLOW);
+	bw32(bp, B44_SBTMSLOW, (SBTMSLOW_CLOCK | SBTMSLOW_FGC));
+	br32(bp, B44_SBTMSLOW);
 	udelay(1);
 
-	bw32(B44_SBTMSLOW, (SBTMSLOW_CLOCK));
-	br32(B44_SBTMSLOW);
+	bw32(bp, B44_SBTMSLOW, (SBTMSLOW_CLOCK));
+	br32(bp, B44_SBTMSLOW);
 	udelay(1);
 }
 
 static int ssb_core_unit(struct b44 *bp)
 {
 #if 0
-	u32 val = br32(B44_SBADMATCH0);
+	u32 val = br32(bp, B44_SBADMATCH0);
 	u32 base;
 
 	type = val & SBADMATCH0_TYPE_MASK;
@@ -263,7 +274,7 @@ static int ssb_core_unit(struct b44 *bp)
 
 static int ssb_is_core_up(struct b44 *bp)
 {
-	return ((br32(B44_SBTMSLOW) & (SBTMSLOW_RESET | SBTMSLOW_REJECT | SBTMSLOW_CLOCK))
+	return ((br32(bp, B44_SBTMSLOW) & (SBTMSLOW_RESET | SBTMSLOW_REJECT | SBTMSLOW_CLOCK))
 		== SBTMSLOW_CLOCK);
 }
 
@@ -275,19 +286,19 @@ static void __b44_cam_write(struct b44 *bp, unsigned char *data, int index)
 	val |= ((u32) data[3]) << 16;
 	val |= ((u32) data[4]) <<  8;
 	val |= ((u32) data[5]) <<  0;
-	bw32(B44_CAM_DATA_LO, val);
+	bw32(bp, B44_CAM_DATA_LO, val);
 	val = (CAM_DATA_HI_VALID | 
 	       (((u32) data[0]) << 8) |
 	       (((u32) data[1]) << 0));
-	bw32(B44_CAM_DATA_HI, val);
-	bw32(B44_CAM_CTRL, (CAM_CTRL_WRITE |
+	bw32(bp, B44_CAM_DATA_HI, val);
+	bw32(bp, B44_CAM_CTRL, (CAM_CTRL_WRITE |
 			    (index << CAM_CTRL_INDEX_SHIFT)));
 	b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1);	
 }
 
 static inline void __b44_disable_ints(struct b44 *bp)
 {
-	bw32(B44_IMASK, 0);
+	bw32(bp, B44_IMASK, 0);
 }
 
 static void b44_disable_ints(struct b44 *bp)
@@ -295,34 +306,34 @@ static void b44_disable_ints(struct b44 *bp)
 	__b44_disable_ints(bp);
 
 	/* Flush posted writes. */
-	br32(B44_IMASK);
+	br32(bp, B44_IMASK);
 }
 
 static void b44_enable_ints(struct b44 *bp)
 {
-	bw32(B44_IMASK, bp->imask);
+	bw32(bp, B44_IMASK, bp->imask);
 }
 
 static int b44_readphy(struct b44 *bp, int reg, u32 *val)
 {
 	int err;
 
-	bw32(B44_EMAC_ISTAT, EMAC_INT_MII);
-	bw32(B44_MDIO_DATA, (MDIO_DATA_SB_START |
+	bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
+	bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START |
 			     (MDIO_OP_READ << MDIO_DATA_OP_SHIFT) |
 			     (bp->phy_addr << MDIO_DATA_PMD_SHIFT) |
 			     (reg << MDIO_DATA_RA_SHIFT) |
 			     (MDIO_TA_VALID << MDIO_DATA_TA_SHIFT)));
 	err = b44_wait_bit(bp, B44_EMAC_ISTAT, EMAC_INT_MII, 100, 0);
-	*val = br32(B44_MDIO_DATA) & MDIO_DATA_DATA;
+	*val = br32(bp, B44_MDIO_DATA) & MDIO_DATA_DATA;
 
 	return err;
 }
 
 static int b44_writephy(struct b44 *bp, int reg, u32 val)
 {
-	bw32(B44_EMAC_ISTAT, EMAC_INT_MII);
-	bw32(B44_MDIO_DATA, (MDIO_DATA_SB_START |
+	bw32(bp, B44_EMAC_ISTAT, EMAC_INT_MII);
+	bw32(bp, B44_MDIO_DATA, (MDIO_DATA_SB_START |
 			     (MDIO_OP_WRITE << MDIO_DATA_OP_SHIFT) |
 			     (bp->phy_addr << MDIO_DATA_PMD_SHIFT) |
 			     (reg << MDIO_DATA_RA_SHIFT) |
@@ -382,20 +393,20 @@ static void __b44_set_flow_ctrl(struct b44 *bp, u32 pause_flags)
 	bp->flags &= ~(B44_FLAG_TX_PAUSE | B44_FLAG_RX_PAUSE);
 	bp->flags |= pause_flags;
 
-	val = br32(B44_RXCONFIG);
+	val = br32(bp, B44_RXCONFIG);
 	if (pause_flags & B44_FLAG_RX_PAUSE)
 		val |= RXCONFIG_FLOW;
 	else
 		val &= ~RXCONFIG_FLOW;
-	bw32(B44_RXCONFIG, val);
+	bw32(bp, B44_RXCONFIG, val);
 
-	val = br32(B44_MAC_FLOW);
+	val = br32(bp, B44_MAC_FLOW);
 	if (pause_flags & B44_FLAG_TX_PAUSE)
 		val |= (MAC_FLOW_PAUSE_ENAB |
 			(0xc0 & MAC_FLOW_RX_HI_WATER));
 	else
 		val &= ~MAC_FLOW_PAUSE_ENAB;
-	bw32(B44_MAC_FLOW, val);
+	bw32(bp, B44_MAC_FLOW, val);
 }
 
 static void b44_set_flow_ctrl(struct b44 *bp, u32 local, u32 remote)
@@ -491,11 +502,11 @@ static void b44_stats_update(struct b44 *bp)
 
 	val = &bp->hw_stats.tx_good_octets;
 	for (reg = B44_TX_GOOD_O; reg <= B44_TX_PAUSE; reg += 4UL) {
-		*val++ += br32(reg);
+		*val++ += br32(bp, reg);
 	}
 	val = &bp->hw_stats.rx_good_octets;
 	for (reg = B44_RX_GOOD_O; reg <= B44_RX_NPAUSE; reg += 4UL) {
-		*val++ += br32(reg);
+		*val++ += br32(bp, reg);
 	}
 }
 
@@ -535,14 +546,14 @@ static void b44_check_phy(struct b44 *bp)
 
 		if (!netif_carrier_ok(bp->dev) &&
 		    (bmsr & BMSR_LSTATUS)) {
-			u32 val = br32(B44_TX_CTRL);
+			u32 val = br32(bp, B44_TX_CTRL);
 			u32 local_adv, remote_adv;
 
 			if (bp->flags & B44_FLAG_FULL_DUPLEX)
 				val |= TX_CTRL_DUPLEX;
 			else
 				val &= ~TX_CTRL_DUPLEX;
-			bw32(B44_TX_CTRL, val);
+			bw32(bp, B44_TX_CTRL, val);
 
 			if (!(bp->flags & B44_FLAG_FORCE_LINK) &&
 			    !b44_readphy(bp, MII_ADVERTISE, &local_adv) &&
@@ -587,7 +598,7 @@ static void b44_tx(struct b44 *bp)
 {
 	u32 cur, cons;
 
-	cur  = br32(B44_DMATX_STAT) & DMATX_STAT_CDMASK;
+	cur  = br32(bp, B44_DMATX_STAT) & DMATX_STAT_CDMASK;
 	cur /= sizeof(struct dma_desc);
 
 	/* XXX needs updating when NETIF_F_SG is supported */
@@ -611,7 +622,7 @@ static void b44_tx(struct b44 *bp)
 	    TX_BUFFS_AVAIL(bp) > B44_TX_WAKEUP_THRESH)
 		netif_wake_queue(bp->dev);
 
-	bw32(B44_GPTIMER, 0);
+	bw32(bp, B44_GPTIMER, 0);
 }
 
 /* Works like this.  This chip writes a 'struct rx_header" 30 bytes
@@ -708,7 +719,7 @@ static int b44_rx(struct b44 *bp, int budget)
 	u32 cons, prod;
 
 	received = 0;
-	prod  = br32(B44_DMARX_STAT) & DMARX_STAT_CDMASK;
+	prod  = br32(bp, B44_DMARX_STAT) & DMARX_STAT_CDMASK;
 	prod /= sizeof(struct dma_desc);
 	cons = bp->rx_cons;
 
@@ -787,7 +798,7 @@ static int b44_rx(struct b44 *bp, int budget)
 	}
 
 	bp->rx_cons = cons;
-	bw32(B44_DMARX_PTR, cons * sizeof(struct dma_desc));
+	bw32(bp, B44_DMARX_PTR, cons * sizeof(struct dma_desc));
 
 	return received;
 }
@@ -851,8 +862,8 @@ static irqreturn_t b44_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
 	spin_lock_irqsave(&bp->lock, flags);
 
-	istat = br32(B44_ISTAT);
-	imask = br32(B44_IMASK);
+	istat = br32(bp, B44_ISTAT);
+	imask = br32(bp, B44_IMASK);
 
 	/* ??? What the fuck is the purpose of the interrupt mask
 	 * ??? register if we have to mask it out by hand anyways?
@@ -872,8 +883,8 @@ static irqreturn_t b44_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 			       dev->name);
 		}
 
-		bw32(B44_ISTAT, istat);
-		br32(B44_ISTAT);
+		bw32(bp, B44_ISTAT, istat);
+		br32(bp, B44_ISTAT);
 	}
 	spin_unlock_irqrestore(&bp->lock, flags);
 	return IRQ_RETVAL(handled);
@@ -937,11 +948,11 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	wmb();
 
-	bw32(B44_DMATX_PTR, entry * sizeof(struct dma_desc));
+	bw32(bp, B44_DMATX_PTR, entry * sizeof(struct dma_desc));
 	if (bp->flags & B44_FLAG_BUGGY_TXPTR)
-		bw32(B44_DMATX_PTR, entry * sizeof(struct dma_desc));
+		bw32(bp, B44_DMATX_PTR, entry * sizeof(struct dma_desc));
 	if (bp->flags & B44_FLAG_REORDER_BUG)
-		br32(B44_DMATX_PTR);
+		br32(bp, B44_DMATX_PTR);
 
 	if (TX_BUFFS_AVAIL(bp) < 1)
 		netif_stop_queue(dev);
@@ -1109,27 +1120,27 @@ static void b44_clear_stats(struct b44 *bp)
 {
 	unsigned long reg;
 
-	bw32(B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
+	bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
 	for (reg = B44_TX_GOOD_O; reg <= B44_TX_PAUSE; reg += 4UL)
-		br32(reg);
+		br32(bp, reg);
 	for (reg = B44_RX_GOOD_O; reg <= B44_RX_NPAUSE; reg += 4UL)
-		br32(reg);
+		br32(bp, reg);
 }
 
 /* bp->lock is held. */
 static void b44_chip_reset(struct b44 *bp)
 {
 	if (ssb_is_core_up(bp)) {
-		bw32(B44_RCV_LAZY, 0);
-		bw32(B44_ENET_CTRL, ENET_CTRL_DISABLE);
+		bw32(bp, B44_RCV_LAZY, 0);
+		bw32(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE);
 		b44_wait_bit(bp, B44_ENET_CTRL, ENET_CTRL_DISABLE, 100, 1);
-		bw32(B44_DMATX_CTRL, 0);
+		bw32(bp, B44_DMATX_CTRL, 0);
 		bp->tx_prod = bp->tx_cons = 0;
-		if (br32(B44_DMARX_STAT) & DMARX_STAT_EMASK) {
+		if (br32(bp, B44_DMARX_STAT) & DMARX_STAT_EMASK) {
 			b44_wait_bit(bp, B44_DMARX_STAT, DMARX_STAT_SIDLE,
 				     100, 0);
 		}
-		bw32(B44_DMARX_CTRL, 0);
+		bw32(bp, B44_DMARX_CTRL, 0);
 		bp->rx_prod = bp->rx_cons = 0;
 	} else {
 		ssb_pci_setup(bp, (bp->core_unit == 0 ?
@@ -1142,20 +1153,20 @@ static void b44_chip_reset(struct b44 *bp)
 	b44_clear_stats(bp);
 
 	/* Make PHY accessible. */
-	bw32(B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
+	bw32(bp, B44_MDIO_CTRL, (MDIO_CTRL_PREAMBLE |
 			     (0x0d & MDIO_CTRL_MAXF_MASK)));
-	br32(B44_MDIO_CTRL);
+	br32(bp, B44_MDIO_CTRL);
 
-	if (!(br32(B44_DEVCTRL) & DEVCTRL_IPP)) {
-		bw32(B44_ENET_CTRL, ENET_CTRL_EPSEL);
-		br32(B44_ENET_CTRL);
+	if (!(br32(bp, B44_DEVCTRL) & DEVCTRL_IPP)) {
+		bw32(bp, B44_ENET_CTRL, ENET_CTRL_EPSEL);
+		br32(bp, B44_ENET_CTRL);
 		bp->flags &= ~B44_FLAG_INTERNAL_PHY;
 	} else {
-		u32 val = br32(B44_DEVCTRL);
+		u32 val = br32(bp, B44_DEVCTRL);
 
 		if (val & DEVCTRL_EPR) {
-			bw32(B44_DEVCTRL, (val & ~DEVCTRL_EPR));
-			br32(B44_DEVCTRL);
+			bw32(bp, B44_DEVCTRL, (val & ~DEVCTRL_EPR));
+			br32(bp, B44_DEVCTRL);
 			udelay(100);
 		}
 		bp->flags |= B44_FLAG_INTERNAL_PHY;
@@ -1172,13 +1183,13 @@ static void b44_halt(struct b44 *bp)
 /* bp->lock is held. */
 static void __b44_set_mac_addr(struct b44 *bp)
 {
-	bw32(B44_CAM_CTRL, 0);
+	bw32(bp, B44_CAM_CTRL, 0);
 	if (!(bp->dev->flags & IFF_PROMISC)) {
 		u32 val;
 
 		__b44_cam_write(bp, bp->dev->dev_addr, 0);
-		val = br32(B44_CAM_CTRL);
-		bw32(B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
+		val = br32(bp, B44_CAM_CTRL);
+		bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
 	}
 }
 
@@ -1212,30 +1223,30 @@ static void b44_init_hw(struct b44 *bp)
 	b44_setup_phy(bp);
 
 	/* Enable CRC32, set proper LED modes and power on PHY */
-	bw32(B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL);
-	bw32(B44_RCV_LAZY, (1 << RCV_LAZY_FC_SHIFT));
+	bw32(bp, B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL);
+	bw32(bp, B44_RCV_LAZY, (1 << RCV_LAZY_FC_SHIFT));
 
 	/* This sets the MAC address too.  */
 	__b44_set_rx_mode(bp->dev);
 
 	/* MTU + eth header + possible VLAN tag + struct rx_header */
-	bw32(B44_RXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
-	bw32(B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
+	bw32(bp, B44_RXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
+	bw32(bp, B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
 
-	bw32(B44_TX_WMARK, 56); /* XXX magic */
-	bw32(B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
-	bw32(B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
-	bw32(B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
+	bw32(bp, B44_TX_WMARK, 56); /* XXX magic */
+	bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
+	bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
+	bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
 			      (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
-	bw32(B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
+	bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
 
-	bw32(B44_DMARX_PTR, bp->rx_pending);
+	bw32(bp, B44_DMARX_PTR, bp->rx_pending);
 	bp->rx_prod = bp->rx_pending;	
 
-	bw32(B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
+	bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
 
-	val = br32(B44_ENET_CTRL);
-	bw32(B44_ENET_CTRL, (val | ENET_CTRL_ENABLE));
+	val = br32(bp, B44_ENET_CTRL);
+	bw32(bp, B44_ENET_CTRL, (val | ENET_CTRL_ENABLE));
 }
 
 static int b44_open(struct net_device *dev)
@@ -1372,11 +1383,11 @@ static void __b44_set_rx_mode(struct net_device *dev)
 	int i=0;
 	unsigned char zero[6] = {0,0,0,0,0,0};
 
-	val = br32(B44_RXCONFIG);
+	val = br32(bp, B44_RXCONFIG);
 	val &= ~(RXCONFIG_PROMISC | RXCONFIG_ALLMULTI);
 	if (dev->flags & IFF_PROMISC) {
 		val |= RXCONFIG_PROMISC;
-		bw32(B44_RXCONFIG, val);
+		bw32(bp, B44_RXCONFIG, val);
 	} else {
 		__b44_set_mac_addr(bp);
 
@@ -1388,9 +1399,9 @@ static void __b44_set_rx_mode(struct net_device *dev)
 		for(;i<64;i++) {
 			__b44_cam_write(bp, zero, i);			
 		}
-		bw32(B44_RXCONFIG, val);
-        	val = br32(B44_CAM_CTRL);
-	        bw32(B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
+		bw32(bp, B44_RXCONFIG, val);
+        	val = br32(bp, B44_CAM_CTRL);
+	        bw32(bp, B44_CAM_CTRL, val | CAM_CTRL_ENABLE);
 	}
 }
 
@@ -1760,7 +1771,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
 
 	spin_lock_init(&bp->lock);
 
-	bp->regs = (unsigned long) ioremap(b44reg_base, b44reg_len);
+	bp->regs = ioremap(b44reg_base, b44reg_len);
 	if (bp->regs == 0UL) {
 		printk(KERN_ERR PFX "Cannot map device registers, "
 		       "aborting.\n");
@@ -1826,7 +1837,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev,
 	return 0;
 
 err_out_iounmap:
-	iounmap((void *) bp->regs);
+	iounmap(bp->regs);
 
 err_out_free_dev:
 	free_netdev(dev);
@@ -1848,7 +1859,7 @@ static void __devexit b44_remove_one(struct pci_dev *pdev)
 		struct b44 *bp = netdev_priv(dev);
 
 		unregister_netdev(dev);
-		iounmap((void *) bp->regs);
+		iounmap(bp->regs);
 		free_netdev(dev);
 		pci_release_regions(pdev);
 		pci_disable_device(pdev);
diff --git a/drivers/net/b44.h b/drivers/net/b44.h
index 23bee93fe..22647be2c 100644
--- a/drivers/net/b44.h
+++ b/drivers/net/b44.h
@@ -395,9 +395,6 @@
 #define SSB_PCI_MASK1		0xfc000000
 #define SSB_PCI_MASK2		0xc0000000
 
-#define br32(REG)	readl(bp->regs + (REG))
-#define bw32(REG,VAL)	writel((VAL), bp->regs + (REG))
-
 /* 4400 PHY registers */
 #define B44_MII_AUXCTRL		24	/* Auxiliary Control */
 #define  MII_AUXCTRL_DUPLEX	0x0001  /* Full Duplex */
@@ -530,7 +527,7 @@ struct b44 {
 	struct net_device_stats	stats;
 	struct b44_hw_stats	hw_stats;
 
-	unsigned long		regs;
+	void __iomem		*regs;
 	struct pci_dev		*pdev;
 	struct net_device	*dev;
 
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 49f5ceee5..a76519afa 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -1285,7 +1285,7 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
 	int res = 1;
 
 	skb->mac.raw = (unsigned char *)skb->data;
-	eth_data = (struct ethhdr *)skb->data;
+	eth_data = eth_hdr(skb);
 
 	/* make sure that the curr_active_slave and the slaves list do
 	 * not change during tx
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index b04bf5e72..3ce3237b1 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -84,6 +84,9 @@
   Oskar Schirmer    : oskar@scara.com
                     : HiCO.SH4 (superh) support added (irq#1, cs89x0_media=)
 
+  Deepak Saxena     : dsaxena@plexity.net
+                    : Intel IXDP2x01 (XScale ixp2x00 NPU) platform support
+
 */
 
 /* Always include 'config.h' first in case the user wants to turn on
@@ -97,7 +100,11 @@
  * Note that even if DMA is turned off we still support the 'dma' and  'use_dma'
  * module options so we don't break any startup scripts.
  */
+#ifndef CONFIG_ARCH_IXDP2X01
+#define ALLOW_DMA	0
+#else
 #define ALLOW_DMA	1
+#endif
 
 /*
  * Set this to zero to remove all the debug statements via
@@ -162,6 +169,10 @@ static unsigned int cs8900_irq_map[] = {12,0,0,0};
 static unsigned int netcard_portlist[] __initdata =
    { 0x0300, 0};
 static unsigned int cs8900_irq_map[] = {1,0,0,0};
+#elif defined(CONFIG_ARCH_IXDP2X01)
+#include <asm/irq.h>
+static unsigned int netcard_portlist[] __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0};
+static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0};
 #else
 static unsigned int netcard_portlist[] __initdata =
    { 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
@@ -454,11 +465,12 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
 		        	retval = -ENODEV;
 				goto out2;
 			}
-		ioaddr &= ~3;
-		outw(PP_ChipID, ioaddr + ADD_PORT);
 	}
 printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
 
+	ioaddr &= ~3;
+	outw(PP_ChipID, ioaddr + ADD_PORT);
+
 	if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG) {
 		printk(KERN_ERR "%s: incorrect signature 0x%x\n",
 			dev->name, inw(ioaddr + DATA_PORT));
@@ -665,6 +677,9 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
 	} else {
 		i = lp->isa_config & INT_NO_MASK;
 		if (lp->chip_type == CS8900) {
+#ifdef CONFIG_ARCH_IXDP2X01
+		        i = cs8900_irq_map[0];
+#else
 			/* Translate the IRQ using the IRQ mapping table. */
 			if (i >= sizeof(cs8900_irq_map)/sizeof(cs8900_irq_map[0]))
 				printk("\ncs89x0: invalid ISA interrupt number %d\n", i);
@@ -681,6 +696,7 @@ printk("PP_addr=0x%x\n", inw(ioaddr + ADD_PORT));
 				if ((irq_map_buff[0] & 0xff) == PNP_IRQ_FRMT)
 					lp->irq_map = (irq_map_buff[0]>>8) | (irq_map_buff[1] << 8);
 			}
+#endif
 		}
 		if (!dev->irq)
 			dev->irq = i;
@@ -884,8 +900,10 @@ skip_this_frame:
 
 void  __init reset_chip(struct net_device *dev)
 {
+#ifndef CONFIG_ARCH_IXDP2X01
 	struct net_local *lp = netdev_priv(dev);
 	int ioaddr = dev->base_addr;
+#endif
 	int reset_start_time;
 
 	writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET);
@@ -894,6 +912,7 @@ void  __init reset_chip(struct net_device *dev)
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(30*HZ/1000);
 
+#ifndef CONFIG_ARCH_IXDP2X01
 	if (lp->chip_type != CS8900) {
 		/* Hardware problem requires PNP registers to be reconfigured after a reset */
 		outw(PP_CS8920_ISAINT, ioaddr + ADD_PORT);
@@ -904,6 +923,8 @@ void  __init reset_chip(struct net_device *dev)
 		outb((dev->mem_start >> 16) & 0xff, ioaddr + DATA_PORT);
 		outb((dev->mem_start >> 8) & 0xff,   ioaddr + DATA_PORT + 1);
 	}
+#endif	/* IXDP2x01 */
+
 	/* Wait until the chip is reset */
 	reset_start_time = jiffies;
 	while( (readreg(dev, PP_SelfST) & INIT_DONE) == 0 && jiffies - reset_start_time < 2)
@@ -1155,12 +1176,14 @@ net_open(struct net_device *dev)
 	else
 #endif
 	{
+#ifndef CONFIG_ARCH_IXDP2X01
 		if (((1 << dev->irq) & lp->irq_map) == 0) {
 			printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
                                dev->name, dev->irq, lp->irq_map);
 			ret = -EAGAIN;
 			goto bad_out;
 		}
+#endif
 /* FIXME: Cirrus' release had this: */
 		writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ );
 /* And 2.3.47 had this: */
@@ -1575,7 +1598,9 @@ static void release_dma_buff(struct net_local *lp)
 static int
 net_close(struct net_device *dev)
 {
+#if ALLOW_DMA
 	struct net_local *lp = netdev_priv(dev);
+#endif
 
 	netif_stop_queue(dev);
 	
diff --git a/drivers/net/cs89x0.h b/drivers/net/cs89x0.h
index f1507b549..b0ef7ad2b 100644
--- a/drivers/net/cs89x0.h
+++ b/drivers/net/cs89x0.h
@@ -16,6 +16,13 @@
 
 #include <linux/config.h>
 
+#ifdef CONFIG_ARCH_IXDP2X01
+/* IXDP2401/IXDP2801 uses dword-aligned register addressing */
+#define CS89x0_PORT(reg) ((reg) * 2)
+#else
+#define CS89x0_PORT(reg) (reg)
+#endif
+
 #define PP_ChipID 0x0000	/* offset   0h -> Corp -ID              */
 				/* offset   2h -> Model/Product Number  */
 				/* offset   3h -> Chip Revision Number  */
@@ -324,16 +331,16 @@
 #define RAM_SIZE	0x1000       /*  The card has 4k bytes or RAM */
 #define PKT_START PP_TxFrame  /*  Start of packet RAM */
 
-#define RX_FRAME_PORT	0x0000
+#define RX_FRAME_PORT	CS89x0_PORT(0x0000)
 #define TX_FRAME_PORT RX_FRAME_PORT
-#define TX_CMD_PORT	0x0004
+#define TX_CMD_PORT	CS89x0_PORT(0x0004)
 #define TX_NOW		0x0000       /*  Tx packet after   5 bytes copied */
 #define TX_AFTER_381	0x0040       /*  Tx packet after 381 bytes copied */
 #define TX_AFTER_ALL	0x00c0       /*  Tx packet after all bytes copied */
-#define TX_LEN_PORT	0x0006
-#define ISQ_PORT	0x0008
-#define ADD_PORT	0x000A
-#define DATA_PORT	0x000C
+#define TX_LEN_PORT	CS89x0_PORT(0x0006)
+#define ISQ_PORT	CS89x0_PORT(0x0008)
+#define ADD_PORT	CS89x0_PORT(0x000A)
+#define DATA_PORT	CS89x0_PORT(0x000C)
 
 #define EEPROM_WRITE_EN		0x00F0
 #define EEPROM_WRITE_DIS	0x0000
diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
index 9ef9f3944..85d1bb3a9 100644
--- a/drivers/net/defxx.c
+++ b/drivers/net/defxx.c
@@ -1814,16 +1814,18 @@ static struct net_device_stats *dfx_ctl_get_stats(struct net_device *dev)
 
 	/* Fill the bp->stats structure with driver-maintained counters */
 
-	bp->stats.rx_packets			= bp->rcv_total_frames;
-	bp->stats.tx_packets			= bp->xmt_total_frames;
-	bp->stats.rx_bytes			= bp->rcv_total_bytes;
-	bp->stats.tx_bytes			= bp->xmt_total_bytes;
-	bp->stats.rx_errors				= (u32)(bp->rcv_crc_errors + bp->rcv_frame_status_errors + bp->rcv_length_errors);
-	bp->stats.tx_errors				= bp->xmt_length_errors;
-	bp->stats.rx_dropped			= bp->rcv_discards;
-	bp->stats.tx_dropped			= bp->xmt_discards;
-	bp->stats.multicast				= bp->rcv_multicast_frames;
-	bp->stats.transmit_collision	= 0;	/* always zero (0) for FDDI */
+	bp->stats.gen.rx_packets = bp->rcv_total_frames;
+	bp->stats.gen.tx_packets = bp->xmt_total_frames;
+	bp->stats.gen.rx_bytes   = bp->rcv_total_bytes;
+	bp->stats.gen.tx_bytes   = bp->xmt_total_bytes;
+	bp->stats.gen.rx_errors  = bp->rcv_crc_errors +
+				   bp->rcv_frame_status_errors +
+				   bp->rcv_length_errors;
+	bp->stats.gen.tx_errors  = bp->xmt_length_errors;
+	bp->stats.gen.rx_dropped = bp->rcv_discards;
+	bp->stats.gen.tx_dropped = bp->xmt_discards;
+	bp->stats.gen.multicast  = bp->rcv_multicast_frames;
+	bp->stats.gen.collisions = 0;		/* always zero (0) for FDDI */
 
 	/* Get FDDI SMT MIB objects */
 
diff --git a/drivers/net/dl2k.h b/drivers/net/dl2k.h
index 86302faf9..d46367392 100644
--- a/drivers/net/dl2k.h
+++ b/drivers/net/dl2k.h
@@ -92,7 +92,7 @@ enum dl2x_offsets {
 	EepromCtrl = 0x4a,
 	ExpromAddr = 0x4c,
 	Exprodata = 0x50,
-	WakeEvent0x51,
+	WakeEvent = 0x51,
 	CountDown = 0x54,
 	IntStatusAck = 0x5a,
 	IntEnable = 0x5c,
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 8855b20e3..a39b58c81 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -87,9 +87,8 @@
  *	cb_to_use is the next CB to use for queuing a command; cb_to_clean
  *	is the next CB to check for completion; cb_to_send is the first
  *	CB to start on in case of a previous failure to resume.  CB clean
- *	up happens in interrupt context in response to a CU interrupt, or
- *	in dev->poll in the case where NAPI is enabled.  cbs_avail keeps
- *	track of number of free CB resources available.
+ *	up happens in interrupt context in response to a CU interrupt.
+ *	cbs_avail keeps track of number of free CB resources available.
  *
  * 	Hardware padding of short packets to minimum packet size is
  * 	enabled.  82557 pads with 7Eh, while the later controllers pad
@@ -112,9 +111,8 @@
  *	replacement RFDs cannot be allocated, or the RU goes non-active,
  *	the RU must be restarted.  Frame arrival generates an interrupt,
  *	and Rx indication and re-allocation happen in the same context,
- *	therefore no locking is required.  If NAPI is enabled, this work
- *	happens in dev->poll.  A software-generated interrupt is gen-
- *	erated from the watchdog to recover from a failed allocation
+ *	therefore no locking is required.  A software-generated interrupt
+ *	is generated from the watchdog to recover from a failed allocation
  *	senario where all Rx resources have been indicated and none re-
  *	placed.
  *
@@ -126,8 +124,6 @@
  * 	supported.  Tx Scatter/Gather is not supported.  Jumbo Frames is
  * 	not supported (hardware limitation).
  *
- * 	NAPI support is enabled with CONFIG_E100_NAPI.
- *
  * 	MagicPacket(tm) WoL support is enabled/disabled via ethtool.
  *
  * 	Thanks to JC (jchapman@katalix.com) for helping with
@@ -158,7 +154,8 @@
 
 
 #define DRV_NAME		"e100"
-#define DRV_VERSION		"3.0.18"
+#define DRV_EXT			"-NAPI"
+#define DRV_VERSION		"3.0.27-k2"DRV_EXT
 #define DRV_DESCRIPTION		"Intel(R) PRO/100 Network Driver"
 #define DRV_COPYRIGHT		"Copyright(c) 1999-2004 Intel Corporation"
 #define PFX			DRV_NAME ": "
@@ -201,6 +198,8 @@ static struct pci_device_id e100_id_table[] = {
 	INTEL_8255X_ETHERNET_DEVICE(0x1053, 5),
 	INTEL_8255X_ETHERNET_DEVICE(0x1054, 5),
 	INTEL_8255X_ETHERNET_DEVICE(0x1055, 5),
+	INTEL_8255X_ETHERNET_DEVICE(0x1056, 5),
+	INTEL_8255X_ETHERNET_DEVICE(0x1057, 5),
 	INTEL_8255X_ETHERNET_DEVICE(0x1064, 6),
 	INTEL_8255X_ETHERNET_DEVICE(0x1065, 6),
 	INTEL_8255X_ETHERNET_DEVICE(0x1066, 6),
@@ -242,6 +241,7 @@ enum phy {
 	phy_nsc_tx   = 0x5C002000,
 	phy_82562_et = 0x033002A8,
 	phy_82562_em = 0x032002A8,
+	phy_82562_ek = 0x031002A8,
 	phy_82562_eh = 0x017002A8,
 	phy_unknown  = 0xFFFFFFFF,
 };
@@ -330,11 +330,16 @@ enum eeprom_op {
 };
 
 enum eeprom_offsets {
+	eeprom_cnfg_mdix  = 0x03,
 	eeprom_id         = 0x0A,
 	eeprom_config_asf = 0x0D,
 	eeprom_smbus_addr = 0x90,
 };
 
+enum eeprom_cnfg_mdix {
+	eeprom_mdix_enabled = 0x0080,
+};
+
 enum eeprom_id {
 	eeprom_id_wol = 0x0020,
 };
@@ -350,10 +355,12 @@ enum cb_status {
 };
 
 enum cb_command {
+	cb_nop    = 0x0000,
 	cb_iaaddr = 0x0001,
 	cb_config = 0x0002,
 	cb_multi  = 0x0003,
 	cb_tx     = 0x0004,
+	cb_ucode  = 0x0005,
 	cb_dump   = 0x0006,
 	cb_tx_sf  = 0x0008,
 	cb_cid    = 0x1f00,
@@ -428,12 +435,14 @@ struct multi {
 };
 
 /* Important: keep total struct u32-aligned */
+#define UCODE_SIZE			134
 struct cb {
 	u16 status;
 	u16 command;
 	u32 link;
 	union {
 		u8 iaaddr[ETH_ALEN];
+		u32 ucode[UCODE_SIZE];
 		struct config config;
 		struct multi multi;
 		struct {
@@ -548,6 +557,7 @@ struct nic {
 	u32 rx_fc_pause;
 	u32 rx_fc_unsupported;
 	u32 rx_tco_frames;
+	u32 rx_over_length_errors;
 
 	u8 rev_id;
 	u16 leds;
@@ -980,6 +990,27 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
 		c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]);
 }
 
+static void e100_load_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+{
+	int i;
+	static const u32 ucode[UCODE_SIZE] = {
+		/* NFS packets are misinterpreted as TCO packets and
+		 * incorrectly routed to the BMC over SMBus.  This
+		 * microcode patch checks the fragmented IP bit in the
+		 * NFS/UDP header to distinguish between NFS and TCO. */
+		0x0EF70E36, 0x1FFF1FFF, 0x1FFF1FFF, 0x1FFF1FFF, 0x1FFF1FFF,
+		0x1FFF1FFF, 0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000,
+		0x00906EFD, 0x00900EFD,	0x00E00EF8,
+	};
+
+	if(nic->mac == mac_82551_F || nic->mac == mac_82551_10) {
+		for(i = 0; i < UCODE_SIZE; i++)
+			cb->u.ucode[i] = cpu_to_le32(ucode[i]);
+		cb->command = cpu_to_le16(cb_ucode);
+	} else
+		cb->command = cpu_to_le16(cb_nop);
+}
+
 static void e100_setup_iaaddr(struct nic *nic, struct cb *cb,
 	struct sk_buff *skb)
 {
@@ -1045,7 +1076,9 @@ static int e100_phy_init(struct nic *nic)
 		mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong);
 	}
 
-	if(nic->mac >= mac_82550_D102)
+	if((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && 
+		(mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && 
+		(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled)))
 		/* enable/disable MDI/MDI-X auto-switching */
 		mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG,
 			nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH);
@@ -1069,6 +1102,8 @@ static int e100_hw_init(struct nic *nic)
 		return err;
 	if((err = e100_exec_cmd(nic, ruc_load_base, 0)))
 		return err;
+	if((err = e100_exec_cb(nic, NULL, e100_load_ucode)))
+		return err;
 	if((err = e100_exec_cb(nic, NULL, e100_configure)))
 		return err;
 	if((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr)))
@@ -1143,9 +1178,11 @@ static void e100_update_stats(struct nic *nic)
 		ns->tx_errors += le32_to_cpu(s->tx_max_collisions) +
 			le32_to_cpu(s->tx_lost_crs);
 		ns->rx_dropped += le32_to_cpu(s->rx_resource_errors);
-		ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors);
+		ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) +
+			nic->rx_over_length_errors;
 		ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors);
 		ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors);
+		ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors);
 		ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors);
 		ns->rx_errors += le32_to_cpu(s->rx_crc_errors) +
 			le32_to_cpu(s->rx_alignment_errors) +
@@ -1456,18 +1493,14 @@ static inline int e100_rx_indicate(struct nic *nic, struct rx *rx,
 		dev_kfree_skb_any(skb);
 	} else if(actual_size > nic->netdev->mtu + VLAN_ETH_HLEN) {
 		/* Don't indicate oversized frames */
-		nic->net_stats.rx_over_errors++;
+		nic->rx_over_length_errors++;
 		nic->net_stats.rx_dropped++;
 		dev_kfree_skb_any(skb);
 	} else {
 		nic->net_stats.rx_packets++;
 		nic->net_stats.rx_bytes += actual_size;
 		nic->netdev->last_rx = jiffies;
-#ifdef CONFIG_E100_NAPI
 		netif_receive_skb(skb);
-#else
-		netif_rx(skb);
-#endif
 		if(work_done)
 			(*work_done)++;
 	}
@@ -1562,20 +1595,12 @@ static irqreturn_t e100_intr(int irq, void *dev_id, struct pt_regs *regs)
 	if(stat_ack & stat_ack_rnr)
 		nic->ru_running = 0;
 
-#ifdef CONFIG_E100_NAPI
 	e100_disable_irq(nic);
 	netif_rx_schedule(netdev);
-#else
-	if(stat_ack & stat_ack_rx)
-		e100_rx_clean(nic, NULL, 0);
-	if(stat_ack & stat_ack_tx)
-		e100_tx_clean(nic);
-#endif
 
 	return IRQ_HANDLED;
 }
 
-#ifdef CONFIG_E100_NAPI
 static int e100_poll(struct net_device *netdev, int *budget)
 {
 	struct nic *nic = netdev_priv(netdev);
@@ -1598,7 +1623,6 @@ static int e100_poll(struct net_device *netdev, int *budget)
 
 	return 1;
 }
-#endif
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void e100_netpoll(struct net_device *netdev)
@@ -1641,7 +1665,7 @@ static int e100_change_mtu(struct net_device *netdev, int new_mtu)
 static int e100_asf(struct nic *nic)
 {
 	/* ASF can be enabled from eeprom */
-	return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1055) &&
+	return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) &&
 	   (nic->eeprom[eeprom_config_asf] & eeprom_asf) &&
 	   !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) &&
 	   ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE));
@@ -1961,18 +1985,27 @@ static int e100_diag_test_count(struct net_device *netdev)
 static void e100_diag_test(struct net_device *netdev,
 	struct ethtool_test *test, u64 *data)
 {
+	struct ethtool_cmd cmd;
 	struct nic *nic = netdev_priv(netdev);
-	int i;
+	int i, err;
 
 	memset(data, 0, E100_TEST_LEN * sizeof(u64));
 	data[0] = !mii_link_ok(&nic->mii);
 	data[1] = e100_eeprom_load(nic);
 	if(test->flags & ETH_TEST_FL_OFFLINE) {
+
+		/* save speed, duplex & autoneg settings */
+		err = mii_ethtool_gset(&nic->mii, &cmd);
+
 		if(netif_running(netdev))
 			e100_down(nic);
 		data[2] = e100_self_test(nic);
 		data[3] = e100_loopback_test(nic, lb_mac);
 		data[4] = e100_loopback_test(nic, lb_phy);
+
+		/* restore speed, duplex & autoneg settings */
+		err = mii_ethtool_sset(&nic->mii, &cmd);
+
 		if(netif_running(netdev))
 			e100_up(nic);
 	}
@@ -2135,10 +2168,8 @@ static int __devinit e100_probe(struct pci_dev *pdev,
 	SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops);
 	netdev->tx_timeout = e100_tx_timeout;
 	netdev->watchdog_timeo = E100_WATCHDOG_PERIOD;
-#ifdef CONFIG_E100_NAPI
 	netdev->poll = e100_poll;
 	netdev->weight = E100_NAPI_WEIGHT;
-#endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	netdev->poll_controller = e100_netpoll;
 #endif
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 067bb099e..108e33145 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -49,6 +49,7 @@
 #include <linux/delay.h>
 #include <linux/timer.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 #include <linux/interrupt.h>
 #include <linux/string.h>
 #include <linux/pagemap.h>
@@ -63,6 +64,7 @@
 #include <linux/udp.h>
 #include <net/pkt_sched.h>
 #include <linux/list.h>
+#include <linux/rtnetlink.h>
 #include <linux/reboot.h>
 #ifdef NETIF_F_TSO
 #include <net/checksum.h>
@@ -77,6 +79,8 @@
 #define BAR_1		1
 #define BAR_5		5
 
+#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
+	PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
 
 struct e1000_adapter;
 
@@ -98,11 +102,12 @@ struct e1000_adapter;
 
 #define E1000_MAX_INTR 10
 
-/* How many descriptors for TX and RX ? */
+/* TX/RX descriptor defines */
 #define E1000_DEFAULT_TXD                  256
 #define E1000_MAX_TXD                      256
 #define E1000_MIN_TXD                       80
 #define E1000_MAX_82544_TXD               4096
+
 #define E1000_DEFAULT_RXD                  256
 #define E1000_MAX_RXD                      256
 #define E1000_MIN_RXD                       80
@@ -123,14 +128,11 @@ struct e1000_adapter;
 #define E1000_TX_HEAD_ADDR_SHIFT 7
 #define E1000_PBA_TX_MASK 0xFFFF0000
 
-/* Flow Control High-Watermark: 5688 bytes below Rx FIFO size */
-#define E1000_FC_HIGH_DIFF 0x1638
-
-/* Flow Control Low-Watermark: 5696 bytes below Rx FIFO size */
-#define E1000_FC_LOW_DIFF 0x1640
+/* Flow Control Watermarks */
+#define E1000_FC_HIGH_DIFF 0x1638  /* High: 5688 bytes below Rx FIFO size */
+#define E1000_FC_LOW_DIFF 0x1640   /* Low:  5696 bytes below Rx FIFO size */
 
-/* Flow Control Pause Time: 858 usec */
-#define E1000_FC_PAUSE_TIME 0x0680
+#define E1000_FC_PAUSE_TIME 0x0680 /* 858 usec */
 
 /* How many Tx Descriptors do we need to call netif_wake_queue ? */
 #define E1000_TX_QUEUE_WAKE	16
@@ -153,9 +155,9 @@ struct e1000_adapter;
 struct e1000_buffer {
 	struct sk_buff *skb;
 	uint64_t dma;
-	unsigned long length;
 	unsigned long time_stamp;
-	unsigned int next_to_watch;
+	uint16_t length;
+	uint16_t next_to_watch;
 };
 
 struct e1000_desc_ring {
@@ -202,7 +204,7 @@ struct e1000_adapter {
 	spinlock_t stats_lock;
 	atomic_t irq_sem;
 	struct work_struct tx_timeout_task;
-    	uint8_t fc_autoneg;
+	uint8_t fc_autoneg;
 
 	struct timer_list blink_timer;
 	unsigned long led_status;
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index 9ca716eab..2e4544eca 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -88,9 +88,9 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
 	{ "rx_flow_control_xoff", E1000_STAT(stats.xoffrxc) },
 	{ "tx_flow_control_xon", E1000_STAT(stats.xontxc) },
 	{ "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) },
+	{ "rx_long_byte_count", E1000_STAT(stats.gorcl) },
 	{ "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
-        { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
-	{ "rx_long_byte_count", E1000_STAT(stats.gorcl) }
+	{ "rx_csum_offload_errors", E1000_STAT(hw_csum_err) }
 };
 #define E1000_STATS_LEN	\
 	sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats)
@@ -170,7 +170,8 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 		ecmd->duplex = -1;
 	}
 
-	ecmd->autoneg = (hw->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
+	ecmd->autoneg = ((hw->media_type == e1000_media_type_fiber) ||
+			 hw->autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE;
 	return 0;
 }
 
@@ -192,6 +193,7 @@ e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 
 	if(netif_running(adapter->netdev)) {
 		e1000_down(adapter);
+		e1000_reset(adapter);
 		e1000_up(adapter);
 	} else
 		e1000_reset(adapter);
@@ -199,12 +201,13 @@ e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 	return 0;
 }
 
-static void 
+static void
 e1000_get_pauseparam(struct net_device *netdev,
-                    struct ethtool_pauseparam *pause)
+                     struct ethtool_pauseparam *pause)
 {
 	struct e1000_adapter *adapter = netdev->priv;
 	struct e1000_hw *hw = &adapter->hw;
+
 	pause->autoneg = 
 		(adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
 	
@@ -218,9 +221,9 @@ e1000_get_pauseparam(struct net_device *netdev,
 	}
 }
 
-static int 
+static int
 e1000_set_pauseparam(struct net_device *netdev,
-                    struct ethtool_pauseparam *pause)
+                     struct ethtool_pauseparam *pause)
 {
 	struct e1000_adapter *adapter = netdev->priv;
 	struct e1000_hw *hw = &adapter->hw;
@@ -271,7 +274,7 @@ e1000_set_rx_csum(struct net_device *netdev, uint32_t data)
 		e1000_reset(adapter);
 	return 0;
 }
-
+	
 static uint32_t
 e1000_get_tx_csum(struct net_device *netdev)
 {
@@ -337,7 +340,7 @@ e1000_get_regs_len(struct net_device *netdev)
 
 static void
 e1000_get_regs(struct net_device *netdev,
-                    struct ethtool_regs *regs, void *p)
+	       struct ethtool_regs *regs, void *p)
 {
 	struct e1000_adapter *adapter = netdev->priv;
 	struct e1000_hw *hw = &adapter->hw;
@@ -418,6 +421,10 @@ e1000_get_regs(struct net_device *netdev,
 	e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
 	regs_buff[24] = (uint32_t)phy_data;  /* phy local receiver status */
 	regs_buff[25] = regs_buff[24];  /* phy remote receiver status */
+	if(hw->mac_type >= e1000_82540 &&
+	   hw->media_type == e1000_media_type_copper) {
+		regs_buff[26] = E1000_READ_REG(hw, MANC);
+	}
 }
 
 static int
@@ -438,7 +445,7 @@ e1000_get_eeprom(struct net_device *netdev,
 	int ret_val = 0;
 	uint16_t i;
 
-	if(eeprom->len == 0) 
+	if(eeprom->len == 0)
 		return -EINVAL;
 
 	eeprom->magic = hw->vendor_id | (hw->device_id << 16);
@@ -446,9 +453,9 @@ e1000_get_eeprom(struct net_device *netdev,
 	first_word = eeprom->offset >> 1;
 	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
 
-	eeprom_buff = kmalloc(sizeof(uint16_t) * 
+	eeprom_buff = kmalloc(sizeof(uint16_t) *
 			(last_word - first_word + 1), GFP_KERNEL);
-	if (!eeprom_buff)
+	if(!eeprom_buff)
 		return -ENOMEM;
 
 	if(hw->eeprom.type == e1000_eeprom_spi)
@@ -466,9 +473,8 @@ e1000_get_eeprom(struct net_device *netdev,
 	for (i = 0; i < last_word - first_word + 1; i++)
 		le16_to_cpus(&eeprom_buff[i]);
 
-
-	memcpy(bytes, (uint8_t *)eeprom_buff + (eeprom->offset%2), 
-				eeprom->len);
+	memcpy(bytes, (uint8_t *)eeprom_buff + (eeprom->offset & 1),
+			eeprom->len);
 	kfree(eeprom_buff);
 
 	return ret_val;
@@ -520,6 +526,7 @@ e1000_set_eeprom(struct net_device *netdev,
 		le16_to_cpus(&eeprom_buff[i]);
 
 	memcpy(ptr, bytes, eeprom->len);
+
 	for (i = 0; i < last_word - first_word + 1; i++)
 		eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]);
 
@@ -575,17 +582,16 @@ static int
 e1000_set_ringparam(struct net_device *netdev,
                     struct ethtool_ringparam *ring)
 {
-	int err;
 	struct e1000_adapter *adapter = netdev->priv;
 	e1000_mac_type mac_type = adapter->hw.mac_type;
 	struct e1000_desc_ring *txdr = &adapter->tx_ring;
 	struct e1000_desc_ring *rxdr = &adapter->rx_ring;
-	struct e1000_desc_ring tx_old, tx_new;
-	struct e1000_desc_ring rx_old, rx_new;
+	struct e1000_desc_ring tx_old, tx_new, rx_old, rx_new;
+	int err;
 
 	tx_old = adapter->tx_ring;
 	rx_old = adapter->rx_ring;
-	
+
 	if(netif_running(adapter->netdev))
 		e1000_down(adapter);
 
@@ -600,15 +606,15 @@ e1000_set_ringparam(struct net_device *netdev,
 	E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE); 
 
 	if(netif_running(adapter->netdev)) {
-		/* try to get new resources before deleting old */
+		/* Try to get new resources before deleting old */
 		if((err = e1000_setup_rx_resources(adapter)))
 			goto err_setup_rx;
 		if((err = e1000_setup_tx_resources(adapter)))
 			goto err_setup_tx;
 
 		/* save the new, restore the old in order to free it,
-		 * then restore the new back again */	
-	
+		 * then restore the new back again */
+
 		rx_new = adapter->rx_ring;
 		tx_new = adapter->tx_ring;
 		adapter->rx_ring = rx_old;
@@ -620,6 +626,7 @@ e1000_set_ringparam(struct net_device *netdev,
 		if((err = e1000_up(adapter)))
 			return err;
 	}
+
 	return 0;
 err_setup_tx:
 	e1000_free_rx_resources(adapter);
@@ -766,13 +773,15 @@ static int
 e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
 {
 	struct net_device *netdev = adapter->netdev;
-	uint32_t icr, mask, i=0;
+ 	uint32_t icr, mask, i=0, shared_int = TRUE;
+ 	uint32_t irq = adapter->pdev->irq;
 
 	*data = 0;
 
 	/* Hook up test interrupt handler just for this test */
-	if(request_irq(adapter->pdev->irq, &e1000_test_intr, SA_SHIRQ,
-	   netdev->name, netdev)) {
+ 	if(!request_irq(irq, &e1000_test_intr, 0, netdev->name, netdev)) {
+ 		shared_int = FALSE;
+ 	} else if(request_irq(irq, &e1000_test_intr, SA_SHIRQ, netdev->name, netdev)){
 		*data = 1;
 		return -1;
 	}
@@ -802,20 +811,22 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
 		/* Interrupt to test */
 		mask = 1 << i;
 
-		/* Disable the interrupt to be reported in
-		 * the cause register and then force the same
-		 * interrupt and see if one gets posted.  If
-		 * an interrupt was posted to the bus, the
-		 * test failed.
-		 */
-		adapter->test_icr = 0;
-		E1000_WRITE_REG(&adapter->hw, IMC, mask);
-		E1000_WRITE_REG(&adapter->hw, ICS, mask);
-		msec_delay(10);
-
-		if(adapter->test_icr & mask) {
-			*data = 3;
-			break;
+ 		if(!shared_int) {
+ 			/* Disable the interrupt to be reported in
+ 			 * the cause register and then force the same
+ 			 * interrupt and see if one gets posted.  If
+ 			 * an interrupt was posted to the bus, the
+ 			 * test failed.
+ 			 */
+ 			adapter->test_icr = 0;
+ 			E1000_WRITE_REG(&adapter->hw, IMC, mask);
+ 			E1000_WRITE_REG(&adapter->hw, ICS, mask);
+ 			msec_delay(10);
+ 
+ 			if(adapter->test_icr & mask) {
+ 				*data = 3;
+ 				break;
+ 			}
 		}
 
 		/* Enable the interrupt to be reported in
@@ -834,20 +845,22 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
 			break;
 		}
 
-		/* Disable the other interrupts to be reported in
-		 * the cause register and then force the other
-		 * interrupts and see if any get posted.  If
-		 * an interrupt was posted to the bus, the
-		 * test failed.
-		 */
-		adapter->test_icr = 0;
-		E1000_WRITE_REG(&adapter->hw, IMC, ~mask);
-		E1000_WRITE_REG(&adapter->hw, ICS, ~mask);
-		msec_delay(10);
+ 		if(!shared_int) {
+			/* Disable the other interrupts to be reported in
+			 * the cause register and then force the other
+			 * interrupts and see if any get posted.  If
+			 * an interrupt was posted to the bus, the
+			 * test failed.
+			 */
+			adapter->test_icr = 0;
+			E1000_WRITE_REG(&adapter->hw, IMC, ~mask);
+			E1000_WRITE_REG(&adapter->hw, ICS, ~mask);
+			msec_delay(10);
 
-		if(adapter->test_icr) {
-			*data = 5;
-			break;
+			if(adapter->test_icr) {
+				*data = 5;
+				break;
+			}
 		}
 	}
 
@@ -856,7 +869,7 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
 	msec_delay(10);
 
 	/* Unhook test interrupt handler */
-	free_irq(adapter->pdev->irq, netdev);
+	free_irq(irq, netdev);
 
 	return *data;
 }
@@ -1021,7 +1034,7 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
 
 	return 0;
 
-      err_nomem:
+err_nomem:
 	e1000_free_desc_rings(adapter);
 	return ret_val;
 }
@@ -1312,15 +1325,15 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
 
 	for(i = 0; i < 64; i++) {
 		e1000_create_lbtest_frame(txdr->buffer_info[i].skb, 1024);
-		pci_dma_sync_single(pdev, txdr->buffer_info[i].dma,
-				    txdr->buffer_info[i].length,
-				    PCI_DMA_TODEVICE);
+		pci_dma_sync_single_for_device(pdev, txdr->buffer_info[i].dma,
+					    txdr->buffer_info[i].length,
+					    PCI_DMA_TODEVICE);
 	}
 	E1000_WRITE_REG(&adapter->hw, TDT, i);
 
 	msec_delay(200);
 
-	pci_dma_sync_single(pdev, rxdr->buffer_info[0].dma,
+	pci_dma_sync_single_for_cpu(pdev, rxdr->buffer_info[0].dma,
 			    rxdr->buffer_info[0].length, PCI_DMA_FROMDEVICE);
 
 	return e1000_check_lbtest_frame(rxdr->buffer_info[0].skb, 1024);
@@ -1357,7 +1370,7 @@ e1000_diag_test_count(struct net_device *netdev)
 }
 
 static void
-e1000_diag_test(struct net_device *netdev, 
+e1000_diag_test(struct net_device *netdev,
 		   struct ethtool_test *eth_test, uint64_t *data)
 {
 	struct e1000_adapter *adapter = netdev->priv;
@@ -1368,7 +1381,7 @@ e1000_diag_test(struct net_device *netdev,
 
 		/* save speed, duplex, autoneg settings */
 		uint16_t autoneg_advertised = adapter->hw.autoneg_advertised;
-    		uint8_t forced_speed_duplex = adapter->hw.forced_speed_duplex;
+		uint8_t forced_speed_duplex = adapter->hw.forced_speed_duplex;
 		uint8_t autoneg = adapter->hw.autoneg;
 
 		/* Link test performed before hardware reset so autoneg doesn't
@@ -1396,10 +1409,11 @@ e1000_diag_test(struct net_device *netdev,
 		if(e1000_loopback_test(adapter, &data[3]))
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 
-		/* restore Autoneg/speed/duplex settings */
+		/* restore speed, duplex, autoneg settings */
 		adapter->hw.autoneg_advertised = autoneg_advertised;
-    		adapter->hw.forced_speed_duplex = forced_speed_duplex;
-    		adapter->hw.autoneg = autoneg;
+		adapter->hw.forced_speed_duplex = forced_speed_duplex;
+		adapter->hw.autoneg = autoneg;
+
 		e1000_reset(adapter);
 		if(if_running)
 			e1000_up(adapter);
@@ -1427,6 +1441,7 @@ e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 	case E1000_DEV_ID_82543GC_FIBER:
 	case E1000_DEV_ID_82543GC_COPPER:
 	case E1000_DEV_ID_82544EI_FIBER:
+	case E1000_DEV_ID_82546EB_QUAD_COPPER:
 		wol->supported = 0;
 		wol->wolopts   = 0;
 		return;
@@ -1469,6 +1484,7 @@ e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 	case E1000_DEV_ID_82543GC_FIBER:
 	case E1000_DEV_ID_82543GC_COPPER:
 	case E1000_DEV_ID_82544EI_FIBER:
+	case E1000_DEV_ID_82546EB_QUAD_COPPER:
 		return wol->wolopts ? -EOPNOTSUPP : 0;
 
 	case E1000_DEV_ID_82546EB_FIBER:
@@ -1571,8 +1587,8 @@ e1000_get_ethtool_stats(struct net_device *netdev,
 	e1000_update_stats(adapter);
 	for(i = 0; i < E1000_STATS_LEN; i++) {
 		char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset;	
-		data[i] = (e1000_gstrings_stats[i].sizeof_stat == sizeof(uint64_t)) 
-			? *(uint64_t *)p : *(uint32_t *)p;
+		data[i] = (e1000_gstrings_stats[i].sizeof_stat == 
+			sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p;
 	}
 }
 
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 41c05e5c3..7c8cd3990 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -251,6 +251,7 @@ e1000_set_mac_type(struct e1000_hw *hw)
         break;
     case E1000_DEV_ID_82541ER:
     case E1000_DEV_ID_82541GI:
+    case E1000_DEV_ID_82541GI_LF:
     case E1000_DEV_ID_82541GI_MOBILE:
         hw->mac_type = e1000_82541_rev_2;
         break;
@@ -920,7 +921,8 @@ e1000_setup_copper_link(struct e1000_hw *hw)
     if(ret_val)
         return ret_val;
 
-    if(hw->mac_type == e1000_82545_rev_3) {
+    if((hw->mac_type == e1000_82545_rev_3) ||
+       (hw->mac_type == e1000_82546_rev_3)) {
         ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
         phy_data |= 0x00000008;
         ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
@@ -3057,16 +3059,6 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
         }
         break;
     default:
-        eeprom->type = e1000_eeprom_spi;
-        eeprom->opcode_bits = 8;
-        eeprom->delay_usec = 1;
-        if (eecd & E1000_EECD_ADDR_BITS) {
-            eeprom->page_size = 32;
-            eeprom->address_bits = 16;
-        } else {
-            eeprom->page_size = 8;
-            eeprom->address_bits = 8;
-        }
         break;
     }
 
@@ -3453,7 +3445,6 @@ e1000_read_eeprom(struct e1000_hw *hw,
     uint32_t i = 0;
 
     DEBUGFUNC("e1000_read_eeprom");
-
     /* A check for invalid values:  offset too large, too many words, and not
      * enough words.
      */
@@ -5224,3 +5215,4 @@ e1000_enable_mng_pass_thru(struct e1000_hw *hw)
     }
     return FALSE;
 }
+
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index c9ee93a0d..9fb134ded 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -357,11 +357,11 @@ int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active);
 #define E1000_DEV_ID_82547GI             0x1075
 #define E1000_DEV_ID_82541GI             0x1076
 #define E1000_DEV_ID_82541GI_MOBILE      0x1077
+#define E1000_DEV_ID_82541GI_LF          0x107C
 #define E1000_DEV_ID_82546GB_COPPER      0x1079
 #define E1000_DEV_ID_82546GB_FIBER       0x107A
 #define E1000_DEV_ID_82546GB_SERDES      0x107B
 #define E1000_DEV_ID_82547EI             0x1019
-
 #define NODE_ADDRESS_SIZE 6
 #define ETH_LENGTH_OF_ADDRESS 6
 
@@ -1043,7 +1043,6 @@ struct e1000_hw {
 
 #define E1000_EEPROM_SWDPIN0   0x0001   /* SWDPIN 0 EEPROM Value */
 #define E1000_EEPROM_LED_LOGIC 0x0020   /* Led Logic Word */
-
 /* Register Bit Masks */
 /* Device Control */
 #define E1000_CTRL_FD       0x00000001  /* Full duplex.0=half; 1=full */
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 4b9b77567..cac241e5a 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -27,73 +27,69 @@
 *******************************************************************************/
 
 #include "e1000.h"
-#include <linux/rtnetlink.h>
 
 /* Change Log
+ * 5.3.12	6/7/04
+ * - kcompat NETIF_MSG for older kernels (2.4.9) <sean.p.mcdermott@intel.com>
+ * - if_mii support and associated kcompat for older kernels
+ * - More errlogging support from Jon Mason <jonmason@us.ibm.com>
+ * - Fix TSO issues on PPC64 machines -- Jon Mason <jonmason@us.ibm.com>
  *
- * 5.2.51   5/14/04
- *   o set default configuration to 'NAPI disabled'. NAPI enabled driver
- *     causes kernel panic when the interface is shutdown while data is being
- *     transferred.
- * 5.2.47   5/04/04
- *   o fixed ethtool -t implementation
- * 5.2.45   4/29/04
- *   o fixed ethtool -e implementation
- *   o Support for ethtool ops [Stephen Hemminger (shemminger@osdl.org)]
- * 5.2.42   4/26/04
- *   o Added support for the DPRINTK macro for enhanced error logging.  Some
- *     parts of the patch were supplied by Jon Mason.
- *   o Move the register_netdevice() donw in the probe routine due to a 
- *     loading/unloading test issue.
- *   o Added a long RX byte count the the extra ethtool data members for BER
- *     testing purposes.
- * 5.2.39	3/12/04
+ * 5.3.11	6/4/04
+ * - ethtool register dump reads MANC register conditionally.
+ *
+ * 5.3.10	6/1/04
  */
 
 char e1000_driver_name[] = "e1000";
 char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
-char e1000_driver_version[] = "5.2.52-k4";
+#ifndef CONFIG_E1000_NAPI
+#define DRIVERNAPI
+#else
+#define DRIVERNAPI "-NAPI"
+#endif
+char e1000_driver_version[] = "5.3.19-k2"DRIVERNAPI;
 char e1000_copyright[] = "Copyright (c) 1999-2004 Intel Corporation.";
 
 /* e1000_pci_tbl - PCI Device ID Table
  *
- * Wildcard entries (PCI_ANY_ID) should come last
  * Last entry must be all 0s
  *
- * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
- *   Class, Class Mask, private data (not used) }
+ * Macro expands to...
+ *   {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
  */
 static struct pci_device_id e1000_pci_tbl[] = {
-	{0x8086, 0x1000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x100C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x100D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x100E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x100F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1015, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1017, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1018, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x101D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1026, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1027, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1075, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1076, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1077, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1078, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x1079, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x107A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x8086, 0x107B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	INTEL_E1000_ETHERNET_DEVICE(0x1000),
+	INTEL_E1000_ETHERNET_DEVICE(0x1001),
+	INTEL_E1000_ETHERNET_DEVICE(0x1004),
+	INTEL_E1000_ETHERNET_DEVICE(0x1008),
+	INTEL_E1000_ETHERNET_DEVICE(0x1009),
+	INTEL_E1000_ETHERNET_DEVICE(0x100C),
+	INTEL_E1000_ETHERNET_DEVICE(0x100D),
+	INTEL_E1000_ETHERNET_DEVICE(0x100E),
+	INTEL_E1000_ETHERNET_DEVICE(0x100F),
+	INTEL_E1000_ETHERNET_DEVICE(0x1010),
+	INTEL_E1000_ETHERNET_DEVICE(0x1011),
+	INTEL_E1000_ETHERNET_DEVICE(0x1012),
+	INTEL_E1000_ETHERNET_DEVICE(0x1013),
+	INTEL_E1000_ETHERNET_DEVICE(0x1015),
+	INTEL_E1000_ETHERNET_DEVICE(0x1016),
+	INTEL_E1000_ETHERNET_DEVICE(0x1017),
+	INTEL_E1000_ETHERNET_DEVICE(0x1018),
+	INTEL_E1000_ETHERNET_DEVICE(0x1019),
+	INTEL_E1000_ETHERNET_DEVICE(0x101D),
+	INTEL_E1000_ETHERNET_DEVICE(0x101E),
+	INTEL_E1000_ETHERNET_DEVICE(0x1026),
+	INTEL_E1000_ETHERNET_DEVICE(0x1027),
+	INTEL_E1000_ETHERNET_DEVICE(0x1028),
+	INTEL_E1000_ETHERNET_DEVICE(0x1075),
+	INTEL_E1000_ETHERNET_DEVICE(0x1076),
+	INTEL_E1000_ETHERNET_DEVICE(0x1077),
+	INTEL_E1000_ETHERNET_DEVICE(0x1078),
+	INTEL_E1000_ETHERNET_DEVICE(0x1079),
+	INTEL_E1000_ETHERNET_DEVICE(0x107A),
+	INTEL_E1000_ETHERNET_DEVICE(0x107B),
+	INTEL_E1000_ETHERNET_DEVICE(0x107C),
 	/* required last entry */
 	{0,}
 };
@@ -132,8 +128,8 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
 static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
 static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
 static int e1000_set_mac(struct net_device *netdev, void *p);
-static inline void e1000_irq_disable(struct e1000_adapter *adapter);
-static inline void e1000_irq_enable(struct e1000_adapter *adapter);
+static void e1000_irq_disable(struct e1000_adapter *adapter);
+static void e1000_irq_enable(struct e1000_adapter *adapter);
 static irqreturn_t e1000_intr(int irq, void *data, struct pt_regs *regs);
 static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter);
 #ifdef CONFIG_E1000_NAPI
@@ -150,9 +146,9 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
 void set_ethtool_ops(struct net_device *netdev);
 static void e1000_enter_82542_rst(struct e1000_adapter *adapter);
 static void e1000_leave_82542_rst(struct e1000_adapter *adapter);
-static inline void e1000_rx_checksum(struct e1000_adapter *adapter,
-                                     struct e1000_rx_desc *rx_desc,
-                                     struct sk_buff *skb);
+static void e1000_rx_checksum(struct e1000_adapter *adapter,
+				struct e1000_rx_desc *rx_desc,
+				struct sk_buff *skb);
 static void e1000_tx_timeout(struct net_device *dev);
 static void e1000_tx_timeout_task(struct net_device *dev);
 static void e1000_smartspeed(struct e1000_adapter *adapter);
@@ -172,7 +168,7 @@ static int e1000_resume(struct pci_dev *pdev);
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
 /* for netdump / net console */
-static void e1000_netpoll (struct net_device *dev);
+static void e1000_netpoll (struct net_device *netdev);
 #endif
 
 struct notifier_block e1000_notifier_reboot = {
@@ -185,7 +181,6 @@ struct notifier_block e1000_notifier_reboot = {
 
 extern void e1000_check_options(struct e1000_adapter *adapter);
 
-
 static struct pci_driver e1000_driver = {
 	.name     = e1000_driver_name,
 	.id_table = e1000_pci_tbl,
@@ -202,7 +197,7 @@ MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
 MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver");
 MODULE_LICENSE("GPL");
 
-static int debug = 3;
+static int debug = NETIF_MSG_DRV | NETIF_MSG_PROBE;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
 
@@ -256,6 +251,14 @@ e1000_up(struct e1000_adapter *adapter)
 
 	/* hardware has been reset, we need to reload some things */
 
+	/* Reset the PHY if it was previously powered down */
+	if(adapter->hw.media_type == e1000_media_type_copper) {
+		uint16_t mii_reg;
+		e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
+		if(mii_reg & MII_CR_POWER_DOWN)
+			e1000_phy_reset(&adapter->hw);
+	}
+
 	e1000_set_multi(netdev);
 
 	e1000_restore_vlan(adapter);
@@ -294,6 +297,15 @@ e1000_down(struct e1000_adapter *adapter)
 	e1000_reset(adapter);
 	e1000_clean_tx_ring(adapter);
 	e1000_clean_rx_ring(adapter);
+
+	/* If WoL is not enabled
+	 * Power down the PHY so no link is implied when interface is down */
+	if(!adapter->wol && adapter->hw.media_type == e1000_media_type_copper) {
+		uint16_t mii_reg;
+		e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
+		mii_reg |= MII_CR_POWER_DOWN;
+		e1000_write_phy_reg(&adapter->hw, PHY_CTRL, mii_reg);
+	}
 }
 
 void
@@ -323,10 +335,10 @@ e1000_reset(struct e1000_adapter *adapter)
 	E1000_WRITE_REG(&adapter->hw, PBA, pba);
 
 	/* flow control settings */
-	adapter->hw.fc_high_water =
-		(pba << E1000_PBA_BYTES_SHIFT) - E1000_FC_HIGH_DIFF;
-	adapter->hw.fc_low_water =
-		(pba << E1000_PBA_BYTES_SHIFT) - E1000_FC_LOW_DIFF;
+	adapter->hw.fc_high_water = (pba << E1000_PBA_BYTES_SHIFT) -
+				    E1000_FC_HIGH_DIFF;
+	adapter->hw.fc_low_water = (pba << E1000_PBA_BYTES_SHIFT) -
+				   E1000_FC_LOW_DIFF;
 	adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME;
 	adapter->hw.fc_send_xon = 1;
 	adapter->hw.fc = adapter->hw.original_fc;
@@ -334,7 +346,8 @@ e1000_reset(struct e1000_adapter *adapter)
 	e1000_reset_hw(&adapter->hw);
 	if(adapter->hw.mac_type >= e1000_82544)
 		E1000_WRITE_REG(&adapter->hw, WUC, 0);
-	e1000_init_hw(&adapter->hw);
+	if(e1000_init_hw(&adapter->hw))
+		DPRINTK(PROBE, ERR, "Hardware Error\n");
 
 	/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
 	E1000_WRITE_REG(&adapter->hw, VET, ETHERNET_IEEE_VLAN_TYPE);
@@ -410,8 +423,8 @@ e1000_probe(struct pci_dev *pdev,
 	adapter->msg_enable = (1 << debug) - 1;
 
 	rtnl_lock();
-	/* we need to set the name early since the DPRINTK macro needs it set */
-	if (dev_alloc_name(netdev, netdev->name) < 0) 
+	/* we need to set the name early for the DPRINTK macro */
+	if(dev_alloc_name(netdev, netdev->name) < 0)
 		goto err_free_unlock;
 
 	mmio_start = pci_resource_start(pdev, BAR_0);
@@ -476,7 +489,6 @@ e1000_probe(struct pci_dev *pdev,
 	}
 
 #ifdef NETIF_F_TSO
-#ifdef BROKEN_ON_NON_IA_ARCHS
 	/* Disbaled for now until root-cause is found for
 	 * hangs reported against non-IA archs.  TSO can be
 	 * enabled using ethtool -K eth<x> tso on */
@@ -484,11 +496,12 @@ e1000_probe(struct pci_dev *pdev,
 	   (adapter->hw.mac_type != e1000_82547))
 		netdev->features |= NETIF_F_TSO;
 #endif
-#endif
-
 	if(pci_using_dac)
 		netdev->features |= NETIF_F_HIGHDMA;
 
+ 	/* hard_start_xmit is safe against parallel locking */
+ 	netdev->features |= NETIF_F_LLTX; 
+ 
 	adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw);
 
 	/* before reading the EEPROM, reset the controller to 
@@ -506,10 +519,12 @@ e1000_probe(struct pci_dev *pdev,
 
 	/* copy the MAC address out of the EEPROM */
 
-	e1000_read_mac_addr(&adapter->hw);
+	if (e1000_read_mac_addr(&adapter->hw))
+		DPRINTK(PROBE, ERR, "EEPROM Read Error\n");
 	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
 
 	if(!is_valid_ether_addr(netdev->dev_addr)) {
+		DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
 		err = -EIO;
 		goto err_eeprom;
 	}
@@ -569,10 +584,9 @@ e1000_probe(struct pci_dev *pdev,
 		adapter->wol |= E1000_WUFC_MAG;
 
 	/* reset the hardware with the new settings */
-
 	e1000_reset(adapter);
 
-	/* since we are holding the rtnl lock already, call the no-lock version */
+	/* We're already holding the rtnl lock; call the no-lock version */
 	if((err = register_netdevice(netdev)))
 		goto err_register;
 
@@ -663,7 +677,7 @@ e1000_sw_init(struct e1000_adapter *adapter)
 
 	/* identify the MAC */
 
-	if (e1000_set_mac_type(hw)) {
+	if(e1000_set_mac_type(hw)) {
 		DPRINTK(PROBE, ERR, "Unknown MAC Type\n");
 		return -EIO;
 	}
@@ -672,19 +686,19 @@ e1000_sw_init(struct e1000_adapter *adapter)
 
 	e1000_init_eeprom_params(hw);
 
-	if((hw->mac_type == e1000_82541) ||
-	   (hw->mac_type == e1000_82547) ||
-	   (hw->mac_type == e1000_82541_rev_2) ||
-	   (hw->mac_type == e1000_82547_rev_2))
+	switch(hw->mac_type) {
+	default:
+		break;
+	case e1000_82541:
+	case e1000_82547:
+	case e1000_82541_rev_2:
+	case e1000_82547_rev_2:
 		hw->phy_init_script = 1;
+		break;
+	}
 
 	e1000_set_media_type(hw);
 
-	if(hw->mac_type < e1000_82543)
-		hw->report_tx_early = 0;
-	else
-		hw->report_tx_early = 1;
-
 	hw->wait_autoneg_complete = FALSE;
 	hw->tbi_compatibility_en = TRUE;
 	hw->adaptive_ifs = TRUE;
@@ -736,7 +750,7 @@ e1000_open(struct net_device *netdev)
 	if((err = e1000_up(adapter)))
 		goto err_up;
 
-	return 0;
+	return E1000_SUCCESS;
 
 err_up:
 	e1000_free_rx_resources(adapter);
@@ -788,8 +802,10 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter)
 	int size;
 
 	size = sizeof(struct e1000_buffer) * txdr->count;
-	txdr->buffer_info = kmalloc(size, GFP_KERNEL);
+	txdr->buffer_info = vmalloc(size);
 	if(!txdr->buffer_info) {
+		DPRINTK(PROBE, ERR, 
+		"Unble to Allocate Memory for the Transmit descriptor ring\n");
 		return -ENOMEM;
 	}
 	memset(txdr->buffer_info, 0, size);
@@ -801,7 +817,9 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter)
 
 	txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
 	if(!txdr->desc) {
-		kfree(txdr->buffer_info);
+		DPRINTK(PROBE, ERR, 
+		"Unble to Allocate Memory for the Transmit descriptor ring\n");
+		vfree(txdr->buffer_info);
 		return -ENOMEM;
 	}
 	memset(txdr->desc, 0, txdr->size);
@@ -878,10 +896,10 @@ e1000_configure_tx(struct e1000_adapter *adapter)
 	adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP |
 		E1000_TXD_CMD_IFCS;
 
-	if(adapter->hw.report_tx_early == 1)
-		adapter->txd_cmd |= E1000_TXD_CMD_RS;
-	else
+	if(adapter->hw.mac_type < e1000_82543)
 		adapter->txd_cmd |= E1000_TXD_CMD_RPS;
+	else
+		adapter->txd_cmd |= E1000_TXD_CMD_RS;
 
 	/* Cache if we're 82544 running in PCI-X because we'll
 	 * need this to apply a workaround later in the send path. */
@@ -905,8 +923,10 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter)
 	int size;
 
 	size = sizeof(struct e1000_buffer) * rxdr->count;
-	rxdr->buffer_info = kmalloc(size, GFP_KERNEL);
+	rxdr->buffer_info = vmalloc(size);
 	if(!rxdr->buffer_info) {
+		DPRINTK(PROBE, ERR, 
+		"Unble to Allocate Memory for the Recieve descriptor ring\n");
 		return -ENOMEM;
 	}
 	memset(rxdr->buffer_info, 0, size);
@@ -919,7 +939,9 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter)
 	rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
 
 	if(!rxdr->desc) {
-		kfree(rxdr->buffer_info);
+		DPRINTK(PROBE, ERR, 
+		"Unble to Allocate Memory for the Recieve descriptor ring\n");
+		vfree(rxdr->buffer_info);
 		return -ENOMEM;
 	}
 	memset(rxdr->desc, 0, rxdr->size);
@@ -953,7 +975,9 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
 	else
 		rctl &= ~E1000_RCTL_SBP;
 
+	/* Setup buffer sizes */
 	rctl &= ~(E1000_RCTL_SZ_4096);
+	rctl |= (E1000_RCTL_BSEX | E1000_RCTL_LPE);
 	switch (adapter->rx_buffer_len) {
 	case E1000_RXBUFFER_2048:
 	default:
@@ -961,13 +985,13 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
 		rctl &= ~(E1000_RCTL_BSEX | E1000_RCTL_LPE);
 		break;
 	case E1000_RXBUFFER_4096:
-		rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX | E1000_RCTL_LPE;
+		rctl |= E1000_RCTL_SZ_4096;
 		break;
 	case E1000_RXBUFFER_8192:
-		rctl |= E1000_RCTL_SZ_8192 | E1000_RCTL_BSEX | E1000_RCTL_LPE;
+		rctl |= E1000_RCTL_SZ_8192;
 		break;
 	case E1000_RXBUFFER_16384:
-		rctl |= E1000_RCTL_SZ_16384 | E1000_RCTL_BSEX | E1000_RCTL_LPE;
+		rctl |= E1000_RCTL_SZ_16384;
 		break;
 	}
 
@@ -989,13 +1013,11 @@ e1000_configure_rx(struct e1000_adapter *adapter)
 	uint32_t rctl;
 	uint32_t rxcsum;
 
-	/* make sure receives are disabled while setting up the descriptors */
-
+	/* disable receives while setting up the descriptors */
 	rctl = E1000_READ_REG(&adapter->hw, RCTL);
 	E1000_WRITE_REG(&adapter->hw, RCTL, rctl & ~E1000_RCTL_EN);
 
 	/* set the Receive Delay Timer Register */
-
 	E1000_WRITE_REG(&adapter->hw, RDTR, adapter->rx_int_delay);
 
 	if(adapter->hw.mac_type >= e1000_82540) {
@@ -1006,7 +1028,6 @@ e1000_configure_rx(struct e1000_adapter *adapter)
 	}
 
 	/* Setup the Base and Length of the Rx Descriptor Ring */
-
 	E1000_WRITE_REG(&adapter->hw, RDBAL, (rdba & 0x00000000ffffffffULL));
 	E1000_WRITE_REG(&adapter->hw, RDBAH, (rdba >> 32));
 
@@ -1025,7 +1046,6 @@ e1000_configure_rx(struct e1000_adapter *adapter)
 	}
 
 	/* Enable Receives */
-
 	E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
 }
 
@@ -1043,7 +1063,7 @@ e1000_free_tx_resources(struct e1000_adapter *adapter)
 
 	e1000_clean_tx_ring(adapter);
 
-	kfree(adapter->tx_ring.buffer_info);
+	vfree(adapter->tx_ring.buffer_info);
 	adapter->tx_ring.buffer_info = NULL;
 
 	pci_free_consistent(pdev, adapter->tx_ring.size,
@@ -1073,9 +1093,9 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter)
 		if(buffer_info->skb) {
 
 			pci_unmap_page(pdev,
-			               buffer_info->dma,
-			               buffer_info->length,
-			               PCI_DMA_TODEVICE);
+				       buffer_info->dma,
+				       buffer_info->length,
+				       PCI_DMA_TODEVICE);
 
 			dev_kfree_skb(buffer_info->skb);
 
@@ -1112,7 +1132,7 @@ e1000_free_rx_resources(struct e1000_adapter *adapter)
 
 	e1000_clean_rx_ring(adapter);
 
-	kfree(rx_ring->buffer_info);
+	vfree(rx_ring->buffer_info);
 	rx_ring->buffer_info = NULL;
 
 	pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma);
@@ -1141,12 +1161,11 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter)
 		if(buffer_info->skb) {
 
 			pci_unmap_single(pdev,
-			                 buffer_info->dma,
-			                 buffer_info->length,
-			                 PCI_DMA_FROMDEVICE);
+					 buffer_info->dma,
+					 buffer_info->length,
+					 PCI_DMA_FROMDEVICE);
 
 			dev_kfree_skb(buffer_info->skb);
-
 			buffer_info->skb = NULL;
 		}
 	}
@@ -1259,9 +1278,12 @@ e1000_set_multi(struct net_device *netdev)
 	uint32_t rctl;
 	uint32_t hash_value;
 	int i;
+	unsigned long flags;
 
 	/* Check for Promiscuous and All Multicast modes */
 
+	spin_lock_irqsave(&adapter->tx_lock, flags);
+
 	rctl = E1000_READ_REG(hw, RCTL);
 
 	if(netdev->flags & IFF_PROMISC) {
@@ -1310,9 +1332,12 @@ e1000_set_multi(struct net_device *netdev)
 
 	if(hw->mac_type == e1000_82542_rev2_0)
 		e1000_leave_82542_rst(adapter);
+
+	spin_unlock_irqrestore(&adapter->tx_lock, flags);
 }
 
-/* need to wait a few seconds after link up to get diagnostic information from the phy */
+/* Need to wait a few seconds after link up to get diagnostic information from
+ * the phy */
 
 static void
 e1000_update_phy_info(unsigned long data)
@@ -1420,7 +1445,7 @@ e1000_watchdog(unsigned long data)
 	adapter->tpt_old = adapter->stats.tpt;
 	adapter->hw.collision_delta = adapter->stats.colc - adapter->colc_old;
 	adapter->colc_old = adapter->stats.colc;
-	
+
 	adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old;
 	adapter->gorcl_old = adapter->stats.gorcl;
 	adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old;
@@ -1477,8 +1502,9 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
 #ifdef NETIF_F_TSO
 	struct e1000_context_desc *context_desc;
 	unsigned int i;
-	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
+	uint32_t cmd_length = 0;
 	uint16_t ipcse, tucse, mss;
+	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
 
 	if(skb_shinfo(skb)->tso_size) {
 		hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
@@ -1497,6 +1523,10 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
 		tucso = (void *)&(skb->h.th->check) - (void *)skb->data;
 		tucse = 0;
 
+		cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
+			       E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP |
+			       (skb->len - (hdr_len)));
+
 		i = adapter->tx_ring.next_to_use;
 		context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i);
 
@@ -1508,10 +1538,7 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
 		context_desc->upper_setup.tcp_fields.tucse = cpu_to_le16(tucse);
 		context_desc->tcp_seg_setup.fields.mss     = cpu_to_le16(mss);
 		context_desc->tcp_seg_setup.fields.hdr_len = hdr_len;
-		context_desc->cmd_and_length = cpu_to_le32(
-			E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
-			E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP |
-			(skb->len - (hdr_len)));
+		context_desc->cmd_and_length = cpu_to_le32(cmd_length);
 
 		if(++i == adapter->tx_ring.count) i = 0;
 		adapter->tx_ring.next_to_use = i;
@@ -1528,22 +1555,21 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb)
 {
 	struct e1000_context_desc *context_desc;
 	unsigned int i;
-	uint8_t css, cso;
+	uint8_t css;
 
-	if(skb->ip_summed == CHECKSUM_HW) {
+	if(likely(skb->ip_summed == CHECKSUM_HW)) {
 		css = skb->h.raw - skb->data;
-		cso = (skb->h.raw + skb->csum) - skb->data;
 
 		i = adapter->tx_ring.next_to_use;
 		context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i);
 
 		context_desc->upper_setup.tcp_fields.tucss = css;
-		context_desc->upper_setup.tcp_fields.tucso = cso;
+		context_desc->upper_setup.tcp_fields.tucso = css + skb->csum;
 		context_desc->upper_setup.tcp_fields.tucse = 0;
 		context_desc->tcp_seg_setup.data = 0;
 		context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT);
 
-		if(++i == adapter->tx_ring.count) i = 0;
+		if(unlikely(++i == adapter->tx_ring.count)) i = 0;
 		adapter->tx_ring.next_to_use = i;
 
 		return TRUE;
@@ -1567,7 +1593,6 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb,
 	unsigned int f;
 	len -= skb->data_len;
 
-
 	i = tx_ring->next_to_use;
 
 	while(len) {
@@ -1576,14 +1601,14 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb,
 #ifdef NETIF_F_TSO
 		/* Workaround for premature desc write-backs
 		 * in TSO mode.  Append 4-byte sentinel desc */
-		if(mss && !nr_frags && size == len && size > 8)
+		if(unlikely(mss && !nr_frags && size == len && size > 8))
 			size -= 4;
 #endif
 		/* Workaround for potential 82544 hang in PCI-X.  Avoid
 		 * terminating buffers within evenly-aligned dwords. */
-		if(adapter->pcix_82544 &&
+		if(unlikely(adapter->pcix_82544 &&
 		   !((unsigned long)(skb->data + offset + size - 1) & 4) &&
-		   size > 4)
+		   size > 4))
 			size -= 4;
 
 		buffer_info->length = size;
@@ -1597,7 +1622,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb,
 		len -= size;
 		offset += size;
 		count++;
-		if(++i == tx_ring->count) i = 0;
+		if(unlikely(++i == tx_ring->count)) i = 0;
 	}
 
 	for(f = 0; f < nr_frags; f++) {
@@ -1613,15 +1638,15 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb,
 #ifdef NETIF_F_TSO
 			/* Workaround for premature desc write-backs
 			 * in TSO mode.  Append 4-byte sentinel desc */
-			if(mss && f == (nr_frags-1) && size == len && size > 8)
+			if(unlikely(mss && f == (nr_frags-1) && size == len && size > 8))
 				size -= 4;
 #endif
 			/* Workaround for potential 82544 hang in PCI-X.
 			 * Avoid terminating buffers within evenly-aligned
 			 * dwords. */
-			if(adapter->pcix_82544 &&
+			if(unlikely(adapter->pcix_82544 &&
 			   !((unsigned long)(frag->page+offset+size-1) & 4) &&
-			   size > 4)
+			   size > 4))
 				size -= 4;
 
 			buffer_info->length = size;
@@ -1636,13 +1661,14 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb,
 			len -= size;
 			offset += size;
 			count++;
-			if(++i == tx_ring->count) i = 0;
+			if(unlikely(++i == tx_ring->count)) i = 0;
 		}
 	}
+
 	i = (i == 0) ? tx_ring->count - 1 : i - 1;
 	tx_ring->buffer_info[i].skb = skb;
 	tx_ring->buffer_info[first].next_to_watch = i;
-	
+
 	return count;
 }
 
@@ -1655,18 +1681,18 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags)
 	uint32_t txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS;
 	unsigned int i;
 
-	if(tx_flags & E1000_TX_FLAGS_TSO) {
+	if(likely(tx_flags & E1000_TX_FLAGS_TSO)) {
 		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
 		             E1000_TXD_CMD_TSE;
 		txd_upper |= (E1000_TXD_POPTS_IXSM | E1000_TXD_POPTS_TXSM) << 8;
 	}
 
-	if(tx_flags & E1000_TX_FLAGS_CSUM) {
+	if(likely(tx_flags & E1000_TX_FLAGS_CSUM)) {
 		txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D;
 		txd_upper |= E1000_TXD_POPTS_TXSM << 8;
 	}
 
-	if(tx_flags & E1000_TX_FLAGS_VLAN) {
+	if(unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) {
 		txd_lower |= E1000_TXD_CMD_VLE;
 		txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK);
 	}
@@ -1680,7 +1706,7 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags)
 		tx_desc->lower.data =
 			cpu_to_le32(txd_lower | buffer_info->length);
 		tx_desc->upper.data = cpu_to_le32(txd_upper);
-		if(++i == tx_ring->count) i = 0;
+		if(unlikely(++i == tx_ring->count)) i = 0;
 	}
 
 	tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
@@ -1733,7 +1759,7 @@ no_fifo_stall_required:
 	return 0;
 }
 
-#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 ) 
+#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 )
 static int
 e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 {
@@ -1741,22 +1767,23 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 	unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD;
 	unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
 	unsigned int tx_flags = 0;
-	unsigned long flags;
 	unsigned int len = skb->len;
-	int count = 0;
-	unsigned int mss = 0;
+	unsigned long flags;
 	unsigned int nr_frags = 0;
+	unsigned int mss = 0;
+	int count = 0;
 	unsigned int f;
 	nr_frags = skb_shinfo(skb)->nr_frags;
 	len -= skb->data_len;
-	if(skb->len <= 0) {
+
+	if(unlikely(skb->len <= 0)) {
 		dev_kfree_skb_any(skb);
-		return 0;
+		return NETDEV_TX_OK;
 	}
 
 #ifdef NETIF_F_TSO
 	mss = skb_shinfo(skb)->tso_size;
-	/* The controller does a simple calculation to 
+	/* The controller does a simple calculation to
 	 * make sure there is enough room in the FIFO before
 	 * initiating the DMA for each buffer.  The calc is:
 	 * 4 = ceil(buffer len/mss).  To make sure we don't
@@ -1766,62 +1793,70 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 		max_per_txd = min(mss << 2, max_per_txd);
 		max_txd_pwr = fls(max_per_txd) - 1;
 	}
+
 	if((mss) || (skb->ip_summed == CHECKSUM_HW))
 		count++;
-	count++;	/*for sentinel desc*/
+	count++;	/* for sentinel desc */
 #else
 	if(skb->ip_summed == CHECKSUM_HW)
 		count++;
 #endif
-
 	count += TXD_USE_COUNT(len, max_txd_pwr);
+
 	if(adapter->pcix_82544)
 		count++;
 
 	nr_frags = skb_shinfo(skb)->nr_frags;
 	for(f = 0; f < nr_frags; f++)
 		count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size,
-		                       max_txd_pwr);
+				       max_txd_pwr);
 	if(adapter->pcix_82544)
 		count += nr_frags;
-	
-	spin_lock_irqsave(&adapter->tx_lock, flags);
-	/* need: count +  2 desc gap to keep tail from touching 
+
+ 	local_irq_save(flags); 
+ 	if (!spin_trylock(&adapter->tx_lock)) { 
+ 		/* Collision - tell upper layer to requeue */ 
+ 		local_irq_restore(flags); 
+ 		return NETDEV_TX_LOCKED; 
+ 	} 
+
+	/* need: count + 2 desc gap to keep tail from touching
 	 * head, otherwise try next time */
-	if(E1000_DESC_UNUSED(&adapter->tx_ring) < count + 2 ) {
+	if(E1000_DESC_UNUSED(&adapter->tx_ring) < count + 2) {
 		netif_stop_queue(netdev);
 		spin_unlock_irqrestore(&adapter->tx_lock, flags);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
-	spin_unlock_irqrestore(&adapter->tx_lock, flags);
 
-	if(adapter->hw.mac_type == e1000_82547) {
-		if(e1000_82547_fifo_workaround(adapter, skb)) {
+	if(unlikely(adapter->hw.mac_type == e1000_82547)) {
+		if(unlikely(e1000_82547_fifo_workaround(adapter, skb))) {
 			netif_stop_queue(netdev);
 			mod_timer(&adapter->tx_fifo_stall_timer, jiffies);
-			return 1;
+			spin_unlock_irqrestore(&adapter->tx_lock, flags);
+			return NETDEV_TX_BUSY;
 		}
 	}
 
-	if(adapter->vlgrp && vlan_tx_tag_present(skb)) {
+	if(unlikely(adapter->vlgrp && vlan_tx_tag_present(skb))) {
 		tx_flags |= E1000_TX_FLAGS_VLAN;
 		tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT);
 	}
 
 	first = adapter->tx_ring.next_to_use;
 	
-	if(e1000_tso(adapter, skb))
+	if(likely(e1000_tso(adapter, skb)))
 		tx_flags |= E1000_TX_FLAGS_TSO;
-	else if(e1000_tx_csum(adapter, skb))
+	else if(likely(e1000_tx_csum(adapter, skb)))
 		tx_flags |= E1000_TX_FLAGS_CSUM;
 
-	e1000_tx_queue(adapter, 
-		e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss), 
+	e1000_tx_queue(adapter,
+		e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss),
 		tx_flags);
 
 	netdev->trans_start = jiffies;
 
-	return 0;
+	spin_unlock_irqrestore(&adapter->tx_lock, flags);
+	return NETDEV_TX_OK;
 }
 
 /**
@@ -1843,10 +1878,8 @@ e1000_tx_timeout_task(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev->priv;
 
-	netif_device_detach(netdev);
 	e1000_down(adapter);
 	e1000_up(adapter);
-	netif_device_attach(netdev);
 }
 
 /**
@@ -1905,7 +1938,6 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
 	}
 
 	if(old_mtu != adapter->rx_buffer_len && netif_running(netdev)) {
-
 		e1000_down(adapter);
 		e1000_up(adapter);
 	}
@@ -1951,8 +1983,6 @@ e1000_update_stats(struct e1000_adapter *adapter)
 	adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023);
 	adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522);
 
-	/* the rest of the counters are only modified here */
-
 	adapter->stats.symerrs += E1000_READ_REG(hw, SYMERRS);
 	adapter->stats.mpc += E1000_READ_REG(hw, MPC);
 	adapter->stats.scc += E1000_READ_REG(hw, SCC);
@@ -2059,7 +2089,7 @@ e1000_update_stats(struct e1000_adapter *adapter)
  * @adapter: board private structure
  **/
 
-static inline void
+static void
 e1000_irq_disable(struct e1000_adapter *adapter)
 {
 	atomic_inc(&adapter->irq_sem);
@@ -2073,10 +2103,10 @@ e1000_irq_disable(struct e1000_adapter *adapter)
  * @adapter: board private structure
  **/
 
-static inline void
+static void
 e1000_irq_enable(struct e1000_adapter *adapter)
 {
-	if(atomic_dec_and_test(&adapter->irq_sem)) {
+	if(likely(atomic_dec_and_test(&adapter->irq_sem))) {
 		E1000_WRITE_REG(&adapter->hw, IMS, IMS_ENABLE_MASK);
 		E1000_WRITE_FLUSH(&adapter->hw);
 	}
@@ -2095,21 +2125,21 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
 	struct net_device *netdev = data;
 	struct e1000_adapter *adapter = netdev->priv;
 	struct e1000_hw *hw = &adapter->hw;
-	uint32_t icr = E1000_READ_REG(&adapter->hw, ICR);
+	uint32_t icr = E1000_READ_REG(hw, ICR);
 #ifndef CONFIG_E1000_NAPI
 	unsigned int i;
 #endif
 
-	if(!icr)
+	if(unlikely(!icr))
 		return IRQ_NONE;  /* Not our interrupt */
 
-	if(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
+	if(unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
 		hw->get_link_status = 1;
 		mod_timer(&adapter->watchdog_timer, jiffies);
 	}
 
 #ifdef CONFIG_E1000_NAPI
-	if(netif_rx_schedule_prep(netdev)) {
+	if(likely(netif_rx_schedule_prep(netdev))) {
 
 		/* Disable interrupts and register for poll. The flush 
 		  of the posted write is intentionally left out.
@@ -2121,8 +2151,8 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
 	}
 #else
 	for(i = 0; i < E1000_MAX_INTR; i++)
-		if(!e1000_clean_rx_irq(adapter) &
-		   !e1000_clean_tx_irq(adapter))
+		if(unlikely(!e1000_clean_rx_irq(adapter) &
+		   !e1000_clean_tx_irq(adapter)))
 			break;
 #endif
 
@@ -2140,15 +2170,18 @@ e1000_clean(struct net_device *netdev, int *budget)
 {
 	struct e1000_adapter *adapter = netdev->priv;
 	int work_to_do = min(*budget, netdev->quota);
+	int tx_cleaned;
 	int work_done = 0;
 	
-	e1000_clean_tx_irq(adapter);
+	tx_cleaned = e1000_clean_tx_irq(adapter);
 	e1000_clean_rx_irq(adapter, &work_done, work_to_do);
 
 	*budget -= work_done;
 	netdev->quota -= work_done;
 	
-	if(work_done < work_to_do || !netif_running(netdev)) {
+	/* if no Rx and Tx cleanup work was done, exit the polling mode */
+	if(!tx_cleaned || (work_done < work_to_do) || 
+				!netif_running(netdev)) {
 		netif_rx_complete(netdev);
 		e1000_irq_enable(adapter);
 		return 0;
@@ -2156,8 +2189,8 @@ e1000_clean(struct net_device *netdev, int *budget)
 
 	return (work_done >= work_to_do);
 }
-#endif
 
+#endif
 /**
  * e1000_clean_tx_irq - Reclaim resources after transmit completes
  * @adapter: board private structure
@@ -2174,31 +2207,25 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
 	unsigned int i, eop;
 	boolean_t cleaned = FALSE;
 
-
 	i = tx_ring->next_to_clean;
 	eop = tx_ring->buffer_info[i].next_to_watch;
 	eop_desc = E1000_TX_DESC(*tx_ring, eop);
 
 	while(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
-
 		for(cleaned = FALSE; !cleaned; ) {
 			tx_desc = E1000_TX_DESC(*tx_ring, i);
 			buffer_info = &tx_ring->buffer_info[i];
 
-			if(buffer_info->dma) {
-
+			if(likely(buffer_info->dma)) {
 				pci_unmap_page(pdev,
 					       buffer_info->dma,
 					       buffer_info->length,
 					       PCI_DMA_TODEVICE);
-
 				buffer_info->dma = 0;
 			}
 
 			if(buffer_info->skb) {
-
 				dev_kfree_skb_any(buffer_info->skb);
-
 				buffer_info->skb = NULL;
 			}
 
@@ -2207,7 +2234,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
 			tx_desc->upper.data = 0;
 
 			cleaned = (i == eop);
-			if(++i == tx_ring->count) i = 0;
+			if(unlikely(++i == tx_ring->count)) i = 0;
 		}
 		
 		eop = tx_ring->buffer_info[i].next_to_watch;
@@ -2218,7 +2245,8 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
 
 	spin_lock(&adapter->tx_lock);
 
-	if(cleaned && netif_queue_stopped(netdev) && netif_carrier_ok(netdev))
+	if(unlikely(cleaned && netif_queue_stopped(netdev) &&
+		    netif_carrier_ok(netdev)))
 		netif_wake_queue(netdev);
 
 	spin_unlock(&adapter->tx_lock);
@@ -2227,7 +2255,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
 }
 
 /**
- * e1000_clean_rx_irq - Send received data up the network stack,
+ * e1000_clean_rx_irq - Send received data up the network stack
  * @adapter: board private structure
  **/
 
@@ -2256,14 +2284,11 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter)
 
 	while(rx_desc->status & E1000_RXD_STAT_DD) {
 		buffer_info = &rx_ring->buffer_info[i];
-
 #ifdef CONFIG_E1000_NAPI
 		if(*work_done >= work_to_do)
 			break;
-
 		(*work_done)++;
 #endif
-
 		cleaned = TRUE;
 
 		pci_unmap_single(pdev,
@@ -2274,49 +2299,28 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter)
 		skb = buffer_info->skb;
 		length = le16_to_cpu(rx_desc->length);
 
-		if(!(rx_desc->status & E1000_RXD_STAT_EOP)) {
-
+		if(unlikely(!(rx_desc->status & E1000_RXD_STAT_EOP))) {
 			/* All receives must fit into a single buffer */
-
-			E1000_DBG("%s: Receive packet consumed multiple buffers\n",
-				netdev->name);
-
+			E1000_DBG("%s: Receive packet consumed multiple"
+				  " buffers\n", netdev->name);
 			dev_kfree_skb_irq(skb);
-			rx_desc->status = 0;
-			buffer_info->skb = NULL;
-
-			if(++i == rx_ring->count) i = 0;
-
-			rx_desc = E1000_RX_DESC(*rx_ring, i);
-			continue;
+			goto next_desc;
 		}
 
-		if(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK) {
-
+		if(unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
 			last_byte = *(skb->data + length - 1);
-
 			if(TBI_ACCEPT(&adapter->hw, rx_desc->status,
 			              rx_desc->errors, length, last_byte)) {
-
 				spin_lock_irqsave(&adapter->stats_lock, flags);
-
 				e1000_tbi_adjust_stats(&adapter->hw,
 				                       &adapter->stats,
 				                       length, skb->data);
-
 				spin_unlock_irqrestore(&adapter->stats_lock,
 				                       flags);
 				length--;
 			} else {
-
 				dev_kfree_skb_irq(skb);
-				rx_desc->status = 0;
-				buffer_info->skb = NULL;
-
-				if(++i == rx_ring->count) i = 0;
-
-				rx_desc = E1000_RX_DESC(*rx_ring, i);
-				continue;
+				goto next_desc;
 			}
 		}
 
@@ -2328,17 +2332,19 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter)
 
 		skb->protocol = eth_type_trans(skb, netdev);
 #ifdef CONFIG_E1000_NAPI
-		if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) {
+		if(unlikely(adapter->vlgrp &&
+			    (rx_desc->status & E1000_RXD_STAT_VP))) {
 			vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
-				le16_to_cpu(rx_desc->special &
-					E1000_RXD_SPC_VLAN_MASK));
+						 le16_to_cpu(rx_desc->special &
+						 E1000_RXD_SPC_VLAN_MASK));
 		} else {
 			netif_receive_skb(skb);
 		}
 #else /* CONFIG_E1000_NAPI */
-		if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) {
+		if(unlikely(adapter->vlgrp &&
+			    (rx_desc->status & E1000_RXD_STAT_VP))) {
 			vlan_hwaccel_rx(skb, adapter->vlgrp,
-				le16_to_cpu(rx_desc->special &
+					le16_to_cpu(rx_desc->special &
 					E1000_RXD_SPC_VLAN_MASK));
 		} else {
 			netif_rx(skb);
@@ -2346,10 +2352,10 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter)
 #endif /* CONFIG_E1000_NAPI */
 		netdev->last_rx = jiffies;
 
+next_desc:
 		rx_desc->status = 0;
 		buffer_info->skb = NULL;
-
-		if(++i == rx_ring->count) i = 0;
+		if(unlikely(++i == rx_ring->count)) i = 0;
 
 		rx_desc = E1000_RX_DESC(*rx_ring, i);
 	}
@@ -2381,11 +2387,9 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
 	buffer_info = &rx_ring->buffer_info[i];
 
 	while(!buffer_info->skb) {
-		rx_desc = E1000_RX_DESC(*rx_ring, i);
 
 		skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
-
-		if(!skb) {
+		if(unlikely(!skb)) {
 			/* Better luck next round */
 			break;
 		}
@@ -2400,15 +2404,15 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
 
 		buffer_info->skb = skb;
 		buffer_info->length = adapter->rx_buffer_len;
-		buffer_info->dma =
-			pci_map_single(pdev,
-			               skb->data,
-			               adapter->rx_buffer_len,
-			               PCI_DMA_FROMDEVICE);
+		buffer_info->dma = pci_map_single(pdev,
+						  skb->data,
+						  adapter->rx_buffer_len,
+						  PCI_DMA_FROMDEVICE);
 
+		rx_desc = E1000_RX_DESC(*rx_ring, i);
 		rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
 
-		if((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i) {
+		if(unlikely((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i)) {
 			/* Force memory writes to complete before letting h/w
 			 * know there are new descriptors to fetch.  (Only
 			 * applicable for weak-ordered memory model archs,
@@ -2418,7 +2422,7 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
 			E1000_WRITE_REG(&adapter->hw, RDT, i);
 		}
 
-		if(++i == rx_ring->count) i = 0;
+		if(unlikely(++i == rx_ring->count)) i = 0;
 		buffer_info = &rx_ring->buffer_info[i];
 	}
 
@@ -2537,22 +2541,24 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
 			return -EFAULT;
 		mii_reg = data->val_in;
 		if (e1000_write_phy_reg(&adapter->hw, data->reg_num,
-					data->val_in))
+					mii_reg))
 			return -EIO;
 		if (adapter->hw.phy_type == e1000_phy_m88) {
 			switch (data->reg_num) {
 			case PHY_CTRL:
-				if(data->val_in & MII_CR_AUTO_NEG_EN) {
+				if(mii_reg & MII_CR_POWER_DOWN)
+					break;
+				if(mii_reg & MII_CR_AUTO_NEG_EN) {
 					adapter->hw.autoneg = 1;
 					adapter->hw.autoneg_advertised = 0x2F;
 				} else {
-					if (data->val_in & 0x40)
+					if (mii_reg & 0x40)
 						spddplx = SPEED_1000;
-					else if (data->val_in & 0x2000)
+					else if (mii_reg & 0x2000)
 						spddplx = SPEED_100;
 					else
 						spddplx = SPEED_10;
-					spddplx += (data->val_in & 0x100)
+					spddplx += (mii_reg & 0x100)
 						   ? FULL_DUPLEX :
 						   HALF_DUPLEX;
 					retval = e1000_set_spd_dplx(adapter,
@@ -2572,6 +2578,18 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
 					return -EIO;
 				break;
 			}
+		} else {
+			switch (data->reg_num) {
+			case PHY_CTRL:
+				if(mii_reg & MII_CR_POWER_DOWN)
+					break;
+				if(netif_running(adapter->netdev)) {
+					e1000_down(adapter);
+					e1000_up(adapter);
+				} else
+					e1000_reset(adapter);
+				break;
+			}
 		}
 		break;
 	default:
@@ -2587,17 +2605,17 @@ e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
  * @sk_buff: socket buffer with received data
  **/
 
-static inline void
+static void
 e1000_rx_checksum(struct e1000_adapter *adapter,
                   struct e1000_rx_desc *rx_desc,
                   struct sk_buff *skb)
 {
 	/* 82543 or newer only */
-	if((adapter->hw.mac_type < e1000_82543) ||
+	if(unlikely((adapter->hw.mac_type < e1000_82543) ||
 	/* Ignore Checksum bit is set */
 	(rx_desc->status & E1000_RXD_STAT_IXSM) ||
 	/* TCP Checksum has not been calculated */
-	(!(rx_desc->status & E1000_RXD_STAT_TCPCS))) {
+	(!(rx_desc->status & E1000_RXD_STAT_TCPCS)))) {
 		skb->ip_summed = CHECKSUM_NONE;
 		return;
 	}
@@ -2609,7 +2627,7 @@ e1000_rx_checksum(struct e1000_adapter *adapter,
 		skb->ip_summed = CHECKSUM_NONE;
 		adapter->hw_csum_err++;
 	} else {
-	/* TCP checksum is good */
+		/* TCP checksum is good */
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 		adapter->hw_csum_good++;
 	}
@@ -2620,7 +2638,8 @@ e1000_pci_set_mwi(struct e1000_hw *hw)
 {
 	struct e1000_adapter *adapter = hw->back;
 
-	pci_set_mwi(adapter->pdev);
+	int ret;
+	ret = pci_set_mwi(adapter->pdev);
 }
 
 void
@@ -2670,26 +2689,22 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
 
 	if(grp) {
 		/* enable VLAN tag insert/strip */
-
 		ctrl = E1000_READ_REG(&adapter->hw, CTRL);
 		ctrl |= E1000_CTRL_VME;
 		E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
 
 		/* enable VLAN receive filtering */
-
 		rctl = E1000_READ_REG(&adapter->hw, RCTL);
 		rctl |= E1000_RCTL_VFE;
 		rctl &= ~E1000_RCTL_CFIEN;
 		E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
 	} else {
 		/* disable VLAN tag insert/strip */
-
 		ctrl = E1000_READ_REG(&adapter->hw, CTRL);
 		ctrl &= ~E1000_CTRL_VME;
 		E1000_WRITE_REG(&adapter->hw, CTRL, ctrl);
 
 		/* disable VLAN filtering */
-
 		rctl = E1000_READ_REG(&adapter->hw, RCTL);
 		rctl &= ~E1000_RCTL_VFE;
 		E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
@@ -2705,7 +2720,6 @@ e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
 	uint32_t vfta, index;
 
 	/* add VID to filter table */
-
 	index = (vid >> 5) & 0x7F;
 	vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
 	vfta |= (1 << (vid & 0x1F));
@@ -2725,8 +2739,7 @@ e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
 
 	e1000_irq_enable(adapter);
 
-	/* remove VID from filter table*/
-
+	/* remove VID from filter table */
 	index = (vid >> 5) & 0x7F;
 	vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
 	vfta &= ~(1 << (vid & 0x1F));
@@ -2772,6 +2785,8 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx)
 		break;
 	case SPEED_1000 + DUPLEX_HALF: /* not supported */
 	default:
+		DPRINTK(PROBE, ERR, 
+			"Unsupported Speed/Duplexity configuration\n");
 		return -EINVAL;
 	}
 	return 0;
@@ -2865,6 +2880,8 @@ e1000_suspend(struct pci_dev *pdev, uint32_t state)
 		}
 	}
 
+	pci_disable_device(pdev);
+
 	state = (state > 0) ? 3 : 0;
 	pci_set_power_state(pdev, state);
 
@@ -2879,6 +2896,7 @@ e1000_resume(struct pci_dev *pdev)
 	struct e1000_adapter *adapter = netdev->priv;
 	uint32_t manc;
 
+	pci_enable_device(pdev);
 	pci_set_power_state(pdev, 0);
 	pci_restore_state(pdev, adapter->pci_state);
 
@@ -2910,12 +2928,12 @@ e1000_resume(struct pci_dev *pdev)
  * without having to re-enable interrupts. It's not called while
  * the interrupt routine is executing.
  */
-
-static void e1000_netpoll (struct net_device *dev)
+static void
+e1000_netpoll (struct net_device *netdev)
 {
-	struct e1000_adapter *adapter = dev->priv;
+	struct e1000_adapter *adapter = netdev->priv;
 	disable_irq(adapter->pdev->irq);
-	e1000_intr (adapter->pdev->irq, dev, NULL);
+	e1000_intr(adapter->pdev->irq, netdev, NULL);
 	enable_irq(adapter->pdev->irq);
 }
 #endif
diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
index 3e79a45de..555421366 100644
--- a/drivers/net/e1000/e1000_param.c
+++ b/drivers/net/e1000/e1000_param.c
@@ -212,7 +212,7 @@ E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
 #define MAX_TXABSDELAY            0xFFFF
 #define MIN_TXABSDELAY                 0
 
-#define DEFAULT_ITR                    1
+#define DEFAULT_ITR                 8000
 #define MAX_ITR                   100000
 #define MIN_ITR                      100
 
@@ -235,7 +235,7 @@ struct e1000_option {
 
 static int __devinit
 e1000_validate_option(int *value, struct e1000_option *opt,
-	struct e1000_adapter *adapter)
+		struct e1000_adapter *adapter)
 {
 	if(*value == OPTION_UNSET) {
 		*value = opt->def;
@@ -256,7 +256,7 @@ e1000_validate_option(int *value, struct e1000_option *opt,
 	case range_option:
 		if(*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
 			DPRINTK(PROBE, INFO,
-				"%s set to %i\n", opt->name, *value);
+					"%s set to %i\n", opt->name, *value);
 			return 0;
 		}
 		break;
@@ -449,8 +449,7 @@ e1000_check_options(struct e1000_adapter *adapter)
 			DPRINTK(PROBE, INFO, "%s turned off\n", opt.name);
 			break;
 		case 1:
-			DPRINTK(PROBE, INFO,
-				"%s set to dynamic mode\n", opt.name);
+			DPRINTK(PROBE, INFO, "%s set to dynamic mode\n", opt.name);
 			break;
 		default:
 			e1000_validate_option(&adapter->itr, &opt, adapter);
@@ -493,8 +492,9 @@ e1000_check_fiber_options(struct e1000_adapter *adapter)
 		       "parameter ignored\n");
 	}
 	if((AutoNeg[bd] != OPTION_UNSET) && (AutoNeg[bd] != 0x20)) {
-		DPRINTK(PROBE, INFO, "AutoNeg other than Full/1000 is "
-		       "not valid for fiber adapters, parameter ignored\n");
+		DPRINTK(PROBE, INFO, "AutoNeg other than 1000/Full is "
+				 "not valid for fiber adapters, "
+				 "parameter ignored\n");
 	}
 }
 
@@ -611,24 +611,24 @@ e1000_check_copper_options(struct e1000_adapter *adapter)
 		break;
 	case HALF_DUPLEX:
 		DPRINTK(PROBE, INFO, "Half Duplex specified without Speed\n");
-		DPRINTK(PROBE, INFO,
-			"Using Autonegotiation at Half Duplex only\n");
+		DPRINTK(PROBE, INFO, "Using Autonegotiation at "
+			"Half Duplex only\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
 		adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
 		                                 ADVERTISE_100_HALF;
 		break;
 	case FULL_DUPLEX:
 		DPRINTK(PROBE, INFO, "Full Duplex specified without Speed\n");
-		DPRINTK(PROBE, INFO,
-			"Using Autonegotiation at Full Duplex only\n");
+		DPRINTK(PROBE, INFO, "Using Autonegotiation at "
+			"Full Duplex only\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
 		adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
 		                                 ADVERTISE_100_FULL |
 		                                 ADVERTISE_1000_FULL;
 		break;
 	case SPEED_10:
-		DPRINTK(PROBE, INFO,
-			"10 Mbps Speed specified without Duplex\n");
+		DPRINTK(PROBE, INFO, "10 Mbps Speed specified "
+			"without Duplex\n");
 		DPRINTK(PROBE, INFO, "Using Autonegotiation at 10 Mbps only\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
 		adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
@@ -647,10 +647,10 @@ e1000_check_copper_options(struct e1000_adapter *adapter)
 		adapter->hw.autoneg_advertised = 0;
 		break;
 	case SPEED_100:
-		DPRINTK(PROBE, INFO,
-			"100 Mbps Speed specified without Duplex\n");
-		DPRINTK(PROBE, INFO,
-			"Using Autonegotiation at 100 Mbps only\n");
+		DPRINTK(PROBE, INFO, "100 Mbps Speed specified "
+			"without Duplex\n");
+		DPRINTK(PROBE, INFO, "Using Autonegotiation at "
+			"100 Mbps only\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
 		adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
 		                                 ADVERTISE_100_FULL;
@@ -668,10 +668,11 @@ e1000_check_copper_options(struct e1000_adapter *adapter)
 		adapter->hw.autoneg_advertised = 0;
 		break;
 	case SPEED_1000:
+		DPRINTK(PROBE, INFO, "1000 Mbps Speed specified without "
+			"Duplex\n");
 		DPRINTK(PROBE, INFO,
-			"1000 Mbps Speed specified without Duplex\n");
-		DPRINTK(PROBE, INFO,
-		       "Using Autonegotiation at 1000 Mbps Full Duplex only\n");
+			"Using Autonegotiation at 1000 Mbps "
+			"Full Duplex only\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
 		adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
 		break;
@@ -679,7 +680,8 @@ e1000_check_copper_options(struct e1000_adapter *adapter)
 		DPRINTK(PROBE, INFO,
 			"Half Duplex is not supported at 1000 Mbps\n");
 		DPRINTK(PROBE, INFO,
-		       "Using Autonegotiation at 1000 Mbps Full Duplex only\n");
+			"Using Autonegotiation at 1000 Mbps "
+			"Full Duplex only\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
 		adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
 		break;
@@ -696,8 +698,8 @@ e1000_check_copper_options(struct e1000_adapter *adapter)
 	/* Speed, AutoNeg and MDI/MDI-X must all play nice */
 	if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) {
 		DPRINTK(PROBE, INFO,
-		       "Speed, AutoNeg and MDI-X specifications are "
-		       "incompatible. Setting MDI-X to a compatible value.\n");
+			"Speed, AutoNeg and MDI-X specifications are "
+			"incompatible. Setting MDI-X to a compatible value.\n");
 	}
 }
 
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index 36b5508f4..1132101ec 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -88,7 +88,6 @@ static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
 #define PKT_BUF_SZ		1536
 
 #include <linux/config.h>
-#include <linux/version.h>
 #include <linux/module.h>
 
 #include <linux/kernel.h>
@@ -2447,22 +2446,6 @@ static struct pci_driver eepro100_driver = {
 #endif /* CONFIG_PM */
 };
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,48)
-static int pci_module_init(struct pci_driver *pdev)
-{
-	int rc;
-
-	rc = pci_register_driver(pdev);
-	if (rc <= 0) {
-		printk(KERN_INFO "%s: No cards found, driver not installed.\n",
-			   pdev->name);
-		pci_unregister_driver(pdev);
-		return -ENODEV;
-	}
-	return 0;
-}
-#endif
-
 static int __init eepro100_init_module(void)
 {
 #ifdef MODULE
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index 771bfc672..ec327ad3a 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -80,8 +80,6 @@
    These may be modified when a driver module is loaded.*/
 
 static int debug = 1;			/* 1 normal messages, 0 quiet .. 7 verbose. */
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 32;
 
 /* Used to pass the full-duplex flag, etc. */
 #define MAX_UNITS 8		/* More are supported, limit only on options */
@@ -99,9 +97,9 @@ static int rx_copybreak;
    Making the Tx ring too large decreases the effectiveness of channel
    bonding and packet priority.
    There are no ill effects from too-large receive rings. */
-#define TX_RING_SIZE	16
-#define TX_QUEUE_LEN	10		/* Limit ring entries actually used.  */
-#define RX_RING_SIZE	32
+#define TX_RING_SIZE	256
+#define TX_QUEUE_LEN	240		/* Limit ring entries actually used.  */
+#define RX_RING_SIZE	256
 #define TX_TOTAL_SIZE	TX_RING_SIZE*sizeof(struct epic_tx_desc)
 #define RX_TOTAL_SIZE	RX_RING_SIZE*sizeof(struct epic_rx_desc)
 
@@ -152,12 +150,10 @@ MODULE_DESCRIPTION("SMC 83c170 EPIC series Ethernet driver");
 MODULE_LICENSE("GPL");
 
 MODULE_PARM(debug, "i");
-MODULE_PARM(max_interrupt_work, "i");
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM_DESC(debug, "EPIC/100 debug level (0-5)");
-MODULE_PARM_DESC(max_interrupt_work, "EPIC/100 maximum events handled per interrupt");
 MODULE_PARM_DESC(options, "EPIC/100: Bits 0-3: media type, bit 4: full duplex");
 MODULE_PARM_DESC(rx_copybreak, "EPIC/100 copy breakpoint for copy-only-tiny-frames");
 MODULE_PARM_DESC(full_duplex, "EPIC/100 full duplex setting(s) (1)");
@@ -289,6 +285,12 @@ enum CommandBits {
 	StopTxDMA=0x20, StopRxDMA=0x40, RestartTx=0x80,
 };
 
+#define EpicRemoved	0xffffffff	/* Chip failed or removed (CardBus) */
+
+#define EpicNapiEvent	(TxEmpty | TxDone | \
+			 RxDone | RxStarted | RxEarlyWarn | RxOverflow | RxFull)
+#define EpicNormalEvent	(0x0000ffff & ~EpicNapiEvent)
+
 static u16 media2miictl[16] = {
 	0, 0x0C00, 0x0C00, 0x2000,  0x0100, 0x2100, 0, 0,
 	0, 0, 0, 0,  0, 0, 0, 0 };
@@ -327,9 +329,12 @@ struct epic_private {
 
 	/* Ring pointers. */
 	spinlock_t lock;				/* Group with Tx control cache line. */
+	spinlock_t napi_lock;
+	unsigned int reschedule_in_poll;
 	unsigned int cur_tx, dirty_tx;
 
 	unsigned int cur_rx, dirty_rx;
+	u32 irq_mask;
 	unsigned int rx_buf_sz;				/* Based on MTU+slack. */
 
 	struct pci_dev *pci_dev;			/* PCI bus location. */
@@ -356,7 +361,8 @@ static void epic_timer(unsigned long data);
 static void epic_tx_timeout(struct net_device *dev);
 static void epic_init_ring(struct net_device *dev);
 static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static int epic_rx(struct net_device *dev);
+static int epic_rx(struct net_device *dev, int budget);
+static int epic_poll(struct net_device *dev, int *budget);
 static irqreturn_t epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static struct ethtool_ops netdev_ethtool_ops;
@@ -375,7 +381,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
 	int irq;
 	struct net_device *dev;
 	struct epic_private *ep;
-	int i, option = 0, duplex = 0;
+	int i, ret, option = 0, duplex = 0;
 	void *ring_space;
 	dma_addr_t ring_dma;
 
@@ -389,29 +395,33 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
 	
 	card_idx++;
 	
-	i = pci_enable_device(pdev);
-	if (i)
-		return i;
+	ret = pci_enable_device(pdev);
+	if (ret)
+		goto out;
 	irq = pdev->irq;
 
 	if (pci_resource_len(pdev, 0) < pci_id_tbl[chip_idx].io_size) {
 		printk (KERN_ERR "card %d: no PCI region space\n", card_idx);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto err_out_disable;
 	}
 	
 	pci_set_master(pdev);
 
+	ret = pci_request_regions(pdev, DRV_NAME);
+	if (ret < 0)
+		goto err_out_disable;
+
+	ret = -ENOMEM;
+
 	dev = alloc_etherdev(sizeof (*ep));
 	if (!dev) {
 		printk (KERN_ERR "card %d: no memory for eth device\n", card_idx);
-		return -ENOMEM;
+		goto err_out_free_res;
 	}
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	if (pci_request_regions(pdev, DRV_NAME))
-		goto err_out_free_netdev;
-
 #ifdef USE_IO_OPS
 	ioaddr = pci_resource_start (pdev, 0);
 #else
@@ -419,7 +429,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
 	ioaddr = (long) ioremap (ioaddr, pci_resource_len (pdev, 1));
 	if (!ioaddr) {
 		printk (KERN_ERR DRV_NAME " %d: ioremap failed\n", card_idx);
-		goto err_out_free_res;
+		goto err_out_free_netdev;
 	}
 #endif
 
@@ -456,7 +466,9 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
 	dev->base_addr = ioaddr;
 	dev->irq = irq;
 
-	spin_lock_init (&ep->lock);
+	spin_lock_init(&ep->lock);
+	spin_lock_init(&ep->napi_lock);
+	ep->reschedule_in_poll = 0;
 
 	/* Bring the chip out of low-power mode. */
 	outl(0x4200, ioaddr + GENCTL);
@@ -486,6 +498,9 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
 	ep->pci_dev = pdev;
 	ep->chip_id = chip_idx;
 	ep->chip_flags = pci_id_tbl[chip_idx].drv_flags;
+	ep->irq_mask = 
+		(ep->chip_flags & TYPE2_INTR ?  PCIBusErr175 : PCIBusErr170)
+		 | CntFull | TxUnderrun | EpicNapiEvent;
 
 	/* Find the connected MII xcvrs.
 	   Doing this in open() would allow detecting external xcvrs later, but
@@ -540,10 +555,12 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
 	dev->ethtool_ops = &netdev_ethtool_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
 	dev->tx_timeout = &epic_tx_timeout;
+	dev->poll = epic_poll;
+	dev->weight = 64;
 
-	i = register_netdev(dev);
-	if (i)
-		goto err_out_unmap_tx;
+	ret = register_netdev(dev);
+	if (ret < 0)
+		goto err_out_unmap_rx;
 
 	printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ",
 		   dev->name, pci_id_tbl[chip_idx].name, ioaddr, dev->irq);
@@ -551,19 +568,24 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
 		printk("%2.2x:", dev->dev_addr[i]);
 	printk("%2.2x.\n", dev->dev_addr[i]);
 
-	return 0;
+out:
+	return ret;
 
+err_out_unmap_rx:
+	pci_free_consistent(pdev, RX_TOTAL_SIZE, ep->rx_ring, ep->rx_ring_dma);
 err_out_unmap_tx:
 	pci_free_consistent(pdev, TX_TOTAL_SIZE, ep->tx_ring, ep->tx_ring_dma);
 err_out_iounmap:
 #ifndef USE_IO_OPS
 	iounmap(ioaddr);
-err_out_free_res:
-#endif
-	pci_release_regions(pdev);
 err_out_free_netdev:
+#endif
 	free_netdev(dev);
-	return -ENODEV;
+err_out_free_res:
+	pci_release_regions(pdev);
+err_out_disable:
+	pci_disable_device(pdev);
+	goto out;
 }
 
 /* Serial EEPROM section. */
@@ -589,6 +611,38 @@ err_out_free_netdev:
 #define EE_READ256_CMD	(6 << 8)
 #define EE_ERASE_CMD	(7 << 6)
 
+static void epic_disable_int(struct net_device *dev, struct epic_private *ep)
+{
+	long ioaddr = dev->base_addr;
+
+	outl(0x00000000, ioaddr + INTMASK);
+}
+
+static inline void __epic_pci_commit(long ioaddr)
+{
+#ifndef USE_IO_OPS
+	inl(ioaddr + INTMASK);
+#endif
+}
+
+static inline void epic_napi_irq_off(struct net_device *dev,
+				     struct epic_private *ep)
+{
+	long ioaddr = dev->base_addr;
+
+	outl(ep->irq_mask & ~EpicNapiEvent, ioaddr + INTMASK);
+	__epic_pci_commit(ioaddr);
+}
+
+static inline void epic_napi_irq_on(struct net_device *dev,
+				    struct epic_private *ep)
+{
+	long ioaddr = dev->base_addr;
+
+	/* No need to commit possible posted write */
+	outl(ep->irq_mask | EpicNapiEvent, ioaddr + INTMASK);
+}
+
 static int __devinit read_eeprom(long ioaddr, int location)
 {
 	int i;
@@ -749,9 +803,8 @@ static int epic_open(struct net_device *dev)
 
 	/* Enable interrupts by setting the interrupt mask. */
 	outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170)
-		 | CntFull | TxUnderrun | TxDone | TxEmpty
-		 | RxError | RxOverflow | RxFull | RxHeader | RxDone,
-		 ioaddr + INTMASK);
+		 | CntFull | TxUnderrun 
+		 | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK);
 
 	if (debug > 1)
 		printk(KERN_DEBUG "%s: epic_open() ioaddr %lx IRQ %d status %4.4x "
@@ -792,7 +845,7 @@ static void epic_pause(struct net_device *dev)
 	}
 
 	/* Remove the packets on the Rx queue. */
-	epic_rx(dev);
+	epic_rx(dev, RX_RING_SIZE);
 }
 
 static void epic_restart(struct net_device *dev)
@@ -838,9 +891,9 @@ static void epic_restart(struct net_device *dev)
 
 	/* Enable interrupts by setting the interrupt mask. */
 	outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170)
-		 | CntFull | TxUnderrun | TxDone | TxEmpty
-		 | RxError | RxOverflow | RxFull | RxHeader | RxDone,
-		 ioaddr + INTMASK);
+		 | CntFull | TxUnderrun
+		 | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK);
+
 	printk(KERN_DEBUG "%s: epic_restart() done, cmd status %4.4x, ctl %4.4x"
 		   " interrupt %4.4x.\n",
 		   dev->name, (int)inl(ioaddr + COMMAND), (int)inl(ioaddr + GENCTL),
@@ -926,7 +979,6 @@ static void epic_init_ring(struct net_device *dev)
 	int i;
 
 	ep->tx_full = 0;
-	ep->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
 	ep->dirty_tx = ep->cur_tx = 0;
 	ep->cur_rx = ep->dirty_rx = 0;
 	ep->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
@@ -1026,6 +1078,76 @@ static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	return 0;
 }
 
+static void epic_tx_error(struct net_device *dev, struct epic_private *ep,
+			  int status)
+{
+	struct net_device_stats *stats = &ep->stats;
+
+#ifndef final_version
+	/* There was an major error, log it. */
+	if (debug > 1)
+		printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n",
+		       dev->name, status);
+#endif
+	stats->tx_errors++;
+	if (status & 0x1050)
+		stats->tx_aborted_errors++;
+	if (status & 0x0008)
+		stats->tx_carrier_errors++;
+	if (status & 0x0040)
+		stats->tx_window_errors++;
+	if (status & 0x0010)
+		stats->tx_fifo_errors++;
+}
+
+static void epic_tx(struct net_device *dev, struct epic_private *ep)
+{
+	unsigned int dirty_tx, cur_tx;
+
+	/*
+	 * Note: if this lock becomes a problem we can narrow the locked
+	 * region at the cost of occasionally grabbing the lock more times.
+	 */
+	cur_tx = ep->cur_tx;
+	for (dirty_tx = ep->dirty_tx; cur_tx - dirty_tx > 0; dirty_tx++) {
+		struct sk_buff *skb;
+		int entry = dirty_tx % TX_RING_SIZE;
+		int txstatus = le32_to_cpu(ep->tx_ring[entry].txstatus);
+
+		if (txstatus & DescOwn)
+			break;	/* It still hasn't been Txed */
+
+		if (likely(txstatus & 0x0001)) {
+			ep->stats.collisions += (txstatus >> 8) & 15;
+			ep->stats.tx_packets++;
+			ep->stats.tx_bytes += ep->tx_skbuff[entry]->len;
+		} else
+			epic_tx_error(dev, ep, txstatus);
+
+		/* Free the original skb. */
+		skb = ep->tx_skbuff[entry];
+		pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, 
+				 skb->len, PCI_DMA_TODEVICE);
+		dev_kfree_skb_irq(skb);
+		ep->tx_skbuff[entry] = NULL;
+	}
+
+#ifndef final_version
+	if (cur_tx - dirty_tx > TX_RING_SIZE) {
+		printk(KERN_WARNING
+		       "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
+		       dev->name, dirty_tx, cur_tx, ep->tx_full);
+		dirty_tx += TX_RING_SIZE;
+	}
+#endif
+	ep->dirty_tx = dirty_tx;
+	if (ep->tx_full && cur_tx - dirty_tx < TX_QUEUE_LEN - 4) {
+		/* The ring is no longer full, allow new TX entries. */
+		ep->tx_full = 0;
+		netif_wake_queue(dev);
+	}
+}
+
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
 static irqreturn_t epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
@@ -1033,135 +1155,71 @@ static irqreturn_t epic_interrupt(int irq, void *dev_instance, struct pt_regs *r
 	struct net_device *dev = dev_instance;
 	struct epic_private *ep = dev->priv;
 	long ioaddr = dev->base_addr;
-	int status, boguscnt = max_interrupt_work;
 	unsigned int handled = 0;
+	int status;
 
-	do {
-		status = inl(ioaddr + INTSTAT);
-		/* Acknowledge all of the current interrupt sources ASAP. */
-		outl(status & 0x00007fff, ioaddr + INTSTAT);
+	status = inl(ioaddr + INTSTAT);
+	/* Acknowledge all of the current interrupt sources ASAP. */
+	outl(status & EpicNormalEvent, ioaddr + INTSTAT);
 
-		if (debug > 4)
-			printk(KERN_DEBUG "%s: Interrupt, status=%#8.8x new "
-				   "intstat=%#8.8x.\n",
-				   dev->name, status, (int)inl(ioaddr + INTSTAT));
+	if (debug > 4) {
+		printk(KERN_DEBUG "%s: Interrupt, status=%#8.8x new "
+				   "intstat=%#8.8x.\n", dev->name, status,
+				   (int)inl(ioaddr + INTSTAT));
+	}
 
-		if ((status & IntrSummary) == 0)
-			break;
-		handled = 1;
-
-		if (status & (RxDone | RxStarted | RxEarlyWarn | RxOverflow))
-			epic_rx(dev);
-
-		if (status & (TxEmpty | TxDone)) {
-			unsigned int dirty_tx, cur_tx;
-
-			/* Note: if this lock becomes a problem we can narrow the locked
-			   region at the cost of occasionally grabbing the lock more
-			   times. */
-			spin_lock(&ep->lock);
-			cur_tx = ep->cur_tx;
-			dirty_tx = ep->dirty_tx;
-			for (; cur_tx - dirty_tx > 0; dirty_tx++) {
-				struct sk_buff *skb;
-				int entry = dirty_tx % TX_RING_SIZE;
-				int txstatus = le32_to_cpu(ep->tx_ring[entry].txstatus);
-
-				if (txstatus & DescOwn)
-					break;			/* It still hasn't been Txed */
-
-				if ( ! (txstatus & 0x0001)) {
-					/* There was an major error, log it. */
-#ifndef final_version
-					if (debug > 1)
-						printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n",
-							   dev->name, txstatus);
-#endif
-					ep->stats.tx_errors++;
-					if (txstatus & 0x1050) ep->stats.tx_aborted_errors++;
-					if (txstatus & 0x0008) ep->stats.tx_carrier_errors++;
-					if (txstatus & 0x0040) ep->stats.tx_window_errors++;
-					if (txstatus & 0x0010) ep->stats.tx_fifo_errors++;
-				} else {
-					ep->stats.collisions += (txstatus >> 8) & 15;
-					ep->stats.tx_packets++;
-					ep->stats.tx_bytes += ep->tx_skbuff[entry]->len;
-				}
-
-				/* Free the original skb. */
-				skb = ep->tx_skbuff[entry];
-				pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, 
-						 skb->len, PCI_DMA_TODEVICE);
-				dev_kfree_skb_irq(skb);
-				ep->tx_skbuff[entry] = NULL;
-			}
+	if ((status & IntrSummary) == 0)
+		goto out;
 
-#ifndef final_version
-			if (cur_tx - dirty_tx > TX_RING_SIZE) {
-				printk(KERN_WARNING "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
-					   dev->name, dirty_tx, cur_tx, ep->tx_full);
-				dirty_tx += TX_RING_SIZE;
-			}
-#endif
-			ep->dirty_tx = dirty_tx;
-			if (ep->tx_full
-				&& cur_tx - dirty_tx < TX_QUEUE_LEN - 4) {
-				/* The ring is no longer full, allow new TX entries. */
-				ep->tx_full = 0;
-				spin_unlock(&ep->lock);
-				netif_wake_queue(dev);
-			} else
-				spin_unlock(&ep->lock);
-		}
+	handled = 1;
 
-		/* Check uncommon events all at once. */
-		if (status & (CntFull | TxUnderrun | RxOverflow | RxFull |
-					  PCIBusErr170 | PCIBusErr175)) {
-			if (status == 0xffffffff) /* Chip failed or removed (CardBus). */
-				break;
-			/* Always update the error counts to avoid overhead later. */
-			ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
-			ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
-			ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
-
-			if (status & TxUnderrun) { /* Tx FIFO underflow. */
-				ep->stats.tx_fifo_errors++;
-				outl(ep->tx_threshold += 128, ioaddr + TxThresh);
-				/* Restart the transmit process. */
-				outl(RestartTx, ioaddr + COMMAND);
-			}
-			if (status & RxOverflow) {		/* Missed a Rx frame. */
-				ep->stats.rx_errors++;
-			}
-			if (status & (RxOverflow | RxFull))
-				outw(RxQueued, ioaddr + COMMAND);
-			if (status & PCIBusErr170) {
-				printk(KERN_ERR "%s: PCI Bus Error!  EPIC status %4.4x.\n",
-					   dev->name, status);
-				epic_pause(dev);
-				epic_restart(dev);
-			}
-			/* Clear all error sources. */
-			outl(status & 0x7f18, ioaddr + INTSTAT);
+	if ((status & EpicNapiEvent) && !ep->reschedule_in_poll) {
+		spin_lock(&ep->napi_lock);
+		if (netif_rx_schedule_prep(dev)) {
+			epic_napi_irq_off(dev, ep);
+			__netif_rx_schedule(dev);
+		} else
+			ep->reschedule_in_poll++;
+		spin_unlock(&ep->napi_lock);
+	}
+	status &= ~EpicNapiEvent;
+
+	/* Check uncommon events all at once. */
+	if (status & (CntFull | TxUnderrun | PCIBusErr170 | PCIBusErr175)) {
+		if (status == EpicRemoved)
+			goto out;
+
+		/* Always update the error counts to avoid overhead later. */
+		ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
+		ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
+		ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
+
+		if (status & TxUnderrun) { /* Tx FIFO underflow. */
+			ep->stats.tx_fifo_errors++;
+			outl(ep->tx_threshold += 128, ioaddr + TxThresh);
+			/* Restart the transmit process. */
+			outl(RestartTx, ioaddr + COMMAND);
 		}
-		if (--boguscnt < 0) {
-			printk(KERN_ERR "%s: Too much work at interrupt, "
-				   "IntrStatus=0x%8.8x.\n",
-				   dev->name, status);
-			/* Clear all interrupt sources. */
-			outl(0x0001ffff, ioaddr + INTSTAT);
-			break;
+		if (status & PCIBusErr170) {
+			printk(KERN_ERR "%s: PCI Bus Error! status %4.4x.\n",
+					 dev->name, status);
+			epic_pause(dev);
+			epic_restart(dev);
 		}
-	} while (1);
+		/* Clear all error sources. */
+		outl(status & 0x7f18, ioaddr + INTSTAT);
+	}
 
-	if (debug > 3)
-		printk(KERN_DEBUG "%s: exiting interrupt, intr_status=%#4.4x.\n",
-			   dev->name, status);
+out:
+	if (debug > 3) {
+		printk(KERN_DEBUG "%s: exit interrupt, intr_status=%#4.4x.\n",
+				   dev->name, status);
+	}
 
 	return IRQ_RETVAL(handled);
 }
 
-static int epic_rx(struct net_device *dev)
+static int epic_rx(struct net_device *dev, int budget)
 {
 	struct epic_private *ep = dev->priv;
 	int entry = ep->cur_rx % RX_RING_SIZE;
@@ -1171,6 +1229,10 @@ static int epic_rx(struct net_device *dev)
 	if (debug > 4)
 		printk(KERN_DEBUG " In epic_rx(), entry %d %8.8x.\n", entry,
 			   ep->rx_ring[entry].rxstatus);
+
+	if (rx_work_limit > budget)
+		rx_work_limit = budget;
+
 	/* If we own the next entry, it's a new packet. Send it up. */
 	while ((ep->rx_ring[entry].rxstatus & cpu_to_le32(DescOwn)) == 0) {
 		int status = le32_to_cpu(ep->rx_ring[entry].rxstatus);
@@ -1226,7 +1288,7 @@ static int epic_rx(struct net_device *dev)
 				ep->rx_skbuff[entry] = NULL;
 			}
 			skb->protocol = eth_type_trans(skb, dev);
-			netif_rx(skb);
+			netif_receive_skb(skb);
 			dev->last_rx = jiffies;
 			ep->stats.rx_packets++;
 			ep->stats.rx_bytes += pkt_len;
@@ -1254,6 +1316,65 @@ static int epic_rx(struct net_device *dev)
 	return work_done;
 }
 
+static void epic_rx_err(struct net_device *dev, struct epic_private *ep)
+{
+	long ioaddr = dev->base_addr;
+	int status;
+
+	status = inl(ioaddr + INTSTAT);
+
+	if (status == EpicRemoved)
+		return;
+	if (status & RxOverflow) 	/* Missed a Rx frame. */
+		ep->stats.rx_errors++;
+	if (status & (RxOverflow | RxFull))
+		outw(RxQueued, ioaddr + COMMAND);
+}
+
+static int epic_poll(struct net_device *dev, int *budget)
+{
+	struct epic_private *ep = dev->priv;
+	int work_done, orig_budget;
+	long ioaddr = dev->base_addr;
+
+	orig_budget = (*budget > dev->quota) ? dev->quota : *budget;
+
+rx_action:
+
+	epic_tx(dev, ep);
+
+	work_done = epic_rx(dev, *budget);
+
+	epic_rx_err(dev, ep);
+
+	*budget -= work_done;
+	dev->quota -= work_done;
+
+	if (netif_running(dev) && (work_done < orig_budget)) {
+		unsigned long flags;
+		int more;
+
+		/* A bit baroque but it avoids a (space hungry) spin_unlock */
+
+		spin_lock_irqsave(&ep->napi_lock, flags);
+
+		more = ep->reschedule_in_poll;
+		if (!more) {
+			__netif_rx_complete(dev);
+			outl(EpicNapiEvent, ioaddr + INTSTAT);
+			epic_napi_irq_on(dev, ep);
+		} else
+			ep->reschedule_in_poll--;
+
+		spin_unlock_irqrestore(&ep->napi_lock, flags);
+
+		if (more)
+			goto rx_action;
+	}
+
+	return (work_done >= orig_budget);
+}
+
 static int epic_close(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
@@ -1268,9 +1389,13 @@ static int epic_close(struct net_device *dev)
 			   dev->name, (int)inl(ioaddr + INTSTAT));
 
 	del_timer_sync(&ep->timer);
-	epic_pause(dev);
+
+	epic_disable_int(dev, ep);
+
 	free_irq(dev->irq, dev);
 
+	epic_pause(dev);
+
 	/* Free all the skbuffs in the Rx queue. */
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		skb = ep->rx_skbuff[i];
@@ -1491,6 +1616,7 @@ static void __devexit epic_remove_one (struct pci_dev *pdev)
 #endif
 	pci_release_regions(pdev);
 	free_netdev(dev);
+	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
 	/* pci_power_off(pdev, -1); */
 }
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 0ead66f20..8d39ca77b 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -75,6 +75,7 @@
  *			   added CK804/MCP04 device IDs, code fixes
  *			   for registers, link status and other minor fixes.
  *	0.28: 21 Jun 2004: Big cleanup, making driver mostly endian safe
+ *	0.29: 31 Aug 2004: Add backup timer for link change notification.
  *
  * Known bugs:
  * We suspect that on some hardware no TX done interrupts are generated.
@@ -86,7 +87,7 @@
  * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
  * superfluous timer interrupts from the nic.
  */
-#define FORCEDETH_VERSION		"0.28"
+#define FORCEDETH_VERSION		"0.29"
 #define DRV_NAME			"forcedeth"
 
 #include <linux/module.h>
@@ -120,10 +121,11 @@
  * Hardware access:
  */
 
-#define DEV_NEED_LASTPACKET1	0x0001
-#define DEV_IRQMASK_1		0x0002
-#define DEV_IRQMASK_2		0x0004
-#define DEV_NEED_TIMERIRQ	0x0008
+#define DEV_NEED_LASTPACKET1	0x0001	/* set LASTPACKET1 in tx flags */
+#define DEV_IRQMASK_1		0x0002  /* use NVREG_IRQMASK_WANTED_1 for irq mask */
+#define DEV_IRQMASK_2		0x0004  /* use NVREG_IRQMASK_WANTED_2 for irq mask */
+#define DEV_NEED_TIMERIRQ	0x0008  /* set the timer irq flag in the irq mask */
+#define DEV_NEED_LINKTIMER	0x0010	/* poll link settings. Relies on the timer irq */
 
 enum {
 	NvRegIrqStatus = 0x000,
@@ -367,6 +369,7 @@ struct ring_desc {
 
 #define OOM_REFILL	(1+HZ/20)
 #define POLL_WAIT	(1+HZ/100)
+#define LINK_TIMEOUT	(3*HZ)
 
 #define DESC_VER_1	0x0
 #define DESC_VER_2	0x02100
@@ -446,6 +449,11 @@ struct fe_priv {
 	struct timer_list oom_kick;
 	struct timer_list nic_poll;
 
+	/* media detection workaround.
+	 * Locking: Within irq hander or disable_irq+spin_lock(&np->lock);
+	 */
+	int need_linktimer;
+	unsigned long link_timeout;
 	/*
 	 * tx specific fields.
 	 */
@@ -1384,6 +1392,25 @@ set_speed:
 	return retval;
 }
 
+static void nv_linkchange(struct net_device *dev)
+{
+	if (nv_update_linkspeed(dev)) {
+		if (netif_carrier_ok(dev)) {
+			nv_stop_rx(dev);
+		} else {
+			netif_carrier_on(dev);
+			printk(KERN_INFO "%s: link up.\n", dev->name);
+		}
+		nv_start_rx(dev);
+	} else {
+		if (netif_carrier_ok(dev)) {
+			netif_carrier_off(dev);
+			printk(KERN_INFO "%s: link down.\n", dev->name);
+			nv_stop_rx(dev);
+		}
+	}
+}
+
 static void nv_link_irq(struct net_device *dev)
 {
 	u8 *base = get_hwbase(dev);
@@ -1391,25 +1418,10 @@ static void nv_link_irq(struct net_device *dev)
 
 	miistat = readl(base + NvRegMIIStatus);
 	writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus);
-	dprintk(KERN_DEBUG "%s: link change notification, status 0x%x.\n", dev->name, miistat);
+	dprintk(KERN_INFO "%s: link change irq, status 0x%x.\n", dev->name, miistat);
 
-	if (miistat & (NVREG_MIISTAT_LINKCHANGE)) {
-		if (nv_update_linkspeed(dev)) {
-			if (netif_carrier_ok(dev)) {
-				nv_stop_rx(dev);
-			} else {
-				netif_carrier_on(dev);
-				printk(KERN_INFO "%s: link up.\n", dev->name);
-			}
-			nv_start_rx(dev);
-		} else {
-			if (netif_carrier_ok(dev)) {
-				netif_carrier_off(dev);
-				printk(KERN_INFO "%s: link down.\n", dev->name);
-				nv_stop_rx(dev);
-			}
-		}
-	}
+	if (miistat & (NVREG_MIISTAT_LINKCHANGE))
+		nv_linkchange(dev);
 	dprintk(KERN_DEBUG "%s: link change notification done.\n", dev->name);
 }
 
@@ -1452,6 +1464,12 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
 			nv_link_irq(dev);
 			spin_unlock(&np->lock);
 		}
+		if (np->need_linktimer && time_after(jiffies, np->link_timeout)) {
+			spin_lock(&np->lock);
+			nv_linkchange(dev);
+			spin_unlock(&np->lock);
+			np->link_timeout = jiffies + LINK_TIMEOUT;
+		}
 		if (events & (NVREG_IRQ_TX_ERR)) {
 			dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n",
 						dev->name, events);
@@ -1816,6 +1834,14 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
 		np->irqmask = NVREG_IRQMASK_WANTED_2;
 	if (id->driver_data & DEV_NEED_TIMERIRQ)
 		np->irqmask |= NVREG_IRQ_TIMER;
+	if (id->driver_data & DEV_NEED_LINKTIMER) {
+		dprintk(KERN_INFO "%s: link timer on.\n", pci_name(pci_dev));
+		np->need_linktimer = 1;
+		np->link_timeout = jiffies + LINK_TIMEOUT;
+	} else {
+		dprintk(KERN_INFO "%s: link timer off.\n", pci_name(pci_dev));
+		np->need_linktimer = 0;
+	}
 
 	/* find a suitable phy */
 	for (i = 1; i < 32; i++) {
@@ -1909,21 +1935,21 @@ static struct pci_device_id pci_tbl[] = {
 		.device = PCI_DEVICE_ID_NVIDIA_NVENET_1,
 		.subvendor = PCI_ANY_ID,
 		.subdevice = PCI_ANY_ID,
-		.driver_data = DEV_IRQMASK_1|DEV_NEED_TIMERIRQ,
+		.driver_data = DEV_IRQMASK_1|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
 	},
 	{	/* nForce2 Ethernet Controller */
 		.vendor = PCI_VENDOR_ID_NVIDIA,
 		.device = PCI_DEVICE_ID_NVIDIA_NVENET_2,
 		.subvendor = PCI_ANY_ID,
 		.subdevice = PCI_ANY_ID,
-		.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ,
+		.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
 	},
 	{	/* nForce3 Ethernet Controller */
 		.vendor = PCI_VENDOR_ID_NVIDIA,
 		.device = PCI_DEVICE_ID_NVIDIA_NVENET_3,
 		.subvendor = PCI_ANY_ID,
 		.subdevice = PCI_ANY_ID,
-		.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ,
+		.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
 	},
 	{	/* nForce3 Ethernet Controller */
 		.vendor = PCI_VENDOR_ID_NVIDIA,
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 5005c1c94..a8ceee273 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -8,7 +8,7 @@
  * Author: Andy Fleming
  * Maintainer: Kumar Gala (kumar.gala@freescale.com)
  *
- * Copyright 2004 Freescale Semiconductor, Inc
+ * Copyright (c) 2002-2004 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 as published by the
@@ -96,20 +96,11 @@
 
 #include "gianfar.h"
 #include "gianfar_phy.h"
-#ifdef CONFIG_NET_FASTROUTE
-#include <linux/if_arp.h>
-#include <net/ip.h>
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,41)
-#define irqreturn_t void
-#define IRQ_HANDLED 
-#endif
 
 #define TX_TIMEOUT      (1*HZ)
 #define SKB_ALLOC_TIMEOUT 1000000
 #undef BRIEF_GFAR_ERRORS
-#define VERBOSE_GFAR_ERRORS
+#undef VERBOSE_GFAR_ERRORS
 
 #ifdef CONFIG_GFAR_NAPI
 #define RECEIVE(x) netif_receive_skb(x)
@@ -117,9 +108,8 @@
 #define RECEIVE(x) netif_rx(x)
 #endif
 
-#define DEVICE_NAME "%s: Gianfar Ethernet Controller Version 1.0, "
-char gfar_driver_name[] = "Gianfar Ethernet";
-char gfar_driver_version[] = "1.0";
+const char gfar_driver_name[] = "Gianfar Ethernet";
+const char gfar_driver_version[] = "1.1";
 
 int startup_gfar(struct net_device *dev);
 static int gfar_enet_open(struct net_device *dev);
@@ -148,24 +138,11 @@ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
 #ifdef CONFIG_GFAR_NAPI
 static int gfar_poll(struct net_device *dev, int *budget);
 #endif
-#ifdef CONFIG_NET_FASTROUTE
-static int gfar_accept_fastpath(struct net_device *dev, struct dst_entry *dst);
-#endif
-static inline int try_fastroute(struct sk_buff *skb, struct net_device *dev, int length);
-#ifdef CONFIG_GFAR_NAPI
 static int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
-#else
-static int gfar_clean_rx_ring(struct net_device *dev);
-#endif
 static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length);
+static void gfar_phy_startup_timer(unsigned long data);
 
 extern struct ethtool_ops gfar_ethtool_ops;
-extern void gfar_gstrings_normon(struct net_device *dev, u32 stringset, 
-		u8 * buf);
-extern void gfar_fill_stats_normon(struct net_device *dev, 
-		struct ethtool_stats *dummy, u64 * buf);
-extern int gfar_stats_count_normon(struct net_device *dev);
-
 
 MODULE_AUTHOR("Freescale Semiconductor, Inc");
 MODULE_DESCRIPTION("Gianfar Ethernet Driver");
@@ -183,7 +160,7 @@ static int gfar_probe(struct ocp_device *ocpdev)
 	struct ocp_gfar_data *einfo;
 	int idx;
 	int err = 0;
-	struct ethtool_ops *dev_ethtool_ops;
+	int dev_ethtool_ops = 0;
 
 	einfo = (struct ocp_gfar_data *) ocpdev->def->additions;
 
@@ -197,7 +174,8 @@ static int gfar_probe(struct ocp_device *ocpdev)
 	/* get a pointer to the register memory which can
 	 * configure the PHYs.  If it's different from this set,
 	 * get the device which has those regs */
-	if ((einfo->phyregidx >= 0) && (einfo->phyregidx != ocpdev->def->index)) {
+	if ((einfo->phyregidx >= 0) && 
+			(einfo->phyregidx != ocpdev->def->index)) {
 		mdiodev = ocp_find_device(OCP_ANY_ID,
 					  OCP_FUNC_GFAR, einfo->phyregidx);
 
@@ -222,7 +200,7 @@ static int gfar_probe(struct ocp_device *ocpdev)
 
 	/* get a pointer to the register memory */
 	priv->regs = (struct gfar *)
-	    ioremap(ocpdev->def->paddr, sizeof (struct gfar));
+		ioremap(ocpdev->def->paddr, sizeof (struct gfar));
 
 	if (priv->regs == NULL) {
 		err = -ENOMEM;
@@ -238,6 +216,8 @@ static int gfar_probe(struct ocp_device *ocpdev)
 		goto phy_regs_fail;
 	}
 
+	spin_lock_init(&priv->lock);
+
 	ocp_set_drvdata(ocpdev, dev);
 
 	/* Stop the DMA engine now, in case it was running before */
@@ -269,15 +249,13 @@ static int gfar_probe(struct ocp_device *ocpdev)
 	gfar_write(&priv->regs->ecntrl, ECNTRL_INIT_SETTINGS);
 
 	/* Copy the station address into the dev structure, */
-	/* and into the address registers MAC_STNADDR1,2. */
-	/* Backwards, because little endian MACs are dumb. */
-	/* Don't set the regs if the firmware already did */
 	memcpy(dev->dev_addr, einfo->mac_addr, MAC_ADDR_LEN);
 
 	/* Set the dev->base_addr to the gfar reg region */
 	dev->base_addr = (unsigned long) (priv->regs);
 
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &ocpdev->dev);
 
 	/* Fill in the dev structure */
 	dev->open = gfar_enet_open;
@@ -293,37 +271,16 @@ static int gfar_probe(struct ocp_device *ocpdev)
 	dev->change_mtu = gfar_change_mtu;
 	dev->mtu = 1500;
 	dev->set_multicast_list = gfar_set_multi;
-	dev->flags |= IFF_MULTICAST;
-
-	dev_ethtool_ops = 
-		(struct ethtool_ops *)kmalloc(sizeof(struct ethtool_ops), 
-					      GFP_KERNEL);
-
-	if(dev_ethtool_ops == NULL) {
-		err = -ENOMEM;
-		goto ethtool_fail;
-	}
-
-	memcpy(dev_ethtool_ops, &gfar_ethtool_ops, sizeof(gfar_ethtool_ops));
-
-	/* If there is no RMON support in this device, we don't
-	 * want to expose non-existant statistics */
-	if((priv->einfo->flags & GFAR_HAS_RMON) == 0) {
-		dev_ethtool_ops->get_strings = gfar_gstrings_normon;
-		dev_ethtool_ops->get_stats_count = gfar_stats_count_normon;
-		dev_ethtool_ops->get_ethtool_stats = gfar_fill_stats_normon;
-	}
 
-	if((priv->einfo->flags & GFAR_HAS_COALESCE) == 0) {
-		dev_ethtool_ops->set_coalesce = NULL;
-		dev_ethtool_ops->get_coalesce = NULL;
-	}
+	/* Index into the array of possible ethtool
+	 * ops to catch all 4 possibilities */
+	if((priv->einfo->flags & GFAR_HAS_RMON) == 0)
+		dev_ethtool_ops += 1;
 
-	dev->ethtool_ops = dev_ethtool_ops;
+	if((priv->einfo->flags & GFAR_HAS_COALESCE) == 0)
+		dev_ethtool_ops += 2;
 
-#ifdef CONFIG_NET_FASTROUTE
-	dev->accept_fastpath = gfar_accept_fastpath;
-#endif
+	dev->ethtool_ops = gfar_op_array[dev_ethtool_ops];
 
 	priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE;
 #ifdef CONFIG_GFAR_BUFSTASH
@@ -332,24 +289,23 @@ static int gfar_probe(struct ocp_device *ocpdev)
 	priv->tx_ring_size = DEFAULT_TX_RING_SIZE;
 	priv->rx_ring_size = DEFAULT_RX_RING_SIZE;
 
-	/* Initially, coalescing is disabled */
-	priv->txcoalescing = 0;
-	priv->txcount = 0;
-	priv->txtime = 0;
-	priv->rxcoalescing = 0;
-	priv->rxcount = 0;
-	priv->rxtime = 0;
+	priv->txcoalescing = DEFAULT_TX_COALESCE;
+	priv->txcount = DEFAULT_TXCOUNT;
+	priv->txtime = DEFAULT_TXTIME;
+	priv->rxcoalescing = DEFAULT_RX_COALESCE;
+	priv->rxcount = DEFAULT_RXCOUNT;
+	priv->rxtime = DEFAULT_RXTIME;
 
 	err = register_netdev(dev);
 
 	if (err) {
 		printk(KERN_ERR "%s: Cannot register net device, aborting.\n",
-		       dev->name);
+				dev->name);
 		goto register_fail;
 	}
 
 	/* Print out the device info */
-	printk(DEVICE_NAME, dev->name);
+	printk(KERN_INFO DEVICE_NAME, dev->name);
 	for (idx = 0; idx < 6; idx++)
 		printk("%2.2x%c", dev->dev_addr[idx], idx == 5 ? ' ' : ':');
 	printk("\n");
@@ -367,10 +323,7 @@ static int gfar_probe(struct ocp_device *ocpdev)
 
 	return 0;
 
-
 register_fail:
-	kfree(dev_ethtool_ops);
-ethtool_fail:
 	iounmap((void *) priv->phyregs);
 phy_regs_fail:
 	iounmap((void *) priv->regs);
@@ -386,7 +339,6 @@ static void gfar_remove(struct ocp_device *ocpdev)
 
 	ocp_set_drvdata(ocpdev, NULL);
 
-	kfree(dev->ethtool_ops);
 	iounmap((void *) priv->regs);
 	iounmap((void *) priv->phyregs);
 	free_netdev(dev);
@@ -399,26 +351,90 @@ static int init_phy(struct net_device *dev)
 {
 	struct gfar_private *priv = netdev_priv(dev);
 	struct phy_info *curphy;
+	unsigned int timeout = PHY_INIT_TIMEOUT;
+	struct gfar *phyregs = priv->phyregs;
+	struct gfar_mii_info *mii_info;
+	int err;
 
-	priv->link = 1;
 	priv->oldlink = 0;
 	priv->oldspeed = 0;
-	priv->olddplx = -1;
+	priv->oldduplex = -1;
+
+	mii_info = kmalloc(sizeof(struct gfar_mii_info),
+			GFP_KERNEL);
+
+	if(NULL == mii_info) {
+		printk(KERN_ERR "%s: Could not allocate mii_info\n", 
+				dev->name);
+		return -ENOMEM;
+	}
+
+	mii_info->speed = SPEED_1000;
+	mii_info->duplex = DUPLEX_FULL;
+	mii_info->pause = 0;
+	mii_info->link = 1;
+
+	mii_info->advertising = (ADVERTISED_10baseT_Half |
+			ADVERTISED_10baseT_Full |
+			ADVERTISED_100baseT_Half |
+			ADVERTISED_100baseT_Full |
+			ADVERTISED_1000baseT_Full);
+	mii_info->autoneg = 1;
+
+	mii_info->mii_id = priv->einfo->phyid;
+
+	mii_info->dev = dev;
+
+	mii_info->mdio_read = &read_phy_reg;
+	mii_info->mdio_write = &write_phy_reg;
+
+	priv->mii_info = mii_info;
+
+	/* Reset the management interface */
+	gfar_write(&phyregs->miimcfg, MIIMCFG_RESET);
+
+	/* Setup the MII Mgmt clock speed */
+	gfar_write(&phyregs->miimcfg, MIIMCFG_INIT_VALUE);
+
+	/* Wait until the bus is free */
+	while ((gfar_read(&phyregs->miimind) & MIIMIND_BUSY) &&
+			timeout--)
+		cpu_relax();
+
+	if(timeout <= 0) {
+		printk(KERN_ERR "%s: The MII Bus is stuck!\n",
+				dev->name);
+		err = -1;
+		goto bus_fail;
+	}
 
 	/* get info for this PHY */
-	curphy = get_phy_info(dev);
+	curphy = get_phy_info(priv->mii_info);
 
 	if (curphy == NULL) {
 		printk(KERN_ERR "%s: No PHY found\n", dev->name);
-		return -1;
+		err = -1;
+		goto no_phy;
 	}
 
-	priv->phyinfo = curphy;
+	mii_info->phyinfo = curphy;
 
-	/* Run the commands which configure the PHY */
-	phy_run_commands(dev, curphy->config);
+	/* Run the commands which initialize the PHY */
+	if(curphy->init) {
+		err = curphy->init(priv->mii_info);
+
+		if (err) 
+			goto phy_init_fail;
+	}
 
 	return 0;
+
+phy_init_fail:
+no_phy:
+bus_fail:
+	kfree(mii_info);
+
+	return err;
 }
 
 static void init_registers(struct net_device *dev)
@@ -494,7 +510,7 @@ void stop_gfar(struct net_device *dev)
 	spin_lock_irqsave(&priv->lock, flags);
 
 	/* Tell the kernel the link is down */
-	priv->link = 0;
+	priv->mii_info->link = 0;
 	adjust_link(dev);
 
 	/* Mask all interrupts */
@@ -521,7 +537,12 @@ void stop_gfar(struct net_device *dev)
 	gfar_write(&regs->maccfg1, tempval);
 
 	if (priv->einfo->flags & GFAR_HAS_PHY_INTR) {
-		phy_run_commands(dev, priv->phyinfo->shutdown);
+		/* Clear any pending interrupts */
+		mii_clear_phy_interrupt(priv->mii_info);
+
+		/* Disable PHY Interrupts */
+		mii_configure_phy_interrupt(priv->mii_info, 
+				MII_INTERRUPT_DISABLED);
 	}
 
 	spin_unlock_irqrestore(&priv->lock, flags);
@@ -543,15 +564,11 @@ void stop_gfar(struct net_device *dev)
 
 	free_skb_resources(priv);
 
-	dma_unmap_single(NULL, gfar_read(&regs->tbase),
-			sizeof(struct txbd)*priv->tx_ring_size,
-			DMA_BIDIRECTIONAL);
-	dma_unmap_single(NULL, gfar_read(&regs->rbase),
-			sizeof(struct rxbd)*priv->rx_ring_size,
-			DMA_BIDIRECTIONAL);
-
-	/* Free the buffer descriptors */
-	kfree(priv->tx_bd_base);
+	dma_free_coherent(NULL,
+			sizeof(struct txbd8)*priv->tx_ring_size
+			+ sizeof(struct rxbd8)*priv->rx_ring_size,
+			priv->tx_bd_base,
+			gfar_read(&regs->tbase));
 }
 
 /* If there are any tx skbs or rx skbs still around, free them.
@@ -610,7 +627,8 @@ int startup_gfar(struct net_device *dev)
 {
 	struct txbd8 *txbdp;
 	struct rxbd8 *rxbdp;
-	unsigned long addr;
+	dma_addr_t addr;
+	unsigned long vaddr;
 	int i;
 	struct gfar_private *priv = netdev_priv(dev);
 	struct gfar *regs = priv->regs;
@@ -620,32 +638,27 @@ int startup_gfar(struct net_device *dev)
 	gfar_write(&regs->imask, IMASK_INIT_CLEAR);
 
 	/* Allocate memory for the buffer descriptors */
-	addr =
-	    (unsigned int) kmalloc(sizeof (struct txbd8) * priv->tx_ring_size +
-				   sizeof (struct rxbd8) * priv->rx_ring_size,
-				   GFP_KERNEL);
+	vaddr = (unsigned long) dma_alloc_coherent(NULL, 
+			sizeof (struct txbd8) * priv->tx_ring_size +
+			sizeof (struct rxbd8) * priv->rx_ring_size,
+			&addr, GFP_KERNEL);
 
-	if (addr == 0) {
+	if (vaddr == 0) {
 		printk(KERN_ERR "%s: Could not allocate buffer descriptors!\n",
 		       dev->name);
 		return -ENOMEM;
 	}
 
-	priv->tx_bd_base = (struct txbd8 *) addr;
+	priv->tx_bd_base = (struct txbd8 *) vaddr;
 
 	/* enet DMA only understands physical addresses */
-	gfar_write(&regs->tbase, 
-			dma_map_single(NULL, (void *)addr, 
-				sizeof(struct txbd8) * priv->tx_ring_size,
-				DMA_BIDIRECTIONAL));
+	gfar_write(&regs->tbase, addr);
 
 	/* Start the rx descriptor ring where the tx ring leaves off */
 	addr = addr + sizeof (struct txbd8) * priv->tx_ring_size;
-	priv->rx_bd_base = (struct rxbd8 *) addr;
-	gfar_write(&regs->rbase, 
-			dma_map_single(NULL, (void *)addr, 
-				sizeof(struct rxbd8) * priv->rx_ring_size,
-				DMA_BIDIRECTIONAL));
+	vaddr = vaddr + sizeof (struct txbd8) * priv->tx_ring_size;
+	priv->rx_bd_base = (struct rxbd8 *) vaddr;
+	gfar_write(&regs->rbase, addr);
 
 	/* Setup the skbuff rings */
 	priv->tx_skbuff =
@@ -718,7 +731,7 @@ int startup_gfar(struct net_device *dev)
 		/* Install our interrupt handlers for Error, 
 		 * Transmit, and Receive */
 		if (request_irq(priv->einfo->interruptError, gfar_error,
-				SA_SHIRQ, "enet_error", dev) < 0) {
+				0, "enet_error", dev) < 0) {
 			printk(KERN_ERR "%s: Can't get IRQ %d\n",
 			       dev->name, priv->einfo->interruptError);
 
@@ -727,7 +740,7 @@ int startup_gfar(struct net_device *dev)
 		}
 
 		if (request_irq(priv->einfo->interruptTransmit, gfar_transmit,
-				SA_SHIRQ, "enet_tx", dev) < 0) {
+				0, "enet_tx", dev) < 0) {
 			printk(KERN_ERR "%s: Can't get IRQ %d\n",
 			       dev->name, priv->einfo->interruptTransmit);
 
@@ -737,7 +750,7 @@ int startup_gfar(struct net_device *dev)
 		}
 
 		if (request_irq(priv->einfo->interruptReceive, gfar_receive,
-				SA_SHIRQ, "enet_rx", dev) < 0) {
+				0, "enet_rx", dev) < 0) {
 			printk(KERN_ERR "%s: Can't get IRQ %d (receive0)\n",
 			       dev->name, priv->einfo->interruptReceive);
 
@@ -746,7 +759,7 @@ int startup_gfar(struct net_device *dev)
 		}
 	} else {
 		if (request_irq(priv->einfo->interruptTransmit, gfar_interrupt,
-				SA_SHIRQ, "gfar_interrupt", dev) < 0) {
+				0, "gfar_interrupt", dev) < 0) {
 			printk(KERN_ERR "%s: Can't get IRQ %d\n",
 			       dev->name, priv->einfo->interruptError);
 
@@ -755,39 +768,13 @@ int startup_gfar(struct net_device *dev)
 		}
 	}
 
-	/* Grab the PHY interrupt */
-	if (priv->einfo->flags & GFAR_HAS_PHY_INTR) {
-		if (request_irq(priv->einfo->interruptPHY, phy_interrupt,
-				SA_SHIRQ, "phy_interrupt", dev) < 0) {
-			printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n",
-			       dev->name, priv->einfo->interruptPHY);
-
-			err = -1;
-
-			if (priv->einfo->flags & GFAR_HAS_MULTI_INTR)
-				goto phy_irq_fail;
-			else
-				goto tx_irq_fail;
-		}
-	} else {
-		init_timer(&priv->phy_info_timer);
-		priv->phy_info_timer.function = &gfar_phy_timer;
-		priv->phy_info_timer.data = (unsigned long) dev;
-		mod_timer(&priv->phy_info_timer, jiffies + 2 * HZ);
-	}
-
-	/* Set up the bottom half queue */
-	INIT_WORK(&priv->tq, (void (*)(void *))gfar_phy_change, dev);
-
-	/* Configure the PHY interrupt */
-	phy_run_commands(dev, priv->phyinfo->startup);
-
-	/* Tell the kernel the link is up, and determine the
-	 * negotiated features (speed, duplex) */
-	adjust_link(dev);
+	/* Set up the PHY change work queue */
+	INIT_WORK(&priv->tq, gfar_phy_change, dev);
 
-	if (priv->link == 0)
-		printk(KERN_INFO "%s: No link detected\n", dev->name);
+	init_timer(&priv->phy_info_timer);
+	priv->phy_info_timer.function = &gfar_phy_startup_timer;
+	priv->phy_info_timer.data = (unsigned long) priv->mii_info;
+	mod_timer(&priv->phy_info_timer, jiffies + HZ);
 
 	/* Configure the coalescing support */
 	if (priv->txcoalescing)
@@ -827,8 +814,6 @@ int startup_gfar(struct net_device *dev)
 
 	return 0;
 
-phy_irq_fail:
-	free_irq(priv->einfo->interruptReceive, dev);
 rx_irq_fail:
 	free_irq(priv->einfo->interruptTransmit, dev);
 tx_irq_fail:
@@ -837,7 +822,17 @@ err_irq_fail:
 rx_skb_fail:
 	free_skb_resources(priv);
 tx_skb_fail:
-	kfree(priv->tx_bd_base);
+	dma_free_coherent(NULL,
+			sizeof(struct txbd8)*priv->tx_ring_size
+			+ sizeof(struct rxbd8)*priv->rx_ring_size,
+			priv->tx_bd_base,
+			gfar_read(&regs->tbase));
+
+	if (priv->mii_info->phyinfo->close)
+		priv->mii_info->phyinfo->close(priv->mii_info);
+
+	kfree(priv->mii_info);
+
 	return err;
 }
 
@@ -854,7 +849,7 @@ static int gfar_enet_open(struct net_device *dev)
 
 	err = init_phy(dev);
 
-	if (err)
+	if(err)
 		return err;
 
 	err = startup_gfar(dev);
@@ -934,8 +929,15 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
 /* Stops the kernel queue, and halts the controller */
 static int gfar_close(struct net_device *dev)
 {
+	struct gfar_private *priv = netdev_priv(dev);
 	stop_gfar(dev);
 
+	/* Shutdown the PHY */
+	if (priv->mii_info->phyinfo->close)
+		priv->mii_info->phyinfo->close(priv->mii_info);
+
+	kfree(priv->mii_info);
+
 	netif_stop_queue(dev);
 
 	return 0;
@@ -971,121 +973,6 @@ int gfar_set_mac_address(struct net_device *dev)
 	return 0;
 }
 
-/**********************************************************************
- * gfar_accept_fastpath
- *
- * Used to authenticate to the kernel that a fast path entry can be
- * added to device's routing table cache
- *
- * Input : pointer to ethernet interface network device structure and
- *         a pointer to the designated entry to be added to the cache.
- * Output : zero upon success, negative upon failure
- **********************************************************************/
-#ifdef CONFIG_NET_FASTROUTE
-static int gfar_accept_fastpath(struct net_device *dev, struct dst_entry *dst)
-{
-	struct net_device *odev = dst->dev;
-
-	if ((dst->ops->protocol != __constant_htons(ETH_P_IP))
-			|| (odev->type != ARPHRD_ETHER) 
-			|| (odev->accept_fastpath == NULL)) {
-		return -1;
-	}
-
-	return 0;
-}
-#endif
-
-/* try_fastroute() -- Checks the fastroute cache to see if a given packet
- *   can be routed immediately to another device.  If it can, we send it.
- *   If we used a fastroute, we return 1.  Otherwise, we return 0.
- *   Returns 0 if CONFIG_NET_FASTROUTE is not on
- */
-static inline int try_fastroute(struct sk_buff *skb, struct net_device *dev, int length)
-{
-#ifdef CONFIG_NET_FASTROUTE
-	struct ethhdr *eth;
-	struct iphdr *iph;
-	unsigned int hash;
-	struct rtable *rt;
-	struct net_device *odev;
-	struct gfar_private *priv = netdev_priv(dev);
-	unsigned int CPU_ID = smp_processor_id();
-
-	eth = (struct ethhdr *) (skb->data);
-
-	/* Only route ethernet IP packets */
-	if (eth->h_proto == __constant_htons(ETH_P_IP)) {
-		iph = (struct iphdr *) (skb->data + ETH_HLEN);
-
-		/* Generate the hash value */
-		hash = ((*(u8 *) &iph->daddr) ^ (*(u8 *) & iph->saddr)) & NETDEV_FASTROUTE_HMASK;
-
-		rt = (struct rtable *) (dev->fastpath[hash]);
-		if (rt != NULL 
-				&& ((*(u32 *) &iph->daddr) == (*(u32 *) &rt->key.dst))
-				&& ((*(u32 *) &iph->saddr) == (*(u32 *) &rt->key.src))
-				&& !(rt->u.dst.obsolete)) {
-			odev = rt->u.dst.dev;
-			netdev_rx_stat[CPU_ID].fastroute_hit++;
-
-			/* Make sure the packet is:
-			 * 1) IPv4
-			 * 2) without any options (header length of 5)
-			 * 3) Not a multicast packet
-			 * 4) going to a valid destination
-			 * 5) Not out of time-to-live
-			 */
-			if (iph->version == 4 
-					&& iph->ihl == 5 
-					&& (!(eth->h_dest[0] & 0x01)) 
-					&& neigh_is_valid(rt->u.dst.neighbour) 
-					&& iph->ttl > 1) {
-
-				/* Fast Route Path: Taken if the outgoing device is ready to transmit the packet now */
-				if ((!netif_queue_stopped(odev)) 
-						&& (!spin_is_locked(odev->xmit_lock)) 
-						&& (skb->len <= (odev->mtu + ETH_HLEN + 2 + 4))) {
-
-					skb->pkt_type = PACKET_FASTROUTE;
-					skb->protocol = __constant_htons(ETH_P_IP);
-					ip_decrease_ttl(iph);
-					memcpy(eth->h_source, odev->dev_addr, MAC_ADDR_LEN);
-					memcpy(eth->h_dest, rt->u.dst.neighbour->ha, MAC_ADDR_LEN);
-					skb->dev = odev;
-
-					/* Prep the skb for the packet */
-					skb_put(skb, length);
-
-					if (odev->hard_start_xmit(skb, odev) != 0) {
-						panic("%s: FastRoute path corrupted", dev->name);
-					}
-					netdev_rx_stat[CPU_ID].fastroute_success++;
-				}
-
-				/* Semi Fast Route Path: Mark the packet as needing fast routing, but let the
-				 * stack handle getting it to the device */
-				else {
-					skb->pkt_type = PACKET_FASTROUTE;
-					skb->nh.raw = skb->data + ETH_HLEN;
-					skb->protocol = __constant_htons(ETH_P_IP);
-					netdev_rx_stat[CPU_ID].fastroute_defer++;
-
-					/* Prep the skb for the packet */
-					skb_put(skb, length);
-
-					if(RECEIVE(skb) == NET_RX_DROP) {
-						priv->extra_stats.kernel_dropped++;
-					}
-				}
-
-				return 1;
-			}
-		}
-	}
-#endif /* CONFIG_NET_FASTROUTE */
-	return 0;
-}
 
 static int gfar_change_mtu(struct net_device *dev, int new_mtu)
 {
@@ -1148,8 +1035,7 @@ static void gfar_timeout(struct net_device *dev)
 		startup_gfar(dev);
 	}
 
-	if (!netif_queue_stopped(dev))
-		netif_schedule(dev);
+	netif_schedule(dev);
 }
 
 /* Interrupt Handler for Transmit complete */
@@ -1315,7 +1201,7 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs)
 #else
 
 	spin_lock(&priv->lock);
-	gfar_clean_rx_ring(dev);
+	gfar_clean_rx_ring(dev, priv->rx_ring_size);
 
 	/* If we are coalescing interrupts, update the timer */
 	/* Otherwise, clear it */
@@ -1336,7 +1222,7 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs)
 
 
 /* gfar_process_frame() -- handle one incoming packet if skb
- * isn't NULL.  Try the fastroute before using the stack */
+ * isn't NULL.  */
 static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
 		int length)
 {
@@ -1350,17 +1236,15 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
 		priv->stats.rx_dropped++;
 		priv->extra_stats.rx_skbmissing++;
 	} else {
-		if(try_fastroute(skb, dev, length) == 0) {
-			/* Prep the skb for the packet */
-			skb_put(skb, length);
+		/* Prep the skb for the packet */
+		skb_put(skb, length);
 
-			/* Tell the skb what kind of packet this is */
-			skb->protocol = eth_type_trans(skb, dev);
+		/* Tell the skb what kind of packet this is */
+		skb->protocol = eth_type_trans(skb, dev);
 
-			/* Send the packet up the stack */
-			if (RECEIVE(skb) == NET_RX_DROP) {
-				priv->extra_stats.kernel_dropped++;
-			}
+		/* Send the packet up the stack */
+		if (RECEIVE(skb) == NET_RX_DROP) {
+			priv->extra_stats.kernel_dropped++;
 		}
 	}
 
@@ -1368,14 +1252,10 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
 }
 
 /* gfar_clean_rx_ring() -- Processes each frame in the rx ring
- *   until all are gone (or, in the case of NAPI, the budget/quota
- *   has been reached). Returns the number of frames handled
+ *   until the budget/quota has been reached. Returns the number 
+ *   of frames handled
  */
-#ifdef CONFIG_GFAR_NAPI
 static int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
-#else
-static int gfar_clean_rx_ring(struct net_device *dev)
-#endif
 {
 	struct rxbd8 *bdp;
 	struct sk_buff *skb;
@@ -1386,12 +1266,7 @@ static int gfar_clean_rx_ring(struct net_device *dev)
 	/* Get the first full descriptor */
 	bdp = priv->cur_rx;
 
-#ifdef CONFIG_GFAR_NAPI
-#define GFAR_RXDONE() ((bdp->status & RXBD_EMPTY) || (--rx_work_limit < 0))
-#else
-#define GFAR_RXDONE() (bdp->status & RXBD_EMPTY)
-#endif
-	while (!GFAR_RXDONE()) {
+	while (!((bdp->status & RXBD_EMPTY) || (--rx_work_limit < 0))) {
 		skb = priv->rx_skbuff[priv->skb_currx];
 
 		if (!(bdp->status &
@@ -1407,7 +1282,6 @@ static int gfar_clean_rx_ring(struct net_device *dev)
 			gfar_process_frame(dev, skb, pkt_len);
 
 			priv->stats.rx_bytes += pkt_len;
-
 		} else {
 			count_errors(bdp->status, priv);
 
@@ -1462,7 +1336,6 @@ static int gfar_poll(struct net_device *dev, int *budget)
 	if (rx_work_limit > dev->quota)
 		rx_work_limit = dev->quota;
 
-	spin_lock(&priv->lock);
 	howmany = gfar_clean_rx_ring(dev, rx_work_limit);
 
 	dev->quota -= howmany;
@@ -1489,8 +1362,6 @@ static int gfar_poll(struct net_device *dev, int *budget)
 		priv->rxclean = 1;
 	}
 
-	spin_unlock(priv->lock);
-
 	return (rx_work_limit < 0) ? 1 : 0;
 }
 #endif
@@ -1586,10 +1457,14 @@ static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct gfar_private *priv = netdev_priv(dev);
 
-	/* Run the commands which acknowledge the interrupt */
-	phy_run_commands(dev, priv->phyinfo->ack_int);
+	/* Clear the interrupt */
+	mii_clear_phy_interrupt(priv->mii_info);
+
+	/* Disable PHY interrupts */
+	mii_configure_phy_interrupt(priv->mii_info,
+			MII_INTERRUPT_DISABLED);
 
-	/* Schedule the bottom half */
+	/* Schedule the phy change */
 	schedule_work(&priv->tq);
 
 	return IRQ_HANDLED;
@@ -1600,18 +1475,24 @@ static void gfar_phy_change(void *data)
 {
 	struct net_device *dev = (struct net_device *) data;
 	struct gfar_private *priv = netdev_priv(dev);
-	int timeout = HZ / 1000 + 1;
+	int result = 0;
 
 	/* Delay to give the PHY a chance to change the
 	 * register state */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(timeout);
+	msleep(1);
 
-	/* Run the commands which check the link state */
-	phy_run_commands(dev, priv->phyinfo->handle_int);
+	/* Update the link, speed, duplex */
+	result = priv->mii_info->phyinfo->read_status(priv->mii_info);
 
-	/* React to the change in state */
-	adjust_link(dev);
+	/* Adjust the known status as long as the link
+	 * isn't still coming up */
+	if((0 == result) || (priv->mii_info->link == 0))
+		adjust_link(dev);
+
+	/* Reenable interrupts, if needed */
+	if (priv->einfo->flags & GFAR_HAS_PHY_INTR)
+		mii_configure_phy_interrupt(priv->mii_info,
+				MII_INTERRUPT_ENABLED);
 }
 
 /* Called every so often on systems that don't interrupt
@@ -1623,7 +1504,72 @@ static void gfar_phy_timer(unsigned long data)
 
 	schedule_work(&priv->tq);
 
-	mod_timer(&priv->phy_info_timer, jiffies + 2 * HZ);
+	mod_timer(&priv->phy_info_timer, jiffies +
+			GFAR_PHY_CHANGE_TIME * HZ);
+}
+
+/* Keep trying aneg for some time
+ * If, after GFAR_AN_TIMEOUT seconds, it has not
+ * finished, we switch to forced.
+ * Either way, once the process has completed, we either
+ * request the interrupt, or switch the timer over to 
+ * using gfar_phy_timer to check status */
+static void gfar_phy_startup_timer(unsigned long data)
+{
+	int result;
+	static int secondary = GFAR_AN_TIMEOUT;
+	struct gfar_mii_info *mii_info = (struct gfar_mii_info *)data;
+	struct gfar_private *priv = netdev_priv(mii_info->dev);
+
+	/* Configure the Auto-negotiation */
+	result = mii_info->phyinfo->config_aneg(mii_info);
+
+	/* If autonegotiation failed to start, and
+	 * we haven't timed out, reset the timer, and return */
+	if (result && secondary--) {
+		mod_timer(&priv->phy_info_timer, jiffies + HZ);
+		return;
+	} else if (result) {
+		/* Couldn't start autonegotiation.
+		 * Try switching to forced */
+		mii_info->autoneg = 0;
+		result = mii_info->phyinfo->config_aneg(mii_info);
+
+		/* Forcing failed!  Give up */
+		if(result) {
+			printk(KERN_ERR "%s: Forcing failed!\n",
+					mii_info->dev->name);
+			return;
+		}
+	}
+
+	/* Kill the timer so it can be restarted */
+	del_timer_sync(&priv->phy_info_timer);
+
+	/* Grab the PHY interrupt, if necessary/possible */
+	if (priv->einfo->flags & GFAR_HAS_PHY_INTR) {
+		if (request_irq(priv->einfo->interruptPHY, 
+					phy_interrupt,
+					SA_SHIRQ, 
+					"phy_interrupt", 
+					mii_info->dev) < 0) {
+			printk(KERN_ERR "%s: Can't get IRQ %d (PHY)\n",
+					mii_info->dev->name,
+					priv->einfo->interruptPHY);
+		} else {
+			mii_configure_phy_interrupt(priv->mii_info, 
+					MII_INTERRUPT_ENABLED);
+			return;
+		}
+	}
+
+	/* Start the timer again, this time in order to
+	 * handle a change in status */
+	init_timer(&priv->phy_info_timer);
+	priv->phy_info_timer.function = &gfar_phy_timer;
+	priv->phy_info_timer.data = (unsigned long) mii_info->dev;
+	mod_timer(&priv->phy_info_timer, jiffies +
+			GFAR_PHY_CHANGE_TIME * HZ);
 }
 
 /* Called every time the controller might need to be made
@@ -1637,12 +1583,13 @@ static void adjust_link(struct net_device *dev)
 	struct gfar_private *priv = netdev_priv(dev);
 	struct gfar *regs = priv->regs;
 	u32 tempval;
+	struct gfar_mii_info *mii_info = priv->mii_info;
 
-	if (priv->link) {
+	if (mii_info->link) {
 		/* Now we make sure that we can be in full duplex mode.
 		 * If not, we operate in half-duplex mode. */
-		if (priv->duplexity != priv->olddplx) {
-			if (!(priv->duplexity)) {
+		if (mii_info->duplex != priv->oldduplex) {
+			if (!(mii_info->duplex)) {
 				tempval = gfar_read(&regs->maccfg2);
 				tempval &= ~(MACCFG2_FULL_DUPLEX);
 				gfar_write(&regs->maccfg2, tempval);
@@ -1658,11 +1605,11 @@ static void adjust_link(struct net_device *dev)
 				       dev->name);
 			}
 
-			priv->olddplx = priv->duplexity;
+			priv->oldduplex = mii_info->duplex;
 		}
 
-		if (priv->speed != priv->oldspeed) {
-			switch (priv->speed) {
+		if (mii_info->speed != priv->oldspeed) {
+			switch (mii_info->speed) {
 			case 1000:
 				tempval = gfar_read(&regs->maccfg2);
 				tempval =
@@ -1679,14 +1626,14 @@ static void adjust_link(struct net_device *dev)
 			default:
 				printk(KERN_WARNING
 				       "%s: Ack!  Speed (%d) is not 10/100/1000!\n",
-				       dev->name, priv->speed);
+				       dev->name, mii_info->speed);
 				break;
 			}
 
 			printk(KERN_INFO "%s: Speed %dBT\n", dev->name,
-			       priv->speed);
+			       mii_info->speed);
 
-			priv->oldspeed = priv->speed;
+			priv->oldspeed = mii_info->speed;
 		}
 
 		if (!priv->oldlink) {
@@ -1700,15 +1647,10 @@ static void adjust_link(struct net_device *dev)
 			printk(KERN_INFO "%s: Link is down\n", dev->name);
 			priv->oldlink = 0;
 			priv->oldspeed = 0;
-			priv->olddplx = -1;
+			priv->oldduplex = -1;
 			netif_carrier_off(dev);
 		}
 	}
-
-#ifdef VERBOSE_GFAR_ERRORS
-	printk(KERN_INFO "%s: Link now %s; %dBT %s-duplex\n",
-	       dev->name, priv->link ? "up" : "down", priv->speed, priv->duplexity ? "full" : "half");
-#endif
 }
 
 
@@ -1905,11 +1847,7 @@ static int __init gfar_init(void)
 	int rc;
 
 	rc = ocp_register_driver(&gfar_driver);
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41)
 	if (rc != 0) {
-#else
-	if (rc == 0) {
-#endif
 		ocp_unregister_driver(&gfar_driver);
 		return -ENODEV;
 	}
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index f7af3465c..91eaab35d 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -8,7 +8,7 @@
  * Author: Andy Fleming
  * Maintainer: Kumar Gala (kumar.gala@freescale.com)
  *
- * Copyright 2004 Freescale Semiconductor, Inc
+ * Copyright (c) 2002-2004 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 as published by the
@@ -17,6 +17,8 @@
  *
  *  Still left to do:
  *      -Add support for module parameters
+ *	-Add support for ethtool -s
+ *	-Add patch for ethtool phys id
  */
 #ifndef __GIANFAR_H
 #define __GIANFAR_H
@@ -42,15 +44,7 @@
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/crc32.h>
-
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41)
 #include <linux/workqueue.h>
-#else
-#include <linux/tqueue.h>
-#define work_struct tq_struct
-#define schedule_work schedule_task
-#endif
-
 #include <linux/ethtool.h>
 #include <linux/netdevice.h>
 #include <asm/ocp.h>
@@ -70,8 +64,13 @@
 
 #define MAC_ADDR_LEN 6
 
-extern char gfar_driver_name[];
-extern char gfar_driver_version[];
+#define PHY_INIT_TIMEOUT 100000
+#define GFAR_PHY_CHANGE_TIME 2
+
+#define DEVICE_NAME "%s: Gianfar Ethernet Controller Version 1.1, "
+#define DRV_NAME "gfar-enet"
+extern const char gfar_driver_name[];
+extern const char gfar_driver_version[];
 
 /* These need to be powers of 2 for this driver */
 #ifdef CONFIG_GFAR_NAPI
@@ -105,11 +104,13 @@ extern char gfar_driver_version[];
 #define GFAR_100_TIME   2560
 #define GFAR_10_TIME    25600
 
+#define DEFAULT_TX_COALESCE 1
 #define DEFAULT_TXCOUNT	16
-#define DEFAULT_TXTIME	32768
+#define DEFAULT_TXTIME	400
 
+#define DEFAULT_RX_COALESCE 1
 #define DEFAULT_RXCOUNT	16
-#define DEFAULT_RXTIME	32768
+#define DEFAULT_RXTIME	400
 
 #define TBIPA_VALUE		0x1f
 #define MIIMCFG_INIT_VALUE	0x00000007
@@ -467,8 +468,7 @@ struct gfar {
  * empty and completely full conditions.  The empty/ready indicator in
  * the buffer descriptor determines the actual condition.
  */
-struct gfar_private
-{
+struct gfar_private {
 	/* pointers to arrays of skbuffs for tx and rx */
 	struct sk_buff ** tx_skbuff;
 	struct sk_buff ** rx_skbuff;
@@ -496,7 +496,6 @@ struct gfar_private
 	struct txbd8 *cur_tx;	        /* Next free ring entry */
 	struct txbd8 *dirty_tx;		/* The Ring entry to be freed. */
 	struct gfar *regs;	/* Pointer to the GFAR memory mapped Registers */
-	struct phy_info *phyinfo;
 	struct gfar *phyregs;
 	struct work_struct tq;
 	struct timer_list phy_info_timer;
@@ -509,15 +508,14 @@ struct gfar_private
 	unsigned int rx_ring_size;
 	wait_queue_head_t rxcleanupq;
 	unsigned int rxclean;
-	int link;	/* current link state */
-	int oldlink;
-	int duplexity; /* Indicates negotiated duplex state */
-	int olddplx;
-	int speed;	/* Indicates negotiated speed */
-	int oldspeed;
-	
+
 	/* Info structure initialized by board setup code */
 	struct ocp_gfar_data *einfo;
+
+	struct gfar_mii_info *mii_info;
+	int oldspeed;
+	int oldduplex;
+	int oldlink;
 };
 
 extern inline u32 gfar_read(volatile unsigned *addr)
@@ -532,6 +530,6 @@ extern inline void gfar_write(volatile unsigned *addr, u32 val)
 	out_be32(addr, val);
 }
 
-
+extern struct ethtool_ops *gfar_op_array[];
 
 #endif /* __GIANFAR_H */
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index 4ccb5afd6..14ab0b217 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -1,18 +1,18 @@
 /*
- * drivers/net/gianfar_ethtool.c
+ *  drivers/net/gianfar_ethtool.c
  *
- * Gianfar Ethernet Driver
- * Ethtool support for Gianfar Enet
- * Based on e1000 ethtool support
+ *  Gianfar Ethernet Driver
+ *  Ethtool support for Gianfar Enet
+ *  Based on e1000 ethtool support
  *
- * Author: Andy Fleming
- * Maintainer: Kumar Gala (kumar.gala@freescale.com)
+ *  Author: Andy Fleming
+ *  Maintainer: Kumar Gala (kumar.gala@freescale.com)
  *
- * Copyright 2004 Freescale Semiconductor, Inc
+ *  Copyright (c) 2003,2004 Freescale Semiconductor, Inc.
  *
- * This software may be used and distributed according to 
- * the terms of the GNU Public License, Version 2, incorporated herein 
- * by reference.
+ *  This software may be used and distributed according to 
+ *  the terms of the GNU Public License, Version 2, incorporated herein 
+ *  by reference.
  */
 
 #include <linux/config.h>
@@ -58,64 +58,64 @@ int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals);
 void gfar_gdrvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo);
 
 static char stat_gstrings[][ETH_GSTRING_LEN] = {
-	"RX Dropped by Kernel",
-	"RX Large Frame Errors",
-	"RX Short Frame Errors",
-	"RX Non-Octet Errors",
-	"RX CRC Errors",
-	"RX Overrun Errors",
-	"RX Busy Errors",
-	"RX Babbling Errors",
-	"RX Truncated Frames",
-	"Ethernet Bus Error",
-	"TX Babbling Errors",
-	"TX Underrun Errors",
-	"RX SKB Missing Errors",
-	"TX Timeout Errors",
-	"tx&rx 64B frames",
-	"tx&rx 65-127B frames",
-	"tx&rx 128-255B frames",
-	"tx&rx 256-511B frames",
-	"tx&rx 512-1023B frames",
-	"tx&rx 1024-1518B frames",
-	"tx&rx 1519-1522B Good VLAN",
-	"RX bytes",
-	"RX Packets",
-	"RX FCS Errors",
-	"Receive Multicast Packet",
-	"Receive Broadcast Packet",
-	"RX Control Frame Packets",
-	"RX Pause Frame Packets",
-	"RX Unknown OP Code",
-	"RX Alignment Error",
-	"RX Frame Length Error",
-	"RX Code Error",
-	"RX Carrier Sense Error",
-	"RX Undersize Packets",
-	"RX Oversize Packets",
-	"RX Fragmented Frames",
-	"RX Jabber Frames",
-	"RX Dropped Frames",
-	"TX Byte Counter",
-	"TX Packets",
-	"TX Multicast Packets",
-	"TX Broadcast Packets",
-	"TX Pause Control Frames",
-	"TX Deferral Packets",
-	"TX Excessive Deferral Packets",
-	"TX Single Collision Packets",
-	"TX Multiple Collision Packets",
-	"TX Late Collision Packets",
-	"TX Excessive Collision Packets",
-	"TX Total Collision",
-	"RESERVED",
-	"TX Dropped Frames",
-	"TX Jabber Frames",
-	"TX FCS Errors",
-	"TX Control Frames",
-	"TX Oversize Frames",
-	"TX Undersize Frames",
-	"TX Fragmented Frames",
+	"rx-dropped-by-kernel",
+	"rx-large-frame-errors",
+	"rx-short-frame-errors",
+	"rx-non-octet-errors",
+	"rx-crc-errors",
+	"rx-overrun-errors",
+	"rx-busy-errors",
+	"rx-babbling-errors",
+	"rx-truncated-frames",
+	"ethernet-bus-error",
+	"tx-babbling-errors",
+	"tx-underrun-errors",
+	"rx-skb-missing-errors",
+	"tx-timeout-errors",
+	"tx-rx-64-frames",
+	"tx-rx-65-127-frames",
+	"tx-rx-128-255-frames",
+	"tx-rx-256-511-frames",
+	"tx-rx-512-1023-frames",
+	"tx-rx-1024-1518-frames",
+	"tx-rx-1519-1522-good-vlan",
+	"rx-bytes",
+	"rx-packets",
+	"rx-fcs-errors",
+	"receive-multicast-packet",
+	"receive-broadcast-packet",
+	"rx-control-frame-packets",
+	"rx-pause-frame-packets",
+	"rx-unknown-op-code",
+	"rx-alignment-error",
+	"rx-frame-length-error",
+	"rx-code-error",
+	"rx-carrier-sense-error",
+	"rx-undersize-packets",
+	"rx-oversize-packets",
+	"rx-fragmented-frames",
+	"rx-jabber-frames",
+	"rx-dropped-frames",
+	"tx-byte-counter",
+	"tx-packets",
+	"tx-multicast-packets",
+	"tx-broadcast-packets",
+	"tx-pause-control-frames",
+	"tx-deferral-packets",
+	"tx-excessive-deferral-packets",
+	"tx-single-collision-packets",
+	"tx-multiple-collision-packets",
+	"tx-late-collision-packets",
+	"tx-excessive-collision-packets",
+	"tx-total-collision",
+	"reserved",
+	"tx-dropped-frames",
+	"tx-jabber-frames",
+	"tx-fcs-errors",
+	"tx-control-frames",
+	"tx-oversize-frames",
+	"tx-undersize-frames",
+	"tx-fragmented-frames",
 };
 
 /* Fill in an array of 64-bit statistics from various sources.
@@ -125,7 +125,7 @@ static char stat_gstrings[][ETH_GSTRING_LEN] = {
 void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, u64 * buf)
 {
 	int i;
-	struct gfar_private *priv = (struct gfar_private *) dev->priv;
+	struct gfar_private *priv = netdev_priv(dev);
 	u32 *rmon = (u32 *) & priv->regs->rmon;
 	u64 *extra = (u64 *) & priv->extra_stats;
 	struct gfar_stats *stats = (struct gfar_stats *) buf;
@@ -154,7 +154,7 @@ void gfar_fill_stats_normon(struct net_device *dev,
 		struct ethtool_stats *dummy, u64 * buf)
 {
 	int i;
-	struct gfar_private *priv = (struct gfar_private *) dev->priv;
+	struct gfar_private *priv = netdev_priv(dev);
 	u64 *extra = (u64 *) & priv->extra_stats;
 
 	for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) {
@@ -171,7 +171,7 @@ int gfar_stats_count_normon(struct net_device *dev)
 void gfar_gdrvinfo(struct net_device *dev, struct
 	      ethtool_drvinfo *drvinfo)
 {
-	strncpy(drvinfo->driver, gfar_driver_name, GFAR_INFOSTR_LEN);
+	strncpy(drvinfo->driver, DRV_NAME, GFAR_INFOSTR_LEN);
 	strncpy(drvinfo->version, gfar_driver_version, GFAR_INFOSTR_LEN);
 	strncpy(drvinfo->fw_version, "N/A", GFAR_INFOSTR_LEN);
 	strncpy(drvinfo->bus_info, "N/A", GFAR_INFOSTR_LEN);
@@ -184,7 +184,7 @@ void gfar_gdrvinfo(struct net_device *dev, struct
 /* Return the current settings in the ethtool_cmd structure */
 int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-	struct gfar_private *priv = (struct gfar_private *) dev->priv;
+	struct gfar_private *priv = netdev_priv(dev);
 	uint gigabit_support = 
 		priv->einfo->flags & GFAR_HAS_GIGABIT ? SUPPORTED_1000baseT_Full : 0;
 	uint gigabit_advert = 
@@ -201,10 +201,10 @@ int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd)
 			    | ADVERTISED_100baseT_Full
 			    | gigabit_advert | ADVERTISED_Autoneg);
 
-	cmd->speed = priv->speed;
-	cmd->duplex = priv->duplexity;
+	cmd->speed = priv->mii_info->speed;
+	cmd->duplex = priv->mii_info->duplex;
 	cmd->port = PORT_MII;
-	cmd->phy_address = priv->einfo->phyid;
+	cmd->phy_address = priv->mii_info->mii_id;
 	cmd->transceiver = XCVR_EXTERNAL;
 	cmd->autoneg = AUTONEG_ENABLE;
 	cmd->maxtxpkt = priv->txcount;
@@ -223,7 +223,7 @@ int gfar_reglen(struct net_device *dev)
 void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf)
 {
 	int i;
-	struct gfar_private *priv = (struct gfar_private *) dev->priv;
+	struct gfar_private *priv = netdev_priv(dev);
 	u32 *theregs = (u32 *) priv->regs;
 	u32 *buf = (u32 *) regbuf;
 
@@ -231,13 +231,6 @@ void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regb
 		buf[i] = theregs[i];
 }
 
-/* Return the link state 1 is up, 0 is down */
-u32 gfar_get_link(struct net_device *dev)
-{
-	struct gfar_private *priv = (struct gfar_private *) dev->priv;
-	return (u32) priv->link;
-}
-
 /* Fill in a buffer with the strings which correspond to the
  * stats */
 void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf)
@@ -252,7 +245,7 @@ static unsigned int gfar_usecs2ticks(struct gfar_private *priv, unsigned int use
 	unsigned int count;
 
 	/* The timer is different, depending on the interface speed */
-	switch (priv->speed) {
+	switch (priv->mii_info->speed) {
 	case 1000:
 		count = GFAR_GBIT_TIME;
 		break;
@@ -276,7 +269,7 @@ static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int tic
 	unsigned int count;
 
 	/* The timer is different, depending on the interface speed */
-	switch (priv->speed) {
+	switch (priv->mii_info->speed) {
 	case 1000:
 		count = GFAR_GBIT_TIME;
 		break;
@@ -298,7 +291,7 @@ static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int tic
  * structure.  */
 int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals)
 {
-	struct gfar_private *priv = (struct gfar_private *) dev->priv;
+	struct gfar_private *priv = netdev_priv(dev);
 
 	cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, priv->rxtime);
 	cvals->rx_max_coalesced_frames = priv->rxcount;
@@ -344,7 +337,7 @@ int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals)
  */
 int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals)
 {
-	struct gfar_private *priv = (struct gfar_private *) dev->priv;
+	struct gfar_private *priv = netdev_priv(dev);
 
 	/* Set up rx coalescing */
 	if ((cvals->rx_coalesce_usecs == 0) ||
@@ -386,7 +379,7 @@ int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals)
  * jumbo are ignored by the driver */
 void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals)
 {
-	struct gfar_private *priv = (struct gfar_private *) dev->priv;
+	struct gfar_private *priv = netdev_priv(dev);
 
 	rvals->rx_max_pending = GFAR_RX_MAX_RING_SIZE;
 	rvals->rx_mini_max_pending = GFAR_RX_MAX_RING_SIZE;
@@ -409,7 +402,7 @@ void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals)
 int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals)
 {
 	u32 tempval;
-	struct gfar_private *priv = (struct gfar_private *) dev->priv;
+	struct gfar_private *priv = netdev_priv(dev);
 	int err = 0;
 
 	if (rvals->rx_pending > GFAR_RX_MAX_RING_SIZE)
@@ -473,7 +466,7 @@ struct ethtool_ops gfar_ethtool_ops = {
 	.get_drvinfo = gfar_gdrvinfo,
 	.get_regs_len = gfar_reglen,
 	.get_regs = gfar_get_regs,
-	.get_link = gfar_get_link,
+	.get_link = ethtool_op_get_link,
 	.get_coalesce = gfar_gcoalesce,
 	.set_coalesce = gfar_scoalesce,
 	.get_ringparam = gfar_gringparam,
@@ -482,3 +475,51 @@ struct ethtool_ops gfar_ethtool_ops = {
 	.get_stats_count = gfar_stats_count,
 	.get_ethtool_stats = gfar_fill_stats,
 };
+
+struct ethtool_ops gfar_normon_nocoalesce_ethtool_ops = {
+	.get_settings = gfar_gsettings,
+	.get_drvinfo = gfar_gdrvinfo,
+	.get_regs_len = gfar_reglen,
+	.get_regs = gfar_get_regs,
+	.get_link = ethtool_op_get_link,
+	.get_ringparam = gfar_gringparam,
+	.set_ringparam = gfar_sringparam,
+	.get_strings = gfar_gstrings_normon,
+	.get_stats_count = gfar_stats_count_normon,
+	.get_ethtool_stats = gfar_fill_stats_normon,
+};
+
+struct ethtool_ops gfar_nocoalesce_ethtool_ops = {
+	.get_settings = gfar_gsettings,
+	.get_drvinfo = gfar_gdrvinfo,
+	.get_regs_len = gfar_reglen,
+	.get_regs = gfar_get_regs,
+	.get_link = ethtool_op_get_link,
+	.get_ringparam = gfar_gringparam,
+	.set_ringparam = gfar_sringparam,
+	.get_strings = gfar_gstrings,
+	.get_stats_count = gfar_stats_count,
+	.get_ethtool_stats = gfar_fill_stats,
+};
+
+struct ethtool_ops gfar_normon_ethtool_ops = {
+	.get_settings = gfar_gsettings,
+	.get_drvinfo = gfar_gdrvinfo,
+	.get_regs_len = gfar_reglen,
+	.get_regs = gfar_get_regs,
+	.get_link = ethtool_op_get_link,
+	.get_coalesce = gfar_gcoalesce,
+	.set_coalesce = gfar_scoalesce,
+	.get_ringparam = gfar_gringparam,
+	.set_ringparam = gfar_sringparam,
+	.get_strings = gfar_gstrings_normon,
+	.get_stats_count = gfar_stats_count_normon,
+	.get_ethtool_stats = gfar_fill_stats_normon,
+};
+
+struct ethtool_ops *gfar_op_array[] = {
+	&gfar_ethtool_ops,
+	&gfar_normon_ethtool_ops,
+	&gfar_nocoalesce_ethtool_ops,
+	&gfar_normon_nocoalesce_ethtool_ops
+};
diff --git a/drivers/net/gianfar_phy.c b/drivers/net/gianfar_phy.c
index ea02e5da9..02b16abc8 100644
--- a/drivers/net/gianfar_phy.c
+++ b/drivers/net/gianfar_phy.c
@@ -8,7 +8,7 @@
  * Author: Andy Fleming
  * Maintainer: Kumar Gala (kumar.gala@freescale.com)
  *
- * Copyright 2004 Freescale Semiconductor, Inc
+ * Copyright (c) 2002-2004 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 as published by the
@@ -31,7 +31,6 @@
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 #include <linux/mm.h>
-#include <linux/mii.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -39,21 +38,31 @@
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/crc32.h>
+#include <linux/mii.h>
 
 #include "gianfar.h"
 #include "gianfar_phy.h"
 
+static void config_genmii_advert(struct gfar_mii_info *mii_info);
+static void genmii_setup_forced(struct gfar_mii_info *mii_info);
+static void genmii_restart_aneg(struct gfar_mii_info *mii_info);
+static int gbit_config_aneg(struct gfar_mii_info *mii_info);
+static int genmii_config_aneg(struct gfar_mii_info *mii_info);
+static int genmii_update_link(struct gfar_mii_info *mii_info);
+static int genmii_read_status(struct gfar_mii_info *mii_info);
+u16 phy_read(struct gfar_mii_info *mii_info, u16 regnum);
+void phy_write(struct gfar_mii_info *mii_info, u16 regnum, u16 val);
+
 /* Write value to the PHY for this device to the register at regnum, */
 /* waiting until the write is done before it returns.  All PHY */
 /* configuration has to be done through the TSEC1 MIIM regs */
-void write_phy_reg(struct net_device *dev, u16 regnum, u16 value)
+void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value)
 {
-	struct gfar_private *priv = (struct gfar_private *) dev->priv;
+	struct gfar_private *priv = netdev_priv(dev);
 	struct gfar *regbase = priv->phyregs;
-	struct ocp_gfar_data *einfo = priv->einfo;
 
 	/* Set the PHY address and the register address we want to write */
-	gfar_write(&regbase->miimadd, ((einfo->phyid) << 8) | regnum);
+	gfar_write(&regbase->miimadd, (mii_id << 8) | regnum);
 
 	/* Write out the value we want */
 	gfar_write(&regbase->miimcon, value);
@@ -66,19 +75,18 @@ void write_phy_reg(struct net_device *dev, u16 regnum, u16 value)
 /* Reads from register regnum in the PHY for device dev, */
 /* returning the value.  Clears miimcom first.  All PHY */
 /* configuration has to be done through the TSEC1 MIIM regs */
-u16 read_phy_reg(struct net_device *dev, u16 regnum)
+int read_phy_reg(struct net_device *dev, int mii_id, int regnum)
 {
-	struct gfar_private *priv = (struct gfar_private *) dev->priv;
+	struct gfar_private *priv = netdev_priv(dev);
 	struct gfar *regbase = priv->phyregs;
-	struct ocp_gfar_data *einfo = priv->einfo;
 	u16 value;
 
 	/* Set the PHY address and the register address we want to read */
-	gfar_write(&regbase->miimadd, ((einfo->phyid) << 8) | regnum);
+	gfar_write(&regbase->miimadd, (mii_id << 8) | regnum);
 
 	/* Clear miimcom, and then initiate a read */
 	gfar_write(&regbase->miimcom, 0);
-	gfar_write(&regbase->miimcom, MIIM_READ_COMMAND);
+	gfar_write(&regbase->miimcom, MII_READ_COMMAND);
 
 	/* Wait for the transaction to finish */
 	while (gfar_read(&regbase->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY))
@@ -90,444 +98,557 @@ u16 read_phy_reg(struct net_device *dev, u16 regnum)
 	return value;
 }
 
-/* returns which value to write to the control register. */
-/* For 10/100 the value is slightly different. */
-u16 mii_cr_init(u16 mii_reg, struct net_device * dev)
+void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info)
 {
-	struct gfar_private *priv = (struct gfar_private *) dev->priv;
-	struct ocp_gfar_data *einfo = priv->einfo;
+	if(mii_info->phyinfo->ack_interrupt)
+		mii_info->phyinfo->ack_interrupt(mii_info);
+}
 
-	if (einfo->flags & GFAR_HAS_GIGABIT)
-		return MIIM_CONTROL_INIT;
-	else
-		return MIIM_CR_INIT;
+
+void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts)
+{
+	mii_info->interrupts = interrupts;
+	if(mii_info->phyinfo->config_intr)
+		mii_info->phyinfo->config_intr(mii_info);
 }
 
-#define BRIEF_GFAR_ERRORS
-/* Wait for auto-negotiation to complete */
-u16 mii_parse_sr(u16 mii_reg, struct net_device * dev)
+
+/* Writes MII_ADVERTISE with the appropriate values, after
+ * sanitizing advertise to make sure only supported features
+ * are advertised 
+ */
+static void config_genmii_advert(struct gfar_mii_info *mii_info)
 {
-	struct gfar_private *priv = (struct gfar_private *) dev->priv;
+	u32 advertise;
+	u16 adv;
+
+	/* Only allow advertising what this PHY supports */
+	mii_info->advertising &= mii_info->phyinfo->features;
+	advertise = mii_info->advertising;
+
+	/* Setup standard advertisement */
+	adv = phy_read(mii_info, MII_ADVERTISE);
+	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+	if (advertise & ADVERTISED_10baseT_Half)
+		adv |= ADVERTISE_10HALF;
+	if (advertise & ADVERTISED_10baseT_Full)
+		adv |= ADVERTISE_10FULL;
+	if (advertise & ADVERTISED_100baseT_Half)
+		adv |= ADVERTISE_100HALF;
+	if (advertise & ADVERTISED_100baseT_Full)
+		adv |= ADVERTISE_100FULL;
+	phy_write(mii_info, MII_ADVERTISE, adv);
+}
 
-	unsigned int timeout = GFAR_AN_TIMEOUT;
+static void genmii_setup_forced(struct gfar_mii_info *mii_info)
+{
+	u16 ctrl;
+	u32 features = mii_info->phyinfo->features;
+	
+	ctrl = phy_read(mii_info, MII_BMCR);
+
+	ctrl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPEED1000|BMCR_ANENABLE);
+	ctrl |= BMCR_RESET;
+
+	switch(mii_info->speed) {
+		case SPEED_1000:
+			if(features & (SUPPORTED_1000baseT_Half
+						| SUPPORTED_1000baseT_Full)) {
+				ctrl |= BMCR_SPEED1000;
+				break;
+			}
+			mii_info->speed = SPEED_100;
+		case SPEED_100:
+			if (features & (SUPPORTED_100baseT_Half
+						| SUPPORTED_100baseT_Full)) {
+				ctrl |= BMCR_SPEED100;
+				break;
+			}
+			mii_info->speed = SPEED_10;
+		case SPEED_10:
+			if (features & (SUPPORTED_10baseT_Half
+						| SUPPORTED_10baseT_Full))
+				break;
+		default: /* Unsupported speed! */
+			printk(KERN_ERR "%s: Bad speed!\n", 
+					mii_info->dev->name);
+			break;
+	}
 
-	if (mii_reg & MIIM_STATUS_LINK)
-		priv->link = 1;
-	else
-		priv->link = 0;
+	phy_write(mii_info, MII_BMCR, ctrl);
+}
 
-	/* Only auto-negotiate if the link has just gone up */
-	if (priv->link && !priv->oldlink) {
-		while ((!(mii_reg & MIIM_STATUS_AN_DONE)) && timeout--)
-			mii_reg = read_phy_reg(dev, MIIM_STATUS);
 
-#if defined(BRIEF_GFAR_ERRORS)
-		if (mii_reg & MIIM_STATUS_AN_DONE)
-			printk(KERN_INFO "%s: Auto-negotiation done\n",
-			       dev->name);
-		else
-			printk(KERN_INFO "%s: Auto-negotiation timed out\n",
-			       dev->name);
-#endif
-	}
+/* Enable and Restart Autonegotiation */
+static void genmii_restart_aneg(struct gfar_mii_info *mii_info)
+{
+	u16 ctl;
+
+	ctl = phy_read(mii_info, MII_BMCR);
+	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+	phy_write(mii_info, MII_BMCR, ctl);
+}
+
+
+static int gbit_config_aneg(struct gfar_mii_info *mii_info)
+{
+	u16 adv;
+	u32 advertise;
+
+	if(mii_info->autoneg) {
+		/* Configure the ADVERTISE register */
+		config_genmii_advert(mii_info);
+		advertise = mii_info->advertising;
+
+		adv = phy_read(mii_info, MII_1000BASETCONTROL);
+		adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP |
+				MII_1000BASETCONTROL_HALFDUPLEXCAP);
+		if (advertise & SUPPORTED_1000baseT_Half)
+			adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP;
+		if (advertise & SUPPORTED_1000baseT_Full)
+			adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP;
+		phy_write(mii_info, MII_1000BASETCONTROL, adv);
+
+		/* Start/Restart aneg */
+		genmii_restart_aneg(mii_info);
+	} else
+		genmii_setup_forced(mii_info);
 
 	return 0;
 }
 
-/* Determine the speed and duplex which was negotiated */
-u16 mii_parse_88E1011_psr(u16 mii_reg, struct net_device * dev)
+static int marvell_config_aneg(struct gfar_mii_info *mii_info)
+{
+	/* The Marvell PHY has an errata which requires
+	 * that certain registers get written in order
+	 * to restart autonegotiation */
+	phy_write(mii_info, MII_BMCR, BMCR_RESET);
+
+	phy_write(mii_info, 0x1d, 0x1f);
+	phy_write(mii_info, 0x1e, 0x200c);
+	phy_write(mii_info, 0x1d, 0x5);
+	phy_write(mii_info, 0x1e, 0);
+	phy_write(mii_info, 0x1e, 0x100);
+
+	gbit_config_aneg(mii_info);
+
+	return 0;
+}
+static int genmii_config_aneg(struct gfar_mii_info *mii_info)
 {
-	struct gfar_private *priv = (struct gfar_private *) dev->priv;
-	unsigned int speed;
+	if (mii_info->autoneg) {
+		config_genmii_advert(mii_info);
+		genmii_restart_aneg(mii_info);
+	} else
+		genmii_setup_forced(mii_info);
+
+	return 0;
+}
+
+
+static int genmii_update_link(struct gfar_mii_info *mii_info)
+{
+	u16 status;
+
+	/* Do a fake read */
+	phy_read(mii_info, MII_BMSR);
+
+	/* Read link and autonegotiation status */
+	status = phy_read(mii_info, MII_BMSR);
+	if ((status & BMSR_LSTATUS) == 0)
+		mii_info->link = 0;
+	else
+		mii_info->link = 1;
 
-	if (priv->link) {
-		if (mii_reg & MIIM_88E1011_PHYSTAT_DUPLEX)
-			priv->duplexity = 1;
+	/* If we are autonegotiating, and not done, 
+	 * return an error */
+	if (mii_info->autoneg && !(status & BMSR_ANEGCOMPLETE))
+		return -EAGAIN;
+
+	return 0;
+}
+
+static int genmii_read_status(struct gfar_mii_info *mii_info)
+{
+	u16 status;
+	int err;
+
+	/* Update the link, but return if there
+	 * was an error */
+	err = genmii_update_link(mii_info);
+	if (err)
+		return err;
+
+	if (mii_info->autoneg) {
+		status = phy_read(mii_info, MII_LPA);
+
+		if (status & (LPA_10FULL | LPA_100FULL))
+			mii_info->duplex = DUPLEX_FULL;
 		else
-			priv->duplexity = 0;
+			mii_info->duplex = DUPLEX_HALF;
+		if (status & (LPA_100FULL | LPA_100HALF))
+			mii_info->speed = SPEED_100;
+		else
+			mii_info->speed = SPEED_10;
+		mii_info->pause = 0;
+	}
+	/* On non-aneg, we assume what we put in BMCR is the speed,
+	 * though magic-aneg shouldn't prevent this case from occurring
+	 */
 
-		speed = (mii_reg & MIIM_88E1011_PHYSTAT_SPEED);
+	return 0;
+}
+static int marvell_read_status(struct gfar_mii_info *mii_info)
+{
+	u16 status;
+	int err;
+
+	/* Update the link, but return if there
+	 * was an error */
+	err = genmii_update_link(mii_info);
+	if (err)
+		return err;
+
+	/* If the link is up, read the speed and duplex */
+	/* If we aren't autonegotiating, assume speeds 
+	 * are as set */
+	if (mii_info->autoneg && mii_info->link) {
+		int speed;
+		status = phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
 
-		switch (speed) {
-		case MIIM_88E1011_PHYSTAT_GBIT:
-			priv->speed = 1000;
-			break;
-		case MIIM_88E1011_PHYSTAT_100:
-			priv->speed = 100;
-			break;
-		default:
-			priv->speed = 10;
-			break;
+#if 0
+		/* If speed and duplex aren't resolved,
+		 * return an error.  Isn't this handled
+		 * by checking aneg?
+		 */
+		if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0)
+			return -EAGAIN;
+#endif
+
+		/* Get the duplexity */
+		if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
+			mii_info->duplex = DUPLEX_FULL;
+		else
+			mii_info->duplex = DUPLEX_HALF;
+
+		/* Get the speed */
+		speed = status & MII_M1011_PHY_SPEC_STATUS_SPD_MASK;
+		switch(speed) {
+			case MII_M1011_PHY_SPEC_STATUS_1000:
+				mii_info->speed = SPEED_1000;
+				break;
+			case MII_M1011_PHY_SPEC_STATUS_100:
+				mii_info->speed = SPEED_100;
+				break;
+			default:
+				mii_info->speed = SPEED_10;
+				break;
 		}
-	} else {
-		priv->speed = 0;
-		priv->duplexity = 0;
+		mii_info->pause = 0;
 	}
 
 	return 0;
 }
 
-u16 mii_parse_cis8201(u16 mii_reg, struct net_device * dev)
-{
-	struct gfar_private *priv = (struct gfar_private *) dev->priv;
-	unsigned int speed;
 
-	if (priv->link) {
-		if (mii_reg & MIIM_CIS8201_AUXCONSTAT_DUPLEX)
-			priv->duplexity = 1;
+static int cis820x_read_status(struct gfar_mii_info *mii_info)
+{
+	u16 status;
+	int err;
+
+	/* Update the link, but return if there
+	 * was an error */
+	err = genmii_update_link(mii_info);
+	if (err)
+		return err;
+
+	/* If the link is up, read the speed and duplex */
+	/* If we aren't autonegotiating, assume speeds 
+	 * are as set */
+	if (mii_info->autoneg && mii_info->link) {
+		int speed;
+
+		status = phy_read(mii_info, MII_CIS8201_AUX_CONSTAT);
+		if (status & MII_CIS8201_AUXCONSTAT_DUPLEX)
+			mii_info->duplex = DUPLEX_FULL;
 		else
-			priv->duplexity = 0;
+			mii_info->duplex = DUPLEX_HALF;
 
-		speed = mii_reg & MIIM_CIS8201_AUXCONSTAT_SPEED;
+		speed = status & MII_CIS8201_AUXCONSTAT_SPEED;
 
 		switch (speed) {
-		case MIIM_CIS8201_AUXCONSTAT_GBIT:
-			priv->speed = 1000;
+		case MII_CIS8201_AUXCONSTAT_GBIT:
+			mii_info->speed = SPEED_1000;
 			break;
-		case MIIM_CIS8201_AUXCONSTAT_100:
-			priv->speed = 100;
+		case MII_CIS8201_AUXCONSTAT_100:
+			mii_info->speed = SPEED_100;
 			break;
 		default:
-			priv->speed = 10;
+			mii_info->speed = SPEED_10;
 			break;
 		}
-	} else {
-		priv->speed = 0;
-		priv->duplexity = 0;
 	}
 
 	return 0;
 }
 
-u16 mii_parse_dm9161_scsr(u16 mii_reg, struct net_device * dev)
+static int marvell_ack_interrupt(struct gfar_mii_info *mii_info)
 {
-	struct gfar_private *priv = (struct gfar_private *) dev->priv;
+	/* Clear the interrupts by reading the reg */
+	phy_read(mii_info, MII_M1011_IEVENT);
+
+	return 0;
+}
 
-	if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_100H))
-		priv->speed = 100;
+static int marvell_config_intr(struct gfar_mii_info *mii_info)
+{
+	if(mii_info->interrupts == MII_INTERRUPT_ENABLED)
+		phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
 	else
-		priv->speed = 10;
+		phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR);
+
+	return 0;
+}
+
+static int cis820x_init(struct gfar_mii_info *mii_info)
+{
+	phy_write(mii_info, MII_CIS8201_AUX_CONSTAT, 
+			MII_CIS8201_AUXCONSTAT_INIT);
+	phy_write(mii_info, MII_CIS8201_EXT_CON1,
+			MII_CIS8201_EXTCON1_INIT);
+
+	return 0;
+}
 
-	if (mii_reg & (MIIM_DM9161_SCSR_100F | MIIM_DM9161_SCSR_10F))
-		priv->duplexity = 1;
+static int cis820x_ack_interrupt(struct gfar_mii_info *mii_info)
+{
+	phy_read(mii_info, MII_CIS8201_ISTAT);
+
+	return 0;
+}
+
+static int cis820x_config_intr(struct gfar_mii_info *mii_info)
+{
+	if(mii_info->interrupts == MII_INTERRUPT_ENABLED)
+		phy_write(mii_info, MII_CIS8201_IMASK, MII_CIS8201_IMASK_MASK);
 	else
-		priv->duplexity = 0;
+		phy_write(mii_info, MII_CIS8201_IMASK, 0);
 
 	return 0;
 }
 
-u16 dm9161_wait(u16 mii_reg, struct net_device *dev)
+#define DM9161_DELAY 10
+
+static int dm9161_read_status(struct gfar_mii_info *mii_info)
 {
-	int timeout = HZ;
-	int secondary = 10;
-	u16 temp;
+	u16 status;
+	int err;
+
+	/* Update the link, but return if there
+	 * was an error */
+	err = genmii_update_link(mii_info);
+	if (err)
+		return err;
+
+	/* If the link is up, read the speed and duplex */
+	/* If we aren't autonegotiating, assume speeds 
+	 * are as set */
+	if (mii_info->autoneg && mii_info->link) {
+		status = phy_read(mii_info, MII_DM9161_SCSR);
+		if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
+			mii_info->speed = SPEED_100;
+		else
+			mii_info->speed = SPEED_10;
+
+		if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_10F))
+			mii_info->duplex = DUPLEX_FULL;
+		else
+			mii_info->duplex = DUPLEX_HALF;
+	}
 
-	do {
+	return 0;
+}
 
-		/* Davicom takes a bit to come up after a reset,
-		 * so wait here for a bit */
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(timeout);
 
-		temp = read_phy_reg(dev, MIIM_STATUS);
+static int dm9161_config_aneg(struct gfar_mii_info *mii_info)
+{
+	struct dm9161_private *priv = mii_info->priv;
 
-		secondary--;
-	} while ((!(temp & MIIM_STATUS_AN_DONE)) && secondary);
+	if(0 == priv->resetdone)
+		return -EAGAIN;
 
 	return 0;
 }
 
-/*
- * consult the BCM54xx auxilliary status register to find the link settings
- */
-u16 mii_parse_bcm54xx_sr(u16 mii_reg, struct net_device * dev)
+static void dm9161_timer(unsigned long data)
 {
-	struct gfar_private *priv = (struct gfar_private *) dev->priv;
+	struct gfar_mii_info *mii_info = (struct gfar_mii_info *)data;
+	struct dm9161_private *priv = mii_info->priv;
+	u16 status = phy_read(mii_info, MII_BMSR);
+
+	if (status & BMSR_ANEGCOMPLETE) {
+		priv->resetdone = 1;
+	} else
+		mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
+}
+
+static int dm9161_init(struct gfar_mii_info *mii_info)
+{
+	struct dm9161_private *priv;
+
+	/* Allocate the private data structure */
+	priv = kmalloc(sizeof(struct dm9161_private), GFP_KERNEL);
+
+	if (NULL == priv)
+		return -ENOMEM;
 
-	/* Link modes of the BCM5400 PHY */
-	static const uint16_t link_table[8][3] = {
-		{ 0, 0		},	/* No link */
-		{ 0, 10		},	/* 10BT Half Duplex */
-		{ 1, 10		},	/* 10BT Full Duplex */
-		{ 0, 100	},	/* 100BT Half Duplex */
-		{ 0, 100	},	/* 100BT Half Duplex */
-		{ 1, 100	},	/* 100BT Full Duplex*/
-		{ 1, 1000	},	/* 1000BT */
-		{ 1, 1000	},	/* 1000BT */
-	};
+	mii_info->priv = priv;
 
-	uint16_t link_mode;
+	/* Reset is not done yet */
+	priv->resetdone = 0;
 
-	link_mode = mii_reg & MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK;
-	link_mode >>= MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT;
+	/* Isolate the PHY */
+	phy_write(mii_info, MII_BMCR, BMCR_ISOLATE);
 
-	priv->duplexity = link_table[link_mode][0];
-	priv->speed = link_table[link_mode][1];
+	/* Do not bypass the scrambler/descrambler */
+	phy_write(mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
+
+	/* Clear 10BTCSR to default */
+	phy_write(mii_info, MII_DM9161_10BTCSR, MII_DM9161_10BTCSR_INIT);
+
+	/* Reconnect the PHY, and enable Autonegotiation */
+	phy_write(mii_info, MII_BMCR, BMCR_ANENABLE);
+
+	/* Start a timer for DM9161_DELAY seconds to wait
+	 * for the PHY to be ready */
+	init_timer(&priv->timer);
+	priv->timer.function = &dm9161_timer;
+	priv->timer.data = (unsigned long) mii_info;
+	mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ);
 
 	return 0;
 }
 
-static struct phy_info phy_info_M88E1011S = {
-	0x01410c6,
-	"Marvell 88E1011S",
-	4,
-	(const struct phy_cmd[]) {	/* config */
-		/* Reset and configure the PHY */
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, mii_cr_init},
-		{miim_end,}
-	},
-	(const struct phy_cmd[]) {	/* startup */
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, mii_parse_sr},
-		/* Read the status */
-		{MIIM_88E1011_PHY_STATUS, miim_read, mii_parse_88E1011_psr},
-		/* Clear the IEVENT register */
-		{MIIM_88E1011_IEVENT, miim_read, NULL},
-		/* Set up the mask */
-		{MIIM_88E1011_IMASK, MIIM_88E1011_IMASK_INIT, NULL},
-		{miim_end,}
-	},
-	(const struct phy_cmd[]) {	/* ack_int */
-		/* Clear the interrupt */
-		{MIIM_88E1011_IEVENT, miim_read, NULL},
-		/* Disable interrupts */
-		{MIIM_88E1011_IMASK, MIIM_88E1011_IMASK_CLEAR, NULL},
-		{miim_end,}
-	},
-	(const struct phy_cmd[]) {	/* handle_int */
-		/* Read the Status (2x to make sure link is right) */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Check the status */
-		{MIIM_STATUS, miim_read, mii_parse_sr},
-		{MIIM_88E1011_PHY_STATUS, miim_read, mii_parse_88E1011_psr},
-			/* Enable Interrupts */
-		{MIIM_88E1011_IMASK, MIIM_88E1011_IMASK_INIT, NULL},
-		{miim_end,}
-	},
-	(const struct phy_cmd[]) {	/* shutdown */
-		{MIIM_88E1011_IEVENT, miim_read, NULL},
-		{MIIM_88E1011_IMASK, MIIM_88E1011_IMASK_CLEAR, NULL},
-		{miim_end,}
-	},
-};
+static void dm9161_close(struct gfar_mii_info *mii_info)
+{
+	struct dm9161_private *priv = mii_info->priv;
+
+	del_timer_sync(&priv->timer);
+	kfree(priv);
+}
+
+#if 0
+static int dm9161_ack_interrupt(struct gfar_mii_info *mii_info)
+{
+	phy_read(mii_info, MII_DM9161_INTR);
 
-/* Cicada 8204 */
-static struct phy_info phy_info_cis8204 = {
-	0x3f11,
+	return 0;
+}
+#endif
+
+/* Cicada 820x */
+static struct phy_info phy_info_cis820x = {
+	0x000fc440,
 	"Cicada Cis8204",
-	6,
-	(const struct phy_cmd[]) {	/* config */
-		/* Override PHY config settings */
-		{MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
-		/* Set up the interface mode */
-		{MIIM_CIS8201_EXT_CON1, MIIM_CIS8201_EXTCON1_INIT, NULL},
-		/* Configure some basic stuff */
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, mii_cr_init},
-		{miim_end,}
-	},
-	(const struct phy_cmd[]) {	/* startup */
-		/* Read the Status (2x to make sure link is right) */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, mii_parse_sr},
-		/* Read the status */
-		{MIIM_CIS8201_AUX_CONSTAT, miim_read, mii_parse_cis8201},
-		/* Clear the status register */
-		{MIIM_CIS8204_ISTAT, miim_read, NULL},
-		/* Enable interrupts */
-		{MIIM_CIS8204_IMASK, MIIM_CIS8204_IMASK_MASK, NULL},
-		{miim_end,}
-	},
-	(const struct phy_cmd[]) {	/* ack_int */
-		/* Clear the status register */
-		{MIIM_CIS8204_ISTAT, miim_read, NULL},
-		/* Disable interrupts */
-		{MIIM_CIS8204_IMASK, 0x0, NULL},
-		{miim_end,}
-	},
-	(const struct phy_cmd[]) {	/* handle_int */
-		/* Read the Status (2x to make sure link is right) */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, mii_parse_sr},
-		/* Read the status */
-		{MIIM_CIS8201_AUX_CONSTAT, miim_read, mii_parse_cis8201},
-		/* Enable interrupts */
-		{MIIM_CIS8204_IMASK, MIIM_CIS8204_IMASK_MASK, NULL},
-		{miim_end,}
-	},
-	(const struct phy_cmd[]) {	/* shutdown */
-		/* Clear the status register */
-		{MIIM_CIS8204_ISTAT, miim_read, NULL},
-		/* Disable interrupts */
-		{MIIM_CIS8204_IMASK, 0x0, NULL},
-		{miim_end,}
-	},
+	0x000fffc0,
+	.features	= MII_GBIT_FEATURES,
+	.init		= &cis820x_init,
+	.config_aneg	= &gbit_config_aneg,
+	.read_status	= &cis820x_read_status,
+	.ack_interrupt	= &cis820x_ack_interrupt,
+	.config_intr	= &cis820x_config_intr,
 };
 
-/* Cicada 8201 */
-static struct phy_info phy_info_cis8201 = {
-	0xfc41,
-	"CIS8201",
-	4,
-	(const struct phy_cmd[]) {	/* config */
-		/* Override PHY config settings */
-		{MIIM_CIS8201_AUX_CONSTAT, MIIM_CIS8201_AUXCONSTAT_INIT, NULL},
-		/* Set up the interface mode */
-		{MIIM_CIS8201_EXT_CON1, MIIM_CIS8201_EXTCON1_INIT, NULL},
-		/* Configure some basic stuff */
-		{MIIM_CONTROL, MIIM_CONTROL_INIT, mii_cr_init},
-		{miim_end,}
-	},
-	(const struct phy_cmd[]) {	/* startup */
-		/* Read the Status (2x to make sure link is right) */
-		{MIIM_STATUS, miim_read, NULL},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, mii_parse_sr},
-		/* Read the status */
-		{MIIM_CIS8201_AUX_CONSTAT, miim_read, mii_parse_cis8201},
-		{miim_end,}
-	},
-	(const struct phy_cmd[]) {	/* ack_int */
-		{miim_end,}
-	},
-	(const struct phy_cmd[]) {	/* handle_int */
-		{miim_end,}
-	},
-	(const struct phy_cmd[]) {	/* shutdown */
-		{miim_end,}
-	},
+static struct phy_info phy_info_dm9161 = {
+	.phy_id		= 0x0181b880,
+	.name		= "Davicom DM9161E",
+	.phy_id_mask	= 0x0ffffff0,
+	.init		= dm9161_init,
+	.config_aneg	= dm9161_config_aneg,
+	.read_status	= dm9161_read_status,
+	.close		= dm9161_close,
 };
 
-static struct phy_info phy_info_dm9161 = {
-	0x0181b88,
-	"Davicom DM9161E",
-	4,
-	(const struct phy_cmd[]) {	/* config */
-		{MIIM_CONTROL, MIIM_DM9161_CR_STOP, NULL},
-		/* Do not bypass the scrambler/descrambler */
-		{MIIM_DM9161_SCR, MIIM_DM9161_SCR_INIT, NULL},
-		/* Clear 10BTCSR to default */
-		{MIIM_DM9161_10BTCSR, MIIM_DM9161_10BTCSR_INIT, NULL},
-		/* Configure some basic stuff */
-		{MIIM_CONTROL, MIIM_CR_INIT, NULL},
-		{miim_end,}
-	},
-	(const struct phy_cmd[]) {	/* startup */
-		/* Restart Auto Negotiation */
-		{MIIM_CONTROL, MIIM_DM9161_CR_RSTAN, NULL},
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, dm9161_wait},
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, mii_parse_sr},
-		/* Read the status */
-		{MIIM_DM9161_SCSR, miim_read, mii_parse_dm9161_scsr},
-		/* Clear any pending interrupts */
-		{MIIM_DM9161_INTR, miim_read, NULL},
-		{miim_end,}
-	},
-	(const struct phy_cmd[]) {	/* ack_int */
-		{MIIM_DM9161_INTR, miim_read, NULL},
-		{miim_end,}
-	},
-	(const struct phy_cmd[]) {	/* handle_int */
-		{MIIM_STATUS, miim_read, NULL},
-		{MIIM_STATUS, miim_read, mii_parse_sr},
-		{MIIM_DM9161_SCSR, miim_read, mii_parse_dm9161_scsr},
-		{miim_end,}
-	},
-	(const struct phy_cmd[]) {	/* shutdown */
-		{MIIM_DM9161_INTR, miim_read, NULL},
-		{miim_end,}
-	},
+static struct phy_info phy_info_marvell = {
+	.phy_id		= 0x01410c00,
+	.phy_id_mask	= 0xffffff00,
+	.name		= "Marvell 88E1101",
+	.features	= MII_GBIT_FEATURES,
+	.config_aneg	= &marvell_config_aneg,
+	.read_status	= &marvell_read_status,
+	.ack_interrupt	= &marvell_ack_interrupt,
+	.config_intr	= &marvell_config_intr,
 };
 
-/* Broadcom BCM5421S PHY */
-static struct phy_info phy_info_bcm5421s = {
-	.id = 0x2060E1,
-	.name = "Broadcom BCM5421S",
-	.shift = 0,
-	.config = (const struct phy_cmd[]) {
-		/* Configure some basic stuff */
-		{MIIM_CONTROL, MIIM_CR_INIT, NULL},
-#if 0 /* 5421 only */
-		miim_write(MII_BCM5400_AUXCONTROL, 0x1007),
-		miim_set_bits(MII_BCM5400_AUXCONTROL, 0x0400),
-		miim_write(MII_BCM5400_AUXCONTROL, 0x0007),
-		miim_set_bits(MII_BCM5400_AUXCONTROL, 0x0800),
-		miim_write(0x17, 0x000a),
-		miim_set_bits(MII_RERRCOUNTER, 0x0200),
-#endif
-#if 0 /* enable automatic low power */
-		miim_write(MII_NCONFIG, 0x9002),
-		miim_write(MII_NCONFIG, 0xa821),
-		miim_write(MII_NCONFIG, 0x941d),
-#endif
-		{miim_end,}
-	},
-	.startup = (const struct phy_cmd[]) {
-		/* Restart Auto Negotiation */
-		miim_set_bits(MIIM_CONTROL, BMCR_ANENABLE | BMCR_ANRESTART),
-#if 0
-		/* Status is read once to clear old link state */
-		{MIIM_STATUS, miim_read, dm9161_wait},
-#endif
-		/* Auto-negotiate */
-		{MIIM_STATUS, miim_read, mii_parse_sr},
-
-		/* Read the link status */
-		{MIIM_BCM54xx_AUXSTATUS, miim_read, mii_parse_bcm54xx_sr},
-
-		{miim_end,}
-	},
-	.ack_int = (const struct phy_cmd[]) {
-		{miim_end,}
-	},
-	.handle_int = (const struct phy_cmd[]) {
-		{MIIM_STATUS, miim_read, NULL},
-		{MIIM_STATUS, miim_read, mii_parse_sr},
-		{miim_end,}
-	},
-	.shutdown = (const struct phy_cmd[]) {
-		{miim_end,}
-	},
+static struct phy_info phy_info_genmii= {
+	.phy_id		= 0x00000000,
+	.phy_id_mask	= 0x00000000,
+	.name		= "Generic MII",
+	.features	= MII_BASIC_FEATURES,
+	.config_aneg	= genmii_config_aneg,
+	.read_status	= genmii_read_status,
 };
 
 static struct phy_info *phy_info[] = {
-	&phy_info_cis8201,
-	&phy_info_cis8204,
-	&phy_info_M88E1011S,
+	&phy_info_cis820x,
+	&phy_info_marvell,
 	&phy_info_dm9161,
-	&phy_info_bcm5421s,
+	&phy_info_genmii,
 	NULL
 };
 
+u16 phy_read(struct gfar_mii_info *mii_info, u16 regnum)
+{
+	u16 retval;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mii_info->mdio_lock, flags);
+	retval = mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum);
+	spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
+
+	return retval;
+}
+
+void phy_write(struct gfar_mii_info *mii_info, u16 regnum, u16 val)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&mii_info->mdio_lock, flags);
+	mii_info->mdio_write(mii_info->dev, 
+			mii_info->mii_id, 
+			regnum, val);
+	spin_unlock_irqrestore(&mii_info->mdio_lock, flags);
+}
+
 /* Use the PHY ID registers to determine what type of PHY is attached
  * to device dev.  return a struct phy_info structure describing that PHY
  */
-struct phy_info * get_phy_info(struct net_device *dev)
+struct phy_info * get_phy_info(struct gfar_mii_info *mii_info)
 {
 	u16 phy_reg;
 	u32 phy_ID;
 	int i;
 	struct phy_info *theInfo = NULL;
+	struct net_device *dev = mii_info->dev;
 
 	/* Grab the bits from PHYIR1, and put them in the upper half */
-	phy_reg = read_phy_reg(dev, MIIM_PHYIR1);
+	phy_reg = phy_read(mii_info, MII_PHYSID1);
 	phy_ID = (phy_reg & 0xffff) << 16;
 
 	/* Grab the bits from PHYIR2, and put them in the lower half */
-	phy_reg = read_phy_reg(dev, MIIM_PHYIR2);
+	phy_reg = phy_read(mii_info, MII_PHYSID2);
 	phy_ID |= (phy_reg & 0xffff);
 
 	/* loop through all the known PHY types, and find one that */
 	/* matches the ID we read from the PHY. */
 	for (i = 0; phy_info[i]; i++)
-		if (phy_info[i]->id == (phy_ID >> phy_info[i]->shift))
+		if (phy_info[i]->phy_id == 
+				(phy_ID & phy_info[i]->phy_id_mask)) {
 			theInfo = phy_info[i];
+			break;
+		}
 
+	/* This shouldn't happen, as we have generic PHY support */
 	if (theInfo == NULL) {
 		printk("%s: PHY id %x is not supported!\n", dev->name, phy_ID);
 		return NULL;
@@ -538,85 +659,3 @@ struct phy_info * get_phy_info(struct net_device *dev)
 
 	return theInfo;
 }
-
-/* Take a list of struct phy_cmd, and, depending on the values, either */
-/* read or write, using a helper function if provided */
-/* It is assumed that all lists of struct phy_cmd will be terminated by */
-/* mii_end. */
-void phy_run_commands(struct net_device *dev, const struct phy_cmd *cmd)
-{
-	int i;
-	u16 result;
-	struct gfar_private *priv = (struct gfar_private *) dev->priv;
-	struct gfar *phyregs = priv->phyregs;
-
-	/* Reset the management interface */
-	gfar_write(&phyregs->miimcfg, MIIMCFG_RESET);
-
-	/* Setup the MII Mgmt clock speed */
-	gfar_write(&phyregs->miimcfg, MIIMCFG_INIT_VALUE);
-
-	/* Wait until the bus is free */
-	while (gfar_read(&phyregs->miimind) & MIIMIND_BUSY)
-		cpu_relax();
-
-	for (i = 0; cmd->mii_reg != miim_end; i++) {
-		switch (cmd->mii_data >> 16) {
-		case 0x0000:
-			/* Otherwise, it's a write */
-			/* If a function was supplied, it will provide 
-			 * the value to write */
-			/* Otherwise, the value was supplied in cmd->mii_data */
-			if (cmd->funct != NULL)
-				result = (*(cmd->funct)) (0, dev);
-			else
-				result = cmd->mii_data;
-
-			write_phy_reg(dev, cmd->mii_reg, result);
-			break;
-
-		case 0x0001:
-			/* Read the value of the PHY reg */
-			result = read_phy_reg(dev, cmd->mii_reg);
-
-			/* If a function was supplied, we need to let it process */
-			/* the result. */
-			if (cmd->funct != NULL)
-				(*(cmd->funct)) (result, dev);
-			break;
-
-		case 0x0002:
-			/* read the value, clear some bits and write it back */
-			BUG_ON(cmd->funct);
-
-			result = read_phy_reg(dev, cmd->mii_reg);
-			result &= cmd->mii_data;
-			write_phy_reg(dev, cmd->mii_reg, result);
-			break;
-
-		case 0x0003:
-			/* read the value, set some bits and write it back */
-			BUG_ON(cmd->funct);
-
-			result = read_phy_reg(dev, cmd->mii_reg);
-			result &= cmd->mii_data;
-			write_phy_reg(dev, cmd->mii_reg, result);
-			break;
-
-		case 0x0004:
-			/* read the value, flip some bits and write it back */
-			BUG_ON(cmd->funct);
-
-			result = read_phy_reg(dev, cmd->mii_reg);
-			result &= cmd->mii_data;
-			write_phy_reg(dev, cmd->mii_reg, result);
-			break;
-
-		default:
-			printk("GIANFAR: Unknown MII command %08x\n",
-			       cmd->mii_data);
-			BUG();
-		}
-		cmd++;
-	}
-}
diff --git a/drivers/net/gianfar_phy.h b/drivers/net/gianfar_phy.h
index df4c0ec9d..1e9b3abf1 100644
--- a/drivers/net/gianfar_phy.h
+++ b/drivers/net/gianfar_phy.h
@@ -8,7 +8,7 @@
  * Author: Andy Fleming
  * Maintainer: Kumar Gala (kumar.gala@freescale.com)
  *
- * Copyright 2004 Freescale Semiconductor, Inc
+ * Copyright (c) 2002-2004 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 as published by the
@@ -19,145 +19,144 @@
 #ifndef __GIANFAR_PHY_H
 #define __GIANFAR_PHY_H
 
-/* simple datum processing commands */
-#define miim_end		(0xffff0000U)
-#define miim_read		(0x00010000U)
-#define miim_clear_bits(reg,x)	{ reg, (0x00020000U | ~(u32)(x)), NULL }
-#define miim_set_bits(reg,x)	{ reg, (0x00030000U | (u32)(x)),  NULL }
-#define miim_flip_bits(reg,x)	{ reg, (0x00040000U | (u32)(x)),  NULL }
-#define miim_write(reg, x)	{ reg, (0x0000ffffU & (u32)(x)),  NULL }
+#define MII_end ((u32)-2)
+#define MII_read ((u32)-1)
 
 #define MIIMIND_BUSY            0x00000001
 #define MIIMIND_NOTVALID        0x00000004
 
-#define MIIM_CONTROL		0x00
-#define MIIM_CONTROL_RESET	0x00008000
-#define MIIM_CONTROL_INIT	0x00001140
-#define MIIM_ANEN		0x00001000
-
-#define MIIM_CR                 0x00
-#define MIIM_CR_RST		0x00008000
-#define MIIM_CR_INIT	        0x00001000
-
-#define MIIM_STATUS		0x1
-#define MIIM_STATUS_AN_DONE	0x00000020
-#define MIIM_STATUS_LINK	0x0004
-
-#define MIIM_PHYIR1		0x2
-#define MIIM_PHYIR2		0x3
-
-#define GFAR_AN_TIMEOUT         0x000fffff
-
-#define MIIM_ANLPBPA	0x5
-#define MIIM_ANLPBPA_HALF	0x00000040
-#define MIIM_ANLPBPA_FULL	0x00000020
-
-#define MIIM_ANEX		0x6
-#define MIIM_ANEX_NP    	0x00000004
-#define MIIM_ANEX_PRX   	0x00000002
+#define GFAR_AN_TIMEOUT         2000
 
+/* 1000BT control (Marvell & BCM54xx at least) */
+#define MII_1000BASETCONTROL			0x09
+#define MII_1000BASETCONTROL_FULLDUPLEXCAP	0x0200
+#define MII_1000BASETCONTROL_HALFDUPLEXCAP	0x0100
 
 /* Cicada Extended Control Register 1 */
-#define MIIM_CIS8201_EXT_CON1           0x17
-#define MIIM_CIS8201_EXTCON1_INIT       0x0000
+#define MII_CIS8201_EXT_CON1           0x17
+#define MII_CIS8201_EXTCON1_INIT       0x0000
 
 /* Cicada Interrupt Mask Register */
-#define MIIM_CIS8204_IMASK		0x19
-#define MIIM_CIS8204_IMASK_IEN		0x8000
-#define MIIM_CIS8204_IMASK_SPEED	0x4000
-#define MIIM_CIS8204_IMASK_LINK		0x2000
-#define MIIM_CIS8204_IMASK_DUPLEX	0x1000
-#define MIIM_CIS8204_IMASK_MASK		0xf000
+#define MII_CIS8201_IMASK		0x19
+#define MII_CIS8201_IMASK_IEN		0x8000
+#define MII_CIS8201_IMASK_SPEED	0x4000
+#define MII_CIS8201_IMASK_LINK		0x2000
+#define MII_CIS8201_IMASK_DUPLEX	0x1000
+#define MII_CIS8201_IMASK_MASK		0xf000
 
 /* Cicada Interrupt Status Register */
-#define MIIM_CIS8204_ISTAT		0x1a
-#define MIIM_CIS8204_ISTAT_STATUS	0x8000
-#define MIIM_CIS8204_ISTAT_SPEED	0x4000
-#define MIIM_CIS8204_ISTAT_LINK		0x2000
-#define MIIM_CIS8204_ISTAT_DUPLEX	0x1000
+#define MII_CIS8201_ISTAT		0x1a
+#define MII_CIS8201_ISTAT_STATUS	0x8000
+#define MII_CIS8201_ISTAT_SPEED	0x4000
+#define MII_CIS8201_ISTAT_LINK		0x2000
+#define MII_CIS8201_ISTAT_DUPLEX	0x1000
 
 /* Cicada Auxiliary Control/Status Register */
-#define MIIM_CIS8201_AUX_CONSTAT        0x1c
-#define MIIM_CIS8201_AUXCONSTAT_INIT    0x0004
-#define MIIM_CIS8201_AUXCONSTAT_DUPLEX  0x0020
-#define MIIM_CIS8201_AUXCONSTAT_SPEED   0x0018
-#define MIIM_CIS8201_AUXCONSTAT_GBIT    0x0010
-#define MIIM_CIS8201_AUXCONSTAT_100     0x0008
+#define MII_CIS8201_AUX_CONSTAT        0x1c
+#define MII_CIS8201_AUXCONSTAT_INIT    0x0004
+#define MII_CIS8201_AUXCONSTAT_DUPLEX  0x0020
+#define MII_CIS8201_AUXCONSTAT_SPEED   0x0018
+#define MII_CIS8201_AUXCONSTAT_GBIT    0x0010
+#define MII_CIS8201_AUXCONSTAT_100     0x0008
                                                                                 
 /* 88E1011 PHY Status Register */
-#define MIIM_88E1011_PHY_STATUS         0x11
-#define MIIM_88E1011_PHYSTAT_SPEED      0xc000
-#define MIIM_88E1011_PHYSTAT_GBIT       0x8000
-#define MIIM_88E1011_PHYSTAT_100        0x4000
-#define MIIM_88E1011_PHYSTAT_DUPLEX     0x2000
-#define MIIM_88E1011_PHYSTAT_LINK	0x0400
+#define MII_M1011_PHY_SPEC_STATUS		0x11
+#define MII_M1011_PHY_SPEC_STATUS_1000		0x8000
+#define MII_M1011_PHY_SPEC_STATUS_100		0x4000
+#define MII_M1011_PHY_SPEC_STATUS_SPD_MASK	0xc000
+#define MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX	0x2000
+#define MII_M1011_PHY_SPEC_STATUS_RESOLVED	0x0800
+#define MII_M1011_PHY_SPEC_STATUS_LINK		0x0400
 
-#define MIIM_88E1011_IEVENT		0x13
-#define MIIM_88E1011_IEVENT_CLEAR	0x0000
+#define MII_M1011_IEVENT		0x13
+#define MII_M1011_IEVENT_CLEAR		0x0000
 
-#define MIIM_88E1011_IMASK		0x12
-#define MIIM_88E1011_IMASK_INIT		0x6400
-#define MIIM_88E1011_IMASK_CLEAR	0x0000
+#define MII_M1011_IMASK			0x12
+#define MII_M1011_IMASK_INIT		0x6400
+#define MII_M1011_IMASK_CLEAR		0x0000
 
-/* DM9161 Control register values */
-#define MIIM_DM9161_CR_STOP	0x0400
-#define MIIM_DM9161_CR_RSTAN	0x1200
-
-#define MIIM_DM9161_SCR		0x10
-#define MIIM_DM9161_SCR_INIT	0x0610
+#define MII_DM9161_SCR		0x10
+#define MII_DM9161_SCR_INIT	0x0610
 
 /* DM9161 Specified Configuration and Status Register */
-#define MIIM_DM9161_SCSR	0x11
-#define MIIM_DM9161_SCSR_100F	0x8000
-#define MIIM_DM9161_SCSR_100H	0x4000
-#define MIIM_DM9161_SCSR_10F	0x2000
-#define MIIM_DM9161_SCSR_10H	0x1000
+#define MII_DM9161_SCSR	0x11
+#define MII_DM9161_SCSR_100F	0x8000
+#define MII_DM9161_SCSR_100H	0x4000
+#define MII_DM9161_SCSR_10F	0x2000
+#define MII_DM9161_SCSR_10H	0x1000
 
 /* DM9161 Interrupt Register */
-#define MIIM_DM9161_INTR	0x15
-#define MIIM_DM9161_INTR_PEND		0x8000
-#define MIIM_DM9161_INTR_DPLX_MASK	0x0800
-#define MIIM_DM9161_INTR_SPD_MASK	0x0400
-#define MIIM_DM9161_INTR_LINK_MASK	0x0200
-#define MIIM_DM9161_INTR_MASK		0x0100
-#define MIIM_DM9161_INTR_DPLX_CHANGE	0x0010
-#define MIIM_DM9161_INTR_SPD_CHANGE	0x0008
-#define MIIM_DM9161_INTR_LINK_CHANGE	0x0004
-#define MIIM_DM9161_INTR_INIT 		0x0000
-#define MIIM_DM9161_INTR_STOP	\
-(MIIM_DM9161_INTR_DPLX_MASK | MIIM_DM9161_INTR_SPD_MASK \
- | MIIM_DM9161_INTR_LINK_MASK | MIIM_DM9161_INTR_MASK)
+#define MII_DM9161_INTR	0x15
+#define MII_DM9161_INTR_PEND		0x8000
+#define MII_DM9161_INTR_DPLX_MASK	0x0800
+#define MII_DM9161_INTR_SPD_MASK	0x0400
+#define MII_DM9161_INTR_LINK_MASK	0x0200
+#define MII_DM9161_INTR_MASK		0x0100
+#define MII_DM9161_INTR_DPLX_CHANGE	0x0010
+#define MII_DM9161_INTR_SPD_CHANGE	0x0008
+#define MII_DM9161_INTR_LINK_CHANGE	0x0004
+#define MII_DM9161_INTR_INIT 		0x0000
+#define MII_DM9161_INTR_STOP	\
+(MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \
+ | MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK)
 
 /* DM9161 10BT Configuration/Status */
-#define MIIM_DM9161_10BTCSR	0x12
-#define MIIM_DM9161_10BTCSR_INIT	0x7800
-
-/* BCM54xx regs */
-#define MIIM_BCM54xx_AUXCONTROL	0x18
-#define MIIM_BCM54xx_AUXSTATUS	0x19
-#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_MASK     0x0700
-#define MIIM_BCM54xx_AUXSTATUS_LINKMODE_SHIFT    8  
-
-#define MIIM_READ_COMMAND       0x00000001
-
-/*
- * struct phy_cmd:  A command for reading or writing a PHY register
- *
- * mii_reg:  The register to read or write
- *
- * mii_data:  For writes, the value to put in the register.
- * 	A value of -1 indicates this is a read.
- *
- * funct: A function pointer which is invoked for each command.
- * 	For reads, this function will be passed the value read
- *	from the PHY, and process it.
- *	For writes, the result of this function will be written
- *	to the PHY register
- */
-struct phy_cmd {
-    u32 mii_reg;
-    u32 mii_data;
-    u16 (*funct) (u16 mii_reg, struct net_device * dev);
+#define MII_DM9161_10BTCSR	0x12
+#define MII_DM9161_10BTCSR_INIT	0x7800
+
+#define MII_BASIC_FEATURES	(SUPPORTED_10baseT_Half | \
+				 SUPPORTED_10baseT_Full | \
+				 SUPPORTED_100baseT_Half | \
+				 SUPPORTED_100baseT_Full | \
+				 SUPPORTED_Autoneg | \
+				 SUPPORTED_TP | \
+				 SUPPORTED_MII)
+
+#define MII_GBIT_FEATURES	(MII_BASIC_FEATURES | \
+				 SUPPORTED_1000baseT_Half | \
+				 SUPPORTED_1000baseT_Full)
+
+#define MII_READ_COMMAND       0x00000001
+
+#define MII_INTERRUPT_DISABLED 0x0
+#define MII_INTERRUPT_ENABLED 0x1
+/* Taken from mii_if_info and sungem_phy.h */
+struct gfar_mii_info {
+	/* Information about the PHY type */
+	/* And management functions */
+	struct phy_info *phyinfo;
+
+	/* forced speed & duplex (no autoneg)
+	 * partner speed & duplex & pause (autoneg)
+	 */
+	int speed;
+	int duplex;
+	int pause;
+
+	/* The most recently read link state */
+	int link;
+
+	/* Enabled Interrupts */
+	u32 interrupts;
+
+	u32 advertising;
+	int autoneg;
+	int mii_id;
+
+	/* private data pointer */
+	/* For use by PHYs to maintain extra state */
+	void *priv;
+
+	/* Provided by host chip */
+	struct net_device *dev;
+
+	/* A lock to ensure that only one thing can read/write
+	 * the MDIO bus at a time */
+	spinlock_t mdio_lock;
+
+	/* Provided by ethernet driver */
+	int (*mdio_read) (struct net_device *dev, int mii_id, int reg);
+	void (*mdio_write) (struct net_device *dev, int mii_id, int reg, int val);
 };
 
 /* struct phy_info: a structure which defines attributes for a PHY
@@ -165,38 +164,50 @@ struct phy_cmd {
  * id will contain a number which represents the PHY.  During
  * startup, the driver will poll the PHY to find out what its
  * UID--as defined by registers 2 and 3--is.  The 32-bit result
- * gotten from the PHY will be shifted right by "shift" bits to
+ * gotten from the PHY will be ANDed with phy_id_mask to
  * discard any bits which may change based on revision numbers
  * unimportant to functionality
  *
- * The struct phy_cmd entries represent pointers to an arrays of
- * commands which tell the driver what to do to the PHY.
+ * There are 6 commands which take a gfar_mii_info structure.
+ * Each PHY must declare config_aneg, and read_status.
  */
 struct phy_info {
-    u32 id;
-    char *name;
-    unsigned int shift;
-    /* Called to configure the PHY, and modify the controller
-     * based on the results */
-    const struct phy_cmd *config;
-
-    /* Called when starting up the controller.  Usually sets
-     * up the interrupt for state changes */
-    const struct phy_cmd *startup;
-
-    /* Called inside the interrupt handler to acknowledge
-     * the interrupt */
-    const struct phy_cmd *ack_int;
-
-    /* Called in the bottom half to handle the interrupt */
-    const struct phy_cmd *handle_int;
-
-    /* Called when bringing down the controller.  Usually stops
-     * the interrupts from being generated */
-    const struct phy_cmd *shutdown;
+	u32 phy_id;
+	char *name;
+	unsigned int phy_id_mask;
+	u32 features;
+
+	/* Called to initialize the PHY */
+	int (*init)(struct gfar_mii_info *mii_info);
+
+	/* Called to suspend the PHY for power */
+	int (*suspend)(struct gfar_mii_info *mii_info);
+
+	/* Reconfigures autonegotiation (or disables it) */
+	int (*config_aneg)(struct gfar_mii_info *mii_info);
+
+	/* Determines the negotiated speed and duplex */
+	int (*read_status)(struct gfar_mii_info *mii_info);
+
+	/* Clears any pending interrupts */
+	int (*ack_interrupt)(struct gfar_mii_info *mii_info);
+
+	/* Enables or disables interrupts */
+	int (*config_intr)(struct gfar_mii_info *mii_info);
+
+	/* Clears up any memory if needed */
+	void (*close)(struct gfar_mii_info *mii_info);
 };
 
-struct phy_info *get_phy_info(struct net_device *dev);
-void phy_run_commands(struct net_device *dev, const struct phy_cmd *cmd);
+struct phy_info *get_phy_info(struct gfar_mii_info *mii_info);
+int read_phy_reg(struct net_device *dev, int mii_id, int regnum);
+void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value);
+void mii_clear_phy_interrupt(struct gfar_mii_info *mii_info);
+void mii_configure_phy_interrupt(struct gfar_mii_info *mii_info, u32 interrupts);
+
+struct dm9161_private {
+	struct timer_list timer;
+	int resetdone;
+};
 
 #endif /* GIANFAR_PHY_H */
diff --git a/drivers/net/gt96100eth.c b/drivers/net/gt96100eth.c
index 0cbf1d143..a41ccc452 100644
--- a/drivers/net/gt96100eth.c
+++ b/drivers/net/gt96100eth.c
@@ -28,7 +28,6 @@
  *                gt96100_cleanup_module(), and other general code cleanups
  *                <stevel@mvista.com>.
  */
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -66,10 +65,6 @@ static int gt96100_add_hash_entry(struct net_device *dev,
 static void read_mib_counters(struct gt96100_private *gp);
 static int read_MII(int phy_addr, u32 reg);
 static int write_MII(int phy_addr, u32 reg, u16 data);
-#if 0
-static void dump_tx_ring(struct net_device *dev);
-static void dump_rx_ring(struct net_device *dev);
-#endif
 static int gt96100_init_module(void);
 static void gt96100_cleanup_module(void);
 static void dump_MII(int dbg_lvl, struct net_device *dev);
@@ -84,7 +79,7 @@ static void abort(struct net_device *dev, u32 abort_bits);
 static void hard_stop(struct net_device *dev);
 static void enable_ether_irq(struct net_device *dev);
 static void disable_ether_irq(struct net_device *dev);
-static int gt96100_probe1(int port_num);
+static int gt96100_probe1(struct pci_dev *pci, int port_num);
 static void reset_tx(struct net_device *dev);
 static void reset_rx(struct net_device *dev);
 static int gt96100_check_tx_consistent(struct gt96100_private *gp);
@@ -164,13 +159,11 @@ chip_name(int chip_rev)
 /*
   DMA memory allocation, derived from pci_alloc_consistent.
 */
-static void *
-dmaalloc(size_t size, dma_addr_t *dma_handle)
+static void * dmaalloc(size_t size, dma_addr_t *dma_handle)
 {
 	void *ret;
 	
-	ret = (void *)__get_free_pages(GFP_ATOMIC | GFP_DMA,
-				       get_order(size));
+	ret = (void *)__get_free_pages(GFP_ATOMIC | GFP_DMA, get_order(size));
 	
 	if (ret != NULL) {
 		dma_cache_inv((unsigned long)ret, size);
@@ -184,17 +177,13 @@ dmaalloc(size_t size, dma_addr_t *dma_handle)
 	return ret;
 }
 
-static void
-dmafree(size_t size, void *vaddr)
+static void dmafree(size_t size, void *vaddr)
 {
 	vaddr = (void*)KSEG0ADDR(vaddr);
 	free_pages((unsigned long)vaddr, get_order(size));
 }
 
-
-
-static void
-gt96100_delay(int ms)
+static void gt96100_delay(int ms)
 {
 	if (in_interrupt())
 		return;
@@ -327,34 +316,6 @@ write_MII(int phy_addr, u32 reg, u16 data)
 	return 0;
 }
 
-#if 0
-// These routines work, just disabled to avoid compile warnings
-static void
-dump_tx_ring(struct net_device *dev)
-{
-	struct gt96100_private *gp = netdev_priv(dev);
-	int i;
-
-	dbg(0, "%s: txno/txni/cnt=%d/%d/%d\n", __FUNCTION__,
-	    gp->tx_next_out, gp->tx_next_in, gp->tx_count);
-
-	for (i=0; i<TX_RING_SIZE; i++)
-		dump_tx_desc(0, dev, i);
-}
-
-static void
-dump_rx_ring(struct net_device *dev)
-{
-	struct gt96100_private *gp = netdev_priv(dev);
-	int i;
-
-	dbg(0, "%s: rxno=%d\n", __FUNCTION__, gp->rx_next_out);
-
-	for (i=0; i<RX_RING_SIZE; i++)
-		dump_rx_desc(0, dev, i);
-}
-#endif
-
 static void
 dump_MII(int dbg_lvl, struct net_device *dev)
 {
@@ -647,23 +608,19 @@ disable_ether_irq(struct net_device *dev)
 /*
  * Init GT96100 ethernet controller driver
  */
-int gt96100_init_module(void)
+static int gt96100_init_module(void)
 {
+	struct pci_dev *pci;
 	int i, retval=0;
-	u16 vendor_id, device_id;
 	u32 cpuConfig;
 
-#ifndef CONFIG_MIPS_GT96100ETH
-	return -ENODEV;
-#endif
-
-	// probe for GT96100 by reading PCI0 vendor/device ID register
-	pcibios_read_config_word(0, 0, PCI_VENDOR_ID, &vendor_id);
-	pcibios_read_config_word(0, 0, PCI_DEVICE_ID, &device_id);
-    
-	if (vendor_id != PCI_VENDOR_ID_MARVELL ||
-	    (device_id != PCI_DEVICE_ID_MARVELL_GT96100 &&
-	     device_id != PCI_DEVICE_ID_MARVELL_GT96100A)) {
+	/*
+	 * Stupid probe because this really isn't a PCI device
+	 */
+	if (!(pci = pci_find_device(PCI_VENDOR_ID_MARVELL,
+	                            PCI_DEVICE_ID_MARVELL_GT96100, NULL)) &&
+	    !(pci = pci_find_device(PCI_VENDOR_ID_MARVELL,
+		                    PCI_DEVICE_ID_MARVELL_GT96100A, NULL))) {
 		printk(KERN_ERR __FILE__ ": GT96100 not found!\n");
 		return -ENODEV;
 	}
@@ -675,17 +632,13 @@ int gt96100_init_module(void)
 		return -ENODEV;
 	}
 
-	for (i=0; i < NUM_INTERFACES; i++) {
-		retval |= gt96100_probe1(i);
-	}
+	for (i=0; i < NUM_INTERFACES; i++)
+		retval |= gt96100_probe1(pci, i);
 
 	return retval;
 }
 
-
-
-static int __init
-gt96100_probe1(int port_num)
+static int __init gt96100_probe1(struct pci_dev *pci, int port_num)
 {
 	struct gt96100_private *gp = NULL;
 	struct gt96100_if_t *gtif = &gt96100_iflist[port_num];
@@ -696,19 +649,19 @@ gt96100_probe1(int port_num)
 	struct net_device *dev = NULL;
     
 	if (gtif->irq < 0) {
-		printk(KERN_ERR "%s: irq unknown - probing not supported\n", __FUNCTION_);
+		printk(KERN_ERR "%s: irq unknown - probing not supported\n",
+		      __FUNCTION__);
 		return -ENODEV;
 	}
     
-	pcibios_read_config_byte(0, 0, PCI_REVISION_ID, &chip_rev);
+	pci_read_config_byte(pci, PCI_REVISION_ID, &chip_rev);
 
 	if (chip_rev >= REV_GT96100A_1) {
 		phyAD = GT96100_READ(GT96100_ETH_PHY_ADDR_REG);
 		phy_addr = (phyAD >> (5*port_num)) & 0x1f;
 	} else {
 		/*
-		 * not sure what's this about -- probably 
-		 * a gt bug
+		 * not sure what's this about -- probably a gt bug
 		 */
 		phy_addr = port_num;
 		phyAD = GT96100_READ(GT96100_ETH_PHY_ADDR_REG);
@@ -831,6 +784,7 @@ out1:
 	free_netdev (dev);
 out:
 	release_region(gtif->iobase, GT96100_ETH_IO_SIZE);
+
 	err("%s failed.  Returns %d\n", __FUNCTION__, retval);
 	return retval;
 }
@@ -1102,6 +1056,7 @@ gt96100_close(struct net_device *dev)
 	}
 
 	free_irq(dev->irq, dev);
+    
 	return 0;
 }
 
@@ -1312,10 +1267,11 @@ gt96100_tx_complete(struct net_device *dev, u32 status)
 		    cmdstat, nextOut);
 	
 		if (cmdstat & (u32)txOwn) {
-			//dump_tx_ring(dev);
-			// DMA is not finished writing descriptor???
-			// Leave and come back later to pick-up where
-			// we left off.
+			/*
+			 * DMA is not finished writing descriptor???
+			 * Leave and come back later to pick-up where
+			 * we left off.
+			 */
 			break;
 		}
 	
@@ -1342,7 +1298,8 @@ gt96100_tx_complete(struct net_device *dev, u32 status)
 			gp->tx_full = 0;
 			if (gp->last_psr & psrLink) {
 				netif_wake_queue(dev);
-				dbg(2, "%s: Tx Ring was full, queue waked\n", __FUNCTION_);
+				dbg(2, "%s: Tx Ring was full, queue waked\n",
+				    __FUNCTION__);
 			}
 		}
 	
@@ -1425,12 +1382,12 @@ gt96100_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 		
 				if ((psr & psrLink) && !gp->tx_full &&
 				    netif_queue_stopped(dev)) {
-					dbg(0, ": Link up, waking queue.\n",
-					    __FUNCTION_);
+					dbg(0, "%s: Link up, waking queue.\n",
+					    __FUNCTION__);
 					netif_wake_queue(dev);
 				} else if (!(psr & psrLink) &&
 					   !netif_queue_stopped(dev)) {
-					dbg(0, "Link down, stopping queue.\n",
+					dbg(0, "%s: Link down, stopping queue.\n",
 					    __FUNCTION__);
 					netif_stop_queue(dev);
 				}
@@ -1569,8 +1526,8 @@ static void gt96100_cleanup_module(void)
 	for (i=0; i<NUM_INTERFACES; i++) {
 		struct gt96100_if_t *gtif = &gt96100_iflist[i];
 		if (gtif->dev != NULL) {
-			struct gt96100_private *gp =
-				(struct gt96100_private *)gtif->dev->priv;
+			struct gt96100_private *gp = (struct gt96100_private *)
+				netdev_priv(gtif->dev);
 			unregister_netdev(gtif->dev);
 			dmafree(RX_HASH_TABLE_SIZE, gp->hash_table_dma);
 			dmafree(PKT_BUF_SZ*RX_RING_SIZE, gp->rx_buff);
@@ -1583,9 +1540,6 @@ static void gt96100_cleanup_module(void)
 	}
 }
 
-
-#ifndef MODULE
-
 static int __init gt96100_setup(char *options)
 {
 	char *this_opt;
@@ -1610,9 +1564,6 @@ static int __init gt96100_setup(char *options)
 
 __setup("gt96100eth=", gt96100_setup);
 
-#endif /* !MODULE */
-
-
 module_init(gt96100_init_module);
 module_exit(gt96100_cleanup_module);
 
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
index b5169e849..6b0cb2cab 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/hamachi.c
@@ -559,7 +559,7 @@ static void hamachi_tx_timeout(struct net_device *dev);
 static void hamachi_init_ring(struct net_device *dev);
 static int hamachi_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t hamachi_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
-static inline int hamachi_rx(struct net_device *dev);
+static int hamachi_rx(struct net_device *dev);
 static inline int hamachi_tx(struct net_device *dev);
 static void hamachi_error(struct net_device *dev, int intr_status);
 static int hamachi_close(struct net_device *dev);
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index 6b85ab3c9..803d5a137 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -193,7 +193,7 @@ static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
 
 	bpq = (struct bpqdev *)dev->priv;
 
-	eth = (struct ethhdr *)skb->mac.raw;
+	eth = eth_hdr(skb);
 
 	if (!(bpq->acpt_addr[0] & 0x01) &&
 	    memcmp(eth->h_source, bpq->acpt_addr, ETH_ALEN))
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index 9f3dac7d2..4beb7ac2a 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -246,8 +246,14 @@ static int scc_send_packet(struct sk_buff *skb, struct net_device *dev);
 static struct net_device_stats *scc_get_stats(struct net_device *dev);
 static int scc_set_mac_address(struct net_device *dev, void *sa);
 
-static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs * regs);
+static inline void tx_on(struct scc_priv *priv);
+static inline void rx_on(struct scc_priv *priv);
+static inline void rx_off(struct scc_priv *priv);
+static void start_timer(struct scc_priv *priv, int t, int r15);
+static inline unsigned char random(void);
+
 static inline void z8530_isr(struct scc_info *info);
+static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs * regs);
 static void rx_isr(struct scc_priv *priv);
 static void special_condition(struct scc_priv *priv, int rc);
 static void rx_bh(void *arg);
@@ -255,12 +261,6 @@ static void tx_isr(struct scc_priv *priv);
 static void es_isr(struct scc_priv *priv);
 static void tm_isr(struct scc_priv *priv);
 
-static inline void tx_on(struct scc_priv *priv);
-static inline void rx_on(struct scc_priv *priv);
-static inline void rx_off(struct scc_priv *priv);
-static void start_timer(struct scc_priv *priv, int t, int r15);
-static inline unsigned char random(void);
-
 
 /* Initialization variables */
 
@@ -945,42 +945,115 @@ static int scc_set_mac_address(struct net_device *dev, void *sa) {
 }
 
 
-static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs * regs) {
-  struct scc_info *info = dev_id;
+static inline void tx_on(struct scc_priv *priv) {
+  int i, n;
+  unsigned long flags;
 
-  spin_lock(info->priv[0].register_lock);
-  /* At this point interrupts are enabled, and the interrupt under service
-     is already acknowledged, but masked off.
+  if (priv->param.dma >= 0) {
+    n = (priv->chip == Z85230) ? 3 : 1;
+    /* Program DMA controller */
+    flags = claim_dma_lock();
+    set_dma_mode(priv->param.dma, DMA_MODE_WRITE);
+    set_dma_addr(priv->param.dma, (int) priv->tx_buf[priv->tx_tail]+n);
+    set_dma_count(priv->param.dma, priv->tx_len[priv->tx_tail]-n);
+    release_dma_lock(flags);
+    /* Enable TX underrun interrupt */
+    write_scc(priv, R15, TxUIE);
+    /* Configure DREQ */
+    if (priv->type == TYPE_TWIN)
+      outb((priv->param.dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3,
+	   priv->card_base + TWIN_DMA_CFG);
+    else
+      write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB);
+    /* Write first byte(s) */
+    spin_lock_irqsave(priv->register_lock, flags);
+    for (i = 0; i < n; i++)
+      write_scc_data(priv, priv->tx_buf[priv->tx_tail][i], 1);
+    enable_dma(priv->param.dma);
+    spin_unlock_irqrestore(priv->register_lock, flags);
+  } else {
+    write_scc(priv, R15, TxUIE);
+    write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB);
+    tx_isr(priv);
+  }
+  /* Reset EOM latch if we do not have the AUTOEOM feature */
+  if (priv->chip == Z8530) write_scc(priv, R0, RES_EOM_L);
+}
 
-     Interrupt processing: We loop until we know that the IRQ line is
-     low. If another positive edge occurs afterwards during the ISR,
-     another interrupt will be triggered by the interrupt controller
-     as soon as the IRQ level is enabled again (see asm/irq.h).
 
-     Bottom-half handlers will be processed after scc_isr(). This is
-     important, since we only have small ringbuffers and want new data
-     to be fetched/delivered immediately. */
+static inline void rx_on(struct scc_priv *priv) {
+  unsigned long flags;
 
-  if (info->priv[0].type == TYPE_TWIN) {
-    int is, card_base = info->priv[0].card_base;
-    while ((is = ~inb(card_base + TWIN_INT_REG)) &
-	   TWIN_INT_MSK) {
-      if (is & TWIN_SCC_MSK) {
-	z8530_isr(info);
-      } else if (is & TWIN_TMR1_MSK) {
-	inb(card_base + TWIN_CLR_TMR1);
-	tm_isr(&info->priv[0]);
-      } else {
-	inb(card_base + TWIN_CLR_TMR2);
-	tm_isr(&info->priv[1]);
-      }
+  /* Clear RX FIFO */
+  while (read_scc(priv, R0) & Rx_CH_AV) read_scc_data(priv);
+  priv->rx_over = 0;
+  if (priv->param.dma >= 0) {
+    /* Program DMA controller */
+    flags = claim_dma_lock();
+    set_dma_mode(priv->param.dma, DMA_MODE_READ);
+    set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]);
+    set_dma_count(priv->param.dma, BUF_SIZE);
+    release_dma_lock(flags);
+    enable_dma(priv->param.dma);
+    /* Configure PackeTwin DMA */
+    if (priv->type == TYPE_TWIN) {
+      outb((priv->param.dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3,
+	   priv->card_base + TWIN_DMA_CFG);
     }
-  } else z8530_isr(info);
-  spin_unlock(info->priv[0].register_lock);
-  return IRQ_HANDLED;
+    /* Sp. cond. intr. only, ext int enable, RX DMA enable */
+    write_scc(priv, R1, EXT_INT_ENAB | INT_ERR_Rx |
+	      WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB);
+  } else {
+    /* Reset current frame */
+    priv->rx_ptr = 0;
+    /* Intr. on all Rx characters and Sp. cond., ext int enable */
+    write_scc(priv, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT |
+	      WT_FN_RDYFN);
+  }
+  write_scc(priv, R0, ERR_RES);
+  write_scc(priv, R3, RxENABLE | Rx8 | RxCRC_ENAB);
+}
+
+
+static inline void rx_off(struct scc_priv *priv) {
+  /* Disable receiver */
+  write_scc(priv, R3, Rx8);
+  /* Disable DREQ / RX interrupt */
+  if (priv->param.dma >= 0 && priv->type == TYPE_TWIN)
+    outb(0, priv->card_base + TWIN_DMA_CFG);
+  else
+    write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
+  /* Disable DMA */
+  if (priv->param.dma >= 0) disable_dma(priv->param.dma);
+}
+
+
+static void start_timer(struct scc_priv *priv, int t, int r15) {
+  unsigned long flags;
+
+  outb(priv->tmr_mode, priv->tmr_ctrl);
+  if (t == 0) {
+    tm_isr(priv);
+  } else if (t > 0) {
+    save_flags(flags);
+    cli();
+    outb(t & 0xFF, priv->tmr_cnt);
+    outb((t >> 8) & 0xFF, priv->tmr_cnt);
+    if (priv->type != TYPE_TWIN) {
+      write_scc(priv, R15, r15 | CTSIE);
+      priv->rr0 |= CTS;
+    }
+    restore_flags(flags);
+  }
 }
 
 
+static inline unsigned char random(void) {
+  /* See "Numerical Recipes in C", second edition, p. 284 */
+  rand = rand * 1664525L + 1013904223L;
+  return (unsigned char) (rand >> 24);
+}
+
 static inline void z8530_isr(struct scc_info *info) {
   int is, i = 100;
 
@@ -1009,6 +1082,42 @@ static inline void z8530_isr(struct scc_info *info) {
 }
 
 
+static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs * regs) {
+  struct scc_info *info = dev_id;
+
+  spin_lock(info->priv[0].register_lock);
+  /* At this point interrupts are enabled, and the interrupt under service
+     is already acknowledged, but masked off.
+
+     Interrupt processing: We loop until we know that the IRQ line is
+     low. If another positive edge occurs afterwards during the ISR,
+     another interrupt will be triggered by the interrupt controller
+     as soon as the IRQ level is enabled again (see asm/irq.h).
+
+     Bottom-half handlers will be processed after scc_isr(). This is
+     important, since we only have small ringbuffers and want new data
+     to be fetched/delivered immediately. */
+
+  if (info->priv[0].type == TYPE_TWIN) {
+    int is, card_base = info->priv[0].card_base;
+    while ((is = ~inb(card_base + TWIN_INT_REG)) &
+	   TWIN_INT_MSK) {
+      if (is & TWIN_SCC_MSK) {
+	z8530_isr(info);
+      } else if (is & TWIN_TMR1_MSK) {
+	inb(card_base + TWIN_CLR_TMR1);
+	tm_isr(&info->priv[0]);
+      } else {
+	inb(card_base + TWIN_CLR_TMR2);
+	tm_isr(&info->priv[1]);
+      }
+    }
+  } else z8530_isr(info);
+  spin_unlock(info->priv[0].register_lock);
+  return IRQ_HANDLED;
+}
+
+
 static void rx_isr(struct scc_priv *priv) {
   if (priv->param.dma >= 0) {
     /* Check special condition and perform error reset. See 2.4.7.5. */
@@ -1292,114 +1401,3 @@ static void tm_isr(struct scc_priv *priv) {
     break;
   }
 }
-
-
-static inline void tx_on(struct scc_priv *priv) {
-  int i, n;
-  unsigned long flags;
-
-  if (priv->param.dma >= 0) {
-    n = (priv->chip == Z85230) ? 3 : 1;
-    /* Program DMA controller */
-    flags = claim_dma_lock();
-    set_dma_mode(priv->param.dma, DMA_MODE_WRITE);
-    set_dma_addr(priv->param.dma, (int) priv->tx_buf[priv->tx_tail]+n);
-    set_dma_count(priv->param.dma, priv->tx_len[priv->tx_tail]-n);
-    release_dma_lock(flags);
-    /* Enable TX underrun interrupt */
-    write_scc(priv, R15, TxUIE);
-    /* Configure DREQ */
-    if (priv->type == TYPE_TWIN)
-      outb((priv->param.dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3,
-	   priv->card_base + TWIN_DMA_CFG);
-    else
-      write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB);
-    /* Write first byte(s) */
-    spin_lock_irqsave(priv->register_lock, flags);
-    for (i = 0; i < n; i++)
-      write_scc_data(priv, priv->tx_buf[priv->tx_tail][i], 1);
-    enable_dma(priv->param.dma);
-    spin_unlock_irqrestore(priv->register_lock, flags);
-  } else {
-    write_scc(priv, R15, TxUIE);
-    write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB);
-    tx_isr(priv);
-  }
-  /* Reset EOM latch if we do not have the AUTOEOM feature */
-  if (priv->chip == Z8530) write_scc(priv, R0, RES_EOM_L);
-}
-
-
-static inline void rx_on(struct scc_priv *priv) {
-  unsigned long flags;
-
-  /* Clear RX FIFO */
-  while (read_scc(priv, R0) & Rx_CH_AV) read_scc_data(priv);
-  priv->rx_over = 0;
-  if (priv->param.dma >= 0) {
-    /* Program DMA controller */
-    flags = claim_dma_lock();
-    set_dma_mode(priv->param.dma, DMA_MODE_READ);
-    set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]);
-    set_dma_count(priv->param.dma, BUF_SIZE);
-    release_dma_lock(flags);
-    enable_dma(priv->param.dma);
-    /* Configure PackeTwin DMA */
-    if (priv->type == TYPE_TWIN) {
-      outb((priv->param.dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3,
-	   priv->card_base + TWIN_DMA_CFG);
-    }
-    /* Sp. cond. intr. only, ext int enable, RX DMA enable */
-    write_scc(priv, R1, EXT_INT_ENAB | INT_ERR_Rx |
-	      WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB);
-  } else {
-    /* Reset current frame */
-    priv->rx_ptr = 0;
-    /* Intr. on all Rx characters and Sp. cond., ext int enable */
-    write_scc(priv, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT |
-	      WT_FN_RDYFN);
-  }
-  write_scc(priv, R0, ERR_RES);
-  write_scc(priv, R3, RxENABLE | Rx8 | RxCRC_ENAB);
-}
-
-
-static inline void rx_off(struct scc_priv *priv) {
-  /* Disable receiver */
-  write_scc(priv, R3, Rx8);
-  /* Disable DREQ / RX interrupt */
-  if (priv->param.dma >= 0 && priv->type == TYPE_TWIN)
-    outb(0, priv->card_base + TWIN_DMA_CFG);
-  else
-    write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
-  /* Disable DMA */
-  if (priv->param.dma >= 0) disable_dma(priv->param.dma);
-}
-
-
-static void start_timer(struct scc_priv *priv, int t, int r15) {
-  unsigned long flags;
-
-  outb(priv->tmr_mode, priv->tmr_ctrl);
-  if (t == 0) {
-    tm_isr(priv);
-  } else if (t > 0) {
-    save_flags(flags);
-    cli();
-    outb(t & 0xFF, priv->tmr_cnt);
-    outb((t >> 8) & 0xFF, priv->tmr_cnt);
-    if (priv->type != TYPE_TWIN) {
-      write_scc(priv, R15, r15 | CTSIE);
-      priv->rr0 |= CTS;
-    }
-    restore_flags(flags);
-  }
-}
-
-
-static inline unsigned char random(void) {
-  /* See "Numerical Recipes in C", second edition, p. 284 */
-  rand = rand * 1664525L + 1013904223L;
-  return (unsigned char) (rand >> 24);
-}
-
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index c7076aa0b..e2a28b562 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -602,8 +602,6 @@ static int ax25_open(struct tty_struct *tty)
 
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
 
 	/* Restore default settings */
 	ax->dev->type = ARPHRD_AX25;
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index 78ae4b2ac..3c783a459 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -2906,13 +2906,19 @@ static struct eisa_driver hp100_eisa_driver = {
 static int __devinit hp100_pci_probe (struct pci_dev *pdev,
 				     const struct pci_device_id *ent)
 {
-	struct net_device *dev = alloc_etherdev(sizeof(struct hp100_private));
-	int ioaddr = pci_resource_start(pdev, 0);
+	struct net_device *dev;
+	int ioaddr;
 	u_short pci_command;
 	int err;
-	
-	if (!dev)
-		return -ENOMEM;
+
+	if (pci_enable_device(pdev))
+		return -ENODEV;
+
+	dev = alloc_etherdev(sizeof(struct hp100_private));
+	if (!dev) {
+		err = -ENOMEM;
+		goto out0;
+	}
 
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
@@ -2934,7 +2940,7 @@ static int __devinit hp100_pci_probe (struct pci_dev *pdev,
 		pci_write_config_word(pdev, PCI_COMMAND, pci_command);
 	}
 	
-
+	ioaddr = pci_resource_start(pdev, 0);
 	err = hp100_probe1(dev, ioaddr, HP100_BUS_PCI, pdev);
 	if (err) 
 		goto out1;
@@ -2951,6 +2957,8 @@ static int __devinit hp100_pci_probe (struct pci_dev *pdev,
 	release_region(dev->base_addr, HP100_REGION_SIZE);
  out1:
 	free_netdev(dev);
+ out0:
+	pci_disable_device(pdev);
 	return err;
 }
 
@@ -2959,6 +2967,7 @@ static void __devexit hp100_pci_remove (struct pci_dev *pdev)
 	struct net_device *dev = pci_get_drvdata(pdev);
 
 	cleanup_dev(dev);
+	pci_disable_device(pdev);
 }
 
 
diff --git a/drivers/net/ibm_emac/ibm_emac.h b/drivers/net/ibm_emac/ibm_emac.h
index 5310033ad..7436af605 100644
--- a/drivers/net/ibm_emac/ibm_emac.h
+++ b/drivers/net/ibm_emac/ibm_emac.h
@@ -228,6 +228,21 @@ typedef struct emac_regs {
 	 (desc & EMAC_BAD_RX_PACKET)
 #endif
 
+/* SoC implementation specific EMAC register defaults */
+#if defined(CONFIG_440GP)
+#define EMAC_RWMR_DEFAULT		0x80009000
+#define EMAC_TMR0_DEFAULT		0x00000000
+#define EMAC_TMR1_DEFAULT		0xf8640000
+#elif defined(CONFIG_440GX)
+#define EMAC_RWMR_DEFAULT		0x1000a200
+#define EMAC_TMR0_DEFAULT		EMAC_TMR0_TFAE_2_32
+#define EMAC_TMR1_DEFAULT		0xa00f0000
+#else
+#define EMAC_RWMR_DEFAULT		0x0f002000
+#define EMAC_TMR0_DEFAULT		0x00000000
+#define EMAC_TMR1_DEFAULT		0x380f0000
+#endif				/* CONFIG_440GP */
+
 /* Revision specific EMAC register defaults */
 #ifdef CONFIG_IBM_EMAC4
 #define EMAC_M1_DEFAULT			(EMAC_M1_BASE | \
@@ -236,7 +251,7 @@ typedef struct emac_regs {
 #define EMAC_RMR_DEFAULT		(EMAC_RMR_BASE | \
 					EMAC_RMR_RFAF_128_2048)
 #define EMAC_TMR0_XMIT			(EMAC_TMR0_GNP0 | \
-					EMAC_TMR0_TFAE_128_2048)
+					EMAC_TMR0_DEFAULT)
 #define EMAC_TRTR_DEFAULT		EMAC_TRTR_1024
 #else				/* !CONFIG_IBM_EMAC4 */
 #define EMAC_M1_DEFAULT			EMAC_M1_BASE
@@ -245,19 +260,4 @@ typedef struct emac_regs {
 #define EMAC_TRTR_DEFAULT		EMAC_TRTR_1600
 #endif				/* CONFIG_IBM_EMAC4 */
 
-/* SoC implementation specific EMAC register defaults */
-#if defined(CONFIG_440GP)
-#define EMAC_RWMR_DEFAULT		0x80009000
-#define EMAC_TMR0_DEFAULT		0x00000000
-#define EMAC_TMR1_DEFAULT		0xf8640000
-#elif defined(CONFIG_440GX)
-#define EMAC_RWMR_DEFAULT		0x1000a200
-#define EMAC_TMR0_DEFAULT		EMAC_TMR0_TFAE_128_2048
-#define EMAC_TMR1_DEFAULT		0x88810000
-#else
-#define EMAC_RWMR_DEFAULT		0x0f002000
-#define EMAC_TMR0_DEFAULT		0x00000000
-#define EMAC_TMR1_DEFAULT		0x380f0000
-#endif				/* CONFIG_440GP */
-
 #endif
diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c
index 2ca3de076..6b0328fbc 100644
--- a/drivers/net/ibm_emac/ibm_emac_core.c
+++ b/drivers/net/ibm_emac/ibm_emac_core.c
@@ -90,23 +90,24 @@ MODULE_PARM_DESC(skb_res, "Amount of data to reserve on skb buffs\n"
 
 #define RGMII_PRIV(ocpdev) ((struct ibm_ocp_rgmii*)ocp_get_drvdata(ocpdev))
 
-static unsigned int rgmii_enable[] =
-    { RGMII_RTBI, RGMII_RGMII, RGMII_TBI, RGMII_GMII };
+static unsigned int rgmii_enable[] = {
+	RGMII_RTBI,
+	RGMII_RGMII,
+	RGMII_TBI,
+	RGMII_GMII
+};
 
-static unsigned int rgmii_speed_mask[] = { 0,
-	0,
+static unsigned int rgmii_speed_mask[] = {
 	RGMII_MII2_SPDMASK,
 	RGMII_MII3_SPDMASK
 };
 
-static unsigned int rgmii_speed100[] = { 0,
-	0,
+static unsigned int rgmii_speed100[] = {
 	RGMII_MII2_100MB,
 	RGMII_MII3_100MB
 };
 
-static unsigned int rgmii_speed1000[] = { 0,
-	0,
+static unsigned int rgmii_speed1000[] = {
 	RGMII_MII2_1000MB,
 	RGMII_MII3_1000MB
 };
@@ -122,11 +123,21 @@ static unsigned int zmii_enable[][4] = {
 	 ~(ZMII_MDI0 | ZMII_MDI1 | ZMII_MDI3)},
 	{ZMII_SMII3, ZMII_RMII3, ZMII_MII3, ~(ZMII_MDI0 | ZMII_MDI1 | ZMII_MDI2)}
 };
-static unsigned int mdi_enable[] =
-    { ZMII_MDI0, ZMII_MDI1, ZMII_MDI2, ZMII_MDI3 };
+
+static unsigned int mdi_enable[] = {
+	ZMII_MDI0,
+	ZMII_MDI1,
+	ZMII_MDI2,
+	ZMII_MDI3
+};
 
 static unsigned int zmii_speed = 0x0;
-static unsigned int zmii_speed100[] = { ZMII_MII0_100MB, ZMII_MII1_100MB };
+static unsigned int zmii_speed100[] = {
+	ZMII_MII0_100MB,
+	ZMII_MII1_100MB,
+	ZMII_MII2_100MB,
+	ZMII_MII3_100MB
+};
 
 /* Since multiple EMACs share MDIO lines in various ways, we need
  * to avoid re-using the same PHY ID in cases where the arch didn't
@@ -367,6 +378,7 @@ static void emac_close_zmii(struct ocp_device *ocpdev)
 
 int emac_phy_read(struct net_device *dev, int mii_id, int reg)
 {
+	int count;
 	uint32_t stacr;
 	struct ocp_enet_private *fep = dev->priv;
 	emac_t *emacp = fep->emacp;
@@ -385,9 +397,13 @@ int emac_phy_read(struct net_device *dev, int mii_id, int reg)
 		emacp = fep->emacp;
 	}
 
-	udelay(MDIO_DELAY);
+	count = 0;
+	while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0)
+					&& (count++ < MDIO_DELAY))
+		udelay(1);
+	MDIO_DEBUG((" (count was %d)\n", count));
 
-	if ((in_be32(&emacp->em0stacr) & EMAC_STACR_OC) == 0) {
+	if ((stacr & EMAC_STACR_OC) == 0) {
 		printk(KERN_WARNING "%s: PHY read timeout #1!\n", dev->name);
 		return -1;
 	}
@@ -398,8 +414,11 @@ int emac_phy_read(struct net_device *dev, int mii_id, int reg)
 
 	out_be32(&emacp->em0stacr, stacr);
 
-	udelay(MDIO_DELAY);
-	stacr = in_be32(&emacp->em0stacr);
+	count = 0;
+	while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0)
+					&& (count++ < MDIO_DELAY))
+		udelay(1);
+	MDIO_DEBUG((" (count was %d)\n", count));
 
 	if ((stacr & EMAC_STACR_OC) == 0) {
 		printk(KERN_WARNING "%s: PHY read timeout #2!\n", dev->name);
@@ -419,6 +438,7 @@ int emac_phy_read(struct net_device *dev, int mii_id, int reg)
 
 void emac_phy_write(struct net_device *dev, int mii_id, int reg, int data)
 {
+	int count;
 	uint32_t stacr;
 	struct ocp_enet_private *fep = dev->priv;
 	emac_t *emacp = fep->emacp;
@@ -437,9 +457,13 @@ void emac_phy_write(struct net_device *dev, int mii_id, int reg, int data)
 		emacp = fep->emacp;
 	}
 
-	udelay(MDIO_DELAY);
+	count = 0;
+	while ((((stacr = in_be32(&emacp->em0stacr)) & EMAC_STACR_OC) == 0)
+					&& (count++ < MDIO_DELAY))
+		udelay(1);
+	MDIO_DEBUG((" (count was %d)\n", count));
 
-	if ((in_be32(&emacp->em0stacr) & EMAC_STACR_OC) == 0) {
+	if ((stacr & EMAC_STACR_OC) == 0) {
 		printk(KERN_WARNING "%s: PHY write timeout #2!\n", dev->name);
 		return;
 	}
@@ -451,9 +475,12 @@ void emac_phy_write(struct net_device *dev, int mii_id, int reg, int data)
 
 	out_be32(&emacp->em0stacr, stacr);
 
-	udelay(MDIO_DELAY);
+	while (((stacr = in_be32(&emacp->em0stacr) & EMAC_STACR_OC) == 0)
+					&& (count++ < 5000))
+		udelay(1);
+	MDIO_DEBUG((" (count was %d)\n", count));
 
-	if ((in_be32(&emacp->em0stacr) & EMAC_STACR_OC) == 0)
+	if ((stacr & EMAC_STACR_OC) == 0)
 		printk(KERN_WARNING "%s: PHY write timeout #2!\n", dev->name);
 
 	/* Check for a write error */
@@ -1940,8 +1967,6 @@ static struct ocp_driver emac_driver = {
 
 static int __init emac_init(void)
 {
-	int rc;
-
 	printk(KERN_INFO DRV_NAME ": " DRV_DESC ", version " DRV_VERSION "\n");
 	printk(KERN_INFO "Maintained by " DRV_AUTHOR "\n");
 
@@ -1950,13 +1975,8 @@ static int __init emac_init(void)
 		       skb_res);
 		skb_res = 2;
 	}
-	rc = ocp_register_driver(&emac_driver);
-	if (rc < 0) {
-		ocp_unregister_driver(&emac_driver);
-		return -ENODEV;
-	}
 
-	return 0;
+	return ocp_register_driver(&emac_driver);
 }
 
 static void __exit emac_exit(void)
diff --git a/drivers/net/ibm_emac/ibm_emac_core.h b/drivers/net/ibm_emac/ibm_emac_core.h
index 691ce4e5c..97e6e1ea8 100644
--- a/drivers/net/ibm_emac/ibm_emac_core.h
+++ b/drivers/net/ibm_emac/ibm_emac_core.h
@@ -67,7 +67,7 @@
 #define TX_TIMEOUT		(2*HZ)
 
 /* MDIO latency delay */
-#define MDIO_DELAY		50
+#define MDIO_DELAY		250
 
 /* Power managment shift registers */
 #define IBM_CPM_EMMII	0	/* Shift value for MII */
diff --git a/drivers/net/ibm_emac/ibm_emac_mal.c b/drivers/net/ibm_emac/ibm_emac_mal.c
index 02d847cfa..6597791a7 100644
--- a/drivers/net/ibm_emac/ibm_emac_mal.c
+++ b/drivers/net/ibm_emac/ibm_emac_mal.c
@@ -55,8 +55,6 @@ int mal_register_commac(struct ibm_ocp_mal *mal, struct mal_commac *commac)
 
 	write_unlock_irqrestore(&mal_list_lock, flags);
 
-	MOD_INC_USE_COUNT;
-
 	return 0;
 }
 
@@ -73,8 +71,6 @@ int mal_unregister_commac(struct ibm_ocp_mal *mal, struct mal_commac *commac)
 
 	write_unlock_irqrestore(&mal_list_lock, flags);
 
-	MOD_DEC_USE_COUNT;
-
 	return 0;
 }
 
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index 5fa162f6c..be0729dfb 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -2,8 +2,8 @@
 /*                                                                        */
 /* IBM eServer i/pSeries Virtual Ethernet Device Driver                   */
 /* Copyright (C) 2003 IBM Corp.                                           */
-/*  Dave Larson (larson1@us.ibm.com)                                      */
-/*  Santiago Leon (santil@us.ibm.com)                                     */
+/*  Originally written by Dave Larson (larson1@us.ibm.com)                */
+/*  Maintained by Santiago Leon (santil@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  */
@@ -104,11 +104,12 @@ static struct proc_dir_entry *ibmveth_proc_dir;
 
 static const char ibmveth_driver_name[] = "ibmveth";
 static const char ibmveth_driver_string[] = "IBM i/pSeries Virtual Ethernet Driver";
-static const char ibmveth_driver_version[] = "1.0";
+#define ibmveth_driver_version "1.02"
 
-MODULE_AUTHOR("Dave Larson <larson1@us.ibm.com>");
+MODULE_AUTHOR("Santiago Leon <santil@us.ibm.com>");
 MODULE_DESCRIPTION("IBM i/pSeries Virtual Ethernet Driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(ibmveth_driver_version);
 
 /* simple methods of getting data from the current rxq entry */
 static inline int ibmveth_rxq_pending_buffer(struct ibmveth_adapter *adapter)
@@ -213,11 +214,12 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
 		free_index = pool->consumer_index++ % pool->size;
 		index = pool->free_map[free_index];
 	
-		ibmveth_assert(index != 0xffff);
+		ibmveth_assert(index != IBM_VETH_INVALID_MAP);
 		ibmveth_assert(pool->skbuff[index] == NULL);
 
 		dma_addr = vio_map_single(adapter->vdev, skb->data, pool->buff_size, DMA_FROM_DEVICE);
 
+		pool->free_map[free_index] = IBM_VETH_INVALID_MAP;
 		pool->dma_addr[index] = dma_addr;
 		pool->skbuff[index] = skb;
 
@@ -232,6 +234,7 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
 		lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
 		    
 		if(lpar_rc != H_Success) {
+			pool->free_map[free_index] = IBM_VETH_INVALID_MAP;
 			pool->skbuff[index] = NULL;
 			pool->consumer_index--;
 			vio_unmap_single(adapter->vdev, pool->dma_addr[index], pool->buff_size, DMA_FROM_DEVICE);
@@ -239,7 +242,6 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc
 			adapter->replenish_add_buff_failure++;
 			break;
 		} else {
-			pool->free_map[free_index] = 0xffff;
 			buffers_added++;
 			adapter->replenish_add_buff_success++;
 		}
@@ -269,7 +271,6 @@ static void ibmveth_replenish_task(struct ibmveth_adapter *adapter)
 	adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8);
 
 	atomic_inc(&adapter->not_replenishing);
-	ibmveth_assert(atomic_read(&adapter->not_replenishing) == 1);
 }
 
 /* kick the replenish tasklet if we need replenishing and it isn't already running */
@@ -528,7 +529,7 @@ static int ibmveth_open(struct net_device *netdev)
 		ibmveth_error_printk("unable to request irq 0x%x, rc %d\n", netdev->irq, rc);
 		do {
 			rc = h_free_logical_lan(adapter->vdev->unit_address);
-		} while H_isLongBusy(rc);
+		} while (H_isLongBusy(rc) || (rc == H_Busy));
 
 		ibmveth_cleanup(adapter);
 		return rc;
@@ -560,7 +561,7 @@ static int ibmveth_close(struct net_device *netdev)
 
 	do {
 		lpar_rc = h_free_logical_lan(adapter->vdev->unit_address);
-	} while H_isLongBusy(lpar_rc);
+	} while (H_isLongBusy(lpar_rc) || (lpar_rc == H_Busy));
 
 	if(lpar_rc != H_Success)
 	{
@@ -732,6 +733,8 @@ static int ibmveth_poll(struct net_device *netdev, int *budget)
 		if(ibmveth_rxq_pending_buffer(adapter)) {
 			struct sk_buff *skb;
 
+			rmb();
+
 			if(!ibmveth_rxq_buffer_valid(adapter)) {
 				wmb(); /* suggested by larson1 */
 				adapter->rx_invalid_buffer++;
@@ -882,13 +885,16 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
 
 	mac_addr_p = (unsigned char *) vio_get_attribute(dev, VETH_MAC_ADDR, 0);
 	if(!mac_addr_p) {
-		ibmveth_error_printk("Can't find VETH_MAC_ADDR attribute\n");
+		printk(KERN_ERR "(%s:%3.3d) ERROR: Can't find VETH_MAC_ADDR "
+				"attribute\n", __FILE__, __LINE__);
 		return 0;
 	}
 	
 	mcastFilterSize_p= (unsigned int *) vio_get_attribute(dev, VETH_MCAST_FILTER_SIZE, 0);
 	if(!mcastFilterSize_p) {
-		ibmveth_error_printk("Can't find VETH_MCAST_FILTER_SIZE attribute\n");
+		printk(KERN_ERR "(%s:%3.3d) ERROR: Can't find "
+				"VETH_MCAST_FILTER_SIZE attribute\n",
+				__FILE__, __LINE__);
 		return 0;
 	}
 	
diff --git a/drivers/net/ibmveth.h b/drivers/net/ibmveth.h
index 599d15b2f..51a470da9 100644
--- a/drivers/net/ibmveth.h
+++ b/drivers/net/ibmveth.h
@@ -77,6 +77,8 @@
 #define IbmVethPool1DftCnt  256
 #define IbmVethPool2DftCnt  256
 
+#define IBM_VETH_INVALID_MAP ((u16)0xffff)
+
 struct ibmveth_buff_pool {
     u32 size;
     u32 index;
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index a93cda669..e16f8b20a 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -506,7 +506,7 @@ static struct net_device_stats *ioc3_get_stats(struct net_device *dev)
 
 static void ioc3_tcpudp_checksum(struct sk_buff *skb, uint32_t hwsum, int len)
 {
-	struct ethhdr *eh = skb->mac.ethernet;
+	struct ethhdr *eh = eth_hdr(skb);
 	uint32_t csum, ehsum;
 	unsigned int proto;
 	struct iphdr *ih;
@@ -1333,7 +1333,7 @@ static int ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		uint32_t csum, ehsum;
 		uint16_t *eh;
 
-		/* The MAC header.  skb->mac.ethernet seem the logic approach
+		/* The MAC header.  skb->mac seem the logic approach
 		   to find the MAC header - except it's a NULL pointer ...  */
 		eh = (uint16_t *) skb->data;
 
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 6ae10e514..62f985389 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -268,7 +268,6 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self)
                       speed_bulk_callback, self);
 	urb->transfer_buffer_length = USB_IRDA_HEADER;
 	urb->transfer_flags = URB_ASYNC_UNLINK;
-	urb->timeout = msecs_to_jiffies(100);
 
 	/* Irq disabled -> GFP_ATOMIC */
 	if ((ret = usb_submit_urb(urb, GFP_ATOMIC))) {
@@ -411,8 +410,6 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
 	 * after each of our packets that is exact multiple of the frame size.
 	 * This is how the dongle will detect the end of packet - Jean II */
 	urb->transfer_flags |= URB_ZERO_PACKET;
-	/* Timeout need to be shorter than NET watchdog timer */
-	urb->timeout = msecs_to_jiffies(200);
 
 	/* Generate min turn time. FIXME: can we do better than this? */
 	/* Trying to a turnaround time at this level is trying to measure
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
index b67441d0a..13b6e627a 100644
--- a/drivers/net/irda/irtty-sir.c
+++ b/drivers/net/irda/irtty-sir.c
@@ -509,13 +509,6 @@ static int irtty_open(struct tty_struct *tty)
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
 	
-/* from old irtty - but what is it good for?
- * we _are_ the ldisc and we _don't_ implement flush_buffer!
- *
- *	if (tty->ldisc.flush_buffer)
- *		tty->ldisc.flush_buffer(tty);
- */
-
 	/* apply mtt override */
 	sir_tty_drv.qos_mtt_bits = qos_mtt_bits;
 
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index f28ab3346..26af3785d 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -55,6 +55,8 @@ MODULE_DEVICE_TABLE(pci, ixgb_pci_tbl);
 
 /* Local Function Prototypes */
 
+static inline void ixgb_irq_disable(struct ixgb_adapter *adapter);
+static inline void ixgb_irq_enable(struct ixgb_adapter *adapter);
 int ixgb_up(struct ixgb_adapter *adapter);
 void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog);
 void ixgb_reset(struct ixgb_adapter *adapter);
@@ -82,10 +84,11 @@ static struct net_device_stats *ixgb_get_stats(struct net_device *netdev);
 static int ixgb_change_mtu(struct net_device *netdev, int new_mtu);
 static int ixgb_set_mac(struct net_device *netdev, void *p);
 static void ixgb_update_stats(struct ixgb_adapter *adapter);
-static inline void ixgb_irq_disable(struct ixgb_adapter *adapter);
-static inline void ixgb_irq_enable(struct ixgb_adapter *adapter);
 static irqreturn_t ixgb_intr(int irq, void *data, struct pt_regs *regs);
 static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter);
+static inline void ixgb_rx_checksum(struct ixgb_adapter *adapter,
+				    struct ixgb_rx_desc *rx_desc,
+				    struct sk_buff *skb);
 #ifdef CONFIG_IXGB_NAPI
 static int ixgb_clean(struct net_device *netdev, int *budget);
 static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter,
@@ -95,9 +98,6 @@ static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter);
 #endif
 static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter);
 static int ixgb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
-static inline void ixgb_rx_checksum(struct ixgb_adapter *adapter,
-				    struct ixgb_rx_desc *rx_desc,
-				    struct sk_buff *skb);
 static void ixgb_tx_timeout(struct net_device *dev);
 static void ixgb_tx_timeout_task(struct net_device *dev);
 static void ixgb_vlan_rx_register(struct net_device *netdev,
@@ -185,6 +185,34 @@ static void __exit ixgb_exit_module(void)
 
 module_exit(ixgb_exit_module);
 
+/**
+ * ixgb_irq_disable - Mask off interrupt generation on the NIC
+ * @adapter: board private structure
+ **/
+
+static inline void ixgb_irq_disable(struct ixgb_adapter *adapter)
+{
+	atomic_inc(&adapter->irq_sem);
+	IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
+	IXGB_WRITE_FLUSH(&adapter->hw);
+	synchronize_irq(adapter->pdev->irq);
+}
+
+/**
+ * ixgb_irq_enable - Enable default interrupt generation settings
+ * @adapter: board private structure
+ **/
+
+static inline void ixgb_irq_enable(struct ixgb_adapter *adapter)
+{
+	if (atomic_dec_and_test(&adapter->irq_sem)) {
+		IXGB_WRITE_REG(&adapter->hw, IMS,
+			       IXGB_INT_RXT0 | IXGB_INT_RXDMT0 | IXGB_INT_TXDW |
+			       IXGB_INT_RXO | IXGB_INT_LSC);
+		IXGB_WRITE_FLUSH(&adapter->hw);
+	}
+}
+
 int ixgb_up(struct ixgb_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
@@ -1550,34 +1578,6 @@ static void ixgb_update_stats(struct ixgb_adapter *adapter)
 	adapter->net_stats.tx_window_errors = 0;
 }
 
-/**
- * ixgb_irq_disable - Mask off interrupt generation on the NIC
- * @adapter: board private structure
- **/
-
-static inline void ixgb_irq_disable(struct ixgb_adapter *adapter)
-{
-	atomic_inc(&adapter->irq_sem);
-	IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
-	IXGB_WRITE_FLUSH(&adapter->hw);
-	synchronize_irq(adapter->pdev->irq);
-}
-
-/**
- * ixgb_irq_enable - Enable default interrupt generation settings
- * @adapter: board private structure
- **/
-
-static inline void ixgb_irq_enable(struct ixgb_adapter *adapter)
-{
-	if (atomic_dec_and_test(&adapter->irq_sem)) {
-		IXGB_WRITE_REG(&adapter->hw, IMS,
-			       IXGB_INT_RXT0 | IXGB_INT_RXDMT0 | IXGB_INT_TXDW |
-			       IXGB_INT_RXO | IXGB_INT_LSC);
-		IXGB_WRITE_FLUSH(&adapter->hw);
-	}
-}
-
 #define IXGB_MAX_INTR 10
 /**
  * ixgb_intr - Interrupt Handler
@@ -1729,6 +1729,39 @@ static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter)
 	return cleaned;
 }
 
+/**
+ * ixgb_rx_checksum - Receive Checksum Offload for 82597.
+ * @adapter: board private structure
+ * @rx_desc: receive descriptor
+ * @sk_buff: socket buffer with received data
+ **/
+
+static inline void
+ixgb_rx_checksum(struct ixgb_adapter *adapter,
+		 struct ixgb_rx_desc *rx_desc, struct sk_buff *skb)
+{
+	/* Ignore Checksum bit is set OR
+	 * TCP Checksum has not been calculated
+	 */
+	if ((rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) ||
+	    (!(rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS))) {
+		skb->ip_summed = CHECKSUM_NONE;
+		return;
+	}
+
+	/* At this point we know the hardware did the TCP checksum */
+	/* now look at the TCP checksum error bit */
+	if (rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE) {
+		/* let the stack verify checksum errors */
+		skb->ip_summed = CHECKSUM_NONE;
+		adapter->hw_csum_rx_error++;
+	} else {
+		/* TCP checksum is good */
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+		adapter->hw_csum_rx_good++;
+	}
+}
+
 /**
  * ixgb_clean_rx_irq - Send received data up the network stack,
  * @adapter: board private structure
@@ -1955,39 +1988,6 @@ static int ixgb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
 	return 0;
 }
 
-/**
- * ixgb_rx_checksum - Receive Checksum Offload for 82597.
- * @adapter: board private structure
- * @rx_desc: receive descriptor
- * @sk_buff: socket buffer with received data
- **/
-
-static inline void
-ixgb_rx_checksum(struct ixgb_adapter *adapter,
-		 struct ixgb_rx_desc *rx_desc, struct sk_buff *skb)
-{
-	/* Ignore Checksum bit is set OR 
-	 * TCP Checksum has not been calculated 
-	 */
-	if ((rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) ||
-	    (!(rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS))) {
-		skb->ip_summed = CHECKSUM_NONE;
-		return;
-	}
-
-	/* At this point we know the hardware did the TCP checksum */
-	/* now look at the TCP checksum error bit */
-	if (rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE) {
-		/* let the stack verify checksum errors */
-		skb->ip_summed = CHECKSUM_NONE;
-		adapter->hw_csum_rx_error++;
-	} else {
-		/* TCP checksum is good */
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-		adapter->hw_csum_rx_good++;
-	}
-}
-
 /**
  * ixgb_vlan_rx_register - enables or disables vlan tagging/stripping.
  * 
diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c
index 4957de6d8..b315acb14 100644
--- a/drivers/net/lasi_82596.c
+++ b/drivers/net/lasi_82596.c
@@ -1426,8 +1426,6 @@ static int i596_close(struct net_device *dev)
 	free_irq(dev->irq, dev);
 	remove_rx_bufs(dev);
 
-	MOD_DEC_USE_COUNT;
-
 	return 0;
 }
 
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 8ffa894c3..4bca692d6 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -49,6 +49,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+#include <linux/ethtool.h>
 #include <net/sock.h>
 #include <net/checksum.h>
 #include <linux/if_ether.h>	/* For the statistics structure. */
@@ -183,6 +184,17 @@ static struct net_device_stats *get_stats(struct net_device *dev)
 	return stats;
 }
 
+u32 loopback_get_link(struct net_device *dev)
+{
+	return 1;
+}
+
+static struct ethtool_ops loopback_ethtool_ops = {
+	.get_link		= loopback_get_link,
+	.get_tso		= ethtool_op_get_tso,
+	.set_tso		= ethtool_op_set_tso,
+};
+
 struct net_device loopback_dev = {
 	.name	 		= "lo",
 	.mtu			= (16 * 1024) + 20 + 20 + 12,
@@ -199,6 +211,7 @@ struct net_device loopback_dev = {
 	.features 		= NETIF_F_SG|NETIF_F_FRAGLIST
 				  |NETIF_F_NO_CSUM|NETIF_F_HIGHDMA
 				  |NETIF_F_LLTX,
+	.ethtool_ops		= &loopback_ethtool_ops,
 };
 
 /* Setup and register the of the LOOPBACK device. */
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index c4c9cb22a..c5f95959c 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -85,7 +85,7 @@ static char version[] =
 static struct myri_eth *root_myri_dev;
 #endif
 
-static void myri_reset_off(unsigned long lp, unsigned long cregs)
+static void myri_reset_off(void __iomem *lp, void __iomem *cregs)
 {
 	/* Clear IRQ mask. */
 	sbus_writel(0, lp + LANAI_EIMASK);
@@ -94,7 +94,7 @@ static void myri_reset_off(unsigned long lp, unsigned long cregs)
 	sbus_writel(CONTROL_ROFF, cregs + MYRICTRL_CTRL);
 }
 
-static void myri_reset_on(unsigned long cregs)
+static void myri_reset_on(void __iomem *cregs)
 {
 	/* Enable RESET function. */
 	sbus_writel(CONTROL_RON, cregs + MYRICTRL_CTRL);
@@ -103,14 +103,14 @@ static void myri_reset_on(unsigned long cregs)
 	sbus_writel(CONTROL_DIRQ, cregs + MYRICTRL_CTRL);
 }
 
-static void myri_disable_irq(unsigned long lp, unsigned long cregs)
+static void myri_disable_irq(void __iomem *lp, void __iomem *cregs)
 {
 	sbus_writel(CONTROL_DIRQ, cregs + MYRICTRL_CTRL);
 	sbus_writel(0, lp + LANAI_EIMASK);
 	sbus_writel(ISTAT_HOST, lp + LANAI_ISTAT);
 }
 
-static void myri_enable_irq(unsigned long lp, unsigned long cregs)
+static void myri_enable_irq(void __iomem *lp, void __iomem *cregs)
 {
 	sbus_writel(CONTROL_EIRQ, cregs + MYRICTRL_CTRL);
 	sbus_writel(ISTAT_HOST, lp + LANAI_EIMASK);
@@ -119,7 +119,7 @@ static void myri_enable_irq(unsigned long lp, unsigned long cregs)
 static inline void bang_the_chip(struct myri_eth *mp)
 {
 	struct myri_shmem *shmem	= mp->shmem;
-	unsigned long cregs		= mp->cregs;
+	void __iomem *cregs		= mp->cregs;
 
 	sbus_writel(1, &shmem->send);
 	sbus_writel(CONTROL_WON, cregs + MYRICTRL_CTRL);
@@ -128,7 +128,7 @@ static inline void bang_the_chip(struct myri_eth *mp)
 static int myri_do_handshake(struct myri_eth *mp)
 {
 	struct myri_shmem *shmem	= mp->shmem;
-	unsigned long cregs = mp->cregs;
+	void __iomem *cregs = mp->cregs;
 	struct myri_channel *chan	= &shmem->channel;
 	int tick 			= 0;
 
@@ -176,27 +176,27 @@ static int myri_do_handshake(struct myri_eth *mp)
 static int myri_load_lanai(struct myri_eth *mp)
 {
 	struct net_device	*dev = mp->dev;
-	struct myri_shmem	*shmem = mp->shmem;
-	unsigned char		*rptr;
+	struct myri_shmem __iomem *shmem = mp->shmem;
+	void __iomem		*rptr;
 	int 			i;
 
 	myri_disable_irq(mp->lregs, mp->cregs);
 	myri_reset_on(mp->cregs);
 
-	rptr = (unsigned char *) mp->lanai;
+	rptr = mp->lanai;
 	for (i = 0; i < mp->eeprom.ramsz; i++)
-		sbus_writeb(0, &rptr[i]);
+		sbus_writeb(0, rptr + i);
 
 	if (mp->eeprom.cpuvers >= CPUVERS_3_0)
 		sbus_writel(mp->eeprom.cval, mp->lregs + LANAI_CVAL);
 
 	/* Load executable code. */
 	for (i = 0; i < sizeof(lanai4_code); i++)
-		sbus_writeb(lanai4_code[i], &rptr[(lanai4_code_off * 2) + i]);
+		sbus_writeb(lanai4_code[i], rptr + (lanai4_code_off * 2) + i);
 
 	/* Load data segment. */
 	for (i = 0; i < sizeof(lanai4_data); i++)
-		sbus_writeb(lanai4_data[i], &rptr[(lanai4_data_off * 2) + i]);
+		sbus_writeb(lanai4_data[i], rptr + (lanai4_data_off * 2) + i);
 
 	/* Set device address. */
 	sbus_writeb(0, &shmem->addr[0]);
@@ -237,15 +237,15 @@ static int myri_load_lanai(struct myri_eth *mp)
 
 static void myri_clean_rings(struct myri_eth *mp)
 {
-	struct sendq *sq = mp->sq;
-	struct recvq *rq = mp->rq;
+	struct sendq __iomem *sq = mp->sq;
+	struct recvq __iomem *rq = mp->rq;
 	int i;
 
 	sbus_writel(0, &rq->tail);
 	sbus_writel(0, &rq->head);
 	for (i = 0; i < (RX_RING_SIZE+1); i++) {
 		if (mp->rx_skbs[i] != NULL) {
-			struct myri_rxd *rxd = &rq->myri_rxd[i];
+			struct myri_rxd __iomem *rxd = &rq->myri_rxd[i];
 			u32 dma_addr;
 
 			dma_addr = sbus_readl(&rxd->myri_scatters[0].addr);
@@ -261,7 +261,7 @@ static void myri_clean_rings(struct myri_eth *mp)
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		if (mp->tx_skbs[i] != NULL) {
 			struct sk_buff *skb = mp->tx_skbs[i];
-			struct myri_txd *txd = &sq->myri_txd[i];
+			struct myri_txd __iomem *txd = &sq->myri_txd[i];
 			u32 dma_addr;
 
 			dma_addr = sbus_readl(&txd->myri_gathers[0].addr);
@@ -274,8 +274,8 @@ static void myri_clean_rings(struct myri_eth *mp)
 
 static void myri_init_rings(struct myri_eth *mp, int from_irq)
 {
-	struct recvq *rq = mp->rq;
-	struct myri_rxd *rxd = &rq->myri_rxd[0];
+	struct recvq __iomem *rq = mp->rq;
+	struct myri_rxd __iomem *rxd = &rq->myri_rxd[0];
 	struct net_device *dev = mp->dev;
 	int gfp_flags = GFP_KERNEL;
 	int i;
@@ -343,7 +343,7 @@ static void dump_ehdr_and_myripad(unsigned char *stuff)
 
 static void myri_tx(struct myri_eth *mp, struct net_device *dev)
 {
-	struct sendq *sq	= mp->sq;
+	struct sendq __iomem *sq= mp->sq;
 	int entry		= mp->tx_old;
 	int limit		= sbus_readl(&sq->head);
 
@@ -376,7 +376,7 @@ static unsigned short myri_type_trans(struct sk_buff *skb, struct net_device *de
 	
 	skb->mac.raw = (((unsigned char *)skb->data) + MYRI_PAD_LEN);
 	skb_pull(skb, dev->hard_header_len);
-	eth = skb->mac.ethernet;
+	eth = eth_hdr(skb);
 	
 #ifdef DEBUG_HEADER
 	DHDR(("myri_type_trans: "));
@@ -411,8 +411,8 @@ static unsigned short myri_type_trans(struct sk_buff *skb, struct net_device *de
 
 static void myri_rx(struct myri_eth *mp, struct net_device *dev)
 {
-	struct recvq *rq	= mp->rq;
-	struct recvq *rqa	= mp->rqack;
+	struct recvq __iomem *rq = mp->rq;
+	struct recvq __iomem *rqa = mp->rqack;
 	int entry		= sbus_readl(&rqa->head);
 	int limit		= sbus_readl(&rqa->tail);
 	int drops;
@@ -423,11 +423,11 @@ static void myri_rx(struct myri_eth *mp, struct net_device *dev)
 	drops = 0;
 	DRX(("\n"));
 	while (entry != limit) {
-		struct myri_rxd *rxdack = &rqa->myri_rxd[entry];
+		struct myri_rxd __iomem *rxdack = &rqa->myri_rxd[entry];
 		u32 csum		= sbus_readl(&rxdack->csum);
 		int len			= sbus_readl(&rxdack->myri_scatters[0].len);
 		int index		= sbus_readl(&rxdack->ctx);
-		struct myri_rxd *rxd	= &rq->myri_rxd[rq->tail];
+		struct myri_rxd __iomem *rxd	= &rq->myri_rxd[rq->tail];
 		struct sk_buff *skb	= mp->rx_skbs[index];
 
 		/* Ack it. */
@@ -545,7 +545,7 @@ static irqreturn_t myri_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev		= (struct net_device *) dev_id;
 	struct myri_eth *mp		= (struct myri_eth *) dev->priv;
-	unsigned long lregs		= mp->lregs;
+	void __iomem *lregs		= mp->lregs;
 	struct myri_channel *chan	= &mp->shmem->channel;
 	unsigned long flags;
 	u32 status;
@@ -610,8 +610,8 @@ static void myri_tx_timeout(struct net_device *dev)
 static int myri_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct myri_eth *mp = (struct myri_eth *) dev->priv;
-	struct sendq *sq = mp->sq;
-	struct myri_txd *txd;
+	struct sendq __iomem *sq = mp->sq;
+	struct myri_txd __iomem *txd;
 	unsigned long flags;
 	unsigned int head, tail;
 	int len, entry;
@@ -998,22 +998,20 @@ static int __init myri_ether_init(struct sbus_dev *sdev, int num)
 			printk("MyriCOM: Cannot map MyriCOM registers.\n");
 			goto err;
 		}
-		mp->lanai = (unsigned short *) (mp->regs + (256 * 1024));
-		mp->lanai3 = (unsigned int *) mp->lanai;
-		mp->lregs = (unsigned long) &mp->lanai[0x10000];
+		mp->lanai = mp->regs + (256 * 1024);
+		mp->lregs = mp->lanai + (0x10000 * 2);
 	} else {
 		DET(("Mapping regs for cpuvers >= CPUVERS_4_0\n"));
 		mp->cregs = sbus_ioremap(&sdev->resource[0], 0,
 					 PAGE_SIZE, "MyriCOM Control Regs");
 		mp->lregs = sbus_ioremap(&sdev->resource[0], (256 * 1024),
 					 PAGE_SIZE, "MyriCOM LANAI Regs");
-		mp->lanai = (unsigned short *)
+		mp->lanai =
 			sbus_ioremap(&sdev->resource[0], (512 * 1024),
 				     mp->eeprom.ramsz, "MyriCOM SRAM");
-		mp->lanai3 = (unsigned int *) mp->lanai;
 	}
-	DET(("Registers mapped: cregs[%lx] lregs[%lx] lanai[%p] lanai3[%p]\n",
-	     mp->cregs, mp->lregs, mp->lanai, mp->lanai3));
+	DET(("Registers mapped: cregs[%p] lregs[%p] lanai[%p]\n",
+	     mp->cregs, mp->lregs, mp->lanai));
 
 	if (mp->eeprom.cpuvers >= CPUVERS_4_0)
 		mp->shmem_base = 0xf000;
@@ -1022,7 +1020,8 @@ static int __init myri_ether_init(struct sbus_dev *sdev, int num)
 
 	DET(("Shared memory base is %04x, ", mp->shmem_base));
 
-	mp->shmem = (struct myri_shmem *) &mp->lanai[mp->shmem_base];
+	mp->shmem = (struct myri_shmem __iomem *)
+		(mp->lanai + (mp->shmem_base * 2));
 	DET(("shmem mapped at %p\n", mp->shmem));
 
 	mp->rqack	= &mp->shmem->channel.recvqa;
diff --git a/drivers/net/myri_sbus.h b/drivers/net/myri_sbus.h
index 944ddfa65..9391e55a5 100644
--- a/drivers/net/myri_sbus.h
+++ b/drivers/net/myri_sbus.h
@@ -270,22 +270,21 @@ struct myri_eth {
 	 * to obtain good cache hit rates.
 	 */
 	spinlock_t			irq_lock;
-	struct myri_shmem		*shmem;		/* Shared data structures.    */
-	unsigned long			cregs;		/* Control register space.    */
-	struct recvq			*rqack;		/* Where we ack rx's.         */
-	struct recvq			*rq;		/* Where we put buffers.      */
-	struct sendq			*sq;		/* Where we stuff tx's.       */
+	struct myri_shmem __iomem	*shmem;		/* Shared data structures.    */
+	void __iomem			*cregs;		/* Control register space.    */
+	struct recvq __iomem		*rqack;		/* Where we ack rx's.         */
+	struct recvq __iomem		*rq;		/* Where we put buffers.      */
+	struct sendq __iomem		*sq;		/* Where we stuff tx's.       */
 	struct net_device		*dev;		/* Linux/NET dev struct.      */
 	int				tx_old;		/* To speed up tx cleaning.   */
-	unsigned long			lregs;		/* Quick ptr to LANAI regs.   */
+	void __iomem			*lregs;		/* Quick ptr to LANAI regs.   */
 	struct sk_buff	       *rx_skbs[RX_RING_SIZE+1];/* RX skb's                   */
 	struct sk_buff	       *tx_skbs[TX_RING_SIZE];  /* TX skb's                   */
 	struct net_device_stats		enet_stats;	/* Interface stats.           */
 
 	/* These are less frequently accessed. */
-	unsigned long			regs;          /* MyriCOM register space.    */
-	unsigned short			*lanai;		/* View 2 of register space.  */
-	unsigned int			*lanai3;	/* View 3 of register space.  */
+	void __iomem			*regs;          /* MyriCOM register space.    */
+	void __iomem			*lanai;		/* View 2 of register space.  */
 	unsigned int			myri_bursts;	/* SBUS bursts.               */
 	struct myri_eeprom		eeprom;		/* Local copy of EEPROM.      */
 	unsigned int			reg_size;	/* Size of register space.    */
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 88c626afe..fd44cb722 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -719,7 +719,7 @@ struct netdev_private {
 };
 
 static void move_int_phy(struct net_device *dev, int addr);
-static int eeprom_read(long ioaddr, int location);
+static int eeprom_read(void __iomem *ioaddr, int location);
 static int mdio_read(struct net_device *dev, int reg);
 static void mdio_write(struct net_device *dev, int reg, u16 data);
 static void init_phy_fixup(struct net_device *dev);
@@ -750,6 +750,9 @@ static void netdev_error(struct net_device *dev, int intr_status);
 static void netdev_rx(struct net_device *dev);
 static void netdev_tx_done(struct net_device *dev);
 static int natsemi_change_mtu(struct net_device *dev, int new_mtu);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void natsemi_poll_controller(struct net_device *dev);
+#endif
 static void __set_rx_mode(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
 static void __get_stats(struct net_device *dev);
@@ -766,9 +769,15 @@ static int netdev_close(struct net_device *dev);
 static int netdev_get_regs(struct net_device *dev, u8 *buf);
 static int netdev_get_eeprom(struct net_device *dev, u8 *buf);
 
+static inline void __iomem *ns_ioaddr(struct net_device *dev)
+{
+	return (void __iomem *) dev->base_addr;
+}
+
 static void move_int_phy(struct net_device *dev, int addr)
 {
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = ns_ioaddr(dev);
 	int target = 31;
 
 	/* 
@@ -785,8 +794,8 @@ static void move_int_phy(struct net_device *dev, int addr)
 		target--;
 	if (target == np->phy_addr_external)
 		target--;
-	writew(target, dev->base_addr + PhyCtrl);
-	readw(dev->base_addr + PhyCtrl);
+	writew(target, ioaddr + PhyCtrl);
+	readw(ioaddr + PhyCtrl);
 	udelay(1);
 }
 
@@ -797,7 +806,8 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
 	struct netdev_private *np;
 	int i, option, irq, chip_idx = ent->driver_data;
 	static int find_cnt = -1;
-	unsigned long ioaddr, iosize;
+	unsigned long iostart, iosize;
+	void __iomem *ioaddr;
 	const int pcibar = 1; /* PCI base address register */
 	int prev_eedata;
 	u32 tmp;
@@ -824,7 +834,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
 	}
 
 	find_cnt++;
-	ioaddr = pci_resource_start(pdev, pcibar);
+	iostart = pci_resource_start(pdev, pcibar);
 	iosize = pci_resource_len(pdev, pcibar);
 	irq = pdev->irq;
 
@@ -841,7 +851,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
 	if (i)
 		goto err_pci_request_regions;
 
-	ioaddr = (unsigned long) ioremap (ioaddr, iosize);
+	ioaddr = ioremap(iostart, iosize);
 	if (!ioaddr) {
 		i = -ENOMEM;
 		goto err_ioremap;
@@ -856,7 +866,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
 		prev_eedata = eedata;
 	}
 
-	dev->base_addr = ioaddr;
+	dev->base_addr = (unsigned long __force) ioaddr;
 	dev->irq = irq;
 
 	np = netdev_priv(dev);
@@ -876,7 +886,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
 	 * The address would be used to access a phy over the mii bus, but
 	 * the internal phy is accessed through mapped registers.
 	 */
-	if (readl(dev->base_addr + ChipConfig) & CfgExtPhy)
+	if (readl(ioaddr + ChipConfig) & CfgExtPhy)
 		dev->if_port = PORT_MII;
 	else
 		dev->if_port = PORT_TP;
@@ -920,6 +930,9 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
 	dev->do_ioctl = &netdev_ioctl;
 	dev->tx_timeout = &tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = &natsemi_poll_controller;
+#endif
 
 	if (mtu)
 		dev->mtu = mtu;
@@ -965,7 +978,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
 
 	if (netif_msg_drv(np)) {
 		printk(KERN_INFO "natsemi %s: %s at %#08lx (%s), ",
-			dev->name, natsemi_pci_info[chip_idx].name, ioaddr,
+			dev->name, natsemi_pci_info[chip_idx].name, iostart,
 			pci_name(np->pci_dev));
 		for (i = 0; i < ETH_ALEN-1; i++)
 				printk("%02x:", dev->dev_addr[i]);
@@ -978,7 +991,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
 	return 0;
 
  err_register_netdev:
-	iounmap ((void *) dev->base_addr);
+	iounmap(ioaddr);
 
  err_ioremap:
 	pci_release_regions(pdev);
@@ -1010,12 +1023,13 @@ enum EEPROM_Cmds {
 	EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6),
 };
 
-static int eeprom_read(long addr, int location)
+static int eeprom_read(void __iomem *addr, int location)
 {
 	int i;
 	int retval = 0;
-	long ee_addr = addr + EECtrl;
+	void __iomem *ee_addr = addr + EECtrl;
 	int read_cmd = location | EE_ReadCmd;
+
 	writel(EE_Write0, ee_addr);
 
 	/* Shift the read command bits out. */
@@ -1052,33 +1066,35 @@ static int eeprom_read(long addr, int location)
 /* clock transitions >= 20ns (25MHz)
  * One readl should be good to PCI @ 100MHz
  */
-#define mii_delay(dev)  readl(dev->base_addr + EECtrl)
+#define mii_delay(ioaddr)  readl(ioaddr + EECtrl)
 
 static int mii_getbit (struct net_device *dev)
 {
 	int data;
+	void __iomem *ioaddr = ns_ioaddr(dev);
 
-	writel(MII_ShiftClk, dev->base_addr + EECtrl);
-	data = readl(dev->base_addr + EECtrl);
-	writel(0, dev->base_addr + EECtrl);
-	mii_delay(dev);
+	writel(MII_ShiftClk, ioaddr + EECtrl);
+	data = readl(ioaddr + EECtrl);
+	writel(0, ioaddr + EECtrl);
+	mii_delay(ioaddr);
 	return (data & MII_Data)? 1 : 0;
 }
 
 static void mii_send_bits (struct net_device *dev, u32 data, int len)
 {
 	u32 i;
+	void __iomem *ioaddr = ns_ioaddr(dev);
 
 	for (i = (1 << (len-1)); i; i >>= 1)
 	{
 		u32 mdio_val = MII_Write | ((data & i)? MII_Data : 0);
-		writel(mdio_val, dev->base_addr + EECtrl);
-		mii_delay(dev);
-		writel(mdio_val | MII_ShiftClk, dev->base_addr + EECtrl);
-		mii_delay(dev);
+		writel(mdio_val, ioaddr + EECtrl);
+		mii_delay(ioaddr);
+		writel(mdio_val | MII_ShiftClk, ioaddr + EECtrl);
+		mii_delay(ioaddr);
 	}
-	writel(0, dev->base_addr + EECtrl);
-	mii_delay(dev);
+	writel(0, ioaddr + EECtrl);
+	mii_delay(ioaddr);
 }
 
 static int miiport_read(struct net_device *dev, int phy_id, int reg)
@@ -1123,13 +1139,14 @@ static void miiport_write(struct net_device *dev, int phy_id, int reg, u16 data)
 static int mdio_read(struct net_device *dev, int reg)
 {
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = ns_ioaddr(dev);
 
 	/* The 83815 series has two ports:
 	 * - an internal transceiver
 	 * - an external mii bus
 	 */
 	if (dev->if_port == PORT_TP)
-		return readw(dev->base_addr+BasicControl+(reg<<2));
+		return readw(ioaddr+BasicControl+(reg<<2));
 	else
 		return miiport_read(dev, np->phy_addr_external, reg);
 }
@@ -1137,10 +1154,11 @@ static int mdio_read(struct net_device *dev, int reg)
 static void mdio_write(struct net_device *dev, int reg, u16 data)
 {
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = ns_ioaddr(dev);
 
 	/* The 83815 series has an internal transceiver; handle separately */
 	if (dev->if_port == PORT_TP)
-		writew(data, dev->base_addr+BasicControl+(reg<<2));
+		writew(data, ioaddr+BasicControl+(reg<<2));
 	else
 		miiport_write(dev, np->phy_addr_external, reg, data);
 }
@@ -1148,7 +1166,7 @@ static void mdio_write(struct net_device *dev, int reg, u16 data)
 static void init_phy_fixup(struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem *ioaddr = ns_ioaddr(dev);
 	int i;
 	u32 cfg;
 	u16 tmp;
@@ -1180,7 +1198,7 @@ static void init_phy_fixup(struct net_device *dev)
 		 */
 	}
 	mdio_write(dev, MII_BMCR, tmp);
-	readl(dev->base_addr + ChipConfig);
+	readl(ioaddr + ChipConfig);
 	udelay(1);
 
 	/* find out what phy this is */
@@ -1202,7 +1220,7 @@ static void init_phy_fixup(struct net_device *dev)
 	default:
 		break;
 	}
-	cfg = readl(dev->base_addr + ChipConfig);
+	cfg = readl(ioaddr + ChipConfig);
 	if (cfg & CfgExtPhy)
 		return;
 
@@ -1260,9 +1278,10 @@ static void init_phy_fixup(struct net_device *dev)
 static int switch_port_external(struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = ns_ioaddr(dev);
 	u32 cfg;
 
-	cfg = readl(dev->base_addr + ChipConfig);
+	cfg = readl(ioaddr + ChipConfig);
 	if (cfg & CfgExtPhy)
 		return 0;
 
@@ -1272,8 +1291,8 @@ static int switch_port_external(struct net_device *dev)
 	}
 
 	/* 1) switch back to external phy */
-	writel(cfg | (CfgExtPhy | CfgPhyDis), dev->base_addr + ChipConfig);
-	readl(dev->base_addr + ChipConfig);
+	writel(cfg | (CfgExtPhy | CfgPhyDis), ioaddr + ChipConfig);
+	readl(ioaddr + ChipConfig);
 	udelay(1);
 
 	/* 2) reset the external phy: */
@@ -1292,11 +1311,12 @@ static int switch_port_external(struct net_device *dev)
 static int switch_port_internal(struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = ns_ioaddr(dev);
 	int i;
 	u32 cfg;
 	u16 bmcr;
 
-	cfg = readl(dev->base_addr + ChipConfig);
+	cfg = readl(ioaddr + ChipConfig);
 	if (!(cfg &CfgExtPhy))
 		return 0;
 
@@ -1306,17 +1326,17 @@ static int switch_port_internal(struct net_device *dev)
 	}
 	/* 1) switch back to internal phy: */
 	cfg = cfg & ~(CfgExtPhy | CfgPhyDis);
-	writel(cfg, dev->base_addr + ChipConfig);
-	readl(dev->base_addr + ChipConfig);
+	writel(cfg, ioaddr + ChipConfig);
+	readl(ioaddr + ChipConfig);
 	udelay(1);
 	
 	/* 2) reset the internal phy: */
-	bmcr = readw(dev->base_addr+BasicControl+(MII_BMCR<<2));
-	writel(bmcr | BMCR_RESET, dev->base_addr+BasicControl+(MII_BMCR<<2));
-	readl(dev->base_addr + ChipConfig);
+	bmcr = readw(ioaddr+BasicControl+(MII_BMCR<<2));
+	writel(bmcr | BMCR_RESET, ioaddr+BasicControl+(MII_BMCR<<2));
+	readl(ioaddr + ChipConfig);
 	udelay(10);
 	for (i=0;i<NATSEMI_HW_TIMEOUT;i++) {
-		bmcr = readw(dev->base_addr+BasicControl+(MII_BMCR<<2));
+		bmcr = readw(ioaddr+BasicControl+(MII_BMCR<<2));
 		if (!(bmcr & BMCR_RESET))
 			break;
 		udelay(10);
@@ -1392,6 +1412,7 @@ static void natsemi_reset(struct net_device *dev)
 	u16 pmatch[3];
 	u16 sopass[3];
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = ns_ioaddr(dev);
 
 	/*
 	 * Resetting the chip causes some registers to be lost.
@@ -1402,26 +1423,26 @@ static void natsemi_reset(struct net_device *dev)
 	 */
 
 	/* CFG */
-	cfg = readl(dev->base_addr + ChipConfig) & CFG_RESET_SAVE;
+	cfg = readl(ioaddr + ChipConfig) & CFG_RESET_SAVE;
 	/* WCSR */
-	wcsr = readl(dev->base_addr + WOLCmd) & WCSR_RESET_SAVE;
+	wcsr = readl(ioaddr + WOLCmd) & WCSR_RESET_SAVE;
 	/* RFCR */
-	rfcr = readl(dev->base_addr + RxFilterAddr) & RFCR_RESET_SAVE;
+	rfcr = readl(ioaddr + RxFilterAddr) & RFCR_RESET_SAVE;
 	/* PMATCH */
 	for (i = 0; i < 3; i++) {
-		writel(i*2, dev->base_addr + RxFilterAddr);
-		pmatch[i] = readw(dev->base_addr + RxFilterData);
+		writel(i*2, ioaddr + RxFilterAddr);
+		pmatch[i] = readw(ioaddr + RxFilterData);
 	}
 	/* SOPAS */
 	for (i = 0; i < 3; i++) {
-		writel(0xa+(i*2), dev->base_addr + RxFilterAddr);
-		sopass[i] = readw(dev->base_addr + RxFilterData);
+		writel(0xa+(i*2), ioaddr + RxFilterAddr);
+		sopass[i] = readw(ioaddr + RxFilterData);
 	}
 
 	/* now whack the chip */
-	writel(ChipReset, dev->base_addr + ChipCmd);
+	writel(ChipReset, ioaddr + ChipCmd);
 	for (i=0;i<NATSEMI_HW_TIMEOUT;i++) {
-		if (!(readl(dev->base_addr + ChipCmd) & ChipReset))
+		if (!(readl(ioaddr + ChipCmd) & ChipReset))
 			break;
 		udelay(5);
 	}
@@ -1434,40 +1455,41 @@ static void natsemi_reset(struct net_device *dev)
 	}
 
 	/* restore CFG */
-	cfg |= readl(dev->base_addr + ChipConfig) & ~CFG_RESET_SAVE;
+	cfg |= readl(ioaddr + ChipConfig) & ~CFG_RESET_SAVE;
 	/* turn on external phy if it was selected */
 	if (dev->if_port == PORT_TP)
 		cfg &= ~(CfgExtPhy | CfgPhyDis);
 	else
 		cfg |= (CfgExtPhy | CfgPhyDis);
-	writel(cfg, dev->base_addr + ChipConfig);
+	writel(cfg, ioaddr + ChipConfig);
 	/* restore WCSR */
-	wcsr |= readl(dev->base_addr + WOLCmd) & ~WCSR_RESET_SAVE;
-	writel(wcsr, dev->base_addr + WOLCmd);
+	wcsr |= readl(ioaddr + WOLCmd) & ~WCSR_RESET_SAVE;
+	writel(wcsr, ioaddr + WOLCmd);
 	/* read RFCR */
-	rfcr |= readl(dev->base_addr + RxFilterAddr) & ~RFCR_RESET_SAVE;
+	rfcr |= readl(ioaddr + RxFilterAddr) & ~RFCR_RESET_SAVE;
 	/* restore PMATCH */
 	for (i = 0; i < 3; i++) {
-		writel(i*2, dev->base_addr + RxFilterAddr);
-		writew(pmatch[i], dev->base_addr + RxFilterData);
+		writel(i*2, ioaddr + RxFilterAddr);
+		writew(pmatch[i], ioaddr + RxFilterData);
 	}
 	for (i = 0; i < 3; i++) {
-		writel(0xa+(i*2), dev->base_addr + RxFilterAddr);
-		writew(sopass[i], dev->base_addr + RxFilterData);
+		writel(0xa+(i*2), ioaddr + RxFilterAddr);
+		writew(sopass[i], ioaddr + RxFilterData);
 	}
 	/* restore RFCR */
-	writel(rfcr, dev->base_addr + RxFilterAddr);
+	writel(rfcr, ioaddr + RxFilterAddr);
 }
 
 static void natsemi_reload_eeprom(struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = ns_ioaddr(dev);
 	int i;
 
-	writel(EepromReload, dev->base_addr + PCIBusCfg);
+	writel(EepromReload, ioaddr + PCIBusCfg);
 	for (i=0;i<NATSEMI_HW_TIMEOUT;i++) {
 		udelay(50);
-		if (!(readl(dev->base_addr + PCIBusCfg) & EepromReload))
+		if (!(readl(ioaddr + PCIBusCfg) & EepromReload))
 			break;
 	}
 	if (i==NATSEMI_HW_TIMEOUT) {
@@ -1481,7 +1503,7 @@ static void natsemi_reload_eeprom(struct net_device *dev)
 
 static void natsemi_stop_rxtx(struct net_device *dev)
 {
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	struct netdev_private *np = netdev_priv(dev);
 	int i;
 
@@ -1503,7 +1525,7 @@ static void natsemi_stop_rxtx(struct net_device *dev)
 static int netdev_open(struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	int i;
 
 	/* Reset the chip, just in case. */
@@ -1552,6 +1574,7 @@ static int netdev_open(struct net_device *dev)
 static void do_cable_magic(struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = ns_ioaddr(dev);
 
 	if (dev->if_port != PORT_TP)
 		return;
@@ -1565,15 +1588,15 @@ static void do_cable_magic(struct net_device *dev)
 	 * activity LED while idle.  This process is based on instructions
 	 * from engineers at National.
 	 */
-	if (readl(dev->base_addr + ChipConfig) & CfgSpeed100) {
+	if (readl(ioaddr + ChipConfig) & CfgSpeed100) {
 		u16 data;
 
-		writew(1, dev->base_addr + PGSEL);
+		writew(1, ioaddr + PGSEL);
 		/*
 		 * coefficient visibility should already be enabled via
 		 * DSPCFG | 0x1000
 		 */
-		data = readw(dev->base_addr + TSTDAT) & 0xff;
+		data = readw(ioaddr + TSTDAT) & 0xff;
 		/*
 		 * the value must be negative, and within certain values
 		 * (these values all come from National)
@@ -1582,13 +1605,13 @@ static void do_cable_magic(struct net_device *dev)
 			struct netdev_private *np = netdev_priv(dev);
 
 			/* the bug has been triggered - fix the coefficient */
-			writew(TSTDAT_FIXED, dev->base_addr + TSTDAT);
+			writew(TSTDAT_FIXED, ioaddr + TSTDAT);
 			/* lock the value */
-			data = readw(dev->base_addr + DSPCFG);
+			data = readw(ioaddr + DSPCFG);
 			np->dspcfg = data | DSPCFG_LOCK;
-			writew(np->dspcfg, dev->base_addr + DSPCFG);
+			writew(np->dspcfg, ioaddr + DSPCFG);
 		}
-		writew(0, dev->base_addr + PGSEL);
+		writew(0, ioaddr + PGSEL);
 	}
 }
 
@@ -1596,6 +1619,7 @@ static void undo_cable_magic(struct net_device *dev)
 {
 	u16 data;
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem * ioaddr = ns_ioaddr(dev);
 
 	if (dev->if_port != PORT_TP)
 		return;
@@ -1603,18 +1627,18 @@ static void undo_cable_magic(struct net_device *dev)
 	if (np->srr >= SRR_DP83816_A5)
 		return;
 
-	writew(1, dev->base_addr + PGSEL);
+	writew(1, ioaddr + PGSEL);
 	/* make sure the lock bit is clear */
-	data = readw(dev->base_addr + DSPCFG);
+	data = readw(ioaddr + DSPCFG);
 	np->dspcfg = data & ~DSPCFG_LOCK;
-	writew(np->dspcfg, dev->base_addr + DSPCFG);
-	writew(0, dev->base_addr + PGSEL);
+	writew(np->dspcfg, ioaddr + DSPCFG);
+	writew(0, ioaddr + PGSEL);
 }
 
 static void check_link(struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	int duplex;
 	u16 bmsr;
        
@@ -1675,7 +1699,7 @@ static void check_link(struct net_device *dev)
 static void init_registers(struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 
 	init_phy_fixup(dev);
 
@@ -1754,6 +1778,7 @@ static void netdev_timer(unsigned long data)
 {
 	struct net_device *dev = (struct net_device *)data;
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	int next_tick = 5*HZ;
 
 	if (netif_msg_timer(np)) {
@@ -1765,7 +1790,6 @@ static void netdev_timer(unsigned long data)
 	}
 
 	if (dev->if_port == PORT_TP) {
-		long ioaddr = dev->base_addr;
 		u16 dspcfg;
 
 		spin_lock_irq(&np->lock);
@@ -1808,7 +1832,7 @@ static void netdev_timer(unsigned long data)
 		refill_rx(dev);
 		enable_irq(dev->irq);
 		if (!np->oom) {
-			writel(RxOn, dev->base_addr + ChipCmd);
+			writel(RxOn, ioaddr + ChipCmd);
 		} else {
 			next_tick = 1;
 		}
@@ -1842,7 +1866,7 @@ static void dump_ring(struct net_device *dev)
 static void tx_timeout(struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 
 	disable_irq(dev->irq);
 	spin_lock_irq(&np->lock);
@@ -2042,6 +2066,7 @@ static void reinit_ring(struct net_device *dev)
 static int start_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	unsigned entry;
 
 	/* Note: Ordering is important here, set the field with the
@@ -2070,7 +2095,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
 				netif_stop_queue(dev);
 		}
 		/* Wake the potentially-idle transmit channel. */
-		writel(TxOn, dev->base_addr + ChipCmd);
+		writel(TxOn, ioaddr + ChipCmd);
 	} else {
 		dev_kfree_skb_irq(skb);
 		np->stats.tx_dropped++;
@@ -2135,7 +2160,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
 {
 	struct net_device *dev = dev_instance;
 	struct netdev_private *np = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	int boguscnt = max_interrupt_work;
 	unsigned int handled = 0;
 
@@ -2197,6 +2222,7 @@ static void netdev_rx(struct net_device *dev)
 	int boguscnt = np->dirty_rx + RX_RING_SIZE - np->cur_rx;
 	s32 desc_status = le32_to_cpu(np->rx_head_desc->cmd_status);
 	unsigned int buflen = np->rx_buf_sz;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 
 	/* If the driver owns the next entry it's a new packet. Send it up. */
 	while (desc_status < 0) { /* e.g. & DescOwn */
@@ -2278,13 +2304,13 @@ static void netdev_rx(struct net_device *dev)
 	if (np->oom)
 		mod_timer(&np->timer, jiffies + 1);
 	else
-		writel(RxOn, dev->base_addr + ChipCmd);
+		writel(RxOn, ioaddr + ChipCmd);
 }
 
 static void netdev_error(struct net_device *dev, int intr_status)
 {
 	struct netdev_private *np = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 
 	spin_lock(&np->lock);
 	if (intr_status & LinkChange) {
@@ -2343,7 +2369,7 @@ static void netdev_error(struct net_device *dev, int intr_status)
 
 static void __get_stats(struct net_device *dev)
 {
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	struct netdev_private *np = netdev_priv(dev);
 
 	/* The chip only need report frame silently dropped. */
@@ -2364,10 +2390,19 @@ static struct net_device_stats *get_stats(struct net_device *dev)
 	return &np->stats;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void natsemi_poll_controller(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	intr_handler(dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
+
 #define HASH_TABLE	0x200
 static void __set_rx_mode(struct net_device *dev)
 {
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	struct netdev_private *np = netdev_priv(dev);
 	u8 mc_filter[64]; /* Multicast hash filter */
 	u32 rx_mode;
@@ -2413,7 +2448,7 @@ static int natsemi_change_mtu(struct net_device *dev, int new_mtu)
 	/* synchronized against open : rtnl_lock() held by caller */
 	if (netif_running(dev)) {
 		struct netdev_private *np = netdev_priv(dev);
-		long ioaddr = dev->base_addr;
+		void __iomem * ioaddr = ns_ioaddr(dev);
 
 		disable_irq(dev->irq);
 		spin_lock(&np->lock);
@@ -2616,7 +2651,8 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
 static int netdev_set_wol(struct net_device *dev, u32 newval)
 {
 	struct netdev_private *np = netdev_priv(dev);
-	u32 data = readl(dev->base_addr + WOLCmd) & ~WakeOptsSummary;
+	void __iomem * ioaddr = ns_ioaddr(dev);
+	u32 data = readl(ioaddr + WOLCmd) & ~WakeOptsSummary;
 
 	/* translate to bitmasks this chip understands */
 	if (newval & WAKE_PHY)
@@ -2637,7 +2673,7 @@ static int netdev_set_wol(struct net_device *dev, u32 newval)
 		}
 	}
 
-	writel(data, dev->base_addr + WOLCmd);
+	writel(data, ioaddr + WOLCmd);
 
 	return 0;
 }
@@ -2645,7 +2681,8 @@ static int netdev_set_wol(struct net_device *dev, u32 newval)
 static int netdev_get_wol(struct net_device *dev, u32 *supported, u32 *cur)
 {
 	struct netdev_private *np = netdev_priv(dev);
-	u32 regval = readl(dev->base_addr + WOLCmd);
+	void __iomem * ioaddr = ns_ioaddr(dev);
+	u32 regval = readl(ioaddr + WOLCmd);
 
 	*supported = (WAKE_PHY | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST
 			| WAKE_ARP | WAKE_MAGIC);
@@ -2680,6 +2717,7 @@ static int netdev_get_wol(struct net_device *dev, u32 *supported, u32 *cur)
 static int netdev_set_sopass(struct net_device *dev, u8 *newval)
 {
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	u16 *sval = (u16 *)newval;
 	u32 addr;
 
@@ -2688,22 +2726,22 @@ static int netdev_set_sopass(struct net_device *dev, u8 *newval)
 	}
 
 	/* enable writing to these registers by disabling the RX filter */
-	addr = readl(dev->base_addr + RxFilterAddr) & ~RFCRAddressMask;
+	addr = readl(ioaddr + RxFilterAddr) & ~RFCRAddressMask;
 	addr &= ~RxFilterEnable;
-	writel(addr, dev->base_addr + RxFilterAddr);
+	writel(addr, ioaddr + RxFilterAddr);
 
 	/* write the three words to (undocumented) RFCR vals 0xa, 0xc, 0xe */
-	writel(addr | 0xa, dev->base_addr + RxFilterAddr);
-	writew(sval[0], dev->base_addr + RxFilterData);
+	writel(addr | 0xa, ioaddr + RxFilterAddr);
+	writew(sval[0], ioaddr + RxFilterData);
 
-	writel(addr | 0xc, dev->base_addr + RxFilterAddr);
-	writew(sval[1], dev->base_addr + RxFilterData);
+	writel(addr | 0xc, ioaddr + RxFilterAddr);
+	writew(sval[1], ioaddr + RxFilterData);
 
-	writel(addr | 0xe, dev->base_addr + RxFilterAddr);
-	writew(sval[2], dev->base_addr + RxFilterData);
+	writel(addr | 0xe, ioaddr + RxFilterAddr);
+	writew(sval[2], ioaddr + RxFilterData);
 
 	/* re-enable the RX filter */
-	writel(addr | RxFilterEnable, dev->base_addr + RxFilterAddr);
+	writel(addr | RxFilterEnable, ioaddr + RxFilterAddr);
 
 	return 0;
 }
@@ -2711,6 +2749,7 @@ static int netdev_set_sopass(struct net_device *dev, u8 *newval)
 static int netdev_get_sopass(struct net_device *dev, u8 *data)
 {
 	struct netdev_private *np = netdev_priv(dev);
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	u16 *sval = (u16 *)data;
 	u32 addr;
 
@@ -2720,18 +2759,18 @@ static int netdev_get_sopass(struct net_device *dev, u8 *data)
 	}
 
 	/* read the three words from (undocumented) RFCR vals 0xa, 0xc, 0xe */
-	addr = readl(dev->base_addr + RxFilterAddr) & ~RFCRAddressMask;
+	addr = readl(ioaddr + RxFilterAddr) & ~RFCRAddressMask;
 
-	writel(addr | 0xa, dev->base_addr + RxFilterAddr);
-	sval[0] = readw(dev->base_addr + RxFilterData);
+	writel(addr | 0xa, ioaddr + RxFilterAddr);
+	sval[0] = readw(ioaddr + RxFilterData);
 
-	writel(addr | 0xc, dev->base_addr + RxFilterAddr);
-	sval[1] = readw(dev->base_addr + RxFilterData);
+	writel(addr | 0xc, ioaddr + RxFilterAddr);
+	sval[1] = readw(ioaddr + RxFilterData);
 
-	writel(addr | 0xe, dev->base_addr + RxFilterAddr);
-	sval[2] = readw(dev->base_addr + RxFilterData);
+	writel(addr | 0xe, ioaddr + RxFilterAddr);
+	sval[2] = readw(ioaddr + RxFilterData);
 
-	writel(addr, dev->base_addr + RxFilterAddr);
+	writel(addr, ioaddr + RxFilterAddr);
 
 	return 0;
 }
@@ -2894,10 +2933,11 @@ static int netdev_get_regs(struct net_device *dev, u8 *buf)
 	int j;
 	u32 rfcr;
 	u32 *rbuf = (u32 *)buf;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 
 	/* read non-mii page 0 of registers */
 	for (i = 0; i < NATSEMI_PG0_NREGS/2; i++) {
-		rbuf[i] = readl(dev->base_addr + i*4);
+		rbuf[i] = readl(ioaddr + i*4);
 	}
 
 	/* read current mii registers */
@@ -2905,20 +2945,20 @@ static int netdev_get_regs(struct net_device *dev, u8 *buf)
 		rbuf[i] = mdio_read(dev, i & 0x1f);
 
 	/* read only the 'magic' registers from page 1 */
-	writew(1, dev->base_addr + PGSEL);
-	rbuf[i++] = readw(dev->base_addr + PMDCSR);
-	rbuf[i++] = readw(dev->base_addr + TSTDAT);
-	rbuf[i++] = readw(dev->base_addr + DSPCFG);
-	rbuf[i++] = readw(dev->base_addr + SDCFG);
-	writew(0, dev->base_addr + PGSEL);
+	writew(1, ioaddr + PGSEL);
+	rbuf[i++] = readw(ioaddr + PMDCSR);
+	rbuf[i++] = readw(ioaddr + TSTDAT);
+	rbuf[i++] = readw(ioaddr + DSPCFG);
+	rbuf[i++] = readw(ioaddr + SDCFG);
+	writew(0, ioaddr + PGSEL);
 
 	/* read RFCR indexed registers */
-	rfcr = readl(dev->base_addr + RxFilterAddr);
+	rfcr = readl(ioaddr + RxFilterAddr);
 	for (j = 0; j < NATSEMI_RFDR_NREGS; j++) {
-		writel(j*2, dev->base_addr + RxFilterAddr);
-		rbuf[i++] = readw(dev->base_addr + RxFilterData);
+		writel(j*2, ioaddr + RxFilterAddr);
+		rbuf[i++] = readw(ioaddr + RxFilterData);
 	}
-	writel(rfcr, dev->base_addr + RxFilterAddr);
+	writel(rfcr, ioaddr + RxFilterAddr);
 
 	/* the interrupt status is clear-on-read - see if we missed any */
 	if (rbuf[4] & rbuf[5]) {
@@ -2943,10 +2983,11 @@ static int netdev_get_eeprom(struct net_device *dev, u8 *buf)
 {
 	int i;
 	u16 *ebuf = (u16 *)buf;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 
 	/* eeprom_read reads 16 bits, and indexes by 16 bits */
 	for (i = 0; i < NATSEMI_EEPROM_SIZE/2; i++) {
-		ebuf[i] = eeprom_read(dev->base_addr, i);
+		ebuf[i] = eeprom_read(ioaddr, i);
 		/* The EEPROM itself stores data bit-swapped, but eeprom_read
 		 * reads it back "sanely". So we swap it back here in order to
 		 * present it to userland as it is stored. */
@@ -3016,7 +3057,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
 static void enable_wol_mode(struct net_device *dev, int enable_intr)
 {
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	struct netdev_private *np = netdev_priv(dev);
 
 	if (netif_msg_wol(np))
@@ -3049,7 +3090,7 @@ static void enable_wol_mode(struct net_device *dev, int enable_intr)
 
 static int netdev_close(struct net_device *dev)
 {
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 	struct netdev_private *np = netdev_priv(dev);
 
 	if (netif_msg_ifdown(np))
@@ -3126,10 +3167,11 @@ static int netdev_close(struct net_device *dev)
 static void __devexit natsemi_remove1 (struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
+	void __iomem * ioaddr = ns_ioaddr(dev);
 
 	unregister_netdev (dev);
 	pci_release_regions (pdev);
-	iounmap ((char *) dev->base_addr);
+	iounmap(ioaddr);
 	free_netdev (dev);
 	pci_set_drvdata(pdev, NULL);
 }
@@ -3163,7 +3205,7 @@ static int natsemi_suspend (struct pci_dev *pdev, u32 state)
 {
 	struct net_device *dev = pci_get_drvdata (pdev);
 	struct netdev_private *np = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
+	void __iomem * ioaddr = ns_ioaddr(dev);
 
 	rtnl_lock();
 	if (netif_running (dev)) {
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index a4116f136..d9a9a0bb7 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -29,6 +29,7 @@
     last in cleanup_modue()
     Richard Guenther    : Added support for ISAPnP cards
     Paul Gortmaker	: Discontinued PCI support - use ne2k-pci.c instead.
+    Hayato Fujiwara	: Add m32r support.
 
 */
 
@@ -128,6 +129,14 @@ bad_clone_list[] __initdata = {
 #define NESM_START_PG	0x40	/* First page of TX buffer */
 #define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
 
+#ifdef CONFIG_PLAT_MAPPI
+#  define DCR_VAL 0x4b
+#elif CONFIG_PLAT_OAKS32R
+#  define DCR_VAL 0x48
+#else
+#  define DCR_VAL 0x49
+#endif
+
 static int ne_probe1(struct net_device *dev, int ioaddr);
 static int ne_probe_isapnp(struct net_device *dev);
 
@@ -387,7 +396,7 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
 		for (i = 0; i < 16; i++)
 			SA_prom[i] = SA_prom[i+i];
 		/* We must set the 8390 for word mode. */
-		outb_p(0x49, ioaddr + EN0_DCFG);
+		outb_p(DCR_VAL, ioaddr + EN0_DCFG);
 		start_page = NESM_START_PG;
 		stop_page = NESM_STOP_PG;
 	} else {
@@ -395,7 +404,12 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
 		stop_page = NE1SM_STOP_PG;
 	}
 
+#if  defined(CONFIG_PLAT_MAPPI) || defined(CONFIG_PLAT_OAKS32R)
+	neX000 = ((SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57)
+		|| (SA_prom[14] == 0x42 && SA_prom[15] == 0x42));
+#else
 	neX000 = (SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57);
+#endif
 	ctron =  (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
 	copam =  (SA_prom[14] == 0x49 && SA_prom[15] == 0x00);
 
@@ -476,10 +490,20 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
 
 	dev->base_addr = ioaddr;
 
+#ifdef CONFIG_PLAT_MAPPI
+	outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
+		ioaddr + E8390_CMD); /* 0x61 */
+	for (i = 0 ; i < ETHER_ADDR_LEN ; i++) {
+		dev->dev_addr[i] = SA_prom[i]
+			= inb_p(ioaddr + EN1_PHYS_SHIFT(i));
+		printk(" %2.2x", SA_prom[i]);
+	}
+#else
 	for(i = 0; i < ETHER_ADDR_LEN; i++) {
 		printk(" %2.2x", SA_prom[i]);
 		dev->dev_addr[i] = SA_prom[i];
 	}
+#endif
 
 	printk("\n%s: %s found at %#x, using IRQ %d.\n",
 		dev->name, name, ioaddr, dev->irq);
@@ -487,7 +511,11 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
 	ei_status.name = name;
 	ei_status.tx_start_page = start_page;
 	ei_status.stop_page = stop_page;
+#ifdef CONFIG_PLAT_OAKS32R
+	ei_status.word16 = 0;
+#else
 	ei_status.word16 = (wordlength == 2);
+#endif
 
 	ei_status.rx_start_page = start_page + TX_PAGES;
 #ifdef PACKETBUF_MEMSIZE
diff --git a/drivers/net/plip.c b/drivers/net/plip.c
index 43f923c96..937b6198c 100644
--- a/drivers/net/plip.c
+++ b/drivers/net/plip.c
@@ -547,7 +547,7 @@ static unsigned short plip_type_trans(struct sk_buff *skb, struct net_device *de
 	
 	skb->mac.raw=skb->data;
 	skb_pull(skb,dev->hard_header_len);
-	eth= skb->mac.ethernet;
+	eth = eth_hdr(skb);
 	
 	if(*eth->h_dest&1)
 	{
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
index e44b189c6..b64f284c1 100644
--- a/drivers/net/ppp_async.c
+++ b/drivers/net/ppp_async.c
@@ -122,6 +122,9 @@ static struct ppp_channel_ops async_ops = {
  * frees the memory that ppp_asynctty_receive is using.  The best
  * way to fix this is to use a rwlock in the tty struct, but for now
  * we use a single global rwlock for all ttys in ppp line discipline.
+ *
+ * FIXME: this is no longer true. The _close path for the ldisc is 
+ * now guaranteed to be sane. 
  */
 static rwlock_t disc_data_lock = RW_LOCK_UNLOCKED;
 
@@ -144,7 +147,8 @@ static void ap_put(struct asyncppp *ap)
 }
 
 /*
- * Called when a tty is put into PPP line discipline.
+ * Called when a tty is put into PPP line discipline. Called in process
+ * context.
  */
 static int
 ppp_asynctty_open(struct tty_struct *tty)
@@ -255,6 +259,11 @@ ppp_asynctty_write(struct tty_struct *tty, struct file *file,
 	return -EAGAIN;
 }
 
+/*
+ * Called in process context only. May be re-entered by multiple
+ * ioctl calling threads.
+ */
+ 
 static int
 ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
 		   unsigned int cmd, unsigned long arg)
@@ -716,7 +725,8 @@ flush:
 
 /*
  * Flush output from our internal buffers.
- * Called for the TCFLSH ioctl.
+ * Called for the TCFLSH ioctl. Can be entered in parallel
+ * but this is covered by the xmit_lock.
  */
 static void
 ppp_async_flush_output(struct asyncppp *ap)
@@ -816,7 +826,9 @@ process_input_packet(struct asyncppp *ap)
 		skb_trim(skb, 0);
 }
 
-/* called when the tty driver has data for us. */
+/* Called when the tty driver has data for us. Runs parallel with the
+   other ldisc functions but will not be re-entered */
+
 static void
 ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
 		char *flags, int count)
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 651601105..a56741087 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -1595,6 +1595,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
 			skb->dev = ppp->dev;
 			skb->protocol = htons(npindex_to_ethertype[npi]);
 			skb->mac.raw = skb->data;
+			skb->input_dev = ppp->dev;
 			netif_rx(skb);
 			ppp->dev->last_rx = jiffies;
 		}
diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c
index a8f890858..a59c8f354 100644
--- a/drivers/net/ppp_synctty.c
+++ b/drivers/net/ppp_synctty.c
@@ -175,6 +175,8 @@ ppp_print_buffer (const char *name, const __u8 *buf, int count)
  * frees the memory that ppp_synctty_receive is using.  The best
  * way to fix this is to use a rwlock in the tty struct, but for now
  * we use a single global rwlock for all ttys in ppp line discipline.
+ *
+ * FIXME: Fixed in tty_io nowdays.
  */
 static rwlock_t disc_data_lock = RW_LOCK_UNLOCKED;
 
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index 64b35cc25..672e3cd2d 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -391,7 +391,7 @@ static int pppoe_rcv(struct sk_buff *skb,
 
 	ph = (struct pppoe_hdr *) skb->nh.raw;
 
-	po = get_item((unsigned long) ph->sid, skb->mac.ethernet->h_source);
+	po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source);
 	if (!po) 
 		goto drop;
 
@@ -440,7 +440,7 @@ static int pppoe_disc_rcv(struct sk_buff *skb,
 	if (ph->code != PADT_CODE)
 		goto abort;
 
-	po = get_item((unsigned long) ph->sid, skb->mac.ethernet->h_source);
+	po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source);
 	if (po) {
 		struct sock *sk = po->sk;
 
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index e686cb440..98cd7d888 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -7,7 +7,7 @@
  Feb  4 2002	- created initially by ShuChen <shuchen@realtek.com.tw>.
  May 20 2002	- Add link status force-mode and TBI mode support.
 =========================================================================
-  1. The media can be forced in 5 modes.
+  1. [DEPRECATED: use ethtool instead] The media can be forced in 5 modes.
 	 Command: 'insmod r8169 media = SET_MEDIA'
 	 Ex:	  'insmod r8169 media = 0x04' will force PHY to operate in 100Mpbs Half-duplex.
 	
@@ -41,6 +41,7 @@ VERSION 1.2	<2002/11/30>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
 #include <linux/ethtool.h>
+#include <linux/mii.h>
 #include <linux/crc32.h>
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
@@ -64,6 +65,14 @@ VERSION 1.2	<2002/11/30>
 #define dprintk(fmt, args...)	do {} while (0)
 #endif /* RTL8169_DEBUG */
 
+#ifdef CONFIG_R8169_NAPI
+#define rtl8169_rx_skb			netif_receive_skb
+#define rtl8169_rx_quota(count, quota)	min(count, quota)
+#else
+#define rtl8169_rx_skb			netif_rx
+#define rtl8169_rx_quota(count, quota)	count
+#endif
+
 /* media options */
 #define MAX_UNITS 8
 static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
@@ -90,15 +99,16 @@ static int multicast_filter_limit = 32;
 #define RxPacketMaxSize	0x0800	/* Maximum size supported is 16K-1 */
 #define InterFrameGap	0x03	/* 3 means InterFrameGap = the shortest one */
 
+#define R8169_NAPI_WEIGHT	64
 #define NUM_TX_DESC	64	/* Number of Tx descriptor registers */
-#define NUM_RX_DESC	64	/* Number of Rx descriptor registers */
+#define NUM_RX_DESC	256	/* Number of Rx descriptor registers */
 #define RX_BUF_SIZE	1536	/* Rx Buffer size */
 #define R8169_TX_RING_BYTES	(NUM_TX_DESC * sizeof(struct TxDesc))
 #define R8169_RX_RING_BYTES	(NUM_RX_DESC * sizeof(struct RxDesc))
 
 #define RTL_MIN_IO_SIZE 0x80
 #define RTL8169_TX_TIMEOUT	(6*HZ)
-#define RTL8169_PHY_TIMEOUT	(HZ) 
+#define RTL8169_PHY_TIMEOUT	(10*HZ)
 
 /* write/read MMIO register */
 #define RTL_W8(reg, val8)	writeb ((val8), ioaddr + (reg))
@@ -146,6 +156,7 @@ static struct pci_device_id rtl8169_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
 
 static int rx_copybreak = 200;
+static int use_dac;
 
 enum RTL8169_registers {
 	MAC0 = 0,		/* Ethernet hardware address. */
@@ -194,7 +205,7 @@ enum RTL8169_register_content {
 	SWInt = 0x0100,
 	TxDescUnavail = 0x80,
 	RxFIFOOver = 0x40,
-	RxUnderrun = 0x20,
+	LinkChg = 0x20,
 	RxOverflow = 0x10,
 	TxErr = 0x08,
 	TxOK = 0x04,
@@ -233,6 +244,14 @@ enum RTL8169_register_content {
 	TxInterFrameGapShift = 24,
 	TxDMAShift = 8,	/* DMA burst value (0-7) is shift this many bits */
 
+	/* TBICSR p.28 */
+	TBIReset	= 0x80000000,
+	TBILoopback	= 0x40000000,
+	TBINwEnable	= 0x20000000,
+	TBINwRestart	= 0x10000000,
+	TBILinkOk	= 0x02000000,
+	TBINwComplete	= 0x01000000,
+
 	/* CPlusCmd p.31 */
 	RxVlan		= (1 << 6),
 	RxChkSum	= (1 << 5),
@@ -306,10 +325,10 @@ struct RxDesc {
 };
 
 struct rtl8169_private {
-	void *mmio_addr;	/* memory map physical address */
+	void *mmio_addr;		/* memory map physical address */
 	struct pci_dev *pci_dev;	/* Index of PCI device  */
 	struct net_device_stats stats;	/* statistics of net device */
-	spinlock_t lock;	/* spin lock flag */
+	spinlock_t lock;		/* spin lock flag */
 	int chipset;
 	int mac_version;
 	int phy_version;
@@ -317,21 +336,31 @@ struct rtl8169_private {
 	u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
 	u32 dirty_rx;
 	u32 dirty_tx;
-	struct TxDesc *TxDescArray;	/* Index of 256-alignment Tx Descriptor buffer */
-	struct RxDesc *RxDescArray;	/* Index of 256-alignment Rx Descriptor buffer */
+	struct TxDesc *TxDescArray;	/* 256-aligned Tx descriptor ring */
+	struct RxDesc *RxDescArray;	/* 256-aligned Rx descriptor ring */
 	dma_addr_t TxPhyAddr;
 	dma_addr_t RxPhyAddr;
 	struct sk_buff *Rx_skbuff[NUM_RX_DESC];	/* Rx data buffers */
-	struct sk_buff *Tx_skbuff[NUM_TX_DESC];	/* Index of Transmit data buffer */
+	struct sk_buff *Tx_skbuff[NUM_TX_DESC];	/* Tx data buffers */
 	struct timer_list timer;
-	unsigned long phy_link_down_cnt;
 	u16 cp_cmd;
+	u16 intr_mask;
+	int phy_auto_nego_reg;
+	int phy_1000_ctrl_reg;
+
+	int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex);
+	void (*get_settings)(struct net_device *, struct ethtool_cmd *);
+	void (*phy_reset_enable)(void *);
+	unsigned int (*phy_reset_pending)(void *);
+	unsigned int (*link_ok)(void *);
 };
 
 MODULE_AUTHOR("Realtek");
 MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
 MODULE_PARM(media, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM(use_dac, "i");
+MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
 MODULE_LICENSE("GPL");
 
 static int rtl8169_open(struct net_device *dev);
@@ -344,9 +373,14 @@ static int rtl8169_close(struct net_device *dev);
 static void rtl8169_set_rx_mode(struct net_device *dev);
 static void rtl8169_tx_timeout(struct net_device *dev);
 static struct net_device_stats *rtl8169_get_stats(struct net_device *netdev);
+#ifdef CONFIG_R8169_NAPI
+static int rtl8169_poll(struct net_device *dev, int *budget);
+#endif
 
 static const u16 rtl8169_intr_mask =
-    RxUnderrun | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK;
+	SYSErr | LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK;
+static const u16 rtl8169_napi_event =
+	RxOK | RxOverflow | RxFIFOOver | TxOK | TxErr;
 static const unsigned int rtl8169_rx_config =
     (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift);
 
@@ -364,11 +398,9 @@ static void mdio_write(void *ioaddr, int RegAddr, int value)
 
 	for (i = 2000; i > 0; i--) {
 		// Check if the RTL8169 has completed writing to the specified MII register
-		if (!(RTL_R32(PHYAR) & 0x80000000)) {
+		if (!(RTL_R32(PHYAR) & 0x80000000)) 
 			break;
-		} else {
-			udelay(100);
-		}
+		udelay(100);
 	}
 }
 
@@ -390,18 +422,264 @@ static int mdio_read(void *ioaddr, int RegAddr)
 	return value;
 }
 
+static unsigned int rtl8169_tbi_reset_pending(void *ioaddr)
+{
+	return RTL_R32(TBICSR) & TBIReset;
+}
+
+static unsigned int rtl8169_xmii_reset_pending(void *ioaddr)
+{
+	return mdio_read(ioaddr, 0) & 0x8000;
+}
+
+static unsigned int rtl8169_tbi_link_ok(void *ioaddr)
+{
+	return RTL_R32(TBICSR) & TBILinkOk;
+}
+
+static unsigned int rtl8169_xmii_link_ok(void *ioaddr)
+{
+	return RTL_R8(PHYstatus) & LinkStatus;
+}
+
+static void rtl8169_tbi_reset_enable(void *ioaddr)
+{
+	RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset);
+}
+
+static void rtl8169_xmii_reset_enable(void *ioaddr)
+{
+	unsigned int val;
+
+	val = (mdio_read(ioaddr, PHY_CTRL_REG) | 0x8000) & 0xffff;
+	mdio_write(ioaddr, PHY_CTRL_REG, val);
+}
+
+static void rtl8169_check_link_status(struct net_device *dev,
+				      struct rtl8169_private *tp, void *ioaddr)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&tp->lock, flags);
+	if (tp->link_ok(ioaddr)) {
+		netif_carrier_on(dev);
+		printk(KERN_INFO PFX "%s: link up\n", dev->name);
+	} else
+		netif_carrier_off(dev);
+	spin_unlock_irqrestore(&tp->lock, flags);
+}
+
+static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex)
+{
+	struct {
+		u16 speed;
+		u8 duplex;
+		u8 autoneg;
+		u8 media;
+	} link_settings[] = {
+		{ SPEED_10,	DUPLEX_HALF, AUTONEG_DISABLE,	_10_Half },
+		{ SPEED_10,	DUPLEX_FULL, AUTONEG_DISABLE,	_10_Full },
+		{ SPEED_100,	DUPLEX_HALF, AUTONEG_DISABLE,	_100_Half },
+		{ SPEED_100,	DUPLEX_FULL, AUTONEG_DISABLE,	_100_Full },
+		{ SPEED_1000,	DUPLEX_FULL, AUTONEG_DISABLE,	_1000_Full },
+		/* Make TBI happy */
+		{ SPEED_1000,	DUPLEX_FULL, AUTONEG_ENABLE,	0xff }
+	}, *p;
+	unsigned char option;
+	
+	option = ((idx < MAX_UNITS) && (idx >= 0)) ? media[idx] : 0xff;
+
+	if ((option != 0xff) && !idx)
+		printk(KERN_WARNING PFX "media option is deprecated.\n");
+
+	for (p = link_settings; p->media != 0xff; p++) {
+		if (p->media == option)
+			break;
+	}
+	*autoneg = p->autoneg;
+	*speed = p->speed;
+	*duplex = p->duplex;
+}
+
 static void rtl8169_get_drvinfo(struct net_device *dev,
 				struct ethtool_drvinfo *info)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 
 	strcpy(info->driver, RTL8169_DRIVER_NAME);
 	strcpy(info->version, RTL8169_VERSION );
 	strcpy(info->bus_info, pci_name(tp->pci_dev));
 }
 
+static int rtl8169_set_speed_tbi(struct net_device *dev,
+				 u8 autoneg, u16 speed, u8 duplex)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	void *ioaddr = tp->mmio_addr;
+	int ret = 0;
+	u32 reg;
+
+	reg = RTL_R32(TBICSR);
+	if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) &&
+	    (duplex == DUPLEX_FULL)) {
+		RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart));
+	} else if (autoneg == AUTONEG_ENABLE)
+		RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart);
+	else {
+		printk(KERN_WARNING PFX
+		       "%s: incorrect speed setting refused in TBI mode\n",
+		       dev->name);
+		ret = -EOPNOTSUPP;
+	}
+
+	return ret;
+}
+
+static int rtl8169_set_speed_xmii(struct net_device *dev,
+				  u8 autoneg, u16 speed, u8 duplex)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	void *ioaddr = tp->mmio_addr;
+	int auto_nego, giga_ctrl;
+
+	auto_nego = mdio_read(ioaddr, PHY_AUTO_NEGO_REG);
+	auto_nego &= ~(PHY_Cap_10_Half | PHY_Cap_10_Full |
+		       PHY_Cap_100_Half | PHY_Cap_100_Full);
+	giga_ctrl = mdio_read(ioaddr, PHY_1000_CTRL_REG);
+	giga_ctrl &= ~(PHY_Cap_1000_Full | PHY_Cap_Null);
+
+	if (autoneg == AUTONEG_ENABLE) {
+		auto_nego |= (PHY_Cap_10_Half | PHY_Cap_10_Full |
+			      PHY_Cap_100_Half | PHY_Cap_100_Full);
+		giga_ctrl |= PHY_Cap_1000_Full;
+	} else {
+		if (speed == SPEED_10)
+			auto_nego |= PHY_Cap_10_Half | PHY_Cap_10_Full;
+		else if (speed == SPEED_100)
+			auto_nego |= PHY_Cap_100_Half | PHY_Cap_100_Full;
+		else if (speed == SPEED_1000)
+			giga_ctrl |= PHY_Cap_1000_Full;
+
+		if (duplex == DUPLEX_HALF)
+			auto_nego &= ~(PHY_Cap_10_Full | PHY_Cap_100_Full);
+	}
+
+	tp->phy_auto_nego_reg = auto_nego;
+	tp->phy_1000_ctrl_reg = giga_ctrl;
+
+	mdio_write(ioaddr, PHY_AUTO_NEGO_REG, auto_nego);
+	mdio_write(ioaddr, PHY_1000_CTRL_REG, giga_ctrl);
+	mdio_write(ioaddr, PHY_CTRL_REG, PHY_Enable_Auto_Nego |
+					 PHY_Restart_Auto_Nego);
+	return 0;
+}
+
+static int rtl8169_set_speed(struct net_device *dev,
+			     u8 autoneg, u16 speed, u8 duplex)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	int ret;
+
+	ret = tp->set_speed(dev, autoneg, speed, duplex);
+
+	if (netif_running(dev) && (tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full))
+		mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT);
+
+	return ret;
+}
+
+static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&tp->lock, flags);
+	ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex);
+	spin_unlock_irqrestore(&tp->lock, flags);
+	
+	return ret;
+}
+
+static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	void *ioaddr = tp->mmio_addr;
+	u32 status;
+
+	cmd->supported =
+		SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE;
+	cmd->port = PORT_FIBRE;
+	cmd->transceiver = XCVR_INTERNAL;
+
+	status = RTL_R32(TBICSR);
+	cmd->advertising = (status & TBINwEnable) ?  ADVERTISED_Autoneg : 0;
+	cmd->autoneg = !!(status & TBINwEnable);
+
+	cmd->speed = SPEED_1000;
+	cmd->duplex = DUPLEX_FULL; /* Always set */
+}
+
+static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	void *ioaddr = tp->mmio_addr;
+	u8 status;
+
+	cmd->supported = SUPPORTED_10baseT_Half |
+			 SUPPORTED_10baseT_Full |
+			 SUPPORTED_100baseT_Half |
+			 SUPPORTED_100baseT_Full |
+			 SUPPORTED_1000baseT_Full |
+			 SUPPORTED_Autoneg |
+		         SUPPORTED_TP;
+
+	cmd->autoneg = 1;
+	cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg;
+
+	if (tp->phy_auto_nego_reg & PHY_Cap_10_Half)
+		cmd->advertising |= ADVERTISED_10baseT_Half;
+	if (tp->phy_auto_nego_reg & PHY_Cap_10_Full)
+		cmd->advertising |= ADVERTISED_10baseT_Full;
+	if (tp->phy_auto_nego_reg & PHY_Cap_100_Half)
+		cmd->advertising |= ADVERTISED_100baseT_Half;
+	if (tp->phy_auto_nego_reg & PHY_Cap_100_Full)
+		cmd->advertising |= ADVERTISED_100baseT_Full;
+	if (tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full)
+		cmd->advertising |= ADVERTISED_1000baseT_Full;
+
+	status = RTL_R8(PHYstatus);
+
+	if (status & _1000bpsF)
+		cmd->speed = SPEED_1000;
+	else if (status & _100bps)
+		cmd->speed = SPEED_100;
+	else if (status & _10bps)
+		cmd->speed = SPEED_10;
+
+	cmd->duplex = ((status & _1000bpsF) || (status & FullDup)) ?
+		      DUPLEX_FULL : DUPLEX_HALF;
+}
+
+static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&tp->lock, flags);
+
+	tp->get_settings(dev, cmd);
+
+	spin_unlock_irqrestore(&tp->lock, flags);
+	return 0;
+}
+
+
 static struct ethtool_ops rtl8169_ethtool_ops = {
 	.get_drvinfo		= rtl8169_get_drvinfo,
+	.get_link		= ethtool_op_get_link,
+	.get_settings		= rtl8169_get_settings,
+	.set_settings		= rtl8169_set_settings,
 };
 
 static void rtl8169_write_gmii_reg_bit(void *ioaddr, int reg, int bitnum,
@@ -500,7 +778,7 @@ static void rtl8169_print_phy_version(struct rtl8169_private *tp)
 
 static void rtl8169_hw_phy_config(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	struct {
 		u16 regs[5]; /* Beware of bit-sign propagation */
@@ -566,61 +844,47 @@ static void rtl8169_hw_phy_config(struct net_device *dev)
 	mdio_write(ioaddr, 31, 0x0000); //w 31 2 0 0
 }
 
-static void rtl8169_hw_phy_reset(struct net_device *dev)
-{
-	struct rtl8169_private *tp = dev->priv;
-	void *ioaddr = tp->mmio_addr;
-	int i, val;
-
-	printk(KERN_WARNING PFX "%s: Reset RTL8169s PHY\n", dev->name);
-
-	val = (mdio_read(ioaddr, 0) | 0x8000) & 0xffff;
-	mdio_write(ioaddr, 0, val);
-
-	for (i = 50; i >= 0; i--) {
-		if (!(mdio_read(ioaddr, 0) & 0x8000))
-			break;
-		udelay(100); /* Gross */
-	}
-
-	if (i < 0) {
-		printk(KERN_WARNING PFX "%s: no PHY Reset ack. Giving up.\n",
-		       dev->name);
-	}
-}
-
 static void rtl8169_phy_timer(unsigned long __opaque)
 {
 	struct net_device *dev = (struct net_device *)__opaque;
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	struct timer_list *timer = &tp->timer;
 	void *ioaddr = tp->mmio_addr;
+	unsigned long timeout = RTL8169_PHY_TIMEOUT;
 
 	assert(tp->mac_version > RTL_GIGA_MAC_VER_B);
 	assert(tp->phy_version < RTL_GIGA_PHY_VER_G);
 
-	if (RTL_R8(PHYstatus) & LinkStatus)
-		tp->phy_link_down_cnt = 0;
-	else {
-		tp->phy_link_down_cnt++;
-		if (tp->phy_link_down_cnt >= 12) {
-			int reg;
+	if (!(tp->phy_1000_ctrl_reg & PHY_Cap_1000_Full))
+		return;
 
-			// If link on 1000, perform phy reset.
-			reg = mdio_read(ioaddr, PHY_1000_CTRL_REG);
-			if (reg & PHY_Cap_1000_Full) 
-				rtl8169_hw_phy_reset(dev);
+	spin_lock_irq(&tp->lock);
 
-			tp->phy_link_down_cnt = 0;
-		}
+	if (tp->phy_reset_pending(ioaddr)) {
+		/* 
+		 * A busy loop could burn quite a few cycles on nowadays CPU.
+		 * Let's delay the execution of the timer for a few ticks.
+		 */
+		timeout = HZ/10;
+		goto out_mod_timer;
 	}
 
-	mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT);
+	if (tp->link_ok(ioaddr))
+		goto out_unlock;
+
+	printk(KERN_WARNING PFX "%s: PHY reset until link up\n", dev->name);
+
+	tp->phy_reset_enable(ioaddr);
+
+out_mod_timer:
+	mod_timer(timer, jiffies + timeout);
+out_unlock:
+	spin_unlock_irq(&tp->lock);
 }
 
 static inline void rtl8169_delete_timer(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	struct timer_list *timer = &tp->timer;
 
 	if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) ||
@@ -628,21 +892,17 @@ static inline void rtl8169_delete_timer(struct net_device *dev)
 		return;
 
 	del_timer_sync(timer);
-
-	tp->phy_link_down_cnt = 0;
 }
 
 static inline void rtl8169_request_timer(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	struct timer_list *timer = &tp->timer;
 
 	if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) ||
 	    (tp->phy_version >= RTL_GIGA_PHY_VER_G))
 		return;
 
-	tp->phy_link_down_cnt = 0;
-
 	init_timer(timer);
 	timer->expires = jiffies + RTL8169_PHY_TIMEOUT;
 	timer->data = (unsigned long)(dev);
@@ -681,7 +941,7 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
 	// enable device (incl. PCI PM wakeup and hotplug setup)
 	rc = pci_enable_device(pdev);
 	if (rc) {
-		printk(KERN_ERR PFX "%s: unable to enable device\n", pdev->slot_name);
+		printk(KERN_ERR PFX "%s: enable failure\n", pdev->slot_name);
 		goto err_out;
 	}
 
@@ -693,7 +953,8 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
 		pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command);
 		acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
 	} else {
-		printk(KERN_ERR PFX "Cannot find PowerManagement capability, aborting.\n");
+		printk(KERN_ERR PFX
+		       "Cannot find PowerManagement capability, aborting.\n");
 		goto err_out_free_res;
 	}
 
@@ -718,14 +979,15 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
 
 	rc = pci_request_regions(pdev, MODULENAME);
 	if (rc) {
-		printk(KERN_ERR PFX "%s: Could not request regions.\n", pdev->slot_name);
+		printk(KERN_ERR PFX "%s: could not request regions.\n",
+		       pdev->slot_name);
 		goto err_out_disable;
 	}
 
 	tp->cp_cmd = PCIMulRW | RxChkSum;
 
-	if ((sizeof(dma_addr_t) > 32) &&
-	    !pci_set_dma_mask(pdev, DMA_64BIT_MASK))
+	if ((sizeof(dma_addr_t) > 4) &&
+	    !pci_set_dma_mask(pdev, DMA_64BIT_MASK) && use_dac)
 		tp->cp_cmd |= PCIDAC;
 	else {
 		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
@@ -800,8 +1062,9 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	void *ioaddr = NULL;
 	static int board_idx = -1;
 	static int printed_version = 0;
+	u8 autoneg, duplex;
+	u16 speed;
 	int i, rc;
-	int option = -1, Cap10_100 = 0, Cap1000 = 0;
 
 	assert(pdev != NULL);
 	assert(ent != NULL);
@@ -822,6 +1085,22 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	assert(dev != NULL);
 	assert(tp != NULL);
 
+	if (RTL_R8(PHYstatus) & TBI_Enable) {
+		tp->set_speed = rtl8169_set_speed_tbi;
+		tp->get_settings = rtl8169_gset_tbi;
+		tp->phy_reset_enable = rtl8169_tbi_reset_enable;
+		tp->phy_reset_pending = rtl8169_tbi_reset_pending;
+		tp->link_ok = rtl8169_tbi_link_ok;
+
+		tp->phy_1000_ctrl_reg = PHY_Cap_1000_Full; /* Implied by TBI */
+	} else {
+		tp->set_speed = rtl8169_set_speed_xmii;
+		tp->get_settings = rtl8169_gset_xmii;
+		tp->phy_reset_enable = rtl8169_xmii_reset_enable;
+		tp->phy_reset_pending = rtl8169_xmii_reset_pending;
+		tp->link_ok = rtl8169_xmii_link_ok;
+	}
+
 	// Get MAC address.  FIXME: read EEPROM
 	for (i = 0; i < MAC_ADDR_LEN; i++)
 		dev->dev_addr[i] = RTL_R8(MAC0 + i);
@@ -836,9 +1115,12 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
 	dev->irq = pdev->irq;
 	dev->base_addr = (unsigned long) ioaddr;
-//      dev->do_ioctl           = mii_ioctl;
-
-	tp = dev->priv;		// private data //
+#ifdef CONFIG_R8169_NAPI
+	dev->poll = rtl8169_poll;
+	dev->weight = R8169_NAPI_WEIGHT;
+	printk(KERN_INFO PFX "NAPI enabled\n");
+#endif
+	tp->intr_mask = 0xffff;
 	tp->pci_dev = pdev;
 	tp->mmio_addr = ioaddr;
 
@@ -885,95 +1167,12 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0
 	}
 
-	// if TBI is not endbled
-	if (!(RTL_R8(PHYstatus) & TBI_Enable)) {
-		int val = mdio_read(ioaddr, PHY_AUTO_NEGO_REG);
-
-		option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx];
-		// Force RTL8169 in 10/100/1000 Full/Half mode.
-		if (option > 0) {
-			printk(KERN_INFO "%s: Force-mode Enabled.\n",
-			       dev->name);
-			Cap10_100 = 0, Cap1000 = 0;
-			switch (option) {
-			case _10_Half:
-				Cap10_100 = PHY_Cap_10_Half_Or_Less;
-				Cap1000 = PHY_Cap_Null;
-				break;
-			case _10_Full:
-				Cap10_100 = PHY_Cap_10_Full_Or_Less;
-				Cap1000 = PHY_Cap_Null;
-				break;
-			case _100_Half:
-				Cap10_100 = PHY_Cap_100_Half_Or_Less;
-				Cap1000 = PHY_Cap_Null;
-				break;
-			case _100_Full:
-				Cap10_100 = PHY_Cap_100_Full_Or_Less;
-				Cap1000 = PHY_Cap_Null;
-				break;
-			case _1000_Full:
-				Cap10_100 = PHY_Cap_100_Full_Or_Less;
-				Cap1000 = PHY_Cap_1000_Full;
-				break;
-			default:
-				break;
-			}
-			mdio_write(ioaddr, PHY_AUTO_NEGO_REG, Cap10_100 | (val & 0x1F));	//leave PHY_AUTO_NEGO_REG bit4:0 unchanged
-			mdio_write(ioaddr, PHY_1000_CTRL_REG, Cap1000);
-		} else {
-			printk(KERN_INFO "%s: Auto-negotiation Enabled.\n",
-			       dev->name);
-
-			// enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged
-			mdio_write(ioaddr, PHY_AUTO_NEGO_REG,
-				   PHY_Cap_100_Full_Or_Less | (val & 0x1f));
+	rtl8169_link_option(board_idx, &autoneg, &speed, &duplex);
 
-			// enable 1000 Full Mode
-			mdio_write(ioaddr, PHY_1000_CTRL_REG,
-				   PHY_Cap_1000_Full);
-
-		}
-
-		// Enable auto-negotiation and restart auto-nigotiation
-		mdio_write(ioaddr, PHY_CTRL_REG,
-			   PHY_Enable_Auto_Nego | PHY_Restart_Auto_Nego);
-		udelay(100);
-
-		// wait for auto-negotiation process
-		for (i = 10000; i > 0; i--) {
-			//check if auto-negotiation complete
-			if (mdio_read(ioaddr, PHY_STAT_REG) &
-			    PHY_Auto_Neco_Comp) {
-				udelay(100);
-				option = RTL_R8(PHYstatus);
-				if (option & _1000bpsF) {
-					printk(KERN_INFO
-					       "%s: 1000Mbps Full-duplex operation.\n",
-					       dev->name);
-				} else {
-					printk(KERN_INFO
-					       "%s: %sMbps %s-duplex operation.\n",
-					       dev->name,
-					       (option & _100bps) ? "100" :
-					       "10",
-					       (option & FullDup) ? "Full" :
-					       "Half");
-				}
-				break;
-			} else {
-				udelay(100);
-			}
-		}		// end for-loop to wait for auto-negotiation process
-
-	} else {
-		udelay(100);
-		printk(KERN_INFO
-		       "%s: 1000Mbps Full-duplex operation, TBI Link %s!\n",
-		       dev->name,
-		       (RTL_R32(TBICSR) & TBILinkOK) ? "OK" : "Failed");
-
-	}
+	rtl8169_set_speed(dev, autoneg, speed, duplex);
+	
+	if (RTL_R8(PHYstatus) & TBI_Enable)
+		printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name);
 
 	return 0;
 }
@@ -982,7 +1181,7 @@ static void __devexit
 rtl8169_remove_one(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 
 	assert(dev != NULL);
 	assert(tp != NULL);
@@ -1001,7 +1200,7 @@ rtl8169_remove_one(struct pci_dev *pdev)
 static int rtl8169_suspend(struct pci_dev *pdev, u32 state)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	unsigned long flags;
 
@@ -1042,7 +1241,7 @@ static int rtl8169_resume(struct pci_dev *pdev)
 static int
 rtl8169_open(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	struct pci_dev *pdev = tp->pci_dev;
 	int retval;
 
@@ -1074,6 +1273,8 @@ rtl8169_open(struct net_device *dev)
 	rtl8169_hw_start(dev);
 
 	rtl8169_request_timer(dev);
+
+	rtl8169_check_link_status(dev, tp, tp->mmio_addr);
 out:
 	return retval;
 
@@ -1091,7 +1292,7 @@ err_free_irq:
 static void
 rtl8169_hw_start(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	u32 i;
 
@@ -1102,8 +1303,7 @@ rtl8169_hw_start(struct net_device *dev)
 	for (i = 1000; i > 0; i--) {
 		if ((RTL_R8(ChipCmd) & CmdReset) == 0)
 			break;
-		else
-			udelay(10);
+		udelay(10);
 	}
 
 	RTL_W8(Cfg9346, Cfg9346_Unlock);
@@ -1114,8 +1314,8 @@ rtl8169_hw_start(struct net_device *dev)
 	RTL_W16(RxMaxSize, RxPacketMaxSize);
 
 	// Set Rx Config register
-	i = rtl8169_rx_config | (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].
-				 RxConfigMask);
+	i = rtl8169_rx_config |
+		(RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
 	RTL_W32(RxConfig, i);
 
 	/* Set DMA burst size and Interframe Gap Time */
@@ -1126,7 +1326,8 @@ rtl8169_hw_start(struct net_device *dev)
 	RTL_W16(CPlusCmd, tp->cp_cmd);
 
 	if (tp->mac_version == RTL_GIGA_MAC_VER_D) {
-		dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14 MUST be 1\n");
+		dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0. "
+			"Bit-3 and bit-14 MUST be 1\n");
 		tp->cp_cmd |= (1 << 14) | PCIMulRW;
 		RTL_W16(CPlusCmd, tp->cp_cmd);
 	}
@@ -1151,7 +1352,6 @@ rtl8169_hw_start(struct net_device *dev)
 	RTL_W16(IntrMask, rtl8169_intr_mask);
 
 	netif_start_queue(dev);
-
 }
 
 static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc)
@@ -1248,7 +1448,7 @@ static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc)
 
 static int rtl8169_init_ring(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 
 	tp->cur_rx = tp->dirty_rx = 0;
 	tp->cur_tx = tp->dirty_tx = 0;
@@ -1302,10 +1502,11 @@ rtl8169_tx_clear(struct rtl8169_private *tp)
 static void
 rtl8169_tx_timeout(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	u8 tmp8;
 
+	printk(KERN_INFO "%s: TX Timeout\n", dev->name);
 	/* disable Tx, if not already */
 	tmp8 = RTL_R8(ChipCmd);
 	if (tmp8 & CmdTxEnb)
@@ -1328,9 +1529,9 @@ rtl8169_tx_timeout(struct net_device *dev)
 static int
 rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
-	int entry = tp->cur_tx % NUM_TX_DESC;
+	unsigned int entry = tp->cur_tx % NUM_TX_DESC;
 	u32 len = skb->len;
 
 	if (unlikely(skb->len < ETH_ZLEN)) {
@@ -1340,10 +1541,9 @@ rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		len = ETH_ZLEN;
 	}
 	
-	spin_lock_irq(&tp->lock);
-
 	if (!(le32_to_cpu(tp->TxDescArray[entry].status) & OWNbit)) {
 		dma_addr_t mapping;
+		u32 status;
 
 		mapping = pci_map_single(tp->pci_dev, skb->data, len,
 					 PCI_DMA_TODEVICE);
@@ -1351,24 +1551,30 @@ rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		tp->Tx_skbuff[entry] = skb;
 		tp->TxDescArray[entry].addr = cpu_to_le64(mapping);
 
-		tp->TxDescArray[entry].status = cpu_to_le32(OWNbit | FSbit |
-			LSbit | len | (EORbit * !((entry + 1) % NUM_TX_DESC)));
+		/* anti gcc 2.95.3 bugware */
+		status = OWNbit | FSbit | LSbit | len |
+			 (EORbit * !((entry + 1) % NUM_TX_DESC));
+		tp->TxDescArray[entry].status = cpu_to_le32(status);
 			
 		RTL_W8(TxPoll, 0x40);	//set polling bit
 
 		dev->trans_start = jiffies;
 
 		tp->cur_tx++;
+		smp_wmb();
 	} else
 		goto err_drop;
 
-
 	if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) {
+		u32 dirty = tp->dirty_tx;
+	
 		netif_stop_queue(dev);
+		smp_rmb();
+		if (dirty != tp->dirty_tx)
+			netif_wake_queue(dev);
 	}
-out:
-	spin_unlock_irq(&tp->lock);
 
+out:
 	return 0;
 
 err_drop:
@@ -1382,17 +1588,18 @@ static void
 rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
 		     void *ioaddr)
 {
-	unsigned long dirty_tx, tx_left;
+	unsigned int dirty_tx, tx_left;
 
 	assert(dev != NULL);
 	assert(tp != NULL);
 	assert(ioaddr != NULL);
 
 	dirty_tx = tp->dirty_tx;
+	smp_rmb();
 	tx_left = tp->cur_tx - dirty_tx;
 
 	while (tx_left > 0) {
-		int entry = dirty_tx % NUM_TX_DESC;
+		unsigned int entry = dirty_tx % NUM_TX_DESC;
 		struct sk_buff *skb = tp->Tx_skbuff[entry];
 		u32 status;
 
@@ -1415,6 +1622,7 @@ rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
 
 	if (tp->dirty_tx != dirty_tx) {
 		tp->dirty_tx = dirty_tx;
+		smp_wmb();
 		if (netif_queue_stopped(dev))
 			netif_wake_queue(dev);
 	}
@@ -1442,11 +1650,11 @@ static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
 	return ret;
 }
 
-static void
+static int
 rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
 		     void *ioaddr)
 {
-	unsigned long cur_rx, rx_left;
+	unsigned int cur_rx, rx_left, count;
 	int delta;
 
 	assert(dev != NULL);
@@ -1455,9 +1663,10 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
 
 	cur_rx = tp->cur_rx;
 	rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
+	rx_left = rtl8169_rx_quota(rx_left, (u32) dev->quota);
 
 	while (rx_left > 0) {
-		int entry = cur_rx % NUM_RX_DESC;
+		unsigned int entry = cur_rx % NUM_RX_DESC;
 		u32 status;
 
 		rmb();
@@ -1494,7 +1703,7 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
 
 			skb_put(skb, pkt_size);
 			skb->protocol = eth_type_trans(skb, dev);
-			netif_rx(skb);
+			rtl8169_rx_skb(skb);
 
 			dev->last_rx = jiffies;
 			tp->stats.rx_bytes += pkt_size;
@@ -1505,13 +1714,15 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
 		rx_left--;
 	}
 
+	count = cur_rx - tp->cur_rx;
 	tp->cur_rx = cur_rx;
 
 	delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx);
-	if (delta > 0)
-		tp->dirty_rx += delta;
-	else if (delta < 0)
+	if (delta < 0) {
 		printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name);
+		delta = 0;
+	}
+	tp->dirty_rx += delta;
 
 	/*
 	 * FIXME: until there is periodic timer to try and refill the ring,
@@ -1522,6 +1733,8 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
 	 */
 	if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx)
 		printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name);
+
+	return count;
 }
 
 /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */
@@ -1529,7 +1742,7 @@ static irqreturn_t
 rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_instance;
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	int boguscnt = max_interrupt_work;
 	void *ioaddr = tp->mmio_addr;
 	int status = 0;
@@ -1543,26 +1756,46 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 			break;
 
 		handled = 1;
-/*
-		if (status & RxUnderrun)
-			link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit;
-*/
+
+		status &= tp->intr_mask;
 		RTL_W16(IntrStatus,
 			(status & RxFIFOOver) ? (status | RxOverflow) : status);
 
 		if (!(status & rtl8169_intr_mask))
 			break;
 
+		if (unlikely(status & SYSErr)) {
+			printk(KERN_ERR PFX "%s: PCI error (status: 0x%04x)."
+			       " Device disabled.\n", dev->name, status);
+			RTL_W8(ChipCmd, 0x00);
+			RTL_W16(IntrMask, 0x0000);
+			RTL_R16(IntrMask);
+			break;
+		}
+
+		if (status & LinkChg)
+			rtl8169_check_link_status(dev, tp, ioaddr);
+
+#ifdef CONFIG_R8169_NAPI
+		RTL_W16(IntrMask, rtl8169_intr_mask & ~rtl8169_napi_event);
+		tp->intr_mask = ~rtl8169_napi_event;
+
+		if (likely(netif_rx_schedule_prep(dev)))
+			__netif_rx_schedule(dev);
+		else {
+			printk(KERN_INFO "%s: interrupt %x taken in poll\n",
+			       dev->name, status);	
+		}
+		break;
+#else
 		// Rx interrupt 
-		if (status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOver)) {
+		if (status & (RxOK | RxOverflow | RxFIFOOver)) {
 			rtl8169_rx_interrupt(dev, tp, ioaddr);
 		}
 		// Tx interrupt
-		if (status & (TxOK | TxErr)) {
-			spin_lock(&tp->lock);
+		if (status & (TxOK | TxErr))
 			rtl8169_tx_interrupt(dev, tp, ioaddr);
-			spin_unlock(&tp->lock);
-		}
+#endif
 
 		boguscnt--;
 	} while (boguscnt > 0);
@@ -1576,10 +1809,40 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 	return IRQ_RETVAL(handled);
 }
 
+#ifdef CONFIG_R8169_NAPI
+static int rtl8169_poll(struct net_device *dev, int *budget)
+{
+	unsigned int work_done, work_to_do = min(*budget, dev->quota);
+	struct rtl8169_private *tp = netdev_priv(dev);
+	void *ioaddr = tp->mmio_addr;
+
+	work_done = rtl8169_rx_interrupt(dev, tp, ioaddr);
+	rtl8169_tx_interrupt(dev, tp, ioaddr);
+
+	*budget -= work_done;
+	dev->quota -= work_done;
+
+	if ((work_done < work_to_do) || !netif_running(dev)) {
+		netif_rx_complete(dev);
+		tp->intr_mask = 0xffff;
+		/*
+		 * 20040426: the barrier is not strictly required but the
+		 * behavior of the irq handler could be less predictable
+		 * without it. Btw, the lack of flush for the posted pci
+		 * write is safe - FR
+		 */
+		smp_wmb();
+		RTL_W16(IntrMask, rtl8169_intr_mask);
+	}
+
+	return (work_done >= work_to_do);
+}
+#endif
+
 static int
 rtl8169_close(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	struct pci_dev *pdev = tp->pci_dev;
 	void *ioaddr = tp->mmio_addr;
 
@@ -1621,7 +1884,7 @@ rtl8169_close(struct net_device *dev)
 static void
 rtl8169_set_rx_mode(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	unsigned long flags;
 	u32 mc_filter[2];	/* Multicast hash filter */
@@ -1655,10 +1918,8 @@ rtl8169_set_rx_mode(struct net_device *dev)
 
 	spin_lock_irqsave(&tp->lock, flags);
 
-	tmp =
-	    rtl8169_rx_config | rx_mode | (RTL_R32(RxConfig) &
-					   rtl_chip_info[tp->chipset].
-					   RxConfigMask);
+	tmp = rtl8169_rx_config | rx_mode |
+	      (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
 
 	RTL_W32(RxConfig, tmp);
 	RTL_W32(MAR0 + 0, mc_filter[0]);
@@ -1675,7 +1936,7 @@ rtl8169_set_rx_mode(struct net_device *dev)
  */
 static struct net_device_stats *rtl8169_get_stats(struct net_device *dev)
 {
-	struct rtl8169_private *tp = dev->priv;
+	struct rtl8169_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	unsigned long flags;
 
diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c
index 059f1a68a..402f779ff 100644
--- a/drivers/net/rrunner.c
+++ b/drivers/net/rrunner.c
@@ -1139,6 +1139,49 @@ static irqreturn_t rr_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
 	return IRQ_HANDLED;
 }
 
+static inline void rr_raz_tx(struct rr_private *rrpriv,
+			     struct net_device *dev)
+{
+	int i;
+
+	for (i = 0; i < TX_RING_ENTRIES; i++) {
+		struct sk_buff *skb = rrpriv->tx_skbuff[i];
+
+		if (skb) {
+			struct tx_desc *desc = &(rrpriv->tx_ring[i]);
+
+	        	pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo,
+				skb->len, PCI_DMA_TODEVICE);
+			desc->size = 0;
+			set_rraddr(&desc->addr, 0);
+			dev_kfree_skb(skb);
+			rrpriv->tx_skbuff[i] = NULL;
+		}
+	}
+}
+
+
+static inline void rr_raz_rx(struct rr_private *rrpriv,
+			     struct net_device *dev)
+{
+	int i;
+
+	for (i = 0; i < RX_RING_ENTRIES; i++) {
+		struct sk_buff *skb = rrpriv->rx_skbuff[i];
+
+		if (skb) {
+			struct rx_desc *desc = &(rrpriv->rx_ring[i]);
+
+	        	pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo,
+				dev->mtu + HIPPI_HLEN, PCI_DMA_FROMDEVICE);
+			desc->size = 0;
+			set_rraddr(&desc->addr, 0);
+			dev_kfree_skb(skb);
+			rrpriv->rx_skbuff[i] = NULL;
+		}
+	}
+}
+
 static void rr_timer(unsigned long data)
 {
 	struct net_device *dev = (struct net_device *)data;
@@ -1254,49 +1297,6 @@ static int rr_open(struct net_device *dev)
 }
 
 
-static inline void rr_raz_tx(struct rr_private *rrpriv, 
-			     struct net_device *dev)
-{
-	int i;
-
-	for (i = 0; i < TX_RING_ENTRIES; i++) {
-		struct sk_buff *skb = rrpriv->tx_skbuff[i];
-
-		if (skb) {
-			struct tx_desc *desc = &(rrpriv->tx_ring[i]);
-
-	        	pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo, 
-				skb->len, PCI_DMA_TODEVICE);
-			desc->size = 0;
-			set_rraddr(&desc->addr, 0);
-			dev_kfree_skb(skb);
-			rrpriv->tx_skbuff[i] = NULL;
-		}
-	}
-}
-
-
-static inline void rr_raz_rx(struct rr_private *rrpriv, 
-			     struct net_device *dev)
-{
-	int i;
-
-	for (i = 0; i < RX_RING_ENTRIES; i++) {
-		struct sk_buff *skb = rrpriv->rx_skbuff[i];
-
-		if (skb) {
-			struct rx_desc *desc = &(rrpriv->rx_ring[i]);
-
-	        	pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo, 
-				dev->mtu + HIPPI_HLEN, PCI_DMA_FROMDEVICE);
-			desc->size = 0;
-			set_rraddr(&desc->addr, 0);
-			dev_kfree_skb(skb);
-			rrpriv->rx_skbuff[i] = NULL;
-		}
-	}
-}
-
 static void rr_dump(struct net_device *dev)
 {
 	struct rr_private *rrpriv;
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index c4bd1793f..c68c1c0e7 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -235,10 +235,10 @@ static struct pci_device_id s2io_tbl[] __devinitdata = {
 MODULE_DEVICE_TABLE(pci, s2io_tbl);
 
 static struct pci_driver s2io_driver = {
-      name:"S2IO",
-      id_table:s2io_tbl,
-      probe:s2io_init_nic,
-      remove:__devexit_p(s2io_rem_nic),
+      .name = "S2IO",
+      .id_table = s2io_tbl,
+      .probe = s2io_init_nic,
+      .remove = __devexit_p(s2io_rem_nic),
 };
 
 /*  
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 425e89fe2..1a87a82a8 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -124,6 +124,7 @@ static struct mii_chip_info {
 	{ "AMD 79C901 HomePNA PHY",		0x0000, 0x6B90, HOME},
 	{ "ICS LAN PHY",			0x0015, 0xF440, LAN },
 	{ "NS 83851 PHY",			0x2000, 0x5C20, MIX },
+	{ "NS 83847 PHY",                       0x2000, 0x5C30, MIX },
 	{ "Realtek RTL8201 PHY",		0x0000, 0x8200, LAN },
 	{ "VIA 6103 PHY",			0x0101, 0x8f20, LAN },
 	{NULL,},
diff --git a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h
index 0790e7b7a..c80ac3c55 100644
--- a/drivers/net/sk98lin/h/skdrv2nd.h
+++ b/drivers/net/sk98lin/h/skdrv2nd.h
@@ -53,60 +53,6 @@
 #include "h/skrlmt.h"
 #include "h/skgedrv.h"
 
-#define SK_PCI_ISCOMPLIANT(result, pdev) {     \
-    result = SK_FALSE; /* default */     \
-    /* 3Com (0x10b7) */     \
-    if (pdev->vendor == 0x10b7) {     \
-        /* Gigabit Ethernet Adapter (0x1700) */     \
-        if ((pdev->device == 0x1700) || \
-            (pdev->device == 0x80eb)) { \
-            result = SK_TRUE;     \
-        }     \
-    /* SysKonnect (0x1148) */     \
-    } else if (pdev->vendor == 0x1148) {     \
-        /* SK-98xx Gigabit Ethernet Server Adapter (0x4300) */     \
-        /* SK-98xx V2.0 Gigabit Ethernet Adapter (0x4320) */     \
-        if ((pdev->device == 0x4300) || \
-            (pdev->device == 0x4320)) { \
-            result = SK_TRUE;     \
-        }     \
-    /* D-Link (0x1186) */     \
-    } else if (pdev->vendor == 0x1186) {     \
-        /* Gigabit Ethernet Adapter (0x4c00) */     \
-        if ((pdev->device == 0x4c00)) { \
-            result = SK_TRUE;     \
-        }     \
-    /* Marvell (0x11ab) */     \
-    } else if (pdev->vendor == 0x11ab) {     \
-        /* Gigabit Ethernet Adapter (0x4320) */     \
-        /* Gigabit Ethernet Adapter (0x4360) */     \
-        /* Gigabit Ethernet Adapter (0x4361) */     \
-        /* Belkin (0x5005) */     \
-        if ((pdev->device == 0x4320) || \
-            (pdev->device == 0x4360) || \
-            (pdev->device == 0x4361) || \
-            (pdev->device == 0x5005)) { \
-            result = SK_TRUE;     \
-        }     \
-    /* CNet (0x1371) */     \
-    } else if (pdev->vendor == 0x1371) {     \
-        /* GigaCard Network Adapter (0x434e) */     \
-        if ((pdev->device == 0x434e)) { \
-            result = SK_TRUE;     \
-        }     \
-    /* Linksys (0x1737) */     \
-    } else if (pdev->vendor == 0x1737) {     \
-        /* Gigabit Network Adapter (0x1032) */     \
-        /* Gigabit Network Adapter (0x1064) */     \
-        if ((pdev->device == 0x1032) || \
-            (pdev->device == 0x1064)) { \
-            result = SK_TRUE;     \
-        }     \
-    } else {     \
-        result = SK_FALSE;     \
-    }     \
-}
-
 
 extern SK_MBUF		*SkDrvAllocRlmtMbuf(SK_AC*, SK_IOC, unsigned);
 extern void		SkDrvFreeRlmtMbuf(SK_AC*, SK_IOC, SK_MBUF*);
diff --git a/drivers/net/sk98lin/skaddr.c b/drivers/net/sk98lin/skaddr.c
index 5a7ce8ef8..abf857603 100644
--- a/drivers/net/sk98lin/skaddr.c
+++ b/drivers/net/sk98lin/skaddr.c
@@ -892,7 +892,7 @@ SK_AC	*pAC,		/* adapter context */
 SK_IOC	IoC,		/* I/O context */
 SK_U32	PortNumber)	/* Port Number */
 {
-	int ReturnCode;
+	int ReturnCode = 0;
 #if (!defined(SK_SLIM) || defined(DEBUG))
 	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
 		return (SK_ADDR_ILLEGAL_PORT);
@@ -1424,7 +1424,7 @@ SK_IOC	IoC,			/* I/O context */
 SK_U32	PortNumber,		/* port whose promiscuous mode changes */
 int		NewPromMode)	/* new promiscuous mode */
 {
-	int ReturnCode;
+	int ReturnCode = 0;
 #if (!defined(SK_SLIM) || defined(DEBUG))
 	if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
 		return (SK_ADDR_ILLEGAL_PORT);
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index 503fdff54..6cb5342a4 100644
--- a/drivers/net/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
@@ -110,10 +110,7 @@
 
 #include	<linux/module.h>
 #include	<linux/init.h>
-
-#ifdef CONFIG_PROC_FS
 #include 	<linux/proc_fs.h>
-#endif
 
 #include	"h/skdrv1st.h"
 #include	"h/skdrv2nd.h"
@@ -239,7 +236,7 @@ static int      SkDrvDeInitAdapter(SK_AC *pAC, int devNbr);
 
 #ifdef CONFIG_PROC_FS
 static const char 	SK_Root_Dir_entry[] = "sk98lin";
-static struct		proc_dir_entry *pSkRootDir = NULL;
+static struct		proc_dir_entry *pSkRootDir;
 extern struct	file_operations sk_proc_fops;
 #endif
 
@@ -255,303 +252,13 @@ static void	DumpLong(char*, int);
 #endif
 
 /* global variables *********************************************************/
-static const char *BootString = BOOT_STRING;
 struct SK_NET_DEVICE *SkGeRootDev = NULL;
-static int probed __initdata = 0;
 static SK_BOOL DoPrintInterfaceChange = SK_TRUE;
 
 /* local variables **********************************************************/
 static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}};
 static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480};
 
-
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry	*pSkRootDir;
-#endif
-
-
-
-/*****************************************************************************
- *
- * 	skge_probe - find all SK-98xx adapters
- *
- * Description:
- *	This function scans the PCI bus for SK-98xx adapters. Resources for
- *	each adapter are allocated and the adapter is brought into Init 1
- *	state.
- *
- * Returns:
- *	0, if everything is ok
- *	!=0, on error
- */
-static int __init skge_probe (void)
-{
-	int			boards_found = 0;
-	int			vendor_flag = SK_FALSE;
-	SK_AC			*pAC;
-	DEV_NET			*pNet = NULL;
-	struct pci_dev	*pdev = NULL;
-	struct SK_NET_DEVICE *dev = NULL;
-	SK_BOOL DeviceFound = SK_FALSE;
-	SK_BOOL BootStringCount = SK_FALSE;
-	int			retval;
-#ifdef CONFIG_PROC_FS
-	struct proc_dir_entry	*pProcFile;
-#endif
-
-	if (probed)
-		return -ENODEV;
-	probed++;
-
-
-	while((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev))) {
-
-                if (pci_enable_device(pdev)) {
-                        continue;
-                }
-		dev = NULL;
-		pNet = NULL;
-
-		/* Don't handle Yukon2 cards at the moment */
-		/* 12-feb-2004 ---- mlindner@syskonnect.de */
-		if (pdev->vendor == 0x11ab) {
-			if ( (pdev->device == 0x4360) || (pdev->device == 0x4361) )
-				continue;
-		}
-
-		SK_PCI_ISCOMPLIANT(vendor_flag, pdev);
-		if (!vendor_flag)
-			continue;
-
-		/* Configure DMA attributes. */
-		if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL) &&
-			pci_set_dma_mask(pdev, (u64) 0xffffffff))
-			continue;
-
-
-		if ((dev = alloc_etherdev(sizeof(DEV_NET))) == NULL) {
-			printk(KERN_ERR "Unable to allocate etherdev "
-			       "structure!\n");
-			break;
-		}
-
-		pNet = dev->priv;
-		pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL);
-		if (pNet->pAC == NULL){
-			free_netdev(dev);
-			printk(KERN_ERR "Unable to allocate adapter "
-			       "structure!\n");
-			break;
-		}
-
-		/* Print message */
-		if (!BootStringCount) {
-			/* set display flag to TRUE so that */
-			/* we only display this string ONCE */
-			BootStringCount = SK_TRUE;
-			printk("%s\n", BootString);
-		}
-
-		memset(pNet->pAC, 0, sizeof(SK_AC));
-		pAC = pNet->pAC;
-		pAC->PciDev = pdev;
-		pAC->PciDevId = pdev->device;
-		pAC->dev[0] = dev;
-		pAC->dev[1] = dev;
-		sprintf(pAC->Name, "SysKonnect SK-98xx");
-		pAC->CheckQueue = SK_FALSE;
-
-		pNet->Mtu = 1500;
-		pNet->Up = 0;
-		dev->irq = pdev->irq;
-		retval = SkGeInitPCI(pAC);
-		if (retval) {
-			printk("SKGE: PCI setup failed: %i\n", retval);
-			free_netdev(dev);
-			continue;
-		}
-
-		SET_MODULE_OWNER(dev);
-		dev->open =		&SkGeOpen;
-		dev->stop =		&SkGeClose;
-		dev->hard_start_xmit =	&SkGeXmit;
-		dev->get_stats =	&SkGeStats;
-		dev->last_stats =	&SkGeStats;
-		dev->set_multicast_list = &SkGeSetRxMode;
-		dev->set_mac_address =	&SkGeSetMacAddr;
-		dev->do_ioctl =		&SkGeIoctl;
-		dev->change_mtu =	&SkGeChangeMtu;
-		dev->flags &= 		~IFF_RUNNING;
-		SET_NETDEV_DEV(dev, &pdev->dev);
-
-#ifdef SK_ZEROCOPY
-#ifdef USE_SK_TX_CHECKSUM
-
-		if (pAC->ChipsetType) {
-			/* Use only if yukon hardware */
-			/* SK and ZEROCOPY - fly baby... */
-			dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
-		}
-#endif
-#endif
-
-		pAC->Index = boards_found;
-
-		if (SkGeBoardInit(dev, pAC)) {
-			free_netdev(dev);
-			continue;
-		}
-
-		/* Register net device */
-		if (register_netdev(dev)) {
-			printk(KERN_ERR "SKGE: Could not register device.\n");
-			FreeResources(dev);
-			free_netdev(dev);
-			continue;
-		}
-
-		/* Print adapter specific string from vpd */
-		ProductStr(pAC);
-		printk("%s: %s\n", dev->name, pAC->DeviceStr);
-
-		/* Print configuration settings */
-		printk("      PrefPort:%c  RlmtMode:%s\n",
-			'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber,
-			(pAC->RlmtMode==0)  ? "Check Link State" :
-			((pAC->RlmtMode==1) ? "Check Link State" :
-			((pAC->RlmtMode==3) ? "Check Local Port" :
-			((pAC->RlmtMode==7) ? "Check Segmentation" :
-			((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error")))));
-
-		SkGeYellowLED(pAC, pAC->IoBase, 1);
-
-
-		memcpy((caddr_t) &dev->dev_addr,
-			(caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6);
-
-		/* First adapter... Create proc and print message */
-#ifdef CONFIG_PROC_FS
-		if (!DeviceFound) {
-			DeviceFound = SK_TRUE;
-			SK_MEMCPY(&SK_Root_Dir_entry, BootString,
-				sizeof(SK_Root_Dir_entry) - 1);
-
-			/*Create proc (directory)*/
-			if(!pSkRootDir) {
-				pSkRootDir = proc_mkdir(SK_Root_Dir_entry, proc_net);
-				if (!pSkRootDir) {
-					printk(KERN_WARNING "%s: Unable to create /proc/net/%s",
-						dev->name, SK_Root_Dir_entry);
-				} else {
-					pSkRootDir->owner = THIS_MODULE;
-				}
-			}
-		}
-
-		/* Create proc file */
-		if (pSkRootDir && 
-			(pProcFile = create_proc_entry(dev->name, S_IRUGO,
-				pSkRootDir))) {
-			pProcFile->proc_fops = &sk_proc_fops;
-			pProcFile->data      = dev;
-		}
-
-#endif
-
-		pNet->PortNr = 0;
-		pNet->NetNr  = 0;
-
-		boards_found++;
-
-		/* More then one port found */
-		if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
-			if ((dev = alloc_etherdev(sizeof(DEV_NET))) == 0) {
-				printk(KERN_ERR "Unable to allocate etherdev "
-					"structure!\n");
-				break;
-			}
-
-			pAC->dev[1]   = dev;
-			pNet          = dev->priv;
-			pNet->PortNr  = 1;
-			pNet->NetNr   = 1;
-			pNet->pAC     = pAC;
-			pNet->Mtu     = 1500;
-			pNet->Up      = 0;
-
-			dev->open               = &SkGeOpen;
-			dev->stop               = &SkGeClose;
-			dev->hard_start_xmit    = &SkGeXmit;
-			dev->get_stats          = &SkGeStats;
-			dev->last_stats         = &SkGeStats;
-			dev->set_multicast_list = &SkGeSetRxMode;
-			dev->set_mac_address    = &SkGeSetMacAddr;
-			dev->do_ioctl           = &SkGeIoctl;
-			dev->change_mtu         = &SkGeChangeMtu;
-			dev->flags             &= ~IFF_RUNNING;
-
-#ifdef SK_ZEROCOPY
-#ifdef USE_SK_TX_CHECKSUM
-			if (pAC->ChipsetType) {
-				/* SG and ZEROCOPY - fly baby... */
-				dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
-			}
-#endif
-#endif
-
-			if (register_netdev(dev)) {
-				printk(KERN_ERR "SKGE: Could not register device.\n");
-				free_netdev(dev);
-				pAC->dev[1] = pAC->dev[0];
-			} else {
-#ifdef CONFIG_PROC_FS
-				if (pSkRootDir 
-				    && (pProcFile = create_proc_entry(dev->name, 
-								S_IRUGO, pSkRootDir))) {
-					pProcFile->proc_fops = &sk_proc_fops;
-					pProcFile->data      = dev;
-				}
-#endif
-
-			memcpy((caddr_t) &dev->dev_addr,
-			(caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6);
-	
-			printk("%s: %s\n", dev->name, pAC->DeviceStr);
-			printk("      PrefPort:B  RlmtMode:Dual Check Link State\n");
-			}
-		}
-
-		/* Save the hardware revision */
-		pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) +
-			(pAC->GIni.GIPciHwRev & 0x0F);
-
-		/* Set driver globals */
-		pAC->Pnmi.pDriverFileName    = DRIVER_FILE_NAME;
-		pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE;
-
-		SK_MEMSET(&(pAC->PnmiBackup), 0, sizeof(SK_PNMI_STRUCT_DATA));
-		SK_MEMCPY(&(pAC->PnmiBackup), &(pAC->PnmiStruct), 
-				sizeof(SK_PNMI_STRUCT_DATA));
-
-		/*
-		 * This is bollocks, but we need to tell the net-init
-		 * code that it shall go for the next device.
-		 */
-#ifndef MODULE
-		dev->base_addr = 0;
-#endif
-	}
-
-	/*
-	 * If we're at this point we're going through skge_probe() for
-	 * the first time.  Return success (0) if we've initialized 1
-	 * or more boards. Otherwise, return failure (-ENODEV).
-	 */
-
-	return boards_found;
-} /* skge_probe */
-
-
 /*****************************************************************************
  *
  * 	SkGeInitPCI - Init the PCI resources
@@ -666,9 +373,6 @@ MODULE_PARM(Role_B,	"1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
 MODULE_PARM(ConType,	"1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
 MODULE_PARM(PrefPort,   "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
 MODULE_PARM(RlmtMode,   "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
-/* not used, just there because every driver should have them: */
-MODULE_PARM(options,    "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i");
-MODULE_PARM(debug,      "i");
 /* used for interrupt moderation */
 MODULE_PARM(IntsPerSec,     "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i");
 MODULE_PARM(Moderation,     "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
@@ -755,123 +459,12 @@ static char *RlmtMode[SK_MAX_CARD_PARAM] = RLMT_MODE;
 static char *RlmtMode[SK_MAX_CARD_PARAM] = {"", };
 #endif
 
-static int debug = 0; /* not used */
-static int options[SK_MAX_CARD_PARAM] = {0, }; /* not used */
-
 static int   IntsPerSec[SK_MAX_CARD_PARAM];
 static char *Moderation[SK_MAX_CARD_PARAM];
 static char *ModerationMask[SK_MAX_CARD_PARAM];
 static char *AutoSizing[SK_MAX_CARD_PARAM];
 static char *Stats[SK_MAX_CARD_PARAM];
 
-
-/*****************************************************************************
- *
- * 	skge_init_module - module initialization function
- *
- * Description:
- *	Very simple, only call skge_probe and return approriate result.
- *
- * Returns:
- *	0, if everything is ok
- *	!=0, on error
- */
-static int __init skge_init_module(void)
-{
-	int cards;
-	SkGeRootDev = NULL;
-	
-	/* just to avoid warnings ... */
-	debug = 0;
-	options[0] = 0;
-
-	cards = skge_probe();
-	if (cards == 0) {
-		printk("sk98lin: No adapter found.\n");
-	}
-	return cards ? 0 : -ENODEV;
-} /* skge_init_module */
-
-
-/*****************************************************************************
- *
- * 	skge_cleanup_module - module unload function
- *
- * Description:
- *	Disable adapter if it is still running, free resources,
- *	free device struct.
- *
- * Returns: N/A
- */
-static void __exit skge_cleanup_module(void)
-{
-DEV_NET		*pNet;
-SK_AC		*pAC;
-struct SK_NET_DEVICE *next;
-unsigned long Flags;
-SK_EVPARA EvPara;
-
-	while (SkGeRootDev) {
-		pNet = (DEV_NET*) SkGeRootDev->priv;
-		pAC = pNet->pAC;
-		next = pAC->Next;
-
-		netif_stop_queue(SkGeRootDev);
-		SkGeYellowLED(pAC, pAC->IoBase, 0);
-
-		if(pAC->BoardLevel == SK_INIT_RUN) {
-			/* board is still alive */
-			spin_lock_irqsave(&pAC->SlowPathLock, Flags);
-			EvPara.Para32[0] = 0;
-			EvPara.Para32[1] = -1;
-			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-			EvPara.Para32[0] = 1;
-			EvPara.Para32[1] = -1;
-			SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
-			SkEventDispatcher(pAC, pAC->IoBase);
-			/* disable interrupts */
-			SK_OUT32(pAC->IoBase, B0_IMSK, 0);
-			SkGeDeInit(pAC, pAC->IoBase);
-			spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
-			pAC->BoardLevel = SK_INIT_DATA;
-			/* We do NOT check here, if IRQ was pending, of course*/
-		}
-
-		if(pAC->BoardLevel == SK_INIT_IO) {
-			/* board is still alive */
-			SkGeDeInit(pAC, pAC->IoBase);
-			pAC->BoardLevel = SK_INIT_DATA;
-		}
-
-		if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2){
-			unregister_netdev(pAC->dev[1]);
-			free_netdev(pAC->dev[1]);
-		}
-
-		FreeResources(SkGeRootDev);
-
-		SkGeRootDev->get_stats = NULL;
-		/*
-		 * otherwise unregister_netdev calls get_stats with
-		 * invalid IO ...  :-(
-		 */
-		unregister_netdev(SkGeRootDev);
-		free_netdev(SkGeRootDev);
-		kfree(pAC);
-		SkGeRootDev = next;
-	}
-
-#ifdef CONFIG_PROC_FS
-	/* clear proc-dir */
-	remove_proc_entry(pSkRootDir->name, proc_net);
-#endif
-
-} /* skge_cleanup_module */
-
-module_init(skge_init_module);
-module_exit(skge_cleanup_module);
-
-
 /*****************************************************************************
  *
  * 	SkGeBoardInit - do level 0 and 1 initialization
@@ -3094,8 +2687,7 @@ SK_EVPARA 	EvPara;
 	SkEventDispatcher(pAC, pAC->IoBase);
 
 	for (i=0; i<pAC->GIni.GIMacsFound; i++) {
-		spin_lock_irqsave(
-			&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock, Flags);
+		spin_lock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock);
 		netif_stop_queue(pAC->dev[i]);
 
 	}
@@ -4774,12 +4366,10 @@ SK_BOOL		DualNet;
 		spin_lock_irqsave(
 			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
 			Flags);
-		spin_lock_irqsave(
-			&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
+		spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
 		SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST);
 		SkGeStopPort(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST);
-		spin_unlock_irqrestore(
-			&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
+		spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
 		spin_unlock_irqrestore(
 			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
 			Flags);
@@ -4792,8 +4382,7 @@ SK_BOOL		DualNet;
 		spin_lock_irqsave(
 			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
 			Flags);
-		spin_lock_irqsave(
-			&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
+		spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
 		pAC->ActivePort = ToPort;
 #if 0
 		SetQueueSizes(pAC);
@@ -4808,8 +4397,7 @@ SK_BOOL		DualNet;
 			pAC,
 			pAC->ActivePort,
 			DualNet)) {
-			spin_unlock_irqrestore(
-				&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
+			spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
 			spin_unlock_irqrestore(
 				&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
 				Flags);
@@ -4835,8 +4423,7 @@ SK_BOOL		DualNet;
 		SkGePollTxD(pAC, IoC, ToPort, SK_TRUE);
 		ClearAndStartRx(pAC, FromPort);
 		ClearAndStartRx(pAC, ToPort);
-		spin_unlock_irqrestore(
-			&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
+		spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
 		spin_unlock_irqrestore(
 			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
 			Flags);
@@ -5311,8 +4898,317 @@ int	l;
 
 #endif
 
-/*******************************************************************************
- *
- * End of file
- *
- ******************************************************************************/
+static int __devinit skge_probe_one(struct pci_dev *pdev,
+		const struct pci_device_id *ent)
+{
+	SK_AC			*pAC;
+	DEV_NET			*pNet = NULL;
+	struct net_device	*dev = NULL;
+#ifdef CONFIG_PROC_FS
+	struct proc_dir_entry	*pProcFile;
+#endif
+	static int boards_found = 0;
+	int error = -ENODEV;
+
+	if (pci_enable_device(pdev))
+		goto out;
+ 
+	/* Configure DMA attributes. */
+	if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL) &&
+	    pci_set_dma_mask(pdev, (u64) 0xffffffff))
+		goto out_disable_device;
+
+
+	if ((dev = alloc_etherdev(sizeof(DEV_NET))) == NULL) {
+		printk(KERN_ERR "Unable to allocate etherdev "
+		       "structure!\n");
+		goto out_disable_device;
+	}
+
+	pNet = dev->priv;
+	pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL);
+	if (!pNet->pAC) {
+		printk(KERN_ERR "Unable to allocate adapter "
+		       "structure!\n");
+		goto out_free_netdev;
+	}
+
+	memset(pNet->pAC, 0, sizeof(SK_AC));
+	pAC = pNet->pAC;
+	pAC->PciDev = pdev;
+	pAC->PciDevId = pdev->device;
+	pAC->dev[0] = dev;
+	pAC->dev[1] = dev;
+	sprintf(pAC->Name, "SysKonnect SK-98xx");
+	pAC->CheckQueue = SK_FALSE;
+
+	pNet->Mtu = 1500;
+	pNet->Up = 0;
+	dev->irq = pdev->irq;
+	error = SkGeInitPCI(pAC);
+	if (error) {
+		printk("SKGE: PCI setup failed: %i\n", error);
+		goto out_free_netdev;
+	}
+
+	SET_MODULE_OWNER(dev);
+	dev->open =		&SkGeOpen;
+	dev->stop =		&SkGeClose;
+	dev->hard_start_xmit =	&SkGeXmit;
+	dev->get_stats =	&SkGeStats;
+	dev->set_multicast_list = &SkGeSetRxMode;
+	dev->set_mac_address =	&SkGeSetMacAddr;
+	dev->do_ioctl =		&SkGeIoctl;
+	dev->change_mtu =	&SkGeChangeMtu;
+	dev->flags &= 		~IFF_RUNNING;
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+#ifdef SK_ZEROCOPY
+#ifdef USE_SK_TX_CHECKSUM
+	if (pAC->ChipsetType) {
+		/* Use only if yukon hardware */
+		/* SK and ZEROCOPY - fly baby... */
+		dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+	}
+#endif
+#endif
+
+	pAC->Index = boards_found++;
+
+	if (SkGeBoardInit(dev, pAC))
+		goto out_free_netdev;
+
+	/* Register net device */
+	if (register_netdev(dev)) {
+		printk(KERN_ERR "SKGE: Could not register device.\n");
+		goto out_free_resources;
+	}
+
+	/* Print adapter specific string from vpd */
+	ProductStr(pAC);
+	printk("%s: %s\n", dev->name, pAC->DeviceStr);
+
+	/* Print configuration settings */
+	printk("      PrefPort:%c  RlmtMode:%s\n",
+		'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber,
+		(pAC->RlmtMode==0)  ? "Check Link State" :
+		((pAC->RlmtMode==1) ? "Check Link State" :
+		((pAC->RlmtMode==3) ? "Check Local Port" :
+		((pAC->RlmtMode==7) ? "Check Segmentation" :
+		((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error")))));
+
+	SkGeYellowLED(pAC, pAC->IoBase, 1);
+
+
+	memcpy(&dev->dev_addr, &pAC->Addr.Net[0].CurrentMacAddress, 6);
+
+#ifdef CONFIG_PROC_FS
+	pProcFile = create_proc_entry(dev->name, S_IRUGO, pSkRootDir);
+	if (pProcFile) {
+		pProcFile->proc_fops = &sk_proc_fops;
+		pProcFile->data = dev;
+		pProcFile->owner = THIS_MODULE;
+	}
+#endif
+
+	pNet->PortNr = 0;
+	pNet->NetNr  = 0;
+
+	boards_found++;
+
+	/* More then one port found */
+	if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+		if ((dev = alloc_etherdev(sizeof(DEV_NET))) == 0) {
+			printk(KERN_ERR "Unable to allocate etherdev "
+				"structure!\n");
+			goto out;
+		}
+
+		pAC->dev[1]   = dev;
+		pNet          = dev->priv;
+		pNet->PortNr  = 1;
+		pNet->NetNr   = 1;
+		pNet->pAC     = pAC;
+		pNet->Mtu     = 1500;
+		pNet->Up      = 0;
+
+		dev->open               = &SkGeOpen;
+		dev->stop               = &SkGeClose;
+		dev->hard_start_xmit    = &SkGeXmit;
+		dev->get_stats          = &SkGeStats;
+		dev->set_multicast_list = &SkGeSetRxMode;
+		dev->set_mac_address    = &SkGeSetMacAddr;
+		dev->do_ioctl           = &SkGeIoctl;
+		dev->change_mtu         = &SkGeChangeMtu;
+		dev->flags             &= ~IFF_RUNNING;
+
+#ifdef SK_ZEROCOPY
+#ifdef USE_SK_TX_CHECKSUM
+		if (pAC->ChipsetType) {
+			/* SG and ZEROCOPY - fly baby... */
+			dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+		}
+#endif
+#endif
+
+		if (register_netdev(dev)) {
+			printk(KERN_ERR "SKGE: Could not register device.\n");
+			free_netdev(dev);
+			pAC->dev[1] = pAC->dev[0];
+		} else {
+#ifdef CONFIG_PROC_FS
+			pProcFile = create_proc_entry(dev->name, S_IRUGO,
+					pSkRootDir);
+			if (pProcFile) {
+				pProcFile->proc_fops = &sk_proc_fops;
+				pProcFile->data = dev;
+				pProcFile->owner = THIS_MODULE;
+			}
+#endif
+
+			memcpy(&dev->dev_addr,
+					&pAC->Addr.Net[1].CurrentMacAddress, 6);
+	
+			printk("%s: %s\n", dev->name, pAC->DeviceStr);
+			printk("      PrefPort:B  RlmtMode:Dual Check Link State\n");
+		}
+	}
+
+	/* Save the hardware revision */
+	pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) +
+		(pAC->GIni.GIPciHwRev & 0x0F);
+
+	/* Set driver globals */
+	pAC->Pnmi.pDriverFileName    = DRIVER_FILE_NAME;
+	pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE;
+
+	memset(&pAC->PnmiBackup, 0, sizeof(SK_PNMI_STRUCT_DATA));
+	memcpy(&pAC->PnmiBackup, &pAC->PnmiStruct, sizeof(SK_PNMI_STRUCT_DATA));
+
+	pci_set_drvdata(pdev, dev);
+	return 0;
+
+ out_free_resources:
+	FreeResources(dev);
+ out_free_netdev:
+	free_netdev(dev);
+ out_disable_device:
+	pci_disable_device(pdev);
+ out:
+	return error;
+}
+
+static void __devexit skge_remove_one(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	DEV_NET *pNet = (DEV_NET *) dev->priv;
+	SK_AC *pAC = pNet->pAC;
+	int have_second_mac = 0;
+
+	if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2)
+		have_second_mac = 1;
+
+	remove_proc_entry(dev->name, pSkRootDir);
+	unregister_netdev(dev);
+	if (have_second_mac) {
+		remove_proc_entry(pAC->dev[1]->name, pSkRootDir);
+		unregister_netdev(pAC->dev[1]);
+	}
+
+	SkGeYellowLED(pAC, pAC->IoBase, 0);
+
+	if (pAC->BoardLevel == SK_INIT_RUN) {
+		SK_EVPARA EvPara;
+		unsigned long Flags;
+
+		/* board is still alive */
+		spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+		EvPara.Para32[0] = 0;
+		EvPara.Para32[1] = -1;
+		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+		EvPara.Para32[0] = 1;
+		EvPara.Para32[1] = -1;
+		SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+		SkEventDispatcher(pAC, pAC->IoBase);
+		/* disable interrupts */
+		SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+		SkGeDeInit(pAC, pAC->IoBase);
+		spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+		pAC->BoardLevel = SK_INIT_DATA;
+		/* We do NOT check here, if IRQ was pending, of course*/
+	}
+
+	if (pAC->BoardLevel == SK_INIT_IO) {
+		/* board is still alive */
+		SkGeDeInit(pAC, pAC->IoBase);
+		pAC->BoardLevel = SK_INIT_DATA;
+	}
+
+	FreeResources(dev);
+	free_netdev(dev);
+	if (have_second_mac)
+		free_netdev(pAC->dev[1]);
+	kfree(pAC);
+}
+
+static struct pci_device_id skge_pci_tbl[] = {
+	{ PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+#if 0	/* don't handle Yukon2 cards at the moment -- mlindner@syskonnect.de */
+	{ PCI_VENDOR_ID_MARVELL, 0x4360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_MARVELL, 0x4361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+#endif
+	{ PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ 0, }
+};
+
+static struct pci_driver skge_driver = {
+	.name		= "skge",
+	.id_table	= skge_pci_tbl,
+	.probe		= skge_probe_one,
+	.remove		= __devexit_p(skge_remove_one),
+};
+
+static int __init skge_init(void)
+{
+	int error;
+
+#ifdef CONFIG_PROC_FS
+	memcpy(&SK_Root_Dir_entry, BOOT_STRING, sizeof(SK_Root_Dir_entry) - 1);
+
+	pSkRootDir = proc_mkdir(SK_Root_Dir_entry, proc_net);
+	if (!pSkRootDir) {
+		printk(KERN_WARNING "Unable to create /proc/net/%s",
+				SK_Root_Dir_entry);
+		return -ENOMEM;
+	}
+	pSkRootDir->owner = THIS_MODULE;
+#endif
+
+	error = pci_module_init(&skge_driver);
+	if (error) {
+#ifdef CONFIG_PROC_FS
+		remove_proc_entry(pSkRootDir->name, proc_net);
+#endif
+	}
+
+	return error;
+}
+
+static void __exit skge_exit(void)
+{
+	 pci_unregister_driver(&skge_driver);
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry(pSkRootDir->name, proc_net);
+#endif
+}
+
+module_init(skge_init);
+module_exit(skge_exit);
diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
index 1eee9d37f..8308bcc14 100644
--- a/drivers/net/skfp/skfddi.c
+++ b/drivers/net/skfp/skfddi.c
@@ -1095,7 +1095,7 @@ static int skfp_send_pkt(struct sk_buff *skb, struct net_device *dev)
 	 */
 
 	if (!(skb->len >= FDDI_K_LLC_ZLEN && skb->len <= FDDI_K_LLC_LEN)) {
-		bp->MacStat.tx_errors++;	/* bump error counter */
+		bp->MacStat.gen.tx_errors++;	/* bump error counter */
 		// dequeue packets from xmt queue and send them
 		netif_start_queue(dev);
 		dev_kfree_skb(skb);
@@ -1546,8 +1546,8 @@ void mac_drv_tx_complete(struct s_smc *smc, volatile struct s_smt_fp_txd *txd)
 			 skb->len, PCI_DMA_TODEVICE);
 	txd->txd_os.dma_addr = 0;
 
-	smc->os.MacStat.tx_packets++;	// Count transmitted packets.
-	smc->os.MacStat.tx_bytes+=skb->len;	// Count bytes
+	smc->os.MacStat.gen.tx_packets++;	// Count transmitted packets.
+	smc->os.MacStat.gen.tx_bytes+=skb->len;	// Count bytes
 
 	// free the skb
 	dev_kfree_skb_irq(skb);
@@ -1629,7 +1629,7 @@ void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
 	skb = rxd->rxd_os.skb;
 	if (!skb) {
 		PRINTK(KERN_INFO "No skb in rxd\n");
-		smc->os.MacStat.rx_errors++;
+		smc->os.MacStat.gen.rx_errors++;
 		goto RequeueRxd;
 	}
 	virt = skb->data;
@@ -1682,13 +1682,14 @@ void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
 	}
 
 	// Count statistics.
-	smc->os.MacStat.rx_packets++;	// Count indicated receive packets.
-	smc->os.MacStat.rx_bytes+=len;	// Count bytes
+	smc->os.MacStat.gen.rx_packets++;	// Count indicated receive
+						// packets.
+	smc->os.MacStat.gen.rx_bytes+=len;	// Count bytes.
 
 	// virt points to header again
 	if (virt[1] & 0x01) {	// Check group (multicast) bit.
 
-		smc->os.MacStat.multicast++;
+		smc->os.MacStat.gen.multicast++;
 	}
 
 	// deliver frame to system
@@ -1706,7 +1707,8 @@ void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
       RequeueRxd:
 	PRINTK(KERN_INFO "Rx: re-queue RXD.\n");
 	mac_drv_requeue_rxd(smc, rxd, frag_count);
-	smc->os.MacStat.rx_errors++;	// Count receive packets not indicated.
+	smc->os.MacStat.gen.rx_errors++;	// Count receive packets
+						// not indicated.
 
 }				// mac_drv_rx_complete
 
@@ -2081,7 +2083,7 @@ void smt_stat_counter(struct s_smc *smc, int stat)
 		break;
 	case 1:
 		PRINTK(KERN_INFO "Receive fifo overflow.\n");
-		smc->os.MacStat.rx_errors++;
+		smc->os.MacStat.gen.rx_errors++;
 		break;
 	default:
 		PRINTK(KERN_INFO "Unknown status (%d).\n", stat);
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 6209a35aa..0c1995bc2 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -672,7 +672,9 @@ static int slip_receive_room(struct tty_struct *tty)
  * Handle the 'receiver data ready' interrupt.
  * This function is called by the 'tty_io' module in the kernel when
  * a block of SLIP data has been received, which can now be decapsulated
- * and sent on to some IP layer for further processing.
+ * and sent on to some IP layer for further processing. This will not
+ * be re-entered while running but other ldisc functions may be called
+ * in parallel
  */
  
 static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
@@ -841,9 +843,11 @@ sl_alloc(dev_t line)
  * SLIP line discipline is called for.  Because we are
  * sure the tty line exists, we only have to link it to
  * a free SLIP channel...
+ *
+ * Called in process context serialized from other ldisc calls.
  */
-static int
-slip_open(struct tty_struct *tty)
+
+static int slip_open(struct tty_struct *tty)
 {
 	struct slip *sl;
 	int err;
@@ -876,11 +880,11 @@ slip_open(struct tty_struct *tty)
 	tty->disc_data = sl;
 	sl->line = tty_devnum(tty);
 	sl->pid = current->pid;
+	
+	/* FIXME: already done before we were called - seems this can go */
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
-
+		
 	if (!test_bit(SLF_INUSE, &sl->flags)) {
 		/* Perform the low-level SLIP initialization. */
 		if ((err = sl_alloc_bufs(sl, SL_MTU)) != 0)
@@ -923,6 +927,9 @@ err_exit:
 }
 
 /*
+
+  FIXME: 1,2 are fixed 3 was never true anyway.
+  
    Let me to blame a bit.
    1. TTY module calls this funstion on soft interrupt.
    2. TTY module calls this function WITH MASKED INTERRUPTS!
@@ -941,9 +948,8 @@ err_exit:
 
 /*
  * Close down a SLIP channel.
- * This means flushing out any pending queues, and then restoring the
- * TTY line discipline to what it was before it got hooked to SLIP
- * (which usually is TTY again).
+ * This means flushing out any pending queues, and then returning. This
+ * call is serialized against other ldisc functions.
  */
 static void
 slip_close(struct tty_struct *tty)
diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c
index 8ee249a38..f5071b047 100644
--- a/drivers/net/smc9194.c
+++ b/drivers/net/smc9194.c
@@ -1191,133 +1191,6 @@ static void smc_timeout(struct net_device *dev)
 	netif_wake_queue(dev);
 }
 
-/*--------------------------------------------------------------------
- .
- . This is the main routine of the driver, to handle the device when
- . it needs some attention.
- .
- . So:
- .   first, save state of the chipset
- .   branch off into routines to handle each case, and acknowledge
- .	    each to the interrupt register
- .   and finally restore state.
- .
- ---------------------------------------------------------------------*/
-
-static irqreturn_t smc_interrupt(int irq, void * dev_id,  struct pt_regs * regs)
-{
-	struct net_device *dev 	= dev_id;
-	int ioaddr 		= dev->base_addr;
-	struct smc_local *lp = netdev_priv(dev);
-
-	byte	status;
-	word	card_stats;
-	byte	mask;
-	int	timeout;
-	/* state registers */
-	word	saved_bank;
-	word	saved_pointer;
-	int handled = 0;
-
-
-	PRINTK3((CARDNAME": SMC interrupt started \n"));
-
-	saved_bank = inw( ioaddr + BANK_SELECT );
-
-	SMC_SELECT_BANK(2);
-	saved_pointer = inw( ioaddr + POINTER );
-
-	mask = inb( ioaddr + INT_MASK );
-	/* clear all interrupts */
-	outb( 0, ioaddr + INT_MASK );
-
-
-	/* set a timeout value, so I don't stay here forever */
-	timeout = 4;
-
-	PRINTK2((KERN_WARNING CARDNAME ": MASK IS %x \n", mask ));
-	do {
-		/* read the status flag, and mask it */
-		status = inb( ioaddr + INTERRUPT ) & mask;
-		if (!status )
-			break;
-
-		handled = 1;
-
-		PRINTK3((KERN_WARNING CARDNAME
-			": Handling interrupt status %x \n", status ));
-
-		if (status & IM_RCV_INT) {
-			/* Got a packet(s). */
-			PRINTK2((KERN_WARNING CARDNAME
-				": Receive Interrupt\n"));
-			smc_rcv(dev);
-		} else if (status & IM_TX_INT ) {
-			PRINTK2((KERN_WARNING CARDNAME
-				": TX ERROR handled\n"));
-			smc_tx(dev);
-			outb(IM_TX_INT, ioaddr + INTERRUPT );
-		} else if (status & IM_TX_EMPTY_INT ) {
-			/* update stats */
-			SMC_SELECT_BANK( 0 );
-			card_stats = inw( ioaddr + COUNTER );
-			/* single collisions */
-			lp->stats.collisions += card_stats & 0xF;
-			card_stats >>= 4;
-			/* multiple collisions */
-			lp->stats.collisions += card_stats & 0xF;
-
-			/* these are for when linux supports these statistics */
-
-			SMC_SELECT_BANK( 2 );
-			PRINTK2((KERN_WARNING CARDNAME
-				": TX_BUFFER_EMPTY handled\n"));
-			outb( IM_TX_EMPTY_INT, ioaddr + INTERRUPT );
-			mask &= ~IM_TX_EMPTY_INT;
-			lp->stats.tx_packets += lp->packets_waiting;
-			lp->packets_waiting = 0;
-
-		} else if (status & IM_ALLOC_INT ) {
-			PRINTK2((KERN_DEBUG CARDNAME
-				": Allocation interrupt \n"));
-			/* clear this interrupt so it doesn't happen again */
-			mask &= ~IM_ALLOC_INT;
-
-			smc_hardware_send_packet( dev );
-
-			/* enable xmit interrupts based on this */
-			mask |= ( IM_TX_EMPTY_INT | IM_TX_INT );
-
-			/* and let the card send more packets to me */
-			netif_wake_queue(dev);
-			
-			PRINTK2((CARDNAME": Handoff done successfully.\n"));
-		} else if (status & IM_RX_OVRN_INT ) {
-			lp->stats.rx_errors++;
-			lp->stats.rx_fifo_errors++;
-			outb( IM_RX_OVRN_INT, ioaddr + INTERRUPT );
-		} else if (status & IM_EPH_INT ) {
-			PRINTK((CARDNAME ": UNSUPPORTED: EPH INTERRUPT \n"));
-		} else if (status & IM_ERCV_INT ) {
-			PRINTK((CARDNAME ": UNSUPPORTED: ERCV INTERRUPT \n"));
-			outb( IM_ERCV_INT, ioaddr + INTERRUPT );
-		}
-	} while ( timeout -- );
-
-
-	/* restore state register */
-	SMC_SELECT_BANK( 2 );
-	outb( mask, ioaddr + INT_MASK );
-
-	PRINTK3(( KERN_WARNING CARDNAME ": MASK is now %x \n", mask ));
-	outw( saved_pointer, ioaddr + POINTER );
-
-	SMC_SELECT_BANK( saved_bank );
-
-	PRINTK3((CARDNAME ": Interrupt done\n"));
-	return IRQ_RETVAL(handled);
-}
-
 /*-------------------------------------------------------------
  .
  . smc_rcv -  receive a packet from the card
@@ -1509,6 +1382,134 @@ static void smc_tx( struct net_device * dev )
 	return;
 }
 
+/*--------------------------------------------------------------------
+ .
+ . This is the main routine of the driver, to handle the device when
+ . it needs some attention.
+ .
+ . So:
+ .   first, save state of the chipset
+ .   branch off into routines to handle each case, and acknowledge
+ .	    each to the interrupt register
+ .   and finally restore state.
+ .
+ ---------------------------------------------------------------------*/
+
+static irqreturn_t smc_interrupt(int irq, void * dev_id,  struct pt_regs * regs)
+{
+	struct net_device *dev 	= dev_id;
+	int ioaddr 		= dev->base_addr;
+	struct smc_local *lp = netdev_priv(dev);
+
+	byte	status;
+	word	card_stats;
+	byte	mask;
+	int	timeout;
+	/* state registers */
+	word	saved_bank;
+	word	saved_pointer;
+	int handled = 0;
+
+
+	PRINTK3((CARDNAME": SMC interrupt started \n"));
+
+	saved_bank = inw( ioaddr + BANK_SELECT );
+
+	SMC_SELECT_BANK(2);
+	saved_pointer = inw( ioaddr + POINTER );
+
+	mask = inb( ioaddr + INT_MASK );
+	/* clear all interrupts */
+	outb( 0, ioaddr + INT_MASK );
+
+
+	/* set a timeout value, so I don't stay here forever */
+	timeout = 4;
+
+	PRINTK2((KERN_WARNING CARDNAME ": MASK IS %x \n", mask ));
+	do {
+		/* read the status flag, and mask it */
+		status = inb( ioaddr + INTERRUPT ) & mask;
+		if (!status )
+			break;
+
+		handled = 1;
+
+		PRINTK3((KERN_WARNING CARDNAME
+			": Handling interrupt status %x \n", status ));
+
+		if (status & IM_RCV_INT) {
+			/* Got a packet(s). */
+			PRINTK2((KERN_WARNING CARDNAME
+				": Receive Interrupt\n"));
+			smc_rcv(dev);
+		} else if (status & IM_TX_INT ) {
+			PRINTK2((KERN_WARNING CARDNAME
+				": TX ERROR handled\n"));
+			smc_tx(dev);
+			outb(IM_TX_INT, ioaddr + INTERRUPT );
+		} else if (status & IM_TX_EMPTY_INT ) {
+			/* update stats */
+			SMC_SELECT_BANK( 0 );
+			card_stats = inw( ioaddr + COUNTER );
+			/* single collisions */
+			lp->stats.collisions += card_stats & 0xF;
+			card_stats >>= 4;
+			/* multiple collisions */
+			lp->stats.collisions += card_stats & 0xF;
+
+			/* these are for when linux supports these statistics */
+
+			SMC_SELECT_BANK( 2 );
+			PRINTK2((KERN_WARNING CARDNAME
+				": TX_BUFFER_EMPTY handled\n"));
+			outb( IM_TX_EMPTY_INT, ioaddr + INTERRUPT );
+			mask &= ~IM_TX_EMPTY_INT;
+			lp->stats.tx_packets += lp->packets_waiting;
+			lp->packets_waiting = 0;
+
+		} else if (status & IM_ALLOC_INT ) {
+			PRINTK2((KERN_DEBUG CARDNAME
+				": Allocation interrupt \n"));
+			/* clear this interrupt so it doesn't happen again */
+			mask &= ~IM_ALLOC_INT;
+
+			smc_hardware_send_packet( dev );
+
+			/* enable xmit interrupts based on this */
+			mask |= ( IM_TX_EMPTY_INT | IM_TX_INT );
+
+			/* and let the card send more packets to me */
+			netif_wake_queue(dev);
+
+			PRINTK2((CARDNAME": Handoff done successfully.\n"));
+		} else if (status & IM_RX_OVRN_INT ) {
+			lp->stats.rx_errors++;
+			lp->stats.rx_fifo_errors++;
+			outb( IM_RX_OVRN_INT, ioaddr + INTERRUPT );
+		} else if (status & IM_EPH_INT ) {
+			PRINTK((CARDNAME ": UNSUPPORTED: EPH INTERRUPT \n"));
+		} else if (status & IM_ERCV_INT ) {
+			PRINTK((CARDNAME ": UNSUPPORTED: ERCV INTERRUPT \n"));
+			outb( IM_ERCV_INT, ioaddr + INTERRUPT );
+		}
+	} while ( timeout -- );
+
+
+	/* restore state register */
+	SMC_SELECT_BANK( 2 );
+	outb( mask, ioaddr + INT_MASK );
+
+	PRINTK3(( KERN_WARNING CARDNAME ": MASK is now %x \n", mask ));
+	outw( saved_pointer, ioaddr + POINTER );
+
+	SMC_SELECT_BANK( saved_bank );
+
+	PRINTK3((CARDNAME ": Interrupt done\n"));
+	return IRQ_RETVAL(handled);
+}
+
+
 /*----------------------------------------------------
  . smc_close
  .
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 85fae0965..5d224b642 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -55,6 +55,9 @@
  *                                  smc_phy_configure
  *                                - clean up (and fix stack overrun) in PHY
  *                                  MII read/write functions
+ *   09/15/04  Hayato Fujiwara    - Add m32r support.
+ *                                - Modify for SMP kernel; Change spin-locked
+ *                                  regions.
  */
 static const char version[] =
 	"smc91x.c: v1.0, mar 07 2003 by Nicolas Pitre <nico@cam.org>\n";
@@ -256,24 +259,18 @@ static void PRINT_PKT(u_char *buf, int length)
 
 /* this enables an interrupt in the interrupt mask register */
 #define SMC_ENABLE_INT(x) do {						\
-	unsigned long flags;						\
 	unsigned char mask;						\
-	spin_lock_irqsave(&lp->lock, flags);				\
 	mask = SMC_GET_INT_MASK();					\
 	mask |= (x);							\
 	SMC_SET_INT_MASK(mask);						\
-	spin_unlock_irqrestore(&lp->lock, flags);			\
 } while (0)
 
 /* this disables an interrupt from the interrupt mask register */
 #define SMC_DISABLE_INT(x) do {						\
-	unsigned long flags;						\
 	unsigned char mask;						\
-	spin_lock_irqsave(&lp->lock, flags);				\
 	mask = SMC_GET_INT_MASK();					\
 	mask &= ~(x);							\
 	SMC_SET_INT_MASK(mask);						\
-	spin_unlock_irqrestore(&lp->lock, flags);			\
 } while (0)
 
 /*
@@ -580,9 +577,12 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct smc_local *lp = netdev_priv(dev);
 	unsigned long ioaddr = dev->base_addr;
 	unsigned int numPages, poll_count, status, saved_bank;
+	unsigned long flags;
 
 	DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
 
+	spin_lock_irqsave(&lp->lock, flags);
+
 	BUG_ON(lp->saved_skb != NULL);
 	lp->saved_skb = skb;
 
@@ -604,6 +604,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		lp->stats.tx_errors++;
 		lp->stats.tx_dropped++;
 		dev_kfree_skb(skb);
+		spin_unlock_irqrestore(&lp->lock, flags);
 		return 0;
 	}
 
@@ -652,6 +653,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	}
 
 	SMC_SELECT_BANK(saved_bank);
+	spin_unlock_irqrestore(&lp->lock, flags);
 	return 0;
 }
 
@@ -1166,6 +1168,8 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
 	DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
 
+	spin_lock(&lp->lock);
+
 	saved_bank = SMC_CURRENT_BANK();
 	SMC_SELECT_BANK(2);
 	saved_pointer = SMC_GET_PTR();
@@ -1189,8 +1193,6 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 		if (!status)
 			break;
 
-		spin_lock(&lp->lock);
-
 		if (status & IM_RCV_INT) {
 			DBG(3, "%s: RX irq\n", dev->name);
 			smc_rcv(dev);
@@ -1239,7 +1241,6 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 			PRINTK("%s: UNSUPPORTED: ERCV INTERRUPT \n", dev->name);
 		}
 
-		spin_unlock(&lp->lock);
 	} while (--timeout);
 
 	/* restore register states */
@@ -1249,6 +1250,7 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
 	DBG(3, "%s: Interrupt done (%d loops)\n", dev->name, 8-timeout);
 
+	spin_unlock(&lp->lock);
 	/*
 	 * We return IRQ_HANDLED unconditionally here even if there was
 	 * nothing to do.  There is a possibility that a packet might
@@ -1264,7 +1266,9 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 static void smc_timeout(struct net_device *dev)
 {
 	struct smc_local *lp = netdev_priv(dev);
+	unsigned long flags;
 
+	spin_lock_irqsave(&lp->lock, flags);
 	DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
 
 	smc_reset(dev);
@@ -1298,6 +1302,9 @@ static void smc_timeout(struct net_device *dev)
 	}
 	/* We can accept TX packets again */
 	dev->trans_start = jiffies;
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
 	netif_wake_queue(dev);
 }
 
@@ -1438,7 +1445,7 @@ smc_open(struct net_device *dev)
 	 * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
 	 */
 	if (!is_valid_ether_addr(dev->dev_addr)) {
-		DBG(2, (KERN_DEBUG "smc_open: no valid ethernet hw addr\n"));
+		DBG(2, "smc_open: no valid ethernet hw addr\n");
 		return -EINVAL;
 	}
 
@@ -1878,7 +1885,9 @@ static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
       	if (retval)
       		goto err_out;
 
+#if !defined(__m32r__)
 	set_irq_type(dev->irq, IRQT_RISING);
+#endif
 #ifdef SMC_USE_PXA_DMA
 	{
 		int dma = pxa_request_dma(dev->name, DMA_PRIO_LOW,
@@ -2154,10 +2163,12 @@ static struct device_driver smc_driver = {
 static int __init smc_init(void)
 {
 #ifdef MODULE
+#ifdef CONFIG_ISA
 	if (io == -1)
 		printk(KERN_WARNING 
 			"%s: You shouldn't use auto-probing with insmod!\n",
 			CARDNAME);
+#endif
 #endif
 
 	return driver_register(&smc_driver);
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index 7679022c0..cf74b74c3 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -160,6 +160,19 @@ SMC_outw(u16 val, unsigned long ioaddr, int reg)
 #define SMC_insw(a, r, p, l)	insw((a) + (r), p, l)
 #define SMC_outsw(a, r, p, l)	outsw((a) + (r), p, l)
 
+#elif   defined(CONFIG_M32R)
+
+#define SMC_CAN_USE_8BIT	0
+#define SMC_CAN_USE_16BIT	1
+#define SMC_CAN_USE_32BIT	0
+
+#define SMC_inb(a, r)		inb((a) + (r) - 0xa0000000)
+#define SMC_inw(a, r)		inw((a) + (r) - 0xa0000000)
+#define SMC_outb(v, a, r)	outb(v, (a) + (r) - 0xa0000000)
+#define SMC_outw(v, a, r)	outw(v, (a) + (r) - 0xa0000000)
+#define SMC_insw(a, r, p, l)	insw((a) + (r) - 0xa0000000, p, l)
+#define SMC_outsw(a, r, p, l)	outsw((a) + (r) - 0xa0000000, p, l)
+
 #else
 
 #define SMC_CAN_USE_8BIT	1
@@ -809,9 +822,10 @@ static const char * chip_ids[ 16 ] =  {
 	do {								\
 		char *__ptr = (p);					\
 		int __len = (l);					\
-		if (__len >= 2 && (long)__ptr & 2) {			\
+		if (__len >= 2 && (unsigned long)__ptr & 2) {		\
 			__len -= 2;					\
-			SMC_outw( *((u16 *)__ptr)++, ioaddr, DATA_REG );\
+			SMC_outw( *(u16 *)__ptr, ioaddr, DATA_REG );	\
+			__ptr += 2;					\
 		}							\
 		SMC_outsl( ioaddr, DATA_REG, __ptr, __len >> 2);	\
 		if (__len & 2) {					\
@@ -823,7 +837,7 @@ static const char * chip_ids[ 16 ] =  {
 	do {								\
 		char *__ptr = (p);					\
 		int __len = (l);					\
-		if ((long)__ptr & 2) {					\
+		if ((unsigned long)__ptr & 2) {				\
 			/*						\
 			 * We want 32bit alignment here.		\
 			 * Since some buses perform a full 32bit	\
@@ -831,7 +845,7 @@ static const char * chip_ids[ 16 ] =  {
 			 * SMC_inw() here.  Back both source (on chip	\
 			 * and destination) pointers of 2 bytes.	\
 			 */						\
-			(long)__ptr &= ~2;				\
+			__ptr -= 2;					\
 			__len += 2;					\
 			SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC );	\
 		}							\
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index ec05d1bd1..25d35022b 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -68,7 +68,7 @@ static struct bigmac *root_bigmac_dev;
 
 #define QEC_RESET_TRIES 200
 
-static int qec_global_reset(unsigned long gregs)
+static int qec_global_reset(void __iomem *gregs)
 {
 	int tries = QEC_RESET_TRIES;
 
@@ -88,7 +88,7 @@ static int qec_global_reset(unsigned long gregs)
 
 static void qec_init(struct bigmac *bp)
 {
-	unsigned long gregs = bp->gregs;
+	void __iomem *gregs = bp->gregs;
 	struct sbus_dev *qec_sdev = bp->qec_sdev;
 	u8 bsizes = bp->bigmac_bursts;
 	u32 regval;
@@ -117,7 +117,7 @@ static void qec_init(struct bigmac *bp)
 #define TX_RESET_TRIES     32
 #define RX_RESET_TRIES     32
 
-static void bigmac_tx_reset(unsigned long bregs)
+static void bigmac_tx_reset(void __iomem *bregs)
 {
 	int tries = TX_RESET_TRIES;
 
@@ -137,7 +137,7 @@ static void bigmac_tx_reset(unsigned long bregs)
 	}
 }
 
-static void bigmac_rx_reset(unsigned long bregs)
+static void bigmac_rx_reset(void __iomem *bregs)
 {
 	int tries = RX_RESET_TRIES;
 
@@ -159,7 +159,7 @@ static void bigmac_stop(struct bigmac *bp)
 	bigmac_rx_reset(bp->bregs);
 }
 
-static void bigmac_get_counters(struct bigmac *bp, unsigned long bregs)
+static void bigmac_get_counters(struct bigmac *bp, void __iomem *bregs)
 {
 	struct net_device_stats *stats = &bp->enet_stats;
 
@@ -244,7 +244,7 @@ static void bigmac_init_rings(struct bigmac *bp, int from_irq)
 #define MGMT_CLKON  (MGMT_PAL_INT_MDIO|MGMT_PAL_EXT_MDIO|MGMT_PAL_OENAB|MGMT_PAL_DCLOCK)
 #define MGMT_CLKOFF (MGMT_PAL_INT_MDIO|MGMT_PAL_EXT_MDIO|MGMT_PAL_OENAB)
 
-static void idle_transceiver(unsigned long tregs)
+static void idle_transceiver(void __iomem *tregs)
 {
 	int i = 20;
 
@@ -256,7 +256,7 @@ static void idle_transceiver(unsigned long tregs)
 	}
 }
 
-static void write_tcvr_bit(struct bigmac *bp, unsigned long tregs, int bit)
+static void write_tcvr_bit(struct bigmac *bp, void __iomem *tregs, int bit)
 {
 	if (bp->tcvr_type == internal) {
 		bit = (bit & 1) << 3;
@@ -279,7 +279,7 @@ static void write_tcvr_bit(struct bigmac *bp, unsigned long tregs, int bit)
 	}
 }
 
-static int read_tcvr_bit(struct bigmac *bp, unsigned long tregs)
+static int read_tcvr_bit(struct bigmac *bp, void __iomem *tregs)
 {
 	int retval = 0;
 
@@ -302,7 +302,7 @@ static int read_tcvr_bit(struct bigmac *bp, unsigned long tregs)
 	return retval;
 }
 
-static int read_tcvr_bit2(struct bigmac *bp, unsigned long tregs)
+static int read_tcvr_bit2(struct bigmac *bp, void __iomem *tregs)
 {
 	int retval = 0;
 
@@ -325,7 +325,7 @@ static int read_tcvr_bit2(struct bigmac *bp, unsigned long tregs)
 }
 
 static void put_tcvr_byte(struct bigmac *bp,
-			  unsigned long tregs,
+			  void __iomem *tregs,
 			  unsigned int byte)
 {
 	int shift = 4;
@@ -336,7 +336,7 @@ static void put_tcvr_byte(struct bigmac *bp,
 	} while (shift >= 0);
 }
 
-static void bigmac_tcvr_write(struct bigmac *bp, unsigned long tregs,
+static void bigmac_tcvr_write(struct bigmac *bp, void __iomem *tregs,
 			      int reg, unsigned short val)
 {
 	int shift;
@@ -376,7 +376,7 @@ static void bigmac_tcvr_write(struct bigmac *bp, unsigned long tregs,
 }
 
 static unsigned short bigmac_tcvr_read(struct bigmac *bp,
-				       unsigned long tregs,
+				       void __iomem *tregs,
 				       int reg)
 {
 	unsigned short retval = 0;
@@ -444,7 +444,7 @@ static unsigned short bigmac_tcvr_read(struct bigmac *bp,
 
 static void bigmac_tcvr_init(struct bigmac *bp)
 {
-	unsigned long tregs = bp->tregs;
+	void __iomem *tregs = bp->tregs;
 	u32 mpal;
 
 	idle_transceiver(tregs);
@@ -482,7 +482,7 @@ static void bigmac_tcvr_init(struct bigmac *bp)
 
 static int bigmac_init(struct bigmac *, int);
 
-static int try_next_permutation(struct bigmac *bp, unsigned long tregs)
+static int try_next_permutation(struct bigmac *bp, void __iomem *tregs)
 {
 	if (bp->sw_bmcr & BMCR_SPEED100) {
 		int timeout;
@@ -518,7 +518,7 @@ static int try_next_permutation(struct bigmac *bp, unsigned long tregs)
 static void bigmac_timer(unsigned long data)
 {
 	struct bigmac *bp = (struct bigmac *) data;
-	unsigned long tregs = bp->tregs;
+	void __iomem *tregs = bp->tregs;
 	int restart_timer = 0;
 
 	bp->timer_ticks++;
@@ -573,7 +573,7 @@ static void bigmac_timer(unsigned long data)
  */
 static void bigmac_begin_auto_negotiation(struct bigmac *bp)
 {
-	unsigned long tregs = bp->tregs;
+	void __iomem *tregs = bp->tregs;
 	int timeout;
 
 	/* Grab new software copies of PHY registers. */
@@ -612,9 +612,9 @@ static void bigmac_begin_auto_negotiation(struct bigmac *bp)
 
 static int bigmac_init(struct bigmac *bp, int from_irq)
 {
-	unsigned long gregs        = bp->gregs;
-	unsigned long cregs        = bp->creg;
-	unsigned long bregs        = bp->bregs;
+	void __iomem *gregs        = bp->gregs;
+	void __iomem *cregs        = bp->creg;
+	void __iomem *bregs        = bp->bregs;
 	unsigned char *e = &bp->dev->dev_addr[0];
 
 	/* Latch current counters into statistics. */
@@ -987,7 +987,7 @@ static struct net_device_stats *bigmac_get_stats(struct net_device *dev)
 static void bigmac_set_multicast(struct net_device *dev)
 {
 	struct bigmac *bp = (struct bigmac *) dev->priv;
-	unsigned long bregs = bp->bregs;
+	void __iomem *bregs = bp->bregs;
 	struct dev_mc_list *dmi = dev->mc_list;
 	char *addrs;
 	int i;
diff --git a/drivers/net/sunbmac.h b/drivers/net/sunbmac.h
index b4c5309b3..5674003fc 100644
--- a/drivers/net/sunbmac.h
+++ b/drivers/net/sunbmac.h
@@ -303,10 +303,10 @@ enum bigmac_timer_state {
 };
 
 struct bigmac {
-	unsigned long	gregs;	/* QEC Global Registers               */
-	unsigned long	creg;	/* QEC BigMAC Channel Registers       */
-	unsigned long	bregs;	/* BigMAC Registers                   */
-	unsigned long	tregs;	/* BigMAC Transceiver                 */
+	void __iomem	*gregs;	/* QEC Global Registers               */
+	void __iomem	*creg;	/* QEC BigMAC Channel Registers       */
+	void __iomem	*bregs;	/* BigMAC Registers                   */
+	void __iomem	*tregs;	/* BigMAC Transceiver                 */
 	struct bmac_init_block	*bmac_block;	/* RX and TX descriptors */
 	__u32			 bblock_dvma;	/* RX and TX descriptors */
 
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index 849b57634..e0ddf2be9 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -879,7 +879,7 @@ static int netdev_open(struct net_device *dev)
 	if (dev->if_port == 0)
 		dev->if_port = np->default_port;
 
-	np->mcastlock = (spinlock_t) SPIN_LOCK_UNLOCKED;
+	np->mcastlock = SPIN_LOCK_UNLOCKED;
 
 	set_rx_mode(dev);
 	writew(0, ioaddr + IntrEnable);
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index e48ec3421..c78811b00 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -5,6 +5,9 @@
  * 
  * Support for Apple GMAC and assorted PHYs by
  * Benjamin Herrenscmidt (benh@kernel.crashing.org)
+ *
+ * NAPI and NETPOLL support
+ * (C) 2004 by Eric Lemoine (eric.lemoine@gmail.com)
  * 
  * TODO: 
  *  - Get rid of all those nasty mdelay's and replace them
@@ -181,6 +184,18 @@ static inline void phy_write(struct gem *gp, int reg, u16 val)
 	__phy_write(gp, gp->mii_phy_addr, reg, val);
 }
 
+static inline void gem_enable_ints(struct gem *gp)
+{
+	/* Enable all interrupts but TXDONE */
+	writel(GREG_STAT_TXDONE, gp->regs + GREG_IMASK);
+}
+
+static inline void gem_disable_ints(struct gem *gp)
+{
+	/* Disable all interrupts, including TXDONE */
+	writel(GREG_STAT_NAPI | GREG_STAT_TXDONE, gp->regs + GREG_IMASK);
+}
+
 static void gem_handle_mif_event(struct gem *gp, u32 reg_val, u32 changed_bits)
 {
 	if (netif_msg_intr(gp))
@@ -678,12 +693,12 @@ static __inline__ void gem_post_rxds(struct gem *gp, int limit)
 	}
 }
 
-static void gem_rx(struct gem *gp)
+static int gem_rx(struct gem *gp, int work_to_do)
 {
-	int entry, drops;
+	int entry, drops, work_done = 0;
 	u32 done;
 
-	if (netif_msg_intr(gp))
+	if (netif_msg_rx_status(gp))
 		printk(KERN_DEBUG "%s: rx interrupt, done: %d, rx_new: %d\n",
 			gp->dev->name, readl(gp->regs + RXDMA_DONE), gp->rx_new);
 
@@ -700,6 +715,9 @@ static void gem_rx(struct gem *gp)
 		if ((status & RXDCTRL_OWN) != 0)
 			break;
 
+		if (work_done >= RX_RING_SIZE || work_done >= work_to_do)
+			break;
+
 		/* When writing back RX descriptor, GEM writes status
 		 * then buffer address, possibly in seperate transactions.
 		 * If we don't wait for the chip to write both, we could
@@ -713,6 +731,9 @@ static void gem_rx(struct gem *gp)
 				break;
 		}
 
+		/* We can now account for the work we're about to do */
+		work_done++;
+
 		skb = gp->rx_skbs[entry];
 
 		len = (status & RXDCTRL_BUFSZ) >> 16;
@@ -775,7 +796,8 @@ static void gem_rx(struct gem *gp)
 		skb->csum = ntohs((status & RXDCTRL_TCPCSUM) ^ 0xffff);
 		skb->ip_summed = CHECKSUM_HW;
 		skb->protocol = eth_type_trans(skb, gp->dev);
-		netif_rx(skb);
+
+		netif_receive_skb(skb);
 
 		gp->net_stats.rx_packets++;
 		gp->net_stats.rx_bytes += len;
@@ -792,35 +814,103 @@ static void gem_rx(struct gem *gp)
 	if (drops)
 		printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n",
 		       gp->dev->name);
+
+	return work_done;
+}
+
+static int gem_poll(struct net_device *dev, int *budget)
+{
+	struct gem *gp = dev->priv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gp->lock, flags);
+
+	do {
+		int work_to_do, work_done;
+
+		/* Handle anomalies */
+		if (gp->status & GREG_STAT_ABNORMAL) {
+			if (gem_abnormal_irq(dev, gp, gp->status))
+				break;
+		}
+
+		/* Run TX completion thread */
+		spin_lock(&gp->tx_lock);
+		gem_tx(dev, gp, gp->status);
+		spin_unlock(&gp->tx_lock);
+
+		spin_unlock_irqrestore(&gp->lock, flags);
+
+		/* Run RX thread. We don't use any locking here, 
+		 * code willing to do bad things - like cleaning the 
+		 * rx ring - must call netif_poll_disable(), which
+		 * schedule_timeout()'s if polling is already disabled.
+		 */
+		work_to_do = min(*budget, dev->quota);
+
+		work_done = gem_rx(gp, work_to_do);
+
+		*budget -= work_done;
+		dev->quota -= work_done;
+
+		if (work_done >= work_to_do)
+			return 1;
+
+		spin_lock_irqsave(&gp->lock, flags);
+		
+		gp->status = readl(gp->regs + GREG_STAT);
+	} while (gp->status & GREG_STAT_NAPI);
+
+	__netif_rx_complete(dev);
+	gem_enable_ints(gp);
+
+	spin_unlock_irqrestore(&gp->lock, flags);
+	return 0;
 }
 
 static irqreturn_t gem_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_id;
 	struct gem *gp = dev->priv;
-	u32 gem_status = readl(gp->regs + GREG_STAT);
+	unsigned long flags;
 
 	/* Swallow interrupts when shutting the chip down */
-	if (gp->hw_running == 0)
-		goto out;
+	if (!gp->hw_running)
+		return IRQ_HANDLED;
 
-	spin_lock(&gp->lock);
+	spin_lock_irqsave(&gp->lock, flags);
+	
+	if (netif_rx_schedule_prep(dev)) {
+		u32 gem_status = readl(gp->regs + GREG_STAT);
 
-	if (gem_status & GREG_STAT_ABNORMAL) {
-		if (gem_abnormal_irq(dev, gp, gem_status))
-			goto out;
+		if (gem_status == 0) {
+			spin_unlock_irqrestore(&gp->lock, flags);
+			return IRQ_NONE;
+		}
+		gp->status = gem_status;
+		gem_disable_ints(gp);
+		__netif_rx_schedule(dev);
 	}
-	if (gem_status & (GREG_STAT_TXALL | GREG_STAT_TXINTME))
-		gem_tx(dev, gp, gem_status);
-	if (gem_status & GREG_STAT_RXDONE)
-		gem_rx(gp);
-
-out:
-	spin_unlock(&gp->lock);
 
+	spin_unlock_irqrestore(&gp->lock, flags);
+  
+	/* If polling was disabled at the time we received that
+	 * interrupt, we may return IRQ_HANDLED here while we 
+	 * should return IRQ_NONE. No big deal...
+	 */
 	return IRQ_HANDLED;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void gem_poll_controller(struct net_device *dev)
+{
+	/* gem_interrupt is safe to reentrance so no need
+	 * to disable_irq here.
+	 */
+	gem_interrupt(dev->irq, dev, NULL);
+}
+#endif
+
 static void gem_tx_timeout(struct net_device *dev)
 {
 	struct gem *gp = dev->priv;
@@ -842,10 +932,12 @@ static void gem_tx_timeout(struct net_device *dev)
 	       readl(gp->regs + MAC_RXCFG));
 
 	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 
 	gp->reset_task_pending = 2;
 	schedule_work(&gp->reset_task);
 
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 }
 
@@ -863,6 +955,7 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct gem *gp = dev->priv;
 	int entry;
 	u64 ctrl;
+	unsigned long flags;
 
 	ctrl = 0;
 	if (skb->ip_summed == CHECKSUM_HW) {
@@ -876,15 +969,20 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev)
 			(csum_stuff_off << 21));
 	}
 
-	spin_lock_irq(&gp->lock);
+	local_irq_save(flags);
+	if (!spin_trylock(&gp->tx_lock)) {
+		/* Tell upper layer to requeue */
+		local_irq_restore(flags);
+		return NETDEV_TX_LOCKED;
+	}
 
 	/* This is a hard error, log it. */
 	if (TX_BUFFS_AVAIL(gp) <= (skb_shinfo(skb)->nr_frags + 1)) {
 		netif_stop_queue(dev);
-		spin_unlock_irq(&gp->lock);
+		spin_unlock_irqrestore(&gp->tx_lock, flags);
 		printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
 		       dev->name);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	entry = gp->tx_new;
@@ -968,11 +1066,11 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		       dev->name, entry, skb->len);
 	mb();
 	writel(gp->tx_new, gp->regs + TXDMA_KICK);
-	spin_unlock_irq(&gp->lock);
+	spin_unlock_irqrestore(&gp->tx_lock, flags);
 
 	dev->trans_start = jiffies;
 
-	return 0;
+	return NETDEV_TX_OK;
 }
 
 /* Jumbo-grams don't seem to work :-( */
@@ -999,9 +1097,11 @@ static int gem_change_mtu(struct net_device *dev, int new_mtu)
 	}
 
 	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 	dev->mtu = new_mtu;
 	gp->reset_task_pending = 1;
 	schedule_work(&gp->reset_task);
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 
 	flush_scheduled_work();
@@ -1011,7 +1111,7 @@ static int gem_change_mtu(struct net_device *dev, int new_mtu)
 
 #define STOP_TRIES 32
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_stop(struct gem *gp)
 {
 	int limit;
@@ -1037,7 +1137,7 @@ static void gem_stop(struct gem *gp)
 		printk(KERN_ERR "%s: SW reset is ghetto.\n", gp->dev->name);
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_start_dma(struct gem *gp)
 {
 	unsigned long val;
@@ -1062,7 +1162,7 @@ static void gem_start_dma(struct gem *gp)
 }
 
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 // XXX dbl check what that function should do when called on PCS PHY
 static void gem_begin_auto_negotiation(struct gem *gp, struct ethtool_cmd *ep)
 {
@@ -1149,7 +1249,7 @@ non_mii:
 /* A link-up condition has occurred, initialize and enable the
  * rest of the chip.
  *
- * Must be invoked under gp->lock.
+ * Must be invoked under gp->lock and gp->tx_lock.
  */
 static int gem_set_link_modes(struct gem *gp)
 {
@@ -1256,7 +1356,7 @@ static int gem_set_link_modes(struct gem *gp)
 	return 0;
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static int gem_mdio_link_not_up(struct gem *gp)
 {
 	switch (gp->lstate) {
@@ -1312,19 +1412,13 @@ static void gem_reset_task(void *data)
 {
 	struct gem *gp = (struct gem *) data;
 
-	/* The link went down, we reset the ring, but keep
-	 * DMA stopped. Todo: Use this function for reset
-	 * on error as well.
-	 */
-
+	netif_poll_disable(gp->dev);
 	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 
 	if (gp->hw_running && gp->opened) {
-		/* Make sure we don't get interrupts or tx packets */
 		netif_stop_queue(gp->dev);
 
-		writel(0xffffffff, gp->regs + GREG_IMASK);
-
 		/* Reset the chip & rings */
 		gem_stop(gp);
 		gem_init_rings(gp);
@@ -1336,7 +1430,9 @@ static void gem_reset_task(void *data)
 	}
 	gp->reset_task_pending = 0;
 
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
+	netif_poll_enable(gp->dev);
 }
 
 static void gem_link_timer(unsigned long data)
@@ -1348,6 +1444,7 @@ static void gem_link_timer(unsigned long data)
 		return;
 
 	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 
 	/* If the link of task is still pending, we just
 	 * reschedule the link timer
@@ -1417,10 +1514,11 @@ static void gem_link_timer(unsigned long data)
 restart:
 	mod_timer(&gp->link_timer, jiffies + ((12 * HZ) / 10));
 out_unlock:
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_clean_rings(struct gem *gp)
 {
 	struct gem_init_block *gb = gp->init_block;
@@ -1471,7 +1569,7 @@ static void gem_clean_rings(struct gem *gp)
 	}
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_init_rings(struct gem *gp)
 {
 	struct gem_init_block *gb = gp->init_block;
@@ -1521,7 +1619,7 @@ static void gem_init_rings(struct gem *gp)
 	wmb();
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_init_phy(struct gem *gp)
 {
 	u32 mifcfg;
@@ -1659,7 +1757,7 @@ static void gem_init_phy(struct gem *gp)
 	}
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_init_dma(struct gem *gp)
 {
 	u64 desc_dma = (u64) gp->gblock_dvma;
@@ -1697,7 +1795,7 @@ static void gem_init_dma(struct gem *gp)
 		       gp->regs + RXDMA_BLANK);
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static u32
 gem_setup_multicast(struct gem *gp)
 {
@@ -1740,7 +1838,7 @@ gem_setup_multicast(struct gem *gp)
 	return rxcfg;
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_init_mac(struct gem *gp)
 {
 	unsigned char *e = &gp->dev->dev_addr[0];
@@ -1818,7 +1916,7 @@ static void gem_init_mac(struct gem *gp)
 	writel(0xffffffff, gp->regs + MAC_MCMASK);
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_init_pause_thresholds(struct gem *gp)
 {
        	u32 cfg;
@@ -1954,7 +2052,7 @@ static int gem_check_invariants(struct gem *gp)
 	return 0;
 }
 
-/* Must be invoked under gp->lock. */
+/* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_init_hw(struct gem *gp, int restart_link)
 {
 	/* On Apple's gmac, I initialize the PHY only after
@@ -2052,9 +2150,11 @@ static void gem_stop_phy(struct gem *gp)
 
 	if (!gp->wake_on_lan) {
 		spin_lock_irqsave(&gp->lock, flags);
+		spin_lock(&gp->tx_lock);
 		gem_stop(gp);
 		writel(MAC_TXRST_CMD, gp->regs + MAC_TXRST);
 		writel(MAC_RXRST_CMD, gp->regs + MAC_RXRST);
+		spin_unlock(&gp->tx_lock);
 		spin_unlock_irqrestore(&gp->lock, flags);
 	}
 
@@ -2102,8 +2202,10 @@ static void gem_shutdown(struct gem *gp)
 		unsigned long flags;
 
 		spin_lock_irqsave(&gp->lock, flags);
+		spin_lock(&gp->tx_lock);
 		gem_stop(gp);
-		spin_unlock_irqrestore(&gp->lock, flags);	
+		spin_unlock(&gp->tx_lock);
+		spin_unlock_irqrestore(&gp->lock, flags);
 	}
 }
 
@@ -2163,7 +2265,9 @@ static int gem_open(struct net_device *dev)
 
 		/* Reset the chip */
 		spin_lock_irq(&gp->lock);
+		spin_lock(&gp->tx_lock);
 		gem_stop(gp);
+		spin_unlock(&gp->tx_lock);
 		spin_unlock_irq(&gp->lock);
 
 		gp->hw_running = 1;
@@ -2177,6 +2281,7 @@ static int gem_open(struct net_device *dev)
 		printk(KERN_ERR "%s: failed to request irq !\n", gp->dev->name);
 
 		spin_lock_irq(&gp->lock);
+		spin_lock(&gp->tx_lock);
 #ifdef CONFIG_PPC_PMAC
 		if (!hw_was_up && gp->pdev->vendor == PCI_VENDOR_ID_APPLE)
 			gem_apple_powerdown(gp);
@@ -2185,12 +2290,14 @@ static int gem_open(struct net_device *dev)
 		gp->pm_timer.expires = jiffies + 10*HZ;
 		add_timer(&gp->pm_timer);
 		up(&gp->pm_sem);
+		spin_unlock(&gp->tx_lock);
 		spin_unlock_irq(&gp->lock);
 
 		return -EAGAIN;
 	}
 
        	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 
 	/* Allocate & setup ring buffers */
 	gem_init_rings(gp);
@@ -2200,6 +2307,7 @@ static int gem_open(struct net_device *dev)
 
 	gp->opened = 1;
 
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 
 	up(&gp->pm_sem);
@@ -2214,11 +2322,16 @@ static int gem_close(struct net_device *dev)
 	/* Make sure we don't get distracted by suspend/resume */
 	down(&gp->pm_sem);
 
+	/* Note: we don't need to call netif_poll_disable() here because
+	 * our caller (dev_close) already did it for us
+	 */
+
 	/* Stop traffic, mark us closed */
 	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 
 	gp->opened = 0;	
-	writel(0xffffffff, gp->regs + GREG_IMASK);
+
 	netif_stop_queue(dev);
 
 	/* Stop chip */
@@ -2230,6 +2343,7 @@ static int gem_close(struct net_device *dev)
 	/* Bye, the pm timer will finish the job */
 	free_irq(gp->pdev->irq, (void *) dev);
 
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 
 	/* Fire the PM timer that will shut us down in about 10 seconds */
@@ -2247,6 +2361,8 @@ static int gem_suspend(struct pci_dev *pdev, u32 state)
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct gem *gp = dev->priv;
 
+	netif_poll_disable(dev);
+
 	/* We hold the PM semaphore during entire driver
 	 * sleep time
 	 */
@@ -2258,18 +2374,18 @@ static int gem_suspend(struct pci_dev *pdev, u32 state)
 	/* If the driver is opened, we stop the DMA */
 	if (gp->opened) {
 		spin_lock_irq(&gp->lock);
+		spin_lock(&gp->tx_lock);
 
 		/* Stop traffic, mark us closed */
 		netif_device_detach(dev);
 
-		writel(0xffffffff, gp->regs + GREG_IMASK);
-
 		/* Stop chip */
 		gem_stop(gp);
 
 		/* Get rid of ring buffers */
 		gem_clean_rings(gp);
 
+		spin_unlock(&gp->tx_lock);
 		spin_unlock_irq(&gp->lock);
 
 		if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE)
@@ -2303,12 +2419,14 @@ static int gem_resume(struct pci_dev *pdev)
 		}
 #endif /* CONFIG_PPC_PMAC */
 		spin_lock_irq(&gp->lock);
+		spin_lock(&gp->tx_lock);
 
 		gem_stop(gp);
 		gp->hw_running = 1;
 		gem_init_rings(gp);
 		gem_init_hw(gp, 1);
 
+		spin_unlock(&gp->tx_lock);
 		spin_unlock_irq(&gp->lock);
 
 		netif_device_attach(dev);
@@ -2317,6 +2435,8 @@ static int gem_resume(struct pci_dev *pdev)
 	}
 	up(&gp->pm_sem);
 
+	netif_poll_enable(dev);
+	
 	return 0;
 }
 #endif /* CONFIG_PM */
@@ -2327,6 +2447,7 @@ static struct net_device_stats *gem_get_stats(struct net_device *dev)
 	struct net_device_stats *stats = &gp->net_stats;
 
 	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 
 	if (gp->hw_running) {
 		stats->rx_crc_errors += readl(gp->regs + MAC_FCSERR);
@@ -2346,6 +2467,7 @@ static struct net_device_stats *gem_get_stats(struct net_device *dev)
 		writel(0, gp->regs + MAC_LCOLL);
 	}
 
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 
 	return &gp->net_stats;
@@ -2361,6 +2483,7 @@ static void gem_set_multicast(struct net_device *dev)
 		return;
 		
 	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 
 	netif_stop_queue(dev);
 
@@ -2385,6 +2508,7 @@ static void gem_set_multicast(struct net_device *dev)
 
 	netif_wake_queue(dev);
 
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 }
 
@@ -2416,6 +2540,7 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 
 		/* Return current PHY settings */
 		spin_lock_irq(&gp->lock);
+		spin_lock(&gp->tx_lock);
 		cmd->autoneg = gp->want_autoneg;
 		cmd->speed = gp->phy_mii.speed;
 		cmd->duplex = gp->phy_mii.duplex;			
@@ -2427,6 +2552,7 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 		 */
 		if (cmd->advertising == 0)
 			cmd->advertising = cmd->supported;
+		spin_unlock(&gp->tx_lock);
 		spin_unlock_irq(&gp->lock);
 	} else { // XXX PCS ?
 		cmd->supported =
@@ -2466,7 +2592,9 @@ static int gem_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 	      
 	/* Apply settings and restart link process. */
 	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 	gem_begin_auto_negotiation(gp, cmd);
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 
 	return 0;
@@ -2481,7 +2609,9 @@ static int gem_nway_reset(struct net_device *dev)
 
 	/* Restart link process. */
 	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 	gem_begin_auto_negotiation(gp, NULL);
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 
 	return 0;
@@ -2581,7 +2711,7 @@ static void find_eth_addr_in_vpd(void *rom_base, int len, unsigned char *dev_add
 static void get_gem_mac_nonobp(struct pci_dev *pdev, unsigned char *dev_addr)
 {
 	u32 rom_reg_orig;
-	void *p;
+	void __iomem *p;
 
 	if (pdev->resource[PCI_ROM_RESOURCE].parent == NULL) {
 		if (pci_assign_resource(pdev, PCI_ROM_RESOURCE) < 0)
@@ -2733,6 +2863,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
 	gp->msg_enable = DEFAULT_MSG;
 
 	spin_lock_init(&gp->lock);
+	spin_lock_init(&gp->tx_lock);
 	init_MUTEX(&gp->pm_sem);
 
 	init_timer(&gp->link_timer);
@@ -2750,7 +2881,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
 	gp->timer_ticks = 0;
 	netif_carrier_off(dev);
 
-	gp->regs = (unsigned long) ioremap(gemreg_base, gemreg_len);
+	gp->regs = ioremap(gemreg_base, gemreg_len);
 	if (gp->regs == 0UL) {
 		printk(KERN_ERR PFX "Cannot map device registers, "
 		       "aborting.\n");
@@ -2768,7 +2899,9 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
 		gem_apple_powerup(gp);
 #endif
 	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 	gem_stop(gp);
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 
 	/* Fill up the mii_phy structure (even if we won't use it) */
@@ -2806,12 +2939,17 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
 	dev->get_stats = gem_get_stats;
 	dev->set_multicast_list = gem_set_multicast;
 	dev->do_ioctl = gem_ioctl;
+	dev->poll = gem_poll;
+	dev->weight = 64;
 	dev->ethtool_ops = &gem_ethtool_ops;
 	dev->tx_timeout = gem_tx_timeout;
 	dev->watchdog_timeo = 5 * HZ;
 	dev->change_mtu = gem_change_mtu;
 	dev->irq = pdev->irq;
 	dev->dma = 0;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = gem_poll_controller;
+#endif
 
 	if (register_netdev(dev)) {
 		printk(KERN_ERR PFX "Cannot register net device, "
@@ -2829,9 +2967,11 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
 
 	/* Detect & init PHY, start autoneg */
 	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 	gp->hw_running = 1;
 	gem_init_phy(gp);
 	gem_begin_auto_negotiation(gp, NULL);
+	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 
 	if (gp->phy_type == phy_mii_mdio0 ||
@@ -2842,7 +2982,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
 	pci_set_drvdata(pdev, dev);
 
 	/* GEM can do it all... */
-	dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM;
+	dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_LLTX;
 	if (pci_using_dac)
 		dev->features |= NETIF_F_HIGHDMA;
 
@@ -2867,7 +3007,7 @@ err_out_iounmap:
 		gem_shutdown(gp);
 	up(&gp->pm_sem);
 
-	iounmap((void *) gp->regs);
+	iounmap(gp->regs);
 
 err_out_free_res:
 	pci_release_regions(pdev);
@@ -2901,7 +3041,7 @@ static void __devexit gem_remove_one(struct pci_dev *pdev)
 				    sizeof(struct gem_init_block),
 				    gp->init_block,
 				    gp->gblock_dvma);
-		iounmap((void *) gp->regs);
+		iounmap(gp->regs);
 		pci_release_regions(pdev);
 		free_netdev(dev);
 
diff --git a/drivers/net/sungem.h b/drivers/net/sungem.h
index eed77bfe1..00343226f 100644
--- a/drivers/net/sungem.h
+++ b/drivers/net/sungem.h
@@ -60,6 +60,9 @@
 				 GREG_STAT_PCS | GREG_STAT_TXMAC | GREG_STAT_RXMAC | \
 				 GREG_STAT_MAC | GREG_STAT_MIF | GREG_STAT_PCIERR)
 
+#define GREG_STAT_NAPI		(GREG_STAT_TXALL  | GREG_STAT_TXINTME | \
+				 GREG_STAT_RXDONE | GREG_STAT_ABNORMAL)
+
 /* The layout of GREG_IMASK and GREG_IACK is identical to GREG_STAT.
  * Bits set in GREG_IMASK will prevent that interrupt type from being
  * signalled to the cpu.  GREG_IACK can be used to clear specific top-level
@@ -950,7 +953,8 @@ enum link_state {
 
 struct gem {
 	spinlock_t lock;
-	unsigned long regs;
+	spinlock_t tx_lock;
+	void __iomem *regs;
 	int rx_new, rx_old;
 	int tx_new, tx_old;
 
@@ -969,6 +973,7 @@ struct gem {
 	struct sk_buff *tx_skbs[RX_RING_SIZE];
 
 	u32			msg_enable;
+	u32			status;
 
 	struct net_device_stats net_stats;
 
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 13fdcca49..2cb1ac95a 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -203,12 +203,12 @@ MODULE_DEVICE_TABLE(pci, happymeal_pci_ids);
  */
 
 #if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
-static void sbus_hme_write32(unsigned long reg, u32 val)
+static void sbus_hme_write32(void __iomem *reg, u32 val)
 {
 	sbus_writel(val, reg);
 }
 
-static u32 sbus_hme_read32(unsigned long reg)
+static u32 sbus_hme_read32(void __iomem *reg)
 {
 	return sbus_readl(reg);
 }
@@ -232,12 +232,12 @@ static u32 sbus_hme_read_desc32(u32 *p)
 	return *p;
 }
 
-static void pci_hme_write32(unsigned long reg, u32 val)
+static void pci_hme_write32(void __iomem *reg, u32 val)
 {
 	writel(val, reg);
 }
 
-static u32 pci_hme_read32(unsigned long reg)
+static u32 pci_hme_read32(void __iomem *reg)
 {
 	return readl(reg);
 }
@@ -354,7 +354,7 @@ do {	(__txd)->tx_addr = cpu_to_le32(__addr); \
 
 
 /* Oh yes, the MIF BitBang is mighty fun to program.  BitBucket is more like it. */
-static void BB_PUT_BIT(struct happy_meal *hp, unsigned long tregs, int bit)
+static void BB_PUT_BIT(struct happy_meal *hp, void __iomem *tregs, int bit)
 {
 	hme_write32(hp, tregs + TCVR_BBDATA, bit);
 	hme_write32(hp, tregs + TCVR_BBCLOCK, 0);
@@ -362,7 +362,7 @@ static void BB_PUT_BIT(struct happy_meal *hp, unsigned long tregs, int bit)
 }
 
 #if 0
-static u32 BB_GET_BIT(struct happy_meal *hp, unsigned long tregs, int internal)
+static u32 BB_GET_BIT(struct happy_meal *hp, void __iomem *tregs, int internal)
 {
 	u32 ret;
 
@@ -378,7 +378,7 @@ static u32 BB_GET_BIT(struct happy_meal *hp, unsigned long tregs, int internal)
 }
 #endif
 
-static u32 BB_GET_BIT2(struct happy_meal *hp, unsigned long tregs, int internal)
+static u32 BB_GET_BIT2(struct happy_meal *hp, void __iomem *tregs, int internal)
 {
 	u32 retval;
 
@@ -397,7 +397,7 @@ static u32 BB_GET_BIT2(struct happy_meal *hp, unsigned long tregs, int internal)
 #define TCVR_FAILURE      0x80000000     /* Impossible MIF read value */
 
 static int happy_meal_bb_read(struct happy_meal *hp,
-			      unsigned long tregs, int reg)
+			      void __iomem *tregs, int reg)
 {
 	u32 tmp;
 	int retval = 0;
@@ -443,7 +443,7 @@ static int happy_meal_bb_read(struct happy_meal *hp,
 }
 
 static void happy_meal_bb_write(struct happy_meal *hp,
-				unsigned long tregs, int reg,
+				void __iomem *tregs, int reg,
 				unsigned short value)
 {
 	u32 tmp;
@@ -488,7 +488,7 @@ static void happy_meal_bb_write(struct happy_meal *hp,
 #define TCVR_READ_TRIES   16
 
 static int happy_meal_tcvr_read(struct happy_meal *hp,
-				unsigned long tregs, int reg)
+				void __iomem *tregs, int reg)
 {
 	int tries = TCVR_READ_TRIES;
 	int retval;
@@ -520,7 +520,7 @@ static int happy_meal_tcvr_read(struct happy_meal *hp,
 #define TCVR_WRITE_TRIES  16
 
 static void happy_meal_tcvr_write(struct happy_meal *hp,
-				  unsigned long tregs, int reg,
+				  void __iomem *tregs, int reg,
 				  unsigned short value)
 {
 	int tries = TCVR_WRITE_TRIES;
@@ -579,7 +579,7 @@ static void happy_meal_tcvr_write(struct happy_meal *hp,
  * service routine, and the chip is reset, or the link is ifconfig'd down
  * and then back up, this entire process repeats itself all over again.
  */
-static int try_next_permutation(struct happy_meal *hp, unsigned long tregs)
+static int try_next_permutation(struct happy_meal *hp, void __iomem *tregs)
 {
 	hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, MII_BMCR);
 
@@ -603,7 +603,7 @@ static int try_next_permutation(struct happy_meal *hp, unsigned long tregs)
 	return -1;
 }
 
-static void display_link_mode(struct happy_meal *hp, unsigned long tregs)
+static void display_link_mode(struct happy_meal *hp, void __iomem *tregs)
 {
 	printk(KERN_INFO "%s: Link is up using ", hp->dev->name);
 	if (hp->tcvr_type == external)
@@ -625,7 +625,7 @@ static void display_link_mode(struct happy_meal *hp, unsigned long tregs)
 	}
 }
 
-static void display_forced_link_mode(struct happy_meal *hp, unsigned long tregs)
+static void display_forced_link_mode(struct happy_meal *hp, void __iomem *tregs)
 {
 	printk(KERN_INFO "%s: Link has been forced up using ", hp->dev->name);
 	if (hp->tcvr_type == external)
@@ -644,7 +644,7 @@ static void display_forced_link_mode(struct happy_meal *hp, unsigned long tregs)
 		printk("Half Duplex.\n");
 }
 
-static int set_happy_link_modes(struct happy_meal *hp, unsigned long tregs)
+static int set_happy_link_modes(struct happy_meal *hp, void __iomem *tregs)
 {
 	int full;
 
@@ -708,7 +708,7 @@ static int happy_meal_init(struct happy_meal *hp);
 
 static int is_lucent_phy(struct happy_meal *hp)
 {
-	unsigned long tregs = hp->tcvregs;
+	void __iomem *tregs = hp->tcvregs;
 	unsigned short mr2, mr3;
 	int ret = 0;
 
@@ -724,7 +724,7 @@ static int is_lucent_phy(struct happy_meal *hp)
 static void happy_meal_timer(unsigned long data)
 {
 	struct happy_meal *hp = (struct happy_meal *) data;
-	unsigned long tregs = hp->tcvregs;
+	void __iomem *tregs = hp->tcvregs;
 	int restart_timer = 0;
 
 	spin_lock_irq(&hp->happy_lock);
@@ -905,7 +905,7 @@ out:
 #define RX_RESET_TRIES     32
 
 /* hp->happy_lock must be held */
-static void happy_meal_tx_reset(struct happy_meal *hp, unsigned long bregs)
+static void happy_meal_tx_reset(struct happy_meal *hp, void __iomem *bregs)
 {
 	int tries = TX_RESET_TRIES;
 
@@ -925,7 +925,7 @@ static void happy_meal_tx_reset(struct happy_meal *hp, unsigned long bregs)
 }
 
 /* hp->happy_lock must be held */
-static void happy_meal_rx_reset(struct happy_meal *hp, unsigned long bregs)
+static void happy_meal_rx_reset(struct happy_meal *hp, void __iomem *bregs)
 {
 	int tries = RX_RESET_TRIES;
 
@@ -947,7 +947,7 @@ static void happy_meal_rx_reset(struct happy_meal *hp, unsigned long bregs)
 #define STOP_TRIES         16
 
 /* hp->happy_lock must be held */
-static void happy_meal_stop(struct happy_meal *hp, unsigned long gregs)
+static void happy_meal_stop(struct happy_meal *hp, void __iomem *gregs)
 {
 	int tries = STOP_TRIES;
 
@@ -967,7 +967,7 @@ static void happy_meal_stop(struct happy_meal *hp, unsigned long gregs)
 }
 
 /* hp->happy_lock must be held */
-static void happy_meal_get_counters(struct happy_meal *hp, unsigned long bregs)
+static void happy_meal_get_counters(struct happy_meal *hp, void __iomem *bregs)
 {
 	struct net_device_stats *stats = &hp->net_stats;
 
@@ -990,7 +990,7 @@ static void happy_meal_get_counters(struct happy_meal *hp, unsigned long bregs)
 }
 
 /* hp->happy_lock must be held */
-static void happy_meal_poll_stop(struct happy_meal *hp, unsigned long tregs)
+static void happy_meal_poll_stop(struct happy_meal *hp, void __iomem *tregs)
 {
 	ASD(("happy_meal_poll_stop: "));
 
@@ -1025,7 +1025,7 @@ static void happy_meal_poll_stop(struct happy_meal *hp, unsigned long tregs)
 #define TCVR_UNISOLATE_TRIES   32 /* Dis-isolation can take longer. */
 
 /* hp->happy_lock must be held */
-static int happy_meal_tcvr_reset(struct happy_meal *hp, unsigned long tregs)
+static int happy_meal_tcvr_reset(struct happy_meal *hp, void __iomem *tregs)
 {
 	u32 tconfig;
 	int result, tries = TCVR_RESET_TRIES;
@@ -1123,7 +1123,7 @@ static int happy_meal_tcvr_reset(struct happy_meal *hp, unsigned long tregs)
  *
  * hp->happy_lock must be held
  */
-static void happy_meal_transceiver_check(struct happy_meal *hp, unsigned long tregs)
+static void happy_meal_transceiver_check(struct happy_meal *hp, void __iomem *tregs)
 {
 	unsigned long tconfig = hme_read32(hp, tregs + TCVR_CFG);
 
@@ -1318,7 +1318,7 @@ static void happy_meal_init_rings(struct happy_meal *hp)
 
 /* hp->happy_lock must be held */
 static void happy_meal_begin_auto_negotiation(struct happy_meal *hp,
-					      unsigned long tregs,
+					      void __iomem *tregs,
 					      struct ethtool_cmd *ep)
 {
 	int timeout;
@@ -1443,11 +1443,11 @@ force_link:
 /* hp->happy_lock must be held */
 static int happy_meal_init(struct happy_meal *hp)
 {
-	unsigned long gregs        = hp->gregs;
-	unsigned long etxregs      = hp->etxregs;
-	unsigned long erxregs      = hp->erxregs;
-	unsigned long bregs        = hp->bigmacregs;
-	unsigned long tregs        = hp->tcvregs;
+	void __iomem *gregs        = hp->gregs;
+	void __iomem *etxregs      = hp->etxregs;
+	void __iomem *erxregs      = hp->erxregs;
+	void __iomem *bregs        = hp->bigmacregs;
+	void __iomem *tregs        = hp->tcvregs;
 	u32 regtmp, rxcfg;
 	unsigned char *e = &hp->dev->dev_addr[0];
 
@@ -1736,9 +1736,9 @@ static int happy_meal_init(struct happy_meal *hp)
 /* hp->happy_lock must be held */
 static void happy_meal_set_initial_advertisement(struct happy_meal *hp)
 {
-	unsigned long tregs	= hp->tcvregs;
-	unsigned long bregs	= hp->bigmacregs;
-	unsigned long gregs	= hp->gregs;
+	void __iomem *tregs	= hp->tcvregs;
+	void __iomem *bregs	= hp->bigmacregs;
+	void __iomem *gregs	= hp->gregs;
 
 	happy_meal_stop(hp, gregs);
 	hme_write32(hp, tregs + TCVR_IMASK, 0xffff);
@@ -1910,7 +1910,7 @@ static int happy_meal_is_not_so_happy(struct happy_meal *hp, u32 status)
 /* hp->happy_lock must be held */
 static void happy_meal_mif_interrupt(struct happy_meal *hp)
 {
-	unsigned long tregs = hp->tcvregs;
+	void __iomem *tregs = hp->tcvregs;
 
 	printk(KERN_INFO "%s: Link status change.\n", hp->dev->name);
 	hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, MII_BMCR);
@@ -2390,7 +2390,7 @@ static struct net_device_stats *happy_meal_get_stats(struct net_device *dev)
 static void happy_meal_set_multicast(struct net_device *dev)
 {
 	struct happy_meal *hp = dev->priv;
-	unsigned long bregs = hp->bigmacregs;
+	void __iomem *bregs = hp->bigmacregs;
 	struct dev_mc_list *dmi = dev->mc_list;
 	char *addrs;
 	int i;
@@ -3025,7 +3025,8 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev)
 #endif
 	struct happy_meal *hp;
 	struct net_device *dev;
-	unsigned long hpreg_base;
+	void __iomem *hpreg_base;
+	unsigned long hpreg_res;
 	int i, qfe_slot = -1;
 	char prom_name[64];
 	int err;
@@ -3084,7 +3085,7 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev)
 		qp->happy_meals[qfe_slot] = dev;
 	}		
 
-	hpreg_base = pci_resource_start(pdev, 0);
+	hpreg_res = pci_resource_start(pdev, 0);
 	err = -ENODEV;
 	if ((pci_resource_flags(pdev, 0) & IORESOURCE_IO) != 0) {
 		printk(KERN_ERR "happymeal(PCI): Cannot find proper PCI device base address.\n");
@@ -3096,7 +3097,7 @@ static int __init happy_meal_pci_init(struct pci_dev *pdev)
 		goto err_out_clear_quattro;
 	}
 
-	if ((hpreg_base = (unsigned long) ioremap(hpreg_base, 0x8000)) == 0) {
+	if ((hpreg_base = ioremap(hpreg_res, 0x8000)) == 0) {
 		printk(KERN_ERR "happymeal(PCI): Unable to remap card memory.\n");
 		goto err_out_free_res;
 	}
diff --git a/drivers/net/sunhme.h b/drivers/net/sunhme.h
index f2784d217..34e9f953c 100644
--- a/drivers/net/sunhme.h
+++ b/drivers/net/sunhme.h
@@ -397,7 +397,7 @@ struct quattro;
 
 /* Happy happy, joy joy! */
 struct happy_meal {
-	unsigned long	gregs;			/* Happy meal global registers       */
+	void __iomem	*gregs;			/* Happy meal global registers       */
 	struct hmeal_init_block  *happy_block;	/* RX and TX descriptors (CPU addr)  */
 
 #if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
@@ -423,14 +423,14 @@ struct happy_meal {
 	struct net_device_stats	  net_stats;      /* Statistical counters              */
 
 #if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
-	u32 (*read32)(unsigned long);
-	void (*write32)(unsigned long, u32);
+	u32 (*read32)(void __iomem *);
+	void (*write32)(void __iomem *, u32);
 #endif
 
-	unsigned long	etxregs;        /* External transmitter regs         */
-	unsigned long	erxregs;        /* External receiver regs            */
-	unsigned long	bigmacregs;     /* BIGMAC core regs		     */
-	unsigned long	tcvregs;        /* MIF transceiver regs              */
+	void __iomem	*etxregs;        /* External transmitter regs        */
+	void __iomem	*erxregs;        /* External receiver regs           */
+	void __iomem	*bigmacregs;     /* BIGMAC core regs		     */
+	void __iomem	*tcvregs;        /* MIF transceiver regs             */
 
 	dma_addr_t                hblock_dvma;    /* DVMA visible address happy block  */
 	unsigned int              happy_flags;    /* Driver state flags                */
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index e80311524..6e4bb5781 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -230,9 +230,9 @@ struct lance_init_block {
 ((__u32)(((unsigned long)(&(((struct lance_init_block *)0)->rt[elem][0])))))
 
 struct lance_private {
-	unsigned long	lregs;		/* Lance RAP/RDP regs.		*/
-	unsigned long	dregs;		/* DMA controller regs.		*/
-	volatile struct lance_init_block *init_block;
+	void __iomem	*lregs;		/* Lance RAP/RDP regs.		*/
+	void __iomem	*dregs;		/* DMA controller regs.		*/
+	struct lance_init_block *init_block;
     
 	spinlock_t	lock;
 
@@ -270,7 +270,7 @@ struct lance_private {
 #define LANCE_REG_SIZE	0x04UL
 
 #define STOP_LANCE(__lp) \
-do {	unsigned long __base = (__lp)->lregs; \
+do {	void __iomem *__base = (__lp)->lregs; \
 	sbus_writew(LE_CSR0,	__base + RAP); \
 	sbus_writew(LE_C0_STOP,	__base + RDP); \
 } while (0)
@@ -314,7 +314,7 @@ static void load_csrs(struct lance_private *lp)
 static void lance_init_ring_dvma(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
+	struct lance_init_block *ib = lp->init_block;
 	dma_addr_t aib = lp->init_block_dvma;
 	__u32 leptr;
 	int i;
@@ -371,7 +371,7 @@ static void lance_init_ring_dvma(struct net_device *dev)
 static void lance_init_ring_pio(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
+	struct lance_init_block *ib = lp->init_block;
 	u32 leptr;
 	int i;
     
@@ -501,8 +501,8 @@ static int init_restart_lance(struct lance_private *lp)
 static void lance_rx_dvma(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
-	volatile struct lance_rx_desc *rd;
+	struct lance_init_block *ib = lp->init_block;
+	struct lance_rx_desc *rd;
 	u8 bits;
 	int len, entry = lp->rx_new;
 	struct sk_buff *skb;
@@ -564,14 +564,14 @@ static void lance_rx_dvma(struct net_device *dev)
 static void lance_tx_dvma(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
+	struct lance_init_block *ib = lp->init_block;
 	int i, j;
 
 	spin_lock(&lp->lock);
 
 	j = lp->tx_old;
 	for (i = j; i != lp->tx_new; i = j) {
-		volatile struct lance_tx_desc *td = &ib->btx_ring [i];
+		struct lance_tx_desc *td = &ib->btx_ring [i];
 		u8 bits = td->tmd1_bits;
 
 		/* If we hit a packet not owned by us, stop */
@@ -641,12 +641,12 @@ out:
 	spin_unlock(&lp->lock);
 }
 
-static void lance_piocopy_to_skb(struct sk_buff *skb, volatile void *piobuf, int len)
+static void lance_piocopy_to_skb(struct sk_buff *skb, void __iomem *piobuf, int len)
 {
 	u16 *p16 = (u16 *) skb->data;
 	u32 *p32;
 	u8 *p8;
-	unsigned long pbuf = (unsigned long) piobuf;
+	void __iomem *pbuf = piobuf;
 
 	/* We know here that both src and dest are on a 16bit boundary. */
 	*p16++ = sbus_readw(pbuf);
@@ -674,8 +674,8 @@ static void lance_piocopy_to_skb(struct sk_buff *skb, volatile void *piobuf, int
 static void lance_rx_pio(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
-	volatile struct lance_rx_desc *rd;
+	struct lance_init_block *ib = lp->init_block;
+	struct lance_rx_desc *rd;
 	unsigned char bits;
 	int len, entry;
 	struct sk_buff *skb;
@@ -736,14 +736,14 @@ static void lance_rx_pio(struct net_device *dev)
 static void lance_tx_pio(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
+	struct lance_init_block *ib = lp->init_block;
 	int i, j;
 
 	spin_lock(&lp->lock);
 
 	j = lp->tx_old;
 	for (i = j; i != lp->tx_new; i = j) {
-		volatile struct lance_tx_desc *td = &ib->btx_ring [i];
+		struct lance_tx_desc *td = &ib->btx_ring [i];
 		u8 bits = sbus_readb(&td->tmd1_bits);
 
 		/* If we hit a packet not owned by us, stop */
@@ -880,7 +880,7 @@ static irqreturn_t lance_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 static void build_fake_packet(struct lance_private *lp)
 {
 	struct net_device *dev = lp->dev;
-	volatile struct lance_init_block *ib = lp->init_block;
+	struct lance_init_block *ib = lp->init_block;
 	u16 *packet;
 	struct ethhdr *eth;
 	int i, entry;
@@ -916,7 +916,7 @@ struct net_device *last_dev;
 static int lance_open(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
+	struct lance_init_block *ib = lp->init_block;
 	int status = 0;
 
 	last_dev = dev;
@@ -1006,9 +1006,9 @@ static int lance_reset(struct net_device *dev)
 	return status;
 }
 
-static void lance_piocopy_from_skb(volatile void *dest, unsigned char *src, int len)
+static void lance_piocopy_from_skb(void __iomem *dest, unsigned char *src, int len)
 {
-	unsigned long piobuf = (unsigned long) dest;
+	void __iomem *piobuf = dest;
 	u32 *p32;
 	u16 *p16;
 	u8 *p8;
@@ -1064,11 +1064,11 @@ static void lance_piocopy_from_skb(volatile void *dest, unsigned char *src, int
 		sbus_writeb(src[0], piobuf);
 }
 
-static void lance_piozero(volatile void *dest, int len)
+static void lance_piozero(void __iomem *dest, int len)
 {
-	unsigned long piobuf = (unsigned long) dest;
+	void __iomem *piobuf = dest;
 
-	if (piobuf & 1) {
+	if ((unsigned long)piobuf & 1) {
 		sbus_writeb(0, piobuf);
 		piobuf += 1;
 		len -= 1;
@@ -1079,7 +1079,7 @@ static void lance_piozero(volatile void *dest, int len)
 		sbus_writeb(0, piobuf);
 		return;
 	}
-	if (piobuf & 2) {
+	if ((unsigned long)piobuf & 2) {
 		sbus_writew(0, piobuf);
 		piobuf += 2;
 		len -= 2;
@@ -1113,7 +1113,7 @@ static void lance_tx_timeout(struct net_device *dev)
 static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
+	struct lance_init_block *ib = lp->init_block;
 	int entry, skblen, len;
 
 	skblen = skb->len;
@@ -1174,8 +1174,8 @@ static struct net_device_stats *lance_get_stats(struct net_device *dev)
 static void lance_load_multicast(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
-	volatile u16 *mcast_table = (u16 *) &ib->filter;
+	struct lance_init_block *ib = lp->init_block;
+	u16 *mcast_table = (u16 *) &ib->filter;
 	struct dev_mc_list *dmi = dev->mc_list;
 	char *addrs;
 	int i;
@@ -1224,7 +1224,7 @@ static void lance_load_multicast(struct net_device *dev)
 static void lance_set_multicast(struct net_device *dev)
 {
 	struct lance_private *lp = netdev_priv(dev);
-	volatile struct lance_init_block *ib = lp->init_block;
+	struct lance_init_block *ib = lp->init_block;
 	u16 mode;
 
 	if (!netif_running(dev))
@@ -1277,12 +1277,12 @@ static void lance_free_hwresources(struct lance_private *lp)
 		sbus_iounmap(lp->lregs, LANCE_REG_SIZE);
 	if (lp->init_block != NULL) {
 		if (lp->pio_buffer) {
-			sbus_iounmap((unsigned long)lp->init_block,
+			sbus_iounmap(lp->init_block,
 				     sizeof(struct lance_init_block));
 		} else {
 			sbus_free_consistent(lp->sdev,
 					     sizeof(struct lance_init_block),
-					     (void *)lp->init_block,
+					     lp->init_block,
 					     lp->init_block_dvma);
 		}
 	}
@@ -1349,7 +1349,7 @@ static int __init sparc_lance_init(struct sbus_dev *sdev,
 
 	lp->sdev = sdev;
 	if (lebuffer) {
-		lp->init_block = (volatile struct lance_init_block *)
+		lp->init_block =
 			sbus_ioremap(&lebuffer->resource[0], 0,
 				     sizeof(struct lance_init_block), "lebuffer");
 		if (lp->init_block == NULL) {
@@ -1362,7 +1362,7 @@ static int __init sparc_lance_init(struct sbus_dev *sdev,
 		lp->rx = lance_rx_pio;
 		lp->tx = lance_tx_pio;
 	} else {
-		lp->init_block = (volatile struct lance_init_block *)
+		lp->init_block =
 			sbus_alloc_consistent(sdev, sizeof(struct lance_init_block),
 					      &lp->init_block_dvma);
 		if (lp->init_block == NULL ||
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
index 39a4b40b4..1ed3ff5b3 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/sunqe.c
@@ -49,7 +49,7 @@ static void qe_set_multicast(struct net_device *dev);
 
 #define QEC_RESET_TRIES 200
 
-static inline int qec_global_reset(unsigned long gregs)
+static inline int qec_global_reset(void __iomem *gregs)
 {
 	int tries = QEC_RESET_TRIES;
 
@@ -73,8 +73,8 @@ static inline int qec_global_reset(unsigned long gregs)
 
 static inline int qe_stop(struct sunqe *qep)
 {
-	unsigned long cregs = qep->qcregs;
-	unsigned long mregs = qep->mregs;
+	void __iomem *cregs = qep->qcregs;
+	void __iomem *mregs = qep->mregs;
 	int tries;
 
 	/* Reset the MACE, then the QEC channel. */
@@ -130,9 +130,9 @@ static void qe_init_rings(struct sunqe *qep)
 static int qe_init(struct sunqe *qep, int from_irq)
 {
 	struct sunqec *qecp = qep->parent;
-	unsigned long cregs = qep->qcregs;
-	unsigned long mregs = qep->mregs;
-	unsigned long gregs = qecp->gregs;
+	void __iomem *cregs = qep->qcregs;
+	void __iomem *mregs = qep->mregs;
+	void __iomem *gregs = qecp->gregs;
 	unsigned char *e = &qep->dev->dev_addr[0];
 	u32 tmp;
 	int i;
@@ -699,7 +699,7 @@ static void qe_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 static u32 qe_get_link(struct net_device *dev)
 {
 	struct sunqe *qep = dev->priv;
-	unsigned long mregs = qep->mregs;
+	void __iomem *mregs = qep->mregs;
 	u8 phyconfig;
 
 	spin_lock_irq(&qep->lock);
diff --git a/drivers/net/sunqe.h b/drivers/net/sunqe.h
index b90ed5db4..af34f3611 100644
--- a/drivers/net/sunqe.h
+++ b/drivers/net/sunqe.h
@@ -311,7 +311,7 @@ struct qe_init_block {
 struct sunqe;
 
 struct sunqec {
-	unsigned long		gregs;		/* QEC Global Registers         */
+	void __iomem		*gregs;		/* QEC Global Registers         */
 	struct sunqe		*qes[4];	/* Each child MACE              */
 	unsigned int            qec_bursts;	/* Support burst sizes          */
 	struct sbus_dev		*qec_sdev;	/* QEC's SBUS device            */
@@ -331,8 +331,8 @@ struct sunqe_buffers {
 ((__u32)((unsigned long)(&(((struct sunqe_buffers *)0)->mem[elem][0]))))
 
 struct sunqe {
-	unsigned long			qcregs;		/* QEC per-channel Registers   */
-	unsigned long			mregs;		/* Per-channel MACE Registers  */
+	void __iomem			*qcregs;		/* QEC per-channel Registers   */
+	void __iomem			*mregs;		/* Per-channel MACE Registers  */
 	struct qe_init_block      	*qe_block;	/* RX and TX descriptors       */
 	__u32                      	qblock_dvma;	/* RX and TX descriptors       */
 	spinlock_t			lock;		/* Protects txfull state       */
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 0e4615472..1a26b11fb 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -4,6 +4,9 @@
  * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
  * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com)
  * Copyright (C) 2004 Sun Microsystems Inc.
+ *
+ * Firmware is:
+ * 	Copyright (C) 2000-2003 Broadcom Corporation.
  */
 
 #include <linux/config.h>
@@ -57,8 +60,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.8"
-#define DRV_MODULE_RELDATE	"July 14, 2004"
+#define DRV_MODULE_VERSION	"3.10"
+#define DRV_MODULE_RELDATE	"September 14, 2004"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -328,7 +331,7 @@ static void _tw32_flush(struct tg3 *tp, u32 off, u32 val)
 		pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
 		spin_unlock_irqrestore(&tp->indirect_lock, flags);
 	} else {
-		unsigned long dest = tp->regs + off;
+		void __iomem *dest = tp->regs + off;
 		writel(val, dest);
 		readl(dest);    /* always flush PCI write */
 	}
@@ -336,7 +339,7 @@ static void _tw32_flush(struct tg3 *tp, u32 off, u32 val)
 
 static inline void _tw32_rx_mbox(struct tg3 *tp, u32 off, u32 val)
 {
-	unsigned long mbox = tp->regs + off;
+	void __iomem *mbox = tp->regs + off;
 	writel(val, mbox);
 	if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
 		readl(mbox);
@@ -344,7 +347,7 @@ static inline void _tw32_rx_mbox(struct tg3 *tp, u32 off, u32 val)
 
 static inline void _tw32_tx_mbox(struct tg3 *tp, u32 off, u32 val)
 {
-	unsigned long mbox = tp->regs + off;
+	void __iomem *mbox = tp->regs + off;
 	writel(val, mbox);
 	if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG)
 		writel(val, mbox);
@@ -442,9 +445,14 @@ static void tg3_switch_clocks(struct tg3 *tp)
 		       0x1f);
 	tp->pci_clock_ctrl = clock_ctrl;
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
-	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 &&
-	    (orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) {
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+		if (orig_clock_ctrl & CLOCK_CTRL_625_CORE) {
+			tw32_f(TG3PCI_CLOCK_CTRL,
+			       clock_ctrl | CLOCK_CTRL_625_CORE);
+			udelay(40);
+		}
+	} else if ((orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) {
 		tw32_f(TG3PCI_CLOCK_CTRL,
 		     clock_ctrl |
 		     (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK));
@@ -980,7 +988,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
 		tp->link_config.orig_autoneg = tp->link_config.autoneg;
 	}
 
-	if (tp->phy_id != PHY_ID_SERDES) {
+	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
 		tp->link_config.speed = SPEED_10;
 		tp->link_config.duplex = DUPLEX_HALF;
 		tp->link_config.autoneg = AUTONEG_ENABLE;
@@ -992,7 +1000,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
 	if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) {
 		u32 mac_mode;
 
-		if (tp->phy_id != PHY_ID_SERDES) {
+		if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
 			tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a);
 			udelay(40);
 
@@ -1114,29 +1122,33 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv
 	u32 old_rx_mode = tp->rx_mode;
 	u32 old_tx_mode = tp->tx_mode;
 
-	if (local_adv & ADVERTISE_PAUSE_CAP) {
-		if (local_adv & ADVERTISE_PAUSE_ASYM) {
-			if (remote_adv & LPA_PAUSE_CAP)
-				new_tg3_flags |=
-					(TG3_FLAG_RX_PAUSE |
-					 TG3_FLAG_TX_PAUSE);
-			else if (remote_adv & LPA_PAUSE_ASYM)
-				new_tg3_flags |=
-					(TG3_FLAG_RX_PAUSE);
-		} else {
-			if (remote_adv & LPA_PAUSE_CAP)
-				new_tg3_flags |=
-					(TG3_FLAG_RX_PAUSE |
-					 TG3_FLAG_TX_PAUSE);
+	if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) {
+		if (local_adv & ADVERTISE_PAUSE_CAP) {
+			if (local_adv & ADVERTISE_PAUSE_ASYM) {
+				if (remote_adv & LPA_PAUSE_CAP)
+					new_tg3_flags |=
+						(TG3_FLAG_RX_PAUSE |
+					 	TG3_FLAG_TX_PAUSE);
+				else if (remote_adv & LPA_PAUSE_ASYM)
+					new_tg3_flags |=
+						(TG3_FLAG_RX_PAUSE);
+			} else {
+				if (remote_adv & LPA_PAUSE_CAP)
+					new_tg3_flags |=
+						(TG3_FLAG_RX_PAUSE |
+					 	TG3_FLAG_TX_PAUSE);
+			}
+		} else if (local_adv & ADVERTISE_PAUSE_ASYM) {
+			if ((remote_adv & LPA_PAUSE_CAP) &&
+		    	(remote_adv & LPA_PAUSE_ASYM))
+				new_tg3_flags |= TG3_FLAG_TX_PAUSE;
 		}
-	} else if (local_adv & ADVERTISE_PAUSE_ASYM) {
-		if ((remote_adv & LPA_PAUSE_CAP) &&
-		    (remote_adv & LPA_PAUSE_ASYM))
-			new_tg3_flags |= TG3_FLAG_TX_PAUSE;
-	}
 
-	tp->tg3_flags &= ~(TG3_FLAG_RX_PAUSE | TG3_FLAG_TX_PAUSE);
-	tp->tg3_flags |= new_tg3_flags;
+		tp->tg3_flags &= ~(TG3_FLAG_RX_PAUSE | TG3_FLAG_TX_PAUSE);
+		tp->tg3_flags |= new_tg3_flags;
+	} else {
+		new_tg3_flags = tp->tg3_flags;
+	}
 
 	if (new_tg3_flags & TG3_FLAG_RX_PAUSE)
 		tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE;
@@ -1487,6 +1499,18 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
 	current_speed = SPEED_INVALID;
 	current_duplex = DUPLEX_INVALID;
 
+	if (tp->tg3_flags2 & TG3_FLG2_CAPACITIVE_COUPLING) {
+		u32 val;
+
+		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4007);
+		tg3_readphy(tp, MII_TG3_AUX_CTRL, &val);
+		if (!(val & (1 << 10))) {
+			val |= (1 << 10);
+			tg3_writephy(tp, MII_TG3_AUX_CTRL, val);
+			goto relink;
+		}
+	}
+
 	bmsr = 0;
 	for (i = 0; i < 100; i++) {
 		tg3_readphy(tp, MII_BMSR, &bmsr);
@@ -1566,7 +1590,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
 			tg3_setup_flow_control(tp, local_adv, remote_adv);
 		}
 	}
-
+relink:
 	if (current_link_up == 0) {
 		u32 tmp;
 
@@ -1616,7 +1640,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
 	tw32_f(MAC_MODE, tp->mac_mode);
 	udelay(40);
 
-	if (tp->tg3_flags & (TG3_FLAG_USE_LINKCHG_REG | TG3_FLAG_POLL_SERDES)) {
+	if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) {
 		/* Polled via timer. */
 		tw32_f(MAC_EVENT, 0);
 	} else {
@@ -1965,190 +1989,318 @@ static int tg3_fiber_aneg_smachine(struct tg3 *tp,
 static int fiber_autoneg(struct tg3 *tp, u32 *flags)
 {
 	int res = 0;
+	struct tg3_fiber_aneginfo aninfo;
+	int status = ANEG_FAILED;
+	unsigned int tick;
+	u32 tmp;
 
-	if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) {
-		u32 dig_status;
+	tw32_f(MAC_TX_AUTO_NEG, 0);
 
-		dig_status = tr32(SG_DIG_STATUS);
-		*flags = 0;
-		if (dig_status & SG_DIG_PARTNER_ASYM_PAUSE)
-			*flags |= MR_LP_ADV_ASYM_PAUSE;
-		if (dig_status & SG_DIG_PARTNER_PAUSE_CAPABLE)
-			*flags |= MR_LP_ADV_SYM_PAUSE;
+	tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
+	tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
+	udelay(40);
 
-		if ((dig_status & SG_DIG_AUTONEG_COMPLETE) &&
-		    !(dig_status & (SG_DIG_AUTONEG_ERROR |
-				    SG_DIG_PARTNER_FAULT_MASK)))
-			res = 1;
-	} else {
-		struct tg3_fiber_aneginfo aninfo;
-		int status = ANEG_FAILED;
-		unsigned int tick;
-		u32 tmp;
+	tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
+	udelay(40);
 
-		tw32_f(MAC_TX_AUTO_NEG, 0);
+	memset(&aninfo, 0, sizeof(aninfo));
+	aninfo.flags |= MR_AN_ENABLE;
+	aninfo.state = ANEG_STATE_UNKNOWN;
+	aninfo.cur_time = 0;
+	tick = 0;
+	while (++tick < 195000) {
+		status = tg3_fiber_aneg_smachine(tp, &aninfo);
+		if (status == ANEG_DONE || status == ANEG_FAILED)
+			break;
 
-		tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
-		tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
-		udelay(40);
+		udelay(1);
+	}
 
-		tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
-		udelay(40);
+	tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
+	tw32_f(MAC_MODE, tp->mac_mode);
+	udelay(40);
 
-		memset(&aninfo, 0, sizeof(aninfo));
-		aninfo.flags |= MR_AN_ENABLE;
-		aninfo.state = ANEG_STATE_UNKNOWN;
-		aninfo.cur_time = 0;
-		tick = 0;
-		while (++tick < 195000) {
-			status = tg3_fiber_aneg_smachine(tp, &aninfo);
-			if (status == ANEG_DONE || status == ANEG_FAILED)
-				break;
+	*flags = aninfo.flags;
 
-			udelay(1);
-		}
+	if (status == ANEG_DONE &&
+	    (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK |
+			     MR_LP_ADV_FULL_DUPLEX)))
+		res = 1;
 
-		tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
-		tw32_f(MAC_MODE, tp->mac_mode);
-		udelay(40);
+	return res;
+}
 
-		*flags = aninfo.flags;
+static void tg3_init_bcm8002(struct tg3 *tp)
+{
+	u32 mac_status = tr32(MAC_STATUS);
+	int i;
 
-		if (status == ANEG_DONE &&
-		    (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK |
-				     MR_LP_ADV_FULL_DUPLEX)))
-			res = 1;
-	}
+	/* Reset when initting first time or we have a link. */
+	if ((tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) &&
+	    !(mac_status & MAC_STATUS_PCS_SYNCED))
+		return;
 
-	return res;
+	/* Set PLL lock range. */
+	tg3_writephy(tp, 0x16, 0x8007);
+
+	/* SW reset */
+	tg3_writephy(tp, MII_BMCR, BMCR_RESET);
+
+	/* Wait for reset to complete. */
+	/* XXX schedule_timeout() ... */
+	for (i = 0; i < 500; i++)
+		udelay(10);
+
+	/* Config mode; select PMA/Ch 1 regs. */
+	tg3_writephy(tp, 0x10, 0x8411);
+
+	/* Enable auto-lock and comdet, select txclk for tx. */
+	tg3_writephy(tp, 0x11, 0x0a10);
+
+	tg3_writephy(tp, 0x18, 0x00a0);
+	tg3_writephy(tp, 0x16, 0x41ff);
+
+	/* Assert and deassert POR. */
+	tg3_writephy(tp, 0x13, 0x0400);
+	udelay(40);
+	tg3_writephy(tp, 0x13, 0x0000);
+
+	tg3_writephy(tp, 0x11, 0x0a50);
+	udelay(40);
+	tg3_writephy(tp, 0x11, 0x0a10);
+
+	/* Wait for signal to stabilize */
+	/* XXX schedule_timeout() ... */
+	for (i = 0; i < 15000; i++)
+		udelay(10);
+
+	/* Deselect the channel register so we can read the PHYID
+	 * later.
+	 */
+	tg3_writephy(tp, 0x10, 0x8011);
 }
 
-static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
+static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status)
 {
-	u32 orig_pause_cfg;
-	u16 orig_active_speed;
-	u8 orig_active_duplex;
+	u32 sg_dig_ctrl, sg_dig_status;
+	u32 serdes_cfg, expected_sg_dig_ctrl;
+	int workaround, port_a;
 	int current_link_up;
-	int i;
 
-	orig_pause_cfg =
-		(tp->tg3_flags & (TG3_FLAG_RX_PAUSE |
-				  TG3_FLAG_TX_PAUSE));
-	orig_active_speed = tp->link_config.active_speed;
-	orig_active_duplex = tp->link_config.active_duplex;
+	serdes_cfg = 0;
+	expected_sg_dig_ctrl = 0;
+	workaround = 0;
+	port_a = 1;
+	current_link_up = 0;
 
-	tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
-	tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
-	tw32_f(MAC_MODE, tp->mac_mode);
-	udelay(40);
+	if (tp->pci_chip_rev_id != CHIPREV_ID_5704_A0 &&
+	    tp->pci_chip_rev_id != CHIPREV_ID_5704_A1) {
+		workaround = 1;
+		if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
+			port_a = 0;
 
-	if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) {
-		/* Allow time for the hardware to auto-negotiate (195ms) */
-		unsigned int tick = 0;
+		serdes_cfg = tr32(MAC_SERDES_CFG) &
+			((1 << 23) | (1 << 22) | (1 << 21) | (1 << 20));
+	}
 
-		while (++tick < 195000) { 
-			if (tr32(SG_DIG_STATUS) & SG_DIG_AUTONEG_COMPLETE)
-				break;
-			udelay(1);
+	sg_dig_ctrl = tr32(SG_DIG_CTRL);
+
+	if (tp->link_config.autoneg != AUTONEG_ENABLE) {
+		if (sg_dig_ctrl & (1 << 31)) {
+			if (workaround) {
+				u32 val = serdes_cfg;
+
+				if (port_a)
+					val |= 0xc010880;
+				else
+					val |= 0x4010880;
+				tw32_f(MAC_SERDES_CFG, val);
+			}
+			tw32_f(SG_DIG_CTRL, 0x01388400);
 		}
-		if (tick >= 195000)
-			printk(KERN_INFO PFX "%s: HW autoneg failed !\n",
-			    tp->dev->name);
+		if (mac_status & MAC_STATUS_PCS_SYNCED) {
+			tg3_setup_flow_control(tp, 0, 0);
+			current_link_up = 1;
+		}
+		goto out;
 	}
 
-	/* Reset when initting first time or we have a link. */
-	if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) ||
-	    (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {
-		/* Set PLL lock range. */
-		tg3_writephy(tp, 0x16, 0x8007);
+	/* Want auto-negotiation.  */
+	expected_sg_dig_ctrl = 0x81388400;
 
-		/* SW reset */
-		tg3_writephy(tp, MII_BMCR, BMCR_RESET);
+	/* Pause capability */
+	expected_sg_dig_ctrl |= (1 << 11);
 
-		/* Wait for reset to complete. */
-		/* XXX schedule_timeout() ... */
-		for (i = 0; i < 500; i++)
-			udelay(10);
+	/* Asymettric pause */
+	expected_sg_dig_ctrl |= (1 << 12);
 
-		/* Config mode; select PMA/Ch 1 regs. */
-		tg3_writephy(tp, 0x10, 0x8411);
+	if (sg_dig_ctrl != expected_sg_dig_ctrl) {
+		if (workaround)
+			tw32_f(MAC_SERDES_CFG, serdes_cfg | 0xc011880);
+		tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | (1 << 30));
+		udelay(5);
+		tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl);
 
-		/* Enable auto-lock and comdet, select txclk for tx. */
-		tg3_writephy(tp, 0x11, 0x0a10);
+		tp->tg3_flags2 |= TG3_FLG2_PHY_JUST_INITTED;
+	} else if (mac_status & (MAC_STATUS_PCS_SYNCED |
+				 MAC_STATUS_SIGNAL_DET)) {
+		sg_dig_status = tr32(SG_DIG_STATUS);
 
-		tg3_writephy(tp, 0x18, 0x00a0);
-		tg3_writephy(tp, 0x16, 0x41ff);
+		if ((sg_dig_status & (1 << 1)) &&
+		    (mac_status & MAC_STATUS_PCS_SYNCED)) {
+			u32 local_adv, remote_adv;
 
-		/* Assert and deassert POR. */
-		tg3_writephy(tp, 0x13, 0x0400);
-		udelay(40);
-		tg3_writephy(tp, 0x13, 0x0000);
+			local_adv = ADVERTISE_PAUSE_CAP;
+			remote_adv = 0;
+			if (sg_dig_status & (1 << 19))
+				remote_adv |= LPA_PAUSE_CAP;
+			if (sg_dig_status & (1 << 20))
+				remote_adv |= LPA_PAUSE_ASYM;
 
-		tg3_writephy(tp, 0x11, 0x0a50);
-		udelay(40);
-		tg3_writephy(tp, 0x11, 0x0a10);
+			tg3_setup_flow_control(tp, local_adv, remote_adv);
+			current_link_up = 1;
+			tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED;
+		} else if (!(sg_dig_status & (1 << 1))) {
+			if (tp->tg3_flags2 & TG3_FLG2_PHY_JUST_INITTED)
+				tp->tg3_flags2 &= ~TG3_FLG2_PHY_JUST_INITTED;
+			else {
+				if (workaround) {
+					u32 val = serdes_cfg;
+
+					if (port_a)
+						val |= 0xc010880;
+					else
+						val |= 0x4010880;
+
+					tw32_f(MAC_SERDES_CFG, val);
+				}
 
-		/* Wait for signal to stabilize */
-		/* XXX schedule_timeout() ... */
-		for (i = 0; i < 15000; i++)
-			udelay(10);
+				tw32_f(SG_DIG_CTRL, 0x01388400);
+				udelay(40);
 
-		/* Deselect the channel register so we can read the PHYID
-		 * later.
-		 */
-		tg3_writephy(tp, 0x10, 0x8011);
+				mac_status = tr32(MAC_STATUS);
+				if (mac_status & MAC_STATUS_PCS_SYNCED) {
+					tg3_setup_flow_control(tp, 0, 0);
+					current_link_up = 1;
+				}
+			}
+		}
 	}
 
-	/* Enable link change interrupt unless serdes polling.  */
-	if (!(tp->tg3_flags & TG3_FLAG_POLL_SERDES))
-		tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
-	else
-		tw32_f(MAC_EVENT, 0);
-	udelay(40);
+out:
+	return current_link_up;
+}
 
-	current_link_up = 0;
- 	if (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) {
-		if (tp->link_config.autoneg == AUTONEG_ENABLE) {
-			u32 flags;
+static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status)
+{
+	int current_link_up = 0;
+
+ 	if (!(mac_status & MAC_STATUS_PCS_SYNCED)) {
+		tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL;
+		goto out;
+	}
+
+	if (tp->link_config.autoneg == AUTONEG_ENABLE) {
+		u32 flags;
+		int i;
   
-			if (fiber_autoneg(tp, &flags)) {
-				u32 local_adv, remote_adv;
+		if (fiber_autoneg(tp, &flags)) {
+			u32 local_adv, remote_adv;
 
-				local_adv = ADVERTISE_PAUSE_CAP;
-				remote_adv = 0;
-				if (flags & MR_LP_ADV_SYM_PAUSE)
-  					remote_adv |= LPA_PAUSE_CAP;
-				if (flags & MR_LP_ADV_ASYM_PAUSE)
-					remote_adv |= LPA_PAUSE_ASYM;
+			local_adv = ADVERTISE_PAUSE_CAP;
+			remote_adv = 0;
+			if (flags & MR_LP_ADV_SYM_PAUSE)
+				remote_adv |= LPA_PAUSE_CAP;
+			if (flags & MR_LP_ADV_ASYM_PAUSE)
+				remote_adv |= LPA_PAUSE_ASYM;
 
-				tg3_setup_flow_control(tp, local_adv, remote_adv);
+			tg3_setup_flow_control(tp, local_adv, remote_adv);
 
-				tp->tg3_flags |=
-					TG3_FLAG_GOT_SERDES_FLOWCTL;
-				current_link_up = 1;
-			}
-			for (i = 0; i < 60; i++) {
-				udelay(20);
-				tw32_f(MAC_STATUS,
-				     (MAC_STATUS_SYNC_CHANGED |
-				      MAC_STATUS_CFG_CHANGED));
-				udelay(40);
-				if ((tr32(MAC_STATUS) &
-				     (MAC_STATUS_SYNC_CHANGED |
-				      MAC_STATUS_CFG_CHANGED)) == 0)
-					break;
-			}
-			if (current_link_up == 0 &&
-			    (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {
-				current_link_up = 1;
-			}
-		} else {
-			/* Forcing 1000FD link up. */
-			current_link_up = 1;
 			tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
+			current_link_up = 1;
 		}
-	} else
-		tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL;
+		for (i = 0; i < 30; i++) {
+			udelay(20);
+			tw32_f(MAC_STATUS,
+			       (MAC_STATUS_SYNC_CHANGED |
+				MAC_STATUS_CFG_CHANGED));
+			udelay(40);
+			if ((tr32(MAC_STATUS) &
+			     (MAC_STATUS_SYNC_CHANGED |
+			      MAC_STATUS_CFG_CHANGED)) == 0)
+				break;
+		}
+
+		mac_status = tr32(MAC_STATUS);
+		if (current_link_up == 0 &&
+		    (mac_status & MAC_STATUS_PCS_SYNCED) &&
+		    !(mac_status & MAC_STATUS_RCVD_CFG))
+			current_link_up = 1;
+	} else {
+		/* Forcing 1000FD link up. */
+		current_link_up = 1;
+		tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
+
+		tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS));
+		udelay(40);
+	}
+
+out:
+	return current_link_up;
+}
+
+static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
+{
+	u32 orig_pause_cfg;
+	u16 orig_active_speed;
+	u8 orig_active_duplex;
+	u32 mac_status;
+	int current_link_up;
+	int i;
+
+	orig_pause_cfg =
+		(tp->tg3_flags & (TG3_FLAG_RX_PAUSE |
+				  TG3_FLAG_TX_PAUSE));
+	orig_active_speed = tp->link_config.active_speed;
+	orig_active_duplex = tp->link_config.active_duplex;
+
+	if (!(tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) &&
+	    netif_carrier_ok(tp->dev) &&
+	    (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)) {
+		mac_status = tr32(MAC_STATUS);
+		mac_status &= (MAC_STATUS_PCS_SYNCED |
+			       MAC_STATUS_SIGNAL_DET |
+			       MAC_STATUS_CFG_CHANGED |
+			       MAC_STATUS_RCVD_CFG);
+		if (mac_status == (MAC_STATUS_PCS_SYNCED |
+				   MAC_STATUS_SIGNAL_DET)) {
+			tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED |
+					    MAC_STATUS_CFG_CHANGED));
+			return 0;
+		}
+	}
+
+	tw32_f(MAC_TX_AUTO_NEG, 0);
+
+	tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
+	tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
+	tw32_f(MAC_MODE, tp->mac_mode);
+	udelay(40);
+
+	if (tp->phy_id == PHY_ID_BCM8002)
+		tg3_init_bcm8002(tp);
+
+	/* Enable link change event even when serdes polling.  */
+	tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
+	udelay(40);
+
+	current_link_up = 0;
+	mac_status = tr32(MAC_STATUS);
+
+	if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG)
+		current_link_up = tg3_setup_fiber_hw_autoneg(tp, mac_status);
+	else
+		current_link_up = tg3_setup_fiber_by_hand(tp, mac_status);
 
 	tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
 	tw32_f(MAC_MODE, tp->mac_mode);
@@ -2159,19 +2311,24 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
 		 (tp->hw_status->status & ~SD_STATUS_LINK_CHG));
 
 	for (i = 0; i < 100; i++) {
-		udelay(20);
-		tw32_f(MAC_STATUS,
-		     (MAC_STATUS_SYNC_CHANGED |
-		      MAC_STATUS_CFG_CHANGED));
-		udelay(40);
-		if ((tr32(MAC_STATUS) &
-		     (MAC_STATUS_SYNC_CHANGED |
-		      MAC_STATUS_CFG_CHANGED)) == 0)
+		tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED |
+				    MAC_STATUS_CFG_CHANGED));
+		udelay(5);
+		if ((tr32(MAC_STATUS) & (MAC_STATUS_SYNC_CHANGED |
+					 MAC_STATUS_CFG_CHANGED)) == 0)
 			break;
 	}
 
-	if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0)
+	mac_status = tr32(MAC_STATUS);
+	if ((mac_status & MAC_STATUS_PCS_SYNCED) == 0) {
 		current_link_up = 0;
+		if (tp->link_config.autoneg == AUTONEG_ENABLE) {
+			tw32_f(MAC_MODE, (tp->mac_mode |
+					  MAC_MODE_SEND_CONFIGS));
+			udelay(1);
+			tw32_f(MAC_MODE, tp->mac_mode);
+		}
+	}
 
 	if (current_link_up == 1) {
 		tp->link_config.active_speed = SPEED_1000;
@@ -2203,15 +2360,6 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
 			tg3_link_report(tp);
 	}
 
-	if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) {
-		tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY);
-		udelay(40);
-		if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) {
-			tw32_f(MAC_MODE, tp->mac_mode);
-			udelay(40);
-		}
-	}
-
 	return 0;
 }
 
@@ -2219,7 +2367,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
 {
 	int err;
 
-	if (tp->phy_id == PHY_ID_SERDES) {
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
 		err = tg3_setup_fiber_phy(tp, force_reset);
 	} else {
 		err = tg3_setup_copper_phy(tp, force_reset);
@@ -2738,11 +2886,11 @@ static void tg3_reset_task(void *_data)
 	tg3_halt(tp);
 	tg3_init_hw(tp);
 
+	tg3_netif_start(tp);
+
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
 
-	tg3_netif_start(tp);
-
 	if (restart_timer)
 		mod_timer(&tp->timer, jiffies + 1);
 }
@@ -2812,6 +2960,7 @@ static void tg3_set_txd(struct tg3 *tp, int entry,
 			dma_addr_t mapping, int len, u32 flags,
 			u32 mss_and_is_end)
 {
+	struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry];
 	int is_end = (mss_and_is_end & 0x1);
 	u32 mss = (mss_and_is_end >> 1);
 	u32 vlan_tag = 0;
@@ -2823,35 +2972,11 @@ static void tg3_set_txd(struct tg3 *tp, int entry,
 		flags &= 0xffff;
 	}
 	vlan_tag |= (mss << TXD_MSS_SHIFT);
-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
-		struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry];
-
-		txd->addr_hi = ((u64) mapping >> 32);
-		txd->addr_lo = ((u64) mapping & 0xffffffff);
-		txd->len_flags = (len << TXD_LEN_SHIFT) | flags;
-		txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT;
-	} else {
-		struct tx_ring_info *txr = &tp->tx_buffers[entry];
-		unsigned long txd;
 
-		txd = (tp->regs +
-		       NIC_SRAM_WIN_BASE +
-		       NIC_SRAM_TX_BUFFER_DESC);
-		txd += (entry * TXD_SIZE);
-
-		/* Save some PIOs */
-		if (sizeof(dma_addr_t) != sizeof(u32))
-			writel(((u64) mapping >> 32),
-			       txd + TXD_ADDR + TG3_64BIT_REG_HIGH);
-
-		writel(((u64) mapping & 0xffffffff),
-		       txd + TXD_ADDR + TG3_64BIT_REG_LOW);
-		writel(len << TXD_LEN_SHIFT | flags, txd + TXD_LEN_FLAGS);
-		if (txr->prev_vlan_tag != vlan_tag) {
-			writel(vlan_tag << TXD_VLAN_TAG_SHIFT, txd + TXD_VLAN_TAG);
-			txr->prev_vlan_tag = vlan_tag;
-		}
-	}
+	txd->addr_hi = ((u64) mapping >> 32);
+	txd->addr_lo = ((u64) mapping & 0xffffffff);
+	txd->len_flags = (len << TXD_LEN_SHIFT) | flags;
+	txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT;
 }
 
 static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
@@ -2892,7 +3017,11 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	 * So we really do need to disable interrupts when taking
 	 * tx_lock here.
 	 */
-	spin_lock_irqsave(&tp->tx_lock, flags);
+	local_irq_save(flags);
+	if (!spin_trylock(&tp->tx_lock)) { 
+		local_irq_restore(flags);
+		return NETDEV_TX_LOCKED; 
+	} 
 
 	/* This is a hard error, log it. */
 	if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
@@ -2900,7 +3029,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		spin_unlock_irqrestore(&tp->tx_lock, flags);
 		printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
 		       dev->name);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	entry = tp->tx_prod;
@@ -3040,19 +3169,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	}
 
 	/* Packets are ready, update Tx producer idx local and on card. */
-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
-		tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 +
-			      TG3_64BIT_REG_LOW), entry);
-	} else {
-		/* First, make sure tg3 sees last descriptor fully
-		 * in SRAM.
-		 */
-		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW);
-
-		tw32_tx_mbox((MAILBOX_SNDNIC_PROD_IDX_0 +
-			      TG3_64BIT_REG_LOW), entry);
-	}
+	tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
 
 	tp->tx_prod = entry;
 	if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))
@@ -3063,7 +3180,7 @@ out_unlock:
 
 	dev->trans_start = jiffies;
 
-	return 0;
+	return NETDEV_TX_OK;
 }
 
 static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp,
@@ -3102,9 +3219,10 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
 
 	tg3_init_hw(tp);
 
+	tg3_netif_start(tp);
+
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
-	tg3_netif_start(tp);
 
 	return 0;
 }
@@ -3190,7 +3308,6 @@ static void tg3_free_rings(struct tg3 *tp)
  */
 static void tg3_init_rings(struct tg3 *tp)
 {
-	unsigned long start, end;
 	u32 i;
 
 	/* Free up all the SKBs. */
@@ -3200,21 +3317,7 @@ static void tg3_init_rings(struct tg3 *tp)
 	memset(tp->rx_std, 0, TG3_RX_RING_BYTES);
 	memset(tp->rx_jumbo, 0, TG3_RX_JUMBO_RING_BYTES);
 	memset(tp->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
-
-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
-		memset(tp->tx_ring, 0, TG3_TX_RING_BYTES);
-	} else {
-		start = (tp->regs +
-			 NIC_SRAM_WIN_BASE +
-			 NIC_SRAM_TX_BUFFER_DESC);
-		end = start + TG3_TX_RING_BYTES;
-		while (start < end) {
-			writel(0, start);
-			start += 4;
-		}
-		for (i = 0; i < TG3_TX_RING_SIZE; i++)
-			tp->tx_buffers[i].prev_vlan_tag = 0;
-	}
+	memset(tp->tx_ring, 0, TG3_TX_RING_BYTES);
 
 	/* Initialize invariants of the rings, we only set this
 	 * stuff once.  This works because the card does not
@@ -3345,15 +3448,10 @@ static int tg3_alloc_consistent(struct tg3 *tp)
 	if (!tp->rx_rcb)
 		goto err_out;
 
-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
-		tp->tx_ring = pci_alloc_consistent(tp->pdev, TG3_TX_RING_BYTES,
-						   &tp->tx_desc_mapping);
-		if (!tp->tx_ring)
-			goto err_out;
-	} else {
-		tp->tx_ring = NULL;
-		tp->tx_desc_mapping = 0;
-	}
+	tp->tx_ring = pci_alloc_consistent(tp->pdev, TG3_TX_RING_BYTES,
+					   &tp->tx_desc_mapping);
+	if (!tp->tx_ring)
+		goto err_out;
 
 	tp->hw_status = pci_alloc_consistent(tp->pdev,
 					     TG3_HW_STATUS_SIZE,
@@ -3595,6 +3693,8 @@ static void tg3_write_sig_legacy(struct tg3 *tp, int kind)
 	}
 }
 
+static void tg3_stop_fw(struct tg3 *);
+
 /* tp->lock is held. */
 static int tg3_chip_reset(struct tg3 *tp)
 {
@@ -3602,7 +3702,7 @@ static int tg3_chip_reset(struct tg3 *tp)
 	u32 flags_save;
 	int i;
 
-	if (!(tp->tg3_flags2 & TG3_FLG2_SUN_5704))
+	if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X))
 		tg3_nvram_lock(tp);
 
 	/*
@@ -3697,6 +3797,11 @@ static int tg3_chip_reset(struct tg3 *tp)
 
 	tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
 
+	if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) {
+		tg3_stop_fw(tp);
+		tw32(0x5000, 0x400);
+	}
+
 	tw32(GRC_MODE, tp->grc_mode);
 
 	if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) {
@@ -3713,7 +3818,7 @@ static int tg3_chip_reset(struct tg3 *tp)
 		tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
 	}
 
-	if (tp->phy_id == PHY_ID_SERDES) {
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
 		tp->mac_mode = MAC_MODE_PORT_MODE_TBI;
 		tw32_f(MAC_MODE, tp->mac_mode);
 	} else
@@ -3728,7 +3833,7 @@ static int tg3_chip_reset(struct tg3 *tp)
 		udelay(10);
 	}
 	if (i >= 100000 &&
-	    !(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) {
+	    !(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) {
 		printk(KERN_ERR PFX "tg3_reset_hw timed out for %s, "
 		       "firmware will not restart magic=%08x\n",
 		       tp->dev->name, val);
@@ -4810,10 +4915,7 @@ static int tg3_reset_hw(struct tg3 *tp)
 			  GRC_MODE_4X_NIC_SEND_RINGS |
 			  GRC_MODE_NO_TX_PHDR_CSUM |
 			  GRC_MODE_NO_RX_PHDR_CSUM);
-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS)
-		tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
-	else
-		tp->grc_mode |= GRC_MODE_4X_NIC_SEND_RINGS;
+	tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
 	if (tp->tg3_flags & TG3_FLAG_NO_TX_PSEUDO_CSUM)
 		tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
 	if (tp->tg3_flags & TG3_FLAG_NO_RX_PSEUDO_CSUM)
@@ -4966,18 +5068,11 @@ static int tg3_reset_hw(struct tg3 *tp)
 	tw32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
 	tw32_tx_mbox(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
 
-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
-		tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB,
-			       tp->tx_desc_mapping,
-			       (TG3_TX_RING_SIZE <<
-				BDINFO_FLAGS_MAXLEN_SHIFT),
-			       NIC_SRAM_TX_BUFFER_DESC);
-	} else {
-		tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB,
-			       0,
-			       BDINFO_FLAGS_DISABLED,
-			       NIC_SRAM_TX_BUFFER_DESC);
-	}
+	tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB,
+		       tp->tx_desc_mapping,
+		       (TG3_TX_RING_SIZE <<
+			BDINFO_FLAGS_MAXLEN_SHIFT),
+		       NIC_SRAM_TX_BUFFER_DESC);
 
 	/* There is only one receive return ring on 5705/5750, no need
 	 * to explicitly disable the others.
@@ -5243,14 +5338,14 @@ static int tg3_reset_hw(struct tg3 *tp)
 	tw32(MAC_LED_CTRL, tp->led_ctrl);
 
 	tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
-	if (tp->phy_id == PHY_ID_SERDES) {
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
 		tw32_f(MAC_RX_MODE, RX_MODE_RESET);
 		udelay(10);
 	}
 	tw32_f(MAC_RX_MODE, tp->rx_mode);
 	udelay(10);
 
-	if (tp->phy_id == PHY_ID_SERDES) {
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
 			/* Set drive transmission level to 1.2V  */
 			val = tr32(MAC_SERDES_CFG);
@@ -5268,22 +5363,8 @@ static int tg3_reset_hw(struct tg3 *tp)
 	tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, 2);
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
-	    tp->phy_id == PHY_ID_SERDES) {
-		/* Enable hardware link auto-negotiation */
-		u32 digctrl, txctrl;
-
-		digctrl = SG_DIG_USING_HW_AUTONEG | SG_DIG_CRC16_CLEAR_N |
-		    SG_DIG_LOCAL_DUPLEX_STATUS | SG_DIG_LOCAL_LINK_STATUS |
-		    (2 << SG_DIG_SPEED_STATUS_SHIFT) | SG_DIG_FIBER_MODE |
-		    SG_DIG_GBIC_ENABLE;
-
-		txctrl = tr32(MAC_SERDES_CFG);
-		tw32_f(MAC_SERDES_CFG, txctrl | MAC_SERDES_CFG_EDGE_SELECT);
-		tw32_f(SG_DIG_CTRL, digctrl | SG_DIG_SOFT_RESET);
-		tr32(SG_DIG_CTRL);
-		udelay(5);
-		tw32_f(SG_DIG_CTRL, digctrl);
-
+	    (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
+		/* Use hardware link auto-negotiation */
 		tp->tg3_flags2 |= TG3_FLG2_HW_AUTONEG;
 	}
 
@@ -5291,7 +5372,7 @@ static int tg3_reset_hw(struct tg3 *tp)
 	if (err)
 		return err;
 
-	if (tp->phy_id != PHY_ID_SERDES) {
+	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
 		u32 tmp;
 
 		/* Clear CRC stats. */
@@ -5483,7 +5564,8 @@ static void tg3_timer(unsigned long __opaque)
 				need_setup = 1;
 			}
 			if (! netif_carrier_ok(tp->dev) &&
-			    (mac_stat & MAC_STATUS_PCS_SYNCED)) {
+			    (mac_stat & (MAC_STATUS_PCS_SYNCED |
+					 MAC_STATUS_SIGNAL_DET))) {
 				need_setup = 1;
 			}
 			if (need_setup) {
@@ -5536,8 +5618,8 @@ static int tg3_open(struct net_device *dev)
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
 
-	/* If you move this call, make sure TG3_FLAG_HOST_TXDS in
-	 * tp->tg3_flags is accurate at that new place.
+	/* The placement of this call is tied
+	 * to the setup and use of Host TX descriptors.
 	 */
 	err = tg3_alloc_consistent(tp);
 	if (err)
@@ -5879,7 +5961,7 @@ static unsigned long calc_crc_errors(struct tg3 *tp)
 {
 	struct tg3_hw_stats *hw_stats = tp->hw_stats;
 
-	if (tp->phy_id != PHY_ID_SERDES &&
+	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
 	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
 	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) {
 		unsigned long flags;
@@ -6152,7 +6234,9 @@ static void tg3_set_rx_mode(struct net_device *dev)
 	struct tg3 *tp = netdev_priv(dev);
 
 	spin_lock_irq(&tp->lock);
+	spin_lock(&tp->tx_lock);
 	__tg3_set_rx_mode(dev);
+	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
 }
 
@@ -6310,7 +6394,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 		cmd->supported |= (SUPPORTED_1000baseT_Half |
 				   SUPPORTED_1000baseT_Full);
 
-	if (tp->phy_id != PHY_ID_SERDES)
+	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES))
 		cmd->supported |= (SUPPORTED_100baseT_Half |
 				  SUPPORTED_100baseT_Full |
 				  SUPPORTED_10baseT_Half |
@@ -6339,7 +6423,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 	    tp->link_config.phy_is_low_power)
 		return -EAGAIN;
 
-	if (tp->phy_id == PHY_ID_SERDES) {
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
 		/* These are the only valid advertisement bits allowed.  */
 		if (cmd->autoneg == AUTONEG_ENABLE &&
 		    (cmd->advertising & ~(ADVERTISED_1000baseT_Half |
@@ -6397,7 +6481,7 @@ static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 	if (wol->wolopts & ~WAKE_MAGIC)
 		return -EINVAL;
 	if ((wol->wolopts & WAKE_MAGIC) &&
-	    tp->phy_id == PHY_ID_SERDES &&
+	    tp->tg3_flags2 & TG3_FLG2_PHY_SERDES &&
 	    !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP))
 		return -EINVAL;
   
@@ -6493,10 +6577,9 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
 
 	tg3_halt(tp);
 	tg3_init_hw(tp);
-	netif_wake_queue(tp->dev);
+	tg3_netif_start(tp);
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
-	tg3_netif_start(tp);
   
 	return 0;
 }
@@ -6506,8 +6589,8 @@ static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam
 	struct tg3 *tp = netdev_priv(dev);
   
 	epause->autoneg = (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) != 0;
-	epause->rx_pause = (tp->tg3_flags & TG3_FLAG_PAUSE_RX) != 0;
-	epause->tx_pause = (tp->tg3_flags & TG3_FLAG_PAUSE_TX) != 0;
+	epause->rx_pause = (tp->tg3_flags & TG3_FLAG_RX_PAUSE) != 0;
+	epause->tx_pause = (tp->tg3_flags & TG3_FLAG_TX_PAUSE) != 0;
 }
   
 static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
@@ -6522,18 +6605,18 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
 	else
 		tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG;
 	if (epause->rx_pause)
-		tp->tg3_flags |= TG3_FLAG_PAUSE_RX;
+		tp->tg3_flags |= TG3_FLAG_RX_PAUSE;
 	else
-		tp->tg3_flags &= ~TG3_FLAG_PAUSE_RX;
+		tp->tg3_flags &= ~TG3_FLAG_RX_PAUSE;
 	if (epause->tx_pause)
-		tp->tg3_flags |= TG3_FLAG_PAUSE_TX;
+		tp->tg3_flags |= TG3_FLAG_TX_PAUSE;
 	else
-		tp->tg3_flags &= ~TG3_FLAG_PAUSE_TX;
+		tp->tg3_flags &= ~TG3_FLAG_TX_PAUSE;
 	tg3_halt(tp);
 	tg3_init_hw(tp);
+	tg3_netif_start(tp);
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
-	tg3_netif_start(tp);
   
 	return 0;
 }
@@ -6620,7 +6703,7 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	case SIOCGMIIREG: {
 		u32 mii_regval;
 
-		if (tp->phy_id == PHY_ID_SERDES)
+		if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
 			break;			/* We have no PHY */
 
 		spin_lock_irq(&tp->lock);
@@ -6633,7 +6716,7 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	}
 
 	case SIOCSMIIREG:
-		if (tp->phy_id == PHY_ID_SERDES)
+		if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
 			break;			/* We have no PHY */
 
 		if (!capable(CAP_NET_ADMIN))
@@ -6720,7 +6803,7 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
 {
 	int j;
 
-	if (tp->tg3_flags2 & TG3_FLG2_SUN_5704)
+	if (tp->tg3_flags2 & TG3_FLG2_SUN_570X)
 		return;
 
 	tw32_f(GRC_EEPROM_ADDR,
@@ -6807,8 +6890,8 @@ static int __devinit tg3_nvram_read(struct tg3 *tp,
 {
 	int i;
 
-	if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) {
-		printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 5704\n");
+	if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
+		printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 570X\n");
 		return -EINVAL;
 	}
 
@@ -6870,10 +6953,10 @@ static struct subsys_tbl_ent subsys_id_to_phy_id[] = {
 	{ PCI_VENDOR_ID_BROADCOM, 0x1644, PHY_ID_BCM5401 }, /* BCM95700A6 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x0001, PHY_ID_BCM5701 }, /* BCM95701A5 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x0002, PHY_ID_BCM8002 }, /* BCM95700T6 */
-	{ PCI_VENDOR_ID_BROADCOM, 0x0003, PHY_ID_SERDES  }, /* BCM95700A9 */
+	{ PCI_VENDOR_ID_BROADCOM, 0x0003, 0 },		    /* BCM95700A9 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x0005, PHY_ID_BCM5701 }, /* BCM95701T1 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x0006, PHY_ID_BCM5701 }, /* BCM95701T8 */
-	{ PCI_VENDOR_ID_BROADCOM, 0x0007, PHY_ID_SERDES  }, /* BCM95701A7 */
+	{ PCI_VENDOR_ID_BROADCOM, 0x0007, 0 },		    /* BCM95701A7 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x0008, PHY_ID_BCM5701 }, /* BCM95701A10 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x8008, PHY_ID_BCM5701 }, /* BCM95701A12 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x0009, PHY_ID_BCM5703 }, /* BCM95703Ax1 */
@@ -6882,7 +6965,7 @@ static struct subsys_tbl_ent subsys_id_to_phy_id[] = {
 	/* 3com boards. */
 	{ PCI_VENDOR_ID_3COM, 0x1000, PHY_ID_BCM5401 }, /* 3C996T */
 	{ PCI_VENDOR_ID_3COM, 0x1006, PHY_ID_BCM5701 }, /* 3C996BT */
-	{ PCI_VENDOR_ID_3COM, 0x1004, PHY_ID_SERDES  }, /* 3C996SX */
+	{ PCI_VENDOR_ID_3COM, 0x1004, 0 },		/* 3C996SX */
 	{ PCI_VENDOR_ID_3COM, 0x1007, PHY_ID_BCM5701 }, /* 3C1000T */
 	{ PCI_VENDOR_ID_3COM, 0x1008, PHY_ID_BCM5701 }, /* 3C940BR01 */
 
@@ -6895,37 +6978,43 @@ static struct subsys_tbl_ent subsys_id_to_phy_id[] = {
 	/* Compaq boards. */
 	{ PCI_VENDOR_ID_COMPAQ, 0x007c, PHY_ID_BCM5701 }, /* BANSHEE */
 	{ PCI_VENDOR_ID_COMPAQ, 0x009a, PHY_ID_BCM5701 }, /* BANSHEE_2 */
-	{ PCI_VENDOR_ID_COMPAQ, 0x007d, PHY_ID_SERDES  }, /* CHANGELING */
+	{ PCI_VENDOR_ID_COMPAQ, 0x007d, 0 },		  /* CHANGELING */
 	{ PCI_VENDOR_ID_COMPAQ, 0x0085, PHY_ID_BCM5701 }, /* NC7780 */
 	{ PCI_VENDOR_ID_COMPAQ, 0x0099, PHY_ID_BCM5701 }, /* NC7780_2 */
 
 	/* IBM boards. */
-	{ PCI_VENDOR_ID_IBM, 0x0281, PHY_ID_SERDES } /* IBM??? */
+	{ PCI_VENDOR_ID_IBM, 0x0281, 0 } /* IBM??? */
 };
 
-static int __devinit tg3_phy_probe(struct tg3 *tp)
+static inline struct subsys_tbl_ent *lookup_by_subsys(struct tg3 *tp)
 {
-	u32 eeprom_phy_id, hw_phy_id_1, hw_phy_id_2;
-	u32 hw_phy_id, hw_phy_id_masked;
-	u32 val;
-	int i, eeprom_signature_found, err;
+	int i;
 
-	tp->phy_id = PHY_ID_INVALID;
 	for (i = 0; i < ARRAY_SIZE(subsys_id_to_phy_id); i++) {
 		if ((subsys_id_to_phy_id[i].subsys_vendor ==
 		     tp->pdev->subsystem_vendor) &&
 		    (subsys_id_to_phy_id[i].subsys_devid ==
-		     tp->pdev->subsystem_device)) {
-			tp->phy_id = subsys_id_to_phy_id[i].phy_id;
-			break;
-		}
+		     tp->pdev->subsystem_device))
+			return &subsys_id_to_phy_id[i];
 	}
+	return NULL;
+}
 
+static int __devinit tg3_phy_probe(struct tg3 *tp)
+{
+	u32 eeprom_phy_id, hw_phy_id_1, hw_phy_id_2;
+	u32 hw_phy_id, hw_phy_id_masked;
+	u32 val;
+	int eeprom_signature_found, eeprom_phy_serdes, err;
+
+	tp->phy_id = PHY_ID_INVALID;
 	eeprom_phy_id = PHY_ID_INVALID;
+	eeprom_phy_serdes = 0;
 	eeprom_signature_found = 0;
 	tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
 	if (val == NIC_SRAM_DATA_SIG_MAGIC) {
 		u32 nic_cfg, led_cfg;
+		u32 nic_phy_id, cfg2;
 
 		tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
 		tp->nic_sram_data_cfg = nic_cfg;
@@ -6933,21 +7022,19 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
 		eeprom_signature_found = 1;
 
 		if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) ==
-		    NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER) {
-			eeprom_phy_id = PHY_ID_SERDES;
-		} else {
-			u32 nic_phy_id;
+		    NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER)
+			eeprom_phy_serdes = 1;
 
-			tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &nic_phy_id);
-			if (nic_phy_id != 0) {
-				u32 id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK;
-				u32 id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK;
+		tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &nic_phy_id);
+		if (nic_phy_id != 0) {
+			u32 id1 = nic_phy_id & NIC_SRAM_DATA_PHY_ID1_MASK;
+			u32 id2 = nic_phy_id & NIC_SRAM_DATA_PHY_ID2_MASK;
 
-				eeprom_phy_id  = (id1 >> 16) << 10;
-				eeprom_phy_id |= (id2 & 0xfc00) << 16;
-				eeprom_phy_id |= (id2 & 0x03ff) <<  0;
-			}
-		}
+			eeprom_phy_id  = (id1 >> 16) << 10;
+			eeprom_phy_id |= (id2 & 0xfc00) << 16;
+			eeprom_phy_id |= (id2 & 0x03ff) <<  0;
+		} else
+			eeprom_phy_id = 0;
 
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
 			tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &led_cfg);
@@ -7009,6 +7096,10 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
 		}
 		if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL)
 			tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP;
+
+		tg3_read_mem(tp, NIC_SRAM_DATA_PHY_ID, &cfg2);
+		if (cfg2 & (1 << 17))
+			tp->tg3_flags2 |= TG3_FLG2_CAPACITIVE_COUPLING;
 	}
 
 	/* Reading the PHY ID register can conflict with ASF
@@ -7035,20 +7126,31 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
 
 	if (!err && KNOWN_PHY_ID(hw_phy_id_masked)) {
 		tp->phy_id = hw_phy_id;
+		if (hw_phy_id_masked == PHY_ID_BCM8002)
+			tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
 	} else {
-		/* phy_id currently holds the value found in the
-		 * subsys_id_to_phy_id[] table or PHY_ID_INVALID
-		 * if a match was not found there.
-		 */
-		if (tp->phy_id == PHY_ID_INVALID) {
-			if (!eeprom_signature_found ||
-			    !KNOWN_PHY_ID(eeprom_phy_id & PHY_ID_MASK))
-				return -ENODEV;
+		if (eeprom_signature_found) {
 			tp->phy_id = eeprom_phy_id;
+			if (eeprom_phy_serdes)
+				tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
+		} else {
+			struct subsys_tbl_ent *p;
+
+			/* No eeprom signature?  Try the hardcoded
+			 * subsys device table.
+			 */
+			p = lookup_by_subsys(tp);
+			if (!p)
+				return -ENODEV;
+
+			tp->phy_id = p->phy_id;
+			if (!tp->phy_id ||
+			    tp->phy_id == PHY_ID_BCM8002)
+				tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
 		}
 	}
 
-	if (tp->phy_id != PHY_ID_SERDES &&
+	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
 	    !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
 		u32 bmsr, adv_reg, tg3_ctrl;
 
@@ -7105,7 +7207,7 @@ skip_phy_reset:
 	if (!eeprom_signature_found)
 		tp->led_ctrl = LED_CTRL_MODE_PHY_1;
 
-	if (tp->phy_id == PHY_ID_SERDES)
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
 		tp->link_config.advertising =
 			(ADVERTISED_1000baseT_Half |
 			 ADVERTISED_1000baseT_Full |
@@ -7124,11 +7226,11 @@ static void __devinit tg3_read_partno(struct tg3 *tp)
 	unsigned char vpd_data[256];
 	int i;
 
-	if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) {
+	if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
 		/* Sun decided not to put the necessary bits in the
 		 * NVRAM of their onboard tg3 parts :(
 		 */
-		strcpy(tp->board_part_number, "Sun 5704");
+		strcpy(tp->board_part_number, "Sun 570X");
 		return;
 	}
 
@@ -7189,27 +7291,21 @@ out_not_found:
 }
 
 #ifdef CONFIG_SPARC64
-static int __devinit tg3_is_sun_5704(struct tg3 *tp)
+static int __devinit tg3_is_sun_570X(struct tg3 *tp)
 {
 	struct pci_dev *pdev = tp->pdev;
 	struct pcidev_cookie *pcp = pdev->sysdata;
 
 	if (pcp != NULL) {
 		int node = pcp->prom_node;
-		u32 venid, devid;
+		u32 venid;
 		int err;
 
 		err = prom_getproperty(node, "subsystem-vendor-id",
 				       (char *) &venid, sizeof(venid));
 		if (err == 0 || err == -1)
 			return 0;
-		err = prom_getproperty(node, "subsystem-id",
-				       (char *) &devid, sizeof(devid));
-		if (err == 0 || err == -1)
-			return 0;
-
-		if (venid == PCI_VENDOR_ID_SUN &&
-		    devid == PCI_DEVICE_ID_TIGON3_5704)
+		if (venid == PCI_VENDOR_ID_SUN)
 			return 1;
 	}
 	return 0;
@@ -7226,8 +7322,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 	int err;
 
 #ifdef CONFIG_SPARC64
-	if (tg3_is_sun_5704(tp))
-		tp->tg3_flags2 |= TG3_FLG2_SUN_5704;
+	if (tg3_is_sun_570X(tp))
+		tp->tg3_flags2 |= TG3_FLG2_SUN_570X;
 #endif
 
 	/* If we have an AMD 762 or Intel ICH/ICH0/ICH2 chipset, write
@@ -7453,7 +7549,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 		    chiprevid == CHIPREV_ID_5701_B0 ||
 		    chiprevid == CHIPREV_ID_5701_B2 ||
 		    chiprevid == CHIPREV_ID_5701_B5) {
-			unsigned long sram_base;
+			void __iomem *sram_base;
 
 			/* Write some dummy words into the SRAM status block
 			 * area, see if it reads back correctly.  If the return
@@ -7472,32 +7568,17 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 	udelay(50);
 	tg3_nvram_init(tp);
 
-	/* Always use host TXDs, it performs better in particular
-	 * with multi-frag packets.  The tests below are kept here
-	 * as documentation should we change this decision again
-	 * in the future.
-	 */
-	tp->tg3_flags |= TG3_FLAG_HOST_TXDS;
-
-#if 0
-	/* Determine if TX descriptors will reside in
-	 * main memory or in the chip SRAM.
-	 */
-	if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
-		tp->tg3_flags |= TG3_FLAG_HOST_TXDS;
-#endif
-
 	grc_misc_cfg = tr32(GRC_MISC_CFG);
 	grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK;
 
+	/* Broadcom's driver says that CIOBE multisplit has a bug */
+#if 0
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
 	    grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5704CIOBE) {
 		tp->tg3_flags |= TG3_FLAG_SPLIT_MODE;
 		tp->split_mode_max_reqs = SPLIT_MODE_5704_MAX_REQ;
 	}
-
+#endif
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
 	    (grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788 ||
 	     grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M))
@@ -7524,7 +7605,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 
 	tg3_read_partno(tp);
 
-	if (tp->phy_id == PHY_ID_SERDES) {
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
 		tp->tg3_flags &= ~TG3_FLAG_USE_MI_INTERRUPT;
 	} else {
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
@@ -7547,13 +7628,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 	 * upon subsystem IDs.
 	 */
 	if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
-	    tp->phy_id != PHY_ID_SERDES) {
+	    !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
 		tp->tg3_flags |= (TG3_FLAG_USE_MI_INTERRUPT |
 				  TG3_FLAG_USE_LINKCHG_REG);
 	}
 
 	/* For all SERDES we poll the MAC status register. */
-	if (tp->phy_id == PHY_ID_SERDES)
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
 		tp->tg3_flags |= TG3_FLAG_POLL_SERDES;
 	else
 		tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES;
@@ -7624,7 +7705,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
 
 	mac_offset = 0x7c;
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
-	    !(tp->tg3_flags & TG3_FLG2_SUN_5704)) {
+	    !(tp->tg3_flags & TG3_FLG2_SUN_570X)) {
 		if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
 			mac_offset = 0xcc;
 		if (tg3_nvram_lock(tp))
@@ -7646,7 +7727,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
 		dev->dev_addr[5] = (lo >>  0) & 0xff;
 	}
 	/* Next, try NVRAM. */
-	else if (!(tp->tg3_flags & TG3_FLG2_SUN_5704) &&
+	else if (!(tp->tg3_flags & TG3_FLG2_SUN_570X) &&
 		 !tg3_nvram_read(tp, mac_offset + 0, &hi) &&
 		 !tg3_nvram_read(tp, mac_offset + 4, &lo)) {
 		dev->dev_addr[0] = ((hi >> 16) & 0xff);
@@ -7988,8 +8069,8 @@ static char * __devinit tg3_phy_string(struct tg3 *tp)
 	case PHY_ID_BCM5704:	return "5704";
 	case PHY_ID_BCM5705:	return "5705";
 	case PHY_ID_BCM5750:	return "5750";
-	case PHY_ID_BCM8002:	return "8002";
-	case PHY_ID_SERDES:	return "serdes";
+	case PHY_ID_BCM8002:	return "8002/serdes";
+	case 0:			return "serdes";
 	default:		return "unknown";
 	};
 }
@@ -8096,6 +8177,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
 	if (pci_using_dac)
 		dev->features |= NETIF_F_HIGHDMA;
+	dev->features |= NETIF_F_LLTX;
 #if TG3_VLAN_TAG_USED
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 	dev->vlan_rx_register = tg3_vlan_rx_register;
@@ -8141,7 +8223,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 	spin_lock_init(&tp->indirect_lock);
 	INIT_WORK(&tp->reset_task, tg3_reset_task, tp);
 
-	tp->regs = (unsigned long) ioremap(tg3reg_base, tg3reg_len);
+	tp->regs = ioremap(tg3reg_base, tg3reg_len);
 	if (tp->regs == 0UL) {
 		printk(KERN_ERR PFX "Cannot map device registers, "
 		       "aborting.\n");
@@ -8257,6 +8339,9 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 	if (tp->tg3_flags2 & TG3_FLG2_IS_5788)
 		dev->features &= ~NETIF_F_HIGHDMA;
 
+	/* flow control autonegotiation is default behavior */
+	tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
+
 	err = register_netdev(dev);
 	if (err) {
 		printk(KERN_ERR PFX "Cannot register net device, "
@@ -8288,11 +8373,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 		printk("%2.2x%c", dev->dev_addr[i],
 		       i == 5 ? '\n' : ':');
 
-	printk(KERN_INFO "%s: HostTXDS[%d] RXcsums[%d] LinkChgREG[%d] "
+	printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] "
 	       "MIirq[%d] ASF[%d] Split[%d] WireSpeed[%d] "
 	       "TSOcap[%d] \n",
 	       dev->name,
-	       (tp->tg3_flags & TG3_FLAG_HOST_TXDS) != 0,
 	       (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0,
 	       (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0,
 	       (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0,
@@ -8304,7 +8388,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 	return 0;
 
 err_out_iounmap:
-	iounmap((void *) tp->regs);
+	iounmap(tp->regs);
 
 err_out_free_dev:
 	free_netdev(dev);
@@ -8326,7 +8410,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev)
 		struct tg3 *tp = netdev_priv(dev);
 
 		unregister_netdev(dev);
-		iounmap((void *)tp->regs);
+		iounmap(tp->regs);
 		free_netdev(dev);
 		pci_release_regions(pdev);
 		pci_disable_device(pdev);
@@ -8371,11 +8455,11 @@ static int tg3_suspend(struct pci_dev *pdev, u32 state)
 		tp->timer.expires = jiffies + tp->timer_offset;
 		add_timer(&tp->timer);
 
-		spin_unlock(&tp->tx_lock);
-		spin_unlock_irq(&tp->lock);
-
 		netif_device_attach(dev);
 		tg3_netif_start(tp);
+
+		spin_unlock(&tp->tx_lock);
+		spin_unlock_irq(&tp->lock);
 	}
 
 	return err;
@@ -8408,11 +8492,11 @@ static int tg3_resume(struct pci_dev *pdev)
 
 	tg3_enable_ints(tp);
 
+	tg3_netif_start(tp);
+
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
 
-	tg3_netif_start(tp);
-
 	return 0;
 }
 
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 5c0c104f4..5a6bd6276 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -124,6 +124,7 @@
 #define  CHIPREV_ID_5705_A3		 0x3003
 #define  CHIPREV_ID_5750_A0		 0x4000
 #define  CHIPREV_ID_5750_A1		 0x4001
+#define  CHIPREV_ID_5750_A3		 0x4003
 #define  GET_ASIC_REV(CHIP_REV_ID)	((CHIP_REV_ID) >> 12)
 #define   ASIC_REV_5700			 0x07
 #define   ASIC_REV_5701			 0x00
@@ -1548,7 +1549,7 @@
  * exist only in the cards on-chip SRAM.  All 16 send bds are under
  * the same mode, they may not be configured individually.
  *
- * The mode we use is controlled by TG3_FLAG_HOST_TXDS in tp->tg3_flags.
+ * This driver always uses host memory TX descriptors.
  *
  * To use host memory TX descriptors:
  *	1) Set GRC_MODE_HOST_SENDBDS in GRC_MODE register.
@@ -1988,7 +1989,7 @@ struct tg3 {
 	spinlock_t			lock;
 	spinlock_t			indirect_lock;
 
-	unsigned long			regs;
+	void __iomem			*regs;
 	struct net_device		*dev;
 	struct pci_dev			*pdev;
 
@@ -2004,7 +2005,6 @@ struct tg3 {
 
 	spinlock_t			tx_lock;
 
-	/* TX descs are only used if TG3_FLAG_HOST_TXDS is set. */
 	struct tg3_tx_buffer_desc	*tx_ring;
 	struct tx_ring_info		*tx_buffers;
 	dma_addr_t			tx_desc_mapping;
@@ -2040,7 +2040,6 @@ struct tg3 {
 
 	u32				rx_offset;
 	u32				tg3_flags;
-#define TG3_FLAG_HOST_TXDS		0x00000001
 #define TG3_FLAG_TXD_MBOX_HWBUG		0x00000002
 #define TG3_FLAG_RX_CHECKSUMS		0x00000004
 #define TG3_FLAG_USE_LINKCHG_REG	0x00000008
@@ -2070,15 +2069,13 @@ struct tg3 {
 #define TG3_FLAG_JUMBO_ENABLE		0x00800000
 #define TG3_FLAG_10_100_ONLY		0x01000000
 #define TG3_FLAG_PAUSE_AUTONEG		0x02000000
-#define TG3_FLAG_PAUSE_RX		0x04000000
-#define TG3_FLAG_PAUSE_TX		0x08000000
 #define TG3_FLAG_BROKEN_CHECKSUMS	0x10000000
 #define TG3_FLAG_GOT_SERDES_FLOWCTL	0x20000000
 #define TG3_FLAG_SPLIT_MODE		0x40000000
 #define TG3_FLAG_INIT_COMPLETE		0x80000000
 	u32				tg3_flags2;
 #define TG3_FLG2_RESTART_TIMER		0x00000001
-#define TG3_FLG2_SUN_5704		0x00000002
+#define TG3_FLG2_SUN_570X		0x00000002
 #define TG3_FLG2_NO_ETH_WIRE_SPEED	0x00000004
 #define TG3_FLG2_IS_5788		0x00000008
 #define TG3_FLG2_MAX_RXPEND_64		0x00000010
@@ -2089,6 +2086,9 @@ struct tg3 {
 #define TG3_FLG2_PCI_EXPRESS		0x00000200
 #define TG3_FLG2_ASF_NEW_HANDSHAKE	0x00000400
 #define TG3_FLG2_HW_AUTONEG		0x00000800
+#define TG3_FLG2_PHY_JUST_INITTED	0x00001000
+#define TG3_FLG2_PHY_SERDES		0x00002000
+#define TG3_FLG2_CAPACITIVE_COUPLING	0x00004000
 
 	u32				split_mode_max_reqs;
 #define SPLIT_MODE_5704_MAX_REQ		3
@@ -2136,7 +2136,6 @@ struct tg3 {
 #define PHY_ID_BCM5705			0x600081a0
 #define PHY_ID_BCM5750			0x60008180
 #define PHY_ID_BCM8002			0x60010140
-#define PHY_ID_SERDES			0xfeedbee0
 #define PHY_ID_INVALID			0xffffffff
 #define PHY_ID_REV_MASK			0x0000000f
 #define PHY_REV_BCM5401_B0		0x1
@@ -2159,7 +2158,7 @@ struct tg3 {
 	 (X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \
 	 (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \
 	 (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \
-	 (X) == PHY_ID_BCM8002 || (X) == PHY_ID_SERDES)
+	 (X) == PHY_ID_BCM8002)
 
 	struct tg3_hw_stats		*hw_stats;
 	dma_addr_t			stats_mapping;
diff --git a/drivers/net/tokenring/Kconfig b/drivers/net/tokenring/Kconfig
index f34e40e8f..9e91287c1 100644
--- a/drivers/net/tokenring/Kconfig
+++ b/drivers/net/tokenring/Kconfig
@@ -84,7 +84,8 @@ config 3C359
 
 config TMS380TR
 	tristate "Generic TMS380 Token Ring ISA/PCI adapter support"
-	depends on TR && (PCI || ISA)
+	depends on TR && (PCI || ISA) && HOTPLUG
+	select FW_LOADER
 	---help---
 	  This driver provides generic support for token ring adapters
 	  based on the Texas Instruments TMS380 series chipsets.  This
diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
index 69e9246d8..c11a992c8 100644
--- a/drivers/net/tokenring/ibmtr.c
+++ b/drivers/net/tokenring/ibmtr.c
@@ -895,7 +895,7 @@ static int tok_open(struct net_device *dev)
 
 	ti->sram_virt &= ~1; /* to reverse what we do in tok_close */
 	/* init the spinlock */
-	ti->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
+	ti->lock = SPIN_LOCK_UNLOCKED;
 	init_timer(&ti->tr_timer);
 	
 	i = tok_init_card(dev);
diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
index ea82d131a..1ec45b2b9 100644
--- a/drivers/net/tokenring/olympic.c
+++ b/drivers/net/tokenring/olympic.c
@@ -221,6 +221,8 @@ static int __devinit olympic_probe(struct pci_dev *pdev, const struct pci_device
 
 	olympic_priv = dev->priv ;
 	
+	spin_lock_init(&olympic_priv->olympic_lock) ; 
+
 	init_waitqueue_head(&olympic_priv->srb_wait);
 	init_waitqueue_head(&olympic_priv->trb_wait);
 #if OLYMPIC_DEBUG  
@@ -291,7 +293,7 @@ op_disable_dev:
 static int __devinit olympic_init(struct net_device *dev)
 {
     	struct olympic_private *olympic_priv;
-	u8 *olympic_mmio, *init_srb,*adapter_addr;
+	u8 __iomem *olympic_mmio, *init_srb,*adapter_addr;
 	unsigned long t; 
 	unsigned int uaa_addr;
 
@@ -311,7 +313,6 @@ static int __devinit olympic_init(struct net_device *dev)
 		}
 	}
 
-	spin_lock_init(&olympic_priv->olympic_lock) ; 
 
 	/* Needed for cardbus */
 	if(!(readl(olympic_mmio+BCTL) & BCTL_MODE_INDICATOR)) {
@@ -435,13 +436,15 @@ static int __devinit olympic_init(struct net_device *dev)
 static int olympic_open(struct net_device *dev) 
 {
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
-	u8 *olympic_mmio=olympic_priv->olympic_mmio,*init_srb;
+	u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio,*init_srb;
 	unsigned long flags, t;
 	char open_error[255] ; 
 	int i, open_finished = 1 ;
 
 	DECLARE_WAITQUEUE(wait,current) ; 
 
+	olympic_init(dev);
+
 	if(request_irq(dev->irq, &olympic_interrupt, SA_SHIRQ , "olympic", dev)) {
 		return -EAGAIN;
 	}
@@ -706,10 +709,10 @@ static int olympic_open(struct net_device *dev)
 #endif
 
 	if (olympic_priv->olympic_network_monitor) { 
-		u8 *oat ; 
-		u8 *opt ; 
-		oat = (u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; 
-		opt = (u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; 
+		u8 __iomem *oat ; 
+		u8 __iomem *opt ; 
+		oat = (olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; 
+		opt = (olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; 
 
 		printk("%s: Node Address: %02x:%02x:%02x:%02x:%02x:%02x\n",dev->name, 
 			readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)), 
@@ -755,7 +758,7 @@ static int olympic_open(struct net_device *dev)
 static void olympic_rx(struct net_device *dev)
 {
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
-	u8 *olympic_mmio=olympic_priv->olympic_mmio;
+	u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio;
 	struct olympic_rx_status *rx_status;
 	struct olympic_rx_desc *rx_desc ; 
 	int rx_ring_last_received,length, buffer_cnt, cpy_length, frag_len;
@@ -898,7 +901,10 @@ static void olympic_freemem(struct net_device *dev)
 	int i;
 			
 	for(i=0;i<OLYMPIC_RX_RING_SIZE;i++) {
-		dev_kfree_skb_irq(olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received]);
+		if (olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received] != NULL) {
+			dev_kfree_skb_irq(olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received]);
+			olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received] = NULL;
+		}
 		if (olympic_priv->olympic_rx_ring[olympic_priv->rx_status_last_received].buffer != 0xdeadbeef) {
 			pci_unmap_single(olympic_priv->pdev, 
 			le32_to_cpu(olympic_priv->olympic_rx_ring[olympic_priv->rx_status_last_received].buffer),
@@ -925,9 +931,9 @@ static irqreturn_t olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs
 {
 	struct net_device *dev= (struct net_device *)dev_id;
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
-	u8 *olympic_mmio=olympic_priv->olympic_mmio;
+	u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio;
 	u32 sisr;
-	u8 *adapter_check_area ; 
+	u8 __iomem *adapter_check_area ; 
 	
 	/* 
 	 *  Read sisr but don't reset it yet. 
@@ -944,9 +950,6 @@ static irqreturn_t olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs
 	/* Hotswap gives us this on removal */
 	if (sisr == 0xffffffff) { 
 		printk(KERN_WARNING "%s: Hotswap adapter removal.\n",dev->name) ; 
-		olympic_freemem(dev) ; 
-		free_irq(dev->irq, dev) ;
-		dev->stop = NULL ;  
 		spin_unlock(&olympic_priv->olympic_lock) ; 
 		return IRQ_NONE;
 	} 
@@ -961,9 +964,7 @@ static irqreturn_t olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs
 			printk(KERN_ERR "The adapter must be reset to clear this condition.\n") ; 
 			printk(KERN_ERR "Please report this error to the driver maintainer and/\n") ; 
 			printk(KERN_ERR "or the linux-tr mailing list.\n") ; 
-			olympic_freemem(dev) ; 
-			free_irq(dev->irq, dev) ;
-			dev->stop = NULL ;  
+			wake_up_interruptible(&olympic_priv->srb_wait);
 			spin_unlock(&olympic_priv->olympic_lock) ; 
 			return IRQ_HANDLED;
 		} /* SISR_ERR */
@@ -1006,9 +1007,6 @@ static irqreturn_t olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs
 			writel(readl(olympic_mmio+LAPWWC),olympic_mmio+LAPA);
 			adapter_check_area = olympic_priv->olympic_lap + ((readl(olympic_mmio+LAPWWC)) & (~0xf800)) ;
 			printk(KERN_WARNING "%s: Bytes %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",dev->name, readb(adapter_check_area+0), readb(adapter_check_area+1), readb(adapter_check_area+2), readb(adapter_check_area+3), readb(adapter_check_area+4), readb(adapter_check_area+5), readb(adapter_check_area+6), readb(adapter_check_area+7)) ; 
-			olympic_freemem(dev) ;
-			free_irq(dev->irq, dev) ;
-			dev->stop = NULL ;  
 			spin_unlock(&olympic_priv->olympic_lock) ; 
 			return IRQ_HANDLED; 
 		} /* SISR_ADAPTER_CHECK */
@@ -1049,7 +1047,7 @@ static irqreturn_t olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs
 static int olympic_xmit(struct sk_buff *skb, struct net_device *dev) 
 {
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
-	u8 *olympic_mmio=olympic_priv->olympic_mmio;
+	u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio;
 	unsigned long flags ; 
 
 	spin_lock_irqsave(&olympic_priv->olympic_lock, flags);
@@ -1080,7 +1078,7 @@ static int olympic_xmit(struct sk_buff *skb, struct net_device *dev)
 static int olympic_close(struct net_device *dev) 
 {
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
-    	u8 *olympic_mmio=olympic_priv->olympic_mmio,*srb;
+	u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio,*srb;
 	unsigned long t,flags;
 
 	DECLARE_WAITQUEUE(wait,current) ; 
@@ -1094,34 +1092,32 @@ static int olympic_close(struct net_device *dev)
 	writeb(0,srb+1);
 	writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
 
+	add_wait_queue(&olympic_priv->srb_wait,&wait) ;
+	set_current_state(TASK_INTERRUPTIBLE) ; 
+
 	spin_lock_irqsave(&olympic_priv->olympic_lock,flags);
 	olympic_priv->srb_queued=1;
 
 	writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
 	spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags);
-	
-	t = jiffies ; 
-
-	add_wait_queue(&olympic_priv->srb_wait,&wait) ;
-	set_current_state(TASK_INTERRUPTIBLE) ; 
 
 	while(olympic_priv->srb_queued) {
-		schedule() ; 
+
+		t = schedule_timeout(60*HZ); 
+
         	if(signal_pending(current))	{            
 			printk(KERN_WARNING "%s: SRB timed out.\n",dev->name);
             		printk(KERN_WARNING "SISR=%x MISR=%x\n",readl(olympic_mmio+SISR),readl(olympic_mmio+LISR));
             		olympic_priv->srb_queued=0;
             		break;
         	}
-		if ((jiffies-t) > 60*HZ) { 
+
+		if (t == 0) { 
 			printk(KERN_WARNING "%s: SRB timed out. May not be fatal. \n",dev->name) ; 
-			olympic_priv->srb_queued=0;
-			break ; 
 		} 
-		set_current_state(TASK_INTERRUPTIBLE) ; 
+		olympic_priv->srb_queued=0;
     	}
 	remove_wait_queue(&olympic_priv->srb_wait,&wait) ; 
-	set_current_state(TASK_RUNNING) ; 
 
 	olympic_priv->rx_status_last_received++;
 	olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1;
@@ -1152,9 +1148,9 @@ static int olympic_close(struct net_device *dev)
 static void olympic_set_rx_mode(struct net_device *dev) 
 {
 	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; 
-   	u8 *olympic_mmio = olympic_priv->olympic_mmio ; 
+   	u8 __iomem *olympic_mmio = olympic_priv->olympic_mmio ; 
 	u8 options = 0; 
-	u8 *srb;
+	u8 __iomem *srb;
 	struct dev_mc_list *dmi ; 
 	unsigned char dev_mc_address[4] ; 
 	int i ; 
@@ -1220,8 +1216,8 @@ static void olympic_set_rx_mode(struct net_device *dev)
 static void olympic_srb_bh(struct net_device *dev) 
 { 
 	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; 
-   	u8 *olympic_mmio = olympic_priv->olympic_mmio ; 
-	u8 *srb;
+   	u8 __iomem *olympic_mmio = olympic_priv->olympic_mmio ; 
+	u8 __iomem *srb;
 
 	writel(olympic_priv->srb,olympic_mmio+LAPA);
 	srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800));
@@ -1394,22 +1390,22 @@ static int olympic_set_mac_address (struct net_device *dev, void *addr)
 static void olympic_arb_cmd(struct net_device *dev)
 {
 	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv;
-    	u8 *olympic_mmio=olympic_priv->olympic_mmio;
-	u8 *arb_block, *asb_block, *srb  ; 
+	u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio;
+	u8 __iomem *arb_block, *asb_block, *srb  ; 
 	u8 header_len ; 
 	u16 frame_len, buffer_len ;
 	struct sk_buff *mac_frame ;  
-	u8 *buf_ptr ;
-	u8 *frame_data ;  
+	u8 __iomem *buf_ptr ;
+	u8 __iomem *frame_data ;  
 	u16 buff_off ; 
 	u16 lan_status = 0, lan_status_diff  ; /* Initialize to stop compiler warning */
 	u8 fdx_prot_error ; 
 	u16 next_ptr;
 	int i ; 
 
-	arb_block = (u8 *)(olympic_priv->olympic_lap + olympic_priv->arb) ; 
-	asb_block = (u8 *)(olympic_priv->olympic_lap + olympic_priv->asb) ; 
-	srb = (u8 *)(olympic_priv->olympic_lap + olympic_priv->srb) ; 
+	arb_block = (olympic_priv->olympic_lap + olympic_priv->arb) ; 
+	asb_block = (olympic_priv->olympic_lap + olympic_priv->asb) ; 
+	srb = (olympic_priv->olympic_lap + olympic_priv->srb) ; 
 	
 	if (readb(arb_block+0) == ARB_RECEIVE_DATA) { /* Receive.data, MAC frames */
 
@@ -1513,29 +1509,6 @@ drop_frame:
 			writel(readl(olympic_mmio+BCTL)&~(3<<13),olympic_mmio+BCTL);
 			netif_stop_queue(dev);
 			olympic_priv->srb = readw(olympic_priv->olympic_lap + LAPWWO) ; 
-			for(i=0;i<OLYMPIC_RX_RING_SIZE;i++) {
-				dev_kfree_skb_irq(olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received]);
-				if (olympic_priv->olympic_rx_ring[olympic_priv->rx_status_last_received].buffer != 0xdeadbeef) {
-					pci_unmap_single(olympic_priv->pdev, 
-						le32_to_cpu(olympic_priv->olympic_rx_ring[olympic_priv->rx_status_last_received].buffer),
-						olympic_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE);
-				}
-				olympic_priv->rx_status_last_received++;
-				olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1;
-			}
-			/* unmap rings */
-			pci_unmap_single(olympic_priv->pdev, olympic_priv->rx_status_ring_dma_addr, 
-				sizeof(struct olympic_rx_status) * OLYMPIC_RX_RING_SIZE, PCI_DMA_FROMDEVICE);
-			pci_unmap_single(olympic_priv->pdev, olympic_priv->rx_ring_dma_addr,
-				sizeof(struct olympic_rx_desc) * OLYMPIC_RX_RING_SIZE, PCI_DMA_TODEVICE);
-
-			pci_unmap_single(olympic_priv->pdev, olympic_priv->tx_status_ring_dma_addr, 
-				sizeof(struct olympic_tx_status) * OLYMPIC_TX_RING_SIZE, PCI_DMA_FROMDEVICE);
-			pci_unmap_single(olympic_priv->pdev, olympic_priv->tx_ring_dma_addr, 
-				sizeof(struct olympic_tx_desc) * OLYMPIC_TX_RING_SIZE, PCI_DMA_TODEVICE);
-
-			free_irq(dev->irq,dev);
-			dev->stop=NULL;
 			printk(KERN_WARNING "%s: Adapter has been closed \n", dev->name) ; 
 		} /* If serious error */
 		
@@ -1604,10 +1577,10 @@ drop_frame:
 static void olympic_asb_bh(struct net_device *dev) 
 {
 	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; 
-	u8 *arb_block, *asb_block ; 
+	u8 __iomem *arb_block, *asb_block ; 
 
-	arb_block = (u8 *)(olympic_priv->olympic_lap + olympic_priv->arb) ; 
-	asb_block = (u8 *)(olympic_priv->olympic_lap + olympic_priv->asb) ; 
+	arb_block = (olympic_priv->olympic_lap + olympic_priv->arb) ; 
+	asb_block = (olympic_priv->olympic_lap + olympic_priv->asb) ; 
 
 	if (olympic_priv->asb_queued == 1) {   /* Dropped through the first time */
 
@@ -1666,8 +1639,8 @@ static int olympic_proc_info(char *buffer, char **start, off_t offset, int lengt
 {
 	struct net_device *dev = (struct net_device *)data ; 
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
-	u8 *oat = (u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; 
-	u8 *opt = (u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; 
+	u8 __iomem *oat = (olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; 
+	u8 __iomem *opt = (olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; 
 	int size = 0 ; 
 	int len=0;
 	off_t begin=0;
diff --git a/drivers/net/tokenring/olympic.h b/drivers/net/tokenring/olympic.h
index e209b79d6..2fc59c997 100644
--- a/drivers/net/tokenring/olympic.h
+++ b/drivers/net/tokenring/olympic.h
@@ -251,8 +251,8 @@ struct olympic_private {
 	u16 arb;      /* be16 */
 	u16 asb;      /* be16 */
 
-	u8 *olympic_mmio;
-	u8 *olympic_lap;
+	u8 __iomem *olympic_mmio;
+	u8 __iomem *olympic_lap;
 	struct pci_dev *pdev ; 
 	char *olympic_card_name ; 
 
diff --git a/drivers/net/tulip/Kconfig b/drivers/net/tulip/Kconfig
index 6182cf4e3..e2cdaf876 100644
--- a/drivers/net/tulip/Kconfig
+++ b/drivers/net/tulip/Kconfig
@@ -40,9 +40,7 @@ config TULIP
 	  (smc9332dst), you can also try the driver for "Generic DECchip"
 	  cards, above.  However, most people with a network card of this type
 	  will say Y here.) Do read the Ethernet-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>.  More specific
-	  information is contained in 
-	  <file:Documentation/networking/tulip.txt>.
+	  <http://www.tldp.org/docs.html#howto>.
 
 	  To compile this driver as a module, choose M here and read
 	  <file:Documentation/networking/net-modules.txt>.  The module will
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index 962138008..05e8947f9 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -1141,7 +1141,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
 	lp->asBitValid = TRUE;
 	lp->timeout = -1;
 	lp->gendev = gendev;
-	lp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
+	lp->lock = SPIN_LOCK_UNLOCKED;
 	init_timer(&lp->timer);
 	de4x5_parse_params(dev);
 
@@ -1316,7 +1316,7 @@ de4x5_open(struct net_device *dev)
     ** Re-initialize the DE4X5... 
     */
     status = de4x5_init(dev);
-    lp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
+    lp->lock = SPIN_LOCK_UNLOCKED;
     lp->state = OPEN;
     de4x5_dbg_open(dev);
     
@@ -2242,8 +2242,13 @@ static int __devinit de4x5_pci_probe (struct pci_dev *pdev,
 		return -ENODEV;
 
 	/* Ok, the device seems to be for us. */
-	if (!(dev = alloc_etherdev (sizeof (struct de4x5_private))))
-		return -ENOMEM;
+	if (pci_enable_device (pdev))
+		return -ENODEV;
+
+	if (!(dev = alloc_etherdev (sizeof (struct de4x5_private)))) {
+		error = -ENOMEM;
+		goto disable_dev;
+	}
 
 	lp = netdev_priv(dev);
 	lp->bus = PCI;
@@ -2327,6 +2332,8 @@ static int __devinit de4x5_pci_probe (struct pci_dev *pdev,
 	release_region (iobase, DE4X5_PCI_TOTAL_SIZE);
  free_dev:
 	free_netdev (dev);
+ disable_dev:
+	pci_disable_device (pdev);
 	return error;
 }
 
@@ -2341,6 +2348,7 @@ static void __devexit de4x5_pci_remove (struct pci_dev *pdev)
 	unregister_netdev (dev);
 	free_netdev (dev);
 	release_region (iobase, DE4X5_PCI_TOTAL_SIZE);
+	pci_disable_device (pdev);
 }
 
 static struct pci_device_id de4x5_pci_tbl[] = {
diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c
index f3298d161..7353f28cc 100644
--- a/drivers/net/tulip/dmfe.c
+++ b/drivers/net/tulip/dmfe.c
@@ -314,13 +314,13 @@ static u16 phy_read_1bit(unsigned long);
 static u8 dmfe_sense_speed(struct dmfe_board_info *);
 static void dmfe_process_mode(struct dmfe_board_info *);
 static void dmfe_timer(unsigned long);
+static inline u32 cal_CRC(unsigned char *, unsigned int, u8);
 static void dmfe_rx_packet(struct DEVICE *, struct dmfe_board_info *);
 static void dmfe_free_tx_pkt(struct DEVICE *, struct dmfe_board_info *);
 static void dmfe_reuse_skb(struct dmfe_board_info *, struct sk_buff *);
 static void dmfe_dynamic_reset(struct DEVICE *);
 static void dmfe_free_rxbuffer(struct dmfe_board_info *);
 static void dmfe_init_dm910x(struct DEVICE *);
-static inline u32 cal_CRC(unsigned char *, unsigned int, u8);
 static void dmfe_parse_srom(struct dmfe_board_info *);
 static void dmfe_program_DM9801(struct dmfe_board_info *, int);
 static void dmfe_program_DM9802(struct dmfe_board_info *);
@@ -884,6 +884,20 @@ static void dmfe_free_tx_pkt(struct DEVICE *dev, struct dmfe_board_info * db)
 }
 
 
+/*
+ *	Calculate the CRC valude of the Rx packet
+ *	flag = 	1 : return the reverse CRC (for the received packet CRC)
+ *		0 : return the normal CRC (for Hash Table index)
+ */
+
+static inline u32 cal_CRC(unsigned char * Data, unsigned int Len, u8 flag)
+{
+	u32 crc = crc32(~0, Data, Len);
+	if (flag) crc = ~crc;
+	return crc;
+}
+
+
 /*
  *	Receive the come packet and pass to upper layer
  */
@@ -1773,20 +1787,6 @@ static u16 phy_read_1bit(unsigned long ioaddr)
 }
 
 
-/*
- *	Calculate the CRC valude of the Rx packet
- *	flag = 	1 : return the reverse CRC (for the received packet CRC)
- *		0 : return the normal CRC (for Hash Table index)
- */
-
-static inline u32 cal_CRC(unsigned char * Data, unsigned int Len, u8 flag)
-{
-	u32 crc = crc32(~0, Data, Len);
-	if (flag) crc = ~crc;
-	return crc;
-}
-
-
 /*
  *	Parser SROM and media mode
  */
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 142f5f52f..ea5643afd 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -248,11 +248,11 @@ struct typhoon {
 	/* Tx cache line section */
 	struct transmit_ring 	txLoRing	____cacheline_aligned;	
 	struct pci_dev *	tx_pdev;
-	unsigned long		tx_ioaddr;
+	void __iomem		*tx_ioaddr;
 	u32			txlo_dma_addr;
 
 	/* Irq/Rx cache line section */
-	unsigned long		ioaddr		____cacheline_aligned;
+	void __iomem		*ioaddr		____cacheline_aligned;
 	struct typhoon_indexes *indexes;
 	u8			awaiting_resp;
 	u8			duplex;
@@ -373,7 +373,7 @@ typhoon_inc_rx_index(u32 *index, const int count)
 }
 
 static int
-typhoon_reset(unsigned long ioaddr, int wait_type)
+typhoon_reset(void __iomem *ioaddr, int wait_type)
 {
 	int i, err = 0;
 	int timeout;
@@ -428,7 +428,7 @@ out:
 }
 
 static int
-typhoon_wait_status(unsigned long ioaddr, u32 wait_value)
+typhoon_wait_status(void __iomem *ioaddr, u32 wait_value)
 {
 	int i, err = 0;
 
@@ -1240,7 +1240,7 @@ typhoon_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 }
 
 static int
-typhoon_wait_interrupt(unsigned long ioaddr)
+typhoon_wait_interrupt(void __iomem *ioaddr)
 {
 	int i, err = 0;
 
@@ -1348,7 +1348,7 @@ typhoon_init_rings(struct typhoon *tp)
 static int
 typhoon_download_firmware(struct typhoon *tp)
 {
-	unsigned long ioaddr = tp->ioaddr;
+	void __iomem *ioaddr = tp->ioaddr;
 	struct pci_dev *pdev = tp->pdev;
 	struct typhoon_file_header *fHdr;
 	struct typhoon_section_header *sHdr;
@@ -1497,7 +1497,7 @@ err_out:
 static int
 typhoon_boot_3XP(struct typhoon *tp, u32 initial_status)
 {
-	unsigned long ioaddr = tp->ioaddr;
+	void __iomem *ioaddr = tp->ioaddr;
 
 	if(typhoon_wait_status(ioaddr, initial_status) < 0) {
 		printk(KERN_ERR "%s: boot ready timeout\n", tp->name);
@@ -1812,7 +1812,8 @@ static irqreturn_t
 typhoon_interrupt(int irq, void *dev_instance, struct pt_regs *rgs)
 {
 	struct net_device *dev = (struct net_device *) dev_instance;
-	unsigned long ioaddr = dev->base_addr;
+	struct typhoon *tp = dev->priv;
+	void __iomem *ioaddr = tp->ioaddr;
 	u32 intr_status;
 
 	intr_status = readl(ioaddr + TYPHOON_REG_INTR_STATUS);
@@ -1852,7 +1853,7 @@ static int
 typhoon_sleep(struct typhoon *tp, int state, u16 events)
 {
 	struct pci_dev *pdev = tp->pdev;
-	unsigned long ioaddr = tp->ioaddr;
+	void __iomem *ioaddr = tp->ioaddr;
 	struct cmd_desc xp_cmd;
 	int err;
 
@@ -1890,7 +1891,7 @@ static int
 typhoon_wakeup(struct typhoon *tp, int wait_type)
 {
 	struct pci_dev *pdev = tp->pdev;
-	unsigned long ioaddr = tp->ioaddr;
+	void __iomem *ioaddr = tp->ioaddr;
 
 	pci_set_power_state(pdev, 0);
 	pci_restore_state(pdev, tp->pci_state);
@@ -1911,7 +1912,7 @@ static int
 typhoon_start_runtime(struct typhoon *tp)
 {
 	struct net_device *dev = tp->dev;
-	unsigned long ioaddr = tp->ioaddr;
+	void __iomem *ioaddr = tp->ioaddr;
 	struct cmd_desc xp_cmd;
 	int err;
 
@@ -2006,7 +2007,7 @@ typhoon_stop_runtime(struct typhoon *tp, int wait_type)
 {
 	struct typhoon_indexes *indexes = tp->indexes;
 	struct transmit_ring *txLo = &tp->txLoRing;
-	unsigned long ioaddr = tp->ioaddr;
+	void __iomem *ioaddr = tp->ioaddr;
 	struct cmd_desc xp_cmd;
 	int i;
 
@@ -2070,7 +2071,7 @@ typhoon_tx_timeout(struct net_device *dev)
 {
 	struct typhoon *tp = (struct typhoon *) dev->priv;
 
-	if(typhoon_reset(dev->base_addr, WaitNoSleep) < 0) {
+	if(typhoon_reset(tp->ioaddr, WaitNoSleep) < 0) {
 		printk(KERN_WARNING "%s: could not reset in tx timeout\n",
 					dev->name);
 		goto truely_dead;
@@ -2091,7 +2092,7 @@ typhoon_tx_timeout(struct net_device *dev)
 
 truely_dead:
 	/* Reset the hardware, and turn off carrier to avoid more timeouts */
-	typhoon_reset(dev->base_addr, NoWait);
+	typhoon_reset(tp->ioaddr, NoWait);
 	netif_carrier_off(dev);
 }
 
@@ -2126,7 +2127,7 @@ out_sleep:
 	if(typhoon_boot_3XP(tp, TYPHOON_STATUS_WAITING_FOR_HOST) < 0) {
 		printk(KERN_ERR "%s: unable to reboot into sleep img\n",
 				dev->name);
-		typhoon_reset(dev->base_addr, NoWait);
+		typhoon_reset(tp->ioaddr, NoWait);
 		goto out;
 	}
 
@@ -2192,7 +2193,7 @@ typhoon_resume(struct pci_dev *pdev)
 	return 0;
 
 reset:
-	typhoon_reset(dev->base_addr, NoWait);
+	typhoon_reset(tp->ioaddr, NoWait);
 	return -EBUSY;
 }
 
@@ -2276,6 +2277,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	struct typhoon *tp;
 	int card_id = (int) ent->driver_data;
 	unsigned long ioaddr;
+	void __iomem *ioaddr_mapped;
 	void *shared;
 	dma_addr_t shared_dma;
 	struct cmd_desc xp_cmd;
@@ -2345,14 +2347,13 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	/* map our MMIO region
 	 */
 	ioaddr = pci_resource_start(pdev, 1);
-	ioaddr = (unsigned long) ioremap(ioaddr, 128);
-	if(!ioaddr) {
+	ioaddr_mapped = ioremap(ioaddr, 128);
+	if (!ioaddr_mapped) {
 		printk(ERR_PFX "%s: cannot remap MMIO, aborting\n",
 		       pci_name(pdev));
 		err = -EIO;
 		goto error_out_regions;
 	}
-	dev->base_addr = ioaddr;
 
 	/* allocate pci dma space for rx and tx descriptor rings
 	 */
@@ -2371,8 +2372,8 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	tp->shared_dma = shared_dma;
 	tp->pdev = pdev;
 	tp->tx_pdev = pdev;
-	tp->ioaddr = dev->base_addr;
-	tp->tx_ioaddr = dev->base_addr;
+	tp->ioaddr = ioaddr_mapped;
+	tp->tx_ioaddr = ioaddr_mapped;
 	tp->dev = dev;
 
 	/* need to be able to restore PCI state after a suspend */
@@ -2385,7 +2386,7 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	 * 4) Get the hardware address.
 	 * 5) Put the card to sleep.
 	 */
-	if(typhoon_reset(ioaddr, WaitSleep) < 0) {
+	if (typhoon_reset(ioaddr_mapped, WaitSleep) < 0) {
 		printk(ERR_PFX "%s: could not reset 3XP\n", pci_name(pdev));
 		err = -EIO;
 		goto error_out_dma;
@@ -2518,13 +2519,13 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	return 0;
 
 error_out_reset:
-	typhoon_reset(ioaddr, NoWait);
+	typhoon_reset(ioaddr_mapped, NoWait);
 
 error_out_dma:
 	pci_free_consistent(pdev, sizeof(struct typhoon_shared),
 			    shared, shared_dma);
 error_out_remap:
-	iounmap((void *) ioaddr);
+	iounmap(ioaddr_mapped);
 error_out_regions:
 	pci_release_regions(pdev);
 error_out_dev:
@@ -2542,8 +2543,8 @@ typhoon_remove_one(struct pci_dev *pdev)
 	unregister_netdev(dev);
 	pci_set_power_state(pdev, 0);
 	pci_restore_state(pdev, tp->pci_state);
-	typhoon_reset(dev->base_addr, NoWait);
-	iounmap((char *) (dev->base_addr));
+	typhoon_reset(tp->ioaddr, NoWait);
+	iounmap(tp->ioaddr);
 	pci_free_consistent(pdev, sizeof(struct typhoon_shared),
 			    tp->shared, tp->shared_dma);
 	pci_release_regions(pdev);
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index 6c9206301..20bfbb9c7 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -125,11 +125,16 @@
 	LK1.1.19 (Roger Luethi)
 	- Increase Tx threshold for unspecified errors
 
+	LK1.2.0-2.6 (Roger Luethi)
+	- Massive clean-up
+	- Rewrite PHY, media handling (remove options, full_duplex, backoff)
+	- Fix Tx engine race for good
+
 */
 
 #define DRV_NAME	"via-rhine"
-#define DRV_VERSION	"1.1.20-2.6"
-#define DRV_RELDATE	"May-23-2004"
+#define DRV_VERSION	"1.2.0-2.6"
+#define DRV_RELDATE	"June-10-2004"
 
 
 /* A few user-configurable values.
@@ -142,22 +147,10 @@ static int max_interrupt_work = 20;
    Setting to > 1518 effectively disables this feature. */
 static int rx_copybreak;
 
-/* Select a backoff algorithm (Ethernet capture effect) */
-static int backoff;
-
-/* Used to pass the media type, etc.
-   Both 'options[]' and 'full_duplex[]' should exist for driver
-   interoperability.
-   The media type is usually passed in 'options[]'.
-   The default is autonegotiation for speed and duplex.
-     This should rarely be overridden.
-   Use option values 0x10/0x20 for 10Mbps, 0x100,0x200 for 100Mbps.
-   Use option values 0x10 and 0x100 for forcing half duplex fixed speed.
-   Use option values 0x20 and 0x200 for forcing full duplex operation.
-*/
-#define MAX_UNITS	8	/* More are supported, limit only on options */
-static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+/*
+ * In case you are looking for 'options[]' or 'full_duplex[]', they
+ * are gone. Use ethtool(8) instead.
+ */
 
 /* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
    The Rhine has a 64 element 8390-like hash table. */
@@ -210,9 +203,6 @@ static const int multicast_filter_limit = 32;
 static char version[] __devinitdata =
 KERN_INFO DRV_NAME ".c:v1.10-LK" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n";
 
-static char shortname[] = DRV_NAME;
-
-
 /* This driver was written to use PCI memory space. Some early versions
    of the Rhine may only work correctly with I/O space accesses. */
 #ifdef CONFIG_VIA_RHINE_MMIO
@@ -239,15 +229,9 @@ MODULE_LICENSE("GPL");
 MODULE_PARM(max_interrupt_work, "i");
 MODULE_PARM(debug, "i");
 MODULE_PARM(rx_copybreak, "i");
-MODULE_PARM(backoff, "i");
-MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM_DESC(max_interrupt_work, "VIA Rhine maximum events handled per interrupt");
 MODULE_PARM_DESC(debug, "VIA Rhine debug level (0-7)");
 MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames");
-MODULE_PARM_DESC(backoff, "VIA Rhine: Bits 0-3: backoff algorithm");
-MODULE_PARM_DESC(options, "VIA Rhine: Bits 0-3: media type, bit 17: full duplex");
-MODULE_PARM_DESC(full_duplex, "VIA Rhine full duplex setting(s) (1)");
 
 /*
 		Theory of Operation
@@ -350,24 +334,24 @@ The chip does not pad to minimum transmit length.
 
 enum rhine_revs {
 	VT86C100A	= 0x00,
+	VTunknown0	= 0x20,
 	VT6102		= 0x40,
 	VT8231		= 0x50,	/* Integrated MAC */
 	VT8233		= 0x60,	/* Integrated MAC */
 	VT8235		= 0x74,	/* Integrated MAC */
 	VT8237		= 0x78,	/* Integrated MAC */
-	VTunknown0	= 0x7C,
+	VTunknown1	= 0x7C,
 	VT6105		= 0x80,
 	VT6105_B0	= 0x83,
 	VT6105L		= 0x8A,
 	VT6107		= 0x8C,
-	VTunknown1	= 0x8E,
-	VT6105M		= 0x90,
+	VTunknown2	= 0x8E,
+	VT6105M		= 0x90,	/* Management adapter */
 };
 
 enum rhine_quirks {
 	rqWOL		= 0x0001,	/* Wake-On-LAN support */
 	rqForceReset	= 0x0002,
-	rqDavicomPhy	= 0x0020,
 	rq6patterns	= 0x0040,	/* 6 instead of 4 patterns for WOL */
 	rqStatusWBRace	= 0x0080,	/* Tx Status Writeback Error possible */
 	rqRhineI	= 0x0100,	/* See comment below */
@@ -395,6 +379,7 @@ MODULE_DEVICE_TABLE(pci, rhine_pci_tbl);
 /* Offsets to the device registers. */
 enum register_offsets {
 	StationAddr=0x00, RxConfig=0x06, TxConfig=0x07, ChipCmd=0x08,
+	ChipCmd1=0x09,
 	IntrStatus=0x0C, IntrEnable=0x0E,
 	MulticastFilter0=0x10, MulticastFilter1=0x14,
 	RxRingPtr=0x18, TxRingPtr=0x1C, GFIFOTest=0x54,
@@ -403,8 +388,8 @@ enum register_offsets {
 	ConfigA=0x78, ConfigB=0x79, ConfigC=0x7A, ConfigD=0x7B,
 	RxMissed=0x7C, RxCRCErrs=0x7E, MiscCmd=0x81,
 	StickyHW=0x83, IntrStatus2=0x84,
-	WOLcrSet=0xA0, WOLcrClr=0xA4, WOLcrClr1=0xA6,
-	WOLcgClr=0xA7,
+	WOLcrSet=0xA0, PwcfgSet=0xA1, WOLcgSet=0xA3, WOLcrClr=0xA4,
+	WOLcrClr1=0xA6, WOLcgClr=0xA7,
 	PwrcsrSet=0xA8, PwrcsrSet1=0xA9, PwrcsrClr=0xAC, PwrcsrClr1=0xAD,
 };
 
@@ -436,6 +421,15 @@ enum intr_status_bits {
 	IntrTxErrSummary=0x082218,
 };
 
+/* Bits in WOLcrSet/WOLcrClr and PwrcsrSet/PwrcsrClr */
+enum wol_bits {
+	WOLucast	= 0x10,
+	WOLmagic	= 0x20,
+	WOLbmcast	= 0x30,
+	WOLlnkon	= 0x40,
+	WOLlnkoff	= 0x80,
+};
+
 /* The Rx and Tx buffer descriptors. */
 struct rx_desc {
 	s32 rx_status;
@@ -464,13 +458,12 @@ enum desc_status_bits {
 
 /* Bits in ChipCmd. */
 enum chip_cmd_bits {
-	CmdInit=0x0001, CmdStart=0x0002, CmdStop=0x0004, CmdRxOn=0x0008,
-	CmdTxOn=0x0010, CmdTxDemand=0x0020, CmdRxDemand=0x0040,
-	CmdEarlyRx=0x0100, CmdEarlyTx=0x0200, CmdFDuplex=0x0400,
-	CmdNoTxPoll=0x0800, CmdReset=0x8000,
+	CmdInit=0x01, CmdStart=0x02, CmdStop=0x04, CmdRxOn=0x08,
+	CmdTxOn=0x10, Cmd1TxDemand=0x20, CmdRxDemand=0x40,
+	Cmd1EarlyRx=0x01, Cmd1EarlyTx=0x02, Cmd1FDuplex=0x04,
+	Cmd1NoTxPoll=0x08, Cmd1Reset=0x80,
 };
 
-#define MAX_MII_CNT	4
 struct rhine_private {
 	/* Descriptor rings */
 	struct rx_desc *rx_ring;
@@ -492,8 +485,8 @@ struct rhine_private {
 	dma_addr_t tx_bufs_dma;
 
 	struct pci_dev *pdev;
+	long pioaddr;
 	struct net_device_stats stats;
-	struct timer_list timer;	/* Media monitoring timer. */
 	spinlock_t lock;
 
 	/* Frequently used values: keep some adjacent for cache effect. */
@@ -502,23 +495,16 @@ struct rhine_private {
 	unsigned int cur_rx, dirty_rx;	/* Producer/consumer ring indices */
 	unsigned int cur_tx, dirty_tx;
 	unsigned int rx_buf_sz;		/* Based on MTU+slack. */
-	u16 chip_cmd;			/* Current setting for ChipCmd */
+	u8 wolopts;
 
-	/* These values are keep track of the transceiver/media in use. */
 	u8 tx_thresh, rx_thresh;
 
-	/* MII transceiver section. */
-	unsigned char phys[MAX_MII_CNT];	/* MII device addresses. */
-	unsigned int mii_cnt;		/* number of MIIs found, but only the first one is used */
-	u16 mii_status;			/* last read MII status */
 	struct mii_if_info mii_if;
 };
 
 static int  mdio_read(struct net_device *dev, int phy_id, int location);
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
 static int  rhine_open(struct net_device *dev);
-static void rhine_check_duplex(struct net_device *dev);
-static void rhine_timer(unsigned long data);
 static void rhine_tx_timeout(struct net_device *dev);
 static int  rhine_start_tx(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
@@ -530,6 +516,16 @@ static struct net_device_stats *rhine_get_stats(struct net_device *dev);
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static struct ethtool_ops netdev_ethtool_ops;
 static int  rhine_close(struct net_device *dev);
+static void rhine_shutdown (struct device *gdev);
+
+#define RHINE_WAIT_FOR(condition) do {					\
+	int i=1024;							\
+	while (!(condition) && --i)					\
+		;							\
+	if (debug > 1 && i < 512)					\
+		printk(KERN_INFO "%s: %4d cycles used @ %s:%d\n",	\
+				DRV_NAME, 1024-i, __func__, __LINE__);	\
+} while(0)
 
 static inline u32 get_intr_status(struct net_device *dev)
 {
@@ -546,12 +542,13 @@ static inline u32 get_intr_status(struct net_device *dev)
 
 /*
  * Get power related registers into sane state.
- * Returns content of power-event (WOL) registers.
+ * Notify user about past WOL event.
  */
 static void rhine_power_init(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
 	struct rhine_private *rp = netdev_priv(dev);
+	u16 wolstat;
 
 	if (rp->quirks & rqWOL) {
 		/* Make sure chip is in power state D0 */
@@ -566,63 +563,109 @@ static void rhine_power_init(struct net_device *dev)
 		if (rp->quirks & rq6patterns)
 			writeb(0x03, ioaddr + WOLcrClr1);
 
+		/* Save power-event status bits */
+		wolstat = readb(ioaddr + PwrcsrSet);
+		if (rp->quirks & rq6patterns)
+			wolstat |= (readb(ioaddr + PwrcsrSet1) & 0x03) << 8;
+
 		/* Clear power-event status bits */
 		writeb(0xFF, ioaddr + PwrcsrClr);
 		if (rp->quirks & rq6patterns)
 			writeb(0x03, ioaddr + PwrcsrClr1);
+
+		if (wolstat) {
+			char *reason;
+			switch (wolstat) {
+			case WOLmagic:
+				reason = "Magic packet";
+				break;
+			case WOLlnkon:
+				reason = "Link went up";
+				break;
+			case WOLlnkoff:
+				reason = "Link went down";
+				break;
+			case WOLucast:
+				reason = "Unicast packet";
+				break;
+			case WOLbmcast:
+				reason = "Multicast/broadcast packet";
+				break;
+			default:
+				reason = "Unknown";
+			}
+			printk(KERN_INFO "%s: Woke system up. Reason: %s.\n",
+			       DRV_NAME, reason);
+		}
 	}
 }
 
-static void wait_for_reset(struct net_device *dev, u32 quirks, char *name)
+static void rhine_chip_reset(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
-	int boguscnt = 20;
+	struct rhine_private *rp = netdev_priv(dev);
 
+	writeb(Cmd1Reset, ioaddr + ChipCmd1);
 	IOSYNC;
 
-	if (readw(ioaddr + ChipCmd) & CmdReset) {
+	if (readb(ioaddr + ChipCmd1) & Cmd1Reset) {
 		printk(KERN_INFO "%s: Reset not complete yet. "
-			"Trying harder.\n", name);
+			"Trying harder.\n", DRV_NAME);
 
-		/* Rhine-II needs to be forced sometimes */
-		if (quirks & rqForceReset)
+		/* Force reset */
+		if (rp->quirks & rqForceReset)
 			writeb(0x40, ioaddr + MiscCmd);
 
-		/* VT86C100A may need long delay after reset (dlink) */
-		/* Seen on Rhine-II as well (rl) */
-		while ((readw(ioaddr + ChipCmd) & CmdReset) && --boguscnt)
-			udelay(5);
-
+		/* Reset can take somewhat longer (rare) */
+		RHINE_WAIT_FOR(!(readb(ioaddr + ChipCmd1) & Cmd1Reset));
 	}
 
 	if (debug > 1)
-		printk(KERN_INFO "%s: Reset %s.\n", name,
-			boguscnt ? "succeeded" : "failed");
+		printk(KERN_INFO "%s: Reset %s.\n", dev->name,
+			(readb(ioaddr + ChipCmd1) & Cmd1Reset) ?
+			"failed" : "succeeded");
 }
 
 #ifdef USE_MMIO
-static void __devinit enable_mmio(long ioaddr, u32 quirks)
+static void __devinit enable_mmio(long pioaddr, u32 quirks)
 {
 	int n;
 	if (quirks & rqRhineI) {
 		/* More recent docs say that this bit is reserved ... */
-		n = inb(ioaddr + ConfigA) | 0x20;
-		outb(n, ioaddr + ConfigA);
+		n = inb(pioaddr + ConfigA) | 0x20;
+		outb(n, pioaddr + ConfigA);
 	} else {
-		n = inb(ioaddr + ConfigD) | 0x80;
-		outb(n, ioaddr + ConfigD);
+		n = inb(pioaddr + ConfigD) | 0x80;
+		outb(n, pioaddr + ConfigD);
 	}
 }
 #endif
 
-static void __devinit reload_eeprom(long ioaddr)
+/*
+ * Loads bytes 0x00-0x05, 0x6E-0x6F, 0x78-0x7B from EEPROM
+ * (plus 0x6C for Rhine-I/II)
+ */
+static void __devinit rhine_reload_eeprom(long pioaddr, struct net_device *dev)
 {
-	int i;
-	outb(0x20, ioaddr + MACRegEEcsr);
-	/* Typically 2 cycles to reload. */
-	for (i = 0; i < 150; i++)
-		if (! (inb(ioaddr + MACRegEEcsr) & 0x20))
-			break;
+	long ioaddr = dev->base_addr;
+	struct rhine_private *rp = netdev_priv(dev);
+
+	outb(0x20, pioaddr + MACRegEEcsr);
+	RHINE_WAIT_FOR(!(inb(pioaddr + MACRegEEcsr) & 0x20));
+
+#ifdef USE_MMIO
+	/*
+	 * Reloading from EEPROM overwrites ConfigA-D, so we must re-enable
+	 * MMIO. If reloading EEPROM was done first this could be avoided, but
+	 * it is not known if that still works with the "win98-reboot" problem.
+	 */
+	enable_mmio(pioaddr, rp->quirks);
+#endif
+
+	/* Turn off EEPROM-controlled wake-up (magic packet) */
+	if (rp->quirks & rqWOL)
+		writeb(readb(ioaddr + ConfigA) & 0xFE, ioaddr + ConfigA);
+
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -634,22 +677,33 @@ static void rhine_poll(struct net_device *dev)
 }
 #endif
 
+static void rhine_hw_init(struct net_device *dev, long pioaddr)
+{
+	struct rhine_private *rp = netdev_priv(dev);
+
+	/* Reset the chip to erase previous misconfiguration. */
+	rhine_chip_reset(dev);
+
+	/* Rhine-I needs extra time to recuperate before EEPROM reload */
+	if (rp->quirks & rqRhineI)
+		msleep(5);
+
+	/* Reload EEPROM controlled bytes cleared by soft reset */
+	rhine_reload_eeprom(pioaddr, dev);
+}
+
 static int __devinit rhine_init_one(struct pci_dev *pdev,
 				    const struct pci_device_id *ent)
 {
 	struct net_device *dev;
 	struct rhine_private *rp;
-	int i, option, rc;
+	int i, rc;
 	u8 pci_rev;
 	u32 quirks;
-	static int card_idx = -1;
-	long ioaddr;
+	long pioaddr;
 	long memaddr;
-	int io_size;
-	int phy, phy_idx = 0;
-#ifdef USE_MMIO
-	long ioaddr0;
-#endif
+	long ioaddr;
+	int io_size, phy_id;
 	const char *name;
 
 /* when built into the kernel, we only print version if device is found */
@@ -659,26 +713,30 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
 		printk(version);
 #endif
 
-	card_idx++;
-	option = card_idx < MAX_UNITS ? options[card_idx] : 0;
 	pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev);
 
 	io_size = 256;
-	if (pci_rev < VT6102) {
-		quirks = rqRhineI | rqDavicomPhy;
+	phy_id = 0;
+	quirks = 0;
+	name = "Rhine";
+	if (pci_rev < VTunknown0) {
+		quirks = rqRhineI;
 		io_size = 128;
-		name = "VT86C100A Rhine";
 	}
-	else {
+	else if (pci_rev >= VT6102) {
 		quirks = rqWOL | rqForceReset;
 		if (pci_rev < VT6105) {
 			name = "Rhine II";
 			quirks |= rqStatusWBRace;	/* Rhine-II exclusive */
 		}
 		else {
-			name = "Rhine III";
+			phy_id = 1;	/* Integrated PHY, phy_id fixed to 1 */
 			if (pci_rev >= VT6105_B0)
 				quirks |= rq6patterns;
+			if (pci_rev < VT6105M)
+				name = "Rhine III";
+			else
+				name = "Rhine III (Management Adapter)";
 		}
 	}
 
@@ -702,28 +760,31 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
 		goto err_out;
 	}
 
-	ioaddr = pci_resource_start(pdev, 0);
+	pioaddr = pci_resource_start(pdev, 0);
 	memaddr = pci_resource_start(pdev, 1);
 
 	pci_set_master(pdev);
 
-	dev = alloc_etherdev(sizeof(*rp));
-	if (dev == NULL) {
+	dev = alloc_etherdev(sizeof(struct rhine_private));
+	if (!dev) {
 		rc = -ENOMEM;
-		printk(KERN_ERR "init_ethernet failed for card #%d\n",
-		       card_idx);
+		printk(KERN_ERR "alloc_etherdev failed\n");
 		goto err_out;
 	}
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	rc = pci_request_regions(pdev, shortname);
+	rp = netdev_priv(dev);
+	rp->quirks = quirks;
+	rp->pioaddr = pioaddr;
+	rp->pdev = pdev;
+
+	rc = pci_request_regions(pdev, DRV_NAME);
 	if (rc)
 		goto err_out_free_netdev;
 
 #ifdef USE_MMIO
-	ioaddr0 = ioaddr;
-	enable_mmio(ioaddr0, quirks);
+	enable_mmio(pioaddr, quirks);
 
 	ioaddr = (long) ioremap(memaddr, io_size);
 	if (!ioaddr) {
@@ -737,7 +798,7 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
 	i = 0;
 	while (mmio_verify_registers[i]) {
 		int reg = mmio_verify_registers[i++];
-		unsigned char a = inb(ioaddr0+reg);
+		unsigned char a = inb(pioaddr+reg);
 		unsigned char b = readb(ioaddr+reg);
 		if (a != b) {
 			rc = -EIO;
@@ -746,65 +807,38 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
 			goto err_out_unmap;
 		}
 	}
+#else
+	ioaddr = pioaddr;
 #endif /* USE_MMIO */
+
 	dev->base_addr = ioaddr;
-	rp = netdev_priv(dev);
-	rp->quirks = quirks;
 
+	/* Get chip registers into a sane state */
 	rhine_power_init(dev);
-
-	/* Reset the chip to erase previous misconfiguration. */
-	writew(CmdReset, ioaddr + ChipCmd);
-
-	wait_for_reset(dev, quirks, shortname);
-
-	/* Reload the station address from the EEPROM. */
-#ifdef USE_MMIO
-	reload_eeprom(ioaddr0);
-	/* Reloading from eeprom overwrites cfgA-D, so we must re-enable MMIO.
-	   If reload_eeprom() was done first this could be avoided, but it is
-	   not known if that still works with the "win98-reboot" problem. */
-	enable_mmio(ioaddr0, quirks);
-#else
-	reload_eeprom(ioaddr);
-#endif
+	rhine_hw_init(dev, pioaddr);
 
 	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = readb(ioaddr + StationAddr + i);
 
 	if (!is_valid_ether_addr(dev->dev_addr)) {
 		rc = -EIO;
-		printk(KERN_ERR "Invalid MAC address for card #%d\n", card_idx);
+		printk(KERN_ERR "Invalid MAC address\n");
 		goto err_out_unmap;
 	}
 
-	if (quirks & rqWOL) {
-		/*
-		 * for 3065D, EEPROM reloaded will cause bit 0 in MAC_REG_CFGA
-		 * turned on. it makes MAC receive magic packet
-		 * automatically. So, we turn it off. (D-Link)
-		 */
-		writeb(readb(ioaddr + ConfigA) & 0xFE, ioaddr + ConfigA);
-	}
-
-	/* Select backoff algorithm */
-	if (backoff)
-		writeb(readb(ioaddr + ConfigD) & (0xF0 | backoff),
-		       ioaddr + ConfigD);
+	/* For Rhine-I/II, phy_id is loaded from EEPROM */
+	if (!phy_id)
+		phy_id = readb(ioaddr + 0x6C);
 
 	dev->irq = pdev->irq;
 
 	spin_lock_init(&rp->lock);
-	rp->pdev = pdev;
 	rp->mii_if.dev = dev;
 	rp->mii_if.mdio_read = mdio_read;
 	rp->mii_if.mdio_write = mdio_write;
 	rp->mii_if.phy_id_mask = 0x1f;
 	rp->mii_if.reg_num_mask = 0x1f;
 
-	if (dev->mem_start)
-		option = dev->mem_start;
-
 	/* The chip-specific entries in the device structure. */
 	dev->open = rhine_open;
 	dev->hard_start_xmit = rhine_start_tx;
@@ -826,20 +860,6 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
 	if (rc)
 		goto err_out_unmap;
 
-	/* The lower four bits are the media type. */
-	if (option > 0) {
-		if (option & 0x220)
-			rp->mii_if.full_duplex = 1;
-	}
-	if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0)
-		rp->mii_if.full_duplex = 1;
-
-	if (rp->mii_if.full_duplex) {
-		printk(KERN_INFO "%s: Set to forced full duplex, "
-		       "autonegotiation disabled.\n", dev->name);
-		rp->mii_if.force_media = 1;
-	}
-
 	printk(KERN_INFO "%s: VIA %s at 0x%lx, ",
 	       dev->name, name,
 #ifdef USE_MMIO
@@ -855,17 +875,18 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
 
 	pci_set_drvdata(pdev, dev);
 
-	rp->phys[0] = 1;		/* Standard for this chip. */
-	for (phy = 1; phy < 32 && phy_idx < MAX_MII_CNT; phy++) {
-		int mii_status = mdio_read(dev, phy, 1);
+	{
+		u16 mii_cmd;
+		int mii_status = mdio_read(dev, phy_id, 1);
+		mii_cmd = mdio_read(dev, phy_id, MII_BMCR) & ~BMCR_ISOLATE;
+		mdio_write(dev, phy_id, MII_BMCR, mii_cmd);
 		if (mii_status != 0xffff && mii_status != 0x0000) {
-			rp->phys[phy_idx++] = phy;
-			rp->mii_if.advertising = mdio_read(dev, phy, 4);
+			rp->mii_if.advertising = mdio_read(dev, phy_id, 4);
 			printk(KERN_INFO "%s: MII PHY found at address "
 			       "%d, status 0x%4.4x advertising %4.4x "
-			       "Link %4.4x.\n", dev->name, phy,
+			       "Link %4.4x.\n", dev->name, phy_id,
 			       mii_status, rp->mii_if.advertising,
-			       mdio_read(dev, phy, 5));
+			       mdio_read(dev, phy_id, 5));
 
 			/* set IFF_RUNNING */
 			if (mii_status & BMSR_LSTATUS)
@@ -873,27 +894,9 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
 			else
 				netif_carrier_off(dev);
 
-			break;
-		}
-	}
-	rp->mii_cnt = phy_idx;
-	rp->mii_if.phy_id = rp->phys[0];
-
-	/* Allow forcing the media type. */
-	if (option > 0) {
-		if (option & 0x220)
-			rp->mii_if.full_duplex = 1;
-		if (option & 0x330) {
-			printk(KERN_INFO " Forcing %dMbs %s-duplex "
-				"operation.\n",
-			       (option & 0x300 ? 100 : 10),
-			       (option & 0x220 ? "full" : "half"));
-			if (rp->mii_cnt)
-				mdio_write(dev, rp->phys[0], MII_BMCR,
-					   ((option & 0x300) ? 0x2000 : 0) | /* 100mbps? */
-					   ((option & 0x220) ? 0x0100 : 0)); /* Full duplex? */
 		}
 	}
+	rp->mii_if.phy_id = phy_id;
 
 	return 0;
 
@@ -1065,6 +1068,21 @@ static void free_tbufs(struct net_device* dev)
 	}
 }
 
+static void rhine_check_media(struct net_device *dev, unsigned int init_media)
+{
+	struct rhine_private *rp = netdev_priv(dev);
+	long ioaddr = dev->base_addr;
+
+	mii_check_media(&rp->mii_if, debug, init_media);
+
+	if (rp->mii_if.full_duplex)
+	    writeb(readb(ioaddr + ChipCmd1) | Cmd1FDuplex,
+		   ioaddr + ChipCmd1);
+	else
+	    writeb(readb(ioaddr + ChipCmd1) & ~Cmd1FDuplex,
+		   ioaddr + ChipCmd1);
+}
+
 static void init_registers(struct net_device *dev)
 {
 	struct rhine_private *rp = netdev_priv(dev);
@@ -1080,7 +1098,6 @@ static void init_registers(struct net_device *dev)
 	writeb(0x20, ioaddr + TxConfig);
 	rp->tx_thresh = 0x20;
 	rp->rx_thresh = 0x60;		/* Written in rhine_set_rx_mode(). */
-	rp->mii_if.full_duplex = 0;
 
 	writel(rp->rx_ring_dma, ioaddr + RxRingPtr);
 	writel(rp->tx_ring_dma, ioaddr + TxRingPtr);
@@ -1094,17 +1111,44 @@ static void init_registers(struct net_device *dev)
 	       IntrPCIErr | IntrStatsMax | IntrLinkChange,
 	       ioaddr + IntrEnable);
 
-	rp->chip_cmd = CmdStart|CmdTxOn|CmdRxOn|CmdNoTxPoll;
-	if (rp->mii_if.force_media)
-		rp->chip_cmd |= CmdFDuplex;
-	writew(rp->chip_cmd, ioaddr + ChipCmd);
+	writew(CmdStart | CmdTxOn | CmdRxOn | (Cmd1NoTxPoll << 8),
+	       ioaddr + ChipCmd);
+	rhine_check_media(dev, 1);
+}
+
+/* Enable MII link status auto-polling (required for IntrLinkChange) */
+static void rhine_enable_linkmon(long ioaddr)
+{
+	writeb(0, ioaddr + MIICmd);
+	writeb(MII_BMSR, ioaddr + MIIRegAddr);
+	writeb(0x80, ioaddr + MIICmd);
+
+	RHINE_WAIT_FOR((readb(ioaddr + MIIRegAddr) & 0x20));
+
+	writeb(MII_BMSR | 0x40, ioaddr + MIIRegAddr);
+}
+
+/* Disable MII link status auto-polling (required for MDIO access) */
+static void rhine_disable_linkmon(long ioaddr, u32 quirks)
+{
+	writeb(0, ioaddr + MIICmd);
+
+	if (quirks & rqRhineI) {
+		writeb(0x01, ioaddr + MIIRegAddr);	// MII_BMSR
+
+		/* Can be called from ISR. Evil. */
+		mdelay(1);
+
+		/* 0x80 must be set immediately before turning it off */
+		writeb(0x80, ioaddr + MIICmd);
 
-	rhine_check_duplex(dev);
+		RHINE_WAIT_FOR(readb(ioaddr + MIIRegAddr) & 0x20);
 
-	/* The LED outputs of various MII xcvrs should be configured. */
-	/* For NS or Mison phys, turn on bit 1 in register 0x17 */
-	mdio_write(dev, rp->phys[0], 0x17, mdio_read(dev, rp->phys[0], 0x17) |
-		   0x0001);
+		/* Heh. Now clear 0x80 again. */
+		writeb(0, ioaddr + MIICmd);
+	}
+	else
+		RHINE_WAIT_FOR(readb(ioaddr + MIIRegAddr) & 0x80);
 }
 
 /* Read and write over the MII Management Data I/O (MDIO) interface. */
@@ -1112,156 +1156,72 @@ static void init_registers(struct net_device *dev)
 static int mdio_read(struct net_device *dev, int phy_id, int regnum)
 {
 	long ioaddr = dev->base_addr;
-	int boguscnt = 1024;
+	struct rhine_private *rp = netdev_priv(dev);
+	int result;
 
-	/* Wait for a previous command to complete. */
-	while ((readb(ioaddr + MIICmd) & 0x60) && --boguscnt > 0)
-		;
-	writeb(0x00, ioaddr + MIICmd);
+	rhine_disable_linkmon(ioaddr, rp->quirks);
+
+	/* rhine_disable_linkmon already cleared MIICmd */
 	writeb(phy_id, ioaddr + MIIPhyAddr);
 	writeb(regnum, ioaddr + MIIRegAddr);
 	writeb(0x40, ioaddr + MIICmd);		/* Trigger read */
-	boguscnt = 1024;
-	while ((readb(ioaddr + MIICmd) & 0x40) && --boguscnt > 0)
-		;
-	return readw(ioaddr + MIIData);
+	RHINE_WAIT_FOR(!(readb(ioaddr + MIICmd) & 0x40));
+	result = readw(ioaddr + MIIData);
+
+	rhine_enable_linkmon(ioaddr);
+	return result;
 }
 
 static void mdio_write(struct net_device *dev, int phy_id, int regnum, int value)
 {
 	struct rhine_private *rp = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
-	int boguscnt = 1024;
 
-	if (phy_id == rp->phys[0]) {
-		switch (regnum) {
-		case MII_BMCR:		/* Is user forcing speed/duplex? */
-			if (value & 0x9000)	/* Autonegotiation. */
-				rp->mii_if.force_media = 0;
-			else
-				rp->mii_if.full_duplex = (value & 0x0100) ? 1 : 0;
-			break;
-		case MII_ADVERTISE:
-			rp->mii_if.advertising = value;
-			break;
-		}
-	}
+	rhine_disable_linkmon(ioaddr, rp->quirks);
 
-	/* Wait for a previous command to complete. */
-	while ((readb(ioaddr + MIICmd) & 0x60) && --boguscnt > 0)
-		;
-	writeb(0x00, ioaddr + MIICmd);
+	/* rhine_disable_linkmon already cleared MIICmd */
 	writeb(phy_id, ioaddr + MIIPhyAddr);
 	writeb(regnum, ioaddr + MIIRegAddr);
 	writew(value, ioaddr + MIIData);
-	writeb(0x20, ioaddr + MIICmd);		/* Trigger write. */
-}
+	writeb(0x20, ioaddr + MIICmd);		/* Trigger write */
+	RHINE_WAIT_FOR(!(readb(ioaddr + MIICmd) & 0x20));
 
+	rhine_enable_linkmon(ioaddr);
+}
 
 static int rhine_open(struct net_device *dev)
 {
 	struct rhine_private *rp = netdev_priv(dev);
 	long ioaddr = dev->base_addr;
-	int i;
-
-	/* Reset the chip. */
-	writew(CmdReset, ioaddr + ChipCmd);
+	int rc;
 
-	i = request_irq(rp->pdev->irq, &rhine_interrupt, SA_SHIRQ, dev->name,
+	rc = request_irq(rp->pdev->irq, &rhine_interrupt, SA_SHIRQ, dev->name,
 			dev);
-	if (i)
-		return i;
+	if (rc)
+		return rc;
 
 	if (debug > 1)
 		printk(KERN_DEBUG "%s: rhine_open() irq %d.\n",
 		       dev->name, rp->pdev->irq);
 
-	i = alloc_ring(dev);
-	if (i)
-		return i;
+	rc = alloc_ring(dev);
+	if (rc)
+		return rc;
 	alloc_rbufs(dev);
 	alloc_tbufs(dev);
-	wait_for_reset(dev, rp->quirks, dev->name);
+	rhine_chip_reset(dev);
 	init_registers(dev);
 	if (debug > 2)
 		printk(KERN_DEBUG "%s: Done rhine_open(), status %4.4x "
 		       "MII status: %4.4x.\n",
 		       dev->name, readw(ioaddr + ChipCmd),
-		       mdio_read(dev, rp->phys[0], MII_BMSR));
+		       mdio_read(dev, rp->mii_if.phy_id, MII_BMSR));
 
 	netif_start_queue(dev);
 
-	/* Set the timer to check for link beat. */
-	init_timer(&rp->timer);
-	rp->timer.expires = jiffies + 2 * HZ/100;
-	rp->timer.data = (unsigned long)dev;
-	rp->timer.function = &rhine_timer;		/* timer handler */
-	add_timer(&rp->timer);
-
 	return 0;
 }
 
-static void rhine_check_duplex(struct net_device *dev)
-{
-	struct rhine_private *rp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-	int mii_lpa = mdio_read(dev, rp->phys[0], MII_LPA);
-	int negotiated = mii_lpa & rp->mii_if.advertising;
-	int duplex;
-
-	if (rp->mii_if.force_media || mii_lpa == 0xffff)
-		return;
-	duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
-	if (rp->mii_if.full_duplex != duplex) {
-		rp->mii_if.full_duplex = duplex;
-		if (debug)
-			printk(KERN_INFO "%s: Setting %s-duplex based on "
-			       "MII #%d link partner capability of %4.4x.\n",
-			       dev->name, duplex ? "full" : "half",
-			       rp->phys[0], mii_lpa);
-		if (duplex)
-			rp->chip_cmd |= CmdFDuplex;
-		else
-			rp->chip_cmd &= ~CmdFDuplex;
-		writew(rp->chip_cmd, ioaddr + ChipCmd);
-	}
-}
-
-
-static void rhine_timer(unsigned long data)
-{
-	struct net_device *dev = (struct net_device *)data;
-	struct rhine_private *rp = netdev_priv(dev);
-	long ioaddr = dev->base_addr;
-	int next_tick = 10*HZ;
-	int mii_status;
-
-	if (debug > 3) {
-		printk(KERN_DEBUG "%s: VIA Rhine monitor tick, status %4.4x.\n",
-		       dev->name, readw(ioaddr + IntrStatus));
-	}
-
-	spin_lock_irq (&rp->lock);
-
-	rhine_check_duplex(dev);
-
-	/* make IFF_RUNNING follow the MII status bit "Link established" */
-	mii_status = mdio_read(dev, rp->phys[0], MII_BMSR);
-	if ((mii_status & BMSR_LSTATUS) != (rp->mii_status & BMSR_LSTATUS)) {
-		if (mii_status & BMSR_LSTATUS)
-			netif_carrier_on(dev);
-		else
-			netif_carrier_off(dev);
-	}
-	rp->mii_status = mii_status;
-
-	spin_unlock_irq(&rp->lock);
-
-	rp->timer.expires = jiffies + next_tick;
-	add_timer(&rp->timer);
-}
-
-
 static void rhine_tx_timeout(struct net_device *dev)
 {
 	struct rhine_private *rp = netdev_priv(dev);
@@ -1270,16 +1230,13 @@ static void rhine_tx_timeout(struct net_device *dev)
 	printk(KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status "
 	       "%4.4x, resetting...\n",
 	       dev->name, readw(ioaddr + IntrStatus),
-	       mdio_read(dev, rp->phys[0], MII_BMSR));
+	       mdio_read(dev, rp->mii_if.phy_id, MII_BMSR));
 
 	/* protect against concurrent rx interrupts */
 	disable_irq(rp->pdev->irq);
 
 	spin_lock(&rp->lock);
 
-	/* Reset the chip. */
-	writew(CmdReset, ioaddr + ChipCmd);
-
 	/* clear all descriptors */
 	free_tbufs(dev);
 	free_rbufs(dev);
@@ -1287,7 +1244,7 @@ static void rhine_tx_timeout(struct net_device *dev)
 	alloc_rbufs(dev);
 
 	/* Reinitialize the hardware. */
-	wait_for_reset(dev, rp->quirks, dev->name);
+	rhine_chip_reset(dev);
 	init_registers(dev);
 
 	spin_unlock(&rp->lock);
@@ -1301,8 +1258,8 @@ static void rhine_tx_timeout(struct net_device *dev)
 static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	struct rhine_private *rp = netdev_priv(dev);
+	long ioaddr = dev->base_addr;
 	unsigned entry;
-	u32 intr_status;
 
 	/* Caution: the write order is important here, set the field
 	   with the "ownership" bits last. */
@@ -1353,14 +1310,9 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev)
 
 	/* Non-x86 Todo: explicitly flush cache lines here. */
 
-	/*
-	 * Wake the potentially-idle transmit channel unless errors are
-	 * pending (the ISR must sort them out first).
-	 */
-	intr_status = get_intr_status(dev);
-	if ((intr_status & IntrTxErrSummary) == 0) {
-		writew(CmdTxDemand | rp->chip_cmd, dev->base_addr + ChipCmd);
-	}
+	/* Wake the potentially-idle transmit channel */
+	writeb(readb(ioaddr + ChipCmd1) | Cmd1TxDemand,
+	       ioaddr + ChipCmd1);
 	IOSYNC;
 
 	if (rp->cur_tx == rp->dirty_tx + TX_QUEUE_LEN)
@@ -1408,11 +1360,10 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *
 
 		if (intr_status & (IntrTxErrSummary | IntrTxDone)) {
 			if (intr_status & IntrTxErrSummary) {
-				int cnt = 20;
 				/* Avoid scavenging before Tx engine turned off */
-				while ((readw(ioaddr+ChipCmd) & CmdTxOn) && --cnt)
-					udelay(5);
-				if (debug > 2 && !cnt)
+				RHINE_WAIT_FOR(!(readb(ioaddr+ChipCmd) & CmdTxOn));
+				if (debug > 2 &&
+				    readb(ioaddr+ChipCmd) & CmdTxOn)
 					printk(KERN_WARNING "%s: "
 					       "rhine_interrupt() Tx engine"
 					       "still on.\n", dev->name);
@@ -1572,10 +1523,6 @@ static void rhine_rx(struct net_device *dev)
 							    rp->rx_buf_sz,
 							    PCI_DMA_FROMDEVICE);
 
-				/* *_IP_COPYSUM isn't defined anywhere and
-				   eth_copy_and_sum is memcpy for all archs so
-				   this is kind of pointless right now
-				   ... or? */
 				eth_copy_and_sum(skb,
 						 rp->rx_skbuff[entry]->tail,
 						 pkt_len, 0);
@@ -1627,10 +1574,6 @@ static void rhine_rx(struct net_device *dev)
 		}
 		rp->rx_ring[entry].rx_status = cpu_to_le32(DescOwn);
 	}
-
-	/* Pre-emptively restart Rx engine. */
-	writew(readw(dev->base_addr + ChipCmd) | CmdRxOn | CmdRxDemand,
-	       dev->base_addr + ChipCmd);
 }
 
 /*
@@ -1664,7 +1607,10 @@ static void rhine_restart_tx(struct net_device *dev) {
 		writel(rp->tx_ring_dma + entry * sizeof(struct tx_desc),
 		       ioaddr + TxRingPtr);
 
-		writew(CmdTxDemand | rp->chip_cmd, ioaddr + ChipCmd);
+		writeb(readb(ioaddr + ChipCmd) | CmdTxOn,
+		       ioaddr + ChipCmd);
+		writeb(readb(ioaddr + ChipCmd1) | Cmd1TxDemand,
+		       ioaddr + ChipCmd1);
 		IOSYNC;
 	}
 	else {
@@ -1684,20 +1630,8 @@ static void rhine_error(struct net_device *dev, int intr_status)
 
 	spin_lock(&rp->lock);
 
-	if (intr_status & (IntrLinkChange)) {
-		if (readb(ioaddr + MIIStatus) & 0x02) {
-			/* Link failed, restart autonegotiation. */
-			if (rp->quirks & rqRhineI)
-				mdio_write(dev, rp->phys[0], MII_BMCR, 0x3300);
-		} else
-			rhine_check_duplex(dev);
-		if (debug)
-			printk(KERN_ERR "%s: MII status changed: "
-			       "Autonegotiation advertising %4.4x partner "
-			       "%4.4x.\n", dev->name,
-			       mdio_read(dev, rp->phys[0], MII_ADVERTISE),
-			       mdio_read(dev, rp->phys[0], MII_LPA));
-	}
+	if (intr_status & IntrLinkChange)
+		rhine_check_media(dev, 0);
 	if (intr_status & IntrStatsMax) {
 		rp->stats.rx_crc_errors += readw(ioaddr + RxCRCErrs);
 		rp->stats.rx_missed_errors += readw(ioaddr + RxMissed);
@@ -1790,7 +1724,7 @@ static void rhine_set_rx_mode(struct net_device *dev)
 		     i++, mclist = mclist->next) {
 			int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
 
-			mc_filter[bit_nr >> 5] |= cpu_to_le32(1 << (bit_nr & 31));
+			mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
 		}
 		writel(mc_filter[0], ioaddr + MulticastFilter0);
 		writel(mc_filter[1], ioaddr + MulticastFilter1);
@@ -1856,6 +1790,39 @@ static void netdev_set_msglevel(struct net_device *dev, u32 value)
 	debug = value;
 }
 
+static void rhine_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct rhine_private *rp = netdev_priv(dev);
+
+	if (!(rp->quirks & rqWOL))
+		return;
+
+	spin_lock_irq(&rp->lock);
+	wol->supported = WAKE_PHY | WAKE_MAGIC |
+			 WAKE_UCAST | WAKE_MCAST | WAKE_BCAST;	/* Untested */
+	wol->wolopts = rp->wolopts;
+	spin_unlock_irq(&rp->lock);
+}
+
+static int rhine_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct rhine_private *rp = netdev_priv(dev);
+	u32 support = WAKE_PHY | WAKE_MAGIC |
+		      WAKE_UCAST | WAKE_MCAST | WAKE_BCAST;	/* Untested */
+
+	if (!(rp->quirks & rqWOL))
+		return -EINVAL;
+
+	if (wol->wolopts & ~support)
+		return -EINVAL;
+
+	spin_lock_irq(&rp->lock);
+	rp->wolopts = wol->wolopts;
+	spin_unlock_irq(&rp->lock);
+
+	return 0;
+}
+
 static struct ethtool_ops netdev_ethtool_ops = {
 	.get_drvinfo		= netdev_get_drvinfo,
 	.get_settings		= netdev_get_settings,
@@ -1864,6 +1831,8 @@ static struct ethtool_ops netdev_ethtool_ops = {
 	.get_link		= netdev_get_link,
 	.get_msglevel		= netdev_get_msglevel,
 	.set_msglevel		= netdev_set_msglevel,
+	.get_wol		= rhine_get_wol,
+	.set_wol		= rhine_set_wol,
 	.get_sg			= ethtool_op_get_sg,
 	.get_tx_csum		= ethtool_op_get_tx_csum,
 };
@@ -1888,8 +1857,6 @@ static int rhine_close(struct net_device *dev)
 	long ioaddr = dev->base_addr;
 	struct rhine_private *rp = netdev_priv(dev);
 
-	del_timer_sync(&rp->timer);
-
 	spin_lock_irq(&rp->lock);
 
 	netif_stop_queue(dev);
@@ -1936,12 +1903,110 @@ static void __devexit rhine_remove_one(struct pci_dev *pdev)
 	pci_set_drvdata(pdev, NULL);
 }
 
+static void rhine_shutdown (struct device *gendev)
+{
+	struct pci_dev *pdev = to_pci_dev(gendev);
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct rhine_private *rp = netdev_priv(dev);
+
+	long ioaddr = dev->base_addr;
+
+	rhine_power_init(dev);
+
+	/* Make sure we use pattern 0, 1 and not 4, 5 */
+	if (rp->quirks & rq6patterns)
+		writeb(0x04, ioaddr + 0xA7);
+
+	if (rp->wolopts & WAKE_MAGIC)
+		writeb(WOLmagic, ioaddr + WOLcrSet);
+
+	if (rp->wolopts & (WAKE_BCAST|WAKE_MCAST))
+		writeb(WOLbmcast, ioaddr + WOLcgSet);
+
+	if (rp->wolopts & WAKE_PHY)
+		writeb(WOLlnkon | WOLlnkoff, ioaddr + WOLcrSet);
+
+	if (rp->wolopts & WAKE_UCAST)
+		writeb(WOLucast, ioaddr + WOLcrSet);
+
+	/* Enable legacy WOL (for old motherboards) */
+	writeb(0x01, ioaddr + PwcfgSet);
+	writeb(readb(ioaddr + StickyHW) | 0x04, ioaddr + StickyHW);
+
+	/* Hit power state D3 (sleep) */
+	writeb(readb(ioaddr + StickyHW) | 0x03, ioaddr + StickyHW);
+
+	/* TODO: Check use of pci_enable_wake() */
+
+}
+
+#ifdef CONFIG_PM
+static int rhine_suspend(struct pci_dev *pdev, u32 state)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct rhine_private *rp = netdev_priv(dev);
+	unsigned long flags;
+
+	if (!netif_running(dev))
+		return 0;
+
+	netif_device_detach(dev);
+	pci_save_state(pdev, pdev->saved_config_space);
+
+	spin_lock_irqsave(&rp->lock, flags);
+	rhine_shutdown(&pdev->dev);
+	spin_unlock_irqrestore(&rp->lock, flags);
+
+	return 0;
+}
+
+static int rhine_resume(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct rhine_private *rp = netdev_priv(dev);
+	unsigned long flags;
+	int ret;
+
+	if (!netif_running(dev))
+		return 0;
+
+	ret = pci_set_power_state(pdev, 0);
+	if (debug > 1)
+		printk(KERN_INFO "%s: Entering power state D0 %s (%d).\n",
+			dev->name, ret ? "failed" : "succeeded", ret);
+
+	pci_restore_state(pdev, pdev->saved_config_space);
+
+	spin_lock_irqsave(&rp->lock, flags);
+#ifdef USE_MMIO
+	enable_mmio(rp->pioaddr, rp->quirks);
+#endif
+	rhine_power_init(dev);
+	free_tbufs(dev);
+	free_rbufs(dev);
+	alloc_tbufs(dev);
+	alloc_rbufs(dev);
+	init_registers(dev);
+	spin_unlock_irqrestore(&rp->lock, flags);
+
+	netif_device_attach(dev);
+
+	return 0;
+}
+#endif /* CONFIG_PM */
 
 static struct pci_driver rhine_driver = {
-	.name		= "via-rhine",
+	.name		= DRV_NAME,
 	.id_table	= rhine_pci_tbl,
 	.probe		= rhine_init_one,
 	.remove		= __devexit_p(rhine_remove_one),
+#ifdef CONFIG_PM
+	.suspend	= rhine_suspend,
+	.resume		= rhine_resume,
+#endif /* CONFIG_PM */
+	.driver = {
+		.shutdown = rhine_shutdown,
+	}
 };
 
 
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index f053d2a9e..57a6d2924 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -78,6 +78,8 @@
 #include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/udp.h>
+#include <linux/crc-ccitt.h>
+#include <linux/crc32.h>
 
 #include "via-velocity.h"
 
@@ -226,7 +228,10 @@ VELOCITY_PARAM(wol_opts, "Wake On Lan options");
 
 VELOCITY_PARAM(int_works, "Number of packets per interrupt services");
 
-static int velocity_found1(struct pci_dev *pdev, const struct pci_device_id *ent);
+static int rx_copybreak = 200;
+MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
+
 static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr, struct velocity_info_tbl *info);
 static int velocity_get_pci_info(struct velocity_info *, struct pci_dev *pdev);
 static void velocity_print_info(struct velocity_info *vptr);
@@ -238,10 +243,8 @@ static void velocity_set_multi(struct net_device *dev);
 static struct net_device_stats *velocity_get_stats(struct net_device *dev);
 static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int velocity_close(struct net_device *dev);
-static int velocity_rx_srv(struct velocity_info *vptr, int status);
 static int velocity_receive_frame(struct velocity_info *, int idx);
 static int velocity_alloc_rx_buf(struct velocity_info *, int idx);
-static void velocity_init_registers(struct velocity_info *vptr, enum velocity_init_type type);
 static void velocity_free_rd_ring(struct velocity_info *vptr);
 static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_info *);
 static int velocity_soft_reset(struct velocity_info *vptr);
@@ -254,25 +257,40 @@ static void enable_flow_control_ability(struct velocity_info *vptr);
 static void enable_mii_autopoll(struct mac_regs * regs);
 static int velocity_mii_read(struct mac_regs *, u8 byIdx, u16 * pdata);
 static int velocity_mii_write(struct mac_regs *, u8 byMiiAddr, u16 data);
-static int velocity_set_wol(struct velocity_info *vptr);
-static void velocity_save_context(struct velocity_info *vptr, struct velocity_context *context);
-static void velocity_restore_context(struct velocity_info *vptr, struct velocity_context *context);
 static u32 mii_check_media_mode(struct mac_regs * regs);
 static u32 check_connection_type(struct mac_regs * regs);
-static void velocity_init_cam_filter(struct velocity_info *vptr);
 static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status);
 
 #ifdef CONFIG_PM
+
 static int velocity_suspend(struct pci_dev *pdev, u32 state);
 static int velocity_resume(struct pci_dev *pdev);
 
 static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr);
 
 static struct notifier_block velocity_inetaddr_notifier = {
-      notifier_call:velocity_netdev_event,
+      .notifier_call	= velocity_netdev_event,
 };
 
-#endif				/* CONFIG_PM */
+static spinlock_t velocity_dev_list_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(velocity_dev_list);
+
+static void velocity_register_notifier(void)
+{
+	register_inetaddr_notifier(&velocity_inetaddr_notifier);
+}
+
+static void velocity_unregister_notifier(void)
+{
+	unregister_inetaddr_notifier(&velocity_inetaddr_notifier);
+}
+
+#else				/* CONFIG_PM */
+
+#define velocity_register_notifier()	do {} while (0)
+#define velocity_unregister_notifier()	do {} while (0)
+
+#endif				/* !CONFIG_PM */
 
 /*
  *	Internal board variants. At the moment we have only one
@@ -289,8 +307,9 @@ static struct velocity_info_tbl chip_info_table[] = {
  */
 
 static struct pci_device_id velocity_id_table[] __devinitdata = {
-	{0x1106, 0x3119, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &chip_info_table[0]},
-	{0,}
+	{PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_612X,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) chip_info_table},
+	{0, }
 };
 
 MODULE_DEVICE_TABLE(pci, velocity_id_table);
@@ -326,12 +345,22 @@ static void __devexit velocity_remove1(struct pci_dev *pdev)
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct velocity_info *vptr = dev->priv;
 
+#ifdef CONFIG_PM
+	unsigned long flags;
+
+	spin_lock_irqsave(&velocity_dev_list_lock, flags);
+	if (!list_empty(&velocity_dev_list))
+		list_del(&vptr->list);
+	spin_unlock_irqrestore(&velocity_dev_list_lock, flags);
+#endif
 	unregister_netdev(dev);
 	iounmap(vptr->mac_regs);
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
 	free_netdev(dev);
+
+	velocity_nics--;
 }
 
 /**
@@ -435,7 +464,7 @@ static void velocity_init_cam_filter(struct velocity_info *vptr)
 {
 	struct mac_regs * regs = vptr->mac_regs;
 
-	/* T urn on MCFG_PQEN, turn off MCFG_RTGOPT */
+	/* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */
 	WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, &regs->MCFG);
 	WORD_REG_BITS_ON(MCFG_VIDFR, &regs->MCFG);
 
@@ -477,13 +506,13 @@ static void velocity_rx_reset(struct velocity_info *vptr)
 	struct mac_regs * regs = vptr->mac_regs;
 	int i;
 
-	vptr->rd_used = vptr->rd_curr = 0;
+	vptr->rd_dirty = vptr->rd_filled = vptr->rd_curr = 0;
 
 	/*
 	 *	Init state, all RD entries belong to the NIC
 	 */
 	for (i = 0; i < vptr->options.numrx; ++i)
-		vptr->rd_ring[i].rdesc0.owner = cpu_to_le32(OWNED_BY_NIC);
+		vptr->rd_ring[i].rdesc0.owner = OWNED_BY_NIC;
 
 	writew(vptr->options.numrx, &regs->RBRDU);
 	writel(vptr->rd_pool_dma, &regs->RDBaseLo);
@@ -558,10 +587,15 @@ static void velocity_init_registers(struct velocity_info *vptr,
 
 		writeb(WOLCFG_SAM | WOLCFG_SAB, &regs->WOLCFGSet);
 		/*
-		 *	Bback off algorithm use original IEEE standard
+		 *	Back off algorithm use original IEEE standard
 		 */
 		BYTE_REG_BITS_SET(CFGB_OFSET, (CFGB_CRANDOM | CFGB_CAP | CFGB_MBA | CFGB_BAKOPT), &regs->CFGB);
 
+		/*
+		 *	Init CAM filter
+		 */
+		velocity_init_cam_filter(vptr);
+
 		/*
 		 *	Set packet filter: Receive directed and broadcast address
 		 */
@@ -586,8 +620,6 @@ static void velocity_init_registers(struct velocity_info *vptr,
 			mac_tx_queue_run(regs, i);
 		}
 
-		velocity_init_cam_filter(vptr);
-
 		init_flow_control_register(vptr);
 
 		writel(CR0_STOP, &regs->CR0Clr);
@@ -595,7 +627,6 @@ static void velocity_init_registers(struct velocity_info *vptr,
 
 		mii_status = velocity_get_opt_media_mode(vptr);
 		netif_stop_queue(vptr->dev);
-		mac_clear_isr(regs);
 
 		mii_init(vptr, mii_status);
 
@@ -662,7 +693,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
 	struct mac_regs * regs;
 	int ret = -ENOMEM;
 
-	if (velocity_nics++ >= MAX_UNITS) {
+	if (velocity_nics >= MAX_UNITS) {
 		printk(KERN_NOTICE VELOCITY_NAME ": already found %d NICs.\n", 
 				velocity_nics);
 		return -ENODEV;
@@ -694,7 +725,6 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
 
 	vptr->dev = dev;
 
-	dev->priv = vptr;
 	dev->irq = pdev->irq;
 
 	ret = pci_enable_device(pdev);
@@ -729,7 +759,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
 		dev->dev_addr[i] = readb(&regs->PAR[i]);
 
 
-	velocity_get_options(&vptr->options, velocity_nics - 1, dev->name);
+	velocity_get_options(&vptr->options, velocity_nics, dev->name);
 
 	/* 
 	 *	Mask out the options cannot be set to the chip
@@ -775,6 +805,16 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
 	/* and leave the chip powered down */
 	
 	pci_set_power_state(pdev, 3);
+#ifdef CONFIG_PM
+	{
+		unsigned long flags;
+
+		spin_lock_irqsave(&velocity_dev_list_lock, flags);
+		list_add(&vptr->list, &velocity_dev_list);
+		spin_unlock_irqrestore(&velocity_dev_list_lock, flags);
+	}
+#endif
+	velocity_nics++;
 out:
 	return ret;
 
@@ -827,9 +867,8 @@ static void __devinit velocity_init_info(struct pci_dev *pdev, struct velocity_i
 	vptr->io_size = info->io_size;
 	vptr->num_txq = info->txqueue;
 	vptr->multicast_limit = MCAM_SIZE;
-
 	spin_lock_init(&vptr->lock);
-	spin_lock_init(&vptr->xmit_lock);
+	INIT_LIST_HEAD(&vptr->list);
 }
 
 /**
@@ -966,6 +1005,60 @@ static void velocity_free_rings(struct velocity_info *vptr)
 	pci_free_consistent(vptr->pdev, size, vptr->tx_bufs, vptr->tx_bufs_dma);
 }
 
+static inline void velocity_give_many_rx_descs(struct velocity_info *vptr)
+{
+	struct mac_regs *regs = vptr->mac_regs;
+	int avail, dirty, unusable;
+
+	/*
+	 * RD number must be equal to 4X per hardware spec
+	 * (programming guide rev 1.20, p.13)
+	 */
+	if (vptr->rd_filled < 4)
+		return;
+
+	wmb();
+
+	unusable = vptr->rd_filled & 0x0003;
+	dirty = vptr->rd_dirty - unusable;
+	for (avail = vptr->rd_filled & 0xfffc; avail; avail--) {
+		dirty = (dirty > 0) ? dirty - 1 : vptr->options.numrx - 1;
+		vptr->rd_ring[dirty].rdesc0.owner = OWNED_BY_NIC;
+	}
+
+	writew(vptr->rd_filled & 0xfffc, &regs->RBRDU);
+	vptr->rd_filled = unusable;
+}
+
+static int velocity_rx_refill(struct velocity_info *vptr)
+{
+	int dirty = vptr->rd_dirty, done = 0, ret = 0;
+
+	do {
+		struct rx_desc *rd = vptr->rd_ring + dirty;
+
+		/* Fine for an all zero Rx desc at init time as well */
+		if (rd->rdesc0.owner == OWNED_BY_NIC)
+			break;
+
+		if (!vptr->rd_info[dirty].skb) {
+			ret = velocity_alloc_rx_buf(vptr, dirty);
+			if (ret < 0)
+				break;
+		}
+		done++;
+		dirty = (dirty < vptr->options.numrx - 1) ? dirty + 1 : 0;	
+	} while (dirty != vptr->rd_curr);
+
+	if (done) {
+		vptr->rd_dirty = dirty;
+		vptr->rd_filled += done;
+		velocity_give_many_rx_descs(vptr);
+	}
+
+	return ret;
+}
+
 /**
  *	velocity_init_rd_ring	-	set up receive ring
  *	@vptr: velocity to configure
@@ -976,9 +1069,7 @@ static void velocity_free_rings(struct velocity_info *vptr)
 
 static int velocity_init_rd_ring(struct velocity_info *vptr)
 {
-	int i, ret = -ENOMEM;
-	struct rx_desc *rd;
-	struct velocity_rd_info *rd_info;
+	int ret = -ENOMEM;
 	unsigned int rsize = sizeof(struct velocity_rd_info) * 
 					vptr->options.numrx;
 
@@ -987,28 +1078,20 @@ static int velocity_init_rd_ring(struct velocity_info *vptr)
 		goto out;
 	memset(vptr->rd_info, 0, rsize);
 
-	/* Init the RD ring entries */
-	for (i = 0; i < vptr->options.numrx; i++) {
-		rd = &(vptr->rd_ring[i]);
-		rd_info = &(vptr->rd_info[i]);
+	vptr->rd_filled = vptr->rd_dirty = vptr->rd_curr = 0;
 
-		ret = velocity_alloc_rx_buf(vptr, i);
-		if (ret < 0) {
-			VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR
-				"%s: failed to allocate RX buffer.\n", 
-				vptr->dev->name);
-			velocity_free_rd_ring(vptr);
-			goto out;
-		}
-		rd->rdesc0.owner = OWNED_BY_NIC;
+	ret = velocity_rx_refill(vptr);
+	if (ret < 0) {
+		VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR
+			"%s: failed to allocate RX buffer.\n", vptr->dev->name);
+		velocity_free_rd_ring(vptr);
 	}
-	vptr->rd_used = vptr->rd_curr = 0;
 out:
 	return ret;
 }
 
 /**
- *	velocity_free_rd_ring	-	set up receive ring
+ *	velocity_free_rd_ring	-	free receive ring
  *	@vptr: velocity to clean up
  *
  *	Free the receive buffers for each ring slot and any
@@ -1025,7 +1108,7 @@ static void velocity_free_rd_ring(struct velocity_info *vptr)
 	for (i = 0; i < vptr->options.numrx; i++) {
 		struct velocity_rd_info *rd_info = &(vptr->rd_info[i]);
 
-		if (!rd_info->skb_dma)
+		if (!rd_info->skb)
 			continue;
 		pci_unmap_single(vptr->pdev, rd_info->skb_dma, vptr->rx_buf_sz,
 				 PCI_DMA_FROMDEVICE);
@@ -1073,8 +1156,10 @@ static int velocity_init_td_ring(struct velocity_info *vptr)
 		for (i = 0; i < vptr->options.numtx; i++, curr += sizeof(struct tx_desc)) {
 			td = &(vptr->td_rings[j][i]);
 			td_info = &(vptr->td_infos[j][i]);
-			td_info->buf = vptr->tx_bufs + (i + j) * PKT_BUF_SZ;
-			td_info->buf_dma = vptr->tx_bufs_dma + (i + j) * PKT_BUF_SZ;
+			td_info->buf = vptr->tx_bufs +
+				(j * vptr->options.numtx + i) * PKT_BUF_SZ;
+			td_info->buf_dma = vptr->tx_bufs_dma +
+				(j * vptr->options.numtx + i) * PKT_BUF_SZ;
 		}
 		vptr->td_tail[j] = vptr->td_curr[j] = vptr->td_used[j] = 0;
 	}
@@ -1146,40 +1231,27 @@ static void velocity_free_td_ring(struct velocity_info *vptr)
  
 static int velocity_rx_srv(struct velocity_info *vptr, int status)
 {
-	struct rx_desc *rd;
 	struct net_device_stats *stats = &vptr->stats;
-	struct mac_regs * regs = vptr->mac_regs;
 	int rd_curr = vptr->rd_curr;
 	int works = 0;
 
-	while (1) {
-
-		rd = &(vptr->rd_ring[rd_curr]);
+	do {
+		struct rx_desc *rd = vptr->rd_ring + rd_curr;
 
-		if ((vptr->rd_info[rd_curr]).skb == NULL) {
-			if (velocity_alloc_rx_buf(vptr, rd_curr) < 0)
-				break;
-		}
-
-		if (works++ > 15)
+		if (!vptr->rd_info[rd_curr].skb)
 			break;
 
 		if (rd->rdesc0.owner == OWNED_BY_NIC)
 			break;
 
+		rmb();
+
 		/*
 		 *	Don't drop CE or RL error frame although RXOK is off
-		 *	FIXME: need to handle copybreak
 		 */
 		if ((rd->rdesc0.RSR & RSR_RXOK) || (!(rd->rdesc0.RSR & RSR_RXOK) && (rd->rdesc0.RSR & (RSR_CE | RSR_RL)))) {
-			if (velocity_receive_frame(vptr, rd_curr) == 0) {
-				if (velocity_alloc_rx_buf(vptr, rd_curr) < 0) {
-					VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR "%s: can not allocate rx buf\n", vptr->dev->name);
-					break;
-				}
-			} else {
+			if (velocity_receive_frame(vptr, rd_curr) < 0)
 				stats->rx_dropped++;
-			}
 		} else {
 			if (rd->rdesc0.RSR & RSR_CRC)
 				stats->rx_crc_errors++;
@@ -1191,26 +1263,20 @@ static int velocity_rx_srv(struct velocity_info *vptr, int status)
 
 		rd->inten = 1;
 
-		if (++vptr->rd_used >= 4) {
-			int i, rd_prev = rd_curr;
-			for (i = 0; i < 4; i++) {
-				if (--rd_prev < 0)
-					rd_prev = vptr->options.numrx - 1;
-
-				rd = &(vptr->rd_ring[rd_prev]);
-				rd->rdesc0.owner = OWNED_BY_NIC;
-			}
-			writew(4, &(regs->RBRDU));
-			vptr->rd_used -= 4;
-		}
-
 		vptr->dev->last_rx = jiffies;
 
 		rd_curr++;
 		if (rd_curr >= vptr->options.numrx)
 			rd_curr = 0;
-	}
+	} while (++works <= 15);
+
 	vptr->rd_curr = rd_curr;
+
+	if (works > 0 && velocity_rx_refill(vptr) < 0) {
+		VELOCITY_PRT(MSG_LEVEL_ERR, KERN_ERR
+			"%s: rx buf allocation failure\n", vptr->dev->name);
+	}
+
 	VAR_USED(stats);
 	return works;
 }
@@ -1241,6 +1307,65 @@ static inline void velocity_rx_csum(struct rx_desc *rd, struct sk_buff *skb)
 	}
 }
 
+/**
+ *	velocity_rx_copy	-	in place Rx copy for small packets
+ *	@rx_skb: network layer packet buffer candidate
+ *	@pkt_size: received data size
+ *	@rd: receive packet descriptor
+ *	@dev: network device
+ *
+ *	Replace the current skb that is scheduled for Rx processing by a
+ *	shorter, immediatly allocated skb, if the received packet is small
+ *	enough. This function returns a negative value if the received
+ *	packet is too big or if memory is exhausted.
+ */
+static inline int velocity_rx_copy(struct sk_buff **rx_skb, int pkt_size,
+				   struct velocity_info *vptr)
+{
+	int ret = -1;
+
+	if (pkt_size < rx_copybreak) {
+		struct sk_buff *new_skb;
+
+		new_skb = dev_alloc_skb(pkt_size + 2);
+		if (new_skb) {
+			new_skb->dev = vptr->dev;
+			new_skb->ip_summed = rx_skb[0]->ip_summed;
+
+			if (vptr->flags & VELOCITY_FLAGS_IP_ALIGN)
+				skb_reserve(new_skb, 2);
+
+			memcpy(new_skb->data, rx_skb[0]->tail, pkt_size);
+			*rx_skb = new_skb;
+			ret = 0;
+		}
+		
+	}
+	return ret;
+}
+
+/**
+ *	velocity_iph_realign	-	IP header alignment
+ *	@vptr: velocity we are handling
+ *	@skb: network layer packet buffer
+ *	@pkt_size: received data size
+ *
+ *	Align IP header on a 2 bytes boundary. This behavior can be
+ *	configured by the user.
+ */
+static inline void velocity_iph_realign(struct velocity_info *vptr,
+					struct sk_buff *skb, int pkt_size)
+{
+	/* FIXME - memmove ? */
+	if (vptr->flags & VELOCITY_FLAGS_IP_ALIGN) {
+		int i;
+
+		for (i = pkt_size; i >= 0; i--)
+			*(skb->data + i + 2) = *(skb->data + i);
+		skb_reserve(skb, 2);
+	}
+}
+
 /**
  *	velocity_receive_frame	-	received packet processor
  *	@vptr: velocity we are handling
@@ -1252,9 +1377,11 @@ static inline void velocity_rx_csum(struct rx_desc *rd, struct sk_buff *skb)
  
 static int velocity_receive_frame(struct velocity_info *vptr, int idx)
 {
+	void (*pci_action)(struct pci_dev *, dma_addr_t, size_t, int);
 	struct net_device_stats *stats = &vptr->stats;
 	struct velocity_rd_info *rd_info = &(vptr->rd_info[idx]);
 	struct rx_desc *rd = &(vptr->rd_ring[idx]);
+	int pkt_len = rd->rdesc0.len;
 	struct sk_buff *skb;
 
 	if (rd->rdesc0.RSR & (RSR_STP | RSR_EDP)) {
@@ -1269,22 +1396,8 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
 	skb = rd_info->skb;
 	skb->dev = vptr->dev;
 
-	pci_unmap_single(vptr->pdev, rd_info->skb_dma, vptr->rx_buf_sz, 
-							PCI_DMA_FROMDEVICE);
-	rd_info->skb_dma = (dma_addr_t) NULL;
-	rd_info->skb = NULL;
-
-	/* FIXME - memmove ? */
-	if (vptr->flags & VELOCITY_FLAGS_IP_ALIGN) {
-		int i;
-		for (i = rd->rdesc0.len + 4; i >= 0; i--)
-			*(skb->data + i + 2) = *(skb->data + i);
-		skb->data += 2;
-		skb->tail += 2;
-	}
-
-	skb_put(skb, (rd->rdesc0.len - 4));
-	skb->protocol = eth_type_trans(skb, skb->dev);
+	pci_dma_sync_single_for_cpu(vptr->pdev, rd_info->skb_dma,
+				    vptr->rx_buf_sz, PCI_DMA_FROMDEVICE);
 
 	/*
 	 *	Drop frame not meeting IEEE 802.3
@@ -1297,13 +1410,23 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
 		}
 	}
 
+	pci_action = pci_dma_sync_single_for_device;
+
 	velocity_rx_csum(rd, skb);
-	
-	/*
-	 *	FIXME: need rx_copybreak handling
-	 */
 
-	stats->rx_bytes += skb->len;
+	if (velocity_rx_copy(&skb, pkt_len, vptr) < 0) {
+		velocity_iph_realign(vptr, skb, pkt_len);
+		pci_action = pci_unmap_single;
+		rd_info->skb = NULL;
+	}
+
+	pci_action(vptr->pdev, rd_info->skb_dma, vptr->rx_buf_sz,
+		   PCI_DMA_FROMDEVICE);
+
+	skb_put(skb, pkt_len - 4);
+	skb->protocol = eth_type_trans(skb, skb->dev);	
+
+	stats->rx_bytes += pkt_len;
 	netif_rx(skb);
 
 	return 0;
@@ -1962,32 +2085,6 @@ static int velocity_intr(int irq, void *dev_instance, struct pt_regs *regs)
 }
 
 
-/**
- *	ether_crc	-	ethernet CRC function
- *
- *	Compute an ethernet CRC hash of the data block provided. This
- *	is not performance optimised but is not needed in performance
- *	critical code paths.
- *
- *	FIXME: could we use shared code here ?
- */
- 
-static inline u32 ether_crc(int length, unsigned char *data)
-{
-	static unsigned const ethernet_polynomial = 0x04c11db7U;
-	
-	int crc = -1;
-
-	while (--length >= 0) {
-		unsigned char current_octet = *data++;
-		int bit;
-		for (bit = 0; bit < 8; bit++, current_octet >>= 1) {
-			crc = (crc << 1) ^ ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0);
-		}
-	}
-	return crc;
-}
-
 /**
  *	velocity_set_multi	-	filter list change callback
  *	@dev: network device
@@ -2123,13 +2220,13 @@ static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
  */
  
 static struct pci_driver velocity_driver = {
-      name:VELOCITY_NAME,
-      id_table:velocity_id_table,
-      probe:velocity_found1,
-      remove:velocity_remove1,
+      .name	= VELOCITY_NAME,
+      .id_table	= velocity_id_table,
+      .probe	= velocity_found1,
+      .remove	= __devexit_p(velocity_remove1),
 #ifdef CONFIG_PM
-      suspend:velocity_suspend,
-      resume:velocity_resume,
+      .suspend	= velocity_suspend,
+      .resume	= velocity_resume,
 #endif
 };
 
@@ -2145,11 +2242,11 @@ static struct pci_driver velocity_driver = {
 static int __init velocity_init_module(void)
 {
 	int ret;
-	ret = pci_module_init(&velocity_driver);
 
-#ifdef CONFIG_PM
-	register_inetaddr_notifier(&velocity_inetaddr_notifier);
-#endif
+	velocity_register_notifier();
+	ret = pci_module_init(&velocity_driver);
+	if (ret < 0)
+		velocity_unregister_notifier();
 	return ret;
 }
 
@@ -2164,9 +2261,7 @@ static int __init velocity_init_module(void)
  
 static void __exit velocity_cleanup_module(void)
 {
-#ifdef CONFIG_PM
-	unregister_inetaddr_notifier(&velocity_inetaddr_notifier);
-#endif
+	velocity_unregister_notifier();
 	pci_unregister_driver(&velocity_driver);
 }
 
@@ -2992,172 +3087,6 @@ static void velocity_restore_context(struct velocity_info *vptr, struct velocity
 
 }
 
-static int velocity_suspend(struct pci_dev *pdev, u32 state)
-{
-	struct velocity_info *vptr = pci_get_drvdata(pdev);
-	unsigned long flags;
-	
-	if(!netif_running(vptr->dev))
-		return 0;
-		
-	netif_device_detach(vptr->dev);
-	
-	spin_lock_irqsave(&vptr->lock, flags);
-	pci_save_state(pdev, vptr->pci_state);
-#ifdef ETHTOOL_GWOL
-	if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED) {
-		velocity_get_ip(vptr);
-		velocity_save_context(vptr, &vptr->context);
-		velocity_shutdown(vptr);
-		velocity_set_wol(vptr);
-		pci_enable_wake(pdev, 3, 1);
-		pci_set_power_state(pdev, 3);
-	} else {
-		velocity_save_context(vptr, &vptr->context);
-		velocity_shutdown(vptr);
-		pci_disable_device(pdev);
-		pci_set_power_state(pdev, state);
-	}
-#else
-	pci_set_power_state(pdev, state);
-#endif
-	spin_unlock_irqrestore(&vptr->lock, flags);
-	return 0;
-}
-
-static int velocity_resume(struct pci_dev *pdev)
-{
-	struct velocity_info *vptr = pci_get_drvdata(pdev);
-	unsigned long flags;
-	int i;
-	
-	if(!netif_running(vptr->dev))
-		return 0;
-		
-	pci_set_power_state(pdev, 0);
-	pci_enable_wake(pdev, 0, 0);
-	pci_restore_state(pdev, vptr->pci_state);
-
-	mac_wol_reset(vptr->mac_regs);
-
-	spin_lock_irqsave(&vptr->lock, flags);
-	velocity_restore_context(vptr, &vptr->context);
-	velocity_init_registers(vptr, VELOCITY_INIT_WOL);
-	mac_disable_int(vptr->mac_regs);
-
-	velocity_tx_srv(vptr, 0);
-
-	for (i = 0; i < vptr->num_txq; i++) {
-		if (vptr->td_used[i]) {
-			mac_tx_queue_wake(vptr->mac_regs, i);
-		}
-	}
-
-	mac_enable_int(vptr->mac_regs);
-	spin_unlock_irqrestore(&vptr->lock, flags);
-	netif_device_attach(vptr->dev);
-
-	return 0;
-}
-
-static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
-{
-	struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
-	struct net_device *dev;
-	struct velocity_info *vptr;
-
-	if (ifa) {
-		dev = ifa->ifa_dev->dev;
-		vptr = dev->priv;
-		velocity_get_ip(vptr);
-	}
-	return NOTIFY_DONE;
-}
-#endif
-
-/*
- * Purpose: Functions to set WOL.
- */
-
-const static unsigned short crc16_tab[256] = {
-	0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
-	0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
-	0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
-	0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
-	0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
-	0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
-	0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
-	0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
-	0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
-	0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
-	0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
-	0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
-	0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
-	0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
-	0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
-	0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
-	0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
-	0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
-	0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
-	0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
-	0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
-	0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
-	0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
-	0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
-	0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
-	0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
-	0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
-	0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
-	0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
-	0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
-	0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
-	0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
-};
-
-
-static u32 mask_pattern[2][4] = {
-	{0x00203000, 0x000003C0, 0x00000000, 0x0000000},	/* ARP		*/
-	{0xfffff000, 0xffffffff, 0xffffffff, 0x000ffff}		/* Magic Packet */ 
-};
-
-/**
- *	ether_crc16	-	compute ethernet CRC
- *	@len: buffer length
- *	@cp: buffer
- *	@crc16: initial CRC
- *
- *	Compute a CRC value for a block of data. 
- *	FIXME: can we use generic functions ?
- */
- 
-static u16 ether_crc16(int len, u8 * cp, u16 crc16)
-{
-	while (len--)
-		crc16 = (crc16 >> 8) ^ crc16_tab[(crc16 ^ *cp++) & 0xff];
-	return (crc16);
-}
-
-/**
- *	bit_reverse		-	16bit reverse
- *	@data: 16bit data t reverse
- *
- *	Reverse the order of a 16bit value and return the reversed bits
- */
- 
-static u16 bit_reverse(u16 data)
-{
-	u32 new = 0x00000000;
-	int ii;
-
-
-	for (ii = 0; ii < 16; ii++) {
-		new |= ((u32) (data & 1) << (31 - ii));
-		data >>= 1;
-	}
-
-	return (u16) (new >> 16);
-}
-
 /**
  *	wol_calc_crc		-	WOL CRC
  *	@pattern: data pattern
@@ -3166,7 +3095,7 @@ static u16 bit_reverse(u16 data)
  *	Compute the wake on lan crc hashes for the packet header
  *	we are interested in.
  */
- 
+
 u16 wol_calc_crc(int size, u8 * pattern, u8 *mask_pattern)
 {
 	u16 crc = 0xFFFF;
@@ -3186,12 +3115,12 @@ u16 wol_calc_crc(int size, u8 * pattern, u8 *mask_pattern)
 				continue;
 			}
 			mask >>= 1;
-			crc = ether_crc16(1, &(pattern[i * 8 + j]), crc);
+			crc = crc_ccitt(crc, &(pattern[i * 8 + j]), 1);
 		}
 	}
 	/*	Finally, invert the result once to get the correct data */
 	crc = ~crc;
-	return bit_reverse(crc);
+	return bitreverse(crc) >> 16;
 }
 
 /**
@@ -3203,13 +3132,18 @@ u16 wol_calc_crc(int size, u8 * pattern, u8 *mask_pattern)
  *
  *	FIXME: check static buffer is safe here
  */
- 
+
 static int velocity_set_wol(struct velocity_info *vptr)
 {
 	struct mac_regs * regs = vptr->mac_regs;
 	static u8 buf[256];
 	int i;
 
+	static u32 mask_pattern[2][4] = {
+		{0x00203000, 0x000003C0, 0x00000000, 0x0000000}, /* ARP */
+		{0xfffff000, 0xffffffff, 0xffffffff, 0x000ffff}	 /* Magic Packet */
+	};
+
 	writew(0xFFFF, &regs->WOLCRClr);
 	writeb(WOLCFG_SAB | WOLCFG_SAM, &regs->WOLCFGSet);
 	writew(WOLCR_MAGIC_EN, &regs->WOLCRSet);
@@ -3236,7 +3170,8 @@ static int velocity_set_wol(struct velocity_info *vptr)
 
 		memcpy(arp->ar_tip, vptr->ip_addr, 4);
 
-		crc = wol_calc_crc((sizeof(struct arp_packet) + 7) / 8, buf, (u8 *) & mask_pattern[0][0]);
+		crc = wol_calc_crc((sizeof(struct arp_packet) + 7) / 8, buf,
+				(u8 *) & mask_pattern[0][0]);
 
 		writew(crc, &regs->PatternCRC[0]);
 		writew(WOLCR_ARP_EN, &regs->WOLCRSet);
@@ -3275,3 +3210,92 @@ static int velocity_set_wol(struct velocity_info *vptr)
 	return 0;
 }
 
+static int velocity_suspend(struct pci_dev *pdev, u32 state)
+{
+	struct velocity_info *vptr = pci_get_drvdata(pdev);
+	unsigned long flags;
+
+	if(!netif_running(vptr->dev))
+		return 0;
+
+	netif_device_detach(vptr->dev);
+
+	spin_lock_irqsave(&vptr->lock, flags);
+	pci_save_state(pdev, vptr->pci_state);
+#ifdef ETHTOOL_GWOL
+	if (vptr->flags & VELOCITY_FLAGS_WOL_ENABLED) {
+		velocity_get_ip(vptr);
+		velocity_save_context(vptr, &vptr->context);
+		velocity_shutdown(vptr);
+		velocity_set_wol(vptr);
+		pci_enable_wake(pdev, 3, 1);
+		pci_set_power_state(pdev, 3);
+	} else {
+		velocity_save_context(vptr, &vptr->context);
+		velocity_shutdown(vptr);
+		pci_disable_device(pdev);
+		pci_set_power_state(pdev, state);
+	}
+#else
+	pci_set_power_state(pdev, state);
+#endif
+	spin_unlock_irqrestore(&vptr->lock, flags);
+	return 0;
+}
+
+static int velocity_resume(struct pci_dev *pdev)
+{
+	struct velocity_info *vptr = pci_get_drvdata(pdev);
+	unsigned long flags;
+	int i;
+
+	if(!netif_running(vptr->dev))
+		return 0;
+
+	pci_set_power_state(pdev, 0);
+	pci_enable_wake(pdev, 0, 0);
+	pci_restore_state(pdev, vptr->pci_state);
+
+	mac_wol_reset(vptr->mac_regs);
+
+	spin_lock_irqsave(&vptr->lock, flags);
+	velocity_restore_context(vptr, &vptr->context);
+	velocity_init_registers(vptr, VELOCITY_INIT_WOL);
+	mac_disable_int(vptr->mac_regs);
+
+	velocity_tx_srv(vptr, 0);
+
+	for (i = 0; i < vptr->num_txq; i++) {
+		if (vptr->td_used[i]) {
+			mac_tx_queue_wake(vptr->mac_regs, i);
+		}
+	}
+
+	mac_enable_int(vptr->mac_regs);
+	spin_unlock_irqrestore(&vptr->lock, flags);
+	netif_device_attach(vptr->dev);
+
+	return 0;
+}
+
+static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr)
+{
+	struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
+
+	if (ifa) {
+		struct net_device *dev = ifa->ifa_dev->dev;
+		struct velocity_info *vptr;
+		unsigned long flags;
+
+		spin_lock_irqsave(&velocity_dev_list_lock, flags);
+		list_for_each_entry(vptr, &velocity_dev_list, list) {
+			if (vptr->dev == dev) {
+				velocity_get_ip(vptr);
+				break;
+			}
+		}
+		spin_unlock_irqrestore(&velocity_dev_list_lock, flags);
+	}
+	return NOTIFY_DONE;
+}
+#endif
diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h
index 2175b8696..9a187de48 100644
--- a/drivers/net/via-velocity.h
+++ b/drivers/net/via-velocity.h
@@ -37,7 +37,6 @@
 #define OPTION_DEFAULT      { [0 ... MAX_UNITS-1] = -1}
 
 #define REV_ID_VT6110       (0)
-#define DEVICE_ID           (0x3119)
 
 #define BYTE_REG_BITS_ON(x,p)       do { writeb(readb((p))|(x),(p));} while (0)
 #define WORD_REG_BITS_ON(x,p)       do { writew(readw((p))|(x),(p));} while (0)
@@ -1320,7 +1319,7 @@ static inline void mac_set_cam_mask(struct mac_regs * regs, u8 * mask, enum velo
 	/* disable CAMEN */
 	writeb(0, &regs->CAMADDR);
 
-	/* Select CAM mask */
+	/* Select mar */
 	BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
 }
 
@@ -1361,7 +1360,7 @@ static inline void mac_set_cam(struct mac_regs * regs, int idx, u8 *addr, enum v
 
 	writeb(0, &regs->CAMADDR);
 
-	/* Select CAM mask */
+	/* Select mar */
 	BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
 }
 
@@ -1402,7 +1401,7 @@ static inline void mac_get_cam(struct mac_regs * regs, int idx, u8 *addr, enum v
 
 	writeb(0, &regs->CAMADDR);
 
-	/* Select CAM mask */
+	/* Select mar */
 	BYTE_REG_BITS_SET(CAMCR_PS_MAR, CAMCR_PS1 | CAMCR_PS0, &regs->CAMCR);
 }
 
@@ -1734,14 +1733,13 @@ struct velocity_opt {
 };
 
 struct velocity_info {
-	struct velocity_info *next;
-	struct velocity_info *prev;
+	struct list_head list;
 
 	struct pci_dev *pdev;
 	struct net_device *dev;
 	struct net_device_stats stats;
 
-#if CONFIG_PM
+#ifdef CONFIG_PM
 	u32 pci_state[16];
 #endif
 
@@ -1772,7 +1770,8 @@ struct velocity_info {
 	struct velocity_td_info *td_infos[TX_QUEUE_NO];
 
 	int rd_curr;
-	int rd_used;
+	int rd_dirty;
+	u32 rd_filled;
 	struct rx_desc *rd_ring;
 	struct velocity_rd_info *rd_info;	/* It's an array */
 
@@ -1793,7 +1792,6 @@ struct velocity_info {
 	u8 mCAMmask[(MCAM_SIZE / 8)];
 
 	spinlock_t lock;
-	spinlock_t xmit_lock;
 
 	int wol_opts;
 	u8 wol_passwd[6];
diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c
index cd1cd8569..07bfe107a 100644
--- a/drivers/net/wan/cycx_x25.c
+++ b/drivers/net/wan/cycx_x25.c
@@ -186,7 +186,7 @@ static void nibble_to_byte(u8 *s, u8 *d, u8 len, u8 nibble),
 	    reset_timer(struct net_device *dev);
 
 static u8 bps_to_speed_code(u32 bps);
-static u8 log2(u32 n);
+static u8 cycx_log2(u32 n);
 
 static unsigned dec_to_uint(u8 *str, int len);
 
@@ -263,7 +263,7 @@ int cycx_x25_wan_init(struct cycx_device *card, wandev_conf_t *conf)
 	else
 		card->wandev.mtu = 64;
 
-	cfg.pktlen = log2(card->wandev.mtu);
+	cfg.pktlen = cycx_log2(card->wandev.mtu);
 
 	if (conf->station == WANOPT_DTE) {
 		cfg.locaddr = 3; /* DTE */
@@ -1513,7 +1513,7 @@ static u8 bps_to_speed_code(u32 bps)
 }
 
 /* log base 2 */
-static u8 log2(u32 n)
+static u8 cycx_log2(u32 n)
 {
 	u8 log = 0;
 
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index 4cbda752b..fffe12085 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -351,8 +351,8 @@ struct dscc4_dev_priv {
 #endif
 
 /* Functions prototypes */
-static inline void dscc4_rx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *);
-static inline void dscc4_tx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *);
+static void dscc4_rx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *);
+static void dscc4_tx_irq(struct dscc4_pci_priv *, struct dscc4_dev_priv *);
 static int dscc4_found1(struct pci_dev *, unsigned long ioaddr);
 static int dscc4_init_one(struct pci_dev *, const struct pci_device_id *ent);
 static int dscc4_open(struct net_device *);
@@ -366,7 +366,6 @@ static void dscc4_tx_timeout(struct net_device *);
 static irqreturn_t dscc4_irq(int irq, void *dev_id, struct pt_regs *ptregs);
 static int dscc4_hdlc_attach(struct net_device *, unsigned short, unsigned short);
 static int dscc4_set_iface(struct dscc4_dev_priv *, struct net_device *);
-static inline int dscc4_set_quartz(struct dscc4_dev_priv *, int);
 #ifdef DSCC4_POLLING
 static int dscc4_tx_poll(struct dscc4_dev_priv *, struct net_device *);
 #endif
@@ -866,6 +865,18 @@ static void dscc4_init_registers(struct dscc4_dev_priv *dpriv,
 	//scc_writel(0x00250008 & ~RxActivate, dpriv, dev, CCR2);
 }
 
+static inline int dscc4_set_quartz(struct dscc4_dev_priv *dpriv, int hz)
+{
+	int ret = 0;
+
+	if ((hz < 0) || (hz > DSCC4_HZ_MAX))
+		ret = -EOPNOTSUPP;
+	else
+		dpriv->pci_priv->xtal_hz = hz;
+
+	return ret;
+}
+
 static int dscc4_found1(struct pci_dev *pdev, unsigned long ioaddr)
 {
 	struct dscc4_pci_priv *ppriv;
@@ -1340,18 +1351,6 @@ static int dscc4_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	return ret;
 }
 
-static inline int dscc4_set_quartz(struct dscc4_dev_priv *dpriv, int hz)
-{
-	int ret = 0;
-
-	if ((hz < 0) || (hz > DSCC4_HZ_MAX))
-		ret = -EOPNOTSUPP;
-	else
-		dpriv->pci_priv->xtal_hz = hz;
-
-	return ret;
-}
-
 static int dscc4_match(struct thingie *p, int value)
 {
 	int i;
@@ -1531,7 +1530,7 @@ out:
 	return IRQ_RETVAL(handled);
 }
 
-static inline void dscc4_tx_irq(struct dscc4_pci_priv *ppriv,
+static void dscc4_tx_irq(struct dscc4_pci_priv *ppriv,
 				struct dscc4_dev_priv *dpriv)
 {
 	struct net_device *dev = dscc4_to_dev(dpriv);
@@ -1700,7 +1699,7 @@ try:
 	goto try;
 }
 
-static inline void dscc4_rx_irq(struct dscc4_pci_priv *priv,
+static void dscc4_rx_irq(struct dscc4_pci_priv *priv,
 				    struct dscc4_dev_priv *dpriv)
 {
 	struct net_device *dev = dscc4_to_dev(dpriv);
diff --git a/drivers/net/wan/hd6457x.c b/drivers/net/wan/hd6457x.c
index b7f6504a5..690a02fdf 100644
--- a/drivers/net/wan/hd6457x.c
+++ b/drivers/net/wan/hd6457x.c
@@ -463,8 +463,8 @@ static void sca_set_port(port_t *port)
 			brv >>= 1; /* brv = 2^9 = 512 max in specs */
 
 			/* Baud Rate = CLOCK_BASE / TMC / 2^BR */
-			tmc = CLOCK_BASE / (brv * port->settings.clock_rate);
-		}while(br > 1 && tmc <= 128);
+			tmc = CLOCK_BASE / brv / port->settings.clock_rate;
+		}while (br > 1 && tmc <= 128);
 
 		if (tmc < 1) {
 			tmc = 1;
@@ -473,7 +473,7 @@ static void sca_set_port(port_t *port)
 		} else if (tmc > 255)
 			tmc = 256; /* tmc=0 means 256 - low baud rates */
 
-		port->settings.clock_rate = CLOCK_BASE / (brv * tmc);
+		port->settings.clock_rate = CLOCK_BASE / brv / tmc;
 	} else {
 		br = 9; /* Minimum clock rate */
 		tmc = 256;	/* 8bit = 0 */
diff --git a/drivers/net/wan/lmc/lmc_debug.c b/drivers/net/wan/lmc/lmc_debug.c
index 058ff8048..9dccd9546 100644
--- a/drivers/net/wan/lmc/lmc_debug.c
+++ b/drivers/net/wan/lmc/lmc_debug.c
@@ -64,7 +64,7 @@ void lmcEventLog (u_int32_t EventNum, u_int32_t arg2, u_int32_t arg3)
 #endif
 }
 
-inline void lmc_trace(struct net_device *dev, char *msg){
+void lmc_trace(struct net_device *dev, char *msg){
 #ifdef LMC_TRACE
     unsigned long j = jiffies + 3; /* Wait for 50 ms */
 
diff --git a/drivers/net/wan/pc300.h b/drivers/net/wan/pc300.h
index e6af4921e..a4bfff8d1 100644
--- a/drivers/net/wan/pc300.h
+++ b/drivers/net/wan/pc300.h
@@ -164,9 +164,9 @@ typedef	unsigned char	ucchar;		/* 8 bits, unsigned */
  * (required to support Alpha systems) *
  ***************************************/
 #ifdef __KERNEL__
-#define cpc_writeb(port,val)	{writeb((ucchar)(val),(ulong)(port)); mb();}
-#define cpc_writew(port,val)	{writew((ushort)(val),(ulong)(port)); mb();}
-#define cpc_writel(port,val)	{writel((uclong)(val),(ulong)(port)); mb();}
+#define cpc_writeb(port,val)	{writeb((ucchar)(val),(port)); mb();}
+#define cpc_writew(port,val)	{writew((ushort)(val),(port)); mb();}
+#define cpc_writel(port,val)	{writel((uclong)(val),(port)); mb();}
 
 #define cpc_readb(port)		readb(port)
 #define cpc_readw(port)		readw(port)
@@ -358,17 +358,17 @@ typedef struct pc300hw {
 	uclong iophys;		/* PLX registers I/O base */
 	uclong iosize;		/* PLX registers I/O size */
 	uclong plxphys;		/* PLX registers MMIO base (physical) */
-	uclong plxbase;		/* PLX registers MMIO base (virtual) */
+	void __iomem * plxbase;	/* PLX registers MMIO base (virtual) */
 	uclong plxsize;		/* PLX registers MMIO size */
 	uclong scaphys;		/* SCA registers MMIO base (physical) */
-	uclong scabase;		/* SCA registers MMIO base (virtual) */
+	void __iomem * scabase;	/* SCA registers MMIO base (virtual) */
 	uclong scasize;		/* SCA registers MMIO size */
 	uclong ramphys;		/* On-board RAM MMIO base (physical) */
-	uclong rambase;		/* On-board RAM MMIO base (virtual) */
+	void __iomem * rambase;	/* On-board RAM MMIO base (virtual) */
 	uclong alloc_ramsize;	/* RAM MMIO size allocated by the PCI bridge */
 	uclong ramsize;		/* On-board RAM MMIO size */
 	uclong falcphys;	/* FALC registers MMIO base (physical) */
-	uclong falcbase;	/* FALC registers MMIO base (virtual) */
+	void __iomem * falcbase;/* FALC registers MMIO base (virtual) */
 	uclong falcsize;	/* FALC registers MMIO size */
 } pc300hw_t;
 
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index 29b82687b..7a972ca25 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -307,7 +307,7 @@ static void tx_dma_buf_pt_init(pc300_t * card, int ch)
 {
 	int i;
 	int ch_factor = ch * N_DMA_TX_BUF;
-	volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *) (card->hw.rambase
+	volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase
 			               + DMA_TX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
 
 	for (i = 0; i < N_DMA_TX_BUF; i++, ptdescr++) {
@@ -322,7 +322,7 @@ static void tx_dma_buf_init(pc300_t * card, int ch)
 {
 	int i;
 	int ch_factor = ch * N_DMA_TX_BUF;
-	volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *) (card->hw.rambase
+	volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase
 			       + DMA_TX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
 
 	for (i = 0; i < N_DMA_TX_BUF; i++, ptdescr++) {
@@ -337,7 +337,7 @@ static void rx_dma_buf_pt_init(pc300_t * card, int ch)
 {
 	int i;
 	int ch_factor = ch * N_DMA_RX_BUF;
-	volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *) (card->hw.rambase
+	volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase
 				       + DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
 
 	for (i = 0; i < N_DMA_RX_BUF; i++, ptdescr++) {
@@ -352,7 +352,7 @@ static void rx_dma_buf_init(pc300_t * card, int ch)
 {
 	int i;
 	int ch_factor = ch * N_DMA_RX_BUF;
-	volatile pcsca_bd_t *ptdescr = (pcsca_bd_t *) (card->hw.rambase
+	volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase
 				       + DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
 
 	for (i = 0; i < N_DMA_RX_BUF; i++, ptdescr++) {
@@ -365,7 +365,7 @@ static void rx_dma_buf_init(pc300_t * card, int ch)
 
 static void tx_dma_buf_check(pc300_t * card, int ch)
 {
-	volatile pcsca_bd_t *ptdescr;
+	volatile pcsca_bd_t __iomem *ptdescr;
 	int i;
 	ucshort first_bd = card->chan[ch].tx_first_bd;
 	ucshort next_bd = card->chan[ch].tx_next_bd;
@@ -374,10 +374,10 @@ static void tx_dma_buf_check(pc300_t * card, int ch)
 	       first_bd, TX_BD_ADDR(ch, first_bd),
 	       next_bd, TX_BD_ADDR(ch, next_bd));
 	for (i = first_bd,
-	     ptdescr = (pcsca_bd_t *) (card->hw.rambase + TX_BD_ADDR(ch, first_bd));
+	     ptdescr = (card->hw.rambase + TX_BD_ADDR(ch, first_bd));
 	     i != ((next_bd + 1) & (N_DMA_TX_BUF - 1));
 	     i = (i + 1) & (N_DMA_TX_BUF - 1), 
-		 ptdescr = (pcsca_bd_t *) (card->hw.rambase + TX_BD_ADDR(ch, i))) {
+		 ptdescr = (card->hw.rambase + TX_BD_ADDR(ch, i))) {
 		printk("\n CH%d TX%d: next=0x%lx, ptbuf=0x%lx, ST=0x%x, len=%d",
 		       ch, i, (uclong) cpc_readl(&ptdescr->next),
 		       (uclong) cpc_readl(&ptdescr->ptbuf),
@@ -390,7 +390,7 @@ static void tx_dma_buf_check(pc300_t * card, int ch)
 /* Show all TX buffer descriptors */
 static void tx1_dma_buf_check(pc300_t * card, int ch)
 {
-	volatile pcsca_bd_t *ptdescr;
+	volatile pcsca_bd_t __iomem *ptdescr;
 	int i;
 	ucshort first_bd = card->chan[ch].tx_first_bd;
 	ucshort next_bd = card->chan[ch].tx_next_bd;
@@ -404,7 +404,7 @@ static void tx1_dma_buf_check(pc300_t * card, int ch)
 	       (uclong) cpc_readl(scabase + DTX_REG(CDAL, ch)),
 	       (uclong) cpc_readl(scabase + DTX_REG(EDAL, ch)));
 	for (i = 0; i < N_DMA_TX_BUF; i++) {
-		ptdescr = (pcsca_bd_t *) (card->hw.rambase + TX_BD_ADDR(ch, i));
+		ptdescr = (card->hw.rambase + TX_BD_ADDR(ch, i));
 		printk("\n CH%d TX%d: next=0x%lx, ptbuf=0x%lx, ST=0x%x, len=%d",
 		       ch, i, (uclong) cpc_readl(&ptdescr->next),
 		       (uclong) cpc_readl(&ptdescr->ptbuf),
@@ -416,7 +416,7 @@ static void tx1_dma_buf_check(pc300_t * card, int ch)
 			 
 static void rx_dma_buf_check(pc300_t * card, int ch)
 {
-	volatile pcsca_bd_t *ptdescr;
+	volatile pcsca_bd_t __iomem *ptdescr;
 	int i;
 	ucshort first_bd = card->chan[ch].rx_first_bd;
 	ucshort last_bd = card->chan[ch].rx_last_bd;
@@ -424,7 +424,7 @@ static void rx_dma_buf_check(pc300_t * card, int ch)
 
 	ch_factor = ch * N_DMA_RX_BUF;
 	printk("#CH%d: f_bd = %d, l_bd = %d\n", ch, first_bd, last_bd);
-	for (i = 0, ptdescr = (pcsca_bd_t *) (card->hw.rambase +
+	for (i = 0, ptdescr = (card->hw.rambase +
 					      DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
 	     i < N_DMA_RX_BUF; i++, ptdescr++) {
 		if (cpc_readb(&ptdescr->status) & DST_OSB)
@@ -439,12 +439,12 @@ static void rx_dma_buf_check(pc300_t * card, int ch)
 
 int dma_get_rx_frame_size(pc300_t * card, int ch)
 {
-	volatile pcsca_bd_t *ptdescr;
+	volatile pcsca_bd_t __iomem *ptdescr;
 	ucshort first_bd = card->chan[ch].rx_first_bd;
 	int rcvd = 0;
 	volatile ucchar status;
 
-	ptdescr = (pcsca_bd_t *)(card->hw.rambase + RX_BD_ADDR(ch, first_bd));
+	ptdescr = (card->hw.rambase + RX_BD_ADDR(ch, first_bd));
 	while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) {
 		rcvd += cpc_readw(&ptdescr->len);
 		first_bd = (first_bd + 1) & (N_DMA_RX_BUF - 1);
@@ -453,7 +453,7 @@ int dma_get_rx_frame_size(pc300_t * card, int ch)
 			* (dma_buf_read will clean the buffer descriptors in this case). */
 			return (rcvd);
 		}
-		ptdescr = (pcsca_bd_t *)(card->hw.rambase + cpc_readl(&ptdescr->next));
+		ptdescr = (card->hw.rambase + cpc_readl(&ptdescr->next));
 	}
 	return (-1);
 }
@@ -465,7 +465,7 @@ int dma_get_rx_frame_size(pc300_t * card, int ch)
 int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len)
 {
 	int i, nchar;
-	volatile pcsca_bd_t *ptdescr;
+	volatile pcsca_bd_t __iomem *ptdescr;
 	int tosend = len;
 	ucchar nbuf = ((len - 1) / BD_DEF_LEN) + 1;
 
@@ -474,11 +474,11 @@ int dma_buf_write(pc300_t * card, int ch, ucchar * ptdata, int len)
 	}
 
 	for (i = 0; i < nbuf; i++) {
-		ptdescr = (pcsca_bd_t *) (card->hw.rambase +
+		ptdescr = (card->hw.rambase +
 					  TX_BD_ADDR(ch, card->chan[ch].tx_next_bd));
 		nchar = cpc_min(BD_DEF_LEN, tosend);
 		if (cpc_readb(&ptdescr->status) & DST_OSB) {
-			memcpy_toio((void *)(card->hw.rambase + cpc_readl(&ptdescr->ptbuf)),
+			memcpy_toio((card->hw.rambase + cpc_readl(&ptdescr->ptbuf)),
 				    &ptdata[len - tosend], nchar);
 			cpc_writew(&ptdescr->len, nchar);
 			card->chan[ch].nfree_tx_bd--;
@@ -507,11 +507,11 @@ int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
 {
 	int nchar;
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-	volatile pcsca_bd_t *ptdescr;
+	volatile pcsca_bd_t __iomem *ptdescr;
 	int rcvd = 0;
 	volatile ucchar status;
 
-	ptdescr = (pcsca_bd_t *) (card->hw.rambase +
+	ptdescr = (card->hw.rambase +
 				  RX_BD_ADDR(ch, chan->rx_first_bd));
 	while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) {
 		nchar = cpc_readw(&ptdescr->len);
@@ -527,7 +527,7 @@ int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
 				chan->rx_first_bd = (chan->rx_first_bd+1) & (N_DMA_RX_BUF-1);
 				if (status & DST_EOM)
 					break;
-				ptdescr = (pcsca_bd_t *) (card->hw.rambase +
+				ptdescr = (card->hw.rambase +
 							  cpc_readl(&ptdescr->next));
 				status = cpc_readb(&ptdescr->status);
 			}
@@ -536,7 +536,7 @@ int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
 		if (nchar != 0) {
 			if (skb) {
 				memcpy_fromio(skb_put(skb, nchar),
-				 (void *)(card->hw.rambase+cpc_readl(&ptdescr->ptbuf)),nchar);
+				 (card->hw.rambase+cpc_readl(&ptdescr->ptbuf)),nchar);
 			}
 			rcvd += nchar;
 		}
@@ -547,7 +547,7 @@ int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
 		if (status & DST_EOM)
 			break;
 
-		ptdescr = (pcsca_bd_t *) (card->hw.rambase + cpc_readl(&ptdescr->next));
+		ptdescr = (card->hw.rambase + cpc_readl(&ptdescr->next));
 	}
 
 	if (rcvd != 0) {
@@ -562,7 +562,7 @@ int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
 
 void tx_dma_stop(pc300_t * card, int ch)
 {
-	uclong scabase = card->hw.scabase;
+	void __iomem *scabase = card->hw.scabase;
 	ucchar drr_ena_bit = 1 << (5 + 2 * ch);
 	ucchar drr_rst_bit = 1 << (1 + 2 * ch);
 
@@ -573,7 +573,7 @@ void tx_dma_stop(pc300_t * card, int ch)
 
 void rx_dma_stop(pc300_t * card, int ch)
 {
-	uclong scabase = card->hw.scabase;
+	void __iomem *scabase = card->hw.scabase;
 	ucchar drr_ena_bit = 1 << (4 + 2 * ch);
 	ucchar drr_rst_bit = 1 << (2 * ch);
 
@@ -584,7 +584,7 @@ void rx_dma_stop(pc300_t * card, int ch)
 
 void rx_dma_start(pc300_t * card, int ch)
 {
-	uclong scabase = card->hw.scabase;
+	void __iomem *scabase = card->hw.scabase;
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	
 	/* Start DMA */
@@ -609,7 +609,7 @@ void rx_dma_start(pc300_t * card, int ch)
 /*************************/
 void falc_issue_cmd(pc300_t * card, int ch, ucchar cmd)
 {
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 	unsigned long i = 0;
 
 	while (cpc_readb(falcbase + F_REG(SIS, ch)) & SIS_CEC) {
@@ -627,7 +627,7 @@ void falc_intr_enable(pc300_t * card, int ch)
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	/* Interrupt pins are open-drain */
 	cpc_writeb(falcbase + F_REG(IPC, ch),
@@ -674,7 +674,7 @@ void falc_intr_enable(pc300_t * card, int ch)
 
 void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
 {
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 	ucchar tshf = card->chan[ch].falc.offset;
 
 	cpc_writeb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch),
@@ -690,7 +690,7 @@ void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
 
 void falc_close_timeslot(pc300_t * card, int ch, int timeslot)
 {
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 	ucchar tshf = card->chan[ch].falc.offset;
 
 	cpc_writeb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch),
@@ -708,7 +708,7 @@ void falc_close_all_timeslots(pc300_t * card, int ch)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	cpc_writeb(falcbase + F_REG(ICB1, ch), 0xff);
 	cpc_writeb(falcbase + F_REG(TTR1, ch), 0);
@@ -730,7 +730,7 @@ void falc_open_all_timeslots(pc300_t * card, int ch)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	cpc_writeb(falcbase + F_REG(ICB1, ch), 0);
 	if (conf->fr_mode == PC300_FR_UNFRAMED) {
@@ -811,7 +811,7 @@ void falc_init_t1(pc300_t * card, int ch)
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 	ucchar dja = (ch ? (LIM2_DJA2 | LIM2_DJA1) : 0);
 
 	/* Switch to T1 mode (PCM 24) */
@@ -980,7 +980,7 @@ void falc_init_e1(pc300_t * card, int ch)
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 	ucchar dja = (ch ? (LIM2_DJA2 | LIM2_DJA1) : 0);
 
 	/* Switch to E1 mode (PCM 30) */
@@ -1157,7 +1157,7 @@ void falc_init_e1(pc300_t * card, int ch)
 
 void falc_init_hdlc(pc300_t * card, int ch)
 {
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 
@@ -1186,7 +1186,7 @@ void te_config(pc300_t * card, int ch)
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 	ucchar dummy;
 	unsigned long flags;
 
@@ -1246,7 +1246,7 @@ void falc_check_status(pc300_t * card, int ch, unsigned char frs0)
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	/* Verify LOS */
 	if (frs0 & FRS0_LOS) {
@@ -1402,7 +1402,7 @@ void falc_update_stats(pc300_t * card, int ch)
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 	ucshort counter;
 
 	counter = cpc_readb(falcbase + F_REG(FECL, ch));
@@ -1455,7 +1455,7 @@ void falc_remote_loop(pc300_t * card, int ch, int loop_on)
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	if (loop_on) {
 		// EVENT_FALC_ABNORMAL
@@ -1499,7 +1499,7 @@ void falc_local_loop(pc300_t * card, int ch, int loop_on)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	if (loop_on) {
 		cpc_writeb(falcbase + F_REG(LIM0, ch),
@@ -1527,7 +1527,7 @@ void falc_payload_loop(pc300_t * card, int ch, int loop_on)
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	if (loop_on) {
 		// EVENT_FALC_ABNORMAL
@@ -1580,7 +1580,7 @@ void turn_off_xlu(pc300_t * card, int ch)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	if (conf->media == IF_IFACE_T1) {
 		cpc_writeb(falcbase + F_REG(FMR5, ch),
@@ -1601,7 +1601,7 @@ void turn_off_xld(pc300_t * card, int ch)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	if (conf->media == IF_IFACE_T1) {
 		cpc_writeb(falcbase + F_REG(FMR5, ch),
@@ -1624,7 +1624,7 @@ void falc_generate_loop_up_code(pc300_t * card, int ch)
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	if (conf->media == IF_IFACE_T1) {
 		cpc_writeb(falcbase + F_REG(FMR5, ch),
@@ -1657,7 +1657,7 @@ void falc_generate_loop_down_code(pc300_t * card, int ch)
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	if (conf->media == IF_IFACE_T1) {
 		cpc_writeb(falcbase + F_REG(FMR5, ch),
@@ -1687,7 +1687,7 @@ void falc_pattern_test(pc300_t * card, int ch, unsigned int activate)
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	if (activate) {
 		pfalc->prbs = 1;
@@ -1973,11 +1973,11 @@ static void sca_tx_intr(pc300dev_t *dev)
 	pc300ch_t *chan = (pc300ch_t *)dev->chan; 
 	pc300_t *card = (pc300_t *)chan->card; 
 	int ch = chan->channel; 
-	volatile pcsca_bd_t * ptdescr; 
+	volatile pcsca_bd_t __iomem * ptdescr; 
 	struct net_device_stats *stats = hdlc_stats(dev->dev);
 
     /* Clean up descriptors from previous transmission */
-	ptdescr = (pcsca_bd_t *)(card->hw.rambase +
+	ptdescr = (card->hw.rambase +
 						TX_BD_ADDR(ch,chan->tx_first_bd));
 	while ((cpc_readl(card->hw.scabase + DTX_REG(CDAL,ch)) != 
 							TX_BD_ADDR(ch,chan->tx_first_bd)) && 
@@ -1988,8 +1988,7 @@ static void sca_tx_intr(pc300dev_t *dev)
 		cpc_writew(&ptdescr->len, 0);
 		chan->nfree_tx_bd++;
 		chan->tx_first_bd = (chan->tx_first_bd + 1) & (N_DMA_TX_BUF - 1);
-		ptdescr = (pcsca_bd_t *)(card->hw.rambase +
-						TX_BD_ADDR(ch,chan->tx_first_bd));
+		ptdescr = (card->hw.rambase + TX_BD_ADDR(ch,chan->tx_first_bd));
     }
 
 #ifdef CONFIG_PC300_MLPPP
@@ -2006,7 +2005,7 @@ static void sca_tx_intr(pc300dev_t *dev)
 
 static void sca_intr(pc300_t * card)
 {
-	uclong scabase = card->hw.scabase;
+	void __iomem *scabase = card->hw.scabase;
 	volatile uclong status;
 	int ch;
 	int intr_count = 0;
@@ -2187,7 +2186,7 @@ static void falc_t1_loop_detection(pc300_t * card, int ch, ucchar frs1)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	if (((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_XPRBS) == 0) &&
 	    !pfalc->loop_gen) {
@@ -2212,7 +2211,7 @@ static void falc_e1_loop_detection(pc300_t * card, int ch, ucchar rsp)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 
 	if (((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_XPRBS) == 0) &&
 	    !pfalc->loop_gen) {
@@ -2237,7 +2236,7 @@ static void falc_t1_intr(pc300_t * card, int ch)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 	ucchar isr0, isr3, gis;
 	ucchar dummy;
 
@@ -2284,7 +2283,7 @@ static void falc_e1_intr(pc300_t * card, int ch)
 {
 	pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
 	falc_t *pfalc = (falc_t *) & chan->falc;
-	uclong falcbase = card->hw.falcbase;
+	void __iomem *falcbase = card->hw.falcbase;
 	ucchar isr1, isr2, isr3, gis, rsp;
 	ucchar dummy;
 
@@ -2408,7 +2407,7 @@ static irqreturn_t cpc_intr(int irq, void *dev_id, struct pt_regs *regs)
 void cpc_sca_status(pc300_t * card, int ch)
 {
 	ucchar ilar;
-	uclong scabase = card->hw.scabase;
+	void __iomem *scabase = card->hw.scabase;
 	uclong flags;
 
 	tx_dma_buf_check(card, ch);
@@ -2544,7 +2543,7 @@ int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	int ch = chan->channel;
 	void __user *arg = ifr->ifr_data;
 	struct if_settings *settings = &ifr->ifr_settings;
-	uclong scabase = card->hw.scabase;
+	void __iomem *scabase = card->hw.scabase;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
@@ -2863,8 +2862,8 @@ int ch_config(pc300dev_t * d)
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
 	pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
 	pc300_t *card = (pc300_t *) chan->card;
-	uclong scabase = card->hw.scabase;
-	uclong plxbase = card->hw.plxbase;
+	void __iomem *scabase = card->hw.scabase;
+	void __iomem *plxbase = card->hw.plxbase;
 	int ch = chan->channel;
 	uclong clkrate = chan->conf.phys_settings.clock_rate;
 	uclong clktype = chan->conf.phys_settings.clock_type;
@@ -3010,7 +3009,7 @@ int rx_config(pc300dev_t * d)
 {
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
 	pc300_t *card = (pc300_t *) chan->card;
-	uclong scabase = card->hw.scabase;
+	void __iomem *scabase = card->hw.scabase;
 	int ch = chan->channel;
 
 	cpc_writeb(scabase + DSR_RX(ch), 0);
@@ -3041,7 +3040,7 @@ int tx_config(pc300dev_t * d)
 {
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
 	pc300_t *card = (pc300_t *) chan->card;
-	uclong scabase = card->hw.scabase;
+	void __iomem *scabase = card->hw.scabase;
 	int ch = chan->channel;
 
 	cpc_writeb(scabase + DSR_TX(ch), 0);
@@ -3105,7 +3104,7 @@ void cpc_opench(pc300dev_t * d)
 	pc300ch_t *chan = (pc300ch_t *) d->chan;
 	pc300_t *card = (pc300_t *) chan->card;
 	int ch = chan->channel;
-	uclong scabase = card->hw.scabase;
+	void __iomem *scabase = card->hw.scabase;
 
 	ch_config(d);
 
@@ -3211,7 +3210,7 @@ static uclong detect_ram(pc300_t * card)
 {
 	uclong i;
 	ucchar data;
-	uclong rambase = card->hw.rambase;
+	void __iomem *rambase = card->hw.rambase;
 
 	card->hw.ramsize = PC300_RAMSIZE;
 	/* Let's find out how much RAM is present on this board */
@@ -3227,7 +3226,7 @@ static uclong detect_ram(pc300_t * card)
 
 static void plx_init(pc300_t * card)
 {
-	struct RUNTIME_9050 *plx_ctl = (struct RUNTIME_9050 *) card->hw.plxbase;
+	struct RUNTIME_9050 __iomem *plx_ctl = card->hw.plxbase;
 
 	/* Reset PLX */
 	cpc_writel(&plx_ctl->init_ctrl,
@@ -3532,10 +3531,9 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if ((err = pci_enable_device(pdev)) != 0)
 		goto err_release_sca;
 
-	card->hw.plxbase = (uclong) ioremap(card->hw.plxphys, card->hw.plxsize);
-	card->hw.rambase = (uclong) ioremap(card->hw.ramphys,
-					    card->hw.alloc_ramsize);
-	card->hw.scabase = (uclong) ioremap(card->hw.scaphys, card->hw.scasize);
+	card->hw.plxbase = ioremap(card->hw.plxphys, card->hw.plxsize);
+	card->hw.rambase = ioremap(card->hw.ramphys, card->hw.alloc_ramsize);
+	card->hw.scabase = ioremap(card->hw.scaphys, card->hw.scasize);
 	switch (device_id) {
 		case PCI_DEVICE_ID_PC300_TE_1:
 		case PCI_DEVICE_ID_PC300_TE_2:
@@ -3543,14 +3541,13 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		case PCI_DEVICE_ID_PC300_TE_M_2:
 			request_mem_region(card->hw.falcphys, card->hw.falcsize,
 					   "FALC Registers");
-			card->hw.falcbase = (uclong) ioremap(card->hw.falcphys,
-							     card->hw.falcsize);
+			card->hw.falcbase = ioremap(card->hw.falcphys, card->hw.falcsize);
 			break;
 
 		case PCI_DEVICE_ID_PC300_RX_1:
 		case PCI_DEVICE_ID_PC300_RX_2:
 		default:
-			card->hw.falcbase = 0;
+			card->hw.falcbase = NULL;
 			break;
 	}
 
@@ -3616,11 +3613,11 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	return 0;
 
 err_io_unmap:
-	iounmap((void *) card->hw.plxbase);
-	iounmap((void *) card->hw.scabase);
-	iounmap((void *) card->hw.rambase);
+	iounmap(card->hw.plxbase);
+	iounmap(card->hw.scabase);
+	iounmap(card->hw.rambase);
 	if (card->hw.type == PC300_TE) {
-		iounmap((void *) card->hw.falcbase);
+		iounmap(card->hw.falcbase);
 		release_mem_region(card->hw.falcphys, card->hw.falcsize);
 	}
 err_release_sca:
@@ -3649,15 +3646,15 @@ static void __devexit cpc_remove_one(struct pci_dev *pdev)
 		for (i = 0; i < card->hw.nchan; i++) {
 			unregister_hdlc_device(card->chan[i].d.dev);
 		}
-		iounmap((void *) card->hw.plxbase);
-		iounmap((void *) card->hw.scabase);
-		iounmap((void *) card->hw.rambase);
+		iounmap(card->hw.plxbase);
+		iounmap(card->hw.scabase);
+		iounmap(card->hw.rambase);
 		release_mem_region(card->hw.plxphys, card->hw.plxsize);
 		release_mem_region(card->hw.ramphys, card->hw.alloc_ramsize);
 		release_mem_region(card->hw.scaphys, card->hw.scasize);
 		release_region(card->hw.iophys, card->hw.iosize);
 		if (card->hw.type == PC300_TE) {
-			iounmap((void *) card->hw.falcbase);
+			iounmap(card->hw.falcbase);
 			release_mem_region(card->hw.falcphys, card->hw.falcsize);
 		}
 		for (i = 0; i < card->hw.nchan; i++)
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index 79d6894ac..9e50d5d02 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/net/wan/pc300_tty.c
@@ -192,13 +192,14 @@ static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char signal)
  */
 void cpc_tty_init(pc300dev_t *pc300dev)
 {
-	int port, aux;
+	unsigned long port;
+	int aux;
 	st_cpc_tty_area * cpc_tty;
 
 	/* hdlcX - X=interface number */
 	port = pc300dev->dev->name[4] - '0';
 	if (port >= CPC_TTY_NPORTS) {
-		printk("%s-tty: invalid interface selected (0-%i): %i", 
+		printk("%s-tty: invalid interface selected (0-%i): %li",
 			pc300dev->dev->name,
 			CPC_TTY_NPORTS-1,port);
 		return;
@@ -634,14 +635,8 @@ static void cpc_tty_flush_buffer(struct tty_struct *tty)
 	}
 
 	CPC_TTY_DBG("%s: call wake_up_interruptible\n",cpc_tty->name);
-	
-	wake_up_interruptible(&tty->write_wait); 
-
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup){
-		CPC_TTY_DBG("%s: call line disc. wake up\n",cpc_tty->name);
-		tty->ldisc.write_wakeup(tty); 
-	} 
 
+	tty_wakeup(tty);	
 	return; 
 } 
 
@@ -688,25 +683,32 @@ static void cpc_tty_hangup(struct tty_struct *tty)
  */
 static void cpc_tty_rx_work(void * data)
 {
-	int port, i, j;
+	unsigned long port;
+	int i, j;
 	st_cpc_tty_area *cpc_tty; 
 	volatile st_cpc_rx_buf * buf;
 	char flags=0,flg_rx=1; 
+	struct tty_ldisc *ld;
 
 	if (cpc_tty_cnt == 0) return;
 
+	
 	for (i=0; (i < 4) && flg_rx ; i++) {
 		flg_rx = 0;
-		port = (int) data;
+		port = (unsigned long)data;
 		for (j=0; j < CPC_TTY_NPORTS; j++) {
 			cpc_tty = &cpc_tty_area[port];
 		
 			if ((buf=cpc_tty->buf_rx.first) != 0) {
-															
-				if (cpc_tty->tty && (cpc_tty->tty->ldisc.receive_buf)) { 
-					CPC_TTY_DBG("%s: call line disc. receive_buf\n",cpc_tty->name);
-					cpc_tty->tty->ldisc.receive_buf(cpc_tty->tty, (char *)(buf->data), 
-					&flags, buf->size);
+				if(cpc_tty->tty) {
+					ld = tty_ldisc_ref(cpc_tty->tty);
+					if(ld) {
+						if (ld->receive_buf) {
+							CPC_TTY_DBG("%s: call line disc. receive_buf\n",cpc_tty->name);
+							ld->receive_buf(cpc_tty->tty, (char *)(buf->data), &flags, buf->size);
+						}
+						tty_ldisc_deref(ld);
+					}
 				}	
 				cpc_tty->buf_rx.first = cpc_tty->buf_rx.first->next;
 				kfree((unsigned char *)buf);
@@ -760,7 +762,7 @@ void cpc_tty_receive(pc300dev_t *pc300dev)
 	int rx_len, rx_aux; 
 	volatile unsigned char status; 
 	unsigned short first_bd = pc300chan->rx_first_bd;
-	st_cpc_rx_buf	*new;
+	st_cpc_rx_buf	*new=NULL;
 	unsigned char dsr_rx;
 
 	if (pc300dev->cpc_tty == NULL) { 
@@ -789,6 +791,10 @@ void cpc_tty_receive(pc300dev_t *pc300dev)
 				cpc_writel(card->hw.scabase + DRX_REG(EDAL, ch), 
 						RX_BD_ADDR(ch, pc300chan->rx_last_bd)); 
 			}
+			if (new) {
+				kfree(new);
+				new = NULL;
+			}
 			return; 
 		}
 		
@@ -834,7 +840,8 @@ void cpc_tty_receive(pc300dev_t *pc300dev)
 						cpc_tty->name);
 				cpc_tty_rx_disc_frame(pc300chan);
 				rx_len = 0;
-				kfree((unsigned char *)new);
+				kfree(new);
+				new = NULL;
 				break; /* read next frame - while(1) */
 			}
 
@@ -843,7 +850,8 @@ void cpc_tty_receive(pc300dev_t *pc300dev)
 				cpc_tty_rx_disc_frame(pc300chan);
 				stats->rx_dropped++; 
 				rx_len = 0; 
-				kfree((unsigned char *)new);
+				kfree(new);
+				new = NULL;
 				break; /* read next frame - while(1) */
 			}
 
@@ -910,13 +918,7 @@ static void cpc_tty_tx_work(void *data)
 		CPC_TTY_DBG("%s: the interface is not opened\n",cpc_tty->name);
 		return; 
 	}
-
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup){
-		CPC_TTY_DBG("%s:call line disc. wakeup\n",cpc_tty->name);
-		tty->ldisc.write_wakeup (tty); 
-	}
-
-	wake_up_interruptible(&tty->write_wait); 
+	tty_wakeup(tty);
 }
 
 /*
diff --git a/drivers/net/wan/sdla_chdlc.c b/drivers/net/wan/sdla_chdlc.c
index b00fb7837..e66c250ea 100644
--- a/drivers/net/wan/sdla_chdlc.c
+++ b/drivers/net/wan/sdla_chdlc.c
@@ -3628,11 +3628,7 @@ static void tty_poll_work (void* data)
 	if ((tty=card->tty)==NULL)
 		return;
 	
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup){
-		(tty->ldisc.write_wakeup)(tty);
-	}
-	wake_up_interruptible(&tty->write_wait);
+	tty_wakeup(tty);
 #if defined(SERIAL_HAVE_POLL_WAIT)
 	wake_up_interruptible(&tty->poll_wait);
 #endif	
@@ -3857,6 +3853,7 @@ static void wanpipe_tty_receive(sdla_t *card, unsigned addr, unsigned int len)
 	char fp=0;
 	struct tty_struct *tty;
 	int i;
+	struct tty_ldisc *ld;
 	
 	if (!card->tty_open){
 		dbg_printk(KERN_INFO "%s: TTY not open during receive\n",
@@ -3944,8 +3941,11 @@ static void wanpipe_tty_receive(sdla_t *card, unsigned addr, unsigned int len)
 			len -= offset;
 		}
 		sdla_peek(&card->hw, addr, card->tty_rx+offset, len);
-		if (tty->ldisc.receive_buf){
-			tty->ldisc.receive_buf(tty,card->tty_rx,&fp,olen);
+		ld = tty_ldisc_ref(tty);
+		if (ld) {
+			if (ld->receive_buf)
+				ld->receive_buf(tty,card->tty_rx,&fp,olen);
+			tty_ldisc_deref(ld);
 		}else{
 			if (net_ratelimit()){
 				printk(KERN_INFO 
@@ -4252,14 +4252,10 @@ static void wanpipe_tty_flush_buffer(struct tty_struct *tty)
 	if (!tty)
 		return;
 	
-	wake_up_interruptible(&tty->write_wait);
 #if defined(SERIAL_HAVE_POLL_WAIT)
 	wake_up_interruptible(&tty->poll_wait);
 #endif
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
-
+	tty_wakeup(tty);
 	return;
 }
 
diff --git a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c
index 52f40883d..2efccb055 100644
--- a/drivers/net/wan/sdla_fr.c
+++ b/drivers/net/wan/sdla_fr.c
@@ -3678,7 +3678,7 @@ static int process_udp_mgmt_pkt(sdla_t* card)
                                 break;
                         }
 
-			(void *)ptr_trc_el = card->u.f.curr_trc_el;
+			ptr_trc_el = (void *)card->u.f.curr_trc_el;
 
                         buffer_length = 0;
 			fr_udp_pkt->data[0x00] = 0x00;
@@ -3729,7 +3729,7 @@ static int process_udp_mgmt_pkt(sdla_t* card)
                                
 				ptr_trc_el ++;
 				if((void *)ptr_trc_el > card->u.f.trc_el_last)
-					(void*)ptr_trc_el = card->u.f.trc_el_base;
+					ptr_trc_el = (void*)card->u.f.trc_el_base;
 
 				buffer_length += sizeof(fpipemon_trc_hdr_t);
                                	if(fpipemon_trc->fpipemon_trc_hdr.data_passed) {
diff --git a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c
index 501e9a752..c8bc6da57 100644
--- a/drivers/net/wan/sdladrv.c
+++ b/drivers/net/wan/sdladrv.c
@@ -937,7 +937,7 @@ int sdla_peek (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len)
                         peek_by_4 ((unsigned long)hw->dpmbase + curpos, buf,
 				curlen);
                         addr       += curlen;
-                        (char*)buf += curlen;
+                        buf         = (char*)buf + curlen;
                         len        -= curlen;
                 }
 
@@ -1019,7 +1019,7 @@ int sdla_poke (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len)
                         poke_by_4 ((unsigned long)hw->dpmbase + curpos, buf,
 				curlen);
 	                addr       += curlen;
-                        (char*)buf += curlen;
+                        buf         = (char*)buf + curlen;
                         len        -= curlen;
                 }
 
@@ -2001,7 +2001,7 @@ static int detect_s514 (sdlahw_t* hw)
 	(void *)hw->dpmbase = ioremap((unsigned long)S514_mem_base_addr,
 		(unsigned long)MAX_SIZEOF_S514_MEMORY);
     	/* map the physical control register memory to virtual memory */
-	(void *)hw->vector = ioremap(
+	hw->vector = (unsigned long)ioremap(
 		(unsigned long)(S514_mem_base_addr + S514_CTRL_REG_BYTE),
 		(unsigned long)16);
      
diff --git a/drivers/net/wan/sdlamain.c b/drivers/net/wan/sdlamain.c
index be10f8c41..74e151ace 100644
--- a/drivers/net/wan/sdlamain.c
+++ b/drivers/net/wan/sdlamain.c
@@ -976,7 +976,7 @@ static int ioctl_dump (sdla_t* card, sdla_dump_t* u_dump)
 
                         dump.length     -= len;
                         dump.offset     += len;
-                        (char*)dump.ptr += len;
+                        dump.ptr         = (char*)dump.ptr + len;
                 }
 		
                 sdla_mapmem(&card->hw, oldvec);/* restore DPM window position */
diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c
index f7442d52d..2329c23af 100644
--- a/drivers/net/wan/syncppp.c
+++ b/drivers/net/wan/syncppp.c
@@ -50,6 +50,7 @@
 #include <linux/random.h>
 #include <linux/pkt_sched.h>
 #include <linux/spinlock.h>
+#include <linux/rcupdate.h>
 
 #include <net/syncppp.h>
 
@@ -767,9 +768,9 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb)
 		struct in_ifaddr *ifa;
 		u32 addr = 0, mask = ~0; /* FIXME: is the mask correct? */
 #ifdef CONFIG_INET
-		if ((in_dev=in_dev_get(dev)) != NULL)
+		rcu_read_lock();
+		if ((in_dev = __in_dev_get(dev)) != NULL)
 		{
-			read_lock(&in_dev->lock);
 			for (ifa=in_dev->ifa_list; ifa != NULL;
 				ifa=ifa->ifa_next) {
 				if (strcmp(dev->name, ifa->ifa_label) == 0) 
@@ -779,9 +780,8 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb)
 					break;
 				}
 			}
-			read_unlock(&in_dev->lock);
-			in_dev_put(in_dev);
 		}
+		rcu_read_unlock();
 #endif		
 		/* I hope both addr and mask are in the net order */
 		sppp_cisco_send (sp, CISCO_ADDR_REPLY, addr, mask);
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 8d38c1803..041b15b0f 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -25,6 +25,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/proc_fs.h>
+#include <linux/smp_lock.h>
 
 #include <linux/sched.h>
 #include <linux/ptrace.h>
@@ -1815,7 +1816,8 @@ static int writeConfigRid(struct airo_info*ai, int lock) {
 	if (!test_bit (FLAG_COMMIT, &ai->flags))
 		return SUCCESS;
 
-	clear_bit (FLAG_COMMIT | FLAG_RESET, &ai->flags);
+	clear_bit (FLAG_COMMIT, &ai->flags);
+	clear_bit (FLAG_RESET, &ai->flags);
 	checkThrottle(ai);
 	cfgr = ai->config;
 
@@ -1979,9 +1981,6 @@ static int mpi_send_packet (struct net_device *dev)
 	ai->txfids[0].tx_desc.eoc = 1;
 	ai->txfids[0].tx_desc.len =len+sizeof(WifiHdr);
 
-	memcpy((char *)ai->txfids[0].card_ram_off,
-		(char *)&ai->txfids[0].tx_desc, sizeof(TxFid));
-
 /*
  * Magic, the cards firmware needs a length count (2 bytes) in the host buffer
  * right after  TXFID_HDR.The TXFID_HDR contains the status short so payloadlen
@@ -2011,6 +2010,7 @@ static int mpi_send_packet (struct net_device *dev)
 			return ERROR;
 
 		*payloadLen = cpu_to_le16(len-sizeof(etherHead)+sizeof(pMic));
+		ai->txfids[0].tx_desc.len += sizeof(pMic);
 		/* copy data into airo dma buffer */
 		memcpy (sendbuf, buffer, sizeof(etherHead));
 		buffer += sizeof(etherHead);
@@ -2029,6 +2029,9 @@ static int mpi_send_packet (struct net_device *dev)
 		memcpy(sendbuf, buffer, len);
 	}
 
+	memcpy((char *)ai->txfids[0].card_ram_off,
+		(char *)&ai->txfids[0].tx_desc, sizeof(TxFid));
+
 	OUT4500(ai, EVACK, 8);
 
 	dev_kfree_skb_any(skb);
@@ -2183,6 +2186,12 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
 	struct airo_info *priv = dev->priv;
 	u32 *fids = priv->fids;
 
+	if (test_bit(FLAG_MPI, &priv->flags)) {
+		/* Not implemented yet for MPI350 */
+		netif_stop_queue(dev);
+		return -ENETDOWN;
+	}
+
 	if ( skb == NULL ) {
 		printk( KERN_ERR "airo:  skb == NULL!!!\n" );
 		return 0;
@@ -2248,12 +2257,14 @@ struct net_device_stats *airo_get_stats(struct net_device *dev)
 {
 	struct airo_info *local =  dev->priv;
 
-	/* Get stats out of the card if available */
-	if (down_trylock(&local->sem) != 0) {
-		set_bit(JOB_STATS, &local->flags);
-		wake_up_interruptible(&local->thr_wait);
-	} else
-		airo_read_stats(local);
+	if (!test_bit(JOB_STATS, &local->flags)) {
+		/* Get stats out of the card if available */
+		if (down_trylock(&local->sem) != 0) {
+			set_bit(JOB_STATS, &local->flags);
+			wake_up_interruptible(&local->thr_wait);
+		} else
+			airo_read_stats(local);
+	}
 
 	return &local->stats;
 }
@@ -2339,6 +2350,9 @@ static void del_airo_dev( struct net_device *dev );
 void stop_airo_card( struct net_device *dev, int freeres )
 {
 	struct airo_info *ai = dev->priv;
+
+	set_bit(FLAG_RADIO_DOWN, &ai->flags);
+	disable_MAC(ai, 1);
 	disable_interrupts(ai);
 	free_irq( dev->irq, dev );
 	takedown_proc_entry( dev, ai );
@@ -3405,13 +3419,8 @@ static void disable_MAC( struct airo_info *ai, int lock ) {
 }
 
 static void enable_interrupts( struct airo_info *ai ) {
-	/* Reset the status register */
-	u16 status = IN4500( ai, EVSTAT );
-	OUT4500( ai, EVACK, status );
 	/* Enable the interrupts */
 	OUT4500( ai, EVINTEN, STATUS_INTS );
-	/* Note there is a race condition between the last two lines that
-	   I don't know how to get rid of right now... */
 }
 
 static void disable_interrupts( struct airo_info *ai ) {
@@ -3459,7 +3468,7 @@ static void mpi_receive_802_3(struct airo_info *ai)
 		memcpy(buffer + ETH_ALEN * 2,
 			ai->rxfids[0].virtual_host_addr + ETH_ALEN * 2 + off,
 			len - ETH_ALEN * 2 - off);
-		if (decapsulate (ai, &micbuf, (etherHead*)buffer, len - off)) {
+		if (decapsulate (ai, &micbuf, (etherHead*)buffer, len - off - ETH_ALEN * 2)) {
 badmic:
 			dev_kfree_skb_irq (skb);
 			goto badrx;
@@ -3669,18 +3678,6 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
 		status = readCapabilityRid(ai, &cap_rid, lock);
 		if ( status != SUCCESS ) return ERROR;
 
-		/*
-		 * This driver supports MPI350 firmwares up to, and
-		 * including 5.30.17
-		 */
-		if (test_bit(FLAG_MPI, &ai->flags) &&
-		    strncmp (cap_rid.prodVer, "5.00.", 5) &&
-		    strncmp (cap_rid.prodVer, "5b00.", 5) &&
-		    strncmp (cap_rid.prodVer, "5.02.", 5) &&
-		    strncmp (cap_rid.prodVer, "5.20.", 5) &&
-		    strncmp (cap_rid.prodVer, "5.30.", 5))
-			printk(KERN_ERR "airo: Firmware version %s is not supported. Use it at your own risk!\n", cap_rid.prodVer);
-
 		status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid),lock);
 		if ( status == SUCCESS ) {
 			if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL)
@@ -3715,9 +3712,9 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
 
 		/* Check to see if there are any insmod configured
 		   rates to add */
-		if ( rates ) {
+		if ( rates[0] ) {
 			int i = 0;
-			if ( rates[0] ) memset(ai->config.rates,0,sizeof(ai->config.rates));
+			memset(ai->config.rates,0,sizeof(ai->config.rates));
 			for( i = 0; i < 8 && rates[i]; i++ ) {
 				ai->config.rates[i] = rates[i];
 			}
@@ -3784,7 +3781,6 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
 static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {
         // Im really paranoid about letting it run forever!
 	int max_tries = 600000;
-	u16 cmd;
 
 	if (IN4500(ai, EVSTAT) & EV_CMD)
 		OUT4500(ai, EVACK, EV_CMD);
@@ -3793,26 +3789,23 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {
 	OUT4500(ai, PARAM1, pCmd->parm1);
 	OUT4500(ai, PARAM2, pCmd->parm2);
 	OUT4500(ai, COMMAND, pCmd->cmd);
-	while ( max_tries-- && (IN4500(ai, EVSTAT) & EV_CMD) == 0 &&
-		(cmd = IN4500(ai, COMMAND)) != 0 )
-			if (cmd == pCmd->cmd)
-				// PC4500 didn't notice command, try again
-				OUT4500(ai, COMMAND, pCmd->cmd);
-	if ( max_tries == -1 ) {
-		printk( KERN_ERR
-			"airo: Max tries exceeded when issueing command\n" );
-                return ERROR;
-	}
 
 	while (max_tries-- && (IN4500(ai, EVSTAT) & EV_CMD) == 0) {
+		if ((IN4500(ai, COMMAND)) == pCmd->cmd)
+			// PC4500 didn't notice command, try again
+			OUT4500(ai, COMMAND, pCmd->cmd);
 		if (!in_atomic() && (max_tries & 255) == 0)
 			schedule();
 	}
+
 	if ( max_tries == -1 ) {
 		printk( KERN_ERR
-			"airo: Max tries exceeded waiting for command\n" );
-                return ERROR;
+			"airo: Max tries exceeded when issueing command\n" );
+		if (IN4500(ai, COMMAND) & COMMAND_BUSY)
+			OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY);
+		return ERROR;
 	}
+
 	// command completed
 	pRsp->status = IN4500(ai, STATUS);
 	pRsp->rsp0 = IN4500(ai, RESP0);
@@ -4508,8 +4501,6 @@ static ssize_t proc_read( struct file *file,
 		len = priv->readlen - pos;
 	if (copy_to_user(buffer, priv->rbuffer + pos, len))
 		return -EFAULT;
-	if (pos + len > priv->writelen)
-		priv->writelen = pos + len;
 	*offset = pos + len;
 	return len;
 }
@@ -5520,7 +5511,6 @@ static int airo_pci_resume(struct pci_dev *pdev)
 		mpi_init_descriptors(ai);
 		setup_card(ai, dev->dev_addr, 0);
 		clear_bit(FLAG_RADIO_OFF, &ai->flags);
-		clear_bit(FLAG_RADIO_DOWN, &ai->flags);
 		clear_bit(FLAG_PENDING_XMIT, &ai->flags);
 	} else {
 		OUT4500(ai, EVACK, EV_AWAKEN);
@@ -5605,6 +5595,30 @@ static void __exit airo_cleanup_module( void )
  * would not work at all... - Jean II
  */
 
+static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid)
+{
+	int quality = 0;
+
+	if ((status_rid->mode & 0x3f) == 0x3f && (cap_rid->hardCap & 8)) {
+		if (memcmp(cap_rid->prodName, "350", 3))
+			if (status_rid->signalQuality > 0x20)
+				quality = 0;
+			else
+				quality = 0x20 - status_rid->signalQuality;
+		else
+			if (status_rid->signalQuality > 0xb0)
+				quality = 0;
+			else if (status_rid->signalQuality < 0x10)
+				quality = 0xa0;
+			else
+				quality = 0xb0 - status_rid->signalQuality;
+	}
+	return quality;
+}
+
+#define airo_get_max_quality(cap_rid) (memcmp((cap_rid)->prodName, "350", 3) ? 0x20 : 0xa0)
+#define airo_get_avg_quality(cap_rid) (memcmp((cap_rid)->prodName, "350", 3) ? 0x10 : 0x50);
+
 /*------------------------------------------------------------------*/
 /*
  * Wireless Handler : get protocol name
@@ -6292,7 +6306,8 @@ static int airo_set_txpow(struct net_device *dev,
 	readCapabilityRid(local, &cap_rid, 1);
 
 	if (vwrq->disabled) {
-		set_bit (FLAG_RADIO_OFF | FLAG_COMMIT, &local->flags);
+		set_bit (FLAG_RADIO_OFF, &local->flags);
+		set_bit (FLAG_COMMIT, &local->flags);
 		return -EINPROGRESS;		/* Call commit handler */
 	}
 	if (vwrq->flags != IW_TXPOW_MWATT) {
@@ -6431,7 +6446,7 @@ static int airo_get_range(struct net_device *dev,
 	range->num_frequency = k;
 
 	/* Hum... Should put the right values there */
-	range->max_qual.qual = 10;
+	range->max_qual.qual = airo_get_max_quality(&cap_rid);
 	range->max_qual.level = 0x100 - 120;	/* -120 dBm */
 	range->max_qual.noise = 0;
 	range->sensitivity = 65535;
@@ -6498,7 +6513,7 @@ static int airo_get_range(struct net_device *dev,
 	/* Experimental measurements - boundary 11/5.5 Mb/s */
 	/* Note : with or without the (local->rssi), results
 	 * are somewhat different. - Jean II */
-	range->avg_qual.qual = 6;
+	range->avg_qual.qual = airo_get_avg_quality(&cap_rid);
 	if (local->rssi)
 		range->avg_qual.level = 186;	/* -70 dBm */
 	else
@@ -7112,6 +7127,7 @@ static void airo_read_wireless_stats(struct airo_info *local)
 {
 	StatusRid status_rid;
 	StatsRid stats_rid;
+	CapabilityRid cap_rid;
 	u32 *vals = stats_rid.vals;
 
 	/* Get stats out of the card */
@@ -7120,6 +7136,7 @@ static void airo_read_wireless_stats(struct airo_info *local)
 		up(&local->sem);
 		return;
 	}
+	readCapabilityRid(local, &cap_rid, 0);
 	readStatusRid(local, &status_rid, 0);
 	readStatsRid(local, &stats_rid, RID_STATS, 0);
 	up(&local->sem);
@@ -7128,7 +7145,7 @@ static void airo_read_wireless_stats(struct airo_info *local)
 	local->wstats.status = status_rid.mode;
 
 	/* Signal quality and co. But where is the noise level ??? */
-	local->wstats.qual.qual = status_rid.signalQuality;
+	local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid);
 	if (local->rssi)
 		local->wstats.qual.level = 0x100 - local->rssi[status_rid.sigQuality].rssidBm;
 	else
@@ -7155,12 +7172,14 @@ struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
 {
 	struct airo_info *local =  dev->priv;
 
-	/* Get stats out of the card if available */
-	if (down_trylock(&local->sem) != 0) {
-		set_bit(JOB_WSTATS, &local->flags);
-		wake_up_interruptible(&local->thr_wait);
-	} else
-		airo_read_wireless_stats(local);
+	if (!test_bit(JOB_WSTATS, &local->flags)) {
+		/* Get stats out of the card if available */
+		if (down_trylock(&local->sem) != 0) {
+			set_bit(JOB_WSTATS, &local->flags);
+			wake_up_interruptible(&local->thr_wait);
+		} else
+			airo_read_wireless_stats(local);
+	}
 
 	return &local->wstats;
 }
@@ -7187,9 +7206,11 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
 	{
 	case AIROGCAP:      ridcode = RID_CAPABILITIES; break;
 	case AIROGCFG:      ridcode = RID_CONFIG;
-		disable_MAC (ai, 1);
-		writeConfigRid (ai, 1);
-		enable_MAC (ai, &rsp, 1);
+		if (test_bit(FLAG_COMMIT, &ai->flags)) {
+			disable_MAC (ai, 1);
+			writeConfigRid (ai, 1);
+			enable_MAC (ai, &rsp, 1);
+		}
 		break;
 	case AIROGSLIST:    ridcode = RID_SSID;         break;
 	case AIROGVLIST:    ridcode = RID_APLIST;       break;
@@ -7269,6 +7290,7 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
 	case AIROPCAP:      ridcode = RID_CAPABILITIES; break;
 	case AIROPAPLIST:   ridcode = RID_APLIST;       break;
 	case AIROPCFG: ai->config.len = 0;
+			    clear_bit(FLAG_COMMIT, &ai->flags);
 			    ridcode = RID_CONFIG;       break;
 	case AIROPWEPKEYNV: ridcode = RID_WEP_PERM;     break;
 	case AIROPLEAPUSR:  ridcode = RID_LEAPUSERNAME; break;
diff --git a/drivers/net/wireless/airport.c b/drivers/net/wireless/airport.c
index 20bd0dfef..51c54132c 100644
--- a/drivers/net/wireless/airport.c
+++ b/drivers/net/wireless/airport.c
@@ -1,4 +1,4 @@
-/* airport.c 0.13e
+/* airport.c
  *
  * A driver for "Hermes" chipset based Apple Airport wireless
  * card.
@@ -11,6 +11,9 @@
  *  0.06 : fix possible hang on powerup, add sleep support
  */
 
+#define DRIVER_NAME "airport"
+#define PFX DRIVER_NAME ": "
+
 #include <linux/config.h>
 
 #include <linux/module.h>
@@ -25,6 +28,7 @@
 #include <linux/if_arp.h>
 #include <linux/etherdevice.h>
 #include <linux/wireless.h>
+#include <linux/delay.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
@@ -50,7 +54,7 @@ static int
 airport_suspend(struct macio_dev *mdev, u32 state)
 {
 	struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
-	struct orinoco_private *priv = dev->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
 	unsigned long flags;
 	int err;
 
@@ -84,15 +88,14 @@ static int
 airport_resume(struct macio_dev *mdev)
 {
 	struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
-	struct orinoco_private *priv = dev->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
 	unsigned long flags;
 	int err;
 
 	printk(KERN_DEBUG "%s: Airport waking up\n", dev->name);
 
 	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ/5);
+	msleep(200);
 
 	enable_irq(dev->irq);
 
@@ -126,7 +129,7 @@ static int
 airport_detach(struct macio_dev *mdev)
 {
 	struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
-	struct orinoco_private *priv = dev->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
 	struct airport *card = priv->card;
 
 	if (card->ndev_registered)
@@ -144,8 +147,7 @@ airport_detach(struct macio_dev *mdev)
 	macio_release_resource(mdev, 0);
 
 	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 0);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ);
+	ssleep(1);
 
 	macio_set_drvdata(mdev, NULL);
 	free_netdev(dev);
@@ -171,14 +173,12 @@ static int airport_hard_reset(struct orinoco_private *priv)
 	disable_irq(dev->irq);
 
 	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(card->mdev), 0, 0);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ);
+	ssleep(1);
 	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(card->mdev), 0, 1);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ);
+	ssleep(1);
 
 	enable_irq(dev->irq);
-	schedule_timeout(HZ);
+	ssleep(1);
 #endif
 
 	return 0;
@@ -194,24 +194,24 @@ airport_attach(struct macio_dev *mdev, const struct of_match *match)
 	hermes_t *hw;
 
 	if (macio_resource_count(mdev) < 1 || macio_irq_count(mdev) < 1) {
-		printk(KERN_ERR "airport: wrong interrupt/addresses in OF tree\n");
+		printk(KERN_ERR PFX "wrong interrupt/addresses in OF tree\n");
 		return -ENODEV;
 	}
 
 	/* Allocate space for private device-specific data */
 	dev = alloc_orinocodev(sizeof(*card), airport_hard_reset);
 	if (! dev) {
-		printk(KERN_ERR "airport: can't allocate device datas\n");
+		printk(KERN_ERR PFX "can't allocate device datas\n");
 		return -ENODEV;
 	}
-	priv = dev->priv;
+	priv = netdev_priv(dev);
 	card = priv->card;
 
 	hw = &priv->hw;
 	card->mdev = mdev;
 
 	if (macio_request_resource(mdev, 0, "airport")) {
-		printk(KERN_ERR "airport: can't request IO resource !\n");
+		printk(KERN_ERR PFX "can't request IO resource !\n");
 		free_netdev(dev);
 		return -EBUSY;
 	}
@@ -224,11 +224,11 @@ airport_attach(struct macio_dev *mdev, const struct of_match *match)
 	/* Setup interrupts & base address */
 	dev->irq = macio_irq(mdev, 0);
 	phys_addr = macio_resource_start(mdev, 0);  /* Physical address */
-	printk(KERN_DEBUG "Airport at physical address %lx\n", phys_addr);
+	printk(KERN_DEBUG PFX "Airport at physical address %lx\n", phys_addr);
 	dev->base_addr = phys_addr;
 	card->vaddr = ioremap(phys_addr, AIRPORT_IO_LEN);
 	if (!card->vaddr) {
-		printk("airport: ioremap() failed\n");
+		printk(PFX "ioremap() failed\n");
 		goto failed;
 	}
 
@@ -237,24 +237,23 @@ airport_attach(struct macio_dev *mdev, const struct of_match *match)
 		
 	/* Power up card */
 	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ);
+	ssleep(1);
 
 	/* Reset it before we get the interrupt */
 	hermes_init(hw);
 
 	if (request_irq(dev->irq, orinoco_interrupt, 0, "Airport", dev)) {
-		printk(KERN_ERR "airport: Couldn't get IRQ %d\n", dev->irq);
+		printk(KERN_ERR PFX "Couldn't get IRQ %d\n", dev->irq);
 		goto failed;
 	}
 	card->irq_requested = 1;
 
 	/* Tell the stack we exist */
 	if (register_netdev(dev) != 0) {
-		printk(KERN_ERR "airport: register_netdev() failed\n");
+		printk(KERN_ERR PFX "register_netdev() failed\n");
 		goto failed;
 	}
-	printk(KERN_DEBUG "airport: card registered for interface %s\n", dev->name);
+	printk(KERN_DEBUG PFX "card registered for interface %s\n", dev->name);
 	card->ndev_registered = 1;
 	return 0;
  failed:
@@ -263,7 +262,8 @@ airport_attach(struct macio_dev *mdev, const struct of_match *match)
 }				/* airport_attach */
 
 
-static char version[] __initdata = "airport.c 0.13e (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+	" (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
 MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
 MODULE_DESCRIPTION("Driver for the Apple Airport wireless card.");
 MODULE_LICENSE("Dual MPL/GPL");
@@ -280,7 +280,7 @@ static struct of_match airport_match[] =
 
 static struct macio_driver airport_driver = 
 {
-	.name 		= "airport",
+	.name 		= DRIVER_NAME,
 	.match_table	= airport_match,
 	.probe		= airport_attach,
 	.remove		= airport_detach,
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index cde68a443..fd8953c63 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -2430,12 +2430,13 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 			rc = -ENOMEM;
 			break;
 		}
-		
+
 		if (copy_from_user(new_firmware, com.data, com.len)) {
+			kfree(new_firmware);
 			rc = -EFAULT;
 			break;
 		}
-		
+
 		if (priv->firmware)
 			kfree(priv->firmware);
 		
diff --git a/drivers/net/wireless/hermes.c b/drivers/net/wireless/hermes.c
index d5ec3dedb..730090118 100644
--- a/drivers/net/wireless/hermes.c
+++ b/drivers/net/wireless/hermes.c
@@ -13,8 +13,8 @@
  * (wvlan_hcf.c) library, and the NetBSD wireless driver (in no
  * particular order).
  *
- * Copyright (C) 2000, David Gibson, Linuxcare Australia <hermes@gibson.dropbear.id.au>
- * Copyright (C) 2001, David Gibson, IBM <hermes@gibson.dropbear.id.au>
+ * Copyright (C) 2000, David Gibson, Linuxcare Australia.
+ * (C) Copyright David Gibson, IBM Corp. 2001-2003.
  * 
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -53,10 +53,9 @@
 #include "hermes.h"
 
 MODULE_DESCRIPTION("Low-level driver helper for Lucent Hermes chipset and Prism II HFA384x wireless MAC controller");
-MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
-#ifdef MODULE_LICENSE
+MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>"
+	" & David Gibson <hermes@gibson.dropbear.id.au>");
 MODULE_LICENSE("Dual MPL/GPL");
-#endif
 
 /* These are maximum timeouts. Most often, card wil react much faster */
 #define CMD_BUSY_TIMEOUT (100) /* In iterations of ~1us */
@@ -226,7 +225,7 @@ int hermes_init(hermes_t *hw)
  *
  * Callable from any context, but locking is your problem. */
 int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
-		      hermes_response_t *resp)
+		      struct hermes_response *resp)
 {
 	int err;
 	int k;
@@ -392,7 +391,6 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset)
 		return -EIO;
 	}
 
-
 	return 0;
 }
 
diff --git a/drivers/net/wireless/hermes.h b/drivers/net/wireless/hermes.h
index 126923ffd..429d57240 100644
--- a/drivers/net/wireless/hermes.h
+++ b/drivers/net/wireless/hermes.h
@@ -12,7 +12,8 @@
  * project, the Linux wvlan_cs driver, Lucent's HCF-Light
  * (wvlan_hcf.c) library, and the NetBSD wireless driver.
  *
- * Copyright (C) 2000, David Gibson, Linuxcare Australia <hermes@gibson.dropbear.id.au>
+ * Copyright (C) 2000, David Gibson, Linuxcare Australia.
+ * (C) Copyright David Gibson, IBM Corp. 2001-2003.
  *
  * Portions taken from hfa384x.h, Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
  *
@@ -124,29 +125,52 @@
 /*
  * Command codes
  */
-/*--- Controller Commands --------------------------*/
+/*--- Controller Commands ----------------------------*/
 #define		HERMES_CMD_INIT			(0x0000)
 #define		HERMES_CMD_ENABLE		(0x0001)
 #define		HERMES_CMD_DISABLE		(0x0002)
 #define		HERMES_CMD_DIAG			(0x0003)
 
-/*--- Buffer Mgmt Commands --------------------------*/
+/*--- Buffer Mgmt Commands ---------------------------*/
 #define		HERMES_CMD_ALLOC		(0x000A)
 #define		HERMES_CMD_TX			(0x000B)
-#define		HERMES_CMD_CLRPRST		(0x0012)
 
-/*--- Regulate Commands --------------------------*/
+/*--- Regulate Commands ------------------------------*/
 #define		HERMES_CMD_NOTIFY		(0x0010)
 #define		HERMES_CMD_INQUIRE		(0x0011)
 
-/*--- Configure Commands --------------------------*/
+/*--- Configure Commands -----------------------------*/
 #define		HERMES_CMD_ACCESS		(0x0021)
 #define		HERMES_CMD_DOWNLD		(0x0022)
 
+/*--- Serial I/O Commands ----------------------------*/
+#define		HERMES_CMD_READMIF		(0x0030)
+#define		HERMES_CMD_WRITEMIF		(0x0031)
+
 /*--- Debugging Commands -----------------------------*/
-#define 	HERMES_CMD_MONITOR		(0x0038)
-#define		HERMES_MONITOR_ENABLE		(0x000b)
-#define		HERMES_MONITOR_DISABLE		(0x000f)
+#define 	HERMES_CMD_TEST			(0x0038)
+
+
+/* Test command arguments */
+#define		HERMES_TEST_SET_CHANNEL		0x0800
+#define		HERMES_TEST_MONITOR		0x0b00
+#define		HERMES_TEST_STOP		0x0f00
+
+/* Authentication algorithms */
+#define		HERMES_AUTH_OPEN		1
+#define		HERMES_AUTH_SHARED_KEY		2
+
+/* WEP settings */
+#define		HERMES_WEP_PRIVACY_INVOKED	0x0001
+#define		HERMES_WEP_EXCL_UNENCRYPTED	0x0002
+#define		HERMES_WEP_HOST_ENCRYPT		0x0010
+#define		HERMES_WEP_HOST_DECRYPT		0x0080
+
+/* Symbol hostscan options */
+#define		HERMES_HOSTSCAN_SYMBOL_5SEC	0x0001
+#define		HERMES_HOSTSCAN_SYMBOL_ONCE	0x0002
+#define		HERMES_HOSTSCAN_SYMBOL_PASSIVE	0x0040
+#define		HERMES_HOSTSCAN_SYMBOL_BCAST	0x0080
 
 /*
  * Frame structures and constants
@@ -157,16 +181,6 @@
 #define HERMES_802_3_OFFSET		(14+32)
 #define HERMES_802_2_OFFSET		(14+32+14)
 
-struct hermes_rx_descriptor {
-	u16 status;
-	u32 time;
-	u8 silence;
-	u8 signal;
-	u8 rate;
-	u8 rxflow;
-	u32 reserved;
-} __attribute__ ((packed));
-
 #define HERMES_RXSTAT_ERR		(0x0003)
 #define	HERMES_RXSTAT_BADCRC		(0x0001)
 #define	HERMES_RXSTAT_UNDECRYPTABLE	(0x0002)
@@ -201,7 +215,11 @@ struct hermes_tx_descriptor {
 
 #define HERMES_INQ_TALLIES		(0xF100)
 #define HERMES_INQ_SCAN			(0xF101)
+#define HERMES_INQ_CHANNELINFO		(0xF102)
+#define HERMES_INQ_HOSTSCAN		(0xF103)
+#define HERMES_INQ_HOSTSCAN_SYMBOL	(0xF104)
 #define HERMES_INQ_LINKSTATUS		(0xF200)
+#define HERMES_INQ_SEC_STAT_AGERE	(0xF202)
 
 struct hermes_tallies_frame {
 	u16 TxUnicastFrames;
@@ -233,23 +251,58 @@ struct hermes_tallies_frame {
 /* Grabbed from wlan-ng - Thanks Mark... - Jean II
  * This is the result of a scan inquiry command */
 /* Structure describing info about an Access Point */
-struct hermes_scan_apinfo {
+struct prism2_scan_apinfo {
 	u16 channel;		/* Channel where the AP sits */
 	u16 noise;		/* Noise level */
 	u16 level;		/* Signal level */
 	u8 bssid[ETH_ALEN];	/* MAC address of the Access Point */
-	u16 beacon_interv;	/* Beacon interval ? */
-	u16 capabilities;	/* Capabilities ? */
+	u16 beacon_interv;	/* Beacon interval */
+	u16 capabilities;	/* Capabilities */
+	u16 essid_len;		/* ESSID length */
 	u8 essid[32];		/* ESSID of the network */
 	u8 rates[10];		/* Bit rate supported */
-	u16 proberesp_rate;	/* ???? */
+	u16 proberesp_rate;	/* Data rate of the response frame */
+	u16 atim;		/* ATIM window time, Kus (hostscan only) */
 } __attribute__ ((packed));
-/* Container */
-struct hermes_scan_frame {
-	u16 rsvd;                   /* ??? */
-	u16 scanreason;             /* ??? */
-	struct hermes_scan_apinfo aps[35];        /* Scan result */
+
+/* Same stuff for the Lucent/Agere card.
+ * Thanks to h1kari <h1kari AT dachb0den.com> - Jean II */
+struct agere_scan_apinfo {
+	u16 channel;		/* Channel where the AP sits */
+	u16 noise;		/* Noise level */
+	u16 level;		/* Signal level */
+	u8 bssid[ETH_ALEN];	/* MAC address of the Access Point */
+	u16 beacon_interv;	/* Beacon interval */
+	u16 capabilities;	/* Capabilities */
+	/* bits: 0-ess, 1-ibss, 4-privacy [wep] */
+	u16 essid_len;		/* ESSID length */
+	u8 essid[32];		/* ESSID of the network */
 } __attribute__ ((packed));
+
+/* Moustafa: Scan structure for Symbol cards */
+struct symbol_scan_apinfo {
+	u8 channel;		/* Channel where the AP sits */
+	u8 unknown1;		/* 8 in 2.9x and 3.9x f/w, 0 otherwise */
+	u16 noise;		/* Noise level */
+	u16 level;		/* Signal level */
+	u8 bssid[ETH_ALEN];	/* MAC address of the Access Point */
+	u16 beacon_interv;	/* Beacon interval */
+	u16 capabilities;	/* Capabilities */
+	/* bits: 0-ess, 1-ibss, 4-privacy [wep] */
+	u16 essid_len;		/* ESSID length */
+	u8 essid[32];		/* ESSID of the network */
+    	u16 rates[5];		/* Bit rate supported */
+	u16 basic_rates;	/* Basic rates bitmask */
+	u8 unknown2[6];		/* Always FF:FF:FF:FF:00:00 */
+	u8 unknown3[8];		/* Always 0, appeared in f/w 3.91-68 */
+} __attribute__ ((packed));
+
+union hermes_scan_info {
+	struct agere_scan_apinfo	a;
+	struct prism2_scan_apinfo	p;
+	struct symbol_scan_apinfo	s;
+};
+
 #define HERMES_LINKSTATUS_NOT_CONNECTED   (0x0000)  
 #define HERMES_LINKSTATUS_CONNECTED       (0x0001)
 #define HERMES_LINKSTATUS_DISCONNECTED    (0x0002)
@@ -262,6 +315,20 @@ struct hermes_linkstatus {
 	u16 linkstatus;         /* Link status */
 } __attribute__ ((packed));
 
+struct hermes_response {
+	u16 status, resp0, resp1, resp2;
+};
+
+/* "ID" structure - used for ESSID and station nickname */
+struct hermes_idstring {
+	u16 len;
+	u16 val[16];
+} __attribute__ ((packed));
+
+struct hermes_multicast {
+	u8 addr[HERMES_MAX_MULTICAST][ETH_ALEN];
+} __attribute__ ((packed));
+
 // #define HERMES_DEBUG_BUFFER 1
 #define HERMES_DEBUG_BUFSIZE 4096
 struct hermes_debug_entry {
@@ -294,10 +361,6 @@ typedef struct hermes {
 #endif
 } hermes_t;
 
-typedef struct hermes_response {
-	u16 status, resp0, resp1, resp2;
-} hermes_response_t;
-
 /* Register access convenience macros */
 #define hermes_read_reg(hw, off) ((hw)->io_space ? \
 	inw((hw)->iobase + ( (off) << (hw)->reg_spacing )) : \
@@ -312,9 +375,11 @@ typedef struct hermes_response {
 #define hermes_write_regn(hw, name, val) hermes_write_reg((hw), HERMES_##name, (val))
 
 /* Function prototypes */
-void hermes_struct_init(hermes_t *hw, ulong address, int io_space, int reg_spacing);
+void hermes_struct_init(hermes_t *hw, ulong address, int io_space,
+			int reg_spacing);
 int hermes_init(hermes_t *hw);
-int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, hermes_response_t *resp);
+int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
+		      struct hermes_response *resp);
 int hermes_allocate(hermes_t *hw, u16 size, u16 *fid);
 
 int hermes_bap_pread(hermes_t *hw, int bap, void *buf, unsigned len,
diff --git a/drivers/net/wireless/hermes_rid.h b/drivers/net/wireless/hermes_rid.h
index 761c5422e..4f46b4809 100644
--- a/drivers/net/wireless/hermes_rid.h
+++ b/drivers/net/wireless/hermes_rid.h
@@ -4,21 +4,21 @@
 /*
  * Configuration RIDs
  */
-#define HERMES_RID_CNFPORTTYPE			0xFC00	/* used */
-#define HERMES_RID_CNFOWNMACADDR		0xFC01	/* used */
-#define HERMES_RID_CNFDESIREDSSID		0xFC02	/* used */
-#define HERMES_RID_CNFOWNCHANNEL		0xFC03	/* used */
-#define HERMES_RID_CNFOWNSSID			0xFC04	/* used */
+#define HERMES_RID_CNFPORTTYPE			0xFC00
+#define HERMES_RID_CNFOWNMACADDR		0xFC01
+#define HERMES_RID_CNFDESIREDSSID		0xFC02
+#define HERMES_RID_CNFOWNCHANNEL		0xFC03
+#define HERMES_RID_CNFOWNSSID			0xFC04
 #define HERMES_RID_CNFOWNATIMWINDOW		0xFC05
-#define HERMES_RID_CNFSYSTEMSCALE		0xFC06	/* used */
+#define HERMES_RID_CNFSYSTEMSCALE		0xFC06
 #define HERMES_RID_CNFMAXDATALEN		0xFC07
 #define HERMES_RID_CNFWDSADDRESS		0xFC08
-#define HERMES_RID_CNFPMENABLED			0xFC09	/* used */
+#define HERMES_RID_CNFPMENABLED			0xFC09
 #define HERMES_RID_CNFPMEPS			0xFC0A
-#define HERMES_RID_CNFMULTICASTRECEIVE		0xFC0B	/* used */
-#define HERMES_RID_CNFMAXSLEEPDURATION		0xFC0C	/* used */
-#define HERMES_RID_CNFPMHOLDOVERDURATION	0xFC0D	/* used */
-#define HERMES_RID_CNFOWNNAME			0xFC0E	/* used */
+#define HERMES_RID_CNFMULTICASTRECEIVE		0xFC0B
+#define HERMES_RID_CNFMAXSLEEPDURATION		0xFC0C
+#define HERMES_RID_CNFPMHOLDOVERDURATION	0xFC0D
+#define HERMES_RID_CNFOWNNAME			0xFC0E
 #define HERMES_RID_CNFOWNDTIMPERIOD		0xFC10
 #define HERMES_RID_CNFWDSADDRESS1		0xFC11
 #define HERMES_RID_CNFWDSADDRESS2		0xFC12
@@ -27,17 +27,18 @@
 #define HERMES_RID_CNFWDSADDRESS5		0xFC15
 #define HERMES_RID_CNFWDSADDRESS6		0xFC16
 #define HERMES_RID_CNFMULTICASTPMBUFFERING	0xFC17
-#define HERMES_RID_CNFWEPENABLED_AGERE		0xFC20	/* used */
+#define HERMES_RID_CNFWEPENABLED_AGERE		0xFC20
+#define HERMES_RID_CNFAUTHENTICATION_AGERE	0xFC21
 #define HERMES_RID_CNFMANDATORYBSSID_SYMBOL	0xFC21
-#define HERMES_RID_CNFWEPDEFAULTKEYID		0xFC23	/* used */
-#define HERMES_RID_CNFDEFAULTKEY0		0xFC24	/* used */
-#define HERMES_RID_CNFDEFAULTKEY1		0xFC25	/* used */
-#define HERMES_RID_CNFMWOROBUST_AGERE		0xFC25	/* used */
-#define HERMES_RID_CNFDEFAULTKEY2		0xFC26	/* used */
-#define HERMES_RID_CNFDEFAULTKEY3		0xFC27	/* used */
-#define HERMES_RID_CNFWEPFLAGS_INTERSIL		0xFC28	/* used */
+#define HERMES_RID_CNFWEPDEFAULTKEYID		0xFC23
+#define HERMES_RID_CNFDEFAULTKEY0		0xFC24
+#define HERMES_RID_CNFDEFAULTKEY1		0xFC25
+#define HERMES_RID_CNFMWOROBUST_AGERE		0xFC25
+#define HERMES_RID_CNFDEFAULTKEY2		0xFC26
+#define HERMES_RID_CNFDEFAULTKEY3		0xFC27
+#define HERMES_RID_CNFWEPFLAGS_INTERSIL		0xFC28
 #define HERMES_RID_CNFWEPKEYMAPPINGTABLE	0xFC29
-#define HERMES_RID_CNFAUTHENTICATION		0xFC2A	/* used */
+#define HERMES_RID_CNFAUTHENTICATION		0xFC2A
 #define HERMES_RID_CNFMAXASSOCSTA		0xFC2B
 #define	HERMES_RID_CNFKEYLENGTH_SYMBOL		0xFC2B
 #define HERMES_RID_CNFTXCONTROL			0xFC2C
@@ -53,14 +54,14 @@
 #define HERMES_RID_CNFTIMCTRL			0xFC40
 #define HERMES_RID_CNFTHIRTY2TALLY		0xFC42
 #define HERMES_RID_CNFENHSECURITY		0xFC43
-#define HERMES_RID_CNFGROUPADDRESSES		0xFC80	/* used */
-#define HERMES_RID_CNFCREATEIBSS		0xFC81	/* used */
-#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD	0xFC82	/* used */
-#define HERMES_RID_CNFRTSTHRESHOLD		0xFC83	/* used */
-#define HERMES_RID_CNFTXRATECONTROL		0xFC84	/* used */
-#define HERMES_RID_CNFPROMISCUOUSMODE		0xFC85	/* used */
+#define HERMES_RID_CNFGROUPADDRESSES		0xFC80
+#define HERMES_RID_CNFCREATEIBSS		0xFC81
+#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD	0xFC82
+#define HERMES_RID_CNFRTSTHRESHOLD		0xFC83
+#define HERMES_RID_CNFTXRATECONTROL		0xFC84
+#define HERMES_RID_CNFPROMISCUOUSMODE		0xFC85
 #define HERMES_RID_CNFBASICRATES_SYMBOL		0xFC8A
-#define HERMES_RID_CNFPREAMBLE_SYMBOL		0xFC8C	/* used */
+#define HERMES_RID_CNFPREAMBLE_SYMBOL		0xFC8C
 #define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD0	0xFC90
 #define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD1	0xFC91
 #define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD2	0xFC92
@@ -75,18 +76,21 @@
 #define HERMES_RID_CNFRTSTHRESHOLD4		0xFC9B
 #define HERMES_RID_CNFRTSTHRESHOLD5		0xFC9C
 #define HERMES_RID_CNFRTSTHRESHOLD6		0xFC9D
+#define HERMES_RID_CNFHOSTSCAN_SYMBOL		0xFCAB
 #define HERMES_RID_CNFSHORTPREAMBLE		0xFCB0
-#define HERMES_RID_CNFWEPKEYS_AGERE		0xFCB0	/* used */
+#define HERMES_RID_CNFWEPKEYS_AGERE		0xFCB0
 #define HERMES_RID_CNFEXCLUDELONGPREAMBLE	0xFCB1
-#define HERMES_RID_CNFTXKEY_AGERE		0xFCB1	/* used */
+#define HERMES_RID_CNFTXKEY_AGERE		0xFCB1
 #define HERMES_RID_CNFAUTHENTICATIONRSPTO	0xFCB2
+#define HERMES_RID_CNFSCANSSID_AGERE		0xFCB2
 #define HERMES_RID_CNFBASICRATES		0xFCB3
 #define HERMES_RID_CNFSUPPORTEDRATES		0xFCB4
-#define HERMES_RID_CNFTICKTIME			0xFCE0	/* used */
+#define HERMES_RID_CNFTICKTIME			0xFCE0
 #define HERMES_RID_CNFSCANREQUEST		0xFCE1
 #define HERMES_RID_CNFJOINREQUEST		0xFCE2
 #define HERMES_RID_CNFAUTHENTICATESTATION	0xFCE3
 #define HERMES_RID_CNFCHANNELINFOREQUEST	0xFCE4
+#define HERMES_RID_CNFHOSTSCAN			0xFCE5
 
 /*
  * Information RIDs
@@ -100,30 +104,31 @@
 #define HERMES_RID_NICID			0xFD0B
 #define HERMES_RID_MFISUPRANGE			0xFD0C
 #define HERMES_RID_CFISUPRANGE			0xFD0D
-#define HERMES_RID_CHANNELLIST			0xFD10	/* used */
+#define HERMES_RID_CHANNELLIST			0xFD10
 #define HERMES_RID_REGULATORYDOMAINS		0xFD11
 #define HERMES_RID_TEMPTYPE			0xFD12
 #define HERMES_RID_CIS				0xFD13
-#define HERMES_RID_STAID			0xFD20	/* used */
+#define HERMES_RID_STAID			0xFD20
 #define HERMES_RID_STASUPRANGE			0xFD21
 #define HERMES_RID_MFIACTRANGES			0xFD22
 #define HERMES_RID_CFIACTRANGES2		0xFD23
-#define HERMES_RID_SECONDARYVERSION_SYMBOL	0xFD24	/* used */
+#define HERMES_RID_SECONDARYVERSION_SYMBOL	0xFD24
 #define HERMES_RID_PORTSTATUS			0xFD40
-#define HERMES_RID_CURRENTSSID			0xFD41	/* used */
-#define HERMES_RID_CURRENTBSSID			0xFD42	/* used */
-#define HERMES_RID_COMMSQUALITY			0xFD43	/* used */
-#define HERMES_RID_CURRENTTXRATE		0xFD44	/* used */
+#define HERMES_RID_CURRENTSSID			0xFD41
+#define HERMES_RID_CURRENTBSSID			0xFD42
+#define HERMES_RID_COMMSQUALITY			0xFD43
+#define HERMES_RID_CURRENTTXRATE		0xFD44
 #define HERMES_RID_CURRENTBEACONINTERVAL	0xFD45
 #define HERMES_RID_CURRENTSCALETHRESHOLDS	0xFD46
 #define HERMES_RID_PROTOCOLRSPTIME		0xFD47
-#define HERMES_RID_SHORTRETRYLIMIT		0xFD48	/* used */
-#define HERMES_RID_LONGRETRYLIMIT		0xFD49	/* used */
-#define HERMES_RID_MAXTRANSMITLIFETIME		0xFD4A	/* used */
+#define HERMES_RID_SHORTRETRYLIMIT		0xFD48
+#define HERMES_RID_LONGRETRYLIMIT		0xFD49
+#define HERMES_RID_MAXTRANSMITLIFETIME		0xFD4A
 #define HERMES_RID_MAXRECEIVELIFETIME		0xFD4B
 #define HERMES_RID_CFPOLLABLE			0xFD4C
 #define HERMES_RID_AUTHENTICATIONALGORITHMS	0xFD4D
 #define HERMES_RID_PRIVACYOPTIONIMPLEMENTED	0xFD4F
+#define HERMES_RID_DBMCOMMSQUALITY_INTERSIL	0xFD51
 #define HERMES_RID_CURRENTTXRATE1		0xFD80
 #define HERMES_RID_CURRENTTXRATE2		0xFD81
 #define HERMES_RID_CURRENTTXRATE3		0xFD82
@@ -133,21 +138,11 @@
 #define HERMES_RID_OWNMACADDR			0xFD86
 #define HERMES_RID_SCANRESULTSTABLE		0xFD88
 #define HERMES_RID_PHYTYPE			0xFDC0
-#define HERMES_RID_CURRENTCHANNEL		0xFDC1	/* used */
+#define HERMES_RID_CURRENTCHANNEL		0xFDC1
 #define HERMES_RID_CURRENTPOWERSTATE		0xFDC2
 #define HERMES_RID_CCAMODE			0xFDC3
-#define HERMES_RID_SUPPORTEDDATARATES		0xFDC6	/* used */
+#define HERMES_RID_SUPPORTEDDATARATES		0xFDC6
 #define HERMES_RID_BUILDSEQ			0xFFFE
 #define HERMES_RID_FWID				0xFFFF
 
-/* "ID" structure - used for ESSID and station nickname */
-struct hermes_idstring {
-	u16 len;
-	u16 val[16];
-} __attribute__ ((packed));
-
-typedef struct hermes_multicast {
-	u8 addr[HERMES_MAX_MULTICAST][ETH_ALEN];
-} __attribute__ ((packed)) hermes_multicast_t;
-
 #endif
diff --git a/drivers/net/wireless/ieee802_11.h b/drivers/net/wireless/ieee802_11.h
index 07d626ea1..53dd5248f 100644
--- a/drivers/net/wireless/ieee802_11.h
+++ b/drivers/net/wireless/ieee802_11.h
@@ -76,4 +76,3 @@ struct ieee802_11_hdr {
 #define IEEE802_11_SCTL_SEQ		0xFFF0
 
 #endif /* _IEEE802_11_H */
-
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 8161a1c00..284aabeff 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -1,17 +1,23 @@
-/* orinoco.c 0.13e	- (formerly known as dldwd_cs.c and orinoco_cs.c)
+/* orinoco.c - (formerly known as dldwd_cs.c and orinoco_cs.c)
  *
  * A driver for Hermes or Prism 2 chipset based PCMCIA wireless
  * adaptors, with Lucent/Agere, Intersil or Symbol firmware.
  *
- * Copyright (C) 2000 David Gibson, Linuxcare Australia <hermes@gibson.dropbear.id.au>
+ * Current maintainers (as of 29 September 2003) are:
+ * 	Pavel Roskin <proski AT gnu.org>
+ * and	David Gibson <hermes AT gibson.dropbear.id.au>
+ *
+ * (C) Copyright David Gibson, IBM Corporation 2001-2003.
+ * Copyright (C) 2000 David Gibson, Linuxcare Australia.
  *	With some help from :
- * Copyright (C) 2001 Jean Tourrilhes, HP Labs <jt@hpl.hp.com>
- * Copyright (C) 2001 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ * Copyright (C) 2001 Jean Tourrilhes, HP Labs
+ * Copyright (C) 2001 Benjamin Herrenschmidt
  *
  * Based on dummy_cs.c 1.27 2000/06/12 21:27:25
  *
- * Portions based on wvlan_cs.c 1.0.6, Copyright Andreas Neuhaus <andy@fasta.fh-dortmund.de>
- *      http://www.fasta.fh-dortmund.de/users/andy/wvlan/
+ * Portions based on wvlan_cs.c 1.0.6, Copyright Andreas Neuhaus <andy
+ * AT fasta.fh-dortmund.de>
+ *      http://www.stud.fh-dortmund.de/~andy/wvlan/
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -24,7 +30,7 @@
  * limitations under the License.
  *
  * The initial developer of the original code is David A. Hinds
- * <dahinds@users.sourceforge.net>.  Portions created by David
+ * <dahinds AT users.sourceforge.net>.  Portions created by David
  * A. Hinds are Copyright (C) 1999 David A. Hinds.  All Rights
  * Reserved.
  *
@@ -58,7 +64,7 @@
  *	o Add PM timeout (holdover duration)
  *	o Enable "iwconfig eth0 key off" and friends (toggle flags)
  *	o Enable "iwconfig eth0 power unicast/all" (toggle flags)
- *	o Try with an intel card. It report firmware 1.01, behave like
+ *	o Try with an Intel card. It report firmware 1.01, behave like
  *	  an antiquated firmware, however on windows it says 2.00. Yuck !
  *	o Workaround firmware bug in allocate buffer (Intel 1.01)
  *	o Finish external renaming to orinoco...
@@ -68,8 +74,8 @@
  *	o Update to Wireless 11 -> add retry limit/lifetime support
  *	o Tested with a D-Link DWL 650 card, fill in firmware support
  *	o Warning on Vcc mismatch (D-Link 3.3v card in Lucent 5v only slot)
- *	o Fixed the Prims2 WEP bugs that I introduced in v0.03 :-(
- *	  It work on D-Link *only* after a tcpdump. Weird...
+ *	o Fixed the Prism2 WEP bugs that I introduced in v0.03 :-(
+ *	  It works on D-Link *only* after a tcpdump. Weird...
  *	  And still doesn't work on Intel card. Grrrr...
  *	o Update the mode after a setport3
  *	o Add preamble setting for Symbol cards (not yet enabled)
@@ -82,7 +88,7 @@
  *	o Clean up RID definitions in hermes.h, other cleanups
  *
  * v0.04b -> v0.04c - 24/4/2001 - Jean II
- *	o Tim Hurley <timster@seiki.bliztech.com> reported a D-Link card
+ *	o Tim Hurley <timster AT seiki.bliztech.com> reported a D-Link card
  *	  with vendor 02 and firmware 0.08. Added in the capabilities...
  *	o Tested Lucent firmware 7.28, everything works...
  *
@@ -105,15 +111,15 @@
  *	o Remove deferred power enabling code
  *
  * v0.05c -> v0.05d - 5/5/2001 - Jean II
- *	o Workaround to SNAP decapsulate frame from LinkSys AP
- *	  original patch from : Dong Liu <dliu@research.bell-labs.com>
+ *	o Workaround to SNAP decapsulate frame from Linksys AP
+ *	  original patch from : Dong Liu <dliu AT research.bell-labs.com>
  *	  (note : the memcmp bug was mine - fixed)
  *	o Remove set_retry stuff, no firmware support it (bloat--).
  *
  * v0.05d -> v0.06 - 25/5/2001 - Jean II
- *		Original patch from "Hong Lin" <alin@redhat.com>,
- *		"Ian Kinner" <ikinner@redhat.com>
- *		and "David Smith" <dsmith@redhat.com>
+ *		Original patch from "Hong Lin" <alin AT redhat.com>,
+ *		"Ian Kinner" <ikinner AT redhat.com>
+ *		and "David Smith" <dsmith AT redhat.com>
  *	o Init of priv->tx_rate_ctrl in firmware specific section.
  *	o Prism2/Symbol rate, upto should be 0xF and not 0x15. Doh !
  *	o Spectrum card always need cor_reset (for every reset)
@@ -134,15 +140,15 @@
  *
  * v0.06c -> v0.06d - 6/7/2001 - David Gibson
  *      o Change a bunch of KERN_INFO messages to KERN_DEBUG, as per Linus'
- *        wishes to reduce the number of unecessary messages.
+ *        wishes to reduce the number of unnecessary messages.
  *	o Removed bogus message on CRC error.
- *	o Merged fixeds for v0.08 Prism 2 firmware from William Waghorn
- *	  <willwaghorn@yahoo.co.uk>
+ *	o Merged fixes for v0.08 Prism 2 firmware from William Waghorn
+ *	  <willwaghorn AT yahoo.co.uk>
  *	o Slight cleanup/re-arrangement of firmware detection code.
  *
  * v0.06d -> v0.06e - 1/8/2001 - David Gibson
  *	o Removed some redundant global initializers (orinoco_cs.c).
- *	o Added some module metadataa
+ *	o Added some module metadata
  *
  * v0.06e -> v0.06f - 14/8/2001 - David Gibson
  *	o Wording fix to license
@@ -159,7 +165,7 @@
  * v0.07 -> v0.07a - 1/10/3001 - Jean II
  *	o Add code to read Symbol firmware revision, inspired by latest code
  *	  in Spectrum24 by Lee John Keyser-Allen - Thanks Lee !
- *	o Thanks to Jared Valentine <hidden@xmission.com> for "providing" me
+ *	o Thanks to Jared Valentine <hidden AT xmission.com> for "providing" me
  *	  a 3Com card with a recent firmware, fill out Symbol firmware
  *	  capabilities of latest rev (2.20), as well as older Symbol cards.
  *	o Disable Power Management in newer Symbol firmware, the API 
@@ -172,7 +178,7 @@
  *	o Turned has_big_wep on for Intersil cards.  That's not true for all of
  *	  them but we should at least let the capable ones try.
  *	o Wait for BUSY to clear at the beginning of hermes_bap_seek().  I
- *	  realised that my assumption that the driver's serialization
+ *	  realized that my assumption that the driver's serialization
  *	  would prevent the BAP being busy on entry was possibly false, because
  *	  things other than seeks may make the BAP busy.
  *	o Use "alternate" (oui 00:00:00) encapsulation by default.
@@ -181,12 +187,12 @@
  *	o Don't try to make __initdata const (the version string).  This can't
  *	  work because of the way the __initdata sectioning works.
  *	o Added MODULE_LICENSE tags.
- *	o Support for PLX (transparent PCMCIA->PCI brdge) cards.
- *	o Changed to using the new type-facist min/max.
+ *	o Support for PLX (transparent PCMCIA->PCI bridge) cards.
+ *	o Changed to using the new type-fascist min/max.
  *
  * v0.08 -> v0.08a - 9/10/2001 - David Gibson
  *	o Inserted some missing acknowledgements/info into the Changelog.
- *	o Fixed some bugs in the normalisation of signel level reporting.
+ *	o Fixed some bugs in the normalization of signal level reporting.
  *	o Fixed bad bug in WEP key handling on Intersil and Symbol firmware,
  *	  which led to an instant crash on big-endian machines.
  *
@@ -342,7 +348,7 @@
  *	o Bugfix in orinoco_stop() - it used to fail if hw_unavailable
  *	  was set, which was usually true on PCMCIA hot removes.
  * 	o Track LINKSTATUS messages, silently drop Tx packets before
- * 	  we are connected (avoids cofusing the firmware), and only
+ * 	  we are connected (avoids confusing the firmware), and only
  * 	  give LINKSTATUS printk()s if the status has changed.
  *
  * v0.13b -> v0.13c - 11 Mar 2003 - David Gibson
@@ -397,7 +403,8 @@
  *	o Disconnect wireless extensions from fundamental configuration.
  *	o (maybe) Software WEP support (patch from Stano Meduna).
  *	o (maybe) Use multiple Tx buffers - driver handling queue
- *	  rather than firmware. */
+ *	  rather than firmware.
+ */
 
 /* Locking and synchronization:
  *
@@ -414,7 +421,10 @@
  * flag after taking the lock, and if it is set, give up on whatever
  * they are doing and drop the lock again.  The orinoco_lock()
  * function handles this (it unlocks and returns -EBUSY if
- * hw_unavailable is non-zero). */
+ * hw_unavailable is non-zero).
+ */
+
+#define DRIVER_NAME "orinoco"
 
 #include <linux/config.h>
 
@@ -444,11 +454,9 @@
 /* Module information                                               */
 /********************************************************************/
 
-MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
+MODULE_AUTHOR("Pavel Roskin <proski@gnu.org> & David Gibson <hermes@gibson.dropbear.id.au>");
 MODULE_DESCRIPTION("Driver for Lucent Orinoco, Prism II based and similar wireless cards");
-#ifdef MODULE_LICENSE
 MODULE_LICENSE("Dual MPL/GPL");
-#endif
 
 /* Level of debugging. Used in the macros in orinoco.h */
 #ifdef ORINOCO_DEBUG
@@ -464,11 +472,6 @@ MODULE_PARM(suppress_linkstatus, "i");
 /* Compile time configuration and compatibility stuff               */
 /********************************************************************/
 
-/* Wireless extensions backwards compatibility */
-#ifndef SIOCIWFIRSTPRIV
-#define SIOCIWFIRSTPRIV		SIOCDEVPRIVATE
-#endif /* SIOCIWFIRSTPRIV */
-
 /* We do this this way to avoid ifdefs in the actual code */
 #ifdef WIRELESS_SPY
 #define SPY_NUMBER(priv)	(priv->spy_number)
@@ -497,25 +500,29 @@ MODULE_PARM(suppress_linkstatus, "i");
 
 #define DUMMY_FID		0xFFFF
 
-#define RUP_EVEN(a) (((a) + 1) & (~1))
-
 /*#define MAX_MULTICAST(priv)	(priv->firmware_type == FIRMWARE_TYPE_AGERE ? \
   HERMES_MAX_MULTICAST : 0)*/
 #define MAX_MULTICAST(priv)	(HERMES_MAX_MULTICAST)
 
+#define ORINOCO_INTEN	 	(HERMES_EV_RX | HERMES_EV_ALLOC \
+				 | HERMES_EV_TX | HERMES_EV_TXEXC \
+				 | HERMES_EV_WTERR | HERMES_EV_INFO \
+				 | HERMES_EV_INFDROP )
+
 /********************************************************************/
 /* Data tables                                                      */
 /********************************************************************/
 
 /* The frequency of each channel in MHz */
-const long channel_frequency[] = {
+static const long channel_frequency[] = {
 	2412, 2417, 2422, 2427, 2432, 2437, 2442,
 	2447, 2452, 2457, 2462, 2467, 2472, 2484
 };
-#define NUM_CHANNELS ( sizeof(channel_frequency) / sizeof(channel_frequency[0]) )
+#define NUM_CHANNELS ARRAY_SIZE(channel_frequency)
 
-/* This tables gives the actual meanings of the bitrate IDs returned by the firmware. */
-struct {
+/* This tables gives the actual meanings of the bitrate IDs returned
+ * by the firmware. */
+static struct {
 	int bitrate; /* in 100s of kilobits */
 	int automatic;
 	u16 agere_txratectrl;
@@ -530,7 +537,7 @@ struct {
 	{55,  1,  7,  7},
 	{110, 0,  5,  8},
 };
-#define BITRATE_TABLE_SIZE (sizeof(bitrate_table) / sizeof(bitrate_table[0]))
+#define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table)
 
 /********************************************************************/
 /* Data types                                                       */
@@ -555,133 +562,54 @@ u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
 
 #define ENCAPS_OVERHEAD		(sizeof(encaps_hdr) + 2)
 
+struct hermes_rx_descriptor {
+	u16 status;
+	u32 time;
+	u8 silence;
+	u8 signal;
+	u8 rate;
+	u8 rxflow;
+	u32 reserved;
+} __attribute__ ((packed));
+
 /********************************************************************/
 /* Function prototypes                                              */
 /********************************************************************/
 
-static void orinoco_stat_gather(struct net_device *dev,
-				struct sk_buff *skb,
-				struct hermes_rx_descriptor *desc);
-
-static struct net_device_stats *orinoco_get_stats(struct net_device *dev);
-static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev);
-
-/* Hardware control routines */
-
+static int orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int __orinoco_program_rids(struct net_device *dev);
-
-static int __orinoco_hw_set_bitrate(struct orinoco_private *priv);
-static int __orinoco_hw_setup_wep(struct orinoco_private *priv);
-static int orinoco_hw_get_bssid(struct orinoco_private *priv, char buf[ETH_ALEN]);
-static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
-				char buf[IW_ESSID_MAX_SIZE+1]);
-static long orinoco_hw_get_freq(struct orinoco_private *priv);
-static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, int *numrates,
-				      s32 *rates, int max);
 static void __orinoco_set_multicast_list(struct net_device *dev);
-
-/* Interrupt handling routines */
-static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw);
-static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw);
-static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw);
-static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw);
-static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw);
-static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw);
-static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw);
-static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw);
-
-/* ioctl() routines */
 static int orinoco_debug_dump_recs(struct net_device *dev);
 
 /********************************************************************/
-/* Function prototypes                                              */
+/* Internal helper functions                                        */
 /********************************************************************/
 
-int __orinoco_up(struct net_device *dev)
-{
-	struct orinoco_private *priv = netdev_priv(dev);
-	struct hermes *hw = &priv->hw;
-	int err;
-
-	err = __orinoco_program_rids(dev);
-	if (err) {
-		printk(KERN_ERR "%s: Error %d configuring card\n",
-		       dev->name, err);
-		return err;
-	}
-
-	/* Fire things up again */
-	hermes_set_irqmask(hw, ORINOCO_INTEN);
-	err = hermes_enable_port(hw, 0);
-	if (err) {
-		printk(KERN_ERR "%s: Error %d enabling MAC port\n",
-		       dev->name, err);
-		return err;
-	}
-
-	netif_start_queue(dev);
-
-	return 0;
-}
-
-int __orinoco_down(struct net_device *dev)
+static inline void set_port_type(struct orinoco_private *priv)
 {
-	struct orinoco_private *priv = netdev_priv(dev);
-	struct hermes *hw = &priv->hw;
-	int err;
-
-	netif_stop_queue(dev);
-
-	if (! priv->hw_unavailable) {
-		if (! priv->broken_disableport) {
-			err = hermes_disable_port(hw, 0);
-			if (err) {
-				/* Some firmwares (e.g. Intersil 1.3.x) seem
-				 * to have problems disabling the port, oh
-				 * well, too bad. */
-				printk(KERN_WARNING "%s: Error %d disabling MAC port\n",
-				       dev->name, err);
-				priv->broken_disableport = 1;
-			}
+	switch (priv->iw_mode) {
+	case IW_MODE_INFRA:
+		priv->port_type = 1;
+		priv->createibss = 0;
+		break;
+	case IW_MODE_ADHOC:
+		if (priv->prefer_port3) {
+			priv->port_type = 3;
+			priv->createibss = 0;
+		} else {
+			priv->port_type = priv->ibss_port;
+			priv->createibss = 1;
 		}
-		hermes_set_irqmask(hw, 0);
-		hermes_write_regn(hw, EVACK, 0xffff);
+		break;
+	default:
+		printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",
+		       priv->ndev->name);
 	}
-	
-	/* firmware will have to reassociate */
-	priv->last_linkstatus = 0xffff;
-	priv->connected = 0;
-
-	return 0;
 }
 
-int orinoco_reinit_firmware(struct net_device *dev)
-{
-	struct orinoco_private *priv = netdev_priv(dev);
-	struct hermes *hw = &priv->hw;
-	int err;
-
-	err = hermes_init(hw);
-	if (err)
-		return err;
-
-	err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
-	if (err == -EIO) {
-		/* Try workaround for old Symbol firmware bug */
-		printk(KERN_WARNING "%s: firmware ALLOC bug detected "
-		       "(old Symbol firmware?). Trying to work around... ",
-		       dev->name);
-		
-		priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
-		err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
-		if (err)
-			printk("failed!\n");
-		else
-			printk("ok.\n");
-	}
-
-	return err;
-}
+/********************************************************************/
+/* Device methods                                                   */
+/********************************************************************/
 
 static int orinoco_open(struct net_device *dev)
 {
@@ -722,843 +650,562 @@ int orinoco_stop(struct net_device *dev)
 	return err;
 }
 
-static int __orinoco_program_rids(struct net_device *dev)
+static struct net_device_stats *orinoco_get_stats(struct net_device *dev)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	
+	return &priv->stats;
+}
+
+static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
 {
 	struct orinoco_private *priv = netdev_priv(dev);
 	hermes_t *hw = &priv->hw;
-	int err;
-	struct hermes_idstring idbuf;
+	struct iw_statistics *wstats = &priv->wstats;
+	int err = 0;
+	unsigned long flags;
 
-	/* Set the MAC address */
-	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
-			       HERMES_BYTES_TO_RECLEN(ETH_ALEN), dev->dev_addr);
-	if (err) {
-		printk(KERN_ERR "%s: Error %d setting MAC address\n", dev->name, err);
-		return err;
+	if (! netif_device_present(dev)) {
+		printk(KERN_WARNING "%s: get_wireless_stats() called while device not present\n",
+		       dev->name);
+		return NULL; /* FIXME: Can we do better than this? */
 	}
 
-	/* Set up the link mode */
-	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE, priv->port_type);
-	if (err) {
-		printk(KERN_ERR "%s: Error %d setting port type\n", dev->name, err);
-		return err;
-	}
-	/* Set the channel/frequency */
-	if (priv->channel == 0) {
-		printk(KERN_DEBUG "%s: Channel is 0 in __orinoco_program_rids()\n", dev->name);
-		if (priv->createibss)
-			priv->channel = 10;
-	}
-	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFOWNCHANNEL, priv->channel);
-	if (err) {
-		printk(KERN_ERR "%s: Error %d setting channel\n", dev->name, err);
-		return err;
-	}
+	err = orinoco_lock(priv, &flags);
+	if (err)
+		return NULL; /* FIXME: Erg, we've been signalled, how
+			      * do we propagate this back up? */
 
-	if (priv->has_ibss) {
-		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFCREATEIBSS,
-					   priv->createibss);
-		if (err) {
-			printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n", dev->name, err);
-			return err;
+	if (priv->iw_mode == IW_MODE_ADHOC) {
+		memset(&wstats->qual, 0, sizeof(wstats->qual));
+		/* If a spy address is defined, we report stats of the
+		 * first spy address - Jean II */
+		if (SPY_NUMBER(priv)) {
+			wstats->qual.qual = priv->spy_stat[0].qual;
+			wstats->qual.level = priv->spy_stat[0].level;
+			wstats->qual.noise = priv->spy_stat[0].noise;
+			wstats->qual.updated = priv->spy_stat[0].updated;
 		}
+	} else {
+		struct {
+			u16 qual, signal, noise;
+		} __attribute__ ((packed)) cq;
 
-		if ((strlen(priv->desired_essid) == 0) && (priv->createibss)
-		   && (!priv->has_ibss_any)) {
-			printk(KERN_WARNING "%s: This firmware requires an \
-ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
-			/* With wvlan_cs, in this case, we would crash.
-			 * hopefully, this driver will behave better...
-			 * Jean II */
-		}
+		err = HERMES_READ_RECORD(hw, USER_BAP,
+					 HERMES_RID_COMMSQUALITY, &cq);
+		
+		wstats->qual.qual = (int)le16_to_cpu(cq.qual);
+		wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
+		wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
+		wstats->qual.updated = 7;
 	}
 
-	/* Set the desired ESSID */
-	idbuf.len = cpu_to_le16(strlen(priv->desired_essid));
-	memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
-	/* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */
-	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
-			       HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
-			       &idbuf);
-	if (err) {
-		printk(KERN_ERR "%s: Error %d setting OWNSSID\n", dev->name, err);
-		return err;
-	}
-	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
-			       HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
-			       &idbuf);
-	if (err) {
-		printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n", dev->name, err);
-		return err;
-	}
+	/* We can't really wait for the tallies inquiry command to
+	 * complete, so we just use the previous results and trigger
+	 * a new tallies inquiry command for next time - Jean II */
+	/* FIXME: We're in user context (I think?), so we should just
+           wait for the tallies to come through */
+	err = hermes_inquire(hw, HERMES_INQ_TALLIES);
+               
+	orinoco_unlock(priv, &flags);
 
-	/* Set the station name */
-	idbuf.len = cpu_to_le16(strlen(priv->nick));
-	memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
-	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
-			       HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
-			       &idbuf);
-	if (err) {
-		printk(KERN_ERR "%s: Error %d setting nickname\n", dev->name, err);
-		return err;
-	}
+	if (err)
+		return NULL;
+		
+	return wstats;
+}
 
-	/* Set AP density */
-	if (priv->has_sensitivity) {
-		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE,
-					   priv->ap_density);
-		if (err) {
-			printk(KERN_WARNING "%s: Error %d setting SYSTEMSCALE.  "
-			       "Disabling sensitivity control\n", dev->name, err);
+static void orinoco_set_multicast_list(struct net_device *dev)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	unsigned long flags;
 
-			priv->has_sensitivity = 0;
-		}
+	if (orinoco_lock(priv, &flags) != 0) {
+		printk(KERN_DEBUG "%s: orinoco_set_multicast_list() "
+		       "called when hw_unavailable\n", dev->name);
+		return;
 	}
 
-	/* Set RTS threshold */
-	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD, priv->rts_thresh);
-	if (err) {
-		printk(KERN_ERR "%s: Error %d setting RTS threshold\n", dev->name, err);
-		return err;
-	}
+	__orinoco_set_multicast_list(dev);
+	orinoco_unlock(priv, &flags);
+}
 
-	/* Set fragmentation threshold or MWO robustness */
-	if (priv->has_mwo)
-		err = hermes_write_wordrec(hw, USER_BAP,
-					   HERMES_RID_CNFMWOROBUST_AGERE,
-					   priv->mwo_robust);
-	else
-		err = hermes_write_wordrec(hw, USER_BAP,
-					   HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
-					   priv->frag_thresh);
-	if (err) {
-		printk(KERN_ERR "%s: Error %d setting framentation\n", dev->name, err);
-		return err;
-	}
-
-	/* Set bitrate */
-	err = __orinoco_hw_set_bitrate(priv);
-	if (err) {
-		printk(KERN_ERR "%s: Error %d setting bitrate\n", dev->name, err);
-		return err;
-	}
-
-	/* Set power management */
-	if (priv->has_pm) {
-		err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPMENABLED,
-					   priv->pm_on);
-		if (err) {
-			printk(KERN_ERR "%s: Error %d setting up PM\n",
-			       dev->name, err);
-			return err;
-		}
-
-		err = hermes_write_wordrec(hw, USER_BAP,
-					   HERMES_RID_CNFMULTICASTRECEIVE,
-					   priv->pm_mcast);
-		if (err) {
-			printk(KERN_ERR "%s: Error %d setting up PM\n",
-			       dev->name, err);
-			return err;
-		}
-		err = hermes_write_wordrec(hw, USER_BAP,
-					   HERMES_RID_CNFMAXSLEEPDURATION,
-					   priv->pm_period);
-		if (err) {
-			printk(KERN_ERR "%s: Error %d setting up PM\n",
-			       dev->name, err);
-			return err;
-		}
-		err = hermes_write_wordrec(hw, USER_BAP,
-					   HERMES_RID_CNFPMHOLDOVERDURATION,
-					   priv->pm_timeout);
-		if (err) {
-			printk(KERN_ERR "%s: Error %d setting up PM\n",
-			       dev->name, err);
-			return err;
-		}
-	}
+static int orinoco_change_mtu(struct net_device *dev, int new_mtu)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
 
-	/* Set preamble - only for Symbol so far... */
-	if (priv->has_preamble) {
-		err = hermes_write_wordrec(hw, USER_BAP,
-					   HERMES_RID_CNFPREAMBLE_SYMBOL,
-					   priv->preamble);
-		if (err) {
-			printk(KERN_ERR "%s: Error %d setting preamble\n",
-			       dev->name, err);
-			return err;
-		}
-	}
+	if ( (new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU) )
+		return -EINVAL;
 
-	/* Set up encryption */
-	if (priv->has_wep) {
-		err = __orinoco_hw_setup_wep(priv);
-		if (err) {
-			printk(KERN_ERR "%s: Error %d activating WEP\n",
-			       dev->name, err);
-			return err;
-		}
-	}
+	if ( (new_mtu + ENCAPS_OVERHEAD + IEEE802_11_HLEN) >
+	     (priv->nicbuf_size - ETH_HLEN) )
+		return -EINVAL;
 
-	/* Set promiscuity / multicast*/
-	priv->promiscuous = 0;
-	priv->mc_count = 0;
-	__orinoco_set_multicast_list(dev); /* FIXME: what about the xmit_lock */
+	dev->mtu = new_mtu;
 
 	return 0;
 }
 
-/* xyzzy */
-static int orinoco_reconfigure(struct net_device *dev)
+/********************************************************************/
+/* Tx path                                                          */
+/********************************************************************/
+
+static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct orinoco_private *priv = netdev_priv(dev);
-	struct hermes *hw = &priv->hw;
-	unsigned long flags;
+	struct net_device_stats *stats = &priv->stats;
+	hermes_t *hw = &priv->hw;
 	int err = 0;
+	u16 txfid = priv->txfid;
+	char *p;
+	struct ethhdr *eh;
+	int len, data_len, data_off;
+	struct hermes_tx_descriptor desc;
+	unsigned long flags;
 
-	if (priv->broken_disableport) {
-		schedule_work(&priv->reset_work);
-		return 0;
-	}
-
-	err = orinoco_lock(priv, &flags);
-	if (err)
-		return err;
+	TRACE_ENTER(dev->name);
 
-		
-	err = hermes_disable_port(hw, 0);
-	if (err) {
-		printk(KERN_WARNING "%s: Unable to disable port while reconfiguring card\n",
+	if (! netif_running(dev)) {
+		printk(KERN_ERR "%s: Tx on stopped device!\n",
 		       dev->name);
-		priv->broken_disableport = 1;
-		goto out;
+		TRACE_EXIT(dev->name);
+		return 1;
 	}
-
-	err = __orinoco_program_rids(dev);
-	if (err) {
-		printk(KERN_WARNING "%s: Unable to reconfigure card\n",
+	
+	if (netif_queue_stopped(dev)) {
+		printk(KERN_DEBUG "%s: Tx while transmitter busy!\n", 
 		       dev->name);
-		goto out;
+		TRACE_EXIT(dev->name);
+		return 1;
 	}
-
-	err = hermes_enable_port(hw, 0);
-	if (err) {
-		printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",
+	
+	if (orinoco_lock(priv, &flags) != 0) {
+		printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n",
 		       dev->name);
-		goto out;
+		TRACE_EXIT(dev->name);
+		return 1;
 	}
 
- out:
-	if (err) {
-		printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);
-		schedule_work(&priv->reset_work);
-		err = 0;
+	if (! priv->connected) {
+		/* Oops, the firmware hasn't established a connection,
+                   silently drop the packet (this seems to be the
+                   safest approach). */
+		stats->tx_errors++;
+		orinoco_unlock(priv, &flags);
+		dev_kfree_skb(skb);
+		TRACE_EXIT(dev->name);
+		return 0;
 	}
 
-	orinoco_unlock(priv, &flags);
-	return err;
-
-}
-
-/* This must be called from user context, without locks held - use
- * schedule_work() */
-static void orinoco_reset(struct net_device *dev)
-{
-	struct orinoco_private *priv = netdev_priv(dev);
-	struct hermes *hw = &priv->hw;
-	int err;
-	unsigned long flags;
+	/* Length of the packet body */
+	/* FIXME: what if the skb is smaller than this? */
+	len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN);
 
-	err = orinoco_lock(priv, &flags);
-	if (err)
-		/* When the hardware becomes available again, whatever
-		 * detects that is responsible for re-initializing
-		 * it. So no need for anything further*/
-		return;
+	eh = (struct ethhdr *)skb->data;
 
-	netif_stop_queue(dev);
+	memset(&desc, 0, sizeof(desc));
+ 	desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX);
+	err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), txfid, 0);
+	if (err) {
+		printk(KERN_ERR "%s: Error %d writing Tx descriptor to BAP\n",
+		       dev->name, err);
+		stats->tx_errors++;
+		goto fail;
+	}
 
-	/* Shut off interrupts.  Depending on what state the hardware
-	 * is in, this might not work, but we'll try anyway */
-	hermes_set_irqmask(hw, 0);
-	hermes_write_regn(hw, EVACK, 0xffff);
+	/* Clear the 802.11 header and data length fields - some
+	 * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused
+	 * if this isn't done. */
+	hermes_clear_words(hw, HERMES_DATA0,
+			   HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);
 
-	priv->hw_unavailable++;
-	priv->last_linkstatus = 0xffff; /* firmware will have to reassociate */
-	priv->connected = 0;
+	/* Encapsulate Ethernet-II frames */
+	if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */
+		struct header_struct hdr;
+		data_len = len;
+		data_off = HERMES_802_3_OFFSET + sizeof(hdr);
+		p = skb->data + ETH_HLEN;
 
-	orinoco_unlock(priv, &flags);
+		/* 802.3 header */
+		memcpy(hdr.dest, eh->h_dest, ETH_ALEN);
+		memcpy(hdr.src, eh->h_source, ETH_ALEN);
+		hdr.len = htons(data_len + ENCAPS_OVERHEAD);
+		
+		/* 802.2 header */
+		memcpy(&hdr.dsap, &encaps_hdr, sizeof(encaps_hdr));
+			
+		hdr.ethertype = eh->h_proto;
+		err  = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),
+					 txfid, HERMES_802_3_OFFSET);
+		if (err) {
+			printk(KERN_ERR "%s: Error %d writing packet header to BAP\n",
+			       dev->name, err);
+			stats->tx_errors++;
+			goto fail;
+		}
+	} else { /* IEEE 802.3 frame */
+		data_len = len + ETH_HLEN;
+		data_off = HERMES_802_3_OFFSET;
+		p = skb->data;
+	}
 
-	if (priv->hard_reset)
-		err = (*priv->hard_reset)(priv);
+	/* Round up for odd length packets */
+	err = hermes_bap_pwrite(hw, USER_BAP, p, ALIGN(data_len, 2),
+				txfid, data_off);
 	if (err) {
-		printk(KERN_ERR "%s: orinoco_reset: Error %d performing hard reset\n",
+		printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
 		       dev->name, err);
-		/* FIXME: shutdown of some sort */
-		return;
+		stats->tx_errors++;
+		goto fail;
 	}
 
-	err = orinoco_reinit_firmware(dev);
+	/* Finally, we actually initiate the send */
+	netif_stop_queue(dev);
+
+	err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL,
+				txfid, NULL);
 	if (err) {
-		printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n",
+		netif_start_queue(dev);
+		printk(KERN_ERR "%s: Error %d transmitting packet\n",
 		       dev->name, err);
-		return;
+		stats->tx_errors++;
+		goto fail;
 	}
 
-	spin_lock_irq(&priv->lock); /* This has to be called from user context */
+	dev->trans_start = jiffies;
+	stats->tx_bytes += data_off + data_len;
 
-	priv->hw_unavailable--;
+	orinoco_unlock(priv, &flags);
 
-	/* priv->open or priv->hw_unavailable might have changed while
-	 * we dropped the lock */
-	if (priv->open && (! priv->hw_unavailable)) {
-		err = __orinoco_up(dev);
-		if (err) {
-			printk(KERN_ERR "%s: orinoco_reset: Error %d reenabling card\n",
-			       dev->name, err);
-		} else
-			dev->trans_start = jiffies;
-	}
+	dev_kfree_skb(skb);
 
-	spin_unlock_irq(&priv->lock);
+	TRACE_EXIT(dev->name);
 
-	return;
-}
+	return 0;
+ fail:
+	TRACE_EXIT(dev->name);
 
-/********************************************************************/
-/* Internal helper functions                                        */
-/********************************************************************/
-
-static inline void
-set_port_type(struct orinoco_private *priv)
-{
-	switch (priv->iw_mode) {
-	case IW_MODE_INFRA:
-		priv->port_type = 1;
-		priv->createibss = 0;
-		break;
-	case IW_MODE_ADHOC:
-		if (priv->prefer_port3) {
-			priv->port_type = 3;
-			priv->createibss = 0;
-		} else {
-			priv->port_type = priv->ibss_port;
-			priv->createibss = 1;
-		}
-		break;
-	default:
-		printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",
-		       priv->ndev->name);
-	}
-}
-
-/* Does the frame have a SNAP header indicating it should be
- * de-encapsulated to Ethernet-II? */
-static inline int
-is_ethersnap(struct header_struct *hdr)
-{
-	/* We de-encapsulate all packets which, a) have SNAP headers
-	 * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header
-	 * and where b) the OUI of the SNAP header is 00:00:00 or
-	 * 00:00:f8 - we need both because different APs appear to use
-	 * different OUIs for some reason */
-	return (memcmp(&hdr->dsap, &encaps_hdr, 5) == 0)
-		&& ( (hdr->oui[2] == 0x00) || (hdr->oui[2] == 0xf8) );
+	orinoco_unlock(priv, &flags);
+	return err;
 }
 
-static void
-orinoco_set_multicast_list(struct net_device *dev)
+static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
 {
 	struct orinoco_private *priv = netdev_priv(dev);
-	unsigned long flags;
+	u16 fid = hermes_read_regn(hw, ALLOCFID);
 
-	if (orinoco_lock(priv, &flags) != 0) {
-		printk(KERN_DEBUG "%s: orinoco_set_multicast_list() "
-		       "called when hw_unavailable\n", dev->name);
+	if (fid != priv->txfid) {
+		if (fid != DUMMY_FID)
+			printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n",
+			       dev->name, fid);
 		return;
+	} else {
+		netif_wake_queue(dev);
 	}
 
-	__orinoco_set_multicast_list(dev);
-	orinoco_unlock(priv, &flags);
+	hermes_write_regn(hw, ALLOCFID, DUMMY_FID);
 }
 
-/********************************************************************/
-/* Hardware control functions                                       */
-/********************************************************************/
+static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &priv->stats;
 
+	stats->tx_packets++;
 
-static int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
+	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
+}
+
+static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
 {
-	hermes_t *hw = &priv->hw;
+	struct orinoco_private *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &priv->stats;
+	u16 fid = hermes_read_regn(hw, TXCOMPLFID);
+	struct hermes_tx_descriptor desc;
 	int err = 0;
 
-	if (priv->bitratemode >= BITRATE_TABLE_SIZE) {
-		printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n",
-		       priv->ndev->name, priv->bitratemode);
-		return -EINVAL;
-	}
+	if (fid == DUMMY_FID)
+		return; /* Nothing's really happened */
 
-	switch (priv->firmware_type) {
-	case FIRMWARE_TYPE_AGERE:
-		err = hermes_write_wordrec(hw, USER_BAP,
-					   HERMES_RID_CNFTXRATECONTROL,
-					   bitrate_table[priv->bitratemode].agere_txratectrl);
-		break;
-	case FIRMWARE_TYPE_INTERSIL:
-	case FIRMWARE_TYPE_SYMBOL:
-		err = hermes_write_wordrec(hw, USER_BAP,
-					   HERMES_RID_CNFTXRATECONTROL,
-					   bitrate_table[priv->bitratemode].intersil_txratectrl);
-		break;
-	default:
-		BUG();
+	err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc), fid, 0);
+	if (err) {
+		printk(KERN_WARNING "%s: Unable to read descriptor on Tx error "
+		       "(FID=%04X error %d)\n",
+		       dev->name, fid, err);
+	} else {
+		DEBUG(1, "%s: Tx error, status %d\n",
+		      dev->name, le16_to_cpu(desc.status));
 	}
+	
+	stats->tx_errors++;
 
-	return err;
+	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
 }
 
-
-static int __orinoco_hw_setup_wep(struct orinoco_private *priv)
+static void orinoco_tx_timeout(struct net_device *dev)
 {
-	hermes_t *hw = &priv->hw;
-	int err = 0;
-	int	master_wep_flag;
-	int	auth_flag;
+	struct orinoco_private *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &priv->stats;
+	struct hermes *hw = &priv->hw;
 
-	switch (priv->firmware_type) {
-	case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
-		if (priv->wep_on) {
-			err = hermes_write_wordrec(hw, USER_BAP,
-						   HERMES_RID_CNFTXKEY_AGERE,
-						   priv->tx_key);
-			if (err)
-				return err;
-			
-			err = HERMES_WRITE_RECORD(hw, USER_BAP,
-						  HERMES_RID_CNFWEPKEYS_AGERE,
-						  &priv->keys);
-			if (err)
-				return err;
-		}
-		err = hermes_write_wordrec(hw, USER_BAP,
-					   HERMES_RID_CNFWEPENABLED_AGERE,
-					   priv->wep_on);
-		if (err)
-			return err;
-		break;
+	printk(KERN_WARNING "%s: Tx timeout! "
+	       "ALLOCFID=%04x, TXCOMPLFID=%04x, EVSTAT=%04x\n",
+	       dev->name, hermes_read_regn(hw, ALLOCFID),
+	       hermes_read_regn(hw, TXCOMPLFID), hermes_read_regn(hw, EVSTAT));
 
-	case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
-	case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
-		master_wep_flag = 0;		/* Off */
-		if (priv->wep_on) {
-			int keylen;
-			int i;
+	stats->tx_errors++;
 
-			/* Fudge around firmware weirdness */
-			keylen = le16_to_cpu(priv->keys[priv->tx_key].len);
-			
-			/* Write all 4 keys */
-			for(i = 0; i < ORINOCO_MAX_KEYS; i++) {
-/*  				int keylen = le16_to_cpu(priv->keys[i].len); */
-				
-				if (keylen > LARGE_KEY_SIZE) {
-					printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
-					       priv->ndev->name, i, keylen);
-					return -E2BIG;
-				}
+	schedule_work(&priv->reset_work);
+}
 
-				err = hermes_write_ltv(hw, USER_BAP,
-						       HERMES_RID_CNFDEFAULTKEY0 + i,
-						       HERMES_BYTES_TO_RECLEN(keylen),
-						       priv->keys[i].data);
-				if (err)
-					return err;
-			}
+/********************************************************************/
+/* Rx path (data frames)                                            */
+/********************************************************************/
 
-			/* Write the index of the key used in transmission */
-			err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFWEPDEFAULTKEYID,
-						   priv->tx_key);
-			if (err)
-				return err;
-			
-			if (priv->wep_restrict) {
-				auth_flag = 2;
-				master_wep_flag = 3;
-			} else {
-				/* Authentication is where Intersil and Symbol
-				 * firmware differ... */
-				auth_flag = 1;
-				if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)
-					master_wep_flag = 3; /* Symbol */ 
-				else 
-					master_wep_flag = 1; /* Intersil */
-			}
+/* Does the frame have a SNAP header indicating it should be
+ * de-encapsulated to Ethernet-II? */
+static inline int is_ethersnap(struct header_struct *hdr)
+{
+	/* We de-encapsulate all packets which, a) have SNAP headers
+	 * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header
+	 * and where b) the OUI of the SNAP header is 00:00:00 or
+	 * 00:00:f8 - we need both because different APs appear to use
+	 * different OUIs for some reason */
+	return (memcmp(&hdr->dsap, &encaps_hdr, 5) == 0)
+		&& ( (hdr->oui[2] == 0x00) || (hdr->oui[2] == 0xf8) );
+}
 
+static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
+				      int level, int noise)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	int i;
 
-			err = hermes_write_wordrec(hw, USER_BAP,
-						   HERMES_RID_CNFAUTHENTICATION, auth_flag);
-			if (err)
-				return err;
+	/* Gather wireless spy statistics: for each packet, compare the
+	 * source address with out list, and if match, get the stats... */
+	for (i = 0; i < priv->spy_number; i++)
+		if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) {
+			priv->spy_stat[i].level = level - 0x95;
+			priv->spy_stat[i].noise = noise - 0x95;
+			priv->spy_stat[i].qual = (level > noise) ? (level - noise) : 0;
+			priv->spy_stat[i].updated = 7;
 		}
-		
-		/* Master WEP setting : on/off */
-		err = hermes_write_wordrec(hw, USER_BAP,
-					   HERMES_RID_CNFWEPFLAGS_INTERSIL,
-					   master_wep_flag);
-		if (err)
-			return err;	
+}
 
-		break;
+static void orinoco_stat_gather(struct net_device *dev,
+				struct sk_buff *skb,
+				struct hermes_rx_descriptor *desc)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
 
-	default:
-		if (priv->wep_on) {
-			printk(KERN_ERR "%s: WEP enabled, although not supported!\n",
-			       priv->ndev->name);
-			return -EINVAL;
-		}
+	/* Using spy support with lots of Rx packets, like in an
+	 * infrastructure (AP), will really slow down everything, because
+	 * the MAC address must be compared to each entry of the spy list.
+	 * If the user really asks for it (set some address in the
+	 * spy list), we do it, but he will pay the price.
+	 * Note that to get here, you need both WIRELESS_SPY
+	 * compiled in AND some addresses in the list !!!
+	 */
+	/* Note : gcc will optimise the whole section away if
+	 * WIRELESS_SPY is not defined... - Jean II */
+	if (SPY_NUMBER(priv)) {
+		orinoco_spy_gather(dev, skb->mac.raw + ETH_ALEN,
+				   desc->signal, desc->silence);
 	}
-
-	return 0;
 }
 
-static int orinoco_hw_get_bssid(struct orinoco_private *priv,
-				char buf[ETH_ALEN])
+static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
 {
-	hermes_t *hw = &priv->hw;
-	int err = 0;
-	unsigned long flags;
-
-	err = orinoco_lock(priv, &flags);
-	if (err)
-		return err;
-
-	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
-			      ETH_ALEN, NULL, buf);
+	struct orinoco_private *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &priv->stats;
+	struct iw_statistics *wstats = &priv->wstats;
+	struct sk_buff *skb = NULL;
+	u16 rxfid, status;
+	int length, data_len, data_off;
+	char *p;
+	struct hermes_rx_descriptor desc;
+	struct header_struct hdr;
+	struct ethhdr *eh;
+	int err;
 
-	orinoco_unlock(priv, &flags);
+	rxfid = hermes_read_regn(hw, RXFID);
 
-	return err;
-}
+	err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc),
+			       rxfid, 0);
+	if (err) {
+		printk(KERN_ERR "%s: error %d reading Rx descriptor. "
+		       "Frame dropped.\n", dev->name, err);
+		stats->rx_errors++;
+		goto drop;
+	}
 
-static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
-				char buf[IW_ESSID_MAX_SIZE+1])
-{
-	hermes_t *hw = &priv->hw;
-	int err = 0;
-	struct hermes_idstring essidbuf;
-	char *p = (char *)(&essidbuf.val);
-	int len;
-	unsigned long flags;
+	status = le16_to_cpu(desc.status);
 
-	err = orinoco_lock(priv, &flags);
-	if (err)
-		return err;
+	if (status & HERMES_RXSTAT_ERR) {
+		if (status & HERMES_RXSTAT_UNDECRYPTABLE) {
+			wstats->discard.code++;
+			DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n",
+			       dev->name);
+		} else {
+			stats->rx_crc_errors++;
+			DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name);
+		}
+		stats->rx_errors++;
+		goto drop;
+	}
 
-	if (strlen(priv->desired_essid) > 0) {
-		/* We read the desired SSID from the hardware rather
-		   than from priv->desired_essid, just in case the
-		   firmware is allowed to change it on us. I'm not
-		   sure about this */
-		/* My guess is that the OWNSSID should always be whatever
-		 * we set to the card, whereas CURRENT_SSID is the one that
-		 * may change... - Jean II */
-		u16 rid;
+	/* For now we ignore the 802.11 header completely, assuming
+           that the card's firmware has handled anything vital */
 
-		*active = 1;
+	err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr),
+			       rxfid, HERMES_802_3_OFFSET);
+	if (err) {
+		printk(KERN_ERR "%s: error %d reading frame header. "
+		       "Frame dropped.\n", dev->name, err);
+		stats->rx_errors++;
+		goto drop;
+	}
 
-		rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
-			HERMES_RID_CNFDESIREDSSID;
-		
-		err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
-				      NULL, &essidbuf);
-		if (err)
-			goto fail_unlock;
-	} else {
-		*active = 0;
+	length = ntohs(hdr.len);
+	
+	/* Sanity checks */
+	if (length < 3) { /* No for even an 802.2 LLC header */
+		/* At least on Symbol firmware with PCF we get quite a
+                   lot of these legitimately - Poll frames with no
+                   data. */
+		stats->rx_dropped++;
+		goto drop;
+	}
+	if (length > IEEE802_11_DATA_LEN) {
+		printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
+		       dev->name, length);
+		stats->rx_length_errors++;
+		stats->rx_errors++;
+		goto drop;
+	}
 
-		err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
-				      sizeof(essidbuf), NULL, &essidbuf);
-		if (err)
-			goto fail_unlock;
+	/* We need space for the packet data itself, plus an ethernet
+	   header, plus 2 bytes so we can align the IP header on a
+	   32bit boundary, plus 1 byte so we can read in odd length
+	   packets from the card, which has an IO granularity of 16
+	   bits */  
+	skb = dev_alloc_skb(length+ETH_HLEN+2+1);
+	if (!skb) {
+		printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
+		       dev->name);
+		goto drop;
 	}
 
-	len = le16_to_cpu(essidbuf.len);
+	skb_reserve(skb, 2); /* This way the IP header is aligned */
 
-	memset(buf, 0, IW_ESSID_MAX_SIZE+1);
-	memcpy(buf, p, len);
-	buf[len] = '\0';
+	/* Handle decapsulation
+	 * In most cases, the firmware tell us about SNAP frames.
+	 * For some reason, the SNAP frames sent by LinkSys APs
+	 * are not properly recognised by most firmwares.
+	 * So, check ourselves */
+	if (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||
+	    ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||
+	    is_ethersnap(&hdr)) {
+		/* These indicate a SNAP within 802.2 LLC within
+		   802.11 frame which we'll need to de-encapsulate to
+		   the original EthernetII frame. */
 
- fail_unlock:
-	orinoco_unlock(priv, &flags);
+		if (length < ENCAPS_OVERHEAD) { /* No room for full LLC+SNAP */
+			stats->rx_length_errors++;
+			goto drop;
+		}
 
-	return err;       
-}
+		/* Remove SNAP header, reconstruct EthernetII frame */
+		data_len = length - ENCAPS_OVERHEAD;
+		data_off = HERMES_802_3_OFFSET + sizeof(hdr);
 
-static long orinoco_hw_get_freq(struct orinoco_private *priv)
-{
-	
-	hermes_t *hw = &priv->hw;
-	int err = 0;
-	u16 channel;
-	long freq = 0;
-	unsigned long flags;
+		eh = (struct ethhdr *)skb_put(skb, ETH_HLEN);
 
-	err = orinoco_lock(priv, &flags);
-	if (err)
-		return err;
-	
-	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL, &channel);
-	if (err)
-		goto out;
+		memcpy(eh, &hdr, 2 * ETH_ALEN);
+		eh->h_proto = hdr.ethertype;
+	} else {
+		/* All other cases indicate a genuine 802.3 frame.  No
+		   decapsulation needed.  We just throw the whole
+		   thing in, and hope the protocol layer can deal with
+		   it as 802.3 */
+		data_len = length;
+		data_off = HERMES_802_3_OFFSET;
+		/* FIXME: we re-read from the card data we already read here */
+	}
 
-	/* Intersil firmware 1.3.5 returns 0 when the interface is down */
-	if (channel == 0) {
-		err = -EBUSY;
-		goto out;
+	p = skb_put(skb, data_len);
+	err = hermes_bap_pread(hw, IRQ_BAP, p, ALIGN(data_len, 2),
+			       rxfid, data_off);
+	if (err) {
+		printk(KERN_ERR "%s: error %d reading frame. "
+		       "Frame dropped.\n", dev->name, err);
+		stats->rx_errors++;
+		goto drop;
 	}
 
-	if ( (channel < 1) || (channel > NUM_CHANNELS) ) {
-		printk(KERN_WARNING "%s: Channel out of range (%d)!\n",
-		       priv->ndev->name, channel);
-		err = -EBUSY;
-		goto out;
+	dev->last_rx = jiffies;
+	skb->dev = dev;
+	skb->protocol = eth_type_trans(skb, dev);
+	skb->ip_summed = CHECKSUM_NONE;
+	
+	/* Process the wireless stats if needed */
+	orinoco_stat_gather(dev, skb, &desc);
 
-	}
-	freq = channel_frequency[channel-1] * 100000;
+	/* Pass the packet to the networking stack */
+	netif_rx(skb);
+	stats->rx_packets++;
+	stats->rx_bytes += length;
 
- out:
-	orinoco_unlock(priv, &flags);
+	return;
 
-	if (err > 0)
-		err = -EBUSY;
-	return err ? err : freq;
+ drop:	
+	stats->rx_dropped++;
+
+	if (skb)
+		dev_kfree_skb_irq(skb);
+	return;
 }
 
-static int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
-				      int *numrates, s32 *rates, int max)
-{
-	hermes_t *hw = &priv->hw;
-	struct hermes_idstring list;
-	unsigned char *p = (unsigned char *)&list.val;
-	int err = 0;
-	int num;
-	int i;
-	unsigned long flags;
+/********************************************************************/
+/* Rx path (info frames)                                            */
+/********************************************************************/
 
-	err = orinoco_lock(priv, &flags);
-	if (err)
-		return err;
+static void print_linkstatus(struct net_device *dev, u16 status)
+{
+	char * s;
 
-	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
-			      sizeof(list), NULL, &list);
-	orinoco_unlock(priv, &flags);
+	if (suppress_linkstatus)
+		return;
 
-	if (err)
-		return err;
+	switch (status) {
+	case HERMES_LINKSTATUS_NOT_CONNECTED:
+		s = "Not Connected";
+		break;
+	case HERMES_LINKSTATUS_CONNECTED:
+		s = "Connected";
+		break;
+	case HERMES_LINKSTATUS_DISCONNECTED:
+		s = "Disconnected";
+		break;
+	case HERMES_LINKSTATUS_AP_CHANGE:
+		s = "AP Changed";
+		break;
+	case HERMES_LINKSTATUS_AP_OUT_OF_RANGE:
+		s = "AP Out of Range";
+		break;
+	case HERMES_LINKSTATUS_AP_IN_RANGE:
+		s = "AP In Range";
+		break;
+	case HERMES_LINKSTATUS_ASSOC_FAILED:
+		s = "Association Failed";
+		break;
+	default:
+		s = "UNKNOWN";
+	}
 	
-	num = le16_to_cpu(list.len);
-	*numrates = num;
-	num = min(num, max);
-
-	for (i = 0; i < num; i++) {
-		rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
-	}
-
-	return 0;
-}
-
-#if 0
-static void show_rx_frame(struct orinoco_rxframe_hdr *frame)
-{
-	printk(KERN_DEBUG "RX descriptor:\n");
-	printk(KERN_DEBUG "  status      = 0x%04x\n", frame->desc.status);
-	printk(KERN_DEBUG "  time        = 0x%08x\n", frame->desc.time);
-	printk(KERN_DEBUG "  silence     = 0x%02x\n", frame->desc.silence);
-	printk(KERN_DEBUG "  signal      = 0x%02x\n", frame->desc.signal);
-	printk(KERN_DEBUG "  rate        = 0x%02x\n", frame->desc.rate);
-	printk(KERN_DEBUG "  rxflow      = 0x%02x\n", frame->desc.rxflow);
-	printk(KERN_DEBUG "  reserved    = 0x%08x\n", frame->desc.reserved);
-
-	printk(KERN_DEBUG "IEEE 802.11 header:\n");
-	printk(KERN_DEBUG "  frame_ctl   = 0x%04x\n",
-	       frame->p80211.frame_ctl);
-	printk(KERN_DEBUG "  duration_id = 0x%04x\n",
-	       frame->p80211.duration_id);
-	printk(KERN_DEBUG "  addr1       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p80211.addr1[0], frame->p80211.addr1[1],
-	       frame->p80211.addr1[2], frame->p80211.addr1[3],
-	       frame->p80211.addr1[4], frame->p80211.addr1[5]);
-	printk(KERN_DEBUG "  addr2       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p80211.addr2[0], frame->p80211.addr2[1],
-	       frame->p80211.addr2[2], frame->p80211.addr2[3],
-	       frame->p80211.addr2[4], frame->p80211.addr2[5]);
-	printk(KERN_DEBUG "  addr3       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p80211.addr3[0], frame->p80211.addr3[1],
-	       frame->p80211.addr3[2], frame->p80211.addr3[3],
-	       frame->p80211.addr3[4], frame->p80211.addr3[5]);
-	printk(KERN_DEBUG "  seq_ctl     = 0x%04x\n",
-	       frame->p80211.seq_ctl);
-	printk(KERN_DEBUG "  addr4       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p80211.addr4[0], frame->p80211.addr4[1],
-	       frame->p80211.addr4[2], frame->p80211.addr4[3],
-	       frame->p80211.addr4[4], frame->p80211.addr4[5]);
-	printk(KERN_DEBUG "  data_len    = 0x%04x\n",
-	       frame->p80211.data_len);
-
-	printk(KERN_DEBUG "IEEE 802.3 header:\n");
-	printk(KERN_DEBUG "  dest        = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p8023.h_dest[0], frame->p8023.h_dest[1],
-	       frame->p8023.h_dest[2], frame->p8023.h_dest[3],
-	       frame->p8023.h_dest[4], frame->p8023.h_dest[5]);
-	printk(KERN_DEBUG "  src         = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p8023.h_source[0], frame->p8023.h_source[1],
-	       frame->p8023.h_source[2], frame->p8023.h_source[3],
-	       frame->p8023.h_source[4], frame->p8023.h_source[5]);
-	printk(KERN_DEBUG "  len         = 0x%04x\n", frame->p8023.h_proto);
-
-	printk(KERN_DEBUG "IEEE 802.2 LLC/SNAP header:\n");
-	printk(KERN_DEBUG "  DSAP        = 0x%02x\n", frame->p8022.dsap);
-	printk(KERN_DEBUG "  SSAP        = 0x%02x\n", frame->p8022.ssap);
-	printk(KERN_DEBUG "  ctrl        = 0x%02x\n", frame->p8022.ctrl);
-	printk(KERN_DEBUG "  OUI         = %02x:%02x:%02x\n",
-	       frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]);
-	printk(KERN_DEBUG "  ethertype  = 0x%04x\n", frame->ethertype);
-}
-#endif /* 0 */
-
-/*
- * Interrupt handler
- */
-irqreturn_t orinoco_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct net_device *dev = (struct net_device *)dev_id;
-	struct orinoco_private *priv = netdev_priv(dev);
-	hermes_t *hw = &priv->hw;
-	int count = MAX_IRQLOOPS_PER_IRQ;
-	u16 evstat, events;
-	/* These are used to detect a runaway interrupt situation */
-	/* If we get more than MAX_IRQLOOPS_PER_JIFFY iterations in a jiffy,
-	 * we panic and shut down the hardware */
-	static int last_irq_jiffy = 0; /* jiffies value the last time we were called */
-	static int loops_this_jiffy = 0;
-	unsigned long flags;
-
-	if (orinoco_lock(priv, &flags) != 0) {
-		/* If hw is unavailable - we don't know if the irq was
-		 * for us or not */
-		return IRQ_HANDLED;
-	}
-
-	evstat = hermes_read_regn(hw, EVSTAT);
-	events = evstat & hw->inten;
-	if (! events) {
-		orinoco_unlock(priv, &flags);
-		return IRQ_NONE;
-	}
-	
-	if (jiffies != last_irq_jiffy)
-		loops_this_jiffy = 0;
-	last_irq_jiffy = jiffies;
-
-	while (events && count--) {
-		if (++loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY) {
-			printk(KERN_WARNING "%s: IRQ handler is looping too "
-			       "much! Resetting.\n", dev->name);
-			/* Disable interrupts for now */
-			hermes_set_irqmask(hw, 0);
-			schedule_work(&priv->reset_work);
-			break;
-		}
-
-		/* Check the card hasn't been removed */
-		if (! hermes_present(hw)) {
-			DEBUG(0, "orinoco_interrupt(): card removed\n");
-			break;
-		}
-
-		if (events & HERMES_EV_TICK)
-			__orinoco_ev_tick(dev, hw);
-		if (events & HERMES_EV_WTERR)
-			__orinoco_ev_wterr(dev, hw);
-		if (events & HERMES_EV_INFDROP)
-			__orinoco_ev_infdrop(dev, hw);
-		if (events & HERMES_EV_INFO)
-			__orinoco_ev_info(dev, hw);
-		if (events & HERMES_EV_RX)
-			__orinoco_ev_rx(dev, hw);
-		if (events & HERMES_EV_TXEXC)
-			__orinoco_ev_txexc(dev, hw);
-		if (events & HERMES_EV_TX)
-			__orinoco_ev_tx(dev, hw);
-		if (events & HERMES_EV_ALLOC)
-			__orinoco_ev_alloc(dev, hw);
-		
-		hermes_write_regn(hw, EVACK, events);
-
-		evstat = hermes_read_regn(hw, EVSTAT);
-		events = evstat & hw->inten;
-	};
-
-	orinoco_unlock(priv, &flags);
-	return IRQ_HANDLED;
-}
-
-static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw)
-{
-	printk(KERN_DEBUG "%s: TICK\n", dev->name);
-}
-
-static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw)
-{
-	/* This seems to happen a fair bit under load, but ignoring it
-	   seems to work fine...*/
-	printk(KERN_DEBUG "%s: MAC controller error (WTERR). Ignoring.\n",
-	       dev->name);
-}
-
-static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
-{
-	if (net_ratelimit())
-		printk(KERN_WARNING "%s: Information frame lost.\n", dev->name);
-}
-
-static void print_linkstatus(struct net_device *dev, u16 status)
-{
-	char * s;
-
-	if (suppress_linkstatus)
-		return;
-
-	switch (status) {
-	case HERMES_LINKSTATUS_NOT_CONNECTED:
-		s = "Not Connected";
-		break;
-	case HERMES_LINKSTATUS_CONNECTED:
-		s = "Connected";
-		break;
-	case HERMES_LINKSTATUS_DISCONNECTED:
-		s = "Disconnected";
-		break;
-	case HERMES_LINKSTATUS_AP_CHANGE:
-		s = "AP Changed";
-		break;
-	case HERMES_LINKSTATUS_AP_OUT_OF_RANGE:
-		s = "AP Out of Range";
-		break;
-	case HERMES_LINKSTATUS_AP_IN_RANGE:
-		s = "AP In Range";
-		break;
-	case HERMES_LINKSTATUS_ASSOC_FAILED:
-		s = "Association Failed";
-		break;
-	default:
-		s = "UNKNOWN";
-	}
-	
-	printk(KERN_INFO "%s: New link status: %s (%04x)\n",
-	       dev->name, s, status);
-}
+	printk(KERN_INFO "%s: New link status: %s (%04x)\n",
+	       dev->name, s, status);
+}
 
 static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
 {
@@ -1614,19 +1261,17 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
 				le16_to_cpu(tallies.RxDiscards_WEPExcluded);
 		wstats->discard.misc +=
 			le16_to_cpu(tallies.TxDiscardsWrongSA);
-#if WIRELESS_EXT > 11
 		wstats->discard.fragment +=
 			le16_to_cpu(tallies.RxMsgInBadMsgFragments);
 		wstats->discard.retries +=
 			le16_to_cpu(tallies.TxRetryLimitExceeded);
 		/* wstats->miss.beacon - no match */
-#endif /* WIRELESS_EXT > 11 */
 	}
 	break;
 	case HERMES_INQ_LINKSTATUS: {
 		struct hermes_linkstatus linkstatus;
 		u16 newstatus;
-		
+
 		if (len != sizeof(linkstatus)) {
 			printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n",
 			       dev->name, len);
@@ -1654,219 +1299,726 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
 	}
 	break;
 	default:
-		printk(KERN_DEBUG "%s: Unknown information frame received (type %04x).\n",
-		      dev->name, type);
+		printk(KERN_DEBUG "%s: Unknown information frame received "
+		       "(type %04x).\n", dev->name, type);
 		/* We don't actually do anything about it */
 		break;
 	}
 }
 
-static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
+static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
+{
+	if (net_ratelimit())
+		printk(KERN_WARNING "%s: Information frame lost.\n", dev->name);
+}
+
+/********************************************************************/
+/* Internal hardware control routines                               */
+/********************************************************************/
+
+int __orinoco_up(struct net_device *dev)
 {
 	struct orinoco_private *priv = netdev_priv(dev);
-	struct net_device_stats *stats = &priv->stats;
-	struct iw_statistics *wstats = &priv->wstats;
-	struct sk_buff *skb = NULL;
-	u16 rxfid, status;
-	int length, data_len, data_off;
-	char *p;
-	struct hermes_rx_descriptor desc;
-	struct header_struct hdr;
-	struct ethhdr *eh;
+	struct hermes *hw = &priv->hw;
 	int err;
 
-	rxfid = hermes_read_regn(hw, RXFID);
-
-	err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc),
-			       rxfid, 0);
+	err = __orinoco_program_rids(dev);
 	if (err) {
-		printk(KERN_ERR "%s: error %d reading Rx descriptor. "
-		       "Frame dropped.\n", dev->name, err);
-		stats->rx_errors++;
-		goto drop;
+		printk(KERN_ERR "%s: Error %d configuring card\n",
+		       dev->name, err);
+		return err;
 	}
 
-	status = le16_to_cpu(desc.status);
-	
-	if (status & HERMES_RXSTAT_ERR) {
-		if (status & HERMES_RXSTAT_UNDECRYPTABLE) {
-			wstats->discard.code++;
-			DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n",
-			       dev->name);
-		} else {
-			stats->rx_crc_errors++;
-			DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name);
-		}
-		stats->rx_errors++;
-		goto drop;
+	/* Fire things up again */
+	hermes_set_irqmask(hw, ORINOCO_INTEN);
+	err = hermes_enable_port(hw, 0);
+	if (err) {
+		printk(KERN_ERR "%s: Error %d enabling MAC port\n",
+		       dev->name, err);
+		return err;
 	}
 
-	/* For now we ignore the 802.11 header completely, assuming
-           that the card's firmware has handled anything vital */
+	netif_start_queue(dev);
 
-	err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr),
-			       rxfid, HERMES_802_3_OFFSET);
+	return 0;
+}
+
+int __orinoco_down(struct net_device *dev)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	struct hermes *hw = &priv->hw;
+	int err;
+
+	netif_stop_queue(dev);
+
+	if (! priv->hw_unavailable) {
+		if (! priv->broken_disableport) {
+			err = hermes_disable_port(hw, 0);
+			if (err) {
+				/* Some firmwares (e.g. Intersil 1.3.x) seem
+				 * to have problems disabling the port, oh
+				 * well, too bad. */
+				printk(KERN_WARNING "%s: Error %d disabling MAC port\n",
+				       dev->name, err);
+				priv->broken_disableport = 1;
+			}
+		}
+		hermes_set_irqmask(hw, 0);
+		hermes_write_regn(hw, EVACK, 0xffff);
+	}
+	
+	/* firmware will have to reassociate */
+	priv->last_linkstatus = 0xffff;
+	priv->connected = 0;
+
+	return 0;
+}
+
+int orinoco_reinit_firmware(struct net_device *dev)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	struct hermes *hw = &priv->hw;
+	int err;
+
+	err = hermes_init(hw);
+	if (err)
+		return err;
+
+	err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
+	if (err == -EIO) {
+		/* Try workaround for old Symbol firmware bug */
+		printk(KERN_WARNING "%s: firmware ALLOC bug detected "
+		       "(old Symbol firmware?). Trying to work around... ",
+		       dev->name);
+		
+		priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
+		err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
+		if (err)
+			printk("failed!\n");
+		else
+			printk("ok.\n");
+	}
+
+	return err;
+}
+
+static int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
+{
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+
+	if (priv->bitratemode >= BITRATE_TABLE_SIZE) {
+		printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n",
+		       priv->ndev->name, priv->bitratemode);
+		return -EINVAL;
+	}
+
+	switch (priv->firmware_type) {
+	case FIRMWARE_TYPE_AGERE:
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFTXRATECONTROL,
+					   bitrate_table[priv->bitratemode].agere_txratectrl);
+		break;
+	case FIRMWARE_TYPE_INTERSIL:
+	case FIRMWARE_TYPE_SYMBOL:
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFTXRATECONTROL,
+					   bitrate_table[priv->bitratemode].intersil_txratectrl);
+		break;
+	default:
+		BUG();
+	}
+
+	return err;
+}
+
+static int __orinoco_hw_setup_wep(struct orinoco_private *priv)
+{
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+	int	master_wep_flag;
+	int	auth_flag;
+
+	switch (priv->firmware_type) {
+	case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
+		if (priv->wep_on) {
+			err = hermes_write_wordrec(hw, USER_BAP,
+						   HERMES_RID_CNFTXKEY_AGERE,
+						   priv->tx_key);
+			if (err)
+				return err;
+			
+			err = HERMES_WRITE_RECORD(hw, USER_BAP,
+						  HERMES_RID_CNFWEPKEYS_AGERE,
+						  &priv->keys);
+			if (err)
+				return err;
+		}
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFWEPENABLED_AGERE,
+					   priv->wep_on);
+		if (err)
+			return err;
+		break;
+
+	case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
+	case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
+		master_wep_flag = 0;		/* Off */
+		if (priv->wep_on) {
+			int keylen;
+			int i;
+
+			/* Fudge around firmware weirdness */
+			keylen = le16_to_cpu(priv->keys[priv->tx_key].len);
+			
+			/* Write all 4 keys */
+			for(i = 0; i < ORINOCO_MAX_KEYS; i++) {
+/*  				int keylen = le16_to_cpu(priv->keys[i].len); */
+				
+				if (keylen > LARGE_KEY_SIZE) {
+					printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
+					       priv->ndev->name, i, keylen);
+					return -E2BIG;
+				}
+
+				err = hermes_write_ltv(hw, USER_BAP,
+						       HERMES_RID_CNFDEFAULTKEY0 + i,
+						       HERMES_BYTES_TO_RECLEN(keylen),
+						       priv->keys[i].data);
+				if (err)
+					return err;
+			}
+
+			/* Write the index of the key used in transmission */
+			err = hermes_write_wordrec(hw, USER_BAP,
+						   HERMES_RID_CNFWEPDEFAULTKEYID,
+						   priv->tx_key);
+			if (err)
+				return err;
+			
+			if (priv->wep_restrict) {
+				auth_flag = 2;
+				master_wep_flag = 3;
+			} else {
+				/* Authentication is where Intersil and Symbol
+				 * firmware differ... */
+				auth_flag = 1;
+				if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)
+					master_wep_flag = 3; /* Symbol */ 
+				else 
+					master_wep_flag = 1; /* Intersil */
+			}
+
+
+			err = hermes_write_wordrec(hw, USER_BAP,
+						   HERMES_RID_CNFAUTHENTICATION,
+						   auth_flag);
+			if (err)
+				return err;
+		}
+
+		/* Master WEP setting : on/off */
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFWEPFLAGS_INTERSIL,
+					   master_wep_flag);
+		if (err)
+			return err;	
+
+		break;
+
+	default:
+		if (priv->wep_on) {
+			printk(KERN_ERR "%s: WEP enabled, although not supported!\n",
+			       priv->ndev->name);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int __orinoco_program_rids(struct net_device *dev)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	hermes_t *hw = &priv->hw;
+	int err;
+	struct hermes_idstring idbuf;
+
+	/* Set the MAC address */
+	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
+			       HERMES_BYTES_TO_RECLEN(ETH_ALEN), dev->dev_addr);
 	if (err) {
-		printk(KERN_ERR "%s: error %d reading frame header. "
-		       "Frame dropped.\n", dev->name, err);
-		stats->rx_errors++;
-		goto drop;
+		printk(KERN_ERR "%s: Error %d setting MAC address\n",
+		       dev->name, err);
+		return err;
 	}
 
-	length = ntohs(hdr.len);
-	
-	/* Sanity checks */
-	if (length < 3) { /* No for even an 802.2 LLC header */
-		/* At least on Symbol firmware with PCF we get quite a
-                   lot of these legitimately - Poll frames with no
-                   data. */
-		stats->rx_dropped++;
-		goto drop;
+	/* Set up the link mode */
+	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE,
+				   priv->port_type);
+	if (err) {
+		printk(KERN_ERR "%s: Error %d setting port type\n",
+		       dev->name, err);
+		return err;
 	}
-	if (length > IEEE802_11_DATA_LEN) {
-		printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
-		       dev->name, length);
-		stats->rx_length_errors++;
-		stats->rx_errors++;
-		goto drop;
+	/* Set the channel/frequency */
+	if (priv->channel == 0) {
+		printk(KERN_DEBUG "%s: Channel is 0 in __orinoco_program_rids()\n", dev->name);
+		if (priv->createibss)
+			priv->channel = 10;
+	}
+	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFOWNCHANNEL,
+				   priv->channel);
+	if (err) {
+		printk(KERN_ERR "%s: Error %d setting channel\n",
+		       dev->name, err);
+		return err;
+	}
+
+	if (priv->has_ibss) {
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFCREATEIBSS,
+					   priv->createibss);
+		if (err) {
+			printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n", dev->name, err);
+			return err;
+		}
+
+		if ((strlen(priv->desired_essid) == 0) && (priv->createibss)
+		   && (!priv->has_ibss_any)) {
+			printk(KERN_WARNING "%s: This firmware requires an "
+			       "ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
+			/* With wvlan_cs, in this case, we would crash.
+			 * hopefully, this driver will behave better...
+			 * Jean II */
+		}
+	}
+
+	/* Set the desired ESSID */
+	idbuf.len = cpu_to_le16(strlen(priv->desired_essid));
+	memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
+	/* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */
+	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
+			       HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
+			       &idbuf);
+	if (err) {
+		printk(KERN_ERR "%s: Error %d setting OWNSSID\n",
+		       dev->name, err);
+		return err;
+	}
+	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
+			       HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
+			       &idbuf);
+	if (err) {
+		printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n",
+		       dev->name, err);
+		return err;
+	}
+
+	/* Set the station name */
+	idbuf.len = cpu_to_le16(strlen(priv->nick));
+	memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
+	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
+			       HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
+			       &idbuf);
+	if (err) {
+		printk(KERN_ERR "%s: Error %d setting nickname\n",
+		       dev->name, err);
+		return err;
+	}
+
+	/* Set AP density */
+	if (priv->has_sensitivity) {
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFSYSTEMSCALE,
+					   priv->ap_density);
+		if (err) {
+			printk(KERN_WARNING "%s: Error %d setting SYSTEMSCALE.  "
+			       "Disabling sensitivity control\n",
+			       dev->name, err);
+
+			priv->has_sensitivity = 0;
+		}
+	}
+
+	/* Set RTS threshold */
+	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
+				   priv->rts_thresh);
+	if (err) {
+		printk(KERN_ERR "%s: Error %d setting RTS threshold\n",
+		       dev->name, err);
+		return err;
+	}
+
+	/* Set fragmentation threshold or MWO robustness */
+	if (priv->has_mwo)
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFMWOROBUST_AGERE,
+					   priv->mwo_robust);
+	else
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
+					   priv->frag_thresh);
+	if (err) {
+		printk(KERN_ERR "%s: Error %d setting fragmentation\n",
+		       dev->name, err);
+		return err;
+	}
+
+	/* Set bitrate */
+	err = __orinoco_hw_set_bitrate(priv);
+	if (err) {
+		printk(KERN_ERR "%s: Error %d setting bitrate\n",
+		       dev->name, err);
+		return err;
+	}
+
+	/* Set power management */
+	if (priv->has_pm) {
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFPMENABLED,
+					   priv->pm_on);
+		if (err) {
+			printk(KERN_ERR "%s: Error %d setting up PM\n",
+			       dev->name, err);
+			return err;
+		}
+
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFMULTICASTRECEIVE,
+					   priv->pm_mcast);
+		if (err) {
+			printk(KERN_ERR "%s: Error %d setting up PM\n",
+			       dev->name, err);
+			return err;
+		}
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFMAXSLEEPDURATION,
+					   priv->pm_period);
+		if (err) {
+			printk(KERN_ERR "%s: Error %d setting up PM\n",
+			       dev->name, err);
+			return err;
+		}
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFPMHOLDOVERDURATION,
+					   priv->pm_timeout);
+		if (err) {
+			printk(KERN_ERR "%s: Error %d setting up PM\n",
+			       dev->name, err);
+			return err;
+		}
+	}
+
+	/* Set preamble - only for Symbol so far... */
+	if (priv->has_preamble) {
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFPREAMBLE_SYMBOL,
+					   priv->preamble);
+		if (err) {
+			printk(KERN_ERR "%s: Error %d setting preamble\n",
+			       dev->name, err);
+			return err;
+		}
+	}
+
+	/* Set up encryption */
+	if (priv->has_wep) {
+		err = __orinoco_hw_setup_wep(priv);
+		if (err) {
+			printk(KERN_ERR "%s: Error %d activating WEP\n",
+			       dev->name, err);
+			return err;
+		}
+	}
+
+	/* Set promiscuity / multicast*/
+	priv->promiscuous = 0;
+	priv->mc_count = 0;
+	__orinoco_set_multicast_list(dev); /* FIXME: what about the xmit_lock */
+
+	return 0;
+}
+
+/* FIXME: return int? */
+static void
+__orinoco_set_multicast_list(struct net_device *dev)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+	int promisc, mc_count;
+
+	/* The Hermes doesn't seem to have an allmulti mode, so we go
+	 * into promiscuous mode and let the upper levels deal. */
+	if ( (dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) ||
+	     (dev->mc_count > MAX_MULTICAST(priv)) ) {
+		promisc = 1;
+		mc_count = 0;
+	} else {
+		promisc = 0;
+		mc_count = dev->mc_count;
+	}
+
+	if (promisc != priv->promiscuous) {
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFPROMISCUOUSMODE,
+					   promisc);
+		if (err) {
+			printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n",
+			       dev->name, err);
+		} else 
+			priv->promiscuous = promisc;
+	}
+
+	if (! promisc && (mc_count || priv->mc_count) ) {
+		struct dev_mc_list *p = dev->mc_list;
+		struct hermes_multicast mclist;
+		int i;
+
+		for (i = 0; i < mc_count; i++) {
+			/* paranoia: is list shorter than mc_count? */
+			BUG_ON(! p);
+			/* paranoia: bad address size in list? */
+			BUG_ON(p->dmi_addrlen != ETH_ALEN);
+			
+			memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN);
+			p = p->next;
+		}
+		
+		if (p)
+			printk(KERN_WARNING "Multicast list is longer than mc_count\n");
+
+		err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFGROUPADDRESSES,
+				       HERMES_BYTES_TO_RECLEN(priv->mc_count * ETH_ALEN),
+				       &mclist);
+		if (err)
+			printk(KERN_ERR "%s: Error %d setting multicast list.\n",
+			       dev->name, err);
+		else
+			priv->mc_count = mc_count;
+	}
+
+	/* Since we can set the promiscuous flag when it wasn't asked
+	   for, make sure the net_device knows about it. */
+	if (priv->promiscuous)
+		dev->flags |= IFF_PROMISC;
+	else
+		dev->flags &= ~IFF_PROMISC;
+}
+
+static int orinoco_reconfigure(struct net_device *dev)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	struct hermes *hw = &priv->hw;
+	unsigned long flags;
+	int err = 0;
+
+	if (priv->broken_disableport) {
+		schedule_work(&priv->reset_work);
+		return 0;
+	}
+
+	err = orinoco_lock(priv, &flags);
+	if (err)
+		return err;
+
+		
+	err = hermes_disable_port(hw, 0);
+	if (err) {
+		printk(KERN_WARNING "%s: Unable to disable port while reconfiguring card\n",
+		       dev->name);
+		priv->broken_disableport = 1;
+		goto out;
 	}
 
-	/* We need space for the packet data itself, plus an ethernet
-	   header, plus 2 bytes so we can align the IP header on a
-	   32bit boundary, plus 1 byte so we can read in odd length
-	   packets from the card, which has an IO granularity of 16
-	   bits */  
-	skb = dev_alloc_skb(length+ETH_HLEN+2+1);
-	if (!skb) {
-		printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
+	err = __orinoco_program_rids(dev);
+	if (err) {
+		printk(KERN_WARNING "%s: Unable to reconfigure card\n",
 		       dev->name);
-		goto drop;
+		goto out;
 	}
 
-	skb_reserve(skb, 2); /* This way the IP header is aligned */
+	err = hermes_enable_port(hw, 0);
+	if (err) {
+		printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",
+		       dev->name);
+		goto out;
+	}
 
-	/* Handle decapsulation
-	 * In most cases, the firmware tell us about SNAP frames.
-	 * For some reason, the SNAP frames sent by LinkSys APs
-	 * are not properly recognised by most firmwares.
-	 * So, check ourselves */
-	if(((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||
-	   ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||
-	   is_ethersnap(&hdr)) {
-		/* These indicate a SNAP within 802.2 LLC within
-		   802.11 frame which we'll need to de-encapsulate to
-		   the original EthernetII frame. */
+ out:
+	if (err) {
+		printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);
+		schedule_work(&priv->reset_work);
+		err = 0;
+	}
 
-		if (length < ENCAPS_OVERHEAD) { /* No room for full LLC+SNAP */
-			stats->rx_length_errors++;
-			goto drop;
-		}
+	orinoco_unlock(priv, &flags);
+	return err;
 
-		/* Remove SNAP header, reconstruct EthernetII frame */
-		data_len = length - ENCAPS_OVERHEAD;
-		data_off = HERMES_802_3_OFFSET + sizeof(hdr);
+}
 
-		eh = (struct ethhdr *)skb_put(skb, ETH_HLEN);
+/* This must be called from user context, without locks held - use
+ * schedule_work() */
+static void orinoco_reset(struct net_device *dev)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	struct hermes *hw = &priv->hw;
+	int err;
+	unsigned long flags;
 
-		memcpy(eh, &hdr, 2 * ETH_ALEN);
-		eh->h_proto = hdr.ethertype;
-	} else {
-		/* All other cases indicate a genuine 802.3 frame.  No
-		   decapsulation needed.  We just throw the whole
-		   thing in, and hope the protocol layer can deal with
-		   it as 802.3 */
-		data_len = length;
-		data_off = HERMES_802_3_OFFSET;
-		/* FIXME: we re-read from the card data we already read here */
+	err = orinoco_lock(priv, &flags);
+	if (err)
+		/* When the hardware becomes available again, whatever
+		 * detects that is responsible for re-initializing
+		 * it. So no need for anything further */
+		return;
+
+	netif_stop_queue(dev);
+
+	/* Shut off interrupts.  Depending on what state the hardware
+	 * is in, this might not work, but we'll try anyway */
+	hermes_set_irqmask(hw, 0);
+	hermes_write_regn(hw, EVACK, 0xffff);
+
+	priv->hw_unavailable++;
+	priv->last_linkstatus = 0xffff; /* firmware will have to reassociate */
+	priv->connected = 0;
+
+	orinoco_unlock(priv, &flags);
+
+	if (priv->hard_reset)
+		err = (*priv->hard_reset)(priv);
+	if (err) {
+		printk(KERN_ERR "%s: orinoco_reset: Error %d "
+		       "performing  hard reset\n", dev->name, err);
+		/* FIXME: shutdown of some sort */
+		return;
 	}
 
-	p = skb_put(skb, data_len);
-	err = hermes_bap_pread(hw, IRQ_BAP, p, RUP_EVEN(data_len),
-			       rxfid, data_off);
+	err = orinoco_reinit_firmware(dev);
 	if (err) {
-		printk(KERN_ERR "%s: error %d reading frame. "
-		       "Frame dropped.\n", dev->name, err);
-		stats->rx_errors++;
-		goto drop;
+		printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n",
+		       dev->name, err);
+		return;
 	}
 
-	dev->last_rx = jiffies;
-	skb->dev = dev;
-	skb->protocol = eth_type_trans(skb, dev);
-	skb->ip_summed = CHECKSUM_NONE;
-	
-	/* Process the wireless stats if needed */
-	orinoco_stat_gather(dev, skb, &desc);
+	spin_lock_irq(&priv->lock); /* This has to be called from user context */
 
-	/* Pass the packet to the networking stack */
-	netif_rx(skb);
-	stats->rx_packets++;
-	stats->rx_bytes += length;
+	priv->hw_unavailable--;
 
-	return;
+	/* priv->open or priv->hw_unavailable might have changed while
+	 * we dropped the lock */
+	if (priv->open && (! priv->hw_unavailable)) {
+		err = __orinoco_up(dev);
+		if (err) {
+			printk(KERN_ERR "%s: orinoco_reset: Error %d reenabling card\n",
+			       dev->name, err);
+		} else
+			dev->trans_start = jiffies;
+	}
 
- drop:	
-	stats->rx_dropped++;
+	spin_unlock_irq(&priv->lock);
 
-	if (skb)
-		dev_kfree_skb_irq(skb);
 	return;
 }
 
-static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
-{
-	struct orinoco_private *priv = netdev_priv(dev);
-	struct net_device_stats *stats = &priv->stats;
-	u16 fid = hermes_read_regn(hw, TXCOMPLFID);
-	struct hermes_tx_descriptor desc;
-	int err = 0;
-
-	if (fid == DUMMY_FID)
-		return; /* Nothing's really happened */
-
-	err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc), fid, 0);
-	if (err) {
-		printk(KERN_WARNING "%s: Unable to read descriptor on Tx error "
-		       "(FID=%04X error %d)\n",
-		       dev->name, fid, err);
-	} else {
-		DEBUG(1, "%s: Tx error, status %d\n",
-		      dev->name, le16_to_cpu(desc.status));
-	}
-	
-	stats->tx_errors++;
+/********************************************************************/
+/* Interrupt handler                                                */
+/********************************************************************/
 
-	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
+static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw)
+{
+	printk(KERN_DEBUG "%s: TICK\n", dev->name);
 }
 
-static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw)
+static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw)
 {
-	struct orinoco_private *priv = netdev_priv(dev);
-	struct net_device_stats *stats = &priv->stats;
-
-	stats->tx_packets++;
-
-	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
+	/* This seems to happen a fair bit under load, but ignoring it
+	   seems to work fine...*/
+	printk(KERN_DEBUG "%s: MAC controller error (WTERR). Ignoring.\n",
+	       dev->name);
 }
 
-static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
+irqreturn_t orinoco_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
+	struct net_device *dev = (struct net_device *)dev_id;
 	struct orinoco_private *priv = netdev_priv(dev);
+	hermes_t *hw = &priv->hw;
+	int count = MAX_IRQLOOPS_PER_IRQ;
+	u16 evstat, events;
+	/* These are used to detect a runaway interrupt situation */
+	/* If we get more than MAX_IRQLOOPS_PER_JIFFY iterations in a jiffy,
+	 * we panic and shut down the hardware */
+	static int last_irq_jiffy = 0; /* jiffies value the last time
+					* we were called */
+	static int loops_this_jiffy = 0;
+	unsigned long flags;
 
-	u16 fid = hermes_read_regn(hw, ALLOCFID);
+	if (orinoco_lock(priv, &flags) != 0) {
+		/* If hw is unavailable - we don't know if the irq was
+		 * for us or not */
+		return IRQ_HANDLED;
+	}
 
-	if (fid != priv->txfid) {
-		if (fid != DUMMY_FID)
-			printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n",
-			       dev->name, fid);
-		return;
-	} else {
-		netif_wake_queue(dev);
+	evstat = hermes_read_regn(hw, EVSTAT);
+	events = evstat & hw->inten;
+	if (! events) {
+		orinoco_unlock(priv, &flags);
+		return IRQ_NONE;
 	}
+	
+	if (jiffies != last_irq_jiffy)
+		loops_this_jiffy = 0;
+	last_irq_jiffy = jiffies;
 
-	hermes_write_regn(hw, ALLOCFID, DUMMY_FID);
+	while (events && count--) {
+		if (++loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY) {
+			printk(KERN_WARNING "%s: IRQ handler is looping too "
+			       "much! Resetting.\n", dev->name);
+			/* Disable interrupts for now */
+			hermes_set_irqmask(hw, 0);
+			schedule_work(&priv->reset_work);
+			break;
+		}
+
+		/* Check the card hasn't been removed */
+		if (! hermes_present(hw)) {
+			DEBUG(0, "orinoco_interrupt(): card removed\n");
+			break;
+		}
+
+		if (events & HERMES_EV_TICK)
+			__orinoco_ev_tick(dev, hw);
+		if (events & HERMES_EV_WTERR)
+			__orinoco_ev_wterr(dev, hw);
+		if (events & HERMES_EV_INFDROP)
+			__orinoco_ev_infdrop(dev, hw);
+		if (events & HERMES_EV_INFO)
+			__orinoco_ev_info(dev, hw);
+		if (events & HERMES_EV_RX)
+			__orinoco_ev_rx(dev, hw);
+		if (events & HERMES_EV_TXEXC)
+			__orinoco_ev_txexc(dev, hw);
+		if (events & HERMES_EV_TX)
+			__orinoco_ev_tx(dev, hw);
+		if (events & HERMES_EV_ALLOC)
+			__orinoco_ev_alloc(dev, hw);
+		
+		hermes_write_regn(hw, EVACK, events);
+
+		evstat = hermes_read_regn(hw, EVSTAT);
+		events = evstat & hw->inten;
+	};
+
+	orinoco_unlock(priv, &flags);
+	return IRQ_HANDLED;
 }
 
+/********************************************************************/
+/* Initialization                                                   */
+/********************************************************************/
+
 struct sta_id {
 	u16 id, variant, major, minor;
 } __attribute__ ((packed));
@@ -1901,11 +2053,11 @@ static void determine_firmware(struct net_device *dev)
 		       dev->name, err);
 		memset(&sta_id, 0, sizeof(sta_id));
 	}
+
 	le16_to_cpus(&sta_id.id);
 	le16_to_cpus(&sta_id.variant);
 	le16_to_cpus(&sta_id.major);
 	le16_to_cpus(&sta_id.minor);
-
 	printk(KERN_DEBUG "%s: Station identity %04x:%04x:%04x:%04x\n",
 	       dev->name, sta_id.id, sta_id.variant,
 	       sta_id.major, sta_id.minor);
@@ -2018,12 +2170,7 @@ static void determine_firmware(struct net_device *dev)
 	}
 }
 
-/*
- * struct net_device methods
- */
-
-static int
-orinoco_init(struct net_device *dev)
+static int orinoco_init(struct net_device *dev)
 {
 	struct orinoco_private *priv = netdev_priv(dev);
 	hermes_t *hw = &priv->hw;
@@ -2112,7 +2259,8 @@ orinoco_init(struct net_device *dev)
 	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
 				  &priv->rts_thresh);
 	if (err) {
-		printk(KERN_ERR "%s: failed to read RTS threshold!\n", dev->name);
+		printk(KERN_ERR "%s: failed to read RTS threshold!\n",
+		       dev->name);
 		goto out;
 	}
 
@@ -2125,7 +2273,8 @@ orinoco_init(struct net_device *dev)
 		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
 					  &priv->frag_thresh);
 	if (err) {
-		printk(KERN_ERR "%s: failed to read fragmentation settings!\n", dev->name);
+		printk(KERN_ERR "%s: failed to read fragmentation settings!\n",
+		       dev->name);
 		goto out;
 	}
 
@@ -2153,7 +2302,8 @@ orinoco_init(struct net_device *dev)
 
 	/* Preamble setup */
 	if (priv->has_preamble) {
-		err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFPREAMBLE_SYMBOL,
+		err = hermes_read_wordrec(hw, USER_BAP,
+					  HERMES_RID_CNFPREAMBLE_SYMBOL,
 					  &priv->preamble);
 		if (err)
 			goto out;
@@ -2202,357 +2352,204 @@ orinoco_init(struct net_device *dev)
 	return err;
 }
 
-struct net_device_stats *
-orinoco_get_stats(struct net_device *dev)
-{
-	struct orinoco_private *priv = netdev_priv(dev);
-	
-	return &priv->stats;
-}
-
-struct iw_statistics *
-orinoco_get_wireless_stats(struct net_device *dev)
+struct net_device *alloc_orinocodev(int sizeof_card,
+				    int (*hard_reset)(struct orinoco_private *))
 {
-	struct orinoco_private *priv = netdev_priv(dev);
-	hermes_t *hw = &priv->hw;
-	struct iw_statistics *wstats = &priv->wstats;
-	int err = 0;
-	unsigned long flags;
-
-	if (! netif_device_present(dev)) {
-		printk(KERN_WARNING "%s: get_wireless_stats() called while device not present\n",
-		       dev->name);
-		return NULL; /* FIXME: Can we do better than this? */
-	}
+	struct net_device *dev;
+	struct orinoco_private *priv;
 
-	err = orinoco_lock(priv, &flags);
-	if (err)
-		return NULL; /* FIXME: Erg, we've been signalled, how
-			      * do we propagate this back up? */
+	dev = alloc_etherdev(sizeof(struct orinoco_private) + sizeof_card);
+	if (! dev)
+		return NULL;
+	priv = netdev_priv(dev);
+	priv->ndev = dev;
+	if (sizeof_card)
+		priv->card = (void *)((unsigned long)netdev_priv(dev)
+				      + sizeof(struct orinoco_private));
+	else
+		priv->card = NULL;
 
-	if (priv->iw_mode == IW_MODE_ADHOC) {
-		memset(&wstats->qual, 0, sizeof(wstats->qual));
-		/* If a spy address is defined, we report stats of the
-		 * first spy address - Jean II */
-		if (SPY_NUMBER(priv)) {
-			wstats->qual.qual = priv->spy_stat[0].qual;
-			wstats->qual.level = priv->spy_stat[0].level;
-			wstats->qual.noise = priv->spy_stat[0].noise;
-			wstats->qual.updated = priv->spy_stat[0].updated;
-		}
-	} else {
-		struct {
-			u16 qual, signal, noise;
-		} __attribute__ ((packed)) cq;
+	/* Setup / override net_device fields */
+	dev->init = orinoco_init;
+	dev->hard_start_xmit = orinoco_xmit;
+	dev->tx_timeout = orinoco_tx_timeout;
+	dev->watchdog_timeo = HZ; /* 1 second timeout */
+	dev->get_stats = orinoco_get_stats;
+	dev->get_wireless_stats = orinoco_get_wireless_stats;
+	dev->do_ioctl = orinoco_ioctl;
+	dev->change_mtu = orinoco_change_mtu;
+	dev->set_multicast_list = orinoco_set_multicast_list;
+	/* we use the default eth_mac_addr for setting the MAC addr */
 
-		err = HERMES_READ_RECORD(hw, USER_BAP,
-					 HERMES_RID_COMMSQUALITY, &cq);
-		
-		wstats->qual.qual = (int)le16_to_cpu(cq.qual);
-		wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
-		wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
-		wstats->qual.updated = 7;
-	}
+	/* Set up default callbacks */
+	dev->open = orinoco_open;
+	dev->stop = orinoco_stop;
+	priv->hard_reset = hard_reset;
 
-	/* We can't really wait for the tallies inquiry command to
-	 * complete, so we just use the previous results and trigger
-	 * a new tallies inquiry command for next time - Jean II */
-	/* FIXME: We're in user context (I think?), so we should just
-           wait for the tallies to come through */
-	err = hermes_inquire(hw, HERMES_INQ_TALLIES);
-               
-	orinoco_unlock(priv, &flags);
+	spin_lock_init(&priv->lock);
+	priv->open = 0;
+	priv->hw_unavailable = 1; /* orinoco_init() must clear this
+				   * before anything else touches the
+				   * hardware */
+	INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev);
 
-	if (err)
-		return NULL;
-		
-	return wstats;
-}
+	priv->last_linkstatus = 0xffff;
+	priv->connected = 0;
 
-static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
-				    int level, int noise)
-{
-	struct orinoco_private *priv = netdev_priv(dev);
-	int i;
+	return dev;
 
-	/* Gather wireless spy statistics: for each packet, compare the
-	 * source address with out list, and if match, get the stats... */
-	for (i = 0; i < priv->spy_number; i++)
-		if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) {
-			priv->spy_stat[i].level = level - 0x95;
-			priv->spy_stat[i].noise = noise - 0x95;
-			priv->spy_stat[i].qual = (level > noise) ? (level - noise) : 0;
-			priv->spy_stat[i].updated = 7;
-		}
 }
 
-void
-orinoco_stat_gather(struct net_device *dev,
-		    struct sk_buff *skb,
-		    struct hermes_rx_descriptor *desc)
-{
-	struct orinoco_private *priv = netdev_priv(dev);
-
-	/* Using spy support with lots of Rx packets, like in an
-	 * infrastructure (AP), will really slow down everything, because
-	 * the MAC address must be compared to each entry of the spy list.
-	 * If the user really asks for it (set some address in the
-	 * spy list), we do it, but he will pay the price.
-	 * Note that to get here, you need both WIRELESS_SPY
-	 * compiled in AND some addresses in the list !!!
-	 */
-	/* Note : gcc will optimise the whole section away if
-	 * WIRELESS_SPY is not defined... - Jean II */
-	if (SPY_NUMBER(priv)) {
-		orinoco_spy_gather(dev, skb->mac.raw + ETH_ALEN,
-				   desc->signal, desc->silence);
-	}
-}
+/********************************************************************/
+/* Wireless extensions                                              */
+/********************************************************************/
 
-static int
-orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
+static int orinoco_hw_get_bssid(struct orinoco_private *priv,
+				char buf[ETH_ALEN])
 {
-	struct orinoco_private *priv = netdev_priv(dev);
-	struct net_device_stats *stats = &priv->stats;
 	hermes_t *hw = &priv->hw;
 	int err = 0;
-	u16 txfid = priv->txfid;
-	char *p;
-	struct ethhdr *eh;
-	int len, data_len, data_off;
-	struct hermes_tx_descriptor desc;
 	unsigned long flags;
 
-	TRACE_ENTER(dev->name);
+	err = orinoco_lock(priv, &flags);
+	if (err)
+		return err;
 
-	if (! netif_running(dev)) {
-		printk(KERN_ERR "%s: Tx on stopped device!\n",
-		       dev->name);
-		TRACE_EXIT(dev->name);
-		return 1;
-	}
-	
-	if (netif_queue_stopped(dev)) {
-		printk(KERN_DEBUG "%s: Tx while transmitter busy!\n", 
-		       dev->name);
-		TRACE_EXIT(dev->name);
-		return 1;
-	}
-	
-	if (orinoco_lock(priv, &flags) != 0) {
-		printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n",
-		       dev->name);
-		TRACE_EXIT(dev->name);
-/*  		BUG(); */
-		return 1;
-	}
+	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
+			      ETH_ALEN, NULL, buf);
 
-	if (! priv->connected) {
-		/* Oops, the firmware hasn't established a connection,
-                   silently drop the packet (this seems to be the
-                   safest approach). */
-		stats->tx_errors++;
-		orinoco_unlock(priv, &flags);
-		dev_kfree_skb(skb);
-		TRACE_EXIT(dev->name);
-		return 0;
-	}
+	orinoco_unlock(priv, &flags);
 
-	/* Length of the packet body */
-	/* FIXME: what if the skb is smaller than this? */
-	len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN);
+	return err;
+}
 
-	eh = (struct ethhdr *)skb->data;
+static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
+				char buf[IW_ESSID_MAX_SIZE+1])
+{
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+	struct hermes_idstring essidbuf;
+	char *p = (char *)(&essidbuf.val);
+	int len;
+	unsigned long flags;
 
-	memset(&desc, 0, sizeof(desc));
- 	desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX);
-	err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), txfid, 0);
-	if (err) {
-		printk(KERN_ERR "%s: Error %d writing Tx descriptor to BAP\n",
-		       dev->name, err);
-		stats->tx_errors++;
-		goto fail;
-	}
+	err = orinoco_lock(priv, &flags);
+	if (err)
+		return err;
 
-	/* Clear the 802.11 header and data length fields - some
-	 * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused
-	 * if this isn't done. */
-	hermes_clear_words(hw, HERMES_DATA0,
-			   HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);
+	if (strlen(priv->desired_essid) > 0) {
+		/* We read the desired SSID from the hardware rather
+		   than from priv->desired_essid, just in case the
+		   firmware is allowed to change it on us. I'm not
+		   sure about this */
+		/* My guess is that the OWNSSID should always be whatever
+		 * we set to the card, whereas CURRENT_SSID is the one that
+		 * may change... - Jean II */
+		u16 rid;
 
-	/* Encapsulate Ethernet-II frames */
-	if (ntohs(eh->h_proto) > 1500) { /* Ethernet-II frame */
-		struct header_struct hdr;
-		data_len = len;
-		data_off = HERMES_802_3_OFFSET + sizeof(hdr);
-		p = skb->data + ETH_HLEN;
+		*active = 1;
 
-		/* 802.3 header */
-		memcpy(hdr.dest, eh->h_dest, ETH_ALEN);
-		memcpy(hdr.src, eh->h_source, ETH_ALEN);
-		hdr.len = htons(data_len + ENCAPS_OVERHEAD);
+		rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
+			HERMES_RID_CNFDESIREDSSID;
 		
-		/* 802.2 header */
-		memcpy(&hdr.dsap, &encaps_hdr, sizeof(encaps_hdr));
-			
-		hdr.ethertype = eh->h_proto;
-		err  = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),
-					 txfid, HERMES_802_3_OFFSET);
-		if (err) {
-			printk(KERN_ERR "%s: Error %d writing packet header to BAP\n",
-			       dev->name, err);
-			stats->tx_errors++;
-			goto fail;
-		}
-	} else { /* IEEE 802.3 frame */
-		data_len = len + ETH_HLEN;
-		data_off = HERMES_802_3_OFFSET;
-		p = skb->data;
-	}
+		err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
+				      NULL, &essidbuf);
+		if (err)
+			goto fail_unlock;
+	} else {
+		*active = 0;
 
-	/* Round up for odd length packets */
-	err = hermes_bap_pwrite(hw, USER_BAP, p, RUP_EVEN(data_len), txfid, data_off);
-	if (err) {
-		printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
-		       dev->name, err);
-		stats->tx_errors++;
-		goto fail;
+		err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
+				      sizeof(essidbuf), NULL, &essidbuf);
+		if (err)
+			goto fail_unlock;
 	}
 
-	/* Finally, we actually initiate the send */
-	netif_stop_queue(dev);
-
-	err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL, txfid, NULL);
-	if (err) {
-		netif_start_queue(dev);
-		printk(KERN_ERR "%s: Error %d transmitting packet\n", dev->name, err);
-		stats->tx_errors++;
-		goto fail;
-	}
+	len = le16_to_cpu(essidbuf.len);
 
-	dev->trans_start = jiffies;
-	stats->tx_bytes += data_off + data_len;
+	memset(buf, 0, IW_ESSID_MAX_SIZE+1);
+	memcpy(buf, p, len);
+	buf[len] = '\0';
 
+ fail_unlock:
 	orinoco_unlock(priv, &flags);
 
-	dev_kfree_skb(skb);
-
-	TRACE_EXIT(dev->name);
-
-	return 0;
- fail:
-	TRACE_EXIT(dev->name);
-
-	orinoco_unlock(priv, &flags);
-	return err;
+	return err;       
 }
 
-static void
-orinoco_tx_timeout(struct net_device *dev)
+static long orinoco_hw_get_freq(struct orinoco_private *priv)
 {
-	struct orinoco_private *priv = netdev_priv(dev);
-	struct net_device_stats *stats = &priv->stats;
-	struct hermes *hw = &priv->hw;
-
-	printk(KERN_WARNING "%s: Tx timeout! "
-	       "ALLOCFID=%04x, TXCOMPLFID=%04x, EVSTAT=%04x\n",
-	       dev->name, hermes_read_regn(hw, ALLOCFID),
-	       hermes_read_regn(hw, TXCOMPLFID), hermes_read_regn(hw, EVSTAT));
-
-	stats->tx_errors++;
+	
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+	u16 channel;
+	long freq = 0;
+	unsigned long flags;
 
-	schedule_work(&priv->reset_work);
-}
+	err = orinoco_lock(priv, &flags);
+	if (err)
+		return err;
+	
+	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL, &channel);
+	if (err)
+		goto out;
 
-static int
-orinoco_change_mtu(struct net_device *dev, int new_mtu)
-{
-	struct orinoco_private *priv = netdev_priv(dev);
+	/* Intersil firmware 1.3.5 returns 0 when the interface is down */
+	if (channel == 0) {
+		err = -EBUSY;
+		goto out;
+	}
 
-	if ( (new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU) )
-		return -EINVAL;
+	if ( (channel < 1) || (channel > NUM_CHANNELS) ) {
+		printk(KERN_WARNING "%s: Channel out of range (%d)!\n",
+		       priv->ndev->name, channel);
+		err = -EBUSY;
+		goto out;
 
-	if ( (new_mtu + ENCAPS_OVERHEAD + IEEE802_11_HLEN) >
-	     (priv->nicbuf_size - ETH_HLEN) )
-		return -EINVAL;
+	}
+	freq = channel_frequency[channel-1] * 100000;
 
-	dev->mtu = new_mtu;
+ out:
+	orinoco_unlock(priv, &flags);
 
-	return 0;
+	if (err > 0)
+		err = -EBUSY;
+	return err ? err : freq;
 }
 
-/* FIXME: return int? */
-static void
-__orinoco_set_multicast_list(struct net_device *dev)
+static int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
+				      int *numrates, s32 *rates, int max)
 {
-	struct orinoco_private *priv = netdev_priv(dev);
 	hermes_t *hw = &priv->hw;
+	struct hermes_idstring list;
+	unsigned char *p = (unsigned char *)&list.val;
 	int err = 0;
-	int promisc, mc_count;
-
-	/* The Hermes doesn't seem to have an allmulti mode, so we go
-	 * into promiscuous mode and let the upper levels deal. */
-	if ( (dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) ||
-	     (dev->mc_count > MAX_MULTICAST(priv)) ) {
-		promisc = 1;
-		mc_count = 0;
-	} else {
-		promisc = 0;
-		mc_count = dev->mc_count;
-	}
+	int num;
+	int i;
+	unsigned long flags;
 
-	if (promisc != priv->promiscuous) {
-		err = hermes_write_wordrec(hw, USER_BAP,
-					   HERMES_RID_CNFPROMISCUOUSMODE,
-					   promisc);
-		if (err) {
-			printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n",
-			       dev->name, err);
-		} else 
-			priv->promiscuous = promisc;
-	}
+	err = orinoco_lock(priv, &flags);
+	if (err)
+		return err;
 
-	if (! promisc && (mc_count || priv->mc_count) ) {
-		struct dev_mc_list *p = dev->mc_list;
-		hermes_multicast_t mclist;
-		int i;
+	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
+			      sizeof(list), NULL, &list);
+	orinoco_unlock(priv, &flags);
 
-		for (i = 0; i < mc_count; i++) {
-			/* Paranoia: */
-			if (! p)
-				BUG(); /* Multicast list shorter than mc_count */
-			if (p->dmi_addrlen != ETH_ALEN)
-				BUG(); /* Bad address size in multicast list */
-			
-			memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN);
-			p = p->next;
-		}
-		
-		if (p)
-			printk(KERN_WARNING "Multicast list is longer than mc_count\n");
+	if (err)
+		return err;
+	
+	num = le16_to_cpu(list.len);
+	*numrates = num;
+	num = min(num, max);
 
-		err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFGROUPADDRESSES,
-				       HERMES_BYTES_TO_RECLEN(priv->mc_count * ETH_ALEN),
-				       &mclist);
-		if (err)
-			printk(KERN_ERR "%s: Error %d setting multicast list.\n",
-			       dev->name, err);
-		else
-			priv->mc_count = mc_count;
+	for (i = 0; i < num; i++) {
+		rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
 	}
 
-	/* Since we can set the promiscuous flag when it wasn't asked
-	   for, make sure the net_device knows about it. */
-	if (priv->promiscuous)
-		dev->flags |= IFF_PROMISC;
-	else
-		dev->flags &= ~IFF_PROMISC;
+	return 0;
 }
 
-/********************************************************************/
-/* Wireless extensions support                                      */
-/********************************************************************/
-
 static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq)
 {
 	struct orinoco_private *priv = netdev_priv(dev);
@@ -2582,10 +2579,8 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq
 
 	/* Much of this shamelessly taken from wvlan_cs.c. No idea
 	 * what it all means -dgibson */
-#if WIRELESS_EXT > 10
 	range.we_version_compiled = WIRELESS_EXT;
 	range.we_version_source = 11;
-#endif /* WIRELESS_EXT > 10 */
 
 	range.min_nwid = range.max_nwid = 0; /* We don't use nwids */
 
@@ -2612,22 +2607,17 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq
 		range.max_qual.qual = 0;
 		range.max_qual.level = 0;
 		range.max_qual.noise = 0;
-#if WIRELESS_EXT > 11
 		range.avg_qual.qual = 0;
 		range.avg_qual.level = 0;
 		range.avg_qual.noise = 0;
-#endif /* WIRELESS_EXT > 11 */
-
 	} else {
 		range.max_qual.qual = 0x8b - 0x2f;
 		range.max_qual.level = 0x2f - 0x95 - 1;
 		range.max_qual.noise = 0x2f - 0x95 - 1;
-#if WIRELESS_EXT > 11
 		/* Need to get better values */
 		range.avg_qual.qual = 0x24;
 		range.avg_qual.level = 0xC2;
 		range.avg_qual.noise = 0x9E;
-#endif /* WIRELESS_EXT > 11 */
 	}
 
 	err = orinoco_hw_get_bitratelist(priv, &numrates,
@@ -2680,7 +2670,6 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq
 	range.txpower[0] = 15; /* 15dBm */
 	range.txpower_capa = IW_TXPOW_DBM;
 
-#if WIRELESS_EXT > 10
 	range.retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
 	range.retry_flags = IW_RETRY_LIMIT;
 	range.r_time_flags = IW_RETRY_LIFETIME;
@@ -2688,7 +2677,6 @@ static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq
 	range.max_retry = 65535;	/* ??? */
 	range.min_r_time = 0;
 	range.max_r_time = 65535 * 1000;	/* ??? */
-#endif /* WIRELESS_EXT > 10 */
 
 	if (copy_to_user(rrq->pointer, &range, sizeof(range)))
 		return -EFAULT;
@@ -2737,7 +2725,8 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er
 		
 		if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
 			index = priv->tx_key;
-		
+
+		/* Adjust key length to a supported value */
 		if (erq->length > SMALL_KEY_SIZE) {
 			xlen = LARGE_KEY_SIZE;
 		} else if (erq->length > 0) {
@@ -2779,14 +2768,14 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er
 
 	if (erq->pointer) {
 		priv->keys[index].len = cpu_to_le16(xlen);
-		memset(priv->keys[index].data, 0, sizeof(priv->keys[index].data));
+		memset(priv->keys[index].data, 0,
+		       sizeof(priv->keys[index].data));
 		memcpy(priv->keys[index].data, keybuf, erq->length);
 	}
 	priv->tx_key = setindex;
 	priv->wep_on = enable;
 	priv->wep_restrict = restricted;
 
-	
  out:
 	orinoco_unlock(priv, &flags);
 
@@ -3012,7 +3001,8 @@ static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq)
 	err = orinoco_lock(priv, &flags);
 	if (err)
 		return err;
-	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE, &val);
+	err = hermes_read_wordrec(hw, USER_BAP,
+				  HERMES_RID_CNFSYSTEMSCALE, &val);
 	orinoco_unlock(priv, &flags);
 
 	if (err)
@@ -3201,8 +3191,7 @@ static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq)
 
 	ratemode = priv->bitratemode;
 
-	if ( (ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE) )
-		BUG();
+	BUG_ON((ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE));
 
 	rrq->value = bitrate_table[ratemode].bitrate * 100000;
 	rrq->fixed = ! bitrate_table[ratemode].automatic;
@@ -3354,7 +3343,6 @@ static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq)
 	return err;
 }
 
-#if WIRELESS_EXT > 10
 static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq)
 {
 	struct orinoco_private *priv = netdev_priv(dev);
@@ -3406,7 +3394,6 @@ static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq)
 
 	return err;
 }
-#endif /* WIRELESS_EXT > 10 */
 
 static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq)
 {
@@ -3500,7 +3487,6 @@ static int orinoco_ioctl_getport3(struct net_device *dev, struct iwreq *wrq)
 
 	*val = priv->prefer_port3;
 	orinoco_unlock(priv, &flags);
-
 	return 0;
 }
 
@@ -3790,7 +3776,6 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 		wrq->u.txpower.flags = IW_TXPOW_DBM;
 		break;
 
-#if WIRELESS_EXT > 10
 	case SIOCSIWRETRY:
 		err = -EOPNOTSUPP;
 		break;
@@ -3798,7 +3783,6 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	case SIOCGIWRETRY:
 		err = orinoco_ioctl_getretry(dev, &wrq->u.retry);
 		break;
-#endif /* WIRELESS_EXT > 10 */
 
 	case SIOCSIWSPY:
 		err = orinoco_ioctl_setspy(dev, &wrq->u.data);
@@ -4124,51 +4108,68 @@ static int orinoco_debug_dump_recs(struct net_device *dev)
 	return 0;
 }
 
-struct net_device *alloc_orinocodev(int sizeof_card, int (*hard_reset)(struct orinoco_private *))
-{
-	struct net_device *dev;
-	struct orinoco_private *priv;
-
-	dev = alloc_etherdev(sizeof(struct orinoco_private) + sizeof_card);
-	if (!dev)
-		return NULL;
-	priv = netdev_priv(dev);
-	priv->ndev = dev;
-	if (sizeof_card)
-		priv->card = (void *)((unsigned long)dev->priv + sizeof(struct orinoco_private));
-	else
-		priv->card = NULL;
-
-	/* Setup / override net_device fields */
-	dev->init = orinoco_init;
-	dev->hard_start_xmit = orinoco_xmit;
-	dev->tx_timeout = orinoco_tx_timeout;
-	dev->watchdog_timeo = HZ; /* 1 second timeout */
-	dev->get_stats = orinoco_get_stats;
-	dev->get_wireless_stats = orinoco_get_wireless_stats;
-	dev->do_ioctl = orinoco_ioctl;
-	dev->change_mtu = orinoco_change_mtu;
-	dev->set_multicast_list = orinoco_set_multicast_list;
-	/* we use the default eth_mac_addr for setting the MAC addr */
-
-	/* Set up default callbacks */
-	dev->open = orinoco_open;
-	dev->stop = orinoco_stop;
-	priv->hard_reset = hard_reset;
+/********************************************************************/
+/* Debugging                                                        */
+/********************************************************************/
 
-	spin_lock_init(&priv->lock);
-	priv->open = 0;
-	priv->hw_unavailable = 1; /* orinoco_init() must clear this
-				   * before anything else touches the
-				   * hardware */
-	INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev);
+#if 0
+static void show_rx_frame(struct orinoco_rxframe_hdr *frame)
+{
+	printk(KERN_DEBUG "RX descriptor:\n");
+	printk(KERN_DEBUG "  status      = 0x%04x\n", frame->desc.status);
+	printk(KERN_DEBUG "  time        = 0x%08x\n", frame->desc.time);
+	printk(KERN_DEBUG "  silence     = 0x%02x\n", frame->desc.silence);
+	printk(KERN_DEBUG "  signal      = 0x%02x\n", frame->desc.signal);
+	printk(KERN_DEBUG "  rate        = 0x%02x\n", frame->desc.rate);
+	printk(KERN_DEBUG "  rxflow      = 0x%02x\n", frame->desc.rxflow);
+	printk(KERN_DEBUG "  reserved    = 0x%08x\n", frame->desc.reserved);
 
-	priv->last_linkstatus = 0xffff;
-	priv->connected = 0;
+	printk(KERN_DEBUG "IEEE 802.11 header:\n");
+	printk(KERN_DEBUG "  frame_ctl   = 0x%04x\n",
+	       frame->p80211.frame_ctl);
+	printk(KERN_DEBUG "  duration_id = 0x%04x\n",
+	       frame->p80211.duration_id);
+	printk(KERN_DEBUG "  addr1       = %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       frame->p80211.addr1[0], frame->p80211.addr1[1],
+	       frame->p80211.addr1[2], frame->p80211.addr1[3],
+	       frame->p80211.addr1[4], frame->p80211.addr1[5]);
+	printk(KERN_DEBUG "  addr2       = %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       frame->p80211.addr2[0], frame->p80211.addr2[1],
+	       frame->p80211.addr2[2], frame->p80211.addr2[3],
+	       frame->p80211.addr2[4], frame->p80211.addr2[5]);
+	printk(KERN_DEBUG "  addr3       = %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       frame->p80211.addr3[0], frame->p80211.addr3[1],
+	       frame->p80211.addr3[2], frame->p80211.addr3[3],
+	       frame->p80211.addr3[4], frame->p80211.addr3[5]);
+	printk(KERN_DEBUG "  seq_ctl     = 0x%04x\n",
+	       frame->p80211.seq_ctl);
+	printk(KERN_DEBUG "  addr4       = %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       frame->p80211.addr4[0], frame->p80211.addr4[1],
+	       frame->p80211.addr4[2], frame->p80211.addr4[3],
+	       frame->p80211.addr4[4], frame->p80211.addr4[5]);
+	printk(KERN_DEBUG "  data_len    = 0x%04x\n",
+	       frame->p80211.data_len);
 
-	return dev;
+	printk(KERN_DEBUG "IEEE 802.3 header:\n");
+	printk(KERN_DEBUG "  dest        = %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       frame->p8023.h_dest[0], frame->p8023.h_dest[1],
+	       frame->p8023.h_dest[2], frame->p8023.h_dest[3],
+	       frame->p8023.h_dest[4], frame->p8023.h_dest[5]);
+	printk(KERN_DEBUG "  src         = %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       frame->p8023.h_source[0], frame->p8023.h_source[1],
+	       frame->p8023.h_source[2], frame->p8023.h_source[3],
+	       frame->p8023.h_source[4], frame->p8023.h_source[5]);
+	printk(KERN_DEBUG "  len         = 0x%04x\n", frame->p8023.h_proto);
 
+	printk(KERN_DEBUG "IEEE 802.2 LLC/SNAP header:\n");
+	printk(KERN_DEBUG "  DSAP        = 0x%02x\n", frame->p8022.dsap);
+	printk(KERN_DEBUG "  SSAP        = 0x%02x\n", frame->p8022.ssap);
+	printk(KERN_DEBUG "  ctrl        = 0x%02x\n", frame->p8022.ctrl);
+	printk(KERN_DEBUG "  OUI         = %02x:%02x:%02x\n",
+	       frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]);
+	printk(KERN_DEBUG "  ethertype  = 0x%04x\n", frame->ethertype);
 }
+#endif /* 0 */
 
 /********************************************************************/
 /* Module initialization                                            */
@@ -4185,7 +4186,9 @@ EXPORT_SYMBOL(orinoco_interrupt);
 
 /* Can't be declared "const" or the whole __initdata section will
  * become const */
-static char version[] __initdata = "orinoco.c 0.13e (David Gibson <hermes@gibson.dropbear.id.au> and others)";
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+	" (David Gibson <hermes@gibson.dropbear.id.au>, "
+	"Pavel Roskin <proski@gnu.org>, et al)";
 
 static int __init init_orinoco(void)
 {
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h
index 972a8510f..c2f5f78f5 100644
--- a/drivers/net/wireless/orinoco.h
+++ b/drivers/net/wireless/orinoco.h
@@ -7,39 +7,19 @@
 #ifndef _ORINOCO_H
 #define _ORINOCO_H
 
+#define DRIVER_VERSION "0.13e"
+
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <linux/netdevice.h>
 #include <linux/wireless.h>
 #include <linux/version.h>
-#include "hermes.h"
-
-/* Workqueue / task queue backwards compatibility stuff */
-
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41)
-#include <linux/workqueue.h>
-#else
-#include <linux/tqueue.h>
-#define work_struct tq_struct
-#define INIT_WORK INIT_TQUEUE
-#define schedule_work schedule_task
-#endif
-
-/* Interrupt handler backwards compatibility stuff */
-#ifndef IRQ_NONE
-
-#define IRQ_NONE
-#define IRQ_HANDLED
-typedef void irqreturn_t;
 
-#endif
+#include "hermes.h"
 
 /* To enable debug messages */
 //#define ORINOCO_DEBUG		3
 
-#if (! defined (WIRELESS_EXT)) || (WIRELESS_EXT < 10)
-#error "orinoco driver requires Wireless extensions v10 or later."
-#endif /* (! defined (WIRELESS_EXT)) || (WIRELESS_EXT < 10) */
 #define WIRELESS_SPY		// enable iwspy support
 
 #define ORINOCO_MAX_KEY_SIZE	14
@@ -50,11 +30,6 @@ struct orinoco_key {
 	char data[ORINOCO_MAX_KEY_SIZE];
 } __attribute__ ((packed));
 
-#define ORINOCO_INTEN	 	( HERMES_EV_RX | HERMES_EV_ALLOC | HERMES_EV_TX | \
-				HERMES_EV_TXEXC | HERMES_EV_WTERR | HERMES_EV_INFO | \
-				HERMES_EV_INFDROP )
-
-
 struct orinoco_private {
 	void *card;	/* Pointer to card dependent structure */
 	int (*hard_reset)(struct orinoco_private *);
@@ -78,7 +53,6 @@ struct orinoco_private {
 	hermes_t hw;
 	u16 txfid;
 
-
 	/* Capabilities of the hardware/firmware */
 	int firmware_type;
 #define FIRMWARE_TYPE_AGERE 1
@@ -128,6 +102,10 @@ extern int orinoco_debug;
 #define TRACE_ENTER(devname) DEBUG(2, "%s: -> %s()\n", devname, __FUNCTION__);
 #define TRACE_EXIT(devname)  DEBUG(2, "%s: <- %s()\n", devname, __FUNCTION__);
 
+/********************************************************************/
+/* Exported prototypes                                              */
+/********************************************************************/
+
 extern struct net_device *alloc_orinocodev(int sizeof_card,
 					   int (*hard_reset)(struct orinoco_private *));
 extern int __orinoco_up(struct net_device *dev);
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index 292eeffb6..4eb92ac6a 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -1,4 +1,4 @@
-/* orinoco_cs.c 0.13e	- (formerly known as dldwd_cs.c)
+/* orinoco_cs.c (formerly known as dldwd_cs.c)
  *
  * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
  * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
@@ -10,6 +10,9 @@
  * Copyright notice & release notes in file orinoco.c
  */
 
+#define DRIVER_NAME "orinoco_cs"
+#define PFX DRIVER_NAME ": "
+
 #include <linux/config.h>
 #ifdef  __IN_PCMCIA_PACKAGE__
 #include <pcmcia/k_compat.h>
@@ -47,9 +50,7 @@
 
 MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
 MODULE_DESCRIPTION("Driver for PCMCIA Lucent Orinoco, Prism II based and similar wireless cards");
-#ifdef MODULE_LICENSE
 MODULE_LICENSE("Dual MPL/GPL");
-#endif
 
 /* Module parameters */
 
@@ -76,7 +77,7 @@ MODULE_PARM(ignore_cis_vcc, "i");
  * device driver with appropriate cards, through the card
  * configuration database.
  */
-static dev_info_t dev_info = "orinoco_cs";
+static dev_info_t dev_info = DRIVER_NAME;
 
 /********************************************************************/
 /* Data structures						    */
@@ -144,15 +145,6 @@ orinoco_cs_hard_reset(struct orinoco_private *priv)
 /* PCMCIA stuff     						    */
 /********************************************************************/
 
-/* In 2.5 (as of 2.5.69 at least) there is a cs_error exported which
- * does this, but it's not in 2.4 so we do our own for now. */
-static void
-orinoco_cs_error(client_handle_t handle, int func, int ret)
-{
-	error_info_t err = { func, ret };
-	pcmcia_report_error(handle, &err);
-}
-
 /*
  * This creates an "instance" of the driver, allocating local data
  * structures for one device.  The device is registered with Card
@@ -174,7 +166,7 @@ orinoco_cs_attach(void)
 	dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset);
 	if (! dev)
 		return NULL;
-	priv = dev->priv;
+	priv = netdev_priv(dev);
 	card = priv->card;
 
 	/* Link both structures together */
@@ -216,7 +208,7 @@ orinoco_cs_attach(void)
 
 	ret = pcmcia_register_client(&link->handle, &client_reg);
 	if (ret != CS_SUCCESS) {
-		orinoco_cs_error(link->handle, RegisterClient, ret);
+		cs_error(link->handle, RegisterClient, ret);
 		orinoco_cs_detach(link);
 		return NULL;
 	}
@@ -230,8 +222,7 @@ orinoco_cs_attach(void)
  * are freed.  Otherwise, the structures will be freed when the device
  * is released.
  */
-static void
-orinoco_cs_detach(dev_link_t * link)
+static void orinoco_cs_detach(dev_link_t *link)
 {
 	dev_link_t **linkp;
 	struct net_device *dev = link->priv;
@@ -240,10 +231,8 @@ orinoco_cs_detach(dev_link_t * link)
 	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
 		if (*linkp == link)
 			break;
-	if (*linkp == NULL) {
-		BUG();
-		return;
-	}
+
+	BUG_ON(*linkp == NULL);
 
 	if (link->state & DEV_CONFIG)
 		orinoco_cs_release(link);
@@ -254,9 +243,9 @@ orinoco_cs_detach(dev_link_t * link)
 
 	/* Unlink device structure, and free it */
 	*linkp = link->next;
-	DEBUG(0, "orinoco_cs: detach: link=%p link->dev=%p\n", link, link->dev);
+	DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
 	if (link->dev) {
-		DEBUG(0, "orinoco_cs: About to unregister net device %p\n",
+		DEBUG(0, PFX "About to unregister net device %p\n",
 		      dev);
 		unregister_netdev(dev);
 	}
@@ -269,15 +258,16 @@ orinoco_cs_detach(dev_link_t * link)
  * device available to the system.
  */
 
-#define CS_CHECK(fn, ret) \
-do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+#define CS_CHECK(fn, ret) do { \
+		last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \
+	} while (0)
 
 static void
 orinoco_cs_config(dev_link_t *link)
 {
 	struct net_device *dev = link->priv;
 	client_handle_t handle = link->handle;
-	struct orinoco_private *priv = dev->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
 	struct orinoco_pccard *card = priv->card;
 	hermes_t *hw = &priv->hw;
 	int last_fn, last_ret;
@@ -308,7 +298,8 @@ orinoco_cs_config(dev_link_t *link)
 	link->state |= DEV_CONFIG;
 
 	/* Look up the current Vcc */
-	CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
+	CS_CHECK(GetConfigurationInfo,
+		 pcmcia_get_configuration_info(handle, &conf));
 	link->conf.Vcc = conf.Vcc;
 
 	/*
@@ -412,8 +403,9 @@ orinoco_cs_config(dev_link_t *link)
 			pcmcia_release_io(link->handle, &link->io);
 		last_ret = pcmcia_get_next_tuple(handle, &tuple);
 		if (last_ret  == CS_NO_MORE_ITEMS) {
-			printk(KERN_ERR "GetNextTuple().  No matching CIS configuration, "
-			       "maybe you need the ignore_cis_vcc=1 parameter.\n");
+			printk(KERN_ERR PFX "GetNextTuple(): No matching "
+			       "CIS configuration, maybe you need the "
+			       "ignore_cis_vcc=1 parameter.\n");
 			goto cs_failed;
 		}
 	}
@@ -451,7 +443,8 @@ orinoco_cs_config(dev_link_t *link)
 	 * the I/O windows and the interrupt mapping, and putting the
 	 * card and host interface into "Memory and IO" mode.
 	 */
-	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
+	CS_CHECK(RequestConfiguration,
+		 pcmcia_request_configuration(link->handle, &link->conf));
 
 	/* Ok, we have the configuration, prepare to register the netdev */
 	dev->base_addr = link->io.BasePort1;
@@ -463,7 +456,7 @@ orinoco_cs_config(dev_link_t *link)
 	dev->name[0] = '\0';
 	/* Tell the stack we exist */
 	if (register_netdev(dev) != 0) {
-		printk(KERN_ERR "orinoco_cs: register_netdev() failed\n");
+		printk(KERN_ERR PFX "register_netdev() failed\n");
 		goto failed;
 	}
 
@@ -495,7 +488,7 @@ orinoco_cs_config(dev_link_t *link)
 	return;
 
  cs_failed:
-	orinoco_cs_error(link->handle, last_fn, last_ret);
+	cs_error(link->handle, last_fn, last_ret);
 
  failed:
 	orinoco_cs_release(link);
@@ -510,7 +503,7 @@ static void
 orinoco_cs_release(dev_link_t *link)
 {
 	struct net_device *dev = link->priv;
-	struct orinoco_private *priv = dev->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
 	unsigned long flags;
 
 	/* We're committed to taking the device away now, so mark the
@@ -538,7 +531,7 @@ orinoco_cs_event(event_t event, int priority,
 {
 	dev_link_t *link = args->client_data;
 	struct net_device *dev = link->priv;
-	struct orinoco_private *priv = dev->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
 	struct orinoco_pccard *card = priv->card;
 	int err = 0;
 	unsigned long flags;
@@ -635,12 +628,14 @@ orinoco_cs_event(event_t event, int priority,
 
 /* Can't be declared "const" or the whole __initdata section will
  * become const */
-static char version[] __initdata = "orinoco_cs.c 0.13e (David Gibson <hermes@gibson.dropbear.id.au> and others)";
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+	" (David Gibson <hermes@gibson.dropbear.id.au>, "
+	"Pavel Roskin <proski@gnu.org>, et al)";
 
 static struct pcmcia_driver orinoco_driver = {
 	.owner		= THIS_MODULE,
 	.drv		= {
-		.name	= "orinoco_cs",
+		.name	= DRIVER_NAME,
 	},
 	.attach		= orinoco_cs_attach,
 	.detach		= orinoco_cs_detach,
@@ -660,7 +655,7 @@ exit_orinoco_cs(void)
 	pcmcia_unregister_driver(&orinoco_driver);
 
 	if (dev_list)
-		DEBUG(0, "orinoco_cs: Removing leftover devices.\n");
+		DEBUG(0, PFX "Removing leftover devices.\n");
 	while (dev_list != NULL) {
 		if (dev_list->state & DEV_CONFIG)
 			orinoco_cs_release(dev_list);
@@ -670,4 +665,3 @@ exit_orinoco_cs(void)
 
 module_init(init_orinoco_cs);
 module_exit(exit_orinoco_cs);
-
diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c
index 23222b951..3e58b7583 100644
--- a/drivers/net/wireless/orinoco_pci.c
+++ b/drivers/net/wireless/orinoco_pci.c
@@ -1,19 +1,23 @@
-/* orinoco_pci.c 0.13e
+/* orinoco_pci.c
  * 
  * Driver for Prism II devices that have a direct PCI interface
  * (i.e., not in a Pcmcia or PLX bridge)
  *
  * Specifically here we're talking about the Linksys WMP11
  *
+ * Current maintainers (as of 29 September 2003) are:
+ * 	Pavel Roskin <proski AT gnu.org>
+ * and	David Gibson <hermes AT gibson.dropbear.id.au>
+ *
  * Some of this code is borrowed from orinoco_plx.c
- *	Copyright (C) 2001 Daniel Barlow <dan@telent.net>
+ *	Copyright (C) 2001 Daniel Barlow <dan AT telent.net>
  * Some of this code is "inspired" by linux-wlan-ng-0.1.10, but nothing
  * has been copied from it. linux-wlan-ng-0.1.10 is originally :
  *	Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.
  * This file originally written by:
- *	Copyright (C) 2001 Jean Tourrilhes <jt@hpl.hp.com>
+ *	Copyright (C) 2001 Jean Tourrilhes <jt AT hpl.hp.com>
  * And is now maintained by:
- *	Copyright (C) 2002 David Gibson, IBM Corporation <herme@gibson.dropbear.id.au>
+ *	(C) Copyright David Gibson, IBM Corp. 2002-2003.
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -85,6 +89,9 @@
  * Jean II
  */
 
+#define DRIVER_NAME "orinoco_pci"
+#define PFX DRIVER_NAME ": "
+
 #include <linux/config.h>
 
 #include <linux/module.h>
@@ -99,7 +106,6 @@
 #include <linux/netdevice.h>
 #include <linux/if_arp.h>
 #include <linux/etherdevice.h>
-#include <linux/wireless.h>
 #include <linux/list.h>
 #include <linux/pci.h>
 #include <linux/fcntl.h>
@@ -174,7 +180,7 @@ orinoco_pci_cor_reset(struct orinoco_private *priv)
 	}
 	/* Did we timeout ? */
 	if(time_after_eq(jiffies, timeout)) {
-		printk(KERN_ERR "orinoco_pci: Busy timeout\n");
+		printk(KERN_ERR PFX "Busy timeout\n");
 		return -ETIMEDOUT;
 	}
 	printk(KERN_NOTICE "pci_cor : reg = 0x%X - %lX - %lX\n", reg, timeout, jiffies);
@@ -206,22 +212,21 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
 	if (! pci_iorange)
 		goto fail;
 
-	/* Usual setup of structures */
+	/* Allocate network device */
 	dev = alloc_orinocodev(0, NULL);
 	if (! dev) {
 		err = -ENOMEM;
 		goto fail;
 	}
-	priv = dev->priv;
 
+	priv = netdev_priv(dev);
 	dev->base_addr = (unsigned long) pci_ioaddr;
 	dev->mem_start = pci_iorange;
 	dev->mem_end = pci_iorange + pci_iolen - 1;
-
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	printk(KERN_DEBUG
+	printk(KERN_DEBUG PFX
 	       "Detected Orinoco/Prism2 PCI device at %s, mem:0x%lX to 0x%lX -> 0x%p, irq:%d\n",
 	       pci_name(pdev), dev->mem_start, dev->mem_end, pci_ioaddr, pdev->irq);
 
@@ -232,12 +237,13 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
 	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
 			  dev->name, dev);
 	if (err) {
-		printk(KERN_ERR "orinoco_pci: Error allocating IRQ %d.\n",
+		printk(KERN_ERR PFX "Error allocating IRQ %d.\n",
 		       pdev->irq);
 		err = -EBUSY;
 		goto fail;
 	}
 	dev->irq = pdev->irq;
+
 	/* Perform a COR reset to start the card */
 	if(orinoco_pci_cor_reset(priv) != 0) {
 		printk(KERN_ERR "%s: Failed to start the card\n", dev->name);
@@ -255,7 +261,8 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
 		goto fail;
 	}
 
-        return 0;               /* succeeded */
+	return 0;
+
  fail:
 	if (dev) {
 		if (dev->irq)
@@ -275,11 +282,11 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
 static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct orinoco_private *priv = dev->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
 
 	unregister_netdev(dev);
 
-        if (dev->irq)
+	if (dev->irq)
 		free_irq(dev->irq, dev);
 
 	if (priv->hw.iobase)
@@ -294,7 +301,7 @@ static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev)
 static int orinoco_pci_suspend(struct pci_dev *pdev, u32 state)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct orinoco_private *priv = dev->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
 	unsigned long flags;
 	int err;
 	
@@ -325,7 +332,7 @@ static int orinoco_pci_suspend(struct pci_dev *pdev, u32 state)
 static int orinoco_pci_resume(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct orinoco_private *priv = dev->priv;
+	struct orinoco_private *priv = netdev_priv(dev);
 	unsigned long flags;
 	int err;
 
@@ -357,7 +364,9 @@ static int orinoco_pci_resume(struct pci_dev *pdev)
 }
 
 static struct pci_device_id orinoco_pci_pci_id_table[] = {
+	/* Intersil Prism 3 */
 	{0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,},
+	/* Intersil Prism 2.5 */
 	{0x1260, 0x3873, PCI_ANY_ID, PCI_ANY_ID,},
 	{0,},
 };
@@ -365,7 +374,7 @@ static struct pci_device_id orinoco_pci_pci_id_table[] = {
 MODULE_DEVICE_TABLE(pci, orinoco_pci_pci_id_table);
 
 static struct pci_driver orinoco_pci_driver = {
-	.name		= "orinoco_pci",
+	.name		= DRIVER_NAME,
 	.id_table	= orinoco_pci_pci_id_table,
 	.probe		= orinoco_pci_init_one,
 	.remove		= __devexit_p(orinoco_pci_remove_one),
@@ -373,8 +382,11 @@ static struct pci_driver orinoco_pci_driver = {
 	.resume		= orinoco_pci_resume,
 };
 
-static char version[] __initdata = "orinoco_pci.c 0.13e (David Gibson <hermes@gibson.dropbear.id.au> & Jean Tourrilhes <jt@hpl.hp.com>)";
-MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+	" (Pavel Roskin <proski@gnu.org>,"
+	" David Gibson <hermes@gibson.dropbear.id.au> &"
+	" Jean Tourrilhes <jt@hpl.hp.com>)";
+MODULE_AUTHOR("Pavel Roskin <proski@gnu.org> & David Gibson <hermes@gibson.dropbear.id.au>");
 MODULE_DESCRIPTION("Driver for wireless LAN cards using direct PCI interface");
 MODULE_LICENSE("Dual MPL/GPL");
 
@@ -384,7 +396,7 @@ static int __init orinoco_pci_init(void)
 	return pci_module_init(&orinoco_pci_driver);
 }
 
-void __exit orinoco_pci_exit(void)
+static void __exit orinoco_pci_exit(void)
 {
 	pci_unregister_driver(&orinoco_pci_driver);
 }
diff --git a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c
index b5660defd..d21ca78f0 100644
--- a/drivers/net/wireless/orinoco_plx.c
+++ b/drivers/net/wireless/orinoco_plx.c
@@ -1,9 +1,14 @@
-/* orinoco_plx.c 0.13e
- * 
+/* orinoco_plx.c
+ *
  * Driver for Prism II devices which would usually be driven by orinoco_cs,
- * but are connected to the PCI bus by a PLX9052. 
+ * but are connected to the PCI bus by a PLX9052.
+ *
+ * Current maintainers (as of 29 September 2003) are:
+ * 	Pavel Roskin <proski AT gnu.org>
+ * and	David Gibson <hermes AT gibson.dropbear.id.au>
  *
- * Copyright (C) 2001 Daniel Barlow <dan@telent.net>
+ * (C) Copyright David Gibson, IBM Corp. 2001-2003.
+ * Copyright (C) 2001 Daniel Barlow
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -33,77 +38,83 @@
  * drop me mail with the id and "it works"/"it doesn't work".
  *
  * Note: if everything gets detected fine but it doesn't actually send
- * or receive packets, your first port of call should probably be to   
+ * or receive packets, your first port of call should probably be to
  * try newer firmware in the card.  Especially if you're doing Ad-Hoc
- * modes
+ * modes.
  *
  * The actual driving is done by orinoco.c, this is just resource
  * allocation stuff.  The explanation below is courtesy of Ryan Niemi
  * on the linux-wlan-ng list at
  * http://archives.neohapsis.com/archives/dev/linux-wlan/2001-q1/0026.html
+ *
+ * The PLX9052-based cards (WL11000 and several others) are a
+ * different beast than the usual PCMCIA-based PRISM2 configuration
+ * expected by wlan-ng.  Here's the general details on how the WL11000
+ * PCI adapter works:
+ *
+ * - Two PCI I/O address spaces, one 0x80 long which contains the
+ * PLX9052 registers, and one that's 0x40 long mapped to the PCMCIA
+ * slot I/O address space.
+ *
+ * - One PCI memory address space, mapped to the PCMCIA memory space
+ * (containing the CIS).
+ *
+ * After identifying the I/O and memory space, you can read through
+ * the memory space to confirm the CIS's device ID or manufacturer ID
+ * to make sure it's the expected card.  qKeep in mind that the PCMCIA
+ * spec specifies the CIS as the lower 8 bits of each word read from
+ * the CIS, so to read the bytes of the CIS, read every other byte
+ * (0,2,4,...). Passing that test, you need to enable the I/O address
+ * space on the PCMCIA card via the PCMCIA COR register. This is the
+ * first byte following the CIS. In my case (which may not have any
+ * relation to what's on the PRISM2 cards), COR was at offset 0x800
+ * within the PCI memory space. Write 0x41 to the COR register to
+ * enable I/O mode and to select level triggered interrupts. To
+ * confirm you actually succeeded, read the COR register back and make
+ * sure it actually got set to 0x41, incase you have an unexpected
+ * card inserted.
+ *
+ * Following that, you can treat the second PCI I/O address space (the
+ * one that's not 0x80 in length) as the PCMCIA I/O space.
+ *
+ * Note that in the Eumitcom's source for their drivers, they register
+ * the interrupt as edge triggered when registering it with the
+ * Windows kernel. I don't recall how to register edge triggered on
+ * Linux (if it can be done at all). But in some experimentation, I
+ * don't see much operational difference between using either
+ * interrupt mode. Don't mess with the interrupt mode in the COR
+ * register though, as the PLX9052 wants level triggers with the way
+ * the serial EEPROM configures it on the WL11000.
+ *
+ * There's some other little quirks related to timing that I bumped
+ * into, but I don't recall right now. Also, there's two variants of
+ * the WL11000 I've seen, revision A1 and T2. These seem to differ
+ * slightly in the timings configured in the wait-state generator in
+ * the PLX9052. There have also been some comments from Eumitcom that
+ * cards shouldn't be hot swapped, apparently due to risk of cooking
+ * the PLX9052. I'm unsure why they believe this, as I can't see
+ * anything in the design that would really cause a problem, except
+ * for crashing drivers not written to expect it. And having developed
+ * drivers for the WL11000, I'd say it's quite tricky to write code
+ * that will successfully deal with a hot unplug. Very odd things
+ * happen on the I/O side of things. But anyway, be warned. Despite
+ * that, I've hot-swapped a number of times during debugging and
+ * driver development for various reasons (stuck WAIT# line after the
+ * radio card's firmware locks up).
+ *
+ * Hope this is enough info for someone to add PLX9052 support to the
+ * wlan-ng card. In the case of the WL11000, the PCI ID's are
+ * 0x1639/0x0200, with matching subsystem ID's. Other PLX9052-based
+ * manufacturers other than Eumitcom (or on cards other than the
+ * WL11000) may have different PCI ID's.
+ *
+ * If anyone needs any more specific info, let me know. I haven't had
+ * time to implement support myself yet, and with the way things are
+ * going, might not have time for a while..
+ */
 
-The PLX9052-based cards (WL11000 and several others) are a different
-beast than the usual PCMCIA-based PRISM2 configuration expected by
-wlan-ng. Here's the general details on how the WL11000 PCI adapter
-works:
-
- - Two PCI I/O address spaces, one 0x80 long which contains the PLX9052
-   registers, and one that's 0x40 long mapped to the PCMCIA slot I/O
-   address space.
-
- - One PCI memory address space, mapped to the PCMCIA memory space
-   (containing the CIS).
-
-After identifying the I/O and memory space, you can read through the
-memory space to confirm the CIS's device ID or manufacturer ID to make
-sure it's the expected card. Keep in mind that the PCMCIA spec specifies
-the CIS as the lower 8 bits of each word read from the CIS, so to read the
-bytes of the CIS, read every other byte (0,2,4,...). Passing that test,
-you need to enable the I/O address space on the PCMCIA card via the PCMCIA
-COR register. This is the first byte following the CIS. In my case
-(which may not have any relation to what's on the PRISM2 cards), COR was
-at offset 0x800 within the PCI memory space. Write 0x41 to the COR
-register to enable I/O mode and to select level triggered interrupts. To
-confirm you actually succeeded, read the COR register back and make sure
-it actually got set to 0x41, incase you have an unexpected card inserted.
-
-Following that, you can treat the second PCI I/O address space (the one
-that's not 0x80 in length) as the PCMCIA I/O space.
-
-Note that in the Eumitcom's source for their drivers, they register the
-interrupt as edge triggered when registering it with the Windows kernel. I
-don't recall how to register edge triggered on Linux (if it can be done at
-all). But in some experimentation, I don't see much operational
-difference between using either interrupt mode. Don't mess with the
-interrupt mode in the COR register though, as the PLX9052 wants level
-triggers with the way the serial EEPROM configures it on the WL11000.
-
-There's some other little quirks related to timing that I bumped into, but
-I don't recall right now. Also, there's two variants of the WL11000 I've
-seen, revision A1 and T2. These seem to differ slightly in the timings
-configured in the wait-state generator in the PLX9052. There have also
-been some comments from Eumitcom that cards shouldn't be hot swapped,
-apparently due to risk of cooking the PLX9052. I'm unsure why they
-believe this, as I can't see anything in the design that would really
-cause a problem, except for crashing drivers not written to expect it. And
-having developed drivers for the WL11000, I'd say it's quite tricky to
-write code that will successfully deal with a hot unplug. Very odd things
-happen on the I/O side of things. But anyway, be warned. Despite that,
-I've hot-swapped a number of times during debugging and driver development
-for various reasons (stuck WAIT# line after the radio card's firmware
-locks up).
-
-Hope this is enough info for someone to add PLX9052 support to the wlan-ng
-card. In the case of the WL11000, the PCI ID's are 0x1639/0x0200, with
-matching subsystem ID's. Other PLX9052-based manufacturers other than
-Eumitcom (or on cards other than the WL11000) may have different PCI ID's.
-
-If anyone needs any more specific info, let me know. I haven't had time
-to implement support myself yet, and with the way things are going, might
-not have time for a while..
-
----end of mail---
-*/
+#define DRIVER_NAME "orinoco_plx"
+#define PFX DRIVER_NAME ": "
 
 #include <linux/config.h>
 
@@ -122,7 +133,6 @@ not have time for a while..
 #include <linux/netdevice.h>
 #include <linux/if_arp.h>
 #include <linux/etherdevice.h>
-#include <linux/wireless.h>
 #include <linux/list.h>
 #include <linux/pci.h>
 #include <linux/fcntl.h>
@@ -132,13 +142,11 @@ not have time for a while..
 #include "hermes.h"
 #include "orinoco.h"
 
-static char dev_info[] = "orinoco_plx";
-
-#define COR_OFFSET    (0x3e0 / 2)	/* COR attribute offset of Prism2 PC card */
-#define COR_VALUE     (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
+#define COR_OFFSET	(0x3e0/2) /* COR attribute offset of Prism2 PC card */
+#define COR_VALUE	(COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
 
-#define PLX_INTCSR       0x4c /* Interrupt Control and Status Register */
-#define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */
+#define PLX_INTCSR		0x4c /* Interrupt Control & Status Register */
+#define PLX_INTCSR_INTEN	(1<<6) /* Interrupt Enable bit */
 
 static const u16 cis_magic[] = {
 	0x0001, 0x0003, 0x0000, 0x0000, 0x00ff, 0x0017, 0x0004, 0x0067
@@ -215,7 +223,7 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
 	/* and 3 to the PCMCIA slot I/O address space */
 	pccard_ioaddr = pci_resource_start(pdev, 3);
 	pccard_iolen = pci_resource_len(pdev, 3);
-	if (! request_region(pccard_ioaddr, pccard_iolen, dev_info)) {
+	if (! request_region(pccard_ioaddr, pccard_iolen, DRIVER_NAME)) {
 		printk(KERN_ERR "orinoco_plx: I/O resource 0x%lx @ 0x%lx busy\n",
 		       pccard_iolen, pccard_ioaddr);
 		pccard_ioaddr = 0;
@@ -223,28 +231,30 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
 		goto fail;
 	}
 
+	/* Allocate network device */
 	dev = alloc_orinocodev(0, NULL);
 	if (! dev) {
 		err = -ENOMEM;
 		goto fail;
 	}
 
-	priv = dev->priv;
+	priv = netdev_priv(dev);
 	dev->base_addr = pccard_ioaddr;
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	printk(KERN_DEBUG
-	       "Detected Orinoco/Prism2 PLX device at %s irq:%d, io addr:0x%lx\n",
-	       pci_name(pdev), pdev->irq, pccard_ioaddr);
+	printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 PLX device "
+	       "at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq,
+	       pccard_ioaddr);
 
-	hermes_struct_init(&(priv->hw), dev->base_addr,
-			HERMES_IO, HERMES_16BIT_REGSPACING);
+	hermes_struct_init(&(priv->hw), dev->base_addr, HERMES_IO,
+			   HERMES_16BIT_REGSPACING);
 	pci_set_drvdata(pdev, dev);
 
-	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, dev->name, dev);
+	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
+			  dev->name, dev);
 	if (err) {
-		printk(KERN_ERR "orinoco_plx: Error allocating IRQ %d.\n", pdev->irq);
+		printk(KERN_ERR PFX "Error allocating IRQ %d.\n", pdev->irq);
 		err = -EBUSY;
 		goto fail;
 	}
@@ -254,10 +264,10 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
 	if (err)
 		goto fail;
 
-	return 0;		/* succeeded */
+	return 0;
 
- fail:	
-	printk(KERN_DEBUG "orinoco_plx: init_one(), FAIL!\n");
+ fail:
+	printk(KERN_DEBUG PFX "init_one(), FAIL!\n");
 
 	if (dev) {
 		if (dev->irq)
@@ -281,8 +291,7 @@ static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 
-	if (! dev)
-		BUG();
+	BUG_ON(! dev);
 
 	unregister_netdev(dev);
 		
@@ -305,33 +314,34 @@ static struct pci_device_id orinoco_plx_pci_id_table[] = {
 	{0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,},	/* Correga  - does this work? */
 	{0x1638, 0x1100, PCI_ANY_ID, PCI_ANY_ID,},	/* SMC EZConnect SMC2602W,
 							   Eumitcom PCI WL11000,
-							   Addtron AWA-100*/
+							   Addtron AWA-100 */
 	{0x16ab, 0x1100, PCI_ANY_ID, PCI_ANY_ID,},	/* Global Sun Tech GL24110P */
 	{0x16ab, 0x1101, PCI_ANY_ID, PCI_ANY_ID,},	/* Reported working, but unknown */
 	{0x16ab, 0x1102, PCI_ANY_ID, PCI_ANY_ID,},	/* Linksys WDT11 */
 	{0x16ec, 0x3685, PCI_ANY_ID, PCI_ANY_ID,},	/* USR 2415 */
 	{0xec80, 0xec00, PCI_ANY_ID, PCI_ANY_ID,},	/* Belkin F5D6000 tested by
-							   Brendan W. McAdams <rit@jacked-in.org> */
+							   Brendan W. McAdams <rit AT jacked-in.org> */
 	{0x10b7, 0x7770, PCI_ANY_ID, PCI_ANY_ID,},	/* 3Com AirConnect PCI tested by
-							   Damien Persohn <damien@persohn.net> */
+							   Damien Persohn <damien AT persohn.net> */
 	{0,},
 };
 
 MODULE_DEVICE_TABLE(pci, orinoco_plx_pci_id_table);
 
 static struct pci_driver orinoco_plx_driver = {
-	.name		= "orinoco_plx",
+	.name		= DRIVER_NAME,
 	.id_table	= orinoco_plx_pci_id_table,
 	.probe		= orinoco_plx_init_one,
 	.remove		= __devexit_p(orinoco_plx_remove_one),
 };
 
-static char version[] __initdata = "orinoco_plx.c 0.13e (Daniel Barlow <dan@telent.net>, David Gibson <hermes@gibson.dropbear.id.au>)";
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+	" (Pavel Roskin <proski@gnu.org>,"
+	" David Gibson <hermes@gibson.dropbear.id.au>,"
+	" Daniel Barlow <dan@telent.net>)";
 MODULE_AUTHOR("Daniel Barlow <dan@telent.net>");
 MODULE_DESCRIPTION("Driver for wireless LAN cards using the PLX9052 PCI bridge");
-#ifdef MODULE_LICENSE
 MODULE_LICENSE("Dual MPL/GPL");
-#endif
 
 static int __init orinoco_plx_init(void)
 {
@@ -339,7 +349,7 @@ static int __init orinoco_plx_init(void)
 	return pci_module_init(&orinoco_plx_driver);
 }
 
-void __exit orinoco_plx_exit(void)
+static void __exit orinoco_plx_exit(void)
 {
 	pci_unregister_driver(&orinoco_plx_driver);
 	current->state = TASK_UNINTERRUPTIBLE;
diff --git a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco_tmd.c
index 56ab51cf5..b619f6dea 100644
--- a/drivers/net/wireless/orinoco_tmd.c
+++ b/drivers/net/wireless/orinoco_tmd.c
@@ -1,10 +1,10 @@
-/* orinoco_tmd.c 0.01
+/* orinoco_tmd.c
  * 
  * Driver for Prism II devices which would usually be driven by orinoco_cs,
  * but are connected to the PCI bus by a TMD7160. 
  *
- * Copyright (C) 2003 Joerg Dorchain <joerg@dorchain.net>
- * based heavily upon orinoco_plx.c Copyright (C) 2001 Daniel Barlow <dan@telent.net>
+ * Copyright (C) 2003 Joerg Dorchain <joerg AT dorchain.net>
+ * based heavily upon orinoco_plx.c Copyright (C) 2001 Daniel Barlow
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -49,6 +49,9 @@
  * Pheecom sells cards with the TMD chip as "ASIC version"
  */
 
+#define DRIVER_NAME "orinoco_tmd"
+#define PFX DRIVER_NAME ": "
+
 #include <linux/config.h>
 
 #include <linux/module.h>
@@ -66,7 +69,6 @@
 #include <linux/netdevice.h>
 #include <linux/if_arp.h>
 #include <linux/etherdevice.h>
-#include <linux/wireless.h>
 #include <linux/list.h>
 #include <linux/pci.h>
 #include <linux/fcntl.h>
@@ -76,10 +78,7 @@
 #include "hermes.h"
 #include "orinoco.h"
 
-static char dev_info[] = "orinoco_tmd";
-
-#define COR_VALUE     (COR_LEVEL_REQ | COR_FUNC_ENA | COR_FUNC_ENA) /* Enable PC card with level triggered irqs and irq requests */
-
+#define COR_VALUE	(COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
 
 static int orinoco_tmd_init_one(struct pci_dev *pdev,
 				const struct pci_device_id *ent)
@@ -95,11 +94,11 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
 	if (err)
 		return -EIO;
 
-	printk(KERN_DEBUG "TMD setup\n");
+	printk(KERN_DEBUG PFX "TMD setup\n");
 	pccard_ioaddr = pci_resource_start(pdev, 2);
 	pccard_iolen = pci_resource_len(pdev, 2);
-	if (! request_region(pccard_ioaddr, pccard_iolen, dev_info)) {
-		printk(KERN_ERR "orinoco_tmd: I/O resource at 0x%lx len 0x%lx busy\n",
+	if (! request_region(pccard_ioaddr, pccard_iolen, DRIVER_NAME)) {
+		printk(KERN_ERR PFX "I/O resource at 0x%lx len 0x%lx busy\n",
 			pccard_ioaddr, pccard_iolen);
 		pccard_ioaddr = 0;
 		err = -EBUSY;
@@ -110,34 +109,35 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
 	mdelay(1);
 	reg = inb(addr);
 	if (reg != COR_VALUE) {
-		printk(KERN_ERR "orinoco_tmd: Error setting TMD COR values %x should be %x\n", reg, COR_VALUE);
+		printk(KERN_ERR PFX "Error setting TMD COR values %x should be %x\n", reg, COR_VALUE);
 		err = -EIO;
 		goto fail;
 	}
 
+	/* Allocate network device */
 	dev = alloc_orinocodev(0, NULL);
 	if (! dev) {
 		err = -ENOMEM;
 		goto fail;
 	}
 
-	priv = dev->priv;
+	priv = netdev_priv(dev);
 	dev->base_addr = pccard_ioaddr;
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	printk(KERN_DEBUG
-	       "Detected Orinoco/Prism2 TMD device at %s irq:%d, io addr:0x%lx\n",
-	       pci_name(pdev), pdev->irq, pccard_ioaddr);
+	printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 TMD device "
+	       "at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq,
+	       pccard_ioaddr);
 
 	hermes_struct_init(&(priv->hw), dev->base_addr,
 			HERMES_IO, HERMES_16BIT_REGSPACING);
 	pci_set_drvdata(pdev, dev);
 
-	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, dev->name,
-			  dev);
+	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
+			  dev->name, dev);
 	if (err) {
-		printk(KERN_ERR "orinoco_tmd: Error allocating IRQ %d.\n",
+		printk(KERN_ERR PFX "Error allocating IRQ %d.\n",
 		       pdev->irq);
 		err = -EBUSY;
 		goto fail;
@@ -148,10 +148,10 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
 	if (err)
 		goto fail;
 
-	return 0;		/* succeeded */
+	return 0;
 
- fail:	
-	printk(KERN_DEBUG "orinoco_tmd: init_one(), FAIL!\n");
+ fail:
+	printk(KERN_DEBUG PFX "init_one(), FAIL!\n");
 
 	if (dev) {
 		if (dev->irq)
@@ -172,8 +172,7 @@ static void __devexit orinoco_tmd_remove_one(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 
-	if (! dev)
-		BUG();
+	BUG_ON(! dev);
 
 	unregister_netdev(dev);
 		
@@ -198,18 +197,17 @@ static struct pci_device_id orinoco_tmd_pci_id_table[] = {
 MODULE_DEVICE_TABLE(pci, orinoco_tmd_pci_id_table);
 
 static struct pci_driver orinoco_tmd_driver = {
-	.name		= "orinoco_tmd",
+	.name		= DRIVER_NAME,
 	.id_table	= orinoco_tmd_pci_id_table,
 	.probe		= orinoco_tmd_init_one,
 	.remove		= __devexit_p(orinoco_tmd_remove_one),
 };
 
-static char version[] __initdata = "orinoco_tmd.c 0.01 (Joerg Dorchain <joerg@dorchain.net>)";
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+	" (Joerg Dorchain <joerg@dorchain.net>)";
 MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>");
 MODULE_DESCRIPTION("Driver for wireless LAN cards using the TMD7160 PCI bridge");
-#ifdef MODULE_LICENSE
 MODULE_LICENSE("Dual MPL/GPL");
-#endif
 
 static int __init orinoco_tmd_init(void)
 {
@@ -217,7 +215,7 @@ static int __init orinoco_tmd_init(void)
 	return pci_module_init(&orinoco_tmd_driver);
 }
 
-void __exit orinoco_tmd_exit(void)
+static void __exit orinoco_tmd_exit(void)
 {
 	pci_unregister_driver(&orinoco_tmd_driver);
 	current->state = TASK_UNINTERRUPTIBLE;
diff --git a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c
index 3ee31021f..651189105 100644
--- a/drivers/net/wireless/prism54/isl_38xx.c
+++ b/drivers/net/wireless/prism54/isl_38xx.c
@@ -44,7 +44,7 @@
  *  register located at offset %ISL38XX_INT_IDENT_REG.
  */
 void
-isl38xx_disable_interrupts(void *device)
+isl38xx_disable_interrupts(void __iomem *device)
 {
 	isl38xx_w32_flush(device, 0x00000000, ISL38XX_INT_EN_REG);
 	udelay(ISL38XX_WRITEIO_DELAY);
@@ -52,7 +52,7 @@ isl38xx_disable_interrupts(void *device)
 
 void
 isl38xx_handle_sleep_request(isl38xx_control_block *control_block,
-			     int *powerstate, void *device_base)
+			     int *powerstate, void __iomem *device_base)
 {
 	/* device requests to go into sleep mode
 	 * check whether the transmit queues for data and management are empty */
@@ -88,7 +88,7 @@ isl38xx_handle_sleep_request(isl38xx_control_block *control_block,
 
 void
 isl38xx_handle_wakeup(isl38xx_control_block *control_block,
-		      int *powerstate, void *device_base)
+		      int *powerstate, void __iomem *device_base)
 {
 	/* device is in active state, update the powerstate flag */
 	*powerstate = ISL38XX_PSM_ACTIVE_STATE;
@@ -110,7 +110,7 @@ isl38xx_handle_wakeup(isl38xx_control_block *control_block,
 }
 
 void
-isl38xx_trigger_device(int asleep, void *device_base)
+isl38xx_trigger_device(int asleep, void __iomem *device_base)
 {
 	struct timeval current_time;
 	u32 reg, counter = 0;
@@ -190,7 +190,7 @@ isl38xx_trigger_device(int asleep, void *device_base)
 }
 
 void
-isl38xx_interface_reset(void *device_base, dma_addr_t host_address)
+isl38xx_interface_reset(void __iomem *device_base, dma_addr_t host_address)
 {
 	u32 reg;
 
@@ -219,7 +219,7 @@ isl38xx_interface_reset(void *device_base, dma_addr_t host_address)
 }
 
 void
-isl38xx_enable_common_interrupts(void *device_base) {
+isl38xx_enable_common_interrupts(void __iomem *device_base) {
 	u32 reg;
 	reg = ( ISL38XX_INT_IDENT_UPDATE | 
 			ISL38XX_INT_IDENT_SLEEP | ISL38XX_INT_IDENT_WAKEUP);
diff --git a/drivers/net/wireless/prism54/isl_38xx.h b/drivers/net/wireless/prism54/isl_38xx.h
index 0bd5ff6ad..d63fd641d 100644
--- a/drivers/net/wireless/prism54/isl_38xx.h
+++ b/drivers/net/wireless/prism54/isl_38xx.h
@@ -75,7 +75,7 @@
  *  from the %ISL38XX_PCI_POSTING_FLUSH offset.
  */
 static inline void
-isl38xx_w32_flush(void *base, u32 val, unsigned long offset)
+isl38xx_w32_flush(void __iomem *base, u32 val, unsigned long offset)
 {
 	writel(val, base + offset);
 	(void) readl(base + ISL38XX_PCI_POSTING_FLUSH);
@@ -157,13 +157,13 @@ typedef struct isl38xx_cb isl38xx_control_block;
 /* determine number of entries currently in queue */
 int isl38xx_in_queue(isl38xx_control_block *cb, int queue);
 
-void isl38xx_disable_interrupts(void *);
-void isl38xx_enable_common_interrupts(void *);
+void isl38xx_disable_interrupts(void __iomem *);
+void isl38xx_enable_common_interrupts(void __iomem *);
 
 void isl38xx_handle_sleep_request(isl38xx_control_block *, int *,
-				  void *);
-void isl38xx_handle_wakeup(isl38xx_control_block *, int *, void *);
-void isl38xx_trigger_device(int, void *);
-void isl38xx_interface_reset(void *, dma_addr_t);
+				  void __iomem *);
+void isl38xx_handle_wakeup(isl38xx_control_block *, int *, void __iomem *);
+void isl38xx_trigger_device(int, void __iomem *);
+void isl38xx_interface_reset(void __iomem *, dma_addr_t);
 
 #endif				/* _ISL_38XX_H */
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 7924b36a7..2d7e1cf88 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -334,9 +334,10 @@ prism54_get_freq(struct net_device *ndev, struct iw_request_info *info,
 	int rvalue;
 
 	rvalue = mgt_get_request(priv, DOT11_OID_CHANNEL, 0, NULL, &r);
-
+	fwrq->i = r.u;
+	rvalue |= mgt_get_request(priv, DOT11_OID_FREQUENCY, 0, NULL, &r);
 	fwrq->m = r.u;
-	fwrq->e = 0;
+	fwrq->e = 3;
 
 	return rvalue;
 }
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
index d96d621f1..650f86a8c 100644
--- a/drivers/net/wireless/prism54/islpci_dev.c
+++ b/drivers/net/wireless/prism54/islpci_dev.c
@@ -58,7 +58,7 @@ static int
 isl_upload_firmware(islpci_private *priv)
 {
 	u32 reg, rc;
-	void *device_base = priv->device_base;
+	void __iomem *device_base = priv->device_base;
 
 	/* clear the RAMBoot and the Reset bit */
 	reg = readl(device_base + ISL38XX_CTRL_STAT_REG);
@@ -113,7 +113,7 @@ isl_upload_firmware(islpci_private *priv)
 			    (fw_len >
 			     ISL38XX_MEMORY_WINDOW_SIZE) ?
 			    ISL38XX_MEMORY_WINDOW_SIZE : fw_len;
-			u32 *dev_fw_ptr = device_base + ISL38XX_DIRECT_MEM_WIN;
+			u32 __iomem *dev_fw_ptr = device_base + ISL38XX_DIRECT_MEM_WIN;
 
 			/* set the cards base address for writting the data */
 			isl38xx_w32_flush(device_base, reg,
@@ -183,7 +183,7 @@ islpci_interrupt(int irq, void *config, struct pt_regs *regs)
 	u32 reg;
 	islpci_private *priv = config;
 	struct net_device *ndev = priv->ndev;
-	void *device = priv->device_base;
+	void __iomem *device = priv->device_base;
 	int powerstate = ISL38XX_PSM_POWERSAVE_STATE;
 
 	/* lock the interrupt handler */
@@ -405,7 +405,7 @@ islpci_close(struct net_device *ndev)
 static int
 prism54_bring_down(islpci_private *priv)
 {
-	void *device_base = priv->device_base;
+	void __iomem *device_base = priv->device_base;
 	u32 reg;
 	/* we are going to shutdown the device */
 	islpci_set_state(priv, PRV_STATE_PREBOOT);
diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h
index e0ec5de03..628fb9107 100644
--- a/drivers/net/wireless/prism54/islpci_dev.h
+++ b/drivers/net/wireless/prism54/islpci_dev.h
@@ -109,7 +109,7 @@ typedef struct {
 	u32 pci_state[16];	/* used for suspend/resume */
 	char firmware[33];
 
-	void *device_base;	/* ioremapped device base address */
+	void __iomem *device_base;	/* ioremapped device base address */
 
 	/* consistent DMA region */
 	void *driver_mem_address;	/* base DMA address */
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index e39bcddc3..1bb0ada59 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -54,7 +54,6 @@
 #include <pcmcia/ds.h>
 #include <pcmcia/mem_op.h>
 
-#ifdef CONFIG_NET_PCMCIA_RADIO
 #include <linux/wireless.h>
 
 #include <asm/io.h>
@@ -68,7 +67,6 @@
 typedef struct iw_statistics	iw_stats;
 typedef struct iw_quality	iw_qual;
 typedef u_char	mac_addr[ETH_ALEN];	/* Hardware address */
-#endif	/* CONFIG_NET_PCMCIA_RADIO */
 
 #include "rayctl.h"
 #include "ray_cs.h"
@@ -112,9 +110,9 @@ static int ray_open(struct net_device *dev);
 static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
 static void ray_update_multi_list(struct net_device *dev, int all);
-static int translate_frame(ray_dev_t *local, struct tx_msg *ptx,
+static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx,
                 unsigned char *data, int len);
-static void ray_build_header(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type,
+static void ray_build_header(ray_dev_t *local, struct tx_msg __iomem *ptx, UCHAR msg_type,
                 unsigned char *data);
 static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len);
 #if WIRELESS_EXT > 7	/* If wireless extension exist in the kernel */
@@ -140,14 +138,14 @@ static void verify_dl_startup(u_long);
 /* Prototypes for interrpt time functions **********************************/
 static irqreturn_t ray_interrupt (int reg, void *dev_id, struct pt_regs *regs);
 static void clear_interrupt(ray_dev_t *local);
-static void rx_deauthenticate(ray_dev_t *local, struct rcs *prcs, 
+static void rx_deauthenticate(ray_dev_t *local, struct rcs __iomem *prcs, 
                        unsigned int pkt_addr, int rx_len);
 static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int len);
-static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs);
-static void release_frag_chain(ray_dev_t *local, struct rcs *prcs);
-static void rx_authenticate(ray_dev_t *local, struct rcs *prcs,
+static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs __iomem *prcs);
+static void release_frag_chain(ray_dev_t *local, struct rcs __iomem *prcs);
+static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs,
                      unsigned int pkt_addr, int rx_len);
-static void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr, 
+static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, unsigned int pkt_addr, 
              int rx_len);
 static void associate(ray_dev_t *local);
 
@@ -540,7 +538,7 @@ static void ray_config(dev_link_t *link)
     CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win));
     mem.CardOffset = 0x0000; mem.Page = 0;
     CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem));
-    local->sram = (UCHAR *)(ioremap(req.Base,req.Size));
+    local->sram = ioremap(req.Base,req.Size);
 
 /*** Set up 16k window for shared memory (receive buffer) ***************/
     req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
@@ -550,7 +548,7 @@ static void ray_config(dev_link_t *link)
     CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->rmem_handle));
     mem.CardOffset = 0x8000; mem.Page = 0;
     CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->rmem_handle, &mem));
-    local->rmem = (UCHAR *)(ioremap(req.Base,req.Size));
+    local->rmem = ioremap(req.Base,req.Size);
 
 /*** Set up window for attribute memory ***********************************/
     req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM | WIN_ENABLE | WIN_USE_WAIT;
@@ -560,7 +558,7 @@ static void ray_config(dev_link_t *link)
     CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->amem_handle));
     mem.CardOffset = 0x0000; mem.Page = 0;
     CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->amem_handle, &mem));
-    local->amem = (UCHAR *)(ioremap(req.Base,req.Size));
+    local->amem = ioremap(req.Base,req.Size);
 
     DEBUG(3,"ray_config sram=%p\n",local->sram);
     DEBUG(3,"ray_config rmem=%p\n",local->rmem);
@@ -593,12 +591,30 @@ cs_failed:
 
     ray_release(link);
 } /* ray_config */
+
+static inline struct ccs __iomem *ccs_base(ray_dev_t *dev)
+{
+	return dev->sram + CCS_BASE;
+}
+
+static inline struct rcs __iomem *rcs_base(ray_dev_t *dev)
+{
+	/*
+	 * This looks nonsensical, since there is a separate
+	 * RCS_BASE. But the difference between a "struct rcs"
+	 * and a "struct ccs" ends up being in the _index_ off
+	 * the base, so the base pointer is the same for both
+	 * ccs/rcs.
+	 */
+	return dev->sram + CCS_BASE;
+}
+
 /*===========================================================================*/
 static int ray_init(struct net_device *dev)
 {
     int i;
     UCHAR *p;
-    struct ccs *pccs;
+    struct ccs __iomem *pccs;
     ray_dev_t *local = (ray_dev_t *)dev->priv;
     dev_link_t *link = local->finder;
     DEBUG(1, "ray_init(0x%p)\n", dev);
@@ -632,7 +648,7 @@ static int ray_init(struct net_device *dev)
         local->tib_length = local->startup_res.tib_length;
     DEBUG(2,"ray_init tib_length = 0x%02x\n", local->tib_length);
     /* Initialize CCS's to buffer free state */
-    pccs = (struct ccs *)(local->sram + CCS_BASE);
+    pccs = ccs_base(local);
     for (i=0;  i<NUMBER_OF_CCS;  i++) {
         writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status);
     }
@@ -661,7 +677,7 @@ static int dl_startup_params(struct net_device *dev)
 {
     int ccsindex;
     ray_dev_t *local = (ray_dev_t *)dev->priv;
-    struct ccs *pccs;
+    struct ccs __iomem *pccs;
     dev_link_t *link = local->finder;
 
     DEBUG(1,"dl_startup_params entered\n");
@@ -682,7 +698,7 @@ static int dl_startup_params(struct net_device *dev)
     /* Fill in the CCS fields for the ECF */
     if ((ccsindex = get_free_ccs(local)) < 0) return -1;
     local->dl_param_ccs = ccsindex;
-    pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex;
+    pccs = ccs_base(local) + ccsindex;
     writeb(CCS_DOWNLOAD_STARTUP_PARAMS, &pccs->cmd);
     DEBUG(2,"dl_startup_params start ccsindex = %d\n", local->dl_param_ccs);
     /* Interrupt the firmware to process the command */
@@ -767,7 +783,7 @@ static void init_startup_params(ray_dev_t *local)
 static void verify_dl_startup(u_long data)
 {
     ray_dev_t *local = (ray_dev_t *)data;
-    struct ccs *pccs = ((struct ccs *)(local->sram + CCS_BASE)) + local->dl_param_ccs;
+    struct ccs __iomem *pccs = ccs_base(local) + local->dl_param_ccs;
     UCHAR status;
     dev_link_t *link = local->finder;
 
@@ -807,7 +823,7 @@ static void verify_dl_startup(u_long data)
 static void start_net(u_long data)
 {
     ray_dev_t *local = (ray_dev_t *)data;
-    struct ccs *pccs;
+    struct ccs __iomem *pccs;
     int ccsindex;
     dev_link_t *link = local->finder;
     if (!(link->state & DEV_PRESENT)) {
@@ -816,7 +832,7 @@ static void start_net(u_long data)
     }
     /* Fill in the CCS fields for the ECF */
     if ((ccsindex = get_free_ccs(local)) < 0) return;
-    pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex;
+    pccs = ccs_base(local) + ccsindex;
     writeb(CCS_START_NETWORK, &pccs->cmd);
     writeb(0, &pccs->var.start_network.update_param);
     /* Interrupt the firmware to process the command */
@@ -834,7 +850,7 @@ static void join_net(u_long data)
 {
     ray_dev_t *local = (ray_dev_t *)data;
 
-    struct ccs *pccs;
+    struct ccs __iomem *pccs;
     int ccsindex;
     dev_link_t *link = local->finder;
     
@@ -844,7 +860,7 @@ static void join_net(u_long data)
     }
     /* Fill in the CCS fields for the ECF */
     if ((ccsindex = get_free_ccs(local)) < 0) return;
-    pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex;
+    pccs = ccs_base(local) + ccsindex;
     writeb(CCS_JOIN_NETWORK, &pccs->cmd);
     writeb(0, &pccs->var.join_network.update_param);
     writeb(0, &pccs->var.join_network.net_initiated);
@@ -1049,10 +1065,10 @@ static int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev,
                 UCHAR msg_type)
 {
     ray_dev_t *local = (ray_dev_t *)dev->priv;
-    struct ccs *pccs;
+    struct ccs __iomem *pccs;
     int ccsindex;
     int offset;
-    struct tx_msg *ptx; /* Address of xmit buffer in PC space */
+    struct tx_msg __iomem *ptx; /* Address of xmit buffer in PC space */
     short int addr;     /* Address of xmit buffer in card space */
     
     DEBUG(3,"ray_hw_xmit(data=%p, len=%d, dev=%p)\n",data,len,dev);
@@ -1079,7 +1095,7 @@ static int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev,
         local->stats.tx_packets++;
     }
 
-    ptx = (struct tx_msg *)(local->sram + addr);
+    ptx = local->sram + addr;
 
     ray_build_header(local, ptx, msg_type, data);
     if (translate) {
@@ -1092,7 +1108,7 @@ static int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev,
     }
 
     /* fill in the CCS */
-    pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex;
+    pccs = ccs_base(local) + ccsindex;
     len += TX_HEADER_LENGTH + offset;
     writeb(CCS_TX_REQUEST, &pccs->cmd);
     writeb(addr >> 8, &pccs->var.tx_request.tx_data_ptr[0]);
@@ -1119,21 +1135,21 @@ static int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev,
     return XMIT_OK;
 } /* end ray_hw_xmit */
 /*===========================================================================*/
-static int translate_frame(ray_dev_t *local, struct tx_msg *ptx, unsigned char *data,
+static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx, unsigned char *data,
                     int len)
 {
     unsigned short int proto = ((struct ethhdr *)data)->h_proto;
     if (ntohs(proto) >= 1536) { /* DIX II ethernet frame */
         DEBUG(3,"ray_cs translate_frame DIX II\n");
         /* Copy LLC header to card buffer */
-        memcpy_toio((UCHAR *)&ptx->var, eth2_llc, sizeof(eth2_llc));
-        memcpy_toio( ((UCHAR *)&ptx->var) + sizeof(eth2_llc), (UCHAR *)&proto, 2);
+        memcpy_toio(&ptx->var, eth2_llc, sizeof(eth2_llc));
+        memcpy_toio( ((void __iomem *)&ptx->var) + sizeof(eth2_llc), (UCHAR *)&proto, 2);
         if ((proto == 0xf380) || (proto == 0x3781)) {
             /* This is the selective translation table, only 2 entries */
-            writeb(0xf8, (UCHAR *) &((struct snaphdr_t *)ptx->var)->org[3]);
+            writeb(0xf8, &((struct snaphdr_t __iomem *)ptx->var)->org[3]);
         }
         /* Copy body of ethernet packet without ethernet header */
-        memcpy_toio((UCHAR *)&ptx->var + sizeof(struct snaphdr_t), \
+        memcpy_toio((void __iomem *)&ptx->var + sizeof(struct snaphdr_t), \
                     data + ETH_HLEN,  len - ETH_HLEN);
         return (int) sizeof(struct snaphdr_t) - ETH_HLEN;
     }
@@ -1141,16 +1157,16 @@ static int translate_frame(ray_dev_t *local, struct tx_msg *ptx, unsigned char *
         DEBUG(3,"ray_cs translate_frame 802\n");
         if (proto == 0xffff) { /* evil netware IPX 802.3 without LLC */
         DEBUG(3,"ray_cs translate_frame evil IPX\n");
-            memcpy_toio((UCHAR *)&ptx->var, data + ETH_HLEN,  len - ETH_HLEN);
+            memcpy_toio(&ptx->var, data + ETH_HLEN,  len - ETH_HLEN);
             return 0 - ETH_HLEN;
         }
-        memcpy_toio((UCHAR *)&ptx->var, data + ETH_HLEN,  len - ETH_HLEN);
+        memcpy_toio(&ptx->var, data + ETH_HLEN,  len - ETH_HLEN);
         return 0 - ETH_HLEN;
     }
     /* TBD do other frame types */
 } /* end translate_frame */
 /*===========================================================================*/
-static void ray_build_header(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type,
+static void ray_build_header(ray_dev_t *local, struct tx_msg __iomem *ptx, UCHAR msg_type,
                 unsigned char *data)
 {
     writeb(PROTOCOL_VER | msg_type, &ptx->mac.frame_ctl_1);
@@ -1633,7 +1649,7 @@ static iw_stats * ray_get_wireless_stats(struct net_device *	dev)
 {
   ray_dev_t *	local = (ray_dev_t *) dev->priv;
   dev_link_t *link = local->finder;
-  struct status *p = (struct status *)(local->sram + STATUS_BASE);
+  struct status __iomem *p = local->sram + STATUS_BASE;
 
   if(local == (ray_dev_t *) NULL)
     return (iw_stats *) NULL;
@@ -1755,7 +1771,7 @@ static int interrupt_ecf(ray_dev_t *local, int ccs)
 static int get_free_tx_ccs(ray_dev_t *local)
 {
     int i;
-    struct ccs *pccs = (struct ccs *)(local->sram + CCS_BASE);
+    struct ccs __iomem *pccs = ccs_base(local);
     dev_link_t *link = local->finder;
 
     if (!(link->state & DEV_PRESENT)) {
@@ -1786,7 +1802,7 @@ static int get_free_tx_ccs(ray_dev_t *local)
 static int get_free_ccs(ray_dev_t *local)
 {
     int i;
-    struct ccs *pccs = (struct ccs *)(local->sram + CCS_BASE);
+    struct ccs __iomem *pccs = ccs_base(local);
     dev_link_t *link = local->finder;
 
     if (!(link->state & DEV_PRESENT)) {
@@ -1863,7 +1879,7 @@ static struct net_device_stats *ray_get_stats(struct net_device *dev)
 {
     ray_dev_t *local = (ray_dev_t *)dev->priv;
     dev_link_t *link = local->finder;
-    struct status *p = (struct status *)(local->sram + STATUS_BASE);
+    struct status __iomem *p = local->sram + STATUS_BASE;
     if (!(link->state & DEV_PRESENT)) {
         DEBUG(2,"ray_cs net_device_stats - device not present\n");
         return &local->stats;
@@ -1895,7 +1911,7 @@ static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, i
     dev_link_t *link = local->finder;
     int ccsindex;
     int i;
-    struct ccs *pccs;
+    struct ccs __iomem *pccs;
 
     if (!(link->state & DEV_PRESENT)) {
         DEBUG(2,"ray_update_parm - device not present\n");
@@ -1907,7 +1923,7 @@ static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, i
         DEBUG(0,"ray_update_parm - No free ccs\n");
         return;
     }
-    pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex;
+    pccs = ccs_base(local) + ccsindex;
     writeb(CCS_UPDATE_PARAMS, &pccs->cmd);
     writeb(objid, &pccs->var.update_param.object_id);
     writeb(1, &pccs->var.update_param.number_objects);
@@ -1926,11 +1942,11 @@ static void ray_update_multi_list(struct net_device *dev, int all)
 {
     struct dev_mc_list *dmi, **dmip;
     int ccsindex;
-    struct ccs *pccs;
+    struct ccs __iomem *pccs;
     int i = 0;
     ray_dev_t *local = (ray_dev_t *)dev->priv;
     dev_link_t *link = local->finder;
-    UCHAR *p = local->sram + HOST_TO_ECF_BASE;
+    void __iomem *p = local->sram + HOST_TO_ECF_BASE;
 
     if (!(link->state & DEV_PRESENT)) {
         DEBUG(2,"ray_update_multi_list - device not present\n");
@@ -1943,7 +1959,7 @@ static void ray_update_multi_list(struct net_device *dev, int all)
         DEBUG(1,"ray_update_multi - No free ccs\n");
         return;
     }
-    pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex;
+    pccs = ccs_base(local) + ccsindex;
     writeb(CCS_UPDATE_MULTICAST_LIST, &pccs->cmd);
 
     if (all) {
@@ -2011,8 +2027,8 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs)
     struct net_device *dev = (struct net_device *)dev_id;
     dev_link_t *link;
     ray_dev_t *local;
-    struct ccs *pccs;
-    struct rcs *prcs;
+    struct ccs __iomem *pccs;
+    struct rcs __iomem *prcs;
     UCHAR rcsindex;
     UCHAR tmp;
     UCHAR cmd;
@@ -2029,7 +2045,7 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs)
         DEBUG(2,"ray_cs interrupt from device not present or suspended.\n");
         return IRQ_NONE;
     }
-    rcsindex = readb(&((struct scb *)(local->sram))->rcs_index);
+    rcsindex = readb(&((struct scb __iomem *)(local->sram))->rcs_index);
 
     if (rcsindex >= (NUMBER_OF_CCS + NUMBER_OF_RCS))
     {
@@ -2039,7 +2055,7 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs)
     }
     if (rcsindex < NUMBER_OF_CCS) /* If it's a returned CCS */
     {
-        pccs = ((struct ccs *) (local->sram + CCS_BASE)) + rcsindex;
+        pccs = ccs_base(local) + rcsindex;
         cmd = readb(&pccs->cmd);
         status = readb(&pccs->buffer_status);
         switch (cmd)
@@ -2153,7 +2169,7 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs)
     }
     else /* It's an RCS */
     {
-        prcs = ((struct rcs *)(local->sram + CCS_BASE)) + rcsindex;
+        prcs = rcs_base(local) + rcsindex;
     
         switch (readb(&prcs->interrupt_id))
         {
@@ -2194,11 +2210,11 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs)
     return IRQ_HANDLED;
 } /* ray_interrupt */
 /*===========================================================================*/
-static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs)
+static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs __iomem *prcs)
 {
     int rx_len;
     unsigned int pkt_addr;
-    UCHAR *pmsg;
+    void __iomem *pmsg;
     DEBUG(4,"ray_rx process rx packet\n");
 
     /* Calculate address of packet within Rx buffer */
@@ -2248,11 +2264,11 @@ static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs)
 
 } /* end ray_rx */
 /*===========================================================================*/
-static void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr, 
+static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, unsigned int pkt_addr, 
              int rx_len)
 {
     struct sk_buff *skb = NULL;
-    struct rcs *prcslink = prcs;
+    struct rcs __iomem *prcslink = prcs;
     ray_dev_t *local = dev->priv;
     UCHAR *rx_ptr;
     int total_len;
@@ -2294,7 +2310,7 @@ static void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_a
                 +   readb(&prcslink->var.rx_packet.rx_data_length[1]);
             if (readb(&prcslink->var.rx_packet.next_frag_rcs_index) == 0xFF
                 || tmp < 0) break;
-            prcslink = ((struct rcs *)(local->sram + CCS_BASE))
+            prcslink = rcs_base(local)
                 + readb(&prcslink->link_field);
         } while (1);
 
@@ -2355,7 +2371,7 @@ static void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_a
         prcslink = prcs;
         DEBUG(1,"ray_cs rx_data in fragment loop\n");
         do {
-            prcslink = ((struct rcs *)(local->sram + CCS_BASE))
+            prcslink = rcs_base(local)
                 + readb(&prcslink->var.rx_packet.next_frag_rcs_index);
             rx_len = (( readb(&prcslink->var.rx_packet.rx_data_length[0]) << 8)
                       + readb(&prcslink->var.rx_packet.rx_data_length[1]))
@@ -2529,9 +2545,9 @@ static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int le
     return length;
 }
 /*===========================================================================*/
-static void release_frag_chain(ray_dev_t *local, struct rcs* prcs)
+static void release_frag_chain(ray_dev_t *local, struct rcs __iomem * prcs)
 {
-    struct rcs *prcslink = prcs;
+    struct rcs __iomem *prcslink = prcs;
     int tmp = 17;
     unsigned rcsindex = readb(&prcs->var.rx_packet.next_frag_rcs_index);
 
@@ -2541,7 +2557,7 @@ static void release_frag_chain(ray_dev_t *local, struct rcs* prcs)
             DEBUG(1,"ray_cs interrupt bad rcsindex = 0x%x\n",rcsindex);
             break;      
         }   
-        prcslink = ((struct rcs *)(local->sram + CCS_BASE)) + rcsindex;
+        prcslink = rcs_base(local) + rcsindex;
         rcsindex = readb(&prcslink->var.rx_packet.next_frag_rcs_index);
     }
     writeb(CCS_BUFFER_FREE, &prcslink->buffer_status);
@@ -2569,7 +2585,7 @@ static void authenticate(ray_dev_t *local)
     local->authentication_state = AWAITING_RESPONSE;
 } /* end authenticate */
 /*===========================================================================*/
-static void rx_authenticate(ray_dev_t *local, struct rcs *prcs,
+static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs,
                      unsigned int pkt_addr, int rx_len)
 {
     UCHAR buff[256];
@@ -2614,7 +2630,7 @@ static void rx_authenticate(ray_dev_t *local, struct rcs *prcs,
 /*===========================================================================*/
 static void associate(ray_dev_t *local)
 {
-    struct ccs *pccs;
+    struct ccs __iomem *pccs;
     dev_link_t *link = local->finder;
     struct net_device *dev = link->priv;
     int ccsindex;
@@ -2630,7 +2646,7 @@ static void associate(ray_dev_t *local)
         return;
     }
     DEBUG(1,"ray_cs Starting association with access point\n");
-    pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex;
+    pccs = ccs_base(local) + ccsindex;
     /* fill in the CCS */
     writeb(CCS_START_ASSOCIATION, &pccs->cmd);
     /* Interrupt the firmware to process the command */
@@ -2650,7 +2666,7 @@ static void associate(ray_dev_t *local)
 
 } /* end associate */
 /*===========================================================================*/
-static void rx_deauthenticate(ray_dev_t *local, struct rcs *prcs, 
+static void rx_deauthenticate(ray_dev_t *local, struct rcs __iomem *prcs, 
                        unsigned int pkt_addr, int rx_len)
 {
 /*  UCHAR buff[256];
@@ -2798,8 +2814,8 @@ static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len)
 static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type)
 {
     int addr;
-    struct ccs *pccs;
-    struct tx_msg *ptx;
+    struct ccs __iomem *pccs;
+    struct tx_msg __iomem *ptx;
     int ccsindex;
 
     /* If no tx buffers available, return */
@@ -2809,7 +2825,7 @@ static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type)
         return -1;
     }
 
-    pccs = ((struct ccs *)(local->sram + CCS_BASE)) + ccsindex;
+    pccs = ccs_base(local) + ccsindex;
 
     /* Address in card space */
     addr = TX_BUF_BASE + (ccsindex << 11);
@@ -2821,7 +2837,7 @@ static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type)
     writeb(TX_AUTHENTICATE_LENGTH_LSB,pccs->var.tx_request.tx_data_length + 1);
     writeb(0, &pccs->var.tx_request.pow_sav_mode);
 
-    ptx = (struct tx_msg *)(local->sram + addr);
+    ptx = local->sram + addr;
     /* fill in the mac header */
     writeb(PROTOCOL_VER | AUTHENTIC_TYPE, &ptx->mac.frame_ctl_1);
     writeb(0, &ptx->mac.frame_ctl_2);
@@ -2931,15 +2947,6 @@ static void __exit exit_ray_cs(void)
 {
     DEBUG(0, "ray_cs: cleanup_module\n");
 
-
-#ifdef CONFIG_PROC_FS
-    remove_proc_entry("ray_cs", proc_root_driver);
-#endif
-
-    pcmcia_unregister_driver(&ray_driver);
-    while (dev_list != NULL)
-        ray_detach(dev_list);
-
 #ifdef CONFIG_PROC_FS
     remove_proc_entry("driver/ray_cs/ray_cs", NULL);
     remove_proc_entry("driver/ray_cs/essid", NULL);
@@ -2947,6 +2954,10 @@ static void __exit exit_ray_cs(void)
     remove_proc_entry("driver/ray_cs/translate", NULL);
     remove_proc_entry("driver/ray_cs", NULL);
 #endif
+
+    pcmcia_unregister_driver(&ray_driver);
+    while (dev_list != NULL)
+        ray_detach(dev_list);
 } /* exit_ray_cs */
 
 module_init(init_ray_cs);
diff --git a/drivers/net/wireless/ray_cs.h b/drivers/net/wireless/ray_cs.h
index 6d4985061..c77afa14f 100644
--- a/drivers/net/wireless/ray_cs.h
+++ b/drivers/net/wireless/ray_cs.h
@@ -28,9 +28,9 @@ typedef struct ray_dev_t {
     dev_node_t  node;
     window_handle_t amem_handle;   /* handle to window for attribute memory  */
     window_handle_t rmem_handle;   /* handle to window for rx buffer on card */
-    UCHAR *sram;                   /* pointer to beginning of shared RAM     */
-    UCHAR *amem;                   /* pointer to attribute mem window        */
-    UCHAR *rmem;                   /* pointer to receive buffer window       */
+    void __iomem *sram;            /* pointer to beginning of shared RAM     */
+    void __iomem *amem;            /* pointer to attribute mem window        */
+    void __iomem *rmem;            /* pointer to receive buffer window       */
     dev_link_t *finder;            /* pointer back to dev_link_t for card    */
     struct timer_list timer;
     long tx_ccs_lock;
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index 98cee21f7..7f44588cb 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -106,6 +106,7 @@ static const char StripVersion[] = "1.3A-STUART.CHESHIRE";
 #include <linux/seq_file.h>
 #include <linux/serial.h>
 #include <linux/serialP.h>
+#include <linux/rcupdate.h>
 #include <net/arp.h>
 
 #include <linux/ip.h>
@@ -1348,14 +1349,17 @@ static unsigned char *strip_make_packet(unsigned char *buffer,
 	 */
 	if (haddr.c[0] == 0xFF) {
 		u32 brd = 0;
-		struct in_device *in_dev = in_dev_get(strip_info->dev);
-		if (in_dev == NULL)
+		struct in_device *in_dev;
+
+		rcu_read_lock();
+		in_dev = __in_dev_get(strip_info->dev);
+		if (in_dev == NULL) {
+			rcu_read_unlock();
 			return NULL;
-		read_lock(&in_dev->lock);
+		}
 		if (in_dev->ifa_list)
 			brd = in_dev->ifa_list->ifa_broadcast;
-		read_unlock(&in_dev->lock);
-		in_dev_put(in_dev);
+		rcu_read_unlock();
 
 		/* arp_query returns 1 if it succeeds in looking up the address, 0 if it fails */
 		if (!arp_query(haddr.c, brd, strip_info->dev)) {
@@ -1500,17 +1504,18 @@ static void strip_send(struct strip *strip_info, struct sk_buff *skb)
 	}
 
 	if (1) {
-		struct in_device *in_dev = in_dev_get(strip_info->dev);
+		struct in_device *in_dev;
+
 		brd = addr = 0;
+		rcu_read_lock();
+		in_dev = __in_dev_get(strip_info->dev);
 		if (in_dev) {
-			read_lock(&in_dev->lock);
 			if (in_dev->ifa_list) {
 				brd = in_dev->ifa_list->ifa_broadcast;
 				addr = in_dev->ifa_list->ifa_local;
 			}
-			read_unlock(&in_dev->lock);
-			in_dev_put(in_dev);
 		}
+		rcu_read_unlock();
 	}
 
 
@@ -2661,8 +2666,6 @@ static int strip_open(struct tty_struct *tty)
 	tty->disc_data = strip_info;
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
 
 	/*
 	 * Restore default settings
diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
index 1cbd34ba5..3047d8cfa 100644
--- a/drivers/net/wireless/wavelan.c
+++ b/drivers/net/wireless/wavelan.c
@@ -3822,17 +3822,18 @@ static irqreturn_t wavelan_interrupt(int irq, void *dev_id, struct pt_regs *regs
 	if ((hasr & HASR_MMC_INTR) && (lp->hacr & HACR_MMC_INT_ENABLE)) {
 		u8 dce_status;
 
-#ifdef DEBUG_INTERRUPT_ERROR
-		printk(KERN_INFO
-		       "%s: wavelan_interrupt(): unexpected mmc interrupt: status 0x%04x.\n",
-		       dev->name, dce_status);
-#endif
 		/*
 		 * Interrupt from the modem management controller.
 		 * This will clear it -- ignored for now.
 		 */
 		mmc_read(ioaddr, mmroff(0, mmr_dce_status), &dce_status,
 			 sizeof(dce_status));
+
+#ifdef DEBUG_INTERRUPT_ERROR
+		printk(KERN_INFO
+		       "%s: wavelan_interrupt(): unexpected mmc interrupt: status 0x%04x.\n",
+		       dev->name, dce_status);
+#endif
 	}
 
 	/* Check if not controller interrupt */
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
index e5d06ea62..884a53243 100644
--- a/drivers/oprofile/buffer_sync.c
+++ b/drivers/oprofile/buffer_sync.c
@@ -32,61 +32,65 @@
 #include "cpu_buffer.h"
 #include "buffer_sync.h"
  
-#define DEFAULT_EXPIRE (HZ / 4)
- 
-static void wq_sync_buffers(void *);
-static DECLARE_WORK(sync_wq, wq_sync_buffers, NULL);
- 
-static struct timer_list sync_timer;
-static void timer_ping(unsigned long data);
-static void sync_cpu_buffers(void);
+static LIST_HEAD(dying_tasks);
+static LIST_HEAD(dead_tasks);
+cpumask_t marked_cpus = CPU_MASK_NONE;
+static spinlock_t task_mortuary = SPIN_LOCK_UNLOCKED;
+void process_task_mortuary(void);
 
- 
-/* We must make sure to process every entry in the CPU buffers
- * before a task got the PF_EXITING flag, otherwise we will hold
- * references to a possibly freed task_struct. We are safe with
- * samples past the PF_EXITING point in do_exit(), because we
- * explicitly check for that in cpu_buffer.c 
+
+/* Take ownership of the task struct and place it on the
+ * list for processing. Only after two full buffer syncs
+ * does the task eventually get freed, because by then
+ * we are sure we will not reference it again.
  */
-static int exit_task_notify(struct notifier_block * self, unsigned long val, void * data)
+static int task_free_notify(struct notifier_block * self, unsigned long val, void * data)
 {
-	sync_cpu_buffers();
-	return 0;
+	struct task_struct * task = (struct task_struct *)data;
+	spin_lock(&task_mortuary);
+	list_add(&task->tasks, &dying_tasks);
+	spin_unlock(&task_mortuary);
+	return NOTIFY_OK;
 }
- 
-/* There are two cases of tasks modifying task->mm->mmap list we
- * must concern ourselves with. First, when a task is about to
- * exit (exit_mmap()), we should process the buffer to deal with
- * any samples in the CPU buffer, before we lose the ->mmap information
- * we need. It is vital to get this case correct, otherwise we can
- * end up trying to access a freed task_struct.
+
+
+/* The task is on its way out. A sync of the buffer means we can catch
+ * any remaining samples for this task.
  */
-static int mm_notify(struct notifier_block * self, unsigned long val, void * data)
+static int task_exit_notify(struct notifier_block * self, unsigned long val, void * data)
 {
-	sync_cpu_buffers();
-	return 0;
+	/* To avoid latency problems, we only process the current CPU,
+	 * hoping that most samples for the task are on this CPU
+	 */
+	sync_buffer(smp_processor_id());
+  	return 0;
 }
 
 
-/* Second, a task may unmap (part of) an executable mmap,
- * so we want to process samples before that happens too. This is merely
- * a QOI issue not a correctness one.
+/* The task is about to try a do_munmap(). We peek at what it's going to
+ * do, and if it's an executable region, process the samples first, so
+ * we don't lose any. This does not have to be exact, it's a QoI issue
+ * only.
  */
 static int munmap_notify(struct notifier_block * self, unsigned long val, void * data)
 {
-	/* Note that we cannot sync the buffers directly, because we might end up
-	 * taking the the mmap_sem that we hold now inside of event_buffer_read()
-	 * on a page fault, whilst holding buffer_sem - deadlock.
-	 *
-	 * This would mean a threaded reader of the event buffer, but we should
-	 * prevent it anyway.
-	 *
-	 * Delaying the work in a context that doesn't hold the mmap_sem means
-	 * that we won't lose samples from other mappings that current() may
-	 * have. Note that either way, we lose any pending samples for what is
-	 * being unmapped.
-	 */
-	schedule_work(&sync_wq);
+	unsigned long addr = (unsigned long)data;
+	struct mm_struct * mm = current->mm;
+	struct vm_area_struct * mpnt;
+
+	down_read(&mm->mmap_sem);
+
+	mpnt = find_vma(mm, addr);
+	if (mpnt && mpnt->vm_file && (mpnt->vm_flags & VM_EXEC)) {
+		up_read(&mm->mmap_sem);
+		/* To avoid latency problems, we only process the current CPU,
+		 * hoping that most samples for the task are on this CPU
+		 */
+		sync_buffer(smp_processor_id());
+		return 0;
+	}
+
+	up_read(&mm->mmap_sem);
 	return 0;
 }
 
@@ -100,7 +104,7 @@ static int module_load_notify(struct notifier_block * self, unsigned long val, v
 	if (val != MODULE_STATE_COMING)
 		return 0;
 
-	sync_cpu_buffers();
+	/* FIXME: should we process all CPU buffers ? */
 	down(&buffer_sem);
 	add_event_entry(ESCAPE_CODE);
 	add_event_entry(MODULE_LOADED_CODE);
@@ -110,16 +114,16 @@ static int module_load_notify(struct notifier_block * self, unsigned long val, v
 }
 
  
-static struct notifier_block exit_task_nb = {
-	.notifier_call	= exit_task_notify,
+static struct notifier_block task_free_nb = {
+	.notifier_call	= task_free_notify,
 };
 
-static struct notifier_block exec_unmap_nb = {
-	.notifier_call	= munmap_notify,
+static struct notifier_block task_exit_nb = {
+	.notifier_call	= task_exit_notify,
 };
 
-static struct notifier_block exit_mmap_nb = {
-	.notifier_call	= mm_notify,
+static struct notifier_block munmap_nb = {
+	.notifier_call	= munmap_notify,
 };
 
 static struct notifier_block module_load_nb = {
@@ -127,11 +131,12 @@ static struct notifier_block module_load_nb = {
 };
 
  
-static void end_sync_timer(void)
+static void end_sync(void)
 {
-	del_timer_sync(&sync_timer);
-	/* timer might have queued work, make sure it's completed. */
-	flush_scheduled_work();
+	end_cpu_work();
+	/* make sure we don't leak task structs */
+	process_task_mortuary();
+	process_task_mortuary();
 }
 
 
@@ -139,18 +144,15 @@ int sync_start(void)
 {
 	int err;
 
-	init_timer(&sync_timer);
-	sync_timer.function = timer_ping;
-	sync_timer.expires = jiffies + DEFAULT_EXPIRE;
-	add_timer(&sync_timer);
+	start_cpu_work();
 
-	err = profile_event_register(EXIT_TASK, &exit_task_nb);
+	err = task_handoff_register(&task_free_nb);
 	if (err)
 		goto out1;
-	err = profile_event_register(EXIT_MMAP, &exit_mmap_nb);
+	err = profile_event_register(PROFILE_TASK_EXIT, &task_exit_nb);
 	if (err)
 		goto out2;
-	err = profile_event_register(EXEC_UNMAP, &exec_unmap_nb);
+	err = profile_event_register(PROFILE_MUNMAP, &munmap_nb);
 	if (err)
 		goto out3;
 	err = register_module_notifier(&module_load_nb);
@@ -160,13 +162,13 @@ int sync_start(void)
 out:
 	return err;
 out4:
-	profile_event_unregister(EXEC_UNMAP, &exec_unmap_nb);
+	profile_event_unregister(PROFILE_MUNMAP, &munmap_nb);
 out3:
-	profile_event_unregister(EXIT_MMAP, &exit_mmap_nb);
+	profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb);
 out2:
-	profile_event_unregister(EXIT_TASK, &exit_task_nb);
+	task_handoff_unregister(&task_free_nb);
 out1:
-	end_sync_timer();
+	end_sync();
 	goto out;
 }
 
@@ -174,10 +176,10 @@ out1:
 void sync_stop(void)
 {
 	unregister_module_notifier(&module_load_nb);
-	profile_event_unregister(EXIT_TASK, &exit_task_nb);
-	profile_event_unregister(EXIT_MMAP, &exit_mmap_nb);
-	profile_event_unregister(EXEC_UNMAP, &exec_unmap_nb);
-	end_sync_timer();
+	profile_event_unregister(PROFILE_MUNMAP, &munmap_nb);
+	profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb);
+	task_handoff_unregister(&task_free_nb);
+	end_sync();
 }
 
  
@@ -337,40 +339,25 @@ static void add_sample(struct mm_struct * mm, struct op_sample * s, int in_kerne
 	}
 }
  
- 
+
 static void release_mm(struct mm_struct * mm)
 {
-	if (mm)
-		up_read(&mm->mmap_sem);
+	if (!mm)
+		return;
+	up_read(&mm->mmap_sem);
+	mmput(mm);
 }
 
 
-/* Take the task's mmap_sem to protect ourselves from
- * races when we do lookup_dcookie().
- */
 static struct mm_struct * take_tasks_mm(struct task_struct * task)
 {
-	struct mm_struct * mm;
-       
-	/* Subtle. We don't need to keep a reference to this task's mm,
-	 * because, for the mm to be freed on another CPU, that would have
-	 * to go through the task exit notifier, which ends up sleeping
-	 * on the buffer_sem we hold, so we end up with mutual exclusion
-	 * anyway.
-	 */
-	task_lock(task);
-	mm = task->mm;
-	task_unlock(task);
- 
-	if (mm) {
-		/* needed to walk the task's VMAs */
+	struct mm_struct * mm = get_task_mm(task);
+	if (mm)
 		down_read(&mm->mmap_sem);
-	}
- 
 	return mm;
 }
- 
- 
+
+
 static inline int is_ctx_switch(unsigned long val)
 {
 	return val == ~0UL;
@@ -417,24 +404,80 @@ static void increment_tail(struct oprofile_cpu_buffer * b)
 }
 
 
+/* Move tasks along towards death. Any tasks on dead_tasks
+ * will definitely have no remaining references in any
+ * CPU buffers at this point, because we use two lists,
+ * and to have reached the list, it must have gone through
+ * one full sync already.
+ */
+void process_task_mortuary(void)
+{
+	struct list_head * pos;
+	struct list_head * pos2;
+	struct task_struct * task;
+
+	spin_lock(&task_mortuary);
+
+	list_for_each_safe(pos, pos2, &dead_tasks) {
+		task = list_entry(pos, struct task_struct, tasks);
+		list_del(&task->tasks);
+		free_task(task);
+	}
+
+	list_for_each_safe(pos, pos2, &dying_tasks) {
+		task = list_entry(pos, struct task_struct, tasks);
+		list_del(&task->tasks);
+		list_add_tail(&task->tasks, &dead_tasks);
+	}
+
+	spin_unlock(&task_mortuary);
+}
+
+
+static void mark_done(int cpu)
+{
+	int i;
+
+	cpu_set(cpu, marked_cpus);
+
+	for_each_online_cpu(i) {
+		if (!cpu_isset(i, marked_cpus))
+			return;
+	}
+
+	/* All CPUs have been processed at least once,
+	 * we can process the mortuary once
+	 */
+	process_task_mortuary();
+
+	cpus_clear(marked_cpus);
+}
+
+
 /* Sync one of the CPU's buffers into the global event buffer.
  * Here we need to go through each batch of samples punctuated
  * by context switch notes, taking the task's mmap_sem and doing
  * lookup in task->mm->mmap to convert EIP into dcookie/offset
  * value.
  */
-static void sync_buffer(struct oprofile_cpu_buffer * cpu_buf)
+void sync_buffer(int cpu)
 {
+	struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[cpu];
 	struct mm_struct *mm = NULL;
 	struct task_struct * new;
 	unsigned long cookie = 0;
 	int in_kernel = 1;
 	unsigned int i;
+	unsigned long available;
+
+	down(&buffer_sem);
  
+	add_cpu_switch(cpu);
+
 	/* Remember, only we can modify tail_pos */
 
-	unsigned long const available = get_slots(cpu_buf);
-  
+	available = get_slots(cpu_buf);
+
 	for (i=0; i < available; ++i) {
 		struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos];
  
@@ -462,50 +505,8 @@ static void sync_buffer(struct oprofile_cpu_buffer * cpu_buf)
 		increment_tail(cpu_buf);
 	}
 	release_mm(mm);
-}
- 
- 
-/* Process each CPU's local buffer into the global
- * event buffer.
- */
-static void sync_cpu_buffers(void)
-{
-	int i;
 
-	down(&buffer_sem);
- 
-	for (i = 0; i < NR_CPUS; ++i) {
-		struct oprofile_cpu_buffer * cpu_buf;
- 
-		if (!cpu_possible(i))
-			continue;
- 
-		cpu_buf = &cpu_buffer[i];
- 
-		add_cpu_switch(i);
-		sync_buffer(cpu_buf);
-	}
+	mark_done(cpu);
 
 	up(&buffer_sem);
- 
-	mod_timer(&sync_timer, jiffies + DEFAULT_EXPIRE);
-}
- 
-
-static void wq_sync_buffers(void * data)
-{
-	sync_cpu_buffers();
-}
- 
- 
-/* It is possible that we could have no munmap() or
- * other events for a period of time. This will lead
- * the CPU buffers to overflow and lose samples and
- * context switches. We try to reduce the problem
- * by timing out when nothing happens for a while.
- */
-static void timer_ping(unsigned long data)
-{
-	schedule_work(&sync_wq);
-	/* timer is re-added by the scheduled task */
 }
diff --git a/drivers/oprofile/buffer_sync.h b/drivers/oprofile/buffer_sync.h
index a8def27d8..08866f6a9 100644
--- a/drivers/oprofile/buffer_sync.h
+++ b/drivers/oprofile/buffer_sync.h
@@ -16,4 +16,7 @@ int sync_start(void);
 /* remove the hooks */
 void sync_stop(void);
  
+/* sync the given CPU's buffer */
+void sync_buffer(int cpu);
+
 #endif /* OPROFILE_BUFFER_SYNC_H */
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
index 7ee6a3d99..420dc8e83 100644
--- a/drivers/oprofile/cpu_buffer.c
+++ b/drivers/oprofile/cpu_buffer.c
@@ -9,7 +9,7 @@
  * Each CPU has a local buffer that stores PC value/event
  * pairs. We also log context switches when we notice them.
  * Eventually each CPU's buffer is processed into the global
- * event buffer by sync_cpu_buffers().
+ * event buffer by sync_buffer().
  *
  * We use a local buffer for two reasons: an NMI or similar
  * interrupt cannot synchronise, and high sampling rates
@@ -22,21 +22,23 @@
 #include <linux/errno.h>
  
 #include "cpu_buffer.h"
+#include "buffer_sync.h"
 #include "oprof.h"
 
 struct oprofile_cpu_buffer cpu_buffer[NR_CPUS] __cacheline_aligned;
 
+static void wq_sync_buffer(void *);
+
+#define DEFAULT_TIMER_EXPIRE (HZ / 10)
+int work_enabled;
+
 static void __free_cpu_buffers(int num)
 {
 	int i;
  
-	for (i=0; i < num; ++i) {
-		struct oprofile_cpu_buffer * b = &cpu_buffer[i];
- 
-		if (!cpu_possible(i)) 
-			continue;
- 
-		vfree(b->buffer);
+	for_each_online_cpu(i) {
+		if (cpu_buffer[i].buffer)
+			vfree(cpu_buffer[i].buffer);
 	}
 }
  
@@ -47,12 +49,9 @@ int alloc_cpu_buffers(void)
  
 	unsigned long buffer_size = fs_cpu_buffer_size;
  
-	for (i=0; i < NR_CPUS; ++i) {
+	for_each_online_cpu(i) {
 		struct oprofile_cpu_buffer * b = &cpu_buffer[i];
  
-		if (!cpu_possible(i)) 
-			continue;
- 
 		b->buffer = vmalloc(sizeof(struct op_sample) * buffer_size);
 		if (!b->buffer)
 			goto fail;
@@ -64,9 +63,11 @@ int alloc_cpu_buffers(void)
 		b->head_pos = 0;
 		b->sample_received = 0;
 		b->sample_lost_overflow = 0;
-		b->sample_lost_task_exit = 0;
+		b->cpu = i;
+		INIT_WORK(&b->work, wq_sync_buffer, b);
 	}
 	return 0;
+
 fail:
 	__free_cpu_buffers(i);
 	return -ENOMEM;
@@ -79,6 +80,40 @@ void free_cpu_buffers(void)
 }
 
 
+void start_cpu_work(void)
+{
+	int i;
+
+	work_enabled = 1;
+
+	for_each_online_cpu(i) {
+		struct oprofile_cpu_buffer * b = &cpu_buffer[i];
+
+		/*
+		 * Spread the work by 1 jiffy per cpu so they dont all
+		 * fire at once.
+		 */
+		schedule_delayed_work_on(i, &b->work, DEFAULT_TIMER_EXPIRE + i);
+	}
+}
+
+
+void end_cpu_work(void)
+{
+	int i;
+
+	work_enabled = 0;
+
+	for_each_online_cpu(i) {
+		struct oprofile_cpu_buffer * b = &cpu_buffer[i];
+
+		cancel_delayed_work(&b->work);
+	}
+
+	flush_scheduled_work();
+}
+
+
 /* compute number of available slots in cpu_buffer queue */
 static unsigned long nr_available_slots(struct oprofile_cpu_buffer const * b)
 {
@@ -145,21 +180,9 @@ void oprofile_add_sample(unsigned long eip, unsigned int is_kernel,
 	/* notice a task switch */
 	if (cpu_buf->last_task != task) {
 		cpu_buf->last_task = task;
-		if (!(task->flags & PF_EXITING)) {
-			cpu_buf->buffer[cpu_buf->head_pos].eip = ~0UL;
-			cpu_buf->buffer[cpu_buf->head_pos].event = (unsigned long)task;
-			increment_head(cpu_buf);
-		}
-	}
- 
-	/* If the task is exiting it's not safe to take a sample
-	 * as the task_struct is about to be freed. We can't just
-	 * notify at release_task() time because of CLONE_DETACHED
-	 * tasks that release_task() themselves.
-	 */
-	if (task->flags & PF_EXITING) {
-		cpu_buf->sample_lost_task_exit++;
-		return;
+		cpu_buf->buffer[cpu_buf->head_pos].eip = ~0UL;
+		cpu_buf->buffer[cpu_buf->head_pos].event = (unsigned long)task;
+		increment_head(cpu_buf);
 	}
  
 	cpu_buf->buffer[cpu_buf->head_pos].eip = eip;
@@ -178,3 +201,25 @@ void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf)
 	cpu_buf->last_is_kernel = -1;
 	cpu_buf->last_task = NULL;
 }
+
+
+/*
+ * This serves to avoid cpu buffer overflow, and makes sure
+ * the task mortuary progresses
+ *
+ * By using schedule_delayed_work_on and then schedule_delayed_work
+ * we guarantee this will stay on the correct cpu
+ */
+static void wq_sync_buffer(void * data)
+{
+	struct oprofile_cpu_buffer * b = (struct oprofile_cpu_buffer *)data;
+	if (b->cpu != smp_processor_id()) {
+		printk("WQ on CPU%d, prefer CPU%d\n",
+		       smp_processor_id(), b->cpu);
+	}
+	sync_buffer(b->cpu);
+
+	/* don't re-add the work if we're shutting down */
+	if (work_enabled)
+		schedule_delayed_work(&b->work, DEFAULT_TIMER_EXPIRE);
+}
diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h
index 66eafcdb1..23be2013a 100644
--- a/drivers/oprofile/cpu_buffer.h
+++ b/drivers/oprofile/cpu_buffer.h
@@ -12,15 +12,17 @@
 
 #include <linux/types.h>
 #include <linux/spinlock.h>
+#include <linux/workqueue.h>
 #include <linux/cache.h>
  
 struct task_struct;
  
-/* allocate a sample buffer for each CPU */
 int alloc_cpu_buffers(void);
-
 void free_cpu_buffers(void);
 
+void start_cpu_work(void);
+void end_cpu_work(void);
+
 /* CPU buffer is composed of such entries (which are
  * also used for context switch notes)
  */
@@ -38,11 +40,12 @@ struct oprofile_cpu_buffer {
 	struct op_sample * buffer;
 	unsigned long sample_received;
 	unsigned long sample_lost_overflow;
-	unsigned long sample_lost_task_exit;
+	int cpu;
+	struct work_struct work;
 } ____cacheline_aligned;
 
 extern struct oprofile_cpu_buffer cpu_buffer[];
 
-void cpu_buffer_reset(struct oprofile_cpu_buffer *cpu_buf);
+void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf);
 
 #endif /* OPROFILE_CPU_BUFFER_H */
diff --git a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c
index 8e92b0388..3ec23d8a6 100644
--- a/drivers/oprofile/oprofile_stats.c
+++ b/drivers/oprofile/oprofile_stats.c
@@ -22,14 +22,10 @@ void oprofile_reset_stats(void)
 	struct oprofile_cpu_buffer * cpu_buf; 
 	int i;
  
-	for (i = 0; i < NR_CPUS; ++i) {
-		if (!cpu_possible(i))
-			continue;
-
+	for_each_cpu(i) {
 		cpu_buf = &cpu_buffer[i]; 
 		cpu_buf->sample_received = 0;
 		cpu_buf->sample_lost_overflow = 0;
-		cpu_buf->sample_lost_task_exit = 0;
 	}
  
 	atomic_set(&oprofile_stats.sample_lost_no_mm, 0);
@@ -50,10 +46,7 @@ void oprofile_create_stats_files(struct super_block * sb, struct dentry * root)
 	if (!dir)
 		return;
 
-	for (i = 0; i < NR_CPUS; ++i) {
-		if (!cpu_possible(i))
-			continue;
-
+	for_each_cpu(i) {
 		cpu_buf = &cpu_buffer[i]; 
 		snprintf(buf, 10, "cpu%d", i);
 		cpudir = oprofilefs_mkdir(sb, dir, buf);
@@ -66,8 +59,6 @@ void oprofile_create_stats_files(struct super_block * sb, struct dentry * root)
 			&cpu_buf->sample_received);
 		oprofilefs_create_ro_ulong(sb, cpudir, "sample_lost_overflow",
 			&cpu_buf->sample_lost_overflow);
-		oprofilefs_create_ro_ulong(sb, cpudir, "sample_lost_task_exit",
-			&cpu_buf->sample_lost_task_exit);
 	}
  
 	oprofilefs_create_ro_atomic(sb, dir, "sample_lost_no_mm",
diff --git a/drivers/oprofile/timer_int.c b/drivers/oprofile/timer_int.c
index 3fae2c772..5f0318908 100644
--- a/drivers/oprofile/timer_int.c
+++ b/drivers/oprofile/timer_int.c
@@ -19,7 +19,7 @@ static int timer_notify(struct notifier_block * self, unsigned long val, void *
 {
 	struct pt_regs * regs = (struct pt_regs *)data;
 	int cpu = smp_processor_id();
-	unsigned long eip = instruction_pointer(regs);
+	unsigned long eip = profile_pc(regs);
  
 	oprofile_add_sample(eip, !user_mode(regs), 0, cpu);
 	return 0;
diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c
index 6e67ea060..45f2be4cc 100644
--- a/drivers/parisc/lasi.c
+++ b/drivers/parisc/lasi.c
@@ -11,7 +11,7 @@
  *      (at your option) any later version.
  *
  *	by Alan Cox <alan@redhat.com> and 
- * 	   Alex deVries <adevries@thepuffingroup.com> 
+ * 	   Alex deVries <alex@onefishtwo.ca>
  */
 
 #include <linux/errno.h>
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index 6357ec10e..0e1426ccd 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -8,7 +8,7 @@
  *	(C) Copyright 2000 Linuxcare, Inc.
  * 	(C) Copyright 2000 Linuxcare Canada, Inc.
  *	(C) Copyright 2000 Martin K. Petersen <mkp@linuxcare.com>
- * 	(C) Copyright 2000 Alex deVries <alex@linuxcare.com>
+ * 	(C) Copyright 2000 Alex deVries <alex@onefishtwo.ca>
  *      (C) Copyright 2001 John Marvin <jsm fc hp com>
  *      (C) Copyright 2003 Grant Grundler <grundler parisc-linux org>
  *
@@ -484,6 +484,7 @@ void superio_fixup_pci(struct pci_dev *pdev)
 	pci_read_config_byte(pdev, PCI_CLASS_PROG, &prog);
 	printk("PCI: Enabled native mode for NS87415 (pif=0x%x)\n", prog);
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415, superio_fixup_pci);
 
 /* Because of a defect in Super I/O, all reads of the PCI DMA status 
  * registers, IDE status register and the IDE select register need to be 
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index dfc8a8404..5b550ab81 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -1194,7 +1194,7 @@ struct parport_operations parport_pc_ops =
 
 #ifdef CONFIG_PARPORT_PC_SUPERIO
 /* Super-IO chipset detection, Winbond, SMSC */
-static void __devinit show_parconfig_smsc37c669(int io, int key)
+static int __devinit show_parconfig_smsc37c669(int io, int key)
 {
 	int cr1,cr4,cra,cr23,cr26,cr27,i=0;
 	static const char *modes[]={ "SPP and Bidirectional (PS/2)",	
@@ -1261,17 +1261,26 @@ static void __devinit show_parconfig_smsc37c669(int io, int key)
 					superios[i].io = 0x278;
 					superios[i].irq = 5;
 			}
+			if (io != superios[i].io) {
+				/* how many bytes? */
+				if (!request_region(superios[i].io, 3, "smsc parport")) {
+					superios[i].io = 0;
+					return 0;
+				}
+			}
 			d=(cr26 &0x0f);
 			if((d==1) || (d==3)) 
 				superios[i].dma= d;
 			else
 				superios[i].dma= PARPORT_DMA_NONE;
+			return 1;
 		}
  	}
+	return 0;
 }
 
 
-static void __devinit show_parconfig_winbond(int io, int key)
+static int __devinit show_parconfig_winbond(int io, int key)
 {
 	int cr30,cr60,cr61,cr70,cr74,crf0,i=0;
 	static const char *modes[] = {
@@ -1327,14 +1336,23 @@ static void __devinit show_parconfig_winbond(int io, int key)
 			printk(KERN_INFO "Super-IO: too many chips!\n");
 		else {
 			superios[i].io = (cr60<<8)|cr61;
+			if (io != superios[i].io) {
+				/* how many bytes? */
+				if (!request_region(superios[i].io, 3, "winbond parport")) {
+					superios[i].io = 0;
+					return 0;
+				}
+			}
 			superios[i].irq = cr70&0x0f;
 			superios[i].dma = (((cr74 & 0x07) > 3) ?
 					   PARPORT_DMA_NONE : (cr74 & 0x07));
+			return 1;
 		}
 	}
+	return 0;
 }
 
-static void __devinit decode_winbond(int efer, int key, int devid, int devrev, int oldid)
+static int __devinit decode_winbond(int efer, int key, int devid, int devrev, int oldid)
 {
 	const char *type = "unknown";
 	int id,progif=2;
@@ -1342,7 +1360,7 @@ static void __devinit decode_winbond(int efer, int key, int devid, int devrev, i
 	if (devid == devrev)
 		/* simple heuristics, we happened to read some
                    non-winbond register */
-		return;
+		return 0;
 
 	id=(devid<<8) | devrev;
 
@@ -1367,19 +1385,20 @@ static void __devinit decode_winbond(int efer, int key, int devid, int devrev, i
 		       efer, key, devid, devrev, oldid, type);
 
 	if (progif == 2)
-		show_parconfig_winbond(efer,key);
+		return show_parconfig_winbond(efer,key);
+	return 0;
 }
 
-static void __devinit decode_smsc(int efer, int key, int devid, int devrev)
+static int __devinit decode_smsc(int efer, int key, int devid, int devrev)
 {
         const char *type = "unknown";
-	void (*func)(int io, int key);
+	int (*func)(int io, int key);
         int id;
 
         if (devid == devrev)
 		/* simple heuristics, we happened to read some
                    non-smsc register */
-		return;
+		return 0;
 
 	func=NULL;
         id=(devid<<8) | devrev;
@@ -1395,7 +1414,8 @@ static void __devinit decode_smsc(int efer, int key, int devid, int devrev)
 		       efer, key, devid, devrev, type);
 
 	if (func)
-		func(efer,key);
+		return func(efer,key);
+	return 0;
 }
 
 
@@ -1403,6 +1423,9 @@ static void __devinit winbond_check(int io, int key)
 {
 	int devid,devrev,oldid,x_devid,x_devrev,x_oldid;
 
+	if (!request_region(io, 3, __FUNCTION__))
+		return;
+
 	/* First probe without key */
 	outb(0x20,io);
 	x_devid=inb(io+1);
@@ -1423,15 +1446,21 @@ static void __devinit winbond_check(int io, int key)
 	outb(0xaa,io);    /* Magic Seal */
 
 	if ((x_devid == devid) && (x_devrev == devrev) && (x_oldid == oldid))
-		return; /* protection against false positives */
+		goto out; /* protection against false positives */
 
-	decode_winbond(io,key,devid,devrev,oldid);
+	if (decode_winbond(io,key,devid,devrev,oldid));
+		return;
+out:
+	release_region(io, 3);
 }
 
 static void __devinit winbond_check2(int io,int key)
 {
         int devid,devrev,oldid,x_devid,x_devrev,x_oldid;
 
+	if (!request_region(io, 3, __FUNCTION__))
+		return;
+
 	/* First probe without the key */
 	outb(0x20,io+2);
 	x_devid=inb(io+2);
@@ -1451,15 +1480,21 @@ static void __devinit winbond_check2(int io,int key)
         outb(0xaa,io);    /* Magic Seal */
 
 	if ((x_devid == devid) && (x_devrev == devrev) && (x_oldid == oldid))
-		return; /* protection against false positives */
+		goto out; /* protection against false positives */
 
-        decode_winbond(io,key,devid,devrev,oldid);
+        if (decode_winbond(io,key,devid,devrev,oldid))
+		return;
+out:
+	release_region(io, 3);
 }
 
 static void __devinit smsc_check(int io, int key)
 {
         int id,rev,oldid,oldrev,x_id,x_rev,x_oldid,x_oldrev;
 
+	if (!request_region(io, 3, __FUNCTION__))
+		return;
+
 	/* First probe without the key */
 	outb(0x0d,io);
 	x_oldid=inb(io+1);
@@ -1485,9 +1520,12 @@ static void __devinit smsc_check(int io, int key)
 
 	if ((x_id == id) && (x_oldrev == oldrev) &&
 	    (x_oldid == oldid) && (x_rev == rev))
-		return; /* protection against false positives */
+		goto out; /* protection against false positives */
 
-        decode_smsc(io,key,oldid,oldrev);
+        if (decode_smsc(io,key,oldid,oldrev))
+		return;
+out:
+	release_region(io, 3);
 }
 
 
@@ -2636,6 +2674,10 @@ enum parport_pc_pci_cards {
 	netmos_9805,
 	netmos_9815,
 	netmos_9855,
+	netmos_9735,
+	netmos_9835,
+	netmos_9755,
+	netmos_9715
 };
 
 
@@ -2709,6 +2751,10 @@ static struct parport_pc_pci {
 	/* netmos_9805 */               { 1, { { 0, -1 }, } }, /* untested */
 	/* netmos_9815 */               { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */
 	/* netmos_9855 */               { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */
+	/* netmos_9735 */               { 1, { { 2, 3 }, } },  /* untested */
+	/* netmos_9835 */               { 1, { { 2, 3 }, } },  /* untested */
+        /* netmos_9755 */               { 2, { { 0, 1 }, { 2, 3 },} }, /* untested */
+        /* netmos_9715 */               { 2, { { 0, 1 }, { 2, 3 },} }, /* untested */
 };
 
 static struct pci_device_id parport_pc_pci_tbl[] = {
@@ -2786,6 +2832,14 @@ static struct pci_device_id parport_pc_pci_tbl[] = {
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 },
 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9735,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9735 },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9835 },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9755,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9755 },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9715,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9715 },
 	{ 0, } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl);
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 377c7238c..474eacd34 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -35,7 +35,7 @@ ifndef CONFIG_X86
 obj-y += syscall.o
 endif
 
-host-progs := gen-devlist
+hostprogs-y := gen-devlist
 
 # Dependencies on generated files need to be listed explicitly
 $(obj)/names.o: $(obj)/devlist.h $(obj)/classlist.h
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index 3dc99c18a..9117a95a3 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -88,6 +88,18 @@ config HOTPLUG_PCI_ACPI
 
 	  When in doubt, say N.
 
+config HOTPLUG_PCI_ACPI_IBM
+	tristate "ACPI PCI Hotplug driver IBM extensions"
+	depends on HOTPLUG_PCI_ACPI
+	help
+	  Say Y here if you have an IBM system that supports PCI Hotplug using
+	  ACPI.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called acpiphp_ibm.
+
+	  When in doubt, say N.
+
 config HOTPLUG_PCI_CPCI
 	bool "CompactPCI Hotplug driver"
 	depends on HOTPLUG_PCI
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile
index a972757a0..4fc3ed9b8 100644
--- a/drivers/pci/hotplug/Makefile
+++ b/drivers/pci/hotplug/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_HOTPLUG_PCI_FAKE)		+= fakephp.o
 obj-$(CONFIG_HOTPLUG_PCI_COMPAQ)	+= cpqphp.o
 obj-$(CONFIG_HOTPLUG_PCI_IBM)		+= ibmphp.o
 obj-$(CONFIG_HOTPLUG_PCI_ACPI)		+= acpiphp.o
+obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM)	+= acpiphp_ibm.o
 obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550)	+= cpcihp_zt5550.o
 obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC)	+= cpcihp_generic.o
 obj-$(CONFIG_HOTPLUG_PCI_PCIE)		+= pciehp.o
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index 670c874fe..d9499874c 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -171,6 +171,18 @@ struct acpiphp_func {
 	struct pci_resource *bus_head;
 };
 
+/**
+ * struct acpiphp_attention_info - device specific attention registration
+ *
+ * ACPI has no generic method of setting/getting attention status
+ * this allows for device specific driver registration
+ */
+struct acpiphp_attention_info
+{
+	int (*set_attn)(struct hotplug_slot *slot, u8 status);
+	int (*get_attn)(struct hotplug_slot *slot, u8 *status);
+	struct module *owner;
+};
 
 /* PCI bus bridge HID */
 #define ACPI_PCI_HOST_HID		"PNP0A03"
@@ -212,6 +224,10 @@ struct acpiphp_func {
 
 /* function prototypes */
 
+/* acpiphp_core.c */
+extern int acpiphp_register_attention(struct acpiphp_attention_info*info);
+extern int acpiphp_unregister_attention(struct acpiphp_attention_info *info);
+
 /* acpiphp_glue.c */
 extern int acpiphp_glue_init (void);
 extern void acpiphp_glue_exit (void);
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
index fb4155ad7..4539e61a3 100644
--- a/drivers/pci/hotplug/acpiphp_core.c
+++ b/drivers/pci/hotplug/acpiphp_core.c
@@ -51,6 +51,7 @@ int acpiphp_debug;
 
 /* local variables */
 static int num_slots;
+static struct acpiphp_attention_info *attention_info;
 
 #define DRIVER_VERSION	"0.4"
 #define DRIVER_AUTHOR	"Greg Kroah-Hartman <gregkh@us.ibm.com>, Takayoshi Kochi <t-kochi@bq.jp.nec.com>"
@@ -60,12 +61,17 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
-module_param(debug, bool, 644);
+module_param(debug, bool, 0644);
+
+/* export the attention callback registration methods */
+EXPORT_SYMBOL_GPL(acpiphp_register_attention);
+EXPORT_SYMBOL_GPL(acpiphp_unregister_attention);
 
 static int enable_slot		(struct hotplug_slot *slot);
 static int disable_slot		(struct hotplug_slot *slot);
 static int set_attention_status (struct hotplug_slot *slot, u8 value);
 static int get_power_status	(struct hotplug_slot *slot, u8 *value);
+static int get_attention_status (struct hotplug_slot *slot, u8 *value);
 static int get_address		(struct hotplug_slot *slot, u32 *value);
 static int get_latch_status	(struct hotplug_slot *slot, u8 *value);
 static int get_adapter_status	(struct hotplug_slot *slot, u8 *value);
@@ -76,11 +82,54 @@ static struct hotplug_slot_ops acpi_hotplug_slot_ops = {
 	.disable_slot		= disable_slot,
 	.set_attention_status	= set_attention_status,
 	.get_power_status	= get_power_status,
+	.get_attention_status	= get_attention_status,
 	.get_latch_status	= get_latch_status,
 	.get_adapter_status	= get_adapter_status,
 	.get_address		= get_address,
 };
 
+
+/**
+ * acpiphp_register_attention - set attention LED callback
+ * @info: must be completely filled with LED callbacks
+ *
+ * Description: this is used to register a hardware specific ACPI
+ * driver that manipulates the attention LED.  All the fields in
+ * info must be set.
+ **/
+int acpiphp_register_attention(struct acpiphp_attention_info *info)
+{
+	int retval = -EINVAL;
+
+	if (info && info->owner && info->set_attn &&
+			info->get_attn && !attention_info) {
+		retval = 0;
+		attention_info = info;
+	}
+	return retval;
+}
+
+
+/**
+ * acpiphp_unregister_attention - unset attention LED callback
+ * @info: must match the pointer used to register
+ *
+ * Description: this is used to un-register a hardware specific acpi
+ * driver that manipulates the attention LED.  The pointer to the 
+ * info struct must be the same as the one used to set it.
+ **/
+int acpiphp_unregister_attention(struct acpiphp_attention_info *info)
+{
+	int retval = -EINVAL;
+
+	if (info && attention_info == info) {
+		attention_info = NULL;
+		retval = 0;
+	}
+	return retval;
+}
+
+
 /**
  * enable_slot - power on and enable a slot
  * @hotplug_slot: slot to enable
@@ -117,33 +166,29 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
 }
 
 
-/**
- * set_attention_status - set attention LED
+ /**
+  * set_attention_status - set attention LED
+ * @hotplug_slot: slot to set attention LED on
+ * @status: value to set attention LED to (0 or 1)
  *
- * TBD:
- * ACPI doesn't have known method to manipulate
- * attention status LED.
- *
- */
-static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
-{
-	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
-
-	switch (status) {
-		case 0:
-			/* FIXME turn light off */
-			hotplug_slot->info->attention_status = 0;
-			break;
-
-		case 1:
-		default:
-			/* FIXME turn light on */
-			hotplug_slot->info->attention_status = 1;
-			break;
-	}
-
-	return 0;
-}
+ * attention status LED, so we use a callback that
+ * was registered with us.  This allows hardware specific
+ * ACPI implementations to blink the light for us.
+ **/
+ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
+ {
+	int retval = -ENODEV;
+
+ 	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+ 
+	if (attention_info && try_module_get(attention_info->owner)) {
+		retval = attention_info->set_attn(hotplug_slot, status);
+		module_put(attention_info->owner);
+	} else
+		attention_info = NULL;
+	return retval;
+ }
+ 
 
 /**
  * get_power_status - get power status of a slot
@@ -165,6 +210,32 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
 	return 0;
 }
 
+
+ /**
+ * get_attention_status - get attention LED status
+ * @hotplug_slot: slot to get status from
+ * @value: returns with value of attention LED
+ *
+ * ACPI doesn't have known method to determine the state
+ * of the attention status LED, so we use a callback that
+ * was registered with us.  This allows hardware specific
+ * ACPI implementations to determine its state
+ **/
+static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
+{
+	int retval = -EINVAL;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	if (attention_info && try_module_get(attention_info->owner)) {
+		retval = attention_info->get_attn(hotplug_slot, value);
+		module_put(attention_info->owner);
+	} else
+		attention_info = NULL;
+	return retval;
+}
+
+
 /**
  * get_latch_status - get latch status of a slot
  * @hotplug_slot: slot to get status
@@ -307,7 +378,7 @@ static int __init init_slots(void)
 
 		slot->acpi_slot = get_slot_from_id(i);
 		slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot);
-		slot->hotplug_slot->info->attention_status = acpiphp_get_attention_status(slot->acpi_slot);
+		slot->hotplug_slot->info->attention_status = 0;
 		slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot);
 		slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot);
 		slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN;
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index d41795bb6..e400e4acc 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -1301,20 +1301,6 @@ u8 acpiphp_get_power_status(struct acpiphp_slot *slot)
 }
 
 
-/*
- * attention LED ON: 1
- *		OFF: 0
- *
- * TBD
- * no direct attention led status information via ACPI
- *
- */
-u8 acpiphp_get_attention_status(struct acpiphp_slot *slot)
-{
-	return 0;
-}
-
-
 /*
  * latch closed:  1
  * latch   open:  0
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c
index 868623fd6..ed243605d 100644
--- a/drivers/pci/hotplug/cpci_hotplug_core.c
+++ b/drivers/pci/hotplug/cpci_hotplug_core.c
@@ -33,6 +33,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/smp_lock.h>
+#include <linux/delay.h>
 #include "pci_hotplug.h"
 #include "cpci_hotplug.h"
 
@@ -513,11 +514,10 @@ event_thread(void *data)
 			break;
 		while(controller->ops->query_enum()) {
 			rc = check_slots();
-			if(rc > 0) {
+			if (rc > 0)
 				/* Give userspace a chance to handle extraction */
-				set_current_state(TASK_INTERRUPTIBLE);
-				schedule_timeout(HZ / 2);
-			} else if(rc < 0) {
+				msleep(500);
+			else if (rc < 0) {
 				dbg("%s - error checking slots", __FUNCTION__);
 				thread_finished = 1;
 				break;
@@ -568,11 +568,10 @@ poll_thread(void *data)
 
 		while(controller->ops->query_enum()) {
 			rc = check_slots();
-			if(rc > 0) {
+			if(rc > 0)
 				/* Give userspace a chance to handle extraction */
-				set_current_state(TASK_INTERRUPTIBLE);
-				schedule_timeout(HZ / 2);
-			} else if(rc < 0) {
+				msleep(500);
+			else if (rc < 0) {
 				dbg("%s - error checking slots", __FUNCTION__);
 				thread_finished = 1;
 				break;
@@ -595,8 +594,7 @@ poll_thread(void *data)
 			}
 		}
 
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ / 10);
+		msleep(100);
 	}
 	dbg("poll thread signals exit");
 	up(&thread_exit);
diff --git a/drivers/pci/hotplug/cpcihp_zt5550.c b/drivers/pci/hotplug/cpcihp_zt5550.c
index cb54fa8ab..0a01b0710 100644
--- a/drivers/pci/hotplug/cpcihp_zt5550.c
+++ b/drivers/pci/hotplug/cpcihp_zt5550.c
@@ -298,7 +298,7 @@ module_exit(zt5550_exit);
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
-module_param(debug, bool, 644);
+module_param(debug, bool, 0644);
 MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
-module_param(poll, bool, 644);
+module_param(poll, bool, 0644);
 MODULE_PARM_DESC(poll, "#ENUM polling mode enabled or not");
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index aa8a1a4d7..13d147989 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -69,10 +69,10 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-module_param(power_mode, bool, 644);
+module_param(power_mode, bool, 0644);
 MODULE_PARM_DESC(power_mode, "Power mode enabled or not");
 
-module_param(debug, bool, 644);
+module_param(debug, bool, 0644);
 MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
 
 #define CPQHPC_MODULE_MINOR 208
diff --git a/drivers/pci/hotplug/ibmphp.h b/drivers/pci/hotplug/ibmphp.h
index b24b8cd45..b42346b02 100644
--- a/drivers/pci/hotplug/ibmphp.h
+++ b/drivers/pci/hotplug/ibmphp.h
@@ -759,11 +759,5 @@ extern int ibmphp_configure_card (struct pci_func *, u8);
 extern int ibmphp_unconfigure_card (struct slot **, int);
 extern struct hotplug_slot_ops ibmphp_hotplug_slot_ops;
 
-static inline void long_delay (int delay)
-{
-	set_current_state (TASK_INTERRUPTIBLE);
-	schedule_timeout (delay);
-}
-
 #endif				//__IBMPHP_H
 
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index 89354eb0a..1307f7adc 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -190,7 +190,7 @@ static inline int power_on (struct slot *slot_cur)
 		err ("command not completed successfully in power_on\n");
 		return -EIO;
 	}
-	long_delay (3 * HZ); /* For ServeRAID cards, and some 66 PCI */
+	msleep(3000);	/* For ServeRAID cards, and some 66 PCI */
 	return 0;
 }
 
@@ -913,7 +913,7 @@ static int set_bus (struct slot * slot_cur)
 	}
 	/* This is for x440, once Brandon fixes the firmware, 
 	will not need this delay */
-	long_delay (1 * HZ);
+	msleep(1000);
 	debug ("%s -Exit\n", __FUNCTION__);
 	return 0;
 }
diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c
index 105dc70e6..04459b7c2 100644
--- a/drivers/pci/hotplug/ibmphp_hpc.c
+++ b/drivers/pci/hotplug/ibmphp_hpc.c
@@ -29,6 +29,7 @@
 
 #include <linux/wait.h>
 #include <linux/time.h>
+#include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/smp_lock.h>
@@ -205,7 +206,7 @@ static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void *WPGBbar, u8 index)
 	// READ - step 4 : wait until start operation bit clears
 	i = CMD_COMPLETE_TOUT_SEC;
 	while (i) {
-		long_delay (1 * HZ / 100);
+		msleep(10);
 		wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET;
 		wpg_data = readl (wpg_addr);
 		data = swab32 (wpg_data);
@@ -221,7 +222,7 @@ static u8 i2c_ctrl_read (struct controller *ctlr_ptr, void *WPGBbar, u8 index)
 	// READ - step 5 : read I2C status register
 	i = CMD_COMPLETE_TOUT_SEC;
 	while (i) {
-		long_delay (1 * HZ / 100);
+		msleep(10);
 		wpg_addr = WPGBbar + WPG_I2CSTAT_OFFSET;
 		wpg_data = readl (wpg_addr);
 		data = swab32 (wpg_data);
@@ -316,7 +317,7 @@ static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void *WPGBbar, u8 index,
 	// WRITE - step 4 : wait until start operation bit clears
 	i = CMD_COMPLETE_TOUT_SEC;
 	while (i) {
-		long_delay (1 * HZ / 100);
+		msleep(10);
 		wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET;
 		wpg_data = readl (wpg_addr);
 		data = swab32 (wpg_data);
@@ -333,7 +334,7 @@ static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void *WPGBbar, u8 index,
 	// WRITE - step 5 : read I2C status register
 	i = CMD_COMPLETE_TOUT_SEC;
 	while (i) {
-		long_delay (1 * HZ / 100);
+		msleep(10);
 		wpg_addr = WPGBbar + WPG_I2CSTAT_OFFSET;
 		wpg_data = readl (wpg_addr);
 		data = swab32 (wpg_data);
@@ -748,7 +749,7 @@ int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd)
 					done = TRUE;
 			}
 			if (!done) {
-				long_delay (1 * HZ);
+				msleep(1000);
 				if (timeout < 1) {
 					done = TRUE;
 					err ("%s - Error command complete timeout\n", __FUNCTION__);
@@ -891,7 +892,7 @@ static void poll_hpc (void)
 		case POLL_SLEEP:
 			/* don't sleep with a lock on the hardware */
 			up (&semOperations);
-			long_delay (POLL_INTERVAL_SEC * HZ);
+			msleep(POLL_INTERVAL_SEC * 1000);
 
 			if (ibmphp_shutdown) 
 				break;
@@ -908,8 +909,7 @@ static void poll_hpc (void)
 		/* give up the harware semaphore */
 		up (&semOperations);
 		/* sleep for a short time just for good measure */
-		set_current_state (TASK_INTERRUPTIBLE);
-		schedule_timeout (HZ/10);
+		msleep(100);
 	}
 	up (&sem_exit);
 	debug ("%s - Exit\n", __FUNCTION__);
@@ -974,7 +974,7 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot)
 			if (SLOT_PWRGD (pslot->status)) {
 				// power goes on and off after closing latch
 				// check again to make sure power is still ON
-				long_delay (1 * HZ);
+				msleep(1000);
 				rc = ibmphp_hpc_readslot (pslot, READ_SLOTSTATUS, &status);
 				if (SLOT_PWRGD (status))
 					update = TRUE;
@@ -1147,7 +1147,7 @@ static int hpc_wait_ctlr_notworking (int timeout, struct controller *ctlr_ptr, v
 		if (CTLR_WORKING (*pstatus) == HPC_CTLR_WORKING_NO)
 			done = TRUE;
 		if (!done) {
-			long_delay (1 * HZ);
+			msleep(1000);
 			if (timeout < 1) {
 				done = TRUE;
 				err ("HPCreadslot - Error ctlr timeout\n");
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index 039213c29..dff5d88b7 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -701,7 +701,7 @@ module_exit(pci_hotplug_exit);
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
-module_param(debug, bool, 644);
+module_param(debug, bool, 0644);
 MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
 
 EXPORT_SYMBOL_GPL(pci_hotplug_slots_subsys);
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index b31ccbcea..9df420db2 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -57,9 +57,9 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-module_param(pciehp_debug, bool, 644);
-module_param(pciehp_poll_mode, bool, 644);
-module_param(pciehp_poll_time, int, 644);
+module_param(pciehp_debug, bool, 0644);
+module_param(pciehp_poll_mode, bool, 0644);
+module_param(pciehp_poll_time, int, 0644);
 MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not");
 MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not");
 MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds");
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index cb0804b2d..b8ca99b42 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -1017,7 +1017,7 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
 	return IRQ_HANDLED;
 }
 
-static int hpc_get_max_lnk_speed (struct slot *slot, enum pcie_link_speed *value)
+static int hpc_get_max_lnk_speed (struct slot *slot, enum pci_bus_speed *value)
 {
 	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	enum pcie_link_speed lnk_speed;
@@ -1120,7 +1120,7 @@ static int hpc_get_max_lnk_width (struct slot *slot, enum pcie_link_width *value
 	return retval;
 }
 
-static int hpc_get_cur_lnk_speed (struct slot *slot, enum pcie_link_speed *value)
+static int hpc_get_cur_lnk_speed (struct slot *slot, enum pci_bus_speed *value)
 {
 	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	enum pcie_link_speed lnk_speed = PCI_SPEED_UNKNOWN;
diff --git a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c
index f413495a2..6605d6bda 100644
--- a/drivers/pci/hotplug/pcihp_skeleton.c
+++ b/drivers/pci/hotplug/pcihp_skeleton.c
@@ -70,7 +70,7 @@ static int num_slots;
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
-module_param(debug, bool, 644);
+module_param(debug, bool, 0644);
 MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
 
 static int enable_slot		(struct hotplug_slot *slot);
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index dd6dcdc73..1e679730d 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -54,8 +54,6 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-void eeh_register_disable_func(int (*)(struct pci_dev *));
-
 module_param(debug, bool, 0644);
 
 static int enable_slot(struct hotplug_slot *slot);
@@ -407,18 +405,12 @@ static int __init rpaphp_init(void)
 {
 	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
 
-	/* let EEH know they can use hotplug */
-	eeh_register_disable_func(&rpaphp_disable_slot);
-
 	/* read all the PRA info from the system */
 	return init_rpa();
 }
 
 static void __exit rpaphp_exit(void)
 {
-	/* let EEH know we are going away */
-	eeh_register_disable_func(NULL);
-
 	cleanup_slots();
 }
 
@@ -457,7 +449,7 @@ static int rpaphp_disable_slot(struct pci_dev *dev)
 
 static int disable_slot(struct hotplug_slot *hotplug_slot)
 {
-	int retval;
+	int retval = -EINVAL;
 	struct slot *slot = (struct slot *)hotplug_slot->private;
 
 	dbg("%s - Entry: slot[%s]\n", __FUNCTION__, slot->name);
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
index 0dd2d2369..76d722f34 100644
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -186,7 +186,7 @@ static struct pci_dev *
 rpaphp_pci_config_slot(struct device_node *dn, struct pci_bus *bus)
 {
 	struct device_node *eads_first_child = dn->child;
-	struct pci_dev *dev;
+	struct pci_dev *dev = NULL;
 	int num;
 	
 	dbg("Enter %s: dn=%s bus=%s\n", __FUNCTION__, dn->full_name, bus->name);
@@ -341,7 +341,6 @@ exit:
 	return rc;
 }
 
-
 static void rpaphp_eeh_remove_bus_device(struct pci_dev *dev)
 {
 	eeh_remove_device(dev);
@@ -363,7 +362,7 @@ static void rpaphp_eeh_remove_bus_device(struct pci_dev *dev)
 int rpaphp_unconfig_pci_adapter(struct slot *slot)
 {
 	int retval = 0;
-	struct list_head *ln;
+	struct list_head *ln, *tmp;
 
 	dbg("Entry %s: slot[%s]\n", __FUNCTION__, slot->name);
 	if (list_empty(&slot->dev.pci_funcs)) {
@@ -374,7 +373,7 @@ int rpaphp_unconfig_pci_adapter(struct slot *slot)
 		goto exit;
 	}
 	/* remove the devices from the pci core */
-	list_for_each (ln, &slot->dev.pci_funcs) {
+	list_for_each_safe (ln, tmp, &slot->dev.pci_funcs) {
 		struct rpaphp_pci_func *func;
 	
 		func = list_entry(ln, struct rpaphp_pci_func, sibling);
@@ -430,10 +429,26 @@ static int setup_pci_slot(struct slot *slot)
 				__FUNCTION__, slot->name);
 			goto exit_rc;
 		}
-		if (init_slot_pci_funcs(slot)) {
-			err("%s: init_slot_pci_funcs failed\n", __FUNCTION__);
+
+		if (slot->hotplug_slot->info->adapter_status == NOT_CONFIGURED) {
+			dbg("%s CONFIGURING pci adapter in slot[%s]\n",  
+				__FUNCTION__, slot->name);
+			if (rpaphp_config_pci_adapter(slot)) {
+				err("%s: CONFIG pci adapter failed\n", __FUNCTION__);
+				goto exit_rc;		
+			}
+		} else if (slot->hotplug_slot->info->adapter_status == CONFIGURED) {
+			if (init_slot_pci_funcs(slot)) {
+				err("%s: init_slot_pci_funcs failed\n", __FUNCTION__);
+				goto exit_rc;
+			}
+
+		} else {
+			err("%s: slot[%s]'s adapter_status is NOT_VALID.\n",
+				__FUNCTION__, slot->name);
 			goto exit_rc;
 		}
+		
 		print_slot_pci_funcs(slot);
 		if (!list_empty(&slot->dev.pci_funcs)) {
 			slot->state = CONFIGURED;
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
index c58541add..8519b9d05 100644
--- a/drivers/pci/hotplug/rpaphp_slot.c
+++ b/drivers/pci/hotplug/rpaphp_slot.c
@@ -244,7 +244,7 @@ int register_slot(struct slot *slot)
 
 int rpaphp_get_power_status(struct slot *slot, u8 * value)
 {
-	int rc = 0;
+	int rc = 0, level;
 	
 	if (slot->type == EMBEDDED) {
 		dbg("%s set to POWER_ON for EMBEDDED slot %s\n",
@@ -252,10 +252,14 @@ int rpaphp_get_power_status(struct slot *slot, u8 * value)
 		*value = POWER_ON;
 	}
 	else {
-		rc = rtas_get_power_level(slot->power_domain, (int *) value);
-		if (rc)
+		rc = rtas_get_power_level(slot->power_domain, &level);
+		if (!rc) {
+			dbg("%s the power level of slot %s(pwd-domain:0x%x) is %d\n",
+				__FUNCTION__, slot->name, slot->power_domain, level);
+			*value = level;
+		} else
 			err("failed to get power-level for slot(%s), rc=0x%x\n",
-		    		slot->location, rc);
+				slot->location, rc);
 	}
 
 	return rc;
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index 7f34ec941..4f7a11d87 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -57,9 +57,9 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-module_param(shpchp_debug, bool, 644);
-module_param(shpchp_poll_mode, bool, 644);
-module_param(shpchp_poll_time, int, 644);
+module_param(shpchp_debug, bool, 0644);
+module_param(shpchp_poll_mode, bool, 0644);
+module_param(shpchp_poll_time, int, 0644);
 MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not");
 MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not");
 MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds");
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 7ca8e9369..d71925c26 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -2163,12 +2163,14 @@ int shpchp_disable_slot (struct slot *p_slot)
 	u32 rc = 0;
 	int ret = 0;
 	unsigned int devfn;
-	struct pci_bus *pci_bus = p_slot->ctrl->pci_dev->subordinate;
+	struct pci_bus *pci_bus;
 	struct pci_func *func;
 
 	if (!p_slot->ctrl)
 		return 1;
 
+	pci_bus = p_slot->ctrl->pci_dev->subordinate;
+
 	/* Check to see if (latch closed, card present, power on) */
 	down(&p_slot->ctrl->crit_sect);
 
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index b1fab4532..752d72575 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -35,6 +35,7 @@
 #include <linux/vmalloc.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
+#include <linux/delay.h>
 #include <linux/pci.h>
 #include <asm/system.h>
 #include "shpchp.h"
@@ -300,8 +301,7 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
 		if (!(cmd_status & 0x1))
 			break;
 		/*  Check every 0.1 sec for a total of 1 sec*/
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ/10);
+		msleep(100);
 	}
 
 	cmd_status = readw(php_ctlr->creg + CMD_STATUS);
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 9936879eb..64195d6d6 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -299,10 +299,23 @@ static int pci_device_suspend(struct device * dev, u32 state)
 {
 	struct pci_dev * pci_dev = to_pci_dev(dev);
 	struct pci_driver * drv = pci_dev->driver;
+	u32 dev_state;
 	int i = 0;
 
+	/* Translate PM_SUSPEND_xx states to PCI device states */
+	static u32 state_conversion[] = {
+		[PM_SUSPEND_ON] = 0,
+		[PM_SUSPEND_STANDBY] = 1,
+		[PM_SUSPEND_MEM] = 3,
+		[PM_SUSPEND_DISK] = 3,
+	};
+
+	if (state >= sizeof(state_conversion) / sizeof(state_conversion[1]))
+		return -EINVAL;
+
+	dev_state = state_conversion[state];
 	if (drv && drv->suspend)
-		i = drv->suspend(pci_dev,state);
+		i = drv->suspend(pci_dev, dev_state);
 		
 	pci_save_state(pci_dev, pci_dev->saved_config_space);
 	return i;
@@ -390,10 +403,9 @@ pci_populate_driver_dir(struct pci_driver *drv)
  * pci_register_driver - register a new pci driver
  * @drv: the driver structure to register
  * 
- * Adds the driver structure to the list of registered drivers
- * Returns the number of pci devices which were claimed by the driver
- * during registration.  The driver remains registered even if the
- * return value is zero.
+ * Adds the driver structure to the list of registered drivers.
+ * Returns a negative value on error. The driver remains registered
+ * even if no device was claimed during registration.
  */
 int
 pci_register_driver(struct pci_driver *drv)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 05daa8cff..46d56c8cc 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -291,10 +291,7 @@ pci_set_power_state(struct pci_dev *dev, int state)
 	/* Mandatory power management transition delays */
 	/* see PCI PM 1.1 5.6.1 table 18 */
 	if(state == 3 || dev->current_state == 3)
-	{
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ/100);
-	}
+		msleep(10);
 	else if(state == 2 || dev->current_state == 2)
 		udelay(200);
 	dev->current_state = state;
@@ -748,7 +745,7 @@ static int __devinit pci_init(void)
 	struct pci_dev *dev = NULL;
 
 	while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		pci_fixup_device(PCI_FIXUP_FINAL, dev);
+		pci_fixup_device(pci_fixup_final, dev);
 	}
 	return 0;
 }
diff --git a/drivers/pci/pci.ids b/drivers/pci/pci.ids
index c1f3d74cc..9670ed404 100644
--- a/drivers/pci/pci.ids
+++ b/drivers/pci/pci.ids
@@ -7,7 +7,7 @@
 #	so if you have anything to contribute, please visit the home page or
 #	send a diff -u against the most recent pci.ids to pci-ids@ucw.cz.
 #
-#	Daily snapshot on Thu 2004-04-15 10:00:04
+#	Daily snapshot on Mon 2004-07-12 10:00:27
 #
 
 # Vendors, devices and subsystems. Please keep sorted.
@@ -150,37 +150,58 @@
 		0e11 4082  Smart Array 532
 		0e11 4083  Smart Array 5312
 	b1a4  NC7131 Gigabit Server Adapter
+	b203  Integrated Lights Out Controller
+	b204  Integrated Lights Out  Processor
 	f130  NetFlex-3/P ThunderLAN 1.0
 	f150  NetFlex-3/P ThunderLAN 2.3
 0e55  HaSoTec GmbH
 # Formerly NCR
 1000  LSI Logic / Symbios Logic
 	0001  53c810
-		1000 1000  8100S
+		1000 1000  LSI53C810AE PCI to SCSI I/O Processor
 	0002  53c820
 	0003  53c825
+		1000 1000  LSI53C825AE PCI to SCSI I/O Processor (Ultra Wide)
 	0004  53c815
 	0005  53c810AP
 	0006  53c860
+		1000 1000  LSI53C860E PCI to Ultra SCSI I/O Processor
 	000a  53c1510
-	000b  53c896
+		1000 1000  LSI53C1510 PCI to Dual Channel Wide Ultra2 SCSI Controller (Nonintelligent mode)
+	000b  53C896/897
+		1000 1000  LSI53C896/7 PCI to Dual Channel Ultra2 SCSI Multifunction Controller
+		1000 1010  LSI22910 PCI to Dual Channel Ultra2 SCSI host adapter
+		1000 1020  LSI21002 PCI to Dual Channel Ultra2 SCSI host adapter
+# multifunction PCI card: Dual U2W SCSI, dual 10/100TX, graphics
+		13e9 1000  6221L-4U
 	000c  53c895
+		1000 1010  LSI8951U PCI to Ultra2 SCSI host adapter
+		1000 1020  LSI8952U PCI to Ultra2 SCSI host adapter
+		1de1 3906  DC-390U2B SCSI adapter
 		1de1 3907  DC-390U2W
 	000d  53c885
 	000f  53c875
 		0e11 7004  Embedded Ultra Wide SCSI Controller
+		1000 1000  LSI53C876/E PCI to Dual Channel SCSI Controller
+		1000 1010  LSI22801 PCI to Dual Channel Ultra SCSI host adapter
+		1000 1020  LSI22802 PCI to Dual Channel Ultra SCSI host adapter
 		1092 8760  FirePort 40 Dual SCSI Controller
-		1de1 3904  DC390F Ultra Wide SCSI Controller
+		1de1 3904  DC390F/U Ultra Wide SCSI Adapter
 		4c53 1000  CC7/CR7/CP7/VC7/VP7/VR7 mainboard
 		4c53 1050  CT7 mainboard
-	0010  53c895
+	0010  53C1510
 		0e11 4040  Integrated Array Controller
 		0e11 4048  Integrated Array Controller
+		1000 1000  53C1510 PCI to Dual Channel Wide Ultra2 SCSI Controller (Intelligent mode)
 	0012  53c895a
+		1000 1000  LSI53C895A PCI to Ultra2 SCSI Controller
 	0013  53c875a
+		1000 1000  LSI53C875A PCI to Ultra SCSI Controller
 	0020  53c1010 Ultra3 SCSI Adapter
+		1000 1000  LSI53C1010-33 PCI to Dual Channel Ultra160 SCSI Controller
 		1de1 1020  DC-390U3W
 	0021  53c1010 66MHz  Ultra3 SCSI Adapter
+		1000 1000  LSI53C1000/1000R/1010R/1010-66 PCI to Ultra160 SCSI Controller
 		124b 1070  PMC-USCSI3
 		4c53 1080  CT8 mainboard
 		4c53 1300  P017 mezzanine (32-bit PMC)
@@ -191,6 +212,7 @@
 		1028 1010  LSI U320 SCSI Controller
 	0031  53c1030ZC PCI-X Fusion-MPT Dual Ultra320 SCSI
 	0032  53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI
+		1000 1000  LSI53C1020/1030 PCI-X to Ultra320 SCSI Controller
 	0033  1030ZC_53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI
 	0040  53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI
 		1000 0033  MegaRAID SCSI 320-2XR
@@ -203,8 +225,22 @@
 		1000 0530  MegaRAID 530 SCSI 320-0X RAID Controller
 		1000 0531  MegaRAID 531 SCSI 320-4X RAID Controller
 		1000 0532  MegaRAID 532 SCSI 320-2X RAID Controller
-		1028 0533  PowerEgde Expandable RAID Controller 4/QC
-		8086 0532  Storage RAID Controller SRCU42X
+		1028 0531  PowerEdge Expandable RAID Controller 4/QC
+		8086 0530  MegaRAID Intel RAID Controller SRCZCRX
+		8086 0532  MegaRAID Intel RAID Controller SRCU42X
+	0408  MegaRAID
+		1000 0001  MegaRAID SCSI 320-1E RAID Controller
+		1000 0002  MegaRAID SCSI 320-2E RAID Controller
+		1028 0001  Dell PowerEdge RAID Controller PERC4e/SC
+		1028 0002  Dell PowerEdge RAID Controller PERC4e/DC
+		1734 1065  FSC MegaRAID PCI Express ROMB
+		8086 0002  MegaRAID Intel RAID Controller SRCU42E
+	0409  MegaRAID
+		1000 3004  MegaRAID SATA 300-4X RAID Controller
+		1000 3008  MegaRAID SATA 300-8X RAID Controller
+		8086 3008  MegaRAID Intel RAID Controller SRCS28X
+		8086 3431  MegaRAID Intel RAID Controller Alief SROMBU42E
+		8086 3499  MegaRAID Intel RAID Controller Harwich SROMBU42E
 	0621  FC909 Fibre Channel Adapter
 	0622  FC929 Fibre Channel Adapter
 		1000 1020  44929 O Dual Fibre Channel card
@@ -228,13 +264,16 @@
 	1960  MegaRAID
 		1000 0518  MegaRAID 518 SCSI 320-2 Controller
 		1000 0520  MegaRAID 520 SCSI 320-1 Controller
-		1000 0522  MegaRAID 522 i4133 RAID Controller
+		1000 0522  MegaRAID 522 i4 133 RAID Controller
 		1000 0523  MegaRAID SATA 150-6 RAID Controller
 		1000 4523  MegaRAID SATA 150-4 RAID Controller
 		1000 a520  MegaRAID ZCR SCSI 320-0 Controller
 		1028 0518  MegaRAID 518 DELL PERC 4/DC RAID Controller
 		1028 0520  MegaRAID 520 DELL PERC 4/SC RAID Controller
 		1028 0531  PowerEdge Expandable RAID Controller 4/QC
+		1028 0533  PowerEdge Expandable RAID Controller 4/QC
+		8086 0520  MegaRAID Intel RAID Controller SRCU41L
+		8086 0523  MegaRAID Intel RAID Controller SRCS16
 1001  Kolter Electronic
 	0010  PCI 1616 Measurement card with 32 digital I/O lines
 	0011  OPTO-PCI Opto-Isolated digital I/O board
@@ -350,6 +389,8 @@
 		1002 8008  Rage XL
 		1028 00ce  PowerEdge 1400
 		1028 00d1  PowerEdge 2550
+		8086 3411  SDS2 Mainboard
+		8086 3427  S875WP1-E mainboard
 	4753  Rage XC
 		1002 4753  Rage XC
 	4754  3D Rage I/II 215GT [Mach64 GT]
@@ -435,10 +476,12 @@
 	4e44  Radeon R300 ND [Radeon 9700 Pro]
 	4e45  Radeon R300 NE [Radeon 9500 Pro]
 		1002 0002  Radeon R300 NE [Radeon 9500 Pro]
+		1681 0002  Hercules 3D Prophet 9500 PRO [Radeon 9500 Pro]
 # New PCI ID provided by ATI developer relations (correction to above)
 	4e46  RV350 NF [Radeon 9600]
 	4e47  Radeon R300 NG [FireGL X1]
-	4e48  Radeon R350 [Radeon 9800]
+# (added pro)
+	4e48  Radeon R350 [Radeon 9800 Pro]
 # New PCI ID provided by ATI developer relations
 	4e49  Radeon R350 [Radeon 9800]
 	4e4a  RV350 NJ [Radeon 9800 XT]
@@ -451,10 +494,12 @@
 	4e64  Radeon R300 [Radeon 9700 Pro] (Secondary)
 	4e65  Radeon R300 [Radeon 9500 Pro] (Secondary)
 		1002 0003  Radeon R300 NE [Radeon 9500 Pro]
+		1681 0003  Hercules 3D Prophet 9500 PRO [Radeon 9500 Pro] (Secondary)
 # New PCI ID provided by ATI developer relations (correction to above)
 	4e66  RV350 NF [Radeon 9600] (Secondary)
 	4e67  Radeon R300 [FireGL X1] (Secondary)
-	4e68  Radeon R350 [Radeon 9800] (Secondary)
+# (added pro)
+	4e68  Radeon R350 [Radeon 9800 Pro] (Secondary)
 # New PCI ID provided by ATI developer relations
 	4e69  Radeon R350 [Radeon 9800] (Secondary)
 	4e6a  RV350 NJ [Radeon 9800 XT] (Secondary)
@@ -535,6 +580,7 @@
 		148c 2024  RV200 QW [Radeon 7500LE Dual Display]
 		148c 2025  RV200 QW [Radeon 7500 Evil Master Multi Display Edition]
 		148c 2036  RV200 QW [Radeon 7500 PCI Dual Display]
+		174b 7146  RV200 QW [Radeon 7500 LE]
 		174b 7147  RV200 QW [Sapphire Radeon 7500LE]
 		174b 7161  Radeon RV200 QW [Radeon 7500 LE]
 		17af 0202  RV200 QW [Excalibur Radeon 7500LE]
@@ -624,6 +670,7 @@
 	5d44  RV280 [Radeon 9200 SE] (Secondary)
 	700f  PCI Bridge [IGP 320M]
 	7010  PCI Bridge [IGP 340M]
+	7c37  RV350 AQ [Radeon 9600 SE]
 	cab0  AGP Bridge [IGP 320M]
 	cab2  RS200/RS200M AGP Bridge [IGP 340M]
 1003  ULSI Systems
@@ -865,6 +912,8 @@
 		1014 002e  ServeRAID-3x
 		1014 022e  ServeRAID-4H
 	0031  2 Port Serial Adapter
+# AS400 iSeries PCI sync serial card
+		1014 0031  2721 WAN IOA - 2 Port Sync Serial Adapter
 	0036  Miami
 	003a  CPU to PCI Bridge
 	003c  GXT250P/GXT255P Graphics Adapter
@@ -924,6 +973,7 @@
 	0180  Snipe chipset SCSI controller
 		1014 0241  iSeries 2757 DASD IOA
 		1014 0264  Quad Channel PCI-X U320 SCSI RAID Adapter (2780)
+		1014 02BD  Quad Channel PCI-X U320 DDR SCSI RAID Adapter (570F)
 	01a7  PCI-X to PCI-X Bridge
 	01bd  ServeRAID Controller
 		1014 01be  ServeRAID-4M
@@ -946,7 +996,9 @@
 	0266  PCI-X Dual Channel SCSI
 	0268  Gigabit Ethernet-SX Adapter (PCI-X)
 	0269  10/100/1000 Base-TX Ethernet Adapter (PCI-X)
-	0302  XA-32 chipset [Summit]
+	028C  Citrine chipset SCSI controller
+		1014 02BE  Dual Channel PCI-X U320 DDR SCSI RAID Adapter (571B)
+	0302  X-Architecture Bridge [Summit]
 	ffff  MPIC-2 interrupt controller
 1015  LSI Logic Corp of Canada
 1016  ICL Personal Systems
@@ -1059,20 +1111,27 @@
 	7454  AMD-8151 System Controller
 	7455  AMD-8151 AGP Bridge
 	7460  AMD-8111 PCI
+		161f 3017  HDAMB
 	7461  AMD-8111 USB
 	7462  AMD-8111 Ethernet
 	7464  AMD-8111 USB
+		161f 3017  HDAMB
 	7468  AMD-8111 LPC
+		161f 3017  HDAMB
 	7469  AMD-8111 IDE
+		161f 3017  HDAMB
 	746a  AMD-8111 SMBus 2.0
 	746b  AMD-8111 ACPI
+		161f 3017  HDAMB
 	746d  AMD-8111 AC97 Audio
+		161f 3017  HDAMB
 	746e  AMD-8111 MC97 Modem
 	756b  AMD-8111 ACPI
 1023  Trident Microsystems
 	0194  82C194
 	2000  4DWave DX
 	2001  4DWave NX
+		122d 1400  Trident PCI288-Q3DII (NX)
 	2100  CyberBlade XP4m32
 	8400  CyberBlade/i7
 		1023 8400  CyberBlade i7 AGP
@@ -1083,7 +1142,7 @@
 		0e11 b16e  CyberBlade i1 AGP
 		1023 8520  CyberBlade i1 AGP
 	8620  CyberBlade/i1
-		1014 0502  ThinkPad T30
+		1014 0502  ThinkPad R30/T30
 	8820  CyberBlade XPAi1
 	9320  TGUI 9320
 	9350  GUI Accelerator
@@ -1179,34 +1238,32 @@
 	5453  M5453 PCI AC-Link Controller Modem Device
 	7101  M7101 PCI PMU Power Management Controller
 		10b9 7101  M7101 PCI PMU Power Management Controller
-1028  Dell Computer Corporation
+1028  Dell
 	0001  PowerEdge Expandable RAID Controller 2/Si
-		1028 0001  PowerEdge Expandable RAID Controller 2/Si
-	0002  PowerEdge Expandable RAID Controller 3
-		1028 0002  PowerEdge Expandable RAID Controller 3/Di
-		1028 00d1  PowerEdge Expandable RAID Controller 3/Di
-		1028 00d9  PowerEdge Expandable RAID Controller 3/Di
+		1028 0001  PowerEdge 2400
+	0002  PowerEdge Expandable RAID Controller 3/Di
+		1028 0002  PowerEdge 4400
 	0003  PowerEdge Expandable RAID Controller 3/Si
-		1028 0003  PowerEdge Expandable RAID Controller 3/Si
-	0004  PowerEdge Expandable RAID Controller 3/Si
-		1028 00d0  PowerEdge Expandable RAID Controller 3/Si
+		1028 0003  PowerEdge 2450
 	0006  PowerEdge Expandable RAID Controller 3/Di
-	0007  Remote Access Controller:DRAC III
-	0008  Remote Access Controller
-	0009  BMC/SMIC device not present
-	000a  PowerEdge Expandable RAID Controller 3
-		1028 0106  PowerEdge Expandable RAID Controller 3/Di
-		1028 011b  PowerEdge Expandable RAID Controller 3/Di
-		1028 0121  PowerEdge Expandable RAID Controller 3/Di
-	000c  Remote Access Controller:ERA or ERA/O
-	000d  BMC/SMIC device
-	000e  PowerEdge Expandable RAID controller 4
-		1028 0123  PowerEdge Expandable RAID Controller 4/Di
-	000f  PowerEdge Expandable RAID controller 4
-		1028 013b  MegaRAID DELL PERC 4/Di RAID On Motherboard
-		1028 014a  PowerEdge Expandable RAID Controller 4/Di
-		1028 014c  MegaRAID DELL PERC 4/Di RAID On Motherboard
-		1028 014d  MegaRAID DELL PERC 4/Di RAID On Motherboard
+	0007  Remote Access Card III
+	0008  Remote Access Card III
+	0009  Remote Access Card III: BMC/SMIC device not present
+	000a  PowerEdge Expandable RAID Controller 3/Di
+	000c  Embedded Remote Access or ERA/O
+	000d  Embedded Remote Access: BMC/SMIC device
+	000e  PowerEdge Expandable RAID controller 4/Di
+	000f  PowerEdge Expandable RAID controller 4/Di
+	0010  Remote Access Card 4
+	0011  Remote Access Card 4 Daughter Card
+	0012  Remote Access Card 4 Daughter Card Virtual UART
+	0013  PowerEdge Expandable RAID controller 4
+		1028 016c  PowerEdge Expandable RAID Controller 4e/Si
+		1028 016d  PowerEdge Expandable RAID Controller 4e/Di
+		1028 016e  PowerEdge Expandable RAID Controller 4e/Di
+		1028 016f  PowerEdge Expandable RAID Controller 4e/Di
+		1028 0170  PowerEdge Expandable RAID Controller 4e/Di
+	0014  Remote Access Card 4 Daughter Card SMIC interface
 1029  Siemens Nixdorf IS
 102a  LSI Logic
 	0000  HYDRA
@@ -1518,6 +1575,7 @@
 		1039 5513  SiS5513 EIDE Controller (A,B step)
 		1043 8035  CUSI-FX motherboard
 	5517  5517
+	5518  5518 [IDE]
 	5571  5571
 	5581  5581 Pentium Chipset
 	5582  5582
@@ -1542,6 +1600,7 @@
 		1092 4920  SpeedStar A70
 		1569 6326  SiS6326 GUI Accelerator
 	6330  661FX/M661FX/M661MX/741/M741/760/M760 PCI/AGP
+		1039 6330  [M]661FX/M661MX/[M]741/[M]760 PCI/AGP VGA Display Adapter
 	7001  USB 1.0 Controller
 		1039 7000  Onboard USB Controller
 	7002  USB 2.0 Controller
@@ -1604,7 +1663,7 @@
 		103c 1049  Tosca Console
 		103c 104a  Tosca Secondary
 		103c 104b  Maestro SP2
-		103c 1223  Halfdome Console
+		103c 1223  Superdome Console
 		103c 1226  Keystone SP2
 		103c 1227  Powerbar SP2
 		103c 1282  Everest SP2
@@ -1642,7 +1701,7 @@
 	4057  v8200 GeForce 3
 	8043  v8240 PAL 128M [P4T] Motherboard
 	807b  v9280/TD [Geforce4 TI4200 8X With TV-Out and DVI]
-1044  Distributed Processing Technology
+1044  Adaptec (formerly DPT)
 	1012  Domino RAID Engine
 	a400  SmartCache/Raid I-IV Controller
 	a500  PCI Bridge
@@ -1683,6 +1742,7 @@
 		1044 c065  3010S Ultra3 Four Channel
 		1044 c066  3010S Fibre Channel
 	a511  SmartRAID V Controller
+		1044 c032  ASR-2005S I2O Zero Channel
 1045  OPTi Inc.
 	a0f8  82C750 [Vendetta] USB Controller
 	c101  92C264
@@ -1786,6 +1846,7 @@
 		1028 00e6  PCI4451 IEEE-1394 Controller (Dell Inspiron 8100)
 	8029  PCI4510 IEEE-1394 Controller
 		1071 8160  MIM2900
+	802e  PCI7x20 1394a-2000 OHCI Two-Port PHY/Link-Layer Controller
 	8400  ACX 100 22Mbps Wireless Interface
 		00fc 16ec  U.S. Robotics 22 Mbps Wireless PC Card (model 2210)
 		00fd 16ec  U.S. Robotics 22Mbps Wireless PCI Adapter (model 2216)
@@ -1894,6 +1955,8 @@
 	0003  MPC8240 [Kahlua]
 	0004  MPC107
 	0006  MPC8245 [Unity]
+	0008  MPC8540
+	0009  MPC8560
 	0100  MC145575 [HFC-PCI]
 	0431  KTI829c 100VG
 	1801  DSP56301 Digital Signal Processor
@@ -1939,44 +2002,49 @@
 1058  Electronics & Telecommunications RSH
 1059  Teknor Industrial Computers Inc
 105a  Promise Technology, Inc.
-	0d30  20265
+# more correct description from promise linux sources
+	0d30  PDC20265 (FastTrak100 Lite/Ultra100)
 		105a 4d33  Ultra100
 	0d38  20263
 		105a 4d39  Fasttrak66
 	1275  20275
 	3318  PDC20318 (SATA150 TX4)
-	3319  PDC20319 (SATA150 TX4)
-	3373  PDC20378 (SATA150 TX)
+	3319  PDC20319 (FastTrak S150 TX4)
+		8086 3427  S875WP1-E mainboard
+	3371  PDC20371 (FastTrak S150 TX2plus)
+	3373  PDC20378 (FastTrak 378/SATA 378)
+		1043 80f5  PC-DL Deluxe motherboard
 		1462 702e  K8T NEO FIS2R motherboard
 	3375  PDC20375 (SATA150 TX2plus)
-	3376  PDC20376
+	3376  PDC20376 (FastTrak 376)
 		1043 809e  A7V8X motherboard
-	4d30  20267
+	4d30  PDC20267 (FastTrak100/Ultra100)
 		105a 4d33  Ultra100
-		105a 4d39  Fasttrak100
+		105a 4d39  FastTrak100
 	4d33  20246
 		105a 4d33  20246 IDE Controller
-	4d38  20262
+	4d38  PDC20262 (FastTrak66/Ultra66)
 		105a 4d30  Ultra Device on SuperTrak
 		105a 4d33  Ultra66
-		105a 4d39  Fasttrak66
-	4d68  20268
+		105a 4d39  FastTrak66
+	4d68  PDC20268 (Ultra100 TX2)
 		105a 4d68  Ultra100TX2
 	4d69  20269
 		105a 4d68  Ultra133TX2
-	5275  PDC20276 IDE
+	5275  PDC20276 (MBFastTrak133 Lite)
 		105a 0275  SuperTrak SX6000 IDE
 		105a 1275  MBFastTrak133 Lite (tm) Controller (RAID mode)
 		1458 b001  MBUltra 133
 	5300  DC5300
-	6268  20268R
-	6269  PDC20271
+	6268  PDC20270 (FastTrak100 LP/TX2/TX4)
+		105a 4d68  FastTrak100 TX2
+	6269  PDC20271 (FastTrak TX2000)
 		105a 6269  FastTrak TX2/TX2000
-	6621  PDC20621 [SX4000] 4 Channel IDE RAID Controller
+	6621  PDC20621 (FastTrak S150 SX4/FastTrak SX4000 lite)
 	6622  PDC20621 [SATA150 SX4] 4 Channel IDE RAID Controller
-	6626  PDC20618 Ultra 618
-	6629  PDC20619 FastTrak TX4000 RAID
-	7275  PDC20277
+	6626  PDC20618 (Ultra 618)
+	6629  PDC20619 (FastTrak TX4000)
+	7275  PDC20277 (SBFastTrak133 Lite)
 105b  Foxconn International, Inc.
 105c  Wipro Infotech Limited
 105d  Number 9 Computer Company
@@ -2070,6 +2138,8 @@
 		1014 0242  iSeries 2872 DASD IOA
 		1014 0266  Dual Channel PCI-X U320 SCSI Adapter
 		1014 0278  Dual Channel PCI-X U320 SCSI RAID Adapter
+		1014 02D3  Dual Channel PCI-X U320 SCSI Adapter
+		1014 02D4  Dual Channel PCI-X U320 SCSI RAID Adapter
 	ba55  eXtremeRAID 1100 support Device
 	ba56  eXtremeRAID 2000/3000 support Device
 106a  Aten Research Inc
@@ -2199,6 +2269,7 @@
 107c  LG Electronics [Lucky Goldstar Co. Ltd]
 107d  LeadTek Research Inc.
 	0000  P86C850
+	2134  WinFast 3D S320 II
 107e  Interphase Corporation
 	0001  5515 ATM Adapter [Flipper]
 	0002  100 VG AnyLan Controller
@@ -2348,10 +2419,10 @@
 	0673  USB0673
 	0680  PCI0680 Ultra ATA-133 Host Controller
 		1095 3680  Winic W-680 (Silicon Image 680 based)
-	3112  Silicon Image Serial ATARaid Controller [ CMD/Sil 3112/3112A ]
+	3112  SiI 3112 [SATALink/SATARaid] Serial ATA Controller
 		1095 6112  Asus A7N8X
-	3114  Silicon Image SiI 3114 SATARaid
-	3512  Silicon Image Serial ATARaid Controller [ CMD/Sil 3512 ]
+	3114  SiI 3114 [SATALink/SATARaid] Serial ATA Controller
+	3512  SiI 3512 [SATALink/SATARaid] Serial ATA Controller
 1096  Alacron
 1097  Appian Technology
 1098  Quantum Designs (H.K.) Ltd
@@ -2742,6 +2813,7 @@
 		10b7 7000  10/100 Mini PCI Ethernet Adapter
 		10f1 2466  Tiger MPX S2466 (3C920 Integrated Fast Ethernet Controller)
 	9201  3C920B-EMB Integrated Fast Ethernet Controller [Tornado]
+		1043 80ab  A7N8X Deluxe onboard 3C920B-EMB Integrated Fast Ethernet Controller
 	9202  3Com 3C920B-EMB-WNM Integrated Fast Ethernet Controller
 	9210  3C920B-EMB-WNM Integrated Fast Ethernet Controller
 	9300  3CSOHO100B-TX 910-A01 [tulip]
@@ -2837,6 +2909,7 @@
 	5219  M5219
 	5225  M5225
 	5229  M5229 IDE
+		1014 050f  ThinkPad R30
 		1043 8053  A7A266 Motherboard IDE
 	5235  M5225
 	5237  USB 1.1 Controller
@@ -2859,8 +2932,8 @@
 	545a  SmartLink SmartPCI563 56K Modem
 	5471  M5471 Memory Stick Controller
 	5473  M5473 SD-MMC Controller
-	7101  M7101 PMU
-		10b9 7101  ALI M7101 Power Management Controller
+	7101  M7101 Power Management Controller [PMU]
+		1014 0510  ThinkPad R30
 10ba  Mitsubishi Electric Corp.
 	0301  AccelGraphics AccelECLIPSE
 	0304  AccelGALAXY A2100 [OEM Evans & Sutherland]
@@ -3001,6 +3074,7 @@
 		1043 0205  PCI-V3800
 		1043 4000  AGP-V3800PRO
 		1048 0c21  Synergy II
+		107d 2134  WinFast 3D S320 II + TV-Out
 		1092 4804  Viper V770
 		1092 4a00  Viper V770
 		1092 4a02  Viper V770 Ultra
@@ -3041,11 +3115,13 @@
 		1554 1041  Pixelview RIVA TNT2 M64
 	002e  NV6 [Vanta]
 	002f  NV6 [Vanta]
+	0041  NV40 OS1RT00B30
 	0060  nForce2 ISA Bridge
 		1043 80ad  A7N8X Mainboard
 	0064  nForce2 SMBus (MCP)
 	0065  nForce2 IDE
 	0066  nForce2 Ethernet Controller
+		1043 80a7  A7N8X Mainboard onboard nForce2 Ethernet
 	0067  nForce2 USB Controller
 		1043 0c11  A7N8X Mainboard
 	0068  nForce2 USB Controller
@@ -3292,6 +3368,7 @@
 		1071 8160  MIM2000
 		10bd 0320  EP-320X-R
 		10ec 8139  RT8139
+		1113 ec01  FNC-0107TX
 		1186 1300  DFE-538TX
 		1186 1320  SN5200
 		1186 8139  DRN-32TX
@@ -3342,7 +3419,7 @@
 10f9  PC Direct
 10fa  Truevision
 	000c  TARGA 1000
-10fb  Thesys Gesellschaft für Mikroelektronik mbH
+10fb  Thesys Gesellschaft für Mikroelektronik mbH
 	186f  TH 6255
 10fc  I-O Data Device, Inc.
 # What's in the cardbus end of a Sony ACR-A01 card, comes with newer Vaio CD-RW drives
@@ -3358,6 +3435,7 @@
 	9400  INI-940
 	9401  INI-950
 	9500  360P
+	9502  Initio INI-9100UW Ultra Wide SCSI Controller INIC-950P chip
 1102  Creative Labs
 	0002  SB Live! EMU10k1
 		1102 0020  CT4850 SBLive! Value
@@ -3507,13 +3585,16 @@
 		0e11 0097  SoundMax Digital Integrated Audio
 		0e11 b194  Soundmax integrated digital audio
 		1019 0985  P6VXA Motherboard
+		1043 1106  A7V133/A7V133-C Mainboard
 		1106 4511  Onboard Audio on EP7KXA
 		1458 7600  Onboard Audio
 		1462 3091  MS-6309 Onboard Audio
+		1462 3300  MS-6330 Onboard Audio
 		15dd 7609  Onboard Audio
 	3059  VT8233/A/8235/8237 AC97 Audio Controller
 		1019 0a81  L7VTA v1.0 Motherboard (KT400-8235)
 		1043 8095  A7V8X Motherboard (Realtek ALC650 codec)
+		1043 80a1  A7V8X-X Motherboard
 		1043 80b0  A7V600 motherboard (ADI AD1980 codec [SoundMAX])
 		1106 3059  L7VMM2 Motherboard
 		1297 c160  FX41 motherboard (Realtek ALC650 codec)
@@ -3526,6 +3607,7 @@
 		1186 1401  DFE-530TX rev B
 		13b9 1421  LD-10/100AL PCI Fast Ethernet Adapter (rev.B)
 	3068  Intel 537 [AC97 Modem]
+		1462 309e  MS-6309 Saturn Motherboard
 	3074  VT8233 PCI to ISA Bridge
 		1043 8052  VT8233A
 	3091  VT8633 [Apollo Pro266]
@@ -3906,7 +3988,15 @@
 		1133 1c0b  Diva Server V-PRI/T1-24 Cornet NQ 3
 		1133 1c0c  Diva Server V-PRI/E1-30 Cornet NQ 3
 	e01e  Diva Server 2PRI
+		1133 1e00  Diva Server V-2PRI/E1-60
+		1133 1e01  Diva Server V-2PRI/T1-48
+		1133 1e02  Diva Server 2PRI/E1-60
+		1133 1e03  Diva Server 2PRI/T1-48
 	e020  Diva Server 4PRI
+		1133 2000  Diva Server V-4PRI/E1-120
+		1133 2001  Diva Server V-4PRI/T1-96
+		1133 2002  Diva Server 4PRI/E1-120
+		1133 2003  Diva Server 4PRI/T1-96
 	e024  Diva Server Analog-4P
 	e028  Diva Server Analog-8P
 1134  Mercury Computer Systems
@@ -4145,6 +4235,7 @@
 1165  Imagraph Corporation
 	0001  Motion TPEG Recorder/Player with audio
 1166  ServerWorks
+	0000  CMIC-LE
 	0005  CNB20-LE Host Bridge
 	0006  CNB20HE Host Bridge
 	0007  CNB20-LE Host Bridge
@@ -4152,13 +4243,13 @@
 	0009  CNB20LE Host Bridge
 	0010  CIOB30
 	0011  CMIC-HE
-	0012  CMIC-LE
+	0012  CMIC-WS Host Bridge (GC-LE chipset)
 	0013  CNB20-HE Host Bridge
-	0014  CNB20-HE Host Bridge
+	0014  CMIC-LE Host Bridge (GC-LE chipset)
 	0015  CMIC-GC Host Bridge
 	0016  CMIC-GC Host Bridge
 	0017  GCNB-LE Host Bridge
-	0101  CIOB-X2
+	0101  CIOB-X2 PCI-X I/O Bridge
 	0110  CIOB-E I/O Bridge with Gigabit Ethernet
 	0200  OSB4 South Bridge
 	0201  CSB5 South Bridge
@@ -4255,6 +4346,7 @@
 		1186 1300  DFE-538TX 10/100 Ethernet Adapter
 		1186 1301  DFE-530TX+ 10/100 Ethernet Adapter
 	1340  DFE-690TXD CardBus PC Card
+	1541  DFE-680TXD CardBus PC Card
 	1561  DRP-32TXD Cardbus PC Card
 	3300  DWL-510 2.4GHz Wireless PCI Adapter
 	3b05  DWL-G650+ CardBus PC Card
@@ -4337,9 +4429,10 @@
 11a9  InnoSys Inc.
 	4240  AMCC S933Q Intelligent Serial Card
 11aa  Actel
-# (formerly Galileo technologies)
-11ab  Marvell
+# Formerly Galileo Technology, Inc.
+11ab  Marvell Technology Group Ltd.
 	0146  GT-64010/64010A System Controller
+	1fa6  Marvell W8300 802.11 Adapter
 	4320  Yukon Gigabit Ethernet 10/100/1000Base-T Adapter
 	4611  GT-64115 System Controller
 	4620  GT-64120/64120A/64121A System Controller
@@ -4677,6 +4770,7 @@
 	6933  OZ6933 Cardbus Controller
 		1025 1016  Travelmate 612 TX
 	6972  OZ6912 Cardbus Controller
+		1014 020c  ThinkPad R30
 		1179 0001  Magnia Z310
 	7110  OZ711Mx MultiMediaBay Accelerator
 	7112  OZ711EC1/M1 SmartCardBus MultiMediaBay Controller
@@ -4762,6 +4856,7 @@
 122c  Sican GmbH
 122d  Aztech System Ltd
 	1206  368DSP
+	1400  Trident PCI288-Q3DII (NX)
 	50dc  3328 Audio
 		122d 0001  3328 Audio
 	80da  3328 Audio
@@ -4905,11 +5000,15 @@
 	3873  Prism 2.5 Wavelan chipset
 		1186 3501  DWL-520 Wireless PCI Adapter
 		1186 3700  DWL-520 Wireless PCI Adapter, Rev E1
+		1385 4105  MA311 802.11b wireless adapter
 		1668 0414  HWP01170-01 802.11b PCI Wireless Adapter
 		16a5 1601  AIR.mate PC-400 PCI Wireless LAN Adapter
 		1737 3874  WMP11 Wireless 802.11b PCI Adapter
 		8086 2513  Wireless 802.11b MiniPCI Adapter
+	3886  ISL3886 [Prism Javelin/Prism Xbow]
 	3890  Intersil ISL3890 [Prism GT/Prism Duette]
+		10b8 a835  SMC2835W V2 Wireless Cardbus Adapter
+		16a5 1605  ALLNET ALL0271 Wireless PCI Adapter
 		17cf 0014  Ovislink WL-5400PCM, Prism GT
 	8130  HMP8130 NTSC/PAL Video Decoder
 	8131  HMP8131 NTSC/PAL Video Decoder
@@ -5155,7 +5254,7 @@
 	9132  Ethernet 100/10 MBit
 1283  Integrated Technology Express, Inc.
 	673a  IT8330G
-	8212  IT/ITE8212 Dual channel ATA RAID
+	8212  IT/ITE8212 Dual channel ATA RAID controller
 	8330  IT8330G
 	8872  IT8874F PCI Dual Serial Port Controller
 	8888  IT8888F PCI to ISA Bridge with SMB
@@ -5466,7 +5565,8 @@
 	0985  NC100 Network Everywhere Fast Ethernet 10/100
 	1985  21x4x DEC-Tulip compatible 10/100 Ethernet
 	2850  HSP MicroModem 56
-	8201  [ADMtek] SP906B_V2 Wireless LAN adapter
+	8201  ADMtek ADM8211 802.11b Wireless Interface
+		10b8 2635  SMC2635W 802.11b (11Mbps) wireless lan pcmcia (cardbus) card
 		1317 8201  SMC2635W 802.11b (11mbps) wireless lan pcmcia (cardbus) card
 	9511  21x4x DEC-Tulip compatible 10/100 Ethernet
 1318  Packet Engines Inc.
@@ -5535,7 +5635,6 @@
 132d  Integrated Silicon Solution, Inc.
 1330  MMC Networks
 1331  Radisys Corp.
-	0030  ENP-2611
 	8200  82600 Host Bridge
 	8201  82600 IDE
 	8202  82600 USB
@@ -5659,9 +5758,11 @@
 1385  Netgear
 	4100  802.11b Wireless Adapter (MA301)
 	4105  MA311 802.11b wireless adapter
+	4a00  WAG311 802.11abg Wireless Adapter
 	620a  GA620 Gigabit Ethernet
 	622a  GA622
 	630a  GA630 Gigabit Ethernet
+	f004  FA310TX
 1386  Video Domain Technologies
 1387  Systran Corp
 1388  Hitachi Information Technology Co Ltd
@@ -5720,6 +5821,7 @@
 13a6  Videonics Inc
 13a7  Teles AG
 13a8  Exar Corp.
+	0154  XR17C154 Quad UART
 	0158  XR17C158 Octal UART
 13a9  Siemens Medical Systems, Ultrasound Group
 13aa  Broadband Networks Inc
@@ -5752,6 +5854,7 @@
 13c1  3ware Inc
 	1000  3ware ATA-RAID
 	1001  3ware 7000-series ATA-RAID
+		13c1 1001  3ware Inc 3ware 7xxx/8xxx-series PATA/SATA-RAID
 	1002  3ware ATA-RAID
 13c2  Technotrend Systemtechnik GmbH
 13c3  Janz Computer AG
@@ -5884,10 +5987,11 @@
 140f  Salient Systems Corp
 1410  Midas lab Inc
 1411  Ikos Systems Inc
-1412  IC Ensemble Inc
-	1712  ICE1712 [Envy24]
+# formerly IC Ensemble Inc.
+1412  VIA Technologies Inc.
+	1712  ICE1712 [Envy24] PCI Multi-Channel I/O Controller
 		1412 d638  M-Audio Delta 410
-	1724  ICE1724 [Envy24HT]
+	1724  VT1720/24 [Envy24PT/HT] PCI Multi-Channel Audio Controller
 1413  Addonics
 1414  Microsoft Corporation
 1415  Oxford Semiconductor Ltd
@@ -5990,6 +6094,7 @@
 1460  DYNARC INC
 1461  Avermedia Technologies Inc
 1462  Micro-Star International Co., Ltd.
+	6825  PCI Card wireless 11g [PC54G]
 	8725  NVIDIA NV25 [GeForce4 Ti 4600] VGA Adapter
 # MSI G4Ti4800, 128MB DDR SDRAM, TV-Out, DVI-I
 	9000  NVIDIA NV28 [GeForce4 Ti 4800] VGA Adapter
@@ -6150,8 +6255,9 @@
 14d6  Accusys Inc
 14d7  Hirakawa Hewtech Corp
 14d8  HOPF Elektronik GmBH
-14d9  Alpha Processor Inc
-	0010  AP1011 HyperTransport-PCI Bridge [Sturgeon]
+# Formerly SiPackets, Inc., formerly API NetWorks, Inc., formerly Alpha Processor, Inc.
+14d9  Alliance Semiconductor Corporation
+	0010  AP1011/SP1011 HyperTransport-PCI Bridge [Sturgeon]
 14da  National Aerospace Laboratories
 14db  AFAVLAB Technology Inc
 	2120  TK9902
@@ -6175,6 +6281,14 @@
 14e2  INFOLIBRIA
 14e3  AMTELCO
 14e4  Broadcom Corporation
+	0800  Sentry5 Chipcommon I/O Controller
+	0804  Sentry5 PCI Bridge
+	0805  Sentry5 MIPS32 CPU
+	0806  Sentry5 Ethernet Controller
+	080b  Sentry5 Crypto Accelerator
+	080f  Sentry5 DDR/SDR RAM Controller
+	0811  Sentry5 External Interface Core
+	0816  BCM3302 Sentry5 MIPS32 CPU
 	1644  NetXtreme BCM5700 Gigabit Ethernet
 		1014 0277  Broadcom Vigil B5700 1000Base-T
 		1028 00d1  Broadcom BCM5700
@@ -6241,21 +6355,14 @@
 	164d  NetXtreme BCM5702FE Gigabit Ethernet
 	1653  NetXtreme BCM5705 Gigabit Ethernet
 	1654  NetXtreme BCM5705_2 Gigabit Ethernet
-	1658  NetXtreme BCM5720 Gigabit Ethernet
-	1659  NetXtreme BCM5721 Gigabit Ethernet
+	1659  NetXtreme BCM5721 Gigabit Ethernet PCI Express
 	165d  NetXtreme BCM5705M Gigabit Ethernet
 	165e  NetXtreme BCM5705M_2 Gigabit Ethernet
-	166e  NetXtreme BCM5705F Gigabit Ethernet
-	1676  NetXtreme BCM5750 Gigabit Ethernet
-	1677  NetXtreme BCM5751 Gigabit Ethernet
-	167c  NetXtreme BCM5750M Gigabit Ethernet
-	167d  NetXtreme BCM5751M Gigabit Ethernet
-	167e  NetXtreme BCM5751F Gigabit Ethernet
+	1677  NetXtreme BCM5751 Gigabit Ethernet PCI Express
 	1696  NetXtreme BCM5782 Gigabit Ethernet
 		103c 12bc  HP d530 CMT (DG746A)
 		14e4 000d  NetXtreme BCM5782 1000Base-T
 	169c  NetXtreme BCM5788 Gigabit Ethernet
-	169d  NetXtreme BCM5789 Gigabit Ethernet
 	16a6  NetXtreme BCM5702X Gigabit Ethernet
 		0e11 00bb  NC7760 Gigabit Server Adapter (PCI-X, 10/100/1000-T)
 		1028 0126  BCM5702 1000Base-T
@@ -6279,13 +6386,17 @@
 		103c 12ca  HP Combo FC/GigE-T [A9784A]
 		14e4 0009  NetXtreme BCM5703 1000Base-T
 		14e4 000a  NetXtreme BCM5703 1000Base-SX
-	170d  NetXtreme BCM5901 Gigabit Ethernet
-	170e  NetXtreme BCM5901_2 Gigabit Ethernet
+	170c  BCM4401-B0 100Base-TX
+	170d  NetXtreme BCM5901 100Base-TX
+	170e  NetXtreme BCM5901 100Base-TX
+	3352  BCM3352
+	3360  BCM3360
 	4210  BCM4210 iLine10 HomePNA 2.0
 	4211  BCM4211 iLine10 HomePNA 2.0 + V.90 56k modem
 	4212  BCM4212 v.90 56k modem
 	4301  BCM4301 802.11b
-	4320  BCM94306 802.11g
+	4307  BCM4307 802.11b Wireless LAN Controller
+	4320  BCM4306 802.11b/g Wireless LAN Controller
 		1028 0001  TrueMobile 1300 WLAN Mini-PCI Card
 		1737 4320  WPC54G
 	4324  BCM4309 802.11a/b/g
@@ -6293,12 +6404,47 @@
 	4401  BCM4401 100Base-T
 		1043 80a8  A7V8X motherboard
 	4402  BCM4402 Integrated 10/100BaseT
+	4403  BCM4402 V.90 56k Modem
 	4410  BCM4413 iLine32 HomePNA 2.0
 	4411  BCM4413 V.90 56k modem
 	4412  BCM4413 10/100BaseT
+	4430  BCM44xx CardBus iLine32 HomePNA 2.0
+	4432  BCM44xx CardBus 10/100BaseT
+	4610  BCM4610 Sentry5 PCI to SB Bridge
+	4611  BCM4610 Sentry5 iLine32 HomePNA 1.0
+	4612  BCM4610 Sentry5 V.90 56k Modem
+	4613  BCM4610 Sentry5 Ethernet Controller
+	4614  BCM4610 Sentry5 External Interface
+	4615  BCM4610 Sentry5 USB Controller
+	4704  BCM4704 PCI to SB Bridge
+	4708  BCM4708 Sentry5 PCI to SB Bridge
+	4710  BCM4710 Sentry5 PCI to SB Bridge
+	4711  BCM47xx Sentry5 iLine32 HomePNA 2.0
+	4712  Sentry5 UART
+	4713  Sentry5 Ethernet Controller
+	4714  BCM47xx Sentry5 External Interface
+	4715  Sentry5 USB Controller
+	4716  BCM47xx Sentry5 USB Host Controller
+	4717  BCM47xx Sentry5 USB Device Controller
+	4718  Sentry5 Crypto Accelerator
+	5365  BCM5365P Sentry5 Host Bridge
+	5600  BCM5600 StrataSwitch 24+2 Ethernet Switch Controller
+	5605  BCM5605 StrataSwitch 24+2 Ethernet Switch Controller
+	5615  BCM5615 StrataSwitch 24+2 Ethernet Switch Controller
+	5625  BCM5625 StrataSwitch 24+2 Ethernet Switch Controller
+	5645  BCM5645 StrataSwitch 24+2 Ethernet Switch Controller
+	5670  BCM5670 8-Port 10GE Ethernet Switch Fabric
+	5680  BCM5680 G-Switch 8 Port Gigabit Ethernet Switch Controller
 	5690  BCM5690 12-port Multi-Layer Gigabit Ethernet Switch
+	5691  BCM5691 GE/10GE 8+2 Gigabit Ethernet Switch Controller
 	5820  BCM5820 Crypto Accelerator
 	5821  BCM5821 Crypto Accelerator
+	5822  BCM5822 Crypto Accelerator
+	5823  BCM5823 Crypto Accelerator
+	5824  BCM5824 Crypto Accelerator
+	5840  BCM5840 Crypto Accelerator
+	5841  BCM5841 Crypto Accelerator
+	5850  BCM5850 Crypto Accelerator
 14e5  Pixelfusion Ltd
 14e6  SHINING Technology Inc
 14e7  3CX
@@ -6823,11 +6969,16 @@
 1619  FarSite Communications Ltd
 	0400  FarSync T2P (2 port X.21/V.35/V.24)
 	0440  FarSync T4P (4 port X.21/V.35/V.24)
+# www.rioworks.com
+161f  Rioworks
 1626  TDK Semiconductor Corp.
 	8410  RTL81xx Fast Ethernet
 1629  Kongsberg Spacetec AS
 	1003  Format synchronizer v3.0
 	2002  Fast Universal Data Output
+# This seems to occur on their 802.11b Wireless card WMP-11
+1637  Linksys
+	3874  Linksys 802.11b WMP11 PCI Wireless card
 1638  Standard Microsystems Corp [SMC]
 	1100  SMC2602W EZConnect/Addtron AWA-100/Eumitcom WL11000
 163c  Smart Link Ltd.
@@ -6862,6 +7013,7 @@
 		168c 0013  WG511T Wireless CardBus Adapter
 		168c 1025  DWL-G650B2 Wireless CardBus Adapter
 	1014  AR5212 802.11abg NIC
+16a5  Tekram Technology Co.,Ltd.
 16ab  Global Sun Technology Inc
 	1100  GL24110P
 	1101  PLX9052 PCMCIA-to-PCI Wireless LAN
@@ -6874,9 +7026,13 @@
 16cd  Densitron Technologies
 # www.pikatechnologies.com
 16df  PIKA Technologies Inc.
+16e3  European Space Agency
+	1e0f  LEON2FT Processor
 16ec  U.S. Robotics
 	00ff  USR997900 10/100 Mbps PCI Network Card
 	3685  Wireless Access PCI Adapter Model 022415
+16f4  Vweb Corp
+	8000  VW2010
 16f6  VideoTele.com, Inc.
 # www.internetmachines.com
 1702  Internet Machines Corporation (IMC)
@@ -6884,8 +7040,12 @@
 170b  NetOctave
 	0100  NSP2000-SSL crypto accelerator
 170c  YottaYotta Inc.
+# Seems to be a 2nd ID for Vitesse Semiconductor
+1725  Vitesse Semiconductor
+	7174  VSC7174 PCI/PCI-X Serial ATA Host Bus Controller
 172a  Accelerated Encryption
 1737  Linksys
+	0013  WMP54G Wireless Pci Card
 	1032  Gigabit Network Adapter
 		1737 0015  EG1032 v2 Instant Gigabit Network Adapter
 	1064  Gigabit Network Adapter
@@ -6914,10 +7074,12 @@
 	0004  CAMAC Controller
 	0005  PROFIBUS
 	0006  AMCC HOTlink
+1797  JumpTec h, GMBH
 1799  Belkin
 	6001  Wireless PCI Card - F5D6001
 	6020  Wireless PCMCIA Card - F5D6020
 	6060  Wireless PDA Card - F5D6060
+	7000  Wireless PCI Card - F5D7000
 17af  Hightech Information System Ltd.
 17b3  Hawking Technologies
 	ab08  PN672TX 10/100 Ethernet
@@ -6929,6 +7091,9 @@
 	2280  USB 2.0
 # S2io ships 10Gb PCI-X Ethernet adapters www.s2io.com
 17d5  S2io Inc.
+# Supplying full name for a currently green entry
+17fe  Linksys, A Division of Cisco Systems
+	2220  [AirConn] INPROCOMM IPN 2220 WLAN Adapter (rev 01)
 1813  Ambient Technologies Inc
 	4000  HaM controllerless modem
 		16be 0001  V9x HAM Data Fax Modem
@@ -6937,6 +7102,8 @@
 1814  RaLink
 	0101  Wireless PCI Adpator RT2400 / RT2460
 	0201  Ralink RT2500 802.11 Cardbus Reference Card
+1820  InfiniCon Systems Inc.
+1822  Twinhan Technology Co. Ltd
 1830  Credence Systems Corporation
 1851  Microtune, Inc.
 1852  Anritsu Corp.
@@ -6952,6 +7119,8 @@
 # found e.g. on KNC DVB-S card
 1894  KNC One
 18a1  Astute Networks Inc.
+18bc  Info-Tek Corp.
+18c9  ARVOO Engineering BV
 18ca  XGI - Xabre Graphics Inc
 	0040  Volari V8
 18e6  MPL AG
@@ -7018,6 +7187,7 @@
 	0008  GLINT Gamma G1
 	0009  Permedia II 2D+3D
 		1040 0011  AccelStar II
+		13e9 1000  6221L-4U
 		3d3d 0100  AccelStar II 3D Accelerator
 		3d3d 0111  Permedia 3:16
 		3d3d 0114  Santa Ana
@@ -7269,10 +7439,11 @@
 5555  Genroco, Inc
 	0003  TURBOstor HFP-832 [HiPPI NIC]
 5654  VoiceTronix Pty Ltd
+	3132  OpenSwitch12
 5700  Netpower
 5851  Exacq Technologies
 6356  UltraStor
-6374  c't Magazin für Computertechnik
+6374  c't Magazin für Computertechnik
 	6773  GPPCI
 6409  Logitec Corp.
 6666  Decision Computer International Co.
@@ -7292,6 +7463,8 @@
 		0008 1000  WorldMark 4300 INCA ASIC
 	0039  21145 Fast Ethernet
 	0122  82437FX
+	0309  80303 I/O Processor PCI-to-PCI Bridge
+	030d  80312 I/O Companion Chip PCI-to-PCI Bridge
 	0326  PCI Bridge Hub I/OxAPIC Interrupt Controller A
 	0327  PCI Bridge Hub I/OxAPIC Interrupt Controller B
 	0329  PCI Bridge Hub A
@@ -7315,13 +7488,38 @@
 	0340  41210 [Lanai] Serial to Parallel PCI Bridge
 # B-segment bridge
 	0341  41210 [Lanai] Serial to Parallel PCI Bridge
-	0482  82375EB
-	0483  82424ZX [Saturn]
-	0484  82378IB [SIO ISA Bridge]
-	0486  82430ZX [Aries]
-	04a3  82434LX [Mercury/Neptune]
+	0482  82375EB/SB PCI to EISA Bridge
+	0483  82424TX/ZX [Saturn] CPU to PCI bridge
+	0484  82378ZB/IB, 82379AB (SIO, SIO.A) PCI to ISA Bridge
+	0486  82425EX/ZX [Aries] PCIset with ISA bridge
+	04a3  82434LX/NX [Mercury/Neptune] Processor to PCI bridge
 	04d0  82437FX [Triton FX]
+	0500  E8870 Processor bus control
+	0501  E8870 Memory controller
+# and registers common to both SPs
+	0502  E8870 Scalability Port 0
+# and global performance monitoring
+	0503  E8870 Scalability Port 1
+	0510  E8870IO Hub Interface Port 0 registers (8-bit compatibility port)
+	0511  E8870IO Hub Interface Port 1 registers
+	0512  E8870IO Hub Interface Port 2 registers
+	0513  E8870IO Hub Interface Port 3 registers
+	0514  E8870IO Hub Interface Port 4 registers
+	0515  E8870IO General SIOH registers
+	0516  E8870IO RAS registers
+	0530  E8870SP Scalability Port 0 registers
+	0531  E8870SP Scalability Port 1 registers
+	0532  E8870SP Scalability Port 2 registers
+	0533  E8870SP Scalability Port 3 registers
+	0534  E8870SP Scalability Port 4 registers
+	0535  E8870SP Scalability Port 5 registers
+# (bi-interleave 0) and global registers that are neither per-port nor per-interleave
+	0536  E8870SP Interleave registers 0 and 1
+# (bi-interleave 1)
+	0537  E8870SP Interleave registers 2 and 3
 	0600  RAID Controller
+		8086 01c1  ICP Vortex GDT8546RZ
+		8086 01f7  SCRU32
 	0960  80960RP [i960 RP Microprocessor/Bridge]
 	0962  80960RM [i960RM Bridge]
 	0964  80960RP [i960 RP Microprocessor/Bridge]
@@ -7406,6 +7604,7 @@
 	1019  82547EI Gigabit Ethernet Controller (LOM)
 		1458 1019  GA-8IPE1000 Pro2 motherboard (865PE)
 		8086 1019  PRO/1000 CT Desktop Connection
+		8086 3427  S875WP1-E mainboard
 	101d  82546EB Gigabit Ethernet Controller
 		8086 1000  PRO/1000 MT Quad Port Server Adapter
 	101e  82540EP Gigabit Ethernet Controller (Mobile)
@@ -7453,13 +7652,16 @@
 		16be 1040  V.9X DSP Data Fax Modem
 	1043  PRO/Wireless LAN 2100 3B Mini PCI Adapter
 		8086 2527  MIM2000/Centrino
-	1048  Intel(R) PRO/10GbE LR Server Adapter
+	1048  PRO/10GbE LR Server Adapter
 		8086 a01f  PRO/10GbE LR Server Adapter
 		8086 a11f  PRO/10GbE LR Server Adapter
 	1050  82562EZ 10/100 Ethernet Controller
 		1462 728c  865PE Neo2 (MS-6728)
+		1462 758c  MS-6758 (875P Neo)
+		8086 3427  S875WP1-E mainboard
 	1051  82801EB/ER (ICH5/ICH5R) integrated LAN Controller
 	1059  82551QM Ethernet Controller
+	1065  82801FB/FBM/FR/FW/FRW (ICH6 Family) LAN Controller
 # Updated controller name from 82547EI to 82547GI
 	1075  82547GI Gigabit Ethernet Controller
 		8086 0075  PRO/1000 CT Network Connection
@@ -7516,8 +7718,8 @@
 		4c53 1050  CT7 mainboard
 		4c53 1051  CE7 mainboard
 		4c53 1070  PC6 mainboard
-	1221  82092AA_0
-	1222  82092AA_1
+	1221  82092AA PCI to PCMCIA Bridge
+	1222  82092AA IDE Controller
 	1223  SAA7116
 	1225  82452KX/GX [Orion]
 	1226  82596 PRO/10 PCI
@@ -7587,6 +7789,7 @@
 		1259 2560  AT-2560 100
 		1259 2561  AT-2560 100 FX Ethernet Adapter
 		1266 0001  NE10/100 Adapter
+		13e9 1000  6221L-4U
 		144d 2501  SEM-2000 MiniPCI LAN Adapter
 		144d 2502  SEM-2100IL MiniPCI LAN Adapter
 		1668 1100  EtherExpress PRO/100B (TX) (MiniPCI Ethernet+Modem)
@@ -7675,6 +7878,7 @@
 		8086 3010  EtherExpress PRO/100 S Network Connection
 		8086 3011  EtherExpress PRO/100 S Network Connection
 		8086 3012  EtherExpress PRO/100 Network Connection
+		8086 3411  SDS2 Mainboard
 	122d  430FX - 82437FX TSC [Triton I]
 	122e  82371FB PIIX ISA [Triton I]
 	1230  82371FB PIIX IDE [Triton I]
@@ -7682,13 +7886,15 @@
 	1234  430MX - 82371MX Mobile PCI I/O IDE Xcelerator (MPIIX)
 	1235  430MX - 82437MX Mob. System Ctrlr (MTSC) & 82438MX Data Path (MTDP)
 	1237  440FX - 82441FX PMC [Natoma]
-	1239  82371FB
-	123b  82380PB
-	123c  82380AB
+	1239  82371FB PIIX IDE Interface
+	123b  82380PB PCI to PCI Docking Bridge
+	123c  82380AB (MISA) Mobile PCI-to-ISA Bridge
 	123d  683053 Programmable Interrupt Device
+# in" hidden" mode
+	123e  82466GX (IHPC) Integrated Hot-Plug Controller
 	123f  82466GX Integrated Hot-Plug Controller (IHPC)
-	1240  752 AGP
-	124b  82380FB
+	1240  82752 (752) AGP Graphics Accelerator
+	124b  82380FB (MPCI2) Mobile Docking Controller
 	1250  430HX - 82439HX TXC [Triton II]
 	1360  82806AA PCI64 Hub PCI Bridge
 	1361  82806AA PCI64 Hub Controller (HRes)
@@ -7782,7 +7988,7 @@
 	2446  Intel 537 [82801BA/BAM AC'97 Modem]
 		1025 1016  Travelmate 612 TX
 		104d 80df  Vaio PCG-FX403
-	2448  82801BAM/CAM PCI Bridge
+	2448  82801 PCI Bridge
 	2449  82801BA/BAM/CA/CAM Ethernet Controller
 		0e11 0012  EtherExpress PRO/100 VM
 		0e11 0091  EtherExpress PRO/100 VE
@@ -7824,7 +8030,7 @@
 		8086 4532  D815EEA2 mainboard
 		8086 4557  D815EGEW Mainboard
 	244c  82801BAM ISA Bridge (LPC)
-	244e  82801BA/CA/DB/EB/ER Hub interface to PCI Bridge
+	244e  82801 PCI Bridge
 		1014 0267  NetVista A30p
 	2450  82801E ISA Bridge (LPC)
 	2452  82801E USB
@@ -7879,45 +8085,45 @@
 	248b  82801CA Ultra ATA Storage Controller
 		15d9 3480  P4DP6
 	248c  82801CAM ISA Bridge (LPC)
-	24c0  82801DB (ICH4) LPC Bridge
+	24c0  82801DB/DBL (ICH4/ICH4-L) LPC Bridge
 		1014 0267  NetVista A30p
 		1462 5800  845PE Max (MS-6580)
-	24c2  82801DB (ICH4) USB UHCI #1
+	24c2  82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1
 		1014 0267  NetVista A30p
 		1071 8160  MIM2000
 		1462 5800  845PE Max (MS-6580)
-	24c3  82801DB/DBM (ICH4) SMBus Controller
+	24c3  82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller
 		1014 0267  NetVista A30p
 		1071 8160  MIM2000
 		1458 24c2  GA-8PE667 Ultra
 		1462 5800  845PE Max (MS-6580)
 		4c53 1090  Cx9 / Vx9 mainboard
-	24c4  82801DB (ICH4) USB UHCI #2
+	24c4  82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2
 		1014 0267  NetVista A30p
 		1071 8160  MIM2000
 		1462 5800  845PE Max (MS-6580)
 		4c53 1090  Cx9 / Vx9 mainboard
-	24c5  82801DB (ICH4) AC'97 Audio Controller
+	24c5  82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller
 		0e11 00b8  Analog Devices Inc. codec [SoundMAX]
 		1014 0267  NetVista A30p
 		1071 8160  MIM2000
 		1458 a002  GA-8PE667 Ultra
 		1462 5800  845PE Max (MS-6580)
-	24c6  82801DB (ICH4) AC'97 Modem Controller
+	24c6  82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller
 		1071 8160  MIM2000
-	24c7  82801DB (ICH4) USB UHCI #3
+	24c7  82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3
 		1014 0267  NetVista A30p
 		1071 8160  MIM2000
 		1462 5800  845PE Max (MS-6580)
 	24ca  82801DBM (ICH4) Ultra ATA Storage Controller
 		1071 8160  MIM2000
-	24cb  82801DB (ICH4) Ultra ATA 100 Storage Controller
+	24cb  82801DB/DBL (ICH4/ICH4-L) UltraATA-100 IDE Controller
 		1014 0267  NetVista A30p
 		1458 24c2  GA-8PE667 Ultra
 		1462 5800  845PE Max (MS-6580)
 		4c53 1090  Cx9 / Vx9 mainboard
 	24cc  82801DBM LPC Interface Controller
-	24cd  82801DB (ICH4) USB2 EHCI Controller
+	24cd  82801DB/DBM (ICH4/ICH4-M) USB 2.0 EHCI Controller
 		1014 0267  NetVista A30p
 		1071 8160  MIM2000
 		1462 3981  845PE Max (MS-6580)
@@ -7927,19 +8133,23 @@
 		103c 12bc  d530 CMT (DG746A)
 		1458 24d1  GA-8IPE1000 Pro2 motherboard (865PE)
 		1462 7280  865PE Neo2 (MS-6728)
+		8086 3427  S875WP1-E mainboard
 	24d2  82801EB/ER (ICH5/ICH5R) USB UHCI #1
 		103c 12bc  d530 CMT (DG746A)
 		1043 80a6  P4P800 Mainboard
 		1462 7280  865PE Neo2 (MS-6728)
+		8086 3427  S875WP1-E mainboard
 	24d3  82801EB/ER (ICH5/ICH5R) SMBus Controller
 		1043 80a6  P4P800 Mainboard
 		1458 24d2  GA-8IPE1000 Pro2 motherboard (865PE)
 		1462 7280  865PE Neo2 (MS-6728)
+		8086 3427  S875WP1-E mainboard
 	24d4  82801EB/ER (ICH5/ICH5R) USB UHCI #2
 		103c 12bc  d530 CMT (DG746A)
 		1043 80a6  P4P800 Mainboard
 		1458 24d2  GA-8IPE1000 Pro2 motherboard (865PE)
 		1462 7280  865PE Neo2 (MS-6728)
+		8086 3427  S875WP1-E mainboard
 	24d5  82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller
 		103c 12bc  Analog Devices codec [SoundMAX Integrated Digital Audio]
 		1043 80f3  P4P800 Mainboard
@@ -7950,22 +8160,26 @@
 		1043 80a6  P4P800 Mainboard
 		1458 24d2  GA-8IPE1000 Pro2 motherboard (865PE)
 		1462 7280  865PE Neo2 (MS-6728)
+		8086 3427  S875WP1-E mainboard
 	24db  82801EB/ER (ICH5/ICH5R) Ultra ATA 100 Storage Controller
 		103c 12bc  d530 CMT (DG746A)
 		1043 80a6  P4P800 Mainboard
 		1458 24d2  GA-8IPE1000 Pro2 motherboard (865PE)
 		1462 7280  865PE Neo2 (MS-6728)
 		1462 7580  MSI 875P
+		8086 3427  S875WP1-E mainboard
 	24dc  82801EB LPC Interface Controller
 	24dd  82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller
 		103c 12bc  d530 CMT (DG746A)
 		1043 80a6  P4P800 Mainboard
 		1458 5006  GA-8IPE1000 Pro2 motherboard (865PE)
 		1462 7280  865PE Neo2 (MS-6728)
+		8086 3427  S875WP1-E mainboard
 	24de  82801EB/ER (ICH5/ICH5R) USB UHCI #4
 		1043 80a6  P4P800 Mainboard
 		1458 24d2  GA-8IPE1000 Pro2 motherboard (865PE)
 		1462 7280  865PE Neo2 (MS-6728)
+		8086 3427  S875WP1-E mainboard
 	24df  82801EB (ICH5R) SATA (cc=RAID)
 	2500  82820 820 (Camino) Chipset Host Bridge (MCH)
 		1028 0095  Precision Workstation 220 Chipset
@@ -7984,23 +8198,23 @@
 	2534  82860 860 (Wombat) Chipset PCI Bridge
 	2540  E7500 Memory Controller Hub
 		15d9 3480  P4DP6
-	2541  E7000 Series Host RASUM Controller
+	2541  E7500/E7501 Host RASUM Controller
 		15d9 3480  P4DP6
 		4c53 1090  Cx9 / Vx9 mainboard
-	2543  E7000 Series Hub Interface B PCI-to-PCI Bridge
-	2544  E7000 Series Hub Interface B RASUM Controller
+	2543  E7500/E7501 Hub Interface B PCI-to-PCI Bridge
+	2544  E7500/E7501 Hub Interface B RASUM Controller
 		4c53 1090  Cx9 / Vx9 mainboard
-	2545  E7000 Series Hub Interface C PCI-to-PCI Bridge
-	2546  E7000 Series Hub Interface C RASUM Controller
-	2547  E7000 Series Hub Interface D PCI-to-PCI Bridge
-	2548  E7000 Series Hub Interface D RASUM Controller
+	2545  E7500/E7501 Hub Interface C PCI-to-PCI Bridge
+	2546  E7500/E7501 Hub Interface C RASUM Controller
+	2547  E7500/E7501 Hub Interface D PCI-to-PCI Bridge
+	2548  E7500/E7501 Hub Interface D RASUM Controller
 	254c  E7501 Memory Controller Hub
 		4c53 1090  Cx9 / Vx9 mainboard
 	2550  E7505 Memory Controller Hub
-	2551  E7000 Series RAS Controller
-	2552  E7000 Series Processor to AGP Controller
-	2553  E7000 Series Hub Interface B PCI-to-PCI Bridge
-	2554  E7000 Series Hub Interface B PCI-to-PCI Bridge RAS Controller
+	2551  E7505/E7205 Series RAS Controller
+	2552  E7505/E7205 PCI-to-AGP Bridge
+	2553  E7505 Hub Interface B PCI-to-PCI Bridge
+	2554  E7505 Hub Interface B PCI-to-PCI Bridge RAS Controller
 	255d  E7205 Memory Controller Hub
 	2560  82845G/GL[Brookdale-G]/GE/PE DRAM Controller/Host-Hub Interface
 		1458 2560  GA-8PE667 Ultra
@@ -8022,14 +8236,17 @@
 	2579  82875P Processor to AGP Controller
 	257b  82875P Processor to PCI to CSA Bridge
 	257e  82875P Processor to I/O Memory Interface
-	2580  Memory Controller Hub
-	2581  Memory Controller Hub PCI Express Port
-	2582  Graphics Controller
-	2584  Workstation Memory Controller Hub
-	2585  Workstation Memory Controller Hub PCI Express Port
+	2580  915G/P/GV Processor to I/O Controller
+	2581  915G/P/GV PCI Express Root Port
+	2582  82915G Express Chipset Family Graphics Controller
+	2584  925X Memory Controller Hub
+	2585  925X PCI Express Root Port
 	2588  Server Memory Controller Hub
 	2589  Server Memory Controller Hub PCI Express Port
 	258a  Graphics Controller
+	2590  Mobile Memory Controller Hub
+	2591  Mobile Memory Controller Hub PCI Express Port
+	2592  Mobile Graphics Controller
 	25a1  6300ESB LPC Interface Controller
 	25a2  6300ESB PATA Storage Controller
 	25a3  6300ESB SATA Storage Controller
@@ -8043,26 +8260,63 @@
 	25ad  6300ESB USB2 Enhanced Host Controller
 	25ae  6300ESB 64-bit PCI-X Bridge
 	25b0  6300ESB SATA RAID Controller
-	2640  I/O Controller Hub LPC
-	2641  I/O Controller Hub LPC
-	2642  I/O Controller Hub LPC
-	2651  I/O Controller Hub SATA cc=ide
-	2652  I/O Controller Hub SATA cc=raid
-	2658  I/O Controller Hub USB
-	2659  I/O Controller Hub USB
-	265a  I/O Controller Hub USB
-	265b  I/O Controller Hub USB
-	265c  I/O Controller Hub USB2
-	2660  I/O Controller Hub PCI Express Port 0
-	2662  I/O Controller Hub PCI Express Port 1
-	2664  I/O Controller Hub PCI Express Port 2
-	2666  I/O Controller Hub PCI Express Port 3
-	2668  I/O Controller Hub Audio
-	266a  I/O Controller Hub SMBus
-	266d  I/O Controller Hub Modem
-	266e  I/O Controller Hub Audio
-	266f  I/O Controller Hub PATA
-	2782  Graphics Controller
+	2600  Server Hub Interface
+	2601  Server Hub PCI Express x4 Port D
+	2602  Server Hub PCI Express x4 Port C0
+	2603  Server Hub PCI Express x4 Port C1
+	2604  Server Hub PCI Express x4 Port B0
+	2605  Server Hub PCI Express x4 Port B1
+	2606  Server Hub PCI Express x4 Port A0
+	2607  Server Hub PCI Express x4 Port A1
+	2608  Server Hub PCI Express x8 Port C
+	2609  Server Hub PCI Express x8 Port B
+	260a  Server Hub PCI Express x8 Port A
+	260c  Server Hub IMI Registers
+	2610  Server Hub System Bus, Boot, and Interrupt Registers
+	2611  Server Hub Address Mapping Registers
+	2612  Server Hub RAS Registers
+	2613  Server Hub Performance Monitoring Registers
+	2614  Server Hub Performance Monitoring Registers
+	2615  Server Hub Performance Monitoring Registers
+	2617  Server Hub Debug Registers
+	2618  Server Hub Debug Registers
+	2619  Server Hub Debug Registers
+	261a  Server Hub Debug Registers
+	261b  Server Hub Debug Registers
+	261c  Server Hub Debug Registers
+	261d  Server Hub Debug Registers
+	261e  Server Hub Debug Registers
+	2620  External Memory Bridge
+	2621  External Memory Bridge Control Registers
+	2622  External Memory Bridge Memory Interleaving Registers
+	2623  External Memory Bridge DDR Initialization and Calibration
+	2624  External Memory Bridge Reserved Registers
+	2625  External Memory Bridge Reserved Registers
+	2626  External Memory Bridge Reserved Registers
+	2627  External Memory Bridge Reserved Registers
+	2640  82801FB/FR (ICH6/ICH6R) LPC Interface Bridge
+	2641  82801FBM (ICH6M) LPC Interface Bridge
+	2642  82801FW/FRW (ICH6W/ICH6RW) LPC Interface Bridge
+	2651  82801FB/FW (ICH6/ICH6W) SATA Controller
+	2652  82801FR/FRW (ICH6R/ICH6RW) SATA Controller
+	2653  82801FBM (ICH6M) SATA Controller
+	2658  82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1
+	2659  82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2
+	265a  82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3
+	265b  82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4
+	265c  82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller
+	2660  82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1
+	2662  82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 2
+	2664  82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 3
+	2666  82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 4
+	2668  82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller
+	266a  82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller
+	266c  82801FB/FBM/FR/FW/FRW (ICH6 Family) LAN Controller
+	266d  82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Modem Controller
+	266e  82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller
+	266f  82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller
+	2782  82915G Express Chipset Family Graphics Controller
+	2792  Mobile Graphics Controller
 	3092  Integrated RAID
 	3200  GD31244 PCI-X SATA HBA
 	3340  82855PM Processor to I/O Controller
@@ -8092,7 +8346,7 @@
 	359a  Memory Controller Hub PCI Express Port C1
 	359b  Memory Controller Hub Extended Configuration Registers
 	359e  Workstation Memory Controller Hub
-	4220  Intel(R) PRO/Wireless 2200BG
+	4220  PRO/Wireless 2200BG
 	5200  EtherExpress PRO/100 Intelligent Server
 	5201  EtherExpress PRO/100 Intelligent Server
 		8086 0001  EtherExpress PRO/100 Server Ethernet Adapter
@@ -8155,7 +8409,7 @@
 	7601  82372FB PIIX5 IDE
 	7602  82372FB PIIX5 USB
 	7603  82372FB PIIX5 SMBus
-	7800  i740
+	7800  82740 (i740) AGP Graphics Accelerator
 		003d 0008  Starfighter AGP
 		003d 000b  Starfighter AGP
 		1092 0100  Stealth II G460
@@ -8175,7 +8429,9 @@
 	84e6  460GX - 82466GX Wide and fast PCI eXpander Bridge (WXB)
 	84ea  460GX - 84460GX AGP Bridge (GXB function 1)
 	8500  IXP4xx Family  Network Processor (IXP420, 421, 422, 425 and IXC1100)
-	9000  Intel IXP2000 Familly Network Processor
+	9000  Intel IXP2000 Family Network Processor
+	9001  Intel IXP2400 Network Processor
+	9004  Intel IXP2800 Network Processor
 	9621  Integrated RAID
 	9622  Integrated RAID
 	9641  Integrated RAID
@@ -8184,10 +8440,12 @@
 # observed, and documented in Intel revision note; new mask of 1011:0026
 	b154  21154 PCI-to-PCI Bridge
 	b555  21555 Non transparent PCI-to-PCI Bridge
+		1331 0030  Radisys ENP-2611
 		4c53 1050  CT7 mainboard
 		4c53 1051  CE7 mainboard
 		e4bf 1000  CC8-1-BLUES
 	ffff  450NX/GX [Orion] - 82453KX/GX Memory controller [BUG]
+8401  TRENDware International Inc.
 8800  Trigem Computer Inc.
 	2008  Video assistent component
 8866  T-Square Design Inc.
@@ -8352,15 +8610,18 @@
 	00c1  AIC-7899B U160/m
 	00c3  AIC-7899D U160/m
 	00c5  RAID subsystem HBA
-		1028 00c5  PowerEdge 2550
+		1028 00c5  PowerEdge 2400,2500,2550,4400
 	00cf  AIC-7899P U160/m
 		1028 00ce  PowerEdge 1400
 		1028 00d1  PowerEdge 2550
 		10f1 2462  Thunder K7 S2462
 		15d9 9005  Onboard SCSI Host Adapter
+		8086 3411  SDS2 Mainboard
 	0250  ServeRAID Controller
 		1014 0279  ServeRAID-xx
 		1014 028c  ServeRAID-xx
+# from kernel sources
+	0279  ServeRAID 6M
 	0283  AAC-RAID
 		9005 0283  Catapult
 	0284  AAC-RAID
@@ -8429,7 +8690,7 @@
 		1000 0012  1P2S
 	9845  PCI 9845 Multi-I/O Controller
 		1000 0006  0P6S (6 port 16550a serial card)
-	9855  PCI 9855 Multi-I/O Controller 4 Serial 1 Parallel
+	9855  PCI 9855 Multi-I/O Controller
 		1000 0014  1P4S
 9902  Stargen Inc.
 	0001  SG2010 PCI over Starfabric Bridge
@@ -8444,6 +8705,7 @@ a304  Sony
 a727  3Com Corporation
 aa42  Scitex Digital Video
 ac1e  Digital Receiver Technology Inc
+aecb  Adrienne Electronics Corporation
 b1b3  Shiva Europe Limited
 # Pinnacle should be 11bd, but they got it wrong several times --mj
 bd11  Pinnacle Systems, Inc. (Wrong ID)
@@ -8464,9 +8726,9 @@ d84d  Exsys
 dead  Indigita Corporation
 e000  Winbond
 	e000  W89C940
-# see : http://www.schoenfeld.de/inside/Inside_CWMK3.txt
-e159  Individual Computers - Jens Schoenfeld
-	0001  Intel 537
+# see also : http://www.schoenfeld.de/inside/Inside_CWMK3.txt maybe a misuse of TJN id or it use the TJN 3XX chip for other applic
+e159  Tiger Jet Network Inc.
+	0001  Tiger3XX Modem/ISDN interface
 		0059 0001  128k ISDN-S/T Adapter
 		0059 0003  128k ISDN-U Adapter
 	0002  Tiger100APC ISDN chipset
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index ee7b9feb6..e88017d6f 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -373,7 +373,10 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
 		child->bridge_ctl = bctl;
 
 		cmax = pci_scan_child_bus(child);
-		if (cmax > max) max = cmax;
+		if (cmax > max)
+			max = cmax;
+		if (child->subordinate > max)
+			max = child->subordinate;
 	} else {
 		/*
 		 * We need to assign a number to this bus which we always
@@ -571,6 +574,11 @@ static int pci_cfg_space_size(struct pci_dev *dev)
 	return PCI_CFG_SPACE_SIZE;
 }
 
+static void pci_release_bus_bridge_dev(struct device *dev)
+{
+	kfree(dev);
+}
+
 /*
  * Read the config data for a PCI device, sanity-check it
  * and fill in the dev structure...
@@ -640,7 +648,7 @@ pci_scan_single_device(struct pci_bus *bus, int devfn)
 		return NULL;
 	
 	/* Fix up broken headers */
-	pci_fixup_device(PCI_FIXUP_HEADER, dev);
+	pci_fixup_device(pci_fixup_header, dev);
 
 	/*
 	 * Add the device to our list of discovered devices
@@ -772,6 +780,7 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus,
 
 	memset(dev, 0, sizeof(*dev));
 	dev->parent = parent;
+	dev->release = pci_release_bus_bridge_dev;
 	sprintf(dev->bus_id, "pci%04x:%02x", pci_domain_nr(b), bus);
 	device_register(dev);
 	b->bridge = get_device(dev);
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 6e7c35013..164f738df 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1,10 +1,10 @@
 /*
- * $Id: quirks.c,v 1.5 1998/05/02 19:24:14 mj Exp $
- *
  *  This file contains work-arounds for many known PCI hardware
  *  bugs.  Devices present only on certain architectures (host
  *  bridges et cetera) should be handled in arch-specific code.
  *
+ *  Note: any quirks for hotpluggable devices must _NOT_ be declared __init.
+ *
  *  Copyright (c) 1999 Martin Mares <mj@ucw.cz>
  *
  *  The bridge optimization stuff has been removed. If you really
@@ -39,6 +39,7 @@ static void __devinit quirk_passive_release(struct pci_dev *dev)
 		}
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82441,	quirk_passive_release );
 
 /*  The VIA VP2/VP3/MVP3 seem to have some 'features'. There may be a workaround
     but VIA don't answer queries. If you happen to have good contacts at VIA
@@ -46,8 +47,6 @@ static void __devinit quirk_passive_release(struct pci_dev *dev)
     
     This appears to be BIOS not version dependent. So presumably there is a 
     chipset level fix */
-    
-
 int isa_dma_bridge_buggy;		/* Exported */
     
 static void __devinit quirk_isa_dma_hangs(struct pci_dev *dev)
@@ -57,34 +56,47 @@ static void __devinit quirk_isa_dma_hangs(struct pci_dev *dev)
 		printk(KERN_INFO "Activating ISA DMA hang workarounds.\n");
 	}
 }
+	/*
+	 * Its not totally clear which chipsets are the problematic ones
+	 * We know 82C586 and 82C596 variants are affected.
+	 */
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_0,	quirk_isa_dma_hangs );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C596,	quirk_isa_dma_hangs );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82371SB_0,  quirk_isa_dma_hangs );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL,	PCI_DEVICE_ID_AL_M1533, 	quirk_isa_dma_hangs );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_1,	quirk_isa_dma_hangs );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_2,	quirk_isa_dma_hangs );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_3,	quirk_isa_dma_hangs );
 
 int pci_pci_problems;
 
 /*
  *	Chipsets where PCI->PCI transfers vanish or hang
  */
-
 static void __devinit quirk_nopcipci(struct pci_dev *dev)
 {
-	if((pci_pci_problems&PCIPCI_FAIL)==0)
-	{
+	if ((pci_pci_problems & PCIPCI_FAIL)==0) {
 		printk(KERN_INFO "Disabling direct PCI/PCI transfers.\n");
-		pci_pci_problems|=PCIPCI_FAIL;
+		pci_pci_problems |= PCIPCI_FAIL;
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_5597,		quirk_nopcipci );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_496,		quirk_nopcipci );
 
 /*
  *	Triton requires workarounds to be used by the drivers
  */
- 
 static void __devinit quirk_triton(struct pci_dev *dev)
 {
-	if((pci_pci_problems&PCIPCI_TRITON)==0)
-	{
+	if ((pci_pci_problems&PCIPCI_TRITON)==0) {
 		printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
-		pci_pci_problems|=PCIPCI_TRITON;
+		pci_pci_problems |= PCIPCI_TRITON;
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82437, 	quirk_triton ); 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82437VX, 	quirk_triton ); 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82439, 	quirk_triton ); 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82439TX, 	quirk_triton ); 
 
 /*
  *	VIA Apollo KT133 needs PCI latency patch
@@ -104,19 +116,16 @@ static void __devinit quirk_vialatency(struct pci_dev *dev)
 	/* Ok we have a potential problem chipset here. Now see if we have
 	   a buggy southbridge */
 	   
-	p=pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, NULL);
-	if(p!=NULL)
-	{
+	p = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, NULL);
+	if (p!=NULL) {
 		pci_read_config_byte(p, PCI_CLASS_REVISION, &rev);
 		/* 0x40 - 0x4f == 686B, 0x10 - 0x2f == 686A; thanks Dan Hollis */
 		/* Check for buggy part revisions */
 		if (rev < 0x40 || rev > 0x42) 
 			return;
-	}
-	else
-	{
+	} else {
 		p = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, NULL);
-		if(p==NULL)	/* No problem parts */
+		if (p==NULL)	/* No problem parts */
 			return;
 		pci_read_config_byte(p, PCI_CLASS_REVISION, &rev);
 		/* Check for buggy part revisions */
@@ -145,27 +154,30 @@ static void __devinit quirk_vialatency(struct pci_dev *dev)
 	pci_write_config_byte(dev, 0x76, busarb);
 	printk(KERN_INFO "Applying VIA southbridge workaround.\n");
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8363_0,	quirk_vialatency );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8371_1,	quirk_vialatency );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8361,		quirk_vialatency );
 
 /*
  *	VIA Apollo VP3 needs ETBF on BT848/878
  */
- 
 static void __devinit quirk_viaetbf(struct pci_dev *dev)
 {
-	if((pci_pci_problems&PCIPCI_VIAETBF)==0)
-	{
+	if ((pci_pci_problems&PCIPCI_VIAETBF)==0) {
 		printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
-		pci_pci_problems|=PCIPCI_VIAETBF;
+		pci_pci_problems |= PCIPCI_VIAETBF;
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C597_0,	quirk_viaetbf );
+
 static void __devinit quirk_vsfx(struct pci_dev *dev)
 {
-	if((pci_pci_problems&PCIPCI_VSFX)==0)
-	{
+	if ((pci_pci_problems&PCIPCI_VSFX)==0) {
 		printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
-		pci_pci_problems|=PCIPCI_VSFX;
+		pci_pci_problems |= PCIPCI_VSFX;
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C576,	quirk_vsfx );
 
 /*
  *	Ali Magik requires workarounds to be used by the drivers
@@ -173,36 +185,38 @@ static void __devinit quirk_vsfx(struct pci_dev *dev)
  *	workaround applied too
  *	[Info kindly provided by ALi]
  */	
- 
 static void __init quirk_alimagik(struct pci_dev *dev)
 {
-	if((pci_pci_problems&PCIPCI_ALIMAGIK)==0)
-	{
+	if ((pci_pci_problems&PCIPCI_ALIMAGIK)==0) {
 		printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
-		pci_pci_problems|=PCIPCI_ALIMAGIK|PCIPCI_TRITON;
+		pci_pci_problems |= PCIPCI_ALIMAGIK|PCIPCI_TRITON;
 	}
 }
-
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 	PCI_DEVICE_ID_AL_M1647, 	quirk_alimagik );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 	PCI_DEVICE_ID_AL_M1651, 	quirk_alimagik );
 
 /*
  *	Natoma has some interesting boundary conditions with Zoran stuff
  *	at least
  */
- 
 static void __devinit quirk_natoma(struct pci_dev *dev)
 {
-	if((pci_pci_problems&PCIPCI_NATOMA)==0)
-	{
+	if ((pci_pci_problems&PCIPCI_NATOMA)==0) {
 		printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
-		pci_pci_problems|=PCIPCI_NATOMA;
+		pci_pci_problems |= PCIPCI_NATOMA;
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82441, 	quirk_natoma ); 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443LX_0, 	quirk_natoma ); 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443LX_1, 	quirk_natoma ); 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_0, 	quirk_natoma ); 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_1, 	quirk_natoma ); 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_2, 	quirk_natoma );
 
 /*
  *  S3 868 and 968 chips report region size equal to 32M, but they decode 64M.
  *  If it's needed, re-allocate the region.
  */
-
 static void __devinit quirk_s3_64M(struct pci_dev *dev)
 {
 	struct resource *r = &dev->resource[0];
@@ -212,6 +226,8 @@ static void __devinit quirk_s3_64M(struct pci_dev *dev)
 		r->end = 0x3ffffff;
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3,	PCI_DEVICE_ID_S3_868,		quirk_s3_64M );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3,	PCI_DEVICE_ID_S3_968,		quirk_s3_64M );
 
 static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region, unsigned size, int nr)
 {
@@ -231,7 +247,6 @@ static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region, unsi
  *	ATI Northbridge setups MCE the processor if you even
  *	read somewhere between 0x3b0->0x3bb or read 0x3d3
  */
- 
 static void __devinit quirk_ati_exploding_mce(struct pci_dev *dev)
 {
 	printk(KERN_INFO "ATI Northbridge, reserving I/O ports 0x3b0 to 0x3bb.\n");
@@ -239,6 +254,7 @@ static void __devinit quirk_ati_exploding_mce(struct pci_dev *dev)
 	request_region(0x3b0, 0x0C, "RadeonIGP");
 	request_region(0x3d3, 0x01, "RadeonIGP");
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI,	PCI_DEVICE_ID_ATI_RS100,   quirk_ati_exploding_mce );
 
 /*
  * Let's make the southbridge information explicit instead
@@ -260,6 +276,7 @@ static void __devinit quirk_ali7101_acpi(struct pci_dev *dev)
 	pci_read_config_word(dev, 0xE2, &region);
 	quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1);
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL,	PCI_DEVICE_ID_AL_M7101,		quirk_ali7101_acpi );
 
 /*
  * PIIX4 ACPI: Two IO regions pointed to by longwords at
@@ -275,6 +292,7 @@ static void __devinit quirk_piix4_acpi(struct pci_dev *dev)
 	pci_read_config_dword(dev, 0x90, &region);
 	quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1);
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_3,	quirk_piix4_acpi );
 
 /*
  * ICH4, ICH4-M, ICH5, ICH5-M ACPI: Three IO regions pointed to by longwords at
@@ -291,6 +309,15 @@ static void __devinit quirk_ich4_lpc_acpi(struct pci_dev *dev)
 	pci_read_config_dword(dev, 0x58, &region);
 	quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1);
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AA_0,		quirk_ich4_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AB_0,		quirk_ich4_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801BA_0,		quirk_ich4_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801BA_10,	quirk_ich4_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801CA_0,		quirk_ich4_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801CA_12,	quirk_ich4_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801DB_0,		quirk_ich4_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801DB_12,	quirk_ich4_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801EB_0,		quirk_ich4_lpc_acpi );
 
 /*
  * VIA ACPI: One IO region pointed to by longword at
@@ -308,6 +335,7 @@ static void __devinit quirk_vt82c586_acpi(struct pci_dev *dev)
 		quirk_io_region(dev, region, 256, PCI_BRIDGE_RESOURCES);
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_3,	quirk_vt82c586_acpi );
 
 /*
  * VIA VT82C686 ACPI: Three IO region pointed to by (long)words at
@@ -330,6 +358,7 @@ static void __devinit quirk_vt82c686_acpi(struct pci_dev *dev)
 	smb &= PCI_BASE_ADDRESS_IO_MASK;
 	quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2);
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_4,	quirk_vt82c686_acpi );
 
 
 #ifdef CONFIG_X86_IO_APIC 
@@ -358,6 +387,7 @@ static void __devinit quirk_via_ioapic(struct pci_dev *dev)
 	/* Offset 0x58: External APIC IRQ output control */
 	pci_write_config_byte (dev, 0x58, tmp);
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686,	quirk_via_ioapic );
 
 /*
  * The AMD io apic can hang the box when an apic irq is masked.
@@ -368,30 +398,29 @@ static void __devinit quirk_via_ioapic(struct pci_dev *dev)
  * noapic specified. For the moment we assume its the errata. We may be wrong
  * of course. However the advice is demonstrably good even if so..
  */
- 
 static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
 {
 	u8 rev;
 
 	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
-	if(rev >= 0x02)
-	{
+	if (rev >= 0x02) {
 		printk(KERN_WARNING "I/O APIC: AMD Errata #22 may be present. In the event of instability try\n");
 		printk(KERN_WARNING "        : booting with the \"noapic\" option.\n");
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_VIPER_7410,	quirk_amd_ioapic );
 
 static void __init quirk_ioapic_rmw(struct pci_dev *dev)
 {
 	if (dev->devfn == 0 && dev->bus->number == 0)
 		sis_apic_bug = 1;
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,	PCI_ANY_ID,			quirk_ioapic_rmw );
 
 #define AMD8131_revA0        0x01
 #define AMD8131_revB0        0x11
 #define AMD8131_MISC         0x40
 #define AMD8131_NIOAMODE_BIT 0
-
 static void __init quirk_amd_8131_ioapic(struct pci_dev *dev) 
 { 
         unsigned char revid, tmp;
@@ -407,6 +436,7 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev)
                 pci_write_config_byte( dev, AMD8131_MISC, tmp);
         }
 } 
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC,         quirk_amd_8131_ioapic ); 
 
 #endif /* CONFIG_X86_IO_APIC */
 
@@ -444,6 +474,8 @@ static void __devinit quirk_via_acpi(struct pci_dev *d)
 	if (irq && (irq != 2))
 		d->irq = irq;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_3,	quirk_via_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_4,	quirk_via_acpi );
 
 static void __devinit quirk_via_irqpic(struct pci_dev *dev)
 {
@@ -459,6 +491,9 @@ static void __devinit quirk_via_irqpic(struct pci_dev *dev)
 		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_2,	quirk_via_irqpic );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_5,	quirk_via_irqpic );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_6,	quirk_via_irqpic );
 
 
 /*
@@ -480,6 +515,8 @@ static void __devinit quirk_piix3_usb(struct pci_dev *dev)
 	legsup &= 0x50ef;
 	pci_write_config_word(dev, 0xc0, legsup);
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371SB_2,	quirk_piix3_usb );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_2,	quirk_piix3_usb );
 
 /*
  * VIA VT82C598 has its device ID settable and many BIOSes
@@ -492,6 +529,7 @@ static void __devinit quirk_vt82c598_id(struct pci_dev *dev)
 	pci_write_config_byte(dev, 0xfc, 0);
 	pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device);
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C597_0,	quirk_vt82c598_id );
 
 /*
  * CardBus controllers have a legacy base address that enables them
@@ -505,6 +543,7 @@ static void __devinit quirk_cardbus_legacy(struct pci_dev *dev)
 		return;
 	pci_write_config_dword(dev, PCI_CB_LEGACY_MODE_BASE, 0);
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID,		PCI_ANY_ID,			quirk_cardbus_legacy );
 
 /*
  * Following the PCI ordering rules is optional on the AMD762. I'm not
@@ -513,13 +552,11 @@ static void __devinit quirk_cardbus_legacy(struct pci_dev *dev)
  * To be fair to AMD, it follows the spec by default, its BIOS people
  * who turn it off!
  */
- 
 static void __devinit quirk_amd_ordering(struct pci_dev *dev)
 {
 	u32 pcic;
 	pci_read_config_dword(dev, 0x4C, &pcic);
-	if((pcic&6)!=6)
-	{
+	if ((pcic&6)!=6) {
 		pcic |= 6;
 		printk(KERN_WARNING "BIOS failed to enable PCI standards compliance, fixing this error.\n");
 		pci_write_config_dword(dev, 0x4C, pcic);
@@ -528,6 +565,7 @@ static void __devinit quirk_amd_ordering(struct pci_dev *dev)
 		pci_write_config_dword(dev, 0x84, pcic);
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering );
 
 /*
  *	DreamWorks provided workaround for Dunord I-3000 problem
@@ -536,18 +574,26 @@ static void __devinit quirk_amd_ordering(struct pci_dev *dev)
  *	assigned to it. We force a larger allocation to ensure that
  *	nothing gets put too close to it.
  */
-
 static void __devinit quirk_dunord ( struct pci_dev * dev )
 {
-	struct resource * r = & dev -> resource [ 1 ];
-	r -> start = 0;
-	r -> end = 0xffffff;
+	struct resource *r = &dev->resource [1];
+	r->start = 0;
+	r->end = 0xffffff;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DUNORD,	PCI_DEVICE_ID_DUNORD_I3000,	quirk_dunord );
 
+/*
+ * i82380FB mobile docking controller: its PCI-to-PCI bridge
+ * is subtractive decoding (transparent), and does indicate this
+ * in the ProgIf. Unfortunately, the ProgIf value is wrong - 0x80
+ * instead of 0x01.
+ */
 static void __devinit quirk_transparent_bridge(struct pci_dev *dev)
 {
 	dev->transparent = 1;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82380FB,	quirk_transparent_bridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA,	0x605,	quirk_transparent_bridge );
 
 /*
  * Common misconfiguration of the MediaGX/Geode PCI master that will
@@ -555,7 +601,6 @@ static void __devinit quirk_transparent_bridge(struct pci_dev *dev)
  * datasheets found at http://www.national.com/ds/GX for info on what
  * these bits do.  <christer@weinigel.se>
  */
- 
 static void __init quirk_mediagx_master(struct pci_dev *dev)
 {
 	u8 reg;
@@ -566,6 +611,7 @@ static void __init quirk_mediagx_master(struct pci_dev *dev)
                 pci_write_config_byte(dev, 0x41, reg);
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CYRIX,	PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master );
 
 /*
  * As per PCI spec, ignore base address registers 0-3 of the IDE controllers
@@ -584,7 +630,6 @@ static void __init quirk_mediagx_master(struct pci_dev *dev)
  * we do now ? We don't want is pci_enable_device to come along
  * and assign new resources. Both approaches work for that.
  */ 
-
 static void __devinit quirk_ide_bases(struct pci_dev *dev)
 {
        struct resource *res;
@@ -616,34 +661,33 @@ static void __devinit quirk_ide_bases(struct pci_dev *dev)
        printk(KERN_INFO "PCI: Ignoring BAR%d-%d of IDE controller %s\n",
               first_bar, last_bar, pci_name(dev));
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID,             PCI_ANY_ID,                     quirk_ide_bases );
 
 /*
  *	Ensure C0 rev restreaming is off. This is normally done by
  *	the BIOS but in the odd case it is not the results are corruption
  *	hence the presence of a Linux check
  */
- 
 static void __init quirk_disable_pxb(struct pci_dev *pdev)
 {
 	u16 config;
 	u8 rev;
 	
 	pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-	if(rev != 0x04)		/* Only C0 requires this */
+	if (rev != 0x04)		/* Only C0 requires this */
 		return;
 	pci_read_config_word(pdev, 0x40, &config);
-	if(config & (1<<6))
-	{
+	if (config & (1<<6)) {
 		config &= ~(1<<6);
 		pci_write_config_word(pdev, 0x40, config);
 		printk(KERN_INFO "PCI: C0 revision 450NX. Disabling PCI restreaming.\n");
 	}
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82454NX,	quirk_disable_pxb );
 
 /*
  *	VIA northbridges care about PCI_INTERRUPT_LINE
  */
- 
 int interrupt_line_quirk;
 
 static void __devinit quirk_via_bridge(struct pci_dev *pdev)
@@ -651,6 +695,7 @@ static void __devinit quirk_via_bridge(struct pci_dev *pdev)
 	if(pdev->devfn == 0)
 		interrupt_line_quirk = 1;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_ANY_ID,                     quirk_via_bridge );
 
 /*
  *	Serverworks CSB5 IDE does not fully support native mode
@@ -667,15 +712,16 @@ static void __init quirk_svwks_csb5ide(struct pci_dev *pdev)
 		quirk_ide_bases(pdev);
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, quirk_svwks_csb5ide );
 
 /* This was originally an Alpha specific thing, but it really fits here.
  * The i82375 PCI/EISA bridge appears as non-classified. Fix that.
  */
-
 static void __init quirk_eisa_bridge(struct pci_dev *dev)
 {
 	dev->class = PCI_CLASS_BRIDGE_EISA << 8;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82375,	quirk_eisa_bridge );
 
 /*
  * On ASUS P4B boards, the SMBus PCI Device within the ICH2/4 southbridge
@@ -689,7 +735,6 @@ static void __init quirk_eisa_bridge(struct pci_dev *dev)
  * becomes necessary to do this tweak in two steps -- I've chosen the Host
  * bridge as trigger.
  */
-
 static int __initdata asus_hides_smbus = 0;
 
 static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
@@ -699,6 +744,7 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
 			switch(dev->subsystem_device) {
 			case 0x8070: /* P4B */
 			case 0x8088: /* P4B533 */
+			case 0x1626: /* L3C notebook */
 				asus_hides_smbus = 1;
 			}
 		if (dev->device == PCI_DEVICE_ID_INTEL_82845G_HB)
@@ -730,8 +776,20 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
 			case 0x0890: /* HP Compaq nc6000 */
 				asus_hides_smbus = 1;
 			}
+		if (dev->device == PCI_DEVICE_ID_INTEL_82865_HB)
+			switch (dev->subsystem_device) {
+			case 0x12bc: /* HP D330L */
+				asus_hides_smbus = 1;
+			}
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82845_HB,	asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82845G_HB,	asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82850_HB,	asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82865_HB,	asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_7205_0,	asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82855PM_HB,	asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82855GM_HB,	asus_hides_smbus_hostbridge );
 
 static void __init asus_hides_smbus_lpc(struct pci_dev *dev)
 {
@@ -744,12 +802,17 @@ static void __init asus_hides_smbus_lpc(struct pci_dev *dev)
 	if (val & 0x8) {
 		pci_write_config_word(dev, 0xF2, val & (~0x8));
 		pci_read_config_word(dev, 0xF2, &val);
-		if(val & 0x8)
+		if (val & 0x8)
 			printk(KERN_INFO "PCI: i801 SMBus device continues to play 'hide and seek'! 0x%x\n", val);
 		else
 			printk(KERN_INFO "PCI: Enabled i801 SMBus device\n");
 	}
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_0,	asus_hides_smbus_lpc );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801BA_0,	asus_hides_smbus_lpc );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801CA_12,	asus_hides_smbus_lpc );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_12,	asus_hides_smbus_lpc );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801EB_0,	asus_hides_smbus_lpc );
 
 /*
  * SiS 96x south bridge: BIOS typically hides SMBus device...
@@ -803,6 +866,19 @@ static void __init quirk_sis_96x_compatible(struct pci_dev *dev)
 {
 	sis_96x_compatible = 1;
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_645,		quirk_sis_96x_compatible );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_646,		quirk_sis_96x_compatible );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_648,		quirk_sis_96x_compatible );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_650,		quirk_sis_96x_compatible );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_651,		quirk_sis_96x_compatible );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_735,		quirk_sis_96x_compatible );
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_503,		quirk_sis_503 );
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_961,		quirk_sis_96x_smbus );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_962,		quirk_sis_96x_smbus );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_963,		quirk_sis_96x_smbus );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_LPC,		quirk_sis_96x_smbus );
 
 #ifdef CONFIG_X86_IO_APIC
 static void __init quirk_alder_ioapic(struct pci_dev *pdev)
@@ -815,16 +891,17 @@ static void __init quirk_alder_ioapic(struct pci_dev *pdev)
 	/* the first BAR is the location of the IO APIC...we must
 	 * not touch this (and it's already covered by the fixmap), so
 	 * forcibly insert it into the resource tree */
-	if(pci_resource_start(pdev, 0) && pci_resource_len(pdev, 0))
+	if (pci_resource_start(pdev, 0) && pci_resource_len(pdev, 0))
 		insert_resource(&iomem_resource, &pdev->resource[0]);
 
 	/* The next five BARs all seem to be rubbish, so just clean
 	 * them out */
-	for(i=1; i < 6; i++) {
+	for (i=1; i < 6; i++) {
 		memset(&pdev->resource[i], 0, sizeof(pdev->resource[i]));
 	}
 
 }
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_EESSC,	quirk_alder_ioapic );
 #endif
 
 #ifdef CONFIG_SCSI_SATA
@@ -898,6 +975,7 @@ static void __init quirk_intel_ide_combined(struct pci_dev *pdev)
 	else
 		request_region(0x170, 8, "libata");	/* port 1 */
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,    PCI_ANY_ID,	  quirk_intel_ide_combined );
 #endif /* CONFIG_SCSI_SATA */
 
 int pciehp_msi_quirk;
@@ -906,163 +984,45 @@ static void __devinit quirk_pciehp_msi(struct pci_dev *pdev)
 {
 	pciehp_msi_quirk = 1;
 }
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_SMCH,	quirk_pciehp_msi );
 
-/*
- *  The main table of quirks.
- *
- *  Note: any hooks for hotpluggable devices in this table must _NOT_
- *        be declared __init.
- */
-
-static struct pci_fixup pci_fixups[] __devinitdata = {
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_DUNORD,	PCI_DEVICE_ID_DUNORD_I3000,	quirk_dunord },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82441,	quirk_passive_release },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82441,	quirk_passive_release },
-	/*
-	 * Its not totally clear which chipsets are the problematic ones
-	 * We know 82C586 and 82C596 variants are affected.
-	 */
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_0,	quirk_isa_dma_hangs },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C596,	quirk_isa_dma_hangs },
-	{ PCI_FIXUP_FINAL,      PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82371SB_0,  quirk_isa_dma_hangs },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_AL,	PCI_DEVICE_ID_AL_M1533, 	quirk_isa_dma_hangs },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82454NX,	quirk_disable_pxb },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_1,	quirk_isa_dma_hangs },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_2,	quirk_isa_dma_hangs },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_3,	quirk_isa_dma_hangs },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_S3,	PCI_DEVICE_ID_S3_868,		quirk_s3_64M },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_S3,	PCI_DEVICE_ID_S3_968,		quirk_s3_64M },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82437, 	quirk_triton }, 
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82437VX, 	quirk_triton }, 
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82439, 	quirk_triton }, 
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82439TX, 	quirk_triton }, 
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82441, 	quirk_natoma }, 
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443LX_0, 	quirk_natoma }, 
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443LX_1, 	quirk_natoma }, 
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_0, 	quirk_natoma }, 
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_1, 	quirk_natoma }, 
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_2, 	quirk_natoma },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_5597,		quirk_nopcipci },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_496,		quirk_nopcipci },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_503,		quirk_sis_503 },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_LPC,		quirk_sis_96x_smbus },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_645,		quirk_sis_96x_compatible },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_646,		quirk_sis_96x_compatible },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_648,		quirk_sis_96x_compatible },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_650,		quirk_sis_96x_compatible },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_651,		quirk_sis_96x_compatible },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_735,		quirk_sis_96x_compatible },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_961,		quirk_sis_96x_smbus },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_962,		quirk_sis_96x_smbus },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_963,		quirk_sis_96x_smbus },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_AL, 	PCI_DEVICE_ID_AL_M1647, 	quirk_alimagik },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_AL, 	PCI_DEVICE_ID_AL_M1651, 	quirk_alimagik },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8363_0,	quirk_vialatency },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8371_1,	quirk_vialatency },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8361,	quirk_vialatency },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C576,	quirk_vsfx },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C597_0,	quirk_viaetbf },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C597_0,	quirk_vt82c598_id },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_3,	quirk_vt82c586_acpi },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_4,	quirk_vt82c686_acpi },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_3,	quirk_piix4_acpi },
-
-	/* Intel LPC interface bridges all have 128 bytes of magic ACPI/TCO regs and 64 bytes of GPIO */
-	{ PCI_FIXUP_HEADER,     PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AA_0,	quirk_ich4_lpc_acpi },
-	{ PCI_FIXUP_HEADER,     PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AB_0,	quirk_ich4_lpc_acpi },
-	{ PCI_FIXUP_HEADER,     PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801BA_0,	quirk_ich4_lpc_acpi },
-	{ PCI_FIXUP_HEADER,     PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801BA_10,	quirk_ich4_lpc_acpi },
-	{ PCI_FIXUP_HEADER,     PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801CA_0,	quirk_ich4_lpc_acpi },
-	{ PCI_FIXUP_HEADER,     PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801CA_12,	quirk_ich4_lpc_acpi },
-	{ PCI_FIXUP_HEADER,     PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801DB_0,	quirk_ich4_lpc_acpi },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_12,	quirk_ich4_lpc_acpi },
-	{ PCI_FIXUP_HEADER,     PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801EB_0,	quirk_ich4_lpc_acpi },
-
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_AL,	PCI_DEVICE_ID_AL_M7101,		quirk_ali7101_acpi },
- 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371SB_2,	quirk_piix3_usb },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_2,	quirk_piix3_usb },
-	{ PCI_FIXUP_HEADER,     PCI_ANY_ID,             PCI_ANY_ID,                     quirk_ide_bases },
-	{ PCI_FIXUP_HEADER,     PCI_VENDOR_ID_VIA,	PCI_ANY_ID,                     quirk_via_bridge },
-	{ PCI_FIXUP_FINAL,	PCI_ANY_ID,		PCI_ANY_ID,			quirk_cardbus_legacy },
-
-#ifdef CONFIG_X86_IO_APIC 
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686,	quirk_via_ioapic },
-	{ PCI_FIXUP_FINAL, 	PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_VIPER_7410,	quirk_amd_ioapic },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_SI,	PCI_ANY_ID,			quirk_ioapic_rmw },
-        { PCI_FIXUP_FINAL,      PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC,
-          quirk_amd_8131_ioapic }, 
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_EESSC,	quirk_alder_ioapic },
-#endif
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_3,	quirk_via_acpi },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_4,	quirk_via_acpi },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_2,	quirk_via_irqpic },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_5,	quirk_via_irqpic },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_6,	quirk_via_irqpic },
-
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering },
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_ATI,	PCI_DEVICE_ID_ATI_RS100,   quirk_ati_exploding_mce },
-	/*
-	 * i82380FB mobile docking controller: its PCI-to-PCI bridge
-	 * is subtractive decoding (transparent), and does indicate this
-	 * in the ProgIf. Unfortunately, the ProgIf value is wrong - 0x80
-	 * instead of 0x01.
-	 */
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82380FB,	quirk_transparent_bridge },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_TOSHIBA,	0x605,	quirk_transparent_bridge },
-
-	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_CYRIX,	PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master },
-
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, quirk_svwks_csb5ide },
-
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82375,	quirk_eisa_bridge },
 
-	/*
-	 * on Asus P4B boards, the i801SMBus device is disabled at startup.
-	 * this also goes for boards in HP Compaq nc6000 and nc8000 notebooks.
-	 */
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82845_HB,	asus_hides_smbus_hostbridge },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82845G_HB,	asus_hides_smbus_hostbridge },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82850_HB,	asus_hides_smbus_hostbridge },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_7205_0,	asus_hides_smbus_hostbridge },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82855PM_HB,	asus_hides_smbus_hostbridge },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82855GM_HB,	asus_hides_smbus_hostbridge },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_0,	asus_hides_smbus_lpc },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801BA_0,	asus_hides_smbus_lpc },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_12,	asus_hides_smbus_lpc },
-
-#ifdef CONFIG_SCSI_SATA
-	/* Fixup BIOSes that configure Parallel ATA (PATA / IDE) and
-	 * Serial ATA (SATA) into the same PCI ID.
-	 */
-	{ PCI_FIXUP_FINAL,      PCI_VENDOR_ID_INTEL,    PCI_ANY_ID,
-	  quirk_intel_ide_combined },
-#endif /* CONFIG_SCSI_SATA */
-
-	{ PCI_FIXUP_FINAL,      PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_SMCH,	quirk_pciehp_msi },
-
-	{ 0 }
-};
-
-
-static void pci_do_fixups(struct pci_dev *dev, int pass, struct pci_fixup *f)
+static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end)
 {
-	while (f->pass) {
-		if (f->pass == pass &&
- 		    (f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) &&
+	while (f < end) {
+		if ((f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) &&
  		    (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) {
-#ifdef DEBUG
-			printk(KERN_INFO "PCI: Calling quirk %p for %s\n", f->hook, pci_name(dev));
-#endif
+			pr_debug(KERN_INFO "PCI: Calling quirk %p for %s\n", f->hook, pci_name(dev));
 			f->hook(dev);
 		}
 		f++;
 	}
 }
 
-void pci_fixup_device(int pass, struct pci_dev *dev)
+extern struct pci_fixup __start_pci_fixups_header[];
+extern struct pci_fixup __end_pci_fixups_header[];
+extern struct pci_fixup __start_pci_fixups_final[];
+extern struct pci_fixup __end_pci_fixups_final[];
+
+void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
 {
-	pci_do_fixups(dev, pass, pcibios_fixups);
-	pci_do_fixups(dev, pass, pci_fixups);
+	struct pci_fixup *start, *end;
+
+	switch(pass) {
+	case pci_fixup_header:
+		start = __start_pci_fixups_header;
+		end = __end_pci_fixups_header;
+		break;
+
+	case pci_fixup_final:
+		start = __start_pci_fixups_final;
+		end = __end_pci_fixups_final;
+		break;
+	default:
+		/* stupid compiler warning, you would think with an enum... */
+		return;
+	}
+	pci_do_fixups(dev, start, end);
 }
 
 EXPORT_SYMBOL(pciehp_msi_quirk);
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 5ef19b175..889b2e3ac 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -59,6 +59,18 @@ int pci_remove_device_safe(struct pci_dev *dev)
 }
 EXPORT_SYMBOL(pci_remove_device_safe);
 
+void pci_remove_bus(struct pci_bus *b)
+{
+	pci_proc_detach_bus(b);
+
+	spin_lock(&pci_bus_lock);
+	list_del(&b->node);
+	spin_unlock(&pci_bus_lock);
+
+	class_device_unregister(&b->class_dev);
+}
+EXPORT_SYMBOL(pci_remove_bus);
+
 /**
  * pci_remove_bus_device - remove a PCI device and any children
  * @dev: the device to remove
@@ -77,13 +89,7 @@ void pci_remove_bus_device(struct pci_dev *dev)
 		struct pci_bus *b = dev->subordinate;
 
 		pci_remove_behind_bridge(dev);
-		pci_proc_detach_bus(b);
-
-		spin_lock(&pci_bus_lock);
-		list_del(&b->node);
-		spin_unlock(&pci_bus_lock);
-
-		class_device_unregister(&b->class_dev);
+		pci_remove_bus(b);
 		dev->subordinate = NULL;
 	}
 
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 7f0f6c209..e21250c39 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -537,10 +537,11 @@ pci_assign_unassigned_resources(void)
 
 	/* Depth first, calculate sizes and alignments of all
 	   subordinate buses. */
-	for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next)
+	list_for_each(ln, &pci_root_buses) {
 		pci_bus_size_bridges(pci_bus_b(ln));
+	}
 	/* Depth last, allocate resources and update the hardware. */
-	for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next) {
+	list_for_each(ln, &pci_root_buses) {
 		pci_bus_assign_resources(pci_bus_b(ln));
 		pci_enable_bridges(pci_bus_b(ln));
 	}
diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c
index bd79f3bd1..124225edc 100644
--- a/drivers/pcmcia/au1000_generic.c
+++ b/drivers/pcmcia/au1000_generic.c
@@ -566,7 +566,6 @@ static int
 au1000_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map)
 {
 	unsigned int speed;
-	unsigned long start;
 	u_long flags;
 
 	if(map->map>=MAX_WIN){
@@ -588,25 +587,19 @@ au1000_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map)
 	}
 
 	spin_lock_irqsave(&pcmcia_lock, flags);
-	start=map->sys_start;
-
-	if(map->sys_stop==0)
-		map->sys_stop=MAP_SIZE-1;
-
 	if (map->flags & MAP_ATTRIB) {
-		map->sys_start = pcmcia_socket[sock].phys_attr + 
+		map->static_start = pcmcia_socket[sock].phys_attr + 
 			map->card_start;
 	}
 	else {
-		map->sys_start = pcmcia_socket[sock].phys_mem + 
+		map->static_start = pcmcia_socket[sock].phys_mem + 
 			map->card_start;
 	}
 
-	map->sys_stop=map->sys_start+(map->sys_stop-start);
 	pcmcia_socket[sock].mem_map[map->map]=*map;
 	spin_unlock_irqrestore(&pcmcia_lock, flags);
-	debug(3, "set_mem_map %d start %x stop %x card_start %x\n", 
-			map->map, map->sys_start, map->sys_stop, 
+	debug(3, "set_mem_map %d start %x card_start %x\n", 
+			map->map, map->static_start,
 			map->card_start);
 	return 0;
 
diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
index 4dab2ffc8..1b86c6d3a 100644
--- a/drivers/pcmcia/cardbus.c
+++ b/drivers/pcmcia/cardbus.c
@@ -85,7 +85,7 @@
     
 =====================================================================*/
 
-static u_int xlate_rom_addr(u_char * b, u_int addr)
+static u_int xlate_rom_addr(void __iomem *b, u_int addr)
 {
 	u_int img = 0, ofs = 0, sz;
 	u_short data;
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index b78d41a3c..317ca50a3 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -103,7 +103,7 @@ void release_cis_mem(struct pcmcia_socket *s)
  * If flags & MAP_ATTRIB, map the attribute space, otherwise
  * map the memory space.
  */
-static unsigned char *
+static void __iomem *
 set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags)
 {
     pccard_mem_map *mem = &s->cis_mem;
@@ -114,8 +114,6 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag
 	    printk(KERN_NOTICE "cs: unable to map card memory!\n");
 	    return NULL;
 	}
-	mem->sys_start = mem->res->start;
-	mem->sys_stop = mem->res->end;
 	s->cis_virt = ioremap(mem->res->start, s->map_size);
     }
     mem->card_start = card_offset;
@@ -124,7 +122,7 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag
     if (s->features & SS_CAP_STATIC_MAP) {
 	if (s->cis_virt)
 	    iounmap(s->cis_virt);
-	s->cis_virt = ioremap(mem->sys_start, s->map_size);
+	s->cis_virt = ioremap(mem->static_start, s->map_size);
     }
     return s->cis_virt;
 }
@@ -143,7 +141,8 @@ set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flag
 int read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
 		 u_int len, void *ptr)
 {
-    u_char *sys, *end, *buf = ptr;
+    void __iomem *sys, *end;
+    unsigned char *buf = ptr;
     
     cs_dbg(s, 3, "read_cis_mem(%d, %#x, %u)\n", attr, addr, len);
 
@@ -206,7 +205,8 @@ int read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
 void write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
 		   u_int len, void *ptr)
 {
-    u_char *sys, *end, *buf = ptr;
+    void __iomem *sys, *end;
+    unsigned char *buf = ptr;
     
     cs_dbg(s, 3, "write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
 
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index f796bc99c..c33ac2756 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -427,8 +427,6 @@ static int send_event(struct pcmcia_socket *s, event_t event, int priority)
     return ret;
 } /* send_event */
 
-#define cs_to_timeout(cs) (((cs) * HZ + 99) / 100)
-
 static void socket_remove_drivers(struct pcmcia_socket *skt)
 {
 	client_t *client;
@@ -448,8 +446,7 @@ static void socket_shutdown(struct pcmcia_socket *skt)
 
 	socket_remove_drivers(skt);
 	skt->state &= SOCKET_INUSE|SOCKET_PRESENT;
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(cs_to_timeout(shutdown_delay));
+	msleep(shutdown_delay * 10);
 	skt->state &= SOCKET_INUSE;
 	shutdown_socket(skt);
 }
@@ -467,8 +464,7 @@ static int socket_reset(struct pcmcia_socket *skt)
 	skt->socket.flags &= ~SS_RESET;
 	skt->ops->set_socket(skt, &skt->socket);
 
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(cs_to_timeout(unreset_delay));
+	msleep(unreset_delay * 10);
 	for (i = 0; i < unreset_limit; i++) {
 		skt->ops->get_status(skt, &status);
 
@@ -478,8 +474,7 @@ static int socket_reset(struct pcmcia_socket *skt)
 		if (status & SS_READY)
 			return CS_SUCCESS;
 
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(cs_to_timeout(unreset_check));
+		msleep(unreset_check * 10);
 	}
 
 	cs_err(skt, "time out after reset.\n");
@@ -496,8 +491,7 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
 	if (!(status & SS_DETECT))
 		return CS_NO_CARD;
 
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(cs_to_timeout(initial_delay));
+	msleep(initial_delay * 10);
 
 	for (i = 0; i < 100; i++) {
 		skt->ops->get_status(skt, &status);
@@ -507,8 +501,7 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
 		if (!(status & SS_PENDING))
 			break;
 
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(cs_to_timeout(10));
+		msleep(100);
 	}
 
 	if (status & SS_PENDING) {
@@ -541,8 +534,7 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
 	/*
 	 * Wait "vcc_settle" for the supply to stabilise.
 	 */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(cs_to_timeout(vcc_settle));
+	msleep(vcc_settle * 10);
 
 	skt->ops->get_status(skt, &status);
 	if (!(status & SS_POWERON)) {
@@ -659,10 +651,8 @@ static void socket_detect_change(struct pcmcia_socket *skt)
 	if (!(skt->state & SOCKET_SUSPEND)) {
 		int status;
 
-		if (!(skt->state & SOCKET_PRESENT)) {
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout(cs_to_timeout(2));
-		}
+		if (!(skt->state & SOCKET_PRESENT))
+			msleep(20);
 
 		skt->ops->get_status(skt, &status);
 		if ((skt->state & SOCKET_PRESENT) &&
@@ -1886,11 +1876,6 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle
 				       (*handle)->dev_info, s);
 	if (!win->ctl.res)
 	    return CS_IN_USE;
-	win->ctl.sys_start = win->ctl.res->start;
-	win->ctl.sys_stop = win->ctl.res->end;
-    } else {
-	win->ctl.sys_start = req->Base;
-	win->ctl.sys_stop = req->Base + req->Size - 1;
     }
     (*handle)->state |= CLIENT_WIN_REQ(w);
 
@@ -1912,7 +1897,11 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle
     s->state |= SOCKET_WIN_REQ(w);
 
     /* Return window handle */
-    req->Base = win->ctl.sys_start;
+    if (s->features & SS_CAP_STATIC_MAP) {
+	req->Base = win->ctl.static_start;
+    } else {
+	req->Base = win->ctl.res->start;
+    }
     *wh = win;
     
     return CS_SUCCESS;
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 71592c71d..b4f741a12 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -50,6 +50,7 @@
 #include <linux/poll.h>
 #include <linux/pci.h>
 #include <linux/list.h>
+#include <linux/delay.h>
 #include <linux/workqueue.h>
 
 #include <asm/atomic.h>
@@ -133,7 +134,7 @@ static dev_info_t dev_info = "Driver Services";
 
 static int major_dev = -1;
 
-extern struct proc_dir_entry *proc_pccard;
+static struct proc_dir_entry *proc_pccard;
 
 /*====================================================================*/
 
@@ -1080,8 +1081,7 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev)
 	 * Ugly. But we want to wait for the socket threads to have started up.
 	 * We really should let the drivers themselves drive some of this..
 	 */
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(HZ/4);
+	msleep(250);
 
 	init_waitqueue_head(&s->queue);
 	init_waitqueue_head(&s->request);
diff --git a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c
index fd08c3a5b..875c9cfae 100644
--- a/drivers/pcmcia/hd64465_ss.c
+++ b/drivers/pcmcia/hd64465_ss.c
@@ -636,19 +636,17 @@ static int hs_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem)
     	hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
 	struct pccard_mem_map *smem;
 	int map = mem->map;
-	unsigned long paddr, size;
+	unsigned long paddr;
 
 #if 0
-    	DPRINTK("hs_set_mem_map(sock=%d, map=%d, flags=0x%x, sys_start=0x%08lx, sys_end=0x%08lx, card_start=0x%08x)\n",
-	    sock, map, mem->flags, mem->sys_start, mem->sys_stop, mem->card_start);
+    	DPRINTK("hs_set_mem_map(sock=%d, map=%d, flags=0x%x, card_start=0x%08x)\n",
+	    sock, map, mem->flags, mem->card_start);
 #endif
 
 	if (map >= MAX_WIN)
 	    return -EINVAL;
 	smem = &sp->mem_maps[map];
 	
-	size = mem->sys_stop - mem->sys_start + 1;
-	
 	paddr = sp->mem_base;	    	    /* base of Attribute mapping */
 	if (!(mem->flags & MAP_ATTRIB))
 	    paddr += HD64465_PCC_WINDOW;    /* base of Common mapping */
@@ -660,8 +658,7 @@ static int hs_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem)
 	 * queries our fixed mapping.  I wish this fact had been
 	 * documented - Greg Banks.
 	 */
-    	mem->sys_start = paddr;
-	mem->sys_stop = paddr + size - 1;
+    	mem->static_start = paddr;
 	
 	*smem = *mem;
 	
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
index 3115eb3bc..eb255238a 100644
--- a/drivers/pcmcia/i82092.c
+++ b/drivers/pcmcia/i82092.c
@@ -422,7 +422,7 @@ static int i82092aa_init(struct pcmcia_socket *sock)
 	int i;
 	struct resource res = { .start = 0, .end = 0x0fff };
         pccard_io_map io = { 0, 0, 0, 0, 1 };
-	pccard_mem_map mem = { .res = &res, .sys_stop = 0x0fff, };
+	pccard_mem_map mem = { .res = &res, };
         
         enter("i82092aa_init");
                         
@@ -706,11 +706,15 @@ static int i82092aa_set_io_map(struct pcmcia_socket *socket, struct pccard_io_ma
 
 static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem)
 {
-	unsigned int sock = container_of(socket, struct socket_info, socket)->number;
+	struct socket_info *sock_info = container_of(socket, struct socket_info, socket);
+	unsigned int sock = sock_info->number;
+	struct pci_bus_region region;
 	unsigned short base, i;
 	unsigned char map;
 	
 	enter("i82092aa_set_mem_map");
+
+	pcibios_resource_to_bus(sock_info->dev, &region, mem->res);
 	
 	map = mem->map;
 	if (map > 4) {
@@ -719,10 +723,10 @@ static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_
 	}
 	
 	
-	if ( (mem->card_start > 0x3ffffff) || (mem->sys_start > mem->sys_stop) ||
+	if ( (mem->card_start > 0x3ffffff) || (region.start > region.end) ||
 	     (mem->speed > 1000) ) {
 		leave("i82092aa_set_mem_map: invalid address / speed");
-		printk("invalid mem map for socket %i : %lx to %lx with a start of %x \n",sock,mem->sys_start, mem->sys_stop, mem->card_start);
+		printk("invalid mem map for socket %i : %lx to %lx with a start of %x \n",sock,region.start, region.end, mem->card_start);
 		return -EINVAL;
 	}
 	
@@ -731,11 +735,11 @@ static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_
 	              indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_MEM(map));
 	                 
 	                 
-/* 	printk("set_mem_map: Setting map %i range to %x - %x on socket %i, speed is %i, active = %i \n",map, mem->sys_start,mem->sys_stop,sock,mem->speed,mem->flags & MAP_ACTIVE);  */
+/* 	printk("set_mem_map: Setting map %i range to %x - %x on socket %i, speed is %i, active = %i \n",map, region.start,region.end,sock,mem->speed,mem->flags & MAP_ACTIVE);  */
 
 	/* write the start address */
 	base = I365_MEM(map);
-	i = (mem->sys_start >> 12) & 0x0fff;
+	i = (region.start >> 12) & 0x0fff;
 	if (mem->flags & MAP_16BIT) 
 		i |= I365_MEM_16BIT;
 	if (mem->flags & MAP_0WS)
@@ -744,7 +748,7 @@ static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_
 		               
 	/* write the stop address */
 	
-	i= (mem->sys_stop >> 12) & 0x0fff;
+	i= (region.end >> 12) & 0x0fff;
 	switch (to_cycles(mem->speed)) {
 		case 0:
 			break;
@@ -763,7 +767,7 @@ static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_
 	
 	/* card start */
 	
-	i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
+	i = ((mem->card_start - region.start) >> 12) & 0x3fff;
 	if (mem->flags & MAP_WRPROT)
 		i |= I365_MEM_WRPROT;
 	if (mem->flags & MAP_ATTRIB) {
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index b753c3186..561974efb 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -513,8 +513,7 @@ static u_int __init test_irq(u_short sock, int irq)
     if (request_irq(irq, i365_count_irq, 0, "scan", i365_count_irq) != 0)
 	return 1;
     irq_hits = 0; irq_sock = sock;
-    __set_current_state(TASK_UNINTERRUPTIBLE);
-    schedule_timeout(HZ/100);
+    msleep(10);
     if (irq_hits) {
 	free_irq(irq, i365_count_irq);
 	debug(2, "    spurious hit!\n");
@@ -1159,13 +1158,13 @@ static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem)
     
     debug(1, "SetMemMap(%d, %d, %#2.2x, %d ns, %#5.5lx-%#5.5"
 	  "lx, %#5.5x)\n", sock, mem->map, mem->flags, mem->speed,
-	  mem->sys_start, mem->sys_stop, mem->card_start);
+	  mem->res->start, mem->res->end, mem->card_start);
 
     map = mem->map;
     if ((map > 4) || (mem->card_start > 0x3ffffff) ||
-	(mem->sys_start > mem->sys_stop) || (mem->speed > 1000))
+	(mem->res->start > mem->res->end) || (mem->speed > 1000))
 	return -EINVAL;
-    if ((mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff))
+    if ((mem->res->start > 0xffffff) || (mem->res->end > 0xffffff))
 	return -EINVAL;
 	
     /* Turn off the window before changing anything */
@@ -1173,12 +1172,12 @@ static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem)
 	i365_bclr(sock, I365_ADDRWIN, I365_ENA_MEM(map));
     
     base = I365_MEM(map);
-    i = (mem->sys_start >> 12) & 0x0fff;
+    i = (mem->res->start >> 12) & 0x0fff;
     if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT;
     if (mem->flags & MAP_0WS) i |= I365_MEM_0WS;
     i365_set_pair(sock, base+I365_W_START, i);
     
-    i = (mem->sys_stop >> 12) & 0x0fff;
+    i = (mem->res->end >> 12) & 0x0fff;
     switch (to_cycles(mem->speed)) {
     case 0:	break;
     case 1:	i |= I365_MEM_WS0; break;
@@ -1187,7 +1186,7 @@ static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem)
     }
     i365_set_pair(sock, base+I365_W_STOP, i);
     
-    i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
+    i = ((mem->card_start - mem->res->start) >> 12) & 0x3fff;
     if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT;
     if (mem->flags & MAP_ATTRIB) i |= I365_MEM_REG;
     i365_set_pair(sock, base+I365_W_OFF, i);
@@ -1309,7 +1308,7 @@ static int pcic_init(struct pcmcia_socket *s)
 	int i;
 	struct resource res = { .start = 0, .end = 0x1000 };
 	pccard_io_map io = { 0, 0, 0, 0, 1 };
-	pccard_mem_map mem = { .res = &res, .sys_stop = 0x1000, };
+	pccard_mem_map mem = { .res = &res, };
 
 	for (i = 0; i < 2; i++) {
 		io.map = i;
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index 57b1bca00..4f00c9dda 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -502,10 +502,10 @@ static int pd6729_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
 		return -EINVAL;
 	}
 
-	if ((mem->sys_start > mem->sys_stop) || (mem->speed > 1000)) {
+	if ((mem->res->start > mem->res->end) || (mem->speed > 1000)) {
 		printk("pd6729_set_mem_map: invalid address / speed");
 		/* printk("invalid mem map for socket %i : %lx to %lx with a start of %x\n",
-			 sock, mem->sys_start, mem->sys_stop, mem->card_start); */
+			 sock, mem->res->start, mem->res->end, mem->card_start); */
 		return -EINVAL;
 	}
 
@@ -515,7 +515,7 @@ static int pd6729_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
 
 	/* write the start address */
 	base = I365_MEM(map);
-	i = (mem->sys_start >> 12) & 0x0fff;
+	i = (mem->res->start >> 12) & 0x0fff;
 	if (mem->flags & MAP_16BIT)
 		i |= I365_MEM_16BIT;
 	if (mem->flags & MAP_0WS)
@@ -524,7 +524,7 @@ static int pd6729_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
 
 	/* write the stop address */
 
-	i= (mem->sys_stop >> 12) & 0x0fff;
+	i= (mem->res->end >> 12) & 0x0fff;
 	switch (to_cycles(mem->speed)) {
 	case 0:
 		break;
@@ -543,11 +543,11 @@ static int pd6729_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
 
 	/* Take care of high byte */
 	indirect_write(socket, PD67_EXT_INDEX, PD67_MEM_PAGE(map));
-	indirect_write(socket, PD67_EXT_DATA, mem->sys_start >> 24);
+	indirect_write(socket, PD67_EXT_DATA, mem->res->start >> 24);
 
 	/* card start */
 
-	i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
+	i = ((mem->card_start - mem->res->start) >> 12) & 0x3fff;
 	if (mem->flags & MAP_WRPROT)
 		i |= I365_MEM_WRPROT;
 	if (mem->flags & MAP_ATTRIB) {
@@ -577,7 +577,7 @@ static int pd6729_init(struct pcmcia_socket *sock)
 	int i;
 	struct resource res = { .end = 0x0fff };
 	pccard_io_map io = { 0, 0, 0, 0, 1 };
-	pccard_mem_map mem = { .res = &res, .sys_stop = 0x0fff };
+	pccard_mem_map mem = { .res = &res, };
 
 	pd6729_set_socket(sock, &dead_socket);
 	for (i = 0; i < 2; i++) {
diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c
index 491d11bc8..2bdf9a004 100644
--- a/drivers/pcmcia/pxa2xx_base.c
+++ b/drivers/pcmcia/pxa2xx_base.c
@@ -28,6 +28,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
+#include <asm/arch/pxa-regs.h>
 
 #include <pcmcia/cs_types.h>
 #include <pcmcia/ss.h>
@@ -178,39 +179,6 @@ int pxa2xx_drv_pcmcia_probe(struct device *dev)
 	first = ops->first;
 	nr = ops->nr;
 
-	/* Setup GPIOs for PCMCIA/CF alternate function mode.
-	 *
-	 * It would be nice if set_GPIO_mode included support
-	 * for driving GPIO outputs to default high/low state
-	 * before programming GPIOs as outputs. Setting GPIO
-	 * outputs to default high/low state via GPSR/GPCR
-	 * before defining them as outputs should reduce
-	 * the possibility of glitching outputs during GPIO
-	 * setup. This of course assumes external terminators
-	 * are present to hold GPIOs in a defined state.
-	 *
-	 * In the meantime, setup default state of GPIO
-	 * outputs before we enable them as outputs.
-	 */
-
-	GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) |
-		GPIO_bit(GPIO49_nPWE) |
-		GPIO_bit(GPIO50_nPIOR) |
-		GPIO_bit(GPIO51_nPIOW) |
-		GPIO_bit(GPIO52_nPCE_1) |
-		GPIO_bit(GPIO53_nPCE_2);
-
-	pxa_gpio_mode(GPIO48_nPOE_MD);
-	pxa_gpio_mode(GPIO49_nPWE_MD);
-	pxa_gpio_mode(GPIO50_nPIOR_MD);
-	pxa_gpio_mode(GPIO51_nPIOW_MD);
-	pxa_gpio_mode(GPIO52_nPCE_1_MD);
-	pxa_gpio_mode(GPIO53_nPCE_2_MD);
-	pxa_gpio_mode(GPIO54_pSKTSEL_MD); /* REVISIT: s/b dependent on num sockets */
-	pxa_gpio_mode(GPIO55_nPREG_MD);
-	pxa_gpio_mode(GPIO56_nPWAIT_MD);
-	pxa_gpio_mode(GPIO57_nIOIS16_MD);
-
 	/* Provide our PXA2xx specific timing routines. */
 	ops->set_timing  = pxa2xx_pcmcia_set_timing;
 #ifdef CONFIG_CPU_FREQ
diff --git a/drivers/pcmcia/pxa2xx_lubbock.c b/drivers/pcmcia/pxa2xx_lubbock.c
index e22a57a4a..48726e739 100644
--- a/drivers/pcmcia/pxa2xx_lubbock.c
+++ b/drivers/pcmcia/pxa2xx_lubbock.c
@@ -25,10 +25,40 @@
 #include <asm/hardware.h>
 #include <asm/hardware/sa1111.h>
 #include <asm/mach-types.h>
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/lubbock.h>
 
 #include "sa1111_generic.h"
 
+static int
+lubbock_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+	/*
+	 * Setup default state of GPIO outputs
+	 * before we enable them as outputs.
+	 */
+	GPSR(GPIO48_nPOE) =
+		GPIO_bit(GPIO48_nPOE) |
+		GPIO_bit(GPIO49_nPWE) |
+		GPIO_bit(GPIO50_nPIOR) |
+		GPIO_bit(GPIO51_nPIOW) |
+		GPIO_bit(GPIO52_nPCE_1) |
+		GPIO_bit(GPIO53_nPCE_2);
+
+	pxa_gpio_mode(GPIO48_nPOE_MD);
+	pxa_gpio_mode(GPIO49_nPWE_MD);
+	pxa_gpio_mode(GPIO50_nPIOR_MD);
+	pxa_gpio_mode(GPIO51_nPIOW_MD);
+	pxa_gpio_mode(GPIO52_nPCE_1_MD);
+	pxa_gpio_mode(GPIO53_nPCE_2_MD);
+	pxa_gpio_mode(GPIO54_pSKTSEL_MD);
+	pxa_gpio_mode(GPIO55_nPREG_MD);
+	pxa_gpio_mode(GPIO56_nPWAIT_MD);
+	pxa_gpio_mode(GPIO57_nIOIS16_MD);
+
+	return sa1111_pcmcia_hw_init(skt);
+}
+
 static int
 lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
 				const socket_state_t *state)
@@ -201,7 +231,7 @@ lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
 
 static struct pcmcia_low_level lubbock_pcmcia_ops = {
 	.owner			= THIS_MODULE,
-	.hw_init		= sa1111_pcmcia_hw_init,
+	.hw_init		= lubbock_pcmcia_hw_init,
 	.hw_shutdown		= sa1111_pcmcia_hw_shutdown,
 	.socket_state		= sa1111_pcmcia_socket_state,
 	.configure_socket	= lubbock_pcmcia_configure_socket,
diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c
index fe62a597d..5309734e1 100644
--- a/drivers/pcmcia/pxa2xx_mainstone.c
+++ b/drivers/pcmcia/pxa2xx_mainstone.c
@@ -24,6 +24,7 @@
 #include <asm/hardware.h>
 #include <asm/irq.h>
 
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/mainstone.h>
 
 #include "soc_common.h"
@@ -38,6 +39,29 @@ static struct pcmcia_irqs irqs[] = {
 
 static int mst_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
+	/*
+	 * Setup default state of GPIO outputs
+	 * before we enable them as outputs.
+	 */
+	GPSR(GPIO48_nPOE) =
+		GPIO_bit(GPIO48_nPOE) |
+		GPIO_bit(GPIO49_nPWE) |
+		GPIO_bit(GPIO50_nPIOR) |
+		GPIO_bit(GPIO51_nPIOW) |
+		GPIO_bit(GPIO85_nPCE_1) |
+		GPIO_bit(GPIO54_nPCE_2);
+
+	pxa_gpio_mode(GPIO48_nPOE_MD);
+	pxa_gpio_mode(GPIO49_nPWE_MD);
+	pxa_gpio_mode(GPIO50_nPIOR_MD);
+	pxa_gpio_mode(GPIO51_nPIOW_MD);
+	pxa_gpio_mode(GPIO85_nPCE_1_MD);
+	pxa_gpio_mode(GPIO54_nPCE_2_MD);
+	pxa_gpio_mode(GPIO79_pSKTSEL_MD);
+	pxa_gpio_mode(GPIO55_nPREG_MD);
+	pxa_gpio_mode(GPIO56_nPWAIT_MD);
+	pxa_gpio_mode(GPIO57_nIOIS16_MD);
+
 	skt->irq = (skt->nr == 0) ? MAINSTONE_S0_IRQ : MAINSTONE_S1_IRQ;
 	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index 6869e209d..620b20f7e 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -88,6 +88,9 @@ static resource_map_t io_db = {
 };
 
 static DECLARE_MUTEX(rsrc_sem);
+static unsigned int rsrc_mem_probe;
+#define MEM_PROBE_LOW	(1 << 0)
+#define MEM_PROBE_HIGH	(1 << 1)
 
 #ifdef CONFIG_PCMCIA_PROBE
 
@@ -301,8 +304,6 @@ static int readable(struct pcmcia_socket *s, struct resource *res, cisinfo_t *in
 {
 	int ret = -1;
 
-	s->cis_mem.sys_start = res->start;
-	s->cis_mem.sys_stop = res->end;
 	s->cis_mem.res = res;
 	s->cis_virt = ioremap(res->start, s->map_size);
 	if (s->cis_virt) {
@@ -312,8 +313,6 @@ static int readable(struct pcmcia_socket *s, struct resource *res, cisinfo_t *in
 		s->cis_virt = NULL;
 		destroy_cis_cache(s);
 	}
-	s->cis_mem.sys_start = 0;
-	s->cis_mem.sys_stop = 0;
 	s->cis_mem.res = NULL;
 	if ((ret != 0) || (info->Chains == 0))
 		return 0;
@@ -325,15 +324,13 @@ static int checksum(struct pcmcia_socket *s, struct resource *res)
 {
 	pccard_mem_map map;
 	int i, a = 0, b = -1, d;
-	void *virt;
+	void __iomem *virt;
 
 	virt = ioremap(res->start, s->map_size);
 	if (virt) {
 		map.map = 0;
 		map.flags = MAP_ACTIVE;
 		map.speed = 0;
-		map.sys_start = res->start;
-		map.sys_stop = res->end;
 		map.res = res;
 		map.card_start = 0;
 		s->ops->set_mem_map(s, &map);
@@ -457,24 +454,21 @@ static u_long inv_probe(resource_map_t *m, struct pcmcia_socket *s)
     return do_mem_probe(m->base, m->num, s);
 }
 
-static void validate_mem(struct pcmcia_socket *s)
+static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
 {
     resource_map_t *m, mm;
     static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
-    static int hi = 0, lo = 0;
     u_long b, i, ok = 0;
-    int force_low = !(s->features & SS_CAP_PAGE_REGS);
 
-    down(&rsrc_sem);
     /* We do up to four passes through the list */
-    if (!force_low) {
-	if (hi++ || (inv_probe(mem_db.next, s) > 0))
-	    goto out;
+    if (probe_mask & MEM_PROBE_HIGH) {
+	if (inv_probe(mem_db.next, s) > 0)
+	    return;
 	printk(KERN_NOTICE "cs: warning: no high memory space "
 	       "available!\n");
     }
-    if (lo++)
-	goto out;
+    if ((probe_mask & MEM_PROBE_LOW) == 0)
+	return;
     for (m = mem_db.next; m != &mem_db; m = mm.next) {
 	mm = *m;
 	/* Only probe < 1 MB */
@@ -494,38 +488,51 @@ static void validate_mem(struct pcmcia_socket *s)
 	    }
 	}
     }
- out:
-    up(&rsrc_sem);
 }
 
 #else /* CONFIG_PCMCIA_PROBE */
 
-static void validate_mem(struct pcmcia_socket *s)
+static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
 {
-    resource_map_t *m, mm;
-    static int done = 0;
+	resource_map_t *m, mm;
     
-    if (done++ == 0) {
-	down(&rsrc_sem);
 	for (m = mem_db.next; m != &mem_db; m = mm.next) {
-	    mm = *m;
-	    if (do_mem_probe(mm.base, mm.num, s))
-		break;
+		mm = *m;
+		if (do_mem_probe(mm.base, mm.num, s))
+			break;
 	}
-	up(&rsrc_sem);
-    }
 }
 
 #endif /* CONFIG_PCMCIA_PROBE */
 
+/*
+ * Locking note: this is the only place where we take
+ * both rsrc_sem and skt_sem.
+ */
 void pcmcia_validate_mem(struct pcmcia_socket *s)
 {
-	down(&s->skt_sem);
+	if (probe_mem) {
+		unsigned int probe_mask;
+
+		down(&rsrc_sem);
+
+		probe_mask = MEM_PROBE_LOW;
+		if (s->features & SS_CAP_PAGE_REGS)
+			probe_mask = MEM_PROBE_HIGH;
+
+		if (probe_mask & ~rsrc_mem_probe) {
+			rsrc_mem_probe |= probe_mask;
 
-	if (probe_mem && s->state & SOCKET_PRESENT)
-		validate_mem(s);
+			down(&s->skt_sem);
 
-	up(&s->skt_sem);
+			if (s->state & SOCKET_PRESENT)
+				validate_mem(s, probe_mask);
+
+			up(&s->skt_sem);
+		}
+
+		up(&rsrc_sem);
+	}
 }
 
 EXPORT_SYMBOL(pcmcia_validate_mem);
diff --git a/drivers/pcmcia/sa1100_h3600.c b/drivers/pcmcia/sa1100_h3600.c
index e442953b3..64fd5e37f 100644
--- a/drivers/pcmcia/sa1100_h3600.c
+++ b/drivers/pcmcia/sa1100_h3600.c
@@ -10,6 +10,7 @@
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
@@ -96,8 +97,7 @@ static void h3600_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
 	set_h3600_egpio(IPAQ_EGPIO_OPT_ON);
 	clr_h3600_egpio(IPAQ_EGPIO_OPT_RESET);
 
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(10*HZ / 1000);
+	msleep(10);
 
 	soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
 }
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index 6d393e739..a45fee3f4 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -49,6 +49,11 @@
 
 #include "soc_common.h"
 
+/* FIXME: platform dependent resource declaration has to move out of this file */
+#ifdef CONFIG_ARCH_PXA
+#include <asm/arch/pxa-regs.h>
+#endif
+
 #ifdef DEBUG
 
 static int pc_debug;
@@ -448,9 +453,7 @@ soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
 
 	skt->ops->set_timing(skt);
 
-	map->sys_stop -= map->sys_start;
-	map->sys_stop += res->start + map->card_start;
-	map->sys_start = res->start + map->card_start;
+	map->static_start = res->start + map->card_start;
 
 	return 0;
 }
@@ -662,6 +665,7 @@ static void soc_pcmcia_cpufreq_unregister(void)
 int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr)
 {
 	struct skt_dev_info *sinfo;
+	struct soc_pcmcia_socket *skt;
 	int ret, i;
 
 	down(&soc_pcmcia_sockets_lock);
@@ -679,7 +683,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
 	 * Initialise the per-socket structure.
 	 */
 	for (i = 0; i < nr; i++) {
-		struct soc_pcmcia_socket *skt = &sinfo->skt[i];
+		skt = &sinfo->skt[i];
 
 		skt->socket.ops = &soc_common_pcmcia_operations;
 		skt->socket.owner = ops->owner;
@@ -777,7 +781,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
 	goto out;
 
 	do {
-		struct soc_pcmcia_socket *skt = &sinfo->skt[i];
+		skt = &sinfo->skt[i];
 
 		del_timer_sync(&skt->poll_timer);
 		pcmcia_unregister_socket(&skt->socket);
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index f3b38e96d..d986d13f2 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -829,15 +829,15 @@ static int tcic_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *m
 
     debug(1, "SetMemMap(%d, %d, %#2.2x, %d ns, "
 	  "%#5.5lx-%#5.5lx, %#5.5x)\n", psock, mem->map, mem->flags,
-	  mem->speed, mem->sys_start, mem->sys_stop, mem->card_start);
+	  mem->speed, mem->res->start, mem->res->end, mem->card_start);
     if ((mem->map > 3) || (mem->card_start > 0x3ffffff) ||
-	(mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff) ||
-	(mem->sys_start > mem->sys_stop) || (mem->speed > 1000))
+	(mem->res->start > 0xffffff) || (mem->res->end > 0xffffff) ||
+	(mem->res->start > mem->res->end) || (mem->speed > 1000))
 	return -EINVAL;
     tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));
     addr = TCIC_MWIN(psock, mem->map);
 
-    base = mem->sys_start; len = mem->sys_stop - mem->sys_start;
+    base = mem->res->start; len = mem->res->end - mem->res->start;
     if ((len & (len+1)) || (base & len)) return -EINVAL;
     if (len == 0x0fff)
 	base = (base >> TCIC_MBASE_HA_SHFT) | TCIC_MBASE_4K_BIT;
@@ -846,7 +846,7 @@ static int tcic_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *m
     tcic_setw(TCIC_ADDR, addr + TCIC_MBASE_X);
     tcic_setw(TCIC_DATA, base);
     
-    mmap = mem->card_start - mem->sys_start;
+    mmap = mem->card_start - mem->res->start;
     mmap = (mmap >> TCIC_MMAP_CA_SHFT) & TCIC_MMAP_CA_MASK;
     if (mem->flags & MAP_ATTRIB) mmap |= TCIC_MMAP_REG;
     tcic_setw(TCIC_ADDR, addr + TCIC_MMAP_X);
@@ -870,7 +870,7 @@ static int tcic_init(struct pcmcia_socket *s)
 	int i;
 	struct resource res = { .start = 0, .end = 0x1000 };
 	pccard_io_map io = { 0, 0, 0, 0, 1 };
-	pccard_mem_map mem = { .res = &res, .sys_stop = 0x1000, };
+	pccard_mem_map mem = { .res = &res, };
 
 	for (i = 0; i < 2; i++) {
 		io.map = i;
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 4c8a7a572..d6974a147 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -343,14 +343,17 @@ static int yenta_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io
 static int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
 {
 	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+	struct pci_bus_region region;
 	int map;
 	unsigned char addr, enable;
 	unsigned int start, stop, card_start;
 	unsigned short word;
 
+	pcibios_resource_to_bus(socket->dev, &region, mem->res);
+
 	map = mem->map;
-	start = mem->sys_start;
-	stop = mem->sys_stop;
+	start = region.start;
+	stop = region.end;
 	card_start = mem->card_start;
 
 	if (map > 4 || start > stop || ((start ^ stop) >> 24) ||
@@ -447,7 +450,7 @@ static void yenta_clear_maps(struct yenta_socket *socket)
 	int i;
 	struct resource res = { .start = 0, .end = 0x0fff };
 	pccard_io_map io = { 0, 0, 0, 0, 1 };
-	pccard_mem_map mem = { .res = &res, .sys_stop = 0x0fff, };
+	pccard_mem_map mem = { .res = &res, };
 
 	yenta_set_socket(&socket->socket, &dead_socket);
 	for (i = 0; i < 2; i++) {
@@ -1088,6 +1091,7 @@ static struct pci_device_id yenta_table [] = {
 	CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4410, TI12XX),
 	CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4450, TI12XX),
 	CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4451, TI12XX),
+	CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_4520, TI12XX),
 
 	CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1250, TI1250),
 	CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1410, TI1250),
diff --git a/drivers/pcmcia/yenta_socket.h b/drivers/pcmcia/yenta_socket.h
index 7c3bfbfaa..7f04a6b73 100644
--- a/drivers/pcmcia/yenta_socket.h
+++ b/drivers/pcmcia/yenta_socket.h
@@ -107,7 +107,7 @@ struct cardbus_type {
 struct yenta_socket {
 	struct pci_dev *dev;
 	int cb_irq, io_irq;
-	void *base;
+	void __iomem *base;
 	struct timer_list poll_timer;
 
 	struct pcmcia_socket socket;
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c
index 781a4c064..f7548c410 100644
--- a/drivers/pnp/interface.c
+++ b/drivers/pnp/interface.c
@@ -240,12 +240,14 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
 	int i, ret;
-	pnp_info_buffer_t *buffer = (pnp_info_buffer_t *)
-				pnp_alloc(sizeof(pnp_info_buffer_t));
-	if (!buffer)
-		return -ENOMEM;
+	pnp_info_buffer_t *buffer;
+
 	if (!dev)
 		return -EINVAL;
+
+	buffer = (pnp_info_buffer_t *) pnp_alloc(sizeof(pnp_info_buffer_t));
+	if (!buffer)
+		return -ENOMEM;
 	buffer->len = PAGE_SIZE;
 	buffer->buffer = buf;
 	buffer->curr = buffer->buffer;
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index ee6d1ed50..bf52990a8 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -655,8 +655,10 @@ static int __init isapnp_create_device(struct pnp_card *card,
 	if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
 		return 1;
 	option = pnp_register_independent_option(dev);
-	if (!option)
+	if (!option) {
+		kfree(dev);
 		return 1;
+	}
 	pnp_add_card_device(card,dev);
 
 	while (1) {
diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c
index c224f74fa..ca7996d4b 100644
--- a/drivers/pnp/pnpbios/bioscalls.c
+++ b/drivers/pnp/pnpbios/bioscalls.c
@@ -69,14 +69,14 @@ __asm__(
 
 #define Q_SET_SEL(cpu, selname, address, size) \
 do { \
-set_base(cpu_gdt_table[cpu][(selname) >> 3], __va((u32)(address))); \
-set_limit(cpu_gdt_table[cpu][(selname) >> 3], size); \
+set_base(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], __va((u32)(address))); \
+set_limit(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], size); \
 } while(0)
 
 #define Q2_SET_SEL(cpu, selname, address, size) \
 do { \
-set_base(cpu_gdt_table[cpu][(selname) >> 3], (u32)(address)); \
-set_limit(cpu_gdt_table[cpu][(selname) >> 3], size); \
+set_base(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], (u32)(address)); \
+set_limit(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], size); \
 } while(0)
 
 static struct desc_struct bad_bios_desc = { 0, 0x00409200 };
@@ -115,8 +115,8 @@ static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3,
 		return PNP_FUNCTION_NOT_SUPPORTED;
 
 	cpu = get_cpu();
-	save_desc_40 = cpu_gdt_table[cpu][0x40 / 8];
-	cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc;
+	save_desc_40 = per_cpu(cpu_gdt_table,cpu)[0x40 / 8];
+	per_cpu(cpu_gdt_table,cpu)[0x40 / 8] = bad_bios_desc;
 
 	/* On some boxes IRQ's during PnP BIOS calls are deadly.  */
 	spin_lock_irqsave(&pnp_bios_lock, flags);
@@ -158,7 +158,7 @@ static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3,
 	);
 	spin_unlock_irqrestore(&pnp_bios_lock, flags);
 
-	cpu_gdt_table[cpu][0x40 / 8] = save_desc_40;
+	per_cpu(cpu_gdt_table,cpu)[0x40 / 8] = save_desc_40;
 	put_cpu();
 
 	/* If we get here and this is set then the PnP BIOS faulted on us. */
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index 6c9866346..1a2fe19dd 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -252,8 +252,10 @@ static int pnpbios_set_resources(struct pnp_dev * dev, struct pnp_resource_table
 	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node)
 		return -1;
-	if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node))
+	if (pnp_bios_get_dev_node(&nodenum, (char )PNPMODE_DYNAMIC, node)) {
+		kfree(node);
 		return -ENODEV;
+	}
 	if(pnpbios_write_resources_to_node(res, node)<0) {
 		kfree(node);
 		return -1;
diff --git a/drivers/pnp/pnpbios/proc.c b/drivers/pnp/pnpbios/proc.c
index 88fcd1668..2fa4d21c7 100644
--- a/drivers/pnp/pnpbios/proc.c
+++ b/drivers/pnp/pnpbios/proc.c
@@ -90,8 +90,10 @@ static int proc_read_escd(char *buf, char **start, off_t pos,
 	tmpbuf = pnpbios_kmalloc(escd.escd_size, GFP_KERNEL);
 	if (!tmpbuf) return -ENOMEM;
 
-	if (pnp_bios_read_escd(tmpbuf, escd.nv_storage_base))
+	if (pnp_bios_read_escd(tmpbuf, escd.nv_storage_base)) {
+		kfree(tmpbuf);
 		return -EIO;
+	}
 
 	escd_size = (unsigned char)(tmpbuf[0]) + (unsigned char)(tmpbuf[1])*256;
 
@@ -168,8 +170,10 @@ static int proc_read_node(char *buf, char **start, off_t pos,
 
 	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node) return -ENOMEM;
-	if (pnp_bios_get_dev_node(&nodenum, boot, node))
+	if (pnp_bios_get_dev_node(&nodenum, boot, node)) {
+		kfree(node);
 		return -EIO;
+	}
 	len = node->size - sizeof(struct pnp_bios_node);
 	memcpy(buf, node->data, len);
 	kfree(node);
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c
index f990065e1..7aafbf80d 100644
--- a/drivers/pnp/pnpbios/rsparser.c
+++ b/drivers/pnp/pnpbios/rsparser.c
@@ -346,12 +346,12 @@ pnpbios_parse_resource_option_data(unsigned char * p, unsigned char * end, struc
 {
 	unsigned int len, tag;
 	int priority = 0;
-	struct pnp_option *option;
+	struct pnp_option *option, *option_independent;
 
 	if (!p)
 		return NULL;
 
-	option = pnp_register_independent_option(dev);
+	option_independent = option = pnp_register_independent_option(dev);
 	if (!option)
 		return NULL;
 
@@ -428,9 +428,14 @@ pnpbios_parse_resource_option_data(unsigned char * p, unsigned char * end, struc
 		case SMALL_TAG_ENDDEP:
 			if (len != 0)
 				goto len_err;
+			if (option_independent == option)
+				printk(KERN_WARNING "PnPBIOS: Missing SMALL_TAG_STARTDEP tag\n");
+			option = option_independent;
 			break;
 
 		case SMALL_TAG_END:
+			if (option_independent != option)
+				printk(KERN_WARNING "PnPBIOS: Missing SMALL_TAG_ENDDEP tag\n");
 			p = p + 2;
         		return (unsigned char *)p;
 			break;
diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c
index da52c86dc..d42015c38 100644
--- a/drivers/pnp/system.c
+++ b/drivers/pnp/system.c
@@ -104,4 +104,8 @@ static int __init pnp_system_init(void)
 	return pnp_register_driver(&system_pnp_driver);
 }
 
-subsys_initcall(pnp_system_init);
+/**
+ * Reserve motherboard resources after PCI claim BARs,
+ * but before PCI assign resources for uninitialized PCI devices
+ */
+fs_initcall(pnp_system_init);
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index cc79775b0..deaecd080 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -6,7 +6,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.37 $
+ * $Revision: 1.38 $
  */
 
 #include <linux/config.h>
@@ -304,8 +304,11 @@ dasd_diag_check_device(struct dasd_device *device)
 			    (device->bp_block >> 10),
 			    (device->blocks << device->s2b_shift) >> 1);
 		rc = 0;
-	} else
+	} else {
+		DEV_MESSAGE(KERN_WARNING, device, "%s",
+			    "volume has incompatible disk layout");
 		rc = -EMEDIUMTYPE;
+	}
 	free_page((long) label);
 	return rc;
 }
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 27bf674af..56f471c23 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -7,7 +7,7 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.57 $
+ * $Revision: 1.61 $
  */
 
 #include <linux/config.h>
@@ -68,6 +68,10 @@ static struct ccw_device_id dasd_eckd_ids[] = {
 	{ CCW_DEVICE_DEVTYPE (0x3990, 0, 0x3380, 0), driver_info: 0x4},
 	{ CCW_DEVICE_DEVTYPE (0x2105, 0, 0x3380, 0), driver_info: 0x5},
 	{ CCW_DEVICE_DEVTYPE (0x9343, 0, 0x9345, 0), driver_info: 0x6},
+	{ CCW_DEVICE_DEVTYPE (0x2107, 0, 0x3390, 0), driver_info: 0x7},
+	{ CCW_DEVICE_DEVTYPE (0x2107, 0, 0x3380, 0), driver_info: 0x8},
+	{ CCW_DEVICE_DEVTYPE (0x1750, 0, 0x3390, 0), driver_info: 0x9},
+	{ CCW_DEVICE_DEVTYPE (0x1750, 0, 0x3380, 0), driver_info: 0xa},
 	{ /* end of list */ },
 };
 
@@ -274,9 +278,11 @@ define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk,
 
 	data->attributes.mode = 0x3;	/* ECKD */
 
-	if (private->rdc_data.cu_type == 0x2105
+	if ((private->rdc_data.cu_type == 0x2105 ||
+	     private->rdc_data.cu_type == 0x2107 ||
+	     private->rdc_data.cu_type == 0x1750)
 	    && !(private->uses_cdl && trk < 2))
-		data->ga_extended |= 0x40;
+		data->ga_extended |= 0x40; /* Regular Data Format Mode */
 
 	geo.cyl = private->rdc_data.no_cyl;
 	geo.head = private->rdc_data.trk_per_cyl;
@@ -499,11 +505,13 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
 			"sizes of configuration data mismatch"
 			"%d (read) vs %ld (expected)",
 			conf_len, sizeof (struct dasd_eckd_confdata));
+
+		kfree(conf_data); /* allocated by read_conf_data() */
 		return 0;	/* no errror */
 	}
 	memcpy(&private->conf_data, conf_data,
 	       sizeof (struct dasd_eckd_confdata));
-
+	kfree(conf_data); /* allocated by read_conf_data() */
 	return 0;
 }
 
@@ -903,6 +911,8 @@ dasd_eckd_examine_error(struct dasd_ccw_req * cqr, struct irb * irb)
 	switch (cdev->id.cu_type) {
 	case 0x3990:
 	case 0x2105:
+	case 0x2107:
+	case 0x1750:
 		return dasd_3990_erp_examine(cqr, irb);
 	case 0x9343:
 		return dasd_9343_erp_examine(cqr, irb);
@@ -923,6 +933,8 @@ dasd_eckd_erp_action(struct dasd_ccw_req * cqr)
 	switch (cdev->id.cu_type) {
 	case 0x3990:
 	case 0x2105:
+	case 0x2107:
+	case 0x1750:
 		return dasd_3990_erp_action;
 	case 0x9343:
 		/* Return dasd_9343_erp_action; */
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index ca83f9b0a..b7a764ca3 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -5,6 +5,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/ctype.h>
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -19,6 +20,7 @@
 //#define DCSSBLK_DEBUG		/* Debug messages on/off */
 #define DCSSBLK_NAME "dcssblk"
 #define DCSSBLK_MINORS_PER_DISK 1
+#define DCSSBLK_PARM_LEN 400
 
 #ifdef DCSSBLK_DEBUG
 #define PRINT_DEBUG(x...) printk(KERN_DEBUG DCSSBLK_NAME " debug: " x)
@@ -34,6 +36,8 @@ static int dcssblk_open(struct inode *inode, struct file *filp);
 static int dcssblk_release(struct inode *inode, struct file *filp);
 static int dcssblk_make_request(struct request_queue *q, struct bio *bio);
 
+static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0";
+
 static int dcssblk_major;
 static struct block_device_operations dcssblk_devops = {
 	.owner   = THIS_MODULE,
@@ -641,6 +645,47 @@ fail:
 	return 0;
 }
 
+static void
+dcssblk_check_params(void)
+{
+	int rc, i, j, k;
+	char buf[9];
+	struct dcssblk_dev_info *dev_info;
+
+	for (i = 0; (i < DCSSBLK_PARM_LEN) && (dcssblk_segments[i] != '\0');
+	     i++) {
+		for (j = i; (dcssblk_segments[j] != ',')  &&
+			    (dcssblk_segments[j] != '\0') &&
+			    (dcssblk_segments[j] != '(')  &&
+			    (j - i) < 8; j++)
+		{
+			buf[j-i] = dcssblk_segments[j];
+		}
+		buf[j-i] = '\0';
+		rc = dcssblk_add_store(dcssblk_root_dev, buf, j-i);
+		if ((rc >= 0) && (dcssblk_segments[j] == '(')) {
+			for (k = 0; buf[k] != '\0'; k++)
+				buf[k] = toupper(buf[k]);
+			if (!strncmp(&dcssblk_segments[j], "(local)", 7)) {
+				down_read(&dcssblk_devices_sem);
+				dev_info = dcssblk_get_device_by_name(buf);
+				up_read(&dcssblk_devices_sem);
+				if (dev_info)
+					dcssblk_shared_store(&dev_info->dev,
+							     "0\n", 2);
+			}
+		}
+		while ((dcssblk_segments[j] != ',') &&
+		       (dcssblk_segments[j] != '\0'))
+		{
+			j++;
+		}
+		if (dcssblk_segments[j] == '\0')
+			break;
+		i = j;
+	}
+}
+
 /*
  * The init/exit functions.
  */
@@ -689,6 +734,9 @@ dcssblk_init(void)
 	}
 	dcssblk_major = rc;
 	init_rwsem(&dcssblk_devices_sem);
+
+	dcssblk_check_params();
+
 	PRINT_DEBUG("...finished!\n");
 	return 0;
 }
@@ -696,4 +744,12 @@ dcssblk_init(void)
 module_init(dcssblk_init);
 module_exit(dcssblk_exit);
 
+module_param_string(segments, dcssblk_segments, DCSSBLK_PARM_LEN, 0444);
+MODULE_PARM_DESC(segments, "Name of DCSS segment(s) to be loaded, "
+		 "comma-separated list, each name max. 8 chars.\n"
+		 "Adding \"(local)\" to segment name equals echoing 0 to "
+		 "/sys/devices/dcssblk/<segment name>/shared after loading "
+		 "the segment - \n"
+		 "e.g. segments=\"mydcss1,mydcss2,mydcss3(local)\"");
+
 MODULE_LICENSE("GPL");
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index e92bb9473..9c72ffb65 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -366,10 +366,7 @@ raw3215_tasklet(void *data)
 	tty = raw->tty;
 	if (tty != NULL &&
 	    RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
+	    	tty_wakeup(tty);
 	}
 }
 
@@ -1055,10 +1052,7 @@ tty3215_flush_buffer(struct tty_struct *tty)
 
 	raw = (struct raw3215_info *) tty->driver_data;
 	raw3215_flush_buffer(raw);
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /*
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index 047d305cc..ca0f875bf 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -20,6 +20,7 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/cpumask.h>
+#include <linux/reboot.h>
 #include <asm/s390_ext.h>
 #include <asm/processor.h>
 
@@ -60,6 +61,7 @@ static volatile unsigned long sclp_status = 0;
 #define SCLP_INIT		0
 #define SCLP_RUNNING		1
 #define SCLP_READING		2
+#define SCLP_SHUTDOWN		3
 
 #define SCLP_INIT_POLL_INTERVAL	1
 #define SCLP_BUSY_POLL_INTERVAL	1
@@ -606,10 +608,12 @@ sclp_init_mask(void)
 	sccb->mask_length = sizeof(sccb_mask_t);
 	/* copy in the sccb mask of the registered event types */
 	spin_lock_irqsave(&sclp_lock, flags);
-	list_for_each(l, &sclp_reg_list) {
-		t = list_entry(l, struct sclp_register, list);
-		sccb->receive_mask |= t->receive_mask;
-		sccb->send_mask |= t->send_mask;
+	if (!test_bit(SCLP_SHUTDOWN, &sclp_status)) {
+		list_for_each(l, &sclp_reg_list) {
+			t = list_entry(l, struct sclp_register, list);
+			sccb->receive_mask |= t->receive_mask;
+			sccb->send_mask |= t->send_mask;
+		}
 	}
 	sccb->sclp_receive_mask = 0;
 	sccb->sclp_send_mask = 0;
@@ -647,9 +651,10 @@ sclp_init_mask(void)
 		/* WRITEMASK failed - we cannot rely on receiving a state
 		   change event, so initially, polling is the only alternative
 		   for us to ever become operational. */
-		if (!timer_pending(&retry_timer) ||
-		    !mod_timer(&retry_timer,
-			       jiffies + SCLP_INIT_POLL_INTERVAL*HZ)) {
+		if (!test_bit(SCLP_SHUTDOWN, &sclp_status) &&
+		    (!timer_pending(&retry_timer) ||
+		     !mod_timer(&retry_timer,
+			       jiffies + SCLP_INIT_POLL_INTERVAL*HZ))) {
 			retry_timer.function = sclp_init_mask_retry;
 			retry_timer.data = 0;
 			retry_timer.expires = jiffies +
@@ -671,6 +676,26 @@ sclp_init_mask_retry(unsigned long data)
 	sclp_init_mask();
 }
 
+/* Reboot event handler - reset send and receive mask to prevent pending SCLP
+ * events from interfering with rebooted system. */
+static int
+sclp_reboot_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+	unsigned long flags;
+
+	/* Note: need spinlock to maintain atomicity when accessing global
+         * variables. */
+	spin_lock_irqsave(&sclp_lock, flags);
+	set_bit(SCLP_SHUTDOWN, &sclp_status);
+	spin_unlock_irqrestore(&sclp_lock, flags);
+	sclp_init_mask();
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block sclp_reboot_notifier = {
+	.notifier_call = sclp_reboot_event
+};
+
 /*
  * sclp setup function. Called early (no kmalloc!) from sclp_console_init().
  */
@@ -691,6 +716,10 @@ sclp_init(void)
 	list_add(&sclp_state_change_event.list, &sclp_reg_list);
 	list_add(&sclp_quiesce_event.list, &sclp_reg_list);
 
+	rc = register_reboot_notifier(&sclp_reboot_notifier);
+	if (rc)
+		return rc;
+
 	/*
 	 * request the 0x2401 external interrupt
 	 * The sclp driver is initialized early (before kmalloc works). We
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index a1ad37580..cd11cb171 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -277,10 +277,7 @@ sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc)
 	wake_up(&sclp_tty_waitq);
 	/* check if the tty needs a wake up call */
 	if (sclp_tty != NULL) {
-		if ((sclp_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    sclp_tty->ldisc.write_wakeup)
-			(sclp_tty->ldisc.write_wakeup)(sclp_tty);
-		wake_up_interruptible(&sclp_tty->write_wait);
+		tty_wakeup(sclp_tty);
 	}
 }
 
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index 22760a120..cc143fa9f 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -139,10 +139,7 @@ sclp_vt220_process_queue(struct sclp_vt220_request *request)
 	wake_up(&sclp_vt220_waitq);
 	/* Check if the tty needs a wake up call */
 	if (sclp_vt220_tty != NULL) {
-		if ((sclp_vt220_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    (sclp_vt220_tty->ldisc.write_wakeup != NULL))
-			(sclp_vt220_tty->ldisc.write_wakeup)(sclp_vt220_tty);
-		wake_up_interruptible(&sclp_vt220_tty->write_wait);
+		tty_wakeup(sclp_vt220_tty);
 	}
 }
 
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index 29000d5e7..4a06c7d0e 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/blacklist.c
  *   S/390 common I/O routines -- blacklisting of specific devices
- *   $Revision: 1.31 $
+ *   $Revision: 1.33 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
@@ -229,7 +229,7 @@ s390_redo_validation (void)
 	unsigned int irq;
 
 	CIO_TRACE_EVENT (0, "redoval");
-	for (irq = 0; irq <= __MAX_SUBCHANNELS; irq++) {
+	for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
 		int ret;
 		struct subchannel *sch;
 
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index 9b86522fb..21a75ee28 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/ccwgroup.c
  *  bus driver for ccwgroup
- *   $Revision: 1.28 $
+ *   $Revision: 1.29 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *                       IBM Corporation
@@ -191,14 +191,12 @@ ccwgroup_create(struct device *root,
 		gdev->cdev[i]->dev.driver_data = gdev;
 	del_drvdata = 1;
 
-	*gdev = (struct ccwgroup_device) {
-		.creator_id = creator_id,
-		.count = argc,
-		.dev = {
-			.bus = &ccwgroup_bus_type,
-			.parent = root,
-			.release = ccwgroup_release,
-		},
+	gdev->creator_id = creator_id;
+	gdev->count = argc;
+	gdev->dev = (struct device ) {
+		.bus = &ccwgroup_bus_type,
+		.parent = root,
+		.release = ccwgroup_release,
 	};
 
 	snprintf (gdev->dev.bus_id, BUS_ID_SIZE, "%s",
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 38e59dd24..fa6f0b105 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/cio.c
  *   S/390 common I/O routines -- low level i/o calls
- *   $Revision: 1.123 $
+ *   $Revision: 1.128 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
@@ -17,8 +17,8 @@
 #include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/kernel_stat.h>
+#include <linux/interrupt.h>
 
-#include <asm/hardirq.h>
 #include <asm/cio.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
@@ -141,6 +141,7 @@ cio_tpi(void)
 	sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
 	if (!sch)
 		return 1;
+	local_bh_disable();
 	irq_enter ();
 	spin_lock(&sch->lock);
 	memcpy (&sch->schib.scsw, &irb->scsw, sizeof (struct scsw));
@@ -148,6 +149,7 @@ cio_tpi(void)
 		sch->driver->irq(&sch->dev);
 	spin_unlock(&sch->lock);
 	irq_exit ();
+	__local_bh_enable();
 	return 1;
 }
 
@@ -409,10 +411,10 @@ cio_enable_subchannel (struct subchannel *sch, unsigned int isc)
 	if (ccode)
 		return -ENODEV;
 
-	sch->schib.pmcw.ena = 1;
-	sch->schib.pmcw.isc = isc;
-	sch->schib.pmcw.intparm = (__u32)(unsigned long)sch;
 	for (retry = 5, ret = 0; retry > 0; retry--) {
+		sch->schib.pmcw.ena = 1;
+		sch->schib.pmcw.isc = isc;
+		sch->schib.pmcw.intparm = (__u32)(unsigned long)sch;
 		ret = cio_modify(sch);
 		if (ret == -ENODEV)
 			break;
@@ -463,9 +465,8 @@ cio_disable_subchannel (struct subchannel *sch)
 		 */
 		return -EBUSY;
 
-
-	sch->schib.pmcw.ena = 0;
 	for (retry = 5, ret = 0; retry > 0; retry--) {
+		sch->schib.pmcw.ena = 0;
 		ret = cio_modify(sch);
 		if (ret == -ENODEV)
 			break;
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index 788ae49c5..1708a16e4 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/s390/cio/cmf.c ($Revision: 1.15 $)
+ * linux/drivers/s390/cio/cmf.c ($Revision: 1.16 $)
  *
  * Linux on zSeries Channel Measurement Facility support
  *
@@ -526,29 +526,26 @@ readall_cmb (struct ccw_device *cdev, struct cmbdata *data)
 	time = get_clock() - cdev->private->cmb_start_time;
 	spin_unlock_irqrestore(cdev->ccwlock, flags);
 
-	*data = (struct cmbdata) {
-		/* we only know values before device_busy_time */
-		.size = offsetof(struct cmbdata, device_busy_time),
-
-		/* conver to nanoseconds */
-		.elapsed_time = (time * 1000) >> 12,
-
-		/* copy data to new structure */
-		.ssch_rsch_count		= cmb.ssch_rsch_count,
-		.sample_count			= cmb.sample_count,
-
-		/* time fields are converted to nanoseconds while copying */
-		.device_connect_time
-			= time_to_nsec(cmb.device_connect_time),
-		.function_pending_time
-			= time_to_nsec(cmb.function_pending_time),
-		.device_disconnect_time
-			= time_to_nsec(cmb.device_disconnect_time),
-		.control_unit_queuing_time
-		 	= time_to_nsec(cmb.control_unit_queuing_time),
-		.device_active_only_time
-			= time_to_nsec(cmb.device_active_only_time),
-	};
+	memset(data, sizeof(struct cmbdata), 0);
+
+	/* we only know values before device_busy_time */
+	data->size = offsetof(struct cmbdata, device_busy_time);
+
+	/* convert to nanoseconds */
+	data->elapsed_time = (time * 1000) >> 12;
+
+	/* copy data to new structure */
+	data->ssch_rsch_count = cmb.ssch_rsch_count;
+	data->sample_count = cmb.sample_count;
+
+	/* time fields are converted to nanoseconds while copying */
+	data->device_connect_time = time_to_nsec(cmb.device_connect_time);
+	data->function_pending_time = time_to_nsec(cmb.function_pending_time);
+	data->device_disconnect_time = time_to_nsec(cmb.device_disconnect_time);
+	data->control_unit_queuing_time
+		= time_to_nsec(cmb.control_unit_queuing_time);
+	data->device_active_only_time
+		= time_to_nsec(cmb.device_active_only_time);
 
 	return 0;
 }
@@ -739,33 +736,29 @@ readall_cmbe (struct ccw_device *cdev, struct cmbdata *data)
 	time = get_clock() - cdev->private->cmb_start_time;
 	spin_unlock_irqrestore(cdev->ccwlock, flags);
 
-	*data = (struct cmbdata) {
-		/* we only know values before device_busy_time */
-		.size = offsetof(struct cmbdata, device_busy_time),
-
-		/* conver to nanoseconds */
-		.elapsed_time = (time * 1000) >> 12,
-
-		/* copy data to new structure */
-		.ssch_rsch_count		= cmb.ssch_rsch_count,
-		.sample_count			= cmb.sample_count,
-
-		/* time fields are converted to nanoseconds while copying */
-		.device_connect_time
-			= time_to_nsec(cmb.device_connect_time),
-		.function_pending_time
-			= time_to_nsec(cmb.function_pending_time),
-		.device_disconnect_time
-			= time_to_nsec(cmb.device_disconnect_time),
-		.control_unit_queuing_time
-		 	= time_to_nsec(cmb.control_unit_queuing_time),
-		.device_active_only_time
-			= time_to_nsec(cmb.device_active_only_time),
-		.device_busy_time
-			= time_to_nsec(cmb.device_busy_time),
-		.initial_command_response_time
-			= time_to_nsec(cmb.initial_command_response_time),
-	};
+	memset (data, sizeof(struct cmbdata), 0);
+
+	/* we only know values before device_busy_time */
+	data->size = offsetof(struct cmbdata, device_busy_time);
+
+	/* conver to nanoseconds */
+	data->elapsed_time = (time * 1000) >> 12;
+
+	/* copy data to new structure */
+	data->ssch_rsch_count = cmb.ssch_rsch_count;
+	data->sample_count = cmb.sample_count;
+
+	/* time fields are converted to nanoseconds while copying */
+	data->device_connect_time = time_to_nsec(cmb.device_connect_time);
+	data->function_pending_time = time_to_nsec(cmb.function_pending_time);
+	data->device_disconnect_time = time_to_nsec(cmb.device_disconnect_time);
+	data->control_unit_queuing_time
+		= time_to_nsec(cmb.control_unit_queuing_time);
+	data->device_active_only_time
+		= time_to_nsec(cmb.device_active_only_time);
+	data->device_busy_time = time_to_nsec(cmb.device_busy_time);
+	data->initial_command_response_time
+		= time_to_nsec(cmb.initial_command_response_time);
 
 	return 0;
 }
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index dba1bfb9a..dd12416e8 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/css.c
  *  driver for channel subsystem
- *   $Revision: 1.80 $
+ *   $Revision: 1.82 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *			 IBM Corporation
@@ -278,7 +278,7 @@ css_rescan_devices(void)
 {
 	int irq, ret;
 
-	for (irq = 0; irq <= __MAX_SUBCHANNELS; irq++) {
+	for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) {
 		ret = css_evaluate_subchannel(irq, 1);
 		/* No more memory. It doesn't make sense to continue. No
 		 * panic because this can happen in midflight and just
@@ -521,6 +521,7 @@ css_enqueue_subchannel_slow(unsigned long schid)
 	new_slow_sch = kmalloc(sizeof(struct slow_subchannel), GFP_ATOMIC);
 	if (!new_slow_sch)
 		return -ENOMEM;
+	memset(new_slow_sch, sizeof(struct slow_subchannel), 0);
 	new_slow_sch->schid = schid;
 	spin_lock_irqsave(&slow_subchannel_lock, flags);
 	list_add_tail(&new_slow_sch->slow_list, &slow_subchannels_head);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index a921b1fea..bf652fa34 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/device.c
  *  bus driver for ccw devices
- *   $Revision: 1.120 $
+ *   $Revision: 1.124 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *			 IBM Corporation
@@ -540,6 +540,8 @@ get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling)
 	return cdev;
 }
 
+extern int css_get_ssd_info(struct subchannel *sch);
+
 void
 ccw_device_do_unreg_rereg(void *data)
 {
@@ -581,6 +583,8 @@ ccw_device_do_unreg_rereg(void *data)
 				device_unregister(&other_sch->dev);
 			}
 		}
+		/* Update ssd info here. */
+		css_get_ssd_info(sch);
 		cdev->private->devno = sch->schib.pmcw.dev;
 	} else
 		need_rename = 0;
@@ -633,7 +637,8 @@ io_subchannel_register(void *data)
 		sch->dev.driver_data = 0;
 		kfree (cdev->private);
 		kfree (cdev);
-		goto out;
+		put_device(&sch->dev);
+		return;
 	}
 
 	ret = subchannel_add_files(cdev->dev.parent);
@@ -707,18 +712,19 @@ static int
 io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch)
 {
 	int rc;
+	struct ccw_device_private *priv;
 
 	sch->dev.driver_data = cdev;
 	sch->driver = &io_subchannel_driver;
 	cdev->ccwlock = &sch->lock;
-	*cdev->private = (struct ccw_device_private) {
-		.devno	= sch->schib.pmcw.dev,
-		.irq	= sch->irq,
-		.state	= DEV_STATE_NOT_OPER,
-		.cmb_list = LIST_HEAD_INIT(cdev->private->cmb_list),
-	};
-	init_waitqueue_head(&cdev->private->wait_q);
-	init_timer(&cdev->private->timer);
+	/* Init private data. */
+	priv = cdev->private;
+	priv->devno = sch->schib.pmcw.dev;
+	priv->irq = sch->irq;
+	priv->state = DEV_STATE_NOT_OPER;
+	INIT_LIST_HEAD(&priv->cmb_list);
+	init_waitqueue_head(&priv->wait_q);
+	init_timer(&priv->timer);
 
 	/* Set an initial name for the device. */
 	snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.0.%04x",
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 6a8db8450..03b569b4b 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -995,6 +995,7 @@ device_trigger_reprobe(struct subchannel *sch)
 	if ((sch->lpm & (sch->lpm - 1)) != 0)
 		sch->schib.pmcw.mp = 1;
 	sch->schib.pmcw.intparm = (__u32)(unsigned long)sch;
+	/* We should also udate ssd info, but this has to wait. */
 	ccw_device_start_id(cdev, 0);
 	spin_unlock_irqrestore(&sch->lock, flags);
 }
diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
index 32365959c..f6cb89728 100644
--- a/drivers/s390/cio/device_id.c
+++ b/drivers/s390/cio/device_id.c
@@ -303,10 +303,10 @@ ccw_device_sense_id_irq(struct ccw_device *cdev, enum dev_event dev_event)
 
 	sch = to_subchannel(cdev->dev.parent);
 	irb = (struct irb *) __LC_IRB;
-	/* Retry sense id for cc=1. */
+	/* Retry sense id, if needed. */
 	if (irb->scsw.stctl ==
 	    (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
-		if (irb->scsw.cc == 1) {
+		if ((irb->scsw.cc == 1) || !irb->scsw.actl) {
 			ret = __ccw_device_sense_id_start(cdev);
 			if (ret && ret != -EBUSY)
 				ccw_device_sense_id_done(cdev, ret);
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index bc768b62a..4f7dca3c7 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -56,7 +56,7 @@
 #include "ioasm.h"
 #include "chsc.h"
 
-#define VERSION_QDIO_C "$Revision: 1.84 $"
+#define VERSION_QDIO_C "$Revision: 1.86 $"
 
 /****************** MODULE PARAMETER VARIABLES ********************/
 MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
@@ -365,7 +365,7 @@ qdio_stop_polling(struct qdio_q *q)
 	 * small window we can miss between resetting it and
 	 * checking for PRIMED state 
 	 */
-	if (q->is_iqdio_q)
+	if (q->is_thinint_q)
 		tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind);
 	return 0;
 
diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c
index 6290b5c56..2806b2d15 100644
--- a/drivers/s390/net/ctctty.c
+++ b/drivers/s390/net/ctctty.c
@@ -307,10 +307,7 @@ ctc_tty_tint(ctc_tty_info * info)
 
 		info->flags &= ~CTC_ASYNC_TX_LINESTAT;
 		if (tty) {
-			if (wake && (tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-			    tty->ldisc.write_wakeup)
-				(tty->ldisc.write_wakeup)(tty);
-			wake_up_interruptible(&tty->write_wait);
+			tty_wakeup(tty);
 		}
 	}
 	return (skb_queue_empty(&info->tx_queue) ? 0 : 1);
@@ -589,9 +586,7 @@ ctc_tty_flush_buffer(struct tty_struct *tty)
 	info->lsr |= UART_LSR_TEMT;
 	spin_unlock_irqrestore(&ctc_tty_lock, flags);
 	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup) (tty);
+	tty_wakeup(tty);
 ex:
 	DBF_TEXT_(trace, 2, "ex: %s ", __FUNCTION__);
 	return;
@@ -1066,8 +1061,7 @@ ctc_tty_close(struct tty_struct *tty, struct file *filp)
 		skb_queue_purge(&info->tx_queue);
 		info->lsr |= UART_LSR_TEMT;
 	}
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
 	info->tty = 0;
 	tty->closing = 0;
 	if (info->blocked_open) {
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index cac57951a..f78636132 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -11,7 +11,7 @@
  *			  Frank Pavlic (pavlic@de.ibm.com) and
  *		 	  Martin Schwidefsky <schwidefsky@de.ibm.com>
  *
- *    $Revision: 1.85 $	 $Date: 2004/08/04 11:05:43 $
+ *    $Revision: 1.92 $	 $Date: 2004/09/03 08:06:11 $
  *
  * 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
@@ -59,7 +59,7 @@
 /**
  * initialization string for output
  */
-#define VERSION_LCS_C  "$Revision: 1.85 $"
+#define VERSION_LCS_C  "$Revision: 1.92 $"
 
 static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")";
 static char debug_buffer[255];
@@ -70,6 +70,7 @@ static char debug_buffer[255];
 static void lcs_tasklet(unsigned long);
 static void lcs_start_kernel_thread(struct lcs_card *card);
 static void lcs_get_frames_cb(struct lcs_channel *, struct lcs_buffer *);
+static int lcs_send_delipm(struct lcs_card *, struct lcs_ipm_list *);
 
 /**
  * Debug Facility Stuff
@@ -100,9 +101,9 @@ lcs_register_debug_facility(void)
 		return -ENOMEM;
 	}
 	debug_register_view(lcs_dbf_setup, &debug_hex_ascii_view);
-	debug_set_level(lcs_dbf_setup, 2);
+	debug_set_level(lcs_dbf_setup, 4);
 	debug_register_view(lcs_dbf_trace, &debug_hex_ascii_view);
-	debug_set_level(lcs_dbf_trace, 2);
+	debug_set_level(lcs_dbf_trace, 4);
 	return 0;
 }
 
@@ -316,7 +317,106 @@ lcs_setup_write(struct lcs_card *card)
 	init_waitqueue_head(&card->write.wait_q);
 }
 
+static void
+lcs_set_allowed_threads(struct lcs_card *card, unsigned long threads)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->mask_lock, flags);
+	card->thread_allowed_mask = threads;
+	spin_unlock_irqrestore(&card->mask_lock, flags);
+	wake_up(&card->wait_q);
+}
+static inline int
+lcs_threads_running(struct lcs_card *card, unsigned long threads)
+{
+        unsigned long flags;
+        int rc = 0;
+
+	spin_lock_irqsave(&card->mask_lock, flags);
+        rc = (card->thread_running_mask & threads);
+	spin_unlock_irqrestore(&card->mask_lock, flags);
+        return rc;
+}
+
+static int
+lcs_wait_for_threads(struct lcs_card *card, unsigned long threads)
+{
+        return wait_event_interruptible(card->wait_q,
+                        lcs_threads_running(card, threads) == 0);
+}
+
+static inline int
+lcs_set_thread_start_bit(struct lcs_card *card, unsigned long thread)
+{
+        unsigned long flags;
+
+	spin_lock_irqsave(&card->mask_lock, flags);
+        if ( !(card->thread_allowed_mask & thread) ||
+              (card->thread_start_mask & thread) ) {
+                spin_unlock_irqrestore(&card->mask_lock, flags);
+                return -EPERM;
+        }
+        card->thread_start_mask |= thread;
+	spin_unlock_irqrestore(&card->mask_lock, flags);
+        return 0;
+}
+
+static void
+lcs_clear_thread_running_bit(struct lcs_card *card, unsigned long thread)
+{
+        unsigned long flags;
 
+	spin_lock_irqsave(&card->mask_lock, flags);
+        card->thread_running_mask &= ~thread;
+	spin_unlock_irqrestore(&card->mask_lock, flags);
+        wake_up(&card->wait_q);
+}
+
+static inline int
+__lcs_do_run_thread(struct lcs_card *card, unsigned long thread)
+{
+        unsigned long flags;
+        int rc = 0;
+
+	spin_lock_irqsave(&card->mask_lock, flags);
+        if (card->thread_start_mask & thread){
+                if ((card->thread_allowed_mask & thread) &&
+                    !(card->thread_running_mask & thread)){
+                        rc = 1;
+                        card->thread_start_mask &= ~thread;
+                        card->thread_running_mask |= thread;
+                } else
+                        rc = -EPERM;
+        }
+	spin_unlock_irqrestore(&card->mask_lock, flags);
+        return rc;
+}
+
+static int
+lcs_do_run_thread(struct lcs_card *card, unsigned long thread)
+{
+        int rc = 0;
+        wait_event(card->wait_q,
+                   (rc = __lcs_do_run_thread(card, thread)) >= 0);
+        return rc;
+}
+
+static int
+lcs_do_start_thread(struct lcs_card *card, unsigned long thread)
+{
+        unsigned long flags;
+        int rc = 0;
+
+	spin_lock_irqsave(&card->mask_lock, flags);
+        LCS_DBF_TEXT_(4, trace, "  %02x%02x%02x",
+                        (u8) card->thread_start_mask,
+                        (u8) card->thread_allowed_mask,
+                        (u8) card->thread_running_mask);
+        rc = (card->thread_start_mask & thread);
+	spin_unlock_irqrestore(&card->mask_lock, flags);
+        return rc;
+}
 
 /**
  * Initialize channels,card and state machines.
@@ -337,34 +437,53 @@ lcs_setup_card(struct lcs_card *card)
 	/* Initialize kernel thread task used for LGW commands. */
 	INIT_WORK(&card->kernel_thread_starter,
 		  (void *)lcs_start_kernel_thread,card);
-	card->thread_mask = 0;
+	card->thread_start_mask = 0;
+	card->thread_allowed_mask = 0;
+	card->thread_running_mask = 0;
+	init_waitqueue_head(&card->wait_q);
 	spin_lock_init(&card->lock);
 	spin_lock_init(&card->ipm_lock);
+	spin_lock_init(&card->mask_lock);
 #ifdef CONFIG_IP_MULTICAST
 	INIT_LIST_HEAD(&card->ipm_list);
 #endif
 	INIT_LIST_HEAD(&card->lancmd_waiters);
 }
 
+static inline void
+lcs_clear_multicast_list(struct lcs_card *card)
+{
+#ifdef	CONFIG_IP_MULTICAST
+	struct lcs_ipm_list *ipm;
+	unsigned long flags;
+
+	/* Free multicast list. */
+	LCS_DBF_TEXT(3, setup, "clmclist");
+	spin_lock_irqsave(&card->ipm_lock, flags);
+	while (!list_empty(&card->ipm_list)){
+		ipm = list_entry(card->ipm_list.next,
+				 struct lcs_ipm_list, list);
+		list_del(&ipm->list);
+		if (ipm->ipm_state != LCS_IPM_STATE_SET_REQUIRED){
+			spin_unlock_irqrestore(&card->ipm_lock, flags);
+			lcs_send_delipm(card, ipm);
+			spin_lock_irqsave(&card->ipm_lock, flags);
+		}
+		kfree(ipm);
+	}
+	spin_unlock_irqrestore(&card->ipm_lock, flags);
+#endif
+}
 /**
  * Cleanup channels,card and state machines.
  */
 static void
 lcs_cleanup_card(struct lcs_card *card)
 {
-	struct list_head *l, *n;
-	struct lcs_ipm_list *ipm_list;
 
 	LCS_DBF_TEXT(3, setup, "cleancrd");
 	LCS_DBF_HEX(2,setup,&card,sizeof(void*));
-#ifdef	CONFIG_IP_MULTICAST
-	/* Free multicast list. */
-	list_for_each_safe(l, n, &card->ipm_list) {
-		ipm_list = list_entry(l, struct lcs_ipm_list, list);
-		list_del(&ipm_list->list);
-		kfree(ipm_list);
-	}
-#endif
+
 	if (card->dev != NULL)
 		free_netdev(card->dev);
 	/* Cleanup channels. */
@@ -651,6 +770,44 @@ lcs_get_lancmd(struct lcs_card *card, int count)
 	return buffer;
 }
 
+
+static void
+lcs_get_reply(struct lcs_reply *reply)
+{
+	WARN_ON(atomic_read(&reply->refcnt) <= 0);
+	atomic_inc(&reply->refcnt);
+}
+
+static void
+lcs_put_reply(struct lcs_reply *reply)
+{
+        WARN_ON(atomic_read(&reply->refcnt) <= 0);
+        if (atomic_dec_and_test(&reply->refcnt)) {
+		kfree(reply);
+	}
+
+}
+
+static struct lcs_reply *
+lcs_alloc_reply(struct lcs_cmd *cmd)
+{
+	struct lcs_reply *reply;
+
+	LCS_DBF_TEXT(4, trace, "getreply");
+
+	reply = kmalloc(sizeof(struct lcs_reply), GFP_ATOMIC);
+	if (!reply)
+		return NULL;
+	memset(reply,0,sizeof(struct lcs_reply));
+	atomic_set(&reply->refcnt,1);
+	reply->sequence_no = cmd->sequence_no;
+	reply->received = 0;
+	reply->rc = 0;
+	init_waitqueue_head(&reply->wait_q);
+
+	return reply;
+}
+
 /**
  * Notifier function for lancmd replies. Called from read irq.
  */
@@ -665,12 +822,14 @@ lcs_notify_lancmd_waiters(struct lcs_card *card, struct lcs_cmd *cmd)
 	list_for_each_safe(l, n, &card->lancmd_waiters) {
 		reply = list_entry(l, struct lcs_reply, list);
 		if (reply->sequence_no == cmd->sequence_no) {
-			list_del(&reply->list);
+			lcs_get_reply(reply);
+			list_del_init(&reply->list);
 			if (reply->callback != NULL)
 				reply->callback(card, cmd);
 			reply->received = 1;
 			reply->rc = cmd->return_code;
 			wake_up(&reply->wait_q);
+			lcs_put_reply(reply);
 			break;
 		}
 	}
@@ -683,50 +842,66 @@ lcs_notify_lancmd_waiters(struct lcs_card *card, struct lcs_cmd *cmd)
 void
 lcs_lancmd_timeout(unsigned long data)
 {
-	struct lcs_reply *reply;
+	struct lcs_reply *reply, *list_reply, *r;
+	unsigned long flags;
 
 	LCS_DBF_TEXT(4, trace, "timeout");
 	reply = (struct lcs_reply *) data;
-	list_del(&reply->list);
-	reply->received = 1;
-	reply->rc = -ETIME;
-	wake_up(&reply->wait_q);
+	spin_lock_irqsave(&reply->card->lock, flags);
+	list_for_each_entry_safe(list_reply, r,
+				 &reply->card->lancmd_waiters,list) {
+		if (reply == list_reply) {
+			lcs_get_reply(reply);
+			list_del_init(&reply->list);
+			spin_unlock_irqrestore(&reply->card->lock, flags);
+			reply->received = 1;
+			reply->rc = -ETIME;
+			wake_up(&reply->wait_q);
+			lcs_put_reply(reply);
+			return;
+		}
+	}
+	spin_unlock_irqrestore(&reply->card->lock, flags);
 }
 
 static int
 lcs_send_lancmd(struct lcs_card *card, struct lcs_buffer *buffer,
 		void (*reply_callback)(struct lcs_card *, struct lcs_cmd *))
 {
-	struct lcs_reply reply;
+	struct lcs_reply *reply;
 	struct lcs_cmd *cmd;
 	struct timer_list timer;
+	unsigned long flags;
 	int rc;
 
 	LCS_DBF_TEXT(4, trace, "sendcmd");
 	cmd = (struct lcs_cmd *) buffer->data;
-	cmd->sequence_no = ++card->sequence_no;
 	cmd->return_code = 0;
-	reply.sequence_no = cmd->sequence_no;
-	reply.callback = reply_callback;
-	reply.received = 0;
-	reply.rc = 0;
-	init_waitqueue_head(&reply.wait_q);
-	spin_lock(&card->lock);
-	list_add_tail(&reply.list, &card->lancmd_waiters);
-	spin_unlock(&card->lock);
+	cmd->sequence_no = card->sequence_no++;
+	reply = lcs_alloc_reply(cmd);
+	if (!reply)
+		return -ENOMEM;
+	reply->callback = reply_callback;
+	reply->card = card;
+	spin_lock_irqsave(&card->lock, flags);
+	list_add_tail(&reply->list, &card->lancmd_waiters);
+	spin_unlock_irqrestore(&card->lock, flags);
+
 	buffer->callback = lcs_release_buffer;
 	rc = lcs_ready_buffer(&card->write, buffer);
 	if (rc)
 		return rc;
 	init_timer(&timer);
 	timer.function = lcs_lancmd_timeout;
-	timer.data = (unsigned long) &reply;
+	timer.data = (unsigned long) reply;
 	timer.expires = jiffies + HZ*card->lancmd_timeout;
 	add_timer(&timer);
-	wait_event(reply.wait_q, reply.received);
-	del_timer(&timer);
-	LCS_DBF_TEXT_(4, trace, "rc:%d",reply.rc);
-	return reply.rc ? -EIO : 0;
+	wait_event(reply->wait_q, reply->received);
+	del_timer_sync(&timer);
+	LCS_DBF_TEXT_(4, trace, "rc:%d",reply->rc);
+	rc = reply->rc;
+	lcs_put_reply(reply);
+	return rc ? -EIO : 0;
 }
 
 /**
@@ -940,33 +1115,56 @@ lcs_check_multicast_support(struct lcs_card *card)
 static void
 lcs_fix_multicast_list(struct lcs_card *card)
 {
-	struct list_head *l, *n;
-	struct lcs_ipm_list *ipm;
+	struct list_head failed_list;
+	struct lcs_ipm_list *ipm, *tmp;
+	unsigned long flags;
+	int rc;
 
 	LCS_DBF_TEXT(4,trace, "fixipm");
-	spin_lock(&card->ipm_lock);
-	list_for_each_safe(l, n, &card->ipm_list) {
-		ipm = list_entry(l, struct lcs_ipm_list, list);
+	INIT_LIST_HEAD(&failed_list);
+	spin_lock_irqsave(&card->ipm_lock, flags);
+list_modified:
+	list_for_each_entry_safe(ipm, tmp, &card->ipm_list, list){
 		switch (ipm->ipm_state) {
 		case LCS_IPM_STATE_SET_REQUIRED:
-			if (lcs_send_setipm(card, ipm))
+			/* del from ipm_list so noone else can tamper with
+			 * this entry */
+			list_del_init(&ipm->list);
+			spin_unlock_irqrestore(&card->ipm_lock, flags);
+			rc = lcs_send_setipm(card, ipm);
+			spin_lock_irqsave(&card->ipm_lock, flags);
+			if (rc) {
 				PRINT_INFO("Adding multicast address failed."
 					   "Table possibly full!\n");
-			else
+				/* store ipm in failed list -> will be added
+				 * to ipm_list again, so a retry will be done
+				 * during the next call of this function */
+				list_add_tail(&ipm->list, &failed_list);
+			} else {
 				ipm->ipm_state = LCS_IPM_STATE_ON_CARD;
-			break;
+				/* re-insert into ipm_list */
+				list_add_tail(&ipm->list, &card->ipm_list);
+			}
+			goto list_modified;
 		case LCS_IPM_STATE_DEL_REQUIRED:
-			lcs_send_delipm(card, ipm);
 			list_del(&ipm->list);
+			spin_unlock_irqrestore(&card->ipm_lock, flags);
+			lcs_send_delipm(card, ipm);
+			spin_lock_irqsave(&card->ipm_lock, flags);
 			kfree(ipm);
-			break;
+			goto list_modified;
 		case LCS_IPM_STATE_ON_CARD:
 			break;
 		}
 	}
+	/* re-insert all entries from the failed_list into ipm_list */
+	list_for_each_entry(ipm, &failed_list, list) {
+		list_del_init(&ipm->list);
+		list_add_tail(&ipm->list, &card->ipm_list);
+	}
+	spin_unlock_irqrestore(&card->ipm_lock, flags);
 	if (card->state == DEV_STATE_UP)
 		netif_wake_queue(card->dev);
-	spin_unlock(&card->ipm_lock);
 }
 
 /**
@@ -985,51 +1183,67 @@ lcs_get_mac_for_ipm(__u32 ipm, char *mac, struct net_device *dev)
 /**
  * function called by net device to handle multicast address relevant things
  */
-static int
-lcs_register_mc_addresses(void *data)
+static inline void
+lcs_remove_mc_addresses(struct lcs_card *card, struct in_device *in4_dev)
 {
-	struct lcs_card *card;
-	char buf[MAX_ADDR_LEN];
-	struct list_head *l;
 	struct ip_mc_list *im4;
-	struct in_device *in4_dev;
-	struct lcs_ipm_list *ipm, *tmp;
-
-	daemonize("regipm");
-	LCS_DBF_TEXT(4, trace, "regmulti");
+	struct list_head *l;
+	struct lcs_ipm_list *ipm;
+	unsigned long flags;
+	char buf[MAX_ADDR_LEN];
 
-	card = (struct lcs_card *) data;
-	in4_dev = in_dev_get(card->dev);
-	if (in4_dev == NULL)
-		return 0;
-	read_lock(&in4_dev->lock);
-	spin_lock(&card->ipm_lock);
-	/* Check for multicast addresses to be removed. */
+	LCS_DBF_TEXT(4, trace, "remmclst");
+	spin_lock_irqsave(&card->ipm_lock, flags);
 	list_for_each(l, &card->ipm_list) {
 		ipm = list_entry(l, struct lcs_ipm_list, list);
 		for (im4 = in4_dev->mc_list; im4 != NULL; im4 = im4->next) {
 			lcs_get_mac_for_ipm(im4->multiaddr, buf, card->dev);
-			if (memcmp(buf, &ipm->ipm.mac_addr,
-				   LCS_MAC_LENGTH) == 0 &&
-			    ipm->ipm.ip_addr == im4->multiaddr)
+			if ( (ipm->ipm.ip_addr == im4->multiaddr) &&
+			     (memcmp(buf, &ipm->ipm.mac_addr,
+				     LCS_MAC_LENGTH) == 0) )
 				break;
 		}
 		if (im4 == NULL)
 			ipm->ipm_state = LCS_IPM_STATE_DEL_REQUIRED;
 	}
-	/* Check for multicast addresses to be added. */
+	spin_unlock_irqrestore(&card->ipm_lock, flags);
+}
+
+static inline struct lcs_ipm_list *
+lcs_check_addr_entry(struct lcs_card *card, struct ip_mc_list *im4, char *buf)
+{
+	struct lcs_ipm_list *tmp, *ipm = NULL;
+	struct list_head *l;
+	unsigned long flags;
+
+	LCS_DBF_TEXT(4, trace, "chkmcent");
+	spin_lock_irqsave(&card->ipm_lock, flags);
+	list_for_each(l, &card->ipm_list) {
+		tmp = list_entry(l, struct lcs_ipm_list, list);
+		if ( (tmp->ipm.ip_addr == im4->multiaddr) &&
+		     (memcmp(buf, &tmp->ipm.mac_addr,
+			     LCS_MAC_LENGTH) == 0) ) {
+			ipm = tmp;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&card->ipm_lock, flags);
+	return ipm;
+}
+
+static inline void
+lcs_set_mc_addresses(struct lcs_card *card, struct in_device *in4_dev)
+{
+
+	struct ip_mc_list *im4;
+	struct lcs_ipm_list *ipm;
+	char buf[MAX_ADDR_LEN];
+	unsigned long flags;
+
+	LCS_DBF_TEXT(4, trace, "setmclst");
 	for (im4 = in4_dev->mc_list; im4; im4 = im4->next) {
 		lcs_get_mac_for_ipm(im4->multiaddr, buf, card->dev);
-		ipm = NULL;
-		list_for_each(l, &card->ipm_list) {
-			tmp = list_entry(l, struct lcs_ipm_list, list);
-			if (memcmp(buf, &tmp->ipm.mac_addr,
-				   LCS_MAC_LENGTH) == 0 &&
-			    tmp->ipm.ip_addr == im4->multiaddr) {
-				ipm = tmp;
-				break;
-			}
-		}
+		ipm = lcs_check_addr_entry(card, im4, buf);
 		if (ipm != NULL)
 			continue;	/* Address already in list. */
 		ipm = (struct lcs_ipm_list *)
@@ -1043,12 +1257,37 @@ lcs_register_mc_addresses(void *data)
 		memcpy(&ipm->ipm.mac_addr, buf, LCS_MAC_LENGTH);
 		ipm->ipm.ip_addr = im4->multiaddr;
 		ipm->ipm_state = LCS_IPM_STATE_SET_REQUIRED;
+		spin_lock_irqsave(&card->ipm_lock, flags);
 		list_add(&ipm->list, &card->ipm_list);
+		spin_unlock_irqrestore(&card->ipm_lock, flags);
 	}
-	spin_unlock(&card->ipm_lock);
-	read_unlock(&in4_dev->lock);
+}
+
+static int
+lcs_register_mc_addresses(void *data)
+{
+	struct lcs_card *card;
+	struct in_device *in4_dev;
+
+	card = (struct lcs_card *) data;
+	daemonize("regipm");
+
+	if (!lcs_do_run_thread(card, LCS_SET_MC_THREAD))
+		return 0;
+	LCS_DBF_TEXT(4, trace, "regmulti");
+
+	in4_dev = in_dev_get(card->dev);
+	if (in4_dev == NULL)
+		goto out;
+	read_lock(&in4_dev->mc_list_lock);
+	lcs_remove_mc_addresses(card,in4_dev);
+	lcs_set_mc_addresses(card, in4_dev);
+	read_unlock(&in4_dev->mc_list_lock);
 	in_dev_put(in4_dev);
+
 	lcs_fix_multicast_list(card);
+out:
+	lcs_clear_thread_running_bit(card, LCS_SET_MC_THREAD);
 	return 0;
 }
 /**
@@ -1062,8 +1301,10 @@ lcs_set_multicast_list(struct net_device *dev)
 
         LCS_DBF_TEXT(4, trace, "setmulti");
         card = (struct lcs_card *) dev->priv;
-        set_bit(3, &card->thread_mask);
-        schedule_work(&card->kernel_thread_starter);
+
+        if (!lcs_set_thread_start_bit(card, LCS_SET_MC_THREAD)) {
+		schedule_work(&card->kernel_thread_starter);
+	}
 }
 
 #endif /* CONFIG_IP_MULTICAST */
@@ -1427,6 +1668,7 @@ lcs_resetcard(struct lcs_card *card)
 	return -EIO;
 }
 
+
 /**
  * LCS Stop card
  */
@@ -1440,6 +1682,7 @@ lcs_stopcard(struct lcs_card *card)
 	if (card->read.state != CH_STATE_STOPPED &&
 	    card->write.state != CH_STATE_STOPPED &&
 	    card->state == DEV_STATE_UP) {
+		lcs_clear_multicast_list(card);
 		rc = lcs_send_stoplan(card,LCS_INITIATOR_TCPIP);
 		rc = lcs_send_shutdown(card);
 	}
@@ -1459,6 +1702,9 @@ lcs_lgw_startlan_thread(void *data)
 
 	card = (struct lcs_card *) data;
 	daemonize("lgwstpln");
+
+	if (!lcs_do_run_thread(card, LCS_STARTLAN_THREAD))
+		return 0;
 	LCS_DBF_TEXT(4, trace, "lgwstpln");
 	if (card->dev)
 		netif_stop_queue(card->dev);
@@ -1471,6 +1717,7 @@ lcs_lgw_startlan_thread(void *data)
 	} else
 		PRINT_ERR("LCS Startlan for device %s failed!\n",
 			  card->dev->name);
+	lcs_clear_thread_running_bit(card, LCS_STARTLAN_THREAD);
 	return 0;
 }
 
@@ -1485,8 +1732,11 @@ lcs_lgw_startup_thread(void *data)
 	struct lcs_card *card;
 
 	card = (struct lcs_card *) data;
-	daemonize("lgwstpln");
-	LCS_DBF_TEXT(4, trace, "lgwstpln");
+	daemonize("lgwstaln");
+
+	if (!lcs_do_run_thread(card, LCS_STARTUP_THREAD))
+		return 0;
+	LCS_DBF_TEXT(4, trace, "lgwstaln");
 	if (card->dev)
 		netif_stop_queue(card->dev);
 	rc = lcs_send_startup(card, LCS_INITIATOR_LGW);
@@ -1511,6 +1761,7 @@ Done:
 	else
 		PRINT_ERR("LCS Startup for device %s failed!\n",
 			  card->dev->name);
+	lcs_clear_thread_running_bit(card, LCS_STARTUP_THREAD);
 	return 0;
 }
 
@@ -1526,6 +1777,9 @@ lcs_lgw_stoplan_thread(void *data)
 
 	card = (struct lcs_card *) data;
 	daemonize("lgwstop");
+
+	if (!lcs_do_run_thread(card, LCS_STOPLAN_THREAD))
+		return 0;
 	LCS_DBF_TEXT(4, trace, "lgwstop");
 	if (card->dev)
 		netif_stop_queue(card->dev);
@@ -1539,6 +1793,7 @@ lcs_lgw_stoplan_thread(void *data)
         rc = lcs_resetcard(card);
         if (rc != 0)
                 rc = lcs_stopcard(card);
+	lcs_clear_thread_running_bit(card, LCS_STOPLAN_THREAD);
         return rc;
 }
 
@@ -1549,14 +1804,14 @@ static void
 lcs_start_kernel_thread(struct lcs_card *card)
 {
 	LCS_DBF_TEXT(5, trace, "krnthrd");
-	if (test_and_clear_bit(0, &card->thread_mask))
+	if (lcs_do_start_thread(card, LCS_STARTUP_THREAD))
 		kernel_thread(lcs_lgw_startup_thread, (void *) card, SIGCHLD);
-	if (test_and_clear_bit(1, &card->thread_mask))
+	if (lcs_do_start_thread(card, LCS_STARTLAN_THREAD))
 		kernel_thread(lcs_lgw_startlan_thread, (void *) card, SIGCHLD);
-	if (test_and_clear_bit(2, &card->thread_mask))
+	if (lcs_do_start_thread(card, LCS_STOPLAN_THREAD))
 		kernel_thread(lcs_lgw_stoplan_thread, (void *) card, SIGCHLD);
 #ifdef CONFIG_IP_MULTICAST
-	if (test_and_clear_bit(3, &card->thread_mask))
+	if (lcs_do_start_thread(card, LCS_SET_MC_THREAD))
 		kernel_thread(lcs_register_mc_addresses, (void *) card, SIGCHLD);
 #endif
 }
@@ -1571,16 +1826,19 @@ lcs_get_control(struct lcs_card *card, struct lcs_cmd *cmd)
 	if (cmd->initiator == LCS_INITIATOR_LGW) {
 		switch(cmd->cmd_code) {
 		case LCS_CMD_STARTUP:
-			set_bit(0, &card->thread_mask);
-			schedule_work(&card->kernel_thread_starter);
+			if (!lcs_set_thread_start_bit(card,
+						      LCS_STARTUP_THREAD))
+				schedule_work(&card->kernel_thread_starter);
 			break;
 		case LCS_CMD_STARTLAN:
-			set_bit(1, &card->thread_mask);
-			schedule_work(&card->kernel_thread_starter);
+			if (!lcs_set_thread_start_bit(card,
+						      LCS_STARTLAN_THREAD))
+				schedule_work(&card->kernel_thread_starter);
 			break;
 		case LCS_CMD_STOPLAN:
-			set_bit(2, &card->thread_mask);
-			schedule_work(&card->kernel_thread_starter);
+			if (!lcs_set_thread_start_bit(card,
+						      LCS_STOPLAN_THREAD))
+				schedule_work(&card->kernel_thread_starter);
 			break;
 		default:
 			PRINT_INFO("UNRECOGNIZED LGW COMMAND\n");
@@ -1953,7 +2211,9 @@ netdev_out:
 		card->dev->set_multicast_list = lcs_set_multicast_list;
 #endif
 	netif_stop_queue(card->dev);
+	lcs_set_allowed_threads(card,0xffffffff);
 	if (recover_state == DEV_STATE_RECOVER) {
+		lcs_set_multicast_list(card->dev);
 		card->dev->flags |= IFF_UP;
 		netif_wake_queue(card->dev);
 		card->state = DEV_STATE_UP;
@@ -1982,7 +2242,9 @@ lcs_shutdown_device(struct ccwgroup_device *ccwgdev)
 	card = (struct lcs_card *)ccwgdev->dev.driver_data;
 	if (!card)
 		return -ENODEV;
-
+	lcs_set_allowed_threads(card, 0);
+	if (lcs_wait_for_threads(card, LCS_SET_MC_THREAD))
+		return -ERESTARTSYS;
 	LCS_DBF_HEX(3, setup, &card, sizeof(void*));
 	recover_state = card->state;
 
diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h
index 44cf99060..bd3fee027 100644
--- a/drivers/s390/net/lcs.h
+++ b/drivers/s390/net/lcs.h
@@ -6,7 +6,7 @@
 #include <linux/workqueue.h>
 #include <asm/ccwdev.h>
 
-#define VERSION_LCS_H "$Revision: 1.17 $"
+#define VERSION_LCS_H "$Revision: 1.18 $"
 
 #define LCS_DBF_TEXT(level, name, text) \
 	do { \
@@ -152,6 +152,12 @@ enum lcs_dev_states {
 	DEV_STATE_RECOVER,
 };
 
+enum lcs_threads {
+	LCS_SET_MC_THREAD 	= 1,
+	LCS_STARTLAN_THREAD	= 2,
+	LCS_STOPLAN_THREAD	= 4,
+	LCS_STARTUP_THREAD	= 8,
+};
 /**
  * LCS struct declarations
  */
@@ -247,9 +253,11 @@ struct lcs_buffer {
 struct lcs_reply {
 	struct list_head list;
 	__u16 sequence_no;
+	atomic_t refcnt;
 	/* Callback for completion notification. */
 	void (*callback)(struct lcs_card *, struct lcs_cmd *);
 	wait_queue_head_t wait_q;
+	struct lcs_card *card;
 	int received;
 	int rc;
 };
@@ -268,6 +276,7 @@ struct lcs_channel {
 	int buf_idx;
 };
 
+
 /**
  * definition of the lcs card
  */
@@ -287,7 +296,11 @@ struct lcs_card {
 	int lancmd_timeout;
 
 	struct work_struct kernel_thread_starter;
-	unsigned long thread_mask;
+	spinlock_t mask_lock;
+	unsigned long thread_start_mask;
+	unsigned long thread_running_mask;
+	unsigned long thread_allowed_mask;
+	wait_queue_head_t wait_q;
 
 #ifdef CONFIG_IP_MULTICAST
 	struct list_head ipm_list;
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 17f0f67d8..3e374ddfe 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.130 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.145 $)
  *
  * Linux on zSeries OSA Express and HiperSockets support
  *
@@ -12,7 +12,7 @@
  *			  Frank Pavlic (pavlic@de.ibm.com) and
  *		 	  Thomas Spatzier <tspat@de.ibm.com>
  *
- *    $Revision: 1.130 $	 $Date: 2004/08/05 11:21:50 $
+ *    $Revision: 1.145 $	 $Date: 2004/10/08 15:08:40 $
  *
  * 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
@@ -73,12 +73,13 @@ qeth_eyecatcher(void)
 #include <linux/reboot.h>
 #include <asm/qeth.h>
 #include <linux/mii.h>
+#include <linux/rcupdate.h>
 
 #include "qeth.h"
 #include "qeth_mpc.h"
 #include "qeth_fs.h"
 
-#define VERSION_QETH_C "$Revision: 1.130 $"
+#define VERSION_QETH_C "$Revision: 1.145 $"
 static const char *version = "qeth S/390 OSA-Express driver";
 
 /**
@@ -2147,7 +2148,7 @@ qeth_type_trans(struct sk_buff *skb, struct net_device *dev)
 
 	skb->mac.raw = skb->data;
 	skb_pull(skb, ETH_ALEN * 2 + sizeof (short));
-	eth = skb->mac.ethernet;
+	eth = eth_hdr(skb);
 
 	if (*eth->h_dest & 1) {
 		if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
@@ -3834,6 +3835,7 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
 				/* return EBUSY because we sent old packet, not
 				 * the current one */
 				rc = -EBUSY;
+				atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
 				goto out;
 			}
 		}
@@ -4372,12 +4374,13 @@ qeth_snmp_command(struct qeth_card *card, char *udata)
 	/* skip 4 bytes (data_len struct member) to get req_len */
 	if (copy_from_user(&req_len, udata + sizeof(int), sizeof(int)))
 		return -EFAULT;
-	ureq = kmalloc(req_len, GFP_KERNEL);
+	ureq = kmalloc(req_len+sizeof(struct qeth_snmp_ureq_hdr), GFP_KERNEL);
 	if (!ureq) {
 		QETH_DBF_TEXT(trace, 2, "snmpnome");
 		return -ENOMEM;
 	}
-	if (copy_from_user(ureq, udata, req_len)){
+	if (copy_from_user(ureq, udata,
+			req_len+sizeof(struct qeth_snmp_ureq_hdr))){
 		kfree(ureq);
 		return -EFAULT;
 	}
@@ -4546,7 +4549,8 @@ qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	if (!card)
 		return -ENODEV;
 
-	if (card->state != CARD_STATE_UP)
+	if ((card->state != CARD_STATE_UP) &&
+            (card->state != CARD_STATE_SOFTSETUP))
 		return -ENODEV;
 
 	switch (cmd){
@@ -4733,9 +4737,10 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid)
 	QETH_DBF_TEXT(trace, 4, "frvaddr4");
 	if (!card->vlangrp)
 		return;
-	in_dev = in_dev_get(card->vlangrp->vlan_devices[vid]);
+	rcu_read_lock();
+	in_dev = __in_dev_get(card->vlangrp->vlan_devices[vid]);
 	if (!in_dev)
-		return;
+		goto out;
 	for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next){
 		addr = qeth_get_addr_buffer(QETH_PROT_IPV4);
 		if (addr){
@@ -4746,7 +4751,8 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid)
 				kfree(addr);
 		}
 	}
-	in_dev_put(in_dev);
+out:
+	rcu_read_unlock();
 }
 
 static void
@@ -4918,9 +4924,9 @@ qeth_add_vlan_mc(struct qeth_card *card)
 		in_dev = in_dev_get(vg->vlan_devices[i]);
 		if (!in_dev)
 			continue;
-		read_lock(&in_dev->lock);
+		read_lock(&in_dev->mc_list_lock);
 		qeth_add_mc(card,in_dev);
-		read_unlock(&in_dev->lock);
+		read_unlock(&in_dev->mc_list_lock);
 		in_dev_put(in_dev);
 	}
 #endif
@@ -4935,10 +4941,10 @@ qeth_add_multicast_ipv4(struct qeth_card *card)
 	in4_dev = in_dev_get(card->dev);
 	if (in4_dev == NULL)
 		return;
-	read_lock(&in4_dev->lock);
+	read_lock(&in4_dev->mc_list_lock);
 	qeth_add_mc(card, in4_dev);
 	qeth_add_vlan_mc(card);
-	read_unlock(&in4_dev->lock);
+	read_unlock(&in4_dev->mc_list_lock);
 	in_dev_put(in4_dev);
 }
 
@@ -5739,7 +5745,7 @@ qeth_start_ipa_ip_fragmentation(struct qeth_card *card)
 	QETH_DBF_TEXT(trace,3,"ipaipfrg");
 
 	if (!qeth_is_supported(card, IPA_IP_FRAGMENTATION)) {
-		PRINT_INFO("IP fragmentation not supported on %s\n",
+		PRINT_INFO("Hardware IP fragmentation not supported on %s\n",
 			   card->info.if_name);
 		return  -EOPNOTSUPP;
 	}
@@ -5747,11 +5753,11 @@ qeth_start_ipa_ip_fragmentation(struct qeth_card *card)
 	rc = qeth_send_simple_setassparms(card, IPA_IP_FRAGMENTATION,
 					  IPA_CMD_ASS_START, 0);
 	if (rc) {
-		PRINT_WARN("Could not start IP fragmentation "
+		PRINT_WARN("Could not start Hardware IP fragmentation "
 			   "assist on %s: 0x%x\n",
 			   card->info.if_name, rc);
 	} else
-		PRINT_INFO("IP fragmentation enabled \n");
+		PRINT_INFO("Hardware IP fragmentation enabled \n");
 	return rc;
 }
 
@@ -6706,19 +6712,26 @@ static int
 qeth_arp_constructor(struct neighbour *neigh)
 {
 	struct net_device *dev = neigh->dev;
-	struct in_device *in_dev = in_dev_get(dev);
+	struct in_device *in_dev;
+	struct neigh_parms *parms;
 
-	if (in_dev == NULL)
-		return -EINVAL;
 	if (!qeth_verify_dev(dev)) {
-		in_dev_put(in_dev);
 		return qeth_old_arp_constructor(neigh);
 	}
 
+	rcu_read_lock();
+	in_dev = rcu_dereference(__in_dev_get(dev));
+	if (in_dev == NULL) {
+		rcu_read_unlock();
+		return -EINVAL;
+	}
+
+	parms = in_dev->arp_parms;
+	__neigh_parms_put(neigh->parms);
+	neigh->parms = neigh_parms_clone(parms);
+	rcu_read_unlock();
+
 	neigh->type = inet_addr_type(*(u32 *) neigh->primary_key);
-	if (in_dev->arp_parms)
-		neigh->parms = in_dev->arp_parms;
-	in_dev_put(in_dev);
 	neigh->nud_state = NUD_NOARP;
 	neigh->ops = arp_direct_ops;
 	neigh->output = neigh->ops->queue_xmit;
diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h
index 167043492..7e26f0f1b 100644
--- a/drivers/s390/s390mach.h
+++ b/drivers/s390/s390mach.h
@@ -63,10 +63,6 @@ struct crw {
 #define CRW_ERC_PERRI    0x07 /* perm. error, facility init */
 #define CRW_ERC_PMOD     0x08 /* installed parameters modified */
 
-#define MCHCHK_STATUS_TO_PROCESS    0x00000001
-#define MCHCHK_STATUS_IN_PROGRESS   0x00000002
-#define MCHCHK_STATUS_WAITING       0x00000004
-
 extern __inline__ int stcrw(struct crw *pcrw )
 {
         int ccode;
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index dad02890e..88414579d 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -29,7 +29,7 @@
  */
 
 /* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_AUX_REVISION "$Revision: 1.115 $"
+#define ZFCP_AUX_REVISION "$Revision: 1.129 $"
 
 #include "zfcp_ext.h"
 
@@ -47,11 +47,11 @@ static void zfcp_ns_gid_pn_handler(unsigned long);
 /* miscellaneous */
 
 static inline int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t);
-static inline int zfcp_sg_list_free(struct zfcp_sg_list *);
-static inline int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *, void *,
-					      size_t);
-static inline int zfcp_sg_list_copy_to_user(void *, struct zfcp_sg_list *,
-					    size_t);
+static inline void zfcp_sg_list_free(struct zfcp_sg_list *);
+static inline int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *,
+					      void __user *, size_t);
+static inline int zfcp_sg_list_copy_to_user(void __user *,
+					    struct zfcp_sg_list *, size_t);
 
 static int zfcp_cfdc_dev_ioctl(struct inode *, struct file *,
 	unsigned int, unsigned long);
@@ -95,7 +95,7 @@ MODULE_PARM_DESC(device, "specify initial device");
 module_param(loglevel, uint, 0);
 MODULE_PARM_DESC(loglevel,
 		 "log levels, 8 nibbles: "
-		 "(unassigned) ERP QDIO DIO Config FSF SCSI Other, "
+		 "FC ERP QDIO CIO Config FSF SCSI Other, "
 		 "levels: 0=none 1=normal 2=devel 3=trace");
 
 #ifdef ZFCP_PRINT_FLAGS
@@ -257,24 +257,20 @@ zfcp_device_setup(char *str)
 static void __init
 zfcp_init_device_configure(void)
 {
-	int found = 0;
 	struct zfcp_adapter *adapter;
 	struct zfcp_port *port;
 	struct zfcp_unit *unit;
 
 	down(&zfcp_data.config_sema);
 	read_lock_irq(&zfcp_data.config_lock);
-	list_for_each_entry(adapter, &zfcp_data.adapter_list_head, list)
-		if (strcmp(zfcp_data.init_busid,
-			   zfcp_get_busid_by_adapter(adapter)) == 0) {
-			zfcp_adapter_get(adapter);
-			found = 1;
-			break;
-		}
+	adapter = zfcp_get_adapter_by_busid(zfcp_data.init_busid);
+	if (adapter)
+		zfcp_adapter_get(adapter);
 	read_unlock_irq(&zfcp_data.config_lock);
-	if (!found)
+
+	if (adapter == NULL)
 		goto out_adapter;
-	port = zfcp_port_enqueue(adapter, zfcp_data.init_wwpn, 0);
+	port = zfcp_port_enqueue(adapter, zfcp_data.init_wwpn, 0, 0);
 	if (!port)
 		goto out_port;
 	unit = zfcp_unit_enqueue(port, zfcp_data.init_fcp_lun);
@@ -377,12 +373,13 @@ zfcp_module_init(void)
  *              -ENOMEM     - Insufficient memory
  *              -EFAULT     - User space memory I/O operation fault
  *              -EPERM      - Cannot create or queue FSF request or create SBALs
+ *              -ERESTARTSYS- Received signal (is mapped to EAGAIN by VFS)
  */
 static int
 zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file,
                     unsigned int command, unsigned long buffer)
 {
-	struct zfcp_cfdc_sense_data sense_data, *sense_data_user;
+	struct zfcp_cfdc_sense_data sense_data, __user *sense_data_user;
 	struct zfcp_adapter *adapter = NULL;
 	struct zfcp_fsf_req *fsf_req = NULL;
 	struct zfcp_sg_list *sg_list = NULL;
@@ -403,7 +400,7 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file,
 		goto out;
 	}
 
-	if ((sense_data_user = (struct zfcp_cfdc_sense_data*)buffer) == NULL) {
+	if ((sense_data_user = (void __user *) buffer) == NULL) {
 		ZFCP_LOG_INFO("sense data record is required\n");
 		retval = -EINVAL;
 		goto out;
@@ -467,22 +464,17 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file,
 		(sense_data.devno >> 16) & 0xFF,
 		(sense_data.devno & 0xFFFF));
 
-	retval = -ENXIO;
 	read_lock_irq(&zfcp_data.config_lock);
-	list_for_each_entry(adapter, &zfcp_data.adapter_list_head, list) {
-		if (strncmp(bus_id, zfcp_get_busid_by_adapter(adapter),
-		    BUS_ID_SIZE) == 0) {
-			zfcp_adapter_get(adapter);
-			retval = 0;
-			break;
-		}
-	}
+	adapter = zfcp_get_adapter_by_busid(bus_id);
+	if (adapter)
+		zfcp_adapter_get(adapter);
 	read_unlock_irq(&zfcp_data.config_lock);
 
 	kfree(bus_id);
 
-	if (retval != 0) {
+	if (adapter == NULL) {
 		ZFCP_LOG_INFO("invalid adapter\n");
+		retval = -ENXIO;
 		goto out;
 	}
 
@@ -520,6 +512,12 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file,
 	wait_event(fsf_req->completion_wq,
 	           fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
 
+	if ((fsf_req->qtcb->prefix.prot_status != FSF_PROT_GOOD) &&
+	    (fsf_req->qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) {
+		retval = -ENXIO;
+		goto out;
+	}
+
 	sense_data.fsf_status = fsf_req->qtcb->header.fsf_status;
 	memcpy(&sense_data.fsf_status_qual,
 	       &fsf_req->qtcb->header.fsf_status_qual,
@@ -559,13 +557,16 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file,
 }
 
 
-/*
- * function:    zfcp_sg_list_alloc
- *
- * purpose:     Create a scatter-gather list of the specified size
+/**
+ * zfcp_sg_list_alloc - create a scatter-gather list of the specified size
+ * @sg_list: structure describing a scatter gather list
+ * @size: size of scatter-gather list
+ * Return: 0 on success, else -ENOMEM
  *
- * returns:     0       - Scatter gather list is created
- *              -ENOMEM - Insufficient memory (*list_ptr is then set to NULL)
+ * In sg_list->sg a pointer to the created scatter-gather list is returned,
+ * or NULL if we run out of memory. sg_list->count specifies the number of
+ * elements of the scatter-gather list. The maximum size of a single element
+ * in the scatter-gather list is PAGE_SIZE.
  */
 static inline int
 zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size)
@@ -573,6 +574,9 @@ zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size)
 	struct scatterlist *sg;
 	unsigned int i;
 	int retval = 0;
+	void *address;
+
+	BUG_ON(sg_list == NULL);
 
 	sg_list->count = size >> PAGE_SHIFT;
 	if (size & ~PAGE_MASK)
@@ -588,7 +592,8 @@ zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size)
 	for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++) {
 		sg->length = min(size, PAGE_SIZE);
 		sg->offset = 0;
-		sg->page = alloc_pages(GFP_KERNEL, 0);
+		address = (void *) get_zeroed_page(GFP_KERNEL);
+		zfcp_address_to_sg(address, sg);
 		if (sg->page == NULL) {
 			sg_list->count = i;
 			zfcp_sg_list_free(sg_list);
@@ -603,41 +608,61 @@ zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size)
 }
 
 
-/*
- * function:    zfcp_sg_list_free
- *
- * purpose:     Destroy a scatter-gather list and release memory
+/**
+ * zfcp_sg_list_free - free memory of a scatter-gather list
+ * @sg_list: structure describing a scatter-gather list
  *
- * returns:     Always 0
+ * Memory for each element in the scatter-gather list is freed.
+ * Finally sg_list->sg is freed itself and sg_list->count is reset.
  */
-static inline int
+static inline void
 zfcp_sg_list_free(struct zfcp_sg_list *sg_list)
 {
 	struct scatterlist *sg;
 	unsigned int i;
-	int retval = 0;
 
 	BUG_ON(sg_list == NULL);
 
 	for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++)
 		__free_pages(sg->page, 0);
 
+	sg_list->count = 0;
 	kfree(sg_list->sg);
+}
 
-	return retval;
+/**
+ * zfcp_sg_size - determine size of a scatter-gather list
+ * @sg: array of (struct scatterlist)
+ * @sg_count: elements in array
+ * Return: size of entire scatter-gather list
+ */
+size_t
+zfcp_sg_size(struct scatterlist *sg, unsigned int sg_count)
+{
+	unsigned int i;
+	struct scatterlist *p;
+	size_t size;
+
+	size = 0;
+	for (i = 0, p = sg; i < sg_count; i++, p++) {
+		BUG_ON(p == NULL);
+		size += p->length;
+	}
+
+	return size;
 }
 
 
-/*
- * function:    zfcp_sg_list_copy_from_user
- *
- * purpose:     Copy data from user space memory to the scatter-gather list
- *
- * returns:     0       - The data has been copied from user
- *              -EFAULT - Memory I/O operation fault
+/**
+ * zfcp_sg_list_copy_from_user -copy data from user space to scatter-gather list
+ * @sg_list: structure describing a scatter-gather list
+ * @user_buffer: pointer to buffer in user space
+ * @size: number of bytes to be copied
+ * Return: 0 on success, -EFAULT if copy_from_user fails.
  */
 static inline int
-zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list, void *user_buffer,
+zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list,
+			    void __user *user_buffer,
                             size_t size)
 {
 	struct scatterlist *sg;
@@ -645,10 +670,14 @@ zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list, void *user_buffer,
 	void *zfcp_buffer;
 	int retval = 0;
 
+	BUG_ON(sg_list == NULL);
+
+	if (zfcp_sg_size(sg_list->sg, sg_list->count) < size)
+		return -EFAULT;
+
 	for (sg = sg_list->sg; size > 0; sg++) {
 		length = min((unsigned int)size, sg->length);
-		zfcp_buffer = (void*)
-			((page_to_pfn(sg->page) << PAGE_SHIFT) + sg->offset);
+		zfcp_buffer = zfcp_sg_to_address(sg);
 		if (copy_from_user(zfcp_buffer, user_buffer, length)) {
 			retval = -EFAULT;
 			goto out;
@@ -662,16 +691,16 @@ zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list, void *user_buffer,
 }
 
 
-/*
- * function:    zfcp_sg_list_copy_to_user
- *
- * purpose:     Copy data from the scatter-gather list to user space memory
- *
- * returns:     0       - The data has been copied to user
- *              -EFAULT - Memory I/O operation fault
+/**
+ * zfcp_sg_list_copy_to_user - copy data from scatter-gather list to user space
+ * @user_buffer: pointer to buffer in user space
+ * @sg_list: structure describing a scatter-gather list
+ * @size: number of bytes to be copied
+ * Return: 0 on success, -EFAULT if copy_to_user fails
  */
 static inline int
-zfcp_sg_list_copy_to_user(void *user_buffer, struct zfcp_sg_list *sg_list,
+zfcp_sg_list_copy_to_user(void __user  *user_buffer,
+			  struct zfcp_sg_list *sg_list,
                           size_t size)
 {
 	struct scatterlist *sg;
@@ -679,10 +708,14 @@ zfcp_sg_list_copy_to_user(void *user_buffer, struct zfcp_sg_list *sg_list,
 	void *zfcp_buffer;
 	int retval = 0;
 
+	BUG_ON(sg_list == NULL);
+
+	if (zfcp_sg_size(sg_list->sg, sg_list->count) < size)
+		return -EFAULT;
+
 	for (sg = sg_list->sg; size > 0; sg++) {
-		length = min((unsigned int)size, sg->length);
-		zfcp_buffer = (void*)
-			((page_to_pfn(sg->page) << PAGE_SHIFT) + sg->offset);
+		length = min((unsigned int) size, sg->length);
+		zfcp_buffer = zfcp_sg_to_address(sg);
 		if (copy_to_user(user_buffer, zfcp_buffer, length)) {
 			retval = -EFAULT;
 			goto out;
@@ -705,13 +738,12 @@ zfcp_sg_list_copy_to_user(void *user_buffer, struct zfcp_sg_list *sg_list,
 #define ZFCP_LOG_AREA			ZFCP_LOG_AREA_CONFIG
 
 /**
- * zfcp_get_unit_by_lun - find unit in unit list of port by fcp lun
+ * zfcp_get_unit_by_lun - find unit in unit list of port by FCP LUN
  * @port: pointer to port to search for unit
- * @fcp_lun: lun to search for
- * Traverses list of all units of a port and returns pointer to a unit
- * if lun of a unit matches.
+ * @fcp_lun: FCP LUN to search for
+ * Traverse list of all units of a port and return pointer to a unit
+ * with the given FCP LUN.
  */
-
 struct zfcp_unit *
 zfcp_get_unit_by_lun(struct zfcp_port *port, fcp_lun_t fcp_lun)
 {
@@ -730,13 +762,12 @@ zfcp_get_unit_by_lun(struct zfcp_port *port, fcp_lun_t fcp_lun)
 }
 
 /**
- * zfcp_get_port_by_wwpn - find unit in unit list of port by fcp lun
+ * zfcp_get_port_by_wwpn - find port in port list of adapter by wwpn
  * @adapter: pointer to adapter to search for port
  * @wwpn: wwpn to search for
- * Traverses list of all ports of an adapter and returns a pointer to a port
- * if wwpn of a port matches.
+ * Traverse list of all ports of an adapter and return pointer to a port
+ * with the given wwpn.
  */
-
 struct zfcp_port *
 zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter, wwn_t wwpn)
 {
@@ -745,6 +776,30 @@ zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter, wwn_t wwpn)
 
 	list_for_each_entry(port, &adapter->port_list_head, list) {
 		if ((port->wwpn == wwpn) &&
+		    !(atomic_read(&port->status) &
+		      (ZFCP_STATUS_PORT_NO_WWPN | ZFCP_STATUS_COMMON_REMOVE))) {
+			found = 1;
+			break;
+		}
+	}
+	return found ? port : NULL;
+}
+
+/**
+ * zfcp_get_port_by_did - find port in port list of adapter by d_id
+ * @adapter: pointer to adapter to search for port
+ * @d_id: d_id to search for
+ * Traverse list of all ports of an adapter and return pointer to a port
+ * with the given d_id.
+ */
+struct zfcp_port *
+zfcp_get_port_by_did(struct zfcp_adapter *adapter, u32 d_id)
+{
+	struct zfcp_port *port;
+	int found = 0;
+
+	list_for_each_entry(port, &adapter->port_list_head, list) {
+		if ((port->d_id == d_id) &&
 		    !atomic_test_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status))
 		{
 			found = 1;
@@ -754,14 +809,38 @@ zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter, wwn_t wwpn)
 	return found ? port : NULL;
 }
 
-/*
- * Enqueues a logical unit at the end of the unit list associated with the 
- * specified port. Also sets up some unit internal structures.
+/**
+ * zfcp_get_adapter_by_busid - find adpater in adapter list by bus_id
+ * @bus_id: bus_id to search for
+ * Traverse list of all adapters and return pointer to an adapter
+ * with the given bus_id.
+ */
+struct zfcp_adapter *
+zfcp_get_adapter_by_busid(char *bus_id)
+{
+	struct zfcp_adapter *adapter;
+	int found = 0;
+
+	list_for_each_entry(adapter, &zfcp_data.adapter_list_head, list) {
+		if ((strncmp(bus_id, zfcp_get_busid_by_adapter(adapter),
+			     BUS_ID_SIZE) == 0) &&
+		    !atomic_test_mask(ZFCP_STATUS_COMMON_REMOVE,
+				      &adapter->status)){
+			found = 1;
+			break;
+		}
+	}
+	return found ? adapter : NULL;
+}
+
+/**
+ * zfcp_unit_enqueue - enqueue unit to unit list of a port.
+ * @port: pointer to port where unit is added
+ * @fcp_lun: FCP LUN of unit to be enqueued
+ * Return: pointer to enqueued unit on success, NULL on error
+ * Locks: config_sema must be held to serialize changes to the unit list
  *
- * returns:	pointer to unit with a usecount of 1 if a new unit was
- *              successfully enqueued
- *              NULL otherwise
- * locks:	config_sema must be held to serialise changes to the unit list
+ * Sets up some unit internal structures and creates sysfs entry.
  */
 struct zfcp_unit *
 zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
@@ -1022,6 +1101,12 @@ zfcp_adapter_debug_unregister(struct zfcp_adapter *adapter)
 	debug_unregister(adapter->in_els_dbf);
 }
 
+void
+zfcp_dummy_release(struct device *dev)
+{
+	return;
+}
+
 /*
  * Enqueues an adapter at the end of the adapter list in the driver data.
  * All adapter internal structures are set up.
@@ -1113,6 +1198,14 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
 	if (zfcp_sysfs_adapter_create_files(&ccw_device->dev))
 		goto sysfs_failed;
 
+	adapter->generic_services.parent = &adapter->ccw_device->dev;
+	adapter->generic_services.release = zfcp_dummy_release;
+	snprintf(adapter->generic_services.bus_id, BUS_ID_SIZE,
+		 "generic_services");
+
+	if (device_register(&adapter->generic_services))
+		goto generic_services_failed;
+
 	/* put allocated adapter at list tail */
 	write_lock_irq(&zfcp_data.config_lock);
 	atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
@@ -1123,6 +1216,8 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
 
 	goto out;
 
+ generic_services_failed:
+	zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
  sysfs_failed:
 	dev_set_drvdata(&ccw_device->dev, NULL);
  failed_low_mem_buffers:
@@ -1153,6 +1248,7 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
 	int retval = 0;
 	unsigned long flags;
 
+	device_unregister(&adapter->generic_services);
 	zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
 	dev_set_drvdata(&adapter->ccw_device->dev, NULL);
 	/* sanity check: no pending FSF requests */
@@ -1195,15 +1291,22 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
 	return;
 }
 
-/*
- * Enqueues a remote port to the port list. All port internal structures
- * are set up and the sysfs entry is also generated.
+/**
+ * zfcp_port_enqueue - enqueue port to port list of adapter
+ * @adapter: adapter where remote port is added
+ * @wwpn: WWPN of the remote port to be enqueued
+ * @status: initial status for the port
+ * @d_id: destination id of the remote port to be enqueued
+ * Return: pointer to enqueued port on success, NULL on error
+ * Locks: config_sema must be held to serialize changes to the port list
  *
- * returns:     pointer to port or NULL
- * locks:       config_sema must be held to serialise changes to the port list
+ * All port internal structures are set up and the sysfs entry is generated.
+ * d_id is used to enqueue ports with a well known address like the Directory
+ * Service for nameserver lookup.
  */
 struct zfcp_port *
-zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status)
+zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status,
+		  u32 d_id)
 {
 	struct zfcp_port *port, *tmp_port;
 	int check_wwpn;
@@ -1243,12 +1346,39 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status)
 	atomic_set_mask(status, &port->status);
 
 	/* setup for sysfs registration */
-	if (status & ZFCP_STATUS_PORT_NAMESERVER)
-		snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE, "nameserver");
-	else
+	if (status & ZFCP_STATUS_PORT_WKA) {
+		switch (d_id) {
+		case ZFCP_DID_DIRECTORY_SERVICE:
+			snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE,
+				 "directory");
+			break;
+		case ZFCP_DID_MANAGEMENT_SERVICE:
+			snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE,
+				 "management");
+			break;
+		case ZFCP_DID_KEY_DISTRIBUTION_SERVICE:
+			snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE,
+				 "key_distribution");
+			break;
+		case ZFCP_DID_ALIAS_SERVICE:
+			snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE,
+				 "alias");
+			break;
+		case ZFCP_DID_TIME_SERVICE:
+			snprintf(port->sysfs_device.bus_id, BUS_ID_SIZE,
+				 "time");
+			break;
+		default:
+			kfree(port);
+			return NULL;
+		}
+		port->d_id = d_id;
+		port->sysfs_device.parent = &adapter->generic_services;
+	} else {
 		snprintf(port->sysfs_device.bus_id,
 			 BUS_ID_SIZE, "0x%016llx", wwpn);
 	port->sysfs_device.parent = &adapter->ccw_device->dev;
+	}
 	port->sysfs_device.release = zfcp_sysfs_port_release;
 	dev_set_drvdata(&port->sysfs_device, port);
 
@@ -1287,9 +1417,12 @@ zfcp_port_enqueue(struct zfcp_adapter *adapter, wwn_t wwpn, u32 status)
 		list_add_tail(&port->list, &adapter->port_list_head);
 	atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
 	atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status);
+	if (d_id == ZFCP_DID_DIRECTORY_SERVICE)
+		if (!adapter->nameserver_port)
+			adapter->nameserver_port = port;
+	adapter->ports++;
 	write_unlock_irq(&zfcp_data.config_lock);
 
-	adapter->ports++;
 	zfcp_adapter_get(adapter);
 
 	return port;
@@ -1301,8 +1434,8 @@ zfcp_port_dequeue(struct zfcp_port *port)
 	zfcp_port_wait(port);
 	write_lock_irq(&zfcp_data.config_lock);
 	list_del(&port->list);
-	write_unlock_irq(&zfcp_data.config_lock);
 	port->adapter->ports--;
+	write_unlock_irq(&zfcp_data.config_lock);
 	zfcp_adapter_put(port->adapter);
 	zfcp_sysfs_port_remove_files(&port->sysfs_device,
 				     atomic_read(&port->status));
@@ -1315,17 +1448,14 @@ zfcp_nameserver_enqueue(struct zfcp_adapter *adapter)
 {
 	struct zfcp_port *port;
 
-	/* generate port structure */
-	port = zfcp_port_enqueue(adapter, 0, ZFCP_STATUS_PORT_NAMESERVER);
+	port = zfcp_port_enqueue(adapter, 0, ZFCP_STATUS_PORT_WKA,
+				 ZFCP_DID_DIRECTORY_SERVICE);
 	if (!port) {
 		ZFCP_LOG_INFO("error: enqueue of nameserver port for "
 			      "adapter %s failed\n",
 			      zfcp_get_busid_by_adapter(adapter));
 		return -ENXIO;
 	}
-	/* set special D_ID */
-	port->d_id = ZFCP_DID_NAMESERVER;
-	adapter->nameserver_port = port;
 	zfcp_port_put(port);
 
 	return 0;
@@ -1389,7 +1519,7 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
 		read_lock_irqsave(&zfcp_data.config_lock, flags);
 		list_for_each_entry(port, &adapter->port_list_head, list) {
 			if (atomic_test_mask
-			    (ZFCP_STATUS_PORT_NAMESERVER, &port->status))
+			    (ZFCP_STATUS_PORT_WKA, &port->status))
 				continue;
 			/* Do we know this port? If not skip it. */
 			if (!atomic_test_mask
@@ -1646,15 +1776,7 @@ static void zfcp_ns_gid_pn_handler(unsigned long data)
 	ct_iu_req = zfcp_sg_to_address(ct->req);
 	ct_iu_resp = zfcp_sg_to_address(ct->resp);
 
-        if (ct_iu_resp->header.revision != ZFCP_CT_REVISION)
-		goto failed;
-        if (ct_iu_resp->header.gs_type != ZFCP_CT_DIRECTORY_SERVICE)
-		goto failed;
-        if (ct_iu_resp->header.gs_subtype != ZFCP_CT_NAME_SERVER)
-		goto failed;
-        if (ct_iu_resp->header.options != ZFCP_CT_SYNCHRONOUS)
-		goto failed;
-        if (ct_iu_resp->header.cmd_rsp_code != ZFCP_CT_ACCEPT) {
+	if ((ct->status != 0) || zfcp_check_ct_response(&ct_iu_resp->header)) {
 		/* FIXME: do we need some specific erp entry points */
 		atomic_set_mask(ZFCP_STATUS_PORT_INVALID_WWPN, &port->status);
 		goto failed;
@@ -1665,7 +1787,7 @@ static void zfcp_ns_gid_pn_handler(unsigned long data)
 				"lookup does not match expected wwpn 0x%016Lx "
 				"for adapter %s\n", ct_iu_req->wwpn, port->wwpn,
 				zfcp_get_busid_by_port(port));
-		goto failed;
+		goto mismatch;
 	}
 
 	/* looks like a valid d_id */
@@ -1675,19 +1797,185 @@ static void zfcp_ns_gid_pn_handler(unsigned long data)
 		       zfcp_get_busid_by_port(port), port->wwpn, port->d_id);
 	goto out;
 
-failed:
-	ZFCP_LOG_NORMAL("warning: failed gid_pn nameserver request for wwpn "
-			"0x%016Lx for adapter %s\n",
-			port->wwpn, zfcp_get_busid_by_port(port));
+ mismatch:
 	ZFCP_LOG_DEBUG("CT IUs do not match:\n");
 	ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, (char *) ct_iu_req,
 		      sizeof(struct ct_iu_gid_pn_req));
 	ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, (char *) ct_iu_resp,
 		      sizeof(struct ct_iu_gid_pn_resp));
 
+ failed:
+	ZFCP_LOG_NORMAL("warning: failed gid_pn nameserver request for wwpn "
+			"0x%016Lx for adapter %s\n",
+			port->wwpn, zfcp_get_busid_by_port(port));
  out:
         zfcp_gid_pn_buffers_free(gid_pn);
 	return;
 }
 
+/* reject CT_IU reason codes acc. to FC-GS-4 */
+static const struct zfcp_rc_entry zfcp_ct_rc[] = {
+	{0x01, "invalid command code"},
+	{0x02, "invalid version level"},
+	{0x03, "logical error"},
+	{0x04, "invalid CT_IU size"},
+	{0x05, "logical busy"},
+	{0x07, "protocol error"},
+	{0x09, "unable to perform command request"},
+	{0x0b, "command not supported"},
+	{0x0d, "server not available"},
+	{0x0e, "session could not be established"},
+	{0xff, "vendor specific error"},
+	{0, NULL},
+};
+
+/* LS_RJT reason codes acc. to FC-FS */
+static const struct zfcp_rc_entry zfcp_ls_rjt_rc[] = {
+	{0x01, "invalid LS_Command code"},
+	{0x03, "logical error"},
+	{0x05, "logical busy"},
+	{0x07, "protocol error"},
+	{0x09, "unable to perform command request"},
+	{0x0b, "command not supported"},
+	{0x0e, "command already in progress"},
+	{0xff, "vendor specific error"},
+	{0, NULL},
+};
+
+/* reject reason codes according to FC-PH/FC-FS */
+static const struct zfcp_rc_entry zfcp_p_rjt_rc[] = {
+	{0x01, "invalid D_ID"},
+	{0x02, "invalid S_ID"},
+	{0x03, "Nx_Port not available, temporary"},
+	{0x04, "Nx_Port not available, permament"},
+	{0x05, "class not supported"},
+	{0x06, "delimiter usage error"},
+	{0x07, "TYPE not supported"},
+	{0x08, "invalid Link_Control"},
+	{0x09, "invalid R_CTL field"},
+	{0x0a, "invalid F_CTL field"},
+	{0x0b, "invalid OX_ID"},
+	{0x0c, "invalid RX_ID"},
+	{0x0d, "invalid SEQ_ID"},
+	{0x0e, "invalid DF_CTL"},
+	{0x0f, "invalid SEQ_CNT"},
+	{0x10, "invalid parameter field"},
+	{0x11, "exchange error"},
+	{0x12, "protocol error"},
+	{0x13, "incorrect length"},
+	{0x14, "unsupported ACK"},
+	{0x15, "class of service not supported by entity at FFFFFE"},
+	{0x16, "login required"},
+	{0x17, "excessive sequences attempted"},
+	{0x18, "unable to establish exchange"},
+	{0x1a, "fabric path not available"},
+	{0x1b, "invalid VC_ID (class 4)"},
+	{0x1c, "invalid CS_CTL field"},
+	{0x1d, "insufficient resources for VC (class 4)"},
+	{0x1f, "invalid class of service"},
+	{0x20, "preemption request rejected"},
+	{0x21, "preemption not enabled"},
+	{0x22, "multicast error"},
+	{0x23, "multicast error terminate"},
+	{0x24, "process login required"},
+	{0xff, "vendor specific reject"},
+	{0, NULL},
+};
+
+/**
+ * zfcp_rc_description - return description for given reaon code
+ * @code: reason code
+ * @rc_table: table of reason codes and descriptions
+ */
+static inline const char *
+zfcp_rc_description(u8 code, const struct zfcp_rc_entry *rc_table)
+{
+	const char *descr = "unknown reason code";
+
+	do {
+		if (code == rc_table->code) {
+			descr = rc_table->description;
+			break;
+		}
+		rc_table++;
+	} while (rc_table->code && rc_table->description);
+
+	return descr;
+}
+
+/**
+ * zfcp_check_ct_response - evaluate reason code for CT_IU
+ * @rjt: response payload to an CT_IU request
+ * Return: 0 for accept CT_IU, 1 for reject CT_IU or invlid response code
+ */
+int
+zfcp_check_ct_response(struct ct_hdr *rjt)
+{
+	if (rjt->cmd_rsp_code == ZFCP_CT_ACCEPT)
+		return 0;
+
+	if (rjt->cmd_rsp_code != ZFCP_CT_REJECT) {
+		ZFCP_LOG_NORMAL("error: invalid Generic Service command/"
+				"response code (0x%04hx)\n",
+				rjt->cmd_rsp_code);
+		return 1;
+	}
+
+	ZFCP_LOG_INFO("Generic Service command rejected\n");
+	ZFCP_LOG_INFO("%s (0x%02x, 0x%02x, 0x%02x)\n",
+		      zfcp_rc_description(rjt->reason_code, zfcp_ct_rc),
+		      (u32) rjt->reason_code, (u32) rjt->reason_code_expl,
+		      (u32) rjt->vendor_unique);
+
+	return 1;
+}
+
+/**
+ * zfcp_print_els_rjt - print reject parameter and description for ELS reject
+ * @rjt_par: reject parameter acc. to FC-PH/FC-FS
+ * @rc_table: table of reason codes and descriptions
+ */
+static inline void
+zfcp_print_els_rjt(struct zfcp_ls_rjt_par *rjt_par,
+		   const struct zfcp_rc_entry *rc_table)
+{
+	ZFCP_LOG_INFO("%s (%02x %02x %02x %02x)\n",
+		      zfcp_rc_description(rjt_par->reason_code, rc_table),
+		      (u32) rjt_par->action, (u32) rjt_par->reason_code,
+		      (u32) rjt_par->reason_expl, (u32) rjt_par->vendor_unique);
+}
+
+/**
+ * zfcp_fsf_handle_els_rjt - evaluate status qualifier/reason code on ELS reject
+ * @sq: status qualifier word
+ * @rjt_par: reject parameter as described in FC-PH and FC-FS
+ * Return: -EROMTEIO for LS_RJT, -EREMCHG for invalid D_ID, -EIO else
+ */
+int
+zfcp_handle_els_rjt(u32 sq, struct zfcp_ls_rjt_par *rjt_par)
+{
+	int ret = -EIO;
+
+	if (sq == FSF_IOSTAT_NPORT_RJT) {
+		ZFCP_LOG_INFO("ELS rejected (P_RJT)\n");
+		zfcp_print_els_rjt(rjt_par, zfcp_p_rjt_rc);
+		/* invalid d_id */
+		if (rjt_par->reason_code == 0x01)
+			ret = -EREMCHG;
+	} else if (sq == FSF_IOSTAT_FABRIC_RJT) {
+		ZFCP_LOG_INFO("ELS rejected (F_RJT)\n");
+		zfcp_print_els_rjt(rjt_par, zfcp_p_rjt_rc);
+		/* invalid d_id */
+		if (rjt_par->reason_code == 0x01)
+			ret = -EREMCHG;
+	} else if (sq == FSF_IOSTAT_LS_RJT) {
+		ZFCP_LOG_INFO("ELS rejected (LS_RJT)\n");
+		zfcp_print_els_rjt(rjt_par, zfcp_ls_rjt_rc);
+		ret = -EREMOTEIO;
+	} else
+		ZFCP_LOG_INFO("unexpected SQ: 0x%02x\n", sq);
+
+	return ret;
+}
+
 #undef ZFCP_LOG_AREA
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index dda20bf00..22f69d6bf 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -33,7 +33,7 @@
 #define ZFCP_DEF_H
 
 /* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_DEF_REVISION "$Revision: 1.81 $"
+#define ZFCP_DEF_REVISION "$Revision: 1.91 $"
 
 /*************************** INCLUDES *****************************************/
 
@@ -43,6 +43,7 @@
 #include <linux/major.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
+#include <linux/timer.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsi_cmnd.h>
@@ -72,12 +73,22 @@
 /* zfcp version number, it consists of major, minor, and patch-level number */
 #define ZFCP_VERSION		"4.1.3"
 
+/**
+ * zfcp_sg_to_address - determine kernel address from struct scatterlist
+ * @list: struct scatterlist
+ * Return: kernel address
+ */
 static inline void *
 zfcp_sg_to_address(struct scatterlist *list)
 {
 	return (void *) (page_address(list->page) + list->offset);
 }
 
+/**
+ * zfcp_address_to_sg - set up struct scatterlist from kernel address
+ * @address: kernel address
+ * @list: struct scatterlist
+ */
 static inline void
 zfcp_address_to_sg(void *address, struct scatterlist *list)
 {
@@ -146,6 +157,9 @@ typedef u32 scsi_lun_t;
 #define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES	6
 #define ZFCP_EXCHANGE_CONFIG_DATA_SLEEP		50
 
+/* timeout value for "default timer" for fsf requests */
+#define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ);
+
 /*************** FIBRE CHANNEL PROTOCOL SPECIFIC DEFINES ********************/
 
 typedef unsigned long long wwn_t;
@@ -158,7 +172,6 @@ typedef unsigned int       fcp_dl_t;
 
 /* timeout for name-server lookup (in seconds) */
 #define ZFCP_NS_GID_PN_TIMEOUT		10
-#define ZFCP_NS_GA_NXT_TIMEOUT		120
 
 /* largest SCSI command we can process */
 /* FCP-2 (FCP_CMND IU) allows up to (255-3+16) */
@@ -276,33 +289,17 @@ struct fcp_logo {
 #define R_A_TOV				10 /* seconds */
 #define ZFCP_ELS_TIMEOUT		(2 * R_A_TOV)
 
-#define ZFCP_LS_RJT			0x01
-#define ZFCP_LS_ACC			0x02
 #define ZFCP_LS_RTV			0x0E
 #define ZFCP_LS_RLS			0x0F
 #define ZFCP_LS_PDISC			0x50
 #define ZFCP_LS_ADISC			0x52
-#define ZFCP_LS_RSCN			0x61
-#define ZFCP_LS_RNID			0x78
-#define ZFCP_LS_RLIR			0x7A
 #define ZFCP_LS_RTV_E_D_TOV_FLAG	0x04000000
 
-/* LS_ACC Reason Codes */
-#define ZFCP_LS_RJT_INVALID_COMMAND_CODE	0x01
-#define ZFCP_LS_RJT_LOGICAL_ERROR		0x03
-#define ZFCP_LS_RJT_LOGICAL_BUSY		0x05
-#define ZFCP_LS_RJT_PROTOCOL_ERROR		0x07
-#define ZFCP_LS_RJT_UNABLE_TO_PERFORM		0x09
-#define ZFCP_LS_RJT_COMMAND_NOT_SUPPORTED	0x0B
-#define ZFCP_LS_RJT_VENDOR_UNIQUE_ERROR		0xFF
-
-struct zfcp_ls_rjt {
-	u8		code;
-	u8		field[3];
-	u8		reserved;
-	u8	reason_code;
-	u8		reason_expl;
-	u8	vendor_unique;
+struct zfcp_ls_rjt_par {
+	u8 action;
+ 	u8 reason_code;
+ 	u8 reason_expl;
+ 	u8 vendor_unique;
 } __attribute__ ((packed));
 
 struct zfcp_ls_rtv {
@@ -383,45 +380,10 @@ struct zfcp_ls_adisc_acc {
 	fc_id_t		nport_id;
 } __attribute__ ((packed));
 
-struct zfcp_ls_rnid {
-	u8		code;
-	u8		field[3];
-	u8		node_id_format;
-	u8		reserved[3];
-} __attribute__((packed));
-
-/* common identification data */
-struct zfcp_ls_rnid_common_id {
-	u64		n_port_name;
-	u64		node_name;
-} __attribute__((packed));
-
-/* general topology specific identification data */
-struct zfcp_ls_rnid_general_topology_id {
-	u8		vendor_unique[16];
-	u32		associated_type;
-	u32		physical_port_number;
-	u32		nr_attached_nodes;
-	u8		node_management;
-	u8		ip_version;
-	u16		port_number;
-	u8		ip_address[16];
-	u8		reserved[2];
-	u16		vendor_specific;
-} __attribute__((packed));
-
-struct zfcp_ls_rnid_acc {
-	u8		code;
-	u8		field[3];
-	u8		node_id_format;
-	u8		common_id_length;
-	u8		reserved;
-	u8		specific_id_length;
-	struct zfcp_ls_rnid_common_id
-			common_id;
-	struct zfcp_ls_rnid_general_topology_id
-			specific_id;
-} __attribute__((packed));
+struct zfcp_rc_entry {
+	u8 code;
+	const char *description;
+};
 
 /*
  * FC-GS-2 stuff
@@ -431,9 +393,9 @@ struct zfcp_ls_rnid_acc {
 #define ZFCP_CT_NAME_SERVER		0x02
 #define ZFCP_CT_SYNCHRONOUS		0x00
 #define ZFCP_CT_GID_PN			0x0121
-#define ZFCP_CT_GA_NXT			0x0100
 #define ZFCP_CT_MAX_SIZE		0x1020
 #define ZFCP_CT_ACCEPT			0x8002
+#define ZFCP_CT_REJECT			0x8001
 
 /*
  * FC-GS-4 stuff
@@ -530,23 +492,29 @@ struct zfcp_ls_rnid_acc {
 	       __LINE__ , ##args);
 
 #define ZFCP_LOG(level, fmt, args...) \
+do { \
 	if (ZFCP_LOG_CHECK(level)) \
-		_ZFCP_LOG(fmt , ##args)
+		_ZFCP_LOG(fmt, ##args); \
+} while (0)
 	
 #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_NORMAL
 # define ZFCP_LOG_NORMAL(fmt, args...)
 #else
 # define ZFCP_LOG_NORMAL(fmt, args...) \
+do { \
 	if (ZFCP_LOG_CHECK(ZFCP_LOG_LEVEL_NORMAL)) \
-		printk(KERN_ERR ZFCP_NAME": " fmt , ##args);
+		printk(KERN_ERR ZFCP_NAME": " fmt, ##args); \
+} while (0)
 #endif
 
 #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_INFO
 # define ZFCP_LOG_INFO(fmt, args...)
 #else
 # define ZFCP_LOG_INFO(fmt, args...) \
+do { \
 	if (ZFCP_LOG_CHECK(ZFCP_LOG_LEVEL_INFO)) \
-		printk(KERN_ERR ZFCP_NAME": " fmt , ##args);
+		printk(KERN_ERR ZFCP_NAME": " fmt, ##args); \
+} while (0)
 #endif
 
 #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_DEBUG
@@ -568,8 +536,10 @@ struct zfcp_ls_rnid_acc {
 #else
 extern u32 flags_dump;
 # define ZFCP_LOG_FLAGS(level, fmt, args...) \
+do { \
 	if (level <= flags_dump) \
-		_ZFCP_LOG(fmt , ##args)
+		_ZFCP_LOG(fmt, ##args); \
+} while (0)
 #endif
 
 /*************** ADAPTER/PORT/UNIT AND FSF_REQ STATUS FLAGS ******************/
@@ -606,7 +576,12 @@ extern u32 flags_dump;
 		 ZFCP_STATUS_ADAPTER_REGISTERED)
 
 
-#define ZFCP_DID_NAMESERVER			0xFFFFFC
+/* FC-PH/FC-GS well-known address identifiers for generic services */
+#define ZFCP_DID_MANAGEMENT_SERVICE		0xFFFFFA
+#define ZFCP_DID_TIME_SERVICE			0xFFFFFB
+#define ZFCP_DID_DIRECTORY_SERVICE		0xFFFFFC
+#define ZFCP_DID_ALIAS_SERVICE			0xFFFFF8
+#define ZFCP_DID_KEY_DISTRIBUTION_SERVICE	0xFFFFF7
 
 /* remote port status */
 #define ZFCP_STATUS_PORT_PHYS_OPEN		0x00000001
@@ -616,7 +591,8 @@ extern u32 flags_dump;
 #define ZFCP_STATUS_PORT_NO_SCSI_ID		0x00000010
 #define ZFCP_STATUS_PORT_INVALID_WWPN		0x00000020
 
-#define ZFCP_STATUS_PORT_NAMESERVER \
+/* for ports with well known addresses */
+#define ZFCP_STATUS_PORT_WKA \
 		(ZFCP_STATUS_PORT_NO_WWPN | \
 		 ZFCP_STATUS_PORT_NO_SCSI_ID)
 
@@ -789,43 +765,29 @@ struct ct_iu_gid_pn_req {
 	wwn_t wwpn;
 } __attribute__ ((packed));
 
-/* nameserver request CT_IU -- for requests where
- * a port identifier is required */
-struct ct_iu_ga_nxt_req {
-	struct ct_hdr header;
-	fc_id_t d_id;
-} __attribute__ ((packed));
-
 /* FS_ACC IU and data unit for GID_PN nameserver request */
 struct ct_iu_gid_pn_resp {
 	struct ct_hdr header;
 	fc_id_t d_id;
 } __attribute__ ((packed));
 
-/* FS_ACC IU and data unit for GA_NXT nameserver request */
-struct ct_iu_ga_nxt_resp {
-	struct ct_hdr header;
-        u8 port_type;
-        u8 port_id[3];
-        u64 port_wwn;
-        u8 port_symbolic_name_length;
-        u8 port_symbolic_name[255];
-        u64 node_wwn;
-        u8 node_symbolic_name_length;
-        u8 node_symbolic_name[255];
-        u64 initial_process_associator;
-        u8 node_ip[16];
-        u32 cos;
-        u8 fc4_types[32];
-        u8 port_ip[16];
-        u64 fabric_wwn;
-        u8 reserved;
-        u8 hard_address[3];
-} __attribute__ ((packed));
-
 typedef void (*zfcp_send_ct_handler_t)(unsigned long);
 
-/* used to pass parameters to zfcp_send_ct() */
+/**
+ * struct zfcp_send_ct - used to pass parameters to function zfcp_fsf_send_ct
+ * @port: port where the request is sent to
+ * @req: scatter-gather list for request
+ * @resp: scatter-gather list for response
+ * @req_count: number of elements in request scatter-gather list
+ * @resp_count: number of elements in response scatter-gather list
+ * @handler: handler function (called for response to the request)
+ * @handler_data: data passed to handler function
+ * @pool: pointer to memory pool for ct request structure
+ * @timeout: FSF timeout for this request
+ * @timer: timer (e.g. for request initiated by erp)
+ * @completion: completion for synchronization purposes
+ * @status: used to pass error status to calling function
+ */
 struct zfcp_send_ct {
 	struct zfcp_port *port;
 	struct scatterlist *req;
@@ -834,7 +796,7 @@ struct zfcp_send_ct {
 	unsigned int resp_count;
 	zfcp_send_ct_handler_t handler;
 	unsigned long handler_data;
-	mempool_t *pool;		/* mempool for ct not for fsf_req */
+	mempool_t *pool;
 	int timeout;
 	struct timer_list *timer;
 	struct completion *completion;
@@ -851,10 +813,22 @@ struct zfcp_gid_pn_data {
         struct zfcp_port *port;
 };
 
-typedef int (*zfcp_send_els_handler_t)(unsigned long);
-
-/* used to pass parameters to zfcp_send_els() */
-/* ToDo merge send_ct() and send_els() and corresponding structs */
+typedef void (*zfcp_send_els_handler_t)(unsigned long);
+
+/**
+ * struct zfcp_send_els - used to pass parameters to function zfcp_fsf_send_els
+ * @port: port where the request is sent to
+ * @req: scatter-gather list for request
+ * @resp: scatter-gather list for response
+ * @req_count: number of elements in request scatter-gather list
+ * @resp_count: number of elements in response scatter-gather list
+ * @handler: handler function (called for response to the request)
+ * @handler_data: data passed to handler function
+ * @timer: timer (e.g. for request initiated by erp)
+ * @completion: completion for synchronization purposes
+ * @ls_code: hex code of ELS command
+ * @status: used to pass error status to calling function
+ */
 struct zfcp_send_els {
 	struct zfcp_port *port;
 	struct scatterlist *req;
@@ -863,6 +837,7 @@ struct zfcp_send_els {
 	unsigned int resp_count;
 	zfcp_send_els_handler_t handler;
 	unsigned long handler_data;
+	struct timer_list *timer;
 	struct completion *completion;
 	int ls_code;
 	int status;
@@ -892,6 +867,7 @@ union zfcp_req_data {
 	struct zfcp_send_ct *send_ct;
 	struct zfcp_send_els *send_els;
 	struct zfcp_status_read 	  status_read;
+	struct fsf_qtcb_bottom_port *port_data;
 };
 
 struct zfcp_qdio_queue {
@@ -979,6 +955,7 @@ struct zfcp_adapter {
 	rwlock_t                cmd_dbf_lock;
 	struct zfcp_adapter_mempool	pool;      /* Adapter memory pools */
 	struct qdio_initialize  qdio_init_data;    /* for qdio_establish */
+	struct device           generic_services;  /* directory for WKA ports */
 };
 
 /*
@@ -1080,6 +1057,11 @@ struct zfcp_data {
 	fcp_lun_t               init_fcp_lun;
 };
 
+/**
+ * struct zfcp_sg_list - struct describing a scatter-gather list
+ * @sg: pointer to array of (struct scatterlist)
+ * @count: number of elements in scatter-gather list
+ */
 struct zfcp_sg_list {
 	struct scatterlist *sg;
 	unsigned int count;
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index e0766777e..55759e83f 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -31,12 +31,12 @@
 #define ZFCP_LOG_AREA			ZFCP_LOG_AREA_ERP
 
 /* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_ERP_REVISION "$Revision: 1.61 $"
+#define ZFCP_ERP_REVISION "$Revision: 1.65 $"
 
 #include "zfcp_ext.h"
 
 static int zfcp_els(struct zfcp_port *, u8);
-static int zfcp_els_handler(unsigned long);
+static void zfcp_els_handler(unsigned long);
 
 static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int);
 static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *, int);
@@ -126,6 +126,25 @@ static void zfcp_erp_memwait_handler(unsigned long);
 static void zfcp_erp_timeout_handler(unsigned long);
 static inline void zfcp_erp_timeout_init(struct zfcp_erp_action *);
 
+/**
+ * zfcp_fsf_request_timeout_handler - called if a request timed out
+ * @data: pointer to adapter for handler function
+ *
+ * This function needs to be called if requests (ELS, Generic Service,
+ * or SCSI commands) exceed a certain time limit. The assumption is
+ * that after the time limit the adapter get stuck. So we trigger a reopen of
+ * the adapter. This should not be used for error recovery, SCSI abort
+ * commands and SCSI requests from SCSI mid-layer.
+ */
+void
+zfcp_fsf_request_timeout_handler(unsigned long data)
+{
+	struct zfcp_adapter *adapter;
+
+	adapter = (struct zfcp_adapter *) data;
+
+	zfcp_erp_adapter_reopen(adapter, 0);
+}
 
 /*
  * function:	zfcp_fsf_scsi_er_timeout_handler
@@ -324,6 +343,7 @@ zfcp_els(struct zfcp_port *port, u8 ls_code)
 	send_els->completion = NULL;
 
 	req = zfcp_sg_to_address(send_els->req);
+	memset(req, 0, PAGE_SIZE);
 
 	*(u32*)req = 0;
 	*(u8*)req = ls_code;
@@ -412,185 +432,99 @@ out:
 }
 
 
-/*
- * function:    zfcp_els_handler
- *
- * purpose:     Handler for all kind of ELSs
- *
- * returns:     0       - Operation completed successfuly
- *              -ENXIO  - ELS has been rejected
- *              -EPERM  - Port forced reopen failed
+/**
+ * zfcp_els_handler - handler for ELS commands
+ * @data: pointer to struct zfcp_send_els
+ * If ELS failed (LS_RJT or timed out) forced reopen of the port is triggered.
  */
-int
+void
 zfcp_els_handler(unsigned long data)
 {
 	struct zfcp_send_els *send_els = (struct zfcp_send_els*)data;
 	struct zfcp_port *port = send_els->port;
-	struct zfcp_ls_rjt *rjt;
 	struct zfcp_ls_rtv_acc *rtv;
 	struct zfcp_ls_rls_acc *rls;
 	struct zfcp_ls_pdisc_acc *pdisc;
 	struct zfcp_ls_adisc_acc *adisc;
 	void *req, *resp;
-	u8 req_code, resp_code;
-	int retval = 0;
+	u8 req_code;
 
+	/* request rejected or timed out */
 	if (send_els->status != 0) {
 		ZFCP_LOG_NORMAL("ELS request timed out, force physical port "
 				"reopen of port 0x%016Lx on adapter %s\n",
 				port->wwpn, zfcp_get_busid_by_port(port));
 		debug_text_event(port->adapter->erp_dbf, 3, "forcreop");
-		retval = zfcp_erp_port_forced_reopen(port, 0);
-		if (retval != 0) {
+		if (zfcp_erp_port_forced_reopen(port, 0))
 			ZFCP_LOG_NORMAL("reopen of remote port 0x%016Lx "
 					"on adapter %s failed\n", port->wwpn,
 					zfcp_get_busid_by_port(port));
-			retval = -EPERM;
-		}
-		goto skip_fsfstatus;
+		goto out;
 	}
 
-	req = (void*)((page_to_pfn(send_els->req->page) << PAGE_SHIFT) + send_els->req->offset);
-	resp = (void*)((page_to_pfn(send_els->resp->page) << PAGE_SHIFT) + send_els->resp->offset);
+	req = zfcp_sg_to_address(send_els->req);
+	resp = zfcp_sg_to_address(send_els->resp);
 	req_code = *(u8*)req;
-	resp_code = *(u8*)resp;
-
-	switch (resp_code) {
-
-	case ZFCP_LS_RJT:
-		rjt = (struct zfcp_ls_rjt*)resp;
-
-		switch (rjt->reason_code) {
-
-		case ZFCP_LS_RJT_INVALID_COMMAND_CODE:
-			ZFCP_LOG_INFO("invalid LS command code "
-				      "(wwpn=0x%016Lx, command=0x%02x)\n",
-				      port->wwpn, req_code);
-			break;
-
-		case ZFCP_LS_RJT_LOGICAL_ERROR:
-			ZFCP_LOG_INFO("logical error (wwpn=0x%016Lx, "
-				      "reason_expl=0x%02x)\n",
-				      port->wwpn, rjt->reason_expl);
-			break;
-
-		case ZFCP_LS_RJT_LOGICAL_BUSY:
-			ZFCP_LOG_INFO("logical busy (wwpn=0x%016Lx, "
-				      "reason_expl=0x%02x)\n",
-				      port->wwpn, rjt->reason_expl);
-			break;
-
-		case ZFCP_LS_RJT_PROTOCOL_ERROR:
-			ZFCP_LOG_INFO("protocol error (wwpn=0x%016Lx, "
-				      "reason_expl=0x%02x)\n",
-				      port->wwpn, rjt->reason_expl);
-			break;
 
-		case ZFCP_LS_RJT_UNABLE_TO_PERFORM:
-			ZFCP_LOG_INFO("unable to perform command requested "
-				      "(wwpn=0x%016Lx, reason_expl=0x%02x)\n",
-				      port->wwpn, rjt->reason_expl);
-			break;
-
-		case ZFCP_LS_RJT_COMMAND_NOT_SUPPORTED:
-			ZFCP_LOG_INFO("command not supported (wwpn=0x%016Lx, "
-				      "command=0x%02x)\n",
-				      port->wwpn, req_code);
-			break;
+	switch (req_code) {
 
-		case ZFCP_LS_RJT_VENDOR_UNIQUE_ERROR:
-			ZFCP_LOG_INFO("vendor specific error (wwpn=0x%016Lx, "
-				      "vendor_unique=0x%02x)\n",
-				      port->wwpn, rjt->vendor_unique);
-			break;
-
-		default:
-			ZFCP_LOG_NORMAL("ELS rejected by remote port 0x%016Lx "
-					"on adapter %s (reason_code=0x%02x)\n",
-					port->wwpn,
-					zfcp_get_busid_by_port(port),
-					rjt->reason_code);
-		}
-		retval = -ENXIO;
+	case ZFCP_LS_RTV:
+		rtv = (struct zfcp_ls_rtv_acc*)resp;
+		ZFCP_LOG_INFO("RTV response from d_id 0x%08x to s_id "
+			      "0x%08x (R_A_TOV=%ds E_D_TOV=%d%cs)\n",
+			      port->d_id, port->adapter->s_id,
+			      rtv->r_a_tov, rtv->e_d_tov,
+			      rtv->qualifier &
+			      ZFCP_LS_RTV_E_D_TOV_FLAG ? 'n' : 'm');
 		break;
 
-	case ZFCP_LS_ACC:
-		switch (req_code) {
-
-		case ZFCP_LS_RTV:
-			rtv = (struct zfcp_ls_rtv_acc*)resp;
-			ZFCP_LOG_INFO("RTV response from d_id 0x%08x to s_id "
-				      "0x%08x (R_A_TOV=%ds E_D_TOV=%d%cs)\n",
-				      port->d_id, port->adapter->s_id,
-				      rtv->r_a_tov, rtv->e_d_tov,
-				      rtv->qualifier &
-				      ZFCP_LS_RTV_E_D_TOV_FLAG ? 'n' : 'm');
-			break;
-
-		case ZFCP_LS_RLS:
-			rls = (struct zfcp_ls_rls_acc*)resp;
-			ZFCP_LOG_INFO("RLS response from d_id 0x%08x to s_id "
-				      "0x%08x (link_failure_count=%u, "
-				      "loss_of_sync_count=%u, "
-				      "loss_of_signal_count=%u, "
-				      "primitive_sequence_protocol_error=%u, "
-				      "invalid_transmition_word=%u, "
-				      "invalid_crc_count=%u)\n",
-				      port->d_id, port->adapter->s_id,
-				      rls->link_failure_count,
-				      rls->loss_of_sync_count,
-				      rls->loss_of_signal_count,
-				      rls->prim_seq_prot_error,
-				      rls->invalid_transmition_word,
-				      rls->invalid_crc_count);
-			break;
-
-		case ZFCP_LS_PDISC:
-			pdisc = (struct zfcp_ls_pdisc_acc*)resp;
-			ZFCP_LOG_INFO("PDISC response from d_id 0x%08x to s_id "
-				      "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, "
-				      "vendor='%-16s')\n", port->d_id,
-				      port->adapter->s_id, pdisc->wwpn,
-				      pdisc->wwnn, pdisc->vendor_version);
-			break;
+	case ZFCP_LS_RLS:
+		rls = (struct zfcp_ls_rls_acc*)resp;
+		ZFCP_LOG_INFO("RLS response from d_id 0x%08x to s_id "
+			      "0x%08x (link_failure_count=%u, "
+			      "loss_of_sync_count=%u, "
+			      "loss_of_signal_count=%u, "
+			      "primitive_sequence_protocol_error=%u, "
+			      "invalid_transmition_word=%u, "
+			      "invalid_crc_count=%u)\n",
+			      port->d_id, port->adapter->s_id,
+			      rls->link_failure_count,
+			      rls->loss_of_sync_count,
+			      rls->loss_of_signal_count,
+			      rls->prim_seq_prot_error,
+			      rls->invalid_transmition_word,
+			      rls->invalid_crc_count);
+		break;
 
-		case ZFCP_LS_ADISC:
-			adisc = (struct zfcp_ls_adisc_acc*)resp;
-			ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id "
-				      "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, "
-				      "hard_nport_id=0x%08x, "
-				      "nport_id=0x%08x)\n", port->d_id,
-				      port->adapter->s_id, adisc->wwpn,
-				      adisc->wwnn, adisc->hard_nport_id,
-				      adisc->nport_id);
-			/* FIXME: set wwnn in during open port */
-			if (port->wwnn == 0)
-				port->wwnn = adisc->wwnn;
-			break;
-		}
+	case ZFCP_LS_PDISC:
+		pdisc = (struct zfcp_ls_pdisc_acc*)resp;
+		ZFCP_LOG_INFO("PDISC response from d_id 0x%08x to s_id "
+			      "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, "
+			      "vendor='%-16s')\n", port->d_id,
+			      port->adapter->s_id, pdisc->wwpn,
+			      pdisc->wwnn, pdisc->vendor_version);
 		break;
 
-	default:
-		ZFCP_LOG_NORMAL("unknown payload code 0x%02x received for "
-				"request 0x%02x to d_id 0x%08x, reopen needed "
-				"for port 0x%016Lx on adapter %s\n", resp_code,
-				req_code, port->d_id,  port->wwpn,
-				zfcp_get_busid_by_port(port));
-		retval = zfcp_erp_port_forced_reopen(port, 0);
-		if (retval != 0) {
-			ZFCP_LOG_NORMAL("reopen of remote port 0x%016Lx on "
-					"adapter %s failed\n", port->wwpn,
-					zfcp_get_busid_by_port(port));
-			retval = -EPERM;
-		}
+	case ZFCP_LS_ADISC:
+		adisc = (struct zfcp_ls_adisc_acc*)resp;
+		ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id "
+			      "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, "
+			      "hard_nport_id=0x%08x, "
+			      "nport_id=0x%08x)\n", port->d_id,
+			      port->adapter->s_id, adisc->wwpn,
+			      adisc->wwnn, adisc->hard_nport_id,
+			      adisc->nport_id);
+		/* FIXME: set wwnn in during open port */
+		if (port->wwnn == 0)
+			port->wwnn = adisc->wwnn;
+		break;
 	}
 
-skip_fsfstatus:
+ out:
 	__free_pages(send_els->req->page, 0);
 	kfree(send_els->req);
 	kfree(send_els->resp);
-
-	return retval;
+	kfree(send_els);
 }
 
 
@@ -735,14 +669,15 @@ zfcp_erp_port_reopen_internal(struct zfcp_port *port, int clear_mask)
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	Wrappper for zfcp_erp_port_reopen_internal
- *              used to ensure the correct locking
+/**
+ * zfcp_erp_port_reopen - initiate reopen of a remote port
+ * @port: port to be reopened
+ * @clear_mask: specifies flags in port status to be cleared
+ * Return: 0 on success, < 0 on error
  *
- * returns:	0	- initiated action succesfully
- *		<0	- failed to initiate action
+ * This is a wrappper function for zfcp_erp_port_reopen_internal. It ensures
+ * correct locking. An error recovery task is initiated to do the reopen.
+ * To wait for the completion of the reopen zfcp_erp_wait should be used.
  */
 int
 zfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask)
@@ -802,14 +737,15 @@ zfcp_erp_unit_reopen_internal(struct zfcp_unit *unit, int clear_mask)
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	Wrappper for zfcp_erp_unit_reopen_internal
- *              used to ensure the correct locking
+/**
+ * zfcp_erp_unit_reopen - initiate reopen of a unit
+ * @unit: unit to be reopened
+ * @clear_mask: specifies flags in unit status to be cleared
+ * Return: 0 on success, < 0 on error
  *
- * returns:	0	- initiated action succesfully
- *		<0	- failed to initiate action
+ * This is a wrappper for zfcp_erp_unit_reopen_internal. It ensures correct
+ * locking. An error recovery task is initiated to do the reopen.
+ * To wait for the completion of the reopen zfcp_erp_wait should be used.
  */
 int
 zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask)
@@ -1987,12 +1923,10 @@ zfcp_erp_strategy_check_queues(struct zfcp_adapter *adapter)
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
+/**
+ * zfcp_erp_wait - wait for completion of error recovery on an adapter
+ * @adapter: adapter for which to wait for completion of its error recovery
+ * Return: 0
  */
 int
 zfcp_erp_wait(struct zfcp_adapter *adapter)
@@ -2130,7 +2064,7 @@ zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter, int clear_mask)
 	struct zfcp_port *port;
 
 	list_for_each_entry(port, &adapter->port_list_head, list)
-		if (!atomic_test_mask(ZFCP_STATUS_PORT_NAMESERVER, &port->status))
+		if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
 			zfcp_erp_port_reopen_internal(port, clear_mask);
 
 	return retval;
@@ -2725,7 +2659,7 @@ zfcp_erp_port_strategy_open(struct zfcp_erp_action *erp_action)
 {
 	int retval;
 
-	if (atomic_test_mask(ZFCP_STATUS_PORT_NAMESERVER,
+	if (atomic_test_mask(ZFCP_STATUS_PORT_WKA,
 			     &erp_action->port->status))
 		retval = zfcp_erp_port_strategy_open_nameserver(erp_action);
 	else
@@ -2863,10 +2797,10 @@ zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *erp_action)
 
 	case ZFCP_ERP_STEP_PORT_OPENING:
 		if (atomic_test_mask(ZFCP_STATUS_COMMON_OPEN, &port->status)) {
-			ZFCP_LOG_DEBUG("nameserver port is open\n");
+			ZFCP_LOG_DEBUG("WKA port is open\n");
 			retval = ZFCP_ERP_SUCCEEDED;
 		} else {
-			ZFCP_LOG_DEBUG("open failed for nameserver port\n");
+			ZFCP_LOG_DEBUG("open failed for WKA port\n");
 			retval = ZFCP_ERP_FAILED;
 		}
 		/* this is needed anyway (dont care for retval of wakeup) */
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index d99005c01..35c6104ec 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -31,7 +31,7 @@
 #ifndef ZFCP_EXT_H
 #define ZFCP_EXT_H
 /* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_EXT_REVISION "$Revision: 1.51 $"
+#define ZFCP_EXT_REVISION "$Revision: 1.57 $"
 
 #include "zfcp_def.h"
 
@@ -50,15 +50,16 @@ extern void zfcp_sysfs_port_release(struct device *);
 extern void zfcp_sysfs_unit_release(struct device *);
 
 /**************************** CONFIGURATION  *********************************/
-extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *,
-					      fcp_lun_t fcp_lun);
-extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *,
-					       wwn_t wwpn);
+extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, fcp_lun_t);
+extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, wwn_t);
+extern struct zfcp_port *zfcp_get_port_by_did(struct zfcp_adapter *, u32);
+struct zfcp_adapter *zfcp_get_adapter_by_busid(char *);
 extern struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *);
 extern int    zfcp_adapter_debug_register(struct zfcp_adapter *);
 extern void   zfcp_adapter_dequeue(struct zfcp_adapter *);
 extern void   zfcp_adapter_debug_unregister(struct zfcp_adapter *);
-extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, wwn_t, u32);
+extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, wwn_t,
+					   u32, u32);
 extern void   zfcp_port_dequeue(struct zfcp_port *);
 extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, fcp_lun_t);
 extern void   zfcp_unit_dequeue(struct zfcp_unit *);
@@ -94,8 +95,11 @@ extern int  zfcp_fsf_open_unit(struct zfcp_erp_action *);
 extern int  zfcp_fsf_close_unit(struct zfcp_erp_action *);
 
 extern int  zfcp_fsf_exchange_config_data(struct zfcp_erp_action *);
+extern int  zfcp_fsf_exchange_port_data(struct zfcp_adapter *,
+					struct fsf_qtcb_bottom_port *);
 extern int  zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **,
 				  u32, u32, struct zfcp_sg_list *);
+extern void zfcp_fsf_request_timeout_handler(unsigned long);
 extern void zfcp_fsf_scsi_er_timeout_handler(unsigned long);
 extern int  zfcp_fsf_req_dismiss_all(struct zfcp_adapter *);
 extern int  zfcp_fsf_status_read(struct zfcp_adapter *, int);
@@ -108,7 +112,7 @@ extern int  zfcp_fsf_req_wait_and_cleanup(struct zfcp_fsf_req *, int, u32 *);
 extern int  zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *,
 					   struct zfcp_unit *,
 					   struct scsi_cmnd *,
-					   int);
+					   struct timer_list*, int);
 extern int  zfcp_fsf_req_complete(struct zfcp_fsf_req *);
 extern void zfcp_fsf_incoming_els(struct zfcp_fsf_req *);
 extern void zfcp_fsf_req_cleanup(struct zfcp_fsf_req *);
@@ -117,9 +121,11 @@ extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_command_task_management(
 extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(
 	unsigned long, struct zfcp_adapter *, struct zfcp_unit *, int);
 
-/******************************** FCP ****************************************/
+/******************************* FC/FCP **************************************/
 extern int  zfcp_nameserver_enqueue(struct zfcp_adapter *);
 extern int  zfcp_ns_gid_pn_request(struct zfcp_erp_action *);
+extern int  zfcp_check_ct_response(struct ct_hdr *);
+extern int  zfcp_handle_els_rjt(u32, struct zfcp_ls_rjt_par *);
 
 /******************************* SCSI ****************************************/
 extern int  zfcp_adapter_scsi_register(struct zfcp_adapter *);
@@ -132,10 +138,10 @@ extern char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *);
 extern void zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *);
 extern fcp_dl_t zfcp_get_fcp_dl(struct fcp_cmnd_iu *);
 
-extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *unit,
-				   struct scsi_cmnd *scsi_cmnd);
-extern int zfcp_scsi_command_sync(struct zfcp_unit *unit,
-				  struct scsi_cmnd *scsi_cmnd);
+extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *,
+				   struct scsi_cmnd *, struct timer_list *);
+extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *,
+				  struct timer_list *);
 extern struct scsi_transport_template *zfcp_transport_template;
 extern struct fc_function_template zfcp_transport_functions;
 
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 79451af65..44c646cca 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -29,11 +29,12 @@
  */
 
 /* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_FSF_C_REVISION "$Revision: 1.55 $"
+#define ZFCP_FSF_C_REVISION "$Revision: 1.65 $"
 
 #include "zfcp_ext.h"
 
 static int zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *);
+static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *);
 static int zfcp_fsf_open_port_handler(struct zfcp_fsf_req *);
 static int zfcp_fsf_close_port_handler(struct zfcp_fsf_req *);
 static int zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *);
@@ -48,7 +49,7 @@ static int zfcp_fsf_status_read_handler(struct zfcp_fsf_req *);
 static int zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *);
 static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *);
 static int zfcp_fsf_control_file_handler(struct zfcp_fsf_req *);
-static inline int zfcp_fsf_req_create_sbal_check(
+static inline int zfcp_fsf_req_sbal_check(
 	unsigned long *, struct zfcp_qdio_queue *, int);
 static inline int zfcp_use_one_sbal(
 	struct scatterlist *, int, struct scatterlist *, int);
@@ -79,10 +80,9 @@ static u32 fsf_qtcb_type[] = {
 };
 
 static const char zfcp_act_subtable_type[5][8] = {
-	{"unknown"}, {"OS"}, {"WWPN"}, {"DID"}, {"LUN"}
+	"unknown", "OS", "WWPN", "DID", "LUN"
 };
 
-
 /****************************************************************/
 /*************** FSF related Functions  *************************/
 /****************************************************************/
@@ -684,13 +684,11 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req)
 		break;
 	case FSF_SQ_ULP_PROGRAMMING_ERROR:
 		ZFCP_LOG_FLAGS(0, "FSF_SQ_ULP_PROGRAMMING_ERROR\n");
-		ZFCP_LOG_NORMAL("bug: An illegal amount of data was attempted "
-				"to be sent to the adapter %s "
-				"Stopping all operations on this adapter. ",
+		ZFCP_LOG_NORMAL("error: not enough SBALs for data transfer "
+				"(adapter %s)\n",
 				zfcp_get_busid_by_adapter(fsf_req->adapter));
 		debug_text_exception(fsf_req->adapter->erp_dbf, 0,
 				     "fsf_sq_ulp_err");
-		zfcp_erp_adapter_shutdown(fsf_req->adapter, 0);
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
@@ -785,6 +783,11 @@ zfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req)
 		zfcp_fsf_exchange_config_data_handler(fsf_req);
 		break;
 
+	case FSF_QTCB_EXCHANGE_PORT_DATA :
+		ZFCP_LOG_FLAGS(2, "FSF_QTCB_EXCHANGE_PORT_DATA\n");
+		zfcp_fsf_exchange_port_data_handler(fsf_req);
+		break;
+
 	case FSF_QTCB_SEND_ELS :
 		ZFCP_LOG_FLAGS(2, "FSF_QTCB_SEND_ELS\n");
 		zfcp_fsf_send_els_handler(fsf_req);
@@ -1624,26 +1627,6 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 
-	case FSF_REQUEST_BUF_NOT_VALID :
-		ZFCP_LOG_FLAGS(2, "FSF_REQUEST_BUF_NOT_VALID\n");
-		ZFCP_LOG_NORMAL("error: The port 0x%016Lx on adapter %s has "
-				"rejected a generic services command "
-				"due to invalid request buffer.\n",
-				port->wwpn, zfcp_get_busid_by_port(port));
-		debug_text_event(adapter->erp_dbf, 1, "fsf_s_reqiv");
-		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-
-	case FSF_RESPONSE_BUF_NOT_VALID :
-		ZFCP_LOG_FLAGS(2, "FSF_RESPONSE_BUF_NOT_VALID\n");
-		ZFCP_LOG_NORMAL("error: The port 0x%016Lx on adapter %s has "
-				"rejected a generic services command "
-				"due to invalid response buffer.\n",
-				port->wwpn, zfcp_get_busid_by_port(port));
-		debug_text_event(adapter->erp_dbf, 1, "fsf_s_resiv");
-		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-
         case FSF_PORT_BOXED :
 		ZFCP_LOG_FLAGS(2, "FSF_PORT_BOXED\n");
 		ZFCP_LOG_INFO("The remote port 0x%016Lx on adapter %s "
@@ -1665,9 +1648,10 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
 	}
 
 skip_fsfstatus:
-	if (send_ct->handler != NULL) {
+	send_ct->status = retval;
+
+	if (send_ct->handler != NULL)
 		send_ct->handler(send_ct->handler_data);
-        }
 
 	return retval;
 }
@@ -1769,7 +1753,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
 	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
 
 	/* start QDIO request for this FSF request */
-	ret = zfcp_fsf_req_send(fsf_req, NULL);
+	ret = zfcp_fsf_req_send(fsf_req, els->timer);
 	if (ret) {
 		ZFCP_LOG_DEBUG("error: initiation of ELS request failed "
 			       "(adapter %s, port 0x%016Lx)\n",
@@ -1863,6 +1847,10 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
 			/* ERP strategy will escalate */
 			debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp");
 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+			retval =
+			  zfcp_handle_els_rjt(header->fsf_status_qual.word[1],
+					      (struct zfcp_ls_rjt_par *)
+					      &header->fsf_status_qual.word[2]);
 			break;
 		case FSF_SQ_RETRY_IF_POSSIBLE:
 			ZFCP_LOG_FLAGS(2, "FSF_SQ_RETRY_IF_POSSIBLE\n");
@@ -1921,15 +1909,6 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
 			bottom->resp_buf_length);
 		break;
 
-	case FSF_UNKNOWN_COMMAND:
-		ZFCP_LOG_FLAGS(2, "FSF_UNKNOWN_COMMAND\n");
-		ZFCP_LOG_INFO(
-			"FSF command 0x%x is not supported by FCP adapter "
-			"(adapter: %s)\n", fsf_req->fsf_command,
-			zfcp_get_busid_by_port(port));
-		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-
 	case FSF_ACCESS_DENIED:
 		ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
 		ZFCP_LOG_NORMAL("Access denied, cannot send ELS "
@@ -1971,8 +1950,6 @@ skip_fsfstatus:
 	if (send_els->handler != 0)
 		send_els->handler(send_els->handler_data);
 
-	kfree(send_els);
-
 	return retval;
 }
 
@@ -2219,6 +2196,111 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
 	return 0;
 }
 
+/**
+ * zfcp_fsf_exchange_port_data - request information about local port
+ * @adapter: for which port data is requested
+ * @data: response to exchange port data request
+ */
+int
+zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter,
+			    struct fsf_qtcb_bottom_port *data)
+{
+	volatile struct qdio_buffer_element *sbale;
+	int retval = 0;
+	unsigned long lock_flags;
+        struct zfcp_fsf_req *fsf_req;
+	struct timer_list *timer;
+
+        if(!(adapter->supported_features & FSF_FEATURE_HBAAPI_MANAGEMENT)){
+		ZFCP_LOG_INFO("error: exchange port data "
+                              "command not supported by adapter %s\n",
+			      zfcp_get_busid_by_adapter(adapter));
+                return -EOPNOTSUPP;
+        }
+
+	timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
+	if (!timer)
+		return -ENOMEM;
+
+	/* setup new FSF request */
+	retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA,
+                                     0, 0, &lock_flags, &fsf_req);
+	if (retval < 0) {
+		ZFCP_LOG_INFO("error: Out of resources. Could not create an "
+                              "exchange port data request for"
+                              "the adapter %s.\n",
+			      zfcp_get_busid_by_adapter(adapter));
+		write_unlock_irqrestore(&adapter->request_queue.queue_lock,
+					lock_flags);
+		goto out;
+	}
+
+	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
+        sbale[0].flags |= SBAL_FLAGS0_TYPE_READ;
+        sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY;
+
+        fsf_req->data.port_data = data;
+
+	init_timer(timer);
+	timer->function = zfcp_fsf_request_timeout_handler;
+	timer->data = (unsigned long) adapter;
+	timer->expires = ZFCP_FSF_REQUEST_TIMEOUT;
+
+	retval = zfcp_fsf_req_send(fsf_req, timer);
+	if (retval) {
+		ZFCP_LOG_INFO("error: Could not send an exchange port data "
+                              "command on the adapter %s\n",
+			      zfcp_get_busid_by_adapter(adapter));
+		zfcp_fsf_req_free(fsf_req);
+		write_unlock_irqrestore(&adapter->request_queue.queue_lock,
+					lock_flags);
+		goto out;
+	}
+
+	ZFCP_LOG_DEBUG("Exchange Port Data request initiated (adapter %s)\n",
+		       zfcp_get_busid_by_adapter(adapter));
+
+	write_unlock_irqrestore(&adapter->request_queue.queue_lock,
+				lock_flags);
+
+	wait_event(fsf_req->completion_wq,
+		   fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
+	del_timer_sync(timer);
+	zfcp_fsf_req_cleanup(fsf_req);
+ out:
+	kfree(timer);
+	return retval;
+}
+
+
+/**
+ * zfcp_fsf_exchange_port_data_handler - handler for exchange_port_data request
+ * @fsf_req: pointer to struct zfcp_fsf_req
+ */
+static void
+zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req)
+{
+	struct fsf_qtcb_bottom_port *bottom;
+	struct fsf_qtcb_bottom_port *data = fsf_req->data.port_data;
+
+	if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
+		return;
+
+	switch (fsf_req->qtcb->header.fsf_status) {
+        case FSF_GOOD :
+                ZFCP_LOG_FLAGS(2,"FSF_GOOD\n");
+                bottom = &fsf_req->qtcb->bottom.port;
+                memcpy(data, bottom, sizeof(*data));
+                break;
+
+        default:
+		debug_text_event(fsf_req->adapter->erp_dbf, 0, "xchg-port-ng");
+                debug_event(fsf_req->adapter->erp_dbf, 0,
+			    &fsf_req->qtcb->header.fsf_status, sizeof(u32));
+	}
+}
+
+
 /*
  * function:    zfcp_fsf_open_port
  *
@@ -3319,19 +3401,19 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
 	return retval;
 }
 
-/*
- * function:    zfcp_fsf_send_fcp_command_task
- *
- * purpose:
- *
- * returns:
- *
- * note: we do not employ linked commands (not supported by HBA anyway)
+/**
+ * zfcp_fsf_send_fcp_command_task - initiate an FCP command (for a SCSI command)
+ * @adapter: adapter where scsi command is issued
+ * @unit: unit where command is sent to
+ * @scsi_cmnd: scsi command to be sent
+ * @timer: timer to be started when request is initiated
+ * @req_flags: flags for fsf_request
  */
 int
 zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
 			       struct zfcp_unit *unit,
-			       struct scsi_cmnd * scsi_cmnd, int req_flags)
+			       struct scsi_cmnd * scsi_cmnd,
+			       struct timer_list *timer, int req_flags)
 {
 	struct zfcp_fsf_req *fsf_req = NULL;
 	struct fcp_cmnd_iu *fcp_cmnd_iu;
@@ -3486,7 +3568,7 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
 	 * start QDIO request for this FSF request
 	 *  covered by an SBALE)
 	 */
-	retval = zfcp_fsf_req_send(fsf_req, NULL);
+	retval = zfcp_fsf_req_send(fsf_req, timer);
 	if (unlikely(retval < 0)) {
 		ZFCP_LOG_INFO("error: Could not send FCP command request "
 			      "on adapter %s, port 0x%016Lx, unit 0x%016Lx\n",
@@ -3788,44 +3870,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 
-		/* FIXME: this should be obsolete, isn' it? */
-	case FSF_INBOUND_DATA_LENGTH_NOT_VALID:
-		ZFCP_LOG_FLAGS(0, "FSF_INBOUND_DATA_LENGTH_NOT_VALID\n");
-		ZFCP_LOG_NORMAL("bug: An invalid inbound data length field "
-				"was found in a command for unit 0x%016Lx "
-				"on port 0x%016Lx on adapter %s.\n",
-				unit->fcp_lun,
-				unit->port->wwpn, zfcp_get_busid_by_unit(unit));
-		/* stop operation for this adapter */
-		debug_text_event(fsf_req->adapter->erp_dbf, 0,
-				 "fsf_s_in_dl_nv");
-		zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
-		zfcp_cmd_dbf_event_fsf("idleninv",
-				       fsf_req,
-				       &header->fsf_status_qual,
-				       sizeof (union fsf_status_qual));
-		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-
-		/* FIXME: this should be obsolete, isn' it? */
-	case FSF_OUTBOUND_DATA_LENGTH_NOT_VALID:
-		ZFCP_LOG_FLAGS(0, "FSF_OUTBOUND_DATA_LENGTH_NOT_VALID\n");
-		ZFCP_LOG_NORMAL("bug: An invalid outbound data length field "
-				"was found in a command unit 0x%016Lx on port "
-				"0x%016Lx on adapter %s\n",
-				unit->fcp_lun,
-				unit->port->wwpn,
-				zfcp_get_busid_by_unit(unit));
-		/* stop operation for this adapter */
-		debug_text_event(fsf_req->adapter->erp_dbf, 0,
-				 "fsf_s_out_dl_nv");
-		zfcp_erp_adapter_shutdown(unit->port->adapter, 0);
-		zfcp_cmd_dbf_event_fsf("odleninv", fsf_req,
-				       &header->fsf_status_qual,
-				       sizeof (union fsf_status_qual));
-		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		break;
-
 	case FSF_CMND_LENGTH_NOT_VALID:
 		ZFCP_LOG_FLAGS(0, "FSF_CMND_LENGTH_NOT_VALID\n");
 		ZFCP_LOG_NORMAL
@@ -4157,87 +4201,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
 	}
 
  skip_fsfstatus:
-#if 0
-	/*
-	 * This nasty chop at the problem is not working anymore
-	 * as we do not adjust the retry count anylonger in order
-	 * to have a number of retries that avoids I/O errors.
-	 * The manipulation of the retry count has been removed
-	 * in favour of a safe tape device handling. We must not
-	 * sent SCSI commands more than once to a device if no
-	 * retries are permitted by the high level driver. Generally
-	 * speaking, it was a mess to change retry counts. So it is
-	 * fine that this sort of workaround is gone.
-	 * Then, we had to face a certain number of immediate retries in case of
-	 * busy and queue full conditions (see below).
-	 * This is not acceptable
-	 * for the latter. Queue full conditions are used
-	 * by devices to indicate to a host that the host can rely
-	 * on the completion (or timeout) of at least one outstanding
-	 * command as a suggested trigger for command retries.
-	 * Busy conditions require a different trigger since
-	 * no commands are outstanding for that initiator from the
-	 * devices perspective.
-	 * The drawback of mapping a queue full condition to a
-	 * busy condition is the chance of wasting all retries prior
-	 * to the time when the device indicates that a command
-	 * rejected due to a queue full condition should be re-driven.
-	 * This case would lead to unnecessary I/O errors that
-	 * have to be considered fatal if for example ext3's
-	 * journaling would be torpedoed by such an avoidable
-	 * I/O error.
-	 * So, what issues are there with not mapping a queue-full
-	 * condition to a busy condition?
-	 * Due to the 'exclusive LUN'
-	 * policy enforced by the zSeries FCP channel, this 
-	 * Linux instance is the only initiator with regard to
-	 * this adapter. It is safe to rely on the information
-	 * 'don't disturb me now ... and btw. no other commands
-	 * pending for you' (= queue full) sent by the LU,
-	 * since no other Linux can use this LUN via this adapter
-	 * at the same time. If there is a potential race
-	 * introduced by the FCP channel by not inhibiting Linux A
-	 * to give up a LU with commands pending while Linux B
-	 * grabs this LU and sends commands  - thus providing
-	 * an exploit at the 'exclusive LUN' policy - then this
-	 * issue has to be considered a hardware problem. It should
-	 * be tracked as such if it really occurs. Even if the
-	 * FCP Channel spec. begs exploiters to wait for the
-	 * completion of all request sent to a LU prior to
-	 * closing this LU connection.
-	 * This spec. statement in conjunction with
-	 * the 'exclusive LUN' policy is not consistent design.
-	 * Another issue is how resource constraints for SCSI commands
-	 * might be handled by the FCP channel (just guessing for now).
-	 * If the FCP channel would always map resource constraints,
-	 * e.g. no free FC exchange ID due to I/O stress caused by
-	 * other sharing Linux instances, to faked queue-full
-	 * conditions then this would be a misinterpretation and
-	 * violation of SCSI standards.
-	 * If there are SCSI stack races as indicated below
-	 * then they need to be fixed just there.
-	 * Providing all issue above are not applicable or will
-	 * be fixed appropriately, removing the following hack
-	 * is the right thing to do.
-	 */
-
-	/*
-	 * Note: This is a rather nasty chop at the problem. We cannot 
-	 * risk adding to the mlqueue however as this will block the 
-	 * device. If it is the last outstanding command for this host
-	 * it will remain blocked indefinitely. This would be quite possible
-	 * on the zSeries FCP adapter.
-	 * Also, there exists a race with scsi_insert_special relying on 
-	 * scsi_request_fn to recalculate some command data which may not 
-	 * happen when q->plugged is true in scsi_request_fn
-	 */
-	if (status_byte(scpnt->result) == QUEUE_FULL) {
-		ZFCP_LOG_DEBUG("Changing QUEUE_FULL to BUSY....\n");
-		scpnt->result &= ~(QUEUE_FULL << 1);
-		scpnt->result |= (BUSY << 1);
-	}
-#endif
-
 	ZFCP_LOG_DEBUG("scpnt->result =0x%x\n", scpnt->result);
 
 	zfcp_cmd_dbf_event_scsi("response", scpnt);
@@ -4585,16 +4548,6 @@ zfcp_fsf_control_file_handler(struct zfcp_fsf_req *fsf_req)
 		retval = -EIO;
 		break;
 
-	case FSF_UNKNOWN_COMMAND:
-		ZFCP_LOG_FLAGS(2, "FSF_UNKNOWN_COMMAND\n");
-		ZFCP_LOG_NORMAL(
-			"FSF command 0x%x is not supported by the adapter %s\n",
-			fsf_req->fsf_command,
-			zfcp_get_busid_by_adapter(adapter));
-		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-		retval = -EINVAL;
-		break;
-
 	case FSF_UNKNOWN_OP_SUBTYPE:
 		ZFCP_LOG_FLAGS(2, "FSF_UNKNOWN_OP_SUBTYPE\n");
 		ZFCP_LOG_NORMAL(
@@ -4682,8 +4635,8 @@ zfcp_fsf_req_wait_and_cleanup(struct zfcp_fsf_req *fsf_req,
 }
 
 static inline int
-zfcp_fsf_req_create_sbal_check(unsigned long *flags,
-			       struct zfcp_qdio_queue *queue, int needed)
+zfcp_fsf_req_sbal_check(unsigned long *flags,
+			struct zfcp_qdio_queue *queue, int needed)
 {
 	write_lock_irqsave(&queue->queue_lock, *flags);
 	if (likely(atomic_read(&queue->free_count) >= needed))
@@ -4712,30 +4665,25 @@ zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req, u32 fsf_cmd)
  * zfcp_fsf_req_sbal_get - try to get one SBAL in the request queue
  * @adapter: adapter for which request queue is examined
  * @req_flags: flags indicating whether to wait for needed SBAL or not
- * @lock_flags: lock_flags is queue_lock is taken
- *
- * locking: on success the queue_lock for the request queue of the adapter
- *	is held
+ * @lock_flags: lock_flags if queue_lock is taken
+ * Return: 0 on success, otherwise -EIO, or -ERESTARTSYS
+ * Locks: lock adapter->request_queue->queue_lock on success
  */
 static int
 zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter, int req_flags,
 		      unsigned long *lock_flags)
 {
-        int condition;
+        long ret;
         struct zfcp_qdio_queue *req_queue = &adapter->request_queue;
 
         if (unlikely(req_flags & ZFCP_WAIT_FOR_SBAL)) {
-                wait_event_interruptible_timeout(adapter->request_wq,
-						 (condition =
-						  zfcp_fsf_req_create_sbal_check
-						  (lock_flags, req_queue, 1)),
-						 ZFCP_SBAL_TIMEOUT);
-                if (!condition) {
-                        return -EIO;
-		}
-        } else if (!zfcp_fsf_req_create_sbal_check(lock_flags, req_queue, 1)) {
+                ret = wait_event_interruptible_timeout(adapter->request_wq,
+			zfcp_fsf_req_sbal_check(lock_flags, req_queue, 1),
+						       ZFCP_SBAL_TIMEOUT);
+		if (ret < 0)
+			return ret;
+        } else if (!zfcp_fsf_req_sbal_check(lock_flags, req_queue, 1))
                 return -EIO;
-	}
 
         return 0;
 }
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
index 879313864..3ad0ace82 100644
--- a/drivers/s390/scsi/zfcp_fsf.h
+++ b/drivers/s390/scsi/zfcp_fsf.h
@@ -84,19 +84,12 @@
 #define FSF_SERVICE_CLASS_NOT_SUPPORTED		0x00000006
 #define FSF_FCPLUN_NOT_VALID			0x00000009
 #define FSF_ACCESS_DENIED			0x00000010
-#define FSF_ACCESS_TYPE_NOT_VALID		0x00000011
 #define FSF_LUN_SHARING_VIOLATION               0x00000012
-#define FSF_COMMAND_ABORTED_ULP			0x00000020
-#define FSF_COMMAND_ABORTED_ADAPTER		0x00000021
 #define FSF_FCP_COMMAND_DOES_NOT_EXIST		0x00000022
 #define FSF_DIRECTION_INDICATOR_NOT_VALID	0x00000030
-#define FSF_INBOUND_DATA_LENGTH_NOT_VALID	0x00000031 /* FIX: obsolete? */
-#define FSF_OUTBOUND_DATA_LENGTH_NOT_VALID	0x00000032 /* FIX: obsolete? */
 #define FSF_CMND_LENGTH_NOT_VALID		0x00000033
 #define FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED	0x00000040
 #define FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED	0x00000041
-#define FSF_REQUEST_BUF_NOT_VALID		0x00000042
-#define FSF_RESPONSE_BUF_NOT_VALID		0x00000043
 #define FSF_ELS_COMMAND_REJECTED		0x00000050
 #define FSF_GENERIC_COMMAND_REJECTED		0x00000051
 #define FSF_OPERATION_PARTIALLY_SUCCESSFUL	0x00000052
@@ -227,6 +220,10 @@
 #define FSF_HBA_PORTSTATE_LINKDOWN		0x00000006
 #define FSF_HBA_PORTSTATE_ERROR			0x00000007
 
+/* IO states of adapter */
+#define FSF_IOSTAT_NPORT_RJT			0x00000004
+#define FSF_IOSTAT_FABRIC_RJT			0x00000005
+#define FSF_IOSTAT_LS_RJT			0x00000009
 
 struct fsf_queue_designator;
 struct fsf_status_read_buffer;
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index d0a879f0a..6c0808163 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -31,7 +31,7 @@
 #define ZFCP_LOG_AREA			ZFCP_LOG_AREA_SCSI
 
 /* this drivers version (do not edit !!! generated and updated by cvs) */
-#define ZFCP_SCSI_REVISION "$Revision: 1.65 $"
+#define ZFCP_SCSI_REVISION "$Revision: 1.68 $"
 
 #include "zfcp_ext.h"
 
@@ -247,15 +247,16 @@ zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result)
 /**
  * zfcp_scsi_command_async - worker for zfcp_scsi_queuecommand and
  *	zfcp_scsi_command_sync
- * @adapter: adapter for where scsi command is issued
+ * @adapter: adapter where scsi command is issued
  * @unit: unit to which scsi command is sent
  * @scpnt: scsi command to be sent
+ * @timer: timer to be started if request is successfully initiated
  *
  * Note: In scsi_done function must be set in scpnt.
  */
 int
 zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit,
-			struct scsi_cmnd *scpnt)
+			struct scsi_cmnd *scpnt, struct timer_list *timer)
 {
 	int tmp;
 	int retval;
@@ -291,7 +292,7 @@ zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit,
 		goto out;
 	}
 
-	tmp = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt,
+	tmp = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, timer,
 					     ZFCP_REQ_AUTO_CLEANUP);
 
 	if (unlikely(tmp < 0)) {
@@ -313,18 +314,28 @@ zfcp_scsi_command_sync_handler(struct scsi_cmnd *scpnt)
 
 /**
  * zfcp_scsi_command_sync - send a SCSI command and wait for completion
- * returns 0, errors are indicated by scsi_cmnd->result
+ * @unit: unit where command is sent to
+ * @scpnt: scsi command to be sent
+ * @timer: timer to be started if request is successfully initiated
+ * Return: 0
+ *
+ * Errors are indicated in scpnt->result
  */
 int
-zfcp_scsi_command_sync(struct zfcp_unit *unit, struct scsi_cmnd *scpnt)
+zfcp_scsi_command_sync(struct zfcp_unit *unit, struct scsi_cmnd *scpnt,
+		       struct timer_list *timer)
 {
+	int ret;
 	DECLARE_COMPLETION(wait);
 
 	scpnt->SCp.ptr = (void *) &wait;  /* silent re-use */
-	scpnt->done = zfcp_scsi_command_sync_handler;
-        zfcp_scsi_command_async(unit->port->adapter, unit, scpnt);
+	scpnt->scsi_done = zfcp_scsi_command_sync_handler;
+	ret = zfcp_scsi_command_async(unit->port->adapter, unit, scpnt, timer);
+	if ((ret == 0) && (scpnt->result == 0))
 	wait_for_completion(&wait);
 
+	scpnt->SCp.ptr = NULL;
+
 	return 0;
 }
 
@@ -355,7 +366,7 @@ zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
 	adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0];
 	unit = (struct zfcp_unit *) scpnt->device->hostdata;
 
-	return zfcp_scsi_command_async(adapter, unit, scpnt);
+	return zfcp_scsi_command_async(adapter, unit, scpnt, NULL);
 }
 
 /*
@@ -430,7 +441,7 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
 	u64 dbf_fsf_req = 0;
 	u64 dbf_fsf_status = 0;
 	u64 dbf_fsf_qual[2] = { 0, 0 };
-	char dbf_result[ZFCP_ABORT_DBF_LENGTH] = { "##undef" };
+	char dbf_result[ZFCP_ABORT_DBF_LENGTH] = "##undef";
 
 	memset(dbf_opcode, 0, ZFCP_ABORT_DBF_LENGTH);
 	memcpy(dbf_opcode,
diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c
index d7536a11a..f92ec32d7 100644
--- a/drivers/s390/scsi/zfcp_sysfs_adapter.c
+++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c
@@ -26,18 +26,18 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_SYSFS_ADAPTER_C_REVISION "$Revision: 1.33 $"
+#define ZFCP_SYSFS_ADAPTER_C_REVISION "$Revision: 1.37 $"
 
 #include "zfcp_ext.h"
 
 #define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_CONFIG
 
 static const char fc_topologies[5][25] = {
-	{"<error>"},
-	{"point-to-point"},
-	{"fabric"},
-	{"arbitrated loop"},
-	{"fabric (virt. adapter)"}
+	"<error>",
+	"point-to-point",
+	"fabric",
+	"arbitrated loop",
+	"fabric (virt. adapter)"
 };
 
 /**
@@ -74,29 +74,8 @@ ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n",
 			 adapter->hardware_version);
 ZFCP_DEFINE_ADAPTER_ATTR(serial_number, "%17s\n", adapter->serial_number);
 ZFCP_DEFINE_ADAPTER_ATTR(scsi_host_no, "0x%x\n", adapter->scsi_host_no);
-
-/**
- * zfcp_sysfs_adapter_in_recovery_show - recovery state of adapter
- * @dev: pointer to belonging device
- * @buf: pointer to input buffer
- *
- * Show function of "in_recovery" attribute of adapter. Will be
- * "0" if no error recovery is pending for adapter, otherwise "1".
- */
-static ssize_t
-zfcp_sysfs_adapter_in_recovery_show(struct device *dev, char *buf)
-{
-	struct zfcp_adapter *adapter;
-
-	adapter = dev_get_drvdata(dev);
-	if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status))
-		return sprintf(buf, "1\n");
-	else
-		return sprintf(buf, "0\n");
-}
-
-static DEVICE_ATTR(in_recovery, S_IRUGO,
-		   zfcp_sysfs_adapter_in_recovery_show, NULL);
+ZFCP_DEFINE_ADAPTER_ATTR(in_recovery, "%d\n", atomic_test_mask
+			 (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status));
 
 /**
  * zfcp_sysfs_port_add_store - add a port to sysfs tree
@@ -127,7 +106,7 @@ zfcp_sysfs_port_add_store(struct device *dev, const char *buf, size_t count)
 	if ((endp + 1) < (buf + count))
 		goto out;
 
-	port = zfcp_port_enqueue(adapter, wwpn, 0);
+	port = zfcp_port_enqueue(adapter, wwpn, 0, 0);
 	if (!port)
 		goto out;
 
@@ -138,7 +117,7 @@ zfcp_sysfs_port_add_store(struct device *dev, const char *buf, size_t count)
 	zfcp_port_put(port);
  out:
 	up(&zfcp_data.config_sema);
-	return retval ? retval : count;
+	return retval ? retval : (ssize_t) count;
 }
 
 static DEVICE_ATTR(port_add, S_IWUSR, NULL, zfcp_sysfs_port_add_store);
@@ -197,7 +176,7 @@ zfcp_sysfs_port_remove_store(struct device *dev, const char *buf, size_t count)
 	zfcp_port_dequeue(port);
  out:
 	up(&zfcp_data.config_sema);
-	return retval ? retval : count;
+	return retval ? retval : (ssize_t) count;
 }
 
 static DEVICE_ATTR(port_remove, S_IWUSR, NULL, zfcp_sysfs_port_remove_store);
@@ -241,7 +220,7 @@ zfcp_sysfs_adapter_failed_store(struct device *dev,
 	zfcp_erp_wait(adapter);
  out:
 	up(&zfcp_data.config_sema);
-	return retval ? retval : count;
+	return retval ? retval : (ssize_t) count;
 }
 
 /**
diff --git a/drivers/s390/scsi/zfcp_sysfs_driver.c b/drivers/s390/scsi/zfcp_sysfs_driver.c
index e0d6eecfe..ffd55176f 100644
--- a/drivers/s390/scsi/zfcp_sysfs_driver.c
+++ b/drivers/s390/scsi/zfcp_sysfs_driver.c
@@ -26,7 +26,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_SYSFS_DRIVER_C_REVISION "$Revision: 1.14 $"
+#define ZFCP_SYSFS_DRIVER_C_REVISION "$Revision: 1.15 $"
 
 #include "zfcp_ext.h"
 
@@ -65,7 +65,7 @@ static ssize_t zfcp_sysfs_loglevel_##_name##_store(struct device_driver *drv, \
 static ssize_t zfcp_sysfs_loglevel_##_name##_show(struct device_driver *dev,  \
 						  char *buf)                  \
 {                                                                             \
-	return sprintf(buf,"%d\n",				              \
+	return sprintf(buf,"%d\n", (unsigned int)                             \
 		       ZFCP_GET_LOG_VALUE(ZFCP_LOG_AREA_##_define));          \
 }                                                                             \
                                                                               \
diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c
index 11a27c1ff..10b66cd8c 100644
--- a/drivers/s390/scsi/zfcp_sysfs_port.c
+++ b/drivers/s390/scsi/zfcp_sysfs_port.c
@@ -26,7 +26,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.41 $"
+#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.44 $"
 
 #include "zfcp_ext.h"
 
@@ -66,6 +66,8 @@ ZFCP_DEFINE_PORT_ATTR(status, "0x%08x\n", atomic_read(&port->status));
 ZFCP_DEFINE_PORT_ATTR(wwnn, "0x%016llx\n", port->wwnn);
 ZFCP_DEFINE_PORT_ATTR(d_id, "0x%06x\n", port->d_id);
 ZFCP_DEFINE_PORT_ATTR(scsi_id, "0x%x\n", port->scsi_id);
+ZFCP_DEFINE_PORT_ATTR(in_recovery, "%d\n", atomic_test_mask
+		      (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status));
 
 /**
  * zfcp_sysfs_unit_add_store - add a unit to sysfs tree
@@ -107,7 +109,7 @@ zfcp_sysfs_unit_add_store(struct device *dev, const char *buf, size_t count)
 	zfcp_unit_put(unit);
  out:
 	up(&zfcp_data.config_sema);
-	return retval ? retval : count;
+	return retval ? retval : (ssize_t) count;
 }
 
 static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store);
@@ -164,7 +166,7 @@ zfcp_sysfs_unit_remove_store(struct device *dev, const char *buf, size_t count)
 	zfcp_unit_dequeue(unit);
  out:
 	up(&zfcp_data.config_sema);
-	return retval ? retval : count;
+	return retval ? retval : (ssize_t) count;
 }
 
 static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store);
@@ -206,7 +208,7 @@ zfcp_sysfs_port_failed_store(struct device *dev, const char *buf, size_t count)
 	zfcp_erp_wait(port->adapter);
  out:
 	up(&zfcp_data.config_sema);
-	return retval ? retval : count;
+	return retval ? retval : (ssize_t) count;
 }
 
 /**
@@ -232,29 +234,6 @@ zfcp_sysfs_port_failed_show(struct device *dev, char *buf)
 static DEVICE_ATTR(failed, S_IWUSR | S_IRUGO, zfcp_sysfs_port_failed_show,
 		   zfcp_sysfs_port_failed_store);
 
-/**
- * zfcp_sysfs_port_in_recovery_show - recovery state of port
- * @dev: pointer to belonging device
- * @buf: pointer to input buffer
- * 
- * Show function of "in_recovery" attribute of port. Will be
- * "0" if no error recovery is pending for port, otherwise "1".
- */
-static ssize_t
-zfcp_sysfs_port_in_recovery_show(struct device *dev, char *buf)
-{
-	struct zfcp_port *port;
-
-	port = dev_get_drvdata(dev);
-	if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status))
-		return sprintf(buf, "1\n");
-	else
-		return sprintf(buf, "0\n");
-}
-
-static DEVICE_ATTR(in_recovery, S_IRUGO, zfcp_sysfs_port_in_recovery_show,
-		   NULL);
-
 /**
  * zfcp_port_common_attrs
  * sysfs attributes that are common for all kind of fc ports.
@@ -300,7 +279,7 @@ zfcp_sysfs_port_create_files(struct device *dev, u32 flags)
 
 	retval = sysfs_create_group(&dev->kobj, &zfcp_port_common_attr_group);
 
-	if ((flags & ZFCP_STATUS_PORT_NAMESERVER) || retval)
+	if ((flags & ZFCP_STATUS_PORT_WKA) || retval)
 		return retval;
 
 	retval = sysfs_create_group(&dev->kobj, &zfcp_port_no_ns_attr_group);
@@ -320,7 +299,7 @@ void
 zfcp_sysfs_port_remove_files(struct device *dev, u32 flags)
 {
 	sysfs_remove_group(&dev->kobj, &zfcp_port_common_attr_group);
-	if (!(flags & ZFCP_STATUS_PORT_NAMESERVER))
+	if (!(flags & ZFCP_STATUS_PORT_WKA))
 		sysfs_remove_group(&dev->kobj, &zfcp_port_no_ns_attr_group);
 }
 
diff --git a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c
index 904c8aead..bad3b7f2c 100644
--- a/drivers/s390/scsi/zfcp_sysfs_unit.c
+++ b/drivers/s390/scsi/zfcp_sysfs_unit.c
@@ -26,7 +26,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#define ZFCP_SYSFS_UNIT_C_REVISION "$Revision: 1.25 $"
+#define ZFCP_SYSFS_UNIT_C_REVISION "$Revision: 1.27 $"
 
 #include "zfcp_ext.h"
 
@@ -64,6 +64,8 @@ static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_unit_##_name##_show, NULL);
 
 ZFCP_DEFINE_UNIT_ATTR(status, "0x%08x\n", atomic_read(&unit->status));
 ZFCP_DEFINE_UNIT_ATTR(scsi_lun, "0x%x\n", unit->scsi_lun);
+ZFCP_DEFINE_UNIT_ATTR(in_recovery, "%d\n", atomic_test_mask
+		      (ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status));
 
 /**
  * zfcp_sysfs_unit_failed_store - failed state of unit
@@ -101,7 +103,7 @@ zfcp_sysfs_unit_failed_store(struct device *dev, const char *buf, size_t count)
 	zfcp_erp_wait(unit->port->adapter);
  out:
 	up(&zfcp_data.config_sema);
-	return retval ? retval : count;
+	return retval ? retval : (ssize_t) count;
 }
 
 /**
@@ -127,29 +129,6 @@ zfcp_sysfs_unit_failed_show(struct device *dev, char *buf)
 static DEVICE_ATTR(failed, S_IWUSR | S_IRUGO, zfcp_sysfs_unit_failed_show,
 		   zfcp_sysfs_unit_failed_store);
 
-/**
- * zfcp_sysfs_unit_in_recovery_show - recovery state of unit
- * @dev: pointer to belonging device
- * @buf: pointer to input buffer
- *
- * Show function of "in_recovery" attribute of unit. Will be
- * "0" if no error recovery is pending for unit, otherwise "1".
- */
-static ssize_t
-zfcp_sysfs_unit_in_recovery_show(struct device *dev, char *buf)
-{
-	struct zfcp_unit *unit;
-
-	unit = dev_get_drvdata(dev);
-	if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status))
-		return sprintf(buf, "1\n");
-	else
-		return sprintf(buf, "0\n");
-}
-
-static DEVICE_ATTR(in_recovery, S_IRUGO, zfcp_sysfs_unit_in_recovery_show,
-		   NULL);
-
 static struct attribute *zfcp_unit_attrs[] = {
 	&dev_attr_scsi_lun.attr,
 	&dev_attr_failed.attr,
diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c
index d45619f3b..1ff81bec8 100644
--- a/drivers/sbus/char/aurora.c
+++ b/drivers/sbus/char/aurora.c
@@ -1531,8 +1531,7 @@ static void aurora_close(struct tty_struct * tty, struct file * filp)
 	aurora_shutdown_port(bp, port);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
 	tty->closing = 0;
 	port->event = 0;
 	port->tty = 0;
@@ -1743,10 +1742,7 @@ static void aurora_flush_buffer(struct tty_struct *tty)
 	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
 	restore_flags(flags);
 	
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 #ifdef AURORA_DEBUG
 	printk("aurora_flush_buffer: end\n");
 #endif
@@ -2223,10 +2219,7 @@ static void do_softint(void *private_)
 		return;
 
 	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
+		tty_wakeup(tty);
 	}
 #ifdef AURORA_DEBUG
 	printk("do_softint: end\n");
diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c
index 37189ef06..d5259f7fe 100644
--- a/drivers/sbus/char/bbc_envctrl.c
+++ b/drivers/sbus/char/bbc_envctrl.c
@@ -452,7 +452,7 @@ static void fans_full_blast(void)
 	}
 }
 
-#define POLL_INTERVAL	(5 * HZ)
+#define POLL_INTERVAL	(5 * 1000)
 static unsigned long last_warning_jiffies;
 static struct task_struct *kenvctrld_task;
 
@@ -468,8 +468,7 @@ static int kenvctrld(void *__unused)
 		struct bbc_cpu_temperature *tp;
 		struct bbc_fan_control *fp;
 
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(POLL_INTERVAL);
+		msleep_interruptible(POLL_INTERVAL);
 		if (signal_pending(current))
 			break;
 
diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c
index a489c544f..2dcd3cd87 100644
--- a/drivers/sbus/char/bbc_i2c.c
+++ b/drivers/sbus/char/bbc_i2c.c
@@ -189,13 +189,13 @@ static int wait_for_pin(struct bbc_i2c_bus *bp, u8 *status)
 	while (limit-- > 0) {
 		u8 val;
 
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		*status = val = readb(bp->i2c_control_regs + 0);
 		if ((val & I2C_PCF_PIN) == 0) {
 			ret = 0;
 			break;
 		}
-		schedule_timeout(HZ/4);
+		msleep_interruptible(250);
 	}
 	remove_wait_queue(&bp->wq, &wait);
 	bp->waiting = 0;
diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c
index ad870a300..9fcf180ba 100644
--- a/drivers/sbus/char/cpwatchdog.c
+++ b/drivers/sbus/char/cpwatchdog.c
@@ -118,40 +118,26 @@
  * UNKNOWN, MAGICAL MYSTERY REGISTER
  *
  */
-struct wd_timer_regblk {
-	volatile __u16	dcntr;		/* down counter		- hw	*/
-	volatile __u16	dcntr_pad;
-	volatile __u16	limit;		/* limit register	- hw	*/
-	volatile __u16	limit_pad;
-	volatile __u8	status;		/* status register	- b		*/
-	volatile __u8	status_pad;
-	volatile __u16	status_pad2;
-	volatile __u32	pad32;		/* yet more padding			*/
-};
+#define WD_TIMER_REGSZ	16
+#define WD0_OFF		0
+#define WD1_OFF		(WD_TIMER_REGSZ * 1)
+#define WD2_OFF		(WD_TIMER_REGSZ * 2)
+#define PLD_OFF		(WD_TIMER_REGSZ * 3)
 
-struct wd_pld_regblk {
-	volatile __u8	intr_mask;	/* interrupt mask	- b		*/
-	volatile __u8	intr_mask_pad;
-	volatile __u16	intr_mask_pad2;
-	volatile __u8	status;		/* device status	- b		*/
-	volatile __u8	status_pad;
-	volatile __u16	status_pad2;
-};
+#define WD_DCNTR	0x00
+#define WD_LIMIT	0x04
+#define WD_STATUS	0x08
 
-struct wd_regblk {
-	volatile struct wd_timer_regblk		wd0_regs;
-	volatile struct wd_timer_regblk		wd1_regs;
-	volatile struct wd_timer_regblk		wd2_regs;
-	volatile struct wd_pld_regblk		pld_regs;
-};
+#define PLD_IMASK	(PLD_OFF + 0x00)
+#define PLD_STATUS	(PLD_OFF + 0x04)
 
 /* Individual timer structure 
  */
 struct wd_timer {
 	__u16			timeout;
 	__u8			intr_mask;
-	unsigned char	runstatus;
-	volatile struct wd_timer_regblk* regs;
+	unsigned char		runstatus;
+	void __iomem		*regs;
 };
 
 /* Device structure
@@ -165,7 +151,7 @@ struct wd_device {
 	unsigned short	opt_timeout;
 	unsigned char	initialized;
 	struct wd_timer	watchdog[WD_NUMDEVS];
-	volatile struct	wd_regblk* regs;
+	void __iomem	*regs;
 };
 
 static struct wd_device wd_dev = { 
@@ -495,12 +481,12 @@ static void wd_dumpregs(void)
 				i,
 				wd_getstatus(&wd_dev.watchdog[i]));
 	}
-	printk("\tintr_mask  at 0x%lx: 0x%x\n", 
-		(unsigned long)(&wd_dev.regs->pld_regs.intr_mask), 
-		readb(&wd_dev.regs->pld_regs.intr_mask));
-	printk("\tpld_status at 0x%lx: 0x%x\n", 
-		(unsigned long)(&wd_dev.regs->pld_regs.status), 
-		readb(&wd_dev.regs->pld_regs.status));
+	printk("\tintr_mask  at %p: 0x%x\n", 
+		wd_dev.regs + PLD_IMASK,
+		readb(wd_dev.regs + PLD_IMASK));
+	printk("\tpld_status at %p: 0x%x\n", 
+		wd_dev.regs + PLD_STATUS, 
+		readb(wd_dev.regs + PLD_STATUS));
 }
 #endif
 
@@ -513,7 +499,7 @@ static void wd_dumpregs(void)
  */
 static void wd_toggleintr(struct wd_timer* pTimer, int enable)
 {
-	unsigned char curregs = wd_readb(&wd_dev.regs->pld_regs.intr_mask);
+	unsigned char curregs = wd_readb(wd_dev.regs + PLD_IMASK);
 	unsigned char setregs = 
 		(NULL == pTimer) ? 
 			(WD0_INTR_MASK | WD1_INTR_MASK | WD2_INTR_MASK) : 
@@ -523,7 +509,7 @@ static void wd_toggleintr(struct wd_timer* pTimer, int enable)
 		(curregs &= ~setregs):
 		(curregs |=  setregs);
 
-	wd_writeb(curregs, &wd_dev.regs->pld_regs.intr_mask);
+	wd_writeb(curregs, wd_dev.regs + PLD_IMASK);
 	return;
 }
 
@@ -534,8 +520,8 @@ static void wd_toggleintr(struct wd_timer* pTimer, int enable)
  */
 static void wd_pingtimer(struct wd_timer* pTimer)
 {
-	if(wd_readb(&pTimer->regs->status) & WD_S_RUNNING) {
-		wd_readw(&pTimer->regs->dcntr);
+	if (wd_readb(pTimer->regs + WD_STATUS) & WD_S_RUNNING) {
+		wd_readw(pTimer->regs + WD_DCNTR);
 	}
 }
 
@@ -547,7 +533,7 @@ static void wd_pingtimer(struct wd_timer* pTimer)
  */
 static void wd_stoptimer(struct wd_timer* pTimer)
 {
-	if(wd_readb(&pTimer->regs->status) & WD_S_RUNNING) {
+	if(wd_readb(pTimer->regs + WD_STATUS) & WD_S_RUNNING) {
 		wd_toggleintr(pTimer, WD_INTR_OFF);
 
 		if(wd_dev.isbaddoggie) {
@@ -574,7 +560,7 @@ static void wd_starttimer(struct wd_timer* pTimer)
 	}
 	pTimer->runstatus &= ~WD_STAT_SVCD;
 
-	wd_writew(pTimer->timeout, &pTimer->regs->limit);
+	wd_writew(pTimer->timeout, pTimer->regs + WD_LIMIT);
 	wd_toggleintr(pTimer, WD_INTR_ON);
 }
 
@@ -584,7 +570,7 @@ static void wd_starttimer(struct wd_timer* pTimer)
 static void wd_resetbrokentimer(struct wd_timer* pTimer)
 {
 	wd_toggleintr(pTimer, WD_INTR_ON);
-	wd_writew(WD_BLIMIT, &pTimer->regs->limit);
+	wd_writew(WD_BLIMIT, pTimer->regs + WD_LIMIT);
 }
 
 /* Timer device initialization helper.
@@ -593,7 +579,7 @@ static void wd_resetbrokentimer(struct wd_timer* pTimer)
 static int wd_inittimer(int whichdog)
 {
 	struct miscdevice 				*whichmisc;
-	volatile struct wd_timer_regblk	*whichregs;
+	void __iomem *whichregs;
 	char 							whichident[8];
 	int								whichmask;
 	__u16							whichlimit;
@@ -603,7 +589,7 @@ static int wd_inittimer(int whichdog)
 		case WD0_ID:
 			whichmisc = &wd0_miscdev;
 			strcpy(whichident, "RIC");
-			whichregs = &wd_dev.regs->wd0_regs;
+			whichregs = wd_dev.regs + WD0_OFF;
 			whichmask = WD0_INTR_MASK;
 			whichlimit= (0 == wd0_timeout) 	? 
 						(wd_dev.opt_timeout): 
@@ -612,7 +598,7 @@ static int wd_inittimer(int whichdog)
 		case WD1_ID:
 			whichmisc = &wd1_miscdev;
 			strcpy(whichident, "XIR");
-			whichregs = &wd_dev.regs->wd1_regs;
+			whichregs = wd_dev.regs + WD1_OFF;
 			whichmask = WD1_INTR_MASK;
 			whichlimit= (0 == wd1_timeout) 	? 
 						(wd_dev.opt_timeout): 
@@ -621,7 +607,7 @@ static int wd_inittimer(int whichdog)
 		case WD2_ID:
 			whichmisc = &wd2_miscdev;
 			strcpy(whichident, "POR");
-			whichregs = &wd_dev.regs->wd2_regs;
+			whichregs = wd_dev.regs + WD2_OFF;
 			whichmask = WD2_INTR_MASK;
 			whichlimit= (0 == wd2_timeout) 	? 
 						(wd_dev.opt_timeout): 
@@ -686,8 +672,8 @@ static void wd_brokentimer(unsigned long data)
 
 static int wd_getstatus(struct wd_timer* pTimer)
 {
-	unsigned char stat = wd_readb(&pTimer->regs->status);
-	unsigned char intr = wd_readb(&wd_dev.regs->pld_regs.intr_mask);
+	unsigned char stat = wd_readb(pTimer->regs + WD_STATUS);
+	unsigned char intr = wd_readb(wd_dev.regs + PLD_IMASK);
 	unsigned char ret  = WD_STOPPED;
 
 	/* determine STOPPED */
@@ -805,7 +791,7 @@ static void __exit wd_cleanup(void)
 	 * also now eventually trip. 
 	 */
 	for(id = WD0_ID; id < WD_NUMDEVS; ++id) {
-		if(WD_S_RUNNING == wd_readb(&wd_dev.watchdog[id].regs->status)) {
+		if(WD_S_RUNNING == wd_readb(wd_dev.watchdog[id].regs + WD_STATUS)) {
 			if(wd_dev.opt_enable) {
 				printk(KERN_WARNING "%s%i: timer not stopped at release\n",
 					WD_OBPNAME, id);
@@ -818,7 +804,7 @@ static void __exit wd_cleanup(void)
 							"%s%i: defect workaround disabled at release, "\
 							"timer expires in ~%01i sec\n",
 							WD_OBPNAME, id, 
-							wd_readw(&wd_dev.watchdog[id].regs->limit) / 10);
+							wd_readw(wd_dev.watchdog[id].regs + WD_LIMIT) / 10);
 				}
 			}
 		}
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index e8ac0b4d3..adb30d5d3 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -70,7 +70,7 @@ MODULE_SUPPORTED_DEVICE
  * FLIP		- Inverts display for upside-down mounted board
  * bits 0-4	- 7-segment display contents
  */
-volatile u8* d7s_regs = NULL;
+static void __iomem* d7s_regs;
 
 static inline void d7s_free(void)
 {
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
index cd6e2d39f..f6ed35b24 100644
--- a/drivers/sbus/char/envctrl.c
+++ b/drivers/sbus/char/envctrl.c
@@ -130,10 +130,8 @@ static int errno;
  */
 #define ENVCTRL_CPCI_IGNORED_NODE		0x70
 
-struct pcf8584_reg {
-	 unsigned char data;
-	 unsigned char csr;
-};
+#define PCF8584_DATA	0x00
+#define PCF8584_CSR	0x01
 
 /* Each child device can be monitored by up to PCF8584_MAX_CHANNELS.
  * Property of a port or channel as defined by the firmware.
@@ -175,7 +173,7 @@ struct i2c_child_t {
 	char mon_type[PCF8584_MAX_CHANNELS];
 };
 
-volatile static struct pcf8584_reg *i2c = NULL;
+static void __iomem *i2c;
 static struct i2c_child_t i2c_childlist[ENVCTRL_MAX_CPU*2];
 static unsigned char chnls_mask[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
 static unsigned int warning_temperature = 0;
@@ -185,22 +183,6 @@ static char read_cpu;
 /* Forward declarations. */
 static struct i2c_child_t *envctrl_get_i2c_child(unsigned char);
 
-/* Function description: Read a byte from an i2c controller register.
- * Return: A byte from the passed in address.
- */
-static inline unsigned char envctrl_readb(volatile unsigned char *p)
-{
-	return readb(p);
-}
-
-/* Function description: Write a byte to an i2c controller register.
- * Return: Nothing.
- */
-static inline void envctrl_writeb(unsigned char val, volatile unsigned char *p)
-{
-	writeb(val, p);
-}
-
 /* Function Description: Test the PIN bit (Pending Interrupt Not) 
  * 			 to test when serial transmission is completed .
  * Return : None.
@@ -210,7 +192,7 @@ static void envtrl_i2c_test_pin(void)
 	int limit = 1000000;
 
 	while (--limit > 0) {
-		if (!(envctrl_readb(&i2c->csr) & STATUS_PIN)) 
+		if (!(readb(i2c + PCF8584_CSR) & STATUS_PIN)) 
 			break;
 		udelay(1);
 	} 
@@ -228,7 +210,7 @@ static void envctrl_i2c_test_bb(void)
 
 	while (--limit > 0) {
 		/* Busy bit 0 means busy. */
-		if (envctrl_readb(&i2c->csr) & STATUS_BB)
+		if (readb(i2c + PCF8584_CSR) & STATUS_BB)
 			break;
 		udelay(1);
 	} 
@@ -245,20 +227,20 @@ static int envctrl_i2c_read_addr(unsigned char addr)
 	envctrl_i2c_test_bb();
 
 	/* Load address. */
-	envctrl_writeb(addr + 1, &i2c->data);
+	writeb(addr + 1, i2c + PCF8584_DATA);
 
 	envctrl_i2c_test_bb();
 
-	envctrl_writeb(OBD_SEND_START, &i2c->csr);
+	writeb(OBD_SEND_START, i2c + PCF8584_CSR);
 
 	/* Wait for PIN. */
 	envtrl_i2c_test_pin();
 
 	/* CSR 0 means acknowledged. */
-	if (!(envctrl_readb(&i2c->csr) & STATUS_LRB)) {
-		return envctrl_readb(&i2c->data);
+	if (!(readb(i2c + PCF8584_CSR) & STATUS_LRB)) {
+		return readb(i2c + PCF8584_DATA);
 	} else {
-		envctrl_writeb(OBD_SEND_STOP, &i2c->csr);
+		writeb(OBD_SEND_STOP, i2c + PCF8584_CSR);
 		return 0;
 	}
 }
@@ -269,10 +251,10 @@ static int envctrl_i2c_read_addr(unsigned char addr)
 static void envctrl_i2c_write_addr(unsigned char addr)
 {
 	envctrl_i2c_test_bb();
-	envctrl_writeb(addr, &i2c->data);
+	writeb(addr, i2c + PCF8584_DATA);
 
 	/* Generate Start condition. */
-	envctrl_writeb(OBD_SEND_START, &i2c->csr);
+	writeb(OBD_SEND_START, i2c + PCF8584_CSR);
 }
 
 /* Function Description: Read 1 byte of data from addr 
@@ -282,8 +264,8 @@ static void envctrl_i2c_write_addr(unsigned char addr)
 static unsigned char envctrl_i2c_read_data(void)
 {
 	envtrl_i2c_test_pin();
-	envctrl_writeb(CONTROL_ES0, &i2c->csr);  /* Send neg ack. */
-	return envctrl_readb(&i2c->data);
+	writeb(CONTROL_ES0, i2c + PCF8584_CSR);  /* Send neg ack. */
+	return readb(i2c + PCF8584_DATA);
 }
 
 /* Function Description: Instruct the device which port to read data from.  
@@ -292,7 +274,7 @@ static unsigned char envctrl_i2c_read_data(void)
 static void envctrl_i2c_write_data(unsigned char port)
 {
 	envtrl_i2c_test_pin();
-	envctrl_writeb(port, &i2c->data);
+	writeb(port, i2c + PCF8584_DATA);
 }
 
 /* Function Description: Generate Stop condition after last byte is sent.
@@ -301,7 +283,7 @@ static void envctrl_i2c_write_data(unsigned char port)
 static void envctrl_i2c_stop(void)
 {
 	envtrl_i2c_test_pin();
-	envctrl_writeb(OBD_SEND_STOP, &i2c->csr);
+	writeb(OBD_SEND_STOP, i2c + PCF8584_CSR);
 }
 
 /* Function Description: Read adc device.
@@ -323,7 +305,7 @@ static unsigned char envctrl_i2c_read_8591(unsigned char addr, unsigned char por
 	envctrl_i2c_read_data();
 	envctrl_i2c_stop();
 
-	return envctrl_readb(&i2c->data);
+	return readb(i2c + PCF8584_DATA);
 }
 
 /* Function Description: Read gpio device.
@@ -1084,8 +1066,7 @@ static int __init envctrl_init(void)
 	for_each_ebus(ebus) {
 		for_each_ebusdev(edev, ebus) {
 			if (!strcmp(edev->prom_name, "i2c")) {
-				i2c = ioremap(	edev->resource[0].start, 
-								sizeof(struct pcf8584_reg));
+				i2c = ioremap(edev->resource[0].start, 0x2);
 				for_each_edevchild(edev, edev_child) {
 					if (!strcmp("gpio", edev_child->prom_name)) {
 						i2c_childlist[i].i2ctype = I2C_GPIO;
@@ -1108,15 +1089,15 @@ done:
 	}
 
 	/* Set device address. */
-	envctrl_writeb(CONTROL_PIN, &i2c->csr);
-	envctrl_writeb(PCF8584_ADDRESS, &i2c->data);
+	writeb(CONTROL_PIN, i2c + PCF8584_CSR);
+	writeb(PCF8584_ADDRESS, i2c + PCF8584_DATA);
 
 	/* Set system clock and SCL frequencies. */ 
-	envctrl_writeb(CONTROL_PIN | CONTROL_ES1, &i2c->csr);
-	envctrl_writeb(CLK_4_43 | BUS_CLK_90, &i2c->data);
+	writeb(CONTROL_PIN | CONTROL_ES1, i2c + PCF8584_CSR);
+	writeb(CLK_4_43 | BUS_CLK_90, i2c + PCF8584_DATA);
 
 	/* Enable serial interface. */
-	envctrl_writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_ACK, &i2c->csr);
+	writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_ACK, i2c + PCF8584_CSR);
 	udelay(200);
 
 	/* Register the device as a minor miscellaneous device. */
diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c
index f35cb3276..0d4295044 100644
--- a/drivers/sbus/char/flash.c
+++ b/drivers/sbus/char/flash.c
@@ -22,6 +22,7 @@
 #include <asm/io.h>
 #include <asm/sbus.h>
 #include <asm/ebus.h>
+#include <asm/upa.h>
 
 static spinlock_t flash_lock = SPIN_LOCK_UNLOCKED;
 static struct {
@@ -115,7 +116,7 @@ flash_read(struct file * file, char __user * buf,
 		count = flash.read_size - p;
 
 	for (i = 0; i < count; i++) {
-		u8 data = readb(flash.read_base + p + i);
+		u8 data = upa_readb(flash.read_base + p + i);
 		if (put_user(data, buf))
 			return -EFAULT;
 		buf++;
diff --git a/drivers/sbus/dvma.c b/drivers/sbus/dvma.c
index c095308db..378a1d680 100644
--- a/drivers/sbus/dvma.c
+++ b/drivers/sbus/dvma.c
@@ -17,14 +17,6 @@
 
 struct sbus_dma *dma_chain;
 
-/* Print out the current values in the DMA control registers */
-extern __inline__ void dump_dma_regs(unsigned long dregs)
-{
-	printk("DMA CONTROL<%08x> ADDR<%08x> CNT<%08x> TEST<%08x>\n",
-	       sbus_readl(dregs + DMA_CSR), sbus_readl(dregs + DMA_ADDR),
-	       sbus_readl(dregs + DMA_COUNT), sbus_readl(dregs + DMA_TEST));
-}
-
 void __init init_one_dvma(struct sbus_dma *dma, int num_dma)
 {
 	printk("dma%d: ", num_dma);
@@ -64,9 +56,6 @@ void __init init_one_dvma(struct sbus_dma *dma, int num_dma)
 		break;
 	}
 	printk("\n");
-#if 0 /* Clutters up the screen */
-	dump_dma_regs(dma->regs);
-#endif
 }
 
 /* Probe this SBus DMA module(s) */
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index b8731f204..68ca37d2d 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -551,7 +551,7 @@ int tw_aen_read_queue(TW_Device_Extension *tw_dev, int request_id)
 	/* Now post the command packet */
 	if ((status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL) == 0) {
 		dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Post succeeded.\n");
-		tw_dev->srb[request_id] = 0; /* Flag internal command */
+		tw_dev->srb[request_id] = NULL; /* Flag internal command */
 		tw_dev->state[request_id] = TW_S_POSTED;
 		outl(command_que_value, command_que_addr);
 	} else {
@@ -718,7 +718,7 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
 			tw_state_request_start(tw_dev, &request_id);
 
 			/* Flag internal command */
-			tw_dev->srb[request_id] = 0;
+			tw_dev->srb[request_id] = NULL;
 
 			/* Flag chrdev ioctl */
 			tw_dev->chrdev_request_id = request_id;
@@ -2692,7 +2692,7 @@ int tw_scsi_release(struct Scsi_Host *tw_host)
 	/* Fake like we just shut down, so notify the card that
 	 * we "shut down cleanly".
 	 */
-	tw_halt(0, 0, 0);  // parameters aren't actually used
+	tw_halt(NULL, 0, NULL);  // parameters aren't actually used
 
 	/* Free up the IO region */
 	release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index e4d60d1d1..06faeb228 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -142,11 +142,8 @@ static char *BusLogic_CommandFailureReason;
 
 static void BusLogic_AnnounceDriver(struct BusLogic_HostAdapter *HostAdapter)
 {
-  BusLogic_Announce("***** BusLogic SCSI Driver Version "
-		    BusLogic_DriverVersion " of "
-		    BusLogic_DriverDate " *****\n", HostAdapter);
-  BusLogic_Announce("Copyright 1995-1998 by Leonard N. Zubkoff "
-		    "<lnz@dandelion.com>\n", HostAdapter);
+	BusLogic_Announce("***** BusLogic SCSI Driver Version " BusLogic_DriverVersion " of " BusLogic_DriverDate " *****\n", HostAdapter);
+	BusLogic_Announce("Copyright 1995-1998 by Leonard N. Zubkoff " "<lnz@dandelion.com>\n", HostAdapter);
 }
 
 
@@ -157,9 +154,8 @@ static void BusLogic_AnnounceDriver(struct BusLogic_HostAdapter *HostAdapter)
 
 static const char *BusLogic_DriverInfo(struct Scsi_Host *Host)
 {
-  struct BusLogic_HostAdapter *HostAdapter =
-    (struct BusLogic_HostAdapter *) Host->hostdata;
-  return HostAdapter->FullModelName;
+	struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Host->hostdata;
+	return HostAdapter->FullModelName;
 }
 
 
@@ -170,17 +166,14 @@ static const char *BusLogic_DriverInfo(struct Scsi_Host *Host)
 
 static void __init BusLogic_RegisterHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
 {
-  HostAdapter->Next = NULL;
-  if (BusLogic_FirstRegisteredHostAdapter == NULL)
-    {
-      BusLogic_FirstRegisteredHostAdapter = HostAdapter;
-      BusLogic_LastRegisteredHostAdapter = HostAdapter;
-    }
-  else
-    {
-      BusLogic_LastRegisteredHostAdapter->Next = HostAdapter;
-      BusLogic_LastRegisteredHostAdapter = HostAdapter;
-    }
+	HostAdapter->Next = NULL;
+	if (BusLogic_FirstRegisteredHostAdapter == NULL) {
+		BusLogic_FirstRegisteredHostAdapter = HostAdapter;
+		BusLogic_LastRegisteredHostAdapter = HostAdapter;
+	} else {
+		BusLogic_LastRegisteredHostAdapter->Next = HostAdapter;
+		BusLogic_LastRegisteredHostAdapter = HostAdapter;
+	}
 }
 
 
@@ -191,24 +184,18 @@ static void __init BusLogic_RegisterHostAdapter(struct BusLogic_HostAdapter *Hos
 
 static void BusLogic_UnregisterHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
 {
-  if (HostAdapter == BusLogic_FirstRegisteredHostAdapter)
-    {
-      BusLogic_FirstRegisteredHostAdapter =
-	BusLogic_FirstRegisteredHostAdapter->Next;
-      if (HostAdapter == BusLogic_LastRegisteredHostAdapter)
-	BusLogic_LastRegisteredHostAdapter = NULL;
-    }
-  else
-    {
-      struct BusLogic_HostAdapter *PreviousHostAdapter =
-	BusLogic_FirstRegisteredHostAdapter;
-      while (PreviousHostAdapter != NULL &&
-	     PreviousHostAdapter->Next != HostAdapter)
-	PreviousHostAdapter = PreviousHostAdapter->Next;
-      if (PreviousHostAdapter != NULL)
-	PreviousHostAdapter->Next = HostAdapter->Next;
-    }
-  HostAdapter->Next = NULL;
+	if (HostAdapter == BusLogic_FirstRegisteredHostAdapter) {
+		BusLogic_FirstRegisteredHostAdapter = BusLogic_FirstRegisteredHostAdapter->Next;
+		if (HostAdapter == BusLogic_LastRegisteredHostAdapter)
+			BusLogic_LastRegisteredHostAdapter = NULL;
+	} else {
+		struct BusLogic_HostAdapter *PreviousHostAdapter = BusLogic_FirstRegisteredHostAdapter;
+		while (PreviousHostAdapter != NULL && PreviousHostAdapter->Next != HostAdapter)
+			PreviousHostAdapter = PreviousHostAdapter->Next;
+		if (PreviousHostAdapter != NULL)
+			PreviousHostAdapter->Next = HostAdapter->Next;
+	}
+	HostAdapter->Next = NULL;
 }
 
 
@@ -218,33 +205,29 @@ static void BusLogic_UnregisterHostAdapter(struct BusLogic_HostAdapter *HostAdap
   created CCBs are added to Host Adapter's free list.
 */
 
-static void BusLogic_InitializeCCBs(struct BusLogic_HostAdapter *HostAdapter,
-				    void *BlockPointer, int BlockSize,
-				    dma_addr_t BlockPointerHandle)
+static void BusLogic_InitializeCCBs(struct BusLogic_HostAdapter *HostAdapter, void *BlockPointer, int BlockSize, dma_addr_t BlockPointerHandle)
 {
-  struct BusLogic_CCB *CCB = (struct BusLogic_CCB *) BlockPointer;
-  unsigned int offset = 0;
-  memset(BlockPointer, 0, BlockSize);
-  CCB->AllocationGroupHead = BlockPointerHandle;
-  CCB->AllocationGroupSize = BlockSize;
-  while ((BlockSize -= sizeof(struct BusLogic_CCB)) >= 0)
-    {
-      CCB->Status = BusLogic_CCB_Free;
-      CCB->HostAdapter = HostAdapter;
-      CCB->DMA_Handle = (u32)BlockPointerHandle + offset;
-      if (BusLogic_FlashPointHostAdapterP(HostAdapter))
-	{
-	  CCB->CallbackFunction = BusLogic_QueueCompletedCCB;
-	  CCB->BaseAddress = HostAdapter->FlashPointInfo.BaseAddress;
+	struct BusLogic_CCB *CCB = (struct BusLogic_CCB *) BlockPointer;
+	unsigned int offset = 0;
+	memset(BlockPointer, 0, BlockSize);
+	CCB->AllocationGroupHead = BlockPointerHandle;
+	CCB->AllocationGroupSize = BlockSize;
+	while ((BlockSize -= sizeof(struct BusLogic_CCB)) >= 0) {
+		CCB->Status = BusLogic_CCB_Free;
+		CCB->HostAdapter = HostAdapter;
+		CCB->DMA_Handle = (u32) BlockPointerHandle + offset;
+		if (BusLogic_FlashPointHostAdapterP(HostAdapter)) {
+			CCB->CallbackFunction = BusLogic_QueueCompletedCCB;
+			CCB->BaseAddress = HostAdapter->FlashPointInfo.BaseAddress;
+		}
+		CCB->Next = HostAdapter->Free_CCBs;
+		CCB->NextAll = HostAdapter->All_CCBs;
+		HostAdapter->Free_CCBs = CCB;
+		HostAdapter->All_CCBs = CCB;
+		HostAdapter->AllocatedCCBs++;
+		CCB++;
+		offset += sizeof(struct BusLogic_CCB);
 	}
-      CCB->Next = HostAdapter->Free_CCBs;
-      CCB->NextAll = HostAdapter->All_CCBs;
-      HostAdapter->Free_CCBs = CCB;
-      HostAdapter->All_CCBs = CCB;
-      HostAdapter->AllocatedCCBs++;
-      CCB++;
-      offset += sizeof(struct BusLogic_CCB);
-    }
 }
 
 
@@ -254,23 +237,18 @@ static void BusLogic_InitializeCCBs(struct BusLogic_HostAdapter *HostAdapter,
 
 static boolean __init BusLogic_CreateInitialCCBs(struct BusLogic_HostAdapter *HostAdapter)
 {
-  int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB);
-  void *BlockPointer;
-  dma_addr_t BlockPointerHandle;
-  while (HostAdapter->AllocatedCCBs < HostAdapter->InitialCCBs)
-    {
-      BlockPointer = pci_alloc_consistent(HostAdapter->PCI_Device, BlockSize,
-					  &BlockPointerHandle);
-      if (BlockPointer == NULL)
-	{
-	  BusLogic_Error("UNABLE TO ALLOCATE CCB GROUP - DETACHING\n",
-			 HostAdapter);
-	  return false;
+	int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB);
+	void *BlockPointer;
+	dma_addr_t BlockPointerHandle;
+	while (HostAdapter->AllocatedCCBs < HostAdapter->InitialCCBs) {
+		BlockPointer = pci_alloc_consistent(HostAdapter->PCI_Device, BlockSize, &BlockPointerHandle);
+		if (BlockPointer == NULL) {
+			BusLogic_Error("UNABLE TO ALLOCATE CCB GROUP - DETACHING\n", HostAdapter);
+			return false;
+		}
+		BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize, BlockPointerHandle);
 	}
-      BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize,
-			      BlockPointerHandle);
-    }
-  return true;
+	return true;
 }
 
 
@@ -280,25 +258,19 @@ static boolean __init BusLogic_CreateInitialCCBs(struct BusLogic_HostAdapter *Ho
 
 static void BusLogic_DestroyCCBs(struct BusLogic_HostAdapter *HostAdapter)
 {
-  struct BusLogic_CCB *NextCCB = HostAdapter->All_CCBs, *CCB, *Last_CCB = NULL;
-  HostAdapter->All_CCBs = NULL;
-  HostAdapter->Free_CCBs = NULL;
-  while ((CCB = NextCCB) != NULL)
-    {
-      NextCCB = CCB->NextAll;
-      if (CCB->AllocationGroupHead)
-	{
-	  if (Last_CCB)
-	    pci_free_consistent(HostAdapter->PCI_Device,
-				Last_CCB->AllocationGroupSize, Last_CCB,
-			 	Last_CCB->AllocationGroupHead);
-	  Last_CCB = CCB;
+	struct BusLogic_CCB *NextCCB = HostAdapter->All_CCBs, *CCB, *Last_CCB = NULL;
+	HostAdapter->All_CCBs = NULL;
+	HostAdapter->Free_CCBs = NULL;
+	while ((CCB = NextCCB) != NULL) {
+		NextCCB = CCB->NextAll;
+		if (CCB->AllocationGroupHead) {
+			if (Last_CCB)
+				pci_free_consistent(HostAdapter->PCI_Device, Last_CCB->AllocationGroupSize, Last_CCB, Last_CCB->AllocationGroupHead);
+			Last_CCB = CCB;
+		}
 	}
-    }
-  if (Last_CCB)
-    pci_free_consistent(HostAdapter->PCI_Device,
-			Last_CCB->AllocationGroupSize, Last_CCB,
-		 	Last_CCB->AllocationGroupHead);
+	if (Last_CCB)
+		pci_free_consistent(HostAdapter->PCI_Device, Last_CCB->AllocationGroupSize, Last_CCB, Last_CCB->AllocationGroupHead);
 }
 
 
@@ -309,40 +281,30 @@ static void BusLogic_DestroyCCBs(struct BusLogic_HostAdapter *HostAdapter)
   multiple host adapters share the same IRQ Channel.
 */
 
-static void BusLogic_CreateAdditionalCCBs(struct BusLogic_HostAdapter *HostAdapter,
-					  int AdditionalCCBs,
-					  boolean SuccessMessageP)
+static void BusLogic_CreateAdditionalCCBs(struct BusLogic_HostAdapter *HostAdapter, int AdditionalCCBs, boolean SuccessMessageP)
 {
-  int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB);
-  int PreviouslyAllocated = HostAdapter->AllocatedCCBs;
-  void *BlockPointer;
-  dma_addr_t BlockPointerHandle;
-  if (AdditionalCCBs <= 0) return;
-  while (HostAdapter->AllocatedCCBs - PreviouslyAllocated < AdditionalCCBs)
-    {
-      BlockPointer = pci_alloc_consistent(HostAdapter->PCI_Device, BlockSize,
-					  &BlockPointerHandle);
-      if (BlockPointer == NULL) break;
-      BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize,
-			      BlockPointerHandle);
-    }
-  if (HostAdapter->AllocatedCCBs > PreviouslyAllocated)
-    {
-      if (SuccessMessageP)
-	BusLogic_Notice("Allocated %d additional CCBs (total now %d)\n",
-			HostAdapter,
-			HostAdapter->AllocatedCCBs - PreviouslyAllocated,
-			HostAdapter->AllocatedCCBs);
-      return;
-    }
-  BusLogic_Notice("Failed to allocate additional CCBs\n", HostAdapter);
-  if (HostAdapter->DriverQueueDepth >
-      HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount)
-    {
-      HostAdapter->DriverQueueDepth =
-	HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount;
-      HostAdapter->SCSI_Host->can_queue = HostAdapter->DriverQueueDepth;
-    }
+	int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(struct BusLogic_CCB);
+	int PreviouslyAllocated = HostAdapter->AllocatedCCBs;
+	void *BlockPointer;
+	dma_addr_t BlockPointerHandle;
+	if (AdditionalCCBs <= 0)
+		return;
+	while (HostAdapter->AllocatedCCBs - PreviouslyAllocated < AdditionalCCBs) {
+		BlockPointer = pci_alloc_consistent(HostAdapter->PCI_Device, BlockSize, &BlockPointerHandle);
+		if (BlockPointer == NULL)
+			break;
+		BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize, BlockPointerHandle);
+	}
+	if (HostAdapter->AllocatedCCBs > PreviouslyAllocated) {
+		if (SuccessMessageP)
+			BusLogic_Notice("Allocated %d additional CCBs (total now %d)\n", HostAdapter, HostAdapter->AllocatedCCBs - PreviouslyAllocated, HostAdapter->AllocatedCCBs);
+		return;
+	}
+	BusLogic_Notice("Failed to allocate additional CCBs\n", HostAdapter);
+	if (HostAdapter->DriverQueueDepth > HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount) {
+		HostAdapter->DriverQueueDepth = HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount;
+		HostAdapter->SCSI_Host->can_queue = HostAdapter->DriverQueueDepth;
+	}
 }
 
 /*
@@ -352,31 +314,27 @@ static void BusLogic_CreateAdditionalCCBs(struct BusLogic_HostAdapter *HostAdapt
 */
 
 static struct BusLogic_CCB *BusLogic_AllocateCCB(struct BusLogic_HostAdapter
-					    *HostAdapter)
+						 *HostAdapter)
 {
-  static unsigned long SerialNumber = 0;
-  struct BusLogic_CCB *CCB;
-  CCB = HostAdapter->Free_CCBs;
-  if (CCB != NULL)
-    {
-      CCB->SerialNumber = ++SerialNumber;
-      HostAdapter->Free_CCBs = CCB->Next;
-      CCB->Next = NULL;
-      if (HostAdapter->Free_CCBs == NULL)
-	BusLogic_CreateAdditionalCCBs(HostAdapter,
-				      HostAdapter->IncrementalCCBs,
-				      true);
-      return CCB;
-    }
-  BusLogic_CreateAdditionalCCBs(HostAdapter,
-				HostAdapter->IncrementalCCBs,
-				true);
-  CCB = HostAdapter->Free_CCBs;
-  if (CCB == NULL) return NULL;
-  CCB->SerialNumber = ++SerialNumber;
-  HostAdapter->Free_CCBs = CCB->Next;
-  CCB->Next = NULL;
-  return CCB;
+	static unsigned long SerialNumber = 0;
+	struct BusLogic_CCB *CCB;
+	CCB = HostAdapter->Free_CCBs;
+	if (CCB != NULL) {
+		CCB->SerialNumber = ++SerialNumber;
+		HostAdapter->Free_CCBs = CCB->Next;
+		CCB->Next = NULL;
+		if (HostAdapter->Free_CCBs == NULL)
+			BusLogic_CreateAdditionalCCBs(HostAdapter, HostAdapter->IncrementalCCBs, true);
+		return CCB;
+	}
+	BusLogic_CreateAdditionalCCBs(HostAdapter, HostAdapter->IncrementalCCBs, true);
+	CCB = HostAdapter->Free_CCBs;
+	if (CCB == NULL)
+		return NULL;
+	CCB->SerialNumber = ++SerialNumber;
+	HostAdapter->Free_CCBs = CCB->Next;
+	CCB->Next = NULL;
+	return CCB;
 }
 
 
@@ -388,26 +346,17 @@ static struct BusLogic_CCB *BusLogic_AllocateCCB(struct BusLogic_HostAdapter
 
 static void BusLogic_DeallocateCCB(struct BusLogic_CCB *CCB)
 {
-  struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter;
-  if (CCB->Command->use_sg != 0)
-    {
-      pci_unmap_sg(HostAdapter->PCI_Device,
-		   (struct scatterlist *)CCB->Command->request_buffer,
-		   CCB->Command->use_sg,
-		   scsi_to_pci_dma_dir(CCB->Command->sc_data_direction));
-    }
-  else if (CCB->Command->request_bufflen != 0)
-    {
-      pci_unmap_single(HostAdapter->PCI_Device, CCB->DataPointer,
-		       CCB->DataLength,
-		       scsi_to_pci_dma_dir(CCB->Command->sc_data_direction));
-    }
-  pci_unmap_single(HostAdapter->PCI_Device, CCB->SenseDataPointer,
-		   CCB->SenseDataLength, PCI_DMA_FROMDEVICE);
-  CCB->Command = NULL;
-  CCB->Status = BusLogic_CCB_Free;
-  CCB->Next = HostAdapter->Free_CCBs;
-  HostAdapter->Free_CCBs = CCB;
+	struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter;
+	if (CCB->Command->use_sg != 0) {
+		pci_unmap_sg(HostAdapter->PCI_Device, (struct scatterlist *) CCB->Command->request_buffer, CCB->Command->use_sg, scsi_to_pci_dma_dir(CCB->Command->sc_data_direction));
+	} else if (CCB->Command->request_bufflen != 0) {
+		pci_unmap_single(HostAdapter->PCI_Device, CCB->DataPointer, CCB->DataLength, scsi_to_pci_dma_dir(CCB->Command->sc_data_direction));
+	}
+	pci_unmap_single(HostAdapter->PCI_Device, CCB->SenseDataPointer, CCB->SenseDataLength, PCI_DMA_FROMDEVICE);
+	CCB->Command = NULL;
+	CCB->Status = BusLogic_CCB_Free;
+	CCB->Next = HostAdapter->Free_CCBs;
+	HostAdapter->Free_CCBs = CCB;
 }
 
 
@@ -429,228 +378,205 @@ static void BusLogic_DeallocateCCB(struct BusLogic_CCB *CCB)
   waiting for the Host Adapter Ready bit to be set in the Status Register.
 */
 
-static int BusLogic_Command(struct BusLogic_HostAdapter *HostAdapter,
-			    enum BusLogic_OperationCode OperationCode,
-			    void *ParameterData,
-			    int ParameterLength,
-			    void *ReplyData,
-			    int ReplyLength)
+static int BusLogic_Command(struct BusLogic_HostAdapter *HostAdapter, enum BusLogic_OperationCode OperationCode, void *ParameterData, int ParameterLength, void *ReplyData, int ReplyLength)
 {
-  unsigned char *ParameterPointer = (unsigned char *) ParameterData;
-  unsigned char *ReplyPointer = (unsigned char *) ReplyData;
-  union BusLogic_StatusRegister StatusRegister;
-  union BusLogic_InterruptRegister InterruptRegister;
-  unsigned long ProcessorFlags = 0;
-  int ReplyBytes = 0, Result;
-  long TimeoutCounter;
-  /*
-    Clear out the Reply Data if provided.
-  */
-  if (ReplyLength > 0)
-    memset(ReplyData, 0, ReplyLength);
-  /*
-    If the IRQ Channel has not yet been acquired, then interrupts must be
-    disabled while issuing host adapter commands since a Command Complete
-    interrupt could occur if the IRQ Channel was previously enabled by another
-    BusLogic Host Adapter or another driver sharing the same IRQ Channel.
-  */
-  if (!HostAdapter->IRQ_ChannelAcquired)
-    {
-      local_irq_save(ProcessorFlags);
-      local_irq_disable();
-    }
-  /*
-    Wait for the Host Adapter Ready bit to be set and the Command/Parameter
-    Register Busy bit to be reset in the Status Register.
-  */
-  TimeoutCounter = 10000;
-  while (--TimeoutCounter >= 0)
-    {
-      StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
-      if (StatusRegister.sr.HostAdapterReady &&
-	  !StatusRegister.sr.CommandParameterRegisterBusy)
-	break;
-      udelay(100);
-    }
-  if (TimeoutCounter < 0)
-    {
-      BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready";
-      Result = -2;
-      goto Done;
-    }
-  /*
-    Write the OperationCode to the Command/Parameter Register.
-  */
-  HostAdapter->HostAdapterCommandCompleted = false;
-  BusLogic_WriteCommandParameterRegister(HostAdapter, OperationCode);
-  /*
-    Write any additional Parameter Bytes.
-  */
-  TimeoutCounter = 10000;
-  while (ParameterLength > 0 && --TimeoutCounter >= 0)
-    {
-      /*
-	Wait 100 microseconds to give the Host Adapter enough time to determine
-	whether the last value written to the Command/Parameter Register was
-	valid or not.  If the Command Complete bit is set in the Interrupt
-	Register, then the Command Invalid bit in the Status Register will be
-	reset if the Operation Code or Parameter was valid and the command
-	has completed, or set if the Operation Code or Parameter was invalid.
-	If the Data In Register Ready bit is set in the Status Register, then
-	the Operation Code was valid, and data is waiting to be read back
-	from the Host Adapter.  Otherwise, wait for the Command/Parameter
-	Register Busy bit in the Status Register to be reset.
-      */
-      udelay(100);
-      InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
-      StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
-      if (InterruptRegister.ir.CommandComplete) break;
-      if (HostAdapter->HostAdapterCommandCompleted) break;
-      if (StatusRegister.sr.DataInRegisterReady) break;
-      if (StatusRegister.sr.CommandParameterRegisterBusy) continue;
-      BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++);
-      ParameterLength--;
-    }
-  if (TimeoutCounter < 0)
-    {
-      BusLogic_CommandFailureReason =
-	"Timeout waiting for Parameter Acceptance";
-      Result = -2;
-      goto Done;
-    }
-  /*
-    The Modify I/O Address command does not cause a Command Complete Interrupt.
-  */
-  if (OperationCode == BusLogic_ModifyIOAddress)
-    {
-      StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
-      if (StatusRegister.sr.CommandInvalid)
-	{
-	  BusLogic_CommandFailureReason = "Modify I/O Address Invalid";
-	  Result = -1;
-	  goto Done;
+	unsigned char *ParameterPointer = (unsigned char *) ParameterData;
+	unsigned char *ReplyPointer = (unsigned char *) ReplyData;
+	union BusLogic_StatusRegister StatusRegister;
+	union BusLogic_InterruptRegister InterruptRegister;
+	unsigned long ProcessorFlags = 0;
+	int ReplyBytes = 0, Result;
+	long TimeoutCounter;
+	/*
+	   Clear out the Reply Data if provided.
+	 */
+	if (ReplyLength > 0)
+		memset(ReplyData, 0, ReplyLength);
+	/*
+	   If the IRQ Channel has not yet been acquired, then interrupts must be
+	   disabled while issuing host adapter commands since a Command Complete
+	   interrupt could occur if the IRQ Channel was previously enabled by another
+	   BusLogic Host Adapter or another driver sharing the same IRQ Channel.
+	 */
+	if (!HostAdapter->IRQ_ChannelAcquired) {
+		local_irq_save(ProcessorFlags);
+		local_irq_disable();
+	}
+	/*
+	   Wait for the Host Adapter Ready bit to be set and the Command/Parameter
+	   Register Busy bit to be reset in the Status Register.
+	 */
+	TimeoutCounter = 10000;
+	while (--TimeoutCounter >= 0) {
+		StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+		if (StatusRegister.sr.HostAdapterReady && !StatusRegister.sr.CommandParameterRegisterBusy)
+			break;
+		udelay(100);
+	}
+	if (TimeoutCounter < 0) {
+		BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready";
+		Result = -2;
+		goto Done;
+	}
+	/*
+	   Write the OperationCode to the Command/Parameter Register.
+	 */
+	HostAdapter->HostAdapterCommandCompleted = false;
+	BusLogic_WriteCommandParameterRegister(HostAdapter, OperationCode);
+	/*
+	   Write any additional Parameter Bytes.
+	 */
+	TimeoutCounter = 10000;
+	while (ParameterLength > 0 && --TimeoutCounter >= 0) {
+		/*
+		   Wait 100 microseconds to give the Host Adapter enough time to determine
+		   whether the last value written to the Command/Parameter Register was
+		   valid or not.  If the Command Complete bit is set in the Interrupt
+		   Register, then the Command Invalid bit in the Status Register will be
+		   reset if the Operation Code or Parameter was valid and the command
+		   has completed, or set if the Operation Code or Parameter was invalid.
+		   If the Data In Register Ready bit is set in the Status Register, then
+		   the Operation Code was valid, and data is waiting to be read back
+		   from the Host Adapter.  Otherwise, wait for the Command/Parameter
+		   Register Busy bit in the Status Register to be reset.
+		 */
+		udelay(100);
+		InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
+		StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+		if (InterruptRegister.ir.CommandComplete)
+			break;
+		if (HostAdapter->HostAdapterCommandCompleted)
+			break;
+		if (StatusRegister.sr.DataInRegisterReady)
+			break;
+		if (StatusRegister.sr.CommandParameterRegisterBusy)
+			continue;
+		BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++);
+		ParameterLength--;
 	}
-      if (BusLogic_GlobalOptions.TraceConfiguration)
-	BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: "
-			"(Modify I/O Address)\n", HostAdapter,
-			OperationCode, StatusRegister.All);
-      Result = 0;
-      goto Done;
-    }
-  /*
-    Select an appropriate timeout value for awaiting command completion.
-  */
-  switch (OperationCode)
-    {
-    case BusLogic_InquireInstalledDevicesID0to7:
-    case BusLogic_InquireInstalledDevicesID8to15:
-    case BusLogic_InquireTargetDevices:
-      /* Approximately 60 seconds. */
-      TimeoutCounter = 60*10000;
-      break;
-    default:
-      /* Approximately 1 second. */
-      TimeoutCounter = 10000;
-      break;
-    }
-  /*
-    Receive any Reply Bytes, waiting for either the Command Complete bit to
-    be set in the Interrupt Register, or for the Interrupt Handler to set the
-    Host Adapter Command Completed bit in the Host Adapter structure.
-  */
-  while (--TimeoutCounter >= 0)
-    {
-      InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
-      StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
-      if (InterruptRegister.ir.CommandComplete) break;
-      if (HostAdapter->HostAdapterCommandCompleted) break;
-      if (StatusRegister.sr.DataInRegisterReady)
-	{
-	  if (++ReplyBytes <= ReplyLength)
-	    *ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter);
-	  else BusLogic_ReadDataInRegister(HostAdapter);
+	if (TimeoutCounter < 0) {
+		BusLogic_CommandFailureReason = "Timeout waiting for Parameter Acceptance";
+		Result = -2;
+		goto Done;
 	}
-      if (OperationCode == BusLogic_FetchHostAdapterLocalRAM &&
-	  StatusRegister.sr.HostAdapterReady) break;
-      udelay(100);
-    }
-  if (TimeoutCounter < 0)
-    {
-      BusLogic_CommandFailureReason = "Timeout waiting for Command Complete";
-      Result = -2;
-      goto Done;
-    }
-  /*
-    Clear any pending Command Complete Interrupt.
-  */
-  BusLogic_InterruptReset(HostAdapter);
-  /*
-    Provide tracing information if requested.
-  */
-  if (BusLogic_GlobalOptions.TraceConfiguration)
-    {
-      int i;
-      BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: %2d ==> %2d:",
-		      HostAdapter, OperationCode,
-		      StatusRegister.All, ReplyLength, ReplyBytes);
-      if (ReplyLength > ReplyBytes) ReplyLength = ReplyBytes;
-      for (i = 0; i < ReplyLength; i++)
-	BusLogic_Notice(" %02X", HostAdapter,
-			((unsigned char *) ReplyData)[i]);
-      BusLogic_Notice("\n", HostAdapter);
-    }
-  /*
-    Process Command Invalid conditions.
-  */
-  if (StatusRegister.sr.CommandInvalid)
-    {
-      /*
-	Some early BusLogic Host Adapters may not recover properly from
-	a Command Invalid condition, so if this appears to be the case,
-	a Soft Reset is issued to the Host Adapter.  Potentially invalid
-	commands are never attempted after Mailbox Initialization is
-	performed, so there should be no Host Adapter state lost by a
-	Soft Reset in response to a Command Invalid condition.
-      */
-      udelay(1000);
-      StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
-      if (StatusRegister.sr.CommandInvalid ||
-	  StatusRegister.sr.Reserved ||
-	  StatusRegister.sr.DataInRegisterReady ||
-	  StatusRegister.sr.CommandParameterRegisterBusy ||
-	  !StatusRegister.sr.HostAdapterReady ||
-	  !StatusRegister.sr.InitializationRequired ||
-	  StatusRegister.sr.DiagnosticActive ||
-	  StatusRegister.sr.DiagnosticFailure)
-	{
-	  BusLogic_SoftReset(HostAdapter);
-	  udelay(1000);
+	/*
+	   The Modify I/O Address command does not cause a Command Complete Interrupt.
+	 */
+	if (OperationCode == BusLogic_ModifyIOAddress) {
+		StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+		if (StatusRegister.sr.CommandInvalid) {
+			BusLogic_CommandFailureReason = "Modify I/O Address Invalid";
+			Result = -1;
+			goto Done;
+		}
+		if (BusLogic_GlobalOptions.TraceConfiguration)
+			BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: " "(Modify I/O Address)\n", HostAdapter, OperationCode, StatusRegister.All);
+		Result = 0;
+		goto Done;
+	}
+	/*
+	   Select an appropriate timeout value for awaiting command completion.
+	 */
+	switch (OperationCode) {
+	case BusLogic_InquireInstalledDevicesID0to7:
+	case BusLogic_InquireInstalledDevicesID8to15:
+	case BusLogic_InquireTargetDevices:
+		/* Approximately 60 seconds. */
+		TimeoutCounter = 60 * 10000;
+		break;
+	default:
+		/* Approximately 1 second. */
+		TimeoutCounter = 10000;
+		break;
 	}
-      BusLogic_CommandFailureReason = "Command Invalid";
-      Result = -1;
-      goto Done;
-    }
-  /*
-    Handle Excess Parameters Supplied conditions.
-  */
-  if (ParameterLength > 0)
-    {
-      BusLogic_CommandFailureReason = "Excess Parameters Supplied";
-      Result = -1;
-      goto Done;
-    }
-  /*
-    Indicate the command completed successfully.
-  */
-  BusLogic_CommandFailureReason = NULL;
-  Result = ReplyBytes;
-  /*
-    Restore the interrupt status if necessary and return.
-  */
-Done:
-  if (!HostAdapter->IRQ_ChannelAcquired)
-    local_irq_restore(ProcessorFlags);
-  return Result;
+	/*
+	   Receive any Reply Bytes, waiting for either the Command Complete bit to
+	   be set in the Interrupt Register, or for the Interrupt Handler to set the
+	   Host Adapter Command Completed bit in the Host Adapter structure.
+	 */
+	while (--TimeoutCounter >= 0) {
+		InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
+		StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+		if (InterruptRegister.ir.CommandComplete)
+			break;
+		if (HostAdapter->HostAdapterCommandCompleted)
+			break;
+		if (StatusRegister.sr.DataInRegisterReady) {
+			if (++ReplyBytes <= ReplyLength)
+				*ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter);
+			else
+				BusLogic_ReadDataInRegister(HostAdapter);
+		}
+		if (OperationCode == BusLogic_FetchHostAdapterLocalRAM && StatusRegister.sr.HostAdapterReady)
+			break;
+		udelay(100);
+	}
+	if (TimeoutCounter < 0) {
+		BusLogic_CommandFailureReason = "Timeout waiting for Command Complete";
+		Result = -2;
+		goto Done;
+	}
+	/*
+	   Clear any pending Command Complete Interrupt.
+	 */
+	BusLogic_InterruptReset(HostAdapter);
+	/*
+	   Provide tracing information if requested.
+	 */
+	if (BusLogic_GlobalOptions.TraceConfiguration) {
+		int i;
+		BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: %2d ==> %2d:", HostAdapter, OperationCode, StatusRegister.All, ReplyLength, ReplyBytes);
+		if (ReplyLength > ReplyBytes)
+			ReplyLength = ReplyBytes;
+		for (i = 0; i < ReplyLength; i++)
+			BusLogic_Notice(" %02X", HostAdapter, ((unsigned char *) ReplyData)[i]);
+		BusLogic_Notice("\n", HostAdapter);
+	}
+	/*
+	   Process Command Invalid conditions.
+	 */
+	if (StatusRegister.sr.CommandInvalid) {
+		/*
+		   Some early BusLogic Host Adapters may not recover properly from
+		   a Command Invalid condition, so if this appears to be the case,
+		   a Soft Reset is issued to the Host Adapter.  Potentially invalid
+		   commands are never attempted after Mailbox Initialization is
+		   performed, so there should be no Host Adapter state lost by a
+		   Soft Reset in response to a Command Invalid condition.
+		 */
+		udelay(1000);
+		StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+		if (StatusRegister.sr.CommandInvalid ||
+		    StatusRegister.sr.Reserved ||
+		    StatusRegister.sr.DataInRegisterReady ||
+		    StatusRegister.sr.CommandParameterRegisterBusy || !StatusRegister.sr.HostAdapterReady || !StatusRegister.sr.InitializationRequired || StatusRegister.sr.DiagnosticActive || StatusRegister.sr.DiagnosticFailure) {
+			BusLogic_SoftReset(HostAdapter);
+			udelay(1000);
+		}
+		BusLogic_CommandFailureReason = "Command Invalid";
+		Result = -1;
+		goto Done;
+	}
+	/*
+	   Handle Excess Parameters Supplied conditions.
+	 */
+	if (ParameterLength > 0) {
+		BusLogic_CommandFailureReason = "Excess Parameters Supplied";
+		Result = -1;
+		goto Done;
+	}
+	/*
+	   Indicate the command completed successfully.
+	 */
+	BusLogic_CommandFailureReason = NULL;
+	Result = ReplyBytes;
+	/*
+	   Restore the interrupt status if necessary and return.
+	 */
+      Done:
+	if (!HostAdapter->IRQ_ChannelAcquired)
+		local_irq_restore(ProcessorFlags);
+	return Result;
 }
 
 
@@ -662,13 +588,14 @@ Done:
 
 static void __init BusLogic_AppendProbeAddressISA(unsigned long IO_Address)
 {
-  struct BusLogic_ProbeInfo *ProbeInfo;
-  if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters) return;
-  ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
-  ProbeInfo->HostAdapterType = BusLogic_MultiMaster;
-  ProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus;
-  ProbeInfo->IO_Address = IO_Address;
-  ProbeInfo->PCI_Device = NULL;
+	struct BusLogic_ProbeInfo *ProbeInfo;
+	if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters)
+		return;
+	ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
+	ProbeInfo->HostAdapterType = BusLogic_MultiMaster;
+	ProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus;
+	ProbeInfo->IO_Address = IO_Address;
+	ProbeInfo->PCI_Device = NULL;
 }
 
 
@@ -681,38 +608,27 @@ static void __init BusLogic_AppendProbeAddressISA(unsigned long IO_Address)
 static void __init BusLogic_InitializeProbeInfoListISA(struct BusLogic_HostAdapter
 						       *PrototypeHostAdapter)
 {
-  /*
-    If BusLogic Driver Options specifications requested that ISA Bus Probes
-    be inhibited, do not proceed further.
-  */
-  if (BusLogic_ProbeOptions.NoProbeISA) return;
-  /*
-    Append the list of standard BusLogic MultiMaster ISA I/O Addresses.
-  */
-  if (BusLogic_ProbeOptions.LimitedProbeISA
-      ? BusLogic_ProbeOptions.Probe330
-      : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0)
-    BusLogic_AppendProbeAddressISA(0x330);
-  if (BusLogic_ProbeOptions.LimitedProbeISA
-      ? BusLogic_ProbeOptions.Probe334
-      : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0)
-    BusLogic_AppendProbeAddressISA(0x334);
-  if (BusLogic_ProbeOptions.LimitedProbeISA
-      ? BusLogic_ProbeOptions.Probe230
-      : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0)
-    BusLogic_AppendProbeAddressISA(0x230);
-  if (BusLogic_ProbeOptions.LimitedProbeISA
-      ? BusLogic_ProbeOptions.Probe234
-      : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0)
-    BusLogic_AppendProbeAddressISA(0x234);
-  if (BusLogic_ProbeOptions.LimitedProbeISA
-      ? BusLogic_ProbeOptions.Probe130
-      : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0)
-    BusLogic_AppendProbeAddressISA(0x130);
-  if (BusLogic_ProbeOptions.LimitedProbeISA
-      ? BusLogic_ProbeOptions.Probe134
-      : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0)
-    BusLogic_AppendProbeAddressISA(0x134);
+	/*
+	   If BusLogic Driver Options specifications requested that ISA Bus Probes
+	   be inhibited, do not proceed further.
+	 */
+	if (BusLogic_ProbeOptions.NoProbeISA)
+		return;
+	/*
+	   Append the list of standard BusLogic MultiMaster ISA I/O Addresses.
+	 */
+	if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe330 : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0)
+		BusLogic_AppendProbeAddressISA(0x330);
+	if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe334 : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0)
+		BusLogic_AppendProbeAddressISA(0x334);
+	if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe230 : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0)
+		BusLogic_AppendProbeAddressISA(0x230);
+	if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe234 : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0)
+		BusLogic_AppendProbeAddressISA(0x234);
+	if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe130 : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0)
+		BusLogic_AppendProbeAddressISA(0x130);
+	if (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe134 : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0)
+		BusLogic_AppendProbeAddressISA(0x134);
 }
 
 
@@ -724,30 +640,24 @@ static void __init BusLogic_InitializeProbeInfoListISA(struct BusLogic_HostAdapt
   of increasing PCI Bus and Device Number.
 */
 
-static void __init BusLogic_SortProbeInfo(struct BusLogic_ProbeInfo *ProbeInfoList,
-					  int ProbeInfoCount)
+static void __init BusLogic_SortProbeInfo(struct BusLogic_ProbeInfo *ProbeInfoList, int ProbeInfoCount)
 {
-  int LastInterchange = ProbeInfoCount-1, Bound, j;
-  while (LastInterchange > 0)
-    {
-      Bound = LastInterchange;
-      LastInterchange = 0;
-      for (j = 0; j < Bound; j++)
-	{
-	  struct BusLogic_ProbeInfo *ProbeInfo1 = &ProbeInfoList[j];
-	  struct BusLogic_ProbeInfo *ProbeInfo2 = &ProbeInfoList[j+1];
-	  if (ProbeInfo1->Bus > ProbeInfo2->Bus ||
-	      (ProbeInfo1->Bus == ProbeInfo2->Bus &&
-	       (ProbeInfo1->Device > ProbeInfo2->Device)))
-	    {
-	      struct BusLogic_ProbeInfo TempProbeInfo;
-	      memcpy(&TempProbeInfo, ProbeInfo1, sizeof(struct BusLogic_ProbeInfo));
-	      memcpy(ProbeInfo1, ProbeInfo2, sizeof(struct BusLogic_ProbeInfo));
-	      memcpy(ProbeInfo2, &TempProbeInfo, sizeof(struct BusLogic_ProbeInfo));
-	      LastInterchange = j;
-	    }
+	int LastInterchange = ProbeInfoCount - 1, Bound, j;
+	while (LastInterchange > 0) {
+		Bound = LastInterchange;
+		LastInterchange = 0;
+		for (j = 0; j < Bound; j++) {
+			struct BusLogic_ProbeInfo *ProbeInfo1 = &ProbeInfoList[j];
+			struct BusLogic_ProbeInfo *ProbeInfo2 = &ProbeInfoList[j + 1];
+			if (ProbeInfo1->Bus > ProbeInfo2->Bus || (ProbeInfo1->Bus == ProbeInfo2->Bus && (ProbeInfo1->Device > ProbeInfo2->Device))) {
+				struct BusLogic_ProbeInfo TempProbeInfo;
+				memcpy(&TempProbeInfo, ProbeInfo1, sizeof(struct BusLogic_ProbeInfo));
+				memcpy(ProbeInfo1, ProbeInfo2, sizeof(struct BusLogic_ProbeInfo));
+				memcpy(ProbeInfo2, &TempProbeInfo, sizeof(struct BusLogic_ProbeInfo));
+				LastInterchange = j;
+			}
+		}
 	}
-    }
 }
 
 
@@ -762,292 +672,226 @@ static void __init BusLogic_SortProbeInfo(struct BusLogic_ProbeInfo *ProbeInfoLi
 static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAdapter
 							  *PrototypeHostAdapter)
 {
-  struct BusLogic_ProbeInfo *PrimaryProbeInfo =
-    &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount];
-  int NonPrimaryPCIMultiMasterIndex = BusLogic_ProbeInfoCount + 1;
-  int NonPrimaryPCIMultiMasterCount = 0, PCIMultiMasterCount = 0;
-  boolean ForceBusDeviceScanningOrder = false;
-  boolean ForceBusDeviceScanningOrderChecked = false;
-  boolean StandardAddressSeen[6];
-  struct pci_dev *PCI_Device = NULL;
-  int i;
-  if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters) return 0;
-  BusLogic_ProbeInfoCount++;
-  for (i = 0; i < 6; i++)
-    StandardAddressSeen[i] = false;
-  /*
-    Iterate over the MultiMaster PCI Host Adapters.  For each enumerated host
-    adapter, determine whether its ISA Compatible I/O Port is enabled and if
-    so, whether it is assigned the Primary I/O Address.  A host adapter that is
-    assigned the Primary I/O Address will always be the preferred boot device.
-    The MultiMaster BIOS will first recognize a host adapter at the Primary I/O
-    Address, then any other PCI host adapters, and finally any host adapters
-    located at the remaining standard ISA I/O Addresses.  When a PCI host
-    adapter is found with its ISA Compatible I/O Port enabled, a command is
-    issued to disable the ISA Compatible I/O Port, and it is noted that the
-    particular standard ISA I/O Address need not be probed.
-  */
-  PrimaryProbeInfo->IO_Address = 0;
-  while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC,
-				       PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER,
-				       PCI_Device)) != NULL)
-    {
-      struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter;
-      struct BusLogic_PCIHostAdapterInformation PCIHostAdapterInformation;
-      enum BusLogic_ISACompatibleIOPort ModifyIOAddressRequest;
-      unsigned char Bus;
-      unsigned char Device;
-      unsigned int IRQ_Channel;
-      unsigned long BaseAddress0;
-      unsigned long BaseAddress1;
-      unsigned long IO_Address;
-      unsigned long PCI_Address;
-
-      if (pci_enable_device(PCI_Device))
-      	continue;
-
-      if (pci_set_dma_mask(PCI_Device, (u64)0xffffffff))
-	continue;
-      
-      Bus = PCI_Device->bus->number;
-      Device = PCI_Device->devfn >> 3;
-      IRQ_Channel = PCI_Device->irq;
-      IO_Address  = BaseAddress0 = pci_resource_start(PCI_Device, 0);
-      PCI_Address = BaseAddress1 = pci_resource_start(PCI_Device, 1);
-
-      if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM)
-	{
-	  BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for "
-			 "MultiMaster Host Adapter\n", NULL, BaseAddress0);
-	  BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n",
-			 NULL, Bus, Device, IO_Address);
-	  continue;
-	}
-      if (pci_resource_flags(PCI_Device,1) & IORESOURCE_IO)
-	{
-	  BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for "
-			 "MultiMaster Host Adapter\n", NULL, BaseAddress1);
-	  BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n",
-			 NULL, Bus, Device, PCI_Address);
-	  continue;
-	}
-      if (IRQ_Channel == 0)
-	{
-	  BusLogic_Error("BusLogic: IRQ Channel %d invalid for "
-			 "MultiMaster Host Adapter\n", NULL, IRQ_Channel);
-	  BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n",
-			 NULL, Bus, Device, IO_Address);
-	  continue;
-	}
-      if (BusLogic_GlobalOptions.TraceProbe)
-	{
-	  BusLogic_Notice("BusLogic: PCI MultiMaster Host Adapter "
-			  "detected at\n", NULL);
-	  BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address "
-			  "0x%X PCI Address 0x%X\n", NULL,
-			  Bus, Device, IO_Address, PCI_Address);
-	}
-      /*
-	Issue the Inquire PCI Host Adapter Information command to determine
-	the ISA Compatible I/O Port.  If the ISA Compatible I/O Port is
-	known and enabled, note that the particular Standard ISA I/O
-	Address should not be probed.
-      */
-      HostAdapter->IO_Address = IO_Address;
-      BusLogic_InterruptReset(HostAdapter);
-      if (BusLogic_Command(HostAdapter,
-			   BusLogic_InquirePCIHostAdapterInformation,
-			   NULL, 0, &PCIHostAdapterInformation,
-			   sizeof(PCIHostAdapterInformation))
-	  == sizeof(PCIHostAdapterInformation))
-	{
-	  if (PCIHostAdapterInformation.ISACompatibleIOPort < 6)
-	    StandardAddressSeen[PCIHostAdapterInformation
-				.ISACompatibleIOPort] = true;
-	}
-      else PCIHostAdapterInformation.ISACompatibleIOPort =
-	     BusLogic_IO_Disable;
-      /*
-       * Issue the Modify I/O Address command to disable the ISA Compatible
-       * I/O Port.  On PCI Host Adapters, the Modify I/O Address command
-       * allows modification of the ISA compatible I/O Address that the Host
-       * Adapter responds to; it does not affect the PCI compliant I/O Address
-       * assigned at system initialization.
-       */
-      ModifyIOAddressRequest = BusLogic_IO_Disable;
-      BusLogic_Command(HostAdapter, BusLogic_ModifyIOAddress,
-		       &ModifyIOAddressRequest,
-		       sizeof(ModifyIOAddressRequest), NULL, 0);
-      /*
-	For the first MultiMaster Host Adapter enumerated, issue the Fetch
-	Host Adapter Local RAM command to read byte 45 of the AutoSCSI area,
-	for the setting of the "Use Bus And Device # For PCI Scanning Seq."
-	option.  Issue the Inquire Board ID command since this option is
-	only valid for the BT-948/958/958D.
-      */
-      if (!ForceBusDeviceScanningOrderChecked)
-	{
-	  struct BusLogic_FetchHostAdapterLocalRAMRequest
-	    FetchHostAdapterLocalRAMRequest;
-	  struct BusLogic_AutoSCSIByte45 AutoSCSIByte45;
-	  struct BusLogic_BoardID BoardID;
-	  FetchHostAdapterLocalRAMRequest.ByteOffset =
-	    BusLogic_AutoSCSI_BaseOffset + 45;
-	  FetchHostAdapterLocalRAMRequest.ByteCount =
-	    sizeof(AutoSCSIByte45);
-	  BusLogic_Command(HostAdapter,
-			   BusLogic_FetchHostAdapterLocalRAM,
-			   &FetchHostAdapterLocalRAMRequest,
-			   sizeof(FetchHostAdapterLocalRAMRequest),
-			   &AutoSCSIByte45, sizeof(AutoSCSIByte45));
-	  BusLogic_Command(HostAdapter, BusLogic_InquireBoardID,
-			   NULL, 0, &BoardID, sizeof(BoardID));
-	  if (BoardID.FirmwareVersion1stDigit == '5')
-	    ForceBusDeviceScanningOrder =
-	      AutoSCSIByte45.ForceBusDeviceScanningOrder;
-	  ForceBusDeviceScanningOrderChecked = true;
-	}
-      /*
-	Determine whether this MultiMaster Host Adapter has its ISA
-	Compatible I/O Port enabled and is assigned the Primary I/O Address.
-	If it does, then it is the Primary MultiMaster Host Adapter and must
-	be recognized first.  If it does not, then it is added to the list
-	for probing after any Primary MultiMaster Host Adapter is probed.
-      */
-      if (PCIHostAdapterInformation.ISACompatibleIOPort == BusLogic_IO_330)
-	{
-	  PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster;
-	  PrimaryProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
-	  PrimaryProbeInfo->IO_Address = IO_Address;
-	  PrimaryProbeInfo->PCI_Address = PCI_Address;
-	  PrimaryProbeInfo->Bus = Bus;
-	  PrimaryProbeInfo->Device = Device;
-	  PrimaryProbeInfo->IRQ_Channel = IRQ_Channel;
-	  PrimaryProbeInfo->PCI_Device = PCI_Device;
-	  PCIMultiMasterCount++;
+	struct BusLogic_ProbeInfo *PrimaryProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount];
+	int NonPrimaryPCIMultiMasterIndex = BusLogic_ProbeInfoCount + 1;
+	int NonPrimaryPCIMultiMasterCount = 0, PCIMultiMasterCount = 0;
+	boolean ForceBusDeviceScanningOrder = false;
+	boolean ForceBusDeviceScanningOrderChecked = false;
+	boolean StandardAddressSeen[6];
+	struct pci_dev *PCI_Device = NULL;
+	int i;
+	if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters)
+		return 0;
+	BusLogic_ProbeInfoCount++;
+	for (i = 0; i < 6; i++)
+		StandardAddressSeen[i] = false;
+	/*
+	   Iterate over the MultiMaster PCI Host Adapters.  For each enumerated host
+	   adapter, determine whether its ISA Compatible I/O Port is enabled and if
+	   so, whether it is assigned the Primary I/O Address.  A host adapter that is
+	   assigned the Primary I/O Address will always be the preferred boot device.
+	   The MultiMaster BIOS will first recognize a host adapter at the Primary I/O
+	   Address, then any other PCI host adapters, and finally any host adapters
+	   located at the remaining standard ISA I/O Addresses.  When a PCI host
+	   adapter is found with its ISA Compatible I/O Port enabled, a command is
+	   issued to disable the ISA Compatible I/O Port, and it is noted that the
+	   particular standard ISA I/O Address need not be probed.
+	 */
+	PrimaryProbeInfo->IO_Address = 0;
+	while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER, PCI_Device)) != NULL) {
+		struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter;
+		struct BusLogic_PCIHostAdapterInformation PCIHostAdapterInformation;
+		enum BusLogic_ISACompatibleIOPort ModifyIOAddressRequest;
+		unsigned char Bus;
+		unsigned char Device;
+		unsigned int IRQ_Channel;
+		unsigned long BaseAddress0;
+		unsigned long BaseAddress1;
+		unsigned long IO_Address;
+		unsigned long PCI_Address;
+
+		if (pci_enable_device(PCI_Device))
+			continue;
+
+		if (pci_set_dma_mask(PCI_Device, (u64) 0xffffffff))
+			continue;
+
+		Bus = PCI_Device->bus->number;
+		Device = PCI_Device->devfn >> 3;
+		IRQ_Channel = PCI_Device->irq;
+		IO_Address = BaseAddress0 = pci_resource_start(PCI_Device, 0);
+		PCI_Address = BaseAddress1 = pci_resource_start(PCI_Device, 1);
+
+		if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM) {
+			BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " "MultiMaster Host Adapter\n", NULL, BaseAddress0);
+			BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address);
+			continue;
+		}
+		if (pci_resource_flags(PCI_Device, 1) & IORESOURCE_IO) {
+			BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for " "MultiMaster Host Adapter\n", NULL, BaseAddress1);
+			BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n", NULL, Bus, Device, PCI_Address);
+			continue;
+		}
+		if (IRQ_Channel == 0) {
+			BusLogic_Error("BusLogic: IRQ Channel %d invalid for " "MultiMaster Host Adapter\n", NULL, IRQ_Channel);
+			BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address);
+			continue;
+		}
+		if (BusLogic_GlobalOptions.TraceProbe) {
+			BusLogic_Notice("BusLogic: PCI MultiMaster Host Adapter " "detected at\n", NULL);
+			BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address " "0x%X PCI Address 0x%X\n", NULL, Bus, Device, IO_Address, PCI_Address);
+		}
+		/*
+		   Issue the Inquire PCI Host Adapter Information command to determine
+		   the ISA Compatible I/O Port.  If the ISA Compatible I/O Port is
+		   known and enabled, note that the particular Standard ISA I/O
+		   Address should not be probed.
+		 */
+		HostAdapter->IO_Address = IO_Address;
+		BusLogic_InterruptReset(HostAdapter);
+		if (BusLogic_Command(HostAdapter, BusLogic_InquirePCIHostAdapterInformation, NULL, 0, &PCIHostAdapterInformation, sizeof(PCIHostAdapterInformation))
+		    == sizeof(PCIHostAdapterInformation)) {
+			if (PCIHostAdapterInformation.ISACompatibleIOPort < 6)
+				StandardAddressSeen[PCIHostAdapterInformation.ISACompatibleIOPort] = true;
+		} else
+			PCIHostAdapterInformation.ISACompatibleIOPort = BusLogic_IO_Disable;
+		/*
+		 * Issue the Modify I/O Address command to disable the ISA Compatible
+		 * I/O Port.  On PCI Host Adapters, the Modify I/O Address command
+		 * allows modification of the ISA compatible I/O Address that the Host
+		 * Adapter responds to; it does not affect the PCI compliant I/O Address
+		 * assigned at system initialization.
+		 */
+		ModifyIOAddressRequest = BusLogic_IO_Disable;
+		BusLogic_Command(HostAdapter, BusLogic_ModifyIOAddress, &ModifyIOAddressRequest, sizeof(ModifyIOAddressRequest), NULL, 0);
+		/*
+		   For the first MultiMaster Host Adapter enumerated, issue the Fetch
+		   Host Adapter Local RAM command to read byte 45 of the AutoSCSI area,
+		   for the setting of the "Use Bus And Device # For PCI Scanning Seq."
+		   option.  Issue the Inquire Board ID command since this option is
+		   only valid for the BT-948/958/958D.
+		 */
+		if (!ForceBusDeviceScanningOrderChecked) {
+			struct BusLogic_FetchHostAdapterLocalRAMRequest FetchHostAdapterLocalRAMRequest;
+			struct BusLogic_AutoSCSIByte45 AutoSCSIByte45;
+			struct BusLogic_BoardID BoardID;
+			FetchHostAdapterLocalRAMRequest.ByteOffset = BusLogic_AutoSCSI_BaseOffset + 45;
+			FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIByte45);
+			BusLogic_Command(HostAdapter, BusLogic_FetchHostAdapterLocalRAM, &FetchHostAdapterLocalRAMRequest, sizeof(FetchHostAdapterLocalRAMRequest), &AutoSCSIByte45, sizeof(AutoSCSIByte45));
+			BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, NULL, 0, &BoardID, sizeof(BoardID));
+			if (BoardID.FirmwareVersion1stDigit == '5')
+				ForceBusDeviceScanningOrder = AutoSCSIByte45.ForceBusDeviceScanningOrder;
+			ForceBusDeviceScanningOrderChecked = true;
+		}
+		/*
+		   Determine whether this MultiMaster Host Adapter has its ISA
+		   Compatible I/O Port enabled and is assigned the Primary I/O Address.
+		   If it does, then it is the Primary MultiMaster Host Adapter and must
+		   be recognized first.  If it does not, then it is added to the list
+		   for probing after any Primary MultiMaster Host Adapter is probed.
+		 */
+		if (PCIHostAdapterInformation.ISACompatibleIOPort == BusLogic_IO_330) {
+			PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster;
+			PrimaryProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
+			PrimaryProbeInfo->IO_Address = IO_Address;
+			PrimaryProbeInfo->PCI_Address = PCI_Address;
+			PrimaryProbeInfo->Bus = Bus;
+			PrimaryProbeInfo->Device = Device;
+			PrimaryProbeInfo->IRQ_Channel = IRQ_Channel;
+			PrimaryProbeInfo->PCI_Device = PCI_Device;
+			PCIMultiMasterCount++;
+		} else if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters) {
+			struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
+			ProbeInfo->HostAdapterType = BusLogic_MultiMaster;
+			ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
+			ProbeInfo->IO_Address = IO_Address;
+			ProbeInfo->PCI_Address = PCI_Address;
+			ProbeInfo->Bus = Bus;
+			ProbeInfo->Device = Device;
+			ProbeInfo->IRQ_Channel = IRQ_Channel;
+			ProbeInfo->PCI_Device = PCI_Device;
+			NonPrimaryPCIMultiMasterCount++;
+			PCIMultiMasterCount++;
+		} else
+			BusLogic_Warning("BusLogic: Too many Host Adapters " "detected\n", NULL);
 	}
-      else if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters)
-	{
-	  struct BusLogic_ProbeInfo *ProbeInfo =
-	    &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
-	  ProbeInfo->HostAdapterType = BusLogic_MultiMaster;
-	  ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
-	  ProbeInfo->IO_Address = IO_Address;
-	  ProbeInfo->PCI_Address = PCI_Address;
-	  ProbeInfo->Bus = Bus;
-	  ProbeInfo->Device = Device;
-	  ProbeInfo->IRQ_Channel = IRQ_Channel;
-	  ProbeInfo->PCI_Device = PCI_Device;
-	  NonPrimaryPCIMultiMasterCount++;
-	  PCIMultiMasterCount++;
+	/*
+	   If the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option is ON
+	   for the first enumerated MultiMaster Host Adapter, and if that host adapter
+	   is a BT-948/958/958D, then the MultiMaster BIOS will recognize MultiMaster
+	   Host Adapters in the order of increasing PCI Bus and Device Number.  In
+	   that case, sort the probe information into the same order the BIOS uses.
+	   If this option is OFF, then the MultiMaster BIOS will recognize MultiMaster
+	   Host Adapters in the order they are enumerated by the PCI BIOS, and hence
+	   no sorting is necessary.
+	 */
+	if (ForceBusDeviceScanningOrder)
+		BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[NonPrimaryPCIMultiMasterIndex], NonPrimaryPCIMultiMasterCount);
+	/*
+	   If no PCI MultiMaster Host Adapter is assigned the Primary I/O Address,
+	   then the Primary I/O Address must be probed explicitly before any PCI
+	   host adapters are probed.
+	 */
+	if (!BusLogic_ProbeOptions.NoProbeISA)
+		if (PrimaryProbeInfo->IO_Address == 0 && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe330 : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0)) {
+			PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster;
+			PrimaryProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus;
+			PrimaryProbeInfo->IO_Address = 0x330;
+		}
+	/*
+	   Append the list of standard BusLogic MultiMaster ISA I/O Addresses,
+	   omitting the Primary I/O Address which has already been handled.
+	 */
+	if (!BusLogic_ProbeOptions.NoProbeISA) {
+		if (!StandardAddressSeen[1] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe334 : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0))
+			BusLogic_AppendProbeAddressISA(0x334);
+		if (!StandardAddressSeen[2] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe230 : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0))
+			BusLogic_AppendProbeAddressISA(0x230);
+		if (!StandardAddressSeen[3] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe234 : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0))
+			BusLogic_AppendProbeAddressISA(0x234);
+		if (!StandardAddressSeen[4] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe130 : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0))
+			BusLogic_AppendProbeAddressISA(0x130);
+		if (!StandardAddressSeen[5] && (BusLogic_ProbeOptions.LimitedProbeISA ? BusLogic_ProbeOptions.Probe134 : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0))
+			BusLogic_AppendProbeAddressISA(0x134);
 	}
-      else BusLogic_Warning("BusLogic: Too many Host Adapters "
-			    "detected\n", NULL);
-    }
-  /*
-    If the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option is ON
-    for the first enumerated MultiMaster Host Adapter, and if that host adapter
-    is a BT-948/958/958D, then the MultiMaster BIOS will recognize MultiMaster
-    Host Adapters in the order of increasing PCI Bus and Device Number.  In
-    that case, sort the probe information into the same order the BIOS uses.
-    If this option is OFF, then the MultiMaster BIOS will recognize MultiMaster
-    Host Adapters in the order they are enumerated by the PCI BIOS, and hence
-    no sorting is necessary.
-  */
-  if (ForceBusDeviceScanningOrder)
-    BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[
-			      NonPrimaryPCIMultiMasterIndex],
-			   NonPrimaryPCIMultiMasterCount);
-  /*
-    If no PCI MultiMaster Host Adapter is assigned the Primary I/O Address,
-    then the Primary I/O Address must be probed explicitly before any PCI
-    host adapters are probed.
-  */
-  if (!BusLogic_ProbeOptions.NoProbeISA)
-    if (PrimaryProbeInfo->IO_Address == 0 &&
-	(BusLogic_ProbeOptions.LimitedProbeISA
-	 ? BusLogic_ProbeOptions.Probe330
-	 : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0))
-      {
-	PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster;
-	PrimaryProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus;
-	PrimaryProbeInfo->IO_Address = 0x330;
-      }
-  /*
-    Append the list of standard BusLogic MultiMaster ISA I/O Addresses,
-    omitting the Primary I/O Address which has already been handled.
-  */
-  if (!BusLogic_ProbeOptions.NoProbeISA)
-    {
-      if (!StandardAddressSeen[1] &&
-	  (BusLogic_ProbeOptions.LimitedProbeISA
-	   ? BusLogic_ProbeOptions.Probe334
-	   : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0))
-	BusLogic_AppendProbeAddressISA(0x334);
-      if (!StandardAddressSeen[2] &&
-	  (BusLogic_ProbeOptions.LimitedProbeISA
-	   ? BusLogic_ProbeOptions.Probe230
-	   : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0))
-	BusLogic_AppendProbeAddressISA(0x230);
-      if (!StandardAddressSeen[3] &&
-	  (BusLogic_ProbeOptions.LimitedProbeISA
-	   ? BusLogic_ProbeOptions.Probe234
-	   : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0))
-	BusLogic_AppendProbeAddressISA(0x234);
-      if (!StandardAddressSeen[4] &&
-	  (BusLogic_ProbeOptions.LimitedProbeISA
-	   ? BusLogic_ProbeOptions.Probe130
-	   : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0))
-	BusLogic_AppendProbeAddressISA(0x130);
-      if (!StandardAddressSeen[5] &&
-	  (BusLogic_ProbeOptions.LimitedProbeISA
-	   ? BusLogic_ProbeOptions.Probe134
-	   : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0))
-	BusLogic_AppendProbeAddressISA(0x134);
-    }
-  /*
-    Iterate over the older non-compliant MultiMaster PCI Host Adapters,
-    noting the PCI bus location and assigned IRQ Channel.
-  */
-  PCI_Device = NULL;
-  while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC,
-				       PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC,
-				       PCI_Device)) != NULL)
-    {
-      unsigned char Bus;
-      unsigned char Device;
-      unsigned int IRQ_Channel;
-      unsigned long IO_Address;
-
-      if (pci_enable_device(PCI_Device))
-	continue;
-
-      if (pci_set_dma_mask(PCI_Device, (u64)0xffffffff))
-	continue;
-
-      Bus = PCI_Device->bus->number;
-      Device = PCI_Device->devfn >> 3;
-      IRQ_Channel = PCI_Device->irq;
-      IO_Address = pci_resource_start(PCI_Device, 0);
-
-      if (IO_Address == 0 || IRQ_Channel == 0) continue;
-      for (i = 0; i < BusLogic_ProbeInfoCount; i++)
-	{
-	  struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[i];
-	  if (ProbeInfo->IO_Address == IO_Address &&
-	      ProbeInfo->HostAdapterType == BusLogic_MultiMaster)
-	    {
-	      ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
-	      ProbeInfo->PCI_Address = 0;
-	      ProbeInfo->Bus = Bus;
-	      ProbeInfo->Device = Device;
-	      ProbeInfo->IRQ_Channel = IRQ_Channel;
-	      ProbeInfo->PCI_Device = PCI_Device;
-	      break;
-	    }
+	/*
+	   Iterate over the older non-compliant MultiMaster PCI Host Adapters,
+	   noting the PCI bus location and assigned IRQ Channel.
+	 */
+	PCI_Device = NULL;
+	while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC, PCI_Device)) != NULL) {
+		unsigned char Bus;
+		unsigned char Device;
+		unsigned int IRQ_Channel;
+		unsigned long IO_Address;
+
+		if (pci_enable_device(PCI_Device))
+			continue;
+
+		if (pci_set_dma_mask(PCI_Device, (u64) 0xffffffff))
+			continue;
+
+		Bus = PCI_Device->bus->number;
+		Device = PCI_Device->devfn >> 3;
+		IRQ_Channel = PCI_Device->irq;
+		IO_Address = pci_resource_start(PCI_Device, 0);
+
+		if (IO_Address == 0 || IRQ_Channel == 0)
+			continue;
+		for (i = 0; i < BusLogic_ProbeInfoCount; i++) {
+			struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[i];
+			if (ProbeInfo->IO_Address == IO_Address && ProbeInfo->HostAdapterType == BusLogic_MultiMaster) {
+				ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
+				ProbeInfo->PCI_Address = 0;
+				ProbeInfo->Bus = Bus;
+				ProbeInfo->Device = Device;
+				ProbeInfo->IRQ_Channel = IRQ_Channel;
+				ProbeInfo->PCI_Device = PCI_Device;
+				break;
+			}
+		}
 	}
-    }
-  return PCIMultiMasterCount;
+	return PCIMultiMasterCount;
 }
 
 
@@ -1061,100 +905,77 @@ static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAd
 static int __init BusLogic_InitializeFlashPointProbeInfo(struct BusLogic_HostAdapter
 							 *PrototypeHostAdapter)
 {
-  int FlashPointIndex = BusLogic_ProbeInfoCount, FlashPointCount = 0;
-  struct pci_dev *PCI_Device = NULL;
-  /*
-    Interrogate PCI Configuration Space for any FlashPoint Host Adapters.
-  */
-  while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC,
-				       PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT,
-				       PCI_Device)) != NULL)
-    {
-      unsigned char Bus;
-      unsigned char Device;
-      unsigned int IRQ_Channel;
-      unsigned long BaseAddress0;
-      unsigned long BaseAddress1;
-      unsigned long IO_Address;
-      unsigned long PCI_Address;
-
-      if (pci_enable_device(PCI_Device))
-	continue;
-
-      if (pci_set_dma_mask(PCI_Device, (u64)0xffffffff))
-	continue;
-
-      Bus = PCI_Device->bus->number;
-      Device = PCI_Device->devfn >> 3;
-      IRQ_Channel = PCI_Device->irq;
-      IO_Address = BaseAddress0 = pci_resource_start(PCI_Device, 0);
-      PCI_Address = BaseAddress1 = pci_resource_start(PCI_Device, 1);
+	int FlashPointIndex = BusLogic_ProbeInfoCount, FlashPointCount = 0;
+	struct pci_dev *PCI_Device = NULL;
+	/*
+	   Interrogate PCI Configuration Space for any FlashPoint Host Adapters.
+	 */
+	while ((PCI_Device = pci_find_device(PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT, PCI_Device)) != NULL) {
+		unsigned char Bus;
+		unsigned char Device;
+		unsigned int IRQ_Channel;
+		unsigned long BaseAddress0;
+		unsigned long BaseAddress1;
+		unsigned long IO_Address;
+		unsigned long PCI_Address;
+
+		if (pci_enable_device(PCI_Device))
+			continue;
+
+		if (pci_set_dma_mask(PCI_Device, (u64) 0xffffffff))
+			continue;
+
+		Bus = PCI_Device->bus->number;
+		Device = PCI_Device->devfn >> 3;
+		IRQ_Channel = PCI_Device->irq;
+		IO_Address = BaseAddress0 = pci_resource_start(PCI_Device, 0);
+		PCI_Address = BaseAddress1 = pci_resource_start(PCI_Device, 1);
 #ifndef CONFIG_SCSI_OMIT_FLASHPOINT
-      if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM)
-	{
-	  BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for "
-			 "FlashPoint Host Adapter\n", NULL, BaseAddress0);
-	  BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n",
-			 NULL, Bus, Device, IO_Address);
-	  continue;
-	}
-      if (pci_resource_flags(PCI_Device, 1) & IORESOURCE_IO)
-	{
-	  BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for "
-			 "FlashPoint Host Adapter\n", NULL, BaseAddress1);
-	  BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n",
-			 NULL, Bus, Device, PCI_Address);
-	  continue;
-	}
-      if (IRQ_Channel == 0)
-	{
-	  BusLogic_Error("BusLogic: IRQ Channel %d invalid for "
-			 "FlashPoint Host Adapter\n", NULL, IRQ_Channel);
-	  BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n",
-			 NULL, Bus, Device, IO_Address);
-	  continue;
-	}
-      if (BusLogic_GlobalOptions.TraceProbe)
-	{
-	  BusLogic_Notice("BusLogic: FlashPoint Host Adapter "
-			  "detected at\n", NULL);
-	  BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address "
-			  "0x%X PCI Address 0x%X\n", NULL,
-			  Bus, Device, IO_Address, PCI_Address);
-	}
-      if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters)
-	{
-	  struct BusLogic_ProbeInfo *ProbeInfo =
-	    &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
-	  ProbeInfo->HostAdapterType = BusLogic_FlashPoint;
-	  ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
-	  ProbeInfo->IO_Address = IO_Address;
-	  ProbeInfo->PCI_Address = PCI_Address;
-	  ProbeInfo->Bus = Bus;
-	  ProbeInfo->Device = Device;
-	  ProbeInfo->IRQ_Channel = IRQ_Channel;
-	  ProbeInfo->PCI_Device = PCI_Device;
-	  FlashPointCount++;
-	}
-      else BusLogic_Warning("BusLogic: Too many Host Adapters "
-			    "detected\n", NULL);
+		if (pci_resource_flags(PCI_Device, 0) & IORESOURCE_MEM) {
+			BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for " "FlashPoint Host Adapter\n", NULL, BaseAddress0);
+			BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address);
+			continue;
+		}
+		if (pci_resource_flags(PCI_Device, 1) & IORESOURCE_IO) {
+			BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for " "FlashPoint Host Adapter\n", NULL, BaseAddress1);
+			BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n", NULL, Bus, Device, PCI_Address);
+			continue;
+		}
+		if (IRQ_Channel == 0) {
+			BusLogic_Error("BusLogic: IRQ Channel %d invalid for " "FlashPoint Host Adapter\n", NULL, IRQ_Channel);
+			BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n", NULL, Bus, Device, IO_Address);
+			continue;
+		}
+		if (BusLogic_GlobalOptions.TraceProbe) {
+			BusLogic_Notice("BusLogic: FlashPoint Host Adapter " "detected at\n", NULL);
+			BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address " "0x%X PCI Address 0x%X\n", NULL, Bus, Device, IO_Address, PCI_Address);
+		}
+		if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters) {
+			struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
+			ProbeInfo->HostAdapterType = BusLogic_FlashPoint;
+			ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
+			ProbeInfo->IO_Address = IO_Address;
+			ProbeInfo->PCI_Address = PCI_Address;
+			ProbeInfo->Bus = Bus;
+			ProbeInfo->Device = Device;
+			ProbeInfo->IRQ_Channel = IRQ_Channel;
+			ProbeInfo->PCI_Device = PCI_Device;
+			FlashPointCount++;
+		} else
+			BusLogic_Warning("BusLogic: Too many Host Adapters " "detected\n", NULL);
 #else
-      BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at "
-		     "PCI Bus %d Device %d\n", NULL, Bus, Device);
-      BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, irq %d, "
-		     "but FlashPoint\n", NULL, IO_Address, PCI_Address, IRQ_Channel);
-      BusLogic_Error("BusLogic: support was omitted in this kernel "
-		     "configuration.\n", NULL);
+		BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at " "PCI Bus %d Device %d\n", NULL, Bus, Device);
+		BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, irq %d, " "but FlashPoint\n", NULL, IO_Address, PCI_Address, IRQ_Channel);
+		BusLogic_Error("BusLogic: support was omitted in this kernel " "configuration.\n", NULL);
 #endif
-    }
-  /*
-    The FlashPoint BIOS will scan for FlashPoint Host Adapters in the order of
-    increasing PCI Bus and Device Number, so sort the probe information into
-    the same order the BIOS uses.
-  */
-  BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[FlashPointIndex],
-			 FlashPointCount);
-  return FlashPointCount;
+	}
+	/*
+	   The FlashPoint BIOS will scan for FlashPoint Host Adapters in the order of
+	   increasing PCI Bus and Device Number, so sort the probe information into
+	   the same order the BIOS uses.
+	 */
+	BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[FlashPointIndex], FlashPointCount);
+	return FlashPointCount;
 }
 
 
@@ -1174,106 +995,70 @@ static int __init BusLogic_InitializeFlashPointProbeInfo(struct BusLogic_HostAda
 static void __init BusLogic_InitializeProbeInfoList(struct BusLogic_HostAdapter
 						    *PrototypeHostAdapter)
 {
-  /*
-    If a PCI BIOS is present, interrogate it for MultiMaster and FlashPoint
-    Host Adapters; otherwise, default to the standard ISA MultiMaster probe.
-  */
-  if (!BusLogic_ProbeOptions.NoProbePCI)
-    {
-      if (BusLogic_ProbeOptions.MultiMasterFirst)
-	{
-	  BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
-	  BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
-	}
-      else if (BusLogic_ProbeOptions.FlashPointFirst)
-	{
-	  BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
-	  BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
-	}
-      else
-	{
-	  int FlashPointCount =
-	    BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
-	  int PCIMultiMasterCount =
-	    BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
-	  if (FlashPointCount > 0 && PCIMultiMasterCount > 0)
-	    {
-	      struct BusLogic_ProbeInfo *ProbeInfo =
-		&BusLogic_ProbeInfoList[FlashPointCount];
-	      struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter;
-	      struct BusLogic_FetchHostAdapterLocalRAMRequest
-		FetchHostAdapterLocalRAMRequest;
-	      struct BusLogic_BIOSDriveMapByte Drive0MapByte;
-	      while (ProbeInfo->HostAdapterBusType != BusLogic_PCI_Bus)
-		ProbeInfo++;
-	      HostAdapter->IO_Address = ProbeInfo->IO_Address;
-	      FetchHostAdapterLocalRAMRequest.ByteOffset =
-		BusLogic_BIOS_BaseOffset + BusLogic_BIOS_DriveMapOffset + 0;
-	      FetchHostAdapterLocalRAMRequest.ByteCount =
-		sizeof(Drive0MapByte);
-	      BusLogic_Command(HostAdapter,
-			       BusLogic_FetchHostAdapterLocalRAM,
-			       &FetchHostAdapterLocalRAMRequest,
-			       sizeof(FetchHostAdapterLocalRAMRequest),
-			       &Drive0MapByte, sizeof(Drive0MapByte));
-	      /*
-		If the Map Byte for BIOS Drive 0 indicates that BIOS Drive 0
-		is controlled by this PCI MultiMaster Host Adapter, then
-		reverse the probe order so that MultiMaster Host Adapters are
-		probed before FlashPoint Host Adapters.
-	      */
-	      if (Drive0MapByte.DiskGeometry !=
-		  BusLogic_BIOS_Disk_Not_Installed)
-		{
-		  struct BusLogic_ProbeInfo
-		    SavedProbeInfo[BusLogic_MaxHostAdapters];
-		  int MultiMasterCount =
-		    BusLogic_ProbeInfoCount - FlashPointCount;
-		  memcpy(SavedProbeInfo,
-			 BusLogic_ProbeInfoList,
-			 BusLogic_ProbeInfoCount
-			 * sizeof(struct BusLogic_ProbeInfo));
-		  memcpy(&BusLogic_ProbeInfoList[0],
-			 &SavedProbeInfo[FlashPointCount],
-			 MultiMasterCount * sizeof(struct BusLogic_ProbeInfo));
-		  memcpy(&BusLogic_ProbeInfoList[MultiMasterCount],
-			 &SavedProbeInfo[0],
-			 FlashPointCount * sizeof(struct BusLogic_ProbeInfo));
+	/*
+	   If a PCI BIOS is present, interrogate it for MultiMaster and FlashPoint
+	   Host Adapters; otherwise, default to the standard ISA MultiMaster probe.
+	 */
+	if (!BusLogic_ProbeOptions.NoProbePCI) {
+		if (BusLogic_ProbeOptions.MultiMasterFirst) {
+			BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
+			BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
+		} else if (BusLogic_ProbeOptions.FlashPointFirst) {
+			BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
+			BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
+		} else {
+			int FlashPointCount = BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
+			int PCIMultiMasterCount = BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
+			if (FlashPointCount > 0 && PCIMultiMasterCount > 0) {
+				struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[FlashPointCount];
+				struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter;
+				struct BusLogic_FetchHostAdapterLocalRAMRequest FetchHostAdapterLocalRAMRequest;
+				struct BusLogic_BIOSDriveMapByte Drive0MapByte;
+				while (ProbeInfo->HostAdapterBusType != BusLogic_PCI_Bus)
+					ProbeInfo++;
+				HostAdapter->IO_Address = ProbeInfo->IO_Address;
+				FetchHostAdapterLocalRAMRequest.ByteOffset = BusLogic_BIOS_BaseOffset + BusLogic_BIOS_DriveMapOffset + 0;
+				FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(Drive0MapByte);
+				BusLogic_Command(HostAdapter, BusLogic_FetchHostAdapterLocalRAM, &FetchHostAdapterLocalRAMRequest, sizeof(FetchHostAdapterLocalRAMRequest), &Drive0MapByte, sizeof(Drive0MapByte));
+				/*
+				   If the Map Byte for BIOS Drive 0 indicates that BIOS Drive 0
+				   is controlled by this PCI MultiMaster Host Adapter, then
+				   reverse the probe order so that MultiMaster Host Adapters are
+				   probed before FlashPoint Host Adapters.
+				 */
+				if (Drive0MapByte.DiskGeometry != BusLogic_BIOS_Disk_Not_Installed) {
+					struct BusLogic_ProbeInfo SavedProbeInfo[BusLogic_MaxHostAdapters];
+					int MultiMasterCount = BusLogic_ProbeInfoCount - FlashPointCount;
+					memcpy(SavedProbeInfo, BusLogic_ProbeInfoList, BusLogic_ProbeInfoCount * sizeof(struct BusLogic_ProbeInfo));
+					memcpy(&BusLogic_ProbeInfoList[0], &SavedProbeInfo[FlashPointCount], MultiMasterCount * sizeof(struct BusLogic_ProbeInfo));
+					memcpy(&BusLogic_ProbeInfoList[MultiMasterCount], &SavedProbeInfo[0], FlashPointCount * sizeof(struct BusLogic_ProbeInfo));
+				}
+			}
 		}
-	    }
-	}
-    }
-  else BusLogic_InitializeProbeInfoListISA(PrototypeHostAdapter);
+	} else
+		BusLogic_InitializeProbeInfoListISA(PrototypeHostAdapter);
 }
 
 
-#endif  /* CONFIG_PCI */
+#endif				/* CONFIG_PCI */
 
 
 /*
   BusLogic_Failure prints a standardized error message, and then returns false.
 */
 
-static boolean BusLogic_Failure(struct BusLogic_HostAdapter *HostAdapter,
-				char *ErrorMessage)
+static boolean BusLogic_Failure(struct BusLogic_HostAdapter *HostAdapter, char *ErrorMessage)
 {
-  BusLogic_AnnounceDriver(HostAdapter);
-  if (HostAdapter->HostAdapterBusType == BusLogic_PCI_Bus)
-    {
-      BusLogic_Error("While configuring BusLogic PCI Host Adapter at\n",
-		     HostAdapter);
-      BusLogic_Error("Bus %d Device %d I/O Address 0x%X PCI Address 0x%X:\n",
-		     HostAdapter, HostAdapter->Bus, HostAdapter->Device,
-		     HostAdapter->IO_Address, HostAdapter->PCI_Address);
-    }
-  else BusLogic_Error("While configuring BusLogic Host Adapter at "
-		      "I/O Address 0x%X:\n", HostAdapter,
-		      HostAdapter->IO_Address);
-  BusLogic_Error("%s FAILED - DETACHING\n", HostAdapter, ErrorMessage);
-  if (BusLogic_CommandFailureReason != NULL)
-    BusLogic_Error("ADDITIONAL FAILURE INFO - %s\n", HostAdapter,
-		   BusLogic_CommandFailureReason);
-  return false;
+	BusLogic_AnnounceDriver(HostAdapter);
+	if (HostAdapter->HostAdapterBusType == BusLogic_PCI_Bus) {
+		BusLogic_Error("While configuring BusLogic PCI Host Adapter at\n", HostAdapter);
+		BusLogic_Error("Bus %d Device %d I/O Address 0x%X PCI Address 0x%X:\n", HostAdapter, HostAdapter->Bus, HostAdapter->Device, HostAdapter->IO_Address, HostAdapter->PCI_Address);
+	} else
+		BusLogic_Error("While configuring BusLogic Host Adapter at " "I/O Address 0x%X:\n", HostAdapter, HostAdapter->IO_Address);
+	BusLogic_Error("%s FAILED - DETACHING\n", HostAdapter, ErrorMessage);
+	if (BusLogic_CommandFailureReason != NULL)
+		BusLogic_Error("ADDITIONAL FAILURE INFO - %s\n", HostAdapter, BusLogic_CommandFailureReason);
+	return false;
 }
 
 
@@ -1283,81 +1068,64 @@ static boolean BusLogic_Failure(struct BusLogic_HostAdapter *HostAdapter,
 
 static boolean __init BusLogic_ProbeHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
 {
-  union BusLogic_StatusRegister StatusRegister;
-  union BusLogic_InterruptRegister InterruptRegister;
-  union BusLogic_GeometryRegister GeometryRegister;
-  /*
-    FlashPoint Host Adapters are Probed by the FlashPoint SCCB Manager.
-  */
-  if (BusLogic_FlashPointHostAdapterP(HostAdapter))
-    {
-      struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo;
-      FlashPointInfo->BaseAddress =
-	(u32) HostAdapter->IO_Address;
-      FlashPointInfo->IRQ_Channel = HostAdapter->IRQ_Channel;
-      FlashPointInfo->Present = false;
-      if (!(FlashPoint_ProbeHostAdapter(FlashPointInfo) == 0 &&
-	    FlashPointInfo->Present))
-	{
-	  BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at "
-			 "PCI Bus %d Device %d\n", HostAdapter,
-			 HostAdapter->Bus, HostAdapter->Device);
-	  BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, "
-			 "but FlashPoint\n", HostAdapter,
-			 HostAdapter->IO_Address, HostAdapter->PCI_Address);
-	  BusLogic_Error("BusLogic: Probe Function failed to validate it.\n",
-			 HostAdapter);
-	  return false;
+	union BusLogic_StatusRegister StatusRegister;
+	union BusLogic_InterruptRegister InterruptRegister;
+	union BusLogic_GeometryRegister GeometryRegister;
+	/*
+	   FlashPoint Host Adapters are Probed by the FlashPoint SCCB Manager.
+	 */
+	if (BusLogic_FlashPointHostAdapterP(HostAdapter)) {
+		struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo;
+		FlashPointInfo->BaseAddress = (u32) HostAdapter->IO_Address;
+		FlashPointInfo->IRQ_Channel = HostAdapter->IRQ_Channel;
+		FlashPointInfo->Present = false;
+		if (!(FlashPoint_ProbeHostAdapter(FlashPointInfo) == 0 && FlashPointInfo->Present)) {
+			BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at " "PCI Bus %d Device %d\n", HostAdapter, HostAdapter->Bus, HostAdapter->Device);
+			BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, " "but FlashPoint\n", HostAdapter, HostAdapter->IO_Address, HostAdapter->PCI_Address);
+			BusLogic_Error("BusLogic: Probe Function failed to validate it.\n", HostAdapter);
+			return false;
+		}
+		if (BusLogic_GlobalOptions.TraceProbe)
+			BusLogic_Notice("BusLogic_Probe(0x%X): FlashPoint Found\n", HostAdapter, HostAdapter->IO_Address);
+		/*
+		   Indicate the Host Adapter Probe completed successfully.
+		 */
+		return true;
 	}
-      if (BusLogic_GlobalOptions.TraceProbe)
-	BusLogic_Notice("BusLogic_Probe(0x%X): FlashPoint Found\n",
-			HostAdapter, HostAdapter->IO_Address);
-      /*
-	Indicate the Host Adapter Probe completed successfully.
-      */
-      return true;
-    }
-  /*
-    Read the Status, Interrupt, and Geometry Registers to test if there are I/O
-    ports that respond, and to check the values to determine if they are from a
-    BusLogic Host Adapter.  A nonexistent I/O port will return 0xFF, in which
-    case there is definitely no BusLogic Host Adapter at this base I/O Address.
-    The test here is a subset of that used by the BusLogic Host Adapter BIOS.
-  */
-  StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
-  InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
-  GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter);
-  if (BusLogic_GlobalOptions.TraceProbe)
-    BusLogic_Notice("BusLogic_Probe(0x%X): Status 0x%02X, Interrupt 0x%02X, "
-		    "Geometry 0x%02X\n", HostAdapter,
-		    HostAdapter->IO_Address, StatusRegister.All,
-		    InterruptRegister.All, GeometryRegister.All);
-  if (StatusRegister.All == 0 ||
-      StatusRegister.sr.DiagnosticActive ||
-      StatusRegister.sr.CommandParameterRegisterBusy ||
-      StatusRegister.sr.Reserved ||
-      StatusRegister.sr.CommandInvalid ||
-      InterruptRegister.ir.Reserved != 0)
-    return false;
-  /*
-    Check the undocumented Geometry Register to test if there is an I/O port
-    that responded.  Adaptec Host Adapters do not implement the Geometry
-    Register, so this test helps serve to avoid incorrectly recognizing an
-    Adaptec 1542A or 1542B as a BusLogic.  Unfortunately, the Adaptec 1542C
-    series does respond to the Geometry Register I/O port, but it will be
-    rejected later when the Inquire Extended Setup Information command is
-    issued in BusLogic_CheckHostAdapter.  The AMI FastDisk Host Adapter is a
-    BusLogic clone that implements the same interface as earlier BusLogic
-    Host Adapters, including the undocumented commands, and is therefore
-    supported by this driver.  However, the AMI FastDisk always returns 0x00
-    upon reading the Geometry Register, so the extended translation option
-    should always be left disabled on the AMI FastDisk.
-  */
-  if (GeometryRegister.All == 0xFF) return false;
-  /*
-    Indicate the Host Adapter Probe completed successfully.
-  */
-  return true;
+	/*
+	   Read the Status, Interrupt, and Geometry Registers to test if there are I/O
+	   ports that respond, and to check the values to determine if they are from a
+	   BusLogic Host Adapter.  A nonexistent I/O port will return 0xFF, in which
+	   case there is definitely no BusLogic Host Adapter at this base I/O Address.
+	   The test here is a subset of that used by the BusLogic Host Adapter BIOS.
+	 */
+	StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+	InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
+	GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter);
+	if (BusLogic_GlobalOptions.TraceProbe)
+		BusLogic_Notice("BusLogic_Probe(0x%X): Status 0x%02X, Interrupt 0x%02X, " "Geometry 0x%02X\n", HostAdapter, HostAdapter->IO_Address, StatusRegister.All, InterruptRegister.All, GeometryRegister.All);
+	if (StatusRegister.All == 0 || StatusRegister.sr.DiagnosticActive || StatusRegister.sr.CommandParameterRegisterBusy || StatusRegister.sr.Reserved || StatusRegister.sr.CommandInvalid || InterruptRegister.ir.Reserved != 0)
+		return false;
+	/*
+	   Check the undocumented Geometry Register to test if there is an I/O port
+	   that responded.  Adaptec Host Adapters do not implement the Geometry
+	   Register, so this test helps serve to avoid incorrectly recognizing an
+	   Adaptec 1542A or 1542B as a BusLogic.  Unfortunately, the Adaptec 1542C
+	   series does respond to the Geometry Register I/O port, but it will be
+	   rejected later when the Inquire Extended Setup Information command is
+	   issued in BusLogic_CheckHostAdapter.  The AMI FastDisk Host Adapter is a
+	   BusLogic clone that implements the same interface as earlier BusLogic
+	   Host Adapters, including the undocumented commands, and is therefore
+	   supported by this driver.  However, the AMI FastDisk always returns 0x00
+	   upon reading the Geometry Register, so the extended translation option
+	   should always be left disabled on the AMI FastDisk.
+	 */
+	if (GeometryRegister.All == 0xFF)
+		return false;
+	/*
+	   Indicate the Host Adapter Probe completed successfully.
+	 */
+	return true;
 }
 
 
@@ -1370,113 +1138,101 @@ static boolean __init BusLogic_ProbeHostAdapter(struct BusLogic_HostAdapter *Hos
 */
 
 static boolean BusLogic_HardwareResetHostAdapter(struct BusLogic_HostAdapter
-						   *HostAdapter,
-						 boolean HardReset)
+						 *HostAdapter, boolean HardReset)
 {
-  union BusLogic_StatusRegister StatusRegister;
-  int TimeoutCounter;
-  /*
-    FlashPoint Host Adapters are Hard Reset by the FlashPoint SCCB Manager.
-  */
-  if (BusLogic_FlashPointHostAdapterP(HostAdapter))
-    {
-      struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo;
-      FlashPointInfo->HostSoftReset = !HardReset;
-      FlashPointInfo->ReportDataUnderrun = true;
-      HostAdapter->CardHandle =
-	FlashPoint_HardwareResetHostAdapter(FlashPointInfo);
-      if (HostAdapter->CardHandle == FlashPoint_BadCardHandle) return false;
-      /*
-	Indicate the Host Adapter Hard Reset completed successfully.
-      */
-      return true;
-    }
-  /*
-    Issue a Hard Reset or Soft Reset Command to the Host Adapter.  The Host
-    Adapter should respond by setting Diagnostic Active in the Status Register.
-  */
-  if (HardReset)
-    BusLogic_HardReset(HostAdapter);
-  else BusLogic_SoftReset(HostAdapter);
-  /*
-    Wait until Diagnostic Active is set in the Status Register.
-  */
-  TimeoutCounter = 5*10000;
-  while (--TimeoutCounter >= 0)
-    {
-      StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
-      if (StatusRegister.sr.DiagnosticActive) break;
-      udelay(100);
-    }
-  if (BusLogic_GlobalOptions.TraceHardwareReset)
-    BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Active, "
-		    "Status 0x%02X\n", HostAdapter,
-		    HostAdapter->IO_Address, StatusRegister.All);
-  if (TimeoutCounter < 0) return false;
-  /*
-    Wait 100 microseconds to allow completion of any initial diagnostic
-    activity which might leave the contents of the Status Register
-    unpredictable.
-  */
-  udelay(100);
-  /*
-    Wait until Diagnostic Active is reset in the Status Register.
-  */
-  TimeoutCounter = 10*10000;
-  while (--TimeoutCounter >= 0)
-    {
-      StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
-      if (!StatusRegister.sr.DiagnosticActive) break;
-      udelay(100);
-    }
-  if (BusLogic_GlobalOptions.TraceHardwareReset)
-    BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Completed, "
-		    "Status 0x%02X\n", HostAdapter,
-		    HostAdapter->IO_Address, StatusRegister.All);
-  if (TimeoutCounter < 0) return false;
-  /*
-    Wait until at least one of the Diagnostic Failure, Host Adapter Ready,
-    or Data In Register Ready bits is set in the Status Register.
-  */
-  TimeoutCounter = 10000;
-  while (--TimeoutCounter >= 0)
-    {
-      StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
-      if (StatusRegister.sr.DiagnosticFailure ||
-	  StatusRegister.sr.HostAdapterReady ||
-	  StatusRegister.sr.DataInRegisterReady)
-	break;
-      udelay(100);
-    }
-  if (BusLogic_GlobalOptions.TraceHardwareReset)
-    BusLogic_Notice("BusLogic_HardwareReset(0x%X): Host Adapter Ready, "
-		    "Status 0x%02X\n", HostAdapter,
-		    HostAdapter->IO_Address, StatusRegister.All);
-  if (TimeoutCounter < 0) return false;
-  /*
-    If Diagnostic Failure is set or Host Adapter Ready is reset, then an
-    error occurred during the Host Adapter diagnostics.  If Data In Register
-    Ready is set, then there is an Error Code available.
-  */
-  if (StatusRegister.sr.DiagnosticFailure ||
-      !StatusRegister.sr.HostAdapterReady)
-    {
-      BusLogic_CommandFailureReason = NULL;
-      BusLogic_Failure(HostAdapter, "HARD RESET DIAGNOSTICS");
-      BusLogic_Error("HOST ADAPTER STATUS REGISTER = %02X\n",
-		     HostAdapter, StatusRegister.All);
-      if (StatusRegister.sr.DataInRegisterReady)
-	{
-	  unsigned char ErrorCode = BusLogic_ReadDataInRegister(HostAdapter);
-	  BusLogic_Error("HOST ADAPTER ERROR CODE = %d\n",
-			 HostAdapter, ErrorCode);
+	union BusLogic_StatusRegister StatusRegister;
+	int TimeoutCounter;
+	/*
+	   FlashPoint Host Adapters are Hard Reset by the FlashPoint SCCB Manager.
+	 */
+	if (BusLogic_FlashPointHostAdapterP(HostAdapter)) {
+		struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo;
+		FlashPointInfo->HostSoftReset = !HardReset;
+		FlashPointInfo->ReportDataUnderrun = true;
+		HostAdapter->CardHandle = FlashPoint_HardwareResetHostAdapter(FlashPointInfo);
+		if (HostAdapter->CardHandle == FlashPoint_BadCardHandle)
+			return false;
+		/*
+		   Indicate the Host Adapter Hard Reset completed successfully.
+		 */
+		return true;
+	}
+	/*
+	   Issue a Hard Reset or Soft Reset Command to the Host Adapter.  The Host
+	   Adapter should respond by setting Diagnostic Active in the Status Register.
+	 */
+	if (HardReset)
+		BusLogic_HardReset(HostAdapter);
+	else
+		BusLogic_SoftReset(HostAdapter);
+	/*
+	   Wait until Diagnostic Active is set in the Status Register.
+	 */
+	TimeoutCounter = 5 * 10000;
+	while (--TimeoutCounter >= 0) {
+		StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+		if (StatusRegister.sr.DiagnosticActive)
+			break;
+		udelay(100);
 	}
-      return false;
-    }
-  /*
-    Indicate the Host Adapter Hard Reset completed successfully.
-  */
-  return true;
+	if (BusLogic_GlobalOptions.TraceHardwareReset)
+		BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Active, " "Status 0x%02X\n", HostAdapter, HostAdapter->IO_Address, StatusRegister.All);
+	if (TimeoutCounter < 0)
+		return false;
+	/*
+	   Wait 100 microseconds to allow completion of any initial diagnostic
+	   activity which might leave the contents of the Status Register
+	   unpredictable.
+	 */
+	udelay(100);
+	/*
+	   Wait until Diagnostic Active is reset in the Status Register.
+	 */
+	TimeoutCounter = 10 * 10000;
+	while (--TimeoutCounter >= 0) {
+		StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+		if (!StatusRegister.sr.DiagnosticActive)
+			break;
+		udelay(100);
+	}
+	if (BusLogic_GlobalOptions.TraceHardwareReset)
+		BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Completed, " "Status 0x%02X\n", HostAdapter, HostAdapter->IO_Address, StatusRegister.All);
+	if (TimeoutCounter < 0)
+		return false;
+	/*
+	   Wait until at least one of the Diagnostic Failure, Host Adapter Ready,
+	   or Data In Register Ready bits is set in the Status Register.
+	 */
+	TimeoutCounter = 10000;
+	while (--TimeoutCounter >= 0) {
+		StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+		if (StatusRegister.sr.DiagnosticFailure || StatusRegister.sr.HostAdapterReady || StatusRegister.sr.DataInRegisterReady)
+			break;
+		udelay(100);
+	}
+	if (BusLogic_GlobalOptions.TraceHardwareReset)
+		BusLogic_Notice("BusLogic_HardwareReset(0x%X): Host Adapter Ready, " "Status 0x%02X\n", HostAdapter, HostAdapter->IO_Address, StatusRegister.All);
+	if (TimeoutCounter < 0)
+		return false;
+	/*
+	   If Diagnostic Failure is set or Host Adapter Ready is reset, then an
+	   error occurred during the Host Adapter diagnostics.  If Data In Register
+	   Ready is set, then there is an Error Code available.
+	 */
+	if (StatusRegister.sr.DiagnosticFailure || !StatusRegister.sr.HostAdapterReady) {
+		BusLogic_CommandFailureReason = NULL;
+		BusLogic_Failure(HostAdapter, "HARD RESET DIAGNOSTICS");
+		BusLogic_Error("HOST ADAPTER STATUS REGISTER = %02X\n", HostAdapter, StatusRegister.All);
+		if (StatusRegister.sr.DataInRegisterReady) {
+			unsigned char ErrorCode = BusLogic_ReadDataInRegister(HostAdapter);
+			BusLogic_Error("HOST ADAPTER ERROR CODE = %d\n", HostAdapter, ErrorCode);
+		}
+		return false;
+	}
+	/*
+	   Indicate the Host Adapter Hard Reset completed successfully.
+	 */
+	return true;
 }
 
 
@@ -1487,35 +1243,30 @@ static boolean BusLogic_HardwareResetHostAdapter(struct BusLogic_HostAdapter
 
 static boolean __init BusLogic_CheckHostAdapter(struct BusLogic_HostAdapter *HostAdapter)
 {
-  struct BusLogic_ExtendedSetupInformation ExtendedSetupInformation;
-  unsigned char RequestedReplyLength;
-  boolean Result = true;
-  /*
-    FlashPoint Host Adapters do not require this protection.
-  */
-  if (BusLogic_FlashPointHostAdapterP(HostAdapter)) return true;
-  /*
-    Issue the Inquire Extended Setup Information command.  Only genuine
-    BusLogic Host Adapters and true clones support this command.  Adaptec 1542C
-    series Host Adapters that respond to the Geometry Register I/O port will
-    fail this command.
-  */
-  RequestedReplyLength = sizeof(ExtendedSetupInformation);
-  if (BusLogic_Command(HostAdapter,
-		       BusLogic_InquireExtendedSetupInformation,
-		       &RequestedReplyLength,
-		       sizeof(RequestedReplyLength),
-		       &ExtendedSetupInformation,
-		       sizeof(ExtendedSetupInformation))
-      != sizeof(ExtendedSetupInformation))
-    Result = false;
-  /*
-    Provide tracing information if requested and return.
-  */
-  if (BusLogic_GlobalOptions.TraceProbe)
-    BusLogic_Notice("BusLogic_Check(0x%X): MultiMaster %s\n", HostAdapter,
-		    HostAdapter->IO_Address, (Result ? "Found" : "Not Found"));
-  return Result;
+	struct BusLogic_ExtendedSetupInformation ExtendedSetupInformation;
+	unsigned char RequestedReplyLength;
+	boolean Result = true;
+	/*
+	   FlashPoint Host Adapters do not require this protection.
+	 */
+	if (BusLogic_FlashPointHostAdapterP(HostAdapter))
+		return true;
+	/*
+	   Issue the Inquire Extended Setup Information command.  Only genuine
+	   BusLogic Host Adapters and true clones support this command.  Adaptec 1542C
+	   series Host Adapters that respond to the Geometry Register I/O port will
+	   fail this command.
+	 */
+	RequestedReplyLength = sizeof(ExtendedSetupInformation);
+	if (BusLogic_Command(HostAdapter, BusLogic_InquireExtendedSetupInformation, &RequestedReplyLength, sizeof(RequestedReplyLength), &ExtendedSetupInformation, sizeof(ExtendedSetupInformation))
+	    != sizeof(ExtendedSetupInformation))
+		Result = false;
+	/*
+	   Provide tracing information if requested and return.
+	 */
+	if (BusLogic_GlobalOptions.TraceProbe)
+		BusLogic_Notice("BusLogic_Check(0x%X): MultiMaster %s\n", HostAdapter, HostAdapter->IO_Address, (Result ? "Found" : "Not Found"));
+	return Result;
 }
 
 
@@ -1527,513 +1278,442 @@ static boolean __init BusLogic_CheckHostAdapter(struct BusLogic_HostAdapter *Hos
 static boolean __init BusLogic_ReadHostAdapterConfiguration(struct BusLogic_HostAdapter
 							    *HostAdapter)
 {
-  struct BusLogic_BoardID BoardID;
-  struct BusLogic_Configuration Configuration;
-  struct BusLogic_SetupInformation SetupInformation;
-  struct BusLogic_ExtendedSetupInformation ExtendedSetupInformation;
-  unsigned char HostAdapterModelNumber[5];
-  unsigned char FirmwareVersion3rdDigit;
-  unsigned char FirmwareVersionLetter;
-  struct BusLogic_PCIHostAdapterInformation PCIHostAdapterInformation;
-  struct BusLogic_FetchHostAdapterLocalRAMRequest FetchHostAdapterLocalRAMRequest;
-  struct BusLogic_AutoSCSIData AutoSCSIData;
-  union BusLogic_GeometryRegister GeometryRegister;
-  unsigned char RequestedReplyLength;
-  unsigned char *TargetPointer, Character;
-  int TargetID, i;
-  /*
-    Configuration Information for FlashPoint Host Adapters is provided in the
-    FlashPoint_Info structure by the FlashPoint SCCB Manager's Probe Function.
-    Initialize fields in the Host Adapter structure from the FlashPoint_Info
-    structure.
-  */
-  if (BusLogic_FlashPointHostAdapterP(HostAdapter))
-    {
-      struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo;
-      TargetPointer = HostAdapter->ModelName;
-      *TargetPointer++ = 'B';
-      *TargetPointer++ = 'T';
-      *TargetPointer++ = '-';
-      for (i = 0; i < sizeof(FlashPointInfo->ModelNumber); i++)
-	*TargetPointer++ = FlashPointInfo->ModelNumber[i];
-      *TargetPointer++ = '\0';
-      strcpy(HostAdapter->FirmwareVersion, FlashPoint_FirmwareVersion);
-      HostAdapter->SCSI_ID = FlashPointInfo->SCSI_ID;
-      HostAdapter->ExtendedTranslationEnabled =
-	FlashPointInfo->ExtendedTranslationEnabled;
-      HostAdapter->ParityCheckingEnabled =
-	FlashPointInfo->ParityCheckingEnabled;
-      HostAdapter->BusResetEnabled = !FlashPointInfo->HostSoftReset;
-      HostAdapter->LevelSensitiveInterrupt = true;
-      HostAdapter->HostWideSCSI = FlashPointInfo->HostWideSCSI;
-      HostAdapter->HostDifferentialSCSI = false;
-      HostAdapter->HostSupportsSCAM = true;
-      HostAdapter->HostUltraSCSI = true;
-      HostAdapter->ExtendedLUNSupport = true;
-      HostAdapter->TerminationInfoValid = true;
-      HostAdapter->LowByteTerminated = FlashPointInfo->LowByteTerminated;
-      HostAdapter->HighByteTerminated = FlashPointInfo->HighByteTerminated;
-      HostAdapter->SCAM_Enabled = FlashPointInfo->SCAM_Enabled;
-      HostAdapter->SCAM_Level2 = FlashPointInfo->SCAM_Level2;
-      HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit;
-      HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8);
-      HostAdapter->MaxLogicalUnits = 32;
-      HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize;
-      HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize;
-      HostAdapter->DriverQueueDepth = 255;
-      HostAdapter->HostAdapterQueueDepth = HostAdapter->DriverQueueDepth;
-      HostAdapter->SynchronousPermitted = FlashPointInfo->SynchronousPermitted;
-      HostAdapter->FastPermitted = FlashPointInfo->FastPermitted;
-      HostAdapter->UltraPermitted = FlashPointInfo->UltraPermitted;
-      HostAdapter->WidePermitted = FlashPointInfo->WidePermitted;
-      HostAdapter->DisconnectPermitted = FlashPointInfo->DisconnectPermitted;
-      HostAdapter->TaggedQueuingPermitted = 0xFFFF;
-      goto Common;
-    }
-  /*
-    Issue the Inquire Board ID command.
-  */
-  if (BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, NULL, 0,
-		       &BoardID, sizeof(BoardID)) != sizeof(BoardID))
-    return BusLogic_Failure(HostAdapter, "INQUIRE BOARD ID");
-  /*
-    Issue the Inquire Configuration command.
-  */
-  if (BusLogic_Command(HostAdapter, BusLogic_InquireConfiguration, NULL, 0,
-		       &Configuration, sizeof(Configuration))
-      != sizeof(Configuration))
-    return BusLogic_Failure(HostAdapter, "INQUIRE CONFIGURATION");
-  /*
-    Issue the Inquire Setup Information command.
-  */
-  RequestedReplyLength = sizeof(SetupInformation);
-  if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation,
-		       &RequestedReplyLength, sizeof(RequestedReplyLength),
-		       &SetupInformation, sizeof(SetupInformation))
-      != sizeof(SetupInformation))
-    return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION");
-  /*
-    Issue the Inquire Extended Setup Information command.
-  */
-  RequestedReplyLength = sizeof(ExtendedSetupInformation);
-  if (BusLogic_Command(HostAdapter, BusLogic_InquireExtendedSetupInformation,
-		       &RequestedReplyLength, sizeof(RequestedReplyLength),
-		       &ExtendedSetupInformation,
-		       sizeof(ExtendedSetupInformation))
-      != sizeof(ExtendedSetupInformation))
-    return BusLogic_Failure(HostAdapter, "INQUIRE EXTENDED SETUP INFORMATION");
-  /*
-    Issue the Inquire Firmware Version 3rd Digit command.
-  */
-  FirmwareVersion3rdDigit = '\0';
-  if (BoardID.FirmwareVersion1stDigit > '0')
-    if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersion3rdDigit,
-			 NULL, 0, &FirmwareVersion3rdDigit,
-			 sizeof(FirmwareVersion3rdDigit))
-	!= sizeof(FirmwareVersion3rdDigit))
-      return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE 3RD DIGIT");
-  /*
-    Issue the Inquire Host Adapter Model Number command.
-  */
-  if (ExtendedSetupInformation.BusType == 'A' &&
-      BoardID.FirmwareVersion1stDigit == '2')
-    /* BusLogic BT-542B ISA 2.xx */
-    strcpy(HostAdapterModelNumber, "542B");
-  else if (ExtendedSetupInformation.BusType == 'E' &&
-	   BoardID.FirmwareVersion1stDigit == '2' &&
-	   (BoardID.FirmwareVersion2ndDigit <= '1' ||
-	    (BoardID.FirmwareVersion2ndDigit == '2' &&
-	     FirmwareVersion3rdDigit == '0')))
-    /* BusLogic BT-742A EISA 2.1x or 2.20 */
-    strcpy(HostAdapterModelNumber, "742A");
-  else if (ExtendedSetupInformation.BusType == 'E' &&
-	   BoardID.FirmwareVersion1stDigit == '0')
-    /* AMI FastDisk EISA Series 441 0.x */
-    strcpy(HostAdapterModelNumber, "747A");
-  else
-    {
-      RequestedReplyLength = sizeof(HostAdapterModelNumber);
-      if (BusLogic_Command(HostAdapter, BusLogic_InquireHostAdapterModelNumber,
-			   &RequestedReplyLength, sizeof(RequestedReplyLength),
-			   &HostAdapterModelNumber,
-			   sizeof(HostAdapterModelNumber))
-	  != sizeof(HostAdapterModelNumber))
-	return BusLogic_Failure(HostAdapter,
-				"INQUIRE HOST ADAPTER MODEL NUMBER");
-    }
-  /*
-    BusLogic MultiMaster Host Adapters can be identified by their model number
-    and the major version number of their firmware as follows:
-
-    5.xx	BusLogic "W" Series Host Adapters:
-		  BT-948/958/958D
-    4.xx	BusLogic "C" Series Host Adapters:
-		  BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF
-    3.xx	BusLogic "S" Series Host Adapters:
-		  BT-747S/747D/757S/757D/445S/545S/542D
-		  BT-542B/742A (revision H)
-    2.xx	BusLogic "A" Series Host Adapters:
-		  BT-542B/742A (revision G and below)
-    0.xx	AMI FastDisk VLB/EISA BusLogic Clone Host Adapter
-  */
-  /*
-    Save the Model Name and Host Adapter Name in the Host Adapter structure.
-  */
-  TargetPointer = HostAdapter->ModelName;
-  *TargetPointer++ = 'B';
-  *TargetPointer++ = 'T';
-  *TargetPointer++ = '-';
-  for (i = 0; i < sizeof(HostAdapterModelNumber); i++)
-    {
-      Character = HostAdapterModelNumber[i];
-      if (Character == ' ' || Character == '\0') break;
-      *TargetPointer++ = Character;
-    }
-  *TargetPointer++ = '\0';
-  /*
-    Save the Firmware Version in the Host Adapter structure.
-  */
-  TargetPointer = HostAdapter->FirmwareVersion;
-  *TargetPointer++ = BoardID.FirmwareVersion1stDigit;
-  *TargetPointer++ = '.';
-  *TargetPointer++ = BoardID.FirmwareVersion2ndDigit;
-  if (FirmwareVersion3rdDigit != ' ' && FirmwareVersion3rdDigit != '\0')
-    *TargetPointer++ = FirmwareVersion3rdDigit;
-  *TargetPointer = '\0';
-  /*
-    Issue the Inquire Firmware Version Letter command.
-  */
-  if (strcmp(HostAdapter->FirmwareVersion, "3.3") >= 0)
-    {
-      if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersionLetter,
-			   NULL, 0, &FirmwareVersionLetter,
-			   sizeof(FirmwareVersionLetter))
-	  != sizeof(FirmwareVersionLetter))
-	return BusLogic_Failure(HostAdapter,
-				"INQUIRE FIRMWARE VERSION LETTER");
-      if (FirmwareVersionLetter != ' ' && FirmwareVersionLetter != '\0')
-	*TargetPointer++ = FirmwareVersionLetter;
-      *TargetPointer = '\0';
-    }
-  /*
-    Save the Host Adapter SCSI ID in the Host Adapter structure.
-  */
-  HostAdapter->SCSI_ID = Configuration.HostAdapterID;
-  /*
-    Determine the Bus Type and save it in the Host Adapter structure, determine
-    and save the IRQ Channel if necessary, and determine and save the DMA
-    Channel for ISA Host Adapters.
-  */
-  HostAdapter->HostAdapterBusType =
-    BusLogic_HostAdapterBusTypes[HostAdapter->ModelName[3] - '4'];
-  if (HostAdapter->IRQ_Channel == 0)
-    {
-      if (Configuration.IRQ_Channel9)
-	HostAdapter->IRQ_Channel = 9;
-      else if (Configuration.IRQ_Channel10)
-	HostAdapter->IRQ_Channel = 10;
-      else if (Configuration.IRQ_Channel11)
-	HostAdapter->IRQ_Channel = 11;
-      else if (Configuration.IRQ_Channel12)
-	HostAdapter->IRQ_Channel = 12;
-      else if (Configuration.IRQ_Channel14)
-	HostAdapter->IRQ_Channel = 14;
-      else if (Configuration.IRQ_Channel15)
-	HostAdapter->IRQ_Channel = 15;
-    }
-  if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus)
-    {
-      if (Configuration.DMA_Channel5)
-	HostAdapter->DMA_Channel = 5;
-      else if (Configuration.DMA_Channel6)
-	HostAdapter->DMA_Channel = 6;
-      else if (Configuration.DMA_Channel7)
-	HostAdapter->DMA_Channel = 7;
-    }
-  /*
-    Determine whether Extended Translation is enabled and save it in
-    the Host Adapter structure.
-  */
-  GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter);
-  HostAdapter->ExtendedTranslationEnabled =
-    GeometryRegister.gr.ExtendedTranslationEnabled;
-  /*
-    Save the Scatter Gather Limits, Level Sensitive Interrupt flag, Wide
-    SCSI flag, Differential SCSI flag, SCAM Supported flag, and
-    Ultra SCSI flag in the Host Adapter structure.
-  */
-  HostAdapter->HostAdapterScatterGatherLimit =
-    ExtendedSetupInformation.ScatterGatherLimit;
-  HostAdapter->DriverScatterGatherLimit =
-    HostAdapter->HostAdapterScatterGatherLimit;
-  if (HostAdapter->HostAdapterScatterGatherLimit > BusLogic_ScatterGatherLimit)
-    HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit;
-  if (ExtendedSetupInformation.Misc.LevelSensitiveInterrupt)
-    HostAdapter->LevelSensitiveInterrupt = true;
-  HostAdapter->HostWideSCSI = ExtendedSetupInformation.HostWideSCSI;
-  HostAdapter->HostDifferentialSCSI =
-    ExtendedSetupInformation.HostDifferentialSCSI;
-  HostAdapter->HostSupportsSCAM = ExtendedSetupInformation.HostSupportsSCAM;
-  HostAdapter->HostUltraSCSI = ExtendedSetupInformation.HostUltraSCSI;
-  /*
-    Determine whether Extended LUN Format CCBs are supported and save the
-    information in the Host Adapter structure.
-  */
-  if (HostAdapter->FirmwareVersion[0] == '5' ||
-      (HostAdapter->FirmwareVersion[0] == '4' && HostAdapter->HostWideSCSI))
-    HostAdapter->ExtendedLUNSupport = true;
-  /*
-    Issue the Inquire PCI Host Adapter Information command to read the
-    Termination Information from "W" series MultiMaster Host Adapters.
-  */
-  if (HostAdapter->FirmwareVersion[0] == '5')
-    {
-      if (BusLogic_Command(HostAdapter,
-			   BusLogic_InquirePCIHostAdapterInformation,
-			   NULL, 0, &PCIHostAdapterInformation,
-			   sizeof(PCIHostAdapterInformation))
-	  != sizeof(PCIHostAdapterInformation))
-	return BusLogic_Failure(HostAdapter,
-				"INQUIRE PCI HOST ADAPTER INFORMATION");
-      /*
-	Save the Termination Information in the Host Adapter structure.
-      */
-      if (PCIHostAdapterInformation.GenericInfoValid)
-	{
-	  HostAdapter->TerminationInfoValid = true;
-	  HostAdapter->LowByteTerminated =
-	    PCIHostAdapterInformation.LowByteTerminated;
-	  HostAdapter->HighByteTerminated =
-	    PCIHostAdapterInformation.HighByteTerminated;
+	struct BusLogic_BoardID BoardID;
+	struct BusLogic_Configuration Configuration;
+	struct BusLogic_SetupInformation SetupInformation;
+	struct BusLogic_ExtendedSetupInformation ExtendedSetupInformation;
+	unsigned char HostAdapterModelNumber[5];
+	unsigned char FirmwareVersion3rdDigit;
+	unsigned char FirmwareVersionLetter;
+	struct BusLogic_PCIHostAdapterInformation PCIHostAdapterInformation;
+	struct BusLogic_FetchHostAdapterLocalRAMRequest FetchHostAdapterLocalRAMRequest;
+	struct BusLogic_AutoSCSIData AutoSCSIData;
+	union BusLogic_GeometryRegister GeometryRegister;
+	unsigned char RequestedReplyLength;
+	unsigned char *TargetPointer, Character;
+	int TargetID, i;
+	/*
+	   Configuration Information for FlashPoint Host Adapters is provided in the
+	   FlashPoint_Info structure by the FlashPoint SCCB Manager's Probe Function.
+	   Initialize fields in the Host Adapter structure from the FlashPoint_Info
+	   structure.
+	 */
+	if (BusLogic_FlashPointHostAdapterP(HostAdapter)) {
+		struct FlashPoint_Info *FlashPointInfo = &HostAdapter->FlashPointInfo;
+		TargetPointer = HostAdapter->ModelName;
+		*TargetPointer++ = 'B';
+		*TargetPointer++ = 'T';
+		*TargetPointer++ = '-';
+		for (i = 0; i < sizeof(FlashPointInfo->ModelNumber); i++)
+			*TargetPointer++ = FlashPointInfo->ModelNumber[i];
+		*TargetPointer++ = '\0';
+		strcpy(HostAdapter->FirmwareVersion, FlashPoint_FirmwareVersion);
+		HostAdapter->SCSI_ID = FlashPointInfo->SCSI_ID;
+		HostAdapter->ExtendedTranslationEnabled = FlashPointInfo->ExtendedTranslationEnabled;
+		HostAdapter->ParityCheckingEnabled = FlashPointInfo->ParityCheckingEnabled;
+		HostAdapter->BusResetEnabled = !FlashPointInfo->HostSoftReset;
+		HostAdapter->LevelSensitiveInterrupt = true;
+		HostAdapter->HostWideSCSI = FlashPointInfo->HostWideSCSI;
+		HostAdapter->HostDifferentialSCSI = false;
+		HostAdapter->HostSupportsSCAM = true;
+		HostAdapter->HostUltraSCSI = true;
+		HostAdapter->ExtendedLUNSupport = true;
+		HostAdapter->TerminationInfoValid = true;
+		HostAdapter->LowByteTerminated = FlashPointInfo->LowByteTerminated;
+		HostAdapter->HighByteTerminated = FlashPointInfo->HighByteTerminated;
+		HostAdapter->SCAM_Enabled = FlashPointInfo->SCAM_Enabled;
+		HostAdapter->SCAM_Level2 = FlashPointInfo->SCAM_Level2;
+		HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit;
+		HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8);
+		HostAdapter->MaxLogicalUnits = 32;
+		HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize;
+		HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize;
+		HostAdapter->DriverQueueDepth = 255;
+		HostAdapter->HostAdapterQueueDepth = HostAdapter->DriverQueueDepth;
+		HostAdapter->SynchronousPermitted = FlashPointInfo->SynchronousPermitted;
+		HostAdapter->FastPermitted = FlashPointInfo->FastPermitted;
+		HostAdapter->UltraPermitted = FlashPointInfo->UltraPermitted;
+		HostAdapter->WidePermitted = FlashPointInfo->WidePermitted;
+		HostAdapter->DisconnectPermitted = FlashPointInfo->DisconnectPermitted;
+		HostAdapter->TaggedQueuingPermitted = 0xFFFF;
+		goto Common;
+	}
+	/*
+	   Issue the Inquire Board ID command.
+	 */
+	if (BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, NULL, 0, &BoardID, sizeof(BoardID)) != sizeof(BoardID))
+		return BusLogic_Failure(HostAdapter, "INQUIRE BOARD ID");
+	/*
+	   Issue the Inquire Configuration command.
+	 */
+	if (BusLogic_Command(HostAdapter, BusLogic_InquireConfiguration, NULL, 0, &Configuration, sizeof(Configuration))
+	    != sizeof(Configuration))
+		return BusLogic_Failure(HostAdapter, "INQUIRE CONFIGURATION");
+	/*
+	   Issue the Inquire Setup Information command.
+	 */
+	RequestedReplyLength = sizeof(SetupInformation);
+	if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation, &RequestedReplyLength, sizeof(RequestedReplyLength), &SetupInformation, sizeof(SetupInformation))
+	    != sizeof(SetupInformation))
+		return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION");
+	/*
+	   Issue the Inquire Extended Setup Information command.
+	 */
+	RequestedReplyLength = sizeof(ExtendedSetupInformation);
+	if (BusLogic_Command(HostAdapter, BusLogic_InquireExtendedSetupInformation, &RequestedReplyLength, sizeof(RequestedReplyLength), &ExtendedSetupInformation, sizeof(ExtendedSetupInformation))
+	    != sizeof(ExtendedSetupInformation))
+		return BusLogic_Failure(HostAdapter, "INQUIRE EXTENDED SETUP INFORMATION");
+	/*
+	   Issue the Inquire Firmware Version 3rd Digit command.
+	 */
+	FirmwareVersion3rdDigit = '\0';
+	if (BoardID.FirmwareVersion1stDigit > '0')
+		if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersion3rdDigit, NULL, 0, &FirmwareVersion3rdDigit, sizeof(FirmwareVersion3rdDigit))
+		    != sizeof(FirmwareVersion3rdDigit))
+			return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE 3RD DIGIT");
+	/*
+	   Issue the Inquire Host Adapter Model Number command.
+	 */
+	if (ExtendedSetupInformation.BusType == 'A' && BoardID.FirmwareVersion1stDigit == '2')
+		/* BusLogic BT-542B ISA 2.xx */
+		strcpy(HostAdapterModelNumber, "542B");
+	else if (ExtendedSetupInformation.BusType == 'E' && BoardID.FirmwareVersion1stDigit == '2' && (BoardID.FirmwareVersion2ndDigit <= '1' || (BoardID.FirmwareVersion2ndDigit == '2' && FirmwareVersion3rdDigit == '0')))
+		/* BusLogic BT-742A EISA 2.1x or 2.20 */
+		strcpy(HostAdapterModelNumber, "742A");
+	else if (ExtendedSetupInformation.BusType == 'E' && BoardID.FirmwareVersion1stDigit == '0')
+		/* AMI FastDisk EISA Series 441 0.x */
+		strcpy(HostAdapterModelNumber, "747A");
+	else {
+		RequestedReplyLength = sizeof(HostAdapterModelNumber);
+		if (BusLogic_Command(HostAdapter, BusLogic_InquireHostAdapterModelNumber, &RequestedReplyLength, sizeof(RequestedReplyLength), &HostAdapterModelNumber, sizeof(HostAdapterModelNumber))
+		    != sizeof(HostAdapterModelNumber))
+			return BusLogic_Failure(HostAdapter, "INQUIRE HOST ADAPTER MODEL NUMBER");
 	}
-    }
-  /*
-    Issue the Fetch Host Adapter Local RAM command to read the AutoSCSI data
-    from "W" and "C" series MultiMaster Host Adapters.
-  */
-  if (HostAdapter->FirmwareVersion[0] >= '4')
-    {
-      FetchHostAdapterLocalRAMRequest.ByteOffset =
-	BusLogic_AutoSCSI_BaseOffset;
-      FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIData);
-      if (BusLogic_Command(HostAdapter,
-			   BusLogic_FetchHostAdapterLocalRAM,
-			   &FetchHostAdapterLocalRAMRequest,
-			   sizeof(FetchHostAdapterLocalRAMRequest),
-			   &AutoSCSIData, sizeof(AutoSCSIData))
-	  != sizeof(AutoSCSIData))
-	return BusLogic_Failure(HostAdapter, "FETCH HOST ADAPTER LOCAL RAM");
-      /*
-	Save the Parity Checking Enabled, Bus Reset Enabled, and Termination
-	Information in the Host Adapter structure.
-      */
-      HostAdapter->ParityCheckingEnabled = AutoSCSIData.ParityCheckingEnabled;
-      HostAdapter->BusResetEnabled = AutoSCSIData.BusResetEnabled;
-      if (HostAdapter->FirmwareVersion[0] == '4')
-	{
-	  HostAdapter->TerminationInfoValid = true;
-	  HostAdapter->LowByteTerminated = AutoSCSIData.LowByteTerminated;
-	  HostAdapter->HighByteTerminated = AutoSCSIData.HighByteTerminated;
+	/*
+	   BusLogic MultiMaster Host Adapters can be identified by their model number
+	   and the major version number of their firmware as follows:
+
+	   5.xx       BusLogic "W" Series Host Adapters:
+	   BT-948/958/958D
+	   4.xx       BusLogic "C" Series Host Adapters:
+	   BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF
+	   3.xx       BusLogic "S" Series Host Adapters:
+	   BT-747S/747D/757S/757D/445S/545S/542D
+	   BT-542B/742A (revision H)
+	   2.xx       BusLogic "A" Series Host Adapters:
+	   BT-542B/742A (revision G and below)
+	   0.xx       AMI FastDisk VLB/EISA BusLogic Clone Host Adapter
+	 */
+	/*
+	   Save the Model Name and Host Adapter Name in the Host Adapter structure.
+	 */
+	TargetPointer = HostAdapter->ModelName;
+	*TargetPointer++ = 'B';
+	*TargetPointer++ = 'T';
+	*TargetPointer++ = '-';
+	for (i = 0; i < sizeof(HostAdapterModelNumber); i++) {
+		Character = HostAdapterModelNumber[i];
+		if (Character == ' ' || Character == '\0')
+			break;
+		*TargetPointer++ = Character;
+	}
+	*TargetPointer++ = '\0';
+	/*
+	   Save the Firmware Version in the Host Adapter structure.
+	 */
+	TargetPointer = HostAdapter->FirmwareVersion;
+	*TargetPointer++ = BoardID.FirmwareVersion1stDigit;
+	*TargetPointer++ = '.';
+	*TargetPointer++ = BoardID.FirmwareVersion2ndDigit;
+	if (FirmwareVersion3rdDigit != ' ' && FirmwareVersion3rdDigit != '\0')
+		*TargetPointer++ = FirmwareVersion3rdDigit;
+	*TargetPointer = '\0';
+	/*
+	   Issue the Inquire Firmware Version Letter command.
+	 */
+	if (strcmp(HostAdapter->FirmwareVersion, "3.3") >= 0) {
+		if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersionLetter, NULL, 0, &FirmwareVersionLetter, sizeof(FirmwareVersionLetter))
+		    != sizeof(FirmwareVersionLetter))
+			return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE VERSION LETTER");
+		if (FirmwareVersionLetter != ' ' && FirmwareVersionLetter != '\0')
+			*TargetPointer++ = FirmwareVersionLetter;
+		*TargetPointer = '\0';
 	}
-      /*
-	Save the Wide Permitted, Fast Permitted, Synchronous Permitted,
-	Disconnect Permitted, Ultra Permitted, and SCAM Information in the
-	Host Adapter structure.
-      */
-      HostAdapter->WidePermitted = AutoSCSIData.WidePermitted;
-      HostAdapter->FastPermitted = AutoSCSIData.FastPermitted;
-      HostAdapter->SynchronousPermitted =
-	AutoSCSIData.SynchronousPermitted;
-      HostAdapter->DisconnectPermitted =
-	AutoSCSIData.DisconnectPermitted;
-      if (HostAdapter->HostUltraSCSI)
-	HostAdapter->UltraPermitted = AutoSCSIData.UltraPermitted;
-      if (HostAdapter->HostSupportsSCAM)
-	{
-	  HostAdapter->SCAM_Enabled = AutoSCSIData.SCAM_Enabled;
-	  HostAdapter->SCAM_Level2 = AutoSCSIData.SCAM_Level2;
+	/*
+	   Save the Host Adapter SCSI ID in the Host Adapter structure.
+	 */
+	HostAdapter->SCSI_ID = Configuration.HostAdapterID;
+	/*
+	   Determine the Bus Type and save it in the Host Adapter structure, determine
+	   and save the IRQ Channel if necessary, and determine and save the DMA
+	   Channel for ISA Host Adapters.
+	 */
+	HostAdapter->HostAdapterBusType = BusLogic_HostAdapterBusTypes[HostAdapter->ModelName[3] - '4'];
+	if (HostAdapter->IRQ_Channel == 0) {
+		if (Configuration.IRQ_Channel9)
+			HostAdapter->IRQ_Channel = 9;
+		else if (Configuration.IRQ_Channel10)
+			HostAdapter->IRQ_Channel = 10;
+		else if (Configuration.IRQ_Channel11)
+			HostAdapter->IRQ_Channel = 11;
+		else if (Configuration.IRQ_Channel12)
+			HostAdapter->IRQ_Channel = 12;
+		else if (Configuration.IRQ_Channel14)
+			HostAdapter->IRQ_Channel = 14;
+		else if (Configuration.IRQ_Channel15)
+			HostAdapter->IRQ_Channel = 15;
+	}
+	if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus) {
+		if (Configuration.DMA_Channel5)
+			HostAdapter->DMA_Channel = 5;
+		else if (Configuration.DMA_Channel6)
+			HostAdapter->DMA_Channel = 6;
+		else if (Configuration.DMA_Channel7)
+			HostAdapter->DMA_Channel = 7;
 	}
-    }
-  /*
-    Initialize fields in the Host Adapter structure for "S" and "A" series
-    MultiMaster Host Adapters.
-  */
-  if (HostAdapter->FirmwareVersion[0] < '4')
-    {
-      if (SetupInformation.SynchronousInitiationEnabled)
-	{
-	  HostAdapter->SynchronousPermitted = 0xFF;
-	  if (HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus)
-	    {
-	      if (ExtendedSetupInformation.Misc.FastOnEISA)
-		HostAdapter->FastPermitted = 0xFF;
-	      if (strcmp(HostAdapter->ModelName, "BT-757") == 0)
-		HostAdapter->WidePermitted = 0xFF;
-	    }
+	/*
+	   Determine whether Extended Translation is enabled and save it in
+	   the Host Adapter structure.
+	 */
+	GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter);
+	HostAdapter->ExtendedTranslationEnabled = GeometryRegister.gr.ExtendedTranslationEnabled;
+	/*
+	   Save the Scatter Gather Limits, Level Sensitive Interrupt flag, Wide
+	   SCSI flag, Differential SCSI flag, SCAM Supported flag, and
+	   Ultra SCSI flag in the Host Adapter structure.
+	 */
+	HostAdapter->HostAdapterScatterGatherLimit = ExtendedSetupInformation.ScatterGatherLimit;
+	HostAdapter->DriverScatterGatherLimit = HostAdapter->HostAdapterScatterGatherLimit;
+	if (HostAdapter->HostAdapterScatterGatherLimit > BusLogic_ScatterGatherLimit)
+		HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit;
+	if (ExtendedSetupInformation.Misc.LevelSensitiveInterrupt)
+		HostAdapter->LevelSensitiveInterrupt = true;
+	HostAdapter->HostWideSCSI = ExtendedSetupInformation.HostWideSCSI;
+	HostAdapter->HostDifferentialSCSI = ExtendedSetupInformation.HostDifferentialSCSI;
+	HostAdapter->HostSupportsSCAM = ExtendedSetupInformation.HostSupportsSCAM;
+	HostAdapter->HostUltraSCSI = ExtendedSetupInformation.HostUltraSCSI;
+	/*
+	   Determine whether Extended LUN Format CCBs are supported and save the
+	   information in the Host Adapter structure.
+	 */
+	if (HostAdapter->FirmwareVersion[0] == '5' || (HostAdapter->FirmwareVersion[0] == '4' && HostAdapter->HostWideSCSI))
+		HostAdapter->ExtendedLUNSupport = true;
+	/*
+	   Issue the Inquire PCI Host Adapter Information command to read the
+	   Termination Information from "W" series MultiMaster Host Adapters.
+	 */
+	if (HostAdapter->FirmwareVersion[0] == '5') {
+		if (BusLogic_Command(HostAdapter, BusLogic_InquirePCIHostAdapterInformation, NULL, 0, &PCIHostAdapterInformation, sizeof(PCIHostAdapterInformation))
+		    != sizeof(PCIHostAdapterInformation))
+			return BusLogic_Failure(HostAdapter, "INQUIRE PCI HOST ADAPTER INFORMATION");
+		/*
+		   Save the Termination Information in the Host Adapter structure.
+		 */
+		if (PCIHostAdapterInformation.GenericInfoValid) {
+			HostAdapter->TerminationInfoValid = true;
+			HostAdapter->LowByteTerminated = PCIHostAdapterInformation.LowByteTerminated;
+			HostAdapter->HighByteTerminated = PCIHostAdapterInformation.HighByteTerminated;
+		}
+	}
+	/*
+	   Issue the Fetch Host Adapter Local RAM command to read the AutoSCSI data
+	   from "W" and "C" series MultiMaster Host Adapters.
+	 */
+	if (HostAdapter->FirmwareVersion[0] >= '4') {
+		FetchHostAdapterLocalRAMRequest.ByteOffset = BusLogic_AutoSCSI_BaseOffset;
+		FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIData);
+		if (BusLogic_Command(HostAdapter, BusLogic_FetchHostAdapterLocalRAM, &FetchHostAdapterLocalRAMRequest, sizeof(FetchHostAdapterLocalRAMRequest), &AutoSCSIData, sizeof(AutoSCSIData))
+		    != sizeof(AutoSCSIData))
+			return BusLogic_Failure(HostAdapter, "FETCH HOST ADAPTER LOCAL RAM");
+		/*
+		   Save the Parity Checking Enabled, Bus Reset Enabled, and Termination
+		   Information in the Host Adapter structure.
+		 */
+		HostAdapter->ParityCheckingEnabled = AutoSCSIData.ParityCheckingEnabled;
+		HostAdapter->BusResetEnabled = AutoSCSIData.BusResetEnabled;
+		if (HostAdapter->FirmwareVersion[0] == '4') {
+			HostAdapter->TerminationInfoValid = true;
+			HostAdapter->LowByteTerminated = AutoSCSIData.LowByteTerminated;
+			HostAdapter->HighByteTerminated = AutoSCSIData.HighByteTerminated;
+		}
+		/*
+		   Save the Wide Permitted, Fast Permitted, Synchronous Permitted,
+		   Disconnect Permitted, Ultra Permitted, and SCAM Information in the
+		   Host Adapter structure.
+		 */
+		HostAdapter->WidePermitted = AutoSCSIData.WidePermitted;
+		HostAdapter->FastPermitted = AutoSCSIData.FastPermitted;
+		HostAdapter->SynchronousPermitted = AutoSCSIData.SynchronousPermitted;
+		HostAdapter->DisconnectPermitted = AutoSCSIData.DisconnectPermitted;
+		if (HostAdapter->HostUltraSCSI)
+			HostAdapter->UltraPermitted = AutoSCSIData.UltraPermitted;
+		if (HostAdapter->HostSupportsSCAM) {
+			HostAdapter->SCAM_Enabled = AutoSCSIData.SCAM_Enabled;
+			HostAdapter->SCAM_Level2 = AutoSCSIData.SCAM_Level2;
+		}
+	}
+	/*
+	   Initialize fields in the Host Adapter structure for "S" and "A" series
+	   MultiMaster Host Adapters.
+	 */
+	if (HostAdapter->FirmwareVersion[0] < '4') {
+		if (SetupInformation.SynchronousInitiationEnabled) {
+			HostAdapter->SynchronousPermitted = 0xFF;
+			if (HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus) {
+				if (ExtendedSetupInformation.Misc.FastOnEISA)
+					HostAdapter->FastPermitted = 0xFF;
+				if (strcmp(HostAdapter->ModelName, "BT-757") == 0)
+					HostAdapter->WidePermitted = 0xFF;
+			}
+		}
+		HostAdapter->DisconnectPermitted = 0xFF;
+		HostAdapter->ParityCheckingEnabled = SetupInformation.ParityCheckingEnabled;
+		HostAdapter->BusResetEnabled = true;
+	}
+	/*
+	   Determine the maximum number of Target IDs and Logical Units supported by
+	   this driver for Wide and Narrow Host Adapters.
+	 */
+	HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8);
+	HostAdapter->MaxLogicalUnits = (HostAdapter->ExtendedLUNSupport ? 32 : 8);
+	/*
+	   Select appropriate values for the Mailbox Count, Driver Queue Depth,
+	   Initial CCBs, and Incremental CCBs variables based on whether or not Strict
+	   Round Robin Mode is supported.  If Strict Round Robin Mode is supported,
+	   then there is no performance degradation in using the maximum possible
+	   number of Outgoing and Incoming Mailboxes and allowing the Tagged and
+	   Untagged Queue Depths to determine the actual utilization.  If Strict Round
+	   Robin Mode is not supported, then the Host Adapter must scan all the
+	   Outgoing Mailboxes whenever an Outgoing Mailbox entry is made, which can
+	   cause a substantial performance penalty.  The host adapters actually have
+	   room to store the following number of CCBs internally; that is, they can
+	   internally queue and manage this many active commands on the SCSI bus
+	   simultaneously.  Performance measurements demonstrate that the Driver Queue
+	   Depth should be set to the Mailbox Count, rather than the Host Adapter
+	   Queue Depth (internal CCB capacity), as it is more efficient to have the
+	   queued commands waiting in Outgoing Mailboxes if necessary than to block
+	   the process in the higher levels of the SCSI Subsystem.
+
+	   192          BT-948/958/958D
+	   100          BT-946C/956C/956CD/747C/757C/757CD/445C
+	   50   BT-545C/540CF
+	   30   BT-747S/747D/757S/757D/445S/545S/542D/542B/742A
+	 */
+	if (HostAdapter->FirmwareVersion[0] == '5')
+		HostAdapter->HostAdapterQueueDepth = 192;
+	else if (HostAdapter->FirmwareVersion[0] == '4')
+		HostAdapter->HostAdapterQueueDepth = (HostAdapter->HostAdapterBusType != BusLogic_ISA_Bus ? 100 : 50);
+	else
+		HostAdapter->HostAdapterQueueDepth = 30;
+	if (strcmp(HostAdapter->FirmwareVersion, "3.31") >= 0) {
+		HostAdapter->StrictRoundRobinModeSupport = true;
+		HostAdapter->MailboxCount = BusLogic_MaxMailboxes;
+	} else {
+		HostAdapter->StrictRoundRobinModeSupport = false;
+		HostAdapter->MailboxCount = 32;
+	}
+	HostAdapter->DriverQueueDepth = HostAdapter->MailboxCount;
+	HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize;
+	HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize;
+	/*
+	   Tagged Queuing support is available and operates properly on all "W" series
+	   MultiMaster Host Adapters, on "C" series MultiMaster Host Adapters with
+	   firmware version 4.22 and above, and on "S" series MultiMaster Host
+	   Adapters with firmware version 3.35 and above.
+	 */
+	HostAdapter->TaggedQueuingPermitted = 0;
+	switch (HostAdapter->FirmwareVersion[0]) {
+	case '5':
+		HostAdapter->TaggedQueuingPermitted = 0xFFFF;
+		break;
+	case '4':
+		if (strcmp(HostAdapter->FirmwareVersion, "4.22") >= 0)
+			HostAdapter->TaggedQueuingPermitted = 0xFFFF;
+		break;
+	case '3':
+		if (strcmp(HostAdapter->FirmwareVersion, "3.35") >= 0)
+			HostAdapter->TaggedQueuingPermitted = 0xFFFF;
+		break;
 	}
-      HostAdapter->DisconnectPermitted = 0xFF;
-      HostAdapter->ParityCheckingEnabled =
-	SetupInformation.ParityCheckingEnabled;
-      HostAdapter->BusResetEnabled = true;
-    }
-  /*
-    Determine the maximum number of Target IDs and Logical Units supported by
-    this driver for Wide and Narrow Host Adapters.
-  */
-  HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8);
-  HostAdapter->MaxLogicalUnits = (HostAdapter->ExtendedLUNSupport ? 32 : 8);
-  /*
-    Select appropriate values for the Mailbox Count, Driver Queue Depth,
-    Initial CCBs, and Incremental CCBs variables based on whether or not Strict
-    Round Robin Mode is supported.  If Strict Round Robin Mode is supported,
-    then there is no performance degradation in using the maximum possible
-    number of Outgoing and Incoming Mailboxes and allowing the Tagged and
-    Untagged Queue Depths to determine the actual utilization.  If Strict Round
-    Robin Mode is not supported, then the Host Adapter must scan all the
-    Outgoing Mailboxes whenever an Outgoing Mailbox entry is made, which can
-    cause a substantial performance penalty.  The host adapters actually have
-    room to store the following number of CCBs internally; that is, they can
-    internally queue and manage this many active commands on the SCSI bus
-    simultaneously.  Performance measurements demonstrate that the Driver Queue
-    Depth should be set to the Mailbox Count, rather than the Host Adapter
-    Queue Depth (internal CCB capacity), as it is more efficient to have the
-    queued commands waiting in Outgoing Mailboxes if necessary than to block
-    the process in the higher levels of the SCSI Subsystem.
-
-	192	  BT-948/958/958D
-	100	  BT-946C/956C/956CD/747C/757C/757CD/445C
-	 50	  BT-545C/540CF
-	 30	  BT-747S/747D/757S/757D/445S/545S/542D/542B/742A
-  */
-  if (HostAdapter->FirmwareVersion[0] == '5')
-    HostAdapter->HostAdapterQueueDepth = 192;
-  else if (HostAdapter->FirmwareVersion[0] == '4')
-    HostAdapter->HostAdapterQueueDepth =
-      (HostAdapter->HostAdapterBusType != BusLogic_ISA_Bus ? 100 : 50);
-  else HostAdapter->HostAdapterQueueDepth = 30;
-  if (strcmp(HostAdapter->FirmwareVersion, "3.31") >= 0)
-    {
-      HostAdapter->StrictRoundRobinModeSupport = true;
-      HostAdapter->MailboxCount = BusLogic_MaxMailboxes;
-    }
-  else
-    {
-      HostAdapter->StrictRoundRobinModeSupport = false;
-      HostAdapter->MailboxCount = 32;
-    }
-  HostAdapter->DriverQueueDepth = HostAdapter->MailboxCount;
-  HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize;
-  HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize;
-  /*
-    Tagged Queuing support is available and operates properly on all "W" series
-    MultiMaster Host Adapters, on "C" series MultiMaster Host Adapters with
-    firmware version 4.22 and above, and on "S" series MultiMaster Host
-    Adapters with firmware version 3.35 and above.
-  */
-  HostAdapter->TaggedQueuingPermitted = 0;
-  switch (HostAdapter->FirmwareVersion[0])
-    {
-    case '5':
-      HostAdapter->TaggedQueuingPermitted = 0xFFFF;
-      break;
-    case '4':
-      if (strcmp(HostAdapter->FirmwareVersion, "4.22") >= 0)
-	HostAdapter->TaggedQueuingPermitted = 0xFFFF;
-      break;
-    case '3':
-      if (strcmp(HostAdapter->FirmwareVersion, "3.35") >= 0)
-	HostAdapter->TaggedQueuingPermitted = 0xFFFF;
-      break;
-    }
-  /*
-    Determine the Host Adapter BIOS Address if the BIOS is enabled and
-    save it in the Host Adapter structure.  The BIOS is disabled if the
-    BIOS_Address is 0.
-  */
-  HostAdapter->BIOS_Address = ExtendedSetupInformation.BIOS_Address << 12;
-  /*
-    ISA Host Adapters require Bounce Buffers if there is more than 16MB memory.
-  */
-  if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus &&
-      (void *) high_memory > (void *) MAX_DMA_ADDRESS)
-    HostAdapter->BounceBuffersRequired = true;
-  /*
-    BusLogic BT-445S Host Adapters prior to board revision E have a hardware
-    bug whereby when the BIOS is enabled, transfers to/from the same address
-    range the BIOS occupies modulo 16MB are handled incorrectly.  Only properly
-    functioning BT-445S Host Adapters have firmware version 3.37, so require
-    that ISA Bounce Buffers be used for the buggy BT-445S models if there is
-    more than 16MB memory.
-  */
-  if (HostAdapter->BIOS_Address > 0 &&
-      strcmp(HostAdapter->ModelName, "BT-445S") == 0 &&
-      strcmp(HostAdapter->FirmwareVersion, "3.37") < 0 &&
-      (void *) high_memory > (void *) MAX_DMA_ADDRESS)
-    HostAdapter->BounceBuffersRequired = true;
-  /*
-    Initialize parameters common to MultiMaster and FlashPoint Host Adapters.
-  */
-Common:
-  /*
-    Initialize the Host Adapter Full Model Name from the Model Name.
-  */
-  strcpy(HostAdapter->FullModelName, "BusLogic ");
-  strcat(HostAdapter->FullModelName, HostAdapter->ModelName);
-  /*
-    Select an appropriate value for the Tagged Queue Depth either from a
-    BusLogic Driver Options specification, or based on whether this Host
-    Adapter requires that ISA Bounce Buffers be used.  The Tagged Queue Depth
-    is left at 0 for automatic determination in BusLogic_SelectQueueDepths.
-    Initialize the Untagged Queue Depth.
-  */
-  for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
-    {
-      unsigned char QueueDepth = 0;
-      if (HostAdapter->DriverOptions != NULL &&
-	  HostAdapter->DriverOptions->QueueDepth[TargetID] > 0)
-	QueueDepth = HostAdapter->DriverOptions->QueueDepth[TargetID];
-      else if (HostAdapter->BounceBuffersRequired)
-	QueueDepth = BusLogic_TaggedQueueDepthBB;
-      HostAdapter->QueueDepth[TargetID] = QueueDepth;
-    }
-  if (HostAdapter->BounceBuffersRequired)
-    HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepthBB;
-  else HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepth;
-  if (HostAdapter->DriverOptions != NULL)
-    HostAdapter->CommonQueueDepth =
-      HostAdapter->DriverOptions->CommonQueueDepth;
-  if (HostAdapter->CommonQueueDepth > 0 &&
-      HostAdapter->CommonQueueDepth < HostAdapter->UntaggedQueueDepth)
-    HostAdapter->UntaggedQueueDepth = HostAdapter->CommonQueueDepth;
-  /*
-    Tagged Queuing is only allowed if Disconnect/Reconnect is permitted.
-    Therefore, mask the Tagged Queuing Permitted Default bits with the
-    Disconnect/Reconnect Permitted bits.
-  */
-  HostAdapter->TaggedQueuingPermitted &= HostAdapter->DisconnectPermitted;
-  /*
-    Combine the default Tagged Queuing Permitted bits with any BusLogic Driver
-    Options Tagged Queuing specification.
-  */
-  if (HostAdapter->DriverOptions != NULL)
-    HostAdapter->TaggedQueuingPermitted =
-      (HostAdapter->DriverOptions->TaggedQueuingPermitted &
-       HostAdapter->DriverOptions->TaggedQueuingPermittedMask) |
-      (HostAdapter->TaggedQueuingPermitted &
-       ~HostAdapter->DriverOptions->TaggedQueuingPermittedMask);
-
-  /*
-    Select an appropriate value for Bus Settle Time either from a BusLogic
-    Driver Options specification, or from BusLogic_DefaultBusSettleTime.
-  */
-  if (HostAdapter->DriverOptions != NULL &&
-      HostAdapter->DriverOptions->BusSettleTime > 0)
-    HostAdapter->BusSettleTime = HostAdapter->DriverOptions->BusSettleTime;
-  else HostAdapter->BusSettleTime = BusLogic_DefaultBusSettleTime;
-  /*
-    Indicate reading the Host Adapter Configuration completed successfully.
-  */
-  return true;
+	/*
+	   Determine the Host Adapter BIOS Address if the BIOS is enabled and
+	   save it in the Host Adapter structure.  The BIOS is disabled if the
+	   BIOS_Address is 0.
+	 */
+	HostAdapter->BIOS_Address = ExtendedSetupInformation.BIOS_Address << 12;
+	/*
+	   ISA Host Adapters require Bounce Buffers if there is more than 16MB memory.
+	 */
+	if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus && (void *) high_memory > (void *) MAX_DMA_ADDRESS)
+		HostAdapter->BounceBuffersRequired = true;
+	/*
+	   BusLogic BT-445S Host Adapters prior to board revision E have a hardware
+	   bug whereby when the BIOS is enabled, transfers to/from the same address
+	   range the BIOS occupies modulo 16MB are handled incorrectly.  Only properly
+	   functioning BT-445S Host Adapters have firmware version 3.37, so require
+	   that ISA Bounce Buffers be used for the buggy BT-445S models if there is
+	   more than 16MB memory.
+	 */
+	if (HostAdapter->BIOS_Address > 0 && strcmp(HostAdapter->ModelName, "BT-445S") == 0 && strcmp(HostAdapter->FirmwareVersion, "3.37") < 0 && (void *) high_memory > (void *) MAX_DMA_ADDRESS)
+		HostAdapter->BounceBuffersRequired = true;
+	/*
+	   Initialize parameters common to MultiMaster and FlashPoint Host Adapters.
+	 */
+      Common:
+	/*
+	   Initialize the Host Adapter Full Model Name from the Model Name.
+	 */
+	strcpy(HostAdapter->FullModelName, "BusLogic ");
+	strcat(HostAdapter->FullModelName, HostAdapter->ModelName);
+	/*
+	   Select an appropriate value for the Tagged Queue Depth either from a
+	   BusLogic Driver Options specification, or based on whether this Host
+	   Adapter requires that ISA Bounce Buffers be used.  The Tagged Queue Depth
+	   is left at 0 for automatic determination in BusLogic_SelectQueueDepths.
+	   Initialize the Untagged Queue Depth.
+	 */
+	for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) {
+		unsigned char QueueDepth = 0;
+		if (HostAdapter->DriverOptions != NULL && HostAdapter->DriverOptions->QueueDepth[TargetID] > 0)
+			QueueDepth = HostAdapter->DriverOptions->QueueDepth[TargetID];
+		else if (HostAdapter->BounceBuffersRequired)
+			QueueDepth = BusLogic_TaggedQueueDepthBB;
+		HostAdapter->QueueDepth[TargetID] = QueueDepth;
+	}
+	if (HostAdapter->BounceBuffersRequired)
+		HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepthBB;
+	else
+		HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepth;
+	if (HostAdapter->DriverOptions != NULL)
+		HostAdapter->CommonQueueDepth = HostAdapter->DriverOptions->CommonQueueDepth;
+	if (HostAdapter->CommonQueueDepth > 0 && HostAdapter->CommonQueueDepth < HostAdapter->UntaggedQueueDepth)
+		HostAdapter->UntaggedQueueDepth = HostAdapter->CommonQueueDepth;
+	/*
+	   Tagged Queuing is only allowed if Disconnect/Reconnect is permitted.
+	   Therefore, mask the Tagged Queuing Permitted Default bits with the
+	   Disconnect/Reconnect Permitted bits.
+	 */
+	HostAdapter->TaggedQueuingPermitted &= HostAdapter->DisconnectPermitted;
+	/*
+	   Combine the default Tagged Queuing Permitted bits with any BusLogic Driver
+	   Options Tagged Queuing specification.
+	 */
+	if (HostAdapter->DriverOptions != NULL)
+		HostAdapter->TaggedQueuingPermitted =
+		    (HostAdapter->DriverOptions->TaggedQueuingPermitted & HostAdapter->DriverOptions->TaggedQueuingPermittedMask) | (HostAdapter->TaggedQueuingPermitted & ~HostAdapter->DriverOptions->TaggedQueuingPermittedMask);
+
+	/*
+	   Select an appropriate value for Bus Settle Time either from a BusLogic
+	   Driver Options specification, or from BusLogic_DefaultBusSettleTime.
+	 */
+	if (HostAdapter->DriverOptions != NULL && HostAdapter->DriverOptions->BusSettleTime > 0)
+		HostAdapter->BusSettleTime = HostAdapter->DriverOptions->BusSettleTime;
+	else
+		HostAdapter->BusSettleTime = BusLogic_DefaultBusSettleTime;
+	/*
+	   Indicate reading the Host Adapter Configuration completed successfully.
+	 */
+	return true;
 }
 
 
@@ -2045,210 +1725,144 @@ Common:
 static boolean __init BusLogic_ReportHostAdapterConfiguration(struct BusLogic_HostAdapter
 							      *HostAdapter)
 {
-  unsigned short AllTargetsMask = (1 << HostAdapter->MaxTargetDevices) - 1;
-  unsigned short SynchronousPermitted, FastPermitted;
-  unsigned short UltraPermitted, WidePermitted;
-  unsigned short DisconnectPermitted, TaggedQueuingPermitted;
-  boolean CommonSynchronousNegotiation, CommonTaggedQueueDepth;
-  char SynchronousString[BusLogic_MaxTargetDevices+1];
-  char WideString[BusLogic_MaxTargetDevices+1];
-  char DisconnectString[BusLogic_MaxTargetDevices+1];
-  char TaggedQueuingString[BusLogic_MaxTargetDevices+1];
-  char *SynchronousMessage = SynchronousString;
-  char *WideMessage = WideString;
-  char *DisconnectMessage = DisconnectString;
-  char *TaggedQueuingMessage = TaggedQueuingString;
-  int TargetID;
-  BusLogic_Info("Configuring BusLogic Model %s %s%s%s%s SCSI Host Adapter\n",
-		HostAdapter, HostAdapter->ModelName,
-		BusLogic_HostAdapterBusNames[HostAdapter->HostAdapterBusType],
-		(HostAdapter->HostWideSCSI ? " Wide" : ""),
-		(HostAdapter->HostDifferentialSCSI ? " Differential" : ""),
-		(HostAdapter->HostUltraSCSI ? " Ultra" : ""));
-  BusLogic_Info("  Firmware Version: %s, I/O Address: 0x%X, "
-		"IRQ Channel: %d/%s\n", HostAdapter,
-		HostAdapter->FirmwareVersion,
-		HostAdapter->IO_Address, HostAdapter->IRQ_Channel,
-		(HostAdapter->LevelSensitiveInterrupt ? "Level" : "Edge"));
-  if (HostAdapter->HostAdapterBusType != BusLogic_PCI_Bus)
-    {
-      BusLogic_Info("  DMA Channel: ", HostAdapter);
-      if (HostAdapter->DMA_Channel > 0)
-	BusLogic_Info("%d, ", HostAdapter, HostAdapter->DMA_Channel);
-      else BusLogic_Info("None, ", HostAdapter);
-      if (HostAdapter->BIOS_Address > 0)
-	BusLogic_Info("BIOS Address: 0x%X, ", HostAdapter,
-		      HostAdapter->BIOS_Address);
-      else BusLogic_Info("BIOS Address: None, ", HostAdapter);
-    }
-  else
-    {
-      BusLogic_Info("  PCI Bus: %d, Device: %d, Address: ",
-		    HostAdapter, HostAdapter->Bus, HostAdapter->Device);
-      if (HostAdapter->PCI_Address > 0)
-	BusLogic_Info("0x%X, ", HostAdapter, HostAdapter->PCI_Address);
-      else BusLogic_Info("Unassigned, ", HostAdapter);
-    }
-  BusLogic_Info("Host Adapter SCSI ID: %d\n", HostAdapter,
-		HostAdapter->SCSI_ID);
-  BusLogic_Info("  Parity Checking: %s, Extended Translation: %s\n",
-		HostAdapter,
-		(HostAdapter->ParityCheckingEnabled
-		 ? "Enabled" : "Disabled"),
-		(HostAdapter->ExtendedTranslationEnabled
-		 ? "Enabled" : "Disabled"));
-  AllTargetsMask &= ~(1 << HostAdapter->SCSI_ID);
-  SynchronousPermitted = HostAdapter->SynchronousPermitted & AllTargetsMask;
-  FastPermitted = HostAdapter->FastPermitted & AllTargetsMask;
-  UltraPermitted = HostAdapter->UltraPermitted & AllTargetsMask;
-  if ((BusLogic_MultiMasterHostAdapterP(HostAdapter) &&
-       (HostAdapter->FirmwareVersion[0] >= '4' ||
-	HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus)) ||
-      BusLogic_FlashPointHostAdapterP(HostAdapter))
-    {
-      CommonSynchronousNegotiation = false;
-      if (SynchronousPermitted == 0)
-	{
-	  SynchronousMessage = "Disabled";
-	  CommonSynchronousNegotiation = true;
-	}
-      else if (SynchronousPermitted == AllTargetsMask)
-	{
-	  if (FastPermitted == 0)
-	    {
-	      SynchronousMessage = "Slow";
-	      CommonSynchronousNegotiation = true;
-	    }
-	  else if (FastPermitted == AllTargetsMask)
-	    {
-	      if (UltraPermitted == 0)
-		{
-		  SynchronousMessage = "Fast";
-		  CommonSynchronousNegotiation = true;
+	unsigned short AllTargetsMask = (1 << HostAdapter->MaxTargetDevices) - 1;
+	unsigned short SynchronousPermitted, FastPermitted;
+	unsigned short UltraPermitted, WidePermitted;
+	unsigned short DisconnectPermitted, TaggedQueuingPermitted;
+	boolean CommonSynchronousNegotiation, CommonTaggedQueueDepth;
+	char SynchronousString[BusLogic_MaxTargetDevices + 1];
+	char WideString[BusLogic_MaxTargetDevices + 1];
+	char DisconnectString[BusLogic_MaxTargetDevices + 1];
+	char TaggedQueuingString[BusLogic_MaxTargetDevices + 1];
+	char *SynchronousMessage = SynchronousString;
+	char *WideMessage = WideString;
+	char *DisconnectMessage = DisconnectString;
+	char *TaggedQueuingMessage = TaggedQueuingString;
+	int TargetID;
+	BusLogic_Info("Configuring BusLogic Model %s %s%s%s%s SCSI Host Adapter\n",
+		      HostAdapter, HostAdapter->ModelName,
+		      BusLogic_HostAdapterBusNames[HostAdapter->HostAdapterBusType], (HostAdapter->HostWideSCSI ? " Wide" : ""), (HostAdapter->HostDifferentialSCSI ? " Differential" : ""), (HostAdapter->HostUltraSCSI ? " Ultra" : ""));
+	BusLogic_Info("  Firmware Version: %s, I/O Address: 0x%X, " "IRQ Channel: %d/%s\n", HostAdapter, HostAdapter->FirmwareVersion, HostAdapter->IO_Address, HostAdapter->IRQ_Channel, (HostAdapter->LevelSensitiveInterrupt ? "Level" : "Edge"));
+	if (HostAdapter->HostAdapterBusType != BusLogic_PCI_Bus) {
+		BusLogic_Info("  DMA Channel: ", HostAdapter);
+		if (HostAdapter->DMA_Channel > 0)
+			BusLogic_Info("%d, ", HostAdapter, HostAdapter->DMA_Channel);
+		else
+			BusLogic_Info("None, ", HostAdapter);
+		if (HostAdapter->BIOS_Address > 0)
+			BusLogic_Info("BIOS Address: 0x%X, ", HostAdapter, HostAdapter->BIOS_Address);
+		else
+			BusLogic_Info("BIOS Address: None, ", HostAdapter);
+	} else {
+		BusLogic_Info("  PCI Bus: %d, Device: %d, Address: ", HostAdapter, HostAdapter->Bus, HostAdapter->Device);
+		if (HostAdapter->PCI_Address > 0)
+			BusLogic_Info("0x%X, ", HostAdapter, HostAdapter->PCI_Address);
+		else
+			BusLogic_Info("Unassigned, ", HostAdapter);
+	}
+	BusLogic_Info("Host Adapter SCSI ID: %d\n", HostAdapter, HostAdapter->SCSI_ID);
+	BusLogic_Info("  Parity Checking: %s, Extended Translation: %s\n", HostAdapter, (HostAdapter->ParityCheckingEnabled ? "Enabled" : "Disabled"), (HostAdapter->ExtendedTranslationEnabled ? "Enabled" : "Disabled"));
+	AllTargetsMask &= ~(1 << HostAdapter->SCSI_ID);
+	SynchronousPermitted = HostAdapter->SynchronousPermitted & AllTargetsMask;
+	FastPermitted = HostAdapter->FastPermitted & AllTargetsMask;
+	UltraPermitted = HostAdapter->UltraPermitted & AllTargetsMask;
+	if ((BusLogic_MultiMasterHostAdapterP(HostAdapter) && (HostAdapter->FirmwareVersion[0] >= '4' || HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus)) || BusLogic_FlashPointHostAdapterP(HostAdapter)) {
+		CommonSynchronousNegotiation = false;
+		if (SynchronousPermitted == 0) {
+			SynchronousMessage = "Disabled";
+			CommonSynchronousNegotiation = true;
+		} else if (SynchronousPermitted == AllTargetsMask) {
+			if (FastPermitted == 0) {
+				SynchronousMessage = "Slow";
+				CommonSynchronousNegotiation = true;
+			} else if (FastPermitted == AllTargetsMask) {
+				if (UltraPermitted == 0) {
+					SynchronousMessage = "Fast";
+					CommonSynchronousNegotiation = true;
+				} else if (UltraPermitted == AllTargetsMask) {
+					SynchronousMessage = "Ultra";
+					CommonSynchronousNegotiation = true;
+				}
+			}
 		}
-	      else if (UltraPermitted == AllTargetsMask)
-		{
-		  SynchronousMessage = "Ultra";
-		  CommonSynchronousNegotiation = true;
+		if (!CommonSynchronousNegotiation) {
+			for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+				SynchronousString[TargetID] = ((!(SynchronousPermitted & (1 << TargetID))) ? 'N' : (!(FastPermitted & (1 << TargetID)) ? 'S' : (!(UltraPermitted & (1 << TargetID)) ? 'F' : 'U')));
+			SynchronousString[HostAdapter->SCSI_ID] = '#';
+			SynchronousString[HostAdapter->MaxTargetDevices] = '\0';
 		}
-	    }
-	}
-      if (!CommonSynchronousNegotiation)
-	{
-	  for (TargetID = 0;
-	       TargetID < HostAdapter->MaxTargetDevices;
-	       TargetID++)
-	    SynchronousString[TargetID] =
-	      ((!(SynchronousPermitted & (1 << TargetID))) ? 'N' :
-	       (!(FastPermitted & (1 << TargetID)) ? 'S' :
-		(!(UltraPermitted & (1 << TargetID)) ? 'F' : 'U')));
-	  SynchronousString[HostAdapter->SCSI_ID] = '#';
-	  SynchronousString[HostAdapter->MaxTargetDevices] = '\0';
+	} else
+		SynchronousMessage = (SynchronousPermitted == 0 ? "Disabled" : "Enabled");
+	WidePermitted = HostAdapter->WidePermitted & AllTargetsMask;
+	if (WidePermitted == 0)
+		WideMessage = "Disabled";
+	else if (WidePermitted == AllTargetsMask)
+		WideMessage = "Enabled";
+	else {
+		for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+			WideString[TargetID] = ((WidePermitted & (1 << TargetID)) ? 'Y' : 'N');
+		WideString[HostAdapter->SCSI_ID] = '#';
+		WideString[HostAdapter->MaxTargetDevices] = '\0';
+	}
+	DisconnectPermitted = HostAdapter->DisconnectPermitted & AllTargetsMask;
+	if (DisconnectPermitted == 0)
+		DisconnectMessage = "Disabled";
+	else if (DisconnectPermitted == AllTargetsMask)
+		DisconnectMessage = "Enabled";
+	else {
+		for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+			DisconnectString[TargetID] = ((DisconnectPermitted & (1 << TargetID)) ? 'Y' : 'N');
+		DisconnectString[HostAdapter->SCSI_ID] = '#';
+		DisconnectString[HostAdapter->MaxTargetDevices] = '\0';
+	}
+	TaggedQueuingPermitted = HostAdapter->TaggedQueuingPermitted & AllTargetsMask;
+	if (TaggedQueuingPermitted == 0)
+		TaggedQueuingMessage = "Disabled";
+	else if (TaggedQueuingPermitted == AllTargetsMask)
+		TaggedQueuingMessage = "Enabled";
+	else {
+		for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+			TaggedQueuingString[TargetID] = ((TaggedQueuingPermitted & (1 << TargetID)) ? 'Y' : 'N');
+		TaggedQueuingString[HostAdapter->SCSI_ID] = '#';
+		TaggedQueuingString[HostAdapter->MaxTargetDevices] = '\0';
+	}
+	BusLogic_Info("  Synchronous Negotiation: %s, Wide Negotiation: %s\n", HostAdapter, SynchronousMessage, WideMessage);
+	BusLogic_Info("  Disconnect/Reconnect: %s, Tagged Queuing: %s\n", HostAdapter, DisconnectMessage, TaggedQueuingMessage);
+	if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) {
+		BusLogic_Info("  Scatter/Gather Limit: %d of %d segments, " "Mailboxes: %d\n", HostAdapter, HostAdapter->DriverScatterGatherLimit, HostAdapter->HostAdapterScatterGatherLimit, HostAdapter->MailboxCount);
+		BusLogic_Info("  Driver Queue Depth: %d, " "Host Adapter Queue Depth: %d\n", HostAdapter, HostAdapter->DriverQueueDepth, HostAdapter->HostAdapterQueueDepth);
+	} else
+		BusLogic_Info("  Driver Queue Depth: %d, " "Scatter/Gather Limit: %d segments\n", HostAdapter, HostAdapter->DriverQueueDepth, HostAdapter->DriverScatterGatherLimit);
+	BusLogic_Info("  Tagged Queue Depth: ", HostAdapter);
+	CommonTaggedQueueDepth = true;
+	for (TargetID = 1; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+		if (HostAdapter->QueueDepth[TargetID] != HostAdapter->QueueDepth[0]) {
+			CommonTaggedQueueDepth = false;
+			break;
+		}
+	if (CommonTaggedQueueDepth) {
+		if (HostAdapter->QueueDepth[0] > 0)
+			BusLogic_Info("%d", HostAdapter, HostAdapter->QueueDepth[0]);
+		else
+			BusLogic_Info("Automatic", HostAdapter);
+	} else
+		BusLogic_Info("Individual", HostAdapter);
+	BusLogic_Info(", Untagged Queue Depth: %d\n", HostAdapter, HostAdapter->UntaggedQueueDepth);
+	if (HostAdapter->TerminationInfoValid) {
+		if (HostAdapter->HostWideSCSI)
+			BusLogic_Info("  SCSI Bus Termination: %s", HostAdapter, (HostAdapter->LowByteTerminated ? (HostAdapter->HighByteTerminated ? "Both Enabled" : "Low Enabled")
+										  : (HostAdapter->HighByteTerminated ? "High Enabled" : "Both Disabled")));
+		else
+			BusLogic_Info("  SCSI Bus Termination: %s", HostAdapter, (HostAdapter->LowByteTerminated ? "Enabled" : "Disabled"));
+		if (HostAdapter->HostSupportsSCAM)
+			BusLogic_Info(", SCAM: %s", HostAdapter, (HostAdapter->SCAM_Enabled ? (HostAdapter->SCAM_Level2 ? "Enabled, Level 2" : "Enabled, Level 1")
+								  : "Disabled"));
+		BusLogic_Info("\n", HostAdapter);
 	}
-    }
-  else SynchronousMessage =
-	 (SynchronousPermitted == 0 ? "Disabled" : "Enabled");
-  WidePermitted = HostAdapter->WidePermitted & AllTargetsMask;
-  if (WidePermitted == 0)
-    WideMessage = "Disabled";
-  else if (WidePermitted == AllTargetsMask)
-    WideMessage = "Enabled";
-  else
-    {
-      for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-	 WideString[TargetID] =
-	   ((WidePermitted & (1 << TargetID)) ? 'Y' : 'N');
-      WideString[HostAdapter->SCSI_ID] = '#';
-      WideString[HostAdapter->MaxTargetDevices] = '\0';
-    }
-  DisconnectPermitted = HostAdapter->DisconnectPermitted & AllTargetsMask;
-  if (DisconnectPermitted == 0)
-    DisconnectMessage = "Disabled";
-  else if (DisconnectPermitted == AllTargetsMask)
-    DisconnectMessage = "Enabled";
-  else
-    {
-      for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-	DisconnectString[TargetID] =
-	  ((DisconnectPermitted & (1 << TargetID)) ? 'Y' : 'N');
-      DisconnectString[HostAdapter->SCSI_ID] = '#';
-      DisconnectString[HostAdapter->MaxTargetDevices] = '\0';
-    }
-  TaggedQueuingPermitted =
-    HostAdapter->TaggedQueuingPermitted & AllTargetsMask;
-  if (TaggedQueuingPermitted == 0)
-    TaggedQueuingMessage = "Disabled";
-  else if (TaggedQueuingPermitted == AllTargetsMask)
-    TaggedQueuingMessage = "Enabled";
-  else
-    {
-      for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-	TaggedQueuingString[TargetID] =
-	  ((TaggedQueuingPermitted & (1 << TargetID)) ? 'Y' : 'N');
-      TaggedQueuingString[HostAdapter->SCSI_ID] = '#';
-      TaggedQueuingString[HostAdapter->MaxTargetDevices] = '\0';
-    }
-  BusLogic_Info("  Synchronous Negotiation: %s, Wide Negotiation: %s\n",
-		HostAdapter, SynchronousMessage, WideMessage);
-  BusLogic_Info("  Disconnect/Reconnect: %s, Tagged Queuing: %s\n",
-		HostAdapter, DisconnectMessage, TaggedQueuingMessage);
-  if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
-    {
-      BusLogic_Info("  Scatter/Gather Limit: %d of %d segments, "
-		    "Mailboxes: %d\n", HostAdapter,
-		    HostAdapter->DriverScatterGatherLimit,
-		    HostAdapter->HostAdapterScatterGatherLimit,
-		    HostAdapter->MailboxCount);
-      BusLogic_Info("  Driver Queue Depth: %d, "
-		    "Host Adapter Queue Depth: %d\n",
-		    HostAdapter, HostAdapter->DriverQueueDepth,
-		    HostAdapter->HostAdapterQueueDepth);
-    }
-  else BusLogic_Info("  Driver Queue Depth: %d, "
-		     "Scatter/Gather Limit: %d segments\n",
-		     HostAdapter, HostAdapter->DriverQueueDepth,
-		     HostAdapter->DriverScatterGatherLimit);
-  BusLogic_Info("  Tagged Queue Depth: ", HostAdapter);
-  CommonTaggedQueueDepth = true;
-  for (TargetID = 1; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-    if (HostAdapter->QueueDepth[TargetID] != HostAdapter->QueueDepth[0])
-      {
-	CommonTaggedQueueDepth = false;
-	break;
-      }
-  if (CommonTaggedQueueDepth)
-    {
-      if (HostAdapter->QueueDepth[0] > 0)
-	BusLogic_Info("%d", HostAdapter, HostAdapter->QueueDepth[0]);
-      else BusLogic_Info("Automatic", HostAdapter);
-    }
-  else BusLogic_Info("Individual", HostAdapter);
-  BusLogic_Info(", Untagged Queue Depth: %d\n", HostAdapter,
-		HostAdapter->UntaggedQueueDepth);
-  if (HostAdapter->TerminationInfoValid)
-    {
-      if (HostAdapter->HostWideSCSI)
-	BusLogic_Info("  SCSI Bus Termination: %s", HostAdapter,
-		      (HostAdapter->LowByteTerminated
-		       ? (HostAdapter->HighByteTerminated
-			  ? "Both Enabled" : "Low Enabled")
-		       : (HostAdapter->HighByteTerminated
-			  ? "High Enabled" : "Both Disabled")));
-      else BusLogic_Info("  SCSI Bus Termination: %s", HostAdapter,
-			 (HostAdapter->LowByteTerminated ?
-			  "Enabled" : "Disabled"));
-      if (HostAdapter->HostSupportsSCAM)
-	BusLogic_Info(", SCAM: %s", HostAdapter,
-		      (HostAdapter->SCAM_Enabled
-		       ? (HostAdapter->SCAM_Level2
-			  ? "Enabled, Level 2" : "Enabled, Level 1")
-		       : "Disabled"));
-      BusLogic_Info("\n", HostAdapter);
-    }
-  /*
-    Indicate reporting the Host Adapter configuration completed successfully.
-  */
-  return true;
+	/*
+	   Indicate reporting the Host Adapter configuration completed successfully.
+	 */
+	return true;
 }
 
 
@@ -2259,43 +1873,34 @@ static boolean __init BusLogic_ReportHostAdapterConfiguration(struct BusLogic_Ho
 
 static boolean __init BusLogic_AcquireResources(struct BusLogic_HostAdapter *HostAdapter)
 {
-  if (HostAdapter->IRQ_Channel == 0)
-    {
-      BusLogic_Error("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n",
-		     HostAdapter);
-      return false;
-    }
-  /*
-    Acquire shared access to the IRQ Channel.
-  */
-  if (request_irq(HostAdapter->IRQ_Channel, BusLogic_InterruptHandler,
-		  SA_SHIRQ, HostAdapter->FullModelName, HostAdapter) < 0)
-    {
-      BusLogic_Error("UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n",
-		     HostAdapter, HostAdapter->IRQ_Channel);
-      return false;
-    }
-  HostAdapter->IRQ_ChannelAcquired = true;
-  /*
-    Acquire exclusive access to the DMA Channel.
-  */
-  if (HostAdapter->DMA_Channel > 0)
-    {
-      if (request_dma(HostAdapter->DMA_Channel,
-		      HostAdapter->FullModelName) < 0)
-	{
-	  BusLogic_Error("UNABLE TO ACQUIRE DMA CHANNEL %d - DETACHING\n",
-			 HostAdapter, HostAdapter->DMA_Channel);
-	  return false;
+	if (HostAdapter->IRQ_Channel == 0) {
+		BusLogic_Error("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n", HostAdapter);
+		return false;
 	}
-      set_dma_mode(HostAdapter->DMA_Channel, DMA_MODE_CASCADE);
-      enable_dma(HostAdapter->DMA_Channel);
-      HostAdapter->DMA_ChannelAcquired = true;
-    }
-  /*
-    Indicate the System Resource Acquisition completed successfully,
-  */
-  return true;
+	/*
+	   Acquire shared access to the IRQ Channel.
+	 */
+	if (request_irq(HostAdapter->IRQ_Channel, BusLogic_InterruptHandler, SA_SHIRQ, HostAdapter->FullModelName, HostAdapter) < 0) {
+		BusLogic_Error("UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n", HostAdapter, HostAdapter->IRQ_Channel);
+		return false;
+	}
+	HostAdapter->IRQ_ChannelAcquired = true;
+	/*
+	   Acquire exclusive access to the DMA Channel.
+	 */
+	if (HostAdapter->DMA_Channel > 0) {
+		if (request_dma(HostAdapter->DMA_Channel, HostAdapter->FullModelName) < 0) {
+			BusLogic_Error("UNABLE TO ACQUIRE DMA CHANNEL %d - DETACHING\n", HostAdapter, HostAdapter->DMA_Channel);
+			return false;
+		}
+		set_dma_mode(HostAdapter->DMA_Channel, DMA_MODE_CASCADE);
+		enable_dma(HostAdapter->DMA_Channel);
+		HostAdapter->DMA_ChannelAcquired = true;
+	}
+	/*
+	   Indicate the System Resource Acquisition completed successfully,
+	 */
+	return true;
 }
 
 
@@ -2306,26 +1911,24 @@ static boolean __init BusLogic_AcquireResources(struct BusLogic_HostAdapter *Hos
 
 static void BusLogic_ReleaseResources(struct BusLogic_HostAdapter *HostAdapter)
 {
-  /*
-    Release shared access to the IRQ Channel.
-  */
-  if (HostAdapter->IRQ_ChannelAcquired)
-    free_irq(HostAdapter->IRQ_Channel, HostAdapter);
-  /*
-    Release exclusive access to the DMA Channel.
-  */
-  if (HostAdapter->DMA_ChannelAcquired)
-    free_dma(HostAdapter->DMA_Channel);
-  /*
-    Release any allocated memory structs not released elsewhere
-  */
-  if (HostAdapter->MailboxSpace)
-    pci_free_consistent(HostAdapter->PCI_Device, HostAdapter->MailboxSize,
-			HostAdapter->MailboxSpace,
-			HostAdapter->MailboxSpaceHandle);
-  HostAdapter->MailboxSpace = NULL;
-  HostAdapter->MailboxSpaceHandle = 0;
-  HostAdapter->MailboxSize = 0;
+	/*
+	   Release shared access to the IRQ Channel.
+	 */
+	if (HostAdapter->IRQ_ChannelAcquired)
+		free_irq(HostAdapter->IRQ_Channel, HostAdapter);
+	/*
+	   Release exclusive access to the DMA Channel.
+	 */
+	if (HostAdapter->DMA_ChannelAcquired)
+		free_dma(HostAdapter->DMA_Channel);
+	/*
+	   Release any allocated memory structs not released elsewhere
+	 */
+	if (HostAdapter->MailboxSpace)
+		pci_free_consistent(HostAdapter->PCI_Device, HostAdapter->MailboxSize, HostAdapter->MailboxSpace, HostAdapter->MailboxSpaceHandle);
+	HostAdapter->MailboxSpace = NULL;
+	HostAdapter->MailboxSpaceHandle = 0;
+	HostAdapter->MailboxSize = 0;
 }
 
 
@@ -2338,114 +1941,94 @@ static void BusLogic_ReleaseResources(struct BusLogic_HostAdapter *HostAdapter)
 static boolean BusLogic_InitializeHostAdapter(struct BusLogic_HostAdapter
 					      *HostAdapter)
 {
-  struct BusLogic_ExtendedMailboxRequest ExtendedMailboxRequest;
-  enum BusLogic_RoundRobinModeRequest RoundRobinModeRequest;
-  enum BusLogic_SetCCBFormatRequest SetCCBFormatRequest;
-  int TargetID;
-  /*
-    Initialize the pointers to the first and last CCBs that are queued for
-    completion processing.
-  */
-  HostAdapter->FirstCompletedCCB = NULL;
-  HostAdapter->LastCompletedCCB = NULL;
-  /*
-    Initialize the Bus Device Reset Pending CCB, Tagged Queuing Active,
-    Command Successful Flag, Active Commands, and Commands Since Reset
-    for each Target Device.
-  */
-  for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-    {
-      HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
-      HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
-      HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = false;
-      HostAdapter->ActiveCommands[TargetID] = 0;
-      HostAdapter->CommandsSinceReset[TargetID] = 0;
-    }
-  /*
-    FlashPoint Host Adapters do not use Outgoing and Incoming Mailboxes.
-  */
-  if (BusLogic_FlashPointHostAdapterP(HostAdapter)) goto Done;
-  /*
-    Initialize the Outgoing and Incoming Mailbox pointers.
-  */
-  HostAdapter->MailboxSize = HostAdapter->MailboxCount *
-    (sizeof(struct BusLogic_OutgoingMailbox) + sizeof(struct BusLogic_IncomingMailbox));
-  HostAdapter->MailboxSpace = pci_alloc_consistent(HostAdapter->PCI_Device,
-    HostAdapter->MailboxSize, &HostAdapter->MailboxSpaceHandle);
-  if (HostAdapter->MailboxSpace == NULL)
-    return BusLogic_Failure(HostAdapter, "MAILBOX ALLOCATION");
-  HostAdapter->FirstOutgoingMailbox =
-    (struct BusLogic_OutgoingMailbox *) HostAdapter->MailboxSpace;
-  HostAdapter->LastOutgoingMailbox =
-    HostAdapter->FirstOutgoingMailbox + HostAdapter->MailboxCount - 1;
-  HostAdapter->NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
-  HostAdapter->FirstIncomingMailbox =
-    (struct BusLogic_IncomingMailbox *) (HostAdapter->LastOutgoingMailbox + 1);
-  HostAdapter->LastIncomingMailbox =
-    HostAdapter->FirstIncomingMailbox + HostAdapter->MailboxCount - 1;
-  HostAdapter->NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
-
-  /*
-    Initialize the Outgoing and Incoming Mailbox structures.
-  */
-  memset(HostAdapter->FirstOutgoingMailbox, 0,
-	 HostAdapter->MailboxCount * sizeof(struct BusLogic_OutgoingMailbox));
-  memset(HostAdapter->FirstIncomingMailbox, 0,
-	 HostAdapter->MailboxCount * sizeof(struct BusLogic_IncomingMailbox));
-  /*
-    Initialize the Host Adapter's Pointer to the Outgoing/Incoming Mailboxes.
-  */
-  ExtendedMailboxRequest.MailboxCount = HostAdapter->MailboxCount;
-  ExtendedMailboxRequest.BaseMailboxAddress =
-    (u32) HostAdapter->MailboxSpaceHandle;
-  if (BusLogic_Command(HostAdapter, BusLogic_InitializeExtendedMailbox,
-		       &ExtendedMailboxRequest,
-		       sizeof(ExtendedMailboxRequest), NULL, 0) < 0)
-    return BusLogic_Failure(HostAdapter, "MAILBOX INITIALIZATION");
-  /*
-    Enable Strict Round Robin Mode if supported by the Host Adapter.  In
-    Strict Round Robin Mode, the Host Adapter only looks at the next Outgoing
-    Mailbox for each new command, rather than scanning through all the
-    Outgoing Mailboxes to find any that have new commands in them.  Strict
-    Round Robin Mode is significantly more efficient.
-  */
-  if (HostAdapter->StrictRoundRobinModeSupport)
-    {
-      RoundRobinModeRequest = BusLogic_StrictRoundRobinMode;
-      if (BusLogic_Command(HostAdapter, BusLogic_EnableStrictRoundRobinMode,
-			   &RoundRobinModeRequest,
-			   sizeof(RoundRobinModeRequest), NULL, 0) < 0)
-	return BusLogic_Failure(HostAdapter, "ENABLE STRICT ROUND ROBIN MODE");
-    }
-  /*
-    For Host Adapters that support Extended LUN Format CCBs, issue the Set CCB
-    Format command to allow 32 Logical Units per Target Device.
-  */
-  if (HostAdapter->ExtendedLUNSupport)
-    {
-      SetCCBFormatRequest = BusLogic_ExtendedLUNFormatCCB;
-      if (BusLogic_Command(HostAdapter, BusLogic_SetCCBFormat,
-			   &SetCCBFormatRequest, sizeof(SetCCBFormatRequest),
-			   NULL, 0) < 0)
-	return BusLogic_Failure(HostAdapter, "SET CCB FORMAT");
-    }
-  /*
-    Announce Successful Initialization.
-  */
-Done:
-  if (!HostAdapter->HostAdapterInitialized)
-    {
-      BusLogic_Info("*** %s Initialized Successfully ***\n",
-		    HostAdapter, HostAdapter->FullModelName);
-      BusLogic_Info("\n", HostAdapter);
-    }
-  else BusLogic_Warning("*** %s Initialized Successfully ***\n",
-			HostAdapter, HostAdapter->FullModelName);
-  HostAdapter->HostAdapterInitialized = true;
-  /*
-    Indicate the Host Adapter Initialization completed successfully.
-  */
-  return true;
+	struct BusLogic_ExtendedMailboxRequest ExtendedMailboxRequest;
+	enum BusLogic_RoundRobinModeRequest RoundRobinModeRequest;
+	enum BusLogic_SetCCBFormatRequest SetCCBFormatRequest;
+	int TargetID;
+	/*
+	   Initialize the pointers to the first and last CCBs that are queued for
+	   completion processing.
+	 */
+	HostAdapter->FirstCompletedCCB = NULL;
+	HostAdapter->LastCompletedCCB = NULL;
+	/*
+	   Initialize the Bus Device Reset Pending CCB, Tagged Queuing Active,
+	   Command Successful Flag, Active Commands, and Commands Since Reset
+	   for each Target Device.
+	 */
+	for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
+		HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
+		HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
+		HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = false;
+		HostAdapter->ActiveCommands[TargetID] = 0;
+		HostAdapter->CommandsSinceReset[TargetID] = 0;
+	}
+	/*
+	   FlashPoint Host Adapters do not use Outgoing and Incoming Mailboxes.
+	 */
+	if (BusLogic_FlashPointHostAdapterP(HostAdapter))
+		goto Done;
+	/*
+	   Initialize the Outgoing and Incoming Mailbox pointers.
+	 */
+	HostAdapter->MailboxSize = HostAdapter->MailboxCount * (sizeof(struct BusLogic_OutgoingMailbox) + sizeof(struct BusLogic_IncomingMailbox));
+	HostAdapter->MailboxSpace = pci_alloc_consistent(HostAdapter->PCI_Device, HostAdapter->MailboxSize, &HostAdapter->MailboxSpaceHandle);
+	if (HostAdapter->MailboxSpace == NULL)
+		return BusLogic_Failure(HostAdapter, "MAILBOX ALLOCATION");
+	HostAdapter->FirstOutgoingMailbox = (struct BusLogic_OutgoingMailbox *) HostAdapter->MailboxSpace;
+	HostAdapter->LastOutgoingMailbox = HostAdapter->FirstOutgoingMailbox + HostAdapter->MailboxCount - 1;
+	HostAdapter->NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
+	HostAdapter->FirstIncomingMailbox = (struct BusLogic_IncomingMailbox *) (HostAdapter->LastOutgoingMailbox + 1);
+	HostAdapter->LastIncomingMailbox = HostAdapter->FirstIncomingMailbox + HostAdapter->MailboxCount - 1;
+	HostAdapter->NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
+
+	/*
+	   Initialize the Outgoing and Incoming Mailbox structures.
+	 */
+	memset(HostAdapter->FirstOutgoingMailbox, 0, HostAdapter->MailboxCount * sizeof(struct BusLogic_OutgoingMailbox));
+	memset(HostAdapter->FirstIncomingMailbox, 0, HostAdapter->MailboxCount * sizeof(struct BusLogic_IncomingMailbox));
+	/*
+	   Initialize the Host Adapter's Pointer to the Outgoing/Incoming Mailboxes.
+	 */
+	ExtendedMailboxRequest.MailboxCount = HostAdapter->MailboxCount;
+	ExtendedMailboxRequest.BaseMailboxAddress = (u32) HostAdapter->MailboxSpaceHandle;
+	if (BusLogic_Command(HostAdapter, BusLogic_InitializeExtendedMailbox, &ExtendedMailboxRequest, sizeof(ExtendedMailboxRequest), NULL, 0) < 0)
+		return BusLogic_Failure(HostAdapter, "MAILBOX INITIALIZATION");
+	/*
+	   Enable Strict Round Robin Mode if supported by the Host Adapter.  In
+	   Strict Round Robin Mode, the Host Adapter only looks at the next Outgoing
+	   Mailbox for each new command, rather than scanning through all the
+	   Outgoing Mailboxes to find any that have new commands in them.  Strict
+	   Round Robin Mode is significantly more efficient.
+	 */
+	if (HostAdapter->StrictRoundRobinModeSupport) {
+		RoundRobinModeRequest = BusLogic_StrictRoundRobinMode;
+		if (BusLogic_Command(HostAdapter, BusLogic_EnableStrictRoundRobinMode, &RoundRobinModeRequest, sizeof(RoundRobinModeRequest), NULL, 0) < 0)
+			return BusLogic_Failure(HostAdapter, "ENABLE STRICT ROUND ROBIN MODE");
+	}
+	/*
+	   For Host Adapters that support Extended LUN Format CCBs, issue the Set CCB
+	   Format command to allow 32 Logical Units per Target Device.
+	 */
+	if (HostAdapter->ExtendedLUNSupport) {
+		SetCCBFormatRequest = BusLogic_ExtendedLUNFormatCCB;
+		if (BusLogic_Command(HostAdapter, BusLogic_SetCCBFormat, &SetCCBFormatRequest, sizeof(SetCCBFormatRequest), NULL, 0) < 0)
+			return BusLogic_Failure(HostAdapter, "SET CCB FORMAT");
+	}
+	/*
+	   Announce Successful Initialization.
+	 */
+      Done:
+	if (!HostAdapter->HostAdapterInitialized) {
+		BusLogic_Info("*** %s Initialized Successfully ***\n", HostAdapter, HostAdapter->FullModelName);
+		BusLogic_Info("\n", HostAdapter);
+	} else
+		BusLogic_Warning("*** %s Initialized Successfully ***\n", HostAdapter, HostAdapter->FullModelName);
+	HostAdapter->HostAdapterInitialized = true;
+	/*
+	   Indicate the Host Adapter Initialization completed successfully.
+	 */
+	return true;
 }
 
 
@@ -2457,127 +2040,106 @@ Done:
 static boolean __init BusLogic_TargetDeviceInquiry(struct BusLogic_HostAdapter
 						   *HostAdapter)
 {
-  u16 InstalledDevices;
-  u8 InstalledDevicesID0to7[8];
-  struct BusLogic_SetupInformation SetupInformation;
-  u8 SynchronousPeriod[BusLogic_MaxTargetDevices];
-  unsigned char RequestedReplyLength;
-  int TargetID;
-  /*
-    Wait a few seconds between the Host Adapter Hard Reset which initiates
-    a SCSI Bus Reset and issuing any SCSI Commands.  Some SCSI devices get
-    confused if they receive SCSI Commands too soon after a SCSI Bus Reset.
-  */
-  BusLogic_Delay(HostAdapter->BusSettleTime);
-  /*
-    FlashPoint Host Adapters do not provide for Target Device Inquiry.
-  */
-  if (BusLogic_FlashPointHostAdapterP(HostAdapter)) return true;
-  /*
-    Inhibit the Target Device Inquiry if requested.
-  */
-  if (HostAdapter->DriverOptions != NULL &&
-      HostAdapter->DriverOptions->LocalOptions.InhibitTargetInquiry)
-    return true;
-  /*
-    Issue the Inquire Target Devices command for host adapters with firmware
-    version 4.25 or later, or the Inquire Installed Devices ID 0 to 7 command
-    for older host adapters.  This is necessary to force Synchronous Transfer
-    Negotiation so that the Inquire Setup Information and Inquire Synchronous
-    Period commands will return valid data.  The Inquire Target Devices command
-    is preferable to Inquire Installed Devices ID 0 to 7 since it only probes
-    Logical Unit 0 of each Target Device.
-  */
-  if (strcmp(HostAdapter->FirmwareVersion, "4.25") >= 0)
-    {
-
-      /*
-       * Issue a Inquire Target Devices command.  Inquire Target Devices only
-       * tests Logical Unit 0 of each Target Device unlike the Inquire Installed
-       * Devices commands which test Logical Units 0 - 7.  Two bytes are
-       * returned, where byte 0 bit 0 set indicates that Target Device 0 exists,
-       * and so on.
-       */
-
-      if (BusLogic_Command(HostAdapter, BusLogic_InquireTargetDevices, NULL, 0,
-			   &InstalledDevices, sizeof(InstalledDevices))
-	  != sizeof(InstalledDevices))
-	return BusLogic_Failure(HostAdapter, "INQUIRE TARGET DEVICES");
-      for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-	HostAdapter->TargetFlags[TargetID].TargetExists =
-	  (InstalledDevices & (1 << TargetID) ? true : false);
-    }
-  else
-    {
-
-      /*
-       * Issue an Inquire Installed Devices command.  For each Target Device,
-       * a byte is returned where bit 0 set indicates that Logical Unit 0
-       * exists, bit 1 set indicates that Logical Unit 1 exists, and so on.
-       */
-
-      if (BusLogic_Command(HostAdapter, BusLogic_InquireInstalledDevicesID0to7,
-			   NULL, 0, &InstalledDevicesID0to7,
-			   sizeof(InstalledDevicesID0to7))
-	  != sizeof(InstalledDevicesID0to7))
-	return BusLogic_Failure(HostAdapter,
-				"INQUIRE INSTALLED DEVICES ID 0 TO 7");
-      for (TargetID = 0; TargetID < 8; TargetID++)
-	HostAdapter->TargetFlags[TargetID].TargetExists =
-	  (InstalledDevicesID0to7[TargetID] != 0 ? true : false);
-    }
-  /*
-    Issue the Inquire Setup Information command.
-  */
-  RequestedReplyLength = sizeof(SetupInformation);
-  if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation,
-		       &RequestedReplyLength, sizeof(RequestedReplyLength),
-		       &SetupInformation, sizeof(SetupInformation))
-      != sizeof(SetupInformation))
-    return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION");
-  for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-      HostAdapter->SynchronousOffset[TargetID] =
-	(TargetID < 8
-	 ? SetupInformation.SynchronousValuesID0to7[TargetID].Offset
-	 : SetupInformation.SynchronousValuesID8to15[TargetID-8].Offset);
-  if (strcmp(HostAdapter->FirmwareVersion, "5.06L") >= 0)
-    for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-      HostAdapter->TargetFlags[TargetID].WideTransfersActive =
-	(TargetID < 8
-	 ? (SetupInformation.WideTransfersActiveID0to7 & (1 << TargetID)
-	    ? true : false)
-	 : (SetupInformation.WideTransfersActiveID8to15 & (1 << (TargetID-8))
-	    ? true : false));
-  /*
-    Issue the Inquire Synchronous Period command.
-  */
-  if (HostAdapter->FirmwareVersion[0] >= '3')
-    {
-
-      /* Issue a Inquire Synchronous Period command.  For each Target Device,
-       * a byte is returned which represents the Synchronous Transfer Period
-       * in units of 10 nanoseconds.
-       */
-
-      RequestedReplyLength = sizeof(SynchronousPeriod);
-      if (BusLogic_Command(HostAdapter, BusLogic_InquireSynchronousPeriod,
-			   &RequestedReplyLength, sizeof(RequestedReplyLength),
-			   &SynchronousPeriod, sizeof(SynchronousPeriod))
-	  != sizeof(SynchronousPeriod))
-	return BusLogic_Failure(HostAdapter, "INQUIRE SYNCHRONOUS PERIOD");
-      for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-	HostAdapter->SynchronousPeriod[TargetID] = SynchronousPeriod[TargetID];
-    }
-  else
-    for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-      if (SetupInformation.SynchronousValuesID0to7[TargetID].Offset > 0)
-	HostAdapter->SynchronousPeriod[TargetID] =
-	  20 + 5 * SetupInformation.SynchronousValuesID0to7[TargetID]
-				   .TransferPeriod;
-  /*
-    Indicate the Target Device Inquiry completed successfully.
-  */
-  return true;
+	u16 InstalledDevices;
+	u8 InstalledDevicesID0to7[8];
+	struct BusLogic_SetupInformation SetupInformation;
+	u8 SynchronousPeriod[BusLogic_MaxTargetDevices];
+	unsigned char RequestedReplyLength;
+	int TargetID;
+	/*
+	   Wait a few seconds between the Host Adapter Hard Reset which initiates
+	   a SCSI Bus Reset and issuing any SCSI Commands.  Some SCSI devices get
+	   confused if they receive SCSI Commands too soon after a SCSI Bus Reset.
+	 */
+	BusLogic_Delay(HostAdapter->BusSettleTime);
+	/*
+	   FlashPoint Host Adapters do not provide for Target Device Inquiry.
+	 */
+	if (BusLogic_FlashPointHostAdapterP(HostAdapter))
+		return true;
+	/*
+	   Inhibit the Target Device Inquiry if requested.
+	 */
+	if (HostAdapter->DriverOptions != NULL && HostAdapter->DriverOptions->LocalOptions.InhibitTargetInquiry)
+		return true;
+	/*
+	   Issue the Inquire Target Devices command for host adapters with firmware
+	   version 4.25 or later, or the Inquire Installed Devices ID 0 to 7 command
+	   for older host adapters.  This is necessary to force Synchronous Transfer
+	   Negotiation so that the Inquire Setup Information and Inquire Synchronous
+	   Period commands will return valid data.  The Inquire Target Devices command
+	   is preferable to Inquire Installed Devices ID 0 to 7 since it only probes
+	   Logical Unit 0 of each Target Device.
+	 */
+	if (strcmp(HostAdapter->FirmwareVersion, "4.25") >= 0) {
+
+		/*
+		 * Issue a Inquire Target Devices command.  Inquire Target Devices only
+		 * tests Logical Unit 0 of each Target Device unlike the Inquire Installed
+		 * Devices commands which test Logical Units 0 - 7.  Two bytes are
+		 * returned, where byte 0 bit 0 set indicates that Target Device 0 exists,
+		 * and so on.
+		 */
+
+		if (BusLogic_Command(HostAdapter, BusLogic_InquireTargetDevices, NULL, 0, &InstalledDevices, sizeof(InstalledDevices))
+		    != sizeof(InstalledDevices))
+			return BusLogic_Failure(HostAdapter, "INQUIRE TARGET DEVICES");
+		for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+			HostAdapter->TargetFlags[TargetID].TargetExists = (InstalledDevices & (1 << TargetID) ? true : false);
+	} else {
+
+		/*
+		 * Issue an Inquire Installed Devices command.  For each Target Device,
+		 * a byte is returned where bit 0 set indicates that Logical Unit 0
+		 * exists, bit 1 set indicates that Logical Unit 1 exists, and so on.
+		 */
+
+		if (BusLogic_Command(HostAdapter, BusLogic_InquireInstalledDevicesID0to7, NULL, 0, &InstalledDevicesID0to7, sizeof(InstalledDevicesID0to7))
+		    != sizeof(InstalledDevicesID0to7))
+			return BusLogic_Failure(HostAdapter, "INQUIRE INSTALLED DEVICES ID 0 TO 7");
+		for (TargetID = 0; TargetID < 8; TargetID++)
+			HostAdapter->TargetFlags[TargetID].TargetExists = (InstalledDevicesID0to7[TargetID] != 0 ? true : false);
+	}
+	/*
+	   Issue the Inquire Setup Information command.
+	 */
+	RequestedReplyLength = sizeof(SetupInformation);
+	if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation, &RequestedReplyLength, sizeof(RequestedReplyLength), &SetupInformation, sizeof(SetupInformation))
+	    != sizeof(SetupInformation))
+		return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION");
+	for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+		HostAdapter->SynchronousOffset[TargetID] = (TargetID < 8 ? SetupInformation.SynchronousValuesID0to7[TargetID].Offset : SetupInformation.SynchronousValuesID8to15[TargetID - 8].Offset);
+	if (strcmp(HostAdapter->FirmwareVersion, "5.06L") >= 0)
+		for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+			HostAdapter->TargetFlags[TargetID].WideTransfersActive = (TargetID < 8 ? (SetupInformation.WideTransfersActiveID0to7 & (1 << TargetID)
+												  ? true : false)
+										  : (SetupInformation.WideTransfersActiveID8to15 & (1 << (TargetID - 8))
+										     ? true : false));
+	/*
+	   Issue the Inquire Synchronous Period command.
+	 */
+	if (HostAdapter->FirmwareVersion[0] >= '3') {
+
+		/* Issue a Inquire Synchronous Period command.  For each Target Device,
+		 * a byte is returned which represents the Synchronous Transfer Period
+		 * in units of 10 nanoseconds.
+		 */
+
+		RequestedReplyLength = sizeof(SynchronousPeriod);
+		if (BusLogic_Command(HostAdapter, BusLogic_InquireSynchronousPeriod, &RequestedReplyLength, sizeof(RequestedReplyLength), &SynchronousPeriod, sizeof(SynchronousPeriod))
+		    != sizeof(SynchronousPeriod))
+			return BusLogic_Failure(HostAdapter, "INQUIRE SYNCHRONOUS PERIOD");
+		for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+			HostAdapter->SynchronousPeriod[TargetID] = SynchronousPeriod[TargetID];
+	} else
+		for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+			if (SetupInformation.SynchronousValuesID0to7[TargetID].Offset > 0)
+				HostAdapter->SynchronousPeriod[TargetID] = 20 + 5 * SetupInformation.SynchronousValuesID0to7[TargetID]
+				    .TransferPeriod;
+	/*
+	   Indicate the Target Device Inquiry completed successfully.
+	 */
+	return true;
 }
 
 /*
@@ -2590,18 +2152,17 @@ static boolean __init BusLogic_TargetDeviceInquiry(struct BusLogic_HostAdapter
 */
 
 static void __init BusLogic_InitializeHostStructure(struct BusLogic_HostAdapter
-						    *HostAdapter,
-						    struct Scsi_Host *Host)
+						    *HostAdapter, struct Scsi_Host *Host)
 {
-  Host->max_id = HostAdapter->MaxTargetDevices;
-  Host->max_lun = HostAdapter->MaxLogicalUnits;
-  Host->max_channel = 0;
-  Host->unique_id = HostAdapter->IO_Address;
-  Host->this_id = HostAdapter->SCSI_ID;
-  Host->can_queue = HostAdapter->DriverQueueDepth;
-  Host->sg_tablesize = HostAdapter->DriverScatterGatherLimit;
-  Host->unchecked_isa_dma = HostAdapter->BounceBuffersRequired;
-  Host->cmd_per_lun = HostAdapter->UntaggedQueueDepth;
+	Host->max_id = HostAdapter->MaxTargetDevices;
+	Host->max_lun = HostAdapter->MaxLogicalUnits;
+	Host->max_channel = 0;
+	Host->unique_id = HostAdapter->IO_Address;
+	Host->this_id = HostAdapter->SCSI_ID;
+	Host->can_queue = HostAdapter->DriverQueueDepth;
+	Host->sg_tablesize = HostAdapter->DriverScatterGatherLimit;
+	Host->unchecked_isa_dma = HostAdapter->BounceBuffersRequired;
+	Host->cmd_per_lun = HostAdapter->UntaggedQueueDepth;
 }
 
 /*
@@ -2614,38 +2175,29 @@ static void __init BusLogic_InitializeHostStructure(struct BusLogic_HostAdapter
 */
 static int BusLogic_SlaveConfigure(struct scsi_device *Device)
 {
-  struct BusLogic_HostAdapter *HostAdapter =
-    (struct BusLogic_HostAdapter *) Device->host->hostdata;
-  int TargetID = Device->id;
-  int QueueDepth = HostAdapter->QueueDepth[TargetID];
-
-  if (HostAdapter->TargetFlags[TargetID].TaggedQueuingSupported &&
-      (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)))
-    {
-      if (QueueDepth == 0)
-	QueueDepth = BusLogic_MaxAutomaticTaggedQueueDepth;
-      HostAdapter->QueueDepth[TargetID] = QueueDepth;
-      scsi_adjust_queue_depth(Device, MSG_SIMPLE_TAG, QueueDepth);
-    }
-  else
-    {
-      HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID);
-      QueueDepth = HostAdapter->UntaggedQueueDepth;
-      HostAdapter->QueueDepth[TargetID] = QueueDepth;
-      scsi_adjust_queue_depth(Device, 0, QueueDepth);
-    }
-  QueueDepth = 0;
-  for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-    if (HostAdapter->TargetFlags[TargetID].TargetExists)
-      {
-	QueueDepth += HostAdapter->QueueDepth[TargetID];
-      }
-  if (QueueDepth > HostAdapter->AllocatedCCBs)
-    BusLogic_CreateAdditionalCCBs(HostAdapter,
-				  QueueDepth
-				  - HostAdapter->AllocatedCCBs,
-				  false);
-  return 0;
+	struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Device->host->hostdata;
+	int TargetID = Device->id;
+	int QueueDepth = HostAdapter->QueueDepth[TargetID];
+
+	if (HostAdapter->TargetFlags[TargetID].TaggedQueuingSupported && (HostAdapter->TaggedQueuingPermitted & (1 << TargetID))) {
+		if (QueueDepth == 0)
+			QueueDepth = BusLogic_MaxAutomaticTaggedQueueDepth;
+		HostAdapter->QueueDepth[TargetID] = QueueDepth;
+		scsi_adjust_queue_depth(Device, MSG_SIMPLE_TAG, QueueDepth);
+	} else {
+		HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID);
+		QueueDepth = HostAdapter->UntaggedQueueDepth;
+		HostAdapter->QueueDepth[TargetID] = QueueDepth;
+		scsi_adjust_queue_depth(Device, 0, QueueDepth);
+	}
+	QueueDepth = 0;
+	for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+		if (HostAdapter->TargetFlags[TargetID].TargetExists) {
+			QueueDepth += HostAdapter->QueueDepth[TargetID];
+		}
+	if (QueueDepth > HostAdapter->AllocatedCCBs)
+		BusLogic_CreateAdditionalCCBs(HostAdapter, QueueDepth - HostAdapter->AllocatedCCBs, false);
+	return 0;
 }
 
 /*
@@ -2658,162 +2210,145 @@ static int BusLogic_SlaveConfigure(struct scsi_device *Device)
 
 static int __init BusLogic_DetectHostAdapter(struct scsi_host_template *HostTemplate)
 {
-  int BusLogicHostAdapterCount = 0, DriverOptionsIndex = 0, ProbeIndex;
-  struct BusLogic_HostAdapter *PrototypeHostAdapter;
-  if (BusLogic_ProbeOptions.NoProbe) return 0;
-  BusLogic_ProbeInfoList = (struct BusLogic_ProbeInfo *)
-    kmalloc(BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo),
-	    GFP_ATOMIC);
-  if (BusLogic_ProbeInfoList == NULL)
-    {
-      BusLogic_Error("BusLogic: Unable to allocate Probe Info List\n", NULL);
-      return 0;
-    }
-  memset(BusLogic_ProbeInfoList, 0,
-	 BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo));
-  PrototypeHostAdapter = (struct BusLogic_HostAdapter *)
-    kmalloc(sizeof(struct BusLogic_HostAdapter), GFP_ATOMIC);
-  if (PrototypeHostAdapter == NULL)
-    {
-      kfree(BusLogic_ProbeInfoList);
-      BusLogic_Error("BusLogic: Unable to allocate Prototype "
-		     "Host Adapter\n", NULL);
-      return 0;
-    }
-  memset(PrototypeHostAdapter, 0, sizeof(struct BusLogic_HostAdapter));
+	int BusLogicHostAdapterCount = 0, DriverOptionsIndex = 0, ProbeIndex;
+	struct BusLogic_HostAdapter *PrototypeHostAdapter;
+	if (BusLogic_ProbeOptions.NoProbe)
+		return 0;
+	BusLogic_ProbeInfoList = (struct BusLogic_ProbeInfo *)
+	    kmalloc(BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo), GFP_ATOMIC);
+	if (BusLogic_ProbeInfoList == NULL) {
+		BusLogic_Error("BusLogic: Unable to allocate Probe Info List\n", NULL);
+		return 0;
+	}
+	memset(BusLogic_ProbeInfoList, 0, BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo));
+	PrototypeHostAdapter = (struct BusLogic_HostAdapter *)
+	    kmalloc(sizeof(struct BusLogic_HostAdapter), GFP_ATOMIC);
+	if (PrototypeHostAdapter == NULL) {
+		kfree(BusLogic_ProbeInfoList);
+		BusLogic_Error("BusLogic: Unable to allocate Prototype " "Host Adapter\n", NULL);
+		return 0;
+	}
+	memset(PrototypeHostAdapter, 0, sizeof(struct BusLogic_HostAdapter));
 #ifdef MODULE
-  if (BusLogic != NULL)
-    BusLogic_Setup(BusLogic);
+	if (BusLogic != NULL)
+		BusLogic_Setup(BusLogic);
 #endif
-  BusLogic_InitializeProbeInfoList(PrototypeHostAdapter);
-  for (ProbeIndex = 0; ProbeIndex < BusLogic_ProbeInfoCount; ProbeIndex++)
-    {
-      struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[ProbeIndex];
-      struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter;
-      struct Scsi_Host *Host;
-      if (ProbeInfo->IO_Address == 0) continue;
-      memset(HostAdapter, 0, sizeof(struct BusLogic_HostAdapter));
-      HostAdapter->HostAdapterType = ProbeInfo->HostAdapterType;
-      HostAdapter->HostAdapterBusType = ProbeInfo->HostAdapterBusType;
-      HostAdapter->IO_Address = ProbeInfo->IO_Address;
-      HostAdapter->PCI_Address = ProbeInfo->PCI_Address;
-      HostAdapter->Bus = ProbeInfo->Bus;
-      HostAdapter->Device = ProbeInfo->Device;
-      HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel;
-      HostAdapter->AddressCount =
-	BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType];
-      /*
-	Probe the Host Adapter.  If unsuccessful, abort further initialization.
-      */
-      if (!BusLogic_ProbeHostAdapter(HostAdapter)) continue;
-      /*
-	Hard Reset the Host Adapter.  If unsuccessful, abort further
-	initialization.
-      */
-      if (!BusLogic_HardwareResetHostAdapter(HostAdapter, true)) continue;
-      /*
-	Check the Host Adapter.  If unsuccessful, abort further initialization.
-      */
-      if (!BusLogic_CheckHostAdapter(HostAdapter)) continue;
-      /*
-	Initialize the Driver Options field if provided.
-      */
-      if (DriverOptionsIndex < BusLogic_DriverOptionsCount)
-	HostAdapter->DriverOptions =
-	  &BusLogic_DriverOptions[DriverOptionsIndex++];
-      /*
-	Announce the Driver Version and Date, Author's Name, Copyright Notice,
-	and Electronic Mail Address.
-      */
-      BusLogic_AnnounceDriver(HostAdapter);
-      /*
-	Register usage of the I/O Address range.  From this point onward, any
-	failure will be assumed to be due to a problem with the Host Adapter,
-	rather than due to having mistakenly identified this port as belonging
-	to a BusLogic Host Adapter.  The I/O Address range will not be
-	released, thereby preventing it from being incorrectly identified as
-	any other type of Host Adapter.
-      */
-      if (!request_region(HostAdapter->IO_Address, HostAdapter->AddressCount,
-		     "BusLogic")) continue;
-      /*
-	Register the SCSI Host structure.
-      */
-
-      Host = scsi_host_alloc(HostTemplate, sizeof(struct BusLogic_HostAdapter));
-      if(Host==NULL)
-      {
-      	release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
-      	continue;
-      }
-      HostAdapter = (struct BusLogic_HostAdapter *) Host->hostdata;
-      memcpy(HostAdapter, PrototypeHostAdapter, sizeof(struct BusLogic_HostAdapter));
-      HostAdapter->SCSI_Host = Host;
-      HostAdapter->HostNumber = Host->host_no;
-      /*
-	Add Host Adapter to the end of the list of registered BusLogic
-	Host Adapters.
-      */
-      BusLogic_RegisterHostAdapter(HostAdapter);
-      /*
-	Read the Host Adapter Configuration, Configure the Host Adapter,
-	Acquire the System Resources necessary to use the Host Adapter, then
-	Create the Initial CCBs, Initialize the Host Adapter, and finally
-	perform Target Device Inquiry.
-      */
-      if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) &&
-	  BusLogic_ReportHostAdapterConfiguration(HostAdapter) &&
-	  BusLogic_AcquireResources(HostAdapter) &&
-	  BusLogic_CreateInitialCCBs(HostAdapter) &&
-	  BusLogic_InitializeHostAdapter(HostAdapter) &&
-	  BusLogic_TargetDeviceInquiry(HostAdapter))
-	{
-	  /*
-	    Initialization has been completed successfully.  Release and
-	    re-register usage of the I/O Address range so that the Model
-	    Name of the Host Adapter will appear, and initialize the SCSI
-	    Host structure.
-	  */
-	  release_region(HostAdapter->IO_Address,
-			 HostAdapter->AddressCount);
-	  if(!request_region(HostAdapter->IO_Address,
-			     HostAdapter->AddressCount,
-			     HostAdapter->FullModelName)) {
-		  printk(KERN_WARNING "BusLogic: Release and re-register of "
-			 "port 0x%04lx failed \n",
-			 (unsigned long)HostAdapter->IO_Address);
-		  BusLogic_DestroyCCBs(HostAdapter);
-		  BusLogic_ReleaseResources(HostAdapter);
-		  BusLogic_UnregisterHostAdapter(HostAdapter);
-		  scsi_host_put(Host);
-	  }
-	  else {
-		  BusLogic_InitializeHostStructure(HostAdapter, Host);
-	          scsi_add_host(Host, NULL);
-	          scsi_scan_host(Host);
-		  BusLogicHostAdapterCount++;
-	  }
-	}
-      else
-	{
-	  /*
-	    An error occurred during Host Adapter Configuration Querying, Host
-	    Adapter Configuration, Resource Acquisition, CCB Creation, Host
-	    Adapter Initialization, or Target Device Inquiry, so remove Host
-	    Adapter from the list of registered BusLogic Host Adapters, destroy
-	    the CCBs, Release the System Resources, and Unregister the SCSI
-	    Host.
-	  */
-	  BusLogic_DestroyCCBs(HostAdapter);
-	  BusLogic_ReleaseResources(HostAdapter);
-	  BusLogic_UnregisterHostAdapter(HostAdapter);
-	  scsi_host_put(Host);
+	BusLogic_InitializeProbeInfoList(PrototypeHostAdapter);
+	for (ProbeIndex = 0; ProbeIndex < BusLogic_ProbeInfoCount; ProbeIndex++) {
+		struct BusLogic_ProbeInfo *ProbeInfo = &BusLogic_ProbeInfoList[ProbeIndex];
+		struct BusLogic_HostAdapter *HostAdapter = PrototypeHostAdapter;
+		struct Scsi_Host *Host;
+		if (ProbeInfo->IO_Address == 0)
+			continue;
+		memset(HostAdapter, 0, sizeof(struct BusLogic_HostAdapter));
+		HostAdapter->HostAdapterType = ProbeInfo->HostAdapterType;
+		HostAdapter->HostAdapterBusType = ProbeInfo->HostAdapterBusType;
+		HostAdapter->IO_Address = ProbeInfo->IO_Address;
+		HostAdapter->PCI_Address = ProbeInfo->PCI_Address;
+		HostAdapter->Bus = ProbeInfo->Bus;
+		HostAdapter->Device = ProbeInfo->Device;
+		HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel;
+		HostAdapter->AddressCount = BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType];
+		/*
+		   Probe the Host Adapter.  If unsuccessful, abort further initialization.
+		 */
+		if (!BusLogic_ProbeHostAdapter(HostAdapter))
+			continue;
+		/*
+		   Hard Reset the Host Adapter.  If unsuccessful, abort further
+		   initialization.
+		 */
+		if (!BusLogic_HardwareResetHostAdapter(HostAdapter, true))
+			continue;
+		/*
+		   Check the Host Adapter.  If unsuccessful, abort further initialization.
+		 */
+		if (!BusLogic_CheckHostAdapter(HostAdapter))
+			continue;
+		/*
+		   Initialize the Driver Options field if provided.
+		 */
+		if (DriverOptionsIndex < BusLogic_DriverOptionsCount)
+			HostAdapter->DriverOptions = &BusLogic_DriverOptions[DriverOptionsIndex++];
+		/*
+		   Announce the Driver Version and Date, Author's Name, Copyright Notice,
+		   and Electronic Mail Address.
+		 */
+		BusLogic_AnnounceDriver(HostAdapter);
+		/*
+		   Register usage of the I/O Address range.  From this point onward, any
+		   failure will be assumed to be due to a problem with the Host Adapter,
+		   rather than due to having mistakenly identified this port as belonging
+		   to a BusLogic Host Adapter.  The I/O Address range will not be
+		   released, thereby preventing it from being incorrectly identified as
+		   any other type of Host Adapter.
+		 */
+		if (!request_region(HostAdapter->IO_Address, HostAdapter->AddressCount, "BusLogic"))
+			continue;
+		/*
+		   Register the SCSI Host structure.
+		 */
+
+		Host = scsi_host_alloc(HostTemplate, sizeof(struct BusLogic_HostAdapter));
+		if (Host == NULL) {
+			release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
+			continue;
+		}
+		HostAdapter = (struct BusLogic_HostAdapter *) Host->hostdata;
+		memcpy(HostAdapter, PrototypeHostAdapter, sizeof(struct BusLogic_HostAdapter));
+		HostAdapter->SCSI_Host = Host;
+		HostAdapter->HostNumber = Host->host_no;
+		/*
+		   Add Host Adapter to the end of the list of registered BusLogic
+		   Host Adapters.
+		 */
+		BusLogic_RegisterHostAdapter(HostAdapter);
+		/*
+		   Read the Host Adapter Configuration, Configure the Host Adapter,
+		   Acquire the System Resources necessary to use the Host Adapter, then
+		   Create the Initial CCBs, Initialize the Host Adapter, and finally
+		   perform Target Device Inquiry.
+		 */
+		if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) &&
+		    BusLogic_ReportHostAdapterConfiguration(HostAdapter) && BusLogic_AcquireResources(HostAdapter) && BusLogic_CreateInitialCCBs(HostAdapter) && BusLogic_InitializeHostAdapter(HostAdapter) && BusLogic_TargetDeviceInquiry(HostAdapter)) {
+			/*
+			   Initialization has been completed successfully.  Release and
+			   re-register usage of the I/O Address range so that the Model
+			   Name of the Host Adapter will appear, and initialize the SCSI
+			   Host structure.
+			 */
+			release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
+			if (!request_region(HostAdapter->IO_Address, HostAdapter->AddressCount, HostAdapter->FullModelName)) {
+				printk(KERN_WARNING "BusLogic: Release and re-register of " "port 0x%04lx failed \n", (unsigned long) HostAdapter->IO_Address);
+				BusLogic_DestroyCCBs(HostAdapter);
+				BusLogic_ReleaseResources(HostAdapter);
+				BusLogic_UnregisterHostAdapter(HostAdapter);
+				scsi_host_put(Host);
+			} else {
+				BusLogic_InitializeHostStructure(HostAdapter, Host);
+				scsi_add_host(Host, NULL);
+				scsi_scan_host(Host);
+				BusLogicHostAdapterCount++;
+			}
+		} else {
+			/*
+			   An error occurred during Host Adapter Configuration Querying, Host
+			   Adapter Configuration, Resource Acquisition, CCB Creation, Host
+			   Adapter Initialization, or Target Device Inquiry, so remove Host
+			   Adapter from the list of registered BusLogic Host Adapters, destroy
+			   the CCBs, Release the System Resources, and Unregister the SCSI
+			   Host.
+			 */
+			BusLogic_DestroyCCBs(HostAdapter);
+			BusLogic_ReleaseResources(HostAdapter);
+			BusLogic_UnregisterHostAdapter(HostAdapter);
+			scsi_host_put(Host);
+		}
 	}
-    }
-  kfree(PrototypeHostAdapter);
-  kfree(BusLogic_ProbeInfoList);
-  BusLogic_ProbeInfoList = NULL;
-  return BusLogicHostAdapterCount;
+	kfree(PrototypeHostAdapter);
+	kfree(BusLogic_ProbeInfoList);
+	BusLogic_ProbeInfoList = NULL;
+	return BusLogicHostAdapterCount;
 }
 
 
@@ -2825,29 +2360,28 @@ static int __init BusLogic_DetectHostAdapter(struct scsi_host_template *HostTemp
 
 static int __exit BusLogic_ReleaseHostAdapter(struct Scsi_Host *Host)
 {
-  struct BusLogic_HostAdapter *HostAdapter =
-    (struct BusLogic_HostAdapter *) Host->hostdata;
-  /*
-    FlashPoint Host Adapters must first be released by the FlashPoint
-    SCCB Manager.
-  */
-  if (BusLogic_FlashPointHostAdapterP(HostAdapter))
-    FlashPoint_ReleaseHostAdapter(HostAdapter->CardHandle);
-  /*
-    Destroy the CCBs and release any system resources acquired to
-    support Host Adapter.
-  */
-  BusLogic_DestroyCCBs(HostAdapter);
-  BusLogic_ReleaseResources(HostAdapter);
-  /*
-    Release usage of the I/O Address range.
-  */
-  release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
-  /*
-    Remove Host Adapter from the list of registered BusLogic Host Adapters.
-  */
-  BusLogic_UnregisterHostAdapter(HostAdapter);
-  return 0;
+	struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Host->hostdata;
+	/*
+	   FlashPoint Host Adapters must first be released by the FlashPoint
+	   SCCB Manager.
+	 */
+	if (BusLogic_FlashPointHostAdapterP(HostAdapter))
+		FlashPoint_ReleaseHostAdapter(HostAdapter->CardHandle);
+	/*
+	   Destroy the CCBs and release any system resources acquired to
+	   support Host Adapter.
+	 */
+	BusLogic_DestroyCCBs(HostAdapter);
+	BusLogic_ReleaseResources(HostAdapter);
+	/*
+	   Release usage of the I/O Address range.
+	 */
+	release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
+	/*
+	   Remove Host Adapter from the list of registered BusLogic Host Adapters.
+	 */
+	BusLogic_UnregisterHostAdapter(HostAdapter);
+	return 0;
 }
 
 
@@ -2857,20 +2391,17 @@ static int __exit BusLogic_ReleaseHostAdapter(struct Scsi_Host *Host)
 
 static void BusLogic_QueueCompletedCCB(struct BusLogic_CCB *CCB)
 {
-  struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter;
-  CCB->Status = BusLogic_CCB_Completed;
-  CCB->Next = NULL;
-  if (HostAdapter->FirstCompletedCCB == NULL)
-    {
-      HostAdapter->FirstCompletedCCB = CCB;
-      HostAdapter->LastCompletedCCB = CCB;
-    }
-  else
-    {
-      HostAdapter->LastCompletedCCB->Next = CCB;
-      HostAdapter->LastCompletedCCB = CCB;
-    }
-  HostAdapter->ActiveCommands[CCB->TargetID]--;
+	struct BusLogic_HostAdapter *HostAdapter = CCB->HostAdapter;
+	CCB->Status = BusLogic_CCB_Completed;
+	CCB->Next = NULL;
+	if (HostAdapter->FirstCompletedCCB == NULL) {
+		HostAdapter->FirstCompletedCCB = CCB;
+		HostAdapter->LastCompletedCCB = CCB;
+	} else {
+		HostAdapter->LastCompletedCCB->Next = CCB;
+		HostAdapter->LastCompletedCCB = CCB;
+	}
+	HostAdapter->ActiveCommands[CCB->TargetID]--;
 }
 
 
@@ -2879,57 +2410,50 @@ static void BusLogic_QueueCompletedCCB(struct BusLogic_CCB *CCB)
   the Host Adapter Status and Target Device Status.
 */
 
-static int BusLogic_ComputeResultCode(struct BusLogic_HostAdapter *HostAdapter,
-				      enum BusLogic_HostAdapterStatus
-					HostAdapterStatus,
-				      enum BusLogic_TargetDeviceStatus
-					TargetDeviceStatus)
+static int BusLogic_ComputeResultCode(struct BusLogic_HostAdapter *HostAdapter, enum BusLogic_HostAdapterStatus HostAdapterStatus, enum BusLogic_TargetDeviceStatus TargetDeviceStatus)
 {
-  int HostStatus;
-  switch (HostAdapterStatus)
-    {
-    case BusLogic_CommandCompletedNormally:
-    case BusLogic_LinkedCommandCompleted:
-    case BusLogic_LinkedCommandCompletedWithFlag:
-      HostStatus = DID_OK;
-      break;
-    case BusLogic_SCSISelectionTimeout:
-      HostStatus = DID_TIME_OUT;
-      break;
-    case BusLogic_InvalidOutgoingMailboxActionCode:
-    case BusLogic_InvalidCommandOperationCode:
-    case BusLogic_InvalidCommandParameter:
-      BusLogic_Warning("BusLogic Driver Protocol Error 0x%02X\n",
-		       HostAdapter, HostAdapterStatus);
-    case BusLogic_DataUnderRun:
-    case BusLogic_DataOverRun:
-    case BusLogic_UnexpectedBusFree:
-    case BusLogic_LinkedCCBhasInvalidLUN:
-    case BusLogic_AutoRequestSenseFailed:
-    case BusLogic_TaggedQueuingMessageRejected:
-    case BusLogic_UnsupportedMessageReceived:
-    case BusLogic_HostAdapterHardwareFailed:
-    case BusLogic_TargetDeviceReconnectedImproperly:
-    case BusLogic_AbortQueueGenerated:
-    case BusLogic_HostAdapterSoftwareError:
-    case BusLogic_HostAdapterHardwareTimeoutError:
-    case BusLogic_SCSIParityErrorDetected:
-      HostStatus = DID_ERROR;
-      break;
-    case BusLogic_InvalidBusPhaseRequested:
-    case BusLogic_TargetFailedResponseToATN:
-    case BusLogic_HostAdapterAssertedRST:
-    case BusLogic_OtherDeviceAssertedRST:
-    case BusLogic_HostAdapterAssertedBusDeviceReset:
-      HostStatus = DID_RESET;
-      break;
-    default:
-      BusLogic_Warning("Unknown Host Adapter Status 0x%02X\n",
-		       HostAdapter, HostAdapterStatus);
-      HostStatus = DID_ERROR;
-      break;
-    }
-  return (HostStatus << 16) | TargetDeviceStatus;
+	int HostStatus;
+	switch (HostAdapterStatus) {
+	case BusLogic_CommandCompletedNormally:
+	case BusLogic_LinkedCommandCompleted:
+	case BusLogic_LinkedCommandCompletedWithFlag:
+		HostStatus = DID_OK;
+		break;
+	case BusLogic_SCSISelectionTimeout:
+		HostStatus = DID_TIME_OUT;
+		break;
+	case BusLogic_InvalidOutgoingMailboxActionCode:
+	case BusLogic_InvalidCommandOperationCode:
+	case BusLogic_InvalidCommandParameter:
+		BusLogic_Warning("BusLogic Driver Protocol Error 0x%02X\n", HostAdapter, HostAdapterStatus);
+	case BusLogic_DataUnderRun:
+	case BusLogic_DataOverRun:
+	case BusLogic_UnexpectedBusFree:
+	case BusLogic_LinkedCCBhasInvalidLUN:
+	case BusLogic_AutoRequestSenseFailed:
+	case BusLogic_TaggedQueuingMessageRejected:
+	case BusLogic_UnsupportedMessageReceived:
+	case BusLogic_HostAdapterHardwareFailed:
+	case BusLogic_TargetDeviceReconnectedImproperly:
+	case BusLogic_AbortQueueGenerated:
+	case BusLogic_HostAdapterSoftwareError:
+	case BusLogic_HostAdapterHardwareTimeoutError:
+	case BusLogic_SCSIParityErrorDetected:
+		HostStatus = DID_ERROR;
+		break;
+	case BusLogic_InvalidBusPhaseRequested:
+	case BusLogic_TargetFailedResponseToATN:
+	case BusLogic_HostAdapterAssertedRST:
+	case BusLogic_OtherDeviceAssertedRST:
+	case BusLogic_HostAdapterAssertedBusDeviceReset:
+		HostStatus = DID_RESET;
+		break;
+	default:
+		BusLogic_Warning("Unknown Host Adapter Status 0x%02X\n", HostAdapter, HostAdapterStatus);
+		HostStatus = DID_ERROR;
+		break;
+	}
+	return (HostStatus << 16) | TargetDeviceStatus;
 }
 
 
@@ -2940,62 +2464,51 @@ static int BusLogic_ComputeResultCode(struct BusLogic_HostAdapter *HostAdapter,
 
 static void BusLogic_ScanIncomingMailboxes(struct BusLogic_HostAdapter *HostAdapter)
 {
-  /*
-    Scan through the Incoming Mailboxes in Strict Round Robin fashion, saving
-    any completed CCBs for further processing.  It is essential that for each
-    CCB and SCSI Command issued, command completion processing is performed
-    exactly once.  Therefore, only Incoming Mailboxes with completion code
-    Command Completed Without Error, Command Completed With Error, or Command
-    Aborted At Host Request are saved for completion processing.  When an
-    Incoming Mailbox has a completion code of Aborted Command Not Found, the
-    CCB had already completed or been aborted before the current Abort request
-    was processed, and so completion processing has already occurred and no
-    further action should be taken.
-  */
-  struct BusLogic_IncomingMailbox *NextIncomingMailbox =
-    HostAdapter->NextIncomingMailbox;
-  enum BusLogic_CompletionCode CompletionCode;
-  while ((CompletionCode = NextIncomingMailbox->CompletionCode) !=
-	 BusLogic_IncomingMailboxFree)
-    {
-      /*
-        We are only allowed to do this because we limit our architectures we
-        run on to machines where bus_to_virt() actually works.  There *needs*
-        to be a dma_addr_to_virt() in the new PCI DMA mapping interface to
-        replace bus_to_virt() or else this code is going to become very
-        innefficient.
-      */
-      struct BusLogic_CCB *CCB = (struct BusLogic_CCB *)
-	Bus_to_Virtual(NextIncomingMailbox->CCB);
-      if (CompletionCode != BusLogic_AbortedCommandNotFound)
-	{
-	  if (CCB->Status == BusLogic_CCB_Active ||
-	      CCB->Status == BusLogic_CCB_Reset)
-	    {
-	      /*
-		Save the Completion Code for this CCB and queue the CCB
-		for completion processing.
-	      */
-	      CCB->CompletionCode = CompletionCode;
-	      BusLogic_QueueCompletedCCB(CCB);
-	    }
-	  else
-	    {
-	      /*
-		If a CCB ever appears in an Incoming Mailbox and is not marked
-		as status Active or Reset, then there is most likely a bug in
-		the Host Adapter firmware.
-	      */
-	      BusLogic_Warning("Illegal CCB #%ld status %d in "
-			       "Incoming Mailbox\n", HostAdapter,
-			       CCB->SerialNumber, CCB->Status);
-	    }
+	/*
+	   Scan through the Incoming Mailboxes in Strict Round Robin fashion, saving
+	   any completed CCBs for further processing.  It is essential that for each
+	   CCB and SCSI Command issued, command completion processing is performed
+	   exactly once.  Therefore, only Incoming Mailboxes with completion code
+	   Command Completed Without Error, Command Completed With Error, or Command
+	   Aborted At Host Request are saved for completion processing.  When an
+	   Incoming Mailbox has a completion code of Aborted Command Not Found, the
+	   CCB had already completed or been aborted before the current Abort request
+	   was processed, and so completion processing has already occurred and no
+	   further action should be taken.
+	 */
+	struct BusLogic_IncomingMailbox *NextIncomingMailbox = HostAdapter->NextIncomingMailbox;
+	enum BusLogic_CompletionCode CompletionCode;
+	while ((CompletionCode = NextIncomingMailbox->CompletionCode) != BusLogic_IncomingMailboxFree) {
+		/*
+		   We are only allowed to do this because we limit our architectures we
+		   run on to machines where bus_to_virt() actually works.  There *needs*
+		   to be a dma_addr_to_virt() in the new PCI DMA mapping interface to
+		   replace bus_to_virt() or else this code is going to become very
+		   innefficient.
+		 */
+		struct BusLogic_CCB *CCB = (struct BusLogic_CCB *) Bus_to_Virtual(NextIncomingMailbox->CCB);
+		if (CompletionCode != BusLogic_AbortedCommandNotFound) {
+			if (CCB->Status == BusLogic_CCB_Active || CCB->Status == BusLogic_CCB_Reset) {
+				/*
+				   Save the Completion Code for this CCB and queue the CCB
+				   for completion processing.
+				 */
+				CCB->CompletionCode = CompletionCode;
+				BusLogic_QueueCompletedCCB(CCB);
+			} else {
+				/*
+				   If a CCB ever appears in an Incoming Mailbox and is not marked
+				   as status Active or Reset, then there is most likely a bug in
+				   the Host Adapter firmware.
+				 */
+				BusLogic_Warning("Illegal CCB #%ld status %d in " "Incoming Mailbox\n", HostAdapter, CCB->SerialNumber, CCB->Status);
+			}
+		}
+		NextIncomingMailbox->CompletionCode = BusLogic_IncomingMailboxFree;
+		if (++NextIncomingMailbox > HostAdapter->LastIncomingMailbox)
+			NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
 	}
-      NextIncomingMailbox->CompletionCode = BusLogic_IncomingMailboxFree;
-      if (++NextIncomingMailbox > HostAdapter->LastIncomingMailbox)
-	NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
-    }
-  HostAdapter->NextIncomingMailbox = NextIncomingMailbox;
+	HostAdapter->NextIncomingMailbox = NextIncomingMailbox;
 }
 
 
@@ -3008,153 +2521,126 @@ static void BusLogic_ScanIncomingMailboxes(struct BusLogic_HostAdapter *HostAdap
 
 static void BusLogic_ProcessCompletedCCBs(struct BusLogic_HostAdapter *HostAdapter)
 {
-  if (HostAdapter->ProcessCompletedCCBsActive) return;
-  HostAdapter->ProcessCompletedCCBsActive = true;
-  while (HostAdapter->FirstCompletedCCB != NULL)
-    {
-      struct BusLogic_CCB *CCB = HostAdapter->FirstCompletedCCB;
-      struct scsi_cmnd *Command = CCB->Command;
-      HostAdapter->FirstCompletedCCB = CCB->Next;
-      if (HostAdapter->FirstCompletedCCB == NULL)
-	HostAdapter->LastCompletedCCB = NULL;
-      /*
-	Process the Completed CCB.
-      */
-      if (CCB->Opcode == BusLogic_BusDeviceReset)
-	{
-	  int TargetID = CCB->TargetID;
-	  BusLogic_Warning("Bus Device Reset CCB #%ld to Target "
-			   "%d Completed\n", HostAdapter,
-			   CCB->SerialNumber, TargetID);
-	  BusLogic_IncrementErrorCounter(
-	    &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsCompleted);
-	  HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
-	  HostAdapter->CommandsSinceReset[TargetID] = 0;
-	  HostAdapter->LastResetCompleted[TargetID] = jiffies;
-	  /*
-	    Place CCB back on the Host Adapter's free list.
-	  */
-	  BusLogic_DeallocateCCB(CCB);
-#if 0	/* this needs to be redone different for new EH */
-	  /*
-	    Bus Device Reset CCBs have the Command field non-NULL only when a
-	    Bus Device Reset was requested for a Command that did not have a
-	    currently active CCB in the Host Adapter (i.e., a Synchronous
-	    Bus Device Reset), and hence would not have its Completion Routine
-	    called otherwise.
-	  */
-	  while (Command != NULL)
-	    {
-	      struct scsi_cmnd *NextCommand = Command->reset_chain;
-	      Command->reset_chain = NULL;
-	      Command->result = DID_RESET << 16;
-	      Command->scsi_done(Command);
-	      Command = NextCommand;
-	    }
+	if (HostAdapter->ProcessCompletedCCBsActive)
+		return;
+	HostAdapter->ProcessCompletedCCBsActive = true;
+	while (HostAdapter->FirstCompletedCCB != NULL) {
+		struct BusLogic_CCB *CCB = HostAdapter->FirstCompletedCCB;
+		struct scsi_cmnd *Command = CCB->Command;
+		HostAdapter->FirstCompletedCCB = CCB->Next;
+		if (HostAdapter->FirstCompletedCCB == NULL)
+			HostAdapter->LastCompletedCCB = NULL;
+		/*
+		   Process the Completed CCB.
+		 */
+		if (CCB->Opcode == BusLogic_BusDeviceReset) {
+			int TargetID = CCB->TargetID;
+			BusLogic_Warning("Bus Device Reset CCB #%ld to Target " "%d Completed\n", HostAdapter, CCB->SerialNumber, TargetID);
+			BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].BusDeviceResetsCompleted);
+			HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
+			HostAdapter->CommandsSinceReset[TargetID] = 0;
+			HostAdapter->LastResetCompleted[TargetID] = jiffies;
+			/*
+			   Place CCB back on the Host Adapter's free list.
+			 */
+			BusLogic_DeallocateCCB(CCB);
+#if 0				/* this needs to be redone different for new EH */
+			/*
+			   Bus Device Reset CCBs have the Command field non-NULL only when a
+			   Bus Device Reset was requested for a Command that did not have a
+			   currently active CCB in the Host Adapter (i.e., a Synchronous
+			   Bus Device Reset), and hence would not have its Completion Routine
+			   called otherwise.
+			 */
+			while (Command != NULL) {
+				struct scsi_cmnd *NextCommand = Command->reset_chain;
+				Command->reset_chain = NULL;
+				Command->result = DID_RESET << 16;
+				Command->scsi_done(Command);
+				Command = NextCommand;
+			}
 #endif
-	  /*
-	    Iterate over the CCBs for this Host Adapter performing completion
-	    processing for any CCBs marked as Reset for this Target.
-	  */
-	  for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
-	    if (CCB->Status == BusLogic_CCB_Reset && CCB->TargetID == TargetID)
-	      {
-		Command = CCB->Command;
-		BusLogic_DeallocateCCB(CCB);
-		HostAdapter->ActiveCommands[TargetID]--;
-		Command->result = DID_RESET << 16;
-		Command->scsi_done(Command);
-	      }
-	  HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
-	}
-      else
-	{
-	  /*
-	    Translate the Completion Code, Host Adapter Status, and Target
-	    Device Status into a SCSI Subsystem Result Code.
-	  */
-	  switch (CCB->CompletionCode)
-	    {
-	    case BusLogic_IncomingMailboxFree:
-	    case BusLogic_AbortedCommandNotFound:
-	    case BusLogic_InvalidCCB:
-	      BusLogic_Warning("CCB #%ld to Target %d Impossible State\n",
-			       HostAdapter, CCB->SerialNumber, CCB->TargetID);
-	      break;
-	    case BusLogic_CommandCompletedWithoutError:
-	      HostAdapter->TargetStatistics[CCB->TargetID]
-			   .CommandsCompleted++;
-	      HostAdapter->TargetFlags[CCB->TargetID]
-			   .CommandSuccessfulFlag = true;
-	      Command->result = DID_OK << 16;
-	      break;
-	    case BusLogic_CommandAbortedAtHostRequest:
-	      BusLogic_Warning("CCB #%ld to Target %d Aborted\n",
-			       HostAdapter, CCB->SerialNumber, CCB->TargetID);
-	      BusLogic_IncrementErrorCounter(
-		&HostAdapter->TargetStatistics[CCB->TargetID]
-			      .CommandAbortsCompleted);
-	      Command->result = DID_ABORT << 16;
-	      break;
-	    case BusLogic_CommandCompletedWithError:
-	      Command->result =
-		BusLogic_ComputeResultCode(HostAdapter,
-					   CCB->HostAdapterStatus,
-					   CCB->TargetDeviceStatus);
-	      if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout)
-		{
-		  HostAdapter->TargetStatistics[CCB->TargetID]
-			       .CommandsCompleted++;
-		  if (BusLogic_GlobalOptions.TraceErrors)
-		    {
-		      int i;
-		      BusLogic_Notice("CCB #%ld Target %d: Result %X Host "
-				      "Adapter Status %02X "
-				      "Target Status %02X\n",
-				      HostAdapter, CCB->SerialNumber,
-				      CCB->TargetID, Command->result,
-				      CCB->HostAdapterStatus,
-				      CCB->TargetDeviceStatus);
-		      BusLogic_Notice("CDB   ", HostAdapter);
-		      for (i = 0; i < CCB->CDB_Length; i++)
-			BusLogic_Notice(" %02X", HostAdapter, CCB->CDB[i]);
-		      BusLogic_Notice("\n", HostAdapter);
-		      BusLogic_Notice("Sense ", HostAdapter);
-		      for (i = 0; i < CCB->SenseDataLength; i++)
-			BusLogic_Notice(" %02X", HostAdapter,
-					Command->sense_buffer[i]);
-		      BusLogic_Notice("\n", HostAdapter);
-		    }
+			/*
+			   Iterate over the CCBs for this Host Adapter performing completion
+			   processing for any CCBs marked as Reset for this Target.
+			 */
+			for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
+				if (CCB->Status == BusLogic_CCB_Reset && CCB->TargetID == TargetID) {
+					Command = CCB->Command;
+					BusLogic_DeallocateCCB(CCB);
+					HostAdapter->ActiveCommands[TargetID]--;
+					Command->result = DID_RESET << 16;
+					Command->scsi_done(Command);
+				}
+			HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
+		} else {
+			/*
+			   Translate the Completion Code, Host Adapter Status, and Target
+			   Device Status into a SCSI Subsystem Result Code.
+			 */
+			switch (CCB->CompletionCode) {
+			case BusLogic_IncomingMailboxFree:
+			case BusLogic_AbortedCommandNotFound:
+			case BusLogic_InvalidCCB:
+				BusLogic_Warning("CCB #%ld to Target %d Impossible State\n", HostAdapter, CCB->SerialNumber, CCB->TargetID);
+				break;
+			case BusLogic_CommandCompletedWithoutError:
+				HostAdapter->TargetStatistics[CCB->TargetID]
+				    .CommandsCompleted++;
+				HostAdapter->TargetFlags[CCB->TargetID]
+				    .CommandSuccessfulFlag = true;
+				Command->result = DID_OK << 16;
+				break;
+			case BusLogic_CommandAbortedAtHostRequest:
+				BusLogic_Warning("CCB #%ld to Target %d Aborted\n", HostAdapter, CCB->SerialNumber, CCB->TargetID);
+				BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[CCB->TargetID]
+							       .CommandAbortsCompleted);
+				Command->result = DID_ABORT << 16;
+				break;
+			case BusLogic_CommandCompletedWithError:
+				Command->result = BusLogic_ComputeResultCode(HostAdapter, CCB->HostAdapterStatus, CCB->TargetDeviceStatus);
+				if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout) {
+					HostAdapter->TargetStatistics[CCB->TargetID]
+					    .CommandsCompleted++;
+					if (BusLogic_GlobalOptions.TraceErrors) {
+						int i;
+						BusLogic_Notice("CCB #%ld Target %d: Result %X Host "
+								"Adapter Status %02X " "Target Status %02X\n", HostAdapter, CCB->SerialNumber, CCB->TargetID, Command->result, CCB->HostAdapterStatus, CCB->TargetDeviceStatus);
+						BusLogic_Notice("CDB   ", HostAdapter);
+						for (i = 0; i < CCB->CDB_Length; i++)
+							BusLogic_Notice(" %02X", HostAdapter, CCB->CDB[i]);
+						BusLogic_Notice("\n", HostAdapter);
+						BusLogic_Notice("Sense ", HostAdapter);
+						for (i = 0; i < CCB->SenseDataLength; i++)
+							BusLogic_Notice(" %02X", HostAdapter, Command->sense_buffer[i]);
+						BusLogic_Notice("\n", HostAdapter);
+					}
+				}
+				break;
+			}
+			/*
+			   When an INQUIRY command completes normally, save the
+			   CmdQue (Tagged Queuing Supported) and WBus16 (16 Bit
+			   Wide Data Transfers Supported) bits.
+			 */
+			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;
+				TargetFlags->TargetExists = true;
+				TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue;
+				TargetFlags->WideTransfersSupported = InquiryResult->WBus16;
+			}
+			/*
+			   Place CCB back on the Host Adapter's free list.
+			 */
+			BusLogic_DeallocateCCB(CCB);
+			/*
+			   Call the SCSI Command Completion Routine.
+			 */
+			Command->scsi_done(Command);
 		}
-	      break;
-	    }
-	  /*
-	    When an INQUIRY command completes normally, save the
-	    CmdQue (Tagged Queuing Supported) and WBus16 (16 Bit
-	    Wide Data Transfers Supported) bits.
-	  */
-	  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;
-	      TargetFlags->TargetExists = true;
-	      TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue;
-	      TargetFlags->WideTransfersSupported = InquiryResult->WBus16;
-	    }
-	  /*
-	    Place CCB back on the Host Adapter's free list.
-	  */
-	  BusLogic_DeallocateCCB(CCB);
-	  /*
-	    Call the SCSI Command Completion Routine.
-	  */
-	  Command->scsi_done(Command);
 	}
-    }
-  HostAdapter->ProcessCompletedCCBsActive = false;
+	HostAdapter->ProcessCompletedCCBsActive = false;
 }
 
 
@@ -3163,97 +2649,83 @@ static void BusLogic_ProcessCompletedCCBs(struct BusLogic_HostAdapter *HostAdapt
   Adapters.
 */
 
-static irqreturn_t BusLogic_InterruptHandler(int IRQ_Channel,
-				      void *DeviceIdentifier,
-				      struct pt_regs *InterruptRegisters)
+static irqreturn_t BusLogic_InterruptHandler(int IRQ_Channel, void *DeviceIdentifier, struct pt_regs *InterruptRegisters)
 {
-  struct BusLogic_HostAdapter *HostAdapter =
-    (struct BusLogic_HostAdapter *) DeviceIdentifier;
-  unsigned long ProcessorFlags;
-  /*
-    Acquire exclusive access to Host Adapter.
-  */
-  BusLogic_AcquireHostAdapterLockIH(HostAdapter, &ProcessorFlags);
-  /*
-    Handle Interrupts appropriately for each Host Adapter type.
-  */
-  if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
-    {
-      union BusLogic_InterruptRegister InterruptRegister;
-      /*
-	Read the Host Adapter Interrupt Register.
-      */
-      InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
-      if (InterruptRegister.ir.InterruptValid)
-	{
-	  /*
-	    Acknowledge the interrupt and reset the Host Adapter
-	    Interrupt Register.
-	  */
-	  BusLogic_InterruptReset(HostAdapter);
-	  /*
-	    Process valid External SCSI Bus Reset and Incoming Mailbox
-	    Loaded Interrupts.  Command Complete Interrupts are noted,
-	    and Outgoing Mailbox Available Interrupts are ignored, as
-	    they are never enabled.
-	  */
-	  if (InterruptRegister.ir.ExternalBusReset)
-	    HostAdapter->HostAdapterExternalReset = true;
-	  else if (InterruptRegister.ir.IncomingMailboxLoaded)
-	    BusLogic_ScanIncomingMailboxes(HostAdapter);
-	  else if (InterruptRegister.ir.CommandComplete)
-	    HostAdapter->HostAdapterCommandCompleted = true;
+	struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) DeviceIdentifier;
+	unsigned long ProcessorFlags;
+	/*
+	   Acquire exclusive access to Host Adapter.
+	 */
+	BusLogic_AcquireHostAdapterLockIH(HostAdapter, &ProcessorFlags);
+	/*
+	   Handle Interrupts appropriately for each Host Adapter type.
+	 */
+	if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) {
+		union BusLogic_InterruptRegister InterruptRegister;
+		/*
+		   Read the Host Adapter Interrupt Register.
+		 */
+		InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
+		if (InterruptRegister.ir.InterruptValid) {
+			/*
+			   Acknowledge the interrupt and reset the Host Adapter
+			   Interrupt Register.
+			 */
+			BusLogic_InterruptReset(HostAdapter);
+			/*
+			   Process valid External SCSI Bus Reset and Incoming Mailbox
+			   Loaded Interrupts.  Command Complete Interrupts are noted,
+			   and Outgoing Mailbox Available Interrupts are ignored, as
+			   they are never enabled.
+			 */
+			if (InterruptRegister.ir.ExternalBusReset)
+				HostAdapter->HostAdapterExternalReset = true;
+			else if (InterruptRegister.ir.IncomingMailboxLoaded)
+				BusLogic_ScanIncomingMailboxes(HostAdapter);
+			else if (InterruptRegister.ir.CommandComplete)
+				HostAdapter->HostAdapterCommandCompleted = true;
+		}
+	} else {
+		/*
+		   Check if there is a pending interrupt for this Host Adapter.
+		 */
+		if (FlashPoint_InterruptPending(HostAdapter->CardHandle))
+			switch (FlashPoint_HandleInterrupt(HostAdapter->CardHandle)) {
+			case FlashPoint_NormalInterrupt:
+				break;
+			case FlashPoint_ExternalBusReset:
+				HostAdapter->HostAdapterExternalReset = true;
+				break;
+			case FlashPoint_InternalError:
+				BusLogic_Warning("Internal FlashPoint Error detected" " - Resetting Host Adapter\n", HostAdapter);
+				HostAdapter->HostAdapterInternalError = true;
+				break;
+			}
+	}
+	/*
+	   Process any completed CCBs.
+	 */
+	if (HostAdapter->FirstCompletedCCB != NULL)
+		BusLogic_ProcessCompletedCCBs(HostAdapter);
+	/*
+	   Reset the Host Adapter if requested.
+	 */
+	if (HostAdapter->HostAdapterExternalReset) {
+		BusLogic_Warning("Resetting %s due to External SCSI Bus Reset\n", HostAdapter, HostAdapter->FullModelName);
+		BusLogic_IncrementErrorCounter(&HostAdapter->ExternalHostAdapterResets);
+		BusLogic_ResetHostAdapter(HostAdapter, false);
+		HostAdapter->HostAdapterExternalReset = false;
+	} else if (HostAdapter->HostAdapterInternalError) {
+		BusLogic_Warning("Resetting %s due to Host Adapter Internal Error\n", HostAdapter, HostAdapter->FullModelName);
+		BusLogic_IncrementErrorCounter(&HostAdapter->HostAdapterInternalErrors);
+		BusLogic_ResetHostAdapter(HostAdapter, true);
+		HostAdapter->HostAdapterInternalError = false;
 	}
-    }
-  else
-    {
-      /*
-	Check if there is a pending interrupt for this Host Adapter.
-      */
-      if (FlashPoint_InterruptPending(HostAdapter->CardHandle))
-	switch (FlashPoint_HandleInterrupt(HostAdapter->CardHandle))
-	  {
-	  case FlashPoint_NormalInterrupt:
-	    break;
-	  case FlashPoint_ExternalBusReset:
-	    HostAdapter->HostAdapterExternalReset = true;
-	    break;
-	  case FlashPoint_InternalError:
-	    BusLogic_Warning("Internal FlashPoint Error detected"
-			     " - Resetting Host Adapter\n", HostAdapter);
-	    HostAdapter->HostAdapterInternalError = true;
-	    break;
-	  }
-    }
-  /*
-    Process any completed CCBs.
-  */
-  if (HostAdapter->FirstCompletedCCB != NULL)
-    BusLogic_ProcessCompletedCCBs(HostAdapter);
-  /*
-    Reset the Host Adapter if requested.
-  */
-  if (HostAdapter->HostAdapterExternalReset)
-    {
-      BusLogic_Warning("Resetting %s due to External SCSI Bus Reset\n",
-		       HostAdapter, HostAdapter->FullModelName);
-      BusLogic_IncrementErrorCounter(&HostAdapter->ExternalHostAdapterResets);
-      BusLogic_ResetHostAdapter(HostAdapter, false);
-      HostAdapter->HostAdapterExternalReset = false;
-    }
-  else if (HostAdapter->HostAdapterInternalError)
-    {
-      BusLogic_Warning("Resetting %s due to Host Adapter Internal Error\n",
-		       HostAdapter, HostAdapter->FullModelName);
-      BusLogic_IncrementErrorCounter(&HostAdapter->HostAdapterInternalErrors);
-      BusLogic_ResetHostAdapter(HostAdapter, true);
-      HostAdapter->HostAdapterInternalError = false;
-    }
-  /*
-    Release exclusive access to Host Adapter.
-  */
-  BusLogic_ReleaseHostAdapterLockIH(HostAdapter, &ProcessorFlags);
-  return IRQ_HANDLED;
+	/*
+	   Release exclusive access to Host Adapter.
+	 */
+	BusLogic_ReleaseHostAdapterLockIH(HostAdapter, &ProcessorFlags);
+	return IRQ_HANDLED;
 }
 
 
@@ -3264,43 +2736,38 @@ static irqreturn_t BusLogic_InterruptHandler(int IRQ_Channel,
 */
 
 static boolean BusLogic_WriteOutgoingMailbox(struct BusLogic_HostAdapter
-					       *HostAdapter,
-					     enum BusLogic_ActionCode ActionCode,
-					     struct BusLogic_CCB *CCB)
+					     *HostAdapter, enum BusLogic_ActionCode ActionCode, struct BusLogic_CCB *CCB)
 {
-  struct BusLogic_OutgoingMailbox *NextOutgoingMailbox;
-  NextOutgoingMailbox = HostAdapter->NextOutgoingMailbox;
-  if (NextOutgoingMailbox->ActionCode == BusLogic_OutgoingMailboxFree)
-    {
-      CCB->Status = BusLogic_CCB_Active;
-      /*
-	The CCB field must be written before the Action Code field since
-	the Host Adapter is operating asynchronously and the locking code
-	does not protect against simultaneous access by the Host Adapter.
-      */
-      NextOutgoingMailbox->CCB = CCB->DMA_Handle;
-      NextOutgoingMailbox->ActionCode = ActionCode;
-      BusLogic_StartMailboxCommand(HostAdapter);
-      if (++NextOutgoingMailbox > HostAdapter->LastOutgoingMailbox)
-	NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
-      HostAdapter->NextOutgoingMailbox = NextOutgoingMailbox;
-      if (ActionCode == BusLogic_MailboxStartCommand)
-	{
-	  HostAdapter->ActiveCommands[CCB->TargetID]++;
-	  if (CCB->Opcode != BusLogic_BusDeviceReset)
-	    HostAdapter->TargetStatistics[CCB->TargetID].CommandsAttempted++;
+	struct BusLogic_OutgoingMailbox *NextOutgoingMailbox;
+	NextOutgoingMailbox = HostAdapter->NextOutgoingMailbox;
+	if (NextOutgoingMailbox->ActionCode == BusLogic_OutgoingMailboxFree) {
+		CCB->Status = BusLogic_CCB_Active;
+		/*
+		   The CCB field must be written before the Action Code field since
+		   the Host Adapter is operating asynchronously and the locking code
+		   does not protect against simultaneous access by the Host Adapter.
+		 */
+		NextOutgoingMailbox->CCB = CCB->DMA_Handle;
+		NextOutgoingMailbox->ActionCode = ActionCode;
+		BusLogic_StartMailboxCommand(HostAdapter);
+		if (++NextOutgoingMailbox > HostAdapter->LastOutgoingMailbox)
+			NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
+		HostAdapter->NextOutgoingMailbox = NextOutgoingMailbox;
+		if (ActionCode == BusLogic_MailboxStartCommand) {
+			HostAdapter->ActiveCommands[CCB->TargetID]++;
+			if (CCB->Opcode != BusLogic_BusDeviceReset)
+				HostAdapter->TargetStatistics[CCB->TargetID].CommandsAttempted++;
+		}
+		return true;
 	}
-      return true;
-    }
-  return false;
+	return false;
 }
 
 /* Error Handling (EH) support */
 
-static int BusLogic_host_reset(Scsi_Cmnd *SCpnt)
+static int BusLogic_host_reset(Scsi_Cmnd * SCpnt)
 {
-	struct BusLogic_HostAdapter *HostAdapter =
-		(struct BusLogic_HostAdapter *) SCpnt->device->host->hostdata;
+	struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) SCpnt->device->host->hostdata;
 
 	unsigned int id = SCpnt->device->id;
 	struct BusLogic_TargetStatistics *stats = &HostAdapter->TargetStatistics[id];
@@ -3314,237 +2781,190 @@ static int BusLogic_host_reset(Scsi_Cmnd *SCpnt)
   Outgoing Mailbox for execution by the associated Host Adapter.
 */
 
-static int BusLogic_QueueCommand(struct scsi_cmnd *Command,
-				 void (*CompletionRoutine)(struct scsi_cmnd *))
+static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRoutine) (struct scsi_cmnd *))
 {
-  struct BusLogic_HostAdapter *HostAdapter =
-    (struct BusLogic_HostAdapter *) Command->device->host->hostdata;
-  struct BusLogic_TargetFlags *TargetFlags =
-    &HostAdapter->TargetFlags[Command->device->id];
-  struct BusLogic_TargetStatistics *TargetStatistics =
-    HostAdapter->TargetStatistics;
-  unsigned char *CDB = Command->cmnd;
-  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;
-  struct BusLogic_CCB *CCB;
-  /*
-    SCSI REQUEST_SENSE commands will be executed automatically by the Host
-    Adapter for any errors, so they should not be executed explicitly unless
-    the Sense Data is zero indicating that no error occurred.
-  */
-  if (CDB[0] == REQUEST_SENSE && Command->sense_buffer[0] != 0)
-    {
-      Command->result = DID_OK << 16;
-      CompletionRoutine(Command);
-      return 0;
-    }
-  /*
-    Allocate a CCB from the Host Adapter's free list.  In the unlikely event
-    that there are none available and memory allocation fails, wait 1 second
-    and try again.  If that fails, the Host Adapter is probably hung so signal
-    an error as a Host Adapter Hard Reset should be initiated soon.
-  */
-  CCB = BusLogic_AllocateCCB(HostAdapter);
-  if (CCB == NULL)
-    {
-      BusLogic_ReleaseHostAdapterLock(HostAdapter);
-      BusLogic_Delay(1);
-      BusLogic_AcquireHostAdapterLock(HostAdapter);
-      CCB = BusLogic_AllocateCCB(HostAdapter);
-      if (CCB == NULL)
-	{
-	  Command->result = DID_ERROR << 16;
-	  CompletionRoutine(Command);
-	  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,
-		       scsi_to_pci_dma_dir(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,
-			 scsi_to_pci_dma_dir(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);
-	}
-    }
-  else
-    {
-      CCB->Opcode = BusLogic_InitiatorCCB;
-      CCB->DataLength = BufferLength;
-      CCB->DataPointer = 0;
-    }
-  switch (CDB[0])
-    {
-    case READ_6:
-    case READ_10:
-      CCB->DataDirection = BusLogic_DataInLengthChecked;
-      TargetStatistics[TargetID].ReadCommands++;
-      BusLogic_IncrementByteCounter(
-	&TargetStatistics[TargetID].TotalBytesRead, BufferLength);
-      BusLogic_IncrementSizeBucket(
-	TargetStatistics[TargetID].ReadCommandSizeBuckets, BufferLength);
-      break;
-    case WRITE_6:
-    case WRITE_10:
-      CCB->DataDirection = BusLogic_DataOutLengthChecked;
-      TargetStatistics[TargetID].WriteCommands++;
-      BusLogic_IncrementByteCounter(
-	&TargetStatistics[TargetID].TotalBytesWritten, BufferLength);
-      BusLogic_IncrementSizeBucket(
-	TargetStatistics[TargetID].WriteCommandSizeBuckets, BufferLength);
-      break;
-    default:
-      CCB->DataDirection = BusLogic_UncheckedDataTransfer;
-      break;
-    }
-  CCB->CDB_Length = CDB_Length;
-  CCB->HostAdapterStatus = 0;
-  CCB->TargetDeviceStatus = 0;
-  CCB->TargetID = TargetID;
-  CCB->LogicalUnit = LogicalUnit;
-  CCB->TagEnable = false;
-  CCB->LegacyTagEnable = false;
-  /*
-    BusLogic recommends that after a Reset the first couple of commands that
-    are sent to a Target Device be sent in a non Tagged Queue fashion so that
-    the Host Adapter and Target Device can establish Synchronous and Wide
-    Transfer before Queue Tag messages can interfere with the Synchronous and
-    Wide Negotiation messages.  By waiting to enable Tagged Queuing until after
-    the first BusLogic_MaxTaggedQueueDepth commands have been queued, it is
-    assured that after a Reset any pending commands are requeued before Tagged
-    Queuing is enabled and that the Tagged Queuing message will not occur while
-    the partition table is being printed.  In addition, some devices do not
-    properly handle the transition from non-tagged to tagged commands, so it is
-    necessary to wait until there are no pending commands for a target device
-    before queuing tagged commands.
-  */
-  if (HostAdapter->CommandsSinceReset[TargetID]++ >=
-	BusLogic_MaxTaggedQueueDepth &&
-      !TargetFlags->TaggedQueuingActive &&
-      HostAdapter->ActiveCommands[TargetID] == 0 &&
-      TargetFlags->TaggedQueuingSupported &&
-      (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)))
-    {
-      TargetFlags->TaggedQueuingActive = true;
-      BusLogic_Notice("Tagged Queuing now active for Target %d\n",
-		      HostAdapter, TargetID);
-    }
-  if (TargetFlags->TaggedQueuingActive)
-    {
-      enum BusLogic_QueueTag QueueTag = BusLogic_SimpleQueueTag;
-      /*
-	When using Tagged Queuing with Simple Queue Tags, it appears that disk
-	drive controllers do not guarantee that a queued command will not
-	remain in a disconnected state indefinitely if commands that read or
-	write nearer the head position continue to arrive without interruption.
-	Therefore, for each Target Device this driver keeps track of the last
-	time either the queue was empty or an Ordered Queue Tag was issued.  If
-	more than 4 seconds (one fifth of the 20 second disk timeout) have
-	elapsed since this last sequence point, this command will be issued
-	with an Ordered Queue Tag rather than a Simple Queue Tag, which forces
-	the Target Device to complete all previously queued commands before
-	this command may be executed.
-      */
-      if (HostAdapter->ActiveCommands[TargetID] == 0)
-	HostAdapter->LastSequencePoint[TargetID] = jiffies;
-      else if (jiffies - HostAdapter->LastSequencePoint[TargetID] > 4*HZ)
-	{
-	  HostAdapter->LastSequencePoint[TargetID] = jiffies;
-	  QueueTag = BusLogic_OrderedQueueTag;
-	}
-      if (HostAdapter->ExtendedLUNSupport)
-	{
-	  CCB->TagEnable = true;
-	  CCB->QueueTag = QueueTag;
+	struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Command->device->host->hostdata;
+	struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[Command->device->id];
+	struct BusLogic_TargetStatistics *TargetStatistics = HostAdapter->TargetStatistics;
+	unsigned char *CDB = Command->cmnd;
+	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;
+	struct BusLogic_CCB *CCB;
+	/*
+	   SCSI REQUEST_SENSE commands will be executed automatically by the Host
+	   Adapter for any errors, so they should not be executed explicitly unless
+	   the Sense Data is zero indicating that no error occurred.
+	 */
+	if (CDB[0] == REQUEST_SENSE && Command->sense_buffer[0] != 0) {
+		Command->result = DID_OK << 16;
+		CompletionRoutine(Command);
+		return 0;
 	}
-      else
-	{
-	  CCB->LegacyTagEnable = true;
-	  CCB->LegacyQueueTag = QueueTag;
+	/*
+	   Allocate a CCB from the Host Adapter's free list.  In the unlikely event
+	   that there are none available and memory allocation fails, wait 1 second
+	   and try again.  If that fails, the Host Adapter is probably hung so signal
+	   an error as a Host Adapter Hard Reset should be initiated soon.
+	 */
+	CCB = BusLogic_AllocateCCB(HostAdapter);
+	if (CCB == NULL) {
+		BusLogic_ReleaseHostAdapterLock(HostAdapter);
+		BusLogic_Delay(1);
+		BusLogic_AcquireHostAdapterLock(HostAdapter);
+		CCB = BusLogic_AllocateCCB(HostAdapter);
+		if (CCB == NULL) {
+			Command->result = DID_ERROR << 16;
+			CompletionRoutine(Command);
+			return 0;
+		}
 	}
-    }
-  memcpy(CCB->CDB, CDB, CDB_Length);
-  CCB->SenseDataLength = sizeof(Command->sense_buffer);
-  CCB->SenseDataPointer = pci_map_single(HostAdapter->PCI_Device,
-					 Command->sense_buffer,
-					 CCB->SenseDataLength,
-					 PCI_DMA_FROMDEVICE);
-  CCB->Command = Command;
-  Command->scsi_done = CompletionRoutine;
-  if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
-    {
-      /*
-	Place the CCB in an Outgoing Mailbox.  The higher levels of the SCSI
-	Subsystem should not attempt to queue more commands than can be placed
-	in Outgoing Mailboxes, so there should always be one free.  In the
-	unlikely event that there are none available, wait 1 second and try
-	again.  If that fails, the Host Adapter is probably hung so signal an
-	error as a Host Adapter Hard Reset should be initiated soon.
-      */
-      if (!BusLogic_WriteOutgoingMailbox(
-	     HostAdapter, BusLogic_MailboxStartCommand, CCB))
-	{
-	  BusLogic_ReleaseHostAdapterLock(HostAdapter);
-	  BusLogic_Warning("Unable to write Outgoing Mailbox - "
-			   "Pausing for 1 second\n", HostAdapter);
-	  BusLogic_Delay(1);
-	  BusLogic_AcquireHostAdapterLock(HostAdapter);
-	  if (!BusLogic_WriteOutgoingMailbox(
-		 HostAdapter, BusLogic_MailboxStartCommand, CCB))
-	    {
-	      BusLogic_Warning("Still unable to write Outgoing Mailbox - "
-			       "Host Adapter Dead?\n", HostAdapter);
-	      BusLogic_DeallocateCCB(CCB);
-	      Command->result = DID_ERROR << 16;
-	      Command->scsi_done(Command);
-	    }
+	/*
+	   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, scsi_to_pci_dma_dir(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, scsi_to_pci_dma_dir(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);
+		}
+	} else {
+		CCB->Opcode = BusLogic_InitiatorCCB;
+		CCB->DataLength = BufferLength;
+		CCB->DataPointer = 0;
+	}
+	switch (CDB[0]) {
+	case READ_6:
+	case READ_10:
+		CCB->DataDirection = BusLogic_DataInLengthChecked;
+		TargetStatistics[TargetID].ReadCommands++;
+		BusLogic_IncrementByteCounter(&TargetStatistics[TargetID].TotalBytesRead, BufferLength);
+		BusLogic_IncrementSizeBucket(TargetStatistics[TargetID].ReadCommandSizeBuckets, BufferLength);
+		break;
+	case WRITE_6:
+	case WRITE_10:
+		CCB->DataDirection = BusLogic_DataOutLengthChecked;
+		TargetStatistics[TargetID].WriteCommands++;
+		BusLogic_IncrementByteCounter(&TargetStatistics[TargetID].TotalBytesWritten, BufferLength);
+		BusLogic_IncrementSizeBucket(TargetStatistics[TargetID].WriteCommandSizeBuckets, BufferLength);
+		break;
+	default:
+		CCB->DataDirection = BusLogic_UncheckedDataTransfer;
+		break;
+	}
+	CCB->CDB_Length = CDB_Length;
+	CCB->HostAdapterStatus = 0;
+	CCB->TargetDeviceStatus = 0;
+	CCB->TargetID = TargetID;
+	CCB->LogicalUnit = LogicalUnit;
+	CCB->TagEnable = false;
+	CCB->LegacyTagEnable = false;
+	/*
+	   BusLogic recommends that after a Reset the first couple of commands that
+	   are sent to a Target Device be sent in a non Tagged Queue fashion so that
+	   the Host Adapter and Target Device can establish Synchronous and Wide
+	   Transfer before Queue Tag messages can interfere with the Synchronous and
+	   Wide Negotiation messages.  By waiting to enable Tagged Queuing until after
+	   the first BusLogic_MaxTaggedQueueDepth commands have been queued, it is
+	   assured that after a Reset any pending commands are requeued before Tagged
+	   Queuing is enabled and that the Tagged Queuing message will not occur while
+	   the partition table is being printed.  In addition, some devices do not
+	   properly handle the transition from non-tagged to tagged commands, so it is
+	   necessary to wait until there are no pending commands for a target device
+	   before queuing tagged commands.
+	 */
+	if (HostAdapter->CommandsSinceReset[TargetID]++ >=
+	    BusLogic_MaxTaggedQueueDepth && !TargetFlags->TaggedQueuingActive && HostAdapter->ActiveCommands[TargetID] == 0 && TargetFlags->TaggedQueuingSupported && (HostAdapter->TaggedQueuingPermitted & (1 << TargetID))) {
+		TargetFlags->TaggedQueuingActive = true;
+		BusLogic_Notice("Tagged Queuing now active for Target %d\n", HostAdapter, TargetID);
+	}
+	if (TargetFlags->TaggedQueuingActive) {
+		enum BusLogic_QueueTag QueueTag = BusLogic_SimpleQueueTag;
+		/*
+		   When using Tagged Queuing with Simple Queue Tags, it appears that disk
+		   drive controllers do not guarantee that a queued command will not
+		   remain in a disconnected state indefinitely if commands that read or
+		   write nearer the head position continue to arrive without interruption.
+		   Therefore, for each Target Device this driver keeps track of the last
+		   time either the queue was empty or an Ordered Queue Tag was issued.  If
+		   more than 4 seconds (one fifth of the 20 second disk timeout) have
+		   elapsed since this last sequence point, this command will be issued
+		   with an Ordered Queue Tag rather than a Simple Queue Tag, which forces
+		   the Target Device to complete all previously queued commands before
+		   this command may be executed.
+		 */
+		if (HostAdapter->ActiveCommands[TargetID] == 0)
+			HostAdapter->LastSequencePoint[TargetID] = jiffies;
+		else if (jiffies - HostAdapter->LastSequencePoint[TargetID] > 4 * HZ) {
+			HostAdapter->LastSequencePoint[TargetID] = jiffies;
+			QueueTag = BusLogic_OrderedQueueTag;
+		}
+		if (HostAdapter->ExtendedLUNSupport) {
+			CCB->TagEnable = true;
+			CCB->QueueTag = QueueTag;
+		} else {
+			CCB->LegacyTagEnable = true;
+			CCB->LegacyQueueTag = QueueTag;
+		}
 	}
-    }
-  else
-    {
-      /*
-	Call the FlashPoint SCCB Manager to start execution of the CCB.
-      */
-      CCB->Status = BusLogic_CCB_Active;
-      HostAdapter->ActiveCommands[TargetID]++;
-      TargetStatistics[TargetID].CommandsAttempted++;
-      FlashPoint_StartCCB(HostAdapter->CardHandle, CCB);
-      /*
-	The Command may have already completed and BusLogic_QueueCompletedCCB
-	been called, or it may still be pending.
-      */
-      if (CCB->Status == BusLogic_CCB_Completed)
-	BusLogic_ProcessCompletedCCBs(HostAdapter);
-    }
-  return 0;
+	memcpy(CCB->CDB, CDB, CDB_Length);
+	CCB->SenseDataLength = sizeof(Command->sense_buffer);
+	CCB->SenseDataPointer = pci_map_single(HostAdapter->PCI_Device, Command->sense_buffer, CCB->SenseDataLength, PCI_DMA_FROMDEVICE);
+	CCB->Command = Command;
+	Command->scsi_done = CompletionRoutine;
+	if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) {
+		/*
+		   Place the CCB in an Outgoing Mailbox.  The higher levels of the SCSI
+		   Subsystem should not attempt to queue more commands than can be placed
+		   in Outgoing Mailboxes, so there should always be one free.  In the
+		   unlikely event that there are none available, wait 1 second and try
+		   again.  If that fails, the Host Adapter is probably hung so signal an
+		   error as a Host Adapter Hard Reset should be initiated soon.
+		 */
+		if (!BusLogic_WriteOutgoingMailbox(HostAdapter, BusLogic_MailboxStartCommand, CCB)) {
+			BusLogic_ReleaseHostAdapterLock(HostAdapter);
+			BusLogic_Warning("Unable to write Outgoing Mailbox - " "Pausing for 1 second\n", HostAdapter);
+			BusLogic_Delay(1);
+			BusLogic_AcquireHostAdapterLock(HostAdapter);
+			if (!BusLogic_WriteOutgoingMailbox(HostAdapter, BusLogic_MailboxStartCommand, CCB)) {
+				BusLogic_Warning("Still unable to write Outgoing Mailbox - " "Host Adapter Dead?\n", HostAdapter);
+				BusLogic_DeallocateCCB(CCB);
+				Command->result = DID_ERROR << 16;
+				Command->scsi_done(Command);
+			}
+		}
+	} else {
+		/*
+		   Call the FlashPoint SCCB Manager to start execution of the CCB.
+		 */
+		CCB->Status = BusLogic_CCB_Active;
+		HostAdapter->ActiveCommands[TargetID]++;
+		TargetStatistics[TargetID].CommandsAttempted++;
+		FlashPoint_StartCCB(HostAdapter->CardHandle, CCB);
+		/*
+		   The Command may have already completed and BusLogic_QueueCompletedCCB
+		   been called, or it may still be pending.
+		 */
+		if (CCB->Status == BusLogic_CCB_Completed)
+			BusLogic_ProcessCompletedCCBs(HostAdapter);
+	}
+	return 0;
 }
 
 
@@ -3554,105 +2974,75 @@ static int BusLogic_QueueCommand(struct scsi_cmnd *Command,
 
 static int BusLogic_AbortCommand(struct scsi_cmnd *Command)
 {
-  struct BusLogic_HostAdapter *HostAdapter =
-    (struct BusLogic_HostAdapter *) Command->device->host->hostdata;
-
-  int TargetID = Command->device->id;
-  struct BusLogic_CCB *CCB;
-  BusLogic_IncrementErrorCounter(
-    &HostAdapter->TargetStatistics[TargetID].CommandAbortsRequested);
-  /*
-    If this Command has already completed, then no Abort is necessary.
-  */
-  if (Command->serial_number != Command->serial_number_at_timeout)
-    {
-      BusLogic_Warning("Unable to Abort Command to Target %d - "
-		       "Already Completed\n", HostAdapter, TargetID);
-      return SUCCESS;
-    }
-  /*
-    Attempt to find an Active CCB for this Command.  If no Active CCB for this
-    Command is found, then no Abort is necessary.
-  */
-  for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
-    if (CCB->Command == Command) break;
-  if (CCB == NULL)
-    {
-      BusLogic_Warning("Unable to Abort Command to Target %d - "
-		       "No CCB Found\n", HostAdapter, TargetID);
-      return SUCCESS;
-    }
-  else if (CCB->Status == BusLogic_CCB_Completed)
-    {
-      BusLogic_Warning("Unable to Abort Command to Target %d - "
-		       "CCB Completed\n", HostAdapter, TargetID);
-      return SUCCESS;
-    }
-  else if (CCB->Status == BusLogic_CCB_Reset)
-    {
-      BusLogic_Warning("Unable to Abort Command to Target %d - "
-		       "CCB Reset\n", HostAdapter, TargetID);
-      return SUCCESS;
-    }
-  if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
-    {
-      /*
-	Attempt to Abort this CCB.  MultiMaster Firmware versions prior to 5.xx
-	do not generate Abort Tag messages, but only generate the non-tagged
-	Abort message.  Since non-tagged commands are not sent by the Host
-	Adapter until the queue of outstanding tagged commands has completed,
-	and the Abort message is treated as a non-tagged command, it is
-	effectively impossible to abort commands when Tagged Queuing is active.
-	Firmware version 5.xx does generate Abort Tag messages, so it is
-	possible to abort commands when Tagged Queuing is active.
-      */
-      if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive &&
-	  HostAdapter->FirmwareVersion[0] < '5')
-	{
-	  BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - "
-			   "Abort Tag Not Supported\n",
-			   HostAdapter, CCB->SerialNumber, TargetID);
-	  return FAILURE;
-	}
-      else if (BusLogic_WriteOutgoingMailbox(
-		 HostAdapter, BusLogic_MailboxAbortCommand, CCB))
-	{
-	  BusLogic_Warning("Aborting CCB #%ld to Target %d\n",
-			   HostAdapter, CCB->SerialNumber, TargetID);
-	  BusLogic_IncrementErrorCounter(
-	    &HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted);
-	  return SUCCESS;
-	}
-      else
-	{
-	  BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - "
-			   "No Outgoing Mailboxes\n",
-			    HostAdapter, CCB->SerialNumber, TargetID);
-	  return FAILURE;
+	struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) Command->device->host->hostdata;
+
+	int TargetID = Command->device->id;
+	struct BusLogic_CCB *CCB;
+	BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].CommandAbortsRequested);
+	/*
+	   If this Command has already completed, then no Abort is necessary.
+	 */
+	if (Command->serial_number != Command->serial_number_at_timeout) {
+		BusLogic_Warning("Unable to Abort Command to Target %d - " "Already Completed\n", HostAdapter, TargetID);
+		return SUCCESS;
 	}
-    }
-  else
-    {
-      /*
-	Call the FlashPoint SCCB Manager to abort execution of the CCB.
-      */
-      BusLogic_Warning("Aborting CCB #%ld to Target %d\n",
-		       HostAdapter, CCB->SerialNumber, TargetID);
-      BusLogic_IncrementErrorCounter(
-	&HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted);
-      FlashPoint_AbortCCB(HostAdapter->CardHandle, CCB);
-      /*
-	The Abort may have already been completed and
-	BusLogic_QueueCompletedCCB been called, or it
-	may still be pending.
-      */
-      if (CCB->Status == BusLogic_CCB_Completed)
-	{
-	  BusLogic_ProcessCompletedCCBs(HostAdapter);
+	/*
+	   Attempt to find an Active CCB for this Command.  If no Active CCB for this
+	   Command is found, then no Abort is necessary.
+	 */
+	for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
+		if (CCB->Command == Command)
+			break;
+	if (CCB == NULL) {
+		BusLogic_Warning("Unable to Abort Command to Target %d - " "No CCB Found\n", HostAdapter, TargetID);
+		return SUCCESS;
+	} else if (CCB->Status == BusLogic_CCB_Completed) {
+		BusLogic_Warning("Unable to Abort Command to Target %d - " "CCB Completed\n", HostAdapter, TargetID);
+		return SUCCESS;
+	} else if (CCB->Status == BusLogic_CCB_Reset) {
+		BusLogic_Warning("Unable to Abort Command to Target %d - " "CCB Reset\n", HostAdapter, TargetID);
+		return SUCCESS;
+	}
+	if (BusLogic_MultiMasterHostAdapterP(HostAdapter)) {
+		/*
+		   Attempt to Abort this CCB.  MultiMaster Firmware versions prior to 5.xx
+		   do not generate Abort Tag messages, but only generate the non-tagged
+		   Abort message.  Since non-tagged commands are not sent by the Host
+		   Adapter until the queue of outstanding tagged commands has completed,
+		   and the Abort message is treated as a non-tagged command, it is
+		   effectively impossible to abort commands when Tagged Queuing is active.
+		   Firmware version 5.xx does generate Abort Tag messages, so it is
+		   possible to abort commands when Tagged Queuing is active.
+		 */
+		if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive && HostAdapter->FirmwareVersion[0] < '5') {
+			BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - " "Abort Tag Not Supported\n", HostAdapter, CCB->SerialNumber, TargetID);
+			return FAILURE;
+		} else if (BusLogic_WriteOutgoingMailbox(HostAdapter, BusLogic_MailboxAbortCommand, CCB)) {
+			BusLogic_Warning("Aborting CCB #%ld to Target %d\n", HostAdapter, CCB->SerialNumber, TargetID);
+			BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted);
+			return SUCCESS;
+		} else {
+			BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - " "No Outgoing Mailboxes\n", HostAdapter, CCB->SerialNumber, TargetID);
+			return FAILURE;
+		}
+	} else {
+		/*
+		   Call the FlashPoint SCCB Manager to abort execution of the CCB.
+		 */
+		BusLogic_Warning("Aborting CCB #%ld to Target %d\n", HostAdapter, CCB->SerialNumber, TargetID);
+		BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted);
+		FlashPoint_AbortCCB(HostAdapter->CardHandle, CCB);
+		/*
+		   The Abort may have already been completed and
+		   BusLogic_QueueCompletedCCB been called, or it
+		   may still be pending.
+		 */
+		if (CCB->Status == BusLogic_CCB_Completed) {
+			BusLogic_ProcessCompletedCCBs(HostAdapter);
+		}
+		return SUCCESS;
 	}
-      return SUCCESS;
-    }
-  return SUCCESS;
+	return SUCCESS;
 }
 
 /*
@@ -3660,8 +3050,7 @@ static int BusLogic_AbortCommand(struct scsi_cmnd *Command)
   currently executing SCSI Commands as having been Reset.
 */
 
-static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter,
-				     boolean HardReset)
+static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter, boolean HardReset)
 {
 	struct BusLogic_CCB *CCB;
 	int TargetID;
@@ -3670,10 +3059,8 @@ static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter,
 	 * Attempt to Reset and Reinitialize the Host Adapter.
 	 */
 
-	if (!(BusLogic_HardwareResetHostAdapter(HostAdapter, HardReset) &&
-		BusLogic_InitializeHostAdapter(HostAdapter))) {
-		BusLogic_Error("Resetting %s Failed\n", HostAdapter,
-			       HostAdapter->FullModelName);
+	if (!(BusLogic_HardwareResetHostAdapter(HostAdapter, HardReset) && BusLogic_InitializeHostAdapter(HostAdapter))) {
+		BusLogic_Error("Resetting %s Failed\n", HostAdapter, HostAdapter->FullModelName);
 		return FAILURE;
 	}
 
@@ -3721,98 +3108,70 @@ static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *HostAdapter,
   the BIOS, and a warning may be displayed.
 */
 
-static int BusLogic_BIOSDiskParameters(struct scsi_device *sdev, struct block_device *Device,
-				       sector_t capacity, int *Parameters)
+static int BusLogic_BIOSDiskParameters(struct scsi_device *sdev, struct block_device *Device, sector_t capacity, int *Parameters)
 {
-  struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) sdev->host->hostdata;
-  struct BIOS_DiskParameters *DiskParameters = (struct BIOS_DiskParameters *) Parameters;
-  unsigned char *buf;
-  if (HostAdapter->ExtendedTranslationEnabled &&
-      capacity >= 2*1024*1024 /* 1 GB in 512 byte sectors */)
-    {
-      if (capacity >= 4*1024*1024 /* 2 GB in 512 byte sectors */)
-	{
-	  DiskParameters->Heads = 255;
-	  DiskParameters->Sectors = 63;
-	}
-      else
-	{
-	  DiskParameters->Heads = 128;
-	  DiskParameters->Sectors = 32;
-	}
-    }
-  else
-    {
-      DiskParameters->Heads = 64;
-      DiskParameters->Sectors = 32;
-    }
-  DiskParameters->Cylinders =
-    (unsigned long)capacity / (DiskParameters->Heads * DiskParameters->Sectors);
-  buf = scsi_bios_ptable(Device);
-  if (buf == NULL) return 0;
-  /*
-    If the boot sector partition table flag is valid, search for a partition
-    table entry whose end_head matches one of the standard BusLogic geometry
-    translations (64/32, 128/32, or 255/63).
-  */
-  if (*(unsigned short *) (buf+64) == 0xAA55)
-    {
-      struct partition *FirstPartitionEntry = (struct partition *) buf;
-      struct partition *PartitionEntry = FirstPartitionEntry;
-      int SavedCylinders = DiskParameters->Cylinders, PartitionNumber;
-      unsigned char PartitionEntryEndHead=0, PartitionEntryEndSector=0;
-      for (PartitionNumber = 0; PartitionNumber < 4; PartitionNumber++)
-	{
-	  PartitionEntryEndHead = PartitionEntry->end_head;
-	  PartitionEntryEndSector = PartitionEntry->end_sector & 0x3F;
-	  if (PartitionEntryEndHead == 64-1)
-	    {
-	      DiskParameters->Heads = 64;
-	      DiskParameters->Sectors = 32;
-	      break;
-	    }
-	  else if (PartitionEntryEndHead == 128-1)
-	    {
-	      DiskParameters->Heads = 128;
-	      DiskParameters->Sectors = 32;
-	      break;
-	    }
-	  else if (PartitionEntryEndHead == 255-1)
-	    {
-	      DiskParameters->Heads = 255;
-	      DiskParameters->Sectors = 63;
-	      break;
-	    }
-	  PartitionEntry++;
-	}
-      if (PartitionNumber == 4)
-	{
-	  PartitionEntryEndHead = FirstPartitionEntry->end_head;
-	  PartitionEntryEndSector = FirstPartitionEntry->end_sector & 0x3F;
-	}
-      DiskParameters->Cylinders =
-	(unsigned long)capacity / (DiskParameters->Heads * DiskParameters->Sectors);
-      if (PartitionNumber < 4 &&
-	  PartitionEntryEndSector == DiskParameters->Sectors)
-	{
-	  if (DiskParameters->Cylinders != SavedCylinders)
-	    BusLogic_Warning("Adopting Geometry %d/%d from Partition Table\n",
-			     HostAdapter,
-			     DiskParameters->Heads, DiskParameters->Sectors);
+	struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) sdev->host->hostdata;
+	struct BIOS_DiskParameters *DiskParameters = (struct BIOS_DiskParameters *) Parameters;
+	unsigned char *buf;
+	if (HostAdapter->ExtendedTranslationEnabled && capacity >= 2 * 1024 * 1024 /* 1 GB in 512 byte sectors */ ) {
+		if (capacity >= 4 * 1024 * 1024 /* 2 GB in 512 byte sectors */ ) {
+			DiskParameters->Heads = 255;
+			DiskParameters->Sectors = 63;
+		} else {
+			DiskParameters->Heads = 128;
+			DiskParameters->Sectors = 32;
+		}
+	} else {
+		DiskParameters->Heads = 64;
+		DiskParameters->Sectors = 32;
 	}
-      else if (PartitionEntryEndHead > 0 || PartitionEntryEndSector > 0)
-	{
-	  BusLogic_Warning("Warning: Partition Table appears to "
-			   "have Geometry %d/%d which is\n", HostAdapter,
-			   PartitionEntryEndHead + 1,
-			   PartitionEntryEndSector);
-	  BusLogic_Warning("not compatible with current BusLogic "
-			   "Host Adapter Geometry %d/%d\n", HostAdapter,
-			   DiskParameters->Heads, DiskParameters->Sectors);
+	DiskParameters->Cylinders = (unsigned long) capacity / (DiskParameters->Heads * DiskParameters->Sectors);
+	buf = scsi_bios_ptable(Device);
+	if (buf == NULL)
+		return 0;
+	/*
+	   If the boot sector partition table flag is valid, search for a partition
+	   table entry whose end_head matches one of the standard BusLogic geometry
+	   translations (64/32, 128/32, or 255/63).
+	 */
+	if (*(unsigned short *) (buf + 64) == 0xAA55) {
+		struct partition *FirstPartitionEntry = (struct partition *) buf;
+		struct partition *PartitionEntry = FirstPartitionEntry;
+		int SavedCylinders = DiskParameters->Cylinders, PartitionNumber;
+		unsigned char PartitionEntryEndHead = 0, PartitionEntryEndSector = 0;
+		for (PartitionNumber = 0; PartitionNumber < 4; PartitionNumber++) {
+			PartitionEntryEndHead = PartitionEntry->end_head;
+			PartitionEntryEndSector = PartitionEntry->end_sector & 0x3F;
+			if (PartitionEntryEndHead == 64 - 1) {
+				DiskParameters->Heads = 64;
+				DiskParameters->Sectors = 32;
+				break;
+			} else if (PartitionEntryEndHead == 128 - 1) {
+				DiskParameters->Heads = 128;
+				DiskParameters->Sectors = 32;
+				break;
+			} else if (PartitionEntryEndHead == 255 - 1) {
+				DiskParameters->Heads = 255;
+				DiskParameters->Sectors = 63;
+				break;
+			}
+			PartitionEntry++;
+		}
+		if (PartitionNumber == 4) {
+			PartitionEntryEndHead = FirstPartitionEntry->end_head;
+			PartitionEntryEndSector = FirstPartitionEntry->end_sector & 0x3F;
+		}
+		DiskParameters->Cylinders = (unsigned long) capacity / (DiskParameters->Heads * DiskParameters->Sectors);
+		if (PartitionNumber < 4 && PartitionEntryEndSector == DiskParameters->Sectors) {
+			if (DiskParameters->Cylinders != SavedCylinders)
+				BusLogic_Warning("Adopting Geometry %d/%d from Partition Table\n", HostAdapter, DiskParameters->Heads, DiskParameters->Sectors);
+		} else if (PartitionEntryEndHead > 0 || PartitionEntryEndSector > 0) {
+			BusLogic_Warning("Warning: Partition Table appears to " "have Geometry %d/%d which is\n", HostAdapter, PartitionEntryEndHead + 1, PartitionEntryEndSector);
+			BusLogic_Warning("not compatible with current BusLogic " "Host Adapter Geometry %d/%d\n", HostAdapter, DiskParameters->Heads, DiskParameters->Sectors);
+		}
 	}
-    }
-  kfree(buf);
-  return 0;
+	kfree(buf);
+	return 0;
 }
 
 
@@ -3820,178 +3179,124 @@ static int BusLogic_BIOSDiskParameters(struct scsi_device *sdev, struct block_de
   BugLogic_ProcDirectoryInfo implements /proc/scsi/BusLogic/<N>.
 */
 
-static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *shost, char *ProcBuffer,
-				      char **StartPointer, off_t Offset,
-				      int BytesAvailable, int WriteFlag)
+static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *shost, char *ProcBuffer, char **StartPointer, off_t Offset, int BytesAvailable, int WriteFlag)
 {
-  struct BusLogic_HostAdapter *HostAdapter;
-  struct BusLogic_TargetStatistics *TargetStatistics;
-  int TargetID, Length;
-  char *Buffer;
-  for (HostAdapter = BusLogic_FirstRegisteredHostAdapter;
-       HostAdapter != NULL;
-       HostAdapter = HostAdapter->Next)
-    if (HostAdapter->HostNumber == shost->host_no) break;
-  if (HostAdapter == NULL)
-    {
-      BusLogic_Error("Cannot find Host Adapter for SCSI Host %d\n",
-		     NULL, shost->host_no);
-      return 0;
-    }
-  TargetStatistics = HostAdapter->TargetStatistics;
-  if (WriteFlag)
-    {
-      HostAdapter->ExternalHostAdapterResets = 0;
-      HostAdapter->HostAdapterInternalErrors = 0;
-      memset(TargetStatistics, 0,
-	     BusLogic_MaxTargetDevices * sizeof(struct BusLogic_TargetStatistics));
-      return 0;
-    }
-  Buffer = HostAdapter->MessageBuffer;
-  Length = HostAdapter->MessageBufferLength;
-  Length += sprintf(&Buffer[Length], "\n\
+	struct BusLogic_HostAdapter *HostAdapter;
+	struct BusLogic_TargetStatistics *TargetStatistics;
+	int TargetID, Length;
+	char *Buffer;
+	for (HostAdapter = BusLogic_FirstRegisteredHostAdapter; HostAdapter != NULL; HostAdapter = HostAdapter->Next)
+		if (HostAdapter->HostNumber == shost->host_no)
+			break;
+	if (HostAdapter == NULL) {
+		BusLogic_Error("Cannot find Host Adapter for SCSI Host %d\n", NULL, shost->host_no);
+		return 0;
+	}
+	TargetStatistics = HostAdapter->TargetStatistics;
+	if (WriteFlag) {
+		HostAdapter->ExternalHostAdapterResets = 0;
+		HostAdapter->HostAdapterInternalErrors = 0;
+		memset(TargetStatistics, 0, BusLogic_MaxTargetDevices * sizeof(struct BusLogic_TargetStatistics));
+		return 0;
+	}
+	Buffer = HostAdapter->MessageBuffer;
+	Length = HostAdapter->MessageBufferLength;
+	Length += sprintf(&Buffer[Length], "\n\
 Current Driver Queue Depth:	%d\n\
-Currently Allocated CCBs:	%d\n",
-		    HostAdapter->DriverQueueDepth,
-		    HostAdapter->AllocatedCCBs);
-  Length += sprintf(&Buffer[Length], "\n\n\
+Currently Allocated CCBs:	%d\n", HostAdapter->DriverQueueDepth, HostAdapter->AllocatedCCBs);
+	Length += sprintf(&Buffer[Length], "\n\n\
 			   DATA TRANSFER STATISTICS\n\
 \n\
 Target	Tagged Queuing	Queue Depth  Active  Attempted	Completed\n\
 ======	==============	===========  ======  =========	=========\n");
-  for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-    {
-      struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
-      if (!TargetFlags->TargetExists) continue;
-      Length +=
-	sprintf(&Buffer[Length], "  %2d	%s", TargetID,
-		(TargetFlags->TaggedQueuingSupported
-		 ? (TargetFlags->TaggedQueuingActive
-		    ? "    Active"
-		    : (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)
-		       ? "  Permitted" : "   Disabled"))
-		 : "Not Supported"));
-      Length += sprintf(&Buffer[Length],
-			"	    %3d       %3u    %9u	%9u\n",
-			HostAdapter->QueueDepth[TargetID],
-			HostAdapter->ActiveCommands[TargetID],
-			TargetStatistics[TargetID].CommandsAttempted,
-			TargetStatistics[TargetID].CommandsCompleted);
-    }
-  Length += sprintf(&Buffer[Length], "\n\
+	for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
+		struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
+		if (!TargetFlags->TargetExists)
+			continue;
+		Length += sprintf(&Buffer[Length], "  %2d	%s", TargetID, (TargetFlags->TaggedQueuingSupported ? (TargetFlags->TaggedQueuingActive ? "    Active" : (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)
+																				    ? "  Permitted" : "   Disabled"))
+									  : "Not Supported"));
+		Length += sprintf(&Buffer[Length],
+				  "	    %3d       %3u    %9u	%9u\n", HostAdapter->QueueDepth[TargetID], HostAdapter->ActiveCommands[TargetID], TargetStatistics[TargetID].CommandsAttempted, TargetStatistics[TargetID].CommandsCompleted);
+	}
+	Length += sprintf(&Buffer[Length], "\n\
 Target  Read Commands  Write Commands   Total Bytes Read    Total Bytes Written\n\
 ======  =============  ==============  ===================  ===================\n");
-  for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-    {
-      struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
-      if (!TargetFlags->TargetExists) continue;
-      Length +=
-	sprintf(&Buffer[Length], "  %2d	  %9u	 %9u", TargetID,
-		TargetStatistics[TargetID].ReadCommands,
-		TargetStatistics[TargetID].WriteCommands);
-      if (TargetStatistics[TargetID].TotalBytesRead.Billions > 0)
-	Length +=
-	  sprintf(&Buffer[Length], "     %9u%09u",
-		  TargetStatistics[TargetID].TotalBytesRead.Billions,
-		  TargetStatistics[TargetID].TotalBytesRead.Units);
-      else
-	Length +=
-	  sprintf(&Buffer[Length], "		%9u",
-		  TargetStatistics[TargetID].TotalBytesRead.Units);
-      if (TargetStatistics[TargetID].TotalBytesWritten.Billions > 0)
-	Length +=
-	  sprintf(&Buffer[Length], "   %9u%09u\n",
-		  TargetStatistics[TargetID].TotalBytesWritten.Billions,
-		  TargetStatistics[TargetID].TotalBytesWritten.Units);
-      else
-	Length +=
-	  sprintf(&Buffer[Length], "	     %9u\n",
-		  TargetStatistics[TargetID].TotalBytesWritten.Units);
-    }
-  Length += sprintf(&Buffer[Length], "\n\
+	for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
+		struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
+		if (!TargetFlags->TargetExists)
+			continue;
+		Length += sprintf(&Buffer[Length], "  %2d	  %9u	 %9u", TargetID, TargetStatistics[TargetID].ReadCommands, TargetStatistics[TargetID].WriteCommands);
+		if (TargetStatistics[TargetID].TotalBytesRead.Billions > 0)
+			Length += sprintf(&Buffer[Length], "     %9u%09u", TargetStatistics[TargetID].TotalBytesRead.Billions, TargetStatistics[TargetID].TotalBytesRead.Units);
+		else
+			Length += sprintf(&Buffer[Length], "		%9u", TargetStatistics[TargetID].TotalBytesRead.Units);
+		if (TargetStatistics[TargetID].TotalBytesWritten.Billions > 0)
+			Length += sprintf(&Buffer[Length], "   %9u%09u\n", TargetStatistics[TargetID].TotalBytesWritten.Billions, TargetStatistics[TargetID].TotalBytesWritten.Units);
+		else
+			Length += sprintf(&Buffer[Length], "	     %9u\n", TargetStatistics[TargetID].TotalBytesWritten.Units);
+	}
+	Length += sprintf(&Buffer[Length], "\n\
 Target  Command    0-1KB      1-2KB      2-4KB      4-8KB     8-16KB\n\
 ======  =======  =========  =========  =========  =========  =========\n");
-  for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-    {
-      struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
-      if (!TargetFlags->TargetExists) continue;
-      Length +=
-	sprintf(&Buffer[Length],
-		"  %2d	 Read	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
-		TargetStatistics[TargetID].ReadCommandSizeBuckets[0],
-		TargetStatistics[TargetID].ReadCommandSizeBuckets[1],
-		TargetStatistics[TargetID].ReadCommandSizeBuckets[2],
-		TargetStatistics[TargetID].ReadCommandSizeBuckets[3],
-		TargetStatistics[TargetID].ReadCommandSizeBuckets[4]);
-      Length +=
-	sprintf(&Buffer[Length],
-		"  %2d	 Write	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
-		TargetStatistics[TargetID].WriteCommandSizeBuckets[0],
-		TargetStatistics[TargetID].WriteCommandSizeBuckets[1],
-		TargetStatistics[TargetID].WriteCommandSizeBuckets[2],
-		TargetStatistics[TargetID].WriteCommandSizeBuckets[3],
-		TargetStatistics[TargetID].WriteCommandSizeBuckets[4]);
-    }
-  Length += sprintf(&Buffer[Length], "\n\
+	for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
+		struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
+		if (!TargetFlags->TargetExists)
+			continue;
+		Length +=
+		    sprintf(&Buffer[Length],
+			    "  %2d	 Read	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
+			    TargetStatistics[TargetID].ReadCommandSizeBuckets[0],
+			    TargetStatistics[TargetID].ReadCommandSizeBuckets[1], TargetStatistics[TargetID].ReadCommandSizeBuckets[2], TargetStatistics[TargetID].ReadCommandSizeBuckets[3], TargetStatistics[TargetID].ReadCommandSizeBuckets[4]);
+		Length +=
+		    sprintf(&Buffer[Length],
+			    "  %2d	 Write	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
+			    TargetStatistics[TargetID].WriteCommandSizeBuckets[0],
+			    TargetStatistics[TargetID].WriteCommandSizeBuckets[1], TargetStatistics[TargetID].WriteCommandSizeBuckets[2], TargetStatistics[TargetID].WriteCommandSizeBuckets[3], TargetStatistics[TargetID].WriteCommandSizeBuckets[4]);
+	}
+	Length += sprintf(&Buffer[Length], "\n\
 Target  Command   16-32KB    32-64KB   64-128KB   128-256KB   256KB+\n\
 ======  =======  =========  =========  =========  =========  =========\n");
-  for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-    {
-      struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
-      if (!TargetFlags->TargetExists) continue;
-      Length +=
-	sprintf(&Buffer[Length],
-		"  %2d	 Read	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
-		TargetStatistics[TargetID].ReadCommandSizeBuckets[5],
-		TargetStatistics[TargetID].ReadCommandSizeBuckets[6],
-		TargetStatistics[TargetID].ReadCommandSizeBuckets[7],
-		TargetStatistics[TargetID].ReadCommandSizeBuckets[8],
-		TargetStatistics[TargetID].ReadCommandSizeBuckets[9]);
-      Length +=
-	sprintf(&Buffer[Length],
-		"  %2d	 Write	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
-		TargetStatistics[TargetID].WriteCommandSizeBuckets[5],
-		TargetStatistics[TargetID].WriteCommandSizeBuckets[6],
-		TargetStatistics[TargetID].WriteCommandSizeBuckets[7],
-		TargetStatistics[TargetID].WriteCommandSizeBuckets[8],
-		TargetStatistics[TargetID].WriteCommandSizeBuckets[9]);
-    }
-  Length += sprintf(&Buffer[Length], "\n\n\
+	for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
+		struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
+		if (!TargetFlags->TargetExists)
+			continue;
+		Length +=
+		    sprintf(&Buffer[Length],
+			    "  %2d	 Read	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
+			    TargetStatistics[TargetID].ReadCommandSizeBuckets[5],
+			    TargetStatistics[TargetID].ReadCommandSizeBuckets[6], TargetStatistics[TargetID].ReadCommandSizeBuckets[7], TargetStatistics[TargetID].ReadCommandSizeBuckets[8], TargetStatistics[TargetID].ReadCommandSizeBuckets[9]);
+		Length +=
+		    sprintf(&Buffer[Length],
+			    "  %2d	 Write	 %9u  %9u  %9u  %9u  %9u\n", TargetID,
+			    TargetStatistics[TargetID].WriteCommandSizeBuckets[5],
+			    TargetStatistics[TargetID].WriteCommandSizeBuckets[6], TargetStatistics[TargetID].WriteCommandSizeBuckets[7], TargetStatistics[TargetID].WriteCommandSizeBuckets[8], TargetStatistics[TargetID].WriteCommandSizeBuckets[9]);
+	}
+	Length += sprintf(&Buffer[Length], "\n\n\
 			   ERROR RECOVERY STATISTICS\n\
 \n\
 	  Command Aborts      Bus Device Resets	  Host Adapter Resets\n\
 Target	Requested Completed  Requested Completed  Requested Completed\n\
   ID	\\\\\\\\ Attempted ////  \\\\\\\\ Attempted ////  \\\\\\\\ Attempted ////\n\
 ======	 ===== ===== =====    ===== ===== =====	   ===== ===== =====\n");
-  for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
-    {
-      struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
-      if (!TargetFlags->TargetExists) continue;
-      Length +=
-	sprintf(&Buffer[Length], "\
-  %2d	 %5d %5d %5d    %5d %5d %5d	   %5d %5d %5d\n", TargetID,
-		TargetStatistics[TargetID].CommandAbortsRequested,
-		TargetStatistics[TargetID].CommandAbortsAttempted,
-		TargetStatistics[TargetID].CommandAbortsCompleted,
-		TargetStatistics[TargetID].BusDeviceResetsRequested,
-		TargetStatistics[TargetID].BusDeviceResetsAttempted,
-		TargetStatistics[TargetID].BusDeviceResetsCompleted,
-		TargetStatistics[TargetID].HostAdapterResetsRequested,
-		TargetStatistics[TargetID].HostAdapterResetsAttempted,
-		TargetStatistics[TargetID].HostAdapterResetsCompleted);
-    }
-  Length += sprintf(&Buffer[Length], "\nExternal Host Adapter Resets: %d\n",
-		    HostAdapter->ExternalHostAdapterResets);
-  Length += sprintf(&Buffer[Length], "Host Adapter Internal Errors: %d\n",
-		    HostAdapter->HostAdapterInternalErrors);
-  if (Length >= BusLogic_MessageBufferSize)
-    BusLogic_Error("Message Buffer length %d exceeds size %d\n",
-		   HostAdapter, Length, BusLogic_MessageBufferSize);
-  if ((Length -= Offset) <= 0) return 0;
-  if (Length >= BytesAvailable) Length = BytesAvailable;
-  memcpy(ProcBuffer, HostAdapter->MessageBuffer + Offset, Length);
-  *StartPointer = ProcBuffer;
-  return Length;
+	for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) {
+		struct BusLogic_TargetFlags *TargetFlags = &HostAdapter->TargetFlags[TargetID];
+		if (!TargetFlags->TargetExists)
+			continue;
+		Length += sprintf(&Buffer[Length], "\
+  %2d	 %5d %5d %5d    %5d %5d %5d	   %5d %5d %5d\n", TargetID, TargetStatistics[TargetID].CommandAbortsRequested, TargetStatistics[TargetID].CommandAbortsAttempted, TargetStatistics[TargetID].CommandAbortsCompleted, TargetStatistics[TargetID].BusDeviceResetsRequested, TargetStatistics[TargetID].BusDeviceResetsAttempted, TargetStatistics[TargetID].BusDeviceResetsCompleted, TargetStatistics[TargetID].HostAdapterResetsRequested, TargetStatistics[TargetID].HostAdapterResetsAttempted, TargetStatistics[TargetID].HostAdapterResetsCompleted);
+	}
+	Length += sprintf(&Buffer[Length], "\nExternal Host Adapter Resets: %d\n", HostAdapter->ExternalHostAdapterResets);
+	Length += sprintf(&Buffer[Length], "Host Adapter Internal Errors: %d\n", HostAdapter->HostAdapterInternalErrors);
+	if (Length >= BusLogic_MessageBufferSize)
+		BusLogic_Error("Message Buffer length %d exceeds size %d\n", HostAdapter, Length, BusLogic_MessageBufferSize);
+	if ((Length -= Offset) <= 0)
+		return 0;
+	if (Length >= BytesAvailable)
+		Length = BytesAvailable;
+	memcpy(ProcBuffer, HostAdapter->MessageBuffer + Offset, Length);
+	*StartPointer = ProcBuffer;
+	return Length;
 }
 
 
@@ -3999,52 +3304,39 @@ Target	Requested Completed  Requested Completed  Requested Completed\n\
   BusLogic_Message prints Driver Messages.
 */
 
-static void BusLogic_Message(enum BusLogic_MessageLevel MessageLevel,
-			     char *Format,
-			     struct BusLogic_HostAdapter *HostAdapter,
-			     ...)
+static void BusLogic_Message(enum BusLogic_MessageLevel MessageLevel, char *Format, struct BusLogic_HostAdapter *HostAdapter, ...)
 {
-  static char Buffer[BusLogic_LineBufferSize];
-  static boolean BeginningOfLine = true;
-  va_list Arguments;
-  int Length = 0;
-  va_start(Arguments, HostAdapter);
-  Length = vsprintf(Buffer, Format, Arguments);
-  va_end(Arguments);
-  if (MessageLevel == BusLogic_AnnounceLevel)
-    {
-      static int AnnouncementLines = 0;
-      strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength],
-	     Buffer);
-      HostAdapter->MessageBufferLength += Length;
-      if (++AnnouncementLines <= 2)
-	printk("%sscsi: %s", BusLogic_MessageLevelMap[MessageLevel], Buffer);
-    }
-  else if (MessageLevel == BusLogic_InfoLevel)
-    {
-      strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength],
-	     Buffer);
-      HostAdapter->MessageBufferLength += Length;
-      if (BeginningOfLine)
-	{
-	  if (Buffer[0] != '\n' || Length > 1)
-	    printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel],
-		   HostAdapter->HostNumber, Buffer);
-	}
-      else printk("%s", Buffer);
-    }
-  else
-    {
-      if (BeginningOfLine)
-	{
-	  if (HostAdapter != NULL && HostAdapter->HostAdapterInitialized)
-	    printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel],
-		   HostAdapter->HostNumber, Buffer);
-	  else printk("%s%s", BusLogic_MessageLevelMap[MessageLevel], Buffer);
-	}
-      else printk("%s", Buffer);
-    }
-  BeginningOfLine = (Buffer[Length-1] == '\n');
+	static char Buffer[BusLogic_LineBufferSize];
+	static boolean BeginningOfLine = true;
+	va_list Arguments;
+	int Length = 0;
+	va_start(Arguments, HostAdapter);
+	Length = vsprintf(Buffer, Format, Arguments);
+	va_end(Arguments);
+	if (MessageLevel == BusLogic_AnnounceLevel) {
+		static int AnnouncementLines = 0;
+		strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength], Buffer);
+		HostAdapter->MessageBufferLength += Length;
+		if (++AnnouncementLines <= 2)
+			printk("%sscsi: %s", BusLogic_MessageLevelMap[MessageLevel], Buffer);
+	} else if (MessageLevel == BusLogic_InfoLevel) {
+		strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength], Buffer);
+		HostAdapter->MessageBufferLength += Length;
+		if (BeginningOfLine) {
+			if (Buffer[0] != '\n' || Length > 1)
+				printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel], HostAdapter->HostNumber, Buffer);
+		} else
+			printk("%s", Buffer);
+	} else {
+		if (BeginningOfLine) {
+			if (HostAdapter != NULL && HostAdapter->HostAdapterInitialized)
+				printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel], HostAdapter->HostNumber, Buffer);
+			else
+				printk("%s%s", BusLogic_MessageLevelMap[MessageLevel], Buffer);
+		} else
+			printk("%s", Buffer);
+	}
+	BeginningOfLine = (Buffer[Length - 1] == '\n');
 }
 
 
@@ -4055,19 +3347,19 @@ static void BusLogic_Message(enum BusLogic_MessageLevel MessageLevel,
 
 static boolean __init BusLogic_ParseKeyword(char **StringPointer, char *Keyword)
 {
-  char *Pointer = *StringPointer;
-  while (*Keyword != '\0')
-    {
-      char StringChar = *Pointer++;
-      char KeywordChar = *Keyword++;
-      if (StringChar >= 'A' && StringChar <= 'Z')
-	StringChar += 'a' - 'Z';
-      if (KeywordChar >= 'A' && KeywordChar <= 'Z')
-	KeywordChar += 'a' - 'Z';
-      if (StringChar != KeywordChar) return false;
-    }
-  *StringPointer = Pointer;
-  return true;
+	char *Pointer = *StringPointer;
+	while (*Keyword != '\0') {
+		char StringChar = *Pointer++;
+		char KeywordChar = *Keyword++;
+		if (StringChar >= 'A' && StringChar <= 'Z')
+			StringChar += 'a' - 'Z';
+		if (KeywordChar >= 'A' && KeywordChar <= 'Z')
+			KeywordChar += 'a' - 'Z';
+		if (StringChar != KeywordChar)
+			return false;
+	}
+	*StringPointer = Pointer;
+	return true;
 }
 
 
@@ -4090,225 +3382,165 @@ static boolean __init BusLogic_ParseKeyword(char **StringPointer, char *Keyword)
 
 static int __init BusLogic_ParseDriverOptions(char *OptionsString)
 {
-  while (true)
-    {
-      struct BusLogic_DriverOptions *DriverOptions =
-	&BusLogic_DriverOptions[BusLogic_DriverOptionsCount++];
-      int TargetID;
-      memset(DriverOptions, 0, sizeof(struct BusLogic_DriverOptions));
-      while (*OptionsString != '\0' && *OptionsString != ';')
-	{
-	  /* Probing Options. */
-	  if (BusLogic_ParseKeyword(&OptionsString, "IO:"))
-	    {
-	      unsigned long IO_Address =
-		simple_strtoul(OptionsString, &OptionsString, 0);
-	      BusLogic_ProbeOptions.LimitedProbeISA = true;
-	      switch (IO_Address)
-		{
-		case 0x330:
-		  BusLogic_ProbeOptions.Probe330 = true;
-		  break;
-		case 0x334:
-		  BusLogic_ProbeOptions.Probe334 = true;
-		  break;
-		case 0x230:
-		  BusLogic_ProbeOptions.Probe230 = true;
-		  break;
-		case 0x234:
-		  BusLogic_ProbeOptions.Probe234 = true;
-		  break;
-		case 0x130:
-		  BusLogic_ProbeOptions.Probe130 = true;
-		  break;
-		case 0x134:
-		  BusLogic_ProbeOptions.Probe134 = true;
-		  break;
-		default:
-		  BusLogic_Error("BusLogic: Invalid Driver Options "
-				 "(invalid I/O Address 0x%X)\n",
-				 NULL, IO_Address);
-		  return 0;
-		}
-	    }
-	  else if (BusLogic_ParseKeyword(&OptionsString, "NoProbeISA"))
-	    BusLogic_ProbeOptions.NoProbeISA = true;
-	  else if (BusLogic_ParseKeyword(&OptionsString, "NoProbePCI"))
-	    BusLogic_ProbeOptions.NoProbePCI = true;
-	  else if (BusLogic_ParseKeyword(&OptionsString, "NoProbe"))
-	    BusLogic_ProbeOptions.NoProbe = true;
-	  else if (BusLogic_ParseKeyword(&OptionsString, "NoSortPCI"))
-	    BusLogic_ProbeOptions.NoSortPCI = true;
-	  else if (BusLogic_ParseKeyword(&OptionsString, "MultiMasterFirst"))
-	    BusLogic_ProbeOptions.MultiMasterFirst = true;
-	  else if (BusLogic_ParseKeyword(&OptionsString, "FlashPointFirst"))
-	    BusLogic_ProbeOptions.FlashPointFirst = true;
-	  /* Tagged Queuing Options. */
-	  else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:[") ||
-		   BusLogic_ParseKeyword(&OptionsString, "QD:["))
-	    {
-	      for (TargetID = 0;
-		   TargetID < BusLogic_MaxTargetDevices;
-		   TargetID++)
-		{
-		  unsigned short QueueDepth =
-		    simple_strtoul(OptionsString, &OptionsString, 0);
-		  if (QueueDepth > BusLogic_MaxTaggedQueueDepth)
-		    {
-		      BusLogic_Error("BusLogic: Invalid Driver Options "
-				     "(invalid Queue Depth %d)\n",
-				     NULL, QueueDepth);
-		      return 0;
-		    }
-		  DriverOptions->QueueDepth[TargetID] = QueueDepth;
-		  if (*OptionsString == ',')
-		    OptionsString++;
-		  else if (*OptionsString == ']')
-		    break;
-		  else
-		    {
-		      BusLogic_Error("BusLogic: Invalid Driver Options "
-				     "(',' or ']' expected at '%s')\n",
-				     NULL, OptionsString);
-		      return 0;
-		    }
-		}
-	      if (*OptionsString != ']')
-		{
-		  BusLogic_Error("BusLogic: Invalid Driver Options "
-				 "(']' expected at '%s')\n",
-				 NULL, OptionsString);
-		  return 0;
-		}
-	      else OptionsString++;
-	    }
-	  else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:") ||
-		   BusLogic_ParseKeyword(&OptionsString, "QD:"))
-	    {
-	      unsigned short QueueDepth =
-		simple_strtoul(OptionsString, &OptionsString, 0);
-	      if (QueueDepth == 0 || QueueDepth > BusLogic_MaxTaggedQueueDepth)
-		{
-		  BusLogic_Error("BusLogic: Invalid Driver Options "
-				 "(invalid Queue Depth %d)\n",
-				 NULL, QueueDepth);
-		  return 0;
+	while (true) {
+		struct BusLogic_DriverOptions *DriverOptions = &BusLogic_DriverOptions[BusLogic_DriverOptionsCount++];
+		int TargetID;
+		memset(DriverOptions, 0, sizeof(struct BusLogic_DriverOptions));
+		while (*OptionsString != '\0' && *OptionsString != ';') {
+			/* Probing Options. */
+			if (BusLogic_ParseKeyword(&OptionsString, "IO:")) {
+				unsigned long IO_Address = simple_strtoul(OptionsString, &OptionsString, 0);
+				BusLogic_ProbeOptions.LimitedProbeISA = true;
+				switch (IO_Address) {
+				case 0x330:
+					BusLogic_ProbeOptions.Probe330 = true;
+					break;
+				case 0x334:
+					BusLogic_ProbeOptions.Probe334 = true;
+					break;
+				case 0x230:
+					BusLogic_ProbeOptions.Probe230 = true;
+					break;
+				case 0x234:
+					BusLogic_ProbeOptions.Probe234 = true;
+					break;
+				case 0x130:
+					BusLogic_ProbeOptions.Probe130 = true;
+					break;
+				case 0x134:
+					BusLogic_ProbeOptions.Probe134 = true;
+					break;
+				default:
+					BusLogic_Error("BusLogic: Invalid Driver Options " "(invalid I/O Address 0x%X)\n", NULL, IO_Address);
+					return 0;
+				}
+			} else if (BusLogic_ParseKeyword(&OptionsString, "NoProbeISA"))
+				BusLogic_ProbeOptions.NoProbeISA = true;
+			else if (BusLogic_ParseKeyword(&OptionsString, "NoProbePCI"))
+				BusLogic_ProbeOptions.NoProbePCI = true;
+			else if (BusLogic_ParseKeyword(&OptionsString, "NoProbe"))
+				BusLogic_ProbeOptions.NoProbe = true;
+			else if (BusLogic_ParseKeyword(&OptionsString, "NoSortPCI"))
+				BusLogic_ProbeOptions.NoSortPCI = true;
+			else if (BusLogic_ParseKeyword(&OptionsString, "MultiMasterFirst"))
+				BusLogic_ProbeOptions.MultiMasterFirst = true;
+			else if (BusLogic_ParseKeyword(&OptionsString, "FlashPointFirst"))
+				BusLogic_ProbeOptions.FlashPointFirst = true;
+			/* Tagged Queuing Options. */
+			else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:[") || BusLogic_ParseKeyword(&OptionsString, "QD:[")) {
+				for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++) {
+					unsigned short QueueDepth = simple_strtoul(OptionsString, &OptionsString, 0);
+					if (QueueDepth > BusLogic_MaxTaggedQueueDepth) {
+						BusLogic_Error("BusLogic: Invalid Driver Options " "(invalid Queue Depth %d)\n", NULL, QueueDepth);
+						return 0;
+					}
+					DriverOptions->QueueDepth[TargetID] = QueueDepth;
+					if (*OptionsString == ',')
+						OptionsString++;
+					else if (*OptionsString == ']')
+						break;
+					else {
+						BusLogic_Error("BusLogic: Invalid Driver Options " "(',' or ']' expected at '%s')\n", NULL, OptionsString);
+						return 0;
+					}
+				}
+				if (*OptionsString != ']') {
+					BusLogic_Error("BusLogic: Invalid Driver Options " "(']' expected at '%s')\n", NULL, OptionsString);
+					return 0;
+				} else
+					OptionsString++;
+			} else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:") || BusLogic_ParseKeyword(&OptionsString, "QD:")) {
+				unsigned short QueueDepth = simple_strtoul(OptionsString, &OptionsString, 0);
+				if (QueueDepth == 0 || QueueDepth > BusLogic_MaxTaggedQueueDepth) {
+					BusLogic_Error("BusLogic: Invalid Driver Options " "(invalid Queue Depth %d)\n", NULL, QueueDepth);
+					return 0;
+				}
+				DriverOptions->CommonQueueDepth = QueueDepth;
+				for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
+					DriverOptions->QueueDepth[TargetID] = QueueDepth;
+			} else if (BusLogic_ParseKeyword(&OptionsString, "TaggedQueuing:") || BusLogic_ParseKeyword(&OptionsString, "TQ:")) {
+				if (BusLogic_ParseKeyword(&OptionsString, "Default")) {
+					DriverOptions->TaggedQueuingPermitted = 0x0000;
+					DriverOptions->TaggedQueuingPermittedMask = 0x0000;
+				} else if (BusLogic_ParseKeyword(&OptionsString, "Enable")) {
+					DriverOptions->TaggedQueuingPermitted = 0xFFFF;
+					DriverOptions->TaggedQueuingPermittedMask = 0xFFFF;
+				} else if (BusLogic_ParseKeyword(&OptionsString, "Disable")) {
+					DriverOptions->TaggedQueuingPermitted = 0x0000;
+					DriverOptions->TaggedQueuingPermittedMask = 0xFFFF;
+				} else {
+					unsigned short TargetBit;
+					for (TargetID = 0, TargetBit = 1; TargetID < BusLogic_MaxTargetDevices; TargetID++, TargetBit <<= 1)
+						switch (*OptionsString++) {
+						case 'Y':
+							DriverOptions->TaggedQueuingPermitted |= TargetBit;
+							DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
+							break;
+						case 'N':
+							DriverOptions->TaggedQueuingPermitted &= ~TargetBit;
+							DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
+							break;
+						case 'X':
+							break;
+						default:
+							OptionsString--;
+							TargetID = BusLogic_MaxTargetDevices;
+							break;
+						}
+				}
+			}
+			/* Miscellaneous Options. */
+			else if (BusLogic_ParseKeyword(&OptionsString, "BusSettleTime:") || BusLogic_ParseKeyword(&OptionsString, "BST:")) {
+				unsigned short BusSettleTime = simple_strtoul(OptionsString, &OptionsString, 0);
+				if (BusSettleTime > 5 * 60) {
+					BusLogic_Error("BusLogic: Invalid Driver Options " "(invalid Bus Settle Time %d)\n", NULL, BusSettleTime);
+					return 0;
+				}
+				DriverOptions->BusSettleTime = BusSettleTime;
+			} else if (BusLogic_ParseKeyword(&OptionsString, "InhibitTargetInquiry"))
+				DriverOptions->LocalOptions.InhibitTargetInquiry = true;
+			/* Debugging Options. */
+			else if (BusLogic_ParseKeyword(&OptionsString, "TraceProbe"))
+				BusLogic_GlobalOptions.TraceProbe = true;
+			else if (BusLogic_ParseKeyword(&OptionsString, "TraceHardwareReset"))
+				BusLogic_GlobalOptions.TraceHardwareReset = true;
+			else if (BusLogic_ParseKeyword(&OptionsString, "TraceConfiguration"))
+				BusLogic_GlobalOptions.TraceConfiguration = true;
+			else if (BusLogic_ParseKeyword(&OptionsString, "TraceErrors"))
+				BusLogic_GlobalOptions.TraceErrors = true;
+			else if (BusLogic_ParseKeyword(&OptionsString, "Debug")) {
+				BusLogic_GlobalOptions.TraceProbe = true;
+				BusLogic_GlobalOptions.TraceHardwareReset = true;
+				BusLogic_GlobalOptions.TraceConfiguration = true;
+				BusLogic_GlobalOptions.TraceErrors = true;
+			}
+			if (*OptionsString == ',')
+				OptionsString++;
+			else if (*OptionsString != ';' && *OptionsString != '\0') {
+				BusLogic_Error("BusLogic: Unexpected Driver Option '%s' " "ignored\n", NULL, OptionsString);
+				*OptionsString = '\0';
+			}
 		}
-	      DriverOptions->CommonQueueDepth = QueueDepth;
-	      for (TargetID = 0;
-		   TargetID < BusLogic_MaxTargetDevices;
-		   TargetID++)
-		DriverOptions->QueueDepth[TargetID] = QueueDepth;
-	    }
-	  else if (BusLogic_ParseKeyword(&OptionsString, "TaggedQueuing:") ||
-		   BusLogic_ParseKeyword(&OptionsString, "TQ:"))
-	    {
-	      if (BusLogic_ParseKeyword(&OptionsString, "Default"))
-		{
-		  DriverOptions->TaggedQueuingPermitted = 0x0000;
-		  DriverOptions->TaggedQueuingPermittedMask = 0x0000;
+		if (!(BusLogic_DriverOptionsCount == 0 || BusLogic_ProbeInfoCount == 0 || BusLogic_DriverOptionsCount == BusLogic_ProbeInfoCount)) {
+			BusLogic_Error("BusLogic: Invalid Driver Options " "(all or no I/O Addresses must be specified)\n", NULL);
+			return 0;
 		}
-	      else if (BusLogic_ParseKeyword(&OptionsString, "Enable"))
-		{
-		  DriverOptions->TaggedQueuingPermitted = 0xFFFF;
-		  DriverOptions->TaggedQueuingPermittedMask = 0xFFFF;
-		}
-	      else if (BusLogic_ParseKeyword(&OptionsString, "Disable"))
-		{
-		  DriverOptions->TaggedQueuingPermitted = 0x0000;
-		  DriverOptions->TaggedQueuingPermittedMask = 0xFFFF;
-		}
-	      else
-		{
-		  unsigned short TargetBit;
-		  for (TargetID = 0, TargetBit = 1;
-		       TargetID < BusLogic_MaxTargetDevices;
-		       TargetID++, TargetBit <<= 1)
-		    switch (*OptionsString++)
-		      {
-		      case 'Y':
-			DriverOptions->TaggedQueuingPermitted |= TargetBit;
-			DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
-			break;
-		      case 'N':
-			DriverOptions->TaggedQueuingPermitted &= ~TargetBit;
-			DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
-			break;
-		      case 'X':
-			break;
-		      default:
-			OptionsString--;
-			TargetID = BusLogic_MaxTargetDevices;
-			break;
-		      }
-		}
-	    }
-	  /* Miscellaneous Options. */
-	  else if (BusLogic_ParseKeyword(&OptionsString, "BusSettleTime:") ||
-		   BusLogic_ParseKeyword(&OptionsString, "BST:"))
-	    {
-	      unsigned short BusSettleTime =
-		simple_strtoul(OptionsString, &OptionsString, 0);
-	      if (BusSettleTime > 5 * 60)
-		{
-		  BusLogic_Error("BusLogic: Invalid Driver Options "
-				 "(invalid Bus Settle Time %d)\n",
-				 NULL, BusSettleTime);
-		  return 0;
-		}
-	      DriverOptions->BusSettleTime = BusSettleTime;
-	    }
-	  else if (BusLogic_ParseKeyword(&OptionsString,
-					 "InhibitTargetInquiry"))
-	    DriverOptions->LocalOptions.InhibitTargetInquiry = true;
-	  /* Debugging Options. */
-	  else if (BusLogic_ParseKeyword(&OptionsString, "TraceProbe"))
-	      BusLogic_GlobalOptions.TraceProbe = true;
-	  else if (BusLogic_ParseKeyword(&OptionsString, "TraceHardwareReset"))
-	      BusLogic_GlobalOptions.TraceHardwareReset = true;
-	  else if (BusLogic_ParseKeyword(&OptionsString, "TraceConfiguration"))
-	      BusLogic_GlobalOptions.TraceConfiguration = true;
-	  else if (BusLogic_ParseKeyword(&OptionsString, "TraceErrors"))
-	      BusLogic_GlobalOptions.TraceErrors = true;
-	  else if (BusLogic_ParseKeyword(&OptionsString, "Debug"))
-	    {
-	      BusLogic_GlobalOptions.TraceProbe = true;
-	      BusLogic_GlobalOptions.TraceHardwareReset = true;
-	      BusLogic_GlobalOptions.TraceConfiguration = true;
-	      BusLogic_GlobalOptions.TraceErrors = true;
-	    }
-	  if (*OptionsString == ',')
-	    OptionsString++;
-	  else if (*OptionsString != ';' && *OptionsString != '\0')
-	    {
-	      BusLogic_Error("BusLogic: Unexpected Driver Option '%s' "
-			     "ignored\n", NULL, OptionsString);
-	      *OptionsString = '\0';
-	    }
-	}
-      if (!(BusLogic_DriverOptionsCount == 0 ||
-	    BusLogic_ProbeInfoCount == 0 ||
-	    BusLogic_DriverOptionsCount == BusLogic_ProbeInfoCount))
-	{
-	  BusLogic_Error("BusLogic: Invalid Driver Options "
-			 "(all or no I/O Addresses must be specified)\n", NULL);
-	  return 0;
-	}
-      /*
-	Tagged Queuing is disabled when the Queue Depth is 1 since queuing
-	multiple commands is not possible.
-      */
-      for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
-	if (DriverOptions->QueueDepth[TargetID] == 1)
-	  {
-	    unsigned short TargetBit = 1 << TargetID;
-	    DriverOptions->TaggedQueuingPermitted &= ~TargetBit;
-	    DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
-	  }
-      if (*OptionsString == ';') OptionsString++;
-      if (*OptionsString == '\0') return 0;
-    }
-    return 1;
+		/*
+		   Tagged Queuing is disabled when the Queue Depth is 1 since queuing
+		   multiple commands is not possible.
+		 */
+		for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
+			if (DriverOptions->QueueDepth[TargetID] == 1) {
+				unsigned short TargetBit = 1 << TargetID;
+				DriverOptions->TaggedQueuingPermitted &= ~TargetBit;
+				DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
+			}
+		if (*OptionsString == ';')
+			OptionsString++;
+		if (*OptionsString == '\0')
+			return 0;
+	}
+	return 1;
 }
 
 /*
@@ -4316,21 +3548,21 @@ static int __init BusLogic_ParseDriverOptions(char *OptionsString)
 */
 
 static struct scsi_host_template driver_template = {
-	.module			= THIS_MODULE,
-	.proc_name		= "BusLogic",
-	.proc_info		= BusLogic_ProcDirectoryInfo,
-	.name			= "BusLogic",
-	.info			= BusLogic_DriverInfo,
-	.queuecommand		= BusLogic_QueueCommand,
-	.slave_configure	= BusLogic_SlaveConfigure,
-	.bios_param		= BusLogic_BIOSDiskParameters,
-	.eh_host_reset_handler	= BusLogic_host_reset,
+	.module = THIS_MODULE,
+	.proc_name = "BusLogic",
+	.proc_info = BusLogic_ProcDirectoryInfo,
+	.name = "BusLogic",
+	.info = BusLogic_DriverInfo,
+	.queuecommand = BusLogic_QueueCommand,
+	.slave_configure = BusLogic_SlaveConfigure,
+	.bios_param = BusLogic_BIOSDiskParameters,
+	.eh_host_reset_handler = BusLogic_host_reset,
 #if 0
-	.eh_abort_handler	= BusLogic_AbortCommand,
+	.eh_abort_handler = BusLogic_AbortCommand,
 #endif
-	.unchecked_isa_dma	= 1,
-	.max_sectors		= 128,
-	.use_clustering		= ENABLE_CLUSTERING,
+	.unchecked_isa_dma = 1,
+	.max_sectors = 128,
+	.use_clustering = ENABLE_CLUSTERING,
 };
 
 /*
@@ -4341,11 +3573,10 @@ static int __init BusLogic_Setup(char *str)
 {
 	int ints[3];
 
-	(void)get_options(str, ARRAY_SIZE(ints), ints);
+	(void) get_options(str, ARRAY_SIZE(ints), ints);
 
 	if (ints[0] != 0) {
-		BusLogic_Error("BusLogic: Obsolete Command Line Entry "
-				"Format Ignored\n", NULL);
+		BusLogic_Error("BusLogic: Obsolete Command Line Entry " "Format Ignored\n", NULL);
 		return 0;
 	}
 	if (str == NULL || *str == '\0')
@@ -4357,13 +3588,14 @@ static int __init BusLogic_Setup(char *str)
  * Initialization function
  */
 
-static int __init BusLogic_init(void) {
+static int __init BusLogic_init(void)
+{
 
 #ifdef MODULE
 	if (BusLogic)
 		BusLogic_Setup(BusLogic);
 #endif
-	 
+
 	return BusLogic_DetectHostAdapter(&driver_template) ? 0 : -ENODEV;
 }
 
@@ -4374,14 +3606,12 @@ static int __init BusLogic_init(void) {
 static void __exit BusLogic_exit(void)
 {
 	struct BusLogic_HostAdapter *HostAdapter;
-	for (HostAdapter = BusLogic_FirstRegisteredHostAdapter;
-		HostAdapter != NULL; HostAdapter = HostAdapter->Next) {
+	for (HostAdapter = BusLogic_FirstRegisteredHostAdapter; HostAdapter != NULL; HostAdapter = HostAdapter->Next) {
 		struct Scsi_Host *host = HostAdapter->SCSI_Host;
 		scsi_remove_host(host);
 
 	}
-	for (HostAdapter = BusLogic_FirstRegisteredHostAdapter;
-		HostAdapter != NULL; HostAdapter = HostAdapter->Next) {
+	for (HostAdapter = BusLogic_FirstRegisteredHostAdapter; HostAdapter != NULL; HostAdapter = HostAdapter->Next) {
 		struct Scsi_Host *host = HostAdapter->SCSI_Host;
 		BusLogic_ReleaseHostAdapter(host);
 	}
diff --git a/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h
index 2dd778f57..facbce6da 100644
--- a/drivers/scsi/BusLogic.h
+++ b/drivers/scsi/BusLogic.h
@@ -128,17 +128,15 @@
   Define the Driver Message Levels.
 */
 
-enum BusLogic_MessageLevel
-{
-  BusLogic_AnnounceLevel =			0,
-  BusLogic_InfoLevel =				1,
-  BusLogic_NoticeLevel =			2,
-  BusLogic_WarningLevel =			3,
-  BusLogic_ErrorLevel =				4
+enum BusLogic_MessageLevel {
+	BusLogic_AnnounceLevel = 0,
+	BusLogic_InfoLevel = 1,
+	BusLogic_NoticeLevel = 2,
+	BusLogic_WarningLevel = 3,
+	BusLogic_ErrorLevel = 4
 };
 
-static char *BusLogic_MessageLevelMap[] =
-    { KERN_NOTICE, KERN_NOTICE, KERN_NOTICE, KERN_WARNING, KERN_ERR };
+static char *BusLogic_MessageLevelMap[] = { KERN_NOTICE, KERN_NOTICE, KERN_NOTICE, KERN_WARNING, KERN_ERR };
 
 
 /*
@@ -166,17 +164,15 @@ static char *BusLogic_MessageLevelMap[] =
   of I/O Addresses required by each type.
 */
 
-enum BusLogic_HostAdapterType
-{
-  BusLogic_MultiMaster =			1,
-  BusLogic_FlashPoint =				2
+enum BusLogic_HostAdapterType {
+	BusLogic_MultiMaster = 1,
+	BusLogic_FlashPoint = 2
 } PACKED;
 
 #define BusLogic_MultiMasterAddressCount	4
 #define BusLogic_FlashPointAddressCount		256
 
-static int BusLogic_HostAdapterAddressCount[3] =
-    { 0, BusLogic_MultiMasterAddressCount, BusLogic_FlashPointAddressCount };
+static int BusLogic_HostAdapterAddressCount[3] = { 0, BusLogic_MultiMasterAddressCount, BusLogic_FlashPointAddressCount };
 
 
 /*
@@ -206,39 +202,35 @@ static int BusLogic_HostAdapterAddressCount[3] =
   Define the possible Host Adapter Bus Types.
 */
 
-enum BusLogic_HostAdapterBusType
-{
-  BusLogic_Unknown_Bus =			0,
-  BusLogic_ISA_Bus =				1,
-  BusLogic_EISA_Bus =				2,
-  BusLogic_PCI_Bus =				3,
-  BusLogic_VESA_Bus =				4,
-  BusLogic_MCA_Bus =				5
+enum BusLogic_HostAdapterBusType {
+	BusLogic_Unknown_Bus = 0,
+	BusLogic_ISA_Bus = 1,
+	BusLogic_EISA_Bus = 2,
+	BusLogic_PCI_Bus = 3,
+	BusLogic_VESA_Bus = 4,
+	BusLogic_MCA_Bus = 5
 } PACKED;
 
-static char *BusLogic_HostAdapterBusNames[] =
-    { "Unknown", "ISA", "EISA", "PCI", "VESA", "MCA" };
+static char *BusLogic_HostAdapterBusNames[] = { "Unknown", "ISA", "EISA", "PCI", "VESA", "MCA" };
 
-static enum BusLogic_HostAdapterBusType BusLogic_HostAdapterBusTypes[] =
-{
-  BusLogic_VESA_Bus,				/* BT-4xx */
-  BusLogic_ISA_Bus,				/* BT-5xx */
-  BusLogic_MCA_Bus,				/* BT-6xx */
-  BusLogic_EISA_Bus,				/* BT-7xx */
-  BusLogic_Unknown_Bus,				/* BT-8xx */
-  BusLogic_PCI_Bus				/* BT-9xx */
+static enum BusLogic_HostAdapterBusType BusLogic_HostAdapterBusTypes[] = {
+	BusLogic_VESA_Bus,	/* BT-4xx */
+	BusLogic_ISA_Bus,	/* BT-5xx */
+	BusLogic_MCA_Bus,	/* BT-6xx */
+	BusLogic_EISA_Bus,	/* BT-7xx */
+	BusLogic_Unknown_Bus,	/* BT-8xx */
+	BusLogic_PCI_Bus	/* BT-9xx */
 };
 
 /*
   Define the possible Host Adapter BIOS Disk Geometry Translations.
 */
 
-enum BusLogic_BIOS_DiskGeometryTranslation
-{
-  BusLogic_BIOS_Disk_Not_Installed =		0,
-  BusLogic_BIOS_Disk_Installed_64x32 =		1,
-  BusLogic_BIOS_Disk_Installed_128x32 =		2,
-  BusLogic_BIOS_Disk_Installed_255x63 =		3
+enum BusLogic_BIOS_DiskGeometryTranslation {
+	BusLogic_BIOS_Disk_Not_Installed = 0,
+	BusLogic_BIOS_Disk_Installed_64x32 = 1,
+	BusLogic_BIOS_Disk_Installed_128x32 = 2,
+	BusLogic_BIOS_Disk_Installed_255x63 = 3
 } PACKED;
 
 
@@ -247,18 +239,17 @@ enum BusLogic_BIOS_DiskGeometryTranslation
 */
 
 typedef enum {
-  false,
-  true
+	false,
+	true
 } PACKED boolean;
 
 /*
   Define a 10^18 Statistics Byte Counter data type.
 */
 
-struct BusLogic_ByteCounter
-{
-  unsigned int Units;
-  unsigned int Billions;
+struct BusLogic_ByteCounter {
+	unsigned int Units;
+	unsigned int Billions;
 };
 
 
@@ -266,58 +257,54 @@ struct BusLogic_ByteCounter
   Define the structure for I/O Address and Bus Probing Information.
 */
 
-struct BusLogic_ProbeInfo
-{
-  enum BusLogic_HostAdapterType HostAdapterType;
-  enum BusLogic_HostAdapterBusType HostAdapterBusType;
-  unsigned long IO_Address;
-  unsigned long PCI_Address;
-  struct pci_dev *PCI_Device;
-  unsigned char Bus;
-  unsigned char Device;
-  unsigned char IRQ_Channel;
+struct BusLogic_ProbeInfo {
+	enum BusLogic_HostAdapterType HostAdapterType;
+	enum BusLogic_HostAdapterBusType HostAdapterBusType;
+	unsigned long IO_Address;
+	unsigned long PCI_Address;
+	struct pci_dev *PCI_Device;
+	unsigned char Bus;
+	unsigned char Device;
+	unsigned char IRQ_Channel;
 };
 
 /*
   Define the Probe Options.
 */
 
-struct BusLogic_ProbeOptions
-{
-  boolean NoProbe:1;					/* Bit 0 */
-  boolean NoProbeISA:1;					/* Bit 1 */
-  boolean NoProbePCI:1;					/* Bit 2 */
-  boolean NoSortPCI:1;					/* Bit 3 */
-  boolean MultiMasterFirst:1;				/* Bit 4 */
-  boolean FlashPointFirst:1;				/* Bit 5 */
-  boolean LimitedProbeISA:1;				/* Bit 6 */
-  boolean Probe330:1;					/* Bit 7 */
-  boolean Probe334:1;					/* Bit 8 */
-  boolean Probe230:1;					/* Bit 9 */
-  boolean Probe234:1;					/* Bit 10 */
-  boolean Probe130:1;					/* Bit 11 */
-  boolean Probe134:1;					/* Bit 12 */
+struct BusLogic_ProbeOptions {
+	boolean NoProbe:1;	/* Bit 0 */
+	boolean NoProbeISA:1;	/* Bit 1 */
+	boolean NoProbePCI:1;	/* Bit 2 */
+	boolean NoSortPCI:1;	/* Bit 3 */
+	boolean MultiMasterFirst:1;	/* Bit 4 */
+	boolean FlashPointFirst:1;	/* Bit 5 */
+	boolean LimitedProbeISA:1;	/* Bit 6 */
+	boolean Probe330:1;	/* Bit 7 */
+	boolean Probe334:1;	/* Bit 8 */
+	boolean Probe230:1;	/* Bit 9 */
+	boolean Probe234:1;	/* Bit 10 */
+	boolean Probe130:1;	/* Bit 11 */
+	boolean Probe134:1;	/* Bit 12 */
 };
 
 /*
   Define the Global Options.
 */
 
-struct BusLogic_GlobalOptions
-{
-  boolean TraceProbe:1;					/* Bit 0 */
-  boolean TraceHardwareReset:1;				/* Bit 1 */
-  boolean TraceConfiguration:1;				/* Bit 2 */
-  boolean TraceErrors:1;				/* Bit 3 */
+struct BusLogic_GlobalOptions {
+	boolean TraceProbe:1;	/* Bit 0 */
+	boolean TraceHardwareReset:1;	/* Bit 1 */
+	boolean TraceConfiguration:1;	/* Bit 2 */
+	boolean TraceErrors:1;	/* Bit 3 */
 };
 
 /*
   Define the Local Options.
 */
 
-struct BusLogic_LocalOptions
-{
-  boolean InhibitTargetInquiry:1;			/* Bit 0 */
+struct BusLogic_LocalOptions {
+	boolean InhibitTargetInquiry:1;	/* Bit 0 */
 };
 
 /*
@@ -335,198 +322,188 @@ struct BusLogic_LocalOptions
   Define the structure of the write-only Control Register.
 */
 
-union BusLogic_ControlRegister
-{
-  unsigned char All;
-  struct {
-    unsigned char :4;					/* Bits 0-3 */
-    boolean SCSIBusReset:1;				/* Bit 4 */
-    boolean InterruptReset:1;				/* Bit 5 */
-    boolean SoftReset:1;				/* Bit 6 */
-    boolean HardReset:1;				/* Bit 7 */
-  } cr;
+union BusLogic_ControlRegister {
+	unsigned char All;
+	struct {
+		unsigned char:4;	/* Bits 0-3 */
+		boolean SCSIBusReset:1;	/* Bit 4 */
+		boolean InterruptReset:1;	/* Bit 5 */
+		boolean SoftReset:1;	/* Bit 6 */
+		boolean HardReset:1;	/* Bit 7 */
+	} cr;
 };
 
 /*
   Define the structure of the read-only Status Register.
 */
 
-union BusLogic_StatusRegister
-{
-  unsigned char All;
-  struct {
-    boolean CommandInvalid:1;				/* Bit 0 */
-    boolean Reserved:1;					/* Bit 1 */
-    boolean DataInRegisterReady:1;			/* Bit 2 */
-    boolean CommandParameterRegisterBusy:1;		/* Bit 3 */
-    boolean HostAdapterReady:1;				/* Bit 4 */
-    boolean InitializationRequired:1;			/* Bit 5 */
-    boolean DiagnosticFailure:1;			/* Bit 6 */
-    boolean DiagnosticActive:1;				/* Bit 7 */
-  } sr;
+union BusLogic_StatusRegister {
+	unsigned char All;
+	struct {
+		boolean CommandInvalid:1;	/* Bit 0 */
+		boolean Reserved:1;	/* Bit 1 */
+		boolean DataInRegisterReady:1;	/* Bit 2 */
+		boolean CommandParameterRegisterBusy:1;	/* Bit 3 */
+		boolean HostAdapterReady:1;	/* Bit 4 */
+		boolean InitializationRequired:1;	/* Bit 5 */
+		boolean DiagnosticFailure:1;	/* Bit 6 */
+		boolean DiagnosticActive:1;	/* Bit 7 */
+	} sr;
 };
 
 /*
   Define the structure of the read-only Interrupt Register.
 */
 
-union BusLogic_InterruptRegister
-{
-  unsigned char All;
-  struct {
-    boolean IncomingMailboxLoaded:1;			/* Bit 0 */
-    boolean OutgoingMailboxAvailable:1;			/* Bit 1 */
-    boolean CommandComplete:1;				/* Bit 2 */
-    boolean ExternalBusReset:1;				/* Bit 3 */
-    unsigned char Reserved:3;				/* Bits 4-6 */
-    boolean InterruptValid:1;				/* Bit 7 */
-  } ir;
+union BusLogic_InterruptRegister {
+	unsigned char All;
+	struct {
+		boolean IncomingMailboxLoaded:1;	/* Bit 0 */
+		boolean OutgoingMailboxAvailable:1;	/* Bit 1 */
+		boolean CommandComplete:1;	/* Bit 2 */
+		boolean ExternalBusReset:1;	/* Bit 3 */
+		unsigned char Reserved:3;	/* Bits 4-6 */
+		boolean InterruptValid:1;	/* Bit 7 */
+	} ir;
 };
 
 /*
   Define the structure of the read-only Geometry Register.
 */
 
-union BusLogic_GeometryRegister
-{
-  unsigned char All;
-  struct {
-    enum BusLogic_BIOS_DiskGeometryTranslation Drive0Geometry:2;/* Bits 0-1 */
-    enum BusLogic_BIOS_DiskGeometryTranslation Drive1Geometry:2;/* Bits 2-3 */
-    unsigned char :3;						/* Bits 4-6 */
-    boolean ExtendedTranslationEnabled:1;			/* Bit 7 */
-  } gr;
+union BusLogic_GeometryRegister {
+	unsigned char All;
+	struct {
+		enum BusLogic_BIOS_DiskGeometryTranslation Drive0Geometry:2;	/* Bits 0-1 */
+		enum BusLogic_BIOS_DiskGeometryTranslation Drive1Geometry:2;	/* Bits 2-3 */
+		unsigned char:3;	/* Bits 4-6 */
+		boolean ExtendedTranslationEnabled:1;	/* Bit 7 */
+	} gr;
 };
 
 /*
   Define the BusLogic SCSI Host Adapter Command Register Operation Codes.
 */
 
-enum BusLogic_OperationCode
-{
-  BusLogic_TestCommandCompleteInterrupt =		0x00,
-  BusLogic_InitializeMailbox =				0x01,
-  BusLogic_ExecuteMailboxCommand =			0x02,
-  BusLogic_ExecuteBIOSCommand =				0x03,
-  BusLogic_InquireBoardID =				0x04,
-  BusLogic_EnableOutgoingMailboxAvailableInt =		0x05,
-  BusLogic_SetSCSISelectionTimeout =			0x06,
-  BusLogic_SetPreemptTimeOnBus =			0x07,
-  BusLogic_SetTimeOffBus =				0x08,
-  BusLogic_SetBusTransferRate =				0x09,
-  BusLogic_InquireInstalledDevicesID0to7 =		0x0A,
-  BusLogic_InquireConfiguration =			0x0B,
-  BusLogic_EnableTargetMode =				0x0C,
-  BusLogic_InquireSetupInformation =			0x0D,
-  BusLogic_WriteAdapterLocalRAM =			0x1A,
-  BusLogic_ReadAdapterLocalRAM =			0x1B,
-  BusLogic_WriteBusMasterChipFIFO =			0x1C,
-  BusLogic_ReadBusMasterChipFIFO =			0x1D,
-  BusLogic_EchoCommandData =				0x1F,
-  BusLogic_HostAdapterDiagnostic =			0x20,
-  BusLogic_SetAdapterOptions =				0x21,
-  BusLogic_InquireInstalledDevicesID8to15 =		0x23,
-  BusLogic_InquireTargetDevices =			0x24,
-  BusLogic_DisableHostAdapterInterrupt =		0x25,
-  BusLogic_InitializeExtendedMailbox =			0x81,
-  BusLogic_ExecuteSCSICommand =				0x83,
-  BusLogic_InquireFirmwareVersion3rdDigit =		0x84,
-  BusLogic_InquireFirmwareVersionLetter =		0x85,
-  BusLogic_InquirePCIHostAdapterInformation =		0x86,
-  BusLogic_InquireHostAdapterModelNumber =		0x8B,
-  BusLogic_InquireSynchronousPeriod =			0x8C,
-  BusLogic_InquireExtendedSetupInformation =		0x8D,
-  BusLogic_EnableStrictRoundRobinMode =			0x8F,
-  BusLogic_StoreHostAdapterLocalRAM =			0x90,
-  BusLogic_FetchHostAdapterLocalRAM =			0x91,
-  BusLogic_StoreLocalDataInEEPROM =			0x92,
-  BusLogic_UploadAutoSCSICode =				0x94,
-  BusLogic_ModifyIOAddress =				0x95,
-  BusLogic_SetCCBFormat =				0x96,
-  BusLogic_WriteInquiryBuffer =				0x9A,
-  BusLogic_ReadInquiryBuffer =				0x9B,
-  BusLogic_FlashROMUploadDownload =			0xA7,
-  BusLogic_ReadSCAMData =				0xA8,
-  BusLogic_WriteSCAMData =				0xA9
+enum BusLogic_OperationCode {
+	BusLogic_TestCommandCompleteInterrupt = 0x00,
+	BusLogic_InitializeMailbox = 0x01,
+	BusLogic_ExecuteMailboxCommand = 0x02,
+	BusLogic_ExecuteBIOSCommand = 0x03,
+	BusLogic_InquireBoardID = 0x04,
+	BusLogic_EnableOutgoingMailboxAvailableInt = 0x05,
+	BusLogic_SetSCSISelectionTimeout = 0x06,
+	BusLogic_SetPreemptTimeOnBus = 0x07,
+	BusLogic_SetTimeOffBus = 0x08,
+	BusLogic_SetBusTransferRate = 0x09,
+	BusLogic_InquireInstalledDevicesID0to7 = 0x0A,
+	BusLogic_InquireConfiguration = 0x0B,
+	BusLogic_EnableTargetMode = 0x0C,
+	BusLogic_InquireSetupInformation = 0x0D,
+	BusLogic_WriteAdapterLocalRAM = 0x1A,
+	BusLogic_ReadAdapterLocalRAM = 0x1B,
+	BusLogic_WriteBusMasterChipFIFO = 0x1C,
+	BusLogic_ReadBusMasterChipFIFO = 0x1D,
+	BusLogic_EchoCommandData = 0x1F,
+	BusLogic_HostAdapterDiagnostic = 0x20,
+	BusLogic_SetAdapterOptions = 0x21,
+	BusLogic_InquireInstalledDevicesID8to15 = 0x23,
+	BusLogic_InquireTargetDevices = 0x24,
+	BusLogic_DisableHostAdapterInterrupt = 0x25,
+	BusLogic_InitializeExtendedMailbox = 0x81,
+	BusLogic_ExecuteSCSICommand = 0x83,
+	BusLogic_InquireFirmwareVersion3rdDigit = 0x84,
+	BusLogic_InquireFirmwareVersionLetter = 0x85,
+	BusLogic_InquirePCIHostAdapterInformation = 0x86,
+	BusLogic_InquireHostAdapterModelNumber = 0x8B,
+	BusLogic_InquireSynchronousPeriod = 0x8C,
+	BusLogic_InquireExtendedSetupInformation = 0x8D,
+	BusLogic_EnableStrictRoundRobinMode = 0x8F,
+	BusLogic_StoreHostAdapterLocalRAM = 0x90,
+	BusLogic_FetchHostAdapterLocalRAM = 0x91,
+	BusLogic_StoreLocalDataInEEPROM = 0x92,
+	BusLogic_UploadAutoSCSICode = 0x94,
+	BusLogic_ModifyIOAddress = 0x95,
+	BusLogic_SetCCBFormat = 0x96,
+	BusLogic_WriteInquiryBuffer = 0x9A,
+	BusLogic_ReadInquiryBuffer = 0x9B,
+	BusLogic_FlashROMUploadDownload = 0xA7,
+	BusLogic_ReadSCAMData = 0xA8,
+	BusLogic_WriteSCAMData = 0xA9
 };
 
 /*
   Define the Inquire Board ID reply structure.
 */
 
-struct BusLogic_BoardID
-{
-  unsigned char BoardType;				/* Byte 0 */
-  unsigned char CustomFeatures;				/* Byte 1 */
-  unsigned char FirmwareVersion1stDigit;		/* Byte 2 */
-  unsigned char FirmwareVersion2ndDigit;		/* Byte 3 */
+struct BusLogic_BoardID {
+	unsigned char BoardType;	/* Byte 0 */
+	unsigned char CustomFeatures;	/* Byte 1 */
+	unsigned char FirmwareVersion1stDigit;	/* Byte 2 */
+	unsigned char FirmwareVersion2ndDigit;	/* Byte 3 */
 };
 
 /*
   Define the Inquire Configuration reply structure.
 */
 
-struct BusLogic_Configuration
-{
-  unsigned char :5;					/* Byte 0 Bits 0-4 */
-  boolean DMA_Channel5:1;				/* Byte 0 Bit 5 */
-  boolean DMA_Channel6:1;				/* Byte 0 Bit 6 */
-  boolean DMA_Channel7:1;				/* Byte 0 Bit 7 */
-  boolean IRQ_Channel9:1;				/* Byte 1 Bit 0 */
-  boolean IRQ_Channel10:1;				/* Byte 1 Bit 1 */
-  boolean IRQ_Channel11:1;				/* Byte 1 Bit 2 */
-  boolean IRQ_Channel12:1;				/* Byte 1 Bit 3 */
-  unsigned char :1;					/* Byte 1 Bit 4 */
-  boolean IRQ_Channel14:1;				/* Byte 1 Bit 5 */
-  boolean IRQ_Channel15:1;				/* Byte 1 Bit 6 */
-  unsigned char :1;					/* Byte 1 Bit 7 */
-  unsigned char HostAdapterID:4;			/* Byte 2 Bits 0-3 */
-  unsigned char :4;					/* Byte 2 Bits 4-7 */
+struct BusLogic_Configuration {
+	unsigned char:5;	/* Byte 0 Bits 0-4 */
+	boolean DMA_Channel5:1;	/* Byte 0 Bit 5 */
+	boolean DMA_Channel6:1;	/* Byte 0 Bit 6 */
+	boolean DMA_Channel7:1;	/* Byte 0 Bit 7 */
+	boolean IRQ_Channel9:1;	/* Byte 1 Bit 0 */
+	boolean IRQ_Channel10:1;	/* Byte 1 Bit 1 */
+	boolean IRQ_Channel11:1;	/* Byte 1 Bit 2 */
+	boolean IRQ_Channel12:1;	/* Byte 1 Bit 3 */
+	unsigned char:1;	/* Byte 1 Bit 4 */
+	boolean IRQ_Channel14:1;	/* Byte 1 Bit 5 */
+	boolean IRQ_Channel15:1;	/* Byte 1 Bit 6 */
+	unsigned char:1;	/* Byte 1 Bit 7 */
+	unsigned char HostAdapterID:4;	/* Byte 2 Bits 0-3 */
+	unsigned char:4;	/* Byte 2 Bits 4-7 */
 };
 
 /*
   Define the Inquire Setup Information reply structure.
 */
 
-struct BusLogic_SynchronousValue
-{
-  unsigned char Offset:4;				/* Bits 0-3 */
-  unsigned char TransferPeriod:3;			/* Bits 4-6 */
-  boolean Synchronous:1;				/* Bit 7 */
+struct BusLogic_SynchronousValue {
+	unsigned char Offset:4;	/* Bits 0-3 */
+	unsigned char TransferPeriod:3;	/* Bits 4-6 */
+	boolean Synchronous:1;	/* Bit 7 */
 };
 
-struct BusLogic_SetupInformation
-{
-  boolean SynchronousInitiationEnabled:1;		/* Byte 0 Bit 0 */
-  boolean ParityCheckingEnabled:1;			/* Byte 0 Bit 1 */
-  unsigned char :6;					/* Byte 0 Bits 2-7 */
-  unsigned char BusTransferRate;			/* Byte 1 */
-  unsigned char PreemptTimeOnBus;			/* Byte 2 */
-  unsigned char TimeOffBus;				/* Byte 3 */
-  unsigned char MailboxCount;				/* Byte 4 */
-  unsigned char MailboxAddress[3];			/* Bytes 5-7 */
-  struct BusLogic_SynchronousValue SynchronousValuesID0to7[8];/* Bytes 8-15 */
-  unsigned char DisconnectPermittedID0to7;		/* Byte 16 */
-  unsigned char Signature;				/* Byte 17 */
-  unsigned char CharacterD;				/* Byte 18 */
-  unsigned char HostBusType;				/* Byte 19 */
-  unsigned char WideTransfersPermittedID0to7;		/* Byte 20 */
-  unsigned char WideTransfersActiveID0to7;		/* Byte 21 */
-  struct BusLogic_SynchronousValue SynchronousValuesID8to15[8]; /* Bytes 22-29 */
-  unsigned char DisconnectPermittedID8to15;		/* Byte 30 */
-  unsigned char :8;					/* Byte 31 */
-  unsigned char WideTransfersPermittedID8to15;		/* Byte 32 */
-  unsigned char WideTransfersActiveID8to15;		/* Byte 33 */
+struct BusLogic_SetupInformation {
+	boolean SynchronousInitiationEnabled:1;	/* Byte 0 Bit 0 */
+	boolean ParityCheckingEnabled:1;	/* Byte 0 Bit 1 */
+	unsigned char:6;	/* Byte 0 Bits 2-7 */
+	unsigned char BusTransferRate;	/* Byte 1 */
+	unsigned char PreemptTimeOnBus;	/* Byte 2 */
+	unsigned char TimeOffBus;	/* Byte 3 */
+	unsigned char MailboxCount;	/* Byte 4 */
+	unsigned char MailboxAddress[3];	/* Bytes 5-7 */
+	struct BusLogic_SynchronousValue SynchronousValuesID0to7[8];	/* Bytes 8-15 */
+	unsigned char DisconnectPermittedID0to7;	/* Byte 16 */
+	unsigned char Signature;	/* Byte 17 */
+	unsigned char CharacterD;	/* Byte 18 */
+	unsigned char HostBusType;	/* Byte 19 */
+	unsigned char WideTransfersPermittedID0to7;	/* Byte 20 */
+	unsigned char WideTransfersActiveID0to7;	/* Byte 21 */
+	struct BusLogic_SynchronousValue SynchronousValuesID8to15[8];	/* Bytes 22-29 */
+	unsigned char DisconnectPermittedID8to15;	/* Byte 30 */
+	unsigned char:8;	/* Byte 31 */
+	unsigned char WideTransfersPermittedID8to15;	/* Byte 32 */
+	unsigned char WideTransfersActiveID8to15;	/* Byte 33 */
 };
 
 /*
   Define the Initialize Extended Mailbox request structure.
 */
 
-struct BusLogic_ExtendedMailboxRequest
-{
-  unsigned char MailboxCount;				/* Byte 0 */
-  u32 BaseMailboxAddress;				/* Bytes 1-4 */
+struct BusLogic_ExtendedMailboxRequest {
+	unsigned char MailboxCount;	/* Byte 0 */
+	u32 BaseMailboxAddress;	/* Bytes 1-4 */
 } PACKED;
 
 
@@ -536,67 +513,63 @@ struct BusLogic_ExtendedMailboxRequest
   the Modify I/O Address command.
 */
 
-enum BusLogic_ISACompatibleIOPort
-{
-  BusLogic_IO_330 =				0,
-  BusLogic_IO_334 =				1,
-  BusLogic_IO_230 =				2,
-  BusLogic_IO_234 =				3,
-  BusLogic_IO_130 =				4,
-  BusLogic_IO_134 =				5,
-  BusLogic_IO_Disable =				6,
-  BusLogic_IO_Disable2 =			7
+enum BusLogic_ISACompatibleIOPort {
+	BusLogic_IO_330 = 0,
+	BusLogic_IO_334 = 1,
+	BusLogic_IO_230 = 2,
+	BusLogic_IO_234 = 3,
+	BusLogic_IO_130 = 4,
+	BusLogic_IO_134 = 5,
+	BusLogic_IO_Disable = 6,
+	BusLogic_IO_Disable2 = 7
 } PACKED;
 
-struct BusLogic_PCIHostAdapterInformation
-{
-  enum BusLogic_ISACompatibleIOPort ISACompatibleIOPort;/* Byte 0 */
-  unsigned char PCIAssignedIRQChannel;			/* Byte 1 */
-  boolean LowByteTerminated:1;				/* Byte 2 Bit 0 */
-  boolean HighByteTerminated:1;				/* Byte 2 Bit 1 */
-  unsigned char :2;					/* Byte 2 Bits 2-3 */
-  boolean JP1:1;					/* Byte 2 Bit 4 */
-  boolean JP2:1;					/* Byte 2 Bit 5 */
-  boolean JP3:1;					/* Byte 2 Bit 6 */
-  boolean GenericInfoValid:1;				/* Byte 2 Bit 7 */
-  unsigned char :8;					/* Byte 3 */
+struct BusLogic_PCIHostAdapterInformation {
+	enum BusLogic_ISACompatibleIOPort ISACompatibleIOPort;	/* Byte 0 */
+	unsigned char PCIAssignedIRQChannel;	/* Byte 1 */
+	boolean LowByteTerminated:1;	/* Byte 2 Bit 0 */
+	boolean HighByteTerminated:1;	/* Byte 2 Bit 1 */
+	unsigned char:2;	/* Byte 2 Bits 2-3 */
+	boolean JP1:1;		/* Byte 2 Bit 4 */
+	boolean JP2:1;		/* Byte 2 Bit 5 */
+	boolean JP3:1;		/* Byte 2 Bit 6 */
+	boolean GenericInfoValid:1;	/* Byte 2 Bit 7 */
+	unsigned char:8;	/* Byte 3 */
 };
 
 /*
   Define the Inquire Extended Setup Information reply structure.
 */
 
-struct BusLogic_ExtendedSetupInformation
-{
-  unsigned char BusType;				/* Byte 0 */
-  unsigned char BIOS_Address;				/* Byte 1 */
-  unsigned short ScatterGatherLimit;			/* Bytes 2-3 */
-  unsigned char MailboxCount;				/* Byte 4 */
-  u32 BaseMailboxAddress;				/* Bytes 5-8 */
-  struct {
-           unsigned char :2;				/* Byte 9 Bits 0-1 */
-	   boolean FastOnEISA:1;			/* Byte 9 Bit 2 */
-	   unsigned char :3;				/* Byte 9 Bits 3-5 */
-	   boolean LevelSensitiveInterrupt:1;		/* Byte 9 Bit 6 */
-	   unsigned char :1;				/* Byte 9 Bit 7 */
-  } Misc;
-  unsigned char FirmwareRevision[3];			/* Bytes 10-12 */
-  boolean HostWideSCSI:1;				/* Byte 13 Bit 0 */
-  boolean HostDifferentialSCSI:1;			/* Byte 13 Bit 1 */
-  boolean HostSupportsSCAM:1;				/* Byte 13 Bit 2 */
-  boolean HostUltraSCSI:1;				/* Byte 13 Bit 3 */
-  boolean HostSmartTermination:1;			/* Byte 13 Bit 4 */
-  unsigned char :3;					/* Byte 13 Bits 5-7 */
+struct BusLogic_ExtendedSetupInformation {
+	unsigned char BusType;	/* Byte 0 */
+	unsigned char BIOS_Address;	/* Byte 1 */
+	unsigned short ScatterGatherLimit;	/* Bytes 2-3 */
+	unsigned char MailboxCount;	/* Byte 4 */
+	u32 BaseMailboxAddress;	/* Bytes 5-8 */
+	struct {
+		unsigned char:2;	/* Byte 9 Bits 0-1 */
+		boolean FastOnEISA:1;	/* Byte 9 Bit 2 */
+		unsigned char:3;	/* Byte 9 Bits 3-5 */
+		boolean LevelSensitiveInterrupt:1;	/* Byte 9 Bit 6 */
+		unsigned char:1;	/* Byte 9 Bit 7 */
+	} Misc;
+	unsigned char FirmwareRevision[3];	/* Bytes 10-12 */
+	boolean HostWideSCSI:1;	/* Byte 13 Bit 0 */
+	boolean HostDifferentialSCSI:1;	/* Byte 13 Bit 1 */
+	boolean HostSupportsSCAM:1;	/* Byte 13 Bit 2 */
+	boolean HostUltraSCSI:1;	/* Byte 13 Bit 3 */
+	boolean HostSmartTermination:1;	/* Byte 13 Bit 4 */
+	unsigned char:3;	/* Byte 13 Bits 5-7 */
 } PACKED;
 
 /*
   Define the Enable Strict Round Robin Mode request type.
 */
 
-enum BusLogic_RoundRobinModeRequest
-{
-  BusLogic_AggressiveRoundRobinMode =		0,
-  BusLogic_StrictRoundRobinMode =		1
+enum BusLogic_RoundRobinModeRequest {
+	BusLogic_AggressiveRoundRobinMode = 0,
+	BusLogic_StrictRoundRobinMode = 1
 } PACKED;
 
 
@@ -607,96 +580,93 @@ enum BusLogic_RoundRobinModeRequest
 #define BusLogic_BIOS_BaseOffset		0
 #define BusLogic_AutoSCSI_BaseOffset		64
 
-struct BusLogic_FetchHostAdapterLocalRAMRequest
-{
-  unsigned char ByteOffset;				/* Byte 0 */
-  unsigned char ByteCount;				/* Byte 1 */
+struct BusLogic_FetchHostAdapterLocalRAMRequest {
+	unsigned char ByteOffset;	/* Byte 0 */
+	unsigned char ByteCount;	/* Byte 1 */
 };
 
 /*
   Define the Host Adapter Local RAM AutoSCSI structure.
 */
 
-struct BusLogic_AutoSCSIData
-{
-  unsigned char InternalFactorySignature[2];		/* Bytes 0-1 */
-  unsigned char InformationByteCount;			/* Byte 2 */
-  unsigned char HostAdapterType[6];			/* Bytes 3-8 */
-  unsigned char :8;					/* Byte 9 */
-  boolean FloppyEnabled:1;				/* Byte 10 Bit 0 */
-  boolean FloppySecondary:1;				/* Byte 10 Bit 1 */
-  boolean LevelSensitiveInterrupt:1;			/* Byte 10 Bit 2 */
-  unsigned char :2;					/* Byte 10 Bits 3-4 */
-  unsigned char SystemRAMAreaForBIOS:3;			/* Byte 10 Bits 5-7 */
-  unsigned char DMA_Channel:7;				/* Byte 11 Bits 0-6 */
-  boolean DMA_AutoConfiguration:1;			/* Byte 11 Bit 7 */
-  unsigned char IRQ_Channel:7;				/* Byte 12 Bits 0-6 */
-  boolean IRQ_AutoConfiguration:1;			/* Byte 12 Bit 7 */
-  unsigned char DMA_TransferRate;			/* Byte 13 */
-  unsigned char SCSI_ID;				/* Byte 14 */
-  boolean LowByteTerminated:1;				/* Byte 15 Bit 0 */
-  boolean ParityCheckingEnabled:1;			/* Byte 15 Bit 1 */
-  boolean HighByteTerminated:1;				/* Byte 15 Bit 2 */
-  boolean NoisyCablingEnvironment:1;			/* Byte 15 Bit 3 */
-  boolean FastSynchronousNegotiation:1;			/* Byte 15 Bit 4 */
-  boolean BusResetEnabled:1;				/* Byte 15 Bit 5 */
-  boolean :1;						/* Byte 15 Bit 6 */
-  boolean ActiveNegationEnabled:1;			/* Byte 15 Bit 7 */
-  unsigned char BusOnDelay;				/* Byte 16 */
-  unsigned char BusOffDelay;				/* Byte 17 */
-  boolean HostAdapterBIOSEnabled:1;			/* Byte 18 Bit 0 */
-  boolean BIOSRedirectionOfINT19Enabled:1;		/* Byte 18 Bit 1 */
-  boolean ExtendedTranslationEnabled:1;			/* Byte 18 Bit 2 */
-  boolean MapRemovableAsFixedEnabled:1;			/* Byte 18 Bit 3 */
-  boolean :1;						/* Byte 18 Bit 4 */
-  boolean BIOSSupportsMoreThan2DrivesEnabled:1;		/* Byte 18 Bit 5 */
-  boolean BIOSInterruptModeEnabled:1;			/* Byte 18 Bit 6 */
-  boolean FlopticalSupportEnabled:1;			/* Byte 19 Bit 7 */
-  unsigned short DeviceEnabled;				/* Bytes 19-20 */
-  unsigned short WidePermitted;				/* Bytes 21-22 */
-  unsigned short FastPermitted;				/* Bytes 23-24 */
-  unsigned short SynchronousPermitted;			/* Bytes 25-26 */
-  unsigned short DisconnectPermitted;			/* Bytes 27-28 */
-  unsigned short SendStartUnitCommand;			/* Bytes 29-30 */
-  unsigned short IgnoreInBIOSScan;			/* Bytes 31-32 */
-  unsigned char PCIInterruptPin:2;			/* Byte 33 Bits 0-1 */
-  unsigned char HostAdapterIOPortAddress:2;		/* Byte 33 Bits 2-3 */
-  boolean StrictRoundRobinModeEnabled:1;		/* Byte 33 Bit 4 */
-  boolean VESABusSpeedGreaterThan33MHz:1;		/* Byte 33 Bit 5 */
-  boolean VESABurstWriteEnabled:1;			/* Byte 33 Bit 6 */
-  boolean VESABurstReadEnabled:1;			/* Byte 33 Bit 7 */
-  unsigned short UltraPermitted;			/* Bytes 34-35 */
-  unsigned int :32;					/* Bytes 36-39 */
-  unsigned char :8;					/* Byte 40 */
-  unsigned char AutoSCSIMaximumLUN;			/* Byte 41 */
-  boolean :1;						/* Byte 42 Bit 0 */
-  boolean SCAM_Dominant:1;				/* Byte 42 Bit 1 */
-  boolean SCAM_Enabled:1;				/* Byte 42 Bit 2 */
-  boolean SCAM_Level2:1;				/* Byte 42 Bit 3 */
-  unsigned char :4;					/* Byte 42 Bits 4-7 */
-  boolean INT13ExtensionEnabled:1;			/* Byte 43 Bit 0 */
-  boolean :1;						/* Byte 43 Bit 1 */
-  boolean CDROMBootEnabled:1;				/* Byte 43 Bit 2 */
-  unsigned char :5;					/* Byte 43 Bits 3-7 */
-  unsigned char BootTargetID:4;				/* Byte 44 Bits 0-3 */
-  unsigned char BootChannel:4;				/* Byte 44 Bits 4-7 */
-  unsigned char ForceBusDeviceScanningOrder:1;		/* Byte 45 Bit 0 */
-  unsigned char :7;					/* Byte 45 Bits 1-7 */
-  unsigned short NonTaggedToAlternateLUNPermitted;	/* Bytes 46-47 */
-  unsigned short RenegotiateSyncAfterCheckCondition;	/* Bytes 48-49 */
-  unsigned char Reserved[10];				/* Bytes 50-59 */
-  unsigned char ManufacturingDiagnostic[2];		/* Bytes 60-61 */
-  unsigned short Checksum;				/* Bytes 62-63 */
+struct BusLogic_AutoSCSIData {
+	unsigned char InternalFactorySignature[2];	/* Bytes 0-1 */
+	unsigned char InformationByteCount;	/* Byte 2 */
+	unsigned char HostAdapterType[6];	/* Bytes 3-8 */
+	unsigned char:8;	/* Byte 9 */
+	boolean FloppyEnabled:1;	/* Byte 10 Bit 0 */
+	boolean FloppySecondary:1;	/* Byte 10 Bit 1 */
+	boolean LevelSensitiveInterrupt:1;	/* Byte 10 Bit 2 */
+	unsigned char:2;	/* Byte 10 Bits 3-4 */
+	unsigned char SystemRAMAreaForBIOS:3;	/* Byte 10 Bits 5-7 */
+	unsigned char DMA_Channel:7;	/* Byte 11 Bits 0-6 */
+	boolean DMA_AutoConfiguration:1;	/* Byte 11 Bit 7 */
+	unsigned char IRQ_Channel:7;	/* Byte 12 Bits 0-6 */
+	boolean IRQ_AutoConfiguration:1;	/* Byte 12 Bit 7 */
+	unsigned char DMA_TransferRate;	/* Byte 13 */
+	unsigned char SCSI_ID;	/* Byte 14 */
+	boolean LowByteTerminated:1;	/* Byte 15 Bit 0 */
+	boolean ParityCheckingEnabled:1;	/* Byte 15 Bit 1 */
+	boolean HighByteTerminated:1;	/* Byte 15 Bit 2 */
+	boolean NoisyCablingEnvironment:1;	/* Byte 15 Bit 3 */
+	boolean FastSynchronousNegotiation:1;	/* Byte 15 Bit 4 */
+	boolean BusResetEnabled:1;	/* Byte 15 Bit 5 */
+	 boolean:1;		/* Byte 15 Bit 6 */
+	boolean ActiveNegationEnabled:1;	/* Byte 15 Bit 7 */
+	unsigned char BusOnDelay;	/* Byte 16 */
+	unsigned char BusOffDelay;	/* Byte 17 */
+	boolean HostAdapterBIOSEnabled:1;	/* Byte 18 Bit 0 */
+	boolean BIOSRedirectionOfINT19Enabled:1;	/* Byte 18 Bit 1 */
+	boolean ExtendedTranslationEnabled:1;	/* Byte 18 Bit 2 */
+	boolean MapRemovableAsFixedEnabled:1;	/* Byte 18 Bit 3 */
+	 boolean:1;		/* Byte 18 Bit 4 */
+	boolean BIOSSupportsMoreThan2DrivesEnabled:1;	/* Byte 18 Bit 5 */
+	boolean BIOSInterruptModeEnabled:1;	/* Byte 18 Bit 6 */
+	boolean FlopticalSupportEnabled:1;	/* Byte 19 Bit 7 */
+	unsigned short DeviceEnabled;	/* Bytes 19-20 */
+	unsigned short WidePermitted;	/* Bytes 21-22 */
+	unsigned short FastPermitted;	/* Bytes 23-24 */
+	unsigned short SynchronousPermitted;	/* Bytes 25-26 */
+	unsigned short DisconnectPermitted;	/* Bytes 27-28 */
+	unsigned short SendStartUnitCommand;	/* Bytes 29-30 */
+	unsigned short IgnoreInBIOSScan;	/* Bytes 31-32 */
+	unsigned char PCIInterruptPin:2;	/* Byte 33 Bits 0-1 */
+	unsigned char HostAdapterIOPortAddress:2;	/* Byte 33 Bits 2-3 */
+	boolean StrictRoundRobinModeEnabled:1;	/* Byte 33 Bit 4 */
+	boolean VESABusSpeedGreaterThan33MHz:1;	/* Byte 33 Bit 5 */
+	boolean VESABurstWriteEnabled:1;	/* Byte 33 Bit 6 */
+	boolean VESABurstReadEnabled:1;	/* Byte 33 Bit 7 */
+	unsigned short UltraPermitted;	/* Bytes 34-35 */
+	unsigned int:32;	/* Bytes 36-39 */
+	unsigned char:8;	/* Byte 40 */
+	unsigned char AutoSCSIMaximumLUN;	/* Byte 41 */
+	 boolean:1;		/* Byte 42 Bit 0 */
+	boolean SCAM_Dominant:1;	/* Byte 42 Bit 1 */
+	boolean SCAM_Enabled:1;	/* Byte 42 Bit 2 */
+	boolean SCAM_Level2:1;	/* Byte 42 Bit 3 */
+	unsigned char:4;	/* Byte 42 Bits 4-7 */
+	boolean INT13ExtensionEnabled:1;	/* Byte 43 Bit 0 */
+	 boolean:1;		/* Byte 43 Bit 1 */
+	boolean CDROMBootEnabled:1;	/* Byte 43 Bit 2 */
+	unsigned char:5;	/* Byte 43 Bits 3-7 */
+	unsigned char BootTargetID:4;	/* Byte 44 Bits 0-3 */
+	unsigned char BootChannel:4;	/* Byte 44 Bits 4-7 */
+	unsigned char ForceBusDeviceScanningOrder:1;	/* Byte 45 Bit 0 */
+	unsigned char:7;	/* Byte 45 Bits 1-7 */
+	unsigned short NonTaggedToAlternateLUNPermitted;	/* Bytes 46-47 */
+	unsigned short RenegotiateSyncAfterCheckCondition;	/* Bytes 48-49 */
+	unsigned char Reserved[10];	/* Bytes 50-59 */
+	unsigned char ManufacturingDiagnostic[2];	/* Bytes 60-61 */
+	unsigned short Checksum;	/* Bytes 62-63 */
 } PACKED;
 
 /*
   Define the Host Adapter Local RAM Auto SCSI Byte 45 structure.
 */
 
-struct BusLogic_AutoSCSIByte45
-{
-  unsigned char ForceBusDeviceScanningOrder:1;		/* Bit 0 */
-  unsigned char :7;					/* Bits 1-7 */
+struct BusLogic_AutoSCSIByte45 {
+	unsigned char ForceBusDeviceScanningOrder:1;	/* Bit 0 */
+	unsigned char:7;	/* Bits 1-7 */
 };
 
 /*
@@ -705,12 +675,11 @@ struct BusLogic_AutoSCSIByte45
 
 #define BusLogic_BIOS_DriveMapOffset		17
 
-struct BusLogic_BIOSDriveMapByte
-{
-  unsigned char TargetIDBit3:1;				/* Bit 0 */
-  unsigned char :2;					/* Bits 1-2 */
-  enum BusLogic_BIOS_DiskGeometryTranslation DiskGeometry:2; /* Bits 3-4 */
-  unsigned char TargetID:3;				/* Bits 5-7 */
+struct BusLogic_BIOSDriveMapByte {
+	unsigned char TargetIDBit3:1;	/* Bit 0 */
+	unsigned char:2;	/* Bits 1-2 */
+	enum BusLogic_BIOS_DiskGeometryTranslation DiskGeometry:2;	/* Bits 3-4 */
+	unsigned char TargetID:3;	/* Bits 5-7 */
 };
 
 /*
@@ -718,21 +687,19 @@ struct BusLogic_BIOSDriveMapByte
   necessary to support more than 8 Logical Units per Target Device.
 */
 
-enum BusLogic_SetCCBFormatRequest
-{
-  BusLogic_LegacyLUNFormatCCB =			0,
-  BusLogic_ExtendedLUNFormatCCB =		1
+enum BusLogic_SetCCBFormatRequest {
+	BusLogic_LegacyLUNFormatCCB = 0,
+	BusLogic_ExtendedLUNFormatCCB = 1
 } PACKED;
 
 /*
   Define the Outgoing Mailbox Action Codes.
 */
 
-enum BusLogic_ActionCode
-{
-  BusLogic_OutgoingMailboxFree =		0x00,
-  BusLogic_MailboxStartCommand =		0x01,
-  BusLogic_MailboxAbortCommand =		0x02
+enum BusLogic_ActionCode {
+	BusLogic_OutgoingMailboxFree = 0x00,
+	BusLogic_MailboxStartCommand = 0x01,
+	BusLogic_MailboxAbortCommand = 0x02
 } PACKED;
 
 
@@ -742,28 +709,26 @@ enum BusLogic_ActionCode
   completion codes are stored in the CCB; it only uses codes 1, 2, 4, and 5.
 */
 
-enum BusLogic_CompletionCode
-{
-  BusLogic_IncomingMailboxFree =		0x00,
-  BusLogic_CommandCompletedWithoutError =	0x01,
-  BusLogic_CommandAbortedAtHostRequest =	0x02,
-  BusLogic_AbortedCommandNotFound =		0x03,
-  BusLogic_CommandCompletedWithError =		0x04,
-  BusLogic_InvalidCCB =				0x05
+enum BusLogic_CompletionCode {
+	BusLogic_IncomingMailboxFree = 0x00,
+	BusLogic_CommandCompletedWithoutError = 0x01,
+	BusLogic_CommandAbortedAtHostRequest = 0x02,
+	BusLogic_AbortedCommandNotFound = 0x03,
+	BusLogic_CommandCompletedWithError = 0x04,
+	BusLogic_InvalidCCB = 0x05
 } PACKED;
 
 /*
   Define the Command Control Block (CCB) Opcodes.
 */
 
-enum BusLogic_CCB_Opcode
-{
-  BusLogic_InitiatorCCB =			0x00,
-  BusLogic_TargetCCB =				0x01,
-  BusLogic_InitiatorCCB_ScatterGather =		0x02,
-  BusLogic_InitiatorCCB_ResidualDataLength =	0x03,
-  BusLogic_InitiatorCCB_ScatterGatherResidual =	0x04,
-  BusLogic_BusDeviceReset =			0x81
+enum BusLogic_CCB_Opcode {
+	BusLogic_InitiatorCCB = 0x00,
+	BusLogic_TargetCCB = 0x01,
+	BusLogic_InitiatorCCB_ScatterGather = 0x02,
+	BusLogic_InitiatorCCB_ResidualDataLength = 0x03,
+	BusLogic_InitiatorCCB_ScatterGatherResidual = 0x04,
+	BusLogic_BusDeviceReset = 0x81
 } PACKED;
 
 
@@ -771,12 +736,11 @@ enum BusLogic_CCB_Opcode
   Define the CCB Data Direction Codes.
 */
 
-enum BusLogic_DataDirection
-{
-  BusLogic_UncheckedDataTransfer =		0,
-  BusLogic_DataInLengthChecked =		1,
-  BusLogic_DataOutLengthChecked =		2,
-  BusLogic_NoDataTransfer =			3
+enum BusLogic_DataDirection {
+	BusLogic_UncheckedDataTransfer = 0,
+	BusLogic_DataInLengthChecked = 1,
+	BusLogic_DataOutLengthChecked = 2,
+	BusLogic_NoDataTransfer = 3
 };
 
 
@@ -785,33 +749,32 @@ enum BusLogic_DataDirection
   return status code 0x0C; it uses 0x12 for both overruns and underruns.
 */
 
-enum BusLogic_HostAdapterStatus
-{
-  BusLogic_CommandCompletedNormally =		0x00,
-  BusLogic_LinkedCommandCompleted =		0x0A,
-  BusLogic_LinkedCommandCompletedWithFlag =	0x0B,
-  BusLogic_DataUnderRun =			0x0C,
-  BusLogic_SCSISelectionTimeout =		0x11,
-  BusLogic_DataOverRun =			0x12,
-  BusLogic_UnexpectedBusFree =			0x13,
-  BusLogic_InvalidBusPhaseRequested =		0x14,
-  BusLogic_InvalidOutgoingMailboxActionCode =	0x15,
-  BusLogic_InvalidCommandOperationCode =	0x16,
-  BusLogic_LinkedCCBhasInvalidLUN =		0x17,
-  BusLogic_InvalidCommandParameter =		0x1A,
-  BusLogic_AutoRequestSenseFailed =		0x1B,
-  BusLogic_TaggedQueuingMessageRejected =	0x1C,
-  BusLogic_UnsupportedMessageReceived =		0x1D,
-  BusLogic_HostAdapterHardwareFailed =		0x20,
-  BusLogic_TargetFailedResponseToATN =		0x21,
-  BusLogic_HostAdapterAssertedRST =		0x22,
-  BusLogic_OtherDeviceAssertedRST =		0x23,
-  BusLogic_TargetDeviceReconnectedImproperly =	0x24,
-  BusLogic_HostAdapterAssertedBusDeviceReset =	0x25,
-  BusLogic_AbortQueueGenerated =		0x26,
-  BusLogic_HostAdapterSoftwareError =		0x27,
-  BusLogic_HostAdapterHardwareTimeoutError =	0x30,
-  BusLogic_SCSIParityErrorDetected =		0x34
+enum BusLogic_HostAdapterStatus {
+	BusLogic_CommandCompletedNormally = 0x00,
+	BusLogic_LinkedCommandCompleted = 0x0A,
+	BusLogic_LinkedCommandCompletedWithFlag = 0x0B,
+	BusLogic_DataUnderRun = 0x0C,
+	BusLogic_SCSISelectionTimeout = 0x11,
+	BusLogic_DataOverRun = 0x12,
+	BusLogic_UnexpectedBusFree = 0x13,
+	BusLogic_InvalidBusPhaseRequested = 0x14,
+	BusLogic_InvalidOutgoingMailboxActionCode = 0x15,
+	BusLogic_InvalidCommandOperationCode = 0x16,
+	BusLogic_LinkedCCBhasInvalidLUN = 0x17,
+	BusLogic_InvalidCommandParameter = 0x1A,
+	BusLogic_AutoRequestSenseFailed = 0x1B,
+	BusLogic_TaggedQueuingMessageRejected = 0x1C,
+	BusLogic_UnsupportedMessageReceived = 0x1D,
+	BusLogic_HostAdapterHardwareFailed = 0x20,
+	BusLogic_TargetFailedResponseToATN = 0x21,
+	BusLogic_HostAdapterAssertedRST = 0x22,
+	BusLogic_OtherDeviceAssertedRST = 0x23,
+	BusLogic_TargetDeviceReconnectedImproperly = 0x24,
+	BusLogic_HostAdapterAssertedBusDeviceReset = 0x25,
+	BusLogic_AbortQueueGenerated = 0x26,
+	BusLogic_HostAdapterSoftwareError = 0x27,
+	BusLogic_HostAdapterHardwareTimeoutError = 0x30,
+	BusLogic_SCSIParityErrorDetected = 0x34
 } PACKED;
 
 
@@ -819,23 +782,21 @@ enum BusLogic_HostAdapterStatus
   Define the SCSI Target Device Status Codes.
 */
 
-enum BusLogic_TargetDeviceStatus
-{
-  BusLogic_OperationGood =			0x00,
-  BusLogic_CheckCondition =			0x02,
-  BusLogic_DeviceBusy =				0x08
+enum BusLogic_TargetDeviceStatus {
+	BusLogic_OperationGood = 0x00,
+	BusLogic_CheckCondition = 0x02,
+	BusLogic_DeviceBusy = 0x08
 } PACKED;
 
 /*
   Define the Queue Tag Codes.
 */
 
-enum BusLogic_QueueTag
-{
-  BusLogic_SimpleQueueTag =			0,
-  BusLogic_HeadOfQueueTag =			1,
-  BusLogic_OrderedQueueTag =			2,
-  BusLogic_ReservedQT =				3
+enum BusLogic_QueueTag {
+	BusLogic_SimpleQueueTag = 0,
+	BusLogic_HeadOfQueueTag = 1,
+	BusLogic_OrderedQueueTag = 2,
+	BusLogic_ReservedQT = 3
 };
 
 /*
@@ -852,22 +813,20 @@ typedef unsigned char SCSI_CDB_T[BusLogic_CDB_MaxLength];
   Firmware Interface and the FlashPoint SCCB Manager.
 */
 
-struct BusLogic_ScatterGatherSegment
-{
-  u32 SegmentByteCount;					/* Bytes 0-3 */
-  u32 SegmentDataPointer;				/* Bytes 4-7 */
+struct BusLogic_ScatterGatherSegment {
+	u32 SegmentByteCount;	/* Bytes 0-3 */
+	u32 SegmentDataPointer;	/* Bytes 4-7 */
 };
 
 /*
   Define the Driver CCB Status Codes.
 */
 
-enum BusLogic_CCB_Status
-{
-  BusLogic_CCB_Free =				0,
-  BusLogic_CCB_Active =				1,
-  BusLogic_CCB_Completed =			2,
-  BusLogic_CCB_Reset =				3
+enum BusLogic_CCB_Status {
+	BusLogic_CCB_Free = 0,
+	BusLogic_CCB_Active = 1,
+	BusLogic_CCB_Completed = 2,
+	BusLogic_CCB_Reset = 3
 } PACKED;
 
 
@@ -890,82 +849,79 @@ enum BusLogic_CCB_Status
   32 Logical Units per Target Device.
 */
 
-struct BusLogic_CCB
-{
-  /*
-    MultiMaster Firmware and FlashPoint SCCB Manager Common Portion.
-  */
-  enum BusLogic_CCB_Opcode Opcode;			/* Byte 0 */
-  unsigned char :3;					/* Byte 1 Bits 0-2 */
-  enum BusLogic_DataDirection DataDirection:2;		/* Byte 1 Bits 3-4 */
-  boolean TagEnable:1;					/* Byte 1 Bit 5 */
-  enum BusLogic_QueueTag QueueTag:2;			/* Byte 1 Bits 6-7 */
-  unsigned char CDB_Length;				/* Byte 2 */
-  unsigned char SenseDataLength;			/* Byte 3 */
-  u32 DataLength;					/* Bytes 4-7 */
-  u32 DataPointer;					/* Bytes 8-11 */
-  unsigned char :8;					/* Byte 12 */
-  unsigned char :8;					/* Byte 13 */
-  enum BusLogic_HostAdapterStatus HostAdapterStatus;	/* Byte 14 */
-  enum BusLogic_TargetDeviceStatus TargetDeviceStatus;	/* Byte 15 */
-  unsigned char TargetID;				/* Byte 16 */
-  unsigned char LogicalUnit:5;				/* Byte 17 Bits 0-4 */
-  boolean LegacyTagEnable:1;				/* Byte 17 Bit 5 */
-  enum BusLogic_QueueTag LegacyQueueTag:2;		/* Byte 17 Bits 6-7 */
-  SCSI_CDB_T CDB;					/* Bytes 18-29 */
-  unsigned char :8;					/* Byte 30 */
-  unsigned char :8;					/* Byte 31 */
-  unsigned int :32;					/* Bytes 32-35 */
-  u32 SenseDataPointer;					/* Bytes 36-39 */
-  /*
-    FlashPoint SCCB Manager Defined Portion.
-  */
-  void (*CallbackFunction)(struct BusLogic_CCB *);	/* Bytes 40-43 */
-  u32 BaseAddress;					/* Bytes 44-47 */
-  enum BusLogic_CompletionCode CompletionCode;		/* Byte 48 */
+struct BusLogic_CCB {
+	/*
+	   MultiMaster Firmware and FlashPoint SCCB Manager Common Portion.
+	 */
+	enum BusLogic_CCB_Opcode Opcode;	/* Byte 0 */
+	unsigned char:3;	/* Byte 1 Bits 0-2 */
+	enum BusLogic_DataDirection DataDirection:2;	/* Byte 1 Bits 3-4 */
+	boolean TagEnable:1;	/* Byte 1 Bit 5 */
+	enum BusLogic_QueueTag QueueTag:2;	/* Byte 1 Bits 6-7 */
+	unsigned char CDB_Length;	/* Byte 2 */
+	unsigned char SenseDataLength;	/* Byte 3 */
+	u32 DataLength;		/* Bytes 4-7 */
+	u32 DataPointer;	/* Bytes 8-11 */
+	unsigned char:8;	/* Byte 12 */
+	unsigned char:8;	/* Byte 13 */
+	enum BusLogic_HostAdapterStatus HostAdapterStatus;	/* Byte 14 */
+	enum BusLogic_TargetDeviceStatus TargetDeviceStatus;	/* Byte 15 */
+	unsigned char TargetID;	/* Byte 16 */
+	unsigned char LogicalUnit:5;	/* Byte 17 Bits 0-4 */
+	boolean LegacyTagEnable:1;	/* Byte 17 Bit 5 */
+	enum BusLogic_QueueTag LegacyQueueTag:2;	/* Byte 17 Bits 6-7 */
+	SCSI_CDB_T CDB;		/* Bytes 18-29 */
+	unsigned char:8;	/* Byte 30 */
+	unsigned char:8;	/* Byte 31 */
+	unsigned int:32;	/* Bytes 32-35 */
+	u32 SenseDataPointer;	/* Bytes 36-39 */
+	/*
+	   FlashPoint SCCB Manager Defined Portion.
+	 */
+	void (*CallbackFunction) (struct BusLogic_CCB *);	/* Bytes 40-43 */
+	u32 BaseAddress;	/* Bytes 44-47 */
+	enum BusLogic_CompletionCode CompletionCode;	/* Byte 48 */
 #ifndef CONFIG_SCSI_OMIT_FLASHPOINT
-  unsigned char :8;					/* Byte 49 */
-  unsigned short OS_Flags;				/* Bytes 50-51 */
-  unsigned char Private[48];				/* Bytes 52-99 */
+	unsigned char:8;	/* Byte 49 */
+	unsigned short OS_Flags;	/* Bytes 50-51 */
+	unsigned char Private[48];	/* Bytes 52-99 */
 #endif
-  /*
-    BusLogic Linux Driver Defined Portion.
-  */
-  dma_addr_t AllocationGroupHead;
-  unsigned int AllocationGroupSize;
-  u32 DMA_Handle;
-  enum BusLogic_CCB_Status Status;
-  unsigned long SerialNumber;
-  struct scsi_cmnd *Command;
-  struct BusLogic_HostAdapter *HostAdapter;
-  struct BusLogic_CCB *Next;
-  struct BusLogic_CCB *NextAll;
-  struct BusLogic_ScatterGatherSegment
-    ScatterGatherList[BusLogic_ScatterGatherLimit];
+	/*
+	   BusLogic Linux Driver Defined Portion.
+	 */
+	dma_addr_t AllocationGroupHead;
+	unsigned int AllocationGroupSize;
+	u32 DMA_Handle;
+	enum BusLogic_CCB_Status Status;
+	unsigned long SerialNumber;
+	struct scsi_cmnd *Command;
+	struct BusLogic_HostAdapter *HostAdapter;
+	struct BusLogic_CCB *Next;
+	struct BusLogic_CCB *NextAll;
+	struct BusLogic_ScatterGatherSegment
+	 ScatterGatherList[BusLogic_ScatterGatherLimit];
 };
 
 /*
   Define the 32 Bit Mode Outgoing Mailbox structure.
 */
 
-struct BusLogic_OutgoingMailbox
-{
-  u32 CCB;						/* Bytes 0-3 */
-  unsigned int :24;					/* Bytes 4-6 */
-  enum BusLogic_ActionCode ActionCode;			/* Byte 7 */
+struct BusLogic_OutgoingMailbox {
+	u32 CCB;		/* Bytes 0-3 */
+	unsigned int:24;	/* Bytes 4-6 */
+	enum BusLogic_ActionCode ActionCode;	/* Byte 7 */
 };
 
 /*
   Define the 32 Bit Mode Incoming Mailbox structure.
 */
 
-struct BusLogic_IncomingMailbox
-{
-  u32 CCB;						/* Bytes 0-3 */
-  enum BusLogic_HostAdapterStatus HostAdapterStatus;	/* Byte 4 */
-  enum BusLogic_TargetDeviceStatus TargetDeviceStatus;	/* Byte 5 */
-  unsigned char :8;					/* Byte 6 */
-  enum BusLogic_CompletionCode CompletionCode;		/* Byte 7 */
+struct BusLogic_IncomingMailbox {
+	u32 CCB;		/* Bytes 0-3 */
+	enum BusLogic_HostAdapterStatus HostAdapterStatus;	/* Byte 4 */
+	enum BusLogic_TargetDeviceStatus TargetDeviceStatus;	/* Byte 5 */
+	unsigned char:8;	/* Byte 6 */
+	enum BusLogic_CompletionCode CompletionCode;	/* Byte 7 */
 };
 
 
@@ -973,29 +929,27 @@ struct BusLogic_IncomingMailbox
   Define the BusLogic Driver Options structure.
 */
 
-struct BusLogic_DriverOptions
-{
-  unsigned short TaggedQueuingPermitted;
-  unsigned short TaggedQueuingPermittedMask;
-  unsigned short BusSettleTime;
-  struct BusLogic_LocalOptions LocalOptions;
-  unsigned char CommonQueueDepth;
-  unsigned char QueueDepth[BusLogic_MaxTargetDevices];
+struct BusLogic_DriverOptions {
+	unsigned short TaggedQueuingPermitted;
+	unsigned short TaggedQueuingPermittedMask;
+	unsigned short BusSettleTime;
+	struct BusLogic_LocalOptions LocalOptions;
+	unsigned char CommonQueueDepth;
+	unsigned char QueueDepth[BusLogic_MaxTargetDevices];
 };
 
 /*
   Define the Host Adapter Target Flags structure.
 */
 
-struct BusLogic_TargetFlags
-{
-  boolean TargetExists:1;
-  boolean TaggedQueuingSupported:1;
-  boolean WideTransfersSupported:1;
-  boolean TaggedQueuingActive:1;
-  boolean WideTransfersActive:1;
-  boolean CommandSuccessfulFlag:1;
-  boolean TargetInfoReported:1;
+struct BusLogic_TargetFlags {
+	boolean TargetExists:1;
+	boolean TaggedQueuingSupported:1;
+	boolean WideTransfersSupported:1;
+	boolean TaggedQueuingActive:1;
+	boolean WideTransfersActive:1;
+	boolean CommandSuccessfulFlag:1;
+	boolean TargetInfoReported:1;
 };
 
 /*
@@ -1006,25 +960,24 @@ struct BusLogic_TargetFlags
 
 typedef unsigned int BusLogic_CommandSizeBuckets_T[BusLogic_SizeBuckets];
 
-struct BusLogic_TargetStatistics
-{
-  unsigned int CommandsAttempted;
-  unsigned int CommandsCompleted;
-  unsigned int ReadCommands;
-  unsigned int WriteCommands;
-  struct BusLogic_ByteCounter TotalBytesRead;
-  struct BusLogic_ByteCounter TotalBytesWritten;
-  BusLogic_CommandSizeBuckets_T ReadCommandSizeBuckets;
-  BusLogic_CommandSizeBuckets_T WriteCommandSizeBuckets;
-  unsigned short CommandAbortsRequested;
-  unsigned short CommandAbortsAttempted;
-  unsigned short CommandAbortsCompleted;
-  unsigned short BusDeviceResetsRequested;
-  unsigned short BusDeviceResetsAttempted;
-  unsigned short BusDeviceResetsCompleted;
-  unsigned short HostAdapterResetsRequested;
-  unsigned short HostAdapterResetsAttempted;
-  unsigned short HostAdapterResetsCompleted;
+struct BusLogic_TargetStatistics {
+	unsigned int CommandsAttempted;
+	unsigned int CommandsCompleted;
+	unsigned int ReadCommands;
+	unsigned int WriteCommands;
+	struct BusLogic_ByteCounter TotalBytesRead;
+	struct BusLogic_ByteCounter TotalBytesWritten;
+	BusLogic_CommandSizeBuckets_T ReadCommandSizeBuckets;
+	BusLogic_CommandSizeBuckets_T WriteCommandSizeBuckets;
+	unsigned short CommandAbortsRequested;
+	unsigned short CommandAbortsAttempted;
+	unsigned short CommandAbortsCompleted;
+	unsigned short BusDeviceResetsRequested;
+	unsigned short BusDeviceResetsAttempted;
+	unsigned short BusDeviceResetsCompleted;
+	unsigned short HostAdapterResetsRequested;
+	unsigned short HostAdapterResetsAttempted;
+	unsigned short HostAdapterResetsCompleted;
 };
 
 /*
@@ -1041,183 +994,179 @@ typedef unsigned int FlashPoint_CardHandle_T;
   by the FlashPoint SCCB Manager.
 */
 
-struct FlashPoint_Info
-{
-  u32 BaseAddress;					/* Bytes 0-3 */
-  boolean Present;					/* Byte 4 */
-  unsigned char IRQ_Channel;				/* Byte 5 */
-  unsigned char SCSI_ID;				/* Byte 6 */
-  unsigned char SCSI_LUN;				/* Byte 7 */
-  unsigned short FirmwareRevision;			/* Bytes 8-9 */
-  unsigned short SynchronousPermitted;			/* Bytes 10-11 */
-  unsigned short FastPermitted;				/* Bytes 12-13 */
-  unsigned short UltraPermitted;			/* Bytes 14-15 */
-  unsigned short DisconnectPermitted;			/* Bytes 16-17 */
-  unsigned short WidePermitted;				/* Bytes 18-19 */
-  boolean ParityCheckingEnabled:1;			/* Byte 20 Bit 0 */
-  boolean HostWideSCSI:1;				/* Byte 20 Bit 1 */
-  boolean HostSoftReset:1;				/* Byte 20 Bit 2 */
-  boolean ExtendedTranslationEnabled:1;			/* Byte 20 Bit 3 */
-  boolean LowByteTerminated:1;				/* Byte 20 Bit 4 */
-  boolean HighByteTerminated:1;				/* Byte 20 Bit 5 */
-  boolean ReportDataUnderrun:1;				/* Byte 20 Bit 6 */
-  boolean SCAM_Enabled:1;				/* Byte 20 Bit 7 */
-  boolean SCAM_Level2:1;				/* Byte 21 Bit 0 */
-  unsigned char :7;					/* Byte 21 Bits 1-7 */
-  unsigned char Family;					/* Byte 22 */
-  unsigned char BusType;				/* Byte 23 */
-  unsigned char ModelNumber[3];				/* Bytes 24-26 */
-  unsigned char RelativeCardNumber;			/* Byte 27 */
-  unsigned char Reserved[4];				/* Bytes 28-31 */
-  unsigned int OS_Reserved;				/* Bytes 32-35 */
-  unsigned char TranslationInfo[4];			/* Bytes 36-39 */
-  unsigned int Reserved2[5];				/* Bytes 40-59 */
-  unsigned int SecondaryRange;				/* Bytes 60-63 */
+struct FlashPoint_Info {
+	u32 BaseAddress;	/* Bytes 0-3 */
+	boolean Present;	/* Byte 4 */
+	unsigned char IRQ_Channel;	/* Byte 5 */
+	unsigned char SCSI_ID;	/* Byte 6 */
+	unsigned char SCSI_LUN;	/* Byte 7 */
+	unsigned short FirmwareRevision;	/* Bytes 8-9 */
+	unsigned short SynchronousPermitted;	/* Bytes 10-11 */
+	unsigned short FastPermitted;	/* Bytes 12-13 */
+	unsigned short UltraPermitted;	/* Bytes 14-15 */
+	unsigned short DisconnectPermitted;	/* Bytes 16-17 */
+	unsigned short WidePermitted;	/* Bytes 18-19 */
+	boolean ParityCheckingEnabled:1;	/* Byte 20 Bit 0 */
+	boolean HostWideSCSI:1;	/* Byte 20 Bit 1 */
+	boolean HostSoftReset:1;	/* Byte 20 Bit 2 */
+	boolean ExtendedTranslationEnabled:1;	/* Byte 20 Bit 3 */
+	boolean LowByteTerminated:1;	/* Byte 20 Bit 4 */
+	boolean HighByteTerminated:1;	/* Byte 20 Bit 5 */
+	boolean ReportDataUnderrun:1;	/* Byte 20 Bit 6 */
+	boolean SCAM_Enabled:1;	/* Byte 20 Bit 7 */
+	boolean SCAM_Level2:1;	/* Byte 21 Bit 0 */
+	unsigned char:7;	/* Byte 21 Bits 1-7 */
+	unsigned char Family;	/* Byte 22 */
+	unsigned char BusType;	/* Byte 23 */
+	unsigned char ModelNumber[3];	/* Bytes 24-26 */
+	unsigned char RelativeCardNumber;	/* Byte 27 */
+	unsigned char Reserved[4];	/* Bytes 28-31 */
+	unsigned int OS_Reserved;	/* Bytes 32-35 */
+	unsigned char TranslationInfo[4];	/* Bytes 36-39 */
+	unsigned int Reserved2[5];	/* Bytes 40-59 */
+	unsigned int SecondaryRange;	/* Bytes 60-63 */
 };
 
 /*
   Define the BusLogic Driver Host Adapter structure.
 */
 
-struct BusLogic_HostAdapter
-{
-  struct Scsi_Host *SCSI_Host;
-  struct pci_dev *PCI_Device;
-  enum BusLogic_HostAdapterType HostAdapterType;
-  enum BusLogic_HostAdapterBusType HostAdapterBusType;
-  unsigned long IO_Address;
-  unsigned long PCI_Address;
-  unsigned short AddressCount;
-  unsigned char HostNumber;
-  unsigned char ModelName[9];
-  unsigned char FirmwareVersion[6];
-  unsigned char FullModelName[18];
-  unsigned char Bus;
-  unsigned char Device;
-  unsigned char IRQ_Channel;
-  unsigned char DMA_Channel;
-  unsigned char SCSI_ID;
-  boolean IRQ_ChannelAcquired:1;
-  boolean DMA_ChannelAcquired:1;
-  boolean ExtendedTranslationEnabled:1;
-  boolean ParityCheckingEnabled:1;
-  boolean BusResetEnabled:1;
-  boolean LevelSensitiveInterrupt:1;
-  boolean HostWideSCSI:1;
-  boolean HostDifferentialSCSI:1;
-  boolean HostSupportsSCAM:1;
-  boolean HostUltraSCSI:1;
-  boolean ExtendedLUNSupport:1;
-  boolean TerminationInfoValid:1;
-  boolean LowByteTerminated:1;
-  boolean HighByteTerminated:1;
-  boolean BounceBuffersRequired:1;
-  boolean StrictRoundRobinModeSupport:1;
-  boolean SCAM_Enabled:1;
-  boolean SCAM_Level2:1;
-  boolean HostAdapterInitialized:1;
-  boolean HostAdapterExternalReset:1;
-  boolean HostAdapterInternalError:1;
-  boolean ProcessCompletedCCBsActive;
-  volatile boolean HostAdapterCommandCompleted;
-  unsigned short HostAdapterScatterGatherLimit;
-  unsigned short DriverScatterGatherLimit;
-  unsigned short MaxTargetDevices;
-  unsigned short MaxLogicalUnits;
-  unsigned short MailboxCount;
-  unsigned short InitialCCBs;
-  unsigned short IncrementalCCBs;
-  unsigned short AllocatedCCBs;
-  unsigned short DriverQueueDepth;
-  unsigned short HostAdapterQueueDepth;
-  unsigned short UntaggedQueueDepth;
-  unsigned short CommonQueueDepth;
-  unsigned short BusSettleTime;
-  unsigned short SynchronousPermitted;
-  unsigned short FastPermitted;
-  unsigned short UltraPermitted;
-  unsigned short WidePermitted;
-  unsigned short DisconnectPermitted;
-  unsigned short TaggedQueuingPermitted;
-  unsigned short ExternalHostAdapterResets;
-  unsigned short HostAdapterInternalErrors;
-  unsigned short TargetDeviceCount;
-  unsigned short MessageBufferLength;
-  u32 BIOS_Address;
-  struct BusLogic_DriverOptions *DriverOptions;
-  struct FlashPoint_Info FlashPointInfo;
-  FlashPoint_CardHandle_T CardHandle;
-  struct BusLogic_HostAdapter *Next;
-  struct BusLogic_CCB *All_CCBs;
-  struct BusLogic_CCB *Free_CCBs;
-  struct BusLogic_CCB *FirstCompletedCCB;
-  struct BusLogic_CCB *LastCompletedCCB;
-  struct BusLogic_CCB *BusDeviceResetPendingCCB[BusLogic_MaxTargetDevices];
-  struct BusLogic_TargetFlags TargetFlags[BusLogic_MaxTargetDevices];
-  unsigned char QueueDepth[BusLogic_MaxTargetDevices];
-  unsigned char SynchronousPeriod[BusLogic_MaxTargetDevices];
-  unsigned char SynchronousOffset[BusLogic_MaxTargetDevices];
-  unsigned char ActiveCommands[BusLogic_MaxTargetDevices];
-  unsigned int CommandsSinceReset[BusLogic_MaxTargetDevices];
-  unsigned long LastSequencePoint[BusLogic_MaxTargetDevices];
-  unsigned long LastResetAttempted[BusLogic_MaxTargetDevices];
-  unsigned long LastResetCompleted[BusLogic_MaxTargetDevices];
-  struct BusLogic_OutgoingMailbox *FirstOutgoingMailbox;
-  struct BusLogic_OutgoingMailbox *LastOutgoingMailbox;
-  struct BusLogic_OutgoingMailbox *NextOutgoingMailbox;
-  struct BusLogic_IncomingMailbox *FirstIncomingMailbox;
-  struct BusLogic_IncomingMailbox *LastIncomingMailbox;
-  struct BusLogic_IncomingMailbox *NextIncomingMailbox;
-  struct BusLogic_TargetStatistics TargetStatistics[BusLogic_MaxTargetDevices];
-  unsigned char *MailboxSpace;
-  dma_addr_t MailboxSpaceHandle;
-  unsigned int MailboxSize;
-  unsigned long CCB_Offset;
-  char MessageBuffer[BusLogic_MessageBufferSize];
+struct BusLogic_HostAdapter {
+	struct Scsi_Host *SCSI_Host;
+	struct pci_dev *PCI_Device;
+	enum BusLogic_HostAdapterType HostAdapterType;
+	enum BusLogic_HostAdapterBusType HostAdapterBusType;
+	unsigned long IO_Address;
+	unsigned long PCI_Address;
+	unsigned short AddressCount;
+	unsigned char HostNumber;
+	unsigned char ModelName[9];
+	unsigned char FirmwareVersion[6];
+	unsigned char FullModelName[18];
+	unsigned char Bus;
+	unsigned char Device;
+	unsigned char IRQ_Channel;
+	unsigned char DMA_Channel;
+	unsigned char SCSI_ID;
+	boolean IRQ_ChannelAcquired:1;
+	boolean DMA_ChannelAcquired:1;
+	boolean ExtendedTranslationEnabled:1;
+	boolean ParityCheckingEnabled:1;
+	boolean BusResetEnabled:1;
+	boolean LevelSensitiveInterrupt:1;
+	boolean HostWideSCSI:1;
+	boolean HostDifferentialSCSI:1;
+	boolean HostSupportsSCAM:1;
+	boolean HostUltraSCSI:1;
+	boolean ExtendedLUNSupport:1;
+	boolean TerminationInfoValid:1;
+	boolean LowByteTerminated:1;
+	boolean HighByteTerminated:1;
+	boolean BounceBuffersRequired:1;
+	boolean StrictRoundRobinModeSupport:1;
+	boolean SCAM_Enabled:1;
+	boolean SCAM_Level2:1;
+	boolean HostAdapterInitialized:1;
+	boolean HostAdapterExternalReset:1;
+	boolean HostAdapterInternalError:1;
+	boolean ProcessCompletedCCBsActive;
+	volatile boolean HostAdapterCommandCompleted;
+	unsigned short HostAdapterScatterGatherLimit;
+	unsigned short DriverScatterGatherLimit;
+	unsigned short MaxTargetDevices;
+	unsigned short MaxLogicalUnits;
+	unsigned short MailboxCount;
+	unsigned short InitialCCBs;
+	unsigned short IncrementalCCBs;
+	unsigned short AllocatedCCBs;
+	unsigned short DriverQueueDepth;
+	unsigned short HostAdapterQueueDepth;
+	unsigned short UntaggedQueueDepth;
+	unsigned short CommonQueueDepth;
+	unsigned short BusSettleTime;
+	unsigned short SynchronousPermitted;
+	unsigned short FastPermitted;
+	unsigned short UltraPermitted;
+	unsigned short WidePermitted;
+	unsigned short DisconnectPermitted;
+	unsigned short TaggedQueuingPermitted;
+	unsigned short ExternalHostAdapterResets;
+	unsigned short HostAdapterInternalErrors;
+	unsigned short TargetDeviceCount;
+	unsigned short MessageBufferLength;
+	u32 BIOS_Address;
+	struct BusLogic_DriverOptions *DriverOptions;
+	struct FlashPoint_Info FlashPointInfo;
+	FlashPoint_CardHandle_T CardHandle;
+	struct BusLogic_HostAdapter *Next;
+	struct BusLogic_CCB *All_CCBs;
+	struct BusLogic_CCB *Free_CCBs;
+	struct BusLogic_CCB *FirstCompletedCCB;
+	struct BusLogic_CCB *LastCompletedCCB;
+	struct BusLogic_CCB *BusDeviceResetPendingCCB[BusLogic_MaxTargetDevices];
+	struct BusLogic_TargetFlags TargetFlags[BusLogic_MaxTargetDevices];
+	unsigned char QueueDepth[BusLogic_MaxTargetDevices];
+	unsigned char SynchronousPeriod[BusLogic_MaxTargetDevices];
+	unsigned char SynchronousOffset[BusLogic_MaxTargetDevices];
+	unsigned char ActiveCommands[BusLogic_MaxTargetDevices];
+	unsigned int CommandsSinceReset[BusLogic_MaxTargetDevices];
+	unsigned long LastSequencePoint[BusLogic_MaxTargetDevices];
+	unsigned long LastResetAttempted[BusLogic_MaxTargetDevices];
+	unsigned long LastResetCompleted[BusLogic_MaxTargetDevices];
+	struct BusLogic_OutgoingMailbox *FirstOutgoingMailbox;
+	struct BusLogic_OutgoingMailbox *LastOutgoingMailbox;
+	struct BusLogic_OutgoingMailbox *NextOutgoingMailbox;
+	struct BusLogic_IncomingMailbox *FirstIncomingMailbox;
+	struct BusLogic_IncomingMailbox *LastIncomingMailbox;
+	struct BusLogic_IncomingMailbox *NextIncomingMailbox;
+	struct BusLogic_TargetStatistics TargetStatistics[BusLogic_MaxTargetDevices];
+	unsigned char *MailboxSpace;
+	dma_addr_t MailboxSpaceHandle;
+	unsigned int MailboxSize;
+	unsigned long CCB_Offset;
+	char MessageBuffer[BusLogic_MessageBufferSize];
 };
 
 /*
   Define a structure for the BIOS Disk Parameters.
 */
 
-struct BIOS_DiskParameters
-{
-  int Heads;
-  int Sectors;
-  int Cylinders;
+struct BIOS_DiskParameters {
+	int Heads;
+	int Sectors;
+	int Cylinders;
 };
 
 /*
   Define a structure for the SCSI Inquiry command results.
 */
 
-struct SCSI_Inquiry
-{
-  unsigned char PeripheralDeviceType:5;			/* Byte 0 Bits 0-4 */
-  unsigned char PeripheralQualifier:3;			/* Byte 0 Bits 5-7 */
-  unsigned char DeviceTypeModifier:7;			/* Byte 1 Bits 0-6 */
-  boolean RMB:1;					/* Byte 1 Bit 7 */
-  unsigned char ANSI_ApprovedVersion:3;			/* Byte 2 Bits 0-2 */
-  unsigned char ECMA_Version:3;				/* Byte 2 Bits 3-5 */
-  unsigned char ISO_Version:2;				/* Byte 2 Bits 6-7 */
-  unsigned char ResponseDataFormat:4;			/* Byte 3 Bits 0-3 */
-  unsigned char :2;					/* Byte 3 Bits 4-5 */
-  boolean TrmIOP:1;					/* Byte 3 Bit 6 */
-  boolean AENC:1;					/* Byte 3 Bit 7 */
-  unsigned char AdditionalLength;			/* Byte 4 */
-  unsigned char :8;					/* Byte 5 */
-  unsigned char :8;					/* Byte 6 */
-  boolean SftRe:1;					/* Byte 7 Bit 0 */
-  boolean CmdQue:1;					/* Byte 7 Bit 1 */
-  boolean :1;						/* Byte 7 Bit 2 */
-  boolean Linked:1;					/* Byte 7 Bit 3 */
-  boolean Sync:1;					/* Byte 7 Bit 4 */
-  boolean WBus16:1;					/* Byte 7 Bit 5 */
-  boolean WBus32:1;					/* Byte 7 Bit 6 */
-  boolean RelAdr:1;					/* Byte 7 Bit 7 */
-  unsigned char VendorIdentification[8];		/* Bytes 8-15 */
-  unsigned char ProductIdentification[16];		/* Bytes 16-31 */
-  unsigned char ProductRevisionLevel[4];		/* Bytes 32-35 */
+struct SCSI_Inquiry {
+	unsigned char PeripheralDeviceType:5;	/* Byte 0 Bits 0-4 */
+	unsigned char PeripheralQualifier:3;	/* Byte 0 Bits 5-7 */
+	unsigned char DeviceTypeModifier:7;	/* Byte 1 Bits 0-6 */
+	boolean RMB:1;		/* Byte 1 Bit 7 */
+	unsigned char ANSI_ApprovedVersion:3;	/* Byte 2 Bits 0-2 */
+	unsigned char ECMA_Version:3;	/* Byte 2 Bits 3-5 */
+	unsigned char ISO_Version:2;	/* Byte 2 Bits 6-7 */
+	unsigned char ResponseDataFormat:4;	/* Byte 3 Bits 0-3 */
+	unsigned char:2;	/* Byte 3 Bits 4-5 */
+	boolean TrmIOP:1;	/* Byte 3 Bit 6 */
+	boolean AENC:1;		/* Byte 3 Bit 7 */
+	unsigned char AdditionalLength;	/* Byte 4 */
+	unsigned char:8;	/* Byte 5 */
+	unsigned char:8;	/* Byte 6 */
+	boolean SftRe:1;	/* Byte 7 Bit 0 */
+	boolean CmdQue:1;	/* Byte 7 Bit 1 */
+	 boolean:1;		/* Byte 7 Bit 2 */
+	boolean Linked:1;	/* Byte 7 Bit 3 */
+	boolean Sync:1;		/* Byte 7 Bit 4 */
+	boolean WBus16:1;	/* Byte 7 Bit 5 */
+	boolean WBus32:1;	/* Byte 7 Bit 6 */
+	boolean RelAdr:1;	/* Byte 7 Bit 7 */
+	unsigned char VendorIdentification[8];	/* Bytes 8-15 */
+	unsigned char ProductIdentification[16];	/* Bytes 16-31 */
+	unsigned char ProductRevisionLevel[4];	/* Bytes 32-35 */
 };
 
 /*
@@ -1226,7 +1175,7 @@ struct SCSI_Inquiry
 
 static inline void BusLogic_AcquireHostAdapterLock(struct BusLogic_HostAdapter *HostAdapter)
 {
-  spin_lock_irq(HostAdapter->SCSI_Host->host_lock);
+	spin_lock_irq(HostAdapter->SCSI_Host->host_lock);
 }
 
 /*
@@ -1235,7 +1184,7 @@ static inline void BusLogic_AcquireHostAdapterLock(struct BusLogic_HostAdapter *
 
 static inline void BusLogic_ReleaseHostAdapterLock(struct BusLogic_HostAdapter *HostAdapter)
 {
-  spin_unlock_irq(HostAdapter->SCSI_Host->host_lock);
+	spin_unlock_irq(HostAdapter->SCSI_Host->host_lock);
 }
 
 
@@ -1244,10 +1193,9 @@ static inline void BusLogic_ReleaseHostAdapterLock(struct BusLogic_HostAdapter *
   but is only called from the interrupt handler.
 */
 
-static inline void BusLogic_AcquireHostAdapterLockIH(struct BusLogic_HostAdapter *HostAdapter,
-						     unsigned long *ProcessorFlags)
+static inline void BusLogic_AcquireHostAdapterLockIH(struct BusLogic_HostAdapter *HostAdapter, unsigned long *ProcessorFlags)
 {
-  spin_lock_irqsave(HostAdapter->SCSI_Host->host_lock, *ProcessorFlags);
+	spin_lock_irqsave(HostAdapter->SCSI_Host->host_lock, *ProcessorFlags);
 }
 
 
@@ -1256,10 +1204,9 @@ static inline void BusLogic_AcquireHostAdapterLockIH(struct BusLogic_HostAdapter
   but is only called from the interrupt handler.
 */
 
-static inline void BusLogic_ReleaseHostAdapterLockIH(struct BusLogic_HostAdapter *HostAdapter,
-						     unsigned long *ProcessorFlags)
+static inline void BusLogic_ReleaseHostAdapterLockIH(struct BusLogic_HostAdapter *HostAdapter, unsigned long *ProcessorFlags)
 {
-  spin_unlock_irqrestore(HostAdapter->SCSI_Host->host_lock, *ProcessorFlags);
+	spin_unlock_irqrestore(HostAdapter->SCSI_Host->host_lock, *ProcessorFlags);
 }
 
 
@@ -1270,65 +1217,60 @@ static inline void BusLogic_ReleaseHostAdapterLockIH(struct BusLogic_HostAdapter
 
 static inline void BusLogic_SCSIBusReset(struct BusLogic_HostAdapter *HostAdapter)
 {
-  union BusLogic_ControlRegister ControlRegister;
-  ControlRegister.All = 0;
-  ControlRegister.cr.SCSIBusReset = true;
-  outb(ControlRegister.All,
-       HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
+	union BusLogic_ControlRegister ControlRegister;
+	ControlRegister.All = 0;
+	ControlRegister.cr.SCSIBusReset = true;
+	outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
 }
 
 static inline void BusLogic_InterruptReset(struct BusLogic_HostAdapter *HostAdapter)
 {
-  union BusLogic_ControlRegister ControlRegister;
-  ControlRegister.All = 0;
-  ControlRegister.cr.InterruptReset = true;
-  outb(ControlRegister.All,
-       HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
+	union BusLogic_ControlRegister ControlRegister;
+	ControlRegister.All = 0;
+	ControlRegister.cr.InterruptReset = true;
+	outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
 }
 
 static inline void BusLogic_SoftReset(struct BusLogic_HostAdapter *HostAdapter)
 {
-  union BusLogic_ControlRegister ControlRegister;
-  ControlRegister.All = 0;
-  ControlRegister.cr.SoftReset = true;
-  outb(ControlRegister.All,
-       HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
+	union BusLogic_ControlRegister ControlRegister;
+	ControlRegister.All = 0;
+	ControlRegister.cr.SoftReset = true;
+	outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
 }
 
 static inline void BusLogic_HardReset(struct BusLogic_HostAdapter *HostAdapter)
 {
-  union BusLogic_ControlRegister ControlRegister;
-  ControlRegister.All = 0;
-  ControlRegister.cr.HardReset = true;
-  outb(ControlRegister.All,
-       HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
+	union BusLogic_ControlRegister ControlRegister;
+	ControlRegister.All = 0;
+	ControlRegister.cr.HardReset = true;
+	outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
 }
 
 static inline unsigned char BusLogic_ReadStatusRegister(struct BusLogic_HostAdapter *HostAdapter)
 {
-  return inb(HostAdapter->IO_Address + BusLogic_StatusRegisterOffset);
+	return inb(HostAdapter->IO_Address + BusLogic_StatusRegisterOffset);
 }
 
 static inline void BusLogic_WriteCommandParameterRegister(struct BusLogic_HostAdapter
-							  *HostAdapter,
-							  unsigned char Value)
+							  *HostAdapter, unsigned char Value)
 {
-  outb(Value, HostAdapter->IO_Address + BusLogic_CommandParameterRegisterOffset);
+	outb(Value, HostAdapter->IO_Address + BusLogic_CommandParameterRegisterOffset);
 }
 
 static inline unsigned char BusLogic_ReadDataInRegister(struct BusLogic_HostAdapter *HostAdapter)
 {
-  return inb(HostAdapter->IO_Address + BusLogic_DataInRegisterOffset);
+	return inb(HostAdapter->IO_Address + BusLogic_DataInRegisterOffset);
 }
 
 static inline unsigned char BusLogic_ReadInterruptRegister(struct BusLogic_HostAdapter *HostAdapter)
 {
-  return inb(HostAdapter->IO_Address + BusLogic_InterruptRegisterOffset);
+	return inb(HostAdapter->IO_Address + BusLogic_InterruptRegisterOffset);
 }
 
 static inline unsigned char BusLogic_ReadGeometryRegister(struct BusLogic_HostAdapter *HostAdapter)
 {
-  return inb(HostAdapter->IO_Address + BusLogic_GeometryRegisterOffset);
+	return inb(HostAdapter->IO_Address + BusLogic_GeometryRegisterOffset);
 }
 
 /*
@@ -1339,7 +1281,7 @@ static inline unsigned char BusLogic_ReadGeometryRegister(struct BusLogic_HostAd
 
 static inline void BusLogic_StartMailboxCommand(struct BusLogic_HostAdapter *HostAdapter)
 {
-  BusLogic_WriteCommandParameterRegister(HostAdapter, BusLogic_ExecuteMailboxCommand);
+	BusLogic_WriteCommandParameterRegister(HostAdapter, BusLogic_ExecuteMailboxCommand);
 }
 
 /*
@@ -1348,7 +1290,7 @@ static inline void BusLogic_StartMailboxCommand(struct BusLogic_HostAdapter *Hos
 
 static inline void BusLogic_Delay(int Seconds)
 {
-  mdelay(1000 * Seconds);
+	mdelay(1000 * Seconds);
 }
 
 /*
@@ -1358,12 +1300,12 @@ static inline void BusLogic_Delay(int Seconds)
 
 static inline u32 Virtual_to_Bus(void *VirtualAddress)
 {
-  return (u32) virt_to_bus(VirtualAddress);
+	return (u32) virt_to_bus(VirtualAddress);
 }
 
 static inline void *Bus_to_Virtual(u32 BusAddress)
 {
-  return (void *) bus_to_virt(BusAddress);
+	return (void *) bus_to_virt(BusAddress);
 }
 
 /*
@@ -1374,7 +1316,7 @@ static inline void *Bus_to_Virtual(u32 BusAddress)
 
 static inline u32 Virtual_to_32Bit_Virtual(void *VirtualAddress)
 {
-  return (u32) (unsigned long) VirtualAddress;
+	return (u32) (unsigned long) VirtualAddress;
 }
 
 /*
@@ -1384,7 +1326,8 @@ static inline u32 Virtual_to_32Bit_Virtual(void *VirtualAddress)
 
 static inline void BusLogic_IncrementErrorCounter(unsigned short *ErrorCounter)
 {
-  if (*ErrorCounter < 65535) (*ErrorCounter)++;
+	if (*ErrorCounter < 65535)
+		(*ErrorCounter)++;
 }
 
 /*
@@ -1392,40 +1335,35 @@ static inline void BusLogic_IncrementErrorCounter(unsigned short *ErrorCounter)
 */
 
 static inline void BusLogic_IncrementByteCounter(struct BusLogic_ByteCounter
-						 *ByteCounter,
-						 unsigned int Amount)
+						 *ByteCounter, unsigned int Amount)
 {
-  ByteCounter->Units += Amount;
-  if (ByteCounter->Units > 999999999)
-    {
-      ByteCounter->Units -= 1000000000;
-      ByteCounter->Billions++;
-    }
+	ByteCounter->Units += Amount;
+	if (ByteCounter->Units > 999999999) {
+		ByteCounter->Units -= 1000000000;
+		ByteCounter->Billions++;
+	}
 }
 
 /*
   BusLogic_IncrementSizeBucket increments the Bucket for Amount.
 */
 
-static inline void BusLogic_IncrementSizeBucket(BusLogic_CommandSizeBuckets_T
-						CommandSizeBuckets,
-						unsigned int Amount)
-{
-  int Index = 0;
-  if (Amount < 8*1024)
-    {
-      if (Amount < 2*1024)
-	Index = (Amount < 1*1024 ? 0 : 1);
-      else Index = (Amount < 4*1024 ? 2 : 3);
-    }
-  else if (Amount < 128*1024)
-    {
-      if (Amount < 32*1024)
-	Index = (Amount < 16*1024 ? 4 : 5);
-      else Index = (Amount < 64*1024 ? 6 : 7);
-    }
-  else Index = (Amount < 256*1024 ? 8 : 9);
-  CommandSizeBuckets[Index]++;
+static inline void BusLogic_IncrementSizeBucket(BusLogic_CommandSizeBuckets_T CommandSizeBuckets, unsigned int Amount)
+{
+	int Index = 0;
+	if (Amount < 8 * 1024) {
+		if (Amount < 2 * 1024)
+			Index = (Amount < 1 * 1024 ? 0 : 1);
+		else
+			Index = (Amount < 4 * 1024 ? 2 : 3);
+	} else if (Amount < 128 * 1024) {
+		if (Amount < 32 * 1024)
+			Index = (Amount < 16 * 1024 ? 4 : 5);
+		else
+			Index = (Amount < 64 * 1024 ? 6 : 7);
+	} else
+		Index = (Amount < 256 * 1024 ? 8 : 9);
+	CommandSizeBuckets[Index]++;
 }
 
 /*
@@ -1450,20 +1388,14 @@ static inline void BusLogic_IncrementSizeBucket(BusLogic_CommandSizeBuckets_T
 static const char *BusLogic_DriverInfo(struct Scsi_Host *);
 static int BusLogic_DetectHostAdapter(struct scsi_host_template *);
 static int BusLogic_ReleaseHostAdapter(struct Scsi_Host *);
-static int BusLogic_QueueCommand(struct scsi_cmnd *,
-				 void (*CompletionRoutine)(struct scsi_cmnd *));
-static int BusLogic_BIOSDiskParameters(struct scsi_device *,
-				       struct block_device *,
-				       sector_t, int *);
-static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *, char *,
-				      char **, off_t, int, int);
+static int BusLogic_QueueCommand(struct scsi_cmnd *, void (*CompletionRoutine) (struct scsi_cmnd *));
+static int BusLogic_BIOSDiskParameters(struct scsi_device *, struct block_device *, sector_t, int *);
+static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *, char *, char **, off_t, int, int);
 static int BusLogic_SlaveConfigure(struct scsi_device *);
 static void BusLogic_QueueCompletedCCB(struct BusLogic_CCB *);
 static irqreturn_t BusLogic_InterruptHandler(int, void *, struct pt_regs *);
-static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *,
-				     boolean HardReset);
-static void BusLogic_Message(enum BusLogic_MessageLevel, char *,
-			     struct BusLogic_HostAdapter *, ...);
+static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *, boolean HardReset);
+static void BusLogic_Message(enum BusLogic_MessageLevel, char *, struct BusLogic_HostAdapter *, ...);
 static int __init BusLogic_Setup(char *);
 
-#endif /* _BUSLOGIC_H */
+#endif				/* _BUSLOGIC_H */
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 711865972..60015656c 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -320,7 +320,7 @@ source "drivers/scsi/aic7xxx/Kconfig.aic7xxx"
 
 config SCSI_AIC7XXX_OLD
 	tristate "Adaptec AIC7xxx support (old driver)"
-	depends on SCSI
+	depends on (ISA || EISA || PCI ) && SCSI
 	help
 	  WARNING This driver is an older aic7xxx driver and is no longer
 	  under active development.  Adaptec, Inc. is writing a new driver to
@@ -395,15 +395,7 @@ config SCSI_IN2000
 	  To compile this driver as a module, choose M here: the
 	  module will be called in2000.
 
-config SCSI_MEGARAID
-	tristate "AMI MegaRAID support"
-	depends on PCI && SCSI
-	help
-	  This driver supports the AMI MegaRAID 418, 428, 438, 466, 762, 490
-	  and 467 SCSI host adapters.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called megaraid.
+source "drivers/scsi/megaraid/Kconfig.megaraid"
 
 config SCSI_SATA
 	bool "Serial ATA (SATA) support"
@@ -595,7 +587,7 @@ config SCSI_EATA_MAX_TAGS
 
 config SCSI_EATA_PIO
 	tristate "EATA-PIO (old DPT PM2001, PM2012A) support"
-	depends on SCSI
+	depends on (ISA || EISA || PCI) && SCSI
 	---help---
 	  This driver supports all EATA-PIO protocol compliant SCSI Host
 	  Adapters like the DPT PM2001 and the PM2012A.  EATA-DMA compliant
@@ -780,6 +772,15 @@ config SCSI_IPS
 	  To compile this driver as a module, choose M here: the
 	  module will be called ips.
 
+config SCSI_IBMVSCSI
+	tristate "IBM Virtual SCSI support"
+	depends on PPC_PSERIES || PPC_ISERIES
+	help
+	  This is the IBM POWER Virtual SCSI Client
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ibmvscsic.
+
 config SCSI_INITIO
 	tristate "Initio 9100U(W) support"
 	depends on PCI && SCSI && BROKEN
@@ -1462,7 +1463,7 @@ config SCSI_DEBUG
 
 config SCSI_MESH
 	tristate "MESH (Power Mac internal SCSI) support"
-	depends on PPC_PMAC && SCSI
+	depends on PPC32 && PPC_PMAC && SCSI
 	help
 	  Many Power Macintoshes and clones have a MESH (Macintosh Enhanced
 	  SCSI Hardware) SCSI bus adaptor (the 7200 doesn't, but all of the
@@ -1507,7 +1508,7 @@ source "drivers/scsi/arm/Kconfig"
 
 config JAZZ_ESP
 	bool "MIPS JAZZ FAS216 SCSI support"
-	depends on MIPS_JAZZ && SCSI
+	depends on MACH_JAZZ && SCSI
 	help
 	  This is the driver for the onboard SCSI host adapter of MIPS Magnum
 	  4000, Acer PICA, Olivetti M700-10 and a few other identical OEM
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 7aebabba4..4173562d0 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -95,7 +95,8 @@ obj-$(CONFIG_SCSI_IBMMCA)	+= ibmmca.o
 obj-$(CONFIG_SCSI_EATA)		+= eata.o
 obj-$(CONFIG_SCSI_DC395x)	+= dc395x.o
 obj-$(CONFIG_SCSI_DC390T)	+= tmscsim.o
-obj-$(CONFIG_SCSI_MEGARAID)	+= megaraid.o
+obj-$(CONFIG_MEGARAID_LEGACY)	+= megaraid.o
+obj-$(CONFIG_MEGARAID_NEWGEN)	+= megaraid/
 obj-$(CONFIG_SCSI_ACARD)	+= atp870u.o
 obj-$(CONFIG_SCSI_SUNESP)	+= esp.o
 obj-$(CONFIG_SCSI_GDTH)		+= gdth.o
@@ -119,6 +120,7 @@ obj-$(CONFIG_SCSI_CPQFCTS)	+= cpqfc.o
 obj-$(CONFIG_SCSI_LASI700)	+= 53c700.o lasi700.o
 obj-$(CONFIG_SCSI_NSP32)	+= nsp32.o
 obj-$(CONFIG_SCSI_IPR)		+= ipr.o
+obj-$(CONFIG_SCSI_IBMVSCSI)	+= ibmvscsi/
 obj-$(CONFIG_SCSI_SATA_SVW)	+= libata.o sata_svw.o
 obj-$(CONFIG_SCSI_ATA_PIIX)	+= libata.o ata_piix.o
 obj-$(CONFIG_SCSI_SATA_PROMISE)	+= libata.o sata_promise.o
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index e3bb9dde6..2032b6230 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -310,12 +310,8 @@
  * possible) function may be used.  Before the specific driver initialization
  * code finishes, NCR5380_print_options should be called.
  */
-
 static int do_abort(struct Scsi_Host *host);
 static void do_reset(struct Scsi_Host *host);
-static struct NCR5380_hostdata *first_host = NULL;
-static struct NCR5380_hostdata *last_host = NULL;
-static struct timer_list usleep_timer;
 
 /*
  *	initialize_SCp		-	init the scsi pointer field
@@ -533,9 +529,6 @@ static void NCR5380_print_phase(struct Scsi_Host *instance)
 #define USLEEP_WAITLONG USLEEP_SLEEP
 #endif
 
-static struct Scsi_Host *expires_first = NULL;
-static spinlock_t timer_lock;	/* Guards expires list */
-
 /* 
  * Function : int should_disconnect (unsigned char cmd)
  *
@@ -578,90 +571,10 @@ static int should_disconnect(unsigned char cmd)
 	}
 }
 
-/*
- * Assumes instance->time_expires has been set in higher level code.
- * We should move to a timer per host
- *
- * Locks: Takes the timer queue lock
- */
-
-static int NCR5380_set_timer(struct Scsi_Host *instance)
-{
-	struct Scsi_Host *tmp, **prev;
-	unsigned long flags;
-
-	if (((struct NCR5380_hostdata *) (instance->hostdata))->next_timer) {
-		return -1;
-	}
-	
-	spin_lock_irqsave(&timer_lock, flags);
-	for (prev = &expires_first, tmp = expires_first; tmp; prev = &(((struct NCR5380_hostdata *) tmp->hostdata)->next_timer), tmp = ((struct NCR5380_hostdata *) tmp->hostdata)->next_timer)
-		if (((struct NCR5380_hostdata *) instance->hostdata)->time_expires < ((struct NCR5380_hostdata *) tmp->hostdata)->time_expires)
-			break;
-
-	((struct NCR5380_hostdata *) instance->hostdata)->next_timer = tmp;
-	*prev = instance;
-
-	mod_timer(&usleep_timer, ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires);
-	
-	spin_unlock_irqrestore(&timer_lock, flags);
-	return 0;
-}
-
-/**
- *	NCR5380_timer_fn	-	handle polled timeouts
- *	@unused: unused
- *
- *	Walk the list of controllers, find which controllers have exceeded
- *	their expiry timeout and then schedule the processing co-routine to
- *	do the real work.
- *
- *	Doing something about unwanted reentrancy here might be useful 
- *
- *	Locks: disables irqs, takes and frees the timer lock
- */
- 
-static void NCR5380_timer_fn(unsigned long unused)
-{
-	struct Scsi_Host *instance;
-	struct NCR5380_hostdata *hostdata;
-	unsigned long flags;
-
-	spin_lock_irqsave(&timer_lock, flags);
-	for (; expires_first && time_before_eq(((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires, jiffies);) 
-	{
-		hostdata = (struct NCR5380_hostdata *) expires_first->hostdata;
-		schedule_work(&hostdata->coroutine);
-		instance = hostdata->next_timer;
-		hostdata->next_timer = NULL;
-		hostdata->time_expires = 0;
-		expires_first = instance;
-	}
-
-	del_timer(&usleep_timer);
-	if (expires_first) {
-		usleep_timer.expires = ((struct NCR5380_hostdata *) expires_first->hostdata)->time_expires;
-		add_timer(&usleep_timer);
-	}
-	spin_unlock_irqrestore(&timer_lock, flags);
-}
-
-/**
- *	NCR5380_all_init	-	global setup
- *
- *	Set up the global values and timers needed by the NCR5380 driver
- */
- 
-static inline void NCR5380_all_init(void)
+static void NCR5380_set_timer(struct NCR5380_hostdata *hostdata, unsigned long timeout)
 {
-	static int done = 0;
-	if (!done) {
-		dprintk(NDEBUG_INIT, ("scsi : NCR5380_all_init()\n"));
-		done = 1;
-		init_timer(&usleep_timer);
-		spin_lock_init(&timer_lock);
-		usleep_timer.function = NCR5380_timer_fn;
-	}
+	hostdata->time_expires = jiffies + timeout;
+	schedule_delayed_work(&hostdata->coroutine, hostdata->time_expires);
 }
 
 
@@ -787,22 +700,6 @@ static void __init NCR5380_print_options(struct Scsi_Host *instance)
 	}
 }
 
-/**
- *	NCR5380_coroutine_running	-	coroutine status
- *	@instance: controller to check
- *
- *	Return true if the co-routine for this controller is running
- *	or scheduled to run
- *
- *	FIXME: this test function belongs in the workqueue code!
- */
- 
-static int NCR5380_coroutine_running(struct Scsi_Host *instance)
-{
-	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)instance->hostdata;
-	return test_bit(0, &hostdata->coroutine.pending);
-}
-
 /**
  *	NCR5380_print_status 	-	dump controller info
  *	@instance: controller to dump
@@ -819,8 +716,6 @@ static void NCR5380_print_status(struct Scsi_Host *instance)
 	char *start;
 	int len;
 
-	printk("NCR5380 : coroutine is%s running.\n",  NCR5380_coroutine_running(instance)? "" : "n't");
-
 	NCR5380_dprint(NDEBUG_ANY, instance);
 	NCR5380_dprint_phase(NDEBUG_ANY, instance);
 
@@ -900,7 +795,6 @@ int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start, of
 	SPRINTF("Highwater I/O busy_spin_counts -- write: %d  read: %d\n", pas_wmaxi, pas_maxi);
 #endif
 	spin_lock_irq(instance->host_lock);
-	SPRINTF("NCR5380 : coroutine is%s running.\n", NCR5380_coroutine_running(instance) ? "" : "n't");
 	if (!hostdata->connected)
 		SPRINTF("scsi%d: no currently connected command\n", instance->host_no);
 	else
@@ -912,7 +806,6 @@ int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start, of
 	SPRINTF("scsi%d: disconnected_queue\n", instance->host_no);
 	for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
 		pos = lprint_Scsi_Cmnd(ptr, pos, buffer, length);
-
 	spin_unlock_irq(instance->host_lock);
 	
 	*start = buffer;
@@ -964,7 +857,7 @@ static char *lprint_opcode(int opcode, char *pos, char *buffer, int length)
  *	Locks: interrupts must be enabled when we are called 
  */
 
-static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
+static int __devinit NCR5380_init(struct Scsi_Host *instance, int flags)
 {
 	NCR5380_local_declare();
 	int i, pass;
@@ -984,7 +877,6 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
 #endif
 
 	NCR5380_setup(instance);
-	NCR5380_all_init();
 
 	hostdata->aborted = 0;
 	hostdata->id_mask = 1 << instance->this_id;
@@ -1021,18 +913,8 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
 	else
 		hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT | flags;
 
-	hostdata->next = NULL;
-	
-	if (!first_host)
-		first_host = hostdata;
-	else
-		last_host->next = hostdata;
-
-	last_host = hostdata;
-	
 	hostdata->host = instance;
 	hostdata->time_expires = 0;
-	hostdata->next_timer = NULL;
 
 #ifndef AUTOSENSE
 	if ((instance->cmd_per_lun > 1) || instance->can_queue > 1)
@@ -1088,6 +970,19 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
 	return 0;
 }
 
+/**
+ *	NCR5380_exit	-	remove an NCR5380
+ *	@instance: adapter to remove
+ */
+
+static void __devexit NCR5380_exit(struct Scsi_Host *instance)
+{
+	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
+
+	cancel_delayed_work(&hostdata->coroutine);
+	flush_scheduled_work();
+}
+
 /**
  *	NCR5380_queue_command 		-	queue a command
  *	@cmd: SCSI command
@@ -1169,6 +1064,7 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 	return 0;
 }
 
+
 /**
  *	NCR5380_main	-	NCR state machines
  *
@@ -1184,28 +1080,11 @@ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
 static void NCR5380_main(void *p)
 {
 	struct NCR5380_hostdata *hostdata = p;
+	struct Scsi_Host *instance = hostdata->host;
 	Scsi_Cmnd *tmp, *prev;
-	struct Scsi_Host *instance;
 	int done;
-	unsigned long flags = 0;
 	
-	/*
-	 * 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 can exit
-	 *
-	 * Interrupts are enabled before doing various other internal 
-	 * instructions, after we've decided that we need to run through
-	 * the loop again.
-	 *
-	 * this should prevent any race conditions.
-	 */
-
-	instance = hostdata->host;
-
-	if(instance->irq != SCSI_IRQ_NONE)
-		spin_lock_irqsave(instance->host_lock, flags);
-
+	spin_lock_irq(instance->host_lock);
 	do {
 		/* Lock held here */
 		done = 1;
@@ -1286,8 +1165,7 @@ static void NCR5380_main(void *p)
 				LIST(tmp, hostdata->issue_queue);
 				tmp->host_scribble = (unsigned char *) hostdata->issue_queue;
 				hostdata->issue_queue = tmp;
-				hostdata->time_expires = jiffies + USLEEP_WAITLONG;
-				NCR5380_set_timer(instance);
+				NCR5380_set_timer(hostdata, USLEEP_WAITLONG);
 			}
 		}	/* if hostdata->selecting */
 		if (hostdata->connected
@@ -1304,8 +1182,7 @@ static void NCR5380_main(void *p)
 			break;
 	} while (!done);
 	
-	if(instance->irq != SCSI_IRQ_NONE)
-		spin_unlock_irqrestore(instance->host_lock, flags);
+	spin_unlock_irq(instance->host_lock);
 }
 
 #ifndef DONT_USE_INTR
@@ -1330,12 +1207,13 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs)
 	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 	int done;
 	unsigned char basr;
+	unsigned long flags;
 
 	dprintk(NDEBUG_INTR, ("scsi : NCR5380 irq %d triggered\n", irq));
 
 	do {
 		done = 1;
-		spin_lock_irq(instance->host_lock);
+		spin_lock_irqsave(instance->host_lock, flags);
 		/* Look for pending interrupts */
 		NCR5380_setup(instance);
 		basr = NCR5380_read(BUS_AND_STATUS_REG);
@@ -1386,7 +1264,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs)
 #endif
 			}
 		}	/* if BASR_IRQ */
-		spin_unlock_irq(instance->host_lock);
+		spin_unlock_irqrestore(instance->host_lock, flags);
 		if(!done)
 			schedule_work(&hostdata->coroutine);
 	} while (!done);
@@ -1469,12 +1347,8 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
 	int err;
 	NCR5380_setup(instance);
 
-	if (hostdata->selecting) {
-		if(instance->irq != SCSI_IRQ_NONE)
-			spin_unlock_irq(instance->host_lock);
-		goto part2;	/* RvC: sorry prof. Dijkstra, but it keeps the
-				   rest of the code nearly the same */
-	}
+	if (hostdata->selecting)
+		goto part2;
 
 	hostdata->restart_select = 0;
 
@@ -1495,16 +1369,12 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag)
 	NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
 	NCR5380_write(MODE_REG, MR_ARBITRATE);
 
-	if(instance->irq != SCSI_IRQ_NONE)
-		spin_unlock_irq(instance->host_lock);
 
 	/* We can be relaxed here, interrupts are on, we are
 	   in workqueue context, the birds are singing in the trees */
-
+	spin_unlock_irq(instance->host_lock);
 	err = NCR5380_poll_politely(instance, INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS, ICR_ARBITRATION_PROGRESS, 5*HZ);
-	if(instance->irq != SCSI_IRQ_NONE)
-		spin_lock_irq(instance->host_lock);
-
+	spin_lock_irq(instance->host_lock);
 	if (err < 0) {
 		printk(KERN_DEBUG "scsi: arbitration timeout at %d\n", __LINE__);
 		NCR5380_write(MODE_REG, MR_BASE);
@@ -1628,8 +1498,7 @@ part2:
 	if (!value && (hostdata->select_time < HZ/4)) {
 		/* RvC: we still must wait for a device response */
 		hostdata->select_time++;	/* after 25 ticks the device has failed */
-		hostdata->time_expires = jiffies + 1;
-		NCR5380_set_timer(instance);
+		NCR5380_set_timer(hostdata, 1);
 		return 0;	/* RvC: we return here with hostdata->selecting set,
 				   to go to sleep */
 	}
@@ -1638,8 +1507,6 @@ part2:
 					   waiting period */
 	if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
 		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-		if(instance->irq != SCSI_IRQ_NONE)
-			spin_lock_irq(instance->host_lock);
 		NCR5380_reselect(instance);
 		printk("scsi%d : reselection after won arbitration?\n", instance->host_no);
 		NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
@@ -1665,8 +1532,6 @@ part2:
 			NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
 			return -1;
 		}
-		if(instance->irq != SCSI_IRQ_NONE)
-			spin_lock_irq(instance->host_lock);
 		cmd->result = DID_BAD_TARGET << 16;
 		collect_stats(hostdata, cmd);
 		cmd->scsi_done(cmd);
@@ -1693,11 +1558,13 @@ part2:
 	 */
 
 	/* Wait for start of REQ/ACK handshake */
-	
+
+	spin_unlock_irq(instance->host_lock);
 	err = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ);
+	spin_lock_irq(instance->host_lock);
 	
-	if(err)
-	{	printk(KERN_ERR "scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__);
+	if(err) {
+		printk(KERN_ERR "scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__);
 		NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
 		goto failed;
 	}
@@ -1705,9 +1572,6 @@ part2:
 	dprintk(NDEBUG_SELECTION, ("scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->device->id));
 	tmp[0] = IDENTIFY(((instance->irq == SCSI_IRQ_NONE) ? 0 : 1), cmd->device->lun);
 
-	if(instance->irq != SCSI_IRQ_NONE)
-		spin_lock_irq(instance->host_lock);
-		
 	len = 1;
 	cmd->tag = 0;
 
@@ -1720,15 +1584,14 @@ part2:
 	hostdata->connected = cmd;
 	hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
 
-	initialize_SCp(cmd);
-
+	if (cmd->SCp.ptr != (char *)cmd->sense_buffer) {
+		initialize_SCp(cmd);
+	}
 
 	return 0;
 
 	/* Selection failed */
 failed:
-	if(instance->irq != SCSI_IRQ_NONE)
-		spin_lock_irq(instance->host_lock);
 	return -1;
 
 }
@@ -1804,8 +1667,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase
 		while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ) && !break_allowed);
 		if (!(tmp & SR_REQ)) {
 			/* timeout condition */
-			hostdata->time_expires = jiffies + USLEEP_SLEEP;
-			NCR5380_set_timer(instance);
+			NCR5380_set_timer(hostdata, USLEEP_SLEEP);
 			break;
 		}
 
@@ -2643,9 +2505,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
 				 */
 				NCR5380_transfer_pio(instance, &phase, &len, &data);
 				if (!cmd->device->disconnect && should_disconnect(cmd->cmnd[0])) {
-					hostdata->time_expires = jiffies + USLEEP_SLEEP;
+					NCR5380_set_timer(hostdata, USLEEP_SLEEP);
 					dprintk(NDEBUG_USLEEP, ("scsi%d : issued command, sleeping until %ul\n", instance->host_no, hostdata->time_expires));
-					NCR5380_set_timer(instance);
 					return;
 				}
 				break;
@@ -2664,9 +2525,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
 			/* RvC: go to sleep if polling time expired
 			 */
 			if (!cmd->device->disconnect && time_after_eq(jiffies, poll_time)) {
-				hostdata->time_expires = jiffies + USLEEP_SLEEP;
+				NCR5380_set_timer(hostdata, USLEEP_SLEEP);
 				dprintk(NDEBUG_USLEEP, ("scsi%d : poll timed out, sleeping until %ul\n", instance->host_no, hostdata->time_expires));
-				NCR5380_set_timer(instance);
 				return;
 			}
 		}
diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
index 321540cb4..b5103f94d 100644
--- a/drivers/scsi/NCR5380.h
+++ b/drivers/scsi/NCR5380.h
@@ -251,7 +251,6 @@
 struct NCR5380_hostdata {
 	NCR5380_implementation_fields;		/* implementation specific */
 	struct Scsi_Host *host;			/* Host backpointer */
-	struct NCR5380_hostdata *next;		/* Next in our hot chain */
 	unsigned char id_mask, id_higher_mask;	/* 1 << id, all bits greater */
 	unsigned char targets_present;		/* targets we have connected
 						   to, so we can call a select
@@ -270,7 +269,6 @@ struct NCR5380_hostdata {
 	volatile unsigned aborted:1;		/* flag, says aborted */
 	int flags;
 	unsigned long time_expires;		/* in jiffies, set prior to sleeping */
-	struct Scsi_Host *next_timer;
 	int select_time;			/* timer in select for target response */
 	volatile Scsi_Cmnd *selecting;
 	struct work_struct coroutine;		/* our co-routine */
@@ -295,6 +293,7 @@ struct NCR5380_hostdata {
 static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible);
 #endif
 static int NCR5380_init(struct Scsi_Host *instance, int flags);
+static void NCR5380_exit(struct Scsi_Host *instance);
 static void NCR5380_information_transfer(struct Scsi_Host *instance);
 #ifndef DONT_USE_INTR
 static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs);
diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
index 9f70a7b0b..9cd6f27d7 100644
--- a/drivers/scsi/NCR53C9x.c
+++ b/drivers/scsi/NCR53C9x.c
@@ -94,7 +94,7 @@ enum {
 };
 
 /* The master ring of all esp hosts we are managing in this driver. */
-struct NCR_ESP *espchain = 0;
+struct NCR_ESP *espchain;
 int nesps = 0, esps_in_use = 0, esps_running = 0;
 
 irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
@@ -555,7 +555,7 @@ struct NCR_ESP* esp_allocate(Scsi_Host_Template *tpnt, void *esp_dev)
 	} else {
 		espchain = esp;
 	}
-	esp->next = 0;
+	esp->next = NULL;
 
 	return esp;
 }
@@ -565,7 +565,7 @@ void esp_deallocate(struct NCR_ESP *esp)
 	struct NCR_ESP *elink;
 
 	if(espchain == esp) {
-		espchain = 0;
+		espchain = NULL;
 	} else {
 		for(elink = espchain; elink && (elink->next != esp); elink = elink->next);
 		if(elink) 
@@ -708,9 +708,9 @@ void esp_initialize(struct NCR_ESP *esp)
 	}				
 
 	/* Initialize the command queues */
-	esp->current_SC = 0;
-	esp->disconnected_SC = 0;
-	esp->issue_SC = 0;
+	esp->current_SC = NULL;
+	esp->disconnected_SC = NULL;
+	esp->issue_SC = NULL;
 
 	/* Clear the state machines. */
 	esp->targets_present = 0;
@@ -1728,7 +1728,7 @@ static inline void esp_reconnect(struct NCR_ESP *esp, Scsi_Cmnd *sp)
 		ESPLOG(("esp%d: Weird, being reselected but disconnected "
 			"command queue is empty.\n", esp->esp_id));
 	esp->snip = 0;
-	esp->current_SC = 0;
+	esp->current_SC = NULL;
 	sp->SCp.phase = not_issued;
 	append_SC(&esp->issue_SC, sp);
 }
@@ -3393,7 +3393,7 @@ static int esp_work_bus(struct NCR_ESP *esp, struct ESP_regs *eregs)
 }
 
 static espfunc_t isvc_vector[] = {
-	0,
+	NULL,
 	esp_do_phase_determine,
 	esp_do_resetbus,
 	esp_finish_reset,
diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
index 3f457dc1b..c407e8643 100644
--- a/drivers/scsi/NCR53c406a.c
+++ b/drivers/scsi/NCR53c406a.c
@@ -606,22 +606,24 @@ static int NCR53c406a_release(struct Scsi_Host *shost)
 }
 
 /* called from init/main.c */
-static void __init NCR53c406a_setup(char *str, int *ints)
+static int __init NCR53c406a_setup(char *str)
 {
 	static size_t setup_idx = 0;
 	size_t i;
+	int ints[4];
 
 	DEB(printk("NCR53c406a: Setup called\n");
 	    );
 
 	if (setup_idx >= PORT_COUNT - 1) {
 		printk("NCR53c406a: Setup called too many times.  Bad LILO params?\n");
-		return;
+		return 0;
 	}
+	get_options(str, 4, ints);
 	if (ints[0] < 1 || ints[0] > 3) {
 		printk("NCR53c406a: Malformed command line\n");
 		printk("NCR53c406a: Usage: ncr53c406a=<PORTBASE>[,<IRQ>[,<FASTPIO>]]\n");
-		return;
+		return 0;
 	}
 	for (i = 0; i < PORT_COUNT && !port_base; i++)
 		if (ports[i] == ints[1]) {
@@ -631,7 +633,7 @@ static void __init NCR53c406a_setup(char *str, int *ints)
 		}
 	if (!port_base) {
 		printk("NCR53c406a: Invalid PORTBASE 0x%x specified\n", ints[1]);
-		return;
+		return 0;
 	}
 
 	if (ints[0] > 1) {
@@ -654,6 +656,7 @@ static void __init NCR53c406a_setup(char *str, int *ints)
 		fast_pio = ints[3];
 
 	DEB(printk("NCR53c406a: port_base=0x%x, irq=%d, fast_pio=%d\n", port_base, irq_level, fast_pio);)
+	return 1;
 }
 
 __setup("ncr53c406a=", NCR53c406a_setup);
diff --git a/drivers/scsi/NCR_Q720.c b/drivers/scsi/NCR_Q720.c
index d47a86ef5..862014d7b 100644
--- a/drivers/scsi/NCR_Q720.c
+++ b/drivers/scsi/NCR_Q720.c
@@ -216,7 +216,21 @@ NCR_Q720_probe(struct device *dev)
 		goto out_free;
 	}
 	
-	mem_base = (__u32)ioremap(base_addr, mem_size);
+	if (dma_declare_coherent_memory(dev, base_addr, base_addr,
+					mem_size, DMA_MEMORY_MAP)
+	    != DMA_MEMORY_MAP) {
+		printk(KERN_ERR "NCR_Q720: DMA declare memory failed\n");
+		goto out_release_region;
+	}
+
+	/* The first 1k of the memory buffer is a memory map of the registers
+	 */
+	mem_base = (__u32)dma_mark_declared_memory_occupied(dev, base_addr,
+							    1024);
+	if (IS_ERR((void *)mem_base)) {
+		printk("NCR_Q720 failed to reserve memory mapped region\n");
+		goto out_release;
+	}
 
 	/* now also enable accesses in asr 2 */
 	asr2 = inb(io_base + 0x0a);
@@ -296,7 +310,8 @@ NCR_Q720_probe(struct device *dev)
 	return 0;
 
  out_release:
-	iounmap((void *)mem_base);
+	dma_release_declared_memory(dev);
+ out_release_region:
 	release_mem_region(base_addr, mem_size);
  out_free:
 	kfree(p);
@@ -321,7 +336,7 @@ NCR_Q720_remove(struct device *dev)
 		if(p->hosts[i])
 			NCR_Q720_remove_one(p->hosts[i]);
 
-	iounmap((void *)p->mem_base);
+	dma_release_declared_memory(dev);
 	release_mem_region(p->phys_mem_base, p->mem_size);
 	free_irq(p->irq, p);
 	kfree(p);
diff --git a/drivers/scsi/aacraid/README b/drivers/scsi/aacraid/README
index 6abbe026b..52015523c 100644
--- a/drivers/scsi/aacraid/README
+++ b/drivers/scsi/aacraid/README
@@ -10,14 +10,23 @@ the original).
 
 Supported Cards/Chipsets
 -------------------------
-	AAR-2410SA SATA
+	Adaptec 2020S
+	Adaptec 2025S
 	Adaptec 2120S
 	Adaptec 2200S
 	Adaptec 2230S
+	Adaptec 2240S
+	Adaptec 2410SA
+	Adaptec 2610SA
+	Adaptec 2810SA
+	Adaptec 21610SA
 	Adaptec 3230S
 	Adaptec 3240S
+	Adaptec 4000SAS
+	Adaptec 4005SAS
+	Adaptec 4800SAS
+	Adaptec 4805SAS
 	Adaptec 5400S
-	ASR-2020S PCI-X
 	Dell PERC 2 Quad Channel
 	Dell PERC 2/Si
 	Dell PERC 3/Si
@@ -49,7 +58,6 @@ Adaptec Unix OEM Product Group
 Mailing List
 -------------------------
 linux-scsi@vger.kernel.org (Interested parties troll here)
-http://mbserver.adaptec.com/ (Currently more Community Support than Devel Support)
 Also note this is very different to Brian's original driver
 so don't expect him to support it.
 Adaptec does support this driver.  Contact either tech support or Mark Salyzyn.
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 7b02a48a2..bb03a95fa 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -179,6 +179,20 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd);
 static char *aac_get_status_string(u32 status);
 #endif
 
+/*
+ *	Non dasd selection is handled entirely in aachba now
+ */	
+ 
+MODULE_PARM(nondasd, "i");
+MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on");
+MODULE_PARM(dacmode, "i");
+MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC. 0=off, 1=on");
+MODULE_PARM(commit, "i");
+MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the adapter for foreign arrays.\nThis is typically needed in systems that do not have a BIOS. 0=off, 1=on");
+
+static int nondasd = -1;
+static int dacmode = -1;
+
 /**
  *	aac_get_containers	-	list containers
  *	@common: adapter to probe
@@ -481,8 +495,7 @@ int aac_get_adapter_info(struct aac_dev* dev)
 
 	dev->nondasd_support = 0;
 	if(dev->adapter_info.options & AAC_OPT_NONDASD){
-//		dev->nondasd_support = 1;
-// dmb - temporarily disable nondasd
+		dev->nondasd_support = 1;
 	}
 	if(nondasd != -1) {  
 		dev->nondasd_support = (nondasd!=0);
@@ -491,18 +504,30 @@ int aac_get_adapter_info(struct aac_dev* dev)
 		printk(KERN_INFO "%s%d: Non-DASD support enabled.\n",dev->name, dev->id);
 	}
 
-	dev->pae_support = 0;
+	dev->dac_support = 0;
 	if( (sizeof(dma_addr_t) > 4) && (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)){
 		printk(KERN_INFO "%s%d: 64bit support enabled.\n", dev->name, dev->id);
-		dev->pae_support = 1;
+		dev->dac_support = 1;
 	}
 
-	if(paemode != -1){
-		dev->pae_support = (paemode!=0);
+	if(dacmode != -1) {
+		dev->dac_support = (dacmode!=0);
 	}
-	if(dev->pae_support != 0) {
-		printk(KERN_INFO"%s%d: 64 Bit PAE enabled\n", dev->name, dev->id);
-		pci_set_dma_mask(dev->pdev, (dma_addr_t)0xFFFFFFFFFFFFFFFFULL);
+	if(dev->dac_support != 0) {
+		if (!pci_set_dma_mask(dev->pdev, 0xFFFFFFFFFFFFFFFFULL) &&
+			!pci_set_consistent_dma_mask(dev->pdev, 0xFFFFFFFFFFFFFFFFULL)) {
+			printk(KERN_INFO"%s%d: 64 Bit DAC enabled\n",
+				dev->name, dev->id);
+		} else if (!pci_set_dma_mask(dev->pdev, 0xFFFFFFFFULL) &&
+			!pci_set_consistent_dma_mask(dev->pdev, 0xFFFFFFFFULL)) {
+			printk(KERN_INFO"%s%d: DMA mask set failed, 64 Bit DAC disabled\n",
+				dev->name, dev->id);
+			dev->dac_support = 0;
+		} else {
+			printk(KERN_WARNING"%s%d: No suitable DMA available.\n",
+				dev->name, dev->id);
+			rcode = -ENOMEM;
+		}
 	}
 
 	fib_complete(fibptr);
@@ -537,7 +562,7 @@ static void read_callback(void *context, struct fib * fibptr)
 			scsicmd->use_sg,
 			scsicmd->sc_data_direction);
 	else if(scsicmd->request_bufflen)
-		pci_unmap_single(dev->pdev, (dma_addr_t)(ulong)scsicmd->SCp.ptr,
+		pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle,
 				 scsicmd->request_bufflen,
 				 scsicmd->sc_data_direction);
 	readreply = (struct aac_read_reply *)fib_data(fibptr);
@@ -582,7 +607,7 @@ static void write_callback(void *context, struct fib * fibptr)
 			scsicmd->use_sg,
 			scsicmd->sc_data_direction);
 	else if(scsicmd->request_bufflen)
-		pci_unmap_single(dev->pdev, (dma_addr_t)(ulong)scsicmd->SCp.ptr,
+		pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle,
 				 scsicmd->request_bufflen,
 				 scsicmd->sc_data_direction);
 
@@ -644,7 +669,7 @@ int aac_read(struct scsi_cmnd * scsicmd, int cid)
 
 	fib_init(cmd_fibcontext);
 
-	if(dev->pae_support == 1){
+	if(dev->dac_support == 1) {
 		struct aac_read64 *readcmd;
 		readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext);
 		readcmd->command = cpu_to_le32(VM_CtHostRead64);
@@ -752,7 +777,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
 	}
 	fib_init(cmd_fibcontext);
 
-	if(dev->pae_support == 1){
+	if(dev->dac_support == 1) {
 		struct aac_write64 *writecmd;
 		writecmd = (struct aac_write64 *) fib_data(cmd_fibcontext);
 		writecmd->command = cpu_to_le32(VM_CtHostWrite64);
@@ -1220,7 +1245,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
 			scsicmd->use_sg,
 			scsicmd->sc_data_direction);
 	else if(scsicmd->request_bufflen)
-		pci_unmap_single(dev->pdev, (ulong)scsicmd->SCp.ptr, scsicmd->request_bufflen,
+		pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle, scsicmd->request_bufflen,
 			scsicmd->sc_data_direction);
 
 	/*
@@ -1348,7 +1373,12 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
 	case SRB_STATUS_DOMAIN_VALIDATION_FAIL:
 	default:
 #ifdef AAC_DETAILED_STATUS_INFO
-		printk("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n",le32_to_cpu(srbreply->srb_status&0x3f),aac_get_status_string(le32_to_cpu(srbreply->srb_status)), scsicmd->cmnd[0], le32_to_cpu(srbreply->scsi_status) );
+		printk("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n",
+			le32_to_cpu(srbreply->srb_status & 0x3F),
+			aac_get_status_string(
+				le32_to_cpu(srbreply->srb_status) & 0x3F), 
+			scsicmd->cmnd[0], 
+			le32_to_cpu(srbreply->scsi_status));
 #endif
 		scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
 		break;
@@ -1358,7 +1388,10 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
 		scsicmd->result |= SAM_STAT_CHECK_CONDITION;
 		len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))?
 				sizeof(scsicmd->sense_buffer):srbreply->sense_data_size;
-		dprintk((KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n", le32_to_cpu(srbreply->status), len));
+#ifdef AAC_DETAILED_STATUS_INFO
+		dprintk((KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n", 
+					le32_to_cpu(srbreply->status), len));
+#endif
 		memcpy(scsicmd->sense_buffer, srbreply->sense_data, len);
 		
 	}
@@ -1437,7 +1470,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
 	srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter
 	srbcmd->cdb_size = cpu_to_le32(scsicmd->cmd_len);
 	
-	if( dev->pae_support ==1 ) {
+	if( dev->dac_support == 1 ) {
 		aac_build_sg64(scsicmd, (struct sgmap64*) &srbcmd->sg);
 		srbcmd->count = cpu_to_le32(scsicmd->request_bufflen);
 
@@ -1532,7 +1565,7 @@ static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg)
 		psg->count = cpu_to_le32(1);
 		psg->sg[0].addr = cpu_to_le32(addr);
 		psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);  
-		scsicmd->SCp.ptr = (char *)(ulong)addr;
+		scsicmd->SCp.dma_handle = addr;
 		byte_count = scsicmd->request_bufflen;
 	}
 	return byte_count;
@@ -1593,7 +1626,7 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
 		psg->sg[0].addr[1] = (u32)(le_addr>>32);
 		psg->sg[0].addr[0] = (u32)(le_addr & 0xffffffff);
 		psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);  
-		scsicmd->SCp.ptr = (char *)(ulong)addr;
+		scsicmd->SCp.dma_handle = addr;
 		byte_count = scsicmd->request_bufflen;
 	}
 	return byte_count;
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 8b077f224..20302a3e8 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -28,10 +28,7 @@
 #define aac_phys_to_logical(x)  (x+1)
 #define aac_logical_to_phys(x)  (x?x-1:0)
 
-#define AAC_DETAILED_STATUS_INFO
-
-extern int nondasd;
-extern int paemode;
+/* #define AAC_DETAILED_STATUS_INFO */
 
 struct diskparm
 {
@@ -404,15 +401,15 @@ struct aac_init
 };
 
 enum aac_log_level {
-	LOG_INIT			= 10,
-	LOG_INFORMATIONAL		= 20,
-	LOG_WARNING			= 30,
-	LOG_LOW_ERROR			= 40,
-	LOG_MEDIUM_ERROR		= 50,
-	LOG_HIGH_ERROR			= 60,
-	LOG_PANIC			= 70,
-	LOG_DEBUG			= 80,
-	LOG_WINDBG_PRINT		= 90
+	LOG_AAC_INIT			= 10,
+	LOG_AAC_INFORMATIONAL		= 20,
+	LOG_AAC_WARNING			= 30,
+	LOG_AAC_LOW_ERROR		= 40,
+	LOG_AAC_MEDIUM_ERROR		= 50,
+	LOG_AAC_HIGH_ERROR		= 60,
+	LOG_AAC_PANIC			= 70,
+	LOG_AAC_DEBUG			= 80,
+	LOG_AAC_WINDBG_PRINT		= 90
 };
 
 #define FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT	0x030b
@@ -841,7 +838,7 @@ struct aac_dev
 	 * lets break them out so we don't have to do an AND to check them
 	 */
 	u8			nondasd_support; 
-	u8			pae_support;
+	u8			dac_support;
 };
 
 #define AllocateAndMapFibSpace(dev, MapFibContext) \
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 36ae4af39..7f3a22200 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -480,7 +480,7 @@ int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
 	default:
 		data_dir = DMA_NONE;
 	}
-	if (dev->pae_support == 1) {
+	if (dev->dac_support == 1) {
 		struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg;
 		byte_count = 0;
 
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index b5ac3c270..f53956f77 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -761,7 +761,7 @@ void aac_printf(struct aac_dev *dev, u32 val)
 		length = 255;
 	if (cp[length] != 0)
 		cp[length] = 0;
-	if (level == LOG_HIGH_ERROR)
+	if (level == LOG_AAC_HIGH_ERROR)
 		printk(KERN_WARNING "aacraid:%s", cp);
 	else
 		printk(KERN_INFO "aacraid:%s", cp);
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index c55219142..04a8a571a 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -44,6 +44,7 @@
 #include <linux/spinlock.h>
 #include <linux/syscalls.h>
 #include <linux/ioctl32.h>
+#include <linux/delay.h>
 #include <asm/semaphore.h>
 
 #include <scsi/scsi.h>
@@ -62,15 +63,7 @@ MODULE_DESCRIPTION("Dell PERC2, 2/Si, 3/Si, 3/Di, "
 		   "Adaptec Advanced Raid Products, "
 		   "and HP NetRAID-4M SCSI driver");
 MODULE_LICENSE("GPL");
-
-
-int nondasd = -1;
-module_param(nondasd, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on");
-
-int paemode = -1;
-module_param(paemode, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(paemode, "Control whether dma addressing is using PAE. 0=off, 1=on");
+MODULE_VERSION(AAC_DRIVER_VERSION);
 
 struct aac_dev *aac_devices[MAXIMUM_NUM_ADAPTERS];
 static unsigned aac_count;
@@ -83,44 +76,54 @@ static int aac_cfg_major = -1;
  * Note: The last field is used to index into aac_drivers below.
  */
 static struct pci_device_id aac_pci_tbl[] = {
-	{ 0x1028, 0x0001, 0x1028, 0x0001, 0, 0, 0 }, /* PERC 2/Si */
-	{ 0x1028, 0x0002, 0x1028, 0x0002, 0, 0, 1 }, /* PERC 3/Di */
-	{ 0x1028, 0x0003, 0x1028, 0x0003, 0, 0, 2 }, /* PERC 3/Si */
-	{ 0x1028, 0x0004, 0x1028, 0x00d0, 0, 0, 3 }, /* PERC 3/Si */
-	{ 0x1028, 0x0002, 0x1028, 0x00d1, 0, 0, 4 }, /* PERC 3/Di */
-	{ 0x1028, 0x0002, 0x1028, 0x00d9, 0, 0, 5 }, /* PERC 3/Di */
-	{ 0x1028, 0x000a, 0x1028, 0x0106, 0, 0, 6 }, /* PERC 3/Di */
-	{ 0x1028, 0x000a, 0x1028, 0x011b, 0, 0, 7 }, /* PERC 3/Di */
-	{ 0x1028, 0x000a, 0x1028, 0x0121, 0, 0, 8 }, /* PERC 3/Di */
-	{ 0x9005, 0x0283, 0x9005, 0x0283, 0, 0, 9 }, /* catapult*/
-	{ 0x9005, 0x0284, 0x9005, 0x0284, 0, 0, 10 }, /* tomcat*/
-	{ 0x9005, 0x0285, 0x9005, 0x0286, 0, 0, 11 }, /* Adaptec 2120S (Crusader)*/
-	{ 0x9005, 0x0285, 0x9005, 0x0285, 0, 0, 12 }, /* Adaptec 2200S (Vulcan)*/
-	{ 0x9005, 0x0285, 0x9005, 0x0287, 0, 0, 13 }, /* Adaptec 2200S (Vulcan-2m)*/
-	{ 0x9005, 0x0285, 0x17aa, 0x0286, 0, 0, 14 }, /* Legend S220*/
-	{ 0x9005, 0x0285, 0x17aa, 0x0287, 0, 0, 15 }, /* Legend S230*/
-
-	{ 0x9005, 0x0285, 0x9005, 0x0288, 0, 0, 16 }, /* Adaptec 3230S (Harrier)*/
-	{ 0x9005, 0x0285, 0x9005, 0x0289, 0, 0, 17 }, /* Adaptec 3240S (Tornado)*/
-	{ 0x9005, 0x0285, 0x9005, 0x028a, 0, 0, 18 }, /* ASR-2020 ZCR PCI-X U320 */
-	{ 0x9005, 0x0285, 0x9005, 0x028b, 0, 0, 19 }, /* ASR-2025 ZCR DIMM U320 */
-	{ 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 20 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II)*/
-
-	{ 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 21 }, /* Perc 320/DC*/
-	{ 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 22 }, /* Adaptec 5400S (Mustang)*/
-	{ 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 23 }, /* Adaptec 5400S (Mustang)*/
-	{ 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 24 }, /* Dell PERC2 "Quad Channel" */
-	{ 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 25 }, /* HP NetRAID-4M */
-
+	{ 0x1028, 0x0001, 0x1028, 0x0001, 0, 0, 0 }, /* PERC 2/Si (Iguana/PERC2Si) */
+	{ 0x1028, 0x0002, 0x1028, 0x0002, 0, 0, 1 }, /* PERC 3/Di (Opal/PERC3Di) */
+	{ 0x1028, 0x0003, 0x1028, 0x0003, 0, 0, 2 }, /* PERC 3/Si (SlimFast/PERC3Si */
+	{ 0x1028, 0x0004, 0x1028, 0x00d0, 0, 0, 3 }, /* PERC 3/Di (Iguana FlipChip/PERC3DiF */
+	{ 0x1028, 0x0002, 0x1028, 0x00d1, 0, 0, 4 }, /* PERC 3/Di (Viper/PERC3DiV) */
+	{ 0x1028, 0x0002, 0x1028, 0x00d9, 0, 0, 5 }, /* PERC 3/Di (Lexus/PERC3DiL) */
+	{ 0x1028, 0x000a, 0x1028, 0x0106, 0, 0, 6 }, /* PERC 3/Di (Jaguar/PERC3DiJ) */
+	{ 0x1028, 0x000a, 0x1028, 0x011b, 0, 0, 7 }, /* PERC 3/Di (Dagger/PERC3DiD) */
+	{ 0x1028, 0x000a, 0x1028, 0x0121, 0, 0, 8 }, /* PERC 3/Di (Boxster/PERC3DiB) */
+	{ 0x9005, 0x0283, 0x9005, 0x0283, 0, 0, 9 }, /* catapult */
+	{ 0x9005, 0x0284, 0x9005, 0x0284, 0, 0, 10 }, /* tomcat */
+	{ 0x9005, 0x0285, 0x9005, 0x0286, 0, 0, 11 }, /* Adaptec 2120S (Crusader) */
+	{ 0x9005, 0x0285, 0x9005, 0x0285, 0, 0, 12 }, /* Adaptec 2200S (Vulcan) */
+	{ 0x9005, 0x0285, 0x9005, 0x0287, 0, 0, 13 }, /* Adaptec 2200S (Vulcan-2m) */
+	{ 0x9005, 0x0285, 0x17aa, 0x0286, 0, 0, 14 }, /* Legend S220 (Legend Crusader) */
+	{ 0x9005, 0x0285, 0x17aa, 0x0287, 0, 0, 15 }, /* Legend S230 (Legend Vulcan) */
+
+	{ 0x9005, 0x0285, 0x9005, 0x0288, 0, 0, 16 }, /* Adaptec 3230S (Harrier) */
+	{ 0x9005, 0x0285, 0x9005, 0x0289, 0, 0, 17 }, /* Adaptec 3240S (Tornado) */
+	{ 0x9005, 0x0285, 0x9005, 0x028a, 0, 0, 18 }, /* ASR-2020ZCR SCSI PCI-X ZCR (Skyhawk) */
+	{ 0x9005, 0x0285, 0x9005, 0x028b, 0, 0, 19 }, /* ASR-2025ZCR SCSI SO-DIMM PCI-X ZCR (Terminator) */
+	{ 0x9005, 0x0286, 0x9005, 0x028c, 0, 0, 20 }, /* ASR-2230S + ASR-2230SLP PCI-X (Lancer) */
+	{ 0x9005, 0x0286, 0x9005, 0x028d, 0, 0, 21 }, /* ASR-2130S (Lancer) */
+	{ 0x9005, 0x0286, 0x9005, 0x0800, 0, 0, 22 }, /* Jupiter Platform */
+	{ 0x9005, 0x0285, 0x9005, 0x028e, 0, 0, 23 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */
+	{ 0x9005, 0x0285, 0x9005, 0x028f, 0, 0, 24 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */
+	{ 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 25 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
 	{ 0x9005, 0x0285, 0x1028, 0x0291, 0, 0, 26 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
 	{ 0x9005, 0x0285, 0x9005, 0x0292, 0, 0, 27 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
 	{ 0x9005, 0x0285, 0x9005, 0x0293, 0, 0, 28 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
 	{ 0x9005, 0x0285, 0x9005, 0x0294, 0, 0, 29 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
-	{ 0x9005, 0x0285, 0x0E11, 0x0295, 0, 0, 30 }, /* SATA 6Ch (Bearcat) */
-
-	{ 0x9005, 0x0286, 0x9005, 0x028c, 0, 0, 31 }, /* ASR-2230S + ASR-2230SLP PCI-X (Lancer) */
-	{ 0x9005, 0x0285, 0x9005, 0x028e, 0, 0, 32 }, /* ASR-2020SA      (ZCR PCI-X SATA) */
-	{ 0x9005, 0x0285, 0x9005, 0x028f, 0, 0, 33 }, /* ASR-2025SA      (ZCR DIMM SATA) */
+	{ 0x9005, 0x0285, 0x0E11, 0x0295, 0, 0, 30 }, /* AAR-2610SA PCI SATA 6ch */
+	{ 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 31 }, /* ASR-2240S */
+	{ 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 32 }, /* ASR-4005SAS */
+	{ 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 33 }, /* ASR-4000SAS */
+	{ 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 34 }, /* ASR-4800SAS */
+	{ 0x9005, 0x0285, 0x9005, 0x0296, 0, 0, 35 }, /* ASR-4805SAS */
+
+	{ 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 36 }, /* Perc 320/DC*/
+	{ 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 37 }, /* Adaptec 5400S (Mustang)*/
+	{ 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 38 }, /* Adaptec 5400S (Mustang)*/
+	{ 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 39 }, /* Dell PERC2/QC */
+	{ 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 40 }, /* HP NetRAID-4M */
+
+	{ 0x9005, 0x0285, 0x1028, PCI_ANY_ID, 0, 0, 41 }, /* Dell Catchall */
+	{ 0x9005, 0x0285, 0x17aa, PCI_ANY_ID, 0, 0, 42 }, /* Legend Catchall */
+	{ 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 43 }, /* Adaptec Catch All */
+	{ 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 44 }, /* Adaptec Rocket Catch All */
 	{ 0,}
 };
 MODULE_DEVICE_TABLE(pci, aac_pci_tbl);
@@ -131,44 +134,54 @@ MODULE_DEVICE_TABLE(pci, aac_pci_tbl);
  * for the card.  At that time we can remove the channels from here
  */
 static struct aac_driver_ident aac_drivers[] = {
-	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 2/Si */
-	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */
-	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Si */
-	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Si */
-	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */
-	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */
-	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */
-	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */
-	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di */
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "catapult        ", 2, AAC_QUIRK_31BIT }, /* catapult*/
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "tomcat          ", 2, AAC_QUIRK_31BIT }, /* tomcat*/
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 2120S   ", 1, AAC_QUIRK_31BIT }, /* Adaptec 2120S (Crusader)*/
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 2200S   ", 2, AAC_QUIRK_31BIT }, /* Adaptec 2200S (Vulcan)*/
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 2200S   ", 2, AAC_QUIRK_31BIT }, /* Adaptec 2200S (Vulcan-2m)*/
-	{ aac_rx_init, "aacraid",  "Legend  ", "Legend S220     ", 1, AAC_QUIRK_31BIT }, /* Legend S220*/
-	{ aac_rx_init, "aacraid",  "Legend  ", "Legend S230     ", 2, AAC_QUIRK_31BIT }, /* Legend S230*/
-
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 3230S   ", 2 }, /* Adaptec 3230S (Harrier)*/
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 3240S   ", 2 }, /* Adaptec 3240S (Tornado)*/
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2020ZCR     ", 2 }, /* ASR-2020 ZCR PCI-X U320 */
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2025ZCR     ", 2 }, /* ASR-2025 ZCR DIMM U320 */
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-2410SA SATA ", 2 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II)*/
-
-	{ aac_rx_init, "percraid", "DELL    ", "PERC 320/DC     ", 2, AAC_QUIRK_31BIT }, /* Perc 320/DC*/
-	{ aac_sa_init, "aacraid",  "ADAPTEC ", "Adaptec 5400S   ", 4 }, /* Adaptec 5400S (Mustang)*/
-	{ aac_sa_init, "aacraid",  "ADAPTEC ", "AAC-364         ", 4 }, /* Adaptec 5400S (Mustang)*/
-	{ aac_sa_init, "percraid", "DELL    ", "PERCRAID        ", 4, AAC_QUIRK_31BIT }, /* Dell PERC2 "Quad Channel" */
-	{ aac_sa_init, "hpnraid",  "HP      ", "NetRAID         ", 4 },  /* HP NetRAID-4M */
-
+	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 2/Si (Iguana/PERC2Si) */
+	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di (Opal/PERC3Di) */
+	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Si (SlimFast/PERC3Si */
+	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di (Iguana FlipChip/PERC3DiF */
+	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di (Viper/PERC3DiV) */
+	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di (Lexus/PERC3DiL) */
+	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 1, AAC_QUIRK_31BIT }, /* PERC 3/Di (Jaguar/PERC3DiJ) */
+	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di (Dagger/PERC3DiD) */
+	{ aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2, AAC_QUIRK_31BIT }, /* PERC 3/Di (Boxster/PERC3DiB) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "catapult        ", 2, AAC_QUIRK_31BIT }, /* catapult */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "tomcat          ", 2, AAC_QUIRK_31BIT }, /* tomcat */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 2120S   ", 1, AAC_QUIRK_31BIT }, /* Adaptec 2120S (Crusader) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 2200S   ", 2, AAC_QUIRK_31BIT }, /* Adaptec 2200S (Vulcan) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 2200S   ", 2, AAC_QUIRK_31BIT }, /* Adaptec 2200S (Vulcan-2m) */
+	{ aac_rx_init, "aacraid",  "Legend  ", "Legend S220     ", 1, AAC_QUIRK_31BIT }, /* Legend S220 (Legend Crusader) */
+	{ aac_rx_init, "aacraid",  "Legend  ", "Legend S230     ", 2, AAC_QUIRK_31BIT }, /* Legend S230 (Legend Vulcan) */
+
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 3230S   ", 2 }, /* Adaptec 3230S (Harrier) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 3240S   ", 2 }, /* Adaptec 3240S (Tornado) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2020ZCR     ", 2 }, /* ASR-2020ZCR SCSI PCI-X ZCR (Skyhawk) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2025ZCR     ", 2 }, /* ASR-2025ZCR SCSI SO-DIMM PCI-X ZCR (Terminator) */
+	{ aac_rkt_init, "aacraid",  "ADAPTEC ", "ASR-2230S PCI-X ", 2 }, /* ASR-2230S + ASR-2230SLP PCI-X (Lancer) */
+	{ aac_rkt_init, "aacraid",  "ADAPTEC ", "ASR-2130S PCI-X ", 1 }, /* ASR-2130S (Lancer) */
+	{ aac_rkt_init, "aacraid",  "ADAPTEC ", "Callisto        ", 2 }, /* Jupiter Platform */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2020SA       ", 1 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2025SA       ", 1 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-2410SA SATA ", 1 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
 	{ aac_rx_init, "aacraid",  "DELL    ", "CERC SR2        ", 1 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-2810SA SATA ", 1 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-21610SA SATA", 1 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "SO-DIMM SATA ZCR", 1 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "SATA 6Channel   ", 1 }, /* SATA 6Ch (Bearcat) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-2610SA      ", 1 }, /* SATA 6Ch (Bearcat) */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2240S       ", 1 }, /* ASR-2240S */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4005SAS     ", 1 }, /* ASR-4005SAS */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4000SAS     ", 1 }, /* ASR-4000SAS */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4800SAS     ", 1 }, /* ASR-4800SAS */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4805SAS     ", 1 }, /* ASR-4805SAS */
 
-	{ aac_rkt_init,"aacraid",  "ADAPTEC ", "ASR-2230S PCI-X ", 2 }, /* ASR-2230S + ASR-2230SLP PCI-X (Lancer) */
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2020SA      ", 1 }, /* ASR-2020SA      (ZCR PCI-X SATA) */
-	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2025SA      ", 1 }, /* ASR-2025SA      (ZCR DIMM SATA) */
+	{ aac_rx_init, "percraid", "DELL    ", "PERC 320/DC     ", 2, AAC_QUIRK_31BIT }, /* Perc 320/DC*/
+	{ aac_sa_init, "aacraid",  "ADAPTEC ", "Adaptec 5400S   ", 4 }, /* Adaptec 5400S (Mustang)*/
+	{ aac_sa_init, "aacraid",  "ADAPTEC ", "AAC-364         ", 4 }, /* Adaptec 5400S (Mustang)*/
+	{ aac_sa_init, "percraid", "DELL    ", "PERCRAID        ", 4, AAC_QUIRK_31BIT }, /* Dell PERC2/QC */
+	{ aac_sa_init, "hpnraid",  "HP      ", "NetRAID         ", 4 }, /* HP NetRAID-4M */
+
+	{ aac_rx_init, "aacraid",  "DELL    ", "RAID            ", 2, AAC_QUIRK_31BIT }, /* Dell Catchall */
+	{ aac_rx_init, "aacraid",  "Legend  ", "RAID            ", 2, AAC_QUIRK_31BIT }, /* Legend Catchall */
+	{ aac_rx_init, "aacraid",  "ADAPTEC ", "RAID            ", 2, AAC_QUIRK_31BIT }, /* Adaptec Catch All */
+	{ aac_rkt_init, "aacraid", "ADAPTEC ", "RAID            ", 2 } /* Adaptec Rocket Catch All */
 };
 
 #ifdef CONFIG_COMPAT
@@ -408,15 +421,17 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
 				}
 			}
 			spin_unlock_irqrestore(&dev->list_lock, flags);
+			if (active)
+				break;
 
-			/*
-			 * We can exit If all the commands are complete
-			 */
-			if (active == 0)
-				return SUCCESS;
 		}
+		/*
+		 * We can exit If all the commands are complete
+		 */
+		if (active == 0)
+			return SUCCESS;
 		spin_unlock_irq(host->host_lock);
-		scsi_sleep(HZ);
+		ssleep(1);
 		spin_lock_irq(host->host_lock);
 	}
 	printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME);
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index d796cac2a..40d282fb7 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -15,16 +15,6 @@
  * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys)
  * changed its name to ConnectCom Solutions, Inc.
  *
- * There is an AdvanSys Linux WWW page at:
- *  http://www.connectcom.net/downloads/software/os/linux.html
- *  http://www.advansys.com/linux.html
- *
- * The latest released version of the AdvanSys driver is available at:
- *  ftp://ftp.advansys.com/pub/linux/linux.tgz
- *  ftp://ftp.connectcom.net/pub/linux/linux.tgz
- *
- * Please send questions, comments, bug reports to:
- *  support@connectcom.net
  */
 
 /*
@@ -41,7 +31,6 @@
   H. Release History
   I. Known Problems/Fix List
   J. Credits (Chronological Order)
-  K. ConnectCom (AdvanSys) Contact Information
 
   A. Linux Kernels Supported by this Driver
 
@@ -2032,9 +2021,6 @@ STATIC ASC_DCNT  AscGetMaxDmaCount(ushort);
 #define ADV_LIB_VERSION_MAJOR  5
 #define ADV_LIB_VERSION_MINOR  14
 
-/* d_os_dep.h */
-#define ADV_OS_LINUX
-
 /*
  * Define Adv Library required special types.
  */
@@ -3370,9 +3356,9 @@ do { \
 /*
  * Default EEPROM Configuration structure defined in a_init.c.
  */
-extern ADVEEP_3550_CONFIG Default_3550_EEPROM_Config;
-extern ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config;
-extern ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config;
+static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config;
+static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config;
+static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config;
 
 /*
  * DvcGetPhyAddr() flag arguments
diff --git a/drivers/scsi/advansys.h b/drivers/scsi/advansys.h
index 5230ba01c..3f4bde023 100644
--- a/drivers/scsi/advansys.h
+++ b/drivers/scsi/advansys.h
@@ -13,37 +13,11 @@
  * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys)
  * changed its name to ConnectCom Solutions, Inc.
  *
- * There is an AdvanSys Linux WWW page at:
- *  http://www.connectcom.net/downloads/software/os/linux.html
- *  http://www.advansys.com/linux.html
- *
- * The latest released version of the AdvanSys driver is available at:
- *  ftp://ftp.advansys.com/pub/linux/linux.tgz
- *  ftp://ftp.connectcom.net/pub/linux/linux.tgz
- *
- * Please send questions, comments, bug reports to:
- *  linux@connectcom.net or bfrey@turbolinux.com.cn
  */
 
 #ifndef _ADVANSYS_H
 #define _ADVANSYS_H
 
-#include <linux/config.h>
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif /* LINUX_VERSION_CODE */
-
-/* Convert Linux Version, Patch-level, Sub-level to LINUX_VERSION_CODE. */
-#define ASC_LINUX_VERSION(V, P, S)    (((V) * 65536) + ((P) * 256) + (S))
-/* Driver supported only in version 2.2 and version >= 2.4. */
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,2,0) || \
-    (LINUX_VERSION_CODE > ASC_LINUX_VERSION(2,3,0) && \
-     LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,4,0))
-#error "AdvanSys driver supported only in 2.2 and 2.4 or greater kernels."
-#endif
-#define ASC_LINUX_KERNEL22 (LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,4,0))
-#define ASC_LINUX_KERNEL24 (LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,4,0))
-
 /*
  * Scsi_Host_Template function prototypes.
  */
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index 4c5e9c38f..8b93d6e43 100644
--- a/drivers/scsi/aha1542.c
+++ b/drivers/scsi/aha1542.c
@@ -1479,7 +1479,7 @@ static int aha1542_bus_reset(Scsi_Cmnd * SCpnt)
 	 * we are pretty desperate anyways.
 	 */
 	spin_unlock_irq(SCpnt->device->host->host_lock);
-	scsi_sleep(4 * HZ);
+	ssleep(4);
 	spin_lock_irq(SCpnt->device->host->host_lock);
 
 	WAIT(STATUS(SCpnt->device->host->io_port),
@@ -1543,7 +1543,7 @@ static int aha1542_host_reset(Scsi_Cmnd * SCpnt)
 	 * we are pretty desperate anyways.
 	 */
 	spin_unlock_irq(SCpnt->device->host->host_lock);
-	scsi_sleep(4 * HZ);
+	ssleep(4);
 	spin_lock_irq(SCpnt->device->host->host_lock);
 
 	WAIT(STATUS(SCpnt->device->host->io_port),
diff --git a/drivers/scsi/aha1542.h b/drivers/scsi/aha1542.h
index cba290ce9..c402351dc 100644
--- a/drivers/scsi/aha1542.h
+++ b/drivers/scsi/aha1542.h
@@ -91,10 +91,12 @@ struct chain {
 };
 
 /* These belong in scsi.h also */
-#define any2scsi(up, p)				\
-(up)[0] = (((unsigned long)(p)) >> 16)  ;	\
-(up)[1] = (((unsigned long)(p)) >> 8);		\
-(up)[2] = ((unsigned long)(p));
+static inline void any2scsi(u8 *p, u32 v)
+{
+	p[0] = v >> 16;
+	p[1] = v >> 8;
+	p[2] = v;
+}
 
 #define scsi2int(up) ( (((long)*(up)) << 16) + (((long)(up)[1]) << 8) + ((long)(up)[2]) )
 
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx
index b29981521..c2523a30a 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic79xx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx
@@ -46,7 +46,7 @@ config AIC79XX_RESET_DELAY_MS
 
 config AIC79XX_BUILD_FIRMWARE
 	bool "Build Adapter Firmware with Kernel Build"
-	depends on SCSI_AIC79XX
+	depends on SCSI_AIC79XX && !PREVENT_FIRMWARE_BUILD
 	help
 	This option should only be enabled if you are modifying the firmware
 	source to the aic79xx driver and wish to have the generated firmware
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
index 473a658d2..8398e0dd4 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
@@ -61,7 +61,7 @@ config AIC7XXX_PROBE_EISA_VL
 
 config AIC7XXX_BUILD_FIRMWARE
 	bool "Build Adapter Firmware with Kernel Build"
-	depends on SCSI_AIC7XXX
+	depends on SCSI_AIC7XXX && !PREVENT_FIRMWARE_BUILD
 	help
 	This option should only be enabled if you are modifying the firmware
 	source to the aic7xxx driver and wish to have the generated firmware
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 68b4539a4..c9f3a52f1 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -61,6 +61,7 @@
 #endif
 
 #include <linux/mm.h>		/* For fetching system memory size */
+#include <linux/delay.h>	/* For ssleep/msleep */
 
 /*
  * Lock protecting manipulation of the ahd softc list.
@@ -415,7 +416,6 @@ uint32_t aic79xx_periodic_otag;
 /*
  * Module information and settable options.
  */
-#ifdef MODULE
 static char *aic79xx = NULL;
 /*
  * Just in case someone uses commas to separate items on the insmod
@@ -426,9 +426,8 @@ static char dummy_buffer[60] = "Please don't trounce on me insmod!!\n";
 
 MODULE_AUTHOR("Maintainer: Justin T. Gibbs <gibbs@scsiguy.com>");
 MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver");
-#ifdef MODULE_LICENSE
 MODULE_LICENSE("Dual BSD/GPL");
-#endif
+MODULE_VERSION(AIC79XX_DRIVER_VERSION);
 MODULE_PARM(aic79xx, "s");
 MODULE_PARM_DESC(aic79xx,
 "period delimited, options string.\n"
@@ -463,7 +462,6 @@ MODULE_PARM_DESC(aic79xx,
 "		Change Read Streaming for Controller's 2 and 3\n"
 "\n"
 "	options aic79xx 'aic79xx=rd_strm:{..0xFFF0.0xC0F0}'");
-#endif
 
 static void ahd_linux_handle_scsi_status(struct ahd_softc *,
 					 struct ahd_linux_device *,
@@ -513,9 +511,6 @@ static void ahd_linux_dv_su(struct ahd_softc *ahd,
 			    struct scsi_cmnd *cmd,
 			    struct ahd_devinfo *devinfo,
 			    struct ahd_linux_target *targ);
-static __inline int
-	   ahd_linux_dv_fallback(struct ahd_softc *ahd,
-				 struct ahd_devinfo *devinfo);
 static int ahd_linux_fallback(struct ahd_softc *ahd,
 			      struct ahd_devinfo *devinfo);
 static __inline int ahd_linux_dv_fallback(struct ahd_softc *ahd,
@@ -2915,6 +2910,19 @@ out:
 	ahd_unlock(ahd, &s);
 }
 
+static __inline int
+ahd_linux_dv_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
+{
+	u_long s;
+	int retval;
+
+	ahd_lock(ahd, &s);
+	retval = ahd_linux_fallback(ahd, devinfo);
+	ahd_unlock(ahd, &s);
+
+	return (retval);
+}
+
 static void
 ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
 			struct ahd_devinfo *devinfo,
@@ -3163,7 +3171,7 @@ ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
 				break;
 			}
 			if (status & SSQ_DELAY)
-				scsi_sleep(1 * HZ);
+				ssleep(1);
 
 			break;
 		case SS_START:
@@ -3323,7 +3331,7 @@ ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
 			}
 			if (targ->dv_state_retry <= 10) {
 				if ((status & (SSQ_DELAY_RANDOM|SSQ_DELAY))!= 0)
-					scsi_sleep(ahd->our_id*HZ/10);
+					msleep(ahd->our_id*1000/10);
 				break;
 			}
 #ifdef AHD_DEBUG
@@ -3367,7 +3375,7 @@ ahd_linux_dv_transition(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
 				targ->dv_state_retry--;
 			} else if (targ->dv_state_retry < 60) {
 				if ((status & SSQ_DELAY) != 0)
-					scsi_sleep(1 * HZ);
+					ssleep(1);
 			} else {
 #ifdef AHD_DEBUG
 				if (ahd_debug & AHD_SHOW_DV) {
@@ -3551,19 +3559,6 @@ ahd_linux_dv_su(struct ahd_softc *ahd, struct scsi_cmnd *cmd,
 	cmd->cmnd[4] = le | SSS_START;
 }
 
-static __inline int
-ahd_linux_dv_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
-{
-	u_long s;
-	int retval;
-
-	ahd_lock(ahd, &s);
-	retval = ahd_linux_fallback(ahd, devinfo);
-	ahd_unlock(ahd, &s);
-
-	return (retval);
-}
-
 static int
 ahd_linux_fallback(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
 {
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
index 913984539..7cc83dafa 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
@@ -452,8 +452,10 @@ ahd_pci_test_register_access(struct ahd_softc *ahd)
 	 * or read prefetching could be initiated by the
 	 * CPU or host bridge.  Our device does not support
 	 * either, so look for data corruption and/or flaged
-	 * PCI errors.
+	 * PCI errors.  First pause without causing another
+	 * chip reset.
 	 */
+	hcntrl &= ~CHIPRST;
 	ahd_outb(ahd, HCNTRL, hcntrl|PAUSE);
 	while (ahd_is_paused(ahd) == 0)
 		;
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index 3c7a4854d..ecbc05d84 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -140,6 +140,7 @@
 
 #include <linux/mm.h>		/* For fetching system memory size */
 #include <linux/blkdev.h>		/* For block_size() */
+#include <linux/delay.h>	/* For ssleep/msleep */
 
 /*
  * Lock protecting manipulation of the ahc softc list.
@@ -436,7 +437,6 @@ uint32_t aic7xxx_periodic_otag;
 /*
  * Module information and settable options.
  */
-#ifdef MODULE
 static char *aic7xxx = NULL;
 /*
  * Just in case someone uses commas to separate items on the insmod
@@ -447,9 +447,8 @@ static char dummy_buffer[60] = "Please don't trounce on me insmod!!\n";
 
 MODULE_AUTHOR("Maintainer: Justin T. Gibbs <gibbs@scsiguy.com>");
 MODULE_DESCRIPTION("Adaptec Aic77XX/78XX SCSI Host Bus Adapter driver");
-#ifdef MODULE_LICENSE
 MODULE_LICENSE("Dual BSD/GPL");
-#endif
+MODULE_VERSION(AIC7XXX_DRIVER_VERSION);
 MODULE_PARM(aic7xxx, "s");
 MODULE_PARM_DESC(aic7xxx,
 "period delimited, options string.\n"
@@ -479,7 +478,6 @@ MODULE_PARM_DESC(aic7xxx,
 "\n"
 "	options aic7xxx 'aic7xxx=probe_eisa_vl.tag_info:{{}.{.10}}.seltime:1'\n"
 );
-#endif
 
 static void ahc_linux_handle_scsi_status(struct ahc_softc *,
 					 struct ahc_linux_device *,
@@ -2825,7 +2823,7 @@ ahc_linux_dv_transition(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
 				break;
 			}
 			if (status & SSQ_DELAY)
-				scsi_sleep(1 * HZ);
+				ssleep(1);
 
 			break;
 		case SS_START:
@@ -2985,7 +2983,7 @@ ahc_linux_dv_transition(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
 			}
 			if (targ->dv_state_retry <= 10) {
 				if ((status & (SSQ_DELAY_RANDOM|SSQ_DELAY))!= 0)
-					scsi_sleep(ahc->our_id*HZ/10);
+					msleep(ahc->our_id*1000/10);
 				break;
 			}
 #ifdef AHC_DEBUG
@@ -3029,7 +3027,7 @@ ahc_linux_dv_transition(struct ahc_softc *ahc, struct scsi_cmnd *cmd,
 				targ->dv_state_retry--;
 			} else if (targ->dv_state_retry < 60) {
 				if ((status & SSQ_DELAY) != 0)
-					scsi_sleep(1 * HZ);
+					ssleep(1);
 			} else {
 #ifdef AHC_DEBUG
 				if (ahc_debug & AHC_SHOW_DV) {
diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c
index 01cfab0e3..476780bae 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c
@@ -1284,8 +1284,10 @@ ahc_pci_test_register_access(struct ahc_softc *ahc)
 	 * or read prefetching could be initiated by the
 	 * CPU or host bridge.  Our device does not support
 	 * either, so look for data corruption and/or flagged
-	 * PCI errors.
+	 * PCI errors.  First pause without causing another
+	 * chip reset.
 	 */
+	hcntrl &= ~CHIPRST;
 	ahc_outb(ahc, HCNTRL, hcntrl|PAUSE);
 	while (ahc_is_paused(ahc) == 0)
 		;
diff --git a/drivers/scsi/aic7xxx/aicasm/Makefile b/drivers/scsi/aic7xxx/aicasm/Makefile
index e8c345b8e..8c91fda64 100644
--- a/drivers/scsi/aic7xxx/aicasm/Makefile
+++ b/drivers/scsi/aic7xxx/aicasm/Makefile
@@ -34,10 +34,14 @@ $(PROG):  ${GENHDRS} $(SRCS)
 	$(AICASM_CC) $(AICASM_CFLAGS) $(SRCS) -o $(PROG) $(LIBS)
 
 aicdb.h:
-	@if [ -e "/usr/include/db3/db_185.h" ]; then		\
+	@if [ -e "/usr/include/db4/db_185.h" ]; then		\
+		echo "#include <db4/db_185.h>" > aicdb.h;	\
+	 elif [ -e "/usr/include/db3/db_185.h" ]; then		\
 		echo "#include <db3/db_185.h>" > aicdb.h;	\
 	 elif [ -e "/usr/include/db2/db_185.h" ]; then		\
 		echo "#include <db2/db_185.h>" > aicdb.h;	\
+	 elif [ -e "/usr/include/db1/db_185.h" ]; then		\
+		echo "#include <db1/db_185.h>" > aicdb.h;	\
 	 elif [ -e "/usr/include/db/db_185.h" ]; then		\
 		echo "#include <db/db_185.h>" > aicdb.h;	\
 	 elif [ -e "/usr/include/db_185.h" ]; then		\
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index 3d6149675..c92226b8c 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -10489,7 +10489,7 @@ aic7xxx_bus_device_reset(Scsi_Cmnd *cmd)
       aic_outb(p, lastphase | ATNO, SCSISIGO);
       unpause_sequencer(p, FALSE);
       spin_unlock_irq(p->host->host_lock);
-      scsi_sleep(HZ);
+      ssleep(1);
       spin_lock_irq(p->host->host_lock);
       if(aic_dev->flags & BUS_DEVICE_RESET_PENDING)
         return FAILED;
@@ -10548,7 +10548,7 @@ aic7xxx_bus_device_reset(Scsi_Cmnd *cmd)
   aic_outb(p, saved_scbptr, SCBPTR);
   unpause_sequencer(p, FALSE);
   spin_unlock_irq(p->host->host_lock);
-  scsi_sleep(HZ/4);
+  msleep(1000/4);
   spin_lock_irq(p->host->host_lock);
   if(aic_dev->flags & BUS_DEVICE_RESET_PENDING)
     return FAILED;
@@ -10786,7 +10786,7 @@ aic7xxx_abort(Scsi_Cmnd *cmd)
   }
   unpause_sequencer(p, FALSE);
   spin_unlock_irq(p->host->host_lock);
-  scsi_sleep(HZ/4);
+  msleep(1000/4);
   spin_lock_irq(p->host->host_lock);
   if (p->flags & AHC_ABORT_PENDING)
   {
@@ -10887,7 +10887,7 @@ aic7xxx_reset(Scsi_Cmnd *cmd)
   aic7xxx_run_done_queue(p, TRUE);
   unpause_sequencer(p, FALSE);
   spin_unlock_irq(p->host->host_lock);
-  scsi_sleep(2 * HZ);
+  ssleep(2);
   spin_lock_irq(p->host->host_lock);
   return SUCCESS;
 }
@@ -11139,6 +11139,7 @@ aic7xxx_print_scratch_ram(struct aic7xxx_host *p)
 #include "aic7xxx_old/aic7xxx_proc.c"
 
 MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(AIC7XXX_H_VERSION);
 
 
 static Scsi_Host_Template driver_template = {
diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c
index 6dad72222..27271bfc0 100644
--- a/drivers/scsi/arm/cumana_1.c
+++ b/drivers/scsi/arm/cumana_1.c
@@ -321,6 +321,7 @@ static void __devexit cumanascsi1_remove(struct expansion_card *ec)
 
 	scsi_remove_host(host);
 	free_irq(host->irq, host);
+	NCR5380_exit(host);
 	release_region(host->io_port, host->n_io_port);
 	scsi_host_put(host);
 }
diff --git a/drivers/scsi/arm/ecoscsi.c b/drivers/scsi/arm/ecoscsi.c
index 57e79614f..303648a84 100644
--- a/drivers/scsi/arm/ecoscsi.c
+++ b/drivers/scsi/arm/ecoscsi.c
@@ -222,6 +222,7 @@ static void __exit ecoscsi_exit(void)
 
 	if (shpnt->irq != IRQ_NONE)
 		free_irq(shpnt->irq, NULL);
+	NCR5380_exit(host);
 	if (shpnt->io_port)
 		release_region(shpnt->io_port, shpnt->n_io_port);
 
diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c
index 530b59c01..5f037d24c 100644
--- a/drivers/scsi/arm/eesox.c
+++ b/drivers/scsi/arm/eesox.c
@@ -231,7 +231,8 @@ static void eesoxscsi_buffer_in(void *buf, int length, void *base)
 		 * Align buffer.
 		 */
 		if (((u32)buf) & 2 && status >= 2) {
-			*((u16 *)buf)++ = readl(reg_dmadata);
+			*(u16 *)buf = readl(reg_dmadata);
+			buf += 2;
 			status -= 2;
 			length -= 2;
 		}
@@ -243,8 +244,10 @@ static void eesoxscsi_buffer_in(void *buf, int length, void *base)
 			l1 |= readl(reg_dmadata) << 16;
 			l2 = readl(reg_dmadata) & mask;
 			l2 |= readl(reg_dmadata) << 16;
-			*((u32 *)buf)++ = l1;
-			*((u32 *)buf)++ = l2;
+			*(u32 *)buf = l1;
+			buf += 4;
+			*(u32 *)buf = l2;
+			buf += 4;
 			length -= 8;
 			continue;
 		}
@@ -255,13 +258,15 @@ static void eesoxscsi_buffer_in(void *buf, int length, void *base)
 			l1 = readl(reg_dmadata) & mask;
 			l1 |= readl(reg_dmadata) << 16;
 
-			*((u32 *)buf)++ = l1;
+			*(u32 *)buf = l1;
+			buf += 4;
 			length -= 4;
 			continue;
 		}
 
 		if (status >= 2) {
-			*((u16 *)buf)++ = readl(reg_dmadata);
+			*(u16 *)buf = readl(reg_dmadata);
+			buf += 2;
 			length -= 2;
 		}
 	} while (length);
@@ -305,7 +310,8 @@ static void eesoxscsi_buffer_out(void *buf, int length, void *base)
 		 * Align buffer.
 		 */
 		if (((u32)buf) & 2 && status >= 2) {
-			writel(*((u16 *)buf)++ << 16, reg_dmadata);
+			writel(*(u16 *)buf << 16, reg_dmadata);
+			buf += 2;
 			status -= 2;
 			length -= 2;
 		}
@@ -313,8 +319,10 @@ static void eesoxscsi_buffer_out(void *buf, int length, void *base)
 		if (status >= 8) {
 			unsigned long l1, l2;
 
-			l1 = *((u32 *)buf)++;
-			l2 = *((u32 *)buf)++;
+			l1 = *(u32 *)buf;
+			buf += 4;
+			l2 = *(u32 *)buf;
+			buf += 4;
 
 			writel(l1 << 16, reg_dmadata);
 			writel(l1, reg_dmadata);
@@ -327,7 +335,8 @@ static void eesoxscsi_buffer_out(void *buf, int length, void *base)
 		if (status >= 4) {
 			unsigned long l1;
 
-			l1 = *((u32 *)buf)++;
+			l1 = *(u32 *)buf;
+			buf += 4;
 
 			writel(l1 << 16, reg_dmadata);
 			writel(l1, reg_dmadata);
@@ -336,7 +345,8 @@ static void eesoxscsi_buffer_out(void *buf, int length, void *base)
 		}
 
 		if (status >= 2) {
-			writel(*((u16 *)buf)++ << 16, reg_dmadata);
+			writel(*(u16 *)buf << 16, reg_dmadata);
+			buf += 2;
 			length -= 2;
 		}
 	} while (length);
diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
index f54b47025..bd607455e 100644
--- a/drivers/scsi/arm/fas216.c
+++ b/drivers/scsi/arm/fas216.c
@@ -2681,7 +2681,7 @@ int fas216_eh_host_reset(Scsi_Cmnd *SCpnt)
 	 * IRQs after the sleep.
 	 */
 	spin_unlock_irq(info->host->host_lock);
-	scsi_sleep(50 * HZ/100);
+	msleep(50 * 1000/100);
 	spin_lock_irq(info->host->host_lock);
 
 	/*
@@ -2920,7 +2920,7 @@ int fas216_add(struct Scsi_Host *host, struct device *dev)
 	 * scsi standard says wait 250ms
 	 */
 	spin_unlock_irq(info->host->host_lock);
-	scsi_sleep(100*HZ/100);
+	msleep(100*1000/100);
 	spin_lock_irq(info->host->host_lock);
 
 	fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]);
diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c
index ecfee930c..ff2554f4c 100644
--- a/drivers/scsi/arm/oak.c
+++ b/drivers/scsi/arm/oak.c
@@ -179,6 +179,7 @@ static void __devexit oakscsi_remove(struct expansion_card *ec)
 	ecard_set_drvdata(ec, NULL);
 	scsi_remove_host(host);
 
+	NCR5380_exit(host);
 	release_region(host->io_port, host->n_io_port);
 	scsi_host_put(host);
 }
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index c030c0a68..adad8d394 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -39,6 +39,7 @@ enum {
 	ICH5_PMR		= 0x90, /* port mapping register */
 	ICH5_PCS		= 0x92,	/* port control and status */
 
+	PIIX_FLAG_AHCI		= (1 << 28), /* AHCI possible */
 	PIIX_FLAG_CHECKINTR	= (1 << 29), /* make sure PCI INTx enabled */
 	PIIX_FLAG_COMBINED	= (1 << 30), /* combined mode possible */
 
@@ -58,6 +59,7 @@ enum {
 	ich5_sata		= 1,
 	piix4_pata		= 2,
 	ich6_sata		= 3,
+	ich6_sata_rm		= 4,
 };
 
 static int piix_init_one (struct pci_dev *pdev,
@@ -65,10 +67,8 @@ static int piix_init_one (struct pci_dev *pdev,
 
 static void piix_pata_phy_reset(struct ata_port *ap);
 static void piix_sata_phy_reset(struct ata_port *ap);
-static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev,
-			      unsigned int pio);
-static void piix_set_udmamode (struct ata_port *ap, struct ata_device *adev,
-			       unsigned int udma);
+static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev);
+static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev);
 
 static unsigned int in_module_init = 1;
 
@@ -87,13 +87,9 @@ static struct pci_device_id piix_pci_tbl[] = {
 	{ 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
 	{ 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
 	{ 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
-
-	/* ICH6 operates in two modes, "looks-like-ICH5" mode,
-	 * and enhanced mode, with queueing and other fancy stuff.
-	 * This is distinguished by PCI class code.
-	 */
 	{ 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
-	{ 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata },
+	{ 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_rm },
+	{ 0x8086, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_rm },
 
 	{ }	/* terminate list */
 };
@@ -108,6 +104,7 @@ static struct pci_driver piix_pci_driver = {
 static Scsi_Host_Template piix_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -126,17 +123,18 @@ static Scsi_Host_Template piix_sht = {
 static struct ata_port_operations piix_pata_ops = {
 	.port_disable		= ata_port_disable,
 	.set_piomode		= piix_set_piomode,
-	.set_udmamode		= piix_set_udmamode,
+	.set_dmamode		= piix_set_dmamode,
 
-	.tf_load		= ata_tf_load_pio,
-	.tf_read		= ata_tf_read_pio,
-	.check_status		= ata_check_status_pio,
-	.exec_command		= ata_exec_command_pio,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= ata_exec_command,
+	.dev_select		= ata_std_dev_select,
 
 	.phy_reset		= piix_pata_phy_reset,
 
-	.bmdma_setup		= ata_bmdma_setup_pio,
-	.bmdma_start		= ata_bmdma_start_pio,
+	.bmdma_setup		= ata_bmdma_setup,
+	.bmdma_start		= ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 
@@ -151,18 +149,17 @@ static struct ata_port_operations piix_pata_ops = {
 
 static struct ata_port_operations piix_sata_ops = {
 	.port_disable		= ata_port_disable,
-	.set_piomode		= piix_set_piomode,
-	.set_udmamode		= piix_set_udmamode,
 
-	.tf_load		= ata_tf_load_pio,
-	.tf_read		= ata_tf_read_pio,
-	.check_status		= ata_check_status_pio,
-	.exec_command		= ata_exec_command_pio,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= ata_exec_command,
+	.dev_select		= ata_std_dev_select,
 
 	.phy_reset		= piix_sata_phy_reset,
 
-	.bmdma_setup		= ata_bmdma_setup_pio,
-	.bmdma_start		= ata_bmdma_start_pio,
+	.bmdma_setup		= ata_bmdma_setup,
+	.bmdma_start		= ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 
@@ -181,7 +178,12 @@ static struct ata_port_info piix_port_info[] = {
 		.sht		= &piix_sht,
 		.host_flags	= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST |
 				  PIIX_FLAG_CHECKINTR,
-		.pio_mask	= 0x03,	/* pio3-4 */
+		.pio_mask	= 0x1f,	/* pio0-4 */
+#if 0
+		.mwdma_mask	= 0x06, /* mwdma1-2 */
+#else
+		.mwdma_mask	= 0x00, /* mwdma broken */
+#endif
 		.udma_mask	= ATA_UDMA_MASK_40C, /* FIXME: cbl det */
 		.port_ops	= &piix_pata_ops,
 	},
@@ -191,8 +193,9 @@ static struct ata_port_info piix_port_info[] = {
 		.sht		= &piix_sht,
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST |
 				  PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR,
-		.pio_mask	= 0x03,	/* pio3-4 */
-		.udma_mask	= 0x7f,	/* udma0-6 ; FIXME */
+		.pio_mask	= 0x1f,	/* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.udma_mask	= 0x7f,	/* udma0-6 */
 		.port_ops	= &piix_sata_ops,
 	},
 
@@ -200,7 +203,12 @@ static struct ata_port_info piix_port_info[] = {
 	{
 		.sht		= &piix_sht,
 		.host_flags	= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
-		.pio_mask	= 0x03, /* pio3-4 */
+		.pio_mask	= 0x1f,	/* pio0-4 */
+#if 0
+		.mwdma_mask	= 0x06, /* mwdma1-2 */
+#else
+		.mwdma_mask	= 0x00, /* mwdma broken */
+#endif
 		.udma_mask	= ATA_UDMA_MASK_40C, /* FIXME: cbl det */
 		.port_ops	= &piix_pata_ops,
 	},
@@ -211,8 +219,21 @@ static struct ata_port_info piix_port_info[] = {
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST |
 				  PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
 				  ATA_FLAG_SLAVE_POSS,
-		.pio_mask	= 0x03,	/* pio3-4 */
-		.udma_mask	= 0x7f,	/* udma0-6 ; FIXME */
+		.pio_mask	= 0x1f,	/* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.udma_mask	= 0x7f,	/* udma0-6 */
+		.port_ops	= &piix_sata_ops,
+	},
+
+	/* ich6_sata_rm */
+	{
+		.sht		= &piix_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST |
+				  PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
+				  ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI,
+		.pio_mask	= 0x1f,	/* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.udma_mask	= 0x7f,	/* udma0-6 */
 		.port_ops	= &piix_sata_ops,
 	},
 };
@@ -368,11 +389,11 @@ static void piix_sata_phy_reset(struct ata_port *ap)
  *	None (inherited from caller).
  */
 
-static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev,
-			      unsigned int pio)
+static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev)
 {
+	unsigned int pio	= adev->pio_mode - XFER_PIO_0;
 	struct pci_dev *dev	= ap->host_set->pdev;
-	unsigned int is_slave	= (adev->flags & ATA_DFLAG_MASTER) ? 0 : 1;
+	unsigned int is_slave	= (adev->devno != 0);
 	unsigned int master_port= ap->port_no ? 0x42 : 0x40;
 	unsigned int slave_port	= 0x44;
 	u16 master_data;
@@ -409,7 +430,7 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev,
 }
 
 /**
- *	piix_set_udmamode - Initialize host controller PATA PIO timings
+ *	piix_set_dmamode - Initialize host controller PATA PIO timings
  *	@ap: Port whose timings we are configuring
  *	@adev: um
  *	@udma: udma mode, 0 - 6
@@ -420,9 +441,9 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev,
  *	None (inherited from caller).
  */
 
-static void piix_set_udmamode (struct ata_port *ap, struct ata_device *adev,
-			      unsigned int udma)
+static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev)
 {
+	unsigned int udma	= adev->dma_mode; /* FIXME: MWDMA too */
 	struct pci_dev *dev	= ap->host_set->pdev;
 	u8 maslave		= ap->port_no ? 0x42 : 0x40;
 	u8 speed		= udma;
@@ -452,25 +473,38 @@ static void piix_set_udmamode (struct ata_port *ap, struct ata_device *adev,
 		case XFER_UDMA_3:
 		case XFER_UDMA_1:	u_speed = 1 << (drive_dn * 4); break;
 		case XFER_UDMA_0:	u_speed = 0 << (drive_dn * 4); break;
+		case XFER_MW_DMA_2:
+		case XFER_MW_DMA_1:	break;
 		default:
 			BUG();
 			return;
 	}
 
-	if (!(reg48 & u_flag))
-		pci_write_config_byte(dev, 0x48, reg48 | u_flag);
-	if (speed == XFER_UDMA_5) {
-		pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag);
+	if (speed >= XFER_UDMA_0) {
+		if (!(reg48 & u_flag))
+			pci_write_config_byte(dev, 0x48, reg48 | u_flag);
+		if (speed == XFER_UDMA_5) {
+			pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag);
+		} else {
+			pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
+		}
+		if ((reg4a & a_speed) != u_speed)
+			pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed);
+		if (speed > XFER_UDMA_2) {
+			if (!(reg54 & v_flag))
+				pci_write_config_byte(dev, 0x54, reg54 | v_flag);
+		} else
+			pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
 	} else {
-		pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
+		if (reg48 & u_flag)
+			pci_write_config_byte(dev, 0x48, reg48 & ~u_flag);
+		if (reg4a & a_speed)
+			pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+		if (reg54 & v_flag)
+			pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
+		if (reg55 & w_flag)
+			pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
 	}
-	if ((reg4a & a_speed) != u_speed)
-		pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed);
-	if (speed > XFER_UDMA_2) {
-		if (!(reg54 & v_flag))
-			pci_write_config_byte(dev, 0x54, reg54 | v_flag);
-	} else
-		pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
 }
 
 /* move to PCI layer, integrate w/ MSI stuff */
@@ -485,6 +519,42 @@ static void pci_enable_intx(struct pci_dev *pdev)
 	}
 }
 
+#define AHCI_PCI_BAR 5
+#define AHCI_GLOBAL_CTL 0x04
+#define AHCI_ENABLE (1 << 31)
+static int piix_disable_ahci(struct pci_dev *pdev)
+{
+	void *mmio;
+	unsigned long addr;
+	u32 tmp;
+	int rc = 0;
+
+	/* BUG: pci_enable_device has not yet been called.  This
+	 * works because this device is usually set up by BIOS.
+	 */
+
+	addr = pci_resource_start(pdev, AHCI_PCI_BAR);
+	if (!addr || !pci_resource_len(pdev, AHCI_PCI_BAR))
+		return 0;
+	
+	mmio = ioremap(addr, 64);
+	if (!mmio)
+		return -ENOMEM;
+	
+	tmp = readl(mmio + AHCI_GLOBAL_CTL);
+	if (tmp & AHCI_ENABLE) {
+		tmp &= ~AHCI_ENABLE;
+		writel(tmp, mmio + AHCI_GLOBAL_CTL);
+
+		tmp = readl(mmio + AHCI_GLOBAL_CTL);
+		if (tmp & AHCI_ENABLE)
+			rc = -EIO;
+	}
+	
+	iounmap(mmio);
+	return rc;
+}
+
 /**
  *	piix_init_one - Register PIIX ATA PCI device with kernel services
  *	@pdev: PCI device to register
@@ -517,6 +587,12 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 	port_info[0] = &piix_port_info[ent->driver_data];
 	port_info[1] = NULL;
 
+	if (port_info[0]->host_flags & PIIX_FLAG_AHCI) {
+		int rc = piix_disable_ahci(pdev);
+		if (rc)
+			return rc;
+	}
+
 	if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) {
 		u8 tmp;
 		pci_read_config_byte(pdev, ICH5_PMR, &tmp);
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 9cf23b9f2..49feb64cd 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -363,7 +363,7 @@ go_42:
 			/*
 			 *      Clear it off the queue
 			 */
-			dev->id[target_id].curr_req = 0;
+			dev->id[target_id].curr_req = NULL;
 			dev->working--;
 			spin_unlock_irqrestore(dev->host->host_lock, flags);
 			/*
@@ -2263,10 +2263,10 @@ static int atp870u_init_tables(struct Scsi_Host *host)
 	dev->in_snd = 0;
 	dev->in_int = 0;
 	for (k = 0; k < qcnt; k++) {
-		dev->querequ[k] = 0;
+		dev->querequ[k] = NULL;
 	}
 	for (k = 0; k < 16; k++) {
-		dev->id[k].curr_req = 0;
+		dev->id[k].curr_req = NULL;
 		dev->sp[k] = 0x04;
 	}
 	return 0;
diff --git a/drivers/scsi/cpqfcTScontrol.c b/drivers/scsi/cpqfcTScontrol.c
index a69bd792e..bd94c70f4 100644
--- a/drivers/scsi/cpqfcTScontrol.c
+++ b/drivers/scsi/cpqfcTScontrol.c
@@ -116,7 +116,6 @@ int CpqTsCreateTachLiteQues( void* pHBA, int opcode)
   cpqfcHBAdata->fcLQ = pci_alloc_consistent(cpqfcHBAdata->PciDev,
 				 sizeof( FC_LINK_QUE), &cpqfcHBAdata->fcLQ_dma_handle);
   /* printk("@ %p (%u elements)\n", cpqfcHBAdata->fcLQ, FC_LINKQ_DEPTH); */
-  memset( cpqfcHBAdata->fcLQ, 0, sizeof( FC_LINK_QUE));
 
   if( cpqfcHBAdata->fcLQ == NULL ) // fatal error!!
   {
diff --git a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c
index 8778aac34..58d140cd1 100644
--- a/drivers/scsi/cpqfcTSinit.c
+++ b/drivers/scsi/cpqfcTSinit.c
@@ -302,10 +302,16 @@ int cpqfcTS_detect(Scsi_Host_Template *ScsiHostTemplate)
 				    cpqfc_boards[i].device_id, PciDev)))
     {
 
+      if (pci_enable_device(PciDev)) {
+	printk(KERN_ERR
+		"cpqfc: can't enable PCI device at %s\n", pci_name(PciDev));
+	goto err_continue;
+      }
+
       if (pci_set_dma_mask(PciDev, CPQFCTS_DMA_MASK) != 0) {
 	printk(KERN_WARNING 
 		"cpqfc: HBA cannot support required DMA mask, skipping.\n");
-	continue;
+	goto err_disable_dev;
       }
 
       // NOTE: (kernel 2.2.12-32) limits allocation to 128k bytes...
@@ -314,8 +320,11 @@ int cpqfcTS_detect(Scsi_Host_Template *ScsiHostTemplate)
 
       HostAdapter = scsi_register( ScsiHostTemplate, sizeof( CPQFCHBA ) );
       
-      if(HostAdapter == NULL)
-      	continue;
+      if(HostAdapter == NULL) {
+	printk(KERN_WARNING
+		"cpqfc: can't register SCSI HBA, skipping.\n");
+      	goto err_disable_dev;
+      }
       DEBUG_PCI( printk("  HBA found!\n"));
       DEBUG_PCI( printk("  HostAdapter->PciDev->irq = %u\n", PciDev->irq) );
       DEBUG_PCI(printk("  PciDev->baseaddress[0]= %lx\n", 
@@ -367,9 +376,8 @@ int cpqfcTS_detect(Scsi_Host_Template *ScsiHostTemplate)
 	               DEV_NAME,
 		       HostAdapter) )
       {
-	printk(" IRQ %u already used\n", HostAdapter->irq);
-        scsi_unregister( HostAdapter);
-	continue;
+	printk(KERN_WARNING "cpqfc: IRQ %u already used\n", HostAdapter->irq);
+	goto err_unregister;
       }
 
       // Since we have two 256-byte I/O port ranges (upper
@@ -377,22 +385,17 @@ int cpqfcTS_detect(Scsi_Host_Template *ScsiHostTemplate)
       if( !request_region( cpqfcHBAdata->fcChip.Registers.IOBaseU,
       	                   0xff, DEV_NAME ) )
       {
-	printk("  cpqfcTS address in use: %x\n", 
+	printk(KERN_WARNING "cpqfc: address in use: %x\n",
 			cpqfcHBAdata->fcChip.Registers.IOBaseU);
-	free_irq( HostAdapter->irq, HostAdapter);
-        scsi_unregister( HostAdapter);
-	continue;
+	goto err_free_irq;
       }	
       
       if( !request_region( cpqfcHBAdata->fcChip.Registers.IOBaseL,
       			   0xff, DEV_NAME ) )
       {
-  	printk("  cpqfcTS address in use: %x\n", 
+  	printk(KERN_WARNING "cpqfc: address in use: %x\n",
 	      			cpqfcHBAdata->fcChip.Registers.IOBaseL);
-	release_region( cpqfcHBAdata->fcChip.Registers.IOBaseU, 0xff );
-	free_irq( HostAdapter->irq, HostAdapter);
-        scsi_unregister( HostAdapter);
-	continue;
+	goto err_release_region_U;
       }	
       
       // OK, we have grabbed everything we need now.
@@ -424,7 +427,7 @@ int cpqfcTS_detect(Scsi_Host_Template *ScsiHostTemplate)
       // now initialize our hardware...
       if (cpqfcHBAdata->fcChip.InitializeTachyon( cpqfcHBAdata, 1,1)) {
 	printk(KERN_WARNING "cpqfc: initialization of HBA hardware failed.\n");
-	// FIXME: might want to do something better than nothing here.
+	goto err_release_region_L;
       }
 
       cpqfcHBAdata->fcStatsTime = jiffies;  // (for FC Statistics delta)
@@ -455,6 +458,21 @@ int cpqfcTS_detect(Scsi_Host_Template *ScsiHostTemplate)
       spin_lock_irq(HostAdapter->host_lock);
       NumberOfAdapters++; 
       spin_unlock_irq(HostAdapter->host_lock);
+
+      continue;
+
+err_release_region_L:
+      release_region( cpqfcHBAdata->fcChip.Registers.IOBaseL, 0xff );
+err_release_region_U:
+      release_region( cpqfcHBAdata->fcChip.Registers.IOBaseU, 0xff );
+err_free_irq:
+      free_irq( HostAdapter->irq, HostAdapter);
+err_unregister:
+      scsi_unregister( HostAdapter);
+err_disable_dev:
+      pci_disable_device( PciDev );
+err_continue:
+      continue;
     } // end of while()
   }
 
@@ -811,6 +829,7 @@ int cpqfcTS_release(struct Scsi_Host *HostAdapter)
       cpqfcHBAdata->fcChip.Registers.ReMapMemBase)
     vfree( cpqfcHBAdata->fcChip.Registers.ReMapMemBase);
 */
+  pci_disable_device( cpqfcHBAdata->PciDev);
 
   LEAVE("cpqfcTS_release");
   return 0;
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index bde847c73..b08c3e6b1 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -376,6 +376,8 @@ static void disconnect(struct AdapterCtlBlk *acb);
 static void reselect(struct AdapterCtlBlk *acb);
 static u8 start_scsi(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
 		struct ScsiReqBlk *srb);
+static inline void enable_msgout_abort(struct AdapterCtlBlk *acb,
+		struct ScsiReqBlk *srb);
 static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
 		struct ScsiReqBlk *srb);
 static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_code,
@@ -384,13 +386,11 @@ static void scsi_reset_detect(struct AdapterCtlBlk *acb);
 static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb);
 static void pci_unmap_srb_sense(struct AdapterCtlBlk *acb,
 		struct ScsiReqBlk *srb);
-static inline void enable_msgout_abort(struct AdapterCtlBlk *acb,
-		struct ScsiReqBlk *srb);
 static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
 		struct ScsiReqBlk *srb);
 static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
 		struct ScsiReqBlk *srb);
-static inline void set_xfer_rate(struct AdapterCtlBlk *acb,
+static void set_xfer_rate(struct AdapterCtlBlk *acb,
 		struct DeviceCtlBlk *dcb);
 static void waiting_timeout(unsigned long ptr);
 
@@ -989,7 +989,7 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
 	srb->sg_count = 0;
 	srb->total_xfer_length = 0;
 	srb->sg_bus_addr = 0;
-	srb->virt_addr = 0;
+	srb->virt_addr = NULL;
 	srb->sg_index = 0;
 	srb->adapter_status = 0;
 	srb->target_status = 0;
@@ -1676,6 +1676,23 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb,
 }
 
 
+#define DC395x_ENABLE_MSGOUT \
+ DC395x_write16 (acb, TRM_S1040_SCSI_CONTROL, DO_SETATN); \
+ srb->state |= SRB_MSGOUT
+
+
+/* abort command */
+static inline void enable_msgout_abort(struct AdapterCtlBlk *acb,
+		struct ScsiReqBlk *srb)
+{
+	srb->msgout_buf[0] = ABORT;
+	srb->msg_count = 1;
+	DC395x_ENABLE_MSGOUT;
+	srb->state &= ~SRB_MSGIN;
+	srb->state |= SRB_MSGOUT;
+}
+
+
 /**
  * dc395x_handle_interrupt - Handle an interrupt that has been confirmed to
  *                           have been triggered for this card.
@@ -1999,7 +2016,7 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left)
 	}
 
 	dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n");
-	srb->virt_addr = 0;
+	srb->virt_addr = NULL;
 }
 
 
@@ -2583,11 +2600,6 @@ static inline u8 msgin_completed(u8 * msgbuf, u32 len)
 	return 1;
 }
 
-#define DC395x_ENABLE_MSGOUT \
- DC395x_write16 (acb, TRM_S1040_SCSI_CONTROL, DO_SETATN); \
- srb->state |= SRB_MSGOUT
-
-
 /* reject_msg */
 static inline void msgin_reject(struct AdapterCtlBlk *acb,
 		struct ScsiReqBlk *srb)
@@ -2603,18 +2615,6 @@ static inline void msgin_reject(struct AdapterCtlBlk *acb,
 }
 
 
-/* abort command */
-static inline void enable_msgout_abort(struct AdapterCtlBlk *acb,
-		struct ScsiReqBlk *srb)
-{
-	srb->msgout_buf[0] = ABORT;
-	srb->msg_count = 1;
-	DC395x_ENABLE_MSGOUT;
-	srb->state &= ~SRB_MSGIN;
-	srb->state |= SRB_MSGOUT;
-}
-
-
 static struct ScsiReqBlk *msgin_qtag(struct AdapterCtlBlk *acb,
 		struct DeviceCtlBlk *dcb, u8 tag)
 {
@@ -3656,7 +3656,7 @@ static void scsi_reset_detect(struct AdapterCtlBlk *acb)
 	} else {
 		acb->acb_flag |= RESET_DETECT;
 		reset_dev_param(acb);
-		doing_srb_done(acb, DID_RESET, 0, 1);
+		doing_srb_done(acb, DID_RESET, NULL, 1);
 		/*DC395x_RecoverSRB( acb ); */
 		acb->active_dcb = NULL;
 		acb->acb_flag = 0;
diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c
index 26e060bb8..21a701c6c 100644
--- a/drivers/scsi/dmx3191d.c
+++ b/drivers/scsi/dmx3191d.c
@@ -106,9 +106,10 @@ static const char * dmx3191d_info(struct Scsi_Host *host) {
 
 static int dmx3191d_release_resources(struct Scsi_Host *instance)
 {
-	release_region(instance->io_port, DMX3191D_REGION);
 	if(instance->irq!=SCSI_IRQ_NONE)
 		free_irq(instance->irq, instance);
+	NCR5380_exit(instance);
+	release_region(instance->io_port, DMX3191D_REGION);
 
 	return 0;
 }
diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c
index 624c7ee5d..6611113a2 100644
--- a/drivers/scsi/dtc.c
+++ b/drivers/scsi/dtc.c
@@ -451,6 +451,7 @@ static int dtc_release(struct Scsi_Host *shost)
 {
 	if (shost->irq)
 		free_irq(shost->irq, NULL);
+	NCR5380_exit(shost);
 	if (shost->io_port && shost->n_io_port)
 		release_region(shost->io_port, shost->n_io_port);
 	scsi_unregister(shost);
diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c
index e2c07fca0..0ee49dc50 100644
--- a/drivers/scsi/eata_pio.c
+++ b/drivers/scsi/eata_pio.c
@@ -59,6 +59,8 @@
 #include <linux/interrupt.h>
 #include <linux/blkdev.h>
 #include <linux/spinlock.h>
+#include <linux/delay.h>
+
 #include <asm/io.h>
 
 #include <scsi/scsi.h>
@@ -511,8 +513,7 @@ static int eata_pio_host_reset(struct scsi_cmnd *cmd)
 	HD(cmd)->state = RESET;
 
 	spin_unlock_irq(host->host_lock);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(3 * HZ);
+	msleep(3000);
 	spin_lock_irq(host->host_lock);
 
 	DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: interrupts disabled, " "loops %d.\n", limit));
diff --git a/drivers/scsi/esp.h b/drivers/scsi/esp.h
index 85beb4750..73f7d6968 100644
--- a/drivers/scsi/esp.h
+++ b/drivers/scsi/esp.h
@@ -77,8 +77,8 @@ struct scsi_cmnd;
 
 /* We get one of these for each ESP probed. */
 struct esp {
-	unsigned long		eregs;		/* ESP controller registers */
-	unsigned long		dregs;		/* DMA controller registers */
+	void __iomem		*eregs;		/* ESP controller registers */
+	void __iomem		*dregs;		/* DMA controller registers */
 	struct sbus_dma		*dma;		/* DMA controller sw state */
 	struct Scsi_Host	*ehost;		/* Backpointer to SCSI Host */
 	struct sbus_dev		*sdev;		/* Pointer to SBus entry */
diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c
index 763e33b13..32e0cd597 100644
--- a/drivers/scsi/fd_mcs.c
+++ b/drivers/scsi/fd_mcs.c
@@ -78,6 +78,7 @@
  **************************************************************************/
 
 #include <linux/module.h>
+#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/blkdev.h>
 #include <linux/errno.h>
@@ -288,7 +289,7 @@ static irqreturn_t fd_mcs_intr(int irq, void *dev_id, struct pt_regs *regs);
 
 static unsigned long addresses[] = { 0xc8000, 0xca000, 0xce000, 0xde000 };
 static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
-static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
+static unsigned short interrupts[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
 
 /* host information */
 static int found = 0;
@@ -297,16 +298,20 @@ static struct Scsi_Host *hosts[FD_MAX_HOSTS + 1] = { NULL };
 static int user_fifo_count = 0;
 static int user_fifo_size = 0;
 
-static void fd_mcs_setup(char *str, int *ints)
+static int __init fd_mcs_setup(char *str)
 {
 	static int done_setup = 0;
+	int ints[3];
 
+	get_options(str, 3, ints);
 	if (done_setup++ || ints[0] < 1 || ints[0] > 2 || ints[1] < 1 || ints[1] > 16) {
 		printk("fd_mcs: usage: fd_mcs=FIFO_COUNT, FIFO_SIZE\n");
+		return 0;
 	}
 
 	user_fifo_count = ints[0] >= 1 ? ints[1] : 0;
 	user_fifo_size = ints[0] >= 2 ? ints[2] : 0;
+	return 1;
 }
 
 __setup("fd_mcs=", fd_mcs_setup);
@@ -391,7 +396,7 @@ static int fd_mcs_detect(Scsi_Host_Template * tpnt)
 			} else {
 				bios = addresses[pos2 >> 6];
 				port = ports[(pos2 >> 4) & 0x03];
-				irq = ints[(pos2 >> 1) & 0x07];
+				irq = interrupts[(pos2 >> 1) & 0x07];
 			}
 
 			if (irq) {
diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
index 6529f0c55..a78b6f257 100644
--- a/drivers/scsi/fdomain.c
+++ b/drivers/scsi/fdomain.c
@@ -733,17 +733,20 @@ static int fdomain_isa_detect( int *irq, int *iobase )
       printk( " %x,", base );
 #endif
 
-      for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) {
-	 if (base == ports[i])
-	       ++flag;
+      for (i = 0; i < PORT_COUNT; i++) {
+	if (base == ports[i]) {
+		if (!request_region(base, 0x10, "fdomain"))
+			break;
+		if (!fdomain_is_valid_port(base)) {
+			release_region(base, 0x10);
+			break;
+		}
+		*irq    = fdomain_get_irq( base );
+		*iobase = base;
+		return 1;
+	}
       }
 
-      if (flag && fdomain_is_valid_port( base )) {
-	 *irq    = fdomain_get_irq( base );
-	 *iobase = base;
-	 return 1;
-      }
-      
       /* This is a bad sign.  It usually means that someone patched the
 	 BIOS signature list (the signatures variable) to contain a BIOS
 	 signature for a board *OTHER THAN* the TMC-1660/TMC-1680. */
@@ -764,7 +767,7 @@ static int fdomain_isa_detect( int *irq, int *iobase )
 
    for (i = 0; i < PORT_COUNT; i++) {
       base = ports[i];
-      if (check_region( base, 0x10 )) {
+      if (!request_region(base, 0x10, "fdomain")) {
 #if DEBUG_DETECT
 	 printk( " (%x inuse),", base );
 #endif
@@ -773,7 +776,10 @@ static int fdomain_isa_detect( int *irq, int *iobase )
 #if DEBUG_DETECT
       printk( " %x,", base );
 #endif
-      if ((flag = fdomain_is_valid_port( base ))) break;
+      flag = fdomain_is_valid_port(base);
+      if (flag)
+	break;
+      release_region(base, 0x10);
    }
 
 #if DEBUG_DETECT
@@ -832,6 +838,9 @@ static int fdomain_pci_bios_detect( int *irq, int *iobase, struct pci_dev **ret_
    pci_base = pci_resource_start(pdev, 0);
    pci_irq = pdev->irq;
 
+   if (!request_region( pci_base, 0x10, "fdomain" ))
+	return 0;
+
    /* Now we have the I/O base address and interrupt from the PCI
       configuration registers. */
 
@@ -844,8 +853,9 @@ static int fdomain_pci_bios_detect( int *irq, int *iobase, struct pci_dev **ret_
 	   " IRQ = %d, I/O base = 0x%x [0x%lx]\n", *irq, *iobase, pci_base );
 #endif
 
-   if (!fdomain_is_valid_port( *iobase )) {
+   if (!fdomain_is_valid_port(pci_base)) {
       printk(KERN_ERR "scsi: <fdomain> PCI card detected, but driver not loaded (invalid port)\n" );
+      release_region(pci_base, 0x10);
       return 0;
    }
 
@@ -870,10 +880,16 @@ struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt )
       printk( "scsi: <fdomain> No BIOS, using port_base = 0x%x, irq = %d\n",
 	      port_base, interrupt_level );
 #endif
+      if (!request_region(port_base, 0x10, "fdomain")) {
+	 printk( "scsi: <fdomain> port 0x%x is busy\n", port_base );
+	 printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
+	 return NULL;
+      }
       if (!fdomain_is_valid_port( port_base )) {
 	 printk( "scsi: <fdomain> Cannot locate chip at port base 0x%x\n",
 		 port_base );
 	 printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
+	 release_region(port_base, 0x10);
 	 return NULL;
       }
    } else {
@@ -915,6 +931,7 @@ struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt )
       if (setup_called) {
 	 printk(KERN_ERR "scsi: <fdomain> Bad LILO/INSMOD parameters?\n");
       }
+      release_region(port_base, 0x10);
       return NULL;
    }
 
@@ -935,8 +952,10 @@ struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt )
    get resources.  */
 
    shpnt = scsi_register( tpnt, 0 );
-   if(shpnt == NULL)
+   if(shpnt == NULL) {
+	release_region(port_base, 0x10);
    	return NULL;
+   }
    shpnt->irq = interrupt_level;
    shpnt->io_port = port_base;
    scsi_set_device(shpnt, &pdev->dev);
@@ -946,6 +965,7 @@ struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt )
    /* Log IRQ with kernel */   
    if (!interrupt_level) {
       printk(KERN_ERR "scsi: <fdomain> Card Detected, but driver not loaded (no IRQ)\n" );
+      release_region(port_base, 0x10);
       return NULL;
    } else {
       /* Register the IRQ with the kernel */
@@ -967,13 +987,10 @@ struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt )
 	    printk(KERN_ERR "                Send mail to faith@acm.org\n" );
 	 }
 	 printk(KERN_ERR "scsi: <fdomain> Detected, but driver not loaded (IRQ)\n" );
+         release_region(port_base, 0x10);
 	 return NULL;
       }
    }
-
-   /* Log I/O ports with kernel */
-   request_region( port_base, 0x10, "fdomain" );
-
    return shpnt;
 }
 
diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index bcf97ec03..9c1f8cc4d 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -501,6 +501,10 @@ int generic_NCR5380_release_resources(struct Scsi_Host *instance)
 {
 	NCR5380_local_declare();
 	NCR5380_setup(instance);
+	
+	if (instance->irq != SCSI_IRQ_NONE)
+		free_irq(instance->irq, NULL);
+	NCR5380_exit(instance);
 
 #ifndef CONFIG_SCSI_G_NCR5380_MEM
 	release_region(instance->NCR5380_instance_name, instance->n_io_port);
@@ -508,8 +512,6 @@ int generic_NCR5380_release_resources(struct Scsi_Host *instance)
 	release_mem_region(instance->NCR5380_instance_name, NCR5380_region_size);
 #endif
 
-	if (instance->irq != SCSI_IRQ_NONE)
-		free_irq(instance->irq, NULL);
 
 	return 0;
 }
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 6cb8fa2bd..df28e91a6 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -571,12 +571,12 @@ static struct timer_list gdth_timer;
 
 #define BUS_L2P(a,b)    ((b)>(a)->virt_bus ? (b-1):(b))
 
-#define gdth_readb(addr)        readb((ulong)(addr))
-#define gdth_readw(addr)        readw((ulong)(addr))
-#define gdth_readl(addr)        (ulong32)readl((ulong)(addr))
-#define gdth_writeb(b,addr)     writeb((b),(ulong)(addr))
-#define gdth_writew(b,addr)     writew((b),(ulong)(addr))
-#define gdth_writel(b,addr)     writel((ulong32)(b),(ulong)(addr))
+#define gdth_readb(addr)        readb(addr)
+#define gdth_readw(addr)        readw(addr)
+#define gdth_readl(addr)        readl(addr)
+#define gdth_writeb(b,addr)     writeb((b),(addr))
+#define gdth_writew(b,addr)     writew((b),(addr))
+#define gdth_writel(b,addr)     writel((b),(addr))
 
 static unchar   gdth_drq_tab[4] = {5,6,7,7};            /* DRQ table */
 static unchar   gdth_irq_tab[6] = {0,10,11,12,14,0};    /* IRQ table */
@@ -618,9 +618,6 @@ static unchar gdth_direction_tab[0x100] = {
 };
 
 /* __initfunc, __initdata macros */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-#define __devinitdata
-#endif
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 #define GDTH_INITFUNC(type, func)       type __init func 
 #include <linux/init.h>
@@ -778,7 +775,7 @@ GDTH_INITFUNC(static int, gdth_search_eisa(ushort eisa_adr))
 
 GDTH_INITFUNC(static int, gdth_search_isa(ulong32 bios_adr))
 {
-    void *addr;
+    void __iomem *addr;
     ulong32 id;
 
     TRACE(("gdth_search_isa() bios adr. %x\n",bios_adr));
@@ -1053,7 +1050,7 @@ GDTH_INITFUNC(static int, gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha))
        
 GDTH_INITFUNC(static int, gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha))
 {
-    register gdt2_dpram_str *dp2_ptr;
+    register gdt2_dpram_str __iomem *dp2_ptr;
     int i;
     unchar irq_drq,prot_ver;
     ulong32 retries;
@@ -1065,10 +1062,10 @@ GDTH_INITFUNC(static int, gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha))
         printk("GDT-ISA: Initialization error (DPMEM remap error)\n");
         return 0;
     }
-    dp2_ptr = (gdt2_dpram_str *)ha->brd;
+    dp2_ptr = ha->brd;
     gdth_writeb(1, &dp2_ptr->io.memlock); /* switch off write protection */
     /* reset interface area */
-    memset_io((char *)&dp2_ptr->u,0,sizeof(dp2_ptr->u));
+    memset_io(&dp2_ptr->u, 0, sizeof(dp2_ptr->u));
     if (gdth_readl(&dp2_ptr->u) != 0) {
         printk("GDT-ISA: Initialization error (DPMEM write error)\n");
         iounmap(ha->brd);
@@ -1153,9 +1150,9 @@ GDTH_INITFUNC(static int, gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha))
 
 GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
 {
-    register gdt6_dpram_str *dp6_ptr;
-    register gdt6c_dpram_str *dp6c_ptr;
-    register gdt6m_dpram_str *dp6m_ptr;
+    register gdt6_dpram_str __iomem *dp6_ptr;
+    register gdt6c_dpram_str __iomem *dp6c_ptr;
+    register gdt6m_dpram_str __iomem *dp6m_ptr;
     ulong32 retries;
     unchar prot_ver;
     ushort command;
@@ -1183,7 +1180,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
             return 0;
         }
         /* check and reset interface area */
-        dp6_ptr = (gdt6_dpram_str *)ha->brd;
+        dp6_ptr = ha->brd;
         gdth_writel(DPMEM_MAGIC, &dp6_ptr->u);
         if (gdth_readl(&dp6_ptr->u) != DPMEM_MAGIC) {
             printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", 
@@ -1208,7 +1205,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
                     return 0;
                 }
-                dp6_ptr = (gdt6_dpram_str *)ha->brd;
+                dp6_ptr = ha->brd;
                 gdth_writel(DPMEM_MAGIC, &dp6_ptr->u);
                 if (gdth_readl(&dp6_ptr->u) == DPMEM_MAGIC) {
                     printk("GDT-PCI: Use free address at 0x%x\n", i);
@@ -1222,7 +1219,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
                 return 0;
             }
         }
-        memset_io((char *)&dp6_ptr->u,0,sizeof(dp6_ptr->u));
+        memset_io(&dp6_ptr->u, 0, sizeof(dp6_ptr->u));
         if (gdth_readl(&dp6_ptr->u) != 0) {
             printk("GDT-PCI: Initialization error (DPMEM write error)\n");
             iounmap(ha->brd);
@@ -1293,7 +1290,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
             return 0;
         }
         /* check and reset interface area */
-        dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
+        dp6c_ptr = ha->brd;
         gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u);
         if (gdth_readl(&dp6c_ptr->u) != DPMEM_MAGIC) {
             printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", 
@@ -1318,7 +1315,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
                     return 0;
                 }
-                dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
+                dp6c_ptr = ha->brd;
                 gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u);
                 if (gdth_readl(&dp6c_ptr->u) == DPMEM_MAGIC) {
                     printk("GDT-PCI: Use free address at 0x%x\n", i);
@@ -1332,7 +1329,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
                 return 0;
             }
         }
-        memset_io((char *)&dp6c_ptr->u,0,sizeof(dp6c_ptr->u));
+        memset_io(&dp6c_ptr->u, 0, sizeof(dp6c_ptr->u));
         if (gdth_readl(&dp6c_ptr->u) != 0) {
             printk("GDT-PCI: Initialization error (DPMEM write error)\n");
             iounmap(ha->brd);
@@ -1428,13 +1425,14 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
                                pcistr->pdev->rom_address);
 #endif
         
+        dp6m_ptr = ha->brd;
+
         /* Ensure that it is safe to access the non HW portions of DPMEM.
          * Aditional check needed for Xscale based RAID controllers */
-        while( ((int)gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg) ) & 3 )
+        while( ((int)gdth_readb(&dp6m_ptr->i960r.sema0_reg) ) & 3 )
             gdth_delay(1);
         
         /* check and reset interface area */
-        dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
         gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u);
         if (gdth_readl(&dp6m_ptr->u) != DPMEM_MAGIC) {
             printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", 
@@ -1459,7 +1457,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
                     return 0;
                 }
-                dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
+                dp6m_ptr = ha->brd;
                 gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u);
                 if (gdth_readl(&dp6m_ptr->u) == DPMEM_MAGIC) {
                     printk("GDT-PCI: Use free address at 0x%x\n", i);
@@ -1473,7 +1471,7 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
                 return 0;
             }
         }
-        memset_io((char *)&dp6m_ptr->u,0,sizeof(dp6m_ptr->u));
+        memset_io(&dp6m_ptr->u, 0, sizeof(dp6m_ptr->u));
         
         /* disable board interrupts, deinit services */
         gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) | 4,
@@ -1556,9 +1554,9 @@ GDTH_INITFUNC(static void, gdth_enable_int(int hanum))
 {
     gdth_ha_str *ha;
     ulong flags;
-    gdt2_dpram_str *dp2_ptr;
-    gdt6_dpram_str *dp6_ptr;
-    gdt6m_dpram_str *dp6m_ptr;
+    gdt2_dpram_str __iomem *dp2_ptr;
+    gdt6_dpram_str __iomem *dp6_ptr;
+    gdt6m_dpram_str __iomem *dp6m_ptr;
 
     TRACE(("gdth_enable_int() hanum %d\n",hanum));
     ha = HADATA(gdth_ctr_tab[hanum]);
@@ -1569,12 +1567,12 @@ GDTH_INITFUNC(static void, gdth_enable_int(int hanum))
         outb(0xff, ha->bmic + EDENABREG);
         outb(0x01, ha->bmic + EINTENABREG);
     } else if (ha->type == GDT_ISA) {
-        dp2_ptr = (gdt2_dpram_str *)ha->brd;
+        dp2_ptr = ha->brd;
         gdth_writeb(1, &dp2_ptr->io.irqdel);
         gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index);
         gdth_writeb(1, &dp2_ptr->io.irqen);
     } else if (ha->type == GDT_PCI) {
-        dp6_ptr = (gdt6_dpram_str *)ha->brd;
+        dp6_ptr = ha->brd;
         gdth_writeb(1, &dp6_ptr->io.irqdel);
         gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index);
         gdth_writeb(1, &dp6_ptr->io.irqen);
@@ -1582,7 +1580,7 @@ GDTH_INITFUNC(static void, gdth_enable_int(int hanum))
         outb(0xff, PTR2USHORT(&ha->plx->edoor_reg));
         outb(0x03, PTR2USHORT(&ha->plx->control1));
     } else if (ha->type == GDT_PCIMPR) {
-        dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
+        dp6m_ptr = ha->brd;
         gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
         gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4,
                     &dp6m_ptr->i960r.edoor_en_reg);
@@ -1608,15 +1606,15 @@ static int gdth_get_status(unchar *pIStatus,int irq)
             *pIStatus = inb((ushort)ha->bmic + EDOORREG);
         else if (ha->type == GDT_ISA)
             *pIStatus =
-                gdth_readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Cmd_Index);
+                gdth_readb(&((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index);
         else if (ha->type == GDT_PCI)
             *pIStatus =
-                gdth_readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Cmd_Index);
+                gdth_readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index);
         else if (ha->type == GDT_PCINEW) 
             *pIStatus = inb(PTR2USHORT(&ha->plx->edoor_reg));
         else if (ha->type == GDT_PCIMPR)
             *pIStatus =
-                gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.edoor_reg);
+                gdth_readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.edoor_reg);
    
         if (*pIStatus)                                  
             return i;                           /* board found */
@@ -1636,14 +1634,14 @@ static int gdth_test_busy(int hanum)
     if (ha->type == GDT_EISA)
         gdtsema0 = (int)inb(ha->bmic + SEMA0REG);
     else if (ha->type == GDT_ISA)
-        gdtsema0 = (int)gdth_readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Sema0);
+        gdtsema0 = (int)gdth_readb(&((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Sema0);
     else if (ha->type == GDT_PCI)
-        gdtsema0 = (int)gdth_readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Sema0);
+        gdtsema0 = (int)gdth_readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Sema0);
     else if (ha->type == GDT_PCINEW) 
         gdtsema0 = (int)inb(PTR2USHORT(&ha->plx->sema0_reg));
     else if (ha->type == GDT_PCIMPR)
         gdtsema0 = 
-            (int)gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg);
+            (int)gdth_readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.sema0_reg);
 
     return (gdtsema0 & 1);
 }
@@ -1679,13 +1677,13 @@ static void gdth_set_sema0(int hanum)
     if (ha->type == GDT_EISA) {
         outb(1, ha->bmic + SEMA0REG);
     } else if (ha->type == GDT_ISA) {
-        gdth_writeb(1, &((gdt2_dpram_str *)ha->brd)->u.ic.Sema0);
+        gdth_writeb(1, &((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Sema0);
     } else if (ha->type == GDT_PCI) {
-        gdth_writeb(1, &((gdt6_dpram_str *)ha->brd)->u.ic.Sema0);
+        gdth_writeb(1, &((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Sema0);
     } else if (ha->type == GDT_PCINEW) { 
         outb(1, PTR2USHORT(&ha->plx->sema0_reg));
     } else if (ha->type == GDT_PCIMPR) {
-        gdth_writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg);
+        gdth_writeb(1, &((gdt6m_dpram_str __iomem *)ha->brd)->i960r.sema0_reg);
     }
 }
 
@@ -1694,10 +1692,10 @@ static void gdth_copy_command(int hanum)
 {
     register gdth_ha_str *ha;
     register gdth_cmd_str *cmd_ptr;
-    register gdt6m_dpram_str *dp6m_ptr;
-    register gdt6c_dpram_str *dp6c_ptr;
-    gdt6_dpram_str *dp6_ptr;
-    gdt2_dpram_str *dp2_ptr;
+    register gdt6m_dpram_str __iomem *dp6m_ptr;
+    register gdt6c_dpram_str __iomem *dp6c_ptr;
+    gdt6_dpram_str __iomem *dp6_ptr;
+    gdt2_dpram_str __iomem *dp2_ptr;
     ushort cp_count,dp_offset,cmd_no;
     
     TRACE(("gdth_copy_command() hanum %d\n",hanum));
@@ -1720,28 +1718,28 @@ static void gdth_copy_command(int hanum)
     
     /* set offset and service, copy command to DPMEM */
     if (ha->type == GDT_ISA) {
-        dp2_ptr = (gdt2_dpram_str *)ha->brd;
+        dp2_ptr = ha->brd;
         gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, 
                     &dp2_ptr->u.ic.comm_queue[cmd_no].offset);
         gdth_writew((ushort)cmd_ptr->Service, 
                     &dp2_ptr->u.ic.comm_queue[cmd_no].serv_id);
         memcpy_toio(&dp2_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
     } else if (ha->type == GDT_PCI) {
-        dp6_ptr = (gdt6_dpram_str *)ha->brd;
+        dp6_ptr = ha->brd;
         gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, 
                     &dp6_ptr->u.ic.comm_queue[cmd_no].offset);
         gdth_writew((ushort)cmd_ptr->Service, 
                     &dp6_ptr->u.ic.comm_queue[cmd_no].serv_id);
         memcpy_toio(&dp6_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
     } else if (ha->type == GDT_PCINEW) {
-        dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
+        dp6c_ptr = ha->brd;
         gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, 
                     &dp6c_ptr->u.ic.comm_queue[cmd_no].offset);
         gdth_writew((ushort)cmd_ptr->Service, 
                     &dp6c_ptr->u.ic.comm_queue[cmd_no].serv_id);
         memcpy_toio(&dp6c_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
     } else if (ha->type == GDT_PCIMPR) {
-        dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
+        dp6m_ptr = ha->brd;
         gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, 
                     &dp6m_ptr->u.ic.comm_queue[cmd_no].offset);
         gdth_writew((ushort)cmd_ptr->Service, 
@@ -1780,13 +1778,13 @@ static void gdth_release_event(int hanum)
             outl(ha->ccb_phys, ha->bmic + MAILBOXREG);
         outb(ha->pccb->Service, ha->bmic + LDOORREG);
     } else if (ha->type == GDT_ISA) {
-        gdth_writeb(0, &((gdt2_dpram_str *)ha->brd)->io.event);
+        gdth_writeb(0, &((gdt2_dpram_str __iomem *)ha->brd)->io.event);
     } else if (ha->type == GDT_PCI) {
-        gdth_writeb(0, &((gdt6_dpram_str *)ha->brd)->io.event);
+        gdth_writeb(0, &((gdt6_dpram_str __iomem *)ha->brd)->io.event);
     } else if (ha->type == GDT_PCINEW) { 
         outb(1, PTR2USHORT(&ha->plx->ldoor_reg));
     } else if (ha->type == GDT_PCIMPR) {
-        gdth_writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.ldoor_reg);
+        gdth_writeb(1, &((gdt6m_dpram_str __iomem *)ha->brd)->i960r.ldoor_reg);
     }
 }
 
@@ -3419,7 +3417,7 @@ static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, ushort source,
     /* no GDTH_LOCK_HA() ! */
     TRACE2(("gdth_store_event() source %d idx %d\n", source, idx));
     if (source == 0)                        /* no source -> no event */
-        return 0;
+        return NULL;
 
     if (ebuffer[elastidx].event_source == source &&
         ebuffer[elastidx].event_idx == idx &&
@@ -3538,9 +3536,9 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
 #endif
 {
     register gdth_ha_str *ha;
-    gdt6m_dpram_str *dp6m_ptr = NULL;
-    gdt6_dpram_str *dp6_ptr;
-    gdt2_dpram_str *dp2_ptr;
+    gdt6m_dpram_str __iomem *dp6m_ptr = NULL;
+    gdt6_dpram_str __iomem *dp6_ptr;
+    gdt2_dpram_str __iomem *dp2_ptr;
     Scsi_Cmnd *scp;
     int hanum, rval, i;
     unchar IStatus;
@@ -3619,7 +3617,7 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
             outb(0xff, ha->bmic + EDOORREG);    /* acknowledge interrupt */
             outb(0x00, ha->bmic + SEMA1REG);    /* reset status semaphore */
         } else if (ha->type == GDT_ISA) {
-            dp2_ptr = (gdt2_dpram_str *)ha->brd;
+            dp2_ptr = ha->brd;
             if (IStatus & 0x80) {                       /* error flag */
                 IStatus &= ~0x80;
                 ha->status = gdth_readw(&dp2_ptr->u.ic.Status);
@@ -3634,7 +3632,7 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
             gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index);/* reset command index */
             gdth_writeb(0, &dp2_ptr->io.Sema1);     /* reset status semaphore */
         } else if (ha->type == GDT_PCI) {
-            dp6_ptr = (gdt6_dpram_str *)ha->brd;
+            dp6_ptr = ha->brd;
             if (IStatus & 0x80) {                       /* error flag */
                 IStatus &= ~0x80;
                 ha->status = gdth_readw(&dp6_ptr->u.ic.Status);
@@ -3662,7 +3660,7 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
             outb(0xff, PTR2USHORT(&ha->plx->edoor_reg)); 
             outb(0x00, PTR2USHORT(&ha->plx->sema1_reg)); 
         } else if (ha->type == GDT_PCIMPR) {
-            dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
+            dp6m_ptr = ha->brd;
             if (IStatus & 0x80) {                       /* error flag */
                 IStatus &= ~0x80;
 #ifdef INT_COAL
@@ -3692,10 +3690,10 @@ static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
                 if (ha->service != SCREENSERVICE &&
                     (ha->fw_vers & 0xff) >= 0x1a) {
                     ha->dvr.severity = gdth_readb
-                        (&((gdt6m_dpram_str *)ha->brd)->i960r.severity);
+                        (&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.severity);
                     for (i = 0; i < 256; ++i) {
                         ha->dvr.event_string[i] = gdth_readb
-                            (&((gdt6m_dpram_str *)ha->brd)->i960r.evt_str[i]);
+                            (&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.evt_str[i]);
                         if (ha->dvr.event_string[i] == 0)
                             break;
                     }
diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h
index 78a93cbac..bf269f05e 100644
--- a/drivers/scsi/gdth.h
+++ b/drivers/scsi/gdth.h
@@ -868,7 +868,7 @@ typedef struct {
     ushort              raw_feat;               /* feat. raw service (s/g,..)*/
     ushort              screen_feat;            /* feat. raw service (s/g,..)*/
     ushort              bmic;                   /* BMIC address (EISA) */
-    void                *brd;                   /* DPRAM address */
+    void __iomem        *brd;                   /* DPRAM address */
     ulong32             brd_phys;               /* slot number/BIOS address */
     gdt6c_plx_regs      *plx;                   /* PLX regs (new PCI contr.) */
     gdth_cmd_str        *pccb;                  /* address command structure */
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 12c5245c2..e552bac6d 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -75,9 +75,9 @@ void scsi_host_cancel(struct Scsi_Host *shost, int recovery)
  **/
 void scsi_remove_host(struct Scsi_Host *shost)
 {
+	scsi_forget_host(shost);
 	scsi_host_cancel(shost, 0);
 	scsi_proc_host_rm(shost);
-	scsi_forget_host(shost);
 
 	set_bit(SHOST_DEL, &shost->shost_state);
 
diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c
index 915d593fb..eda703d73 100644
--- a/drivers/scsi/imm.c
+++ b/drivers/scsi/imm.c
@@ -758,7 +758,7 @@ static void imm_interrupt(void *data)
 	case DID_OK:
 		break;
 	case DID_NO_CONNECT:
-		printk("imm: no device at SCSI ID %i\n", cmd->target);
+		printk("imm: no device at SCSI ID %i\n", cmd->device->id);
 		break;
 	case DID_BUS_BUSY:
 		printk("imm: BUS BUSY - EPP timeout detected\n");
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index bf3942769..40bfff7f2 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -1,7 +1,7 @@
 /*
  * ipr.c -- driver for IBM Power Linux RAID adapters
  *
- * Written By: Brian King, IBM Corporation
+ * Written By: Brian King <brking@us.ibm.com>, IBM Corporation
  *
  * Copyright (C) 2003, 2004 IBM Corporation
  *
@@ -93,7 +93,7 @@ static spinlock_t ipr_driver_lock = SPIN_LOCK_UNLOCKED;
 
 /* This table describes the differences between DMA controller chips */
 static const struct ipr_chip_cfg_t ipr_chip_cfg[] = {
-	{ /* Gemstone */
+	{ /* Gemstone and Citrine */
 		.mailbox = 0x0042C,
 		.cache_line_size = 0x20,
 		{
@@ -208,6 +208,8 @@ struct ipr_error_table_t ipr_error_table[] = {
 	"Synchronization required"},
 	{0x024E0000, 0, 0,
 	"No ready, IOA shutdown"},
+	{0x025A0000, 0, 0,
+	"Not ready, IOA has been shutdown"},
 	{0x02670100, 0, 1,
 	"3020: Storage subsystem configuration error"},
 	{0x03110B00, 0, 0,
@@ -880,11 +882,13 @@ static void ipr_process_ccn(struct ipr_cmnd *ipr_cmd)
  **/
 static void ipr_log_vpd(struct ipr_std_inq_vpids *vpids, u8 *serial_num)
 {
-	char buffer[max_t(int, sizeof(struct ipr_std_inq_vpids),
-			  IPR_SERIAL_NUM_LEN) + 1];
+	char buffer[IPR_VENDOR_ID_LEN + IPR_PROD_ID_LEN
+		    + IPR_SERIAL_NUM_LEN];
 
-	memcpy(buffer, vpids, sizeof(struct ipr_std_inq_vpids));
-	buffer[sizeof(struct ipr_std_inq_vpids)] = '\0';
+	memcpy(buffer, vpids->vendor_id, IPR_VENDOR_ID_LEN);
+	memcpy(buffer + IPR_VENDOR_ID_LEN, vpids->product_id,
+	       IPR_PROD_ID_LEN);
+	buffer[IPR_VENDOR_ID_LEN + IPR_PROD_ID_LEN] = '\0';
 	ipr_err("Vendor/Product ID: %s\n", buffer);
 
 	memcpy(buffer, serial_num, IPR_SERIAL_NUM_LEN);
@@ -1765,6 +1769,33 @@ static void ipr_get_ioa_dump(struct ipr_ioa_cfg *ioa_cfg, struct ipr_dump *dump)
 #define ipr_get_ioa_dump(ioa_cfg, dump) do { } while(0)
 #endif
 
+/**
+ * ipr_release_dump - Free adapter dump memory
+ * @kref:	kref struct
+ *
+ * Return value:
+ *	nothing
+ **/
+static void ipr_release_dump(struct kref *kref)
+{
+	struct ipr_dump *dump = container_of(kref,struct ipr_dump,kref);
+	struct ipr_ioa_cfg *ioa_cfg = dump->ioa_cfg;
+	unsigned long lock_flags = 0;
+	int i;
+
+	ENTER;
+	spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+	ioa_cfg->dump = NULL;
+	ioa_cfg->sdt_state = INACTIVE;
+	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+
+	for (i = 0; i < dump->ioa_dump.next_page_index; i++)
+		free_page((unsigned long) dump->ioa_dump.ioa_data[i]);
+
+	kfree(dump);
+	LEAVE;
+}
+
 /**
  * ipr_worker_thread - Worker thread
  * @data:		ioa config struct
@@ -1791,13 +1822,14 @@ static void ipr_worker_thread(void *data)
 
 	if (ioa_cfg->sdt_state == GET_DUMP) {
 		dump = ioa_cfg->dump;
-		if (!dump || !kobject_get(&dump->kobj)) {
+		if (!dump) {
 			spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 			return;
 		}
+		kref_get(&dump->kref);
 		spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 		ipr_get_ioa_dump(ioa_cfg, dump);
-		kobject_put(&dump->kobj);
+		kref_put(&dump->kref, ipr_release_dump);
 
 		spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
 		if (ioa_cfg->sdt_state == DUMP_OBTAINED)
@@ -2008,7 +2040,7 @@ static ssize_t ipr_store_diagnostics(struct class_device *class_dev,
 		wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
 
 		/* Wait for a second for any errors to be logged */
-		schedule_timeout(HZ);
+		msleep(1000);
 	} else {
 		spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 		return -EIO;
@@ -2392,15 +2424,15 @@ static ssize_t ipr_read_dump(struct kobject *kobj, char *buf,
 	spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
 	dump = ioa_cfg->dump;
 
-	if (ioa_cfg->sdt_state != DUMP_OBTAINED || !dump || !kobject_get(&dump->kobj)) {
+	if (ioa_cfg->sdt_state != DUMP_OBTAINED || !dump) {
 		spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 		return 0;
 	}
-
+	kref_get(&dump->kref);
 	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 
 	if (off > dump->driver_dump.hdr.len) {
-		kobject_put(&dump->kobj);
+		kref_put(&dump->kref, ipr_release_dump);
 		return 0;
 	}
 
@@ -2450,41 +2482,10 @@ static ssize_t ipr_read_dump(struct kobject *kobj, char *buf,
 		count -= len;
 	}
 
-	kobject_put(&dump->kobj);
+	kref_put(&dump->kref, ipr_release_dump);
 	return rc;
 }
 
-/**
- * ipr_release_dump - Free adapter dump memory
- * @kobj:	kobject struct
- *
- * Return value:
- *	nothing
- **/
-static void ipr_release_dump(struct kobject *kobj)
-{
-	struct ipr_dump *dump = container_of(kobj,struct ipr_dump,kobj);
-	struct ipr_ioa_cfg *ioa_cfg = dump->ioa_cfg;
-	unsigned long lock_flags = 0;
-	int i;
-
-	ENTER;
-	spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
-	ioa_cfg->dump = NULL;
-	ioa_cfg->sdt_state = INACTIVE;
-	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
-
-	for (i = 0; i < dump->ioa_dump.next_page_index; i++)
-		free_page((unsigned long) dump->ioa_dump.ioa_data[i]);
-
-	kfree(dump);
-	LEAVE;
-}
-
-static struct kobj_type ipr_dump_kobj_type = {
-	.release = ipr_release_dump,
-};
-
 /**
  * ipr_alloc_dump - Prepare for adapter dump
  * @ioa_cfg:	ioa config struct
@@ -2506,8 +2507,7 @@ static int ipr_alloc_dump(struct ipr_ioa_cfg *ioa_cfg)
 	}
 
 	memset(dump, 0, sizeof(struct ipr_dump));
-	kobject_init(&dump->kobj);
-	dump->kobj.ktype = &ipr_dump_kobj_type;
+	kref_init(&dump->kref);
 	dump->ioa_cfg = ioa_cfg;
 
 	spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
@@ -2554,7 +2554,7 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg)
 	ioa_cfg->dump = NULL;
 	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 
-	kobject_put(&dump->kobj);
+	kref_put(&dump->kref, ipr_release_dump);
 
 	LEAVE;
 	return 0;
@@ -2690,8 +2690,6 @@ static ssize_t ipr_store_tcq_enable(struct device *dev,
 	struct ipr_resource_entry *res;
 	unsigned long lock_flags = 0;
 	int tcq_active = simple_strtoul(buf, NULL, 10);
-	int qdepth = IPR_MAX_CMD_PER_LUN;
-	int tagged = 0;
 	ssize_t len = -ENXIO;
 
 	spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
@@ -2699,13 +2697,13 @@ static ssize_t ipr_store_tcq_enable(struct device *dev,
 	res = (struct ipr_resource_entry *)sdev->hostdata;
 
 	if (res) {
-		res->tcq_active = 0;
-		qdepth = res->qdepth;
-
 		if (ipr_is_gscsi(res) && sdev->tagged_supported) {
 			if (tcq_active) {
-				tagged = MSG_ORDERED_TAG;
 				res->tcq_active = 1;
+				scsi_activate_tcq(sdev, res->qdepth);
+			} else {
+				res->tcq_active = 0;
+				scsi_deactivate_tcq(sdev, res->qdepth);
 			}
 
 			len = strlen(buf);
@@ -2715,7 +2713,6 @@ static ssize_t ipr_store_tcq_enable(struct device *dev,
 	}
 
 	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
-	scsi_adjust_queue_depth(sdev, tagged, qdepth);
 	return len;
 }
 
@@ -2785,7 +2782,8 @@ static int ipr_biosparam(struct scsi_device *sdev,
 			 struct block_device *block_device,
 			 sector_t capacity, int *parm)
 {
-	int heads, sectors, cylinders;
+	int heads, sectors;
+	sector_t cylinders;
 
 	heads = 128;
 	sectors = 32;
@@ -2849,8 +2847,8 @@ static int ipr_slave_configure(struct scsi_device *sdev)
 			sdev->scsi_level = 4;
 		if (ipr_is_vset_device(res))
 			sdev->timeout = IPR_VSET_RW_TIMEOUT;
-
-		sdev->allow_restart = 1;
+		if (IPR_IS_DASD_DEVICE(res->cfgte.std_inq_data))
+			sdev->allow_restart = 1;
 		scsi_adjust_queue_depth(sdev, 0, res->qdepth);
 	}
 	spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
@@ -3080,7 +3078,7 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd)
 	struct ipr_ioa_cfg *ioa_cfg;
 	struct ipr_resource_entry *res;
 	struct ipr_cmd_pkt *cmd_pkt;
-	u32 ioasc, ioarcb_addr;
+	u32 ioasc;
 	int op_found = 0;
 
 	ENTER;
@@ -3101,21 +3099,15 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd)
 	if (!op_found)
 		return SUCCESS;
 
-	ioarcb_addr = be32_to_cpu(ipr_cmd->ioarcb.ioarcb_host_pci_addr);
-
 	ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
 	ipr_cmd->ioarcb.res_handle = res->cfgte.res_handle;
 	cmd_pkt = &ipr_cmd->ioarcb.cmd_pkt;
 	cmd_pkt->request_type = IPR_RQTYPE_IOACMD;
-	cmd_pkt->cdb[0] = IPR_ABORT_TASK;
-	cmd_pkt->cdb[2] = (ioarcb_addr >> 24) & 0xff;
-	cmd_pkt->cdb[3] = (ioarcb_addr >> 16) & 0xff;
-	cmd_pkt->cdb[4] = (ioarcb_addr >> 8) & 0xff;
-	cmd_pkt->cdb[5] = ioarcb_addr & 0xff;
+	cmd_pkt->cdb[0] = IPR_CANCEL_ALL_REQUESTS;
 	ipr_cmd->u.sdev = scsi_cmd->device;
 
 	ipr_sdev_err(scsi_cmd->device, "Aborting command: %02X\n", scsi_cmd->cmnd[0]);
-	ipr_send_blocking_cmd(ipr_cmd, ipr_abort_timeout, IPR_ABORT_TASK_TIMEOUT);
+	ipr_send_blocking_cmd(ipr_cmd, ipr_abort_timeout, IPR_CANCEL_ALL_TIMEOUT);
 	ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
 
 	/*
@@ -3737,7 +3729,7 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg,
 
 	switch (ioasc & IPR_IOASC_IOASC_MASK) {
 	case IPR_IOASC_ABORTED_CMD_TERM_BY_HOST:
-		scsi_cmd->result |= (DID_ERROR << 16);
+		scsi_cmd->result |= (DID_IMM_RETRY << 16);
 		break;
 	case IPR_IOASC_IR_RESOURCE_HANDLE:
 		scsi_cmd->result |= (DID_NO_CONNECT << 16);
@@ -3873,7 +3865,7 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd,
 	 * We have told the host to stop giving us new requests, but
 	 * ERP ops don't count. FIXME
 	 */
-	if (unlikely(!ioa_cfg->allow_cmds))
+	if (unlikely(!ioa_cfg->allow_cmds && !ioa_cfg->ioa_is_dead))
 		return SCSI_MLQUEUE_HOST_BUSY;
 
 	/*
@@ -5437,13 +5429,15 @@ static void ipr_free_mem(struct ipr_ioa_cfg *ioa_cfg)
  **/
 static void ipr_free_all_resources(struct ipr_ioa_cfg *ioa_cfg)
 {
+	struct pci_dev *pdev = ioa_cfg->pdev;
+
 	ENTER;
-	free_irq(ioa_cfg->pdev->irq, ioa_cfg);
+	free_irq(pdev->irq, ioa_cfg);
 	iounmap((void *) ioa_cfg->hdw_dma_regs);
-	release_mem_region(ioa_cfg->hdw_dma_regs_pci,
-			   pci_resource_len(ioa_cfg->pdev, 0));
+	pci_release_regions(pdev);
 	ipr_free_mem(ioa_cfg);
 	scsi_host_put(ioa_cfg->host);
+	pci_disable_device(pdev);
 	LEAVE;
 }
 
@@ -5458,7 +5452,7 @@ static int __devinit ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
 {
 	struct ipr_cmnd *ipr_cmd;
 	struct ipr_ioarcb *ioarcb;
-	u32 dma_addr;
+	dma_addr_t dma_addr;
 	int i;
 
 	ioa_cfg->ipr_cmd_pool = pci_pool_create (IPR_NAME, ioa_cfg->pdev,
@@ -5508,14 +5502,15 @@ static int __devinit ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg)
  **/
 static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
 {
-	int i;
+	struct pci_dev *pdev = ioa_cfg->pdev;
+	int i, rc = -ENOMEM;
 
 	ENTER;
 	ioa_cfg->res_entries = kmalloc(sizeof(struct ipr_resource_entry) *
 				       IPR_MAX_PHYSICAL_DEVS, GFP_KERNEL);
 
 	if (!ioa_cfg->res_entries)
-		goto cleanup;
+		goto out;
 
 	memset(ioa_cfg->res_entries, 0,
 	       sizeof(struct ipr_resource_entry) * IPR_MAX_PHYSICAL_DEVS);
@@ -5528,24 +5523,24 @@ static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
 						&ioa_cfg->vpd_cbs_dma);
 
 	if (!ioa_cfg->vpd_cbs)
-		goto cleanup;
+		goto out_free_res_entries;
 
 	if (ipr_alloc_cmd_blks(ioa_cfg))
-		goto cleanup;
+		goto out_free_vpd_cbs;
 
 	ioa_cfg->host_rrq = pci_alloc_consistent(ioa_cfg->pdev,
 						 sizeof(u32) * IPR_NUM_CMD_BLKS,
 						 &ioa_cfg->host_rrq_dma);
 
 	if (!ioa_cfg->host_rrq)
-		goto cleanup;
+		goto out_ipr_free_cmd_blocks;
 
 	ioa_cfg->cfg_table = pci_alloc_consistent(ioa_cfg->pdev,
 						  sizeof(struct ipr_config_table),
 						  &ioa_cfg->cfg_table_dma);
 
 	if (!ioa_cfg->cfg_table)
-		goto cleanup;
+		goto out_free_host_rrq;
 
 	for (i = 0; i < IPR_NUM_HCAMS; i++) {
 		ioa_cfg->hostrcb[i] = pci_alloc_consistent(ioa_cfg->pdev,
@@ -5553,9 +5548,8 @@ static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
 							   &ioa_cfg->hostrcb_dma[i]);
 
 		if (!ioa_cfg->hostrcb[i])
-			goto cleanup;
+			goto out_free_hostrcb_dma;
 
-		memset(ioa_cfg->hostrcb[i], 0, sizeof(struct ipr_hostrcb));
 		ioa_cfg->hostrcb[i]->hostrcb_dma =
 			ioa_cfg->hostrcb_dma[i] + offsetof(struct ipr_hostrcb, hcam);
 		list_add_tail(&ioa_cfg->hostrcb[i]->queue, &ioa_cfg->hostrcb_free_q);
@@ -5565,19 +5559,35 @@ static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
 				 IPR_NUM_TRACE_ENTRIES, GFP_KERNEL);
 
 	if (!ioa_cfg->trace)
-		goto cleanup;
+		goto out_free_hostrcb_dma;
 
 	memset(ioa_cfg->trace, 0,
 	       sizeof(struct ipr_trace_entry) * IPR_NUM_TRACE_ENTRIES);
 
+	rc = 0;
+out:
 	LEAVE;
-	return 0;
-
-cleanup:
-	ipr_free_mem(ioa_cfg);
+	return rc;
 
-	LEAVE;
-	return -ENOMEM;
+out_free_hostrcb_dma:
+	while (i-- > 0) {
+		pci_free_consistent(pdev, sizeof(struct ipr_hostrcb),
+				    ioa_cfg->hostrcb[i],
+				    ioa_cfg->hostrcb_dma[i]);
+	}
+	pci_free_consistent(pdev, sizeof(struct ipr_config_table),
+			    ioa_cfg->cfg_table, ioa_cfg->cfg_table_dma);
+out_free_host_rrq:
+	pci_free_consistent(pdev, sizeof(u32) * IPR_NUM_CMD_BLKS,
+			    ioa_cfg->host_rrq, ioa_cfg->host_rrq_dma);
+out_ipr_free_cmd_blocks:
+	ipr_free_cmd_blks(ioa_cfg);
+out_free_vpd_cbs:
+	pci_free_consistent(pdev, sizeof(struct ipr_misc_cbs),
+			    ioa_cfg->vpd_cbs, ioa_cfg->vpd_cbs_dma);
+out_free_res_entries:
+	kfree(ioa_cfg->res_entries);
+	goto out;
 }
 
 /**
@@ -5678,7 +5688,7 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
 
 	if ((rc = pci_enable_device(pdev))) {
 		dev_err(&pdev->dev, "Cannot enable adapter\n");
-		return rc;
+		goto out;
 	}
 
 	dev_info(&pdev->dev, "Found IOA with IRQ: %d\n", pdev->irq);
@@ -5687,7 +5697,8 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
 
 	if (!host) {
 		dev_err(&pdev->dev, "call to scsi_host_alloc failed!\n");
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto out_disable;
 	}
 
 	ioa_cfg = (struct ipr_ioa_cfg *)host->hostdata;
@@ -5697,12 +5708,11 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
 
 	ipr_regs_pci = pci_resource_start(pdev, 0);
 
-	if (!request_mem_region(ipr_regs_pci,
-				pci_resource_len(pdev, 0), IPR_NAME)) {
+	rc = pci_request_regions(pdev, IPR_NAME);
+	if (rc < 0) {
 		dev_err(&pdev->dev,
 			"Couldn't register memory range of registers\n");
-		scsi_host_put(host);
-		return -ENOMEM;
+		goto out_scsi_host_put;
 	}
 
 	ipr_regs = (unsigned long)ioremap(ipr_regs_pci,
@@ -5711,9 +5721,8 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
 	if (!ipr_regs) {
 		dev_err(&pdev->dev,
 			"Couldn't map memory range of registers\n");
-		release_mem_region(ipr_regs_pci, pci_resource_len(pdev, 0));
-		scsi_host_put(host);
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto out_release_regions;
 	}
 
 	ioa_cfg->hdw_dma_regs = ipr_regs;
@@ -5723,11 +5732,10 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
 	ipr_init_ioa_cfg(ioa_cfg, host, pdev);
 
 	pci_set_master(pdev);
-	rc = pci_set_dma_mask(pdev, 0xffffffff);
 
-	if (rc != PCIBIOS_SUCCESSFUL) {
+	rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+	if (rc < 0) {
 		dev_err(&pdev->dev, "Failed to set PCI DMA mask\n");
-		rc = -EIO;
 		goto cleanup_nomem;
 	}
 
@@ -5755,8 +5763,12 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
 	if ((rc = ipr_set_pcix_cmd_reg(ioa_cfg)))
 		goto cleanup_nomem;
 
-	if ((rc = ipr_alloc_mem(ioa_cfg)))
-		goto cleanup;
+	rc = ipr_alloc_mem(ioa_cfg);
+	if (rc < 0) {
+		dev_err(&pdev->dev,
+			"Couldn't allocate enough memory for device driver!\n");
+		goto cleanup_nomem;
+	}
 
 	ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER);
 	rc = request_irq(pdev->irq, ipr_isr, SA_SHIRQ, IPR_NAME, ioa_cfg);
@@ -5772,18 +5784,20 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
 	spin_unlock(&ipr_driver_lock);
 
 	LEAVE;
-	return 0;
+out:
+	return rc;
 
-cleanup:
-	dev_err(&pdev->dev, "Couldn't allocate enough memory for device driver!\n");
 cleanup_nolog:
 	ipr_free_mem(ioa_cfg);
 cleanup_nomem:
 	iounmap((void *) ipr_regs);
-	release_mem_region(ipr_regs_pci, pci_resource_len(pdev, 0));
+out_release_regions:
+	pci_release_regions(pdev);
+out_scsi_host_put:
 	scsi_host_put(host);
-
-	return rc;
+out_disable:
+	pci_disable_device(pdev);
+	goto out;
 }
 
 /**
@@ -5988,9 +6002,15 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = {
 	{ PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE,
 		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_573D,
 	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
+	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE,
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571B,
+	      0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
 	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE,
 		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780,
 		0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] },
+	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE,
+		PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_570F,
+		0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] },
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, ipr_pci_table);
@@ -6009,16 +6029,14 @@ static struct pci_driver ipr_driver = {
  * ipr_init - Module entry point
  *
  * Return value:
- * 	0 on success / non-zero on failure
+ * 	0 on success / negative value on failure
  **/
 static int __init ipr_init(void)
 {
 	ipr_info("IBM Power RAID SCSI Device Driver version: %s %s\n",
 		 IPR_DRIVER_VERSION, IPR_DRIVER_DATE);
 
-	pci_register_driver(&ipr_driver);
-
-	return 0;
+	return pci_module_init(&ipr_driver);
 }
 
 /**
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 6d616ac42..e91afc446 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -1,7 +1,7 @@
 /*
  * ipr.h -- driver for IBM Power Linux RAID adapters
  *
- * Written By: Brian King, IBM Corporation
+ * Written By: Brian King <brking@us.ibm.com>, IBM Corporation
  *
  * Copyright (C) 2003, 2004 IBM Corporation
  *
@@ -19,6 +19,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
+ * Alan Cox <alan@redhat.com> - Removed several careless u32/dma_addr_t errors
+ *				that broke 64bit platforms.
  */
 
 #ifndef _IPR_H
@@ -27,6 +29,7 @@
 #include <linux/types.h>
 #include <linux/completion.h>
 #include <linux/list.h>
+#include <linux/kref.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #ifdef CONFIG_KDB
@@ -36,8 +39,8 @@
 /*
  * Literals
  */
-#define IPR_DRIVER_VERSION "2.0.10"
-#define IPR_DRIVER_DATE "(June 7, 2004)"
+#define IPR_DRIVER_VERSION "2.0.11"
+#define IPR_DRIVER_DATE "(August 3, 2004)"
 
 /*
  * IPR_DBG_TRACE: Setting this to 1 will turn on some general function tracing
@@ -72,6 +75,8 @@
 #define IPR_SUBS_DEV_ID_5703	0x0278
 #define IPR_SUBS_DEV_ID_572E  0x02D3
 #define IPR_SUBS_DEV_ID_573D  0x02D4
+#define IPR_SUBS_DEV_ID_570F	0x02BD
+#define IPR_SUBS_DEV_ID_571B	0x02BE
 
 #define IPR_NAME				"ipr"
 
@@ -148,7 +153,6 @@
 #define	IPR_BUS_RESET					0x10
 #define IPR_ID_HOST_RR_Q				0xC4
 #define IPR_QUERY_IOA_CONFIG				0xC5
-#define IPR_ABORT_TASK					0xC7
 #define IPR_CANCEL_ALL_REQUESTS			0xCE
 #define IPR_HOST_CONTROLLED_ASYNC			0xCF
 #define	IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE	0x01
@@ -667,7 +671,7 @@ struct ipr_hcam {
 
 struct ipr_hostrcb {
 	struct ipr_hcam hcam;
-	u32 hostrcb_dma;
+	dma_addr_t hostrcb_dma;
 	struct list_head queue;
 };
 
@@ -850,7 +854,7 @@ struct ipr_ioa_cfg {
 	char cfg_table_start[8];
 #define IPR_CFG_TBL_START		"cfg"
 	struct ipr_config_table *cfg_table;
-	u32 cfg_table_dma;
+	dma_addr_t cfg_table_dma;
 
 	char resource_table_label[8];
 #define IPR_RES_TABLE_LABEL		"res_tbl"
@@ -861,12 +865,12 @@ struct ipr_ioa_cfg {
 	char ipr_hcam_label[8];
 #define IPR_HCAM_LABEL			"hcams"
 	struct ipr_hostrcb *hostrcb[IPR_NUM_HCAMS];
-	u32 hostrcb_dma[IPR_NUM_HCAMS];
+	dma_addr_t hostrcb_dma[IPR_NUM_HCAMS];
 	struct list_head hostrcb_free_q;
 	struct list_head hostrcb_pending_q;
 
 	u32 *host_rrq;
-	u32 host_rrq_dma;
+	dma_addr_t host_rrq_dma;
 #define IPR_HRRQ_REQ_RESP_HANDLE_MASK	0xfffffffc
 #define IPR_HRRQ_RESP_BIT_SET			0x00000002
 #define IPR_HRRQ_TOGGLE_BIT				0x00000001
@@ -905,7 +909,7 @@ struct ipr_ioa_cfg {
 	enum ipr_sdt_state sdt_state;
 
 	struct ipr_misc_cbs *vpd_cbs;
-	u32 vpd_cbs_dma;
+	dma_addr_t vpd_cbs_dma;
 
 	struct pci_pool *ipr_cmd_pool;
 
@@ -1029,7 +1033,7 @@ struct ipr_ioa_dump {
 }__attribute__((packed, aligned (4)));
 
 struct ipr_dump {
-	struct kobject kobj;
+	struct kref kref;
 	struct ipr_ioa_cfg *ioa_cfg;
 	struct ipr_driver_dump driver_dump;
 	struct ipr_ioa_dump ioa_dump;
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index dc110cc80..b2e7c233c 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -215,7 +215,7 @@ MODULE_PARM(ips, "s");
 #endif
 #else
 #define IPS_SG_ADDRESS(sg)      (page_address((sg)->page) ? \
-                                     page_address((sg)->page)+(sg)->offset : 0)
+                                   page_address((sg)->page)+(sg)->offset : NULL)
 #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
@@ -474,21 +474,17 @@ static uint32_t ips_statupd_copperhead(ips_ha_t *);
 static uint32_t ips_statupd_copperhead_memio(ips_ha_t *);
 static uint32_t ips_statupd_morpheus(ips_ha_t *);
 static ips_scb_t *ips_getscb(ips_ha_t *);
-static inline void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *);
-static inline void ips_putq_scb_tail(ips_scb_queue_t *, ips_scb_t *);
-static inline void ips_putq_wait_head(ips_wait_queue_t *, Scsi_Cmnd *);
-static inline void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *);
-static inline void ips_putq_copp_head(ips_copp_queue_t *,
+static void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *);
+static void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *);
+static void ips_putq_copp_tail(ips_copp_queue_t *,
 				      ips_copp_wait_item_t *);
-static inline void ips_putq_copp_tail(ips_copp_queue_t *,
-				      ips_copp_wait_item_t *);
-static inline ips_scb_t *ips_removeq_scb_head(ips_scb_queue_t *);
-static inline ips_scb_t *ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *);
-static inline Scsi_Cmnd *ips_removeq_wait_head(ips_wait_queue_t *);
-static inline Scsi_Cmnd *ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *);
-static inline ips_copp_wait_item_t *ips_removeq_copp(ips_copp_queue_t *,
+static ips_scb_t *ips_removeq_scb_head(ips_scb_queue_t *);
+static ips_scb_t *ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *);
+static Scsi_Cmnd *ips_removeq_wait_head(ips_wait_queue_t *);
+static Scsi_Cmnd *ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *);
+static ips_copp_wait_item_t *ips_removeq_copp(ips_copp_queue_t *,
 						     ips_copp_wait_item_t *);
-static inline ips_copp_wait_item_t *ips_removeq_copp_head(ips_copp_queue_t *);
+static ips_copp_wait_item_t *ips_removeq_copp_head(ips_copp_queue_t *);
 
 static int ips_is_passthru(Scsi_Cmnd *);
 static int ips_make_passthru(ips_ha_t *, Scsi_Cmnd *, ips_scb_t *, int);
@@ -1885,7 +1881,7 @@ ips_flash_bios(ips_ha_t * ha, ips_passthru_t * pt, ips_scb_t * scb)
 /*   Fill in a single scb sg_list element from an address                   */
 /*   return a -1 if a breakup occurred                                      */
 /****************************************************************************/
-static inline int
+static int
 ips_fill_scb_sg_single(ips_ha_t * ha, dma_addr_t busaddr,
 		       ips_scb_t * scb, int indx, unsigned int e_len)
 {
@@ -2950,7 +2946,7 @@ ips_next(ips_ha_t * ha, int intr)
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline void
+static void
 ips_putq_scb_head(ips_scb_queue_t * queue, ips_scb_t * item)
 {
 	METHOD_TRACE("ips_putq_scb_head", 1);
@@ -2967,38 +2963,6 @@ ips_putq_scb_head(ips_scb_queue_t * queue, ips_scb_t * item)
 	queue->count++;
 }
 
-/****************************************************************************/
-/*                                                                          */
-/* Routine Name: ips_putq_scb_tail                                          */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   Add an item to the tail of the queue                                   */
-/*                                                                          */
-/* ASSUMED to be called from within the HA lock                             */
-/*                                                                          */
-/****************************************************************************/
-static inline void
-ips_putq_scb_tail(ips_scb_queue_t * queue, ips_scb_t * item)
-{
-	METHOD_TRACE("ips_putq_scb_tail", 1);
-
-	if (!item)
-		return;
-
-	item->q_next = NULL;
-
-	if (queue->tail)
-		queue->tail->q_next = item;
-
-	queue->tail = item;
-
-	if (!queue->head)
-		queue->head = item;
-
-	queue->count++;
-}
-
 /****************************************************************************/
 /*                                                                          */
 /* Routine Name: ips_removeq_scb_head                                       */
@@ -3010,7 +2974,7 @@ ips_putq_scb_tail(ips_scb_queue_t * queue, ips_scb_t * item)
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline ips_scb_t *
+static ips_scb_t *
 ips_removeq_scb_head(ips_scb_queue_t * queue)
 {
 	ips_scb_t *item;
@@ -3045,7 +3009,7 @@ ips_removeq_scb_head(ips_scb_queue_t * queue)
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline ips_scb_t *
+static ips_scb_t *
 ips_removeq_scb(ips_scb_queue_t * queue, ips_scb_t * item)
 {
 	ips_scb_t *p;
@@ -3080,34 +3044,6 @@ ips_removeq_scb(ips_scb_queue_t * queue, ips_scb_t * item)
 	return (NULL);
 }
 
-/****************************************************************************/
-/*                                                                          */
-/* Routine Name: ips_putq_wait_head                                         */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   Add an item to the head of the queue                                   */
-/*                                                                          */
-/* ASSUMED to be called from within the HA lock                             */
-/*                                                                          */
-/****************************************************************************/
-static inline void
-ips_putq_wait_head(ips_wait_queue_t * queue, Scsi_Cmnd * item)
-{
-	METHOD_TRACE("ips_putq_wait_head", 1);
-
-	if (!item)
-		return;
-
-	item->host_scribble = (char *) queue->head;
-	queue->head = item;
-
-	if (!queue->tail)
-		queue->tail = item;
-
-	queue->count++;
-}
-
 /****************************************************************************/
 /*                                                                          */
 /* Routine Name: ips_putq_wait_tail                                         */
@@ -3119,7 +3055,7 @@ ips_putq_wait_head(ips_wait_queue_t * queue, Scsi_Cmnd * item)
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline void
+static void
 ips_putq_wait_tail(ips_wait_queue_t * queue, Scsi_Cmnd * item)
 {
 	METHOD_TRACE("ips_putq_wait_tail", 1);
@@ -3151,7 +3087,7 @@ ips_putq_wait_tail(ips_wait_queue_t * queue, Scsi_Cmnd * item)
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline Scsi_Cmnd *
+static Scsi_Cmnd *
 ips_removeq_wait_head(ips_wait_queue_t * queue)
 {
 	Scsi_Cmnd *item;
@@ -3186,7 +3122,7 @@ ips_removeq_wait_head(ips_wait_queue_t * queue)
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline Scsi_Cmnd *
+static Scsi_Cmnd *
 ips_removeq_wait(ips_wait_queue_t * queue, Scsi_Cmnd * item)
 {
 	Scsi_Cmnd *p;
@@ -3221,34 +3157,6 @@ ips_removeq_wait(ips_wait_queue_t * queue, Scsi_Cmnd * item)
 	return (NULL);
 }
 
-/****************************************************************************/
-/*                                                                          */
-/* Routine Name: ips_putq_copp_head                                         */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   Add an item to the head of the queue                                   */
-/*                                                                          */
-/* ASSUMED to be called from within the HA lock                             */
-/*                                                                          */
-/****************************************************************************/
-static inline void
-ips_putq_copp_head(ips_copp_queue_t * queue, ips_copp_wait_item_t * item)
-{
-	METHOD_TRACE("ips_putq_copp_head", 1);
-
-	if (!item)
-		return;
-
-	item->next = queue->head;
-	queue->head = item;
-
-	if (!queue->tail)
-		queue->tail = item;
-
-	queue->count++;
-}
-
 /****************************************************************************/
 /*                                                                          */
 /* Routine Name: ips_putq_copp_tail                                         */
@@ -3260,7 +3168,7 @@ ips_putq_copp_head(ips_copp_queue_t * queue, ips_copp_wait_item_t * item)
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline void
+static void
 ips_putq_copp_tail(ips_copp_queue_t * queue, ips_copp_wait_item_t * item)
 {
 	METHOD_TRACE("ips_putq_copp_tail", 1);
@@ -3292,7 +3200,7 @@ ips_putq_copp_tail(ips_copp_queue_t * queue, ips_copp_wait_item_t * item)
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline ips_copp_wait_item_t *
+static ips_copp_wait_item_t *
 ips_removeq_copp_head(ips_copp_queue_t * queue)
 {
 	ips_copp_wait_item_t *item;
@@ -3327,7 +3235,7 @@ ips_removeq_copp_head(ips_copp_queue_t * queue)
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline ips_copp_wait_item_t *
+static ips_copp_wait_item_t *
 ips_removeq_copp(ips_copp_queue_t * queue, ips_copp_wait_item_t * item)
 {
 	ips_copp_wait_item_t *p;
@@ -6946,8 +6854,8 @@ ips_abort_init(ips_ha_t * ha, int index)
 {
 	ha->active = 0;
 	ips_free(ha);
-	ips_ha[index] = 0;
-	ips_sh[index] = 0;
+	ips_ha[index] = NULL;
+	ips_sh[index] = NULL;
 	return -1;
 }
 
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 7f2d11d87..8325e0912 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -43,18 +43,21 @@
 #include <linux/libata.h>
 #include <asm/io.h>
 #include <asm/semaphore.h>
+#include <asm/byteorder.h>
 
 #include "libata.h"
 
 static unsigned int ata_busy_sleep (struct ata_port *ap,
 				    unsigned long tmout_pat,
 			    	    unsigned long tmout);
-static void __ata_dev_select (struct ata_port *ap, unsigned int device);
-static void ata_host_set_pio(struct ata_port *ap);
-static void ata_host_set_udma(struct ata_port *ap);
-static void ata_dev_set_pio(struct ata_port *ap, unsigned int device);
-static void ata_dev_set_udma(struct ata_port *ap, unsigned int device);
 static void ata_set_mode(struct ata_port *ap);
+static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev);
+static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift);
+static int fgb(u32 bitmap);
+static int ata_choose_xfer_mode(struct ata_port *ap,
+				u8 *xfer_mode_out,
+				unsigned int *xfer_shift_out);
+static int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat);
 
 static unsigned int ata_unique_id = 1;
 static struct workqueue_struct *ata_wq;
@@ -64,17 +67,17 @@ MODULE_DESCRIPTION("Library module for ATA devices");
 MODULE_LICENSE("GPL");
 
 /**
- *	ata_tf_load_pio - send taskfile registers to host controller
+ *	ata_tf_load - send taskfile registers to host controller
  *	@ap: Port to which output is sent
  *	@tf: ATA taskfile register set
  *
- *	Outputs ATA taskfile to standard ATA host controller using PIO.
+ *	Outputs ATA taskfile to standard ATA host controller.
  *
  *	LOCKING:
  *	Inherited from caller.
  */
 
-void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
@@ -132,23 +135,23 @@ void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf)
  *	Inherited from caller.
  */
 
-void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
 
 	if (tf->ctl != ap->last_ctl) {
-		writeb(tf->ctl, ap->ioaddr.ctl_addr);
+		writeb(tf->ctl, (void __iomem *) ap->ioaddr.ctl_addr);
 		ap->last_ctl = tf->ctl;
 		ata_wait_idle(ap);
 	}
 
 	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
-		writeb(tf->hob_feature, (void *) ioaddr->feature_addr);
-		writeb(tf->hob_nsect, (void *) ioaddr->nsect_addr);
-		writeb(tf->hob_lbal, (void *) ioaddr->lbal_addr);
-		writeb(tf->hob_lbam, (void *) ioaddr->lbam_addr);
-		writeb(tf->hob_lbah, (void *) ioaddr->lbah_addr);
+		writeb(tf->hob_feature, (void __iomem *) ioaddr->feature_addr);
+		writeb(tf->hob_nsect, (void __iomem *) ioaddr->nsect_addr);
+		writeb(tf->hob_lbal, (void __iomem *) ioaddr->lbal_addr);
+		writeb(tf->hob_lbam, (void __iomem *) ioaddr->lbam_addr);
+		writeb(tf->hob_lbah, (void __iomem *) ioaddr->lbah_addr);
 		VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
 			tf->hob_feature,
 			tf->hob_nsect,
@@ -158,11 +161,11 @@ void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 	}
 
 	if (is_addr) {
-		writeb(tf->feature, (void *) ioaddr->feature_addr);
-		writeb(tf->nsect, (void *) ioaddr->nsect_addr);
-		writeb(tf->lbal, (void *) ioaddr->lbal_addr);
-		writeb(tf->lbam, (void *) ioaddr->lbam_addr);
-		writeb(tf->lbah, (void *) ioaddr->lbah_addr);
+		writeb(tf->feature, (void __iomem *) ioaddr->feature_addr);
+		writeb(tf->nsect, (void __iomem *) ioaddr->nsect_addr);
+		writeb(tf->lbal, (void __iomem *) ioaddr->lbal_addr);
+		writeb(tf->lbam, (void __iomem *) ioaddr->lbam_addr);
+		writeb(tf->lbah, (void __iomem *) ioaddr->lbah_addr);
 		VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
 			tf->feature,
 			tf->nsect,
@@ -172,26 +175,34 @@ void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 	}
 
 	if (tf->flags & ATA_TFLAG_DEVICE) {
-		writeb(tf->device, (void *) ioaddr->device_addr);
+		writeb(tf->device, (void __iomem *) ioaddr->device_addr);
 		VPRINTK("device 0x%X\n", tf->device);
 	}
 
 	ata_wait_idle(ap);
 }
 
+void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	if (ap->flags & ATA_FLAG_MMIO)
+		ata_tf_load_mmio(ap, tf);
+	else
+		ata_tf_load_pio(ap, tf);
+}
+
 /**
- *	ata_exec_command_pio - issue ATA command to host controller
+ *	ata_exec_command - issue ATA command to host controller
  *	@ap: port to which command is being issued
  *	@tf: ATA taskfile register set
  *
- *	Issues PIO write to ATA command register, with proper
+ *	Issues PIO/MMIO write to ATA command register, with proper
  *	synchronization with interrupt handler / other threads.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
 
@@ -212,20 +223,28 @@ void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf)
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
 
-       	writeb(tf->command, (void *) ap->ioaddr.command_addr);
+       	writeb(tf->command, (void __iomem *) ap->ioaddr.command_addr);
 	ata_pause(ap);
 }
 
+void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	if (ap->flags & ATA_FLAG_MMIO)
+		ata_exec_command_mmio(ap, tf);
+	else
+		ata_exec_command_pio(ap, tf);
+}
+
 /**
  *	ata_exec - issue ATA command to host controller
  *	@ap: port to which command is being issued
  *	@tf: ATA taskfile register set
  *
- *	Issues PIO write to ATA command register, with proper
+ *	Issues PIO/MMIO write to ATA command register, with proper
  *	synchronization with interrupt handler / other threads.
  *
  *	LOCKING:
@@ -248,7 +267,7 @@ static inline void ata_exec(struct ata_port *ap, struct ata_taskfile *tf)
  *	@tf: ATA taskfile register set
  *
  *	Issues ATA taskfile register set to ATA host controller,
- *	via PIO, with proper synchronization with interrupt handler and
+ *	with proper synchronization with interrupt handler and
  *	other threads.
  *
  *	LOCKING:
@@ -268,7 +287,7 @@ static void ata_tf_to_host(struct ata_port *ap, struct ata_taskfile *tf)
  *	@tf: ATA taskfile register set
  *
  *	Issues ATA taskfile register set to ATA host controller,
- *	via PIO, with proper synchronization with interrupt handler and
+ *	with proper synchronization with interrupt handler and
  *	other threads.
  *
  *	LOCKING:
@@ -282,18 +301,18 @@ void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf)
 }
 
 /**
- *	ata_tf_read_pio - input device's ATA taskfile shadow registers
+ *	ata_tf_read - input device's ATA taskfile shadow registers
  *	@ap: Port from which input is read
  *	@tf: ATA taskfile register set for storing input
  *
  *	Reads ATA taskfile registers for currently-selected device
- *	into @tf via PIO.
+ *	into @tf.
  *
  *	LOCKING:
  *	Inherited from caller.
  */
 
-void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 
@@ -325,38 +344,46 @@ void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf)
  *	Inherited from caller.
  */
 
-void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 
-	tf->nsect = readb((void *)ioaddr->nsect_addr);
-	tf->lbal = readb((void *)ioaddr->lbal_addr);
-	tf->lbam = readb((void *)ioaddr->lbam_addr);
-	tf->lbah = readb((void *)ioaddr->lbah_addr);
-	tf->device = readb((void *)ioaddr->device_addr);
+	tf->nsect = readb((void __iomem *)ioaddr->nsect_addr);
+	tf->lbal = readb((void __iomem *)ioaddr->lbal_addr);
+	tf->lbam = readb((void __iomem *)ioaddr->lbam_addr);
+	tf->lbah = readb((void __iomem *)ioaddr->lbah_addr);
+	tf->device = readb((void __iomem *)ioaddr->device_addr);
 
 	if (tf->flags & ATA_TFLAG_LBA48) {
-		writeb(tf->ctl | ATA_HOB, ap->ioaddr.ctl_addr);
-		tf->hob_feature = readb((void *)ioaddr->error_addr);
-		tf->hob_nsect = readb((void *)ioaddr->nsect_addr);
-		tf->hob_lbal = readb((void *)ioaddr->lbal_addr);
-		tf->hob_lbam = readb((void *)ioaddr->lbam_addr);
-		tf->hob_lbah = readb((void *)ioaddr->lbah_addr);
+		writeb(tf->ctl | ATA_HOB, (void __iomem *) ap->ioaddr.ctl_addr);
+		tf->hob_feature = readb((void __iomem *)ioaddr->error_addr);
+		tf->hob_nsect = readb((void __iomem *)ioaddr->nsect_addr);
+		tf->hob_lbal = readb((void __iomem *)ioaddr->lbal_addr);
+		tf->hob_lbam = readb((void __iomem *)ioaddr->lbam_addr);
+		tf->hob_lbah = readb((void __iomem *)ioaddr->lbah_addr);
 	}
 }
 
+void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	if (ap->flags & ATA_FLAG_MMIO)
+		ata_tf_read_mmio(ap, tf);
+	else
+		ata_tf_read_pio(ap, tf);
+}
+
 /**
- *	ata_check_status_pio - Read device status reg & clear interrupt
+ *	ata_check_status - Read device status reg & clear interrupt
  *	@ap: port where the device is
  *
  *	Reads ATA taskfile status register for currently-selected device
- *	via PIO and return it's value. This also clears pending interrupts
+ *	and return it's value. This also clears pending interrupts
  *      from this device
  *
  *	LOCKING:
  *	Inherited from caller.
  */
-u8 ata_check_status_pio(struct ata_port *ap)
+static u8 ata_check_status_pio(struct ata_port *ap)
 {
 	return inb(ap->ioaddr.status_addr);
 }
@@ -372,9 +399,16 @@ u8 ata_check_status_pio(struct ata_port *ap)
  *	LOCKING:
  *	Inherited from caller.
  */
-u8 ata_check_status_mmio(struct ata_port *ap)
+static u8 ata_check_status_mmio(struct ata_port *ap)
+{
+       	return readb((void __iomem *) ap->ioaddr.status_addr);
+}
+
+u8 ata_check_status(struct ata_port *ap)
 {
-       	return readb((void *) ap->ioaddr.status_addr);
+	if (ap->flags & ATA_FLAG_MMIO)
+		return ata_check_status_mmio(ap);
+	return ata_check_status_pio(ap);
 }
 
 /**
@@ -524,7 +558,7 @@ static void ata_dev_set_protocol(struct ata_device *dev)
 	dev->write_cmd = (cmd >> 8) & 0xff;
 }
 
-static const char * udma_str[] = {
+static const char * xfer_mode_str[] = {
 	"UDMA/16",
 	"UDMA/25",
 	"UDMA/33",
@@ -533,6 +567,14 @@ static const char * udma_str[] = {
 	"UDMA/100",
 	"UDMA/133",
 	"UDMA7",
+	"MWDMA0",
+	"MWDMA1",
+	"MWDMA2",
+	"PIO0",
+	"PIO1",
+	"PIO2",
+	"PIO3",
+	"PIO4",
 };
 
 /**
@@ -550,16 +592,24 @@ static const char * udma_str[] = {
  *	@udma_mask, or the constant C string "<n/a>".
  */
 
-static const char *ata_udma_string(unsigned int udma_mask)
+static const char *ata_mode_string(unsigned int mask)
 {
 	int i;
 
-	for (i = 7; i >= 0; i--) {
-		if (udma_mask & (1 << i))
-			return udma_str[i];
-	}
+	for (i = 7; i >= 0; i--)
+		if (mask & (1 << i))
+			goto out;
+	for (i = ATA_SHIFT_MWDMA + 2; i >= ATA_SHIFT_MWDMA; i--)
+		if (mask & (1 << i))
+			goto out;
+	for (i = ATA_SHIFT_PIO + 4; i >= ATA_SHIFT_PIO; i--)
+		if (mask & (1 << i))
+			goto out;
 
 	return "<n/a>";
+
+out:
+	return xfer_mode_str[i];
 }
 
 /**
@@ -586,7 +636,7 @@ static unsigned int ata_pio_devchk(struct ata_port *ap,
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 	u8 nsect, lbal;
 
-	__ata_dev_select(ap, device);
+	ap->ops->dev_select(ap, device);
 
 	outb(0x55, ioaddr->nsect_addr);
 	outb(0xaa, ioaddr->lbal_addr);
@@ -630,19 +680,19 @@ static unsigned int ata_mmio_devchk(struct ata_port *ap,
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 	u8 nsect, lbal;
 
-	__ata_dev_select(ap, device);
+	ap->ops->dev_select(ap, device);
 
-	writeb(0x55, (void *) ioaddr->nsect_addr);
-	writeb(0xaa, (void *) ioaddr->lbal_addr);
+	writeb(0x55, (void __iomem *) ioaddr->nsect_addr);
+	writeb(0xaa, (void __iomem *) ioaddr->lbal_addr);
 
-	writeb(0xaa, (void *) ioaddr->nsect_addr);
-	writeb(0x55, (void *) ioaddr->lbal_addr);
+	writeb(0xaa, (void __iomem *) ioaddr->nsect_addr);
+	writeb(0x55, (void __iomem *) ioaddr->lbal_addr);
 
-	writeb(0x55, (void *) ioaddr->nsect_addr);
-	writeb(0xaa, (void *) ioaddr->lbal_addr);
+	writeb(0x55, (void __iomem *) ioaddr->nsect_addr);
+	writeb(0xaa, (void __iomem *) ioaddr->lbal_addr);
 
-	nsect = readb((void *) ioaddr->nsect_addr);
-	lbal = readb((void *) ioaddr->lbal_addr);
+	nsect = readb((void __iomem *) ioaddr->nsect_addr);
+	lbal = readb((void __iomem *) ioaddr->lbal_addr);
 
 	if ((nsect == 0x55) && (lbal == 0xaa))
 		return 1;	/* we found a device */
@@ -651,7 +701,7 @@ static unsigned int ata_mmio_devchk(struct ata_port *ap,
 }
 
 /**
- *	ata_dev_devchk - PATA device presence detection
+ *	ata_devchk - PATA device presence detection
  *	@ap: ATA channel to examine
  *	@device: Device to examine (starting at zero)
  *
@@ -663,7 +713,7 @@ static unsigned int ata_mmio_devchk(struct ata_port *ap,
  *	caller.
  */
 
-static unsigned int ata_dev_devchk(struct ata_port *ap,
+static unsigned int ata_devchk(struct ata_port *ap,
 				    unsigned int device)
 {
 	if (ap->flags & ATA_FLAG_MMIO)
@@ -687,7 +737,7 @@ static unsigned int ata_dev_devchk(struct ata_port *ap,
  *	the event of failure.
  */
 
-static unsigned int ata_dev_classify(struct ata_taskfile *tf)
+unsigned int ata_dev_classify(struct ata_taskfile *tf)
 {
 	/* Apple's open source Darwin code hints that some devices only
 	 * put a proper signature into the LBA mid/high registers,
@@ -735,7 +785,7 @@ static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device)
 	unsigned int class;
 	u8 err;
 
-	__ata_dev_select(ap, device);
+	ap->ops->dev_select(ap, device);
 
 	memset(&tf, 0, sizeof(tf));
 
@@ -798,8 +848,12 @@ void ata_dev_id_string(struct ata_device *dev, unsigned char *s,
 	}
 }
 
+void ata_noop_dev_select (struct ata_port *ap, unsigned int device)
+{
+}
+
 /**
- *	__ata_dev_select - Select device 0/1 on ATA bus
+ *	ata_std_dev_select - Select device 0/1 on ATA bus
  *	@ap: ATA channel to manipulate
  *	@device: ATA device (numbered from zero) to select
  *
@@ -811,7 +865,7 @@ void ata_dev_id_string(struct ata_device *dev, unsigned char *s,
  *	caller.
  */
 
-static void __ata_dev_select (struct ata_port *ap, unsigned int device)
+void ata_std_dev_select (struct ata_port *ap, unsigned int device)
 {
 	u8 tmp;
 
@@ -821,7 +875,7 @@ static void __ata_dev_select (struct ata_port *ap, unsigned int device)
 		tmp = ATA_DEVICE_OBS | ATA_DEV1;
 
 	if (ap->flags & ATA_FLAG_MMIO) {
-		writeb(tmp, (void *) ap->ioaddr.device_addr);
+		writeb(tmp, (void __iomem *) ap->ioaddr.device_addr);
 	} else {
 		outb(tmp, ap->ioaddr.device_addr);
 	}
@@ -839,7 +893,7 @@ static void __ata_dev_select (struct ata_port *ap, unsigned int device)
  *	make either device 0, or device 1, active on the
  *	ATA channel.
  *
- *	This is a high-level version of __ata_dev_select(),
+ *	This is a high-level version of ata_std_dev_select(),
  *	which additionally provides the services of inserting
  *	the proper pauses and status polling, where needed.
  *
@@ -856,7 +910,7 @@ void ata_dev_select(struct ata_port *ap, unsigned int device,
 	if (wait)
 		ata_wait_idle(ap);
 
-	__ata_dev_select(ap, device);
+	ap->ops->dev_select(ap, device);
 
 	if (wait) {
 		if (can_sleep && ap->device[device].class == ATA_DEV_ATAPI)
@@ -930,10 +984,14 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
 {
 	struct ata_device *dev = &ap->device[device];
 	unsigned int i;
-	u16 tmp, udma_modes;
+	u16 tmp;
+	unsigned long xfer_modes;
 	u8 status;
-	struct ata_taskfile tf;
 	unsigned int using_edd;
+	DECLARE_COMPLETION(wait);
+	struct ata_queued_cmd *qc;
+	unsigned long flags;
+	int rc;
 
 	if (!ata_dev_present(dev)) {
 		DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n",
@@ -953,27 +1011,34 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
 
 	ata_dev_select(ap, device, 1, 1); /* select device 0/1 */
 
-retry:
-	ata_tf_init(ap, &tf, device);
-	tf.ctl |= ATA_NIEN;
-	tf.protocol = ATA_PROT_PIO;
+	qc = ata_qc_new_init(ap, dev);
+	BUG_ON(qc == NULL);
 
+	ata_sg_init_one(qc, dev->id, sizeof(dev->id));
+	qc->pci_dma_dir = PCI_DMA_FROMDEVICE;
+	qc->tf.protocol = ATA_PROT_PIO;
+	qc->nsect = 1;
+
+retry:
 	if (dev->class == ATA_DEV_ATA) {
-		tf.command = ATA_CMD_ID_ATA;
+		qc->tf.command = ATA_CMD_ID_ATA;
 		DPRINTK("do ATA identify\n");
 	} else {
-		tf.command = ATA_CMD_ID_ATAPI;
+		qc->tf.command = ATA_CMD_ID_ATAPI;
 		DPRINTK("do ATAPI identify\n");
 	}
 
-	ata_tf_to_host(ap, &tf);
+	qc->waiting = &wait;
+	qc->complete_fn = ata_qc_complete_noop;
 
-	/* crazy ATAPI devices... */
-	if (dev->class == ATA_DEV_ATAPI)
-		msleep(150);
+	spin_lock_irqsave(&ap->host_set->lock, flags);
+	rc = ata_qc_issue(qc);
+	spin_unlock_irqrestore(&ap->host_set->lock, flags);
 
-	if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT))
+	if (rc)
 		goto err_out;
+	else
+		wait_for_completion(&wait);
 
 	status = ata_chk_status(ap);
 	if (status & ATA_ERR) {
@@ -988,44 +1053,21 @@ retry:
 		 * ATA software reset (SRST, the default) does not appear
 		 * to have this problem.
 		 */
-		if ((using_edd) && (tf.command == ATA_CMD_ID_ATA)) {
+		if ((using_edd) && (qc->tf.command == ATA_CMD_ID_ATA)) {
 			u8 err = ata_chk_err(ap);
 			if (err & ATA_ABORTED) {
 				dev->class = ATA_DEV_ATAPI;
+				qc->cursg = 0;
+				qc->cursg_ofs = 0;
+				qc->cursect = 0;
+				qc->nsect = 1;
 				goto retry;
 			}
 		}
 		goto err_out;
 	}
 
-	/* make sure we have BSY=0, DRQ=1 */
-	if ((status & ATA_DRQ) == 0) {
-		printk(KERN_WARNING "ata%u: dev %u (ATA%s?) not returning id page (0x%x)\n",
-		       ap->id, device,
-		       dev->class == ATA_DEV_ATA ? "" : "PI",
-		       status);
-		goto err_out;
-	}
-
-	/* read IDENTIFY [X] DEVICE page */
-	if (ap->flags & ATA_FLAG_MMIO) {
-		for (i = 0; i < ATA_ID_WORDS; i++)
-			dev->id[i] = readw((void *)ap->ioaddr.data_addr);
-	} else
-		for (i = 0; i < ATA_ID_WORDS; i++)
-			dev->id[i] = inw(ap->ioaddr.data_addr);
-
-	/* wait for host_idle */
-	status = ata_wait_idle(ap);
-	if (status & (ATA_BUSY | ATA_DRQ)) {
-		printk(KERN_WARNING "ata%u: dev %u (ATA%s?) error after id page (0x%x)\n",
-		       ap->id, device,
-		       dev->class == ATA_DEV_ATA ? "" : "PI",
-		       status);
-		goto err_out;
-	}
-
-	ata_irq_on(ap);	/* re-enable interrupts */
+	swap_buf_le16(dev->id, ATA_ID_WORDS);
 
 	/* print device capabilities */
 	printk(KERN_DEBUG "ata%u: dev %u cfg "
@@ -1045,12 +1087,13 @@ retry:
 		goto err_out_nosup;
 	}
 
-	/* we require UDMA support */
-	udma_modes =
-	tmp = dev->id[ATA_ID_UDMA_MODES];
-	if ((tmp & 0xff) == 0) {
-		printk(KERN_DEBUG "ata%u: no udma\n", ap->id);
-		goto err_out_nosup;
+	/* quick-n-dirty find max transfer mode; for printk only */
+	xfer_modes = dev->id[ATA_ID_UDMA_MODES];
+	if (!xfer_modes)
+		xfer_modes = (dev->id[ATA_ID_MWDMA_MODES]) << ATA_SHIFT_MWDMA;
+	if (!xfer_modes) {
+		xfer_modes = (dev->id[ATA_ID_PIO_MODES]) << (ATA_SHIFT_PIO + 3);
+		xfer_modes |= (0x7 << ATA_SHIFT_PIO);
 	}
 
 	ata_dump_id(dev);
@@ -1083,7 +1126,7 @@ retry:
 		/* print device info to dmesg */
 		printk(KERN_INFO "ata%u: dev %u ATA, max %s, %Lu sectors:%s\n",
 		       ap->id, device,
-		       ata_udma_string(udma_modes),
+		       ata_mode_string(xfer_modes),
 		       (unsigned long long)dev->n_sectors,
 		       dev->flags & ATA_DFLAG_LBA48 ? " lba48" : "");
 	}
@@ -1093,15 +1136,18 @@ retry:
 		if (ata_id_is_ata(dev))		/* sanity check */
 			goto err_out_nosup;
 
-		/* see if 16-byte commands supported */
-		tmp = dev->id[0] & 0x3;
-		if (tmp == 1)
-			ap->host->max_cmd_len = 16;
+		rc = atapi_cdb_len(dev->id);
+		if ((rc < 12) || (rc > ATAPI_CDB_LEN)) {
+			printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id);
+			goto err_out_nosup;
+		}
+		ap->cdb_len = (unsigned int) rc;
+		ap->host->max_cmd_len = (unsigned char) ap->cdb_len;
 
 		/* print device info to dmesg */
 		printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n",
 		       ap->id, device,
-		       ata_udma_string(udma_modes));
+		       ata_mode_string(xfer_modes));
 	}
 
 	DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap));
@@ -1171,13 +1217,13 @@ void ata_port_probe(struct ata_port *ap)
 }
 
 /**
- *	sata_phy_reset -
+ *	__sata_phy_reset -
  *	@ap:
  *
  *	LOCKING:
  *
  */
-void sata_phy_reset(struct ata_port *ap)
+void __sata_phy_reset(struct ata_port *ap)
 {
 	u32 sstatus;
 	unsigned long timeout = jiffies + (HZ * 5);
@@ -1215,6 +1261,21 @@ void sata_phy_reset(struct ata_port *ap)
 		return;
 	}
 
+	ap->cbl = ATA_CBL_SATA;
+}
+
+/**
+ *	__sata_phy_reset -
+ *	@ap:
+ *
+ *	LOCKING:
+ *
+ */
+void sata_phy_reset(struct ata_port *ap)
+{
+	__sata_phy_reset(ap);
+	if (ap->flags & ATA_FLAG_PORT_DISABLED)
+		return;
 	ata_bus_reset(ap);
 }
 
@@ -1232,6 +1293,101 @@ void ata_port_disable(struct ata_port *ap)
 	ap->flags |= ATA_FLAG_PORT_DISABLED;
 }
 
+static struct {
+	unsigned int shift;
+	u8 base;
+} xfer_mode_classes[] = {
+	{ ATA_SHIFT_UDMA,	XFER_UDMA_0 },
+	{ ATA_SHIFT_MWDMA,	XFER_MW_DMA_0 },
+	{ ATA_SHIFT_PIO,	XFER_PIO_0 },
+};
+
+static inline u8 base_from_shift(unsigned int shift)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(xfer_mode_classes); i++)
+		if (xfer_mode_classes[i].shift == shift)
+			return xfer_mode_classes[i].base;
+
+	return 0xff;
+}
+
+static void ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev)
+{
+	int ofs, idx;
+	u8 base;
+
+	if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED))
+		return;
+
+	if (dev->xfer_shift == ATA_SHIFT_PIO)
+		dev->flags |= ATA_DFLAG_PIO;
+
+	ata_dev_set_xfermode(ap, dev);
+
+	base = base_from_shift(dev->xfer_shift);
+	ofs = dev->xfer_mode - base;
+	idx = ofs + dev->xfer_shift;
+	WARN_ON(idx >= ARRAY_SIZE(xfer_mode_str));
+
+	DPRINTK("idx=%d xfer_shift=%u, xfer_mode=0x%x, base=0x%x, offset=%d\n",
+		idx, dev->xfer_shift, (int)dev->xfer_mode, (int)base, ofs);
+
+	printk(KERN_INFO "ata%u: dev %u configured for %s\n",
+		ap->id, dev->devno, xfer_mode_str[idx]);
+}
+
+static int ata_host_set_pio(struct ata_port *ap)
+{
+	unsigned int mask;
+	int x, i;
+	u8 base, xfer_mode;
+
+	mask = ata_get_mode_mask(ap, ATA_SHIFT_PIO);
+	x = fgb(mask);
+	if (x < 0) {
+		printk(KERN_WARNING "ata%u: no PIO support\n", ap->id);
+		return -1;
+	}
+
+	base = base_from_shift(ATA_SHIFT_PIO);
+	xfer_mode = base + x;
+
+	DPRINTK("base 0x%x xfer_mode 0x%x mask 0x%x x %d\n",
+		(int)base, (int)xfer_mode, mask, x);
+
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		struct ata_device *dev = &ap->device[i];
+		if (ata_dev_present(dev)) {
+			dev->pio_mode = xfer_mode;
+			dev->xfer_mode = xfer_mode;
+			dev->xfer_shift = ATA_SHIFT_PIO;
+			if (ap->ops->set_piomode)
+				ap->ops->set_piomode(ap, dev);
+		}
+	}
+
+	return 0;
+}
+
+static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode,
+			    unsigned int xfer_shift)
+{
+	int i;
+
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		struct ata_device *dev = &ap->device[i];
+		if (ata_dev_present(dev)) {
+			dev->dma_mode = xfer_mode;
+			dev->xfer_mode = xfer_mode;
+			dev->xfer_shift = xfer_shift;
+			if (ap->ops->set_dmamode)
+				ap->ops->set_dmamode(ap, dev);
+		}
+	}
+}
+
 /**
  *	ata_set_mode - Program timings and issue SET FEATURES - XFER
  *	@ap: port on which timings will be programmed
@@ -1241,29 +1397,28 @@ void ata_port_disable(struct ata_port *ap)
  */
 static void ata_set_mode(struct ata_port *ap)
 {
-	unsigned int force_pio, i;
+	unsigned int i, xfer_shift;
+	u8 xfer_mode;
+	int rc;
 
-	ata_host_set_pio(ap);
-	if (ap->flags & ATA_FLAG_PORT_DISABLED)
-		return;
+	/* step 1: always set host PIO timings */
+	rc = ata_host_set_pio(ap);
+	if (rc)
+		goto err_out;
 
-	ata_host_set_udma(ap);
-	if (ap->flags & ATA_FLAG_PORT_DISABLED)
-		return;
+	/* step 2: choose the best data xfer mode */
+	xfer_mode = xfer_shift = 0;
+	rc = ata_choose_xfer_mode(ap, &xfer_mode, &xfer_shift);
+	if (rc)
+		goto err_out;
 
-#ifdef ATA_FORCE_PIO
-	force_pio = 1;
-#else
-	force_pio = 0;
-#endif
+	/* step 3: if that xfer mode isn't PIO, set host DMA timings */
+	if (xfer_shift != ATA_SHIFT_PIO)
+		ata_host_set_dma(ap, xfer_mode, xfer_shift);
 
-	if (force_pio) {
-		ata_dev_set_pio(ap, 0);
-		ata_dev_set_pio(ap, 1);
-	} else {
-		ata_dev_set_udma(ap, 0);
-		ata_dev_set_udma(ap, 1);
-	}
+	/* step 4: update devices' xfer mode */
+	ata_dev_set_mode(ap, &ap->device[0]);
+	ata_dev_set_mode(ap, &ap->device[1]);
 
 	if (ap->flags & ATA_FLAG_PORT_DISABLED)
 		return;
@@ -1275,6 +1430,11 @@ static void ata_set_mode(struct ata_port *ap)
 		struct ata_device *dev = &ap->device[i];
 		ata_dev_set_protocol(dev);
 	}
+
+	return;
+
+err_out:
+	ata_port_disable(ap);
 }
 
 /**
@@ -1328,23 +1488,23 @@ static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask)
 	unsigned int dev1 = devmask & (1 << 1);
 	unsigned long timeout;
 
-	/* if device 0 was found in ata_dev_devchk, wait for its
+	/* if device 0 was found in ata_devchk, wait for its
 	 * BSY bit to clear
 	 */
 	if (dev0)
 		ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
 
-	/* if device 1 was found in ata_dev_devchk, wait for
+	/* if device 1 was found in ata_devchk, wait for
 	 * register access, then wait for BSY to clear
 	 */
 	timeout = jiffies + ATA_TMOUT_BOOT;
 	while (dev1) {
 		u8 nsect, lbal;
 
-		__ata_dev_select(ap, 1);
+		ap->ops->dev_select(ap, 1);
 		if (ap->flags & ATA_FLAG_MMIO) {
-			nsect = readb((void *) ioaddr->nsect_addr);
-			lbal = readb((void *) ioaddr->lbal_addr);
+			nsect = readb((void __iomem *) ioaddr->nsect_addr);
+			lbal = readb((void __iomem *) ioaddr->lbal_addr);
 		} else {
 			nsect = inb(ioaddr->nsect_addr);
 			lbal = inb(ioaddr->lbal_addr);
@@ -1361,11 +1521,11 @@ static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask)
 		ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
 
 	/* is all this really necessary? */
-	__ata_dev_select(ap, 0);
+	ap->ops->dev_select(ap, 0);
 	if (dev1)
-		__ata_dev_select(ap, 1);
+		ap->ops->dev_select(ap, 1);
 	if (dev0)
-		__ata_dev_select(ap, 0);
+		ap->ops->dev_select(ap, 0);
 }
 
 /**
@@ -1408,11 +1568,11 @@ static unsigned int ata_bus_softreset(struct ata_port *ap,
 
 	/* software reset.  causes dev0 to be selected */
 	if (ap->flags & ATA_FLAG_MMIO) {
-		writeb(ap->ctl, ioaddr->ctl_addr);
+		writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
 		udelay(20);	/* FIXME: flush */
-		writeb(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
+		writeb(ap->ctl | ATA_SRST, (void __iomem *) ioaddr->ctl_addr);
 		udelay(20);	/* FIXME: flush */
-		writeb(ap->ctl, ioaddr->ctl_addr);
+		writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
 	} else {
 		outb(ap->ctl, ioaddr->ctl_addr);
 		udelay(10);
@@ -1469,9 +1629,9 @@ void ata_bus_reset(struct ata_port *ap)
 	if (ap->flags & ATA_FLAG_SATA_RESET)
 		dev0 = 1;
 	else {
-		dev0 = ata_dev_devchk(ap, 0);
+		dev0 = ata_devchk(ap, 0);
 		if (slave_possible)
-			dev1 = ata_dev_devchk(ap, 1);
+			dev1 = ata_devchk(ap, 1);
 	}
 
 	if (dev0)
@@ -1480,7 +1640,7 @@ void ata_bus_reset(struct ata_port *ap)
 		devmask |= (1 << 1);
 
 	/* select device 0 again */
-	__ata_dev_select(ap, 0);
+	ap->ops->dev_select(ap, 0);
 
 	/* issue bus reset */
 	if (ap->flags & ATA_FLAG_SRST)
@@ -1488,7 +1648,7 @@ void ata_bus_reset(struct ata_port *ap)
 	else if ((ap->flags & ATA_FLAG_SATA_RESET) == 0) {
 		/* set up device control */
 		if (ap->flags & ATA_FLAG_MMIO)
-			writeb(ap->ctl, ioaddr->ctl_addr);
+			writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
 		else
 			outb(ap->ctl, ioaddr->ctl_addr);
 		rc = ata_bus_edd(ap);
@@ -1509,9 +1669,9 @@ void ata_bus_reset(struct ata_port *ap)
 
 	/* is double-select really necessary? */
 	if (ap->device[1].class != ATA_DEV_NONE)
-		__ata_dev_select(ap, 1);
+		ap->ops->dev_select(ap, 1);
 	if (ap->device[0].class != ATA_DEV_NONE)
-		__ata_dev_select(ap, 0);
+		ap->ops->dev_select(ap, 0);
 
 	/* if no devices were detected, disable this port */
 	if ((ap->device[0].class == ATA_DEV_NONE) &&
@@ -1521,7 +1681,7 @@ void ata_bus_reset(struct ata_port *ap)
 	if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) {
 		/* set up device control for ATA_FLAG_SATA_RESET */
 		if (ap->flags & ATA_FLAG_MMIO)
-			writeb(ap->ctl, ioaddr->ctl_addr);
+			writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
 		else
 			outb(ap->ctl, ioaddr->ctl_addr);
 	}
@@ -1536,116 +1696,102 @@ err_out:
 	DPRINTK("EXIT\n");
 }
 
-/**
- *	ata_host_set_pio -
- *	@ap:
- *
- *	LOCKING:
- */
-
-static void ata_host_set_pio(struct ata_port *ap)
+static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift)
 {
 	struct ata_device *master, *slave;
-	unsigned int pio, i;
-	u16 mask;
+	unsigned int mask;
 
 	master = &ap->device[0];
 	slave = &ap->device[1];
 
 	assert (ata_dev_present(master) || ata_dev_present(slave));
 
-	mask = ap->pio_mask;
-	if (ata_dev_present(master))
-		mask &= (master->id[ATA_ID_PIO_MODES] & 0x03);
-	if (ata_dev_present(slave))
-		mask &= (slave->id[ATA_ID_PIO_MODES] & 0x03);
-
-	/* require pio mode 3 or 4 support for host and all devices */
-	if (mask == 0) {
-		printk(KERN_WARNING "ata%u: no PIO3/4 support, ignoring\n",
-		       ap->id);
-		goto err_out;
+	if (shift == ATA_SHIFT_UDMA) {
+		mask = ap->udma_mask;
+		if (ata_dev_present(master))
+			mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff);
+		if (ata_dev_present(slave))
+			mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff);
+	}
+	else if (shift == ATA_SHIFT_MWDMA) {
+		mask = ap->mwdma_mask;
+		if (ata_dev_present(master))
+			mask &= (master->id[ATA_ID_MWDMA_MODES] & 0x07);
+		if (ata_dev_present(slave))
+			mask &= (slave->id[ATA_ID_MWDMA_MODES] & 0x07);
+	}
+	else if (shift == ATA_SHIFT_PIO) {
+		mask = ap->pio_mask;
+		if (ata_dev_present(master)) {
+			/* spec doesn't return explicit support for
+			 * PIO0-2, so we fake it
+			 */
+			u16 tmp_mode = master->id[ATA_ID_PIO_MODES] & 0x03;
+			tmp_mode <<= 3;
+			tmp_mode |= 0x7;
+			mask &= tmp_mode;
+		}
+		if (ata_dev_present(slave)) {
+			/* spec doesn't return explicit support for
+			 * PIO0-2, so we fake it
+			 */
+			u16 tmp_mode = slave->id[ATA_ID_PIO_MODES] & 0x03;
+			tmp_mode <<= 3;
+			tmp_mode |= 0x7;
+			mask &= tmp_mode;
+		}
+	}
+	else {
+		mask = 0xffffffff; /* shut up compiler warning */
+		BUG();
 	}
 
-	pio = (mask & ATA_ID_PIO4) ? 4 : 3;
-	for (i = 0; i < ATA_MAX_DEVICES; i++)
-		if (ata_dev_present(&ap->device[i])) {
-			ap->device[i].pio_mode = (pio == 3) ?
-				XFER_PIO_3 : XFER_PIO_4;
-			if (ap->ops->set_piomode)
-				ap->ops->set_piomode(ap, &ap->device[i], pio);
-		}
+	return mask;
+}
 
-	return;
+/* find greatest bit */
+static int fgb(u32 bitmap)
+{
+	unsigned int i;
+	int x = -1;
 
-err_out:
-	ap->ops->port_disable(ap);
+	for (i = 0; i < 32; i++)
+		if (bitmap & (1 << i))
+			x = i;
+
+	return x;
 }
 
 /**
- *	ata_host_set_udma -
+ *	ata_choose_xfer_mode -
  *	@ap:
  *
  *	LOCKING:
+ *
+ *	RETURNS:
+ *	Zero on success, negative on error.
  */
 
-static void ata_host_set_udma(struct ata_port *ap)
+static int ata_choose_xfer_mode(struct ata_port *ap,
+				u8 *xfer_mode_out,
+				unsigned int *xfer_shift_out)
 {
-	struct ata_device *master, *slave;
-	u16 mask;
-	unsigned int i, j;
-	int udma_mode = -1;
+	unsigned int mask, shift;
+	int x, i;
 
-	master = &ap->device[0];
-	slave = &ap->device[1];
+	for (i = 0; i < ARRAY_SIZE(xfer_mode_classes); i++) {
+		shift = xfer_mode_classes[i].shift;
+		mask = ata_get_mode_mask(ap, shift);
 
-	assert (ata_dev_present(master) || ata_dev_present(slave));
-	assert ((ap->flags & ATA_FLAG_PORT_DISABLED) == 0);
-
-	DPRINTK("udma masks: host 0x%X, master 0x%X, slave 0x%X\n",
-		ap->udma_mask,
-		(!ata_dev_present(master)) ? 0xff :
-			(master->id[ATA_ID_UDMA_MODES] & 0xff),
-		(!ata_dev_present(slave)) ? 0xff :
-			(slave->id[ATA_ID_UDMA_MODES] & 0xff));
-
-	mask = ap->udma_mask;
-	if (ata_dev_present(master))
-		mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff);
-	if (ata_dev_present(slave))
-		mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff);
-
-	i = XFER_UDMA_7;
-	while (i >= XFER_UDMA_0) {
-		j = i - XFER_UDMA_0;
-		DPRINTK("mask 0x%X i 0x%X j %u\n", mask, i, j);
-		if (mask & (1 << j)) {
-			udma_mode = i;
-			break;
+		x = fgb(mask);
+		if (x >= 0) {
+			*xfer_mode_out = xfer_mode_classes[i].base + x;
+			*xfer_shift_out = shift;
+			return 0;
 		}
-
-		i--;
 	}
 
-	/* require udma for host and all attached devices */
-	if (udma_mode < 0) {
-		printk(KERN_WARNING "ata%u: no UltraDMA support, ignoring\n",
-		       ap->id);
-		goto err_out;
-	}
-
-	for (i = 0; i < ATA_MAX_DEVICES; i++)
-		if (ata_dev_present(&ap->device[i])) {
-			ap->device[i].udma_mode = udma_mode;
-			if (ap->ops->set_udmamode)
-				ap->ops->set_udmamode(ap, &ap->device[i],
-						      udma_mode);
-		}
-
-	return;
-
-err_out:
-	ap->ops->port_disable(ap);
+	return -1;
 }
 
 /**
@@ -1658,88 +1804,38 @@ err_out:
 
 static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
 {
-	struct ata_taskfile tf;
+	DECLARE_COMPLETION(wait);
+	struct ata_queued_cmd *qc;
+	int rc;
+	unsigned long flags;
 
 	/* set up set-features taskfile */
 	DPRINTK("set features - xfer mode\n");
-	ata_tf_init(ap, &tf, dev->devno);
-	tf.ctl |= ATA_NIEN;
-	tf.command = ATA_CMD_SET_FEATURES;
-	tf.feature = SETFEATURES_XFER;
-	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-	tf.protocol = ATA_PROT_NODATA;
-	if (dev->flags & ATA_DFLAG_PIO)
-		tf.nsect = dev->pio_mode;
-	else
-		tf.nsect = dev->udma_mode;
 
-	/* do bus reset */
-	ata_tf_to_host(ap, &tf);
+	qc = ata_qc_new_init(ap, dev);
+	BUG_ON(qc == NULL);
 
-	/* crazy ATAPI devices... */
-	if (dev->class == ATA_DEV_ATAPI)
-		msleep(150);
+	qc->tf.command = ATA_CMD_SET_FEATURES;
+	qc->tf.feature = SETFEATURES_XFER;
+	qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	qc->tf.protocol = ATA_PROT_NODATA;
+	qc->tf.nsect = dev->xfer_mode;
 
-	ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+	qc->waiting = &wait;
+	qc->complete_fn = ata_qc_complete_noop;
 
-	ata_irq_on(ap);	/* re-enable interrupts */
+	spin_lock_irqsave(&ap->host_set->lock, flags);
+	rc = ata_qc_issue(qc);
+	spin_unlock_irqrestore(&ap->host_set->lock, flags);
 
-	ata_wait_idle(ap);
+	if (rc)
+		ata_port_disable(ap);
+	else
+		wait_for_completion(&wait);
 
 	DPRINTK("EXIT\n");
 }
 
-/**
- *	ata_dev_set_udma - Set ATA device's transfer mode to Ultra DMA
- *	@ap: Port associated with device @dev
- *	@device: Device whose mode will be set
- *
- *	LOCKING:
- */
-
-static void ata_dev_set_udma(struct ata_port *ap, unsigned int device)
-{
-	struct ata_device *dev = &ap->device[device];
-
-	if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED))
-		return;
-
-	ata_dev_set_xfermode(ap, dev);
-
-	assert((dev->udma_mode >= XFER_UDMA_0) &&
-	       (dev->udma_mode <= XFER_UDMA_7));
-	printk(KERN_INFO "ata%u: dev %u configured for %s\n",
-	       ap->id, device,
-	       udma_str[dev->udma_mode - XFER_UDMA_0]);
-}
-
-/**
- *	ata_dev_set_pio - Set ATA device's transfer mode to PIO
- *	@ap: Port associated with device @dev
- *	@device: Device whose mode will be set
- *
- *	LOCKING:
- */
-
-static void ata_dev_set_pio(struct ata_port *ap, unsigned int device)
-{
-	struct ata_device *dev = &ap->device[device];
-
-	if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED))
-		return;
-
-	/* force PIO mode */
-	dev->flags |= ATA_DFLAG_PIO;
-
-	ata_dev_set_xfermode(ap, dev);
-
-	assert((dev->pio_mode >= XFER_PIO_3) &&
-	       (dev->pio_mode <= XFER_PIO_4));
-	printk(KERN_INFO "ata%u: dev %u configured for PIO%c\n",
-	       ap->id, device,
-	       dev->pio_mode == 3 ? '3' : '4');
-}
-
 /**
  *	ata_sg_clean -
  *	@qc:
@@ -1789,7 +1885,7 @@ static void ata_fill_sg(struct ata_queued_cmd *qc)
 
 	idx = 0;
 	for (nelem = qc->n_elem; nelem; nelem--,sg++) {
-		u32 addr, boundary;
+		u32 addr, offset;
 		u32 sg_len, len;
 
 		/* determine if physical DMA addr spans 64K boundary.
@@ -1800,10 +1896,10 @@ static void ata_fill_sg(struct ata_queued_cmd *qc)
 		sg_len = sg_dma_len(sg);
 
 		while (sg_len) {
-			boundary = (addr & ~0xffff) + (0xffff + 1);
+			offset = addr & 0xffff;
 			len = sg_len;
-			if ((addr + sg_len) > boundary)
-				len = boundary - addr;
+			if ((offset + sg_len) > 0x10000)
+				len = 0x10000 - offset;
 
 			ap->prd[idx].addr = cpu_to_le32(addr);
 			ap->prd[idx].flags_len = cpu_to_le32(len & 0xffff);
@@ -2003,7 +2099,7 @@ static void ata_pio_complete (struct ata_port *ap)
 	}
 
 	drv_stat = ata_wait_idle(ap);
-	if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
+	if (!ata_ok(drv_stat)) {
 		ap->pio_task_state = PIO_ST_ERR;
 		return;
 	}
@@ -2018,6 +2114,126 @@ static void ata_pio_complete (struct ata_port *ap)
 	ata_qc_complete(qc, drv_stat);
 }
 
+void swap_buf_le16(u16 *buf, unsigned int buf_words)
+{
+#ifdef __BIG_ENDIAN
+	unsigned int i;
+
+	for (i = 0; i < buf_words; i++)
+		buf[i] = le16_to_cpu(buf[i]);
+#endif /* __BIG_ENDIAN */
+}
+
+static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf,
+			       unsigned int buflen, int write_data)
+{
+	unsigned int i;
+	unsigned int words = buflen >> 1;
+	u16 *buf16 = (u16 *) buf;
+	void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr;
+
+	if (write_data) {
+		for (i = 0; i < words; i++)
+			writew(le16_to_cpu(buf16[i]), mmio);
+	} else {
+		for (i = 0; i < words; i++)
+			buf16[i] = cpu_to_le16(readw(mmio));
+	}
+}
+
+static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf,
+			      unsigned int buflen, int write_data)
+{
+	unsigned int dwords = buflen >> 1;
+
+	if (write_data)
+		outsw(ap->ioaddr.data_addr, buf, dwords);
+	else
+		insw(ap->ioaddr.data_addr, buf, dwords);
+}
+
+static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
+			  unsigned int buflen, int do_write)
+{
+	if (ap->flags & ATA_FLAG_MMIO)
+		ata_mmio_data_xfer(ap, buf, buflen, do_write);
+	else
+		ata_pio_data_xfer(ap, buf, buflen, do_write);
+}
+
+static void ata_pio_sector(struct ata_queued_cmd *qc)
+{
+	int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
+	struct scatterlist *sg = qc->sg;
+	struct ata_port *ap = qc->ap;
+	struct page *page;
+	unsigned char *buf;
+
+	if (qc->cursect == (qc->nsect - 1))
+		ap->pio_task_state = PIO_ST_LAST;
+
+	page = sg[qc->cursg].page;
+	buf = kmap(page) +
+	      sg[qc->cursg].offset + (qc->cursg_ofs * ATA_SECT_SIZE);
+
+	qc->cursect++;
+	qc->cursg_ofs++;
+
+	if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg_dma_len(&sg[qc->cursg])) {
+		qc->cursg++;
+		qc->cursg_ofs = 0;
+	}
+
+	DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
+
+	/* do the actual data transfer */
+	do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
+	ata_data_xfer(ap, buf, ATA_SECT_SIZE, do_write);
+
+	kunmap(page);
+}
+
+static void atapi_pio_sector(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct ata_device *dev = qc->dev;
+	unsigned int i, ireason, bc_lo, bc_hi, bytes;
+	int i_write, do_write = (qc->tf.flags & ATA_TFLAG_WRITE) ? 1 : 0;
+
+	ap->ops->tf_read(ap, &qc->tf);
+	ireason = qc->tf.nsect;
+	bc_lo = qc->tf.lbam;
+	bc_hi = qc->tf.lbah;
+	bytes = (bc_hi << 8) | bc_lo;
+
+	/* shall be cleared to zero, indicating xfer of data */
+	if (ireason & (1 << 0))
+		goto err_out;
+
+	/* make sure transfer direction matches expected */
+	i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0;
+	if (do_write != i_write)
+		goto err_out;
+
+	/* make sure byte count is multiple of sector size; not
+	* required by standard (warning! warning!), but IDE driver
+	* does this to simplify things a bit.  We are lazy, and
+	* follow suit.
+	*/
+	if (bytes & (ATA_SECT_SIZE - 1))
+		goto err_out;
+
+	for (i = 0; i < (bytes >> 9); i++)
+		ata_pio_sector(qc);
+
+	return;
+
+err_out:
+	printk(KERN_INFO "ata%u: dev %u: ATAPI check failed\n",
+	      ap->id, dev->devno);
+	ap->pio_task_state = PIO_ST_ERR;
+}
+
 /**
  *	ata_pio_sector -
  *	@ap:
@@ -2025,12 +2241,9 @@ static void ata_pio_complete (struct ata_port *ap)
  *	LOCKING:
  */
 
-static void ata_pio_sector(struct ata_port *ap)
+static void ata_pio_block(struct ata_port *ap)
 {
 	struct ata_queued_cmd *qc;
-	struct scatterlist *sg;
-	struct page *page;
-	unsigned char *buf;
 	u8 status;
 
 	/*
@@ -2061,36 +2274,29 @@ static void ata_pio_sector(struct ata_port *ap)
 	qc = ata_qc_from_tag(ap, ap->active_tag);
 	assert(qc != NULL);
 
-	sg = qc->sg;
-
-	if (qc->cursect == (qc->nsect - 1))
-		ap->pio_task_state = PIO_ST_LAST;
+	if (is_atapi_taskfile(&qc->tf))
+		atapi_pio_sector(qc);
+	else
+		ata_pio_sector(qc);
+}
 
-	page = sg[qc->cursg].page;
-	buf = kmap(page) +
-	      sg[qc->cursg].offset + (qc->cursg_ofs * ATA_SECT_SIZE);
+static void ata_pio_error(struct ata_port *ap)
+{
+	struct ata_queued_cmd *qc;
+	u8 drv_stat;
 
-	qc->cursect++;
-	qc->cursg_ofs++;
+	qc = ata_qc_from_tag(ap, ap->active_tag);
+	assert(qc != NULL);
 
-	if (qc->flags & ATA_QCFLAG_SG)
-		if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg_dma_len(&sg[qc->cursg])) {
-			qc->cursg++;
-			qc->cursg_ofs = 0;
-		}
+	drv_stat = ata_chk_status(ap);
+	printk(KERN_WARNING "ata%u: PIO error, drv_stat 0x%x\n",
+	       ap->id, drv_stat);
 
-	DPRINTK("data %s, drv_stat 0x%X\n",
-		qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read",
-		status);
+	ap->pio_task_state = PIO_ST_IDLE;
 
-	/* do the actual data transfer */
-	/* FIXME: mmio-ize */
-	if (qc->tf.flags & ATA_TFLAG_WRITE)
-		outsl(ap->ioaddr.data_addr, buf, ATA_SECT_DWORDS);
-	else
-		insl(ap->ioaddr.data_addr, buf, ATA_SECT_DWORDS);
+	ata_irq_on(ap);
 
-	kunmap(page);
+	ata_qc_complete(qc, drv_stat | ATA_ERR);
 }
 
 static void ata_pio_task(void *_data)
@@ -2100,7 +2306,7 @@ static void ata_pio_task(void *_data)
 
 	switch (ap->pio_task_state) {
 	case PIO_ST:
-		ata_pio_sector(ap);
+		ata_pio_block(ap);
 		break;
 
 	case PIO_ST_LAST:
@@ -2113,15 +2319,8 @@ static void ata_pio_task(void *_data)
 		break;
 
 	case PIO_ST_TMOUT:
-		printk(KERN_ERR "ata%d: FIXME: PIO_ST_TMOUT\n", /* FIXME */
-		       ap->id);
-		timeout = 11 * HZ;
-		break;
-
 	case PIO_ST_ERR:
-		printk(KERN_ERR "ata%d: FIXME: PIO_ST_ERR\n", /* FIXME */
-		       ap->id);
-		timeout = 11 * HZ;
+		ata_pio_error(ap);
 		break;
 	}
 
@@ -2180,7 +2379,6 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
 
 		/* fall through */
 
-	case ATA_PROT_NODATA:
 	default:
 		ata_altstatus(ap);
 		drv_stat = ata_chk_status(ap);
@@ -2287,8 +2485,6 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
 
 		ata_tf_init(ap, &qc->tf, dev->devno);
 
-		if (likely((dev->flags & ATA_DFLAG_PIO) == 0))
-			qc->flags |= ATA_QCFLAG_DMA;
 		if (dev->flags & ATA_DFLAG_LBA48)
 			qc->tf.flags |= ATA_TFLAG_LBA48;
 	}
@@ -2296,6 +2492,11 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
 	return qc;
 }
 
+static int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat)
+{
+	return 0;
+}
+
 /**
  *	ata_qc_complete - Complete an active ATA command
  *	@qc: Command to complete
@@ -2335,11 +2536,16 @@ void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
 		do_clear = 1;
 	}
 
-	if (qc->waiting)
-		complete(qc->waiting);
+	if (qc->waiting) {
+		struct completion *waiting = qc->waiting;
+		qc->waiting = NULL;
+		complete(waiting);
+	}
 
 	if (likely(do_clear))
 		clear_bit(tag, &ap->qactive);
+
+	VPRINTK("EXIT\n");
 }
 
 /**
@@ -2422,6 +2628,12 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc)
 		break;
 
 	case ATA_PROT_ATAPI:
+		ata_qc_set_polling(qc);
+		ata_tf_to_host_nolock(ap, &qc->tf);
+		queue_work(ata_wq, &ap->packet_task);
+		break;
+
+	case ATA_PROT_ATAPI_NODATA:
 		ata_tf_to_host_nolock(ap, &qc->tf);
 		queue_work(ata_wq, &ap->packet_task);
 		break;
@@ -2441,19 +2653,19 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc)
 }
 
 /**
- *	ata_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction (MMIO)
+ *	ata_bmdma_setup - Set up PCI IDE BMDMA transaction
  *	@qc: Info associated with this ATA transaction.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc)
+static void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
 	u8 dmactl;
-	void *mmio = (void *) ap->ioaddr.bmdma_addr;
+	void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
 
 	/* load PRD table addr. */
 	mb();	/* make sure PRD table writes are visible to controller */
@@ -2471,17 +2683,17 @@ void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc)
 }
 
 /**
- *	ata_bmdma_start_mmio - Start a PCI IDE BMDMA transaction (MMIO)
+ *	ata_bmdma_start - Start a PCI IDE BMDMA transaction
  *	@qc: Info associated with this ATA transaction.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
+static void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	void *mmio = (void *) ap->ioaddr.bmdma_addr;
+	void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
 	u8 dmactl;
 
 	/* start host DMA transaction */
@@ -2509,7 +2721,7 @@ void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_bmdma_setup_pio (struct ata_queued_cmd *qc)
+static void ata_bmdma_setup_pio (struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
@@ -2537,7 +2749,7 @@ void ata_bmdma_setup_pio (struct ata_queued_cmd *qc)
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
+static void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	u8 dmactl;
@@ -2548,6 +2760,22 @@ void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
 	     ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
 }
 
+void ata_bmdma_start(struct ata_queued_cmd *qc)
+{
+	if (qc->ap->flags & ATA_FLAG_MMIO)
+		ata_bmdma_start_mmio(qc);
+	else
+		ata_bmdma_start_pio(qc);
+}
+
+void ata_bmdma_setup(struct ata_queued_cmd *qc)
+{
+	if (qc->ap->flags & ATA_FLAG_MMIO)
+		ata_bmdma_setup_mmio(qc);
+	else
+		ata_bmdma_setup_pio(qc);
+}
+
 void ata_bmdma_irq_clear(struct ata_port *ap)
 {
 	ata_bmdma_ack_irq(ap);
@@ -2581,7 +2809,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
 	case ATA_PROT_ATAPI:
 		/* check status of DMA engine */
 		host_stat = ata_bmdma_status(ap);
-		VPRINTK("BUS_DMA (host_stat 0x%X)\n", host_stat);
+		VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat);
 
 		/* if it's not our irq... */
 		if (!(host_stat & ATA_DMA_INTR))
@@ -2592,6 +2820,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
 
 		/* fall through */
 
+	case ATA_PROT_ATAPI_NODATA:
 	case ATA_PROT_NODATA:
 		/* check altstatus */
 		status = ata_altstatus(ap);
@@ -2602,7 +2831,8 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
 		status = ata_chk_status(ap);
 		if (unlikely(status & ATA_BUSY))
 			goto idle_irq;
-		DPRINTK("BUS_NODATA (dev_stat 0x%X)\n", status);
+		DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
+			ap->id, qc->tf.protocol, status);
 
 		/* ack bmdma irq events */
 		ata_bmdma_ack_irq(ap);
@@ -2701,21 +2931,20 @@ static void atapi_packet_task(void *_data)
 
 	/* make sure DRQ is set */
 	status = ata_chk_status(ap);
-	if ((status & ATA_DRQ) == 0)
+	if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)
 		goto err_out;
 
 	/* send SCSI cdb */
-	/* FIXME: mmio-ize */
 	DPRINTK("send cdb\n");
-	outsl(ap->ioaddr.data_addr,
-	      qc->scsicmd->cmnd, ap->host->max_cmd_len / 4);
+	assert(ap->cdb_len >= 12);
+	ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1);
 
 	/* if we are DMA'ing, irq handler takes over from here */
 	if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
 		ap->ops->bmdma_start(qc);	    /* initiate bmdma */
 
 	/* non-data commands are also handled via irq */
-	else if (qc->scsicmd->sc_data_direction == SCSI_DATA_NONE) {
+	else if (qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
 		/* do nothing */
 	}
 
@@ -2804,11 +3033,11 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
 	ap->host_set = host_set;
 	ap->port_no = port_no;
 	ap->pio_mask = ent->pio_mask;
+	ap->mwdma_mask = ent->mwdma_mask;
 	ap->udma_mask = ent->udma_mask;
 	ap->flags |= ent->host_flags;
 	ap->ops = ent->port_ops;
 	ap->cbl = ATA_CBL_NONE;
-	ap->device[0].flags = ATA_DFLAG_MASTER;
 	ap->active_tag = ATA_TAG_POISON;
 	ap->last_ctl = 0xFF;
 
@@ -2901,19 +3130,23 @@ int ata_device_add(struct ata_probe_ent *ent)
 	/* register each port bound to this device */
 	for (i = 0; i < ent->n_ports; i++) {
 		struct ata_port *ap;
+		unsigned long xfer_mode_mask;
 
 		ap = ata_host_add(ent, host_set, i);
 		if (!ap)
 			goto err_out;
 
 		host_set->ports[i] = ap;
+		xfer_mode_mask =(ap->udma_mask << ATA_SHIFT_UDMA) |
+				(ap->mwdma_mask << ATA_SHIFT_MWDMA) |
+				(ap->pio_mask << ATA_SHIFT_PIO);
 
 		/* print per-port info to dmesg */
 		printk(KERN_INFO "ata%u: %cATA max %s cmd 0x%lX ctl 0x%lX "
 				 "bmdma 0x%lX irq %lu\n",
 			ap->id,
 			ap->flags & ATA_FLAG_SATA ? 'S' : 'P',
-			ata_udma_string(ent->udma_mask),
+			ata_mode_string(xfer_mode_mask),
 	       		ap->ioaddr.cmd_addr,
 	       		ap->ioaddr.ctl_addr,
 	       		ap->ioaddr.bmdma_addr,
@@ -3035,6 +3268,95 @@ void ata_std_ports(struct ata_ioports *ioaddr)
 	ioaddr->command_addr = ioaddr->cmd_addr + ATA_REG_CMD;
 }
 
+static struct ata_probe_ent *
+ata_probe_ent_alloc(int n, struct pci_dev *pdev, struct ata_port_info **port)
+{
+	struct ata_probe_ent *probe_ent;
+	int i;
+
+	probe_ent = kmalloc(sizeof(*probe_ent) * n, GFP_KERNEL);
+	if (!probe_ent) {
+		printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
+		       pci_name(pdev));
+		return NULL;
+	}
+
+	memset(probe_ent, 0, sizeof(*probe_ent) * n);
+
+	for (i = 0; i < n; i++) {
+		INIT_LIST_HEAD(&probe_ent[i].node);
+		probe_ent[i].pdev = pdev;
+
+		probe_ent[i].sht = port[i]->sht;
+		probe_ent[i].host_flags = port[i]->host_flags;
+		probe_ent[i].pio_mask = port[i]->pio_mask;
+		probe_ent[i].mwdma_mask = port[i]->mwdma_mask;
+		probe_ent[i].udma_mask = port[i]->udma_mask;
+		probe_ent[i].port_ops = port[i]->port_ops;
+
+	}
+
+	return probe_ent;
+}
+
+struct ata_probe_ent *
+ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port)
+{
+	struct ata_probe_ent *probe_ent = ata_probe_ent_alloc(1, pdev, port);
+	if (!probe_ent)
+		return NULL;
+
+	probe_ent->n_ports = 2;
+	probe_ent->irq = pdev->irq;
+	probe_ent->irq_flags = SA_SHIRQ;
+
+	probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
+	probe_ent->port[0].altstatus_addr =
+	probe_ent->port[0].ctl_addr =
+		pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
+	probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
+
+	probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
+	probe_ent->port[1].altstatus_addr =
+	probe_ent->port[1].ctl_addr =
+		pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
+	probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
+
+	ata_std_ports(&probe_ent->port[0]);
+	ata_std_ports(&probe_ent->port[1]);
+
+	return probe_ent;
+}
+
+struct ata_probe_ent *
+ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port)
+{
+	struct ata_probe_ent *probe_ent = ata_probe_ent_alloc(2, pdev, port);
+	if (!probe_ent)
+		return NULL;
+
+	probe_ent[0].n_ports = 1;
+	probe_ent[0].irq = 14;
+
+	probe_ent[1].n_ports = 1;
+	probe_ent[1].irq = 15;
+
+	probe_ent[0].port[0].cmd_addr = 0x1f0;
+	probe_ent[0].port[0].altstatus_addr =
+	probe_ent[0].port[0].ctl_addr = 0x3f6;
+	probe_ent[0].port[0].bmdma_addr = pci_resource_start(pdev, 4);
+
+	probe_ent[1].port[0].cmd_addr = 0x170;
+	probe_ent[1].port[0].altstatus_addr =
+	probe_ent[1].port[0].ctl_addr = 0x376;
+	probe_ent[1].port[0].bmdma_addr = pci_resource_start(pdev, 4)+8;
+
+	ata_std_ports(&probe_ent[0].port[0]);
+	ata_std_ports(&probe_ent[1].port[0]);
+
+	return probe_ent;
+}
+
 /**
  *	ata_pci_init_one - Initialize/register PCI IDE host controller
  *	@pdev: Controller to be initialized
@@ -3052,20 +3374,20 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
 		      unsigned int n_ports)
 {
 	struct ata_probe_ent *probe_ent, *probe_ent2 = NULL;
-	struct ata_port_info *port0, *port1;
+	struct ata_port_info *port[2];
 	u8 tmp8, mask;
 	unsigned int legacy_mode = 0;
 	int rc;
 
 	DPRINTK("ENTER\n");
 
-	port0 = port_info[0];
+	port[0] = port_info[0];
 	if (n_ports > 1)
-		port1 = port_info[1];
+		port[1] = port_info[1];
 	else
-		port1 = port0;
+		port[1] = port[0];
 
-	if ((port0->host_flags & ATA_FLAG_NO_LEGACY) == 0) {
+	if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0) {
 		/* TODO: support transitioning to native mode? */
 		pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
 		mask = (1 << 2) | (1 << 0);
@@ -3126,75 +3448,17 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
 	if (rc)
 		goto err_out_regions;
 
-	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	if (legacy_mode) {
+		probe_ent = ata_pci_init_legacy_mode(pdev, port);
+		if (probe_ent)
+			probe_ent2 = &probe_ent[1];
+	} else
+		probe_ent = ata_pci_init_native_mode(pdev, port);
 	if (!probe_ent) {
 		rc = -ENOMEM;
 		goto err_out_regions;
 	}
 
-	memset(probe_ent, 0, sizeof(*probe_ent));
-	probe_ent->pdev = pdev;
-	INIT_LIST_HEAD(&probe_ent->node);
-
-	if (legacy_mode) {
-		probe_ent2 = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
-		if (!probe_ent2) {
-			rc = -ENOMEM;
-			goto err_out_free_ent;
-		}
-
-		memset(probe_ent2, 0, sizeof(*probe_ent));
-		probe_ent2->pdev = pdev;
-		INIT_LIST_HEAD(&probe_ent2->node);
-	}
-
-	probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
-	probe_ent->sht = port0->sht;
-	probe_ent->host_flags = port0->host_flags;
-	probe_ent->pio_mask = port0->pio_mask;
-	probe_ent->udma_mask = port0->udma_mask;
-	probe_ent->port_ops = port0->port_ops;
-
-	if (legacy_mode) {
-		probe_ent->port[0].cmd_addr = 0x1f0;
-		probe_ent->port[0].altstatus_addr =
-		probe_ent->port[0].ctl_addr = 0x3f6;
-		probe_ent->n_ports = 1;
-		probe_ent->irq = 14;
-		ata_std_ports(&probe_ent->port[0]);
-
-		probe_ent2->port[0].cmd_addr = 0x170;
-		probe_ent2->port[0].altstatus_addr =
-		probe_ent2->port[0].ctl_addr = 0x376;
-		probe_ent2->port[0].bmdma_addr = pci_resource_start(pdev, 4)+8;
-		probe_ent2->n_ports = 1;
-		probe_ent2->irq = 15;
-		ata_std_ports(&probe_ent2->port[0]);
-
-		probe_ent2->sht = port1->sht;
-		probe_ent2->host_flags = port1->host_flags;
-		probe_ent2->pio_mask = port1->pio_mask;
-		probe_ent2->udma_mask = port1->udma_mask;
-		probe_ent2->port_ops = port1->port_ops;
-	} else {
-		probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
-		ata_std_ports(&probe_ent->port[0]);
-		probe_ent->port[0].altstatus_addr =
-		probe_ent->port[0].ctl_addr =
-			pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
-
-		probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
-		ata_std_ports(&probe_ent->port[1]);
-		probe_ent->port[1].altstatus_addr =
-		probe_ent->port[1].ctl_addr =
-			pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
-		probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
-
-		probe_ent->n_ports = 2;
-		probe_ent->irq = pdev->irq;
-		probe_ent->irq_flags = SA_SHIRQ;
-	}
-
 	pci_set_master(pdev);
 
 	/* FIXME: check ata_device_add return */
@@ -3203,17 +3467,13 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
 			ata_device_add(probe_ent);
 		if (legacy_mode & (1 << 1))
 			ata_device_add(probe_ent2);
-		kfree(probe_ent2);
 	} else {
 		ata_device_add(probe_ent);
-		assert(probe_ent2 == NULL);
 	}
 	kfree(probe_ent);
 
 	return 0;
 
-err_out_free_ent:
-	kfree(probe_ent);
 err_out_regions:
 	if (legacy_mode & (1 << 0))
 		release_region(0x1f0, 8);
@@ -3363,34 +3623,35 @@ EXPORT_SYMBOL_GPL(ata_sg_init_one);
 EXPORT_SYMBOL_GPL(ata_qc_complete);
 EXPORT_SYMBOL_GPL(ata_qc_issue_prot);
 EXPORT_SYMBOL_GPL(ata_eng_timeout);
-EXPORT_SYMBOL_GPL(ata_tf_load_pio);
-EXPORT_SYMBOL_GPL(ata_tf_load_mmio);
-EXPORT_SYMBOL_GPL(ata_tf_read_pio);
-EXPORT_SYMBOL_GPL(ata_tf_read_mmio);
+EXPORT_SYMBOL_GPL(ata_tf_load);
+EXPORT_SYMBOL_GPL(ata_tf_read);
+EXPORT_SYMBOL_GPL(ata_noop_dev_select);
+EXPORT_SYMBOL_GPL(ata_std_dev_select);
 EXPORT_SYMBOL_GPL(ata_tf_to_fis);
 EXPORT_SYMBOL_GPL(ata_tf_from_fis);
-EXPORT_SYMBOL_GPL(ata_check_status_pio);
-EXPORT_SYMBOL_GPL(ata_check_status_mmio);
-EXPORT_SYMBOL_GPL(ata_exec_command_pio);
-EXPORT_SYMBOL_GPL(ata_exec_command_mmio);
+EXPORT_SYMBOL_GPL(ata_pci_init_legacy_mode);
+EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
+EXPORT_SYMBOL_GPL(ata_check_status);
+EXPORT_SYMBOL_GPL(ata_exec_command);
 EXPORT_SYMBOL_GPL(ata_port_start);
 EXPORT_SYMBOL_GPL(ata_port_stop);
 EXPORT_SYMBOL_GPL(ata_interrupt);
 EXPORT_SYMBOL_GPL(ata_qc_prep);
-EXPORT_SYMBOL_GPL(ata_bmdma_setup_pio);
-EXPORT_SYMBOL_GPL(ata_bmdma_start_pio);
-EXPORT_SYMBOL_GPL(ata_bmdma_setup_mmio);
-EXPORT_SYMBOL_GPL(ata_bmdma_start_mmio);
+EXPORT_SYMBOL_GPL(ata_bmdma_setup);
+EXPORT_SYMBOL_GPL(ata_bmdma_start);
 EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear);
 EXPORT_SYMBOL_GPL(ata_port_probe);
 EXPORT_SYMBOL_GPL(sata_phy_reset);
+EXPORT_SYMBOL_GPL(__sata_phy_reset);
 EXPORT_SYMBOL_GPL(ata_bus_reset);
 EXPORT_SYMBOL_GPL(ata_port_disable);
 EXPORT_SYMBOL_GPL(ata_pci_init_one);
 EXPORT_SYMBOL_GPL(ata_pci_remove_one);
+EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
 EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
 EXPORT_SYMBOL_GPL(ata_scsi_error);
 EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
 EXPORT_SYMBOL_GPL(ata_scsi_release);
 EXPORT_SYMBOL_GPL(ata_host_intr);
+EXPORT_SYMBOL_GPL(ata_dev_classify);
 EXPORT_SYMBOL_GPL(ata_dev_id_string);
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index b3340607b..47c0af26f 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -29,6 +29,7 @@
 #include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
+#include <asm/uaccess.h>
 
 #include "libata.h"
 
@@ -36,6 +37,8 @@ typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, u8 *scsicmd);
 static void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
 			      struct scsi_cmnd *cmd,
 			      void (*done)(struct scsi_cmnd *));
+static struct ata_device *
+ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev);
 
 
 /**
@@ -67,6 +70,43 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
 	return 0;
 }
 
+int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
+{
+	struct ata_port *ap;
+	struct ata_device *dev;
+	int val = -EINVAL, rc = -EINVAL;
+
+	ap = (struct ata_port *) &scsidev->host->hostdata[0];
+	if (!ap)
+		goto out;
+
+	dev = ata_scsi_find_dev(ap, scsidev);
+	if (!dev) {
+		rc = -ENODEV;
+		goto out;
+	}
+
+	switch (cmd) {
+	case ATA_IOC_GET_IO32:
+		val = 0;
+		if (copy_to_user(arg, &val, 1))
+			return -EFAULT;
+		return 0;
+
+	case ATA_IOC_SET_IO32:
+		val = (unsigned long) arg;
+		if (val != 0)
+			return -EINVAL;
+		return 0;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+out:
+	return rc;
+}
 
 /**
  *	ata_scsi_qc_new - acquire new ata_queued_cmd reference
@@ -120,34 +160,158 @@ struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap,
  *	ata_to_sense_error - convert ATA error to SCSI error
  *	@qc: Command that we are erroring out
  *
- *	Converts an ATA error into a SCSI error.
- *
- *	Right now, this routine is laughably primitive.  We
- *	don't even examine what ATA told us, we just look at
- *	the command data direction, and return a fatal SCSI
- *	sense error based on that.
+ *	Converts an ATA error into a SCSI error. While we are at it
+ *	we decode and dump the ATA error for the user so that they
+ *	have some idea what really happened at the non make-believe
+ *	layer.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_to_sense_error(struct ata_queued_cmd *qc)
+void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
 {
 	struct scsi_cmnd *cmd = qc->scsicmd;
+	u8 err = 0;
+	unsigned char *sb = cmd->sense_buffer;
+	/* Based on the 3ware driver translation table */
+	static unsigned char sense_table[][4] = {
+		/* BBD|ECC|ID|MAR */
+		{0xd1, 		ABORTED_COMMAND, 0x00, 0x00}, 	// Device busy                  Aborted command
+		/* BBD|ECC|ID */
+		{0xd0,  	ABORTED_COMMAND, 0x00, 0x00}, 	// Device busy                  Aborted command
+		/* ECC|MC|MARK */
+		{0x61, 		HARDWARE_ERROR, 0x00, 0x00}, 	// Device fault                 Hardware error
+		/* ICRC|ABRT */		/* NB: ICRC & !ABRT is BBD */
+		{0x84, 		ABORTED_COMMAND, 0x47, 0x00}, 	// Data CRC error               SCSI parity error
+		/* MC|ID|ABRT|TRK0|MARK */
+		{0x37, 		NOT_READY, 0x04, 0x00}, 	// Unit offline                 Not ready
+		/* MCR|MARK */
+		{0x09, 		NOT_READY, 0x04, 0x00}, 	// Unrecovered disk error       Not ready
+		/*  Bad address mark */
+		{0x01, 		MEDIUM_ERROR, 0x13, 0x00}, 	// Address mark not found       Address mark not found for data field
+		/* TRK0 */
+		{0x02, 		HARDWARE_ERROR, 0x00, 0x00}, 	// Track 0 not found		  Hardware error
+		/* Abort & !ICRC */
+		{0x04, 		ABORTED_COMMAND, 0x00, 0x00}, 	// Aborted command              Aborted command
+		/* Media change request */
+		{0x08, 		NOT_READY, 0x04, 0x00}, 	// Media change request	  FIXME: faking offline
+		/* SRV */
+		{0x10, 		ABORTED_COMMAND, 0x14, 0x00}, 	// ID not found                 Recorded entity not found
+		/* Media change */
+		{0x08,  	NOT_READY, 0x04, 0x00}, 	// Media change		  FIXME: faking offline
+		/* ECC */
+		{0x40, 		MEDIUM_ERROR, 0x11, 0x04}, 	// Uncorrectable ECC error      Unrecovered read error
+		/* BBD - block marked bad */
+		{0x80, 		MEDIUM_ERROR, 0x11, 0x04}, 	// Block marked bad		  Medium error, unrecovered read error
+		{0xFF, 0xFF, 0xFF, 0xFF}, // END mark 
+	};
+	static unsigned char stat_table[][4] = {
+		/* Must be first because BUSY means no other bits valid */
+		{0x80, 		ABORTED_COMMAND, 0x47, 0x00},	// Busy, fake parity for now
+		{0x20, 		HARDWARE_ERROR,  0x00, 0x00}, 	// Device fault
+		{0x08, 		ABORTED_COMMAND, 0x47, 0x00},	// Timed out in xfer, fake parity for now
+		{0x04, 		RECOVERED_ERROR, 0x11, 0x00},	// Recovered ECC error	  Medium error, recovered
+		{0xFF, 0xFF, 0xFF, 0xFF}, // END mark 
+	};
+	int i = 0;
 
 	cmd->result = SAM_STAT_CHECK_CONDITION;
-
-	cmd->sense_buffer[0] = 0x70;
-	cmd->sense_buffer[2] = MEDIUM_ERROR;
-	cmd->sense_buffer[7] = 14 - 8;	/* addnl. sense len. FIXME: correct? */
-
+	
+	/*
+	 *	Is this an error we can process/parse
+	 */
+	 
+	if(drv_stat & ATA_ERR)
+		/* Read the err bits */
+		err = ata_chk_err(qc->ap);
+
+	/* Display the ATA level error info */
+	
+	printk(KERN_WARNING "ata%u: status=0x%02x { ", qc->ap->id, drv_stat);
+	if(drv_stat & 0x80)
+	{
+		printk("Busy ");
+		err = 0;	/* Data is not valid in this case */
+	}
+	else {
+		if(drv_stat & 0x40)	printk("DriveReady ");
+		if(drv_stat & 0x20)	printk("DeviceFault ");
+		if(drv_stat & 0x10)	printk("SeekComplete ");
+		if(drv_stat & 0x08)	printk("DataRequest ");
+		if(drv_stat & 0x04)	printk("CorrectedError ");
+		if(drv_stat & 0x02)	printk("Index ");
+		if(drv_stat & 0x01)	printk("Error ");
+	}
+	printk("}\n");
+	
+	if(err)
+	{
+		printk(KERN_WARNING "ata%u: error=0x%02x { ", qc->ap->id, err);
+		if(err & 0x04)		printk("DriveStatusError ");
+		if(err & 0x80)
+		{
+			if(err & 0x04)
+				printk("BadCRC ");
+			else
+				printk("Sector ");
+		}
+		if(err & 0x40)		printk("UncorrectableError ");
+		if(err & 0x10)		printk("SectorIdNotFound ");
+		if(err & 0x02)		printk("TrackZeroNotFound ");
+		if(err & 0x01)		printk("AddrMarkNotFound ");
+		printk("}\n");
+		
+		/* Should we dump sector info here too ?? */
+	}
+		
+	
+	/* Look for err */
+	while(sense_table[i][0] != 0xFF)
+	{
+		/* Look for best matches first */
+		if((sense_table[i][0] & err) == sense_table[i][0])
+		{
+			sb[0] = 0x70;
+			sb[2] = sense_table[i][1];
+			sb[7] = 0x0a;
+			sb[12] = sense_table[i][2];
+			sb[13] = sense_table[i][3];
+			return;
+		}
+		i++;
+	}
+	/* No immediate match */
+	if(err)
+		printk(KERN_DEBUG "ata%u: no sense translation for 0x%02x\n", qc->ap->id, err);
+	
+	/* Fall back to interpreting status bits */
+	while(stat_table[i][0] != 0xFF)
+	{
+		if(stat_table[i][0] & drv_stat)
+		{
+			sb[0] = 0x70;
+			sb[2] = stat_table[i][1];
+			sb[7] = 0x0a;
+			sb[12] = stat_table[i][2];
+			sb[13] = stat_table[i][3];
+			return;
+		}
+		i++;
+	}
+	/* No error ?? */
+	printk(KERN_ERR "ata%u: called with no error (%02X)!\n", qc->ap->id, drv_stat);
 	/* additional-sense-code[-qualifier] */
+	
+	sb[0] = 0x70;
+	sb[2] = MEDIUM_ERROR;
+	sb[7] = 0x0A;
 	if (cmd->sc_data_direction == SCSI_DATA_READ) {
-		cmd->sense_buffer[12] = 0x11; /* "unrecovered read error" */
-		cmd->sense_buffer[13] = 0x04;
+		sb[12] = 0x11; /* "unrecovered read error" */
+		sb[13] = 0x04;
 	} else {
-		cmd->sense_buffer[12] = 0x0C; /* "write error -             */
-		cmd->sense_buffer[13] = 0x02; /*  auto-reallocation failed" */
+		sb[12] = 0x0C; /* "write error -             */
+		sb[13] = 0x02; /*  auto-reallocation failed" */
 	}
 }
 
@@ -214,10 +378,134 @@ int ata_scsi_error(struct Scsi_Host *host)
 	ap = (struct ata_port *) &host->hostdata[0];
 	ap->ops->eng_timeout(ap);
 
+	/* TODO: this is per-command; when queueing is supported
+	 * this code will either change or move to a more
+	 * appropriate place
+	 */
+	host->host_failed--;
+
 	DPRINTK("EXIT\n");
 	return 0;
 }
 
+/**
+ *	ata_scsi_flush_xlat - Translate SCSI SYNCHRONIZE CACHE command
+ *	@qc: Storage for translated ATA taskfile
+ *	@scsicmd: SCSI command to translate (ignored)
+ *
+ *	Sets up an ATA taskfile to issue FLUSH CACHE or
+ *	FLUSH CACHE EXT.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	Zero on success, non-zero on error.
+ */
+
+static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
+{
+	struct ata_taskfile *tf = &qc->tf;
+
+	tf->flags |= ATA_TFLAG_DEVICE;
+	tf->protocol = ATA_PROT_NODATA;
+
+	if ((tf->flags & ATA_TFLAG_LBA48) &&
+	    (ata_id_has_flush_ext(qc->dev)))
+		tf->command = ATA_CMD_FLUSH_EXT;
+	else
+		tf->command = ATA_CMD_FLUSH;
+
+	return 0;
+}
+
+/**
+ *	ata_scsi_verify_xlat - Translate SCSI VERIFY command into an ATA one
+ *	@qc: Storage for translated ATA taskfile
+ *	@scsicmd: SCSI command to translate
+ *
+ *	Converts SCSI VERIFY command to an ATA READ VERIFY command.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	Zero on success, non-zero on error.
+ */
+
+static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
+{
+	struct ata_taskfile *tf = &qc->tf;
+	unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
+	u64 dev_sectors = qc->dev->n_sectors;
+	u64 sect = 0;
+	u32 n_sect = 0;
+
+	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf->protocol = ATA_PROT_NODATA;
+	tf->device |= ATA_LBA;
+
+	if (scsicmd[0] == VERIFY) {
+		sect |= ((u64)scsicmd[2]) << 24;
+		sect |= ((u64)scsicmd[3]) << 16;
+		sect |= ((u64)scsicmd[4]) << 8;
+		sect |= ((u64)scsicmd[5]);
+
+		n_sect |= ((u32)scsicmd[7]) << 8;
+		n_sect |= ((u32)scsicmd[8]);
+	}
+
+	else if (scsicmd[0] == VERIFY_16) {
+		sect |= ((u64)scsicmd[2]) << 56;
+		sect |= ((u64)scsicmd[3]) << 48;
+		sect |= ((u64)scsicmd[4]) << 40;
+		sect |= ((u64)scsicmd[5]) << 32;
+		sect |= ((u64)scsicmd[6]) << 24;
+		sect |= ((u64)scsicmd[7]) << 16;
+		sect |= ((u64)scsicmd[8]) << 8;
+		sect |= ((u64)scsicmd[9]);
+
+		n_sect |= ((u32)scsicmd[10]) << 24;
+		n_sect |= ((u32)scsicmd[11]) << 16;
+		n_sect |= ((u32)scsicmd[12]) << 8;
+		n_sect |= ((u32)scsicmd[13]);
+	}
+
+	else
+		return 1;
+
+	if (!n_sect)
+		return 1;
+	if (sect >= dev_sectors)
+		return 1;
+	if ((sect + n_sect) > dev_sectors)
+		return 1;
+	if (lba48) {
+		if (n_sect > (64 * 1024))
+			return 1;
+	} else {
+		if (n_sect > 256)
+			return 1;
+	}
+
+	if (lba48) {
+		tf->hob_nsect = (n_sect >> 8) & 0xff;
+
+		tf->hob_lbah = (sect >> 40) & 0xff;
+		tf->hob_lbam = (sect >> 32) & 0xff;
+		tf->hob_lbal = (sect >> 24) & 0xff;
+	} else
+		tf->device |= (sect >> 24) & 0xf;
+
+	tf->nsect = n_sect & 0xff;
+
+	tf->hob_lbah = (sect >> 16) & 0xff;
+	tf->hob_lbam = (sect >> 8) & 0xff;
+	tf->hob_lbal = sect & 0xff;
+
+	return 0;
+}
+
 /**
  *	ata_scsi_rw_xlat - Translate SCSI r/w command into an ATA one
  *	@qc: Storage for translated ATA taskfile
@@ -244,10 +532,6 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
 	unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
 
 	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-	tf->hob_nsect = 0;
-	tf->hob_lbal = 0;
-	tf->hob_lbam = 0;
-	tf->hob_lbah = 0;
 	tf->protocol = qc->dev->xfer_protocol;
 	tf->device |= ATA_LBA;
 
@@ -339,14 +623,10 @@ static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
 {
 	struct scsi_cmnd *cmd = qc->scsicmd;
 
-	if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) {
-		if (is_atapi_taskfile(&qc->tf))
-			cmd->result = SAM_STAT_CHECK_CONDITION;
-		else
-			ata_to_sense_error(qc);
-	} else {
+	if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ)))
+		ata_to_sense_error(qc, drv_stat);
+	else
 		cmd->result = SAM_STAT_GOOD;
-	}
 
 	qc->scsidone(cmd);
 
@@ -534,7 +814,7 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
 		0,
 		0x5,	/* claim SPC-3 version compatibility */
 		2,
-		96 - 4
+		95 - 4
 	};
 
 	/* set scsi removeable (RMB) bit per ata bit */
@@ -545,7 +825,7 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
 
 	memcpy(rbuf, hdr, sizeof(hdr));
 
-	if (buflen > 36) {
+	if (buflen > 35) {
 		memcpy(&rbuf[8], "ATA     ", 8);
 		ata_dev_id_string(dev, &rbuf[16], ATA_ID_PROD_OFS, 16);
 		ata_dev_id_string(dev, &rbuf[32], ATA_ID_FW_REV_OFS, 4);
@@ -964,6 +1244,31 @@ void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8
 	done(cmd);
 }
 
+static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
+{
+	struct scsi_cmnd *cmd = qc->scsicmd;
+
+	if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ)))
+		cmd->result = SAM_STAT_CHECK_CONDITION;
+	else {
+		u8 *scsicmd = cmd->cmnd;
+
+		if (scsicmd[0] == INQUIRY) {
+			u8 *buf = NULL;
+			unsigned int buflen;
+
+			buflen = ata_scsi_rbuf_get(cmd, &buf);
+			buf[2] = 0x5;
+			buf[3] = (buf[3] & 0xf0) | 2;
+			ata_scsi_rbuf_put(cmd);
+		}
+		cmd->result = SAM_STAT_GOOD;
+	}
+
+	qc->scsidone(cmd);
+
+	return 0;
+}
 /**
  *	atapi_xlat - Initialize PACKET taskfile
  *	@qc: command structure to be initialized
@@ -979,6 +1284,13 @@ void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8
 static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
 {
 	struct scsi_cmnd *cmd = qc->scsicmd;
+	struct ata_device *dev = qc->dev;
+	int using_pio = (dev->flags & ATA_DFLAG_PIO);
+	int nodata = (cmd->sc_data_direction == SCSI_DATA_NONE);
+
+	memcpy(&qc->cdb, scsicmd, qc->ap->cdb_len);
+
+	qc->complete_fn = atapi_qc_complete;
 
 	qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
 	if (cmd->sc_data_direction == SCSI_DATA_WRITE) {
@@ -988,19 +1300,18 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
 
 	qc->tf.command = ATA_CMD_PACKET;
 
-	/* no data - interrupt-driven */
-	if (cmd->sc_data_direction == SCSI_DATA_NONE)
-		qc->tf.protocol = ATA_PROT_ATAPI;
-
-	/* PIO data xfer - polling */
-	else if ((qc->flags & ATA_QCFLAG_DMA) == 0) {
-		ata_qc_set_polling(qc);
-		qc->tf.protocol = ATA_PROT_ATAPI;
+	/* no data, or PIO data xfer */
+	if (using_pio || nodata) {
+		if (nodata)
+			qc->tf.protocol = ATA_PROT_ATAPI_NODATA;
+		else
+			qc->tf.protocol = ATA_PROT_ATAPI;
 		qc->tf.lbam = (8 * 1024) & 0xff;
 		qc->tf.lbah = (8 * 1024) >> 8;
+	}
 
-	/* DMA data xfer - interrupt-driven */
-	} else {
+	/* DMA data xfer */
+	else {
 		qc->tf.protocol = ATA_PROT_ATAPI_DMA;
 		qc->tf.feature |= ATAPI_PKT_DMA;
 
@@ -1031,19 +1342,19 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
  *	Associated ATA device, or %NULL if not found.
  */
 
-static inline struct ata_device *
-ata_scsi_find_dev(struct ata_port *ap, struct scsi_cmnd *cmd)
+static struct ata_device *
+ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev)
 {
 	struct ata_device *dev;
 
 	/* skip commands not addressed to targets we simulate */
-	if (likely(cmd->device->id < ATA_MAX_DEVICES))
-		dev = &ap->device[cmd->device->id];
+	if (likely(scsidev->id < ATA_MAX_DEVICES))
+		dev = &ap->device[scsidev->id];
 	else
 		return NULL;
 
-	if (unlikely((cmd->device->channel != 0) ||
-		     (cmd->device->lun != 0)))
+	if (unlikely((scsidev->channel != 0) ||
+		     (scsidev->lun != 0)))
 		return NULL;
 
 	if (unlikely(!ata_dev_present(dev)))
@@ -1059,6 +1370,7 @@ ata_scsi_find_dev(struct ata_port *ap, struct scsi_cmnd *cmd)
 
 /**
  *	ata_get_xlat_func - check if SCSI to ATA translation is possible
+ *	@dev: ATA device
  *	@cmd: SCSI command opcode to consider
  *
  *	Look up the SCSI command given, and determine whether the
@@ -1068,7 +1380,7 @@ ata_scsi_find_dev(struct ata_port *ap, struct scsi_cmnd *cmd)
  *	Pointer to translation function if possible, %NULL if not.
  */
 
-static inline ata_xlat_func_t ata_get_xlat_func(u8 cmd)
+static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
 {
 	switch (cmd) {
 	case READ_6:
@@ -1079,6 +1391,15 @@ static inline ata_xlat_func_t ata_get_xlat_func(u8 cmd)
 	case WRITE_10:
 	case WRITE_16:
 		return ata_scsi_rw_xlat;
+
+	case SYNCHRONIZE_CACHE:
+		if (ata_try_flush_cache(dev))
+			return ata_scsi_flush_xlat;
+		break;
+
+	case VERIFY:
+	case VERIFY_16:
+		return ata_scsi_verify_xlat;
 	}
 
 	return NULL;
@@ -1096,11 +1417,12 @@ static inline void ata_scsi_dump_cdb(struct ata_port *ap,
 				     struct scsi_cmnd *cmd)
 {
 #ifdef ATA_DEBUG
+	struct scsi_device *scsidev = cmd->device;
 	u8 *scsicmd = cmd->cmnd;
 
 	DPRINTK("CDB (%u:%d,%d,%d) %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
 		ap->id,
-		cmd->device->channel, cmd->device->id, cmd->device->lun,
+		scsidev->channel, scsidev->id, scsidev->lun,
 		scsicmd[0], scsicmd[1], scsicmd[2], scsicmd[3],
 		scsicmd[4], scsicmd[5], scsicmd[6], scsicmd[7],
 		scsicmd[8]);
@@ -1130,12 +1452,13 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 {
 	struct ata_port *ap;
 	struct ata_device *dev;
+	struct scsi_device *scsidev = cmd->device;
 
-	ap = (struct ata_port *) &cmd->device->host->hostdata[0];
+	ap = (struct ata_port *) &scsidev->host->hostdata[0];
 
 	ata_scsi_dump_cdb(ap, cmd);
 
-	dev = ata_scsi_find_dev(ap, cmd);
+	dev = ata_scsi_find_dev(ap, scsidev);
 	if (unlikely(!dev)) {
 		cmd->result = (DID_BAD_TARGET << 16);
 		done(cmd);
@@ -1143,7 +1466,8 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 	}
 
 	if (dev->class == ATA_DEV_ATA) {
-		ata_xlat_func_t xlat_func = ata_get_xlat_func(cmd->cmnd[0]);
+		ata_xlat_func_t xlat_func = ata_get_xlat_func(dev,
+							      cmd->cmnd[0]);
 
 		if (xlat_func)
 			ata_scsi_translate(ap, dev, cmd, done, xlat_func);
@@ -1184,7 +1508,7 @@ static void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
 
 	switch(scsicmd[0]) {
 		/* no-op's, complete with success */
-		case SYNCHRONIZE_CACHE:		/* FIXME: temporary */
+		case SYNCHRONIZE_CACHE:
 		case REZERO_UNIT:
 		case SEEK_6:
 		case SEEK_10:
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index 460c72c1b..68c268e41 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -42,10 +42,11 @@ extern int ata_qc_issue(struct ata_queued_cmd *qc);
 extern void ata_dev_select(struct ata_port *ap, unsigned int device,
                            unsigned int wait, unsigned int can_sleep);
 extern void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf);
+extern void swap_buf_le16(u16 *buf, unsigned int buf_words);
 
 
 /* libata-scsi.c */
-extern void ata_to_sense_error(struct ata_queued_cmd *qc);
+extern void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat);
 extern int ata_scsi_error(struct Scsi_Host *host);
 extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
 			       unsigned int buflen);
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index f343fc704..ef6a0c807 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -326,6 +326,7 @@ int macscsi_release (struct Scsi_Host *shpnt)
 {
 	if (shpnt->irq != SCSI_IRQ_NONE)
 		free_irq (shpnt->irq, NCR5380_intr);
+	NCR5380_exit(shpnt);
 
 	return 0;
 }
diff --git a/drivers/scsi/mca_53c9x.c b/drivers/scsi/mca_53c9x.c
index e64b8ec2f..d959c627a 100644
--- a/drivers/scsi/mca_53c9x.c
+++ b/drivers/scsi/mca_53c9x.c
@@ -238,15 +238,15 @@ int mca_esp_detect(Scsi_Host_Template *tpnt)
 
 			/* Optional functions */
 
-			esp->dma_barrier = 0;
-			esp->dma_drain = 0;
-			esp->dma_invalidate = 0;
-			esp->dma_irq_entry = 0;
-			esp->dma_irq_exit = 0;
+			esp->dma_barrier = NULL;
+			esp->dma_drain = NULL;
+			esp->dma_invalidate = NULL;
+			esp->dma_irq_entry = NULL;
+			esp->dma_irq_exit = NULL;
 			esp->dma_led_on = dma_led_on;
 			esp->dma_led_off = dma_led_off;
-			esp->dma_poll = 0;
-			esp->dma_reset = 0;
+			esp->dma_poll = NULL;
+			esp->dma_reset = NULL;
 
 			/* Set the command buffer */
 
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 5fd685e9a..bdab1b659 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -25,11 +25,8 @@
  *					518, 520, 531, 532
  *
  * This driver is supported by LSI Logic, with assistance from Red Hat, Dell,
- * and others. Please send updates to the public mailing list
- * linux-megaraid-devel@dell.com, and subscribe to and read archives of this
- * list at http://lists.us.dell.com/.
- *
- * For history of changes, see ChangeLog.megaraid.
+ * and others. Please send updates to the mailing list
+ * linux-scsi@vger.kernel.org .
  *
  */
 
@@ -53,9 +50,12 @@
 
 #include "megaraid.h"
 
+#define MEGARAID_MODULE_VERSION "2.00.3"
+
 MODULE_AUTHOR ("LSI Logic Corporation");
 MODULE_DESCRIPTION ("LSI Logic MegaRAID driver");
 MODULE_LICENSE ("GPL");
+MODULE_VERSION(MEGARAID_MODULE_VERSION);
 
 static unsigned int max_cmd_per_lun = DEF_CMD_PER_LUN;
 MODULE_PARM(max_cmd_per_lun, "i");
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index b43feb93c..9735d05ad 100644
--- a/drivers/scsi/nsp32.c
+++ b/drivers/scsi/nsp32.c
@@ -267,8 +267,8 @@ static        void nsp32_prom_stop     (nsp32_hw_data *);
 static        int  nsp32_prom_read     (nsp32_hw_data *, int);
 static        int  nsp32_prom_read_bit (nsp32_hw_data *);
 static        void nsp32_prom_write_bit(nsp32_hw_data *, int);
-static inline void nsp32_prom_set      (nsp32_hw_data *, int, int);
-static inline int  nsp32_prom_get      (nsp32_hw_data *, int);
+static        void nsp32_prom_set      (nsp32_hw_data *, int, int);
+static        int  nsp32_prom_get      (nsp32_hw_data *, int);
 
 /* debug/warning/info message */
 static void nsp32_message (const char *, int, char *, char *, ...);
@@ -3342,7 +3342,7 @@ static int nsp32_prom_read(nsp32_hw_data *data, int romaddr)
 	return val;
 }
 
-static inline void nsp32_prom_set(nsp32_hw_data *data, int bit, int val)
+static void nsp32_prom_set(nsp32_hw_data *data, int bit, int val)
 {
 	int base = data->BaseAddress;
 	int tmp;
@@ -3360,7 +3360,7 @@ static inline void nsp32_prom_set(nsp32_hw_data *data, int bit, int val)
 	udelay(10);
 }
 
-static inline int nsp32_prom_get(nsp32_hw_data *data, int bit)
+static int nsp32_prom_get(nsp32_hw_data *data, int bit)
 {
 	int base = data->BaseAddress;
 	int tmp, ret;
diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c
index 1c9788e2d..78127896a 100644
--- a/drivers/scsi/pas16.c
+++ b/drivers/scsi/pas16.c
@@ -605,6 +605,7 @@ static int pas16_release(struct Scsi_Host *shost)
 {
 	if (shost->irq)
 		free_irq(shost->irq, NULL);
+	NCR5380_exit(shost);
 	if (shost->dma_channel != 0xff)
 		free_dma(shost->dma_channel);
 	if (shost->io_port && shost->n_io_port)
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index 363d79399..75648dcb6 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -1528,7 +1528,7 @@ nsp_proc_info(
 	thislength = pos - (buffer + offset);
 
 	if(thislength < 0) {
-		*start = 0;
+		*start = NULL;
                 return 0;
         }
 
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 917a208d1..c4820cfde 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -4,7 +4,7 @@
 * QLogic  QLA1280 (Ultra2)  and  QLA12160 (Ultra3) SCSI driver
 * Copyright (C) 2000 Qlogic Corporation (www.qlogic.com)
 * Copyright (C) 2001-2004 Jes Sorensen, Wild Open Source Inc.
-* Copyright (C) 2003 Christoph Hellwig
+* Copyright (C) 2003-2004 Christoph Hellwig
 *
 * 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
@@ -17,9 +17,12 @@
 * General Public License for more details.
 *
 ******************************************************************************/
-#define QLA1280_VERSION      "3.24.3"
+#define QLA1280_VERSION      "3.24.4"
 /*****************************************************************************
     Revision History:
+    Rev  3.24.4 June 7, 2004 Christoph Hellwig
+	- restructure firmware loading, cleanup initialization code
+	- prepare support for ISP1020/1040 chips
     Rev  3.24.3 January 19, 2004, Jes Sorensen
 	- Handle PCI DMA mask settings correctly
 	- Correct order of error handling in probe_one, free_irq should not
@@ -485,6 +488,14 @@ static inline void scsi_host_put(struct Scsi_Host *h)
 #define ia64_platform_is(foo)		(!strcmp(x, platform_name))
 #endif
 
+
+#define IS_ISP1040(ha) (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP1020)
+#define IS_ISP1x40(ha) (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP1020 || \
+			ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP1240)
+#define IS_ISP1x160(ha)        (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP10160 || \
+				ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP12160)
+
+
 static int qla1280_probe_one(struct pci_dev *, const struct pci_device_id *);
 static void qla1280_remove_one(struct pci_dev *);
 
@@ -501,9 +512,7 @@ static int qla1280_setup(char *s) __init;
 /*
  *  QLogic ISP1280 Hardware Support Function Prototypes.
  */
-static int qla1280_isp_firmware(struct scsi_qla_host *);
-static int qla1280_chip_diag(struct scsi_qla_host *);
-static int qla1280_setup_chip(struct scsi_qla_host *);
+static int qla1280_load_firmware(struct scsi_qla_host *);
 static int qla1280_init_rings(struct scsi_qla_host *);
 static int qla1280_nvram_config(struct scsi_qla_host *);
 static int qla1280_mailbox_command(struct scsi_qla_host *,
@@ -1384,16 +1393,10 @@ qla1280_set_target_parameters(struct scsi_qla_host *ha, int bus, int target)
 	uint8_t mr;
 	uint16_t mb[MAILBOX_REGISTER_COUNT];
 	struct nvram *nv;
-	int is1x160, status;
+	int status;
 
 	nv = &ha->nvram;
 
-	if (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP12160 ||
-	    ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP10160)
-		is1x160 = 1;
-	else
-		is1x160 = 0;
-
 	mr = BIT_3 | BIT_2 | BIT_1 | BIT_0;
 
 	/* Set Target Parameters. */
@@ -1403,17 +1406,16 @@ qla1280_set_target_parameters(struct scsi_qla_host *ha, int bus, int target)
 
 	mb[2] = (nv->bus[bus].target[target].parameter.c << 8);
 
-	if (is1x160)
-		mb[3] =	nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8;
-	else
-		mb[3] =	nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8;
-	mb[3] |= nv->bus[bus].target[target].sync_period;
-
-	if (is1x160) {
+	if (IS_ISP1x160(ha)) {
 		mb[2] |= nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr << 5;
-		mb[6] =	nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8;
-		mb[6] |= nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width;
+		mb[3] =	(nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8) |
+			 nv->bus[bus].target[target].sync_period;
+		mb[6] =	(nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8) |
+			 nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width;
 		mr |= BIT_6;
+	} else {
+		mb[3] =	(nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8) |
+			 nv->bus[bus].target[target].sync_period;
 	}
 
 	status = qla1280_mailbox_command(ha, mr, &mb[0]);
@@ -1476,8 +1478,7 @@ qla1280_slave_configure(struct scsi_device *device)
 	    (driver_setup.wide_mask &&
 	     (~driver_setup.wide_mask & (1 << target))))
 		nv->bus[bus].target[target].parameter.f.enable_wide = 0;
-	if (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP12160 ||
-	    ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP10160) {
+	if (IS_ISP1x160(ha)) {
 		if (driver_setup.no_ppr ||
 		    (driver_setup.ppr_mask &&
 		     (~driver_setup.ppr_mask & (1 << target))))
@@ -1802,17 +1803,8 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha)
 	 */
 	spin_lock_irqsave(HOST_LOCK, flags);
 #endif
-	/* If firmware needs to be loaded */
-	if (qla1280_isp_firmware(ha)) {
-		if (!(status = qla1280_chip_diag(ha))) {
-			status = qla1280_setup_chip(ha);
-		}
-	} else {
-		printk(KERN_ERR "scsi(%li): isp_firmware() failed!\n",
-		       ha->host_no);
-		status = 1;
-	}
 
+	status = qla1280_load_firmware(ha);
 	if (status) {
 		printk(KERN_ERR "scsi(%li): initialize: pci probe failed!\n",
 		       ha->host_no);
@@ -1823,36 +1815,24 @@ qla1280_initialize_adapter(struct scsi_qla_host *ha)
 	dprintk(1, "scsi(%ld): Configure NVRAM parameters\n", ha->host_no);
 	qla1280_nvram_config(ha);
 
-	if (!ha->flags.disable_host_adapter && !qla1280_init_rings(ha)) {
-		/* Issue SCSI reset. */
-		/* dg 03/13 if we can't reset twice then bus is dead */
-		for (bus = 0; bus < ha->ports; bus++) {
-			if (!ha->bus_settings[bus].disable_scsi_reset){
-				if (qla1280_bus_reset(ha, bus)) {
-					if (qla1280_bus_reset(ha, bus)) {
-						ha->bus_settings[bus].scsi_bus_dead = 1;
-					}
-				}
-			}
-		}
+	if (ha->flags.disable_host_adapter) {
+		status = 1;
+		goto out;
+	}
 
-		/*
-		 * qla1280_bus_reset() will take care of issueing markers,
-		 * no need to do that here as well!
-		 */
-#if 0
-		/* Issue marker command. */
-		ha->flags.reset_marker = 0;
-		for (bus = 0; bus < ha->ports; bus++) {
-			ha->bus_settings[bus].reset_marker = 0;
-			qla1280_marker(ha, bus, 0, 0, MK_SYNC_ALL);
-		}
-#endif
+	status = qla1280_init_rings(ha);
+	if (status)
+		goto out;
 
-		ha->flags.online = 1;
-	} else
-		status = 1;
+	/* Issue SCSI reset, if we can't reset twice then bus is dead */
+	for (bus = 0; bus < ha->ports; bus++) {
+		if (!ha->bus_settings[bus].disable_scsi_reset &&
+		    qla1280_bus_reset(ha, bus) &&
+		    qla1280_bus_reset(ha, bus))
+			ha->bus_settings[bus].scsi_bus_dead = 1;
+	}
 
+	ha->flags.online = 1;
  out:
 #if LINUX_VERSION_CODE >= 0x020500
 	spin_unlock_irqrestore(HOST_LOCK, flags);
@@ -1945,13 +1925,13 @@ qla1280_chip_diag(struct scsi_qla_host *ha)
 	int status = 0;
 	int cnt;
 	uint16_t data;
-
 	dprintk(3, "qla1280_chip_diag: testing device at 0x%p \n", &reg->id_l);
 
 	dprintk(1, "scsi(%ld): Verifying chip\n", ha->host_no);
 
 	/* Soft reset chip and wait for it to finish. */
 	WRT_REG_WORD(&reg->ictrl, ISP_RESET);
+
 	/*
 	 * We can't do a traditional PCI write flush here by reading
 	 * back the register. The card will not respond once the reset
@@ -1969,145 +1949,138 @@ qla1280_chip_diag(struct scsi_qla_host *ha)
 		data = RD_REG_WORD(&reg->ictrl);
 	}
 
-	if (cnt) {
-		/* Reset register cleared by chip reset. */
-		dprintk(3, "qla1280_chip_diag: reset register cleared by "
-			"chip reset\n");
+	if (!cnt)
+		goto fail;
 
-		WRT_REG_WORD(&reg->cfg_1, 0);
+	/* Reset register cleared by chip reset. */
+	dprintk(3, "qla1280_chip_diag: reset register cleared by chip reset\n");
 
-		/* Reset RISC and disable BIOS which
-		   allows RISC to execute out of RAM. */
-#if 0
-		WRT_REG_WORD(&reg->host_cmd, HC_RESET_RISC);
-		RD_REG_WORD(&reg->id_l);	/* Flush PCI write */
-		WRT_REG_WORD(&reg->host_cmd, HC_RELEASE_RISC);
-		RD_REG_WORD(&reg->id_l);	/* Flush PCI write */
-		WRT_REG_WORD(&reg->host_cmd, HC_DISABLE_BIOS);
-#else
-		WRT_REG_WORD(&reg->host_cmd, HC_RESET_RISC |
-			     HC_RELEASE_RISC | HC_DISABLE_BIOS);
-#endif
-		RD_REG_WORD(&reg->id_l);	/* Flush PCI write */
-		data = qla1280_debounce_register(&reg->mailbox0);
-		/*
-		 * I *LOVE* this code!
-		 */
-		for (cnt = 1000000; cnt && data == MBS_BUSY; cnt--) {
-			udelay(5);
-			data = RD_REG_WORD(&reg->mailbox0);
-		}
+	WRT_REG_WORD(&reg->cfg_1, 0);
 
-		if (cnt) {
-			/* Check product ID of chip */
-			dprintk(3, "qla1280_chip_diag: Checking product "
-				"ID of chip\n");
-
-			if (RD_REG_WORD(&reg->mailbox1) != PROD_ID_1 ||
-			    (RD_REG_WORD(&reg->mailbox2) != PROD_ID_2 &&
-			     RD_REG_WORD(&reg->mailbox2) != PROD_ID_2a) ||
-			    RD_REG_WORD(&reg->mailbox3) != PROD_ID_3 ||
-			    RD_REG_WORD(&reg->mailbox4) != PROD_ID_4) {
-				printk(KERN_INFO "qla1280: Wrong product ID = "
-				       "0x%x,0x%x,0x%x,0x%x\n",
-				       RD_REG_WORD(&reg->mailbox1),
-				       RD_REG_WORD(&reg->mailbox2),
-				       RD_REG_WORD(&reg->mailbox3),
-				       RD_REG_WORD(&reg->mailbox4));
-				status = 1;
-			} else {
-				/*
-				 * Enable ints early!!!
-				 */
-				qla1280_enable_intrs(ha);
-
-				dprintk(1, "qla1280_chip_diag: Checking "
-					"mailboxes of chip\n");
-				/* Wrap Incoming Mailboxes Test. */
-				mb[0] = MBC_MAILBOX_REGISTER_TEST;
-				mb[1] = 0xAAAA;
-				mb[2] = 0x5555;
-				mb[3] = 0xAA55;
-				mb[4] = 0x55AA;
-				mb[5] = 0xA5A5;
-				mb[6] = 0x5A5A;
-				mb[7] = 0x2525;
-				if (!(status = qla1280_mailbox_command(ha,
-								       0xff,
-								       &mb
-								       [0]))) {
-					if (mb[1] != 0xAAAA ||
-					    mb[2] != 0x5555 ||
-					    mb[3] != 0xAA55 ||
-					    mb[4] != 0x55AA ||
-					    mb[5] != 0xA5A5 ||
-					    mb[6] != 0x5A5A ||
-					    mb[7] != 0x2525) {
-						status = 1;
-						printk(KERN_INFO "qla1280: "
-						       "Failed mbox check\n");
-					}
-				}
-			}
-		} else
-			status = 1;
-	} else
-		status = 1;
+	/* Reset RISC and disable BIOS which
+	   allows RISC to execute out of RAM. */
+	WRT_REG_WORD(&reg->host_cmd, HC_RESET_RISC |
+		     HC_RELEASE_RISC | HC_DISABLE_BIOS);
 
+	RD_REG_WORD(&reg->id_l);	/* Flush PCI write */
+	data = qla1280_debounce_register(&reg->mailbox0);
+
+	/*
+	 * I *LOVE* this code!
+	 */
+	for (cnt = 1000000; cnt && data == MBS_BUSY; cnt--) {
+		udelay(5);
+		data = RD_REG_WORD(&reg->mailbox0);
+	}
+
+	if (!cnt)
+		goto fail;
+
+	/* Check product ID of chip */
+	dprintk(3, "qla1280_chip_diag: Checking product ID of chip\n");
+
+	if (RD_REG_WORD(&reg->mailbox1) != PROD_ID_1 ||
+	    (RD_REG_WORD(&reg->mailbox2) != PROD_ID_2 &&
+	     RD_REG_WORD(&reg->mailbox2) != PROD_ID_2a) ||
+	    RD_REG_WORD(&reg->mailbox3) != PROD_ID_3 ||
+	    RD_REG_WORD(&reg->mailbox4) != PROD_ID_4) {
+		printk(KERN_INFO "qla1280: Wrong product ID = "
+		       "0x%x,0x%x,0x%x,0x%x\n",
+		       RD_REG_WORD(&reg->mailbox1),
+		       RD_REG_WORD(&reg->mailbox2),
+		       RD_REG_WORD(&reg->mailbox3),
+		       RD_REG_WORD(&reg->mailbox4));
+		goto fail;
+	}
+
+	/*
+	 * Enable ints early!!!
+	 */
+	qla1280_enable_intrs(ha);
+
+	dprintk(1, "qla1280_chip_diag: Checking mailboxes of chip\n");
+	/* Wrap Incoming Mailboxes Test. */
+	mb[0] = MBC_MAILBOX_REGISTER_TEST;
+	mb[1] = 0xAAAA;
+	mb[2] = 0x5555;
+	mb[3] = 0xAA55;
+	mb[4] = 0x55AA;
+	mb[5] = 0xA5A5;
+	mb[6] = 0x5A5A;
+	mb[7] = 0x2525;
+
+	status = qla1280_mailbox_command(ha, 0xff, mb);
 	if (status)
-		dprintk(2, "qla1280_chip_diag: **** FAILED ****\n");
-	else
-		dprintk(3, "qla1280_chip_diag: exiting normally\n");
+		goto fail;
+
+	if (mb[1] != 0xAAAA || mb[2] != 0x5555 || mb[3] != 0xAA55 ||
+	    mb[4] != 0x55AA || mb[5] != 0xA5A5 || mb[6] != 0x5A5A ||
+	    mb[7] != 0x2525) {
+		printk(KERN_INFO "qla1280: Failed mbox check\n");
+		goto fail;
+	}
 
+	dprintk(3, "qla1280_chip_diag: exiting normally\n");
+	return 0;
+ fail:
+	dprintk(2, "qla1280_chip_diag: **** FAILED ****\n");
 	return status;
 }
 
-/*
- * Setup chip
- *      Load and start RISC firmware.
- *
- * Input:
- *      ha = adapter block pointer.
- *
- * Returns:
- *      0 = success.
- */
-#define DUMP_IT_BACK 0		/* for debug of RISC loading */
 static int
-qla1280_setup_chip(struct scsi_qla_host *ha)
+qla1280_load_firmware_pio(struct scsi_qla_host *ha)
 {
-	int status = 0;
-	uint16_t risc_address;
-	uint16_t *risc_code_address;
-	int risc_code_size;
-	uint16_t mb[MAILBOX_REGISTER_COUNT];
-	uint16_t cnt;
-	int num, i;
-#if DUMP_IT_BACK
-	uint8_t *sp;
-	uint8_t *tbuf;
-	dma_addr_t p_tbuf;
-#endif
+	uint16_t risc_address, *risc_code_address, risc_code_size;
+	uint16_t mb[MAILBOX_REGISTER_COUNT], i;
+	int err;
 
-	ENTER("qla1280_setup_chip");
+	/* Load RISC code. */
+	risc_address = *ql1280_board_tbl[ha->devnum].fwstart;
+	risc_code_address = ql1280_board_tbl[ha->devnum].fwcode;
+	risc_code_size = *ql1280_board_tbl[ha->devnum].fwlen;
+
+	for (i = 0; i < risc_code_size; i++) {
+		mb[0] = MBC_WRITE_RAM_WORD;
+		mb[1] = risc_address + i;
+		mb[2] = risc_code_address[i];
+
+		err = qla1280_mailbox_command(ha, BIT_0 | BIT_1 | BIT_2, mb);
+		if (err) {
+			printk(KERN_ERR "scsi(%li): Failed to load firmware\n",
+					ha->host_no);
+			return err;
+		}
+	}
 
-	dprintk(1, "scsi(%ld): Setup chip\n", ha->host_no);
+	return 0;
+}
 
+#define DUMP_IT_BACK 0		/* for debug of RISC loading */
+static int
+qla1280_load_firmware_dma(struct scsi_qla_host *ha)
+{
+	uint16_t risc_address, *risc_code_address, risc_code_size;
+	uint16_t mb[MAILBOX_REGISTER_COUNT], cnt;
+	int err = 0, num, i;
 #if DUMP_IT_BACK
-	/* get consistent memory allocated for setup_chip */
+	uint8_t *sp, *tbuf;
+	dma_addr_t p_tbuf;
+
 	tbuf = pci_alloc_consistent(ha->pdev, 8000, &p_tbuf);
+	if (!tbuf)
+		return -ENOMEM;
 #endif
 
 	/* Load RISC code. */
 	risc_address = *ql1280_board_tbl[ha->devnum].fwstart;
 	risc_code_address = ql1280_board_tbl[ha->devnum].fwcode;
-	risc_code_size = (int) *ql1280_board_tbl[ha->devnum].fwlen;
+	risc_code_size = *ql1280_board_tbl[ha->devnum].fwlen;
 
-	dprintk(1, "qla1280_setup_chip: DMA RISC code (%i) words\n",
-		risc_code_size);
+	dprintk(1, "%s: DMA RISC code (%i) words\n",
+			__FUNCTION__, risc_code_size);
 
 	num = 0;
-	while (risc_code_size > 0 && !status) {
+	while (risc_code_size > 0) {
 		int warn __attribute__((unused)) = 0;
 
 		cnt = 2000 >> 1;
@@ -2129,15 +2102,16 @@ qla1280_setup_chip(struct scsi_qla_host *ha)
 		mb[2] = (ha->request_dma >> 16) & 0xffff;
 		mb[7] = pci_dma_hi32(ha->request_dma) & 0xffff;
 		mb[6] = pci_dma_hi32(ha->request_dma) >> 16;
-		dprintk(2, "qla1280_setup_chip: op=%d  0x%p = 0x%4x,0x%4x,"
-			"0x%4x,0x%4x\n", mb[0], (void *)(long)ha->request_dma,
-			mb[6], mb[7], mb[2], mb[3]);
-		if ((status = qla1280_mailbox_command(ha, BIT_4 | BIT_3 |
-						      BIT_2 | BIT_1 | BIT_0,
-						      &mb[0]))) {
+		dprintk(2, "%s: op=%d  0x%p = 0x%4x,0x%4x,0x%4x,0x%4x\n",
+				__FUNCTION__, mb[0],
+				(void *)(long)ha->request_dma,
+				mb[6], mb[7], mb[2], mb[3]);
+		err = qla1280_mailbox_command(ha, BIT_4 | BIT_3 | BIT_2 |
+				BIT_1 | BIT_0, mb);
+		if (err) {
 			printk(KERN_ERR "scsi(%li): Failed to load partial "
 			       "segment of f\n", ha->host_no);
-			break;
+			goto out;
 		}
 
 #if DUMP_IT_BACK
@@ -2149,22 +2123,22 @@ qla1280_setup_chip(struct scsi_qla_host *ha)
 		mb[7] = pci_dma_hi32(p_tbuf) & 0xffff;
 		mb[6] = pci_dma_hi32(p_tbuf) >> 16;
 
-		if ((status = qla1280_mailbox_command(ha,
-						      BIT_4 | BIT_3 | BIT_2 |
-						      BIT_1 | BIT_0,
-						      &mb[0]))) {
+		err = qla1280_mailbox_command(ha, BIT_4 | BIT_3 | BIT_2 |
+				BIT_1 | BIT_0, mb);
+		if (err) {
 			printk(KERN_ERR
 			       "Failed to dump partial segment of f/w\n");
-			break;
+			goto out;
 		}
 		sp = (uint8_t *)ha->request_ring;
 		for (i = 0; i < (cnt << 1); i++) {
 			if (tbuf[i] != sp[i] && warn++ < 10) {
-				printk(KERN_ERR "qla1280_setup_chip: FW "
-				       "compare error @ byte(0x%x) loop#=%x\n",
-				       i, num);
-				printk(KERN_ERR "setup_chip: FWbyte=%x  "
-				       "FWfromChip=%x\n", sp[i], tbuf[i]);
+				printk(KERN_ERR "%s: FW compare error @ "
+						"byte(0x%x) loop#=%x\n",
+						__FUNCTION__, i, num);
+				printk(KERN_ERR "%s: FWbyte=%x  "
+						"FWfromChip=%x\n",
+						__FUNCTION__, sp[i], tbuf[i]);
 				/*break; */
 			}
 		}
@@ -2175,37 +2149,69 @@ qla1280_setup_chip(struct scsi_qla_host *ha)
 		num++;
 	}
 
+ out:
+#if DUMP_IT_BACK
+	pci_free_consistent(ha->pdev, 8000, tbuf, p_tbuf);
+#endif
+	return err;
+}
+
+static int
+qla1280_start_firmware(struct scsi_qla_host *ha)
+{
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+	int err;
+
+	dprintk(1, "%s: Verifying checksum of loaded RISC code.\n",
+			__FUNCTION__);
+
 	/* Verify checksum of loaded RISC code. */
-	if (!status) {
-		dprintk(1, "qla1280_setup_chip: Verifying checksum of "
-			"loaded RISC code.\n");
-		mb[0] = MBC_VERIFY_CHECKSUM;
-		/* mb[1] = ql12_risc_code_addr01; */
-		mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
+	mb[0] = MBC_VERIFY_CHECKSUM;
+	/* mb[1] = ql12_risc_code_addr01; */
+	mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
+	err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
+	if (err) {
+		printk(KERN_ERR "scsi(%li): Failed checksum\n", ha->host_no);
+		return err;
+	}
 
-		if (!(status =
-		      qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]))) {
-			/* Start firmware execution. */
-			dprintk(1,
-				"qla1280_setup_chip: start firmware running.\n");
-			mb[0] = MBC_EXECUTE_FIRMWARE;
-			mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
-			qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
-		} else
-			printk(KERN_ERR "scsi(%li): qla1280_setup_chip: "
-			       "Failed checksum\n", ha->host_no);
+	/* Start firmware execution. */
+	dprintk(1, "%s: start firmware running.\n", __FUNCTION__);
+	mb[0] = MBC_EXECUTE_FIRMWARE;
+	mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
+	err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
+	if (err) {
+		printk(KERN_ERR "scsi(%li): Failed to start firmware\n",
+				ha->host_no);
 	}
 
-#if DUMP_IT_BACK
-	/* free consistent memory allocated for setup_chip */
-	pci_free_consistent(ha->pdev, 8000, tbuf, p_tbuf);
-#endif
+	return err;
+}
 
-	if (status)
-		dprintk(2, "qla1280_setup_chip: **** FAILED ****\n");
+static int
+qla1280_load_firmware(struct scsi_qla_host *ha)
+{
+	int err = -ENODEV;
 
-	LEAVE("qla1280_setup_chip");
-	return status;
+	/* If firmware needs to be loaded */
+	if (!qla1280_isp_firmware(ha)) {
+		printk(KERN_ERR "scsi(%li): isp_firmware() failed!\n",
+				ha->host_no);
+		goto out;
+	}
+
+	err = qla1280_chip_diag(ha);
+	if (err)
+		goto out;
+	if (IS_ISP1040(ha))
+		err = qla1280_load_firmware_pio(ha);
+	else
+		err = qla1280_load_firmware_dma(ha);
+	if (err)
+		goto out;
+	err = qla1280_start_firmware(ha);
+ out:
+	return err;
 }
 
 /*
@@ -2271,123 +2277,9 @@ qla1280_init_rings(struct scsi_qla_host *ha)
 	return status;
 }
 
-/*
- * NVRAM configuration.
- *
- * Input:
- *      ha                = adapter block pointer.
- *      ha->request_ring  = request ring virtual address
- *
- * Output:
- *      host adapters parameters in host adapter block
- *
- * Returns:
- *      0 = success.
- */
-static int
-qla1280_nvram_config(struct scsi_qla_host *ha)
+static void
+qla1280_print_settings(struct nvram *nv)
 {
-	struct device_reg *reg = ha->iobase;
-	struct nvram *nv;
-	int is1x160, status = 0;
-	int bus, target, lun;
-	uint16_t mb[MAILBOX_REGISTER_COUNT];
-	uint16_t mask;
-
-	ENTER("qla1280_nvram_config");
-
-	if (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP12160 ||
-	    ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP10160)
-		is1x160 = 1;
-	else
-		is1x160 = 0;
-
-	nv = &ha->nvram;
-	if (!ha->nvram_valid) {
-		dprintk(1, "Using defaults for NVRAM: \n");
-		memset(nv, 0, sizeof(struct nvram));
-
-		/* nv->cntr_flags_1.disable_loading_risc_code = 1; */
-		nv->firmware_feature.f.enable_fast_posting = 1;
-		nv->firmware_feature.f.disable_synchronous_backoff = 1;
-
-		nv->termination.f.scsi_bus_0_control = 3;
-		nv->termination.f.scsi_bus_1_control = 3;
-		nv->termination.f.auto_term_support = 1;
-
-		/*
-		 * Set default FIFO magic - What appropriate values
-		 * would be here is unknown. This is what I have found
-		 * testing with 12160s.
-		 * Now, I would love the magic decoder ring for this one,
-		 * the header file provided by QLogic seems to be bogus
-		 * or incomplete at best.
-		 */
-		nv->isp_config.c = 0x44;
-
-		if (is1x160)
-			nv->isp_parameter = 0x01;
-
-		for (bus = 0; bus < MAX_BUSES; bus++) {
-			nv->bus[bus].config_1.initiator_id = 7;
-			nv->bus[bus].bus_reset_delay = 5;
-			/* 8 = 5.0 clocks */
-			nv->bus[bus].config_2.async_data_setup_time = 8;
-			nv->bus[bus].config_2.req_ack_active_negation = 1;
-			nv->bus[bus].config_2.data_line_active_negation = 1;
-			nv->bus[bus].selection_timeout = 250;
-			nv->bus[bus].max_queue_depth = 256;
-
-			for (target = 0; target < MAX_TARGETS; target++) {
-				nv->bus[bus].target[target].parameter.f.
-					renegotiate_on_error = 1;
-				nv->bus[bus].target[target].parameter.f.
-					auto_request_sense = 1;
-				nv->bus[bus].target[target].parameter.f.
-					tag_queuing = 1;
-				nv->bus[bus].target[target].parameter.f.
-					enable_sync = 1;
-#if 1	/* Some SCSI Processors do not seem to like this */
-				nv->bus[bus].target[target].parameter.f.
-					enable_wide = 1;
-#endif
-				nv->bus[bus].target[target].parameter.f.
-					parity_checking = 1;
-				nv->bus[bus].target[target].parameter.f.
-					disconnect_allowed = 1;
-				nv->bus[bus].target[target].execution_throttle=
-					nv->bus[bus].max_queue_depth - 1;
-				if (is1x160) {
-					nv->bus[bus].target[target].flags.
-						flags1x160.device_enable = 1;
-					nv->bus[bus].target[target].flags.
-						flags1x160.sync_offset = 0x0e;
-					nv->bus[bus].target[target].
-						sync_period = 9;
-					nv->bus[bus].target[target].
-						ppr_1x160.flags.enable_ppr = 1;
-					nv->bus[bus].target[target].ppr_1x160.
-						flags.ppr_options = 2;
-					nv->bus[bus].target[target].ppr_1x160.
-						flags.ppr_bus_width = 1;
-				} else {
-					nv->bus[bus].target[target].flags.
-						flags1x80.device_enable = 1;
-					nv->bus[bus].target[target].flags.
-						flags1x80.sync_offset = 0x8;
-					nv->bus[bus].target[target].
-						sync_period = 10;
-				}
-			}
-		}
-	} else {
-		/* Always force AUTO sense for LINUX SCSI */
-		for (bus = 0; bus < MAX_BUSES; bus++)
-			for (target = 0; target < MAX_TARGETS; target++) {
-				nv->bus[bus].target[target].parameter.f.
-					auto_request_sense = 1;
-			}
-	}
 	dprintk(1, "qla1280 : initiator scsi id bus[0]=%d\n",
 		nv->bus[0].config_1.initiator_id);
 	dprintk(1, "qla1280 : initiator scsi id bus[1]=%d\n",
@@ -2433,36 +2325,264 @@ qla1280_nvram_config(struct scsi_qla_host *ha)
 		nv->bus[0].max_queue_depth);
 	dprintk(1, "qla1280 : max queue depth[1]=%d\n",
 		nv->bus[1].max_queue_depth);
+}
+
+static void
+qla1280_set_target_defaults(struct scsi_qla_host *ha, int bus, int target)
+{
+	struct nvram *nv = &ha->nvram;
+
+	nv->bus[bus].target[target].parameter.f.renegotiate_on_error = 1;
+	nv->bus[bus].target[target].parameter.f.auto_request_sense = 1;
+	nv->bus[bus].target[target].parameter.f.tag_queuing = 1;
+	nv->bus[bus].target[target].parameter.f.enable_sync = 1;
+#if 1	/* Some SCSI Processors do not seem to like this */
+	nv->bus[bus].target[target].parameter.f.enable_wide = 1;
+#endif
+	if (!IS_ISP1040(ha))
+		nv->bus[bus].target[target].parameter.f.parity_checking = 1;
+
+	nv->bus[bus].target[target].parameter.f.disconnect_allowed = 1;
+	nv->bus[bus].target[target].execution_throttle =
+		nv->bus[bus].max_queue_depth - 1;
+
+	if (IS_ISP1x160(ha)) {
+		nv->bus[bus].target[target].flags.flags1x160.device_enable = 1;
+		nv->bus[bus].target[target].flags.flags1x160.sync_offset = 0x0e;
+		nv->bus[bus].target[target].sync_period = 9;
+		nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 1;
+		nv->bus[bus].target[target].ppr_1x160.flags.ppr_options = 2;
+		nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width = 1;
+	} else {
+		nv->bus[bus].target[target].flags.flags1x80.device_enable = 1;
+		nv->bus[bus].target[target].flags.flags1x80.sync_offset = 12;
+		nv->bus[bus].target[target].sync_period = 10;
+	}
+}
+
+static void
+qla1280_set_defaults(struct scsi_qla_host *ha)
+{
+	struct nvram *nv = &ha->nvram;
+	int bus, target;
+
+	dprintk(1, "Using defaults for NVRAM: \n");
+	memset(nv, 0, sizeof(struct nvram));
+
+	/* nv->cntr_flags_1.disable_loading_risc_code = 1; */
+	nv->firmware_feature.f.enable_fast_posting = 1;
+	nv->firmware_feature.f.disable_synchronous_backoff = 1;
+	nv->termination.f.scsi_bus_0_control = 3;
+	nv->termination.f.scsi_bus_1_control = 3;
+	nv->termination.f.auto_term_support = 1;
+
+	/*
+	 * Set default FIFO magic - What appropriate values would be here
+	 * is unknown. This is what I have found testing with 12160s.
+	 *
+	 * Now, I would love the magic decoder ring for this one, the
+	 * header file provided by QLogic seems to be bogus or incomplete
+	 * at best.
+	 */
+	nv->isp_config.c = ISP_CFG1_BENAB|ISP_CFG1_F128;
+	if (IS_ISP1x160(ha))
+		nv->isp_parameter = 0x01; /* fast memory enable */
+
+	for (bus = 0; bus < MAX_BUSES; bus++) {
+		nv->bus[bus].config_1.initiator_id = 7;
+		nv->bus[bus].config_2.req_ack_active_negation = 1;
+		nv->bus[bus].config_2.data_line_active_negation = 1;
+		nv->bus[bus].selection_timeout = 250;
+		nv->bus[bus].max_queue_depth = 256;
+
+		if (IS_ISP1040(ha)) {
+			nv->bus[bus].bus_reset_delay = 3;
+			nv->bus[bus].config_2.async_data_setup_time = 6;
+			nv->bus[bus].retry_delay = 1;
+		} else {
+			nv->bus[bus].bus_reset_delay = 5;
+			nv->bus[bus].config_2.async_data_setup_time = 8;
+		}
+
+		for (target = 0; target < MAX_TARGETS; target++)
+			qla1280_set_target_defaults(ha, bus, target);
+	}
+}
+
+static int
+qla1280_config_target(struct scsi_qla_host *ha, int bus, int target)
+{
+	struct nvram *nv = &ha->nvram;
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+	int status, lun;
+
+	/* Set Target Parameters. */
+	mb[0] = MBC_SET_TARGET_PARAMETERS;
+	mb[1] = (uint16_t) (bus ? target | BIT_7 : target);
+	mb[1] <<= 8;
+
+	/*
+	 * Do not enable wide, sync, and ppr for the initial
+	 * INQUIRY run. We enable this later if we determine
+	 * the target actually supports it.
+	 */
+	nv->bus[bus].target[target].parameter.f.
+		auto_request_sense = 1;
+	nv->bus[bus].target[target].parameter.f.
+		stop_queue_on_check = 0;
+
+	if (IS_ISP1x160(ha))
+		nv->bus[bus].target[target].ppr_1x160.
+			flags.enable_ppr = 0;
+
+	/*
+	 * No sync, wide, etc. while probing
+	 */
+	mb[2] = (nv->bus[bus].target[target].parameter.c << 8) &
+		~(TP_SYNC /*| TP_WIDE | TP_PPR*/);
+
+	if (IS_ISP1x160(ha))
+		mb[3] =	nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8;
+	else
+		mb[3] =	nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8;
+	mb[3] |= nv->bus[bus].target[target].sync_period;
+
+	status = qla1280_mailbox_command(ha, BIT_3 | BIT_2 | BIT_1 | BIT_0, &mb[0]);
+
+	/* Save Tag queuing enable flag. */
+	mb[0] = BIT_0 << target;
+	if (nv->bus[bus].target[target].parameter.f.tag_queuing)
+		ha->bus_settings[bus].qtag_enables |= mb[0];
+
+	/* Save Device enable flag. */
+	if (IS_ISP1x160(ha)) {
+		if (nv->bus[bus].target[target].flags.flags1x160.device_enable)
+			ha->bus_settings[bus].device_enables |= mb[0];
+		ha->bus_settings[bus].lun_disables |= 0;
+	} else {
+		if (nv->bus[bus].target[target].flags.flags1x80.device_enable)
+			ha->bus_settings[bus].device_enables |= mb[0];
+		/* Save LUN disable flag. */
+		if (nv->bus[bus].target[target].flags.flags1x80.lun_disable)
+			ha->bus_settings[bus].lun_disables |= mb[0];
+	}
+
+	/* Set Device Queue Parameters. */
+	for (lun = 0; lun < MAX_LUNS; lun++) {
+		mb[0] = MBC_SET_DEVICE_QUEUE;
+		mb[1] = (uint16_t)(bus ? target | BIT_7 : target);
+		mb[1] = mb[1] << 8 | lun;
+		mb[2] = nv->bus[bus].max_queue_depth;
+		mb[3] = nv->bus[bus].target[target].execution_throttle;
+		status |= qla1280_mailbox_command(ha, 0x0f, &mb[0]);
+	}
+
+	return status;
+}
+
+static int
+qla1280_config_bus(struct scsi_qla_host *ha, int bus)
+{
+	struct nvram *nv = &ha->nvram;
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+	int target, status;
+
+	/* SCSI Reset Disable. */
+	ha->bus_settings[bus].disable_scsi_reset =
+		nv->bus[bus].config_1.scsi_reset_disable;
+
+	/* Initiator ID. */
+	ha->bus_settings[bus].id = nv->bus[bus].config_1.initiator_id;
+	mb[0] = MBC_SET_INITIATOR_ID;
+	mb[1] = bus ? ha->bus_settings[bus].id | BIT_7 :
+		ha->bus_settings[bus].id;
+	status = qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
+
+	/* Reset Delay. */
+	ha->bus_settings[bus].bus_reset_delay =
+		nv->bus[bus].bus_reset_delay;
+
+	/* Command queue depth per device. */
+	ha->bus_settings[bus].hiwat = nv->bus[bus].max_queue_depth - 1;
+
+	/* Set target parameters. */
+	for (target = 0; target < MAX_TARGETS; target++)
+		status |= qla1280_config_target(ha, bus, target);
+
+	return status;
+}
+
+static int
+qla1280_nvram_config(struct scsi_qla_host *ha)
+{
+	struct device_reg *reg = ha->iobase;
+	struct nvram *nv = &ha->nvram;
+	int bus, target, status = 0;
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+	uint16_t mask;
+
+	ENTER("qla1280_nvram_config");
+
+	if (ha->nvram_valid) {
+		/* Always force AUTO sense for LINUX SCSI */
+		for (bus = 0; bus < MAX_BUSES; bus++)
+			for (target = 0; target < MAX_TARGETS; target++) {
+				nv->bus[bus].target[target].parameter.f.
+					auto_request_sense = 1;
+			}
+	} else {
+		qla1280_set_defaults(ha);
+	}
+
+	qla1280_print_settings(nv);
 
 	/* Disable RISC load of firmware. */
 	ha->flags.disable_risc_code_load =
 		nv->cntr_flags_1.disable_loading_risc_code;
 
-	/* Set ISP hardware DMA burst */
-	mb[0] = nv->isp_config.c;
-	/* Enable DMA arbitration on dual channel controllers */
-	if (ha->ports > 1)
-		mb[0] |= BIT_13;
-	WRT_REG_WORD(&reg->cfg_1, mb[0]);
-
-#if 1	/* Is this safe? */
-	/* Set SCSI termination. */
-	WRT_REG_WORD(&reg->gpio_enable, (BIT_3 + BIT_2 + BIT_1 + BIT_0));
-	mb[0] = nv->termination.c & (BIT_3 + BIT_2 + BIT_1 + BIT_0);
-	WRT_REG_WORD(&reg->gpio_data, mb[0]);
-#endif
+	if (IS_ISP1040(ha)) {
+		uint16_t hwrev, cfg1, cdma_conf, ddma_conf;
+
+		hwrev = RD_REG_WORD(&reg->cfg_0) & ISP_CFG0_HWMSK;
+
+		cfg1 = RD_REG_WORD(&reg->cfg_1);
+		cdma_conf = RD_REG_WORD(&reg->cdma_cfg);
+		ddma_conf = RD_REG_WORD(&reg->ddma_cfg);
+
+		/* Busted fifo, says mjacob. */
+		if (hwrev == ISP_CFG0_1040A)
+			WRT_REG_WORD(&reg->cfg_1, cfg1 | ISP_CFG1_F64);
+		else
+			WRT_REG_WORD(&reg->cfg_1, cfg1 | ISP_CFG1_F64 | ISP_CFG1_BENAB);
+
+		WRT_REG_WORD(&reg->cdma_cfg, cdma_conf | CDMA_CONF_BENAB);
+		WRT_REG_WORD(&reg->ddma_cfg, cdma_conf | DDMA_CONF_BENAB);
+	} else {
+		/* Set ISP hardware DMA burst */
+		mb[0] = nv->isp_config.c;
+		/* Enable DMA arbitration on dual channel controllers */
+		if (ha->ports > 1)
+			mb[0] |= BIT_13;
+		WRT_REG_WORD(&reg->cfg_1, mb[0]);
+
+		/* Set SCSI termination. */
+		WRT_REG_WORD(&reg->gpio_enable, (BIT_3 + BIT_2 + BIT_1 + BIT_0));
+		mb[0] = nv->termination.c & (BIT_3 + BIT_2 + BIT_1 + BIT_0);
+		WRT_REG_WORD(&reg->gpio_data, mb[0]);
+	}
 
 	/* ISP parameter word. */
 	mb[0] = MBC_SET_SYSTEM_PARAMETER;
 	mb[1] = nv->isp_parameter;
 	status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
 
-#if 0
-	/* clock rate - for qla1240 and older, only */
-	mb[0] = MBC_SET_CLOCK_RATE;
-	mb[1] = 0x50;
- 	status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
-#endif
+	if (IS_ISP1x40(ha)) {
+		/* clock rate - for qla1240 and older, only */
+		mb[0] = MBC_SET_CLOCK_RATE;
+		mb[1] = 40;
+	 	status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
+	}
+
 	/* Firmware feature word. */
 	mb[0] = MBC_SET_FIRMWARE_FEATURES;
 	mask = BIT_5 | BIT_1 | BIT_0;
@@ -2515,112 +2635,18 @@ qla1280_nvram_config(struct scsi_qla_host *ha)
 	mb[2] = 2;	/* Command DMA Channel Burst Enable */
 	status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
 
+	mb[0] = MBC_SET_TAG_AGE_LIMIT;
+	mb[1] = 8;
+	status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
+
 	/* Selection timeout. */
 	mb[0] = MBC_SET_SELECTION_TIMEOUT;
 	mb[1] = nv->bus[0].selection_timeout;
 	mb[2] = nv->bus[1].selection_timeout;
 	status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
 
-	for (bus = 0; bus < ha->ports; bus++) {
-		/* SCSI Reset Disable. */
-		ha->bus_settings[bus].disable_scsi_reset =
-			nv->bus[bus].config_1.scsi_reset_disable;
-
-		/* Initiator ID. */
-		ha->bus_settings[bus].id = nv->bus[bus].config_1.initiator_id;
-		mb[0] = MBC_SET_INITIATOR_ID;
-		mb[1] = bus ? ha->bus_settings[bus].id | BIT_7 :
-			ha->bus_settings[bus].id;
-		status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
-
-		/* Reset Delay. */
-		ha->bus_settings[bus].bus_reset_delay =
-			nv->bus[bus].bus_reset_delay;
-
-		/* Command queue depth per device. */
-		ha->bus_settings[bus].hiwat = nv->bus[bus].max_queue_depth - 1;
-
-		/* Set target parameters. */
-		for (target = 0; target < MAX_TARGETS; target++) {
-			uint8_t mr = BIT_2 | BIT_1 | BIT_0;
-
-			/* Set Target Parameters. */
-			mb[0] = MBC_SET_TARGET_PARAMETERS;
-			mb[1] = (uint16_t) (bus ? target | BIT_7 : target);
-			mb[1] <<= 8;
-			/*
-			 * Do not enable wide, sync, and ppr for the initial
-			 * INQUIRY run. We enable this later if we determine
-			 * the target actually supports it.
-			 */
-			nv->bus[bus].target[target].parameter.f.
-				auto_request_sense = 1;
-			nv->bus[bus].target[target].parameter.f.
-				stop_queue_on_check = 0;
-
-			if (is1x160)
-				nv->bus[bus].target[target].ppr_1x160.
-					flags.enable_ppr = 0;
-			/*
-			 * No sync, wide, etc. while probing
-			 */
-			mb[2] = (nv->bus[bus].target[target].parameter.c << 8)&
-				~(TP_SYNC /*| TP_WIDE | TP_PPR*/);
-
-			if (is1x160)
-				mb[3] =	nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8;
-			else
-				mb[3] =	nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8;
-			mb[3] |= nv->bus[bus].target[target].sync_period;
-			mr |= BIT_3;
-
-			/*
-			 * We don't want to enable ppr etc. before we have 
-			 * determined that the target actually supports it
-			 */
-#if 0
-			if (is1x160) {
-				mb[2] |= nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr << 5;
-
-				mb[6] =	nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8;
-				mb[6] |= nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width;
-				mr |= BIT_6;
-			}
-#endif
-
-			status = qla1280_mailbox_command(ha, mr, &mb[0]);
-
-			/* Save Tag queuing enable flag. */
-			mb[0] = BIT_0 << target;
-			if (nv->bus[bus].target[target].parameter.f.tag_queuing)
-				ha->bus_settings[bus].qtag_enables |= mb[0];
-
-			/* Save Device enable flag. */
-			if (is1x160) {
-				if (nv->bus[bus].target[target].flags.flags1x160.device_enable)
-					ha->bus_settings[bus].device_enables |= mb[0];
-				ha->bus_settings[bus].lun_disables |= 0;
-			} else {
-				if (nv->bus[bus].target[target].flags.flags1x80.device_enable)
-					ha->bus_settings[bus].device_enables |= mb[0];
-				/* Save LUN disable flag. */
-				if (nv->bus[bus].target[target].flags.flags1x80.lun_disable)
-				ha->bus_settings[bus].lun_disables |= mb[0];
-			}
-
-
-			/* Set Device Queue Parameters. */
-			for (lun = 0; lun < MAX_LUNS; lun++) {
-				mb[0] = MBC_SET_DEVICE_QUEUE;
-				mb[1] = (uint16_t)(bus ? target | BIT_7 : target);
-				mb[1] = mb[1] << 8 | lun;
-				mb[2] = nv->bus[bus].max_queue_depth;
-				mb[3] = nv->bus[bus].target[target].execution_throttle;
-				status |= qla1280_mailbox_command(ha, 0x0f,
-								  &mb[0]);
-			}
-		}
-	}
+	for (bus = 0; bus < ha->ports; bus++)
+		status |= qla1280_config_bus(ha, bus);
 
 	if (status)
 		dprintk(2, "qla1280_nvram_config: **** FAILED ****\n");
@@ -4231,6 +4257,7 @@ qla1280_error_entry(struct scsi_qla_host *ha, struct response *pkt,
 static int
 qla1280_abort_isp(struct scsi_qla_host *ha)
 {
+	struct device_reg *reg = ha->iobase;
 	struct srb *sp;
 	int status = 0;
 	int cnt;
@@ -4238,69 +4265,53 @@ qla1280_abort_isp(struct scsi_qla_host *ha)
 
 	ENTER("qla1280_abort_isp");
 
-	if (!ha->flags.abort_isp_active && ha->flags.online) {
-		struct device_reg *reg = ha->iobase;
-		ha->flags.abort_isp_active = 1;
-
-		/* Disable ISP interrupts. */
-		qla1280_disable_intrs(ha);
-		WRT_REG_WORD(&reg->host_cmd, HC_PAUSE_RISC);
-		RD_REG_WORD(&reg->id_l);
+	if (ha->flags.abort_isp_active || !ha->flags.online)
+		goto out;
+	
+	ha->flags.abort_isp_active = 1;
 
-		printk(KERN_INFO "scsi(%li): dequeuing outstanding commands\n",
-		       ha->host_no);
-		/* Dequeue all commands in outstanding command list. */
-		for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
-			struct scsi_cmnd *cmd;
-			sp = ha->outstanding_cmds[cnt];
-			if (sp) {
+	/* Disable ISP interrupts. */
+	qla1280_disable_intrs(ha);
+	WRT_REG_WORD(&reg->host_cmd, HC_PAUSE_RISC);
+	RD_REG_WORD(&reg->id_l);
 
-				cmd = sp->cmd;
-				CMD_RESULT(cmd) = DID_RESET << 16;
+	printk(KERN_INFO "scsi(%li): dequeuing outstanding commands\n",
+	       ha->host_no);
+	/* Dequeue all commands in outstanding command list. */
+	for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
+		struct scsi_cmnd *cmd;
+		sp = ha->outstanding_cmds[cnt];
+		if (sp) {
 
-				sp->cmd = NULL;
-				ha->outstanding_cmds[cnt] = NULL;
+			cmd = sp->cmd;
+			CMD_RESULT(cmd) = DID_RESET << 16;
 
-				(*cmd->scsi_done)(cmd);
+			sp->cmd = NULL;
+			ha->outstanding_cmds[cnt] = NULL;
 
-				sp->flags = 0;
-			}
-		}
+			(*cmd->scsi_done)(cmd);
 
-		/* If firmware needs to be loaded */
-		if (qla1280_isp_firmware (ha)) {
-			if (!(status = qla1280_chip_diag(ha)))
-				status = qla1280_setup_chip(ha);
+			sp->flags = 0;
 		}
+	}
 
-		if (!status) {
-			/* Setup adapter based on NVRAM parameters. */
-			qla1280_nvram_config (ha);
+	status = qla1280_load_firmware(ha);
+	if (status)
+		goto out;
 
-			if (!(status = qla1280_init_rings(ha))) {
-				/* Issue SCSI reset. */
-				for (bus = 0; bus < ha->ports; bus++) {
-					qla1280_bus_reset(ha, bus);
-				}
-				/*
-				 * qla1280_bus_reset() will do the marker
-				 * dance - no reason to repeat here!
-				 */
-#if  0
-				/* Issue marker command. */
-				ha->flags.reset_marker = 0;
-				for (bus = 0; bus < ha->ports; bus++) {
-					ha->bus_settings[bus].
-						reset_marker = 0;
-					qla1280_marker(ha, bus, 0, 0,
-						       MK_SYNC_ALL);
-				}
-#endif
-				ha->flags.abort_isp_active = 0;
-			}
-		}
-	}
+	/* Setup adapter based on NVRAM parameters. */
+	qla1280_nvram_config (ha);
 
+	status = qla1280_init_rings(ha);
+	if (status)
+		goto out;
+		
+	/* Issue SCSI reset. */
+	for (bus = 0; bus < ha->ports; bus++)
+		qla1280_bus_reset(ha, bus);
+		
+	ha->flags.abort_isp_active = 0;
+ out:
 	if (status) {
 		printk(KERN_WARNING
 		       "qla1280: ISP error recovery failed, board disabled");
@@ -4936,6 +4947,7 @@ module_exit(qla1280_exit);
 MODULE_AUTHOR("Qlogic & Jes Sorensen");
 MODULE_DESCRIPTION("Qlogic ISP SCSI (qla1x80/qla1x160) driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA1280_VERSION);
 
 /*
  * Overrides for Emacs so that we almost follow Linus's tabbing style.
diff --git a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h
index 0027485bf..5dc7ca3da 100644
--- a/drivers/scsi/qla1280.h
+++ b/drivers/scsi/qla1280.h
@@ -62,6 +62,7 @@
 #define WRT_REG_WORD(addr, data)	writew(data, addr)
 #else				/* MEMORY_MAPPED_IO */
 #define RD_REG_WORD(addr)		inw((unsigned long)addr)
+#define RD_REG_WORD_dmasync(addr)	RD_REG_WORD(addr)
 #define WRT_REG_WORD(addr, data)	outw(data, (unsigned long)addr)
 #endif				/* MEMORY_MAPPED_IO */
 
@@ -126,7 +127,20 @@ struct device_reg {
 	uint16_t id_l;		/* ID low */
 	uint16_t id_h;		/* ID high */
 	uint16_t cfg_0;		/* Configuration 0 */
+#define ISP_CFG0_HWMSK   0x000f	/* Hardware revision mask */
+#define ISP_CFG0_1020    BIT_0	/* ISP1020 */
+#define ISP_CFG0_1020A	 BIT_1	/* ISP1020A */
+#define ISP_CFG0_1040	 BIT_2	/* ISP1040 */
+#define ISP_CFG0_1040A	 BIT_3	/* ISP1040A */
+#define ISP_CFG0_1040B	 BIT_4	/* ISP1040B */
+#define ISP_CFG0_1040C	 BIT_5	/* ISP1040C */
 	uint16_t cfg_1;		/* Configuration 1 */
+#define ISP_CFG1_F128    BIT_6  /* 128-byte FIFO threshold */
+#define ISP_CFG1_F64     BIT_4|BIT_5 /* 128-byte FIFO threshold */
+#define ISP_CFG1_F32     BIT_5  /* 128-byte FIFO threshold */
+#define ISP_CFG1_F16     BIT_4  /* 128-byte FIFO threshold */
+#define ISP_CFG1_BENAB   BIT_2  /* Global Bus burst enable */
+#define ISP_CFG1_SXP     BIT_0  /* SXP register select */
 	uint16_t ictrl;		/* Interface control */
 #define ISP_RESET        BIT_0	/* ISP soft reset */
 #define ISP_EN_INT       BIT_1	/* ISP enable interrupts. */
@@ -147,7 +161,42 @@ struct device_reg {
 	uint16_t flash_data;	/* Flash BIOS data */
 	uint16_t flash_address;	/* Flash BIOS address */
 
-	uint16_t unused_1[0x2e];	/* 0x14-0x6f Gap */
+	uint16_t unused_1[0x06];
+	
+	/* cdma_* and ddma_* are 1040 only */
+	uint16_t cdma_cfg;
+#define CDMA_CONF_SENAB  BIT_3	/* SXP to DMA Data enable */
+#define CDMA_CONF_RIRQ   BIT_2	/* RISC interrupt enable */
+#define CDMA_CONF_BENAB  BIT_1	/* Bus burst enable */
+#define CDMA_CONF_DIR    BIT_0	/* DMA direction (0=fifo->host 1=host->fifo) */
+	uint16_t cdma_ctrl; 
+	uint16_t cdma_status;   
+	uint16_t cdma_fifo_status;
+	uint16_t cdma_count;
+	uint16_t cdma_reserved;
+	uint16_t cdma_address_count_0;
+	uint16_t cdma_address_count_1;
+	uint16_t cdma_address_count_2;
+	uint16_t cdma_address_count_3;
+
+	uint16_t unused_2[0x06];
+
+	uint16_t ddma_cfg;
+#define DDMA_CONF_SENAB  BIT_3	/* SXP to DMA Data enable */
+#define DDMA_CONF_RIRQ   BIT_2	/* RISC interrupt enable */
+#define DDMA_CONF_BENAB  BIT_1	/* Bus burst enable */
+#define DDMA_CONF_DIR    BIT_0	/* DMA direction (0=fifo->host 1=host->fifo) */
+	uint16_t ddma_ctrl;
+	uint16_t ddma_status; 
+	uint16_t ddma_fifo_status;
+	uint16_t ddma_xfer_count_low;
+	uint16_t ddma_xfer_count_high;
+	uint16_t ddma_addr_count_0;
+	uint16_t ddma_addr_count_1;
+	uint16_t ddma_addr_count_2;
+	uint16_t ddma_addr_count_3; 
+
+	uint16_t unused_3[0x0e];
 
 	uint16_t mailbox0;	/* Mailbox 0 */
 	uint16_t mailbox1;	/* Mailbox 1 */
@@ -158,18 +207,18 @@ struct device_reg {
 	uint16_t mailbox6;	/* Mailbox 6 */
 	uint16_t mailbox7;	/* Mailbox 7 */
 
-	uint16_t unused_2[0x20];/* 0x80-0xbf Gap */
+	uint16_t unused_4[0x20];/* 0x80-0xbf Gap */
 
 	uint16_t host_cmd;	/* Host command and control */
 #define HOST_INT      BIT_7	/* host interrupt bit */
 #define BIOS_ENABLE   BIT_0
 
-	uint16_t unused_6[0x5];	/* 0xc2-0xcb Gap */
+	uint16_t unused_5[0x5];	/* 0xc2-0xcb Gap */
 
 	uint16_t gpio_data;
 	uint16_t gpio_enable;
 
-	uint16_t unused_7[0x11];	/* d0-f0 */
+	uint16_t unused_6[0x11];	/* d0-f0 */
 	uint16_t scsiControlPins;	/* f2 */
 };
 
diff --git a/drivers/scsi/qla2xxx/ql2100.c b/drivers/scsi/qla2xxx/ql2100.c
index 77de0f4f9..ea136a61a 100644
--- a/drivers/scsi/qla2xxx/ql2100.c
+++ b/drivers/scsi/qla2xxx/ql2100.c
@@ -89,3 +89,4 @@ module_exit(qla2100_exit);
 MODULE_AUTHOR("QLogic Corporation");
 MODULE_DESCRIPTION("QLogic ISP21xx FC-SCSI Host Bus Adapter driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff --git a/drivers/scsi/qla2xxx/ql2200.c b/drivers/scsi/qla2xxx/ql2200.c
index c254daaa0..2f5698d52 100644
--- a/drivers/scsi/qla2xxx/ql2200.c
+++ b/drivers/scsi/qla2xxx/ql2200.c
@@ -89,3 +89,4 @@ module_exit(qla2200_exit);
 MODULE_AUTHOR("QLogic Corporation");
 MODULE_DESCRIPTION("QLogic ISP22xx FC-SCSI Host Bus Adapter driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff --git a/drivers/scsi/qla2xxx/ql2300.c b/drivers/scsi/qla2xxx/ql2300.c
index 177aa3617..1f6fc895c 100644
--- a/drivers/scsi/qla2xxx/ql2300.c
+++ b/drivers/scsi/qla2xxx/ql2300.c
@@ -100,3 +100,4 @@ module_exit(qla2300_exit);
 MODULE_AUTHOR("QLogic Corporation");
 MODULE_DESCRIPTION("QLogic ISP2300 FC-SCSI Host Bus Adapter driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff --git a/drivers/scsi/qla2xxx/ql2322.c b/drivers/scsi/qla2xxx/ql2322.c
index ebbb51ea6..70b6d75ed 100644
--- a/drivers/scsi/qla2xxx/ql2322.c
+++ b/drivers/scsi/qla2xxx/ql2322.c
@@ -105,3 +105,4 @@ module_exit(qla2322_exit);
 MODULE_AUTHOR("QLogic Corporation");
 MODULE_DESCRIPTION("QLogic ISP2322 FC-SCSI Host Bus Adapter driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff --git a/drivers/scsi/qla2xxx/ql6312.c b/drivers/scsi/qla2xxx/ql6312.c
index 6c0720da8..c6b08a6e2 100644
--- a/drivers/scsi/qla2xxx/ql6312.c
+++ b/drivers/scsi/qla2xxx/ql6312.c
@@ -87,3 +87,4 @@ module_exit(qla6312_exit);
 MODULE_AUTHOR("QLogic Corporation");
 MODULE_DESCRIPTION("QLogic ISP6312 FC-SCSI Host Bus Adapter driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff --git a/drivers/scsi/qla2xxx/ql6322.c b/drivers/scsi/qla2xxx/ql6322.c
index ce651454d..75fb9b266 100644
--- a/drivers/scsi/qla2xxx/ql6322.c
+++ b/drivers/scsi/qla2xxx/ql6322.c
@@ -105,3 +105,4 @@ module_exit(qla6322_exit);
 MODULE_AUTHOR("QLogic Corporation");
 MODULE_DESCRIPTION("QLogic ISP6322 FC-SCSI Host Bus Adapter driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index e31b5fe3e..23a854528 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -783,7 +783,6 @@ qla2x00_init_response_q_entries(scsi_qla_host_t *ha)
 static void
 qla2x00_update_fw_options(scsi_qla_host_t *ha)
 {
-	/* Setup seriallink options */
 	uint16_t swing, emphasis;
 
 	memset(ha->fw_options, 0, sizeof(ha->fw_options));
@@ -807,7 +806,6 @@ qla2x00_update_fw_options(scsi_qla_host_t *ha)
 	emphasis = ha->fw_seriallink_options[0] & (BIT_4 | BIT_3);
 	emphasis >>= 3;
 	ha->fw_options[10] = (emphasis << 14) | (swing << 8) | 0x3;
-
 	/*  2G settings */
 	swing = ha->fw_seriallink_options[0] & (BIT_7 | BIT_6 | BIT_5);
 	swing >>= 5;
@@ -818,7 +816,7 @@ qla2x00_update_fw_options(scsi_qla_host_t *ha)
 	/*  Return command IOCBs without waiting for an ABTS to complete. */
 	ha->fw_options[3] |= BIT_13;
 
-	/* Update Serial Link options. */
+	/* Update firmware options. */
 	qla2x00_set_fw_options(ha, ha->fw_options);
 }
 
@@ -843,7 +841,7 @@ qla2x00_init_rings(scsi_qla_host_t *ha)
 
 	/* Clear outstanding commands array. */
 	for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)
-		ha->outstanding_cmds[cnt] = 0;
+		ha->outstanding_cmds[cnt] = NULL;
 
 	ha->current_outstanding_cmd = 0;
 
@@ -869,15 +867,15 @@ qla2x00_init_rings(scsi_qla_host_t *ha)
 
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
+	/* Update any ISP specific firmware options before initialization. */
+	qla2x00_update_fw_options(ha);
+
 	DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no));
 	rval = qla2x00_init_firmware(ha, sizeof(init_cb_t));
 	if (rval) {
 		DEBUG2_3(printk("scsi(%ld): Init firmware **** FAILED ****.\n",
 		    ha->host_no));
 	} else {
-		/* Update any ISP specific firmware options. */
-		qla2x00_update_fw_options(ha);
-
 		DEBUG3(printk("scsi(%ld): Init firmware -- success.\n",
 		    ha->host_no));
 	}
@@ -4133,7 +4131,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
 		for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
 			sp = ha->outstanding_cmds[cnt];
 			if (sp) {
-				ha->outstanding_cmds[cnt] = 0;
+				ha->outstanding_cmds[cnt] = NULL;
 				if (ha->actthreads)
 					ha->actthreads--;
 				sp->lun_queue->out_cnt--;
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 710a88d67..ebbae6059 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -22,6 +22,8 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 
+#include <scsi/scsi_tcq.h>
+
 static inline uint16_t qla2x00_get_cmd_direction(struct scsi_cmnd *cmd);
 static inline cont_entry_t *qla2x00_prep_cont_type0_iocb(scsi_qla_host_t *);
 static inline cont_a64_entry_t *qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *);
@@ -337,6 +339,7 @@ qla2x00_start_scsi(srb_t *sp)
 	uint16_t	req_cnt;
 	uint16_t	tot_dsds;
 	device_reg_t	*reg;
+	char		tag[2];
 
 	/* Setup device pointers. */
 	ret = 0;
@@ -415,14 +418,17 @@ qla2x00_start_scsi(srb_t *sp)
 	cmd_pkt->lun = cpu_to_le16(fclun->lun);
 
 	/* Update tagged queuing modifier */
-	cmd_pkt->control_flags = __constant_cpu_to_le16(CF_SIMPLE_TAG);
-	if (cmd->device->tagged_supported) {
-		switch (cmd->tag) {
-		case HEAD_OF_QUEUE_TAG:
+	if (scsi_populate_tag_msg(cmd, tag)) {
+		switch (tag[0]) {
+		case MSG_SIMPLE_TAG:
+			cmd_pkt->control_flags =
+			    __constant_cpu_to_le16(CF_SIMPLE_TAG);
+			break;
+		case MSG_HEAD_TAG:
 			cmd_pkt->control_flags =
 			    __constant_cpu_to_le16(CF_HEAD_TAG);
 			break;
-		case ORDERED_QUEUE_TAG:
+		case MSG_ORDERED_TAG:
 			cmd_pkt->control_flags =
 			    __constant_cpu_to_le16(CF_ORDERED_TAG);
 			break;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index dd5aaba4e..591f1d5a5 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1663,7 +1663,7 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
 		goto out;
 
 	/* Waiting for our command in done_queue to be returned to OS.*/
-	if (qla2x00_eh_wait_for_pending_commands(ha))
+	if (!qla2x00_eh_wait_for_pending_commands(ha))
 		rval = FAILED;
 
  out:
@@ -1784,7 +1784,7 @@ qla2xxx_slave_configure(struct scsi_device *sdev)
 
 		ql2xmaxqdepth = queue_depth;
 
-		scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
+		scsi_activate_tcq(sdev, queue_depth);
 
 		qla_printk(KERN_INFO, ha,
 		    "scsi(%d:%d:%d:%d): Enabled tagged queuing, queue "
@@ -3590,7 +3590,7 @@ qla2x00_get_new_sp(scsi_qla_host_t *ha)
 {
 	srb_t *sp;
 
-	sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL);
+	sp = mempool_alloc(ha->srb_mempool, GFP_ATOMIC);
 	if (sp)
 		atomic_set(&sp->ref_count, 1);
 	return (sp);
@@ -4517,3 +4517,4 @@ module_exit(qla2x00_module_exit);
 MODULE_AUTHOR("QLogic Corporation");
 MODULE_DESCRIPTION("QLogic Fibre Channel HBA Driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 1dc4c9594..9ee334ec7 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -19,9 +19,9 @@
 /*
  * Driver version 
  */
-#define QLA2XXX_VERSION      "8.00.00b14-k"
+#define QLA2XXX_VERSION      "8.00.00b15-k"
 
 #define QLA_DRIVER_MAJOR_VER	8
 #define QLA_DRIVER_MINOR_VER	0
 #define QLA_DRIVER_PATCH_VER	0
-#define QLA_DRIVER_BETA_VER	14
+#define QLA_DRIVER_BETA_VER	15
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index c49ca7f2f..91aaf50c7 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -987,7 +987,7 @@ const char *qlogicpti_info(struct Scsi_Host *host)
 	static char buf[80];
 	struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata;
 
-	sprintf(buf, "PTI Qlogic,ISP SBUS SCSI irq %s regs at %lx",
+	sprintf(buf, "PTI Qlogic,ISP SBUS SCSI irq %s regs at %p",
 		__irq_itoa(qpti->qhost->irq), qpti->qregs);
 	return buf;
 }
diff --git a/drivers/scsi/qlogicpti.h b/drivers/scsi/qlogicpti.h
index a40ff75ca..6cd1c0771 100644
--- a/drivers/scsi/qlogicpti.h
+++ b/drivers/scsi/qlogicpti.h
@@ -335,7 +335,7 @@ struct scsi_cmnd;
 /* Software state for the driver. */
 struct qlogicpti {
 	/* These are the hot elements in the cache, so they come first. */
-	unsigned long             qregs;                /* Adapter registers          */
+	void __iomem             *qregs;                /* Adapter registers          */
 	struct pti_queue_entry   *res_cpu;              /* Ptr to RESPONSE bufs (CPU) */
 	struct pti_queue_entry   *req_cpu;              /* Ptr to REQUEST bufs (CPU)  */
 
@@ -370,7 +370,7 @@ struct qlogicpti {
 	struct	host_param        host_param;
 	struct	dev_param         dev_param[MAX_TARGETS];
 
-	unsigned long             sreg;
+	void __iomem              *sreg;
 #define SREG_TPOWER               0x80   /* State of termpwr           */
 #define SREG_FUSE                 0x40   /* State of on board fuse     */
 #define SREG_PDISAB               0x20   /* Disable state for power on */
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index 29248d608..aef957b52 100644
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -20,6 +20,10 @@
  *  If you do not delete the provisions above, a recipient may use your
  *  version of this file under either the OSL or the GPL.
  *
+ *  0.03
+ *     - Fixed a bug where the hotplug handlers for non-CK804/MCP04 were using
+ *       mmio_base, which is only set for the CK804/MCP04 case.
+ *
  *  0.02
  *     - Added support for CK804 SATA controller.
  *
@@ -40,13 +44,12 @@
 #include <linux/libata.h>
 
 #define DRV_NAME			"sata_nv"
-#define DRV_VERSION			"0.02"
+#define DRV_VERSION			"0.03"
 
 #define NV_PORTS			2
 #define NV_PIO_MASK			0x1f
+#define NV_MWDMA_MASK			0x07
 #define NV_UDMA_MASK			0x7f
-#define NV_PORT0_BMDMA_REG_OFFSET	0x00
-#define NV_PORT1_BMDMA_REG_OFFSET	0x08
 #define NV_PORT0_SCR_REG_OFFSET		0x00
 #define NV_PORT1_SCR_REG_OFFSET		0x40
 
@@ -177,11 +180,12 @@ static struct pci_driver nv_pci_driver = {
 static Scsi_Host_Template nv_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
 	.this_id		= ATA_SHT_THIS_ID,
-	.sg_tablesize		= ATA_MAX_PRD,
+	.sg_tablesize		= LIBATA_MAX_PRD,
 	.max_sectors		= ATA_MAX_SECTORS,
 	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
 	.emulated		= ATA_SHT_EMULATED,
@@ -194,13 +198,14 @@ static Scsi_Host_Template nv_sht = {
 
 static struct ata_port_operations nv_ops = {
 	.port_disable		= ata_port_disable,
-	.tf_load		= ata_tf_load_pio,
-	.tf_read		= ata_tf_read_pio,
-	.exec_command		= ata_exec_command_pio,
-	.check_status		= ata_check_status_pio,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.exec_command		= ata_exec_command,
+	.check_status		= ata_check_status,
+	.dev_select		= ata_std_dev_select,
 	.phy_reset		= sata_phy_reset,
-	.bmdma_setup		= ata_bmdma_setup_pio,
-	.bmdma_start		= ata_bmdma_start_pio,
+	.bmdma_setup		= ata_bmdma_setup,
+	.bmdma_start		= ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 	.eng_timeout		= ata_eng_timeout,
@@ -213,6 +218,18 @@ static struct ata_port_operations nv_ops = {
 	.host_stop		= nv_host_stop,
 };
 
+static struct ata_port_info nv_port_info = {
+	.sht		= &nv_sht,
+	.host_flags	= ATA_FLAG_SATA |
+			  ATA_FLAG_SATA_RESET |
+			  ATA_FLAG_SRST |
+			  ATA_FLAG_NO_LEGACY,
+	.pio_mask	= NV_PIO_MASK,
+	.mwdma_mask	= NV_MWDMA_MASK,
+	.udma_mask	= NV_UDMA_MASK,
+	.port_ops	= &nv_ops,
+};
+
 MODULE_AUTHOR("NVIDIA");
 MODULE_DESCRIPTION("low-level driver for NVIDIA nForce SATA controller");
 MODULE_LICENSE("GPL");
@@ -293,6 +310,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	static int printed_version = 0;
 	struct nv_host *host;
+	struct ata_port_info *ppi;
 	struct ata_probe_ent *probe_ent = NULL;
 	int rc;
 
@@ -314,7 +332,8 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (rc)
 		goto err_out_regions;
 
-	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	ppi = &nv_port_info;
+	probe_ent = ata_pci_init_native_mode(pdev, &ppi);
 	if (!probe_ent) {
 		rc = -ENOMEM;
 		goto err_out_regions;
@@ -328,39 +347,6 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	host->host_desc = &nv_device_tbl[ent->driver_data];
 
-	memset(probe_ent, 0, sizeof(*probe_ent));
-	INIT_LIST_HEAD(&probe_ent->node);
-
-	probe_ent->pdev = pdev;
-	probe_ent->sht = &nv_sht;
-	probe_ent->host_flags = ATA_FLAG_SATA |
-				ATA_FLAG_SATA_RESET |
-				ATA_FLAG_SRST |
-				ATA_FLAG_NO_LEGACY;
-
-	probe_ent->port_ops = &nv_ops;
-	probe_ent->n_ports = NV_PORTS;
-	probe_ent->irq = pdev->irq;
-	probe_ent->irq_flags = SA_SHIRQ;
-	probe_ent->pio_mask = NV_PIO_MASK;
-	probe_ent->udma_mask = NV_UDMA_MASK;
-
-	probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
-	ata_std_ports(&probe_ent->port[0]);
-	probe_ent->port[0].altstatus_addr =
-	probe_ent->port[0].ctl_addr =
-		pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
-	probe_ent->port[0].bmdma_addr =
-		pci_resource_start(pdev, 4) | NV_PORT0_BMDMA_REG_OFFSET;
-
-	probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
-	ata_std_ports(&probe_ent->port[1]);
-	probe_ent->port[1].altstatus_addr =
-	probe_ent->port[1].ctl_addr =
-		pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
-	probe_ent->port[1].bmdma_addr =
-		pci_resource_start(pdev, 4) | NV_PORT1_BMDMA_REG_OFFSET;
-
 	probe_ent->private_data = host;
 
 	if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO) {
@@ -369,7 +355,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 		probe_ent->mmio_base = ioremap(pci_resource_start(pdev, 5),
 				pci_resource_len(pdev, 5));
 		if (probe_ent->mmio_base == NULL)
-			goto err_out_free_ent;
+			goto err_out_iounmap;
 
 		base = (unsigned long)probe_ent->mmio_base;
 
@@ -393,12 +379,16 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	rc = ata_device_add(probe_ent);
 	if (rc != NV_PORTS)
-		goto err_out_free_ent;
+		goto err_out_iounmap;
 
 	kfree(probe_ent);
 
 	return 0;
 
+err_out_iounmap:
+	if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO)
+		iounmap(probe_ent->mmio_base);
+
 err_out_free_ent:
 	kfree(probe_ent);
 
@@ -415,33 +405,33 @@ static void nv_enable_hotplug(struct ata_probe_ent *probe_ent)
 	u8 intr_mask;
 
 	outb(NV_INT_STATUS_HOTPLUG,
-		(unsigned long)probe_ent->mmio_base + NV_INT_STATUS);
+		probe_ent->port[0].scr_addr + NV_INT_STATUS);
 
-	intr_mask = inb((unsigned long)probe_ent->mmio_base + NV_INT_ENABLE);
+	intr_mask = inb(probe_ent->port[0].scr_addr + NV_INT_ENABLE);
 	intr_mask |= NV_INT_ENABLE_HOTPLUG;
 
-	outb(intr_mask, (unsigned long)probe_ent->mmio_base + NV_INT_ENABLE);
+	outb(intr_mask, probe_ent->port[0].scr_addr + NV_INT_ENABLE);
 }
 
 static void nv_disable_hotplug(struct ata_host_set *host_set)
 {
 	u8 intr_mask;
 
-	intr_mask = inb((unsigned long)host_set->mmio_base + NV_INT_ENABLE);
+	intr_mask = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE);
 
 	intr_mask &= ~(NV_INT_ENABLE_HOTPLUG);
 
-	outb(intr_mask, (unsigned long)host_set->mmio_base + NV_INT_ENABLE);
+	outb(intr_mask, host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE);
 }
 
 static void nv_check_hotplug(struct ata_host_set *host_set)
 {
 	u8 intr_status;
 
-	intr_status = inb((unsigned long)host_set->mmio_base + NV_INT_STATUS);
+	intr_status = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS);
 
 	// Clear interrupt status.
-	outb(0xff, (unsigned long)host_set->mmio_base + NV_INT_STATUS);
+	outb(0xff, host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS);
 
 	if (intr_status & NV_INT_STATUS_HOTPLUG) {
 		if (intr_status & NV_INT_STATUS_PDEV_ADDED)
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index a2eefb6bc..67bdfb910 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -74,7 +74,6 @@ struct pdc_port_priv {
 static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static void pdc_dma_start(struct ata_queued_cmd *qc);
 static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
 static void pdc_eng_timeout(struct ata_port *ap);
 static int pdc_port_start(struct ata_port *ap);
@@ -83,14 +82,13 @@ static void pdc_phy_reset(struct ata_port *ap);
 static void pdc_qc_prep(struct ata_queued_cmd *qc);
 static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
 static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
-static inline void pdc_dma_complete (struct ata_port *ap,
-                                     struct ata_queued_cmd *qc, int have_err);
 static void pdc_irq_clear(struct ata_port *ap);
 static int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
 
 static Scsi_Host_Template pdc_sata_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -109,9 +107,10 @@ static Scsi_Host_Template pdc_sata_sht = {
 static struct ata_port_operations pdc_sata_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= pdc_tf_load_mmio,
-	.tf_read		= ata_tf_read_mmio,
-	.check_status		= ata_check_status_mmio,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
 	.exec_command		= pdc_exec_command_mmio,
+	.dev_select		= ata_std_dev_select,
 	.phy_reset		= pdc_phy_reset,
 	.qc_prep		= pdc_qc_prep,
 	.qc_issue		= pdc_qc_issue_prot,
@@ -130,7 +129,8 @@ static struct ata_port_info pdc_port_info[] = {
 		.sht		= &pdc_sata_sht,
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_SRST | ATA_FLAG_MMIO,
-		.pio_mask	= 0x03, /* pio3-4 */
+		.pio_mask	= 0x1f, /* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
 		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
 		.port_ops	= &pdc_sata_ops,
 	},
@@ -140,7 +140,8 @@ static struct ata_port_info pdc_port_info[] = {
 		.sht		= &pdc_sata_sht,
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_SRST | ATA_FLAG_MMIO,
-		.pio_mask	= 0x03, /* pio3-4 */
+		.pio_mask	= 0x1f, /* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
 		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
 		.port_ops	= &pdc_sata_ops,
 	},
@@ -269,26 +270,26 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc)
 
 	VPRINTK("ENTER\n");
 
-	ata_qc_prep(qc);
-
-	i = pdc_pkt_header(&qc->tf, qc->ap->prd_dma,  qc->dev->devno, pp->pkt);
+	switch (qc->tf.protocol) {
+	case ATA_PROT_DMA:
+		ata_qc_prep(qc);
+		/* fall through */
 
-	if (qc->tf.flags & ATA_TFLAG_LBA48)
-		i = pdc_prep_lba48(&qc->tf, pp->pkt, i);
-	else
-		i = pdc_prep_lba28(&qc->tf, pp->pkt, i);
+	case ATA_PROT_NODATA:
+		i = pdc_pkt_header(&qc->tf, qc->ap->prd_dma,
+				   qc->dev->devno, pp->pkt);
 
-	pdc_pkt_footer(&qc->tf, pp->pkt, i);
-}
+		if (qc->tf.flags & ATA_TFLAG_LBA48)
+			i = pdc_prep_lba48(&qc->tf, pp->pkt, i);
+		else
+			i = pdc_prep_lba28(&qc->tf, pp->pkt, i);
 
-static inline void pdc_dma_complete (struct ata_port *ap,
-                                     struct ata_queued_cmd *qc,
-				     int have_err)
-{
-	u8 err_bit = have_err ? ATA_ERR : 0;
+		pdc_pkt_footer(&qc->tf, pp->pkt, i);
+		break;
 
-	/* get drive status; clear intr; complete txn */
-	ata_qc_complete(qc, ata_wait_idle(ap) | err_bit);
+	default:
+		break;
+	}
 }
 
 static void pdc_eng_timeout(struct ata_port *ap)
@@ -315,17 +316,9 @@ static void pdc_eng_timeout(struct ata_port *ap)
 
 	switch (qc->tf.protocol) {
 	case ATA_PROT_DMA:
-		printk(KERN_ERR "ata%u: DMA timeout\n", ap->id);
-		ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
-		break;
-
 	case ATA_PROT_NODATA:
-		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
-
-		printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n",
-		       ap->id, qc->tf.command, drv_stat);
-
-		ata_qc_complete(qc, drv_stat);
+		printk(KERN_ERR "ata%u: command timeout\n", ap->id);
+		ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
 		break;
 
 	default:
@@ -358,13 +351,8 @@ static inline unsigned int pdc_host_intr( struct ata_port *ap,
 
 	switch (qc->tf.protocol) {
 	case ATA_PROT_DMA:
-		pdc_dma_complete(ap, qc, have_err);
-		handled = 1;
-		break;
-
-	case ATA_PROT_NODATA:   /* command completion, but no data xfer */
-		status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
-		DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
+	case ATA_PROT_NODATA:
+		status = ata_wait_idle(ap);
 		if (have_err)
 			status |= ATA_ERR;
 		ata_qc_complete(qc, status);
@@ -440,7 +428,7 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r
 	return IRQ_RETVAL(handled);
 }
 
-static inline void pdc_dma_start(struct ata_queued_cmd *qc)
+static inline void pdc_packet_start(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	struct pdc_port_priv *pp = ap->private_data;
@@ -462,7 +450,8 @@ static int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
 {
 	switch (qc->tf.protocol) {
 	case ATA_PROT_DMA:
-		pdc_dma_start(qc);
+	case ATA_PROT_NODATA:
+		pdc_packet_start(qc);
 		return 0;
 
 	case ATA_PROT_ATAPI_DMA:
@@ -478,15 +467,17 @@ static int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
 
 static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
-	WARN_ON (tf->protocol == ATA_PROT_DMA);
-	ata_tf_load_mmio(ap, tf);
+	WARN_ON (tf->protocol == ATA_PROT_DMA ||
+		 tf->protocol == ATA_PROT_NODATA);
+	ata_tf_load(ap, tf);
 }
 
 
 static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
-	WARN_ON (tf->protocol == ATA_PROT_DMA);
-	ata_exec_command_mmio(ap, tf);
+	WARN_ON (tf->protocol == ATA_PROT_DMA ||
+		 tf->protocol == ATA_PROT_NODATA);
+	ata_exec_command(ap, tf);
 }
 
 
@@ -539,8 +530,7 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
 	writel(tmp, mmio + PDC_TBG_MODE);
 
 	readl(mmio + PDC_TBG_MODE);	/* flush */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(msecs_to_jiffies(10) + 1);
+	msleep(10);
 
 	/* adjust slew rate control register. */
 	tmp = readl(mmio + PDC_SLEW_CTL);
@@ -601,6 +591,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
 	probe_ent->sht		= pdc_port_info[board_idx].sht;
 	probe_ent->host_flags	= pdc_port_info[board_idx].host_flags;
 	probe_ent->pio_mask	= pdc_port_info[board_idx].pio_mask;
+	probe_ent->mwdma_mask	= pdc_port_info[board_idx].mwdma_mask;
 	probe_ent->udma_mask	= pdc_port_info[board_idx].udma_mask;
 	probe_ent->port_ops	= pdc_port_info[board_idx].port_ops;
 
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 72a89d1be..9a349a9be 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -6,7 +6,7 @@
  *		    on emails.
  *
  *  Copyright 2003 Red Hat, Inc.
- *  Copyright 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ *  Copyright 2003 Benjamin Herrenschmidt
  *
  *  The contents of this file are subject to the Open
  *  Software License version 1.1 that can be found at
@@ -106,6 +106,7 @@ static struct pci_driver sil_pci_driver = {
 static Scsi_Host_Template sil_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -124,14 +125,15 @@ static Scsi_Host_Template sil_sht = {
 static struct ata_port_operations sil_ops = {
 	.port_disable		= ata_port_disable,
 	.dev_config		= sil_dev_config,
-	.tf_load		= ata_tf_load_mmio,
-	.tf_read		= ata_tf_read_mmio,
-	.check_status		= ata_check_status_mmio,
-	.exec_command		= ata_exec_command_mmio,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= ata_exec_command,
+	.dev_select		= ata_std_dev_select,
 	.phy_reset		= sata_phy_reset,
 	.post_set_mode		= sil_post_set_mode,
-	.bmdma_setup            = ata_bmdma_setup_mmio,
-	.bmdma_start            = ata_bmdma_start_mmio,
+	.bmdma_setup            = ata_bmdma_setup,
+	.bmdma_start            = ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 	.eng_timeout		= ata_eng_timeout,
@@ -149,7 +151,8 @@ static struct ata_port_info sil_port_info[] = {
 		.sht		= &sil_sht,
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_SRST | ATA_FLAG_MMIO,
-		.pio_mask	= 0x03,			/* pio3-4 */
+		.pio_mask	= 0x1f,			/* pio0-4 */
+		.mwdma_mask	= 0x07,			/* mwdma0-2 */
 		.udma_mask	= 0x3f,			/* udma0-5 */
 		.port_ops	= &sil_ops,
 	}, /* sil_3114 */
@@ -157,7 +160,8 @@ static struct ata_port_info sil_port_info[] = {
 		.sht		= &sil_sht,
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_SRST | ATA_FLAG_MMIO,
-		.pio_mask	= 0x03,			/* pio3-4 */
+		.pio_mask	= 0x1f,			/* pio0-4 */
+		.mwdma_mask	= 0x07,			/* mwdma0-2 */
 		.udma_mask	= 0x3f,			/* udma0-5 */
 		.port_ops	= &sil_ops,
 	},
@@ -363,6 +367,7 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 	probe_ent->sht = sil_port_info[ent->driver_data].sht;
 	probe_ent->n_ports = (ent->driver_data == sil_3114) ? 4 : 2;
 	probe_ent->pio_mask = sil_port_info[ent->driver_data].pio_mask;
+	probe_ent->mwdma_mask = sil_port_info[ent->driver_data].mwdma_mask;
 	probe_ent->udma_mask = sil_port_info[ent->driver_data].udma_mask;
        	probe_ent->irq = pdev->irq;
        	probe_ent->irq_flags = SA_SHIRQ;
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
index 88b7a02ea..17eb7ed5a 100644
--- a/drivers/scsi/sata_sis.c
+++ b/drivers/scsi/sata_sis.c
@@ -76,6 +76,7 @@ static struct pci_driver sis_pci_driver = {
 static Scsi_Host_Template sis_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -93,13 +94,14 @@ static Scsi_Host_Template sis_sht = {
 
 static struct ata_port_operations sis_ops = {
 	.port_disable		= ata_port_disable,
-	.tf_load		= ata_tf_load_pio,
-	.tf_read		= ata_tf_read_pio,
-	.check_status		= ata_check_status_pio,
-	.exec_command		= ata_exec_command_pio,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= ata_exec_command,
+	.dev_select		= ata_std_dev_select,
 	.phy_reset		= sata_phy_reset,
-	.bmdma_setup            = ata_bmdma_setup_pio,
-	.bmdma_start            = ata_bmdma_start_pio,
+	.bmdma_setup            = ata_bmdma_setup,
+	.bmdma_start            = ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 	.eng_timeout		= ata_eng_timeout,
@@ -111,6 +113,16 @@ static struct ata_port_operations sis_ops = {
 	.port_stop		= ata_port_stop,
 };
 
+static struct ata_port_info sis_port_info = {
+	.sht		= &sis_sht,
+	.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
+			  ATA_FLAG_NO_LEGACY,
+	.pio_mask	= 0x1f,
+	.mwdma_mask	= 0x7,
+	.udma_mask	= 0x7f,
+	.port_ops	= &sis_ops,
+};
+
 
 MODULE_AUTHOR("Uwe Koziolek");
 MODULE_DESCRIPTION("low-level driver for Silicon Integratad Systems SATA controller");
@@ -184,6 +196,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 	struct ata_probe_ent *probe_ent = NULL;
 	int rc;
 	u32 genctl;
+	struct ata_port_info *ppi;
 
 	rc = pci_enable_device(pdev);
 	if (rc)
@@ -200,20 +213,13 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (rc)
 		goto err_out_regions;
 
-	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	ppi = &sis_port_info;
+	probe_ent = ata_pci_init_native_mode(pdev, &ppi);
 	if (!probe_ent) {
 		rc = -ENOMEM;
 		goto err_out_regions;
 	}
 
-	memset(probe_ent, 0, sizeof(*probe_ent));
-	probe_ent->pdev = pdev;
-	INIT_LIST_HEAD(&probe_ent->node);
-
-	probe_ent->sht = &sis_sht;
-	probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
-				ATA_FLAG_NO_LEGACY;
-
 	/* check and see if the SCRs are in IO space or PCI cfg space */
 	pci_read_config_dword(pdev, SIS_GENCTL, &genctl);
 	if ((genctl & GENCTL_IOMAPPED_SCR) == 0)
@@ -230,31 +236,12 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 		probe_ent->host_flags |= SIS_FLAG_CFGSCR;
 	}
 
-	probe_ent->pio_mask = 0x03;
-	probe_ent->udma_mask = 0x7f;
-	probe_ent->port_ops = &sis_ops;
-
-	probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
-	ata_std_ports(&probe_ent->port[0]);
-	probe_ent->port[0].ctl_addr =
-		pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
-	probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
-	if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR))
+	if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR)) {
 		probe_ent->port[0].scr_addr =
 			pci_resource_start(pdev, SIS_SCR_PCI_BAR);
-
-	probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
-	ata_std_ports(&probe_ent->port[1]);
-	probe_ent->port[1].ctl_addr =
-		pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
-	probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
-	if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR))
 		probe_ent->port[1].scr_addr =
 			pci_resource_start(pdev, SIS_SCR_PCI_BAR) + 64;
-
-	probe_ent->n_ports = 2;
-	probe_ent->irq = pdev->irq;
-	probe_ent->irq_flags = SA_SHIRQ;
+	}
 
 	pci_set_master(pdev);
 	pci_enable_intx(pdev);
@@ -284,6 +271,6 @@ static void __exit sis_exit(void)
 	pci_unregister_driver(&sis_pci_driver);
 }
 
-
 module_init(sis_init);
 module_exit(sis_exit);
+
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index 398f24f27..fd01225a7 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -148,7 +148,73 @@ static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
         }
 }
 
+/**
+ *	k2_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction (MMIO)
+ *	@qc: Info associated with this ATA transaction.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
+	u8 dmactl;
+	void *mmio = (void *) ap->ioaddr.bmdma_addr;
+	/* load PRD table addr. */
+	mb();	/* make sure PRD table writes are visible to controller */
+	writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS);
+
+	/* specify data direction, triple-check start bit is clear */
+	dmactl = readb(mmio + ATA_DMA_CMD);
+	dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
+	if (!rw)
+		dmactl |= ATA_DMA_WR;
+	writeb(dmactl, mmio + ATA_DMA_CMD);
+
+	/* issue r/w command if this is not a ATA DMA command*/
+	if (qc->tf.protocol != ATA_PROT_DMA)
+		ap->ops->exec_command(ap, &qc->tf);
+}
+
+/**
+ *	k2_bmdma_start_mmio - Start a PCI IDE BMDMA transaction (MMIO)
+ *	@qc: Info associated with this ATA transaction.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	void *mmio = (void *) ap->ioaddr.bmdma_addr;
+	u8 dmactl;
+
+	/* start host DMA transaction */
+	dmactl = readb(mmio + ATA_DMA_CMD);
+	writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD);
+	/* There is a race condition in certain SATA controllers that can 
+	   be seen when the r/w command is given to the controller before the 
+	   host DMA is started. On a Read command, the controller would initiate
+	   the command to the drive even before it sees the DMA start. When there
+	   are very fast drives connected to the controller, or when the data request 
+	   hits in the drive cache, there is the possibility that the drive returns a part
+	   or all of the requested data to the controller before the DMA start is issued.
+	   In this case, the controller would become confused as to what to do with the data.
+	   In the worst case when all the data is returned back to the controller, the
+	   controller could hang. In other cases it could return partial data returning
+	   in data corruption. This problem has been seen in PPC systems and can also appear
+	   on an system with very fast disks, where the SATA controller is sitting behind a 
+	   number of bridges, and hence there is significant latency between the r/w command
+	   and the start command. */
+	/* issue r/w command if the access is to ATA*/
+	if (qc->tf.protocol == ATA_PROT_DMA)
+		ap->ops->exec_command(ap, &qc->tf);
+}
 
+									      
 static u8 k2_stat_check_status(struct ata_port *ap)
 {
        	return readl((void *) ap->ioaddr.status_addr);
@@ -205,6 +271,7 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start,
 static Scsi_Host_Template k2_sata_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -229,10 +296,11 @@ static struct ata_port_operations k2_sata_ops = {
 	.tf_load		= k2_sata_tf_load,
 	.tf_read		= k2_sata_tf_read,
 	.check_status		= k2_stat_check_status,
-	.exec_command		= ata_exec_command_mmio,
+	.exec_command		= ata_exec_command,
+	.dev_select		= ata_std_dev_select,
 	.phy_reset		= sata_phy_reset,
-	.bmdma_setup            = ata_bmdma_setup_mmio,
-	.bmdma_start            = ata_bmdma_start_mmio,
+	.bmdma_setup		= k2_bmdma_setup_mmio,
+	.bmdma_start		= k2_bmdma_start_mmio,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 	.eng_timeout		= ata_eng_timeout,
@@ -343,6 +411,7 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
 	 * if we don't fill these
 	 */
 	probe_ent->pio_mask = 0x1f;
+	probe_ent->mwdma_mask = 0x7;
 	probe_ent->udma_mask = 0x7f;
 
 	/* We have 4 ports per PCI function */
@@ -371,6 +440,8 @@ err_out:
 
 static struct pci_device_id k2_sata_pci_tbl[] = {
 	{ 0x1166, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ }
 };
 
@@ -388,6 +459,7 @@ static int __init k2_sata_init(void)
 	return pci_module_init(&k2_sata_pci_driver);
 }
 
+
 static void __exit k2_sata_exit(void)
 {
 	pci_unregister_driver(&k2_sata_pci_driver);
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
index b54fd87e3..8da761487 100644
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -146,8 +146,6 @@ struct pdc_host_priv {
 
 
 static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static void pdc20621_dma_setup(struct ata_queued_cmd *qc);
-static void pdc20621_dma_start(struct ata_queued_cmd *qc);
 static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
 static void pdc_eng_timeout(struct ata_port *ap);
 static void pdc_20621_phy_reset (struct ata_port *ap);
@@ -157,8 +155,6 @@ static void pdc20621_qc_prep(struct ata_queued_cmd *qc);
 static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
 static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
 static void pdc20621_host_stop(struct ata_host_set *host_set);
-static inline void pdc_dma_complete (struct ata_port *ap,
-                                     struct ata_queued_cmd *qc, int have_err);
 static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe);
 static int pdc20621_detect_dimm(struct ata_probe_ent *pe);
 static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, 
@@ -172,11 +168,13 @@ static void pdc20621_get_from_dimm(struct ata_probe_ent *pe,
 static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, 
 				 void *psource, u32 offset, u32 size);
 static void pdc20621_irq_clear(struct ata_port *ap);
+static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc);
 
 
 static Scsi_Host_Template pdc_sata_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -195,14 +193,13 @@ static Scsi_Host_Template pdc_sata_sht = {
 static struct ata_port_operations pdc_20621_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= pdc_tf_load_mmio,
-	.tf_read		= ata_tf_read_mmio,
-	.check_status		= ata_check_status_mmio,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
 	.exec_command		= pdc_exec_command_mmio,
+	.dev_select		= ata_std_dev_select,
 	.phy_reset		= pdc_20621_phy_reset,
-	.bmdma_setup            = pdc20621_dma_setup,
-	.bmdma_start            = pdc20621_dma_start,
 	.qc_prep		= pdc20621_qc_prep,
-	.qc_issue		= ata_qc_issue_prot,
+	.qc_issue		= pdc20621_qc_issue_prot,
 	.eng_timeout		= pdc_eng_timeout,
 	.irq_handler		= pdc20621_interrupt,
 	.irq_clear		= pdc20621_irq_clear,
@@ -217,7 +214,8 @@ static struct ata_port_info pdc_port_info[] = {
 		.sht		= &pdc_sata_sht,
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_SRST | ATA_FLAG_MMIO,
-		.pio_mask	= 0x03, /* pio3-4 */
+		.pio_mask	= 0x1f, /* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
 		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
 		.port_ops	= &pdc_20621_ops,
 	},
@@ -377,7 +375,10 @@ static inline unsigned int pdc20621_ata_pkt(struct ata_taskfile *tf,
 
 	/* dimm dma S/G, and next-pkt */
 	dw = i >> 2;
-	buf32[dw] = cpu_to_le32(dimm_sg);
+	if (tf->protocol == ATA_PROT_NODATA)
+		buf32[dw] = 0;
+	else
+		buf32[dw] = cpu_to_le32(dimm_sg);
 	buf32[dw + 1] = 0;
 	i += 8;
 
@@ -437,7 +438,7 @@ static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf,
 		buf32[dw + 3]);
 }
 
-static void pdc20621_qc_prep(struct ata_queued_cmd *qc)
+static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
 {
 	struct scatterlist *sg = qc->sg;
 	struct ata_port *ap = qc->ap;
@@ -449,8 +450,7 @@ static void pdc20621_qc_prep(struct ata_queued_cmd *qc)
 	unsigned int i, last, idx, total_len = 0, sgt_len;
 	u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
 
-	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
-		return;
+	assert(qc->flags & ATA_QCFLAG_DMAMAP);
 
 	VPRINTK("ata%u: ENTER\n", ap->id);
 
@@ -501,6 +501,56 @@ static void pdc20621_qc_prep(struct ata_queued_cmd *qc)
 	VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied\n", i, sgt_len);
 }
 
+static void pdc20621_nodata_prep(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct pdc_port_priv *pp = ap->private_data;
+	void *mmio = ap->host_set->mmio_base;
+	struct pdc_host_priv *hpriv = ap->host_set->private_data;
+	void *dimm_mmio = hpriv->dimm_mmio;
+	unsigned int portno = ap->port_no;
+	unsigned int i;
+
+	VPRINTK("ata%u: ENTER\n", ap->id);
+
+	/* hard-code chip #0 */
+	mmio += PDC_CHIP0_OFS;
+
+	i = pdc20621_ata_pkt(&qc->tf, qc->dev->devno, &pp->dimm_buf[0], portno);
+
+	if (qc->tf.flags & ATA_TFLAG_LBA48)
+		i = pdc_prep_lba48(&qc->tf, &pp->dimm_buf[0], i);
+	else
+		i = pdc_prep_lba28(&qc->tf, &pp->dimm_buf[0], i);
+
+	pdc_pkt_footer(&qc->tf, &pp->dimm_buf[0], i);
+
+	/* copy three S/G tables and two packets to DIMM MMIO window */
+	memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP),
+		    &pp->dimm_buf, PDC_DIMM_HEADER_SZ);
+
+	/* force host FIFO dump */
+	writel(0x00000001, mmio + PDC_20621_GENERAL_CTL);
+
+	readl(dimm_mmio);	/* MMIO PCI posting flush */
+
+	VPRINTK("ata pkt buf ofs %u, mmio copied\n", i);
+}
+
+static void pdc20621_qc_prep(struct ata_queued_cmd *qc)
+{
+	switch (qc->tf.protocol) {
+	case ATA_PROT_DMA:
+		pdc20621_dma_prep(qc);
+		break;
+	case ATA_PROT_NODATA:
+		pdc20621_nodata_prep(qc);
+		break;
+	default:
+		break;
+	}
+}
+
 static void __pdc20621_push_hdma(struct ata_queued_cmd *qc,
 				 unsigned int seq,
 				 u32 pkt_ofs)
@@ -576,13 +626,7 @@ static void pdc20621_dump_hdma(struct ata_queued_cmd *qc)
 static inline void pdc20621_dump_hdma(struct ata_queued_cmd *qc) { }
 #endif /* ATA_VERBOSE_DEBUG */
 
-static void pdc20621_dma_setup(struct ata_queued_cmd *qc)
-{
-	/* nothing for now.  later, we will call standard
-	 * code in libata-core for ATAPI here */
-}
-
-static void pdc20621_dma_start(struct ata_queued_cmd *qc)
+static void pdc20621_packet_start(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	struct ata_host_set *host_set = ap->host_set;
@@ -590,24 +634,21 @@ static void pdc20621_dma_start(struct ata_queued_cmd *qc)
 	void *mmio = host_set->mmio_base;
 	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
 	u8 seq = (u8) (port_no + 1);
-	unsigned int doing_hdma = 0, port_ofs;
+	unsigned int port_ofs;
 
 	/* hard-code chip #0 */
 	mmio += PDC_CHIP0_OFS;
 
 	VPRINTK("ata%u: ENTER\n", ap->id);
 
+	wmb();			/* flush PRD, pkt writes */
+
 	port_ofs = PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no);
 
 	/* if writing, we (1) DMA to DIMM, then (2) do ATA command */
-	if (rw) {
-		doing_hdma = 1;
+	if (rw && qc->tf.protocol == ATA_PROT_DMA) {
 		seq += 4;
-	}
-
-	wmb();			/* flush PRD, pkt writes */
 
-	if (doing_hdma) {
 		pdc20621_dump_hdma(qc);
 		pdc20621_push_hdma(qc, seq, port_ofs + PDC_DIMM_HOST_PKT);
 		VPRINTK("queued ofs 0x%x (%u), seq %u\n",
@@ -628,6 +669,25 @@ static void pdc20621_dma_start(struct ata_queued_cmd *qc)
 	}
 }
 
+static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
+{
+	switch (qc->tf.protocol) {
+	case ATA_PROT_DMA:
+	case ATA_PROT_NODATA:
+		pdc20621_packet_start(qc);
+		return 0;
+
+	case ATA_PROT_ATAPI_DMA:
+		BUG();
+		break;
+
+	default:
+		break;
+	}
+
+	return ata_qc_issue_prot(qc);
+}
+
 static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
                                           struct ata_queued_cmd *qc,
 					  unsigned int doing_hdma,
@@ -648,7 +708,8 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
 		if (doing_hdma) {
 			VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
 				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
-			pdc_dma_complete(ap, qc, 0);
+			/* get drive status; clear intr; complete txn */
+			ata_qc_complete(qc, ata_wait_idle(ap));
 			pdc20621_pop_hdma(qc);
 		}
 
@@ -685,7 +746,8 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
 		else {
 			VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
 				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
-			pdc_dma_complete(ap, qc, 0);
+			/* get drive status; clear intr; complete txn */
+			ata_qc_complete(qc, ata_wait_idle(ap));
 			pdc20621_pop_hdma(qc);
 		}
 		handled = 1;
@@ -779,16 +841,6 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_re
 	return IRQ_RETVAL(handled);
 }
 
-static inline void pdc_dma_complete (struct ata_port *ap,
-                                     struct ata_queued_cmd *qc,
-				     int have_err)
-{
-	u8 err_bit = have_err ? ATA_ERR : 0;
-
-	/* get drive status; clear intr; complete txn */
-	ata_qc_complete(qc, ata_wait_idle(ap) | err_bit);
-}
-
 static void pdc_eng_timeout(struct ata_port *ap)
 {
 	u8 drv_stat;
@@ -813,17 +865,9 @@ static void pdc_eng_timeout(struct ata_port *ap)
 
 	switch (qc->tf.protocol) {
 	case ATA_PROT_DMA:
-		printk(KERN_ERR "ata%u: DMA timeout\n", ap->id);
-		ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
-		break;
-
 	case ATA_PROT_NODATA:
-		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
-
-		printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n",
-		       ap->id, qc->tf.command, drv_stat);
-
-		ata_qc_complete(qc, drv_stat);
+		printk(KERN_ERR "ata%u: command timeout\n", ap->id);
+		ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
 		break;
 
 	default:
@@ -842,15 +886,17 @@ out:
 
 static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
-	if (tf->protocol != ATA_PROT_DMA)
-		ata_tf_load_mmio(ap, tf);
+	WARN_ON (tf->protocol == ATA_PROT_DMA ||
+		 tf->protocol == ATA_PROT_NODATA);
+	ata_tf_load(ap, tf);
 }
 
 
 static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
-	if (tf->protocol != ATA_PROT_DMA)
-		ata_exec_command_mmio(ap, tf);
+	WARN_ON (tf->protocol == ATA_PROT_DMA ||
+		 tf->protocol == ATA_PROT_NODATA);
+	ata_exec_command(ap, tf);
 }
 
 
@@ -1384,6 +1430,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
 	probe_ent->sht		= pdc_port_info[board_idx].sht;
 	probe_ent->host_flags	= pdc_port_info[board_idx].host_flags;
 	probe_ent->pio_mask	= pdc_port_info[board_idx].pio_mask;
+	probe_ent->mwdma_mask	= pdc_port_info[board_idx].mwdma_mask;
 	probe_ent->udma_mask	= pdc_port_info[board_idx].udma_mask;
 	probe_ent->port_ops	= pdc_port_info[board_idx].port_ops;
 
@@ -1394,21 +1441,11 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
 	probe_ent->private_data = hpriv;
 	base += PDC_CHIP0_OFS;
 
+	probe_ent->n_ports = 4;
 	pdc_sata_setup_port(&probe_ent->port[0], base + 0x200);
 	pdc_sata_setup_port(&probe_ent->port[1], base + 0x280);
-
-	/* notice 4-port boards */
-	switch (board_idx) {
-	case board_20621:
-       		probe_ent->n_ports = 4;
-
-		pdc_sata_setup_port(&probe_ent->port[2], base + 0x300);
-		pdc_sata_setup_port(&probe_ent->port[3], base + 0x380);
-		break;
-	default:
-		BUG();
-		break;
-	}
+	pdc_sata_setup_port(&probe_ent->port[2], base + 0x300);
+	pdc_sata_setup_port(&probe_ent->port[3], base + 0x380);
 
 	pci_set_master(pdev);
 
diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
index 993edfc99..44ffa9b90 100644
--- a/drivers/scsi/sata_via.c
+++ b/drivers/scsi/sata_via.c
@@ -81,6 +81,7 @@ static struct pci_driver svia_pci_driver = {
 static Scsi_Host_Template svia_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -99,15 +100,16 @@ static Scsi_Host_Template svia_sht = {
 static struct ata_port_operations svia_sata_ops = {
 	.port_disable		= ata_port_disable,
 
-	.tf_load		= ata_tf_load_pio,
-	.tf_read		= ata_tf_read_pio,
-	.check_status		= ata_check_status_pio,
-	.exec_command		= ata_exec_command_pio,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= ata_exec_command,
+	.dev_select		= ata_std_dev_select,
 
 	.phy_reset		= sata_phy_reset,
 
-	.bmdma_setup            = ata_bmdma_setup_pio,
-	.bmdma_start            = ata_bmdma_start_pio,
+	.bmdma_setup            = ata_bmdma_setup,
+	.bmdma_start            = ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 
@@ -123,6 +125,15 @@ static struct ata_port_operations svia_sata_ops = {
 	.port_stop		= ata_port_stop,
 };
 
+static struct ata_port_info svia_port_info = {
+	.sht		= &svia_sht,
+	.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST | ATA_FLAG_NO_LEGACY,
+	.pio_mask	= 0x1f,
+	.mwdma_mask	= 0x07,
+	.udma_mask	= 0x7f,
+	.port_ops	= &svia_sata_ops,
+};
+
 MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers");
 MODULE_LICENSE("GPL");
@@ -156,6 +167,7 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 	static int printed_version;
 	unsigned int i;
 	int rc;
+	struct ata_port_info *ppi;
 	struct ata_probe_ent *probe_ent;
 	u8 tmp8;
 
@@ -196,41 +208,17 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (rc)
 		goto err_out_regions;
 
-	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	ppi = &svia_port_info;
+	probe_ent = ata_pci_init_native_mode(pdev, &ppi);
 	if (!probe_ent) {
 		printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
 		       pci_name(pdev));
 		rc = -ENOMEM;
 		goto err_out_regions;
 	}
-	memset(probe_ent, 0, sizeof(*probe_ent));
-	INIT_LIST_HEAD(&probe_ent->node);
-	probe_ent->pdev = pdev;
-	probe_ent->sht = &svia_sht;
-	probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST |
-				ATA_FLAG_NO_LEGACY;
-	probe_ent->port_ops = &svia_sata_ops;
-	probe_ent->n_ports = 2;
-	probe_ent->irq = pdev->irq;
-	probe_ent->irq_flags = SA_SHIRQ;
-	probe_ent->pio_mask = 0x1f;
-	probe_ent->udma_mask = 0x7f;
-
-	probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
-	ata_std_ports(&probe_ent->port[0]);
-	probe_ent->port[0].altstatus_addr =
-	probe_ent->port[0].ctl_addr =
-		pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
-	probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
+
 	probe_ent->port[0].scr_addr =
 		svia_scr_addr(pci_resource_start(pdev, 5), 0);
-
-	probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
-	ata_std_ports(&probe_ent->port[1]);
-	probe_ent->port[1].altstatus_addr =
-	probe_ent->port[1].ctl_addr =
-		pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
-	probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
 	probe_ent->port[1].scr_addr =
 		svia_scr_addr(pci_resource_start(pdev, 5), 1);
 
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index d63a339cc..880f7f115 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -190,6 +190,7 @@ irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, struct pt_regs *reg
 static Scsi_Host_Template vsc_sata_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -210,11 +211,12 @@ static struct ata_port_operations vsc_sata_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= vsc_sata_tf_load,
 	.tf_read		= vsc_sata_tf_read,
-	.exec_command		= ata_exec_command_mmio,
-	.check_status		= ata_check_status_mmio,
+	.exec_command		= ata_exec_command,
+	.check_status		= ata_check_status,
+	.dev_select		= ata_std_dev_select,
 	.phy_reset		= sata_phy_reset,
-	.bmdma_setup            = ata_bmdma_setup_mmio,
-	.bmdma_start            = ata_bmdma_start_mmio,
+	.bmdma_setup            = ata_bmdma_setup,
+	.bmdma_start            = ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 	.eng_timeout		= ata_eng_timeout,
@@ -320,6 +322,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
 	 * if we don't fill these
 	 */
 	probe_ent->pio_mask = 0x1f;
+	probe_ent->mwdma_mask = 0x07;
 	probe_ent->udma_mask = 0x7f;
 
 	/* We have 4 ports per PCI function */
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 17dce6657..481bea6a4 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -897,15 +897,16 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags)
 	 */
 	if (tags <= 0)
 		return;
-	/*
-	 * Limit max queue depth on a single lun to 256 for now.  Remember,
-	 * we allocate a struct scsi_command for each of these and keep it
-	 * around forever.  Too deep of a depth just wastes memory.
-	 */
-	if (tags > 256)
-		return;
 
 	spin_lock_irqsave(&device_request_lock, flags);
+	spin_lock(sdev->request_queue->queue_lock);
+
+	/* Check to see if the queue is managed by the block layer
+	 * if it is, and we fail to adjust the depth, exit */
+	if (blk_queue_tagged(sdev->request_queue) &&
+	    blk_queue_resize_tags(sdev->request_queue, tags) != 0)
+		goto out;
+
 	sdev->queue_depth = tags;
 	switch (tagged) {
 		case MSG_ORDERED_TAG:
@@ -926,6 +927,8 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags)
 			sdev->queue_depth = tags;
 			break;
 	}
+ out:
+	spin_unlock(sdev->request_queue->queue_lock);
 	spin_unlock_irqrestore(&device_request_lock, flags);
 }
 
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 288f2fde9..617412e06 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -22,7 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/blkdev.h>
-#include <linux/smp_lock.h>
+#include <linux/delay.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_dbg.h>
@@ -42,8 +42,8 @@
  * These should *probably* be handled by the host itself.
  * Since it is allowed to sleep, it probably should.
  */
-#define BUS_RESET_SETTLE_TIME   (10*HZ)
-#define HOST_RESET_SETTLE_TIME  (10*HZ)
+#define BUS_RESET_SETTLE_TIME   (10)
+#define HOST_RESET_SETTLE_TIME  (10)
 
 /* called with shost->host_lock held */
 void scsi_eh_wakeup(struct Scsi_Host *shost)
@@ -643,15 +643,13 @@ static void scsi_eh_finish_cmd(struct scsi_cmnd *scmd,
  * Notes:
  *    This has the unfortunate side effect that if a shost adapter does
  *    not automatically request sense information, that we end up shutting
- *    it down before we request it.  All shosts should be doing this
- *    anyways, so for now all I have to say is tough noogies if you end up
- *    in here.  On second thought, this is probably a good idea.  We
- *    *really* want to give authors an incentive to automatically request
- *    this.
+ *    it down before we request it.
  *
- *    In 2.5 this capability will be going away.
+ *    All drivers should request sense information internally these days,
+ *    so for now all I have to say is tough noogies if you end up in here.
  *
- *    Really?  --hch
+ *    XXX: Long term this code should go away, but that needs an audit of
+ *         all LLDDs first.
  **/
 static int scsi_eh_get_sense(struct list_head *work_q,
 			     struct list_head *done_q)
@@ -1044,7 +1042,7 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
 
 	if (rtn == SUCCESS) {
 		if (!scmd->device->host->hostt->skip_settle_delay)
-			scsi_sleep(BUS_RESET_SETTLE_TIME);
+			ssleep(BUS_RESET_SETTLE_TIME);
 		spin_lock_irqsave(scmd->device->host->host_lock, flags);
 		scsi_report_bus_reset(scmd->device->host, scmd->device->channel);
 		spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
@@ -1076,7 +1074,7 @@ static int scsi_try_host_reset(struct scsi_cmnd *scmd)
 
 	if (rtn == SUCCESS) {
 		if (!scmd->device->host->hostt->skip_settle_delay)
-			scsi_sleep(HOST_RESET_SETTLE_TIME);
+			ssleep(HOST_RESET_SETTLE_TIME);
 		spin_lock_irqsave(scmd->device->host->host_lock, flags);
 		scsi_report_bus_reset(scmd->device->host, scmd->device->channel);
 		spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
@@ -1215,43 +1213,6 @@ static void scsi_eh_offline_sdevs(struct list_head *work_q,
 	return;
 }
 
-/**
- * scsi_sleep_done - timer function for scsi_sleep
- * @sem:	semphore to signal
- *
- **/
-static void scsi_sleep_done(unsigned long data)
-{
-	struct semaphore *sem = (struct semaphore *)data;
-
-	if (sem)
-		up(sem);
-}
-
-/**
- * scsi_sleep - sleep for specified timeout
- * @timeout:	timeout value
- *
- **/
-void scsi_sleep(int timeout)
-{
-	DECLARE_MUTEX_LOCKED(sem);
-	struct timer_list timer;
-
-	init_timer(&timer);
-	timer.data = (unsigned long)&sem;
-	timer.expires = jiffies + timeout;
-	timer.function = (void (*)(unsigned long))scsi_sleep_done;
-
-	SCSI_LOG_ERROR_RECOVERY(5, printk("sleeping for timer tics %d\n",
-					  timeout));
-
-	add_timer(&timer);
-
-	down(&sem);
-	del_timer(&timer);
-}
-
 /**
  * scsi_decide_disposition - Disposition a cmd on return from LLD.
  * @scmd:	SCSI cmd to examine.
@@ -1639,8 +1600,6 @@ int scsi_error_handler(void *data)
 	int rtn;
 	DECLARE_MUTEX_LOCKED(sem);
 
-	lock_kernel();
-
 	/*
 	 *    Flush resources
 	 */
@@ -1652,8 +1611,6 @@ int scsi_error_handler(void *data)
 	shost->eh_wait = &sem;
 	shost->ehandler = current;
 
-	unlock_kernel();
-
 	/*
 	 * Wake up the thread that created us.
 	 */
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index bc5869b10..e26addada 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -391,6 +391,21 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
 	if (!scsi_block_when_processing_errors(sdev))
 		return -ENODEV;
 
+	/* Check for deprecated ioctls ... all the ioctls which don't
+	 * follow the new unique numbering scheme are deprecated */
+	switch (cmd) {
+	case SCSI_IOCTL_SEND_COMMAND:
+	case SCSI_IOCTL_TEST_UNIT_READY:
+	case SCSI_IOCTL_BENCHMARK_COMMAND:
+	case SCSI_IOCTL_SYNC:
+	case SCSI_IOCTL_START_UNIT:
+	case SCSI_IOCTL_STOP_UNIT:
+		printk(KERN_WARNING "program %s is using a deprecated SCSI ioctl, please convert it to SG_IO\n", current->comm);
+		break;
+	default:
+		break;
+	}
+
 	switch (cmd) {
 	case SCSI_IOCTL_GET_IDLUN:
 		if (verify_area(VERIFY_WRITE, arg, sizeof(struct scsi_idlun)))
@@ -417,12 +432,8 @@ int scsi_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
 	case SCSI_IOCTL_DOORUNLOCK:
 		return scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW);
 	case SCSI_IOCTL_TEST_UNIT_READY:
-		scsi_cmd[0] = TEST_UNIT_READY;
-		scsi_cmd[1] = 0;
-		scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0;
-		scsi_cmd[4] = 0;
-		return ioctl_internal_command(sdev, scsi_cmd,
-				   IOCTL_NORMAL_TIMEOUT, NORMAL_RETRIES);
+		return scsi_test_unit_ready(sdev, IOCTL_NORMAL_TIMEOUT,
+					    NORMAL_RETRIES);
 	case SCSI_IOCTL_START_UNIT:
 		scsi_cmd[0] = START_STOP;
 		scsi_cmd[1] = 0;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index e30d3f2bf..ac16f21dc 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -954,6 +954,22 @@ static int scsi_init_io(struct scsi_cmnd *cmd)
 	return BLKPREP_KILL;
 }
 
+static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
+			       sector_t *error_sector)
+{
+	struct scsi_device *sdev = q->queuedata;
+	struct scsi_driver *drv;
+
+	if (sdev->sdev_state != SDEV_RUNNING)
+		return -ENXIO;
+
+	drv = *(struct scsi_driver **) disk->private_data;
+	if (drv->issue_flush)
+		return drv->issue_flush(&sdev->sdev_gendev, error_sector);
+
+	return -EOPNOTSUPP;
+}
+
 static int scsi_prep_fn(struct request_queue *q, struct request *req)
 {
 	struct scsi_device *sdev = q->queuedata;
@@ -1335,7 +1351,8 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev)
 	blk_queue_max_sectors(q, shost->max_sectors);
 	blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost));
 	blk_queue_segment_boundary(q, shost->dma_boundary);
- 
+	blk_queue_issue_flush_fn(q, scsi_issue_flush_fn);
+
 	if (!shost->use_clustering)
 		clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
 	return q;
@@ -1555,6 +1572,34 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
 	return ret;
 }
 
+int
+scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries)
+{
+	struct scsi_request *sreq;
+	char cmd[] = {
+		TEST_UNIT_READY, 0, 0, 0, 0, 0,
+	};
+	int result;
+	
+	sreq = scsi_allocate_request(sdev, GFP_KERNEL);
+	if (!sreq)
+		return -ENOMEM;
+
+		sreq->sr_data_direction = DMA_NONE;
+        scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries);
+
+	if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) &&
+	    (sreq->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION &&
+	    sdev->removable) {
+		sdev->changed = 1;
+		sreq->sr_result = 0;
+	}
+	result = sreq->sr_result;
+	scsi_release_request(sreq);
+	return result;
+}
+EXPORT_SYMBOL(scsi_test_unit_ready);
+
 /**
  *	scsi_device_set_state - Take the given device through the device
  *		state model.
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 166cb9ab3..9d4d3ce9e 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -200,7 +200,7 @@ static void print_inquiry(unsigned char *inq_result)
  *     scsi_Device pointer, or NULL on failure.
  **/
 static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost,
-	       	uint channel, uint id, uint lun)
+	       	uint channel, uint id, uint lun, void *hostdata)
 {
 	struct scsi_device *sdev, *device;
 	unsigned long flags;
@@ -224,6 +224,8 @@ static struct scsi_device *scsi_alloc_sdev(struct Scsi_Host *shost,
 	INIT_LIST_HEAD(&sdev->starved_entry);
 	spin_lock_init(&sdev->list_lock);
 
+	/* usually NULL and set by ->slave_alloc instead */
+	sdev->hostdata = hostdata;
 
 	/* if the device needs this changing, it may do so in the
 	 * slave_configure function */
@@ -697,7 +699,7 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
  **/
 static int scsi_probe_and_add_lun(struct Scsi_Host *host,
 		uint channel, uint id, uint lun, int *bflagsp,
-		struct scsi_device **sdevp, int rescan)
+		struct scsi_device **sdevp, int rescan, void *hostdata)
 {
 	struct scsi_device *sdev;
 	struct scsi_request *sreq;
@@ -726,7 +728,7 @@ static int scsi_probe_and_add_lun(struct Scsi_Host *host,
 		}
 	}
 
-	sdev = scsi_alloc_sdev(host, channel, id, lun);
+	sdev = scsi_alloc_sdev(host, channel, id, lun, hostdata);
 	if (!sdev)
 		goto out;
 	sreq = scsi_allocate_request(sdev, GFP_ATOMIC);
@@ -874,7 +876,7 @@ static void scsi_sequential_lun_scan(struct Scsi_Host *shost, uint channel,
 	 */
 	for (lun = 1; lun < max_dev_lun; ++lun)
 		if ((scsi_probe_and_add_lun(shost, channel, id, lun,
-		      NULL, NULL, rescan) != SCSI_SCAN_LUN_PRESENT) &&
+		      NULL, NULL, rescan, NULL) != SCSI_SCAN_LUN_PRESENT) &&
 		    !sparse_lun)
 			return;
 }
@@ -1085,7 +1087,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
 			int res;
 
 			res = scsi_probe_and_add_lun(sdev->host, sdev->channel,
-				sdev->id, lun, NULL, NULL, rescan);
+				sdev->id, lun, NULL, NULL, rescan, NULL);
 			if (res == SCSI_SCAN_NO_RESPONSE) {
 				/*
 				 * Got some results, but now none, abort.
@@ -1111,14 +1113,15 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags,
 	return 0;
 }
 
-struct scsi_device *scsi_add_device(struct Scsi_Host *shost,
-				    uint channel, uint id, uint lun)
+struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
+		uint id, uint lun, void *hostdata)
 {
 	struct scsi_device *sdev;
 	int res;
 
 	down(&shost->scan_mutex);
-	res = scsi_probe_and_add_lun(shost, channel, id, lun, NULL, &sdev, 1);
+	res = scsi_probe_and_add_lun(shost, channel, id, lun, NULL,
+				     &sdev, 1, hostdata);
 	if (res != SCSI_SCAN_LUN_PRESENT)
 		sdev = ERR_PTR(-ENODEV);
 	up(&shost->scan_mutex);
@@ -1178,7 +1181,7 @@ static void scsi_scan_target(struct Scsi_Host *shost, unsigned int channel,
 		 * Scan for a specific host/chan/id/lun.
 		 */
 		scsi_probe_and_add_lun(shost, channel, id, lun, NULL, NULL,
-				       rescan);
+				       rescan, NULL);
 		return;
 	}
 
@@ -1187,7 +1190,7 @@ static void scsi_scan_target(struct Scsi_Host *shost, unsigned int channel,
 	 * would not configure LUN 0 until all LUNs are scanned.
 	 */
 	res = scsi_probe_and_add_lun(shost, channel, id, 0, &bflags, &sdev,
-				     rescan);
+				     rescan, NULL);
 	if (res == SCSI_SCAN_LUN_PRESENT) {
 		if (scsi_report_lun_scan(sdev, bflags, rescan) != 0)
 			/*
@@ -1316,7 +1319,7 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
 {
 	struct scsi_device *sdev;
 
-	sdev = scsi_alloc_sdev(shost, 0, shost->this_id, 0);
+	sdev = scsi_alloc_sdev(shost, 0, shost->this_id, 0, NULL);
 	if (sdev) {
 		sdev->borken = 0;
 	}
diff --git a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c
index 9da2db4ee..37231932e 100644
--- a/drivers/scsi/scsi_syms.c
+++ b/drivers/scsi/scsi_syms.c
@@ -69,11 +69,9 @@ EXPORT_SYMBOL(scsi_track_queue_full);
 EXPORT_SYMBOL(scsi_get_host_dev);
 EXPORT_SYMBOL(scsi_free_host_dev);
 
-EXPORT_SYMBOL(scsi_sleep);
-
 EXPORT_SYMBOL(scsi_io_completion);
 
-EXPORT_SYMBOL(scsi_add_device);
+EXPORT_SYMBOL(__scsi_add_device);
 EXPORT_SYMBOL(scsi_remove_device);
 EXPORT_SYMBOL(scsi_device_cancel);
 
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index a8855d324..3c567e144 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -525,8 +525,11 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
  **/
 void scsi_remove_device(struct scsi_device *sdev)
 {
+	struct Scsi_Host *shost = sdev->host;
+
+	down(&shost->scan_mutex);
 	if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0)
-		return;
+		goto out;
 
 	class_device_unregister(&sdev->sdev_classdev);
 	if (sdev->transport_classdev.class)
@@ -538,6 +541,9 @@ void scsi_remove_device(struct scsi_device *sdev)
 	if (sdev->host->transportt->cleanup)
 		sdev->host->transportt->cleanup(sdev);
 	put_device(&sdev->sdev_gendev);
+
+out:
+	up(&shost->scan_mutex);
 }
 
 int scsi_register_driver(struct device_driver *drv)
diff --git a/drivers/scsi/scsiiom.c b/drivers/scsi/scsiiom.c
index 89b957673..bc6907943 100644
--- a/drivers/scsi/scsiiom.c
+++ b/drivers/scsi/scsiiom.c
@@ -213,8 +213,17 @@ dc390_dma_intr (struct dc390_acb* pACB)
 }
 #endif
 
+
+static void __inline__
+dc390_InvalidCmd(struct dc390_acb* pACB)
+{
+	if (pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_ | SRB_MSGOUT))
+		DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
+}
+
+
 static irqreturn_t __inline__
-DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
+DC390_Interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
     struct dc390_acb *pACB, *pACB2;
     struct dc390_dcb *pDCB;
@@ -594,7 +603,7 @@ dc390_MsgIn_reject (struct dc390_acb* pACB, struct dc390_srb* pSRB)
 }
 
 /* abort command */
-static void __inline__
+static void
 dc390_EnableMsgOut_Abort ( struct dc390_acb* pACB, struct dc390_srb* pSRB )
 {
     pSRB->MsgOutBuf[0] = ABORT; 
@@ -890,14 +899,22 @@ dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
 
     if (pSRB == pACB->pTmpSRB)
     {
-	if (pDCB) printk (KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (%02i-%i)\n",
-			  pDCB->TargetID, pDCB->TargetLUN);
-	else printk (KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (DCB 0!)\n");
-
-	pSRB->pSRBDCB = pDCB;
-	dc390_EnableMsgOut_Abort (pACB, pSRB);
-	if (pDCB) pDCB->DCBFlag |= ABORT_DEV;
-	return;
+	if (pDCB)
+		printk(KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (%02i-%i)\n", pDCB->TargetID, pDCB->TargetLUN);
+	else
+		printk(KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (DCB 0!)\n");
+
+	/* Try to recover - some broken disks react badly to tagged INQUIRY */
+	if (pDCB && pACB->scan_devices && pDCB->GoingSRBCnt == 1) {
+		pSRB = pDCB->pGoingSRB;
+		pDCB->pActiveSRB = pSRB;
+	} else {
+		pSRB->pSRBDCB = pDCB;
+		dc390_EnableMsgOut_Abort(pACB, pSRB);
+		if (pDCB)
+			pDCB->DCBFlag |= ABORT_DEV;
+		return;
+	}
     }
 
     if( pSRB->SGIndex < pSRB->SGcount )
@@ -1138,7 +1155,7 @@ dc390_Disconnect( struct dc390_acb* pACB )
      }
     DC390_write8 (ScsiCmd, EN_SEL_RESEL);
     pSRB = pDCB->pActiveSRB;
-    pACB->pActiveDCB = 0;
+    pACB->pActiveDCB = NULL;
     pSRB->ScsiPhase = SCSI_NOP0;
     if( pSRB->SRBState & SRB_UNEXPECT_RESEL )
     {
@@ -1158,7 +1175,7 @@ dc390_Disconnect( struct dc390_acb* pACB )
 	    dc390_Free_insert (pACB, pSRB);
 	    pSRB = psrb;
 	}
-	pDCB->pGoingSRB = 0;
+	pDCB->pGoingSRB = NULL;
 	dc390_Waiting_process (pACB);
     }
     else
@@ -1187,7 +1204,7 @@ dc390_Disconnect( struct dc390_acb* pACB )
 	{
 disc1:
 	    dc390_freetag (pDCB, pSRB);
-	    pDCB->pActiveSRB = 0;
+	    pDCB->pActiveSRB = NULL;
 	    pSRB->SRBState = SRB_FREE;
 	    dc390_SRBdone( pACB, pDCB, pSRB);
 	}
@@ -1325,6 +1342,35 @@ dc390_add_dev (struct dc390_acb* pACB, struct dc390_dcb* pDCB, PSCSI_INQDATA ptr
 }
 
 
+static void __inline__
+dc390_RequestSense(struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
+{
+	struct scsi_cmnd *pcmd;
+
+	pcmd = pSRB->pcmd;
+
+	REMOVABLEDEBUG(printk(KERN_INFO "DC390: RequestSense(Cmd %02x, Id %02x, LUN %02x)\n",\
+			      pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN));
+
+	pSRB->SRBFlag |= AUTO_REQSENSE;
+	pSRB->SavedSGCount = pcmd->use_sg;
+	pSRB->SavedTotXLen = pSRB->TotalXferredLen;
+	pSRB->AdaptStatus = 0;
+	pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */
+
+	/* We are called from SRBdone, original PCI mapping has been removed
+	 * already, new one is set up from StartSCSI */
+	pSRB->SGIndex = 0;
+
+	pSRB->TotalXferredLen = 0;
+	pSRB->SGToBeXferLen = 0;
+	if (dc390_StartSCSI(pACB, pDCB, pSRB)) {
+		dc390_Going_to_Waiting(pDCB, pSRB);
+		dc390_waiting_timer(pACB, HZ/5);
+	}
+}
+
+
 static void
 dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB )
 {
@@ -1352,26 +1398,7 @@ dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb*
 	pSRB->SRBFlag &= ~AUTO_REQSENSE;
 	pSRB->AdaptStatus = 0;
 	pSRB->TargetStatus = CHECK_CONDITION << 1;
-#ifdef DC390_REMOVABLEDEBUG
-	switch (pcmd->sense_buffer[2] & 0x0f)
-	{	    
-	 case NOT_READY: printk (KERN_INFO "DC390: ReqSense: NOT_READY (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
-				 pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN,
-				 status, pACB->scan_devices); break;
-	 case UNIT_ATTENTION: printk (KERN_INFO "DC390: ReqSense: UNIT_ATTENTION (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
-				      pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN,
-				      status, pACB->scan_devices); break;
-	 case ILLEGAL_REQUEST: printk (KERN_INFO "DC390: ReqSense: ILLEGAL_REQUEST (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
-				       pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN,
-				       status, pACB->scan_devices); break;
-	 case MEDIUM_ERROR: printk (KERN_INFO "DC390: ReqSense: MEDIUM_ERROR (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
-				    pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN,
-				    status, pACB->scan_devices); break;
-	 case HARDWARE_ERROR: printk (KERN_INFO "DC390: ReqSense: HARDWARE_ERROR (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n",
-				      pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN,
-				      status, pACB->scan_devices); break;
-	}
-#endif
+
 	//pcmd->result = MK_RES(DRIVER_SENSE,DID_OK,0,status);
 	if (status == (CHECK_CONDITION << 1))
 	{
@@ -1525,23 +1552,6 @@ dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb*
 	    pDCB->Inquiry7 = ptr->Flags;
 
 ckc_e:
-    if( pACB->scan_devices )
-    {
-	if( pcmd->cmnd[0] == TEST_UNIT_READY ||
-	    pcmd->cmnd[0] == INQUIRY)
-	{
-#ifdef DC390_DEBUG0
-	    printk (KERN_INFO "DC390: %s: result: %08x", 
-		    (pcmd->cmnd[0] == INQUIRY? "INQUIRY": "TEST_UNIT_READY"),
-		    pcmd->result);
-	    if (pcmd->result & (DRIVER_SENSE << 24)) printk (" (sense: %02x %02x %02x %02x)\n",
-				   pcmd->sense_buffer[0], pcmd->sense_buffer[1],
-				   pcmd->sense_buffer[2], pcmd->sense_buffer[3]);
-	    else printk ("\n");
-#endif
-	}
-    }
-
     if( pcmd->cmnd[0] == INQUIRY && 
 	(pcmd->result == (DID_OK << 16) || status_byte(pcmd->result) & CHECK_CONDITION) )
      {
@@ -1586,18 +1596,6 @@ dc390_DoingSRB_Done(struct dc390_acb* pACB, struct scsi_cmnd *cmd)
 	    psrb2 = psrb->pNextSRB;
 	    pcmd = psrb->pcmd;
 	    dc390_Free_insert (pACB, psrb);
-#ifndef USE_NEW_EH
-	    /* New EH will crash on being given timed out cmnds */
-	    if (pcmd == cmd)
-		pcmd->result = MK_RES(0,DID_ABORT,0,0);
-	    else
-		pcmd->result = MK_RES(0,DID_RESET,0,0);
-
-/*	    ReleaseSRB( pDCB, pSRB ); */
-
-	    DEBUG0(printk (KERN_DEBUG "DC390: DoingSRB_Done: done pid %li\n", pcmd->pid));
-	    pcmd->scsi_done( pcmd );
-#endif	
 	    psrb  = psrb2;
 	}
 	pdcb->GoingSRBCnt = 0;
@@ -1646,7 +1644,7 @@ dc390_ScsiRstDetect( struct dc390_acb* pACB )
 	pACB->ACBFlag |= RESET_DETECT;
 
 	dc390_ResetDevParam( pACB );
-	dc390_DoingSRB_Done( pACB, 0 );
+	dc390_DoingSRB_Done( pACB, NULL );
 	//dc390_RecoverSRB( pACB );
 	pACB->pActiveDCB = NULL;
 	pACB->ACBFlag = 0;
@@ -1654,51 +1652,3 @@ dc390_ScsiRstDetect( struct dc390_acb* pACB )
     }
     return;
 }
-
-
-static void __inline__
-dc390_RequestSense( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB )
-{
-    struct scsi_cmnd *pcmd;
-
-    pcmd = pSRB->pcmd;
-
-    REMOVABLEDEBUG(printk (KERN_INFO "DC390: RequestSense (Cmd %02x, Id %02x, LUN %02x)\n",\
-	    pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN));
-
-    pSRB->SRBFlag |= AUTO_REQSENSE;
-    //pSRB->Segment0[0] = (u32) pSRB->CmdBlock[0];
-    //pSRB->Segment0[1] = (u32) pSRB->CmdBlock[4];
-    //pSRB->Segment1[0] = ((u32)(pcmd->cmd_len) << 8) + pSRB->SGcount;
-    //pSRB->Segment1[1] = pSRB->TotalXferredLen;
-    pSRB->SavedSGCount = pcmd->use_sg;
-    pSRB->SavedTotXLen = pSRB->TotalXferredLen;
-    pSRB->AdaptStatus = 0;
-    pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */
-
-    /* We are called from SRBdone, original PCI mapping has been removed
-     * already, new one is set up from StartSCSI */
-    pSRB->SGIndex = 0;
-
-    //pSRB->CmdBlock[0] = REQUEST_SENSE;
-    //pSRB->CmdBlock[1] = pDCB->TargetLUN << 5;
-    //(u16) pSRB->CmdBlock[2] = 0;
-    //(u16) pSRB->CmdBlock[4] = sizeof(pcmd->sense_buffer);
-    //pSRB->ScsiCmdLen = 6;
-
-    pSRB->TotalXferredLen = 0;
-    pSRB->SGToBeXferLen = 0;
-    if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) {
-	dc390_Going_to_Waiting ( pDCB, pSRB );
-	dc390_waiting_timer (pACB, HZ/5);
-    }
-}
-
-
-
-static void __inline__
-dc390_InvalidCmd( struct dc390_acb* pACB )
-{
-    if( pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_+SRB_MSGOUT) )
-	DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-}
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 8fd459060..f44e96df0 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -42,6 +42,7 @@
 #include <linux/genhd.h>
 #include <linux/hdreg.h>
 #include <linux/errno.h>
+#include <linux/idr.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/blkdev.h>
@@ -62,12 +63,18 @@
 
 #include "scsi_logging.h"
 
-
 /*
- * Remaining dev_t-handling stuff
+ * More than enough for everybody ;)  The huge number of majors
+ * is a leftover from 16bit dev_t days, we don't really need that
+ * much numberspace.
  */
 #define SD_MAJORS	16
-#define SD_DISKS	32768	/* anything between 256 and 262144 */
+
+/*
+ * This is limited by the naming scheme enforced in sd_probe,
+ * add another character to it if you really need more disks.
+ */
+#define SD_MAX_DISKS	(((26 * 26) + 26 + 1) * 26)
 
 /*
  * Time out in seconds for disks and Magneto-opticals (which are slower).
@@ -96,8 +103,7 @@ struct scsi_disk {
 	unsigned	RCD : 1;	/* state of disk RCD bit, unused */
 };
 
-
-static unsigned long sd_index_bits[SD_DISKS / BITS_PER_LONG];
+static DEFINE_IDR(sd_index_idr);
 static spinlock_t sd_index_lock = SPIN_LOCK_UNLOCKED;
 
 /* This semaphore is used to mediate the 0->1 reference get in the
@@ -113,6 +119,7 @@ static int sd_remove(struct device *);
 static void sd_shutdown(struct device *dev);
 static void sd_rescan(struct device *);
 static int sd_init_command(struct scsi_cmnd *);
+static int sd_issue_flush(struct device *, sector_t *);
 static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
 		 struct scsi_request *SRpnt, unsigned char *buffer);
 
@@ -126,9 +133,11 @@ static struct scsi_driver sd_template = {
 	},
 	.rescan			= sd_rescan,
 	.init_command		= sd_init_command,
+	.issue_flush		= sd_issue_flush,
 };
 
-/* Device no to disk mapping:
+/*
+ * Device no to disk mapping:
  * 
  *       major         disc2     disc  p1
  *   |............|.............|....|....| <- dev_t
@@ -141,7 +150,6 @@ static struct scsi_driver sd_template = {
  * As we stay compatible with our numbering scheme, we can reuse 
  * the well-know SCSI majors 8, 65--71, 136--143.
  */
-
 static int sd_major(int major_idx)
 {
 	switch (major_idx) {
@@ -157,14 +165,6 @@ static int sd_major(int major_idx)
 	}
 }
 
-static unsigned int make_sd_dev(unsigned int sd_nr, unsigned int part)
-{
-	return  (part & 0xf) | ((sd_nr & 0xf) << 4) |
-		(sd_major((sd_nr & 0xf0) >> 4) << 20) | (sd_nr & 0xfff00);
-}
-
-/* reverse mapping dev -> (sd_nr, part) not currently needed */
-
 #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,kref)
 
 static inline struct scsi_disk *scsi_disk(struct gendisk *disk)
@@ -180,16 +180,14 @@ static struct scsi_disk *scsi_disk_get(struct gendisk *disk)
 	if (disk->private_data == NULL)
 		goto out;
 	sdkp = scsi_disk(disk);
-	if (!kref_get(&sdkp->kref))
-		goto out_sdkp;
+	kref_get(&sdkp->kref);
 	if (scsi_device_get(sdkp->device))
 		goto out_put;
 	up(&sd_ref_sem);
 	return sdkp;
 
  out_put:
-	kref_put(&sdkp->kref);
- out_sdkp:
+	kref_put(&sdkp->kref, scsi_disk_release);
 	sdkp = NULL;
  out:
 	up(&sd_ref_sem);
@@ -200,7 +198,7 @@ static void scsi_disk_put(struct scsi_disk *sdkp)
 {
 	down(&sd_ref_sem);
 	scsi_device_put(sdkp->device);
-	kref_put(&sdkp->kref);
+	kref_put(&sdkp->kref, scsi_disk_release);
 	up(&sd_ref_sem);
 }
 
@@ -648,7 +646,7 @@ static int sd_media_changed(struct gendisk *disk)
 	 */
 	retval = -ENODEV;
 	if (scsi_block_when_processing_errors(sdp))
-		retval = scsi_ioctl(sdp, SCSI_IOCTL_TEST_UNIT_READY, NULL);
+		retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES);
 
 	/*
 	 * Unable to test, unit probably not ready.   This usually
@@ -676,6 +674,62 @@ not_present:
 	return 1;
 }
 
+static int sd_sync_cache(struct scsi_device *sdp)
+{
+	struct scsi_request *sreq;
+	int retries, res;
+
+	if (!scsi_device_online(sdp))
+		return -ENODEV;
+
+	sreq = scsi_allocate_request(sdp, GFP_KERNEL);
+	if (!sreq) {
+		printk("FAILED\n  No memory for request\n");
+		return -ENOMEM;
+	}
+
+	sreq->sr_data_direction = DMA_NONE;
+	for (retries = 3; retries > 0; --retries) {
+		unsigned char cmd[10] = { 0 };
+
+		cmd[0] = SYNCHRONIZE_CACHE;
+		/*
+		 * Leave the rest of the command zero to indicate
+		 * flush everything.
+		 */
+		scsi_wait_req(sreq, cmd, NULL, 0, SD_TIMEOUT, SD_MAX_RETRIES);
+		if (sreq->sr_result == 0)
+			break;
+	}
+
+	res = sreq->sr_result;
+	if (res) {
+		printk(KERN_WARNING "FAILED\n  status = %x, message = %02x, "
+				    "host = %d, driver = %02x\n  ",
+				    status_byte(res), msg_byte(res),
+				    host_byte(res), driver_byte(res));
+			if (driver_byte(res) & DRIVER_SENSE)
+				scsi_print_req_sense("sd", sreq);
+	}
+
+	scsi_release_request(sreq);
+	return res;
+}
+
+static int sd_issue_flush(struct device *dev, sector_t *error_sector)
+{
+	struct scsi_device *sdp = to_scsi_device(dev);
+	struct scsi_disk *sdkp = dev_get_drvdata(dev);
+
+	if (!sdkp)
+               return -ENODEV;
+
+	if (!sdkp->WCE)
+		return 0;
+
+	return sd_sync_cache(sdp);
+}
+
 static void sd_rescan(struct device *dev)
 {
 	struct scsi_disk *sdkp = dev_get_drvdata(dev);
@@ -1347,7 +1401,7 @@ static int sd_probe(struct device *dev)
 	struct scsi_disk *sdkp;
 	struct gendisk *gd;
 	u32 index;
-	int error, devno;
+	int error;
 
 	error = -ENODEV;
 	if ((sdp->type != TYPE_DISK) && (sdp->type != TYPE_MOD))
@@ -1362,27 +1416,23 @@ static int sd_probe(struct device *dev)
 		goto out;
 
 	memset (sdkp, 0, sizeof(*sdkp));
-	kref_init(&sdkp->kref, scsi_disk_release);
-
-	/* Note: We can accomodate 64 partitions, but the genhd code
-	 * assumes partitions allocate consecutive minors, which they don't.
-	 * So for now stay with max 16 partitions and leave two spare bits. 
-	 * Later, we may change the genhd code and the alloc_disk() call
-	 * and the ->minors assignment here. 	KG, 2004-02-10
-	 */ 
+	kref_init(&sdkp->kref);
+
 	gd = alloc_disk(16);
 	if (!gd)
 		goto out_free;
 
+	if (!idr_pre_get(&sd_index_idr, GFP_KERNEL))
+		goto out_put;
+
 	spin_lock(&sd_index_lock);
-	index = find_first_zero_bit(sd_index_bits, SD_DISKS);
-	if (index == SD_DISKS) {
-		spin_unlock(&sd_index_lock);
+	error = idr_get_new(&sd_index_idr, NULL, &index);
+	spin_unlock(&sd_index_lock);
+
+	if (index >= SD_MAX_DISKS)
 		error = -EBUSY;
+	if (error)
 		goto out_put;
-	}
-	__set_bit(index, sd_index_bits);
-	spin_unlock(&sd_index_lock);
 
 	sdkp->device = sdp;
 	sdkp->driver = &sd_template;
@@ -1397,15 +1447,14 @@ static int sd_probe(struct device *dev)
 			sdp->timeout = SD_MOD_TIMEOUT;
 	}
 
-	devno = make_sd_dev(index, 0);
-	gd->major = MAJOR(devno);
-	gd->first_minor = MINOR(devno);
+	gd->major = sd_major((index & 0xf0) >> 4);
+	gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
 	gd->minors = 16;
 	gd->fops = &sd_fops;
 
 	if (index < 26) {
 		sprintf(gd->disk_name, "sd%c", 'a' + index % 26);
-	} else if (index < (26*27)) {
+	} else if (index < (26 + 1) * 26) {
 		sprintf(gd->disk_name, "sd%c%c",
 			'a' + index / 26 - 1,'a' + index % 26);
 	} else {
@@ -1464,7 +1513,7 @@ static int sd_remove(struct device *dev)
 	del_gendisk(sdkp->disk);
 	sd_shutdown(dev);
 	down(&sd_ref_sem);
-	kref_put(&sdkp->kref);
+	kref_put(&sdkp->kref, scsi_disk_release);
 	up(&sd_ref_sem);
 
 	return 0;
@@ -1485,7 +1534,7 @@ static void scsi_disk_release(struct kref *kref)
 	struct gendisk *disk = sdkp->disk;
 	
 	spin_lock(&sd_index_lock);
-	clear_bit(sdkp->index, sd_index_bits);
+	idr_remove(&sd_index_idr, sdkp->index);
 	spin_unlock(&sd_index_lock);
 
 	disk->private_data = NULL;
@@ -1503,52 +1552,17 @@ static void scsi_disk_release(struct kref *kref)
 static void sd_shutdown(struct device *dev)
 {
 	struct scsi_device *sdp = to_scsi_device(dev);
-	struct scsi_disk *sdkp;
-	struct scsi_request *sreq;
-	int retries, res;
+	struct scsi_disk *sdkp = dev_get_drvdata(dev);
 
-	sdkp = dev_get_drvdata(dev);
 	if (!sdkp)
-               return;         /* this can happen */
+		return;         /* this can happen */
 
-	if (!scsi_device_online(sdp) || !sdkp->WCE)
+	if (!sdkp->WCE)
 		return;
 
-	printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: ",
+	printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: \n",
 			sdkp->disk->disk_name);
-
-	sreq = scsi_allocate_request(sdp, GFP_KERNEL);
-	if (!sreq) {
-		printk("FAILED\n  No memory for request\n");
-		return;
-	}
-
-	sreq->sr_data_direction = DMA_NONE;
-	for (retries = 3; retries > 0; --retries) {
-		unsigned char cmd[10] = { 0 };
-
-		cmd[0] = SYNCHRONIZE_CACHE;
-		/*
-		 * Leave the rest of the command zero to indicate
-		 * flush everything.
-		 */
-		scsi_wait_req(sreq, cmd, NULL, 0, SD_TIMEOUT, SD_MAX_RETRIES);
-		if (sreq->sr_result == 0)
-			break;
-	}
-
-	res = sreq->sr_result;
-	if (res) {
-		printk(KERN_WARNING "FAILED\n  status = %x, message = %02x, "
-				    "host = %d, driver = %02x\n  ",
-				    status_byte(res), msg_byte(res),
-				    host_byte(res), driver_byte(res));
-			if (driver_byte(res) & DRIVER_SENSE)
-				scsi_print_req_sense("sd", sreq);
-	}
-	
-	scsi_release_request(sreq);
-	printk("\n");
+	sd_sync_cache(sdp);
 }	
 
 /**
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 7b0665d8b..ed80392b0 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -47,8 +47,9 @@ static int sg_version_num = 30531;	/* 2 digits for each component */
 #include <linux/devfs_fs_kernel.h>
 #include <linux/cdev.h>
 #include <linux/seq_file.h>
-
 #include <linux/blkdev.h>
+#include <linux/delay.h>
+
 #include "scsi.h"
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_driver.h>
@@ -205,8 +206,6 @@ static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id);
 static Sg_request *sg_add_request(Sg_fd * sfp);
 static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
 static int sg_res_in_use(Sg_fd * sfp);
-static int sg_ms_to_jif(unsigned int msecs);
-static inline unsigned sg_jif_to_ms(int jifs);
 static int sg_allow_access(unsigned char opcode, char dev_type);
 static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len);
 static Sg_device *sg_get_dev(int dev);
@@ -611,7 +610,7 @@ sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count,
 			return -EBUSY;	/* reserve buffer already being used */
 		}
 	}
-	timeout = sg_ms_to_jif(srp->header.timeout);
+	timeout = msecs_to_jiffies(srp->header.timeout);
 	if ((!hp->cmdp) || (hp->cmd_len < 6) || (hp->cmd_len > sizeof (cmnd))) {
 		sg_remove_request(sfp, srp);
 		return -EMSGSIZE;
@@ -719,19 +718,6 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
 	return 0;
 }
 
-static inline unsigned
-sg_jif_to_ms(int jifs)
-{
-	if (jifs <= 0)
-		return 0U;
-	else {
-		unsigned int j = (unsigned int) jifs;
-		return (j <
-			(UINT_MAX / 1000)) ? ((j * 1000) / HZ) : ((j / HZ) *
-								  1000);
-	}
-}
-
 static int
 sg_ioctl(struct inode *inode, struct file *filp,
 	 unsigned int cmd_in, unsigned long arg)
@@ -941,7 +927,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
 					    srp->header.driver_status;
 					rinfo[val].duration =
 					    srp->done ? srp->header.duration :
-					    sg_jif_to_ms(
+					    jiffies_to_msecs(
 						jiffies - srp->header.duration);
 					rinfo[val].orphan = srp->orphan;
 					rinfo[val].sg_io_owned = srp->sg_io_owned;
@@ -1263,7 +1249,7 @@ sg_cmd_done(Scsi_Cmnd * SCpnt)
 	srp->header.resid = SCpnt->resid;
 	/* N.B. unit of duration changes here from jiffies to millisecs */
 	srp->header.duration =
-	    sg_jif_to_ms(jiffies - (int) srp->header.duration);
+	    jiffies_to_msecs(jiffies - srp->header.duration);
 	if (0 != SRpnt->sr_result) {
 		memcpy(srp->sense_b, SRpnt->sr_sense_buffer,
 		       sizeof (srp->sense_b));
@@ -1547,7 +1533,7 @@ sg_remove(struct class_device *cl_dev)
 	}
 
 	if (delay)
-		scsi_sleep(2);	/* dirty detach so delay device destruction */
+		msleep(10);	/* dirty detach so delay device destruction */
 }
 
 /* Set 'perm' (4th argument) to 0 to disable module_param's definition
@@ -2587,17 +2573,6 @@ sg_page_free(char *buff, int size)
 	free_pages((unsigned long) buff, order);
 }
 
-static int
-sg_ms_to_jif(unsigned int msecs)
-{
-	if ((UINT_MAX / 2U) < msecs)
-		return INT_MAX;	/* special case, set largest possible */
-	else
-		return ((int) msecs <
-			(INT_MAX / 1000)) ? (((int) msecs * HZ) / 1000)
-		    : (((int) msecs / 1000) * HZ);
-}
-
 static unsigned char allow_ops[] = { TEST_UNIT_READY, REQUEST_SENSE,
 	INQUIRY, READ_CAPACITY, READ_BUFFER, READ_6, READ_10, READ_12,
 	MODE_SENSE, MODE_SENSE_10, LOG_SENSE
@@ -2960,7 +2935,7 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
 	for (k = 0; (fp = sg_get_nth_sfp(sdp, k)); ++k) {
 		seq_printf(s, "   FD(%d): timeout=%dms bufflen=%d "
 			   "(res)sgat=%d low_dma=%d\n", k + 1,
-			   sg_jif_to_ms(fp->timeout),
+			   jiffies_to_msecs(fp->timeout),
 			   fp->reserve.bufflen,
 			   (int) fp->reserve.k_use_sg,
 			   (int) fp->low_dma);
@@ -2996,8 +2971,8 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
 				seq_printf(s, " dur=%d", hp->duration);
 			else
 				seq_printf(s, " t_o/elap=%d/%d",
-				  new_interface ? hp->timeout : sg_jif_to_ms(fp->timeout),
-				  sg_jif_to_ms(hp->duration ? (jiffies - hp->duration) : 0));
+				  new_interface ? hp->timeout : jiffies_to_msecs(fp->timeout),
+				  jiffies_to_msecs(hp->duration ? (jiffies - hp->duration) : 0));
 			seq_printf(s, "ms sgat=%d op=0x%02x\n", usg,
 				   (int) srp->data.cmd_opcode);
 		}
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index b80aa283c..b6c76b568 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -140,15 +140,13 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk *disk)
 	if (disk->private_data == NULL)
 		goto out;
 	cd = scsi_cd(disk);
-	if (!kref_get(&cd->kref))
-		goto out_null;
+	kref_get(&cd->kref);
 	if (scsi_device_get(cd->device))
 		goto out_put;
 	goto out;
 
  out_put:
-	kref_put(&cd->kref);
- out_null:
+	kref_put(&cd->kref, sr_kref_release);
 	cd = NULL;
  out:
 	up(&sr_ref_sem);
@@ -159,7 +157,7 @@ static inline void scsi_cd_put(struct scsi_cd *cd)
 {
 	down(&sr_ref_sem);
 	scsi_device_put(cd->device);
-	kref_put(&cd->kref);
+	kref_put(&cd->kref, sr_kref_release);
 	up(&sr_ref_sem);
 }
 
@@ -183,7 +181,7 @@ int sr_media_change(struct cdrom_device_info *cdi, int slot)
 		return -EINVAL;
 	}
 
-	retval = scsi_ioctl(cd->device, SCSI_IOCTL_TEST_UNIT_READY, NULL);
+	retval = scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES);
 	if (retval) {
 		/* Unable to test, unit probably not ready.  This usually
 		 * means there is no disc in the drive.  Mark as changed,
@@ -576,7 +574,7 @@ static int sr_probe(struct device *dev)
 		goto fail;
 	memset(cd, 0, sizeof(*cd));
 
-	kref_init(&cd->kref, sr_kref_release);
+	kref_init(&cd->kref);
 
 	disk = alloc_disk(1);
 	if (!disk)
@@ -937,7 +935,7 @@ static int sr_remove(struct device *dev)
 	del_gendisk(cd->disk);
 
 	down(&sr_ref_sem);
-	kref_put(&cd->kref);
+	kref_put(&cd->kref, sr_kref_release);
 	up(&sr_ref_sem);
 
 	return 0;
diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c
index 7d24b57c2..1ddb5f27a 100644
--- a/drivers/scsi/sr_ioctl.c
+++ b/drivers/scsi/sr_ioctl.c
@@ -7,6 +7,7 @@
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
 #include <linux/cdrom.h>
+#include <linux/delay.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
@@ -131,7 +132,7 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc)
 					printk(KERN_INFO "%s: CDROM not ready yet.\n", cd->cdi.name);
 				if (retries++ < 10) {
 					/* sleep 2 sec and try again */
-					scsi_sleep(2 * HZ);
+					ssleep(2);
 					goto retry;
 				} else {
 					/* 20 secs are enough? */
diff --git a/drivers/scsi/sym53c8xx_2/sym_defs.h b/drivers/scsi/sym53c8xx_2/sym_defs.h
index 1241104b6..09f861a03 100644
--- a/drivers/scsi/sym53c8xx_2/sym_defs.h
+++ b/drivers/scsi/sym53c8xx_2/sym_defs.h
@@ -53,6 +53,9 @@
 #ifndef SYM_DEFS_H
 #define SYM_DEFS_H
 
+#define SYM_VERSION "2.1.18j"
+#define SYM_DRIVER_NAME	"sym-" SYM_VERSION
+
 /*
  *  Vendor.
  */
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 22238315d..0d9d1b42b 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -142,13 +142,6 @@ m_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m)
 	return b;
 }
 
-/*
- *  Driver host data structure.
- */
-struct host_data {
-	struct sym_hcb *ncb;
-};
-
 /*
  *  Used by the eh thread to wait for command completion.
  *  It is allocated on the eh thread stack.
@@ -220,47 +213,12 @@ static int __map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
 	return use_sg;
 }
 
-static void __sync_scsi_data_for_cpu(struct pci_dev *pdev, struct scsi_cmnd *cmd)
-{
-	int dma_dir = cmd->sc_data_direction;
-
-	switch(SYM_UCMD_PTR(cmd)->data_mapped) {
-	case 2:
-		pci_dma_sync_sg_for_cpu(pdev, cmd->buffer, cmd->use_sg, dma_dir);
-		break;
-	case 1:
-		pci_dma_sync_single_for_cpu(pdev, SYM_UCMD_PTR(cmd)->data_mapping,
-					    cmd->request_bufflen, dma_dir);
-		break;
-	}
-}
-
-static void __sync_scsi_data_for_device(struct pci_dev *pdev, struct scsi_cmnd *cmd)
-{
-	int dma_dir = cmd->sc_data_direction;
-
-	switch(SYM_UCMD_PTR(cmd)->data_mapped) {
-	case 2:
-		pci_dma_sync_sg_for_device(pdev, cmd->buffer, cmd->use_sg, dma_dir);
-		break;
-	case 1:
-		pci_dma_sync_single_for_device(pdev, SYM_UCMD_PTR(cmd)->data_mapping,
-					       cmd->request_bufflen, dma_dir);
-		break;
-	}
-}
-
 #define unmap_scsi_data(np, cmd)	\
 		__unmap_scsi_data(np->s.device, cmd)
 #define map_scsi_single_data(np, cmd)	\
 		__map_scsi_single_data(np->s.device, cmd)
 #define map_scsi_sg_data(np, cmd)	\
 		__map_scsi_sg_data(np->s.device, cmd)
-#define sync_scsi_data_for_cpu(np, cmd)		\
-		__sync_scsi_data_for_cpu(np->s.device, cmd)
-#define sync_scsi_data_for_device(np, cmd)		\
-		__sync_scsi_data_for_device(np->s.device, cmd)
-
 /*
  *  Complete a pending CAM CCB.
  */
@@ -416,27 +374,6 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
 }
 
 
-/*
- *  Called on successfull INQUIRY response.
- */
-void sym_sniff_inquiry(struct sym_hcb *np, struct scsi_cmnd *cmd, int resid)
-{
-	int retv;
-
-	if (!cmd || cmd->use_sg)
-		return;
-
-	sync_scsi_data_for_cpu(np, cmd);
-	retv = __sym_sniff_inquiry(np, cmd->device->id, cmd->device->lun,
-				   (u_char *) cmd->request_buffer,
-				   cmd->request_bufflen - resid);
-	sync_scsi_data_for_device(np, cmd);
-	if (retv < 0)
-		return;
-	else if (retv)
-		sym_update_trans_settings(np, &np->target[cmd->device->id]);
-}
-
 /*
  *  Build the scatter/gather array for an I/O.
  */
@@ -730,14 +667,15 @@ void sym_log_bus_error(struct sym_hcb *np)
  */
 static void sym_requeue_awaiting_cmds(struct sym_hcb *np)
 {
-	struct scsi_cmnd *cmd;
-	struct sym_ucmd *ucp = SYM_UCMD_PTR(cmd);
+	struct sym_ucmd *ucp;
 	SYM_QUEHEAD tmp_cmdq;
 	int sts;
 
 	sym_que_move(&np->s.wait_cmdq, &tmp_cmdq);
 
 	while ((ucp = (struct sym_ucmd *) sym_remque_head(&tmp_cmdq)) != 0) {
+		struct scsi_cmnd *cmd;
+
 		sym_insque_tail(&ucp->link_cmdq, &np->s.busy_cmdq);
 		cmd = SYM_SCMD_PTR(ucp);
 		sts = sym_queue_command(np, cmd);
@@ -1118,12 +1056,7 @@ static int sym53c8xx_slave_configure(struct scsi_device *device)
 
 	np = ((struct host_data *) host->hostdata)->ncb;
 	tp = &np->target[device->id];
-
-	/*
-	 *  Get user settings for transfer parameters.
-	 */
-	tp->inq_byte7_valid = (INQ7_SYNC|INQ7_WIDE16);
-	sym_update_trans_settings(np, tp);
+	tp->sdev = device;
 
 	/*
 	 *  Allocate the LCB if not yet.
@@ -2283,6 +2216,7 @@ static int sym_detach(struct sym_hcb *np)
 }
 
 MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(SYM_VERSION);
 
 /*
  * Driver host template.
@@ -2383,13 +2317,6 @@ static void sym2_set_offset(struct scsi_device *sdev, int offset)
 	struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
 	struct sym_tcb *tp = &np->target[sdev->id];
 
-	if (tp->tinfo.curr.options & PPR_OPT_DT) {
-		if (offset > np->maxoffs_dt)
-			offset = np->maxoffs_dt;
-	} else {
-		if (offset > np->maxoffs)
-			offset = np->maxoffs;
-	}
 	tp->tinfo.goal.offset = offset;
 }
 
@@ -2407,23 +2334,11 @@ static void sym2_set_period(struct scsi_device *sdev, int period)
 	struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
 	struct sym_tcb *tp = &np->target[sdev->id];
 
-	if (period <= 9 && np->minsync_dt) {
-		if (period < np->minsync_dt)
-			period = np->minsync_dt;
-		tp->tinfo.goal.options = PPR_OPT_DT;
-		tp->tinfo.goal.period = period;
-		if (!tp->tinfo.curr.offset ||
-					tp->tinfo.curr.offset > np->maxoffs_dt)
-			tp->tinfo.goal.offset = np->maxoffs_dt;
-	} else {
-		if (period < np->minsync)
-			period = np->minsync;
-		tp->tinfo.goal.options = 0;
-		tp->tinfo.goal.period = period;
-		if (!tp->tinfo.curr.offset ||
-					tp->tinfo.curr.offset > np->maxoffs)
-			tp->tinfo.goal.offset = np->maxoffs;
-	}
+	/* have to have DT for these transfers */
+	if (period <= np->minsync)
+		tp->tinfo.goal.options |= PPR_OPT_DT;
+
+	tp->tinfo.goal.period = period;
 }
 
 static void sym2_get_width(struct scsi_device *sdev)
@@ -2439,6 +2354,10 @@ static void sym2_set_width(struct scsi_device *sdev, int width)
 	struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
 	struct sym_tcb *tp = &np->target[sdev->id];
 
+	/* It is illegal to have DT set on narrow transfers */
+	if (width == 0)
+		tp->tinfo.goal.options &= ~PPR_OPT_DT;
+
 	tp->tinfo.goal.width = width;
 }
 
@@ -2455,17 +2374,10 @@ static void sym2_set_dt(struct scsi_device *sdev, int dt)
 	struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
 	struct sym_tcb *tp = &np->target[sdev->id];
 
-	if (!dt) {
-		/* if clearing DT, then we may need to reduce the
-		 * period and the offset */
-		if (tp->tinfo.curr.period < np->minsync)
-			tp->tinfo.goal.period = np->minsync;
-		if (tp->tinfo.curr.offset > np->maxoffs)
-			tp->tinfo.goal.offset = np->maxoffs;
-		tp->tinfo.goal.options &= ~PPR_OPT_DT;
-	} else {
+	if (dt)
 		tp->tinfo.goal.options |= PPR_OPT_DT;
-	}
+	else
+		tp->tinfo.goal.options &= ~PPR_OPT_DT;
 }
 	
 
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h
index 60d48b750..5dd15fc0f 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.h
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.h
@@ -90,7 +90,6 @@
 #define SYM_OPT_HANDLE_DIR_UNKNOWN
 #define SYM_OPT_HANDLE_DEVICE_QUEUEING
 #define SYM_OPT_NVRAM_PRE_READ
-#define SYM_OPT_SNIFF_INQUIRY
 #define SYM_OPT_LIMIT_COMMAND_REORDERING
 #define	SYM_OPT_ANNOUNCE_TRANSFER_RATE
 
@@ -289,32 +288,32 @@ typedef struct scsi_cmnd *cam_scsiio_p;/* SCSI I/O */
  *  MEMORY mapped IO input / output
  */
 
-#define INB_OFF(o)        readb((char *)np->s.mmio_va + sym_offb(o))
-#define OUTB_OFF(o, val)  writeb((val), (char *)np->s.mmio_va + sym_offb(o))
+#define INB_OFF(o)        readb(np->s.mmio_va + sym_offb(o))
+#define OUTB_OFF(o, val)  writeb((val), np->s.mmio_va + sym_offb(o))
 
 #if	defined(__BIG_ENDIAN) && !defined(SYM_CONF_CHIP_BIG_ENDIAN)
 
-#define INW_OFF(o)        readw_l2b((char *)np->s.mmio_va + sym_offw(o))
-#define INL_OFF(o)        readl_l2b((char *)np->s.mmio_va + (o))
+#define INW_OFF(o)        readw_l2b(np->s.mmio_va + sym_offw(o))
+#define INL_OFF(o)        readl_l2b(np->s.mmio_va + (o))
 
-#define OUTW_OFF(o, val)  writew_b2l((val), (char *)np->s.mmio_va + sym_offw(o))
-#define OUTL_OFF(o, val)  writel_b2l((val), (char *)np->s.mmio_va + (o))
+#define OUTW_OFF(o, val)  writew_b2l((val), np->s.mmio_va + sym_offw(o))
+#define OUTL_OFF(o, val)  writel_b2l((val), np->s.mmio_va + (o))
 
 #elif	defined(__LITTLE_ENDIAN) && defined(SYM_CONF_CHIP_BIG_ENDIAN)
 
-#define INW_OFF(o)        readw_b2l((char *)np->s.mmio_va + sym_offw(o))
-#define INL_OFF(o)        readl_b2l((char *)np->s.mmio_va + (o))
+#define INW_OFF(o)        readw_b2l(np->s.mmio_va + sym_offw(o))
+#define INL_OFF(o)        readl_b2l(np->s.mmio_va + (o))
 
-#define OUTW_OFF(o, val)  writew_l2b((val), (char *)np->s.mmio_va + sym_offw(o))
-#define OUTL_OFF(o, val)  writel_l2b((val), (char *)np->s.mmio_va + (o))
+#define OUTW_OFF(o, val)  writew_l2b((val), np->s.mmio_va + sym_offw(o))
+#define OUTL_OFF(o, val)  writel_l2b((val), np->s.mmio_va + (o))
 
 #else
 
-#define INW_OFF(o)        readw_raw((char *)np->s.mmio_va + sym_offw(o))
-#define INL_OFF(o)        readl_raw((char *)np->s.mmio_va + (o))
+#define INW_OFF(o)        readw_raw(np->s.mmio_va + sym_offw(o))
+#define INL_OFF(o)        readl_raw(np->s.mmio_va + (o))
 
-#define OUTW_OFF(o, val)  writew_raw((val), (char *)np->s.mmio_va + sym_offw(o))
-#define OUTL_OFF(o, val)  writel_raw((val), (char *)np->s.mmio_va + (o))
+#define OUTW_OFF(o, val)  writew_raw((val), np->s.mmio_va + sym_offw(o))
+#define OUTL_OFF(o, val)  writel_raw((val), np->s.mmio_va + (o))
 
 #endif
 
@@ -391,8 +390,8 @@ struct sym_shcb {
 
 	struct Scsi_Host *host;
 
-	void *		mmio_va;	/* MMIO kernel virtual address	*/
-	void *		ram_va;		/* RAM  kernel virtual address	*/
+	void __iomem *	mmio_va;	/* MMIO kernel virtual address	*/
+	void __iomem *	ram_va;		/* RAM  kernel virtual address	*/
 	u_long		io_port;	/* IO port address cookie	*/
 	u_short		io_ws;		/* IO window size		*/
 	int		irq;		/* IRQ number			*/
@@ -424,7 +423,7 @@ struct sym_slot {
 	int	irq;
 /* port and address fields to fit INB, OUTB macros */
 	u_long	io_port;
-	void *	mmio_va;
+	void __iomem *	mmio_va;
 	char	inst_name[16];
 };
 
@@ -439,6 +438,13 @@ struct sym_device {
 	u_char host_id;
 };
 
+/*
+ *  Driver host data structure.
+ */
+struct host_data {
+	struct sym_hcb *ncb;
+};
+
 /*
  *  The driver definitions (sym_hipd.h) must know about a 
  *  couple of things related to the memory allocator.
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index 25a27f998..dddf88b87 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -49,10 +49,6 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-
-#define SYM_VERSION "2.1.18j"
-#define SYM_DRIVER_NAME	"sym-" SYM_VERSION
-
 #include "sym_glue.h"
 #include "sym_nvram.h"
 
@@ -1042,28 +1038,11 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
 	for (i = 0 ; i < SYM_CONF_MAX_TARGET ; i++) {
 		tcb_p tp = &np->target[i];
 
-		tp->tinfo.user.scsi_version = tp->tinfo.curr.scsi_version= 2;
-		tp->tinfo.user.spi_version  = tp->tinfo.curr.spi_version = 2;
-		tp->tinfo.user.period = np->minsync;
-		tp->tinfo.user.offset = np->maxoffs;
-		tp->tinfo.user.width  = np->maxwide ? BUS_16_BIT : BUS_8_BIT;
 		tp->usrflags |= (SYM_DISC_ENABLED | SYM_TAGS_ENABLED);
 		tp->usrtags = SYM_SETUP_MAX_TAG;
 
 		sym_nvram_setup_target (np, i, nvram);
 
-		/*
-		 * Some single-ended devices may crash on receiving a
-		 * PPR negotiation attempt.  Only try PPR if we're in
-		 * LVD mode.
-		 */
-		if (np->features & FE_ULTRA3) {
-			tp->tinfo.user.options |= PPR_OPT_DT;
-			tp->tinfo.user.period = np->minsync_dt;
-			tp->tinfo.user.offset = np->maxoffs_dt;
-			tp->tinfo.user.spi_version = 3;
-		}
-
 		if (!tp->usrtags)
 			tp->usrflags &= ~SYM_TAGS_ENABLED;
 	}
@@ -1497,6 +1476,55 @@ static void sym_update_dmap_regs(hcb_p np)
 }
 #endif
 
+static void sym_check_goals(struct scsi_device *sdev)
+{
+	struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
+	struct sym_trans *st = &np->target[sdev->id].tinfo.goal;
+
+	/* here we enforce all the fiddly SPI rules */
+
+	if (!scsi_device_wide(sdev))
+		st->width = 0;
+
+	if (!scsi_device_sync(sdev)) {
+		st->options = 0;
+		st->period = 0;
+		st->offset = 0;
+		return;
+	}
+		
+	if (scsi_device_dt(sdev)) {
+		if (scsi_device_dt_only(sdev))
+			st->options |= PPR_OPT_DT;
+
+		if (st->offset == 0)
+			st->options &= ~PPR_OPT_DT;
+	} else {
+		st->options &= ~PPR_OPT_DT;
+	}
+
+	if (!(np->features & FE_ULTRA3))
+		st->options &= ~PPR_OPT_DT;
+
+	if (st->options & PPR_OPT_DT) {
+		/* all DT transfers must be wide */
+		st->width = 1;
+		if (st->offset > np->maxoffs_dt)
+			st->offset = np->maxoffs_dt;
+		if (st->period < np->minsync_dt)
+			st->period = np->minsync_dt;
+		if (st->period > np->maxsync_dt)
+			st->period = np->maxsync_dt;
+	} else {
+		if (st->offset > np->maxoffs)
+			st->offset = np->maxoffs;
+		if (st->period < np->minsync)
+			st->period = np->minsync;
+		if (st->period > np->maxsync)
+			st->period = np->maxsync;
+	}
+}		
+
 /*
  *  Prepare the next negotiation message if needed.
  *
@@ -1508,6 +1536,10 @@ static int sym_prepare_nego(hcb_p np, ccb_p cp, int nego, u_char *msgptr)
 {
 	tcb_p tp = &np->target[cp->target];
 	int msglen = 0;
+	struct scsi_device *sdev = tp->sdev;
+
+	if (likely(sdev))
+		sym_check_goals(sdev);
 
 	/*
 	 *  Early C1010 chips need a work-around for DT 
@@ -1518,19 +1550,21 @@ static int sym_prepare_nego(hcb_p np, ccb_p cp, int nego, u_char *msgptr)
 	/*
 	 *  negotiate using PPR ?
 	 */
-	if (tp->tinfo.goal.options & PPR_OPT_MASK)
+	if (scsi_device_dt(sdev)) {
 		nego = NS_PPR;
-	/*
-	 *  negotiate wide transfers ?
-	 */
-	else if (tp->tinfo.curr.width != tp->tinfo.goal.width)
-		nego = NS_WIDE;
-	/*
-	 *  negotiate synchronous transfers?
-	 */
-	else if (tp->tinfo.curr.period != tp->tinfo.goal.period ||
-		 tp->tinfo.curr.offset != tp->tinfo.goal.offset)
-		nego = NS_SYNC;
+	} else {
+		/*
+		 *  negotiate wide transfers ?
+		 */
+		if (tp->tinfo.curr.width != tp->tinfo.goal.width)
+			nego = NS_WIDE;
+		/*
+		 *  negotiate synchronous transfers?
+		 */
+		else if (tp->tinfo.curr.period != tp->tinfo.goal.period ||
+			 tp->tinfo.curr.offset != tp->tinfo.goal.offset)
+			nego = NS_SYNC;
+	}
 
 	switch (nego) {
 	case NS_SYNC:
@@ -3999,7 +4033,6 @@ int sym_compute_residual(hcb_p np, ccb_p cp)
 static int  
 sym_sync_nego_check(hcb_p np, int req, int target)
 {
-	tcb_p tp = &np->target[target];
 	u_char	chg, ofs, per, fak, div;
 
 	if (DEBUG_FLAGS & DEBUG_NEGO) {
@@ -4019,19 +4052,11 @@ sym_sync_nego_check(hcb_p np, int req, int target)
 	if (ofs) {
 		if (ofs > np->maxoffs)
 			{chg = 1; ofs = np->maxoffs;}
-		if (req) {
-			if (ofs > tp->tinfo.user.offset)
-				{chg = 1; ofs = tp->tinfo.user.offset;}
-		}
 	}
 
 	if (ofs) {
 		if (per < np->minsync)
 			{chg = 1; per = np->minsync;}
-		if (req) {
-			if (per < tp->tinfo.user.period)
-				{chg = 1; per = tp->tinfo.user.period;}
-		}
 	}
 
 	/*
@@ -4151,10 +4176,6 @@ sym_ppr_nego_check(hcb_p np, int req, int target)
 	}
 	if (!wide || !(np->features & FE_ULTRA3))
 		dt &= ~PPR_OPT_DT;
-	if (req) {
-		if (wide > tp->tinfo.user.width)
-			{chg = 1; wide = tp->tinfo.user.width;}
-	}
 
 	if (!(np->features & FE_U3EN))	/* Broken U3EN bit not supported */
 		dt &= ~PPR_OPT_DT;
@@ -4168,10 +4189,6 @@ sym_ppr_nego_check(hcb_p np, int req, int target)
 		}
 		else if (ofs > np->maxoffs)
 			{chg = 1; ofs = np->maxoffs;}
-		if (req) {
-			if (ofs > tp->tinfo.user.offset)
-				{chg = 1; ofs = tp->tinfo.user.offset;}
-		}
 	}
 
 	if (ofs) {
@@ -4181,10 +4198,6 @@ sym_ppr_nego_check(hcb_p np, int req, int target)
 		}
 		else if (per < np->minsync)
 			{chg = 1; per = np->minsync;}
-		if (req) {
-			if (per < tp->tinfo.user.period)
-				{chg = 1; per = tp->tinfo.user.period;}
-		}
 	}
 
 	/*
@@ -4286,7 +4299,6 @@ reject_it:
 static int  
 sym_wide_nego_check(hcb_p np, int req, int target)
 {
-	tcb_p tp = &np->target[target];
 	u_char	chg, wide;
 
 	if (DEBUG_FLAGS & DEBUG_NEGO) {
@@ -4306,10 +4318,6 @@ sym_wide_nego_check(hcb_p np, int req, int target)
 		chg = 1;
 		wide = np->maxwide;
 	}
-	if (req) {
-		if (wide > tp->tinfo.user.width)
-			{chg = 1; wide = tp->tinfo.user.width;}
-	}
 
 	if (DEBUG_FLAGS & DEBUG_NEGO) {
 		PRINT_TARGET(np, target);
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h
index aa246dd0f..04b5411ea 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.h
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h
@@ -69,11 +69,6 @@
  *        When this option is set, the driver will use a queue per 
  *        device and handle QUEUE FULL status requeuing internally.
  *
- *    SYM_OPT_SNIFF_INQUIRY
- *        When this option is set, the driver sniff out successful 
- *        INQUIRY response and performs negotiations accordingly.
- *        (set for Linux)
- *
  *    SYM_OPT_LIMIT_COMMAND_REORDERING
  *        When this option is set, the driver tries to limit tagged 
  *        command reordering to some reasonnable value.
@@ -82,7 +77,6 @@
 #if 0
 #define SYM_OPT_HANDLE_DIR_UNKNOWN
 #define SYM_OPT_HANDLE_DEVICE_QUEUEING
-#define SYM_OPT_SNIFF_INQUIRY
 #define SYM_OPT_LIMIT_COMMAND_REORDERING
 #endif
 
@@ -364,7 +358,6 @@ struct sym_trans {
 struct sym_tinfo {
 	struct sym_trans curr;
 	struct sym_trans goal;
-	struct sym_trans user;
 #ifdef	SYM_OPT_ANNOUNCE_TRANSFER_RATE
 	struct sym_trans prev;
 #endif
@@ -465,18 +458,7 @@ struct sym_tcb {
 	 */
 	u_char	usrflags;
 	u_short	usrtags;
-
-#ifdef	SYM_OPT_SNIFF_INQUIRY
-	/*
-	 *  Some minimal information from INQUIRY response.
-	 */
-	u32	cmdq_map[(SYM_CONF_MAX_LUN+31)/32];
-	u_char	inq_version;
-	u_char	inq_byte7;
-	u_char	inq_byte56;
-	u_char	inq_byte7_valid;
-#endif
-
+	struct scsi_device *sdev;
 };
 
 /*
@@ -1168,26 +1150,6 @@ void sym_clock(hcb_p np);
 void sym_announce_transfer_rate(hcb_p np, int target);
 #endif
 
-/*
- *  Optionnaly, the driver may sniff inquiry data.
- */
-#ifdef	SYM_OPT_SNIFF_INQUIRY
-#define	INQ7_CMDQ	(0x02)
-#define	INQ7_SYNC	(0x10)
-#define	INQ7_WIDE16	(0x20)
-
-#define INQ56_CLOCKING	(3<<2)
-#define INQ56_ST_ONLY	(0<<2)
-#define INQ56_DT_ONLY	(1<<2)
-#define INQ56_ST_DT	(3<<2)
-
-void sym_update_trans_settings(hcb_p np, tcb_p tp);
-int  
-__sym_sniff_inquiry(hcb_p np, u_char tn, u_char ln,
-                    u_char *inq_data, int inq_len);
-#endif
-
-
 /*
  *  Build a scatter/gather entry.
  *
diff --git a/drivers/scsi/sym53c8xx_2/sym_misc.c b/drivers/scsi/sym53c8xx_2/sym_misc.c
index ee2a7b28a..6b3c8b84c 100644
--- a/drivers/scsi/sym53c8xx_2/sym_misc.c
+++ b/drivers/scsi/sym53c8xx_2/sym_misc.c
@@ -216,121 +216,3 @@ void sym_announce_transfer_rate(hcb_p np, int target)
 #undef __tprev
 #undef __tcurr
 #endif	/* SYM_OPT_ANNOUNCE_TRANSFER_RATE */
-
-
-#ifdef	SYM_OPT_SNIFF_INQUIRY
-/*
- *  Update transfer settings according to user settings 
- *  and bits sniffed out from INQUIRY response.
- */
-void sym_update_trans_settings(hcb_p np, tcb_p tp)
-{
-	memcpy(&tp->tinfo.goal, &tp->tinfo.user, sizeof(tp->tinfo.goal));
-
-	if (tp->inq_version >= 4) {
-		switch(tp->inq_byte56 & INQ56_CLOCKING) {
-		case INQ56_ST_ONLY:
-			tp->tinfo.goal.options = 0;
-			break;
-		case INQ56_DT_ONLY:
-		case INQ56_ST_DT:
-		default:
-			break;
-		}
-	}
-
-	if (!((tp->inq_byte7 & tp->inq_byte7_valid) & INQ7_WIDE16)) {
-		tp->tinfo.goal.width   = 0;
-		tp->tinfo.goal.options = 0;
-	}
-
-	if (!((tp->inq_byte7 & tp->inq_byte7_valid) & INQ7_SYNC)) {
-		tp->tinfo.goal.offset  = 0;
-		tp->tinfo.goal.options = 0;
-	}
-
-	if (tp->tinfo.goal.options & PPR_OPT_DT) {
-		if (tp->tinfo.goal.offset > np->maxoffs_dt)
-			tp->tinfo.goal.offset = np->maxoffs_dt;
-	}
-	else {
-		if (tp->tinfo.goal.offset > np->maxoffs)
-			tp->tinfo.goal.offset = np->maxoffs;
-	}
-}
-
-/*
- *  Snoop target capabilities from INQUIRY response.
- *  We only believe device versions >= SCSI-2 that use 
- *  appropriate response data format (2). But it seems 
- *  that some CCS devices also support SYNC (?).
- */
-int 
-__sym_sniff_inquiry(hcb_p np, u_char tn, u_char ln,
-                    u_char *inq_data, int inq_len)
-{
-	tcb_p tp = &np->target[tn];
-	u_char inq_version;
-	u_char inq_byte7;
-	u_char inq_byte56;
-
-	if (!inq_data || inq_len < 2)
-		return -1;
-
-	/*
-	 *  Check device type and qualifier.
-	 */
-	if ((inq_data[0] & 0xe0) == 0x60)
-		return -1;
-
-	/*
-	 *  Get SPC version.
-	 */
-	if (inq_len <= 2)
-		return -1;
-	inq_version = inq_data[2] & 0x7;
-
-	/*
-	 *  Get SYNC/WIDE16 capabilities.
-	 */
-	inq_byte7 = tp->inq_byte7;
-	if (inq_version >= 2 && (inq_data[3] & 0xf) == 2) {
-		if (inq_len > 7)
-			inq_byte7 = inq_data[7];
-	}
-	else if (inq_version == 1 && (inq_data[3] & 0xf) == 1)
-		inq_byte7 = INQ7_SYNC;
-
-	/*
-	 *  Get Tagged Command Queuing capability.
-	 */
-	if (inq_byte7 & INQ7_CMDQ)
-		sym_set_bit(tp->cmdq_map, ln);
-	else
-		sym_clr_bit(tp->cmdq_map, ln);
-	inq_byte7 &= ~INQ7_CMDQ;
-
-	/*
-	 *  Get CLOCKING capability.
-	 */
-	inq_byte56 = tp->inq_byte56;
-	if (inq_version >= 4 && inq_len > 56)
-		inq_byte56 = inq_data[56];
-#if 0
-printf("XXXXXX [%d] inq_version=%x inq_byte7=%x inq_byte56=%x XXXXX\n",
-	inq_len, inq_version, inq_byte7, inq_byte56);
-#endif
-	/*
-	 *  Trigger a negotiation if needed.
-	 */
-	if (tp->inq_version != inq_version ||
-	    tp->inq_byte7   != inq_byte7   ||
-	    tp->inq_byte56  != inq_byte56) {
-		tp->inq_version = inq_version;
-		tp->inq_byte7   = inq_byte7;
-		tp->inq_byte56  = inq_byte56;
-		return 1;
-	}
-	return 0;
-}
-#endif	/* SYM_OPT_SNIFF_INQUIRY */
diff --git a/drivers/scsi/sym53c8xx_2/sym_nvram.c b/drivers/scsi/sym53c8xx_2/sym_nvram.c
index 2bb4b3f3e..ca857ffc6 100644
--- a/drivers/scsi/sym53c8xx_2/sym_nvram.c
+++ b/drivers/scsi/sym53c8xx_2/sym_nvram.c
@@ -53,11 +53,6 @@
 #include "sym_glue.h"
 #include "sym_nvram.h"
 
-/*
- *  Some poor and bogus sync table that refers to Tekram NVRAM layout.
- */
-static u_char Tekram_sync[16] =
-	{25,31,37,43, 50,62,75,125, 12,15,18,21, 6,7,9,10};
 #ifdef	SYM_CONF_DEBUG_NVRAM
 static u_char Tekram_boot_delay[7] = {3, 5, 10, 20, 30, 60, 120};
 #endif
@@ -100,8 +95,6 @@ sym_Symbios_setup_target(struct sym_hcb *np, int target, Symbios_nvram *nvram)
 	struct sym_tcb *tp = &np->target[target];
 	Symbios_target *tn = &nvram->target[target];
 
-	tp->tinfo.user.period = tn->sync_period ? (tn->sync_period + 3) / 4 : 0;
-	tp->tinfo.user.width  = tn->bus_width == 0x10 ? BUS_16_BIT : BUS_8_BIT;
 	tp->usrtags =
 		(tn->flags & SYMBIOS_QUEUE_TAGS_ENABLED)? SYM_SETUP_MAX_TAG : 0;
 
@@ -121,15 +114,6 @@ sym_Tekram_setup_target(struct sym_hcb *np, int target, Tekram_nvram *nvram)
 {
 	struct sym_tcb *tp = &np->target[target];
 	struct Tekram_target *tn = &nvram->target[target];
-	int i;
-
-	if (tn->flags & TEKRAM_SYNC_NEGO) {
-		i = tn->sync_index & 0xf;
-		tp->tinfo.user.period = Tekram_sync[i];
-	}
-
-	tp->tinfo.user.width = (tn->flags & TEKRAM_WIDE_NEGO) ?
-		BUS_16_BIT : BUS_8_BIT;
 
 	if (tn->flags & TEKRAM_TAGGED_COMMANDS) {
 		tp->usrtags = 2 << nvram->max_tags_index;
diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c
index 7ef1b8c92..7e73fc257 100644
--- a/drivers/scsi/t128.c
+++ b/drivers/scsi/t128.c
@@ -284,6 +284,7 @@ static int t128_release(struct Scsi_Host *shost)
 {
 	if (shost->irq)
 		free_irq(shost->irq, NULL);
+	NCR5380_exit(shost);
 	if (shost->io_port && shost->n_io_port)
 		release_region(shost->io_port, shost->n_io_port);
 	scsi_unregister(shost);
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
index 1b324b800..8a1ed11fb 100644
--- a/drivers/scsi/tmscsim.c
+++ b/drivers/scsi/tmscsim.c
@@ -240,17 +240,15 @@
 #include <linux/spinlock.h>
 #include <asm/io.h>
 
-#if 0
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
-#else
-#include "scsi.h"
-#endif
 #include <scsi/scsi_host.h>
 #include <scsi/scsicam.h>
 
-#include "dc390.h"
+
+#define DC390_BANNER "Tekram DC390/AM53C974"
+#define DC390_VERSION "2.1d 2004-05-27"
 
 #define PCI_DEVICE_ID_AMD53C974 	PCI_DEVICE_ID_AMD_SCSI
 
@@ -291,20 +289,14 @@ static void dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struc
 static void dc390_DoingSRB_Done( struct dc390_acb* pACB, struct scsi_cmnd * cmd);
 static void dc390_ScsiRstDetect( struct dc390_acb* pACB );
 static void dc390_ResetSCSIBus( struct dc390_acb* pACB );
-static void __inline__ dc390_RequestSense( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB );
-static void __inline__ dc390_InvalidCmd( struct dc390_acb* pACB );
-static void __inline__ dc390_EnableMsgOut_Abort (struct dc390_acb*, struct dc390_srb*);
+static void dc390_EnableMsgOut_Abort(struct dc390_acb*, struct dc390_srb*);
 static irqreturn_t do_DC390_Interrupt( int, void *, struct pt_regs *);
 
 static int    dc390_initAdapter(struct Scsi_Host *psh, unsigned long io_port, u8 Irq, u8 index );
 static void   dc390_updateDCB (struct dc390_acb* pACB, struct dc390_dcb* pDCB);
 
-static int DC390_proc_info (struct Scsi_Host *shpnt, char *buffer, char **start,
-			    off_t offset, int length, int inout);
-
 static struct dc390_acb*	dc390_pACB_start= NULL;
 static struct dc390_acb*	dc390_pACB_current = NULL;
-static unsigned long	dc390_lastabortedpid = 0;
 static u32	dc390_laststatus = 0;
 static u8	dc390_adapterCnt = 0;
 
@@ -612,16 +604,12 @@ static u8 __devinit dc390_CheckEEpromCheckSum(struct pci_dev *pdev, u8 index)
  **********************************************************************/
 static struct dc390_dcb __inline__ *dc390_findDCB ( struct dc390_acb* pACB, u8 id, u8 lun)
 {
-   struct dc390_dcb* pDCB = pACB->pLinkDCB; if (!pDCB) return 0;
+   struct dc390_dcb* pDCB = pACB->pLinkDCB; if (!pDCB) return NULL;
    while (pDCB->TargetID != id || pDCB->TargetLUN != lun)
      {
 	pDCB = pDCB->pNextDCB;
 	if (pDCB == pACB->pLinkDCB)
-	  {
-	     DCBDEBUG(printk (KERN_WARNING "DC390: DCB not found (DCB=%p, DCBmap[%2x]=%2x)\n",
-			      pDCB, id, pACB->DCBmap[id]));
-	     return 0;
-	  }
+	     return NULL;
      }
    DCBDEBUG1( printk (KERN_DEBUG "DCB %p (%02x,%02x) found.\n",	\
 		      pDCB, pDCB->TargetID, pDCB->TargetLUN));
@@ -942,8 +930,6 @@ static void dc390_BuildSRB (struct scsi_cmnd *pcmd, struct dc390_dcb* pDCB, stru
 {
     pSRB->pSRBDCB = pDCB;
     pSRB->pcmd = pcmd;
-    //pSRB->ScsiCmdLen = pcmd->cmd_len;
-    //memcpy (pSRB->CmdBlock, pcmd->cmnd, pcmd->cmd_len);
     
     pSRB->SGIndex = 0;
     pSRB->AdaptStatus = 0;
@@ -991,28 +977,6 @@ static int DC390_queue_command(struct scsi_cmnd *cmd,
     struct dc390_srb*   pSRB;
     struct dc390_acb*   pACB = (struct dc390_acb*) cmd->device->host->hostdata;
 
-    DEBUG0(/*  if(pACB->scan_devices) */	\
-	printk(KERN_INFO "DC390: Queue Cmd=%02x,Tgt=%d,LUN=%d (pid=%li), buffer=%p\n",\
-	       cmd->cmnd[0],cmd->device->id,cmd->device->lun,cmd->pid, cmd->buffer));
-
-    /* TODO: Change the policy: Always accept TEST_UNIT_READY or INQUIRY 
-     * commands and alloc a DCB for the device if not yet there. DCB will
-     * be removed in dc390_SRBdone if SEL_TIMEOUT */
-    if (!(pACB->scan_devices) && !(pACB->DCBmap[cmd->device->id] & (1 << cmd->device->lun))) {
-	printk(KERN_INFO "DC390: Ignore target %02x lun %02x\n",
-		cmd->device->id, cmd->device->lun); 
-	goto fail;
-    }
-
-    /* Should it be: BUG_ON(!pDCB); ? */
-
-    if (!pDCB)
-    {  /* should never happen */
-	printk (KERN_ERR "DC390: no DCB found, target %02x lun %02x\n", 
-		cmd->device->id, cmd->device->lun);
-	goto fail;
-    }
-
     pACB->Cmds++;
     cmd->scsi_done = done;
     cmd->result = 0;
@@ -1033,146 +997,8 @@ static int DC390_queue_command(struct scsi_cmnd *cmd,
 
  requeue:
     return 1;
- fail:
-    cmd->result = DID_BAD_TARGET << 16;
-    done(cmd);
-    return 0;
-}
-
-/* We ignore mapping problems, as we expect everybody to respect 
- * valid partition tables. Waiting for complaints ;-) */
-
-#ifdef CONFIG_SCSI_DC390T_TRADMAP
-/* 
- * The next function, partsize(), is copied from scsicam.c.
- *
- * This is ugly code duplication, but I didn't find another way to solve it:
- * We want to respect the partition table and if it fails, we apply the 
- * DC390 BIOS heuristic. Too bad, just calling scsicam_bios_param() doesn't do
- * the job, because we don't know, whether the values returned are from
- * the part. table or determined by setsize(). Unfortunately the setsize() 
- * values differ from the ones chosen by the DC390 BIOS.
- *
- * Looking forward to seeing suggestions for a better solution! KG, 98/10/14
- */
-#include <asm/unaligned.h>
-
-/*
- * Function : static int partsize(unsigned char *buf, unsigned long 
- *     capacity,unsigned int *cyls, unsigned int *hds, unsigned int *secs);
- *
- * Purpose : to determine the BIOS mapping used to create the partition
- *	table, storing the results in *cyls, *hds, and *secs 
- *
- * Returns : -1 on failure, 0 on success.
- *
- */
-
-static int partsize(unsigned char *buf, unsigned long capacity,
-    unsigned int  *cyls, unsigned int *hds, unsigned int *secs) {
-    struct partition *p, *largest = NULL;
-    int i, largest_cyl;
-    int cyl, ext_cyl, end_head, end_cyl, end_sector;
-    unsigned int logical_end, physical_end, ext_physical_end;
-    
-
-    if (*(unsigned short *) (buf+64) == 0xAA55) {
-	for (largest_cyl = -1, p = (struct partition *) buf, 
-    	    i = 0; i < 4; ++i, ++p) {
-    	    if (!p->sys_ind)
-    	    	continue;
-    	    cyl = p->cyl + ((p->sector & 0xc0) << 2);
-    	    if (cyl > largest_cyl) {
-    	    	largest_cyl = cyl;
-    	    	largest = p;
-    	    }
-    	}
-    }
-
-    if (largest) {
-    	end_cyl = largest->end_cyl + ((largest->end_sector & 0xc0) << 2);
-    	end_head = largest->end_head;
-    	end_sector = largest->end_sector & 0x3f;
-
-    	physical_end =  end_cyl * (end_head + 1) * end_sector +
-    	    end_head * end_sector + end_sector;
-
-	/* This is the actual _sector_ number at the end */
-	logical_end = get_unaligned(&largest->start_sect)
-			+ get_unaligned(&largest->nr_sects);
-
-	/* This is for >1023 cylinders */
-        ext_cyl= (logical_end-(end_head * end_sector + end_sector))
-                                        /(end_head + 1) / end_sector;
-	ext_physical_end = ext_cyl * (end_head + 1) * end_sector +
-            end_head * end_sector + end_sector;
-
-    	if ((logical_end == physical_end) ||
-	    (end_cyl==1023 && ext_physical_end==logical_end)) {
-    	    *secs = end_sector;
-    	    *hds = end_head + 1;
-    	    *cyls = capacity / ((end_head + 1) * end_sector);
-    	    return 0;
-    	}
-    }
-    return -1;
 }
 
-/***********************************************************************
- * Function:
- *   DC390_bios_param
- *
- * Description:
- *   Return the disk geometry for the given SCSI device.
- *   Respect the partition table, otherwise try own heuristic
- *
- * Note:
- *   In contrary to other externally callable funcs (DC390_), we don't lock
- ***********************************************************************/
-static int DC390_bios_param (struct scsi_device *sdev, struct block_device *bdev,
-			     sector_t capacity, int geom[])
-{
-    int heads, sectors, cylinders;
-    struct dc390_acb* pACB = (struct dc390_acb*) sdev->host->hostdata;
-    int ret_code = -1;
-    int size = capacity;
-    unsigned char *buf;
-
-    if ((buf = scsi_bios_ptable(bdev)))
-    {
-	/* try to infer mapping from partition table */
-	ret_code = partsize (buf, (unsigned long) size, (unsigned int *) geom + 2,
-			     (unsigned int *) geom + 0, (unsigned int *) geom + 1);
-	kfree (buf);
-    }
-    if (ret_code == -1)
-    {
-	heads = 64;
-	sectors = 32;
-	cylinders = size / (heads * sectors);
-
-	if ( (pACB->Gmode2 & GREATER_1G) && (cylinders > 1024) )
-	{
-		heads = 255;
-		sectors = 63;
-		cylinders = size / (heads * sectors);
-	}
-
-	geom[0] = heads;
-	geom[1] = sectors;
-	geom[2] = cylinders;
-    }
-
-    return (0);
-}
-#else
-static int DC390_bios_param (struct scsi_device *sdev, struct block_device *bdev,
-			     sector_t capacity, int geom[])
-{
-    return scsicam_bios_param (bdev, capacity, geom);
-}
-#endif
-
 static void dc390_dumpinfo (struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
 {
     struct pci_dev *pdev;
@@ -1219,146 +1045,54 @@ static void dc390_dumpinfo (struct dc390_acb* pACB, struct dc390_dcb* pDCB, stru
 }
 
 
-/***********************************************************************
- * Function : int DC390_abort (struct scsi_cmnd *cmd)
- *
- * Purpose : Abort an errant SCSI command
- *
- * Inputs : cmd - command to abort
- *
- * Returns : 0 on success, -1 on failure.
- *
- * Status: Buggy !
- ***********************************************************************/
-
-static int DC390_abort (struct scsi_cmnd *cmd)
+static int DC390_abort(struct scsi_cmnd *cmd)
 {
-    struct dc390_dcb *pDCB = (struct dc390_dcb*) cmd->device->hostdata;
-    struct dc390_srb *pSRB, *psrb;
-    u32  count, i;
-    int   status;
-    //unsigned long sbac;
-    struct dc390_acb *pACB = (struct dc390_acb*) cmd->device->host->hostdata;
-
-    printk ("DC390: Abort command (pid %li, Device %02i-%02i)\n",
-	    cmd->pid, cmd->device->id, cmd->device->lun);
-
-    if( !pDCB ) goto  NOT_RUN;
-
-    /* Added 98/07/02 KG */
-    /*
-    pSRB = pDCB->pActiveSRB;
-    if (pSRB && pSRB->pcmd == cmd )
-	goto ON_GOING;
-     */
-    
-    pSRB = pDCB->pWaitingSRB;
-    if( !pSRB )
-	goto  ON_GOING;
+	struct dc390_acb *pACB = (struct dc390_acb*) cmd->device->host->hostdata;
+	struct dc390_dcb *pDCB = (struct dc390_dcb*) cmd->device->hostdata;
+	struct dc390_srb *pSRB, *psrb;
 
-    /* Now scan Waiting queue */
-    if( pSRB->pcmd == cmd )
-    {
-	pDCB->pWaitingSRB = pSRB->pNextSRB;
-	goto  IN_WAIT;
-    }
-    else
-    {
-	psrb = pSRB;
-	if( !(psrb->pNextSRB) )
-	    goto ON_GOING;
-	while( psrb->pNextSRB->pcmd != cmd )
-	{
-	    psrb = psrb->pNextSRB;
-	    if( !(psrb->pNextSRB) || psrb == pSRB)
-		goto ON_GOING;
-	}
-	pSRB = psrb->pNextSRB;
-	psrb->pNextSRB = pSRB->pNextSRB;
-	if( pSRB == pDCB->pWaitLast )
-	    pDCB->pWaitLast = psrb;
-IN_WAIT:
-	dc390_Free_insert (pACB, pSRB);
+	printk("DC390: Abort command (pid %li, Device %02i-%02i)\n",
+	       cmd->pid, cmd->device->id, cmd->device->lun);
+
+	pSRB = pDCB->pWaitingSRB;
+	if (!pSRB)
+		goto on_going;
+
+	/* Now scan Waiting queue */
+	if (pSRB->pcmd != cmd) {
+		psrb = pSRB;
+		if (!(psrb->pNextSRB))
+			goto on_going;
+
+		while (psrb->pNextSRB->pcmd != cmd) {
+			psrb = psrb->pNextSRB;
+			if (!(psrb->pNextSRB) || psrb == pSRB)
+				goto on_going;
+		}
+
+		pSRB = psrb->pNextSRB;
+		psrb->pNextSRB = pSRB->pNextSRB;
+		if (pSRB == pDCB->pWaitLast)
+			pDCB->pWaitLast = psrb;
+	} else
+		pDCB->pWaitingSRB = pSRB->pNextSRB;
+
+	dc390_Free_insert(pACB, pSRB);
 	pDCB->WaitSRBCnt--;
 	INIT_LIST_HEAD((struct list_head*)&cmd->SCp);
-	status = SCSI_ABORT_SUCCESS;
-	goto  ABO_X;
-    }
 
-    /* SRB has already been sent ! */
-ON_GOING:
-    /* abort() is too stupid for already sent commands at the moment. 
-     * If it's called we are in trouble anyway, so let's dump some info 
-     * into the syslog at least. (KG, 98/08/20,99/06/20) */
-    dc390_dumpinfo (pACB, pDCB, pSRB);
-    pSRB = pDCB->pGoingSRB;
-    pDCB->DCBFlag |= ABORT_DEV_;
-    /* Now for the hard part: The command is currently processed */
-    for( count = pDCB->GoingSRBCnt, i=0; i<count; i++)
-    {
-	if( pSRB->pcmd != cmd )
-	    pSRB = pSRB->pNextSRB;
-	else
-	{
-	    if( (pACB->pActiveDCB == pDCB) && (pDCB->pActiveSRB == pSRB) )
-	    {
-		status = SCSI_ABORT_BUSY;
-		printk ("DC390: Abort current command (pid %li, SRB %p)\n",
-			cmd->pid, pSRB);
-		goto  ABO_X;
-	    }
-	    else
-	    {
-		status = SCSI_ABORT_SNOOZE;
-		goto  ABO_X;
-	    }
-	}
-    }
+	return SUCCESS;
 
-NOT_RUN:
-    status = SCSI_ABORT_NOT_RUNNING;
+on_going:
+	/* abort() is too stupid for already sent commands at the moment. 
+	 * If it's called we are in trouble anyway, so let's dump some info 
+	 * into the syslog at least. (KG, 98/08/20,99/06/20) */
+	dc390_dumpinfo(pACB, pDCB, pSRB);
 
-ABO_X:
-    cmd->result = DID_ABORT << 16;
-    printk(KERN_INFO "DC390: Aborted pid %li with status %i\n", cmd->pid, status);
-#if 0
-    if (cmd->pid == dc390_lastabortedpid) /* repeated failure ? */
-	{
-		/* Let's do something to help the bus getting clean again */
-		DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-		DC390_write8 (ScsiCmd, DMA_COMMAND);
-		//DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-		//DC390_write8 (ScsiCmd, RESET_ATN_CMD);
-		DC390_write8 (ScsiCmd, NOP_CMD);
-		//udelay (10000);
-		//DC390_read8 (INT_Status);
-		//DC390_write8 (ScsiCmd, EN_SEL_RESEL);
-	}
-    sbac = DC390_read32 (DMA_ScsiBusCtrl);
-    if (sbac & SCSI_BUSY)
-    {	/* clear BSY, SEL and ATN */
-	printk (KERN_WARNING "DC390: Reset SCSI device: ");
-	//DC390_write32 (DMA_ScsiBusCtrl, (sbac | SCAM) & ~SCSI_LINES);
-	//udelay (250);
-	//sbac = DC390_read32 (DMA_ScsiBusCtrl);
-	//printk ("%08lx ", sbac);
-	//DC390_write32 (DMA_ScsiBusCtrl, sbac & ~(SCSI_LINES | SCAM));
-	//udelay (100);
-	//sbac = DC390_read32 (DMA_ScsiBusCtrl);
-	//printk ("%08lx ", sbac);
-	DC390_write8 (ScsiCmd, RST_DEVICE_CMD);
-	udelay (250);
-	DC390_write8 (ScsiCmd, NOP_CMD);
-	sbac = DC390_read32 (DMA_ScsiBusCtrl);
-	printk ("%08lx\n", sbac);
-    }
-#endif
-    dc390_lastabortedpid = cmd->pid;
-    //do_DC390_Interrupt (pACB->IRQLevel, 0, 0);
-#ifndef USE_NEW_EH	
-    if (status == SCSI_ABORT_SUCCESS) cmd->scsi_done(cmd);
-#endif	
-    return( status );
+	pDCB->DCBFlag |= ABORT_DEV_;
+	printk(KERN_INFO "DC390: Aborted pid %li\n", cmd->pid);
+
+	return FAILED;
 }
 
 
@@ -1385,93 +1119,38 @@ static void dc390_ResetDevParam( struct dc390_acb* pACB )
 
 }
 
-#if 0
-/* Moves all SRBs from Going to Waiting for all DCBs */
-static void dc390_RecoverSRB( struct dc390_acb* pACB )
+static int DC390_bus_reset (struct scsi_cmnd *cmd)
 {
-    struct dc390_dcb *pDCB, *pdcb;
-    struct dc390_srb *psrb, *psrb2;
-    u32   cnt, i;
+	struct dc390_acb*    pACB = (struct dc390_acb*) cmd->device->host->hostdata;
+	u8   bval;
 
-    pDCB = pACB->pLinkDCB;
-    if( !pDCB ) return;
-    pdcb = pDCB;
-    do
-    {
-	cnt = pdcb->GoingSRBCnt;
-	psrb = pdcb->pGoingSRB;
-	for (i=0; i<cnt; i++)
-	{
-	    psrb2 = psrb;
-	    psrb = psrb->pNextSRB;
-/*	    dc390_RewaitSRB( pDCB, psrb ); */
-	    if( pdcb->pWaitingSRB )
-	    {
-		psrb2->pNextSRB = pdcb->pWaitingSRB;
-		pdcb->pWaitingSRB = psrb2;
-	    }
-	    else
-	    {
-		pdcb->pWaitingSRB = psrb2;
-		pdcb->pWaitLast = psrb2;
-		psrb2->pNextSRB = NULL;
-	    }
-	}
-	pdcb->GoingSRBCnt = 0;
-	pdcb->pGoingSRB = NULL;
-	pdcb->TagMask = 0;
-	pdcb = pdcb->pNextDCB;
-    } while( pdcb != pDCB );
-}
-#endif
-
-/***********************************************************************
- * Function : int DC390_reset (struct scsi_cmnd *cmd, ...)
- *
- * Purpose : perform a hard reset on the SCSI bus
- *
- * Inputs : cmd - command which caused the SCSI RESET
- *	    resetFlags - how hard to try
- *
- * Returns : 0 on success.
- ***********************************************************************/
-
-static int DC390_reset (struct scsi_cmnd *cmd)
-{
-    u8   bval;
-    struct dc390_acb*    pACB = (struct dc390_acb*) cmd->device->host->hostdata;
+	del_timer (&pACB->Waiting_Timer);
 
-    printk(KERN_INFO "DC390: RESET ... ");
-
-    if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer);
-    bval = DC390_read8 (CtrlReg1);
-    bval |= DIS_INT_ON_SCSI_RST;
-    DC390_write8 (CtrlReg1, bval);	/* disable IRQ on bus reset */
+	bval = DC390_read8(CtrlReg1) | DIS_INT_ON_SCSI_RST;
+	DC390_write8(CtrlReg1, bval);	/* disable IRQ on bus reset */
 
-    pACB->ACBFlag |= RESET_DEV;
-    dc390_ResetSCSIBus( pACB );
+	pACB->ACBFlag |= RESET_DEV;
+	dc390_ResetSCSIBus(pACB);
 
-    dc390_ResetDevParam( pACB );
-    udelay (1000);
-    pACB->pScsiHost->last_reset = jiffies + 3*HZ/2 
+	dc390_ResetDevParam(pACB);
+	udelay(1000);
+	pACB->pScsiHost->last_reset = jiffies + 3*HZ/2 
 		+ HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
     
-    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
-    DC390_read8 (INT_Status);		/* Reset Pending INT */
+	DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
+	DC390_read8(INT_Status);		/* Reset Pending INT */
 
-    dc390_DoingSRB_Done( pACB, cmd );
-    /* dc390_RecoverSRB (pACB); */
-    pACB->pActiveDCB = NULL;
+	dc390_DoingSRB_Done(pACB, cmd);
 
-    pACB->ACBFlag = 0;
-    bval = DC390_read8 (CtrlReg1);
-    bval &= ~DIS_INT_ON_SCSI_RST;
-    DC390_write8 (CtrlReg1, bval);	/* re-enable interrupt */
+	pACB->pActiveDCB = NULL;
+	pACB->ACBFlag = 0;
+
+	bval = DC390_read8(CtrlReg1) & ~DIS_INT_ON_SCSI_RST;
+	DC390_write8(CtrlReg1, bval);	/* re-enable interrupt */
 
-    dc390_Waiting_process( pACB );
+	dc390_Waiting_process(pACB);
 
-    printk("done\n");
-    return( SCSI_RESET_SUCCESS );
+	return SUCCESS;
 }
 
 #include "scsiiom.c"
@@ -1548,7 +1227,6 @@ static void dc390_linkSRB( struct dc390_acb* pACB )
 static void __devinit dc390_initACB (struct Scsi_Host *psh, unsigned long io_port, u8 Irq, u8 index)
 {
     struct dc390_acb*    pACB;
-    u8   i;
 
     psh->can_queue = MAX_CMD_QUEUE;
     psh->cmd_per_lun = MAX_CMD_PER_LUN;
@@ -1595,8 +1273,6 @@ static void __devinit dc390_initACB (struct Scsi_Host *psh, unsigned long io_por
     dc390_linkSRB( pACB );
     pACB->pTmpSRB = &pACB->TmpSRB;
     dc390_initSRB( pACB->pTmpSRB );
-    for(i=0; i<MAX_SCSI_ID; i++)
-	pACB->DCBmap[i] = 0;
     pACB->sel_timeout = SEL_TIMEOUT;
     pACB->glitch_cfg = EATER_25NS;
     pACB->Cmds = pACB->CmdInQ = pACB->CmdOutOfSRB = 0;
@@ -1706,7 +1382,7 @@ static void __devinit dc390_set_pci_cfg (struct pci_dev *pdev)
 static int dc390_slave_alloc(struct scsi_device *scsi_device)
 {
 	struct dc390_acb *pACB = (struct dc390_acb*) scsi_device->host->hostdata;
-	struct dc390_dcb *pDCB, *pDCB2 = 0;
+	struct dc390_dcb *pDCB, *pDCB2 = NULL;
 	uint id = scsi_device->id;
 	uint lun = scsi_device->lun;
 
@@ -1757,7 +1433,6 @@ static int dc390_slave_alloc(struct scsi_device *scsi_device)
 			pDCB->CtrlR4 |= NEGATE_REQACKDATA | NEGATE_REQACK;
 	}
 
-	pACB->DCBmap[id] |= (1 << lun);
 	dc390_updateDCB(pACB, pDCB);
 
 	pACB->scan_devices = 1;
@@ -1781,8 +1456,6 @@ static void dc390_slave_destroy(struct scsi_device *scsi_device)
 
 	BUG_ON(pDCB->GoingSRBCnt > 1);
 	
-	pACB->DCBmap[pDCB->TargetID] &= ~(1 << pDCB->TargetLUN);
-   
 	if (pDCB == pACB->pLinkDCB) {
 		if (pACB->pLastDCB == pDCB) {
 			pDCB->pNextDCB = NULL;
@@ -1818,15 +1491,13 @@ static int dc390_slave_configure(struct scsi_device *scsi_device)
 static struct scsi_host_template driver_template = {
 	.module			= THIS_MODULE,
 	.proc_name		= "tmscsim", 
-	.proc_info		= DC390_proc_info,
 	.name			= DC390_BANNER " V" DC390_VERSION,
 	.slave_alloc		= dc390_slave_alloc,
 	.slave_configure	= dc390_slave_configure,
 	.slave_destroy		= dc390_slave_destroy,
 	.queuecommand		= DC390_queue_command,
 	.eh_abort_handler	= DC390_abort,
-	.eh_bus_reset_handler	= DC390_reset,
-	.bios_param		= DC390_bios_param,
+	.eh_bus_reset_handler	= DC390_bus_reset,
 	.can_queue		= 42,
 	.this_id		= 7,
 	.sg_tablesize		= SG_ALL,
@@ -1939,152 +1610,6 @@ static void __devexit dc390_remove_one(struct pci_dev *dev)
 	pci_set_drvdata(dev, NULL);
 }
 
-/********************************************************************
- * Function: DC390_proc_info(char* buffer, char **start,
- *			     off_t offset, int length, int hostno, int inout)
- *
- * Purpose: return SCSI Adapter/Device Info
- *
- * Input: buffer: Pointer to a buffer where to write info
- *	  start :
- *	  offset:
- *	  hostno: Host adapter index
- *	  inout : Read (=0) or set(!=0) info
- *
- * Output: buffer: contains info
- *	   length; length of info in buffer
- *
- * return value: length
- *
- ********************************************************************/
-
-#undef SPRINTF
-#define SPRINTF(args...) pos += sprintf(pos, ## args)
-
-#define YESNO(YN)		\
- if (YN) SPRINTF(" Yes ");	\
- else SPRINTF(" No  ")
-
-
-static int DC390_proc_info (struct Scsi_Host *shpnt, char *buffer, char **start,
-			    off_t offset, int length, int inout)
-{
-  int dev, spd, spd1;
-  char *pos = buffer;
-  struct dc390_acb* pACB;
-  struct dc390_dcb* pDCB;
-
-  pACB = dc390_pACB_start;
-
-  while(pACB != (struct dc390_acb*)-1)
-     {
-	if (shpnt == pACB->pScsiHost)
-		break;
-	pACB = pACB->pNextACB;
-     }
-
-  if (pACB == (struct dc390_acb*)-1) return(-ESRCH);
-
-  if(inout) /* Has data been written to the file ? */
-      return -ENOSYS;
-   
-  SPRINTF("Tekram DC390/AM53C974 PCI SCSI Host Adapter, ");
-  SPRINTF("Driver Version %s\n", DC390_VERSION);
-
-  SPRINTF("SCSI Host Nr %i, ", shpnt->host_no);
-  SPRINTF("%s Adapter Nr %i\n", dc390_adapname, pACB->AdapterIndex);
-  SPRINTF("IOPortBase 0x%04x, ", pACB->IOPortBase);
-  SPRINTF("IRQ %02i\n", pACB->IRQLevel);
-
-  SPRINTF("MaxID %i, MaxLUN %i, ", shpnt->max_id, shpnt->max_lun);
-  SPRINTF("AdapterID %i, SelTimeout %i ms, DelayReset %i s\n", 
-	  shpnt->this_id, (pACB->sel_timeout*164)/100,
-	  dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]);
-
-  SPRINTF("TagMaxNum %i, Status 0x%02x, ACBFlag 0x%02x, GlitchEater %i ns\n",
-	  pACB->TagMaxNum, pACB->status, pACB->ACBFlag, GLITCH_TO_NS(pACB->glitch_cfg)*12);
-
-  SPRINTF("Statistics: Cmnds %li, Cmnds not sent directly %i, Out of SRB conds %i\n",
-	  pACB->Cmds, pACB->CmdInQ, pACB->CmdOutOfSRB);
-  SPRINTF("            Lost arbitrations %i, Sel. connected %i, Connected: %s\n", 
-	  pACB->SelLost, pACB->SelConn, pACB->Connected? "Yes": "No");
-   
-  SPRINTF("Nr of DCBs: %i\n", pACB->DCBCnt);
-  SPRINTF("Map of attached LUNs: %02x %02x %02x %02x %02x %02x %02x %02x\n",
-	  pACB->DCBmap[0], pACB->DCBmap[1], pACB->DCBmap[2], pACB->DCBmap[3], 
-	  pACB->DCBmap[4], pACB->DCBmap[5], pACB->DCBmap[6], pACB->DCBmap[7]);
-
-  SPRINTF("Idx ID LUN Prty Sync DsCn SndS TagQ NegoPeriod SyncSpeed SyncOffs MaxCmd\n");
-
-  pDCB = pACB->pLinkDCB;
-  for (dev = 0; dev < pACB->DCBCnt; dev++)
-     {
-      SPRINTF("%02i  %02i  %02i ", dev, pDCB->TargetID, pDCB->TargetLUN);
-      YESNO(pDCB->DevMode & PARITY_CHK_);
-      YESNO(pDCB->SyncMode & SYNC_NEGO_DONE);
-      YESNO(pDCB->DevMode & EN_DISCONNECT_);
-      YESNO(pDCB->DevMode & SEND_START_);
-      YESNO(pDCB->SyncMode & EN_TAG_QUEUEING);
-      if (pDCB->SyncOffset & 0x0f)
-      {
-	 int sp = pDCB->SyncPeriod; if (! (pDCB->CtrlR3 & FAST_SCSI)) sp++;
-	 SPRINTF("  %03i ns ", (pDCB->NegoPeriod) << 2);
-	 spd = 40/(sp); spd1 = 40%(sp);
-	 spd1 = (spd1 * 10 + sp/2) / (sp);
-	 SPRINTF("   %2i.%1i M      %02i", spd, spd1, (pDCB->SyncOffset & 0x0f));
-      }
-      else SPRINTF(" (%03i ns)                 ", (pDCB->NegoPeriod) << 2);
-      /* Add more info ...*/
-      SPRINTF ("      %02i\n", pDCB->MaxCommand);
-      pDCB = pDCB->pNextDCB;
-     }
-    if (timer_pending(&pACB->Waiting_Timer)) SPRINTF ("Waiting queue timer running\n");
-    else SPRINTF ("\n");
-    pDCB = pACB->pLinkDCB;
-	
-    for (dev = 0; dev < pACB->DCBCnt; dev++)
-    {
-	struct dc390_srb* pSRB;
-	if (pDCB->WaitSRBCnt) 
-		    SPRINTF ("DCB (%02i-%i): Waiting: %i:", pDCB->TargetID, pDCB->TargetLUN,
-			     pDCB->WaitSRBCnt);
-	for (pSRB = pDCB->pWaitingSRB; pSRB; pSRB = pSRB->pNextSRB)
-		SPRINTF(" %li", pSRB->pcmd->pid);
-	if (pDCB->GoingSRBCnt) 
-		    SPRINTF ("\nDCB (%02i-%i): Going  : %i:", pDCB->TargetID, pDCB->TargetLUN,
-			     pDCB->GoingSRBCnt);
-	for (pSRB = pDCB->pGoingSRB; pSRB; pSRB = pSRB->pNextSRB)
-#if 0 //def DC390_DEBUGTRACE
-		SPRINTF(" %s\n  ", pSRB->debugtrace);
-#else
-		SPRINTF(" %li", pSRB->pcmd->pid);
-#endif
-	if (pDCB->WaitSRBCnt || pDCB->GoingSRBCnt) SPRINTF ("\n");
-	pDCB = pDCB->pNextDCB;
-    }
-	
-#ifdef DC390_DEBUGDCB
-    SPRINTF ("DCB list for ACB %p:\n", pACB);
-    pDCB = pACB->pLinkDCB;
-    SPRINTF ("%p", pDCB);
-    for (dev = 0; dev < pACB->DCBCnt; dev++, pDCB=pDCB->pNextDCB)
-	SPRINTF ("->%p", pDCB->pNextDCB);
-    SPRINTF("\n");
-#endif
-  
-  *start = buffer + offset;
-
-  if (pos - buffer < offset)
-    return 0;
-  else if (pos - buffer - offset < length)
-    return pos - buffer - offset;
-  else
-    return length;
-}
-
-#undef YESNO
-#undef SPRINTF
-
 static struct pci_driver dc390_driver = {
 	.name           = "tmscsim",
 	.id_table       = tmscsim_pci_tbl,
diff --git a/drivers/scsi/tmscsim.h b/drivers/scsi/tmscsim.h
index 62e9f8791..5cc90e951 100644
--- a/drivers/scsi/tmscsim.h
+++ b/drivers/scsi/tmscsim.h
@@ -163,7 +163,6 @@ struct dc390_srb	*pFreeSRB;
 struct dc390_srb	*pTmpSRB;
 
 u8		msgin123[4];
-u8		DCBmap[MAX_SCSI_ID];
 u8		Connected;
 u8		pad;
 
diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
index 193e40c18..553a5f1e2 100644
--- a/drivers/scsi/wd7000.c
+++ b/drivers/scsi/wd7000.c
@@ -190,7 +190,6 @@
 #include <scsi/scsicam.h>
 
 
-#define ANY2SCSI_INLINE		/* undef this to use old macros */
 #undef  WD7000_DEBUG		/* general debug                */
 #ifdef WD7000_DEBUG
 #define dprintk printk
@@ -726,55 +725,17 @@ static int __init wd7000_setup(char *str)
 
 __setup("wd7000=", wd7000_setup);
 
-#ifdef ANY2SCSI_INLINE
-/*
- * Since they're used a lot, I've redone the following from the macros
- * formerly in wd7000.h, hopefully to speed them up by getting rid of
- * all the shifting (it may not matter; GCC might have done as well anyway).
- *
- * xany2scsi and xscsi2int were not being used, and are no longer defined.
- * (They were simply 4-byte versions of these routines).
- */
-typedef union {			/* let's cheat... */
-	int i;
-	unchar u[sizeof(int)];	/* the sizeof(int) makes it more portable */
-} i_u;
-
-
 static inline void any2scsi(unchar * scsi, int any)
 {
-	*scsi++ = ((i_u) any).u[2];
-	*scsi++ = ((i_u) any).u[1];
-	*scsi++ = ((i_u) any).u[0];
+	*scsi++ = (unsigned)any >> 16;
+	*scsi++ = (unsigned)any >> 8;
+	*scsi++ = any;
 }
 
-
 static inline int scsi2int(unchar * scsi)
 {
-	i_u result;
-
-	result.i = 0;		/* clears unused bytes */
-	result.u[2] = *scsi++;
-	result.u[1] = *scsi++;
-	result.u[0] = *scsi++;
-
-	return (result.i);
+	return (scsi[0] << 16) | (scsi[1] << 8) | scsi[2];
 }
-#else
-/*
- * These are the old ones - I've just moved them here...
- */
-#undef any2scsi
-#define any2scsi(up, p)   (up)[0] = (((unsigned long) (p)) >> 16);	\
-			  (up)[1] = ((unsigned long) (p)) >> 8;		\
-			  (up)[2] = ((unsigned long) (p));
-
-#undef scsi2int
-#define scsi2int(up)   ( (((unsigned long) *(up)) << 16) +	\
-			 (((unsigned long) (up)[1]) << 8) +	\
-			 ((unsigned long) (up)[2]) )
-#endif
-
 
 static inline void wd7000_enable_intr(Adapter * host)
 {
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index 5c499be24..6dd522466 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -435,10 +435,7 @@ static void do_softint(void *private)
 		return;
 #if 0
 	if (clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
+		tty_wakeup(tty);
 	}
 #endif   
 }
@@ -858,10 +855,7 @@ static void rs_flush_buffer(struct tty_struct *tty)
 	cli();
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 	sti();
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /*
@@ -1185,11 +1179,13 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
 	shutdown(info);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+		
+	tty_ldisc_flush(tty);
 	tty->closing = 0;
 	info->event = 0;
 	info->tty = 0;
+#warning "This is not and has never been valid so fix it"	
+#if 0
 	if (tty->ldisc.num != ldiscs[N_TTY].num) {
 		if (tty->ldisc.close)
 			(tty->ldisc.close)(tty);
@@ -1198,6 +1194,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
 		if (tty->ldisc.open)
 			(tty->ldisc.open)(tty);
 	}
+#endif	
 	if (info->blocked_open) {
 		if (info->close_delay) {
 			current->state = TASK_INTERRUPTIBLE;
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index 64e296ad3..cd2d62cd1 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -700,12 +700,8 @@ static void do_softint(void *private_)
 	if (!tty)
 		return;
 
-	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
-	}
+	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event))
+		tty_wakeup(tty);
 }
 
 
@@ -1152,10 +1148,7 @@ static void rs_360_flush_buffer(struct tty_struct *tty)
 	/* There is nothing to "flush", whatever we gave the CPM
 	 * is on its way out.
 	 */
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 	info->flags &= ~TX_WAKEUP;
 }
 
@@ -1716,8 +1709,7 @@ static void rs_360_close(struct tty_struct *tty, struct file * filp)
 	shutdown(info);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);		
 	tty->closing = 0;
 	info->event = 0;
 	info->tty = 0;
@@ -2592,7 +2584,7 @@ int rs_360_init(void)
 		state->icount.rx = state->icount.tx = 0;
 		state->icount.frame = state->icount.parity = 0;
 		state->icount.overrun = state->icount.brk = 0;
-		printk(KERN_INFO "ttyS%02d at irq 0x%02x is an %s\n",
+		printk(KERN_INFO "ttyS%d at irq 0x%02x is an %s\n",
 		       i, (unsigned int)(state->irq),
 		       (state->smc_scc_num & NUM_IS_SCC) ? "SCC" : "SMC");
 
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 4906b5751..2ade801d0 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -130,6 +130,7 @@ struct uart_8250_port {
 	struct timer_list	timer;		/* "no irq" timer */
 	struct list_head	list;		/* ports on this IRQ */
 	unsigned int		capabilities;	/* port capabilities */
+	unsigned int		tx_loadsz;	/* transmit fifo load size */
 	unsigned short		rev;
 	unsigned char		acr;
 	unsigned char		ier;
@@ -156,23 +157,23 @@ static struct irq_info irq_lists[NR_IRQS];
 /*
  * Here we define the default xmit fifo size used for each type of UART.
  */
-static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = {
-	{ "unknown",	1,	0 },
-	{ "8250",	1,	0 },
-	{ "16450",	1,	0 },
-	{ "16550",	1,	0 },
-	{ "16550A",	16,	UART_CLEAR_FIFO | UART_USE_FIFO },
-	{ "Cirrus",	1, 	0 },
-	{ "ST16650",	1,	UART_CLEAR_FIFO | UART_STARTECH },
-	{ "ST16650V2",	32,	UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
-	{ "TI16750",	64,	UART_CLEAR_FIFO | UART_USE_FIFO },
-	{ "Startech",	1,	0 },
-	{ "16C950/954",	128,	UART_CLEAR_FIFO | UART_USE_FIFO },
-	{ "ST16654",	64,	UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
-	{ "XR16850",	128,	UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
-	{ "RSA",	2048,	UART_CLEAR_FIFO | UART_USE_FIFO },
-	{ "NS16550A",	16,	UART_CLEAR_FIFO | UART_USE_FIFO | UART_NATSEMI },
-	{ "XScale",	32,	UART_CLEAR_FIFO | UART_USE_FIFO  },
+static const struct serial8250_config uart_config[PORT_MAX_8250+1] = {
+	{ "unknown",	1,	1,	0 },
+	{ "8250",	1,	1,	0 },
+	{ "16450",	1,	1,	0 },
+	{ "16550",	1,	1,	0 },
+	{ "16550A",	16,	16,	UART_CAP_FIFO },
+	{ "Cirrus",	1, 	1,	0 },
+	{ "ST16650",	1,	1,	UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_EFR },
+	{ "ST16650V2",	32,	16,	UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_EFR },
+	{ "TI16750",	64,	64,	UART_CAP_FIFO | UART_CAP_SLEEP },
+	{ "Startech",	1,	1,	0 },
+	{ "16C950/954",	128,	128,	UART_CAP_FIFO },
+	{ "ST16654",	64,	32,	UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_EFR },
+	{ "XR16850",	128,	128,	UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_EFR },
+	{ "RSA",	2048,	2048,	UART_CAP_FIFO },
+	{ "NS16550A",	16,	16,	UART_CAP_FIFO | UART_NATSEMI },
+	{ "XScale",	32,	32,	UART_CAP_FIFO },
 };
 
 static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
@@ -187,6 +188,9 @@ static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset)
 	case UPIO_MEM:
 		return readb(up->port.membase + offset);
 
+	case UPIO_MEM32:
+		return readl(up->port.membase + offset);
+
 	default:
 		return inb(up->port.iobase + offset);
 	}
@@ -207,6 +211,10 @@ serial_out(struct uart_8250_port *up, int offset, int value)
 		writeb(value, up->port.membase + offset);
 		break;
 
+	case UPIO_MEM32:
+		writel(value, up->port.membase + offset);
+		break;
+
 	default:
 		outb(value, up->port.iobase + offset);
 	}
@@ -243,6 +251,41 @@ static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
 	return value;
 }
 
+/*
+ * FIFO support.
+ */
+static inline void serial8250_clear_fifos(struct uart_8250_port *p)
+{
+	if (p->capabilities & UART_CAP_FIFO) {
+		serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO);
+		serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO |
+			       UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+		serial_outp(p, UART_FCR, 0);
+	}
+}
+
+/*
+ * IER sleep support.  UARTs which have EFRs need the "extended
+ * capability" bit enabled.  Note that on XR16C850s, we need to
+ * reset LCR to write to IER.
+ */
+static inline void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
+{
+	if (p->capabilities & UART_CAP_SLEEP) {
+		if (p->capabilities & UART_CAP_EFR) {
+			serial_outp(p, UART_LCR, 0xBF);
+			serial_outp(p, UART_EFR, UART_EFR_ECB);
+			serial_outp(p, UART_LCR, 0);
+		}
+		serial_outp(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
+		if (p->capabilities & UART_CAP_EFR) {
+			serial_outp(p, UART_LCR, 0xBF);
+			serial_outp(p, UART_EFR, 0);
+			serial_outp(p, UART_LCR, 0);
+		}
+	}
+}
+
 #ifdef CONFIG_SERIAL_8250_RSA
 /*
  * Attempts to turn on the RSA FIFO.  Returns zero on failure.
@@ -697,8 +740,9 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
 #endif
 	serial_outp(up, UART_LCR, save_lcr);
 
-	up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size;
+	up->port.fifosize = uart_config[up->port.type].fifo_size;
 	up->capabilities = uart_config[up->port.type].flags;
+	up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
 
 	if (up->port.type == PORT_UNKNOWN)
 		goto out;
@@ -711,10 +755,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
 		serial_outp(up, UART_RSA_FRR, 0);
 #endif
 	serial_outp(up, UART_MCR, save_mcr);
-	serial_outp(up, UART_FCR, (UART_FCR_ENABLE_FIFO |
-				     UART_FCR_CLEAR_RCVR |
-				     UART_FCR_CLEAR_XMIT));
-	serial_outp(up, UART_FCR, 0);
+	serial8250_clear_fifos(up);
 	(void)serial_in(up, UART_RX);
 	serial_outp(up, UART_IER, 0);
 
@@ -923,7 +964,7 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up)
 		return;
 	}
 
-	count = up->port.fifosize;
+	count = up->tx_loadsz;
 	do {
 		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -1227,12 +1268,7 @@ static int serial8250_startup(struct uart_port *port)
 	 * Clear the FIFO buffers and disable them.
 	 * (they will be reeanbled in set_termios())
 	 */
-	if (up->capabilities & UART_CLEAR_FIFO) {
-		serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-		serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-				UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-		serial_outp(up, UART_FCR, 0);
-	}
+	serial8250_clear_fifos(up);
 
 	/*
 	 * Clear the interrupt registers.
@@ -1253,6 +1289,23 @@ static int serial8250_startup(struct uart_port *port)
 		return -ENODEV;
 	}
 
+	/*
+	 * For a XR16C850, we need to set the trigger levels
+	 */
+	if (up->port.type == PORT_16850) {
+		unsigned char fctr;
+
+		serial_outp(up, UART_LCR, 0xbf);
+
+		fctr = serial_inp(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX);
+		serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_RX);
+		serial_outp(up, UART_TRG, UART_TRG_96);
+		serial_outp(up, UART_FCTR, fctr | UART_FCTR_TRGD | UART_FCTR_TX);
+		serial_outp(up, UART_TRG, UART_TRG_96);
+
+		serial_outp(up, UART_LCR, 0);
+	}
+
 	/*
 	 * If the "interrupt" for this port doesn't correspond with any
 	 * hardware interrupt, we use a timer-based system.  The original
@@ -1345,10 +1398,7 @@ static void serial8250_shutdown(struct uart_port *port)
 	 * Disable break condition and FIFOs
 	 */
 	serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC);
-	serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO |
-				  UART_FCR_CLEAR_RCVR |
-				  UART_FCR_CLEAR_XMIT);
-	serial_outp(up, UART_FCR, 0);
+	serial8250_clear_fifos(up);
 
 #ifdef CONFIG_SERIAL_8250_RSA
 	/*
@@ -1440,7 +1490,7 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios,
 	    up->rev == 0x5201)
 		quot ++;
 
-	if (up->capabilities & UART_USE_FIFO) {
+	if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) {
 		if (baud < 2400)
 			fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
 #ifdef CONFIG_SERIAL_8250_RSA
@@ -1514,7 +1564,7 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios,
 
 	serial_out(up, UART_IER, up->ier);
 
-	if (up->capabilities & UART_STARTECH) {
+	if (up->capabilities & UART_CAP_EFR) {
 		serial_outp(up, UART_LCR, 0xBF);
 		serial_outp(up, UART_EFR,
 			    termios->c_cflag & CRTSCTS ? UART_EFR_CTS :0);
@@ -1554,71 +1604,12 @@ static void
 serial8250_pm(struct uart_port *port, unsigned int state,
 	      unsigned int oldstate)
 {
-	struct uart_8250_port *up = (struct uart_8250_port *)port;
-	if (state) {
-		/* sleep */
-		if (up->capabilities & UART_STARTECH) {
-			/* Arrange to enter sleep mode */
-			serial_outp(up, UART_LCR, 0xBF);
-			serial_outp(up, UART_EFR, UART_EFR_ECB);
-			serial_outp(up, UART_LCR, 0);
-			serial_outp(up, UART_IER, UART_IERX_SLEEP);
-			serial_outp(up, UART_LCR, 0xBF);
-			serial_outp(up, UART_EFR, 0);
-			serial_outp(up, UART_LCR, 0);
-		}
-		if (up->port.type == PORT_16750) {
-			/* Arrange to enter sleep mode */
-			serial_outp(up, UART_IER, UART_IERX_SLEEP);
-		}
+	struct uart_8250_port *p = (struct uart_8250_port *)port;
 
-		if (up->pm)
-			up->pm(port, state, oldstate);
-	} else {
-		/* wake */
-		if (up->capabilities & UART_STARTECH) {
-			/* Wake up UART */
-			serial_outp(up, UART_LCR, 0xBF);
-			serial_outp(up, UART_EFR, UART_EFR_ECB);
-			/*
-			 * Turn off LCR == 0xBF so we actually set the IER
-			 * register on the XR16C850
-			 */
-			serial_outp(up, UART_LCR, 0);
-			serial_outp(up, UART_IER, 0);
-			/*
-			 * Now reset LCR so we can turn off the ECB bit
-			 */
-			serial_outp(up, UART_LCR, 0xBF);
-			serial_outp(up, UART_EFR, 0);
-			/*
-			 * For a XR16C850, we need to set the trigger levels
-			 */
-			if (up->port.type == PORT_16850) {
-				unsigned char fctr;
-
-				fctr = serial_inp(up, UART_FCTR) &
-					 ~(UART_FCTR_RX | UART_FCTR_TX);
-				serial_outp(up, UART_FCTR, fctr |
-						UART_FCTR_TRGD |
-						UART_FCTR_RX);
-				serial_outp(up, UART_TRG, UART_TRG_96);
-				serial_outp(up, UART_FCTR, fctr |
-						UART_FCTR_TRGD |
-						UART_FCTR_TX);
-				serial_outp(up, UART_TRG, UART_TRG_96);
-			}
-			serial_outp(up, UART_LCR, 0);
-		}
+	serial8250_set_sleep(p, state != 0);
 
-		if (up->port.type == PORT_16750) {
-			/* Wake up UART */
-			serial_outp(up, UART_IER, 0);
-		}
-
-		if (up->pm)
-			up->pm(port, state, oldstate);
-	}
+	if (p->pm)
+		p->pm(port, state, oldstate);
 }
 
 /*
diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h
index da0ad9b3d..79c036852 100644
--- a/drivers/serial/8250.h
+++ b/drivers/serial/8250.h
@@ -33,6 +33,20 @@ struct old_serial_port {
 	unsigned short iomem_reg_shift;
 };
 
+/*
+ * This replaces serial_uart_config in include/linux/serial.h
+ */
+struct serial8250_config {
+	const char	*name;
+	unsigned int	fifo_size;
+	unsigned int	tx_loadsz;
+	unsigned int	flags;
+};
+
+#define UART_CAP_FIFO	(1 << 8)	/* UART has FIFO */
+#define UART_CAP_EFR	(1 << 9)	/* UART has EFR */
+#define UART_CAP_SLEEP	(1 << 10)	/* UART has IER sleep */
+
 #undef SERIAL_DEBUG_PCI
 
 #if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 34b367778..55c8aa908 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -83,7 +83,7 @@ struct pci_serial_quirk {
 
 struct serial_private {
 	unsigned int		nr;
-	void			*remapped_bar[PCI_NUM_BAR_RESOURCES];
+	void __iomem		*remapped_bar[PCI_NUM_BAR_RESOURCES];
 	struct pci_serial_quirk	*quirk;
 	int			line[0];
 };
@@ -243,7 +243,8 @@ static int __devinit pci_inteli960ni_init(struct pci_dev *dev)
  */
 static int __devinit pci_plx9050_init(struct pci_dev *dev)
 {
-	u8 *p, irq_config;
+	u8 irq_config;
+	void __iomem *p;
 
 	if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0) {
 		moan_device("no memory in bar 0", dev);
@@ -272,12 +273,12 @@ static int __devinit pci_plx9050_init(struct pci_dev *dev)
 	p = ioremap(pci_resource_start(dev, 0), 0x80);
 	if (p == NULL)
 		return -ENOMEM;
-	writel(irq_config, (unsigned long)p + 0x4c);
+	writel(irq_config, p + 0x4c);
 
 	/*
 	 * Read the register back to ensure that it took effect.
 	 */
-	readl((unsigned long)p + 0x4c);
+	readl(p + 0x4c);
 	iounmap(p);
 
 	return 0;
@@ -397,7 +398,8 @@ static void __devexit sbs_exit(struct pci_dev *dev)
 
 static int pci_siig10x_init(struct pci_dev *dev)
 {
-	u16 data, *p;
+	u16 data;
+	void __iomem *p;
 
 	switch (dev->device & 0xfff8) {
 	case PCI_DEVICE_ID_SIIG_1S_10x:	/* 1S */
@@ -415,8 +417,8 @@ static int pci_siig10x_init(struct pci_dev *dev)
 	if (p == NULL)
 		return -ENOMEM;
 
-	writew(readw((unsigned long) p + 0x28) & data, (unsigned long) p + 0x28);
-	readw((unsigned long)p + 0x28);
+	writew(readw(p + 0x28) & data, p + 0x28);
+	readw(p + 0x28);
 	iounmap(p);
 	return 0;
 }
@@ -1068,6 +1070,9 @@ enum pci_board_num_t {
 	pbn_computone_6,
 	pbn_computone_8,
 	pbn_sbsxrsio,
+	pbn_exar_XR17C152,
+	pbn_exar_XR17C154,
+	pbn_exar_XR17C158,
 };
 
 /*
@@ -1488,7 +1493,30 @@ static struct pci_board pci_boards[] __devinitdata = {
 		.base_baud	= 460800,
 		.uart_offset	= 256,
 		.reg_shift	= 4,
-	}
+	},
+	/*
+	 * Exar Corp. XR17C15[248] Dual/Quad/Octal UART
+	 *  Only basic 16550A support.
+	 *  XR17C15[24] are not tested, but they should work.
+	 */
+	[pbn_exar_XR17C152] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 2,
+		.base_baud	= 921600,
+		.uart_offset	= 0x200,
+	},
+	[pbn_exar_XR17C154] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 4,
+		.base_baud	= 921600,
+		.uart_offset	= 0x200,
+	},
+	[pbn_exar_XR17C158] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 8,
+		.base_baud	= 921600,
+		.uart_offset	= 0x200,
+	},
 };
 
 /*
@@ -2147,6 +2175,22 @@ static struct pci_device_id serial_pci_tbl[] = {
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 		pbn_b3_8_115200 },
 
+	/*
+	 * Exar Corp. XR17C15[248] Dual/Quad/Octal UART
+	 */
+	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0,
+		0, pbn_exar_XR17C152 },
+	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0,
+		0, pbn_exar_XR17C154 },
+	{	PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158,
+		PCI_ANY_ID, PCI_ANY_ID,
+		0,
+		0, pbn_exar_XR17C158 },
+
 	/*
 	 * These entries match devices with class COMMUNICATION_SERIAL,
 	 * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 74a0b9cad..6f8984a54 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -450,7 +450,7 @@ config SERIAL_MUX_CONSOLE
 
 config PDC_CONSOLE
 	bool "PDC software console support"
-	depends on PARISC && !SERIAL_MUX
+	depends on PARISC && !SERIAL_MUX && VT
 	default n
 	help
 	  Saying Y here will enable the software based PDC console to be 
@@ -682,6 +682,7 @@ config SERIAL_SGI_L1_CONSOLE
 	bool "SGI Altix L1 serial console support"
 	depends on IA64_GENERIC || IA64_SGI_SN2
 	select SERIAL_CORE
+	select SERIAL_CORE_CONSOLE
 	help
 		If you have an SGI Altix and you would like to use the system
 		controller serial port as your console (you want this!),
@@ -714,4 +715,16 @@ config SERIAL_MPC52xx_CONSOLE_BAUD
 	  This value is only used if the bootloader doesn't pass in the
 	  console baudrate
 
+config SERIAL_ICOM
+	tristate "IBM Multiport Serial Adapter"
+	depends on PPC_ISERIES || PPC_PSERIES
+	select SERIAL_CORE
+	help
+	  This driver is for a family of multiport serial adapters
+	  including 2 port RVX, 2 port internal modem, 4 port internal
+	  modem and a split 1 port RVX and 1 port internal modem.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called icom.
+
 endmenu
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index c91f6b149..69bd7f5ce 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -696,7 +696,6 @@ static int __init pl011_console_setup(struct console *co, char *options)
 	int bits = 8;
 	int parity = 'n';
 	int flow = 'n';
-	int ret;
 
 	/*
 	 * Check whether an invalid uart number has been specified, and
diff --git a/drivers/serial/bast_sio.c b/drivers/serial/bast_sio.c
index 698514d16..2b48fab6f 100644
--- a/drivers/serial/bast_sio.c
+++ b/drivers/serial/bast_sio.c
@@ -1,3 +1,19 @@
+/* linux/drivers/serial/bast_sio.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://www.simtec.co.uk/products/EB2410ITX/
+ *
+ * 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.
+ *
+ * Modifications:
+ *	23-Sep-2004  BJD  Added copyright header
+ *	23-Sep-2004  BJD  Added serial port remove code
+*/
+
 #include <linux/module.h>
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -20,10 +36,6 @@ static int __init serial_bast_register(unsigned long port, unsigned int irq)
 {
 	struct serial_struct serial_req;
 
-#if 0
-	printk("BAST: SuperIO serial (%08lx,%d)\n", port, irq);
-#endif
-
 	serial_req.flags      = UPF_AUTOPROBE | UPF_SHARE_IRQ;
 	serial_req.baud_base  = BASE_BAUD;
 	serial_req.irq        = irq;
@@ -37,11 +49,13 @@ static int __init serial_bast_register(unsigned long port, unsigned int irq)
 
 #define SERIAL_BASE (S3C2410_CS2 + BAST_PA_SUPERIO)
 
+static int port[2] = { -1, -1 };
+
 static int __init serial_bast_init(void)
 {
 	if (machine_is_bast()) {
-		serial_bast_register(SERIAL_BASE + 0x2f8, IRQ_PCSERIAL1);
-		serial_bast_register(SERIAL_BASE + 0x3f8, IRQ_PCSERIAL2);
+		port[0] = serial_bast_register(SERIAL_BASE + 0x2f8, IRQ_PCSERIAL1);
+		port[1] = serial_bast_register(SERIAL_BASE + 0x3f8, IRQ_PCSERIAL2);
 	}
 
 	return 0;
@@ -49,7 +63,10 @@ static int __init serial_bast_init(void)
 
 static void __exit serial_bast_exit(void)
 {
-	/* todo -> remove both our ports */
+	if (port[0] != -1)
+		unregister_serial(port[0]);
+	if (port[1] != -1)
+		unregister_serial(port[1]);
 }
 
 
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
index dfed45204..7f1b9ee7e 100644
--- a/drivers/serial/mcfserial.c
+++ b/drivers/serial/mcfserial.c
@@ -424,11 +424,7 @@ static void mcfrs_offintr(void *private)
 	tty = info->tty;
 	if (!tty)
 		return;
-
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
-	wake_up_interruptible(&tty->write_wait);
+	tty_wakeup(tty);
 }
 
 
@@ -835,10 +831,7 @@ static void mcfrs_flush_buffer(struct tty_struct *tty)
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 	local_irq_restore(flags);
 
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /*
@@ -1232,11 +1225,12 @@ static void mcfrs_close(struct tty_struct *tty, struct file * filp)
 	shutdown(info);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
+	
 	tty->closing = 0;
 	info->event = 0;
 	info->tty = 0;
+#if 0	
 	if (tty->ldisc.num != ldiscs[N_TTY].num) {
 		if (tty->ldisc.close)
 			(tty->ldisc.close)(tty);
@@ -1245,6 +1239,7 @@ static void mcfrs_close(struct tty_struct *tty, struct file * filp)
 		if (tty->ldisc.open)
 			(tty->ldisc.open)(tty);
 	}
+#endif	
 	if (info->blocked_open) {
 		if (info->close_delay) {
 			current->state = TASK_INTERRUPTIBLE;
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index cb6b4f3ec..3a7ab51d2 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -40,6 +40,7 @@
 #include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/irq.h>
+#include <asm/arch/pxa-regs.h>
 
 #if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index 22a02bd69..70d2f8333 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -26,8 +26,6 @@
 #include <asm/hardware.h>
 #include <asm/arch/regs-serial.h>
 
-#include <asm/mach-types.h>
-
 #if 0
 #include <asm/debug-ll.h>
 #define dbg(x...) llprintk(x)
@@ -677,7 +675,7 @@ serial_s3c2410_get_options(struct uart_port *port, int *baud,
 
 		default:
 		case S3C2410_LCON_PNONE:
-			/* nothing */
+			*parity = 'n';
 		}
 
 		/* now calculate the baud rate */
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 24ef1cbf5..1ac6c9d81 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -107,15 +107,7 @@ static void uart_start(struct tty_struct *tty)
 static void uart_tasklet_action(unsigned long data)
 {
 	struct uart_state *state = (struct uart_state *)data;
-	struct tty_struct *tty;
-
-	tty = state->info->tty;
-	if (tty) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			tty->ldisc.write_wakeup(tty);
-		wake_up_interruptible(&tty->write_wait);
-	}
+	tty_wakeup(state->info->tty);
 }
 
 static inline void
@@ -403,7 +395,7 @@ uart_get_divisor(struct uart_port *port, unsigned int baud)
 	if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
 		quot = port->custom_divisor;
 	else
-		quot = port->uartclk / (16 * baud);
+		quot = (port->uartclk + (8 * baud)) / (16 * baud);
 
 	return quot;
 }
@@ -581,10 +573,7 @@ static void uart_flush_buffer(struct tty_struct *tty)
 	spin_lock_irqsave(&port->lock, flags);
 	uart_circ_clear(&state->info->xmit);
 	spin_unlock_irqrestore(&port->lock, flags);
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /*
@@ -1216,7 +1205,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
 {
 	struct uart_state *state = tty->driver_data;
 	struct uart_port *port;
-
+	
 	BUG_ON(!kernel_locked());
 
 	if (!state || !state->port)
@@ -1239,12 +1228,12 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
 		 * one, we've got real problems, since it means the
 		 * serial port won't be shutdown.
 		 */
-		printk("uart_close: bad serial port count; tty->count is 1, "
+		printk(KERN_ERR "uart_close: bad serial port count; tty->count is 1, "
 		       "state->count is %d\n", state->count);
 		state->count = 1;
 	}
 	if (--state->count < 0) {
-		printk("rs_close: bad serial port count for %s: %d\n",
+		printk(KERN_ERR "uart_close: bad serial port count for %s: %d\n",
 		       tty->name, state->count);
 		state->count = 0;
 	}
@@ -1280,8 +1269,9 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
 
 	uart_shutdown(state);
 	uart_flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+
+	tty_ldisc_flush(tty);	
+	
 	tty->closing = 0;
 	state->info->tty = NULL;
 
@@ -1978,6 +1968,7 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)
 		printk("I/O 0x%x offset 0x%x", port->iobase, port->hub6);
 		break;
 	case UPIO_MEM:
+	case UPIO_MEM32:
 		printk("MMIO 0x%lx", port->mapbase);
 		break;
 	}
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index c3e6eb244..8557ed1ce 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -363,9 +363,10 @@ next_tuple(client_handle_t handle, tuple_t * tuple, cisparse_t * parse)
 
 /*====================================================================*/
 
-static int simple_config(dev_link_t * link)
+static int simple_config(dev_link_t *link)
 {
 	static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+	static int size_table[2] = { 8, 16 };
 	client_handle_t handle = link->handle;
 	struct serial_info *info = link->priv;
 	tuple_t tuple;
@@ -374,6 +375,7 @@ static int simple_config(dev_link_t * link)
 	cistpl_cftable_entry_t *cf = &parse.cftable_entry;
 	config_info_t config;
 	int i, j, try;
+	int s;
 
 	/* If the card is already configured, look up the port and irq */
 	i = pcmcia_get_configuration_info(handle, &config);
@@ -399,29 +401,30 @@ static int simple_config(dev_link_t * link)
 	tuple.Attributes = 0;
 	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
 	/* Two tries: without IO aliases, then with aliases */
-	for (try = 0; try < 2; try++) {
-		i = first_tuple(handle, &tuple, &parse);
-		while (i != CS_NO_MORE_ITEMS) {
-			if (i != CS_SUCCESS)
-				goto next_entry;
-			if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
-				link->conf.Vpp1 = link->conf.Vpp2 =
-				    cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
-			if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
-			    (cf->io.win[0].base != 0)) {
-				link->conf.ConfigIndex = cf->index;
-				link->io.BasePort1 = cf->io.win[0].base;
-				link->io.IOAddrLines = (try == 0) ?
-				    16 : cf->io.flags & CISTPL_IO_LINES_MASK;
-				i = pcmcia_request_io(link->handle, &link->io);
-				if (i == CS_SUCCESS)
-					goto found_port;
+	for (s = 0; s < 2; s++) {
+		for (try = 0; try < 2; try++) {
+			i = first_tuple(handle, &tuple, &parse);
+			while (i != CS_NO_MORE_ITEMS) {
+				if (i != CS_SUCCESS)
+					goto next_entry;
+				if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
+					link->conf.Vpp1 = link->conf.Vpp2 =
+					    cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+				if ((cf->io.nwin > 0) && (cf->io.win[0].len == size_table[s]) &&
+					    (cf->io.win[0].base != 0)) {
+					link->conf.ConfigIndex = cf->index;
+					link->io.BasePort1 = cf->io.win[0].base;
+					link->io.IOAddrLines = (try == 0) ?
+					    16 : cf->io.flags & CISTPL_IO_LINES_MASK;
+					i = pcmcia_request_io(link->handle, &link->io);
+					if (i == CS_SUCCESS)
+						goto found_port;
+				}
+next_entry:
+				i = next_tuple(handle, &tuple, &parse);
 			}
-		      next_entry:
-			i = next_tuple(handle, &tuple, &parse);
 		}
 	}
-
 	/* Second pass: try to find an entry that isn't picky about
 	   its base address, then try to grab any standard serial port
 	   address, and finally try to get any free port. */
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index 98b96c546..200bbce42 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -50,6 +50,7 @@
 #include <linux/miscdevice.h>
 #include <linux/serial_core.h>
 
+#include <asm/io.h>
 #include <asm/sn/simulator.h>
 #include <asm/sn/sn2/sn_private.h>
 #include <asm/sn/sn_sal.h>
@@ -80,6 +81,12 @@
 #define DEVICE_MAJOR 204
 #define DEVICE_MINOR 40
 
+#ifdef CONFIG_MAGIC_SYSRQ
+static char sysrq_serial_str[] = "\eSYS";
+static char *sysrq_serial_ptr = sysrq_serial_str;
+static unsigned long sysrq_requested;
+#endif /* CONFIG_MAGIC_SYSRQ */
+
 /*
  * Port definition - this kinda drives it all
  */
@@ -532,13 +539,15 @@ sn_debug_printf(const char *fmt, ...)
  * sn_receive_chars - Grab characters, pass them to tty layer
  * @port: Port to operate on
  * @regs: Saved registers (needed by uart_handle_sysrq_char)
+ * @flags: irq flags
  *
  * Note: If we're not registered with the serial core infrastructure yet,
  * we don't try to send characters to it...
  *
  */
 static void
-sn_receive_chars(struct sn_cons_port *port, struct pt_regs *regs)
+sn_receive_chars(struct sn_cons_port *port, struct pt_regs *regs,
+		 unsigned long flags)
 {
 	int ch;
 	struct tty_struct *tty;
@@ -569,10 +578,34 @@ sn_receive_chars(struct sn_cons_port *port, struct pt_regs *regs)
 			       "obtaining data from the console (0x%0x)\n", ch);
 			break;
 		}
-#if defined(CONFIG_SERIAL_SGI_L1_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-		if (uart_handle_sysrq_char(&port->sc_port, ch, regs))
-			continue;
-#endif				/* CONFIG_SERIAL_SGI_L1_CONSOLE && CONFIG_MAGIC_SYSRQ */
+#ifdef CONFIG_MAGIC_SYSRQ
+                if (sysrq_requested) {
+                        unsigned long sysrq_timeout = sysrq_requested + HZ*5;
+
+                        sysrq_requested = 0;
+                        if (ch && time_before(jiffies, sysrq_timeout)) {
+                                spin_unlock_irqrestore(&port->sc_port.lock, flags);
+                                handle_sysrq(ch, regs, NULL);
+                                spin_lock_irqsave(&port->sc_port.lock, flags);
+                                /* ignore actual sysrq command char */
+                                continue;
+                        }
+                }
+                if (ch == *sysrq_serial_ptr) {
+                        if (!(*++sysrq_serial_ptr)) {
+                                sysrq_requested = jiffies;
+                                sysrq_serial_ptr = sysrq_serial_str;
+                        }
+			/*
+			 * ignore the whole sysrq string except for the
+			 * leading escape
+			 */
+			if (ch != '\e')
+				continue;
+                }
+                else
+			sysrq_serial_ptr = sysrq_serial_str;
+#endif /* CONFIG_MAGIC_SYSRQ */
 
 		/* record the character to pass up to the tty layer */
 		if (tty) {
@@ -583,8 +616,6 @@ sn_receive_chars(struct sn_cons_port *port, struct pt_regs *regs)
 			if (tty->flip.count == TTY_FLIPBUF_SIZE)
 				break;
 		}
-		else {
-		}
 		port->sc_port.icount.rx++;
 	}
 
@@ -695,7 +726,7 @@ sn_sal_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
 	spin_lock_irqsave(&port->sc_port.lock, flags);
 	if (status & SAL_CONSOLE_INTR_RECV) {
-		sn_receive_chars(port, regs);
+		sn_receive_chars(port, regs, flags);
 	}
 	if (status & SAL_CONSOLE_INTR_XMIT) {
 		sn_transmit_chars(port, TRANSMIT_BUFFERED);
@@ -714,7 +745,8 @@ sn_sal_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 static int
 sn_sal_connect_interrupt(struct sn_cons_port *port)
 {
-	if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt, SA_INTERRUPT,
+	if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt,
+			SA_INTERRUPT | SA_SHIRQ,
 			"SAL console driver", port) >= 0) {
 		return SGI_UART_VECTOR;
 	}
@@ -743,7 +775,7 @@ sn_sal_timer_poll(unsigned long data)
 
 	if (!port->sc_port.irq) {
 		spin_lock_irqsave(&port->sc_port.lock, flags);
-		sn_receive_chars(port, NULL);
+		sn_receive_chars(port, NULL, flags);
 		sn_transmit_chars(port, TRANSMIT_RAW);
 		spin_unlock_irqrestore(&port->sc_port.lock, flags);
 		mod_timer(&port->sc_timer,
@@ -851,7 +883,6 @@ sn_sal_switch_to_interrupts(struct sn_cons_port *port)
  * Kernel console definitions
  */
 
-#ifdef CONFIG_SERIAL_SGI_L1_CONSOLE
 static void sn_sal_console_write(struct console *, const char *, unsigned);
 static int __init sn_sal_console_setup(struct console *, char *);
 extern struct uart_driver sal_console_uart;
@@ -867,9 +898,6 @@ static struct console sal_console = {
 };
 
 #define SAL_CONSOLE	&sal_console
-#else
-#define SAL_CONSOLE	0
-#endif				/* CONFIG_SERIAL_SGI_L1_CONSOLE */
 
 static struct uart_driver sal_console_uart = {
 	.owner = THIS_MODULE,
@@ -895,11 +923,11 @@ sn_sal_module_init(void)
 {
 	int retval;
 
-	printk(KERN_INFO "sn_console: Console driver init\n");
-
 	if (!ia64_platform_is("sn2"))
 		return -ENODEV;
 
+	printk(KERN_INFO "sn_console: Console driver init\n");
+
 	if (USE_DYNAMIC_MINOR == 1) {
 		misc.minor = MISC_DYNAMIC_MINOR;
 		misc.name = DEVICE_NAME_DYNAMIC;
@@ -969,8 +997,6 @@ sn_sal_module_exit(void)
 module_init(sn_sal_module_init);
 module_exit(sn_sal_module_exit);
 
-#ifdef CONFIG_SERIAL_SGI_L1_CONSOLE
-
 /**
  * puts_raw_fixed - sn_sal_console_write helper for adding \r's as required
  * @puts_raw : puts function to do the writing
@@ -1085,7 +1111,9 @@ sn_sal_console_write(struct console *co, const char *s, unsigned count)
 			spin_unlock_irqrestore(&port->sc_port.lock, flags);
 
 			puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count);
+#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
 		}
+#endif
 	}
 	else {
 		/* Not yet registered with serial core - simple case */
@@ -1190,5 +1218,3 @@ sn_sal_serial_console_init(void)
 }
 
 console_initcall(sn_sal_serial_console_init);
-
-#endif				/* CONFIG_SERIAL_SGI_L1_CONSOLE */
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index 494df5557..4c38513b2 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -768,25 +768,6 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla
 	writeb((readb(&up->regs->rw.ccr2) & ~0xc0) | ((ebrg >> 2) & 0xc0),
 	       &up->regs->rw.ccr2);
 
-	if (cflag & CRTSCTS) {
-		writeb(readb(&up->regs->rw.mode) & ~SAB82532_MODE_RTS,
-		       &up->regs->rw.mode);
-		writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_FRTS,
-		       &up->regs->rw.mode);
-		writeb(readb(&up->regs->rw.mode) & ~SAB82532_MODE_FCTS,
-		       &up->regs->rw.mode);
-		up->interrupt_mask1 &= ~SAB82532_IMR1_CSC;
-		writeb(up->interrupt_mask1, &up->regs->w.imr1);
-	} else {
-		writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_RTS,
-		       &up->regs->rw.mode);
-		writeb(readb(&up->regs->rw.mode) & ~SAB82532_MODE_FRTS,
-		       &up->regs->rw.mode);
-		writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_FCTS,
-		       &up->regs->rw.mode);
-		up->interrupt_mask1 |= SAB82532_IMR1_CSC;
-		writeb(up->interrupt_mask1, &up->regs->w.imr1);
-	}
 	writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_RAC, &up->regs->rw.mode);
 
 }
@@ -940,6 +921,7 @@ static int sunsab_console_setup(struct console *con, char *options)
 	writeb(up->interrupt_mask1, &up->regs->w.imr1);
 
 	sunsab_convert_to_sab(up, con->cflag, 0, baud);
+	sunsab_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
 
 	spin_unlock_irqrestore(&up->port.lock, flags);
 	
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 02586518a..2446dd664 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -98,7 +98,7 @@ struct uart_sunsu_port {
 	unsigned int		irq;
 
 #ifdef CONFIG_SERIO
-	struct serio		serio;
+	struct serio		*serio;
 	int			serio_open;
 #endif
 };
@@ -520,7 +520,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg
 		/* Stop-A is handled by drivers/char/keyboard.c now. */
 		if (up->su_type == SU_PORT_KBD) {
 #ifdef CONFIG_SERIO
-			serio_interrupt(&up->serio, ch, 0, regs);
+			serio_interrupt(up->serio, ch, 0, regs);
 #endif
 		} else if (up->su_type == SU_PORT_MS) {
 			int ret = suncore_mouse_baud_detection(ch, is_break);
@@ -534,7 +534,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg
 
 			case 0:
 #ifdef CONFIG_SERIO
-				serio_interrupt(&up->serio, ch, 0, regs);
+				serio_interrupt(up->serio, ch, 0, regs);
 #endif
 				break;
 			};
@@ -994,7 +994,7 @@ static spinlock_t sunsu_serio_lock = SPIN_LOCK_UNLOCKED;
 
 static int sunsu_serio_write(struct serio *serio, unsigned char ch)
 {
-	struct uart_sunsu_port *up = serio->driver;
+	struct uart_sunsu_port *up = serio->port_data;
 	unsigned long flags;
 	int lsr;
 
@@ -1014,7 +1014,7 @@ static int sunsu_serio_write(struct serio *serio, unsigned char ch)
 
 static int sunsu_serio_open(struct serio *serio)
 {
-	struct uart_sunsu_port *up = serio->driver;
+	struct uart_sunsu_port *up = serio->port_data;
 	unsigned long flags;
 	int ret;
 
@@ -1031,7 +1031,7 @@ static int sunsu_serio_open(struct serio *serio)
 
 static void sunsu_serio_close(struct serio *serio)
 {
-	struct uart_sunsu_port *up = serio->driver;
+	struct uart_sunsu_port *up = serio->port_data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&sunsu_serio_lock, flags);
@@ -1284,54 +1284,58 @@ static struct uart_driver sunsu_reg = {
 	.major			= TTY_MAJOR,
 };
 
-static int __init sunsu_kbd_ms_init(void)
+static int __init sunsu_kbd_ms_init(struct uart_sunsu_port *up, int channel)
 {
-	struct uart_sunsu_port *up;
-	int i;
+	struct serio *serio;
 
-	for (i = 0, up = sunsu_ports; i < 2; i++, up++) {
-		up->port.line = i;
-		up->port.type = PORT_UNKNOWN;
-		up->port.uartclk = (SU_BASE_BAUD * 16);
+	up->port.line = channel;
+	up->port.type = PORT_UNKNOWN;
+	up->port.uartclk = (SU_BASE_BAUD * 16);
 
-		if (up->su_type == SU_PORT_KBD)
-			up->cflag = B1200 | CS8 | CLOCAL | CREAD;
-		else
-			up->cflag = B4800 | CS8 | CLOCAL | CREAD;
+	if (up->su_type == SU_PORT_KBD)
+		up->cflag = B1200 | CS8 | CLOCAL | CREAD;
+	else
+		up->cflag = B4800 | CS8 | CLOCAL | CREAD;
 
-		sunsu_autoconfig(up);
-		if (up->port.type == PORT_UNKNOWN)
-			continue;
+	sunsu_autoconfig(up);
+	if (up->port.type == PORT_UNKNOWN)
+		return -1;
 
-		printk(KERN_INFO "su%d at 0x%p (irq = %s) is a %s\n",
-		       i,
-		       up->port.membase, __irq_itoa(up->irq),
-		       sunsu_type(&up->port));
+	printk(KERN_INFO "su%d at 0x%p (irq = %s) is a %s\n",
+	       channel,
+	       up->port.membase, __irq_itoa(up->irq),
+	       sunsu_type(&up->port));
 
 #ifdef CONFIG_SERIO
-		memset(&up->serio, 0, sizeof(up->serio));
+	up->serio = serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (serio) {
+		memset(serio, 0, sizeof(*serio));
 
-		up->serio.driver = up;
+		serio->port_data = up;
 
-		up->serio.type = SERIO_RS232;
+		serio->type = SERIO_RS232;
 		if (up->su_type == SU_PORT_KBD) {
-			up->serio.type |= SERIO_SUNKBD;
-			up->serio.name = "sukbd";
+			serio->type |= SERIO_SUNKBD;
+			strlcpy(serio->name, "sukbd", sizeof(serio->name));
 		} else {
-			up->serio.type |= (SERIO_SUN | (1 << 16));
-			up->serio.name = "sums";
+			serio->type |= (SERIO_SUN | (1 << 16));
+			strlcpy(serio->name, "sums", sizeof(serio->name));
 		}
-		up->serio.phys = (i == 0 ? "su/serio0" : "su/serio1");
+		strlcpy(serio->phys, (channel == 0 ? "su/serio0" : "su/serio1"),
+			sizeof(serio->phys));
 
-		up->serio.write = sunsu_serio_write;
-		up->serio.open = sunsu_serio_open;
-		up->serio.close = sunsu_serio_close;
+		serio->write = sunsu_serio_write;
+		serio->open = sunsu_serio_open;
+		serio->close = sunsu_serio_close;
 
-		serio_register_port(&up->serio);
+		serio_register_port(serio);
+	} else {
+		printk(KERN_WARNING "su%d: not enough memory for serio port\n",
+			channel);
+	}
 #endif
 
-		sunsu_startup(&up->port);
-	}
+	sunsu_startup(&up->port);
 	return 0;
 }
 
@@ -1680,10 +1684,12 @@ static int __init sunsu_probe(void)
 	if (scan.msx != -1 && scan.kbx != -1) {
 		sunsu_ports[0].su_type = SU_PORT_MS;
 		sunsu_ports[0].port_node = scan.msnode;
+		sunsu_kbd_ms_init(&sunsu_ports[0], 0);
+
 		sunsu_ports[1].su_type = SU_PORT_KBD;
 		sunsu_ports[1].port_node = scan.kbnode;
+		sunsu_kbd_ms_init(&sunsu_ports[1], 1);
 
-		sunsu_kbd_ms_init();
 		return 0;
 	}
 
@@ -1715,7 +1721,10 @@ static void __exit sunsu_exit(void)
 		if (up->su_type == SU_PORT_MS ||
 		    up->su_type == SU_PORT_KBD) {
 #ifdef CONFIG_SERIO
-			serio_unregister_port(&up->serio);
+			if (up->serio) {
+				serio_unregister_port(up->serio);
+				up->serio = NULL;
+			}
 #endif
 		} else if (up->port.type != PORT_UNKNOWN) {
 			uart_remove_one_port(&sunsu_reg, &up->port);
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index b38c02593..11ec83d8e 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -107,7 +107,7 @@ struct uart_sunzilog_port {
 	unsigned char			prev_status;
 
 #ifdef CONFIG_SERIO
-	struct serio			serio;
+	struct serio			*serio;
 	int				serio_open;
 #endif
 };
@@ -291,7 +291,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
 		/* Stop-A is handled by drivers/char/keyboard.c now. */
 #ifdef CONFIG_SERIO
 		if (up->serio_open)
-			serio_interrupt(&up->serio, ch, 0, regs);
+			serio_interrupt(up->serio, ch, 0, regs);
 #endif
 	} else if (ZS_IS_MOUSE(up)) {
 		int ret = suncore_mouse_baud_detection(ch, is_break);
@@ -306,7 +306,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
 		case 0:
 #ifdef CONFIG_SERIO
 			if (up->serio_open)
-				serio_interrupt(&up->serio, ch, 0, regs);
+				serio_interrupt(up->serio, ch, 0, regs);
 #endif
 			break;
 		};
@@ -1295,7 +1295,7 @@ static spinlock_t sunzilog_serio_lock = SPIN_LOCK_UNLOCKED;
 
 static int sunzilog_serio_write(struct serio *serio, unsigned char ch)
 {
-	struct uart_sunzilog_port *up = serio->driver;
+	struct uart_sunzilog_port *up = serio->port_data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&sunzilog_serio_lock, flags);
@@ -1309,7 +1309,7 @@ static int sunzilog_serio_write(struct serio *serio, unsigned char ch)
 
 static int sunzilog_serio_open(struct serio *serio)
 {
-	struct uart_sunzilog_port *up = serio->driver;
+	struct uart_sunzilog_port *up = serio->port_data;
 	unsigned long flags;
 	int ret;
 
@@ -1326,7 +1326,7 @@ static int sunzilog_serio_open(struct serio *serio)
 
 static void sunzilog_serio_close(struct serio *serio)
 {
-	struct uart_sunzilog_port *up = serio->driver;
+	struct uart_sunzilog_port *up = serio->port_data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&sunzilog_serio_lock, flags);
@@ -1545,33 +1545,44 @@ static void __init sunzilog_init_kbdms(struct uart_sunzilog_port *up, int channe
 	up->curregs[R15] = BRKIE;
 	brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
 	sunzilog_convert_to_zs(up, up->cflag, 0, brg);
+	sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
+	__sunzilog_startup(up);
+}
 
 #ifdef CONFIG_SERIO
-	memset(&up->serio, 0, sizeof(up->serio));
+static void __init sunzilog_register_serio(struct uart_sunzilog_port *up, int channel)
+{
+	struct serio *serio;
 
-	up->serio.driver = up;
+	up->serio = serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
+	if (serio) {
+		memset(serio, 0, sizeof(*serio));
 
-	up->serio.type = SERIO_RS232;
-	if (channel == KEYBOARD_LINE) {
-		up->serio.type |= SERIO_SUNKBD;
-		up->serio.name = "zskbd";
-	} else {
-		up->serio.type |= (SERIO_SUN | (1 << 16));
-		up->serio.name = "zsms";
-	}
-	up->serio.phys = (channel == KEYBOARD_LINE ?
-			  "zs/serio0" : "zs/serio1");
+		serio->port_data = up;
 
-	up->serio.write = sunzilog_serio_write;
-	up->serio.open = sunzilog_serio_open;
-	up->serio.close = sunzilog_serio_close;
+		serio->type = SERIO_RS232;
+		if (channel == KEYBOARD_LINE) {
+			serio->type |= SERIO_SUNKBD;
+			strlcpy(serio->name, "zskbd", sizeof(serio->name));
+		} else {
+			serio->type |= (SERIO_SUN | (1 << 16));
+			strlcpy(serio->name, "zsms", sizeof(serio->name));
+		}
+		strlcpy(serio->phys,
+			(channel == KEYBOARD_LINE ? "zs/serio0" : "zs/serio1"),
+			sizeof(serio->phys));
 
-	serio_register_port(&up->serio);
-#endif
+		serio->write = sunzilog_serio_write;
+		serio->open = sunzilog_serio_open;
+		serio->close = sunzilog_serio_close;
 
-	sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
-	__sunzilog_startup(up);
+		serio_register_port(serio);
+	} else {
+		printk(KERN_WARNING "zs%d: not enough memory for serio port\n",
+			channel);
+	}
 }
+#endif
 
 static void __init sunzilog_init_hw(void)
 {
@@ -1615,6 +1626,11 @@ static void __init sunzilog_init_hw(void)
 		}
 
 		spin_unlock_irqrestore(&up->port.lock, flags);
+
+#ifdef CONFIG_SERIO
+		if (i == KEYBOARD_LINE || i == MOUSE_LINE)
+			sunzilog_register_serio(up, i);
+#endif
 	}
 }
 
@@ -1732,10 +1748,15 @@ static void __exit sunzilog_exit(void)
 	for (i = 0; i < NUM_CHANNELS; i++) {
 		struct uart_sunzilog_port *up = &sunzilog_port_table[i];
 
-		if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up))
-			continue;
-
-		uart_remove_one_port(&sunzilog_reg, &up->port);
+		if (ZS_IS_KEYB(up) || ZS_IS_MOUSE(up)) {
+#ifdef CONFIG_SERIO
+			if (up->serio) {
+				serio_unregister_port(up->serio);
+				up->serio = NULL;
+			}
+#endif
+		} else
+			uart_remove_one_port(&sunzilog_reg, &up->port);
 	}
 
 	uart_unregister_driver(&sunzilog_reg);
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c
index 7391ae649..c5befc9af 100644
--- a/drivers/tc/zs.c
+++ b/drivers/tc/zs.c
@@ -211,10 +211,6 @@ static void probe_sccs(void);
 static void change_speed(struct dec_serial *info);
 static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
 
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
 /*
  * tmp_buf is used as a temporary buffer by serial_write.  We need to
  * lock it in case the copy_from_user blocks while swapping in a page,
@@ -683,10 +679,7 @@ static void do_softint(void *private_)
 		return;
 
 	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
+		tty_wakeup(tty);
 	}
 }
 
@@ -706,7 +699,7 @@ int zs_startup(struct dec_serial * info)
 	save_flags(flags); cli();
 
 #ifdef SERIAL_DEBUG_OPEN
-	printk("starting up ttyS%02d (irq %d)...", info->line, info->irq);
+	printk("starting up ttyS%d (irq %d)...", info->line, info->irq);
 #endif
 
 	/*
@@ -950,16 +943,16 @@ static int rs_write(struct tty_struct * tty, int from_user,
 	save_flags(flags);
 	while (1) {
 		cli();		
-		c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-				   SERIAL_XMIT_SIZE - info->xmit_head));
+		c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+					  SERIAL_XMIT_SIZE - info->xmit_head));
 		if (c <= 0)
 			break;
 
 		if (from_user) {
 			down(&tmp_buf_sem);
 			copy_from_user(tmp_buf, buf, c);
-			c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-				       SERIAL_XMIT_SIZE - info->xmit_head));
+			c = min_t(int, c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+					      SERIAL_XMIT_SIZE - info->xmit_head));
 			memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
 			up(&tmp_buf_sem);
 		} else
@@ -1010,10 +1003,7 @@ static void rs_flush_buffer(struct tty_struct *tty)
 	cli();
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 	sti();
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	tty_wakeup(tty);
 }
 
 /*
@@ -1356,7 +1346,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
 	}
 	
 #ifdef SERIAL_DEBUG_OPEN
-	printk("rs_close ttyS%02d, count = %d\n", info->line, info->count);
+	printk("rs_close ttyS%d, count = %d\n", info->line, info->count);
 #endif
 	if ((tty->count == 1) && (info->count != 1)) {
 		/*
@@ -1371,7 +1361,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
 		info->count = 1;
 	}
 	if (--info->count < 0) {
-		printk("rs_close: bad serial port count for ttyS%02d: %d\n",
+		printk("rs_close: bad serial port count for ttyS%d: %d\n",
 		       info->line, info->count);
 		info->count = 0;
 	}
@@ -1407,8 +1397,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
 	shutdown(info);
 	if (tty->driver->flush_buffer)
 		tty->driver->flush_buffer(tty);
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
+	tty_ldisc_flush(tty);
 	tty->closing = 0;
 	info->event = 0;
 	info->tty = 0;
@@ -1446,7 +1435,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
 	if (char_time == 0)
 		char_time = 1;
 	if (timeout)
-		char_time = MIN(char_time, timeout);
+		char_time = min_t(unsigned long, char_time, timeout);
 	while ((read_zsreg(info->zs_channel, 1) & Tx_BUF_EMP) == 0) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule_timeout(char_time);
@@ -1531,7 +1520,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
 	retval = 0;
 	add_wait_queue(&info->open_wait, &wait);
 #ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready before block: ttyS%02d, count = %d\n",
+	printk("block_til_ready before block: ttyS%d, count = %d\n",
 	       info->line, info->count);
 #endif
 	cli();
@@ -1565,7 +1554,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
 			break;
 		}
 #ifdef SERIAL_DEBUG_OPEN
-		printk("block_til_ready blocking: ttyS%02d, count = %d\n",
+		printk("block_til_ready blocking: ttyS%d, count = %d\n",
 		       info->line, info->count);
 #endif
 		schedule();
@@ -1576,7 +1565,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
 		info->count++;
 	info->blocked_open--;
 #ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready after blocking: ttyS%02d, count = %d\n",
+	printk("block_til_ready after blocking: ttyS%d, count = %d\n",
 	       info->line, info->count);
 #endif
 	if (retval)
@@ -1742,14 +1731,10 @@ static void __init probe_sccs(void)
 			 * We're called early and memory managment isn't up, yet.
 			 * Thus check_region would fail.
 			 */
-			if (check_region((unsigned long)
+			if (!request_region((unsigned long)
 					 zs_channels[n_channels].control,
-					 ZS_CHAN_IO_SIZE) < 0) {
+					 ZS_CHAN_IO_SIZE, "SCC"))
 				panic("SCC I/O region is not free");
-			}
-			request_region((unsigned long)
-				       zs_channels[n_channels].control,
-				       ZS_CHAN_IO_SIZE, "SCC");
 #endif
 			zs_soft[n_channels].zs_channel = &zs_channels[n_channels];
 			zs_soft[n_channels].irq = zs_parms->irq;
@@ -1896,7 +1881,7 @@ int __init zs_init(void)
 		info->tqueue.data = info;
 		init_waitqueue_head(&info->open_wait);
 		init_waitqueue_head(&info->close_wait);
-		printk("ttyS%02d at 0x%08x (irq = %d)", info->line, 
+		printk("ttyS%d at 0x%08x (irq = %d)", info->line,
 		       info->port, info->irq);
 		printk(" is a Z85C30 SCC\n");
 		tty_register_device(serial_driver, info->line, NULL);
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index 1d0a2e1a7..59a6515e7 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -7718,6 +7718,23 @@ static void __exit ixj_exit(void)
         cleanup();
 }
 
+static IXJ *new_ixj(unsigned long port)
+{
+	IXJ *res;
+	if (!request_region(port, 16, "ixj DSP")) {
+		printk(KERN_INFO "ixj: can't get I/O address 0x%lx\n", port);
+		return NULL;
+	}
+	res = ixj_alloc();
+	if (!res) {
+		release_region(port, 16);
+		printk(KERN_INFO "ixj: out of memory\n");
+		return NULL;
+	}
+	res->DSPbase = port;
+	return res;
+}
+
 int __init ixj_probe_isapnp(int *cnt)
 {               
 	int probe = 0;
@@ -7750,15 +7767,9 @@ int __init ixj_probe_isapnp(int *cnt)
 				return -ENODEV;
 			}
 
-			result = check_region(pnp_port_start(dev, 0), 16);
-			if (result) {
-				printk(KERN_INFO "ixj: can't get I/O address 0x%lx\n", pnp_port_start(dev, 0));
+			j = new_ixj(pnp_port_start(dev, 0));
+			if (!j)
 				break;
-			}
-
-			j = ixj_alloc();
-			j->DSPbase = pnp_port_start(dev,0);
-			request_region(j->DSPbase, 16, "ixj DSP");
 
 			if (func != 0x110)
 				j->XILINXbase = pnp_port_start(dev, 1);	/* get real port */
@@ -7806,22 +7817,15 @@ int __init ixj_probe_isapnp(int *cnt)
                         
 int __init ixj_probe_isa(int *cnt)
 {
-	int i, result, probe;
+	int i, probe;
 
 	/* Use passed parameters for older kernels without PnP */
 	for (i = 0; i < IXJMAX; i++) {
 		if (dspio[i]) {
-			IXJ *j;
+			IXJ *j = new_ixj(dspio[i]);
 
-			if ((result = check_region(ixj[*cnt].DSPbase, 16)) < 0) {
-				printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", ixj[*cnt].DSPbase);
+			if (!j)
 				break;
-			}
-
-			j = ixj_alloc();
-
-			j->DSPbase = dspio[i];
-			request_region(j->DSPbase, 16, "ixj DSP");
 
 			j->XILINXbase = xio[i];
 			j->cardtype = 0;
@@ -7840,7 +7844,6 @@ int __init ixj_probe_pci(int *cnt)
 	struct pci_dev *pci = NULL;   
 	int i, probe = 0;
 	IXJ *j = NULL;
-	int result;
 
 	for (i = 0; i < IXJMAX - *cnt; i++) {
 		pci = pci_find_device(0x15E2, 0x0500, pci);
@@ -7849,20 +7852,12 @@ int __init ixj_probe_pci(int *cnt)
 
 		if (pci_enable_device(pci))
 			break;
-		if ((result = check_region(pci_resource_start(pci, 0), 16)) < 0) {
-			printk(KERN_INFO "ixj: can't get I/O address\n");
+		j = new_ixj(pci_resource_start(pci, 0));
+		if (!j)
 			break;
-		}
 
-		/* Grab a device slot */	
-		j = ixj_alloc();
-		if(j == NULL)
-			break;
-	
-		j->DSPbase = pci_resource_start(pci, 0);
 		j->serial = (PCIEE_GetSerialNumber)pci_resource_start(pci, 2);
 		j->XILINXbase = j->DSPbase + 0x10;
-		request_region(j->DSPbase, 16, "ixj DSP");
 		j->cardtype = QTI_PHONEJACK_PCI;
 		j->board = *cnt;
 		probe = ixj_selfprobe(j);
diff --git a/drivers/telephony/ixj.h b/drivers/telephony/ixj.h
index ad23b28e6..143818a56 100644
--- a/drivers/telephony/ixj.h
+++ b/drivers/telephony/ixj.h
@@ -1188,12 +1188,12 @@ typedef struct {
 	unsigned int cid_rec_codec;
 	unsigned int cid_rec_volume;
 	unsigned char cid_rec_flag;
-	char rec_mode;
+	signed char rec_mode;
 	unsigned int play_codec;
 	unsigned int cid_play_codec;
 	unsigned int cid_play_volume;
 	unsigned char cid_play_flag;
-	char play_mode;
+	signed char play_mode;
 	IXJ_FLAGS flags;
 	unsigned long busyflags;
 	unsigned int rec_frame_size;
diff --git a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
index 42f60fa37..17a6dd747 100644
--- a/drivers/usb/class/audio.c
+++ b/drivers/usb/class/audio.c
@@ -1954,9 +1954,9 @@ static int usb_audio_open_mixdev(struct inode *inode, struct file *file)
 	struct usb_audio_state *s;
 
 	down(&open_sem);
-	for (devs = audiodevs.next; devs != &audiodevs; devs = devs->next) {
+	list_for_each(devs, &audiodevs) {
 		s = list_entry(devs, struct usb_audio_state, audiodev);
-		for (mdevs = s->mixerlist.next; mdevs != &s->mixerlist; mdevs = mdevs->next) {
+		list_for_each(mdevs, &s->mixerlist) {
 			ms = list_entry(mdevs, struct usb_mixerdev, list);
 			if (ms->dev_mixer == minor)
 				goto mixer_found;
@@ -2640,9 +2640,9 @@ static int usb_audio_open(struct inode *inode, struct file *file)
 
 	for (;;) {
 		down(&open_sem);
-		for (devs = audiodevs.next; devs != &audiodevs; devs = devs->next) {
+		list_for_each(devs, &audiodevs) {
 			s = list_entry(devs, struct usb_audio_state, audiodev);
-			for (adevs = s->audiolist.next; adevs != &s->audiolist; adevs = adevs->next) {
+			list_for_each(adevs, &s->audiolist) {
 				as = list_entry(adevs, struct usb_audiodev, list);
 				if (!((as->dev_audio ^ minor) & ~0xf))
 					goto device_found;
@@ -3831,7 +3831,7 @@ static void usb_audio_disconnect(struct usb_interface *intf)
 	usb_set_intfdata (intf, NULL);
 
 	/* deregister all audio and mixer devices, so no new processes can open this device */
-	for(list = s->audiolist.next; list != &s->audiolist; list = list->next) {
+	list_for_each(list, &s->audiolist) {
 		as = list_entry(list, struct usb_audiodev, list);
 		usbin_disc(as);
 		usbout_disc(as);
@@ -3843,7 +3843,7 @@ static void usb_audio_disconnect(struct usb_interface *intf)
 		}
 		as->dev_audio = -1;
 	}
-	for(list = s->mixerlist.next; list != &s->mixerlist; list = list->next) {
+	list_for_each(list, &s->mixerlist) {
 		ms = list_entry(list, struct usb_mixerdev, list);
 		if (ms->dev_mixer >= 0) {
 			unregister_sound_mixer(ms->dev_mixer);
diff --git a/drivers/usb/class/bluetty.c b/drivers/usb/class/bluetty.c
index 2e8f5200c..4d8e01895 100644
--- a/drivers/usb/class/bluetty.c
+++ b/drivers/usb/class/bluetty.c
@@ -988,21 +988,13 @@ static void bluetooth_write_bulk_callback (struct urb *urb, struct pt_regs *regs
 static void bluetooth_softint(void *private)
 {
 	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)private, __FUNCTION__);
-	struct tty_struct *tty;
 
 	dbg("%s", __FUNCTION__);
 
-	if (!bluetooth) {
+	if (!bluetooth)
 		return;
-	}
-
-	tty = bluetooth->tty;
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
-		dbg("%s - write wakeup call.", __FUNCTION__);
-		(tty->ldisc.write_wakeup)(tty);
-	}
 
-	wake_up_interruptible(&tty->write_wait);
+	tty_wakeup(bluetooth->tty);
 }
 
 
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 3fae8a6e4..a929a5212 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -142,7 +142,7 @@ static void acm_ctrl_irq(struct urb *urb, struct pt_regs *regs)
 
 		case ACM_IRQ_LINE_STATE:
 
-			newctrl = le16_to_cpu(get_unaligned((__u16 *) data));
+			newctrl = le16_to_cpu(get_unaligned((__le16 *) data));
 
 			if (acm->tty && !acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
 				dbg("calling hangup");
@@ -248,16 +248,11 @@ out:
 static void acm_softint(void *private)
 {
 	struct acm *acm = private;
-	struct tty_struct *tty = acm->tty;
 	dbg("Entering acm_softint.\n");
 	
 	if (!ACM_READY(acm))
 		return;
-
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
-
-	wake_up_interruptible(&tty->write_wait);
+	tty_wakeup(acm->tty);
 }
 
 /*
@@ -367,7 +362,7 @@ static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned c
 	acm->writeurb->dev = acm->dev;
 
 	acm->ready_for_write = 0;
-	stat = usb_submit_urb(acm->writeurb, GFP_NOIO);
+	stat = usb_submit_urb(acm->writeurb, from_user ? GFP_KERNEL : GFP_ATOMIC);
 	if (stat < 0) {
 		dbg("usb_submit_urb(write bulk) failed");
 		acm->ready_for_write = 1;
@@ -583,19 +578,25 @@ next_desc:
 	}
 
 	if (!union_header) {
-		dev_dbg(&intf->dev,"No union descriptor, giving up\n");
-		return -ENODEV;
-	}
-
-	control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0);
-	data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0));
-	if (!control_interface || !data_interface) {
-		dev_dbg(&intf->dev,"no interfaces\n");
-		return -ENODEV;
+		if (call_interface_num > 0) {
+			dev_dbg(&intf->dev,"No union descriptor, using call management descriptor\n");
+			data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num));
+			control_interface = intf;
+		} else {
+			dev_dbg(&intf->dev,"No union descriptor, giving up\n");
+			return -ENODEV;
+		}
+	} else {
+		control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0);
+		data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0));
+		if (!control_interface || !data_interface) {
+			dev_dbg(&intf->dev,"no interfaces\n");
+			return -ENODEV;
+		}
 	}
 	
-	if (data_interface_num != call_interface_num)
-		dev_dbg(&intf->dev,"Seperate call control interface. That is not fully supported.");
+		if (data_interface_num != call_interface_num)
+			dev_dbg(&intf->dev,"Seperate call control interface. That is not fully supported.");
 
 	if (usb_interface_claimed(data_interface)) { /* valid in this context */
 		dev_dbg(&intf->dev,"The data interface isn't available\n");
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index bf72f278b..cc26d9517 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -70,7 +70,7 @@
  */
 
 struct acm_line {
-	__u32 speed;
+	__le32 speed;
 	__u8 stopbits;
 	__u8 parity;
 	__u8 databits;
diff --git a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c
index 6a6dbac49..a9dc047a0 100644
--- a/drivers/usb/class/usb-midi.c
+++ b/drivers/usb/class/usb-midi.c
@@ -55,39 +55,39 @@
 /* ------------------------------------------------------------------------- */
 
 static int singlebyte = 0;
-MODULE_PARM(singlebyte,"i");
+module_param(singlebyte, int, 0);
 MODULE_PARM_DESC(singlebyte,"Enable sending MIDI messages with single message packet");
 
 static int maxdevices = 4;
-MODULE_PARM(maxdevices,"i");
+module_param(maxdevices, int, 0);
 MODULE_PARM_DESC(maxdevices,"Max number of allocatable MIDI device");
 
 static int uvendor     = -1;
-MODULE_PARM(uvendor,"i");
+module_param(uvendor, int, 0);
 MODULE_PARM_DESC(uvendor, "The USB Vendor ID of a semi-compliant interface");
 
 static int uproduct    = -1;
-MODULE_PARM(uproduct,"i");
+module_param(uproduct, int, 0);
 MODULE_PARM_DESC(uproduct, "The USB Product ID of a semi-compliant interface");
 
 static int uinterface  = -1;
-MODULE_PARM(uinterface,"i");
+module_param(uinterface, int, 0);
 MODULE_PARM_DESC(uinterface, "The Interface number of a semi-compliant interface");
 
 static int ualt        = -1;
-MODULE_PARM(ualt,"i");
+module_param(ualt, int, 0);
 MODULE_PARM_DESC(ualt, "The optional alternative setting of a semi-compliant interface");
 
 static int umin        = -1;
-MODULE_PARM(umin,"i");
+module_param(umin, int, 0);
 MODULE_PARM_DESC(umin, "The input endpoint of a semi-compliant interface");
 
 static int umout       = -1;
-MODULE_PARM(umout,"i");
+module_param(umout, int, 0);
 MODULE_PARM_DESC(umout, "The output endpoint of a semi-compliant interface");
 
 static int ucable      = -1;
-MODULE_PARM(ucable,"i");
+module_param(ucable, int, 0);
 MODULE_PARM_DESC(ucable, "The cable number used for a semi-compliant interface");
 
 /** Note -- the usb_string() returns only Latin-1 characters.
@@ -95,7 +95,7 @@ MODULE_PARM_DESC(ucable, "The cable number used for a semi-compliant interface")
  * unicode16LE-to-JIS routine is needed to wrap around usb_get_string().
  **/
 static unsigned short ulangid      = 0x0409; /** 0x0411 for Japanese **/
-MODULE_PARM(ulangid,"h");
+module_param(ulangid, ushort, 0);
 MODULE_PARM_DESC(ulangid, "The optional preferred USB Language ID for all devices");
 
 MODULE_AUTHOR("NAGANO Daisuke <breeze.nagano@nifty.ne.jp>");
@@ -817,9 +817,9 @@ static int usb_midi_open(struct inode *inode, struct file *file)
 
 	for(;;) {
 		down(&open_sem);
-		for (devs = mididevs.next; devs != &mididevs; devs = devs->next) {
+		list_for_each(devs, &mididevs) {
 			s = list_entry(devs, struct usb_midi_state, mididev);
-			for (mdevs = s->midiDevList.next; mdevs != &s->midiDevList; mdevs = mdevs->next) {
+			list_for_each(mdevs, &s->midiDevList) {
 				m = list_entry(mdevs, struct usb_mididev, list);
 				if ( !((m->dev_midi ^ minor) & ~0xf) )
 					goto device_found;
@@ -2012,7 +2012,7 @@ static void usb_midi_disconnect(struct usb_interface *intf)
 	s->usbdev = NULL;
 	usb_set_intfdata (intf, NULL);
 
-	for ( list = s->midiDevList.next; list != &s->midiDevList; list = list->next ) {
+	list_for_each(list, &s->midiDevList) {
 		m = list_entry(list, struct usb_mididev, list);
 		wake_up(&(m->min.ep->wait));
 		wake_up(&(m->mout.ep->wait));
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index b6da40067..da91bbd67 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -221,7 +221,7 @@ static int usblp_set_protocol(struct usblp *usblp, int protocol);
 static int usblp_cache_device_id_string(struct usblp *usblp);
 
 /* forward reference to make our lives easier */
-extern struct usb_driver usblp_driver;
+static struct usb_driver usblp_driver;
 
 /*
  * Functions for usblp control messages.
@@ -397,10 +397,6 @@ static void usblp_cleanup (struct usblp *usblp)
 {
 	info("usblp%d: removed", usblp->minor);
 
-	usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
-			usblp->writebuf, usblp->writeurb->transfer_dma);
-	usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
-			usblp->readbuf, usblp->readurb->transfer_dma);
 	kfree (usblp->device_id_string);
 	kfree (usblp->statusbuf);
 	usb_free_urb(usblp->writeurb);
@@ -1129,7 +1125,7 @@ static int usblp_cache_device_id_string(struct usblp *usblp)
 	/* First two bytes are length in big-endian.
 	 * They count themselves, and we copy them into
 	 * the user's buffer. */
-	length = be16_to_cpu(*((u16 *)usblp->device_id_string));
+	length = be16_to_cpu(*((__be16 *)usblp->device_id_string));
 	if (length < 2)
 		length = 2;
 	else if (length >= USBLP_DEVICE_ID_SIZE)
@@ -1159,6 +1155,10 @@ static void usblp_disconnect(struct usb_interface *intf)
 	usb_set_intfdata (intf, NULL);
 
 	usblp_unlink_urbs(usblp);
+	usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
+			usblp->writebuf, usblp->writeurb->transfer_dma);
+	usb_buffer_free (usblp->dev, USBLP_BUF_SIZE,
+			usblp->readbuf, usblp->readurb->transfer_dma);
 
 	if (!usblp->used)
 		usblp_cleanup (usblp);
@@ -1208,6 +1208,6 @@ module_exit(usblp_exit);
 
 MODULE_AUTHOR( DRIVER_AUTHOR );
 MODULE_DESCRIPTION( DRIVER_DESC );
-MODULE_PARM(proto_bias, "i");
+module_param(proto_bias, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(proto_bias, "Favourite protocol number");
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index 050b078e3..1a9ff6184 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -60,3 +60,40 @@ config USB_DYNAMIC_MINORS
 
 	  If you are unsure about this, say N here.
 
+config USB_SUSPEND
+	bool "USB suspend/resume (EXPERIMENTAL)"
+	depends on USB && PM && EXPERIMENTAL
+	help
+	  If you say Y here, you can use driver calls or the sysfs
+	  "power/state" file to suspend or resume individual USB
+	  peripherals.  There are many related features, such as
+	  remote wakeup and driver-specific suspend processing, that
+	  may not yet work as expected.
+
+	  If you are unsure about this, say N here.
+
+
+config USB_OTG
+	bool
+	depends on USB && EXPERIMENTAL
+	select USB_SUSPEND
+	default n
+
+
+config USB_OTG_WHITELIST
+	bool "Rely on OTG Targeted Peripherals List"
+	depends on USB_OTG
+	default y
+	help
+	  If you say Y here, the "otg_whitelist.h" file will be used as a
+	  product whitelist, so USB peripherals not listed there will be
+	  rejected during enumeration.  This behavior is required by the
+	  USB OTG specification for all devices not on your product's
+	  "Targeted Peripherals List".
+
+	  Otherwise, peripherals not listed there will only generate a
+	  warning and enumeration will continue.  That's more like what
+	  normal Linux-USB hosts do (other than the warning), and is
+	  convenient for many stages of product development.
+
+
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index ae7ec7405..33c51714f 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -106,7 +106,7 @@ skip_to_next_endpoint_or_interface_descriptor:
 	return buffer - buffer0 + i;
 }
 
-static void usb_release_interface_cache(struct kref *ref)
+void usb_release_interface_cache(struct kref *ref)
 {
 	struct usb_interface_cache *intfc = ref_to_usb_interface_cache(ref);
 	int j;
@@ -356,7 +356,7 @@ int usb_parse_configuration(struct device *ddev, int cfgidx,
 		if (!intfc)
 			return -ENOMEM;
 		memset(intfc, 0, len);
-		kref_init(&intfc->ref, usb_release_interface_cache);
+		kref_init(&intfc->ref);
 	}
 
 	/* Skip over any Class Specific or Vendor Specific descriptors;
@@ -422,7 +422,8 @@ void usb_destroy_configuration(struct usb_device *dev)
 
 		for (i = 0; i < cf->desc.bNumInterfaces; i++) {
 			if (cf->intf_cache[i])
-				kref_put(&cf->intf_cache[i]->ref);
+				kref_put(&cf->intf_cache[i]->ref, 
+					  usb_release_interface_cache);
 		}
 	}
 	kfree(dev->config);
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 5541363b6..8e535789f 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -283,9 +283,8 @@ static char *usb_dump_interface(
 
 /* TBD:
  * 0. TBDs
- * 1. marking active config and ifaces (code lists all, but should mark
+ * 1. marking active interface altsettings (code lists all, but should mark
  *    which ones are active, if any)
- * 2. add <halted> status to each endpoint line
  */
 
 static char *usb_dump_config_descriptor(char *start, char *end, const struct usb_config_descriptor *desc, int active)
@@ -584,7 +583,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbyte
 
 	/* enumerate busses */
 	down (&usb_bus_list_lock);
-	for (buslist = usb_bus_list.next; buslist != &usb_bus_list; buslist = buslist->next) {
+	list_for_each(buslist, &usb_bus_list) {
 		/* print devices for this bus */
 		bus = list_entry(buslist, struct usb_bus, bus_list);
 
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 6f969a4da..776c1bf0d 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -72,6 +72,8 @@ MODULE_PARM_DESC (usbfs_snoop, "true to log all usbfs traffic");
 	} while (0)
 
 
+#define	MAX_USBFS_BUFFER_SIZE	16384
+
 static inline int connected (struct usb_device *dev)
 {
 	return dev->state != USB_STATE_NOTATTACHED;
@@ -555,8 +557,10 @@ static int proc_control(struct dev_state *ps, void __user *arg)
 		snoop(&dev->dev, "control read: bRequest=%02x bRrequestType=%02x wValue=%04x wIndex=%04x\n", 
 			ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, ctrl.wIndex);
 
+		up(&dev->serialize);
 		i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType,
 				       ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo);
+		down(&dev->serialize);
 		if ((i > 0) && ctrl.wLength) {
 			if (usbfs_snoop) {
 				dev_info(&dev->dev, "control read: data ");
@@ -584,8 +588,10 @@ static int proc_control(struct dev_state *ps, void __user *arg)
 				printk ("%02x ", (unsigned char)(tbuf)[j]);
 			printk("\n");
 		}
+		up(&dev->serialize);
 		i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType,
 				       ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo);
+		down(&dev->serialize);
 	}
 	free_page((unsigned long)tbuf);
 	if (i<0) {
@@ -619,6 +625,8 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
 	if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN)))
 		return -EINVAL;
 	len1 = bulk.len;
+	if (len1 > MAX_USBFS_BUFFER_SIZE)
+		return -EINVAL;
 	if (!(tbuf = kmalloc(len1, GFP_KERNEL)))
 		return -ENOMEM;
 	tmo = (bulk.timeout * HZ + 999) / 1000;
@@ -627,7 +635,9 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
 			kfree(tbuf);
 			return -EINVAL;
 		}
+		up(&dev->serialize);
 		i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
+		down(&dev->serialize);
 		if (!i && len2) {
 			if (copy_to_user(bulk.data, tbuf, len2)) {
 				kfree(tbuf);
@@ -641,7 +651,9 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
 				return -EFAULT;
 			}
 		}
+		up(&dev->serialize);
 		i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
+		down(&dev->serialize);
 	}
 	kfree(tbuf);
 	if (i < 0) {
@@ -849,7 +861,7 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)
 
 	case USBDEVFS_URB_TYPE_BULK:
 		uurb.number_of_packets = 0;
-		if (uurb.buffer_length > 16384)
+		if (uurb.buffer_length > MAX_USBFS_BUFFER_SIZE)
 			return -EINVAL;
 		if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))
 			return -EFAULT;
@@ -891,7 +903,7 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)
 			interval = 1 << min (15, ep_desc->bInterval - 1);
 		else
 			interval = ep_desc->bInterval;
-		if (uurb.buffer_length > 16384)
+		if (uurb.buffer_length > MAX_USBFS_BUFFER_SIZE)
 			return -EINVAL;
 		if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))
 			return -EFAULT;
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index e7a7ba513..5fdaae079 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -65,7 +65,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
 {
 	struct hc_driver	*driver;
 	unsigned long		resource, len;
-	void			*base;
+	void __iomem		*base;
 	struct usb_hcd		*hcd;
 	int			retval, region;
 	char			buf [8], *bufp = buf;
@@ -121,7 +121,7 @@ clean_1:
 			dev_dbg (&dev->dev, "no i/o regions available\n");
 			return -EBUSY;
 		}
-		base = (void *) resource;
+		base = (void __iomem *) resource;
 	}
 
 	// driver->reset(), later on, will transfer device from
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index cd2268ad1..d970e2c0c 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -708,6 +708,7 @@ int usb_register_bus(struct usb_bus *bus)
 		bus->busnum = busnum;
 	} else {
 		printk (KERN_ERR "%s: too many buses\n", usbcore_name);
+		up(&usb_bus_list_lock);
 		return -E2BIG;
 	}
 
@@ -790,6 +791,8 @@ int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev
 	usb_dev->epmaxpacketin[0] = usb_dev->epmaxpacketout[0] = 64;
 	retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);
 	if (retval != sizeof usb_dev->descriptor) {
+		usb_dev->bus->root_hub = NULL;
+		up (&usb_bus_list_lock);
 		dev_dbg (parent_dev, "can't read %s device descriptor %d\n",
 				usb_dev->dev.bus_id, retval);
 		return (retval < 0) ? retval : -EMSGSIZE;
@@ -1311,13 +1314,10 @@ static void hcd_endpoint_disable (struct usb_device *udev, int endpoint)
 
 rescan:
 	/* (re)block new requests, as best we can */
-	if (endpoint & USB_DIR_IN) {
-		usb_endpoint_halt (udev, epnum, 0);
+	if (endpoint & USB_DIR_IN)
 		udev->epmaxpacketin [epnum] = 0;
-	} else {
-		usb_endpoint_halt (udev, epnum, 1);
+	else
 		udev->epmaxpacketout [epnum] = 0;
-	}
 
 	/* then kill any current requests */
 	spin_lock (&hcd_data_lock);
@@ -1407,6 +1407,45 @@ static int hcd_hub_resume (struct usb_bus *bus)
 
 /*-------------------------------------------------------------------------*/
 
+#ifdef	CONFIG_USB_OTG
+
+/**
+ * usb_bus_start_enum - start immediate enumeration (for OTG)
+ * @bus: the bus (must use hcd framework)
+ * @port: 1-based number of port; usually bus->otg_port
+ * Context: in_interrupt()
+ *
+ * Starts enumeration, with an immediate reset followed later by
+ * khubd identifying and possibly configuring the device.
+ * This is needed by OTG controller drivers, where it helps meet
+ * HNP protocol timing requirements for starting a port reset.
+ */
+int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num)
+{
+	struct usb_hcd		*hcd;
+	int			status = -EOPNOTSUPP;
+
+	/* NOTE: since HNP can't start by grabbing the bus's address0_sem,
+	 * boards with root hubs hooked up to internal devices (instead of
+	 * just the OTG port) may need more attention to resetting...
+	 */
+	hcd = container_of (bus, struct usb_hcd, self);
+	if (port_num && hcd->driver->start_port_reset)
+		status = hcd->driver->start_port_reset(hcd, port_num);
+
+	/* run khubd shortly after (first) root port reset finishes;
+	 * it may issue others, until at least 50 msecs have passed.
+	 */
+	if (status == 0)
+		mod_timer(&hcd->rh_timer, jiffies + msecs_to_jiffies(10));
+	return status;
+}
+EXPORT_SYMBOL (usb_bus_start_enum);
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
 /* called by khubd, rmmod, apmd, or other thread for hcd-private cleanup.
  * we're guaranteed that the device is fully quiesced.  also, that each
  * endpoint has been hcd_endpoint_disabled.
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index 89b6fc2e3..340977b72 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -77,7 +77,7 @@ struct usb_hcd {	/* usb_bus.hcpriv points to this */
 	unsigned		can_wakeup:1;	/* hw supports wakeup? */
 	unsigned		remote_wakeup:1;/* sw should use wakeup? */
 	int			irq;		/* irq allocated */
-	void			*regs;		/* device memory/io */
+	void __iomem		*regs;		/* device memory/io */
 
 #ifdef	CONFIG_PCI
 	int			region;		/* pci region for regs */
@@ -212,6 +212,7 @@ struct hc_driver {
 				char *buf, u16 wLength);
 	int		(*hub_suspend)(struct usb_hcd *);
 	int		(*hub_resume)(struct usb_hcd *);
+	int		(*start_port_reset)(struct usb_hcd *, unsigned port_num);
 };
 
 extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs);
@@ -376,8 +377,6 @@ extern void usb_bus_put (struct usb_bus *bus);
 extern int usb_find_interface_driver (struct usb_device *dev,
 	struct usb_interface *interface);
 
-#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep)))
-
 #define usb_endpoint_out(ep_dir)	(!((ep_dir) & USB_DIR_IN))
 
 /*
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index b13fe4040..7f72ee96c 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -36,7 +36,7 @@
 #include "hcd.h"
 #include "hub.h"
 
-/* Protect all struct usb_device state members */
+/* Protect struct usb_device state and children members */
 static spinlock_t device_state_lock = SPIN_LOCK_UNLOCKED;
 
 /* Wakes up khubd */
@@ -143,7 +143,7 @@ static void led_work (void *__hub)
 	unsigned		changed = 0;
 	int			cursor = -1;
 
-	if (hdev->state != USB_STATE_CONFIGURED)
+	if (hdev->state != USB_STATE_CONFIGURED || hub->quiescing)
 		return;
 
 	for (i = 0; i < hub->descriptor->bNbrPorts; i++) {
@@ -269,6 +269,9 @@ static void hub_irq(struct urb *urb, struct pt_regs *regs)
 	spin_unlock(&hub_event_lock);
 
 resubmit:
+	if (hub->quiescing)
+		return;
+
 	if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0
 			&& status != -ENODEV && status != -EPERM)
 		dev_err (&hub->intf->dev, "resubmit --> %d\n", status);
@@ -623,6 +626,33 @@ fail:
 
 static unsigned highspeed_hubs;
 
+static void hub_quiesce(struct usb_hub *hub)
+{
+	/* stop khubd and related activity */
+	hub->quiescing = 1;
+	usb_kill_urb(hub->urb);
+	if (hub->has_indicators)
+		cancel_delayed_work(&hub->leds);
+	if (hub->has_indicators || hub->tt.hub)
+		flush_scheduled_work();
+}
+
+#ifdef	CONFIG_USB_SUSPEND
+
+static void hub_reactivate(struct usb_hub *hub)
+{
+	int	status;
+
+	hub->quiescing = 0;
+	status = usb_submit_urb(hub->urb, GFP_NOIO);
+	if (status < 0)
+		dev_err(&hub->intf->dev, "reactivate --> %d\n", status);
+	if (hub->has_indicators && blinkenlights)
+		schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
+}
+
+#endif
+
 static void hub_disconnect(struct usb_interface *intf)
 {
 	struct usb_hub *hub = usb_get_intfdata (intf);
@@ -637,22 +667,14 @@ static void hub_disconnect(struct usb_interface *intf)
 
 	usb_set_intfdata (intf, NULL);
 
-	if (hub->urb) {
-		usb_kill_urb(hub->urb);
-		usb_free_urb(hub->urb);
-		hub->urb = NULL;
-	}
+	hub_quiesce(hub);
+	usb_free_urb(hub->urb);
+	hub->urb = NULL;
 
 	spin_lock_irq(&hub_event_lock);
 	list_del_init(&hub->event_list);
 	spin_unlock_irq(&hub_event_lock);
 
-	/* assuming we used keventd, it must quiesce too */
-	if (hub->has_indicators)
-		cancel_delayed_work (&hub->leds);
-	if (hub->has_indicators || hub->tt.hub)
-		flush_scheduled_work ();
-
 	if (hub->descriptor) {
 		kfree(hub->descriptor);
 		hub->descriptor = NULL;
@@ -772,6 +794,7 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
 	}
 }
 
+/* caller has locked the hub and must own the device lock */
 static int hub_reset(struct usb_hub *hub)
 {
 	struct usb_device *hdev = hub->hdev;
@@ -789,7 +812,7 @@ static int hub_reset(struct usb_hub *hub)
 	else
 		return -1;
 
-	if (usb_reset_device(hdev))
+	if (__usb_reset_device(hdev))
 		return -1;
 
 	hub->urb->dev = hdev;                                                    
@@ -801,6 +824,7 @@ static int hub_reset(struct usb_hub *hub)
 	return 0;
 }
 
+/* caller has locked the hub */
 /* FIXME!  This routine should be subsumed into hub_reset */
 static void hub_start_disconnect(struct usb_device *hdev)
 {
@@ -832,12 +856,65 @@ static void recursively_mark_NOTATTACHED(struct usb_device *udev)
 	udev->state = USB_STATE_NOTATTACHED;
 }
 
+/* grab device/port lock, returning index of that port (zero based).
+ * protects the upstream link used by this device from concurrent
+ * tree operations like suspend, resume, reset, and disconnect, which
+ * apply to everything downstream of a given port.
+ */
+static int locktree(struct usb_device *udev)
+{
+	int			t;
+	struct usb_device	*hdev;
+
+	if (!udev)
+		return -ENODEV;
+
+	/* root hub is always the first lock in the series */
+	hdev = udev->parent;
+	if (!hdev) {
+		down(&udev->serialize);
+		return 0;
+	}
+
+	/* on the path from root to us, lock everything from
+	 * top down, dropping parent locks when not needed
+	 *
+	 * NOTE: if disconnect were to ignore the locking, we'd need
+	 * to get extra refcounts to everything since hdev->children
+	 * and udev->parent could be invalidated while we work...
+	 */
+	t = locktree(hdev);
+	if (t < 0)
+		return t;
+	spin_lock_irq(&device_state_lock);
+	for (t = 0; t < hdev->maxchild; t++) {
+		if (hdev->children[t] == udev) {
+			/* everything is fail-fast once disconnect
+			 * processing starts
+			 */
+			if (udev->state == USB_STATE_NOTATTACHED)
+				break;
+
+			/* when everyone grabs locks top->bottom,
+			 * non-overlapping work may be concurrent
+			 */
+			spin_unlock_irq(&device_state_lock);
+			down(&udev->serialize);
+			up(&hdev->serialize);
+			return t;
+		}
+	}
+	spin_unlock_irq(&device_state_lock);
+	up(&hdev->serialize);
+	return -ENODEV;
+}
+
 /**
  * usb_set_device_state - change a device's current state (usbcore-internal)
  * @udev: pointer to device whose state should be changed
  * @new_state: new state value to be stored
  *
- * udev->state is _not_ protected by the udev->serialize semaphore.  This
+ * udev->state is _not_ protected by the device lock.  This
  * is so that devices can be marked as disconnected as soon as possible,
  * without having to wait for the semaphore to be released.  Instead,
  * changes to the state must be protected by the device_state_lock spinlock.
@@ -897,7 +974,7 @@ static void release_address(struct usb_device *udev)
 
 /**
  * usb_disconnect - disconnect a device (usbcore-internal)
- * @pdev: pointer to device being disconnected
+ * @pdev: pointer to device being disconnected, into a locked hub
  * Context: !in_interrupt ()
  *
  * Something got disconnected. Get rid of it, and all of its children.
@@ -921,7 +998,8 @@ void usb_disconnect(struct usb_device **pdev)
 	}
 
 	/* mark the device as inactive, so any further urb submissions for
-	 * this device will fail.
+	 * this device (and any of its children) will fail immediately.
+	 * this quiesces everyting except pending urbs.
 	 */
 	usb_set_device_state(udev, USB_STATE_NOTATTACHED);
 
@@ -940,6 +1018,7 @@ void usb_disconnect(struct usb_device **pdev)
 
 	/* deallocate hcd/hardware state ... nuking all pending urbs and
 	 * cleaning up all state associated with the current configuration
+	 * so that the hardware is now fully quiesced.
 	 */
 	usb_disable_device(udev, 0);
 
@@ -952,7 +1031,7 @@ void usb_disconnect(struct usb_device **pdev)
 	usbfs_remove_device(udev);
 	usb_remove_sysfs_dev_files(udev);
 
-	/* Avoid races with recursively_mark_NOTATTACHED() */
+	/* Avoid races with recursively_mark_NOTATTACHED() and locktree() */
 	spin_lock_irq(&device_state_lock);
 	*pdev = NULL;
 	spin_unlock_irq(&device_state_lock);
@@ -1016,6 +1095,10 @@ static inline void show_string(struct usb_device *udev, char *id, int index)
 {}
 #endif
 
+#ifdef	CONFIG_USB_OTG
+#include "otg_whitelist.h"
+#endif
+
 /**
  * usb_new_device - perform initial device setup (usbcore-internal)
  * @udev: newly addressed device (in ADDRESS state)
@@ -1065,6 +1148,79 @@ int usb_new_device(struct usb_device *udev)
 		show_string(udev, "SerialNumber",
 				udev->descriptor.iSerialNumber);
 
+#ifdef	CONFIG_USB_OTG
+	/*
+	 * OTG-aware devices on OTG-capable root hubs may be able to use SRP,
+	 * to wake us after we've powered off VBUS; and HNP, switching roles
+	 * "host" to "peripheral".  The OTG descriptor helps figure this out.
+	 */
+	if (!udev->bus->is_b_host
+			&& udev->config
+			&& udev->parent == udev->bus->root_hub) {
+		struct usb_otg_descriptor	*desc = 0;
+		struct usb_bus			*bus = udev->bus;
+
+		/* descriptor may appear anywhere in config */
+		if (__usb_get_extra_descriptor (udev->rawdescriptors[0],
+					udev->config[0].desc.wTotalLength,
+					USB_DT_OTG, (void **) &desc) == 0) {
+			if (desc->bmAttributes & USB_OTG_HNP) {
+				unsigned		port;
+				struct usb_device	*root = udev->parent;
+				
+				for (port = 0; port < root->maxchild; port++) {
+					if (root->children[port] == udev)
+						break;
+				}
+				port++;
+
+				dev_info(&udev->dev,
+					"Dual-Role OTG device on %sHNP port\n",
+					(port == bus->otg_port)
+						? "" : "non-");
+
+				/* enable HNP before suspend, it's simpler */
+				if (port == bus->otg_port)
+					bus->b_hnp_enable = 1;
+				err = usb_control_msg(udev,
+					usb_sndctrlpipe(udev, 0),
+					USB_REQ_SET_FEATURE, 0,
+					bus->b_hnp_enable
+						? USB_DEVICE_B_HNP_ENABLE
+						: USB_DEVICE_A_ALT_HNP_SUPPORT,
+					0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
+				if (err < 0) {
+					/* OTG MESSAGE: report errors here,
+					 * customize to match your product.
+					 */
+					dev_info(&udev->dev,
+						"can't set HNP mode; %d\n",
+						err);
+					bus->b_hnp_enable = 0;
+				}
+			}
+		}
+	}
+
+	if (!is_targeted(udev)) {
+
+		/* Maybe it can talk to us, though we can't talk to it.
+		 * (Includes HNP test device.)
+		 */
+		if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
+			static int __usb_suspend_device (struct usb_device *,
+						int port, u32 state);
+			err = __usb_suspend_device(udev,
+					udev->bus->otg_port - 1,
+					PM_SUSPEND_MEM);
+			if (err < 0)
+				dev_dbg(&udev->dev, "HNP fail, %d\n", err);
+		}
+		err = -ENODEV;
+		goto fail;
+	}
+#endif
+
 	/* put device-specific files into sysfs */
 	err = device_add (&udev->dev);
 	if (err) {
@@ -1203,6 +1359,7 @@ static int hub_port_reset(struct usb_device *hdev, int port,
 		if (status == -ENOTCONN || status == 0) {
 			clear_port_feature(hdev,
 				port + 1, USB_PORT_FEAT_C_RESET);
+			/* FIXME need disconnect() for NOTATTACHED device */
 			usb_set_device_state(udev, status
 					? USB_STATE_NOTATTACHED
 					: USB_STATE_DEFAULT);
@@ -1226,9 +1383,11 @@ static int hub_port_disable(struct usb_device *hdev, int port)
 {
 	int ret;
 
-	if (hdev->children[port])
+	if (hdev->children[port]) {
+		/* FIXME need disconnect() for NOTATTACHED device */
 		usb_set_device_state(hdev->children[port],
 				USB_STATE_NOTATTACHED);
+	}
 	ret = clear_port_feature(hdev, port + 1, USB_PORT_FEAT_ENABLE);
 	if (ret)
 		dev_err(hubdev(hdev), "cannot disable port %d (err = %d)\n",
@@ -1239,7 +1398,490 @@ static int hub_port_disable(struct usb_device *hdev, int port)
 
 #ifdef	CONFIG_USB_SUSPEND
 
-	/* no USB_SUSPEND yet! */
+/*
+ * Selective port suspend reduces power; most suspended devices draw
+ * less than 500 uA.  It's also used in OTG, along with remote wakeup.
+ * All devices below the suspended port are also suspended.
+ *
+ * Devices leave suspend state when the host wakes them up.  Some devices
+ * also support "remote wakeup", where the device can activate the USB
+ * tree above them to deliver data, such as a keypress or packet.  In
+ * some cases, this wakes the USB host.
+ */
+static int hub_port_suspend(struct usb_device *hdev, int port)
+{
+	int			status;
+	struct usb_device	*udev;
+
+	udev = hdev->children[port - 1];
+	// dev_dbg(hubdev(hdev), "suspend port %d\n", port);
+
+	/* enable remote wakeup when appropriate; this lets the device
+	 * wake up the upstream hub (including maybe the root hub).
+	 *
+	 * NOTE:  OTG devices may issue remote wakeup (or SRP) even when
+	 * we don't explicitly enable it here.
+	 */
+	if (udev->actconfig
+			// && FIXME (remote wakeup enabled on this bus)
+			// ... currently assuming it's always appropriate
+			&& (udev->actconfig->desc.bmAttributes
+				& USB_CONFIG_ATT_WAKEUP) != 0) {
+		status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+				USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
+				USB_DEVICE_REMOTE_WAKEUP, 0,
+				NULL, 0,
+				USB_CTRL_SET_TIMEOUT);
+		if (status)
+			dev_dbg(&udev->dev,
+				"won't remote wakeup, status %d\n",
+				status);
+	}
+
+	/* see 7.1.7.6 */
+	status = set_port_feature(hdev, port, USB_PORT_FEAT_SUSPEND);
+	if (status) {
+		dev_dbg(hubdev(hdev),
+			"can't suspend port %d, status %d\n",
+			port, status);
+		/* paranoia:  "should not happen" */
+		(void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+				USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE,
+				USB_DEVICE_REMOTE_WAKEUP, 0,
+				NULL, 0,
+				USB_CTRL_SET_TIMEOUT);
+	} else {
+		/* device has up to 10 msec to fully suspend */
+		dev_dbg(&udev->dev, "usb suspend\n");
+		udev->state = USB_STATE_SUSPENDED;
+		msleep(10);
+	}
+	return status;
+}
+
+/*
+ * Devices on USB hub ports have only one "suspend" state, corresponding
+ * to ACPI D2 (PM_SUSPEND_MEM), "may cause the device to lose some context".
+ * State transitions include:
+ *
+ *   - suspend, resume ... when the VBUS power link stays live
+ *   - suspend, disconnect ... VBUS lost
+ *
+ * Once VBUS drop breaks the circuit, the port it's using has to go through
+ * normal re-enumeration procedures, starting with enabling VBUS power.
+ * Other than re-initializing the hub (plug/unplug, except for root hubs),
+ * Linux (2.6) currently has NO mechanisms to initiate that:  no khubd
+ * timer, no SRP, no requests through sysfs.
+ */
+static int __usb_suspend_device (struct usb_device *udev, int port, u32 state)
+{
+	int	status;
+
+	if (port < 0)
+		return port;
+
+	/* NOTE:  udev->serialize released on all real returns! */
+
+	if (state <= udev->dev.power.power_state
+			|| state < PM_SUSPEND_MEM
+			|| udev->state == USB_STATE_SUSPENDED
+			|| udev->state == USB_STATE_NOTATTACHED) {
+		up(&udev->serialize);
+		return 0;
+	}
+
+	/* suspend interface drivers; if this is a hub, it
+	 * suspends the child devices
+	 */
+	if (udev->actconfig) {
+		int	i;
+
+		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+			struct usb_interface	*intf;
+			struct usb_driver	*driver;
+
+			intf = udev->actconfig->interface[i];
+			if (state <= intf->dev.power.power_state)
+				continue;
+			if (!intf->dev.driver)
+				continue;
+			driver = to_usb_driver(intf->dev.driver);
+
+			if (driver->suspend) {
+				status = driver->suspend(intf, state);
+				if (intf->dev.power.power_state != state
+						|| status)
+					dev_err(&intf->dev,
+						"suspend %d fail, code %d\n",
+						state, status);
+			}
+
+			/* only drivers with suspend() can ever resume();
+			 * and after power loss, even they won't.
+			 * bus_rescan_devices() can rebind drivers later.
+			 *
+			 * FIXME the PM core self-deadlocks when unbinding
+			 * drivers during suspend/resume ... everything grabs
+			 * dpm_sem (not a spinlock, ugh).  we want to unbind,
+			 * since we know every driver's probe/disconnect works
+			 * even for drivers that can't suspend.
+			 */
+			if (!driver->suspend || state > PM_SUSPEND_MEM) {
+#if 1
+				dev_warn(&intf->dev, "resume is unsafe!\n");
+#else
+				down_write(&usb_bus_type.rwsem);
+				device_release_driver(&intf->dev);
+				up_write(&usb_bus_type.rwsem);
+#endif
+			}
+		}
+	}
+
+	/*
+	 * FIXME this needs port power off call paths too, to help force
+	 * USB into the "generic" PM model.  At least for devices on
+	 * ports that aren't using ganged switching (usually root hubs).
+	 *
+	 * NOTE: SRP-capable links should adopt more aggressive poweroff
+	 * policies (when HNP doesn't apply) once we have mechanisms to
+	 * turn power back on!  (Likely not before 2.7...)
+	 */
+	if (state > PM_SUSPEND_MEM) {
+		dev_warn(&udev->dev, "no poweroff yet, suspending instead\n");
+		state = PM_SUSPEND_MEM;
+	}
+
+	/* "global suspend" of the HC-to-USB interface (root hub), or
+	 * "selective suspend" of just one hub-device link.
+	 */
+	if (!udev->parent) {
+		struct usb_bus	*bus = udev->bus;
+		if (bus && bus->op->hub_suspend)
+			status = bus->op->hub_suspend (bus);
+		else
+			status = -EOPNOTSUPP;
+	} else
+		status = hub_port_suspend(udev->parent, port + 1);
+
+	if (status == 0)
+		udev->dev.power.power_state = state;
+	up(&udev->serialize);
+	return status;
+}
+
+/**
+ * usb_suspend_device - suspend a usb device
+ * @udev: device that's no longer in active use
+ * @state: PM_SUSPEND_MEM to suspend
+ * Context: must be able to sleep; device not locked
+ *
+ * Suspends a USB device that isn't in active use, conserving power.
+ * Devices may wake out of a suspend, if anything important happens,
+ * using the remote wakeup mechanism.  They may also be taken out of
+ * suspend by the host, using usb_resume_device().  It's also routine
+ * to disconnect devices while they are suspended.
+ *
+ * Suspending OTG devices may trigger HNP, if that's been enabled
+ * between a pair of dual-role devices.  That will change roles, such
+ * as from A-Host to A-Peripheral or from B-Host back to B-Peripheral.
+ *
+ * Returns 0 on success, else negative errno.
+ */
+int usb_suspend_device(struct usb_device *udev, u32 state)
+{
+	return __usb_suspend_device(udev, locktree(udev), state);
+}
+
+/*
+ * hardware resume signaling is finished, either because of selective
+ * resume (by host) or remote wakeup (by device) ... now see what changed
+ * in the tree that's rooted at this device.
+ */
+static int finish_port_resume(struct usb_device *udev)
+{
+	int	status;
+	u16	devstatus;
+
+	/* caller owns udev->serialize */
+	dev_dbg(&udev->dev, "usb resume\n");
+	udev->dev.power.power_state = PM_SUSPEND_ON;
+
+	/* usb ch9 identifies four variants of SUSPENDED, based on what
+	 * state the device resumes to.  Linux currently won't see the
+	 * first two on the host side; they'd be inside hub_port_init()
+	 * during many timeouts, but khubd can't suspend until later.
+	 */
+	udev->state = udev->actconfig
+		? USB_STATE_CONFIGURED
+		: USB_STATE_ADDRESS;
+
+ 	/* 10.5.4.5 says be sure devices in the tree are still there.
+ 	 * For now let's assume the device didn't go crazy on resume,
+	 * and device drivers will know about any resume quirks.
+	 */
+	status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus);
+	if (status < 0)
+		dev_dbg(&udev->dev,
+			"gone after usb resume? status %d\n",
+			status);
+	else if (udev->actconfig) {
+		unsigned	i;
+
+		le16_to_cpus(&devstatus);
+		if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
+			status = usb_control_msg(udev,
+					usb_sndctrlpipe(udev, 0),
+					USB_REQ_CLEAR_FEATURE,
+						USB_RECIP_DEVICE,
+					USB_DEVICE_REMOTE_WAKEUP, 0,
+					NULL, 0,
+					USB_CTRL_SET_TIMEOUT);
+			if (status) {
+				dev_dbg(&udev->dev, "disable remote "
+					"wakeup, status %d\n", status);
+				status = 0;
+			}
+		}
+
+		/* resume interface drivers; if this is a hub, it
+		 * resumes the child devices
+		 */
+		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+			struct usb_interface	*intf;
+			struct usb_driver	*driver;
+
+			intf = udev->actconfig->interface[i];
+			if (intf->dev.power.power_state == PM_SUSPEND_ON)
+				continue;
+			if (!intf->dev.driver) {
+				/* FIXME maybe force to alt 0 */
+				continue;
+			}
+			driver = to_usb_driver(intf->dev.driver);
+
+			/* bus_rescan_devices() may rebind drivers */
+			if (!driver->resume)
+				continue;
+
+			/* can we do better than just logging errors? */
+			status = driver->resume(intf);
+			if (intf->dev.power.power_state != PM_SUSPEND_ON
+					|| status)
+				dev_dbg(&intf->dev,
+					"resume fail, state %d code %d\n",
+					intf->dev.power.power_state, status);
+		}
+		status = 0;
+
+	} else if (udev->devnum <= 0) {
+		dev_dbg(&udev->dev, "bogus resume!\n");
+		status = -EINVAL;
+	}
+	return status;
+}
+
+static int
+hub_port_resume(struct usb_device *hdev, int port)
+{
+	int			status;
+	struct usb_device	*udev;
+
+	udev = hdev->children[port - 1];
+	// dev_dbg(hubdev(hdev), "resume port %d\n", port);
+
+	/* see 7.1.7.7; affects power usage, but not budgeting */
+	status = clear_port_feature(hdev, port, USB_PORT_FEAT_SUSPEND);
+	if (status) {
+		dev_dbg(&hdev->actconfig->interface[0]->dev,
+			"can't resume port %d, status %d\n",
+			port, status);
+	} else {
+		u16		devstatus;
+		u16		portchange;
+
+		/* drive resume for at least 20 msec */
+		dev_dbg(&udev->dev, "RESUME\n");
+		msleep(25);
+
+#define LIVE_FLAGS	( USB_PORT_STAT_POWER \
+			| USB_PORT_STAT_ENABLE \
+			| USB_PORT_STAT_CONNECTION)
+
+		/* Virtual root hubs can trigger on GET_PORT_STATUS to
+		 * stop resume signaling.  Then finish the resume
+		 * sequence.
+		 */
+		devstatus = portchange = 0;
+		status = hub_port_status(hdev, port - 1,
+				&devstatus, &portchange);
+		if (status < 0
+				|| (devstatus & LIVE_FLAGS) != LIVE_FLAGS
+				|| (devstatus & USB_PORT_STAT_SUSPEND) != 0
+				) {
+			dev_dbg(&hdev->actconfig->interface[0]->dev,
+				"port %d status %04x.%04x after resume, %d\n",
+				port, portchange, devstatus, status);
+		} else {
+			/* TRSMRCY = 10 msec */
+			msleep(10);
+			status = finish_port_resume(udev);
+		}
+	}
+	if (status < 0)
+		status = hub_port_disable(hdev, port);
+
+	return status;
+}
+
+static int hub_resume (struct usb_interface *intf);
+
+/**
+ * usb_resume_device - re-activate a suspended usb device
+ * @udev: device to re-activate
+ * Context: must be able to sleep; device not locked
+ *
+ * This will re-activate the suspended device, increasing power usage
+ * while letting drivers communicate again with its endpoints.
+ * USB resume explicitly guarantees that the power session between
+ * the host and the device is the same as it was when the device
+ * suspended.
+ *
+ * Returns 0 on success, else negative errno.
+ */
+int usb_resume_device(struct usb_device *udev)
+{
+	int			port, status;
+
+	port = locktree(udev);
+	if (port < 0)
+		return port;
+
+	/* "global resume" of the HC-to-USB interface (root hub), or
+	 * selective resume of one hub-to-device port
+	 */
+	if (!udev->parent) {
+		struct usb_bus	*bus = udev->bus;
+		if (bus && bus->op->hub_resume)
+			status = bus->op->hub_resume (bus);
+		else
+			status = -EOPNOTSUPP;
+		if (status == 0) {
+			/* TRSMRCY = 10 msec */
+			msleep(10);
+			status = hub_resume (bus->root_hub
+					->actconfig->interface[0]);
+		}
+	} else if (udev->state == USB_STATE_SUSPENDED) {
+		status = hub_port_resume(udev->parent, port + 1);
+	} else {
+		status = 0;
+		udev->dev.power.power_state = PM_SUSPEND_ON;
+	}
+	if (status < 0) {
+		dev_dbg(&udev->dev, "can't resume, status %d\n",
+			status);
+	}
+
+	up(&udev->serialize);
+
+	/* rebind drivers that had no suspend() */
+	bus_rescan_devices(&usb_bus_type);
+
+	return status;
+}
+
+static int remote_wakeup(struct usb_device *udev)
+{
+	int	status = 0;
+
+	/* don't repeat RESUME sequence if this device
+	 * was already woken up by some other task
+	 */
+	down(&udev->serialize);
+	if (udev->state == USB_STATE_SUSPENDED) {
+		dev_dbg(&udev->dev, "RESUME (wakeup)\n");
+		/* TRSMRCY = 10 msec */
+		msleep(10);
+		status = finish_port_resume(udev);
+	}
+	up(&udev->serialize);
+	return status;
+}
+
+static int hub_suspend(struct usb_interface *intf, u32 state)
+{
+	struct usb_hub		*hub = usb_get_intfdata (intf);
+	struct usb_device	*hdev = hub->hdev;
+	unsigned		port;
+	int			status;
+
+	/* stop khubd and related activity */
+	hub_quiesce(hub);
+
+	/* then suspend every port */
+	for (port = 0; port < hdev->maxchild; port++) {
+		struct usb_device	*udev;
+
+		udev = hdev->children [port];
+		if (!udev)
+			continue;
+		down(&udev->serialize);
+		status = __usb_suspend_device(udev, port, state);
+		if (status < 0)
+			dev_dbg(&intf->dev, "suspend port %d --> %d\n",
+				port, status);
+	}
+
+	intf->dev.power.power_state = state;
+	return 0;
+}
+
+static int hub_resume(struct usb_interface *intf)
+{
+	struct usb_device	*hdev = interface_to_usbdev(intf);
+	struct usb_hub		*hub = usb_get_intfdata (intf);
+	unsigned		port;
+	int			status;
+
+	for (port = 0; port < hdev->maxchild; port++) {
+		struct usb_device	*udev;
+		u16			portstat, portchange;
+
+		udev = hdev->children [port];
+		status = hub_port_status(hdev, port, &portstat, &portchange);
+		if (status == 0) {
+			if (portchange & USB_PORT_STAT_C_SUSPEND) {
+				clear_port_feature(hdev, port + 1,
+					USB_PORT_FEAT_C_SUSPEND);
+				portchange &= ~USB_PORT_STAT_C_SUSPEND;
+			}
+
+			/* let khubd handle disconnects etc */
+			if (portchange)
+				continue;
+		}
+
+		if (!udev)
+			continue;
+		down (&udev->serialize);
+		if (portstat & USB_PORT_STAT_SUSPEND)
+			status = hub_port_resume(hdev, port + 1);
+		else {
+			status = finish_port_resume(udev);
+			if (status < 0)
+				status = hub_port_disable(hdev, port);
+			if (status < 0)
+				dev_dbg(&intf->dev, "resume port %d --> %d\n",
+					port, status);
+		}
+		up(&udev->serialize);
+	}
+	intf->dev.power.power_state = PM_SUSPEND_ON;
+
+	hub_reactivate(hub);
+	return 0;
+}
 
 #else	/* !CONFIG_USB_SUSPEND */
 
@@ -1369,6 +2011,10 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port)
 			hdev->bus->b_hnp_enable = 0;
 	}
 
+	retval = clear_port_feature(hdev, port, USB_PORT_FEAT_SUSPEND);
+	if (retval < 0 && retval != -EPIPE)
+		dev_dbg(&udev->dev, "can't clear suspend; %d\n", retval);
+
 	/* Some low speed devices have problems with the quick delay, so */
 	/*  be a bit pessimistic with those devices. RHbug #23670 */
 	if (oldspeed == USB_SPEED_LOW)
@@ -1479,8 +2125,6 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port)
 				!= udev->descriptor.bMaxPacketSize0)) {
 		usb_disable_endpoint(udev, 0 + USB_DIR_IN);
 		usb_disable_endpoint(udev, 0 + USB_DIR_OUT);
-		usb_endpoint_running(udev, 0, 1);
-		usb_endpoint_running(udev, 0, 0);
 		udev->epmaxpacketin [0] = udev->descriptor.bMaxPacketSize0;
 		udev->epmaxpacketout[0] = udev->descriptor.bMaxPacketSize0;
 	}
@@ -1574,6 +2218,7 @@ hub_power_remaining (struct usb_hub *hub)
  *	a port enable-change occurs (often caused by EMI);
  *	usb_reset_device() encounters changed descriptors (as from
  *		a firmware download)
+ * caller already locked the hub
  */
 static void hub_port_connect_change(struct usb_hub *hub, int port,
 					u16 portstatus, u16 portchange)
@@ -1596,6 +2241,12 @@ static void hub_port_connect_change(struct usb_hub *hub, int port,
 		usb_disconnect(&hdev->children[port]);
 	clear_bit(port, hub->change_bits);
 
+#ifdef	CONFIG_USB_OTG
+	/* during HNP, don't repeat the debounce */
+	if (hdev->bus->is_b_host)
+		portchange &= ~USB_PORT_STAT_C_CONNECTION;
+#endif
+
 	if (portchange & USB_PORT_STAT_C_CONNECTION) {
 		status = hub_port_debounce(hdev, port);
 		if (status < 0) {
@@ -1780,7 +2431,8 @@ static void hub_events(void)
 
 		/* Lock the device, then check to see if we were
 		 * disconnected while waiting for the lock to succeed. */
-		down(&hdev->serialize);
+		if (locktree(hdev) < 0)
+			break;
 		if (hdev->state != USB_STATE_CONFIGURED ||
 				!hdev->actconfig ||
 				hub != usb_get_intfdata(
@@ -2034,7 +2686,7 @@ static int config_descriptors_changed(struct usb_device *udev)
 }
 
 /**
- * usb_reset_devce - perform a USB port reset to reinitialize a device
+ * usb_reset_device - perform a USB port reset to reinitialize a device
  * @udev: device to reset (not in SUSPENDED or NOTATTACHED state)
  *
  * WARNING - don't reset any device unless drivers for all of its
@@ -2123,7 +2775,7 @@ int __usb_reset_device(struct usb_device *udev)
 		struct usb_interface *intf = udev->actconfig->interface[i];
 		struct usb_interface_descriptor *desc;
 
-		/* set_interface resets host side toggle and halt status even
+		/* set_interface resets host side toggle even
 		 * for altsetting zero.  the interface may have no driver.
 		 */
 		desc = &intf->cur_altsetting->desc;
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index 9e81738fd..7ace2d24d 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -60,8 +60,8 @@
  * See USB 2.0 spec Table 11-19 and Table 11-20
  */
 struct usb_port_status {
-	__u16 wPortStatus;
-	__u16 wPortChange;	
+	__le16 wPortStatus;
+	__le16 wPortChange;	
 } __attribute__ ((packed));
 
 /* 
@@ -103,8 +103,8 @@ struct usb_port_status {
 #define HUB_CHAR_PORTIND        0x0080 /* D7       */
 
 struct usb_hub_status {
-	__u16 wHubStatus;
-	__u16 wHubChange;
+	__le16 wHubStatus;
+	__le16 wHubChange;
 } __attribute__ ((packed));
 
 /*
@@ -190,8 +190,8 @@ struct usb_hub {
 	struct usb_device	*hdev;
 	struct urb		*urb;		/* for interrupt polling pipe */
 
-	/* buffer for urb ... 1 bit each for hub and children, rounded up */
-	char			(*buffer)[(USB_MAXCHILDREN + 1 + 7) / 8];
+	/* buffer for urb ... with extra space in case of babble */
+	char			(*buffer)[8];
 	dma_addr_t		buffer_dma;	/* DMA address for buffer */
 	union {
 		struct usb_hub_status	hub;
@@ -214,6 +214,8 @@ struct usb_hub {
 
 	u8			power_budget;	/* in 2mA units; or zero */
 
+	unsigned		quiescing:1;
+
 	unsigned		has_indicators:1;
 	enum hub_led_mode	indicator[USB_MAXCHILDREN];
 	struct work_struct	leds;
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index d73c3ad45..c9f57e334 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -345,30 +345,13 @@ static int usbfs_unlink (struct inode *dir, struct dentry *dentry)
 	return 0;
 }
 
-static void d_unhash(struct dentry *dentry)
-{
-	dget(dentry);
-	spin_lock(&dcache_lock);
-	switch (atomic_read(&dentry->d_count)) {
-	default:
-		spin_unlock(&dcache_lock);
-		shrink_dcache_parent(dentry);
-		spin_lock(&dcache_lock);
-		if (atomic_read(&dentry->d_count) != 2)
-			break;
-	case 2:
-		__d_drop(dentry);
-	}
-	spin_unlock(&dcache_lock);
-}
-
 static int usbfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
 	int error = -ENOTEMPTY;
 	struct inode * inode = dentry->d_inode;
 
 	down(&inode->i_sem);
-	d_unhash(dentry);
+	dentry_unhash(dentry);
 	if (usbfs_empty(dentry)) {
 		dentry->d_inode->i_nlink -= 2;
 		dput(dentry);
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index e0eacc28a..98695c68d 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -248,7 +248,7 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs)
 		 * unlink pending urbs so they won't rx/tx bad data.
 		 */
 		for (i = 0, found = 0; i < io->entries; i++) {
-			if (!io->urbs [i])
+			if (!io->urbs [i] || !io->urbs [i]->dev)
 				continue;
 			if (found) {
 				status = usb_unlink_urb (io->urbs [i]);
@@ -337,7 +337,7 @@ int usb_sg_init (
 	if (io->entries <= 0)
 		return io->entries;
 
-	io->count = 0;
+	io->count = io->entries;
 	io->urbs = kmalloc (io->entries * sizeof *io->urbs, mem_flags);
 	if (!io->urbs)
 		goto nomem;
@@ -347,7 +347,7 @@ int usb_sg_init (
 	if (usb_pipein (pipe))
 		urb_flags |= URB_SHORT_NOT_OK;
 
-	for (i = 0; i < io->entries; i++, io->count = i) {
+	for (i = 0; i < io->entries; i++) {
 		unsigned		len;
 
 		io->urbs [i] = usb_alloc_urb (0, mem_flags);
@@ -477,24 +477,19 @@ void usb_sg_wait (struct usb_sg_request *io)
 
 			/* fail any uncompleted urbs */
 		default:
-			spin_lock_irq (&io->lock);
-			io->count -= entries - i;
-			if (io->status == -EINPROGRESS)
-				io->status = retval;
-			if (io->count == 0)
-				complete (&io->complete);
-			spin_unlock_irq (&io->lock);
-
-			io->urbs[i]->dev = NULL;
+			io->urbs [i]->dev = NULL;
 			io->urbs [i]->status = retval;
 			dev_dbg (&io->dev->dev, "%s, submit --> %d\n",
 				__FUNCTION__, retval);
 			usb_sg_cancel (io);
 		}
 		spin_lock_irq (&io->lock);
-		if (retval && io->status == -ECONNRESET)
+		if (retval && (io->status == 0 || io->status == -ECONNRESET))
 			io->status = retval;
 	}
+	io->count -= entries - i;
+	if (io->count == 0)
+		complete (&io->complete);
 	spin_unlock_irq (&io->lock);
 
 	/* OK, yes, this could be packaged as non-blocking.
@@ -577,8 +572,13 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char
 				USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
 				(type << 8) + index, 0, buf, size,
 				HZ * USB_CTRL_GET_TIMEOUT);
-		if (!(result == 0 || result == -EPIPE))
-			break;
+		if (result == 0 || result == -EPIPE)
+			continue;
+		if (result > 1 && ((u8 *)buf)[1] != type) {
+			result = -EPROTO;
+			continue;
+		}
+		break;
 	}
 	return result;
 }
@@ -854,9 +854,8 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
 	 * the copy in usb-storage, for as long as we need two copies.
 	 */
 
-	/* toggle was reset by the clear, then ep was reactivated */
+	/* toggle was reset by the clear */
 	usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
-	usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
 
 	return 0;
 }
@@ -870,9 +869,8 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
  * Deallocates hcd/hardware state for this endpoint ... and nukes all
  * pending urbs.
  *
- * If the HCD hasn't registered a disable() function, this marks the
- * endpoint as halted and sets its maxpacket size to 0 to prevent
- * further submissions.
+ * If the HCD hasn't registered a disable() function, this sets the
+ * endpoint's maxpacket size to 0 to prevent further submissions.
  */
 void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
 {
@@ -881,13 +879,10 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
 	else {
 		unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
 
-		if (usb_endpoint_out(epaddr)) {
-			usb_endpoint_halt(dev, epnum, 1);
+		if (usb_endpoint_out(epaddr))
 			dev->epmaxpacketout[epnum] = 0;
-		} else {
-			usb_endpoint_halt(dev, epnum, 0);
+		else
 			dev->epmaxpacketin[epnum] = 0;
-		}
 	}
 }
 
@@ -930,7 +925,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
 		usb_disable_endpoint(dev, i + USB_DIR_IN);
 	}
 	dev->toggle[0] = dev->toggle[1] = 0;
-	dev->halted[0] = dev->halted[1] = 0;
 
 	/* getting rid of interfaces will disconnect
 	 * any drivers bound to them (a key side effect)
@@ -966,9 +960,8 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
  * @dev: the device whose interface is being enabled
  * @epd: pointer to the endpoint descriptor
  *
- * Marks the endpoint as running, resets its toggle, and stores
- * its maxpacket value.  For control endpoints, both the input
- * and output sides are handled.
+ * Resets the endpoint toggle and stores its maxpacket value.
+ * For control endpoints, both the input and output sides are handled.
  */
 void usb_enable_endpoint(struct usb_device *dev,
 		struct usb_endpoint_descriptor *epd)
@@ -980,12 +973,10 @@ void usb_enable_endpoint(struct usb_device *dev,
 				USB_ENDPOINT_XFER_CONTROL);
 
 	if (usb_endpoint_out(epaddr) || is_control) {
-		usb_endpoint_running(dev, epnum, 1);
 		usb_settoggle(dev, epnum, 1, 0);
 		dev->epmaxpacketout[epnum] = maxsize;
 	}
 	if (!usb_endpoint_out(epaddr) || is_control) {
-		usb_endpoint_running(dev, epnum, 0);
 		usb_settoggle(dev, epnum, 0, 0);
 		dev->epmaxpacketin[epnum] = maxsize;
 	}
@@ -1048,6 +1039,9 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
 	int ret;
 	int manual = 0;
 
+	if (dev->state == USB_STATE_SUSPENDED)
+		return -EHOSTUNREACH;
+
 	iface = usb_ifnum_to_if(dev, interface);
 	if (!iface) {
 		dev_dbg(&dev->dev, "selecting invalid interface %d\n",
@@ -1145,6 +1139,9 @@ int usb_reset_configuration(struct usb_device *dev)
 	int			i, retval;
 	struct usb_host_config	*config;
 
+	if (dev->state == USB_STATE_SUSPENDED)
+		return -EHOSTUNREACH;
+
 	/* caller must own dev->serialize (config won't change)
 	 * and the usb bus readlock (so driver bindings are stable);
 	 * so calls during probe() are fine
@@ -1166,7 +1163,6 @@ int usb_reset_configuration(struct usb_device *dev)
 	}
 
 	dev->toggle[0] = dev->toggle[1] = 0;
-	dev->halted[0] = dev->halted[1] = 0;
 
 	/* re-init hc/hcd interface/endpoint state */
 	for (i = 0; i < config->desc.bNumInterfaces; i++) {
@@ -1195,7 +1191,7 @@ static void release_interface(struct device *dev)
 	struct usb_interface_cache *intfc =
 			altsetting_to_usb_interface_cache(intf->altsetting);
 
-	kref_put(&intfc->ref);
+	kref_put(&intfc->ref, usb_release_interface_cache);
 	kfree(intf);
 }
 
@@ -1258,6 +1254,9 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
 	if (cp && configuration == 0)
 		dev_warn(&dev->dev, "config 0 descriptor??\n");
 
+	if (dev->state == USB_STATE_SUSPENDED)
+		return -EHOSTUNREACH;
+
 	/* Allocate memory for new interfaces before doing anything else,
 	 * so that if we run out then nothing will have changed. */
 	n = nintf = 0;
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 777f34ea6..3c14361bb 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -39,7 +39,7 @@ void usb_init_urb(struct urb *urb)
 {
 	if (urb) {
 		memset(urb, 0, sizeof(*urb));
-		kref_init(&urb->kref, urb_destroy);
+		kref_init(&urb->kref);
 		spin_lock_init(&urb->lock);
 	}
 }
@@ -88,7 +88,7 @@ struct urb *usb_alloc_urb(int iso_packets, int mem_flags)
 void usb_free_urb(struct urb *urb)
 {
 	if (urb)
-		kref_put(&urb->kref);
+		kref_put(&urb->kref, urb_destroy);
 }
 
 /**
@@ -256,13 +256,6 @@ int usb_submit_urb(struct urb *urb, int mem_flags)
 	if (!usb_pipecontrol (pipe) && dev->state < USB_STATE_CONFIGURED)
 		return -ENODEV;
 
-	/* (actually HCDs may need to duplicate this, endpoint might yet
-	 * stall due to queued bulk/intr transactions that complete after
-	 * we check)
-	 */
-	if (usb_endpoint_halted (dev, usb_pipeendpoint (pipe), is_out))
-		return -EPIPE;
-
 	/* FIXME there should be a sharable lock protecting us against
 	 * config/altsetting changes and disconnects, kicking in here.
 	 * (here == before maxpacket, and eventually endpoint type,
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 324e16caf..de2edfb08 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -93,6 +93,8 @@ int usb_probe_interface(struct device *dev)
 
 	if (!driver->probe)
 		return error;
+	if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED)
+		return -EHOSTUNREACH;
 
 	id = usb_match_id (intf, driver->id_table);
 	if (id) {
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 7d978af3a..f1dff4f4d 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -10,6 +10,7 @@ extern int usb_unbind_interface (struct device *dev);
 extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr);
 extern void usb_disable_interface (struct usb_device *dev,
 		struct usb_interface *intf);
+extern void usb_release_interface_cache(struct kref *ref);
 extern void usb_disable_device (struct usb_device *dev, int skip_ep0);
 
 extern void usb_enable_endpoint (struct usb_device *dev,
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 9189fb0da..decbca335 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -135,6 +135,18 @@ config USB_SA1100
 	depends on USB_GADGET_SA1100
 	default USB_GADGET
 
+config USB_GADGET_LH7A40X
+	boolean "LH7A40X"
+	depends on ARCH_LH7A40X
+	help
+    This driver provides USB Device Controller driver for LH7A40x
+
+config USB_LH7A40X
+	tristate
+	depends on USB_GADGET_LH7A40X
+	default USB_GADGET
+
+
 config USB_GADGET_DUMMY_HCD
 	boolean "Dummy HCD (DEVELOPMENT)"
 	depends on USB && EXPERIMENTAL
@@ -163,6 +175,41 @@ config USB_DUMMY_HCD
 	depends on USB_GADGET_DUMMY_HCD
 	default USB_GADGET
 
+config USB_GADGET_OMAP
+	boolean "OMAP USB Device Controller"
+	depends on ARCH_OMAP
+	select ISP1301_OMAP if MACH_OMAP_H2
+	help
+	   Many Texas Instruments OMAP processors have flexible full
+	   speed USB device controllers, with support for up to 30
+	   endpoints (plus endpoint zero).  This driver supports the
+	   controller in the OMAP 1611, and should work with controllers
+	   in other OMAP processors too, given minor tweaks.
+
+	   Say "y" to link the driver statically, or "m" to build a
+	   dynamically linked module called "omap_udc" and force all
+	   gadget drivers to also be dynamically linked.
+
+config USB_OMAP
+	tristate
+	depends on USB_GADGET_OMAP
+	default USB_GADGET
+
+config USB_OTG
+	boolean "OTG Support"
+	depends on USB_GADGET_OMAP && ARCH_OMAP_OTG && USB_OHCI_HCD
+	help
+	   The most notable feature of USB OTG is support for a
+	   "Dual-Role" device, which can act as either a device
+	   or a host.  The initial role choice can be changed
+	   later, when two dual-role devices talk to each other.
+
+	   Select this only if your OMAP board has a Mini-AB connector.
+
+config USB_OMAP_PROC
+	boolean "/proc/driver/udc file"
+	depends on USB_GADGET_OMAP
+
 endchoice
 
 config USB_GADGET_DUALSPEED
@@ -275,7 +322,7 @@ config USB_GADGETFS
 	  dynamically linked module called "gadgetfs".
 
 config USB_FILE_STORAGE
-	tristate "File-backed Storage Gadget (DEVELOPMENT)"
+	tristate "File-backed Storage Gadget"
 	# we don't support the SA1100 because of its limitations
 	depends on USB_GADGET_SA1100 = n
 	help
@@ -288,7 +335,7 @@ config USB_FILE_STORAGE
 	  dynamically linked module called "g_file_storage".
 
 config USB_FILE_STORAGE_TEST
-	bool "File-backed Storage Gadget test version"
+	bool "File-backed Storage Gadget testing version"
 	depends on USB_FILE_STORAGE
 	default n
 	help
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 645d15cf5..03c639bfd 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -5,13 +5,15 @@ obj-$(CONFIG_USB_DUMMY_HCD)	+= dummy_hcd.o
 obj-$(CONFIG_USB_NET2280)	+= net2280.o
 obj-$(CONFIG_USB_PXA2XX)	+= pxa2xx_udc.o
 obj-$(CONFIG_USB_GOKU)		+= goku_udc.o
+obj-$(CONFIG_USB_OMAP)		+= omap_udc.o
+obj-$(CONFIG_USB_LH7A40X)	+= lh7a40x_udc.o
 
 #
 # USB gadget drivers
 #
 g_zero-objs			:= zero.o usbstring.o config.o epautoconf.o
 g_ether-objs			:= ether.o usbstring.o config.o epautoconf.o
-g_serial-objs			:= serial.o usbstring.o
+g_serial-objs			:= serial.o usbstring.o epautoconf.o
 gadgetfs-objs			:= inode.o
 g_file_storage-objs		:= file_storage.o usbstring.o config.o \
 					epautoconf.o
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 4c1b157cf..91e878642 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -596,14 +596,13 @@ static const struct usb_gadget_ops dummy_ops = {
 
 /* "function" sysfs attribute */
 static ssize_t
-show_function (struct device *_dev, char *buf)
+show_function (struct device *dev, char *buf)
 {
-	struct dummy	*dum = the_controller;
+	struct dummy	*dum = gadget_dev_to_dummy (dev);
 
-	if (!dum->driver->function
-			|| strlen (dum->driver->function) > PAGE_SIZE)
+	if (!dum->driver || !dum->driver->function)
 		return 0;
-	return snprintf (buf, PAGE_SIZE, "%s\n", dum->driver->function);
+	return scnprintf (buf, PAGE_SIZE, "%s\n", dum->driver->function);
 }
 DEVICE_ATTR (function, S_IRUGO, show_function, NULL);
 
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 174afd47b..763d05521 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -63,6 +63,7 @@
 
 /*
  * Ethernet gadget driver -- with CDC and non-CDC options
+ * Builds on hardware support for a full duplex link.
  *
  * CDC Ethernet is the standard USB solution for sending Ethernet frames
  * using USB.  Real hardware tends to use the same framing protocol but look
@@ -242,6 +243,10 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
 #define	DEV_CONFIG_SUBSET
 #endif
 
+#ifdef CONFIG_USB_GADGET_LH7A40X
+#define DEV_CONFIG_CDC
+#endif
+
 #ifdef CONFIG_USB_GADGET_SA1100
 /* use non-CDC for backwards compatibility */
 #define	DEV_CONFIG_SUBSET
@@ -855,7 +860,7 @@ static char				product_desc [40] = DRIVER_DESC;
 static char				ethaddr [2 * ETH_ALEN + 1];
 #endif
 
-/* static strings, in iso 8859/1 */
+/* static strings, in UTF-8 */
 static struct usb_string		strings [] = {
 	{ STRING_MANUFACTURER,	manufacturer, },
 	{ STRING_PRODUCT,	product_desc, },
@@ -897,9 +902,9 @@ config_buf (enum usb_device_speed speed,
 
 	if (type == USB_DT_OTHER_SPEED_CONFIG)
 		hs = !hs;
-#define which_fn(t)	(hs ? & hs_ ## t ## _function : & fs_ ## t ## _function)
+#define which_fn(t)	(hs ? hs_ ## t ## _function : fs_ ## t ## _function)
 #else
-#define	which_fn(t)	(& fs_ ## t ## _function)
+#define	which_fn(t)	(fs_ ## t ## _function)
 #endif
 
 	if (index >= device_desc.bNumConfigurations)
@@ -911,14 +916,12 @@ config_buf (enum usb_device_speed speed,
 	 */
 	if (device_desc.bNumConfigurations == 2 && index == 0) {
 		config = &rndis_config;
-		function = (const struct usb_descriptor_header **)
-				which_fn (rndis);
+		function = which_fn (rndis);
 	} else
 #endif
 	{
 		config = &eth_config;
-		function = (const struct usb_descriptor_header **)
-				which_fn (eth);
+		function = which_fn (eth);
 	}
 
 	/* for now, don't advertise srp-only devices */
@@ -2329,6 +2332,8 @@ eth_bind (struct usb_gadget *gadget)
 		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0207);
 	} else if (gadget_is_omap (gadget)) {
 		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0208);
+	} else if (gadget_is_lh7a40x(gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0209);
 	} else {
 		/* can't assume CDC works.  don't want to default to
 		 * anything less functional on CDC-capable hardware,
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 9b978911e..6e8008fa4 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -46,17 +46,16 @@
  *
  * Backing storage is provided by a regular file or a block device, specified
  * by the "file" module parameter.  Access can be limited to read-only by
- * setting the optional "ro" module parameter.
+ * setting the optional "ro" module parameter.  The gadget will indicate that
+ * it has removable media if the optional "removable" module parameter is set.
  *
  * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI),
  * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected
  * by the optional "transport" module parameter.  It also supports the
  * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03),
  * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by
- * the optional "protocol" module parameter.  For testing purposes the
- * gadget will indicate that it has removable media if the optional
- * "removable" module parameter is set.  In addition, the default Vendor ID,
- * Product ID, and release number can be overridden.
+ * the optional "protocol" module parameter.  In addition, the default
+ * Vendor ID, Product ID, and release number can be overridden.
  *
  * There is support for multiple logical units (LUNs), each of which has
  * its own backing file.  The number of LUNs can be set using the optional
@@ -79,13 +78,13 @@
  *					the files or block devices used for
  *					backing storage
  *	ro=b[,b...]		Default false, booleans for read-only access
+ *	removable		Default false, boolean for removable media
  *	luns=N			Default N = number of filenames, number of
  *					LUNs to support
  *	transport=XXX		Default BBB, transport name (CB, CBI, or BBB)
  *	protocol=YYY		Default SCSI, protocol name (RBC, 8020 or
  *					ATAPI, QIC, UFI, 8070, or SCSI;
  *					also 1 - 6)
- *	removable		Default false, boolean for removable media
  *	vendor=0xVVVV		Default 0x0525 (NetChip), USB Vendor ID
  *	product=0xPPPP		Default 0xa4a5 (FSG), USB Product ID
  *	release=0xRRRR		Override the USB release number (bcdDevice)
@@ -97,16 +96,16 @@
  *					boolean to permit the driver to halt
  *					bulk endpoints
  *
- * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file" and "ro"
- * options are available; default values are used for everything else.
+ * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro",
+ * "removable", and "luns" options are available; default values are used
+ * for everything else.
  *
  * The pathnames of the backing files and the ro settings are available in
  * the attribute files "file" and "ro" in the lun<n> subdirectory of the
- * gadget's sysfs directory.  If CONFIG_USB_FILE_STORAGE_TEST and the
- * "removable" option are both set, writing to these files will simulate
- * ejecting/loading the medium (writing an empty line means eject) and
- * adjusting a write-enable tab.  Changes to the ro setting are not allowed
- * when the medium is loaded.
+ * gadget's sysfs directory.  If the "removable" option is set, writing to
+ * these files will simulate ejecting/loading the medium (writing an empty
+ * line means eject) and adjusting a write-enable tab.  Changes to the ro
+ * setting are not allowed when the medium is loaded.
  *
  * This gadget driver is heavily based on "Gadget Zero" by David Brownell.
  */
@@ -178,7 +177,10 @@
  * Bulk-only specification requires a stall.  In such cases the driver
  * will halt the endpoint and set a flag indicating that it should clear
  * the halt in software during the next device reset.  Hopefully this
- * will permit everything to work correctly.
+ * will permit everything to work correctly.  Furthermore, although the
+ * specification allows the bulk-out endpoint to halt when the host sends
+ * too much data, implementing this would cause an unavoidable race.
+ * The driver will always use the "no-stall" approach for OUT transfers.
  *
  * One subtle point concerns sending status-stage responses for ep0
  * requests.  Some of these requests, such as device reset, can involve
@@ -246,7 +248,7 @@
 
 #define DRIVER_DESC		"File-backed Storage Gadget"
 #define DRIVER_NAME		"g_file_storage"
-#define DRIVER_VERSION		"21 March 2004"
+#define DRIVER_VERSION		"28 July 2004"
 
 static const char longname[] = DRIVER_DESC;
 static const char shortname[] = DRIVER_NAME;
@@ -371,14 +373,17 @@ MODULE_PARM_DESC(file, "names of backing files or devices");
 module_param_array(ro, bool, mod_data.num_ros, S_IRUGO);
 MODULE_PARM_DESC(ro, "true to force read-only");
 
+module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
+MODULE_PARM_DESC(luns, "number of LUNs");
 
-/* In the non-TEST version, only the file and ro module parameters
+module_param_named(removable, mod_data.removable, bool, S_IRUGO);
+MODULE_PARM_DESC(removable, "true to simulate removable media");
+
+
+/* In the non-TEST version, only the module parameters listed above
  * are available. */
 #ifdef CONFIG_USB_FILE_STORAGE_TEST
 
-module_param_named(luns, mod_data.nluns, uint, S_IRUGO);
-MODULE_PARM_DESC(luns, "number of LUNs");
-
 module_param_named(transport, mod_data.transport_parm, charp, S_IRUGO);
 MODULE_PARM_DESC(transport, "type of transport (BBB, CBI, or CB)");
 
@@ -386,9 +391,6 @@ module_param_named(protocol, mod_data.protocol_parm, charp, S_IRUGO);
 MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, "
 		"8070, or SCSI)");
 
-module_param_named(removable, mod_data.removable, bool, S_IRUGO);
-MODULE_PARM_DESC(removable, "true to simulate removable media");
-
 module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO);
 MODULE_PARM_DESC(vendor, "USB Vendor ID");
 
@@ -525,11 +527,6 @@ struct interrupt_data {
  * parts of the driver that aren't used in the non-TEST version.  Even gcc
  * can recognize when a test of a constant expression yields a dead code
  * path.
- *
- * Also, in the non-TEST version, open_backing_file() is only used during
- * initialization and the sysfs attribute store_xxx routines aren't used
- * at all.  We will define NORMALLY_INIT to mark them as __init so they
- * don't occupy kernel code space unnecessarily.
  */
 
 #ifdef CONFIG_USB_FILE_STORAGE_TEST
@@ -537,16 +534,12 @@ struct interrupt_data {
 #define transport_is_bbb()	(mod_data.transport_type == USB_PR_BULK)
 #define transport_is_cbi()	(mod_data.transport_type == USB_PR_CBI)
 #define protocol_is_scsi()	(mod_data.protocol_type == USB_SC_SCSI)
-#define backing_file_is_open(curlun)	((curlun)->filp != NULL)
-#define NORMALLY_INIT
 
 #else
 
 #define transport_is_bbb()	1
 #define transport_is_cbi()	0
 #define protocol_is_scsi()	1
-#define backing_file_is_open(curlun)	1
-#define NORMALLY_INIT		__init
 
 #endif /* CONFIG_USB_FILE_STORAGE_TEST */
 
@@ -567,6 +560,8 @@ struct lun {
 	struct device	dev;
 };
 
+#define backing_file_is_open(curlun)	((curlun)->filp != NULL)
+
 static inline struct lun *dev_to_lun(struct device *dev)
 {
 	return container_of(dev, struct lun, dev);
@@ -659,6 +654,7 @@ struct fsg_dev {
 	unsigned long		atomic_bitflags;
 #define REGISTERED		0
 #define CLEAR_BULK_HALTS	1
+#define SUSPENDED		2
 
 	struct usb_ep		*bulk_in;
 	struct usb_ep		*bulk_out;
@@ -1041,8 +1037,6 @@ static int populate_config_buf(enum usb_device_speed speed,
 		function = fs_function;
 
 	len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function);
-	if (len < 0)
-		return len;
 	((struct usb_config_descriptor *) buf)->bDescriptorType = type;
 	return len;
 }
@@ -1172,9 +1166,10 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
 	wakeup_thread(fsg);
 }
 
+
+#ifdef CONFIG_USB_FILE_STORAGE_TEST
 static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
 {
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
 	struct fsg_dev		*fsg = (struct fsg_dev *) ep->driver_data;
 	struct fsg_buffhd	*bh = (struct fsg_buffhd *) req->context;
 
@@ -1190,17 +1185,21 @@ static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
 	bh->state = BUF_STATE_EMPTY;
 	spin_unlock(&fsg->lock);
 	wakeup_thread(fsg);
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
 }
 
+#else
+static void intr_in_complete(struct usb_ep *ep, struct usb_request *req)
+{}
+#endif /* CONFIG_USB_FILE_STORAGE_TEST */
+
 
 /*-------------------------------------------------------------------------*/
 
 /* Ep0 class-specific handlers.  These always run in_irq. */
 
+#ifdef CONFIG_USB_FILE_STORAGE_TEST
 static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
 {
-#ifdef CONFIG_USB_FILE_STORAGE_TEST
 	struct usb_request	*req = fsg->ep0req;
 	static u8		cbi_reset_cmnd[6] = {
 			SC_SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff};
@@ -1238,9 +1237,13 @@ static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
 
 	spin_unlock(&fsg->lock);
 	wakeup_thread(fsg);
-#endif /* CONFIG_USB_FILE_STORAGE_TEST */
 }
 
+#else
+static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh)
+{}
+#endif /* CONFIG_USB_FILE_STORAGE_TEST */
+
 
 static int class_setup_req(struct fsg_dev *fsg,
 		const struct usb_ctrlrequest *ctrl)
@@ -1465,8 +1468,8 @@ static int fsg_setup(struct usb_gadget *gadget,
 	/* Respond with data/status or defer until later? */
 	if (rc >= 0 && rc != DELAYED_STATUS) {
 		fsg->ep0req->length = rc;
-		fsg->ep0req->zero = rc < ctrl->wLength
-				&& (rc % gadget->ep0->maxpacket) == 0;
+		fsg->ep0req->zero = (rc < ctrl->wLength &&
+				(rc % gadget->ep0->maxpacket) == 0);
 		fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ?
 				"ep0-in" : "ep0-out");
 		rc = ep0_queue(fsg);
@@ -2443,14 +2446,19 @@ static int finish_reply(struct fsg_dev *fsg)
 			rc = -EINTR;
 		}
 
-		/* We haven't processed all the incoming data.  If we are
-		 * allowed to stall, halt the bulk-out endpoint and cancel
-		 * any outstanding requests. */
+		/* We haven't processed all the incoming data.  Even though
+		 * we may be allowed to stall, doing so would cause a race.
+		 * The controller may already have ACK'ed all the remaining
+		 * bulk-out packets, in which case the host wouldn't see a
+		 * STALL.  Not realizing the endpoint was halted, it wouldn't
+		 * clear the halt -- leading to problems later on. */
+#if 0
 		else if (mod_data.can_stall) {
 			fsg_set_halt(fsg, fsg->bulk_out);
 			raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
 			rc = -EINTR;
 		}
+#endif
 
 		/* We can't stall.  Read in the excess data and throw it
 		 * all away. */
@@ -2513,7 +2521,7 @@ static int send_status(struct fsg_dev *fsg)
 
 	} else if (mod_data.transport_type == USB_PR_CB) {
 
-		/* Control-Bulk transport has no status stage! */
+		/* Control-Bulk transport has no status phase! */
 		return 0;
 
 	} else {			// USB_PR_CBI
@@ -2603,8 +2611,10 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size,
 	fsg->residue = fsg->usb_amount_left = fsg->data_size;
 
 	/* Conflicting data directions is a phase error */
-	if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0)
-		goto phase_error;
+	if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0) {
+		fsg->phase_error = 1;
+		return -EINVAL;
+	}
 
 	/* Verify the length of the command itself */
 	if (cmnd_size != fsg->cmnd_size) {
@@ -2613,8 +2623,10 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size,
 		 * with cbw->Length == 12 (it should be 6). */
 		if (fsg->cmnd[0] == SC_REQUEST_SENSE && fsg->cmnd_size == 12)
 			cmnd_size = fsg->cmnd_size;
-		else
-			goto phase_error;
+		else {
+			fsg->phase_error = 1;
+			return -EINVAL;
+		}
 	}
 
 	/* Check that the LUN values are oonsistent */
@@ -2674,10 +2686,6 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size,
 	}
 
 	return 0;
-
-phase_error:
-	fsg->phase_error = 1;
-	return -EINVAL;
 }
 
 
@@ -3424,8 +3432,7 @@ static int fsg_main_thread(void *fsg_)
 /* If the next two routines are called while the gadget is registered,
  * the caller must own fsg->filesem for writing. */
 
-static int NORMALLY_INIT open_backing_file(struct lun *curlun,
-		const char *filename)
+static int open_backing_file(struct lun *curlun, const char *filename)
 {
 	int				ro;
 	struct file			*filp = NULL;
@@ -3550,8 +3557,7 @@ static ssize_t show_file(struct device *dev, char *buf)
 }
 
 
-ssize_t NORMALLY_INIT store_ro(struct device *dev, const char *buf,
-		size_t count)
+ssize_t store_ro(struct device *dev, const char *buf, size_t count)
 {
 	ssize_t		rc = count;
 	struct lun	*curlun = dev_to_lun(dev);
@@ -3575,8 +3581,7 @@ ssize_t NORMALLY_INIT store_ro(struct device *dev, const char *buf,
 	return rc;
 }
 
-ssize_t NORMALLY_INIT store_file(struct device *dev, const char *buf,
-		size_t count)
+ssize_t store_file(struct device *dev, const char *buf, size_t count)
 {
 	struct lun	*curlun = dev_to_lun(dev);
 	struct fsg_dev	*fsg = (struct fsg_dev *) dev_get_drvdata(dev);
@@ -3708,6 +3713,8 @@ static int __init check_parameters(struct fsg_dev *fsg)
 			mod_data.release = __constant_cpu_to_le16(0x0307);
 		else if (gadget_is_omap(fsg->gadget))
 			mod_data.release = __constant_cpu_to_le16(0x0308);
+		else if (gadget_is_lh7a40x(gadget))
+			mod_data.release = __constant_cpu_to_le16 (0x0309);
 		else {
 			WARN(fsg, "controller '%s' not recognized\n",
 				fsg->gadget->name);
@@ -3805,9 +3812,8 @@ static int __init fsg_bind(struct usb_gadget *gadget)
 		goto out;
 	}
 
-	/* Create the LUNs and open their backing files.  We can't register
-	 * the LUN devices until the gadget itself is registered, which
-	 * doesn't happen until after fsg_bind() returns. */
+	/* Create the LUNs, open their backing files, and register the
+	 * LUN devices in sysfs. */
 	fsg->luns = kmalloc(i * sizeof(struct lun), GFP_KERNEL);
 	if (!fsg->luns) {
 		rc = -ENOMEM;
@@ -3825,6 +3831,15 @@ static int __init fsg_bind(struct usb_gadget *gadget)
 		snprintf(curlun->dev.bus_id, BUS_ID_SIZE,
 				"%s-lun%d", gadget->dev.bus_id, i);
 
+		if ((rc = device_register(&curlun->dev)) != 0)
+			INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
+		else {
+			curlun->registered = 1;
+			curlun->dev.release = lun_release;
+			device_create_file(&curlun->dev, &dev_attr_ro);
+			device_create_file(&curlun->dev, &dev_attr_file);
+		}
+
 		if (file[i] && *file[i]) {
 			if ((rc = open_backing_file(curlun, file[i])) != 0)
 				goto out;
@@ -3972,6 +3987,25 @@ out:
 }
 
 
+/*-------------------------------------------------------------------------*/
+
+static void fsg_suspend(struct usb_gadget *gadget)
+{
+	struct fsg_dev		*fsg = get_gadget_data(gadget);
+
+	DBG(fsg, "suspend\n");
+	set_bit(SUSPENDED, &fsg->atomic_bitflags);
+}
+
+static void fsg_resume(struct usb_gadget *gadget)
+{
+	struct fsg_dev		*fsg = get_gadget_data(gadget);
+
+	DBG(fsg, "resume\n");
+	clear_bit(SUSPENDED, &fsg->atomic_bitflags);
+}
+
+
 /*-------------------------------------------------------------------------*/
 
 static struct usb_gadget_driver		fsg_driver = {
@@ -3985,6 +4019,8 @@ static struct usb_gadget_driver		fsg_driver = {
 	.unbind		= fsg_unbind,
 	.disconnect	= fsg_disconnect,
 	.setup		= fsg_setup,
+	.suspend	= fsg_suspend,
+	.resume		= fsg_resume,
 
 	.driver		= {
 		.name		= (char *) shortname,
@@ -4024,8 +4060,6 @@ static int __init fsg_init(void)
 {
 	int		rc;
 	struct fsg_dev	*fsg;
-	int		i;
-	struct lun	*curlun;
 
 	if ((rc = fsg_alloc()) != 0)
 		return rc;
@@ -4036,19 +4070,6 @@ static int __init fsg_init(void)
 	}
 	set_bit(REGISTERED, &fsg->atomic_bitflags);
 
-	/* Register the LUN devices and their attribute files */
-	for (i = 0; i < fsg->nluns; ++i) {
-		curlun = &fsg->luns[i];
-		if ((rc = device_register(&curlun->dev)) != 0)
-			INFO(fsg, "failed to register LUN%d: %d\n", i, rc);
-		else {
-			curlun->registered = 1;
-			curlun->dev.release = lun_release;
-			device_create_file(&curlun->dev, &dev_attr_ro);
-			device_create_file(&curlun->dev, &dev_attr_file);
-		}
-	}
-
 	/* Tell the thread to start working */
 	complete(&fsg->thread_notifier);
 	return 0;
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index 3093bceb9..e24e2f9ad 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -44,6 +44,12 @@
 #define	gadget_is_sa1100(g)	0
 #endif
 
+#ifdef CONFIG_USB_GADGET_LH7A40X
+#define	gadget_is_lh7a40x(g)	!strcmp("lh7a40x_udc", (g)->name)
+#else
+#define	gadget_is_lh7a40x(g)	0
+#endif
+
 #ifdef CONFIG_USB_GADGET_MQ11XX
 #define	gadget_is_mq11xx(g)	!strcmp("mq11xx_udc", (g)->name)
 #else
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index c746ecbe1..f5e146225 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -1,7 +1,7 @@
 /*
  * inode.c -- user mode filesystem api for usb gadget controllers
  *
- * Copyright (C) 2003 David Brownell
+ * Copyright (C) 2003-2004 David Brownell
  * Copyright (C) 2003 Agilent Technologies
  *
  * This program is free software; you can redistribute it and/or modify
@@ -71,7 +71,7 @@
  */
 
 #define	DRIVER_DESC	"USB Gadget filesystem"
-#define	DRIVER_VERSION	"18 Nov 2003"
+#define	DRIVER_VERSION	"24 Aug 2004"
 
 static const char driver_desc [] = DRIVER_DESC;
 static const char shortname [] = "gadgetfs";
@@ -229,37 +229,12 @@ static void put_ep (struct ep_data *data)
 /*----------------------------------------------------------------------*/
 
 /* most "how to use the hardware" policy choices are in userspace:
- * mapping endpoint roles the driver needs to the capabilities that
- * the usb controller exposes.
+ * mapping endpoint roles (which the driver needs) to the capabilities
+ * which the usb controller has.  most of those capabilities are exposed
+ * implicitly, starting with the driver name and then endpoint names.
  */
 
-#ifdef	CONFIG_USB_GADGET_DUMMY_HCD
-/* act (mostly) like a net2280 */
-#define CONFIG_USB_GADGET_NET2280
-#endif
-
-#ifdef	CONFIG_USB_GADGET_NET2280
-#define CHIP			"net2280"
-#define HIGHSPEED
-#endif
-
-#ifdef	CONFIG_USB_GADGET_PXA2XX
-#define CHIP			"pxa2xx_udc"
-/* earlier hardware doesn't have UDCCFR, races set_{config,interface} */
-#warning works best with pxa255 or newer
-#endif
-
-#ifdef	CONFIG_USB_GADGET_GOKU
-#define CHIP			"goku_udc"
-#endif
-
-#ifdef	CONFIG_USB_GADGET_OMAP
-#define CHIP			"omap_udc"
-#endif
-
-#ifdef	CONFIG_USB_GADGET_SA1100
-#define CHIP			"sa1100"
-#endif
+static const char *CHIP;
 
 /*----------------------------------------------------------------------*/
 
@@ -558,7 +533,7 @@ struct kiocb_priv {
 
 static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e)
 {
-	struct kiocb_priv	*priv = (void *) &iocb->private;
+	struct kiocb_priv	*priv = iocb->private;
 	struct ep_data		*epdata;
 	int			value;
 
@@ -577,10 +552,10 @@ static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e)
 	return value;
 }
 
-static long ep_aio_read_retry(struct kiocb *iocb)
+static ssize_t ep_aio_read_retry(struct kiocb *iocb)
 {
-	struct kiocb_priv	*priv = (void *) &iocb->private;
-	int			status = priv->actual;
+	struct kiocb_priv	*priv = iocb->private;
+	ssize_t			status = priv->actual;
 
 	/* we "retry" to get the right mm context for this: */
 	status = copy_to_user(priv->ubuf, priv->buf, priv->actual);
@@ -589,6 +564,7 @@ static long ep_aio_read_retry(struct kiocb *iocb)
 	else
 		status = priv->actual;
 	kfree(priv->buf);
+	kfree(priv);
 	aio_put_req(iocb);
 	return status;
 }
@@ -596,7 +572,7 @@ static long ep_aio_read_retry(struct kiocb *iocb)
 static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
 {
 	struct kiocb		*iocb = req->context;
-	struct kiocb_priv	*priv = (void *) &iocb->private;
+	struct kiocb_priv	*priv = iocb->private;
 	struct ep_data		*epdata = priv->epdata;
 
 	/* lock against disconnect (and ideally, cancel) */
@@ -607,6 +583,8 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
 			|| unlikely(0 == req->actual)
 			|| unlikely(kiocbIsCancelled(iocb))) {
 		kfree(req->buf);
+		kfree(priv);
+		iocb->private = NULL;
 		/* aio_complete() reports bytes-transferred _and_ faults */
 		if (unlikely(kiocbIsCancelled(iocb)))
 			aio_put_req(iocb);
@@ -631,17 +609,33 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
 }
 
 static ssize_t
-ep_aio_rwtail(struct kiocb *iocb, char *buf, size_t len, struct ep_data *epdata)
+ep_aio_rwtail(
+	struct kiocb	*iocb,
+	char		*buf,
+	size_t		len,
+	struct ep_data	*epdata,
+	char __user	*ubuf
+)
 {
 	struct kiocb_priv	*priv = (void *) &iocb->private;
 	struct usb_request	*req;
 	ssize_t			value;
 
-	value = get_ready_ep(iocb->ki_filp->f_flags, epdata);
-	if (unlikely(value < 0)) {
+	priv = kmalloc(sizeof *priv, GFP_KERNEL);
+	if (!priv) {
+		value = -ENOMEM;
+fail:
 		kfree(buf);
 		return value;
 	}
+	iocb->private = priv;
+	priv->ubuf = ubuf;
+
+	value = get_ready_ep(iocb->ki_filp->f_flags, epdata);
+	if (unlikely(value < 0)) {
+		kfree(priv);
+		goto fail;
+	}
 
 	iocb->ki_cancel = ep_aio_cancel;
 	get_ep(epdata);
@@ -671,9 +665,10 @@ ep_aio_rwtail(struct kiocb *iocb, char *buf, size_t len, struct ep_data *epdata)
 
 	up(&epdata->lock);
 
-	if (unlikely(value))
+	if (unlikely(value)) {
+		kfree(priv);
 		put_ep(epdata);
-	else
+	} else
 		value = -EIOCBQUEUED;
 	return value;
 }
@@ -681,7 +676,6 @@ ep_aio_rwtail(struct kiocb *iocb, char *buf, size_t len, struct ep_data *epdata)
 static ssize_t
 ep_aio_read(struct kiocb *iocb, char __user *ubuf, size_t len, loff_t o)
 {
-	struct kiocb_priv	*priv = (void *) &iocb->private;
 	struct ep_data		*epdata = iocb->ki_filp->private_data;
 	char			*buf;
 
@@ -691,8 +685,7 @@ ep_aio_read(struct kiocb *iocb, char __user *ubuf, size_t len, loff_t o)
 	if (unlikely(!buf))
 		return -ENOMEM;
 	iocb->ki_retry = ep_aio_read_retry;
-	priv->ubuf = ubuf;
-	return ep_aio_rwtail(iocb, buf, len, epdata);
+	return ep_aio_rwtail(iocb, buf, len, epdata, ubuf);
 }
 
 static ssize_t
@@ -710,7 +703,7 @@ ep_aio_write(struct kiocb *iocb, const char __user *ubuf, size_t len, loff_t o)
 		kfree(buf);
 		return -EFAULT;
 	}
-	return ep_aio_rwtail(iocb, buf, len, epdata);
+	return ep_aio_rwtail(iocb, buf, len, epdata, NULL);
 }
 
 /*----------------------------------------------------------------------*/
@@ -718,6 +711,8 @@ ep_aio_write(struct kiocb *iocb, const char __user *ubuf, size_t len, loff_t o)
 /* used after endpoint configuration */
 static struct file_operations ep_io_operations = {
 	.owner =	THIS_MODULE,
+	.llseek =	no_llseek,
+
 	.read =		ep_read,
 	.write =	ep_write,
 	.ioctl =	ep_ioctl,
@@ -874,6 +869,8 @@ ep_open (struct inode *inode, struct file *fd)
 /* used before endpoint configuration */
 static struct file_operations ep_config_operations = {
 	.owner =	THIS_MODULE,
+	.llseek =	no_llseek,
+
 	.open =		ep_open,
 	.write =	ep_config,
 	.release =	ep_release,
@@ -980,6 +977,18 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
 				retval = usb_ep_queue (ep, req, GFP_ATOMIC);
 			dev->state = STATE_CONNECTED;
 
+			/* assume that was SET_CONFIGURATION */
+			if (dev->current_config) {
+				unsigned power;
+#ifdef	HIGHSPEED
+				if (dev->gadget->speed == USB_SPEED_HIGH)
+					power = dev->hs_config->bMaxPower;
+				else
+#endif
+					power = dev->config->bMaxPower;
+				usb_gadget_vbus_draw(dev->gadget, 2 * power);
+			}
+
 		} else {			/* collect OUT data */
 			if ((fd->f_flags & O_NONBLOCK) != 0
 					&& !dev->setup_out_ready) {
@@ -1230,6 +1239,8 @@ static int dev_ioctl (struct inode *inode, struct file *fd,
 /* used after device configuration */
 static struct file_operations ep0_io_operations = {
 	.owner =	THIS_MODULE,
+	.llseek =	no_llseek,
+
 	.read =		ep0_read,
 	.write =	ep0_write,
 	.fasync =	ep0_fasync,
@@ -1406,19 +1417,25 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 		if (0 == (u8) ctrl->wValue) {
 			value = 0;
 			dev->current_config = 0;
+			usb_gadget_vbus_draw(gadget, 8 /* mA */ );
 			// user mode expected to disable endpoints
 		} else {
-			u8	config;
+			u8	config, power;
 #ifdef	HIGHSPEED
-			if (gadget->speed == USB_SPEED_HIGH)
+			if (gadget->speed == USB_SPEED_HIGH) {
 				config = dev->hs_config->bConfigurationValue;
-			else
+				power = dev->hs_config->bMaxPower;
+			} else
 #endif
+			{
 				config = dev->config->bConfigurationValue;
+				power = dev->config->bMaxPower;
+			}
 
 			if (config == (u8) ctrl->wValue) {
 				value = 0;
 				dev->current_config = config;
+				usb_gadget_vbus_draw(gadget, 2 * power);
 			}
 		}
 
@@ -1636,8 +1653,8 @@ gadgetfs_bind (struct usb_gadget *gadget)
 	if (!dev)
 		return -ESRCH;
 	if (0 != strcmp (CHIP, gadget->name)) {
-		printk (KERN_ERR "%s expected " CHIP " controller not %s\n",
-			shortname, gadget->name);
+		printk (KERN_ERR "%s expected %s controller not %s\n",
+			shortname, CHIP, gadget->name);
 		return -ENODEV;
 	}
 
@@ -1727,6 +1744,26 @@ static struct usb_gadget_driver gadgetfs_driver = {
 
 /*----------------------------------------------------------------------*/
 
+static void gadgetfs_nop(struct usb_gadget *arg) { }
+
+static int gadgetfs_probe (struct usb_gadget *gadget)
+{
+	CHIP = gadget->name;
+	return -EISNAM;
+}
+
+static struct usb_gadget_driver probe_driver = {
+	.speed		= USB_SPEED_HIGH,
+	.bind		= gadgetfs_probe,
+	.unbind		= gadgetfs_nop,
+	.setup		= (void *)gadgetfs_nop,
+	.disconnect	= gadgetfs_nop,
+	.driver 	= {
+		.name		= "nop",
+	},
+};
+
+
 /* DEVICE INITIALIZATION
  *
  *     fd = open ("/dev/gadget/$CHIP", O_RDWR)
@@ -1763,6 +1800,7 @@ static int is_valid_config (struct usb_config_descriptor *config)
 		&& config->bConfigurationValue != 0
 		&& (config->bmAttributes & USB_CONFIG_ATT_ONE) != 0
 		&& (config->bmAttributes & USB_CONFIG_ATT_WAKEUP) == 0;
+	/* FIXME if gadget->is_otg, _must_ include an otg descriptor */
 	/* FIXME check lengths: walk to end */
 }
 
@@ -1881,6 +1919,8 @@ dev_open (struct inode *inode, struct file *fd)
 
 static struct file_operations dev_init_operations = {
 	.owner =	THIS_MODULE,
+	.llseek =	no_llseek,
+
 	.open =		dev_open,
 	.write =	dev_config,
 	.fasync =	ep0_fasync,
@@ -1976,6 +2016,11 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent)
 	if (the_device)
 		return -ESRCH;
 
+	/* fake probe to determine $CHIP */
+	(void) usb_gadget_register_driver (&probe_driver);
+	if (!CHIP)
+		return -ENODEV;
+
 	/* superblock */
 	sb->s_blocksize = PAGE_CACHE_SIZE;
 	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 880b1f799..d28de0b8c 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -7,13 +7,9 @@
  *
  * CODE STATUS HIGHLIGHTS
  *
- * Used with a gadget driver like "zero.c" this enumerates fine to Windows
- * or Linux hosts; handles disconnect, reconnect, and reset, for full or
- * high speed operation; and passes USB-IF "chapter 9" tests.
- *
- * Handles standard stress loads from the Linux "usbtest" driver, with
- * either DMA (default) or PIO (use_dma=n) used for ep-{a,b,c,d}.  Testing
- * with "ttcp" (and the "ether.c" driver) behaves nicely too.
+ * This driver should work well with most "gadget" drivers, including
+ * the File Storage, Serial, and Ethernet/RNDIS gadget drivers
+ * as well as Gadget Zero and Gadgetfs.
  *
  * DMA is enabled by default.  Drivers using transfer queues might use
  * DMA chaining to remove IRQ latencies between transfers.  (Except when
@@ -257,7 +253,7 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
 	return 0;
 }
 
-static int handshake (u32 *ptr, u32 mask, u32 done, int usec)
+static int handshake (u32 __iomem *ptr, u32 mask, u32 done, int usec)
 {
 	u32	result;
 
@@ -276,7 +272,7 @@ static int handshake (u32 *ptr, u32 mask, u32 done, int usec)
 
 static struct usb_ep_ops net2280_ep_ops;
 
-static void ep_reset (struct net2280_regs *regs, struct net2280_ep *ep)
+static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep)
 {
 	u32		tmp;
 
@@ -307,14 +303,16 @@ static void ep_reset (struct net2280_regs *regs, struct net2280_ep *ep)
 	/* init to our chosen defaults, notably so that we NAK OUT
 	 * packets until the driver queues a read (+note erratum 0112)
 	 */
-	writel (  (1 << SET_NAK_OUT_PACKETS_MODE)
+	tmp = (1 << SET_NAK_OUT_PACKETS_MODE)
 		| (1 << SET_NAK_OUT_PACKETS)
 		| (1 << CLEAR_EP_HIDE_STATUS_PHASE)
-		| (1 << CLEAR_INTERRUPT_MODE)
-		| (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
-		| (1 << CLEAR_ENDPOINT_TOGGLE)
-		| (1 << CLEAR_ENDPOINT_HALT)
-		, &ep->regs->ep_rsp);
+		| (1 << CLEAR_INTERRUPT_MODE);
+
+	if (ep->num != 0) {
+		tmp |= (1 << CLEAR_ENDPOINT_TOGGLE)
+			| (1 << CLEAR_ENDPOINT_HALT);
+	}
+	writel (tmp, &ep->regs->ep_rsp);
 
 	/* scrub most status bits, and flush any fifo state */
 	writel (  (1 << TIMEOUT)
@@ -517,7 +515,7 @@ net2280_free_buffer (
 static void
 write_fifo (struct net2280_ep *ep, struct usb_request *req)
 {
-	struct net2280_ep_regs	*regs = ep->regs;
+	struct net2280_ep_regs	__iomem *regs = ep->regs;
 	u8			*buf;
 	u32			tmp;
 	unsigned		count, total;
@@ -577,7 +575,8 @@ write_fifo (struct net2280_ep *ep, struct usb_request *req)
  */
 static void out_flush (struct net2280_ep *ep)
 {
-	u32	*statp, tmp;
+	u32	__iomem *statp;
+	u32	tmp;
 
 	ASSERT_OUT_NAKING (ep);
 
@@ -610,7 +609,7 @@ static void out_flush (struct net2280_ep *ep)
 static int
 read_fifo (struct net2280_ep *ep, struct net2280_request *req)
 {
-	struct net2280_ep_regs	*regs = ep->regs;
+	struct net2280_ep_regs	__iomem *regs = ep->regs;
 	u8			*buf = req->req.buf + req->req.actual;
 	unsigned		count, tmp, is_short;
 	unsigned		cleanup = 0, prevent = 0;
@@ -678,7 +677,7 @@ read_fifo (struct net2280_ep *ep, struct net2280_request *req)
 	}
 	if (count) {
 		tmp = readl (&regs->ep_data);
-		cpu_to_le32s (&tmp);
+		/* LE conversion is implicit here: */
 		do {
 			*buf++ = (u8) tmp;
 			tmp >>= 8;
@@ -737,12 +736,12 @@ static const u32 dmactl_default =
 		/* erratum 0116 workaround part 2 (no AUTOSTART) */
 		| (1 << DMA_ENABLE);
 
-static inline void spin_stop_dma (struct net2280_dma_regs *dma)
+static inline void spin_stop_dma (struct net2280_dma_regs __iomem *dma)
 {
 	handshake (&dma->dmactl, (1 << DMA_ENABLE), 0, 50);
 }
 
-static inline void stop_dma (struct net2280_dma_regs *dma)
+static inline void stop_dma (struct net2280_dma_regs __iomem *dma)
 {
 	writel (readl (&dma->dmactl) & ~(1 << DMA_ENABLE), &dma->dmactl);
 	spin_stop_dma (dma);
@@ -750,7 +749,7 @@ static inline void stop_dma (struct net2280_dma_regs *dma)
 
 static void start_queue (struct net2280_ep *ep, u32 dmactl, u32 td_dma)
 {
-	struct net2280_dma_regs	*dma = ep->dma;
+	struct net2280_dma_regs	__iomem *dma = ep->dma;
 
 	writel ((1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION),
 			&dma->dmacount);
@@ -771,7 +770,7 @@ static void start_queue (struct net2280_ep *ep, u32 dmactl, u32 td_dma)
 static void start_dma (struct net2280_ep *ep, struct net2280_request *req)
 {
 	u32			tmp;
-	struct net2280_dma_regs	*dma = ep->dma;
+	struct net2280_dma_regs	__iomem *dma = ep->dma;
 
 	/* FIXME can't use DMA for ZLPs */
 
@@ -1419,10 +1418,34 @@ static int net2280_set_selfpowered (struct usb_gadget *_gadget, int value)
 	return 0;
 }
 
+static int net2280_pullup(struct usb_gadget *_gadget, int is_on)
+{
+	struct net2280  *dev;
+	u32             tmp;
+	unsigned long   flags;
+
+	if (!_gadget)
+		return -ENODEV;
+	dev = container_of (_gadget, struct net2280, gadget);
+
+	spin_lock_irqsave (&dev->lock, flags);
+	tmp = readl (&dev->usb->usbctl);
+	dev->softconnect = (is_on != 0);
+	if (is_on)
+		tmp |= (1 << USB_DETECT_ENABLE);
+	else
+		tmp &= ~(1 << USB_DETECT_ENABLE);
+	writel (tmp, &dev->usb->usbctl);
+	spin_unlock_irqrestore (&dev->lock, flags);
+
+	return 0;
+}
+
 static const struct usb_gadget_ops net2280_ops = {
 	.get_frame	= net2280_get_frame,
 	.wakeup		= net2280_wakeup,
 	.set_selfpowered = net2280_set_selfpowered,
+	.pullup		= net2280_pullup,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -1807,8 +1830,6 @@ static void usb_reset (struct net2280 *dev)
 {
 	u32	tmp;
 
-	/* force immediate bus disconnect, and synch through pci */
-	writel (0, &dev->usb->usbctl);
 	dev->gadget.speed = USB_SPEED_UNKNOWN;
 	(void) readl (&dev->usb->usbctl);
 
@@ -1902,10 +1923,8 @@ static void ep0_start (struct net2280 *dev)
 		, &dev->usb->stdrsp);
 	writel (  (1 << USB_ROOT_PORT_WAKEUP_ENABLE)
 		| (1 << SELF_POWERED_USB_DEVICE)
-		/* erratum 0102 workaround */
-		| ((dev->chiprev == 0100) ? 0 : 1) << SUSPEND_IMMEDIATELY
 		| (1 << REMOTE_WAKEUP_SUPPORT)
-		| (1 << USB_DETECT_ENABLE)
+		| (dev->softconnect << USB_DETECT_ENABLE)
 		| (1 << SELF_POWERED_STATUS)
 		, &dev->usb->usbctl);
 
@@ -1957,6 +1976,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
 		dev->ep [i].irqs = 0;
 
 	/* hook up the driver ... */
+	dev->softconnect = 1;
 	driver->driver.bus = NULL;
 	dev->driver = driver;
 	dev->gadget.dev.driver = &driver->driver;
@@ -2028,6 +2048,8 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
 	stop_activity (dev, driver);
 	spin_unlock_irqrestore (&dev->lock, flags);
 
+	net2280_pullup (&dev->gadget, 0);
+
 	driver->unbind (&dev->gadget);
 	dev->gadget.dev.driver = NULL;
 	dev->driver = NULL;
@@ -2492,15 +2514,23 @@ next_endpoints:
 static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
 {
 	struct net2280_ep	*ep;
-	u32			tmp, num, scratch;
+	u32			tmp, num, mask, scratch;
 
 	/* after disconnect there's nothing else to do! */
 	tmp = (1 << VBUS_INTERRUPT) | (1 << ROOT_PORT_RESET_INTERRUPT);
+	mask = (1 << HIGH_SPEED) | (1 << FULL_SPEED);
+
+	/* VBUS disconnect is indicated by VBUS_PIN and VBUS_INTERRUPT set.
+	 * Root Port Reset is indicated by ROOT_PORT_RESET_INTERRRUPT set and
+	 * both HIGH_SPEED and FULL_SPEED clear (as ROOT_PORT_RESET_INTERRUPT 
+	 * only indicates a change in the reset state).
+	 */
 	if (stat & tmp) {
 		writel (tmp, &dev->regs->irqstat1);
-		if (((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) != 0
-			|| (readl (&dev->usb->usbctl) & (1 << VBUS_PIN)) == 0
-			) && dev->gadget.speed != USB_SPEED_UNKNOWN) {
+		if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) && 
+				((readl (&dev->usb->usbstat) & mask) == 0))
+				|| ((readl (&dev->usb->usbctl) & (1 << VBUS_PIN)) == 0) 
+			    ) && ( dev->gadget.speed != USB_SPEED_UNKNOWN)) {
 			DEBUG (dev, "disconnect %s\n",
 					dev->driver->driver.name);
 			stop_activity (dev, dev->driver);
@@ -2525,8 +2555,6 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
 		if (stat & (1 << SUSPEND_REQUEST_INTERRUPT)) {
 			if (dev->driver->suspend)
 				dev->driver->suspend (&dev->gadget);
-			/* we use SUSPEND_IMMEDIATELY */
-			stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT);
 		} else {
 			if (dev->driver->resume)
 				dev->driver->resume (&dev->gadget);
@@ -2553,7 +2581,7 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
 	stat &= ~DMA_INTERRUPTS;
 	scratch >>= 9;
 	for (num = 0; scratch; num++) {
-		struct net2280_dma_regs	*dma;
+		struct net2280_dma_regs	__iomem *dma;
 
 		tmp = 1 << num;
 		if ((tmp & scratch) == 0)
@@ -2722,7 +2750,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct net2280		*dev;
 	unsigned long		resource, len;
-	void			*base = NULL;
+	void			__iomem *base = NULL;
 	int			retval, i;
 	char			buf [8], *bufp;
 
@@ -2780,14 +2808,15 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
 		retval = -EFAULT;
 		goto done;
 	}
-	dev->regs = (struct net2280_regs *) base;
-	dev->usb = (struct net2280_usb_regs *) (base + 0x0080);
-	dev->pci = (struct net2280_pci_regs *) (base + 0x0100);
-	dev->dma = (struct net2280_dma_regs *) (base + 0x0180);
-	dev->dep = (struct net2280_dep_regs *) (base + 0x0200);
-	dev->epregs = (struct net2280_ep_regs *) (base + 0x0300);
+	dev->regs = (struct net2280_regs __iomem *) base;
+	dev->usb = (struct net2280_usb_regs __iomem *) (base + 0x0080);
+	dev->pci = (struct net2280_pci_regs __iomem *) (base + 0x0100);
+	dev->dma = (struct net2280_dma_regs __iomem *) (base + 0x0180);
+	dev->dep = (struct net2280_dep_regs __iomem *) (base + 0x0200);
+	dev->epregs = (struct net2280_ep_regs __iomem *) (base + 0x0300);
 
 	/* put into initial config, link up all endpoints */
+	writel (0, &dev->usb->usbctl);
 	usb_reset (dev);
 	usb_reinit (dev);
 
diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
index ec9d6f7e7..8033c4eec 100644
--- a/drivers/usb/gadget/net2280.h
+++ b/drivers/usb/gadget/net2280.h
@@ -446,7 +446,7 @@ struct net2280_ep_regs {	/* [11.9] */
  */
 
 static inline u32
-get_idx_reg (struct net2280_regs *regs, u32 index)
+get_idx_reg (struct net2280_regs __iomem *regs, u32 index)
 {
 	writel (index, &regs->idxaddr);
 	/* NOTE:  synchs device/cpu memory views */
@@ -454,7 +454,7 @@ get_idx_reg (struct net2280_regs *regs, u32 index)
 }
 
 static inline void
-set_idx_reg (struct net2280_regs *regs, u32 index, u32 value)
+set_idx_reg (struct net2280_regs __iomem *regs, u32 index, u32 value)
 {
 	writel (index, &regs->idxaddr);
 	writel (value, &regs->idxdata);
@@ -507,8 +507,8 @@ struct net2280_dma {
 
 struct net2280_ep {
 	struct usb_ep				ep;
-	struct net2280_ep_regs			*regs;
-	struct net2280_dma_regs			*dma;
+	struct net2280_ep_regs			__iomem *regs;
+	struct net2280_dma_regs			__iomem *dma;
 	struct net2280_dma			*dummy;
 	dma_addr_t				td_dma;	/* of dummy */
 	struct net2280				*dev;
@@ -539,7 +539,7 @@ static inline void allow_status (struct net2280_ep *ep)
 /* count (<= 4) bytes in the next fifo write will be valid */
 static inline void set_fifo_bytecount (struct net2280_ep *ep, unsigned count)
 {
-	writeb (count, 2 + (u8 *) &ep->regs->ep_cfg);
+	writeb (count, 2 + (u8 __iomem *) &ep->regs->ep_cfg);
 }
 
 struct net2280_request {
@@ -559,18 +559,19 @@ struct net2280 {
 	struct usb_gadget_driver 	*driver;
 	unsigned			enabled : 1,
 					protocol_stall : 1,
+					softconnect : 1,
 					got_irq : 1,
 					region : 1;
 	u16				chiprev;
 
 	/* pci state used to access those endpoints */
 	struct pci_dev			*pdev;
-	struct net2280_regs		*regs;
-	struct net2280_usb_regs		*usb;
-	struct net2280_pci_regs		*pci;
-	struct net2280_dma_regs		*dma;
-	struct net2280_dep_regs		*dep;
-	struct net2280_ep_regs		*epregs;
+	struct net2280_regs		__iomem *regs;
+	struct net2280_usb_regs		__iomem *usb;
+	struct net2280_pci_regs		__iomem *pci;
+	struct net2280_dma_regs		__iomem *dma;
+	struct net2280_dep_regs		__iomem *dep;
+	struct net2280_ep_regs		__iomem *epregs;
 
 	struct pci_pool			*requests;
 	// statistics...
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 63e538a57..c1139b51d 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -54,6 +54,7 @@
 #include <asm/mach-types.h>
 #include <asm/unaligned.h>
 #include <asm/hardware.h>
+#include <asm/arch/pxa-regs.h>
 
 #include <linux/usb_ch9.h>
 #include <linux/usb_gadget.h>
@@ -116,7 +117,7 @@ static const char ep0name [] = "ep0";
 
 #ifdef	USE_DMA
 static int use_dma = 1;
-MODULE_PARM (use_dma, "i");
+module_param(use_dma, bool, 0);
 MODULE_PARM_DESC (use_dma, "true to use dma");
 
 static void dma_nodesc_handler (int dmach, void *_ep, struct pt_regs *r);
@@ -146,7 +147,7 @@ static void kick_dma(struct pxa2xx_ep *ep, struct pxa2xx_request *req);
  * ... so mode = 3 (or 7, 15, etc) does it for both
  */
 static ushort fifo_mode = 0;
-MODULE_PARM (fifo_mode, "h");
+module_param(fifo_mode, ushort, 0);
 MODULE_PARM_DESC (fifo_mode, "pxa2xx udc fifo mode");
 #endif
 
@@ -1508,7 +1509,7 @@ static void udc_enable (struct pxa2xx_udc *dev)
 	/* caller must be able to sleep in order to cope
 	 * with startup transients.
 	 */
-	schedule_timeout(HZ/10);
+	msleep(100);
 
 	/* enable suspend/resume and reset irqs */
 	udc_clear_mask_UDCCR(UDCCR_SRM | UDCCR_REM);
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index ebfc22b2a..1e18e92a6 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -48,6 +48,8 @@
 #include <linux/usb_ch9.h>
 #include <linux/usb_gadget.h>
 
+#include "gadget_chips.h"
+
 
 /* Wait Cond */
 
@@ -123,8 +125,8 @@ do {									\
 
 /* Defines */
 
-#define GS_VERSION_STR			"v0.1"
-#define GS_VERSION_NUM			0x0001
+#define GS_VERSION_STR			"v1.0"
+#define GS_VERSION_NUM			0x0100
 
 #define GS_LONG_NAME			"Gadget Serial"
 #define GS_SHORT_NAME			"g_serial"
@@ -173,164 +175,6 @@ static int debug = G_SERIAL_DEBUG;
 #endif /* G_SERIAL_DEBUG */
 
 
-/* USB Controllers */
-
-/*
- * NetChip 2280, PCI based.
- *
- * This has half a dozen configurable endpoints, four with dedicated
- * DMA channels to manage their FIFOs.  It supports high speed.
- * Those endpoints can be arranged in any desired configuration.
- */
-#ifdef	CONFIG_USB_GADGET_NET2280
-#define CHIP				"net2280"
-#define EP0_MAXPACKET			64
-static const char EP_OUT_NAME[] =	"ep-a";
-#define EP_OUT_NUM			2
-static const char EP_IN_NAME[] =	"ep-b";
-#define EP_IN_NUM			2
-#define HIGHSPEED
-#define SELFPOWER			USB_CONFIG_ATT_SELFPOWER
-
-extern int net2280_set_fifo_mode(struct usb_gadget *gadget, int mode);
-
-static inline void hw_optimize(struct usb_gadget *gadget)
-{
-	/* we can have bigger ep-a/ep-b fifos (2KB each, 4 packets
-	 * for highspeed bulk) because we're not using ep-c/ep-d.
-	 */
-	net2280_set_fifo_mode (gadget, 1);
-}
-#endif
-
-
-/*
- * Dummy_hcd, software-based loopback controller.
- *
- * This imitates the abilities of the NetChip 2280, so we will use
- * the same configuration.
- */
-#ifdef	CONFIG_USB_GADGET_DUMMY_HCD
-#define CHIP				"dummy"
-#define EP0_MAXPACKET			64
-static const char EP_OUT_NAME[] =	"ep-a";
-#define EP_OUT_NUM			2
-static const char EP_IN_NAME[] =	"ep-b";
-#define EP_IN_NUM			2
-#define HIGHSPEED
-#define SELFPOWER			USB_CONFIG_ATT_SELFPOWER
-
-/* no hw optimizations to apply */
-#define hw_optimize(g)			do {} while (0)
-#endif
-
-
-/*
- * PXA-2xx UDC:  widely used in second gen Linux-capable PDAs.
- *
- * This has fifteen fixed-function full speed endpoints, and it
- * can support all USB transfer types.
- *
- * These supports three or four configurations, with fixed numbers.
- * The hardware interprets SET_INTERFACE, net effect is that you
- * can't use altsettings or reset the interfaces independently.
- * So stick to a single interface.
- */
-#ifdef	CONFIG_USB_GADGET_PXA2XX
-#define CHIP				"pxa2xx"
-#define EP0_MAXPACKET			16
-static const char EP_OUT_NAME[] =	"ep2out-bulk";
-#define EP_OUT_NUM			2
-static const char EP_IN_NAME[] =	"ep1in-bulk";
-#define EP_IN_NUM			1
-#define SELFPOWER 			USB_CONFIG_ATT_SELFPOWER
-
-/* no hw optimizations to apply */
-#define hw_optimize(g)			do {} while (0)
-#endif
-
-#ifdef	CONFIG_USB_GADGET_OMAP
-#define CHIP			"omap"
-#define EP0_MAXPACKET			64
-static const char EP_OUT_NAME [] = "ep2out-bulk";
-#define EP_OUT_NUM	2
-static const char EP_IN_NAME [] = "ep1in-bulk";
-#define EP_IN_NUM	1
-#define SELFPOWER 			USB_CONFIG_ATT_SELFPOWER
-/* supports remote wakeup, but this driver doesn't */
-
-/* no hw optimizations to apply */
-#define hw_optimize(g) do {} while (0)
-#endif
-
-
-/*
- * SA-1100 UDC:  widely used in first gen Linux-capable PDAs.
- *
- * This has only two fixed function endpoints, which can only
- * be used for bulk (or interrupt) transfers.  (Plus control.)
- *
- * Since it can't flush its TX fifos without disabling the UDC,
- * the current configuration or altsettings can't change except
- * in special situations.  So this is a case of "choose it right
- * during enumeration" ...
- */
-#ifdef	CONFIG_USB_GADGET_SA1100
-#define CHIP				"sa1100"
-#define EP0_MAXPACKET			8
-static const char EP_OUT_NAME[] =	"ep1out-bulk";
-#define EP_OUT_NUM			1
-static const char EP_IN_NAME [] =	"ep2in-bulk";
-#define EP_IN_NUM			2
-#define SELFPOWER			USB_CONFIG_ATT_SELFPOWER
-
-/* no hw optimizations to apply */
-#define hw_optimize(g)			do {} while (0)
-#endif
-
-
-/*
- * Toshiba TC86C001 ("Goku-S") UDC
- *
- * This has three semi-configurable full speed bulk/interrupt endpoints.
- */
-#ifdef	CONFIG_USB_GADGET_GOKU
-#define CHIP				"goku"
-#define DRIVER_VERSION_NUM		0x0116
-#define EP0_MAXPACKET			8
-static const char EP_OUT_NAME [] =	"ep1-bulk";
-#define EP_OUT_NUM			1
-static const char EP_IN_NAME [] =	"ep2-bulk";
-#define EP_IN_NUM			2
-#define SELFPOWER			USB_CONFIG_ATT_SELFPOWER
-
-/* no hw optimizations to apply */
-#define hw_optimize(g)			do {} while (0)
-#endif
-
-/*
- * USB Controller Defaults
- */
-#ifndef EP0_MAXPACKET
-#error Configure some USB peripheral controller for g_serial!
-#endif
-
-#ifndef SELFPOWER
-/* default: say we rely on bus power */
-#define SELFPOWER   			0
-/* else value must be USB_CONFIG_ATT_SELFPOWER */
-#endif
-
-#ifndef	MAX_USB_POWER
-/* any hub supports this steady state bus power consumption */
-#define MAX_USB_POWER			100	/* mA */
-#endif
-
-#ifndef	WAKEUP
-/* default: this driver won't do remote wakeup */
-#define WAKEUP				0
-/* else value must be USB_CONFIG_ATT_WAKEUP */
-#endif
 
 /* Thanks to NetChip Technologies for donating this product ID.
  *
@@ -449,11 +293,17 @@ static unsigned int gs_buf_put(struct gs_buf *gb, const char *buf,
 static unsigned int gs_buf_get(struct gs_buf *gb, char *buf,
 	unsigned int count);
 
+/* external functions */
+extern int net2280_set_fifo_mode(struct usb_gadget *gadget, int mode);
+
 
 /* Globals */
 
 static struct gs_dev *gs_device;
 
+static const char *EP_IN_NAME;
+static const char *EP_OUT_NAME;
+
 static struct semaphore	gs_open_close_sem[GS_NUM_PORTS];
 
 static unsigned int read_q_size = GS_DEFAULT_READ_Q_SIZE;
@@ -483,7 +333,7 @@ static struct tty_driver *gs_tty_driver;
 
 /* gadget driver struct */
 static struct usb_gadget_driver gs_gadget_driver = {
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 	.speed =		USB_SPEED_HIGH,
 #else
 	.speed =		USB_SPEED_FULL,
@@ -510,8 +360,9 @@ static struct usb_gadget_driver gs_gadget_driver = {
 #define GS_CONFIG_STR_ID	4
 
 /* static strings, in iso 8859/1 */
+static char manufacturer[40];
 static struct usb_string gs_strings[] = {
-	{ GS_MANUFACTURER_STR_ID, UTS_SYSNAME " " UTS_RELEASE " with " CHIP },
+	{ GS_MANUFACTURER_STR_ID, manufacturer },
 	{ GS_PRODUCT_STR_ID, GS_LONG_NAME },
 	{ GS_SERIAL_STR_ID, "0" },
 	{ GS_CONFIG_STR_ID, "Bulk" },
@@ -523,15 +374,13 @@ static struct usb_gadget_strings gs_string_table = {
 	.strings =		gs_strings,
 };
 
-static const struct usb_device_descriptor gs_device_desc = {
+static struct usb_device_descriptor gs_device_desc = {
 	.bLength =		USB_DT_DEVICE_SIZE,
 	.bDescriptorType =	USB_DT_DEVICE,
 	.bcdUSB =		__constant_cpu_to_le16(0x0200),
 	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,
-	.bMaxPacketSize0 =	EP0_MAXPACKET,
 	.idVendor =		__constant_cpu_to_le16(GS_VENDOR_ID),
 	.idProduct =		__constant_cpu_to_le16(GS_PRODUCT_ID),
-	.bcdDevice =		__constant_cpu_to_le16(GS_VERSION_NUM),
 	.iManufacturer =	GS_MANUFACTURER_STR_ID,
 	.iProduct =		GS_PRODUCT_STR_ID,
 	.iSerialNumber =	GS_SERIAL_STR_ID,
@@ -545,8 +394,8 @@ static const struct usb_config_descriptor gs_config_desc = {
 	.bNumInterfaces =	GS_NUM_INTERFACES,
 	.bConfigurationValue =	GS_BULK_CONFIG_ID,
 	.iConfiguration =	GS_CONFIG_STR_ID,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | SELFPOWER | WAKEUP,
-	.bMaxPower =		(MAX_USB_POWER + 1) / 2,
+	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower =		1,
 };
 
 static const struct usb_interface_descriptor gs_interface_desc = {
@@ -557,46 +406,41 @@ static const struct usb_interface_descriptor gs_interface_desc = {
 	.iInterface =		GS_CONFIG_STR_ID,
 };
 
-static const struct usb_endpoint_descriptor gs_fullspeed_in_desc = {
+static struct usb_endpoint_descriptor gs_fullspeed_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bEndpointAddress =	EP_IN_NUM | USB_DIR_IN,
+	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(64),
 };
 
-static const struct usb_endpoint_descriptor gs_fullspeed_out_desc = {
+static struct usb_endpoint_descriptor gs_fullspeed_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bEndpointAddress =	EP_OUT_NUM | USB_DIR_OUT,
+	.bEndpointAddress =	USB_DIR_OUT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(64),
 };
 
-static const struct usb_endpoint_descriptor gs_highspeed_in_desc = {
+static struct usb_endpoint_descriptor gs_highspeed_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bEndpointAddress =	EP_IN_NUM | USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	__constant_cpu_to_le16(512),
 };
 
-static const struct usb_endpoint_descriptor gs_highspeed_out_desc = {
+static struct usb_endpoint_descriptor gs_highspeed_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
-	.bEndpointAddress =	EP_OUT_NUM | USB_DIR_OUT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	__constant_cpu_to_le16(512),
 };
 
-#ifdef HIGHSPEED
-static const struct usb_qualifier_descriptor gs_qualifier_desc = {
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+static struct usb_qualifier_descriptor gs_qualifier_desc = {
 	.bLength =		sizeof(struct usb_qualifier_descriptor),
 	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
 	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
 	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,
 	/* assumes ep0 uses the same value for both speeds ... */
-	.bMaxPacketSize0 =	EP0_MAXPACKET,
 	.bNumConfigurations =	GS_NUM_CONFIGS,
 };
 #endif
@@ -608,17 +452,17 @@ MODULE_AUTHOR("Al Borchers");
 MODULE_LICENSE("GPL");
 
 #if G_SERIAL_DEBUG
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Enable debugging, 0=off, 1=on");
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging, 0=off, 1=on, larger values for more messages");
 #endif
 
-MODULE_PARM(read_q_size, "i");
+module_param(read_q_size, int, 0);
 MODULE_PARM_DESC(read_q_size, "Read request queue size, default=32");
 
-MODULE_PARM(write_q_size, "i");
+module_param(write_q_size, int, 0);
 MODULE_PARM_DESC(write_q_size, "Write request queue size, default=32");
 
-MODULE_PARM(write_buf_size, "i");
+module_param(write_buf_size, int, 0);
 MODULE_PARM_DESC(write_buf_size, "Write buffer size, default=8192");
 
 module_init(gs_module_init);
@@ -1416,18 +1260,81 @@ requeue:
 static int gs_bind(struct usb_gadget *gadget)
 {
 	int ret;
+	struct usb_ep *ep;
 	struct gs_dev *dev;
 
+	usb_ep_autoconfig_reset(gadget);
+
+	ep = usb_ep_autoconfig(gadget, &gs_fullspeed_in_desc);
+	if (!ep)
+		goto autoconf_fail;
+	EP_IN_NAME = ep->name;
+	ep->driver_data = ep;	/* claim the endpoint */
+
+	ep = usb_ep_autoconfig(gadget, &gs_fullspeed_out_desc);
+	if (!ep)
+		goto autoconf_fail;
+	EP_OUT_NAME = ep->name;
+	ep->driver_data = ep;	/* claim the endpoint */
+
+	/* device specific bcdDevice value in device descriptor */
+	if (gadget_is_net2280(gadget)) {
+		gs_device_desc.bcdDevice =
+			__constant_cpu_to_le16(GS_VERSION_NUM|0x0001);
+	} else if (gadget_is_pxa(gadget)) {
+		gs_device_desc.bcdDevice =
+			__constant_cpu_to_le16(GS_VERSION_NUM|0x0002);
+	} else if (gadget_is_sh(gadget)) {
+		gs_device_desc.bcdDevice =
+			__constant_cpu_to_le16(GS_VERSION_NUM|0x0003);
+	} else if (gadget_is_sa1100(gadget)) {
+		gs_device_desc.bcdDevice =
+			__constant_cpu_to_le16(GS_VERSION_NUM|0x0004);
+	} else if (gadget_is_goku(gadget)) {
+		gs_device_desc.bcdDevice =
+			__constant_cpu_to_le16(GS_VERSION_NUM|0x0005);
+	} else if (gadget_is_mq11xx(gadget)) {
+		gs_device_desc.bcdDevice =
+			__constant_cpu_to_le16(GS_VERSION_NUM|0x0006);
+	} else if (gadget_is_omap(gadget)) {
+		gs_device_desc.bcdDevice =
+			__constant_cpu_to_le16(GS_VERSION_NUM|0x0007);
+	} else if (gadget_is_lh7a40x(gadget)) {
+		gs_device_desc.bcdDevice =
+			__constant_cpu_to_le16(GS_VERSION_NUM|0x0008);
+	} else {
+		printk(KERN_WARNING "gs_bind: controller '%s' not recognized\n",
+			gadget->name);
+		/* unrecognized, but safe unless bulk is REALLY quirky */
+		gs_device_desc.bcdDevice =
+			__constant_cpu_to_le16(GS_VERSION_NUM|0x0099);
+	}
+
+	gs_device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+	/* assume ep0 uses the same packet size for both speeds */
+	gs_qualifier_desc.bMaxPacketSize0 = gs_device_desc.bMaxPacketSize0;
+	/* assume endpoints are dual-speed */
+	gs_highspeed_in_desc.bEndpointAddress =
+		gs_fullspeed_in_desc.bEndpointAddress;
+	gs_highspeed_out_desc.bEndpointAddress =
+		gs_fullspeed_out_desc.bEndpointAddress;
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
+
+	usb_gadget_set_selfpowered(gadget);
+
 	gs_device = dev = kmalloc(sizeof(struct gs_dev), GFP_KERNEL);
 	if (dev == NULL)
 		return -ENOMEM;
 
-	set_gadget_data(gadget, dev);
+	snprintf (manufacturer, sizeof(manufacturer),
+		UTS_SYSNAME " " UTS_RELEASE " with %s", gadget->name);
 
 	memset(dev, 0, sizeof(struct gs_dev));
 	dev->dev_gadget = gadget;
 	spin_lock_init(&dev->dev_lock);
 	INIT_LIST_HEAD(&dev->dev_req_list);
+	set_gadget_data(gadget, dev);
 
 	if ((ret=gs_alloc_ports(dev, GFP_KERNEL)) != 0) {
 		printk(KERN_ERR "gs_bind: cannot allocate ports\n");
@@ -1450,6 +1357,10 @@ static int gs_bind(struct usb_gadget *gadget)
 		GS_LONG_NAME, GS_VERSION_STR);
 
 	return 0;
+
+autoconf_fail:
+	printk(KERN_ERR "gs_bind: cannot autoconfigure on %s\n", gadget->name);
+	return -ENODEV;
 }
 
 /*
@@ -1505,15 +1416,17 @@ static int gs_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctr
 			memcpy(req->buf, &gs_device_desc, ret);
 			break;
 
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 		case USB_DT_DEVICE_QUALIFIER:
+			if (!gadget->is_dualspeed)
+				break;
 			ret = min(ctrl->wLength,
 				(u16)sizeof(struct usb_qualifier_descriptor));
 			memcpy(req->buf, &gs_qualifier_desc, ret);
 			break;
 
 		case USB_DT_OTHER_SPEED_CONFIG:
-#endif /* HIGHSPEED */
+#endif /* CONFIG_USB_GADGET_DUALSPEED */
 		case USB_DT_CONFIG:
 			ret = gs_build_config_desc(req->buf, gadget->speed,
 				ctrl->wValue >> 8, ctrl->wValue & 0xff);
@@ -1677,7 +1590,9 @@ static int gs_set_config(struct gs_dev *dev, unsigned config)
 	if (config != GS_BULK_CONFIG_ID)
 		return -EINVAL;
 
-	hw_optimize(gadget);
+	/* device specific optimizations */
+	if (gadget_is_net2280(gadget))
+		net2280_set_fifo_mode(gadget, 1);
 
 	gadget_for_each_ep(ep, gadget) {
 
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
index 4fa5e1c8f..a415a33ed 100644
--- a/drivers/usb/gadget/zero.c
+++ b/drivers/usb/gadget/zero.c
@@ -399,7 +399,7 @@ static const struct usb_descriptor_header *hs_loopback_function [] = {
 static char				manufacturer [40];
 static char				serial [40];
 
-/* static strings, in iso 8859/1 */
+/* static strings, in UTF-8 */
 static struct usb_string		strings [] = {
 	{ STRING_MANUFACTURER, manufacturer, },
 	{ STRING_PRODUCT, longname, },
@@ -960,7 +960,8 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 		case USB_DT_STRING:
 			/* wIndex == language code.
 			 * this driver only handles one language, you can
-			 * add others even if they don't use iso8859/1
+			 * add string tables for other languages, using
+			 * any UTF-8 characters
 			 */
 			value = usb_gadget_get_string (&stringtab,
 					ctrl->wValue & 0xff, req->buf);
@@ -1185,6 +1186,8 @@ autoconf_fail:
 		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0207);
 	} else if (gadget_is_omap (gadget)) {
 		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0208);
+	} else if (gadget_is_lh7a40x(gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0209);
 	} else {
 		/* gadget zero is so simple (for now, no altsettings) that
 		 * it SHOULD NOT have problems with bulk-capable hardware.
@@ -1236,6 +1239,12 @@ autoconf_fail:
 		loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 	}
 
+	if (gadget->is_otg) {
+		otg_descriptor.bmAttributes |= USB_OTG_HNP,
+		source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+		loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+	}
+
 	usb_gadget_set_selfpowered (gadget);
 
 	init_timer (&dev->resume);
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 946898ac4..c6e6362d0 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -52,6 +52,7 @@ config USB_EHCI_ROOT_HUB_TT
 config USB_OHCI_HCD
 	tristate "OHCI HCD support"
 	depends on USB
+	select ISP1301_OMAP if MACH_OMAP_H2
 	---help---
 	  The Open Host Controller Interface (OHCI) is a standard for accessing
 	  USB 1.1 host controller hardware.  It does more in hardware than Intel's
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index ad32ba159..bb8bf4c98 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -119,16 +119,16 @@ static void __attribute__((__unused__))
 dbg_qtd (const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd)
 {
 	ehci_dbg (ehci, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd,
-		cpu_to_le32p (&qtd->hw_next),
-		cpu_to_le32p (&qtd->hw_alt_next),
-		cpu_to_le32p (&qtd->hw_token),
-		cpu_to_le32p (&qtd->hw_buf [0]));
+		le32_to_cpup (&qtd->hw_next),
+		le32_to_cpup (&qtd->hw_alt_next),
+		le32_to_cpup (&qtd->hw_token),
+		le32_to_cpup (&qtd->hw_buf [0]));
 	if (qtd->hw_buf [1])
 		ehci_dbg (ehci, "  p1=%08x p2=%08x p3=%08x p4=%08x\n",
-			cpu_to_le32p (&qtd->hw_buf [1]),
-			cpu_to_le32p (&qtd->hw_buf [2]),
-			cpu_to_le32p (&qtd->hw_buf [3]),
-			cpu_to_le32p (&qtd->hw_buf [4]));
+			le32_to_cpup (&qtd->hw_buf [1]),
+			le32_to_cpup (&qtd->hw_buf [2]),
+			le32_to_cpup (&qtd->hw_buf [3]),
+			le32_to_cpup (&qtd->hw_buf [4]));
 }
 
 static void __attribute__((__unused__))
@@ -331,14 +331,14 @@ static inline void remove_debug_files (struct ehci_hcd *bus) { }
 		default: tmp = '?'; break; \
 		}; tmp; })
 
-static inline char token_mark (u32 token)
+static inline char token_mark (__le32 token)
 {
-	token = le32_to_cpu (token);
-	if (token & QTD_STS_ACTIVE)
+	__u32 v = le32_to_cpu (token);
+	if (v & QTD_STS_ACTIVE)
 		return '*';
-	if (token & QTD_STS_HALT)
+	if (v & QTD_STS_HALT)
 		return '-';
-	if (!IS_SHORT_READ (token))
+	if (!IS_SHORT_READ (v))
 		return ' ';
 	/* tries to advance through hw_alt_next */
 	return '/';
@@ -371,25 +371,25 @@ static void qh_lines (
 			mark = '.';	/* use hw_qtd_next */
 		/* else alt_next points to some other qtd */
 	}
-	scratch = cpu_to_le32p (&qh->hw_info1);
-	hw_curr = (mark == '*') ? cpu_to_le32p (&qh->hw_current) : 0;
+	scratch = le32_to_cpup (&qh->hw_info1);
+	hw_curr = (mark == '*') ? le32_to_cpup (&qh->hw_current) : 0;
 	temp = scnprintf (next, size,
 			"qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)",
 			qh, scratch & 0x007f,
 			speed_char (scratch),
 			(scratch >> 8) & 0x000f,
-			scratch, cpu_to_le32p (&qh->hw_info2),
-			cpu_to_le32p (&qh->hw_token), mark,
+			scratch, le32_to_cpup (&qh->hw_info2),
+			le32_to_cpup (&qh->hw_token), mark,
 			(__constant_cpu_to_le32 (QTD_TOGGLE) & qh->hw_token)
 				? "data1" : "data0",
-			(cpu_to_le32p (&qh->hw_alt_next) >> 1) & 0x0f);
+			(le32_to_cpup (&qh->hw_alt_next) >> 1) & 0x0f);
 	size -= temp;
 	next += temp;
 
 	/* hc may be modifying the list as we read it ... */
 	list_for_each (entry, &qh->qtd_list) {
 		td = list_entry (entry, struct ehci_qtd, qtd_list);
-		scratch = cpu_to_le32p (&td->hw_token);
+		scratch = le32_to_cpup (&td->hw_token);
 		mark = ' ';
 		if (hw_curr == td->qtd_dma)
 			mark = '*';
@@ -488,7 +488,8 @@ show_periodic (struct class_device *class_dev, char *buf)
 	union ehci_shadow	p, *seen;
 	unsigned		temp, size, seen_count;
 	char			*next;
-	unsigned		i, tag;
+	unsigned		i;
+	__le32			tag;
 
 	if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, SLAB_ATOMIC)))
 		return 0;
@@ -541,7 +542,7 @@ show_periodic (struct class_device *class_dev, char *buf)
 				}
 				/* show more info the first time around */
 				if (temp == seen_count && p.ptr) {
-					u32	scratch = cpu_to_le32p (
+					u32	scratch = le32_to_cpup (
 							&p.qh->hw_info1);
 					struct ehci_qtd	*qtd;
 					char		*type = "";
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index d3bb7b508..e25adf501 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -155,7 +155,7 @@ MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes");
  * before driver shutdown. But it also seems to be caused by bugs in cardbus
  * bridge shutdown:  shutting down the bridge before the devices using it.
  */
-static int handshake (u32 *ptr, u32 mask, u32 done, int usec)
+static int handshake (u32 __iomem *ptr, u32 mask, u32 done, int usec)
 {
 	u32	result;
 
@@ -289,7 +289,7 @@ static void ehci_watchdog (unsigned long param)
 static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap)
 {
 	if (cap & (1 << 16)) {
-		int msec = 500;
+		int msec = 5000;
 		struct pci_dev *pdev = to_pci_dev(ehci->hcd.self.controller);
 
 		/* request handoff to OS */
@@ -305,7 +305,10 @@ static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap)
 		if (cap & (1 << 16)) {
 			ehci_err (ehci, "BIOS handoff failed (%d, %04x)\n",
 				where, cap);
-			return 1;
+			// some BIOS versions seem buggy...
+			// return 1;
+			ehci_warn (ehci, "continuing after BIOS bug...\n");
+			return 0;
 		} 
 		ehci_dbg (ehci, "BIOS handoff succeeded\n");
 	}
@@ -337,8 +340,8 @@ static int ehci_hc_reset (struct usb_hcd *hcd)
 
 	spin_lock_init (&ehci->lock);
 
-	ehci->caps = (struct ehci_caps *) hcd->regs;
-	ehci->regs = (struct ehci_regs *) (hcd->regs + 
+	ehci->caps = hcd->regs;
+	ehci->regs = (hcd->regs + 
 				HC_LENGTH (readl (&ehci->caps->hc_capbase)));
 	dbg_hcs_params (ehci, "reset");
 	dbg_hcc_params (ehci, "reset");
@@ -692,9 +695,18 @@ static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs)
 	timer_action_done (ehci, TIMER_IO_WATCHDOG);
 	if (ehci->reclaim_ready)
 		end_unlink_async (ehci, regs);
+
+	/* another CPU may drop ehci->lock during a schedule scan while
+	 * it reports urb completions.  this flag guards against bogus
+	 * attempts at re-entrant schedule scanning.
+	 */
+	if (ehci->scanning)
+		return;
+	ehci->scanning = 1;
 	scan_async (ehci, regs);
 	if (ehci->next_uframe != -1)
 		scan_periodic (ehci, regs);
+	ehci->scanning = 0;
 
 	/* the IO watchdog guards against hardware or driver bugs that
 	 * misplace IRQs, and should let us run completely without IRQs.
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 452c73ede..4ff7f868b 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -146,8 +146,8 @@ static int ehci_hub_resume (struct usb_hcd *hcd)
 
 #else
 
-#define ehci_hub_suspend	0
-#define ehci_hub_resume		0
+#define ehci_hub_suspend	NULL
+#define ehci_hub_resume		NULL
 
 #endif	/* CONFIG_PM */
 
@@ -455,7 +455,7 @@ static int ehci_hub_control (
 #endif
 		dbg_port (ehci, "GetStatus", wIndex + 1, temp);
 		// we "know" this alignment is good, caller used kmalloc()...
-		*((u32 *) buf) = cpu_to_le32 (status);
+		*((__le32 *) buf) = cpu_to_le32 (status);
 		break;
 	case SetHubFeature:
 		switch (wValue) {
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index 31f311d53..beee4d996 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -114,7 +114,7 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags)
 		return qh;
 
 	memset (qh, 0, sizeof *qh);
-	kref_init(&qh->kref, qh_destroy);
+	kref_init(&qh->kref);
 	qh->ehci = ehci;
 	qh->qh_dma = dma;
 	// INIT_LIST_HEAD (&qh->qh_list);
@@ -139,7 +139,7 @@ static inline struct ehci_qh *qh_get (struct ehci_qh *qh)
 
 static inline void qh_put (struct ehci_qh *qh)
 {
-	kref_put(&qh->kref);
+	kref_put(&qh->kref, qh_destroy);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -235,9 +235,9 @@ static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
 	}
 
 	/* Hardware periodic table */
-	ehci->periodic = (u32 *)
+	ehci->periodic = (__le32 *)
 		dma_alloc_coherent (ehci->hcd.self.controller,
-			ehci->periodic_size * sizeof (u32),
+			ehci->periodic_size * sizeof(__le32),
 			&ehci->periodic_dma, 0);
 	if (ehci->periodic == 0) {
 		goto fail;
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index be39e7aba..b80a2f70d 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -153,17 +153,9 @@ static void qtd_copy_status (
 			usb_pipein (urb->pipe) ? "in" : "out",
 			token, urb->status);
 
-		/* stall indicates some recovery action is needed */
-		if (urb->status == -EPIPE) {
-			int	pipe = urb->pipe;
-
-			if (!usb_pipecontrol (pipe))
-				usb_endpoint_halt (urb->dev,
-					usb_pipeendpoint (pipe),
-					usb_pipeout (pipe));
-
 		/* if async CSPLIT failed, try cleaning out the TT buffer */
-		} else if (urb->dev->tt && !usb_pipeint (urb->pipe)
+		if (urb->status != -EPIPE
+				&& urb->dev->tt && !usb_pipeint (urb->pipe)
 				&& ((token & QTD_STS_MMF) != 0
 					|| QTD_CERR(token) == 0)
 				&& (!ehci_is_ARC(ehci)
@@ -729,7 +721,7 @@ done:
 
 static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
-	u32		dma = QH_NEXT (qh->qh_dma);
+	__le32		dma = QH_NEXT (qh->qh_dma);
 	struct ehci_qh	*head;
 
 	/* (re)start the async schedule? */
@@ -764,7 +756,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
 /*-------------------------------------------------------------------------*/
 
-#define	QH_ADDR_MASK	__constant_le32_to_cpu(0x7f)
+#define	QH_ADDR_MASK	__constant_cpu_to_le32(0x7f)
 
 /*
  * For control/bulk/interrupt, return QH with these TDs appended.
@@ -848,7 +840,7 @@ static struct ehci_qh *qh_append_tds (
 		if (likely (qtd != 0)) {
 			struct ehci_qtd		*dummy;
 			dma_addr_t		dma;
-			u32			token;
+			__le32			token;
 
 			/* to avoid racing the HC, use the dummy td instead of
 			 * the first td of our list (becomes new dummy).  both
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 10df2665e..0000c4608 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -44,7 +44,7 @@ static int ehci_get_frame (struct usb_hcd *hcd);
  * @tag: hardware tag for type of this record
  */
 static union ehci_shadow *
-periodic_next_shadow (union ehci_shadow *periodic, int tag)
+periodic_next_shadow (union ehci_shadow *periodic, __le32 tag)
 {
 	switch (tag) {
 	case Q_TYPE_QH:
@@ -64,7 +64,7 @@ periodic_next_shadow (union ehci_shadow *periodic, int tag)
 static int periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
 {
 	union ehci_shadow	*prev_p = &ehci->pshadow [frame];
-	u32			*hw_p = &ehci->periodic [frame];
+	__le32			*hw_p = &ehci->periodic [frame];
 	union ehci_shadow	here = *prev_p;
 	union ehci_shadow	*next_p;
 
@@ -98,7 +98,7 @@ static int periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
 static unsigned short
 periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
 {
-	u32			*hw_p = &ehci->periodic [frame];
+	__le32			*hw_p = &ehci->periodic [frame];
 	union ehci_shadow	*q = &ehci->pshadow [frame];
 	unsigned		usecs = 0;
 
@@ -196,7 +196,7 @@ static int tt_no_collision (
 	 */
 	for (; frame < ehci->periodic_size; frame += period) {
 		union ehci_shadow	here;
-		u32			type;
+		__le32			type;
 
 		here = ehci->pshadow [frame];
 		type = Q_NEXT_TYPE (ehci->periodic [frame]);
@@ -403,7 +403,7 @@ static int check_intr_schedule (
 	unsigned		frame,
 	unsigned		uframe,
 	const struct ehci_qh	*qh,
-	u32			*c_maskp
+	__le32			*c_maskp
 )
 {
     	int		retval = -ENOSPC;
@@ -412,7 +412,7 @@ static int check_intr_schedule (
 		goto done;
 	if (!qh->c_usecs) {
 		retval = 0;
-		*c_maskp = cpu_to_le32 (0);
+		*c_maskp = 0;
 		goto done;
 	}
 
@@ -447,7 +447,7 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
 	int 		status;
 	unsigned	uframe;
-	u32		c_mask;
+	__le32		c_mask;
 	unsigned	frame;		/* 0..(qh->period - 1), or NO_FRAME */
 
 	qh->hw_next = EHCI_LIST_END;
@@ -1008,8 +1008,7 @@ sitd_slot_ok (
 		uframe += period_uframes;
 	} while (uframe < mod);
 
-	stream->splits = stream->raw_mask << (uframe & 7);
-	cpu_to_le32s (&stream->splits);
+	stream->splits = cpu_to_le32(stream->raw_mask << (uframe & 7));
 	return 1;
 }
 
@@ -1812,7 +1811,7 @@ scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs)
 
 	for (;;) {
 		union ehci_shadow	q, *q_p;
-		u32			type, *hw_p;
+		__le32			type, *hw_p;
 		unsigned		uframes;
 
 		/* don't scan past the live uframe */
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index ed4d00291..0e8541133 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -52,12 +52,13 @@ struct ehci_hcd {			/* one per controller */
 	/* async schedule support */
 	struct ehci_qh		*async;
 	struct ehci_qh		*reclaim;
-	int			reclaim_ready : 1;
+	unsigned		reclaim_ready : 1;
+	unsigned		scanning : 1;
 
 	/* periodic schedule support */
 #define	DEFAULT_I_TDPS		1024		/* some HCs can do less */
 	unsigned		periodic_size;
-	u32			*periodic;	/* hw periodic table */
+	__le32			*periodic;	/* hw periodic table */
 	dma_addr_t		periodic_dma;
 	unsigned		i_thresh;	/* uframes HC might cache */
 
@@ -70,9 +71,9 @@ struct ehci_hcd {			/* one per controller */
 
 	/* glue to PCI and HCD framework */
 	struct usb_hcd		hcd;
-	struct ehci_caps	*caps;
-	struct ehci_regs	*regs;
-	u32			hcs_params;	/* cached register copy */
+	struct ehci_caps __iomem *caps;
+	struct ehci_regs __iomem *regs;
+	__u32			hcs_params;	/* cached register copy */
 
 	/* per-HC memory pools (could be per-bus, but ...) */
 	struct dma_pool		*qh_pool;	/* qh per active urb */
@@ -272,9 +273,9 @@ struct ehci_regs {
  */
 struct ehci_qtd {
 	/* first part defined by EHCI spec */
-	u32			hw_next;	  /* see EHCI 3.5.1 */
-	u32			hw_alt_next;      /* see EHCI 3.5.2 */
-	u32			hw_token;         /* see EHCI 3.5.3 */       
+	__le32			hw_next;	  /* see EHCI 3.5.1 */
+	__le32			hw_alt_next;      /* see EHCI 3.5.2 */
+	__le32			hw_token;         /* see EHCI 3.5.3 */       
 #define	QTD_TOGGLE	(1 << 31)	/* data toggle */
 #define	QTD_LENGTH(tok)	(((tok)>>16) & 0x7fff)
 #define	QTD_IOC		(1 << 15)	/* interrupt on complete */
@@ -288,8 +289,8 @@ struct ehci_qtd {
 #define	QTD_STS_MMF	(1 << 2)	/* incomplete split transaction */
 #define	QTD_STS_STS	(1 << 1)	/* split transaction state */
 #define	QTD_STS_PING	(1 << 0)	/* issue PING? */
-	u32			hw_buf [5];        /* see EHCI 3.5.4 */
-	u32			hw_buf_hi [5];        /* Appendix B */
+	__le32			hw_buf [5];        /* see EHCI 3.5.4 */
+	__le32			hw_buf_hi [5];        /* Appendix B */
 
 	/* the rest is HCD-private */
 	dma_addr_t		qtd_dma;		/* qtd address */
@@ -349,18 +350,18 @@ union ehci_shadow {
 
 struct ehci_qh {
 	/* first part defined by EHCI spec */
-	u32			hw_next;	 /* see EHCI 3.6.1 */
-	u32			hw_info1;        /* see EHCI 3.6.2 */
+	__le32			hw_next;	 /* see EHCI 3.6.1 */
+	__le32			hw_info1;        /* see EHCI 3.6.2 */
 #define	QH_HEAD		0x00008000
-	u32			hw_info2;        /* see EHCI 3.6.2 */
-	u32			hw_current;	 /* qtd list - see EHCI 3.6.4 */
+	__le32			hw_info2;        /* see EHCI 3.6.2 */
+	__le32			hw_current;	 /* qtd list - see EHCI 3.6.4 */
 	
 	/* qtd overlay (hardware parts of a struct ehci_qtd) */
-	u32			hw_qtd_next;
-	u32			hw_alt_next;
-	u32			hw_token;
-	u32			hw_buf [5];
-	u32			hw_buf_hi [5];
+	__le32			hw_qtd_next;
+	__le32			hw_alt_next;
+	__le32			hw_token;
+	__le32			hw_buf [5];
+	__le32			hw_buf_hi [5];
 
 	/* the rest is HCD-private */
 	dma_addr_t		qh_dma;		/* address of qh */
@@ -396,7 +397,7 @@ struct ehci_qh {
 struct ehci_iso_packet {
 	/* These will be copied to iTD when scheduling */
 	u64			bufp;		/* itd->hw_bufp{,_hi}[pg] |= */
-	u32			transaction;	/* itd->hw_transaction[i] |= */
+	__le32			transaction;	/* itd->hw_transaction[i] |= */
 	u8			cross;		/* buf crosses pages */
 	/* for full speed OUT splits */
 	u16			buf1;
@@ -418,8 +419,8 @@ struct ehci_iso_sched {
  */
 struct ehci_iso_stream {
 	/* first two fields match QH, but info1 == 0 */
-	u32			hw_next;
-	u32			hw_info1;
+	__le32			hw_next;
+	__le32			hw_info1;
 
 	u32			refcount;
 	u8			bEndpointAddress;
@@ -433,7 +434,7 @@ struct ehci_iso_stream {
 	unsigned long		start;		/* jiffies */
 	unsigned long		rescheduled;
 	int			next_uframe;
-	u32			splits;
+	__le32			splits;
 
 	/* the rest is derived from the endpoint descriptor,
 	 * trusting urb->interval == f(epdesc->bInterval) and
@@ -446,12 +447,12 @@ struct ehci_iso_stream {
 	unsigned		bandwidth;
 
 	/* This is used to initialize iTD's hw_bufp fields */
-	u32			buf0;		
-	u32			buf1;		
-	u32			buf2;
+	__le32			buf0;		
+	__le32			buf1;		
+	__le32			buf2;
 
 	/* this is used to initialize sITD's tt info */
-	u32			address;
+	__le32			address;
 };
 
 /*-------------------------------------------------------------------------*/
@@ -464,8 +465,8 @@ struct ehci_iso_stream {
  */
 struct ehci_itd {
 	/* first part defined by EHCI spec */
-	u32			hw_next;           /* see EHCI 3.3.1 */
-	u32			hw_transaction [8]; /* see EHCI 3.3.2 */
+	__le32			hw_next;           /* see EHCI 3.3.1 */
+	__le32			hw_transaction [8]; /* see EHCI 3.3.2 */
 #define EHCI_ISOC_ACTIVE        (1<<31)        /* activate transfer this slot */
 #define EHCI_ISOC_BUF_ERR       (1<<30)        /* Data buffer error */
 #define EHCI_ISOC_BABBLE        (1<<29)        /* babble detected */
@@ -475,8 +476,8 @@ struct ehci_itd {
 
 #define ITD_ACTIVE	__constant_cpu_to_le32(EHCI_ISOC_ACTIVE)
 
-	u32			hw_bufp [7];	/* see EHCI 3.3.3 */ 
-	u32			hw_bufp_hi [7];	/* Appendix B */
+	__le32			hw_bufp [7];	/* see EHCI 3.3.3 */ 
+	__le32			hw_bufp_hi [7];	/* Appendix B */
 
 	/* the rest is HCD-private */
 	dma_addr_t		itd_dma;	/* for this itd */
@@ -503,11 +504,11 @@ struct ehci_itd {
  */
 struct ehci_sitd {
 	/* first part defined by EHCI spec */
-	u32			hw_next;
+	__le32			hw_next;
 /* uses bit field macros above - see EHCI 0.95 Table 3-8 */
-	u32			hw_fullspeed_ep;	/* EHCI table 3-9 */
-	u32			hw_uframe;		/* EHCI table 3-10 */
-	u32			hw_results;		/* EHCI table 3-11 */
+	__le32			hw_fullspeed_ep;	/* EHCI table 3-9 */
+	__le32			hw_uframe;		/* EHCI table 3-10 */
+	__le32			hw_results;		/* EHCI table 3-11 */
 #define	SITD_IOC	(1 << 31)	/* interrupt on completion */
 #define	SITD_PAGE	(1 << 30)	/* buffer 0/1 */
 #define	SITD_LENGTH(x)	(0x3ff & ((x)>>16))
@@ -521,9 +522,9 @@ struct ehci_sitd {
 
 #define SITD_ACTIVE	__constant_cpu_to_le32(SITD_STS_ACTIVE)
 
-	u32			hw_buf [2];		/* EHCI table 3-12 */
-	u32			hw_backpointer;		/* EHCI table 3-13 */
-	u32			hw_buf_hi [2];		/* Appendix B */
+	__le32			hw_buf [2];		/* EHCI table 3-12 */
+	__le32			hw_backpointer;		/* EHCI table 3-13 */
+	__le32			hw_buf_hi [2];		/* Appendix B */
 
 	/* the rest is HCD-private */
 	dma_addr_t		sitd_dma;
@@ -548,8 +549,8 @@ struct ehci_sitd {
  * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work.
  */
 struct ehci_fstn {
-	u32			hw_next;	/* any periodic q entry */
-	u32			hw_prev;	/* qh or EHCI_LIST_END */
+	__le32			hw_next;	/* any periodic q entry */
+	__le32			hw_prev;	/* qh or EHCI_LIST_END */
 
 	/* the rest is HCD-private */
 	dma_addr_t		fstn_dma;
diff --git a/drivers/usb/host/hc_simple.c b/drivers/usb/host/hc_simple.c
index 8a464917e..ade67124a 100644
--- a/drivers/usb/host/hc_simple.c
+++ b/drivers/usb/host/hc_simple.c
@@ -146,11 +146,6 @@ static int hci_submit_urb (struct urb * urb, int mem_flags)
 	if (!urb->dev || !urb->dev->bus || urb->hcpriv)
 		return -EINVAL;
 
-	if (usb_endpoint_halted
-	    (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) {
-		printk ("hci_submit_urb: endpoint_halted\n");
-		return -EPIPE;
-	}
 	hci = (hci_t *) urb->dev->bus->hcpriv;
 
 	/* a request to the virtual root hub */
diff --git a/drivers/usb/host/hc_sl811.c b/drivers/usb/host/hc_sl811.c
index 5bda71207..b57f1fe82 100644
--- a/drivers/usb/host/hc_sl811.c
+++ b/drivers/usb/host/hc_sl811.c
@@ -106,14 +106,14 @@ int SL11StartXaction (hci_t * hci, __u8 addr, __u8 epaddr, int pid, int len,
 
 static int sofWaitCnt = 0;
 
-MODULE_PARM (urb_debug, "i");
+module_param(urb_debug, int, 0);
 MODULE_PARM_DESC (urb_debug, "debug urb messages, default is 0 (no)");
 
-MODULE_PARM (base_addr, "i");
+module_param(base_addr, int, 0);
 MODULE_PARM_DESC (base_addr, "sl811 base address 0xd3800000");
-MODULE_PARM (data_reg_addr, "i");
+module_param(data_reg_addr, int, 0);
 MODULE_PARM_DESC (data_reg_addr, "sl811 data register address 0xd3810000");
-MODULE_PARM (irq, "i");
+module_param(irq, int, 0);
 MODULE_PARM_DESC (irq, "IRQ 34 (default)");
 
 static int hc_reset (hci_t * hci);
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 54daaacdc..947bf4a5e 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -131,7 +131,7 @@ static char *hcfs2string (int state)
 static void
 ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
 {
-	struct ohci_regs	*regs = controller->regs;
+	struct ohci_regs __iomem *regs = controller->regs;
 	u32			temp;
 
 	temp = ohci_readl (&regs->revision) & 0xff;
@@ -336,7 +336,7 @@ static void __attribute__((unused))
 ohci_dump_ed (const struct ohci_hcd *ohci, const char *label,
 		const struct ed *ed, int verbose)
 {
-	u32	tmp = ed->hwINFO;
+	__le32	tmp = ed->hwINFO;
 	char	*type = "";
 
 	ohci_dbg (ohci, "%s, ed %p state 0x%x type %s; next ed %08x\n",
@@ -359,7 +359,7 @@ ohci_dump_ed (const struct ohci_hcd *ohci, const char *label,
 		type,
 		0x007f & le32_to_cpu (tmp));
 	ohci_dbg (ohci, "  tds: head %08x %s%s tail %08x%s\n",
-		tmp = le32_to_cpup (&ed->hwHeadP),
+		le32_to_cpup (&ed->hwHeadP),
 		(ed->hwHeadP & ED_C) ? data1 : data0,
 		(ed->hwHeadP & ED_H) ? " HALT" : "",
 		le32_to_cpup (&ed->hwTailP),
@@ -415,8 +415,8 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed)
 
 	/* dump a snapshot of the bulk or control schedule */
 	while (ed) {
-		u32			info = ed->hwINFO;
-		u32			scratch = cpu_to_le32p (&ed->hwINFO);
+		__le32			info = ed->hwINFO;
+		u32			scratch = le32_to_cpup (&ed->hwINFO);
 		struct list_head	*entry;
 		struct td		*td;
 
@@ -439,7 +439,7 @@ show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed)
 			u32		cbp, be;
 
 			td = list_entry (entry, struct td, td_list);
-			scratch = cpu_to_le32p (&td->hwINFO);
+			scratch = le32_to_cpup (&td->hwINFO);
 			cbp = le32_to_cpup (&td->hwCBP);
 			be = le32_to_cpup (&td->hwBE);
 			temp = scnprintf (buf, size,
@@ -541,8 +541,8 @@ show_periodic (struct class_device *class_dev, char *buf)
 
 			/* show more info the first time around */
 			if (temp == seen_count) {
-				u32	info = ed->hwINFO;
-				u32	scratch = cpu_to_le32p (&ed->hwINFO);
+				__le32	info = ed->hwINFO;
+				u32	scratch = le32_to_cpup (&ed->hwINFO);
 				struct list_head	*entry;
 				unsigned		qlen = 0;
 
@@ -599,7 +599,7 @@ show_registers (struct class_device *class_dev, char *buf)
 	struct usb_bus		*bus;
 	struct usb_hcd		*hcd;
 	struct ohci_hcd		*ohci;
-	struct ohci_regs	*regs;
+	struct ohci_regs __iomem *regs;
 	unsigned long		flags;
 	unsigned		temp, size;
 	char			*next;
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index d13e98e35..0609e12ef 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -97,6 +97,7 @@
 #include <linux/list.h>
 #include <linux/interrupt.h>  /* for in_interrupt () */
 #include <linux/usb.h>
+#include <linux/usb_otg.h>
 #include "../core/hcd.h"
 #include <linux/dma-mapping.h> 
 #include <linux/dmapool.h>    /* needed by ohci-mem.c when no PCI */
@@ -593,7 +594,7 @@ static int hc_start (struct ohci_hcd *ohci)
 static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
 {
 	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
-	struct ohci_regs	*regs = ohci->regs;
+	struct ohci_regs __iomem *regs = ohci->regs;
  	int			ints; 
 
 	/* we can eliminate a (slow) ohci_readl()
@@ -693,7 +694,7 @@ static void ohci_stop (struct usb_hcd *hcd)
 
 /* must not be called from interrupt context */
 
-#ifdef CONFIG_PM
+#if	defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
 
 static void mark_children_gone (struct usb_device *dev)
 {
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index f6263bf9b..424971c4b 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -435,6 +435,89 @@ ohci_hub_descriptor (
 
 /*-------------------------------------------------------------------------*/
 
+#ifdef	CONFIG_USB_OTG
+
+static int ohci_start_port_reset (struct usb_hcd *hcd, unsigned port)
+{
+	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
+	u32			status;
+
+	if (!port)
+		return -EINVAL;
+	port--;
+
+	/* start port reset before HNP protocol times out */
+	status = ohci_readl(&ohci->regs->roothub.portstatus [port]);
+	if (!(status & RH_PS_CCS))
+		return -ENODEV;
+
+	/* khubd will finish the reset later */
+	writel(RH_PS_PRS, &ohci->regs->roothub.portstatus [port]);
+	return 0;
+}
+
+static void start_hnp(struct ohci_hcd *ohci);
+
+#else
+
+#define	ohci_start_port_reset		NULL
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+
+/* See usb 7.1.7.5:  root hubs must issue at least 50 msec reset signaling,
+ * not necessarily continuous ... to guard against resume signaling.
+ * The short timeout is safe for non-root hubs, and is backward-compatible
+ * with earlier Linux hosts.
+ */
+#ifdef	CONFIG_USB_SUSPEND
+#define	PORT_RESET_MSEC		50
+#else
+#define	PORT_RESET_MSEC		10
+#endif
+
+/* this timer value might be vendor-specific ... */
+#define	PORT_RESET_HW_MSEC	10
+
+/* wrap-aware logic stolen from <linux/jiffies.h> */
+#define tick_before(t1,t2) ((((s16)(t1))-((s16)(t2))) < 0)
+
+/* called from some task, normally khubd */
+static inline void root_port_reset (struct ohci_hcd *ohci, unsigned port)
+{
+	u32 __iomem *portstat = &ohci->regs->roothub.portstatus [port];
+	u32	temp;
+	u16	now = readl(&ohci->regs->fmnumber);
+	u16	reset_done = now + PORT_RESET_MSEC;
+
+	/* build a "continuous enough" reset signal, with up to
+	 * 3msec gap between pulses.  scheduler HZ==100 must work;
+	 * this might need to be deadline-scheduled.
+	 */
+	do {
+		/* spin until any current reset finishes */
+		for (;;) {
+			temp = ohci_readl (portstat);
+			if (!(temp & RH_PS_PRS))
+				break;
+			udelay (500);
+		} 
+
+		if (!(temp & RH_PS_CCS))
+			break;
+		if (temp & RH_PS_PRSC)
+			writel (RH_PS_PRSC, portstat);
+
+		/* start the next reset, sleep till it's probably done */
+		writel (RH_PS_PRS, portstat);
+		msleep(PORT_RESET_HW_MSEC);
+		now = readl(&ohci->regs->fmnumber);
+	} while (tick_before(now, reset_done));
+	/* caller synchronizes using PRSC */
+}
+
 static int ohci_hub_control (
 	struct usb_hcd	*hcd,
 	u16		typeReq,
@@ -503,14 +586,14 @@ static int ohci_hub_control (
 		break;
 	case GetHubStatus:
 		temp = roothub_status (ohci) & ~(RH_HS_CRWE | RH_HS_DRWE);
-		*(u32 *) buf = cpu_to_le32 (temp);
+		*(__le32 *) buf = cpu_to_le32 (temp);
 		break;
 	case GetPortStatus:
 		if (!wIndex || wIndex > ports)
 			goto error;
 		wIndex--;
 		temp = roothub_portstatus (ohci, wIndex);
-		*(u32 *) buf = cpu_to_le32 (temp);
+		*(__le32 *) buf = cpu_to_le32 (temp);
 
 #ifndef	OHCI_VERBOSE_DEBUG
 	if (*(u16*)(buf+2))	/* only if wPortChange is interesting */
@@ -533,6 +616,12 @@ static int ohci_hub_control (
 		wIndex--;
 		switch (wValue) {
 		case USB_PORT_FEAT_SUSPEND:
+#ifdef	CONFIG_USB_OTG
+			if (ohci->hcd.self.otg_port == (wIndex + 1)
+					&& ohci->hcd.self.b_hnp_enable)
+				start_hnp(ohci);
+			else
+#endif
 			writel (RH_PS_PSS,
 				&ohci->regs->roothub.portstatus [wIndex]);
 			break;
@@ -541,10 +630,7 @@ static int ohci_hub_control (
 				&ohci->regs->roothub.portstatus [wIndex]);
 			break;
 		case USB_PORT_FEAT_RESET:
-			temp = ohci_readl (&ohci->regs->roothub.portstatus [wIndex]);
-			if (temp & RH_PS_CCS)
-				writel (RH_PS_PRS,
-				    &ohci->regs->roothub.portstatus [wIndex]);
+			root_port_reset (ohci, wIndex);
 			break;
 		default:
 			goto error;
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 1e5fc5d93..d133ff22a 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -2,27 +2,30 @@
  * OHCI HCD (Host Controller Driver) for USB.
  *
  * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
+ * (C) Copyright 2000-2004 David Brownell <dbrownell@users.sourceforge.net>
  * (C) Copyright 2002 Hewlett-Packard Company
  * 
  * OMAP Bus Glue
  *
  * Written by Christopher Hoover <ch@hpl.hp.com>
- * Based on fragments of previous driver by Rusell King et al.
+ * Based on fragments of previous driver by Russell King et al.
  *
  * Modified for OMAP from ohci-sa1111.c by Tony Lindgren <tony@atomide.com>
  * Based on the 2.4 OMAP OHCI driver originally done by MontaVista Software Inc.
  *
  * This file is licenced under the GPL.
  */
- 
+
 #include <asm/hardware.h>
 #include <asm/io.h>
+#include <asm/mach-types.h>
 
-#include <asm/arch/bus.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/irqs.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/fpga.h>
+#include <asm/arch/usb.h>
 
 #include "ohci-omap.h"
 
@@ -33,123 +36,54 @@
 extern int usb_disabled(void);
 extern int ocpi_enable(void);
 
-/*
- * Use the first port only by default. Override with hmc_mode option.
- *
- * NOTE: Many OMAP-1510 Innovators supposedly have bad wiring for the USB ports
- *       1 & 2, so only port 0 will work. To use the OHCI on the first port, use 
- *       the Innovator USB client cable with a client-to-client connector and modify
- *       either the cable or the hub to feed 5V VBUS back to Innovator. VBUS should
- *       be the red lead in the cable.
- *
- *       To mount USB hard disk as root, see the patch for do_mounts.c that tries 
- *       remounting the root, and use root=0801 if your root is on sda1. Does not 
- *       work with devfs.
- */
-static int default_hmc_mode = 16;
-static int hmc_mode = 1234;
-
-/*
- * Set the USB host pin multiplexing and the selected HMC mode
- */
-static int omap_usb_set_hmc_mode(int hmc_mode)
-{
-	unsigned int val;
-
-	switch (hmc_mode) {
-	case 0:
-		/* 0: function, 1: disabled, 2: disabled */
-		omap_cfg_reg(W4_USB_PUEN);
-		omap_cfg_reg(R18_1510_USB_GPIO0);
-		break;
-	case 4:
-		/* 0: function 1: host 2: host */
-		omap_cfg_reg(usb1_speed);
-		omap_cfg_reg(usb1_susp);
-		omap_cfg_reg(usb1_seo);
-		omap_cfg_reg(usb1_txen);
-		omap_cfg_reg(usb1_txd);
-		omap_cfg_reg(usb1_vp);
-		omap_cfg_reg(usb1_vm);
-		omap_cfg_reg(usb1_rcv);
-		omap_cfg_reg(usb2_susp);
-		omap_cfg_reg(usb2_seo);
-		omap_cfg_reg(usb2_txen);
-		omap_cfg_reg(usb2_txd);
-		omap_cfg_reg(usb2_vp);
-		omap_cfg_reg(usb2_vm);
-		omap_cfg_reg(usb2_rcv);
-		break;
-	case 16:
-		/* 0: host, 1: disabled, 2: disabled */
-		omap_cfg_reg(W9_USB0_TXEN);
-		omap_cfg_reg(AA9_USB0_VP);
-		omap_cfg_reg(Y5_USB0_RCV);
-		omap_cfg_reg(R9_USB0_VM);
-		omap_cfg_reg(V6_USB0_TXD);
-		omap_cfg_reg(W5_USB0_SE0);
-		break;
-	default:
-		printk("Unknown USB host configuration: %i\n", hmc_mode);
-		return -ENODEV;
-	}
-
-	/* Write the selected HMC mode */
-	val = readl(MOD_CONF_CTRL_0) & ~HMC_CLEAR;
-	val |= (hmc_mode << 1);
-	writel(val, MOD_CONF_CTRL_0);
-
-	return 0;
-}
-
 /*
  * OHCI clock initialization for OMAP-1510 and 1610
  */
 static int omap_ohci_clock_power(int on)
 {
 	if (on) {
-		if (cpu_is_omap_1510()) {
+		if (cpu_is_omap1510()) {
 			/* Use DPLL, not APLL */
-			writel(readl(ULPD_APLL_CTRL_REG) & ~APLL_NDPLL_SWITCH,
-			       ULPD_APLL_CTRL_REG);
+			omap_writel(omap_readl(ULPD_APLL_CTRL) & ~APLL_NDPLL_SWITCH,
+			       ULPD_APLL_CTRL);
 
 			/* Enable DPLL */
-			writel(readl(ULPD_DPLL_CTRL_REG) | DPLL_PLL_ENABLE,
-			       ULPD_DPLL_CTRL_REG);
+			omap_writel(omap_readl(ULPD_DPLL_CTRL) | DPLL_PLL_ENABLE,
+			       ULPD_DPLL_CTRL);
 
 			/* Software request for USB 48MHz clock */
-			writel(readl(ULPD_SOFT_REQ_REG) | SOFT_REQ_REG_REQ,
-			       ULPD_SOFT_REQ_REG);
+			omap_writel(omap_readl(ULPD_SOFT_REQ) | SOFT_REQ_REG_REQ,
+			       ULPD_SOFT_REQ);
 
-			while (!(readl(ULPD_DPLL_CTRL_REG) & DPLL_LOCK));
+			while (!(omap_readl(ULPD_DPLL_CTRL) & DPLL_LOCK));
 		}
 
-		if (cpu_is_omap_1610()) {
+		if (cpu_is_omap16xx()) {
 			/* Enable OHCI */
-			writel(readl(ULPD_SOFT_REQ_REG) | SOFT_USB_OTG_REQ,
-				ULPD_SOFT_REQ_REG);
+			omap_writel(omap_readl(ULPD_SOFT_REQ) | SOFT_USB_OTG_REQ,
+				ULPD_SOFT_REQ);
 
 			/* USB host clock request if not using OTG */
-			writel(readl(ULPD_SOFT_REQ_REG) | SOFT_USB_REQ,
-				ULPD_SOFT_REQ_REG);
+			omap_writel(omap_readl(ULPD_SOFT_REQ) | SOFT_USB_REQ,
+				ULPD_SOFT_REQ);
 
-			writel(readl(ULPD_STATUS_REQ_REG) | USB_HOST_DPLL_REQ,
-			     ULPD_STATUS_REQ_REG);
+			omap_writel(omap_readl(ULPD_STATUS_REQ) | USB_HOST_DPLL_REQ,
+			     ULPD_STATUS_REQ);
 		}
 
 		/* Enable 48MHz clock to USB */
-		writel(readl(ULPD_CLOCK_CTRL_REG) | USB_MCLK_EN,
-		       ULPD_CLOCK_CTRL_REG);
+		omap_writel(omap_readl(ULPD_CLOCK_CTRL) | USB_MCLK_EN,
+		       ULPD_CLOCK_CTRL);
 
-		writel(readl(ARM_IDLECT2) | (1 << EN_LBFREECK) | (1 << EN_LBCK),
+		omap_writel(omap_readl(ARM_IDLECT2) | (1 << EN_LBFREECK) | (1 << EN_LBCK),
 		       ARM_IDLECT2);
 
-		writel(readl(MOD_CONF_CTRL_0) | USB_HOST_HHC_UHOST_EN,
+		omap_writel(omap_readl(MOD_CONF_CTRL_0) | USB_HOST_HHC_UHOST_EN,
 		       MOD_CONF_CTRL_0);
 	} else {
 		/* Disable 48MHz clock to USB */
-		writel(readl(ULPD_CLOCK_CTRL_REG) & ~USB_MCLK_EN,
-		       ULPD_CLOCK_CTRL_REG);
+		omap_writel(omap_readl(ULPD_CLOCK_CTRL) & ~USB_MCLK_EN,
+		       ULPD_CLOCK_CTRL);
 
 		/* FIXME: The DPLL stays on for now */
 	}
@@ -163,13 +97,19 @@ static int omap_ohci_clock_power(int on)
 static int omap_ohci_transceiver_power(int on)
 {
 	if (on) {
-		if (omap_is_innovator())
-			writel(readl(OMAP1510_FPGA_HOST_CTRL) | 0x20, 
-			       OMAP1510_FPGA_HOST_CTRL);
+		if (machine_is_omap_innovator() && cpu_is_omap1510())
+			fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL) | 0x20, 
+			       INNOVATOR_FPGA_CAM_USB_CONTROL);
+		else if (machine_is_omap_osk()) {
+			/* FIXME: GPIO1 -> 1 on the TPS65010 I2C chip */
+		}
 	} else {
-		if (omap_is_innovator())
-			writel(readl(OMAP1510_FPGA_HOST_CTRL) & ~0x20, 
-			       OMAP1510_FPGA_HOST_CTRL);
+		if (machine_is_omap_innovator() && cpu_is_omap1510())
+			fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL) & ~0x20, 
+			       INNOVATOR_FPGA_CAM_USB_CONTROL);
+		else if (machine_is_omap_osk()) {
+			/* FIXME: GPIO1 -> 0 on the TPS65010 I2C chip */
+		}
 	}
 
 	return 0;
@@ -181,10 +121,10 @@ static int omap_ohci_transceiver_power(int on)
 static int omap_1510_local_bus_power(int on)
 {
 	if (on) {
-		writel((1 << 1) | (1 << 0), OMAP1510_LB_MMU_CTL);
+		omap_writel((1 << 1) | (1 << 0), OMAP1510_LB_MMU_CTL);
 		udelay(200);
 	} else {
-		writel(0, OMAP1510_LB_MMU_CTL);
+		omap_writel(0, OMAP1510_LB_MMU_CTL);
 	}
 
 	return 0;
@@ -193,8 +133,8 @@ static int omap_1510_local_bus_power(int on)
 /*
  * OMAP-1510 specific Local Bus initialization
  * NOTE: This assumes 32MB memory size in OMAP1510LB_MEMSIZE.
- *       See also arch/mach-omap/memory.h for __virt_to_bus() and 
- *       __bus_to_virt() which need to match with the physical 
+ *       See also arch/mach-omap/memory.h for __virt_to_dma() and 
+ *       __dma_to_virt() which need to match with the physical 
  *       Local Bus address below.
  */
 static int omap_1510_local_bus_init(void)
@@ -202,125 +142,115 @@ static int omap_1510_local_bus_init(void)
 	unsigned int tlb;
 	unsigned long lbaddr, physaddr;
 
-	writel((readl(OMAP1510_LB_CLOCK_DIV) & 0xfffffff8) | 0x4, 
+	omap_writel((omap_readl(OMAP1510_LB_CLOCK_DIV) & 0xfffffff8) | 0x4, 
 	       OMAP1510_LB_CLOCK_DIV);
 
 	/* Configure the Local Bus MMU table */
 	for (tlb = 0; tlb < OMAP1510_LB_MEMSIZE; tlb++) {
 		lbaddr = tlb * 0x00100000 + OMAP1510_LB_OFFSET;
 		physaddr = tlb * 0x00100000 + PHYS_OFFSET;
-		writel((lbaddr & 0x0fffffff) >> 22, OMAP1510_LB_MMU_CAM_H);
-		writel(((lbaddr & 0x003ffc00) >> 6) | 0xc, 
+		omap_writel((lbaddr & 0x0fffffff) >> 22, OMAP1510_LB_MMU_CAM_H);
+		omap_writel(((lbaddr & 0x003ffc00) >> 6) | 0xc, 
 		       OMAP1510_LB_MMU_CAM_L);
-		writel(physaddr >> 16, OMAP1510_LB_MMU_RAM_H);
-		writel((physaddr & 0x0000fc00) | 0x300, OMAP1510_LB_MMU_RAM_L);
-		writel(tlb << 4, OMAP1510_LB_MMU_LCK);
-		writel(0x1, OMAP1510_LB_MMU_LD_TLB);
+		omap_writel(physaddr >> 16, OMAP1510_LB_MMU_RAM_H);
+		omap_writel((physaddr & 0x0000fc00) | 0x300, OMAP1510_LB_MMU_RAM_L);
+		omap_writel(tlb << 4, OMAP1510_LB_MMU_LCK);
+		omap_writel(0x1, OMAP1510_LB_MMU_LD_TLB);
 	}
 
 	/* Enable the walking table */
-	writel(readl(OMAP1510_LB_MMU_CTL) | (1 << 3), OMAP1510_LB_MMU_CTL);
+	omap_writel(omap_readl(OMAP1510_LB_MMU_CTL) | (1 << 3), OMAP1510_LB_MMU_CTL);
 	udelay(200);
 
 	return 0;
 }
 
-/*
- * OMAP-1610 specific hardware initialization
- *
- * Intended to configure OMAP-1610 USB host and OTG ports depending on 
- * the HMC mode selected.
- *
- * FIXME: Currently only supports alternate ping group 2 mode, should
- *        be easy to modify for other configurations once there is some
- *        hardware to test with.
- */
-static int omap_1610_usb_init(int mode)
-{
-	u_int val = 0;
-
-	/* Configure the OMAP transceiver settings */
-	val |= (1 << 8); /* CONF_USB2_UNI TRM p 15-205*/
-	val |= (4 << 4); /* TRM p 5-59, p 15-157 (1224) */
+#ifdef	CONFIG_USB_OTG
 
-	//val |= (1 << 3); /* Isolate integrated transceiver from port 0 */
-	val |= (1 << 2); /* Disable pulldown on integrated transceiver DM */
-	val |= (1 << 1); /* Disable pulldown on integraded transceiver DP */
+static void start_hnp(struct ohci_hcd *ohci)
+{
+	const unsigned	port = ohci->hcd.self.otg_port - 1;
+	unsigned long	flags;
 
-	writel(val, USB_TRANSCEIVER_CTRL);
+	otg_start_hnp(ohci->transceiver);
 
-	/* Set the USB0_TRX_MODE */
-	val = 0;
-	val &= ~OTG_IDLE_EN;
-	val &= ~DEV_IDLE_EN;
-	val &= ~(7 << 16);	/* Clear USB0_TRX_MODE */
-	val |= (3 << 16);	/* 0 or 3, 6-wire DAT/SE0, TRM p 15-159 */
-	writel(val, OTG_SYSCON_1);
+	local_irq_save(flags);
+	ohci->transceiver->state = OTG_STATE_A_SUSPEND;
+	writel (RH_PS_PSS, &ohci->regs->roothub.portstatus [port]);
+	OTG_CTRL_REG &= ~OTG_A_BUSREQ;
+	local_irq_restore(flags);
+}
 
-	/* 
-	 * Control via OTG, see TRM p 15-163
-	 */
-	val = 0;
-	//val |= 1;		/* REVISIT: Enable OTG = 1 */
+#endif
 
-	/* Control via OTG */
-	val &= ~HMC_PADEN;
-	val &= ~OTG_PADEN;
-	val |= UHOST_EN;	
+/*-------------------------------------------------------------------------*/
 
-	val &= ~0x3f;		/* Clear HMC mode */
-	val |= mode;		/* Set HMC mode */
-	val &= ~(7 << 16);	/* Clear ASE0_BRST */
-	val |= (4 << 16);	/* Must be 4 */
-	val |= USBX_SYNCHRO;	/* Must be set */
-	val |= SRP_VBUS;
-	writel(val, OTG_SYSCON_2);
+static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
+{
+	struct omap_usb_config	*config = pdev->dev.platform_data;
+	int			need_transceiver = (config->otg != 0);
 
-	/* Enable OTG idle */
-	//writel(readl(OTG_SYSCON_1) | OTG_IDLE_EN, OTG_SYSCON_1);
+	dev_dbg(&pdev->dev, "starting USB Controller\n");
 
-	return 0;
-}
+	if (config->otg) {
+		ohci->hcd.self.otg_port = config->otg;
+		/* default/minimum OTG power budget:  8 mA */
+		ohci->power_budget = 8;
+	}
 
-/*-------------------------------------------------------------------------*/
+	/* boards can use OTG transceivers in non-OTG modes */
+	need_transceiver = need_transceiver
+			|| machine_is_omap_h2();
 
-static void omap_start_hc(struct omap_dev *dev)
-{
-	printk(KERN_DEBUG __FILE__ 
-	       ": starting OMAP OHCI USB Controller\n");
+	if (cpu_is_omap16xx())
+		ocpi_enable();
 
-	/* 
-	 * Set the HMC mode for the USB ports
-	 */
-#if 0
-	/* See note about the Innovator wiring above */
-	if (omap_is_innovator())
-		hmc_mode = 4;	/* 0: function 1: host 2: host */
+#ifdef	CONFIG_ARCH_OMAP_OTG
+	if (need_transceiver) {
+		ohci->transceiver = otg_get_transceiver();
+		if (ohci->transceiver) {
+			int	status = otg_set_host(ohci->transceiver,
+						&ohci->hcd.self);
+			dev_dbg(&pdev->dev, "init %s transceiver, status %d\n",
+					ohci->transceiver->label, status);
+			if (status) {
+				if (ohci->transceiver)
+					put_device(ohci->transceiver->dev);
+				return status;
+			}
+		} else {
+			dev_err(&pdev->dev, "can't find transceiver\n");
+			return -ENODEV;
+		}
+	}
 #endif
 
-	if (cpu_is_omap_1610())
-		ocpi_enable();
-
-	omap_usb_set_hmc_mode(hmc_mode);
+	if (machine_is_omap_osk()) {
+		omap_request_gpio(9);
+		omap_set_gpio_direction(9, 1);
+		omap_set_gpio_dataout(9, 1);
+	}
 
 	omap_ohci_clock_power(1);
+
 	omap_ohci_transceiver_power(1);
 
-	if (cpu_is_omap_1510()) {
+	if (cpu_is_omap1510()) {
 		omap_1510_local_bus_power(1);
 		omap_1510_local_bus_init();
 	}
 
-	if (cpu_is_omap_1610())
-		omap_1610_usb_init(hmc_mode);
+	/* board init will have already handled HMC and mux setup.
+	 * any external transceiver should already be initialized
+	 * too, so all configured ports use the right signaling now.
+	 */
 
-	//omap_enable_device(dev);
+	return 0;
 }
 
-static void omap_stop_hc(struct omap_dev *dev)
+static void omap_stop_hc(struct platform_device *pdev)
 {
-	printk(KERN_DEBUG __FILE__ 
-	       ": stopping OMAP OHCI USB Controller\n");
+	dev_dbg(&pdev->dev, "stopping USB Controller\n");
 
 	/*
 	 * FIXME: Put the USB host controller into reset.
@@ -336,16 +266,7 @@ static void omap_stop_hc(struct omap_dev *dev)
 
 /*-------------------------------------------------------------------------*/
 
-static irqreturn_t usb_hcd_omap_hcim_irq (int irq, void *__hcd, struct pt_regs * r)
-{
-	struct usb_hcd *hcd = __hcd;
-
-	return usb_hcd_irq(irq, hcd, r);
-}
-
-/*-------------------------------------------------------------------------*/
-
-void usb_hcd_omap_remove (struct usb_hcd *, struct omap_dev *);
+void usb_hcd_omap_remove (struct usb_hcd *, struct platform_device *);
 
 /* configure so an HC device and id are always provided */
 /* always called with process context; sleeping is OK */
@@ -358,59 +279,71 @@ void usb_hcd_omap_remove (struct usb_hcd *, struct omap_dev *);
  * Allocates basic resources for this USB host controller, and
  * then invokes the start() method for the HCD associated with it
  * through the hotplug entry's driver_data.
- *
- * Store this function in the HCD's struct pci_driver as probe().
  */
 int usb_hcd_omap_probe (const struct hc_driver *driver,
-			  struct usb_hcd **hcd_out,
-			  struct omap_dev *dev)
+			  struct platform_device *pdev)
 {
 	int retval;
 	struct usb_hcd *hcd = 0;
+	struct ohci_hcd *ohci;
 
-	if (!request_mem_region(dev->res.start, 
-				dev->res.end - dev->res.start + 1, hcd_name)) {
-		dbg("request_mem_region failed");
-		return -EBUSY;
+	if (pdev->num_resources != 2) {
+		printk(KERN_ERR "hcd probe: invalid num_resources: %i\n", 
+		       pdev->num_resources);
+		return -ENODEV;
 	}
 
-	omap_start_hc(dev);
+	if (pdev->resource[0].flags != IORESOURCE_MEM 
+	    || pdev->resource[1].flags != IORESOURCE_IRQ) {
+		printk(KERN_ERR "hcd probe: invalid resource type\n");
+		return -ENODEV;
+	}
+
+	if (!request_mem_region(pdev->resource[0].start, 
+				pdev->resource[0].end - pdev->resource[0].start + 1, hcd_name)) {
+		dev_dbg(&pdev->dev, "request_mem_region failed\n");
+		return -EBUSY;
+	}
 
 	hcd = driver->hcd_alloc ();
 	if (hcd == NULL){
-		dbg ("hcd_alloc failed");
+		dev_dbg(&pdev->dev, "hcd_alloc failed\n");
 		retval = -ENOMEM;
 		goto err1;
 	}
+	dev_set_drvdata(&pdev->dev, hcd);
+	ohci = hcd_to_ohci(hcd);
 
 	hcd->driver = (struct hc_driver *) driver;
 	hcd->description = driver->description;
-	hcd->irq = dev->irq[0];
-	hcd->regs = dev->mapbase;
-	hcd->self.controller = &dev->dev;
+	hcd->irq = pdev->resource[1].start;
+	hcd->regs = (void *)pdev->resource[0].start;
+	hcd->self.controller = &pdev->dev;
+
+	retval = omap_start_hc(ohci, pdev);
+	if (retval < 0)
+		goto err2;
 
 	retval = hcd_buffer_create (hcd);
 	if (retval != 0) {
-		dbg ("pool alloc fail");
+		dev_dbg(&pdev->dev, "pool alloc fail\n");
 		goto err1;
 	}
 
-	retval = request_irq (hcd->irq, 
-			      usb_hcd_omap_hcim_irq, 
+	retval = request_irq (hcd->irq, usb_hcd_irq, 
 			      SA_INTERRUPT, hcd->description, hcd);
 	if (retval != 0) {
-		dbg("request_irq failed");
+		dev_dbg(&pdev->dev, "request_irq failed\n");
 		retval = -EBUSY;
 		goto err2;
 	}
 
-	info ("%s (OMAP) at 0x%p, irq %d\n",
-	      hcd->description, hcd->regs, hcd->irq);
+	dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq);
 
 	usb_bus_init (&hcd->self);
 	hcd->self.op = &usb_hcd_operations;
 	hcd->self.hcpriv = (void *) hcd;
-	hcd->self.bus_name = "omap";
+	hcd->self.bus_name = pdev->dev.bus_id;
 	hcd->product_desc = "OMAP OHCI";
 
 	INIT_LIST_HEAD (&hcd->dev_list);
@@ -418,11 +351,10 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
 
 	if ((retval = driver->start (hcd)) < 0) 
 	{
-		usb_hcd_omap_remove(hcd, dev);
+		usb_hcd_omap_remove(hcd, pdev);
 		return retval;
 	}
 
-	*hcd_out = hcd;
 	return 0;
 
  err2:
@@ -430,10 +362,12 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
 	if (hcd)
 		driver->hcd_free(hcd);
  err1:
-	omap_stop_hc(dev);
+	omap_stop_hc(pdev);
 
-	release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1);
+	release_mem_region(pdev->resource[0].start, 
+			   pdev->resource[0].end - pdev->resource[0].start + 1);
 
+	dev_set_drvdata(&pdev->dev, 0);
 	return retval;
 }
 
@@ -451,24 +385,27 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
  * context, normally "rmmod", "apmd", or something similar.
  *
  */
-void usb_hcd_omap_remove (struct usb_hcd *hcd, struct omap_dev *dev)
+void usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
 {
 	void *base;
 
-	info ("remove: %s, state %x", hcd->self.bus_name, hcd->state);
+	dev_info(&pdev->dev, "remove: state %x\n", hcd->state);
 
 	if (in_interrupt ())
 		BUG ();
 
 	hcd->state = USB_STATE_QUIESCING;
 
-	dbg ("%s: roothub graceful disconnect", hcd->self.bus_name);
+	dev_dbg(&pdev->dev, "roothub graceful disconnect\n");
 	usb_disconnect (&hcd->self.root_hub);
 
 	hcd->driver->stop (hcd);
 	hcd_buffer_destroy (hcd);
 	hcd->state = USB_STATE_HALT;
 
+	if (machine_is_omap_osk())
+		omap_free_gpio(9);
+
 	free_irq (hcd->irq, hcd);
 
 	usb_deregister_bus (&hcd->self);
@@ -476,9 +413,10 @@ void usb_hcd_omap_remove (struct usb_hcd *hcd, struct omap_dev *dev)
 	base = hcd->regs;
 	hcd->driver->hcd_free (hcd);
 
-	omap_stop_hc(dev);
+	omap_stop_hc(pdev);
 
-	release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1);
+	release_mem_region(pdev->resource[0].start, 
+			   pdev->resource[0].end - pdev->resource[0].start + 1);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -486,11 +424,13 @@ void usb_hcd_omap_remove (struct usb_hcd *hcd, struct omap_dev *dev)
 static int __devinit
 ohci_omap_start (struct usb_hcd *hcd)
 {
+	struct omap_usb_config *config;
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
 	int		ret;
 
-	ohci->hcca = dma_alloc_consistent (hcd->self.controller,
-			sizeof *ohci->hcca, &ohci->hcca_dma);
+	config = hcd->self.controller->platform_data;
+	ohci->hcca = dma_alloc_coherent (hcd->self.controller,
+			sizeof *ohci->hcca, &ohci->hcca_dma, 0);
 	if (!ohci->hcca)
 		return -ENOMEM;
 
@@ -500,6 +440,10 @@ ohci_omap_start (struct usb_hcd *hcd)
 		return ret;
 	}
 	ohci->regs = hcd->regs;
+
+	if (config->otg || config->rwc)
+		writel(OHCI_CTRL_RWC, &ohci->regs->control);
+
 	if (hc_reset (ohci) < 0) {
 		ohci_stop (hcd);
 		return -ENODEV;
@@ -510,6 +454,9 @@ ohci_omap_start (struct usb_hcd *hcd)
 		ohci_stop (hcd);
 		return -EBUSY;
 	}
+	if (ohci->power_budget)
+		hub_set_power_budget(ohci->hcd.self.root_hub,
+					ohci->power_budget);
 	create_debug_files (ohci);
 
 #ifdef	DEBUG
@@ -533,10 +480,6 @@ static const struct hc_driver ohci_omap_hc_driver = {
 	 * basic lifecycle operations
 	 */
 	.start =		ohci_omap_start,
-#ifdef	CONFIG_PM
-	/* suspend:		ohci_omap_suspend,  -- tbd */
-	/* resume:		ohci_omap_resume,   -- tbd */
-#endif
 	.stop =			ohci_stop,
 
 	/*
@@ -566,104 +509,130 @@ static const struct hc_driver ohci_omap_hc_driver = {
 	.hub_suspend =		ohci_hub_suspend,
 	.hub_resume =		ohci_hub_resume,
 #endif
+	.start_port_reset =	ohci_start_port_reset,
 };
 
 /*-------------------------------------------------------------------------*/
 
-static int ohci_hcd_omap_drv_probe(struct omap_dev *dev)
+static int ohci_hcd_omap_drv_probe(struct device *dev)
 {
-	struct usb_hcd *hcd = NULL;
-	int ret;
+	return usb_hcd_omap_probe(&ohci_omap_hc_driver,
+				to_platform_device(dev));
+}
 
-	if (usb_disabled())
-		return -ENODEV;
+static int ohci_hcd_omap_drv_remove(struct device *dev)
+{
+	struct platform_device	*pdev = to_platform_device(dev);
+	struct usb_hcd		*hcd = dev_get_drvdata(dev);
+	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);
+
+	usb_hcd_omap_remove(hcd, pdev);
+	if (ohci->transceiver) {
+		(void) otg_set_host(ohci->transceiver, 0);
+		put_device(ohci->transceiver->dev);
+	}
+	dev_set_drvdata(dev, NULL);
+
+	return 0;
+}
+
+/*-------------------------------------------------------------------------*/
 
-	ret = usb_hcd_omap_probe(&ohci_omap_hc_driver, &hcd, dev);
+#if	defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
 
-	if (ret == 0)
-		omap_set_drvdata(dev, hcd);
+/* states match PCI usage, always suspending the root hub except that
+ * 4 ~= D3cold (ACPI D3) with clock off (resume sees reset).
+ */
 
-	return ret;
+static int ohci_omap_suspend(struct device *dev, u32 state, u32 level)
+{
+	struct ohci_hcd	*ohci = hcd_to_ohci(dev_get_drvdata(dev));
+	int		status = -EINVAL;
+
+	if (state <= dev->power.power_state)
+		return 0;
+
+	dev_dbg(dev, "suspend to %d\n", state);
+	down(&ohci->hcd.self.root_hub->serialize);
+	status = ohci_hub_suspend(&ohci->hcd);
+	if (status == 0) {
+		if (state >= 4) {
+			/* power off + reset */
+			OTG_SYSCON_2_REG &= ~UHOST_EN;
+			ohci->hcd.self.root_hub->state = USB_STATE_SUSPENDED;
+			state = 4;
+		}
+		ohci->hcd.state = HCD_STATE_SUSPENDED;
+		dev->power.power_state = state;
+	}
+	up(&ohci->hcd.self.root_hub->serialize);
+	return status;
 }
 
-static int ohci_hcd_omap_drv_remove(struct omap_dev *dev)
+static int ohci_omap_resume(struct device *dev, u32 level)
 {
-	struct usb_hcd *hcd = omap_get_drvdata(dev);
+	struct ohci_hcd	*ohci = hcd_to_ohci(dev_get_drvdata(dev));
+	int		status = 0;
 
-	usb_hcd_omap_remove(hcd, dev);
+	switch (dev->power.power_state) {
+	case 0:
+		break;
+	case 4:
+		if (time_before(jiffies, ohci->next_statechange))
+			msleep(5);
+		ohci->next_statechange = jiffies;
+		OTG_SYSCON_2_REG |= UHOST_EN;
+		/* FALLTHROUGH */
+	default:
+		dev_dbg(dev, "resume from %d\n", dev->power.power_state);
+#ifdef	CONFIG_USB_SUSPEND
+		/* get extra cleanup even if remote wakeup isn't in use */
+		status = usb_resume_device(ohci->hcd.self.root_hub);
+#else
+		down(&ohci->hcd.self.root_hub->serialize);
+		status = ohci_hub_resume(&ohci->hcd);
+		up(&ohci->hcd.self.root_hub->serialize);
+#endif
+		if (status == 0)
+			dev->power.power_state = 0;
+		break;
+	}
+	return status;
+}
 
-	omap_set_drvdata(dev, NULL);
+#endif
 
-	return 0;
-}
+/*-------------------------------------------------------------------------*/
 
 /*
  * Driver definition to register with the OMAP bus
  */
-static struct omap_driver ohci_hcd_omap_driver = {
-	.drv = {
-		.name	= OMAP_OHCI_NAME,
-	},
-	.devid		= OMAP_OCP_DEVID_USB,
-	.busid		= OMAP_BUS_OCP,
-	.clocks		= 0,
+static struct device_driver ohci_hcd_omap_driver = {
+	.name		= "ohci",
+	.bus		= &platform_bus_type,
 	.probe		= ohci_hcd_omap_drv_probe,
 	.remove		= ohci_hcd_omap_drv_remove,
-};
-
-/* Any dma_mask must be set for OHCI to work */
-static u64 omap_dmamask = 0xffffffffUL;	
-
-/*
- * Device definition to match the driver above
- */
-static struct omap_dev ohci_hcd_omap_device = {
-	.name		= OMAP_OHCI_NAME,
-	.devid		= OMAP_OCP_DEVID_USB,
-	.busid		= OMAP_BUS_OCP,
-	.mapbase	= (void *)OMAP_OHCI_BASE,
-	.dma_mask	= &omap_dmamask,	/* Needed only for OHCI */
-	.res = {
-		.start	= OMAP_OHCI_BASE,
-		.end	= OMAP_OHCI_BASE + OMAP_OHCI_SIZE,
-	},
-	.irq = {
-		INT_USB_HHC_1,
-	},
+#if	defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
+	.suspend	= ohci_omap_suspend,
+	.resume		= ohci_omap_resume,
+#endif
 };
 
 static int __init ohci_hcd_omap_init (void)
 {
-	int ret;
-
-	dbg (DRIVER_INFO " (OMAP)");
-	dbg ("block sizes: ed %d td %d\n",
-		sizeof (struct ed), sizeof (struct td));
-
-	if (hmc_mode < 0 || hmc_mode > 25)
-		hmc_mode = default_hmc_mode;
-
-	/* Register the driver with OMAP bus */
-	ret = omap_driver_register(&ohci_hcd_omap_driver);
-	if (ret != 0)
+	printk (KERN_DEBUG "%s: " DRIVER_INFO " (OMAP)\n", hcd_name);
+	if (usb_disabled())
 		return -ENODEV;
 
-	/* Register the device with OMAP bus */
-	ret = omap_device_register(&ohci_hcd_omap_device);
-	if (ret != 0) {
-		omap_driver_unregister(&ohci_hcd_omap_driver);
-		return -ENODEV;
-	}
+	pr_debug("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
+		sizeof (struct ed), sizeof (struct td));
 
-	return ret;
+	return driver_register(&ohci_hcd_omap_driver);
 }
 
-MODULE_PARM(hmc_mode, "hmc_mode");
-
 static void __exit ohci_hcd_omap_cleanup (void)
 {
-	omap_device_unregister(&ohci_hcd_omap_device);
-	omap_driver_unregister(&ohci_hcd_omap_driver);
+	driver_unregister(&ohci_hcd_omap_driver);
 }
 
 module_init (ohci_hcd_omap_init);
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index dc8bc13bf..73d9aee65 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -242,6 +242,7 @@ static const struct hc_driver ohci_pci_hc_driver = {
 	.hub_suspend =		ohci_hub_suspend,
 	.hub_resume =		ohci_hub_resume,
 #endif
+	.start_port_reset =	ohci_start_port_reset,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -276,7 +277,7 @@ static int __init ohci_hcd_pci_init (void)
 	if (usb_disabled())
 		return -ENODEV;
 
-	printk (KERN_DEBUG "%s: block sizes: ed %Zd td %Zd\n", hcd_name,
+	pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
 		sizeof (struct ed), sizeof (struct td));
 	return pci_module_init (&ohci_pci_driver);
 }
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index 74c829f92..1afd40fec 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -136,7 +136,7 @@ static void periodic_link (struct ohci_hcd *ohci, struct ed *ed)
 
 	for (i = ed->branch; i < NUM_INTS; i += ed->interval) {
 		struct ed	**prev = &ohci->periodic [i];
-		u32		*prev_p = &ohci->hcca->int_table [i];
+		__le32		*prev_p = &ohci->hcca->int_table [i];
 		struct ed	*here = *prev;
 
 		/* sorting each branch by period (slow before fast)
@@ -156,7 +156,7 @@ static void periodic_link (struct ohci_hcd *ohci, struct ed *ed)
 				ed->hwNextED = *prev_p;
 			wmb ();
 			*prev = ed;
-			*prev_p = cpu_to_le32p (&ed->dma);
+			*prev_p = cpu_to_le32(ed->dma);
 			wmb();
 		}
 		ohci->load [i] += ed->load;
@@ -257,7 +257,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed)
 	for (i = ed->branch; i < NUM_INTS; i += ed->interval) {
 		struct ed	*temp;
 		struct ed	**prev = &ohci->periodic [i];
-		u32		*prev_p = &ohci->hcca->int_table [i];
+		__le32		*prev_p = &ohci->hcca->int_table [i];
 
 		while (*prev && (temp = *prev) != ed) {
 			prev_p = &temp->hwNextED;
@@ -427,20 +427,21 @@ static struct ed *ed_get (
 	 */
   	if (ed->state == ED_IDLE) {
 		u32	info;
+		__le32	hw_info;
 
 		info = usb_pipedevice (pipe);
 		info |= (ep >> 1) << 7;
 		info |= usb_maxpacket (udev, pipe, is_out) << 16;
-		info = cpu_to_le32 (info);
+		hw_info = cpu_to_le32 (info);
 		if (udev->speed == USB_SPEED_LOW)
-			info |= ED_LOWSPEED;
+			hw_info |= ED_LOWSPEED;
 		/* only control transfers store pids in tds */
 		if (type != PIPE_CONTROL) {
-			info |= is_out ? ED_OUT : ED_IN;
+			hw_info |= is_out ? ED_OUT : ED_IN;
 			if (type != PIPE_BULK) {
 				/* periodic transfers... */
 				if (type == PIPE_ISOCHRONOUS)
-					info |= ED_ISO;
+					hw_info |= ED_ISO;
 				else if (interval > 32)	/* iso can be bigger */
 					interval = 32;
 				ed->interval = interval;
@@ -451,7 +452,7 @@ static struct ed *ed_get (
 						/ 1000;
 			}
 		}
-		ed->hwINFO = info;
+		ed->hwINFO = hw_info;
 	}
 
 done:
@@ -751,12 +752,6 @@ static void td_done (struct ohci_hcd *ohci, struct urb *urb, struct td *td)
 
   		cc = TD_CC_GET (tdINFO);
 
-		/* control endpoints only have soft stalls */
-  		if (type != PIPE_CONTROL && cc == TD_CC_STALL)
-			usb_endpoint_halt (urb->dev,
-				usb_pipeendpoint (urb->pipe),
-				usb_pipeout (urb->pipe));
-
 		/* update packet status if needed (short is normally ok) */
 		if (cc == TD_DATAUNDERRUN
 				&& !(urb->transfer_flags & URB_SHORT_NOT_OK))
@@ -795,7 +790,7 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
   	struct urb		*urb = td->urb;
 	struct ed		*ed = td->ed;
 	struct list_head	*tmp = td->td_list.next;
-	u32			toggle = ed->hwHeadP & ED_C;
+	__le32			toggle = ed->hwHeadP & ED_C;
 
 	/* clear ed halt; this is the td that caused it, but keep it inactive
 	 * until its urb->complete() has a chance to clean up.
@@ -810,7 +805,7 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
 	 */
 	while (tmp != &ed->td_list) {
 		struct td	*next;
-		u32		info;
+		__le32		info;
 
 		next = list_entry (tmp, struct td, td_list);
 		tmp = next->td_list.next;
@@ -906,9 +901,6 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
 
 /*-------------------------------------------------------------------------*/
 
-/* wrap-aware logic stolen from <linux/jiffies.h> */
-#define tick_before(t1,t2) ((((s16)(t1))-((s16)(t2))) < 0)
-
 /* there are some urbs/eds to unlink; called in_irq(), with HCD locked */
 static void
 finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs)
@@ -919,7 +911,7 @@ rescan_all:
 	for (last = &ohci->ed_rm_list, ed = *last; ed != NULL; ed = *last) {
 		struct list_head	*entry, *tmp;
 		int			completed, modified;
-		u32			*prev;
+		__le32			*prev;
 
 		/* only take off EDs that the HC isn't using, accounting for
 		 * frame counter wraps and EDs with partially retired TDs
@@ -937,7 +929,7 @@ skip_ed:
 
 				td = list_entry (ed->td_list.next, struct td,
 							td_list);
-				head = cpu_to_le32 (ed->hwHeadP) & TD_MASK;
+				head = le32_to_cpu (ed->hwHeadP) & TD_MASK;
 
 				/* INTR_WDH may need to clean up first */
 				if (td->td_dma != head)
@@ -968,7 +960,7 @@ rescan_this:
 			struct td	*td;
 			struct urb	*urb;
 			urb_priv_t	*urb_priv;
-			u32		savebits;
+			__le32		savebits;
 
 			td = list_entry (entry, struct td, td_list);
 			urb = td->urb;
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 5f0384417..19436cdd7 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -16,7 +16,7 @@
  */
 struct ed {
 	/* first fields are hardware-specified, le32 */
-	__u32			hwINFO;       	/* endpoint config bitmap */
+	__le32			hwINFO;       	/* endpoint config bitmap */
 	/* info bits defined by hcd */
 #define ED_DEQUEUE	__constant_cpu_to_le32(1 << 27)
 	/* info bits defined by the hardware */
@@ -25,11 +25,11 @@ struct ed {
 #define ED_LOWSPEED	__constant_cpu_to_le32(1 << 13)
 #define ED_OUT		__constant_cpu_to_le32(0x01 << 11)
 #define ED_IN		__constant_cpu_to_le32(0x02 << 11)
-	__u32			hwTailP;	/* tail of TD list */
-	__u32			hwHeadP;	/* head of TD list (hc r/w) */
+	__le32			hwTailP;	/* tail of TD list */
+	__le32			hwHeadP;	/* head of TD list (hc r/w) */
 #define ED_C		__constant_cpu_to_le32(0x02)	/* toggle carry */
 #define ED_H		__constant_cpu_to_le32(0x01)	/* halted */
-	__u32			hwNextED;	/* next ED in list */
+	__le32			hwNextED;	/* next ED in list */
 
 	/* rest are purely for the driver's use */
 	dma_addr_t		dma;		/* addr of ED */
@@ -71,7 +71,7 @@ struct ed {
  */
 struct td {
 	/* first fields are hardware-specified, le32 */
-	__u32		hwINFO;		/* transfer info bitmask */
+	__le32		hwINFO;		/* transfer info bitmask */
 
 	/* hwINFO bits for both general and iso tds: */
 #define TD_CC       0xf0000000			/* condition code */
@@ -100,13 +100,13 @@ struct td {
 
 	/* (no hwINFO #defines yet for iso tds) */
 
-  	__u32		hwCBP;		/* Current Buffer Pointer (or 0) */
-  	__u32		hwNextTD;	/* Next TD Pointer */
-  	__u32		hwBE;		/* Memory Buffer End Pointer */
+  	__le32		hwCBP;		/* Current Buffer Pointer (or 0) */
+  	__le32		hwNextTD;	/* Next TD Pointer */
+  	__le32		hwBE;		/* Memory Buffer End Pointer */
 
 	/* PSW is only for ISO */
 #define MAXPSW 1		/* hardware allows 8 */
-  	__u16		hwPSW [MAXPSW];
+  	__le16		hwPSW [MAXPSW];
 
 	/* rest are purely for the driver's use */
   	__u8		index;
@@ -171,16 +171,16 @@ static const int cc_to_error [16] = {
  */
 struct ohci_hcca {
 #define NUM_INTS 32
-	__u32	int_table [NUM_INTS];	/* periodic schedule */
+	__le32	int_table [NUM_INTS];	/* periodic schedule */
 
 	/* 
 	 * OHCI defines u16 frame_no, followed by u16 zero pad.
 	 * Since some processors can't do 16 bit bus accesses,
 	 * portable access must be a 32 bit byteswapped access.
 	 */
-	u32	frame_no;		/* current frame number */
+	__le32	frame_no;		/* current frame number */
 #define OHCI_FRAME_NO(hccap) ((u16)le32_to_cpup(&(hccap)->frame_no))
-	__u32	done_head;		/* info returned for an interrupt */
+	__le32	done_head;		/* info returned for an interrupt */
 	u8	reserved_for_hc [116];
 	u8	what [4];		/* spec only identifies 252 bytes :) */
 } __attribute__ ((aligned(256)));
@@ -343,7 +343,7 @@ struct ohci_hcd {
 	/*
 	 * I/O memory used to communicate with the HC (dma-consistent)
 	 */
-	struct ohci_regs	*regs;
+	struct ohci_regs __iomem *regs;
 
 	/*
 	 * main memory used to communicate with the HC (dma-consistent).
@@ -359,6 +359,13 @@ struct ohci_hcd {
 	struct ed		*ed_controltail;	/* last in ctrl list */
  	struct ed		*periodic [NUM_INTS];	/* shadow int_table */
 
+	/*
+	 * OTG controllers and transceivers need software interaction;
+	 * other external transceivers should be software-transparent 
+	 */
+	struct otg_transceiver	*transceiver;
+	unsigned		power_budget;
+
 	/*
 	 * memory management for queue data structures
 	 */
@@ -443,7 +450,7 @@ static inline unsigned int ohci_readl (void* regs)
 #else
 	/* Standard version of ohci_readl uses standard, platform
 	 * specific implementation. */
-static inline unsigned int ohci_readl (void* regs)
+static inline unsigned int ohci_readl (void __iomem * regs)
 {
 	return readl (regs);
 }
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index bf8ab3cd7..20a42f914 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -82,7 +82,7 @@ static int debug = 1;
 #else
 static int debug = 0;
 #endif
-MODULE_PARM(debug, "i");
+module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug level");
 static char *errbuf;
 #define ERRBUF_LEN    (32 * 1024)
@@ -232,7 +232,7 @@ static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td)
 /*
  * Inserts a td into qh list at the top.
  */
-static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, u32 breadth)
+static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, __le32 breadth)
 {
 	struct list_head *tmp, *head;
 	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
@@ -376,7 +376,7 @@ static void uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struct
 static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
 {
 	struct uhci_qh *pqh;
-	u32 newlink;
+	__le32 newlink;
 	unsigned int age;
 
 	if (!qh)
@@ -1120,10 +1120,6 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
 
 td_error:
 	ret = uhci_map_status(status, uhci_packetout(td_token(td)));
-	if (ret == -EPIPE)
-		/* endpoint has stalled - mark it halted */
-		usb_endpoint_halt(urb->dev, uhci_endpoint(td_token(td)),
-	    			uhci_packetout(td_token(td)));
 
 err:
 	/* 
@@ -1344,7 +1340,7 @@ static struct urb *uhci_find_urb_ep(struct uhci_hcd *uhci, struct urb *urb)
 
 static int uhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, int mem_flags)
 {
-	int ret = -EINVAL;
+	int ret;
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 	unsigned long flags;
 	struct urb *eurb;
@@ -1352,7 +1348,8 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, int mem_flags)
 
 	spin_lock_irqsave(&uhci->schedule_lock, flags);
 
-	if (urb->status != -EINPROGRESS)	/* URB already unlinked! */
+	ret = urb->status;
+	if (ret != -EINPROGRESS)		/* URB already unlinked! */
 		goto out;
 
 	eurb = uhci_find_urb_ep(uhci, urb);
@@ -1637,13 +1634,6 @@ static void stall_callback(unsigned long ptr)
 		if (up->fsbr && !up->fsbr_timeout && time_after_eq(jiffies, up->fsbrtime + IDLE_TIMEOUT))
 			uhci_fsbr_timeout(uhci, u);
 
-		/* Check if the URB timed out */
-		if (u->timeout && u->status == -EINPROGRESS &&
-			time_after_eq(jiffies, up->inserttime + u->timeout)) {
-			u->status = -ETIMEDOUT;
-			list_move_tail(&up->urb_list, &list);
-		}
-
 		spin_unlock(&u->lock);
 	}
 	spin_unlock_irqrestore(&uhci->schedule_lock, flags);
@@ -2258,7 +2248,8 @@ static int uhci_start(struct usb_hcd *hcd)
 			irq = 7;
 
 		/* Only place we don't use the frame list routines */
-		uhci->fl->frame[i] = cpu_to_le32(uhci->skelqh[irq]->dma_handle);
+		uhci->fl->frame[i] = UHCI_PTR_QH |
+				cpu_to_le32(uhci->skelqh[irq]->dma_handle);
 	}
 
 	/*
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index b4bf3b6ca..785c0c2cc 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -80,7 +80,7 @@
 #define CAN_SCHEDULE_FRAMES	1000	/* how far future frames can be scheduled */
 
 struct uhci_frame_list {
-	u32 frame[UHCI_NUMFRAMES];
+	__le32 frame[UHCI_NUMFRAMES];
 
 	void *frame_cpu[UHCI_NUMFRAMES];
 
@@ -105,8 +105,8 @@ struct urb_priv;
  */
 struct uhci_qh {
 	/* Hardware fields */
-	u32 link;			/* Next queue */
-	u32 element;			/* Queue element pointer */
+	__le32 link;			/* Next queue */
+	__le32 element;			/* Queue element pointer */
 
 	/* Software fields */
 	dma_addr_t dma_handle;
@@ -185,10 +185,10 @@ struct uhci_qh {
  */
 struct uhci_td {
 	/* Hardware fields */
-	u32 link;
-	u32 status;
-	u32 token;
-	u32 buffer;
+	__le32 link;
+	__le32 status;
+	__le32 token;
+	__le32 buffer;
 
 	/* Software fields */
 	dma_addr_t dma_handle;
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index 2dde38163..22bbd7006 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -82,7 +82,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 		*/
 
 	case GetHubStatus:
-		*(__u32 *)buf = cpu_to_le32(0);
+		*(__le32 *)buf = cpu_to_le32(0);
 		OK(4);		/* hub power */
 	case GetPortStatus:
 		if (!wIndex || wIndex > uhci->rh_numports)
@@ -126,8 +126,8 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 			dev_dbg(uhci_dev(uhci), "port %d portsc %04x\n",
 					wIndex, status);
 
-		*(__u16 *)buf = cpu_to_le16(wPortStatus);
-		*(__u16 *)(buf + 2) = cpu_to_le16(wPortChange);
+		*(__le16 *)buf = cpu_to_le16(wPortStatus);
+		*(__le16 *)(buf + 2) = cpu_to_le16(wPortChange);
 		OK(4);
 	case SetHubFeature:		/* We don't implement these */
 	case ClearHubFeature:
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index 230efaf7b..9d3aa3075 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -214,8 +214,8 @@ static struct usb_driver mts_usb_driver = {
 #ifdef MTS_DO_DEBUG
 
 static inline void mts_debug_dump(struct mts_desc* desc) {
-	MTS_DEBUG("desc at 0x%x: halted = %02x%02x, toggle = %02x%02x\n",
-		  (int)desc,(int)desc->usb_dev->halted[1],(int)desc->usb_dev->halted[0],
+	MTS_DEBUG("desc at 0x%x: toggle = %02x%02x\n",
+		  (int)desc,
 		  (int)desc->usb_dev->toggle[1],(int)desc->usb_dev->toggle[0]
 		);
 	MTS_DEBUG("ep_out=%x ep_response=%x ep_image=%x\n",
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
index b0261f8a6..44b8faee6 100644
--- a/drivers/usb/input/aiptek.c
+++ b/drivers/usb/input/aiptek.c
@@ -494,9 +494,9 @@ static void aiptek_irq(struct urb *urb, struct pt_regs *regs)
 		} else {
 			input_regs(inputdev, regs);
 
-			x = le16_to_cpu(get_unaligned((__u16 *) (data + 1)));
-			y = le16_to_cpu(get_unaligned((__u16 *) (data + 3)));
-			z = le16_to_cpu(get_unaligned((__u16 *) (data + 6)));
+			x = le16_to_cpu(get_unaligned((__le16 *) (data + 1)));
+			y = le16_to_cpu(get_unaligned((__le16 *) (data + 3)));
+			z = le16_to_cpu(get_unaligned((__le16 *) (data + 6)));
 
 			p = (data[5] & 0x01) != 0 ? 1 : 0;
 			dv = (data[5] & 0x02) != 0 ? 1 : 0;
@@ -573,8 +573,8 @@ static void aiptek_irq(struct urb *urb, struct pt_regs *regs)
 			aiptek->diagnostic = AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED;
 		} else {
 			input_regs(inputdev, regs);
-			x = le16_to_cpu(get_unaligned((__u16 *) (data + 1)));
-			y = le16_to_cpu(get_unaligned((__u16 *) (data + 3)));
+			x = le16_to_cpu(get_unaligned((__le16 *) (data + 1)));
+			y = le16_to_cpu(get_unaligned((__le16 *) (data + 3)));
 
 			jitterable = data[5] & 0x1c;
 
@@ -632,7 +632,7 @@ static void aiptek_irq(struct urb *urb, struct pt_regs *regs)
 		pck = (data[1] & aiptek->curSetting.stylusButtonUpper) != 0 ? 1 : 0;
 
 		macro = data[3];
-		z = le16_to_cpu(get_unaligned((__u16 *) (data + 4)));
+		z = le16_to_cpu(get_unaligned((__le16 *) (data + 4)));
 
 		if (dv != 0) {
 			input_regs(inputdev, regs);
@@ -729,7 +729,7 @@ static void aiptek_irq(struct urb *urb, struct pt_regs *regs)
 	 * hat switches (which just so happen to be the macroKeys.)
 	 */
 	else if (data[0] == 6) {
-		macro = le16_to_cpu(get_unaligned((__u16 *) (data + 1)));
+		macro = le16_to_cpu(get_unaligned((__le16 *) (data + 1)));
 		input_regs(inputdev, regs);
 
 		if (macro > 0) {
@@ -930,7 +930,7 @@ aiptek_query(struct aiptek *aiptek, unsigned char command, unsigned char data)
 		    buf[0], buf[1], buf[2]);
 		ret = -EIO;
 	} else {
-		ret = le16_to_cpu(get_unaligned((__u16 *) (buf + 1)));
+		ret = le16_to_cpu(get_unaligned((__le16 *) (buf + 1)));
 	}
 	kfree(buf);
 	return ret;
@@ -2289,9 +2289,9 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(programmableDelay, "i");
+module_param(programmableDelay, int, 0);
 MODULE_PARM_DESC(programmableDelay, "delay used during tablet programming");
-MODULE_PARM(jitterDelay, "i");
+module_param(jitterDelay, int, 0);
 MODULE_PARM_DESC(jitterDelay, "stylus/mouse settlement delay");
 
 module_init(aiptek_init);
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
index c1f1c1d20..61a42bdae 100644
--- a/drivers/usb/input/ati_remote.c
+++ b/drivers/usb/input/ati_remote.c
@@ -112,11 +112,11 @@
 #define ATI_INPUTNUM      1     /* Which input device to register as */
 
 static unsigned long channel_mask = 0;
-module_param(channel_mask, ulong, 444);
+module_param(channel_mask, ulong, 0444);
 MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore");
 
 static int debug = 0;
-module_param(debug, int, 444);
+module_param(debug, int, 0444);
 MODULE_PARM_DESC(debug, "Enable extra debug messages and information");
 
 #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0)
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 79082d918..35baacd77 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -219,17 +219,13 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
 		dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
 		return -1;
 	}
-	usages = parser->local.usage_index;
+	
+	if (!(usages = max_t(int, parser->local.usage_index, parser->global.report_count)))
+		return 0; /* Ignore padding fields */
 
 	offset = report->size;
 	report->size += parser->global.report_size * parser->global.report_count;
 
-	if (usages < parser->global.report_count)
-		usages = parser->global.report_count;
-
-	if (usages == 0)
-		return 0; /* ignore padding fields */
-
 	if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL)
 		return 0;
 
@@ -609,16 +605,16 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
 		case 2:
 			if ((end - start) < 2) 
 				return NULL;
-			item->data.u16 = le16_to_cpu(get_unaligned((__u16*)start));
-			start = (__u8 *)((__u16 *)start + 1);
+			item->data.u16 = le16_to_cpu(get_unaligned((__le16*)start));
+			start = (__u8 *)((__le16 *)start + 1);
 			return start;
 
 		case 3:
 			item->size++;
 			if ((end - start) < 4)
 				return NULL;
-			item->data.u32 = le32_to_cpu(get_unaligned((__u32*)start));
-			start = (__u8 *)((__u32 *)start + 1);
+			item->data.u32 = le32_to_cpu(get_unaligned((__le32*)start));
+			start = (__u8 *)((__le32 *)start + 1);
 			return start;
 	}
 
@@ -760,15 +756,15 @@ static __inline__ __u32 s32ton(__s32 value, unsigned n)
 static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
 {
 	report += (offset >> 5) << 2; offset &= 31;
-	return (le64_to_cpu(get_unaligned((__u64*)report)) >> offset) & ((1 << n) - 1);
+	return (le64_to_cpu(get_unaligned((__le64*)report)) >> offset) & ((1 << n) - 1);
 }
 
 static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
 {
 	report += (offset >> 5) << 2; offset &= 31;
-	put_unaligned((get_unaligned((__u64*)report)
+	put_unaligned((get_unaligned((__le64*)report)
 		& cpu_to_le64(~((((__u64) 1 << n) - 1) << offset)))
-		| cpu_to_le64((__u64)value << offset), (__u64*)report);
+		| cpu_to_le64((__u64)value << offset), (__le64*)report);
 }
 
 /*
@@ -923,20 +919,22 @@ static void hid_irq_in(struct urb *urb, struct pt_regs *regs)
 	int			status;
 
 	switch (urb->status) {
-	case 0:			/* success */
-		hid_input_report(HID_INPUT_REPORT, urb, regs);
-		break;
-	case -ECONNRESET:	/* unlink */
-	case -ENOENT:
-	case -ESHUTDOWN:
-		return;
-	default:		/* error */
-		dbg("nonzero status in input irq %d", urb->status);
+		case 0:			/* success */
+			hid_input_report(HID_INPUT_REPORT, urb, regs);
+			break;
+		case -ECONNRESET:	/* unlink */
+		case -ENOENT:
+		case -ESHUTDOWN:
+			return;
+		case -ETIMEDOUT:	/* NAK */
+			break;
+		default:		/* error */
+			warn("input irq status %d received", urb->status);
 	}
 	
-	status = usb_submit_urb (urb, SLAB_ATOMIC);
+	status = usb_submit_urb(urb, SLAB_ATOMIC);
 	if (status)
-		err ("can't resubmit intr, %s-%s/input%d, status %d",
+		err("can't resubmit intr, %s-%s/input%d, status %d",
 				hid->dev->bus->bus_name, hid->dev->devpath,
 				hid->ifnum, status);
 }
@@ -1137,23 +1135,31 @@ static void hid_irq_out(struct urb *urb, struct pt_regs *regs)
 	struct hid_device *hid = urb->context;
 	unsigned long flags;
 
-	if (urb->status)
-		warn("output irq status %d received", urb->status);
+	switch (urb->status) {
+		case 0:			/* success */
+		case -ECONNRESET:	/* unlink */
+		case -ENOENT:
+		case -ESHUTDOWN:
+			break;
+		default:		/* error */
+			warn("output irq status %d received", urb->status);
+	}
 
 	spin_lock_irqsave(&hid->outlock, flags);
 
 	hid->outtail = (hid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
 
 	if (hid->outhead != hid->outtail) {
-		hid_submit_out(hid);
+		if (hid_submit_out(hid)) {
+			clear_bit(HID_OUT_RUNNING, &hid->iofl);;
+			wake_up(&hid->wait);
+		}
 		spin_unlock_irqrestore(&hid->outlock, flags);
 		return;
 	}
 
 	clear_bit(HID_OUT_RUNNING, &hid->iofl);
-
 	spin_unlock_irqrestore(&hid->outlock, flags);
-
 	wake_up(&hid->wait);
 }
 
@@ -1166,26 +1172,34 @@ static void hid_ctrl(struct urb *urb, struct pt_regs *regs)
 	struct hid_device *hid = urb->context;
 	unsigned long flags;
 
-	if (urb->status)
-		warn("ctrl urb status %d received", urb->status);
-
 	spin_lock_irqsave(&hid->ctrllock, flags);
 
-	if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN) 
-		hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, regs);
+	switch (urb->status) {
+		case 0:			/* success */
+			if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN) 
+				hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, regs);
+		case -ECONNRESET:	/* unlink */
+		case -ENOENT:
+		case -ESHUTDOWN:
+		case -EPIPE:		/* report not available */
+			break;
+		default:		/* error */
+			warn("ctrl urb status %d received", urb->status);
+	}
 
 	hid->ctrltail = (hid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
 
 	if (hid->ctrlhead != hid->ctrltail) {
-		hid_submit_ctrl(hid);
+		if (hid_submit_ctrl(hid)) {
+			clear_bit(HID_CTRL_RUNNING, &hid->iofl);
+			wake_up(&hid->wait);
+		}
 		spin_unlock_irqrestore(&hid->ctrllock, flags);
 		return;
 	}
 
 	clear_bit(HID_CTRL_RUNNING, &hid->iofl);
-
 	spin_unlock_irqrestore(&hid->ctrllock, flags);
-
 	wake_up(&hid->wait);
 }
 
@@ -1211,7 +1225,8 @@ void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsign
 		hid->outhead = head;
 
 		if (!test_and_set_bit(HID_OUT_RUNNING, &hid->iofl))
-			hid_submit_out(hid);
+			if (hid_submit_out(hid))
+				clear_bit(HID_OUT_RUNNING, &hid->iofl);
 
 		spin_unlock_irqrestore(&hid->outlock, flags);
 		return;
@@ -1230,7 +1245,8 @@ void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsign
 	hid->ctrlhead = head;
 
 	if (!test_and_set_bit(HID_CTRL_RUNNING, &hid->iofl))
-		hid_submit_ctrl(hid);
+		if (hid_submit_ctrl(hid))
+			clear_bit(HID_CTRL_RUNNING, &hid->iofl);
 
 	spin_unlock_irqrestore(&hid->ctrllock, flags);
 }
@@ -1282,7 +1298,7 @@ int hid_open(struct hid_device *hid)
 void hid_close(struct hid_device *hid)
 {
 	if (!--hid->open)
-		usb_unlink_urb(hid->urbin);
+		usb_kill_urb(hid->urbin);
 }
 
 /*
@@ -1439,6 +1455,11 @@ void hid_init_reports(struct hid_device *hid)
 #define USB_DEVICE_ID_1_PHIDGETSERVO_20	0x8101
 #define USB_DEVICE_ID_4_PHIDGETSERVO_20	0x8104
 
+#define USB_VENDOR_ID_CODEMERCS		0x07c0
+#define USB_DEVICE_ID_CODEMERCS_IOW40	0x1500
+#define USB_DEVICE_ID_CODEMERCS_IOW24	0x1501
+
+
 static struct hid_blacklist {
 	__u16 idVendor;
 	__u16 idProduct;
@@ -1453,20 +1474,20 @@ static struct hid_blacklist {
 	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE },
-
 	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE },
-
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PENPARTNER, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 1, HID_QUIRK_IGNORE },
@@ -1619,11 +1640,17 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 
 		struct usb_endpoint_descriptor *endpoint;
 		int pipe;
+		int interval;
 
 		endpoint = &interface->endpoint[n].desc;
 		if ((endpoint->bmAttributes & 3) != 3)		/* Not an interrupt endpoint */
 			continue;
 
+		/* handle potential highspeed HID correctly */
+		interval = endpoint->bInterval;
+		if (dev->speed == USB_SPEED_HIGH)
+			interval = 1 << (interval - 1);
+
 		if (endpoint->bEndpointAddress & USB_DIR_IN) {
 			int len;
 
@@ -1636,9 +1663,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 			if (len > HID_BUFFER_SIZE)
 				len = HID_BUFFER_SIZE;
 			usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, len,
-					 hid_irq_in, hid, endpoint->bInterval);
+					 hid_irq_in, hid, interval);
 			hid->urbin->transfer_dma = hid->inbuf_dma;
-			hid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+			hid->urbin->transfer_flags |=(URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK);
 		} else {
 			if (hid->urbout)
 				continue;
@@ -1646,9 +1673,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 				goto fail;
 			pipe = usb_sndintpipe(dev, endpoint->bEndpointAddress);
 			usb_fill_int_urb(hid->urbout, dev, pipe, hid->outbuf, 0,
-					  hid_irq_out, hid, 1);
+					 hid_irq_out, hid, interval);
 			hid->urbout->transfer_dma = hid->outbuf_dma;
-			hid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+			hid->urbout->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK);
 		}
 	}
 
@@ -1698,8 +1725,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 			     hid->ctrlbuf, 1, hid_ctrl, hid);
 	hid->urbctrl->setup_dma = hid->cr_dma;
 	hid->urbctrl->transfer_dma = hid->ctrlbuf_dma;
-	hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP
-				| URB_NO_SETUP_DMA_MAP);
+	hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP | URB_ASYNC_UNLINK);
 
 	return hid;
 
@@ -1725,9 +1751,9 @@ static void hid_disconnect(struct usb_interface *intf)
 		return;
 
 	usb_set_intfdata(intf, NULL);
-	usb_unlink_urb(hid->urbin);
-	usb_unlink_urb(hid->urbout);
-	usb_unlink_urb(hid->urbctrl);
+	usb_kill_urb(hid->urbin);
+	usb_kill_urb(hid->urbout);
+	usb_kill_urb(hid->urbctrl);
 
 	if (hid->claimed & HID_CLAIMED_INPUT)
 		hidinput_disconnect(hid);
@@ -1835,8 +1861,8 @@ hiddev_init_fail:
 
 static void __exit hid_exit(void)
 {
-	hiddev_exit();
 	usb_deregister(&hid_driver);
+	hiddev_exit();
 }
 
 module_init(hid_init);
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
index ff319d9ad..44e466d19 100644
--- a/drivers/usb/input/hiddev.c
+++ b/drivers/usb/input/hiddev.c
@@ -223,16 +223,6 @@ static int hiddev_fasync(int fd, struct file *file, int on)
 	return retval < 0 ? retval : 0;
 }
 
-/*
- * De-allocate a hiddev structure
- */
-static struct usb_class_driver hiddev_class;
-static void hiddev_cleanup(struct hiddev *hiddev)
-{
-	hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL;
-	usb_deregister_dev(hiddev->hid->intf, &hiddev_class);
-	kfree(hiddev);
-}
 
 /*
  * release file op
@@ -253,7 +243,7 @@ static int hiddev_release(struct inode * inode, struct file * file)
 		if (list->hiddev->exist) 
 			hid_close(list->hiddev->hid);
 		else
-			hiddev_cleanup(list->hiddev);
+			kfree(list->hiddev);
 	}
 
 	kfree(list);
@@ -636,16 +626,19 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
 				goto inval;
 
 			field = report->field[uref->field_index];
-			if (uref->usage_index >= field->maxusage)
-				goto inval;
 
-			if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
-				if (uref_multi->num_values >= HID_MAX_USAGES || 
-				    uref->usage_index >= field->maxusage || 
-				   (uref->usage_index + uref_multi->num_values) >= field->maxusage)
+			if (cmd == HIDIOCGCOLLECTIONINDEX) {
+				if (uref->usage_index >= field->maxusage)
 					goto inval;
+			} else if (uref->usage_index >= field->report_count)
+				goto inval;
+
+			else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
+				 (uref_multi->num_values >= HID_MAX_MULTI_USAGES ||
+				  uref->usage_index + uref_multi->num_values >= field->report_count ||
+				  uref->usage_index + uref_multi->num_values < uref->usage_index))
+				goto inval;
 			}
-		}
 
 		switch (cmd) {
 			case HIDIOCGUSAGE:
@@ -795,17 +788,21 @@ int hiddev_connect(struct hid_device *hid)
  * This is where hid.c calls us to disconnect a hiddev device from the
  * corresponding hid device (usually because the usb device has disconnected)
  */
+static struct usb_class_driver hiddev_class;
 void hiddev_disconnect(struct hid_device *hid)
 {
 	struct hiddev *hiddev = hid->hiddev;
 
 	hiddev->exist = 0;
 
+	hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL;
+	usb_deregister_dev(hiddev->hid->intf, &hiddev_class);
+
 	if (hiddev->open) {
 		hid_close(hiddev->hid);
 		wake_up_interruptible(&hiddev->wait);
 	} else {
-		hiddev_cleanup(hiddev);
+		kfree(hiddev);
 	}
 }
 
diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c
index 43af4031f..39c0d38ae 100644
--- a/drivers/usb/input/kbtab.c
+++ b/drivers/usb/input/kbtab.c
@@ -26,10 +26,9 @@ MODULE_LICENSE(DRIVER_LICENSE);
 
 #define USB_VENDOR_ID_KBGEAR	0x084e
 
-static int       kb_pressure_click = 0x10;
-MODULE_PARM     (kb_pressure_click,"i");
-MODULE_PARM_DESC(kb_pressure_click,
-		 "pressure threshold for clicks");
+static int kb_pressure_click = 0x10;
+module_param(kb_pressure_click, int, 0);
+MODULE_PARM_DESC(kb_pressure_click, "pressure threshold for clicks");
 
 struct kbtab {
 	signed char *data;
@@ -67,8 +66,8 @@ static void kbtab_irq(struct urb *urb, struct pt_regs *regs)
 		goto exit;
 	}
 
-	kbtab->x = le16_to_cpu(get_unaligned((u16 *) &data[1]));
-	kbtab->y = le16_to_cpu(get_unaligned((u16 *) &data[3]));
+	kbtab->x = le16_to_cpu(get_unaligned((__le16 *) &data[1]));
+	kbtab->y = le16_to_cpu(get_unaligned((__le16 *) &data[3]));
 
 	kbtab->pressure = (data[5]);
 
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
index c66001351..492a5cb12 100644
--- a/drivers/usb/input/wacom.c
+++ b/drivers/usb/input/wacom.c
@@ -285,8 +285,8 @@ static void wacom_penpartner_irq(struct urb *urb, struct pt_regs *regs)
 
 	input_regs(dev, regs);
 	input_report_key(dev, BTN_TOOL_PEN, 1);
-	input_report_abs(dev, ABS_X, le16_to_cpu(get_unaligned((u16 *) &data[1])));
-	input_report_abs(dev, ABS_Y, le16_to_cpu(get_unaligned((u16 *) &data[3])));
+	input_report_abs(dev, ABS_X, le16_to_cpu(get_unaligned((__le16 *) &data[1])));
+	input_report_abs(dev, ABS_Y, le16_to_cpu(get_unaligned((__le16 *) &data[3])));
 	input_report_abs(dev, ABS_PRESSURE, (signed char)data[6] + 127);
 	input_report_key(dev, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20));
 	input_report_key(dev, BTN_STYLUS, (data[5] & 0x40));
@@ -329,8 +329,8 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
 	if (data[0] != 2)
 		dbg("wacom_graphire_irq: received unknown report #%d", data[0]);
 
-	x = le16_to_cpu(*(u16 *) &data[2]);
-	y = le16_to_cpu(*(u16 *) &data[4]);
+	x = le16_to_cpu(*(__le16 *) &data[2]);
+	y = le16_to_cpu(*(__le16 *) &data[4]);
 
 	input_regs(dev, regs);
 
@@ -367,7 +367,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
 		input_report_abs(dev, ABS_Y, y);
 	}
 
-	input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(u16 *) &data[6]));
+	input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6]));
 	input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
 	input_report_key(dev, BTN_STYLUS, data[1] & 0x02);
 	input_report_key(dev, BTN_STYLUS2, data[1] & 0x04);
@@ -456,8 +456,8 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
 		goto exit;
 	}
 
-	input_report_abs(dev, ABS_X, be16_to_cpu(*(u16 *) &data[2]));
-	input_report_abs(dev, ABS_Y, be16_to_cpu(*(u16 *) &data[4]));
+	input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2]));
+	input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4]));
 	input_report_abs(dev, ABS_DISTANCE, data[9]);
 
 	if ((data[1] & 0xb8) == 0xa0) {						/* general pen packet */
diff --git a/drivers/usb/media/Kconfig b/drivers/usb/media/Kconfig
index 6dac4dc14..4ac7ac4f3 100644
--- a/drivers/usb/media/Kconfig
+++ b/drivers/usb/media/Kconfig
@@ -106,46 +106,6 @@ config USB_OV511
 	  To compile this driver as a module, choose M here: the
 	  module will be called ov511.
 
-config USB_PWC
-	tristate "USB Philips Cameras"
-	depends on USB && VIDEO_DEV
-	---help---
-	  Say Y or M here if you want to use one of these Philips & OEM
-          webcams:
-           * Philips PCA645, PCA646
-           * Philips PCVC675, PCVC680, PCVC690
-           * Philips PCVC720/40, PCVC730, PCVC740, PCVC750
-	   * Askey VC010
-	   * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro' 
-             and 'Orbit'/'Sphere'
-           * Samsung MPC-C10, MPC-C30
-	   * Creative Webcam 5, Pro Ex
-	   * SOTEC Afina Eye
-	   * Visionite VCS-UC300, VCS-UM100
-	   
-	  The PCA635, PCVC665 and PCVC720/20 are not supported by this driver
-	  and never will be, but the 665 and 720/20 are supported by other 
-	  drivers.
-
-	  This driver has an optional plugin (called PWCX), which is 
-	  distributed as a binary module only. It contains code that allow you 
-	  to use higher resolutions and framerates but may not be distributed 
-	  as source. But even without this plugin you can these cams for most
-	  applications.
-
-	  See <file:Documentation/usb/philips.txt> for more information and
-	  installation instructions.
-
-	  The built-in microphone is enabled by selecting USB Audio support.
-
-	  This driver uses the Video For Linux API. You must say Y or M to
-	  "Video For Linux" (under Character Devices) to use this driver.
-	  Information on this API and pointers to "v4l" programs may be found
-	  at <file:Documentation/video4linux/API.html>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called pwc.
-
 config USB_SE401
 	tristate "USB SE401 Camera support"
 	depends on USB && VIDEO_DEV
@@ -163,11 +123,11 @@ config USB_SE401
 	  module will be called se401.
 
 config USB_SN9C102
-	tristate "USB SN9C10[12] PC Camera Controller support (EXPERIMENTAL)"
-	depends on USB && VIDEO_DEV && EXPERIMENTAL
+	tristate "USB SN9C10[12] PC Camera Controller support"
+	depends on USB && VIDEO_DEV
 	---help---
-	  Say Y here if you want support for cameras based on SN9C101 and
-	  SN9C102 PC Camera Controllers.
+	  Say Y here if you want support for cameras based on SONiX SN9C101
+	  or SN9C102 PC Camera Controllers.
 
 	  See <file:Documentation/usb/sn9c102.txt> for more informations.
 
diff --git a/drivers/usb/media/Makefile b/drivers/usb/media/Makefile
index 059764cd4..9f0a31eb6 100644
--- a/drivers/usb/media/Makefile
+++ b/drivers/usb/media/Makefile
@@ -2,15 +2,13 @@
 # Makefile for USB Media drivers
 #
 
-pwc-objs	:= pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o
-sn9c102-objs	:= sn9c102_core.o sn9c102_pas106b.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o
+sn9c102-objs	:= sn9c102_core.o sn9c102_pas106b.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o sn9c102_pas202bcb.o
 
 obj-$(CONFIG_USB_DABUSB)	+= dabusb.o
 obj-$(CONFIG_USB_DSBR)		+= dsbr100.o
 obj-$(CONFIG_USB_IBMCAM)	+= ibmcam.o usbvideo.o ultracam.o
 obj-$(CONFIG_USB_KONICAWC)	+= konicawc.o usbvideo.o
 obj-$(CONFIG_USB_OV511)		+= ov511.o
-obj-$(CONFIG_USB_PWC)		+= pwc.o
 obj-$(CONFIG_USB_SE401)		+= se401.o
 obj-$(CONFIG_USB_SN9C102)	+= sn9c102.o
 obj-$(CONFIG_USB_STV680)	+= stv680.o
diff --git a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c
index 01f77cbc4..0e5425f32 100644
--- a/drivers/usb/media/dabusb.c
+++ b/drivers/usb/media/dabusb.c
@@ -61,7 +61,7 @@
 
 static dabusb_t dabusb[NRDABUSB];
 static int buffers = 256;
-extern struct usb_driver dabusb_driver;
+static struct usb_driver dabusb_driver;
 
 /*-------------------------------------------------------------------*/
 
@@ -868,7 +868,7 @@ MODULE_AUTHOR( DRIVER_AUTHOR );
 MODULE_DESCRIPTION( DRIVER_DESC );
 MODULE_LICENSE("GPL");
 
-MODULE_PARM (buffers, "i");
+module_param(buffers, int, 0);
 MODULE_PARM_DESC (buffers, "Number of buffers (default=256)");
 
 module_init (dabusb_init);
diff --git a/drivers/usb/media/dsbr100.c b/drivers/usb/media/dsbr100.c
index f6b18a218..7503f5b96 100644
--- a/drivers/usb/media/dsbr100.c
+++ b/drivers/usb/media/dsbr100.c
@@ -107,7 +107,7 @@ static int usb_dsbr100_open(struct inode *inode, struct file *file);
 static int usb_dsbr100_close(struct inode *inode, struct file *file);
 
 static int radio_nr = -1;
-MODULE_PARM(radio_nr, "i");
+module_param(radio_nr, int, 0);
 
 /* Data for one (physical) device */
 typedef struct {
diff --git a/drivers/usb/media/ibmcam.c b/drivers/usb/media/ibmcam.c
index 2740aeb0f..277d65b38 100644
--- a/drivers/usb/media/ibmcam.c
+++ b/drivers/usb/media/ibmcam.c
@@ -124,38 +124,38 @@ static int init_model2_yb = -1;
 /* Settings for camera model 3 */
 static int init_model3_input = 0;
 
-MODULE_PARM(debug, "i");
+module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
-MODULE_PARM(flags, "i");
+module_param(flags, int, 0);
 MODULE_PARM_DESC(flags, "Bitfield: 0=VIDIOCSYNC, 1=B/W, 2=show hints, 3=show stats, 4=test pattern, 5=separate frames, 6=clean frames");
-MODULE_PARM(framerate, "i");
+module_param(framerate, int, 0);
 MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)");
-MODULE_PARM(lighting, "i");
+module_param(lighting, int, 0);
 MODULE_PARM_DESC(lighting, "Photosensitivity: 0=bright, 1=medium (default), 2=low light");
-MODULE_PARM(sharpness, "i");
+module_param(sharpness, int, 0);
 MODULE_PARM_DESC(sharpness, "Model1 noise reduction: 0=smooth, 6=sharp (default=4)");
-MODULE_PARM(size, "i");
+module_param(size, int, 0);
 MODULE_PARM_DESC(size, "Image size: 0=128x96 1=160x120 2=176x144 3=320x240 4=352x240 5=352x288 6=640x480  (default=5)");
-MODULE_PARM(init_brightness, "i");
+module_param(init_brightness, int, 0);
 MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)");
-MODULE_PARM(init_contrast, "i");
+module_param(init_contrast, int, 0);
 MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)");
-MODULE_PARM(init_color, "i");
+module_param(init_color, int, 0);
 MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)");
-MODULE_PARM(init_hue, "i");
+module_param(init_hue, int, 0);
 MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)");
-MODULE_PARM(hue_correction, "i");
+module_param(hue_correction, int, 0);
 MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)");
 
-MODULE_PARM(init_model2_rg2, "i");
+module_param(init_model2_rg2, int, 0);
 MODULE_PARM_DESC(init_model2_rg2, "Model2 preconfiguration: 0-255 (default=47)");
-MODULE_PARM(init_model2_sat, "i");
+module_param(init_model2_sat, int, 0);
 MODULE_PARM_DESC(init_model2_sat, "Model2 preconfiguration: 0-255 (default=52)");
-MODULE_PARM(init_model2_yb, "i");
+module_param(init_model2_yb, int, 0);
 MODULE_PARM_DESC(init_model2_yb, "Model2 preconfiguration: 0-255 (default=160)");
 
 /* 01.01.08 - Added for RCA video in support -LO */
-MODULE_PARM(init_model3_input, "i");
+module_param(init_model3_input, int, 0);
 MODULE_PARM_DESC(init_model3_input, "Model3 input: 0=CCD 1=RCA");
 
 MODULE_AUTHOR ("Dmitri");
diff --git a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c
index 5fc52c5d3..3376654ca 100644
--- a/drivers/usb/media/konicawc.c
+++ b/drivers/usb/media/konicawc.c
@@ -68,7 +68,7 @@ static const int debug = 0;
 /* Some default values for initial camera settings,
    can be set by modprobe */
 
-static enum frame_sizes size;	
+static int size;	
 static int speed = 6;		/* Speed (fps) 0 (slowest) to 6 (fastest) */
 static int brightness =	MAX_BRIGHTNESS/2;
 static int contrast =	MAX_CONTRAST/2;
@@ -362,8 +362,8 @@ static void konicawc_isoc_irq(struct urb *urb, struct pt_regs *regs)
 		else if (!urb->status && !cam->last_data_urb->status)
 			len = konicawc_compress_iso(uvd, cam->last_data_urb, urb);
 
-		resubmit_urb(uvd, urb);
 		resubmit_urb(uvd, cam->last_data_urb);
+		resubmit_urb(uvd, urb);
 		cam->last_data_urb = NULL;
 		uvd->stats.urb_length = len;
 		uvd->stats.data_count += len;
@@ -928,23 +928,23 @@ MODULE_DEVICE_TABLE(usb, id_table);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_PARM(speed, "i");
+module_param(speed, int, 0);
 MODULE_PARM_DESC(speed, "Initial speed: 0 (slowest) - 6 (fastest)");
-MODULE_PARM(size, "i");
+module_param(size, int, 0);
 MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 160x136 2: 176x144 3: 320x240");
-MODULE_PARM(brightness, "i");
+module_param(brightness, int, 0);
 MODULE_PARM_DESC(brightness, "Initial brightness 0 - 108");
-MODULE_PARM(contrast, "i");
+module_param(contrast, int, 0);
 MODULE_PARM_DESC(contrast, "Initial contrast 0 - 108");
-MODULE_PARM(saturation, "i");
+module_param(saturation, int, 0);
 MODULE_PARM_DESC(saturation, "Initial saturation 0 - 108");
-MODULE_PARM(sharpness, "i");
+module_param(sharpness, int, 0);
 MODULE_PARM_DESC(sharpness, "Initial brightness 0 - 108");
-MODULE_PARM(whitebal, "i");
+module_param(whitebal, int, 0);
 MODULE_PARM_DESC(whitebal, "Initial white balance 0 - 363");
 
 #ifdef CONFIG_USB_DEBUG
-MODULE_PARM(debug, "i");
+module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
 #endif
 
diff --git a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c
index 529a2de54..d040c8e30 100644
--- a/drivers/usb/media/ov511.c
+++ b/drivers/usb/media/ov511.c
@@ -119,78 +119,79 @@ static int remove_zeros;
 static int mirror;
 static int ov518_color;
 
-MODULE_PARM(autobright, "i");
+module_param(autobright, int, 0);
 MODULE_PARM_DESC(autobright, "Sensor automatically changes brightness");
-MODULE_PARM(autogain, "i");
+module_param(autogain, int, 0);
 MODULE_PARM_DESC(autogain, "Sensor automatically changes gain");
-MODULE_PARM(autoexp, "i");
+module_param(autoexp, int, 0);
 MODULE_PARM_DESC(autoexp, "Sensor automatically changes exposure");
-MODULE_PARM(debug, "i");
+module_param(debug, int, 0);
 MODULE_PARM_DESC(debug,
   "Debug level: 0=none, 1=inits, 2=warning, 3=config, 4=functions, 5=max");
-MODULE_PARM(snapshot, "i");
+module_param(snapshot, int, 0);
 MODULE_PARM_DESC(snapshot, "Enable snapshot mode");
-MODULE_PARM(cams, "i");
+module_param(cams, int, 0);
 MODULE_PARM_DESC(cams, "Number of simultaneous cameras");
-MODULE_PARM(compress, "i");
+module_param(compress, int, 0);
 MODULE_PARM_DESC(compress, "Turn on compression");
-MODULE_PARM(testpat, "i");
+module_param(testpat, int, 0);
 MODULE_PARM_DESC(testpat,
   "Replace image with vertical bar testpattern (only partially working)");
-MODULE_PARM(dumppix, "i");
+module_param(dumppix, int, 0);
 MODULE_PARM_DESC(dumppix, "Dump raw pixel data");
-MODULE_PARM(led, "i");
+module_param(led, int, 0);
 MODULE_PARM_DESC(led,
   "LED policy (OV511+ or later). 0=off, 1=on (default), 2=auto (on when open)");
-MODULE_PARM(dump_bridge, "i");
+module_param(dump_bridge, int, 0);
 MODULE_PARM_DESC(dump_bridge, "Dump the bridge registers");
-MODULE_PARM(dump_sensor, "i");
+module_param(dump_sensor, int, 0);
 MODULE_PARM_DESC(dump_sensor, "Dump the sensor registers");
-MODULE_PARM(printph, "i");
+module_param(printph, int, 0);
 MODULE_PARM_DESC(printph, "Print frame start/end headers");
-MODULE_PARM(phy, "i");
+module_param(phy, int, 0);
 MODULE_PARM_DESC(phy, "Prediction range (horiz. Y)");
-MODULE_PARM(phuv, "i");
+module_param(phuv, int, 0);
 MODULE_PARM_DESC(phuv, "Prediction range (horiz. UV)");
-MODULE_PARM(pvy, "i");
+module_param(pvy, int, 0);
 MODULE_PARM_DESC(pvy, "Prediction range (vert. Y)");
-MODULE_PARM(pvuv, "i");
+module_param(pvuv, int, 0);
 MODULE_PARM_DESC(pvuv, "Prediction range (vert. UV)");
-MODULE_PARM(qhy, "i");
+module_param(qhy, int, 0);
 MODULE_PARM_DESC(qhy, "Quantization threshold (horiz. Y)");
-MODULE_PARM(qhuv, "i");
+module_param(qhuv, int, 0);
 MODULE_PARM_DESC(qhuv, "Quantization threshold (horiz. UV)");
-MODULE_PARM(qvy, "i");
+module_param(qvy, int, 0);
 MODULE_PARM_DESC(qvy, "Quantization threshold (vert. Y)");
-MODULE_PARM(qvuv, "i");
+module_param(qvuv, int, 0);
 MODULE_PARM_DESC(qvuv, "Quantization threshold (vert. UV)");
-MODULE_PARM(lightfreq, "i");
+module_param(lightfreq, int, 0);
 MODULE_PARM_DESC(lightfreq,
   "Light frequency. Set to 50 or 60 Hz, or zero for default settings");
-MODULE_PARM(bandingfilter, "i");
+module_param(bandingfilter, int, 0);
 MODULE_PARM_DESC(bandingfilter,
   "Enable banding filter (to reduce effects of fluorescent lighting)");
-MODULE_PARM(clockdiv, "i");
+module_param(clockdiv, int, 0);
 MODULE_PARM_DESC(clockdiv, "Force pixel clock divisor to a specific value");
-MODULE_PARM(packetsize, "i");
+module_param(packetsize, int, 0);
 MODULE_PARM_DESC(packetsize, "Force a specific isoc packet size");
-MODULE_PARM(framedrop, "i");
+module_param(framedrop, int, 0);
 MODULE_PARM_DESC(framedrop, "Force a specific frame drop register setting");
-MODULE_PARM(fastset, "i");
+module_param(fastset, int, 0);
 MODULE_PARM_DESC(fastset, "Allows picture settings to take effect immediately");
-MODULE_PARM(force_palette, "i");
+module_param(force_palette, int, 0);
 MODULE_PARM_DESC(force_palette, "Force the palette to a specific value");
-MODULE_PARM(backlight, "i");
+module_param(backlight, int, 0);
 MODULE_PARM_DESC(backlight, "For objects that are lit from behind");
-MODULE_PARM(unit_video, "1-" __MODULE_STRING(OV511_MAX_UNIT_VIDEO) "i");
+static int num_uv;
+module_param_array(unit_video, int, num_uv, 0);
 MODULE_PARM_DESC(unit_video,
   "Force use of specific minor number(s). 0 is not allowed.");
-MODULE_PARM(remove_zeros, "i");
+module_param(remove_zeros, int, 0);
 MODULE_PARM_DESC(remove_zeros,
   "Remove zero-padding from uncompressed incoming data");
-MODULE_PARM(mirror, "i");
+module_param(mirror, int, 0);
 MODULE_PARM_DESC(mirror, "Reverse image horizontally");
-MODULE_PARM(ov518_color, "i");
+module_param(ov518_color, int, 0);
 MODULE_PARM_DESC(ov518_color, "Enable OV518 color (experimental)");
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
@@ -472,7 +473,7 @@ ov518_reg_w32(struct usb_ov511 *ov, unsigned char reg, u32 val, int n)
 
 	down(&ov->cbuf_lock);
 
-	*((u32 *)ov->cbuf) = __cpu_to_le32(val);
+	*((__le32 *)ov->cbuf) = __cpu_to_le32(val);
 
 	rc = usb_control_msg(ov->dev,
 			     usb_sndctrlpipe(ov->dev, 0),
@@ -1169,7 +1170,7 @@ init_ov_sensor(struct usb_ov511 *ov)
 		return -EIO;
 
 	/* Wait for it to initialize */
-	schedule_timeout(1 + 150 * HZ / 1000);
+	msleep(150);
 
 	for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {
 		if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) &&
@@ -1182,7 +1183,7 @@ init_ov_sensor(struct usb_ov511 *ov)
 		if (i2c_w(ov, 0x12, 0x80) < 0)
 			return -EIO;
 		/* Wait for it to initialize */
-		schedule_timeout(1 + 150 * HZ / 1000);
+		msleep(150);
 		/* Dummy read to sync I2C */
 		if (i2c_r(ov, 0x00) < 0)
 			return -EIO;
@@ -4947,7 +4948,7 @@ ov7xx0_configure(struct usb_ov511 *ov)
 			return -1;
 
 		/* Wait for it to initialize */
-		schedule_timeout(1 + 150 * HZ / 1000);
+		msleep(150);
 
 		i = 0;
 		success = 0;
diff --git a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c
index 260bbd98b..c694caaac 100644
--- a/drivers/usb/media/se401.c
+++ b/drivers/usb/media/se401.c
@@ -53,9 +53,9 @@ MODULE_DEVICE_TABLE(usb, device_table);
 MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>");
 MODULE_DESCRIPTION("SE401 USB Camera Driver");
 MODULE_LICENSE("GPL");
-MODULE_PARM(flickerless, "i");
+module_param(flickerless, int, 0);
 MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)");
-MODULE_PARM(video_nr, "i");
+module_param(video_nr, int, 0);
 
 static struct usb_driver se401_driver;
 
diff --git a/drivers/usb/media/sn9c102.h b/drivers/usb/media/sn9c102.h
index fc9cb47e6..62ff21443 100644
--- a/drivers/usb/media/sn9c102.h
+++ b/drivers/usb/media/sn9c102.h
@@ -31,6 +31,7 @@
 #include <linux/types.h>
 #include <linux/param.h>
 #include <linux/rwsem.h>
+#include <asm/semaphore.h>
 
 #include "sn9c102_sensor.h"
 
@@ -39,6 +40,7 @@
 #define SN9C102_DEBUG
 #define SN9C102_DEBUG_LEVEL       2
 #define SN9C102_MAX_DEVICES       64
+#define SN9C102_PRESERVE_IMGSCALE 0
 #define SN9C102_MAX_FRAMES        32
 #define SN9C102_URBS              2
 #define SN9C102_ISO_PACKETS       7
@@ -51,8 +53,8 @@
 #define SN9C102_MODULE_AUTHOR   "(C) 2004 Luca Risolia"
 #define SN9C102_AUTHOR_EMAIL    "<luca.risolia@studio.unibo.it>"
 #define SN9C102_MODULE_LICENSE  "GPL"
-#define SN9C102_MODULE_VERSION  "1:1.01-beta"
-#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 1)
+#define SN9C102_MODULE_VERSION  "1:1.08"
+#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 8)
 
 SN9C102_ID_TABLE;
 SN9C102_SENSOR_TABLE;
diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c
index bcd9fbd3b..9f775f740 100644
--- a/drivers/usb/media/sn9c102_core.c
+++ b/drivers/usb/media/sn9c102_core.c
@@ -31,6 +31,7 @@
 #include <linux/time.h>
 #include <linux/delay.h>
 #include <linux/stddef.h>
+#include <linux/compiler.h>
 #include <linux/ioctl.h>
 #include <linux/poll.h>
 #include <linux/stat.h>
@@ -83,7 +84,7 @@ MODULE_PARM_DESC(debug,
 
 /*****************************************************************************/
 
-typedef char sn9c102_sof_header_t[7];
+typedef char sn9c102_sof_header_t[12];
 typedef char sn9c102_eof_header_t[4];
 
 static sn9c102_sof_header_t sn9c102_sof_header[] = {
@@ -91,8 +92,6 @@ static sn9c102_sof_header_t sn9c102_sof_header[] = {
 	{0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x01},
 };
 
-/* Number of random bytes that complete the SOF above headers */
-#define SN9C102_SOFLEN 5
 
 static sn9c102_eof_header_t sn9c102_eof_header[] = {
 	{0x00, 0x00, 0x00, 0x00},
@@ -237,9 +236,6 @@ int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index)
 	u8* buff = cam->control_buffer;
 	int res;
 
-	if (index == 0x18)
-		value = (value & 0xcf) | (cam->reg[0x18] & 0x30);
-
 	*buff = value;
 
 	res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
@@ -443,14 +439,15 @@ int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value)
 
 static void* sn9c102_find_sof_header(void* mem, size_t len)
 {
-	size_t soflen=sizeof(sn9c102_sof_header_t), SOFLEN=SN9C102_SOFLEN, i;
+	size_t soflen = sizeof(sn9c102_sof_header_t), i;
 	u8 j, n = sizeof(sn9c102_sof_header) / soflen;
 
-	for (i = 0; (len >= soflen+SOFLEN) && (i <= len-soflen-SOFLEN); i++)
+	for (i = 0; (len >= soflen) && (i <= len - soflen); i++)
 		for (j = 0; j < n; j++)
-			if (!memcmp(mem + i, sn9c102_sof_header[j], soflen))
+			/* It's enough to compare 7 bytes */
+			if (!memcmp(mem + i, sn9c102_sof_header[j], 7))
 				/* Skips the header */
-				return mem + i + soflen + SOFLEN;
+				return mem + i + soflen;
 
 	return NULL;
 }
@@ -517,10 +514,12 @@ static void sn9c102_urb_complete(struct urb *urb, struct pt_regs* regs)
 
 		PDBGG("Isochrnous frame: length %u, #%u i", len, i)
 
-		/* NOTE: It is probably correct to assume that SOF and EOF
+		/*
+		   NOTE: It is probably correct to assume that SOF and EOF
 		         headers do not occur between two consecutive packets,
 		         but who knows..Whatever is the truth, this assumption
-		         doesn't introduce bugs. */
+		         doesn't introduce bugs.
+		*/
 
 redo:
 		sof = sn9c102_find_sof_header(pos, len);
@@ -764,9 +763,11 @@ static u8 sn9c102_strtou8(const char* buff, size_t len, ssize_t* count)
 	return (u8)val;
 }
 
-/* NOTE 1: being inside one of the following methods implies that the v4l
+/*
+   NOTE 1: being inside one of the following methods implies that the v4l
            device exists for sure (see kobjects and reference counters)
-   NOTE 2: buffers are PAGE_SIZE long */
+   NOTE 2: buffers are PAGE_SIZE long
+*/
 
 static ssize_t sn9c102_show_reg(struct class_device* cd, char* buf)
 {
@@ -1018,24 +1019,6 @@ sn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len)
 }
 
 
-static ssize_t
-sn9c102_store_redblue(struct class_device* cd, const char* buf, size_t len)
-{
-	ssize_t res = 0;
-	u8 value;
-	ssize_t count;
-
-	value = sn9c102_strtou8(buf, len, &count);
-	if (!count)
-		return -EINVAL;
-
-	if ((res = sn9c102_store_reg(cd, "0x10", 4)) >= 0)
-		res = sn9c102_store_val(cd, buf, len);
-
-	return res;
-}
-
-
 static ssize_t
 sn9c102_store_green(struct class_device* cd, const char* buf, size_t len)
 {
@@ -1062,7 +1045,6 @@ static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR,
                          sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);
 static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
                          sn9c102_show_i2c_val, sn9c102_store_i2c_val);
-static CLASS_DEVICE_ATTR(redblue, S_IWUGO, NULL, sn9c102_store_redblue);
 static CLASS_DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green);
 
 
@@ -1072,7 +1054,6 @@ static void sn9c102_create_sysfs(struct sn9c102_device* cam)
 
 	video_device_create_file(v4ldev, &class_device_attr_reg);
 	video_device_create_file(v4ldev, &class_device_attr_val);
-	video_device_create_file(v4ldev, &class_device_attr_redblue);
 	video_device_create_file(v4ldev, &class_device_attr_green);
 	if (cam->sensor->slave_write_id && cam->sensor->slave_read_id) {
 		video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
@@ -1118,10 +1099,6 @@ static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect)
 	   ae_endy = v_size / 2;
 	int err = 0;
 
-	/* These are a sort of stroboscopic signal for some sensors */
-	err += sn9c102_write_reg(cam, h_size, 0x1a);
-	err += sn9c102_write_reg(cam, v_size, 0x1b);
-
 	err += sn9c102_write_reg(cam, h_start, 0x12);
 	err += sn9c102_write_reg(cam, v_start, 0x13);
 	err += sn9c102_write_reg(cam, h_size, 0x15);
@@ -1134,8 +1111,7 @@ static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect)
 		return -EIO;
 
 	PDBGG("h_start, v_start, h_size, v_size, ho_size, vo_size "
-	      "%u %u %u %u %u %u", h_start, v_start, h_size, v_size, ho_size,
-	      vo_size)
+	      "%u %u %u %u", h_start, v_start, h_size, v_size)
 
 	return 0;
 }
@@ -1229,7 +1205,10 @@ static int sn9c102_open(struct inode* inode, struct file* filp)
 	struct sn9c102_device* cam;
 	int err = 0;
 
-	/* This the only safe way to prevent race conditions with disconnect */
+	/*
+	   This is the only safe way to prevent race conditions with
+	   disconnect
+	*/
 	if (!down_read_trylock(&sn9c102_disconnect))
 		return -ERESTARTSYS;
 
@@ -1727,6 +1706,12 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp,
 				return -EINVAL;
 			}
 
+		/* Preserve R,G or B origin */
+		rect->left = (s->_rect.left & 1L) ?
+		             rect->left | 1L : rect->left & ~1L;
+		rect->top = (s->_rect.top & 1L) ?
+		            rect->top | 1L : rect->top & ~1L;
+
 		if (rect->width < 16)
 			rect->width = 16;
 		if (rect->height < 16)
@@ -1747,13 +1732,15 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp,
 		rect->width &= ~15L;
 		rect->height &= ~15L;
 
-		{ /* calculate the scaling factor */
+		if (SN9C102_PRESERVE_IMGSCALE) {
+			/* Calculate the actual scaling factor */
 			u32 a, b;
 			a = rect->width * rect->height;
 			b = pix_format->width * pix_format->height;
-			scale = b ? (u8)((a / b) <= 1 ? 1 : ((a / b) == 3 ? 2 :
-			            ((a / b) > 4 ? 4 : (a / b)))) : 1;
-		}
+			scale = b ? (u8)((a / b) < 4 ? 1 :
+		                        ((a / b) < 16 ? 2 : 4)) : 1;
+		} else
+			scale = 1;
 
 		if (cam->stream == STREAM_ON) {
 			cam->stream = STREAM_INTERRUPT;
@@ -1879,12 +1866,12 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp,
 
 		memcpy(&rect, &(s->_rect), sizeof(rect));
 
-		{ /* calculate the scaling factor */
+		{ /* calculate the actual scaling factor */
 			u32 a, b;
 			a = rect.width * rect.height;
 			b = pix->width * pix->height;
-			scale = b ? (u8)((a / b) <= 1 ? 1 : ((a / b) == 3 ? 2 :
-			            ((a / b) > 4 ? 4 : (a / b)))) : 1;
+			scale = b ? (u8)((a / b) < 4 ? 1 :
+		                        ((a / b) < 16 ? 2 : 4)) : 1;
 		}
 
 		rect.width = scale * pix->width;
@@ -1895,13 +1882,21 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp,
 		if (rect.height < 16)
 			rect.height = 16;
 		if (rect.width > bounds->left + bounds->width - rect.left)
-			rect.width = bounds->left+bounds->width - rect.left;
+			rect.width = bounds->left + bounds->width - rect.left;
 		if (rect.height > bounds->top + bounds->height - rect.top)
 			rect.height = bounds->top + bounds->height - rect.top;
 
 		rect.width &= ~15L;
 		rect.height &= ~15L;
 
+		{ /* adjust the scaling factor */
+			u32 a, b;
+			a = rect.width * rect.height;
+			b = pix->width * pix->height;
+			scale = b ? (u8)((a / b) < 4 ? 1 :
+		                        ((a / b) < 16 ? 2 : 4)) : 1;
+		}
+
 		pix->width = rect.width / scale;
 		pix->height = rect.height / scale;
 
@@ -2119,7 +2114,7 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp,
 		spin_lock_irqsave(&cam->queue_lock, lock_flags);
 		f = list_entry(cam->outqueue.next, struct sn9c102_frame_t,
 		               frame);
-		list_del(&cam->outqueue);
+		list_del(cam->outqueue.next);
 		spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
 
 		f->state = F_UNUSED;
diff --git a/drivers/usb/media/sn9c102_pas106b.c b/drivers/usb/media/sn9c102_pas106b.c
index 34bdfcf8e..a302a4845 100644
--- a/drivers/usb/media/sn9c102_pas106b.c
+++ b/drivers/usb/media/sn9c102_pas106b.c
@@ -40,13 +40,12 @@ static int pas106b_init(struct sn9c102_device* cam)
 	err += sn9c102_i2c_write(cam, 0x02, 0x0c);
 	err += sn9c102_i2c_write(cam, 0x03, 0x12);
 	err += sn9c102_i2c_write(cam, 0x04, 0x05);
-	err += sn9c102_i2c_write(cam, 0x05, 0x22);
-	err += sn9c102_i2c_write(cam, 0x06, 0xac);
-	err += sn9c102_i2c_write(cam, 0x07, 0x00);
+	err += sn9c102_i2c_write(cam, 0x05, 0x5a);
+	err += sn9c102_i2c_write(cam, 0x06, 0x88);
+	err += sn9c102_i2c_write(cam, 0x07, 0x80);
 	err += sn9c102_i2c_write(cam, 0x08, 0x01);
-	err += sn9c102_i2c_write(cam, 0x0a, 0x00);
+	err += sn9c102_i2c_write(cam, 0x0a, 0x01);
 	err += sn9c102_i2c_write(cam, 0x0b, 0x00);
-	err += sn9c102_i2c_write(cam, 0x0d, 0x00);
 	err += sn9c102_i2c_write(cam, 0x10, 0x06);
 	err += sn9c102_i2c_write(cam, 0x11, 0x06);
 	err += sn9c102_i2c_write(cam, 0x12, 0x00);
@@ -64,11 +63,30 @@ static int pas106b_get_ctrl(struct sn9c102_device* cam,
 {
 	switch (ctrl->id) {
 	case V4L2_CID_RED_BALANCE:
-		return (ctrl->value = sn9c102_i2c_read(cam, 0x0c))<0 ? -EIO:0;
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0)
+			return -EIO;
+		ctrl->value &= 0x1f;
+		return 0;
 	case V4L2_CID_BLUE_BALANCE:
-		return (ctrl->value = sn9c102_i2c_read(cam, 0x09))<0 ? -EIO:0;
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0)
+			return -EIO;
+		ctrl->value &= 0x1f;
+		return 0;
+	case V4L2_CID_GAIN:
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x0e)) < 0)
+			return -EIO;
+		ctrl->value &= 0x1f;
+		return 0;
 	case V4L2_CID_BRIGHTNESS:
-		return (ctrl->value = sn9c102_i2c_read(cam, 0x0e))<0 ? -EIO:0;
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x0d)) < 0)
+			return -EIO;
+		ctrl->value &= 0x1f;
+		return 0;
+	case V4L2_CID_CONTRAST:
+		if ((ctrl->value = sn9c102_i2c_read(cam, 0x0f)) < 0)
+			return -EIO;
+		ctrl->value &= 0x07;
+		return 0;
 	default:
 		return -EINVAL;
 	}
@@ -87,9 +105,15 @@ static int pas106b_set_ctrl(struct sn9c102_device* cam,
 	case V4L2_CID_BLUE_BALANCE:
 		err += sn9c102_i2c_write(cam, 0x09, ctrl->value & 0x1f);
 		break;
-	case V4L2_CID_BRIGHTNESS:
+	case V4L2_CID_GAIN:
 		err += sn9c102_i2c_write(cam, 0x0e, ctrl->value & 0x1f);
 		break;
+	case V4L2_CID_BRIGHTNESS:
+		err += sn9c102_i2c_write(cam, 0x0d, 0x1f-(ctrl->value & 0x1f));
+		break;
+	case V4L2_CID_CONTRAST:
+		err += sn9c102_i2c_write(cam, 0x0f, ctrl->value & 0x03);
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -130,7 +154,7 @@ static struct sn9c102_sensor pas106b = {
 			.minimum = 0x00,
 			.maximum = 0x1f,
 			.step = 0x01,
-			.default_value = 0x03,
+			.default_value = 0x04,
 			.flags = 0,
 		},
 		{
@@ -140,7 +164,17 @@ static struct sn9c102_sensor pas106b = {
 			.minimum = 0x00,
 			.maximum = 0x1f,
 			.step = 0x01,
-			.default_value = 0x02,
+			.default_value = 0x06,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_GAIN,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "global gain",
+			.minimum = 0x00,
+			.maximum = 0x1f,
+			.step = 0x01,
+			.default_value = 0x0d,
 			.flags = 0,
 		},
 		{
@@ -150,7 +184,17 @@ static struct sn9c102_sensor pas106b = {
 			.minimum = 0x00,
 			.maximum = 0x1f,
 			.step = 0x01,
-			.default_value = 0x06,
+			.default_value = 0x1f,
+			.flags = 0,
+		},
+		{
+			.id = V4L2_CID_CONTRAST,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "contrast",
+			.minimum = 0x00,
+			.maximum = 0x07,
+			.step = 0x01,
+			.default_value = 0x00, /* 0x00~0x03 have same effect */
 			.flags = 0,
 		},
 	},
@@ -185,11 +229,13 @@ int sn9c102_probe_pas106b(struct sn9c102_device* cam)
 	int r0 = 0, r1 = 0, err = 0;
 	unsigned int pid = 0;
 
-	/* Minimal initialization to enable the I2C communication
-	   NOTE: do NOT change the values! */
+	/*
+	   Minimal initialization to enable the I2C communication
+	   NOTE: do NOT change the values!
+	*/
 	err += sn9c102_write_reg(cam, 0x01, 0x01); /* sensor power down */
 	err += sn9c102_write_reg(cam, 0x00, 0x01); /* sensor power on */
-	err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 48 MHz */
+	err += sn9c102_write_reg(cam, 0x28, 0x17); /* sensor clock at 24 MHz */
 	if (err)
 		return -EIO;
 
diff --git a/drivers/usb/media/sn9c102_sensor.h b/drivers/usb/media/sn9c102_sensor.h
index 54a3499b5..3e7e4a257 100644
--- a/drivers/usb/media/sn9c102_sensor.h
+++ b/drivers/usb/media/sn9c102_sensor.h
@@ -33,7 +33,8 @@ struct sn9c102_sensor;
 
 /*****************************************************************************/
 
-/* OVERVIEW.
+/*
+   OVERVIEW.
    This is a small interface that allows you to add support for any CCD/CMOS
    image sensors connected to the SN9C10X bridges. The entire API is documented
    below. In the most general case, to support a sensor there are three steps
@@ -48,26 +49,33 @@ struct sn9c102_sensor;
    "sn9c102_pas106b.c" is an example of all this stuff. Remember that you do
    NOT need to touch the source code of the core module for the things to work
    properly, unless you find bugs or flaws in it. Finally, do not forget to
-   read the V4L2 API for completeness. */
+   read the V4L2 API for completeness.
+*/
 
 /*****************************************************************************/
- 
-/* Probing functions: on success, you must attach the sensor to the camera
+
+/*
+   Probing functions: on success, you must attach the sensor to the camera
    by calling sn9c102_attach_sensor() provided below.
    To enable the I2C communication, you might need to perform a really basic
    initialization of the SN9C10X chip by using the write function declared 
    ahead.
-   Functions must return 0 on success, the appropriate error otherwise. */
+   Functions must return 0 on success, the appropriate error otherwise.
+*/
 extern int sn9c102_probe_pas106b(struct sn9c102_device* cam);
+extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam);
 extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam);
 extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
 
-/* Add the above entries to this table. Be sure to add the entry in the right
+/*
+   Add the above entries to this table. Be sure to add the entry in the right
    place, since, on failure, the next probing routine is called according to 
-   the order of the list below, from top to bottom */
+   the order of the list below, from top to bottom.
+*/
 #define SN9C102_SENSOR_TABLE                                                  \
 static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = {              \
-	&sn9c102_probe_pas106b, /* strong detection based on SENSOR vid/pid */\
+	&sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */    \
+	&sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */  \
 	&sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */       \
 	&sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */       \
 	NULL,                                                                 \
@@ -81,28 +89,29 @@ sn9c102_attach_sensor(struct sn9c102_device* cam,
 /* Each SN9C10X camera has proper PID/VID identifiers. Add them here in case.*/
 #define SN9C102_ID_TABLE                                                      \
 static const struct usb_device_id sn9c102_id_table[] = {                      \
-	{ USB_DEVICE(0xc45, 0x6001), },                                       \
+	{ USB_DEVICE(0xc45, 0x6001), }, /* TAS5110C1B */                      \
 	{ USB_DEVICE(0xc45, 0x6005), }, /* TAS5110C1B */                      \
 	{ USB_DEVICE(0xc45, 0x6009), }, /* PAS106B */                         \
 	{ USB_DEVICE(0xc45, 0x600d), }, /* PAS106B */                         \
 	{ USB_DEVICE(0xc45, 0x6024), },                                       \
-	{ USB_DEVICE(0xc45, 0x6025), }, /* TAS5130D1B Maybe also TAS5110C1B */\
-	{ USB_DEVICE(0xc45, 0x6028), }, /* Maybe PAS202B */                   \
-	{ USB_DEVICE(0xc45, 0x6029), },                                       \
-	{ USB_DEVICE(0xc45, 0x602a), }, /* Maybe HV7131[D|E1] */              \
-	{ USB_DEVICE(0xc45, 0x602c), }, /* Maybe OV7620 */                    \
-	{ USB_DEVICE(0xc45, 0x6030), }, /* Maybe MI03 */                      \
-	{ USB_DEVICE(0xc45, 0x8001), },                                       \
+	{ USB_DEVICE(0xc45, 0x6025), }, /* TAS5130D1B and TAS5110C1B */       \
+	{ USB_DEVICE(0xc45, 0x6028), }, /* PAS202BCB */                       \
+	{ USB_DEVICE(0xc45, 0x6029), }, /* PAS106B */                         \
+	{ USB_DEVICE(0xc45, 0x602a), }, /* HV7131[D|E1] */                    \
+	{ USB_DEVICE(0xc45, 0x602c), }, /* OV7620 */                          \
+	{ USB_DEVICE(0xc45, 0x6030), }, /* MI03 */                            \
 	{ }                                                                   \
 };
 
 /*****************************************************************************/
 
-/* Read/write routines: they always return -1 on error, 0 or the read value
+/*
+   Read/write routines: they always return -1 on error, 0 or the read value
    otherwise. NOTE that a real read operation is not supported by the SN9C10X
    chip for some of its registers. To work around this problem, a pseudo-read
    call is provided instead: it returns the last successfully written value 
-   on the register (0 if it has never been written), the usual -1 on error. */
+   on the register (0 if it has never been written), the usual -1 on error.
+*/
 
 /* The "try" I2C I/O versions are used when probing the sensor */
 extern int sn9c102_i2c_try_write(struct sn9c102_device*,struct sn9c102_sensor*,
@@ -110,10 +119,12 @@ extern int sn9c102_i2c_try_write(struct sn9c102_device*,struct sn9c102_sensor*,
 extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*,
                                 u8 address);
 
-/* This must be used if and only if the sensor doesn't implement the standard
-   I2C protocol, like the TASC sensors. There a number of good reasons why you
-   must use the single-byte versions of this function: do not abuse. It writes
-   n bytes, from data0 to datan, (registers 0x09 - 0x09+n of SN9C10X chip) */
+/*
+   This must be used if and only if the sensor doesn't implement the standard
+   I2C protocol. There a number of good reasons why you must use the 
+   single-byte versions of this function: do not abuse. It writes n bytes, 
+   from data0 to datan, (registers 0x09 - 0x09+n of SN9C10X chip).
+*/
 extern int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
                                      struct sn9c102_sensor* sensor, u8 n, 
                                      u8 data0, u8 data1, u8 data2, u8 data3,
@@ -127,12 +138,14 @@ extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address);
 extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index);
 extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index);
 
-/* NOTE: there are no debugging functions here. To uniform the output you must
+/*
+   NOTE: there are no debugging functions here. To uniform the output you must
    use the dev_info()/dev_warn()/dev_err() macros defined in device.h, already
    included here, the argument being the struct device 'dev' of the sensor
    structure. Do NOT use these macros before the sensor is attached or the
    kernel will crash! However you should not need to notify the user about
-   common errors or other messages, since this is done by the master module. */
+   common errors or other messages, since this is done by the master module.
+*/
 
 /*****************************************************************************/
 
@@ -150,24 +163,31 @@ struct sn9c102_sensor {
 	char name[32], /* sensor name */
 	     maintainer[64]; /* name of the mantainer <email> */
 
-	/* These sensor capabilities must be provided if the SN9C10X controller
+	/*
+	   These sensor capabilities must be provided if the SN9C10X controller
 	   needs to communicate through the sensor serial interface by using
-	   at least one of the i2c functions available */
+	   at least one of the i2c functions available.
+	*/
 	enum sn9c102_i2c_frequency frequency;
 	enum sn9c102_i2c_interface interface;
 
-	/* These identifiers must be provided if the image sensor implements
+	/*
+	   These identifiers must be provided if the image sensor implements
 	   the standard I2C protocol. TASC sensors don't, although they have a
 	   serial interface: so this is a case where the "raw" I2C version
-	   could be helpful. */
+	   could be helpful.
+	*/
 	u8 slave_read_id, slave_write_id; /* reg. 0x09 */
 
-	/* NOTE: Where not noted,most of the functions below are not mandatory.
+	/*
+	   NOTE: Where not noted,most of the functions below are not mandatory.
 	         Set to null if you do not implement them. If implemented,
-	         they must return 0 on success, the proper error otherwise. */
+	         they must return 0 on success, the proper error otherwise.
+	*/
 
 	int (*init)(struct sn9c102_device* cam);
-	/* This function is called after the sensor has been attached. 
+	/*
+	   This function is called after the sensor has been attached. 
 	   It should be used to initialize the sensor only, but may also
 	   configure part of the SN9C10X chip if necessary. You don't need to
 	   setup picture settings like brightness, contrast, etc.. here, if
@@ -177,23 +197,29 @@ struct sn9c102_sensor {
 	   specified in the v4l2_queryctrl list of supported controls;
 	   Same suggestions apply for other settings, _if_ the corresponding
 	   methods are present; if not, the initialization must configure the
-	   sensor according to the default configuration structures below. */
+	   sensor according to the default configuration structures below.
+	*/
 
 	struct v4l2_queryctrl qctrl[V4L2_CID_LASTP1-V4L2_CID_BASE];
-	/* Optional list of default controls, defined as indicated in the 
-	   V4L2 API. Menu type controls are not handled by this interface. */
+	/*
+	   Optional list of default controls, defined as indicated in the 
+	   V4L2 API. Menu type controls are not handled by this interface.
+	*/
 
 	int (*get_ctrl)(struct sn9c102_device* cam, struct v4l2_control* ctrl);
 	int (*set_ctrl)(struct sn9c102_device* cam,
 	                const struct v4l2_control* ctrl);
-	/* You must implement at least the set_ctrl method if you have defined
+	/*
+	   You must implement at least the set_ctrl method if you have defined
 	   the list above. The returned value must follow the V4L2
 	   specifications for the VIDIOC_G|C_CTRL ioctls. V4L2_CID_H|VCENTER
 	   are not supported by this driver, so do not implement them. Also,
-	   passed values are NOT checked to see if they are out of bounds. */
+	   passed values are NOT checked to see if they are out of bounds.
+	*/
 
 	struct v4l2_cropcap cropcap;
-	/* Think the image sensor as a grid of R,G,B monochromatic pixels
+	/*
+	   Think the image sensor as a grid of R,G,B monochromatic pixels
 	   disposed according to a particular Bayer pattern, which describes
 	   the complete array of pixels, from (0,0) to (xmax, ymax). We will
 	   use this coordinate system from now on. It is assumed the sensor
@@ -221,11 +247,13 @@ struct sn9c102_sensor {
 	   NOTE: once you have defined the bounds of the active window
 	         (struct cropcap.bounds) you must not change them.anymore.
 	   Only 'bounds' and 'defrect' fields are mandatory, other fields
-	   will be ignored. */
+	   will be ignored.
+	*/
 
 	int (*set_crop)(struct sn9c102_device* cam,
 	                const struct v4l2_rect* rect);
-	/* To be called on VIDIOC_C_SETCROP. The core module always calls a
+	/*
+	   To be called on VIDIOC_C_SETCROP. The core module always calls a
 	   default routine which configures the appropriate SN9C10X regs (also
 	   scaling), but you may need to override/adjust specific stuff.
 	   'rect' contains width and height values that are multiple of 16: in
@@ -237,10 +265,12 @@ struct sn9c102_sensor {
 	         frame after each HSYNC or VSYNC, so that the image starts with
 	         real RGB data (see regs 0x12,0x13) (having set H_SIZE and,
 	         V_SIZE you don't have to care about blank pixels or blank
-	         lines at the end of each line or frame). */
+	         lines at the end of each line or frame).
+	*/
 
 	struct v4l2_pix_format pix_format;
-	/* What you have to define here are: initial 'width' and 'height' of
+	/*
+	   What you have to define here are: initial 'width' and 'height' of
 	   the target rectangle, the bayer 'pixelformat' and 'priv' which we'll
 	   be used to indicate the number of bits per pixel, 8 or 9. 
 	   Nothing more.
@@ -249,20 +279,27 @@ struct sn9c102_sensor {
 	           suggest 1/1.
 	   NOTE 2: as said above, you have to program the SN9C10X chip to get
 	           rid of any blank pixels, so that the output of the sensor
-	           matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR). */
+	           matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR).
+	*/
 
 	const struct device* dev;
-	/* This is the argument for dev_err(), dev_info() and dev_warn(). It
+	/*
+	   This is the argument for dev_err(), dev_info() and dev_warn(). It
 	   is used for debugging purposes. You must not access the struct
-	   before the sensor is attached. */
+	   before the sensor is attached.
+	*/
 
 	const struct usb_device* usbdev;
-	/* Points to the usb_device struct after the sensor is attached.
-	   Do not touch unless you know what you are doing. */
+	/*
+	   Points to the usb_device struct after the sensor is attached.
+	   Do not touch unless you know what you are doing.
+	*/
 
-	/* Do NOT write to the data below, it's READ ONLY. It is used by the
+	/*
+	   Do NOT write to the data below, it's READ ONLY. It is used by the
 	   core module to store successfully updated values of the above
-	   settings, for rollbacks..etc..in case of errors during atomic I/O */
+	   settings, for rollbacks..etc..in case of errors during atomic I/O
+	*/
 	struct v4l2_queryctrl _qctrl[V4L2_CID_LASTP1-V4L2_CID_BASE];
 	struct v4l2_rect _rect;
 };
diff --git a/drivers/usb/media/sn9c102_tas5110c1b.c b/drivers/usb/media/sn9c102_tas5110c1b.c
index d67470013..68e1b2e0c 100644
--- a/drivers/usb/media/sn9c102_tas5110c1b.c
+++ b/drivers/usb/media/sn9c102_tas5110c1b.c
@@ -33,15 +33,33 @@ static int tas5110c1b_init(struct sn9c102_device* cam)
 	err += sn9c102_write_reg(cam, 0x44, 0x01);
 	err += sn9c102_write_reg(cam, 0x00, 0x10);
 	err += sn9c102_write_reg(cam, 0x00, 0x11);
-	err += sn9c102_write_reg(cam, 0x00, 0x14);
+	err += sn9c102_write_reg(cam, 0x0a, 0x14);
 	err += sn9c102_write_reg(cam, 0x60, 0x17);
 	err += sn9c102_write_reg(cam, 0x06, 0x18);
-	err += sn9c102_write_reg(cam, 0xcb, 0x19);
+	err += sn9c102_write_reg(cam, 0xfb, 0x19);
+
+	err += sn9c102_i2c_try_raw_write(cam, &tas5110c1b, 4, 0x11, 0x00, 0xc0,
+	                                 0x80, 0, 0);
 
 	return err;
 }
 
 
+static int tas5110c1b_set_ctrl(struct sn9c102_device* cam, 
+                               const struct v4l2_control* ctrl)
+{
+	switch (ctrl->id) {
+	case V4L2_CID_GAIN:
+		return sn9c102_i2c_try_raw_write(cam, &tas5110c1b, 4, 0x11,
+		                                 0x02, 0x20,
+		                                 0xff - (ctrl->value & 0xff),
+		                                 0, 0);
+	default:
+		return -EINVAL;
+	}
+}
+
+
 static int tas5110c1b_set_crop(struct sn9c102_device* cam, 
                                const struct v4l2_rect* rect)
 {
@@ -53,6 +71,11 @@ static int tas5110c1b_set_crop(struct sn9c102_device* cam,
 	err += sn9c102_write_reg(cam, h_start, 0x12);
 	err += sn9c102_write_reg(cam, v_start, 0x13);
 
+	/* Don't change ! */
+	err += sn9c102_write_reg(cam, 0x14, 0x1a);
+	err += sn9c102_write_reg(cam, 0x0a, 0x1b);
+	err += sn9c102_write_reg(cam, 0xfb, 0x19);
+
 	return err;
 }
 
@@ -60,7 +83,22 @@ static int tas5110c1b_set_crop(struct sn9c102_device* cam,
 static struct sn9c102_sensor tas5110c1b = {
 	.name = "TAS5110C1B",
 	.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+	.frequency = SN9C102_I2C_100KHZ,
+	.interface = SN9C102_I2C_3WIRES,
 	.init = &tas5110c1b_init,
+	.qctrl = {
+		{
+			.id = V4L2_CID_GAIN,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "global gain",
+			.minimum = 0x00,
+			.maximum = 0xff,
+			.step = 0x01,
+			.default_value = 0x48,
+			.flags = 0,
+		},
+	},
+	.set_ctrl = &tas5110c1b_set_ctrl,
 	.cropcap = {
 		.bounds = {
 			.left = 0,
@@ -90,8 +128,9 @@ int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam)
 	/* This sensor has no identifiers, so let's attach it anyway */
 	sn9c102_attach_sensor(cam, &tas5110c1b);
 
-	/* At the moment, only devices whose PID is 0x6005 have this sensor */
-	if (tas5110c1b.usbdev->descriptor.idProduct != 0x6005)
+	/* At the moment, sensor detection is based on USB pid/vid */
+	if (tas5110c1b.usbdev->descriptor.idProduct != 0x6001 &&
+	    tas5110c1b.usbdev->descriptor.idProduct != 0x6005)
 		return -ENODEV;
 
 	return 0;
diff --git a/drivers/usb/media/sn9c102_tas5130d1b.c b/drivers/usb/media/sn9c102_tas5130d1b.c
index 5f1b0f9a6..0bab19435 100644
--- a/drivers/usb/media/sn9c102_tas5130d1b.c
+++ b/drivers/usb/media/sn9c102_tas5130d1b.c
@@ -37,38 +37,45 @@ static int tas5130d1b_init(struct sn9c102_device* cam)
 	err += sn9c102_write_reg(cam, 0x00, 0x14);
 	err += sn9c102_write_reg(cam, 0x60, 0x17);
 	err += sn9c102_write_reg(cam, 0x07, 0x18);
-	err += sn9c102_write_reg(cam, 0x33, 0x19);
 
 	err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x00, 0x40,
 	                                 0x47, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x02, 0x20,
-	                                 0xa9, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x00, 0xc0,
-	                                 0x49, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x02, 0x20,
-	                                 0x6c, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x00, 0xc0,
-	                                 0x08, 0, 0);
-	err += sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11, 0x00, 0x20,
-	                                 0x00, 0, 0);
-
-	err += sn9c102_write_reg(cam, 0x63, 0x19);
 
 	return err;
 }
 
 
+static int tas5130d1b_set_ctrl(struct sn9c102_device* cam, 
+                               const struct v4l2_control* ctrl)
+{
+	switch (ctrl->id) {
+	case V4L2_CID_GAIN:
+		return sn9c102_i2c_try_raw_write(cam, &tas5130d1b, 4, 0x11,
+		                                 0x02, 0x20,
+		                                 0xff - (ctrl->value & 0xff),
+		                                 0, 0);
+	default:
+		return -EINVAL;
+	}
+}
+
+
 static int tas5130d1b_set_crop(struct sn9c102_device* cam, 
                                const struct v4l2_rect* rect)
 {
 	struct sn9c102_sensor* s = &tas5130d1b;
-	int err = 0;
 	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104,
 	   v_start = (u8)(rect->top - s->cropcap.bounds.top) + 12;
+	int err = 0;
 
 	err += sn9c102_write_reg(cam, h_start, 0x12);
 	err += sn9c102_write_reg(cam, v_start, 0x13);
 
+	/* Do NOT change! */
+	err += sn9c102_write_reg(cam, 0x1d, 0x1a);
+	err += sn9c102_write_reg(cam, 0x10, 0x1b);
+	err += sn9c102_write_reg(cam, 0xf3, 0x19);
+
 	return err;
 }
 
@@ -79,6 +86,19 @@ static struct sn9c102_sensor tas5130d1b = {
 	.frequency = SN9C102_I2C_100KHZ,
 	.interface = SN9C102_I2C_3WIRES,
 	.init = &tas5130d1b_init,
+	.qctrl = {
+		{
+			.id = V4L2_CID_GAIN,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "global gain",
+			.minimum = 0x00,
+			.maximum = 0xff,
+			.step = 0x01,
+			.default_value = 0x00,
+			.flags = 0,
+		},
+	},
+	.set_ctrl = &tas5130d1b_set_ctrl,
 	.cropcap = {
 		.bounds = {
 			.left = 0,
@@ -108,13 +128,9 @@ int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam)
 	/* This sensor has no identifiers, so let's attach it anyway */
 	sn9c102_attach_sensor(cam, &tas5130d1b);
 
-	/* At the moment, only devices whose PID is 0x6025 have this sensor */
+	/* At the moment, sensor detection is based on USB pid/vid */
 	if (tas5130d1b.usbdev->descriptor.idProduct != 0x6025)
 		return -ENODEV;
 
-	dev_info(tas5130d1b.dev, "TAS5130D1B detected, but the support for it "
-	                         "is disabled at the moment - needs further "
-	                         "testing -\n");
-
-	return -ENODEV;
+	return 0;
 }
diff --git a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c
index af460298a..cd73a45d0 100644
--- a/drivers/usb/media/stv680.c
+++ b/drivers/usb/media/stv680.c
@@ -93,11 +93,11 @@ static unsigned int debug = 0;
 MODULE_AUTHOR (DRIVER_AUTHOR);
 MODULE_DESCRIPTION (DRIVER_DESC);
 MODULE_LICENSE ("GPL");
-MODULE_PARM (debug, "i");
+module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC (debug, "Debug enabled or not");
-MODULE_PARM (swapRGB_on, "i");
+module_param(swapRGB_on, int, 0);
 MODULE_PARM_DESC (swapRGB_on, "Red/blue swap: 1=always, 0=auto, -1=never");
-MODULE_PARM (video_nr, "i");
+module_param(video_nr, int, 0);
 
 /********************************************************************
  *
@@ -704,7 +704,6 @@ static int stv680_start_stream (struct usb_stv *stv680)
 				   usb_rcvbulkpipe (stv680->udev, stv680->bulk_in_endpointAddr),
 				   stv680->sbuf[i].data, stv680->rawbufsize,
 				   stv680_video_irq, stv680);
-		urb->timeout = PENCAM_TIMEOUT * 2;
 		stv680->urb[i] = urb;
 		err = usb_submit_urb (stv680->urb[i], GFP_KERNEL);
 		if (err)
diff --git a/drivers/usb/media/ultracam.c b/drivers/usb/media/ultracam.c
index cbaf7d804..84f38839c 100644
--- a/drivers/usb/media/ultracam.c
+++ b/drivers/usb/media/ultracam.c
@@ -60,9 +60,9 @@ static int init_color = 128;
 static int init_hue = 128;
 static int hue_correction = 128;
 
-MODULE_PARM(debug, "i");
+module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
-MODULE_PARM(flags, "i");
+module_param(flags, int, 0);
 MODULE_PARM_DESC(flags,
 		"Bitfield: 0=VIDIOCSYNC, "
 		"1=B/W, "
@@ -71,18 +71,18 @@ MODULE_PARM_DESC(flags,
 		"4=test pattern, "
 		"5=separate frames, "
 		"6=clean frames");
-MODULE_PARM(framerate, "i");
+module_param(framerate, int, 0);
 MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)");
 
-MODULE_PARM(init_brightness, "i");
+module_param(init_brightness, int, 0);
 MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)");
-MODULE_PARM(init_contrast, "i");
+module_param(init_contrast, int, 0);
 MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)");
-MODULE_PARM(init_color, "i");
+module_param(init_color, int, 0);
 MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)");
-MODULE_PARM(init_hue, "i");
+module_param(init_hue, int, 0);
 MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)");
-MODULE_PARM(hue_correction, "i");
+module_param(hue_correction, int, 0);
 MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)");
 
 /*
diff --git a/drivers/usb/media/usbvideo.c b/drivers/usb/media/usbvideo.c
index d46b136c9..1107e398d 100644
--- a/drivers/usb/media/usbvideo.c
+++ b/drivers/usb/media/usbvideo.c
@@ -34,7 +34,7 @@
 #endif
 
 static int video_nr = -1;
-MODULE_PARM(video_nr, "i");
+module_param(video_nr, int, 0);
 
 /*
  * Local prototypes.
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index 310c5a96c..c4bebdacd 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -269,7 +269,7 @@ typedef struct
 /* Forwards */
 static void auerswald_ctrlread_complete (struct urb * urb, struct pt_regs *regs);
 static void auerswald_removeservice (pauerswald_t cp, pauerscon_t scp);
-extern struct usb_driver auerswald_driver;
+static struct usb_driver auerswald_driver;
 
 
 /*-------------------------------------------------------------------*/
@@ -1037,7 +1037,8 @@ static void auerswald_int_complete (struct urb * urb, struct pt_regs *regs)
 
         /* now extract the information */
         channelid = cp->intbufp[2];
-        bytecount = le16_to_cpup (&cp->intbufp[3]);
+        bytecount = (unsigned char)cp->intbufp[3];
+        bytecount |= (unsigned char)cp->intbufp[4] << 8;
 
         /* check the channel id */
         if (channelid >= AUH_TYPESIZE) {
@@ -1930,7 +1931,7 @@ static int auerswald_probe (struct usb_interface *intf,
 	struct usb_device *usbdev = interface_to_usbdev(intf);
 	pauerswald_t cp = NULL;
 	unsigned int u = 0;
-	char *pbuf;
+	__le16 *pbuf;
 	int ret;
 
 	dbg ("probe: vendor id 0x%x, device id 0x%x",
@@ -1976,8 +1977,7 @@ static int auerswald_probe (struct usb_interface *intf,
 	dbg ("Version is %X", cp->version);
 
 	/* allow some time to settle the device */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ/3);
+	msleep(334);
 
 	/* Try to get a suitable textual description of the device */
 	/* Device name:*/
@@ -2003,7 +2003,7 @@ static int auerswald_probe (struct usb_interface *intf,
 	info("device is a %s", cp->dev_desc);
 
         /* get the maximum allowed control transfer length */
-        pbuf = (char *) kmalloc (2, GFP_KERNEL);    /* use an allocated buffer because of urb target */
+        pbuf = (__le16 *) kmalloc (2, GFP_KERNEL);    /* use an allocated buffer because of urb target */
         if (!pbuf) {
 		err( "out of memory");
 		goto pfail;
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index cd7b548b9..06c4bfa2f 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -71,6 +71,8 @@
  *   - make device locking interruptible
  * 2004-04-30 - 0.95 Juergen Stuber <starblue@users.sourceforge.net>
  *   - check for valid udev on resubmitting and unlinking urbs
+ * 2004-08-03 - 0.96 Juergen Stuber <starblue@users.sourceforge.net>
+ *   - move reset into open to clean out spurious data
  */
 
 #include <linux/config.h>
@@ -98,12 +100,12 @@
 
 
 /* Version Information */
-#define DRIVER_VERSION "v0.95"
+#define DRIVER_VERSION "v0.96"
 #define DRIVER_AUTHOR "Juergen Stuber <starblue@sourceforge.net>"
 #define DRIVER_DESC "LEGO USB Tower Driver"
 
 /* Module parameters */
-MODULE_PARM(debug, "i");
+module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug enabled or not");
 
 /* The defaults are chosen to work with the latest versions of leJOS and NQC.
@@ -113,8 +115,8 @@ MODULE_PARM_DESC(debug, "Debug enabled or not");
  * In this case read_buffer_size should exceed the maximal packet length
  * (417 for datalog uploads), and packet_timeout should be set.
  */
-static size_t read_buffer_size = 480;
-MODULE_PARM(read_buffer_size, "i");
+static int read_buffer_size = 480;
+module_param(read_buffer_size, int, 0);
 MODULE_PARM_DESC(read_buffer_size, "Read buffer size");
 
 /* Some legacy software likes to send packets in one piece.
@@ -123,8 +125,8 @@ MODULE_PARM_DESC(read_buffer_size, "Read buffer size");
  * A problem with long writes is that the following read may time out
  * if the software is not prepared to wait long enough.
  */
-static size_t write_buffer_size = 480;
-MODULE_PARM(write_buffer_size, "i");
+static int write_buffer_size = 480;
+module_param(write_buffer_size, int, 0);
 MODULE_PARM_DESC(write_buffer_size, "Write buffer size");
 
 /* Some legacy software expects reads to contain whole LASM packets.
@@ -138,7 +140,7 @@ MODULE_PARM_DESC(write_buffer_size, "Write buffer size");
  * Set it to 0 to disable.
  */
 static int packet_timeout = 50;
-MODULE_PARM(packet_timeout, "i");
+module_param(packet_timeout, int, 0);
 MODULE_PARM_DESC(packet_timeout, "Packet timeout in ms");
 
 /* Some legacy software expects blocking reads to time out.
@@ -146,7 +148,7 @@ MODULE_PARM_DESC(packet_timeout, "Packet timeout in ms");
  * Set it to 0 to disable.
  */
 static int read_timeout = 200;
-MODULE_PARM(read_timeout, "i");
+module_param(read_timeout, int, 0);
 MODULE_PARM_DESC(read_timeout, "Read timeout in ms");
 
 /* As of kernel version 2.6.4 ehci-hcd uses an
@@ -159,11 +161,11 @@ MODULE_PARM_DESC(read_timeout, "Read timeout in ms");
  * or set to 0 to use the standard interval from the endpoint descriptors.
  */
 static int interrupt_in_interval = 2;
-MODULE_PARM(interrupt_in_interval, "i");
+module_param(interrupt_in_interval, int, 0);
 MODULE_PARM_DESC(interrupt_in_interval, "Interrupt in interval in ms");
 
 static int interrupt_out_interval = 8;
-MODULE_PARM(interrupt_out_interval, "i");
+module_param(interrupt_out_interval, int, 0);
 MODULE_PARM_DESC(interrupt_out_interval, "Interrupt out interval in ms");
 
 /* Define these values to match your device */
@@ -175,18 +177,18 @@ MODULE_PARM_DESC(interrupt_out_interval, "Interrupt out interval in ms");
 #define LEGO_USB_TOWER_REQUEST_GET_VERSION	0xFD
 
 struct tower_reset_reply {
-	__u16 size;		/* little-endian */
+	__le16 size;		/* little-endian */
 	__u8 err_code;
 	__u8 spare;
 } __attribute__ ((packed));
 
 struct tower_get_version_reply {
-	__u16 size;		/* little-endian */
+	__le16 size;		/* little-endian */
 	__u8 err_code;
 	__u8 spare;
 	__u8 major;
 	__u8 minor;
-	__u16 build_no;		/* little-endian */
+	__le16 build_no;		/* little-endian */
 } __attribute__ ((packed));
 
 
@@ -341,6 +343,8 @@ static int tower_open (struct inode *inode, struct file *file)
 	int subminor;
 	int retval = 0;
 	struct usb_interface *interface;
+	struct tower_reset_reply reset_reply;
+	int result;
 
 	dbg(2, "%s: enter", __FUNCTION__);
 
@@ -378,6 +382,22 @@ static int tower_open (struct inode *inode, struct file *file)
 	}
 	dev->open_count = 1;
 
+	/* reset the tower */
+	result = usb_control_msg (dev->udev,
+				  usb_rcvctrlpipe(dev->udev, 0),
+				  LEGO_USB_TOWER_REQUEST_RESET,
+				  USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
+				  0,
+				  0,
+				  &reset_reply,
+				  sizeof(reset_reply),
+				  HZ);
+	if (result < 0) {
+		err("LEGO USB Tower reset control request failed");
+		retval = result;
+		goto unlock_exit;
+	}
+
 	/* initialize in direction */
 	dev->read_buffer_length = 0;
 	dev->read_packet_length = 0;
@@ -694,7 +714,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t
 	}
 
 	/* write the data into interrupt_out_buffer from userspace */
-	bytes_to_write = min(count, write_buffer_size);
+	bytes_to_write = min_t(int, count, write_buffer_size);
 	dbg(4, "%s: count = %Zd, bytes_to_write = %Zd", __FUNCTION__, count, bytes_to_write);
 
 	if (copy_from_user (dev->interrupt_out_buffer, buffer, bytes_to_write)) {
@@ -828,7 +848,6 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
 	struct lego_usb_tower *dev = NULL;
 	struct usb_host_interface *iface_desc;
 	struct usb_endpoint_descriptor* endpoint;
-	struct tower_reset_reply reset_reply;
 	struct tower_get_version_reply get_version_reply;
 	int i;
 	int retval = -ENOMEM;
@@ -951,22 +970,6 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
 	/* let the user know what node this device is now attached to */
 	info ("LEGO USB Tower #%d now attached to major %d minor %d", (dev->minor - LEGO_USB_TOWER_MINOR_BASE), USB_MAJOR, dev->minor);
 
-	/* reset the tower */
-	result = usb_control_msg (udev,
-				  usb_rcvctrlpipe(udev, 0),
-				  LEGO_USB_TOWER_REQUEST_RESET,
-				  USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
-				  0,
-				  0,
-				  &reset_reply,
-				  sizeof(reset_reply),
-				  HZ);
-	if (result < 0) {
-		err("LEGO USB Tower reset control request failed");
-		retval = result;
-		goto error;
-	}
-
 	/* get the firmware version and log it */
 	result = usb_control_msg (udev,
 				  usb_rcvctrlpipe(udev, 0),
diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c
index b89b53401..8cca7e747 100644
--- a/drivers/usb/misc/phidgetservo.c
+++ b/drivers/usb/misc/phidgetservo.c
@@ -12,8 +12,6 @@
  * controllers available at: http://www.phidgets.com/ 
  *
  * Note that the driver takes input as: degrees.minutes
- * -23 < degrees < 203
- * 0 < minutes < 59
  *
  * CAUTION: Generally you should use 0 < degrees < 180 as anything else
  * is probably beyond the range of your servo and may damage it.
@@ -21,6 +19,10 @@
  * Jun 16, 2004: Sean Young <sean@mess.org>
  *  - cleanups
  *  - was using memory after kfree()
+ * Aug 8, 2004: Sean Young <sean@mess.org>
+ *  - set the highest angle as high as the hardware allows, there are 
+ *    some odd servos out there
+ *
  */
 
 #include <linux/config.h>
@@ -87,6 +89,9 @@ change_position_v30(struct phidget_servo *servo, int servo_no, int degrees,
 	int retval;
 	unsigned char *buffer;
 
+	if (degrees < -23 || degrees > 362)
+		return -EINVAL;
+
 	buffer = kmalloc(6, GFP_KERNEL);
 	if (!buffer) {
 		dev_err(&servo->udev->dev, "%s - out of memory\n",
@@ -157,6 +162,9 @@ change_position_v20(struct phidget_servo *servo, int servo_no, int degrees,
 	int retval;
 	unsigned char *buffer;
 
+	if (degrees < -23 || degrees > 278)
+		return -EINVAL;
+
 	buffer = kmalloc(2, GFP_KERNEL);
 	if (!buffer) {
 		dev_err(&servo->udev->dev, "%s - out of memory\n",
@@ -212,10 +220,8 @@ static ssize_t set_servo##value (struct device *dev,			\
 		return -EINVAL;						\
 	}								\
 									\
-	if (degrees < -23 || degrees > (180 + 23) ||			\
-	    minutes < 0 || minutes > 59) {				\
+	if (minutes < 0 || minutes > 59) 				\
 		return -EINVAL;						\
-	}								\
 									\
 	if (servo->type & SERVO_VERSION_30)				\
 		retval = change_position_v30 (servo, value, degrees, 	\
diff --git a/drivers/usb/misc/tiglusb.c b/drivers/usb/misc/tiglusb.c
index cdf5919f8..0f9c57537 100644
--- a/drivers/usb/misc/tiglusb.c
+++ b/drivers/usb/misc/tiglusb.c
@@ -560,7 +560,7 @@ MODULE_AUTHOR (DRIVER_AUTHOR);
 MODULE_DESCRIPTION (DRIVER_DESC);
 MODULE_LICENSE (DRIVER_LICENSE);
 
-MODULE_PARM (timeout, "i");
+module_param(timeout, int, 0);
 MODULE_PARM_DESC (timeout, "Timeout in tenths of seconds (default=1.5 seconds)");
 
 /* --------------------------------------------------------------------- */
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 8ee1b05ea..a03b8d44a 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -1054,8 +1054,7 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async)
 	urb = simple_alloc_urb (testdev_to_usbdev (dev), pipe, size);
 	if (!urb)
 		return -ENOMEM;
-	if (async)
-		urb->transfer_flags |= URB_ASYNC_UNLINK;
+	urb->transfer_flags |= URB_ASYNC_UNLINK;
 	urb->context = &completion;
 	urb->complete = unlink1_callback;
 
@@ -1074,17 +1073,20 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async)
 	 * hcd states and code paths, even with little other system load.
 	 */
 	msleep (jiffies % (2 * INTERRUPT_RATE));
+	if (async) {
 retry:
-	retval = usb_unlink_urb (urb);
-	if (retval == -EBUSY || retval == -EIDRM) {
-		/* we can't unlink urbs while they're completing.
-		 * or if they've completed, and we haven't resubmitted.
-		 * "normal" drivers would prevent resubmission, but
-		 * since we're testing unlink paths, we can't.
-		 */
-		dev_dbg (&dev->intf->dev, "unlink retry\n");
-		goto retry;
-	}
+		retval = usb_unlink_urb (urb);
+		if (retval == -EBUSY || retval == -EIDRM) {
+			/* we can't unlink urbs while they're completing.
+			 * or if they've completed, and we haven't resubmitted.
+			 * "normal" drivers would prevent resubmission, but
+			 * since we're testing unlink paths, we can't.
+			 */
+			dev_dbg (&dev->intf->dev, "unlink retry\n");
+			goto retry;
+		}
+	} else
+		usb_kill_urb (urb);
 	if (!(retval == 0 || retval == -EINPROGRESS)) {
 		dev_dbg (&dev->intf->dev, "unlink fail %d\n", retval);
 		return retval;
@@ -1095,9 +1097,10 @@ retry:
 	simple_free_urb (urb);
 
 	if (async)
-		return (retval != -ECONNRESET) ? -ECONNRESET : 0;
+		return (retval == -ECONNRESET) ? 0 : retval - 1000;
 	else
-		return (retval != -ENOENT) ? -ENOENT : 0;
+		return (retval == -ENOENT || retval == -EPERM) ?
+				0 : retval - 2000;
 }
 
 static int unlink_simple (struct usbtest_dev *dev, int pipe, int len)
diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
index de9bf863e..455fe6e3b 100644
--- a/drivers/usb/net/catc.c
+++ b/drivers/usb/net/catc.c
@@ -242,7 +242,7 @@ static void catc_rx_done(struct urb *urb, struct pt_regs *regs)
 
 	do {
 		if(!catc->is_f5u011) {
-			pkt_len = le16_to_cpup((u16*)pkt_start);
+			pkt_len = le16_to_cpup((__le16*)pkt_start);
 			if (pkt_len > urb->actual_length) {
 				catc->stats.rx_length_errors++;
 				catc->stats.rx_errors++;
@@ -303,7 +303,7 @@ static void catc_irq_done(struct urb *urb, struct pt_regs *regs)
 		else if (data[1] & 0x20)
 			linksts = LinkBad;
 	} else {
-		hasdata = (unsigned int)(be16_to_cpup((u16*)data) & 0x0fff);
+		hasdata = (unsigned int)(be16_to_cpup((__be16*)data) & 0x0fff);
 		if (data[0] == 0x90)
 			linksts = LinkGood;
 		else if (data[0] == 0xA0)
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
index 6eb637a80..40e921ade 100644
--- a/drivers/usb/net/kaweth.c
+++ b/drivers/usb/net/kaweth.c
@@ -203,7 +203,7 @@ struct kaweth_ethernet_configuration
 	__u8 reserved2;
 	eth_addr_t hw_addr;
 	__u32 statistics_mask;
-	__u16 segment_size;
+	__le16 segment_size;
 	__u16 max_multicast_filters;
 	__u8 reserved3;
 } __attribute__ ((packed));
@@ -588,7 +588,7 @@ static void kaweth_usb_receive(struct urb *urb, struct pt_regs *regs)
 	int count = urb->actual_length;
 	int count2 = urb->transfer_buffer_length;
 
-	__u16 pkt_len = le16_to_cpup((u16 *)kaweth->rx_buf);
+	__u16 pkt_len = le16_to_cpup((__le16 *)kaweth->rx_buf);
 
 	struct sk_buff *skb;
 
@@ -668,7 +668,7 @@ static int kaweth_open(struct net_device *net)
 		INTBUFFERSIZE,
 		int_callback,
 		kaweth,
-		HZ/4);
+		8);
 	kaweth->irq_urb->transfer_dma = kaweth->intbufferhandle;
 	kaweth->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
@@ -763,7 +763,7 @@ static void kaweth_usb_transmit_complete(struct urb *urb, struct pt_regs *regs)
 static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net)
 {
 	struct kaweth_device *kaweth = net->priv;
-	u16 *private_header;
+	__le16 *private_header;
 
 	int res;
 
@@ -794,7 +794,7 @@ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net)
 		}
 	}
 
-	private_header = (u16 *)__skb_push(skb, 2);
+	private_header = (__le16 *)__skb_push(skb, 2);
 	*private_header = cpu_to_le16(skb->len-2);
 	kaweth->tx_skb = skb;
 
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index f4f1071a3..c515916e3 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -78,8 +78,8 @@ static struct usb_device_id pegasus_ids[] = {
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
-MODULE_PARM(loopback, "i");
-MODULE_PARM(mii_mode, "i");
+module_param(loopback, bool, 0);
+module_param(mii_mode, bool, 0);
 MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)");
 MODULE_PARM_DESC(mii_mode, "Enable HomePNA mode (bit 0),default=MII mode = 0");
 
@@ -286,7 +286,7 @@ static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd)
 {
 	int i;
 	__u8 data[4] = { phy, 0, 0, indx };
-	__u16 regdi;
+	__le16 regdi;
 
 	set_register(pegasus, PhyCtrl, 0);
 	set_registers(pegasus, PhyAddr, sizeof (data), data);
@@ -347,7 +347,7 @@ static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata)
 {
 	int i;
 	__u8 tmp;
-	__u16 retdatai;
+	__le16 retdatai;
 
 	set_register(pegasus, EpromCtrl, 0);
 	set_register(pegasus, EpromOffset, index);
@@ -417,7 +417,7 @@ static inline void get_node_id(pegasus_t * pegasus, __u8 * id)
 
 	for (i = 0; i < 3; i++) {
 		read_eprom_word(pegasus, i, &w16);
-		((__u16 *) id)[i] = cpu_to_le16p(&w16);
+		((__le16 *) id)[i] = cpu_to_le16p(&w16);
 	}
 }
 
@@ -581,7 +581,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
 	if (!count)
 		goto goon;
 
-	rx_status = le32_to_cpu(*(int *) (urb->transfer_buffer + count - 4));
+	rx_status = le32_to_cpu(*(__le32 *) (urb->transfer_buffer + count - 4));
 	if (rx_status & 0x000e0000) {
 		dbg("%s: RX packet error %x", net->name, rx_status & 0xe0000);
 		pegasus->stats.rx_errors++;
@@ -594,7 +594,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
 		goto goon;
 	}
 	if (pegasus->chip == 0x8513) {
-		pkt_len = le32_to_cpu(*(int *)urb->transfer_buffer);
+		pkt_len = le32_to_cpu(*(__le32 *)urb->transfer_buffer);
 		pkt_len &= 0x0fff;
 		pegasus->rx_skb->data += 2;
 	} else {
@@ -774,7 +774,7 @@ static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net)
 
 	netif_stop_queue(net);
 
-	((__u16 *) pegasus->tx_buff)[0] = cpu_to_le16(l16);
+	((__le16 *) pegasus->tx_buff)[0] = cpu_to_le16(l16);
 	memcpy(pegasus->tx_buff + 2, skb->data, skb->len);
 	usb_fill_bulk_urb(pegasus->tx_urb, pegasus->usb,
 			  usb_sndbulkpipe(pegasus->usb, 2),
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
index d9d09e984..640aa5b68 100644
--- a/drivers/usb/net/rtl8150.c
+++ b/drivers/usb/net/rtl8150.c
@@ -160,7 +160,7 @@ struct rtl8150 {
 	spinlock_t rx_pool_lock;
 	struct usb_ctrlrequest dr;
 	int intr_interval;
-	u16 rx_creg;
+	__le16 rx_creg;
 	u8 *intr_buff;
 	u8 phy;
 };
@@ -265,7 +265,7 @@ static int read_mii_word(rtl8150_t * dev, u8 phy, __u8 indx, u16 * reg)
 
 	if (i < MII_TIMEOUT) {
 		get_registers(dev, PHYDAT, 2, data);
-		*reg = le16_to_cpup(data);
+		*reg = data[0] | (data[1] << 8);
 		return 0;
 	} else
 		return 1;
@@ -450,7 +450,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
 		goto goon;
 
 	res = urb->actual_length;
-	rx_stat = le16_to_cpu(*(short *)(urb->transfer_buffer + res - 4));
+	rx_stat = le16_to_cpu(*(__le16 *)(urb->transfer_buffer + res - 4));
 	pkt_len = res - 4;
 
 	skb_put(dev->rx_skb, pkt_len);
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index 2d68cb01e..cca6e72cf 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -166,7 +166,7 @@
 #define CONTROL_TIMEOUT_JIFFIES ((CONTROL_TIMEOUT_MS * HZ)/1000)
 
 // between wakeups
-#define UNLINK_TIMEOUT_JIFFIES ((3  /*ms*/ * HZ)/1000)
+#define UNLINK_TIMEOUT_MS	3
 
 /*-------------------------------------------------------------------------*/
 
@@ -268,7 +268,7 @@ static const char driver_name [] = "usbnet";
 
 /* use ethtool to change the level for any given device */
 static int msg_level = 1;
-MODULE_PARM (msg_level, "i");
+module_param (msg_level, int, 0);
 MODULE_PARM_DESC (msg_level, "Initial message level (default = 1)");
 
 
@@ -937,8 +937,8 @@ struct ether_desc {
 
 	u8	iMACAddress;
 	u32	bmEthernetStatistics;
-	u16	wMaxSegmentSize;
-	u16	wNumberMCFilters;
+	__le16	wMaxSegmentSize;
+	__le16	wNumberMCFilters;
 	u8	bNumberPowerFilters;
 } __attribute__ ((packed));
 
@@ -1074,7 +1074,7 @@ static int generic_cdc_bind (struct usbnet *dev, struct usb_interface *intf)
 					info->u->bLength);
 				goto bad_desc;
 			}
-			dev->net->mtu = cpu_to_le16p (
+			dev->net->mtu = le16_to_cpup (
 						&info->ether->wMaxSegmentSize)
 					- ETH_HLEN;
 			/* because of Zaurus, we may be ignoring the host
@@ -2591,8 +2591,7 @@ static int usbnet_stop (struct net_device *net)
 	while (skb_queue_len (&dev->rxq)
 			&& skb_queue_len (&dev->txq)
 			&& skb_queue_len (&dev->done)) {
-		set_current_state (TASK_UNINTERRUPTIBLE);
-		schedule_timeout (UNLINK_TIMEOUT_JIFFIES);
+		msleep(UNLINK_TIMEOUT_MS);
 		devdbg (dev, "waited for %d urb completions", temp);
 	}
 	dev->wait = NULL;
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 3ee5f493a..33613b008 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -44,7 +44,7 @@ static int debug;
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.0"
+#define DRIVER_VERSION "v1.01"
 #define DRIVER_AUTHOR "Matthias Bruestle"
 #define DRIVER_DESC "REINER SCT cyberJack pinpad/e-com USB Chipcard Reader Driver"
 
@@ -111,6 +111,7 @@ struct cyberjack_private {
 static int cyberjack_startup (struct usb_serial *serial)
 {
 	struct cyberjack_private *priv;
+	int i;
 
 	dbg("%s", __FUNCTION__);
 
@@ -128,6 +129,16 @@ static int cyberjack_startup (struct usb_serial *serial)
 
 	init_waitqueue_head(&serial->port[0]->write_wait);
 
+	for (i = 0; i < serial->num_ports; ++i) {
+		int result;
+		serial->port[i]->interrupt_in_urb->dev = serial->dev;
+		result = usb_submit_urb(serial->port[i]->interrupt_in_urb, 
+					GFP_KERNEL);
+		if (result)
+			err(" usb_submit_urb(read int) failed");
+		dbg("%s - usb_submit_urb(int urb)", __FUNCTION__);
+	}
+
 	return( 0 );
 }
 
@@ -138,6 +149,7 @@ static void cyberjack_shutdown (struct usb_serial *serial)
 	dbg("%s", __FUNCTION__);
 
 	for (i=0; i < serial->num_ports; ++i) {
+		usb_unlink_urb (serial->port[i]->interrupt_in_urb);
 		/* My special items, the standard routines free my urbs */
 		kfree(usb_get_serial_port_data(serial->port[i]));
 		usb_set_serial_port_data(serial->port[i], NULL);
@@ -168,17 +180,6 @@ static int  cyberjack_open (struct usb_serial_port *port, struct file *filp)
 	priv->wrsent = 0;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	/* shutdown any bulk reads that might be going on */
-	usb_unlink_urb (port->write_urb);
-	usb_unlink_urb (port->read_urb);
-	usb_unlink_urb (port->interrupt_in_urb);
-
-	port->interrupt_in_urb->dev = port->serial->dev;
-	result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
-	if (result)
-		err(" usb_submit_urb(read int) failed");
-	dbg("%s - usb_submit_urb(int urb)", __FUNCTION__);
-
 	return result;
 }
 
@@ -190,11 +191,6 @@ static void cyberjack_close (struct usb_serial_port *port, struct file *filp)
 		/* shutdown any bulk reads that might be going on */
 		usb_unlink_urb (port->write_urb);
 		usb_unlink_urb (port->read_urb);
-		usb_unlink_urb (port->interrupt_in_urb);
-		dbg("%s - usb_clear_halt", __FUNCTION__ );
-		usb_clear_halt(port->serial->dev, port->write_urb->pipe);
-		usb_clear_halt(port->serial->dev, port->read_urb->pipe);
-		usb_clear_halt(port->serial->dev, port->interrupt_in_urb->pipe);
 	}
 }
 
@@ -376,6 +372,10 @@ static void cyberjack_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
 	}
 
 	tty = port->tty;
+	if (!tty) {
+		dbg("%s - ignoring since device not open\n", __FUNCTION__);
+		return;
+	}
 	if (urb->actual_length) {
 		for (i = 0; i < urb->actual_length ; ++i) {
 			/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index f187b3165..3ac69f2c2 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -624,14 +624,7 @@ static void digi_wakeup_write( struct usb_serial_port *port )
 	wake_up_interruptible( &port->write_wait );
 
 	/* wake up line discipline */
-	if( (tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
-	&& tty->ldisc.write_wakeup )
-		(tty->ldisc.write_wakeup)(tty);
-
-	/* wake up other tty processes */
-	wake_up_interruptible( &tty->write_wait );
-	/* For 2.2.16 backport -- wake_up_interruptible( &tty->poll_wait ); */
-
+	tty_wakeup(tty);
 }
 
 
@@ -1553,13 +1546,17 @@ static void digi_close( struct usb_serial_port *port, struct file *filp )
 dbg( "digi_close: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_count );
 
 
+	/* if disconnected, just clear flags */
+	if (!usb_get_intfdata(port->serial->interface))
+		goto exit;
+
 	/* do cleanup only after final close on this port */
 	spin_lock_irqsave( &priv->dp_port_lock, flags );
 	priv->dp_in_close = 1;
 	spin_unlock_irqrestore( &priv->dp_port_lock, flags );
 
 	/* tell line discipline to process only XON/XOFF */
-        tty->closing = 1;
+	tty->closing = 1;
 
 	/* wait for output to drain */
 	if( (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0 ) {
@@ -1569,8 +1566,7 @@ dbg( "digi_close: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_co
 	/* flush driver and line discipline buffers */
 	if( tty->driver->flush_buffer )
 		tty->driver->flush_buffer( tty );
-	if( tty->ldisc.flush_buffer )
-		tty->ldisc.flush_buffer( tty );
+	tty_ldisc_flush(tty);
 
 	if (port->serial->dev) {
 		/* wait for transmit idle */
@@ -1624,6 +1620,7 @@ dbg( "digi_close: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_co
 
 	tty->closing = 0;
 
+exit:
 	spin_lock_irqsave( &priv->dp_port_lock, flags );
 	priv->dp_write_urb_in_use = 0;
 	priv->dp_in_close = 0;
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 972f3b91d..251a50fda 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -516,11 +516,7 @@ static void empeg_set_termios (struct usb_serial_port *port, struct termios *old
 	 */
 	port->tty->low_latency = 1;
 
-	/* Notify the tty driver that the termios have changed. */
-	port->tty->ldisc.set_termios(port->tty, NULL);
-
 	return;
-
 }
 
 
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index b35ab607a..9073ea84d 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -17,6 +17,11 @@
  * See http://ftdi-usb-sio.sourceforge.net for upto date testing info
  *	and extra documentation
  *
+ * (21/Jul/2004) Ian Abbott
+ *      Incorporated Steven Turner's code to add support for the FT2232C chip.
+ *      The prelimilary port to the 2.6 kernel was by Rus V. Brushkoff.  I have
+ *      fixed a couple of things.
+ *
  * (27/May/2004) Ian Abbott
  *      Improved throttling code, mostly stolen from the WhiteHEAT driver.
  *
@@ -259,7 +264,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.4.0"
+#define DRIVER_VERSION "v1.4.1"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>"
 #define DRIVER_DESC "USB FTDI Serial Converters Driver"
 
@@ -489,11 +494,18 @@ static struct usb_device_id id_table_HE_TIRA1 [] = {
 };
 
 
+static struct usb_device_id id_table_FT2232C[] = {
+	{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
+	{ }						/* Terminating entry */
+};
+
+
 static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
@@ -621,6 +633,8 @@ struct ftdi_private {
 	__u8 rx_flags;		/* receive state flags (throttling) */
 	spinlock_t rx_lock;	/* spinlock for receive state */
 
+	__u16 interface;	/* FT2232C port interface (0 for FT232/245) */
+
 	int force_baud;		/* if non-zero, force the baud rate to this value */
 	int force_rtscts;	/* if non-zero, force RTS-CTS to always be enabled */
 };
@@ -637,6 +651,7 @@ struct ftdi_private {
 static int  ftdi_SIO_startup		(struct usb_serial *serial);
 static int  ftdi_8U232AM_startup	(struct usb_serial *serial);
 static int  ftdi_FT232BM_startup	(struct usb_serial *serial);
+static int  ftdi_FT2232C_startup	(struct usb_serial *serial);
 static int  ftdi_USB_UIRT_startup	(struct usb_serial *serial);
 static int  ftdi_HE_TIRA1_startup	(struct usb_serial *serial);
 static void ftdi_shutdown		(struct usb_serial *serial);
@@ -739,6 +754,32 @@ static struct usb_serial_device_type ftdi_FT232BM_device = {
 	.shutdown =		ftdi_shutdown,
 };
 
+static struct usb_serial_device_type ftdi_FT2232C_device = {
+	.owner =		THIS_MODULE,
+	.name =			"FTDI FT2232C Compatible",
+	.id_table =		id_table_FT2232C,
+	.num_interrupt_in =	0,
+	.num_bulk_in =		1,
+	.num_bulk_out =		1,
+	.num_ports =		1,
+	.open =			ftdi_open,
+	.close =		ftdi_close,
+	.throttle =		ftdi_throttle,
+	.unthrottle =		ftdi_unthrottle,
+	.write =		ftdi_write,
+	.write_room =		ftdi_write_room,
+	.chars_in_buffer =	ftdi_chars_in_buffer,
+	.read_bulk_callback =	ftdi_read_bulk_callback,
+	.write_bulk_callback =	ftdi_write_bulk_callback,
+	.tiocmget =             ftdi_tiocmget,
+	.tiocmset =             ftdi_tiocmset,
+	.ioctl =		ftdi_ioctl,
+	.set_termios =		ftdi_set_termios,
+	.break_ctl =		ftdi_break_ctl,
+	.attach =		ftdi_FT2232C_startup,
+	.shutdown =		ftdi_shutdown,
+};
+
 static struct usb_serial_device_type ftdi_USB_UIRT_device = {
 	.owner =		THIS_MODULE,
 	.name =			"USB-UIRT Infrared Tranceiver",
@@ -866,7 +907,7 @@ static int set_rts(struct usb_serial_port *port, int high_or_low)
 			       usb_sndctrlpipe(port->serial->dev, 0),
 			       FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
 			       FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
-			       ftdi_high_or_low, 0, 
+			       ftdi_high_or_low, priv->interface, 
 			       buf, 0, WDR_TIMEOUT);
 
 	kfree(buf);
@@ -896,7 +937,7 @@ static int set_dtr(struct usb_serial_port *port, int high_or_low)
 			       usb_sndctrlpipe(port->serial->dev, 0),
 			       FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
 			       FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
-			       ftdi_high_or_low, 0, 
+			       ftdi_high_or_low, priv->interface, 
 			       buf, 0, WDR_TIMEOUT);
 
 	kfree(buf);
@@ -909,6 +950,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port);
 
 static int change_speed(struct usb_serial_port *port)
 {
+	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	char *buf;
         __u16 urb_value;
 	__u16 urb_index;
@@ -922,6 +964,9 @@ static int change_speed(struct usb_serial_port *port)
 	urb_index_value = get_ftdi_divisor(port);
 	urb_value = (__u16)urb_index_value;
 	urb_index = (__u16)(urb_index_value >> 16);
+	if (priv->interface) {	/* FT2232C */
+		urb_index = (__u16)((urb_index << 8) | priv->interface);
+	}
 	
 	rv = usb_control_msg(port->serial->dev,
 			    usb_sndctrlpipe(port->serial->dev, 0),
@@ -1015,7 +1060,12 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port)
 		}
 		break;
 	case FT232BM: /* FT232BM chip */
-		chip_name = "FT232BM";
+	case FT2232C: /* FT2232C chip */
+		if (priv->chip_type == FT2232C) {
+			chip_name = "FT2232C";
+		} else {
+			chip_name = "FT232BM";
+		}
 		if (baud <= 3000000) {
 			div_value = ftdi_232bm_baud_to_divisor(baud);
 		} else {
@@ -1231,6 +1281,35 @@ static int ftdi_FT232BM_startup (struct usb_serial *serial)
 	return (0);
 } /* ftdi_FT232BM_startup */
 
+/* Startup for the FT2232C chip */
+/* Called from usbserial:serial_probe */
+static int ftdi_FT2232C_startup (struct usb_serial *serial)
+{ /* ftdi_FT2232C_startup */
+	struct ftdi_private *priv;
+	int err;
+	int inter;
+
+	dbg("%s",__FUNCTION__);
+	err = ftdi_common_startup(serial);
+	if (err){
+		return (err);
+	}
+
+	priv = usb_get_serial_port_data(serial->port[0]);
+	priv->chip_type = FT2232C;
+	inter = serial->interface->altsetting->desc.bInterfaceNumber;
+
+	if (inter) {
+		priv->interface = INTERFACE_B;
+	}
+	else  {
+		priv->interface = INTERFACE_A;
+	}
+	priv->baud_base = 48000000 / 2; /* Would be / 16, but FT2232C supports multiple of 0.125 divisor fractions! */
+	
+	return (0);
+} /* ftdi_FT2232C_startup */
+
 /* Startup for the USB-UIRT device, which requires hardwired baudrate (38400 gets mapped to 312500) */
 /* Called from usbserial:serial_probe */
 static int ftdi_USB_UIRT_startup (struct usb_serial *serial)
@@ -1323,7 +1402,7 @@ static int  ftdi_open (struct usb_serial_port *port, struct file *filp)
 	usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 			FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, 
 			FTDI_SIO_RESET_SIO, 
-			0, buf, 0, WDR_TIMEOUT);
+			priv->interface, buf, 0, WDR_TIMEOUT);
 
 	/* Termios defaults are set by usb_serial_init. We don't change
 	   port->tty->termios - this would loose speed settings, etc.
@@ -1373,6 +1452,7 @@ static int  ftdi_open (struct usb_serial_port *port, struct file *filp)
 static void ftdi_close (struct usb_serial_port *port, struct file *filp)
 { /* ftdi_close */
 	unsigned int c_cflag = port->tty->termios->c_cflag;
+	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	char buf[1];
 
 	dbg("%s", __FUNCTION__);
@@ -1383,7 +1463,8 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp)
 				    usb_sndctrlpipe(port->serial->dev, 0),
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-				    0, 0, buf, 0, WDR_TIMEOUT) < 0) {
+				    0, priv->interface, buf, 0,
+				    WDR_TIMEOUT) < 0) {
 			err("error from flowcontrol urb");
 		}	    
 
@@ -1796,7 +1877,7 @@ static void ftdi_break_ctl( struct usb_serial_port *port, int break_state )
 	if (usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0),
 			    FTDI_SIO_SET_DATA_REQUEST, 
 			    FTDI_SIO_SET_DATA_REQUEST_TYPE,
-			    urb_value , 0,
+			    urb_value , priv->interface,
 			    buf, 0, WDR_TIMEOUT) < 0) {
 		err("%s FAILED to enable/disable break state (state was %d)", __FUNCTION__,break_state);
 	}	   
@@ -1875,7 +1956,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_
 	if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 			    FTDI_SIO_SET_DATA_REQUEST, 
 			    FTDI_SIO_SET_DATA_REQUEST_TYPE,
-			    urb_value , 0,
+			    urb_value , priv->interface,
 			    buf, 0, 100) < 0) {
 		err("%s FAILED to set databits/stopbits/parity", __FUNCTION__);
 	}	   
@@ -1886,7 +1967,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_
 		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST, 
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-				    0, 0, 
+				    0, priv->interface, 
 				    buf, 0, WDR_TIMEOUT) < 0) {
 			err("%s error from disable flowcontrol urb", __FUNCTION__);
 		}	    
@@ -1903,6 +1984,13 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_
 		if (change_speed(port)) {
 			err("%s urb failed to set baurdrate", __FUNCTION__);
 		}
+		/* Ensure  RTS and DTR are raised */
+		else if (set_dtr(port, HIGH) < 0){
+			err("%s Error from DTR HIGH urb", __FUNCTION__);
+		}
+		else if (set_rts(port, HIGH) < 0){
+			err("%s Error from RTS HIGH urb", __FUNCTION__);
+		}	
 	}
 
 	/* Set flow control */
@@ -1913,7 +2001,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_
 				    usb_sndctrlpipe(dev, 0),
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST, 
 				    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-				    0 , FTDI_SIO_RTS_CTS_HS,
+				    0 , (FTDI_SIO_RTS_CTS_HS | priv->interface),
 				    buf, 0, WDR_TIMEOUT) < 0) {
 			err("urb failed to set to rts/cts flow control");
 		}		
@@ -1939,7 +2027,8 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_
 					    usb_sndctrlpipe(dev, 0),
 					    FTDI_SIO_SET_FLOW_CTRL_REQUEST,
 					    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-					    urb_value , FTDI_SIO_XON_XOFF_HS,
+					    urb_value , (FTDI_SIO_XON_XOFF_HS
+							 | priv->interface),
 					    buf, 0, WDR_TIMEOUT) < 0) {
 				err("urb failed to set to xon/xoff flow control");
 			}
@@ -1951,7 +2040,7 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_
 					    usb_sndctrlpipe(dev, 0),
 					    FTDI_SIO_SET_FLOW_CTRL_REQUEST, 
 					    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-					    0, 0, 
+					    0, priv->interface, 
 					    buf, 0, WDR_TIMEOUT) < 0) {
 				err("urb failed to clear flow control");
 			}				
@@ -1985,13 +2074,14 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file)
 		break;
 	case FT8U232AM:
 	case FT232BM:
+	case FT2232C:
 		/* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same
 		   format as the data returned from the in point */
 		if ((ret = usb_control_msg(port->serial->dev, 
 					   usb_rcvctrlpipe(port->serial->dev, 0),
 					   FTDI_SIO_GET_MODEM_STATUS_REQUEST, 
 					   FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
-					   0, 0, 
+					   0, priv->interface, 
 					   buf, 2, WDR_TIMEOUT)) < 0 ) {
 			err("%s Could not get modem status of device - err: %d", __FUNCTION__,
 			    ret);
@@ -2206,6 +2296,9 @@ static int __init ftdi_init (void)
 	retval = usb_serial_register(&ftdi_FT232BM_device);
 	if (retval)
 		goto failed_FT232BM_register;
+	retval = usb_serial_register(&ftdi_FT2232C_device);
+	if (retval)
+		goto failed_FT2232C_register;
 	retval = usb_serial_register(&ftdi_USB_UIRT_device);
 	if (retval)
 		goto failed_USB_UIRT_register;
@@ -2223,6 +2316,8 @@ failed_usb_register:
 failed_HE_TIRA1_register:
 	usb_serial_deregister(&ftdi_USB_UIRT_device);
 failed_USB_UIRT_register:
+	usb_serial_deregister(&ftdi_FT2232C_device);
+failed_FT2232C_register:
 	usb_serial_deregister(&ftdi_FT232BM_device);
 failed_FT232BM_register:
 	usb_serial_deregister(&ftdi_8U232AM_device);
@@ -2241,6 +2336,7 @@ static void __exit ftdi_exit (void)
 	usb_deregister (&ftdi_driver);
 	usb_serial_deregister (&ftdi_HE_TIRA1_device);
 	usb_serial_deregister (&ftdi_USB_UIRT_device);
+	usb_serial_deregister (&ftdi_FT2232C_device);
 	usb_serial_deregister (&ftdi_FT232BM_device);
 	usb_serial_deregister (&ftdi_8U232AM_device);
 	usb_serial_deregister (&ftdi_SIO_device);
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 02554035e..232213b02 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -26,6 +26,7 @@
 #define FTDI_SIO_PID	0x8372	/* Product Id SIO application of 8U100AX  */
 #define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */
 #define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
+#define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
 #define FTDI_RELAIS_PID	0xFA10  /* Relais device from Rudolf Gugler */
 #define FTDI_NF_RIC_VID	0x0DCD	/* Vendor Id */
 #define FTDI_NF_RIC_PID	0x0001	/* Product Id */
@@ -234,6 +235,21 @@
 #define FTDI_SIO_SET_EVENT_CHAR	6 /* Set the event character */
 #define FTDI_SIO_SET_ERROR_CHAR	7 /* Set the error character */
 
+/* Port interface code for FT2232C */
+#define INTERFACE_A		1
+#define INTERFACE_B		2
+
+
+/*
+ *   BmRequestType:  1100 0000b
+ *   bRequest:       FTDI_E2_READ
+ *   wValue:         0
+ *   wIndex:         Address of word to read
+ *   wLength:        2
+ *   Data:           Will return a word of data from E2Address
+ *
+ */
+
 /* Port Identifier Table */
 #define PIT_DEFAULT 		0 /* SIOA */
 #define PIT_SIOA		1 /* SIOA */
@@ -333,6 +349,7 @@ typedef enum {
 	SIO = 1,
 	FT8U232AM = 2,
 	FT232BM = 3,
+	FT2232C = 4,
 } ftdi_chip_type_t;
 
 typedef enum {
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index e727628bd..1ef47613b 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -479,7 +479,7 @@ static void get_boot_desc		(struct edgeport_serial *edge_serial);
 static void load_application_firmware	(struct edgeport_serial *edge_serial);
 
 
-static void unicode_to_ascii		(char *string, short *unicode, int unicode_size);
+static void unicode_to_ascii		(char *string, __le16 *unicode, int unicode_size);
 
 
 
@@ -504,7 +504,7 @@ static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial)
 	__u32 BootNewVer;
 	__u8 BootMajorVersion;                  
 	__u8 BootMinorVersion;                  
-	__u16 BootBuildNumber;
+	__le16 BootBuildNumber;
 	__u8 *BootImage;      
 	__u32 BootSize;
 	struct edge_firmware_image_record *record;
@@ -653,7 +653,7 @@ static void get_product_info(struct edgeport_serial *edge_serial)
 
 	memset (product_info, 0, sizeof(struct edgeport_product_info));
 
-	product_info->ProductId		= (__u16)(edge_serial->serial->dev->descriptor.idProduct & ~ION_DEVICE_ID_GENERATION_2);
+	product_info->ProductId		= (__u16)(edge_serial->serial->dev->descriptor.idProduct & ~ION_DEVICE_ID_80251_NETCHIP);
 	product_info->NumPorts		= edge_serial->manuf_descriptor.NumPorts;
 	product_info->ProdInfoVer	= 0;
 
@@ -669,7 +669,7 @@ static void get_product_info(struct edgeport_serial *edge_serial)
 	memcpy(product_info->ManufactureDescDate, edge_serial->manuf_descriptor.DescDate, sizeof(edge_serial->manuf_descriptor.DescDate));
 
 	// check if this is 2nd generation hardware
-	if (edge_serial->serial->dev->descriptor.idProduct & ION_DEVICE_ID_GENERATION_2) {
+	if (edge_serial->serial->dev->descriptor.idProduct & ION_DEVICE_ID_80251_NETCHIP) {
 		product_info->FirmwareMajorVersion	= OperationalCodeImageVersion_GEN2.MajorVersion;
 		product_info->FirmwareMinorVersion	= OperationalCodeImageVersion_GEN2.MinorVersion;
 		product_info->FirmwareBuildNumber	= cpu_to_le16(OperationalCodeImageVersion_GEN2.BuildNumber);
@@ -900,12 +900,7 @@ static void edge_bulk_out_data_callback (struct urb *urb, struct pt_regs *regs)
 
 	if (tty && edge_port->open) {
 		/* let the tty driver wakeup if it has a special write_wakeup function */
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
-			(tty->ldisc.write_wakeup)(tty);
-		}
-
-		/* tell the tty driver that something has changed */
-		wake_up_interruptible(&tty->write_wait);
+		tty_wakeup(tty);
 	}
 
 	// Release the Write URB
@@ -1389,7 +1384,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
 	//	to bother queueing a write. If it's too small, say a few bytes,
 	//	it's better to wait for more credits so we can do a larger
 	//	write.
-	if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits)) {
+	if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits,EDGE_FW_BULK_MAX_PACKET_SIZE)) {
 		dbg("%s(%d) Not enough credit - fifo %d TxCredit %d", __FUNCTION__, edge_port->port->number, fifo->count, edge_port->txCredits );
 		return;
 	}
@@ -2747,7 +2742,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct termio
  *	ASCII range, but it's only for debugging...
  *	NOTE: expects the unicode in LE format
  ****************************************************************************/
-static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
+static void unicode_to_ascii (char *string, __le16 *unicode, int unicode_size)
 {
 	int i;
 	for (i = 0; i < unicode_size; ++i) {
@@ -3007,9 +3002,6 @@ static void edge_shutdown (struct usb_serial *serial)
 static int __init edgeport_init(void)
 {
 	int retval;
-	retval = usb_serial_register(&edgeport_1port_device);
-	if (retval) 
-		goto failed_1port_device_register;
 	retval = usb_serial_register(&edgeport_2port_device);
 	if (retval)
 		goto failed_2port_device_register;
@@ -3031,8 +3023,6 @@ failed_8port_device_register:
 failed_4port_device_register:
 	usb_serial_deregister(&edgeport_2port_device);
 failed_2port_device_register:
-	usb_serial_deregister(&edgeport_1port_device);
-failed_1port_device_register:
 	return retval;
 }
 
@@ -3045,7 +3035,6 @@ failed_1port_device_register:
 static void __exit edgeport_exit (void)
 {
 	usb_deregister (&io_driver);
-	usb_serial_deregister (&edgeport_1port_device);
 	usb_serial_deregister (&edgeport_2port_device);
 	usb_serial_deregister (&edgeport_4port_device);
 	usb_serial_deregister (&edgeport_8port_device);
diff --git a/drivers/usb/serial/io_edgeport.h b/drivers/usb/serial/io_edgeport.h
index 386139d45..5112d7aac 100644
--- a/drivers/usb/serial/io_edgeport.h
+++ b/drivers/usb/serial/io_edgeport.h
@@ -107,11 +107,11 @@ struct edgeport_product_info {
 
 	__u8	BootMajorVersion;		/* Boot Firmware version: xx. */
 	__u8	BootMinorVersion;		/*	   		  yy. */
-	__u16	BootBuildNumber;		/*		      	  zzzz (LE format) */
+	__le16	BootBuildNumber;		/*		      	  zzzz (LE format) */
 
 	__u8	FirmwareMajorVersion;		/* Operational Firmware version:xx. */
 	__u8	FirmwareMinorVersion;		/*				yy. */
-	__u16	FirmwareBuildNumber;		/*				zzzz (LE format) */
+	__le16	FirmwareBuildNumber;		/*				zzzz (LE format) */
 
 	__u8	ManufactureDescDate[3];		/* MM/DD/YY when descriptor template was compiled */
 	__u8	Unused1[1];			/* Available */
diff --git a/drivers/usb/serial/io_fw_down.h b/drivers/usb/serial/io_fw_down.h
index 245740eb1..d01ec7b22 100644
--- a/drivers/usb/serial/io_fw_down.h
+++ b/drivers/usb/serial/io_fw_down.h
@@ -17,7 +17,7 @@
 		unsigned short	Addr;
 		unsigned short	Len;
 		unsigned char	Data[0];
-	} __attribute ((packed));
+	} __attribute__ ((packed));
 
 	struct edge_firmware_version_info {
 		unsigned char	MajorVersion;
@@ -36,11 +36,11 @@ static unsigned char IMAGE_ARRAY_NAME[] = {
 
 // Segment #1, Start Address 00ff0000, Length 6
 0xff,0x00,0x00,0x00,0x06,0x00,
-    0x02, 0x00, 0x80, 0x02, 0x49, 0x39, 
+    0x02, 0x00, 0x80, 0x02, 0x44, 0xb0, 
 
 // Segment #2, Start Address 00ff000b, Length 3
 0xff,0x00,0x0b,0x00,0x03,0x00,
-    0x02, 0x44, 0x1a, 
+    0x02, 0x44, 0x72, 
 
 // Segment #3, Start Address 00ff0013, Length 3
 0xff,0x00,0x13,0x00,0x03,0x00,
@@ -72,11 +72,11 @@ static unsigned char IMAGE_ARRAY_NAME[] = {
 
 // Segment #10, Start Address 00ff004b, Length 3
 0xff,0x00,0x4b,0x00,0x03,0x00,
-    0x02, 0x70, 0xd4, 
+    0x02, 0x6e, 0xc4, 
 
 // Segment #11, Start Address 00ff0053, Length 3
 0xff,0x00,0x53,0x00,0x03,0x00,
-    0x02, 0x77, 0x9d, 
+    0x02, 0x75, 0x8d, 
 
 // Segment #12, Start Address 00ff007b, Length 3
 0xff,0x00,0x7b,0x00,0x03,0x00,
@@ -86,657 +86,745 @@ static unsigned char IMAGE_ARRAY_NAME[] = {
 0xff,0x00,0x80,0x00,0x07,0x00,
     0x7e, 0x14, 0x00, 0x00, 0x02, 0x40, 0x51, 
 
-// Segment #14, Start Address 00ff4000, Length 15920
-0xff,0x00,0x00,0x40,0x30,0x3e,
+// Segment #14, Start Address 00ff3000, Length 2178
+0xff,0x00,0x00,0x30,0x82,0x08,
+    0x12, 0x37, 0x28, 0x12, 0x30, 0x3e, 0x12, 0x30, 0x54, 0x12, 0x30, 0xe5, 0x12, 0x31, 0x68, 0x12, 
+    0x35, 0x20, 0x12, 0x38, 0x58, 0x12, 0x31, 0x15, 0x12, 0x31, 0x40, 0x12, 0x30, 0xa0, 0x80, 0xe0, 
+    0xe5, 0x23, 0x60, 0x19, 0x7e, 0x14, 0x00, 0x00, 0x09, 0xb1, 0x01, 0xcf, 0xb4, 0x00, 0x02, 0x80, 
+    0x05, 0x14, 0x19, 0xb1, 0x01, 0xcf, 0xa5, 0x0b, 0xbe, 0x31, 0x2f, 0x78, 0xeb, 0x22, 0xc2, 0xaf, 
+    0x7e, 0xb3, 0x3f, 0xf1, 0xb4, 0x01, 0x0a, 0xc0, 0xf1, 0x75, 0xf1, 0x02, 0x12, 0x70, 0xef, 0xd0, 
+    0xf1, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0xe5, 0x22, 0x60, 0x43, 0x7e, 0x07, 0x01, 0xe1, 0xbe, 0x04, 
+    0x03, 0x80, 0x38, 0x39, 0x7e, 0x04, 0x80, 0x00, 0x7e, 0x20, 0x00, 0x13, 0x50, 0x21, 0x09, 0xa0, 
+    0x00, 0x04, 0x4e, 0xa0, 0x05, 0x19, 0xa0, 0x00, 0x04, 0x0a, 0x32, 0x09, 0x53, 0x67, 0x8e, 0x5e, 
+    0x51, 0x27, 0x68, 0x0b, 0x09, 0xa0, 0x00, 0x10, 0x4e, 0xa0, 0x01, 0x19, 0xa0, 0x00, 0x10, 0x2e, 
+    0x04, 0x01, 0x00, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 0x78, 0xd1, 0x75, 0x22, 0x00, 0xd2, 0xaf, 0x22, 
+    0xc2, 0xaf, 0x7e, 0x20, 0x00, 0x7e, 0x30, 0x01, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x32, 0x01, 
+    0x8f, 0xbe, 0x34, 0x00, 0x00, 0x68, 0x12, 0x7e, 0xb1, 0x21, 0xa5, 0x4b, 0x7a, 0xb1, 0x21, 0xca, 
+    0x19, 0x49, 0x22, 0x30, 0xd5, 0x99, 0x24, 0xda, 0x19, 0x3e, 0x30, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 
+    0x78, 0xd6, 0xd2, 0xaf, 0x22, 0x46, 0x0f, 0x49, 0x67, 0x4c, 0xbf, 0x50, 0x17, 0x53, 0x6f, 0x56, 
+    0xc7, 0x5a, 0x1f, 0x5d, 0x77, 0xc2, 0xaf, 0xe5, 0x32, 0x60, 0x14, 0x7e, 0x20, 0x00, 0x13, 0x50, 
+    0x07, 0xca, 0xb8, 0x12, 0x31, 0x02, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 0x78, 0xef, 0xd2, 
+    0xaf, 0x22, 0xca, 0x28, 0x12, 0x67, 0xab, 0xda, 0x28, 0x40, 0x09, 0x0a, 0x22, 0x09, 0xb2, 0x67, 
+    0x8e, 0xf4, 0x52, 0x32, 0x22, 0xc2, 0xaf, 0xe5, 0x34, 0x60, 0x14, 0x7e, 0x20, 0x00, 0x13, 0x50, 
+    0x07, 0xca, 0xb8, 0x12, 0x31, 0x32, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 0x78, 0xef, 0xd2, 
+    0xaf, 0x22, 0xca, 0x28, 0x0a, 0x22, 0x09, 0x42, 0x00, 0x3e, 0x12, 0x69, 0xc2, 0xda, 0x28, 0x22, 
+    0xc2, 0xaf, 0xe5, 0x35, 0x60, 0x14, 0x7e, 0x20, 0x00, 0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x31, 
+    0x5d, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 0x78, 0xef, 0xd2, 0xaf, 0x22, 0xca, 0x28, 0x7e, 
+    0x40, 0x00, 0x12, 0x6c, 0x5b, 0xda, 0x28, 0x22, 0xc2, 0xaf, 0xe5, 0x23, 0x60, 0x14, 0x7e, 0x20, 
+    0x00, 0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x31, 0x85, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 
+    0x78, 0xef, 0xd2, 0xaf, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x31, 0x90, 0x89, 0x24, 
+    0x31, 0xa0, 0x32, 0x10, 0x32, 0x80, 0x32, 0xf0, 0x33, 0x60, 0x33, 0xd0, 0x34, 0x40, 0x34, 0xb0, 
+    0x7e, 0x27, 0x01, 0x8f, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x80, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x49, 0x30, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0x9f, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x9f, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xcf, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xcf, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x18, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xcf, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x27, 0x01, 0x91, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x81, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x4c, 0x88, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0xa1, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xa1, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd0, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xd0, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x19, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xd0, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x27, 0x01, 0x93, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x82, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x4f, 0xe0, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0xa3, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xa3, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd1, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xd1, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1a, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xd1, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x27, 0x01, 0x95, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x83, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x53, 0x38, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0xa5, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xa5, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd2, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xd2, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1b, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xd2, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x27, 0x01, 0x97, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x84, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x56, 0x90, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0xa7, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xa7, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd3, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xd3, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1c, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xd3, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x27, 0x01, 0x99, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x85, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x59, 0xe8, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0xa9, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xa9, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd4, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xd4, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1d, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xd4, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x27, 0x01, 0x9b, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x86, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x5d, 0x40, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0xab, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xab, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd5, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xd5, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1e, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xd5, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x27, 0x01, 0x9d, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x87, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x60, 0x98, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 
+    0x01, 0xad, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0xad, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xd6, 0x80, 
+    0x2e, 0x7e, 0x63, 0x01, 0xd6, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 
+    0xa0, 0xc8, 0x12, 0x62, 0xb6, 0x40, 0x18, 0x75, 0x31, 0xb3, 0x12, 0x7c, 0x15, 0xc2, 0x1f, 0x6c, 
+    0x00, 0x7a, 0x03, 0x01, 0xd6, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0xc2, 0xaf, 0xe5, 0x24, 0x60, 0x14, 0x7e, 0x20, 0x00, 0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x35, 
+    0x3d, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 0x78, 0xef, 0xd2, 0xaf, 0x22, 0x7c, 0xb2, 0x23, 
+    0x0a, 0x2b, 0x49, 0x22, 0x35, 0x48, 0x89, 0x24, 0x35, 0x58, 0x35, 0x92, 0x35, 0xcc, 0x36, 0x06, 
+    0x36, 0x40, 0x36, 0x7a, 0x36, 0xb4, 0x36, 0xee, 0x7e, 0x24, 0x80, 0x00, 0x09, 0xb2, 0x00, 0x14, 
+    0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x49, 0x30, 
+    0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 
+    0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 0x20, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 
+    0xf1, 0x22, 0x7e, 0x24, 0x81, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 
+    0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x4c, 0x88, 0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 
+    0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 
+    0x21, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x82, 0x00, 
+    0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 
+    0x12, 0x12, 0x4f, 0xe0, 0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 
+    0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 0x22, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 
+    0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x83, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 
+    0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x53, 0x38, 0x7d, 0x21, 
+    0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 
+    0x12, 0x7c, 0x15, 0xc2, 0x23, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 
+    0x7e, 0x24, 0x84, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 
+    0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x56, 0x90, 0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 
+    0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 0x24, 0xc0, 
+    0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x85, 0x00, 0x09, 0xb2, 
+    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 
+    0x59, 0xe8, 0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 
+    0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 0x25, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 
+    0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x86, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 
+    0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x5d, 0x40, 0x7d, 0x21, 0xda, 0x19, 
+    0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 
+    0x15, 0xc2, 0x26, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 
+    0x87, 0x00, 0x09, 0xb2, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 
+    0x19, 0x7d, 0x12, 0x12, 0x60, 0x98, 0x7d, 0x21, 0xda, 0x19, 0x5e, 0xb0, 0x01, 0x7e, 0xa0, 0x90, 
+    0x12, 0x62, 0x93, 0x40, 0x12, 0x75, 0x31, 0xb8, 0x12, 0x7c, 0x15, 0xc2, 0x27, 0xc0, 0xf1, 0x75, 
+    0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0xc2, 0xaf, 0xe5, 0x33, 0x60, 0x14, 0x7e, 0x20, 
+    0x00, 0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x37, 0x45, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2f, 
+    0x78, 0xef, 0xd2, 0xaf, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x37, 0x50, 0x89, 0x24, 
+    0x37, 0x60, 0x37, 0x7f, 0x37, 0x9e, 0x37, 0xbd, 0x37, 0xdc, 0x37, 0xfb, 0x38, 0x1a, 0x38, 0x39, 
+    0x7e, 0x24, 0x80, 0x00, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x48, 0x1b, 0xda, 0x19, 0x10, 0x04, 0x02, 
+    0x80, 0x0c, 0xd2, 0x01, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 
+    0x24, 0x81, 0x00, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x4b, 0x73, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 
+    0x0c, 0xd2, 0x01, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 
+    0x82, 0x00, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x4e, 0xcb, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 
+    0xd2, 0x01, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x83, 
+    0x00, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x52, 0x23, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 0xd2, 
+    0x01, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x84, 0x00, 
+    0xca, 0x19, 0x7d, 0x12, 0x12, 0x55, 0x7b, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 0xd2, 0x01, 
+    0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x85, 0x00, 0xca, 
+    0x19, 0x7d, 0x12, 0x12, 0x58, 0xd3, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 0xd2, 0x01, 0xc0, 
+    0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x86, 0x00, 0xca, 0x19, 
+    0x7d, 0x12, 0x12, 0x5c, 0x2b, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 0xd2, 0x01, 0xc0, 0xf1, 
+    0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x7e, 0x24, 0x87, 0x00, 0xca, 0x19, 0x7d, 
+    0x12, 0x12, 0x5f, 0x83, 0xda, 0x19, 0x10, 0x04, 0x02, 0x80, 0x0c, 0xd2, 0x01, 0xc0, 0xf1, 0x75, 
+    0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0xc2, 0xaf, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0xa9, 
+    0x32, 0xf2, 0x1a, 0x7e, 0x07, 0x01, 0xe1, 0xbe, 0x04, 0x00, 0x00, 0x78, 0x10, 0xe5, 0xf5, 0x33, 
+    0x82, 0xe7, 0x40, 0x09, 0x85, 0x31, 0x31, 0x12, 0x7c, 0x15, 0x75, 0xf6, 0x00, 0xd0, 0xf1, 0xd2, 
+    0xaf, 0x22, 
+
+// Segment #15, Start Address 00ff4000, Length 15381
+0xff,0x00,0x00,0x40,0x15,0x3c,
     0x7e, 0x04, 0x00, 0x01, 0x7e, 0x14, 0x7f, 0xf8, 0x7e, 0x24, 0x00, 0xfe, 0x7d, 0x31, 0x0b, 0x1a, 
-    0x50, 0x1b, 0x0a, 0x50, 0x7e, 0x14, 0x40, 0x1b, 0x02, 0x40, 0x6a, 0x7e, 0xf8, 0x00, 0x59, 0xd2, 
-    0x04, 0xc2, 0x94, 0xd2, 0x95, 0x7e, 0xf4, 0x40, 0x2c, 0x02, 0x40, 0x7c, 0x12, 0x7f, 0x3f, 0xf5, 
-    0x2e, 0x7a, 0xa1, 0x2d, 0x7a, 0x11, 0x58, 0x12, 0x77, 0xda, 0x12, 0x40, 0xdc, 0x7e, 0xb3, 0x3f, 
-    0xf1, 0x60, 0x03, 0x12, 0x43, 0x68, 0x75, 0xf1, 0x00, 0x12, 0x78, 0x7f, 0xd2, 0xaf, 0x02, 0x44, 
-    0x06, 0x7e, 0x04, 0x00, 0xff, 0x7e, 0x18, 0x40, 0x5f, 0x7a, 0x1c, 0x00, 0x01, 0x89, 0x18, 0xa9, 
+    0x50, 0x1b, 0x0a, 0x50, 0x7e, 0x14, 0x40, 0x1b, 0x02, 0x40, 0x6a, 0x7e, 0xf8, 0x00, 0x6f, 0xd2, 
+    0x04, 0xc2, 0x94, 0xd2, 0x95, 0x7e, 0xf4, 0x40, 0x2c, 0x02, 0x40, 0x7c, 0x12, 0x7d, 0x30, 0xf5, 
+    0x2f, 0x7a, 0xa1, 0x30, 0x7a, 0x11, 0x6e, 0x12, 0x75, 0xca, 0x12, 0x40, 0xdc, 0x7e, 0xb3, 0x3f, 
+    0xf1, 0x60, 0x03, 0x12, 0x43, 0xd4, 0x75, 0xf1, 0x00, 0x12, 0x76, 0x6f, 0xd2, 0xaf, 0x02, 0x30, 
+    0x00, 0x7e, 0x04, 0x00, 0xff, 0x7e, 0x18, 0x40, 0x5f, 0x7a, 0x1c, 0x00, 0x01, 0x89, 0x18, 0xa9, 
     0x25, 0x87, 0x03, 0xa9, 0xd5, 0x87, 0xd2, 0x93, 0x89, 0x08, 0x7e, 0x04, 0x00, 0xff, 0x7e, 0x18, 
     0x40, 0x78, 0x7a, 0x1c, 0x00, 0x01, 0x89, 0x18, 0xc2, 0x93, 0x89, 0x08, 0x7e, 0x08, 0x00, 0x20, 
-    0x7e, 0x44, 0x04, 0x00, 0x7e, 0x40, 0x00, 0x7e, 0xe4, 0x40, 0x8e, 0x02, 0x7e, 0x4b, 0x7e, 0x08, 
-    0x01, 0x59, 0x7e, 0x44, 0x28, 0x7c, 0x7e, 0x40, 0x00, 0x7e, 0xe4, 0x40, 0xa0, 0x02, 0x7e, 0x4b, 
-    0x7e, 0x08, 0x00, 0x59, 0x7e, 0x44, 0x01, 0x00, 0x7e, 0x40, 0x53, 0x7e, 0xe4, 0x40, 0xb2, 0x02, 
-    0x7e, 0x4b, 0x75, 0x57, 0x20, 0x75, 0x56, 0x30, 0x7e, 0x04, 0x00, 0x08, 0x75, 0x54, 0x58, 0x75, 
-    0x55, 0x08, 0x75, 0x51, 0x08, 0x75, 0x53, 0x01, 0x75, 0x89, 0x01, 0x75, 0x8a, 0x01, 0x75, 0x8c, 
-    0x00, 0xd2, 0x8c, 0x7e, 0x04, 0x00, 0x02, 0x7a, 0x05, 0x42, 0x89, 0xf4, 0x75, 0xb7, 0x7f, 0x75, 
+    0x7e, 0x44, 0x04, 0x00, 0x7e, 0x40, 0x00, 0x7e, 0xe4, 0x40, 0x8e, 0x02, 0x7c, 0x30, 0x7e, 0x08, 
+    0x01, 0x6f, 0x7e, 0x44, 0x28, 0x7c, 0x7e, 0x40, 0x00, 0x7e, 0xe4, 0x40, 0xa0, 0x02, 0x7c, 0x30, 
+    0x7e, 0x08, 0x00, 0x6f, 0x7e, 0x44, 0x01, 0x00, 0x7e, 0x40, 0x53, 0x7e, 0xe4, 0x40, 0xb2, 0x02, 
+    0x7c, 0x30, 0x75, 0x6d, 0x20, 0x75, 0x6c, 0x30, 0x7e, 0x04, 0x00, 0x08, 0x75, 0x6a, 0x58, 0x75, 
+    0x6b, 0x08, 0x75, 0x67, 0x08, 0x75, 0x69, 0x01, 0x75, 0x89, 0x01, 0x75, 0x8a, 0x01, 0x75, 0x8c, 
+    0x00, 0xd2, 0x8c, 0x7e, 0x04, 0x00, 0x02, 0x7a, 0x05, 0x58, 0x89, 0xf4, 0x75, 0xb7, 0x7f, 0x75, 
     0xb8, 0x7f, 0x75, 0xb3, 0x07, 0x75, 0xb2, 0x07, 0xd2, 0xa9, 0x22, 0xd2, 0x92, 0xe4, 0xd5, 0xe0, 
-    0xfd, 0xc2, 0x92, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x2e, 0x7e, 0xa0, 0x08, 0x19, 0xa2, 0x00, 
-    0x10, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0xf2, 0x7e, 0x20, 0x00, 0x12, 0x41, 0x72, 0x0b, 0x20, 
-    0xbe, 0x21, 0x2e, 0x78, 0xf6, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x74, 0xbf, 0x19, 0xb0, 
+    0xfd, 0xc2, 0x92, 0x7e, 0x24, 0x80, 0x00, 0x7e, 0x11, 0x2f, 0x7e, 0xa0, 0x08, 0x19, 0xa2, 0x00, 
+    0x10, 0x2e, 0x24, 0x01, 0x00, 0xa5, 0xd9, 0xf2, 0x7e, 0x20, 0x00, 0x12, 0x41, 0x7e, 0x0b, 0x20, 
+    0xbe, 0x21, 0x2f, 0x78, 0xf6, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x74, 0xbf, 0x19, 0xb0, 
     0x00, 0x0c, 0x74, 0x10, 0x19, 0xb0, 0x00, 0x08, 0x74, 0x80, 0x19, 0xb0, 0x00, 0x0c, 0x7e, 0x54, 
     0x00, 0x02, 0x19, 0xa0, 0x00, 0x04, 0x19, 0xb0, 0x00, 0x00, 0x74, 0x03, 0x19, 0xb0, 0x00, 0x0c, 
-    0x74, 0x07, 0x20, 0x68, 0x02, 0x74, 0x0f, 0x19, 0xb0, 0x00, 0x04, 0x30, 0x6b, 0x17, 0x74, 0xbf, 
-    0x19, 0xb0, 0x00, 0x0c, 0x74, 0x28, 0x20, 0x68, 0x02, 0x74, 0x20, 0x19, 0xb0, 0x00, 0x04, 0x74, 
-    0x03, 0x19, 0xb0, 0x00, 0x0c, 0x74, 0xa7, 0x19, 0xb0, 0x00, 0x08, 0x74, 0x0c, 0x19, 0xb0, 0x00, 
-    0x10, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0xe4, 0x19, 0xb0, 0x00, 0x04, 0x09, 0xb0, 0x00, 
-    0x10, 0x54, 0x08, 0x19, 0xb0, 0x00, 0x10, 0x74, 0xa7, 0x19, 0xb0, 0x00, 0x08, 0x22, 0x7c, 0xb2, 
-    0x23, 0x0a, 0x2b, 0x49, 0x22, 0x41, 0x99, 0x89, 0x24, 0x41, 0xa9, 0x41, 0xc6, 0x41, 0xe3, 0x42, 
-    0x00, 0x42, 0x1d, 0x42, 0x3a, 0x42, 0x57, 0x42, 0x74, 0xc2, 0x10, 0xc2, 0x18, 0xc2, 0x08, 0x7e, 
-    0x04, 0x09, 0xcd, 0x7a, 0x07, 0x01, 0x59, 0x7a, 0x07, 0x01, 0x69, 0x6d, 0x00, 0x7a, 0x07, 0x01, 
-    0x79, 0x7a, 0x07, 0x01, 0x89, 0x22, 0xc2, 0x11, 0xc2, 0x19, 0xc2, 0x09, 0x7e, 0x04, 0x0d, 0xcd, 
-    0x7a, 0x07, 0x01, 0x5b, 0x7a, 0x07, 0x01, 0x6b, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x7b, 0x7a, 0x07, 
-    0x01, 0x8b, 0x22, 0xc2, 0x12, 0xc2, 0x1a, 0xc2, 0x0a, 0x7e, 0x04, 0x11, 0xcd, 0x7a, 0x07, 0x01, 
-    0x5d, 0x7a, 0x07, 0x01, 0x6d, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x7d, 0x7a, 0x07, 0x01, 0x8d, 0x22, 
-    0xc2, 0x13, 0xc2, 0x1b, 0xc2, 0x0b, 0x7e, 0x04, 0x15, 0xcd, 0x7a, 0x07, 0x01, 0x5f, 0x7a, 0x07, 
-    0x01, 0x6f, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x7f, 0x7a, 0x07, 0x01, 0x8f, 0x22, 0xc2, 0x14, 0xc2, 
-    0x1c, 0xc2, 0x0c, 0x7e, 0x04, 0x19, 0xcd, 0x7a, 0x07, 0x01, 0x61, 0x7a, 0x07, 0x01, 0x71, 0x6d, 
-    0x00, 0x7a, 0x07, 0x01, 0x81, 0x7a, 0x07, 0x01, 0x91, 0x22, 0xc2, 0x15, 0xc2, 0x1d, 0xc2, 0x0d, 
-    0x7e, 0x04, 0x1d, 0xcd, 0x7a, 0x07, 0x01, 0x63, 0x7a, 0x07, 0x01, 0x73, 0x6d, 0x00, 0x7a, 0x07, 
-    0x01, 0x83, 0x7a, 0x07, 0x01, 0x93, 0x22, 0xc2, 0x16, 0xc2, 0x1e, 0xc2, 0x0e, 0x7e, 0x04, 0x21, 
-    0xcd, 0x7a, 0x07, 0x01, 0x65, 0x7a, 0x07, 0x01, 0x75, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x85, 0x7a, 
-    0x07, 0x01, 0x95, 0x22, 0xc2, 0x17, 0xc2, 0x1f, 0xc2, 0x0f, 0x7e, 0x04, 0x25, 0xcd, 0x7a, 0x07, 
-    0x01, 0x67, 0x7a, 0x07, 0x01, 0x77, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x87, 0x7a, 0x07, 0x01, 0x97, 
-    0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x42, 0x9c, 0x89, 0x24, 0x42, 0xac, 0x42, 0xc3, 
-    0x42, 0xda, 0x42, 0xf1, 0x43, 0x08, 0x43, 0x1f, 0x43, 0x36, 0x43, 0x4d, 0x30, 0x40, 0x07, 0x20, 
-    0x58, 0x04, 0xc2, 0x28, 0x80, 0x0c, 0x30, 0x48, 0x07, 0x20, 0x50, 0x04, 0xc2, 0x28, 0x80, 0x02, 
-    0xd2, 0x28, 0x22, 0x30, 0x41, 0x07, 0x20, 0x59, 0x04, 0xc2, 0x29, 0x80, 0x0c, 0x30, 0x49, 0x07, 
-    0x20, 0x51, 0x04, 0xc2, 0x29, 0x80, 0x02, 0xd2, 0x29, 0x22, 0x30, 0x42, 0x07, 0x20, 0x5a, 0x04, 
-    0xc2, 0x2a, 0x80, 0x0c, 0x30, 0x4a, 0x07, 0x20, 0x52, 0x04, 0xc2, 0x2a, 0x80, 0x02, 0xd2, 0x2a, 
-    0x22, 0x30, 0x43, 0x07, 0x20, 0x5b, 0x04, 0xc2, 0x2b, 0x80, 0x0c, 0x30, 0x4b, 0x07, 0x20, 0x53, 
-    0x04, 0xc2, 0x2b, 0x80, 0x02, 0xd2, 0x2b, 0x22, 0x30, 0x44, 0x07, 0x20, 0x5c, 0x04, 0xc2, 0x2c, 
-    0x80, 0x0c, 0x30, 0x4c, 0x07, 0x20, 0x54, 0x04, 0xc2, 0x2c, 0x80, 0x02, 0xd2, 0x2c, 0x22, 0x30, 
-    0x45, 0x07, 0x20, 0x5d, 0x04, 0xc2, 0x2d, 0x80, 0x0c, 0x30, 0x4d, 0x07, 0x20, 0x55, 0x04, 0xc2, 
-    0x2d, 0x80, 0x02, 0xd2, 0x2d, 0x22, 0x30, 0x46, 0x07, 0x20, 0x5e, 0x04, 0xc2, 0x2e, 0x80, 0x0c, 
-    0x30, 0x4e, 0x07, 0x20, 0x56, 0x04, 0xc2, 0x2e, 0x80, 0x02, 0xd2, 0x2e, 0x22, 0x30, 0x47, 0x07, 
-    0x20, 0x5f, 0x04, 0xc2, 0x2f, 0x80, 0x0c, 0x30, 0x4f, 0x07, 0x20, 0x57, 0x04, 0xc2, 0x2f, 0x80, 
-    0x02, 0xd2, 0x2f, 0x22, 0x43, 0xcc, 0x43, 0x79, 0xbe, 0xb0, 0x02, 0x40, 0x01, 0x22, 0x23, 0x0a, 
-    0x5b, 0x49, 0x55, 0x43, 0x64, 0x99, 0x54, 0xd3, 0x22, 0xa9, 0xc5, 0x87, 0x12, 0x43, 0xd7, 0x7e, 
-    0x04, 0x05, 0xcd, 0x7a, 0x07, 0x01, 0xc1, 0x7a, 0x07, 0x01, 0xc3, 0x7e, 0x04, 0x01, 0xcd, 0x7a, 
-    0x07, 0x01, 0xc7, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x04, 0x76, 0xbd, 0x7a, 0x05, 0x4b, 0x75, 0xf1, 
-    0x01, 0x75, 0xe1, 0x1f, 0x75, 0xe4, 0x04, 0x75, 0xf4, 0x04, 0x75, 0xf1, 0x02, 0x75, 0xe1, 0x03, 
-    0x75, 0xe4, 0x04, 0x75, 0xf4, 0x04, 0x43, 0xa2, 0x1c, 0x12, 0x40, 0xeb, 0x7e, 0x20, 0x00, 0x12, 
-    0x41, 0x8e, 0x0b, 0x20, 0xbe, 0x21, 0x2e, 0x78, 0xf6, 0xd2, 0xa8, 0x22, 0xa9, 0xd5, 0x87, 0x12, 
-    0x43, 0xd7, 0xd2, 0x92, 0xc2, 0xa8, 0x22, 0x75, 0xa3, 0x00, 0x53, 0xa2, 0x03, 0x75, 0xc1, 0x00, 
-    0x53, 0xc0, 0x03, 0x7e, 0x00, 0x05, 0x7a, 0x01, 0xf1, 0x43, 0xf4, 0x80, 0x43, 0xe4, 0x80, 0xe5, 
-    0xf2, 0x54, 0x7f, 0x44, 0x08, 0xf5, 0xf2, 0xe5, 0xe2, 0x54, 0x7f, 0x44, 0x08, 0xf5, 0xe2, 0x75, 
-    0xe1, 0x10, 0xa5, 0xd8, 0xe1, 0x22, 0x12, 0x44, 0x76, 0x12, 0x44, 0x8c, 0x12, 0x45, 0x27, 0x12, 
-    0x45, 0x57, 0x12, 0x49, 0x0f, 0x12, 0x44, 0xd8, 0x80, 0xec, 0xca, 0x09, 0x12, 0x44, 0x58, 0x10, 
-    0x01, 0x12, 0xd5, 0x51, 0x1e, 0x63, 0x53, 0x01, 0x7e, 0x00, 0x54, 0x2e, 0x01, 0x53, 0xa5, 0xe6, 
-    0xf5, 0x51, 0x80, 0x12, 0x20, 0x02, 0x1e, 0x75, 0x53, 0x00, 0x85, 0x54, 0x51, 0xd2, 0x02, 0x74, 
-    0x00, 0x80, 0x0d, 0x30, 0x02, 0x0f, 0xc2, 0x02, 0x7e, 0x00, 0x56, 0x2e, 0x01, 0x53, 0xa5, 0xe6, 
-    0x53, 0x90, 0xcf, 0x42, 0x90, 0xda, 0x09, 0x32, 0xe5, 0x23, 0x60, 0x19, 0x7e, 0x14, 0x00, 0x00, 
-    0x09, 0xb1, 0x01, 0xb9, 0xb4, 0x00, 0x02, 0x80, 0x05, 0x14, 0x19, 0xb1, 0x01, 0xb9, 0xa5, 0x0a, 
-    0xbe, 0x21, 0x2e, 0x78, 0xeb, 0x22, 0xc2, 0xaf, 0x7e, 0xb3, 0x3f, 0xf1, 0xb4, 0x01, 0x0a, 0xc0, 
-    0xf1, 0x75, 0xf1, 0x02, 0x12, 0x72, 0xff, 0xd0, 0xf1, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0xe5, 0x22, 
-    0x60, 0x43, 0x7e, 0x07, 0x01, 0xcb, 0xbe, 0x04, 0x03, 0x80, 0x38, 0x39, 0x7e, 0x04, 0x80, 0x00, 
-    0x7e, 0x20, 0x00, 0x13, 0x50, 0x21, 0x09, 0xa0, 0x00, 0x04, 0x4e, 0xa0, 0x05, 0x19, 0xa0, 0x00, 
-    0x04, 0x0a, 0x32, 0x09, 0x53, 0x6a, 0x93, 0x5e, 0x51, 0x27, 0x68, 0x0b, 0x09, 0xa0, 0x00, 0x10, 
-    0x4e, 0xa0, 0x01, 0x19, 0xa0, 0x00, 0x10, 0x2e, 0x04, 0x01, 0x00, 0xa5, 0x0a, 0xbe, 0x21, 0x2e, 
-    0x78, 0xd1, 0x75, 0x22, 0x00, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0xe5, 0x26, 0x60, 0x36, 0x7e, 0x20, 
-    0x00, 0x7e, 0x30, 0x01, 0xe5, 0x26, 0xa5, 0x5b, 0x68, 0x21, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 
-    0x32, 0x01, 0x79, 0xbe, 0x34, 0x00, 0x00, 0x68, 0x12, 0x7e, 0xb1, 0x21, 0xa5, 0x4b, 0x7a, 0xb1, 
-    0x21, 0xca, 0x19, 0x49, 0x22, 0x45, 0x17, 0x99, 0x24, 0xda, 0x19, 0x3e, 0x30, 0xa5, 0x0a, 0xbe, 
-    0x21, 0x2e, 0x78, 0xd0, 0xd2, 0xaf, 0x22, 0x4a, 0x98, 0x4d, 0xcd, 0x51, 0x02, 0x54, 0x37, 0x57, 
-    0x6c, 0x5a, 0xa1, 0x5d, 0xd6, 0x61, 0x0b, 0xc2, 0xaf, 0xe5, 0x24, 0x60, 0x14, 0x7e, 0x20, 0x00, 
-    0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x45, 0x44, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2e, 0x78, 
-    0xef, 0xd2, 0xaf, 0x22, 0xca, 0x28, 0x12, 0x6a, 0xac, 0xda, 0x28, 0x40, 0x09, 0x0a, 0x22, 0x09, 
-    0xb2, 0x6a, 0x93, 0xf4, 0x52, 0x24, 0x22, 0xc2, 0xaf, 0xe5, 0x23, 0x60, 0x14, 0x7e, 0x20, 0x00, 
-    0x13, 0x50, 0x07, 0xca, 0xb8, 0x12, 0x45, 0x74, 0xda, 0xb8, 0xa5, 0x0a, 0xbe, 0x21, 0x2e, 0x78, 
-    0xef, 0xd2, 0xaf, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x45, 0x7f, 0x89, 0x24, 0x45, 
-    0x8f, 0x45, 0xff, 0x46, 0x6f, 0x46, 0xdf, 0x47, 0x4f, 0x47, 0xbf, 0x48, 0x2f, 0x48, 0x9f, 0x7e, 
-    0x27, 0x01, 0x79, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x80, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x4d, 
-    0x96, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x89, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x89, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xb9, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xb9, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x18, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xb9, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
-    0x27, 0x01, 0x7b, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x81, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x50, 
-    0xcb, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x8b, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x8b, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xba, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xba, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x19, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xba, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
-    0x27, 0x01, 0x7d, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x82, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x54, 
-    0x00, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x8d, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x8d, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbb, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xbb, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1a, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xbb, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
-    0x27, 0x01, 0x7f, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x83, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x57, 
-    0x35, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x8f, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x8f, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbc, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xbc, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1b, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xbc, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
-    0x27, 0x01, 0x81, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x84, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x5a, 
-    0x6a, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x91, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x91, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbd, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xbd, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1c, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xbd, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
-    0x27, 0x01, 0x83, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x85, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x5d, 
-    0x9f, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x93, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x93, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbe, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xbe, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1d, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xbe, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
-    0x27, 0x01, 0x85, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x86, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x60, 
-    0xd4, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x95, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x95, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xbf, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xbf, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1e, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xbf, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0x7e, 
-    0x27, 0x01, 0x87, 0xbe, 0x24, 0x00, 0x00, 0x78, 0x24, 0x7e, 0x24, 0x87, 0x00, 0x09, 0xb2, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x0b, 0xca, 0x19, 0x7d, 0x12, 0x12, 0x64, 
-    0x09, 0x7d, 0x21, 0xda, 0x19, 0x30, 0xe6, 0x18, 0x7e, 0x60, 0x00, 0x80, 0x1e, 0xbe, 0x27, 0x01, 
-    0x97, 0x68, 0x0d, 0x7a, 0x27, 0x01, 0x97, 0x7e, 0x60, 0x9c, 0x7a, 0x63, 0x01, 0xc0, 0x80, 0x2e, 
-    0x7e, 0x63, 0x01, 0xc0, 0xa5, 0xbe, 0x00, 0x26, 0x7e, 0x60, 0x01, 0x7e, 0xb0, 0x00, 0x7e, 0xa0, 
-    0xc8, 0x12, 0x65, 0xbf, 0x40, 0x18, 0x75, 0x2f, 0xb3, 0x12, 0x7e, 0x30, 0xc2, 0x1f, 0x6c, 0x00, 
-    0x7a, 0x03, 0x01, 0xc0, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0x22, 0xc2, 
-    0xaf, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0xa9, 0x32, 0xf2, 0x1a, 0x7e, 0x07, 0x01, 0xcb, 0xbe, 0x04, 
-    0x00, 0x00, 0x78, 0x10, 0xe5, 0xf5, 0x33, 0x82, 0xe7, 0x40, 0x09, 0x85, 0x31, 0x2f, 0x12, 0x7e, 
-    0x30, 0x75, 0xf6, 0x00, 0xd0, 0xf1, 0xd2, 0xaf, 0x22, 0xc0, 0xd0, 0xc0, 0xd1, 0xc0, 0xe0, 0xc0, 
-    0xf0, 0xca, 0x0b, 0xca, 0x1b, 0xca, 0x2b, 0xd2, 0x01, 0x75, 0x2f, 0x89, 0x12, 0x7e, 0x30, 0x7e, 
-    0x14, 0x80, 0x00, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x49, 0xd8, 0x20, 0x70, 0x5a, 
-    0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x49, 0xf0, 0x20, 0x71, 0x4b, 0xa5, 
-    0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x4a, 0x08, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 
-    0x08, 0x20, 0xe0, 0x03, 0x02, 0x4a, 0x20, 0x20, 0x72, 0x30, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 
-    0x20, 0xe0, 0x03, 0x02, 0x4a, 0x38, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 
-    0x4a, 0x50, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x4a, 0x68, 0xa5, 0x0a, 
-    0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x4a, 0x80, 0x30, 0x04, 0x0c, 0xc2, 0x04, 0xc0, 
-    0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0xd0, 
-    0xf0, 0xd0, 0xe0, 0xd0, 0xd1, 0xd0, 0xd0, 0x32, 0x75, 0x2f, 0x80, 0x12, 0x7e, 0x30, 0x54, 0x3e, 
-    0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x66, 0x34, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 
-    0x75, 0x2f, 0x81, 0x12, 0x7e, 0x30, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 
-    0x66, 0x74, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 0x75, 0x2f, 0x82, 0x12, 0x7e, 0x30, 0x54, 0x3e, 
-    0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x66, 0xb4, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 
-    0x75, 0x2f, 0x83, 0x12, 0x7e, 0x30, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 
-    0x66, 0xf4, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 0x75, 0x2f, 0x84, 0x12, 0x7e, 0x30, 0x54, 0x3e, 
-    0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x67, 0x34, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 
-    0x75, 0x2f, 0x85, 0x12, 0x7e, 0x30, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 
-    0x67, 0x74, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 0x75, 0x2f, 0x86, 0x12, 0x7e, 0x30, 0x54, 0x3e, 
-    0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x67, 0xb4, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 
-    0x75, 0x2f, 0x87, 0x12, 0x7e, 0x30, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 
-    0x67, 0xf4, 0xca, 0x06, 0x4f, 0x49, 0x89, 0x54, 0x10, 0x08, 0x01, 0x22, 0x20, 0x28, 0x03, 0xd2, 
-    0x08, 0x22, 0x75, 0x2f, 0xa0, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x80, 0x00, 0x80, 0x06, 0x20, 0x28, 
-    0x03, 0xd2, 0x08, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 
-    0x03, 0x12, 0x4d, 0x96, 0x30, 0x30, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x08, 0x22, 0x30, 0xe6, 0x02, 
-    0xd2, 0x60, 0x7e, 0x37, 0x01, 0x79, 0x7e, 0x27, 0x01, 0x99, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 
-    0x2e, 0x05, 0x32, 0x7a, 0x05, 0x32, 0x7a, 0x37, 0x01, 0x79, 0x7e, 0x37, 0x01, 0x59, 0x7d, 0x43, 
-    0x2d, 0x42, 0xbe, 0x44, 0x0d, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x59, 0x75, 0x2f, 0x94, 0x12, 
-    0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x60, 0xc4, 0x22, 0xc2, 
-    0x60, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x79, 0xbe, 0x24, 0x00, 
-    0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0x99, 0x28, 0x04, 0x7e, 0x27, 0x01, 0x99, 0x7e, 0x37, 0x01, 
-    0x79, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x32, 0x7a, 0x05, 0x32, 0x7a, 0x37, 0x01, 0x79, 0x7e, 
-    0x37, 0x01, 0x59, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x0d, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 
-    0x59, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 
-    0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x0d, 0xcd, 
-    0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x09, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 
-    0x59, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x4b, 0x0b, 0x22, 0xd2, 0x08, 0x7e, 
-    0x04, 0x09, 0xcd, 0x7a, 0x07, 0x01, 0x59, 0x7a, 0x07, 0x01, 0x69, 0x75, 0x2f, 0x94, 0x12, 0x7e, 
-    0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 
-    0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 
-    0x7e, 0x27, 0x01, 0xa9, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 
-    0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 
-    0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 
-    0x00, 0x00, 0x2e, 0x27, 0x01, 0xa9, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 
-    0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 
-    0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x38, 0x0a, 0x09, 
-    0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x10, 0x22, 0x80, 0x7f, 0x7a, 0x51, 
-    0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x00, 0x00, 0x2e, 0x67, 
-    0x01, 0xa9, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 
-    0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 
-    0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 
-    0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x00, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 
-    0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 
-    0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 
-    0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 
-    0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 
-    0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 
-    0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 
-    0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 
-    0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 
-    0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x4c, 0x6f, 0x75, 
-    0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 
-    0x38, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x10, 0x22, 0xda, 
-    0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x4c, 0x6f, 0xda, 0xb8, 0x02, 
-    0x4d, 0x96, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 
-    0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 
-    0x68, 0x04, 0xd2, 0x58, 0x80, 0x02, 0xc2, 0x58, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 
-    0x50, 0x80, 0x02, 0xc2, 0x50, 0x12, 0x42, 0xac, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 
-    0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 
-    0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 
-    0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 
-    0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x4c, 0xc3, 0x75, 
-    0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x09, 0x01, 
-    0x22, 0x20, 0x29, 0x03, 0xd2, 0x09, 0x22, 0x75, 0x2f, 0xa1, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x81, 
-    0x00, 0x80, 0x06, 0x20, 0x29, 0x03, 0xd2, 0x09, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 
-    0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x50, 0xcb, 0x30, 0x31, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 
-    0x09, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x61, 0x7e, 0x37, 0x01, 0x7b, 0x7e, 0x27, 0x01, 0x9b, 0x9d, 
-    0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x34, 0x7a, 0x05, 0x34, 0x7a, 0x37, 0x01, 0x7b, 0x7e, 
-    0x37, 0x01, 0x5b, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x11, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 
-    0x5b, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 
-    0x10, 0x61, 0xc4, 0x22, 0xc2, 0x61, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 
-    0x01, 0x7b, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0x9b, 0x28, 0x04, 0x7e, 0x27, 
-    0x01, 0x9b, 0x7e, 0x37, 0x01, 0x7b, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x34, 0x7a, 0x05, 0x34, 
-    0x7a, 0x37, 0x01, 0x7b, 0x7e, 0x37, 0x01, 0x5b, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x11, 0xcc, 
-    0x38, 0x13, 0x7a, 0x47, 0x01, 0x5b, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 
-    0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 
-    0x30, 0x9e, 0x44, 0x11, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x0d, 0xcd, 0x7d, 0x24, 
-    0x2d, 0x43, 0x7a, 0x47, 0x01, 0x5b, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x4e, 
-    0x40, 0x22, 0xd2, 0x09, 0x7e, 0x04, 0x0d, 0xcd, 0x7a, 0x07, 0x01, 0x5b, 0x7a, 0x07, 0x01, 0x6b, 
-    0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 
-    0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 
-    0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xab, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 
-    0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 
-    0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 
-    0x47, 0x01, 0xc9, 0x7e, 0x24, 0x01, 0x00, 0x2e, 0x27, 0x01, 0xab, 0x1b, 0x38, 0x20, 0x0b, 0x35, 
-    0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 
-    0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 
-    0x04, 0x30, 0x39, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x11, 
-    0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 
-    0x64, 0x01, 0x00, 0x2e, 0x67, 0x01, 0xab, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 
-    0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 
-    0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 
-    0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x01, 0x7a, 
-    0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 
-    0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 
-    0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 
-    0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 
-    0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 
-    0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 
-    0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 
-    0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 
-    0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 
-    0xe7, 0x02, 0x4f, 0xa4, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 
-    0x19, 0xb1, 0x00, 0x04, 0x30, 0x39, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 
-    0x10, 0xd2, 0x11, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 
-    0x4f, 0xa4, 0xda, 0xb8, 0x02, 0x50, 0xcb, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 
-    0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 
-    0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x59, 0x80, 0x02, 0xc2, 0x59, 0xa5, 0xfd, 0x5e, 
-    0x50, 0x80, 0x68, 0x04, 0xd2, 0x51, 0x80, 0x02, 0xc2, 0x51, 0x12, 0x42, 0xc3, 0x02, 0x65, 0x9c, 
-    0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 
-    0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 
-    0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 
-    0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 
-    0x22, 0x02, 0x4f, 0xf8, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 
-    0x30, 0x22, 0x10, 0x0a, 0x01, 0x22, 0x20, 0x2a, 0x03, 0xd2, 0x0a, 0x22, 0x75, 0x2f, 0xa2, 0x12, 
-    0x7e, 0x30, 0x7e, 0x14, 0x82, 0x00, 0x80, 0x06, 0x20, 0x2a, 0x03, 0xd2, 0x0a, 0x22, 0x09, 0xb1, 
-    0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x54, 0x00, 0x30, 0x32, 
-    0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0a, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x62, 0x7e, 0x37, 0x01, 0x7d, 
-    0x7e, 0x27, 0x01, 0x9d, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x36, 0x7a, 0x05, 0x36, 
-    0x7a, 0x37, 0x01, 0x7d, 0x7e, 0x37, 0x01, 0x5d, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x15, 0xcc, 
-    0x38, 0x68, 0x7a, 0x47, 0x01, 0x5d, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 
-    0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x62, 0xc4, 0x22, 0xc2, 0x62, 0x2d, 0x23, 0x68, 0x78, 0x6d, 
-    0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x7d, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 
-    0x9d, 0x28, 0x04, 0x7e, 0x27, 0x01, 0x9d, 0x7e, 0x37, 0x01, 0x7d, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 
-    0x05, 0x36, 0x7a, 0x05, 0x36, 0x7a, 0x37, 0x01, 0x7d, 0x7e, 0x37, 0x01, 0x5d, 0x7d, 0x43, 0x2d, 
-    0x42, 0xbe, 0x44, 0x15, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x5d, 0x75, 0x2f, 0x94, 0x12, 0x7e, 
-    0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 
-    0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x15, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 
-    0x34, 0x11, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x5d, 0x12, 0x68, 0x34, 0xbe, 0x25, 
-    0x20, 0x78, 0x03, 0x02, 0x51, 0x75, 0x22, 0xd2, 0x0a, 0x7e, 0x04, 0x11, 0xcd, 0x7a, 0x07, 0x01, 
-    0x5d, 0x7a, 0x07, 0x01, 0x6d, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 
-    0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 
-    0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xad, 0x2e, 0x24, 
-    0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 
-    0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 
-    0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x02, 0x00, 0x2e, 0x27, 0x01, 0xad, 
-    0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 
-    0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 
-    0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3a, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 
-    0xb1, 0x00, 0x10, 0xd2, 0x12, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 
-    0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x02, 0x00, 0x2e, 0x67, 0x01, 0xad, 0x9e, 0x24, 0x00, 0x02, 
-    0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 
-    0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 
-    0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 
-    0x23, 0x23, 0x44, 0x02, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 
-    0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 
-    0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 
-    0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 
-    0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 
-    0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 
-    0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 
-    0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 
-    0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 
-    0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x52, 0xd9, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 
-    0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3a, 0x0a, 0x09, 0xb1, 0x00, 0x10, 
-    0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x12, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 
-    0x68, 0x07, 0xca, 0xb8, 0x12, 0x52, 0xd9, 0xda, 0xb8, 0x02, 0x54, 0x00, 0x09, 0xb1, 0x00, 0x18, 
-    0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 
-    0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5a, 0x80, 0x02, 
-    0xc2, 0x5a, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x52, 0x80, 0x02, 0xc2, 0x52, 0x12, 
-    0x42, 0xda, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 
-    0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 
-    0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 
-    0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 
-    0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x53, 0x2d, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 
-    0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x0b, 0x01, 0x22, 0x20, 0x2b, 0x03, 0xd2, 0x0b, 
-    0x22, 0x75, 0x2f, 0xa3, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x83, 0x00, 0x80, 0x06, 0x20, 0x2b, 0x03, 
+    0x74, 0x07, 0xa9, 0x20, 0x30, 0x0b, 0xa9, 0x35, 0x30, 0x05, 0xbe, 0x20, 0x01, 0x28, 0x02, 0x74, 
+    0x0f, 0x19, 0xb0, 0x00, 0x04, 0xa9, 0x33, 0x30, 0x18, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x74, 
+    0x28, 0xa9, 0x20, 0x30, 0x02, 0x74, 0x20, 0x19, 0xb0, 0x00, 0x04, 0x74, 0x03, 0x19, 0xb0, 0x00, 
+    0x0c, 0x74, 0xa7, 0x19, 0xb0, 0x00, 0x08, 0x74, 0x0c, 0x19, 0xb0, 0x00, 0x10, 0x22, 0x7e, 0x04, 
+    0x80, 0x00, 0x4c, 0x02, 0xe4, 0x19, 0xb0, 0x00, 0x04, 0x09, 0xb0, 0x00, 0x10, 0x54, 0x08, 0x19, 
+    0xb0, 0x00, 0x10, 0x74, 0xa7, 0x19, 0xb0, 0x00, 0x08, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x2b, 0x49, 
+    0x22, 0x41, 0xa5, 0x89, 0x24, 0x41, 0xb5, 0x41, 0xd4, 0x41, 0xf3, 0x42, 0x12, 0x42, 0x31, 0x42, 
+    0x50, 0x42, 0x6f, 0x42, 0x8e, 0xc2, 0x10, 0xc2, 0x18, 0xc2, 0x20, 0xc2, 0x08, 0x7e, 0x04, 0x09, 
+    0xe3, 0x7a, 0x07, 0x01, 0x6f, 0x7a, 0x07, 0x01, 0x7f, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x8f, 0x7a, 
+    0x07, 0x01, 0x9f, 0x22, 0xc2, 0x11, 0xc2, 0x19, 0xc2, 0x21, 0xc2, 0x09, 0x7e, 0x04, 0x0d, 0xe3, 
+    0x7a, 0x07, 0x01, 0x71, 0x7a, 0x07, 0x01, 0x81, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x91, 0x7a, 0x07, 
+    0x01, 0xa1, 0x22, 0xc2, 0x12, 0xc2, 0x1a, 0xc2, 0x22, 0xc2, 0x0a, 0x7e, 0x04, 0x11, 0xe3, 0x7a, 
+    0x07, 0x01, 0x73, 0x7a, 0x07, 0x01, 0x83, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x93, 0x7a, 0x07, 0x01, 
+    0xa3, 0x22, 0xc2, 0x13, 0xc2, 0x1b, 0xc2, 0x23, 0xc2, 0x0b, 0x7e, 0x04, 0x15, 0xe3, 0x7a, 0x07, 
+    0x01, 0x75, 0x7a, 0x07, 0x01, 0x85, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x95, 0x7a, 0x07, 0x01, 0xa5, 
+    0x22, 0xc2, 0x14, 0xc2, 0x1c, 0xc2, 0x24, 0xc2, 0x0c, 0x7e, 0x04, 0x19, 0xe3, 0x7a, 0x07, 0x01, 
+    0x77, 0x7a, 0x07, 0x01, 0x87, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x97, 0x7a, 0x07, 0x01, 0xa7, 0x22, 
+    0xc2, 0x15, 0xc2, 0x1d, 0xc2, 0x25, 0xc2, 0x0d, 0x7e, 0x04, 0x1d, 0xe3, 0x7a, 0x07, 0x01, 0x79, 
+    0x7a, 0x07, 0x01, 0x89, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x99, 0x7a, 0x07, 0x01, 0xa9, 0x22, 0xc2, 
+    0x16, 0xc2, 0x1e, 0xc2, 0x26, 0xc2, 0x0e, 0x7e, 0x04, 0x21, 0xe3, 0x7a, 0x07, 0x01, 0x7b, 0x7a, 
+    0x07, 0x01, 0x8b, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x9b, 0x7a, 0x07, 0x01, 0xab, 0x22, 0xc2, 0x17, 
+    0xc2, 0x1f, 0xc2, 0x27, 0xc2, 0x0f, 0x7e, 0x04, 0x25, 0xe3, 0x7a, 0x07, 0x01, 0x7d, 0x7a, 0x07, 
+    0x01, 0x8d, 0x6d, 0x00, 0x7a, 0x07, 0x01, 0x9d, 0x7a, 0x07, 0x01, 0xad, 0x22, 0x7c, 0xb2, 0x23, 
+    0x0a, 0x2b, 0x49, 0x22, 0x42, 0xb8, 0x89, 0x24, 0x42, 0xc8, 0x42, 0xe9, 0x43, 0x0a, 0x43, 0x2b, 
+    0x43, 0x4c, 0x43, 0x6d, 0x43, 0x8e, 0x43, 0xaf, 0x30, 0x50, 0x07, 0x20, 0x68, 0x04, 0xc2, 0x28, 
+    0x80, 0x16, 0x30, 0x40, 0x07, 0x20, 0x60, 0x04, 0xc2, 0x28, 0x80, 0x0c, 0x30, 0x48, 0x07, 0x20, 
+    0x58, 0x04, 0xc2, 0x28, 0x80, 0x02, 0xd2, 0x28, 0x22, 0x30, 0x51, 0x07, 0x20, 0x69, 0x04, 0xc2, 
+    0x29, 0x80, 0x16, 0x30, 0x41, 0x07, 0x20, 0x61, 0x04, 0xc2, 0x29, 0x80, 0x0c, 0x30, 0x49, 0x07, 
+    0x20, 0x59, 0x04, 0xc2, 0x29, 0x80, 0x02, 0xd2, 0x29, 0x22, 0x30, 0x52, 0x07, 0x20, 0x6a, 0x04, 
+    0xc2, 0x2a, 0x80, 0x16, 0x30, 0x42, 0x07, 0x20, 0x62, 0x04, 0xc2, 0x2a, 0x80, 0x0c, 0x30, 0x4a, 
+    0x07, 0x20, 0x5a, 0x04, 0xc2, 0x2a, 0x80, 0x02, 0xd2, 0x2a, 0x22, 0x30, 0x53, 0x07, 0x20, 0x6b, 
+    0x04, 0xc2, 0x2b, 0x80, 0x16, 0x30, 0x43, 0x07, 0x20, 0x63, 0x04, 0xc2, 0x2b, 0x80, 0x0c, 0x30, 
+    0x4b, 0x07, 0x20, 0x5b, 0x04, 0xc2, 0x2b, 0x80, 0x02, 0xd2, 0x2b, 0x22, 0x30, 0x54, 0x07, 0x20, 
+    0x6c, 0x04, 0xc2, 0x2c, 0x80, 0x16, 0x30, 0x44, 0x07, 0x20, 0x64, 0x04, 0xc2, 0x2c, 0x80, 0x0c, 
+    0x30, 0x4c, 0x07, 0x20, 0x5c, 0x04, 0xc2, 0x2c, 0x80, 0x02, 0xd2, 0x2c, 0x22, 0x30, 0x55, 0x07, 
+    0x20, 0x6d, 0x04, 0xc2, 0x2d, 0x80, 0x16, 0x30, 0x45, 0x07, 0x20, 0x65, 0x04, 0xc2, 0x2d, 0x80, 
+    0x0c, 0x30, 0x4d, 0x07, 0x20, 0x5d, 0x04, 0xc2, 0x2d, 0x80, 0x02, 0xd2, 0x2d, 0x22, 0x30, 0x56, 
+    0x07, 0x20, 0x6e, 0x04, 0xc2, 0x2e, 0x80, 0x16, 0x30, 0x46, 0x07, 0x20, 0x66, 0x04, 0xc2, 0x2e, 
+    0x80, 0x0c, 0x30, 0x4e, 0x07, 0x20, 0x5e, 0x04, 0xc2, 0x2e, 0x80, 0x02, 0xd2, 0x2e, 0x22, 0x30, 
+    0x57, 0x07, 0x20, 0x6f, 0x04, 0xc2, 0x2f, 0x80, 0x16, 0x30, 0x47, 0x07, 0x20, 0x67, 0x04, 0xc2, 
+    0x2f, 0x80, 0x0c, 0x30, 0x4f, 0x07, 0x20, 0x5f, 0x04, 0xc2, 0x2f, 0x80, 0x02, 0xd2, 0x2f, 0x22, 
+    0x44, 0x38, 0x43, 0xe5, 0xbe, 0xb0, 0x02, 0x40, 0x01, 0x22, 0x23, 0x0a, 0x5b, 0x49, 0x55, 0x43, 
+    0xd0, 0x99, 0x54, 0xd3, 0x22, 0xa9, 0xc5, 0x87, 0x12, 0x44, 0x43, 0x7e, 0x04, 0x05, 0xe3, 0x7a, 
+    0x07, 0x01, 0xd7, 0x7a, 0x07, 0x01, 0xd9, 0x7e, 0x04, 0x01, 0xe3, 0x7a, 0x07, 0x01, 0xdd, 0x7a, 
+    0x07, 0x01, 0xdf, 0x7e, 0x04, 0x74, 0xad, 0x7a, 0x05, 0x61, 0x75, 0xf1, 0x01, 0x75, 0xe1, 0x1f, 
+    0x75, 0xe4, 0x04, 0x75, 0xf4, 0x04, 0x75, 0xf1, 0x02, 0x75, 0xe1, 0x03, 0x75, 0xe4, 0x04, 0x75, 
+    0xf4, 0x04, 0x43, 0xa2, 0x1c, 0x12, 0x40, 0xeb, 0x7e, 0x20, 0x00, 0x12, 0x41, 0x9a, 0x0b, 0x20, 
+    0xbe, 0x21, 0x2f, 0x78, 0xf6, 0xd2, 0xa8, 0x22, 0xa9, 0xd5, 0x87, 0x12, 0x44, 0x43, 0xd2, 0x92, 
+    0xc2, 0xa8, 0x22, 0x75, 0xa3, 0x00, 0x53, 0xa2, 0x03, 0x75, 0xc1, 0x00, 0x53, 0xc0, 0x03, 0x7e, 
+    0x00, 0x05, 0x7a, 0x01, 0xf1, 0x43, 0xf4, 0x80, 0x43, 0xe4, 0x80, 0xe5, 0xf2, 0x54, 0x7f, 0x44, 
+    0x08, 0xf5, 0xf2, 0xe5, 0xe2, 0x54, 0x7f, 0x44, 0x08, 0xf5, 0xe2, 0x75, 0xe1, 0x10, 0xa5, 0xd8, 
+    0xe1, 0x22, 0xca, 0x09, 0x12, 0x30, 0x20, 0x10, 0x01, 0x12, 0xd5, 0x67, 0x1e, 0x63, 0x69, 0x01, 
+    0x7e, 0x00, 0x6a, 0x2e, 0x01, 0x69, 0xa5, 0xe6, 0xf5, 0x67, 0x80, 0x12, 0x20, 0x02, 0x1e, 0x75, 
+    0x69, 0x00, 0x85, 0x6a, 0x67, 0xd2, 0x02, 0x74, 0x00, 0x80, 0x0d, 0x30, 0x02, 0x0f, 0xc2, 0x02, 
+    0x7e, 0x00, 0x6c, 0x2e, 0x01, 0x69, 0xa5, 0xe6, 0x53, 0x90, 0xcf, 0x42, 0x90, 0xda, 0x09, 0x32, 
+    0xc0, 0xd0, 0xc0, 0xd1, 0xc0, 0xe0, 0xc0, 0xf0, 0xca, 0x0b, 0xca, 0x1b, 0xca, 0x2b, 0xd2, 0x01, 
+    0x75, 0x31, 0x89, 0x12, 0x7c, 0x15, 0x7e, 0x14, 0x80, 0x00, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 
+    0x03, 0x02, 0x45, 0x4f, 0x20, 0x78, 0x5a, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 
+    0x02, 0x45, 0x67, 0x20, 0x79, 0x4b, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 
+    0x45, 0x7f, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x45, 0x97, 0x20, 0x7a, 
+    0x30, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x45, 0xaf, 0xa5, 0x0a, 0x09, 
+    0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x45, 0xc7, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 
+    0xe0, 0x03, 0x02, 0x45, 0xdf, 0xa5, 0x0a, 0x09, 0xb1, 0x00, 0x08, 0x20, 0xe0, 0x03, 0x02, 0x45, 
+    0xf7, 0x30, 0x04, 0x0c, 0xc2, 0x04, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 
+    0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0xd0, 0xf0, 0xd0, 0xe0, 0xd0, 0xd1, 0xd0, 0xd0, 0x32, 0x75, 
+    0x31, 0x80, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x63, 
+    0x2b, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 0x31, 0x81, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 
+    0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x63, 0x6b, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 
+    0x31, 0x82, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x63, 
+    0xab, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 0x31, 0x83, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 
+    0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x63, 0xeb, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 
+    0x31, 0x84, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x64, 
+    0x2b, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 0x31, 0x85, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 
+    0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x64, 0x6b, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 
+    0x31, 0x86, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x64, 
+    0xab, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x75, 0x31, 0x87, 0x12, 0x7c, 0x15, 0x54, 0x3e, 0x0a, 
+    0x5b, 0x7e, 0x44, 0x00, 0xff, 0x69, 0x52, 0x64, 0xeb, 0xca, 0x06, 0xc6, 0x44, 0x89, 0x54, 0x10, 
+    0x08, 0x01, 0x22, 0x20, 0x28, 0x03, 0xd2, 0x08, 0x22, 0x75, 0x31, 0xa0, 0x12, 0x7c, 0x15, 0x7e, 
+    0x14, 0x80, 0x00, 0x80, 0x06, 0x20, 0x28, 0x03, 0xd2, 0x08, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 
+    0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x49, 0x30, 0x20, 0xe6, 0x03, 0xd2, 0x08, 
+    0x22, 0x30, 0x30, 0x49, 0xd2, 0x70, 0x7e, 0x37, 0x01, 0x8f, 0x7e, 0x27, 0x01, 0xaf, 0x9d, 0x32, 
+    0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x48, 0x7a, 0x05, 0x48, 0x7a, 0x37, 0x01, 0x8f, 0x7e, 0x37, 
+    0x01, 0x6f, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x0d, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x6f, 
+    0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 
+    0x70, 0xc4, 0x22, 0xc2, 0x70, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 
+    0x8f, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xaf, 0x28, 0x04, 0x7e, 0x27, 0x01, 
+    0xaf, 0x7e, 0x37, 0x01, 0x8f, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x48, 0x7a, 0x05, 0x48, 0x7a, 
+    0x37, 0x01, 0x8f, 0x7e, 0x37, 0x01, 0x6f, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x0d, 0xe2, 0x38, 
+    0x13, 0x7a, 0x47, 0x01, 0x6f, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 
+    0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x0d, 0xe3, 0x9d, 0x24, 0x12, 0x65, 0x2b, 0x7e, 0x34, 0x09, 0xe3, 0x7d, 0x24, 0x2d, 
+    0x43, 0x7a, 0x47, 0x01, 0x6f, 0x12, 0x65, 0x2b, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x46, 0x7f, 
+    0x22, 0xd2, 0x08, 0x7e, 0x04, 0x09, 0xe3, 0x7a, 0x07, 0x01, 0x6f, 0x7a, 0x07, 0x01, 0x7f, 0x75, 
+    0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 
+    0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 
+    0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xbf, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 
+    0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 
+    0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 
+    0x01, 0xdf, 0x7e, 0x24, 0x00, 0x00, 0x2e, 0x27, 0x01, 0xbf, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 
+    0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 
+    0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 
+    0x30, 0x38, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x10, 0x22, 
+    0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 
+    0x00, 0x00, 0x2e, 0x67, 0x01, 0xbf, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 
+    0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 
+    0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 
+    0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x00, 0x7a, 0x69, 
+    0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 
+    0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 
+    0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 
+    0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 
+    0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 
+    0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 
+    0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 
+    0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 
+    0x02, 0x47, 0xe3, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 
+    0xb1, 0x00, 0x04, 0x30, 0x38, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 
+    0xd2, 0x10, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x47, 
+    0xe3, 0xda, 0xb8, 0x02, 0x49, 0x30, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 
+    0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 
+    0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 
+    0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 
+    0x68, 0x80, 0x02, 0xc2, 0x68, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x60, 0x80, 0x02, 
+    0xc2, 0x60, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x58, 0x80, 0x02, 0xc2, 0x58, 0x12, 
+    0x42, 0xc8, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 
+    0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 
+    0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 
+    0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 
+    0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x48, 0x35, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 
+    0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 0x09, 0x01, 0x22, 0x20, 0x29, 0x03, 0xd2, 0x09, 
+    0x22, 0x75, 0x31, 0xa1, 0x12, 0x7c, 0x15, 0x7e, 0x14, 0x81, 0x00, 0x80, 0x06, 0x20, 0x29, 0x03, 
+    0xd2, 0x09, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 
+    0x12, 0x4c, 0x88, 0x20, 0xe6, 0x03, 0xd2, 0x09, 0x22, 0x30, 0x31, 0x49, 0xd2, 0x71, 0x7e, 0x37, 
+    0x01, 0x91, 0x7e, 0x27, 0x01, 0xb1, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x4a, 0x7a, 
+    0x05, 0x4a, 0x7a, 0x37, 0x01, 0x91, 0x7e, 0x37, 0x01, 0x71, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 
+    0x11, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x71, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 
+    0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 0x71, 0xc4, 0x22, 0xc2, 0x71, 0x2d, 0x23, 0x68, 
+    0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x91, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 
+    0x27, 0x01, 0xb1, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xb1, 0x7e, 0x37, 0x01, 0x91, 0x9d, 0x32, 0x7d, 
+    0x02, 0x2e, 0x05, 0x4a, 0x7a, 0x05, 0x4a, 0x7a, 0x37, 0x01, 0x91, 0x7e, 0x37, 0x01, 0x71, 0x7d, 
+    0x43, 0x2d, 0x42, 0xbe, 0x44, 0x11, 0xe2, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x71, 0x75, 0x31, 0x94, 
+    0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 
+    0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x11, 0xe3, 0x9d, 0x24, 0x12, 0x65, 
+    0x2b, 0x7e, 0x34, 0x0d, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x71, 0x12, 0x65, 0x2b, 
+    0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x49, 0xd7, 0x22, 0xd2, 0x09, 0x7e, 0x04, 0x0d, 0xe3, 0x7a, 
+    0x07, 0x01, 0x71, 0x7a, 0x07, 0x01, 0x81, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 
+    0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 
+    0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xc1, 
+    0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 
+    0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 
+    0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xdf, 0x7e, 0x24, 0x01, 0x00, 0x2e, 0x27, 
+    0x01, 0xc1, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 
+    0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 
+    0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x39, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 
+    0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x11, 0x22, 0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 0x01, 0x00, 0x2e, 0x67, 0x01, 0xc1, 0x9e, 0x24, 
+    0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 
+    0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 
+    0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 
+    0x0f, 0x23, 0x23, 0x23, 0x44, 0x01, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 
+    0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 
+    0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 
+    0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 
+    0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 
+    0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 
+    0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 
+    0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 
+    0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x4b, 0x3b, 0x75, 0x31, 0x99, 0x12, 0x7c, 
+    0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x39, 0x0a, 0x09, 0xb1, 
+    0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x11, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 
+    0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x4b, 0x3b, 0xda, 0xb8, 0x02, 0x4c, 0x88, 0x09, 0xb1, 
+    0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 
+    0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 
+    0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 
+    0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x69, 0x80, 0x02, 0xc2, 0x69, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x20, 0x68, 0x04, 0xd2, 0x61, 0x80, 0x02, 0xc2, 0x61, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 
+    0x04, 0xd2, 0x59, 0x80, 0x02, 0xc2, 0x59, 0x12, 0x42, 0xe9, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 
+    0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 
+    0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 
+    0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 
+    0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x4b, 
+    0x8d, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 
+    0x0a, 0x01, 0x22, 0x20, 0x2a, 0x03, 0xd2, 0x0a, 0x22, 0x75, 0x31, 0xa2, 0x12, 0x7c, 0x15, 0x7e, 
+    0x14, 0x82, 0x00, 0x80, 0x06, 0x20, 0x2a, 0x03, 0xd2, 0x0a, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 
+    0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x4f, 0xe0, 0x20, 0xe6, 0x03, 0xd2, 0x0a, 
+    0x22, 0x30, 0x32, 0x49, 0xd2, 0x72, 0x7e, 0x37, 0x01, 0x93, 0x7e, 0x27, 0x01, 0xb3, 0x9d, 0x32, 
+    0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x4c, 0x7a, 0x05, 0x4c, 0x7a, 0x37, 0x01, 0x93, 0x7e, 0x37, 
+    0x01, 0x73, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x15, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x73, 
+    0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 
+    0x72, 0xc4, 0x22, 0xc2, 0x72, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 
+    0x93, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xb3, 0x28, 0x04, 0x7e, 0x27, 0x01, 
+    0xb3, 0x7e, 0x37, 0x01, 0x93, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x4c, 0x7a, 0x05, 0x4c, 0x7a, 
+    0x37, 0x01, 0x93, 0x7e, 0x37, 0x01, 0x73, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x15, 0xe2, 0x38, 
+    0x13, 0x7a, 0x47, 0x01, 0x73, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 
+    0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x15, 0xe3, 0x9d, 0x24, 0x12, 0x65, 0x2b, 0x7e, 0x34, 0x11, 0xe3, 0x7d, 0x24, 0x2d, 
+    0x43, 0x7a, 0x47, 0x01, 0x73, 0x12, 0x65, 0x2b, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x4d, 0x2f, 
+    0x22, 0xd2, 0x0a, 0x7e, 0x04, 0x11, 0xe3, 0x7a, 0x07, 0x01, 0x73, 0x7a, 0x07, 0x01, 0x83, 0x75, 
+    0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 
+    0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 
+    0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xc3, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 
+    0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 
+    0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 
+    0x01, 0xdf, 0x7e, 0x24, 0x02, 0x00, 0x2e, 0x27, 0x01, 0xc3, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 
+    0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 
+    0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 
+    0x30, 0x3a, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x12, 0x22, 
+    0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 
+    0x02, 0x00, 0x2e, 0x67, 0x01, 0xc3, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 
+    0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 
+    0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 
+    0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x02, 0x7a, 0x69, 
+    0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 
+    0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 
+    0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 
+    0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 
+    0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 
+    0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 
+    0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 
+    0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 
+    0x02, 0x4e, 0x93, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 
+    0xb1, 0x00, 0x04, 0x30, 0x3a, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 
+    0xd2, 0x12, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x4e, 
+    0x93, 0xda, 0xb8, 0x02, 0x4f, 0xe0, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 
+    0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 
+    0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 
+    0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 
+    0x6a, 0x80, 0x02, 0xc2, 0x6a, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x62, 0x80, 0x02, 
+    0xc2, 0x62, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5a, 0x80, 0x02, 0xc2, 0x5a, 0x12, 
+    0x43, 0x0a, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 
+    0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 
+    0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 
+    0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 
+    0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x4e, 0xe5, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 
+    0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 0x0b, 0x01, 0x22, 0x20, 0x2b, 0x03, 0xd2, 0x0b, 
+    0x22, 0x75, 0x31, 0xa3, 0x12, 0x7c, 0x15, 0x7e, 0x14, 0x83, 0x00, 0x80, 0x06, 0x20, 0x2b, 0x03, 
     0xd2, 0x0b, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 
-    0x12, 0x57, 0x35, 0x30, 0x33, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0b, 0x22, 0x30, 0xe6, 0x02, 0xd2, 
-    0x63, 0x7e, 0x37, 0x01, 0x7f, 0x7e, 0x27, 0x01, 0x9f, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 
-    0x05, 0x38, 0x7a, 0x05, 0x38, 0x7a, 0x37, 0x01, 0x7f, 0x7e, 0x37, 0x01, 0x5f, 0x7d, 0x43, 0x2d, 
-    0x42, 0xbe, 0x44, 0x19, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x5f, 0x75, 0x2f, 0x94, 0x12, 0x7e, 
-    0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x63, 0xc4, 0x22, 0xc2, 0x63, 
-    0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x7f, 0xbe, 0x24, 0x00, 0x00, 
-    0x68, 0x6a, 0xbe, 0x27, 0x01, 0x9f, 0x28, 0x04, 0x7e, 0x27, 0x01, 0x9f, 0x7e, 0x37, 0x01, 0x7f, 
-    0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x38, 0x7a, 0x05, 0x38, 0x7a, 0x37, 0x01, 0x7f, 0x7e, 0x37, 
-    0x01, 0x5f, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x19, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x5f, 
-    0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 
-    0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x19, 0xcd, 0x9d, 
-    0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x15, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x5f, 
-    0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x54, 0xaa, 0x22, 0xd2, 0x0b, 0x7e, 0x04, 
-    0x15, 0xcd, 0x7a, 0x07, 0x01, 0x5f, 0x7a, 0x07, 0x01, 0x6f, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 
-    0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 
-    0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 
-    0x27, 0x01, 0xaf, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 
-    0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 
-    0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x03, 
-    0x00, 0x2e, 0x27, 0x01, 0xaf, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 
-    0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 
-    0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3b, 0x0a, 0x09, 0xb1, 
-    0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x13, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 
-    0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x03, 0x00, 0x2e, 0x67, 0x01, 
-    0xaf, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 
-    0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 
-    0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 
-    0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x03, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 
-    0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 
-    0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 
-    0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 
-    0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 
-    0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 
-    0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 
-    0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 
-    0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 
-    0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x56, 0x0e, 0x75, 0x2f, 
-    0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3b, 
-    0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x13, 0x22, 0xda, 0xb8, 
-    0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x56, 0x0e, 0xda, 0xb8, 0x02, 0x57, 
-    0x35, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 
-    0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 
-    0x04, 0xd2, 0x5b, 0x80, 0x02, 0xc2, 0x5b, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x53, 
-    0x80, 0x02, 0xc2, 0x53, 0x12, 0x42, 0xf1, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 
-    0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 
-    0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 
-    0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 
-    0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x56, 0x62, 0x75, 0x2f, 
-    0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x0c, 0x01, 0x22, 
-    0x20, 0x2c, 0x03, 0xd2, 0x0c, 0x22, 0x75, 0x2f, 0xa4, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x84, 0x00, 
-    0x80, 0x06, 0x20, 0x2c, 0x03, 0xd2, 0x0c, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 
-    0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x5a, 0x6a, 0x30, 0x34, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0c, 
-    0x22, 0x30, 0xe6, 0x02, 0xd2, 0x64, 0x7e, 0x37, 0x01, 0x81, 0x7e, 0x27, 0x01, 0xa1, 0x9d, 0x32, 
-    0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x3a, 0x7a, 0x05, 0x3a, 0x7a, 0x37, 0x01, 0x81, 0x7e, 0x37, 
-    0x01, 0x61, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x1d, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x61, 
-    0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 
-    0x64, 0xc4, 0x22, 0xc2, 0x64, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 
-    0x81, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xa1, 0x28, 0x04, 0x7e, 0x27, 0x01, 
-    0xa1, 0x7e, 0x37, 0x01, 0x81, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x3a, 0x7a, 0x05, 0x3a, 0x7a, 
-    0x37, 0x01, 0x81, 0x7e, 0x37, 0x01, 0x61, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x1d, 0xcc, 0x38, 
-    0x13, 0x7a, 0x47, 0x01, 0x61, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 
-    0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 
-    0x9e, 0x44, 0x1d, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x19, 0xcd, 0x7d, 0x24, 0x2d, 
-    0x43, 0x7a, 0x47, 0x01, 0x61, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x57, 0xdf, 
-    0x22, 0xd2, 0x0c, 0x7e, 0x04, 0x19, 0xcd, 0x7a, 0x07, 0x01, 0x61, 0x7a, 0x07, 0x01, 0x71, 0x75, 
-    0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 
-    0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 
-    0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xb1, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 
-    0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 
-    0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 
-    0x01, 0xc9, 0x7e, 0x24, 0x04, 0x00, 0x2e, 0x27, 0x01, 0xb1, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 
-    0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 
-    0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 
+    0x12, 0x53, 0x38, 0x20, 0xe6, 0x03, 0xd2, 0x0b, 0x22, 0x30, 0x33, 0x49, 0xd2, 0x73, 0x7e, 0x37, 
+    0x01, 0x95, 0x7e, 0x27, 0x01, 0xb5, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x4e, 0x7a, 
+    0x05, 0x4e, 0x7a, 0x37, 0x01, 0x95, 0x7e, 0x37, 0x01, 0x75, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 
+    0x19, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x75, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 
+    0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 0x73, 0xc4, 0x22, 0xc2, 0x73, 0x2d, 0x23, 0x68, 
+    0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x95, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 
+    0x27, 0x01, 0xb5, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xb5, 0x7e, 0x37, 0x01, 0x95, 0x9d, 0x32, 0x7d, 
+    0x02, 0x2e, 0x05, 0x4e, 0x7a, 0x05, 0x4e, 0x7a, 0x37, 0x01, 0x95, 0x7e, 0x37, 0x01, 0x75, 0x7d, 
+    0x43, 0x2d, 0x42, 0xbe, 0x44, 0x19, 0xe2, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x75, 0x75, 0x31, 0x94, 
+    0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 
+    0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x19, 0xe3, 0x9d, 0x24, 0x12, 0x65, 
+    0x2b, 0x7e, 0x34, 0x15, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x75, 0x12, 0x65, 0x2b, 
+    0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x50, 0x87, 0x22, 0xd2, 0x0b, 0x7e, 0x04, 0x15, 0xe3, 0x7a, 
+    0x07, 0x01, 0x75, 0x7a, 0x07, 0x01, 0x85, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 
+    0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 
+    0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xc5, 
+    0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 
+    0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 
+    0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xdf, 0x7e, 0x24, 0x03, 0x00, 0x2e, 0x27, 
+    0x01, 0xc5, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 
+    0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 
+    0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3b, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 
+    0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x13, 0x22, 0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 0x03, 0x00, 0x2e, 0x67, 0x01, 0xc5, 0x9e, 0x24, 
+    0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 
+    0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 
+    0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 
+    0x0f, 0x23, 0x23, 0x23, 0x44, 0x03, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 
+    0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 
+    0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 
+    0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 
+    0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 
+    0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 
+    0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 
+    0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 
+    0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x51, 0xeb, 0x75, 0x31, 0x99, 0x12, 0x7c, 
+    0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3b, 0x0a, 0x09, 0xb1, 
+    0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x13, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 
+    0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x51, 0xeb, 0xda, 0xb8, 0x02, 0x53, 0x38, 0x09, 0xb1, 
+    0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 
+    0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 
+    0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 
+    0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6b, 0x80, 0x02, 0xc2, 0x6b, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x20, 0x68, 0x04, 0xd2, 0x63, 0x80, 0x02, 0xc2, 0x63, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 
+    0x04, 0xd2, 0x5b, 0x80, 0x02, 0xc2, 0x5b, 0x12, 0x43, 0x2b, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 
+    0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 
+    0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 
+    0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 
+    0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x52, 
+    0x3d, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 
+    0x0c, 0x01, 0x22, 0x20, 0x2c, 0x03, 0xd2, 0x0c, 0x22, 0x75, 0x31, 0xa4, 0x12, 0x7c, 0x15, 0x7e, 
+    0x14, 0x84, 0x00, 0x80, 0x06, 0x20, 0x2c, 0x03, 0xd2, 0x0c, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 
+    0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x56, 0x90, 0x20, 0xe6, 0x03, 0xd2, 0x0c, 
+    0x22, 0x30, 0x34, 0x49, 0xd2, 0x74, 0x7e, 0x37, 0x01, 0x97, 0x7e, 0x27, 0x01, 0xb7, 0x9d, 0x32, 
+    0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x50, 0x7a, 0x05, 0x50, 0x7a, 0x37, 0x01, 0x97, 0x7e, 0x37, 
+    0x01, 0x77, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x1d, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x77, 
+    0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 
+    0x74, 0xc4, 0x22, 0xc2, 0x74, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 
+    0x97, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xb7, 0x28, 0x04, 0x7e, 0x27, 0x01, 
+    0xb7, 0x7e, 0x37, 0x01, 0x97, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x50, 0x7a, 0x05, 0x50, 0x7a, 
+    0x37, 0x01, 0x97, 0x7e, 0x37, 0x01, 0x77, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x1d, 0xe2, 0x38, 
+    0x13, 0x7a, 0x47, 0x01, 0x77, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 
+    0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x1d, 0xe3, 0x9d, 0x24, 0x12, 0x65, 0x2b, 0x7e, 0x34, 0x19, 0xe3, 0x7d, 0x24, 0x2d, 
+    0x43, 0x7a, 0x47, 0x01, 0x77, 0x12, 0x65, 0x2b, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x53, 0xdf, 
+    0x22, 0xd2, 0x0c, 0x7e, 0x04, 0x19, 0xe3, 0x7a, 0x07, 0x01, 0x77, 0x7a, 0x07, 0x01, 0x87, 0x75, 
+    0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 
+    0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 
+    0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xc7, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 
+    0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 
+    0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 
+    0x01, 0xdf, 0x7e, 0x24, 0x04, 0x00, 0x2e, 0x27, 0x01, 0xc7, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 
+    0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 
+    0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 
     0x30, 0x3c, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x14, 0x22, 
-    0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 
-    0x04, 0x00, 0x2e, 0x67, 0x01, 0xb1, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 
-    0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 
-    0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 
+    0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 
+    0x04, 0x00, 0x2e, 0x67, 0x01, 0xc7, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 
+    0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 
+    0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 
     0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x04, 0x7a, 0x69, 
-    0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 
-    0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 
-    0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 
-    0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 
-    0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 
-    0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 
-    0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 
+    0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 
+    0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 
+    0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 
+    0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 
+    0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 
+    0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 
     0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 
     0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 
-    0x02, 0x59, 0x43, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 
+    0x02, 0x55, 0x43, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 
     0xb1, 0x00, 0x04, 0x30, 0x3c, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 
-    0xd2, 0x14, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x59, 
-    0x43, 0xda, 0xb8, 0x02, 0x5a, 0x6a, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 
-    0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 
-    0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5c, 0x80, 0x02, 0xc2, 0x5c, 0xa5, 0xfd, 0x5e, 0x50, 
-    0x80, 0x68, 0x04, 0xd2, 0x54, 0x80, 0x02, 0xc2, 0x54, 0x12, 0x43, 0x08, 0x02, 0x65, 0x9c, 0x75, 
-    0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 
-    0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 
-    0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 
-    0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 
-    0x02, 0x59, 0x97, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 
-    0x22, 0x10, 0x0d, 0x01, 0x22, 0x20, 0x2d, 0x03, 0xd2, 0x0d, 0x22, 0x75, 0x2f, 0xa5, 0x12, 0x7e, 
-    0x30, 0x7e, 0x14, 0x85, 0x00, 0x80, 0x06, 0x20, 0x2d, 0x03, 0xd2, 0x0d, 0x22, 0x09, 0xb1, 0x00, 
-    0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x5d, 0x9f, 0x30, 0x35, 0x06, 
-    0x20, 0xe6, 0x4f, 0xd2, 0x0d, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x65, 0x7e, 0x37, 0x01, 0x83, 0x7e, 
-    0x27, 0x01, 0xa3, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x3c, 0x7a, 0x05, 0x3c, 0x7a, 
-    0x37, 0x01, 0x83, 0x7e, 0x37, 0x01, 0x63, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x21, 0xcc, 0x38, 
-    0x68, 0x7a, 0x47, 0x01, 0x63, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 
-    0x30, 0x12, 0x68, 0x34, 0x10, 0x65, 0xc4, 0x22, 0xc2, 0x65, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 
-    0x80, 0x1a, 0x7e, 0x27, 0x01, 0x83, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xa3, 
-    0x28, 0x04, 0x7e, 0x27, 0x01, 0xa3, 0x7e, 0x37, 0x01, 0x83, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 
-    0x3c, 0x7a, 0x05, 0x3c, 0x7a, 0x37, 0x01, 0x83, 0x7e, 0x37, 0x01, 0x63, 0x7d, 0x43, 0x2d, 0x42, 
-    0xbe, 0x44, 0x21, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x63, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 
-    0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 
-    0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x21, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 
-    0x1d, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x63, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 
-    0x78, 0x03, 0x02, 0x5b, 0x14, 0x22, 0xd2, 0x0d, 0x7e, 0x04, 0x1d, 0xcd, 0x7a, 0x07, 0x01, 0x63, 
-    0x7a, 0x07, 0x01, 0x73, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 
-    0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 
-    0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xb3, 0x2e, 0x24, 0x00, 
-    0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 
-    0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 
-    0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x05, 0x00, 0x2e, 0x27, 0x01, 0xb3, 0x1b, 
-    0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 
-    0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 
-    0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3d, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 
-    0x00, 0x10, 0xd2, 0x15, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 
-    0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x05, 0x00, 0x2e, 0x67, 0x01, 0xb3, 0x9e, 0x24, 0x00, 0x02, 0x40, 
-    0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 
-    0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 
-    0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 
-    0x23, 0x44, 0x05, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 
-    0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 
-    0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 
-    0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 
-    0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 
-    0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 
-    0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 
-    0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 
-    0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 
-    0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x5c, 0x78, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 
+    0xd2, 0x14, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x55, 
+    0x43, 0xda, 0xb8, 0x02, 0x56, 0x90, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 
+    0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 
+    0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 
+    0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 
+    0x6c, 0x80, 0x02, 0xc2, 0x6c, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x64, 0x80, 0x02, 
+    0xc2, 0x64, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5c, 0x80, 0x02, 0xc2, 0x5c, 0x12, 
+    0x43, 0x4c, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 
+    0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 
+    0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 
+    0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 
+    0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x55, 0x95, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 
+    0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 0x0d, 0x01, 0x22, 0x20, 0x2d, 0x03, 0xd2, 0x0d, 
+    0x22, 0x75, 0x31, 0xa5, 0x12, 0x7c, 0x15, 0x7e, 0x14, 0x85, 0x00, 0x80, 0x06, 0x20, 0x2d, 0x03, 
+    0xd2, 0x0d, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 
+    0x12, 0x59, 0xe8, 0x20, 0xe6, 0x03, 0xd2, 0x0d, 0x22, 0x30, 0x35, 0x49, 0xd2, 0x75, 0x7e, 0x37, 
+    0x01, 0x99, 0x7e, 0x27, 0x01, 0xb9, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x52, 0x7a, 
+    0x05, 0x52, 0x7a, 0x37, 0x01, 0x99, 0x7e, 0x37, 0x01, 0x79, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 
+    0x21, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x79, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 
+    0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 0x75, 0xc4, 0x22, 0xc2, 0x75, 0x2d, 0x23, 0x68, 
+    0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x99, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 
+    0x27, 0x01, 0xb9, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xb9, 0x7e, 0x37, 0x01, 0x99, 0x9d, 0x32, 0x7d, 
+    0x02, 0x2e, 0x05, 0x52, 0x7a, 0x05, 0x52, 0x7a, 0x37, 0x01, 0x99, 0x7e, 0x37, 0x01, 0x79, 0x7d, 
+    0x43, 0x2d, 0x42, 0xbe, 0x44, 0x21, 0xe2, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x79, 0x75, 0x31, 0x94, 
+    0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 
+    0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x21, 0xe3, 0x9d, 0x24, 0x12, 0x65, 
+    0x2b, 0x7e, 0x34, 0x1d, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x79, 0x12, 0x65, 0x2b, 
+    0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x57, 0x37, 0x22, 0xd2, 0x0d, 0x7e, 0x04, 0x1d, 0xe3, 0x7a, 
+    0x07, 0x01, 0x79, 0x7a, 0x07, 0x01, 0x89, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 
+    0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 
+    0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xc9, 
+    0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 
+    0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 
+    0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xdf, 0x7e, 0x24, 0x05, 0x00, 0x2e, 0x27, 
+    0x01, 0xc9, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 
+    0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 
     0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3d, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 
-    0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x15, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 
-    0x07, 0xca, 0xb8, 0x12, 0x5c, 0x78, 0xda, 0xb8, 0x02, 0x5d, 0x9f, 0x09, 0xb1, 0x00, 0x18, 0x7e, 
-    0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 
-    0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5d, 0x80, 0x02, 0xc2, 
-    0x5d, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x55, 0x80, 0x02, 0xc2, 0x55, 0x12, 0x43, 
-    0x1f, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 
-    0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 
-    0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 
-    0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 
-    0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x5c, 0xcc, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 
-    0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x0e, 0x01, 0x22, 0x20, 0x2e, 0x03, 0xd2, 0x0e, 0x22, 
-    0x75, 0x2f, 0xa6, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x86, 0x00, 0x80, 0x06, 0x20, 0x2e, 0x03, 0xd2, 
-    0x0e, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 
-    0x60, 0xd4, 0x30, 0x36, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0e, 0x22, 0x30, 0xe6, 0x02, 0xd2, 0x66, 
-    0x7e, 0x37, 0x01, 0x85, 0x7e, 0x27, 0x01, 0xa5, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 
-    0x3e, 0x7a, 0x05, 0x3e, 0x7a, 0x37, 0x01, 0x85, 0x7e, 0x37, 0x01, 0x65, 0x7d, 0x43, 0x2d, 0x42, 
-    0xbe, 0x44, 0x25, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x65, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 
-    0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x66, 0xc4, 0x22, 0xc2, 0x66, 0x2d, 
-    0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x85, 0xbe, 0x24, 0x00, 0x00, 0x68, 
-    0x6a, 0xbe, 0x27, 0x01, 0xa5, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xa5, 0x7e, 0x37, 0x01, 0x85, 0x9d, 
-    0x32, 0x7d, 0x02, 0x2e, 0x05, 0x3e, 0x7a, 0x05, 0x3e, 0x7a, 0x37, 0x01, 0x85, 0x7e, 0x37, 0x01, 
-    0x65, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x25, 0xcc, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x65, 0x75, 
-    0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x02, 0x68, 0x34, 0x75, 0x2f, 
-    0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x25, 0xcd, 0x9d, 0x24, 
-    0x12, 0x68, 0x34, 0x7e, 0x34, 0x21, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x65, 0x12, 
-    0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x5e, 0x49, 0x22, 0xd2, 0x0e, 0x7e, 0x04, 0x21, 
-    0xcd, 0x7a, 0x07, 0x01, 0x65, 0x7a, 0x07, 0x01, 0x75, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x75, 
-    0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 0x30, 0xd2, 0x04, 0x09, 0xb1, 
-    0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x27, 
-    0x01, 0xb5, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 
-    0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc9, 0x7d, 0x43, 
-    0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xc9, 0x7e, 0x24, 0x06, 0x00, 
-    0x2e, 0x27, 0x01, 0xb5, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0xbe, 
-    0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 
-    0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3e, 0x0a, 0x09, 0xb1, 0x00, 
-    0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x16, 0x22, 0x80, 0x7f, 0x7a, 0x51, 0x2f, 0x12, 
-    0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x06, 0x00, 0x2e, 0x67, 0x01, 0xb5, 
-    0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x69, 0x04, 0x7e, 0x34, 
-    0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 0x69, 0x04, 0x7a, 0x39, 0xc0, 
-    0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 
-    0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x06, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 
-    0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0xbd, 0x04, 0x68, 0x2b, 
-    0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xcb, 0x2e, 0x35, 
-    0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 
-    0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xcd, 0x80, 
-    0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 
-    0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd2, 0x7d, 0x70, 0x0b, 
-    0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 
-    0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 
-    0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x5f, 0xad, 0x75, 0x2f, 0x99, 
-    0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3e, 0x0a, 
-    0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x16, 0x22, 0xda, 0xb8, 0x30, 
-    0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x5f, 0xad, 0xda, 0xb8, 0x02, 0x60, 0xd4, 
-    0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 
-    0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 
-    0xd2, 0x5e, 0x80, 0x02, 0xc2, 0x5e, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x56, 0x80, 
-    0x02, 0xc2, 0x56, 0x12, 0x43, 0x36, 0x02, 0x65, 0x9c, 0x75, 0x2f, 0x91, 0x12, 0x7e, 0x30, 0x09, 
-    0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 
-    0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x65, 0x9c, 0xca, 
-    0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 
-    0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x60, 0x01, 0x75, 0x2f, 0x95, 
-    0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 0x10, 0x0f, 0x01, 0x22, 0x20, 
-    0x2f, 0x03, 0xd2, 0x0f, 0x22, 0x75, 0x2f, 0xa7, 0x12, 0x7e, 0x30, 0x7e, 0x14, 0x87, 0x00, 0x80, 
-    0x06, 0x20, 0x2f, 0x03, 0xd2, 0x0f, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 
-    0xda, 0xb8, 0x68, 0x03, 0x12, 0x64, 0x09, 0x30, 0x37, 0x06, 0x20, 0xe6, 0x4f, 0xd2, 0x0f, 0x22, 
-    0x30, 0xe6, 0x02, 0xd2, 0x67, 0x7e, 0x37, 0x01, 0x87, 0x7e, 0x27, 0x01, 0xa7, 0x9d, 0x32, 0x40, 
-    0x31, 0x7d, 0x02, 0x2e, 0x05, 0x40, 0x7a, 0x05, 0x40, 0x7a, 0x37, 0x01, 0x87, 0x7e, 0x37, 0x01, 
-    0x67, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x29, 0xcc, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x67, 0x75, 
-    0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x68, 0x34, 0x10, 0x67, 
-    0xc4, 0x22, 0xc2, 0x67, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x87, 
-    0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xa7, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xa7, 
-    0x7e, 0x37, 0x01, 0x87, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x40, 0x7a, 0x05, 0x40, 0x7a, 0x37, 
-    0x01, 0x87, 0x7e, 0x37, 0x01, 0x67, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x29, 0xcc, 0x38, 0x13, 
-    0x7a, 0x47, 0x01, 0x67, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 
-    0x02, 0x68, 0x34, 0x75, 0x2f, 0x94, 0x12, 0x7e, 0x30, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 
-    0x44, 0x29, 0xcd, 0x9d, 0x24, 0x12, 0x68, 0x34, 0x7e, 0x34, 0x25, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 
-    0x7a, 0x47, 0x01, 0x67, 0x12, 0x68, 0x34, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x61, 0x7e, 0x22, 
-    0xd2, 0x0f, 0x7e, 0x04, 0x25, 0xcd, 0x7a, 0x07, 0x01, 0x67, 0x7a, 0x07, 0x01, 0x77, 0x75, 0x2f, 
-    0x94, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x92, 0x12, 0x7e, 
-    0x30, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 
-    0x37, 0x01, 0xcb, 0x7e, 0x27, 0x01, 0xb7, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 
-    0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x30, 0x7a, 0x05, 0x30, 0x7a, 0x37, 0x01, 0xcb, 0x7e, 
-    0x37, 0x01, 0xc9, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x44, 0x7a, 0x47, 0x01, 
-    0xc9, 0x7e, 0x24, 0x07, 0x00, 0x2e, 0x27, 0x01, 0xb7, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 
-    0x2f, 0x12, 0x7e, 0x30, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x69, 0x1f, 0x02, 0x69, 0x04, 0x75, 
-    0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 
-    0x3f, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x17, 0x22, 0x80, 
-    0x7f, 0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x24, 0x7e, 0x64, 0x07, 
-    0x00, 0x2e, 0x67, 0x01, 0xb7, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 
-    0x12, 0x69, 0x04, 0x7e, 0x34, 0x01, 0xcd, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc9, 0x02, 
-    0x69, 0x04, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xcd, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 
-    0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x07, 0x7a, 0x69, 0xb0, 
-    0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x2f, 0x93, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 
-    0x30, 0xbd, 0x04, 0x68, 0x2b, 0x7a, 0x07, 0x01, 0xc9, 0x7e, 0x47, 0x01, 0xcb, 0x2d, 0x43, 0x7a, 
-    0x47, 0x01, 0xcb, 0x2e, 0x35, 0x30, 0x7a, 0x35, 0x30, 0x22, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 
-    0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x28, 0x7e, 0x04, 0x01, 0xcd, 0x80, 0x2a, 
-    0x7e, 0x04, 0x01, 0xcd, 0x80, 0xcf, 0x7e, 0x07, 0x01, 0xcb, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 
-    0x28, 0x40, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 
-    0x68, 0xd2, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 
-    0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 
-    0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 
-    0x62, 0xe2, 0x75, 0x2f, 0x99, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 
-    0x00, 0x04, 0x30, 0x3f, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 
-    0x17, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x62, 0xe2, 
-    0xda, 0xb8, 0x02, 0x64, 0x09, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x2f, 0x90, 0x12, 
-    0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0xa5, 0xfd, 0x5e, 0x50, 0x0a, 0x68, 0x1d, 0xa5, 0xfd, 
-    0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5f, 0x80, 0x02, 0xc2, 0x5f, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 
-    0x68, 0x04, 0xd2, 0x57, 0x80, 0x02, 0xc2, 0x57, 0x12, 0x43, 0x4d, 0x02, 0x65, 0x9c, 0x75, 0x2f, 
-    0x91, 0x12, 0x7e, 0x30, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x20, 0xe0, 
-    0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x65, 0x9c, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 
-    0x80, 0x12, 0x65, 0x9c, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 
-    0x09, 0x61, 0x00, 0x00, 0x12, 0x65, 0xbf, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 
-    0x63, 0x36, 0x75, 0x2f, 0x95, 0x12, 0x7e, 0x30, 0x22, 0x75, 0x2f, 0x96, 0x12, 0x7e, 0x30, 0x22, 
-    0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 
-    0x20, 0x68, 0x04, 0xd2, 0x58, 0x80, 0x02, 0xc2, 0x58, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 
-    0xd2, 0x50, 0x80, 0x02, 0xc2, 0x50, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 
-    0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x59, 0x80, 0x02, 
-    0xc2, 0x59, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x51, 0x80, 0x02, 0xc2, 0x51, 0x02, 
-    0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 
-    0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5a, 0x80, 0x02, 0xc2, 0x5a, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 
-    0x68, 0x04, 0xd2, 0x52, 0x80, 0x02, 0xc2, 0x52, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 
-    0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5b, 
-    0x80, 0x02, 0xc2, 0x5b, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x53, 0x80, 0x02, 0xc2, 
-    0x53, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 
-    0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5c, 0x80, 0x02, 0xc2, 0x5c, 0xa5, 0xfd, 0x5e, 
-    0x50, 0x80, 0x68, 0x04, 0xd2, 0x54, 0x80, 0x02, 0xc2, 0x54, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 
-    0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 
-    0xd2, 0x5d, 0x80, 0x02, 0xc2, 0x5d, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x55, 0x80, 
-    0x02, 0xc2, 0x55, 0x02, 0x65, 0x88, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 
-    0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x5e, 0x80, 0x02, 0xc2, 0x5e, 0xa5, 
-    0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x56, 0x80, 0x02, 0xc2, 0x56, 0x02, 0x65, 0x88, 0x7c, 
-    0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 
-    0x68, 0x04, 0xd2, 0x5f, 0x80, 0x02, 0xc2, 0x5f, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 
-    0x57, 0x80, 0x02, 0xc2, 0x57, 0x02, 0x65, 0x88, 0x54, 0xf0, 0xc4, 0xa5, 0xff, 0xc4, 0xa5, 0x4f, 
-    0x75, 0x2f, 0x90, 0x12, 0x7e, 0x30, 0xf5, 0x2f, 0x12, 0x7e, 0x30, 0x22, 0xca, 0x19, 0x5e, 0x20, 
-    0x07, 0x4c, 0xa2, 0x7e, 0x74, 0x29, 0xcd, 0xca, 0x79, 0x7a, 0x79, 0xa0, 0x0b, 0x74, 0x7a, 0x79, 
-    0xb0, 0x0b, 0x74, 0xda, 0x79, 0x7e, 0x30, 0x02, 0x7e, 0x64, 0x00, 0x02, 0x02, 0x65, 0xe7, 0xca, 
-    0x19, 0x5e, 0x20, 0x07, 0x4c, 0xa2, 0x7e, 0x74, 0x29, 0xcd, 0xca, 0x79, 0x7a, 0x79, 0xa0, 0x0b, 
-    0x74, 0x7a, 0x79, 0xb0, 0x0b, 0x74, 0x7a, 0x79, 0x60, 0x0b, 0x74, 0xda, 0x79, 0x7e, 0x30, 0x03, 
-    0x7e, 0x64, 0x00, 0x03, 0x02, 0x65, 0xe7, 0xd2, 0x04, 0x7e, 0x27, 0x01, 0xcb, 0x2d, 0x26, 0xbe, 
-    0x24, 0x04, 0x00, 0x38, 0x2e, 0x7e, 0x07, 0x01, 0xc9, 0x7e, 0x44, 0x05, 0xcd, 0x7e, 0x79, 0xa0, 
-    0x7a, 0x09, 0xa0, 0x0b, 0x04, 0x0b, 0x74, 0xbd, 0x04, 0x68, 0x23, 0xa5, 0xdb, 0xef, 0x7a, 0x27, 
-    0x01, 0xcb, 0x7e, 0x25, 0x30, 0x2d, 0x26, 0x7a, 0x25, 0x30, 0x7a, 0x07, 0x01, 0xc9, 0xda, 0x19, 
-    0xc2, 0xd7, 0x22, 0x75, 0x2f, 0x9a, 0x12, 0x7e, 0x30, 0xda, 0x19, 0xd2, 0xd7, 0x22, 0x7e, 0x04, 
-    0x01, 0xcd, 0x80, 0xd7, 0x4d, 0x42, 0x4a, 0xae, 0x4b, 0xa8, 0x4d, 0x7b, 0x49, 0x4f, 0x49, 0x4f, 
-    0x4c, 0xa7, 0x49, 0x4f, 0x4d, 0xbf, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x4d, 0xc6, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x50, 0x77, 0x4d, 0xe3, 0x4e, 0xdd, 0x50, 0xb0, 0x49, 0x4f, 0x49, 0x4f, 
-    0x4f, 0xdc, 0x49, 0x4f, 0x50, 0xf4, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x50, 0xfb, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x53, 0xac, 0x51, 0x18, 0x52, 0x12, 0x53, 0xe5, 0x49, 0x4f, 0x49, 0x4f, 
-    0x53, 0x11, 0x49, 0x4f, 0x54, 0x29, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x54, 0x30, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x56, 0xe1, 0x54, 0x4d, 0x55, 0x47, 0x57, 0x1a, 0x49, 0x4f, 0x49, 0x4f, 
-    0x56, 0x46, 0x49, 0x4f, 0x57, 0x5e, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x57, 0x65, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x5a, 0x16, 0x57, 0x82, 0x58, 0x7c, 0x5a, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x59, 0x7b, 0x49, 0x4f, 0x5a, 0x93, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x5a, 0x9a, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x5d, 0x4b, 0x5a, 0xb7, 0x5b, 0xb1, 0x5d, 0x84, 0x49, 0x4f, 0x49, 0x4f, 
-    0x5c, 0xb0, 0x49, 0x4f, 0x5d, 0xc8, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x5d, 0xcf, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x60, 0x80, 0x5d, 0xec, 0x5e, 0xe6, 0x60, 0xb9, 0x49, 0x4f, 0x49, 0x4f, 
-    0x5f, 0xe5, 0x49, 0x4f, 0x60, 0xfd, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x61, 0x04, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x63, 0xb5, 0x61, 0x21, 0x62, 0x1b, 0x63, 0xee, 0x49, 0x4f, 0x49, 0x4f, 
-    0x63, 0x1a, 0x49, 0x4f, 0x64, 0x32, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x64, 0x39, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 0x49, 0x4f, 
-    0x49, 0x4f, 0x49, 0x4f, 0xca, 0x29, 0x1e, 0x50, 0x40, 0x0d, 0x7e, 0x54, 0x0b, 0x10, 0x9c, 0xb5, 
-    0xa4, 0x2e, 0x54, 0x68, 0x51, 0x89, 0x54, 0x7e, 0x39, 0x00, 0x7a, 0x19, 0x00, 0x0b, 0x34, 0x80, 
-    0xe9, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 
-    0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 
-    0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 
-    0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 
+    0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x15, 0x22, 0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 0x05, 0x00, 0x2e, 0x67, 0x01, 0xc9, 0x9e, 0x24, 
+    0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 
+    0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 
+    0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 
+    0x0f, 0x23, 0x23, 0x23, 0x44, 0x05, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 
+    0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 
+    0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 
+    0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 
+    0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 
+    0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 
+    0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 
+    0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 
+    0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x58, 0x9b, 0x75, 0x31, 0x99, 0x12, 0x7c, 
+    0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3d, 0x0a, 0x09, 0xb1, 
+    0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x15, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 
+    0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x58, 0x9b, 0xda, 0xb8, 0x02, 0x59, 0xe8, 0x09, 0xb1, 
+    0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 
+    0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 
+    0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 
+    0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6d, 0x80, 0x02, 0xc2, 0x6d, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x20, 0x68, 0x04, 0xd2, 0x65, 0x80, 0x02, 0xc2, 0x65, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 
+    0x04, 0xd2, 0x5d, 0x80, 0x02, 0xc2, 0x5d, 0x12, 0x43, 0x6d, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 
+    0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 
+    0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 
+    0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 
+    0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x58, 
+    0xed, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 
+    0x0e, 0x01, 0x22, 0x20, 0x2e, 0x03, 0xd2, 0x0e, 0x22, 0x75, 0x31, 0xa6, 0x12, 0x7c, 0x15, 0x7e, 
+    0x14, 0x86, 0x00, 0x80, 0x06, 0x20, 0x2e, 0x03, 0xd2, 0x0e, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 
+    0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 0x12, 0x5d, 0x40, 0x20, 0xe6, 0x03, 0xd2, 0x0e, 
+    0x22, 0x30, 0x36, 0x49, 0xd2, 0x76, 0x7e, 0x37, 0x01, 0x9b, 0x7e, 0x27, 0x01, 0xbb, 0x9d, 0x32, 
+    0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x54, 0x7a, 0x05, 0x54, 0x7a, 0x37, 0x01, 0x9b, 0x7e, 0x37, 
+    0x01, 0x7b, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x25, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x7b, 
+    0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 
+    0x76, 0xc4, 0x22, 0xc2, 0x76, 0x2d, 0x23, 0x68, 0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 
+    0x9b, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 0x27, 0x01, 0xbb, 0x28, 0x04, 0x7e, 0x27, 0x01, 
+    0xbb, 0x7e, 0x37, 0x01, 0x9b, 0x9d, 0x32, 0x7d, 0x02, 0x2e, 0x05, 0x54, 0x7a, 0x05, 0x54, 0x7a, 
+    0x37, 0x01, 0x9b, 0x7e, 0x37, 0x01, 0x7b, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x25, 0xe2, 0x38, 
+    0x13, 0x7a, 0x47, 0x01, 0x7b, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 
+    0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x25, 0xe3, 0x9d, 0x24, 0x12, 0x65, 0x2b, 0x7e, 0x34, 0x21, 0xe3, 0x7d, 0x24, 0x2d, 
+    0x43, 0x7a, 0x47, 0x01, 0x7b, 0x12, 0x65, 0x2b, 0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x5a, 0x8f, 
+    0x22, 0xd2, 0x0e, 0x7e, 0x04, 0x21, 0xe3, 0x7a, 0x07, 0x01, 0x7b, 0x7a, 0x07, 0x01, 0x8b, 0x75, 
+    0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 
+    0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 
+    0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xcb, 0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 
+    0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 
+    0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 
+    0x01, 0xdf, 0x7e, 0x24, 0x06, 0x00, 0x2e, 0x27, 0x01, 0xcb, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 
+    0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 
+    0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 
+    0x30, 0x3e, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x16, 0x22, 
+    0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 
+    0x06, 0x00, 0x2e, 0x67, 0x01, 0xcb, 0x9e, 0x24, 0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 
+    0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 
+    0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 
+    0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 0x0f, 0x23, 0x23, 0x23, 0x44, 0x06, 0x7a, 0x69, 
+    0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 
+    0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 
+    0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 
+    0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 
+    0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 
+    0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 
+    0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 
+    0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 
+    0x02, 0x5b, 0xf3, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 
+    0xb1, 0x00, 0x04, 0x30, 0x3e, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 
+    0xd2, 0x16, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x5b, 
+    0xf3, 0xda, 0xb8, 0x02, 0x5d, 0x40, 0x09, 0xb1, 0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 
+    0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 
+    0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 
+    0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 
+    0x6e, 0x80, 0x02, 0xc2, 0x6e, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x66, 0x80, 0x02, 
+    0xc2, 0x66, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5e, 0x80, 0x02, 0xc2, 0x5e, 0x12, 
+    0x43, 0x8e, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 
+    0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 
+    0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 
+    0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 
+    0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x5c, 0x45, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 
+    0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x10, 0x0f, 0x01, 0x22, 0x20, 0x2f, 0x03, 0xd2, 0x0f, 
+    0x22, 0x75, 0x31, 0xa7, 0x12, 0x7c, 0x15, 0x7e, 0x14, 0x87, 0x00, 0x80, 0x06, 0x20, 0x2f, 0x03, 
+    0xd2, 0x0f, 0x22, 0x09, 0xb1, 0x00, 0x14, 0xca, 0xb8, 0x5e, 0xb0, 0x1e, 0xda, 0xb8, 0x68, 0x03, 
+    0x12, 0x60, 0x98, 0x20, 0xe6, 0x03, 0xd2, 0x0f, 0x22, 0x30, 0x37, 0x49, 0xd2, 0x77, 0x7e, 0x37, 
+    0x01, 0x9d, 0x7e, 0x27, 0x01, 0xbd, 0x9d, 0x32, 0x40, 0x31, 0x7d, 0x02, 0x2e, 0x05, 0x56, 0x7a, 
+    0x05, 0x56, 0x7a, 0x37, 0x01, 0x9d, 0x7e, 0x37, 0x01, 0x7d, 0x7d, 0x43, 0x2d, 0x42, 0xbe, 0x44, 
+    0x29, 0xe2, 0x38, 0x68, 0x7a, 0x47, 0x01, 0x7d, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x7a, 0x51, 
+    0x31, 0x12, 0x7c, 0x15, 0x12, 0x65, 0x2b, 0x10, 0x77, 0xc4, 0x22, 0xc2, 0x77, 0x2d, 0x23, 0x68, 
+    0x78, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x27, 0x01, 0x9d, 0xbe, 0x24, 0x00, 0x00, 0x68, 0x6a, 0xbe, 
+    0x27, 0x01, 0xbd, 0x28, 0x04, 0x7e, 0x27, 0x01, 0xbd, 0x7e, 0x37, 0x01, 0x9d, 0x9d, 0x32, 0x7d, 
+    0x02, 0x2e, 0x05, 0x56, 0x7a, 0x05, 0x56, 0x7a, 0x37, 0x01, 0x9d, 0x7e, 0x37, 0x01, 0x7d, 0x7d, 
+    0x43, 0x2d, 0x42, 0xbe, 0x44, 0x29, 0xe2, 0x38, 0x13, 0x7a, 0x47, 0x01, 0x7d, 0x75, 0x31, 0x94, 
+    0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x02, 0x65, 0x2b, 0x75, 0x31, 0x94, 0x12, 
+    0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x9e, 0x44, 0x29, 0xe3, 0x9d, 0x24, 0x12, 0x65, 
+    0x2b, 0x7e, 0x34, 0x25, 0xe3, 0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0x7d, 0x12, 0x65, 0x2b, 
+    0xbe, 0x25, 0x20, 0x78, 0x03, 0x02, 0x5d, 0xe7, 0x22, 0xd2, 0x0f, 0x7e, 0x04, 0x25, 0xe3, 0x7a, 
+    0x07, 0x01, 0x7d, 0x7a, 0x07, 0x01, 0x8d, 0x75, 0x31, 0x94, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x00, 
+    0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x92, 0x12, 0x7c, 0x15, 0xd2, 0x04, 0x09, 0xb1, 0x00, 0x14, 
+    0xca, 0xb8, 0x54, 0x82, 0xda, 0xb8, 0x78, 0x70, 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x27, 0x01, 0xcd, 
+    0x2e, 0x24, 0x00, 0x02, 0x2d, 0x32, 0xbe, 0x34, 0x04, 0x00, 0x38, 0x3c, 0x7d, 0x02, 0x2e, 0x05, 
+    0x46, 0x7a, 0x05, 0x46, 0x7a, 0x37, 0x01, 0xe1, 0x7e, 0x37, 0x01, 0xdf, 0x7d, 0x43, 0x2d, 0x42, 
+    0xbe, 0x44, 0x05, 0xe2, 0x38, 0x44, 0x7a, 0x47, 0x01, 0xdf, 0x7e, 0x24, 0x07, 0x00, 0x2e, 0x27, 
+    0x01, 0xcd, 0x1b, 0x38, 0x20, 0x0b, 0x35, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0xbe, 0x50, 0x38, 
+    0x78, 0x03, 0x02, 0x66, 0x16, 0x02, 0x65, 0xfb, 0x75, 0x31, 0x99, 0x12, 0x7c, 0x15, 0x09, 0xb1, 
+    0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3f, 0x0a, 0x09, 0xb1, 0x00, 0x10, 0x54, 
+    0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x17, 0x22, 0x80, 0x7d, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 
+    0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x24, 0x7e, 0x64, 0x07, 0x00, 0x2e, 0x67, 0x01, 0xcd, 0x9e, 0x24, 
+    0x00, 0x02, 0x40, 0x17, 0x1b, 0x38, 0x60, 0x0b, 0x35, 0x12, 0x65, 0xfb, 0x7e, 0x34, 0x01, 0xe3, 
+    0x7d, 0x24, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdf, 0x02, 0x65, 0xfb, 0x7a, 0x39, 0xc0, 0x7e, 0x34, 
+    0x01, 0xe3, 0x7a, 0x39, 0xd0, 0x0b, 0x34, 0x1b, 0x44, 0x80, 0xe5, 0x9d, 0x32, 0x7c, 0xb6, 0x54, 
+    0x0f, 0x23, 0x23, 0x23, 0x44, 0x07, 0x7a, 0x69, 0xb0, 0x7a, 0x79, 0x70, 0x0b, 0x35, 0x75, 0x31, 
+    0x93, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0xbd, 0x04, 0x68, 0x29, 0x7a, 0x07, 
+    0x01, 0xdf, 0x7e, 0x47, 0x01, 0xe1, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xe1, 0x2e, 0x35, 0x46, 0x7a, 
+    0x35, 0x46, 0x22, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0x13, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 
+    0x2a, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0x2c, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0xd1, 0xd2, 0x04, 0x7e, 
+    0x07, 0x01, 0xe1, 0x7e, 0x24, 0x03, 0xfe, 0x9d, 0x20, 0x28, 0x40, 0x7e, 0x07, 0x01, 0xdf, 0x7e, 
+    0x44, 0x05, 0xe3, 0x7d, 0x60, 0x0b, 0x04, 0xbd, 0x04, 0x68, 0xd0, 0x7d, 0x70, 0x0b, 0x04, 0xbd, 
+    0x04, 0x68, 0xce, 0x7d, 0x54, 0x9d, 0x50, 0xbd, 0x25, 0x40, 0x02, 0x7d, 0x25, 0x7d, 0x32, 0x09, 
+    0xb1, 0x00, 0x14, 0xca, 0xb8, 0x54, 0x1f, 0xb4, 0x01, 0x31, 0xda, 0xb8, 0x7e, 0x19, 0xb0, 0x7a, 
+    0x09, 0xb0, 0x0b, 0x04, 0x1b, 0x24, 0x78, 0xe7, 0x02, 0x5f, 0x4b, 0x75, 0x31, 0x99, 0x12, 0x7c, 
+    0x15, 0x09, 0xb1, 0x00, 0x04, 0x54, 0xfa, 0x19, 0xb1, 0x00, 0x04, 0x30, 0x3f, 0x0a, 0x09, 0xb1, 
+    0x00, 0x10, 0x54, 0xfe, 0x19, 0xb1, 0x00, 0x10, 0xd2, 0x17, 0x22, 0xda, 0xb8, 0x30, 0xe0, 0xd8, 
+    0xbd, 0x32, 0x68, 0x07, 0xca, 0xb8, 0x12, 0x5f, 0x4b, 0xda, 0xb8, 0x02, 0x60, 0x98, 0x09, 0xb1, 
+    0x00, 0x18, 0x7e, 0xa0, 0x88, 0x75, 0x31, 0x90, 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 0x7c, 0x15, 
+    0xa5, 0xfc, 0x5e, 0xb0, 0xf0, 0xa5, 0xfd, 0x09, 0xb1, 0x00, 0x18, 0x4c, 0x4b, 0x5e, 0xb0, 0xf0, 
+    0xbc, 0xb5, 0x78, 0xf1, 0x5e, 0x40, 0x0f, 0x4c, 0x54, 0x7c, 0xb5, 0x5e, 0x50, 0x0b, 0x68, 0x2a, 
+    0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6f, 0x80, 0x02, 0xc2, 0x6f, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x20, 0x68, 0x04, 0xd2, 0x67, 0x80, 0x02, 0xc2, 0x67, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 
+    0x04, 0xd2, 0x5f, 0x80, 0x02, 0xc2, 0x5f, 0x12, 0x43, 0xaf, 0x02, 0x62, 0x93, 0x75, 0x31, 0x91, 
+    0x12, 0x7c, 0x15, 0x09, 0xb1, 0x00, 0x14, 0x7a, 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x20, 0xe0, 0x08, 
+    0xd2, 0x04, 0x7e, 0xa0, 0x80, 0x02, 0x62, 0x93, 0xd2, 0x04, 0x30, 0xe1, 0x06, 0x7e, 0xa0, 0x80, 
+    0x12, 0x62, 0x93, 0xca, 0xb8, 0x5e, 0xb0, 0x1c, 0xda, 0xb8, 0x68, 0x12, 0x7e, 0xa0, 0xc0, 0x09, 
+    0x61, 0x00, 0x00, 0x12, 0x62, 0xb6, 0x09, 0xb1, 0x00, 0x14, 0x20, 0xe0, 0xdb, 0x22, 0x02, 0x5f, 
+    0x9d, 0x75, 0x31, 0x95, 0x12, 0x7c, 0x15, 0x22, 0x75, 0x31, 0x96, 0x12, 0x7c, 0x15, 0x22, 0x7c, 
+    0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 
+    0x68, 0x04, 0xd2, 0x68, 0x80, 0x02, 0xc2, 0x68, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 
+    0x60, 0x80, 0x02, 0xc2, 0x60, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x58, 0x80, 0x02, 
+    0xc2, 0x58, 0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 
+    0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x69, 0x80, 0x02, 0xc2, 0x69, 0xa5, 0xfd, 
+    0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x61, 0x80, 0x02, 0xc2, 0x61, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 
+    0x68, 0x04, 0xd2, 0x59, 0x80, 0x02, 0xc2, 0x59, 0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 
+    0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6a, 
+    0x80, 0x02, 0xc2, 0x6a, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x62, 0x80, 0x02, 0xc2, 
+    0x62, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5a, 0x80, 0x02, 0xc2, 0x5a, 0x02, 0x62, 
+    0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x10, 0x68, 0x04, 0xd2, 0x6b, 0x80, 0x02, 0xc2, 0x6b, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 
+    0x04, 0xd2, 0x63, 0x80, 0x02, 0xc2, 0x63, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5b, 
+    0x80, 0x02, 0xc2, 0x5b, 0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 
+    0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6c, 0x80, 0x02, 0xc2, 0x6c, 
+    0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x64, 0x80, 0x02, 0xc2, 0x64, 0xa5, 0xfd, 0x5e, 
+    0x50, 0x80, 0x68, 0x04, 0xd2, 0x5c, 0x80, 0x02, 0xc2, 0x5c, 0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 
+    0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 
+    0xd2, 0x6d, 0x80, 0x02, 0xc2, 0x6d, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x65, 0x80, 
+    0x02, 0xc2, 0x65, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5d, 0x80, 0x02, 0xc2, 0x5d, 
+    0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 
+    0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6e, 0x80, 0x02, 0xc2, 0x6e, 0xa5, 0xfd, 0x5e, 0x50, 
+    0x20, 0x68, 0x04, 0xd2, 0x66, 0x80, 0x02, 0xc2, 0x66, 0xa5, 0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 
+    0xd2, 0x5e, 0x80, 0x02, 0xc2, 0x5e, 0x02, 0x62, 0x7f, 0x7c, 0x02, 0x7e, 0x14, 0x80, 0x00, 0x4c, 
+    0x20, 0x09, 0xb1, 0x00, 0x18, 0xa5, 0xfd, 0x5e, 0x50, 0x10, 0x68, 0x04, 0xd2, 0x6f, 0x80, 0x02, 
+    0xc2, 0x6f, 0xa5, 0xfd, 0x5e, 0x50, 0x20, 0x68, 0x04, 0xd2, 0x67, 0x80, 0x02, 0xc2, 0x67, 0xa5, 
+    0xfd, 0x5e, 0x50, 0x80, 0x68, 0x04, 0xd2, 0x5f, 0x80, 0x02, 0xc2, 0x5f, 0x02, 0x62, 0x7f, 0x54, 
+    0xf0, 0xc4, 0xa5, 0xff, 0xc4, 0xa5, 0x4f, 0x75, 0x31, 0x90, 0x12, 0x7c, 0x15, 0xf5, 0x31, 0x12, 
+    0x7c, 0x15, 0x22, 0xca, 0x19, 0x5e, 0x20, 0x07, 0x4c, 0xa2, 0x7e, 0x74, 0x29, 0xe3, 0xca, 0x79, 
+    0x7a, 0x79, 0xa0, 0x0b, 0x74, 0x7a, 0x79, 0xb0, 0x0b, 0x74, 0xda, 0x79, 0x7e, 0x30, 0x02, 0x7e, 
+    0x64, 0x00, 0x02, 0x02, 0x62, 0xde, 0xca, 0x19, 0x5e, 0x20, 0x07, 0x4c, 0xa2, 0x7e, 0x74, 0x29, 
+    0xe3, 0xca, 0x79, 0x7a, 0x79, 0xa0, 0x0b, 0x74, 0x7a, 0x79, 0xb0, 0x0b, 0x74, 0x7a, 0x79, 0x60, 
+    0x0b, 0x74, 0xda, 0x79, 0x7e, 0x30, 0x03, 0x7e, 0x64, 0x00, 0x03, 0x02, 0x62, 0xde, 0xd2, 0x04, 
+    0x7e, 0x27, 0x01, 0xe1, 0x2d, 0x26, 0xbe, 0x24, 0x04, 0x00, 0x38, 0x2e, 0x7e, 0x07, 0x01, 0xdf, 
+    0x7e, 0x44, 0x05, 0xe3, 0x7e, 0x79, 0xa0, 0x7a, 0x09, 0xa0, 0x0b, 0x04, 0x0b, 0x74, 0xbd, 0x04, 
+    0x68, 0x23, 0xa5, 0xdb, 0xef, 0x7a, 0x27, 0x01, 0xe1, 0x7e, 0x25, 0x46, 0x2d, 0x26, 0x7a, 0x25, 
+    0x46, 0x7a, 0x07, 0x01, 0xdf, 0xda, 0x19, 0xc2, 0xd7, 0x22, 0x75, 0x31, 0x9a, 0x12, 0x7c, 0x15, 
+    0xda, 0x19, 0xd2, 0xd7, 0x22, 0x7e, 0x04, 0x01, 0xe3, 0x80, 0xd7, 0x48, 0xb6, 0x46, 0x25, 0x47, 
+    0x1c, 0x49, 0x15, 0x44, 0xc6, 0x44, 0xc6, 0x48, 0x1b, 0x44, 0xc6, 0x49, 0x59, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x49, 0x60, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x4c, 0x0e, 0x49, 0x7d, 0x4a, 
+    0x74, 0x4c, 0x6d, 0x44, 0xc6, 0x44, 0xc6, 0x4b, 0x73, 0x44, 0xc6, 0x4c, 0xb1, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x4c, 0xb8, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x4f, 0x66, 0x4c, 0xd5, 0x4d, 
+    0xcc, 0x4f, 0xc5, 0x44, 0xc6, 0x44, 0xc6, 0x4e, 0xcb, 0x44, 0xc6, 0x50, 0x09, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x50, 0x10, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x52, 0xbe, 0x50, 0x2d, 0x51, 
+    0x24, 0x53, 0x1d, 0x44, 0xc6, 0x44, 0xc6, 0x52, 0x23, 0x44, 0xc6, 0x53, 0x61, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x53, 0x68, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x56, 0x16, 0x53, 0x85, 0x54, 
+    0x7c, 0x56, 0x75, 0x44, 0xc6, 0x44, 0xc6, 0x55, 0x7b, 0x44, 0xc6, 0x56, 0xb9, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x56, 0xc0, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x59, 0x6e, 0x56, 0xdd, 0x57, 
+    0xd4, 0x59, 0xcd, 0x44, 0xc6, 0x44, 0xc6, 0x58, 0xd3, 0x44, 0xc6, 0x5a, 0x11, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x5a, 0x18, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x5c, 0xc6, 0x5a, 0x35, 0x5b, 
+    0x2c, 0x5d, 0x25, 0x44, 0xc6, 0x44, 0xc6, 0x5c, 0x2b, 0x44, 0xc6, 0x5d, 0x69, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x5d, 0x70, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x60, 0x1e, 0x5d, 0x8d, 0x5e, 
+    0x84, 0x60, 0x7d, 0x44, 0xc6, 0x44, 0xc6, 0x5f, 0x83, 0x44, 0xc6, 0x60, 0xc1, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x60, 0xc8, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 
+    0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0x44, 0xc6, 0xca, 0x29, 0x1e, 0x50, 0x40, 
+    0x0d, 0x7e, 0x54, 0x0b, 0x10, 0x9c, 0xb5, 0xa4, 0x2e, 0x54, 0x65, 0x48, 0x89, 0x54, 0x7e, 0x39, 
+    0x00, 0x7a, 0x19, 0x00, 0x0b, 0x34, 0x80, 0xe9, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 
     0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 
     0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 
     0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 
@@ -744,12 +832,12 @@ static unsigned char IMAGE_ARRAY_NAME[] = {
     0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 
     0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 
     0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 
-    0x35, 0xda, 0x29, 0x22, 0x1e, 0x50, 0x40, 0x0d, 0x7e, 0x54, 0x0b, 0x1c, 0x9c, 0xb5, 0xa4, 0x2e, 
-    0x54, 0x69, 0x1f, 0x89, 0x54, 0x7e, 0x19, 0x00, 0x7a, 0x39, 0x00, 0x0b, 0x34, 0x80, 0xe9, 0x7e, 
-    0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 
-    0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 
-    0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 
-    0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 
+    0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 
+    0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 
+    0x0b, 0x35, 0x0b, 0x38, 0x00, 0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0x0b, 0x38, 0x00, 
+    0x7a, 0x19, 0x00, 0x7a, 0x19, 0x10, 0x0b, 0x35, 0xda, 0x29, 0x22, 0x1e, 0x50, 0x40, 0x0d, 0x7e, 
+    0x54, 0x0b, 0x1c, 0x9c, 0xb5, 0xa4, 0x2e, 0x54, 0x66, 0x16, 0x89, 0x54, 0x7e, 0x19, 0x00, 0x7a, 
+    0x39, 0x00, 0x0b, 0x34, 0x80, 0xe9, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 
     0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 
     0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 
     0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 
@@ -765,157 +853,176 @@ static unsigned char IMAGE_ARRAY_NAME[] = {
     0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 
     0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 
     0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 
-    0x00, 0x0b, 0x35, 0x22, 0x6a, 0x9b, 0x6c, 0x4f, 0x6c, 0x67, 0x6c, 0x82, 0x6d, 0x1d, 0x6d, 0xb5, 
-    0x6d, 0xd0, 0x6e, 0x62, 0x6d, 0xeb, 0x6e, 0x2c, 0x7c, 0xb3, 0xbe, 0xb0, 0x09, 0x28, 0x14, 0x75, 
-    0x2f, 0x09, 0x12, 0x7e, 0x30, 0x75, 0x57, 0x10, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x43, 0xe1, 0xc0, 
-    0xd0, 0xf1, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 0x23, 0x6c, 0xaa, 0x2e, 0x54, 0x6a, 0x54, 0x0b, 0x58, 
-    0x50, 0x89, 0x54, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x75, 0x2f, 0xb0, 0x12, 0x7e, 
-    0x30, 0x0a, 0x22, 0x09, 0xb2, 0x6a, 0x93, 0x42, 0x24, 0xd0, 0xa8, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 
-    0x3b, 0x49, 0x33, 0x6a, 0xb7, 0x89, 0x34, 0x6a, 0xc7, 0x6a, 0xf5, 0x6b, 0x23, 0x6b, 0x51, 0x6b, 
-    0x7f, 0x6b, 0xad, 0x6b, 0xdb, 0x6c, 0x09, 0x12, 0x41, 0xa9, 0xd2, 0x28, 0xd2, 0x08, 0xc2, 0x40, 
-    0xc2, 0x48, 0xc2, 0x38, 0xc2, 0x30, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xb9, 0x7e, 0x04, 0x00, 0x20, 
-    0x7a, 0x07, 0x01, 0x99, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xa9, 0x12, 0x41, 0x16, 0x12, 
-    0x64, 0x40, 0x02, 0x6c, 0x37, 0x12, 0x41, 0xc6, 0xd2, 0x29, 0xd2, 0x09, 0xc2, 0x41, 0xc2, 0x49, 
-    0xc2, 0x39, 0xc2, 0x31, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xba, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 
-    0x01, 0x9b, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xab, 0x12, 0x41, 0x16, 0x12, 0x64, 0x69, 
-    0x02, 0x6c, 0x37, 0x12, 0x41, 0xe3, 0xd2, 0x2a, 0xd2, 0x0a, 0xc2, 0x42, 0xc2, 0x4a, 0xc2, 0x3a, 
-    0xc2, 0x32, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xbb, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0x9d, 
-    0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xad, 0x12, 0x41, 0x16, 0x12, 0x64, 0x92, 0x02, 0x6c, 
-    0x37, 0x12, 0x42, 0x00, 0xd2, 0x2b, 0xd2, 0x0b, 0xc2, 0x43, 0xc2, 0x4b, 0xc2, 0x3b, 0xc2, 0x33, 
-    0x6d, 0x00, 0x7a, 0x03, 0x01, 0xbc, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0x9f, 0x7e, 0x04, 
-    0x00, 0x38, 0x7a, 0x07, 0x01, 0xaf, 0x12, 0x41, 0x16, 0x12, 0x64, 0xbb, 0x02, 0x6c, 0x37, 0x12, 
-    0x42, 0x1d, 0xd2, 0x2c, 0xd2, 0x0c, 0xc2, 0x44, 0xc2, 0x4c, 0xc2, 0x3c, 0xc2, 0x34, 0x6d, 0x00, 
-    0x7a, 0x03, 0x01, 0xbd, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xa1, 0x7e, 0x04, 0x00, 0x38, 
-    0x7a, 0x07, 0x01, 0xb1, 0x12, 0x41, 0x16, 0x12, 0x64, 0xe4, 0x02, 0x6c, 0x37, 0x12, 0x42, 0x3a, 
-    0xd2, 0x2d, 0xd2, 0x0d, 0xc2, 0x45, 0xc2, 0x4d, 0xc2, 0x3d, 0xc2, 0x35, 0x6d, 0x00, 0x7a, 0x03, 
-    0x01, 0xbe, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xa3, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 
-    0x01, 0xb3, 0x12, 0x41, 0x16, 0x12, 0x65, 0x0d, 0x02, 0x6c, 0x37, 0x12, 0x42, 0x57, 0xd2, 0x2e, 
-    0xd2, 0x0e, 0xc2, 0x46, 0xc2, 0x4e, 0xc2, 0x3e, 0xc2, 0x36, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xbf, 
-    0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xa5, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xb5, 
-    0x12, 0x41, 0x16, 0x12, 0x65, 0x36, 0x02, 0x6c, 0x37, 0x12, 0x42, 0x74, 0xd2, 0x2f, 0xd2, 0x0f, 
-    0xc2, 0x47, 0xc2, 0x4f, 0xc2, 0x3f, 0xc2, 0x37, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xc0, 0x7e, 0x04, 
-    0x00, 0x20, 0x7a, 0x07, 0x01, 0xa7, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xb7, 0x12, 0x41, 
-    0x16, 0x12, 0x65, 0x5f, 0x02, 0x6c, 0x37, 0x7e, 0xa0, 0xd0, 0x7e, 0x60, 0x0f, 0x12, 0x65, 0xbf, 
-    0x40, 0x0c, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0xc2, 0xd7, 0x22, 0x75, 
-    0x2f, 0xb1, 0x12, 0x7e, 0x30, 0x0a, 0x52, 0x23, 0x6d, 0x00, 0x59, 0x05, 0x00, 0x32, 0x12, 0x41, 
-    0x72, 0x12, 0x41, 0x8e, 0xd0, 0xa8, 0x22, 0x75, 0x2f, 0xb2, 0x12, 0x7e, 0x30, 0x0a, 0x22, 0x09, 
-    0xb2, 0x6a, 0x93, 0x42, 0x23, 0x7e, 0xb0, 0x9c, 0x19, 0xb2, 0x01, 0xb9, 0x12, 0x45, 0x74, 0xd0, 
-    0xa8, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 
-    0x00, 0x0c, 0x09, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 0x0c, 0x7c, 0x74, 0x5e, 0x70, 0x01, 0x68, 
-    0x12, 0x44, 0x40, 0xca, 0xb8, 0x09, 0xb0, 0x00, 0x10, 0x44, 0x02, 0x19, 0xb0, 0x00, 0x10, 0xda, 
-    0xb8, 0x80, 0x02, 0x54, 0xbf, 0x7c, 0x74, 0x5e, 0x70, 0x08, 0x68, 0x04, 0x44, 0x08, 0x80, 0x02, 
-    0x54, 0xf7, 0x09, 0x30, 0x00, 0x0c, 0xca, 0xb8, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0xda, 0xb8, 
-    0x19, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 0x0c, 0x0a, 0x62, 0x09, 0xb6, 0x6a, 0x93, 0x3e, 0x20, 
-    0x0a, 0x62, 0x7c, 0x74, 0x5e, 0x70, 0x02, 0x68, 0x20, 0x42, 0x27, 0xca, 0xb8, 0x74, 0x61, 0x19, 
-    0xb0, 0x00, 0x08, 0x7e, 0x44, 0x00, 0x10, 0x59, 0x46, 0x01, 0xa9, 0x09, 0xb0, 0x00, 0x10, 0x44, 
-    0x01, 0x19, 0xb0, 0x00, 0x10, 0xda, 0xb8, 0x80, 0x11, 0xf4, 0x52, 0x27, 0x74, 0xa1, 0x19, 0xb0, 
-    0x00, 0x08, 0x7e, 0x44, 0x00, 0x38, 0x59, 0x46, 0x01, 0xa9, 0xd0, 0xa8, 0x22, 0x7c, 0x74, 0x7e, 
-    0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 
-    0xb0, 0x00, 0x08, 0x7c, 0x74, 0x5e, 0x70, 0x01, 0x68, 0x04, 0x44, 0x80, 0x80, 0x02, 0x54, 0x7f, 
-    0x7c, 0x74, 0x5e, 0x70, 0x08, 0x68, 0x04, 0x44, 0x02, 0x80, 0x02, 0x54, 0xfd, 0x19, 0xb0, 0x00, 
-    0x08, 0x19, 0x30, 0x00, 0x0c, 0x0a, 0x62, 0x09, 0xb6, 0x6a, 0x93, 0xa5, 0xfd, 0xf4, 0xa5, 0xfe, 
-    0xca, 0x28, 0x3e, 0x20, 0x0a, 0x62, 0xda, 0x28, 0x7c, 0x74, 0x5e, 0x70, 0x02, 0x68, 0x10, 0xa5, 
-    0xed, 0x42, 0x28, 0x42, 0x26, 0x7e, 0x44, 0x00, 0x08, 0x59, 0x46, 0x01, 0x99, 0x80, 0x04, 0xa5, 
-    0xee, 0x52, 0x28, 0x7c, 0x74, 0x5e, 0x70, 0x04, 0x68, 0x10, 0xa5, 0xed, 0x42, 0x29, 0x42, 0x26, 
-    0x7e, 0x44, 0x00, 0x08, 0x59, 0x46, 0x01, 0x99, 0x80, 0x15, 0xa5, 0xee, 0x52, 0x29, 0x7c, 0x74, 
-    0x5e, 0x70, 0x02, 0x78, 0x0a, 0x52, 0x26, 0x7e, 0x44, 0x00, 0x20, 0x59, 0x46, 0x01, 0x99, 0x12, 
-    0x42, 0x91, 0xd0, 0xa8, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 
-    0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x19, 0x40, 0x00, 0x10, 0x19, 0x30, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 
-    0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 
-    0x19, 0x40, 0x00, 0x18, 0x19, 0x30, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x2f, 0xb5, 0x12, 0x7e, 
-    0x30, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0xb0, 0x00, 0x0c, 0x44, 0x40, 0x19, 0xb0, 0x00, 
-    0x0c, 0xe5, 0x58, 0xb4, 0x07, 0x23, 0x09, 0xb0, 0x00, 0x10, 0x4e, 0xb0, 0x02, 0x19, 0xb0, 0x00, 
-    0x10, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x04, 0x54, 
-    0xf7, 0x19, 0xb0, 0x00, 0x04, 0x19, 0x30, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x2f, 0xb6, 0x12, 
-    0x7e, 0x30, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0xe5, 0x58, 0xb4, 0x07, 0x18, 0x09, 0x30, 0x00, 
-    0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x04, 0x44, 0x08, 0x19, 0xb0, 0x00, 
-    0x04, 0x19, 0x30, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x0c, 0x54, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0xd0, 
-    0xa8, 0x22, 0x75, 0x2f, 0xb4, 0x12, 0x7e, 0x30, 0x7a, 0x21, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x41, 
-    0x2f, 0x12, 0x7e, 0x30, 0x7e, 0xb0, 0x01, 0x7e, 0xa0, 0xc8, 0x7c, 0x64, 0x12, 0x65, 0xbf, 0xc0, 
-    0xf1, 0x75, 0xf1, 0x01, 0x12, 0x71, 0xe9, 0xd0, 0xf1, 0xd0, 0xa8, 0x22, 0x6e, 0x9c, 0x6e, 0xe3, 
-    0x6f, 0x2a, 0x6f, 0x71, 0x6f, 0xb8, 0x6f, 0xff, 0x70, 0x46, 0x70, 0x8d, 0x75, 0x2f, 0x55, 0x12, 
-    0x7e, 0x30, 0x75, 0x2f, 0x00, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 
-    0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x69, 0x7e, 0x27, 0x01, 0x79, 0x2d, 0x23, 0x7e, 0x09, 
-    0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x0d, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 
-    0x78, 0xec, 0x7a, 0x17, 0x01, 0x69, 0x7a, 0x27, 0x01, 0x79, 0x02, 0x4a, 0x98, 0x7e, 0x14, 0x09, 
-    0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x01, 0x12, 0x7e, 0x30, 0x7a, 
-    0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x6b, 0x7e, 
-    0x27, 0x01, 0x7b, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 
-    0x14, 0x11, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x6b, 0x7a, 0x27, 0x01, 
-    0x7b, 0x02, 0x4d, 0xcd, 0x7e, 0x14, 0x0d, 0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 
-    0x75, 0x2f, 0x02, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 
-    0x7e, 0x30, 0x7e, 0x17, 0x01, 0x6d, 0x7e, 0x27, 0x01, 0x7d, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 
-    0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x15, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 
-    0x7a, 0x17, 0x01, 0x6d, 0x7a, 0x27, 0x01, 0x7d, 0x02, 0x51, 0x02, 0x7e, 0x14, 0x11, 0xcd, 0x80, 
-    0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x03, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 
-    0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x6f, 0x7e, 0x27, 0x01, 
-    0x7f, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x19, 
-    0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x6f, 0x7a, 0x27, 0x01, 0x7f, 0x02, 
-    0x54, 0x37, 0x7e, 0x14, 0x15, 0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 
-    0x04, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 
-    0x7e, 0x17, 0x01, 0x71, 0x7e, 0x27, 0x01, 0x81, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 
-    0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x1d, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 
-    0x01, 0x71, 0x7a, 0x27, 0x01, 0x81, 0x02, 0x57, 0x6c, 0x7e, 0x14, 0x19, 0xcd, 0x80, 0xeb, 0x75, 
-    0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x05, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 
-    0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x73, 0x7e, 0x27, 0x01, 0x83, 0x2d, 
-    0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x21, 0xcc, 0x38, 
-    0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x73, 0x7a, 0x27, 0x01, 0x83, 0x02, 0x5a, 0xa1, 
-    0x7e, 0x14, 0x1d, 0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 0x12, 0x7e, 0x30, 0x75, 0x2f, 0x06, 0x12, 
-    0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 
-    0x01, 0x75, 0x7e, 0x27, 0x01, 0x85, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 
-    0x0b, 0x14, 0xbe, 0x14, 0x25, 0xcc, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x75, 
-    0x7a, 0x27, 0x01, 0x85, 0x02, 0x5d, 0xd6, 0x7e, 0x14, 0x21, 0xcd, 0x80, 0xeb, 0x75, 0x2f, 0x55, 
-    0x12, 0x7e, 0x30, 0x75, 0x2f, 0x07, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 
-    0x71, 0x2f, 0x12, 0x7e, 0x30, 0x7e, 0x17, 0x01, 0x77, 0x7e, 0x27, 0x01, 0x87, 0x2d, 0x23, 0x7e, 
-    0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x29, 0xcc, 0x38, 0x0f, 0x1b, 
-    0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x77, 0x7a, 0x27, 0x01, 0x87, 0x02, 0x61, 0x0b, 0x7e, 0x14, 
-    0x25, 0xcd, 0x80, 0xeb, 0xca, 0xb8, 0xc0, 0xf1, 0x75, 0x2f, 0x02, 0x12, 0x7e, 0x30, 0xe5, 0xc0, 
-    0x54, 0x03, 0x68, 0x05, 0x12, 0x77, 0xdd, 0x80, 0xf5, 0x30, 0xc2, 0x08, 0x75, 0xf1, 0x01, 0x12, 
-    0x71, 0xe9, 0x80, 0x14, 0x30, 0xc3, 0x08, 0x75, 0xf1, 0x01, 0x12, 0x71, 0x0d, 0x80, 0x09, 0x30, 
-    0xc4, 0x06, 0x75, 0xf1, 0x02, 0x12, 0x72, 0xf9, 0xd0, 0xf1, 0xda, 0xb8, 0x32, 0x75, 0x2f, 0x10, 
-    0x12, 0x7e, 0x30, 0xca, 0x0b, 0xca, 0x39, 0xca, 0x59, 0xc2, 0xc3, 0xa9, 0x21, 0xe2, 0x5c, 0xe5, 
-    0xe5, 0x54, 0xc0, 0x68, 0x4f, 0xe5, 0xe6, 0x6c, 0xaa, 0x7e, 0x37, 0x01, 0xc5, 0x2d, 0x35, 0xbe, 
-    0x34, 0x04, 0x00, 0x38, 0x4a, 0x7a, 0x37, 0x01, 0xc5, 0x7e, 0x37, 0x01, 0xc3, 0x7d, 0x43, 0x2d, 
-    0x45, 0xbe, 0x44, 0x09, 0xcc, 0x38, 0x40, 0x7a, 0x47, 0x01, 0xc3, 0x75, 0x2f, 0x11, 0x12, 0x7e, 
-    0x30, 0x7a, 0xb1, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x73, 0xc8, 0xa9, 0x21, 0xe5, 0x1f, 0xa9, 0xd4, 
+    0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 
+    0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 
+    0x38, 0x00, 0x0b, 0x35, 0x7e, 0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x7e, 
+    0x19, 0x00, 0x7e, 0x19, 0x10, 0x1b, 0x38, 0x00, 0x0b, 0x35, 0x22, 0x67, 0x96, 0x69, 0x63, 0x69, 
+    0x7b, 0x6a, 0x49, 0x6a, 0xe4, 0x6b, 0x8e, 0x6b, 0xa9, 0x6c, 0x3b, 0x6b, 0xc4, 0x6c, 0x05, 0x69, 
+    0x96, 0x69, 0xaa, 0x7c, 0xb3, 0xbe, 0xb0, 0x0b, 0x28, 0x14, 0x75, 0x31, 0x09, 0x12, 0x7c, 0x15, 
+    0x75, 0x6d, 0x10, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x43, 0xe1, 0xc0, 0xd0, 0xf1, 0x22, 0xc0, 0xa8, 
+    0xc2, 0xaf, 0x23, 0x6c, 0xaa, 0x2e, 0x54, 0x67, 0x4b, 0x0b, 0x58, 0x50, 0x89, 0x54, 0x01, 0x02, 
+    0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x75, 0x31, 0xb0, 0x12, 0x7c, 0x15, 0x0a, 0x32, 0x09, 0xb3, 
+    0x67, 0x8e, 0x42, 0x32, 0x19, 0x43, 0x00, 0x36, 0xd0, 0xa8, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x3b, 
+    0x49, 0x33, 0x67, 0xcb, 0x0a, 0x22, 0x09, 0x32, 0x00, 0x36, 0x09, 0xb2, 0x67, 0x8e, 0xa5, 0xbb, 
+    0x00, 0x05, 0xf4, 0x52, 0x33, 0x80, 0x02, 0x42, 0x33, 0x89, 0x34, 0x67, 0xdb, 0x68, 0x09, 0x68, 
+    0x37, 0x68, 0x65, 0x68, 0x93, 0x68, 0xc1, 0x68, 0xef, 0x69, 0x1d, 0x12, 0x41, 0xb5, 0xd2, 0x28, 
+    0xd2, 0x08, 0xc2, 0x40, 0xc2, 0x48, 0xc2, 0x38, 0xc2, 0x30, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xcf, 
+    0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xaf, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xbf, 
+    0x12, 0x41, 0x16, 0x12, 0x60, 0xcf, 0x02, 0x69, 0x4b, 0x12, 0x41, 0xd4, 0xd2, 0x29, 0xd2, 0x09, 
+    0xc2, 0x41, 0xc2, 0x49, 0xc2, 0x39, 0xc2, 0x31, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xd0, 0x7e, 0x04, 
+    0x00, 0x20, 0x7a, 0x07, 0x01, 0xb1, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xc1, 0x12, 0x41, 
+    0x16, 0x12, 0x61, 0x05, 0x02, 0x69, 0x4b, 0x12, 0x41, 0xf3, 0xd2, 0x2a, 0xd2, 0x0a, 0xc2, 0x42, 
+    0xc2, 0x4a, 0xc2, 0x3a, 0xc2, 0x32, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xd1, 0x7e, 0x04, 0x00, 0x20, 
+    0x7a, 0x07, 0x01, 0xb3, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xc3, 0x12, 0x41, 0x16, 0x12, 
+    0x61, 0x3b, 0x02, 0x69, 0x4b, 0x12, 0x42, 0x12, 0xd2, 0x2b, 0xd2, 0x0b, 0xc2, 0x43, 0xc2, 0x4b, 
+    0xc2, 0x3b, 0xc2, 0x33, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xd2, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 
+    0x01, 0xb5, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xc5, 0x12, 0x41, 0x16, 0x12, 0x61, 0x71, 
+    0x02, 0x69, 0x4b, 0x12, 0x42, 0x31, 0xd2, 0x2c, 0xd2, 0x0c, 0xc2, 0x44, 0xc2, 0x4c, 0xc2, 0x3c, 
+    0xc2, 0x34, 0x6d, 0x00, 0x7a, 0x03, 0x01, 0xd3, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xb7, 
+    0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 0x01, 0xc7, 0x12, 0x41, 0x16, 0x12, 0x61, 0xa7, 0x02, 0x69, 
+    0x4b, 0x12, 0x42, 0x50, 0xd2, 0x2d, 0xd2, 0x0d, 0xc2, 0x45, 0xc2, 0x4d, 0xc2, 0x3d, 0xc2, 0x35, 
+    0x6d, 0x00, 0x7a, 0x03, 0x01, 0xd4, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xb9, 0x7e, 0x04, 
+    0x00, 0x38, 0x7a, 0x07, 0x01, 0xc9, 0x12, 0x41, 0x16, 0x12, 0x61, 0xdd, 0x02, 0x69, 0x4b, 0x12, 
+    0x42, 0x6f, 0xd2, 0x2e, 0xd2, 0x0e, 0xc2, 0x46, 0xc2, 0x4e, 0xc2, 0x3e, 0xc2, 0x36, 0x6d, 0x00, 
+    0x7a, 0x03, 0x01, 0xd5, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xbb, 0x7e, 0x04, 0x00, 0x38, 
+    0x7a, 0x07, 0x01, 0xcb, 0x12, 0x41, 0x16, 0x12, 0x62, 0x13, 0x02, 0x69, 0x4b, 0x12, 0x42, 0x8e, 
+    0xd2, 0x2f, 0xd2, 0x0f, 0xc2, 0x47, 0xc2, 0x4f, 0xc2, 0x3f, 0xc2, 0x37, 0x6d, 0x00, 0x7a, 0x03, 
+    0x01, 0xd6, 0x7e, 0x04, 0x00, 0x20, 0x7a, 0x07, 0x01, 0xbd, 0x7e, 0x04, 0x00, 0x38, 0x7a, 0x07, 
+    0x01, 0xcd, 0x12, 0x41, 0x16, 0x12, 0x62, 0x49, 0x02, 0x69, 0x4b, 0x7e, 0xa0, 0xd0, 0x7e, 0x60, 
+    0x0f, 0x12, 0x62, 0xb6, 0x40, 0x0c, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 
+    0xc2, 0xd7, 0x22, 0x75, 0x31, 0xb1, 0x12, 0x7c, 0x15, 0x0a, 0x52, 0x23, 0x6d, 0x00, 0x59, 0x05, 
+    0x00, 0x48, 0x12, 0x41, 0x7e, 0x12, 0x41, 0x9a, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb2, 0x12, 0x7c, 
+    0x15, 0x0a, 0x22, 0x09, 0xb2, 0x67, 0x8e, 0x42, 0x23, 0x7e, 0xb0, 0x9c, 0x19, 0xb2, 0x01, 0xcf, 
+    0x12, 0x31, 0x85, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb7, 0x12, 0x7c, 0x15, 0x0a, 0x22, 0x09, 0xb2, 
+    0x67, 0x8e, 0x42, 0x24, 0x12, 0x35, 0x3d, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb9, 0x12, 0x7c, 0x15, 
+    0x0a, 0x32, 0x09, 0xb3, 0x67, 0x8e, 0x42, 0x34, 0x19, 0x43, 0x00, 0x3e, 0x12, 0x69, 0xc2, 0xd0, 
+    0xa8, 0x22, 0x7c, 0xb2, 0x23, 0x0a, 0x0b, 0x7c, 0xb4, 0x20, 0xe0, 0x04, 0x6d, 0x33, 0x80, 0x04, 
+    0x49, 0x30, 0x01, 0x8f, 0x7e, 0xa0, 0xd8, 0xa5, 0xef, 0xca, 0x0b, 0xca, 0x29, 0x12, 0x62, 0xb6, 
+    0xda, 0x29, 0xda, 0x0b, 0x40, 0x62, 0x75, 0x31, 0xba, 0x12, 0x7c, 0x15, 0x7c, 0xb4, 0x30, 0xe0, 
+    0x1e, 0x6d, 0x33, 0x59, 0x30, 0x01, 0x8f, 0x7e, 0x34, 0x09, 0xe3, 0x0a, 0x82, 0x7e, 0x94, 0x04, 
+    0x00, 0xad, 0x89, 0x2d, 0x39, 0x59, 0x30, 0x01, 0x6f, 0x59, 0x30, 0x01, 0x7f, 0x7c, 0xb4, 0x30, 
+    0xe1, 0x10, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 0xb0, 0x00, 0x08, 0x44, 0x04, 0x19, 0xb0, 
+    0x00, 0x08, 0x0a, 0x02, 0x09, 0xb0, 0x67, 0x8e, 0x42, 0x21, 0xf4, 0x52, 0x34, 0x7c, 0xb2, 0x23, 
+    0x0a, 0x0b, 0xca, 0x19, 0x49, 0x00, 0x30, 0xd5, 0x99, 0x04, 0xda, 0x19, 0xc0, 0xf1, 0x75, 0xf1, 
+    0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0xc2, 0xd7, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 
+    0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 
+    0x0c, 0x7c, 0x74, 0x5e, 0x70, 0x01, 0x68, 0x12, 0x44, 0x40, 0xca, 0xb8, 0x09, 0xb0, 0x00, 0x10, 
+    0x44, 0x02, 0x19, 0xb0, 0x00, 0x10, 0xda, 0xb8, 0x80, 0x02, 0x54, 0xbf, 0x7c, 0x74, 0x5e, 0x70, 
+    0x08, 0x68, 0x04, 0x44, 0x08, 0x80, 0x02, 0x54, 0xf7, 0x09, 0x30, 0x00, 0x0c, 0xca, 0xb8, 0x74, 
+    0xbf, 0x19, 0xb0, 0x00, 0x0c, 0xda, 0xb8, 0x19, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 0x0c, 0x0a, 
+    0x62, 0x09, 0xb6, 0x67, 0x8e, 0x3e, 0x20, 0x0a, 0x62, 0x7c, 0x74, 0x5e, 0x70, 0x02, 0x68, 0x20, 
+    0x42, 0x27, 0xca, 0xb8, 0x74, 0x61, 0x19, 0xb0, 0x00, 0x08, 0x7e, 0x44, 0x00, 0x10, 0x59, 0x46, 
+    0x01, 0xbf, 0x09, 0xb0, 0x00, 0x10, 0x44, 0x01, 0x19, 0xb0, 0x00, 0x10, 0xda, 0xb8, 0x80, 0x11, 
+    0xf4, 0x52, 0x27, 0x74, 0xa1, 0x19, 0xb0, 0x00, 0x08, 0x7e, 0x44, 0x00, 0x38, 0x59, 0x46, 0x01, 
+    0xbf, 0xd0, 0xa8, 0x22, 0x7c, 0x74, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x0a, 0x62, 0x09, 0xb6, 
+    0x67, 0x8e, 0xa5, 0xfd, 0xf4, 0xa5, 0xfe, 0xca, 0x28, 0x3e, 0x20, 0x0a, 0x62, 0xa5, 0xee, 0x52, 
+    0x26, 0x7e, 0x44, 0x00, 0x20, 0x59, 0x46, 0x01, 0xaf, 0xda, 0x28, 0x09, 0x30, 0x00, 0x0c, 0x74, 
+    0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x08, 0x7c, 0x74, 0x5e, 0x70, 0x01, 0x68, 0x0c, 
+    0x44, 0x80, 0xca, 0xb8, 0xa5, 0xed, 0x42, 0x2a, 0xda, 0xb8, 0x80, 0x0a, 0x54, 0x7f, 0xca, 0xb8, 
+    0xa5, 0xee, 0x52, 0x2a, 0xda, 0xb8, 0x7c, 0x74, 0x5e, 0x70, 0x08, 0x68, 0x04, 0x44, 0x02, 0x80, 
+    0x02, 0x54, 0xfd, 0x19, 0xb0, 0x00, 0x08, 0x19, 0x30, 0x00, 0x0c, 0x7c, 0x74, 0x5e, 0x70, 0x02, 
+    0x68, 0x10, 0xa5, 0xed, 0x42, 0x28, 0x42, 0x26, 0x7e, 0x44, 0x00, 0x08, 0x59, 0x46, 0x01, 0xaf, 
+    0x80, 0x04, 0xa5, 0xee, 0x52, 0x28, 0x7c, 0x74, 0x5e, 0x70, 0x04, 0x68, 0x10, 0xa5, 0xed, 0x42, 
+    0x29, 0x42, 0x26, 0x7e, 0x44, 0x00, 0x08, 0x59, 0x46, 0x01, 0xaf, 0x80, 0x0b, 0xa5, 0xee, 0x52, 
+    0x29, 0x7c, 0x74, 0x5e, 0x70, 0x02, 0x78, 0x00, 0x12, 0x42, 0xad, 0xd0, 0xa8, 0x22, 0x7e, 0x04, 
+    0x80, 0x00, 0x4c, 0x02, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x19, 0x40, 
+    0x00, 0x10, 0x19, 0x30, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 0x09, 
+    0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0x19, 0x40, 0x00, 0x18, 0x19, 0x30, 0x00, 
+    0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb5, 0x12, 0x7c, 0x15, 0x7e, 0x04, 0x80, 0x00, 0x4c, 0x02, 
+    0x09, 0xb0, 0x00, 0x0c, 0x44, 0x40, 0x19, 0xb0, 0x00, 0x0c, 0xe5, 0x6e, 0xb4, 0x07, 0x23, 0x09, 
+    0xb0, 0x00, 0x10, 0x4e, 0xb0, 0x02, 0x19, 0xb0, 0x00, 0x10, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 
+    0x19, 0xb0, 0x00, 0x0c, 0x09, 0xb0, 0x00, 0x04, 0x54, 0xf7, 0x19, 0xb0, 0x00, 0x04, 0x19, 0x30, 
+    0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb6, 0x12, 0x7c, 0x15, 0x7e, 0x04, 0x80, 0x00, 0x4c, 
+    0x02, 0xe5, 0x6e, 0xb4, 0x07, 0x18, 0x09, 0x30, 0x00, 0x0c, 0x74, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 
+    0x09, 0xb0, 0x00, 0x04, 0x44, 0x08, 0x19, 0xb0, 0x00, 0x04, 0x19, 0x30, 0x00, 0x0c, 0x09, 0xb0, 
+    0x00, 0x0c, 0x54, 0xbf, 0x19, 0xb0, 0x00, 0x0c, 0xd0, 0xa8, 0x22, 0x75, 0x31, 0xb4, 0x12, 0x7c, 
+    0x15, 0x7a, 0x21, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x41, 0x31, 0x12, 0x7c, 0x15, 0x0a, 0x32, 0x09, 
+    0xb3, 0x67, 0x8e, 0x42, 0x35, 0x12, 0x6c, 0x5b, 0xd0, 0xa8, 0x22, 0x7e, 0xb0, 0x01, 0x7e, 0xa0, 
+    0xc8, 0x7c, 0x64, 0x12, 0x62, 0xb6, 0x40, 0x13, 0x0a, 0x32, 0x09, 0xb3, 0x67, 0x8e, 0xf4, 0x52, 
+    0x35, 0xc0, 0xf1, 0x75, 0xf1, 0x01, 0x12, 0x6f, 0xd9, 0xd0, 0xf1, 0x22, 0x6c, 0x8c, 0x6c, 0xd3, 
+    0x6d, 0x1a, 0x6d, 0x61, 0x6d, 0xa8, 0x6d, 0xef, 0x6e, 0x36, 0x6e, 0x7d, 0x75, 0x31, 0x55, 0x12, 
+    0x7c, 0x15, 0x75, 0x31, 0x00, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x71, 
+    0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 0x01, 0x7f, 0x7e, 0x27, 0x01, 0x8f, 0x2d, 0x23, 0x7e, 0x09, 
+    0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x0d, 0xe2, 0x38, 0x0f, 0x1b, 0x34, 
+    0x78, 0xec, 0x7a, 0x17, 0x01, 0x7f, 0x7a, 0x27, 0x01, 0x8f, 0x02, 0x46, 0x0f, 0x7e, 0x14, 0x09, 
+    0xe3, 0x80, 0xeb, 0x75, 0x31, 0x55, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x01, 0x12, 0x7c, 0x15, 0x7a, 
+    0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 0x01, 0x81, 0x7e, 
+    0x27, 0x01, 0x91, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 
+    0x14, 0x11, 0xe2, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x81, 0x7a, 0x27, 0x01, 
+    0x91, 0x02, 0x49, 0x67, 0x7e, 0x14, 0x0d, 0xe3, 0x80, 0xeb, 0x75, 0x31, 0x55, 0x12, 0x7c, 0x15, 
+    0x75, 0x31, 0x02, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 
+    0x7c, 0x15, 0x7e, 0x17, 0x01, 0x83, 0x7e, 0x27, 0x01, 0x93, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 
+    0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x15, 0xe2, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 
+    0x7a, 0x17, 0x01, 0x83, 0x7a, 0x27, 0x01, 0x93, 0x02, 0x4c, 0xbf, 0x7e, 0x14, 0x11, 0xe3, 0x80, 
+    0xeb, 0x75, 0x31, 0x55, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x03, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 
+    0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 0x01, 0x85, 0x7e, 0x27, 0x01, 
+    0x95, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x19, 
+    0xe2, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x85, 0x7a, 0x27, 0x01, 0x95, 0x02, 
+    0x50, 0x17, 0x7e, 0x14, 0x15, 0xe3, 0x80, 0xeb, 0x75, 0x31, 0x55, 0x12, 0x7c, 0x15, 0x75, 0x31, 
+    0x04, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 
+    0x7e, 0x17, 0x01, 0x87, 0x7e, 0x27, 0x01, 0x97, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 
+    0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x1d, 0xe2, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 
+    0x01, 0x87, 0x7a, 0x27, 0x01, 0x97, 0x02, 0x53, 0x6f, 0x7e, 0x14, 0x19, 0xe3, 0x80, 0xeb, 0x75, 
+    0x31, 0x55, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x05, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 
+    0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 0x01, 0x89, 0x7e, 0x27, 0x01, 0x99, 0x2d, 
+    0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x21, 0xe2, 0x38, 
+    0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x89, 0x7a, 0x27, 0x01, 0x99, 0x02, 0x56, 0xc7, 
+    0x7e, 0x14, 0x1d, 0xe3, 0x80, 0xeb, 0x75, 0x31, 0x55, 0x12, 0x7c, 0x15, 0x75, 0x31, 0x06, 0x12, 
+    0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 
+    0x01, 0x8b, 0x7e, 0x27, 0x01, 0x9b, 0x2d, 0x23, 0x7e, 0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 
+    0x0b, 0x14, 0xbe, 0x14, 0x25, 0xe2, 0x38, 0x0f, 0x1b, 0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x8b, 
+    0x7a, 0x27, 0x01, 0x9b, 0x02, 0x5a, 0x1f, 0x7e, 0x14, 0x21, 0xe3, 0x80, 0xeb, 0x75, 0x31, 0x55, 
+    0x12, 0x7c, 0x15, 0x75, 0x31, 0x07, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 0x15, 0x7a, 
+    0x71, 0x31, 0x12, 0x7c, 0x15, 0x7e, 0x17, 0x01, 0x8d, 0x7e, 0x27, 0x01, 0x9d, 0x2d, 0x23, 0x7e, 
+    0x09, 0xb0, 0x0b, 0x04, 0x7a, 0x19, 0xb0, 0x0b, 0x14, 0xbe, 0x14, 0x29, 0xe2, 0x38, 0x0f, 0x1b, 
+    0x34, 0x78, 0xec, 0x7a, 0x17, 0x01, 0x8d, 0x7a, 0x27, 0x01, 0x9d, 0x02, 0x5d, 0x77, 0x7e, 0x14, 
+    0x25, 0xe3, 0x80, 0xeb, 0xca, 0xb8, 0xc0, 0xf1, 0x75, 0x31, 0x02, 0x12, 0x7c, 0x15, 0xe5, 0xc0, 
+    0x54, 0x03, 0x68, 0x05, 0x12, 0x75, 0xcd, 0x80, 0xf5, 0x30, 0xc2, 0x08, 0x75, 0xf1, 0x01, 0x12, 
+    0x6f, 0xd9, 0x80, 0x14, 0x30, 0xc3, 0x08, 0x75, 0xf1, 0x01, 0x12, 0x6e, 0xfd, 0x80, 0x09, 0x30, 
+    0xc4, 0x06, 0x75, 0xf1, 0x02, 0x12, 0x70, 0xe9, 0xd0, 0xf1, 0xda, 0xb8, 0x32, 0x75, 0x31, 0x10, 
+    0x12, 0x7c, 0x15, 0xca, 0x0b, 0xca, 0x39, 0xca, 0x59, 0xc2, 0xc3, 0xa9, 0x21, 0xe2, 0x5c, 0xe5, 
+    0xe5, 0x54, 0xc0, 0x68, 0x4f, 0xe5, 0xe6, 0x6c, 0xaa, 0x7e, 0x37, 0x01, 0xdb, 0x2d, 0x35, 0xbe, 
+    0x34, 0x04, 0x00, 0x38, 0x4a, 0x7a, 0x37, 0x01, 0xdb, 0x7e, 0x37, 0x01, 0xd9, 0x7d, 0x43, 0x2d, 
+    0x45, 0xbe, 0x44, 0x09, 0xe2, 0x38, 0x40, 0x7a, 0x47, 0x01, 0xd9, 0x75, 0x31, 0x11, 0x12, 0x7c, 
+    0x15, 0x7a, 0xb1, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x71, 0xb8, 0xa9, 0x21, 0xe5, 0x1f, 0xa9, 0xd4, 
     0xe4, 0xa9, 0x24, 0xe4, 0xfc, 0xc2, 0xc3, 0xa9, 0x21, 0xe2, 0x3b, 0xe5, 0xe5, 0x54, 0xc0, 0x78, 
-    0xb4, 0x12, 0x76, 0x6a, 0xda, 0x59, 0xda, 0x39, 0xda, 0x0b, 0x22, 0x80, 0x29, 0x80, 0x58, 0x75, 
-    0x2f, 0x16, 0x12, 0x7e, 0x30, 0x80, 0xed, 0x75, 0x2f, 0x12, 0x12, 0x7e, 0x30, 0x7a, 0xb1, 0x2f, 
-    0x12, 0x7e, 0x30, 0x9e, 0x44, 0x09, 0xcd, 0x9d, 0x54, 0x12, 0x73, 0xc8, 0x7e, 0x34, 0x05, 0xcd, 
-    0x7d, 0x54, 0x2d, 0x43, 0x80, 0xa1, 0xe5, 0xe5, 0x54, 0x03, 0x78, 0x12, 0x75, 0x2f, 0x13, 0x12, 
-    0x7e, 0x30, 0x7e, 0x0f, 0x29, 0xe9, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xe9, 0x80, 0xa7, 0x75, 0x2f, 
-    0x14, 0x12, 0x7e, 0x30, 0x7e, 0x0f, 0x29, 0xed, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xed, 0xa9, 0xd7, 
-    0xe4, 0xa9, 0x27, 0xe4, 0xfc, 0x80, 0x9d, 0x75, 0x2f, 0x15, 0x12, 0x7e, 0x30, 0x7e, 0x0f, 0x29, 
-    0xf1, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xf1, 0x80, 0xe5, 0x75, 0x2f, 0x18, 0x12, 0x7e, 0x30, 0xca, 
+    0xb4, 0x12, 0x74, 0x5a, 0xda, 0x59, 0xda, 0x39, 0xda, 0x0b, 0x22, 0x80, 0x29, 0x80, 0x58, 0x75, 
+    0x31, 0x16, 0x12, 0x7c, 0x15, 0x80, 0xed, 0x75, 0x31, 0x12, 0x12, 0x7c, 0x15, 0x7a, 0xb1, 0x31, 
+    0x12, 0x7c, 0x15, 0x9e, 0x44, 0x09, 0xe3, 0x9d, 0x54, 0x12, 0x71, 0xb8, 0x7e, 0x34, 0x05, 0xe3, 
+    0x7d, 0x54, 0x2d, 0x43, 0x80, 0xa1, 0xe5, 0xe5, 0x54, 0x03, 0x78, 0x12, 0x75, 0x31, 0x13, 0x12, 
+    0x7c, 0x15, 0x7e, 0x0f, 0x29, 0xff, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xff, 0x80, 0xa7, 0x75, 0x31, 
+    0x14, 0x12, 0x7c, 0x15, 0x7e, 0x0f, 0x2a, 0x03, 0x0b, 0x0c, 0x7a, 0x0f, 0x2a, 0x03, 0xa9, 0xd7, 
+    0xe4, 0xa9, 0x27, 0xe4, 0xfc, 0x80, 0x9d, 0x75, 0x31, 0x15, 0x12, 0x7c, 0x15, 0x7e, 0x0f, 0x2a, 
+    0x07, 0x0b, 0x0c, 0x7a, 0x0f, 0x2a, 0x07, 0x80, 0xe5, 0x75, 0x31, 0x18, 0x12, 0x7c, 0x15, 0xca, 
     0x09, 0xca, 0x39, 0xca, 0x2b, 0xc2, 0xc2, 0xa9, 0x21, 0xf2, 0x52, 0xe5, 0xf5, 0x33, 0x82, 0xe7, 
-    0x40, 0x44, 0x7e, 0x37, 0x01, 0xcb, 0x7e, 0x54, 0x00, 0x40, 0x9d, 0x35, 0x40, 0x43, 0x7a, 0x37, 
-    0x01, 0xcb, 0x7e, 0x37, 0x01, 0xc7, 0x7d, 0x43, 0x2d, 0x45, 0xbe, 0x44, 0x05, 0xcc, 0x38, 0x52, 
-    0x7a, 0x47, 0x01, 0xc7, 0x7d, 0x45, 0x12, 0x75, 0x26, 0xa9, 0x20, 0xf5, 0x22, 0x75, 0x2f, 0x19, 
-    0x12, 0x7e, 0x30, 0x7a, 0x91, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x81, 0xf7, 0x7a, 0x91, 0xf6, 0xe5, 
+    0x40, 0x44, 0x7e, 0x37, 0x01, 0xe1, 0x7e, 0x54, 0x00, 0x40, 0x9d, 0x35, 0x40, 0x43, 0x7a, 0x37, 
+    0x01, 0xe1, 0x7e, 0x37, 0x01, 0xdd, 0x7d, 0x43, 0x2d, 0x45, 0xbe, 0x44, 0x05, 0xe2, 0x38, 0x52, 
+    0x7a, 0x47, 0x01, 0xdd, 0x7d, 0x45, 0x12, 0x73, 0x16, 0xa9, 0x20, 0xf5, 0x22, 0x75, 0x31, 0x19, 
+    0x12, 0x7c, 0x15, 0x7a, 0x91, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x81, 0xf7, 0x7a, 0x91, 0xf6, 0xe5, 
     0xf5, 0x33, 0x82, 0xe7, 0x50, 0xbc, 0xda, 0x2b, 0xda, 0x39, 0xda, 0x09, 0x22, 0x80, 0x41, 0x80, 
-    0x64, 0x2d, 0x53, 0x6d, 0x33, 0x70, 0xb7, 0x7e, 0x04, 0x01, 0xcd, 0x7a, 0x07, 0x01, 0xc9, 0x7a, 
-    0x07, 0x01, 0xc7, 0xa9, 0x32, 0xf2, 0xdf, 0x85, 0x30, 0x2f, 0x12, 0x7e, 0x30, 0x75, 0xf6, 0x00, 
-    0x80, 0xd4, 0xca, 0x59, 0x9e, 0x44, 0x05, 0xcd, 0x9d, 0x54, 0x12, 0x75, 0x26, 0x7e, 0x34, 0x01, 
-    0xcd, 0x7d, 0x54, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xc7, 0x12, 0x75, 0x26, 0xda, 0x49, 0x80, 0x99, 
-    0xe5, 0xf5, 0x54, 0x03, 0x78, 0x1f, 0x7e, 0x0f, 0x29, 0xd9, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xd9, 
-    0x80, 0x9d, 0x7e, 0x0f, 0x29, 0xe1, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xe1, 0xa9, 0xd7, 0xf4, 0xa9, 
-    0x27, 0xf4, 0xfc, 0x80, 0x8a, 0x7e, 0x0f, 0x29, 0xdd, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xdd, 0x80, 
-    0xeb, 0xe5, 0xf5, 0x54, 0x03, 0x78, 0x1f, 0x7e, 0x2f, 0x29, 0xf9, 0x0b, 0x2c, 0x7a, 0x2f, 0x29, 
-    0xf9, 0x80, 0x34, 0x7e, 0x2f, 0x2a, 0x01, 0x0b, 0x2c, 0x7a, 0x2f, 0x2a, 0x01, 0xa9, 0xd7, 0xf4, 
-    0xa9, 0x27, 0xf4, 0xfc, 0x80, 0x21, 0x7e, 0x2f, 0x29, 0xfd, 0x0b, 0x2c, 0x7a, 0x2f, 0x29, 0xfd, 
-    0x80, 0xeb, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0x75, 0x2f, 0x28, 0x12, 0x7e, 0x30, 0xca, 
+    0x64, 0x2d, 0x53, 0x6d, 0x33, 0x70, 0xb7, 0x7e, 0x04, 0x01, 0xe3, 0x7a, 0x07, 0x01, 0xdf, 0x7a, 
+    0x07, 0x01, 0xdd, 0xa9, 0x32, 0xf2, 0xdf, 0x85, 0x30, 0x31, 0x12, 0x7c, 0x15, 0x75, 0xf6, 0x00, 
+    0x80, 0xd4, 0xca, 0x59, 0x9e, 0x44, 0x05, 0xe3, 0x9d, 0x54, 0x12, 0x73, 0x16, 0x7e, 0x34, 0x01, 
+    0xe3, 0x7d, 0x54, 0x2d, 0x43, 0x7a, 0x47, 0x01, 0xdd, 0x12, 0x73, 0x16, 0xda, 0x49, 0x80, 0x99, 
+    0xe5, 0xf5, 0x54, 0x03, 0x78, 0x1f, 0x7e, 0x0f, 0x29, 0xef, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xef, 
+    0x80, 0x9d, 0x7e, 0x0f, 0x29, 0xf7, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xf7, 0xa9, 0xd7, 0xf4, 0xa9, 
+    0x27, 0xf4, 0xfc, 0x80, 0x8a, 0x7e, 0x0f, 0x29, 0xf3, 0x0b, 0x0c, 0x7a, 0x0f, 0x29, 0xf3, 0x80, 
+    0xeb, 0xe5, 0xf5, 0x54, 0x03, 0x78, 0x1f, 0x7e, 0x2f, 0x2a, 0x0f, 0x0b, 0x2c, 0x7a, 0x2f, 0x2a, 
+    0x0f, 0x80, 0x34, 0x7e, 0x2f, 0x2a, 0x17, 0x0b, 0x2c, 0x7a, 0x2f, 0x2a, 0x17, 0xa9, 0xd7, 0xf4, 
+    0xa9, 0x27, 0xf4, 0xfc, 0x80, 0x21, 0x7e, 0x2f, 0x2a, 0x13, 0x0b, 0x2c, 0x7a, 0x2f, 0x2a, 0x13, 
+    0x80, 0xeb, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0x75, 0x31, 0x28, 0x12, 0x7c, 0x15, 0xca, 
     0x0b, 0xca, 0x1b, 0xca, 0x2b, 0xc2, 0xc4, 0xa9, 0x21, 0xf2, 0xb6, 0xe5, 0xf5, 0x33, 0x72, 0xe7, 
-    0x40, 0xe0, 0x7e, 0x0d, 0x30, 0x7e, 0x1d, 0x34, 0x7e, 0x2d, 0x38, 0x7e, 0x3d, 0x3c, 0x7e, 0x85, 
-    0x40, 0x7d, 0x90, 0x4d, 0x91, 0x4d, 0x92, 0x4d, 0x93, 0x4d, 0x94, 0x4d, 0x95, 0x4d, 0x96, 0x4d, 
+    0x40, 0xe0, 0x7e, 0x0d, 0x46, 0x7e, 0x1d, 0x4a, 0x7e, 0x2d, 0x4e, 0x7e, 0x3d, 0x52, 0x7e, 0x85, 
+    0x56, 0x7d, 0x90, 0x4d, 0x91, 0x4d, 0x92, 0x4d, 0x93, 0x4d, 0x94, 0x4d, 0x95, 0x4d, 0x96, 0x4d, 
     0x97, 0x4d, 0x98, 0x68, 0x72, 0x7a, 0x11, 0xf3, 0x7a, 0x01, 0xf3, 0x7a, 0x31, 0xf3, 0x7a, 0x21, 
     0xf3, 0x7a, 0x51, 0xf3, 0x7a, 0x41, 0xf3, 0x7a, 0x71, 0xf3, 0x7a, 0x61, 0xf3, 0x7a, 0x91, 0xf3, 
-    0x7a, 0x81, 0xf3, 0x30, 0x73, 0x1a, 0x7a, 0xb1, 0xf3, 0x7a, 0xa1, 0xf3, 0x7a, 0xd1, 0xf3, 0x7a, 
+    0x7a, 0x81, 0xf3, 0x30, 0x7b, 0x1a, 0x7a, 0xb1, 0xf3, 0x7a, 0xa1, 0xf3, 0x7a, 0xd1, 0xf3, 0x7a, 
     0xc1, 0xf3, 0x7a, 0xf1, 0xf3, 0x7a, 0xe1, 0xf3, 0x7d, 0x78, 0x7a, 0xf1, 0xf3, 0x7a, 0xe1, 0xf3, 
-    0xa9, 0x30, 0xf5, 0x03, 0x02, 0x72, 0xe6, 0x75, 0x2f, 0x29, 0x12, 0x7e, 0x30, 0x20, 0x73, 0x0b, 
-    0x75, 0x2f, 0x0a, 0x12, 0x7e, 0x30, 0x75, 0xf6, 0x0a, 0x80, 0x09, 0x75, 0x2f, 0x12, 0x12, 0x7e, 
-    0x30, 0x75, 0xf6, 0x12, 0x6d, 0x00, 0x7d, 0x10, 0x7a, 0x0d, 0x30, 0x7a, 0x0d, 0x34, 0x7a, 0x0d, 
-    0x38, 0x7a, 0x0d, 0x3c, 0x7a, 0x05, 0x40, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0x1e, 0xb0, 
-    0x40, 0x0c, 0x7e, 0xa0, 0x0a, 0xa4, 0x7e, 0x04, 0x75, 0x0b, 0x9d, 0x05, 0x89, 0x04, 0x7e, 0xa1, 
+    0xa9, 0x30, 0xf5, 0x03, 0x02, 0x70, 0xd6, 0x75, 0x31, 0x29, 0x12, 0x7c, 0x15, 0x20, 0x7b, 0x0b, 
+    0x75, 0x31, 0x0a, 0x12, 0x7c, 0x15, 0x75, 0xf6, 0x0a, 0x80, 0x09, 0x75, 0x31, 0x12, 0x12, 0x7c, 
+    0x15, 0x75, 0xf6, 0x12, 0x6d, 0x00, 0x7d, 0x10, 0x7a, 0x0d, 0x46, 0x7a, 0x0d, 0x4a, 0x7a, 0x0d, 
+    0x4e, 0x7a, 0x0d, 0x52, 0x7a, 0x05, 0x56, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0x1e, 0xb0, 
+    0x40, 0x0c, 0x7e, 0xa0, 0x0a, 0xa4, 0x7e, 0x04, 0x72, 0xfb, 0x9d, 0x05, 0x89, 0x04, 0x7e, 0xa1, 
     0xe3, 0x7a, 0x39, 0xa0, 0x0b, 0x34, 0x80, 0xea, 0xb4, 0x40, 0xe3, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 
     0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 
     0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 
@@ -937,7 +1044,7 @@ static unsigned char IMAGE_ARRAY_NAME[] = {
     0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 
     0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 
     0x35, 0x7e, 0xa1, 0xe3, 0xe5, 0xe3, 0x1b, 0x38, 0x50, 0x0b, 0x35, 0x22, 0x1e, 0xb0, 0x40, 0x0c, 
-    0x7e, 0xa0, 0x0a, 0xa4, 0x7e, 0x04, 0x76, 0x69, 0x9d, 0x05, 0x89, 0x04, 0x7e, 0x39, 0xa0, 0x7a, 
+    0x7e, 0xa0, 0x0a, 0xa4, 0x7e, 0x04, 0x74, 0x59, 0x9d, 0x05, 0x89, 0x04, 0x7e, 0x39, 0xa0, 0x7a, 
     0xa1, 0xf3, 0x0b, 0x34, 0x80, 0xea, 0xb4, 0x40, 0xe3, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 
     0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 
     0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 
@@ -958,144 +1065,144 @@ static unsigned char IMAGE_ARRAY_NAME[] = {
     0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 
     0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 
     0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x0b, 
-    0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x22, 0xc2, 0xaf, 0x7e, 0x37, 0x01, 0xc5, 
-    0x4d, 0x33, 0x68, 0x3b, 0x7e, 0x07, 0x01, 0xc1, 0x7e, 0x54, 0x09, 0xcd, 0x9d, 0x50, 0xbd, 0x35, 
-    0x40, 0x02, 0x7d, 0x35, 0xca, 0x39, 0x7e, 0x65, 0x4b, 0x99, 0x64, 0xda, 0x39, 0x7e, 0x07, 0x01, 
-    0xc5, 0x9d, 0x03, 0x7a, 0x07, 0x01, 0xc5, 0x2e, 0x37, 0x01, 0xc1, 0x7a, 0x37, 0x01, 0xc1, 0xbe, 
-    0x34, 0x09, 0xcc, 0x28, 0xc7, 0x7e, 0x34, 0x05, 0xcd, 0x7a, 0x37, 0x01, 0xc1, 0x80, 0xbd, 0xd2, 
-    0xaf, 0x22, 0x75, 0x2f, 0x53, 0x12, 0x7e, 0x30, 0x7e, 0x15, 0x4d, 0x80, 0x11, 0x75, 0x2f, 0x51, 
-    0x12, 0x7e, 0x30, 0x0b, 0x08, 0x10, 0x0b, 0x05, 0x9e, 0x34, 0x00, 0x02, 0x28, 0x4d, 0x7c, 0xb2, 
-    0x20, 0xe7, 0x27, 0x54, 0x07, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x6e, 0x8c, 0x7c, 0xb2, 0x54, 0x78, 
-    0x03, 0x03, 0x03, 0x7c, 0x2b, 0x9d, 0x13, 0x40, 0x1a, 0x68, 0x12, 0x7a, 0x15, 0x4d, 0x7a, 0x25, 
-    0x4f, 0x7e, 0x64, 0x77, 0x47, 0x7a, 0x65, 0x4b, 0x89, 0x24, 0x02, 0x77, 0x55, 0x7e, 0x64, 0x76, 
-    0xbd, 0x80, 0xf2, 0x2d, 0x13, 0x9d, 0x31, 0xca, 0x39, 0x7d, 0x31, 0x2d, 0x10, 0xca, 0x19, 0xca, 
-    0x29, 0x99, 0x24, 0xda, 0x29, 0xda, 0x09, 0xda, 0x39, 0x80, 0xa2, 0x7a, 0x15, 0x4d, 0x7e, 0x64, 
-    0x77, 0x33, 0x4d, 0x33, 0x78, 0x09, 0x7c, 0xb2, 0x20, 0xe7, 0x2a, 0x7e, 0x64, 0x76, 0xb2, 0x7a, 
-    0x65, 0x4b, 0x22, 0x75, 0x2f, 0x52, 0x12, 0x7e, 0x30, 0x7e, 0x21, 0x4d, 0x7e, 0x09, 0x30, 0x0b, 
-    0x04, 0x1b, 0x34, 0x78, 0x89, 0x80, 0xd4, 0x75, 0x2f, 0x54, 0x12, 0x7e, 0x30, 0x7e, 0x15, 0x4d, 
-    0x7e, 0x25, 0x4f, 0x80, 0x90, 0x5e, 0x20, 0x07, 0x54, 0x78, 0x7e, 0x44, 0x77, 0xd1, 0x30, 0xe6, 
-    0x16, 0x4d, 0x33, 0x68, 0x26, 0x1b, 0x34, 0x7e, 0x09, 0x40, 0x0b, 0x04, 0x7e, 0x44, 0x6a, 0x68, 
-    0x20, 0xe3, 0x04, 0x7e, 0x44, 0x77, 0xd9, 0xca, 0x09, 0xca, 0x39, 0x99, 0x44, 0xda, 0x39, 0xda, 
-    0x09, 0x7e, 0x64, 0x76, 0xbd, 0x4d, 0x33, 0x68, 0xa6, 0x89, 0x64, 0x7a, 0x15, 0x4d, 0xf5, 0x4f, 
-    0x7e, 0x64, 0x77, 0x96, 0x80, 0x99, 0x7e, 0x15, 0x4d, 0xe5, 0x4f, 0x80, 0xc4, 0xc0, 0xd0, 0xc0, 
-    0xd1, 0xc0, 0xe0, 0xca, 0x19, 0xa9, 0x20, 0xdf, 0x12, 0xa9, 0x21, 0xdf, 0x1b, 0x75, 0x2f, 0x01, 
-    0x12, 0x7e, 0x30, 0x53, 0xdf, 0xf7, 0x12, 0x40, 0xdc, 0x80, 0x0d, 0x75, 0x2f, 0xfe, 0x12, 0x7e, 
-    0x30, 0x7e, 0x14, 0x00, 0x53, 0x02, 0x40, 0x51, 0xda, 0x19, 0xd0, 0xe0, 0xd0, 0xd1, 0xd0, 0xd0, 
-    0x32, 0x03, 0xa5, 0xcb, 0x19, 0xb1, 0x80, 0x00, 0x22, 0x22, 0x02, 0x78, 0x52, 0xca, 0x0b, 0xca, 
+    0x38, 0x50, 0x7a, 0xa1, 0xf3, 0xf5, 0xf3, 0x0b, 0x35, 0x22, 0xc2, 0xaf, 0x7e, 0x37, 0x01, 0xdb, 
+    0x4d, 0x33, 0x68, 0x3b, 0x7e, 0x07, 0x01, 0xd7, 0x7e, 0x54, 0x09, 0xe3, 0x9d, 0x50, 0xbd, 0x35, 
+    0x40, 0x02, 0x7d, 0x35, 0xca, 0x39, 0x7e, 0x65, 0x61, 0x99, 0x64, 0xda, 0x39, 0x7e, 0x07, 0x01, 
+    0xdb, 0x9d, 0x03, 0x7a, 0x07, 0x01, 0xdb, 0x2e, 0x37, 0x01, 0xd7, 0x7a, 0x37, 0x01, 0xd7, 0xbe, 
+    0x34, 0x09, 0xe2, 0x28, 0xc7, 0x7e, 0x34, 0x05, 0xe3, 0x7a, 0x37, 0x01, 0xd7, 0x80, 0xbd, 0xd2, 
+    0xaf, 0x22, 0x75, 0x31, 0x53, 0x12, 0x7c, 0x15, 0x7e, 0x15, 0x63, 0x80, 0x11, 0x75, 0x31, 0x51, 
+    0x12, 0x7c, 0x15, 0x0b, 0x08, 0x10, 0x0b, 0x05, 0x9e, 0x34, 0x00, 0x02, 0x28, 0x4d, 0x7c, 0xb2, 
+    0x20, 0xe7, 0x27, 0x54, 0x07, 0x23, 0x0a, 0x2b, 0x49, 0x22, 0x6c, 0x7c, 0x7c, 0xb2, 0x54, 0x78, 
+    0x03, 0x03, 0x03, 0x7c, 0x2b, 0x9d, 0x13, 0x40, 0x1a, 0x68, 0x12, 0x7a, 0x15, 0x63, 0x7a, 0x25, 
+    0x65, 0x7e, 0x64, 0x75, 0x37, 0x7a, 0x65, 0x61, 0x89, 0x24, 0x02, 0x75, 0x45, 0x7e, 0x64, 0x74, 
+    0xad, 0x80, 0xf2, 0x2d, 0x13, 0x9d, 0x31, 0xca, 0x39, 0x7d, 0x31, 0x2d, 0x10, 0xca, 0x19, 0xca, 
+    0x29, 0x99, 0x24, 0xda, 0x29, 0xda, 0x09, 0xda, 0x39, 0x80, 0xa2, 0x7a, 0x15, 0x63, 0x7e, 0x64, 
+    0x75, 0x23, 0x4d, 0x33, 0x78, 0x09, 0x7c, 0xb2, 0x20, 0xe7, 0x2a, 0x7e, 0x64, 0x74, 0xa2, 0x7a, 
+    0x65, 0x61, 0x22, 0x75, 0x31, 0x52, 0x12, 0x7c, 0x15, 0x7e, 0x21, 0x63, 0x7e, 0x09, 0x30, 0x0b, 
+    0x04, 0x1b, 0x34, 0x78, 0x89, 0x80, 0xd4, 0x75, 0x31, 0x54, 0x12, 0x7c, 0x15, 0x7e, 0x15, 0x63, 
+    0x7e, 0x25, 0x65, 0x80, 0x90, 0x5e, 0x20, 0x07, 0x54, 0x78, 0x7e, 0x44, 0x75, 0xc1, 0x30, 0xe6, 
+    0x16, 0x4d, 0x33, 0x68, 0x26, 0x1b, 0x34, 0x7e, 0x09, 0x40, 0x0b, 0x04, 0x7e, 0x44, 0x67, 0x63, 
+    0x20, 0xe3, 0x04, 0x7e, 0x44, 0x75, 0xc9, 0xca, 0x09, 0xca, 0x39, 0x99, 0x44, 0xda, 0x39, 0xda, 
+    0x09, 0x7e, 0x64, 0x74, 0xad, 0x4d, 0x33, 0x68, 0xa6, 0x89, 0x64, 0x7a, 0x15, 0x63, 0xf5, 0x65, 
+    0x7e, 0x64, 0x75, 0x86, 0x80, 0x99, 0x7e, 0x15, 0x63, 0xe5, 0x65, 0x80, 0xc4, 0xc0, 0xd0, 0xc0, 
+    0xd1, 0xc0, 0xe0, 0xca, 0x19, 0xa9, 0x20, 0xdf, 0x12, 0xa9, 0x21, 0xdf, 0x1b, 0x75, 0x31, 0x01, 
+    0x12, 0x7c, 0x15, 0x53, 0xdf, 0xf7, 0x12, 0x40, 0xdc, 0x80, 0x0d, 0x75, 0x31, 0xfe, 0x12, 0x7c, 
+    0x15, 0x7e, 0x14, 0x00, 0x53, 0x02, 0x40, 0x51, 0xda, 0x19, 0xd0, 0xe0, 0xd0, 0xd1, 0xd0, 0xd0, 
+    0x32, 0x03, 0xa5, 0xcb, 0x19, 0xb1, 0x80, 0x00, 0x22, 0x22, 0x02, 0x76, 0x42, 0xca, 0x0b, 0xca, 
     0x1b, 0xca, 0x2b, 0xca, 0x3b, 0xca, 0x4b, 0xca, 0x5b, 0xca, 0x6b, 0xca, 0x7b, 0xca, 0xeb, 0xc0, 
-    0xf1, 0x7e, 0xb3, 0x2a, 0x1d, 0xb4, 0x00, 0x02, 0x80, 0x19, 0xb4, 0x01, 0x16, 0x30, 0xc0, 0x08, 
-    0x75, 0xf1, 0x00, 0x12, 0x78, 0x3c, 0x80, 0x1f, 0x30, 0xc1, 0x1c, 0x75, 0xf1, 0x00, 0x12, 0x78, 
-    0xcd, 0x80, 0x14, 0x30, 0xc1, 0x08, 0x75, 0xf1, 0x00, 0x12, 0x78, 0xcd, 0x80, 0x09, 0x30, 0xc0, 
-    0x06, 0x75, 0xf1, 0x00, 0x12, 0x78, 0x3c, 0xd0, 0xf1, 0xda, 0xeb, 0xda, 0x7b, 0xda, 0x6b, 0xda, 
+    0xf1, 0x7e, 0xb3, 0x2a, 0x33, 0xb4, 0x00, 0x02, 0x80, 0x19, 0xb4, 0x01, 0x16, 0x30, 0xc0, 0x08, 
+    0x75, 0xf1, 0x00, 0x12, 0x76, 0x2c, 0x80, 0x1f, 0x30, 0xc1, 0x1c, 0x75, 0xf1, 0x00, 0x12, 0x76, 
+    0xbd, 0x80, 0x14, 0x30, 0xc1, 0x08, 0x75, 0xf1, 0x00, 0x12, 0x76, 0xbd, 0x80, 0x09, 0x30, 0xc0, 
+    0x06, 0x75, 0xf1, 0x00, 0x12, 0x76, 0x2c, 0xd0, 0xf1, 0xda, 0xeb, 0xda, 0x7b, 0xda, 0x6b, 0xda, 
     0x5b, 0xda, 0x4b, 0xda, 0x3b, 0xda, 0x2b, 0xda, 0x1b, 0xda, 0x0b, 0x22, 0xc2, 0xc0, 0x7e, 0xb3, 
-    0x2a, 0x1d, 0xb4, 0x02, 0x07, 0x12, 0x78, 0x5e, 0x02, 0x78, 0x52, 0x22, 0xb4, 0x01, 0xfc, 0x02, 
-    0x78, 0x98, 0x7e, 0x00, 0x00, 0x7a, 0x03, 0x2a, 0x1d, 0x7a, 0x03, 0x2a, 0x1e, 0x22, 0x7e, 0xb3, 
-    0x2a, 0x15, 0x54, 0x60, 0x60, 0x05, 0xb4, 0x40, 0x15, 0x80, 0x13, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 
-    0x05, 0x0c, 0x75, 0x2f, 0x71, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0xf5, 0x8f, 0x22, 0x75, 
-    0xf6, 0x00, 0x22, 0xbe, 0x57, 0x2a, 0x1b, 0x28, 0x04, 0x7e, 0x57, 0x2a, 0x1b, 0x7a, 0x0f, 0x2a, 
-    0x20, 0x7a, 0x57, 0x2a, 0x24, 0x02, 0x78, 0x98, 0x7e, 0xef, 0x2a, 0x20, 0x7e, 0xf7, 0x2a, 0x24, 
-    0x7e, 0x07, 0x2a, 0x24, 0x4d, 0x00, 0x68, 0x21, 0x7e, 0x00, 0x00, 0x7e, 0xeb, 0xb0, 0xf5, 0xf3, 
-    0xa3, 0xa5, 0x08, 0x1b, 0xf4, 0x68, 0x04, 0xa5, 0xb8, 0x08, 0xf0, 0x7a, 0xef, 0x2a, 0x20, 0x7a, 
-    0xf7, 0x2a, 0x24, 0x75, 0x2f, 0x06, 0x12, 0x7e, 0x30, 0x7a, 0x01, 0xf6, 0x22, 0xc2, 0xc1, 0x75, 
-    0x2f, 0x03, 0x12, 0x7e, 0x30, 0xa9, 0x36, 0xe2, 0x16, 0xe5, 0xf5, 0x54, 0xc0, 0x68, 0x07, 0xa9, 
-    0xd7, 0xf4, 0xa9, 0x27, 0xf4, 0xfc, 0x53, 0xe1, 0x3f, 0x43, 0xf2, 0x88, 0x02, 0x79, 0x44, 0x7e, 
-    0xb3, 0x2a, 0x1e, 0xb4, 0x02, 0x0f, 0xa9, 0xd4, 0xe4, 0x7e, 0xb0, 0x00, 0x7a, 0xb3, 0x2a, 0x1e, 
-    0x7a, 0xb3, 0x2a, 0x1d, 0x22, 0xb4, 0x01, 0x39, 0x7e, 0x21, 0xe6, 0x7c, 0x32, 0x7e, 0x13, 0x2a, 
-    0x1f, 0x2c, 0x21, 0x7a, 0x23, 0x2a, 0x1f, 0x7e, 0x00, 0x00, 0x2e, 0x04, 0x2a, 0x26, 0xe5, 0xe3, 
-    0x7a, 0x09, 0xb0, 0x0b, 0x04, 0xa5, 0xdb, 0xf6, 0xa9, 0xd4, 0xe4, 0x75, 0x2f, 0x70, 0x12, 0x7e, 
-    0x30, 0x7e, 0xb3, 0x2a, 0x1f, 0x7e, 0xa3, 0x2a, 0x1c, 0xbc, 0xab, 0x78, 0x03, 0x12, 0x79, 0xdb, 
-    0x22, 0x02, 0x7d, 0x44, 0xe5, 0xe6, 0xb4, 0x08, 0x65, 0xa9, 0xc4, 0xe2, 0x7e, 0x01, 0xe3, 0x7e, 
-    0x11, 0xe3, 0x7e, 0x31, 0xe3, 0x7e, 0x21, 0xe3, 0x7e, 0x51, 0xe3, 0x7e, 0x41, 0xe3, 0x7e, 0x71, 
-    0xe3, 0x7e, 0x61, 0xe3, 0x7a, 0x0f, 0x2a, 0x15, 0x7a, 0x1f, 0x2a, 0x19, 0x75, 0x2f, 0x04, 0x12, 
-    0x7e, 0x30, 0x7a, 0x01, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x11, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x21, 
-    0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x31, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x41, 0x2f, 0x12, 0x7e, 0x30, 
-    0x7a, 0x51, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x61, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x71, 0x2f, 0x12, 
-    0x7e, 0x30, 0xa9, 0xd4, 0xe4, 0xa9, 0xd7, 0xf4, 0xa9, 0xc6, 0xe2, 0x12, 0x79, 0xaf, 0x22, 0x6d, 
-    0x00, 0x7e, 0x14, 0x01, 0x02, 0x7a, 0x07, 0x2a, 0x24, 0x7a, 0x03, 0x2a, 0x1f, 0x7e, 0xb3, 0x2a, 
-    0x15, 0x20, 0xe7, 0x0f, 0x7a, 0x23, 0x2a, 0x1e, 0x7a, 0x33, 0x2a, 0x1d, 0xbe, 0x07, 0x2a, 0x1b, 
-    0x68, 0x09, 0x22, 0x7a, 0x33, 0x2a, 0x1e, 0x7a, 0x23, 0x2a, 0x1d, 0x7e, 0xb3, 0x2a, 0x15, 0x54, 
-    0xe3, 0x23, 0x23, 0x30, 0xe0, 0x02, 0xd2, 0xe5, 0x30, 0xe7, 0x02, 0xd2, 0xe4, 0x30, 0xe5, 0x06, 
-    0x30, 0xe4, 0x03, 0x02, 0x7d, 0x44, 0x54, 0x3e, 0xf5, 0xf0, 0x03, 0x54, 0x1f, 0xc3, 0x25, 0xf0, 
-    0x90, 0x7a, 0x07, 0x75, 0x84, 0xff, 0x73, 0x02, 0x7b, 0x5b, 0x02, 0x7a, 0x4f, 0x02, 0x7b, 0xf8, 
-    0x02, 0x7c, 0x13, 0x02, 0x7a, 0xf4, 0x02, 0x7a, 0xb5, 0x02, 0x7c, 0x2c, 0x02, 0x7c, 0x2c, 0x02, 
-    0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 
-    0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x2f, 0x02, 0x7c, 0x35, 0x02, 0x7c, 0xe9, 0x02, 0x7c, 0x32, 
-    0x02, 0x7c, 0x32, 0x02, 0x7c, 0x32, 0x02, 0x7c, 0x32, 0x02, 0x7c, 0x32, 0x02, 0x7c, 0x32, 0x7e, 
-    0xb3, 0x2a, 0x16, 0xb4, 0x06, 0x2a, 0x7e, 0xb3, 0x2a, 0x17, 0x60, 0x56, 0x7c, 0x0b, 0x7e, 0x13, 
-    0x2a, 0x18, 0x7e, 0x17, 0x2a, 0x19, 0x75, 0x2f, 0x72, 0x12, 0x7e, 0x30, 0x7a, 0x01, 0x2f, 0x12, 
-    0x7e, 0x30, 0x7a, 0x11, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x7d, 0x4e, 0x40, 0x35, 0x02, 0x78, 0x83, 
-    0xb4, 0x08, 0x10, 0x75, 0x2f, 0x74, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x3f, 0xf1, 0xf5, 0xf3, 0x75, 
-    0xf6, 0x01, 0x22, 0xb4, 0x00, 0x1c, 0x75, 0x2f, 0x75, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x3f, 0xf2, 
-    0x30, 0xe0, 0x05, 0x75, 0xf3, 0x02, 0x80, 0x03, 0x75, 0xf3, 0x00, 0x75, 0xf3, 0x00, 0x75, 0xf6, 
-    0x02, 0x22, 0x02, 0x7d, 0x44, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x00, 0x35, 0x75, 0x2f, 0x76, 0x12, 
-    0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x1a, 0x54, 0x0f, 0xf5, 0xf1, 0x7e, 0xb3, 0x2a, 0x1a, 0x20, 0xe7, 
-    0x09, 0xe5, 0xe1, 0x30, 0xe7, 0x0d, 0x74, 0x01, 0x80, 0x0b, 0xe5, 0xe1, 0x30, 0xe6, 0x04, 0x74, 
-    0x01, 0x80, 0x02, 0x74, 0x00, 0x53, 0xf1, 0x80, 0xf5, 0xf3, 0x75, 0xf3, 0x00, 0x75, 0xf6, 0x02, 
-    0x22, 0x02, 0x7d, 0x44, 0xc0, 0xf1, 0x7e, 0xb3, 0x2a, 0x1a, 0x54, 0x0f, 0x42, 0xf1, 0x7e, 0xb3, 
-    0x2a, 0x18, 0xb4, 0x00, 0x45, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x01, 0x24, 0x75, 0x2f, 0x77, 0x12, 
-    0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x1a, 0x54, 0x0f, 0x78, 0x05, 0x53, 0xe1, 0x3f, 0x80, 0x37, 0x7e, 
-    0xb3, 0x2a, 0x1a, 0x20, 0xe7, 0x05, 0x53, 0xe1, 0x7f, 0x80, 0x2b, 0x53, 0xe1, 0xbf, 0x80, 0x26, 
-    0xb4, 0x03, 0x17, 0x75, 0x2f, 0x78, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x1a, 0x20, 0xe7, 0x05, 
-    0x43, 0xe1, 0x80, 0x80, 0x11, 0x43, 0xe1, 0x40, 0x80, 0x0c, 0x43, 0xe1, 0xc0, 0xd0, 0xf1, 0x75, 
-    0x2f, 0x07, 0x12, 0x7e, 0x30, 0x22, 0xd0, 0xf1, 0x02, 0x78, 0x7f, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 
-    0x09, 0x23, 0x75, 0x2f, 0x79, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0xbe, 0xb3, 0x3f, 0xf1, 
-    0x68, 0x11, 0xca, 0xb8, 0xc0, 0xf1, 0x12, 0x43, 0x68, 0xd0, 0xf1, 0xda, 0xb8, 0x50, 0x76, 0x7a, 
-    0xb3, 0x3f, 0xf1, 0x80, 0x6d, 0xb4, 0x05, 0x08, 0x75, 0x2f, 0x7a, 0x12, 0x7e, 0x30, 0x80, 0x62, 
-    0xb4, 0x03, 0x19, 0x75, 0x2f, 0x7b, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0xb4, 0x01, 0x55, 
-    0x7e, 0xb3, 0x3f, 0xf2, 0x44, 0x01, 0x7a, 0xb3, 0x3f, 0xf2, 0x80, 0x46, 0xb4, 0x01, 0x19, 0x75, 
-    0x2f, 0x7c, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0xb4, 0x01, 0x39, 0x7e, 0xb3, 0x3f, 0xf2, 
-    0x54, 0xfe, 0x7a, 0xb3, 0x3f, 0xf2, 0x80, 0x2a, 0xb4, 0x07, 0x2a, 0x7e, 0xb3, 0x2a, 0x17, 0x60, 
-    0x24, 0x7c, 0x0b, 0x7e, 0x13, 0x2a, 0x18, 0x7e, 0x17, 0x2a, 0x19, 0x75, 0x2f, 0x73, 0x12, 0x7e, 
-    0x30, 0x7a, 0x01, 0x2f, 0x12, 0x7e, 0x30, 0x7a, 0x11, 0x2f, 0x12, 0x7e, 0x30, 0x12, 0x7d, 0x7a, 
-    0x40, 0x03, 0x02, 0x78, 0x7f, 0x02, 0x7d, 0x44, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x0b, 0xf6, 0x75, 
-    0x2f, 0x7d, 0x12, 0x7e, 0x30, 0x7e, 0xb3, 0x2a, 0x18, 0x7e, 0xa3, 0x2a, 0x1a, 0x4c, 0xab, 0x78, 
-    0xe4, 0x80, 0xdf, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x0a, 0xdb, 0x75, 0x2f, 0x7e, 0x12, 0x7e, 0x30, 
-    0x7e, 0xb3, 0x2a, 0x18, 0x70, 0xcf, 0xf5, 0xf3, 0x75, 0xf6, 0x01, 0x22, 0x02, 0x7d, 0x44, 0x02, 
-    0x7d, 0x44, 0x02, 0x7d, 0x44, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x04, 0x20, 0x75, 0x2f, 0xc3, 0x12, 
-    0x7e, 0x30, 0x7e, 0x04, 0x00, 0x01, 0x7e, 0x17, 0x2a, 0x17, 0x7e, 0x18, 0x2a, 0x26, 0x7a, 0x1c, 
-    0x00, 0x00, 0x7e, 0x47, 0x2a, 0x1b, 0x12, 0x7e, 0x3c, 0x02, 0x7c, 0xe3, 0xb4, 0x06, 0x3a, 0x75, 
-    0x2f, 0xc1, 0x12, 0x7e, 0x30, 0x7e, 0x58, 0x00, 0x00, 0x7a, 0x5c, 0x00, 0xfe, 0x7d, 0xca, 0x7e, 
-    0xd7, 0x2a, 0x17, 0x7e, 0x78, 0x2a, 0x26, 0x7a, 0x7c, 0x00, 0x00, 0x7e, 0x77, 0x2a, 0x1b, 0x75, 
-    0x2f, 0xc1, 0x12, 0x7e, 0x30, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x7e, 
-    0x75, 0xd0, 0x87, 0xd0, 0xa8, 0x40, 0x4f, 0x80, 0x4a, 0xb4, 0x00, 0x1c, 0xc2, 0xaf, 0xa9, 0xd5, 
-    0x87, 0x12, 0x78, 0x7f, 0xe4, 0x8d, 0xef, 0x8d, 0xef, 0x8d, 0xef, 0xd5, 0xe0, 0xf7, 0xc0, 0xd1, 
-    0xca, 0x02, 0xff, 0xca, 0x06, 0x00, 0x00, 0x32, 0xb4, 0x09, 0x12, 0x7e, 0x57, 0x2a, 0x17, 0x4d, 
-    0x55, 0x68, 0x05, 0xa9, 0xd2, 0xb1, 0x80, 0x03, 0xa9, 0xc2, 0xb1, 0x80, 0x16, 0xb4, 0x07, 0x16, 
-    0xc2, 0xaf, 0x7e, 0x07, 0x2a, 0x19, 0x7e, 0x17, 0x2a, 0x17, 0xc0, 0xd1, 0xca, 0x18, 0xca, 0x38, 
-    0xca, 0x28, 0x32, 0x02, 0x78, 0x7f, 0x02, 0x7d, 0x44, 0x7e, 0xb3, 0x2a, 0x16, 0xb4, 0x03, 0x15, 
-    0x75, 0x2f, 0xc2, 0x12, 0x7e, 0x30, 0x7e, 0x04, 0x00, 0x01, 0x7e, 0x17, 0x2a, 0x17, 0x7e, 0x57, 
-    0x2a, 0x1b, 0x02, 0x78, 0x83, 0xb4, 0x05, 0x39, 0x75, 0x2f, 0xc0, 0x12, 0x7e, 0x30, 0xc0, 0xa8, 
-    0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x7e, 0x08, 0x2a, 0x26, 0x7a, 0x0c, 0x00, 0x00, 0x7e, 
-    0x24, 0x00, 0xfe, 0x7e, 0x37, 0x2a, 0x17, 0x7e, 0x47, 0x2a, 0x1b, 0x12, 0x7e, 0x3c, 0xd0, 0x87, 
-    0xd0, 0xa8, 0x7e, 0x08, 0x2a, 0x26, 0x7a, 0x0c, 0x00, 0x00, 0x7e, 0x57, 0x2a, 0x1b, 0x02, 0x78, 
-    0x83, 0x02, 0x7d, 0x44, 0x75, 0x2f, 0x07, 0x12, 0x7e, 0x30, 0x43, 0xe1, 0xc0, 0x22, 0xc0, 0xa8, 
-    0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x7d, 0xb9, 0x40, 0x19, 0x7e, 0x08, 0x2a, 0x26, 
-    0x7a, 0x0c, 0x00, 0x00, 0xca, 0x0b, 0xca, 0x49, 0x12, 0x7e, 0x3c, 0xda, 0x59, 0xda, 0x0b, 0xd0, 
-    0x87, 0xd0, 0xa8, 0xc3, 0x22, 0xd0, 0x87, 0xd0, 0xa8, 0x22, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 
-    0xa9, 0xd5, 0x87, 0x12, 0x7d, 0xb9, 0x40, 0x2b, 0x7e, 0x58, 0x00, 0x00, 0x7a, 0x5c, 0x00, 0xfe, 
-    0x7f, 0x61, 0x7e, 0x78, 0x2a, 0x26, 0x7a, 0x7c, 0x00, 0x00, 0x7e, 0x77, 0x2a, 0x1b, 0xbd, 0x74, 
-    0x78, 0x11, 0x75, 0x2f, 0xc1, 0x12, 0x7e, 0x30, 0x12, 0x7e, 0x75, 0x40, 0x06, 0xd0, 0x87, 0xd0, 
-    0xa8, 0xc3, 0x22, 0xd0, 0x87, 0xd0, 0xa8, 0xd3, 0x22, 0x7e, 0x24, 0x00, 0xfe, 0x7e, 0x34, 0x7f, 
-    0xca, 0x0b, 0x1a, 0x50, 0xc5, 0xf0, 0x7d, 0x62, 0x7d, 0x75, 0x7d, 0x87, 0x7e, 0x34, 0x7f, 0xc2, 
-    0x7e, 0x1b, 0xb0, 0x7e, 0x34, 0x7f, 0x03, 0xb4, 0x01, 0x04, 0x7e, 0x34, 0x7f, 0xcc, 0x7e, 0x1b, 
-    0xb0, 0xbc, 0x0b, 0x50, 0x49, 0x3e, 0x00, 0x3e, 0x00, 0x0a, 0x50, 0x2d, 0x75, 0x0b, 0x3a, 0x30, 
-    0x69, 0x53, 0x00, 0x02, 0xbd, 0x38, 0x50, 0x02, 0x2d, 0x38, 0xbc, 0x1b, 0x50, 0x30, 0x3e, 0x10, 
-    0x3e, 0x10, 0x0a, 0x51, 0x2d, 0x35, 0x69, 0x41, 0x00, 0x02, 0x0b, 0x1a, 0x30, 0xbd, 0x38, 0x50, 
-    0x02, 0x2d, 0x38, 0xbe, 0x44, 0xff, 0xff, 0x78, 0x05, 0x7e, 0x1b, 0x90, 0x0a, 0x49, 0x4d, 0x44, 
-    0x68, 0x0c, 0xbe, 0x44, 0x00, 0xff, 0x28, 0x04, 0x7e, 0x44, 0x00, 0xff, 0xc3, 0x22, 0xd3, 0x22, 
+    0x2a, 0x33, 0xb4, 0x02, 0x07, 0x12, 0x76, 0x4e, 0x02, 0x76, 0x42, 0x22, 0xb4, 0x01, 0xfc, 0x02, 
+    0x76, 0x88, 0x7e, 0x00, 0x00, 0x7a, 0x03, 0x2a, 0x33, 0x7a, 0x03, 0x2a, 0x34, 0x22, 0x7e, 0xb3, 
+    0x2a, 0x2b, 0x54, 0x60, 0x60, 0x05, 0xb4, 0x40, 0x15, 0x80, 0x13, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 
+    0x05, 0x0c, 0x75, 0x31, 0x71, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x2e, 0xf5, 0x8f, 0x22, 0x75, 
+    0xf6, 0x00, 0x22, 0xbe, 0x57, 0x2a, 0x31, 0x28, 0x04, 0x7e, 0x57, 0x2a, 0x31, 0x7a, 0x0f, 0x2a, 
+    0x36, 0x7a, 0x57, 0x2a, 0x3a, 0x02, 0x76, 0x88, 0x7e, 0xef, 0x2a, 0x36, 0x7e, 0xf7, 0x2a, 0x3a, 
+    0x7e, 0x07, 0x2a, 0x3a, 0x4d, 0x00, 0x68, 0x21, 0x7e, 0x00, 0x00, 0x7e, 0xeb, 0xb0, 0xf5, 0xf3, 
+    0xa3, 0xa5, 0x08, 0x1b, 0xf4, 0x68, 0x04, 0xa5, 0xb8, 0x08, 0xf0, 0x7a, 0xef, 0x2a, 0x36, 0x7a, 
+    0xf7, 0x2a, 0x3a, 0x75, 0x31, 0x06, 0x12, 0x7c, 0x15, 0x7a, 0x01, 0xf6, 0x22, 0xc2, 0xc1, 0x75, 
+    0x31, 0x03, 0x12, 0x7c, 0x15, 0xa9, 0x36, 0xe2, 0x16, 0xe5, 0xf5, 0x54, 0xc0, 0x68, 0x07, 0xa9, 
+    0xd7, 0xf4, 0xa9, 0x27, 0xf4, 0xfc, 0x53, 0xe1, 0x3f, 0x43, 0xf2, 0x88, 0x02, 0x77, 0x29, 0x7e, 
+    0xb3, 0x2a, 0x34, 0xb4, 0x02, 0x04, 0xa9, 0xd4, 0xe4, 0x22, 0xb4, 0x01, 0x39, 0x7e, 0x21, 0xe6, 
+    0x7c, 0x32, 0x7e, 0x13, 0x2a, 0x35, 0x2c, 0x21, 0x7a, 0x23, 0x2a, 0x35, 0x7e, 0x00, 0x00, 0x2e, 
+    0x04, 0x2a, 0x3c, 0xe5, 0xe3, 0x7a, 0x09, 0xb0, 0x0b, 0x04, 0xa5, 0xdb, 0xf6, 0xa9, 0xd4, 0xe4, 
+    0x75, 0x31, 0x70, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x35, 0x7e, 0xa3, 0x2a, 0x32, 0xbc, 0xab, 
+    0x78, 0x03, 0x12, 0x77, 0xc0, 0x22, 0x02, 0x7b, 0x29, 0xe5, 0xe6, 0xb4, 0x08, 0x65, 0xa9, 0xc4, 
+    0xe2, 0x7e, 0x01, 0xe3, 0x7e, 0x11, 0xe3, 0x7e, 0x31, 0xe3, 0x7e, 0x21, 0xe3, 0x7e, 0x51, 0xe3, 
+    0x7e, 0x41, 0xe3, 0x7e, 0x71, 0xe3, 0x7e, 0x61, 0xe3, 0x7a, 0x0f, 0x2a, 0x2b, 0x7a, 0x1f, 0x2a, 
+    0x2f, 0x75, 0x31, 0x04, 0x12, 0x7c, 0x15, 0x7a, 0x01, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x11, 0x31, 
+    0x12, 0x7c, 0x15, 0x7a, 0x21, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x31, 0x31, 0x12, 0x7c, 0x15, 0x7a, 
+    0x41, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x51, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x61, 0x31, 0x12, 0x7c, 
+    0x15, 0x7a, 0x71, 0x31, 0x12, 0x7c, 0x15, 0xa9, 0xd4, 0xe4, 0xa9, 0xd7, 0xf4, 0xa9, 0xc6, 0xe2, 
+    0x12, 0x77, 0x94, 0x22, 0x6d, 0x00, 0x7e, 0x14, 0x01, 0x02, 0x7a, 0x07, 0x2a, 0x3a, 0x7a, 0x03, 
+    0x2a, 0x35, 0x7e, 0xb3, 0x2a, 0x2b, 0x20, 0xe7, 0x0f, 0x7a, 0x23, 0x2a, 0x34, 0x7a, 0x33, 0x2a, 
+    0x33, 0xbe, 0x07, 0x2a, 0x31, 0x68, 0x09, 0x22, 0x7a, 0x33, 0x2a, 0x34, 0x7a, 0x23, 0x2a, 0x33, 
+    0x7e, 0xb3, 0x2a, 0x2b, 0x54, 0xe3, 0x23, 0x23, 0x30, 0xe0, 0x02, 0xd2, 0xe5, 0x30, 0xe7, 0x02, 
+    0xd2, 0xe4, 0x30, 0xe5, 0x06, 0x30, 0xe4, 0x03, 0x02, 0x7b, 0x29, 0x54, 0x3e, 0xf5, 0xf0, 0x03, 
+    0x54, 0x1f, 0xc3, 0x25, 0xf0, 0x90, 0x77, 0xec, 0x75, 0x84, 0xff, 0x73, 0x02, 0x79, 0x40, 0x02, 
+    0x78, 0x34, 0x02, 0x79, 0xdd, 0x02, 0x79, 0xf8, 0x02, 0x78, 0xd9, 0x02, 0x78, 0x9a, 0x02, 0x7a, 
+    0x11, 0x02, 0x7a, 0x11, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, 
+    0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x14, 0x02, 0x7a, 0x1a, 0x02, 
+    0x7a, 0xce, 0x02, 0x7a, 0x17, 0x02, 0x7a, 0x17, 0x02, 0x7a, 0x17, 0x02, 0x7a, 0x17, 0x02, 0x7a, 
+    0x17, 0x02, 0x7a, 0x17, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x06, 0x2a, 0x7e, 0xb3, 0x2a, 0x2d, 0x60, 
+    0x56, 0x7c, 0x0b, 0x7e, 0x13, 0x2a, 0x2e, 0x7e, 0x17, 0x2a, 0x2f, 0x75, 0x31, 0x72, 0x12, 0x7c, 
+    0x15, 0x7a, 0x01, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x11, 0x31, 0x12, 0x7c, 0x15, 0x12, 0x7b, 0x33, 
+    0x40, 0x35, 0x02, 0x76, 0x73, 0xb4, 0x08, 0x10, 0x75, 0x31, 0x74, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 
+    0x3f, 0xf1, 0xf5, 0xf3, 0x75, 0xf6, 0x01, 0x22, 0xb4, 0x00, 0x1c, 0x75, 0x31, 0x75, 0x12, 0x7c, 
+    0x15, 0x7e, 0xb3, 0x3f, 0xf2, 0x30, 0xe0, 0x05, 0x75, 0xf3, 0x02, 0x80, 0x03, 0x75, 0xf3, 0x00, 
+    0x75, 0xf3, 0x00, 0x75, 0xf6, 0x02, 0x22, 0x02, 0x7b, 0x29, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x00, 
+    0x35, 0x75, 0x31, 0x76, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x30, 0x54, 0x0f, 0xf5, 0xf1, 0x7e, 
+    0xb3, 0x2a, 0x30, 0x20, 0xe7, 0x09, 0xe5, 0xe1, 0x30, 0xe7, 0x0d, 0x74, 0x01, 0x80, 0x0b, 0xe5, 
+    0xe1, 0x30, 0xe6, 0x04, 0x74, 0x01, 0x80, 0x02, 0x74, 0x00, 0x53, 0xf1, 0x80, 0xf5, 0xf3, 0x75, 
+    0xf3, 0x00, 0x75, 0xf6, 0x02, 0x22, 0x02, 0x7b, 0x29, 0xc0, 0xf1, 0x7e, 0xb3, 0x2a, 0x30, 0x54, 
+    0x0f, 0x42, 0xf1, 0x7e, 0xb3, 0x2a, 0x2e, 0xb4, 0x00, 0x45, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x01, 
+    0x24, 0x75, 0x31, 0x77, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x30, 0x54, 0x0f, 0x78, 0x05, 0x53, 
+    0xe1, 0x3f, 0x80, 0x37, 0x7e, 0xb3, 0x2a, 0x30, 0x20, 0xe7, 0x05, 0x53, 0xe1, 0x7f, 0x80, 0x2b, 
+    0x53, 0xe1, 0xbf, 0x80, 0x26, 0xb4, 0x03, 0x17, 0x75, 0x31, 0x78, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 
+    0x2a, 0x30, 0x20, 0xe7, 0x05, 0x43, 0xe1, 0x80, 0x80, 0x11, 0x43, 0xe1, 0x40, 0x80, 0x0c, 0x43, 
+    0xe1, 0xc0, 0xd0, 0xf1, 0x75, 0x31, 0x07, 0x12, 0x7c, 0x15, 0x22, 0xd0, 0xf1, 0x02, 0x76, 0x6f, 
+    0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x09, 0x23, 0x75, 0x31, 0x79, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 
+    0x2e, 0xbe, 0xb3, 0x3f, 0xf1, 0x68, 0x11, 0xca, 0xb8, 0xc0, 0xf1, 0x12, 0x43, 0xd4, 0xd0, 0xf1, 
+    0xda, 0xb8, 0x50, 0x76, 0x7a, 0xb3, 0x3f, 0xf1, 0x80, 0x6d, 0xb4, 0x05, 0x08, 0x75, 0x31, 0x7a, 
+    0x12, 0x7c, 0x15, 0x80, 0x62, 0xb4, 0x03, 0x19, 0x75, 0x31, 0x7b, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 
+    0x2a, 0x2e, 0xb4, 0x01, 0x55, 0x7e, 0xb3, 0x3f, 0xf2, 0x44, 0x01, 0x7a, 0xb3, 0x3f, 0xf2, 0x80, 
+    0x46, 0xb4, 0x01, 0x19, 0x75, 0x31, 0x7c, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x2e, 0xb4, 0x01, 
+    0x39, 0x7e, 0xb3, 0x3f, 0xf2, 0x54, 0xfe, 0x7a, 0xb3, 0x3f, 0xf2, 0x80, 0x2a, 0xb4, 0x07, 0x2a, 
+    0x7e, 0xb3, 0x2a, 0x2d, 0x60, 0x24, 0x7c, 0x0b, 0x7e, 0x13, 0x2a, 0x2e, 0x7e, 0x17, 0x2a, 0x2f, 
+    0x75, 0x31, 0x73, 0x12, 0x7c, 0x15, 0x7a, 0x01, 0x31, 0x12, 0x7c, 0x15, 0x7a, 0x11, 0x31, 0x12, 
+    0x7c, 0x15, 0x12, 0x7b, 0x5f, 0x40, 0x03, 0x02, 0x76, 0x6f, 0x02, 0x7b, 0x29, 0x7e, 0xb3, 0x2a, 
+    0x2c, 0xb4, 0x0b, 0xf6, 0x75, 0x31, 0x7d, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x2e, 0x7e, 0xa3, 
+    0x2a, 0x30, 0x4c, 0xab, 0x78, 0xe4, 0x80, 0xdf, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x0a, 0xdb, 0x75, 
+    0x31, 0x7e, 0x12, 0x7c, 0x15, 0x7e, 0xb3, 0x2a, 0x2e, 0x70, 0xcf, 0xf5, 0xf3, 0x75, 0xf6, 0x01, 
+    0x22, 0x02, 0x7b, 0x29, 0x02, 0x7b, 0x29, 0x02, 0x7b, 0x29, 0x7e, 0xb3, 0x2a, 0x2c, 0xb4, 0x04, 
+    0x20, 0x75, 0x31, 0xc3, 0x12, 0x7c, 0x15, 0x7e, 0x04, 0x00, 0x01, 0x7e, 0x17, 0x2a, 0x2d, 0x7e, 
+    0x18, 0x2a, 0x3c, 0x7a, 0x1c, 0x00, 0x00, 0x7e, 0x47, 0x2a, 0x31, 0x12, 0x7c, 0x21, 0x02, 0x7a, 
+    0xc8, 0xb4, 0x06, 0x3a, 0x75, 0x31, 0xc1, 0x12, 0x7c, 0x15, 0x7e, 0x58, 0x00, 0x00, 0x7a, 0x5c, 
+    0x00, 0xfe, 0x7d, 0xca, 0x7e, 0xd7, 0x2a, 0x2d, 0x7e, 0x78, 0x2a, 0x3c, 0x7a, 0x7c, 0x00, 0x00, 
+    0x7e, 0x77, 0x2a, 0x31, 0x75, 0x31, 0xc1, 0x12, 0x7c, 0x15, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 
+    0xa9, 0xd5, 0x87, 0x12, 0x7c, 0x5a, 0xd0, 0x87, 0xd0, 0xa8, 0x40, 0x4f, 0x80, 0x4a, 0xb4, 0x00, 
+    0x1c, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x76, 0x6f, 0xe4, 0x8d, 0xef, 0x8d, 0xef, 0x8d, 0xef, 
+    0xd5, 0xe0, 0xf7, 0xc0, 0xd1, 0xca, 0x02, 0xff, 0xca, 0x06, 0x00, 0x00, 0x32, 0xb4, 0x09, 0x12, 
+    0x7e, 0x57, 0x2a, 0x2d, 0x4d, 0x55, 0x68, 0x05, 0xa9, 0xd2, 0xb1, 0x80, 0x03, 0xa9, 0xc2, 0xb1, 
+    0x80, 0x16, 0xb4, 0x07, 0x16, 0xc2, 0xaf, 0x7e, 0x07, 0x2a, 0x2f, 0x7e, 0x17, 0x2a, 0x2d, 0xc0, 
+    0xd1, 0xca, 0x18, 0xca, 0x38, 0xca, 0x28, 0x32, 0x02, 0x76, 0x6f, 0x02, 0x7b, 0x29, 0x7e, 0xb3, 
+    0x2a, 0x2c, 0xb4, 0x03, 0x15, 0x75, 0x31, 0xc2, 0x12, 0x7c, 0x15, 0x7e, 0x04, 0x00, 0x01, 0x7e, 
+    0x17, 0x2a, 0x2d, 0x7e, 0x57, 0x2a, 0x31, 0x02, 0x76, 0x73, 0xb4, 0x05, 0x39, 0x75, 0x31, 0xc0, 
+    0x12, 0x7c, 0x15, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x7e, 0x08, 0x2a, 0x3c, 
+    0x7a, 0x0c, 0x00, 0x00, 0x7e, 0x24, 0x00, 0xfe, 0x7e, 0x37, 0x2a, 0x2d, 0x7e, 0x47, 0x2a, 0x31, 
+    0x12, 0x7c, 0x21, 0xd0, 0x87, 0xd0, 0xa8, 0x7e, 0x08, 0x2a, 0x3c, 0x7a, 0x0c, 0x00, 0x00, 0x7e, 
+    0x57, 0x2a, 0x31, 0x02, 0x76, 0x73, 0x02, 0x7b, 0x29, 0x75, 0x31, 0x07, 0x12, 0x7c, 0x15, 0x43, 
+    0xe1, 0xc0, 0x22, 0xc0, 0xa8, 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x7b, 0x9e, 0x40, 
+    0x19, 0x7e, 0x08, 0x2a, 0x3c, 0x7a, 0x0c, 0x00, 0x00, 0xca, 0x0b, 0xca, 0x49, 0x12, 0x7c, 0x21, 
+    0xda, 0x59, 0xda, 0x0b, 0xd0, 0x87, 0xd0, 0xa8, 0xc3, 0x22, 0xd0, 0x87, 0xd0, 0xa8, 0x22, 0xc0, 
+    0xa8, 0xc0, 0x87, 0xc2, 0xaf, 0xa9, 0xd5, 0x87, 0x12, 0x7b, 0x9e, 0x40, 0x2b, 0x7e, 0x58, 0x00, 
+    0x00, 0x7a, 0x5c, 0x00, 0xfe, 0x7f, 0x61, 0x7e, 0x78, 0x2a, 0x3c, 0x7a, 0x7c, 0x00, 0x00, 0x7e, 
+    0x77, 0x2a, 0x31, 0xbd, 0x74, 0x78, 0x11, 0x75, 0x31, 0xc1, 0x12, 0x7c, 0x15, 0x12, 0x7c, 0x5a, 
+    0x40, 0x06, 0xd0, 0x87, 0xd0, 0xa8, 0xc3, 0x22, 0xd0, 0x87, 0xd0, 0xa8, 0xd3, 0x22, 0x7e, 0x24, 
+    0x00, 0xfe, 0x7e, 0x34, 0x7f, 0xca, 0x0b, 0x1a, 0x50, 0xc5, 0xf0, 0x7d, 0x62, 0x7d, 0x75, 0x7d, 
+    0x87, 0x7e, 0x34, 0x7f, 0xc2, 0x7e, 0x1b, 0xb0, 0x7e, 0x34, 0x7f, 0x03, 0xb4, 0x01, 0x04, 0x7e, 
+    0x34, 0x7f, 0xcc, 0x7e, 0x1b, 0xb0, 0xbc, 0x0b, 0x50, 0x49, 0x3e, 0x00, 0x3e, 0x00, 0x0a, 0x50, 
+    0x2d, 0x75, 0x0b, 0x3a, 0x30, 0x69, 0x53, 0x00, 0x02, 0xbd, 0x38, 0x50, 0x02, 0x2d, 0x38, 0xbc, 
+    0x1b, 0x50, 0x30, 0x3e, 0x10, 0x3e, 0x10, 0x0a, 0x51, 0x2d, 0x35, 0x69, 0x41, 0x00, 0x02, 0x0b, 
+    0x1a, 0x30, 0xbd, 0x38, 0x50, 0x02, 0x2d, 0x38, 0xbe, 0x44, 0xff, 0xff, 0x78, 0x05, 0x7e, 0x1b, 
+    0x90, 0x0a, 0x49, 0x4d, 0x44, 0x68, 0x0c, 0xbe, 0x44, 0x00, 0xff, 0x28, 0x04, 0x7e, 0x44, 0x00, 
+    0xff, 0xc3, 0x22, 0xd3, 0x22, 
 
-// Segment #15, Start Address 00ff7fc6, Length 4
+// Segment #16, Start Address 00ff7fc6, Length 4
 0xff,0x00,0xc6,0x7f,0x04,0x00,
-    0x01, 0x0c, 0x03, 0x00, 
+    0x01, 0x10, 0x04, 0x00, 
 
-// Segment #16, Start Address 00ff7e30, Length 315
-0xff,0x00,0x30,0x7e,0x3b,0x01,
-    0xca, 0x08, 0x7e, 0x01, 0x2f, 0x7a, 0x03, 0x3f, 0xf0, 0xda, 0x08, 0x22, 0x7e, 0x1b, 0xc0, 0x7a, 
+// Segment #17, Start Address 00ff7c15, Length 330
+0xff,0x00,0x15,0x7c,0x4a,0x01,
+    0xca, 0x08, 0x7e, 0x01, 0x31, 0x7a, 0x03, 0x3f, 0xf0, 0xda, 0x08, 0x22, 0x7e, 0x1b, 0xc0, 0x7a, 
     0x0b, 0xc0, 0x0b, 0x14, 0x0b, 0x34, 0x1b, 0x44, 0x78, 0xf2, 0x22, 0x7f, 0x6f, 0x7f, 0xf0, 0x1b, 
     0xfc, 0x7c, 0x54, 0x7d, 0x32, 0x80, 0x08, 0xca, 0x1b, 0xca, 0x1b, 0xca, 0x1b, 0xca, 0x1b, 0x9e, 
     0x44, 0x00, 0x10, 0x50, 0xf2, 0x2e, 0x44, 0x00, 0x10, 0x68, 0x06, 0xca, 0x48, 0x1b, 0x44, 0x78, 
     0xfa, 0x7f, 0xf6, 0x89, 0xe4, 0xca, 0x6b, 0x5e, 0xd4, 0x00, 0x3f, 0x68, 0x20, 0x7e, 0x84, 0x00, 
-    0x40, 0x9d, 0x8d, 0xda, 0x6b, 0xbd, 0x87, 0x38, 0x16, 0xca, 0x79, 0x7d, 0x78, 0x12, 0x7e, 0x9f, 
+    0x40, 0x9d, 0x8d, 0xda, 0x6b, 0xbd, 0x87, 0x38, 0x16, 0xca, 0x79, 0x7d, 0x78, 0x12, 0x7c, 0x84, 
     0xda, 0x79, 0x40, 0x08, 0x9d, 0x78, 0x68, 0x02, 0x80, 0x05, 0xc2, 0xd7, 0x22, 0xda, 0x6b, 0x43, 
     0x90, 0x30, 0x74, 0xaa, 0x39, 0xb5, 0x55, 0x55, 0x74, 0x55, 0x39, 0xb5, 0x2a, 0xaa, 0x74, 0xa0, 
     0x39, 0xb5, 0x55, 0x55, 0x7e, 0x04, 0x00, 0x40, 0x9d, 0x70, 0x50, 0x06, 0x2d, 0x70, 0x7d, 0x07, 
@@ -1104,16 +1211,17 @@ static unsigned char IMAGE_ARRAY_NAME[] = {
     0x1b, 0x54, 0x78, 0xf5, 0x80, 0x2c, 0x6d, 0x00, 0x7c, 0x20, 0x7f, 0x16, 0x9f, 0x10, 0x7f, 0x27, 
     0x9f, 0x20, 0x7e, 0x2b, 0x00, 0x7e, 0x1b, 0x10, 0xbc, 0x01, 0x78, 0x16, 0x0b, 0x2c, 0x0b, 0x1c, 
     0xa5, 0xdb, 0xef, 0x7c, 0xb6, 0x20, 0xe0, 0x03, 0x63, 0x90, 0x30, 0x4d, 0x77, 0x78, 0x93, 0xc2, 
-    0xd7, 0x22, 0xd2, 0xd7, 0x22, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x06, 0x04, 0x02, 0x04, 0x00, 
-    0x02, 0x01, 0x04, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 
-    0x02, 0x02, 0x04, 0x00, 0x08, 0x10, 0x02, 0x10, 0x04, 0x02, 0x08, 0x00, 0x01, 0x01, 0x08, 0x7e, 
-    0x18, 0x7f, 0xbd, 0x7a, 0x1c, 0x00, 0xfe, 0x0b, 0x1a, 0x00, 0xbe, 0x10, 0x14, 0x38, 0x1a, 0x0a, 
-    0x51, 0x23, 0x7e, 0x18, 0x7f, 0x15, 0x7a, 0x1c, 0x00, 0xff, 0x2d, 0x35, 0x0b, 0x1a, 0x50, 0x60, 
-    0x08, 0xa5, 0xb8, 0x02, 0x03, 0x4e, 0xa0, 0x08, 0x22, 0x80, 0xfe, 
+    0xd7, 0x22, 0xd2, 0xd7, 0x22, 0x00, 0x04, 0x00, 0x04, 0x42, 0x08, 0x06, 0x04, 0x02, 0x04, 0x00, 
+    0x02, 0x01, 0x04, 0x01, 0x02, 0x82, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 
+    0x02, 0x02, 0x04, 0x02, 0x08, 0x10, 0x02, 0x10, 0x04, 0x02, 0x08, 0x00, 0x01, 0x01, 0x08, 0x00, 
+    0x01, 0x00, 0x02, 0x00, 0x02, 0x02, 0x08, 0x02, 0x04, 0x20, 0x04, 0x7e, 0x18, 0x7f, 0xbd, 0x7a, 
+    0x1c, 0x00, 0xfe, 0x0b, 0x1a, 0x00, 0x5e, 0x10, 0x1f, 0xbe, 0x10, 0x1a, 0x38, 0x1a, 0x0a, 0x51, 
+    0x23, 0x7e, 0x18, 0x7c, 0xfa, 0x7a, 0x1c, 0x00, 0xff, 0x2d, 0x35, 0x0b, 0x1a, 0x50, 0x60, 0x08, 
+    0xa5, 0xb8, 0x02, 0x03, 0x4e, 0xa0, 0x08, 0x22, 0x80, 0xfe, 
 };
 
 static struct edge_firmware_version_info IMAGE_VERSION_NAME = {
-	1, 12, 3 };		// Major, Minor, Build
+	1, 16, 4 };		// Major, Minor, Build
 
 #undef IMAGE_VERSION_NAME
 
diff --git a/drivers/usb/serial/io_fw_down3.h b/drivers/usb/serial/io_fw_down3.h
index 20eecb39d..93b56d68a 100644
--- a/drivers/usb/serial/io_fw_down3.h
+++ b/drivers/usb/serial/io_fw_down3.h
@@ -1,11 +1,11 @@
 //**************************************************************
 //* Edgeport Binary Image (for TI based products)
-//* Generated by TIBin2C v1.00
+//* Generated by TIBin2C v2.00 (watchport)
 //* Copyright (C) 2001 Inside Out Networks, All rights reserved.
 //**************************************************************
 
 
-static int IMAGE_SIZE = 12166;
+static int IMAGE_SIZE = 12749;
 
 struct EDGE_FIRMWARE_VERSION_INFO
 {
@@ -16,7 +16,7 @@ struct EDGE_FIRMWARE_VERSION_INFO
 
 static struct EDGE_FIRMWARE_VERSION_INFO IMAGE_VERSION_NAME =
 {
-	4, 1, 0		// Major, Minor, Build
+	4, 10, 0		// Major, Minor, Build
 
 };
 
@@ -27,20 +27,20 @@ static unsigned char IMAGE_ARRAY_NAME[] =
 //      WORD    Length;
 //      BYTE    CheckSum;
 //  };
-0x83, 0x2f, 
-0x33, 
+0xca, 0x31, 
+0xa8, 
 
-0x02, 0x24, 0x84, 0x02, 0x1f, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x1a, 0x85, 0x45, 
-0x8c, 0x85, 0x46, 0x8a, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 
-0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xe5, 0x44, 
-0x24, 0x08, 0xf8, 0xe6, 0x60, 0x2b, 0xe5, 0x44, 0x24, 0x10, 0xf8, 0xa6, 0x81, 0xe5, 0x44, 0x75, 
-0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0x78, 0x92, 0xe5, 0x81, 
-0x04, 0xc3, 0x98, 0xf9, 0x94, 0x22, 0x40, 0x03, 0x02, 0x11, 0x1a, 0xe6, 0xf0, 0x08, 0xa3, 0xd9, 
-0xfa, 0x74, 0x08, 0x25, 0x44, 0xf8, 0x05, 0x44, 0x08, 0xe6, 0x54, 0x80, 0x70, 0x0c, 0xe5, 0x44, 
-0xb4, 0x07, 0xf3, 0x78, 0x08, 0x75, 0x44, 0x00, 0x80, 0xef, 0xe5, 0x44, 0x24, 0x10, 0xf8, 0x86, 
-0x81, 0xe5, 0x44, 0x75, 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 
-0x78, 0x92, 0xe5, 0x81, 0x04, 0xc3, 0x98, 0xf9, 0xe0, 0xf6, 0x08, 0xa3, 0xd9, 0xfa, 0xd0, 0x07, 
+0x02, 0x26, 0xfe, 0x02, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x1a, 0x85, 0x3f, 
+0x8c, 0x85, 0x40, 0x8a, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 
+0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xe5, 0x3e, 
+0x24, 0x08, 0xf8, 0xe6, 0x60, 0x2b, 0xe5, 0x3e, 0x24, 0x10, 0xf8, 0xa6, 0x81, 0xe5, 0x3e, 0x75, 
+0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0x78, 0x8c, 0xe5, 0x81, 
+0x04, 0xc3, 0x98, 0xf9, 0x94, 0x22, 0x40, 0x03, 0x02, 0x11, 0x94, 0xe6, 0xf0, 0x08, 0xa3, 0xd9, 
+0xfa, 0x74, 0x08, 0x25, 0x3e, 0xf8, 0x05, 0x3e, 0x08, 0xe6, 0x54, 0x80, 0x70, 0x0c, 0xe5, 0x3e, 
+0xb4, 0x07, 0xf3, 0x78, 0x08, 0x75, 0x3e, 0x00, 0x80, 0xef, 0xe5, 0x3e, 0x24, 0x10, 0xf8, 0x86, 
+0x81, 0xe5, 0x3e, 0x75, 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 
+0x78, 0x8c, 0xe5, 0x81, 0x04, 0xc3, 0x98, 0xf9, 0xe0, 0xf6, 0x08, 0xa3, 0xd9, 0xfa, 0xd0, 0x07, 
 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0x83, 
 0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, 0x30, 0x01, 0x4d, 0x30, 0xb4, 0x48, 0x10, 
 0x00, 0x45, 0x90, 0xff, 0x08, 0xe0, 0x54, 0x20, 0xf8, 0x90, 0xff, 0x48, 0xe0, 0x54, 0x20, 0xf9, 
@@ -50,747 +50,783 @@ static unsigned char IMAGE_ARRAY_NAME[] =
 0xa3, 0xe0, 0xcb, 0xf0, 0x6b, 0x60, 0x02, 0x7e, 0x04, 0x22, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, 
 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 
 0xc0, 0x06, 0xc0, 0x07, 0x90, 0xff, 0x93, 0x74, 0x01, 0xf0, 0xe5, 0x81, 0x94, 0xfd, 0x40, 0x03, 
-0x02, 0x11, 0x1a, 0x85, 0x47, 0x8d, 0x85, 0x48, 0x8b, 0x74, 0xae, 0xf5, 0x82, 0x74, 0xfa, 0xf5, 
+0x02, 0x11, 0x94, 0x85, 0x41, 0x8d, 0x85, 0x42, 0x8b, 0x74, 0xaf, 0xf5, 0x82, 0x74, 0xfa, 0xf5, 
 0x83, 0xe0, 0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x4a, 0xe0, 0x30, 0xe7, 0x2c, 
 0x90, 0xff, 0x4e, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x20, 
-0xb4, 0x02, 0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x25, 
-0x13, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82, 
+0xb4, 0x02, 0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x27, 
+0x8d, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82, 
 0xa3, 0xe0, 0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x52, 0xe0, 0x30, 0xe7, 0x2c, 
-0x90, 0xff, 0x56, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x20, 
-0xb4, 0x02, 0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x25, 
-0x13, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82, 
-0x20, 0x02, 0x03, 0x30, 0x01, 0x7b, 0x74, 0x16, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x14, 
-0xfc, 0xf0, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0x64, 0x04, 0x70, 0x0f, 0xec, 0x70, 0x62, 0x7e, 
-0x01, 0x12, 0x00, 0xc9, 0x7c, 0x0a, 0x7d, 0xfa, 0x02, 0x02, 0x22, 0x12, 0x00, 0xc9, 0xee, 0x64, 
-0x04, 0x60, 0x1d, 0xec, 0x70, 0x4b, 0x7c, 0x0a, 0xed, 0x14, 0xfd, 0x70, 0x15, 0xee, 0x64, 0x02, 
-0x60, 0x07, 0x7e, 0x02, 0x7d, 0x32, 0x02, 0x02, 0x22, 0x7e, 0x01, 0x7d, 0xfa, 0x02, 0x02, 0x22, 
-0x7c, 0x0a, 0x74, 0x16, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 0xa3, 
-0xee, 0xf0, 0x14, 0x60, 0x18, 0x20, 0xe1, 0x0f, 0x20, 0x01, 0x06, 0xd2, 0xb1, 0xc2, 0xb0, 0x80, 
-0x10, 0xc2, 0xb1, 0xd2, 0xb0, 0x80, 0x0a, 0xc2, 0xb1, 0xc2, 0xb0, 0x80, 0x04, 0xd2, 0xb0, 0xd2, 
-0xb1, 0x78, 0x19, 0x79, 0x09, 0x7a, 0x07, 0xe7, 0x70, 0x04, 0xa6, 0x00, 0x80, 0x0b, 0xe6, 0x60, 
-0x08, 0x16, 0xe6, 0x70, 0x04, 0xe7, 0x44, 0x80, 0xf7, 0x08, 0x09, 0xda, 0xea, 0xe5, 0x43, 0x60, 
-0x13, 0x14, 0xf5, 0x43, 0x70, 0x0e, 0xe5, 0x44, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x10, 0x95, 
-0xd2, 0x8c, 0xd2, 0x8d, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 
-0xd0, 0x01, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, 0x90, 
-0xff, 0x04, 0xe0, 0x90, 0xfa, 0xb5, 0xf0, 0x90, 0xff, 0x06, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, 
-0xff, 0xea, 0xfe, 0xef, 0xc3, 0x94, 0x08, 0xee, 0x94, 0x01, 0x50, 0x02, 0x80, 0x04, 0x7e, 0x01, 
-0x7f, 0x08, 0x8e, 0x34, 0x8f, 0x35, 0x90, 0xff, 0x02, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, 0xff, 
-0xea, 0x90, 0xfa, 0xb9, 0xf0, 0xef, 0xa3, 0xf0, 0x12, 0x18, 0x49, 0x78, 0x24, 0x7c, 0x00, 0x7d, 
-0x00, 0x12, 0x19, 0x6c, 0x7e, 0x00, 0x7f, 0x05, 0x12, 0x13, 0x8f, 0xe4, 0xf5, 0x53, 0xe5, 0x53, 
-0xc3, 0x94, 0x02, 0x50, 0x0f, 0x12, 0x18, 0x2a, 0xe4, 0x12, 0x13, 0xfb, 0x05, 0x53, 0x04, 0x12, 
-0x18, 0x1b, 0x80, 0xea, 0x12, 0x18, 0x49, 0x90, 0xff, 0x00, 0xe0, 0xff, 0x54, 0x60, 0x24, 0xc0, 
-0x70, 0x03, 0x02, 0x08, 0xb8, 0x24, 0x40, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 
-0xfe, 0x54, 0x0f, 0xf5, 0x53, 0xee, 0x30, 0xe7, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0a, 0x90, 
-0xff, 0x01, 0xe0, 0x12, 0x15, 0x0f, 0x03, 0x55, 0x00, 0x04, 0x28, 0x01, 0x05, 0x2f, 0x03, 0x05, 
-0xf6, 0x05, 0x06, 0x38, 0x06, 0x07, 0x9a, 0x08, 0x07, 0xe2, 0x09, 0x08, 0x3e, 0x0a, 0x08, 0x7e, 
-0x0b, 0x00, 0x00, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, 
-0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x64, 0x02, 0x45, 0x34, 
-0x60, 0x03, 0x02, 0x0e, 0xac, 0xef, 0x54, 0x1f, 0x14, 0x60, 0x2b, 0x14, 0x60, 0x47, 0x24, 0x02, 
-0x60, 0x03, 0x02, 0x0e, 0xac, 0xee, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0x2a, 0x74, 0x01, 
-0x12, 0x13, 0xfb, 0x78, 0x6d, 0xe6, 0x30, 0xe0, 0x08, 0x12, 0x18, 0x2a, 0x74, 0x02, 0x12, 0x13, 
-0xfb, 0x7f, 0x02, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, 0x09, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 
-0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0e, 0xac, 
-0x7f, 0x02, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, 0x0e, 0x90, 0xfa, 0xb5, 0xe0, 0xff, 0x60, 
-0x07, 0x64, 0x80, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0f, 0x38, 0x40, 0x03, 0x02, 0x0e, 0xac, 
-0xe5, 0x53, 0x70, 0x19, 0x30, 0x0a, 0x0b, 0x90, 0xff, 0x80, 0x12, 0x18, 0x27, 0x12, 0x13, 0xfb, 
-0x80, 0x24, 0x90, 0xff, 0x82, 0x12, 0x18, 0x27, 0x12, 0x13, 0xfb, 0x80, 0x19, 0x15, 0x53, 0x30, 
-0x0a, 0x0b, 0x12, 0x18, 0xbd, 0x12, 0x18, 0x25, 0x12, 0x13, 0xfb, 0x80, 0x09, 0x12, 0x18, 0xcb, 
-0x12, 0x18, 0x25, 0x12, 0x13, 0xfb, 0x12, 0x18, 0x2a, 0x12, 0x13, 0xb5, 0x60, 0x05, 0x74, 0x01, 
-0x12, 0x13, 0xfb, 0x7f, 0x02, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 
-0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x14, 0x60, 0x2d, 0x14, 
-0x60, 0x59, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x04, 0xa3, 
-0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 
-0xac, 0x78, 0x6d, 0xe6, 0x54, 0xfe, 0xf6, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, 
-0x06, 0x20, 0xe0, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe0, 0x09, 0x90, 0xfa, 0xb5, 0xe0, 
-0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe1, 0x0c, 0x90, 0xfa, 0xb5, 0xe0, 0xd3, 0x94, 
-0x01, 0x40, 0x03, 0x02, 0x0e, 0xac, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0x90, 0xfa, 0xb9, 0xe0, 0x70, 
-0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0f, 0x38, 0x40, 0x03, 0x02, 0x0e, 0xac, 
-0xe5, 0x2c, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe0, 0x07, 
-0xe5, 0x53, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x53, 0x70, 0x0f, 0x90, 0xff, 0x82, 0xe0, 0x54, 
-0xf7, 0xf0, 0x90, 0xff, 0x80, 0xe0, 0x54, 0xf7, 0xf0, 0x22, 0xe5, 0x53, 0x24, 0xfe, 0x60, 0x1b, 
-0x04, 0x70, 0x2e, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 0xfd, 0x7f, 0x03, 0x12, 0x2a, 0xce, 
-0x80, 0x1f, 0xe4, 0xfd, 0x7f, 0x03, 0x12, 0x2a, 0xce, 0x80, 0x16, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 
-0xe4, 0x33, 0xfd, 0x7f, 0x04, 0x12, 0x2a, 0xce, 0x80, 0x07, 0xe4, 0xfd, 0x7f, 0x04, 0x12, 0x2a, 
-0xce, 0x15, 0x53, 0x30, 0x0a, 0x0b, 0x12, 0x18, 0xbd, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0x80, 
-0x09, 0x12, 0x18, 0xcb, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 
-0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 
-0x12, 0x18, 0xd9, 0x14, 0x60, 0x2d, 0x14, 0x60, 0x55, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0e, 0xac, 
-0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x04, 0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 
-0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x78, 0x6d, 0xe6, 0x44, 0x01, 0xf6, 0xe4, 0xff, 
-0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 
-0x30, 0xe0, 0x07, 0xe5, 0x53, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe1, 0x0a, 0xe5, 
-0x53, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0e, 0xac, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0x90, 0xfa, 
-0xb9, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0xff, 
-0x12, 0x2f, 0x3b, 0x40, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 
-0x02, 0x0e, 0xac, 0xe5, 0x53, 0x70, 0x09, 0x30, 0x0a, 0x03, 0x02, 0x19, 0x7a, 0x02, 0x19, 0x3e, 
-0xe5, 0x2c, 0x20, 0xe1, 0x03, 0x02, 0x0e, 0xac, 0x15, 0x53, 0x30, 0x0a, 0x0b, 0x12, 0x18, 0xbd, 
-0xf5, 0x83, 0xe0, 0x44, 0x08, 0xf0, 0x80, 0x09, 0x12, 0x18, 0xcb, 0xf5, 0x83, 0xe0, 0x44, 0x08, 
-0xf0, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 
-0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 
-0x12, 0x18, 0xd9, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x30, 0xe1, 0x03, 0x02, 0x0e, 0xac, 
-0x90, 0xfa, 0xba, 0xe0, 0x90, 0xff, 0xff, 0xf0, 0xe0, 0x60, 0x05, 0x43, 0x2c, 0x01, 0x80, 0x03, 
-0x53, 0x2c, 0xfe, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 0x20, 0xe7, 0x03, 0x02, 0x0e, 0xac, 
-0xe5, 0x35, 0x45, 0x34, 0x70, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x60, 0x03, 0x02, 0x0e, 
-0xac, 0x90, 0xfa, 0xb9, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0x24, 0xfe, 0x60, 0x3a, 0x14, 0x60, 
-0x75, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xed, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 
-0x49, 0x12, 0x19, 0x73, 0x7d, 0x03, 0x12, 0x0e, 0xf3, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0e, 
-0xb0, 0x90, 0xfa, 0xb2, 0xe0, 0xfd, 0xa3, 0x12, 0x18, 0x93, 0x12, 0x0f, 0x0f, 0x50, 0x02, 0x80, 
-0x04, 0xae, 0x34, 0xaf, 0x35, 0x02, 0x0f, 0x40, 0x12, 0x18, 0x49, 0x90, 0xf9, 0x65, 0xe0, 0x30, 
-0xe4, 0x0d, 0x12, 0x19, 0x73, 0x7d, 0x14, 0x12, 0x0e, 0xf3, 0x60, 0x10, 0x02, 0x0e, 0xac, 0x12, 
-0x19, 0x73, 0x7d, 0x04, 0x12, 0x0f, 0x47, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x0e, 0xb0, 0x90, 
-0xfa, 0xb2, 0xe0, 0xfd, 0xa3, 0x12, 0x18, 0x93, 0x12, 0x0f, 0x0f, 0x50, 0x02, 0x80, 0x04, 0xae, 
-0x34, 0xaf, 0x35, 0x02, 0x0f, 0x40, 0x12, 0x19, 0x73, 0x7d, 0x05, 0x12, 0x0f, 0x47, 0x60, 0x03, 
-0x02, 0x0e, 0xac, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb2, 0x12, 0x18, 0x90, 0x7d, 0x01, 0x12, 0x23, 
-0xee, 0x90, 0xfa, 0xb3, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x14, 0x2f, 0x90, 0xfa, 0xba, 0xe0, 0x90, 
-0xfa, 0xb1, 0xf0, 0xe4, 0xf5, 0x52, 0x90, 0xfa, 0xb1, 0xe0, 0xff, 0xe5, 0x52, 0xc3, 0x9f, 0x50, 
-0x24, 0x12, 0x18, 0x8a, 0x12, 0x0f, 0x52, 0xff, 0xfd, 0x90, 0xfa, 0xb3, 0xe4, 0x8d, 0xf0, 0x12, 
-0x14, 0x2f, 0x90, 0xfa, 0xb2, 0xe0, 0xc3, 0x9f, 0xf0, 0xd3, 0x94, 0x00, 0x50, 0x03, 0x02, 0x0e, 
-0xac, 0x05, 0x52, 0x80, 0xd1, 0x12, 0x18, 0x8a, 0x12, 0x0f, 0x52, 0x24, 0xfe, 0xff, 0x90, 0xfa, 
-0xb2, 0xf0, 0xfd, 0xa3, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x14, 0x2f, 0x7a, 0xf9, 0x79, 0x6e, 0x7b, 
-0x01, 0x8b, 0x2d, 0x8a, 0x2e, 0x89, 0x2f, 0xe9, 0x24, 0x02, 0xf9, 0xe4, 0x3a, 0xfa, 0x12, 0x18, 
-0x90, 0x12, 0x23, 0xee, 0x8f, 0x52, 0x05, 0x52, 0x05, 0x52, 0x12, 0x18, 0x2a, 0xe5, 0x52, 0x12, 
-0x13, 0xfb, 0x12, 0x18, 0x2a, 0x90, 0x00, 0x01, 0x74, 0x03, 0x12, 0x14, 0x0d, 0xaf, 0x52, 0x7e, 
-0x00, 0xc3, 0xef, 0x95, 0x35, 0xee, 0x95, 0x34, 0x50, 0x02, 0x80, 0x04, 0xae, 0x34, 0xaf, 0x35, 
-0x8e, 0x30, 0x8f, 0x31, 0x02, 0x29, 0x2d, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe7, 0x03, 0x02, 
-0x0e, 0xac, 0xe5, 0x35, 0x64, 0x01, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 
-0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 
-0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe0, 0x06, 
-0x20, 0xe1, 0x03, 0x02, 0x0e, 0xac, 0x75, 0x2d, 0x00, 0x75, 0x2e, 0x00, 0x75, 0x2f, 0x29, 0x02, 
-0x0f, 0x2f, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, 
-0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xd3, 0x90, 0xfa, 0xba, 
-0xe0, 0x94, 0x01, 0x90, 0xfa, 0xb9, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 
-0xd9, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 0x02, 0x0e, 
-0xac, 0x90, 0xfa, 0xba, 0xe0, 0xf5, 0x29, 0xe5, 0x29, 0x70, 0x08, 0x43, 0x2c, 0x01, 0x53, 0x2c, 
-0xfd, 0x80, 0x06, 0x53, 0x2c, 0xfe, 0x43, 0x2c, 0x02, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 
-0x20, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x64, 0x01, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 
-0xac, 0x90, 0xfa, 0xb5, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x90, 0xfa, 0xb9, 0xe0, 0x70, 0x02, 
-0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0e, 0xac, 0x12, 0x18, 0xd9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, 
-0xac, 0xe5, 0x2c, 0x20, 0xe1, 0x03, 0x02, 0x0e, 0xac, 0x7f, 0x01, 0x02, 0x2f, 0x6a, 0xe5, 0x2c, 
-0x30, 0xe7, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x35, 0x45, 0x34, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xd3, 
-0x90, 0xfa, 0xba, 0xe0, 0x94, 0x00, 0x90, 0xfa, 0xb9, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0e, 
-0xac, 0x12, 0x18, 0xd9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0e, 0xac, 0xe5, 0x2c, 0x20, 0xe1, 0x03, 
-0x02, 0x0e, 0xac, 0xe4, 0xff, 0x02, 0x2f, 0x6a, 0x90, 0xff, 0x01, 0x12, 0x19, 0x8a, 0xef, 0x12, 
-0x13, 0xfb, 0x90, 0xfa, 0xb5, 0x12, 0x19, 0x8a, 0x90, 0x00, 0x01, 0xef, 0x12, 0x14, 0x0d, 0x90, 
-0x00, 0x02, 0xe4, 0x12, 0x14, 0x0d, 0x74, 0x03, 0x12, 0x18, 0x1b, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 
-0xa3, 0xe0, 0x85, 0x2f, 0x82, 0x85, 0x2e, 0x83, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x01, 
-0xe0, 0x12, 0x15, 0x0f, 0x09, 0x3d, 0x02, 0x09, 0x5f, 0x04, 0x09, 0x81, 0x05, 0x09, 0xad, 0x06, 
-0x09, 0xcb, 0x07, 0x09, 0xe9, 0x08, 0x0a, 0x07, 0x09, 0x0a, 0x25, 0x0b, 0x0a, 0xda, 0x80, 0x0c, 
-0xfa, 0x81, 0x0d, 0x1c, 0x82, 0x0b, 0x21, 0x83, 0x0b, 0x6a, 0x84, 0x0b, 0x89, 0x85, 0x0b, 0xc5, 
-0x86, 0x0c, 0x07, 0x87, 0x0c, 0x95, 0x88, 0x0c, 0xd0, 0x89, 0x0a, 0x43, 0x92, 0x0a, 0x43, 0x93, 
-0x0d, 0xcf, 0xc0, 0x0e, 0x00, 0xc1, 0x0e, 0x11, 0xc2, 0x00, 0x00, 0x0e, 0x9b, 0xe5, 0x2c, 0x20, 
-0xe7, 0x05, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 
-0xfd, 0x7c, 0x00, 0x7f, 0x07, 0x02, 0x10, 0x9c, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2c, 0xc0, 0xe5, 
-0x2c, 0x20, 0xe7, 0x05, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 
-0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0c, 0x02, 0x10, 0x9c, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2c, 
-0xc0, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, 0x19, 0x99, 0x50, 0x06, 0xe5, 0x35, 
-0x45, 0x34, 0x70, 0x05, 0x7f, 0x02, 0x02, 0x2e, 0xa5, 0x90, 0xfa, 0xb5, 0xe0, 0x24, 0xfe, 0x24, 
-0xfd, 0x50, 0x02, 0x80, 0x03, 0x02, 0x2f, 0x28, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 
-0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 
-0x00, 0x7f, 0x08, 0x02, 0x10, 0x9c, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 
-0x02, 0x0e, 0xaf, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 
-0x09, 0x02, 0x10, 0x9c, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 
-0xaf, 0x12, 0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0a, 0x02, 
-0x10, 0x9c, 0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, 
-0x18, 0xe0, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0b, 0x02, 0x10, 0x9c, 
-0x7f, 0x07, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x03, 0x02, 0x0e, 0xaf, 0x12, 0x18, 0xe0, 
-0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0e, 0x02, 0x10, 0x9c, 0x7f, 0x07, 
-0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x56, 0x12, 0x18, 0xd9, 0x70, 0x4a, 0x90, 0xff, 0x02, 
-0xe0, 0xf5, 0x52, 0xe5, 0x52, 0xb4, 0x82, 0x05, 0x75, 0x52, 0x61, 0x80, 0x12, 0xe5, 0x52, 0xb4, 
-0x83, 0x05, 0x75, 0x52, 0x62, 0x80, 0x08, 0xe5, 0x52, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 0x52, 0x12, 
-0x17, 0x8b, 0x12, 0x19, 0x6c, 0x12, 0x22, 0xb8, 0x12, 0x18, 0xe8, 0x12, 0x13, 0xce, 0x60, 0x05, 
-0x12, 0x2f, 0x76, 0x80, 0x06, 0x85, 0x2a, 0x30, 0x85, 0x2b, 0x31, 0x75, 0x2d, 0x01, 0x75, 0x2e, 
-0xf9, 0x75, 0x2f, 0x71, 0x02, 0x29, 0x2d, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2c, 0xc0, 0x12, 0x18, 
-0xd9, 0x60, 0x05, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x19, 0x99, 0x40, 0x05, 0x7f, 0x03, 0x02, 
-0x2e, 0xa5, 0x90, 0xff, 0x02, 0xe0, 0xf5, 0x52, 0xe5, 0x52, 0xb4, 0x82, 0x05, 0x75, 0x52, 0x61, 
-0x80, 0x12, 0xe5, 0x52, 0xb4, 0x83, 0x05, 0x75, 0x52, 0x62, 0x80, 0x08, 0xe5, 0x52, 0xc4, 0x54, 
-0xf0, 0x04, 0xf5, 0x52, 0x12, 0x17, 0x8b, 0x02, 0x2f, 0x28, 0x12, 0x19, 0xa3, 0x12, 0x27, 0x19, 
-0x12, 0x18, 0x9b, 0xe0, 0x54, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x78, 
-0x6e, 0x12, 0x14, 0xeb, 0x90, 0x00, 0x02, 0x12, 0x13, 0xce, 0x30, 0xe7, 0xf2, 0x90, 0x00, 0x02, 
-0xe4, 0x12, 0x14, 0x0d, 0x90, 0xfa, 0xb6, 0xe0, 0x44, 0x80, 0xff, 0xf0, 0x78, 0x82, 0xe6, 0xfc, 
-0x08, 0xe6, 0x8c, 0x83, 0x12, 0x18, 0xa3, 0xef, 0xf0, 0x12, 0x2f, 0x80, 0xe4, 0xff, 0x02, 0x2e, 
-0xa5, 0x90, 0xfa, 0xb5, 0xe0, 0x64, 0x01, 0x70, 0x1f, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x7e, 0x00, 
-0x70, 0x06, 0xa3, 0xe0, 0xf5, 0x90, 0x80, 0x2d, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0x90, 0x90, 0xfa, 
-0xba, 0xe0, 0x42, 0x90, 0xd2, 0xaf, 0x80, 0x1d, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x7e, 0x00, 0x70, 
-0x06, 0xa3, 0xe0, 0xf5, 0xb0, 0x80, 0x0e, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0xb0, 0x90, 0xfa, 0xba, 
-0xe0, 0x42, 0xb0, 0xd2, 0xaf, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0x49, 0x90, 0xfa, 0xb5, 
-0xe0, 0xb4, 0x01, 0x0a, 0x12, 0x18, 0x2a, 0xe5, 0x90, 0x12, 0x13, 0xfb, 0x80, 0x08, 0x12, 0x18, 
-0x2a, 0xe5, 0xb0, 0x12, 0x13, 0xfb, 0x02, 0x0f, 0x2f, 0x90, 0xf9, 0x65, 0xe0, 0x20, 0xe1, 0x30, 
-0x12, 0x18, 0x53, 0x60, 0x18, 0x04, 0x70, 0x28, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x09, 0x90, 0xff, 
-0xa4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x19, 0x12, 0x19, 0xad, 0xf0, 0x80, 0x13, 0x90, 0xfa, 0xb6, 
-0xe0, 0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x04, 0x12, 0x19, 0xb4, 0xf0, 
-0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x90, 0xf9, 0x65, 0xe0, 0x20, 0xe1, 0x36, 0x12, 0x18, 0x53, 0x60, 
-0x1b, 0x04, 0x70, 0x2e, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 
-0xf0, 0x80, 0x1f, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xb6, 0xe0, 
-0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 
-0xdf, 0xf0, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0x53, 0x60, 0x46, 0x04, 0x60, 0x03, 0x02, 
-0x0c, 0x90, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x17, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x04, 0xf0, 0x90, 
-0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x6a, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x61, 0x90, 
-0xff, 0xa4, 0xe0, 0x54, 0xfb, 0xf0, 0x90, 0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x53, 0x30, 0x95, 0x09, 
-0x90, 0xff, 0xa4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x47, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 
-0x80, 0x3e, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x17, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x04, 0xf0, 0x90, 
-0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x2a, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x21, 0x90, 
-0xff, 0xb4, 0xe0, 0x54, 0xfb, 0xf0, 0x90, 0xf9, 0x65, 0xe0, 0x30, 0xe1, 0x13, 0x30, 0x93, 0x09, 
-0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xfd, 0xf0, 
-0xe4, 0xff, 0x02, 0x2e, 0xa5, 0x12, 0x18, 0x53, 0x60, 0x1b, 0x04, 0x70, 0x2e, 0x90, 0xfa, 0xb6, 
-0xe0, 0x60, 0x09, 0x90, 0xff, 0xa2, 0xe0, 0x44, 0x40, 0xf0, 0x80, 0x1f, 0x90, 0xff, 0xa2, 0xe0, 
-0x54, 0xbf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xb2, 0xe0, 0x44, 
-0x40, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb2, 0xe0, 0x54, 0xbf, 0xf0, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 
-0x12, 0x18, 0x49, 0x12, 0x18, 0x5b, 0x60, 0x0f, 0x04, 0x70, 0x16, 0x90, 0xff, 0xa4, 0xe0, 0x12, 
-0x18, 0x2a, 0x12, 0x13, 0xfb, 0x80, 0x0a, 0x90, 0xff, 0xb4, 0xe0, 0x12, 0x18, 0x2a, 0x12, 0x13, 
-0xfb, 0x75, 0x30, 0x00, 0x75, 0x31, 0x01, 0x02, 0x29, 0x2d, 0xe4, 0xff, 0x12, 0x2e, 0xa5, 0x12, 
-0x19, 0x46, 0x7f, 0x03, 0x12, 0x11, 0x9f, 0x90, 0xff, 0xfc, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0xff, 
-0x7e, 0x00, 0x12, 0x2d, 0xee, 0xc2, 0x90, 0xc2, 0xaf, 0x00, 0x80, 0xfd, 0xe4, 0xf5, 0x54, 0xf5, 
-0x55, 0x90, 0xfa, 0xbb, 0x74, 0x3e, 0xf0, 0xa3, 0xe4, 0xf0, 0x90, 0xfa, 0xb3, 0xf0, 0xa3, 0x74, 
-0x15, 0xf0, 0xe0, 0x54, 0x3f, 0xff, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0xfa, 0xb8, 0xf0, 0xd3, 0x94, 
-0x00, 0xe4, 0x94, 0x3e, 0x40, 0x08, 0x90, 0xfa, 0xbc, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x12, 0x0e, 
-0xd6, 0xe5, 0x23, 0x45, 0x22, 0x70, 0x73, 0x12, 0x18, 0x62, 0x90, 0xfa, 0xbb, 0x12, 0x19, 0x65, 
-0x60, 0x27, 0xd3, 0xef, 0x94, 0x40, 0xee, 0x94, 0x00, 0x40, 0x08, 0x90, 0xfa, 0xb8, 0x74, 0x40, 
-0xf0, 0x80, 0x08, 0x90, 0xfa, 0xbc, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x12, 0x0e, 0xd6, 0xe5, 0x23, 
-0x45, 0x22, 0x70, 0x46, 0x12, 0x18, 0x62, 0x80, 0xd1, 0x75, 0x52, 0x02, 0x90, 0xfa, 0xbb, 0xe4, 
-0xf0, 0xa3, 0x04, 0xf0, 0x90, 0xfa, 0xb3, 0xe4, 0xf0, 0xa3, 0x74, 0x0f, 0xf0, 0x7b, 0x00, 0x7a, 
-0x00, 0x79, 0x52, 0x90, 0xfa, 0xbc, 0xe0, 0xf5, 0x50, 0x7d, 0x0f, 0x7c, 0x00, 0x12, 0x26, 0x25, 
-0x75, 0x22, 0x00, 0x8f, 0x23, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x52, 0xe4, 0xf5, 0x40, 0xf5, 0x41, 
-0x7d, 0x01, 0x12, 0x23, 0xee, 0xe4, 0xf5, 0x22, 0xf5, 0x23, 0xaf, 0x23, 0x02, 0x2e, 0xa5, 0x90, 
-0xfa, 0xba, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x30, 0xe7, 0x10, 0xe0, 0x54, 0x0f, 0x90, 0xf9, 0x62, 
-0xf0, 0xd3, 0x94, 0x00, 0x40, 0x15, 0xc2, 0x95, 0x80, 0x11, 0x90, 0xfa, 0xb6, 0xe0, 0x54, 0x0f, 
-0x90, 0xf9, 0x61, 0xf0, 0xd3, 0x94, 0x00, 0x40, 0x02, 0xc2, 0x94, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 
-0x12, 0x19, 0xa3, 0xbf, 0x01, 0x04, 0xd2, 0x93, 0x80, 0x02, 0xc2, 0x93, 0xe4, 0xff, 0x02, 0x2e, 
-0xa5, 0x90, 0xfa, 0xba, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x54, 0x03, 0x14, 0x60, 0x0a, 0x14, 0x60, 
-0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x91, 0x80, 0x27, 0xc2, 0x91, 0x80, 0x23, 
-0x12, 0x19, 0xad, 0x12, 0x0e, 0xfe, 0x60, 0x04, 0xd2, 0x91, 0x80, 0x17, 0x90, 0xff, 0xa4, 0xe0, 
-0x44, 0x10, 0x12, 0x0e, 0xfe, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x91, 0x80, 0x02, 0xd2, 0x91, 0x12, 
-0x19, 0xad, 0xf0, 0x90, 0xfa, 0xb6, 0xe0, 0x54, 0x0c, 0xff, 0x13, 0x13, 0x54, 0x3f, 0x14, 0x60, 
-0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x92, 0x80, 0x27, 0xc2, 
-0x92, 0x80, 0x23, 0x12, 0x19, 0xb4, 0x12, 0x0f, 0x1e, 0x60, 0x04, 0xd2, 0x92, 0x80, 0x17, 0x90, 
-0xff, 0xb4, 0xe0, 0x44, 0x10, 0x12, 0x0f, 0x1e, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x92, 0x80, 0x02, 
-0xd2, 0x92, 0x12, 0x19, 0xb4, 0xf0, 0xe4, 0xff, 0x02, 0x2e, 0xa5, 0xe5, 0x2c, 0x30, 0xe7, 0x07, 
-0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2c, 0xc0, 0x7f, 0x05, 0x02, 0x2e, 0xa5, 0x12, 0x2f, 0x76, 0x22, 
-0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb2, 0x90, 0xfa, 0xb3, 0xe0, 0xf5, 0x40, 0xa3, 0xe0, 0xf5, 0x41, 
-0x7d, 0x01, 0x12, 0x23, 0xee, 0x90, 0xfa, 0xb3, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x14, 0x2f, 0xab, 
-0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 0x22, 0xaa, 0x54, 0xa9, 0x55, 0x7b, 0xff, 0x90, 0xfa, 0xb3, 0xe0, 
-0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xb8, 0xe0, 0xf5, 0x50, 0x12, 0x26, 0x25, 0x75, 0x22, 0x00, 
-0x8f, 0x23, 0x22, 0x12, 0x20, 0xc5, 0x7e, 0x00, 0x8e, 0x22, 0x8f, 0x23, 0xef, 0x22, 0xf0, 0x7f, 
-0x01, 0x12, 0x11, 0x9f, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x54, 0xa0, 0x22, 0x12, 
-0x23, 0xee, 0x8f, 0x52, 0x7e, 0x00, 0xc3, 0xef, 0x95, 0x35, 0xee, 0x95, 0x34, 0x22, 0xf0, 0x7f, 
-0x01, 0x12, 0x11, 0x9f, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x54, 0xa0, 0x22, 0x75, 
-0x30, 0x00, 0x75, 0x31, 0x01, 0x02, 0x29, 0x2d, 0x90, 0xfa, 0xb5, 0xe0, 0xff, 0x02, 0x2f, 0x3b, 
-0x8e, 0x30, 0x8f, 0x31, 0x02, 0x29, 0x2d, 0x12, 0x20, 0xc5, 0x7e, 0x00, 0x8e, 0x22, 0x8f, 0x23, 
-0xef, 0x22, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x90, 0xfa, 0xb0, 0xe0, 0x22, 0xef, 0x90, 0xf8, 0x04, 
-0xf0, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 0xee, 0x60, 0x0a, 0xc0, 0x05, 0x7d, 0x7f, 0xdd, 0xfe, 0xde, 
-0xfa, 0xd0, 0x05, 0xef, 0xc3, 0x94, 0x15, 0x50, 0x03, 0xd0, 0xa8, 0x22, 0x13, 0x70, 0x03, 0xd0, 
-0xa8, 0x22, 0xff, 0xd5, 0x07, 0xfd, 0xd0, 0xa8, 0x22, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 
-0x04, 0xc0, 0x05, 0xe5, 0x44, 0x24, 0x08, 0xf8, 0x86, 0x05, 0x53, 0x05, 0x7f, 0x7c, 0xff, 0x12, 
-0x0f, 0xfe, 0x7f, 0x00, 0x7e, 0x00, 0xe5, 0x49, 0x60, 0x46, 0xfc, 0x90, 0xf9, 0x19, 0xe0, 0x54, 
-0x7f, 0x6d, 0x70, 0x0f, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xa3, 0x15, 
-0x49, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 0xdc, 0xe6, 0x80, 0x26, 0xdc, 0x06, 0xd0, 0x82, 0xd0, 0x83, 
-0x80, 0x1e, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 
-0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 
-0x12, 0x10, 0x95, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x85, 0xa8, 
-0x4a, 0x75, 0xa8, 0x88, 0xec, 0x70, 0x02, 0x7c, 0x3f, 0x8c, 0x43, 0x22, 0xe5, 0x44, 0x24, 0x08, 
-0xf8, 0x76, 0x00, 0x12, 0x10, 0xec, 0x80, 0xfb, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x04, 
-0xc0, 0x06, 0x7c, 0xff, 0x12, 0x0f, 0xfe, 0xe5, 0x49, 0x60, 0x42, 0xfe, 0x90, 0xf9, 0x19, 0xe0, 
-0x54, 0x7f, 0x6f, 0x70, 0x0b, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x15, 0x49, 0x80, 0x07, 
-0xa3, 0xa3, 0xa3, 0xde, 0xea, 0x80, 0x26, 0xde, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, 0xd8, 0xe0, 
-0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 
-0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x78, 0x08, 0x08, 
-0x79, 0x18, 0x09, 0x7c, 0x01, 0xe6, 0x54, 0x7f, 0x6f, 0x70, 0x06, 0x76, 0x00, 0x77, 0x00, 0x80, 
-0x06, 0x08, 0x09, 0x0c, 0xbc, 0x08, 0xee, 0x12, 0x10, 0x95, 0xd0, 0x06, 0xd0, 0x04, 0xd0, 0x02, 
-0xd0, 0x01, 0xd0, 0x00, 0x22, 0x75, 0x43, 0x00, 0x85, 0x4a, 0xa8, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 
-0xc0, 0x83, 0xc3, 0xe5, 0x49, 0x24, 0xe8, 0x50, 0x05, 0x12, 0x10, 0xec, 0x80, 0xf4, 0xef, 0x60, 
-0x31, 0x90, 0x2e, 0x2c, 0xe4, 0x93, 0xc3, 0x9f, 0x40, 0x2f, 0xc0, 0x04, 0x7c, 0xff, 0x12, 0x0f, 
-0xfe, 0xd0, 0x04, 0x43, 0x07, 0x80, 0xe5, 0x49, 0x75, 0xf0, 0x03, 0xa4, 0x24, 0x19, 0xf5, 0x82, 
-0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xef, 0xf0, 0xec, 0xa3, 0xf0, 0xed, 0xa3, 0xf0, 0x05, 0x49, 0x12, 
-0x10, 0x95, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x02, 0x11, 0x1a, 0xc0, 0x04, 0x7c, 0x20, 
-0xd2, 0x8c, 0xd2, 0x8d, 0xd5, 0x04, 0xfd, 0xd0, 0x04, 0x22, 0x75, 0xa8, 0x00, 0x75, 0x88, 0x00, 
-0x75, 0xb8, 0x00, 0x75, 0xf0, 0x00, 0x75, 0xd0, 0x00, 0xe4, 0xf8, 0x90, 0xf8, 0x04, 0xf0, 0x90, 
-0x00, 0x00, 0xf6, 0x08, 0xb8, 0x00, 0xfb, 0x02, 0x00, 0x00, 0xc2, 0xaf, 0xe4, 0x90, 0xff, 0x48, 
-0xf0, 0x90, 0xff, 0x50, 0xf0, 0x90, 0xff, 0x08, 0xf0, 0x90, 0xff, 0x10, 0xf0, 0x90, 0xff, 0x80, 
-0xf0, 0xa3, 0xa3, 0xf0, 0xd2, 0xb1, 0xc2, 0xb0, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e, 
-0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0xd2, 0xb0, 0xd2, 
-0xb1, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x7e, 
-0xff, 0x7f, 0xff, 0x12, 0x0f, 0x62, 0x80, 0xcc, 0xc3, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x03, 
-0x7f, 0xe8, 0xef, 0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x48, 0x8e, 
-0x47, 0x22, 0xc3, 0xef, 0x94, 0xbc, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x07, 0x7f, 0xd0, 0xef, 
-0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x46, 0x8e, 0x45, 0x22, 0xef, 
-0x70, 0x01, 0x22, 0xc0, 0x00, 0xe5, 0x44, 0x24, 0x18, 0xf8, 0xa6, 0x07, 0xe5, 0x44, 0x24, 0x08, 
-0xf8, 0xc6, 0x54, 0x7f, 0xf6, 0xe6, 0x30, 0xe7, 0x03, 0xd0, 0x00, 0x22, 0x12, 0x10, 0xec, 0x80, 
+0x90, 0xff, 0x56, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x25, 
+0xb4, 0x02, 0x22, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x27, 
+0x8d, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 
+0x80, 0x03, 0x02, 0x02, 0x62, 0x74, 0x15, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x20, 0x04, 
+0xf1, 0x20, 0x02, 0x03, 0x30, 0x01, 0xeb, 0x74, 0x18, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 
+0x14, 0xfc, 0xf0, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0x64, 0x04, 0x70, 0x0f, 0xec, 0x70, 0x62, 
+0x7e, 0x01, 0x12, 0x00, 0xc9, 0x7c, 0x0a, 0x7d, 0xfa, 0x02, 0x02, 0x33, 0x12, 0x00, 0xc9, 0xee, 
+0x64, 0x04, 0x60, 0x1d, 0xec, 0x70, 0x4b, 0x7c, 0x0a, 0xed, 0x14, 0xfd, 0x70, 0x15, 0xee, 0x64, 
+0x02, 0x60, 0x07, 0x7e, 0x02, 0x7d, 0x32, 0x02, 0x02, 0x33, 0x7e, 0x01, 0x7d, 0xfa, 0x02, 0x02, 
+0x33, 0x7c, 0x0a, 0x74, 0x18, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 
+0xa3, 0xee, 0xf0, 0x14, 0x60, 0x18, 0x20, 0xe1, 0x0f, 0x20, 0x01, 0x06, 0xd2, 0xb1, 0xc2, 0xb0, 
+0x80, 0x10, 0xc2, 0xb1, 0xd2, 0xb0, 0x80, 0x0a, 0xc2, 0xb1, 0xc2, 0xb0, 0x80, 0x04, 0xd2, 0xb0, 
+0xd2, 0xb1, 0x78, 0x19, 0x79, 0x09, 0x7a, 0x07, 0xe7, 0x70, 0x04, 0xa6, 0x00, 0x80, 0x0b, 0xe6, 
+0x60, 0x08, 0x16, 0xe6, 0x70, 0x04, 0xe7, 0x44, 0x80, 0xf7, 0x08, 0x09, 0xda, 0xea, 0xe5, 0x3d, 
+0x60, 0x13, 0x14, 0xf5, 0x3d, 0x70, 0x0e, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, 
+0x0f, 0xd2, 0x8c, 0xd2, 0x8d, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 
+0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, 
+0x90, 0xff, 0x04, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x90, 0xff, 0x06, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 
+0xec, 0xff, 0xea, 0xfe, 0xef, 0xc3, 0x94, 0x08, 0xee, 0x94, 0x01, 0x50, 0x02, 0x80, 0x04, 0x7e, 
+0x01, 0x7f, 0x08, 0x8e, 0x3b, 0x8f, 0x3c, 0x90, 0xff, 0x02, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, 
+0xff, 0xea, 0x90, 0xfa, 0xba, 0xf0, 0xef, 0xa3, 0xf0, 0x12, 0x1c, 0x30, 0xe4, 0xf5, 0x4d, 0xe5, 
+0x4d, 0xc3, 0x94, 0x02, 0x50, 0x0f, 0x12, 0x1c, 0x11, 0xe4, 0x12, 0x1a, 0x38, 0x05, 0x4d, 0x04, 
+0x12, 0x1c, 0x02, 0x80, 0xea, 0x12, 0x1c, 0x30, 0x90, 0xff, 0x00, 0xe0, 0xff, 0x54, 0x60, 0x24, 
+0xc0, 0x70, 0x03, 0x02, 0x08, 0xc5, 0x24, 0x40, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 
+0xe0, 0xfe, 0x54, 0x0f, 0xf5, 0x4d, 0xee, 0x30, 0xe7, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0a, 
+0x90, 0xff, 0x01, 0xe0, 0x12, 0x1b, 0x4c, 0x03, 0x56, 0x00, 0x04, 0x29, 0x01, 0x05, 0x3c, 0x03, 
+0x06, 0x03, 0x05, 0x06, 0x45, 0x06, 0x07, 0xa7, 0x08, 0x07, 0xef, 0x09, 0x08, 0x4b, 0x0a, 0x08, 
+0x8b, 0x0b, 0x00, 0x00, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 
+0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x64, 0x02, 0x45, 
+0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xef, 0x54, 0x1f, 0x14, 0x60, 0x2b, 0x14, 0x60, 0x47, 0x24, 
+0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xee, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0x11, 0x74, 
+0x01, 0x12, 0x1a, 0x38, 0x78, 0x67, 0xe6, 0x30, 0xe0, 0x08, 0x12, 0x1c, 0x11, 0x74, 0x02, 0x12, 
+0x1a, 0x38, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe1, 0x09, 0x90, 0xfa, 0xb6, 0xe0, 
+0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0f, 
+0x26, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe1, 0x0e, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 
+0x60, 0x07, 0x64, 0x80, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0xb2, 0x40, 0x03, 0x02, 0x0f, 
+0x26, 0xe5, 0x4d, 0x70, 0x19, 0x30, 0x0a, 0x0b, 0x90, 0xff, 0x80, 0x12, 0x1c, 0x0e, 0x12, 0x1a, 
+0x38, 0x80, 0x24, 0x90, 0xff, 0x82, 0x12, 0x1c, 0x0e, 0x12, 0x1a, 0x38, 0x80, 0x19, 0x15, 0x4d, 
+0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0x12, 0x1c, 0x0c, 0x12, 0x1a, 0x38, 0x80, 0x09, 0x12, 0x1c, 
+0xb3, 0x12, 0x1c, 0x0c, 0x12, 0x1a, 0x38, 0x12, 0x1c, 0x11, 0x12, 0x19, 0xf2, 0x60, 0x05, 0x74, 
+0x01, 0x12, 0x1a, 0x38, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 
+0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x14, 0x60, 0x2d, 
+0x14, 0x60, 0x59, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x04, 
+0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, 
+0x0f, 0x26, 0x78, 0x67, 0xe6, 0x54, 0xfe, 0xf6, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 
+0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, 0x09, 0x90, 0xfa, 0xb6, 
+0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x0c, 0x90, 0xfa, 0xb6, 0xe0, 0xd3, 
+0x94, 0x01, 0x40, 0x03, 0x02, 0x0f, 0x26, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xfa, 0xba, 0xe0, 
+0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0xb2, 0x40, 0x03, 0x02, 0x0f, 
+0x26, 0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, 
+0x07, 0xe5, 0x4d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x4d, 0x70, 0x0f, 0x90, 0xff, 0x82, 0xe0, 
+0x54, 0xf7, 0xf0, 0x90, 0xff, 0x80, 0xe0, 0x54, 0xf7, 0xf0, 0x22, 0xe5, 0x4d, 0x24, 0xfe, 0x60, 
+0x20, 0x24, 0xfb, 0x60, 0x34, 0x24, 0x06, 0x70, 0x35, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 
+0xfd, 0x7f, 0x03, 0x12, 0x2d, 0xa8, 0x80, 0x26, 0xe4, 0xfd, 0x7f, 0x03, 0x12, 0x2d, 0xa8, 0x80, 
+0x1d, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 0xfd, 0x7f, 0x04, 0x12, 0x2d, 0xa8, 0x80, 0x0e, 
+0xe4, 0xfd, 0x7f, 0x04, 0x12, 0x2d, 0xa8, 0x80, 0x05, 0x7f, 0x87, 0x12, 0x31, 0x32, 0x15, 0x4d, 
+0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0x80, 0x09, 0x12, 0x1c, 
+0xb3, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 
+0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 
+0x14, 0x60, 0x2d, 0x14, 0x60, 0x55, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 
+0xe0, 0x70, 0x04, 0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 
+0x60, 0x03, 0x02, 0x0f, 0x26, 0x78, 0x67, 0xe6, 0x44, 0x01, 0xf6, 0xe4, 0xff, 0x02, 0x31, 0xb1, 
+0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, 0x07, 
+0xe5, 0x4d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x0a, 0xe5, 0x4d, 0xd3, 0x94, 
+0x01, 0x40, 0x03, 0x02, 0x0f, 0x26, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xfa, 0xba, 0xe0, 0x70, 
+0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x12, 0x31, 0x82, 
+0x40, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 
+0xe5, 0x4d, 0x70, 0x09, 0x30, 0x0a, 0x03, 0x02, 0x1d, 0x64, 0x02, 0x1d, 0x2f, 0xe5, 0x35, 0x20, 
+0xe1, 0x03, 0x02, 0x0f, 0x26, 0x15, 0x4d, 0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0xf5, 0x83, 0xe0, 
+0x44, 0x08, 0xf0, 0x80, 0x09, 0x12, 0x1c, 0xb3, 0xf5, 0x83, 0xe0, 0x44, 0x08, 0xf0, 0xe4, 0xff, 
+0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 
+0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 
+0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xbb, 
+0xe0, 0x90, 0xff, 0xff, 0xf0, 0xe0, 0x60, 0x05, 0x43, 0x35, 0x01, 0x80, 0x03, 0x53, 0x35, 0xfe, 
+0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 
+0x3b, 0x70, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 
+0xba, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0x24, 0xfe, 0x60, 0x3a, 0x14, 0x60, 0x75, 0x24, 0x02, 
+0x60, 0x03, 0x02, 0x0f, 0x26, 0xed, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0x30, 0x12, 0x1d, 
+0x5d, 0x7d, 0x03, 0x12, 0x0f, 0x6d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0x2a, 0x90, 0xfa, 
+0xb3, 0xe0, 0xfd, 0xa3, 0x12, 0x1c, 0x7b, 0x12, 0x0f, 0x89, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 
+0xaf, 0x3c, 0x02, 0x0f, 0xba, 0x12, 0x1c, 0x30, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe4, 0x0d, 0x12, 
+0x1d, 0x5d, 0x7d, 0x14, 0x12, 0x0f, 0x6d, 0x60, 0x10, 0x02, 0x0f, 0x26, 0x12, 0x1d, 0x5d, 0x7d, 
+0x04, 0x12, 0x0f, 0xc1, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0x2a, 0x90, 0xfa, 0xb3, 0xe0, 
+0xfd, 0xa3, 0x12, 0x1c, 0x7b, 0x12, 0x0f, 0x89, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, 
+0x02, 0x0f, 0xba, 0x12, 0x1d, 0x5d, 0x7d, 0x05, 0x12, 0x0f, 0xc1, 0x60, 0x03, 0x02, 0x0f, 0x26, 
+0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb3, 0x12, 0x1c, 0x78, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, 
+0xb4, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xbb, 0xe0, 0x90, 0xfa, 0xb2, 0xf0, 
+0xe4, 0xf5, 0x4c, 0x90, 0xfa, 0xb2, 0xe0, 0xff, 0xe5, 0x4c, 0xc3, 0x9f, 0x50, 0x24, 0x12, 0x1c, 
+0x72, 0x12, 0x0f, 0xcc, 0xff, 0xfd, 0x90, 0xfa, 0xb4, 0xe4, 0x8d, 0xf0, 0x12, 0x1a, 0x6c, 0x90, 
+0xfa, 0xb3, 0xe0, 0xc3, 0x9f, 0xf0, 0xd3, 0x94, 0x00, 0x50, 0x03, 0x02, 0x0f, 0x26, 0x05, 0x4c, 
+0x80, 0xd1, 0x12, 0x1c, 0x72, 0x12, 0x0f, 0xcc, 0x24, 0xfe, 0xff, 0x90, 0xfa, 0xb3, 0xf0, 0xfd, 
+0xa3, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x1a, 0x6c, 0x7a, 0xf9, 0x79, 0x6f, 0x7b, 0x01, 0x8b, 0x36, 
+0x8a, 0x37, 0x89, 0x38, 0xe9, 0x24, 0x02, 0xf9, 0xe4, 0x3a, 0xfa, 0x12, 0x1c, 0x78, 0x12, 0x25, 
+0xd7, 0x8f, 0x4c, 0x05, 0x4c, 0x05, 0x4c, 0x12, 0x1c, 0x11, 0xe5, 0x4c, 0x12, 0x1a, 0x38, 0x12, 
+0x1c, 0x11, 0x90, 0x00, 0x01, 0x74, 0x03, 0x12, 0x1a, 0x4a, 0xaf, 0x4c, 0x7e, 0x00, 0xc3, 0xef, 
+0x95, 0x3c, 0xee, 0x95, 0x3b, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, 0x8e, 0x39, 0x8f, 
+0x3a, 0x02, 0x2c, 0x07, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 
+0x3c, 0x64, 0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 
+0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 
+0x12, 0x1c, 0xc9, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 
+0x02, 0x0f, 0x26, 0x75, 0x36, 0x00, 0x75, 0x37, 0x00, 0x75, 0x38, 0x32, 0x02, 0x0f, 0xa9, 0xe5, 
+0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 
+0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xd3, 0x90, 0xfa, 0xbb, 0xe0, 0x94, 0x01, 
+0x90, 0xfa, 0xba, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x60, 0x03, 
+0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 
+0xbb, 0xe0, 0xf5, 0x32, 0xe5, 0x32, 0x70, 0x08, 0x43, 0x35, 0x01, 0x53, 0x35, 0xfd, 0x80, 0x06, 
+0x53, 0x35, 0xfe, 0x43, 0x35, 0x02, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe7, 0x03, 
+0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x64, 0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 
+0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 
+0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 
+0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x7f, 0x01, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, 
+0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xd3, 0x90, 0xfa, 0xbb, 
+0xe0, 0x94, 0x00, 0x90, 0xfa, 0xba, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 
+0xc9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, 
+0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xff, 0x01, 0x12, 0x1d, 0x74, 0xef, 0x12, 0x1a, 0x38, 0x90, 
+0xfa, 0xb6, 0x12, 0x1d, 0x74, 0x90, 0x00, 0x01, 0xef, 0x12, 0x1a, 0x4a, 0x90, 0x00, 0x02, 0xe4, 
+0x12, 0x1a, 0x4a, 0x74, 0x03, 0x12, 0x1c, 0x02, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0xa3, 0xe0, 0x85, 
+0x38, 0x82, 0x85, 0x37, 0x83, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x01, 0xe0, 0x12, 0x1b, 
+0x4c, 0x09, 0x4a, 0x02, 0x09, 0x6c, 0x04, 0x09, 0x8e, 0x05, 0x09, 0xba, 0x06, 0x09, 0xd8, 0x07, 
+0x09, 0xf6, 0x08, 0x0a, 0x14, 0x09, 0x0a, 0x32, 0x0b, 0x0a, 0xe7, 0x80, 0x0d, 0x6f, 0x81, 0x0d, 
+0xa0, 0x82, 0x0b, 0x2e, 0x83, 0x0b, 0x77, 0x84, 0x0b, 0x96, 0x85, 0x0b, 0xdb, 0x86, 0x0c, 0x26, 
+0x87, 0x0c, 0xb7, 0x88, 0x0d, 0x42, 0x89, 0x0a, 0x50, 0x92, 0x0a, 0x50, 0x93, 0x0e, 0x53, 0xc0, 
+0x0e, 0x7f, 0xc1, 0x0e, 0x90, 0xc2, 0x00, 0x00, 0x0f, 0x15, 0xe5, 0x35, 0x20, 0xe7, 0x05, 0x7f, 
+0x05, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 
+0x7f, 0x07, 0x02, 0x11, 0x16, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0x18, 0xe5, 0x35, 0x20, 0xe7, 
+0x05, 0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 
+0x7c, 0x00, 0x7f, 0x0c, 0x02, 0x11, 0x16, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0x18, 0xe5, 0x35, 
+0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1d, 0x92, 0x50, 0x06, 0xe5, 0x3c, 0x45, 0x3b, 0x70, 
+0x05, 0x7f, 0x02, 0x02, 0x30, 0xec, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfe, 0x24, 0xfd, 0x50, 0x02, 
+0x80, 0x03, 0x02, 0x31, 0x6f, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 
+0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x08, 
+0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 
+0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x09, 0x02, 0x11, 
+0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, 
+0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0a, 0x02, 0x11, 0x16, 0x7f, 
+0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, 
+0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0b, 0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, 
+0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 
+0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0e, 0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, 
+0xe5, 0x35, 0x30, 0xe7, 0x56, 0x12, 0x1c, 0xc9, 0x70, 0x4a, 0x90, 0xff, 0x02, 0xe0, 0xf5, 0x4c, 
+0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12, 0xe5, 0x4c, 0xb4, 0x83, 0x05, 0x75, 
+0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 0x4c, 0x12, 0x1b, 0x72, 0x12, 
+0x1d, 0x8b, 0x12, 0x25, 0x39, 0x12, 0x1c, 0xd9, 0x12, 0x1a, 0x0b, 0x60, 0x05, 0x12, 0x31, 0xbd, 
+0x80, 0x06, 0x85, 0x33, 0x39, 0x85, 0x34, 0x3a, 0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75, 0x38, 
+0x72, 0x02, 0x2c, 0x07, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, 0x18, 0x12, 0x1c, 0xc9, 0x60, 0x05, 
+0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x1d, 0x92, 0x40, 0x05, 0x7f, 0x03, 0x02, 0x30, 0xec, 0x90, 
+0xff, 0x02, 0xe0, 0xf5, 0x4c, 0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12, 0xe5, 
+0x4c, 0xb4, 0x83, 0x05, 0x75, 0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 
+0x4c, 0x12, 0x1b, 0x72, 0x02, 0x31, 0x6f, 0x12, 0x1d, 0x9c, 0x12, 0x2a, 0x06, 0x12, 0x1c, 0x83, 
+0xe0, 0x54, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x78, 0x68, 0x12, 0x1b, 
+0x28, 0x90, 0x00, 0x02, 0x12, 0x1a, 0x0b, 0x30, 0xe7, 0xf2, 0x90, 0x00, 0x02, 0xe4, 0x12, 0x1a, 
+0x4a, 0x90, 0xfa, 0xb7, 0xe0, 0x44, 0x80, 0xff, 0xf0, 0x78, 0x7c, 0xe6, 0xfc, 0x08, 0xe6, 0x8c, 
+0x83, 0x12, 0x1c, 0x8b, 0xef, 0xf0, 0x12, 0x31, 0xc7, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x90, 0xfa, 
+0xb6, 0xe0, 0x64, 0x01, 0x70, 0x1f, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06, 0xa3, 
+0xe0, 0xf5, 0x90, 0x80, 0x2d, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0x90, 0x90, 0xfa, 0xbb, 0xe0, 0x42, 
+0x90, 0xd2, 0xaf, 0x80, 0x1d, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06, 0xa3, 0xe0, 
+0xf5, 0xb0, 0x80, 0x0e, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0xb0, 0x90, 0xfa, 0xbb, 0xe0, 0x42, 0xb0, 
+0xd2, 0xaf, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0x30, 0x90, 0xfa, 0xb6, 0xe0, 0xb4, 0x01, 
+0x0a, 0x12, 0x1c, 0x11, 0xe5, 0x90, 0x12, 0x1a, 0x38, 0x80, 0x08, 0x12, 0x1c, 0x11, 0xe5, 0xb0, 
+0x12, 0x1a, 0x38, 0x02, 0x0f, 0xa9, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x24, 0x12, 0x12, 0x1c, 0x41, 
+0x20, 0xe1, 0x33, 0x12, 0x1c, 0xd0, 0xef, 0x24, 0xfc, 0x60, 0x18, 0x04, 0x70, 0x28, 0x90, 0xfa, 
+0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x19, 0x12, 0x1d, 0xa6, 
+0xf0, 0x80, 0x13, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0xf0, 
+0x80, 0x04, 0x12, 0x1d, 0xad, 0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 
+0x24, 0x12, 0x12, 0x1c, 0x41, 0x20, 0xe1, 0x39, 0x12, 0x1c, 0xd0, 0xef, 0x24, 0xfc, 0x60, 0x1b, 
+0x04, 0x70, 0x2e, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 0xf0, 
+0x80, 0x1f, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 
+0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xdf, 
+0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x12, 0x1c, 0xc1, 0x60, 0x4d, 0x04, 0x60, 
+0x03, 0x02, 0x0c, 0xb2, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x0f, 0x90, 0xff, 0xa4, 0x12, 0x1c, 0x3a, 
+0x30, 0xe1, 0x6f, 0x12, 0x1d, 0x7c, 0x02, 0x0c, 0xb2, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfb, 0x12, 
+0x1c, 0x3d, 0xfe, 0x30, 0xe1, 0x5c, 0x30, 0xe2, 0x11, 0x30, 0xb4, 0x05, 0x12, 0x1d, 0x7c, 0x80, 
+0x51, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x48, 0x30, 0x95, 0x05, 0x12, 0x1d, 0x7c, 
+0x80, 0x40, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x37, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 
+0x12, 0x90, 0xff, 0xb4, 0x12, 0x1c, 0x3a, 0x30, 0xe1, 0x28, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 
+0xf0, 0x80, 0x1f, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xfb, 0x12, 0x1c, 0x3d, 0x30, 0xe1, 0x13, 0x30, 
+0x93, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 
+0xfd, 0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfc, 
+0x60, 0x40, 0x04, 0x70, 0x78, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xa2, 0xe0, 0x44, 
+0x40, 0xf0, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x65, 0xd2, 0x03, 0xa3, 0xe0, 0x54, 0xdf, 0xf0, 0x90, 
+0xff, 0xa3, 0xef, 0x54, 0x7f, 0xf0, 0x80, 0x55, 0x30, 0x03, 0x0e, 0x90, 0xff, 0xa3, 0xe0, 0x44, 
+0x80, 0xf0, 0xc2, 0x03, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x54, 0xbf, 0xf0, 
+0x80, 0x3b, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xb2, 0xe0, 0x44, 0x40, 0xf0, 0xa3, 
+0xe0, 0xff, 0x30, 0xe7, 0x28, 0xd2, 0x04, 0xa3, 0xe0, 0x54, 0xdf, 0xf0, 0x90, 0xff, 0xb3, 0xef, 
+0x54, 0x7f, 0xf0, 0x80, 0x18, 0x30, 0x04, 0x0e, 0x90, 0xff, 0xb3, 0xe0, 0x44, 0x80, 0xf0, 0xc2, 
+0x04, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x54, 0xbf, 0xf0, 0xe4, 0xff, 0x02, 
+0x30, 0xec, 0x12, 0x1c, 0x30, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfc, 0x60, 0x0f, 0x04, 0x70, 0x16, 
+0x90, 0xff, 0xa6, 0xe0, 0x12, 0x1c, 0x11, 0x12, 0x1a, 0x38, 0x80, 0x0a, 0x90, 0xff, 0xb6, 0xe0, 
+0x12, 0x1c, 0x11, 0x12, 0x1a, 0x38, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, 0x2c, 0x07, 0xe4, 
+0xff, 0x12, 0x30, 0xec, 0x12, 0x1d, 0x37, 0x7f, 0x03, 0x12, 0x12, 0x19, 0x90, 0xf9, 0x15, 0xe0, 
+0x30, 0xe4, 0x08, 0x90, 0xff, 0x93, 0x74, 0x80, 0xf0, 0x80, 0x10, 0x90, 0xff, 0xfc, 0xe0, 0x54, 
+0x7f, 0xf0, 0x7f, 0xff, 0x7e, 0x00, 0x12, 0x30, 0x16, 0xc2, 0x90, 0xc2, 0xaf, 0x00, 0x80, 0xfd, 
+0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x90, 0xfa, 0xbc, 0x74, 0x3e, 0xf0, 0xa3, 0xe4, 0xf0, 0x90, 0xfa, 
+0xb4, 0xf0, 0xa3, 0x74, 0x15, 0xf0, 0xe0, 0x54, 0x3f, 0xff, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0xfa, 
+0xb9, 0xf0, 0xd3, 0x94, 0x00, 0xe4, 0x94, 0x3e, 0x40, 0x08, 0x90, 0xfa, 0xbd, 0xe0, 0x90, 0xfa, 
+0xb9, 0xf0, 0x12, 0x0f, 0x50, 0xe5, 0x31, 0x45, 0x30, 0x70, 0x73, 0x12, 0x1c, 0x4a, 0x90, 0xfa, 
+0xbc, 0x12, 0x1d, 0x56, 0x60, 0x27, 0xd3, 0xef, 0x94, 0x40, 0xee, 0x94, 0x00, 0x40, 0x08, 0x90, 
+0xfa, 0xb9, 0x74, 0x40, 0xf0, 0x80, 0x08, 0x90, 0xfa, 0xbd, 0xe0, 0x90, 0xfa, 0xb9, 0xf0, 0x12, 
+0x0f, 0x50, 0xe5, 0x31, 0x45, 0x30, 0x70, 0x46, 0x12, 0x1c, 0x4a, 0x80, 0xd1, 0x75, 0x4c, 0x02, 
+0x90, 0xfa, 0xbc, 0xe4, 0xf0, 0xa3, 0x04, 0xf0, 0x90, 0xfa, 0xb4, 0xe4, 0xf0, 0xa3, 0x74, 0x0f, 
+0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0x90, 0xfa, 0xbd, 0xe0, 0xf5, 0x4a, 0x7d, 0x0f, 0x7c, 
+0x00, 0x12, 0x28, 0x9f, 0x75, 0x30, 0x00, 0x8f, 0x31, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0xe4, 
+0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0xe4, 0xf5, 0x30, 0xf5, 0x31, 0xaf, 0x31, 
+0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x30, 0xe7, 0x10, 0xe0, 0x54, 0x0f, 0x90, 0xf9, 0x64, 0xf0, 
+0xd3, 0x94, 0x00, 0x40, 0x15, 0xc2, 0x95, 0x80, 0x11, 0x90, 0xfa, 0xb7, 0xe0, 0x54, 0x0f, 0x90, 
+0xf9, 0x63, 0xf0, 0xd3, 0x94, 0x00, 0x40, 0x02, 0xc2, 0x94, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 
+0x1d, 0x9c, 0xbf, 0x01, 0x04, 0xd2, 0x93, 0x80, 0x02, 0xc2, 0x93, 0xe4, 0xff, 0x02, 0x30, 0xec, 
+0x12, 0x1c, 0xd0, 0x54, 0x03, 0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 
+0x70, 0x2b, 0xd2, 0x91, 0x80, 0x27, 0xc2, 0x91, 0x80, 0x23, 0x12, 0x1d, 0xa6, 0x12, 0x0f, 0x78, 
+0x60, 0x04, 0xd2, 0x91, 0x80, 0x17, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x10, 0x12, 0x0f, 0x78, 0xff, 
+0xbf, 0xa0, 0x04, 0xc2, 0x91, 0x80, 0x02, 0xd2, 0x91, 0x12, 0x1d, 0xa6, 0xf0, 0x90, 0xfa, 0xb7, 
+0xe0, 0x54, 0x0c, 0xff, 0x13, 0x13, 0x54, 0x3f, 0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 
+0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x92, 0x80, 0x27, 0xc2, 0x92, 0x80, 0x23, 0x12, 0x1d, 0xad, 
+0x12, 0x0f, 0x98, 0x60, 0x04, 0xd2, 0x92, 0x80, 0x17, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0x12, 
+0x0f, 0x98, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x92, 0x80, 0x02, 0xd2, 0x92, 0x12, 0x1d, 0xad, 0xf0, 
+0xe4, 0xff, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x07, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, 
+0x18, 0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x31, 0xbd, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb3, 
+0x90, 0xfa, 0xb4, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 
+0xfa, 0xb4, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x22, 
+0xaa, 0x4e, 0xa9, 0x4f, 0x7b, 0xff, 0x90, 0xfa, 0xb4, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 
+0xb9, 0xe0, 0xf5, 0x4a, 0x12, 0x28, 0x9f, 0x75, 0x30, 0x00, 0x8f, 0x31, 0x22, 0x12, 0x22, 0xa0, 
+0x7e, 0x00, 0x8e, 0x30, 0x8f, 0x31, 0xef, 0x22, 0xf0, 0x7f, 0x01, 0x12, 0x12, 0x19, 0x90, 0xff, 
+0xa6, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x54, 0xa0, 0x22, 0x12, 0x25, 0xd7, 0x8f, 0x4c, 0x7e, 0x00, 
+0xc3, 0xef, 0x95, 0x3c, 0xee, 0x95, 0x3b, 0x22, 0xf0, 0x7f, 0x01, 0x12, 0x12, 0x19, 0x90, 0xff, 
+0xb6, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x54, 0xa0, 0x22, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, 
+0x2c, 0x07, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x02, 0x31, 0x82, 0x8e, 0x39, 0x8f, 0x3a, 0x02, 0x2c, 
+0x07, 0x12, 0x22, 0xa0, 0x7e, 0x00, 0x8e, 0x30, 0x8f, 0x31, 0xef, 0x22, 0x7d, 0x01, 0x12, 0x25, 
+0xd7, 0x90, 0xfa, 0xb1, 0xe0, 0x22, 0xef, 0x90, 0xf8, 0x04, 0xf0, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 
+0xee, 0x60, 0x0a, 0xc0, 0x05, 0x7d, 0x7f, 0xdd, 0xfe, 0xde, 0xfa, 0xd0, 0x05, 0xef, 0xc3, 0x94, 
+0x15, 0x50, 0x03, 0xd0, 0xa8, 0x22, 0x13, 0x70, 0x03, 0xd0, 0xa8, 0x22, 0xff, 0xd5, 0x07, 0xfd, 
+0xd0, 0xa8, 0x22, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x04, 0xc0, 0x05, 0xe5, 0x3e, 0x24, 
+0x08, 0xf8, 0x86, 0x05, 0x53, 0x05, 0x7f, 0x7c, 0xff, 0x12, 0x10, 0x78, 0x7f, 0x00, 0x7e, 0x00, 
+0xe5, 0x43, 0x60, 0x46, 0xfc, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x7f, 0x6d, 0x70, 0x0f, 0xc0, 0x83, 
+0xc0, 0x82, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xa3, 0x15, 0x43, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 
+0xdc, 0xe6, 0x80, 0x26, 0xdc, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, 0x1e, 0xe0, 0xf8, 0xa3, 0xe0, 
+0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 
+0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x12, 0x11, 0x0f, 0xd0, 0x05, 0xd0, 
+0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x85, 0xa8, 0x44, 0x75, 0xa8, 0x88, 0xec, 0x70, 
+0x02, 0x7c, 0x3f, 0x8c, 0x3d, 0x22, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, 0x66, 
+0x80, 0xfb, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x04, 0xc0, 0x06, 0x7c, 0xff, 0x12, 0x10, 
+0x78, 0xe5, 0x43, 0x60, 0x42, 0xfe, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x7f, 0x6f, 0x70, 0x0b, 0xc0, 
+0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x15, 0x43, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 0xde, 0xea, 0x80, 
+0x26, 0xde, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, 0xd8, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 
+0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 
+0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x78, 0x08, 0x08, 0x79, 0x18, 0x09, 0x7c, 0x01, 0xe6, 
+0x54, 0x7f, 0x6f, 0x70, 0x06, 0x76, 0x00, 0x77, 0x00, 0x80, 0x06, 0x08, 0x09, 0x0c, 0xbc, 0x08, 
+0xee, 0x12, 0x11, 0x0f, 0xd0, 0x06, 0xd0, 0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x75, 
+0x3d, 0x00, 0x85, 0x44, 0xa8, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc3, 0xe5, 0x43, 0x24, 
+0xe8, 0x50, 0x05, 0x12, 0x11, 0x66, 0x80, 0xf4, 0xef, 0x60, 0x31, 0x90, 0x30, 0x54, 0xe4, 0x93, 
+0xc3, 0x9f, 0x40, 0x2f, 0xc0, 0x04, 0x7c, 0xff, 0x12, 0x10, 0x78, 0xd0, 0x04, 0x43, 0x07, 0x80, 
+0xe5, 0x43, 0x75, 0xf0, 0x03, 0xa4, 0x24, 0x1b, 0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xef, 
+0xf0, 0xec, 0xa3, 0xf0, 0xed, 0xa3, 0xf0, 0x05, 0x43, 0x12, 0x11, 0x0f, 0xd0, 0x83, 0xd0, 0x82, 
+0xd0, 0xf0, 0x22, 0x02, 0x11, 0x94, 0xc0, 0x04, 0x7c, 0x20, 0xd2, 0x8c, 0xd2, 0x8d, 0xd5, 0x04, 
+0xfd, 0xd0, 0x04, 0x22, 0x75, 0xa8, 0x00, 0x75, 0x88, 0x00, 0x75, 0xb8, 0x00, 0x75, 0xf0, 0x00, 
+0x75, 0xd0, 0x00, 0xe4, 0xf8, 0x90, 0xf8, 0x04, 0xf0, 0x90, 0x00, 0x00, 0xf6, 0x08, 0xb8, 0x00, 
+0xfb, 0x02, 0x00, 0x00, 0xc2, 0xaf, 0xe4, 0x90, 0xff, 0x48, 0xf0, 0x90, 0xff, 0x50, 0xf0, 0x90, 
+0xff, 0x08, 0xf0, 0x90, 0xff, 0x10, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xa3, 0xa3, 0xf0, 0xd2, 0xb1, 
+0xc2, 0xb0, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 
+0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0xd2, 0xb0, 0xd2, 0xb1, 0x7e, 0xff, 0x7f, 0xff, 0x12, 
+0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 
+0x80, 0xcc, 0xc3, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x03, 0x7f, 0xe8, 0xef, 0xf4, 0xff, 0xee, 
+0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x42, 0x8e, 0x41, 0x22, 0xc3, 0xef, 0x94, 0xbc, 
+0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x07, 0x7f, 0xd0, 0xef, 0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 
+0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x40, 0x8e, 0x3f, 0x22, 0xef, 0x70, 0x01, 0x22, 0xc0, 0x00, 0xc0, 
+0xa8, 0xc2, 0xaf, 0xe5, 0x3e, 0x24, 0x18, 0xf8, 0xa6, 0x07, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0xc6, 
+0x54, 0x7f, 0xf6, 0xd0, 0xa8, 0xe6, 0x30, 0xe7, 0x03, 0xd0, 0x00, 0x22, 0x12, 0x11, 0x66, 0x80, 
 0xf4, 0xc0, 0x00, 0x7f, 0x01, 0xef, 0x24, 0x08, 0xf8, 0xe6, 0x60, 0x09, 0x0f, 0xbf, 0x08, 0xf5, 
-0x12, 0x10, 0xec, 0x80, 0xee, 0xd0, 0x00, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 
-0xc0, 0x06, 0xc0, 0x04, 0xed, 0x24, 0x10, 0xf8, 0x76, 0xa0, 0xed, 0x75, 0xf0, 0x21, 0xa4, 0x24, 
+0x12, 0x11, 0x66, 0x80, 0xee, 0xd0, 0x00, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 
+0xc0, 0x06, 0xc0, 0x04, 0xed, 0x24, 0x10, 0xf8, 0x76, 0x9a, 0xed, 0x75, 0xf0, 0x21, 0xa4, 0x24, 
 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0xc0, 0x82, 0xc0, 0x83, 0xa3, 0xa3, 0xe4, 0x78, 
-0x0d, 0xf0, 0xa3, 0xd8, 0xfc, 0xef, 0x54, 0x7f, 0x75, 0xf0, 0x02, 0xa4, 0x24, 0x0e, 0xf5, 0x82, 
-0xe5, 0xf0, 0x34, 0x2e, 0xf5, 0x83, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xfc, 0xd0, 0x83, 0xd0, 
+0x0d, 0xf0, 0xa3, 0xd8, 0xfc, 0xef, 0x54, 0x7f, 0x75, 0xf0, 0x02, 0xa4, 0x24, 0x36, 0xf5, 0x82, 
+0xe5, 0xf0, 0x34, 0x30, 0xf5, 0x83, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xfc, 0xd0, 0x83, 0xd0, 
 0x82, 0xec, 0xf0, 0xa3, 0xee, 0xf0, 0xed, 0x24, 0x08, 0xf8, 0xef, 0x44, 0x80, 0xf6, 0xd0, 0x04, 
-0xd0, 0x06, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x75, 0x44, 0x00, 0x75, 0x49, 
+0xd0, 0x06, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x75, 0x3e, 0x00, 0x75, 0x43, 
 0x00, 0x7a, 0x08, 0x79, 0x18, 0x78, 0x08, 0x76, 0x00, 0x77, 0x00, 0x08, 0x09, 0xda, 0xf8, 0x90, 
-0xf8, 0x04, 0xe0, 0xfc, 0x90, 0x2e, 0x2c, 0xe4, 0x93, 0xc3, 0x9c, 0x50, 0x05, 0xe4, 0x90, 0xf8, 
+0xf8, 0x04, 0xe0, 0xfc, 0x90, 0x30, 0x54, 0xe4, 0x93, 0xc3, 0x9c, 0x50, 0x05, 0xe4, 0x90, 0xf8, 
 0x04, 0xf0, 0x78, 0x08, 0x74, 0x80, 0x44, 0x7f, 0xf6, 0x74, 0x01, 0x44, 0x10, 0xf5, 0x89, 0x75, 
-0xb8, 0x00, 0xd2, 0xab, 0xd2, 0xa9, 0x22, 0x75, 0x81, 0x91, 0xd2, 0x8e, 0xd2, 0x8c, 0xd2, 0xaf, 
-0xe5, 0x49, 0x60, 0x36, 0xff, 0x90, 0xf9, 0x19, 0xe0, 0x54, 0x80, 0x60, 0x28, 0x78, 0x08, 0x79, 
+0xb8, 0x00, 0xd2, 0xab, 0xd2, 0xa9, 0x22, 0x75, 0x81, 0x8b, 0xd2, 0x8e, 0xd2, 0x8c, 0xd2, 0xaf, 
+0xe5, 0x43, 0x60, 0x36, 0xff, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x80, 0x60, 0x28, 0x78, 0x08, 0x79, 
 0x08, 0xe0, 0x54, 0x7f, 0xfa, 0x7b, 0x00, 0xe6, 0x54, 0x7f, 0xb5, 0x02, 0x02, 0x7b, 0xff, 0x08, 
-0xd9, 0xf5, 0xeb, 0x70, 0x10, 0xea, 0xf0, 0xc0, 0x07, 0x12, 0x11, 0xc1, 0xad, 0x07, 0xaf, 0x02, 
-0x12, 0x11, 0xd8, 0xd0, 0x07, 0xa3, 0xa3, 0xa3, 0xdf, 0xce, 0x12, 0x10, 0xec, 0x80, 0xc1, 0xe7, 
-0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e, 0x88, 
-0x82, 0x8c, 0x83, 0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08, 0xdf, 
-0xfa, 0x80, 0x78, 0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83, 0xe3, 
-0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x64, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf6, 0x08, 0xdf, 
-0xfa, 0x80, 0x58, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x4c, 0x80, 
-0xd2, 0x80, 0xfa, 0x80, 0xc6, 0x80, 0xd4, 0x80, 0x69, 0x80, 0xf2, 0x80, 0x33, 0x80, 0x10, 0x80, 
-0xa6, 0x80, 0xea, 0x80, 0x9a, 0x80, 0xa8, 0x80, 0xda, 0x80, 0xe2, 0x80, 0xca, 0x80, 0x33, 0x89, 
-0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 
-0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0x0d, 
-0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf6, 0x08, 0xdf, 0xf9, 0xec, 0xfa, 0xa9, 0xf0, 0xed, 
-0xfb, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 
-0x83, 0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xea, 0xde, 0xe8, 
-0x80, 0xdb, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc, 0x88, 
-0xf0, 0xef, 0x60, 0x01, 0x0e, 0x4e, 0x60, 0xc3, 0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00, 
-0x50, 0xb9, 0xf5, 0x82, 0xeb, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xaf, 0x23, 0x23, 0x45, 0x82, 
-0x23, 0x90, 0x13, 0x0f, 0x73, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 
-0xe7, 0x22, 0xbb, 0xfe, 0x02, 0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 
-0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50, 0x06, 0xe9, 
-0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22, 0xe5, 0x82, 
-0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x06, 0x89, 0x82, 
-0x8a, 0x83, 0xf0, 0x22, 0x50, 0x02, 0xf7, 0x22, 0xbb, 0xfe, 0x01, 0xf3, 0x22, 0xf8, 0xbb, 0x01, 
-0x0d, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0, 0x22, 0x50, 0x06, 
-0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x22, 0xbb, 0xfe, 0x05, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0x22, 0xc5, 
-0xf0, 0xf8, 0xa3, 0xe0, 0x28, 0xf0, 0xc5, 0xf0, 0xf8, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 
-0x83, 0xe0, 0x38, 0xf0, 0x22, 0xa3, 0xf8, 0xe0, 0xc5, 0xf0, 0x25, 0xf0, 0xf0, 0xe5, 0x82, 0x15, 
-0x82, 0x70, 0x02, 0x15, 0x83, 0xe0, 0xc8, 0x38, 0xf0, 0xe8, 0x22, 0xbb, 0x01, 0x10, 0xe5, 0x82, 
-0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0, 0xa3, 0xe0, 0x22, 0x50, 0x09, 
-0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe, 0x0a, 0xe9, 0x25, 0x82, 0xf8, 
-0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83, 0xe9, 0x93, 0xf5, 0xf0, 0xa3, 
-0xe9, 0x93, 0x22, 0xbb, 0x01, 0x0a, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0xe5, 0xf0, 0xa3, 0xf0, 0x22, 
-0x50, 0x06, 0xf7, 0x09, 0xa7, 0xf0, 0x19, 0x22, 0xbb, 0xfe, 0x06, 0xf3, 0xe5, 0xf0, 0x09, 0xf3, 
-0x19, 0x22, 0xf8, 0xbb, 0x01, 0x11, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 
-0xe8, 0xf0, 0xe5, 0xf0, 0xa3, 0xf0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x08, 0xa6, 
-0xf0, 0x22, 0xbb, 0xfe, 0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0xe5, 0xf0, 0x08, 0xf2, 0x22, 0xa4, 
-0x25, 0x82, 0xf5, 0x82, 0xe5, 0xf0, 0x35, 0x83, 0xf5, 0x83, 0x22, 0xe6, 0xfb, 0x08, 0xe6, 0xfa, 
-0x08, 0xe6, 0xf9, 0x22, 0xeb, 0xf6, 0x08, 0xea, 0xf6, 0x08, 0xe9, 0xf6, 0x22, 0xe0, 0xfb, 0xa3, 
-0xe0, 0xfa, 0xa3, 0xe0, 0xf9, 0x22, 0xeb, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xe9, 0xf0, 0x22, 0xd0, 
-0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 
-0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 
-0xa3, 0xa3, 0xa3, 0x80, 0xdf, 0x90, 0xff, 0xfa, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x16, 0xf0, 0x90, 
-0xff, 0xf9, 0x74, 0x02, 0xf0, 0x90, 0xfa, 0xcb, 0xe4, 0xf0, 0xa3, 0x74, 0x0b, 0xf0, 0x7b, 0x00, 
-0x7a, 0x00, 0x79, 0x37, 0x75, 0x40, 0x00, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0xe5, 0x37, 
-0x24, 0x80, 0x90, 0xff, 0xf8, 0xf0, 0xe5, 0x37, 0x64, 0x07, 0x60, 0x0b, 0xe5, 0x37, 0x64, 0x06, 
-0x60, 0x05, 0xe5, 0x37, 0xb4, 0x14, 0x1b, 0xd2, 0x94, 0xd2, 0x95, 0xd2, 0x92, 0xd2, 0x93, 0xe5, 
-0x37, 0xb4, 0x07, 0x08, 0x90, 0xf9, 0x65, 0x74, 0x02, 0xf0, 0x80, 0x06, 0x90, 0xf9, 0x65, 0x74, 
-0x01, 0xf0, 0x90, 0xfa, 0xcb, 0xe4, 0xf0, 0xa3, 0x74, 0x0d, 0xf0, 0x12, 0x17, 0x71, 0x90, 0xff, 
-0xf5, 0xe5, 0x37, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcb, 0xe4, 0xfd, 0x12, 0x20, 0xc5, 0x90, 
-0xfa, 0xcb, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x14, 0x2f, 0x12, 0x17, 0x71, 0xe5, 0x37, 0x30, 0xe7, 
-0x02, 0xd2, 0x02, 0xe4, 0xf5, 0x2c, 0xf5, 0x2a, 0xf5, 0x2b, 0xf5, 0x29, 0x12, 0x19, 0x92, 0x12, 
-0x18, 0x49, 0x12, 0x19, 0x6c, 0x90, 0xf9, 0x66, 0x12, 0x15, 0x06, 0x90, 0xf9, 0x6b, 0x12, 0x15, 
-0x06, 0x90, 0xff, 0xff, 0xe4, 0xf0, 0x90, 0xff, 0x83, 0xe0, 0xe4, 0xf0, 0x90, 0xff, 0x81, 0x74, 
-0x80, 0xf0, 0xa3, 0x74, 0x84, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xe4, 0xf5, 0x37, 0xe5, 0x37, 0x12, 
-0x18, 0xbf, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x37, 0x12, 0x18, 0xcd, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 
-0x37, 0xe5, 0x37, 0xb4, 0x07, 0xe7, 0x78, 0x80, 0x76, 0xfe, 0x08, 0x76, 0xf0, 0x90, 0x2f, 0x06, 
-0xe4, 0x93, 0xff, 0x78, 0x7e, 0xf6, 0xfd, 0xad, 0x07, 0x90, 0x2f, 0x13, 0xe4, 0x93, 0xff, 0x08, 
-0xf6, 0xff, 0xed, 0x54, 0x0f, 0xfd, 0x12, 0x18, 0xaf, 0x74, 0x84, 0xf0, 0xed, 0x75, 0xf0, 0x08, 
-0xa4, 0x24, 0x47, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xc3, 0x74, 0xf0, 0x9f, 
-0x78, 0x81, 0xf6, 0x74, 0xfe, 0x94, 0x00, 0x18, 0x12, 0x18, 0x41, 0xce, 0xc3, 0x13, 0xce, 0x13, 
-0xd8, 0xf9, 0xff, 0xed, 0x12, 0x19, 0x07, 0xef, 0xf0, 0xed, 0x12, 0x19, 0x2d, 0xe4, 0xf5, 0x37, 
-0xe5, 0x37, 0x90, 0x2f, 0x00, 0x93, 0xff, 0x78, 0x7e, 0xf6, 0xfd, 0xe5, 0x37, 0x25, 0xe0, 0x24, 
-0x07, 0xf5, 0x82, 0xe4, 0x34, 0x2f, 0xf5, 0x83, 0xe4, 0x93, 0x08, 0xf6, 0xed, 0x30, 0xe7, 0x53, 
-0x18, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x18, 0xaf, 0x12, 0x19, 0x15, 0x24, 0x47, 0xf5, 0x82, 0xe4, 
-0x34, 0xff, 0x12, 0x18, 0x31, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0xe9, 0x12, 0x19, 
-0x07, 0xef, 0xf0, 0x12, 0x18, 0x38, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x19, 0x1a, 
-0x24, 0x45, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x12, 0x19, 0x2d, 0xe9, 
-0x75, 0xf0, 0x08, 0xa4, 0x24, 0x46, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 0xf0, 
-0x02, 0x17, 0x46, 0x78, 0x7e, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x18, 0xf9, 0x12, 0x19, 0x15, 0x24, 
-0x07, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x12, 0x18, 0x31, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 
-0x12, 0x19, 0x1a, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0x12, 0x18, 
-0x38, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x19, 0x1a, 0x24, 0x05, 0xf5, 0x82, 0xe4, 
-0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 0xe4, 
-0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 0xe4, 
-0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 0x37, 0xe5, 0x37, 0x64, 0x04, 0x60, 0x03, 0x02, 0x16, 
-0x70, 0x90, 0x2f, 0x05, 0xe4, 0x93, 0xff, 0x78, 0x7e, 0xf6, 0x12, 0x18, 0xf7, 0xe4, 0xf0, 0x90, 
-0x2f, 0x04, 0x93, 0xff, 0xf6, 0x12, 0x18, 0xad, 0xe4, 0xf0, 0x90, 0xff, 0xfd, 0x74, 0x05, 0xf0, 
-0x22, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x37, 0x90, 0xfa, 0xcb, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x14, 
-0x45, 0x85, 0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x02, 0x23, 0xee, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, 
-0x2f, 0xe5, 0x52, 0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, 
-0x2e, 0xab, 0x2d, 0xfa, 0xa9, 0x2f, 0x74, 0x11, 0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 
-0x2f, 0xe4, 0x35, 0x2e, 0xf5, 0x2e, 0x90, 0xff, 0x06, 0xe0, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 
-0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, 0x2e, 0xab, 0x2d, 
-0xfa, 0xa9, 0x2f, 0xe4, 0x12, 0x13, 0xfb, 0x04, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, 
-0x2e, 0xab, 0x2d, 0xfa, 0xa9, 0x2f, 0xe4, 0x12, 0x13, 0xfb, 0x04, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 
-0x35, 0x2e, 0xf5, 0x2e, 0x90, 0xff, 0x04, 0xe0, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 0x12, 0x13, 
-0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 0x35, 0x2e, 0xf5, 0x2e, 0x90, 0xff, 0x05, 0xe0, 
-0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 0x12, 0x13, 0xfb, 0x74, 0x01, 0x25, 0x2f, 0xf5, 0x2f, 0xe4, 
-0x35, 0x2e, 0xf5, 0x2e, 0x22, 0xf5, 0x83, 0xe0, 0x54, 0x08, 0xab, 0x2d, 0xaa, 0x2e, 0xa9, 0x2f, 
-0x22, 0xf5, 0x83, 0xef, 0xf0, 0xfd, 0x7c, 0x00, 0xc3, 0x78, 0x81, 0xe6, 0x9d, 0xf6, 0x18, 0xe6, 
-0x9c, 0xf6, 0xe6, 0xfe, 0x08, 0xe6, 0x78, 0x03, 0x22, 0x75, 0x2d, 0x01, 0x75, 0x2e, 0xf9, 0x75, 
-0x2f, 0x6e, 0x22, 0x90, 0xfa, 0xba, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x90, 0xfa, 0xb5, 0xe0, 0x24, 
-0xfc, 0x22, 0x90, 0xfa, 0xb8, 0xe0, 0xff, 0x7e, 0x00, 0xc3, 0x90, 0xfa, 0xbc, 0xe0, 0x9f, 0xf0, 
-0x90, 0xfa, 0xbb, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, 0xb3, 0xee, 0x8f, 0xf0, 0x12, 0x14, 0x2f, 0xef, 
-0x25, 0x55, 0xf5, 0x55, 0xee, 0x35, 0x54, 0xf5, 0x54, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb0, 
-0x90, 0xfa, 0xb3, 0xe0, 0xf5, 0x40, 0xa3, 0xe0, 0xf5, 0x41, 0x22, 0x78, 0x82, 0xe6, 0xfe, 0x08, 
-0xe6, 0x8e, 0x83, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x54, 0x0f, 0x75, 
-0xf0, 0x08, 0xa4, 0x24, 0x40, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0xe5, 0x53, 0x75, 
-0xf0, 0x08, 0xa4, 0x24, 0x48, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x22, 0xe5, 0x53, 0x75, 0xf0, 0x08, 
-0xa4, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x22, 0x90, 0xff, 0x00, 0xe0, 0x54, 0x1f, 0x22, 
-0x90, 0xfa, 0xb5, 0xe0, 0xff, 0x24, 0xfc, 0x22, 0x75, 0x2a, 0x00, 0x8f, 0x2b, 0x90, 0xf9, 0x6b, 
-0x12, 0x14, 0xfd, 0x90, 0x00, 0x02, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 
-0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x41, 0xf5, 0x82, 0xe4, 
-0x34, 0xff, 0xf5, 0x83, 0x22, 0x74, 0x80, 0xf0, 0x08, 0xe6, 0xff, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 
-0x22, 0x74, 0xae, 0x25, 0x36, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0x22, 0x75, 0xf0, 0x08, 
-0xa4, 0x24, 0x42, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 0xf0, 0x22, 0x90, 0xff, 
-0x82, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x03, 0xf0, 0x90, 0xff, 0xfc, 
-0xe0, 0x54, 0xfd, 0xf0, 0x22, 0x78, 0x6d, 0xe6, 0x54, 0xfd, 0xf6, 0x90, 0xff, 0xfd, 0x74, 0x65, 
-0xf0, 0x22, 0x12, 0x14, 0xdf, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x22, 0x7b, 0x01, 0x7a, 0xf9, 
-0x79, 0x6e, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb3, 0x22, 0x90, 0xff, 0x80, 0xe0, 0x44, 0x08, 
-0xf0, 0x22, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x7f, 0xf0, 0x22, 0xe0, 0xff, 0x90, 0xf9, 0x66, 0x02, 
-0x14, 0xfd, 0x75, 0x30, 0x01, 0x75, 0x31, 0x09, 0x22, 0xd3, 0xe5, 0x35, 0x94, 0x08, 0xe5, 0x34, 
-0x94, 0x01, 0x22, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0x90, 0xfa, 0xb6, 0xf0, 0x22, 0x90, 0xff, 0xa4, 
-0xe0, 0x54, 0xef, 0x22, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xef, 0x22, 0x8f, 0x38, 0x12, 0x27, 0x19, 
-0x78, 0x86, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x08, 0x12, 0x20, 0x25, 0xe0, 0xfd, 
-0x12, 0x20, 0xa6, 0x8a, 0x83, 0x24, 0x0a, 0x12, 0x20, 0x25, 0xed, 0xf0, 0x12, 0x20, 0x7c, 0x24, 
-0x07, 0x12, 0x20, 0x25, 0xe0, 0xff, 0x12, 0x20, 0xbe, 0x24, 0x09, 0x12, 0x20, 0x25, 0xef, 0xf0, 
-0x90, 0xf9, 0x65, 0xe0, 0x30, 0xe4, 0x20, 0x08, 0x12, 0x20, 0x2f, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 
-0xe0, 0x25, 0xe0, 0xff, 0x05, 0x82, 0xd5, 0x82, 0x02, 0x15, 0x83, 0x15, 0x82, 0xe0, 0x33, 0xd0, 
-0x82, 0xd0, 0x83, 0xf0, 0xa3, 0xef, 0xf0, 0x78, 0x86, 0x12, 0x20, 0x2f, 0xe0, 0xfc, 0xa3, 0xe0, 
-0xfd, 0xec, 0xff, 0x12, 0x20, 0xa6, 0x8a, 0x83, 0x24, 0x08, 0x12, 0x20, 0x25, 0xef, 0xf0, 0xed, 
-0x12, 0x20, 0xbe, 0x24, 0x07, 0x12, 0x20, 0x25, 0xed, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 
-0xe0, 0xff, 0x53, 0x07, 0xc7, 0x08, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x12, 0x20, 0x69, 0xa3, 0xe0, 
-0x30, 0xe3, 0x12, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x05, 0x12, 0x20, 0x25, 0xe0, 0x90, 
-0x2f, 0x4d, 0x93, 0x42, 0x07, 0x53, 0x07, 0xfb, 0x12, 0x20, 0xae, 0x24, 0x06, 0x12, 0x20, 0x25, 
-0xe0, 0x60, 0x03, 0x43, 0x07, 0x04, 0x53, 0x07, 0xfc, 0x78, 0x86, 0x12, 0x20, 0x96, 0x24, 0x04, 
-0x12, 0x20, 0x25, 0xe0, 0x42, 0x07, 0x43, 0x07, 0x80, 0x12, 0x20, 0xa6, 0xf5, 0x82, 0x8a, 0x83, 
-0xa3, 0xa3, 0xef, 0xf0, 0x12, 0x20, 0xbe, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0xff, 0x8d, 0x82, 
-0x8c, 0x83, 0xa3, 0xa3, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe1, 0x05, 0x53, 0x07, 0xdf, 0x80, 
-0x03, 0x43, 0x07, 0x20, 0xec, 0x30, 0xe4, 0x05, 0x53, 0x07, 0xef, 0x80, 0x03, 0x43, 0x07, 0x10, 
-0x90, 0xf9, 0x65, 0xe0, 0xfe, 0x54, 0x03, 0x60, 0x4c, 0x53, 0x07, 0xdf, 0xee, 0x30, 0xe1, 0x42, 
-0x12, 0x20, 0xae, 0x24, 0x09, 0x12, 0x20, 0x25, 0xe0, 0x14, 0x60, 0x31, 0x14, 0x60, 0x29, 0x14, 
-0x60, 0x26, 0x14, 0x60, 0x28, 0x24, 0x04, 0x70, 0x2c, 0xe5, 0x38, 0xb4, 0x03, 0x0d, 0x30, 0x95, 
-0x05, 0x43, 0x07, 0x02, 0x80, 0x1f, 0x53, 0x07, 0xfd, 0x80, 0x1a, 0x30, 0x93, 0x05, 0x43, 0x07, 
-0x02, 0x80, 0x12, 0x53, 0x07, 0xfd, 0x80, 0x0d, 0x43, 0x07, 0x02, 0x80, 0x08, 0x53, 0x07, 0xfd, 
-0x80, 0x03, 0x53, 0x07, 0xfd, 0x12, 0x20, 0x94, 0x24, 0x04, 0x12, 0x20, 0x25, 0xef, 0xf0, 0x8d, 
-0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xff, 0x90, 0xf9, 0x65, 0xe0, 0xfe, 0x54, 0x03, 0x60, 
-0x4a, 0xee, 0x30, 0xe1, 0x43, 0x08, 0x12, 0x20, 0xb0, 0x24, 0x09, 0x12, 0x20, 0x25, 0xe0, 0x14, 
-0x60, 0x2c, 0x14, 0x60, 0x2e, 0x14, 0x60, 0x26, 0x14, 0x60, 0x28, 0x24, 0x04, 0x70, 0x2c, 0xe5, 
-0x38, 0xb4, 0x03, 0x0d, 0x30, 0x94, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x1f, 0x43, 0x07, 0x80, 0x80, 
-0x1a, 0x30, 0x92, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x12, 0x43, 0x07, 0x80, 0x80, 0x0d, 0x53, 0x07, 
-0x7f, 0x80, 0x08, 0x43, 0x07, 0x80, 0x80, 0x03, 0x53, 0x07, 0x7f, 0x78, 0x86, 0x12, 0x20, 0x65, 
-0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x20, 0x80, 0x03, 0x53, 0x07, 0xdf, 
-0xec, 0x30, 0xe3, 0x05, 0x43, 0x07, 0x40, 0x80, 0x03, 0x53, 0x07, 0xbf, 0xec, 0x30, 0xe0, 0x05, 
-0x43, 0x07, 0x10, 0x80, 0x03, 0x53, 0x07, 0xef, 0xed, 0x30, 0xe4, 0x05, 0x43, 0x07, 0x08, 0x80, 
-0x03, 0x53, 0x07, 0xf7, 0xed, 0x30, 0xe5, 0x05, 0x43, 0x07, 0x04, 0x80, 0x03, 0x53, 0x07, 0xfb, 
-0xed, 0x30, 0xe6, 0x05, 0x43, 0x07, 0x01, 0x80, 0x03, 0x53, 0x07, 0xfe, 0xed, 0x30, 0xe7, 0x05, 
-0x43, 0x07, 0x02, 0x80, 0x03, 0x53, 0x07, 0xfd, 0x78, 0x84, 0x12, 0x20, 0x65, 0xa3, 0xef, 0xf0, 
-0x12, 0x2f, 0x80, 0x7f, 0x00, 0x22, 0x12, 0x0f, 0x89, 0x78, 0x8e, 0xef, 0xf6, 0x12, 0x27, 0x19, 
-0x12, 0x20, 0x70, 0x8e, 0x83, 0x24, 0x09, 0x12, 0x20, 0x25, 0xe0, 0xfd, 0x12, 0x20, 0x53, 0x90, 
-0x00, 0x0a, 0x12, 0x20, 0x78, 0x24, 0x0a, 0x12, 0x20, 0x25, 0xe0, 0x90, 0x00, 0x0b, 0x12, 0x14, 
-0x0d, 0x12, 0x20, 0x70, 0xf5, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf5, 0x59, 0x12, 0x20, 
-0x7c, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0xf5, 0x5a, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 
-0xf5, 0x5b, 0xe5, 0x59, 0xc4, 0x13, 0x13, 0x13, 0x54, 0x01, 0x78, 0x8e, 0xf6, 0xd3, 0x94, 0x00, 
-0x40, 0x06, 0xe5, 0x5a, 0x30, 0xe1, 0x01, 0x06, 0x78, 0x8e, 0xe6, 0x12, 0x20, 0x52, 0x90, 0x00, 
-0x0c, 0xef, 0x12, 0x14, 0x0d, 0x78, 0x86, 0x12, 0x20, 0x2f, 0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 
-0xff, 0x53, 0x07, 0x0c, 0x53, 0x06, 0xe6, 0xe5, 0x59, 0x30, 0xe5, 0x03, 0x43, 0x07, 0x01, 0xe5, 
-0x5a, 0x20, 0xe5, 0x0e, 0xe5, 0x59, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x59, 0x20, 0xe7, 0x03, 0x43, 
-0x07, 0x02, 0xe5, 0x59, 0x30, 0xe3, 0x03, 0x43, 0x07, 0x10, 0xe5, 0x59, 0x30, 0xe2, 0x03, 0x43, 
-0x07, 0x20, 0xe5, 0x59, 0x54, 0x03, 0x60, 0x03, 0x43, 0x07, 0x40, 0xe5, 0x59, 0x30, 0xe1, 0x03, 
-0x43, 0x07, 0x80, 0xe5, 0x59, 0x30, 0xe4, 0x03, 0x43, 0x06, 0x01, 0xe5, 0x59, 0x30, 0xe6, 0x03, 
-0x43, 0x06, 0x08, 0xe5, 0x5a, 0x20, 0xe4, 0x0e, 0xe5, 0x59, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x59, 
-0x20, 0xe7, 0x03, 0x43, 0x06, 0x10, 0x53, 0x07, 0xfb, 0x53, 0x06, 0x79, 0x90, 0x00, 0x05, 0xee, 
-0x8f, 0xf0, 0x12, 0x14, 0xb2, 0xe5, 0x5b, 0x30, 0xe3, 0x12, 0x54, 0x30, 0xff, 0xc4, 0x54, 0x0f, 
-0x12, 0x20, 0x52, 0x90, 0x00, 0x08, 0xef, 0x12, 0x14, 0x0d, 0x80, 0x0a, 0x12, 0x20, 0x53, 0x90, 
-0x00, 0x08, 0xe4, 0x12, 0x14, 0x0d, 0xe5, 0x5b, 0x54, 0x03, 0x12, 0x20, 0x52, 0x90, 0x00, 0x07, 
-0xef, 0x12, 0x14, 0x0d, 0xe5, 0x5b, 0x54, 0x04, 0xff, 0xc3, 0x13, 0x90, 0x00, 0x09, 0x12, 0x14, 
-0x0d, 0x90, 0x00, 0x07, 0x12, 0x13, 0xce, 0x70, 0x13, 0x12, 0x20, 0x53, 0xe9, 0x24, 0x09, 0xf9, 
-0xe4, 0x3a, 0xfa, 0x12, 0x13, 0xb5, 0xff, 0xc3, 0x13, 0x12, 0x13, 0xfb, 0x12, 0x20, 0x94, 0x24, 
-0x08, 0x12, 0x20, 0x25, 0xe0, 0xfe, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x07, 0x12, 0x20, 
-0x25, 0xe0, 0xfd, 0xee, 0xed, 0x12, 0x20, 0x52, 0x90, 0x00, 0x03, 0xee, 0x8f, 0xf0, 0x12, 0x14, 
-0xb2, 0x12, 0x2f, 0x80, 0x7d, 0x0a, 0xe4, 0xff, 0x12, 0x2c, 0xc0, 0x02, 0x10, 0x0c, 0x90, 0xfa, 
-0xe2, 0xe0, 0xb4, 0x03, 0x06, 0x7e, 0x00, 0x7f, 0x40, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x08, 0x90, 
-0xfa, 0xd6, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x00, 0x05, 0x12, 0x13, 0xce, 0xff, 0x7e, 0x00, 
-0x90, 0xfa, 0xd2, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x70, 0x03, 0x7f, 0x08, 0x22, 0x90, 0x00, 0x08, 
-0x12, 0x14, 0x5b, 0xff, 0x90, 0xfa, 0xd4, 0xe5, 0xf0, 0xf0, 0xa3, 0xef, 0xf0, 0xae, 0x02, 0xaf, 
-0x01, 0x8e, 0x56, 0x8f, 0x57, 0x74, 0x0a, 0x25, 0x57, 0xf5, 0x57, 0xe4, 0x35, 0x56, 0xf5, 0x56, 
-0x90, 0xfa, 0xd7, 0xe0, 0xff, 0x14, 0xfe, 0x90, 0xfa, 0xd5, 0xe0, 0x5e, 0xfe, 0xc3, 0xef, 0x9e, 
-0xff, 0x90, 0xfa, 0xd9, 0xf0, 0xc3, 0x90, 0xfa, 0xd3, 0xe0, 0x9f, 0x90, 0xfa, 0xd2, 0xe0, 0x94, 
-0x00, 0x50, 0x06, 0xa3, 0xe0, 0x90, 0xfa, 0xd9, 0xf0, 0x12, 0x1e, 0x2d, 0x60, 0x03, 0xe0, 0xff, 
-0x22, 0x12, 0x2a, 0x80, 0x90, 0xfa, 0xd2, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x60, 0x2b, 0x90, 
-0xfa, 0xd6, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x07, 0xe0, 0x90, 
-0xfa, 0xd9, 0xf0, 0x80, 0x08, 0x90, 0xfa, 0xd3, 0xe0, 0x90, 0xfa, 0xd9, 0xf0, 0x12, 0x1e, 0x2d, 
-0x60, 0x03, 0xe0, 0xff, 0x22, 0x12, 0x2a, 0x80, 0x80, 0xca, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x58, 
-0xe4, 0xf5, 0x40, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x7f, 0x00, 0x22, 0xaa, 0x56, 0xa9, 
-0x57, 0x7b, 0x01, 0x90, 0xfa, 0xd4, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xd9, 0xe0, 0xf5, 
-0x50, 0x12, 0x26, 0x25, 0x90, 0xfa, 0xd8, 0xef, 0xf0, 0x22, 0xef, 0x24, 0xae, 0x60, 0x52, 0x24, 
-0xfe, 0x60, 0x2e, 0x24, 0xfe, 0x70, 0x03, 0x02, 0x1e, 0xed, 0x24, 0x06, 0x60, 0x03, 0x02, 0x1f, 
-0x35, 0x78, 0x77, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xa5, 0xe0, 0xf5, 0x36, 0x44, 0x0f, 0xf0, 
-0x74, 0x33, 0x90, 0xfa, 0x90, 0xf0, 0xe5, 0x36, 0xa3, 0xf0, 0x90, 0xfa, 0xae, 0x74, 0x01, 0xf0, 
-0x22, 0x78, 0x78, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xb5, 0xe0, 0xf5, 0x36, 0x44, 0x0f, 0xf0, 
-0x74, 0x43, 0x90, 0xfa, 0x92, 0xf0, 0xe5, 0x36, 0xa3, 0xf0, 0x90, 0xfa, 0xaf, 0x74, 0x01, 0xf0, 
-0x22, 0x90, 0xfa, 0x9c, 0xe0, 0xa3, 0x20, 0xe5, 0x03, 0x02, 0x1f, 0x35, 0x90, 0xff, 0xa6, 0xe0, 
-0x90, 0xfa, 0xc9, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xc9, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 
-0x90, 0xff, 0xa6, 0x12, 0x20, 0x83, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xc9, 0xf0, 0x80, 0xe6, 
-0x90, 0xfa, 0xca, 0xe0, 0xff, 0x74, 0x34, 0xfe, 0x12, 0x29, 0xda, 0xef, 0x70, 0x57, 0x90, 0xfa, 
-0xca, 0xe0, 0xff, 0x74, 0x34, 0x90, 0xfa, 0x94, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0x90, 0xfa, 0xa6, 
-0xe0, 0xa3, 0x30, 0xe5, 0x40, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xc9, 0xf0, 0xa3, 0xf0, 0x90, 
-0xfa, 0xc9, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 0xb6, 0x12, 0x20, 0x83, 0x90, 
-0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xc9, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 0xca, 0xe0, 0xff, 0x74, 0x44, 
-0xfe, 0x12, 0x29, 0xda, 0xef, 0x70, 0x0e, 0x90, 0xfa, 0xca, 0xe0, 0xff, 0x74, 0x44, 0x90, 0xfa, 
-0x96, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 
-0x75, 0xd0, 0x00, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 
-0x06, 0xc0, 0x07, 0x90, 0xff, 0x92, 0xe0, 0xff, 0x90, 0xfa, 0xc8, 0xf0, 0x90, 0xff, 0x92, 0xe4, 
-0xf0, 0xef, 0x12, 0x15, 0x0f, 0x1f, 0xed, 0x26, 0x1f, 0xed, 0x2e, 0x1f, 0x90, 0x30, 0x1f, 0x90, 
-0x32, 0x1f, 0x9e, 0x38, 0x1f, 0xb0, 0x3a, 0x1f, 0xe2, 0x3e, 0x1f, 0xcd, 0x44, 0x1f, 0xc2, 0x46, 
-0x1f, 0xd8, 0x50, 0x1f, 0xd8, 0x52, 0x1f, 0xd8, 0x54, 0x1f, 0xd8, 0x56, 0x00, 0x00, 0x1f, 0xf2, 
-0x90, 0xfa, 0xc8, 0xe0, 0xfd, 0x7c, 0x00, 0x7f, 0x01, 0x12, 0x10, 0x9c, 0x80, 0x62, 0x7c, 0x00, 
-0x7d, 0x01, 0x7f, 0x03, 0x12, 0x10, 0x9c, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x50, 
-0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x02, 0x12, 0x10, 0x9c, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x40, 0xf0, 
-0x80, 0x3e, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x05, 0x12, 0x10, 0x9c, 0x80, 0x33, 0x7c, 0x00, 0x7d, 
-0x01, 0x7f, 0x06, 0x12, 0x10, 0x9c, 0x80, 0x28, 0x90, 0xfa, 0xc8, 0xe0, 0xff, 0x12, 0x1e, 0x4a, 
-0x80, 0x1e, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x04, 0x12, 0x10, 0x9c, 0x80, 0x13, 0x12, 0x25, 0x13, 
-0x80, 0x0e, 0x90, 0xfa, 0xc8, 0xe0, 0x24, 0x00, 0xff, 0xe4, 0x34, 0xff, 0xfe, 0x12, 0x29, 0xda, 
-0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 
-0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x78, 0x82, 0xe6, 0xfe, 0x08, 
-0xe6, 0x24, 0x04, 0x8e, 0x83, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x78, 0x82, 0xe6, 
-0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 0x83, 0x22, 0x78, 0x86, 0xe6, 0xfe, 0x08, 0xe6, 0xaa, 0x06, 
-0xf8, 0xac, 0x02, 0x7d, 0x01, 0x7b, 0xff, 0x7a, 0x2f, 0x79, 0x52, 0x7e, 0x00, 0x7f, 0x0a, 0x02, 
-0x13, 0x8f, 0xff, 0x90, 0xf9, 0x6b, 0x02, 0x14, 0xfd, 0x90, 0xf9, 0x66, 0x12, 0x14, 0xfd, 0x90, 
-0x00, 0x04, 0x02, 0x13, 0xce, 0xe6, 0xfc, 0x08, 0xe6, 0xf5, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0x22, 
-0x78, 0x84, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x22, 0xed, 0x12, 0x14, 0x0d, 0x8f, 0x82, 0x8e, 0x83, 
-0xe5, 0x82, 0x22, 0xef, 0xf0, 0x90, 0xfa, 0xca, 0xe0, 0x54, 0x0f, 0x4e, 0xfe, 0xf0, 0xef, 0x54, 
-0xf0, 0x4e, 0xf0, 0x22, 0x78, 0x84, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x8c, 0x83, 0x22, 0xa6, 0x07, 
-0xe6, 0x24, 0x74, 0xf8, 0xe6, 0x22, 0x78, 0x84, 0xe6, 0xfa, 0x08, 0xe6, 0xfb, 0x22, 0x78, 0x86, 
-0xe6, 0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x22, 0x26, 0xf6, 0x18, 0xee, 0x36, 0xf6, 0x22, 0x8b, 0x82, 
-0x8a, 0x83, 0xe5, 0x82, 0x22, 0x8b, 0x38, 0x8a, 0x39, 0x89, 0x3a, 0x8d, 0x3b, 0x90, 0xfa, 0xce, 
-0xe4, 0xf0, 0xa3, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcd, 0x90, 0xfa, 0xce, 0xe0, 
-0xf5, 0x40, 0xa3, 0xe0, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x90, 0xfa, 0xcd, 0xe0, 0x65, 
-0x3b, 0x60, 0x46, 0xa3, 0xe0, 0xff, 0xa3, 0xe0, 0xa3, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x21, 
-0x54, 0x90, 0xfa, 0xcd, 0xe0, 0xff, 0x90, 0xfa, 0xd0, 0xe4, 0x8f, 0xf0, 0x12, 0x14, 0x2f, 0x12, 
-0x21, 0x54, 0x90, 0xfa, 0xd0, 0xe0, 0xff, 0xa3, 0xe0, 0x90, 0xfa, 0xce, 0xcf, 0xf0, 0xa3, 0xef, 
-0xf0, 0x90, 0xfa, 0xcd, 0xe0, 0xa3, 0x75, 0xf0, 0x00, 0x12, 0x14, 0x2f, 0x90, 0xfa, 0xce, 0xe4, 
-0x75, 0xf0, 0x04, 0x12, 0x14, 0x2f, 0x02, 0x20, 0xd6, 0x90, 0xfa, 0xcf, 0xe0, 0x24, 0x01, 0xff, 
-0x90, 0xfa, 0xce, 0xe0, 0x34, 0x00, 0xab, 0x38, 0xaa, 0x39, 0xa9, 0x3a, 0x8f, 0xf0, 0x12, 0x14, 
-0x93, 0x7f, 0x00, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcd, 0x90, 0xfa, 0xce, 0xe4, 0x75, 0xf0, 
-0x01, 0x12, 0x14, 0x2f, 0x85, 0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x02, 0x23, 0xee, 0x8f, 0x68, 
-0x12, 0x27, 0x19, 0x12, 0x20, 0x70, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x20, 0x25, 0xe0, 0x54, 0xfb, 
-0xf0, 0x44, 0x02, 0xf0, 0x08, 0x12, 0x20, 0x65, 0xe0, 0xa3, 0x30, 0xe5, 0x0c, 0x12, 0x20, 0x7c, 
-0x24, 0x0b, 0x12, 0x20, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x78, 0x82, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 
-0xf5, 0x82, 0x8e, 0x83, 0xe0, 0x54, 0xb8, 0xfd, 0xf0, 0xe5, 0x68, 0x24, 0xfe, 0x44, 0x20, 0xfc, 
-0x4d, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0x54, 0xb8, 0xf0, 0x4c, 0xf0, 0x8f, 
-0x82, 0x8e, 0x83, 0xa3, 0x74, 0x03, 0xf0, 0x18, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 
-0x05, 0x12, 0x20, 0x25, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x74, 0x95, 0x25, 0x68, 0xf5, 0x82, 
-0xe4, 0x34, 0xfa, 0xf5, 0x83, 0xe0, 0x54, 0xfc, 0x44, 0x03, 0xfc, 0xed, 0x4c, 0xd0, 0x82, 0xd0, 
-0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, 
-0x25, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x2f, 0x80, 0x74, 0x74, 0x25, 0x68, 0xf8, 0x74, 0x04, 0x46, 
-0xf6, 0x7f, 0x00, 0x22, 0x8b, 0x62, 0x8a, 0x63, 0x89, 0x64, 0x12, 0x2a, 0x62, 0x90, 0xfa, 0xbf, 
-0x12, 0x15, 0x06, 0xaa, 0x63, 0xa9, 0x64, 0x90, 0xfa, 0xc2, 0x12, 0x15, 0x06, 0x90, 0xfa, 0xc3, 
-0xe4, 0x75, 0xf0, 0x0a, 0x12, 0x14, 0x2f, 0x90, 0xfa, 0xc2, 0x12, 0x14, 0xfd, 0xe9, 0x24, 0x01, 
-0xf9, 0xe4, 0x3a, 0xfa, 0x90, 0xfa, 0xc5, 0x12, 0x15, 0x06, 0xab, 0x62, 0xaa, 0x63, 0xa9, 0x64, 
-0x12, 0x2a, 0x6e, 0xe0, 0xff, 0xc3, 0x13, 0xf0, 0xe4, 0x78, 0x88, 0xf6, 0x90, 0xfa, 0xbd, 0xe0, 
-0xff, 0x78, 0x88, 0xe6, 0xc3, 0x9f, 0x50, 0x4a, 0x90, 0xfa, 0xbf, 0x12, 0x2a, 0x43, 0xff, 0x78, 
-0x89, 0xf6, 0x90, 0xfa, 0xc2, 0x12, 0x2a, 0x43, 0xfe, 0xf4, 0x5f, 0xff, 0x78, 0x89, 0xf6, 0x12, 
-0x2a, 0x40, 0x5e, 0x4f, 0xff, 0x78, 0x89, 0xf6, 0x12, 0x2a, 0x49, 0x75, 0xf0, 0x02, 0x12, 0x14, 
-0x2f, 0x90, 0xfa, 0xc3, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x14, 0x2f, 0xab, 0x62, 0xaa, 0x63, 0xa9, 
-0x64, 0x90, 0x00, 0x04, 0x12, 0x13, 0xce, 0x30, 0xe4, 0x03, 0x12, 0x2a, 0x58, 0x78, 0x88, 0x06, 
-0x80, 0xaa, 0xe4, 0x90, 0xfa, 0xbe, 0xf0, 0x22, 0x8b, 0x5c, 0x8a, 0x5d, 0x89, 0x5e, 0x90, 0xfa, 
-0xbe, 0x74, 0x06, 0xf0, 0xe4, 0x90, 0xfa, 0xbd, 0xf0, 0x12, 0x13, 0xb5, 0x24, 0x6e, 0x60, 0x26, 
-0x14, 0x70, 0x70, 0x12, 0x2a, 0x2f, 0x60, 0x09, 0x24, 0x30, 0x70, 0x12, 0x12, 0x22, 0x14, 0x80, 
-0x62, 0x12, 0x2a, 0x79, 0x12, 0x1d, 0x5e, 0x90, 0xfa, 0xbe, 0xef, 0xf0, 0x80, 0x55, 0x90, 0xfa, 
-0xbe, 0x74, 0x81, 0xf0, 0x80, 0x4d, 0x12, 0x2a, 0x2f, 0x60, 0x09, 0x24, 0x30, 0x70, 0x3e, 0x12, 
-0x29, 0x85, 0x80, 0x3f, 0xe5, 0x5e, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x5d, 0xfa, 0x7b, 0x01, 0xc0, 
-0x03, 0xc0, 0x02, 0xc0, 0x01, 0x12, 0x2a, 0x79, 0x90, 0x00, 0x05, 0x12, 0x13, 0xce, 0xfd, 0x90, 
-0x00, 0x08, 0x12, 0x14, 0x5b, 0xf5, 0x41, 0x85, 0xf0, 0x40, 0xd0, 0x01, 0xd0, 0x02, 0xd0, 0x03, 
-0x12, 0x23, 0xee, 0x90, 0xfa, 0xbd, 0xef, 0xf0, 0xe4, 0xa3, 0xf0, 0x80, 0x06, 0x90, 0xfa, 0xbe, 
-0x74, 0x81, 0xf0, 0x90, 0xfa, 0xbe, 0xe0, 0x12, 0x2a, 0x79, 0x90, 0x00, 0x02, 0x12, 0x14, 0x0d, 
-0x90, 0xfa, 0xbd, 0xe0, 0xff, 0x22, 0x12, 0x0f, 0x89, 0x7f, 0x02, 0x12, 0x11, 0x9f, 0x78, 0x6d, 
-0xe6, 0x44, 0x02, 0xf6, 0xd2, 0xb0, 0xd2, 0xb1, 0xd2, 0xb3, 0x90, 0xff, 0xa4, 0xe0, 0x90, 0xfa, 
-0x7a, 0xf0, 0x90, 0xff, 0xb4, 0xe0, 0x90, 0xfa, 0x7b, 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x90, 0xfa, 
-0x78, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x90, 0xfa, 0x79, 0xf0, 0x90, 0xff, 0xa4, 0x74, 0x30, 0xf0, 
-0x90, 0xff, 0xb4, 0xf0, 0x90, 0xff, 0xa2, 0x74, 0x40, 0xf0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xfa, 
-0xe3, 0xe5, 0xa8, 0xf0, 0x75, 0xa8, 0x81, 0x90, 0xff, 0x92, 0xe0, 0x60, 0x04, 0xe4, 0xf0, 0x80, 
-0xf6, 0x90, 0xff, 0xfd, 0x74, 0x3a, 0xf0, 0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x90, 0xfa, 0x7a, 
-0xe0, 0x90, 0xff, 0xa4, 0xf0, 0x90, 0xfa, 0x7b, 0xe0, 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xfa, 0x78, 
-0xe0, 0x90, 0xff, 0xa2, 0xf0, 0x90, 0xfa, 0x79, 0xe0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xf9, 0x15, 
-0xe0, 0x60, 0x02, 0xc2, 0xb3, 0x90, 0xfa, 0xe3, 0xe0, 0xf5, 0xa8, 0x02, 0x10, 0x0c, 0x8b, 0x3c, 
-0x8a, 0x3d, 0x89, 0x3e, 0x8d, 0x3f, 0xe5, 0x3f, 0x70, 0x03, 0xaf, 0x3f, 0x22, 0x12, 0x2a, 0xa8, 
-0x70, 0x16, 0x12, 0x2a, 0xc7, 0xe5, 0x40, 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x2e, 0xd4, 0x50, 0xf2, 
-0x12, 0x24, 0x7b, 0x40, 0x0b, 0x7f, 0x00, 0x22, 0x12, 0x2a, 0xc7, 0x12, 0x24, 0x7b, 0x50, 0xf8, 
-0x90, 0xff, 0xf3, 0x74, 0xa1, 0xf0, 0xe5, 0x3f, 0xb4, 0x01, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, 
-0x02, 0xf0, 0x90, 0xff, 0xf1, 0xe4, 0xf0, 0xf5, 0x42, 0xe5, 0x3f, 0x14, 0xff, 0xe5, 0x42, 0xc3, 
-0x9f, 0x50, 0x2a, 0x12, 0x2e, 0xbd, 0x40, 0x03, 0xaf, 0x42, 0x22, 0xc3, 0xe5, 0x3f, 0x95, 0x42, 
-0xff, 0xbf, 0x02, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x12, 0x2a, 0xba, 0x05, 0x42, 
-0x74, 0x01, 0x25, 0x3e, 0xf5, 0x3e, 0xe4, 0x35, 0x3d, 0xf5, 0x3d, 0x80, 0xcc, 0x12, 0x2e, 0xbd, 
-0x40, 0x03, 0x7f, 0x18, 0x22, 0x12, 0x2a, 0xba, 0xaf, 0x3f, 0x22, 0x90, 0xff, 0xf1, 0xe5, 0x41, 
-0xf0, 0x02, 0x2e, 0xd4, 0x75, 0xa8, 0x40, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x91, 
-0x02, 0x24, 0xce, 0x02, 0x2e, 0x88, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 
-0x80, 0x01, 0xf2, 0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 
-0xc8, 0xc3, 0x33, 0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 
-0x46, 0xf6, 0xdf, 0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x28, 
-0xcb, 0xe4, 0x7e, 0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 
-0xfe, 0xe4, 0x93, 0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 
-0xe4, 0x93, 0xa3, 0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 
-0xc5, 0x83, 0xca, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 
-0xe7, 0x80, 0xbe, 0xe4, 0xf5, 0x36, 0x12, 0x19, 0x21, 0xe0, 0xb4, 0x04, 0x0d, 0xe5, 0x36, 0x24, 
-0x03, 0xff, 0x12, 0x2d, 0x4f, 0x12, 0x19, 0x21, 0xe4, 0xf0, 0x05, 0x36, 0xe5, 0x36, 0xc3, 0x94, 
-0x02, 0x40, 0xe3, 0xe4, 0xf5, 0x36, 0x75, 0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, 0x90, 0x12, 0x19, 
-0x62, 0x60, 0x2c, 0x12, 0x29, 0xda, 0xef, 0x60, 0x52, 0x75, 0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, 
-0x90, 0x12, 0x14, 0xdf, 0xe4, 0xf0, 0xa3, 0xf0, 0x75, 0xf0, 0x0a, 0xe5, 0x36, 0x90, 0xfa, 0x9c, 
-0x12, 0x14, 0xdf, 0xe0, 0xa3, 0x30, 0xe6, 0x33, 0x12, 0x19, 0x21, 0x74, 0x04, 0xf0, 0x22, 0x75, 
-0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, 0x94, 0x12, 0x19, 0x62, 0x60, 0x16, 0x12, 0x29, 0xda, 0xef, 
-0x60, 0x19, 0x75, 0xf0, 0x02, 0xe5, 0x36, 0x90, 0xfa, 0x94, 0x12, 0x14, 0xdf, 0xe4, 0xf0, 0xa3, 
-0xf0, 0x22, 0x05, 0x36, 0xe5, 0x36, 0xc3, 0x94, 0x02, 0x40, 0x9b, 0x22, 0xe4, 0xff, 0x90, 0xff, 
-0x83, 0xe0, 0x54, 0x0f, 0xfe, 0xef, 0xc3, 0x9e, 0x50, 0x17, 0x74, 0xf0, 0x2f, 0xf5, 0x82, 0xe4, 
-0x34, 0xfe, 0xf5, 0x83, 0xe0, 0x12, 0x18, 0x2a, 0x12, 0x13, 0xfb, 0x0f, 0x12, 0x18, 0x19, 0x80, 
-0xdd, 0xef, 0xfd, 0xc3, 0xe5, 0x31, 0x9d, 0xf5, 0x31, 0xe5, 0x30, 0x94, 0x00, 0xf5, 0x30, 0xd3, 
-0xe5, 0x31, 0x94, 0x00, 0xe5, 0x30, 0x94, 0x00, 0x40, 0x06, 0xe4, 0x90, 0xff, 0x83, 0xf0, 0x22, 
-0x12, 0x19, 0x3e, 0x12, 0x19, 0x92, 0x12, 0x19, 0x8c, 0x12, 0x13, 0xb5, 0x24, 0x6e, 0x60, 0x1e, 
-0x14, 0x60, 0x1b, 0x24, 0x8e, 0x70, 0x2d, 0x90, 0x00, 0x01, 0x12, 0x13, 0xce, 0xff, 0x24, 0xfc, 
-0x60, 0x03, 0x04, 0x70, 0x1f, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0d, 0x02, 0x10, 0x9c, 0x12, 0x19, 
-0x6c, 0x12, 0x22, 0xb8, 0x12, 0x18, 0xe8, 0x12, 0x13, 0xce, 0x60, 0x03, 0x02, 0x2f, 0x76, 0xe4, 
-0xff, 0x12, 0x2f, 0x6a, 0x22, 0x8b, 0x4b, 0x8a, 0x4c, 0x89, 0x4d, 0x8c, 0x4e, 0x8d, 0x4f, 0xd2, 
-0x00, 0x12, 0x2a, 0xa8, 0x70, 0x16, 0x12, 0x2a, 0xc7, 0xe5, 0x4e, 0x90, 0xff, 0xf1, 0xf0, 0x12, 
-0x2e, 0xd4, 0x50, 0xf2, 0x12, 0x26, 0x9a, 0x40, 0x0b, 0x7f, 0x18, 0x22, 0x12, 0x2a, 0xc7, 0x12, 
-0x26, 0x9a, 0x50, 0xf8, 0xe4, 0xf5, 0x51, 0xe5, 0x50, 0x14, 0xff, 0xe5, 0x51, 0xc3, 0x9f, 0x50, 
-0x17, 0x12, 0x26, 0x8a, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x05, 0x51, 0x74, 0x01, 0x25, 0x4d, 0xf5, 
-0x4d, 0xe4, 0x35, 0x4c, 0xf5, 0x4c, 0x80, 0xdf, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x12, 
-0x26, 0x8a, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x7f, 0x00, 0x22, 0xab, 0x4b, 0xaa, 0x4c, 0xa9, 0x4d, 
-0x12, 0x13, 0xb5, 0x90, 0xff, 0xf1, 0xf0, 0x02, 0x2e, 0xd4, 0x90, 0xff, 0xf1, 0xe5, 0x4f, 0xf0, 
-0x02, 0x2e, 0xd4, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcb, 0xe4, 0xfd, 0x12, 0x20, 0xc5, 0x90, 0xfa, 
-0xcb, 0xe4, 0x75, 0xf0, 0x09, 0x12, 0x14, 0x2f, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x37, 0x90, 0xfa, 
-0xcb, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x14, 0x45, 0x85, 0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x12, 
-0x23, 0xee, 0x90, 0xff, 0xf7, 0xe5, 0x37, 0x12, 0x26, 0xfe, 0x90, 0xff, 0xf6, 0xe5, 0x37, 0xf0, 
-0x90, 0xfa, 0xcb, 0xe4, 0xf0, 0xa3, 0x74, 0x06, 0x12, 0x26, 0xfe, 0xe5, 0x37, 0x30, 0xe0, 0x07, 
-0x90, 0xff, 0xfc, 0x74, 0x94, 0xf0, 0x22, 0x90, 0xff, 0xfc, 0x74, 0x90, 0xf0, 0x22, 0xf0, 0x7b, 
-0x00, 0x7a, 0x00, 0x79, 0x37, 0x90, 0xfa, 0xcb, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x14, 0x45, 0x85, 
-0xf0, 0x41, 0xf5, 0x40, 0x7d, 0x01, 0x02, 0x23, 0xee, 0x15, 0x6b, 0xa8, 0x6b, 0xa6, 0x07, 0x30, 
-0x08, 0x05, 0x12, 0x10, 0xec, 0x80, 0xf8, 0xd2, 0x08, 0xa8, 0x6b, 0xe6, 0xff, 0xb4, 0x03, 0x0f, 
-0x78, 0x82, 0x76, 0xff, 0x08, 0x76, 0xe0, 0x08, 0x76, 0xff, 0x08, 0x76, 0xa0, 0x80, 0x0d, 0x78, 
-0x82, 0x76, 0xff, 0x08, 0x76, 0xe2, 0x08, 0x76, 0xff, 0x08, 0x76, 0xb0, 0x78, 0x86, 0x76, 0xfa, 
-0x08, 0x76, 0x9a, 0xef, 0x24, 0xfd, 0x75, 0xf0, 0x0a, 0xa4, 0xae, 0xf0, 0x12, 0x20, 0xb7, 0x7b, 
-0x01, 0x7a, 0xff, 0x79, 0x48, 0x78, 0x6e, 0x12, 0x14, 0xf4, 0xa8, 0x6b, 0xe6, 0x24, 0xfd, 0x75, 
-0xf0, 0x08, 0xa4, 0xff, 0xae, 0xf0, 0x78, 0x70, 0x12, 0x20, 0xb7, 0x79, 0x08, 0x78, 0x71, 0x12, 
-0x14, 0xf4, 0x78, 0x73, 0xef, 0x12, 0x20, 0xb7, 0x05, 0x6b, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 
-0xab, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xfa, 0xe2, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 
-0x79, 0xcb, 0xe4, 0xf5, 0x40, 0xf5, 0x41, 0x7d, 0x01, 0x12, 0x23, 0xee, 0x7e, 0x00, 0x90, 0xfa, 
-0xe0, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcb, 0xe0, 0xb4, 0x52, 
-0x09, 0x90, 0xf9, 0x65, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x29, 0x90, 0xfa, 0xe0, 0xe0, 0x70, 0x04, 
-0xa3, 0xe0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcb, 0xe0, 0xb4, 0x10, 0x09, 0x90, 0xf9, 0x65, 
-0xe0, 0x44, 0x10, 0xf0, 0x80, 0x0d, 0x90, 0xfa, 0xe2, 0x74, 0x03, 0xf0, 0x90, 0xf9, 0x65, 0xe0, 
-0x54, 0xef, 0xf0, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x22, 0x90, 0xff, 0x93, 0x74, 0x2a, 
-0xf0, 0x90, 0xff, 0xff, 0xe0, 0x60, 0x06, 0x90, 0xff, 0xfc, 0x74, 0x10, 0xf0, 0x90, 0xff, 0x91, 
-0xe0, 0x44, 0x90, 0xf0, 0x12, 0x27, 0x8b, 0x12, 0x15, 0x35, 0x12, 0x2d, 0xa5, 0x7e, 0x07, 0x7f, 
-0xd0, 0x12, 0x11, 0x68, 0x7e, 0x0f, 0x7f, 0xa0, 0x12, 0x11, 0x82, 0xe4, 0x78, 0x7d, 0xf6, 0x78, 
-0x7d, 0xe6, 0xff, 0xc3, 0x94, 0x06, 0x50, 0x0b, 0x74, 0x74, 0x2f, 0xf8, 0xe4, 0xf6, 0x78, 0x7d, 
-0x06, 0x80, 0xec, 0x7f, 0x03, 0x12, 0x2c, 0x5b, 0x90, 0xf9, 0x65, 0xe0, 0x20, 0xe4, 0x05, 0x7f, 
-0x04, 0x12, 0x2c, 0x5b, 0x90, 0xff, 0x9b, 0xe4, 0xf0, 0x90, 0xff, 0x9a, 0xf0, 0x90, 0xff, 0xe8, 
-0xe0, 0x54, 0x1f, 0xf0, 0xd2, 0xa8, 0x22, 0x12, 0x0f, 0x89, 0x78, 0x90, 0xef, 0xf6, 0x12, 0x27, 
-0x19, 0x12, 0x20, 0x59, 0x30, 0xe0, 0x25, 0x12, 0x20, 0x2d, 0xe0, 0x54, 0x7f, 0xf0, 0x78, 0x71, 
-0x12, 0x14, 0xeb, 0x90, 0x00, 0x02, 0x12, 0x13, 0xce, 0x30, 0xe7, 0x09, 0x90, 0x00, 0x02, 0xe4, 
-0x12, 0x14, 0x0d, 0x80, 0xe9, 0x12, 0x20, 0x2d, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x20, 0x59, 0x30, 
-0xe1, 0x1e, 0x12, 0x20, 0x1b, 0xe0, 0x54, 0x7f, 0xf0, 0x12, 0x2f, 0x15, 0x78, 0x6e, 0x12, 0x14, 
-0xeb, 0x90, 0x00, 0x02, 0x74, 0x80, 0x12, 0x14, 0x0d, 0x12, 0x20, 0x1b, 0xe0, 0x44, 0x80, 0xf0, 
-0x12, 0x2f, 0x80, 0xe4, 0xff, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x03, 0x6e, 0x01, 0xff, 0x48, 
-0x03, 0x71, 0x01, 0xff, 0x08, 0x02, 0x6c, 0x00, 0x00, 0x44, 0xfa, 0x94, 0x00, 0x00, 0x00, 0x00, 
-0x44, 0xfa, 0x90, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfa, 0xae, 0x00, 0x00, 0x42, 0xfa, 0x7a, 0x00, 
-0x00, 0x42, 0xfa, 0x78, 0x00, 0x00, 0x42, 0xf9, 0x69, 0xff, 0xff, 0x42, 0xfa, 0x76, 0x00, 0x00, 
-0x43, 0xf9, 0x16, 0x0a, 0x32, 0x02, 0x41, 0xf9, 0x63, 0x20, 0x41, 0xf9, 0x64, 0x20, 0x41, 0xf9, 
-0x61, 0x00, 0x41, 0xf9, 0x62, 0x00, 0x44, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xf9, 0x65, 
-0x00, 0x41, 0xf9, 0x15, 0x00, 0x01, 0x20, 0x00, 0x41, 0xf8, 0x04, 0x00, 0x00, 0x12, 0x19, 0x82, 
-0xe5, 0x31, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x30, 0x64, 0x01, 0x60, 0x48, 0xc3, 0xe5, 0x31, 0x94, 
-0x08, 0xe5, 0x30, 0x94, 0x00, 0x40, 0x11, 0x7f, 0x08, 0xef, 0xe5, 0x31, 0x94, 0x08, 0xf5, 0x31, 
-0xe5, 0x30, 0x94, 0x00, 0xf5, 0x30, 0x80, 0x05, 0xaf, 0x31, 0x12, 0x19, 0x92, 0xe4, 0xfe, 0xee, 
-0xc3, 0x9f, 0x50, 0x19, 0x12, 0x18, 0x2a, 0x12, 0x13, 0xb5, 0xfd, 0x74, 0xf8, 0x2e, 0xf5, 0x82, 
-0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xed, 0xf0, 0x0e, 0x12, 0x18, 0x19, 0x80, 0xe2, 0xef, 0x54, 0x7f, 
-0x90, 0xff, 0x81, 0xf0, 0x22, 0x8b, 0x5f, 0x8a, 0x60, 0x89, 0x61, 0x12, 0x2a, 0x6e, 0x70, 0x05, 
-0xa3, 0x74, 0x08, 0xf0, 0x22, 0xab, 0x5f, 0xaa, 0x60, 0xa9, 0x61, 0x12, 0x2a, 0x62, 0x90, 0xfa, 
-0xc5, 0x12, 0x15, 0x06, 0xe5, 0x61, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x60, 0xfa, 0x90, 0xfa, 0xbf, 
-0x12, 0x15, 0x06, 0xe4, 0x90, 0xfa, 0xbe, 0xf0, 0x78, 0x91, 0xf6, 0x90, 0xfa, 0xbd, 0xe0, 0xff, 
-0x78, 0x91, 0xe6, 0xc3, 0x9f, 0x50, 0x12, 0x12, 0x2a, 0x40, 0xff, 0x12, 0x2a, 0x49, 0x12, 0x2a, 
-0x5c, 0x78, 0x91, 0x06, 0x12, 0x2a, 0x58, 0x80, 0xe2, 0x22, 0xad, 0x07, 0xac, 0x06, 0x90, 0x2f, 
-0x06, 0xe4, 0x93, 0xff, 0x78, 0x7a, 0xf6, 0x54, 0x0f, 0x12, 0x19, 0x07, 0xe0, 0x08, 0x76, 0x00, 
-0x08, 0xf6, 0x18, 0x12, 0x18, 0x42, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0x78, 0x7b, 
-0xee, 0xf6, 0x08, 0xef, 0xf6, 0xee, 0x44, 0xf8, 0x18, 0xf6, 0xef, 0x08, 0xf6, 0x90, 0xff, 0x7a, 
-0xe0, 0x20, 0xe7, 0x03, 0x7f, 0x00, 0x22, 0x78, 0x7b, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 
-0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 0x90, 0xff, 0x7a, 0x74, 0x02, 0xf0, 0x7f, 0x01, 0x22, 0xab, 
-0x5c, 0xaa, 0x5d, 0xa9, 0x5e, 0x90, 0x00, 0x03, 0x12, 0x13, 0xce, 0x54, 0xf0, 0x24, 0xa0, 0x22, 
-0x90, 0xfa, 0xc5, 0x12, 0x14, 0xfd, 0x02, 0x13, 0xb5, 0x90, 0xfa, 0xbf, 0x12, 0x14, 0xfd, 0xef, 
-0x12, 0x13, 0xfb, 0x90, 0xfa, 0xc6, 0xe4, 0x22, 0x90, 0xfa, 0xc0, 0xe4, 0x75, 0xf0, 0x01, 0x02, 
-0x14, 0x2f, 0x90, 0x00, 0x08, 0x12, 0x14, 0x5b, 0xaa, 0xf0, 0xf9, 0x7b, 0x01, 0x22, 0x90, 0x00, 
-0x05, 0x12, 0x13, 0xce, 0x90, 0xfa, 0xbd, 0xf0, 0x22, 0xab, 0x5c, 0xaa, 0x5d, 0xa9, 0x5e, 0x22, 
-0x90, 0xfa, 0xd9, 0xe0, 0xff, 0x7e, 0x00, 0xc3, 0x90, 0xfa, 0xd3, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 
-0xd2, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, 0xd4, 0xee, 0x8f, 0xf0, 0x12, 0x14, 0x2f, 0xef, 0x25, 0x57, 
-0xf5, 0x57, 0xee, 0x35, 0x56, 0xf5, 0x56, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 
-0x54, 0xfd, 0xf0, 0x90, 0xfa, 0xe2, 0xe0, 0x64, 0x03, 0x22, 0x90, 0xff, 0xf2, 0xe0, 0xab, 0x3c, 
-0xaa, 0x3d, 0xa9, 0x3e, 0x02, 0x13, 0xfb, 0x90, 0xff, 0xf3, 0x74, 0xa0, 0xf0, 0x22, 0x8f, 0x6a, 
-0xed, 0x70, 0x0f, 0xe5, 0x6a, 0xb4, 0x03, 0x05, 0x7f, 0x01, 0x02, 0x2e, 0xeb, 0x7f, 0x02, 0x02, 
-0x2e, 0xeb, 0xaf, 0x6a, 0x12, 0x27, 0x19, 0x74, 0x74, 0x25, 0x6a, 0xf8, 0xe6, 0x30, 0xe2, 0x0b, 
-0xd2, 0x09, 0x12, 0x18, 0x9b, 0xe0, 0x54, 0x7f, 0xf0, 0x80, 0x02, 0xc2, 0x09, 0xe5, 0x6a, 0xb4, 
-0x03, 0x07, 0x7f, 0x81, 0x12, 0x2e, 0xeb, 0x80, 0x05, 0x7f, 0x82, 0x12, 0x2e, 0xeb, 0x30, 0x09, 
-0x07, 0x12, 0x18, 0x9b, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x2f, 0x80, 0x22, 0x12, 0x0f, 0x89, 0x90, 
-0xff, 0xfd, 0xe0, 0x44, 0x60, 0xf0, 0xd2, 0x01, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x02, 0xf0, 0x90, 
-0xff, 0x00, 0xe0, 0x30, 0xe7, 0x13, 0x90, 0xff, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x2c, 0x80, 
-0x90, 0xff, 0xfc, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x0d, 0x12, 0x19, 0x3e, 0x53, 0x2c, 0x7f, 0x90, 
-0xff, 0xfc, 0xe0, 0x54, 0xfe, 0xf0, 0x90, 0xff, 0x81, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x02, 0x9f, 
-0x12, 0x19, 0x46, 0x02, 0x10, 0x0c, 0x12, 0x0f, 0x89, 0x78, 0x8a, 0x12, 0x20, 0x9e, 0x30, 0xe1, 
-0x07, 0x7f, 0x13, 0x12, 0x2e, 0xa5, 0x80, 0x34, 0x90, 0xf9, 0x65, 0xe0, 0x54, 0x03, 0x60, 0x16, 
-0x78, 0x8a, 0xe6, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x07, 0x90, 
-0xff, 0xb4, 0xe0, 0x54, 0xdf, 0xf0, 0xc2, 0xb3, 0x90, 0xf9, 0x15, 0xe0, 0x04, 0xf0, 0x78, 0x8a, 
-0xe6, 0xff, 0x12, 0x20, 0x59, 0xfd, 0x12, 0x2d, 0x21, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x12, 
-0x0f, 0x89, 0x78, 0x8f, 0xef, 0xf6, 0xd2, 0x00, 0x12, 0x27, 0x19, 0x90, 0xf9, 0x66, 0x12, 0x14, 
-0xfd, 0xe9, 0x24, 0x03, 0xf9, 0xe4, 0x3a, 0xfa, 0xc0, 0x02, 0x78, 0x86, 0xe6, 0xfe, 0x08, 0xe6, 
-0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0xd0, 0x02, 0x12, 0x20, 0x4b, 0x12, 0x2f, 0x80, 0x78, 
-0x8f, 0xe6, 0xff, 0x12, 0x19, 0xbb, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x12, 0x0f, 0x89, 0x78, 
-0x8b, 0xef, 0xf6, 0x12, 0x2e, 0x4c, 0x12, 0x2e, 0xa5, 0x90, 0xf9, 0x65, 0xe0, 0x54, 0x03, 0x60, 
-0x16, 0x78, 0x8b, 0xe6, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, 
-0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xf9, 0x15, 0xe0, 0x14, 0xf0, 0xe0, 0x70, 0x02, 
-0xd2, 0xb3, 0x02, 0x10, 0x0c, 0x8f, 0x69, 0x12, 0x27, 0x19, 0x12, 0x20, 0x2d, 0xe0, 0x54, 0x3f, 
-0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0x54, 0x3f, 0xf0, 0x08, 0xe6, 0xfe, 0x08, 
-0xe6, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x20, 0x25, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x2f, 0x80, 0x74, 
-0x74, 0x25, 0x69, 0xf8, 0x74, 0xfb, 0x56, 0xf6, 0x7f, 0x00, 0x22, 0x8f, 0x37, 0xc2, 0x08, 0x12, 
-0x27, 0x19, 0x12, 0x20, 0x38, 0x78, 0x84, 0x12, 0x20, 0x1d, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x20, 
-0x70, 0x12, 0x20, 0x21, 0xe0, 0x20, 0xe0, 0xf6, 0xef, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 
-0x83, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x2f, 0x80, 0xaf, 0x37, 0x12, 0x19, 0xbb, 0x22, 0x12, 0x0f, 
-0x89, 0x12, 0x27, 0x19, 0x12, 0x20, 0x70, 0x24, 0x06, 0x12, 0x20, 0x23, 0xe0, 0xfd, 0x12, 0x20, 
-0x53, 0x90, 0x00, 0x03, 0x12, 0x20, 0x78, 0x24, 0x05, 0x12, 0x20, 0x25, 0xe0, 0x90, 0x00, 0x04, 
-0x12, 0x14, 0x0d, 0x12, 0x2f, 0x80, 0x7d, 0x02, 0xe4, 0xff, 0x12, 0x2c, 0xc0, 0x02, 0x10, 0x0c, 
-0xae, 0x05, 0x12, 0x18, 0xed, 0xef, 0x12, 0x14, 0x0d, 0x0e, 0x0e, 0x0e, 0xee, 0xd3, 0x95, 0x35, 
-0xe4, 0x95, 0x34, 0x40, 0x02, 0xae, 0x35, 0xee, 0xd3, 0x94, 0x08, 0x74, 0x80, 0x94, 0x81, 0x40, 
-0x0a, 0x7e, 0x03, 0x90, 0x00, 0x02, 0x74, 0x02, 0x12, 0x14, 0x0d, 0xaf, 0x06, 0x12, 0x2f, 0x6a, 
-0x22, 0x12, 0x0f, 0x89, 0x78, 0x8c, 0x12, 0x20, 0x9e, 0x30, 0xe2, 0x07, 0x7f, 0x13, 0x12, 0x2e, 
-0xa5, 0x80, 0x1b, 0x78, 0x8c, 0xe6, 0x24, 0x74, 0xf8, 0xe6, 0x20, 0xe1, 0x07, 0x7f, 0x12, 0x12, 
-0x2e, 0xa5, 0x80, 0x0a, 0x78, 0x8c, 0xe6, 0xff, 0x12, 0x21, 0x6e, 0x12, 0x2e, 0xa5, 0x02, 0x10, 
-0x0c, 0xae, 0x07, 0xed, 0x54, 0x03, 0x64, 0x01, 0x60, 0x03, 0x7f, 0x10, 0x22, 0xed, 0x54, 0x7c, 
-0xc3, 0x94, 0x04, 0x50, 0x03, 0x7f, 0x0b, 0x22, 0x74, 0x74, 0x2e, 0xf8, 0x74, 0x02, 0x46, 0xf6, 
-0x74, 0x95, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0xed, 0xf0, 0x7f, 0x00, 0x22, 0xbf, 
-0x03, 0x06, 0x7c, 0xff, 0x7d, 0xe0, 0x80, 0x04, 0x7c, 0xff, 0x7d, 0xe2, 0x8d, 0x82, 0x8c, 0x83, 
-0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x20, 0x25, 0xe0, 0x44, 0x80, 0xf0, 0x74, 
-0x74, 0x2f, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 0x00, 0x22, 0x12, 0x0f, 0x89, 0xe5, 0x31, 0x64, 
-0x09, 0x70, 0x04, 0xe5, 0x30, 0x64, 0x01, 0x60, 0x16, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xff, 
-0xc3, 0xe5, 0x31, 0x9f, 0xe5, 0x30, 0x94, 0x00, 0x40, 0x05, 0x12, 0x25, 0x9c, 0x80, 0x03, 0x12, 
-0x2f, 0x76, 0x02, 0x10, 0x0c, 0x90, 0xff, 0xfc, 0xe0, 0x20, 0xe7, 0x1f, 0xc2, 0xaf, 0x7d, 0xff, 
-0xac, 0x05, 0x1d, 0xec, 0x60, 0x15, 0x7e, 0x04, 0x7f, 0x00, 0xef, 0x1f, 0xaa, 0x06, 0x70, 0x01, 
-0x1e, 0x4a, 0x60, 0xec, 0x90, 0xff, 0x92, 0xe4, 0xf0, 0x80, 0xef, 0x22, 0x12, 0x0f, 0x89, 0x78, 
-0x6c, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x30, 0xe0, 0x12, 0x30, 0xe1, 0x0f, 0x90, 0xff, 0xfc, 0xe0, 
-0x44, 0x20, 0xf0, 0x7f, 0x04, 0x12, 0x11, 0x9f, 0x12, 0x19, 0x55, 0x02, 0x10, 0x0c, 0x8e, 0x65, 
-0x8f, 0x66, 0xe5, 0x66, 0x15, 0x66, 0xae, 0x65, 0x70, 0x02, 0x15, 0x65, 0xd3, 0x94, 0x00, 0xee, 
-0x94, 0x00, 0x40, 0x09, 0x7e, 0x07, 0x7f, 0xd0, 0x12, 0x0f, 0x62, 0x80, 0xe5, 0x22, 0x11, 0x1a, 
-0x2b, 0x1c, 0x23, 0x56, 0x2f, 0x5c, 0x2d, 0xcc, 0x2d, 0x7a, 0x2e, 0x6b, 0x2c, 0x8e, 0x2b, 0x66, 
-0x2b, 0xec, 0x2c, 0xf1, 0x2e, 0x2d, 0x1b, 0xe6, 0x2b, 0xaf, 0x28, 0x67, 0x0e, 0x12, 0x0f, 0x89, 
-0x78, 0x8d, 0x12, 0x20, 0x9e, 0x20, 0xe2, 0x07, 0x7f, 0x11, 0x12, 0x2e, 0xa5, 0x80, 0x0a, 0x78, 
-0x8d, 0xe6, 0xff, 0x12, 0x2c, 0x25, 0x12, 0x2e, 0xa5, 0x02, 0x10, 0x0c, 0x8f, 0x67, 0x12, 0x2c, 
-0x25, 0xaf, 0x67, 0x12, 0x27, 0x19, 0x12, 0x20, 0x38, 0x12, 0x2f, 0x80, 0x74, 0x74, 0x25, 0x67, 
-0xf8, 0x74, 0xfd, 0x56, 0xf6, 0xaf, 0x67, 0x12, 0x19, 0xbb, 0x22, 0x12, 0x0f, 0x89, 0xe5, 0x31, 
-0x64, 0x09, 0x70, 0x04, 0xe5, 0x30, 0x64, 0x01, 0x60, 0x05, 0x12, 0x29, 0x2d, 0x80, 0x06, 0x12, 
-0x19, 0x7a, 0x12, 0x19, 0x82, 0x02, 0x10, 0x0c, 0x12, 0x27, 0xfb, 0x12, 0x12, 0x3b, 0x90, 0xf8, 
-0x04, 0xe0, 0xff, 0x60, 0x05, 0x7d, 0x01, 0x12, 0x11, 0xd8, 0x12, 0x26, 0xa3, 0x12, 0x12, 0x77, 
-0x12, 0x10, 0xfa, 0x80, 0xe3, 0x12, 0x18, 0xed, 0xef, 0x12, 0x14, 0x0d, 0xe4, 0xf5, 0x2a, 0xf5, 
-0x2b, 0xef, 0x60, 0x03, 0x02, 0x2f, 0x76, 0xe4, 0xff, 0x12, 0x2f, 0x6a, 0x22, 0x90, 0xff, 0xf0, 
-0xe0, 0xff, 0x54, 0xa0, 0x60, 0xf7, 0xef, 0x30, 0xe5, 0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 
-0xc3, 0x22, 0xd3, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 0x54, 0x28, 0x60, 0xf7, 0xef, 0x30, 0xe5, 
-0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 0xd3, 0x22, 0xef, 0x30, 0xe7, 0x08, 0x12, 
-0x18, 0xad, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0xef, 0x12, 0x18, 0xf7, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 
-0x81, 0x01, 0x82, 0x02, 0x83, 0x03, 0x87, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 
-0x00, 0x40, 0x00, 0x08, 0x00, 0x78, 0x84, 0x12, 0x20, 0x2f, 0xa3, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 
-0x06, 0x54, 0x7f, 0xf0, 0x44, 0x80, 0xf0, 0x22, 0x85, 0x34, 0x30, 0x85, 0x35, 0x31, 0x90, 0xff, 
-0x82, 0xe0, 0x54, 0xf7, 0xf0, 0xa3, 0xe0, 0x54, 0x7f, 0xf0, 0x22, 0xe4, 0xfe, 0xee, 0x90, 0x2f, 
-0x00, 0x93, 0xb5, 0x07, 0x02, 0xd3, 0x22, 0x0e, 0xbe, 0x07, 0xf2, 0xc3, 0x22, 0x00, 0x08, 0x18, 
-0x38, 0x28, 0x01, 0x81, 0x10, 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x0f, 0x89, 0x7f, 
-0x02, 0x12, 0x10, 0x18, 0x12, 0x19, 0x55, 0x02, 0x10, 0x0c, 0x75, 0x30, 0x00, 0x8f, 0x31, 0x12, 
-0x18, 0x49, 0x12, 0x29, 0x2d, 0x22, 0x12, 0x19, 0x82, 0x12, 0x19, 0x3e, 0x12, 0x19, 0x7a, 0x22, 
-0xc2, 0x08, 0x22, 
+0xd9, 0xf5, 0xeb, 0x70, 0x10, 0xea, 0xf0, 0xc0, 0x07, 0x12, 0x12, 0x41, 0xad, 0x07, 0xaf, 0x02, 
+0x12, 0x12, 0x58, 0xd0, 0x07, 0xa3, 0xa3, 0xa3, 0xdf, 0xce, 0x12, 0x11, 0x66, 0x80, 0xc1, 0x8f, 
+0x24, 0x12, 0x2a, 0x06, 0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x08, 0x12, 
+0x21, 0xf3, 0xe0, 0xfd, 0x12, 0x22, 0x8a, 0x8a, 0x83, 0x24, 0x0a, 0x12, 0x21, 0xf3, 0xed, 0xf0, 
+0x12, 0x22, 0x56, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xe0, 0xff, 0x12, 0x22, 0x99, 0x24, 0x09, 0x12, 
+0x21, 0xf3, 0xef, 0xf0, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe4, 0x20, 0x08, 0x12, 0x22, 0x09, 0xc0, 
+0x83, 0xc0, 0x82, 0xa3, 0xe0, 0x25, 0xe0, 0xff, 0x05, 0x82, 0xd5, 0x82, 0x02, 0x15, 0x83, 0x15, 
+0x82, 0xe0, 0x33, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0xa3, 0xef, 0xf0, 0x78, 0x80, 0x12, 0x22, 0x09, 
+0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0xff, 0x12, 0x22, 0x8a, 0x8a, 0x83, 0x24, 0x08, 0x12, 0x21, 
+0xf3, 0xef, 0xf0, 0xed, 0x12, 0x22, 0x99, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xed, 0xf0, 0x12, 0x21, 
+0xfb, 0xe0, 0xff, 0x30, 0xe7, 0x19, 0x12, 0x22, 0x6e, 0x12, 0x21, 0xf3, 0xe0, 0x60, 0x09, 0x12, 
+0x21, 0xfb, 0xef, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x12, 0x21, 0xfb, 0xef, 0x54, 0xfd, 0xf0, 0x78, 
+0x7e, 0x12, 0x22, 0x09, 0xa3, 0xa3, 0xe0, 0xff, 0x53, 0x07, 0xc7, 0x08, 0xe6, 0xfc, 0x08, 0xe6, 
+0xfd, 0x12, 0x22, 0x43, 0xa3, 0xe0, 0x30, 0xe3, 0x12, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 
+0x05, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x31, 0x94, 0x93, 0x42, 0x07, 0x53, 0x07, 0xfb, 0x78, 0x80, 
+0xe6, 0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x24, 0x06, 0x12, 0x21, 0xf3, 0xe0, 0x60, 0x03, 0x43, 0x07, 
+0x04, 0x53, 0x07, 0xfc, 0x78, 0x80, 0x12, 0x22, 0x7a, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0x42, 
+0x07, 0x43, 0x07, 0x80, 0x12, 0x22, 0x8a, 0xf5, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xef, 0xf0, 0x12, 
+0x22, 0x99, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0xff, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xe0, 
+0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe1, 0x05, 0x53, 0x07, 0xdf, 0x80, 0x03, 0x43, 0x07, 0x20, 0xec, 
+0x30, 0xe4, 0x05, 0x53, 0x07, 0xef, 0x80, 0x03, 0x43, 0x07, 0x10, 0x12, 0x21, 0xfb, 0xe0, 0xfe, 
+0x54, 0x03, 0x60, 0x73, 0x53, 0x07, 0xdf, 0xee, 0x30, 0xe1, 0x69, 0x78, 0x80, 0x12, 0x22, 0x6f, 
+0x12, 0x21, 0xf3, 0xe0, 0x12, 0x1b, 0x4c, 0x14, 0xa6, 0x00, 0x14, 0xda, 0x01, 0x14, 0xdf, 0x03, 
+0x14, 0xda, 0x05, 0x14, 0xdf, 0x07, 0x14, 0xda, 0x09, 0x14, 0xdf, 0x0b, 0x14, 0xda, 0x0d, 0x14, 
+0xdf, 0x0f, 0x00, 0x00, 0x14, 0xe7, 0xe5, 0x24, 0x64, 0x03, 0x70, 0x21, 0x90, 0xf9, 0x15, 0xe0, 
+0x30, 0xe2, 0x0d, 0x30, 0xb4, 0x05, 0x43, 0x07, 0x02, 0x80, 0x2c, 0x53, 0x07, 0xfd, 0x80, 0x27, 
+0x30, 0x95, 0x05, 0x43, 0x07, 0x02, 0x80, 0x1f, 0x53, 0x07, 0xfd, 0x80, 0x1a, 0x30, 0x93, 0x05, 
+0x43, 0x07, 0x02, 0x80, 0x12, 0x53, 0x07, 0xfd, 0x80, 0x0d, 0x43, 0x07, 0x02, 0x80, 0x08, 0x53, 
+0x07, 0xfd, 0x80, 0x03, 0x53, 0x07, 0xfd, 0x12, 0x22, 0x78, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xef, 
+0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xff, 0x12, 0x21, 0xfb, 0xe0, 0xfe, 0x54, 
+0x03, 0x70, 0x03, 0x02, 0x15, 0xd7, 0xee, 0x20, 0xe1, 0x03, 0x02, 0x15, 0xd4, 0x12, 0x22, 0x6e, 
+0x12, 0x21, 0xf3, 0xe0, 0x12, 0x1b, 0x4c, 0x15, 0x36, 0x00, 0x15, 0x6c, 0x01, 0x15, 0x6c, 0x03, 
+0x15, 0xa0, 0x05, 0x15, 0xa0, 0x07, 0x15, 0x86, 0x09, 0x15, 0x86, 0x0b, 0x15, 0xba, 0x0d, 0x15, 
+0xba, 0x0f, 0x00, 0x00, 0x15, 0xd7, 0xe5, 0x24, 0x64, 0x03, 0x70, 0x23, 0x90, 0xf9, 0x15, 0xe0, 
+0x30, 0xe2, 0x0f, 0x30, 0xb1, 0x06, 0x53, 0x07, 0x7f, 0x02, 0x15, 0xd7, 0x43, 0x07, 0x80, 0x02, 
+0x15, 0xd7, 0x30, 0x94, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x7d, 0x43, 0x07, 0x80, 0x80, 0x78, 0x30, 
+0x92, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x70, 0x43, 0x07, 0x80, 0x80, 0x6b, 0xe5, 0x24, 0xb4, 0x03, 
+0x09, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xdf, 
+0xf0, 0x53, 0x07, 0x7f, 0x80, 0x51, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x44, 
+0x10, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x20, 0xf0, 0x53, 0x07, 0x7f, 0x80, 0x37, 
+0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x07, 0x90, 0xff, 
+0x9e, 0xe0, 0x54, 0xdf, 0xf0, 0x43, 0x07, 0x80, 0x80, 0x1d, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 
+0xff, 0x9e, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x20, 0xf0, 0x43, 
+0x07, 0x80, 0x80, 0x03, 0x53, 0x07, 0x7f, 0x78, 0x80, 0x12, 0x22, 0x3f, 0xe0, 0xfc, 0xa3, 0xe0, 
+0xfd, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x20, 0x80, 0x03, 0x53, 0x07, 0xdf, 0xec, 0x30, 0xe3, 0x05, 
+0x43, 0x07, 0x40, 0x80, 0x03, 0x53, 0x07, 0xbf, 0xec, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x10, 0x80, 
+0x03, 0x53, 0x07, 0xef, 0xed, 0x30, 0xe4, 0x05, 0x43, 0x07, 0x08, 0x80, 0x03, 0x53, 0x07, 0xf7, 
+0xed, 0x30, 0xe5, 0x05, 0x43, 0x07, 0x04, 0x80, 0x03, 0x53, 0x07, 0xfb, 0xed, 0x30, 0xe6, 0x05, 
+0x43, 0x07, 0x01, 0x80, 0x03, 0x53, 0x07, 0xfe, 0xed, 0x30, 0xe7, 0x05, 0x43, 0x07, 0x02, 0x80, 
+0x03, 0x53, 0x07, 0xfd, 0x78, 0x7e, 0x12, 0x22, 0x3f, 0xa3, 0xef, 0xf0, 0x12, 0x31, 0xc7, 0x7f, 
+0x00, 0x22, 0x90, 0xff, 0xfa, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x16, 0xf0, 0x90, 0xff, 0xf9, 0x74, 
+0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcc, 0xe4, 0xfd, 0x12, 0x22, 0xa0, 0x90, 0xfa, 0xcc, 
+0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0x12, 0x18, 0xe2, 0xe5, 0x23, 0x30, 0xe7, 0x02, 0xd2, 
+0x02, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x24, 0x90, 0xfa, 0xcc, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, 
+0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, 0x74, 0x0b, 0xf0, 0x7b, 
+0x00, 0x7a, 0x00, 0x79, 0x23, 0x75, 0x2d, 0x00, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0xe5, 
+0x23, 0x24, 0x80, 0x90, 0xff, 0xf8, 0xf0, 0xe5, 0x23, 0x64, 0x07, 0x60, 0x1e, 0xe5, 0x23, 0x64, 
+0x06, 0x60, 0x18, 0xe5, 0x23, 0x64, 0x14, 0x60, 0x12, 0xe5, 0x23, 0x64, 0x41, 0x60, 0x0c, 0xe5, 
+0x23, 0x64, 0x1a, 0x70, 0x46, 0xe5, 0x24, 0x64, 0x02, 0x70, 0x40, 0xe5, 0x23, 0xb4, 0x07, 0x16, 
+0xd2, 0x94, 0xd2, 0x95, 0xd2, 0x92, 0xd2, 0x93, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x02, 0xf0, 0xa3, 
+0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1e, 0xe5, 0x23, 0xb4, 0x41, 0x12, 0x90, 0xf9, 0x15, 0xe0, 0x44, 
+0x06, 0xf0, 0xa3, 0xe0, 0x44, 0x06, 0xf0, 0xd2, 0xb1, 0xd2, 0xb4, 0x80, 0x07, 0x90, 0xf9, 0x15, 
+0xe0, 0x44, 0x01, 0xf0, 0x90, 0xf9, 0x16, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x23, 0x64, 0x42, 0x60, 
+0x05, 0xe5, 0x23, 0xb4, 0x43, 0x0c, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x80, 0xf0, 0xa3, 0xe0, 0x44, 
+0x80, 0xf0, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, 0x74, 0x0d, 0xf0, 0x12, 0x18, 0xe2, 0x90, 0xff, 
+0xf5, 0xe5, 0x23, 0xf0, 0xe4, 0xf5, 0x35, 0xf5, 0x33, 0xf5, 0x34, 0xf5, 0x32, 0x12, 0x1d, 0x84, 
+0x12, 0x1c, 0x30, 0x12, 0x1d, 0x8b, 0x90, 0xf9, 0x67, 0x12, 0x1b, 0x43, 0x90, 0xf9, 0x6c, 0x12, 
+0x1b, 0x43, 0x90, 0xff, 0xff, 0xe4, 0xf0, 0x90, 0xff, 0x83, 0xe0, 0xe4, 0xf0, 0x90, 0xff, 0x81, 
+0x74, 0x80, 0xf0, 0xa3, 0x74, 0x84, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xe4, 0xf5, 0x23, 0xe5, 0x23, 
+0x12, 0x1c, 0xa7, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x23, 0x12, 0x1c, 0xb5, 0xf5, 0x83, 0xe4, 0xf0, 
+0x05, 0x23, 0xe5, 0x23, 0xb4, 0x07, 0xe7, 0x78, 0x7a, 0x76, 0xfe, 0x08, 0x76, 0xf0, 0x90, 0x31, 
+0x4d, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xad, 0x07, 0x90, 0x31, 0x5a, 0xe4, 0x93, 0xff, 
+0x08, 0xf6, 0xff, 0xed, 0x54, 0x0f, 0xfd, 0x12, 0x1c, 0x97, 0x74, 0x84, 0xf0, 0xed, 0x75, 0xf0, 
+0x08, 0xa4, 0x24, 0x47, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xc3, 0x74, 0xf0, 
+0x9f, 0x78, 0x7b, 0xf6, 0x74, 0xfe, 0x94, 0x00, 0x18, 0x12, 0x1c, 0x28, 0xce, 0xc3, 0x13, 0xce, 
+0x13, 0xd8, 0xf9, 0xff, 0xed, 0x12, 0x1c, 0xf8, 0xef, 0xf0, 0xed, 0x12, 0x1d, 0x1e, 0xe4, 0xf5, 
+0x23, 0xe5, 0x23, 0x90, 0x31, 0x47, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xe5, 0x23, 0x25, 0xe0, 
+0x24, 0x4e, 0xf5, 0x82, 0xe4, 0x34, 0x31, 0xf5, 0x83, 0xe4, 0x93, 0x08, 0xf6, 0xed, 0x30, 0xe7, 
+0x53, 0x18, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1c, 0x97, 0x12, 0x1d, 0x06, 0x24, 0x47, 0xf5, 0x82, 
+0xe4, 0x34, 0xff, 0x12, 0x1c, 0x18, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0xe9, 0x12, 
+0x1c, 0xf8, 0xef, 0xf0, 0x12, 0x1c, 0x1f, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d, 
+0x0b, 0x24, 0x45, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x12, 0x1d, 0x1e, 
+0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x46, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 
+0xf0, 0x02, 0x18, 0xb7, 0x78, 0x78, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1c, 0xea, 0x12, 0x1d, 0x06, 
+0x24, 0x07, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x12, 0x1c, 0x18, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 
+0xf9, 0x12, 0x1d, 0x0b, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0x12, 
+0x1c, 0x1f, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d, 0x0b, 0x24, 0x05, 0xf5, 0x82, 
+0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 
+0xe4, 0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 
+0xe4, 0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 0x23, 0xe5, 0x23, 0x64, 0x04, 0x60, 0x03, 0x02, 
+0x17, 0xe1, 0x90, 0x31, 0x4c, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0x12, 0x1c, 0xe8, 0xe4, 0xf0, 
+0x90, 0x31, 0x4b, 0x93, 0xff, 0xf6, 0x12, 0x1c, 0x95, 0xe4, 0xf0, 0x90, 0xff, 0xfd, 0x74, 0x05, 
+0xf0, 0x22, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12, 
+0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x25, 0xd7, 0xe7, 0x09, 0xf6, 0x08, 
+0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e, 0x88, 0x82, 0x8c, 0x83, 
+0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x78, 
+0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83, 0xe3, 0x09, 0xf0, 0xa3, 
+0xdf, 0xfa, 0x80, 0x64, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x58, 
+0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x4c, 0x80, 0xd2, 0x80, 0xfa, 
+0x80, 0xc6, 0x80, 0xd4, 0x80, 0x69, 0x80, 0xf2, 0x80, 0x33, 0x80, 0x10, 0x80, 0xa6, 0x80, 0xea, 
+0x80, 0x9a, 0x80, 0xa8, 0x80, 0xda, 0x80, 0xe2, 0x80, 0xca, 0x80, 0x33, 0x89, 0x82, 0x8a, 0x83, 
+0xec, 0xfa, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xf0, 0xa3, 0xc8, 
+0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0x0d, 0x89, 0x82, 0x8a, 
+0x83, 0xe4, 0x93, 0xa3, 0xf6, 0x08, 0xdf, 0xf9, 0xec, 0xfa, 0xa9, 0xf0, 0xed, 0xfb, 0x22, 0x89, 
+0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xf0, 
+0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xea, 0xde, 0xe8, 0x80, 0xdb, 0x89, 
+0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc, 0x88, 0xf0, 0xef, 0x60, 
+0x01, 0x0e, 0x4e, 0x60, 0xc3, 0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xb9, 0xf5, 
+0x82, 0xeb, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xaf, 0x23, 0x23, 0x45, 0x82, 0x23, 0x90, 0x19, 
+0x4c, 0x73, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 
+0xfe, 0x02, 0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x0c, 0xe5, 0x82, 
+0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xf8, 
+0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22, 0xe5, 0x82, 0x29, 0xf5, 0x82, 
+0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xf0, 
+0x22, 0x50, 0x02, 0xf7, 0x22, 0xbb, 0xfe, 0x01, 0xf3, 0x22, 0xf8, 0xbb, 0x01, 0x0d, 0xe5, 0x82, 
+0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0, 0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 
+0xc8, 0xf6, 0x22, 0xbb, 0xfe, 0x05, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0x22, 0xc5, 0xf0, 0xf8, 0xa3, 
+0xe0, 0x28, 0xf0, 0xc5, 0xf0, 0xf8, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 0x83, 0xe0, 0x38, 
+0xf0, 0x22, 0xa3, 0xf8, 0xe0, 0xc5, 0xf0, 0x25, 0xf0, 0xf0, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 
+0x15, 0x83, 0xe0, 0xc8, 0x38, 0xf0, 0xe8, 0x22, 0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 
+0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0, 0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 
+0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe, 0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 
+0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83, 0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22, 
+0xbb, 0x01, 0x0a, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0xe5, 0xf0, 0xa3, 0xf0, 0x22, 0x50, 0x06, 0xf7, 
+0x09, 0xa7, 0xf0, 0x19, 0x22, 0xbb, 0xfe, 0x06, 0xf3, 0xe5, 0xf0, 0x09, 0xf3, 0x19, 0x22, 0xf8, 
+0xbb, 0x01, 0x11, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0, 0xe5, 
+0xf0, 0xa3, 0xf0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x08, 0xa6, 0xf0, 0x22, 0xbb, 
+0xfe, 0x09, 0xe9, 0x25, 0x82, 0xc8, 0xf2, 0xe5, 0xf0, 0x08, 0xf2, 0x22, 0xa4, 0x25, 0x82, 0xf5, 
+0x82, 0xe5, 0xf0, 0x35, 0x83, 0xf5, 0x83, 0x22, 0xe6, 0xfb, 0x08, 0xe6, 0xfa, 0x08, 0xe6, 0xf9, 
+0x22, 0xeb, 0xf6, 0x08, 0xea, 0xf6, 0x08, 0xe9, 0xf6, 0x22, 0xe0, 0xfb, 0xa3, 0xe0, 0xfa, 0xa3, 
+0xe0, 0xf9, 0x22, 0xeb, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xe9, 0xf0, 0x22, 0xd0, 0x83, 0xd0, 0x82, 
+0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 0xf8, 0x74, 0x01, 
+0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 0xa3, 0xa3, 0xa3, 
+0x80, 0xdf, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0xe5, 0x4c, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, 
+0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0x74, 0x11, 0x12, 
+0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x06, 
+0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 
+0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0xe4, 0x12, 0x1a, 0x38, 0x04, 0x25, 
+0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0xe4, 0x12, 0x1a, 
+0x38, 0x04, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x04, 0xe0, 0xab, 
+0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 
+0x37, 0xf5, 0x37, 0x90, 0xff, 0x05, 0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, 
+0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x22, 0xf5, 0x83, 0xe0, 0x54, 
+0x08, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x22, 0xf5, 0x83, 0xef, 0xf0, 0xfd, 0x7c, 0x00, 0xc3, 
+0x78, 0x7b, 0xe6, 0x9d, 0xf6, 0x18, 0xe6, 0x9c, 0xf6, 0xe6, 0xfe, 0x08, 0xe6, 0x78, 0x03, 0x22, 
+0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75, 0x38, 0x6f, 0x22, 0xe0, 0x44, 0x04, 0xf0, 0x74, 0x12, 
+0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xe0, 0x22, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x7e, 
+0x00, 0xc3, 0x90, 0xfa, 0xbd, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xbc, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, 
+0xb4, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0xef, 0x25, 0x4f, 0xf5, 0x4f, 0xee, 0x35, 0x4e, 0xf5, 
+0x4e, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb1, 0x90, 0xfa, 0xb4, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 
+0xf5, 0x2e, 0x22, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0x8e, 0x83, 0x24, 0x04, 0xf5, 0x82, 0xe4, 
+0x35, 0x83, 0xf5, 0x83, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x40, 0xf5, 0x82, 0xe4, 
+0x34, 0xff, 0xf5, 0x83, 0x22, 0xe5, 0x4d, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x48, 0xf5, 0x82, 0xe4, 
+0x34, 0xff, 0x22, 0xe5, 0x4d, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x34, 0xff, 
+0x22, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x24, 0xfc, 0x22, 0x90, 0xff, 0x00, 0xe0, 0x54, 0x1f, 0x22, 
+0x90, 0xfa, 0xbb, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x22, 0x75, 0x33, 0x00, 0x8f, 0x34, 0x90, 0xf9, 
+0x6c, 0x12, 0x1b, 0x3a, 0x90, 0x00, 0x02, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 
+0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x41, 0xf5, 0x82, 
+0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x74, 0x80, 0xf0, 0x08, 0xe6, 0xff, 0xe9, 0x75, 0xf0, 0x08, 
+0xa4, 0x22, 0x74, 0xaf, 0x25, 0x22, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0x22, 0x75, 0xf0, 
+0x08, 0xa4, 0x24, 0x42, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 0xf0, 0x22, 0x90, 
+0xff, 0x82, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x03, 0xf0, 0x90, 0xff, 
+0xfc, 0xe0, 0x54, 0xfd, 0xf0, 0x22, 0x78, 0x67, 0xe6, 0x54, 0xfd, 0xf6, 0x90, 0xff, 0xfd, 0x74, 
+0x65, 0xf0, 0x22, 0x12, 0x1b, 0x1c, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x22, 0x7b, 0x01, 0x7a, 
+0xfa, 0x79, 0xb4, 0x22, 0x90, 0xff, 0x80, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0x83, 0xe0, 
+0x54, 0x7f, 0xf0, 0x22, 0xe0, 0xff, 0x90, 0xf9, 0x67, 0x02, 0x1b, 0x3a, 0x90, 0xff, 0xa4, 0xe0, 
+0x44, 0x02, 0xf0, 0x22, 0x75, 0x39, 0x01, 0x75, 0x3a, 0x09, 0x22, 0x7b, 0x01, 0x7a, 0xf9, 0x79, 
+0x6f, 0x22, 0xd3, 0xe5, 0x3c, 0x94, 0x08, 0xe5, 0x3b, 0x94, 0x01, 0x22, 0x90, 0xfa, 0xbb, 0xe0, 
+0xff, 0x90, 0xfa, 0xb7, 0xf0, 0x22, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xef, 0x22, 0x90, 0xff, 0xb4, 
+0xe0, 0x54, 0xef, 0x22, 0x12, 0x10, 0x03, 0x78, 0x88, 0xef, 0xf6, 0x12, 0x2a, 0x06, 0x12, 0x22, 
+0x4a, 0x8e, 0x83, 0x24, 0x09, 0x12, 0x21, 0xf3, 0xe0, 0xfd, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x0a, 
+0x12, 0x22, 0x52, 0x24, 0x0a, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x00, 0x0b, 0x12, 0x1a, 0x4a, 0x12, 
+0x22, 0x4a, 0xf5, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf5, 0x53, 0x12, 0x22, 0x56, 0x24, 
+0x04, 0x12, 0x21, 0xf3, 0xe0, 0xf5, 0x54, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xf5, 0x55, 
+0xe5, 0x53, 0xc4, 0x13, 0x13, 0x13, 0x54, 0x01, 0x78, 0x88, 0xf6, 0xd3, 0x94, 0x00, 0x40, 0x06, 
+0xe5, 0x54, 0x30, 0xe1, 0x01, 0x06, 0x78, 0x88, 0xe6, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x0c, 0xef, 
+0x12, 0x1a, 0x4a, 0x78, 0x80, 0x12, 0x22, 0x09, 0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x53, 
+0x07, 0x0c, 0x53, 0x06, 0xe6, 0xe5, 0x53, 0x30, 0xe5, 0x03, 0x43, 0x07, 0x01, 0xe5, 0x54, 0x20, 
+0xe5, 0x0e, 0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, 0x03, 0x43, 0x07, 0x02, 
+0xe5, 0x53, 0x30, 0xe3, 0x03, 0x43, 0x07, 0x10, 0xe5, 0x53, 0x30, 0xe2, 0x03, 0x43, 0x07, 0x20, 
+0xe5, 0x53, 0x54, 0x03, 0x60, 0x03, 0x43, 0x07, 0x40, 0xe5, 0x53, 0x30, 0xe1, 0x03, 0x43, 0x07, 
+0x80, 0xe5, 0x53, 0x30, 0xe4, 0x03, 0x43, 0x06, 0x01, 0xe5, 0x53, 0x30, 0xe6, 0x03, 0x43, 0x06, 
+0x08, 0xe5, 0x54, 0x20, 0xe4, 0x0e, 0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, 
+0x03, 0x43, 0x06, 0x10, 0x53, 0x07, 0xfb, 0x53, 0x06, 0x79, 0x90, 0x00, 0x05, 0xee, 0x8f, 0xf0, 
+0x12, 0x1a, 0xef, 0xe5, 0x55, 0x30, 0xe3, 0x12, 0x54, 0x30, 0xff, 0xc4, 0x54, 0x0f, 0x12, 0x22, 
+0x2c, 0x90, 0x00, 0x08, 0xef, 0x12, 0x1a, 0x4a, 0x80, 0x0a, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x08, 
+0xe4, 0x12, 0x1a, 0x4a, 0xe5, 0x55, 0x54, 0x03, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x07, 0xef, 0x12, 
+0x1a, 0x4a, 0xe5, 0x55, 0x54, 0x04, 0xff, 0xc3, 0x13, 0x90, 0x00, 0x09, 0x12, 0x1a, 0x4a, 0x90, 
+0x00, 0x07, 0x12, 0x1a, 0x0b, 0x70, 0x13, 0x12, 0x22, 0x2d, 0xe9, 0x24, 0x09, 0xf9, 0xe4, 0x3a, 
+0xfa, 0x12, 0x19, 0xf2, 0xff, 0xc3, 0x13, 0x12, 0x1a, 0x38, 0x12, 0x22, 0x78, 0x24, 0x08, 0x12, 
+0x21, 0xf3, 0xe0, 0xfe, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xe0, 
+0xfd, 0xee, 0xed, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x03, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0xef, 0x12, 
+0x31, 0xc7, 0x7d, 0x0a, 0xe4, 0xff, 0x12, 0x2f, 0x18, 0x02, 0x10, 0x86, 0x90, 0xfa, 0xe3, 0xe0, 
+0xb4, 0x03, 0x06, 0x7e, 0x00, 0x7f, 0x40, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x08, 0x90, 0xfa, 0xd7, 
+0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0xff, 0x7e, 0x00, 0x90, 0xfa, 
+0xd3, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x70, 0x03, 0x7f, 0x08, 0x22, 0x90, 0x00, 0x08, 0x12, 0x1a, 
+0x98, 0xff, 0x90, 0xfa, 0xd5, 0xe5, 0xf0, 0xf0, 0xa3, 0xef, 0xf0, 0xae, 0x02, 0xaf, 0x01, 0x8e, 
+0x50, 0x8f, 0x51, 0x74, 0x0a, 0x25, 0x51, 0xf5, 0x51, 0xe4, 0x35, 0x50, 0xf5, 0x50, 0x90, 0xfa, 
+0xd8, 0xe0, 0xff, 0x14, 0xfe, 0x90, 0xfa, 0xd6, 0xe0, 0x5e, 0xfe, 0xc3, 0xef, 0x9e, 0xff, 0x90, 
+0xfa, 0xda, 0xf0, 0xc3, 0x90, 0xfa, 0xd4, 0xe0, 0x9f, 0x90, 0xfa, 0xd3, 0xe0, 0x94, 0x00, 0x50, 
+0x06, 0xa3, 0xe0, 0x90, 0xfa, 0xda, 0xf0, 0x12, 0x1f, 0xfb, 0x60, 0x03, 0xe0, 0xff, 0x22, 0x12, 
+0x2d, 0x5a, 0x90, 0xfa, 0xd3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x60, 0x2b, 0x90, 0xfa, 0xd7, 
+0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x07, 0xe0, 0x90, 0xfa, 0xda, 
+0xf0, 0x80, 0x08, 0x90, 0xfa, 0xd4, 0xe0, 0x90, 0xfa, 0xda, 0xf0, 0x12, 0x1f, 0xfb, 0x60, 0x03, 
+0xe0, 0xff, 0x22, 0x12, 0x2d, 0x5a, 0x80, 0xca, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x52, 0xe4, 0xf5, 
+0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x7f, 0x00, 0x22, 0xaa, 0x50, 0xa9, 0x51, 0x7b, 
+0x01, 0x90, 0xfa, 0xd5, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xda, 0xe0, 0xf5, 0x4a, 0x12, 
+0x28, 0x9f, 0x90, 0xfa, 0xd9, 0xef, 0xf0, 0x22, 0xef, 0x24, 0xae, 0x60, 0x52, 0x24, 0xfe, 0x60, 
+0x2e, 0x24, 0xfe, 0x70, 0x03, 0x02, 0x20, 0xbb, 0x24, 0x06, 0x60, 0x03, 0x02, 0x21, 0x03, 0x78, 
+0x71, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xa5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x33, 
+0x90, 0xfa, 0x91, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xaf, 0x74, 0x01, 0xf0, 0x22, 0x78, 
+0x72, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xb5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x43, 
+0x90, 0xfa, 0x93, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xb0, 0x74, 0x01, 0xf0, 0x22, 0x90, 
+0xfa, 0x9d, 0xe0, 0xa3, 0x20, 0xe5, 0x03, 0x02, 0x21, 0x03, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 
+0xca, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xca, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 
+0xa6, 0x12, 0x22, 0x5d, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xca, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 
+0xcb, 0xe0, 0xff, 0x74, 0x34, 0xfe, 0x12, 0x2c, 0xb4, 0xef, 0x70, 0x57, 0x90, 0xfa, 0xcb, 0xe0, 
+0xff, 0x74, 0x34, 0x90, 0xfa, 0x95, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0x90, 0xfa, 0xa7, 0xe0, 0xa3, 
+0x30, 0xe5, 0x40, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xca, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xca, 
+0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 0xb6, 0x12, 0x22, 0x5d, 0x90, 0xff, 0xb6, 
+0xe0, 0x90, 0xfa, 0xca, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 0xcb, 0xe0, 0xff, 0x74, 0x44, 0xfe, 0x12, 
+0x2c, 0xb4, 0xef, 0x70, 0x0e, 0x90, 0xfa, 0xcb, 0xe0, 0xff, 0x74, 0x44, 0x90, 0xfa, 0x97, 0xf0, 
+0xef, 0xa3, 0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 
+0x00, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 
+0x07, 0x90, 0xff, 0x92, 0xe0, 0xff, 0x90, 0xfa, 0xc9, 0xf0, 0x90, 0xff, 0x92, 0xe4, 0xf0, 0xef, 
+0x12, 0x1b, 0x4c, 0x21, 0xbb, 0x26, 0x21, 0xbb, 0x2e, 0x21, 0x5e, 0x30, 0x21, 0x5e, 0x32, 0x21, 
+0x6c, 0x38, 0x21, 0x7e, 0x3a, 0x21, 0xb0, 0x3e, 0x21, 0x9b, 0x44, 0x21, 0x90, 0x46, 0x21, 0xa6, 
+0x50, 0x21, 0xa6, 0x52, 0x21, 0xa6, 0x54, 0x21, 0xa6, 0x56, 0x00, 0x00, 0x21, 0xc0, 0x90, 0xfa, 
+0xc9, 0xe0, 0xfd, 0x7c, 0x00, 0x7f, 0x01, 0x12, 0x11, 0x16, 0x80, 0x62, 0x7c, 0x00, 0x7d, 0x01, 
+0x7f, 0x03, 0x12, 0x11, 0x16, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x50, 0x7c, 0x00, 
+0x7d, 0x01, 0x7f, 0x02, 0x12, 0x11, 0x16, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x40, 0xf0, 0x80, 0x3e, 
+0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x05, 0x12, 0x11, 0x16, 0x80, 0x33, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 
+0x06, 0x12, 0x11, 0x16, 0x80, 0x28, 0x90, 0xfa, 0xc9, 0xe0, 0xff, 0x12, 0x20, 0x18, 0x80, 0x1e, 
+0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x04, 0x12, 0x11, 0x16, 0x80, 0x13, 0x12, 0x27, 0x8d, 0x80, 0x0e, 
+0x90, 0xfa, 0xc9, 0xe0, 0x24, 0x00, 0xff, 0xe4, 0x34, 0xff, 0xfe, 0x12, 0x2c, 0xb4, 0xd0, 0x07, 
+0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0, 
+0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0x24, 
+0x04, 0x8e, 0x83, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x74, 0x12, 0x25, 0x24, 0xf5, 
+0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0x22, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 
+0x83, 0x22, 0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0x7b, 
+0xff, 0x7a, 0x31, 0x79, 0x99, 0x7e, 0x00, 0x7f, 0x0a, 0x02, 0x19, 0xcc, 0xff, 0x90, 0xf9, 0x6c, 
+0x02, 0x1b, 0x3a, 0x90, 0xf9, 0x67, 0x12, 0x1b, 0x3a, 0x90, 0x00, 0x04, 0x02, 0x1a, 0x0b, 0xe6, 
+0xfc, 0x08, 0xe6, 0xf5, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0x22, 0x78, 0x7e, 0xe6, 0xfe, 0x08, 0xe6, 
+0xff, 0x22, 0xed, 0x12, 0x1a, 0x4a, 0x8f, 0x82, 0x8e, 0x83, 0xe5, 0x82, 0x22, 0xef, 0xf0, 0x90, 
+0xfa, 0xcb, 0xe0, 0x54, 0x0f, 0x4e, 0xfe, 0xf0, 0xef, 0x54, 0xf0, 0x4e, 0xf0, 0x22, 0x08, 0xe6, 
+0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x24, 0x09, 0x22, 0x78, 0x7e, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x8c, 
+0x83, 0x22, 0xa6, 0x07, 0xe6, 0x24, 0x6e, 0xf8, 0xe6, 0x22, 0x78, 0x7e, 0xe6, 0xfa, 0x08, 0xe6, 
+0xfb, 0x22, 0x26, 0xf6, 0x18, 0xee, 0x36, 0xf6, 0x22, 0x8b, 0x82, 0x8a, 0x83, 0xe5, 0x82, 0x22, 
+0x8b, 0x25, 0x8a, 0x26, 0x89, 0x27, 0x8d, 0x28, 0x90, 0xfa, 0xcf, 0xe4, 0xf0, 0xa3, 0x74, 0x02, 
+0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xce, 0x90, 0xfa, 0xcf, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, 
+0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xce, 0xe0, 0x65, 0x28, 0x60, 0x46, 0xa3, 0xe0, 
+0xff, 0xa3, 0xe0, 0xa3, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x23, 0x2f, 0x90, 0xfa, 0xce, 0xe0, 
+0xff, 0x90, 0xfa, 0xd1, 0xe4, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0x12, 0x23, 0x2f, 0x90, 0xfa, 0xd1, 
+0xe0, 0xff, 0xa3, 0xe0, 0x90, 0xfa, 0xcf, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xfa, 0xce, 0xe0, 
+0xa3, 0x75, 0xf0, 0x00, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x04, 0x12, 0x1a, 
+0x6c, 0x02, 0x22, 0xb1, 0x90, 0xfa, 0xd0, 0xe0, 0x24, 0x01, 0xff, 0x90, 0xfa, 0xcf, 0xe0, 0x34, 
+0x00, 0xab, 0x25, 0xaa, 0x26, 0xa9, 0x27, 0x8f, 0xf0, 0x12, 0x1a, 0xd0, 0x7f, 0x00, 0x22, 0x7b, 
+0x01, 0x7a, 0xfa, 0x79, 0xce, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1a, 0x6c, 0x85, 
+0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x25, 0xd7, 0x8f, 0x62, 0x12, 0x2a, 0x06, 0x12, 0x22, 
+0x4a, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x21, 0xf3, 0xe0, 0x54, 0xfb, 0xf0, 0x44, 0x02, 0xf0, 0x08, 
+0x12, 0x22, 0x3f, 0xe0, 0xa3, 0x30, 0xe5, 0x0c, 0x12, 0x22, 0x56, 0x24, 0x0b, 0x12, 0x21, 0xf3, 
+0xe0, 0x44, 0x01, 0xf0, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 
+0x54, 0xb8, 0xfd, 0xf0, 0xe5, 0x62, 0x24, 0xfe, 0x44, 0x20, 0xfc, 0x4d, 0xf0, 0xe5, 0x82, 0x24, 
+0x04, 0x12, 0x21, 0xf3, 0xe0, 0x54, 0xb8, 0xf0, 0x4c, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0x74, 
+0x03, 0xf0, 0x18, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x05, 0x12, 0x21, 0xf3, 0xc0, 
+0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x74, 0x96, 0x25, 0x62, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 
+0xe0, 0x54, 0xfc, 0x44, 0x03, 0xfc, 0xed, 0x4c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 
+0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0x44, 0x80, 0xf0, 
+0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x62, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 0x00, 0x22, 0x12, 
+0x10, 0x03, 0x7f, 0x02, 0x12, 0x12, 0x19, 0x78, 0x67, 0xe6, 0x44, 0x02, 0xf6, 0xd2, 0xb0, 0xd2, 
+0xb1, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe7, 0x07, 0x90, 0xff, 0x9e, 0xe4, 0xf0, 0x80, 0x36, 0xd2, 
+0xb3, 0x90, 0xff, 0xa4, 0xe0, 0x90, 0xfa, 0x7b, 0xf0, 0x90, 0xff, 0xb4, 0xe0, 0x90, 0xfa, 0x7c, 
+0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x90, 0xfa, 0x79, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x90, 0xfa, 0x7a, 
+0xf0, 0x90, 0xff, 0xa4, 0x74, 0x30, 0xf0, 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xff, 0xa2, 0x74, 0x40, 
+0xf0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xfa, 0xe4, 0xe5, 0xa8, 0xf0, 0x75, 0xa8, 0x81, 0x90, 0xff, 
+0x92, 0xe0, 0x60, 0x04, 0xe4, 0xf0, 0x80, 0xf6, 0x90, 0xff, 0xfd, 0x74, 0x3a, 0xf0, 0x43, 0x87, 
+0x01, 0x00, 0x00, 0x00, 0x90, 0xfa, 0x7b, 0xe0, 0x90, 0xff, 0xa4, 0xf0, 0x90, 0xfa, 0x7c, 0xe0, 
+0x90, 0xff, 0xb4, 0xf0, 0x90, 0xfa, 0x79, 0xe0, 0x90, 0xff, 0xa2, 0xf0, 0x90, 0xfa, 0x7a, 0xe0, 
+0x90, 0xff, 0xb2, 0xf0, 0x90, 0xf9, 0x17, 0xe0, 0x60, 0x02, 0xc2, 0xb3, 0x90, 0xfa, 0xe4, 0xe0, 
+0xf5, 0xa8, 0x02, 0x10, 0x86, 0x8b, 0x5c, 0x8a, 0x5d, 0x89, 0x5e, 0x12, 0x2d, 0x3c, 0x90, 0xfa, 
+0xc0, 0x12, 0x1b, 0x43, 0xaa, 0x5d, 0xa9, 0x5e, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0x43, 0x90, 0xfa, 
+0xc4, 0xe4, 0x75, 0xf0, 0x0a, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0x3a, 0xe9, 0x24, 
+0x01, 0xf9, 0xe4, 0x3a, 0xfa, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x43, 0xab, 0x5c, 0xaa, 0x5d, 0xa9, 
+0x5e, 0x12, 0x2d, 0x48, 0xe0, 0xff, 0xc3, 0x13, 0xf0, 0xe4, 0x78, 0x82, 0xf6, 0x90, 0xfa, 0xbe, 
+0xe0, 0xff, 0x78, 0x82, 0xe6, 0xc3, 0x9f, 0x50, 0x4a, 0x90, 0xfa, 0xc0, 0x12, 0x2d, 0x1d, 0xff, 
+0x78, 0x83, 0xf6, 0x90, 0xfa, 0xc3, 0x12, 0x2d, 0x1d, 0xfe, 0xf4, 0x5f, 0xff, 0x78, 0x83, 0xf6, 
+0x12, 0x2d, 0x1a, 0x5e, 0x4f, 0xff, 0x78, 0x83, 0xf6, 0x12, 0x2d, 0x23, 0x75, 0xf0, 0x02, 0x12, 
+0x1a, 0x6c, 0x90, 0xfa, 0xc4, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x1a, 0x6c, 0xab, 0x5c, 0xaa, 0x5d, 
+0xa9, 0x5e, 0x90, 0x00, 0x04, 0x12, 0x1a, 0x0b, 0x30, 0xe4, 0x03, 0x12, 0x2d, 0x32, 0x78, 0x82, 
+0x06, 0x80, 0xaa, 0xe4, 0x90, 0xfa, 0xbf, 0xf0, 0x22, 0x8b, 0x56, 0x8a, 0x57, 0x89, 0x58, 0x90, 
+0xfa, 0xbf, 0x74, 0x06, 0xf0, 0xe4, 0x90, 0xfa, 0xbe, 0xf0, 0x12, 0x19, 0xf2, 0x24, 0x6e, 0x60, 
+0x26, 0x14, 0x70, 0x70, 0x12, 0x2d, 0x09, 0x60, 0x09, 0x24, 0x30, 0x70, 0x12, 0x12, 0x24, 0x95, 
+0x80, 0x62, 0x12, 0x2d, 0x53, 0x12, 0x1f, 0x2c, 0x90, 0xfa, 0xbf, 0xef, 0xf0, 0x80, 0x55, 0x90, 
+0xfa, 0xbf, 0x74, 0x81, 0xf0, 0x80, 0x4d, 0x12, 0x2d, 0x09, 0x60, 0x09, 0x24, 0x30, 0x70, 0x3e, 
+0x12, 0x2c, 0x5f, 0x80, 0x3f, 0xe5, 0x58, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x57, 0xfa, 0x7b, 0x01, 
+0xc0, 0x03, 0xc0, 0x02, 0xc0, 0x01, 0x12, 0x2d, 0x53, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0xfd, 
+0x90, 0x00, 0x08, 0x12, 0x1a, 0x98, 0xf5, 0x2e, 0x85, 0xf0, 0x2d, 0xd0, 0x01, 0xd0, 0x02, 0xd0, 
+0x03, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xbe, 0xef, 0xf0, 0xe4, 0xa3, 0xf0, 0x80, 0x06, 0x90, 0xfa, 
+0xbf, 0x74, 0x81, 0xf0, 0x90, 0xfa, 0xbf, 0xe0, 0x12, 0x2d, 0x53, 0x90, 0x00, 0x02, 0x12, 0x1a, 
+0x4a, 0x90, 0xfa, 0xbe, 0xe0, 0xff, 0x22, 0x8b, 0x29, 0x8a, 0x2a, 0x89, 0x2b, 0x8d, 0x2c, 0xe5, 
+0x2c, 0x70, 0x03, 0xaf, 0x2c, 0x22, 0x12, 0x2d, 0x82, 0x70, 0x16, 0x12, 0x2d, 0xa1, 0xe5, 0x2d, 
+0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0x1b, 0x50, 0xf2, 0x12, 0x26, 0x64, 0x40, 0x0b, 0x7f, 0x00, 
+0x22, 0x12, 0x2d, 0xa1, 0x12, 0x26, 0x64, 0x50, 0xf8, 0x90, 0xff, 0xf3, 0x74, 0xa1, 0xf0, 0xe5, 
+0x2c, 0xb4, 0x01, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0xf1, 0xe4, 0xf0, 
+0xf5, 0x2f, 0xe5, 0x2c, 0x14, 0xff, 0xe5, 0x2f, 0xc3, 0x9f, 0x50, 0x2a, 0x12, 0x31, 0x04, 0x40, 
+0x03, 0xaf, 0x2f, 0x22, 0xc3, 0xe5, 0x2c, 0x95, 0x2f, 0xff, 0xbf, 0x02, 0x07, 0x90, 0xff, 0xf0, 
+0xe0, 0x44, 0x02, 0xf0, 0x12, 0x2d, 0x94, 0x05, 0x2f, 0x74, 0x01, 0x25, 0x2b, 0xf5, 0x2b, 0xe4, 
+0x35, 0x2a, 0xf5, 0x2a, 0x80, 0xcc, 0x12, 0x31, 0x04, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x12, 0x2d, 
+0x94, 0xaf, 0x2c, 0x22, 0x90, 0xff, 0xf1, 0xe5, 0x2e, 0xf0, 0x02, 0x31, 0x1b, 0x12, 0x10, 0x03, 
+0x78, 0x84, 0x12, 0x22, 0x82, 0x30, 0xe1, 0x08, 0x7f, 0x13, 0x12, 0x30, 0xec, 0x02, 0x26, 0xfb, 
+0x78, 0x84, 0xe6, 0xf9, 0x24, 0x12, 0x12, 0x21, 0xff, 0xe0, 0xff, 0x30, 0xe7, 0x40, 0x54, 0x03, 
+0x60, 0x1e, 0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x44, 0x04, 
+0xf0, 0x80, 0x46, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfd, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x80, 0x39, 
+0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x80, 
+0x28, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf7, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1b, 0xef, 0x54, 
+0x03, 0x60, 0x14, 0xe9, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x07, 
+0x90, 0xff, 0xb4, 0xe0, 0x54, 0xdf, 0xf0, 0xc2, 0xb3, 0x90, 0xf9, 0x17, 0xe0, 0x04, 0xf0, 0xaf, 
+0x01, 0x12, 0x22, 0x33, 0xfd, 0x12, 0x2f, 0x49, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x75, 0xa8, 
+0x40, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x8b, 0x02, 0x27, 0x48, 0x02, 0x30, 0xcf, 
+0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2, 0x08, 0xdf, 0xf4, 
+0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33, 0xc4, 0x54, 0x0f, 
+0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf, 0xe4, 0x80, 0x0b, 
+0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x2b, 0x4c, 0xe4, 0x7e, 0x01, 0x93, 0x60, 
+0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93, 0xa3, 0x60, 0x01, 
+0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3, 0xfa, 0xe4, 0x93, 
+0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xf0, 0xa3, 0xc8, 
+0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe, 0xe4, 0xf5, 0x22, 
+0x12, 0x1d, 0x12, 0xe0, 0xb4, 0x04, 0x0d, 0xe5, 0x22, 0x24, 0x03, 0xff, 0x12, 0x2f, 0x77, 0x12, 
+0x1d, 0x12, 0xe4, 0xf0, 0x05, 0x22, 0xe5, 0x22, 0xc3, 0x94, 0x02, 0x40, 0xe3, 0xe4, 0xf5, 0x22, 
+0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x91, 0x12, 0x1d, 0x53, 0x60, 0x2c, 0x12, 0x2c, 0xb4, 
+0xef, 0x60, 0x52, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x91, 0x12, 0x1b, 0x1c, 0xe4, 0xf0, 
+0xa3, 0xf0, 0x75, 0xf0, 0x0a, 0xe5, 0x22, 0x90, 0xfa, 0x9d, 0x12, 0x1b, 0x1c, 0xe0, 0xa3, 0x30, 
+0xe6, 0x33, 0x12, 0x1d, 0x12, 0x74, 0x04, 0xf0, 0x22, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 
+0x95, 0x12, 0x1d, 0x53, 0x60, 0x16, 0x12, 0x2c, 0xb4, 0xef, 0x60, 0x19, 0x75, 0xf0, 0x02, 0xe5, 
+0x22, 0x90, 0xfa, 0x95, 0x12, 0x1b, 0x1c, 0xe4, 0xf0, 0xa3, 0xf0, 0x22, 0x05, 0x22, 0xe5, 0x22, 
+0xc3, 0x94, 0x02, 0x40, 0x9b, 0x22, 0xe4, 0xff, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xfe, 0xef, 
+0xc3, 0x9e, 0x50, 0x17, 0x74, 0xf0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xe0, 0x12, 
+0x1c, 0x11, 0x12, 0x1a, 0x38, 0x0f, 0x12, 0x1c, 0x00, 0x80, 0xdd, 0xef, 0xfd, 0xc3, 0xe5, 0x3a, 
+0x9d, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5, 0x39, 0xd3, 0xe5, 0x3a, 0x94, 0x00, 0xe5, 0x39, 
+0x94, 0x00, 0x40, 0x06, 0xe4, 0x90, 0xff, 0x83, 0xf0, 0x22, 0x12, 0x1d, 0x2f, 0x12, 0x1d, 0x84, 
+0x12, 0x1d, 0x76, 0x12, 0x19, 0xf2, 0x24, 0x6e, 0x60, 0x1e, 0x14, 0x60, 0x1b, 0x24, 0x8e, 0x70, 
+0x2d, 0x90, 0x00, 0x01, 0x12, 0x1a, 0x0b, 0xff, 0x24, 0xfc, 0x60, 0x03, 0x04, 0x70, 0x1f, 0xef, 
+0xfd, 0x7c, 0x00, 0x7f, 0x0d, 0x02, 0x11, 0x16, 0x12, 0x1d, 0x8b, 0x12, 0x25, 0x39, 0x12, 0x1c, 
+0xd9, 0x12, 0x1a, 0x0b, 0x60, 0x03, 0x02, 0x31, 0xbd, 0xe4, 0xff, 0x12, 0x31, 0xb1, 0x22, 0x8b, 
+0x45, 0x8a, 0x46, 0x89, 0x47, 0x8c, 0x48, 0x8d, 0x49, 0xd2, 0x00, 0x12, 0x2d, 0x82, 0x70, 0x16, 
+0x12, 0x2d, 0xa1, 0xe5, 0x48, 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0x1b, 0x50, 0xf2, 0x12, 0x29, 
+0x14, 0x40, 0x0b, 0x7f, 0x18, 0x22, 0x12, 0x2d, 0xa1, 0x12, 0x29, 0x14, 0x50, 0xf8, 0xe4, 0xf5, 
+0x4b, 0xe5, 0x4a, 0x14, 0xff, 0xe5, 0x4b, 0xc3, 0x9f, 0x50, 0x17, 0x12, 0x29, 0x04, 0x40, 0x03, 
+0x7f, 0x18, 0x22, 0x05, 0x4b, 0x74, 0x01, 0x25, 0x47, 0xf5, 0x47, 0xe4, 0x35, 0x46, 0xf5, 0x46, 
+0x80, 0xdf, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x29, 0x04, 0x40, 0x03, 0x7f, 0x18, 
+0x22, 0x7f, 0x00, 0x22, 0xab, 0x45, 0xaa, 0x46, 0xa9, 0x47, 0x12, 0x19, 0xf2, 0x90, 0xff, 0xf1, 
+0xf0, 0x02, 0x31, 0x1b, 0x90, 0xff, 0xf1, 0xe5, 0x49, 0xf0, 0x02, 0x31, 0x1b, 0x7b, 0x01, 0x7a, 
+0xfa, 0x79, 0xcc, 0xe4, 0xfd, 0x12, 0x22, 0xa0, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x09, 0x12, 
+0x1a, 0x6c, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12, 
+0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xff, 0xf7, 0xe5, 
+0x23, 0x12, 0x29, 0x78, 0x90, 0xff, 0xf6, 0xe5, 0x23, 0xf0, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, 
+0x74, 0x06, 0x12, 0x29, 0x78, 0xe5, 0x23, 0x30, 0xe0, 0x07, 0x90, 0xff, 0xfc, 0x74, 0x94, 0xf0, 
+0x22, 0x90, 0xff, 0xfc, 0x74, 0x90, 0xf0, 0x22, 0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 
+0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 
+0x02, 0x25, 0xd7, 0x90, 0xff, 0x93, 0x74, 0x2a, 0xf0, 0x90, 0xff, 0xff, 0xe0, 0x60, 0x06, 0x90, 
+0xff, 0xfc, 0x74, 0x10, 0xf0, 0x90, 0xff, 0x91, 0xe0, 0x44, 0x90, 0xf0, 0xe4, 0x90, 0xf9, 0x15, 
+0xf0, 0xa3, 0xf0, 0x12, 0x2a, 0x78, 0x12, 0x16, 0x42, 0x12, 0x2f, 0xcd, 0x7e, 0x07, 0x7f, 0xd0, 
+0x12, 0x11, 0xe2, 0x7e, 0x0f, 0x7f, 0xa0, 0x12, 0x11, 0xfc, 0xe4, 0x78, 0x77, 0xf6, 0x78, 0x77, 
+0xe6, 0xff, 0xc3, 0x94, 0x06, 0x50, 0x0b, 0x74, 0x6e, 0x2f, 0xf8, 0xe4, 0xf6, 0x78, 0x77, 0x06, 
+0x80, 0xec, 0x7f, 0x03, 0x12, 0x2e, 0xb3, 0x90, 0xf9, 0x15, 0xe0, 0x20, 0xe4, 0x05, 0x7f, 0x04, 
+0x12, 0x2e, 0xb3, 0x90, 0xff, 0x9b, 0xe4, 0xf0, 0x90, 0xff, 0x9a, 0xf0, 0x90, 0xff, 0xe8, 0xe0, 
+0x54, 0x1f, 0xf0, 0xd2, 0xa8, 0x22, 0x15, 0x65, 0xa8, 0x65, 0xa6, 0x07, 0x30, 0x08, 0x05, 0x12, 
+0x11, 0x66, 0x80, 0xf8, 0xd2, 0x08, 0xa8, 0x65, 0xe6, 0xff, 0xb4, 0x03, 0x0f, 0x78, 0x7c, 0x76, 
+0xff, 0x08, 0x76, 0xe0, 0x08, 0x76, 0xff, 0x08, 0x76, 0xa0, 0x80, 0x0d, 0x78, 0x7c, 0x76, 0xff, 
+0x08, 0x76, 0xe2, 0x08, 0x76, 0xff, 0x08, 0x76, 0xb0, 0x78, 0x80, 0x76, 0xfa, 0x08, 0x76, 0x9b, 
+0xef, 0x24, 0xfd, 0x75, 0xf0, 0x0a, 0xa4, 0xae, 0xf0, 0x12, 0x22, 0x92, 0x7b, 0x01, 0x7a, 0xff, 
+0x79, 0x48, 0x78, 0x68, 0x12, 0x1b, 0x31, 0xa8, 0x65, 0xe6, 0x24, 0xfd, 0x75, 0xf0, 0x08, 0xa4, 
+0xff, 0xae, 0xf0, 0x78, 0x6a, 0x12, 0x22, 0x92, 0x79, 0x08, 0x78, 0x6b, 0x12, 0x1b, 0x31, 0x78, 
+0x6d, 0xef, 0x12, 0x22, 0x92, 0x05, 0x65, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xab, 0xf0, 0xe0, 
+0x44, 0x20, 0xf0, 0x90, 0xfa, 0xe3, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcc, 0xe4, 
+0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x7e, 0x00, 0x90, 0xfa, 0xe1, 0xee, 0xf0, 
+0xa3, 0xef, 0xf0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcc, 0xe0, 0xb4, 0x52, 0x09, 0x90, 0xf9, 
+0x15, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x29, 0x90, 0xfa, 0xe1, 0xe0, 0x70, 0x04, 0xa3, 0xe0, 0x64, 
+0x01, 0x70, 0x10, 0x90, 0xfa, 0xcc, 0xe0, 0xb4, 0x10, 0x09, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x10, 
+0xf0, 0x80, 0x0d, 0x90, 0xfa, 0xe3, 0x74, 0x03, 0xf0, 0x90, 0xf9, 0x15, 0xe0, 0x54, 0xef, 0xf0, 
+0x90, 0xff, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x22, 0x12, 0x10, 0x03, 0x78, 0x8a, 0xef, 0xf6, 0x12, 
+0x2a, 0x06, 0x12, 0x22, 0x33, 0x30, 0xe0, 0x25, 0x12, 0x22, 0x07, 0xe0, 0x54, 0x7f, 0xf0, 0x78, 
+0x6b, 0x12, 0x1b, 0x28, 0x90, 0x00, 0x02, 0x12, 0x1a, 0x0b, 0x30, 0xe7, 0x09, 0x90, 0x00, 0x02, 
+0xe4, 0x12, 0x1a, 0x4a, 0x80, 0xe9, 0x12, 0x22, 0x07, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x22, 0x33, 
+0x30, 0xe1, 0x1e, 0x12, 0x21, 0xe9, 0xe0, 0x54, 0x7f, 0xf0, 0x12, 0x31, 0x5c, 0x78, 0x68, 0x12, 
+0x1b, 0x28, 0x90, 0x00, 0x02, 0x74, 0x80, 0x12, 0x1a, 0x4a, 0x12, 0x21, 0xe9, 0xe0, 0x44, 0x80, 
+0xf0, 0x12, 0x31, 0xc7, 0xe4, 0xff, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x03, 0x68, 0x01, 0xff, 
+0x48, 0x03, 0x6b, 0x01, 0xff, 0x08, 0x02, 0x66, 0x00, 0x00, 0x44, 0xfa, 0x95, 0x00, 0x00, 0x00, 
+0x00, 0x44, 0xfa, 0x91, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfa, 0xaf, 0x00, 0x00, 0x42, 0xfa, 0x7b, 
+0x00, 0x00, 0x42, 0xfa, 0x79, 0x00, 0x00, 0x42, 0xf9, 0x6a, 0xff, 0xff, 0x42, 0xfa, 0x77, 0x00, 
+0x00, 0x43, 0xf9, 0x18, 0x0a, 0x32, 0x02, 0x41, 0xf9, 0x65, 0x20, 0x41, 0xf9, 0x66, 0x20, 0x41, 
+0xf9, 0x63, 0x00, 0x41, 0xf9, 0x64, 0x00, 0x44, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf9, 
+0x15, 0x00, 0x00, 0x41, 0xf9, 0x17, 0x00, 0x01, 0x20, 0x00, 0x41, 0xf8, 0x04, 0x00, 0x00, 0x12, 
+0x10, 0x03, 0x78, 0x85, 0xef, 0xf6, 0x12, 0x30, 0x93, 0x12, 0x30, 0xec, 0x78, 0x85, 0xe6, 0xff, 
+0x24, 0x12, 0x12, 0x21, 0xff, 0xe0, 0xfe, 0x30, 0xe7, 0x16, 0xef, 0xb4, 0x03, 0x09, 0x90, 0xff, 
+0x9e, 0xe0, 0x54, 0xfa, 0xf0, 0x80, 0x22, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf5, 0xf0, 0x80, 0x19, 
+0xee, 0x54, 0x03, 0x60, 0x14, 0xef, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 0xf0, 
+0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xf9, 0x17, 0xe0, 0x14, 0xf0, 0xe0, 
+0x70, 0x02, 0xd2, 0xb3, 0x02, 0x10, 0x86, 0x12, 0x1d, 0x6c, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 
+0xe5, 0x39, 0x64, 0x01, 0x60, 0x48, 0xc3, 0xe5, 0x3a, 0x94, 0x08, 0xe5, 0x39, 0x94, 0x00, 0x40, 
+0x11, 0x7f, 0x08, 0xef, 0xe5, 0x3a, 0x94, 0x08, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5, 0x39, 
+0x80, 0x05, 0xaf, 0x3a, 0x12, 0x1d, 0x84, 0xe4, 0xfe, 0xee, 0xc3, 0x9f, 0x50, 0x19, 0x12, 0x1c, 
+0x11, 0x12, 0x19, 0xf2, 0xfd, 0x74, 0xf8, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xed, 
+0xf0, 0x0e, 0x12, 0x1c, 0x00, 0x80, 0xe2, 0xef, 0x54, 0x7f, 0x90, 0xff, 0x81, 0xf0, 0x22, 0x8b, 
+0x59, 0x8a, 0x5a, 0x89, 0x5b, 0x12, 0x2d, 0x48, 0x70, 0x05, 0xa3, 0x74, 0x08, 0xf0, 0x22, 0xab, 
+0x59, 0xaa, 0x5a, 0xa9, 0x5b, 0x12, 0x2d, 0x3c, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x43, 0xe5, 0x5b, 
+0x24, 0x03, 0xf9, 0xe4, 0x35, 0x5a, 0xfa, 0x90, 0xfa, 0xc0, 0x12, 0x1b, 0x43, 0xe4, 0x90, 0xfa, 
+0xbf, 0xf0, 0x78, 0x8b, 0xf6, 0x90, 0xfa, 0xbe, 0xe0, 0xff, 0x78, 0x8b, 0xe6, 0xc3, 0x9f, 0x50, 
+0x12, 0x12, 0x2d, 0x1a, 0xff, 0x12, 0x2d, 0x23, 0x12, 0x2d, 0x36, 0x78, 0x8b, 0x06, 0x12, 0x2d, 
+0x32, 0x80, 0xe2, 0x22, 0xad, 0x07, 0xac, 0x06, 0x90, 0x31, 0x4d, 0xe4, 0x93, 0xff, 0x78, 0x74, 
+0xf6, 0x54, 0x0f, 0x12, 0x1c, 0xf8, 0xe0, 0x08, 0x76, 0x00, 0x08, 0xf6, 0x18, 0x12, 0x1c, 0x29, 
+0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0x78, 0x75, 0xee, 0xf6, 0x08, 0xef, 0xf6, 0xee, 
+0x44, 0xf8, 0x18, 0xf6, 0xef, 0x08, 0xf6, 0x90, 0xff, 0x7a, 0xe0, 0x20, 0xe7, 0x03, 0x7f, 0x00, 
+0x22, 0x78, 0x75, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 
+0x90, 0xff, 0x7a, 0x74, 0x02, 0xf0, 0x7f, 0x01, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58, 0x90, 
+0x00, 0x03, 0x12, 0x1a, 0x0b, 0x54, 0xf0, 0x24, 0xa0, 0x22, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x3a, 
+0x02, 0x19, 0xf2, 0x90, 0xfa, 0xc0, 0x12, 0x1b, 0x3a, 0xef, 0x12, 0x1a, 0x38, 0x90, 0xfa, 0xc7, 
+0xe4, 0x22, 0x90, 0xfa, 0xc1, 0xe4, 0x75, 0xf0, 0x01, 0x02, 0x1a, 0x6c, 0x90, 0x00, 0x08, 0x12, 
+0x1a, 0x98, 0xaa, 0xf0, 0xf9, 0x7b, 0x01, 0x22, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0x90, 0xfa, 
+0xbe, 0xf0, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58, 0x22, 0x90, 0xfa, 0xda, 0xe0, 0xff, 0x7e, 
+0x00, 0xc3, 0x90, 0xfa, 0xd4, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xd3, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, 
+0xd5, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0xef, 0x25, 0x51, 0xf5, 0x51, 0xee, 0x35, 0x50, 0xf5, 
+0x50, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0xfa, 0xe3, 
+0xe0, 0x64, 0x03, 0x22, 0x90, 0xff, 0xf2, 0xe0, 0xab, 0x29, 0xaa, 0x2a, 0xa9, 0x2b, 0x02, 0x1a, 
+0x38, 0x90, 0xff, 0xf3, 0x74, 0xa0, 0xf0, 0x22, 0x8f, 0x64, 0xed, 0x70, 0x0f, 0xe5, 0x64, 0xb4, 
+0x03, 0x05, 0x7f, 0x01, 0x02, 0x31, 0x32, 0x7f, 0x02, 0x02, 0x31, 0x32, 0xaf, 0x64, 0x12, 0x2a, 
+0x06, 0x74, 0x6e, 0x25, 0x64, 0xf8, 0xe6, 0x30, 0xe2, 0x0b, 0xd2, 0x09, 0x12, 0x1c, 0x83, 0xe0, 
+0x54, 0x7f, 0xf0, 0x80, 0x02, 0xc2, 0x09, 0xe5, 0x64, 0xb4, 0x03, 0x07, 0x7f, 0x81, 0x12, 0x31, 
+0x32, 0x80, 0x05, 0x7f, 0x82, 0x12, 0x31, 0x32, 0x30, 0x09, 0x07, 0x12, 0x1c, 0x83, 0xe0, 0x44, 
+0x80, 0xf0, 0x12, 0x31, 0xc7, 0x22, 0x12, 0x10, 0x03, 0x90, 0xff, 0xfd, 0xe0, 0x44, 0x60, 0xf0, 
+0xd2, 0x01, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0x00, 0xe0, 0x30, 0xe7, 0x13, 
+0x90, 0xff, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x35, 0x80, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x01, 
+0xf0, 0x80, 0x0d, 0x12, 0x1d, 0x2f, 0x53, 0x35, 0x7f, 0x90, 0xff, 0xfc, 0xe0, 0x54, 0xfe, 0xf0, 
+0x90, 0xff, 0x81, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x02, 0xb0, 0x12, 0x1d, 0x37, 0x02, 0x10, 0x86, 
+0x12, 0x10, 0x03, 0x78, 0x89, 0xef, 0xf6, 0xd2, 0x00, 0x12, 0x2a, 0x06, 0x90, 0xf9, 0x67, 0x12, 
+0x1b, 0x3a, 0xe9, 0x24, 0x03, 0xf9, 0xe4, 0x3a, 0xfa, 0xc0, 0x02, 0x78, 0x80, 0xe6, 0xfe, 0x08, 
+0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0xd0, 0x02, 0x12, 0x22, 0x25, 0x12, 0x31, 0xc7, 
+0x78, 0x89, 0xe6, 0xff, 0x12, 0x13, 0x3f, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x8f, 0x63, 0x12, 
+0x2a, 0x06, 0x12, 0x22, 0x07, 0xe0, 0x54, 0x3f, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x21, 0xf3, 
+0xe0, 0x54, 0x3f, 0xf0, 0x08, 0xe6, 0xfe, 0x08, 0xe6, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x21, 0xf3, 
+0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x63, 0xf8, 0x74, 0xfb, 0x56, 0xf6, 
+0x7f, 0x00, 0x22, 0x8f, 0x23, 0xc2, 0x08, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x12, 0x78, 0x7e, 0x12, 
+0x21, 0xeb, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x22, 0x4a, 0x12, 0x21, 0xef, 0xe0, 0x20, 0xe0, 0xf6, 
+0xef, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x31, 0xc7, 
+0xaf, 0x23, 0x12, 0x13, 0x3f, 0x22, 0x12, 0x10, 0x03, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x4a, 0x24, 
+0x06, 0x12, 0x21, 0xf1, 0xe0, 0xfd, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x03, 0x12, 0x22, 0x52, 0x24, 
+0x05, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x00, 0x04, 0x12, 0x1a, 0x4a, 0x12, 0x31, 0xc7, 0x7d, 0x02, 
+0xe4, 0xff, 0x12, 0x2f, 0x18, 0x02, 0x10, 0x86, 0xae, 0x05, 0x12, 0x1c, 0xde, 0xef, 0x12, 0x1a, 
+0x4a, 0x0e, 0x0e, 0x0e, 0xee, 0xd3, 0x95, 0x3c, 0xe4, 0x95, 0x3b, 0x40, 0x02, 0xae, 0x3c, 0xee, 
+0xd3, 0x94, 0x08, 0x74, 0x80, 0x94, 0x81, 0x40, 0x0a, 0x7e, 0x03, 0x90, 0x00, 0x02, 0x74, 0x02, 
+0x12, 0x1a, 0x4a, 0xaf, 0x06, 0x12, 0x31, 0xb1, 0x22, 0xae, 0x07, 0xed, 0x54, 0x03, 0x64, 0x01, 
+0x60, 0x03, 0x7f, 0x10, 0x22, 0xed, 0x54, 0x7c, 0xc3, 0x94, 0x04, 0x50, 0x03, 0x7f, 0x0b, 0x22, 
+0x74, 0x6e, 0x2e, 0xf8, 0x74, 0x02, 0x46, 0xf6, 0x74, 0x96, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 
+0xf5, 0x83, 0xed, 0xf0, 0x7f, 0x00, 0x22, 0xbf, 0x03, 0x06, 0x7c, 0xff, 0x7d, 0xe0, 0x80, 0x04, 
+0x7c, 0xff, 0x7d, 0xe2, 0x8d, 0x82, 0x8c, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 
+0x12, 0x21, 0xf3, 0xe0, 0x44, 0x80, 0xf0, 0x74, 0x6e, 0x2f, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 
+0x00, 0x22, 0x12, 0x10, 0x03, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, 
+0x16, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xff, 0xc3, 0xe5, 0x3a, 0x9f, 0xe5, 0x39, 0x94, 0x00, 
+0x40, 0x05, 0x12, 0x28, 0x16, 0x80, 0x03, 0x12, 0x31, 0xbd, 0x02, 0x10, 0x86, 0x90, 0xff, 0xfc, 
+0xe0, 0x20, 0xe7, 0x1f, 0xc2, 0xaf, 0x7d, 0xff, 0xac, 0x05, 0x1d, 0xec, 0x60, 0x15, 0x7e, 0x04, 
+0x7f, 0x00, 0xef, 0x1f, 0xaa, 0x06, 0x70, 0x01, 0x1e, 0x4a, 0x60, 0xec, 0x90, 0xff, 0x92, 0xe4, 
+0xf0, 0x80, 0xef, 0x22, 0x12, 0x10, 0x03, 0x78, 0x66, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x30, 0xe0, 
+0x12, 0x30, 0xe1, 0x0f, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x20, 0xf0, 0x7f, 0x04, 0x12, 0x12, 0x19, 
+0x12, 0x1d, 0x46, 0x02, 0x10, 0x86, 0x8e, 0x5f, 0x8f, 0x60, 0xe5, 0x60, 0x15, 0x60, 0xae, 0x5f, 
+0x70, 0x02, 0x15, 0x5f, 0xd3, 0x94, 0x00, 0xee, 0x94, 0x00, 0x40, 0x09, 0x7e, 0x07, 0x7f, 0xd0, 
+0x12, 0x0f, 0xdc, 0x80, 0xe5, 0x22, 0x11, 0x94, 0x2d, 0xf6, 0x23, 0xef, 0x31, 0xa3, 0x2f, 0xf4, 
+0x2f, 0xa2, 0x30, 0xb2, 0x2e, 0xe6, 0x26, 0x6d, 0x2b, 0xaf, 0x30, 0x55, 0x30, 0x74, 0x1d, 0xb4, 
+0x2e, 0x40, 0x2a, 0xe8, 0x0e, 0x12, 0x10, 0x03, 0x78, 0x86, 0x12, 0x22, 0x82, 0x20, 0xe1, 0x07, 
+0x7f, 0x12, 0x12, 0x30, 0xec, 0x80, 0x0a, 0x78, 0x86, 0xe6, 0xff, 0x12, 0x23, 0x49, 0x12, 0x30, 
+0xec, 0x02, 0x10, 0x86, 0x12, 0x10, 0x03, 0x78, 0x87, 0x12, 0x22, 0x82, 0x20, 0xe2, 0x07, 0x7f, 
+0x11, 0x12, 0x30, 0xec, 0x80, 0x0a, 0x78, 0x87, 0xe6, 0xff, 0x12, 0x2e, 0x7d, 0x12, 0x30, 0xec, 
+0x02, 0x10, 0x86, 0x8f, 0x61, 0x12, 0x2e, 0x7d, 0xaf, 0x61, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x12, 
+0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x61, 0xf8, 0x74, 0xfd, 0x56, 0xf6, 0xaf, 0x61, 0x12, 0x13, 
+0x3f, 0x22, 0x12, 0x10, 0x03, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, 
+0x05, 0x12, 0x2c, 0x07, 0x80, 0x06, 0x12, 0x1d, 0x64, 0x12, 0x1d, 0x6c, 0x02, 0x10, 0x86, 0x12, 
+0x29, 0x93, 0x12, 0x12, 0xbb, 0x90, 0xf8, 0x04, 0xe0, 0xff, 0x60, 0x05, 0x7d, 0x01, 0x12, 0x12, 
+0x58, 0x12, 0x29, 0x1d, 0x12, 0x12, 0xf7, 0x12, 0x11, 0x74, 0x80, 0xe3, 0x12, 0x1c, 0xde, 0xef, 
+0x12, 0x1a, 0x4a, 0xe4, 0xf5, 0x33, 0xf5, 0x34, 0xef, 0x60, 0x03, 0x02, 0x31, 0xbd, 0xe4, 0xff, 
+0x12, 0x31, 0xb1, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 0x54, 0xa0, 0x60, 0xf7, 0xef, 0x30, 0xe5, 
+0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 0xd3, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 
+0x54, 0x28, 0x60, 0xf7, 0xef, 0x30, 0xe5, 0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 
+0xd3, 0x22, 0xef, 0x30, 0xe7, 0x08, 0x12, 0x1c, 0x95, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0xef, 0x12, 
+0x1c, 0xe8, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0x81, 0x01, 0x82, 0x02, 0x83, 0x03, 0x87, 0x40, 0x00, 
+0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x08, 0x00, 0x78, 0x7e, 0x12, 0x22, 
+0x09, 0xa3, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x06, 0x54, 0x7f, 0xf0, 0x44, 0x80, 0xf0, 0x22, 0x85, 
+0x3b, 0x39, 0x85, 0x3c, 0x3a, 0x90, 0xff, 0x82, 0xe0, 0x54, 0xf7, 0xf0, 0xa3, 0xe0, 0x54, 0x7f, 
+0xf0, 0x22, 0xe4, 0xfe, 0xee, 0x90, 0x31, 0x47, 0x93, 0xb5, 0x07, 0x02, 0xd3, 0x22, 0x0e, 0xbe, 
+0x07, 0xf2, 0xc3, 0x22, 0x00, 0x08, 0x18, 0x28, 0x38, 0x01, 0x81, 0x10, 0x0a, 0x02, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x12, 0x10, 0x03, 0x7f, 0x02, 0x12, 0x10, 0x92, 0x12, 0x1d, 0x46, 0x02, 0x10, 
+0x86, 0x75, 0x39, 0x00, 0x8f, 0x3a, 0x12, 0x1c, 0x30, 0x12, 0x2c, 0x07, 0x22, 0x12, 0x1d, 0x6c, 
+0x12, 0x1d, 0x2f, 0x12, 0x1d, 0x64, 0x22, 0xc2, 0x08, 0x22, 
 };
 
 #undef IMAGE_VERSION_NAME
diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h
index f4567f166..d43b9e6cd 100644
--- a/drivers/usb/serial/io_tables.h
+++ b/drivers/usb/serial/io_tables.h
@@ -14,22 +14,12 @@
 #ifndef IO_TABLES_H
 #define IO_TABLES_H
 
-static struct usb_device_id edgeport_1port_id_table [] = {
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_PARALLEL_PORT) },
-	{ }
-};
-
 static struct usb_device_id edgeport_2port_id_table [] = {
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2I) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_421) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_21) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_2_DIN) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2I) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_421) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_21) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2_DIN) },
 	{ }
 };
 
@@ -41,12 +31,9 @@ static struct usb_device_id edgeport_4port_id_table [] = {
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4I) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8_DUAL_CPU) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_4_DIN) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_22I) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_412_4) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_COMPATIBLE) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4T) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4I) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8_DUAL_CPU) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4_DIN) },
 	{ }
 };
 
@@ -54,9 +41,9 @@ static struct usb_device_id edgeport_8port_id_table [] = {
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8I) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_16_DUAL_CPU) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8I) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8R) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8RR) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_412_8) },
 	{ }
 };
 
@@ -69,7 +56,6 @@ static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_2) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_4I) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_2I) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_PARALLEL_PORT) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_421) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_21) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_8_DUAL_CPU) },
@@ -77,51 +63,18 @@ static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_2_DIN) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_4_DIN) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_22I) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_412_4) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_COMPATIBLE) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION,	ION_DEVICE_ID_EDGEPORT_8I) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2I) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_421) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_21) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_2_DIN) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4T) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4I) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8_DUAL_CPU) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_4_DIN) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_16_DUAL_CPU) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_BB_EDGEPORT_8I) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8R) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_8RR) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_EDGEPORT_412_8) },
 	{ }							/* Terminating entry */
 };
 
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
-static struct usb_serial_device_type edgeport_1port_device = {
-	.owner			= THIS_MODULE,
-	.name			= "Edgeport 1 port adapter",
-	.short_name		= "edgeport_1",
-	.id_table		= edgeport_1port_id_table,
-	.num_interrupt_in	= 1,
-	.num_bulk_in		= 1,
-	.num_bulk_out		= 1,
-	.num_ports		= 1,
-	.open			= edge_open,
-	.close			= edge_close,
-	.throttle		= edge_throttle,
-	.unthrottle		= edge_unthrottle,
-	.attach			= edge_startup,
-	.shutdown		= edge_shutdown,
-	.ioctl			= edge_ioctl,
-	.set_termios		= edge_set_termios,
-	.tiocmget		= edge_tiocmget,
-	.tiocmset		= edge_tiocmset,
-	.write			= edge_write,
-	.write_room		= edge_write_room,
-	.chars_in_buffer	= edge_chars_in_buffer,
-	.break_ctl		= edge_break,
-};
-
 static struct usb_serial_device_type edgeport_2port_device = {
 	.owner			= THIS_MODULE,
 	.name			= "Edgeport 2 port adapter",
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 6b821b6ed..ace42c870 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -124,15 +124,11 @@ static struct usb_device_id edgeport_2port_id_table [] = {
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2C) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_BOOT) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_DOWN) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_BOOT) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_DOWN) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_42) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4I) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22I) },
 	{ }
 };
 
@@ -143,15 +139,11 @@ static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2C) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_2I) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_BOOT) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_421_DOWN) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_BOOT) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21_DOWN) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_42) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4) },
 	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4I) },
-	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22) },
+	{ USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22I) },
 	{ }
 };
 
@@ -278,7 +270,7 @@ static int TIReadDownloadMemory(struct usb_device *dev, int start_address,
 {
 	int status = 0;
 	__u8 read_length;
-	__u16 be_start_address;
+	__be16 be_start_address;
 	
 	dbg ("%s - @ %x for %d", __FUNCTION__, start_address, length);
 
@@ -395,7 +387,7 @@ static int TIWriteDownloadI2C (struct edgeport_serial *serial, int start_address
 {
 	int status = 0;
 	int write_length;
-	__u16 be_start_address;
+	__be16 be_start_address;
 
 	/* We can only send a maximum of 1 aligned byte page at a time */
 	
@@ -1804,12 +1796,7 @@ static void edge_bulk_out_callback (struct urb *urb, struct pt_regs *regs)
 	tty = port->tty;
 	if (tty) {
 		/* let the tty driver wakeup if it has a special write_wakeup function */
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
-			(tty->ldisc.write_wakeup)(tty);
-		}
-
-		/* tell the tty driver that something has changed */
-		wake_up_interruptible(&tty->write_wait);
+		tty_wakeup(tty);
 	}
 }
 
diff --git a/drivers/usb/serial/io_usbvend.h b/drivers/usb/serial/io_usbvend.h
index 26a8c5a18..65073409f 100644
--- a/drivers/usb/serial/io_usbvend.h
+++ b/drivers/usb/serial/io_usbvend.h
@@ -18,14 +18,6 @@
 #if !defined(_USBVEND_H)
 #define	_USBVEND_H
 
-#ifndef __KERNEL__
-#include "ionprag.h"	/* Extra I/O Networks pragmas */
-
-#include <usbdi.h>
-
-#include "iondef.h"	/* Standard I/O Networks definitions */
-#endif
-
 /************************************************************************
  *
  *		D e f i n e s   /   T y p e d e f s
@@ -37,6 +29,7 @@
 // 
 
 #define	USB_VENDOR_ID_ION	0x1608		// Our VID
+#define	USB_VENDOR_ID_TI	0x0451		// TI VID
 
 //
 // Definitions of USB product IDs (PID)
@@ -48,36 +41,41 @@
 
 // ION-device OEM IDs
 #define	ION_OEM_ID_ION		0		// 00h Inside Out Networks
-#define	ION_OEM_ID_NLYNX	1		// 01h NLynx Systems	  
+#define	ION_OEM_ID_NLYNX	1		// 01h NLynx Systems
 #define	ION_OEM_ID_GENERIC	2		// 02h Generic OEM
 #define	ION_OEM_ID_MAC		3		// 03h Mac Version
 #define	ION_OEM_ID_MEGAWOLF	4		// 04h Lupusb OEM Mac version (MegaWolf)
 #define	ION_OEM_ID_MULTITECH	5		// 05h Multitech Rapidports
+#define	ION_OEM_ID_AGILENT	6		// 06h AGILENT board
+
 
-	
 // ION-device Device IDs
-// Product IDs - assigned to match middle digit of serial number
+// Product IDs - assigned to match middle digit of serial number (No longer true)
 
+#define ION_DEVICE_ID_80251_NETCHIP	0x020	// This bit is set in the PID if this edgeport hardware$
+						// is based on the 80251+Netchip.  
 
-// The ION_DEVICE_ID_GENERATION_2 bit (0x20) will be ORed into the existing edgeport
-// PIDs to identify 80251+Netchip hardware.  This will guarantee that if a second
-// generation edgeport device is plugged into a PC with an older (pre 2.0) driver,
-// it will not enumerate.
+#define ION_DEVICE_ID_GENERATION_1	0x00	// Value for 930 based edgeports
+#define ION_DEVICE_ID_GENERATION_2	0x01	// Value for 80251+Netchip.
+#define ION_DEVICE_ID_GENERATION_3	0x02	// Value for Texas Instruments TUSB5052 chip
+#define ION_DEVICE_ID_GENERATION_4	0x03	// Watchport Family of products
+#define ION_GENERATION_MASK		0x03
 
-#define ION_DEVICE_ID_GENERATION_2	0x020	// This bit is set in the PID if this edgeport hardware
-															// is based on the 80251+Netchip.  
+#define ION_DEVICE_ID_HUB_MASK		0x0080	// This bit in the PID designates a HUB device
+						// for example 8C would be a 421 4 port hub
+						// and 8D would be a 2 port embedded hub
 
-#define EDGEPORT_DEVICE_ID_MASK			0x3df	// Not including GEN_2 bit
+#define EDGEPORT_DEVICE_ID_MASK			0x0ff	// Not including OEM or GENERATION fields
 
 #define	ION_DEVICE_ID_UNCONFIGURED_EDGE_DEVICE	0x000	// In manufacturing only
 #define ION_DEVICE_ID_EDGEPORT_4		0x001	// Edgeport/4 RS232
-//	ION_DEVICE_ID_HUBPORT_7			0x002	// Hubport/7 (Placeholder, not used by software)
+#define	ION_DEVICE_ID_EDGEPORT_8R		0x002	// Edgeport with RJ45 no Ring
 #define ION_DEVICE_ID_RAPIDPORT_4		0x003	// Rapidport/4
 #define ION_DEVICE_ID_EDGEPORT_4T		0x004	// Edgeport/4 RS232 for Telxon (aka "Fleetport")
 #define ION_DEVICE_ID_EDGEPORT_2		0x005	// Edgeport/2 RS232
 #define ION_DEVICE_ID_EDGEPORT_4I		0x006	// Edgeport/4 RS422
 #define ION_DEVICE_ID_EDGEPORT_2I		0x007	// Edgeport/2 RS422/RS485
-//	ION_DEVICE_ID_HUBPORT_4			0x008	// Hubport/4 (Placeholder, not used by software)
+#define	ION_DEVICE_ID_EDGEPORT_8RR		0x008	// Edgeport with RJ45 with Data and RTS/CTS only
 //	ION_DEVICE_ID_EDGEPORT_8_HANDBUILT	0x009	// Hand-built Edgeport/8 (Placeholder, used in middle digit of serial number only!)
 //	ION_DEVICE_ID_MULTIMODEM_4X56		0x00A	// MultiTech version of RP/4 (Placeholder, used in middle digit of serial number only!)
 #define	ION_DEVICE_ID_EDGEPORT_PARALLEL_PORT	0x00B	// Edgeport/(4)21 Parallel port (USS720)
@@ -90,41 +88,134 @@
 #define ION_DEVICE_ID_EDGEPORT_16_DUAL_CPU	0x012	// Half of an Edgeport/16 (the kind with 2 EP/8s)
 #define ION_DEVICE_ID_EDGEPORT_COMPATIBLE	0x013	// Edgeport Compatible, for NCR, Axiohm etc. testing
 #define ION_DEVICE_ID_EDGEPORT_8I		0x014	// Edgeport/8 RS422 (single-CPU)
+#define ION_DEVICE_ID_EDGEPORT_1		0x015	// Edgeport/1 RS232
+#define ION_DEVICE_ID_EPOS44			0x016	// Half of an EPOS/44 (TIUMP BASED)
+#define ION_DEVICE_ID_EDGEPORT_42		0x017	// Edgeport/42
+#define ION_DEVICE_ID_EDGEPORT_412_8		0x018	// Edgeport/412 8 port part
+#define ION_DEVICE_ID_EDGEPORT_412_4		0x019	// Edgeport/412	4 port part
+#define ION_DEVICE_ID_EDGEPORT_22I		0x01A	// Edgeport/22I is an Edgeport/4 with ports 1&2 RS422 and ports 3&4 RS232
+
+// Compact Form factor TI based devices  2c, 21c, 22c, 221c
+#define ION_DEVICE_ID_EDGEPORT_2C		0x01B	// Edgeport/2c is a TI based Edgeport/2 - Small I2c
+#define ION_DEVICE_ID_EDGEPORT_221C		0x01C	// Edgeport/221c is a TI based Edgeport/2 with lucent chip and
+							// 2 external hub ports - Large I2C
+#define ION_DEVICE_ID_EDGEPORT_22C		0x01D	// Edgeport/22c is a TI based Edgeport/2 with
+							// 2 external hub ports - Large I2C
+#define ION_DEVICE_ID_EDGEPORT_21C		0x01E	// Edgeport/21c is a TI based Edgeport/2 with lucent chip
+							// Small I2C
+
+
+/*
+ *  DANGER DANGER The 0x20 bit was used to indicate a 8251/netchip GEN 2 device.
+ *  Since the MAC, Linux, and Optimal drivers still used the old code
+ *  I suggest that you skip the 0x20 bit when creating new PIDs
+ */
+
+
+// Generation 3 devices -- 3410 based edgport/1 (256 byte I2C)
+#define ION_DEVICE_ID_TI3410_EDGEPORT_1		0x040	// Edgeport/1 RS232
+#define ION_DEVICE_ID_TI3410_EDGEPORT_1I	0x041	// Edgeport/1i- RS422 model
+
+// Ti based software switchable RS232/RS422/RS485 devices
+#define ION_DEVICE_ID_EDGEPORT_4S		0x042	// Edgeport/4s - software switchable model
+#define ION_DEVICE_ID_EDGEPORT_8S		0x043	// Edgeport/8s - software switchable model
+
+// Usb to Ethernet dongle
+#define ION_DEVICE_ID_EDGEPORT_E		0x0E0	// Edgeport/E Usb to Ethernet
+
+// Edgeport TI based devices
+#define ION_DEVICE_ID_TI_EDGEPORT_4		0x0201	// Edgeport/4 RS232
+#define ION_DEVICE_ID_TI_EDGEPORT_2		0x0205	// Edgeport/2 RS232
+#define ION_DEVICE_ID_TI_EDGEPORT_4I		0x0206	// Edgeport/4i RS422
+#define ION_DEVICE_ID_TI_EDGEPORT_2I		0x0207	// Edgeport/2i RS422/RS485
+#define ION_DEVICE_ID_TI_EDGEPORT_421		0x020C	// Edgeport/421 4 hub 2 RS232 + Parallel (lucent on a different hub port)
+#define ION_DEVICE_ID_TI_EDGEPORT_21		0x020D	// Edgeport/21 2 RS232 + Parallel (lucent on a different hub port)
+#define ION_DEVICE_ID_TI_EDGEPORT_8		0x020F	// Edgeport/8 (single-CPU)
+#define ION_DEVICE_ID_TI_EDGEPORT_1		0x0215	// Edgeport/1 RS232
+#define ION_DEVICE_ID_TI_EDGEPORT_42		0x0217	// Edgeport/42 4 hub 2 RS232
+#define ION_DEVICE_ID_TI_EDGEPORT_22I  		0x021A	// Edgeport/22I is an Edgeport/4 with ports 1&2 RS422 and ports 3&4 RS232
+#define ION_DEVICE_ID_TI_EDGEPORT_2C		0x021B	// Edgeport/2c RS232
+#define ION_DEVICE_ID_TI_EDGEPORT_221C		0x021C	// Edgeport/221c is a TI based Edgeport/2 with lucent chip and
+							// 2 external hub ports - Large I2C
+#define ION_DEVICE_ID_TI_EDGEPORT_22C		0x021D	// Edgeport/22c is a TI based Edgeport/2 with
+							// 2 external hub ports - Large I2C
+#define ION_DEVICE_ID_TI_EDGEPORT_21C		0x021E	// Edgeport/21c is a TI based Edgeport/2 with lucent chip
+
+// Generation 3 devices -- 3410 based edgport/1 (256 byte I2C) 
+#define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1	0x240	// Edgeport/1 RS232
+#define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I	0x241	// Edgeport/1i- RS422 model
+
+// Ti based software switchable RS232/RS422/RS485 devices
+#define ION_DEVICE_ID_TI_EDGEPORT_4S		0x242	// Edgeport/4s - software switchable model
+#define ION_DEVICE_ID_IT_EDGEPORT_8S		0x243	// Edgeport/8s - software switchable model
+
+
+/************************************************************************
+ *
+ *                        Generation 4 devices
+ *
+ ************************************************************************/
+
+// Watchport based on 3410 both 1-wire and binary products (16K I2C)
+#define ION_DEVICE_ID_WP_UNSERIALIZED		0x300	// Watchport based on 3410 both 1-wire and binary products
+#define ION_DEVICE_ID_WP_PROXIMITY		0x301	// Watchport/P Discontinued
+#define ION_DEVICE_ID_WP_MOTION			0x302	// Watchport/M
+#define ION_DEVICE_ID_WP_MOISTURE		0x303	// Watchport/W
+#define ION_DEVICE_ID_WP_TEMPERATURE		0x304	// Watchport/T
+#define ION_DEVICE_ID_WP_HUMIDITY		0x305	// Watchport/H
+
+#define ION_DEVICE_ID_WP_POWER			0x306	// Watchport
+#define ION_DEVICE_ID_WP_LIGHT			0x307	// Watchport
+#define ION_DEVICE_ID_WP_RADIATION		0x308	// Watchport
+#define ION_DEVICE_ID_WP_ACCELERATION		0x309	// Watchport/A
+#define ION_DEVICE_ID_WP_DISTANCE		0x30A	// Watchport/D Discontinued
+#define ION_DEVICE_ID_WP_PROX_DIST		0x30B	// Watchport/D uses distance sensor
+							// Default to /P function
+
+#define ION_DEVICE_ID_PLUS_PWR_HP4CD		0x30C	// 5052 Plus Power HubPort/4CD+ (for Dell)
+#define ION_DEVICE_ID_PLUS_PWR_HP4C		0x30D	// 5052 Plus Power HubPort/4C+ 
+#define ION_DEVICE_ID_PLUS_PWR_PCI		0x30E	// 3410 Plus Power PCI Host Controller 4 port
+
+
+//
+// Definitions for AXIOHM USB product IDs
+//
+#define	USB_VENDOR_ID_AXIOHM			0x05D9	// Axiohm VID
+
+#define AXIOHM_DEVICE_ID_MASK			0xffff
+#define AXIOHM_DEVICE_ID_EPIC_A758		0xA758
+#define AXIOHM_DEVICE_ID_EPIC_A794		0xA794
+#define AXIOHM_DEVICE_ID_EPIC_A225		0xA225
+
+
+//
+// Definitions for NCR USB product IDs
+//
+#define	USB_VENDOR_ID_NCR			0x0404	// NCR VID
+
+#define NCR_DEVICE_ID_MASK			0xffff
+#define NCR_DEVICE_ID_EPIC_0202			0x0202
+#define NCR_DEVICE_ID_EPIC_0203			0x0203
+#define NCR_DEVICE_ID_EPIC_0310			0x0310
+#define NCR_DEVICE_ID_EPIC_0311			0x0311
+#define NCR_DEVICE_ID_EPIC_0312			0x0312
+
+
+//
+// Definitions for SYMBOL USB product IDs
+//
+#define USB_VENDOR_ID_SYMBOL			0x05E0	// Symbol VID
+#define SYMBOL_DEVICE_ID_MASK			0xffff
+#define SYMBOL_DEVICE_ID_KEYFOB			0x0700
+
+
+//
+// Definitions for other product IDs
 #define ION_DEVICE_ID_MT4X56USB			0x1403	// OEM device
 
-// BlackBox OEM devices
-#define ION_DEVICE_ID_BB_EDGEPORT_4		0x001	// Edgeport/4 RS232
-#define ION_DEVICE_ID_BB_EDGEPORT_4T		0x004	// Edgeport/4 RS232 for Telxon (aka "Fleetport")
-#define ION_DEVICE_ID_BB_EDGEPORT_2		0x005	// Edgeport/2 RS232
-#define ION_DEVICE_ID_BB_EDGEPORT_4I		0x006	// Edgeport/4 RS422
-#define ION_DEVICE_ID_BB_EDGEPORT_2I		0x007	// Edgeport/2 RS422/RS485
-#define	ION_DEVICE_ID_BB_EDGEPORT_421		0x00C	// Edgeport/421 Hub+RS232+Parallel
-#define	ION_DEVICE_ID_BB_EDGEPORT_21		0x00D	// Edgeport/21  RS232+Parallel
-#define ION_DEVICE_ID_BB_EDGEPORT_8_DUAL_CPU	0x00E	// Half of an Edgeport/8 (the kind with 2 EP/4s on 1 PCB)
-#define ION_DEVICE_ID_BB_EDGEPORT_8		0x00F	// Edgeport/8 (single-CPU)
-#define ION_DEVICE_ID_BB_EDGEPORT_2_DIN		0x010	// Edgeport/2 RS232 with Apple DIN connector
-#define ION_DEVICE_ID_BB_EDGEPORT_4_DIN		0x011	// Edgeport/4 RS232 with Apple DIN connector
-#define ION_DEVICE_ID_BB_EDGEPORT_16_DUAL_CPU	0x012	// Half of an Edgeport/16 (the kind with 2 EP/8s)
-#define ION_DEVICE_ID_BB_EDGEPORT_8I		0x014	// Edgeport/8 RS422 (single-CPU)
-
-
-/* Edgeport TI based devices */
-#define ION_DEVICE_ID_TI_EDGEPORT_4		0x0201	/* Edgeport/4 RS232 */
-#define ION_DEVICE_ID_TI_EDGEPORT_2		0x0205	/* Edgeport/2 RS232 */
-#define ION_DEVICE_ID_TI_EDGEPORT_4I		0x0206	/* Edgeport/4i RS422 */
-#define ION_DEVICE_ID_TI_EDGEPORT_2I		0x0207	/* Edgeport/2i RS422/RS485 */
-#define ION_DEVICE_ID_TI_EDGEPORT_421		0x020C	/* Edgeport/421 4 hub 2 RS232 + Parallel (lucent on a different hub port) */
-#define ION_DEVICE_ID_TI_EDGEPORT_21		0x020D	/* Edgeport/21 2 RS232 + Parallel (lucent on a different hub port) */
-#define ION_DEVICE_ID_TI_EDGEPORT_1		0x0215	/* Edgeport/1 RS232 */
-#define ION_DEVICE_ID_TI_EDGEPORT_42		0x0217	/* Edgeport/42 4 hub 2 RS232 */
-#define ION_DEVICE_ID_TI_EDGEPORT_22		0x021A	/* Edgeport/22  Edgeport/22I is an Edgeport/4 with ports 1&2 RS422 and ports 3&4 RS232 */
-#define ION_DEVICE_ID_TI_EDGEPORT_2C		0x021B	/* Edgeport/2c RS232 */
-
-#define ION_DEVICE_ID_TI_EDGEPORT_421_BOOT	0x0240	/* Edgeport/421 in boot mode */
-#define ION_DEVICE_ID_TI_EDGEPORT_421_DOWN	0x0241	/* Edgeport/421 in download mode first interface is 2 RS232 (Note that the second interface of this multi interface device should be a standard USB class 7 printer port) */
-#define ION_DEVICE_ID_TI_EDGEPORT_21_BOOT	0x0242	/* Edgeport/21 in boot mode */
-#define ION_DEVICE_ID_TI_EDGEPORT_21_DOWN	0x0243	/*Edgeport/42 in download mode: first interface is 2 RS232 (Note that the second interface of this multi interface device should be a standard USB class 7 printer port) */
 
+#define	GENERATION_ID_FROM_USB_PRODUCT_ID( ProductId )				\
+			( (__u16) ((ProductId >> 8) & (ION_GENERATION_MASK)) )
 
 #define	MAKE_USB_PRODUCT_ID( OemId, DeviceId )					\
 			( (__u16) (((OemId) << 10) || (DeviceId)) )
@@ -143,7 +234,7 @@
 
 // TxCredits value below which driver won't bother sending (to prevent too many small writes).
 // Send only if above 25%
-#define EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(InitialCredit)	(max(((InitialCredit) / 4), EDGE_FW_BULK_MAX_PACKET_SIZE))
+#define EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(InitialCredit, MaxPacketSize) (max( ((InitialCredit) / 4), (MaxPacketSize) ))
 
 #define	EDGE_FW_BULK_MAX_PACKET_SIZE		64	// Max Packet Size for Bulk In Endpoint (EP1)
 #define EDGE_FW_BULK_READ_BUFFER_SIZE		1024	// Size to use for Bulk reads
@@ -158,8 +249,8 @@
 // Definitions of I/O Networks vendor-specific requests
 // for default endpoint
 //
-//	bmRequestType = 00100000	Set vendor-specific, to device
-//	bmRequestType = 10100000	Get vendor-specific, to device
+//	bmRequestType = 01000000	Set vendor-specific, to device
+//	bmRequestType = 11000000	Get vendor-specific, to device
 //
 // These are the definitions for the bRequest field for the
 // above bmRequestTypes.
@@ -184,11 +275,87 @@
 #define USB_REQUEST_ION_ENABLE_SUSPEND	9	// Enable/Disable suspend feature
 						// (wValue != 0: Enable; wValue = 0: Disable)
 
+#define USB_REQUEST_ION_SEND_IOSP	10	// Send an IOSP command to the edgeport over the control pipe	
+#define USB_REQUEST_ION_RECV_IOSP	11	// Receive an IOSP command from the edgeport over the control pipe
+
+
+#define USB_REQUEST_ION_DIS_INT_TIMER	0x80	// Sent to Axiohm to enable/ disable
+						// interrupt token timer
+						// wValue = 1, enable (default)
+						// wValue = 0, disable
 
 //
 // Define parameter values for our vendor-specific commands
 //
 
+//
+// Edgeport Compatiblity Descriptor
+//
+// This descriptor is only returned by Edgeport-compatible devices
+// supporting the EPiC spec. True ION devices do not return this
+// descriptor, but instead return STALL on receipt of the
+// GET_EPIC_DESC command. The driver interprets a STALL to mean that
+// this is a "real" Edgeport.
+//
+
+struct edge_compatibility_bits
+{
+	// This __u32 defines which Vendor-specific commands/functionality
+	// the device supports on the default EP0 pipe.
+
+	__u32	VendEnableSuspend	:  1;	// 0001 Set if device supports ION_ENABLE_SUSPEND
+	__u32	VendUnused		: 31;	// Available for future expansion, must be 0
+
+	// This __u32 defines which IOSP commands are supported over the
+	// bulk pipe EP1.
+
+											// xxxx Set if device supports:
+	__u32	IOSPOpen		:  1;	// 0001	OPEN / OPEN_RSP (Currently must be 1)
+	__u32	IOSPClose		:  1;	// 0002	CLOSE
+	__u32	IOSPChase		:  1;	// 0004	CHASE / CHASE_RSP
+	__u32	IOSPSetRxFlow		:  1;	// 0008	SET_RX_FLOW
+	__u32	IOSPSetTxFlow		:  1;	// 0010	SET_TX_FLOW
+	__u32	IOSPSetXChar		:  1;	// 0020	SET_XON_CHAR/SET_XOFF_CHAR
+	__u32	IOSPRxCheck		:  1;	// 0040	RX_CHECK_REQ/RX_CHECK_RSP
+	__u32	IOSPSetClrBreak		:  1;	// 0080	SET_BREAK/CLEAR_BREAK
+	__u32	IOSPWriteMCR		:  1;	// 0100	MCR register writes (set/clr DTR/RTS)
+	__u32	IOSPWriteLCR		:  1;	// 0200	LCR register writes (wordlen/stop/parity)
+	__u32	IOSPSetBaudRate		:  1;	// 0400	setting Baud rate (writes to LCR.80h and DLL/DLM register)
+	__u32	IOSPDisableIntPipe	:  1;	// 0800 Do not use the interrupt pipe for TxCredits or RxButesAvailable
+	__u32	IOSPRxDataAvail		:  1;   // 1000 Return status of RX Fifo (Data available in Fifo)
+	__u32	IOSPTxPurge		:  1;	// 2000 Purge TXBuffer and/or Fifo in Edgeport hardware
+	__u32	IOSPUnused		: 18;	// Available for future expansion, must be 0
+
+	// This __u32 defines which 'general' features are supported
+
+	__u32	TrueEdgeport		:  1;	// 0001	Set if device is a 'real' Edgeport
+											// (Used only by driver, NEVER set by an EPiC device)
+	__u32	GenUnused		: 31;	// Available for future expansion, must be 0
+
+};
+
+struct edge_compatibility_descriptor
+{
+	__u8	Length;				// Descriptor Length (per USB spec)
+	__u8	DescType;			// Descriptor Type (per USB spec, =DEVICE type)
+	__u8	EpicVer;			// Version of EPiC spec supported
+											// (Currently must be 1)
+	__u8	NumPorts;			// Number of serial ports supported
+	__u8	iDownloadFile;			// Index of string containing download code filename
+											// 0=no download, FF=download compiled into driver.
+	__u8	Unused[ 3 ];			// Available for future expansion, must be 0
+											// (Currently must be 0).
+	__u8	MajorVersion;			// Firmware version: xx.
+	__u8	MinorVersion;			//  yy.
+	__le16	BuildNumber;			//  zzzz (LE format)
+
+	// The following structure contains __u32s, with each bit
+	// specifying whether the EPiC device supports the given
+	// command or functionality.
+
+	struct edge_compatibility_bits	Supports;
+
+};
 
 // Values for iDownloadFile
 #define	EDGE_DOWNLOAD_FILE_NONE		0	// No download requested
@@ -272,30 +439,30 @@ struct edge_manuf_descriptor {
 
 	__u8	NumPorts;				// F08 Number of ports
 	__u8	DescDate[3];				// F09 MM/DD/YY when descriptor template was compiler,
-							//	   so host can track changes to USB-only descriptors.
+							//     so host can track changes to USB-only descriptors.
 
 	__u8	SerNumLength;				// F0C USB string descriptor len
 	__u8	SerNumDescType;				// F0D USB descriptor type (=STRING type)
-	__u16	SerialNumber[MAX_SERIALNUMBER_LEN];	// F0E "01-01-000100" Unicode Serial Number
+	__le16	SerialNumber[MAX_SERIALNUMBER_LEN];	// F0E "01-01-000100" Unicode Serial Number
 
 	__u8	AssemblyNumLength;			// F26 USB string descriptor len
 	__u8	AssemblyNumDescType;			// F27 USB descriptor type (=STRING type)
-	__u16	AssemblyNumber[MAX_ASSEMBLYNUMBER_LEN];	// F28 "350-1000-01-A " assembly number
+	__le16	AssemblyNumber[MAX_ASSEMBLYNUMBER_LEN];	// F28 "350-1000-01-A " assembly number
 
 	__u8	OemAssyNumLength;			// F44 USB string descriptor len
 	__u8	OemAssyNumDescType;			// F45 USB descriptor type (=STRING type)
-	__u16	OemAssyNumber[MAX_ASSEMBLYNUMBER_LEN];	// F46 "xxxxxxxxxxxxxx" OEM assembly number
+	__le16	OemAssyNumber[MAX_ASSEMBLYNUMBER_LEN];	// F46 "xxxxxxxxxxxxxx" OEM assembly number
 
 	__u8	ManufDateLength;			// F62 USB string descriptor len
 	__u8	ManufDateDescType;			// F63 USB descriptor type (=STRING type)
-	__u16	ManufDate[6];				// F64 "MMDDYY" manufacturing date
+	__le16	ManufDate[6];				// F64 "MMDDYY" manufacturing date
 
 	__u8	Reserved3[0x4D];			// F70 -- unused, set to 0 --
 
 	__u8	UartType;				// FBD Uart Type
 	__u8	IonPid;					// FBE Product ID, == LSB of USB DevDesc.PID
-							//     (Note: Edgeport/4s before 11/98 will have
-							//		00 here instead of 01)
+							//      (Note: Edgeport/4s before 11/98 will have
+							//       00 here instead of 01)
 	__u8	IonConfig;				// FBF Config byte for ION manufacturing use
 							// FBF end of structure, total len = 3C0h
 
@@ -312,7 +479,7 @@ struct edge_manuf_descriptor {
 // both 00 and 01 values mean '654.
 #define MANUF_UART_EXAR_654_EARLY	0	// Exar 16C654 in Edgeport/4s before 11/98
 #define MANUF_UART_EXAR_654		1	// Exar 16C654
-#define MANUF_UART_EXAR_2852		2	// Exar 16C2852 
+#define MANUF_UART_EXAR_2852		2	// Exar 16C2852
 
 //
 // Note: The CpuRev and BoardRev values do not conform to manufacturing
@@ -334,25 +501,22 @@ struct edge_manuf_descriptor {
 #define MANUF_BOARD_REV_GENERATION_2	0x20	// Second generaiton edgeport
 
 
-
-
 // Values of bottom 5 bits of CpuRev & BoardRev for
 // Implementation 1 (ie, 251+Netchip-based)
 #define	MANUF_CPU_REV_1			1	// C251TB Rev 1 (Need actual Intel rev here)
 
 #define MANUF_BOARD_REV_A		1	// First rev of 251+Netchip design
 
-
-
 #define	MANUF_SERNUM_LENGTH		sizeof(((struct edge_manuf_descriptor *)0)->SerialNumber)
 #define	MANUF_ASSYNUM_LENGTH		sizeof(((struct edge_manuf_descriptor *)0)->AssemblyNumber)
 #define	MANUF_OEMASSYNUM_LENGTH		sizeof(((struct edge_manuf_descriptor *)0)->OemAssyNumber)
 #define	MANUF_MANUFDATE_LENGTH		sizeof(((struct edge_manuf_descriptor *)0)->ManufDate)
 
-#define	MANUF_ION_CONFIG_MASTER		0x80	// 1=Master mode, 0=Normal
-#define	MANUF_ION_CONFIG_DIAG		0x40	// 1=Run h/w diags, 0=norm
-#define	MANUF_ION_CONFIG_DIAG_NO_LOOP	0x20	// As above but no ext loopback test
-
+#define	MANUF_ION_CONFIG_DIAG_NO_LOOP	0x20	// As below but no ext loopback test
+#define	MANUF_ION_CONFIG_DIAG		0x40	// 930 based device: 1=Run h/w diags, 0=norm
+						// TIUMP Device    : 1=IONSERIAL needs to run Final Test
+#define	MANUF_ION_CONFIG_MASTER		0x80	// 930 based device:  1=Master mode, 0=Normal
+						// TIUMP Device    :  1=First device on a multi TIUMP Device
 
 //
 // This structure describes parameters for the boot code, and
@@ -368,19 +532,19 @@ struct edge_boot_descriptor {
 	__u8		DescVer;		// C2 Desc version/format
 	__u8		Reserved1;		// C3 -- unused, set to 0 --
 
-	__u16		BootCodeLength;		// C4 Boot code goes from FF:0000 to FF:(len-1)
+	__le16		BootCodeLength;		// C4 Boot code goes from FF:0000 to FF:(len-1)
 						//	  (LE format)
 
 	__u8		MajorVersion;		// C6 Firmware version: xx.
 	__u8		MinorVersion;		// C7			yy.
-	__u16		BuildNumber;		// C8			zzzz (LE format)
+	__le16		BuildNumber;		// C8			zzzz (LE format)
 	
 	__u16		EnumRootDescTable;	// CA Root of ROM-based descriptor table
 	__u8		NumDescTypes;		// CC Number of supported descriptor types
 
 	__u8		Reserved4;		// CD Fix Compiler Packing
 
-	__u16		Capabilities;		// CE-CF Capabilities flags (LE format)
+	__le16		Capabilities;		// CE-CF Capabilities flags (LE format)
 	__u8		Reserved2[0x28];	// D0 -- unused, set to 0 --
 	__u8		UConfig0;		// F8 930-defined CPU configuration byte 0
 	__u8		UConfig1;		// F9 930-defined CPU configuration byte 1
@@ -398,23 +562,29 @@ struct edge_boot_descriptor {
 #define	BOOT_CAP_RESET_CMD	0x0001	// If set, boot correctly supports ION_RESET_DEVICE
 
 
-
 /************************************************************************
                  T I   U M P   D E F I N I T I O N S
  ***********************************************************************/
 
+// Chip definitions in I2C
+#define UMP5152			0x52
+#define UMP3410			0x10
+
+
 //************************************************************************
 //	TI I2C Format Definitions
 //************************************************************************
-#define I2C_DESC_TYPE_INFO_BASIC	1
-#define I2C_DESC_TYPE_FIRMWARE_BASIC	2
-#define I2C_DESC_TYPE_DEVICE		3
-#define I2C_DESC_TYPE_CONFIG		4
-#define I2C_DESC_TYPE_STRING		5
-#define I2C_DESC_TYPE_FIRMWARE_BLANK 	0xf2
-
-#define I2C_DESC_TYPE_MAX		5
-// 3410 may define types 6, 7 for other firmware downloads
+#define I2C_DESC_TYPE_INFO_BASIC	0x01
+#define I2C_DESC_TYPE_FIRMWARE_BASIC	0x02
+#define I2C_DESC_TYPE_DEVICE		0x03
+#define I2C_DESC_TYPE_CONFIG		0x04
+#define I2C_DESC_TYPE_STRING		0x05
+#define I2C_DESC_TYPE_FIRMWARE_AUTO	0x07	// for 3410 download
+#define I2C_DESC_TYPE_CONFIG_KLUDGE	0x14	// for 3410
+#define I2C_DESC_TYPE_WATCHPORT_VERSION	0x15	// firmware version number for watchport
+#define I2C_DESC_TYPE_WATCHPORT_CALIBRATION_DATA 0x16	// Watchport Calibration Data
+
+#define I2C_DESC_TYPE_FIRMWARE_BLANK	0xf2
 
 // Special section defined by ION
 #define I2C_DESC_TYPE_ION		0	// Not defined by TI
@@ -428,7 +598,9 @@ struct ti_i2c_desc
 	__u8	Data[0];		// Data starts here
 }__attribute__((packed));
 
-struct ti_i2c_firmware_rec 
+// for 5152 devices only (type 2 record)
+// for 3410 the version is stored in the WATCHPORT_FIRMWARE_VERSION descriptor
+struct ti_i2c_firmware_rec
 {
 	__u8	Ver_Major;		// Firmware Major version number
 	__u8	Ver_Minor;		// Firmware Minor version number
@@ -436,6 +608,14 @@ struct ti_i2c_firmware_rec
 }__attribute__((packed));
 
 
+struct watchport_firmware_version
+{
+// Added 2 bytes for version number
+	__u8	Version_Major;		//  Download Version (for Watchport)
+	__u8	Version_Minor;
+}__attribute__((packed));
+
+
 // Structure of header of download image in fw_down.h
 struct ti_i2c_image_header
 {
@@ -461,6 +641,15 @@ struct ti_basic_descriptor
 } __attribute__((packed));
 
 
+// CPU / Board Rev Definitions
+#define TI_CPU_REV_5052			2	// 5052 based edgeports
+#define TI_CPU_REV_3410			3	// 3410 based edgeports
+
+#define TI_BOARD_REV_TI_EP		0	// Basic ti based edgeport
+#define TI_BOARD_REV_COMPACT		1	// Compact board
+#define TI_BOARD_REV_WATCHPORT		2	// Watchport
+
+
 #define TI_GET_CPU_REVISION(x)		(__u8)((((x)>>4)&0x0f))
 #define TI_GET_BOARD_REVISION(x)	(__u8)(((x)&0x0f))
 
@@ -469,20 +658,30 @@ struct ti_basic_descriptor
 
 #define TI_MAX_I2C_SIZE			( 16 * 1024 )
 
-/* TI USB 5052 definitions */
+#define TI_MANUF_VERSION_0		0	
+
+// IonConig2 flags
+#define TI_CONFIG2_RS232		0x01
+#define TI_CONFIG2_RS422		0x02
+#define TI_CONFIG2_RS485		0x04
+#define TI_CONFIG2_SWITCHABLE		0x08
+
+#define TI_CONFIG2_WATCHPORT		0x10
+
+
 struct edge_ti_manuf_descriptor
 {
 	__u8 IonConfig;		//  Config byte for ION manufacturing use
 	__u8 IonConfig2;	//  Expansion
-	__u8 Version;		//  Verqsion
+	__u8 Version;		//  Version
 	__u8 CpuRev_BoardRev;	//  CPU revision level (0xF0) and Board Rev Level (0x0F)
 	__u8 NumPorts;		//  Number of ports	for this UMP
 	__u8 NumVirtualPorts;	//  Number of Virtual ports
 	__u8 HubConfig1;	//  Used to configure the Hub
 	__u8 HubConfig2;	//  Used to configure the Hub
 	__u8 TotalPorts;	//  Total Number of Com Ports for the entire device (All UMPs)
-	__u8 Reserved;
+	__u8 Reserved;		//  Reserved
 }__attribute__((packed));
 
 
-#endif		// if !defined()
+#endif		// if !defined(_USBVEND_H)
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 42119dd44..8fbce2732 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -127,6 +127,7 @@ static struct usb_device_id ipaq_id_table [] = {
 	{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_E740_ID) },
 	{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_E335_ID) },
 	{ USB_DEVICE(HTC_VENDOR_ID, HTC_PRODUCT_ID) },
+	{ USB_DEVICE(HTC_VENDOR_ID, HTC_HIMALAYA_ID) },
 	{ USB_DEVICE(NEC_VENDOR_ID, NEC_PRODUCT_ID) },
 	{ USB_DEVICE(ASUS_VENDOR_ID, ASUS_A600_PRODUCT_ID) },
 	{ USB_DEVICE(ASUS_VENDOR_ID, ASUS_A620_PRODUCT_ID) },
@@ -188,6 +189,7 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
 	usb_set_serial_port_data(port, priv);
 	priv->active = 0;
 	priv->queue_len = 0;
+	priv->free_len = 0;
 	INIT_LIST_HEAD(&priv->queue);
 	INIT_LIST_HEAD(&priv->freelist);
 
diff --git a/drivers/usb/serial/ipaq.h b/drivers/usb/serial/ipaq.h
index e9bedde0d..b997a9596 100644
--- a/drivers/usb/serial/ipaq.h
+++ b/drivers/usb/serial/ipaq.h
@@ -78,6 +78,7 @@
 
 #define HTC_VENDOR_ID		0x0bb4
 #define HTC_PRODUCT_ID		0x00ce
+#define HTC_HIMALAYA_ID		0x0a02
 
 #define NEC_VENDOR_ID		0x0409
 #define NEC_PRODUCT_ID		0x00d5
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index cb42cc7c3..3d1571695 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -449,6 +449,10 @@ static void ir_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
 			 */
 			tty = port->tty;
 
+			/*
+			 *	FIXME: must not do this in IRQ context,
+			 *	must honour TTY_DONT_FLIP
+			 */
 			tty->ldisc.receive_buf(
 				tty,
 				data+1,
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index fd6c1b838..cd441d783 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -186,13 +186,7 @@ static void keyspan_pda_wakeup_write( struct usb_serial_port *port )
 	wake_up_interruptible( &port->write_wait );
 
 	/* wake up line discipline */
-	if( (tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
-	&& tty->ldisc.write_wakeup )
-		(tty->ldisc.write_wakeup)(tty);
-
-	/* wake up other tty processes */
-	wake_up_interruptible( &tty->write_wait );
-	/* For 2.2.16 backport -- wake_up_interruptible( &tty->poll_wait ); */
+	tty_wakeup(tty);
 }
 
 static void keyspan_pda_request_unthrottle( struct usb_serial *serial )
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index b4961f0d2..212906c74 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -579,11 +579,7 @@ static void mct_u232_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
 
 	if (write_blocking) {
 		wake_up_interruptible(&port->write_wait);
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-		    tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
-		
+		tty_wakeup(tty);
 	} else {
 		/* from generic_write_bulk_callback */
 		schedule_work(&port->work);
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index af0d230c6..c61e56829 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -659,7 +659,7 @@ static void pl2303_break_ctl (struct usb_serial_port *port, int break_state)
 		state = BREAK_OFF;
 	else
 		state = BREAK_ON;
-	dbg("%s - turning break %s", state==BREAK_OFF ? "off" : "on", __FUNCTION__);
+	dbg("%s - turning break %s", __FUNCTION__, state==BREAK_OFF ? "off" : "on");
 
 	result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
 				  BREAK_REQUEST, BREAK_REQUEST_TYPE, state, 
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 2656807d7..03e8a7e1c 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -421,6 +421,63 @@ static void return_serial (struct usb_serial *serial)
 	return;
 }
 
+static void destroy_serial(struct kref *kref)
+{
+	struct usb_serial *serial;
+	struct usb_serial_port *port;
+	int i;
+
+	serial = to_usb_serial(kref);
+
+	dbg ("%s - %s", __FUNCTION__, serial->type->name);
+
+	serial->type->shutdown(serial);
+
+	/* return the minor range that this device had */
+	return_serial(serial);
+
+	for (i = 0; i < serial->num_ports; ++i)
+		serial->port[i]->open_count = 0;
+
+	/* the ports are cleaned up and released in port_release() */
+	for (i = 0; i < serial->num_ports; ++i)
+		if (serial->port[i]->dev.parent != NULL) {
+			device_unregister(&serial->port[i]->dev);
+			serial->port[i] = NULL;
+		}
+
+	/* If this is a "fake" port, we have to clean it up here, as it will
+	 * not get cleaned up in port_release() as it was never registered with
+	 * the driver core */
+	if (serial->num_ports < serial->num_port_pointers) {
+		for (i = serial->num_ports; i < serial->num_port_pointers; ++i) {
+			port = serial->port[i];
+			if (!port)
+				continue;
+			if (port->read_urb) {
+				usb_unlink_urb(port->read_urb);
+				usb_free_urb(port->read_urb);
+			}
+			if (port->write_urb) {
+				usb_unlink_urb(port->write_urb);
+				usb_free_urb(port->write_urb);
+			}
+			if (port->interrupt_in_urb) {
+				usb_unlink_urb(port->interrupt_in_urb);
+				usb_free_urb(port->interrupt_in_urb);
+			}
+			kfree(port->bulk_in_buffer);
+			kfree(port->bulk_out_buffer);
+			kfree(port->interrupt_in_buffer);
+		}
+	}
+
+	usb_put_dev(serial->dev);
+
+	/* free up any memory that we allocated */
+	kfree (serial);
+}
+
 /*****************************************************************************
  * Driver tty interface functions
  *****************************************************************************/
@@ -465,7 +522,7 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
 		if (retval) {
 			port->open_count = 0;
 			module_put(serial->type->owner);
-			kref_put(&serial->kref);
+			kref_put(&serial->kref, destroy_serial);
 		}
 	}
 bailout:
@@ -496,7 +553,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
 	}
 
 	module_put(port->serial->type->owner);
-	kref_put(&port->serial->kref);
+	kref_put(&port->serial->kref, destroy_serial);
 }
 
 static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
@@ -654,13 +711,6 @@ exit:
 	;
 }
 
-static void serial_shutdown (struct usb_serial *serial)
-{
-	dbg ("%s", __FUNCTION__);
-
-	serial->type->shutdown(serial);
-}
-
 static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data)
 {
 	struct usb_serial *serial;
@@ -694,7 +744,7 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int
 			begin += length;
 			length = 0;
 		}
-		kref_put(&serial->kref);
+		kref_put(&serial->kref, destroy_serial);
 	}
 	*eof = 1;
 done:
@@ -755,68 +805,7 @@ void usb_serial_port_softint(void *private)
 	if (!tty)
 		return;
 
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
-		dbg("%s - write wakeup call.", __FUNCTION__);
-		(tty->ldisc.write_wakeup)(tty);
-	}
-
-	wake_up_interruptible(&tty->write_wait);
-}
-
-static void destroy_serial(struct kref *kref)
-{
-	struct usb_serial *serial;
-	struct usb_serial_port *port;
-	int i;
-
-	serial = to_usb_serial(kref);
-
-	dbg ("%s - %s", __FUNCTION__, serial->type->name);
-	serial_shutdown (serial);
-
-	/* return the minor range that this device had */
-	return_serial(serial);
-
-	for (i = 0; i < serial->num_ports; ++i)
-		serial->port[i]->open_count = 0;
-
-	/* the ports are cleaned up and released in port_release() */
-	for (i = 0; i < serial->num_ports; ++i)
-		if (serial->port[i]->dev.parent != NULL) {
-			device_unregister(&serial->port[i]->dev);
-			serial->port[i] = NULL;
-		}
-
-	/* If this is a "fake" port, we have to clean it up here, as it will
-	 * not get cleaned up in port_release() as it was never registered with
-	 * the driver core */
-	if (serial->num_ports < serial->num_port_pointers) {
-		for (i = serial->num_ports; i < serial->num_port_pointers; ++i) {
-			port = serial->port[i];
-			if (!port)
-				continue;
-			if (port->read_urb) {
-				usb_unlink_urb(port->read_urb);
-				usb_free_urb(port->read_urb);
-			}
-			if (port->write_urb) {
-				usb_unlink_urb(port->write_urb);
-				usb_free_urb(port->write_urb);
-			}
-			if (port->interrupt_in_urb) {
-				usb_unlink_urb(port->interrupt_in_urb);
-				usb_free_urb(port->interrupt_in_urb);
-			}
-			kfree(port->bulk_in_buffer);
-			kfree(port->bulk_out_buffer);
-			kfree(port->interrupt_in_buffer);
-		}
-	}
-
-	usb_put_dev(serial->dev);
-
-	/* free up any memory that we allocated */
-	kfree (serial);
+	tty_wakeup(tty);
 }
 
 static void port_release(struct device *dev)
@@ -859,7 +848,7 @@ static struct usb_serial * create_serial (struct usb_device *dev,
 	serial->interface = interface;
 	serial->vendor = dev->descriptor.idVendor;
 	serial->product = dev->descriptor.idProduct;
-	kref_init(&serial->kref, destroy_serial);
+	kref_init(&serial->kref);
 
 	return serial;
 }
@@ -1209,7 +1198,7 @@ void usb_serial_disconnect(struct usb_interface *interface)
 	if (serial) {
 		/* let the last holder of this object 
 		 * cause it to be cleaned up */
-		kref_put(&serial->kref);
+		kref_put(&serial->kref, destroy_serial);
 	}
 	dev_info(dev, "device disconnected\n");
 }
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index b27741bf5..1b759018e 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -668,8 +668,7 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
 
 	if (port->tty->driver->flush_buffer)
 		port->tty->driver->flush_buffer(port->tty);
-	if (port->tty->ldisc.flush_buffer)
-		port->tty->ldisc.flush_buffer(port->tty);
+	tty_ldisc_flush(port->tty);
 
 	firm_report_tx_done(port);
 
diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
index 58baacc9a..94798eb1a 100644
--- a/drivers/usb/storage/datafab.c
+++ b/drivers/usb/storage/datafab.c
@@ -50,16 +50,19 @@
  * in that routine.
  */
 
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
 #include "datafab.h"
 
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-
 static int datafab_determine_lun(struct us_data *us,
 				 struct datafab_info *info);
 
@@ -388,7 +391,7 @@ static int datafab_id_device(struct us_data *us,
 
 
 static int datafab_handle_mode_sense(struct us_data *us,
-				     Scsi_Cmnd * srb, 
+				     struct scsi_cmnd * srb, 
 				     int sense_6)
 {
 	static unsigned char rw_err_page[12] = {
@@ -483,7 +486,7 @@ static int datafab_handle_mode_sense(struct us_data *us,
 	if (sense_6)
 		ptr[0] = i - 1;
 	else
-		((u16 *) ptr)[0] = cpu_to_be16(i - 2);
+		((__be16 *) ptr)[0] = cpu_to_be16(i - 2);
 	usb_stor_set_xfer_buf(ptr, i, srb);
 
 	return USB_STOR_TRANSPORT_GOOD;
@@ -498,7 +501,7 @@ static void datafab_info_destructor(void *extra)
 
 // Transport for the Datafab MDCFE-B
 //
-int datafab_transport(Scsi_Cmnd * srb, struct us_data *us)
+int datafab_transport(struct scsi_cmnd * srb, struct us_data *us)
 {
 	struct datafab_info *info;
 	int rc;
@@ -540,8 +543,8 @@ int datafab_transport(Scsi_Cmnd * srb, struct us_data *us)
 
 		// build the reply
 		// we need the last sector, not the number of sectors
-		((u32 *) ptr)[0] = cpu_to_be32(info->sectors - 1);
-		((u32 *) ptr)[1] = cpu_to_be32(info->ssize);
+		((__be32 *) ptr)[0] = cpu_to_be32(info->sectors - 1);
+		((__be32 *) ptr)[1] = cpu_to_be32(info->ssize);
 		usb_stor_set_xfer_buf(ptr, 8, srb);
 
 		return USB_STOR_TRANSPORT_GOOD;
@@ -625,12 +628,12 @@ int datafab_transport(Scsi_Cmnd * srb, struct us_data *us)
 
 	if (srb->cmnd[0] == MODE_SENSE) {
 		US_DEBUGP("datafab_transport:  MODE_SENSE_6 detected\n");
-		return datafab_handle_mode_sense(us, srb, TRUE);
+		return datafab_handle_mode_sense(us, srb, 1);
 	}
 
 	if (srb->cmnd[0] == MODE_SENSE_10) {
 		US_DEBUGP("datafab_transport:  MODE_SENSE_10 detected\n");
-		return datafab_handle_mode_sense(us, srb, FALSE);
+		return datafab_handle_mode_sense(us, srb, 0);
 	}
 
 	if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
diff --git a/drivers/usb/storage/datafab.h b/drivers/usb/storage/datafab.h
index c9343f6e4..32e3f271e 100644
--- a/drivers/usb/storage/datafab.h
+++ b/drivers/usb/storage/datafab.h
@@ -24,7 +24,7 @@
 #ifndef _USB_DATAFAB_MDCFE_B_H
 #define _USB_DATAFAB_MDCFE_B_H
 
-extern int datafab_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int datafab_transport(struct scsi_cmnd *srb, struct us_data *us);
 
 struct datafab_info {
 	unsigned long   sectors;	// total sector count
diff --git a/drivers/usb/storage/debug.c b/drivers/usb/storage/debug.c
index d4f278ca7..d76483706 100644
--- a/drivers/usb/storage/debug.c
+++ b/drivers/usb/storage/debug.c
@@ -44,9 +44,15 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/cdrom.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "debug.h"
+#include "scsi.h"
+
 
-void usb_stor_show_command(Scsi_Cmnd *srb)
+void usb_stor_show_command(struct scsi_cmnd *srb)
 {
 	char *what = NULL;
 	int i;
diff --git a/drivers/usb/storage/debug.h b/drivers/usb/storage/debug.h
index d5d6b3c76..c4f4bcf36 100644
--- a/drivers/usb/storage/debug.h
+++ b/drivers/usb/storage/debug.h
@@ -46,13 +46,13 @@
 
 #include <linux/config.h>
 #include <linux/kernel.h>
-#include <linux/cdrom.h>
-#include "usb.h"
+
+struct scsi_cmnd;
 
 #define USB_STORAGE "usb-storage: "
 
 #ifdef CONFIG_USB_STORAGE_DEBUG
-void usb_stor_show_command(Scsi_Cmnd *srb);
+void usb_stor_show_command(struct scsi_cmnd *srb);
 void usb_stor_show_sense( unsigned char key,
 		unsigned char asc, unsigned char ascq );
 #define US_DEBUGP(x...) printk( KERN_DEBUG USB_STORAGE x )
diff --git a/drivers/usb/storage/dpcm.c b/drivers/usb/storage/dpcm.c
index ae135fd3c..12c15f19a 100644
--- a/drivers/usb/storage/dpcm.c
+++ b/drivers/usb/storage/dpcm.c
@@ -30,6 +30,10 @@
  */
 
 #include <linux/config.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
@@ -41,7 +45,7 @@
  * Transport for the Microtech DPCM-USB
  *
  */
-int dpcm_transport(Scsi_Cmnd *srb, struct us_data *us)
+int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
   int ret;
 
diff --git a/drivers/usb/storage/dpcm.h b/drivers/usb/storage/dpcm.h
index e6e5637d6..81b464cfc 100644
--- a/drivers/usb/storage/dpcm.h
+++ b/drivers/usb/storage/dpcm.h
@@ -29,6 +29,6 @@
 #ifndef _MICROTECH_DPCM_USB_H
 #define _MICROTECH_DPCM_USB_H
 
-extern int dpcm_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us);
 
 #endif
diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
index 4b1ff0ad2..1dbb6301d 100644
--- a/drivers/usb/storage/freecom.c
+++ b/drivers/usb/storage/freecom.c
@@ -29,12 +29,16 @@
  */
 
 #include <linux/config.h>
+#include <linux/hdreg.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
 #include "freecom.h"
-#include "linux/hdreg.h"
 
 #ifdef CONFIG_USB_STORAGE_DEBUG
 static void pdump (void *, int);
@@ -55,14 +59,14 @@ struct freecom_cb_wrap {
 struct freecom_xfer_wrap {
 	u8    Type;		/* Command type. */
 	u8    Timeout;		/* Timeout in seconds. */
-	u32   Count;		/* Number of bytes to transfer. */
+	__le32   Count;		/* Number of bytes to transfer. */
 	u8    Pad[58];
 } __attribute__ ((packed));
 
 struct freecom_ide_out {
 	u8    Type;		/* Type + IDE register. */
 	u8    Pad;
-	u16   Value;		/* Value to write. */
+	__le16   Value;		/* Value to write. */
 	u8    Pad2[60];
 };
 
@@ -74,7 +78,7 @@ struct freecom_ide_in {
 struct freecom_status {
 	u8    Status;
 	u8    Reason;
-	u16   Count;
+	__le16   Count;
 	u8    Pad[60];
 };
 
@@ -105,7 +109,7 @@ struct freecom_status {
 #define FCM_STATUS_PACKET_LENGTH	4
 
 static int
-freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
+freecom_readdata (struct scsi_cmnd *srb, struct us_data *us,
 		unsigned int ipipe, unsigned int opipe, int count)
 {
 	struct freecom_xfer_wrap *fxfr =
@@ -139,7 +143,7 @@ freecom_readdata (Scsi_Cmnd *srb, struct us_data *us,
 }
 
 static int
-freecom_writedata (Scsi_Cmnd *srb, struct us_data *us,
+freecom_writedata (struct scsi_cmnd *srb, struct us_data *us,
 		int unsigned ipipe, unsigned int opipe, int count)
 {
 	struct freecom_xfer_wrap *fxfr =
@@ -176,7 +180,7 @@ freecom_writedata (Scsi_Cmnd *srb, struct us_data *us,
  * Transport for the Freecom USB/IDE adaptor.
  *
  */
-int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
+int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	struct freecom_cb_wrap *fcb;
 	struct freecom_status  *fst;
@@ -302,7 +306,7 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
 	 * move in. */
 
 	switch (us->srb->sc_data_direction) {
-	case SCSI_DATA_READ:
+	case DMA_FROM_DEVICE:
 		/* catch bogus "read 0 length" case */
 		if (!length)
 			break;
@@ -334,7 +338,7 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
 		US_DEBUGP("Transfer happy\n");
 		break;
 
-	case SCSI_DATA_WRITE:
+	case DMA_TO_DEVICE:
 		/* catch bogus "write 0 length" case */
 		if (!length)
 			break;
@@ -364,7 +368,7 @@ int freecom_transport(Scsi_Cmnd *srb, struct us_data *us)
 		break;
 
 
-	case SCSI_DATA_NONE:
+	case DMA_NONE:
 		/* Easy, do nothing. */
 		break;
 
diff --git a/drivers/usb/storage/freecom.h b/drivers/usb/storage/freecom.h
index 8c0ada8bb..1b012d62d 100644
--- a/drivers/usb/storage/freecom.h
+++ b/drivers/usb/storage/freecom.h
@@ -29,7 +29,7 @@
 #ifndef _FREECOM_USB_H
 #define _FREECOM_USB_H
 
-extern int freecom_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int freecom_transport(struct scsi_cmnd *srb, struct us_data *us);
 extern int usb_stor_freecom_reset(struct us_data *us);
 extern int freecom_init (struct us_data *us);
 
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index 43cc9c5e0..8aa136b4b 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -44,6 +44,16 @@
 
 /* Include files */
 
+#include <linux/jiffies.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
@@ -51,11 +61,6 @@
 #include "scsiglue.h"
 #include "isd200.h"
 
-#include <linux/jiffies.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/hdreg.h>
-#include <linux/ide.h>
 
 /* Timeout defines (in Seconds) */
 
@@ -290,8 +295,8 @@ struct isd200_info {
  */
 
 struct read_capacity_data {
-	unsigned long LogicalBlockAddress;
-	unsigned long BytesPerBlock;
+	__be32 LogicalBlockAddress;
+	__be32 BytesPerBlock;
 };
 
 /*
@@ -349,7 +354,7 @@ struct sense_data {
  * RETURNS:
  *    void
  */
-static void isd200_build_sense(struct us_data *us, Scsi_Cmnd *srb)
+static void isd200_build_sense(struct us_data *us, struct scsi_cmnd *srb)
 {
 	struct isd200_info *info = (struct isd200_info *)us->extra;
 	struct sense_data *buf = (struct sense_data *) &srb->sense_buffer[0];
@@ -427,7 +432,7 @@ static int isd200_action( struct us_data *us, int action,
 		ata.generic.RegisterSelect =
 		  REG_CYLINDER_LOW | REG_CYLINDER_HIGH |
 		  REG_STATUS | REG_ERROR;
-		srb->sc_data_direction = SCSI_DATA_READ;
+		srb->sc_data_direction = DMA_FROM_DEVICE;
 		srb->request_buffer = pointer;
 		srb->request_bufflen = value;
 		break;
@@ -439,7 +444,7 @@ static int isd200_action( struct us_data *us, int action,
 					   ACTION_SELECT_5;
 		ata.generic.RegisterSelect = REG_DEVICE_HEAD;
 		ata.write.DeviceHeadByte = value;
-		srb->sc_data_direction = SCSI_DATA_NONE;
+		srb->sc_data_direction = DMA_NONE;
 		break;
 
 	case ACTION_RESET:
@@ -448,7 +453,7 @@ static int isd200_action( struct us_data *us, int action,
 					   ACTION_SELECT_3|ACTION_SELECT_4;
 		ata.generic.RegisterSelect = REG_DEVICE_CONTROL;
 		ata.write.DeviceControlByte = ATA_DC_RESET_CONTROLLER;
-		srb->sc_data_direction = SCSI_DATA_NONE;
+		srb->sc_data_direction = DMA_NONE;
 		break;
 
 	case ACTION_REENABLE:
@@ -457,7 +462,7 @@ static int isd200_action( struct us_data *us, int action,
 					   ACTION_SELECT_3|ACTION_SELECT_4;
 		ata.generic.RegisterSelect = REG_DEVICE_CONTROL;
 		ata.write.DeviceControlByte = ATA_DC_REENABLE_CONTROLLER;
-		srb->sc_data_direction = SCSI_DATA_NONE;
+		srb->sc_data_direction = DMA_NONE;
 		break;
 
 	case ACTION_SOFT_RESET:
@@ -466,14 +471,14 @@ static int isd200_action( struct us_data *us, int action,
 		ata.generic.RegisterSelect = REG_DEVICE_HEAD | REG_COMMAND;
 		ata.write.DeviceHeadByte = info->DeviceHead;
 		ata.write.CommandByte = WIN_SRST;
-		srb->sc_data_direction = SCSI_DATA_NONE;
+		srb->sc_data_direction = DMA_NONE;
 		break;
 
 	case ACTION_IDENTIFY:
 		US_DEBUGP("   isd200_action(IDENTIFY)\n");
 		ata.generic.RegisterSelect = REG_COMMAND;
 		ata.write.CommandByte = WIN_IDENTIFY;
-		srb->sc_data_direction = SCSI_DATA_READ;
+		srb->sc_data_direction = DMA_FROM_DEVICE;
 		srb->request_buffer = (void *) info->id;
 		srb->request_bufflen = sizeof(struct hd_driveid);
 		break;
@@ -535,7 +540,7 @@ static int isd200_read_regs( struct us_data *us )
  * the device and receive the response.
  */
 static void isd200_invoke_transport( struct us_data *us, 
-			      Scsi_Cmnd *srb, 
+			      struct scsi_cmnd *srb, 
 			      union ata_cdb *ataCdb )
 {
 	int need_auto_sense = 0;
@@ -839,7 +844,7 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
 	unsigned long endTime;
 	struct isd200_info *info = (struct isd200_info *)us->extra;
 	unsigned char *regs = info->RegsBuf;
-	int recheckAsMaster = FALSE;
+	int recheckAsMaster = 0;
 
 	if ( detect )
 		endTime = jiffies + ISD200_ENUM_DETECT_TIMEOUT * HZ;
@@ -847,7 +852,7 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
 		endTime = jiffies + ISD200_ENUM_BSY_TIMEOUT * HZ;
 
 	/* loop until we detect !BSY or timeout */
-	while(TRUE) {
+	while(1) {
 #ifdef CONFIG_USB_STORAGE_DEBUG
 		char* mstr = master_slave == ATA_ADDRESS_DEVHEAD_STD ?
 			"Master" : "Slave";
@@ -899,9 +904,9 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
 			   itself okay as a master also
 			*/
 			if ((master_slave & ATA_ADDRESS_DEVHEAD_SLAVE) &&
-			    (recheckAsMaster == FALSE)) {
+			    !recheckAsMaster) {
 				US_DEBUGP("   Identified ATAPI device as slave.  Rechecking again as master\n");
-				recheckAsMaster = TRUE;
+				recheckAsMaster = 1;
 				master_slave = ATA_ADDRESS_DEVHEAD_STD;
 			} else {
 				US_DEBUGP("   Identified ATAPI device\n");
@@ -948,15 +953,15 @@ static int isd200_manual_enum(struct us_data *us)
 	if (retStatus == ISD200_GOOD) {
 		int isslave;
 		/* master or slave? */
-		retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_STD, FALSE );
+		retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_STD, 0);
 		if (retStatus == ISD200_GOOD)
-			retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_SLAVE, FALSE );
+			retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_SLAVE, 0);
 
 		if (retStatus == ISD200_GOOD) {
 			retStatus = isd200_srst(us);
 			if (retStatus == ISD200_GOOD)
 				/* ata or atapi? */
-				retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_STD, TRUE );
+				retStatus = isd200_try_enum( us, ATA_ADDRESS_DEVHEAD_STD, 1);
 		}
 
 		isslave = (info->DeviceHead & ATA_ADDRESS_DEVHEAD_SLAVE) ? 1 : 0;
@@ -1011,7 +1016,8 @@ static int isd200_get_inquiry_data( struct us_data *us )
 			} else {
 				/* ATA Command Identify successful */
 				int i;
-				__u16 *src, *dest;
+				__be16 *src;
+				__u16 *dest;
 				ide_fix_driveid(id);
 
 				US_DEBUGP("   Identify Data Structure:\n");
@@ -1063,17 +1069,17 @@ static int isd200_get_inquiry_data( struct us_data *us )
 				}
 
 				/* Fill in vendor identification fields */
-				src = (__u16*)id->model;
+				src = (__be16*)id->model;
 				dest = (__u16*)info->InquiryData.VendorId;
 				for (i=0;i<4;i++)
 					dest[i] = be16_to_cpu(src[i]);
 
-				src = (__u16*)(id->model+8);
+				src = (__be16*)(id->model+8);
 				dest = (__u16*)info->InquiryData.ProductId;
 				for (i=0;i<8;i++)
 					dest[i] = be16_to_cpu(src[i]);
 
-				src = (__u16*)id->fw_rev;
+				src = (__be16*)id->fw_rev;
 				dest = (__u16*)info->InquiryData.ProductRevisionLevel;
 				for (i=0;i<2;i++)
 					dest[i] = be16_to_cpu(src[i]);
@@ -1121,15 +1127,15 @@ static int isd200_get_inquiry_data( struct us_data *us )
  * Translate SCSI commands to ATA commands.
  *
  * RETURNS:
- *    TRUE if the command needs to be sent to the transport layer
- *    FALSE otherwise
+ *    1 if the command needs to be sent to the transport layer
+ *    0 otherwise
  */
-static int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
+static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
 			      union ata_cdb * ataCdb)
 {
 	struct isd200_info *info = (struct isd200_info *)us->extra;
 	struct hd_driveid *id = info->id;
-	int sendToTransport = TRUE;
+	int sendToTransport = 1;
 	unsigned char sectnum, head;
 	unsigned short cylinder;
 	unsigned long lba;
@@ -1147,7 +1153,7 @@ static int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
 		usb_stor_set_xfer_buf((unsigned char *) &info->InquiryData,
 				sizeof(info->InquiryData), srb);
 		srb->result = SAM_STAT_GOOD;
-		sendToTransport = FALSE;
+		sendToTransport = 0;
 		break;
 
 	case MODE_SENSE:
@@ -1167,7 +1173,7 @@ static int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
 		} else {
 			US_DEBUGP("   Media Status not supported, just report okay\n");
 			srb->result = SAM_STAT_GOOD;
-			sendToTransport = FALSE;
+			sendToTransport = 0;
 		}
 		break;
 
@@ -1185,7 +1191,7 @@ static int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
 		} else {
 			US_DEBUGP("   Media Status not supported, just report okay\n");
 			srb->result = SAM_STAT_GOOD;
-			sendToTransport = FALSE;
+			sendToTransport = 0;
 		}
 		break;
 
@@ -1209,15 +1215,14 @@ static int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
 		usb_stor_set_xfer_buf((unsigned char *) &readCapacityData,
 				sizeof(readCapacityData), srb);
 		srb->result = SAM_STAT_GOOD;
-		sendToTransport = FALSE;
+		sendToTransport = 0;
 	}
 	break;
 
 	case READ_10:
 		US_DEBUGP("   ATA OUT - SCSIOP_READ\n");
 
-		lba = *(unsigned long *)&srb->cmnd[2]; 
-		lba = cpu_to_be32(lba);
+		lba = be32_to_cpu(*(__be32 *)&srb->cmnd[2]);
 		blockCount = (unsigned long)srb->cmnd[7]<<8 | (unsigned long)srb->cmnd[8];
 
 		if (id->capability & CAPABILITY_LBA) {
@@ -1249,8 +1254,7 @@ static int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
 	case WRITE_10:
 		US_DEBUGP("   ATA OUT - SCSIOP_WRITE\n");
 
-		lba = *(unsigned long *)&srb->cmnd[2]; 
-		lba = cpu_to_be32(lba);
+		lba = be32_to_cpu(*(__be32 *)&srb->cmnd[2]);
 		blockCount = (unsigned long)srb->cmnd[7]<<8 | (unsigned long)srb->cmnd[8];
 
 		if (id->capability & CAPABILITY_LBA) {
@@ -1293,7 +1297,7 @@ static int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
 		} else {
 			US_DEBUGP("   Not removeable media, just report okay\n");
 			srb->result = SAM_STAT_GOOD;
-			sendToTransport = FALSE;
+			sendToTransport = 0;
 		}
 		break;
 
@@ -1319,14 +1323,14 @@ static int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
 		} else {
 			US_DEBUGP("   Nothing to do, just report okay\n");
 			srb->result = SAM_STAT_GOOD;
-			sendToTransport = FALSE;
+			sendToTransport = 0;
 		}
 		break;
 
 	default:
 		US_DEBUGP("Unsupported SCSI command - 0x%X\n", srb->cmnd[0]);
 		srb->result = DID_ERROR << 16;
-		sendToTransport = FALSE;
+		sendToTransport = 0;
 		break;
 	}
 
@@ -1424,9 +1428,9 @@ int isd200_Initialization(struct us_data *us)
  *
  */
 
-void isd200_ata_command(Scsi_Cmnd *srb, struct us_data *us)
+void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us)
 {
-	int sendToTransport = TRUE;
+	int sendToTransport = 1;
 	union ata_cdb ataCdb;
 
 	/* Make sure driver was initialized */
diff --git a/drivers/usb/storage/isd200.h b/drivers/usb/storage/isd200.h
index 70ebe1c39..0a35f4fa7 100644
--- a/drivers/usb/storage/isd200.h
+++ b/drivers/usb/storage/isd200.h
@@ -25,7 +25,7 @@
 #ifndef _USB_ISD200_H
 #define _USB_ISD200_H
 
-extern void isd200_ata_command(Scsi_Cmnd *srb, struct us_data *us);
+extern void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us);
 extern int isd200_Initialization(struct us_data *us);
 
 #endif
diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
index ac9c908c4..24464ece5 100644
--- a/drivers/usb/storage/jumpshot.c
+++ b/drivers/usb/storage/jumpshot.c
@@ -47,15 +47,19 @@
   * in that routine.
   */
 
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
 #include "jumpshot.h"
 
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
 
 static inline int jumpshot_bulk_read(struct us_data *us,
 				     unsigned char *data, 
@@ -319,7 +323,7 @@ static int jumpshot_id_device(struct us_data *us,
 }
 
 static int jumpshot_handle_mode_sense(struct us_data *us,
-				      Scsi_Cmnd * srb, 
+				      struct scsi_cmnd * srb, 
 				      int sense_6)
 {
 	static unsigned char rw_err_page[12] = {
@@ -409,7 +413,7 @@ static int jumpshot_handle_mode_sense(struct us_data *us,
 	if (sense_6)
 		ptr[0] = i - 1;
 	else
-		((u16 *) ptr)[0] = cpu_to_be16(i - 2);
+		((__be16 *) ptr)[0] = cpu_to_be16(i - 2);
 	usb_stor_set_xfer_buf(ptr, i, srb);
 
 	return USB_STOR_TRANSPORT_GOOD;
@@ -426,7 +430,7 @@ static void jumpshot_info_destructor(void *extra)
 
 // Transport for the Lexar 'Jumpshot'
 //
-int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us)
+int jumpshot_transport(struct scsi_cmnd * srb, struct us_data *us)
 {
 	struct jumpshot_info *info;
 	int rc;
@@ -471,8 +475,8 @@ int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us)
 
 		// build the reply
 		//
-		((u32 *) ptr)[0] = cpu_to_be32(info->sectors - 1);
-		((u32 *) ptr)[1] = cpu_to_be32(info->ssize);
+		((__be32 *) ptr)[0] = cpu_to_be32(info->sectors - 1);
+		((__be32 *) ptr)[1] = cpu_to_be32(info->ssize);
 		usb_stor_set_xfer_buf(ptr, 8, srb);
 
 		return USB_STOR_TRANSPORT_GOOD;
@@ -551,12 +555,12 @@ int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us)
 
 	if (srb->cmnd[0] == MODE_SENSE) {
 		US_DEBUGP("jumpshot_transport:  MODE_SENSE_6 detected\n");
-		return jumpshot_handle_mode_sense(us, srb, TRUE);
+		return jumpshot_handle_mode_sense(us, srb, 1);
 	}
 
 	if (srb->cmnd[0] == MODE_SENSE_10) {
 		US_DEBUGP("jumpshot_transport:  MODE_SENSE_10 detected\n");
-		return jumpshot_handle_mode_sense(us, srb, FALSE);
+		return jumpshot_handle_mode_sense(us, srb, 0);
 	}
 
 	if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
diff --git a/drivers/usb/storage/jumpshot.h b/drivers/usb/storage/jumpshot.h
index 8147197cd..19bac9d15 100644
--- a/drivers/usb/storage/jumpshot.h
+++ b/drivers/usb/storage/jumpshot.h
@@ -24,7 +24,7 @@
 #ifndef _USB_JUMPSHOT_H
 #define _USB_JUMPSHOT_H
 
-extern int jumpshot_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us);
 
 struct jumpshot_info {
    unsigned long   sectors;     // total sector count
diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
index 1c56f4944..99ed4d9bc 100644
--- a/drivers/usb/storage/protocol.c
+++ b/drivers/usb/storage/protocol.c
@@ -45,6 +45,8 @@
  */
 
 #include <linux/highmem.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
@@ -59,7 +61,7 @@
  * Fix-up the return data from an INQUIRY command to show 
  * ANSI SCSI rev 2 so we don't confuse the SCSI layers above us
  */
-static void fix_inquiry_data(Scsi_Cmnd *srb)
+static void fix_inquiry_data(struct scsi_cmnd *srb)
 {
 	unsigned char databuf[3];
 	unsigned int index, offset;
@@ -91,10 +93,10 @@ static void fix_inquiry_data(Scsi_Cmnd *srb)
  * Fix-up the return data from a READ CAPACITY command. My Feiya reader
  * returns a value that is 1 too large.
  */
-static void fix_read_capacity(Scsi_Cmnd *srb)
+static void fix_read_capacity(struct scsi_cmnd *srb)
 {
 	unsigned int index, offset;
-	u32 c;
+	__be32 c;
 	unsigned long capacity;
 
 	/* verify that it's a READ CAPACITY command */
@@ -120,11 +122,11 @@ static void fix_read_capacity(Scsi_Cmnd *srb)
  * Protocol routines
  ***********************************************************************/
 
-void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us)
+void usb_stor_qic157_command(struct scsi_cmnd *srb, struct us_data *us)
 {
 	/* Pad the ATAPI command with zeros 
 	 *
-	 * NOTE: This only works because a Scsi_Cmnd struct field contains
+	 * NOTE: This only works because a scsi_cmnd struct field contains
 	 * a unsigned char cmnd[16], so we know we have storage available
 	 */
 	for (; srb->cmd_len<12; srb->cmd_len++)
@@ -141,11 +143,11 @@ void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us)
 	}
 }
 
-void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us)
+void usb_stor_ATAPI_command(struct scsi_cmnd *srb, struct us_data *us)
 {
 	/* Pad the ATAPI command with zeros 
 	 *
-	 * NOTE: This only works because a Scsi_Cmnd struct field contains
+	 * NOTE: This only works because a scsi_cmnd struct field contains
 	 * a unsigned char cmnd[16], so we know we have storage available
 	 */
 
@@ -166,12 +168,12 @@ void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us)
 }
 
 
-void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us)
+void usb_stor_ufi_command(struct scsi_cmnd *srb, struct us_data *us)
 {
 	/* fix some commands -- this is a form of mode translation
 	 * UFI devices only accept 12 byte long commands 
 	 *
-	 * NOTE: This only works because a Scsi_Cmnd struct field contains
+	 * NOTE: This only works because a scsi_cmnd struct field contains
 	 * a unsigned char cmnd[16], so we know we have storage available
 	 */
 
@@ -213,7 +215,8 @@ void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us)
 	}
 }
 
-void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us)
+void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb,
+				       struct us_data *us)
 {
 	/* send the command to the transport layer */
 	usb_stor_invoke_transport(srb, us);
@@ -241,7 +244,7 @@ void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us)
  * pick up from where this one left off. */
 
 unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
-	unsigned int buflen, Scsi_Cmnd *srb, unsigned int *index,
+	unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index,
 	unsigned int *offset, enum xfer_buf_dir dir)
 {
 	unsigned int cnt;
@@ -327,7 +330,7 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
 /* Store the contents of buffer into srb's transfer buffer and set the
  * SCSI residue. */
 void usb_stor_set_xfer_buf(unsigned char *buffer,
-	unsigned int buflen, Scsi_Cmnd *srb)
+	unsigned int buflen, struct scsi_cmnd *srb)
 {
 	unsigned int index = 0, offset = 0;
 
diff --git a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h
index c1fcb528a..7aa460d3b 100644
--- a/drivers/usb/storage/protocol.h
+++ b/drivers/usb/storage/protocol.h
@@ -41,9 +41,8 @@
 #ifndef _PROTOCOL_H_
 #define _PROTOCOL_H_
 
-#include <linux/blkdev.h>
-#include "scsi.h"
-#include "usb.h"
+struct scsi_cmnd;
+struct us_data;
 
 /* Sub Classes */
 
@@ -60,18 +59,19 @@
 #define US_SC_DEVICE	0xff		/* Use device's value */
 
 /* Protocol handling routines */
-extern void usb_stor_ATAPI_command(Scsi_Cmnd*, struct us_data*);
-extern void usb_stor_qic157_command(Scsi_Cmnd*, struct us_data*);
-extern void usb_stor_ufi_command(Scsi_Cmnd*, struct us_data*);
-extern void usb_stor_transparent_scsi_command(Scsi_Cmnd*, struct us_data*);
+extern void usb_stor_ATAPI_command(struct scsi_cmnd*, struct us_data*);
+extern void usb_stor_qic157_command(struct scsi_cmnd*, struct us_data*);
+extern void usb_stor_ufi_command(struct scsi_cmnd*, struct us_data*);
+extern void usb_stor_transparent_scsi_command(struct scsi_cmnd*,
+		struct us_data*);
 
-/* Scsi_Cmnd transfer buffer access utilities */
+/* struct scsi_cmnd transfer buffer access utilities */
 enum xfer_buf_dir	{TO_XFER_BUF, FROM_XFER_BUF};
 
 extern unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
-	unsigned int buflen, Scsi_Cmnd *srb, unsigned int *index,
+	unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index,
 	unsigned int *offset, enum xfer_buf_dir dir);
 
 extern void usb_stor_set_xfer_buf(unsigned char *buffer,
-	unsigned int buflen, Scsi_Cmnd *srb);
+	unsigned int buflen, struct scsi_cmnd *srb);
 #endif
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index d003abe67..c18cd06ea 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -44,17 +44,23 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-#include "scsiglue.h"
-#include "usb.h"
-#include "debug.h"
-#include "transport.h"
-#include "protocol.h"
 
 #include <linux/slab.h>
 #include <linux/module.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_devinfo.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_eh.h>
 #include <scsi/scsi_host.h>
 
+#include "scsiglue.h"
+#include "usb.h"
+#include "debug.h"
+#include "transport.h"
+#include "protocol.h"
+
 /***********************************************************************
  * Host functions 
  ***********************************************************************/
@@ -92,17 +98,15 @@ static int slave_configure(struct scsi_device *sdev)
 	 * the end, scatter-gather buffers follow page boundaries. */
 	blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
 
-	/* Devices using Genesys Logic chips cause a lot of trouble for
-	 * high-speed transfers; they die unpredictably when given more
-	 * than 64 KB of data at a time.  If we detect such a device,
-	 * reduce the maximum transfer size to 64 KB = 128 sectors. */
-
-#define USB_VENDOR_ID_GENESYS	0x05e3		// Needs a standard location
-
+	/* According to the technical support people at Genesys Logic,
+	 * devices using their chips have problems transferring more than
+	 * 32 KB at a time.  In practice people have found that 64 KB
+	 * works okay and that's what Windows does.  But we'll be
+	 * conservative; people can always use the sysfs interface to
+	 * increase max_sectors. */
 	if (us->pusb_dev->descriptor.idVendor == USB_VENDOR_ID_GENESYS &&
-			us->pusb_dev->speed == USB_SPEED_HIGH &&
-			sdev->request_queue->max_sectors > 128)
-		blk_queue_max_sectors(sdev->request_queue, 128);
+			sdev->request_queue->max_sectors > 64)
+		blk_queue_max_sectors(sdev->request_queue, 64);
 
 	/* We can't put these settings in slave_alloc() because that gets
 	 * called before the device type is known.  Consequently these
@@ -146,7 +150,8 @@ static int slave_configure(struct scsi_device *sdev)
 
 /* queue a command */
 /* This is always called with scsi_lock(srb->host) held */
-static int queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *))
+static int queuecommand(struct scsi_cmnd *srb,
+			void (*done)(struct scsi_cmnd *))
 {
 	struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
 
@@ -176,7 +181,7 @@ static int queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *))
 
 /* Command abort */
 /* This is always called with scsi_lock(srb->host) held */
-static int command_abort( Scsi_Cmnd *srb )
+static int command_abort(struct scsi_cmnd *srb )
 {
 	struct Scsi_Host *host = srb->device->host;
 	struct us_data *us = (struct us_data *) host->hostdata[0];
@@ -223,7 +228,7 @@ static int command_abort( Scsi_Cmnd *srb )
 /* This invokes the transport reset mechanism to reset the state of the
  * device */
 /* This is always called with scsi_lock(srb->host) held */
-static int device_reset( Scsi_Cmnd *srb )
+static int device_reset(struct scsi_cmnd *srb)
 {
 	struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
 	int result;
@@ -258,7 +263,7 @@ static int device_reset( Scsi_Cmnd *srb )
 /* It refuses to work if there's more than one interface in
  * the device, so that other users are not affected. */
 /* This is always called with scsi_lock(srb->host) held */
-static int bus_reset( Scsi_Cmnd *srb )
+static int bus_reset(struct scsi_cmnd *srb)
 {
 	struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
 	int result;
@@ -444,10 +449,10 @@ struct scsi_host_template usb_stor_host_template = {
 	 * periodically someone should test to see which setting is more
 	 * optimal.
 	 */
-	.use_clustering =		TRUE,
+	.use_clustering =		1,
 
 	/* emulated HBA */
-	.emulated =			TRUE,
+	.emulated =			1,
 
 	/* we do our own delay after a device or bus reset */
 	.skip_settle_delay =		1,
diff --git a/drivers/usb/storage/scsiglue.h b/drivers/usb/storage/scsiglue.h
index e5dc7613b..70df2a7bc 100644
--- a/drivers/usb/storage/scsiglue.h
+++ b/drivers/usb/storage/scsiglue.h
@@ -41,17 +41,15 @@
 #ifndef _SCSIGLUE_H_
 #define _SCSIGLUE_H_
 
-#include <linux/blkdev.h>
-#include "scsi.h"
 #include <scsi/scsi_host.h>
-#include "usb.h"
+
+struct us_data;
+struct scsi_cmnd;
 
 extern void usb_stor_report_device_reset(struct us_data *us);
 
 extern unsigned char usb_stor_sense_notready[18];
 extern unsigned char usb_stor_sense_invalidCDB[18];
 extern struct scsi_host_template usb_stor_host_template;
-extern int usb_stor_scsiSense10to6(Scsi_Cmnd*);
-extern int usb_stor_scsiSense6to10(Scsi_Cmnd*);
 
 #endif
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index f96bb7535..ff81b40c2 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -41,16 +41,19 @@
  * EF: compute checksum (?)
  */
 
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
 #include "sddr09.h"
 
-#include <linux/version.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
 
 #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) )
 #define LSB_of(s) ((s)&0xFF)
@@ -1401,7 +1404,7 @@ sddr09_init(struct us_data *us) {
 /*
  * Transport for the Sandisk SDDR-09
  */
-int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
+int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	static unsigned char sensekey = 0, sensecode = 0;
 	static unsigned char havefakesense = 0;
@@ -1486,11 +1489,11 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
 
 		capacity = (info->lbact << info->blockshift) - 1;
 
-		((u32 *) ptr)[0] = cpu_to_be32(capacity);
+		((__be32 *) ptr)[0] = cpu_to_be32(capacity);
 
 		// Report page size
 
-		((u32 *) ptr)[1] = cpu_to_be32(info->pagesize);
+		((__be32 *) ptr)[1] = cpu_to_be32(info->pagesize);
 		usb_stor_set_xfer_buf(ptr, 8, srb);
 
 		return USB_STOR_TRANSPORT_GOOD;
@@ -1507,7 +1510,7 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
 				  "mode page 0x%x\n", modepage);
 
 			memcpy(ptr, mode_page_01, sizeof(mode_page_01));
-			((u16*)ptr)[0] = cpu_to_be16(sizeof(mode_page_01) - 2);
+			((__be16*)ptr)[0] = cpu_to_be16(sizeof(mode_page_01) - 2);
 			ptr[3] = (info->flags & SDDR09_WP) ? 0x80 : 0;
 			usb_stor_set_xfer_buf(ptr, sizeof(mode_page_01), srb);
 			return USB_STOR_TRANSPORT_GOOD;
@@ -1581,13 +1584,13 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
 	if (srb->request_bufflen == 0)
 		return USB_STOR_TRANSPORT_GOOD;
 
-	if (srb->sc_data_direction == SCSI_DATA_WRITE ||
-	    srb->sc_data_direction == SCSI_DATA_READ) {
-		unsigned int pipe = (srb->sc_data_direction == SCSI_DATA_WRITE)
+	if (srb->sc_data_direction == DMA_TO_DEVICE ||
+	    srb->sc_data_direction == DMA_FROM_DEVICE) {
+		unsigned int pipe = (srb->sc_data_direction == DMA_TO_DEVICE)
 				? us->send_bulk_pipe : us->recv_bulk_pipe;
 
 		US_DEBUGP("SDDR09: %s %d bytes\n",
-			  (srb->sc_data_direction == SCSI_DATA_WRITE) ?
+			  (srb->sc_data_direction == DMA_TO_DEVICE) ?
 			  "sending" : "receiving",
 			  srb->request_bufflen);
 
diff --git a/drivers/usb/storage/sddr09.h b/drivers/usb/storage/sddr09.h
index 685123939..c9d78d618 100644
--- a/drivers/usb/storage/sddr09.h
+++ b/drivers/usb/storage/sddr09.h
@@ -29,7 +29,7 @@
 
 /* Sandisk SDDR-09 stuff */
 
-extern int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us);
 
 struct sddr09_card_info {
 	unsigned long	capacity;	/* Size of card in bytes */
diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
index eb9615318..10270f42a 100644
--- a/drivers/usb/storage/sddr55.c
+++ b/drivers/usb/storage/sddr55.c
@@ -24,15 +24,19 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/jiffies.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
 #include "sddr55.h"
 
-#include <linux/jiffies.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
 
 #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) )
 #define LSB_of(s) ((s)&0xFF)
@@ -74,7 +78,7 @@ static int
 sddr55_bulk_transport(struct us_data *us, int direction,
 		      unsigned char *data, unsigned int len) {
 	struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra;
-	unsigned int pipe = (direction == SCSI_DATA_READ) ?
+	unsigned int pipe = (direction == DMA_FROM_DEVICE) ?
 			us->recv_bulk_pipe : us->send_bulk_pipe;
 
 	if (!len)
@@ -99,7 +103,7 @@ static int sddr55_status(struct us_data *us)
 	command[5] = 0xB0;
 	command[7] = 0x80;
 	result = sddr55_bulk_transport(us,
-		SCSI_DATA_WRITE, command, 8);
+		DMA_TO_DEVICE, command, 8);
 
 	US_DEBUGP("Result for send_command in status %d\n",
 		result);
@@ -110,7 +114,7 @@ static int sddr55_status(struct us_data *us)
 	}
 
 	result = sddr55_bulk_transport(us,
-		SCSI_DATA_READ, status,	4);
+		DMA_FROM_DEVICE, status,	4);
 
 	/* expect to get short transfer if no card fitted */
 	if (result == USB_STOR_XFER_SHORT || result == USB_STOR_XFER_STALLED) {
@@ -139,7 +143,7 @@ static int sddr55_status(struct us_data *us)
 
 	/* now read status */
 	result = sddr55_bulk_transport(us,
-		SCSI_DATA_READ, status,	2);
+		DMA_FROM_DEVICE, status,	2);
 
 	if (result != USB_STOR_XFER_GOOD) {
 		set_sense_info (4, 0, 0);	/* hardware error */
@@ -215,7 +219,7 @@ static int sddr55_read_data(struct us_data *us,
 
 			/* send command */
 			result = sddr55_bulk_transport(us,
-				SCSI_DATA_WRITE, command, 8);
+				DMA_TO_DEVICE, command, 8);
 
 			US_DEBUGP("Result for send_command in read_data %d\n",
 				result);
@@ -227,7 +231,7 @@ static int sddr55_read_data(struct us_data *us,
 
 			/* read data */
 			result = sddr55_bulk_transport(us,
-				SCSI_DATA_READ, buffer, len);
+				DMA_FROM_DEVICE, buffer, len);
 
 			if (result != USB_STOR_XFER_GOOD) {
 				result = USB_STOR_TRANSPORT_ERROR;
@@ -236,7 +240,7 @@ static int sddr55_read_data(struct us_data *us,
 
 			/* now read status */
 			result = sddr55_bulk_transport(us,
-				SCSI_DATA_READ, status, 2);
+				DMA_FROM_DEVICE, status, 2);
 
 			if (result != USB_STOR_XFER_GOOD) {
 				result = USB_STOR_TRANSPORT_ERROR;
@@ -390,7 +394,7 @@ static int sddr55_write_data(struct us_data *us,
 
 		/* send command */
 		result = sddr55_bulk_transport(us,
-			SCSI_DATA_WRITE, command, 8);
+			DMA_TO_DEVICE, command, 8);
 
 		if (result != USB_STOR_XFER_GOOD) {
 			US_DEBUGP("Result for send_command in write_data %d\n",
@@ -404,7 +408,7 @@ static int sddr55_write_data(struct us_data *us,
 
 		/* send the data */
 		result = sddr55_bulk_transport(us,
-			SCSI_DATA_WRITE, buffer, len);
+			DMA_TO_DEVICE, buffer, len);
 
 		if (result != USB_STOR_XFER_GOOD) {
 			US_DEBUGP("Result for send_data in write_data %d\n",
@@ -417,7 +421,7 @@ static int sddr55_write_data(struct us_data *us,
 		}
 
 		/* now read status */
-		result = sddr55_bulk_transport(us, SCSI_DATA_READ, status, 6);
+		result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, status, 6);
 
 		if (result != USB_STOR_XFER_GOOD) {
 			US_DEBUGP("Result for get_status in write_data %d\n",
@@ -483,7 +487,7 @@ static int sddr55_read_deviceID(struct us_data *us,
 	memset(command, 0, 8);
 	command[5] = 0xB0;
 	command[7] = 0x84;
-	result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8);
+	result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8);
 
 	US_DEBUGP("Result of send_control for device ID is %d\n",
 		result);
@@ -492,7 +496,7 @@ static int sddr55_read_deviceID(struct us_data *us,
 		return USB_STOR_TRANSPORT_ERROR;
 
 	result = sddr55_bulk_transport(us,
-		SCSI_DATA_READ, content, 4);
+		DMA_FROM_DEVICE, content, 4);
 
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
@@ -502,7 +506,7 @@ static int sddr55_read_deviceID(struct us_data *us,
 
 	if (content[0] != 0xff)	{
     		result = sddr55_bulk_transport(us,
-			SCSI_DATA_READ, content, 2);
+			DMA_FROM_DEVICE, content, 2);
 	}
 
 	return USB_STOR_TRANSPORT_GOOD;
@@ -624,21 +628,21 @@ static int sddr55_read_map(struct us_data *us) {
 	command[6] = numblocks * 2 / 256;
 	command[7] = 0x8A;
 
-	result = sddr55_bulk_transport(us, SCSI_DATA_WRITE, command, 8);
+	result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8);
 
 	if ( result != USB_STOR_XFER_GOOD) {
 		kfree (buffer);
 		return -1;
 	}
 
-	result = sddr55_bulk_transport(us, SCSI_DATA_READ, buffer, numblocks * 2);
+	result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, buffer, numblocks * 2);
 
 	if ( result != USB_STOR_XFER_GOOD) {
 		kfree (buffer);
 		return -1;
 	}
 
-	result = sddr55_bulk_transport(us, SCSI_DATA_READ, command, 2);
+	result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, command, 2);
 
 	if ( result != USB_STOR_XFER_GOOD) {
 		kfree (buffer);
@@ -734,7 +738,7 @@ static void sddr55_card_info_destructor(void *extra) {
 /*
  * Transport for the Sandisk SDDR-55
  */
-int sddr55_transport(Scsi_Cmnd *srb, struct us_data *us)
+int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	int result;
 	static unsigned char inquiry_response[8] = {
@@ -834,8 +838,8 @@ int sddr55_transport(Scsi_Cmnd *srb, struct us_data *us)
 		capacity /= PAGESIZE;
 		capacity--;
 
-		((u32 *) ptr)[0] = cpu_to_be32(capacity);
-		((u32 *) ptr)[1] = cpu_to_be32(PAGESIZE);
+		((__be32 *) ptr)[0] = cpu_to_be32(capacity);
+		((__be32 *) ptr)[1] = cpu_to_be32(PAGESIZE);
 		usb_stor_set_xfer_buf(ptr, 8, srb);
 
 		sddr55_read_map(us);
diff --git a/drivers/usb/storage/sddr55.h b/drivers/usb/storage/sddr55.h
index 6dc0da6d2..d6bd32f6c 100644
--- a/drivers/usb/storage/sddr55.h
+++ b/drivers/usb/storage/sddr55.h
@@ -28,7 +28,7 @@
 
 /* Sandisk SDDR-55 stuff */
 
-extern int sddr55_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us);
 extern int sddr55_reset(struct us_data *us);
 
 #endif
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index b0af06e4f..c98fa3938 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -39,16 +39,20 @@
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/cdrom.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
 #include "shuttle_usbat.h"
 
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-
 #define short_pack(LSB,MSB) ( ((u16)(LSB)) | ( ((u16)(MSB))<<8 ) )
 #define LSB_of(s) ((s)&0xFF)
 #define MSB_of(s) ((s)>>8)
@@ -275,7 +279,7 @@ static int usbat_rw_block_test(struct us_data *us,
 			       int minutes)
 {
 	int result;
-	unsigned int pipe = (direction == SCSI_DATA_READ) ?
+	unsigned int pipe = (direction == DMA_FROM_DEVICE) ?
 			us->recv_bulk_pipe : us->send_bulk_pipe;
 
 	// Not really sure the 0x07, 0x17, 0xfc, 0xe7 is necessary here,
@@ -315,9 +319,9 @@ static int usbat_rw_block_test(struct us_data *us,
 		} else
 			cmdlen = 8;
 
-		command[cmdlen-8] = (direction==SCSI_DATA_WRITE ? 0x40 : 0xC0);
+		command[cmdlen-8] = (direction==DMA_TO_DEVICE ? 0x40 : 0xC0);
 		command[cmdlen-7] = access |
-				(direction==SCSI_DATA_WRITE ? 0x05 : 0x04);
+				(direction==DMA_TO_DEVICE ? 0x05 : 0x04);
 		command[cmdlen-6] = data_reg;
 		command[cmdlen-5] = status_reg;
 		command[cmdlen-4] = timeout;
@@ -355,7 +359,7 @@ static int usbat_rw_block_test(struct us_data *us,
 
 
 		//US_DEBUGP("Transfer %s %d bytes, sg buffers %d\n",
-		//	direction == SCSI_DATA_WRITE ? "out" : "in",
+		//	direction == DMA_TO_DEVICE ? "out" : "in",
 		//	len, use_sg);
 
 		result = usb_stor_bulk_transfer_sg(us,
@@ -388,7 +392,7 @@ static int usbat_rw_block_test(struct us_data *us,
 			 * the bulk output pipe only the first time.
 			 */
 
-			if (direction==SCSI_DATA_READ && i==0) {
+			if (direction==DMA_FROM_DEVICE && i==0) {
 				if (usb_stor_clear_halt(us,
 						us->send_bulk_pipe) < 0)
 					return USB_STOR_TRANSPORT_ERROR;
@@ -399,7 +403,7 @@ static int usbat_rw_block_test(struct us_data *us,
 			 */
 
  			result = usbat_read(us, USBAT_ATA, 
-				direction==SCSI_DATA_WRITE ? 0x17 : 0x0E, 
+				direction==DMA_TO_DEVICE ? 0x17 : 0x0E, 
 				status);
 
 			if (result!=USB_STOR_XFER_GOOD)
@@ -410,7 +414,7 @@ static int usbat_rw_block_test(struct us_data *us,
 				return USB_STOR_TRANSPORT_FAILED;
 
 			US_DEBUGP("Redoing %s\n",
-			  direction==SCSI_DATA_WRITE ? "write" : "read");
+			  direction==DMA_TO_DEVICE ? "write" : "read");
 
 		} else if (result != USB_STOR_XFER_GOOD)
 			return USB_STOR_TRANSPORT_ERROR;
@@ -420,7 +424,7 @@ static int usbat_rw_block_test(struct us_data *us,
 	}
 
 	US_DEBUGP("Bummer! %s bulk data 20 times failed.\n",
-		direction==SCSI_DATA_WRITE ? "Writing" : "Reading");
+		direction==DMA_TO_DEVICE ? "Writing" : "Reading");
 
 	return USB_STOR_TRANSPORT_FAILED;
 }
@@ -520,7 +524,7 @@ static int usbat_write_user_io(struct us_data *us,
 static int usbat_handle_read10(struct us_data *us,
 			       unsigned char *registers,
 			       unsigned char *data,
-			       Scsi_Cmnd *srb)
+			       struct scsi_cmnd *srb)
 {
 	int result = USB_STOR_TRANSPORT_GOOD;
 	unsigned char *buffer;
@@ -537,7 +541,7 @@ static int usbat_handle_read10(struct us_data *us,
 		result = usbat_rw_block_test(us, USBAT_ATA, 
 			registers, data, 19,
 			0x10, 0x17, 0xFD, 0x30,
-			SCSI_DATA_READ,
+			DMA_FROM_DEVICE,
 			srb->request_buffer, 
 			srb->request_bufflen, srb->use_sg, 1);
 
@@ -606,7 +610,7 @@ static int usbat_handle_read10(struct us_data *us,
 		result = usbat_rw_block_test(us, USBAT_ATA, 
 			registers, data, 19,
 			0x10, 0x17, 0xFD, 0x30,
-			SCSI_DATA_READ,
+			DMA_FROM_DEVICE,
 			buffer,
 			len, 0, 1);
 
@@ -803,7 +807,7 @@ int init_8200e(struct us_data *us)
 /*
  * Transport for the HP 8200e
  */
-int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us)
+int hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	int result;
 	unsigned char *status = us->iobuf;
@@ -847,12 +851,12 @@ int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us)
 	if (srb->cmnd[0] == TEST_UNIT_READY)
 		transferred = 0;
 
-	if (srb->sc_data_direction == SCSI_DATA_WRITE) {
+	if (srb->sc_data_direction == DMA_TO_DEVICE) {
 
 		result = usbat_rw_block_test(us, USBAT_ATA, 
 			registers, data, 19,
 			0x10, 0x17, 0xFD, 0x30,
-			SCSI_DATA_WRITE,
+			DMA_TO_DEVICE,
 			srb->request_buffer, 
 			len, srb->use_sg, 10);
 
@@ -900,7 +904,7 @@ int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us)
 	// If there is response data to be read in 
 	// then do it here.
 
-	if (len != 0 && (srb->sc_data_direction == SCSI_DATA_READ)) {
+	if (len != 0 && (srb->sc_data_direction == DMA_FROM_DEVICE)) {
 
 		// How many bytes to read in? Check cylL register
 
diff --git a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h
index e9c4aead5..9855c1d32 100644
--- a/drivers/usb/storage/shuttle_usbat.h
+++ b/drivers/usb/storage/shuttle_usbat.h
@@ -53,7 +53,7 @@
 #define USBAT_UIO_ADPRST	0x01 // Reset SCM chip
 
 /* HP 8200e stuff */
-extern int hp8200e_transport(Scsi_Cmnd *srb, struct us_data *us);
+extern int hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us);
 extern int init_8200e(struct us_data *us);
 
 #endif
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 232155854..42f784321 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -46,15 +46,20 @@
  */
 
 #include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
 #include "transport.h"
 #include "protocol.h"
 #include "scsiglue.h"
 #include "usb.h"
 #include "debug.h"
 
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
 
 /***********************************************************************
  * Data transfer routines
@@ -260,9 +265,7 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
 		USB_ENDPOINT_HALT, endp,
 		NULL, 0, 3*HZ);
 
-	/* reset the toggles and endpoint flags */
-	usb_endpoint_running(us->pusb_dev, usb_pipeendpoint(pipe),
-		usb_pipeout(pipe));
+	/* reset the endpoint toggle */
 	usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe),
 		usb_pipeout(pipe), 0);
 
@@ -522,7 +525,7 @@ int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe,
  * This is used by the protocol layers to actually send the message to
  * the device and receive the response.
  */
-void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
+void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	int need_auto_sense;
 	int result;
@@ -569,7 +572,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
 	 * can signal most data-in errors by stalling the bulk-in pipe.
 	 */
 	if ((us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) &&
-			srb->sc_data_direction != SCSI_DATA_READ) {
+			srb->sc_data_direction != DMA_FROM_DEVICE) {
 		US_DEBUGP("-- CB transport device requiring auto-sense\n");
 		need_auto_sense = 1;
 	}
@@ -629,7 +632,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
 
 		/* set the transfer direction */
 		old_sc_data_direction = srb->sc_data_direction;
-		srb->sc_data_direction = SCSI_DATA_READ;
+		srb->sc_data_direction = DMA_FROM_DEVICE;
 
 		/* use the new buffer we have */
 		old_request_buffer = srb->request_buffer;
@@ -749,7 +752,7 @@ void usb_stor_stop_transport(struct us_data *us)
  * Control/Bulk/Interrupt transport
  */
 
-int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
+int usb_stor_CBI_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	unsigned int transfer_length = srb->request_bufflen;
 	unsigned int pipe = 0;
@@ -778,7 +781,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
 	/* DATA STAGE */
 	/* transfer the data payload for this command, if one exists*/
 	if (transfer_length) {
-		pipe = srb->sc_data_direction == SCSI_DATA_READ ? 
+		pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? 
 				us->recv_bulk_pipe : us->send_bulk_pipe;
 		result = usb_stor_bulk_transfer_sg(us, pipe,
 					srb->request_buffer, transfer_length,
@@ -849,7 +852,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
 /*
  * Control/Bulk transport
  */
-int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
+int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	unsigned int transfer_length = srb->request_bufflen;
 	int result;
@@ -877,7 +880,7 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
 	/* DATA STAGE */
 	/* transfer the data payload for this command, if one exists*/
 	if (transfer_length) {
-		unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ? 
+		unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? 
 				us->recv_bulk_pipe : us->send_bulk_pipe;
 		result = usb_stor_bulk_transfer_sg(us, pipe,
 					srb->request_buffer, transfer_length,
@@ -908,6 +911,7 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
 	int result;
 
 	/* issue the command */
+	us->iobuf[0] = 0;
 	result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
 				 US_BULK_GET_MAX_LUN, 
 				 USB_DIR_IN | USB_TYPE_CLASS | 
@@ -918,7 +922,7 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
 		  result, us->iobuf[0]);
 
 	/* if we have a successful request, return the result */
-	if (result == 1)
+	if (result >= 0)
 		return us->iobuf[0];
 
 	/* 
@@ -939,7 +943,7 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
 	return -1;
 }
 
-int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
+int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
 	struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
@@ -952,7 +956,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
 	/* set up the command wrapper */
 	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
 	bcb->DataTransferLength = cpu_to_le32(transfer_length);
-	bcb->Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
+	bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ? 1 << 7 : 0;
 	bcb->Tag = srb->serial_number;
 	bcb->Lun = srb->device->lun;
 	if (us->flags & US_FL_SCM_MULT_TARG)
@@ -977,8 +981,14 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
 
 	/* DATA STAGE */
 	/* send/receive data payload, if there is any */
+
+	/* Genesys Logic interface chips need a 100us delay between the
+	 * command phase and the data phase */
+	if (us->pusb_dev->descriptor.idVendor == USB_VENDOR_ID_GENESYS)
+		udelay(100);
+
 	if (transfer_length) {
-		unsigned int pipe = srb->sc_data_direction == SCSI_DATA_READ ? 
+		unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? 
 				us->recv_bulk_pipe : us->send_bulk_pipe;
 		result = usb_stor_bulk_transfer_sg(us, pipe,
 					srb->request_buffer, transfer_length,
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
index 123b041ab..153efd623 100644
--- a/drivers/usb/storage/transport.h
+++ b/drivers/usb/storage/transport.h
@@ -44,7 +44,8 @@
 #include <linux/config.h>
 #include <linux/blkdev.h>
 #include "usb.h"
-#include "scsi.h"
+
+struct scsi_cmnd;
 
 /* Protocols */
 
@@ -82,9 +83,9 @@
 
 /* command block wrapper */
 struct bulk_cb_wrap {
-	__u32	Signature;		/* contains 'USBC' */
+	__le32	Signature;		/* contains 'USBC' */
 	__u32	Tag;			/* unique per command id */
-	__u32	DataTransferLength;	/* size of data */
+	__le32	DataTransferLength;	/* size of data */
 	__u8	Flags;			/* direction in bit 0 */
 	__u8	Lun;			/* LUN normally 0 */
 	__u8	Length;			/* of of the CDB */
@@ -98,9 +99,9 @@ struct bulk_cb_wrap {
 
 /* command status wrapper */
 struct bulk_cs_wrap {
-	__u32	Signature;		/* should = 'USBS' */
+	__le32	Signature;		/* should = 'USBS' */
 	__u32	Tag;			/* same as original command */
-	__u32	Residue;		/* amount not transferred */
+	__le32	Residue;		/* amount not transferred */
 	__u8	Status;			/* see below */
 	__u8	Filler[18];
 };
@@ -150,16 +151,16 @@ struct bulk_cs_wrap {
 
 #define US_CBI_ADSC		0
 
-extern int usb_stor_CBI_transport(Scsi_Cmnd*, struct us_data*);
+extern int usb_stor_CBI_transport(struct scsi_cmnd *, struct us_data*);
 
-extern int usb_stor_CB_transport(Scsi_Cmnd*, struct us_data*);
+extern int usb_stor_CB_transport(struct scsi_cmnd *, struct us_data*);
 extern int usb_stor_CB_reset(struct us_data*);
 
-extern int usb_stor_Bulk_transport(Scsi_Cmnd*, struct us_data*);
+extern int usb_stor_Bulk_transport(struct scsi_cmnd *, struct us_data*);
 extern int usb_stor_Bulk_max_lun(struct us_data*);
 extern int usb_stor_Bulk_reset(struct us_data*);
 
-extern void usb_stor_invoke_transport(Scsi_Cmnd*, struct us_data*);
+extern void usb_stor_invoke_transport(struct scsi_cmnd *, struct us_data*);
 extern void usb_stor_stop_transport(struct us_data*);
 
 extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 195e98f95..4fe25f6b0 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -45,11 +45,6 @@
  *
  */
 
-UNUSUAL_DEV(  0x03ee, 0x0000, 0x0000, 0x0245, 
-		"Mitsumi",
-		"CD-R/RW Drive",
-		US_SC_8020, US_PR_CBI, NULL, 0), 
-
 UNUSUAL_DEV(  0x03ee, 0x6901, 0x0000, 0x0100,
 		"Mitsumi",
 		"USB FDD",
@@ -373,6 +368,15 @@ UNUSUAL_DEV(  0x057b, 0x0000, 0x0300, 0x9999,
 		US_SC_DEVICE,  US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN),
 
+/* Reported by Johann Cardon <johann.cardon@free.fr>
+ * This entry is needed only because the device reports
+ * bInterfaceClass = 0xff (vendor-specific)
+ */
+UNUSUAL_DEV(  0x057b, 0x0022, 0x0000, 0x9999, 
+		"Y-E Data",
+		"Silicon Media R/W",
+		US_SC_DEVICE, US_PR_DEVICE, NULL, 0),
+
 /* Fabrizio Fellini <fello@libero.it> */
 UNUSUAL_DEV(  0x0595, 0x4343, 0x0000, 0x2210,
 		"Fujifilm",
@@ -384,11 +388,15 @@ UNUSUAL_DEV(  0x059f, 0xa601, 0x0200, 0x0200,
 		"USB Hard Disk",
 		US_SC_RBC, US_PR_CB, NULL, 0 ), 
 
-/* Submitted by Jol Bourquard <numlock@freesurf.ch> */
+/* Submitted by Joel Bourquard <numlock@freesurf.ch>
+ * Some versions of this device need the SubClass and Protocol overrides
+ * while others don't.
+ */
 UNUSUAL_DEV(  0x05ab, 0x0060, 0x1104, 0x1110,
 		"In-System",
 		"PyroGate External CD-ROM Enclosure (FCD-523)",
-		US_SC_SCSI, US_PR_BULK, NULL, 0 ),
+		US_SC_SCSI, US_PR_BULK, NULL,
+		US_FL_NEED_OVERRIDE ),
 
 #ifdef CONFIG_USB_STORAGE_ISD200
 UNUSUAL_DEV(  0x05ab, 0x0031, 0x0100, 0x0110,
@@ -482,6 +490,13 @@ UNUSUAL_DEV(  0x066b, 0x0105, 0x0100, 0x0100,
 		US_FL_SINGLE_LUN ),
 #endif
 
+/* Reported by Darsen Lu <darsen@micro.ee.nthu.edu.tw> */
+UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001,
+		"SigmaTel",
+		"USBMSC Audio Player",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_CAPACITY ),
+
 /* Submitted by Benny Sjostrand <benny@hostmobility.com> */
 UNUSUAL_DEV( 0x0686, 0x4011, 0x0001, 0x0001,
 		"Minolta",
@@ -510,11 +525,13 @@ UNUSUAL_DEV(  0x0781, 0x0001, 0x0200, 0x0200,
 		US_SC_SCSI, US_PR_CB, NULL,
 		US_FL_SINGLE_LUN ),
 
+#if !defined(CONFIG_BLK_DEV_UB) && !defined(CONFIG_BLK_DEV_UB_MODULE)
 UNUSUAL_DEV(  0x0781, 0x0002, 0x0009, 0x0009, 
 		"Sandisk",
 		"ImageMate SDDR-31",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_IGNORE_SER ),
+#endif
 
 UNUSUAL_DEV(  0x0781, 0x0100, 0x0100, 0x0100,
 		"Sandisk",
@@ -685,7 +702,7 @@ UNUSUAL_DEV(  0x090a, 0x1001, 0x0100, 0x0100,
 		"Trumpion",
 		"t33520 USB Flash Card Controller",
 		US_SC_DEVICE, US_PR_BULK, NULL,
-		US_FL_MODE_XLATE),
+		US_FL_NEED_OVERRIDE | US_FL_MODE_XLATE),
 
 /* Trumpion Microelectronics MP3 player (felipe_alfaro@linuxmail.org) */
 UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999,
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index ad22739be..9579bdf49 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -50,6 +50,11 @@
 #include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
 #include "usb.h"
 #include "scsiglue.h"
 #include "transport.h"
@@ -133,7 +138,9 @@ static struct usb_device_id storage_usb_ids [] = {
 	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_BULK) },
 	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_BULK) },
 	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_BULK) },
+#if !defined(CONFIG_BLK_DEV_UB) && !defined(CONFIG_BLK_DEV_UB_MODULE)
 	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
+#endif
 
 	/* Terminating entry */
 	{ }
@@ -207,8 +214,10 @@ static struct us_unusual_dev us_unusual_dev_list[] = {
 	  .useTransport = US_PR_BULK},
 	{ .useProtocol = US_SC_8070,
 	  .useTransport = US_PR_BULK},
+#if !defined(CONFIG_BLK_DEV_UB) && !defined(CONFIG_BLK_DEV_UB_MODULE)
 	{ .useProtocol = US_SC_SCSI,
 	  .useTransport = US_PR_BULK},
+#endif
 
 	/* Terminating entry */
 	{ NULL }
@@ -322,7 +331,7 @@ static int usb_stor_control_thread(void * __us)
 		/* reject the command if the direction indicator 
 		 * is UNKNOWN
 		 */
-		if (us->srb->sc_data_direction == SCSI_DATA_UNKNOWN) {
+		if (us->srb->sc_data_direction == DMA_BIDIRECTIONAL) {
 			US_DEBUGP("UNKNOWN data direction\n");
 			us->srb->result = DID_ERROR << 16;
 		}
@@ -423,6 +432,13 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf)
 	us->pusb_dev = interface_to_usbdev(intf);
 	us->pusb_intf = intf;
 	us->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+	US_DEBUGP("Vendor: 0x%04x, Product: 0x%04x, Revision: 0x%04x\n",
+			us->pusb_dev->descriptor.idVendor,
+			us->pusb_dev->descriptor.idProduct,
+			us->pusb_dev->descriptor.bcdDevice);
+	US_DEBUGP("Interface Subclass: 0x%02x, Protocol: 0x%02x\n",
+			intf->cur_altsetting->desc.bInterfaceSubClass,
+			intf->cur_altsetting->desc.bInterfaceProtocol);
 
 	/* Store our private data in the interface */
 	usb_set_intfdata(intf, us);
@@ -453,11 +469,6 @@ static void get_device_info(struct us_data *us, int id_index)
 	struct us_unusual_dev *unusual_dev = &us_unusual_dev_list[id_index];
 	struct usb_device_id *id = &storage_usb_ids[id_index];
 
-	if (unusual_dev->vendorName)
-		US_DEBUGP("Vendor: %s\n", unusual_dev->vendorName);
-	if (unusual_dev->productName)
-		US_DEBUGP("Product: %s\n", unusual_dev->productName);
-
 	/* Store the entries */
 	us->unusual_dev = unusual_dev;
 	us->subclass = (unusual_dev->useProtocol == US_SC_DEVICE) ?
@@ -528,6 +539,8 @@ static void get_device_info(struct us_data *us, int id_index)
 	}
 	if (strlen(us->serial) == 0)
 		strcpy(us->serial, "None");
+
+	US_DEBUGP("Vendor: %s,  Product: %s\n", us->vendor, us->product);
 }
 
 /* Get the transport settings */
@@ -715,8 +728,6 @@ static int get_pipes(struct us_data *us)
 			ep_int = ep;
 		}
 	}
-	US_DEBUGP("Endpoints: In: 0x%p Out: 0x%p Int: 0x%p (Period %d)\n",
-		  ep_in, ep_out, ep_int, ep_int ? ep_int->bInterval : 0);
 
 	if (!ep_in || !ep_out || (us->protocol == US_PR_CBI && !ep_int)) {
 		US_DEBUGP("Endpoint sanity check failed! Rejecting dev.\n");
@@ -880,9 +891,6 @@ static int storage_probe(struct usb_interface *intf,
 	int result;
 
 	US_DEBUGP("USB Mass Storage device detected\n");
-	US_DEBUGP("altsetting is %d, id_index is %d\n",
-			intf->cur_altsetting->desc.bAlternateSetting,
-			id_index);
 
 	/* Allocate the us_data structure and initialize the mutexes */
 	us = (struct us_data *) kmalloc(sizeof(*us), GFP_KERNEL);
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 35d01444a..785f30be6 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -48,10 +48,9 @@
 #include <linux/blkdev.h>
 #include <linux/smp_lock.h>
 #include <linux/completion.h>
-#include "scsi.h"
-#include <scsi/scsi_host.h>
 
 struct us_data;
+struct scsi_cmnd;
 
 /*
  * Unusual device list definitions 
@@ -102,9 +101,9 @@ struct us_unusual_dev {
 
 #define US_IOBUF_SIZE		64	/* Size of the DMA-mapped I/O buffer */
 
-typedef int (*trans_cmnd)(Scsi_Cmnd*, struct us_data*);
+typedef int (*trans_cmnd)(struct scsi_cmnd *, struct us_data*);
 typedef int (*trans_reset)(struct us_data*);
-typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*);
+typedef void (*proto_cmnd)(struct scsi_cmnd*, struct us_data*);
 typedef void (*extra_data_destructor)(void *);	 /* extra data destructor   */
 
 /* we allocate one of these for every device that we remember */
@@ -144,7 +143,7 @@ struct us_data {
 
 	/* SCSI interfaces */
 	struct Scsi_Host	*host;		 /* our dummy host data */
-	Scsi_Cmnd		*srb;		 /* current srb		*/
+	struct scsi_cmnd	*srb;		 /* current srb		*/
 
 	/* thread information */
 	int			pid;		 /* control thread	 */
@@ -180,4 +179,8 @@ extern void fill_inquiry_response(struct us_data *us,
 #define scsi_unlock(host)	spin_unlock_irq(host->host_lock)
 #define scsi_lock(host)		spin_lock_irq(host->host_lock)
 
+
+/* Vendor ID list for devices that require special handling */
+#define USB_VENDOR_ID_GENESYS		0x05e3	/* Genesys Logic */
+
 #endif
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index f893cc078..d3a3fd9b1 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -1,42 +1,15 @@
 /*
- * USB Skeleton driver - 1.1
+ * USB Skeleton driver - 2.0
  *
- * Copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.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.
  *
- *
- * This driver is to be used as a skeleton driver to be able to create a
- * USB driver quickly.  The design of it is based on the usb-serial and
- * dc2xx drivers.
- *
- * Thanks to Oliver Neukum, David Brownell, and Alan Stern for their help
- * in debugging this driver.
- *
- *
- * History:
- *
- * 2003-05-06 - 1.1 - changes due to usb core changes with usb_register_dev()
- * 2003-02-25 - 1.0 - fix races involving urb->status, unlink_urb(), and
- *			disconnect.  Fix transfer amount in read().  Use
- *			macros instead of magic numbers in probe().  Change
- *			size variables to size_t.  Show how to eliminate
- *			DMA bounce buffer.
- * 2002_12_12 - 0.9 - compile fixes and got rid of fixed minor array.
- * 2002_09_26 - 0.8 - changes due to USB core conversion to struct device
- *			driver.
- * 2002_02_12 - 0.7 - zero out dev in probe function for devices that do
- *			not have both a bulk in and bulk out endpoint.
- *			Thanks to Holger Waechtler for the fix.
- * 2001_11_05 - 0.6 - fix minor locking problem in skel_disconnect.
- *			Thanks to Pete Zaitcev for the fix.
- * 2001_09_04 - 0.5 - fix devfs bug in skel_disconnect. Thanks to wim delvaux
- * 2001_08_21 - 0.4 - more small bug fixes.
- * 2001_05_29 - 0.3 - more bug fixes based on review from linux-usb-devel
- * 2001_05_24 - 0.2 - bug fixes based on review from linux-usb-devel people
- * 2001_05_01 - 0.1 - first version
+ * This driver is based on the 2.6.3 version of drivers/usb/usb-skeleton.c 
+ * but has been rewritten to be easy to read and use, as no locks are now
+ * needed anymore.
  *
  */
 
@@ -46,31 +19,10 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <linux/smp_lock.h>
-#include <linux/completion.h>
+#include <linux/kref.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
 
-#ifdef CONFIG_USB_DEBUG
-	static int debug = 1;
-#else
-	static int debug;
-#endif
-
-/* Use our own dbg macro */
-#undef dbg
-#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg); } while (0)
-
-
-/* Version Information */
-#define DRIVER_VERSION "v1.0"
-#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com"
-#define DRIVER_DESC "USB Skeleton Driver"
-
-/* Module parameters */
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
 
 /* Define these values to match your devices */
 #define USB_SKEL_VENDOR_ID	0xfff0
@@ -79,11 +31,8 @@ MODULE_PARM_DESC(debug, "Debug enabled or not");
 /* table of devices that work with this driver */
 static struct usb_device_id skel_table [] = {
 	{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
-	/* "Gadget Zero" firmware runs under Linux */
-	{ USB_DEVICE(0x0525, 0xa4a0) },
 	{ }					/* Terminating entry */
 };
-
 MODULE_DEVICE_TABLE (usb, skel_table);
 
 
@@ -92,413 +41,195 @@ MODULE_DEVICE_TABLE (usb, skel_table);
 
 /* Structure to hold all of our device specific stuff */
 struct usb_skel {
-	struct usb_device *	udev;			/* save off the usb device pointer */
+	struct usb_device *	udev;			/* the usb device for this device */
 	struct usb_interface *	interface;		/* the interface for this device */
-	unsigned char		minor;			/* the starting minor number for this device */
-	unsigned char		num_ports;		/* the number of ports this device has */
-	char			num_interrupt_in;	/* number of interrupt in endpoints we have */
-	char			num_bulk_in;		/* number of bulk in endpoints we have */
-	char			num_bulk_out;		/* number of bulk out endpoints we have */
-
 	unsigned char *		bulk_in_buffer;		/* the buffer to receive data */
 	size_t			bulk_in_size;		/* the size of the receive buffer */
 	__u8			bulk_in_endpointAddr;	/* the address of the bulk in endpoint */
-
-	unsigned char *		bulk_out_buffer;	/* the buffer to send data */
-	size_t			bulk_out_size;		/* the size of the send buffer */
-	struct urb *		write_urb;		/* the urb used to send data */
 	__u8			bulk_out_endpointAddr;	/* the address of the bulk out endpoint */
-	atomic_t		write_busy;		/* true iff write urb is busy */
-	struct completion	write_finished;		/* wait for the write to finish */
-
-	int			open;			/* if the port is open or not */
-	int			present;		/* if the device is not disconnected */
-	struct semaphore	sem;			/* locks this structure */
-};
-
-
-/* prevent races between open() and disconnect() */
-static DECLARE_MUTEX (disconnect_sem);
-
-/* local function prototypes */
-static ssize_t skel_read	(struct file *file, char *buffer, size_t count, loff_t *ppos);
-static ssize_t skel_write	(struct file *file, const char *buffer, size_t count, loff_t *ppos);
-static int skel_ioctl		(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
-static int skel_open		(struct inode *inode, struct file *file);
-static int skel_release		(struct inode *inode, struct file *file);
-
-static int skel_probe		(struct usb_interface *interface, const struct usb_device_id *id);
-static void skel_disconnect	(struct usb_interface *interface);
-
-static void skel_write_bulk_callback	(struct urb *urb, struct pt_regs *regs);
-
-/*
- * File operations needed when we register this driver.
- * This assumes that this driver NEEDS file operations,
- * of course, which means that the driver is expected
- * to have a node in the /dev directory. If the USB
- * device were for a network interface then the driver
- * would use "struct net_driver" instead, and a serial
- * device would use "struct tty_driver".
- */
-static struct file_operations skel_fops = {
-	/*
-	 * The owner field is part of the module-locking
-	 * mechanism. The idea is that the kernel knows
-	 * which module to increment the use-counter of
-	 * BEFORE it calls the device's open() function.
-	 * This also means that the kernel can decrement
-	 * the use-counter again before calling release()
-	 * or should the open() function fail.
-	 */
-	.owner =	THIS_MODULE,
-
-	.read =		skel_read,
-	.write =	skel_write,
-	.ioctl =	skel_ioctl,
-	.open =		skel_open,
-	.release =	skel_release,
-};
-
-/* 
- * usb class driver info in order to get a minor number from the usb core,
- * and to have the device registered with devfs and the driver core
- */
-static struct usb_class_driver skel_class = {
-	.name =		"usb/skel%d",
-	.fops =		&skel_fops,
-	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
-	.minor_base =	USB_SKEL_MINOR_BASE,
-};
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver skel_driver = {
-	.owner =	THIS_MODULE,
-	.name =		"skeleton",
-	.probe =	skel_probe,
-	.disconnect =	skel_disconnect,
-	.id_table =	skel_table,
+	struct kref		kref;
 };
+#define to_skel_dev(d) container_of(d, struct usb_skel, kref)
 
+static struct usb_driver skel_driver;
 
-/**
- *	usb_skel_debug_data
- */
-static inline void usb_skel_debug_data (const char *function, int size, const unsigned char *data)
-{
-	int i;
+static void skel_delete(struct kref *kref)
+{	
+	struct usb_skel *dev = to_skel_dev(kref);
 
-	if (!debug)
-		return;
-
-	printk (KERN_DEBUG __FILE__": %s - length = %d, data = ",
-		function, size);
-	for (i = 0; i < size; ++i) {
-		printk ("%.2x ", data[i]);
-	}
-	printk ("\n");
-}
-
-
-/**
- *	skel_delete
- */
-static inline void skel_delete (struct usb_skel *dev)
-{
+	usb_put_dev(dev->udev);
 	kfree (dev->bulk_in_buffer);
-	usb_buffer_free (dev->udev, dev->bulk_out_size,
-				dev->bulk_out_buffer,
-				dev->write_urb->transfer_dma);
-	usb_free_urb (dev->write_urb);
 	kfree (dev);
 }
 
-
-/**
- *	skel_open
- */
-static int skel_open (struct inode *inode, struct file *file)
+static int skel_open(struct inode *inode, struct file *file)
 {
-	struct usb_skel *dev = NULL;
+	struct usb_skel *dev;
 	struct usb_interface *interface;
 	int subminor;
 	int retval = 0;
 
-	dbg("%s", __FUNCTION__);
-
 	subminor = iminor(inode);
 
-	/* prevent disconnects */
-	down (&disconnect_sem);
-
-	interface = usb_find_interface (&skel_driver, subminor);
+	interface = usb_find_interface(&skel_driver, subminor);
 	if (!interface) {
 		err ("%s - error, can't find device for minor %d",
 		     __FUNCTION__, subminor);
 		retval = -ENODEV;
-		goto exit_no_device;
+		goto exit;
 	}
 
 	dev = usb_get_intfdata(interface);
 	if (!dev) {
 		retval = -ENODEV;
-		goto exit_no_device;
+		goto exit;
 	}
 
-	/* lock this device */
-	down (&dev->sem);
-
-	/* increment our usage count for the driver */
-	++dev->open;
+	/* increment our usage count for the device */
+	kref_get(&dev->kref);
 
 	/* save our object in the file's private structure */
 	file->private_data = dev;
 
-	/* unlock this device */
-	up (&dev->sem);
-
-exit_no_device:
-	up (&disconnect_sem);
+exit:
 	return retval;
 }
 
-
-/**
- *	skel_release
- */
-static int skel_release (struct inode *inode, struct file *file)
+static int skel_release(struct inode *inode, struct file *file)
 {
 	struct usb_skel *dev;
-	int retval = 0;
 
 	dev = (struct usb_skel *)file->private_data;
-	if (dev == NULL) {
-		dbg ("%s - object is NULL", __FUNCTION__);
+	if (dev == NULL)
 		return -ENODEV;
-	}
 
-	dbg("%s - minor %d", __FUNCTION__, dev->minor);
-
-	/* lock our device */
-	down (&dev->sem);
-
-	if (dev->open <= 0) {
-		dbg ("%s - device not opened", __FUNCTION__);
-		retval = -ENODEV;
-		goto exit_not_opened;
-	}
-
-	/* wait for any bulk writes that might be going on to finish up */
-	if (atomic_read (&dev->write_busy))
-		wait_for_completion (&dev->write_finished);
-
-	--dev->open;
-
-	if (!dev->present && !dev->open) {
-		/* the device was unplugged before the file was released */
-		up (&dev->sem);
-		skel_delete (dev);
-		return 0;
-	}
-
-exit_not_opened:
-	up (&dev->sem);
-
-	return retval;
+	/* decrement the count on our device */
+	kref_put(&dev->kref, skel_delete);
+	return 0;
 }
 
-
-/**
- *	skel_read
- */
-static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t *ppos)
+static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
 	struct usb_skel *dev;
 	int retval = 0;
 
 	dev = (struct usb_skel *)file->private_data;
-
-	dbg("%s - minor %d, count = %d", __FUNCTION__, dev->minor, count);
-
-	/* lock this object */
-	down (&dev->sem);
-
-	/* verify that the device wasn't unplugged */
-	if (!dev->present) {
-		up (&dev->sem);
-		return -ENODEV;
-	}
-
+	
 	/* do a blocking bulk read to get data from the device */
-	retval = usb_bulk_msg (dev->udev,
-			       usb_rcvbulkpipe (dev->udev,
-						dev->bulk_in_endpointAddr),
-			       dev->bulk_in_buffer,
-			       min (dev->bulk_in_size, count),
-			       &count, HZ*10);
+	retval = usb_bulk_msg(dev->udev,
+			      usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
+			      dev->bulk_in_buffer,
+			      min(dev->bulk_in_size, count),
+			      &count, HZ*10);
 
 	/* if the read was successful, copy the data to userspace */
 	if (!retval) {
-		if (copy_to_user (buffer, dev->bulk_in_buffer, count))
+		if (copy_to_user(buffer, dev->bulk_in_buffer, count))
 			retval = -EFAULT;
 		else
 			retval = count;
 	}
 
-	/* unlock the device */
-	up (&dev->sem);
 	return retval;
 }
 
-
-/**
- *	skel_write
- *
- *	A device driver has to decide how to report I/O errors back to the
- *	user.  The safest course is to wait for the transfer to finish before
- *	returning so that any errors will be reported reliably.  skel_read()
- *	works like this.  But waiting for I/O is slow, so many drivers only
- *	check for errors during I/O initiation and do not report problems
- *	that occur during the actual transfer.  That's what we will do here.
- *
- *	A driver concerned with maximum I/O throughput would use double-
- *	buffering:  Two urbs would be devoted to write transfers, so that
- *	one urb could always be active while the other was waiting for the
- *	user to send more data.
- */
-static ssize_t skel_write (struct file *file, const char *buffer, size_t count, loff_t *ppos)
+static void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
 {
 	struct usb_skel *dev;
-	ssize_t bytes_written = 0;
-	int retval = 0;
 
-	dev = (struct usb_skel *)file->private_data;
+	dev = (struct usb_skel *)urb->context;
 
-	dbg("%s - minor %d, count = %d", __FUNCTION__, dev->minor, count);
+	/* sync/async unlink faults aren't errors */
+	if (urb->status && 
+	    !(urb->status == -ENOENT || 
+	      urb->status == -ECONNRESET ||
+	      urb->status == -ESHUTDOWN)) {
+		dbg("%s - nonzero write bulk status received: %d",
+		    __FUNCTION__, urb->status);
+	}
 
-	/* lock this object */
-	down (&dev->sem);
+	/* free up our allocated buffer */
+	usb_buffer_free(urb->dev, urb->transfer_buffer_length, 
+			urb->transfer_buffer, urb->transfer_dma);
+}
 
-	/* verify that the device wasn't unplugged */
-	if (!dev->present) {
-		retval = -ENODEV;
-		goto exit;
-	}
+static ssize_t skel_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos)
+{
+	struct usb_skel *dev;
+	int retval = 0;
+	struct urb *urb = NULL;
+	char *buf = NULL;
+
+	dev = (struct usb_skel *)file->private_data;
 
 	/* verify that we actually have some data to write */
-	if (count == 0) {
-		dbg("%s - write request of 0 bytes", __FUNCTION__);
+	if (count == 0)
 		goto exit;
-	}
 
-	/* wait for a previous write to finish up; we don't use a timeout
-	 * and so a nonresponsive device can delay us indefinitely.
-	 */
-	if (atomic_read (&dev->write_busy))
-		wait_for_completion (&dev->write_finished);
+	/* create a urb, and a buffer for it, and copy the data to the urb */
+	urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!urb) {
+		retval = -ENOMEM;
+		goto error;
+	}
 
-	/* we can only write as much as our buffer will hold */
-	bytes_written = min (dev->bulk_out_size, count);
+	buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);
+	if (!buf) {
+		retval = -ENOMEM;
+		goto error;
+	}
 
-	/* copy the data from userspace into our transfer buffer;
-	 * this is the only copy required.
-	 */
-	if (copy_from_user(dev->write_urb->transfer_buffer, buffer,
-			   bytes_written)) {
+	if (copy_from_user(buf, user_buffer, count)) {
 		retval = -EFAULT;
-		goto exit;
+		goto error;
 	}
 
-	usb_skel_debug_data (__FUNCTION__, bytes_written,
-			     dev->write_urb->transfer_buffer);
-
-	/* this urb was already set up, except for this write size */
-	dev->write_urb->transfer_buffer_length = bytes_written;
+	/* initialize the urb properly */
+	usb_fill_bulk_urb(urb, dev->udev,
+			  usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
+			  buf, count, skel_write_bulk_callback, dev);
+	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
 	/* send the data out the bulk port */
-	/* a character device write uses GFP_KERNEL,
-	 unless a spinlock is held */
-	init_completion (&dev->write_finished);
-	atomic_set (&dev->write_busy, 1);
-	retval = usb_submit_urb(dev->write_urb, GFP_KERNEL);
+	retval = usb_submit_urb(urb, GFP_KERNEL);
 	if (retval) {
-		atomic_set (&dev->write_busy, 0);
-		err("%s - failed submitting write urb, error %d",
-		    __FUNCTION__, retval);
-	} else {
-		retval = bytes_written;
+		err("%s - failed submitting write urb, error %d", __FUNCTION__, retval);
+		goto error;
 	}
 
+	/* release our reference to this urb, the USB core will eventually free it entirely */
+	usb_free_urb(urb);
+
 exit:
-	/* unlock the device */
-	up (&dev->sem);
+	return count;
 
+error:
+	usb_buffer_free(dev->udev, count, buf, urb->transfer_dma);
+	usb_free_urb(urb);
 	return retval;
 }
 
+static struct file_operations skel_fops = {
+	.owner =	THIS_MODULE,
+	.read =		skel_read,
+	.write =	skel_write,
+	.open =		skel_open,
+	.release =	skel_release,
+};
 
-/**
- *	skel_ioctl
- */
-static int skel_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct usb_skel *dev;
-
-	dev = (struct usb_skel *)file->private_data;
-
-	/* lock this object */
-	down (&dev->sem);
-
-	/* verify that the device wasn't unplugged */
-	if (!dev->present) {
-		up (&dev->sem);
-		return -ENODEV;
-	}
-
-	dbg("%s - minor %d, cmd 0x%.4x, arg %ld", __FUNCTION__,
-	    dev->minor, cmd, arg);
-
-	/* fill in your device specific stuff here */
-
-	/* unlock the device */
-	up (&dev->sem);
-
-	/* return that we did not understand this ioctl call */
-	return -ENOTTY;
-}
-
-
-/**
- *	skel_write_bulk_callback
+/* 
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with devfs and the driver core
  */
-static void skel_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
-{
-	struct usb_skel *dev = (struct usb_skel *)urb->context;
-
-	dbg("%s - minor %d", __FUNCTION__, dev->minor);
-
-	/* sync/async unlink faults aren't errors */
-	if (urb->status && !(urb->status == -ENOENT ||
-				urb->status == -ECONNRESET)) {
-		dbg("%s - nonzero write bulk status received: %d",
-		    __FUNCTION__, urb->status);
-	}
-
-	/* notify anyone waiting that the write has finished */
-	atomic_set (&dev->write_busy, 0);
-	complete (&dev->write_finished);
-}
-
+static struct usb_class_driver skel_class = {
+	.name =		"usb/skel%d",
+	.fops =		&skel_fops,
+	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,
+	.minor_base =	USB_SKEL_MINOR_BASE,
+};
 
-/**
- *	skel_probe
- *
- *	Called by the usb core when a new device is connected that it thinks
- *	this driver might be interested in.
- */
 static int skel_probe(struct usb_interface *interface, const struct usb_device_id *id)
 {
-	struct usb_device *udev = interface_to_usbdev(interface);
 	struct usb_skel *dev = NULL;
 	struct usb_host_interface *iface_desc;
 	struct usb_endpoint_descriptor *endpoint;
@@ -506,28 +237,21 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
 	int i;
 	int retval = -ENOMEM;
 
-	/* See if the device offered us matches what we can accept */
-	if ((udev->descriptor.idVendor != USB_SKEL_VENDOR_ID) ||
-	    (udev->descriptor.idProduct != USB_SKEL_PRODUCT_ID)) {
-		return -ENODEV;
-	}
-
 	/* allocate memory for our device state and initialize it */
-	dev = kmalloc (sizeof(struct usb_skel), GFP_KERNEL);
+	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL) {
-		err ("Out of memory");
-		return -ENOMEM;
+		err("Out of memory");
+		goto error;
 	}
-	memset (dev, 0x00, sizeof (*dev));
+	memset(dev, 0x00, sizeof(*dev));
+	kref_init(&dev->kref);
 
-	init_MUTEX (&dev->sem);
-	dev->udev = udev;
+	dev->udev = usb_get_dev(interface_to_usbdev(interface));
 	dev->interface = interface;
 
 	/* set up the endpoint information */
-	/* check out the endpoints */
 	/* use only the first bulk-in and bulk-out endpoints */
-	iface_desc = &interface->altsetting[0];
+	iface_desc = interface->cur_altsetting;
 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
 		endpoint = &iface_desc->endpoint[i].desc;
 
@@ -539,9 +263,9 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
 			buffer_size = endpoint->wMaxPacketSize;
 			dev->bulk_in_size = buffer_size;
 			dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
-			dev->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
+			dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
 			if (!dev->bulk_in_buffer) {
-				err("Couldn't allocate bulk_in_buffer");
+				err("Could not allocate bulk_in_buffer");
 				goto error;
 			}
 		}
@@ -551,153 +275,85 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
 		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
 					== USB_ENDPOINT_XFER_BULK)) {
 			/* we found a bulk out endpoint */
-			/* a probe() may sleep and has no restrictions on memory allocations */
-			dev->write_urb = usb_alloc_urb(0, GFP_KERNEL);
-			if (!dev->write_urb) {
-				err("No free urbs available");
-				goto error;
-			}
 			dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
-
-			/* on some platforms using this kind of buffer alloc
-			 * call eliminates a dma "bounce buffer".
-			 *
-			 * NOTE: you'd normally want i/o buffers that hold
-			 * more than one packet, so that i/o delays between
-			 * packets don't hurt throughput.
-			 */
-			buffer_size = endpoint->wMaxPacketSize;
-			dev->bulk_out_size = buffer_size;
-			dev->write_urb->transfer_flags = (URB_NO_TRANSFER_DMA_MAP |
-					URB_ASYNC_UNLINK);
-			dev->bulk_out_buffer = usb_buffer_alloc (udev,
-					buffer_size, GFP_KERNEL,
-					&dev->write_urb->transfer_dma);
-			if (!dev->bulk_out_buffer) {
-				err("Couldn't allocate bulk_out_buffer");
-				goto error;
-			}
-			usb_fill_bulk_urb(dev->write_urb, udev,
-				      usb_sndbulkpipe(udev,
-						      endpoint->bEndpointAddress),
-				      dev->bulk_out_buffer, buffer_size,
-				      skel_write_bulk_callback, dev);
 		}
 	}
 	if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) {
-		err("Couldn't find both bulk-in and bulk-out endpoints");
+		err("Could not find both bulk-in and bulk-out endpoints");
 		goto error;
 	}
 
-	/* allow device read, write and ioctl */
-	dev->present = 1;
+	/* save our data pointer in this interface device */
+	usb_set_intfdata(interface, dev);
 
 	/* we can register the device now, as it is ready */
-	usb_set_intfdata (interface, dev);
-	retval = usb_register_dev (interface, &skel_class);
+	retval = usb_register_dev(interface, &skel_class);
 	if (retval) {
 		/* something prevented us from registering this driver */
-		err ("Not able to get a minor for this device.");
-		usb_set_intfdata (interface, NULL);
+		err("Not able to get a minor for this device.");
+		usb_set_intfdata(interface, NULL);
 		goto error;
 	}
 
-	dev->minor = interface->minor;
-
 	/* let the user know what node this device is now attached to */
-	info ("USB Skeleton device now attached to USBSkel-%d", dev->minor);
+	info("USB Skeleton device now attached to USBSkel-%d", interface->minor);
 	return 0;
 
 error:
-	skel_delete (dev);
+	if (dev)
+		kref_put(&dev->kref, skel_delete);
 	return retval;
 }
 
-
-/**
- *	skel_disconnect
- *
- *	Called by the usb core when the device is removed from the system.
- *
- *	This routine guarantees that the driver will not submit any more urbs
- *	by clearing dev->udev.  It is also supposed to terminate any currently
- *	active urbs.  Unfortunately, usb_bulk_msg(), used in skel_read(), does
- *	not provide any way to do this.  But at least we can cancel an active
- *	write.
- */
 static void skel_disconnect(struct usb_interface *interface)
 {
 	struct usb_skel *dev;
-	int minor;
+	int minor = interface->minor;
 
-	/* prevent races with open() */
-	down (&disconnect_sem);
+	/* prevent skel_open() from racing skel_disconnect() */
+	lock_kernel();
 
-	dev = usb_get_intfdata (interface);
-	usb_set_intfdata (interface, NULL);
-
-	down (&dev->sem);
-
-	minor = dev->minor;
+	dev = usb_get_intfdata(interface);
+	usb_set_intfdata(interface, NULL);
 
 	/* give back our minor */
-	usb_deregister_dev (interface, &skel_class);
+	usb_deregister_dev(interface, &skel_class);
 
-	/* terminate an ongoing write */
-	if (atomic_read (&dev->write_busy)) {
-		usb_unlink_urb (dev->write_urb);
-		wait_for_completion (&dev->write_finished);
-	}
-
-	/* prevent device read, write and ioctl */
-	dev->present = 0;
-
-	up (&dev->sem);
+	unlock_kernel();
 
-	/* if the device is opened, skel_release will clean this up */
-	if (!dev->open)
-		skel_delete (dev);
-
-	up (&disconnect_sem);
+	/* decrement our usage count */
+	kref_put(&dev->kref, skel_delete);
 
 	info("USB Skeleton #%d now disconnected", minor);
 }
 
+static struct usb_driver skel_driver = {
+	.owner =	THIS_MODULE,
+	.name =		"skeleton",
+	.probe =	skel_probe,
+	.disconnect =	skel_disconnect,
+	.id_table =	skel_table,
+};
 
-
-/**
- *	usb_skel_init
- */
 static int __init usb_skel_init(void)
 {
 	int result;
 
 	/* register this driver with the USB subsystem */
 	result = usb_register(&skel_driver);
-	if (result) {
-		err("usb_register failed. Error number %d",
-		    result);
-		return result;
-	}
+	if (result)
+		err("usb_register failed. Error number %d", result);
 
-	info(DRIVER_DESC " " DRIVER_VERSION);
-	return 0;
+	return result;
 }
 
-
-/**
- *	usb_skel_exit
- */
 static void __exit usb_skel_exit(void)
 {
 	/* deregister this driver with the USB subsystem */
 	usb_deregister(&skel_driver);
 }
 
-
 module_init (usb_skel_init);
 module_exit (usb_skel_exit);
 
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c
index 5e9bcf5a8..6a3cfbdc6 100644
--- a/drivers/video/68328fb.c
+++ b/drivers/video/68328fb.c
@@ -199,6 +199,15 @@ static int mc68x328fb_check_var(struct fb_var_screeninfo *var,
 	 */
 	switch (var->bits_per_pixel) {
 	case 1:
+		var->red.offset = 0;
+		var->red.length = 1;
+		var->green.offset = 0;
+		var->green.length = 1;
+		var->blue.offset = 0;
+		var->blue.length = 1;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
 	case 8:
 		var->red.offset = 0;
 		var->red.length = 8;
@@ -430,6 +439,13 @@ int __init mc68x328fb_setup(char *options)
 
 int __init mc68x328fb_init(void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("68328fb", &option))
+		return -ENODEV;
+	mc68x328fb_setup(option);
+#endif
 	/*
 	 *  initialize the default mode from the LCD controller registers
 	 */
@@ -452,8 +468,12 @@ int __init mc68x328fb_init(void)
 		get_line_length(mc68x328fb_default.xres_virtual, mc68x328fb_default.bits_per_pixel);
 	fb_info.fix.visual = (mc68x328fb_default.bits_per_pixel) == 1 ?
 		MC68X328FB_MONO_VISUAL : FB_VISUAL_PSEUDOCOLOR;
+	if (fb_info.var.bits_per_pixel == 1) {
+		fb_info.var.red.length = fb_info.var.green.length = fb_info.var.blue.length = 1;
+		fb_info.var.red.offset = fb_info.var.green.offset = fb_info.var.blue.offset = 0;
+	}
 	fb_info.pseudo_palette = &mc68x328fb_pseudo_palette;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 
 	fb_alloc_cmap(&fb_info.cmap, 256, 0);
 
@@ -471,6 +491,8 @@ int __init mc68x328fb_init(void)
 	return 0;
 }
 
+module_init(mc68x328fb_init);
+
 #ifdef MODULE
 
 static void __exit mc68x328fb_cleanup(void)
@@ -478,7 +500,6 @@ static void __exit mc68x328fb_cleanup(void)
 	unregister_framebuffer(&fb_info);
 }
 
-module_init(mc68x328fb_init);
 module_exit(mc68x328fb_cleanup);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 798ba0032..ab23abe01 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -38,6 +38,17 @@ config FB
 	  (e.g. an accelerated X server) and that are not frame buffer
 	  device-aware may cause unexpected results. If unsure, say N.
 
+config FB_MODE_HELPERS
+        bool "Enable Video Mode Handling Helpers"
+        depends on FB
+	default y
+	---help---
+	  This enables functions for handling video modes using the
+	  Generalized Timing Formula and the EDID parser. A few drivers rely
+          on this feature such as the radeonfb, rivafb, and the i810fb. If
+	  your driver does not take advantage of this feature, choosing Y will
+	  just increase the kernel size by about 5K.
+
 config FB_CIRRUS
 	tristate "Cirrus Logic support"
 	depends on FB && (ZORRO || PCI)
@@ -68,6 +79,19 @@ config FB_PM2_FIFO_DISCONNECT
 	help
 	  Support the Permedia2 FIFO disconnect feature (see CONFIG_FB_PM2).
 
+config FB_ARMCLCD
+	tristate "ARM PrimeCell PL110 support"
+	depends on FB && ARM && ARM_AMBA
+	help
+	  This framebuffer device driver is for the ARM PrimeCell PL110
+	  Colour LCD controller.  ARM PrimeCells provide the building
+	  blocks for System on a Chip devices.
+
+	  If you want to compile this as a module (=code which can be
+	  inserted into and removed from the running kernel), say M
+	  here and read <file:Documentation/modules.txt>.  The module
+	  will be called amba-clcd.
+
 config FB_ACORN
 	bool "Acorn VIDC support"
 	depends on FB && ARM && ARCH_ACORN
@@ -392,40 +416,21 @@ config FB_PVR2
 	  (<file:drivers/video/pvr2fb.c>). Please see the file
 	  <file:Documentation/fb/pvr2fb.txt>.
 
-config FB_E1355
+config FB_EPSON1355
 	bool "Epson 1355 framebuffer support"
-	depends on FB && SUPERH
+	depends on FB && (SUPERH || ARCH_CEIVA)
 	help
 	  Build in support for the SED1355 Epson Research Embedded RAMDAC
 	  LCD/CRT Controller (since redesignated as the S1D13505) as a
 	  framebuffer.  Product specs at
 	  <http://www.erd.epson.com/vdc/html/products.htm>.
 
-config E1355_REG_BASE
-	hex "Register Base Address"
-	depends on FB_E1355
-	default "a8000000"
-	help
-	  Epson SED1355/S1D13505 LCD/CRT controller register base address.
-	  See the manuals at
-	  <http://www.erd.epson.com/vdc/html/contents/S1D13505.htm> for
-	  discussion.
-
-config E1355_FB_BASE
-	hex "Framebuffer Base Address"
-	depends on FB_E1355
-	default "a8200000"
-	help
-	  Epson SED1355/S1D13505 LCD/CRT controller memory base address.  See
-	  the manuals at
-	  <http://www.erd.epson.com/vdc/html/contents/S1D13505.htm> for
-	  discussion.
-
 config FB_RIVA
 	tristate "nVidia Riva support"
 	depends on FB && PCI
 	select I2C_ALGOBIT if FB_RIVA_I2C
 	select I2C if FB_RIVA_I2C
+	select FB_MODE_HELPERS
 	help
 	  This driver supports graphics boards with the nVidia Riva/Geforce
 	  chips.
@@ -457,7 +462,10 @@ config FB_RIVA_DEBUG
 
 config FB_I810
 	tristate "Intel 810/815 support (EXPERIMENTAL)"
-	depends on FB && AGP && AGP_INTEL && EXPERIMENTAL && PCI	
+	depends on FB && EXPERIMENTAL && PCI && X86 && !X86_64
+	select AGP
+	select AGP_INTEL
+	select FB_MODE_HELPERS
 	help
 	  This driver supports the on-board graphics built in to the Intel 810 
           and 815 chipsets.  Say Y if you have and plan to use such a board.
@@ -661,6 +669,7 @@ config FB_RADEON
 	depends on FB && PCI
 	select I2C_ALGOBIT if FB_RADEON_I2C
 	select I2C if FB_RADEON_I2C
+	select FB_MODE_HELPERS
 	help
 	  Choose this option if you want to use an ATI Radeon graphics card as
 	  a framebuffer device.  There are both PCI and AGP versions.  You
@@ -766,6 +775,7 @@ config FB_SIS_315
 config FB_NEOMAGIC
 	tristate "NeoMagic display support"
 	depends on FB && PCI
+	select FB_MODE_HELPERS
 	help
 	  This driver supports notebooks with NeoMagic PCI chips.
 	  Say Y if you have such a graphics card. 
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 52e37a0fc..b88f69ae1 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -13,80 +13,88 @@ ifeq ($(CONFIG_FB),y)
 obj-$(CONFIG_PPC)                 += macmodes.o
 endif
 
-obj-$(CONFIG_FB_ACORN)            += acornfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+# Hardware specific drivers go first
+obj-$(CONFIG_FB_RETINAZ3)         += retz3fb.o
 obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p.o
+obj-$(CONFIG_FB_CLPS711X)         += clps711xfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_CYBER)            += cyberfb.o
+obj-$(CONFIG_FB_CYBER2000)        += cyber2000fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_PM2)              += pm2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_PM3)		  += pm3fb.o
-obj-$(CONFIG_FB_APOLLO)           += dnfb.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_Q40)              += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_ATARI)            += atafb.o
-obj-$(CONFIG_FB_68328)            += 68328fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+
+obj-$(CONFIG_FB_MATROX)		  += matrox/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_RIVA)		  += riva/ cfbimgblt.o vgastate.o
+obj-$(CONFIG_FB_ATY)		  += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
+obj-$(CONFIG_FB_ATY128)		  += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
+obj-$(CONFIG_FB_RADEON)		  += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
+obj-$(CONFIG_FB_SIS)		  += sis/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
+obj-$(CONFIG_FB_KYRO)             += kyro/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+
+obj-$(CONFIG_FB_I810)             += cfbcopyarea.o cfbfillrect.o cfbimgblt.o \
+				     vgastate.o
 obj-$(CONFIG_FB_RADEON_OLD)	  += radeonfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_NEOMAGIC)         += neofb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o vgastate.o
-obj-$(CONFIG_FB_IGA)              += igafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_VIRGE)            += virgefb.o
+obj-$(CONFIG_FB_3DFX)             += tdfxfb.o cfbimgblt.o
+ifneq ($(CONFIG_FB_3DFX_ACCEL),y)
+obj-$(CONFIG_FB_3DFX)             += cfbfillrect.o cfbcopyarea.o
+endif
 obj-$(CONFIG_FB_CONTROL)          += controlfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_PLATINUM)         += platinumfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_VALKYRIE)         += valkyriefb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_CT65550)          += chipsfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_CLPS711X)         += clps711xfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_CYBER)            += cyberfb.o
-obj-$(CONFIG_FB_CYBER2000)        += cyber2000fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_GBE)              += gbefb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_SGIVW)            += sgivwfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_3DFX)             += tdfxfb.o cfbimgblt.o
-obj-$(CONFIG_FB_MAC)              += macfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o 
-obj-$(CONFIG_FB_HP300)            += hpfb.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_OF)               += offb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o
 obj-$(CONFIG_FB_IMSTT)            += imsttfb.o cfbimgblt.o
-obj-$(CONFIG_FB_RETINAZ3)         += retz3fb.o
-obj-$(CONFIG_FB_CIRRUS)		  += cirrusfb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o
-obj-$(CONFIG_FB_TRIDENT)	  += tridentfb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o
 obj-$(CONFIG_FB_S3TRIO)           += S3triofb.o
-obj-$(CONFIG_FB_TGA)              += tgafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o 
-obj-$(CONFIG_FB_VESA)             += vesafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o 
-obj-$(CONFIG_FB_VGA16)            += vga16fb.o cfbfillrect.o cfbcopyarea.o \
-	                             cfbimgblt.o vgastate.o 
-obj-$(CONFIG_FB_VIRGE)            += virgefb.o
-obj-$(CONFIG_FB_G364)             += g364fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_FM2)              += fm2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_TRIDENT)	  += tridentfb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o
 obj-$(CONFIG_FB_STI)              += stifb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_PMAG_BA)          += pmag-ba-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_PMAGB_B)          += pmagb-b-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_MAXINE)           += maxinefb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_TX3912)           += tx3912fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-
-obj-$(CONFIG_FB_MATROX)		  += matrox/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_RIVA)		  += riva/ cfbimgblt.o vgastate.o 
-obj-$(CONFIG_FB_SIS)		  += sis/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_ATY)		  += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_ATY128)		  += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_RADEON)		  += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_I810)             += i810/ cfbfillrect.o cfbcopyarea.o \
-	                             cfbimgblt.o vgastate.o
-
-obj-$(CONFIG_FB_SUN3)             += sun3fb.o
+obj-$(CONFIG_FB_FFB)              += ffb.o sbuslib.o cfbimgblt.o cfbcopyarea.o
+obj-$(CONFIG_FB_CG6)              += cg6.o sbuslib.o cfbimgblt.o cfbcopyarea.o
+obj-$(CONFIG_FB_CG3)              += cg3.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
+				     cfbfillrect.o
+obj-$(CONFIG_FB_BW2)              += bw2.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
+				     cfbfillrect.o
+obj-$(CONFIG_FB_CG14)             += cg14.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
+				     cfbfillrect.o
+obj-$(CONFIG_FB_P9100)            += p9100.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
+				     cfbfillrect.o
+obj-$(CONFIG_FB_TCX)              += tcx.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
+				     cfbfillrect.o
+obj-$(CONFIG_FB_LEO)              += leo.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
+				     cfbfillrect.o
+obj-$(CONFIG_FB_SGIVW)            += sgivwfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_ACORN)            += acornfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_ATARI)            += atafb.o
+obj-$(CONFIG_FB_MAC)              += macfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_HGA)              += hgafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o 
+obj-$(CONFIG_FB_IGA)              += igafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_APOLLO)           += dnfb.o cfbfillrect.o cfbimgblt.o
+obj-$(CONFIG_FB_Q40)              += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_TGA)              += tgafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_HP300)            += hpfb.o cfbfillrect.o cfbimgblt.o
+obj-$(CONFIG_FB_G364)             += g364fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_SA1100)           += sa1100fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_VIRTUAL)          += vfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o 
+obj-$(CONFIG_FB_SUN3)             += sun3fb.o
 obj-$(CONFIG_FB_HIT)              += hitfb.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_E1355)            += epson1355fb.o
+obj-$(CONFIG_FB_TX3912)           += tx3912fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_EPSON1355)	  += epson1355fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_PVR2)             += pvr2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_KYRO)             += kyro/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_PMAG_BA)          += pmag-ba-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_PMAGB_B)          += pmagb-b-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_MAXINE)           += maxinefb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 obj-$(CONFIG_FB_VOODOO1)          += sstfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_ARMCLCD)	  += amba-clcd.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_68328)            += 68328fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_GBE)              += gbefb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_CIRRUS)		  += cirrusfb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o
 obj-$(CONFIG_FB_ASILIANT)	  += asiliantfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_PXA)		  += pxafb.o cfbimgblt.o cfbcopyarea.o cfbfillrect.o
+
+# Platform or fallback drivers go here
+obj-$(CONFIG_FB_VESA)             += vesafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_VGA16)            += vga16fb.o cfbfillrect.o cfbcopyarea.o \
+	                             cfbimgblt.o vgastate.o
+obj-$(CONFIG_FB_OF)               += offb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o
 
-obj-$(CONFIG_FB_FFB)               += ffb.o sbuslib.o cfbimgblt.o cfbcopyarea.o
-obj-$(CONFIG_FB_CG6)               += cg6.o sbuslib.o cfbimgblt.o cfbcopyarea.o
-obj-$(CONFIG_FB_CG3)               += cg3.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
-				      cfbfillrect.o
-obj-$(CONFIG_FB_BW2)               += bw2.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
-				      cfbfillrect.o
-obj-$(CONFIG_FB_CG14)              += cg14.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
-				      cfbfillrect.o
-obj-$(CONFIG_FB_P9100)             += p9100.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
-				      cfbfillrect.o
-obj-$(CONFIG_FB_TCX)               += tcx.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
-				      cfbfillrect.o
-obj-$(CONFIG_FB_LEO)               += leo.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
-				      cfbfillrect.o
-obj-$(CONFIG_FB_PXA)		   += pxafb.o cfbimgblt.o cfbcopyarea.o cfbfillrect.o
+# the test framebuffer is last
+obj-$(CONFIG_FB_VIRTUAL)          += vfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index 0c3aa4a7f..f7bfbc722 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -1010,7 +1010,7 @@ static void __init acornfb_init_fbinfo(void)
 	first = 0;
 
 	fb_info.fbops		= &acornfb_ops;
-	fb_info.flags		= FBINFO_FLAG_DEFAULT;
+	fb_info.flags		= FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 	fb_info.pseudo_palette	= current_par.pseudo_palette;
 
 	strcpy(fb_info.fix.id, "Acorn");
@@ -1291,6 +1291,11 @@ acornfb_init(void)
 	unsigned long size;
 	u_int h_sync, v_sync;
 	int rc, i;
+	char *option = NULL;
+
+	if (fb_get_options("acornfb", &option))
+		return -ENODEV;
+	acornfb_setup(option);
 
 	acornfb_init_fbinfo();
 
@@ -1456,6 +1461,8 @@ acornfb_init(void)
 	return 0;
 }
 
+module_init(acornfb_init);
+
 MODULE_AUTHOR("Russell King");
 MODULE_DESCRIPTION("VIDC 1/1a/20 framebuffer driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index 95ea71c9b..baa4fa06b 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -1307,6 +1307,8 @@ static int amifb_set_par(struct fb_info *info)
 		info->fix.ywrapstep = 1;
 		info->fix.xpanstep = 0;
 		info->fix.ypanstep = 0;
+		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP |
+		    FBINFO_READS_FAST; /* override SCROLL_REDRAW */
 	} else {
 		info->fix.ywrapstep = 0;
 		if (par->vmode & FB_VMODE_SMOOTH_XPAN)
@@ -1314,6 +1316,7 @@ static int amifb_set_par(struct fb_info *info)
 		else
 			info->fix.xpanstep = 16<<maxfmode;
 		info->fix.ypanstep = 1;
+		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 	}
 	return 0;
 }
@@ -2254,6 +2257,13 @@ int __init amifb_init(void)
 	u_long chipptr;
 	u_int defmode;
 
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("amifb", &option))
+		return -ENODEV;
+	amifb_setup(option);
+#endif
 	if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO))
 		return -ENXIO;
 
@@ -2382,7 +2392,7 @@ default_chipset:
 
 	fb_info.fbops = &amifb_ops;
 	fb_info.par = &currentpar;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	fb_info.flags = FBINFO_DEFAULT;
 
 	if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb,
 			  NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
@@ -3811,14 +3821,11 @@ static void ami_rebuild_copper(void)
 }
 
 
+module_init(amifb_init);
+
 #ifdef MODULE
 MODULE_LICENSE("GPL");
 
-int init_module(void)
-{
-	return amifb_init();
-}
-
 void cleanup_module(void)
 {
 	unregister_framebuffer(&fb_info);
diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c
index 1563b0d27..bda3ed9ba 100644
--- a/drivers/video/asiliantfb.c
+++ b/drivers/video/asiliantfb.c
@@ -524,7 +524,7 @@ static void __init init_asiliant(struct fb_info *p, unsigned long addr)
 	p->fix.smem_start	= addr;
 	p->var			= asiliantfb_var;
 	p->fbops		= &asiliantfb_ops;
-	p->flags		= FBINFO_FLAG_DEFAULT;
+	p->flags		= FBINFO_DEFAULT;
 
 	fb_alloc_cmap(&p->cmap, 256, 0);
 
@@ -609,9 +609,14 @@ static struct pci_driver asiliantfb_driver = {
 
 int __init asiliantfb_init(void)
 {
+	if (fb_get_options("asiliantfb", NULL))
+		return -ENODEV;
+
 	return pci_module_init(&asiliantfb_driver);
 }
 
+module_init(asiliantfb_init);
+
 static void __exit asiliantfb_exit(void)
 {
 	pci_unregister_driver(&asiliantfb_driver);
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index 1c7bcd80f..f2d82d005 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -2439,6 +2439,14 @@ static int aty128_pci_resume(struct pci_dev *pdev)
 
 int __init aty128fb_init(void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("aty128fb", &option))
+		return -ENODEV;
+	aty128fb_setup(option);
+#endif
+
 	return pci_module_init(&aty128fb_driver);
 }
 
@@ -2447,8 +2455,9 @@ static void __exit aty128fb_exit(void)
 	pci_unregister_driver(&aty128fb_driver);
 }
 
-#ifdef MODULE
 module_init(aty128fb_init);
+
+#ifdef MODULE
 module_exit(aty128fb_exit);
 
 MODULE_AUTHOR("(c)1999-2003 Brad Douglas <brad@neruo.com>");
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 37177bece..2d753a150 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -1902,7 +1902,7 @@ static int __init aty_init(struct fb_info *info, const char *name)
 	return 1;
 }
 
-int __init atyfb_init(void)
+int __init atyfb_do_init(void)
 {
 #if defined(CONFIG_PCI)
 	unsigned long addr, res_start, res_size;
@@ -1917,12 +1917,14 @@ int __init atyfb_init(void)
 	char prop[128];
 	int node, len, j;
 	u32 mem, chip_id;
+#else
+	u16 tmp;
+#endif
 
+#ifdef __sparc__
 	/* Do not attach when we have a serial console. */
 	if (!con_is_present())
 		return -ENXIO;
-#else
-	u16 tmp;
 #endif
 
 	while ((pdev =
@@ -2377,6 +2379,19 @@ int __init atyfb_init(void)
 	return 0;
 }
 
+int __init atyfb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("atyfb", &option))
+		return -ENODEV;
+	atyfb_setup(option);
+#endif
+	return atyfb_do_init();
+}
+
+
 #ifndef MODULE
 int __init atyfb_setup(char *options)
 {
@@ -2445,6 +2460,7 @@ int __init atyfb_setup(char *options)
 	}
 	return 0;
 }
+module_init(atyfb_init);
 #endif				/* !MODULE */
 
 #ifdef CONFIG_ATARI
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index bd3b24caa..325b83b30 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -282,7 +282,7 @@ static void __devexit radeon_unmap_ROM(struct radeonfb_info *rinfo, struct pci_d
 
 static int __devinit radeon_map_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev)
 {
-	void *rom;
+	void __iomem *rom;
 	struct resource *r;
 	u16 dptr;
 	u8 rom_type;
@@ -395,13 +395,13 @@ static int  __devinit radeon_find_mem_vbios(struct radeonfb_info *rinfo)
 	 * if we end up having conflicts
 	 */
         u32  segstart;
-        unsigned char *rom_base = NULL;
+	void __iomem *rom_base = NULL;
                                                 
         for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
-                rom_base = (char *)ioremap(segstart, 0x10000);
+                rom_base = ioremap(segstart, 0x10000);
 		if (rom_base == NULL)
 			return -ENOMEM;
-                if ((*rom_base == 0x55) && (((*(rom_base + 1)) & 0xff) == 0xaa))
+                if (readb(rom_base) == 0x55 && readb(rom_base + 1) == 0xaa)
 	                break;
                 iounmap(rom_base);
 		rom_base = NULL;
@@ -1702,68 +1702,6 @@ int radeonfb_set_par(struct fb_info *info)
 }
 
 
-
-static ssize_t radeonfb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
-{
-	unsigned long p = *ppos;
-	struct inode *inode = file->f_dentry->d_inode;
-	int fbidx = iminor(inode);
-	struct fb_info *info = registered_fb[fbidx];
-	struct radeonfb_info *rinfo = info->par;
-	
-	if (p >= rinfo->mapped_vram)
-	    return 0;
-	if (count >= rinfo->mapped_vram)
-	    count = rinfo->mapped_vram;
-	if (count + p > rinfo->mapped_vram)
-		count = rinfo->mapped_vram - p;
-	radeonfb_sync(info);
-	if (count) {
-	    char *base_addr;
-
-	    base_addr = info->screen_base;
-	    count -= copy_to_user(buf, base_addr+p, count);
-	    if (!count)
-		return -EFAULT;
-	    *ppos += count;
-	}
-	return count;
-}
-
-static ssize_t radeonfb_write(struct file *file, const char __user *buf, size_t count,
-			      loff_t *ppos)
-{
-	unsigned long p = *ppos;
-	struct inode *inode = file->f_dentry->d_inode;
-	int fbidx = iminor(inode);
-	struct fb_info *info = registered_fb[fbidx];
-	struct radeonfb_info *rinfo = info->par;
-	int err;
-
-	if (p > rinfo->mapped_vram)
-	    return -ENOSPC;
-	if (count >= rinfo->mapped_vram)
-	    count = rinfo->mapped_vram;
-	err = 0;
-	if (count + p > rinfo->mapped_vram) {
-	    count = rinfo->mapped_vram - p;
-	    err = -ENOSPC;
-	}
-	radeonfb_sync(info);
-	if (count) {
-	    char *base_addr;
-
-	    base_addr = info->screen_base;
-	    count -= copy_from_user(base_addr+p, buf, count);
-	    *ppos += count;
-	    err = -EFAULT;
-	}
-	if (count)
-		return count;
-	return err;
-}
-
-
 static struct fb_ops radeonfb_ops = {
 	.owner			= THIS_MODULE,
 	.fb_check_var		= radeonfb_check_var,
@@ -1776,8 +1714,6 @@ static struct fb_ops radeonfb_ops = {
 	.fb_fillrect		= radeonfb_fillrect,
 	.fb_copyarea		= radeonfb_copyarea,
 	.fb_imageblit		= radeonfb_imageblit,
-	.fb_read		= radeonfb_read,
-	.fb_write		= radeonfb_write,
 	.fb_cursor		= soft_cursor,
 };
 
@@ -1795,8 +1731,8 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo)
 		    | FBINFO_HWACCEL_XPAN
 		    | FBINFO_HWACCEL_YPAN;
 	info->fbops = &radeonfb_ops;
-	info->screen_base = (char *)rinfo->fb_base;
-
+	info->screen_base = rinfo->fb_base;
+	info->screen_size = rinfo->mapped_vram;
 	/* Fill fix common fields */
 	strlcpy(info->fix.id, rinfo->name, sizeof(info->fix.id));
         info->fix.smem_start = rinfo->fb_base_phys;
@@ -1932,7 +1868,7 @@ static int radeon_set_backlight_level(int level, void *data)
 #undef SET_MC_FB_FROM_APERTURE
 static void fixup_memory_mappings(struct radeonfb_info *rinfo)
 {
-	u32 save_crtc_gen_cntl, save_crtc2_gen_cntl;
+	u32 save_crtc_gen_cntl, save_crtc2_gen_cntl = 0;
 	u32 save_crtc_ext_cntl;
 	u32 aper_base, aper_size;
 	u32 agp_base;
@@ -2069,19 +2005,22 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
 	struct fb_info *info;
 	struct radeonfb_info *rinfo;
 	u32 tmp;
+	int ret;
 
 	RTRACE("radeonfb_pci_register BEGIN\n");
 	
 	/* Enable device in PCI config */
-	if (pci_enable_device(pdev) != 0) {
+	ret = pci_enable_device(pdev);
+	if (ret < 0) {
 		printk(KERN_ERR "radeonfb: Cannot enable PCI device\n");
-		return -ENODEV;
+		goto err_out;
 	}
 
 	info = framebuffer_alloc(sizeof(struct radeonfb_info), &pdev->dev);
 	if (!info) {
 		printk (KERN_ERR "radeonfb: could not allocate memory\n");
-		return -ENODEV;
+		ret = -ENOMEM;
+		goto err_disable;
 	}
 	rinfo = info->par;
 	rinfo->info = info;	
@@ -2106,23 +2045,19 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
 	rinfo->mmio_base_phys = pci_resource_start (pdev, 2);
 
 	/* request the mem regions */
-	if (!request_mem_region (rinfo->fb_base_phys,
-				 pci_resource_len(pdev, 0), "radeonfb")) {
-		printk (KERN_ERR "radeonfb: cannot reserve FB region\n");
-		goto free_rinfo;
-	}
-
-	if (!request_mem_region (rinfo->mmio_base_phys,
-				 pci_resource_len(pdev, 2), "radeonfb")) {
-		printk (KERN_ERR "radeonfb: cannot reserve MMIO region\n");
-		goto release_fb;
+	ret = pci_request_regions(pdev, "radeonfb");
+	if (ret < 0) {
+		printk( KERN_ERR "radeonfb: cannot reserve PCI regions."
+			"  Someone already got them?\n");
+		goto err_release_fb;
 	}
 
 	/* map the regions */
-	rinfo->mmio_base = (unsigned long) ioremap (rinfo->mmio_base_phys, RADEON_REGSIZE);
+	rinfo->mmio_base = ioremap(rinfo->mmio_base_phys, RADEON_REGSIZE);
 	if (!rinfo->mmio_base) {
-		printk (KERN_ERR "radeonfb: cannot map MMIO\n");
-		goto release_mmio;
+		printk(KERN_ERR "radeonfb: cannot map MMIO\n");
+		ret = -EIO;
+		goto err_release_pci;
 	}
 
 	/* On PPC, the firmware sets up a memory mapping that tends
@@ -2226,33 +2161,24 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
 
 	RTRACE("radeonfb: probed %s %ldk videoram\n", (rinfo->ram_type), (rinfo->video_ram/1024));
 
-	rinfo->mapped_vram = MAX_MAPPED_VRAM;
-	if (rinfo->video_ram < rinfo->mapped_vram)
-		rinfo->mapped_vram = rinfo->video_ram;
-	for (;;) {
-		rinfo->fb_base = (unsigned long) ioremap (rinfo->fb_base_phys,
-							  rinfo->mapped_vram);
-		if (rinfo->fb_base == 0 && rinfo->mapped_vram > MIN_MAPPED_VRAM) {
-			rinfo->mapped_vram /= 2;
-			continue;
-		}
-		memset_io(rinfo->fb_base, 0, rinfo->mapped_vram);
-		break;
-	}
+	rinfo->mapped_vram = min_t(unsigned long, MAX_MAPPED_VRAM, rinfo->video_ram);
 
-	if (!rinfo->fb_base) {
+	do {
+		rinfo->fb_base = ioremap (rinfo->fb_base_phys,
+					  rinfo->mapped_vram);
+	} while (   rinfo->fb_base == 0 &&
+		  ((rinfo->mapped_vram /=2) >= MIN_MAPPED_VRAM) );
+
+	if (rinfo->fb_base)
+		memset_io(rinfo->fb_base, 0, rinfo->mapped_vram);
+	else {
 		printk (KERN_ERR "radeonfb: cannot map FB\n");
-		goto unmap_rom;
+		ret = -EIO;
+		goto err_unmap_rom;
 	}
 
 	RTRACE("radeonfb: mapped %ldk videoram\n", rinfo->mapped_vram/1024);
 
-
-	/* Argh. Scary arch !!! */
-#ifdef CONFIG_PPC64
-	rinfo->fb_base = IO_TOKEN_TO_ADDR(rinfo->fb_base);
-#endif
-
 	/*
 	 * Check for required workaround for PLL accesses
 	 */
@@ -2330,9 +2256,10 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
 		printk("radeonfb: Power Management enabled for Mobility chipsets\n");
 	}
 
-	if (register_framebuffer(info) < 0) {
+	ret = register_framebuffer(info);
+	if (ret < 0) {
 		printk (KERN_ERR "radeonfb: could not register framebuffer\n");
-		goto unmap_fb;
+		goto err_unmap_fb;
 	}
 
 #ifdef CONFIG_MTRR
@@ -2358,30 +2285,30 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
 	RTRACE("radeonfb_pci_register END\n");
 
 	return 0;
-unmap_fb:
-	iounmap ((void*)rinfo->fb_base);
-unmap_rom:	
+err_unmap_fb:
+	iounmap(rinfo->fb_base);
+err_unmap_rom:
 	if (rinfo->mon1_EDID)
 	    kfree(rinfo->mon1_EDID);
 	if (rinfo->mon2_EDID)
 	    kfree(rinfo->mon2_EDID);
 	if (rinfo->mon1_modedb)
 		fb_destroy_modedb(rinfo->mon1_modedb);
+	fb_dealloc_cmap(&info->cmap);
 #ifdef CONFIG_FB_RADEON_I2C
 	radeon_delete_i2c_busses(rinfo);
 #endif
 	if (rinfo->bios_seg)
 		radeon_unmap_ROM(rinfo, pdev);
-	iounmap ((void*)rinfo->mmio_base);
-release_mmio:
-	release_mem_region (rinfo->mmio_base_phys,
-			    pci_resource_len(pdev, 2));
-release_fb:	
-	release_mem_region (rinfo->fb_base_phys,
-			    pci_resource_len(pdev, 0));
-free_rinfo:	
+	iounmap(rinfo->mmio_base);
+err_release_pci:
+	pci_release_regions(pdev);
+err_release_fb:
 	framebuffer_release(info);
-	return -ENODEV;
+err_disable:
+	pci_disable_device(pdev);
+err_out:
+	return ret;
 }
 
 
@@ -2410,13 +2337,10 @@ static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
 
         unregister_framebuffer(info);
 
-        iounmap ((void*)rinfo->mmio_base);
-        iounmap ((void*)rinfo->fb_base);
+        iounmap(rinfo->mmio_base);
+        iounmap(rinfo->fb_base);
  
-	release_mem_region (rinfo->mmio_base_phys,
-			    pci_resource_len(pdev, 2));
-	release_mem_region (rinfo->fb_base_phys,
-			    pci_resource_len(pdev, 0));
+ 	pci_release_regions(pdev);
 
 	if (rinfo->mon1_EDID)
 		kfree(rinfo->mon1_EDID);
@@ -2427,7 +2351,9 @@ static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
 #ifdef CONFIG_FB_RADEON_I2C
 	radeon_delete_i2c_busses(rinfo);
 #endif        
+	fb_dealloc_cmap(&info->cmap);
         framebuffer_release(info);
+	pci_disable_device(pdev);
 }
 
 
@@ -2442,9 +2368,17 @@ static struct pci_driver radeonfb_driver = {
 #endif /* CONFIG_PM */
 };
 
+int __init radeonfb_setup (char *options);
 
 int __init radeonfb_init (void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("radeonfb", &option))
+		return -ENODEV;
+	radeonfb_setup(option);
+#endif
 	return pci_module_init (&radeonfb_driver);
 }
 
@@ -2489,9 +2423,9 @@ int __init radeonfb_setup (char *options)
 	return 0;
 }
 
+module_init(radeonfb_init);
 
 #ifdef MODULE
-module_init(radeonfb_init);
 module_exit(radeonfb_exit);
 #endif
 
diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c
index 94ff455d0..e6c01642c 100644
--- a/drivers/video/aty/radeon_monitor.c
+++ b/drivers/video/aty/radeon_monitor.c
@@ -55,7 +55,7 @@ static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_
 	u8 *pedid = NULL;
 	u8 *pmt = NULL;
 	u8 *tmp;
-        int i, mt;  
+        int i, mt = MT_NONE;  
 	
 	RTRACE("analyzing OF properties...\n");
 	pmt = (u8 *)get_property(dp, "display-type", NULL);
@@ -72,7 +72,9 @@ static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_
 	else if (strcmp(pmt, "NONE")) {
 		printk(KERN_WARNING "radeonfb: Unknown OF display-type: %s\n", pmt);
 		return MT_NONE;
-	}
+	} else
+		return MT_NONE;
+
 	for (i = 0; propnames[i] != NULL; ++i) {
 		pedid = (u8 *)get_property(dp, propnames[i], NULL);
 		if (pedid != NULL)
@@ -645,15 +647,23 @@ static void radeon_fixup_panel_info(struct radeonfb_info *rinfo)
 		rinfo->panel_info.fbk_divider = 0xad;
 		rinfo->panel_info.use_bios_dividers = 1;
 	}
+	/* Aluminium PowerBook 15" */
+	if (machine_is_compatible("PowerBook5,4")) {
+		rinfo->panel_info.ref_divider = rinfo->pll.ref_div;
+		rinfo->panel_info.post_divider = 0x2;
+		rinfo->panel_info.fbk_divider = 0x8e;
+		rinfo->panel_info.use_bios_dividers = 1;
+	}
 	/* Aluminium PowerBook 17" */
-	if (machine_is_compatible("PowerBook5,3")) {
+	if (machine_is_compatible("PowerBook5,3") ||
+	    machine_is_compatible("PowerBook5,5")) {
 		rinfo->panel_info.ref_divider = rinfo->pll.ref_div;
 		rinfo->panel_info.post_divider = 0x4;
 		rinfo->panel_info.fbk_divider = 0x80;
 		rinfo->panel_info.use_bios_dividers = 1;
 	}
 	/* iBook G4 */
-        if (machine_is_compatible("PowerBook6,3") |
+        if (machine_is_compatible("PowerBook6,3") ||
             machine_is_compatible("PowerBook6,5")) {
 		rinfo->panel_info.ref_divider = rinfo->pll.ref_div;
 		rinfo->panel_info.post_divider = 0x6;
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index 87223df80..447eb5841 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -262,14 +262,14 @@ struct radeonfb_info {
 	unsigned long		mmio_base_phys;
 	unsigned long		fb_base_phys;
 
-	unsigned long		mmio_base;
-	unsigned long		fb_base;
+	void __iomem		*mmio_base;
+	void __iomem		*fb_base;
 
-	unsigned long 		fb_local_base;
+	unsigned long		fb_local_base;
 
 	struct pci_dev		*pdev;
 
-	u8			*bios_seg;
+	void __iomem		*bios_seg;
 	int			fp_bios_start;
 
 	u32			pseudo_palette[17];
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index b3ab23b07..65b65addf 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -323,7 +323,7 @@ static void bw2_init_one(struct sbus_dev *sdev)
 		resp = &res;
 		all->info.var.xres = all->info.var.xres_virtual = 1152;
 		all->info.var.yres = all->info.var.yres_virtual = 900;
-		all->info.bits_per_pixel = 1;
+		all->info.var.bits_per_pixel = 1;
 		linebytes = 1152 / 8;
 	} else
 #else
@@ -337,6 +337,10 @@ static void bw2_init_one(struct sbus_dev *sdev)
 					       all->info.var.xres);
 	}
 #endif
+	all->info.var.red.length = all->info.var.green.length =
+		all->info.var.blue.length = all->info.var.bits_per_pixel;
+	all->info.var.red.offset = all->info.var.green.offset =
+		all->info.var.blue.offset = 0;
 
 	all->par.regs = (struct bw2_regs *)
 		sbus_ioremap(resp, BWTWO_REGISTER_OFFSET,
@@ -347,7 +351,7 @@ static void bw2_init_one(struct sbus_dev *sdev)
 
 	all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
 
-	all->info.flags = FBINFO_FLAG_DEFAULT;
+	all->info.flags = FBINFO_DEFAULT;
 	all->info.fbops = &bw2_ops;
 #if defined(CONFIG_SPARC32)
 	if (sdev)
@@ -382,6 +386,9 @@ int __init bw2_init(void)
 	struct sbus_bus *sbus;
 	struct sbus_dev *sdev;
 
+	if (fb_get_options("bw2fb", &option))
+		return -ENODEV;
+
 #ifdef CONFIG_SUN4
 	bw2_init_one(NULL);
 #endif
@@ -412,8 +419,9 @@ bw2_setup(char *arg)
 	return 0;
 }
 
-#ifdef MODULE
 module_init(bw2_init);
+
+#ifdef MODULE
 module_exit(bw2_exit);
 #endif
 
diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c
index 9c32d2b40..b4b286a4c 100644
--- a/drivers/video/cfbcopyarea.c
+++ b/drivers/video/cfbcopyarea.c
@@ -43,8 +43,9 @@
 #define BYTES_PER_LONG 8
 #endif
 
-static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
-		   int src_idx, unsigned long n)
+static void bitcpy(unsigned long __iomem *dst, int dst_idx,
+		   const unsigned long __iomem *src, int src_idx,
+		   unsigned long n)
 {
 	unsigned long first, last;
 	int shift = dst_idx-src_idx, left, right;
@@ -185,8 +186,8 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
 	}
 }
 
-static void bitcpy_rev(unsigned long *dst, int dst_idx,
-		       const unsigned long *src, int src_idx, unsigned long n)
+static void bitcpy_rev(unsigned long __iomem *dst, int dst_idx,
+		       const unsigned long __iomem *src, int src_idx, unsigned long n)
 {
 	unsigned long first, last;
 	int shift = dst_idx-src_idx, left, right;
@@ -344,7 +345,7 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
 	int x2, y2, old_dx, old_dy, vxres, vyres;
 	unsigned long next_line = p->fix.line_length;
 	int dst_idx = 0, src_idx = 0, rev_copy = 0;
-	unsigned long *dst = NULL, *src = NULL;
+	unsigned long __iomem *dst = NULL, *src = NULL;
 
 	if (p->state != FBINFO_STATE_RUNNING)
 		return;
@@ -394,7 +395,7 @@ void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
 		rev_copy = 1;
 	}
 
-	dst = src = (unsigned long *)((unsigned long)p->screen_base & 
+	dst = src = (unsigned long __iomem *)((unsigned long)p->screen_base & 
 				      ~(BYTES_PER_LONG-1));
 	dst_idx = src_idx = (unsigned long)p->screen_base & (BYTES_PER_LONG-1);
 	dst_idx += dy*next_line*8 + dx*p->var.bits_per_pixel;
diff --git a/drivers/video/cfbfillrect.c b/drivers/video/cfbfillrect.c
index 20f3acfd8..4a94bf85e 100644
--- a/drivers/video/cfbfillrect.c
+++ b/drivers/video/cfbfillrect.c
@@ -119,7 +119,7 @@ static inline unsigned long pixel_to_pat(const struct fb_info *p,
      *  Unaligned 32-bit pattern fill using 32/64-bit memory accesses
      */
 
-void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
+void bitfill32(unsigned long __iomem *dst, int dst_idx, u32 pat, u32 n)
 {
 	unsigned long val = pat;
 	unsigned long first, last;
@@ -178,7 +178,7 @@ void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
      *  used for the next 32/64-bit word
      */
 
-void bitfill(unsigned long *dst, int dst_idx, unsigned long pat, int left,
+void bitfill(unsigned long __iomem *dst, int dst_idx, unsigned long pat, int left,
 	     int right, u32 n)
 {
 	unsigned long first, last;
@@ -228,7 +228,7 @@ void bitfill(unsigned long *dst, int dst_idx, unsigned long pat, int left,
 	}
 }
 
-void bitfill32_rev(unsigned long *dst, int dst_idx, u32 pat, u32 n)
+void bitfill32_rev(unsigned long __iomem *dst, int dst_idx, u32 pat, u32 n)
 {
 	unsigned long val = pat, dat;
 	unsigned long first, last;
@@ -300,7 +300,7 @@ void bitfill32_rev(unsigned long *dst, int dst_idx, u32 pat, u32 n)
      *  used for the next 32/64-bit word
      */
 
-void bitfill_rev(unsigned long *dst, int dst_idx, unsigned long pat, int left,
+void bitfill_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat, int left,
 	     int right, u32 n)
 {
 	unsigned long first, last, dat;
@@ -364,7 +364,7 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
 	u32 bpp = p->var.bits_per_pixel;
 	unsigned long x2, y2, vxres, vyres;
 	unsigned long height, width, fg;
-	unsigned long *dst;
+	unsigned long __iomem *dst;
 	int dst_idx, left;
 
 	if (p->state != FBINFO_STATE_RUNNING)
@@ -397,7 +397,7 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
 	else
 		fg = rect->color;
 	
-	dst = (unsigned long *)((unsigned long)p->screen_base & 
+	dst = (unsigned long __iomem *)((unsigned long)p->screen_base & 
 				~(BYTES_PER_LONG-1));
 	dst_idx = ((unsigned long)p->screen_base & (BYTES_PER_LONG-1))*8;
 	dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;
@@ -407,7 +407,7 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
 		p->fbops->fb_sync(p);
 	if (!left) {
 		u32 pat = pixel_to_pat32(p, fg);
-		void (*fill_op32)(unsigned long *dst, int dst_idx, u32 pat, 
+		void (*fill_op32)(unsigned long __iomem *dst, int dst_idx, u32 pat, 
 				  u32 n) = NULL;
 		
 		switch (rect->rop) {
@@ -429,7 +429,7 @@ void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
 		unsigned long pat = pixel_to_pat(p, fg, (left-dst_idx) % bpp);
 		int right = bpp-left;
 		int r;
-		void (*fill_op)(unsigned long *dst, int dst_idx, 
+		void (*fill_op)(unsigned long __iomem *dst, int dst_idx, 
 				unsigned long pat, int left, int right, 
 				u32 n) = NULL;
 		
diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c
index 31da88e32..4c123abaa 100644
--- a/drivers/video/cfbimgblt.c
+++ b/drivers/video/cfbimgblt.c
@@ -87,21 +87,22 @@ static u32 cfb_tab32[] = {
 #endif
 
 static inline void color_imageblit(const struct fb_image *image, 
-				   struct fb_info *p, u8 *dst1, 
+				   struct fb_info *p, u8 __iomem *dst1, 
 				   u32 start_index,
 				   u32 pitch_index)
 {
 	/* Draw the penguin */
-	u32 *dst, *dst2, color = 0, val, shift;
+	u32 __iomem *dst, *dst2;
+	u32 color = 0, val, shift;
 	int i, n, bpp = p->var.bits_per_pixel;
 	u32 null_bits = 32 - bpp;
 	u32 *palette = (u32 *) p->pseudo_palette;
 	const u8 *src = image->data;
 
-	dst2 = (u32 *) dst1;
+	dst2 = (u32 __iomem *) dst1;
 	for (i = image->height; i--; ) {
 		n = image->width;
-		dst = (u32 *) dst1;
+		dst = (u32 __iomem *) dst1;
 		shift = 0;
 		val = 0;
 		
@@ -136,7 +137,7 @@ static inline void color_imageblit(const struct fb_image *image,
 		dst1 += p->fix.line_length;
 		if (pitch_index) {
 			dst2 += p->fix.line_length;
-			dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1));
+			dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1));
 
 			start_index += pitch_index;
 			start_index &= 32 - 1;
@@ -145,25 +146,26 @@ static inline void color_imageblit(const struct fb_image *image,
 }
 
 static inline void slow_imageblit(const struct fb_image *image, struct fb_info *p, 
-				  u8 *dst1, u32 fgcolor,
+				  u8 __iomem *dst1, u32 fgcolor,
 				  u32 bgcolor, 
 				  u32 start_index,
 				  u32 pitch_index)
 {
 	u32 shift, color = 0, bpp = p->var.bits_per_pixel;
-	u32 *dst, *dst2, val, pitch = p->fix.line_length;
+	u32 __iomem *dst, *dst2;
+	u32 val, pitch = p->fix.line_length;
 	u32 null_bits = 32 - bpp;
 	u32 spitch = (image->width+7)/8;
 	const u8 *src = image->data, *s;
 	u32 i, j, l;
 	
-	dst2 = (u32 *) dst1;
+	dst2 = (u32 __iomem *) dst1;
 
 	for (i = image->height; i--; ) {
 		shift = val = 0;
 		l = 8;
 		j = image->width;
-		dst = (u32 *) dst1;
+		dst = (u32 __iomem *) dst1;
 		s = src;
 
 		/* write leading bits */
@@ -201,7 +203,7 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
 		src += spitch;	
 		if (pitch_index) {
 			dst2 += pitch;
-			dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1));
+			dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1));
 			start_index += pitch_index;
 			start_index &= 32 - 1;
 		}
@@ -218,14 +220,14 @@ static inline void slow_imageblit(const struct fb_image *image, struct fb_info *
  *           beginning and end of a scanline is dword aligned
  */
 static inline void fast_imageblit(const struct fb_image *image, struct fb_info *p, 
-				  u8 *dst1, u32 fgcolor, 
+				  u8 __iomem *dst1, u32 fgcolor, 
 				  u32 bgcolor) 
 {
 	u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel;
 	u32 ppw = 32/bpp, spitch = (image->width + 7)/8;
 	u32 bit_mask, end_mask, eorx, shift;
 	const char *s = image->data, *src;
-	u32 *dst;
+	u32 __iomem *dst;
 	u32 *tab = NULL;
 	int i, j, k;
 		
@@ -253,7 +255,7 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info *
 	k = image->width/ppw;
 
 	for (i = image->height; i--; ) {
-		dst = (u32 *) dst1, shift = 8; src = s;
+		dst = (u32 __iomem *) dst1, shift = 8; src = s;
 		
 		for (j = k; j--; ) {
 			shift -= ppw;
@@ -273,7 +275,7 @@ void cfb_imageblit(struct fb_info *p, const struct fb_image *image)
 	u32 width = image->width, height = image->height; 
 	u32 dx = image->dx, dy = image->dy;
 	int x2, y2, vxres, vyres;
-	u8 *dst1;
+	u8 __iomem *dst1;
 
 	if (p->state != FBINFO_STATE_RUNNING)
 		return;
@@ -325,7 +327,7 @@ void cfb_imageblit(struct fb_info *p, const struct fb_image *image)
 		else 
 			slow_imageblit(image, p, dst1, fgcolor, bgcolor,
 					start_index, pitch_index);
-	} else if (image->depth <= bpp) 
+	} else
 		color_imageblit(image, p, dst1, start_index, pitch_index);
 }
 
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c
index e0fc4c02c..c43322b2d 100644
--- a/drivers/video/cg14.c
+++ b/drivers/video/cg14.c
@@ -550,7 +550,7 @@ static void cg14_init_one(struct sbus_dev *sdev, int node, int parent_node)
 	all->par.mode = MDI_8_PIX;
 	all->par.ramsize = (is_8mb ? 0x800000 : 0x400000);
 
-	all->info.flags = FBINFO_FLAG_DEFAULT;
+	all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 	all->info.fbops = &cg14_ops;
 	all->info.currcon = -1;
 	all->info.par = &all->par;
@@ -584,6 +584,9 @@ int __init cg14_init(void)
 	struct sbus_bus *sbus;
 	struct sbus_dev *sdev;
 
+	if (fb_get_options("cg14fb", NULL))
+		return -ENODEV;
+
 #ifdef CONFIG_SPARC32
 	{
 		int root, node;
@@ -626,8 +629,9 @@ cg14_setup(char *arg)
 	return 0;
 }
 
-#ifdef MODULE
 module_init(cg14_init);
+
+#ifdef MODULE
 module_exit(cg14_exit);
 #endif
 
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
index dd0163cc3..078394109 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/cg3.c
@@ -398,7 +398,7 @@ static void cg3_init_one(struct sbus_dev *sdev)
 		sbus_ioremap(&sdev->resource[0], CG3_REGS_OFFSET,
 			     sizeof(struct cg3_regs), "cg3 regs");
 
-	all->info.flags = FBINFO_FLAG_DEFAULT;
+	all->info.flags = FBINFO_DEFAULT;
 	all->info.fbops = &cg3_ops;
 #ifdef CONFIG_SPARC32
 	all->info.screen_base = (char *)
@@ -444,6 +444,9 @@ int __init cg3_init(void)
 	struct sbus_bus *sbus;
 	struct sbus_dev *sdev;
 
+	if (fb_get_options("cg3fb", NULL))
+		return -ENODEV;
+
 	for_all_sbusdev(sdev, sbus) {
 		if (!strcmp(sdev->prom_name, "cgthree") ||
 		    !strcmp(sdev->prom_name, "cgRDI"))
@@ -473,8 +476,9 @@ cg3_setup(char *arg)
 	return 0;
 }
 
-#ifdef MODULE
 module_init(cg3_init);
+
+#ifdef MODULE
 module_exit(cg3_exit);
 #endif
 
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c
index 469ac2060..be87a66f1 100644
--- a/drivers/video/cg6.c
+++ b/drivers/video/cg6.c
@@ -712,7 +712,8 @@ static void cg6_init_one(struct sbus_dev *sdev)
 		sbus_ioremap(&sdev->resource[0], CG6_FHC_OFFSET,
 			     sizeof(u32), "cgsix fhc");
 
-	all->info.flags = FBINFO_FLAG_DEFAULT;
+	all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT |
+                          FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;
 	all->info.fbops = &cg6_ops;
 #ifdef CONFIG_SPARC32
 	all->info.screen_base = (char *)
@@ -759,6 +760,9 @@ int __init cg6_init(void)
 	struct sbus_bus *sbus;
 	struct sbus_dev *sdev;
 
+	if (fb_get_options("cg6fb", NULL))
+		return -ENODEV;
+
 	for_all_sbusdev(sdev, sbus) {
 		if (!strcmp(sdev->prom_name, "cgsix") ||
 		    !strcmp(sdev->prom_name, "cgthree+"))
@@ -788,8 +792,9 @@ cg6_setup(char *arg)
 	return 0;
 }
 
-#ifdef MODULE
 module_init(cg6_init);
+
+#ifdef MODULE
 module_exit(cg6_exit);
 #endif
 
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index c804352c0..4ee5a25db 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -362,7 +362,7 @@ static void __init init_chips(struct fb_info *p, unsigned long addr)
 	p->var = chipsfb_var;
 
 	p->fbops = &chipsfb_ops;
-	p->flags = FBINFO_FLAG_DEFAULT;
+	p->flags = FBINFO_DEFAULT;
 
 	fb_alloc_cmap(&p->cmap, 256, 0);
 
@@ -462,9 +462,14 @@ static struct pci_driver chipsfb_driver = {
 
 int __init chips_init(void)
 {
+	if (fb_get_options("chipsfb", NULL))
+		return -ENODEV;
+
 	return pci_module_init(&chipsfb_driver);
 }
 
+module_init(chips_init);
+
 static void __exit chipsfb_exit(void)
 {
 	pci_unregister_driver(&chipsfb_driver);
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 82c26b15c..8132b3bf2 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -752,6 +752,12 @@ int cirrusfb_check_var(struct fb_var_screeninfo *var,
 
 	switch (var->bits_per_pixel) {
 	case 1:
+		var->red.offset = 0;
+		var->red.length = 1;
+		var->green.offset = 0;
+		var->green.length = 1;
+		var->blue.offset = 0;
+		var->blue.length = 1;
 		break;
 
 	case 8:
@@ -2600,6 +2606,14 @@ int __init cirrusfb_init(void)
 {
 	int error = 0;
 
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("cirrusfb", &option))
+		return -ENODEV;
+	cirrusfb_setup(option);
+#endif
+
 #ifdef CONFIG_ZORRO
 	error |= zorro_module_init(&cirrusfb_zorro_driver);
 #endif
@@ -2657,8 +2671,9 @@ void __exit cirrusfb_exit (void)
 #endif
 }
 
-#ifdef MODULE
 module_init(cirrusfb_init);
+
+#ifdef MODULE
 module_exit(cirrusfb_exit);
 #endif
 
diff --git a/drivers/video/clps711xfb.c b/drivers/video/clps711xfb.c
index a982e7520..8692e0029 100644
--- a/drivers/video/clps711xfb.c
+++ b/drivers/video/clps711xfb.c
@@ -364,6 +364,9 @@ int __init clps711xfb_init(void)
 {
 	int err = -ENOMEM;
 
+	if (fb_get_options("clps711xfb", NULL))
+		return -ENODEV;
+
 	cfb = kmalloc(sizeof(*cfb), GFP_KERNEL);
 	if (!cfb)
 		goto out;
@@ -372,7 +375,7 @@ int __init clps711xfb_init(void)
 	strcpy(cfb->fix.id, "clps711x");
 
 	cfb->fbops		= &clps7111fb_ops;
-	cfb->flags		= FBINFO_FLAG_DEFAULT;
+	cfb->flags		= FBINFO_DEFAULT;
 
 	clps711x_guess_lcd_params(cfb);
 
@@ -432,9 +435,7 @@ static void __exit clps711xfb_exit(void)
 	}
 }
 
-#ifdef MODULE
 module_init(clps711xfb_init);
-#endif
 module_exit(clps711xfb_exit);
 
 MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 5bc0ef0ab..85e796b70 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -6,7 +6,7 @@ menu "Console display driver support"
 
 config VGA_CONSOLE
 	bool "VGA text console" if EMBEDDED || !X86
-	depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC32 && !SPARC64 && !M68K
+	depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC32 && !SPARC64 && !M68K && !PARISC
 	default y
 	help
 	  Saying Y here will allow you to use Linux in text mode through a
@@ -43,7 +43,7 @@ config VIDEO_SELECT
 	  about the Video mode selection support. If unsure, say N.
 
 config MDA_CONSOLE
-	depends on !M68K
+	depends on !M68K && ISA
 	tristate "MDA text console (dual-headed) (EXPERIMENTAL)"
 	---help---
 	  Say Y here if you have an old MDA or monochrome Hercules graphics
@@ -67,7 +67,7 @@ config SGI_NEWPORT_CONSOLE
 #  bool 'IODC console' CONFIG_IODC_CONSOLE
 config STI_CONSOLE
         tristate "STI text console" 
-        depends on PARISC
+        depends on PARISC && FRAMEBUFFER_CONSOLE
         default y
         help
           The STI console is the builtin display/keyboard on HP-PARISC
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 2fcb51a57..2fba5cfcb 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -314,6 +314,28 @@ static int search_for_mapped_con(void)
 	return 0;
 }
 
+static int fbcon_takeover(void)
+{
+	int err, i;
+
+	if (!num_registered_fb)
+		return -ENODEV;
+
+	for (i = first_fb_vc; i <= last_fb_vc; i++)
+		con2fb_map[i] = info_idx;
+
+	err = take_over_console(&fb_con, first_fb_vc, last_fb_vc,
+				fbcon_is_default);
+	if (err) {
+		for (i = first_fb_vc; i <= last_fb_vc; i++) {
+			con2fb_map[i] = -1;
+		}
+		info_idx = -1;
+	}
+
+	return err;
+}
+
 /**
  *	set_con2fb_map - map console to frame buffer device
  *	@unit: virtual console number to map
@@ -322,7 +344,7 @@ static int search_for_mapped_con(void)
  *	Maps a virtual console @unit to a frame buffer device
  *	@newidx.
  */
-int set_con2fb_map(int unit, int newidx)
+static int set_con2fb_map(int unit, int newidx)
 {
 	struct vc_data *vc = vc_cons[unit].d;
 	int oldidx = con2fb_map[unit];
@@ -338,8 +360,7 @@ int set_con2fb_map(int unit, int newidx)
 
 	if (!search_for_mapped_con()) {
 		info_idx = newidx;
-		fb_console_init();
-		return 0;
+		return fbcon_takeover();
 	}
 
 	if (oldidx != -1)
@@ -405,6 +426,87 @@ int set_con2fb_map(int unit, int newidx)
 /*
  * Accelerated handlers.
  */
+static inline int get_color(struct vc_data *vc, struct fb_info *info,
+			    u16 c, int is_fg)
+{
+	int depth = fb_get_color_depth(info);
+	int color = 0;
+
+	if (depth != 1)
+		color = (is_fg) ? attr_fgcol((vc->vc_hi_font_mask) ? 9 : 8, c)
+			: attr_bgcol((vc->vc_hi_font_mask) ? 13 : 12, c);
+
+	switch (depth) {
+	case 1:
+	{
+		/* 0 or 1 */
+		int fg = (info->fix.visual != FB_VISUAL_MONO01) ? 1 : 0;
+		int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : 1;
+
+		color = (is_fg) ? fg : bg;
+		break;
+	}
+	case 2:
+		/*
+		 * Scale down 16-colors to 4 colors. Default 4-color palette
+		 * is grayscale.
+		 */
+		color /= 4;
+		break;
+	case 3:
+		/*
+		 * Last 8 entries of default 16-color palette is a more intense
+		 * version of the first 8 (i.e., same chrominance, different
+		 * luminance).
+		 */
+		color &= 7;
+		break;
+	}
+
+	return color;
+}
+
+#define FBCON_ATTRIBUTE_UNDERLINE 1
+#define FBCON_ATTRIBUTE_REVERSE   2
+#define FBCON_ATTRIBUTE_BOLD      4
+
+static inline int get_attribute(struct fb_info *info, u16 c)
+{
+	int attribute = 0;
+
+	if (fb_get_color_depth(info) == 1) {
+		if (attr_underline(c))
+			attribute |= FBCON_ATTRIBUTE_UNDERLINE;
+		if (attr_reverse(c))
+			attribute |= FBCON_ATTRIBUTE_REVERSE;
+		if (attr_bold(c))
+			attribute |= FBCON_ATTRIBUTE_BOLD;
+	}
+
+	return attribute;
+}
+
+static inline void update_attr(u8 *dst, u8 *src, int attribute,
+			       struct vc_data *vc)
+{
+	int i, offset = (vc->vc_font.height < 10) ? 1 : 2;
+	int width = (vc->vc_font.width + 7) >> 3;
+	unsigned int cellsize = vc->vc_font.height * width;
+	u8 c;
+
+	offset = cellsize - (offset * width);
+	for (i = 0; i < cellsize; i++) {
+		c = src[i];
+		if (attribute & FBCON_ATTRIBUTE_UNDERLINE && i >= offset)
+			c = 0xff;
+		if (attribute & FBCON_ATTRIBUTE_BOLD)
+			c |= c >> 1;
+		if (attribute & FBCON_ATTRIBUTE_REVERSE)
+			c = ~c;
+		dst[i] = c;
+	}
+}
+
 void accel_bmove(struct vc_data *vc, struct fb_info *info, int sy, 
 		int sx, int dy, int dx, int height, int width)
 {
@@ -455,13 +557,19 @@ void accel_putcs(struct vc_data *vc, struct fb_info *info,
 	unsigned int shift_low = 0, mod = vc->vc_font.width % 8;
 	unsigned int shift_high = 8, pitch, cnt, size, k;
 	unsigned int idx = vc->vc_font.width >> 3;
+	unsigned int attribute = get_attribute(info, scr_readw(s));
 	struct fb_image image;
-	u8 *src, *dst;
+	u8 *src, *dst, *buf = NULL;
+
+	if (attribute) {
+		buf = kmalloc(cellsize, GFP_KERNEL);
+		if (!buf)
+			return;
+	}
+
+	image.fg_color = get_color(vc, info, scr_readw(s), 1);
+	image.bg_color = get_color(vc, info, scr_readw(s), 0);
 
-	image.fg_color = attr_fgcol((vc->vc_hi_font_mask) ? 9 : 8,
-				    scr_readw(s));
-	image.bg_color = attr_bgcol((vc->vc_hi_font_mask) ? 13 : 12,
-				    scr_readw(s));
 	image.dx = xx * vc->vc_font.width;
 	image.dy = yy * vc->vc_font.height;
 	image.height = vc->vc_font.height;
@@ -491,6 +599,12 @@ void accel_putcs(struct vc_data *vc, struct fb_info *info,
 			while (k--) {
 				src = vc->vc_font.data + (scr_readw(s++)&
 							  charmask)*cellsize;
+
+				if (attribute) {
+					update_attr(buf, src, attribute, vc);
+					src = buf;
+				}
+
 				move_unaligned(info, &info->pixmap, dst, pitch,
 					       src, idx, image.height,
 					       shift_high, shift_low, mod);
@@ -503,6 +617,12 @@ void accel_putcs(struct vc_data *vc, struct fb_info *info,
 			while (k--) {
 				src = vc->vc_font.data + (scr_readw(s++)&
 							  charmask)*cellsize;
+
+				if (attribute) {
+					update_attr(buf, src, attribute, vc);
+					src = buf;
+				}
+
 				move_aligned(info, &info->pixmap, dst, pitch,
 					     src, idx, image.height);
 				dst += width;
@@ -512,6 +632,9 @@ void accel_putcs(struct vc_data *vc, struct fb_info *info,
 		image.dx += cnt * vc->vc_font.width;
 		count -= cnt;
 	}
+
+	if (buf)
+		kfree(buf);
 }
 
 void accel_clear_margins(struct vc_data *vc, struct fb_info *info,
@@ -550,6 +673,47 @@ void accel_clear_margins(struct vc_data *vc, struct fb_info *info,
  *  Low Level Operations
  */
 /* NOTE: fbcon cannot be __init: it may be called from take_over_console later */
+static int var_to_display(struct display *disp,
+			  struct fb_var_screeninfo *var,
+			  struct fb_info *info)
+{
+	disp->xres_virtual = var->xres_virtual;
+	disp->yres_virtual = var->yres_virtual;
+	disp->bits_per_pixel = var->bits_per_pixel;
+	disp->grayscale = var->grayscale;
+	disp->nonstd = var->nonstd;
+	disp->accel_flags = var->accel_flags;
+	disp->height = var->height;
+	disp->width = var->width;
+	disp->red = var->red;
+	disp->green = var->green;
+	disp->blue = var->blue;
+	disp->transp = var->transp;
+	disp->mode = fb_match_mode(var, &info->modelist);
+	if (disp->mode == NULL)
+		/* This should not happen */
+		return -EINVAL;
+	return 0;
+}
+
+static void display_to_var(struct fb_var_screeninfo *var,
+			   struct display *disp)
+{
+	fb_videomode_to_var(var, disp->mode);
+	var->xres_virtual = disp->xres_virtual;
+	var->yres_virtual = disp->yres_virtual;
+	var->bits_per_pixel = disp->bits_per_pixel;
+	var->grayscale = disp->grayscale;
+	var->nonstd = disp->nonstd;
+	var->accel_flags = disp->accel_flags;
+	var->height = disp->height;
+	var->width = disp->width;
+	var->red = disp->red;
+	var->green = disp->green;
+	var->blue = disp->blue;
+	var->transp = disp->transp;
+}
+
 static const char *fbcon_startup(void)
 {
 	const char *display_desc = "frame buffer device";
@@ -723,6 +887,9 @@ static void fbcon_init(struct vc_data *vc, int init)
 
 	info->var.xoffset = info->var.yoffset = p->yscroll = 0;	/* reset wrap/pan */
 
+	if (var_to_display(p, &info->var, info))
+		return;
+
 	/* If we are not the first console on this
 	   fb, copy the font from that console */
 	t = &fb_display[display_fg];
@@ -737,7 +904,7 @@ static void fbcon_init(struct vc_data *vc, int init)
 	}
 	if (p->userfont)
 		charcnt = FNTCHARCNT(p->fontdata);
-	vc->vc_can_do_color = info->var.bits_per_pixel != 1;
+	vc->vc_can_do_color = (fb_get_color_depth(info) != 1);
 	vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
 	if (charcnt == 256) {
 		vc->vc_hi_font_mask = 0;
@@ -780,9 +947,15 @@ static void fbcon_init(struct vc_data *vc, int init)
 
 	if (logo) {
 		/* Need to make room for the logo */
-		int cnt;
+		int cnt, erase = vc->vc_video_erase_char;
 		int step;
 
+		/*
+		 * remove underline attribute from erase character
+		 * if black and white framebuffer.
+		 */
+		if (fb_get_color_depth(info) == 1)
+			erase &= ~0x400;
 		logo_height = fb_prepare_logo(info);
 		logo_lines = (logo_height + vc->vc_font.height - 1) /
 			     vc->vc_font.height;
@@ -796,8 +969,7 @@ static void fbcon_init(struct vc_data *vc, int init)
 			save = kmalloc(logo_lines * new_cols * 2, GFP_KERNEL);
 			if (save) {
 				int i = cols < new_cols ? cols : new_cols;
-				scr_memsetw(save, vc->vc_video_erase_char,
-					    logo_lines * new_cols * 2);
+				scr_memsetw(save, erase, logo_lines * new_cols * 2);
 				r = q - step;
 				for (cnt = 0; cnt < logo_lines; cnt++, r += i)
 					scr_memcpyw(save + cnt * new_cols, r, 2 * i);
@@ -817,7 +989,7 @@ static void fbcon_init(struct vc_data *vc, int init)
 			}
 		}
 		scr_memsetw((unsigned short *) vc->vc_origin,
-			    vc->vc_video_erase_char,
+			    erase,
 			    vc->vc_size_row * logo_lines);
 
 		if (CON_IS_VISIBLE(vc) && vt_cons[vc->vc_num]->vc_mode == KD_TEXT) {
@@ -926,55 +1098,6 @@ static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height,
 		accel_clear(vc, info, real_y(p, sy), sx, height, width);
 }
 
-static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos)
-{
-	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
-	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
-	unsigned int scan_align = info->pixmap.scan_align - 1;
-	unsigned int buf_align = info->pixmap.buf_align - 1;
-	unsigned int width = (vc->vc_font.width + 7) >> 3;
-	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
-	int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;
-	struct display *p = &fb_display[vc->vc_num];
-	unsigned int size, pitch;
-	struct fb_image image;
-	u8 *src, *dst;
-
-	if (!info->fbops->fb_blank && console_blanked)
-		return;
-	if (info->state != FBINFO_STATE_RUNNING)
-		return;
-
-	if (vt_cons[vc->vc_num]->vc_mode != KD_TEXT)
-		return;
-
-	image.dx = xpos * vc->vc_font.width;
-	image.dy = real_y(p, ypos) * vc->vc_font.height;
-	image.width = vc->vc_font.width;
-	image.height = vc->vc_font.height;
-	image.fg_color = attr_fgcol(fgshift, c);
-	image.bg_color = attr_bgcol(bgshift, c);
-	image.depth = 1;
-
-	src = vc->vc_font.data + (c & charmask) * vc->vc_font.height * width;
-
-	pitch = width + scan_align;
-	pitch &= ~scan_align;
-	size = pitch * vc->vc_font.height;
-	size += buf_align;
-	size &= ~buf_align;
-
-	dst = fb_get_buffer_offset(info, &info->pixmap, size);
-	image.data = dst;
-
-	if (info->pixmap.outbuf)
-		fb_iomove_buf_aligned(info, &info->pixmap, dst, pitch, src, width, image.height);
-	else
-		fb_sysmove_buf_aligned(info, &info->pixmap, dst, pitch, src, width, image.height);
-
-	info->fbops->fb_imageblit(info, &image);
-}
-
 static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,
 			int count, int ypos, int xpos)
 {
@@ -992,17 +1115,22 @@ static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,
 	accel_putcs(vc, info, s, count, real_y(p, ypos), xpos);
 }
 
+static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos)
+{
+	fbcon_putcs(vc, (const unsigned short *) &c, 1, ypos, xpos);
+}
+
 static void fbcon_cursor(struct vc_data *vc, int mode)
 {
+	struct fb_cursor cursor;
 	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
 	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
-	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
-	int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;
 	struct display *p = &fb_display[vc->vc_num];
 	int w = (vc->vc_font.width + 7) >> 3, c;
-	int y = real_y(p, vc->vc_y);
-	struct fb_cursor cursor;
-	
+	int y = real_y(p, vc->vc_y), fg, bg;
+	int attribute;
+	u8 *src;
+
 	if (mode & CM_SOFTBACK) {
 		mode &= ~CM_SOFTBACK;
 		if (softback_lines) {
@@ -1015,8 +1143,22 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
 		fbcon_set_origin(vc);
 
  	c = scr_readw((u16 *) vc->vc_pos);
-
-	cursor.image.data = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
+	attribute = get_attribute(info, c);
+	src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
+	if (attribute) {
+		u8 *dst;
+
+		dst = kmalloc(w * vc->vc_font.height, GFP_ATOMIC);
+		if (!dst)
+			return;
+		if (info->cursor.data)
+			kfree(info->cursor.data);
+		info->cursor.data = dst;
+		update_attr(dst, src, attribute, vc);
+		src = dst;
+	}
+
+	cursor.image.data = src;
 	cursor.set = FB_CUR_SETCUR;
 	cursor.image.depth = 1;
 	
@@ -1031,11 +1173,13 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
 	case CM_MOVE:
 	case CM_DRAW:
 		info->cursor.enable = 1;
-		
-		if (info->cursor.image.fg_color != attr_fgcol(fgshift, c) ||
-	    	    info->cursor.image.bg_color != attr_bgcol(bgshift, c)) {
-			cursor.image.fg_color = attr_fgcol(fgshift, c);
-			cursor.image.bg_color = attr_bgcol(bgshift, c);
+		fg = get_color(vc, info, c, 1);
+		bg = get_color(vc, info, c, 0);
+
+		if (info->cursor.image.fg_color != fg ||
+		    info->cursor.image.bg_color != bg) {
+			cursor.image.fg_color = fg;
+			cursor.image.bg_color = bg;
 			cursor.set |= FB_CUR_SETCMAP;
 		}
 		
@@ -1058,17 +1202,19 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
 			cursor.set |= FB_CUR_SETHOT;
 		}
 
-		if ((cursor.set & FB_CUR_SETSIZE) || ((vc->vc_cursor_type & 0x0f) != p->cursor_shape)
+		if ((cursor.set & FB_CUR_SETSIZE) ||
+		    ((vc->vc_cursor_type & 0x0f) != p->cursor_shape)
 		    || info->cursor.mask == NULL) {
 			char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC);
 			int cur_height, size, i = 0;
+			u8 msk = 0xff;
 
-			if (!mask)	return;	
+			if (!mask)
+				return;
 		
 			if (info->cursor.mask)
 				kfree(info->cursor.mask);
 			info->cursor.mask = mask;
-	
 			p->cursor_shape = vc->vc_cursor_type & 0x0f;
 			cursor.set |= FB_CUR_SETSHAPE;
 
@@ -1095,10 +1241,10 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
 			}
 			size = (vc->vc_font.height - cur_height) * w;
 			while (size--)
-				mask[i++] = 0;
+				mask[i++] = ~msk;
 			size = cur_height * w;
 			while (size--)
-				mask[i++] = 0xff;
+				mask[i++] = msk;
 		}
         	info->cursor.rop = ROP_XOR;
 		info->fbops->fb_cursor(info, &cursor);
@@ -1126,6 +1272,8 @@ static void fbcon_set_disp(struct fb_info *info, struct vc_data *vc)
 	int rows, cols, charcnt = 256;
 
 	info->var.xoffset = info->var.yoffset = p->yscroll = 0;
+	if (var_to_display(p, &info->var, info))
+		return;
 	t = &fb_display[display_fg];
 	if (!vc->vc_font.data) {
 		vc->vc_font.data = p->fontdata = t->fontdata;
@@ -1139,7 +1287,7 @@ static void fbcon_set_disp(struct fb_info *info, struct vc_data *vc)
 	if (p->userfont)
 		charcnt = FNTCHARCNT(p->fontdata);
 
-	vc->vc_can_do_color = info->var.bits_per_pixel != 1;
+	vc->vc_can_do_color = (fb_get_color_depth(info) != 1);
 	vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
 	if (charcnt == 256) {
 		vc->vc_hi_font_mask = 0;
@@ -1813,7 +1961,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
 	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
 	struct fb_var_screeninfo var = info->var;
-	int err; int x_diff, y_diff;
+	int x_diff, y_diff;
 	int fw = vc->vc_font.width;
 	int fh = vc->vc_font.height;
 
@@ -1822,15 +1970,31 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
 	x_diff = info->var.xres - var.xres;
 	y_diff = info->var.yres - var.yres;
 	if (x_diff < 0 || x_diff > fw || (y_diff < 0 || y_diff > fh)) {
-		char mode[40];
+		struct fb_videomode *mode;
 
 		DPRINTK("attempting resize %ix%i\n", var.xres, var.yres);
-		snprintf(mode, 40, "%ix%i", var.xres, var.yres);
-		err = fb_find_mode(&var, info, mode, info->monspecs.modedb,
-				   info->monspecs.modedb_len, NULL,
-				   info->var.bits_per_pixel);
-		if (!err || width > var.xres/fw || height > var.yres/fh)
+		mode = fb_find_best_mode(&var, &info->modelist);
+		if (mode == NULL)
+			return -EINVAL;
+		fb_videomode_to_var(&var, mode);
+		if (width > var.xres/fw || height > var.yres/fh)
 			return -EINVAL;
+		/*
+		 * The following can probably have any value... Do we need to
+		 * set all of them?
+		 */
+		var.bits_per_pixel = p->bits_per_pixel;
+		var.xres_virtual = p->xres_virtual;
+		var.yres_virtual = p->yres_virtual;
+		var.accel_flags = p->accel_flags;
+		var.width = p->width;
+		var.height = p->height;
+		var.red = p->red;
+		var.green = p->green;
+		var.blue = p->blue;
+		var.transp = p->transp;
+		var.nonstd = p->nonstd;
+
 		DPRINTK("resize now %ix%i\n", var.xres, var.yres);
 		if (CON_IS_VISIBLE(vc)) {
 			var.activate = FB_ACTIVATE_NOW |
@@ -1838,6 +2002,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
 			fb_set_var(info, &var);
 			info->flags &= ~FBINFO_MISC_MODESWITCH;
 		}
+		var_to_display(p, &info->var, info);
 	}
 	updatescrollmode(p, info, vc);
 	return 0;
@@ -1847,6 +2012,7 @@ static int fbcon_switch(struct vc_data *vc)
 {
 	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
+	struct fb_var_screeninfo var;
 	int i;
 
 	if (softback_top) {
@@ -1872,8 +2038,6 @@ static int fbcon_switch(struct vc_data *vc)
 			conp2->vc_top = 0;
 		logo_shown = -1;
 	}
-	if (info)
-		info->var.yoffset = p->yscroll = 0;
 
 	/*
 	 * FIXME: If we have multiple fbdev's loaded, we need to
@@ -1888,7 +2052,18 @@ static int fbcon_switch(struct vc_data *vc)
 			registered_fb[i]->currcon = vc->vc_num;
 	}
 
- 	fbcon_resize(vc, vc->vc_cols, vc->vc_rows);
+	memset(&var, 0, sizeof(struct fb_var_screeninfo));
+	fb_videomode_to_var(&var, p->mode);
+	display_to_var(&var, p);
+	var.activate = FB_ACTIVATE_NOW;
+
+	/*
+	 * make sure we don't unnecessarily trip the memcmp()
+	 * in fb_set_var()
+	 */
+	info->var.activate = var.activate;
+	info->var.yoffset = info->var.xoffset = p->yscroll = 0;
+	fb_set_var(info, &var);
 
 	if (info->flags & FBINFO_MISC_MODESWITCH) {
 		if (info->fbops->fb_set_par)
@@ -1896,6 +2071,10 @@ static int fbcon_switch(struct vc_data *vc)
 		info->flags &= ~FBINFO_MISC_MODESWITCH;
 	}
 
+	vc->vc_can_do_color = (fb_get_color_depth(info) != 1);
+	vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
+	updatescrollmode(p, info, vc);
+
 	switch (p->scrollmode) {
 	case SCROLL_WRAP_MOVE:
 		scrollback_phys_max = p->vrows - vc->vc_rows;
@@ -2290,26 +2469,31 @@ static struct fb_cmap palette_cmap = {
 static int fbcon_set_palette(struct vc_data *vc, unsigned char *table)
 {
 	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
-	int i, j, k;
+	int i, j, k, depth;
 	u8 val;
 
-	if (!vc->vc_can_do_color
-	    || (!info->fbops->fb_blank && console_blanked))
+	if (!info->fbops->fb_blank && console_blanked)
 		return -EINVAL;
-	for (i = j = 0; i < 16; i++) {
-		k = table[i];
-		val = vc->vc_palette[j++];
-		palette_red[k] = (val << 8) | val;
-		val = vc->vc_palette[j++];
-		palette_green[k] = (val << 8) | val;
-		val = vc->vc_palette[j++];
-		palette_blue[k] = (val << 8) | val;
-	}
-	if (info->var.bits_per_pixel <= 4)
-		palette_cmap.len = 1 << info->var.bits_per_pixel;
-	else
+	depth = fb_get_color_depth(info);
+	if (depth > 3) {
+		for (i = j = 0; i < 16; i++) {
+			k = table[i];
+			val = vc->vc_palette[j++];
+			palette_red[k] = (val << 8) | val;
+			val = vc->vc_palette[j++];
+			palette_green[k] = (val << 8) | val;
+			val = vc->vc_palette[j++];
+			palette_blue[k] = (val << 8) | val;
+		}
 		palette_cmap.len = 16;
-	palette_cmap.start = 0;
+		palette_cmap.start = 0;
+	/*
+	 * If framebuffer is capable of less than 16 colors,
+	 * use default palette of fbcon.
+	 */
+	} else
+		fb_copy_cmap(fb_default_cmap(1 << depth), &palette_cmap);
+
 	return fb_set_cmap(&palette_cmap, info);
 }
 
@@ -2516,10 +2700,9 @@ static void fbcon_modechanged(struct fb_info *info)
 	p = &fb_display[vc->vc_num];
 
 	info->var.xoffset = info->var.yoffset = p->yscroll = 0;
-	vc->vc_can_do_color = info->var.bits_per_pixel != 1;
-	vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
 
 	if (CON_IS_VISIBLE(vc)) {
+		var_to_display(p, &info->var, info);
 		cols = info->var.xres / vc->vc_font.width;
 		rows = info->var.yres / vc->vc_font.height;
 		vc_resize(vc->vc_num, cols, rows);
@@ -2542,10 +2725,52 @@ static void fbcon_modechanged(struct fb_info *info)
 	}
 }
 
+static int fbcon_mode_deleted(struct fb_info *info,
+			      struct fb_videomode *mode)
+{
+	struct fb_info *fb_info;
+	struct display *p;
+	int i, j, found = 0;
+
+	/* before deletion, ensure that mode is not in use */
+	for (i = first_fb_vc; i <= last_fb_vc; i++) {
+		j = (int) con2fb_map[i];
+		if (j == -1)
+			continue;
+		fb_info = registered_fb[j];
+		if (fb_info != info)
+			continue;
+		p = &fb_display[i];
+		if (!p || !p->mode)
+			continue;
+		if (fb_mode_is_equal(p->mode, mode)) {
+			found = 1;
+			break;
+		}
+	}
+	return found;
+}
+
+static int fbcon_fb_registered(int idx)
+{
+	int ret = 0;
+
+	if (info_idx == -1) {
+		info_idx = idx;
+		ret = fbcon_takeover();
+	}
+
+	return ret;
+}
+
 static int fbcon_event_notify(struct notifier_block *self, 
 			      unsigned long action, void *data)
 {
-	struct fb_info *info = (struct fb_info *) data;
+	struct fb_event *event = (struct fb_event *) data;
+	struct fb_info *info = event->info;
+	struct fb_videomode *mode;
+	struct fb_con2fbmap *con2fb;
+	int ret = 0;
 
 	switch(action) {
 	case FB_EVENT_SUSPEND:
@@ -2557,9 +2782,24 @@ static int fbcon_event_notify(struct notifier_block *self,
 	case FB_EVENT_MODE_CHANGE:
 		fbcon_modechanged(info);
 		break;
+	case FB_EVENT_MODE_DELETE:
+		mode = (struct fb_videomode *) event->data;
+		ret = fbcon_mode_deleted(info, mode);
+		break;
+	case FB_EVENT_FB_REGISTERED:
+		ret = fbcon_fb_registered(info->node);
+		break;
+	case FB_EVENT_SET_CONSOLE_MAP:
+		con2fb = (struct fb_con2fbmap *) event->data;
+		ret = set_con2fb_map(con2fb->console - 1, con2fb->framebuffer);
+		break;
+	case FB_EVENT_GET_CONSOLE_MAP:
+		con2fb = (struct fb_con2fbmap *) event->data;
+		con2fb->framebuffer = con2fb_map[con2fb->console - 1];
+		break;
 	}
 
-	return 0;
+	return ret;
 }
 
 /*
@@ -2595,60 +2835,43 @@ const struct consw fb_con = {
 static struct notifier_block fbcon_event_notifier = {
 	.notifier_call	= fbcon_event_notify,
 };
-static int fbcon_event_notifier_registered;
 
-/* can't be __init as it can be called by set_con2fb_map() later */
-int fb_console_init(void)
+int __init fb_console_init(void)
 {
-	int err, i;
+	int i;
+
+	acquire_console_sem();
+	fb_register_client(&fbcon_event_notifier);
+	release_console_sem();
 
 	for (i = 0; i < MAX_NR_CONSOLES; i++)
 		con2fb_map[i] = -1;
 
-	if (!num_registered_fb)
-		return -ENODEV;
-
-	if (info_idx == -1) {
+	if (num_registered_fb) {
 		for (i = 0; i < FB_MAX; i++) {
 			if (registered_fb[i] != NULL) {
 				info_idx = i;
 				break;
 			}
 		}
+		fbcon_takeover();
 	}
-	for (i = first_fb_vc; i <= last_fb_vc; i++)
-		con2fb_map[i] = info_idx;
-	err = take_over_console(&fb_con, first_fb_vc, last_fb_vc,
-				fbcon_is_default);
-	if (err) {
-		for (i = first_fb_vc; i <= last_fb_vc; i++) {
-			con2fb_map[i] = -1;
-		}
-		return err;
-	}
-	acquire_console_sem();
-	if (!fbcon_event_notifier_registered) {
-		fb_register_client(&fbcon_event_notifier);
-		fbcon_event_notifier_registered = 1;
-	} 
-	release_console_sem();
+
 	return 0;
 }
 
+module_init(fb_console_init);
+
 #ifdef MODULE
 
 void __exit fb_console_exit(void)
 {
 	acquire_console_sem();
-	if (fbcon_event_notifier_registered) {
-		fb_unregister_client(&fbcon_event_notifier);
-		fbcon_event_notifier_registered = 0;
-	}
+	fb_unregister_client(&fbcon_event_notifier);
 	release_console_sem();
 	give_up_console(&fb_con);
 }	
 
-module_init(fb_console_init);
 module_exit(fb_console_exit);
 
 #endif
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 71643f5ad..a89001a40 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -33,12 +33,21 @@ struct display {
     short yscroll;                  /* Hardware scrolling */
     int vrows;                      /* number of virtual rows */
     int cursor_shape;
+    u32 xres_virtual;
+    u32 yres_virtual;
+    u32 height;
+    u32 width;
+    u32 bits_per_pixel;
+    u32 grayscale;
+    u32 nonstd;
+    u32 accel_flags;
+    struct fb_bitfield red;
+    struct fb_bitfield green;
+    struct fb_bitfield blue;
+    struct fb_bitfield transp;
+    struct fb_videomode *mode;
 };
 
-/* drivers/video/console/fbcon.c */
-extern signed char con2fb_map[MAX_NR_CONSOLES];
-extern int set_con2fb_map(int unit, int newidx);
-
     /*
      *  Attribute Decoding
      */
@@ -56,8 +65,8 @@ extern int set_con2fb_map(int unit, int newidx);
 /* Monochrome */
 #define attr_bold(s) \
 	((s) & 0x200)
-#define attr_reverse(s, inverse) \
-	(((s) & 0x800) ^ (inverse ? 0x800 : 0))
+#define attr_reverse(s) \
+	((s) & 0x800)
 #define attr_underline(s) \
 	((s) & 0x400)
 #define attr_blink(s) \
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index 8ad33fa31..22896d692 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -556,6 +556,11 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro
 int __init control_init(void)
 {
 	struct device_node *dp;
+	char *option = NULL;
+
+	if (fb_get_options("controlfb", &option))
+		return -ENODEV;
+	control_setup(option);
 
 	dp = find_devices("control");
 	if (dp != 0 && !control_of_init(dp))
@@ -564,6 +569,7 @@ int __init control_init(void)
 	return -ENXIO;
 }
 
+module_init(control_init);
 
 /* Work out which banks of VRAM we have installed. */
 /* danj: I guess the card just ignores writes to nonexistant VRAM... */
@@ -1010,7 +1016,7 @@ static void __init control_init_info(struct fb_info *info, struct fb_info_contro
 	info->par = &p->par;
 	info->fbops = &controlfb_ops;
 	info->pseudo_palette = p->pseudo_palette;
-        info->flags = FBINFO_FLAG_DEFAULT;
+        info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 	info->screen_base = (char *) p->frame_buffer + CTRLFB_OFF;
 
 	fb_alloc_cmap(&info->cmap, 256, 0);
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index 0afebb72c..4dca34fdf 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -1166,7 +1166,7 @@ static struct fb_videomode __devinitdata cyber2000fb_default_mode = {
 	.vmode		= FB_VMODE_NONINTERLACED
 };
 
-static char igs_regs[] __devinitdata = {
+static char igs_regs[] = {
 	EXT_CRT_IRQ,		0,
 	EXT_CRT_TEST,		0,
 	EXT_SYNC_CTL,		0,
@@ -1281,7 +1281,7 @@ cyberpro_alloc_fb_info(unsigned int id, char *name)
 	cfb->fb.var.accel_flags	= FB_ACCELF_TEXT;
 
 	cfb->fb.fbops		= &cyber2000fb_ops;
-	cfb->fb.flags		= FBINFO_FLAG_DEFAULT;
+	cfb->fb.flags		= FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 	cfb->fb.pseudo_palette	= (void *)(cfb + 1);
 
 	fb_alloc_cmap(&cfb->fb.cmap, NR_PALETTE, 0);
@@ -1289,7 +1289,7 @@ cyberpro_alloc_fb_info(unsigned int id, char *name)
 	return cfb;
 }
 
-static void __devinit
+static void
 cyberpro_free_fb_info(struct cfb_info *cfb)
 {
 	if (cfb) {
@@ -1712,11 +1712,21 @@ static struct pci_driver cyberpro_driver = {
  * I don't think we can use the "module_init" stuff here because
  * the fbcon stuff may not be initialised yet.  Hence the #ifdef
  * around module_init.
+ *
+ * Tony: "module_init" is now required
  */
 int __init cyber2000fb_init(void)
 {
 	int ret = -1, err;
 
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("cyber2000fb", NULL))
+		return -ENODEV;
+	cyber2000fb_setup(option);
+#endif
+
 #ifdef CONFIG_ARCH_SHARK
 	err = cyberpro_vl_probe();
 	if (!err) {
@@ -1738,9 +1748,7 @@ static void __exit cyberpro_exit(void)
 	pci_unregister_driver(&cyberpro_driver);
 }
 
-#ifdef MODULE
 module_init(cyber2000fb_init);
-#endif
 module_exit(cyberpro_exit);
 
 MODULE_AUTHOR("Russell King");
diff --git a/drivers/video/dnfb.c b/drivers/video/dnfb.c
index 11ba053b5..1dbb82dca 100644
--- a/drivers/video/dnfb.c
+++ b/drivers/video/dnfb.c
@@ -239,6 +239,9 @@ static int __devinit dnfb_probe(struct device *device)
 	info->fbops = &dn_fb_ops;
 	info->fix = dnfb_fix;
 	info->var = dnfb_var;
+	info->var.red.length = 1;
+	info->var.red.offset = 0;
+	info->var.green = info->var.blue = info->var.red;
 	info->screen_base = (u_char *) info->fix.smem_start;
 
 	err = fb_alloc_cmap(&info->cmap, 2, 0);
@@ -281,6 +284,9 @@ int __init dnfb_init(void)
 {
 	int ret;
 
+	if (fb_get_options("dnfb", NULL))
+		return -ENODEV;
+
 	ret = driver_register(&dnfb_driver);
 
 	if (!ret) {
@@ -291,4 +297,6 @@ int __init dnfb_init(void)
 	return ret;
 }
 
+module_init(dnfb_init);
+
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
index a998ee9d8..6cb54f809 100644
--- a/drivers/video/epson1355fb.c
+++ b/drivers/video/epson1355fb.c
@@ -1,541 +1,771 @@
 /*
- * linux/drivers/video/epson1355fb.c
- *	-- Support for the Epson SED1355 LCD/CRT controller
+ * linux/drivers/video/epson1355fb.c -- Epson S1D13505 frame buffer for 2.5.
  *
- * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ * Epson Research S1D13505 Embedded RAMDAC LCD/CRT Controller
+ *   (previously known as SED1355)
  *
- * based on linux/drivers/video/skeletonfb.c, which was
+ * Cf. http://www.erd.epson.com/vdc/html/S1D13505.html
+ *
+ *
+ * Copyright (C) Hewlett-Packard Company.  All rights reserved.
+ *
+ * Written by Christopher Hoover <ch@hpl.hp.com>
+ *
+ * Adapted from:
+ *
+ *  linux/drivers/video/skeletonfb.c
+ *  Modified to new api Jan 2001 by James Simmons (jsimmons@infradead.org)
  *  Created 28 Dec 1997 by Geert Uytterhoeven
  *
+ *  linux/drivers/video/epson1355fb.c (2.4 driver)
+ *  Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-/* TODO (roughly in order of priority):
- * 16 bpp support
- * crt support
- * hw cursor support
- * SwivelView
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ *
+ * Noteworthy Issues
+ * -----------------
+ *
+ * This driver is complicated by the fact that this is a 16-bit chip
+ * and, on at least one platform (ceiva), we can only do 16-bit reads
+ * and writes to the framebuffer.  We hide this from user space
+ * except in the case of mmap().
+ *
+ *
+ * To Do
+ * -----
+ *
+ * - Test 8-bit pseudocolor mode
+ * - Allow setting bpp, virtual resolution
+ * - Implement horizontal panning
+ * - (maybe) Implement hardware cursor
  */
 
-#include <asm/io.h>
-#include <linux/config.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
 #include <linux/module.h>
-#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/mm.h>
 #include <linux/tty.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-mfb.h>
-#include <video/fbcon.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <asm/types.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
 
-/* Register defines.  The docs don't seem to provide nice mnemonic names
- * so I made them up myself ... */
+#include <video/epson1355.h>
 
-#define E1355_PANEL	0x02
-#define E1355_DISPLAY	0x0D
-#define E1355_MISC	0x1B
-#define E1355_GPIO	0x20
-#define E1355_LUT_INDEX 0x24
-#define E1355_LUT_DATA	0x26
+struct epson1355_par {
+	unsigned long reg_addr;
+};
+
+/* ------------------------------------------------------------------------- */
 
 #ifdef CONFIG_SUPERH
-#define E1355_REG_BASE	CONFIG_E1355_REG_BASE
-#define E1355_FB_BASE	CONFIG_E1355_FB_BASE
 
-static inline u8 e1355_read_reg(int index)
+static inline u8 epson1355_read_reg(int index)
 {
-	return ctrl_inb(E1355_REG_BASE + index);
+	return ctrl_inb(par.reg_addr + index);
 }
 
-static inline void e1355_write_reg(u8 data, int index)
+static inline void epson1355_write_reg(u8 data, int index)
 {
-	ctrl_outb(data, E1355_REG_BASE + index);
+	ctrl_outb(data, par.reg_addr + index);
 }
 
-static inline u16 e1355_read_reg16(int index)
+#elif defined(CONFIG_ARM)
+
+# ifdef CONFIG_ARCH_CEIVA
+#  include <asm/arch/hardware.h>
+#  define EPSON1355FB_BASE_PHYS	(CEIVA_PHYS_SED1355)
+# endif
+
+static inline u8 epson1355_read_reg(struct epson1355_par *par, int index)
 {
-	return e1355_read_reg(index) + (e1355_read_reg(index+1) << 8);
+	return __raw_readb(par->reg_addr + index);
 }
 
-static inline void e1355_write_reg16(u16 data, int index)
+static inline void epson1355_write_reg(struct epson1355_par *par, u8 data, int index)
 {
-	e1355_write_reg((data&0xff), index);
-	e1355_write_reg(((data>>8)&0xff), index + 1);
+	__raw_writeb(data, par->reg_addr + index);
 }
+
 #else
-#error unknown architecture
+# error "no architecture-specific epson1355_{read,write}_reg"
 #endif
 
-struct e1355fb_info {
-	struct fb_info_gen gen;
-};
-
-static int current_par_valid = 0;
-static struct display disp;
+#ifndef EPSON1355FB_BASE_PHYS
+# error  "EPSON1355FB_BASE_PHYS is not defined"
+#endif
 
-static struct fb_var_screeninfo default_var;
+#define EPSON1355FB_REGS_OFS	(0)
+#define EPSON1355FB_REGS_PHYS	(EPSON1355FB_BASE_PHYS + EPSON1355FB_REGS_OFS)
+#define EPSON1355FB_REGS_LEN	(64)
 
-int e1355fb_init(void);
-int e1355fb_setup(char*);
-static int e1355_encode_var(struct fb_var_screeninfo *var, const void *par,
-			    struct fb_info_gen *info);
-/* ------------------- chipset specific functions -------------------------- */
+#define EPSON1355FB_FB_OFS	(0x00200000)
+#define EPSON1355FB_FB_PHYS	(EPSON1355FB_BASE_PHYS + EPSON1355FB_FB_OFS)
+#define EPSON1355FB_FB_LEN	(2 * 1024 * 1024)
 
+/* ------------------------------------------------------------------------- */
 
-static void disable_hw_cursor(void)
+static inline u16 epson1355_read_reg16(struct epson1355_par *par, int index)
 {
-	u8 curs;
+	u8 lo = epson1355_read_reg(par, index);
+	u8 hi = epson1355_read_reg(par, index + 1);
 
-	curs = e1355_read_reg(0x27);
-	curs &= ~0xc0;
-	e1355_write_reg(curs, 0x27);
+	return (hi << 8) | lo;
 }
 
-static void e1355_detect(void)
+static inline void epson1355_write_reg16(struct epson1355_par *par, u16 data, int index)
 {
-	u8 rev;
+	u8 lo = data & 0xff;
+	u8 hi = (data >> 8) & 0xff;
 
-	e1355_write_reg(0x00, E1355_MISC);
+	epson1355_write_reg(par, lo, index);
+	epson1355_write_reg(par, hi, index + 1);
+}
 
-	rev = e1355_read_reg(0x00);
+static inline u32 epson1355_read_reg20(struct epson1355_par *par, int index)
+{
+	u8 b0 = epson1355_read_reg(par, index);
+	u8 b1 = epson1355_read_reg(par, index + 1);
+	u8 b2 = epson1355_read_reg(par, index + 2);
 
-	if ((rev & 0xfc) != 0x0c) {
-		printk(KERN_WARNING "Epson 1355 not detected\n");
-	}
+	return (b2 & 0x0f) << 16 | (b1 << 8) | b0;
+}
 
-	/* XXX */
-	disable_hw_cursor();
+static inline void epson1355_write_reg20(struct epson1355_par *par, u32 data, int index)
+{
+	u8 b0 = data & 0xff;
+	u8 b1 = (data >> 8) & 0xff;
+	u8 b2 = (data >> 16) & 0x0f;
 
-	e1355_encode_var(&default_var, NULL, NULL);
+	epson1355_write_reg(par, b0, index);
+	epson1355_write_reg(par, b1, index + 1);
+	epson1355_write_reg(par, b2, index + 2);
 }
 
-struct e1355_par {
-	u32 xres;
-	u32 yres;
+/* ------------------------------------------------------------------------- */
 
-	int bpp;
-	int mem_bpp;
+static void set_lut(struct epson1355_par *par, u8 index, u8 r, u8 g, u8 b)
+{
+	epson1355_write_reg(par, index, REG_LUT_ADDR);
+	epson1355_write_reg(par, r, REG_LUT_DATA);
+	epson1355_write_reg(par, g, REG_LUT_DATA);
+	epson1355_write_reg(par, b, REG_LUT_DATA);
+}
 
-	u32 panel_xres;
-	u32 panel_yres;
-	
-	int panel_width;
-	int panel_ymul;
-};
 
-static int e1355_encode_fix(struct fb_fix_screeninfo *fix,
-			    const void *raw_par,
-			    struct fb_info_gen *info)
+/**
+ *  	epson1355fb_setcolreg - sets a color register.
+ *      @regno: Which register in the CLUT we are programming
+ *      @red: The red value which can be up to 16 bits wide
+ *	@green: The green value which can be up to 16 bits wide
+ *	@blue:  The blue value which can be up to 16 bits wide.
+ *	@transp: If supported the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ *
+ *	Returns negative errno on error, or zero on success.
+ */
+static int epson1355fb_setcolreg(unsigned regno, unsigned r, unsigned g,
+				 unsigned b, unsigned transp,
+				 struct fb_info *info)
 {
-	const struct e1355_par *par = raw_par;
-	
-	memset(fix, 0, sizeof *fix);
-	
-	fix->type= FB_TYPE_PACKED_PIXELS;
-
-	if (!par)
-		BUG();
+	struct epson1355_par *par = info->par;
 
-	if (par->bpp == 1) {
-		fix->visual = FB_VISUAL_MONO10;
-	} else if (par->bpp <= 8) {
-		fix->visual = FB_VISUAL_PSEUDOCOLOR;
-	} else {
-		fix->visual = FB_VISUAL_TRUECOLOR;
-	}
+	if (info->var.grayscale)
+		r = g = b = (19595 * r + 38470 * g + 7471 * b) >> 16;
 
-	return 0;
-}
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		if (regno >= 16)
+			return -EINVAL;
 
-static int e1355_set_bpp(struct e1355_par *par, int bpp)
-{
-	int code;
-	u8 disp;
-	u16 bytes_per_line;
-
-	switch(bpp) {
-	case 1:
-		code = 0; break;
-	case 2:
-		code = 1; break;
-	case 4:
-		code = 2; break;
-	case 8:
-		code = 3; break;
-	case 16:
-		code = 5; break;
-	default:
-		return -EINVAL; break;
-	}
+		((u32 *) info->pseudo_palette)[regno] =
+		    (r & 0xf800) | (g & 0xfc00) >> 5 | (b & 0xf800) >> 11;
 
-	disp = e1355_read_reg(E1355_DISPLAY);
-	disp &= ~0x1c;
-	disp |= code << 2;
-	e1355_write_reg(disp, E1355_DISPLAY);
-	
-	bytes_per_line = (par->xres * bpp) >> 3;
-	
-	e1355_write_reg16(bytes_per_line, 0x16);
+		break;
+	case FB_VISUAL_PSEUDOCOLOR:
+		if (regno >= 256)
+			return -EINVAL;
 
-	par->bpp = bpp;
+		set_lut(par, regno, r >> 8, g >> 8, b >> 8);
 
+		break;
+	default:
+		return -ENOSYS;
+	}
 	return 0;
 }
-		
-static int e1355_decode_var(const struct fb_var_screeninfo *var,
-			    void *raw_par,
-			    struct fb_info_gen *info)
+
+/* ------------------------------------------------------------------------- */
+
+/**
+ *      epson1355fb_pan_display - Pans the display.
+ *      @var: frame buffer variable screen structure
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *	Pan (or wrap, depending on the `vmode' field) the display using the
+ *  	`xoffset' and `yoffset' fields of the `var' structure.
+ *  	If the values don't fit, return -EINVAL.
+ *
+ *      Returns negative errno on error, or zero on success.
+ */
+static int epson1355fb_pan_display(struct fb_var_screeninfo *var,
+				   struct fb_info *info)
 {
-	struct e1355_par *par = raw_par;
-	int ret;
+	struct epson1355_par *par = info->par;
+	u32 start;
 
-	if (!par)
-		BUG();
+	if (var->xoffset != 0)	/* not yet ... */
+		return -EINVAL;
 
-	/*
-	 * Don't allow setting any of these yet: xres and yres don't
-	 * make sense for LCD panels; xres_virtual and yres_virtual
-	 * should be supported fine by our hardware though.
-	 */
-	if (var->xres != par->xres ||
-	    var->yres != par->yres ||
-	    var->xres != var->xres_virtual ||
-	    var->yres != var->yres_virtual ||
-	    var->xoffset != 0 ||
-	    var->yoffset != 0)
+	if (var->yoffset + info->var.yres > info->var.yres_virtual)
 		return -EINVAL;
 
-	if(var->bits_per_pixel != par->bpp) {
-		ret = e1355_set_bpp(par, var->bits_per_pixel);
+	start = (info->fix.line_length >> 1) * var->yoffset;
+
+	epson1355_write_reg20(par, start, REG_SCRN1_DISP_START_ADDR0);
 
-		if (ret)
-			goto out_err;
-	}
-		
 	return 0;
+}
 
- out_err:
-	return ret;
+/* ------------------------------------------------------------------------- */
+
+static void lcd_enable(struct epson1355_par *par, int enable)
+{
+	u8 mode = epson1355_read_reg(par, REG_DISPLAY_MODE);
+
+	if (enable)
+		mode |= 1;
+	else
+		mode &= ~1;
+
+	epson1355_write_reg(par, mode, REG_DISPLAY_MODE);
 }
 
-static void dump_panel_data(void)
+#if defined(CONFIG_ARCH_CEIVA)
+static void backlight_enable(int enable)
+{
+	/* ### this should be protected by a spinlock ... */
+	u8 pddr = clps_readb(PDDR);
+	if (enable)
+		pddr |= (1 << 5);
+	else
+		pddr &= ~(1 << 5);
+	clps_writeb(pddr, PDDR);
+}
+#else
+static void backlight_enable(int enable)
 {
-	u8 panel = e1355_read_reg(E1355_PANEL);
-	int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 16, -1 } };
-
-	printk("%s %s %s panel, width %d bits\n",
-	       panel & 2 ? "dual" : "single",
-	       panel & 4 ? "color" : "mono",
-	       panel & 1 ? "TFT" : "passive",
-	       width[panel&1][(panel>>4)&3]);
-
-	printk("resolution %d x %d\n",
-	       (e1355_read_reg(0x04) + 1) * 8,
-	       ((e1355_read_reg16(0x08) + 1) * (1 + ((panel & 3) == 2))));
 }
+#endif
+
 
-static int e1355_bpp_to_var(int bpp, struct fb_var_screeninfo *var)
+/**
+ *      epson1355fb_blank - blanks the display.
+ *      @blank_mode: the blank mode we want.
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *      Blank the screen if blank_mode != 0, else unblank. Return 0 if
+ *      blanking succeeded, != 0 if un-/blanking failed due to e.g. a
+ *      video mode which doesn't support it. Implements VESA suspend
+ *      and powerdown modes on hardware that supports disabling hsync/vsync:
+ *      blank_mode == 2: suspend vsync
+ *      blank_mode == 3: suspend hsync
+ *      blank_mode == 4: powerdown
+ *
+ *      Returns negative errno on error, or zero on success.
+ *
+ */
+static int epson1355fb_blank(int blank_mode, struct fb_info *info)
 {
-	switch(bpp) {
-	case 1:
-	case 2:
-	case 4:
-	case 8:
-		var->bits_per_pixel = bpp;
-		var->red.offset = var->green.offset = var->blue.offset = 0;
-		var->red.length = var->green.length = var->blue.length = bpp;
+	struct epson1355_par *par = info->par;
+
+	switch (blank_mode) {
+	case VESA_NO_BLANKING:
+		lcd_enable(par, 1);
+		backlight_enable(1);
 		break;
-	case 16:
-		var->bits_per_pixel = 16;
-		var->red.offset = 11;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 6;
-		var->blue.offset = 0;
-		var->blue.length = 5;
+	case VESA_VSYNC_SUSPEND:
+	case VESA_HSYNC_SUSPEND:
+		backlight_enable(0);
+		break;
+	case VESA_POWERDOWN:
+		backlight_enable(0);
+		lcd_enable(par, 0);
 		break;
+	default:
+		return -EINVAL;
 	}
-
 	return 0;
 }
 
-static int e1355_encode_var(struct fb_var_screeninfo *var, const void *raw_par,
-			    struct fb_info_gen *info)
-{
-	u8 panel, display;
-	u32 xres, xres_virtual, yres;
-	static int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 16, -1 } };
-	static int bpp_tab[8] = { 1, 2, 4, 8, 15, 16 };
-	int bpp, hw_bpp;
-	int is_color, is_dual, is_tft;
-	int lcd_enabled, crt_enabled;
+/* ------------------------------------------------------------------------- */
 
-	panel = e1355_read_reg(E1355_PANEL);
-	display = e1355_read_reg(E1355_DISPLAY);
+/*
+ * We can't use the cfb generic routines, as we have to limit
+ * ourselves to 16-bit or 8-bit loads and stores to this 16-bit
+ * chip.
+ */
 
-	is_color = (panel & 0x04) != 0;
-	is_dual  = (panel & 0x02) != 0;
-	is_tft   = (panel & 0x01) != 0;
+static inline void epson1355fb_fb_writel(unsigned long v, unsigned long *a)
+{
+	u16 *p = (u16 *) a;
+	u16 l = v & 0xffff;
+	u16 h = v >> 16;
 
-	bpp = bpp_tab[(display>>2)&7]; 
-	e1355_bpp_to_var(bpp, var);
+	fb_writew(l, p);
+	fb_writew(h, p + 1);
+}
 
-	crt_enabled = (display & 0x02) != 0;
-	lcd_enabled = (display & 0x02) != 0;
+static inline unsigned long epson1355fb_fb_readl(const unsigned long *a)
+{
+	const u16 *p = (u16 *) a;
+	u16 l = fb_readw(p);
+	u16 h = fb_readw(p + 1);
 
-	hw_bpp = width[is_tft][(panel>>4)&3];
+	return (h << 16) | l;
+}
 
-	xres = e1355_read_reg(0x04) + 1;
-	yres = e1355_read_reg16(0x08) + 1;
-	
-	xres *= 8;
-	/* talk about weird hardware .. */
-	yres *= (is_dual && !crt_enabled) ? 2 : 1;
+#define FB_READL epson1355fb_fb_readl
+#define FB_WRITEL epson1355fb_fb_writel
 
-	xres_virtual = e1355_read_reg16(0x16);
-	/* it's in 2-byte words initially */
-	xres_virtual *= 16;
-	xres_virtual /= var->bits_per_pixel;
+/* ------------------------------------------------------------------------- */
 
-	var->xres = xres;
-	var->yres = yres;
-	var->xres_virtual = xres_virtual;
-	var->yres_virtual = yres;
+static inline unsigned long copy_from_user16(void *to, const void *from,
+					     unsigned long n)
+{
+	u16 *dst = (u16 *) to;
+	u16 *src = (u16 *) from;
 
-	var->xoffset = var->yoffset = 0;
+	if (!access_ok(VERIFY_READ, from, n))
+		return n;
 
-	var->grayscale = !is_color;
-	
-	return 0;
-}
+	while (n > 1) {
+		u16 v;
+		if (__get_user(v, src))
+			return n;
 
-#define is_dual(panel) (((panel)&3)==2)
+		fb_writew(v, dst);
 
-static void get_panel_data(struct e1355_par *par)
-{
-	u8 panel;
-	int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 16, -1 } };
+		src++, dst++;
+		n -= 2;
+	}
 
-	panel = e1355_read_reg(E1355_PANEL);
+	if (n) {
+		u8 v;
 
-	par->panel_width = width[panel&1][(panel>>4)&3];
-	par->panel_xres = (e1355_read_reg(0x04) + 1) * 8;
-	par->panel_ymul = is_dual(panel) ? 2 : 1;
-	par->panel_yres = ((e1355_read_reg16(0x08) + 1)
-			   * par->panel_ymul);
+		if (__get_user(v, ((u8 *) src)))
+			return n;
+
+		fb_writeb(v, dst);
+	}
+	return 0;
 }
 
-static void e1355_get_par(void *raw_par, struct fb_info_gen *info)
+static inline unsigned long copy_to_user16(void *to, const void *from,
+					   unsigned long n)
 {
-	struct e1355_par *par = raw_par;
+	u16 *dst = (u16 *) to;
+	u16 *src = (u16 *) from;
 
-	get_panel_data(par);
-}
+	if (!access_ok(VERIFY_WRITE, to, n))
+		return n;
 
-static void e1355_set_par(const void *par, struct fb_info_gen *info)
-{
-}
+	while (n > 1) {
+		u16 v = fb_readw(src);
 
-static int e1355_getcolreg(unsigned regno, unsigned *red, unsigned *green,
-			   unsigned *blue, unsigned *transp,
-			   struct fb_info *info)
-{
-	u8 r, g, b;
+		if (__put_user(v, dst))
+			return n;
 
-	e1355_write_reg(regno, E1355_LUT_INDEX);
-	r = e1355_read_reg(E1355_LUT_DATA);
-	g = e1355_read_reg(E1355_LUT_DATA);
-	b = e1355_read_reg(E1355_LUT_DATA);
+		src++, dst++;
+		n -= 2;
+	}
 
-	*red = r << 8;
-	*green = g << 8;
-	*blue = b << 8;
+	if (n) {
+		u8 v = fb_readb(src);
 
+		if (__put_user(v, ((u8 *) dst)))
+			return n;
+	}
 	return 0;
 }
 
-static int e1355fb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			     unsigned blue, unsigned transp,
-			     struct fb_info *info)
+
+static ssize_t
+epson1355fb_read(struct file *file, char *buf, size_t count, loff_t * ppos)
 {
-	u8 r = (red >> 8) & 0xf0;
-	u8 g = (green>>8) & 0xf0;
-	u8 b = (blue>> 8) & 0xf0;
-
-	e1355_write_reg(regno, E1355_LUT_INDEX);
-	e1355_write_reg(r, E1355_LUT_DATA);
-	e1355_write_reg(g, E1355_LUT_DATA);
-	e1355_write_reg(b, E1355_LUT_DATA);
-	
-	return 0;
+	struct inode *inode = file->f_dentry->d_inode;
+	int fbidx = iminor(inode);
+	struct fb_info *info = registered_fb[fbidx];
+	unsigned long p = *ppos;
+
+	/* from fbmem.c except for our own copy_*_user */
+	if (!info || !info->screen_base)
+		return -ENODEV;
+
+	if (p >= info->fix.smem_len)
+		return 0;
+	if (count >= info->fix.smem_len)
+		count = info->fix.smem_len;
+	if (count + p > info->fix.smem_len)
+		count = info->fix.smem_len - p;
+
+	if (count) {
+		char *base_addr;
+
+		base_addr = info->screen_base;
+		count -= copy_to_user16(buf, base_addr + p, count);
+		if (!count)
+			return -EFAULT;
+		*ppos += count;
+	}
+	return count;
 }
 
-static int e1355_pan_display(const struct fb_var_screeninfo *var,
-			     struct fb_info_gen *info)
+static ssize_t
+epson1355fb_write(struct file *file, const char *buf,
+		  size_t count, loff_t * ppos)
 {
-	BUG();
-	
-	return -EINVAL;
-}
+	struct inode *inode = file->f_dentry->d_inode;
+	int fbidx = iminor(inode);
+	struct fb_info *info = registered_fb[fbidx];
+	unsigned long p = *ppos;
+	int err;
+
+	/* from fbmem.c except for our own copy_*_user */
+	if (!info || !info->screen_base)
+		return -ENODEV;
+
+	/* from fbmem.c except for our own copy_*_user */
+	if (p > info->fix.smem_len)
+		return -ENOSPC;
+	if (count >= info->fix.smem_len)
+		count = info->fix.smem_len;
+	err = 0;
+	if (count + p > info->fix.smem_len) {
+		count = info->fix.smem_len - p;
+		err = -ENOSPC;
+	}
 
-/*
- * The AERO_HACKS parts disable/enable the backlight on the Compaq Aero 8000.
- * I'm not sure they aren't dangerous to the hardware, so be warned.
- */
-#undef AERO_HACKS
+	if (count) {
+		char *base_addr;
 
-static int e1355_blank(int blank_mode, struct fb_info_gen *info)
-{
-	u8 disp;
+		base_addr = info->screen_base;
+		count -= copy_from_user16(base_addr + p, buf, count);
+		*ppos += count;
+		err = -EFAULT;
+	}
+	if (count)
+		return count;
+	return err;
+}
 
-	switch (blank_mode) {
-	case VESA_NO_BLANKING:
-		disp = e1355_read_reg(E1355_DISPLAY);
-		disp |= 1;
-		e1355_write_reg(disp, E1355_DISPLAY);
- 		
-#ifdef AERO_HACKS
-		e1355_write_reg(0x6, 0x20);
-#endif
-		break;
+/* ------------------------------------------------------------------------- */
+
+static struct fb_ops epson1355fb_fbops = {
+	.owner 		= THIS_MODULE,
+	.fb_setcolreg 	= epson1355fb_setcolreg,
+	.fb_pan_display = epson1355fb_pan_display,
+	.fb_blank 	= epson1355fb_blank,
+	.fb_fillrect 	= cfb_fillrect,
+	.fb_copyarea 	= cfb_copyarea,
+	.fb_imageblit 	= cfb_imageblit,
+	.fb_read 	= epson1355fb_read,
+	.fb_write 	= epson1355fb_write,
+	.fb_cursor 	= soft_cursor,
+};
 
-	case VESA_VSYNC_SUSPEND:
-	case VESA_HSYNC_SUSPEND:
-	case VESA_POWERDOWN:
-		disp = e1355_read_reg(E1355_DISPLAY);
-		disp &= ~1;
-		e1355_write_reg(disp, E1355_DISPLAY);
+/* ------------------------------------------------------------------------- */
 
-#ifdef AERO_HACKS
-		e1355_write_reg(0x0, 0x20);
-#endif
-		break;
+static __init unsigned int get_fb_size(struct fb_info *info)
+{
+	unsigned int size = 2 * 1024 * 1024;
+	char *p = info->screen_base;
 
-	default:
-		return -EINVAL;
-	}
+	/* the 512k framebuffer is aliased at start + 0x80000 * n */
+	fb_writeb(1, p);
+	fb_writeb(0, p + 0x80000);
+	if (!fb_readb(p))
+		size = 512 * 1024;
 
-	return 0;
+	fb_writeb(0, p);
+
+	return size;
 }
 
-static struct display_switch e1355_dispsw;
+static int epson1355_width_tab[2][4] __initdata =
+    { {4, 8, 16, -1}, {9, 12, 16, -1} };
+static int epson1355_bpp_tab[8] __initdata = { 1, 2, 4, 8, 15, 16 };
 
-static void e1355_set_disp(const void *unused, struct display *disp,
-			   struct fb_info_gen *info)
+static void __init fetch_hw_state(struct fb_info *info, struct epson1355_par *par)
 {
-	struct display_switch *d;
+	struct fb_var_screeninfo *var = &info->var;
+	struct fb_fix_screeninfo *fix = &info->fix;
+	u8 panel, display;
+	u16 offset;
+	u32 xres, yres;
+	u32 xres_virtual, yres_virtual;
+	int bpp, lcd_bpp;
+	int is_color, is_dual, is_tft;
+	int lcd_enabled, crt_enabled;
 
-	disp->dispsw = &e1355_dispsw;
-	
-	switch(disp->var.bits_per_pixel) {
-#ifdef FBCON_HAS_MFB
-	case 1:
-		d = &fbcon_mfb; break;
-#endif	       
-#ifdef FBCON_HAS_CFB8
+	fix->type = FB_TYPE_PACKED_PIXELS;
+
+	display = epson1355_read_reg(par, REG_DISPLAY_MODE);
+	bpp = epson1355_bpp_tab[(display >> 2) & 7];
+
+	switch (bpp) {
 	case 8:
-		d = &fbcon_cfb8; break;
-#endif
+		fix->visual = FB_VISUAL_PSEUDOCOLOR;
+		var->bits_per_pixel = 8;
+		var->red.offset = var->green.offset = var->blue.offset = 0;
+		var->red.length = var->green.length = var->blue.length = 8;
+		break;
+	case 16:
+		/* 5-6-5 RGB */
+		fix->visual = FB_VISUAL_TRUECOLOR;
+		var->bits_per_pixel = 16;
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		break;
 	default:
-		BUG(); break;
+		BUG();
 	}
+	fb_alloc_cmap(&(info->cmap), 256, 0);
 
-	memcpy(&e1355_dispsw, d, sizeof *d);
+	panel = epson1355_read_reg(par, REG_PANEL_TYPE);
+	is_color = (panel & 0x04) != 0;
+	is_dual = (panel & 0x02) != 0;
+	is_tft = (panel & 0x01) != 0;
+	crt_enabled = (display & 0x02) != 0;
+	lcd_enabled = (display & 0x01) != 0;
+	lcd_bpp = epson1355_width_tab[is_tft][(panel >> 4) & 3];
 
-	/* reading is terribly slow for us */
-#if 0 /* XXX: need to work out why this doesn't work */
-	e1355_dispsw.bmove = fbcon_redraw_bmove;
-#endif
-}
+	xres = (epson1355_read_reg(par, REG_HORZ_DISP_WIDTH) + 1) * 8;
+	yres = (epson1355_read_reg16(par, REG_VERT_DISP_HEIGHT0) + 1) *
+	    ((is_dual && !crt_enabled) ? 2 : 1);
+	offset = epson1355_read_reg16(par, REG_MEM_ADDR_OFFSET0) & 0x7ff;
+	xres_virtual = offset * 16 / bpp;
+	yres_virtual = fix->smem_len / (offset * 2);
 
-/* ------------ Interfaces to hardware functions ------------ */
+	var->xres = xres;
+	var->yres = yres;
+	var->xres_virtual = xres_virtual;
+	var->yres_virtual = yres_virtual;
+	var->xoffset = var->yoffset = 0;
 
+	fix->line_length = offset * 2;
 
-struct fbgen_hwswitch e1355_switch = {
-	.detect =	e1355_detect,
-	.encode_fix =	e1355_encode_fix,
-	.decode_var =	e1355_decode_var,
-	.encode_var =	e1355_encode_var,
-	.get_par =	e1355_get_par,
-	.set_par =	e1355_set_par,
-	.getcolreg =	e1355_getcolreg,
-	.pan_display =	e1355_pan_display,
-	.blank =	e1355_blank,
-	.set_disp =	e1355_set_disp,
-};
+	fix->xpanstep = 0;	/* no pan yet */
+	fix->ypanstep = 1;
+	fix->ywrapstep = 0;
+	fix->accel = FB_ACCEL_NONE;
+
+	var->grayscale = !is_color;
 
+#ifdef DEBUG
+	printk(KERN_INFO
+	       "epson1355fb: xres=%d, yres=%d, "
+	       "is_color=%d, is_dual=%d, is_tft=%d\n",
+	       xres, yres, is_color, is_dual, is_tft);
+	printk(KERN_INFO
+	       "epson1355fb: bpp=%d, lcd_bpp=%d, "
+	       "crt_enabled=%d, lcd_enabled=%d\n",
+	       bpp, lcd_bpp, crt_enabled, lcd_enabled);
+#endif
+}
 
-/* ------------ Hardware Independent Functions ------------ */
 
+static void clearfb16(struct fb_info *info)
+{
+	u16 *dst = (u16 *) info->screen_base;
+	unsigned long n = info->fix.smem_len;
 
-static struct fb_ops e1355fb_ops = {
-	.owner =	THIS_MODULE,
-	.fb_get_fix =	fbgen_get_fix,
-	.fb_get_var =	fbgen_get_var,
-	.fb_set_var =	fbgen_set_var,
-	.fb_get_cmap =	fbgen_get_cmap,
-	.fb_set_cmap =	gen_set_cmap,
-	.fb_setcolreg =	e1355fb_setcolreg,
-	.fb_pan_display =fbgen_pan_display,
-	.fb_blank =	fbgen_blank,
-};
+	while (n > 1) {
+		fb_writew(0, dst);
+		dst++, n -= 2;
+	}
 
-static struct e1355fb_info fb_info;
+	if (n)
+		fb_writeb(0, dst);
+}
 
-int __init e1355fb_setup(char *str)
+static void epson1355fb_platform_release(struct device *device)
 {
-	return 0;
 }
 
-int __init e1355fb_init(void)
+static int epson1355fb_remove(struct device *device)
 {
-	fb_info.gen.fbhw = &e1355_switch;
-	fb_info.gen.fbhw->detect();
-	strcpy(fb_info.gen.info.modename, "SED1355");
-	fb_info.gen.info.changevar = NULL;
-	fb_info.gen.info.fbops = &e1355fb_ops;
-	fb_info.gen.info.screen_base = (void *)E1355_FB_BASE;
-	fb_info.gen.currcon = -1;
-	fb_info.gen.info.disp = &disp;
-	fb_info.gen.parsize = sizeof(struct e1355_par);
-	fb_info.gen.info.switch_con = &fbgen_switch;
-	fb_info.gen.info.updatevar = &fbgen_update_var;
-	fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
-	/* This should give a reasonable default video mode */
-	fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
-	fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
-	fbgen_set_disp(-1, &fb_info.gen);
-	if (disp.var.bits_per_pixel > 1) 
-		do_install_cmap(0, &fb_info.gen);
-	if (register_framebuffer(&fb_info.gen.info) < 0)
-		return -EINVAL;
-	printk(KERN_INFO "fb%d: %s frame buffer device\n", fb_info.gen.info.node,
-	       fb_info.gen.info.modename);
+	struct fb_info *info = dev_get_drvdata(device);
+	struct epson1355_par *par = info->par;
+
+	backlight_enable(0);
+	if (par) {
+		lcd_enable(par, 0);
+		if (par && par->reg_addr)
+			iounmap((void *) par->reg_addr);
+	}
 
+	if (info) {
+		fb_dealloc_cmap(&info->cmap);
+		if (info->screen_base)
+			iounmap(info->screen_base);
+		framebuffer_release(info);
+	}
+	release_mem_region(EPSON1355FB_FB_PHYS, EPSON1355FB_FB_LEN);
+	release_mem_region(EPSON1355FB_REGS_PHYS, EPSON1355FB_REGS_LEN);
 	return 0;
 }
 
+int __init epson1355fb_probe(struct device *device)
+{
+	struct platform_device *dev = to_platform_device(device);
+	struct epson1355_par *default_par;
+	struct fb_info *info;
+	u8 revision;
+	int rc = 0;
+
+	if (!request_mem_region(EPSON1355FB_REGS_PHYS, EPSON1355FB_REGS_LEN, "S1D13505 registers")) {
+		printk(KERN_ERR "epson1355fb: unable to reserve "
+		       "registers at 0x%0x\n", EPSON1355FB_REGS_PHYS);
+		rc = -EBUSY;
+		goto bail;
+	}
+
+	if (!request_mem_region(EPSON1355FB_FB_PHYS, EPSON1355FB_FB_LEN,
+				"S1D13505 framebuffer")) {
+		printk(KERN_ERR "epson1355fb: unable to reserve "
+		       "framebuffer at 0x%0x\n", EPSON1355FB_FB_PHYS);
+		rc = -EBUSY;
+		goto bail;
+	}
 
-    /*
-     *  Cleanup
-     */
+	info = framebuffer_alloc(sizeof(struct epson1355_par) + sizeof(u32) * 256, &dev->dev);
+	if (!info)
+		rc = -ENOMEM;
+		goto bail;
+
+	default_par = info->par;
+	default_par->reg_addr = (unsigned long) ioremap(EPSON1355FB_REGS_PHYS, EPSON1355FB_REGS_LEN);
+	if (!default_par->reg_addr) {
+		printk(KERN_ERR "epson1355fb: unable to map registers\n");
+		rc = -ENOMEM;
+		goto bail;
+	}
+	info->pseudo_palette = (void *)(default_par + 1);
 
-void e1355fb_cleanup(struct fb_info *info)
-{
+	info->screen_base = ioremap(EPSON1355FB_FB_PHYS, EPSON1355FB_FB_LEN);
+	if (!info->screen_base) {
+		printk(KERN_ERR "epson1355fb: unable to map framebuffer\n");
+		rc = -ENOMEM;
+		goto bail;
+	}
+
+	revision = epson1355_read_reg(default_par, REG_REVISION_CODE);
+	if ((revision >> 2) != 3) {
+		printk(KERN_INFO "epson1355fb: epson1355 not found\n");
+		rc = -ENODEV;
+		goto bail;
+	}
+
+	info->fix.mmio_start = EPSON1355FB_REGS_PHYS;
+	info->fix.mmio_len = EPSON1355FB_REGS_LEN;
+	info->fix.smem_start = EPSON1355FB_FB_PHYS;
+	info->fix.smem_len = get_fb_size(info);
+
+	printk(KERN_INFO "epson1355fb: regs mapped at 0x%lx, fb %d KiB mapped at 0x%p\n",
+	       default_par->reg_addr, info->fix.smem_len / 1024, info->screen_base);
+
+	strcpy(info->fix.id, "S1D13505");
+	info->par = default_par;
+	info->fbops = &epson1355fb_fbops;
+	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+
+	/* we expect the boot loader to have initialized the chip
+	   with appropriate parameters from which we can determinte
+	   the flavor of lcd panel attached */
+	fetch_hw_state(info, default_par);
+
+	/* turn this puppy on ... */
+	clearfb16(info);
+	backlight_enable(1);
+	lcd_enable(default_par, 1);
+
+	if (register_framebuffer(info) < 0) {
+		rc = -EINVAL;
+		goto bail;
+	}
 	/*
-	 *  If your driver supports multiple boards, you should unregister and
-	 *  clean up all instances.
+	 * Our driver data.
 	 */
+	dev_set_drvdata(&dev->dev, info);
+
+	printk(KERN_INFO "fb%d: %s frame buffer device\n",
+	       info->node, info->fix.id);
+
+	return 0;
+
+      bail:
+	epson1355fb_remove(device);
+	return rc;
+}
+
+static struct device_driver epson1355fb_driver = {
+	.name	= "epson1355fb",
+	.bus	= &platform_bus_type,
+	.probe	= epson1355fb_probe,
+	.remove	= epson1355fb_remove,
+};
+
+static struct platform_device epson1355fb_device = {
+	.name	= "epson1355fb",
+	.id	= 0,
+	.dev	= {
+		.release = epson1355fb_platform_release,
+	}
+};
+
+int __init epson1355fb_init(void)
+{
+	int ret = 0;
+
+	if (fb_get_options("epson1355fb", NULL))
+		return -ENODEV;
+
+	ret = driver_register(&epson1355fb_driver);
+	if (!ret) {
+		ret = platform_device_register(&epson1355fb_device);
+		if (ret)
+			driver_unregister(&epson1355fb_driver);
+	}
+	return ret;
+}
+
+module_init(epson1355fb_init);
 	
-	unregister_framebuffer(info);
-	/* ... */
+#ifdef MODULE
+static void __exit epson1355fb_exit(void)
+{
+	platform_device_unregister(&epson1355fb_device);
+	driver_unregister(&epson1355fb_driver);
 }
 
+/* ------------------------------------------------------------------------- */
+
+module_exit(epson1355fb_exit);
+#endif
+
+MODULE_AUTHOR("Christopher Hoover <ch@hpl.hp.com>");
+MODULE_DESCRIPTION("Framebuffer driver for Epson S1D13505");
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 2a55e5dbf..ef5cea5a0 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -47,385 +47,34 @@
 
 #include <linux/fb.h>
 
-#ifdef CONFIG_FRAMEBUFFER_CONSOLE
-#include "console/fbcon.h"
-#endif
     /*
      *  Frame buffer device initialization and setup routines
      */
 
-extern int acornfb_init(void);
-extern int acornfb_setup(char*);
-extern int amifb_init(void);
-extern int amifb_setup(char*);
-extern int atafb_init(void);
-extern int atafb_setup(char*);
-extern int macfb_init(void);
-extern int macfb_setup(char*);
-extern int cyberfb_init(void);
-extern int cyberfb_setup(char*);
-extern int pm2fb_init(void);
-extern int pm2fb_setup(char*);
-extern int pm3fb_init(void);
-extern int pm3fb_setup(char*);
-extern int clps711xfb_init(void);
-extern int cyber2000fb_init(void);
-extern int cyber2000fb_setup(char*);
-extern int retz3fb_init(void);
-extern int retz3fb_setup(char*);
-extern int cirrusfb_init(void);
-extern int cirrusfb_setup(char*);
-extern int hitfb_init(void);
-extern int vfb_init(void);
-extern int vfb_setup(char*);
-extern int offb_init(void);
-extern int atyfb_init(void);
-extern int atyfb_setup(char*);
-extern int aty128fb_init(void);
-extern int aty128fb_setup(char*);
-extern int neofb_init(void);
-extern int neofb_setup(char*);
-extern int igafb_init(void);
-extern int igafb_setup(char*);
-extern int imsttfb_init(void);
-extern int imsttfb_setup(char*);
-extern int dnfb_init(void);
-extern int tgafb_init(void);
-extern int tgafb_setup(char*);
-extern int virgefb_init(void);
-extern int virgefb_setup(char*);
-extern int resolver_video_setup(char*);
-extern int s3triofb_init(void);
-extern int vesafb_init(void);
-extern int vesafb_setup(char*);
-extern int vga16fb_init(void);
-extern int vga16fb_setup(char*);
-extern int hgafb_init(void);
-extern int hgafb_setup(char*);
-extern int matroxfb_init(void);
-extern int matroxfb_setup(char*);
-extern int hpfb_init(void);
-extern int platinumfb_init(void);
-extern int platinumfb_setup(char*);
-extern int control_init(void);
-extern int control_setup(char*);
-extern int valkyriefb_init(void);
-extern int valkyriefb_setup(char*);
-extern int chips_init(void);
-extern int g364fb_init(void);
-extern int sa1100fb_init(void);
-extern int pxafb_init(void);
-extern int pxafb_setup(char*);
-extern int fm2fb_init(void);
-extern int fm2fb_setup(char*);
-extern int q40fb_init(void);
-extern int sun3fb_init(void);
-extern int sun3fb_setup(char *);
-extern int sgivwfb_init(void);
-extern int sgivwfb_setup(char*);
-extern int gbefb_init(void);
-extern int gbefb_setup(char*);
-extern int rivafb_init(void);
-extern int rivafb_setup(char*);
-extern int tdfxfb_init(void);
-extern int tdfxfb_setup(char*);
-extern int tridentfb_init(void);
-extern int tridentfb_setup(char*);
-extern int sisfb_init(void);
-extern int sisfb_setup(char*);
-extern int stifb_init(void);
-extern int stifb_setup(char*);
-extern int pmagbafb_init(void);
-extern int pmagbbfb_init(void);
-extern int maxinefb_init(void);
-extern int tx3912fb_init(void);
-extern int tx3912fb_setup(char*);
-extern int radeonfb_init(void);
-extern int radeonfb_setup(char*);
-extern int radeonfb_old_init(void);
-extern int radeonfb_old_setup(char*);
-extern int e1355fb_init(void);
-extern int e1355fb_setup(char*);
-extern int pvr2fb_init(void);
-extern int pvr2fb_setup(char*);
-extern int sstfb_init(void);
-extern int sstfb_setup(char*);
-extern int i810fb_init(void);
-extern int i810fb_setup(char*);
-extern int ffb_init(void);
-extern int ffb_setup(char*);
-extern int cg6_init(void);
-extern int cg6_setup(char*);
-extern int cg3_init(void);
-extern int cg3_setup(char*);
-extern int bw2_init(void);
-extern int bw2_setup(char*);
-extern int cg14_init(void);
-extern int cg14_setup(char*);
-extern int p9100_init(void);
-extern int p9100_setup(char*);
-extern int tcx_init(void);
-extern int tcx_setup(char*);
-extern int leo_init(void);
-extern int leo_setup(char*);
-extern int kyrofb_init(void);
-extern int kyrofb_setup(char*);
-extern int mc68x328fb_init(void);
-extern int mc68x328fb_setup(char *);
-extern int asiliantfb_init(void);
-
-static struct {
-	const char *name;
-	int (*init)(void);
-	int (*setup)(char*);
-} fb_drivers[] __initdata = {
-
-	/*
-	 * Chipset specific drivers that use resource management
-	 */
-#ifdef CONFIG_FB_RETINAZ3
-	{ "retz3fb", retz3fb_init, retz3fb_setup },
-#endif
-#ifdef CONFIG_FB_AMIGA
-	{ "amifb", amifb_init, amifb_setup },
-#endif
-#ifdef CONFIG_FB_CLPS711X
-	{ "clps711xfb", clps711xfb_init, NULL },
-#endif
-#ifdef CONFIG_FB_CYBER
-	{ "cyberfb", cyberfb_init, cyberfb_setup },
-#endif
-#ifdef CONFIG_FB_CYBER2000
-	{ "cyber2000fb", cyber2000fb_init, cyber2000fb_setup },
-#endif
-#ifdef CONFIG_FB_PM2
-	{ "pm2fb", pm2fb_init, pm2fb_setup },
-#endif
-#ifdef CONFIG_FB_PM3
-	{ "pm3fb", pm3fb_init, pm3fb_setup },
-#endif           
-#ifdef CONFIG_FB_CIRRUS
-	{ "cirrusfb", cirrusfb_init, cirrusfb_setup },
-#endif
-#ifdef CONFIG_FB_ATY
-	{ "atyfb", atyfb_init, atyfb_setup },
-#endif
-#ifdef CONFIG_FB_MATROX
-	{ "matroxfb", matroxfb_init, matroxfb_setup },
-#endif
-#ifdef CONFIG_FB_ATY128
-	{ "aty128fb", aty128fb_init, aty128fb_setup },
-#endif
-#ifdef CONFIG_FB_NEOMAGIC
-	{ "neofb", neofb_init, neofb_setup },
-#endif
-#ifdef CONFIG_FB_VIRGE
-	{ "virgefb", virgefb_init, virgefb_setup },
-#endif
-#ifdef CONFIG_FB_RIVA
-	{ "rivafb", rivafb_init, rivafb_setup },
-#endif
-#ifdef CONFIG_FB_3DFX
-	{ "tdfxfb", tdfxfb_init, tdfxfb_setup },
-#endif
-#ifdef CONFIG_FB_RADEON
-	{ "radeonfb", radeonfb_init, radeonfb_setup },
-#endif
-#ifdef CONFIG_FB_RADEON_OLD
-	{ "radeonfb_old", radeonfb_old_init, radeonfb_old_setup },
-#endif
-#ifdef CONFIG_FB_CONTROL
-	{ "controlfb", control_init, control_setup },
-#endif
-#ifdef CONFIG_FB_PLATINUM
-	{ "platinumfb", platinumfb_init, platinumfb_setup },
-#endif
-#ifdef CONFIG_FB_VALKYRIE
-	{ "valkyriefb", valkyriefb_init, valkyriefb_setup },
-#endif
-#ifdef CONFIG_FB_CT65550
-	{ "chipsfb", chips_init, NULL },
-#endif
-#ifdef CONFIG_FB_IMSTT
-	{ "imsttfb", imsttfb_init, imsttfb_setup },
-#endif
-#ifdef CONFIG_FB_S3TRIO
-	{ "s3triofb", s3triofb_init, NULL },
-#endif 
-#ifdef CONFIG_FB_FM2
-	{ "fm2fb", fm2fb_init, fm2fb_setup },
-#endif 
-#ifdef CONFIG_FB_SIS
-	{ "sisfb", sisfb_init, sisfb_setup },
-#endif
-#ifdef CONFIG_FB_TRIDENT
-	{ "tridentfb", tridentfb_init, tridentfb_setup },
-#endif
-#ifdef CONFIG_FB_I810
-	{ "i810fb", i810fb_init, i810fb_setup },
-#endif	
-#ifdef CONFIG_FB_STI
-	{ "stifb", stifb_init, stifb_setup },
-#endif
-#ifdef CONFIG_FB_FFB
-	{ "ffb", ffb_init, ffb_setup },
-#endif
-#ifdef CONFIG_FB_CG6
-	{ "cg6fb", cg6_init, cg6_setup },
-#endif
-#ifdef CONFIG_FB_CG3
-	{ "cg3fb", cg3_init, cg3_setup },
-#endif
-#ifdef CONFIG_FB_BW2
-	{ "bw2fb", bw2_init, bw2_setup },
-#endif
-#ifdef CONFIG_FB_CG14
-	{ "cg14fb", cg14_init, cg14_setup },
-#endif
-#ifdef CONFIG_FB_P9100
-	{ "p9100fb", p9100_init, p9100_setup },
-#endif
-#ifdef CONFIG_FB_TCX
-	{ "tcxfb", tcx_init, tcx_setup },
-#endif
-#ifdef CONFIG_FB_LEO
-	{ "leofb", leo_init, leo_setup },
-#endif
-
-	/*
-	 * Generic drivers that are used as fallbacks
-	 * 
-	 * These depend on resource management and must be initialized
-	 * _after_ all other frame buffer devices that use resource
-	 * management!
-	 */
-
-#ifdef CONFIG_FB_OF
-	{ "offb", offb_init, NULL },
-#endif
-#ifdef CONFIG_FB_VESA
-	{ "vesafb", vesafb_init, vesafb_setup },
-#endif 
-
-	/*
-	 * Chipset specific drivers that don't use resource management (yet)
-	 */
-
-#ifdef CONFIG_FB_SGIVW
-	{ "sgivwfb", sgivwfb_init, sgivwfb_setup },
-#endif
-#ifdef CONFIG_FB_GBE
-	{ "gbefb", gbefb_init, gbefb_setup },
-#endif
-#ifdef CONFIG_FB_ACORN
-	{ "acornfb", acornfb_init, acornfb_setup },
-#endif
-#ifdef CONFIG_FB_ATARI
-	{ "atafb", atafb_init, atafb_setup },
-#endif
-#ifdef CONFIG_FB_MAC
-	{ "macfb", macfb_init, macfb_setup },
-#endif
-#ifdef CONFIG_FB_HGA
-	{ "hgafb", hgafb_init, hgafb_setup },
-#endif 
-#ifdef CONFIG_FB_IGA
-	{ "igafb", igafb_init, igafb_setup },
-#endif
-#ifdef CONFIG_APOLLO
-	{ "apollofb", dnfb_init, NULL },
-#endif
-#ifdef CONFIG_FB_Q40
-	{ "q40fb", q40fb_init, NULL },
-#endif
-#ifdef CONFIG_FB_TGA
-	{ "tgafb", tgafb_init, tgafb_setup },
-#endif
-#ifdef CONFIG_FB_HP300
-	{ "hpfb", hpfb_init, NULL },
-#endif 
-#ifdef CONFIG_FB_G364
-	{ "g364fb", g364fb_init, NULL },
-#endif
-#ifdef CONFIG_FB_SA1100
-	{ "sa1100fb", sa1100fb_init, NULL },
-#endif
-#ifdef CONFIG_FB_PXA
-	{ "pxafb", pxafb_init, pxafb_setup },
-#endif
-#ifdef CONFIG_FB_SUN3
-	{ "sun3fb", sun3fb_init, sun3fb_setup },
-#endif
-#ifdef CONFIG_FB_HIT
-	{ "hitfb", hitfb_init, NULL },
-#endif
-#ifdef CONFIG_FB_TX3912
-	{ "tx3912fb", tx3912fb_init, tx3912fb_setup },
-#endif
-#ifdef CONFIG_FB_E1355
-	{ "e1355fb", e1355fb_init, e1355fb_setup },
-#endif
-#ifdef CONFIG_FB_PVR2
-	{ "pvr2fb", pvr2fb_init, pvr2fb_setup },
-#endif
-#ifdef CONFIG_FB_PMAG_BA
-	{ "pmagbafb", pmagbafb_init, NULL },
-#endif          
-#ifdef CONFIG_FB_PMAGB_B
-	{ "pmagbbfb", pmagbbfb_init, NULL },
-#endif
-#ifdef CONFIG_FB_MAXINE
-	{ "maxinefb", maxinefb_init, NULL },
-#endif            
-#ifdef CONFIG_FB_VOODOO1
-	{ "sstfb", sstfb_init, sstfb_setup },
-#endif
-#ifdef CONFIG_FB_KYRO
-	{ "kyrofb", kyrofb_init, kyrofb_setup },
-#endif
-#ifdef CONFIG_FB_68328
-	{ "68328fb", mc68x328fb_init, mc68x328fb_setup },
-#endif
-#ifdef CONFIG_FB_ASILIANT
-	{ "asiliantfb", asiliantfb_init, NULL },
-#endif
-
-	/*
-	 * Generic drivers that don't use resource management (yet)
-	 */
-
-#ifdef CONFIG_FB_VGA16
-	{ "vga16fb", vga16fb_init, vga16fb_setup },
-#endif 
-
-#ifdef CONFIG_GSP_RESOLVER
-	/* Not a real frame buffer device... */
-	{ "resolverfb", NULL, resolver_video_setup },
-#endif
-
-#ifdef CONFIG_FB_VIRTUAL
-	/*
-	 * Vfb must be last to avoid that it becomes your primary display if
-	 * other display devices are present
-	 */
-	{ "vfb", vfb_init, vfb_setup },
-#endif
-};
-
-#define NUM_FB_DRIVERS	(sizeof(fb_drivers)/sizeof(*fb_drivers))
 #define FBPIXMAPSIZE	16384
 
-extern const char *global_mode_option;
-
-static initcall_t pref_init_funcs[FB_MAX];
-static int num_pref_init_funcs __initdata = 0;
 static struct notifier_block *fb_notifier_list;
 struct fb_info *registered_fb[FB_MAX];
 int num_registered_fb;
 
-#ifdef CONFIG_FB_OF
-static int ofonly __initdata = 0;
-#endif
+/*
+ * Helpers
+ */
+
+int fb_get_color_depth(struct fb_info *info)
+{
+	struct fb_var_screeninfo *var = &info->var;
+
+	if (var->green.length == var->blue.length &&
+	    var->green.length == var->red.length &&
+	    !var->green.offset && !var->blue.offset &&
+	    !var->red.offset)
+		return var->green.length;
+	else
+		return (var->green.length + var->red.length +
+			var->blue.length);
+}
+EXPORT_SYMBOL(fb_get_color_depth);
 
 /*
  * Drawing helpers.
@@ -646,9 +295,12 @@ static void fb_set_logo(struct fb_info *info,
 			       const struct linux_logo *logo, u8 *dst,
 			       int depth)
 {
-	int i, j, shift;
+	int i, j, k, fg = 1;
 	const u8 *src = logo->data;
-	u8 d, xor = 0;
+	u8 d, xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0;
+
+	if (fb_get_color_depth(info) == 3)
+		fg = 7;
 
 	switch (depth) {
 	case 4:
@@ -662,17 +314,14 @@ static void fb_set_logo(struct fb_info *info,
 				}
 			}
 		break;
-	case ~1:
-		xor = 0xff;
 	case 1:
 		for (i = 0; i < logo->height; i++) {
-			shift = 7;
-			d = *src++ ^ xor;
-			for (j = 0; j < logo->width; j++) {
-				*dst++ = (d >> shift) & 1;
-				shift = (shift-1) & 7;
-				if (shift == 7)
-					d = *src++ ^ xor;
+			for (j = 0; j < logo->width; src++) {
+				d = *src ^ xor;
+				for (k = 7; k >= 0; k--) {
+					*dst++ = ((d >> k) & 1) ? fg : 0;
+					j++;
+				}
 			}
 		}
 		break;
@@ -715,26 +364,35 @@ static struct logo_data {
 
 int fb_prepare_logo(struct fb_info *info)
 {
+	int depth = fb_get_color_depth(info);
+
 	memset(&fb_logo, 0, sizeof(struct logo_data));
 
-	switch (info->fix.visual) {
-	case FB_VISUAL_TRUECOLOR:
-		if (info->var.bits_per_pixel >= 8)
+	if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+		depth = info->var.blue.length;
+		if (info->var.red.length < depth)
+			depth = info->var.red.length;
+		if (info->var.green.length < depth)
+			depth = info->var.green.length;
+	}
+
+	if (depth >= 8) {
+		switch (info->fix.visual) {
+		case FB_VISUAL_TRUECOLOR:
 			fb_logo.needs_truepalette = 1;
-		break;
-	case FB_VISUAL_DIRECTCOLOR:
-		if (info->var.bits_per_pixel >= 24) {
+			break;
+		case FB_VISUAL_DIRECTCOLOR:
 			fb_logo.needs_directpalette = 1;
 			fb_logo.needs_cmapreset = 1;
+			break;
+		case FB_VISUAL_PSEUDOCOLOR:
+			fb_logo.needs_cmapreset = 1;
+			break;
 		}
-		break;
-	case FB_VISUAL_PSEUDOCOLOR:
-		fb_logo.needs_cmapreset = 1;
-		break;
 	}
 
 	/* Return if no suitable logo was found */
-	fb_logo.logo = fb_find_logo(info->var.bits_per_pixel);
+	fb_logo.logo = fb_find_logo(depth);
 	
 	if (!fb_logo.logo || fb_logo.logo->height > info->var.yres) {
 		fb_logo.logo = NULL;
@@ -761,7 +419,7 @@ int fb_show_logo(struct fb_info *info)
 	if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING)
 		return 0;
 
-	image.depth = fb_logo.depth;
+	image.depth = 8;
 	image.data = fb_logo.logo->data;
 
 	if (fb_logo.needs_cmapreset)
@@ -782,7 +440,7 @@ int fb_show_logo(struct fb_info *info)
 		info->pseudo_palette = palette;
 	}
 
-	if (fb_logo.depth == 4) {
+	if (fb_logo.depth <= 4) {
 		logo_new = kmalloc(fb_logo.logo->width * fb_logo.logo->height, 
 				   GFP_KERNEL);
 		if (logo_new == NULL) {
@@ -846,6 +504,9 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 	struct inode *inode = file->f_dentry->d_inode;
 	int fbidx = iminor(inode);
 	struct fb_info *info = registered_fb[fbidx];
+	u32 *buffer, *dst, *src;
+	int c, i, cnt = 0, err = 0;
+	unsigned long total_size;
 
 	if (!info || ! info->screen_base)
 		return -ENODEV;
@@ -856,24 +517,55 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 	if (info->fbops->fb_read)
 		return info->fbops->fb_read(file, buf, count, ppos);
 	
-	if (p >= info->fix.smem_len)
+	total_size = info->screen_size;
+	if (total_size == 0)
+		total_size = info->fix.smem_len;
+
+	if (p >= total_size)
 	    return 0;
-	if (count >= info->fix.smem_len)
-	    count = info->fix.smem_len;
-	if (count + p > info->fix.smem_len)
-		count = info->fix.smem_len - p;
+	if (count >= total_size)
+	    count = total_size;
+	if (count + p > total_size)
+		count = total_size - p;
+
+	cnt = 0;
+	buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
+			 GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	src = (u32 *) (info->screen_base + p);
+
 	if (info->fbops->fb_sync)
 		info->fbops->fb_sync(info);
-	if (count) {
-	    char *base_addr;
 
-	    base_addr = info->screen_base;
-	    count -= copy_to_user(buf, base_addr+p, count);
-	    if (!count)
-		return -EFAULT;
-	    *ppos += count;
+	while (count) {
+		c  = (count > PAGE_SIZE) ? PAGE_SIZE : count;
+		dst = buffer;
+		for (i = c >> 2; i--; )
+			*dst++ = fb_readl(src++);
+		if (c & 3) {
+			u8 *dst8 = (u8 *) dst;
+			u8 *src8 = (u8 *) src;
+
+			for (i = c & 3; i--;)
+				*dst8++ = fb_readb(src8++);
+
+			src = (u32 *) src8;
+		}
+
+		if (copy_to_user(buf, buffer, c)) {
+			err = -EFAULT;
+			break;
+		}
+		*ppos += c;
+		buf += c;
+		cnt += c;
+		count -= c;
 	}
-	return count;
+
+	kfree(buffer);
+	return (err) ? err : cnt;
 }
 
 static ssize_t
@@ -883,7 +575,9 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 	struct inode *inode = file->f_dentry->d_inode;
 	int fbidx = iminor(inode);
 	struct fb_info *info = registered_fb[fbidx];
-	int err;
+	u32 *buffer, *dst, *src;
+	int c, i, cnt = 0, err;
+	unsigned long total_size;
 
 	if (!info || !info->screen_base)
 		return -ENODEV;
@@ -894,28 +588,56 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 	if (info->fbops->fb_write)
 		return info->fbops->fb_write(file, buf, count, ppos);
 	
-	if (p > info->fix.smem_len)
+	total_size = info->screen_size;
+	if (total_size == 0)
+		total_size = info->fix.smem_len;
+
+	if (p > total_size)
 	    return -ENOSPC;
-	if (count >= info->fix.smem_len)
-	    count = info->fix.smem_len;
+	if (count >= total_size)
+	    count = total_size;
 	err = 0;
-	if (count + p > info->fix.smem_len) {
-	    count = info->fix.smem_len - p;
+	if (count + p > total_size) {
+	    count = total_size - p;
 	    err = -ENOSPC;
 	}
+	cnt = 0;
+	buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
+			 GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	dst = (u32 *) (info->screen_base + p);
+
 	if (info->fbops->fb_sync)
 		info->fbops->fb_sync(info);
-	if (count) {
-	    char *base_addr;
 
-	    base_addr = info->screen_base;
-	    count -= copy_from_user(base_addr+p, buf, count);
-	    *ppos += count;
-	    err = -EFAULT;
+	while (count) {
+		c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
+		src = buffer;
+		if (copy_from_user(src, buf, c)) {
+			err = -EFAULT;
+			break;
+		}
+		for (i = c >> 2; i--; )
+			fb_writel(*src++, dst++);
+		if (c & 3) {
+			u8 *src8 = (u8 *) src;
+			u8 *dst8 = (u8 *) dst;
+
+			for (i = c & 3; i--; )
+				fb_writeb(*src8++, dst8++);
+
+			dst = (u32 *) dst8;
+		}
+		*ppos += c;
+		buf += c;
+		cnt += c;
+		count -= c;
 	}
-	if (count)
-		return count;
-	return err;
+	kfree(buffer);
+
+	return (err) ? err : cnt;
 }
 
 #ifdef CONFIG_KMOD
@@ -942,20 +664,21 @@ fb_cursor(struct fb_info *info, struct fb_cursor_user __user *sprite)
 {
 	struct fb_cursor_user cursor_user;
 	struct fb_cursor cursor;
-	char *data = NULL, *mask = NULL;
+	char *data = NULL, *mask = NULL, *info_mask = NULL;
 	u16 *red = NULL, *green = NULL, *blue = NULL, *transp = NULL;
 	int err = -EINVAL;
 	
 	if (copy_from_user(&cursor_user, sprite, sizeof(struct fb_cursor_user)))
 		return -EFAULT;
 
-	memcpy(&cursor, &cursor_user, sizeof(cursor));
-	cursor.mask = NULL;
-	cursor.image.data = NULL;
-	cursor.image.cmap.red = NULL;
-	cursor.image.cmap.green = NULL;
-	cursor.image.cmap.blue = NULL;
-	cursor.image.cmap.transp = NULL;
+	memcpy(&cursor, &cursor_user, sizeof(cursor_user));
+	cursor.mask = info->cursor.mask;
+	cursor.image.data = info->cursor.image.data;
+	cursor.image.cmap.red = info->cursor.image.cmap.red;
+	cursor.image.cmap.green = info->cursor.image.cmap.green;
+	cursor.image.cmap.blue = info->cursor.image.cmap.blue;
+	cursor.image.cmap.transp = info->cursor.image.cmap.transp;
+	cursor.data = NULL;
 
 	if (cursor.set & FB_CUR_SETCUR)
 		info->cursor.enable = 1;
@@ -1014,6 +737,8 @@ fb_cursor(struct fb_info *info, struct fb_cursor_user __user *sprite)
 		
 		cursor.image.data = data;
 		cursor.mask = mask;
+		info_mask = (char *) info->cursor.mask;
+		info->cursor.mask = mask;
 	}
 	info->cursor.set = cursor.set;
 	info->cursor.rop = cursor.rop;
@@ -1025,6 +750,8 @@ out:
 	kfree(green);
 	kfree(blue);
 	kfree(transp);
+	if (info_mask)
+		info->cursor.mask = info_mask;
 	return err;
 }
 
@@ -1055,6 +782,30 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
 {
 	int err;
 
+	if (var->activate & FB_ACTIVATE_INV_MODE) {
+		struct fb_videomode mode1, mode2;
+		int ret = 0;
+
+		fb_var_to_videomode(&mode1, var);
+		fb_var_to_videomode(&mode2, &info->var);
+		/* make sure we don't delete the videomode of current var */
+		ret = fb_mode_is_equal(&mode1, &mode2);
+
+		if (!ret) {
+		    struct fb_event event;
+
+		    event.info = info;
+		    event.data = &mode1;
+		    ret = notifier_call_chain(&fb_notifier_list,
+					      FB_EVENT_MODE_DELETE, &event);
+		}
+
+		if (!ret)
+		    fb_delete_videomode(&mode1, &info->modelist);
+
+		return ret;
+	}
+
 	if ((var->activate & FB_ACTIVATE_FORCE) ||
 	    memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) {
 		if (!info->fbops->fb_check_var) {
@@ -1066,6 +817,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
 			return err;
 
 		if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
+			struct fb_videomode mode;
 			info->var = *var;
 
 			if (info->fbops->fb_set_par)
@@ -1075,10 +827,16 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
 
 			fb_set_cmap(&info->cmap, info);
 
+			fb_var_to_videomode(&mode, &info->var);
+			fb_add_videomode(&mode, &info->modelist);
+
 			if (info->flags & FBINFO_MISC_MODECHANGEUSER) {
+				struct fb_event event;
+
 				info->flags &= ~FBINFO_MISC_MODECHANGEUSER;
+				event.info = info;
 				notifier_call_chain(&fb_notifier_list,
-						    FB_EVENT_MODE_CHANGE, info);
+						    FB_EVENT_MODE_CHANGE, &event);
 			}
 		}
 	}
@@ -1114,10 +872,9 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	struct fb_ops *fb = info->fbops;
 	struct fb_var_screeninfo var;
 	struct fb_fix_screeninfo fix;
-#ifdef CONFIG_FRAMEBUFFER_CONSOLE
 	struct fb_con2fbmap con2fb;
-#endif
 	struct fb_cmap_user cmap;
+	struct fb_event event;
 	void __user *argp = (void __user *)arg;
 	int i;
 	
@@ -1166,13 +923,16 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 		i = fb_cursor(info, argp);
 		release_console_sem();
 		return i;
-#ifdef CONFIG_FRAMEBUFFER_CONSOLE
 	case FBIOGET_CON2FBMAP:
 		if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
 			return -EFAULT;
 		if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
 		    return -EINVAL;
-		con2fb.framebuffer = con2fb_map[con2fb.console-1];
+		con2fb.framebuffer = -1;
+		event.info = info;
+		event.data = &con2fb;
+		notifier_call_chain(&fb_notifier_list,
+				    FB_EVENT_GET_CONSOLE_MAP, &event);
 		return copy_to_user(argp, &con2fb,
 				    sizeof(con2fb)) ? -EFAULT : 0;
 	case FBIOPUT_CON2FBMAP:
@@ -1188,11 +948,14 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 #endif /* CONFIG_KMOD */
 		if (!registered_fb[con2fb.framebuffer])
 		    return -EINVAL;
-		if (con2fb.console > 0 && con2fb.console < MAX_NR_CONSOLES)
-			return set_con2fb_map(con2fb.console-1,
-					      con2fb.framebuffer);
+		if (con2fb.console > 0 && con2fb.console < MAX_NR_CONSOLES) {
+			event.info = info;
+			event.data = &con2fb;
+			return notifier_call_chain(&fb_notifier_list,
+						   FB_EVENT_SET_CONSOLE_MAP,
+						   &event);
+		}
 		return -EINVAL;
-#endif	/* CONFIG_FRAMEBUFFER_CONSOLE */
 	case FBIOBLANK:
 		acquire_console_sem();
 		i = fb_blank(info, arg);
@@ -1371,6 +1134,7 @@ register_framebuffer(struct fb_info *fb_info)
 {
 	int i;
 	struct class_device *c;
+	struct fb_event event;
 
 	if (num_registered_fb == FB_MAX)
 		return -ENXIO;
@@ -1410,10 +1174,23 @@ register_framebuffer(struct fb_info *fb_info)
 	}
 	fb_info->sprite.offset = 0;
 
+	if (!fb_info->modelist.prev ||
+	    !fb_info->modelist.next ||
+	    list_empty(&fb_info->modelist)) {
+	        struct fb_videomode mode;
+
+		INIT_LIST_HEAD(&fb_info->modelist);
+		fb_var_to_videomode(&mode, &fb_info->var);
+		fb_add_videomode(&mode, &fb_info->modelist);
+	}
+
 	registered_fb[i] = fb_info;
 
 	devfs_mk_cdev(MKDEV(FB_MAJOR, i),
 			S_IFCHR | S_IRUGO | S_IWUGO, "fb/%d", i);
+	event.info = fb_info;
+	notifier_call_chain(&fb_notifier_list,
+			    FB_EVENT_FB_REGISTERED, &event);
 	return 0;
 }
 
@@ -1442,6 +1219,7 @@ unregister_framebuffer(struct fb_info *fb_info)
 		kfree(fb_info->pixmap.addr);
 	if (fb_info->sprite.addr && (fb_info->sprite.flags & FB_PIXMAP_DEFAULT))
 		kfree(fb_info->sprite.addr);
+	fb_destroy_modelist(&fb_info->modelist);
 	registered_fb[i]=NULL;
 	num_registered_fb--;
 	class_simple_device_remove(MKDEV(FB_MAJOR, i));
@@ -1477,12 +1255,15 @@ int fb_unregister_client(struct notifier_block *nb)
  */
 void fb_set_suspend(struct fb_info *info, int state)
 {
+	struct fb_event event;
+
+	event.info = info;
 	if (state) {
-		notifier_call_chain(&fb_notifier_list, FB_EVENT_SUSPEND, info);
+		notifier_call_chain(&fb_notifier_list, FB_EVENT_SUSPEND, &event);
 		info->state = FBINFO_STATE_SUSPENDED;
 	} else {
 		info->state = FBINFO_STATE_RUNNING;
-		notifier_call_chain(&fb_notifier_list, FB_EVENT_RESUME, info);
+		notifier_call_chain(&fb_notifier_list, FB_EVENT_RESUME, &event);
 	}
 }
 
@@ -1495,11 +1276,9 @@ void fb_set_suspend(struct fb_info *info, int state)
  *
  */
 
-void __init 
+int __init
 fbmem_init(void)
 {
-	int i;
-
 	create_proc_read_entry("fb", 0, NULL, fbmem_read_proc, NULL);
 
 	devfs_mk_dir("fb");
@@ -1511,26 +1290,53 @@ fbmem_init(void)
 		printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));
 		fb_class = NULL;
 	}
+	return 0;
+}
+module_init(fbmem_init);
+
+#define NR_FB_DRIVERS 64
+static char *video_options[NR_FB_DRIVERS];
+static int ofonly;
 
-#ifdef CONFIG_FB_OF
-	if (ofonly) {
-		offb_init();
-		return;
+/**
+ * fb_get_options - get kernel boot parameters
+ * @name - framebuffer name as it would appear in
+ *         the boot parameter line
+ *         (video=<name>:<options>)
+ *
+ * NOTE: Needed to maintain backwards compatibility
+ */
+int fb_get_options(char *name, char **option)
+{
+	char *opt, *options = NULL;
+	int opt_len, retval = 0;
+	int name_len = strlen(name), i;
+
+	if (name_len && ofonly && strncmp(name, "offb", 4))
+		retval = 1;
+
+	if (name_len && !retval) {
+		for (i = 0; i < NR_FB_DRIVERS; i++) {
+			if (video_options[i] == NULL)
+				continue;
+			opt_len = strlen(video_options[i]);
+			if (!opt_len)
+				continue;
+			opt = video_options[i];
+			if (!strncmp(name, opt, name_len) &&
+			    opt[name_len] == ':')
+				options = opt + name_len + 1;
+		}
 	}
-#endif
+	if (options && !strncmp(options, "off", 3))
+		retval = 1;
 
-	/*
-	 *  Probe for all builtin frame buffer devices
-	 */
-	for (i = 0; i < num_pref_init_funcs; i++)
-		pref_init_funcs[i]();
+	if (option)
+		*option = options;
 
-	for (i = 0; i < NUM_FB_DRIVERS; i++)
-		if (fb_drivers[i].init)
-			fb_drivers[i].init();
+	return retval;
 }
 
-
 /**
  *	video_setup - process command line options
  *	@options: string of options
@@ -1538,6 +1344,8 @@ fbmem_init(void)
  *	Process command line options for frame buffer subsystem.
  *
  *	NOTE: This function is a __setup and __init function.
+ *            It only stores the options.  Drivers have to call
+ *            fb_get_options() as necessary.
  *
  *	Returns zero.
  *
@@ -1545,48 +1353,22 @@ fbmem_init(void)
 
 int __init video_setup(char *options)
 {
-	int i, j;
+	int i;
 
 	if (!options || !*options)
 		return 0;
-	   
-#ifdef CONFIG_FB_OF
-	if (!strcmp(options, "ofonly")) {
-		ofonly = 1;
-		return 0;
-	}
-#endif
-
-	if (num_pref_init_funcs == FB_MAX)
-		return 0;
 
-	for (i = 0; i < NUM_FB_DRIVERS; i++) {
-		j = strlen(fb_drivers[i].name);
-		if (!strncmp(options, fb_drivers[i].name, j) &&
-			options[j] == ':') {
-			if (!strcmp(options+j+1, "off"))
-				fb_drivers[i].init = NULL;
-			else {
-				if (fb_drivers[i].init) {
-					pref_init_funcs[num_pref_init_funcs++] =
-						fb_drivers[i].init;
-					fb_drivers[i].init = NULL;
-				}
-				if (fb_drivers[i].setup)
-					fb_drivers[i].setup(options+j+1);
-			}
-			return 0;
+	for (i = 0; i < NR_FB_DRIVERS; i++) {
+		if (!strncmp(options, "ofonly", 6))
+			ofonly = 1;
+		if (video_options[i] == NULL) {
+			video_options[i] = options;
+			break;
 		}
 	}
 
-	/*
-	 * If we get here no fb was specified.
-	 * We consider the argument to be a global video mode option.
-	 */
-	global_mode_option = options;
 	return 0;
 }
-
 __setup("video=", video_setup);
 
     /*
@@ -1611,5 +1393,6 @@ EXPORT_SYMBOL(fb_load_cursor_image);
 EXPORT_SYMBOL(fb_set_suspend);
 EXPORT_SYMBOL(fb_register_client);
 EXPORT_SYMBOL(fb_unregister_client);
+EXPORT_SYMBOL(fb_get_options);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index a28a66efb..fb2f2254a 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -49,6 +49,22 @@
 #define DPRINTK(fmt, args...)
 #endif
 
+#define FBMON_FIX_HEADER 1
+
+#ifdef CONFIG_FB_MODE_HELPERS
+struct broken_edid {
+	u8  manufacturer[4];
+	u32 model;
+	u32 fix;
+};
+
+static struct broken_edid brokendb[] = {
+	/* DEC FR-PCXAV-YZ */
+	{ .manufacturer = "DEC",
+	  .model        = 0x073a,
+	  .fix          = FBMON_FIX_HEADER,
+	},
+};
 
 const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
 	0xff, 0xff, 0xff, 0x00
@@ -65,30 +81,77 @@ static void copy_string(unsigned char *c, unsigned char *s)
   while (i-- && (*--s == 0x20)) *s = 0;
 }
 
+static void fix_broken_edid(unsigned char *edid)
+{
+	unsigned char *block = edid + ID_MANUFACTURER_NAME, manufacturer[4];
+	u32 model, i;
+
+	manufacturer[0] = ((block[0] & 0x7c) >> 2) + '@';
+	manufacturer[1] = ((block[0] & 0x03) << 3) +
+		((block[1] & 0xe0) >> 5) + '@';
+	manufacturer[2] = (block[1] & 0x1f) + '@';
+	manufacturer[3] = 0;
+	model = block[2] + (block[3] << 8);
+
+	for (i = 0; i < ARRAY_SIZE(brokendb); i++) {
+		if (!strncmp(manufacturer, brokendb[i].manufacturer, 4) &&
+			brokendb[i].model == model) {
+			switch (brokendb[i].fix) {
+			case FBMON_FIX_HEADER:
+				printk("fbmon: The EDID header of "
+				       "Manufacturer: %s Model: 0x%x is "
+				       "known to be broken,\n"
+				       "fbmon: trying a header "
+				       "reconstruct\n", manufacturer, model);
+				memcpy(edid, edid_v1_header, 8);
+				break;
+			}
+		}
+	}
+}
+
 static int edid_checksum(unsigned char *edid)
 {
-	unsigned char i, csum = 0;
+	unsigned char i, csum = 0, all_null = 0;
 
-	for (i = 0; i < EDID_LENGTH; i++)
+	for (i = 0; i < EDID_LENGTH; i++) {
 		csum += edid[i];
+		all_null |= edid[i];
+	}
 
-	if (csum == 0x00) {
+	if (csum == 0x00 && all_null) {
 		/* checksum passed, everything's good */
 		return 1;
-	} else {
+	}
+
+	fix_broken_edid(edid);
+	csum = all_null = 0;
+	for (i = 0; i < EDID_LENGTH; i++) {
+		csum += edid[i];
+		all_null |= edid[i];
+	}
+	if (csum != 0x00 || !all_null) {
 		printk("EDID checksum failed, aborting\n");
 		return 0;
 	}
+	return 1;
 }
 
 static int edid_check_header(unsigned char *edid)
 {
-	if ((edid[0] != 0x00) || (edid[1] != 0xff) || (edid[2] != 0xff) ||
-	    (edid[3] != 0xff) || (edid[4] != 0xff) || (edid[5] != 0xff) ||
-	    (edid[6] != 0xff)) {
-		printk
-		    ("EDID header doesn't match EDID v1 header, aborting\n");
-		return 0;
+	int i, fix = 0;
+
+	for (i = 0; i < 8; i++) {
+		if (edid[i] != edid_v1_header[i])
+			fix = 1;
+	}
+	if (!fix)
+		return 1;
+
+	fix_broken_edid(edid);
+	for (i = 0; i < 8; i++) {
+		if (edid[i] != edid_v1_header[i])
+			return 0;
 	}
 	return 1;
 }
@@ -1094,6 +1157,36 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf
 	
 	return 0;
 }
+#else
+int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
+{
+	return 1;
+}
+void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
+{
+	specs = NULL;
+}
+char *get_EDID_from_firmware(struct device *dev)
+{
+	return NULL;
+}
+struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
+{
+	return NULL;
+}
+void fb_destroy_modedb(struct fb_videomode *modedb)
+{
+}
+int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
+{
+	return 1;
+}
+int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var,
+		struct fb_info *info)
+{
+	return -EINVAL;
+}
+#endif /* CONFIG_FB_MODE_HELPERS */
 	
 /*
  * fb_validate_mode - validates var against monitor capabilities
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
index 1f7613131..349499ef4 100644
--- a/drivers/video/ffb.c
+++ b/drivers/video/ffb.c
@@ -362,61 +362,6 @@ struct ffb_par {
 	struct list_head	list;
 };
 
-#undef FFB_DO_DEBUG_LOG
-
-#ifdef FFB_DO_DEBUG_LOG
-#define FFB_DEBUG_LOG_ENTS	32
-static struct ffb_log {
-	int op;
-#define OP_FILLRECT	1
-#define OP_IMAGEBLIT	2
-
-	int depth, x, y, w, h;
-} ffb_debug_log[FFB_DEBUG_LOG_ENTS];
-static int ffb_debug_log_ent;
-
-static void ffb_do_log(unsigned long unused)
-{
-	int i;
-
-	for (i = 0; i < FFB_DEBUG_LOG_ENTS; i++) {
-		struct ffb_log *p = &ffb_debug_log[i];
-
-		printk("FFB_LOG: OP[%s] depth(%d) x(%d) y(%d) w(%d) h(%d)\n",
-		       (p->op == OP_FILLRECT ? "FILLRECT" : "IMAGEBLIT"),
-		       p->depth, p->x, p->y, p->w, p->h);
-	}
-}
-static struct timer_list ffb_log_timer =
-	TIMER_INITIALIZER(ffb_do_log, 0, 0);
-
-static void ffb_log(int op, int depth, int x, int y, int w, int h)
-{
-	if (ffb_debug_log_ent < FFB_DEBUG_LOG_ENTS) {
-		struct ffb_log *p = &ffb_debug_log[ffb_debug_log_ent];
-
-		if (ffb_debug_log_ent != 0 &&
-		    p[-1].op == op && p[-1].depth == depth)
-			return;
-		p->op = op;
-		p->depth = depth;
-		p->x = x;
-		p->y = y;
-		p->w = w;
-		p->h = h;
-
-		if (++ffb_debug_log_ent == FFB_DEBUG_LOG_ENTS) {
-			ffb_log_timer.expires = jiffies + 2;
-			add_timer(&ffb_log_timer);
-		}
-	}
-}
-#else
-#define ffb_log(a,b,c,d,e,f)	do { } while(0)
-#endif
-
-#undef FORCE_WAIT_EVERY_ROP
-
 static void FFBFifo(struct ffb_par *par, int n)
 {
 	struct ffb_fbc *fbc;
@@ -479,7 +424,7 @@ static void ffb_switch_from_graph(struct ffb_par *par)
 	upa_writel(0x2000707f, &fbc->fbc);
 	upa_writel(par->rop_cache, &fbc->rop);
 	upa_writel(0xffffffff, &fbc->pmask);
-	upa_writel((0 << 16) | (32 << 0), &fbc->fontinc);
+	upa_writel((1 << 16) | (0 << 0), &fbc->fontinc);
 	upa_writel(par->fg_cache, &fbc->fg);
 	upa_writel(par->bg_cache, &fbc->bg);
 	FFBWait(par);
@@ -526,8 +471,6 @@ static void ffb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 	if (rect->rop != ROP_COPY && rect->rop != ROP_XOR)
 		BUG();
 
-	ffb_log(OP_FILLRECT, 0, rect->dx, rect->dy, rect->width, rect->height);
-
 	fg = ((u32 *)info->pseudo_palette)[rect->color];
 
 	spin_lock_irqsave(&par->lock, flags);
@@ -548,9 +491,6 @@ static void ffb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 	upa_writel(rect->dx, &fbc->bx);
 	upa_writel(rect->height, &fbc->bh);
 	upa_writel(rect->width, &fbc->bw);
-#ifdef FORCE_WAIT_EVERY_ROP
-	FFBWait(par);
-#endif
 
 	spin_unlock_irqrestore(&par->lock, flags);
 }
@@ -572,7 +512,7 @@ ffb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 	unsigned long flags;
 
 	if (area->dx != area->sx ||
-	    area->dy == area->dy) {
+	    area->dy == area->sy) {
 		cfb_copyarea(info, area);
 		return;
 	}
@@ -609,10 +549,7 @@ static void ffb_imageblit(struct fb_info *info, const struct fb_image *image)
 	unsigned long flags;
 	u32 fg, bg, xy;
 	u64 fgbg;
-	int i, width;
-
-	ffb_log(OP_IMAGEBLIT, image->depth,
-		image->dx, image->dy, image->width, image->height);
+	int i, width, stride;
 
 	if (image->depth > 1) {
 		cfb_imageblit(info, image);
@@ -623,6 +560,8 @@ static void ffb_imageblit(struct fb_info *info, const struct fb_image *image)
 	bg = ((u32 *)info->pseudo_palette)[image->bg_color];
 	fgbg = ((u64) fg << 32) | (u64) bg;
 	xy = (image->dy << 16) | image->dx;
+	width = image->width;
+	stride = ((width + 7) >> 3);
 
 	spin_lock_irqsave(&par->lock, flags);
 
@@ -632,55 +571,49 @@ static void ffb_imageblit(struct fb_info *info, const struct fb_image *image)
 		*(u64 *)&par->fg_cache = fgbg;
 	}
 
-	ffb_rop(par, FFB_ROP_NEW);
+	if (width >= 32) {
+		FFBFifo(par, 1);
+		upa_writel(32, &fbc->fontw);
+	}
 
-	for (i = 0; i < image->height; i++) {
-		width = image->width;
+	while (width >= 32) {
+		const u8 *next_data = data + 4;
 
 		FFBFifo(par, 1);
 		upa_writel(xy, &fbc->fontxy);
-		xy += (1 << 16);
-
-		while (width >= 32) {
-			u32 val;
-
-			FFBFifo(par, 2);
-			upa_writel(32, &fbc->fontw);
-
-			val = ((u32)data[0] << 24) |
-			      ((u32)data[1] << 16) |
-			      ((u32)data[2] <<  8) |
-			      ((u32)data[3] <<  0);
+		xy += (32 << 0);
+
+		for (i = 0; i < image->height; i++) {
+			u32 val = (((u32)data[0] << 24) |
+				   ((u32)data[1] << 16) |
+				   ((u32)data[2] <<  8) |
+				   ((u32)data[3] <<  0));
+			FFBFifo(par, 1);
 			upa_writel(val, &fbc->font);
 
-			data += 4;
-			width -= 32;
+			data += stride;
 		}
 
-		if (width) {
-			u32 val;
-
-			FFBFifo(par, 2);
-			upa_writel(width, &fbc->fontw);
-			if (width <= 8) {
-				val = (u32) data[0] << 24;
-				data += 1;
-			} else if (width <= 16) {
-				val = ((u32) data[0] << 24) |
-				      ((u32) data[1] << 16);
-				data += 2;
-			} else {
-				val = ((u32) data[0] << 24) |
-				      ((u32) data[1] << 16) |
-				      ((u32) data[2] <<  8);
-				data += 3;
-			}
+		data = next_data;
+		width -= 32;
+	}
+
+	if (width) {
+		FFBFifo(par, 2);
+		upa_writel(width, &fbc->fontw);
+		upa_writel(xy, &fbc->fontxy);
+
+		for (i = 0; i < image->height; i++) {
+			u32 val = (((u32)data[0] << 24) |
+				   ((u32)data[1] << 16) |
+				   ((u32)data[2] <<  8) |
+				   ((u32)data[3] <<  0));
+			FFBFifo(par, 1);
 			upa_writel(val, &fbc->font);
+
+			data += stride;
 		}
 	}
-#ifdef FORCE_WAIT_EVERY_ROP
-	FFBWait(par);
-#endif
 
 	spin_unlock_irqrestore(&par->lock, flags);
 }
@@ -1027,7 +960,13 @@ static void ffb_init_one(int node, int parent)
 	all->par.prom_node = node;
 	all->par.prom_parent_node = parent;
 
-	all->info.flags = FBINFO_FLAG_DEFAULT;
+	/* Don't mention copyarea, so SCROLL_REDRAW is always
+	 * used.  It is the fastest on this chip.
+	 */
+	all->info.flags = (FBINFO_DEFAULT |
+			   /* FBINFO_HWACCEL_COPYAREA | */
+			   FBINFO_HWACCEL_FILLRECT |
+			   FBINFO_HWACCEL_IMAGEBLIT);
 	all->info.fbops = &ffb_ops;
 	all->info.screen_base = (char *) all->par.physbase + FFB_DFB24_POFF;
 	all->info.currcon = -1;
@@ -1110,6 +1049,9 @@ int __init ffb_init(void)
 {
 	int root;
 
+	if (fb_get_options("ffb", NULL))
+		return -ENODEV;
+
 	ffb_scan_siblings(prom_root_node);
 
 	root = prom_getchild(prom_root_node);
@@ -1140,8 +1082,9 @@ ffb_setup(char *arg)
 	return 0;
 }
 
-#ifdef MODULE
 module_init(ffb_init);
+
+#ifdef MODULE
 module_exit(ffb_exit);
 #endif
 
diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c
index 9bd202284..3adb65df1 100644
--- a/drivers/video/fm2fb.c
+++ b/drivers/video/fm2fb.c
@@ -280,7 +280,7 @@ static int __devinit fm2fb_probe(struct zorro_dev *z,
 	info->pseudo_palette = info->par;
 	info->par = NULL;
 	info->fix = fb_fix;
-	info->flags = FBINFO_FLAG_DEFAULT;
+	info->flags = FBINFO_DEFAULT;
 
 	if (register_framebuffer(info) < 0) {
 		fb_dealloc_cmap(&info->cmap);
@@ -292,12 +292,18 @@ static int __devinit fm2fb_probe(struct zorro_dev *z,
 	return 0;
 }
 
+int __init fm2fb_setup(char *options);
+
 int __init fm2fb_init(void)
 {
+	char *option = NULL;
+
+	if (fb_get_options("fm2fb", &option))
+		return -ENODEV;
+	fm2fb_setup(option);
 	return zorro_register_driver(&fm2fb_driver);
 }
 
-int __init fm2fb_setup(char *options)
 {
 	char *this_opt;
 
@@ -313,4 +319,5 @@ int __init fm2fb_setup(char *options)
 	return 0;
 }
 
+module_init(fm2fb_init);
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/g364fb.c b/drivers/video/g364fb.c
index a869bf147..5eed5bd38 100644
--- a/drivers/video/g364fb.c
+++ b/drivers/video/g364fb.c
@@ -202,6 +202,9 @@ int __init g364fb_init(void)
 	    (volatile unsigned int *) CURS_PAL_REG;
 	int mem, i, j;
 
+	if (fb_get_options("g364fb", NULL))
+		return -ENODEV;
+
 	/* TBD: G364 detection */
 
 	/* get the resolution set by ARC console */
@@ -241,7 +244,7 @@ int __init g364fb_init(void)
 	fb_info.screen_base = (char *) G364_MEM_BASE;	/* virtual kernel address */
 	fb_info.var = fb_var;
 	fb_info.fix = fb_fix;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 
 	fb_alloc_cmap(&fb_info.cmap, 255, 0);
 
@@ -250,4 +253,5 @@ int __init g364fb_init(void)
 	return 0;
 }
 
+module_init(g364fb_init);
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index 2afc4148b..1dfc1d65c 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -1083,6 +1083,14 @@ int __init gbefb_init(void)
 {
 	int i, ret = 0;
 
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("gbefb", &option))
+		return -ENODEV;
+	gbefb_setup(options);
+#endif
+
 	if (!request_mem_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) {
 		printk(KERN_ERR "gbefb: couldn't reserve mmio region\n");
 		return -EBUSY;
@@ -1135,7 +1143,7 @@ int __init gbefb_init(void)
 	fb_info.currcon = -1;
 	fb_info.fbops = &gbefb_ops;
 	fb_info.pseudo_palette = pseudo_palette;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	fb_info.flags = FBINFO_DEFAULT;
 	fb_info.screen_base = gbe_mem;
 	fb_alloc_cmap(&fb_info.cmap, 256, 0);
 
@@ -1192,8 +1200,9 @@ void __exit gbefb_exit(void)
 	iounmap(gbe);
 }
 
-#ifdef MODULE
 module_init(gbefb_init);
+
+#ifdef MODULE
 module_exit(gbefb_exit);
 #endif
 
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c
index 05244ce4a..87d008af2 100644
--- a/drivers/video/hgafb.c
+++ b/drivers/video/hgafb.c
@@ -547,6 +547,9 @@ static struct fb_ops hgafb_ops = {
 
 int __init hgafb_init(void)
 {
+	if (fb_get_options("hgafb", NULL))
+		return -ENODEV;
+
 	if (! hga_card_detect()) {
 		printk(KERN_INFO "hgafb: HGA card not detected.\n");
 		return -EINVAL;
@@ -558,7 +561,7 @@ int __init hgafb_init(void)
 	hga_fix.smem_start = VGA_MAP_MEM(hga_vram_base);
 	hga_fix.smem_len = hga_vram_len;
 
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 	fb_info.var = hga_default_var;
 	fb_info.fix = hga_fix;
 	fb_info.monspecs.hfmin = 0;
@@ -609,8 +612,8 @@ MODULE_LICENSE("GPL");
 
 MODULE_PARM(nologo, "i");
 MODULE_PARM_DESC(nologo, "Disables startup logo if != 0 (default=0)");
+module_init(hgafb_init);
 
 #ifdef MODULE
-module_init(hgafb_init);
 module_exit(hgafb_exit);
 #endif
diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c
index 90439cbb2..9d2ea3b4a 100644
--- a/drivers/video/hitfb.c
+++ b/drivers/video/hitfb.c
@@ -270,6 +270,9 @@ int __init hitfb_init(void)
 	unsigned short lcdclor, ldr3, ldvndr;
 	int size;
 
+	if (fb_get_options("hitfb", NULL))
+		return -ENODEV;
+
 	hitfb_fix.smem_start = CONFIG_HD64461_IOBASE + 0x02000000;
 	hitfb_fix.smem_len = (MACH_HP690) ? 1024 * 1024 : 512 * 1024;
 
@@ -321,7 +324,7 @@ int __init hitfb_init(void)
 	fb_info.var = hitfb_var;
 	fb_info.fix = hitfb_fix;
 	fb_info.pseudo_palette = pseudo_palette;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 
 	fb_info.screen_base = (void *)hitfb_fix.smem_start;
 
@@ -341,8 +344,9 @@ static void __exit hitfb_exit(void)
 	unregister_framebuffer(&fb_info);
 }
 
-#ifdef MODULE
 module_init(hitfb_init);
+
+#ifdef MODULE
 module_exit(hitfb_exit);
 #endif
 
diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c
index bfbdbabfd..9405d7169 100644
--- a/drivers/video/hpfb.c
+++ b/drivers/video/hpfb.c
@@ -115,6 +115,9 @@ int __init hpfb_init_one(unsigned long base)
 {
 	unsigned long fboff;
 
+	if (fb_get_options("hpfb", NULL))
+		return -ENODEV;
+
 	fboff = (in_8(base + TOPCAT_FBOMSB) << 8) | in_8(base + TOPCAT_FBOLSB);
 
 	hpfb_fix.smem_start = 0xf0000000 | (in_8(base + fboff) << 16);
@@ -151,7 +154,7 @@ int __init hpfb_init_one(unsigned long base)
 	 *	Let there be consoles..
 	 */
 	fb_info.fbops = &hpfb_ops;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	fb_info.flags = FBINFO_DEFAULT;
 	fb_info.var   = hpfb_defined;
 	fb_info.fix   = hpfb_fix;
 	fb_info.screen_base = (char *)hpfb_fix.smem_start;	// FIXME
@@ -211,4 +214,5 @@ int __init hpfb_init(void)
 	return 0;
 }
 
+module_init(hpfb_init);
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/i810/i810_dvt.c b/drivers/video/i810/i810_dvt.c
index ffeaef872..27fa703a2 100644
--- a/drivers/video/i810/i810_dvt.c
+++ b/drivers/video/i810/i810_dvt.c
@@ -193,19 +193,19 @@ struct mode_registers std_modes[] = {
 
 void round_off_xres(u32 *xres) 
 {
-	if (*xres < 800) 
+	if (*xres <= 640)
 		*xres = 640;
-	if (*xres < 1024 && *xres >= 800) 
+	else if (*xres <= 800)
 		*xres = 800;
-	if (*xres < 1152 && *xres >= 1024)
+	else if (*xres <= 1024)
 		*xres = 1024;
-	if (*xres < 1280 && *xres >= 1152)
+	else if (*xres <= 1152)
 		*xres = 1152;
-	if (*xres < 1600 && *xres >= 1280)
+	else if (*xres <= 1280)
 		*xres = 1280;
-	if (*xres >= 1600)
+	else
 		*xres = 1600;
-}		
+}
 
 inline void round_off_yres(u32 *xres, u32 *yres)
 {
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index 2633664b4..6acde2569 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -1353,11 +1353,15 @@ static int i810fb_set_par(struct fb_info *info)
 
 	encode_fix(&info->fix, info);
 
-	if (info->var.accel_flags && !(par->dev_flags & LOCKUP)) 
+	if (info->var.accel_flags && !(par->dev_flags & LOCKUP)) {
+		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
+		FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
+		FBINFO_HWACCEL_IMAGEBLIT;
 		info->pixmap.scan_align = 2;
-	else 
+	} else {
 		info->pixmap.scan_align = 1;
-	
+		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+	}
 	return 0;
 }
 
@@ -1388,16 +1392,17 @@ static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
 	struct i810fb_par *par = (struct i810fb_par *)info->par;
 	u8 *mmio = par->mmio_start_virtual;	
-	u8 data[64 * 8];
-	
+
 	if (!info->var.accel_flags || par->dev_flags & LOCKUP) 
 		return soft_cursor(info, cursor);
 
 	if (cursor->image.width > 64 || cursor->image.height > 64)
 		return -ENXIO;
 
-	if ((i810_readl(CURBASE, mmio) & 0xf) != par->cursor_heap.physical)
+	if ((i810_readl(CURBASE, mmio) & 0xf) != par->cursor_heap.physical) {
 		i810_init_cursor(par);
+		cursor->set |= FB_CUR_SETALL;
+	}
 
 	i810_enable_cursor(mmio, OFF);
 
@@ -1409,50 +1414,56 @@ static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 
 		info->cursor.image.dx = cursor->image.dx;
 		info->cursor.image.dy = cursor->image.dy;
-		
-		tmp = cursor->image.dx - info->var.xoffset;
-		tmp |= (cursor->image.dy - info->var.yoffset) << 16;
-	    
+		tmp = (info->cursor.image.dx - info->var.xoffset) & 0xffff;
+		tmp |= (info->cursor.image.dy - info->var.yoffset) << 16;
 		i810_writel(CURPOS, mmio, tmp);
 	}
 
 	if (cursor->set & FB_CUR_SETSIZE) {
+		i810_reset_cursor_image(par);
 		info->cursor.image.height = cursor->image.height;
 		info->cursor.image.width = cursor->image.width;
-		i810_reset_cursor_image(par);
 	}
 
 	if (cursor->set & FB_CUR_SETCMAP) {
-		info->cursor.image.fg_color = cursor->image.fg_color;
-		info->cursor.image.bg_color = cursor->image.bg_color;
 		i810_load_cursor_colors(cursor->image.fg_color,
 					cursor->image.bg_color,
 					info);
+		info->cursor.image.fg_color = cursor->image.fg_color;
+		info->cursor.image.bg_color = cursor->image.bg_color;
+
 	}
 
-	if (cursor->set & FB_CUR_SETSHAPE) {
+	if (cursor->set & (FB_CUR_SETSHAPE)) {
 		int size = ((info->cursor.image.width + 7) >> 3) * 
-			     info->cursor.image.height;
+			info->cursor.image.height;
 		int i;
+		u8 *data = kmalloc(64 * 8, GFP_KERNEL);
+
+		if (data == NULL)
+			return -ENOMEM;
+		info->cursor.image.data = cursor->image.data;
 
 		switch (info->cursor.rop) {
 		case ROP_XOR:
 			for (i = 0; i < size; i++)
-				data[i] = cursor->image.data[i] ^ info->cursor.mask[i]; 
+				data[i] = info->cursor.image.data[i] ^ info->cursor.mask[i];
 			break;
 		case ROP_COPY:
 		default:
 			for (i = 0; i < size; i++)
-				data[i] = cursor->image.data[i] & info->cursor.mask[i]; 
+				data[i] = info->cursor.image.data[i] & info->cursor.mask[i];
 			break;
 		}
 		i810_load_cursor_image(info->cursor.image.width, 
 				       info->cursor.image.height, data,
 				       par);
+		kfree(data);
 	}
 
 	if (info->cursor.enable)
 		i810_enable_cursor(mmio, ON);
+
 	return 0;
 }
 
@@ -1641,9 +1652,11 @@ static void __devinit i810_init_monspecs(struct fb_info *info)
 		hsync1 = HFMIN;
 	if (!hsync2) 
 		hsync2 = HFMAX;
-	info->monspecs.hfmax = hsync2;
-	info->monspecs.hfmin = hsync1;
-	if (hsync2 < hsync1) 
+	if (!info->monspecs.hfmax)
+		info->monspecs.hfmax = hsync2;
+	if (!info->monspecs.hfmin)
+		info->monspecs.hfmin = hsync1;
+	if (hsync2 < hsync1)
 		info->monspecs.hfmin = hsync2;
 
 	if (!vsync1)
@@ -1652,8 +1665,10 @@ static void __devinit i810_init_monspecs(struct fb_info *info)
 		vsync2 = VFMAX;
 	if (IS_DVT && vsync1 < 60)
 		vsync1 = 60;
-	info->monspecs.vfmax = vsync2;
-	info->monspecs.vfmin = vsync1;		
+	if (!info->monspecs.vfmax)
+		info->monspecs.vfmax = vsync2;
+	if (!info->monspecs.vfmin)
+		info->monspecs.vfmin = vsync1;
 	if (vsync2 < vsync1) 
 		info->monspecs.vfmin = vsync2;
 }
@@ -1724,6 +1739,7 @@ static void __devinit i810_init_device(struct i810fb_par *par)
 	pci_read_config_byte(par->dev, 0x50, &reg);
 	reg &= FREQ_MASK;
 	par->mem_freq = (reg) ? 133 : 100;
+
 }
 
 static int __devinit 
@@ -1836,8 +1852,9 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev,
 {
 	struct fb_info    *info;
 	struct i810fb_par *par = NULL;
-	int err, vfreq, hfreq, pixclock;
+	int i, err = -1, vfreq, hfreq, pixclock;
 
+	i = 0;
 	if (!(info = kmalloc(sizeof(struct fb_info), GFP_KERNEL))) {
 		i810fb_release_resource(info, par);
 		return -ENOMEM;
@@ -1879,8 +1896,6 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev,
 	info->screen_base = par->fb.virtual;
 	info->fbops = &par->i810fb_ops;
 	info->pseudo_palette = par->pseudo_palette;
-	info->flags = FBINFO_FLAG_DEFAULT;
-	
 	fb_alloc_cmap(&info->cmap, 256, 0);
 
 	if ((err = info->fbops->fb_check_var(&info->var, info))) {
@@ -1957,8 +1972,7 @@ static void i810fb_release_resource(struct fb_info *info,
 
 		kfree(par);
 	}
-	if (info) 
-		kfree(info);
+	kfree(info);
 }
 
 static void __exit i810fb_remove_pci(struct pci_dev *dev)
@@ -1975,10 +1989,11 @@ static void __exit i810fb_remove_pci(struct pci_dev *dev)
 #ifndef MODULE
 int __init i810fb_init(void)
 {
-	if (agp_intel_init()) {
-		printk("i810fb_init: cannot initialize intel agpgart\n");
+	char *option = NULL;
+
+	if (fb_get_options("i810fb", &option))
 		return -ENODEV;
-	}
+	i810fb_setup(option);
 
 	if (pci_register_driver(&i810fb_driver) > 0)
 		return 0;
@@ -2054,9 +2069,8 @@ static void __exit i810fb_exit(void)
 {
 	pci_unregister_driver(&i810fb_driver);
 }
-module_init(i810fb_init);
 module_exit(i810fb_exit);
 
 #endif /* MODULE */
 
-
+module_init(i810fb_init);
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
index 7e0353afb..dd6b16c84 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/igafb.c
@@ -357,7 +357,7 @@ static int __init iga_init(struct fb_info *info, struct iga_par *par)
                 video_cmap_len = 256;
 
 	info->fbops = &igafb_ops;
-	info->flags = FBINFO_FLAG_DEFAULT;
+	info->flags = FBINFO_DEFAULT;
 
 	fb_alloc_cmap(&info->cmap, video_cmap_len, 0);
 
@@ -381,6 +381,9 @@ int __init igafb_init(void)
 	unsigned long addr;
 	int size, iga2000 = 0;
 
+	if (fb_get_options("igafb", NULL))
+		return -ENODEV;
+
         /* Do not attach when we have a serial console. */
         if (!con_is_present())
                 return -ENXIO;
@@ -572,4 +575,5 @@ int __init igafb_setup(char *options)
     return 0;
 }
 
+module_init(igafb_init);
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
index 7bef8b772..c4a07f27c 100644
--- a/drivers/video/imsttfb.c
+++ b/drivers/video/imsttfb.c
@@ -1442,7 +1442,10 @@ init_imstt(struct fb_info *info)
 	info->var.pixclock = 1000000 / getclkMHz(par);
 
 	info->fbops = &imsttfb_ops;
-	info->flags = FBINFO_FLAG_DEFAULT;
+	info->flags = FBINFO_DEFAULT |
+                      FBINFO_HWACCEL_COPYAREA |
+	              FBINFO_HWACCEL_FILLRECT |
+	              FBINFO_HWACCEL_YPAN;
 
 	fb_alloc_cmap(&info->cmap, 0, 0);
 
@@ -1599,6 +1602,14 @@ imsttfb_setup(char *options)
 
 int __init imsttfb_init(void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("imsttfb", &option))
+		return -ENODEV;
+
+	imsttfb_setup(option);
+#endif
 	return pci_module_init(&imsttfb_pci_driver);
 }
  
@@ -1609,7 +1620,7 @@ static void __exit imsttfb_exit(void)
 
 #ifdef MODULE
 MODULE_LICENSE("GPL");
-module_init(imsttfb_init);
 #endif
+module_init(imsttfb_init);
 module_exit(imsttfb_exit);
 
diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c
index ad74caab2..2352a9142 100644
--- a/drivers/video/kyro/fbdev.c
+++ b/drivers/video/kyro/fbdev.c
@@ -712,7 +712,7 @@ static int __devinit kyrofb_probe(struct pci_dev *pdev,
 	info->fix		= kyro_fix;
 	info->par		= currentpar;
 	info->pseudo_palette	= (void *)(currentpar + 1);
-	info->flags		= FBINFO_FLAG_DEFAULT;
+	info->flags		= FBINFO_DEFAULT;
 
 	SetCoreClockPLL(deviceInfo.pSTGReg, pdev);
 
@@ -787,6 +787,13 @@ static void __devexit kyrofb_remove(struct pci_dev *pdev)
 
 int __init kyrofb_init(void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("kyrofb", &option))
+		return -ENODEV;
+	kyrofb_setup(option);
+#endif
 	return pci_module_init(&kyrofb_pci_driver);
 }
 
@@ -795,8 +802,9 @@ static void __exit kyrofb_exit(void)
 	pci_unregister_driver(&kyrofb_pci_driver);
 }
 
-#ifdef MODULE
 module_init(kyrofb_init);
+
+#ifdef MODULE
 module_exit(kyrofb_exit);
 #endif
 
diff --git a/drivers/video/leo.c b/drivers/video/leo.c
index 7547e8936..99fb72aa1 100644
--- a/drivers/video/leo.c
+++ b/drivers/video/leo.c
@@ -588,7 +588,7 @@ static void leo_init_one(struct sbus_dev *sdev)
 		sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_CURSOR,
 			     sizeof(struct leo_cursor), "leolx cursor");
 
-	all->info.flags = FBINFO_FLAG_DEFAULT;
+	all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 	all->info.fbops = &leo_ops;
 	all->info.currcon = -1;
 	all->info.par = &all->par;
@@ -626,6 +626,9 @@ int __init leo_init(void)
 	struct sbus_bus *sbus;
 	struct sbus_dev *sdev;
 
+	if (fb_get_options("leofb", NULL))
+		return -ENODEV;
+
 	for_all_sbusdev(sdev, sbus) {
 		if (!strcmp(sdev->prom_name, "leo"))
 			leo_init_one(sdev);
@@ -654,8 +657,8 @@ leo_setup(char *arg)
 	return 0;
 }
 
-#ifdef MODULE
 module_init(leo_init);
+#ifdef MODULE
 module_exit(leo_exit);
 #endif
 
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c
index 9baa40a0b..4945a4c02 100644
--- a/drivers/video/macfb.c
+++ b/drivers/video/macfb.c
@@ -614,6 +614,11 @@ void __init macfb_init(void)
 {
 	int video_cmap_len, video_is_nubus = 0;
 	struct nubus_dev* ndev = NULL;
+	char *option = NULL;
+
+	if (fb_get_options("macfb", &option))
+		return -ENODEV;
+	macfb_setup(option);
 
 	if (!MACH_IS_MAC) 
 		return;
@@ -660,6 +665,9 @@ void __init macfb_init(void)
 	case 1:
 		/* XXX: I think this will catch any program that tries
 		   to do FBIO_PUTCMAP when the visual is monochrome */
+		macfb_defined.red.length = macfb_defined.bits_per_pixel;
+		macfb_defined.green.length = macfb_defined.bits_per_pixel;
+		macfb_defined.blue.length = macfb_defined.bits_per_pixel;
 		video_cmap_len = 0;
 		macfb_fix.visual = FB_VISUAL_MONO01;
 		break;
@@ -947,7 +955,7 @@ void __init macfb_init(void)
 	fb_info.var		= macfb_defined;
 	fb_info.fix		= macfb_fix;
 	fb_info.pseudo_palette	= pseudo_palette;
-	fb_info.flags		= FBINFO_FLAG_DEFAULT;
+	fb_info.flags		= FBINFO_DEFAULT;
 
 	fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0);
 	
@@ -958,4 +966,5 @@ void __init macfb_init(void)
 	       fb_info.node, fb_info.fix.id);
 }
 
+module_init(macfb_init);
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 8074e858c..e2a2290b6 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -2415,8 +2415,14 @@ static int __initdata initialized = 0;
 
 int __init matroxfb_init(void)
 {
+	char *option = NULL;
+
 	DBG(__FUNCTION__)
 
+	if (fb_get_options("matroxfb", &option))
+		return -ENODEV;
+	matroxfb_setup(option);
+
 	if (disabled)
 		return -ENXIO;
 	if (!initialized) {
@@ -2428,6 +2434,8 @@ int __init matroxfb_init(void)
 	return 0;
 }
 
+module_init(matroxfb_init);
+
 #else
 
 /* *************************** init module code **************************** */
diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
index 18938f119..79a6873f7 100644
--- a/drivers/video/matrox/matroxfb_base.h
+++ b/drivers/video/matrox/matroxfb_base.h
@@ -99,21 +99,16 @@
 #endif
 #endif
 
-#if defined(__alpha__) || defined(__mc68000__)
+#if defined(__alpha__) || defined(__mc68000__) || defined(__i386__) || defined(__x86_64__)
 #define READx_WORKS
 #define MEMCPYTOIO_WORKS
 #else
+/* ppc/ppc64 must use __raw_{read,write}[bwl] as we drive adapter 
+   in big-endian mode for compatibility with XFree mga driver, and
+   so we do not want little-endian {read,write}[bwl] */
 #define READx_FAILS
-/* recheck __ppc__, maybe that __ppc__ needs MEMCPYTOIO_WRITEL */
-/* I benchmarked PII/350MHz with G200... MEMCPY, MEMCPYTOIO and WRITEL are on same speed ( <2% diff) */
-/* so that means that G200 speed (or AGP speed?) is our limit... I do not have benchmark to test, how */
-/* much of PCI bandwidth is used during transfers... */
-#if defined(__i386__) || defined(__x86_64__)
-#define MEMCPYTOIO_MEMCPY
-#else
 #define MEMCPYTOIO_WRITEL
 #endif
-#endif
 
 #if defined(__mc68000__)
 #define MAP_BUSTOVIRT
@@ -160,7 +155,7 @@
 #endif
 
 typedef struct {
-	u_int8_t*	vaddr;
+	u_int8_t __iomem*	vaddr;
 } vaddr_t;
 
 #ifdef READx_WORKS
@@ -189,27 +184,27 @@ static inline void mga_writel(vaddr_t va, unsigned int offs, u_int32_t value) {
 }
 #else
 static inline unsigned int mga_readb(vaddr_t va, unsigned int offs) {
-	return *(volatile u_int8_t*)(va.vaddr + offs);
+	return __raw_readb(va.vaddr + offs);
 }
 
 static inline unsigned int mga_readw(vaddr_t va, unsigned int offs) {
-	return *(volatile u_int16_t*)(va.vaddr + offs);
+	return __raw_readw(va.vaddr + offs);
 }
 
 static inline u_int32_t mga_readl(vaddr_t va, unsigned int offs) {
-	return *(volatile u_int32_t*)(va.vaddr + offs);
+	return __raw_readl(va.vaddr + offs);
 }
 
 static inline void mga_writeb(vaddr_t va, unsigned int offs, u_int8_t value) {
-	*(volatile u_int8_t*)(va.vaddr + offs) = value;
+	__raw_writeb(value, va.vaddr + offs);
 }
 
 static inline void mga_writew(vaddr_t va, unsigned int offs, u_int16_t value) {
-	*(volatile u_int16_t*)(va.vaddr + offs) = value;
+	__raw_writew(value, va.vaddr + offs);
 }
 
 static inline void mga_writel(vaddr_t va, unsigned int offs, u_int32_t value) {
-	*(volatile u_int32_t*)(va.vaddr + offs) = value;
+	__raw_writel(value, va.vaddr + offs);
 }
 #endif
 
@@ -238,8 +233,6 @@ static inline void mga_memcpy_toio(vaddr_t va, unsigned int offs, const void* sr
 		memcpy(&tmp, src, len);
 		mga_writel(va, offs, tmp);
 	}
-#elif defined(MEMCPYTOIO_MEMCPY)
-	memcpy(va.vaddr + offs, src, len);
 #else
 #error "Sorry, do not know how to write block of data to device"
 #endif
@@ -249,7 +242,7 @@ static inline void vaddr_add(vaddr_t* va, unsigned long offs) {
 	va->vaddr += offs;
 }
 
-static inline void* vaddr_va(vaddr_t va) {
+static inline void __iomem* vaddr_va(vaddr_t va) {
 	return va.vaddr;
 }
 
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
index 0d7e067fe..75d19696f 100644
--- a/drivers/video/matrox/matroxfb_crtc2.c
+++ b/drivers/video/matrox/matroxfb_crtc2.c
@@ -721,6 +721,9 @@ static struct matroxfb_driver crtc2 = {
 		.remove =	matroxfb_crtc2_remove };
 
 static int matroxfb_crtc2_init(void) {
+	if (fb_get_options("matrox_crtc2fb", NULL))
+		return -ENODEV;
+
 	matroxfb_register_driver(&crtc2);
 	return 0;
 }
diff --git a/drivers/video/matrox/matroxfb_crtc2.h b/drivers/video/matrox/matroxfb_crtc2.h
index fa148354e..9d92dda90 100644
--- a/drivers/video/matrox/matroxfb_crtc2.h
+++ b/drivers/video/matrox/matroxfb_crtc2.h
@@ -27,7 +27,7 @@ struct matroxfb_dh_fb_info {
 		unsigned int	len;
 			      } mmio;
 
-	int			interlaced:1;
+	unsigned int		interlaced:1;
 
 	u_int32_t cmap[17];
 };
diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c
index 62f498e82..76fd3a519 100644
--- a/drivers/video/matrox/matroxfb_misc.c
+++ b/drivers/video/matrox/matroxfb_misc.c
@@ -391,7 +391,7 @@ void matroxfb_vgaHWrestore(WPMINFO2) {
 	CRITEND
 }
 
-static void get_pins(unsigned char* pins, struct matrox_bios* bd) {
+static void get_pins(unsigned char __iomem* pins, struct matrox_bios* bd) {
 	unsigned int b0 = readb(pins);
 	
 	if (b0 == 0x2E && readb(pins+1) == 0x41) {
@@ -427,7 +427,7 @@ static void get_pins(unsigned char* pins, struct matrox_bios* bd) {
 	}
 }
 
-static void get_bios_version(unsigned char* vbios, struct matrox_bios* bd) {
+static void get_bios_version(unsigned char __iomem * vbios, struct matrox_bios* bd) {
 	unsigned int pcir_offset;
 	
 	pcir_offset = readb(vbios + 24) | (readb(vbios + 25) << 8);
@@ -452,7 +452,7 @@ static void get_bios_version(unsigned char* vbios, struct matrox_bios* bd) {
 	}
 }
 
-static void get_bios_output(unsigned char* vbios, struct matrox_bios* bd) {
+static void get_bios_output(unsigned char __iomem* vbios, struct matrox_bios* bd) {
 	unsigned char b;
 	
 	b = readb(vbios + 0x7FF1);
@@ -462,7 +462,7 @@ static void get_bios_output(unsigned char* vbios, struct matrox_bios* bd) {
 	bd->output.state = b;
 }
 
-static void get_bios_tvout(unsigned char* vbios, struct matrox_bios* bd) {
+static void get_bios_tvout(unsigned char __iomem* vbios, struct matrox_bios* bd) {
 	unsigned int i;
 	
 	/* Check for 'IBM .*(V....TVO' string - it means TVO BIOS */
@@ -489,7 +489,7 @@ static void get_bios_tvout(unsigned char* vbios, struct matrox_bios* bd) {
 	}
 }
 
-static void parse_bios(unsigned char* vbios, struct matrox_bios* bd) {
+static void parse_bios(unsigned char __iomem* vbios, struct matrox_bios* bd) {
 	unsigned int pins_offset;
 	
 	if (readb(vbios) != 0x55 || readb(vbios + 1) != 0xAA) {
@@ -738,7 +738,7 @@ void matroxfb_read_pins(WPMINFO2) {
 	pci_write_config_dword(pdev, PCI_OPTION_REG, opt);
 #ifdef CONFIG_X86
 	if (!ACCESS_FBINFO(bios).bios_valid) {
-		unsigned char* b;
+		unsigned char __iomem* b;
 
 		b = ioremap(0x000C0000, 65536);
 		if (!b) {
diff --git a/drivers/video/maxinefb.c b/drivers/video/maxinefb.c
index 572ed2269..46264bd19 100644
--- a/drivers/video/maxinefb.c
+++ b/drivers/video/maxinefb.c
@@ -126,6 +126,9 @@ int __init maxinefb_init(void)
 	unsigned long fb_start;
 	int i;
 
+	if (fb_get_options("maxinefb", NULL))
+		return -ENODEV;
+
 	/* Validate we're on the proper machine type */
 	if (mips_machtype != MACH_DS5000_XX) {
 		return -EINVAL;
@@ -159,7 +162,7 @@ int __init maxinefb_init(void)
 	fb_info.screen_base = (char *) maxinefb_fix.smem_start;
 	fb_info.var = maxinefb_defined;
 	fb_info.fix = maxinefb_fix;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	fb_info.flags = FBINFO_DEFAULT;
 
 	fb_alloc_cmap(&fb_info.cmap, 256, 0);
 
@@ -175,7 +178,7 @@ static void __exit maxinefb_exit(void)
 
 #ifdef MODULE
 MODULE_LICENSE("GPL");
-module_init(maxinefb_init);
 #endif
+module_init(maxinefb_init);
 module_exit(maxinefb_exit);
 
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index d046edf1e..3892222d1 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -39,7 +39,7 @@ const char *global_mode_option = NULL;
 
 #define DEFAULT_MODEDB_INDEX	0
 
-static const struct fb_videomode modedb[] = {
+static const __init struct fb_videomode modedb[] = {
     {
 	/* 640x400 @ 70 Hz, 31.5 kHz hsync */
 	NULL, 70, 640, 400, 39721, 40, 24, 39, 9, 96, 2,
@@ -251,6 +251,7 @@ static const struct fb_videomode modedb[] = {
     },
 };
 
+#ifdef CONFIG_FB_MODE_HELPERS
 const struct fb_videomode vesa_modes[] = {
 	/* 0 640x350-85 VESA */
 	{ NULL, 85, 640, 350, 31746,  96, 32, 60, 32, 64, 3,
@@ -374,6 +375,8 @@ const struct fb_videomode vesa_modes[] = {
 	{ NULL, 60, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3,
 	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
 };
+EXPORT_SYMBOL(vesa_modes);
+#endif /* CONFIG_FB_MODE_HELPERS */
 
 static int my_atoi(const char *name)
 {
@@ -404,7 +407,7 @@ static int my_atoi(const char *name)
  */
 
 int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
-		  const struct fb_videomode *mode, unsigned int bpp)
+		const struct fb_videomode *mode, unsigned int bpp)
 {
     int err = 0;
 
@@ -570,5 +573,261 @@ done:
     return 0;
 }
 
-EXPORT_SYMBOL(vesa_modes);
+/**
+ * fb_var_to_videomode - convert fb_var_screeninfo to fb_videomode
+ * @mode: pointer to struct fb_videomode
+ * @var: pointer to struct fb_var_screeninfo
+ */
+void fb_var_to_videomode(struct fb_videomode *mode,
+			 struct fb_var_screeninfo *var)
+{
+	u32 pixclock, hfreq, htotal, vtotal;
+
+	mode->name = NULL;
+	mode->xres = var->xres;
+	mode->yres = var->yres;
+	mode->pixclock = var->pixclock;
+	mode->hsync_len = var->hsync_len;
+	mode->vsync_len = var->vsync_len;
+	mode->left_margin = var->left_margin;
+	mode->right_margin = var->right_margin;
+	mode->upper_margin = var->upper_margin;
+	mode->lower_margin = var->lower_margin;
+	mode->sync = var->sync;
+	mode->vmode = var->vmode & FB_VMODE_MASK;
+	mode->flag = FB_MODE_IS_FROM_VAR;
+	if (!var->pixclock)
+		return;
+
+	pixclock = PICOS2KHZ(var->pixclock) * 1000;
+
+	htotal = var->xres + var->right_margin + var->hsync_len +
+		var->left_margin;
+	vtotal = var->yres + var->lower_margin + var->vsync_len +
+		var->upper_margin;
+
+	if (var->vmode & FB_VMODE_INTERLACED)
+		vtotal /= 2;
+	if (var->vmode & FB_VMODE_DOUBLE)
+		vtotal *= 2;
+
+	hfreq = pixclock/htotal;
+	mode->refresh = hfreq/vtotal;
+}
+
+/**
+ * fb_videomode_to_var - convert fb_videomode to fb_var_screeninfo
+ * @var: pointer to struct fb_var_screeninfo
+ * @mode: pointer to struct fb_videomode
+ */
+void fb_videomode_to_var(struct fb_var_screeninfo *var,
+			       struct fb_videomode *mode)
+{
+	var->xres = mode->xres;
+	var->yres = mode->yres;
+	var->pixclock = mode->pixclock;
+	var->left_margin = mode->left_margin;
+	var->hsync_len = mode->hsync_len;
+	var->vsync_len = mode->vsync_len;
+	var->right_margin = mode->right_margin;
+	var->upper_margin = mode->upper_margin;
+	var->lower_margin = mode->lower_margin;
+	var->sync = mode->sync;
+	var->vmode = mode->vmode & FB_VMODE_MASK;
+}
+
+/**
+ * fb_mode_is_equal - compare 2 videomodes
+ * @mode1: first videomode
+ * @mode2: second videomode
+ *
+ * RETURNS:
+ * 1 if equal, 0 if not
+ */
+int fb_mode_is_equal(struct fb_videomode *mode1,
+		     struct fb_videomode *mode2)
+{
+	return (mode1->xres         == mode2->xres &&
+		mode1->yres         == mode2->yres &&
+		mode1->pixclock     == mode2->pixclock &&
+		mode1->hsync_len    == mode2->hsync_len &&
+		mode1->vsync_len    == mode2->vsync_len &&
+		mode1->left_margin  == mode2->left_margin &&
+		mode1->right_margin == mode2->right_margin &&
+		mode1->upper_margin == mode2->upper_margin &&
+		mode1->lower_margin == mode2->lower_margin &&
+		mode1->sync         == mode2->sync &&
+		mode1->vmode        == mode2->vmode);
+}
+
+/**
+ * fb_find_best_mode - find best matching videomode
+ * @var: pointer to struct fb_var_screeninfo
+ * @head: pointer to struct list_head of modelist
+ *
+ * RETURNS:
+ * struct fb_videomode, NULL if none found
+ *
+ * IMPORTANT:
+ * This function assumes that all modelist entries in
+ * info->modelist are valid.
+ *
+ * NOTES:
+ * Finds best matching videomode which has an equal or greater dimension than
+ * var->xres and var->yres.  If more than 1 videomode is found, will return
+ * the videomode with the highest refresh rate
+ */
+struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var,
+				       struct list_head *head)
+{
+	struct list_head *pos;
+	struct fb_modelist *modelist;
+	struct fb_videomode *mode, *best = NULL;
+	u32 diff = -1;
+
+	list_for_each(pos, head) {
+		u32 d;
+
+		modelist = list_entry(pos, struct fb_modelist, list);
+		mode = &modelist->mode;
+
+		if (mode->xres >= var->xres && mode->yres >= var->yres) {
+			d = (mode->xres - var->xres) +
+				(mode->yres - var->yres);
+			if (diff > d) {
+				diff = d;
+				best = mode;
+			} else if (diff == d && mode->refresh > best->refresh)
+			    best = mode;
+		}
+	}
+	return best;
+}
+
+/**
+ * fb_match_mode - find a videomode which exactly matches the timings in var
+ * @var: pointer to struct fb_var_screeninfo
+ * @head: pointer to struct list_head of modelist
+ *
+ * RETURNS:
+ * struct fb_videomode, NULL if none found
+ */
+struct fb_videomode *fb_match_mode(struct fb_var_screeninfo *var,
+				   struct list_head *head)
+{
+	struct list_head *pos;
+	struct fb_modelist *modelist;
+	struct fb_videomode *m, mode;
+
+	fb_var_to_videomode(&mode, var);
+	list_for_each(pos, head) {
+		modelist = list_entry(pos, struct fb_modelist, list);
+		m = &modelist->mode;
+		if (fb_mode_is_equal(m, &mode))
+			return m;
+	}
+	return NULL;
+}
+
+/**
+ * fb_add_videomode: adds videomode entry to modelist
+ * @mode: videomode to add
+ * @head: struct list_head of modelist
+ *
+ * NOTES:
+ * Will only add unmatched mode entries
+ */
+int fb_add_videomode(struct fb_videomode *mode, struct list_head *head)
+{
+	struct list_head *pos;
+	struct fb_modelist *modelist;
+	struct fb_videomode *m;
+	int found = 0;
+
+	list_for_each(pos, head) {
+		modelist = list_entry(pos, struct fb_modelist, list);
+		m = &modelist->mode;
+		if (fb_mode_is_equal(m, mode)) {
+			found = 1;
+			break;
+		}
+	}
+	if (!found) {
+		modelist = kmalloc(sizeof(struct fb_modelist),
+						  GFP_KERNEL);
+
+		if (!modelist)
+			return -ENOMEM;
+		modelist->mode = *mode;
+		list_add(&modelist->list, head);
+	}
+	return 0;
+}
+
+/**
+ * fb_delete_videomode: removed videomode entry from modelist
+ * @mode: videomode to remove
+ * @head: struct list_head of modelist
+ *
+ * NOTES:
+ * Will remove all matching mode entries
+ */
+void fb_delete_videomode(struct fb_videomode *mode, struct list_head *head)
+{
+	struct list_head *pos, *n;
+	struct fb_modelist *modelist;
+	struct fb_videomode *m;
+
+	list_for_each_safe(pos, n, head) {
+		modelist = list_entry(pos, struct fb_modelist, list);
+		m = &modelist->mode;
+		if (fb_mode_is_equal(m, mode)) {
+			list_del(pos);
+			kfree(pos);
+		}
+	}
+}
+
+/**
+ * fb_destroy_modelist: destroy modelist
+ * @head: struct list_head of modelist
+ */
+void fb_destroy_modelist(struct list_head *head)
+{
+	struct list_head *pos, *n;
+
+	list_for_each_safe(pos, n, head) {
+		list_del(pos);
+		kfree(pos);
+	}
+}
+
+/**
+ * fb_videomode_to_modelist: convert mode array to mode list
+ * @modedb: array of struct fb_videomode
+ * @num: number of entries in array
+ * @head: struct list_head of modelist
+ */
+void fb_videomode_to_modelist(struct fb_videomode *modedb, int num,
+			      struct list_head *head)
+{
+	int i;
+
+	INIT_LIST_HEAD(head);
+
+	for (i = 0; i < num; i++) {
+		if (fb_add_videomode(&modedb[i], head))
+			return;
+	}
+}
+
+EXPORT_SYMBOL(fb_videomode_to_var);
+EXPORT_SYMBOL(fb_var_to_videomode);
+EXPORT_SYMBOL(fb_mode_is_equal);
+EXPORT_SYMBOL(fb_add_videomode);
+EXPORT_SYMBOL(fb_delete_videomode);
+EXPORT_SYMBOL(fb_destroy_modelist);
+EXPORT_SYMBOL(fb_match_mode);
+EXPORT_SYMBOL(fb_find_best_mode);
+EXPORT_SYMBOL(fb_videomode_to_modelist);
 EXPORT_SYMBOL(fb_find_mode);
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index dfa6e35d7..6ce5ba85c 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -93,7 +93,7 @@ static int external;
 static int libretto;
 static int nostretch;
 static int nopciburst;
-
+static char *mode_option __initdata = NULL;
 
 #ifdef MODULE
 
@@ -111,6 +111,8 @@ MODULE_PARM_DESC(nostretch,
 		 "Disable stretching of modes smaller than LCD.");
 MODULE_PARM(nopciburst, "i");
 MODULE_PARM_DESC(nopciburst, "Disable PCI burst mode.");
+MODULE_PARM(mode_option, "s");
+MODULE_PARM_DESC(mode_option, "Preferred video mode ('640x480-8@60', etc)");
 
 #endif
 
@@ -544,6 +546,10 @@ static inline void neo2200_accel_init(struct fb_info *info,
 		bltMod = NEO_MODE1_DEPTH16;
 		pitch = var->xres_virtual * 2;
 		break;
+	case 24:
+		bltMod = NEO_MODE1_DEPTH24;
+		pitch = var->xres_virtual * 3;
+		break;
 	default:
 		printk(KERN_ERR
 		       "neofb: neo2200_accel_init: unexpected bits per pixel!\n");
@@ -562,7 +568,7 @@ neofb_open(struct fb_info *info, int user)
 	struct neofb_par *par = (struct neofb_par *) info->par;
 	int cnt = atomic_read(&par->ref_count);
 
-	if (cnt) {
+	if (!cnt) {
 		memset(&par->state, 0, sizeof(struct vgastate));
 		par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
 		save_vga(&par->state);
@@ -695,6 +701,7 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 		var->green.offset = 8;
 		var->green.length = 8;
 		var->blue.offset = 0;
+		var->blue.length = 8;
 		break;
 
 #ifdef NO_32BIT_SUPPORT_YET
@@ -994,41 +1001,6 @@ static int neofb_set_par(struct fb_info *info)
 	/* Since we program the clocks ourselves, always use VCLK3. */
 	par->MiscOutReg |= 0x0C;
 
-	/* linear colormap for non palettized modes */
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		/* PseudoColor, 256 */
-		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
-		break;
-	case 16:
-		/* DirectColor, 64k */
-		info->fix.visual = FB_VISUAL_DIRECTCOLOR;
-
-		for (i = 0; i < 64; i++) {
-			outb(i, 0x3c8);
-
-			outb(i << 1, 0x3c9);
-			outb(i, 0x3c9);
-			outb(i << 1, 0x3c9);
-		}
-		break;
-	case 24:
-#ifdef NO_32BIT_SUPPORT_YET
-	case 32:
-#endif
-		/* TrueColor, 16m */
-		info->fix.visual = FB_VISUAL_TRUECOLOR;
-
-		for (i = 0; i < 256; i++) {
-			outb(i, 0x3c8);
-
-			outb(i, 0x3c9);
-			outb(i, 0x3c9);
-			outb(i, 0x3c9);
-		}
-		break;
-	}
-
 	/* alread unlocked above */
 	/* BOGUS  vga_wgfx(NULL, 0x09, 0x26); */
 
@@ -1090,6 +1062,41 @@ static int neofb_set_par(struct fb_info *info)
 	 * This function handles restoring the generic VGA registers.  */
 	vgaHWRestore(info, par);
 
+	/* linear colormap for non palettized modes */
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		/* PseudoColor, 256 */
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+	case 16:
+		/* TrueColor, 64k */
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+		for (i = 0; i < 64; i++) {
+			outb(i, 0x3c8);
+
+			outb(i << 1, 0x3c9);
+			outb(i, 0x3c9);
+			outb(i << 1, 0x3c9);
+		}
+		break;
+	case 24:
+#ifdef NO_32BIT_SUPPORT_YET
+	case 32:
+#endif
+		/* TrueColor, 16m */
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+		for (i = 0; i < 256; i++) {
+			outb(i, 0x3c8);
+
+			outb(i, 0x3c9);
+			outb(i, 0x3c9);
+			outb(i, 0x3c9);
+		}
+		break;
+	}
+
 	vga_wgfx(NULL, 0x0E, par->ExtCRTDispAddr);
 	vga_wgfx(NULL, 0x0F, par->ExtCRTOffset);
 	temp = vga_rgfx(NULL, 0x10);
@@ -1276,7 +1283,7 @@ static int neofb_pan_display(struct fb_var_screeninfo *var,
 static int neofb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 			   u_int transp, struct fb_info *fb)
 {
-	if (regno >= 255)
+	if (regno >= fb->cmap.len || regno > 255)
 		return -EINVAL;
 
 	switch (fb->var.bits_per_pixel) {
@@ -1288,25 +1295,20 @@ static int neofb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 		outb(blue >> 10, 0x3c9);
 		break;
 	case 16:
-		if (regno < 16)
-			((u16 *) fb->pseudo_palette)[regno] =
-			    ((red & 0xf800)) | ((green & 0xfc00) >> 5) |
-			    ((blue & 0xf800) >> 11);
+		((u32 *) fb->pseudo_palette)[regno] =
+				((red & 0xf800)) | ((green & 0xfc00) >> 5) |
+				((blue & 0xf800) >> 11);
 		break;
 	case 24:
-		if (regno < 16)
-			((u32 *) fb->pseudo_palette)[regno] =
-			    ((red & 0xff00) << 8) | ((green & 0xff00)) |
-			    ((blue & 0xff00) >> 8);
+		((u32 *) fb->pseudo_palette)[regno] =
+				((red & 0xff00) << 8) | ((green & 0xff00)) |
+				((blue & 0xff00) >> 8);
 		break;
 #ifdef NO_32BIT_SUPPORT_YET
 	case 32:
-		if (regno < 16)
-			((u32 *) fb->pseudo_palette)[regno] =
-			    ((transp & 0xff00) << 16) | ((red & 0xff00) <<
-							 8) | ((green &
-								0xff00)) |
-			    ((blue & 0xff00) >> 8);
+		((u32 *) fb->pseudo_palette)[regno] =
+				((transp & 0xff00) << 16) | ((red & 0xff00) << 8) |
+				((green & 0xff00)) | ((blue & 0xff00) >> 8);
 		break;
 #endif
 	default:
@@ -1318,27 +1320,33 @@ static int neofb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 /*
  *    (Un)Blank the display.
  */
-static int neofb_blank(int blank, struct fb_info *info)
+int neofb_blank(int blank_mode, struct fb_info *info)
 {
 	/*
-	 *  Blank the screen if blank_mode != 0, else unblank. If
-	 *  blank == NULL then the caller blanks by setting the CLUT
-	 *  (Color Look Up Table) to all black. Return 0 if blanking
-	 *  succeeded, != 0 if un-/blanking failed due to e.g. a
-	 *  video mode which doesn't support it. Implements VESA
-	 *  suspend and powerdown modes on hardware that supports
-	 *  disabling hsync/vsync:
-	 *    blank_mode == 2: suspend vsync
-	 *    blank_mode == 3: suspend hsync
-	 *    blank_mode == 4: powerdown
+	 *  Blank the screen if blank_mode != 0, else unblank.
+	 *  Return 0 if blanking succeeded, != 0 if un-/blanking failed due to
+	 *  e.g. a video mode which doesn't support it. Implements VESA suspend
+	 *  and powerdown modes for monitors, and backlight control on LCDs.
+	 *    blank_mode == 0: unblanked (backlight on)
+	 *    blank_mode == 1: blank (backlight on)
+	 *    blank_mode == 2: suspend vsync (backlight off)
+	 *    blank_mode == 3: suspend hsync (backlight off)
+	 *    blank_mode == 4: powerdown (backlight off)
 	 *
-	 *  wms...Enable VESA DMPS compatible powerdown mode
+	 *  wms...Enable VESA DPMS compatible powerdown mode
 	 *  run "setterm -powersave powerdown" to take advantage
 	 */
+	struct neofb_par *par = (struct neofb_par *)info->par;
+	int seqflags, lcdflags, dpmsflags, reg;
 
-	switch (blank) {
+	switch (blank_mode) {
 	case 4:		/* powerdown - both sync lines down */
+		seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */
+		lcdflags = 0;			/* LCD off */
+		dpmsflags = NEO_GR01_SUPPRESS_HSYNC |
+			    NEO_GR01_SUPPRESS_VSYNC;
 #ifdef CONFIG_TOSHIBA
+		/* Do we still need this ? */
 		/* attempt to turn off backlight on toshiba; also turns off external */
 		{
 			SMMRegisters regs;
@@ -1351,13 +1359,26 @@ static int neofb_blank(int blank, struct fb_info *info)
 #endif
 		break;
 	case 3:		/* hsync off */
+		seqflags = VGA_SR01_SCREEN_OFF;	/* Disable sequencer */
+		lcdflags = 0;			/* LCD off */
+		dpmsflags = NEO_GR01_SUPPRESS_HSYNC;
 		break;
 	case 2:		/* vsync off */
-		break;
-	case 1:		/* just software blanking of screen */
-		break;
-	default:		/* case 0, or anything else: unblank */
+		seqflags = VGA_SR01_SCREEN_OFF;	/* Disable sequencer */
+		lcdflags = 0;			/* LCD off */
+		dpmsflags = NEO_GR01_SUPPRESS_VSYNC;
+		break;
+	case 1:		/* just blank screen (backlight stays on) */
+		seqflags = VGA_SR01_SCREEN_OFF;	/* Disable sequencer */
+		lcdflags = par->PanelDispCntlReg1 & 0x02; /* LCD normal */
+		dpmsflags = 0;			/* no hsync/vsync suppression */
+		break;
+	case 0:		/* unblank */
+		seqflags = 0;			/* Enable sequencer */
+		lcdflags = par->PanelDispCntlReg1 & 0x02; /* LCD normal */
+		dpmsflags = 0x00;	/* no hsync/vsync suppression */
 #ifdef CONFIG_TOSHIBA
+		/* Do we still need this ? */
 		/* attempt to re-enable backlight/external on toshiba */
 		{
 			SMMRegisters regs;
@@ -1369,7 +1390,19 @@ static int neofb_blank(int blank, struct fb_info *info)
 		}
 #endif
 		break;
+	default:	/* Anything else we don't understand; return 1 to tell
+			 * fb_blank we didn't aactually do anything */
+		return 1;
 	}
+
+	neoUnlock();
+	reg = (vga_rseq(NULL, 0x01) & ~0x20) | seqflags;
+	vga_wseq(NULL, 0x01, reg);
+	reg = (vga_rgfx(NULL, 0x20) & ~0x02) | lcdflags;
+	vga_wgfx(NULL, 0x20, reg);
+	reg = (vga_rgfx(NULL, 0x01) & ~0xF0) | 0x80 | dpmsflags;
+	vga_wgfx(NULL, 0x01, reg);
+	neoLock(&par->state);
 	return 0;
 }
 
@@ -1396,8 +1429,9 @@ neo2200_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 		par->neo2200->fgColor = rect->color;
 		break;
 	case 16:
+	case 24:
 		par->neo2200->fgColor =
-		    ((u16 *) (info->pseudo_palette))[rect->color];
+		    ((u32 *) (info->pseudo_palette))[rect->color];
 		break;
 	}
 
@@ -1440,31 +1474,57 @@ neo2200_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 	    (area->height << 16) | (area->width & 0xffff);
 }
 
-/*
 static void
 neo2200_imageblit(struct fb_info *info, const struct fb_image *image)
 {
 	struct neofb_par *par = (struct neofb_par *) info->par;
+	int s_pitch = (image->width * image->depth + 7) >> 3;
+	int scan_align = info->pixmap.scan_align - 1;
+	int buf_align = info->pixmap.buf_align - 1;
+	int bltCntl_flags, d_pitch, data_len;
+
+	// The data is padded for the hardware
+	d_pitch = (s_pitch + scan_align) & ~scan_align;
+	data_len = ((d_pitch * image->height) + buf_align) & ~buf_align;
 
 	neo2200_sync(info);
 
+	if (image->depth == 1) {
+		if (info->var.bits_per_pixel == 24 && image->width < 16) {
+			/* FIXME. There is a bug with accelerated color-expanded
+			 * transfers in 24 bit mode if the image being transferred
+			 * is less than 16 bits wide. This is due to insufficient
+			 * padding when writing the image. We need to adjust
+			 * struct fb_pixmap. Not yet done. */
+			return cfb_imageblit(info, image);
+		}
+		bltCntl_flags = NEO_BC0_SRC_MONO;
+	} else if (image->depth == info->var.bits_per_pixel) {
+		bltCntl_flags = 0;
+	} else {
+		/* We don't currently support hardware acceleration if image
+		 * depth is different from display */
+		return cfb_imageblit(info, image);
+	}
+
 	switch (info->var.bits_per_pixel) {
 	case 8:
 		par->neo2200->fgColor = image->fg_color;
 		par->neo2200->bgColor = image->bg_color;
 		break;
 	case 16:
+	case 24:
 		par->neo2200->fgColor =
-		    ((u16 *) (info->pseudo_palette))[image->fg_color];
+		    ((u32 *) (info->pseudo_palette))[image->fg_color];
 		par->neo2200->bgColor =
-		    ((u16 *) (info->pseudo_palette))[image->bg_color];
+		    ((u32 *) (info->pseudo_palette))[image->bg_color];
 		break;
 	}
 
 	par->neo2200->bltCntl = NEO_BC0_SYS_TO_VID |
-	    NEO_BC0_SRC_MONO | NEO_BC3_SKIP_MAPPING |
-	    //                      NEO_BC3_DST_XY_ADDR |
-	    0x0c0000;
+		NEO_BC3_SKIP_MAPPING | bltCntl_flags |
+		// NEO_BC3_DST_XY_ADDR |
+		0x0c0000;
 
 	par->neo2200->srcStart = 0;
 //      par->neo2200->dstStart = (image->dy << 16) | (image->dx & 0xffff);
@@ -1474,10 +1534,8 @@ neo2200_imageblit(struct fb_info *info, const struct fb_image *image)
 	par->neo2200->xyExt =
 	    (image->height << 16) | (image->width & 0xffff);
 
-	memcpy(par->mmio_vbase + 0x100000, image->data,
-	       (image->width * image->height) >> 3);
+	memcpy(par->mmio_vbase + 0x100000, image->data, data_len);
 }
-*/
 
 static void
 neofb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
@@ -1514,23 +1572,18 @@ neofb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 static void
 neofb_imageblit(struct fb_info *info, const struct fb_image *image)
 {
-/*
-	if (image->depth == 1) {
-		switch (info->fix.accel) {
-			case FB_ACCEL_NEOMAGIC_NM2200:
-			case FB_ACCEL_NEOMAGIC_NM2230:
-			case FB_ACCEL_NEOMAGIC_NM2360:
-			case FB_ACCEL_NEOMAGIC_NM2380:
-				neo2200_imageblit(info, image);
-				break;
-			default:
-				cfb_imageblit(info, image);
-				break;
-		}
-	} else
-*/
-		cfb_imageblit(info, image);
-}	
+	switch (info->fix.accel) {
+		case FB_ACCEL_NEOMAGIC_NM2200:
+		case FB_ACCEL_NEOMAGIC_NM2230:
+		case FB_ACCEL_NEOMAGIC_NM2360:
+		case FB_ACCEL_NEOMAGIC_NM2380:
+			neo2200_imageblit(info, image);
+			break;
+		default:
+			cfb_imageblit(info, image);
+			break;
+	}
+}
 
 static int 
 neofb_sync(struct fb_info *info)
@@ -1623,48 +1676,9 @@ static struct fb_ops neofb_ops = {
 
 /* --------------------------------------------------------------------- */
 
-static struct fb_var_screeninfo __devinitdata neofb_var640x480x8 = {
-	.accel_flags    = FB_ACCELF_TEXT,
-	.xres           = 640,
-	.yres           = 480,
-	.xres_virtual   = 640,
-	.yres_virtual   = 30000,
-	.bits_per_pixel = 8,
-	.pixclock       = 39722,
-	.left_margin    = 48,
-	.right_margin   = 16,
-	.upper_margin   = 33,
-	.lower_margin   = 10,
-	.hsync_len      = 96,
-	.vsync_len      = 2,
-	.vmode          = FB_VMODE_NONINTERLACED
-};
-
-static struct fb_var_screeninfo __devinitdata neofb_var800x600x8 = {
-	.accel_flags    = FB_ACCELF_TEXT,
-	.xres           = 800,
-	.yres           = 600,
-	.xres_virtual   = 800,
-	.yres_virtual   = 30000,
-	.bits_per_pixel = 8,
-	.pixclock       = 25000,
-	.left_margin    = 88,
-	.right_margin   = 40,
-	.upper_margin   = 23,
-	.lower_margin   = 1,
-	.hsync_len      = 128,
-	.vsync_len      = 4,
-	.sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	.vmode          = FB_VMODE_NONINTERLACED
-};
-
-static struct fb_var_screeninfo __devinitdata neofb_var800x480x8 = {
-	.accel_flags    = FB_ACCELF_TEXT,
+static struct fb_videomode __devinitdata mode800x480 = {
 	.xres           = 800,
 	.yres           = 480,
-	.xres_virtual   = 800,
-	.yres_virtual   = 30000,
-	.bits_per_pixel = 8,
 	.pixclock       = 25000,
 	.left_margin    = 88,
 	.right_margin   = 40,
@@ -1676,44 +1690,6 @@ static struct fb_var_screeninfo __devinitdata neofb_var800x480x8 = {
 	.vmode          = FB_VMODE_NONINTERLACED
 };
 
-static struct fb_var_screeninfo __devinitdata neofb_var1024x768x8 = {
-	.accel_flags    = FB_ACCELF_TEXT,
-	.xres           = 1024,
-	.yres           = 768,
-	.xres_virtual   = 1024,
-	.yres_virtual   = 30000,
-	.bits_per_pixel = 8,
-	.pixclock       = 15385,
-	.left_margin    = 160,
-	.right_margin   = 24,
-	.upper_margin   = 29,
-	.lower_margin   = 3,
-	.hsync_len      = 136,
-	.vsync_len      = 6,
-	.sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	.vmode          = FB_VMODE_NONINTERLACED
-};
-
-#ifdef NOT_DONE
-static struct fb_var_screeninfo __devinitdata neofb_var1280x1024x8 = {
-	.accel_flags    = FB_ACCELF_TEXT,
-	.xres           = 1280,
-	.yres           = 1024,
-	.xres_virtual   = 1280,
-	.yres_virtual   = 30000,
-	.bits_per_pixel = 8,
-	.pixclock       = 9260,
-	.left_margin    = 248,
-	.right_margin   = 48,
-	.upper_margin   = 38,
-	.lower_margin   = 1,
-	.hsync_len      = 112,
-	.vsync_len      = 3,
-	.sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	.vmode          = FB_VMODE_NONINTERLACED
-};
-#endif
-
 static int __devinit neo_map_mmio(struct fb_info *info,
 				  struct pci_dev *dev)
 {
@@ -1803,11 +1779,15 @@ static int __devinit neo_map_video(struct fb_info *info,
 
 static void neo_unmap_video(struct fb_info *info)
 {
+	DBG("neo_unmap_video");
+
 #ifdef CONFIG_MTRR
-	struct neofb_par *par = (struct neofb_par *) info->par;
+	{
+		struct neofb_par *par = (struct neofb_par *) info->par;
 
-	mtrr_del(par->mtrr, info->fix.smem_start,
-		 info->fix.smem_len);
+		mtrr_del(par->mtrr, info->fix.smem_start,
+			 info->fix.smem_len);
+	}
 #endif
 	iounmap(info->screen_base);
 	info->screen_base = NULL;
@@ -1816,32 +1796,17 @@ static void neo_unmap_video(struct fb_info *info)
 			   info->fix.smem_len);
 }
 
-static int __devinit neo_init_hw(struct fb_info *info)
+static int __devinit neo_scan_monitor(struct fb_info *info)
 {
 	struct neofb_par *par = (struct neofb_par *) info->par;
 	unsigned char type, display;
-	int videoRam = 896;
-	int maxClock = 65000;
-	int CursorMem = 1024;
-	int CursorOff = 0x100;
-	int linearSize = 1024;
-	int maxWidth = 1024;
-	int maxHeight = 1024;
 	int w;
 
-	DBG("neo_init_hw");
-
-	neoUnlock();
-
-#if 0
-	printk(KERN_DEBUG "--- Neo extended register dump ---\n");
-	for (w = 0; w < 0x85; w++)
-		printk(KERN_DEBUG "CR %p: %p\n", (void *) w,
-		       (void *) vga_rcrt(NULL, w);
-	for (w = 0; w < 0xC7; w++)
-		printk(KERN_DEBUG "GR %p: %p\n", (void *) w,
-		       (void *) vga_rgfx(NULL, w));
-#endif
+	// Eventually we will have i2c support.
+	info->monspecs.modedb = kmalloc(sizeof(struct fb_videomode), GFP_KERNEL);
+	if (!info->monspecs.modedb)
+		return -ENOMEM;
+	info->monspecs.modedb_len = 1;
 
 	/* Determine the panel type */
 	vga_wgfx(NULL, 0x09, 0x26);
@@ -1860,26 +1825,34 @@ static int __devinit neo_init_hw(struct fb_info *info)
 	vga_wgfx(NULL, 0x09, 0x00);
 	switch ((w & 0x18) >> 3) {
 	case 0x00:
+		// 640x480@60
 		par->NeoPanelWidth = 640;
 		par->NeoPanelHeight = 480;
-		info->var = neofb_var640x480x8;
+		memcpy(info->monspecs.modedb, &vesa_modes[3], sizeof(struct fb_videomode));
 		break;
 	case 0x01:
 		par->NeoPanelWidth = 800;
-		par->NeoPanelHeight = par->libretto ? 480 : 600;
-		info->var = par->libretto ? neofb_var800x480x8 : neofb_var800x600x8;
+		if (par->libretto) {
+			par->NeoPanelHeight = 480;
+			memcpy(info->monspecs.modedb, &mode800x480, sizeof(struct fb_videomode));
+		} else {
+			// 800x600@60
+			par->NeoPanelHeight = 600;
+			memcpy(info->monspecs.modedb, &vesa_modes[8], sizeof(struct fb_videomode));
+		}
 		break;
 	case 0x02:
+		// 1024x768@60
 		par->NeoPanelWidth = 1024;
 		par->NeoPanelHeight = 768;
-		info->var = neofb_var1024x768x8;
+		memcpy(info->monspecs.modedb, &vesa_modes[13], sizeof(struct fb_videomode));
 		break;
 	case 0x03:
-		/* 1280x1024 panel support needs to be added */
+		/* 1280x1024@60 panel support needs to be added */
 #ifdef NOT_DONE
 		par->NeoPanelWidth = 1280;
 		par->NeoPanelHeight = 1024;
-		info->var = neofb_var1280x1024x8;
+		memcpy(info->monspecs.modedb, &vesa_modes[20], sizeof(struct fb_videomode));
 		break;
 #else
 		printk(KERN_ERR
@@ -1887,9 +1860,10 @@ static int __devinit neo_init_hw(struct fb_info *info)
 		return -1;
 #endif
 	default:
+		// 640x480@60
 		par->NeoPanelWidth = 640;
 		par->NeoPanelHeight = 480;
-		info->var = neofb_var640x480x8;
+		memcpy(info->monspecs.modedb, &vesa_modes[3], sizeof(struct fb_videomode));
 		break;
 	}
 
@@ -1898,7 +1872,33 @@ static int __devinit neo_init_hw(struct fb_info *info)
 	       par->NeoPanelHeight,
 	       (type & 0x02) ? "color" : "monochrome",
 	       (type & 0x10) ? "TFT" : "dual scan");
+	return 0;
+}
 
+static int __devinit neo_init_hw(struct fb_info *info)
+{
+	struct neofb_par *par = (struct neofb_par *) info->par;
+	int videoRam = 896;
+	int maxClock = 65000;
+	int CursorMem = 1024;
+	int CursorOff = 0x100;
+	int linearSize = 1024;
+	int maxWidth = 1024;
+	int maxHeight = 1024;
+
+	DBG("neo_init_hw");
+
+	neoUnlock();
+
+#if 0
+	printk(KERN_DEBUG "--- Neo extended register dump ---\n");
+	for (int w = 0; w < 0x85; w++)
+		printk(KERN_DEBUG "CR %p: %p\n", (void *) w,
+		       (void *) vga_rcrt(NULL, w);
+	for (int w = 0; w < 0xC7; w++)
+		printk(KERN_DEBUG "GR %p: %p\n", (void *) w,
+		       (void *) vga_rgfx(NULL, w));
+#endif
 	switch (info->fix.accel) {
 	case FB_ACCEL_NEOMAGIC_NM2070:
 		videoRam = 896;
@@ -2055,7 +2055,9 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st
 	info->fix.accel = id->driver_data;
 
 	info->fbops = &neofb_ops;
-	info->flags = FBINFO_FLAG_DEFAULT;
+	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
+		FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_COPYAREA |
+		FBINFO_HWACCEL_COPYAREA;
 	info->pseudo_palette = (void *) (par + 1);
 	return info;
 }
@@ -2078,8 +2080,7 @@ static int __devinit neofb_probe(struct pci_dev *dev,
 {
 	struct fb_info *info;
 	u_int h_sync, v_sync;
-	int err;
-	int video_len;
+	int video_len, err;
 
 	DBG("neofb_probe");
 
@@ -2096,6 +2097,10 @@ static int __devinit neofb_probe(struct pci_dev *dev,
 	if (err)
 		goto err_map_mmio;
 
+	err = neo_scan_monitor(info);
+	if (err)
+		goto err_scan_monitor;
+
 	video_len = neo_init_hw(info);
 	if (video_len < 0) {
 		err = video_len;
@@ -2106,8 +2111,11 @@ static int __devinit neofb_probe(struct pci_dev *dev,
 	if (err)
 		goto err_init_hw;
 
-	if (neofb_check_var(&info->var, info))
+	if (!fb_find_mode(&info->var, info, mode_option, NULL, 0,
+			info->monspecs.modedb, 16)) {
+		printk(KERN_ERR "neofb: Unable to find usable video mode.\n");
 		goto err_map_video;
+	}
 
 	/*
 	 * Calculate the hsync and vsync frequencies.  Note that
@@ -2149,6 +2157,8 @@ err_reg_fb:
 err_map_video:
 	neo_unmap_video(info);
 err_init_hw:
+	fb_destroy_modedb(info->monspecs.modedb);
+err_scan_monitor:
 	neo_unmap_mmio(info);
 err_map_mmio:
 	neo_free_fb_info(info);
@@ -2172,6 +2182,7 @@ static void __devexit neofb_remove(struct pci_dev *dev)
 			       "neofb: danger danger!  Oopsen imminent!\n");
 
 		neo_unmap_video(info);
+		fb_destroy_modedb(info->monspecs.modedb);
 		neo_unmap_mmio(info);
 		neo_free_fb_info(info);
 
@@ -2240,31 +2251,39 @@ int __init neofb_setup(char *options)
 
 		if (!strncmp(this_opt, "internal", 8))
 			internal = 1;
-		if (!strncmp(this_opt, "external", 8))
+		else if (!strncmp(this_opt, "external", 8))
 			external = 1;
-		if (!strncmp(this_opt, "nostretch", 9))
+		else if (!strncmp(this_opt, "nostretch", 9))
 			nostretch = 1;
-		if (!strncmp(this_opt, "nopciburst", 10))
+		else if (!strncmp(this_opt, "nopciburst", 10))
 			nopciburst = 1;
-		if (!strncmp(this_opt, "libretto", 8))
+		else if (!strncmp(this_opt, "libretto", 8))
 			libretto = 1;
+		else
+			mode_option = this_opt;
 	}
-
 	return 0;
 }
 
 int __init neofb_init(void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("neofb", &option))
+		return -ENODEV;
+	neofb_setup(option);
+#endif
 	return pci_register_driver(&neofb_driver);
 }
 
-#ifdef MODULE
+module_init(neofb_init);
 
+#ifdef MODULE
 static void __exit neofb_exit(void)
 {
 	pci_unregister_driver(&neofb_driver);
 }
 
-module_init(neofb_init);
 module_exit(neofb_exit);
 #endif				/* MODULE */
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index 99c2e6322..92a41f71e 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -28,7 +28,8 @@
 #include <linux/ioport.h>
 #include <asm/io.h>
 #include <asm/prom.h>
-#ifdef CONFIG_BOOTX_TEXT
+
+#ifdef CONFIG_PPC32
 #include <asm/bootx.h>
 #endif
 
@@ -70,7 +71,7 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 			  u_int transp, struct fb_info *info);
 static int offb_blank(int blank, struct fb_info *info);
 
-#ifdef CONFIG_BOOTX_TEXT
+#ifdef CONFIG_PPC32
 extern boot_infos_t *boot_infos;
 #endif
 
@@ -245,18 +246,20 @@ static int offb_blank(int blank, struct fb_info *info)
 
 int __init offb_init(void)
 {
-	struct device_node *dp;
-	unsigned int dpy;
+	struct device_node *dp = NULL, *boot_disp = NULL;
 #if defined(CONFIG_BOOTX_TEXT) && defined(CONFIG_PPC32)
-	struct device_node *displays = find_type_devices("display");
 	struct device_node *macos_display = NULL;
+#endif
+	if (fb_get_options("offb", NULL))
+		return -ENODEV;
 
+#if defined(CONFIG_BOOTX_TEXT) && defined(CONFIG_PPC32)
 	/* If we're booted from BootX... */
-	if (prom_num_displays == 0 && boot_infos != 0) {
+	if (boot_infos != 0) {
 		unsigned long addr =
 		    (unsigned long) boot_infos->dispDeviceBase;
 		/* find the device node corresponding to the macos display */
-		for (dp = displays; dp != NULL; dp = dp->next) {
+		while ((dp = of_find_node_by_type(dp, "display"))) {
 			int i;
 			/*
 			 * Grrr...  It looks like the MacOS ATI driver
@@ -325,10 +328,19 @@ int __init offb_init(void)
 	}
 #endif /* defined(CONFIG_BOOTX_TEXT) && defined(CONFIG_PPC32) */
 
-	for (dpy = 0; dpy < prom_num_displays; dpy++) {
-		if ((dp = find_path_device(prom_display_paths[dpy])))
+	for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) {
+		if (get_property(dp, "linux,opened", NULL) &&
+		    get_property(dp, "linux,boot-display", NULL)) {
+			boot_disp = dp;
 			offb_init_nodriver(dp);
+		}
 	}
+	for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) {
+		if (get_property(dp, "linux,opened", NULL) &&
+		    dp != boot_disp)
+			offb_init_nodriver(dp);
+	}
+
 	return 0;
 }
 
@@ -527,7 +539,7 @@ static void __init offb_init_fb(const char *name, const char *full_name,
 	info->screen_base = ioremap(address, fix->smem_len);
 	info->par = par;
 	info->pseudo_palette = (void *) (info + 1);
-	info->flags = FBINFO_FLAG_DEFAULT;
+	info->flags = FBINFO_DEFAULT;
 
 	fb_alloc_cmap(&info->cmap, 256, 0);
 
@@ -541,4 +553,5 @@ static void __init offb_init_fb(const char *name, const char *full_name,
 	       info->node, full_name);
 }
 
+module_init(offb_init);
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c
index 67b71d5a4..7fbbef461 100644
--- a/drivers/video/p9100.c
+++ b/drivers/video/p9100.c
@@ -297,7 +297,7 @@ static void p9100_init_one(struct sbus_dev *sdev)
 		sbus_ioremap(&sdev->resource[0], 0,
 			     sizeof(struct p9100_regs), "p9100 regs");
 
-	all->info.flags = FBINFO_FLAG_DEFAULT;
+	all->info.flags = FBINFO_DEFAULT;
 	all->info.fbops = &p9100_ops;
 #ifdef CONFIG_SPARC32
 	all->info.screen_base = (char *)
@@ -340,6 +340,9 @@ int __init p9100_init(void)
 	struct sbus_bus *sbus;
 	struct sbus_dev *sdev;
 
+	if (fb_get_options("p9100fb", NULL))
+		return -ENODEV;
+
 	for_all_sbusdev(sdev, sbus) {
 		if (!strcmp(sdev->prom_name, "p9100"))
 			p9100_init_one(sdev);
@@ -368,8 +371,9 @@ p9100_setup(char *arg)
 	return 0;
 }
 
-#ifdef MODULE
 module_init(p9100_init);
+
+#ifdef MODULE
 module_exit(p9100_exit);
 #endif
 
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index feba14a60..5ad8308bf 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -311,7 +311,7 @@ static void __devinit platinum_init_info(struct fb_info *info, struct fb_info_pl
 	/* Fill fb_info */
 	info->fbops = &platinumfb_ops;
 	info->pseudo_palette = pinfo->pseudo_palette;
-        info->flags = FBINFO_FLAG_DEFAULT;
+        info->flags = FBINFO_DEFAULT;
 	info->screen_base = (char *) pinfo->frame_buffer + 0x20;
 
 	fb_alloc_cmap(&info->cmap, 256, 0);
@@ -667,6 +667,13 @@ static struct of_platform_driver platinum_driver =
 
 int __init platinumfb_init(void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("platinumfb", &option))
+		return -ENODEV;
+	platinumfb_setup(option);
+#endif
 	of_register_driver(&platinum_driver);
 
 	return 0;
@@ -679,8 +686,8 @@ void __exit platinumfb_exit(void)
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("framebuffer driver for Apple Platinum video");
+module_init(platinumfb_init);
 
 #ifdef MODULE
-module_init(platinumfb_init);
 module_exit(platinumfb_exit);
 #endif
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 61953c1e1..92f539a65 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -1124,7 +1124,8 @@ static int __devinit pm2fb_probe(struct pci_dev *pdev,
 	info->fbops		= &pm2fb_ops;
 	info->fix		= pm2fb_fix; 	
 	info->pseudo_palette	= (void *)(default_par + 1); 
-	info->flags		= FBINFO_FLAG_DEFAULT;
+	info->flags		= FBINFO_DEFAULT |
+                                  FBINFO_HWACCEL_YPAN;
 
 #ifndef MODULE
 	if (!mode)
@@ -1214,8 +1215,18 @@ MODULE_DEVICE_TABLE(pci, pm2fb_id_table);
  *  Initialization
  */
 
+int __init pm2fb_setup(char *options);
+
 int __init pm2fb_init(void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("pm2fb", &option))
+		return -ENODEV;
+	pm2fb_setup(option);
+#endif
+
 	return pci_module_init(&pm2fb_driver);
 }
 
@@ -1265,9 +1276,7 @@ int __init pm2fb_setup(char *options)
 
 
 
-#ifdef MODULE
 module_init(pm2fb_init);
-#endif 
 module_exit(pm2fb_exit);
 
 MODULE_PARM(mode,"s");
diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c
index 45e326573..0d07707d9 100644
--- a/drivers/video/pmag-ba-fb.c
+++ b/drivers/video/pmag-ba-fb.c
@@ -142,7 +142,7 @@ int __init pmagbafb_init_one(int slot)
 	info->var = pmagbafb_defined;
 	info->fix = pmagbafb_fix; 
 	info->screen_base = pmagbafb_fix.smem_start;
-	info->flags = FBINFO_FLAG_DEFAULT;
+	info->flags = FBINFO_DEFAULT;
 
 	fb_alloc_cmap(&fb_info.cmap, 256, 0);
 	
@@ -160,6 +160,9 @@ int __init pmagbafb_init(void)
 	int sid;
 	int found = 0;
 
+	if (fb_get_options("pmagbafb", NULL))
+		return -ENODEV;
+
 	if (TURBOCHANNEL) {
 		while ((sid = search_tc_card("PMAG-BA")) >= 0) {
 			found = 1;
@@ -172,4 +175,5 @@ int __init pmagbafb_init(void)
 	}
 }
 
+module_init(pmagbafb_init);
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c
index 16847d8d8..7847bed73 100644
--- a/drivers/video/pmagb-b-fb.c
+++ b/drivers/video/pmagb-b-fb.c
@@ -145,7 +145,7 @@ int __init pmagbbfb_init_one(int slot)
 	info->var = pmagbbfb_defined;
 	info->fix = pmagbbfb_fix;
 	info->screen_base = pmagbbfb_fix.smem_start; 
-	info->flags = FBINFO_FLAG_DEFAULT;
+	info->flags = FBINFO_DEFAULT;
 
 	fb_alloc_cmap(&fb_info.cmap, 256, 0);
 
@@ -163,6 +163,9 @@ int __init pmagbbfb_init(void)
 	int sid;
 	int found = 0;
 
+	if (fb_get_options("pmagbbfb", NULL))
+		return -ENODEV;
+
 	if (TURBOCHANNEL) {
 		while ((sid = search_tc_card("PMAGB-BA")) >= 0) {
 			found = 1;
@@ -175,4 +178,5 @@ int __init pmagbbfb_init(void)
 	}
 }
 
+module_init(pmagbbfb_init);
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index 5f63f10af..a6ecf9674 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -795,7 +795,7 @@ static int __init pvr2fb_common_init(void)
 	fb_info->fix		= pvr2_fix;
 	fb_info->par		= currentpar;
 	fb_info->pseudo_palette	= (void *)(fb_info->par + 1);
-	fb_info->flags		= FBINFO_FLAG_DEFAULT;
+	fb_info->flags		= FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 
 	if (video_output == VO_VGA)
 		defmode = DEFMODE_VGA;
@@ -1057,6 +1057,13 @@ int __init pvr2fb_init(void)
 	int i, ret = -ENODEV;
 	int size;
 
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("pvr2fb", &option))
+		return -ENODEV;
+	pvr2fb_setup(option);
+#endif
 	size = sizeof(struct fb_info) + sizeof(struct pvr2fb_par) + 16 * sizeof(u32);
 
 	fb_info = kmalloc(size, GFP_KERNEL);
@@ -1108,9 +1115,7 @@ static void __exit pvr2fb_exit(void)
 	kfree(fb_info);
 }
 
-#ifdef MODULE
 module_init(pvr2fb_init);
-#endif
 module_exit(pvr2fb_exit);
 
 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>");
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 0a860dd88..3e2bb2d88 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -43,6 +43,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/bitfield.h>
 #include <asm/arch/pxafb.h>
 
@@ -1040,7 +1041,7 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
 	fbi->fb.var.vmode	= FB_VMODE_NONINTERLACED;
 
 	fbi->fb.fbops		= &pxafb_ops;
-	fbi->fb.flags		= FBINFO_FLAG_DEFAULT;
+	fbi->fb.flags		= FBINFO_DEFAULT;
 	fbi->fb.node		= -1;
 	fbi->fb.currcon		= -1;
 
@@ -1359,11 +1360,6 @@ static struct device_driver pxafb_driver = {
 #endif
 };
 
-int __devinit pxafb_init(void)
-{
-	return driver_register(&pxafb_driver);
-}
-
 #ifndef MODULE
 int __devinit pxafb_setup(char *options)
 {
@@ -1373,12 +1369,25 @@ int __devinit pxafb_setup(char *options)
 	return 0;
 }
 #else
-module_init(pxafb_init);
 # ifdef CONFIG_FB_PXA_PARAMETERS
 module_param_string(options, g_options, sizeof(g_options), 0);
 MODULE_PARM_DESC(options, "LCD parameters (see Documentation/fb/pxafb.txt)");
 # endif
 #endif
 
+int __devinit pxafb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("pxafb", &option))
+		return -ENODEV;
+	pxafb_setup(option);
+#endif
+	return driver_register(&pxafb_driver);
+}
+
+module_init(pxafb_init);
+
 MODULE_DESCRIPTION("loadable framebuffer driver for PXA");
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c
index 0c7b267e4..71b69da0c 100644
--- a/drivers/video/q40fb.c
+++ b/drivers/video/q40fb.c
@@ -105,7 +105,7 @@ static int __init q40fb_probe(struct device *device)
 	info->var = q40fb_var;
 	info->fix = q40fb_fix;
 	info->fbops = &q40fb_ops;
-	info->flags = FBINFO_FLAG_DEFAULT;  /* not as module for now */
+	info->flags = FBINFO_DEFAULT;  /* not as module for now */
 	info->pseudo_palette = info->par;
 	info->par = NULL;
 	info->screen_base = (char *) q40fb_fix.smem_start;
@@ -143,6 +143,9 @@ int __init q40fb_init(void)
 {
 	int ret = 0;
 
+	if (fb_get_options("q40fb", NULL))
+		return -ENODEV;
+
 	ret = driver_register(&q40fb_driver);
 
 	if (!ret) {
@@ -153,4 +156,5 @@ int __init q40fb_init(void)
 	return ret;
 }
 
+module_init(q40fb_init);
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
index 1f3f23f3c..eedb2b8e9 100644
--- a/drivers/video/radeonfb.c
+++ b/drivers/video/radeonfb.c
@@ -360,13 +360,13 @@ struct radeonfb_info {
 	unsigned long mmio_base_phys;
 	unsigned long fb_base_phys;
 
-	unsigned long mmio_base;
-	unsigned long fb_base;
+	void __iomem *mmio_base;
+	void __iomem *fb_base;
 
 	struct pci_dev *pdev;
 
 	unsigned char *EDID;
-	unsigned char *bios_seg;
+	unsigned char __iomem *bios_seg;
 
 	u32 pseudo_palette[17];
 	struct { u8 red, green, blue, pad; } palette[256];
@@ -702,8 +702,8 @@ static void radeon_write_mode (struct radeonfb_info *rinfo,
 static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo);
 static int __devinit radeon_init_disp (struct radeonfb_info *rinfo);
 static int radeon_init_disp_var (struct radeonfb_info *rinfo, struct fb_var_screeninfo *var);
-static char *radeon_find_rom(struct radeonfb_info *rinfo);
-static void radeon_get_pllinfo(struct radeonfb_info *rinfo, char *bios_seg);
+static void __iomem *radeon_find_rom(struct radeonfb_info *rinfo);
+static void radeon_get_pllinfo(struct radeonfb_info *rinfo, void __iomem *bios_seg);
 static void radeon_get_moninfo (struct radeonfb_info *rinfo);
 static int radeon_get_dfpinfo (struct radeonfb_info *rinfo);
 static int radeon_get_dfpinfo_BIOS(struct radeonfb_info *rinfo);
@@ -735,12 +735,12 @@ static struct backlight_controller radeon_backlight_controller = {
 #endif /* CONFIG_PPC_OF */
 
 
-static char *radeon_find_rom(struct radeonfb_info *rinfo)
+static void __iomem *radeon_find_rom(struct radeonfb_info *rinfo)
 {       
 #if defined(__i386__)
         u32  segstart;
-        char *rom_base;
-        char *rom;
+        char __iomem *rom_base;
+        char __iomem *rom;
         int  stage;
         int  i,j;       
         char aty_rom_sig[] = "761295520";
@@ -753,7 +753,7 @@ static char *radeon_find_rom(struct radeonfb_info *rinfo)
                         
                 stage = 1;
                 
-                rom_base = (char *)ioremap(segstart, 0x1000);
+                rom_base = ioremap(segstart, 0x1000);
 
                 if ((*rom_base == 0x55) && (((*(rom_base + 1)) & 0xff) == 0xaa))
                         stage = 2;
@@ -804,10 +804,10 @@ static char *radeon_find_rom(struct radeonfb_info *rinfo)
 
 
 
-static void radeon_get_pllinfo(struct radeonfb_info *rinfo, char *bios_seg)
+static void radeon_get_pllinfo(struct radeonfb_info *rinfo, void __iomem *bios_seg)
 {
-        void *bios_header;
-        void *header_ptr;
+        void __iomem *bios_header;
+        void __iomem *header_ptr;
         u16 bios_header_offset, pll_info_offset;
         PLL_BLOCK pll;
 
@@ -1077,7 +1077,7 @@ static void radeon_update_default_var(struct radeonfb_info *rinfo)
 
 static int radeon_get_dfpinfo_BIOS(struct radeonfb_info *rinfo)
 {
-	char *fpbiosstart, *tmp, *tmp0;
+	char __iomem *fpbiosstart, *tmp, *tmp0;
 	char stmp[30];
 	int i;
 
@@ -2250,9 +2250,9 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo)
 	info->currcon = -1;
 	info->par = rinfo;
 	info->pseudo_palette = rinfo->pseudo_palette;
-        info->flags = FBINFO_FLAG_DEFAULT;
+        info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
         info->fbops = &radeonfb_ops;
-        info->screen_base = (char *)rinfo->fb_base;
+        info->screen_base = rinfo->fb_base;
 
 	/* Fill fix common fields */
 	strlcpy(info->fix.id, rinfo->name, sizeof(info->fix.id));
@@ -2851,7 +2851,7 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
 	}
 
 	/* map the regions */
-	rinfo->mmio_base = (unsigned long) ioremap (rinfo->mmio_base_phys, RADEON_REGSIZE);
+	rinfo->mmio_base = ioremap (rinfo->mmio_base_phys, RADEON_REGSIZE);
 	if (!rinfo->mmio_base) {
 		printk ("radeonfb: cannot map MMIO\n");
 		release_mem_region (rinfo->mmio_base_phys,
@@ -2978,7 +2978,7 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
 	if ((rinfo->dviDisp_type == MT_DFP) || (rinfo->dviDisp_type == MT_LCD) ||
 	    (rinfo->crtDisp_type == MT_DFP)) {
 		if (!radeon_get_dfpinfo(rinfo)) {
-			iounmap ((void*)rinfo->mmio_base);
+			iounmap(rinfo->mmio_base);
 			release_mem_region (rinfo->mmio_base_phys,
 					    pci_resource_len(pdev, 2));
 			release_mem_region (rinfo->fb_base_phys,
@@ -2988,10 +2988,10 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
 		}
 	}
 
-	rinfo->fb_base = (unsigned long) ioremap (rinfo->fb_base_phys, rinfo->video_ram);
+	rinfo->fb_base = ioremap (rinfo->fb_base_phys, rinfo->video_ram);
 	if (!rinfo->fb_base) {
 		printk ("radeonfb: cannot map FB\n");
-		iounmap ((void*)rinfo->mmio_base);
+		iounmap(rinfo->mmio_base);
 		release_mem_region (rinfo->mmio_base_phys,
 				    pci_resource_len(pdev, 2));
 		release_mem_region (rinfo->fb_base_phys,
@@ -3043,8 +3043,8 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
 
 	if (register_framebuffer ((struct fb_info *) rinfo) < 0) {
 		printk ("radeonfb: could not register framebuffer\n");
-		iounmap ((void*)rinfo->fb_base);
-		iounmap ((void*)rinfo->mmio_base);
+		iounmap(rinfo->fb_base);
+		iounmap(rinfo->mmio_base);
 		release_mem_region (rinfo->mmio_base_phys,
 				    pci_resource_len(pdev, 2));
 		release_mem_region (rinfo->fb_base_phys,
@@ -3113,8 +3113,8 @@ static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
 
         unregister_framebuffer ((struct fb_info *) rinfo);
                 
-        iounmap ((void*)rinfo->mmio_base);
-        iounmap ((void*)rinfo->fb_base);
+        iounmap(rinfo->mmio_base);
+        iounmap(rinfo->fb_base);
  
 	release_mem_region (rinfo->mmio_base_phys,
 			    pci_resource_len(pdev, 2));
@@ -3132,9 +3132,17 @@ static struct pci_driver radeonfb_driver = {
 	.remove		= __devexit_p(radeonfb_pci_unregister),
 };
 
+int __init radeonfb_old_setup (char *options);
 
 int __init radeonfb_old_init (void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("radeonfb_old", &option))
+		return -ENODEV;
+	radeonfb_old_setup(option);
+#endif
 	return pci_module_init (&radeonfb_driver);
 }
 
@@ -3172,8 +3180,9 @@ int __init radeonfb_old_setup (char *options)
 	return 0;
 }
 
-#ifdef MODULE
 module_init(radeonfb_old_init);
+
+#ifdef MODULE
 module_exit(radeonfb_old_exit);
 #endif
 
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index fec702460..825b39dbe 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -111,177 +111,87 @@ static int rivafb_blank(int blank, struct fb_info *info);
  *
  * ------------------------------------------------------------------------- */
 
-enum riva_chips {
-	CH_RIVA_128 = 0,
-	CH_RIVA_TNT,
-	CH_RIVA_TNT2,
-	CH_RIVA_UTNT2,
-	CH_RIVA_VTNT2,
-	CH_RIVA_UVTNT2,
-	CH_RIVA_ITNT2,
-	CH_GEFORCE_SDR,
-	CH_GEFORCE_DDR,
-	CH_QUADRO,
-	CH_GEFORCE2_MX,
-	CH_GEFORCE2_MX2,
-	CH_GEFORCE2_GO,
-	CH_QUADRO2_MXR,
-	CH_GEFORCE2_GTS,
-	CH_GEFORCE2_GTS2,
-	CH_GEFORCE2_ULTRA,
-	CH_QUADRO2_PRO,
-	CH_GEFORCE4_MX_460,
-	CH_GEFORCE4_MX_440,
-	CH_GEFORCE4_MX_420,
-	CH_GEFORCE4_440_GO,
-	CH_GEFORCE4_420_GO,
-	CH_GEFORCE4_420_GO_M32,
-	CH_QUADRO4_500XGL,
-	CH_GEFORCE4_440_GO_M64,
-	CH_QUADRO4_200,
-	CH_QUADRO4_550XGL,
-	CH_QUADRO4_500_GOGL,
-	CH_IGEFORCE2,
-	CH_GEFORCE3,
-	CH_GEFORCE3_1,
-	CH_GEFORCE3_2,
-	CH_QUADRO_DDC,
-	CH_GEFORCE4_TI_4600,
-	CH_GEFORCE4_TI_4400,
-	CH_GEFORCE4_TI_4200,
-	CH_QUADRO4_900XGL,
-	CH_QUADRO4_750XGL,
-	CH_QUADRO4_700XGL
-};
-
-/* directly indexed by riva_chips enum, above */
-static struct riva_chip_info {
-	const char *name;
-	unsigned arch_rev;
-} riva_chip_info[] __initdata = {
-	{ "RIVA-128", NV_ARCH_03 },
-	{ "RIVA-TNT", NV_ARCH_04 },
-	{ "RIVA-TNT2", NV_ARCH_04 },
-	{ "RIVA-UTNT2", NV_ARCH_04 },
-	{ "RIVA-VTNT2", NV_ARCH_04 },
-	{ "RIVA-UVTNT2", NV_ARCH_04 },
-	{ "RIVA-ITNT2", NV_ARCH_04 },
-	{ "GeForce-SDR", NV_ARCH_10 },
-	{ "GeForce-DDR", NV_ARCH_10 },
-	{ "Quadro", NV_ARCH_10 },
-	{ "GeForce2-MX", NV_ARCH_10 },
-	{ "GeForce2-MX", NV_ARCH_10 },
-	{ "GeForce2-GO", NV_ARCH_10 },
-	{ "Quadro2-MXR", NV_ARCH_10 },
-	{ "GeForce2-GTS", NV_ARCH_10 },
-	{ "GeForce2-GTS", NV_ARCH_10 },
-	{ "GeForce2-ULTRA", NV_ARCH_10 },
-	{ "Quadro2-PRO", NV_ARCH_10 },
-	{ "GeForce4-MX-460", NV_ARCH_10 },
-	{ "GeForce4-MX-440", NV_ARCH_10 },
-	{ "GeForce4-MX-420", NV_ARCH_10 },
-	{ "GeForce4-440-GO", NV_ARCH_10 },
-	{ "GeForce4-420-GO", NV_ARCH_10 },
-	{ "GeForce4-420-GO-M32", NV_ARCH_10 },
-	{ "Quadro4-500-XGL", NV_ARCH_10 },
-	{ "GeForce4-440-GO-M64", NV_ARCH_10 },
-	{ "Quadro4-200", NV_ARCH_10 },
-	{ "Quadro4-550-XGL", NV_ARCH_10 },
-	{ "Quadro4-500-GOGL", NV_ARCH_10 },
-	{ "GeForce2", NV_ARCH_10 },
-	{ "GeForce3", NV_ARCH_20 }, 
-	{ "GeForce3 Ti 200", NV_ARCH_20 },
-	{ "GeForce3 Ti 500", NV_ARCH_20 },
-	{ "Quadro DDC", NV_ARCH_20 },
-	{ "GeForce4 Ti 4600", NV_ARCH_20 },
-	{ "GeForce4 Ti 4400", NV_ARCH_20 },
-	{ "GeForce4 Ti 4200", NV_ARCH_20 },
-	{ "Quadro4-900-XGL", NV_ARCH_20 },
-	{ "Quadro4-750-XGL", NV_ARCH_20 },
-	{ "Quadro4-700-XGL", NV_ARCH_20 }
-};
-
 static struct pci_device_id rivafb_pci_tbl[] = {
 	{ PCI_VENDOR_ID_NVIDIA_SGS, PCI_DEVICE_ID_NVIDIA_SGS_RIVA128,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_128 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_TNT },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_TNT2 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UTNT2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_UTNT2 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_VTNT2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_VTNT2 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UVTNT2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_VTNT2 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_ITNT2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_ITNT2 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE_SDR },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE_DDR },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_MX },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_MX2 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_GO },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO2_MXR },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_GTS },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_GTS2 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_ULTRA },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO2_PRO },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_MX_460 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_MX_440 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_MX_420 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_440_GO },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_420_GO },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_420_GO_M32 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_500XGL },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_440_GO_M64 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_200,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_200 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_550XGL },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_500_GOGL },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_IGEFORCE2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_IGEFORCE2 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_1,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3_1 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_2,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3_2 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_DDC,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO_DDC },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_TI_4600 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_TI_4400 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_TI_4200 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
  	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_900XGL },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_750XGL },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_700XGL },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ 0, } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
@@ -293,7 +203,6 @@ MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
  * ------------------------------------------------------------------------- */
 
 /* command line data, set in rivafb_setup() */
-static u32 pseudo_palette[17];
 static int flatpanel __initdata = -1; /* Autodetect later */
 static int forceCRTC __initdata = -1;
 #ifdef CONFIG_MTRR
@@ -303,14 +212,13 @@ static int nomtrr __initdata = 0;
 static char *mode_option __initdata = NULL;
 static int  strictmode       = 0;
 
-static struct fb_fix_screeninfo rivafb_fix = {
-	.id		= "nVidia",
+static struct fb_fix_screeninfo __initdata rivafb_fix = {
 	.type		= FB_TYPE_PACKED_PIXELS,
 	.xpanstep	= 1,
 	.ypanstep	= 1,
 };
 
-static struct fb_var_screeninfo rivafb_default_var = {
+static struct fb_var_screeninfo __initdata rivafb_default_var = {
 	.xres		= 640,
 	.yres		= 480,
 	.xres_virtual	= 640,
@@ -533,6 +441,8 @@ static void rivafb_load_cursor_image(struct riva_par *par, u8 *data8,
 	int i, j, k = 0;
 	u32 b, tmp;
 	u32 *data = (u32 *)data8;
+	bg = le16_to_cpu(bg);
+	fg = le16_to_cpu(fg);
 
 	for (i = 0; i < h; i++) {
 		b = *data++;
@@ -606,7 +516,7 @@ static void riva_rclut(RIVA_HW_INST *chip,
 		       unsigned char *green, unsigned char *blue)
 {
 	
-	VGA_WR08(chip->PDIO, 0x3c8, regnum);
+	VGA_WR08(chip->PDIO, 0x3c7, regnum);
 	*red = VGA_RD08(chip->PDIO, 0x3c9);
 	*green = VGA_RD08(chip->PDIO, 0x3c9);
 	*blue = VGA_RD08(chip->PDIO, 0x3c9);
@@ -1090,13 +1000,15 @@ static int rivafb_open(struct fb_info *info, int user)
 
 	NVTRACE_ENTER();
 	if (!cnt) {
+#ifdef CONFIG_X86
 		memset(&par->state, 0, sizeof(struct vgastate));
 		par->state.flags = VGA_SAVE_MODE  | VGA_SAVE_FONTS;
 		/* save the DAC for Riva128 */
 		if (par->riva.Architecture == NV_ARCH_03)
 			par->state.flags |= VGA_SAVE_CMAP;
 		save_vga(&par->state);
-
+#endif
+		riva_common_setup(par);
 		RivaGetConfig(&par->riva, par->Chipset);
 		/* vgaHWunlock() + riva unlock (0x7F) */
 		CRTCout(par, 0x11, 0xFF);
@@ -1121,7 +1033,9 @@ static int rivafb_release(struct fb_info *info, int user)
 		par->riva.LockUnlock(&par->riva, 0);
 		par->riva.LoadStateExt(&par->riva, &par->initial_state.ext);
 		riva_load_state(par, &par->initial_state);
+#ifdef CONFIG_X86
 		restore_vga(&par->state);
+#endif
 		par->riva.LockUnlock(&par->riva, 1);
 	}
 	atomic_dec(&par->ref_count);
@@ -1131,7 +1045,8 @@ static int rivafb_release(struct fb_info *info, int user)
 
 static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
-	struct fb_monspecs *specs = &info->monspecs;
+	struct fb_videomode *mode;
+	struct riva_par *par = (struct riva_par *) info->par;
 	int nom, den;		/* translating from pixels->bytes */
 	int mode_valid = 0;
 	
@@ -1148,6 +1063,9 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 		/* fall through */
 	case 16:
 		var->bits_per_pixel = 16;
+		/* The Riva128 supports RGB555 only */
+		if (par->riva.Architecture == NV_ARCH_03)
+			var->green.length = 5;
 		if (var->green.length == 5) {
 			/* 0rrrrrgg gggbbbbb */
 			var->red.offset = 10;
@@ -1190,62 +1108,21 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 			mode_valid = 1;
 	}
 
-	/* find best mode from modedb */
-	if (!mode_valid && specs->modedb_len) {
-		int i, best, best_refresh, best_x, best_y, diff_x, diff_y;
-
-		best_refresh = best = best_x = best_y = 0;
-		diff_x = diff_y = -1;
-
-		for (i = 0; i < specs->modedb_len; i++) {
-			if (var->xres <= specs->modedb[i].xres &&
-			    !(specs->modedb[i].flag & FB_MODE_IS_CALCULATED) &&
-			    specs->modedb[i].xres - var->xres < diff_x) {
-				best_x = specs->modedb[i].xres;
-				diff_x = best_x - var->xres;
-			}
-			if (!diff_x) break;
-		}
-
-		if (diff_x != -1) {
-			for (i = 0; i < specs->modedb_len; i++) {
-				if (best_x == specs->modedb[i].xres &&
-				    var->yres <= specs->modedb[i].yres &&
-				    !(specs->modedb[i].flag &
-				      FB_MODE_IS_CALCULATED) &&
-				    specs->modedb[i].yres-var->yres < diff_y) {
-					best_y = specs->modedb[i].yres;
-					diff_y = best_y - var->yres;
-				}
-				if (!diff_y) break;
-			}
-		}
-
-		if (diff_y != -1) {
-			for (i = 0; i < specs->modedb_len; i++) {
-				if (best_x == specs->modedb[i].xres &&
-				    best_y == specs->modedb[i].yres &&
-				    !(specs->modedb[i].flag &
-				      FB_MODE_IS_CALCULATED) &&
-				    specs->modedb[i].refresh > best_refresh) {
-					best_refresh=specs->modedb[i].refresh;
-					best = i;
-				}
-			}
-		}
-
-		if (best_refresh) {
-			riva_update_var(var, &specs->modedb[best]);
-			mode_valid = 1;
-		}
-	}
-
 	/* calculate modeline if supported by monitor */
 	if (!mode_valid && info->monspecs.gtf) {
 		if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info))
 			mode_valid = 1;
 	}
-	if (!mode_valid && info->monspecs.modedb_len)
+
+	if (!mode_valid) {
+		mode = fb_find_best_mode(var, &info->modelist);
+		if (mode) {
+			riva_update_var(var, mode);
+			mode_valid = 1;
+		}
+	}
+
+	if (!mode_valid && !list_empty(&info->modelist))
 		return -EINVAL;
 
 	if (var->xres_virtual < var->xres)
@@ -1293,6 +1170,7 @@ static int rivafb_set_par(struct fb_info *info)
 	info->fix.line_length = (info->var.xres_virtual * (info->var.bits_per_pixel >> 3));
 	info->fix.visual = (info->var.bits_per_pixel == 8) ?
 				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+
 	NVTRACE_LEAVE();
 	return 0;
 }
@@ -1413,7 +1291,7 @@ static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
 	int i;
 
 	if (regno >= riva_get_cmap_len(&info->var))
-		return -EINVAL;
+			return -EINVAL;
 
 	if (info->var.grayscale) {
 		/* gray = 0.30*R + 0.59*G + 0.11*B */
@@ -1421,6 +1299,31 @@ static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
 		    (red * 77 + green * 151 + blue * 28) >> 8;
 	}
 
+	if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+		((u32 *) info->pseudo_palette)[regno] =
+			(regno << info->var.red.offset) |
+			(regno << info->var.green.offset) |
+			(regno << info->var.blue.offset);
+		/*
+		 * The Riva128 2D engine requires color information in
+		 * TrueColor format even if framebuffer is in DirectColor
+		 */
+		if (par->riva.Architecture == NV_ARCH_03) {
+			switch (info->var.bits_per_pixel) {
+			case 16:
+				par->palette[regno] = ((red & 0xf800) >> 1) |
+					((green & 0xf800) >> 6) |
+					((blue & 0xf800) >> 11);
+				break;
+			case 32:
+				par->palette[regno] = ((red & 0xff00) << 8) |
+					((green & 0xff00)) |
+					((blue & 0xff00) >> 8);
+				break;
+			}
+		}
+	}
+
 	switch (info->var.bits_per_pixel) {
 	case 8:
 		/* "transparent" stuff is completely ignored. */
@@ -1428,45 +1331,27 @@ static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
 		break;
 	case 16:
 		if (info->var.green.length == 5) {
-			if (regno < 16) {
-				/* 0rrrrrgg gggbbbbb */
-				((u32 *)info->pseudo_palette)[regno] =
-					((red & 0xf800) >> 1) |
-					((green & 0xf800) >> 6) |
-					((blue & 0xf800) >> 11);
-			}
-			for (i = 0; i < 8; i++) 
+			for (i = 0; i < 8; i++) {
 				riva_wclut(chip, regno*8+i, red >> 8,
 					   green >> 8, blue >> 8);
+			}
 		} else {
 			u8 r, g, b;
 
-			if (regno < 16) {
-				/* rrrrrggg gggbbbbb */
-				((u32 *)info->pseudo_palette)[regno] =
-					((red & 0xf800) >> 0) |
-					((green & 0xf800) >> 5) |
-					((blue & 0xf800) >> 11);
-			}
 			if (regno < 32) {
 				for (i = 0; i < 8; i++) {
-					riva_wclut(chip, regno*8+i, red >> 8, 
-						   green >> 8, blue >> 8);
+					riva_wclut(chip, regno*8+i,
+						   red >> 8, green >> 8,
+						   blue >> 8);
 				}
 			}
-			for (i = 0; i < 4; i++) {
-				riva_rclut(chip, regno*2+i, &r, &g, &b);
-				riva_wclut(chip, regno*4+i, r, green >> 8, b);
-			}
+			riva_rclut(chip, regno*4, &r, &g, &b);
+			for (i = 0; i < 4; i++)
+				riva_wclut(chip, regno*4+i, r,
+					   green >> 8, b);
 		}
 		break;
 	case 32:
-		if (regno < 16) {
-			((u32 *)info->pseudo_palette)[regno] =
-				((red & 0xff00) << 8) |
-				((green & 0xff00)) | ((blue & 0xff00) >> 8);
-			
-		}
 		riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8);
 		break;
 	default:
@@ -1495,8 +1380,12 @@ static void rivafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect
 
 	if (info->var.bits_per_pixel == 8)
 		color = rect->color;
-	else
-		color = ((u32 *)info->pseudo_palette)[rect->color];
+	else {
+		if (par->riva.Architecture != NV_ARCH_03)
+			color = ((u32 *)info->pseudo_palette)[rect->color];
+		else
+			color = par->palette[rect->color];
+	}
 
 	switch (rect->rop) {
 	case ROP_XOR:
@@ -1592,15 +1481,17 @@ static void rivafb_imageblit(struct fb_info *info,
 		bgx = image->bg_color;
 		break;
 	case 16:
-		fgx = ((u32 *)info->pseudo_palette)[image->fg_color];
-		bgx = ((u32 *)info->pseudo_palette)[image->bg_color];
+	case 32:
+		if (par->riva.Architecture != NV_ARCH_03) {
+			fgx = ((u32 *)info->pseudo_palette)[image->fg_color];
+			bgx = ((u32 *)info->pseudo_palette)[image->bg_color];
+		} else {
+			fgx = par->palette[image->fg_color];
+			bgx = par->palette[image->bg_color];
+		}
 		if (info->var.green.length == 6)
 			convert_bgcolor_16(&bgx);	
 		break;
-	case 32:
-		fgx = ((u32 *)info->pseudo_palette)[image->fg_color];
-		bgx = ((u32 *)info->pseudo_palette)[image->bg_color];
-		break;
 	}
 
 	RIVA_FIFO_FREE(par->riva, Bitmap, 7);
@@ -1769,6 +1660,7 @@ static struct fb_ops riva_fb_ops = {
 static int __devinit riva_set_fbinfo(struct fb_info *info)
 {
 	unsigned int cmap_len;
+	struct riva_par *par = (struct riva_par *) info->par;
 
 	NVTRACE_ENTER();
 	info->flags = FBINFO_DEFAULT
@@ -1781,7 +1673,8 @@ static int __devinit riva_set_fbinfo(struct fb_info *info)
 	info->var = rivafb_default_var;
 	info->fix.visual = (info->var.bits_per_pixel == 8) ?
 				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
-	info->pseudo_palette = pseudo_palette;
+
+	info->pseudo_palette = par->pseudo_palette;
 
 	cmap_len = riva_get_cmap_len(&info->var);
 	fb_alloc_cmap(&info->cmap, cmap_len, 0);	
@@ -1796,7 +1689,7 @@ static int __devinit riva_set_fbinfo(struct fb_info *info)
 }
 
 #ifdef CONFIG_PPC_OF
-static int riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd)
+static int __devinit riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd)
 {
 	struct riva_par *par = (struct riva_par *) info->par;
 	struct device_node *dp;
@@ -1828,7 +1721,28 @@ static int riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd)
 }
 #endif /* CONFIG_PPC_OF */
 
-static void riva_update_default_var(struct fb_var_screeninfo *var, struct fb_info *info)
+#if defined(CONFIG_FB_RIVA_I2C) && !defined(CONFIG_PPC_OF)
+static int __devinit riva_get_EDID_i2c(struct fb_info *info)
+{
+	struct riva_par *par = (struct riva_par *) info->par;
+	int i;
+
+	NVTRACE_ENTER();
+	riva_create_i2c_busses(par);
+	for (i = par->bus; i >= 1; i--) {
+		riva_probe_i2c_connector(par, i, &par->EDID);
+		if (par->EDID) {
+			printk("rivafb: Found EDID Block from BUS %i\n", i);
+			break;
+		}
+	}
+	NVTRACE_LEAVE();
+	return (par->EDID) ? 1 : 0;
+}
+#endif /* CONFIG_FB_RIVA_I2C */
+
+static void __devinit riva_update_default_var(struct fb_var_screeninfo *var,
+					      struct fb_info *info)
 {
 	struct fb_monspecs *specs = &info->monspecs;
 	struct fb_videomode modedb;
@@ -1862,41 +1776,28 @@ static void riva_update_default_var(struct fb_var_screeninfo *var, struct fb_inf
 }
 
 
-static void riva_get_EDID(struct fb_info *info, struct pci_dev *pdev)
+static void __devinit riva_get_EDID(struct fb_info *info, struct pci_dev *pdev)
 {
-	struct riva_par *par;
-	int i;
-
 	NVTRACE_ENTER();
 #ifdef CONFIG_PPC_OF
 	if (!riva_get_EDID_OF(info, pdev))
 		printk("rivafb: could not retrieve EDID from OF\n");
-#else
-	/* XXX use other methods later */
-#ifdef CONFIG_FB_RIVA_I2C
-
-	par = (struct riva_par *) info->par;
-	riva_create_i2c_busses(par);
-	for (i = par->bus; i >= 1; i--) {
-		riva_probe_i2c_connector(par, i, &par->EDID);
-		if (par->EDID) {
-			printk("rivafb: Found EDID Block from BUS %i\n", i);
-			break;
-		}
-	}
-	riva_delete_i2c_busses(par);
-#endif
+#elif CONFIG_FB_RIVA_I2C
+	if (!riva_get_EDID_i2c(info))
+		printk("rivafb: could not retrieve EDID from DDC/I2C\n");
 #endif
 	NVTRACE_LEAVE();
 }
 
 
-static void riva_get_edidinfo(struct fb_info *info)
+static void __devinit riva_get_edidinfo(struct fb_info *info)
 {
 	struct fb_var_screeninfo *var = &rivafb_default_var;
 	struct riva_par *par = (struct riva_par *) info->par;
 
 	fb_edid_to_monspecs(par->EDID, &info->monspecs);
+	fb_videomode_to_modelist(info->monspecs.modedb, info->monspecs.modedb_len,
+				 &info->modelist);
 	riva_update_default_var(var, info);
 
 	/* if user specified flatpanel, we respect that */
@@ -1910,16 +1811,52 @@ static void riva_get_edidinfo(struct fb_info *info)
  *
  * ------------------------------------------------------------------------- */
 
+static u32 __devinit riva_get_arch(struct pci_dev *pd)
+{
+    	u32 arch = 0;
+
+	switch (pd->device & 0x0ff0) {
+		case 0x0100:   /* GeForce 256 */
+		case 0x0110:   /* GeForce2 MX */
+		case 0x0150:   /* GeForce2 */
+		case 0x0170:   /* GeForce4 MX */
+		case 0x0180:   /* GeForce4 MX (8x AGP) */
+		case 0x01A0:   /* nForce */
+		case 0x01F0:   /* nForce2 */
+		     arch =  NV_ARCH_10;
+		     break;
+		case 0x0200:   /* GeForce3 */
+		case 0x0250:   /* GeForce4 Ti */
+		case 0x0280:   /* GeForce4 Ti (8x AGP) */
+		     arch =  NV_ARCH_20;
+		     break;
+		case 0x0300:   /* GeForceFX 5800 */
+		case 0x0310:   /* GeForceFX 5600 */
+		case 0x0320:   /* GeForceFX 5200 */
+		case 0x0330:   /* GeForceFX 5900 */
+		case 0x0340:   /* GeForceFX 5700 */
+		     arch =  NV_ARCH_30;
+		     break;
+		case 0x0020:   /* TNT, TNT2 */
+		     arch =  NV_ARCH_04;
+		     break;
+		case 0x0010:   /* Riva128 */
+		     arch =  NV_ARCH_03;
+		     break;
+		default:   /* unknown architecture */
+		     break;
+	}
+	return arch;
+}
+
 static int __devinit rivafb_probe(struct pci_dev *pd,
 			     	const struct pci_device_id *ent)
 {
-	struct riva_chip_info *rci = &riva_chip_info[ent->driver_data];
 	struct riva_par *default_par;
 	struct fb_info *info;
 
 	NVTRACE_ENTER();
 	assert(pd != NULL);
-	assert(rci != NULL);
 
 	info = kmalloc(sizeof(struct fb_info), GFP_KERNEL);
 	if (!info)
@@ -1948,12 +1885,27 @@ static int __devinit rivafb_probe(struct pci_dev *pd,
 		goto err_out_request;
 	}
 
-	strcat(rivafb_fix.id, rci->name);
-	default_par->riva.Architecture = rci->arch_rev;
+	default_par->riva.Architecture = riva_get_arch(pd);
 
 	default_par->Chipset = (pd->vendor << 16) | pd->device;
 	printk(KERN_INFO PFX "nVidia device/chipset %X\n",default_par->Chipset);
 	
+#ifdef CONFIG_PCI_NAMES
+	printk(KERN_INFO PFX "%s\n", pd->pretty_name);
+#endif
+
+	if(default_par->riva.Architecture == 0) {
+		printk(KERN_ERR PFX "unknown NV_ARCH\n");
+		goto err_out_kfree1;
+	}
+	if(default_par->riva.Architecture == NV_ARCH_10 ||
+	   default_par->riva.Architecture == NV_ARCH_20 ||
+	   default_par->riva.Architecture == NV_ARCH_30) {
+		sprintf(rivafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
+	} else {
+		sprintf(rivafb_fix.id, "NV%x", default_par->riva.Architecture);
+	}
+
 	default_par->FlatPanel = flatpanel;
 	if (flatpanel == 1)
 		printk(KERN_INFO PFX "flatpanel support enabled\n");
@@ -1995,15 +1947,14 @@ static int __devinit rivafb_probe(struct pci_dev *pd,
 			goto err_out_free_nv3_pramin;
 		}
 		rivafb_fix.accel = FB_ACCEL_NV3;
-		default_par->bus = 1;
 		break;
 	case NV_ARCH_04:
 	case NV_ARCH_10:
 	case NV_ARCH_20:
+	case NV_ARCH_30:
 		default_par->riva.PCRTC0 = (unsigned *)(default_par->ctrl_base + 0x00600000);
 		default_par->riva.PRAMIN = (unsigned *)(default_par->ctrl_base + 0x00710000);
 		rivafb_fix.accel = FB_ACCEL_NV4;
-		default_par->bus = 2;
 		break;
 	}
 
@@ -2015,7 +1966,6 @@ static int __devinit rivafb_probe(struct pci_dev *pd,
 
 	rivafb_fix.smem_len = riva_get_memlen(default_par) * 1024;
 	default_par->dclk_max = riva_get_maxdclk(default_par) * 1000;
-
 	info->screen_base = ioremap(rivafb_fix.smem_start,
 				    rivafb_fix.smem_len);
 	if (!info->screen_base) {
@@ -2048,6 +1998,10 @@ static int __devinit rivafb_probe(struct pci_dev *pd,
 		goto err_out_iounmap_fb;
 	}
 
+	fb_destroy_modedb(info->monspecs.modedb);
+	info->monspecs.modedb_len = 0;
+	info->monspecs.modedb = NULL;
+
 	if (register_framebuffer(info) < 0) {
 		printk(KERN_ERR PFX
 			"error registering riva framebuffer\n");
@@ -2057,10 +2011,9 @@ static int __devinit rivafb_probe(struct pci_dev *pd,
 	pci_set_drvdata(pd, info);
 
 	printk(KERN_INFO PFX
-		"PCI nVidia NV%x framebuffer ver %s (%s, %dMB @ 0x%lX)\n",
-		default_par->riva.Architecture,
-		RIVAFB_VERSION,
+		"PCI nVidia %s framebuffer ver %s (%dMB @ 0x%lX)\n",
 		info->fix.id,
+		RIVAFB_VERSION,
 		info->fix.smem_len / (1024 * 1024),
 		info->fix.smem_start);
 #ifdef CONFIG_PMAC_BACKLIGHT
@@ -2072,6 +2025,9 @@ static int __devinit rivafb_probe(struct pci_dev *pd,
 	return 0;
 
 err_out_iounmap_fb:
+#ifdef CONFIG_FB_RIVA_I2C
+	riva_delete_i2c_busses((struct riva_par *) info->par);
+#endif
 	iounmap(info->screen_base);
 err_out_free_base1:
 	if (default_par->riva.Architecture == NV_ARCH_03) 
@@ -2101,6 +2057,12 @@ static void __exit rivafb_remove(struct pci_dev *pd)
 	if (!info)
 		return;
 
+#ifdef CONFIG_FB_RIVA_I2C
+	riva_delete_i2c_busses(par);
+	if (par->EDID)
+		kfree(par->EDID);
+#endif
+
 	unregister_framebuffer(info);
 #ifdef CONFIG_MTRR
 	if (par->mtrr.vram_valid)
@@ -2114,7 +2076,6 @@ static void __exit rivafb_remove(struct pci_dev *pd)
 		iounmap((caddr_t)par->riva.PRAMIN);
 	pci_release_regions(pd);
 	pci_disable_device(pd);
-	fb_destroy_modedb(info->monspecs.modedb);
 	kfree(info->pixmap.addr);
 	kfree(par);
 	kfree(info);
@@ -2177,8 +2138,15 @@ static struct pci_driver rivafb_driver = {
  *
  * ------------------------------------------------------------------------- */
 
-int __init rivafb_init(void)
+int __devinit rivafb_init(void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("rivafb", &option))
+		return -ENODEV;
+	rivafb_setup(option);
+#endif
 	if (pci_register_driver(&rivafb_driver) > 0)
 		return 0;
 	pci_unregister_driver(&rivafb_driver);
@@ -2186,13 +2154,14 @@ int __init rivafb_init(void)
 }
 
 
+module_init(rivafb_init);
+
 #ifdef MODULE
 static void __exit rivafb_exit(void)
 {
 	pci_unregister_driver(&rivafb_driver);
 }
 
-module_init(rivafb_init);
 module_exit(rivafb_exit);
 
 MODULE_PARM(flatpanel, "i");
@@ -2203,9 +2172,9 @@ MODULE_PARM_DESC(forceCRTC, "Forces usage of a particular CRTC in case autodetec
 #ifdef CONFIG_MTRR
 MODULE_PARM(nomtrr, "i");
 MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)");
+#endif
 MODULE_PARM(strictmode, "i");
 MODULE_PARM_DESC(strictmode, "Only use video modes from EDID");
-#endif
 #endif /* MODULE */
 
 MODULE_AUTHOR("Ani Joshi, maintainer");
diff --git a/drivers/video/riva/nv_driver.c b/drivers/video/riva/nv_driver.c
index 3caf9f798..983b7285d 100644
--- a/drivers/video/riva/nv_driver.c
+++ b/drivers/video/riva/nv_driver.c
@@ -205,6 +205,7 @@ unsigned long riva_get_memlen(struct riva_par *par)
 		break;
 	case NV_ARCH_10:
 	case NV_ARCH_20:
+	case NV_ARCH_30:
 		if(chipset == NV_CHIP_IGEFORCE2) {
 
 			dev = pci_find_slot(0, 1);
@@ -274,6 +275,7 @@ unsigned long riva_get_maxdclk(struct riva_par *par)
 	case NV_ARCH_04:
 	case NV_ARCH_10:
 	case NV_ARCH_20:
+	case NV_ARCH_30:
 		switch ((chip->PFB[0x00000000/4] >> 3) & 0x00000003) {
 		case 3:
 			dclk = 800000;
diff --git a/drivers/video/riva/riva_hw.c b/drivers/video/riva/riva_hw.c
index ac79134bd..fe5e937b1 100644
--- a/drivers/video/riva/riva_hw.c
+++ b/drivers/video/riva/riva_hw.c
@@ -1274,6 +1274,7 @@ static void CalcStateExt
             break;
         case NV_ARCH_10:
         case NV_ARCH_20:
+        case NV_ARCH_30:
             if((chip->Chipset == NV_CHIP_IGEFORCE2) ||
                (chip->Chipset == NV_CHIP_0x01F0))
             {
@@ -1299,9 +1300,10 @@ static void CalcStateExt
             break;
     }
 
-    /* Paul Richards: below if block borks things in kernel for some reason */
-    /* if((bpp != 8) && (chip->Architecture != NV_ARCH_03))
-    state->general |= 0x00000030; */
+     /* Paul Richards: below if block borks things in kernel for some reason */
+     /* Tony: Below is needed to set hardware in DirectColor */
+    if((bpp != 8) && (chip->Architecture != NV_ARCH_03))
+	    state->general |= 0x00000030;
 
     state->vpll     = (p << 16) | (n << 8) | m;
     state->repaint0 = (((width/8)*pixelDepth) & 0x700) >> 3;
@@ -1349,6 +1351,7 @@ static void UpdateFifoState
             break;
         case NV_ARCH_10:
         case NV_ARCH_20:
+        case NV_ARCH_30:
             /*
              * Initialize state for the RivaTriangle3D05 routines.
              */
@@ -1458,6 +1461,7 @@ static void LoadStateExt
             break;
         case NV_ARCH_10:
         case NV_ARCH_20:
+        case NV_ARCH_30:
             if(chip->twoHeads) {
                VGA_WR08(chip->PCIO, 0x03D4, 0x44);
                VGA_WR08(chip->PCIO, 0x03D5, state->crtcOwner);
@@ -1754,6 +1758,7 @@ static void UnloadStateExt
             break;
         case NV_ARCH_10:
         case NV_ARCH_20:
+        case NV_ARCH_30:
             state->offset0  = chip->PGRAPH[0x00000640/4];
             state->offset1  = chip->PGRAPH[0x00000644/4];
             state->offset2  = chip->PGRAPH[0x00000648/4];
@@ -2184,6 +2189,7 @@ int RivaGetConfig
             break;
         case NV_ARCH_10:
         case NV_ARCH_20:
+        case NV_ARCH_30:
             nv10GetConfig(chip, chipset);
             break;
         default:
diff --git a/drivers/video/riva/riva_hw.h b/drivers/video/riva/riva_hw.h
index e54b015bd..707022a57 100644
--- a/drivers/video/riva/riva_hw.h
+++ b/drivers/video/riva/riva_hw.h
@@ -89,12 +89,14 @@ typedef unsigned int   U032;
 #define VGA_RD08(p,i)   NV_RD08(p,i)
 
 /*
- * Define supported architectures.
+ * Define different architectures.
  */
 #define NV_ARCH_03  0x03
 #define NV_ARCH_04  0x04
 #define NV_ARCH_10  0x10
 #define NV_ARCH_20  0x20
+#define NV_ARCH_30  0x30
+#define NV_ARCH_40  0x40
 
 /***************************************************************************\
 *                                                                           *
diff --git a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c
index a8dbc252d..4b72002c0 100644
--- a/drivers/video/riva/rivafb-i2c.c
+++ b/drivers/video/riva/rivafb-i2c.c
@@ -106,6 +106,7 @@ static int riva_setup_i2c_bus(struct riva_i2c_chan *chan, const char *name)
 	chan->algo.getsda		= riva_gpio_getsda;
 	chan->algo.getscl		= riva_gpio_getscl;
 	chan->algo.udelay		= 40;
+	chan->algo.mdelay               = 5;
 	chan->algo.timeout		= 20;
 	chan->algo.data 		= chan;
 
@@ -130,19 +131,34 @@ void riva_create_i2c_busses(struct riva_par *par)
 	par->chan[1].par	= par;
 	par->chan[2].par        = par;
 
-	switch (par->riva.Architecture) {
-#if 0		/* no support yet for other nVidia chipsets */
+	par->bus = 0;
+
+	switch ((par->pdev->device >> 4) & 0xff) {
+	case 0x17:
+	case 0x18:
+	case 0x25:
+	case 0x28:
+	case 0x30:
+	case 0x31:
+	case 0x32:
+	case 0x33:
+	case 0x34:
 		par->chan[2].ddc_base   = 0x50;
-		riva_setup_i2c_bus(&par->chan[2], "BUS2");
-#endif
-	case NV_ARCH_10:
-	case NV_ARCH_20:
-	case NV_ARCH_04:
+		par->bus++;
+		riva_setup_i2c_bus(&par->chan[2], "BUS3");
+	case 0x04:
+	case 0x05:
+	case 0x10:
+	case 0x11:
+	case 0x15:
+	case 0x20:
 		par->chan[1].ddc_base	= 0x36;
-		riva_setup_i2c_bus(&par->chan[1], "BUS1");
-	case NV_ARCH_03:
+		par->bus++;
+		riva_setup_i2c_bus(&par->chan[1], "BUS2");
+	case 0x03:
 		par->chan[0].ddc_base	= 0x3e;
-		riva_setup_i2c_bus(&par->chan[0], "BUS0");
+		par->bus++;
+		riva_setup_i2c_bus(&par->chan[0], "BUS1");
 	}
 }
 
diff --git a/drivers/video/riva/rivafb.h b/drivers/video/riva/rivafb.h
index 198a29c3c..fab7036fb 100644
--- a/drivers/video/riva/rivafb.h
+++ b/drivers/video/riva/rivafb.h
@@ -44,16 +44,17 @@ struct riva_i2c_chan {
 
 struct riva_par {
 	RIVA_HW_INST riva;	/* interface to riva_hw.c */
-
+	u32 pseudo_palette[16]; /* default palette */
+	u32 palette[16];        /* for Riva128 */
 	caddr_t ctrl_base;	/* virtual control register base addr */
 	unsigned dclk_max;	/* max DCLK */
 
 	struct riva_regs initial_state;	/* initial startup video mode */
 	struct riva_regs current_state;
+#ifdef CONFIG_X86
 	struct vgastate state;
+#endif
 	atomic_t ref_count;
-	u32 cursor_data[32 * 32/4];
-	int cursor_reset;
 	unsigned char *EDID;
 	unsigned int Chipset;
 	int forceCRTC;
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index ae8fb7aef..b2c7aa104 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -1671,7 +1671,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
 	fbi->fb.var.vmode	= FB_VMODE_NONINTERLACED;
 
 	fbi->fb.fbops		= &sa1100fb_ops;
-	fbi->fb.flags		= FBINFO_FLAG_DEFAULT;
+	fbi->fb.flags		= FBINFO_DEFAULT;
 	fbi->fb.monspecs	= monspecs;
 	fbi->fb.currcon		= -1;
 	fbi->fb.pseudo_palette	= (fbi + 1);
@@ -1804,6 +1804,9 @@ static struct device_driver sa1100fb_driver = {
 
 int __init sa1100fb_init(void)
 {
+	if (fb_get_options("sa1100fb", NULL))
+		return -ENODEV;
+
 	return driver_register(&sa1100fb_driver);
 }
 
@@ -1848,5 +1851,6 @@ int __init sa1100fb_setup(char *options)
 	return 0;
 }
 
+module_init(sa1100fb_init);
 MODULE_DESCRIPTION("StrongARM-1100/1110 framebuffer driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c
index 136c9d8e5..4fc54822e 100644
--- a/drivers/video/sgivwfb.c
+++ b/drivers/video/sgivwfb.c
@@ -22,7 +22,7 @@
 #include <asm/mtrr.h>
 
 #define INCLUDE_TIMING_TABLE_DATA
-#define DBE_REG_BASE default_par.regs
+#define DBE_REG_BASE par->regs
 #include <video/sgivw.h>
 
 struct sgivw_par {
@@ -44,9 +44,6 @@ struct sgivw_par {
 extern unsigned long sgivwfb_mem_phys;
 extern unsigned long sgivwfb_mem_size;
 
-static struct sgivw_par default_par;
-static u32 pseudo_palette[17];
-static struct fb_info fb_info;
 static int ypan = 0;
 static int ywrap = 0;
 
@@ -162,7 +159,7 @@ static unsigned long get_line_length(int xres_virtual, int bpp)
  *              console.
  */
 
-static void dbe_TurnOffDma(void)
+static void dbe_TurnOffDma(struct sgivw_par *par)
 {
 	unsigned int readVal;
 	int i;
@@ -367,7 +364,7 @@ static int sgivwfb_check_var(struct fb_var_screeninfo *var,
 /*
  *  Setup flatpanel related registers.
  */
-static void sgivwfb_setup_flatpanel(struct dbe_timing_info *currentTiming)
+static void sgivwfb_setup_flatpanel(struct sgivw_par *par, struct dbe_timing_info *currentTiming)
 {
 	int fp_wid, fp_hgt, fp_vbs, fp_vbe;
 	u32 outputVal = 0;
@@ -429,7 +426,7 @@ static int sgivwfb_set_par(struct fb_info *info)
 	/* Turn on dotclock PLL */
 	DBE_SETREG(ctrlstat, 0x20000000);
 
-	dbe_TurnOffDma();
+	dbe_TurnOffDma(par);
 
 	/* dbe_CalculateScreenParams(); */
 	maxPixelsPerTileX = 512 / bytesPerPixel;
@@ -453,7 +450,7 @@ static int sgivwfb_set_par(struct fb_info *info)
 		DBE_SETREG(vt_xy, 0x00000000);
 		udelay(1);
 	} else
-		dbe_TurnOffDma();
+		dbe_TurnOffDma(par);
 
 	/* dbe_Initdbe(); */
 	for (i = 0; i < 256; i++) {
@@ -567,7 +564,7 @@ static int sgivwfb_set_par(struct fb_info *info)
 	DBE_SETREG(vt_hcmap, outputVal);
 
 	if (flatpanel_id != -1)
-		sgivwfb_setup_flatpanel(currentTiming);
+		sgivwfb_setup_flatpanel(par, currentTiming);
 
 	outputVal = 0;
 	temp = currentTiming->vblank_start - currentTiming->vblank_end - 1;
@@ -752,16 +749,30 @@ int __init sgivwfb_setup(char *options)
 /*
  *  Initialisation
  */
-int __init sgivwfb_init(void)
+static void sgivwfb_release(struct device *device)
+{
+}
+
+static int __init sgivwfb_probe(struct device *device)
 {
+	struct platform_device *dev = to_platform_device(device);
+	struct sgivw_par *par;
+	struct fb_info *info;
 	char *monitor;
 
+	info = framebuffer_alloc(sizeof(struct sgivw_par) + sizeof(u32) * 256, &dev->dev);
+	if (!info)
+		return -ENOMEM;
+	par = info->par;
+
 	if (!request_mem_region(DBE_REG_PHYS, DBE_REG_SIZE, "sgivwfb")) {
 		printk(KERN_ERR "sgivwfb: couldn't reserve mmio region\n");
+		framebuffer_release(info);
 		return -EBUSY;
 	}
-	default_par.regs = (struct asregs *) ioremap_nocache(DBE_REG_PHYS, DBE_REG_SIZE);
-	if (!default_par.regs) {
+
+	par->regs = (struct asregs *) ioremap_nocache(DBE_REG_PHYS, DBE_REG_SIZE);
+	if (!par->regs) {
 		printk(KERN_ERR "sgivwfb: couldn't ioremap registers\n");
 		goto fail_ioremap_regs;
 	}
@@ -773,66 +784,118 @@ int __init sgivwfb_init(void)
 	sgivwfb_fix.ywrapstep = ywrap;
 	sgivwfb_fix.ypanstep = ypan;
 
-	fb_info.fix = sgivwfb_fix;
+	info->fix = sgivwfb_fix;
 
 	switch (flatpanel_id) {
 		case FLATPANEL_SGI_1600SW:
-			fb_info.var = sgivwfb_var1600sw;
+			info->var = sgivwfb_var1600sw;
 			monitor = "SGI 1600SW flatpanel";
 			break;
 		default:
-			fb_info.var = sgivwfb_var;
+			info->var = sgivwfb_var;
 			monitor = "CRT";
 	}
 
 	printk(KERN_INFO "sgivwfb: %s monitor selected\n", monitor);
 
-	fb_info.fbops = &sgivwfb_ops;
-	fb_info.pseudo_palette = pseudo_palette;
-	fb_info.par = &default_par;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	info->fbops = &sgivwfb_ops;
+	info->pseudo_palette = (void *) (par + 1);
+	info->flags = FBINFO_DEFAULT;
 
-	fb_info.screen_base = ioremap_nocache((unsigned long) sgivwfb_mem_phys, sgivwfb_mem_size);
-	if (!fb_info.screen_base) {
+	info->screen_base = ioremap_nocache((unsigned long) sgivwfb_mem_phys, sgivwfb_mem_size);
+	if (!info->screen_base) {
 		printk(KERN_ERR "sgivwfb: couldn't ioremap screen_base\n");
 		goto fail_ioremap_fbmem;
 	}
 
-	fb_alloc_cmap(&fb_info.cmap, 256, 0);
+	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
+		goto fail_color_map;
 
-	if (register_framebuffer(&fb_info) < 0) {
+	if (register_framebuffer(info) < 0) {
 		printk(KERN_ERR "sgivwfb: couldn't register framebuffer\n");
 		goto fail_register_framebuffer;
 	}
 
+	dev_set_drvdata(&dev->dev, info);
+
 	printk(KERN_INFO "fb%d: SGI DBE frame buffer device, using %ldK of video memory at %#lx\n",      
-		fb_info.node, sgivwfb_mem_size >> 10, sgivwfb_mem_phys);
+		info->node, sgivwfb_mem_size >> 10, sgivwfb_mem_phys);
 	return 0;
 
 fail_register_framebuffer:
-	iounmap((char *) fb_info.screen_base);
+	fb_dealloc_cmap(&info->cmap);
+fail_color_map:
+	iounmap((char *) info->screen_base);
 fail_ioremap_fbmem:
-	iounmap(default_par.regs);
+	iounmap(par->regs);
 fail_ioremap_regs:
 	release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
+	framebuffer_release(info);
 	return -ENXIO;
 }
 
-#ifdef MODULE
-MODULE_LICENSE("GPL");
+static int sgivwfb_remove(struct device *device)
+{
+	struct fb_info *info = dev_get_drvdata(device);
+
+	if (info) {
+		struct sgivw_par *par = info->par;
+
+		unregister_framebuffer(info);
+		dbe_TurnOffDma(par);
+		iounmap(par->regs);
+		iounmap(info->screen_base);
+		release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
+	}
+	return 0;
+}
+
+static struct device_driver sgivwfb_driver = {
+	.name	= "sgivwfb",
+	.bus	= &platform_bus_type,
+	.probe	= sgivwfb_probe,
+	.remove	= sgivwfb_remove,
+};
 
-int init_module(void)
+static struct platform_device sgivwfb_device = {
+	.name	= "sgivwfb",
+	.id	= 0,
+	.dev	= {
+		.release = sgivwfb_release,
+	}
+};
+
+int __init sgivwfb_init(void)
 {
-	return sgivwfb_init();
+	int ret;
+
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("sgivwfb", &option))
+		return -ENODEV;
+	sgivwfb_setup(option);
+#endif
+	ret = driver_register(&sgivwfb_driver);
+	if (!ret) {
+		ret = platform_device_register(&sgivwfb_device);
+		if (ret)
+			driver_unregister(&sgivwfb_driver);
+	}
+	return ret;
 }
 
-void cleanup_module(void)
+module_init(sgivwfb_init);
+
+#ifdef MODULE
+MODULE_LICENSE("GPL");
+
+static void __exit sgivwfb_exit(void)
 {
-	unregister_framebuffer(&fb_info);
-	dbe_TurnOffDma();
-	iounmap(regs);
-	iounmap(&fb_info.screen_base);
-	release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE);
+	platform_device_unregister(&sgivwfb_device);
+	driver_unregister(&sgivwfb_driver);
 }
 
+module_exit(sgivwfb_exit);
+
 #endif				/* MODULE */
diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h
index 97599dfd5..6638b5443 100644
--- a/drivers/video/sis/sis.h
+++ b/drivers/video/sis/sis.h
@@ -360,10 +360,10 @@ struct sis_video_info {
 	unsigned long 	mmio_base;
 	unsigned long 	vga_base;
 
-	unsigned long  	video_vbase;
-	unsigned long 	mmio_vbase;
-	char  *	      	bios_vbase;
-	char  *	      	bios_abase;
+	void __iomem *	video_vbase;
+	void __iomem *	mmio_vbase;
+	void __iomem * 	bios_vbase;
+	void *		bios_abase;
 
 	int 		mtrr;
 
@@ -392,8 +392,8 @@ struct sis_video_info {
 #endif
 
 	u32 		heapstart;        /* offset  */
-	unsigned long  	sisfb_heap_start; /* address */
-	unsigned long  	sisfb_heap_end;   /* address */
+	void __iomem * 	sisfb_heap_start; /* address */
+	void __iomem * 	sisfb_heap_end;   /* address */
 	u32 	      	sisfb_heap_size;
 	int		havenoheap;
 #if 0
@@ -469,7 +469,7 @@ struct sis_video_info {
 	u8 		detectedpdca;
 	u8 		detectedlcda;
 
-	unsigned long 	hwcursor_vbase;
+	void __iomem * 	hwcursor_vbase;
 
 	int 		chronteltype;
 	int    		tvxpos, tvypos;
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 9ad218d6a..72afe0838 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -3952,19 +3952,19 @@ int __init sisfb_setup(char *options)
 }
 #endif
 
-static char * __devinit sis_find_rom(struct pci_dev *pdev)
+static void __iomem * __devinit sis_find_rom(struct pci_dev *pdev)
 {
 	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
 
 #if defined(__i386__) || defined(__x86_64__)
         u32  segstart;
-        unsigned char *rom_base, *rom;
+	void __iomem *rom_base, *rom;
         int  romptr;
 	unsigned short pciid;
 
         for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
 
-            rom_base = (unsigned char *)ioremap(segstart, 0x10000);
+            rom_base = ioremap(segstart, 0x10000);
 	    if(!rom_base) continue;
 
 	    if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa)) {
@@ -3998,7 +3998,7 @@ static char * __devinit sis_find_rom(struct pci_dev *pdev)
 	    iounmap(rom_base);
         }
 #else
-	unsigned char *rom_base, *rom, *myrombase = NULL;
+	void __iomem *rom_base, *rom, *myrombase = NULL;
         int  romptr;
 	unsigned short pciid;
 	u32 backup;
@@ -4037,7 +4037,7 @@ static char * __devinit sis_find_rom(struct pci_dev *pdev)
 
 #ifdef CONFIG_FB_SIS_300
 static int __devinit
-sisfb_chkbuswidth300(struct pci_dev *pdev, ULONG FBAddress)
+sisfb_chkbuswidth300(struct pci_dev *pdev, void __iomem *FBAddress)
 {
 	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
 	int i, j;
@@ -4080,7 +4080,7 @@ static void __devinit
 sisfb_setramsize300(struct pci_dev *pdev)
 {
 	struct  sis_video_info *ivideo = pci_get_drvdata(pdev);
-  	ULONG 	FBAddr = (ULONG)ivideo->sishw_ext.pjVideoMemoryAddress, Addr;
+	void __iomem *FBAddr = ivideo->sishw_ext.pjVideoMemoryAddress, *Addr;
 	USHORT 	SR13, SR14=0, buswidth, Done, data, TotalCapacity, PhysicalAdrOtherPage=0;
 	int     PseudoRankCapacity, PseudoTotalCapacity, PseudoAdrPinCount;
    	int     RankCapacity, AdrPinCount, BankNumHigh, BankNumMid, MB2Bank;
@@ -4959,7 +4959,7 @@ int __devinit sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		ivideo->modeprechange = 0x03;
 #if defined(__i386__) || defined(__x86_64__)
 		{
-			unsigned char *tt = ioremap(0, 0x1000);
+			unsigned char __iomem *tt = ioremap(0, 0x1000);
 			if(tt) {
 			   	ivideo->modeprechange = tt[0x449];
 			   	iounmap(tt);
@@ -4993,7 +4993,8 @@ int __devinit sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	}
 #endif
 
-	ivideo->bios_vbase = ivideo->bios_abase = NULL;
+	ivideo->bios_abase = NULL;
+	ivideo->bios_vbase = NULL;
 	if(ivideo->sisfb_userom) {
 	    ivideo->sishw_ext.pjVirtualRomBase = sis_find_rom(pdev);
 #if defined(__i386__) || defined(__x86_64__)
@@ -5147,8 +5148,8 @@ int __devinit sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		return -ENODEV;
 	}
 
-	ivideo->video_vbase = (unsigned long)ioremap(ivideo->video_base, ivideo->video_size);
-	ivideo->sishw_ext.pjVideoMemoryAddress = (unsigned char *)ivideo->video_vbase;
+	ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size);
+	ivideo->sishw_ext.pjVideoMemoryAddress = ivideo->video_vbase;
 	if(!ivideo->video_vbase) {
 	   	printk(KERN_ERR "sisfb: Fatal error: Unable to map frame buffer memory\n");
 	   	release_mem_region(ivideo->video_base, ivideo->video_size);
@@ -5160,10 +5161,10 @@ int __devinit sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	   	return -ENODEV;
 	}
 
-	ivideo->mmio_vbase = (unsigned long)ioremap(ivideo->mmio_base, ivideo->mmio_size);
+	ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
 	if(!ivideo->mmio_vbase) {
 	   	printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
-	   	iounmap((void *)ivideo->video_vbase);
+	   	iounmap(ivideo->video_vbase);
 	   	release_mem_region(ivideo->video_base, ivideo->video_size);
 	   	release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
 		if(ivideo->bios_abase) vfree(ivideo->bios_abase);
@@ -5173,10 +5174,10 @@ int __devinit sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	   	return -ENODEV;
 	}
 
-	printk(KERN_INFO "sisfb: Framebuffer at 0x%lx, mapped to 0x%lx, size %ldk\n",
+	printk(KERN_INFO "sisfb: Framebuffer at 0x%lx, mapped to 0x%p, size %ldk\n",
 	       	ivideo->video_base, ivideo->video_vbase, ivideo->video_size / 1024);
 
-	printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
+	printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
 	       	ivideo->mmio_base, ivideo->mmio_vbase, ivideo->mmio_size / 1024);
 
 	if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
@@ -5450,8 +5451,8 @@ int __devinit sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) {
 			printk(KERN_ERR "sisfb: Fatal error: Setting mode[0x%x] failed\n",
 									ivideo->mode_no);
-			iounmap((void *)ivideo->video_vbase);
-			iounmap((void *)ivideo->mmio_vbase);
+			iounmap(ivideo->video_vbase);
+			iounmap(ivideo->mmio_vbase);
 			release_mem_region(ivideo->video_base, ivideo->video_size);
 			release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
 			if(ivideo->bios_abase) vfree(ivideo->bios_abase);
@@ -5549,7 +5550,7 @@ int __devinit sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 #endif
 		sis_fb_info->var = ivideo->default_var;
 		sis_fb_info->fix = ivideo->sisfb_fix;
-		sis_fb_info->screen_base = (char *)ivideo->video_vbase;
+		sis_fb_info->screen_base = ivideo->video_vbase;
 		sis_fb_info->fbops = &sisfb_ops;
 
 		sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info);
@@ -5574,8 +5575,8 @@ int __devinit sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 		if(register_framebuffer(sis_fb_info) < 0) {
 			printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
-			iounmap((void *)ivideo->video_vbase);
-			iounmap((void *)ivideo->mmio_vbase);
+			iounmap(ivideo->video_vbase);
+			iounmap(ivideo->mmio_vbase);
 			release_mem_region(ivideo->video_base, ivideo->video_size);
 			release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
 			if(ivideo->bios_abase) vfree(ivideo->bios_abase);
@@ -5669,8 +5670,8 @@ static void __devexit sisfb_remove(struct pci_dev *pdev)
 #endif
 
 	/* Unmap */
-	iounmap((void *)ivideo->video_vbase);
-	iounmap((void *)ivideo->mmio_vbase);
+	iounmap(ivideo->video_vbase);
+	iounmap(ivideo->mmio_vbase);
 	if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
 	if(ivideo->bios_abase)    vfree(ivideo->bios_abase);
 
@@ -5718,9 +5719,24 @@ static struct pci_driver sisfb_driver = {
 
 int __init sisfb_init(void)
 {
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("sisfb", &option))
+		return -ENODEV;
+	sisfb_setup(option);
+#endif
+#endif
 	return(pci_module_init(&sisfb_driver));
 }
 
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8)
+#ifndef MODULE
+module_init(sisfb_init);
+#endif
+#endif
+
 /*****************************************************/
 /*                      MODULE                       */
 /*****************************************************/
diff --git a/drivers/video/sis/sis_main.h b/drivers/video/sis/sis_main.h
index 3f9298d52..176a9b165 100644
--- a/drivers/video/sis/sis_main.h
+++ b/drivers/video/sis/sis_main.h
@@ -880,7 +880,7 @@ static int      sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
 		      	struct fb_info *info);
 static void     sisfb_pre_setmode(struct sis_video_info *ivideo);
 static void     sisfb_post_setmode(struct sis_video_info *ivideo);
-static char *   sis_find_rom(struct pci_dev *pdev);
+static void __iomem *sis_find_rom(struct pci_dev *pdev);
 static BOOLEAN  sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
 static BOOLEAN  sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
 static BOOLEAN  sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
index 75ab62945..115440079 100644
--- a/drivers/video/skeletonfb.c
+++ b/drivers/video/skeletonfb.c
@@ -582,6 +582,17 @@ int __init xxxfb_init(void)
 
 static void __exit xxxfb_cleanup(void)
 {
+    /*
+     *  For kernel boot options (in 'video=xxxfb:<options>' format)
+     */
+#ifndef MODULE
+    char *option = NULL;
+
+    if (fb_get_options("xxxfb", &option))
+	    return -ENODEV;
+    xxxfb_setup(option);
+#endif
+
     /*
      *  If your driver supports multiple boards, you should unregister and
      *  clean up all instances.
@@ -639,9 +650,7 @@ static struct fb_ops xxxfb_ops = {
      *  Modularization
      */
 
-#ifdef MODULE
 module_init(xxxfb_init);
-#endif 
 module_exit(xxxfb_cleanup);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/softcursor.c b/drivers/video/softcursor.c
index a953b467b..7637dc870 100644
--- a/drivers/video/softcursor.c
+++ b/drivers/video/softcursor.c
@@ -22,7 +22,8 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
 	unsigned int scan_align = info->sprite.scan_align - 1;
 	unsigned int buf_align = info->sprite.buf_align - 1;
 	unsigned int i, size, dsize, s_pitch, d_pitch;
-	u8 *dst, src[64];
+	struct fb_cursor *cur;
+	u8 *dst, *src;
 
 	if (cursor->set & FB_CUR_SETSIZE) {
 		info->cursor.image.height = cursor->image.height;
@@ -48,9 +49,17 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
 		info->cursor.image.depth = cursor->image.depth;
 	}	
 
+	info->cursor.image.data = cursor->image.data;
+
 	if (info->state != FBINFO_STATE_RUNNING)
 		return 0;
 
+	src = kmalloc(64 + sizeof(struct fb_cursor), GFP_ATOMIC);
+	if (!src)
+		return -ENOMEM;
+	cur = (struct fb_cursor *) (src + 64);
+	*cur = info->cursor;
+
 	s_pitch = (info->cursor.image.width + 7) >> 3;
 	dsize = s_pitch * info->cursor.image.height;
 	d_pitch = (s_pitch + scan_align) & ~scan_align;
@@ -79,9 +88,12 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
 	else
 		fb_sysmove_buf_aligned(info, &info->sprite, dst, d_pitch, src,
 				   s_pitch, info->cursor.image.height);
-	info->cursor.image.data = dst;
+	cur->image.data = dst;
 	
-	info->fbops->fb_imageblit(info, &info->cursor.image);
+	info->fbops->fb_imageblit(info, &cur->image);
+
+	kfree(src);
+
 	return 0;
 }
 
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c
index f732dbbf8..e3ea32b6c 100644
--- a/drivers/video/sstfb.c
+++ b/drivers/video/sstfb.c
@@ -1473,7 +1473,7 @@ static int __devinit sstfb_probe(struct pci_dev *pdev,
 	f_ddprintk("membase_phys: %#lx\n", fix->smem_start);
 	f_ddprintk("fbbase_virt: %p\n", info->screen_base);
 
-	info->flags	= FBINFO_FLAG_DEFAULT;
+	info->flags	= FBINFO_DEFAULT;
 	info->fbops	= &sstfb_ops;
 	info->currcon	= -1;
 	info->pseudo_palette = &all->pseudo_palette;
@@ -1571,6 +1571,13 @@ static struct pci_driver sstfb_driver = {
 
 int __devinit sstfb_init(void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("sstfb", &option))
+		return -ENODEV;
+	sstfb_setup(option);
+#endif
 	return pci_module_init(&sstfb_driver);
 }
 
@@ -1693,9 +1700,9 @@ static void sstfb_drawdebugimage(struct fb_info *info)
 	sstfb_drawrect_XY(info, 250, 250, 120, 100, 0xf800, idx);
 }
 
+module_init(sstfb_init);
 
 #ifdef MODULE
-module_init(sstfb_init);
 module_exit(sstfb_exit);
 #endif
 
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c
index 9a1561503..4b7e498d0 100644
--- a/drivers/video/stifb.c
+++ b/drivers/video/stifb.c
@@ -1298,6 +1298,7 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp)
 	    case 1:
 		fix->type = FB_TYPE_PLANES;	/* well, sort of */
 		fix->visual = FB_VISUAL_MONO10;
+		var->red.length = var->green.length = var->blue.length = 1;
 		break;
 	    case 8:
 		fix->type = FB_TYPE_PACKED_PIXELS;
@@ -1324,7 +1325,7 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp)
 	strcpy(fix->id, "stifb");
 	info->fbops = &stifb_ops;
 	info->screen_base = (void*) REGION_BASE(fb,1);
-	info->flags = FBINFO_FLAG_DEFAULT;
+	info->flags = FBINFO_DEFAULT;
 	info->currcon = -1;
 
 	/* This has to been done !!! */
@@ -1375,12 +1376,22 @@ out_err0:
 
 static int stifb_disabled __initdata;
 
+int __init
+stifb_setup(char *options);
+
 int __init
 stifb_init(void)
 {
 	struct sti_struct *sti;
 	int i;
 	
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("stifb", &option))
+		return -ENODEV;
+	stifb_setup(option);
+#endif
 	if (stifb_disabled) {
 		printk(KERN_INFO "stifb: disabled by \"stifb=off\" kernel parameter\n");
 		return -ENXIO;
@@ -1451,9 +1462,7 @@ stifb_setup(char *options)
 
 __setup("stifb=", stifb_setup);
 
-#ifdef MODULE
 module_init(stifb_init);
-#endif
 module_exit(stifb_cleanup);
 
 MODULE_AUTHOR("Helge Deller <deller@gmx.de>, Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c
index 543711c99..e3e43ca2f 100644
--- a/drivers/video/tcx.c
+++ b/drivers/video/tcx.c
@@ -412,7 +412,7 @@ static void tcx_init_one(struct sbus_dev *sdev)
 		all->par.mmap_map[i].poff = sdev->reg_addrs[j].phys_addr;
 	}
 
-	all->info.flags = FBINFO_FLAG_DEFAULT;
+	all->info.flags = FBINFO_DEFAULT;
 	all->info.fbops = &tcx_ops;
 #ifdef CONFIG_SPARC32
 	all->info.screen_base = (char *)
@@ -468,6 +468,9 @@ int __init tcx_init(void)
 	struct sbus_bus *sbus;
 	struct sbus_dev *sdev;
 
+	if (fb_get_options("tcxfb", NULL))
+		return -ENODEV;
+
 	for_all_sbusdev(sdev, sbus) {
 		if (!strcmp(sdev->prom_name, "tcx"))
 			tcx_init_one(sdev);
@@ -496,8 +499,9 @@ tcx_setup(char *arg)
 	return 0;
 }
 
-#ifdef MODULE
 module_init(tcx_init);
+
+#ifdef MODULE
 module_exit(tcx_exit);
 #endif
 
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index 287387762..503ecc356 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -1,4 +1,3 @@
-
 /*
  *
  * tdfxfb.c
@@ -126,8 +125,9 @@ static struct fb_var_screeninfo tdfx_var __initdata = {
 /*
  * PCI driver prototypes
  */
-static int tdfxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id);
-static void tdfxfb_remove(struct pci_dev *pdev);
+static int __devinit tdfxfb_probe(struct pci_dev *pdev,
+				  const struct pci_device_id *id);
+static void __devexit tdfxfb_remove(struct pci_dev *pdev);
 
 static struct pci_device_id tdfxfb_id_table[] = {
 	{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE,
@@ -155,7 +155,7 @@ MODULE_DEVICE_TABLE(pci, tdfxfb_id_table);
  *  Frame buffer device API
  */
 int tdfxfb_init(void);
-void tdfxfb_setup(char *options, int *ints); 
+void tdfxfb_setup(char *options);
 
 static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb); 
 static int tdfxfb_set_par(struct fb_info *info); 
@@ -163,15 +163,12 @@ static int tdfxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 			    u_int transp, struct fb_info *info); 
 static int tdfxfb_blank(int blank, struct fb_info *info); 
 static int tdfxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
+static int banshee_wait_idle(struct fb_info *info);
+#ifdef CONFIG_FB_3DFX_ACCEL
 static void tdfxfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
 static void tdfxfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);  
 static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image); 
-#ifdef CONFIG_FB_3DFX_ACCEL
-static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor);
-#else /* !CONFIG_FB_3DFX_ACCEL */
-#define tdfxfb_cursor soft_cursor
 #endif /* CONFIG_FB_3DFX_ACCEL */
-static int banshee_wait_idle(struct fb_info *info);
 
 static struct fb_ops tdfxfb_ops = {
 	.owner		= THIS_MODULE,
@@ -180,11 +177,17 @@ static struct fb_ops tdfxfb_ops = {
 	.fb_setcolreg	= tdfxfb_setcolreg,
 	.fb_blank	= tdfxfb_blank,
 	.fb_pan_display	= tdfxfb_pan_display,
+	.fb_sync	= banshee_wait_idle,
+#ifdef CONFIG_FB_3DFX_ACCEL
 	.fb_fillrect	= tdfxfb_fillrect,
 	.fb_copyarea	= tdfxfb_copyarea,
 	.fb_imageblit	= tdfxfb_imageblit,
-	.fb_sync	= banshee_wait_idle,
-	.fb_cursor	= tdfxfb_cursor,
+#else
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+#endif
+	.fb_cursor	= soft_cursor,
 };
 
 /*
@@ -497,23 +500,21 @@ static int tdfxfb_check_var(struct fb_var_screeninfo *var,struct fb_info *info)
 		return -EINVAL;
 	}
 
-	if (var->xres != var->xres_virtual) {
-		DPRINTK("virtual x resolution != physical x resolution not supported\n");
-		return -EINVAL;
-	}
+	if (var->xres != var->xres_virtual)
+		var->xres_virtual = var->xres;
 
-	if (var->yres > var->yres_virtual) {
-		DPRINTK("virtual y resolution < physical y resolution not possible\n");
-		return -EINVAL;
-	}
+	if (var->yres > var->yres_virtual)
+		var->yres_virtual = var->yres;
 
 	if (var->xoffset) {
 		DPRINTK("xoffset not supported\n");
 		return -EINVAL;
 	}
 
-	/* fixme: does Voodoo3 support interlace? Banshee doesn't */
-	if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+	/* Banshee doesn't support interlace, but Voodoo4/5 and probably Voodoo3 do. */
+	/* no direct information about device id now? use max_pixclock for this... */
+	if (((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) &&
+			(par->max_pixclock < VOODOO3_MAX_PIXCLOCK)) {
 		DPRINTK("interlace not supported\n");
 		return -EINVAL;
 	}
@@ -532,9 +533,12 @@ static int tdfxfb_check_var(struct fb_var_screeninfo *var,struct fb_info *info)
 	}
   
 	if (lpitch * var->yres_virtual > info->fix.smem_len) {
-		DPRINTK("no memory for screen (%ux%ux%u)\n",
-		var->xres, var->yres_virtual, var->bits_per_pixel);
-		return -EINVAL;
+		var->yres_virtual = info->fix.smem_len/lpitch;
+		if (var->yres_virtual < var->yres) {
+			DPRINTK("no memory for screen (%ux%ux%u)\n",
+			var->xres, var->yres_virtual, var->bits_per_pixel);
+			return -EINVAL;
+		}
 	}
   
 	if (PICOS2KHZ(var->pixclock) > par->max_pixclock) {
@@ -584,7 +588,6 @@ static int tdfxfb_set_par(struct fb_info *info)
 	int fout, freq;
 	u32 wd, cpp;
   
-	info->cmap.len = (info->var.bits_per_pixel == 8) ? 256 : 16;
 	par->baseline  = 0;
  
 	memset(&reg, 0, sizeof(reg));
@@ -620,10 +623,17 @@ static int tdfxfb_set_par(struct fb_info *info)
 	hbs = hd;
 	hbe = ht;
 
-	vbs = vd = info->var.yres - 1;
-	vs  = vd + info->var.lower_margin;
-	ve  = vs + info->var.vsync_len;
-	vbe = vt = ve + info->var.upper_margin - 1;
+	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+		vbs = vd = (info->var.yres << 1) - 1;
+		vs  = vd + (info->var.lower_margin << 1);
+		ve  = vs + (info->var.vsync_len << 1);
+		vbe = vt = ve + (info->var.upper_margin << 1) - 1;
+	} else {
+		vbs = vd = info->var.yres - 1;
+		vs  = vd + info->var.lower_margin;
+		ve  = vs + info->var.vsync_len;
+		vbe = vt = ve + info->var.upper_margin - 1;
+	}
   
 	/* this is all pretty standard VGA register stuffing */
 	reg.misc[0x00] = 0x0f | 
@@ -746,8 +756,16 @@ static int tdfxfb_set_par(struct fb_info *info)
 	reg.gfxpll = do_calc_pll(..., &fout);
 #endif
 
-	reg.screensize = info->var.xres | (info->var.yres << 12);
-	reg.vidcfg &= ~VIDCFG_HALF_MODE;
+	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+		reg.screensize = info->var.xres | (info->var.yres << 13);
+		reg.vidcfg |= VIDCFG_HALF_MODE;
+		reg.crt[0x09] |= 0x80;
+	} else {
+		reg.screensize = info->var.xres | (info->var.yres << 12);
+		reg.vidcfg &= ~VIDCFG_HALF_MODE;
+	}
+	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
+		reg.vidcfg |= VIDCFG_INTERLACE;
 	reg.miscinit0 = tdfx_inl(par, MISCINIT0);
 
 #if defined(__BIG_ENDIAN)
@@ -787,7 +805,7 @@ static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
 	struct tdfx_par *par = (struct tdfx_par *) info->par;
 	u32 rgbcol;
    
-	if (regno >= info->cmap.len) return 1;
+	if (regno >= info->cmap.len || regno > 255) return 1;
    
 	switch (info->fix.visual) {
 		case FB_VISUAL_PSEUDOCOLOR:
@@ -876,6 +894,7 @@ static int tdfxfb_pan_display(struct fb_var_screeninfo *var,
 	return 0;
 }
 
+#ifdef CONFIG_FB_3DFX_ACCEL
 /*
  * FillRect 2D command (solidfill or invert (via ROP_XOR))   
  */
@@ -894,7 +913,11 @@ static void tdfxfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect
 
 	banshee_make_room(par, 5);
 	tdfx_outl(par,	DSTFORMAT, fmt);
-	tdfx_outl(par,	COLORFORE, rect->color);
+	if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
+		tdfx_outl(par,	COLORFORE, rect->color);
+	} else { /* FB_VISUAL_TRUECOLOR */
+		tdfx_outl(par, COLORFORE, ((u32*)(info->pseudo_palette))[rect->color]);
+	}
 	tdfx_outl(par,	COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24));
 	tdfx_outl(par,	DSTSIZE,    rect->width | (rect->height << 16));
 	tdfx_outl(par,	LAUNCH_2D,  rect->dx | (rect->dy << 16));
@@ -1004,8 +1027,9 @@ static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image)
 	}
 	banshee_wait_idle(info);
 }
+#endif /* CONFIG_FB_3DFX_ACCEL */
 
-#ifdef CONFIG_FB_3DFX_ACCEL
+#ifdef TDFX_HARDWARE_CURSOR
 static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
 	struct tdfx_par *par = (struct tdfx_par *) info->par;
@@ -1043,7 +1067,7 @@ static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 		struct fb_cmap cmap = cursor->image.cmap;
 		unsigned long bg_color, fg_color;
 
-		cmap.len = 2;/* Voodoo 3+ only support 2 color cursors*/
+		cmap.len = 2; /* Voodoo 3+ only support 2 color cursors */
 		fg_color = ((cmap.red[cmap.start] << 16) |
 			    (cmap.green[cmap.start] << 8)  |
 			    (cmap.blue[cmap.start]));
@@ -1101,7 +1125,7 @@ static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 		 */
 		u8 *cursorbase = (u8 *) info->cursor.image.data;
 		char *bitmap = (char *)cursor->image.data;
-		const char *mask = cursor->mask;
+		char *mask = (char *) cursor->mask;
 		int i, j, k, h = 0;
 
 		for (i = 0; i < 64; i++) {
@@ -1142,7 +1166,7 @@ static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 	spin_unlock_irqrestore(&par->DAClock, flags);
 	return 0;
 }
-#endif /* CONFIG_FB_3DFX_ACCEL */
+#endif
 
 /**
  *      tdfxfb_probe - Device Initializiation
@@ -1158,22 +1182,20 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
 {
 	struct tdfx_par *default_par;
 	struct fb_info *info;
-	int size, err;
+	int size, err, lpitch;
 
 	if ((err = pci_enable_device(pdev))) {
 		printk(KERN_WARNING "tdfxfb: Can't enable pdev: %d\n", err);
 		return err;
 	}
 
-	size = sizeof(struct fb_info)+sizeof(struct tdfx_par)+16*sizeof(u32);
+	size = sizeof(struct tdfx_par)+256*sizeof(u32);
 
-	info = kmalloc(size, GFP_KERNEL);
+	info = framebuffer_alloc(size, &pdev->dev);
 
 	if (!info)	return -ENOMEM;
 		
-	memset(info, 0, size);
-    
-	default_par = (struct tdfx_par *) (info + 1);
+	default_par = info->par;
  
 	/* Configure the default fb_fix_screeninfo first */
 	switch (pdev->device) {
@@ -1251,24 +1273,44 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
    
 	info->fbops		= &tdfxfb_ops;
 	info->fix		= tdfx_fix; 	
-	info->par		= default_par;
 	info->pseudo_palette	= (void *)(default_par + 1); 
-	info->flags		= FBINFO_FLAG_DEFAULT;
+	info->flags		= FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+#ifdef CONFIG_FB_3DFX_ACCEL
+	info->flags             |= FBINFO_HWACCEL_FILLRECT |
+		FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_IMAGEBLIT;
+#endif
 
-#ifndef MODULE
 	if (!mode_option)
 		mode_option = "640x480@60";
 	 
 	err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); 
 	if (!err || err == 4)
-#endif
 		info->var = tdfx_var;
 
-	size = (info->var.bits_per_pixel == 8) ? 256 : 16;
-	fb_alloc_cmap(&info->cmap, size, 0);  
+	/* maximize virtual vertical length */
+	lpitch = info->var.xres_virtual * ((info->var.bits_per_pixel + 7) >> 3);
+	info->var.yres_virtual = info->fix.smem_len/lpitch;
+	if (info->var.yres_virtual < info->var.yres)
+		goto out_err;
+
+#ifdef CONFIG_FB_3DFX_ACCEL
+	/*
+	 * FIXME: Limit var->yres_virtual to 4096 because of screen artifacts
+	 * during scrolling. This is only present if 2D acceleration is
+	 * enabled.
+	 */
+	if (info->var.yres_virtual > 4096)
+		info->var.yres_virtual = 4096;
+#endif /* CONFIG_FB_3DFX_ACCEL */
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+		printk(KERN_WARNING "tdfxfb: Can't allocate color map\n");
+		goto out_err;
+	}
 
 	if (register_framebuffer(info) < 0) {
 		printk("tdfxfb: can't register framebuffer\n");
+		fb_dealloc_cmap(&info->cmap);
 		goto out_err;
 	}
 	/*
@@ -1285,7 +1327,7 @@ out_err:
 		iounmap(default_par->regbase_virt);
 	if (info->screen_base)
 		iounmap(info->screen_base);
-	kfree(info);
+	framebuffer_release(info);
 	return -ENXIO;
 }
 
@@ -1315,11 +1357,19 @@ static void __devexit tdfxfb_remove(struct pci_dev *pdev)
 	release_mem_region(pci_resource_start(pdev, 0),
 			   pci_resource_len(pdev, 0));
 	pci_set_drvdata(pdev, NULL);
-	kfree(info);
+	framebuffer_release(info);
 }
 
 int __init tdfxfb_init(void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("tdfxfb", &option))
+		return -ENODEV;
+
+	tdfxfb_setup(option);
+#endif
         return pci_module_init(&tdfxfb_driver);
 }
 
@@ -1332,14 +1382,12 @@ MODULE_AUTHOR("Hannu Mallat <hmallat@cc.hut.fi>");
 MODULE_DESCRIPTION("3Dfx framebuffer device driver");
 MODULE_LICENSE("GPL");
  
-#ifdef MODULE
 module_init(tdfxfb_init);
-#endif
 module_exit(tdfxfb_exit);
 
 
 #ifndef MODULE
-void tdfxfb_setup(char *options, int *ints)
+void tdfxfb_setup(char *options)
 { 
 	char* this_opt;
 
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
index 3d02b0de9..07ee3202e 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -1426,7 +1426,8 @@ tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
 	pci_read_config_byte(pdev, PCI_REVISION_ID, &all->par.tga_chip_rev);
 
 	/* Setup framebuffer.  */
-	all->info.flags = FBINFO_FLAG_DEFAULT;
+	all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
+                          FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT;
 	all->info.fbops = &tgafb_ops;
 	all->info.screen_base = (char *) all->par.tga_fb_base;
 	all->info.currcon = -1;
@@ -1476,12 +1477,6 @@ tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
 	return ret;
 }
 
-int __init
-tgafb_init(void)
-{
-	return pci_module_init(&tgafb_driver);
-}
-
 #ifdef MODULE
 static void __exit
 tgafb_pci_unregister(struct pci_dev *pdev)
@@ -1528,12 +1523,26 @@ tgafb_setup(char *arg)
 }
 #endif /* !MODULE */
 
+int __init
+tgafb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("tgafb", &option))
+		return -ENODEV;
+	tgafb_setup(option);
+#endif
+	return pci_module_init(&tgafb_driver);
+}
+
 /*
  *  Modularisation
  */
 
-#ifdef MODULE
 module_init(tgafb_init);
+
+#ifdef MODULE
 module_exit(tgafb_exit);
 #endif
 
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index 17f8101ff..aea0e05c8 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -28,7 +28,7 @@
 
 struct tridentfb_par {
 	int vclk;		//in MHz
-	unsigned long io_virt;	//iospace virtual memory address
+	void __iomem * io_virt;	//iospace virtual memory address
 };
 
 unsigned char eng_oper;		//engine operation...
@@ -1107,7 +1107,7 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
 		return -1;
 	}
 
-	default_par.io_virt = (unsigned long)ioremap_nocache(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
+	default_par.io_virt = ioremap_nocache(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
 
 	if (!default_par.io_virt) {
 		release_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
@@ -1149,7 +1149,10 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
 	fb_info.fbops = &tridentfb_ops;
 
 
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+#ifdef CONFIG_FB_TRIDENT_ACCEL
+	fb_info.flags |= FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;
+#endif
 	fb_info.pseudo_palette = pseudo_pal;
 
 	if (!fb_find_mode(&default_var,&fb_info,mode,NULL,0,NULL,bpp))
@@ -1175,8 +1178,8 @@ static void __devexit trident_pci_remove(struct pci_dev * dev)
 {
 	struct tridentfb_par *par = (struct tridentfb_par*)fb_info.par;
 	unregister_framebuffer(&fb_info);
-	iounmap((void *)par->io_virt);
-	iounmap((void*)fb_info.screen_base);
+	iounmap(par->io_virt);
+	iounmap(fb_info.screen_base);
 	release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);
 	release_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
 }
@@ -1215,8 +1218,17 @@ static struct pci_driver tridentfb_pci_driver = {
 	.remove		= __devexit_p(trident_pci_remove)
 };
 
+int tridentfb_setup(char *options);
+
 int __init tridentfb_init(void)
 {
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("tridentfb", &option))
+		return -ENODEV;
+	tridentfb_setup(option);
+#endif
 	output("Trident framebuffer %s initializing\n", VERSION);
 	return pci_module_init(&tridentfb_pci_driver);
 }
@@ -1276,9 +1288,7 @@ static struct fb_ops tridentfb_ops = {
 	.fb_cursor = soft_cursor,
 };
 
-#ifdef MODULE
 module_init(tridentfb_init);
-#endif
 module_exit(tridentfb_exit);
 
 MODULE_AUTHOR("Jani Monoses <jani@iv.ro>");
diff --git a/drivers/video/tx3912fb.c b/drivers/video/tx3912fb.c
index f060c0ac3..09a9a3454 100644
--- a/drivers/video/tx3912fb.c
+++ b/drivers/video/tx3912fb.c
@@ -60,6 +60,9 @@ static struct fb_var_screeninfo tx3912fb_var = {
 	.blue =		{ 0, 2, 0 },
 #else
 	.bits_per_pixel =4,
+	.red =		{ 0, 4, 0 },	/* ??? */
+	.green =	{ 0, 4, 0 },
+	.blue =		{ 0, 4, 0 },
 #endif
 	.activate =	FB_ACTIVATE_NOW,
 	.width =	-1,
@@ -205,6 +208,8 @@ static int tx3912fb_setcolreg(u_int regno, u_int red, u_int green,
 	return 0;
 }
 
+int __init tx3912fb_setup(char *options);
+
 /*
  * Initialization of the framebuffer
  */
@@ -212,6 +217,11 @@ int __init tx3912fb_init(void)
 {
 	u_long tx3912fb_paddr = 0;
 	int size = (info->var.bits_per_pixel == 8) ? 256 : 16;
+	char *option = NULL;
+
+	if (fb_get_options("tx3912fb", &option))
+		return -ENODEV;
+	tx3912fb_setup(option);
 
 	/* Disable the video logic */
 	outl(inl(TX3912_VIDEO_CTRL1) &
@@ -296,7 +306,7 @@ int __init tx3912fb_init(void)
 	fb_info.var = tx3912fb_var;
 	fb_info.fix = tx3912fb_fix;
 	fb_info.pseudo_palette = pseudo_palette;
-	fb_info.flags = FBINFO_FLAG_DEFAULT;
+	fb_info.flags = FBINFO_DEFAULT;
 
 	/* Clear the framebuffer */
 	memset((void *) fb_info.fix.smem_start, 0xff, fb_info.fix.smem_len);
@@ -326,4 +336,5 @@ int __init tx3912fb_setup(char *options)
 	return 0;
 }
 
+module_init(tx3912fb_init);
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c
index fd8eb47a4..cdb1b1447 100644
--- a/drivers/video/valkyriefb.c
+++ b/drivers/video/valkyriefb.c
@@ -322,6 +322,11 @@ int __init valkyriefb_init(void)
 	struct fb_info_valkyrie	*p;
 	unsigned long frame_buffer_phys, cmap_regs_phys, flags;
 	int err;
+	char *option = NULL;
+
+	if (fb_get_options("valkyriefb", &option))
+		return -ENODEV;
+	valkyriefb_setup(option);
 
 #ifdef CONFIG_MAC
 	if (!MACH_IS_MAC)
@@ -540,7 +545,7 @@ static void __init valkyrie_init_info(struct fb_info *info, struct fb_info_valky
 {
 	info->fbops = &valkyriefb_ops;
 	info->screen_base = (char *) p->frame_buffer + 0x1000;
-	info->flags = FBINFO_FLAG_DEFAULT;
+	info->flags = FBINFO_DEFAULT;
 	info->pseudo_palette = p->pseudo_palette;
 	fb_alloc_cmap(&info->cmap, 256, 0);
 	info->par = &p->par;
@@ -579,4 +584,5 @@ int __init valkyriefb_setup(char *options)
 	return 0;
 }
 
+module_init(valkyriefb_init);
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index 15f7f8e47..c5c649d9b 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -87,15 +87,17 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var,
 	return 0;
 }
 
-static void vesa_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
+static void vesa_setpalette(int regno, unsigned red, unsigned green,
+			    unsigned blue, struct fb_var_screeninfo *var)
 {
 #ifdef __i386__
 	struct { u_char blue, green, red, pad; } entry;
+	int shift = 16 - var->green.length;
 
 	if (pmi_setpal) {
-		entry.red   = red   >> 10;
-		entry.green = green >> 10;
-		entry.blue  = blue  >> 10;
+		entry.red   = red   >> shift;
+		entry.green = green >> shift;
+		entry.blue  = blue  >> shift;
 		entry.pad   = 0;
 	        __asm__ __volatile__(
                 "call *(%%esi)"
@@ -109,9 +111,9 @@ static void vesa_setpalette(int regno, unsigned red, unsigned green, unsigned bl
 	} else {
 		/* without protected mode interface, try VGA registers... */
 		outb_p(regno,       dac_reg);
-		outb_p(red   >> 10, dac_val);
-		outb_p(green >> 10, dac_val);
-		outb_p(blue  >> 10, dac_val);
+		outb_p(red   >> shift, dac_val);
+		outb_p(green >> shift, dac_val);
+		outb_p(blue  >> shift, dac_val);
 	}
 #endif
 }
@@ -132,7 +134,7 @@ static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
 
 	switch (info->var.bits_per_pixel) {
 	case 8:
-		vesa_setpalette(regno,red,green,blue);
+		vesa_setpalette(regno,red,green,blue, &info->var);
 		break;
 	case 16:
 		if (info->var.red.offset == 10) {
@@ -331,30 +333,26 @@ static int __init vesafb_probe(struct device *device)
 	vesafb_defined.left_margin  = (vesafb_defined.xres / 8) & 0xf8;
 	vesafb_defined.hsync_len    = (vesafb_defined.xres / 8) & 0xf8;
 	
-	if (vesafb_defined.bits_per_pixel > 8) {
-		vesafb_defined.red.offset    = screen_info.red_pos;
-		vesafb_defined.red.length    = screen_info.red_size;
-		vesafb_defined.green.offset  = screen_info.green_pos;
-		vesafb_defined.green.length  = screen_info.green_size;
-		vesafb_defined.blue.offset   = screen_info.blue_pos;
-		vesafb_defined.blue.length   = screen_info.blue_size;
-		vesafb_defined.transp.offset = screen_info.rsvd_pos;
-		vesafb_defined.transp.length = screen_info.rsvd_size;
-		printk(KERN_INFO "vesafb: directcolor: "
-		       "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
-		       screen_info.rsvd_size,
-		       screen_info.red_size,
-		       screen_info.green_size,
-		       screen_info.blue_size,
-		       screen_info.rsvd_pos,
-		       screen_info.red_pos,
-		       screen_info.green_pos,
-		       screen_info.blue_pos);
-	} else {
-		vesafb_defined.red.length   = 6;
-		vesafb_defined.green.length = 6;
-		vesafb_defined.blue.length  = 6;
-	}
+	vesafb_defined.red.offset    = screen_info.red_pos;
+	vesafb_defined.red.length    = screen_info.red_size;
+	vesafb_defined.green.offset  = screen_info.green_pos;
+	vesafb_defined.green.length  = screen_info.green_size;
+	vesafb_defined.blue.offset   = screen_info.blue_pos;
+	vesafb_defined.blue.length   = screen_info.blue_size;
+	vesafb_defined.transp.offset = screen_info.rsvd_pos;
+	vesafb_defined.transp.length = screen_info.rsvd_size;
+	printk(KERN_INFO "vesafb: %s: "
+	       "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
+	       (vesafb_defined.bits_per_pixel > 8) ?
+	       "Truecolor" : "Pseudocolor",
+	       screen_info.rsvd_size,
+	       screen_info.red_size,
+	       screen_info.green_size,
+	       screen_info.blue_size,
+	       screen_info.rsvd_pos,
+	       screen_info.red_pos,
+	       screen_info.green_pos,
+	       screen_info.blue_pos);
 
 	vesafb_fix.ypanstep  = ypan     ? 1 : 0;
 	vesafb_fix.ywrapstep = (ypan>1) ? 1 : 0;
@@ -412,7 +410,11 @@ static struct platform_device vesafb_device = {
 int __init vesafb_init(void)
 {
 	int ret;
+	char *option = NULL;
 
+	/* ignore error return of fb_get_options */
+	fb_get_options("vesafb", &option);
+	vesafb_setup(option);
 	ret = driver_register(&vesafb_driver);
 
 	if (!ret) {
@@ -422,6 +424,7 @@ int __init vesafb_init(void)
 	}
 	return ret;
 }
+module_init(vesafb_init);
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index 8b01918a5..a00da53ec 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -496,6 +496,14 @@ int __init vfb_init(void)
 {
 	int ret = 0;
 
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("vfb", &option))
+		return -ENODEV;
+	vfb_setup(option);
+#endif
+
 	if (!vfb_enable)
 		return -ENXIO;
 
@@ -509,6 +517,8 @@ int __init vfb_init(void)
 	return ret;
 }
 
+module_init(vfb_init);
+
 #ifdef MODULE
 static void __exit vfb_exit(void)
 {
@@ -516,7 +526,6 @@ static void __exit vfb_exit(void)
 	driver_unregister(&vfb_driver);
 }
 
-module_init(vfb_init);
 module_exit(vfb_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 770681ca6..2e132fb61 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -1342,7 +1342,14 @@ int __init vga16fb_init(void)
 {
 	int i;
 	int ret;
+#ifndef MODULE
+	char *option = NULL;
 
+	if (fb_get_options("vga16fb", &option))
+		return -ENODEV;
+
+	vga16fb_setup(option);
+#endif
 	printk(KERN_DEBUG "vga16fb: initializing\n");
 
 	/* XXX share VGA_FB_PHYS and I/O region with vgacon and others */
@@ -1418,8 +1425,8 @@ static void __exit vga16fb_exit(void)
 
 #ifdef MODULE
 MODULE_LICENSE("GPL");
-module_init(vga16fb_init);
 #endif
+module_init(vga16fb_init);
 module_exit(vga16fb_exit);
 
 
diff --git a/drivers/video/vgastate.c b/drivers/video/vgastate.c
index 190228189..0ea62d8bc 100644
--- a/drivers/video/vgastate.c
+++ b/drivers/video/vgastate.c
@@ -32,21 +32,21 @@ struct regstate {
 	__u8 misc;
 };	
 
-static inline unsigned char vga_rcrtcs(caddr_t regbase, unsigned short iobase, 
+static inline unsigned char vga_rcrtcs(void __iomem *regbase, unsigned short iobase, 
 				       unsigned char reg)
 {
 	vga_w(regbase, iobase + 0x4, reg);
 	return vga_r(regbase, iobase + 0x5);
 }
 
-static inline void vga_wcrtcs(caddr_t regbase, unsigned short iobase, 
+static inline void vga_wcrtcs(void __iomem *regbase, unsigned short iobase, 
 			      unsigned char reg, unsigned char val)
 {
 	vga_w(regbase, iobase + 0x4, reg);
 	vga_w(regbase, iobase + 0x5, val);
 }
 
-static void save_vga_text(struct vgastate *state, caddr_t fbbase)
+static void save_vga_text(struct vgastate *state, void __iomem *fbbase)
 {
 	struct regstate *saved = (struct regstate *) state->vidstate;
 	int i;
@@ -134,7 +134,7 @@ static void save_vga_text(struct vgastate *state, caddr_t fbbase)
 	vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1);
 }
 
-static void restore_vga_text(struct vgastate *state, caddr_t fbbase)
+static void restore_vga_text(struct vgastate *state, void __iomem *fbbase)
 {
 	struct regstate *saved = (struct regstate *) state->vidstate;
 	int i;
@@ -403,7 +403,7 @@ int save_vga(struct vgastate *state)
 	}
 
 	if (state->flags & VGA_SAVE_FONTS) {
-		caddr_t fbbase;
+		void __iomem *fbbase;
 
 		/* exit if window is less than 32K */
 		if (state->memsize && state->memsize < 4 * 8192) {
@@ -473,7 +473,7 @@ int restore_vga (struct vgastate *state)
 		restore_vga_mode(state);
 
 	if (state->flags & VGA_SAVE_FONTS) {
-		caddr_t fbbase = ioremap(state->membase, state->memsize);
+		void __iomem *fbbase = ioremap(state->membase, state->memsize);
 
 		if (!fbbase) {
 			vga_cleanup(state);
diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig
index bdeb028aa..984954932 100644
--- a/drivers/w1/Kconfig
+++ b/drivers/w1/Kconfig
@@ -21,6 +21,25 @@ config W1_MATROX
 	  This support is also available as a module.  If so, the module 
 	  will be called matrox_w1.ko.
 
+config W1_DS9490
+	tristate "DS9490R transport layer driver"
+	depends on W1 && USB
+	help
+	  Say Y here if you want to have a driver for DS9490R UWB <-> W1 bridge.
+
+	  This support is also available as a module.  If so, the module 
+	  will be called ds9490r.ko.
+
+config W1_DS9490R_BRIDGE
+	tristate "DS9490R USB <-> W1 transport layer for 1-wire"
+	depends on W1_DS9490
+	help
+	  Say Y here if you want to communicate with your 1-wire devices
+	  using DS9490R USB bridge.
+
+	  This support is also available as a module.  If so, the module 
+	  will be called ds_w1_bridge.ko.
+
 config W1_THERM
 	tristate "Thermal family implementation"
 	depends on W1
@@ -28,4 +47,11 @@ config W1_THERM
 	  Say Y here if you want to connect 1-wire thermal sensors to you
 	  wire.
 
+config W1_SMEM
+	tristate "Simple 64bit memory family implementation"
+	depends on W1
+	help
+	  Say Y here if you want to connect 1-wire 
+	  simple 64bit memory rom(ds2401/ds2411/ds1990*) to you wire.
+
 endmenu
diff --git a/drivers/w1/Makefile b/drivers/w1/Makefile
index 7d005d960..a389bdc04 100644
--- a/drivers/w1/Makefile
+++ b/drivers/w1/Makefile
@@ -7,3 +7,10 @@ wire-objs		:= w1.o w1_int.o w1_family.o w1_netlink.o w1_io.o
 
 obj-$(CONFIG_W1_MATROX)		+= matrox_w1.o
 obj-$(CONFIG_W1_THERM)		+= w1_therm.o
+obj-$(CONFIG_W1_SMEM)		+= w1_smem.o
+
+obj-$(CONFIG_W1_DS9490)		+= ds9490r.o 
+ds9490r-objs    := dscore.o
+
+obj-$(CONFIG_W1_DS9490_BRIDGE)	+= ds_w1_bridge.o
+
diff --git a/drivers/w1/matrox_w1.c b/drivers/w1/matrox_w1.c
index bde17782e..44abe37e4 100644
--- a/drivers/w1/matrox_w1.c
+++ b/drivers/w1/matrox_w1.c
@@ -94,7 +94,7 @@ static void matrox_w1_write_ddc_bit(unsigned long, u8);
 /*
  * These functions read and write DDC Data bit.
  *
- * Using tristate pins, since i can't  fin any open-drain pin in whole motherboard.
+ * Using tristate pins, since i can't find any open-drain pin in whole motherboard.
  * Unfortunately we can't connect to Intel's 82801xx IO controller
  * since we don't know motherboard schema, wich has pretty unused(may be not) GPIO.
  *
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 4f52422ae..278393f79 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -45,7 +45,7 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
 MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol.");
 
-static int w1_timeout = 5 * HZ;
+static int w1_timeout = 10;
 int w1_max_slave_count = 10;
 
 module_param_named(timeout, w1_timeout, int, 0);
@@ -137,25 +137,95 @@ static struct device_attribute w1_slave_attribute_val = {
 	.show = &w1_default_read_name,
 };
 
-static ssize_t w1_master_attribute_show(struct device *dev, char *buf)
+ssize_t w1_master_attribute_show_name(struct device *dev, char *buf)
+{
+	struct w1_master *md = container_of (dev, struct w1_master, dev);
+	ssize_t count;
+	
+	if (down_interruptible (&md->mutex))
+		return -EBUSY;
+
+	count = sprintf(buf, "%s\n", md->name);
+	
+	up(&md->mutex);
+
+	return count;
+}
+
+ssize_t w1_master_attribute_show_pointer(struct device *dev, char *buf)
+{
+	struct w1_master *md = container_of(dev, struct w1_master, dev);
+	ssize_t count;
+	
+	if (down_interruptible(&md->mutex))
+		return -EBUSY;
+
+	count = sprintf(buf, "0x%p\n", md->bus_master);
+	
+	up(&md->mutex);
+	return count;
+}
+
+ssize_t w1_master_attribute_show_timeout(struct device *dev, char *buf)
+{
+	ssize_t count;
+	count = sprintf(buf, "%d\n", w1_timeout);
+	return count;
+}
+
+ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, char *buf)
+{
+	struct w1_master *md = container_of(dev, struct w1_master, dev);
+	ssize_t count;
+	
+	if (down_interruptible(&md->mutex))
+		return -EBUSY;
+
+	count = sprintf(buf, "%d\n", md->max_slave_count);
+	
+	up(&md->mutex);
+	return count;
+}
+
+ssize_t w1_master_attribute_show_attempts(struct device *dev, char *buf)
+{
+	struct w1_master *md = container_of(dev, struct w1_master, dev);
+	ssize_t count;
+	
+	if (down_interruptible(&md->mutex))
+		return -EBUSY;
+
+	count = sprintf(buf, "%lu\n", md->attempts);
+	
+	up(&md->mutex);
+	return count;
+}
+
+ssize_t w1_master_attribute_show_slave_count(struct device *dev, char *buf)
+{
+	struct w1_master *md = container_of(dev, struct w1_master, dev);
+	ssize_t count;
+	
+	if (down_interruptible(&md->mutex))
+		return -EBUSY;
+
+	count = sprintf(buf, "%d\n", md->slave_count);
+	
+	up(&md->mutex);
+	return count;
+}
+
+ssize_t w1_master_attribute_show_slaves(struct device *dev, char *buf)
+
 {
-	return sprintf(buf, "please fix me\n");
-#if 0
 	struct w1_master *md = container_of(dev, struct w1_master, dev);
 	int c = PAGE_SIZE;
 
 	if (down_interruptible(&md->mutex))
 		return -EBUSY;
 
-	c -= snprintf(buf + PAGE_SIZE - c, c, "%s\n", md->name);
-	c -= snprintf(buf + PAGE_SIZE - c, c,
-		       "bus_master=0x%p, timeout=%d, max_slave_count=%d, attempts=%lu\n",
-		       md->bus_master, w1_timeout, md->max_slave_count,
-		       md->attempts);
-	c -= snprintf(buf + PAGE_SIZE - c, c, "%d slaves: ",
-		       md->slave_count);
 	if (md->slave_count == 0)
-		c -= snprintf(buf + PAGE_SIZE - c, c, "no.\n");
+		c -= snprintf(buf + PAGE_SIZE - c, c, "not found.\n");
 	else {
 		struct list_head *ent, *n;
 		struct w1_slave *sl;
@@ -163,25 +233,70 @@ static ssize_t w1_master_attribute_show(struct device *dev, char *buf)
 		list_for_each_safe(ent, n, &md->slist) {
 			sl = list_entry(ent, struct w1_slave, w1_slave_entry);
 
-			c -= snprintf(buf + PAGE_SIZE - c, c, "%s[%p] ",
-				       sl->name, sl);
+ 			c -= snprintf(buf + PAGE_SIZE - c, c, "%s\n", sl->name);
 		}
-		c -= snprintf(buf + PAGE_SIZE - c, c, "\n");
 	}
 
 	up(&md->mutex);
 
 	return PAGE_SIZE - c;
-#endif
 }
 
-struct device_attribute w1_master_attribute = {
+static struct device_attribute w1_master_attribute_slaves = {
 	.attr = {
-			.name = "w1_master_stats",
+ 			.name = "w1_master_slaves",
 			.mode = S_IRUGO,
 			.owner = THIS_MODULE,
 	},
-	.show = &w1_master_attribute_show,
+ 	.show = &w1_master_attribute_show_slaves,
+};
+static struct device_attribute w1_master_attribute_slave_count = {
+	.attr = {
+			.name = "w1_master_slave_count",
+			.mode = S_IRUGO,
+			.owner = THIS_MODULE
+	},
+	.show = &w1_master_attribute_show_slave_count,
+};
+static struct device_attribute w1_master_attribute_attempts = {
+	.attr = {
+			.name = "w1_master_attempts",
+			.mode = S_IRUGO,
+			.owner = THIS_MODULE
+	},
+	.show = &w1_master_attribute_show_attempts,
+};
+static struct device_attribute w1_master_attribute_max_slave_count = {
+	.attr = {
+			.name = "w1_master_max_slave_count",
+			.mode = S_IRUGO,
+			.owner = THIS_MODULE
+	},
+	.show = &w1_master_attribute_show_max_slave_count,
+};
+static struct device_attribute w1_master_attribute_timeout = {
+	.attr = {
+			.name = "w1_master_timeout",
+			.mode = S_IRUGO,
+			.owner = THIS_MODULE
+	},
+	.show = &w1_master_attribute_show_timeout,
+};
+static struct device_attribute w1_master_attribute_pointer = {
+	.attr = {
+			.name = "w1_master_pointer",
+			.mode = S_IRUGO,
+			.owner = THIS_MODULE
+	},
+	.show = &w1_master_attribute_show_pointer,
+};
+static struct device_attribute w1_master_attribute_name = {
+	.attr = {
+			.name = "w1_master_name",
+			.mode = S_IRUGO,
+			.owner = THIS_MODULE
+	},
+	.show = &w1_master_attribute_show_name,
 };
 
 static struct bin_attribute w1_slave_bin_attribute = {
@@ -204,11 +319,11 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
 	sl->dev.release = &w1_slave_release;
 
 	snprintf(&sl->dev.bus_id[0], sizeof(sl->dev.bus_id),
-		  "%x-%llx",
+		  "%02x-%012llx",
 		  (unsigned int) sl->reg_num.family,
 		  (unsigned long long) sl->reg_num.id);
 	snprintf (&sl->name[0], sizeof(sl->name),
-		  "%x-%llx",
+		  "%02x-%012llx",
 		  (unsigned int) sl->reg_num.family,
 		  (unsigned long long) sl->reg_num.id);
 
@@ -223,12 +338,16 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
 		return err;
 	}
 
-	w1_slave_bin_attribute.read = sl->family->fops->rbin;
-	w1_slave_attribute.show = sl->family->fops->rname;
-	w1_slave_attribute_val.show = sl->family->fops->rval;
-	w1_slave_attribute_val.attr.name = sl->family->fops->rvalname;
+	memcpy(&sl->attr_bin, &w1_slave_bin_attribute, sizeof(sl->attr_bin));
+	memcpy(&sl->attr_name, &w1_slave_attribute, sizeof(sl->attr_name));
+	memcpy(&sl->attr_val, &w1_slave_attribute_val, sizeof(sl->attr_val));
+	
+	sl->attr_bin.read = sl->family->fops->rbin;
+	sl->attr_name.show = sl->family->fops->rname;
+	sl->attr_val.show = sl->family->fops->rval;
+	sl->attr_val.attr.name = sl->family->fops->rvalname;
 
-	err = device_create_file(&sl->dev, &w1_slave_attribute);
+	err = device_create_file(&sl->dev, &sl->attr_name);
 	if (err < 0) {
 		dev_err(&sl->dev,
 			 "sysfs file creation for [%s] failed. err=%d\n",
@@ -237,23 +356,23 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
 		return err;
 	}
 
-	err = device_create_file(&sl->dev, &w1_slave_attribute_val);
+	err = device_create_file(&sl->dev, &sl->attr_val);
 	if (err < 0) {
 		dev_err(&sl->dev,
 			 "sysfs file creation for [%s] failed. err=%d\n",
 			 sl->dev.bus_id, err);
-		device_remove_file(&sl->dev, &w1_slave_attribute);
+		device_remove_file(&sl->dev, &sl->attr_name);
 		device_unregister(&sl->dev);
 		return err;
 	}
 
-	err = sysfs_create_bin_file(&sl->dev.kobj, &w1_slave_bin_attribute);
+	err = sysfs_create_bin_file(&sl->dev.kobj, &sl->attr_bin);
 	if (err < 0) {
 		dev_err(&sl->dev,
 			 "sysfs file creation for [%s] failed. err=%d\n",
 			 sl->dev.bus_id, err);
-		device_remove_file(&sl->dev, &w1_slave_attribute);
-		device_remove_file(&sl->dev, &w1_slave_attribute_val);
+		device_remove_file(&sl->dev, &sl->attr_name);
+		device_remove_file(&sl->dev, &sl->attr_val);
 		device_unregister(&sl->dev);
 		return err;
 	}
@@ -268,6 +387,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
 	struct w1_slave *sl;
 	struct w1_family *f;
 	int err;
+	struct w1_netlink_msg msg;
 
 	sl = kmalloc(sizeof(struct w1_slave), GFP_KERNEL);
 	if (!sl) {
@@ -281,6 +401,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
 
 	sl->owner = THIS_MODULE;
 	sl->master = dev;
+	set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
 
 	memcpy(&sl->reg_num, rn, sizeof(sl->reg_num));
 	atomic_set(&sl->refcnt, 0);
@@ -290,8 +411,8 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
 	f = w1_family_registered(rn->family);
 	if (!f) {
 		spin_unlock(&w1_flock);
-		dev_info(&dev->dev, "Family %x is not registered.\n",
-			  rn->family);
+		dev_info(&dev->dev, "Family %x for %02x.%012llx.%02x is not registered.\n",
+			  rn->family, rn->family, rn->id, rn->crc);
 		kfree(sl);
 		return -ENODEV;
 	}
@@ -312,20 +433,31 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
 
 	dev->slave_count++;
 
+	memcpy(&msg.id.id, rn, sizeof(msg.id.id));
+	msg.type = W1_SLAVE_ADD;
+	w1_netlink_send(dev, &msg);
+
 	return 0;
 }
 
 static void w1_slave_detach(struct w1_slave *sl)
 {
+	struct w1_netlink_msg msg;
+	
 	dev_info(&sl->dev, "%s: detaching %s.\n", __func__, sl->name);
 
 	while (atomic_read(&sl->refcnt))
 		schedule_timeout(10);
 
-	sysfs_remove_bin_file(&sl->dev.kobj, &w1_slave_bin_attribute);
-	device_remove_file(&sl->dev, &w1_slave_attribute);
+	sysfs_remove_bin_file (&sl->dev.kobj, &sl->attr_bin);
+	device_remove_file(&sl->dev, &sl->attr_name);
+	device_remove_file(&sl->dev, &sl->attr_val);
 	device_unregister(&sl->dev);
 	w1_family_put(sl->family);
+
+	memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id));
+	msg.type = W1_SLAVE_REMOVE;
+	w1_netlink_send(sl->master, &msg);
 }
 
 static void w1_search(struct w1_master *dev)
@@ -337,12 +469,9 @@ static void w1_search(struct w1_master *dev)
 	struct list_head *ent;
 	struct w1_slave *sl;
 	int family_found = 0;
-	struct w1_netlink_msg msg;
 
 	dev->attempts++;
 
-	memset(&msg, 0, sizeof(msg));
-
 	search_bit = id_bit = comp_bit = 0;
 	rn = tmp = last = 0;
 	last_device = last_zero = last_family_desc = 0;
@@ -368,8 +497,6 @@ static void w1_search(struct w1_master *dev)
 		}
 
 #if 1
-		memset(&msg, 0, sizeof(msg));
-
 		w1_write_8(dev, W1_SEARCH);
 		for (i = 0; i < 64; ++i) {
 			/*
@@ -413,9 +540,6 @@ static void w1_search(struct w1_master *dev)
 
 		}
 #endif
-		msg.id.w1_id = rn;
-		msg.val = w1_calc_crc8((u8 *) & rn, 7);
-		w1_netlink_send(dev, &msg);
 
 		if (desc_bit == last_zero)
 			last_device = 1;
@@ -432,8 +556,10 @@ static void w1_search(struct w1_master *dev)
 
 			if (sl->reg_num.family == tmp->family &&
 			    sl->reg_num.id == tmp->id &&
-			    sl->reg_num.crc == tmp->crc)
+			    sl->reg_num.crc == tmp->crc) {
+				set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
 				break;
+			}
 			else if (sl->reg_num.family == tmp->family) {
 				family_found = 1;
 				break;
@@ -443,12 +569,38 @@ static void w1_search(struct w1_master *dev)
 		}
 
 		if (slave_count == dev->slave_count &&
-		    msg.val && (*((__u8 *) & msg.val) == msg.id.id.crc)) {
+		    ((rn >> 56) & 0xff) == w1_calc_crc8((u8 *)&rn, 7)) {
 			w1_attach_slave_device(dev, (struct w1_reg_num *) &rn);
 		}
 	}
 }
 
+int w1_create_master_attributes(struct w1_master *dev)
+{
+	if (	device_create_file(&dev->dev, &w1_master_attribute_slaves) < 0 ||
+		device_create_file(&dev->dev, &w1_master_attribute_slave_count) < 0 ||
+		device_create_file(&dev->dev, &w1_master_attribute_attempts) < 0 ||
+		device_create_file(&dev->dev, &w1_master_attribute_max_slave_count) < 0 ||
+		device_create_file(&dev->dev, &w1_master_attribute_timeout) < 0||
+		device_create_file(&dev->dev, &w1_master_attribute_pointer) < 0||
+		device_create_file(&dev->dev, &w1_master_attribute_name) < 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+void w1_destroy_master_attributes(struct w1_master *dev)
+{
+	device_remove_file(&dev->dev, &w1_master_attribute_slaves);
+	device_remove_file(&dev->dev, &w1_master_attribute_slave_count);
+	device_remove_file(&dev->dev, &w1_master_attribute_attempts);
+	device_remove_file(&dev->dev, &w1_master_attribute_max_slave_count);
+	device_remove_file(&dev->dev, &w1_master_attribute_timeout);
+	device_remove_file(&dev->dev, &w1_master_attribute_pointer);
+	device_remove_file(&dev->dev, &w1_master_attribute_name);
+}
+
+
 int w1_control(void *data)
 {
 	struct w1_slave *sl;
@@ -462,7 +614,7 @@ int w1_control(void *data)
 	while (!control_needs_exit || have_to_wait) {
 		have_to_wait = 0;
 
-		timeout = w1_timeout;
+		timeout = w1_timeout*HZ;
 		do {
 			timeout = interruptible_sleep_on_timeout(&w1_control_wait, timeout);
 			if (current->flags & PF_FREEZE)
@@ -516,7 +668,7 @@ int w1_control(void *data)
 					kfree(sl);
 				}
 			}
-			device_remove_file(&dev->dev, &w1_master_attribute);
+			w1_destroy_master_attributes(dev);
 			atomic_dec(&dev->refcnt);
 		}
 	}
@@ -528,12 +680,14 @@ int w1_process(void *data)
 {
 	struct w1_master *dev = (struct w1_master *) data;
 	unsigned long timeout;
+	struct list_head *ent, *n;
+	struct w1_slave *sl;
 
 	daemonize("%s", dev->name);
 	allow_signal(SIGTERM);
 
 	while (!dev->need_exit) {
-		timeout = w1_timeout;
+		timeout = w1_timeout*HZ;
 		do {
 			timeout = interruptible_sleep_on_timeout(&dev->kwait, timeout);
 			if (current->flags & PF_FREEZE)
@@ -551,7 +705,28 @@ int w1_process(void *data)
 
 		if (down_interruptible(&dev->mutex))
 			continue;
-		w1_search(dev);
+
+		list_for_each_safe(ent, n, &dev->slist) {
+			sl = list_entry(ent, struct w1_slave, w1_slave_entry);
+
+			if (sl)
+				clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
+		}
+		
+      		w1_search(dev);
+		
+		list_for_each_safe(ent, n, &dev->slist) {
+			sl = list_entry(ent, struct w1_slave, w1_slave_entry);
+
+			if (sl && !test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags)) {
+				list_del (&sl->w1_slave_entry);
+
+				w1_slave_detach (sl);
+				kfree (sl);
+
+				dev->slave_count--;
+			}
+		}
 		up(&dev->mutex);
 	}
 
@@ -621,3 +796,6 @@ void w1_fini(void)
 
 module_init(w1_init);
 module_exit(w1_fini);
+
+EXPORT_SYMBOL(w1_create_master_attributes);
+EXPORT_SYMBOL(w1_destroy_master_attributes);
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h
index aba042d25..54a3437a8 100644
--- a/drivers/w1/w1.h
+++ b/drivers/w1/w1.h
@@ -52,6 +52,8 @@ struct w1_reg_num
 #define W1_READ_PSUPPLY		0xB4
 #define W1_MATCH_ROM		0x55
 
+#define W1_SLAVE_ACTIVE		(1<<0)
+
 struct w1_slave
 {
 	struct module		*owner;
@@ -60,11 +62,15 @@ struct w1_slave
 	struct w1_reg_num	reg_num;
 	atomic_t		refcnt;
 	u8			rom[9];
+	u32			flags;
 
 	struct w1_master	*master;
 	struct w1_family 	*family;
 	struct device 		dev;
 	struct completion 	dev_released;
+
+	struct bin_attribute 	attr_bin;
+	struct device_attribute	attr_name, attr_val;
 };
 
 struct w1_bus_master
@@ -73,6 +79,16 @@ struct w1_bus_master
 
 	u8			(*read_bit)(unsigned long);
 	void			(*write_bit)(unsigned long, u8);
+  	
+	u8			(*read_byte)(unsigned long);
+  	void			(*write_byte)(unsigned long, u8);
+  	
+	u8			(*read_block)(unsigned long, u8 *, int);
+	void			(*write_block)(unsigned long, u8 *, int);
+	
+  	u8			(*touch_bit)(unsigned long, u8);
+  
+  	u8			(*reset_bus)(unsigned long);
 };
 
 struct w1_master
@@ -107,6 +123,9 @@ struct w1_master
 	struct sock 		*nls;
 };
 
+int w1_create_master_attributes(struct w1_master *);
+void w1_destroy_master_attributes(struct w1_master *);
+
 #endif /* __KERNEL__ */
 
 #endif /* __W1_H */
diff --git a/drivers/w1/w1_family.c b/drivers/w1/w1_family.c
index 9b8443cc5..6a62d2adb 100644
--- a/drivers/w1/w1_family.c
+++ b/drivers/w1/w1_family.c
@@ -27,12 +27,23 @@
 spinlock_t w1_flock = SPIN_LOCK_UNLOCKED;
 static LIST_HEAD(w1_families);
 
+static int w1_check_family(struct w1_family *f)
+{
+	if (!f->fops->rname || !f->fops->rbin || !f->fops->rval || !f->fops->rvalname)
+		return -EINVAL;
+
+	return 0;
+}
+
 int w1_register_family(struct w1_family *newf)
 {
 	struct list_head *ent, *n;
 	struct w1_family *f;
 	int ret = 0;
 
+	if (w1_check_family(newf))
+		return -EINVAL;
+
 	spin_lock(&w1_flock);
 	list_for_each_safe(ent, n, &w1_families) {
 		f = list_entry(ent, struct w1_family, family_entry);
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h
index 15f44fe32..03a2de7a6 100644
--- a/drivers/w1/w1_family.h
+++ b/drivers/w1/w1_family.h
@@ -28,7 +28,7 @@
 
 #define W1_FAMILY_DEFAULT	0
 #define W1_FAMILY_THERM		0x10
-#define W1_FAMILY_IBUT		0xff /* ? */
+#define W1_FAMILY_SMEM		0x01
 
 #define MAXNAMELEN		32
 
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c
index c75e9f717..e671d407b 100644
--- a/drivers/w1/w1_int.c
+++ b/drivers/w1/w1_int.c
@@ -24,13 +24,13 @@
 
 #include "w1.h"
 #include "w1_log.h"
+#include "w1_netlink.h"
 
 static u32 w1_ids = 1;
 
 extern struct device_driver w1_driver;
 extern struct bus_type w1_bus_type;
 extern struct device w1_device;
-extern struct device_attribute w1_master_attribute;
 extern int w1_max_slave_count;
 extern struct list_head w1_masters;
 extern spinlock_t w1_mlock;
@@ -119,6 +119,7 @@ int w1_add_master_device(struct w1_bus_master *master)
 {
 	struct w1_master *dev;
 	int retval = 0;
+	struct w1_netlink_msg msg;
 
 	dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, &w1_driver, &w1_device);
 	if (!dev)
@@ -133,7 +134,7 @@ int w1_add_master_device(struct w1_bus_master *master)
 		goto err_out_free_dev;
 	}
 
-	retval = device_create_file(&dev->dev, &w1_master_attribute);
+	retval =  w1_create_master_attributes(dev);
 	if (retval)
 		goto err_out_kill_thread;
 
@@ -145,6 +146,11 @@ int w1_add_master_device(struct w1_bus_master *master)
 	list_add(&dev->w1_master_entry, &w1_masters);
 	spin_unlock(&w1_mlock);
 
+	msg.id.mst.id = dev->id;
+	msg.id.mst.pid = dev->kpid;
+	msg.type = W1_MASTER_ADD;
+	w1_netlink_send(dev, &msg);
+
 	return 0;
 
 err_out_kill_thread:
@@ -164,6 +170,7 @@ err_out_free_dev:
 void __w1_remove_master_device(struct w1_master *dev)
 {
 	int err;
+	struct w1_netlink_msg msg;
 
 	dev->need_exit = 1;
 	err = kill_proc(dev->kpid, SIGTERM, 1);
@@ -175,6 +182,11 @@ void __w1_remove_master_device(struct w1_master *dev)
 	while (atomic_read(&dev->refcnt))
 		schedule_timeout(10);
 
+	msg.id.mst.id = dev->id;
+	msg.id.mst.pid = dev->kpid;
+	msg.type = W1_MASTER_REMOVE;
+	w1_netlink_send(dev, &msg);
+
 	w1_free_dev(dev);
 }
 
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c
index 9baacee68..765f065a5 100644
--- a/drivers/w1/w1_io.c
+++ b/drivers/w1/w1_io.c
@@ -55,6 +55,14 @@ void w1_delay(unsigned long tm)
 	udelay(tm * w1_delay_parm);
 }
 
+u8 w1_touch_bit(struct w1_master *dev, int bit)
+{
+	if (dev->bus_master->touch_bit)
+		return dev->bus_master->touch_bit(dev->bus_master->data, bit);
+	else
+		return w1_read_bit(dev);
+}
+
 void w1_write_bit(struct w1_master *dev, int bit)
 {
 	if (bit) {
@@ -74,8 +82,11 @@ void w1_write_8(struct w1_master *dev, u8 byte)
 {
 	int i;
 
-	for (i = 0; i < 8; ++i)
-		w1_write_bit(dev, (byte >> i) & 0x1);
+	if (dev->bus_master->write_byte)
+		dev->bus_master->write_byte(dev->bus_master->data, byte);
+	else
+		for (i = 0; i < 8; ++i)
+			w1_write_bit(dev, (byte >> i) & 0x1);
 }
 
 u8 w1_read_bit(struct w1_master *dev)
@@ -98,23 +109,57 @@ u8 w1_read_8(struct w1_master * dev)
 	int i;
 	u8 res = 0;
 
-	for (i = 0; i < 8; ++i)
-		res |= (w1_read_bit(dev) << i);
+	if (dev->bus_master->read_byte)
+		res = dev->bus_master->read_byte(dev->bus_master->data);
+	else
+		for (i = 0; i < 8; ++i)
+			res |= (w1_read_bit(dev) << i);
 
 	return res;
 }
 
+void w1_write_block(struct w1_master *dev, u8 *buf, int len)
+{
+	int i;
+
+	if (dev->bus_master->write_block)
+		dev->bus_master->write_block(dev->bus_master->data, buf, len);
+	else
+		for (i = 0; i < len; ++i)
+			w1_write_8(dev, buf[i]);
+}
+
+u8 w1_read_block(struct w1_master *dev, u8 *buf, int len)
+{
+	int i;
+	u8 ret;
+
+	if (dev->bus_master->read_block)
+		ret = dev->bus_master->read_block(dev->bus_master->data, buf, len);
+	else {
+		for (i = 0; i < len; ++i)
+			buf[i] = w1_read_8(dev);
+		ret = len;
+	}
+
+	return ret;
+}
+
 int w1_reset_bus(struct w1_master *dev)
 {
-	int result;
+	int result = 0;
 
-	dev->bus_master->write_bit(dev->bus_master->data, 0);
-	w1_delay(480);
-	dev->bus_master->write_bit(dev->bus_master->data, 1);
-	w1_delay(70);
+	if (dev->bus_master->reset_bus)
+		result = dev->bus_master->reset_bus(dev->bus_master->data) & 0x1;
+	else {
+		dev->bus_master->write_bit(dev->bus_master->data, 0);
+		w1_delay(480);
+		dev->bus_master->write_bit(dev->bus_master->data, 1);
+		w1_delay(70);
 
-	result = dev->bus_master->read_bit(dev->bus_master->data) & 0x1;
-	w1_delay(410);
+		result = dev->bus_master->read_bit(dev->bus_master->data) & 0x1;
+		w1_delay(410);
+	}
 
 	return result;
 }
@@ -136,3 +181,5 @@ EXPORT_SYMBOL(w1_read_8);
 EXPORT_SYMBOL(w1_reset_bus);
 EXPORT_SYMBOL(w1_calc_crc8);
 EXPORT_SYMBOL(w1_delay);
+EXPORT_SYMBOL(w1_read_block);
+EXPORT_SYMBOL(w1_write_block);
diff --git a/drivers/w1/w1_io.h b/drivers/w1/w1_io.h
index e493a87b6..f63c2108b 100644
--- a/drivers/w1/w1_io.h
+++ b/drivers/w1/w1_io.h
@@ -25,11 +25,14 @@
 #include "w1.h"
 
 void w1_delay(unsigned long);
+u8 w1_touch_bit(struct w1_master *, int);
 void w1_write_bit(struct w1_master *, int);
 void w1_write_8(struct w1_master *, u8);
 u8 w1_read_bit(struct w1_master *);
 u8 w1_read_8(struct w1_master *);
 int w1_reset_bus(struct w1_master *);
 u8 w1_calc_crc8(u8 *, int);
+void w1_write_block(struct w1_master *, u8 *, int);
+u8 w1_read_block(struct w1_master *, u8 *, int);
 
 #endif /* __W1_IO_H */
diff --git a/drivers/w1/w1_netlink.h b/drivers/w1/w1_netlink.h
index 7064ded18..ea1b530ab 100644
--- a/drivers/w1/w1_netlink.h
+++ b/drivers/w1/w1_netlink.h
@@ -26,14 +26,27 @@
 
 #include "w1.h"
 
+enum w1_netlink_message_types {
+	W1_SLAVE_ADD = 0,
+	W1_SLAVE_REMOVE,
+	W1_MASTER_ADD,
+	W1_MASTER_REMOVE,
+};
+
 struct w1_netlink_msg 
 {
+	__u8				type;
+	__u8				reserved[3];
 	union
 	{
 		struct w1_reg_num 	id;
 		__u64			w1_id;
+		struct
+		{
+			__u32		id;
+			__u32		pid;
+		} mst;
 	} id;
-	__u64				val;
 };
 
 #ifdef __KERNEL__
diff --git a/drivers/w1/w1_therm.c b/drivers/w1/w1_therm.c
index 3eed82984..d986c601f 100644
--- a/drivers/w1/w1_therm.c
+++ b/drivers/w1/w1_therm.c
@@ -36,6 +36,11 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
 MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family.");
 
+static u8 bad_roms[][9] = {
+				{0xaa, 0x00, 0x4b, 0x46, 0xff, 0xff, 0x0c, 0x10, 0x87}, 
+				{}
+			};
+
 static ssize_t w1_therm_read_name(struct device *, char *);
 static ssize_t w1_therm_read_temp(struct device *, char *);
 static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t);
@@ -69,14 +74,24 @@ static ssize_t w1_therm_read_temp(struct device *dev, char *buf)
 	return sprintf(buf, "%d\n", temp * 1000);
 }
 
+static int w1_therm_check_rom(u8 rom[9])
+{
+	int i;
+
+	for (i=0; i<sizeof(bad_roms)/9; ++i)
+		if (!memcmp(bad_roms[i], rom, 9))
+			return 1;
+
+	return 0;
+}
+
 static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
 {
 	struct w1_slave *sl = container_of(container_of(kobj, struct device, kobj),
 			      			struct w1_slave, dev);
 	struct w1_master *dev = sl->master;
 	u8 rom[9], crc, verdict;
-	size_t icount;
-	int i;
+	int i, max_trying = 10;
 	u16 temp;
 
 	atomic_inc(&sl->refcnt);
@@ -89,10 +104,10 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
 		count = 0;
 		goto out;
 	}
-	if (off + count > W1_SLAVE_DATA_SIZE)
-		count = W1_SLAVE_DATA_SIZE - off;
-
-	icount = count;
+	if (off + count > W1_SLAVE_DATA_SIZE) {
+		count = 0;
+		goto out;
+	}
 
 	memset(buf, 0, count);
 	memset(rom, 0, sizeof(rom));
@@ -100,56 +115,54 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
 	count = 0;
 	verdict = 0;
 	crc = 0;
-	if (!w1_reset_bus(dev)) {
-		u64 id = *(u64 *) & sl->reg_num;
-		int count = 0;
 
-		w1_write_8(dev, W1_MATCH_ROM);
-		for (i = 0; i < 8; ++i)
-			w1_write_8(dev, (id >> i * 8) & 0xff);
+	while (max_trying--) {
+		if (!w1_reset_bus (dev)) {
+			int count = 0;
+			u8 match[9] = {W1_MATCH_ROM, };
 
-		w1_write_8(dev, W1_CONVERT_TEMP);
+			memcpy(&match[1], (u64 *) & sl->reg_num, 8);
+			
+			w1_write_block(dev, match, 9);
 
-		while (dev->bus_master->read_bit(dev->bus_master->data) == 0
-		       && count < 10) {
-			w1_delay(1);
-			count++;
-		}
+			w1_write_8(dev, W1_CONVERT_TEMP);
 
-		if (count < 10) {
-			if (!w1_reset_bus(dev)) {
-				w1_write_8(dev, W1_MATCH_ROM);
-				for (i = 0; i < 8; ++i)
-					w1_write_8(dev,
-						   (id >> i * 8) & 0xff);
+			if (count < 10) {
+				if (!w1_reset_bus(dev)) {
+					w1_write_block(dev, match, 9);
 
-				w1_write_8(dev, W1_READ_SCRATCHPAD);
-				for (i = 0; i < 9; ++i)
-					rom[i] = w1_read_8(dev);
+					w1_write_8(dev, W1_READ_SCRATCHPAD);
+					if ((count = w1_read_block(dev, rom, 9)) != 9) {
+						dev_warn(&dev->dev, "w1_read_block() returned %d instead of 9.\n", count);
+					}
 
-				crc = w1_calc_crc8(rom, 8);
+					crc = w1_calc_crc8(rom, 8);
 
-				if (rom[8] == crc && rom[0])
-					verdict = 1;
+					if (rom[8] == crc && rom[0])
+						verdict = 1;
+				}
 			}
+			else
+				dev_warn(&dev->dev,
+					  "18S20 doesn't respond to CONVERT_TEMP.\n");
 		}
-		else
-			dev_warn(&dev->dev,
-				  "18S20 doesn't respond to CONVERT_TEMP.\n");
+
+		if (!w1_therm_check_rom(rom))
+			break;
 	}
 
 	for (i = 0; i < 9; ++i)
-		count += snprintf(buf + count, icount - count, "%02x ", rom[i]);
-	count += snprintf(buf + count, icount - count, ": crc=%02x %s\n",
+		count += sprintf(buf + count, "%02x ", rom[i]);
+	count += sprintf(buf + count, ": crc=%02x %s\n",
 			   crc, (verdict) ? "YES" : "NO");
 	if (verdict)
 		memcpy(sl->rom, rom, sizeof(sl->rom));
 	for (i = 0; i < 9; ++i)
-		count += snprintf(buf + count, icount - count, "%02x ", sl->rom[i]);
+		count += sprintf(buf + count, "%02x ", sl->rom[i]);
 	temp = 0;
 	temp <<= sl->rom[1] / 2;
 	temp |= sl->rom[0] / 2;
-	count += snprintf(buf + count, icount - count, "t=%u\n", temp);
+	count += sprintf(buf + count, "t=%u\n", temp);
 out:
 	up(&dev->mutex);
 out_dec:
diff --git a/drivers/zorro/Makefile b/drivers/zorro/Makefile
index 32f99d846..f62172603 100644
--- a/drivers/zorro/Makefile
+++ b/drivers/zorro/Makefile
@@ -5,7 +5,7 @@
 obj-$(CONFIG_ZORRO)	+= zorro.o zorro-driver.o zorro-sysfs.o names.o
 obj-$(CONFIG_PROC_FS)	+= proc.o
 
-host-progs 		:= gen-devlist
+hostprogs-y 		:= gen-devlist
 
 # Files generated that shall be removed upon make clean
 clean-files := devlist.h
diff --git a/fs/Kconfig b/fs/Kconfig
index a4035fba9..c8cf86596 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -289,7 +289,7 @@ config FS_POSIX_ACL
 # 	Never use this symbol for ifdefs.
 #
 	bool
-	depends on EXT2_FS_POSIX_ACL || EXT3_FS_POSIX_ACL || JFS_POSIX_ACL || REISERFS_FS_POSIX_ACL
+	depends on EXT2_FS_POSIX_ACL || EXT3_FS_POSIX_ACL || JFS_POSIX_ACL || REISERFS_FS_POSIX_ACL || NFSD_V4
 	default y
 
 config XFS_FS
@@ -650,18 +650,21 @@ config FAT_DEFAULT_CODEPAGE
 	default 437
 	help
 	  This option should be set to the codepage of your FAT filesystems.
-	  It can be overridden with the 'codepage' mount option.
+	  It can be overridden with the "codepage" mount option.
+	  See <file:Documentation/filesystems/vfat.txt> for more information.
 
 config FAT_DEFAULT_IOCHARSET
 	string "Default iocharset for FAT"
 	depends on VFAT_FS
 	default "iso8859-1"
 	help
-	  Set this to the default I/O character set you'd like FAT to use.
-	  It should probably match the character set that most of your
-	  FAT filesystems use, and can be overridded with the 'iocharset'
-	  mount option for FAT filesystems.  Note that UTF8 is *not* a
-	  supported charset for FAT filesystems.
+	  Set this to the default input/output character set you'd
+	  like FAT to use. It should probably match the character set
+	  that most of your FAT filesystems use, and can be overridden
+	  with the "iocharset" mount option for FAT filesystems.
+	  Note that "utf8" is not recommended for FAT filesystems.
+	  If unsure, you shouldn't set "utf8" here.
+	  See <file:Documentation/filesystems/vfat.txt> for more information.
 
 config UMSDOS_FS
 #dep_tristate '    UMSDOS: Unix-like file system on top of standard MSDOS fs' CONFIG_UMSDOS_FS $CONFIG_MSDOS_FS
@@ -1213,7 +1216,7 @@ config JFFS2_CMODE_SIZE
 endchoice
 
 config CRAMFS
-	tristate "Compressed ROM file system support"
+	tristate "Compressed ROM file system support (cramfs)"
 	select ZLIB_INFLATE
 	help
 	  Saying Y here includes support for CramFs (Compressed ROM File
@@ -1415,8 +1418,8 @@ config NFS_V3
 	bool "Provide NFSv3 client support"
 	depends on NFS_FS
 	help
-	  Say Y here if you want your NFS client to be able to speak the newer
-	  version 3 of the NFS protocol.
+	  Say Y here if you want your NFS client to be able to speak version
+	  3 of the NFS protocol.
 
 	  If unsure, say Y.
 
@@ -1495,6 +1498,7 @@ config NFSD_V3
 config NFSD_V4
 	bool "Provide NFSv4 server support (EXPERIMENTAL)"
 	depends on NFSD_V3 && EXPERIMENTAL
+	select NFSD_TCP
 	help
 	  If you would like to include the NFSv4 server as well as the NFSv2
 	  and NFSv3 servers, say Y here.  This feature is experimental, and
@@ -1559,6 +1563,22 @@ config RPCSEC_GSS_KRB5
 
 	  If unsure, say N.
 
+config RPCSEC_GSS_SPKM3
+	tristate "Secure RPC: SPKM3 mechanism (EXPERIMENTAL)"
+	depends on SUNRPC && EXPERIMENTAL
+	select SUNRPC_GSS
+	select CRYPTO
+	select CRYPTO_MD5
+	select CRYPTO_DES
+	help
+	  Provides for secure RPC calls by means of a gss-api
+	  mechanism based on the SPKM3 public-key mechanism.
+
+	  Note: Requires an auxiliary userspace daemon which may be found on
+	  	http://www.citi.umich.edu/projects/nfsv4/
+
+	  If unsure, say N.
+
 config SMB_FS
 	tristate "SMB file system support (to mount Windows shares etc.)"
 	depends on INET
diff --git a/fs/Makefile b/fs/Makefile
index 41cac35d1..e68e9f5bd 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -91,3 +91,5 @@ obj-$(CONFIG_JFS_FS)		+= jfs/
 obj-$(CONFIG_XFS_FS)		+= xfs/
 obj-$(CONFIG_AFS_FS)		+= afs/
 obj-$(CONFIG_BEFS_FS)		+= befs/
+obj-$(CONFIG_HOSTFS)		+= hostfs/
+obj-$(CONFIG_HPPFS)		+= hppfs/
diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h
index 6aed04ea5..63f5df9af 100644
--- a/fs/adfs/adfs.h
+++ b/fs/adfs/adfs.h
@@ -64,15 +64,9 @@ struct adfs_discmap {
 	unsigned int		dm_endbit;
 };
 
-/* dir stuff */
-
-
 /* Inode stuff */
-int adfs_get_block(struct inode *inode, sector_t block,
-		   struct buffer_head *bh, int create);
 struct inode *adfs_iget(struct super_block *sb, struct object_info *obj);
-void adfs_read_inode(struct inode *inode);
-void adfs_write_inode(struct inode *inode,int unused);
+int adfs_write_inode(struct inode *inode,int unused);
 int adfs_notify_change(struct dentry *dentry, struct iattr *attr);
 
 /* map.c */
@@ -84,9 +78,6 @@ void __adfs_error(struct super_block *sb, const char *function,
 		  const char *fmt, ...);
 #define adfs_error(sb, fmt...) __adfs_error(sb, __FUNCTION__, fmt)
 
-/* namei.c */
-extern struct dentry *adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *);
-
 /* super.c */
 
 /*
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c
index 1c047fc77..d80a2d7bf 100644
--- a/fs/adfs/dir.c
+++ b/fs/adfs/dir.c
@@ -268,7 +268,8 @@ struct dentry_operations adfs_dentry_operations = {
 	.d_compare	= adfs_compare,
 };
 
-struct dentry *adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *
+adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode *inode = NULL;
 	struct object_info obj;
diff --git a/fs/adfs/dir_f.c b/fs/adfs/dir_f.c
index 1c6062668..b61648b2d 100644
--- a/fs/adfs/dir_f.c
+++ b/fs/adfs/dir_f.c
@@ -93,7 +93,7 @@ static inline void adfs_writename(char *to, char *from, int maxlen)
 #define dir_u32(idx)				\
 	({ int _buf = idx >> blocksize_bits;	\
 	   int _off = idx - (_buf << blocksize_bits);\
-	  *(u32 *)(bh[_buf]->b_data + _off);	\
+	  *(__le32 *)(bh[_buf]->b_data + _off);	\
 	})
 
 #define bufoff(_bh,_idx)			\
@@ -112,7 +112,7 @@ adfs_dir_checkbyte(const struct adfs_dir *dir)
 {
 	struct buffer_head * const *bh = dir->bh;
 	const int blocksize_bits = dir->sb->s_blocksize_bits;
-	union { u32 *ptr32; u8 *ptr8; } ptr, end;
+	union { __le32 *ptr32; u8 *ptr8; } ptr, end;
 	u32 dircheck = 0;
 	int last = 5 - 26;
 	int i = 0;
@@ -125,7 +125,7 @@ adfs_dir_checkbyte(const struct adfs_dir *dir)
 	do {
 		last += 26;
 		do {
-			dircheck = cpu_to_le32(dir_u32(i)) ^ ror13(dircheck);
+			dircheck = le32_to_cpu(dir_u32(i)) ^ ror13(dircheck);
 
 			i += sizeof(u32);
 		} while (i < (last & ~3));
@@ -155,8 +155,8 @@ adfs_dir_checkbyte(const struct adfs_dir *dir)
 	end.ptr8 = ptr.ptr8 + 36;
 
 	do {
-		unsigned int v = *ptr.ptr32++;
-		dircheck = cpu_to_le32(v) ^ ror13(dircheck);
+		__le32 v = *ptr.ptr32++;
+		dircheck = le32_to_cpu(v) ^ ror13(dircheck);
 	} while (ptr.ptr32 < end.ptr32);
 
 	return (dircheck ^ (dircheck >> 8) ^ (dircheck >> 16) ^ (dircheck >> 24)) & 0xff;
@@ -165,7 +165,7 @@ adfs_dir_checkbyte(const struct adfs_dir *dir)
 /*
  * Read and check that a directory is valid
  */
-int
+static int
 adfs_dir_read(struct super_block *sb, unsigned long object_id,
 	      unsigned int size, struct adfs_dir *dir)
 {
@@ -260,7 +260,7 @@ adfs_obj2dir(struct adfs_direntry *de, struct object_info *obj)
  * get a directory entry.  Note that the caller is responsible
  * for holding the relevant locks.
  */
-int
+static int
 __adfs_dir_get(struct adfs_dir *dir, int pos, struct object_info *obj)
 {
 	struct super_block *sb = dir->sb;
@@ -290,7 +290,7 @@ __adfs_dir_get(struct adfs_dir *dir, int pos, struct object_info *obj)
 	return 0;
 }
 
-int
+static int
 __adfs_dir_put(struct adfs_dir *dir, int pos, struct object_info *obj)
 {
 	struct super_block *sb = dir->sb;
diff --git a/fs/adfs/dir_fplus.h b/fs/adfs/dir_fplus.h
index a65f65348..b55aa41a6 100644
--- a/fs/adfs/dir_fplus.h
+++ b/fs/adfs/dir_fplus.h
@@ -18,27 +18,27 @@
 struct adfs_bigdirheader {
 	__u8	startmasseq;
 	__u8	bigdirversion[3];
-	__u32	bigdirstartname;
-	__u32	bigdirnamelen;
-	__u32	bigdirsize;
-	__u32	bigdirentries;
-	__u32	bigdirnamesize;
-	__u32	bigdirparent;
+	__le32	bigdirstartname;
+	__le32	bigdirnamelen;
+	__le32	bigdirsize;
+	__le32	bigdirentries;
+	__le32	bigdirnamesize;
+	__le32	bigdirparent;
 	char	bigdirname[1];
 };
 
 struct adfs_bigdirentry {
-	__u32	bigdirload;
-	__u32	bigdirexec;
-	__u32	bigdirlen;
-	__u32	bigdirindaddr;
-	__u32	bigdirattr;
-	__u32	bigdirobnamelen;
-	__u32	bigdirobnameptr;
+	__le32	bigdirload;
+	__le32	bigdirexec;
+	__le32	bigdirlen;
+	__le32	bigdirindaddr;
+	__le32	bigdirattr;
+	__le32	bigdirobnamelen;
+	__le32	bigdirobnameptr;
 };
 
 struct adfs_bigdirtail {
-	__u32	bigdirendname;
+	__le32	bigdirendname;
 	__u8	bigdirendmasseq;
 	__u8	reserved[2];
 	__u8	bigdircheckbyte;
diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c
index f17ccbcc5..fee82147f 100644
--- a/fs/adfs/inode.c
+++ b/fs/adfs/inode.c
@@ -24,8 +24,9 @@
  * Lookup/Create a block at offset 'block' into 'inode'.  We currently do
  * not support creation of new blocks, so we return -EIO for this case.
  */
-int
-adfs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh, int create)
+static int
+adfs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh,
+	       int create)
 {
 	if (block < 0)
 		goto abort_negative;
@@ -372,10 +373,11 @@ out:
  * The adfs-specific inode data has already been updated by
  * adfs_notify_change()
  */
-void adfs_write_inode(struct inode *inode, int unused)
+int adfs_write_inode(struct inode *inode, int unused)
 {
 	struct super_block *sb = inode->i_sb;
 	struct object_info obj;
+	int ret;
 
 	lock_kernel();
 	obj.file_id	= inode->i_ino;
@@ -386,7 +388,8 @@ void adfs_write_inode(struct inode *inode, int unused)
 	obj.attr	= ADFS_I(inode)->attr;
 	obj.size	= inode->i_size;
 
-	adfs_dir_update(sb, &obj);
+	ret = adfs_dir_update(sb, &obj);
 	unlock_kernel();
+	return ret;
 }
 MODULE_LICENSE("GPL");
diff --git a/fs/adfs/map.c b/fs/adfs/map.c
index 7c59ca701..48c7a31c8 100644
--- a/fs/adfs/map.c
+++ b/fs/adfs/map.c
@@ -92,9 +92,8 @@ lookup_zone(const struct adfs_discmap *dm, const unsigned int idlen,
 		 * find end of fragment
 		 */
 		{
-			u32 v, *_map = (u32 *)map;
-
-			v = le32_to_cpu(_map[mapptr >> 5]) >> (mapptr & 31);
+			__le32 *_map = (__le32 *)map;
+			u32 v = le32_to_cpu(_map[mapptr >> 5]) >> (mapptr & 31);
 			while (v == 0) {
 				mapptr = (mapptr & ~31) + 32;
 				if (mapptr >= mapsize)
@@ -171,9 +170,8 @@ scan_free_map(struct adfs_sb_info *asb, struct adfs_discmap *dm)
 		 * find end of fragment
 		 */
 		{
-			u32 v, *_map = (u32 *)map;
-
-			v = le32_to_cpu(_map[mapptr >> 5]) >> (mapptr & 31);
+			__le32 *_map = (__le32 *)map;
+			u32 v = le32_to_cpu(_map[mapptr >> 5]) >> (mapptr & 31);
 			while (v == 0) {
 				mapptr = (mapptr & ~31) + 32;
 				if (mapptr >= mapsize)
diff --git a/fs/adfs/super.c b/fs/adfs/super.c
index e9462e76a..87e869450 100644
--- a/fs/adfs/super.c
+++ b/fs/adfs/super.c
@@ -62,7 +62,7 @@ static int adfs_checkdiscrecord(struct adfs_discrecord *dr)
 	 * are unable to represent sector offsets in
 	 * 32 bits.  This works out at 2.0 TB.
 	 */
-	if (dr->disc_size_high >> dr->log2secsize)
+	if (le32_to_cpu(dr->disc_size_high) >> dr->log2secsize)
 		return 1;
 
 	/* idlen must be no greater than 19 v2 [1.0] */
@@ -241,7 +241,7 @@ static int init_inodecache(void)
 {
 	adfs_inode_cachep = kmem_cache_create("adfs_inode_cache",
 					     sizeof(struct adfs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (adfs_inode_cachep == NULL)
 		return -ENOMEM;
@@ -300,8 +300,8 @@ static struct adfs_discmap *adfs_read_map(struct super_block *sb, struct adfs_di
 	i = zone - 1;
 	dm[0].dm_startblk = 0;
 	dm[0].dm_startbit = ADFS_DR_SIZE_BITS;
-	dm[i].dm_endbit   = (dr->disc_size_high << (32 - dr->log2bpmb)) +
-			    (dr->disc_size >> dr->log2bpmb) +
+	dm[i].dm_endbit   = (le32_to_cpu(dr->disc_size_high) << (32 - dr->log2bpmb)) +
+			    (le32_to_cpu(dr->disc_size) >> dr->log2bpmb) +
 			    (ADFS_DR_SIZE_BITS - i * zone_size);
 
 	if (adfs_checkmap(sb, dm))
@@ -439,7 +439,7 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
 	 * get the root_size from the disc record.
 	 */
 	if (asb->s_version) {
-		root_obj.size = dr->root_size;
+		root_obj.size = le32_to_cpu(dr->root_size);
 		asb->s_dir     = &adfs_fplus_dir_ops;
 		asb->s_namelen = ADFS_FPLUS_NAME_LEN;
 	} else {
diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c
index 17a4bfbb1..1ad629167 100644
--- a/fs/affs/amigaffs.c
+++ b/fs/affs/amigaffs.c
@@ -84,7 +84,8 @@ affs_remove_hash(struct inode *dir, struct buffer_head *rem_bh)
 {
 	struct super_block *sb;
 	struct buffer_head *bh;
-	u32 rem_ino, hash_ino, ino;
+	u32 rem_ino, hash_ino;
+	__be32 ino;
 	int offset, retval;
 
 	sb = dir->i_sb;
@@ -203,9 +204,9 @@ affs_remove_link(struct dentry *dentry)
 
 	while ((ino = be32_to_cpu(AFFS_TAIL(sb, bh)->link_chain)) != 0) {
 		if (ino == link_ino) {
-			ino = AFFS_TAIL(sb, link_bh)->link_chain;
-			AFFS_TAIL(sb, bh)->link_chain = ino;
-			affs_adjust_checksum(bh, be32_to_cpu(ino) - link_ino);
+			__be32 ino2 = AFFS_TAIL(sb, link_bh)->link_chain;
+			AFFS_TAIL(sb, bh)->link_chain = ino2;
+			affs_adjust_checksum(bh, be32_to_cpu(ino2) - link_ino);
 			mark_buffer_dirty_inode(bh, inode);
 			retval = 0;
 			/* Fix the link count, if bh is a normal header block without links */
@@ -341,12 +342,12 @@ done_unlock:
 u32
 affs_checksum_block(struct super_block *sb, struct buffer_head *bh)
 {
-	u32 *ptr = (u32 *)bh->b_data;
+	__be32 *ptr = (__be32 *)bh->b_data;
 	u32 sum;
 	int bsize;
 
 	sum = 0;
-	for (bsize = sb->s_blocksize / sizeof(u32); bsize > 0; bsize--)
+	for (bsize = sb->s_blocksize / sizeof(__be32); bsize > 0; bsize--)
 		sum += be32_to_cpu(*ptr++);
 	return sum;
 }
@@ -359,9 +360,10 @@ affs_checksum_block(struct super_block *sb, struct buffer_head *bh)
 void
 affs_fix_checksum(struct super_block *sb, struct buffer_head *bh)
 {
-	int cnt = sb->s_blocksize / sizeof(u32);
-	u32 *ptr = (u32 *)bh->b_data;
-	u32 checksum, *checksumptr;
+	int cnt = sb->s_blocksize / sizeof(__be32);
+	__be32 *ptr = (__be32 *)bh->b_data;
+	u32 checksum;
+	__be32 *checksumptr;
 
 	checksumptr = ptr + 5;
 	*checksumptr = 0;
@@ -384,9 +386,9 @@ secs_to_datestamp(time_t secs, struct affs_date *ds)
 	minute  = secs / 60;
 	secs   -= minute * 60;
 
-	ds->days = be32_to_cpu(days);
-	ds->mins = be32_to_cpu(minute);
-	ds->ticks = be32_to_cpu(secs * 50);
+	ds->days = cpu_to_be32(days);
+	ds->mins = cpu_to_be32(minute);
+	ds->ticks = cpu_to_be32(secs * 50);
 }
 
 mode_t
diff --git a/fs/affs/bitmap.c b/fs/affs/bitmap.c
index 93d32d18e..44e322143 100644
--- a/fs/affs/bitmap.c
+++ b/fs/affs/bitmap.c
@@ -21,7 +21,7 @@
 
 static int nibblemap[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
 
-u32
+static u32
 affs_count_free_bits(u32 blocksize, const void *data)
 {
 	const u32 *map;
@@ -72,7 +72,7 @@ affs_free_block(struct super_block *sb, u32 block)
 	struct affs_bm_info *bm;
 	struct buffer_head *bh;
 	u32 blk, bmap, bit, mask, tmp;
-	u32 *data;
+	__be32 *data;
 
 	pr_debug("AFFS: free_block(%u)\n", block);
 
@@ -97,7 +97,7 @@ affs_free_block(struct super_block *sb, u32 block)
 	}
 
 	mask = 1 << (bit & 31);
-	data = (u32 *)bh->b_data + bit / 32 + 1;
+	data = (__be32 *)bh->b_data + bit / 32 + 1;
 
 	/* mark block free */
 	tmp = be32_to_cpu(*data);
@@ -106,8 +106,8 @@ affs_free_block(struct super_block *sb, u32 block)
 	*data = cpu_to_be32(tmp | mask);
 
 	/* fix checksum */
-	tmp = be32_to_cpu(*(u32 *)bh->b_data);
-	*(u32 *)bh->b_data = cpu_to_be32(tmp - mask);
+	tmp = be32_to_cpu(*(__be32 *)bh->b_data);
+	*(__be32 *)bh->b_data = cpu_to_be32(tmp - mask);
 
 	mark_buffer_dirty(bh);
 	sb->s_dirt = 1;
@@ -149,7 +149,7 @@ affs_alloc_block(struct inode *inode, u32 goal)
 	struct affs_sb_info *sbi;
 	struct affs_bm_info *bm;
 	struct buffer_head *bh;
-	u32 *data, *enddata;
+	__be32 *data, *enddata;
 	u32 blk, bmap, bit, mask, mask2, tmp;
 	int i;
 
@@ -211,8 +211,8 @@ find_bmap_bit:
 
 	/* find an unused block in this bitmap block */
 	bit = blk % sbi->s_bmap_bits;
-	data = (u32 *)bh->b_data + bit / 32 + 1;
-	enddata = (u32 *)((u8 *)bh->b_data + sb->s_blocksize);
+	data = (__be32 *)bh->b_data + bit / 32 + 1;
+	enddata = (__be32 *)((u8 *)bh->b_data + sb->s_blocksize);
 	mask = ~0UL << (bit & 31);
 	blk &= ~31UL;
 
@@ -228,8 +228,8 @@ find_bmap_bit:
 			 * if scan didn't start at 0, try next bmap
 			 */
 			goto find_bmap;
-	} while (!(tmp = *data));
-	tmp = be32_to_cpu(tmp);
+	} while (!*data);
+	tmp = be32_to_cpu(*data);
 	mask = ~0;
 
 find_bit:
@@ -251,8 +251,8 @@ find_bit:
 	*data = cpu_to_be32(tmp & ~mask);
 
 	/* fix checksum */
-	tmp = be32_to_cpu(*(u32 *)bh->b_data);
-	*(u32 *)bh->b_data = cpu_to_be32(tmp + mask);
+	tmp = be32_to_cpu(*(__be32 *)bh->b_data);
+	*(__be32 *)bh->b_data = cpu_to_be32(tmp + mask);
 
 	mark_buffer_dirty(bh);
 	sb->s_dirt = 1;
@@ -276,7 +276,7 @@ int affs_init_bitmap(struct super_block *sb, int *flags)
 {
 	struct affs_bm_info *bm;
 	struct buffer_head *bmap_bh = NULL, *bh = NULL;
-	u32 *bmap_blk;
+	__be32 *bmap_blk;
 	u32 size, blk, end, offset, mask;
 	int i, res = 0;
 	struct affs_sb_info *sbi = AFFS_SB(sb);
@@ -304,7 +304,7 @@ int affs_init_bitmap(struct super_block *sb, int *flags)
 	}
 	memset(sbi->s_bitmap, 0, size);
 
-	bmap_blk = (u32 *)sbi->s_root_bh->b_data;
+	bmap_blk = (__be32 *)sbi->s_root_bh->b_data;
 	blk = sb->s_blocksize / 4 - 49;
 	end = blk + 25;
 
@@ -340,7 +340,7 @@ int affs_init_bitmap(struct super_block *sb, int *flags)
 			res = -EIO;
 			goto out;
 		}
-		bmap_blk = (u32 *)bmap_bh->b_data;
+		bmap_blk = (__be32 *)bmap_bh->b_data;
 		blk = 0;
 		end = sb->s_blocksize / 4 - 1;
 	}
@@ -354,23 +354,23 @@ int affs_init_bitmap(struct super_block *sb, int *flags)
 		u32 old, new;
 
 		/* Mark unused bits in the last word as allocated */
-		old = be32_to_cpu(((u32 *)bh->b_data)[offset]);
+		old = be32_to_cpu(((__be32 *)bh->b_data)[offset]);
 		new = old & mask;
 		//if (old != new) {
-			((u32 *)bh->b_data)[offset] = cpu_to_be32(new);
+			((__be32 *)bh->b_data)[offset] = cpu_to_be32(new);
 			/* fix checksum */
 			//new -= old;
-			//old = be32_to_cpu(*(u32 *)bh->b_data);
-			//*(u32 *)bh->b_data = cpu_to_be32(old - new);
+			//old = be32_to_cpu(*(__be32 *)bh->b_data);
+			//*(__be32 *)bh->b_data = cpu_to_be32(old - new);
 			//mark_buffer_dirty(bh);
 		//}
 		/* correct offset for the bitmap count below */
 		//offset++;
 	}
 	while (++offset < sb->s_blocksize / 4)
-		((u32 *)bh->b_data)[offset] = 0;
-	((u32 *)bh->b_data)[0] = 0;
-	((u32 *)bh->b_data)[0] = cpu_to_be32(-affs_checksum_block(sb, bh));
+		((__be32 *)bh->b_data)[offset] = 0;
+	((__be32 *)bh->b_data)[0] = 0;
+	((__be32 *)bh->b_data)[0] = cpu_to_be32(-affs_checksum_block(sb, bh));
 	mark_buffer_dirty(bh);
 
 	/* recalculate bitmap count for last block */
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index f94afc028..3142f402e 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -181,7 +181,7 @@ bad_inode:
 	return;
 }
 
-void
+int
 affs_write_inode(struct inode *inode, int unused)
 {
 	struct super_block	*sb = inode->i_sb;
@@ -194,14 +194,14 @@ affs_write_inode(struct inode *inode, int unused)
 
 	if (!inode->i_nlink)
 		// possibly free block
-		return;
+		return 0;
 	bh = affs_bread(sb, inode->i_ino);
 	if (!bh) {
 		affs_error(sb,"write_inode","Cannot read block %lu",inode->i_ino);
-		return;
+		return -EIO;
 	}
 	tail = AFFS_TAIL(sb, bh);
-	if (tail->stype == be32_to_cpu(ST_ROOT)) {
+	if (tail->stype == cpu_to_be32(ST_ROOT)) {
 		secs_to_datestamp(inode->i_mtime.tv_sec,&AFFS_ROOT_TAIL(sb, bh)->root_change);
 	} else {
 		tail->protect = cpu_to_be32(AFFS_I(inode)->i_protect);
@@ -226,6 +226,7 @@ affs_write_inode(struct inode *inode, int unused)
 	mark_buffer_dirty_inode(bh, inode);
 	affs_brelse(bh);
 	affs_free_prealloc(inode);
+	return 0;
 }
 
 int
@@ -396,7 +397,7 @@ affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s3
 	AFFS_TAIL(sb, bh)->parent = cpu_to_be32(dir->i_ino);
 
 	if (inode_bh) {
-		u32 chain;
+		__be32 chain;
 	       	chain = AFFS_TAIL(sb, inode_bh)->link_chain;
 		AFFS_TAIL(sb, bh)->original = cpu_to_be32(inode->i_ino);
 		AFFS_TAIL(sb, bh)->link_chain = chain;
diff --git a/fs/affs/namei.c b/fs/affs/namei.c
index f2cbba3b7..d11f39c90 100644
--- a/fs/affs/namei.c
+++ b/fs/affs/namei.c
@@ -37,7 +37,7 @@ struct dentry_operations affs_dentry_operations = {
 	.d_compare	= affs_compare_dentry,
 };
 
-struct dentry_operations affs_intl_dentry_operations = {
+static struct dentry_operations affs_intl_dentry_operations = {
 	.d_hash		= affs_intl_hash_dentry,
 	.d_compare	= affs_intl_compare_dentry,
 };
diff --git a/fs/affs/super.c b/fs/affs/super.c
index f4ebbd27e..073e80cbe 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -44,7 +44,7 @@ affs_put_super(struct super_block *sb)
 	pr_debug("AFFS: put_super()\n");
 
 	if (!(sb->s_flags & MS_RDONLY)) {
-		AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->bm_flag = be32_to_cpu(1);
+		AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->bm_flag = cpu_to_be32(1);
 		secs_to_datestamp(get_seconds(),
 				  &AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->disk_change);
 		affs_fix_checksum(sb, sbi->s_root_bh);
@@ -70,7 +70,7 @@ affs_write_super(struct super_block *sb)
 		//	if (sbi->s_bitmap[i].bm_bh) {
 		//		if (buffer_dirty(sbi->s_bitmap[i].bm_bh)) {
 		//			clean = 0;
-		AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->bm_flag = be32_to_cpu(clean);
+		AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->bm_flag = cpu_to_be32(clean);
 		secs_to_datestamp(get_seconds(),
 				  &AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->disk_change);
 		affs_fix_checksum(sb, sbi->s_root_bh);
@@ -115,7 +115,7 @@ static int init_inodecache(void)
 {
 	affs_inode_cachep = kmem_cache_create("affs_inode_cache",
 					     sizeof(struct affs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (affs_inode_cachep == NULL)
 		return -ENOMEM;
@@ -387,7 +387,7 @@ got_root:
 		printk(KERN_ERR "AFFS: Cannot read boot block\n");
 		goto out_error;
 	}
-	chksum = be32_to_cpu(*(u32 *)boot_bh->b_data);
+	chksum = be32_to_cpu(*(__be32 *)boot_bh->b_data);
 	brelse(boot_bh);
 
 	/* Dircache filesystems are compatible with non-dircache ones
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c
index 1f968366e..72443ef17 100644
--- a/fs/afs/cmservice.c
+++ b/fs/afs/cmservice.c
@@ -424,7 +424,7 @@ static void _SRXAFSCM_CallBack(struct rxrpc_call *call)
 		{
 			struct afs_callback *cb, *pcb;
 			int loop;
-			u32 *fp, *bp;
+			__be32 *fp, *bp;
 
 			fp = rxrpc_call_alloc_scratch(call, qty);
 
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 7fcdd24dc..6682d6d7f 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -65,9 +65,9 @@ union afs_dirent {
 	struct {
 		uint8_t		valid;
 		uint8_t		unused[1];
-		uint16_t	hash_next;
-		uint32_t	vnode;
-		uint32_t	unique;
+		__be16		hash_next;
+		__be32		vnode;
+		__be32		unique;
 		uint8_t		name[16];
 		uint8_t		overflow[4];	/* if any char of the name (inc
 						 * NUL) reaches here, consume
@@ -78,8 +78,8 @@ union afs_dirent {
 
 /* AFS directory page header (one at the beginning of every 2048-byte chunk) */
 struct afs_dir_pagehdr {
-	uint16_t	npages;
-	uint16_t	magic;
+	__be16		npages;
+	__be16		magic;
 #define AFS_DIR_MAGIC htons(1234)
 	uint8_t		nentries;
 	uint8_t		bitmap[8];
@@ -308,7 +308,7 @@ static int afs_dir_iterate_block(unsigned *fpos,
 			      blkoff + offset * sizeof(union afs_dirent),
 			      ntohl(dire->u.vnode),
 			      filldir == afs_dir_lookup_filldir ?
-			      dire->u.unique : DT_UNKNOWN);
+			      ntohl(dire->u.unique) : DT_UNKNOWN);
 		if (ret < 0) {
 			_leave(" = 0 [full]");
 			return 0;
@@ -416,7 +416,7 @@ static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen,
 	struct afs_dir_lookup_cookie *cookie = _cookie;
 
 	_enter("{%s,%Zu},%s,%u,,%lu,%u",
-	       cookie->name, cookie->nlen, name, nlen, ino, ntohl(dtype));
+	       cookie->name, cookie->nlen, name, nlen, ino, dtype);
 
 	if (cookie->nlen != nlen || memcmp(cookie->name, name, nlen) != 0) {
 		_leave(" = 0 [no]");
@@ -424,7 +424,7 @@ static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen,
 	}
 
 	cookie->fid.vnode = ino;
-	cookie->fid.unique = ntohl(dtype);
+	cookie->fid.unique = dtype;
 	cookie->found = 1;
 
 	_leave(" = -1 [found]");
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index e6377cea6..61bc37153 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -307,7 +307,7 @@ int afs_rxfs_fetch_file_status(struct afs_server *server,
 	struct kvec piov[1];
 	size_t sent;
 	int ret;
-	u32 *bp;
+	__be32 *bp;
 
 	DECLARE_WAITQUEUE(myself, current);
 
@@ -432,7 +432,7 @@ int afs_rxfs_fetch_file_data(struct afs_server *server,
 	struct kvec piov[1];
 	size_t sent;
 	int ret;
-	u32 *bp;
+	__be32 *bp;
 
 	DECLARE_WAITQUEUE(myself, current);
 
@@ -583,7 +583,7 @@ int afs_rxfs_give_up_callback(struct afs_server *server,
 	struct kvec piov[1];
 	size_t sent;
 	int ret;
-	u32 *bp;
+	__be32 *bp;
 
 	DECLARE_WAITQUEUE(myself, current);
 
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index fc2c1a936..c476fde33 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -93,9 +93,10 @@ static int afs_inode_map_status(struct afs_vnode *vnode)
 
 /*****************************************************************************/
 /*
- * attempt to fetch the status of an inode, coelescing multiple simultaneous fetches
+ * attempt to fetch the status of an inode, coelescing multiple simultaneous
+ * fetches
  */
-int afs_inode_fetch_status(struct inode *inode)
+static int afs_inode_fetch_status(struct inode *inode)
 {
 	struct afs_vnode *vnode;
 	int ret;
diff --git a/fs/afs/main.c b/fs/afs/main.c
index c567afd54..955dbef62 100644
--- a/fs/afs/main.c
+++ b/fs/afs/main.c
@@ -10,6 +10,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/completion.h>
@@ -47,7 +48,7 @@ MODULE_LICENSE("GPL");
 
 static char *rootcell;
 
-MODULE_PARM(rootcell, "s");
+module_param(rootcell, charp, 0);
 MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list");
 
 
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index 8b5c1e2e5..bfc28abe1 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -235,8 +235,8 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt)
  */
 static int afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-	struct nameidata newnd;
 	struct vfsmount *newmnt;
+	struct dentry *old_dentry;
 	int err;
 
 	kenter("%p{%s},{%s:%p{%s}}",
@@ -247,15 +247,19 @@ static int afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd)
 	       nd->dentry->d_name.name);
 
 	newmnt = afs_mntpt_do_automount(dentry);
-	if (IS_ERR(newmnt))
+	if (IS_ERR(newmnt)) {
+		path_release(nd);
 		return PTR_ERR(newmnt);
+	}
 
-	newnd = *nd;
-	newnd.dentry = dentry;
-	err = do_add_mount(newmnt, &newnd, 0, &afs_vfsmounts);
+	old_dentry = nd->dentry;
+	nd->dentry = dentry;
+	err = do_add_mount(newmnt, nd, 0, &afs_vfsmounts);
+	nd->dentry = old_dentry;
+
+	path_release(nd);
 
 	if (!err) {
-		path_release(nd);
 		mntget(newmnt);
 		nd->mnt = newmnt;
 		dget(newmnt->mnt_root);
diff --git a/fs/afs/vlclient.c b/fs/afs/vlclient.c
index 6a663cedd..7b0e3192e 100644
--- a/fs/afs/vlclient.c
+++ b/fs/afs/vlclient.c
@@ -89,18 +89,19 @@ static void afs_rxvl_aemap(struct rxrpc_call *call)
 	}
 } /* end afs_rxvl_aemap() */
 
+#if 0
 /*****************************************************************************/
 /*
- * probe a volume location server to see if it is still alive
+ * probe a volume location server to see if it is still alive -- unused
  */
-int afs_rxvl_probe(struct afs_server *server, int alloc_flags)
+static int afs_rxvl_probe(struct afs_server *server, int alloc_flags)
 {
 	struct rxrpc_connection *conn;
 	struct rxrpc_call *call;
 	struct kvec piov[1];
 	size_t sent;
 	int ret;
-	u32 param[1];
+	__be32 param[1];
 
 	DECLARE_WAITQUEUE(myself, current);
 
@@ -173,6 +174,7 @@ int afs_rxvl_probe(struct afs_server *server, int alloc_flags)
 	return ret;
 
 } /* end afs_rxvl_probe() */
+#endif
 
 /*****************************************************************************/
 /*
@@ -191,7 +193,7 @@ int afs_rxvl_get_entry_by_name(struct afs_server *server,
 	unsigned tmp;
 	size_t sent;
 	int ret, loop;
-	u32 *bp, param[2], zero;
+	__be32 *bp, param[2], zero;
 
 	_enter(",%*.*s,%u,", volnamesz, volnamesz, volname, volnamesz);
 
@@ -326,7 +328,7 @@ int afs_rxvl_get_entry_by_id(struct afs_server *server,
 	unsigned tmp;
 	size_t sent;
 	int ret, loop;
-	u32 *bp, param[3];
+	__be32 *bp, param[3];
 
 	_enter(",%x,%d,", volid, voltype);
 
@@ -462,7 +464,7 @@ int afs_rxvl_get_entry_by_id_async(struct afs_async_op *op,
 	struct kvec piov[1];
 	size_t sent;
 	int ret;
-	u32 param[3];
+	__be32 param[3];
 
 	_enter(",%x,%d,", volid, voltype);
 
@@ -545,7 +547,8 @@ int afs_rxvl_get_entry_by_id_async(struct afs_async_op *op,
 int afs_rxvl_get_entry_by_id_async2(struct afs_async_op *op,
 				    struct afs_cache_vlocation *entry)
 {
-	unsigned *bp, tmp;
+	__be32 *bp;
+	__u32 tmp;
 	int loop, ret;
 
 	_enter("{op=%p cst=%u}", op, op->call->app_call_state);
diff --git a/fs/afs/vlclient.h b/fs/afs/vlclient.h
index 65b0b6e52..e3d601179 100644
--- a/fs/afs/vlclient.h
+++ b/fs/afs/vlclient.h
@@ -71,9 +71,6 @@ struct afs_vldbentry {
 
 };
 
-/* probe a volume location server to see if it is still alive */
-extern int afs_rxvl_probe(struct afs_server *server, int alloc_flags);
-
 /* look up a volume location database entry by name */
 extern int afs_rxvl_get_entry_by_name(struct afs_server *server,
 				      const char *volname,
diff --git a/fs/afs/vlocation.c b/fs/afs/vlocation.c
index c7396ca08..5d650422e 100644
--- a/fs/afs/vlocation.c
+++ b/fs/afs/vlocation.c
@@ -29,6 +29,7 @@
 static void afs_vlocation_update_timer(struct afs_timer *timer);
 static void afs_vlocation_update_attend(struct afs_async_op *op);
 static void afs_vlocation_update_discard(struct afs_async_op *op);
+static void __afs_put_vlocation(struct afs_vlocation *vlocation);
 
 static void __afs_vlocation_timeout(struct afs_timer *timer)
 {
@@ -455,7 +456,7 @@ int afs_vlocation_lookup(struct afs_cell *cell,
  * finish using a volume location record
  * - caller must have cell->vol_sem write-locked
  */
-void __afs_put_vlocation(struct afs_vlocation *vlocation)
+static void __afs_put_vlocation(struct afs_vlocation *vlocation)
 {
 	struct afs_cell *cell;
 
diff --git a/fs/afs/vnode.c b/fs/afs/vnode.c
index e3e9611cb..9867fef32 100644
--- a/fs/afs/vnode.c
+++ b/fs/afs/vnode.c
@@ -86,9 +86,9 @@ static void afs_vnode_cb_timed_out(struct afs_timer *timer)
  * - starts callback expiry timer
  * - adds to server's callback list
  */
-void afs_vnode_finalise_status_update(struct afs_vnode *vnode,
-				      struct afs_server *server,
-				      int ret)
+static void afs_vnode_finalise_status_update(struct afs_vnode *vnode,
+					     struct afs_server *server,
+					     int ret)
 {
 	struct afs_server *oldserver = NULL;
 
diff --git a/fs/afs/volume.h b/fs/afs/volume.h
index bbe463464..1e691889c 100644
--- a/fs/afs/volume.h
+++ b/fs/afs/volume.h
@@ -99,7 +99,6 @@ extern int afs_vlocation_lookup(struct afs_cell *cell,
 
 #define afs_get_vlocation(V) do { atomic_inc(&(V)->usage); } while(0)
 
-extern void __afs_put_vlocation(struct afs_vlocation *vlocation);
 extern void afs_put_vlocation(struct afs_vlocation *vlocation);
 extern void afs_vlocation_do_timeout(struct afs_vlocation *vlocation);
 
diff --git a/fs/aio.c b/fs/aio.c
index 9e7b5928e..0cd2c6a10 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -39,6 +39,9 @@
 #define dprintk(x...)	do { ; } while (0)
 #endif
 
+long aio_run = 0; /* for testing only */
+long aio_wakeups = 0; /* for testing only */
+
 /*------ sysctl variables----*/
 atomic_t aio_nr = ATOMIC_INIT(0);	/* current system wide number of aio requests */
 unsigned aio_max_nr = 0x10000;	/* system wide maximum number of aio requests */
@@ -277,6 +280,7 @@ static void aio_cancel_all(struct kioctx *ctx)
 		struct kiocb *iocb = list_kiocb(pos);
 		list_del_init(&iocb->ki_list);
 		cancel = iocb->ki_cancel;
+		kiocbSetCancelled(iocb);
 		if (cancel) {
 			iocb->ki_users++;
 			spin_unlock_irq(&ctx->ctx_lock);
@@ -337,6 +341,11 @@ void fastcall exit_aio(struct mm_struct *mm)
 		aio_cancel_all(ctx);
 
 		wait_for_all_aios(ctx);
+		/*
+		 * this is an overkill, but ensures we don't leave
+		 * the ctx on the aio_wq
+		 */
+		flush_workqueue(aio_wq);
 
 		if (1 != atomic_read(&ctx->users))
 			printk(KERN_DEBUG
@@ -359,6 +368,8 @@ void fastcall __put_ioctx(struct kioctx *ctx)
 	if (unlikely(ctx->reqs_active))
 		BUG();
 
+	cancel_delayed_work(&ctx->wq);
+	flush_workqueue(aio_wq);
 	aio_free_ring(ctx);
 	mmdrop(ctx->mm);
 	ctx->mm = NULL;
@@ -398,6 +409,7 @@ static struct kiocb fastcall *__aio_get_req(struct kioctx *ctx)
 	req->ki_obj.user = NULL;
 	req->ki_dtor = NULL;
 	req->private = NULL;
+	INIT_LIST_HEAD(&req->ki_run_list);
 
 	/* Check if the completion queue has enough free space to
 	 * accept an event from this io.
@@ -543,85 +555,367 @@ struct kioctx *lookup_ioctx(unsigned long ctx_id)
 	return ioctx;
 }
 
+/*
+ * use_mm
+ *	Makes the calling kernel thread take on the specified
+ *	mm context.
+ *	Called by the retry thread execute retries within the
+ *	iocb issuer's mm context, so that copy_from/to_user
+ *	operations work seamlessly for aio.
+ *	(Note: this routine is intended to be called only
+ *	from a kernel thread context)
+ */
 static void use_mm(struct mm_struct *mm)
 {
 	struct mm_struct *active_mm;
+	struct task_struct *tsk = current;
 
+	task_lock(tsk);
+	active_mm = tsk->active_mm;
 	atomic_inc(&mm->mm_count);
-	task_lock(current);
-	active_mm = current->active_mm;
-	current->mm = mm;
-	if (mm != active_mm) {
-		current->active_mm = mm;
-		activate_mm(active_mm, mm);
-	}
-	task_unlock(current);
+	tsk->mm = mm;
+	tsk->active_mm = mm;
+	activate_mm(active_mm, mm);
+	task_unlock(tsk);
+
 	mmdrop(active_mm);
 }
 
-static void unuse_mm(struct mm_struct *mm)
+/*
+ * unuse_mm
+ *	Reverses the effect of use_mm, i.e. releases the
+ *	specified mm context which was earlier taken on
+ *	by the calling kernel thread
+ *	(Note: this routine is intended to be called only
+ *	from a kernel thread context)
+ *
+ * Comments: Called with ctx->ctx_lock held. This nests
+ * task_lock instead ctx_lock.
+ */
+void unuse_mm(struct mm_struct *mm)
 {
-	task_lock(current);
-	current->mm = NULL;
-	task_unlock(current);
+	struct task_struct *tsk = current;
+
+	task_lock(tsk);
+	tsk->mm = NULL;
 	/* active_mm is still 'mm' */
-	enter_lazy_tlb(mm, current);
+	enter_lazy_tlb(mm, tsk);
+	task_unlock(tsk);
 }
 
-/* Run on kevent's context.  FIXME: needs to be per-cpu and warn if an
- * operation blocks.
+/*
+ * Queue up a kiocb to be retried. Assumes that the kiocb
+ * has already been marked as kicked, and places it on
+ * the retry run list for the corresponding ioctx, if it
+ * isn't already queued. Returns 1 if it actually queued
+ * the kiocb (to tell the caller to activate the work
+ * queue to process it), or 0, if it found that it was
+ * already queued.
+ *
+ * Should be called with the spin lock iocb->ki_ctx->ctx_lock
+ * held
  */
-static void aio_kick_handler(void *data)
+static inline int __queue_kicked_iocb(struct kiocb *iocb)
 {
-	struct kioctx *ctx = data;
+	struct kioctx *ctx = iocb->ki_ctx;
 
-	use_mm(ctx->mm);
+	if (list_empty(&iocb->ki_run_list)) {
+		list_add_tail(&iocb->ki_run_list,
+			&ctx->run_list);
+		iocb->ki_queued++;
+		return 1;
+	}
+	return 0;
+}
 
-	spin_lock_irq(&ctx->ctx_lock);
-	while (!list_empty(&ctx->run_list)) {
-		struct kiocb *iocb;
-		long ret;
+/* aio_run_iocb
+ *	This is the core aio execution routine. It is
+ *	invoked both for initial i/o submission and
+ *	subsequent retries via the aio_kick_handler.
+ *	Expects to be invoked with iocb->ki_ctx->lock
+ *	already held. The lock is released and reaquired
+ *	as needed during processing.
+ *
+ * Calls the iocb retry method (already setup for the
+ * iocb on initial submission) for operation specific
+ * handling, but takes care of most of common retry
+ * execution details for a given iocb. The retry method
+ * needs to be non-blocking as far as possible, to avoid
+ * holding up other iocbs waiting to be serviced by the
+ * retry kernel thread.
+ *
+ * The trickier parts in this code have to do with
+ * ensuring that only one retry instance is in progress
+ * for a given iocb at any time. Providing that guarantee
+ * simplifies the coding of individual aio operations as
+ * it avoids various potential races.
+ */
+static ssize_t aio_run_iocb(struct kiocb *iocb)
+{
+	struct kioctx	*ctx = iocb->ki_ctx;
+	ssize_t (*retry)(struct kiocb *);
+	ssize_t ret;
 
-		iocb = list_entry(ctx->run_list.next, struct kiocb,
-				  ki_run_list);
-		list_del(&iocb->ki_run_list);
-		iocb->ki_users ++;
-		spin_unlock_irq(&ctx->ctx_lock);
+	if (iocb->ki_retried++ > 1024*1024) {
+		printk("Maximal retry count.  Bytes done %Zd\n",
+			iocb->ki_nbytes - iocb->ki_left);
+		return -EAGAIN;
+	}
 
-		kiocbClearKicked(iocb);
-		ret = iocb->ki_retry(iocb);
-		if (-EIOCBQUEUED != ret) {
+	if (!(iocb->ki_retried & 0xff)) {
+		pr_debug("%ld retry: %d of %d (kick %ld, Q %ld run %ld, wake %ld)\n",
+			iocb->ki_retried,
+			iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes,
+			iocb->ki_kicked, iocb->ki_queued, aio_run, aio_wakeups);
+	}
+
+	if (!(retry = iocb->ki_retry)) {
+		printk("aio_run_iocb: iocb->ki_retry = NULL\n");
+		return 0;
+	}
+
+	/*
+	 * We don't want the next retry iteration for this
+	 * operation to start until this one has returned and
+	 * updated the iocb state. However, wait_queue functions
+	 * can trigger a kick_iocb from interrupt context in the
+	 * meantime, indicating that data is available for the next
+	 * iteration. We want to remember that and enable the
+	 * next retry iteration _after_ we are through with
+	 * this one.
+	 *
+	 * So, in order to be able to register a "kick", but
+	 * prevent it from being queued now, we clear the kick
+	 * flag, but make the kick code *think* that the iocb is
+	 * still on the run list until we are actually done.
+	 * When we are done with this iteration, we check if
+	 * the iocb was kicked in the meantime and if so, queue
+	 * it up afresh.
+	 */
+
+	kiocbClearKicked(iocb);
+
+	/*
+	 * This is so that aio_complete knows it doesn't need to
+	 * pull the iocb off the run list (We can't just call
+	 * INIT_LIST_HEAD because we don't want a kick_iocb to
+	 * queue this on the run list yet)
+	 */
+	iocb->ki_run_list.next = iocb->ki_run_list.prev = NULL;
+	spin_unlock_irq(&ctx->ctx_lock);
+
+	/* Quit retrying if the i/o has been cancelled */
+	if (kiocbIsCancelled(iocb)) {
+		ret = -EINTR;
+		aio_complete(iocb, ret, 0);
+		/* must not access the iocb after this */
+		goto out;
+	}
+
+	/*
+	 * Now we are all set to call the retry method in async
+	 * context. By setting this thread's io_wait context
+	 * to point to the wait queue entry inside the currently
+	 * running iocb for the duration of the retry, we ensure
+	 * that async notification wakeups are queued by the
+	 * operation instead of blocking waits, and when notified,
+	 * cause the iocb to be kicked for continuation (through
+	 * the aio_wake_function callback).
+	 */
+	BUG_ON(current->io_wait != NULL);
+	current->io_wait = &iocb->ki_wait;
+	ret = retry(iocb);
+	current->io_wait = NULL;
+
+	if (-EIOCBRETRY != ret) {
+ 		if (-EIOCBQUEUED != ret) {
+			BUG_ON(!list_empty(&iocb->ki_wait.task_list));
 			aio_complete(iocb, ret, 0);
-			iocb = NULL;
+			/* must not access the iocb after this */
 		}
+	} else {
+		/*
+		 * Issue an additional retry to avoid waiting forever if
+		 * no waits were queued (e.g. in case of a short read).
+		 */
+		if (list_empty(&iocb->ki_wait.task_list))
+			kiocbSetKicked(iocb);
+	}
+out:
+	spin_lock_irq(&ctx->ctx_lock);
 
-		spin_lock_irq(&ctx->ctx_lock);
-		if (NULL != iocb)
-			__aio_put_req(ctx, iocb);
+	if (-EIOCBRETRY == ret) {
+		/*
+		 * OK, now that we are done with this iteration
+		 * and know that there is more left to go,
+		 * this is where we let go so that a subsequent
+		 * "kick" can start the next iteration
+		 */
+
+		/* will make __queue_kicked_iocb succeed from here on */
+		INIT_LIST_HEAD(&iocb->ki_run_list);
+		/* we must queue the next iteration ourselves, if it
+		 * has already been kicked */
+		if (kiocbIsKicked(iocb)) {
+			__queue_kicked_iocb(iocb);
+		}
 	}
+	return ret;
+}
+
+/*
+ * __aio_run_iocbs:
+ * 	Process all pending retries queued on the ioctx
+ * 	run list.
+ * Assumes it is operating within the aio issuer's mm
+ * context. Expects to be called with ctx->ctx_lock held
+ */
+static int __aio_run_iocbs(struct kioctx *ctx)
+{
+	struct kiocb *iocb;
+	int count = 0;
+	LIST_HEAD(run_list);
+
+	list_splice_init(&ctx->run_list, &run_list);
+	while (!list_empty(&run_list)) {
+		iocb = list_entry(run_list.next, struct kiocb,
+			ki_run_list);
+		list_del(&iocb->ki_run_list);
+		/*
+		 * Hold an extra reference while retrying i/o.
+		 */
+		iocb->ki_users++;       /* grab extra reference */
+		aio_run_iocb(iocb);
+		if (__aio_put_req(ctx, iocb))  /* drop extra ref */
+			put_ioctx(ctx);
+		count++;
+ 	}
+	aio_run++;
+	if (!list_empty(&ctx->run_list))
+		return 1;
+	return 0;
+}
+
+static void aio_queue_work(struct kioctx * ctx)
+{
+	unsigned long timeout;
+	/*
+	 * if someone is waiting, get the work started right
+	 * away, otherwise, use a longer delay
+	 */
+	smp_mb();
+	if (waitqueue_active(&ctx->wait))
+		timeout = 1;
+	else
+		timeout = HZ/10;
+	queue_delayed_work(aio_wq, &ctx->wq, timeout);
+}
+
+
+/*
+ * aio_run_iocbs:
+ * 	Process all pending retries queued on the ioctx
+ * 	run list.
+ * Assumes it is operating within the aio issuer's mm
+ * context.
+ */
+static inline void aio_run_iocbs(struct kioctx *ctx)
+{
+	int requeue;
+
+	spin_lock_irq(&ctx->ctx_lock);
+
+	requeue = __aio_run_iocbs(ctx);
 	spin_unlock_irq(&ctx->ctx_lock);
+	if (requeue)
+		aio_queue_work(ctx);
+}
 
-	unuse_mm(ctx->mm);
+/*
+ * just like aio_run_iocbs, but keeps running them until
+ * the list stays empty
+ */
+static inline void aio_run_all_iocbs(struct kioctx *ctx)
+{
+	spin_lock_irq(&ctx->ctx_lock);
+	while (__aio_run_iocbs(ctx))
+		;
+	spin_unlock_irq(&ctx->ctx_lock);
 }
 
-void fastcall kick_iocb(struct kiocb *iocb)
+/*
+ * aio_kick_handler:
+ * 	Work queue handler triggered to process pending
+ * 	retries on an ioctx. Takes on the aio issuer's
+ *	mm context before running the iocbs, so that
+ *	copy_xxx_user operates on the issuer's address
+ *      space.
+ * Run on aiod's context.
+ */
+static void aio_kick_handler(void *data)
 {
-	struct kioctx	*ctx = iocb->ki_ctx;
+	struct kioctx *ctx = data;
+	mm_segment_t oldfs = get_fs();
+	int requeue;
 
+	set_fs(USER_DS);
+	use_mm(ctx->mm);
+	spin_lock_irq(&ctx->ctx_lock);
+	requeue =__aio_run_iocbs(ctx);
+ 	unuse_mm(ctx->mm);
+	spin_unlock_irq(&ctx->ctx_lock);
+	set_fs(oldfs);
+	/*
+	 * we're in a worker thread already, don't use queue_delayed_work,
+	 */
+	if (requeue)
+		queue_work(aio_wq, &ctx->wq);
+}
+
+
+/*
+ * Called by kick_iocb to queue the kiocb for retry
+ * and if required activate the aio work queue to process
+ * it
+ */
+void queue_kicked_iocb(struct kiocb *iocb)
+{
+ 	struct kioctx	*ctx = iocb->ki_ctx;
+	unsigned long flags;
+	int run = 0;
+
+	WARN_ON((!list_empty(&iocb->ki_wait.task_list)));
+
+	spin_lock_irqsave(&ctx->ctx_lock, flags);
+	run = __queue_kicked_iocb(iocb);
+	spin_unlock_irqrestore(&ctx->ctx_lock, flags);
+	if (run) {
+		aio_queue_work(ctx);
+		aio_wakeups++;
+	}
+}
+
+/*
+ * kick_iocb:
+ *      Called typically from a wait queue callback context
+ *      (aio_wake_function) to trigger a retry of the iocb.
+ *      The retry is usually executed by aio workqueue
+ *      threads (See aio_kick_handler).
+ */
+void fastcall kick_iocb(struct kiocb *iocb)
+{
 	/* sync iocbs are easy: they can only ever be executing from a 
 	 * single context. */
 	if (is_sync_kiocb(iocb)) {
 		kiocbSetKicked(iocb);
-		wake_up_process(iocb->ki_obj.tsk);
+	        wake_up_process(iocb->ki_obj.tsk);
 		return;
 	}
 
+	iocb->ki_kicked++;
+	/* If its already kicked we shouldn't queue it again */
 	if (!kiocbTryKick(iocb)) {
-		unsigned long flags;
-		spin_lock_irqsave(&ctx->ctx_lock, flags);
-		list_add_tail(&iocb->ki_run_list, &ctx->run_list);
-		spin_unlock_irqrestore(&ctx->ctx_lock, flags);
-		queue_work(aio_wq, &ctx->wq);
+		queue_kicked_iocb(iocb);
 	}
 }
 EXPORT_SYMBOL(kick_iocb);
@@ -675,6 +969,16 @@ int fastcall aio_complete(struct kiocb *iocb, long res, long res2)
 	 */
 	spin_lock_irqsave(&ctx->ctx_lock, flags);
 
+	if (iocb->ki_run_list.prev && !list_empty(&iocb->ki_run_list))
+		list_del_init(&iocb->ki_run_list);
+
+	/*
+	 * cancelled requests don't get events, userland was given one
+	 * when the event got cancelled.
+	 */
+	if (kiocbIsCancelled(iocb))
+		goto put_rq;
+
 	ring = kmap_atomic(info->ring_pages[0], KM_IRQ1);
 
 	tail = info->tail;
@@ -703,6 +1007,11 @@ int fastcall aio_complete(struct kiocb *iocb, long res, long res2)
 
 	pr_debug("added to ring %p at [%lu]\n", iocb, tail);
 
+	pr_debug("%ld retries: %d of %d (kicked %ld, Q %ld run %ld wake %ld)\n",
+		iocb->ki_retried,
+		iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes,
+		iocb->ki_kicked, iocb->ki_queued, aio_run, aio_wakeups);
+put_rq:
 	/* everything turned out well, dispose of the aiocb. */
 	ret = __aio_put_req(ctx, iocb);
 
@@ -759,7 +1068,7 @@ out:
 	return ret;
 }
 
-struct timeout {
+struct aio_timeout {
 	struct timer_list	timer;
 	int			timed_out;
 	struct task_struct	*p;
@@ -767,13 +1076,13 @@ struct timeout {
 
 static void timeout_func(unsigned long data)
 {
-	struct timeout *to = (struct timeout *)data;
+	struct aio_timeout *to = (struct aio_timeout *)data;
 
 	to->timed_out = 1;
 	wake_up_process(to->p);
 }
 
-static inline void init_timeout(struct timeout *to)
+static inline void init_timeout(struct aio_timeout *to)
 {
 	init_timer(&to->timer);
 	to->timer.data = (unsigned long)to;
@@ -782,7 +1091,7 @@ static inline void init_timeout(struct timeout *to)
 	to->p = current;
 }
 
-static inline void set_timeout(long start_jiffies, struct timeout *to,
+static inline void set_timeout(long start_jiffies, struct aio_timeout *to,
 			       const struct timespec *ts)
 {
 	to->timer.expires = start_jiffies + timespec_to_jiffies(ts);
@@ -792,7 +1101,7 @@ static inline void set_timeout(long start_jiffies, struct timeout *to,
 		to->timed_out = 1;
 }
 
-static inline void clear_timeout(struct timeout *to)
+static inline void clear_timeout(struct aio_timeout *to)
 {
 	del_singleshot_timer_sync(&to->timer);
 }
@@ -808,14 +1117,16 @@ static int read_events(struct kioctx *ctx,
 	int			ret;
 	int			i = 0;
 	struct io_event		ent;
-	struct timeout		to;
+	struct aio_timeout	to;
+	int 			event_loop = 0; /* testing only */
+	int			retry = 0;
 
 	/* needed to zero any padding within an entry (there shouldn't be 
 	 * any, but C is fun!
 	 */
 	memset(&ent, 0, sizeof(ent));
+retry:
 	ret = 0;
-
 	while (likely(i < nr)) {
 		ret = aio_read_evt(ctx, &ent);
 		if (unlikely(ret <= 0))
@@ -844,6 +1155,13 @@ static int read_events(struct kioctx *ctx,
 
 	/* End fast path */
 
+	/* racey check, but it gets redone */
+	if (!retry && unlikely(!list_empty(&ctx->run_list))) {
+		retry = 1;
+		aio_run_all_iocbs(ctx);
+		goto retry;
+	}
+
 	init_timeout(&to);
 	if (timeout) {
 		struct timespec	ts;
@@ -858,7 +1176,6 @@ static int read_events(struct kioctx *ctx,
 		add_wait_queue_exclusive(&ctx->wait, &wait);
 		do {
 			set_task_state(tsk, TASK_INTERRUPTIBLE);
-
 			ret = aio_read_evt(ctx, &ent);
 			if (ret)
 				break;
@@ -868,6 +1185,7 @@ static int read_events(struct kioctx *ctx,
 			if (to.timed_out)	/* Only check after read evt */
 				break;
 			schedule();
+			event_loop++;
 			if (signal_pending(tsk)) {
 				ret = -EINTR;
 				break;
@@ -895,6 +1213,9 @@ static int read_events(struct kioctx *ctx,
 	if (timeout)
 		clear_timeout(&to);
 out:
+	pr_debug("event loop executed %d times\n", event_loop);
+	pr_debug("aio_run %ld\n", aio_run);
+	pr_debug("aio_wakeups %ld\n", aio_wakeups);
 	return i ? i : ret;
 }
 
@@ -962,7 +1283,7 @@ asmlinkage long sys_io_setup(unsigned nr_events, aio_context_t __user *ctxp)
 		ret = put_user(ioctx->user_id, ctxp);
 		if (!ret)
 			return 0;
-	 	get_ioctx(ioctx);
+
 		io_destroy(ioctx);
 	}
 
@@ -987,13 +1308,181 @@ asmlinkage long sys_io_destroy(aio_context_t ctx)
 	return -EINVAL;
 }
 
+/*
+ * Default retry method for aio_read (also used for first time submit)
+ * Responsible for updating iocb state as retries progress
+ */
+static ssize_t aio_pread(struct kiocb *iocb)
+{
+	struct file *file = iocb->ki_filp;
+	struct address_space *mapping = file->f_mapping;
+	struct inode *inode = mapping->host;
+	ssize_t ret = 0;
+
+	ret = file->f_op->aio_read(iocb, iocb->ki_buf,
+		iocb->ki_left, iocb->ki_pos);
+
+	/*
+	 * Can't just depend on iocb->ki_left to determine
+	 * whether we are done. This may have been a short read.
+	 */
+	if (ret > 0) {
+		iocb->ki_buf += ret;
+		iocb->ki_left -= ret;
+		/*
+		 * For pipes and sockets we return once we have
+		 * some data; for regular files we retry till we
+		 * complete the entire read or find that we can't
+		 * read any more data (e.g short reads).
+		 */
+		if (!S_ISFIFO(inode->i_mode) && !S_ISSOCK(inode->i_mode))
+			ret = -EIOCBRETRY;
+	}
+
+	/* This means we must have transferred all that we could */
+	/* No need to retry anymore */
+	if ((ret == 0) || (iocb->ki_left == 0))
+		ret = iocb->ki_nbytes - iocb->ki_left;
+
+	return ret;
+}
+
+/*
+ * Default retry method for aio_write (also used for first time submit)
+ * Responsible for updating iocb state as retries progress
+ */
+static ssize_t aio_pwrite(struct kiocb *iocb)
+{
+	struct file *file = iocb->ki_filp;
+	ssize_t ret = 0;
+
+	ret = file->f_op->aio_write(iocb, iocb->ki_buf,
+		iocb->ki_left, iocb->ki_pos);
+
+	if (ret > 0) {
+		iocb->ki_buf += ret;
+		iocb->ki_left -= ret;
+
+		ret = -EIOCBRETRY;
+	}
+
+	/* This means we must have transferred all that we could */
+	/* No need to retry anymore */
+	if ((ret == 0) || (iocb->ki_left == 0))
+		ret = iocb->ki_nbytes - iocb->ki_left;
+
+	return ret;
+}
+
+static ssize_t aio_fdsync(struct kiocb *iocb)
+{
+	struct file *file = iocb->ki_filp;
+	ssize_t ret = -EINVAL;
+
+	if (file->f_op->aio_fsync)
+		ret = file->f_op->aio_fsync(iocb, 1);
+	return ret;
+}
+
+static ssize_t aio_fsync(struct kiocb *iocb)
+{
+	struct file *file = iocb->ki_filp;
+	ssize_t ret = -EINVAL;
+
+	if (file->f_op->aio_fsync)
+		ret = file->f_op->aio_fsync(iocb, 0);
+	return ret;
+}
+
+/*
+ * aio_setup_iocb:
+ *	Performs the initial checks and aio retry method
+ *	setup for the kiocb at the time of io submission.
+ */
+ssize_t aio_setup_iocb(struct kiocb *kiocb)
+{
+	struct file *file = kiocb->ki_filp;
+	ssize_t ret = 0;
+
+	switch (kiocb->ki_opcode) {
+	case IOCB_CMD_PREAD:
+		ret = -EBADF;
+		if (unlikely(!(file->f_mode & FMODE_READ)))
+			break;
+		ret = -EFAULT;
+		if (unlikely(!access_ok(VERIFY_WRITE, kiocb->ki_buf,
+			kiocb->ki_left)))
+			break;
+		ret = -EINVAL;
+		if (file->f_op->aio_read)
+			kiocb->ki_retry = aio_pread;
+		break;
+	case IOCB_CMD_PWRITE:
+		ret = -EBADF;
+		if (unlikely(!(file->f_mode & FMODE_WRITE)))
+			break;
+		ret = -EFAULT;
+		if (unlikely(!access_ok(VERIFY_READ, kiocb->ki_buf,
+			kiocb->ki_left)))
+			break;
+		ret = -EINVAL;
+		if (file->f_op->aio_write)
+			kiocb->ki_retry = aio_pwrite;
+		break;
+	case IOCB_CMD_FDSYNC:
+		ret = -EINVAL;
+		if (file->f_op->aio_fsync)
+			kiocb->ki_retry = aio_fdsync;
+		break;
+	case IOCB_CMD_FSYNC:
+		ret = -EINVAL;
+		if (file->f_op->aio_fsync)
+			kiocb->ki_retry = aio_fsync;
+		break;
+	default:
+		dprintk("EINVAL: io_submit: no operation provided\n");
+		ret = -EINVAL;
+	}
+
+	if (!kiocb->ki_retry)
+		return ret;
+
+	return 0;
+}
+
+/*
+ * aio_wake_function:
+ * 	wait queue callback function for aio notification,
+ * 	Simply triggers a retry of the operation via kick_iocb.
+ *
+ * 	This callback is specified in the wait queue entry in
+ *	a kiocb	(current->io_wait points to this wait queue
+ *	entry when an aio operation executes; it is used
+ * 	instead of a synchronous wait when an i/o blocking
+ *	condition is encountered during aio).
+ *
+ * Note:
+ * This routine is executed with the wait queue lock held.
+ * Since kick_iocb acquires iocb->ctx->ctx_lock, it nests
+ * the ioctx lock inside the wait queue lock. This is safe
+ * because this callback isn't used for wait queues which
+ * are nested inside ioctx lock (i.e. ctx->wait)
+ */
+int aio_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key)
+{
+	struct kiocb *iocb = container_of(wait, struct kiocb, ki_wait);
+
+	list_del_init(&wait->task_list);
+	kick_iocb(iocb);
+	return 1;
+}
+
 int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
 			 struct iocb *iocb)
 {
 	struct kiocb *req;
 	struct file *file;
 	ssize_t ret;
-	char __user *buf;
 
 	/* enforce forwards compatibility on users */
 	if (unlikely(iocb->aio_reserved1 || iocb->aio_reserved2 ||
@@ -1034,58 +1523,31 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
 	req->ki_user_data = iocb->aio_data;
 	req->ki_pos = iocb->aio_offset;
 
-	buf = (char __user *)(unsigned long)iocb->aio_buf;
+	req->ki_buf = (char __user *)(unsigned long)iocb->aio_buf;
+	req->ki_left = req->ki_nbytes = iocb->aio_nbytes;
+	req->ki_opcode = iocb->aio_lio_opcode;
+	init_waitqueue_func_entry(&req->ki_wait, aio_wake_function);
+	INIT_LIST_HEAD(&req->ki_wait.task_list);
+	req->ki_run_list.next = req->ki_run_list.prev = NULL;
+	req->ki_retry = NULL;
+	req->ki_retried = 0;
+	req->ki_kicked = 0;
+	req->ki_queued = 0;
+	aio_run = 0;
+	aio_wakeups = 0;
 
-	switch (iocb->aio_lio_opcode) {
-	case IOCB_CMD_PREAD:
-		ret = -EBADF;
-		if (unlikely(!(file->f_mode & FMODE_READ)))
-			goto out_put_req;
-		ret = -EFAULT;
-		if (unlikely(!access_ok(VERIFY_WRITE, buf, iocb->aio_nbytes)))
-			goto out_put_req;
-		ret = security_file_permission (file, MAY_READ);
-		if (ret)
-			goto out_put_req;
-		ret = -EINVAL;
-		if (file->f_op->aio_read)
-			ret = file->f_op->aio_read(req, buf,
-					iocb->aio_nbytes, req->ki_pos);
-		break;
-	case IOCB_CMD_PWRITE:
-		ret = -EBADF;
-		if (unlikely(!(file->f_mode & FMODE_WRITE)))
-			goto out_put_req;
-		ret = -EFAULT;
-		if (unlikely(!access_ok(VERIFY_READ, buf, iocb->aio_nbytes)))
-			goto out_put_req;
-		ret = security_file_permission (file, MAY_WRITE);
-		if (ret)
-			goto out_put_req;
-		ret = -EINVAL;
-		if (file->f_op->aio_write)
-			ret = file->f_op->aio_write(req, buf,
-					iocb->aio_nbytes, req->ki_pos);
-		break;
-	case IOCB_CMD_FDSYNC:
-		ret = -EINVAL;
-		if (file->f_op->aio_fsync)
-			ret = file->f_op->aio_fsync(req, 1);
-		break;
-	case IOCB_CMD_FSYNC:
-		ret = -EINVAL;
-		if (file->f_op->aio_fsync)
-			ret = file->f_op->aio_fsync(req, 0);
-		break;
-	default:
-		dprintk("EINVAL: io_submit: no operation provided\n");
-		ret = -EINVAL;
-	}
+	ret = aio_setup_iocb(req);
 
+	if (ret)
+		goto out_put_req;
+
+	spin_lock_irq(&ctx->ctx_lock);
+	list_add_tail(&req->ki_run_list, &ctx->run_list);
+	/* drain the run list */
+	while (__aio_run_iocbs(ctx))
+		;
+	spin_unlock_irq(&ctx->ctx_lock);
 	aio_put_req(req);	/* drop extra ref to req */
-	if (likely(-EIOCBQUEUED == ret))
-		return 0;
-	aio_complete(req, ret, 0);	/* will drop i/o ref to req */
 	return 0;
 
 out_put_req:
@@ -1201,6 +1663,7 @@ asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb,
 	if (kiocb && kiocb->ki_cancel) {
 		cancel = kiocb->ki_cancel;
 		kiocb->ki_users ++;
+		kiocbSetCancelled(kiocb);
 	} else
 		cancel = NULL;
 	spin_unlock_irq(&ctx->ctx_lock);
diff --git a/fs/attr.c b/fs/attr.c
index 89e03f7bb..5f78d75a8 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -81,7 +81,7 @@ int inode_change_ok(struct inode *inode, struct iattr *attr)
 			printk(KERN_WARNING
 				"VSW: xid=%d messing with the devpts.\n",
 				vx_current_xid());
-			goto error;	
+			goto error;
 	}
 fine:
 	retval = 0;
diff --git a/fs/autofs/root.c b/fs/autofs/root.c
index 563706176..a1ab1c0ed 100644
--- a/fs/autofs/root.c
+++ b/fs/autofs/root.c
@@ -238,9 +238,15 @@ static struct dentry *autofs_root_lookup(struct inode *dir, struct dentry *dentr
 	 * a signal. If so we can force a restart..
 	 */
 	if (dentry->d_flags & DCACHE_AUTOFS_PENDING) {
+		/* See if we were interrupted */
 		if (signal_pending(current)) {
-			unlock_kernel();
-			return ERR_PTR(-ERESTARTNOINTR);
+			sigset_t *sigset = &current->pending.signal;
+			if (sigismember (sigset, SIGKILL) ||
+			    sigismember (sigset, SIGQUIT) ||
+			    sigismember (sigset, SIGINT)) {
+				unlock_kernel();
+				return ERR_PTR(-ERESTARTNOINTR);
+			}
 		}
 	}
 	unlock_kernel();
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index 94a12aee2..f5a52c871 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -138,7 +138,6 @@ static inline void autofs4_copy_atime(struct file *src, struct file *dst)
 }
 
 struct inode *autofs4_get_inode(struct super_block *, struct autofs_info *);
-struct autofs_info *autofs4_init_inf(struct autofs_sb_info *, mode_t mode);
 void autofs4_free_ino(struct autofs_info *);
 
 /* Expiration */
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 5ebffa647..31540a640 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -146,10 +146,10 @@ resume:
 	return 1;
 }
 
-struct dentry *autofs4_check_leaves(struct vfsmount *mnt,
-				    struct dentry *parent,
-				    unsigned long timeout,
-				    int do_now)
+static struct dentry *autofs4_check_leaves(struct vfsmount *mnt,
+					   struct dentry *parent,
+					   unsigned long timeout,
+					   int do_now)
 {
 	struct dentry *this_parent = parent;
 	struct list_head *next;
diff --git a/fs/befs/befs.h b/fs/befs/befs.h
index fcb7f47b0..057a2c3d7 100644
--- a/fs/befs/befs.h
+++ b/fs/befs/befs.h
@@ -96,7 +96,6 @@ void befs_dump_super_block(const struct super_block *sb, befs_super_block *);
 void befs_dump_inode(const struct super_block *sb, befs_inode *);
 void befs_dump_index_entry(const struct super_block *sb, befs_btree_super *);
 void befs_dump_index_node(const struct super_block *sb, befs_btree_nodehead *);
-void befs_dump_inode_addr(const struct super_block *sb, befs_inode_addr);
 /****************************/
 
 
diff --git a/fs/befs/debug.c b/fs/befs/debug.c
index b5e190116..f1ad4e00f 100644
--- a/fs/befs/debug.c
+++ b/fs/befs/debug.c
@@ -222,11 +222,13 @@ befs_dump_super_block(const struct super_block *sb, befs_super_block * sup)
 #endif				//CONFIG_BEFS_DEBUG
 }
 
+/* unused */
 void
 befs_dump_small_data(const struct super_block *sb, befs_small_data * sd)
 {
 }
 
+/* unused */
 void
 befs_dump_run(const struct super_block *sb, befs_block_run run)
 {
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index 49cf3428d..de5bb280a 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -64,22 +64,22 @@ static const struct super_operations befs_sops = {
 /* slab cache for befs_inode_info objects */
 static kmem_cache_t *befs_inode_cachep;
 
-struct file_operations befs_dir_operations = {
+static struct file_operations befs_dir_operations = {
 	.read		= generic_read_dir,
 	.readdir	= befs_readdir,
 };
 
-struct inode_operations befs_dir_inode_operations = {
+static struct inode_operations befs_dir_inode_operations = {
 	.lookup		= befs_lookup,
 };
 
-struct file_operations befs_file_operations = {
+static struct file_operations befs_file_operations = {
 	.llseek		= default_llseek,
 	.read		= generic_file_read,
 	.mmap		= generic_file_readonly_mmap,
 };
 
-struct address_space_operations befs_aops = {
+static struct address_space_operations befs_aops = {
 	.readpage	= befs_readpage,
 	.sync_page	= block_sync_page,
 	.bmap		= befs_bmap,
@@ -433,7 +433,7 @@ befs_init_inodecache(void)
 {
 	befs_inode_cachep = kmem_cache_create("befs_inode_cache",
 					      sizeof (struct befs_inode_info),
-					      0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					      0, SLAB_RECLAIM_ACCOUNT,
 					      init_once, NULL);
 	if (befs_inode_cachep == NULL) {
 		printk(KERN_ERR "befs_init_inodecache: "
@@ -857,10 +857,14 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
 		befs_sb->nls = load_nls(befs_sb->mount_opts.iocharset);
 		if (!befs_sb->nls) {
 			befs_warning(sb, "Cannot load nls %s"
-				     "loding default nls",
-				     befs_sb->mount_opts.iocharset);
+					" loading default nls",
+					befs_sb->mount_opts.iocharset);
 			befs_sb->nls = load_nls_default();
 		}
+	/* load default nls if none is specified  in mount options */
+	} else {
+		befs_debug(sb, "Loading default nls");
+		befs_sb->nls = load_nls_default();
 	}
 
 	return 0;
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index 9ef5b3146..f01ebd700 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -85,7 +85,7 @@ static void bfs_read_inode(struct inode * inode)
 	brelse(bh);
 }
 
-static void bfs_write_inode(struct inode * inode, int unused)
+static int bfs_write_inode(struct inode * inode, int unused)
 {
 	unsigned long ino = inode->i_ino;
 	struct bfs_inode * di;
@@ -94,7 +94,7 @@ static void bfs_write_inode(struct inode * inode, int unused)
 
 	if (ino < BFS_ROOT_INO || ino > BFS_SB(inode->i_sb)->si_lasti) {
 		printf("Bad inode number %s:%08lx\n", inode->i_sb->s_id, ino);
-		return;
+		return -EIO;
 	}
 
 	lock_kernel();
@@ -103,7 +103,7 @@ static void bfs_write_inode(struct inode * inode, int unused)
 	if (!bh) {
 		printf("Unable to read inode %s:%08lx\n", inode->i_sb->s_id, ino);
 		unlock_kernel();
-		return;
+		return -EIO;
 	}
 
 	off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK;
@@ -129,6 +129,7 @@ static void bfs_write_inode(struct inode * inode, int unused)
 	mark_buffer_dirty(bh);
 	brelse(bh);
 	unlock_kernel();
+	return 0;
 }
 
 static void bfs_delete_inode(struct inode * inode)
@@ -245,7 +246,7 @@ static int init_inodecache(void)
 {
 	bfs_inode_cachep = kmem_cache_create("bfs_inode_cache",
 					     sizeof(struct bfs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (bfs_inode_cachep == NULL)
 		return -ENOMEM;
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index 85e855611..59d1feb40 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -308,7 +308,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 		(current->mm->start_data = N_DATADDR(ex));
 	current->mm->brk = ex.a_bss +
 		(current->mm->start_brk = N_BSSADDR(ex));
-	current->mm->free_area_cache = TASK_UNMAPPED_BASE;
+	current->mm->free_area_cache = current->mm->mmap_base;
 
 	// current->mm->rss = 0;
 	vx_rsspages_sub(current->mm, current->mm->rss);
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 785da46c8..cb0db6ef2 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -41,6 +41,7 @@
 
 #include <asm/uaccess.h>
 #include <asm/param.h>
+#include <asm/page.h>
 
 #include <linux/elf.h>
 
@@ -488,25 +489,33 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 	unsigned long elf_entry, interp_load_addr = 0;
 	unsigned long start_code, end_code, start_data, end_data;
 	unsigned long reloc_func_desc = 0;
-	struct elfhdr elf_ex;
-	struct elfhdr interp_elf_ex;
-  	struct exec interp_ex;
 	char passed_fileno[6];
 	struct files_struct *files;
 	int have_pt_gnu_stack, executable_stack = EXSTACK_DEFAULT;
 	unsigned long def_flags = 0;
+	struct {
+		struct elfhdr elf_ex;
+		struct elfhdr interp_elf_ex;
+  		struct exec interp_ex;
+	} *loc;
+
+	loc = kmalloc(sizeof(*loc), GFP_KERNEL);
+	if (!loc) {
+		retval = -ENOMEM;
+		goto out_ret;
+	}
 	
 	/* Get the exec-header */
-	elf_ex = *((struct elfhdr *) bprm->buf);
+	loc->elf_ex = *((struct elfhdr *) bprm->buf);
 
 	retval = -ENOEXEC;
 	/* First of all, some simple consistency checks */
-	if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
+	if (memcmp(loc->elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
 		goto out;
 
-	if (elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN)
+	if (loc->elf_ex.e_type != ET_EXEC && loc->elf_ex.e_type != ET_DYN)
 		goto out;
-	if (!elf_check_arch(&elf_ex))
+	if (!elf_check_arch(&loc->elf_ex))
 		goto out;
 	if (!bprm->file->f_op||!bprm->file->f_op->mmap)
 		goto out;
@@ -514,16 +523,16 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 	/* Now read in all of the header information */
 
 	retval = -ENOMEM;
-	if (elf_ex.e_phentsize != sizeof(struct elf_phdr))
+	if (loc->elf_ex.e_phentsize != sizeof(struct elf_phdr))
 		goto out;
-	if (elf_ex.e_phnum > 65536U / sizeof(struct elf_phdr))
+	if (loc->elf_ex.e_phnum > 65536U / sizeof(struct elf_phdr))
 		goto out;
-	size = elf_ex.e_phnum * sizeof(struct elf_phdr);
+	size = loc->elf_ex.e_phnum * sizeof(struct elf_phdr);
 	elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL);
 	if (!elf_phdata)
 		goto out;
 
-	retval = kernel_read(bprm->file, elf_ex.e_phoff, (char *) elf_phdata, size);
+	retval = kernel_read(bprm->file, loc->elf_ex.e_phoff, (char *) elf_phdata, size);
 	if (retval < 0)
 		goto out_free_ph;
 
@@ -554,7 +563,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 	start_data = 0;
 	end_data = 0;
 
-	for (i = 0; i < elf_ex.e_phnum; i++) {
+	for (i = 0; i < loc->elf_ex.e_phnum; i++) {
 		if (elf_ppnt->p_type == PT_INTERP) {
 			/* This is the program interpreter used for
 			 * shared libraries - for now assume that this
@@ -601,7 +610,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 			 * switch really is going to happen - do this in
 			 * flush_thread().	- akpm
 			 */
-			SET_PERSONALITY(elf_ex, ibcs2_interpreter);
+			SET_PERSONALITY(loc->elf_ex, ibcs2_interpreter);
 
 			interpreter = open_exec(elf_interpreter);
 			retval = PTR_ERR(interpreter);
@@ -612,15 +621,15 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 				goto out_free_dentry;
 
 			/* Get the exec headers */
-			interp_ex = *((struct exec *) bprm->buf);
-			interp_elf_ex = *((struct elfhdr *) bprm->buf);
+			loc->interp_ex = *((struct exec *) bprm->buf);
+			loc->interp_elf_ex = *((struct elfhdr *) bprm->buf);
 			break;
 		}
 		elf_ppnt++;
 	}
 
 	elf_ppnt = elf_phdata;
-	for (i = 0; i < elf_ex.e_phnum; i++, elf_ppnt++)
+	for (i = 0; i < loc->elf_ex.e_phnum; i++, elf_ppnt++)
 		if (elf_ppnt->p_type == PT_GNU_STACK) {
 			if (elf_ppnt->p_flags & PF_X)
 				executable_stack = EXSTACK_ENABLE_X;
@@ -628,19 +637,19 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 				executable_stack = EXSTACK_DISABLE_X;
 			break;
 		}
-	have_pt_gnu_stack = (i < elf_ex.e_phnum);
+	have_pt_gnu_stack = (i < loc->elf_ex.e_phnum);
 
 	/* Some simple consistency checks for the interpreter */
 	if (elf_interpreter) {
 		interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
 
 		/* Now figure out which format our binary is */
-		if ((N_MAGIC(interp_ex) != OMAGIC) &&
-		    (N_MAGIC(interp_ex) != ZMAGIC) &&
-		    (N_MAGIC(interp_ex) != QMAGIC))
+		if ((N_MAGIC(loc->interp_ex) != OMAGIC) &&
+		    (N_MAGIC(loc->interp_ex) != ZMAGIC) &&
+		    (N_MAGIC(loc->interp_ex) != QMAGIC))
 			interpreter_type = INTERPRETER_ELF;
 
-		if (memcmp(interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
+		if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
 			interpreter_type &= ~INTERPRETER_ELF;
 
 		retval = -ELIBBAD;
@@ -656,11 +665,11 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 		}
 		/* Verify the interpreter has a valid arch */
 		if ((interpreter_type == INTERPRETER_ELF) &&
-		    !elf_check_arch(&interp_elf_ex))
+		    !elf_check_arch(&loc->interp_elf_ex))
 			goto out_free_dentry;
 	} else {
 		/* Executables without an interpreter also need a personality  */
-		SET_PERSONALITY(elf_ex, ibcs2_interpreter);
+		SET_PERSONALITY(loc->elf_ex, ibcs2_interpreter);
 	}
 
 	/* OK, we are done with that, now set up the arg stuff,
@@ -700,15 +709,17 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 
 	/* Do this immediately, since STACK_TOP as used in setup_arg_pages
 	   may depend on the personality.  */
-	SET_PERSONALITY(elf_ex, ibcs2_interpreter);
-	if (elf_read_implies_exec(elf_ex, have_pt_gnu_stack))
+	SET_PERSONALITY(loc->elf_ex, ibcs2_interpreter);
+	if (elf_read_implies_exec(loc->elf_ex, have_pt_gnu_stack))
 		current->personality |= READ_IMPLIES_EXEC;
 
+	arch_pick_mmap_layout(current->mm);
+
 	/* Do this so that we can load the interpreter, if need be.  We will
 	   change some of these later */
 	// current->mm->rss = 0;
 	vx_rsspages_sub(current->mm, current->mm->rss);
-	current->mm->free_area_cache = TASK_UNMAPPED_BASE;
+	current->mm->free_area_cache = current->mm->mmap_base;
 	retval = setup_arg_pages(bprm, executable_stack);
 	if (retval < 0) {
 		send_sig(SIGKILL, current, 0);
@@ -722,7 +733,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 	   the image should be loaded at fixed address, not at a variable
 	   address. */
 
-	for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
+	for(i = 0, elf_ppnt = elf_phdata; i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
 		int elf_prot = 0, elf_flags;
 		unsigned long k, vaddr;
 
@@ -757,9 +768,9 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 		elf_flags = MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE;
 
 		vaddr = elf_ppnt->p_vaddr;
-		if (elf_ex.e_type == ET_EXEC || load_addr_set) {
+		if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) {
 			elf_flags |= MAP_FIXED;
-		} else if (elf_ex.e_type == ET_DYN) {
+		} else if (loc->elf_ex.e_type == ET_DYN) {
 			/* Try and get dynamic programs out of the way of the default mmap
 			   base, as well as whatever program they might try to exec.  This
 			   is because the brk will follow the loader, and is not movable.  */
@@ -773,7 +784,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 		if (!load_addr_set) {
 			load_addr_set = 1;
 			load_addr = (elf_ppnt->p_vaddr - elf_ppnt->p_offset);
-			if (elf_ex.e_type == ET_DYN) {
+			if (loc->elf_ex.e_type == ET_DYN) {
 				load_bias += error -
 				             ELF_PAGESTART(load_bias + vaddr);
 				load_addr += load_bias;
@@ -810,7 +821,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 			elf_brk = k;
 	}
 
-	elf_ex.e_entry += load_bias;
+	loc->elf_ex.e_entry += load_bias;
 	elf_bss += load_bias;
 	elf_brk += load_bias;
 	start_code += load_bias;
@@ -832,10 +843,10 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 
 	if (elf_interpreter) {
 		if (interpreter_type == INTERPRETER_AOUT)
-			elf_entry = load_aout_interp(&interp_ex,
+			elf_entry = load_aout_interp(&loc->interp_ex,
 						     interpreter);
 		else
-			elf_entry = load_elf_interp(&interp_elf_ex,
+			elf_entry = load_elf_interp(&loc->interp_elf_ex,
 						    interpreter,
 						    &interp_load_addr);
 		if (BAD_ADDR(elf_entry)) {
@@ -850,7 +861,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 		fput(interpreter);
 		kfree(elf_interpreter);
 	} else {
-		elf_entry = elf_ex.e_entry;
+		elf_entry = loc->elf_ex.e_entry;
 	}
 
 	kfree(elf_phdata);
@@ -862,7 +873,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 
 	compute_creds(bprm);
 	current->flags &= ~PF_FORKNOEXEC;
-	create_elf_tables(bprm, &elf_ex, (interpreter_type == INTERPRETER_AOUT),
+	create_elf_tables(bprm, &loc->elf_ex, (interpreter_type == INTERPRETER_AOUT),
 			load_addr, interp_load_addr);
 	/* N.B. passed_fileno might not be initialized? */
 	if (interpreter_type == INTERPRETER_AOUT)
@@ -907,6 +918,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 	}
 	retval = 0;
 out:
+	kfree(loc);
+out_ret:
 	return retval;
 
 	/* error cleanup */
@@ -1178,10 +1191,27 @@ static void fill_prstatus(struct elf_prstatus *prstatus,
 	prstatus->pr_ppid = p->parent->pid;
 	prstatus->pr_pgrp = process_group(p);
 	prstatus->pr_sid = p->signal->session;
-	jiffies_to_timeval(p->utime, &prstatus->pr_utime);
-	jiffies_to_timeval(p->stime, &prstatus->pr_stime);
-	jiffies_to_timeval(p->cutime, &prstatus->pr_cutime);
-	jiffies_to_timeval(p->cstime, &prstatus->pr_cstime);
+	if (p->pid == p->tgid) {
+		/*
+		 * This is the record for the group leader.  Add in the
+		 * cumulative times of previous dead threads.  This total
+		 * won't include the time of each live thread whose state
+		 * is included in the core dump.  The final total reported
+		 * to our parent process when it calls wait4 will include
+		 * those sums as well as the little bit more time it takes
+		 * this and each other thread to finish dying after the
+		 * core dump synchronization phase.
+		 */
+		jiffies_to_timeval(p->utime + p->signal->utime,
+				   &prstatus->pr_utime);
+		jiffies_to_timeval(p->stime + p->signal->stime,
+				   &prstatus->pr_stime);
+	} else {
+		jiffies_to_timeval(p->utime, &prstatus->pr_utime);
+		jiffies_to_timeval(p->stime, &prstatus->pr_stime);
+	}
+	jiffies_to_timeval(p->signal->cutime, &prstatus->pr_cutime);
+	jiffies_to_timeval(p->signal->cstime, &prstatus->pr_cstime);
 }
 
 static void fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
@@ -1226,6 +1256,7 @@ struct elf_thread_status
 	struct list_head list;
 	struct elf_prstatus prstatus;	/* NT_PRSTATUS */
 	elf_fpregset_t fpu;		/* NT_PRFPREG */
+	struct task_struct *thread;
 #ifdef ELF_CORE_COPY_XFPREGS
 	elf_fpxregset_t xfpu;		/* NT_PRXFPREG */
 #endif
@@ -1238,18 +1269,10 @@ struct elf_thread_status
  * we need to keep a linked list of every threads pr_status and then
  * create a single section for them in the final core file.
  */
-static int elf_dump_thread_status(long signr, struct task_struct * p, struct list_head * thread_list)
+static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
 {
-
-	struct elf_thread_status *t;
 	int sz = 0;
-
-	t = kmalloc(sizeof(*t), GFP_ATOMIC);
-	if (!t)
-		return 0;
-	memset(t, 0, sizeof(*t));
-
-	INIT_LIST_HEAD(&t->list);
+	struct task_struct *p = t->thread;
 	t->num_notes = 0;
 
 	fill_prstatus(&t->prstatus, p, signr);
@@ -1272,7 +1295,6 @@ static int elf_dump_thread_status(long signr, struct task_struct * p, struct lis
 		sz += notesize(&t->notes[2]);
 	}
 #endif	
-	list_add(&t->list, thread_list);
 	return sz;
 }
 
@@ -1343,22 +1365,32 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
 		goto cleanup;
 #endif
 
-	/* capture the status of all other threads */
 	if (signr) {
+		struct elf_thread_status *tmp;
 		read_lock(&tasklist_lock);
 		do_each_thread(g,p)
 			if (current->mm == p->mm && current != p) {
-				int sz = elf_dump_thread_status(signr, p, &thread_list);
-				if (!sz) {
+				tmp = kmalloc(sizeof(*tmp), GFP_ATOMIC);
+				if (!tmp) {
 					read_unlock(&tasklist_lock);
 					goto cleanup;
-				} else
-					thread_status_size += sz;
+				}
+				memset(tmp, 0, sizeof(*tmp));
+				INIT_LIST_HEAD(&tmp->list);
+				tmp->thread = p;
+				list_add(&tmp->list, &thread_list);
 			}
 		while_each_thread(g,p);
 		read_unlock(&tasklist_lock);
-	}
+		list_for_each(t, &thread_list) {
+			struct elf_thread_status *tmp;
+			int sz;
 
+			tmp = list_entry(t, struct elf_thread_status, list);
+			sz = elf_dump_thread_status(signr, tmp);
+			thread_status_size += sz;
+		}
+	}
 	/* now collect the dump for the current */
 	memset(prstatus, 0, sizeof(*prstatus));
 	fill_prstatus(prstatus, current, signr);
diff --git a/fs/bio.c b/fs/bio.c
index e246f542a..0ebd86b4a 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -137,33 +137,29 @@ inline void bio_init(struct bio *bio)
  **/
 struct bio *bio_alloc(int gfp_mask, int nr_iovecs)
 {
-	struct bio_vec *bvl = NULL;
-	unsigned long idx;
-	struct bio *bio;
-
-	bio = mempool_alloc(bio_pool, gfp_mask);
-	if (unlikely(!bio))
-		goto out;
+	struct bio *bio = mempool_alloc(bio_pool, gfp_mask);
 
-	bio_init(bio);
+	if (likely(bio)) {
+		struct bio_vec *bvl = NULL;
 
-	if (unlikely(!nr_iovecs))
-		goto noiovec;
+		bio_init(bio);
+		if (likely(nr_iovecs)) {
+			unsigned long idx;
 
-	bvl = bvec_alloc(gfp_mask, nr_iovecs, &idx);
-	if (bvl) {
-		bio->bi_flags |= idx << BIO_POOL_OFFSET;
-		bio->bi_max_vecs = bvec_array[idx].nr_vecs;
-noiovec:
+			bvl = bvec_alloc(gfp_mask, nr_iovecs, &idx);
+			if (unlikely(!bvl)) {
+				mempool_free(bio, bio_pool);
+				bio = NULL;
+				goto out;
+			}
+			bio->bi_flags |= idx << BIO_POOL_OFFSET;
+			bio->bi_max_vecs = bvec_array[idx].nr_vecs;
+		}
 		bio->bi_io_vec = bvl;
 		bio->bi_destructor = bio_destructor;
-out:
-		return bio;
 	}
-
-	mempool_free(bio, bio_pool);
-	bio = NULL;
-	goto out;
+out:
+	return bio;
 }
 
 /**
@@ -376,6 +372,38 @@ int bio_add_page(struct bio *bio, struct page *page, unsigned int len,
 			      len, offset);
 }
 
+struct bio_map_data {
+	struct bio_vec *iovecs;
+	void __user *userptr;
+};
+
+static void bio_set_map_data(struct bio_map_data *bmd, struct bio *bio)
+{
+	memcpy(bmd->iovecs, bio->bi_io_vec, sizeof(struct bio_vec) * bio->bi_vcnt);
+	bio->bi_private = bmd;
+}
+
+static void bio_free_map_data(struct bio_map_data *bmd)
+{
+	kfree(bmd->iovecs);
+	kfree(bmd);
+}
+
+static struct bio_map_data *bio_alloc_map_data(int nr_segs)
+{
+	struct bio_map_data *bmd = kmalloc(sizeof(*bmd), GFP_KERNEL);
+
+	if (!bmd)
+		return NULL;
+
+	bmd->iovecs = kmalloc(sizeof(struct bio_vec) * nr_segs, GFP_KERNEL);
+	if (bmd->iovecs)
+		return bmd;
+
+	kfree(bmd);
+	return NULL;
+}
+
 /**
  *	bio_uncopy_user	-	finish previously mapped bio
  *	@bio: bio being terminated
@@ -385,23 +413,22 @@ int bio_add_page(struct bio *bio, struct page *page, unsigned int len,
  */
 int bio_uncopy_user(struct bio *bio)
 {
+	struct bio_map_data *bmd = bio->bi_private;
+	const int read = bio_data_dir(bio) == READ;
 	struct bio_vec *bvec;
 	int i, ret = 0;
 
-	if (bio_data_dir(bio) == READ) {
-		char *uaddr = bio->bi_private;
-
-		__bio_for_each_segment(bvec, bio, i, 0) {
-			char *addr = page_address(bvec->bv_page);
+	__bio_for_each_segment(bvec, bio, i, 0) {
+		char *addr = page_address(bvec->bv_page);
+		unsigned int len = bmd->iovecs[i].bv_len;
 
-			if (!ret && copy_to_user(uaddr, addr, bvec->bv_len))
-				ret = -EFAULT;
+		if (read && !ret && copy_to_user(bmd->userptr, addr, len))
+			ret = -EFAULT;
 
-			__free_page(bvec->bv_page);
-			uaddr += bvec->bv_len;
-		}
+		__free_page(bvec->bv_page);
+		bmd->userptr += len;
 	}
-
+	bio_free_map_data(bmd);
 	bio_put(bio);
 	return ret;
 }
@@ -422,14 +449,25 @@ struct bio *bio_copy_user(request_queue_t *q, unsigned long uaddr,
 {
 	unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	unsigned long start = uaddr >> PAGE_SHIFT;
+	struct bio_map_data *bmd;
 	struct bio_vec *bvec;
 	struct page *page;
 	struct bio *bio;
 	int i, ret;
 
+	bmd = bio_alloc_map_data(end - start);
+	if (!bmd)
+		return ERR_PTR(-ENOMEM);
+
+	bmd->userptr = (void __user *) uaddr;
+
 	bio = bio_alloc(GFP_KERNEL, end - start);
-	if (!bio)
+	if (!bio) {
+		bio_free_map_data(bmd);
 		return ERR_PTR(-ENOMEM);
+	}
+
+	bio->bi_rw |= (!write_to_vm << BIO_RW);
 
 	ret = 0;
 	while (len) {
@@ -452,31 +490,30 @@ struct bio *bio_copy_user(request_queue_t *q, unsigned long uaddr,
 		len -= bytes;
 	}
 
+	if (ret)
+		goto cleanup;
+
 	/*
 	 * success
 	 */
-	if (!ret) {
-		if (!write_to_vm) {
-			bio->bi_rw |= (1 << BIO_RW);
-			/*
-	 		 * for a write, copy in data to kernel pages
-			 */
-			ret = -EFAULT;
-			bio_for_each_segment(bvec, bio, i) {
-				char *addr = page_address(bvec->bv_page);
+	if (!write_to_vm) {
+		char __user *p = (char __user *) uaddr;
 
-				if (copy_from_user(addr, (char *) uaddr, bvec->bv_len))
-					goto cleanup;
-			}
-		}
+		/*
+		 * for a write, copy in data to kernel pages
+		 */
+		ret = -EFAULT;
+		bio_for_each_segment(bvec, bio, i) {
+			char *addr = page_address(bvec->bv_page);
 
-		bio->bi_private = (void *) uaddr;
-		return bio;
+			if (copy_from_user(addr, p, bvec->bv_len))
+				goto cleanup;
+			p += bvec->bv_len;
+		}
 	}
 
-	/*
-	 * cleanup
-	 */
+	bio_set_map_data(bmd, bio);
+	return bio;
 cleanup:
 	bio_for_each_segment(bvec, bio, i)
 		__free_page(bvec->bv_page);
@@ -608,18 +645,6 @@ static void __bio_unmap_user(struct bio *bio)
 	struct bio_vec *bvec;
 	int i;
 
-	/*
-	 * find original bio if it was bounced
-	 */
-	if (bio->bi_private) {
-		/*
-		 * someone stole our bio, must not happen
-		 */
-		BUG_ON(!bio_flagged(bio, BIO_BOUNCED));
-	
-		bio = bio->bi_private;
-	}
-
 	/*
 	 * make sure we dirty pages we wrote to
 	 */
diff --git a/fs/buffer.c b/fs/buffer.c
index c70e72ef5..81f31297b 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -39,6 +39,7 @@
 #include <linux/cpu.h>
 #include <asm/bitops.h>
 
+static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
 static void invalidate_bh_lrus(void);
 
 #define BH_ENTRY(list) list_entry((list), struct buffer_head, b_assoc_buffers)
@@ -213,7 +214,7 @@ void end_buffer_write_sync(struct buffer_head *bh, int uptodate)
 	if (uptodate) {
 		set_buffer_uptodate(bh);
 	} else {
-		if (printk_ratelimit()) {
+		if (!buffer_eopnotsupp(bh) && printk_ratelimit()) {
 			buffer_io_error(bh);
 			printk(KERN_WARNING "lost page write due to "
 					"I/O error on %s\n",
@@ -725,12 +726,11 @@ still_busy:
  * PageLocked prevents anyone from starting writeback of a page which is
  * under read I/O (PageWriteback is only ever set against a locked page).
  */
-void mark_buffer_async_read(struct buffer_head *bh)
+static void mark_buffer_async_read(struct buffer_head *bh)
 {
 	bh->b_end_io = end_buffer_async_read;
 	set_buffer_async_read(bh);
 }
-EXPORT_SYMBOL(mark_buffer_async_read);
 
 void mark_buffer_async_write(struct buffer_head *bh)
 {
@@ -789,14 +789,6 @@ EXPORT_SYMBOL(mark_buffer_async_write);
  * b_inode back.
  */
 
-void buffer_insert_list(spinlock_t *lock,
-		struct buffer_head *bh, struct list_head *list)
-{
-	spin_lock(lock);
-	list_move_tail(&bh->b_assoc_buffers, list);
-	spin_unlock(lock);
-}
-
 /*
  * The buffer's backing address_space's private_lock must be held
  */
@@ -899,9 +891,12 @@ void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode)
 		if (mapping->assoc_mapping != buffer_mapping)
 			BUG();
 	}
-	if (list_empty(&bh->b_assoc_buffers))
-		buffer_insert_list(&buffer_mapping->private_lock,
-				bh, &mapping->private_list);
+	if (list_empty(&bh->b_assoc_buffers)) {
+		spin_lock(&buffer_mapping->private_lock);
+		list_move_tail(&bh->b_assoc_buffers,
+				&mapping->private_list);
+		spin_unlock(&buffer_mapping->private_lock);
+	}
 }
 EXPORT_SYMBOL(mark_buffer_dirty_inode);
 
@@ -982,7 +977,7 @@ EXPORT_SYMBOL(__set_page_dirty_buffers);
  * the osync code to catch these locked, dirty buffers without requeuing
  * any newly dirty buffers for write.
  */
-int fsync_buffers_list(spinlock_t *lock, struct list_head *list)
+static int fsync_buffers_list(spinlock_t *lock, struct list_head *list)
 {
 	struct buffer_head *bh;
 	struct list_head tmp;
@@ -1551,6 +1546,7 @@ __getblk(struct block_device *bdev, sector_t block, int size)
 {
 	struct buffer_head *bh = __find_get_block(bdev, block, size);
 
+	might_sleep();
 	if (bh == NULL)
 		bh = __getblk_slow(bdev, block, size);
 	return bh;
@@ -1776,6 +1772,8 @@ void unmap_underlying_metadata(struct block_device *bdev, sector_t block)
 {
 	struct buffer_head *old_bh;
 
+	might_sleep();
+
 	old_bh = __find_get_block_slow(bdev, block, 0);
 	if (old_bh) {
 		clear_buffer_dirty(old_bh);
@@ -2756,21 +2754,33 @@ static int end_bio_bh_io_sync(struct bio *bio, unsigned int bytes_done, int err)
 	if (bio->bi_size)
 		return 1;
 
+	if (err == -EOPNOTSUPP) {
+		set_bit(BIO_EOPNOTSUPP, &bio->bi_flags);
+		set_bit(BH_Eopnotsupp, &bh->b_state);
+	}
+
 	bh->b_end_io(bh, test_bit(BIO_UPTODATE, &bio->bi_flags));
 	bio_put(bio);
 	return 0;
 }
 
-void submit_bh(int rw, struct buffer_head * bh)
+int submit_bh(int rw, struct buffer_head * bh)
 {
 	struct bio *bio;
+	int ret = 0;
 
 	BUG_ON(!buffer_locked(bh));
 	BUG_ON(!buffer_mapped(bh));
 	BUG_ON(!bh->b_end_io);
 
-	/* Only clear out a write error when rewriting */
-	if (test_set_buffer_req(bh) && rw == WRITE)
+	if (buffer_ordered(bh) && (rw == WRITE))
+		rw = WRITE_BARRIER;
+
+	/*
+	 * Only clear out a write error when rewriting, should this
+	 * include WRITE_SYNC as well?
+	 */
+	if (test_set_buffer_req(bh) && (rw == WRITE || rw == WRITE_BARRIER))
 		clear_buffer_write_io_error(bh);
 
 	/*
@@ -2792,7 +2802,14 @@ void submit_bh(int rw, struct buffer_head * bh)
 	bio->bi_end_io = end_bio_bh_io_sync;
 	bio->bi_private = bh;
 
+	bio_get(bio);
 	submit_bio(rw, bio);
+
+	if (bio_flagged(bio, BIO_EOPNOTSUPP))
+		ret = -EOPNOTSUPP;
+
+	bio_put(bio);
+	return ret;
 }
 
 /**
@@ -2851,20 +2868,30 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhs[])
 
 /*
  * For a data-integrity writeout, we need to wait upon any in-progress I/O
- * and then start new I/O and then wait upon it.
+ * and then start new I/O and then wait upon it.  The caller must have a ref on
+ * the buffer_head.
  */
-void sync_dirty_buffer(struct buffer_head *bh)
+int sync_dirty_buffer(struct buffer_head *bh)
 {
+	int ret = 0;
+
 	WARN_ON(atomic_read(&bh->b_count) < 1);
 	lock_buffer(bh);
 	if (test_clear_buffer_dirty(bh)) {
 		get_bh(bh);
 		bh->b_end_io = end_buffer_write_sync;
-		submit_bh(WRITE, bh);
+		ret = submit_bh(WRITE, bh);
 		wait_on_buffer(bh);
+		if (buffer_eopnotsupp(bh)) {
+			clear_buffer_eopnotsupp(bh);
+			ret = -EOPNOTSUPP;
+		}
+		if (!ret && !buffer_uptodate(bh))
+			ret = -EIO;
 	} else {
 		unlock_buffer(bh);
 	}
+	return ret;
 }
 
 /*
@@ -3121,14 +3148,12 @@ EXPORT_SYMBOL(block_read_full_page);
 EXPORT_SYMBOL(block_sync_page);
 EXPORT_SYMBOL(block_truncate_page);
 EXPORT_SYMBOL(block_write_full_page);
-EXPORT_SYMBOL(buffer_insert_list);
 EXPORT_SYMBOL(cont_prepare_write);
 EXPORT_SYMBOL(end_buffer_async_write);
 EXPORT_SYMBOL(end_buffer_read_sync);
 EXPORT_SYMBOL(end_buffer_write_sync);
 EXPORT_SYMBOL(file_fsync);
 EXPORT_SYMBOL(fsync_bdev);
-EXPORT_SYMBOL(fsync_buffers_list);
 EXPORT_SYMBOL(generic_block_bmap);
 EXPORT_SYMBOL(generic_commit_write);
 EXPORT_SYMBOL(generic_cont_expand);
diff --git a/fs/cifs/AUTHORS b/fs/cifs/AUTHORS
index 43a7b6534..fccc9ca44 100644
--- a/fs/cifs/AUTHORS
+++ b/fs/cifs/AUTHORS
@@ -24,6 +24,7 @@ Shobhit Dayal
 Sergey Vlasov
 Richard Hughes
 Yury Umanets
+Mark Hamzy
 
 Test case and Bug Report contributors
 -------------------------------------
@@ -31,7 +32,9 @@ Thanks to those in the community who have submitted detailed bug reports
 and debug of problems they have found:  Jochen Dolze, David Blaine,
 Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori,
 Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen,
-Olaf Kirch, Kieron Briggs, Nick Millington and others. 
+Olaf Kirch, Kieron Briggs, Nick Millington and others. Also special
+mention to the Stanford Checker (SWAT) which pointed out many minor
+bugs in error paths.
 
 And thanks to the IBM LTC and Power test teams and SuSE testers for
 finding multiple bugs during excellent stress test runs.
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index a853ec02e..087be3621 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,7 +1,9 @@
 Version 1.22
 ------------
 Add config option to enable XATTR (extended attribute) support, mapping
-xattr names in the "user." namespace space to SMB/CIFS EAs.
+xattr names in the "user." namespace space to SMB/CIFS EAs. Lots of
+minor fixes pointed out by the Stanford SWAT checker (mostly missing
+or out of order NULL pointer checks in little used error paths).
 
 Version 1.21
 ------------
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
index cf3c02767..60f67697b 100644
--- a/fs/cifs/asn1.c
+++ b/fs/cifs/asn1.c
@@ -375,7 +375,7 @@ asn1_subid_decode(struct asn1_ctx *ctx, unsigned long *subid)
 	return 1;
 }
 
-static unsigned char
+static int 
 asn1_oid_decode(struct asn1_ctx *ctx,
 		unsigned char *eoc, unsigned long **oid, unsigned int *len)
 {
@@ -454,11 +454,11 @@ decode_negTokenInit(unsigned char *security_blob, int length,
 	struct asn1_ctx ctx;
 	unsigned char *end;
 	unsigned char *sequence_end;
-	unsigned long *oid;
+	unsigned long *oid = NULL;
 	unsigned int cls, con, tag, oidlen, rc;
 	int use_ntlmssp = FALSE;
 
-    *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default */
+	*secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default */
 
 	/* cifs_dump_mem(" Received SecBlob ", security_blob, length); */
 
@@ -543,16 +543,19 @@ decode_negTokenInit(unsigned char *security_blob, int length,
 				return 0;
 			}
 			if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
-				asn1_oid_decode(&ctx, end, &oid, &oidlen);
-				cFYI(1,
-				     ("OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx",
-				      oidlen, *oid, *(oid + 1), *(oid + 2),
-				      *(oid + 3)));
-				rc = compare_oid(oid, oidlen, NTLMSSP_OID,
+				rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
+				if(rc) {		
+					cFYI(1,
+					  ("OID len = %d oid = 0x%lx 0x%lx 0x%lx 0x%lx",
+					   oidlen, *oid, *(oid + 1), *(oid + 2),
+					   *(oid + 3)));
+					rc = compare_oid(oid, oidlen, NTLMSSP_OID,
 						 NTLMSSP_OID_LEN);
-				kfree(oid);
-				if (rc)
-					use_ntlmssp = TRUE;
+					if(oid)
+						kfree(oid);
+					if (rc)
+						use_ntlmssp = TRUE;
+				}
 			} else {
 				cFYI(1,("This should be an oid what is going on? "));
 			}
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 5ed31456f..0cf2b223e 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -126,26 +126,28 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
 	i = 0;
 	read_lock(&GlobalSMBSeslock);
 	list_for_each(tmp, &GlobalTreeConnectionList) {
+		__u32 dev_type;
 		i++;
 		tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
+		dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
 		length =
 		    sprintf(buf,
 			    "\n%d) %s Uses: %d Type: %s Characteristics: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d",
 			    i, tcon->treeName,
 			    atomic_read(&tcon->useCount),
 			    tcon->nativeFileSystem,
-			    tcon->fsDevInfo.DeviceCharacteristics,
-			    tcon->fsAttrInfo.Attributes,
-			    tcon->fsAttrInfo.MaxPathNameComponentLength,tcon->tidStatus);
+			    le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics),
+			    le32_to_cpu(tcon->fsAttrInfo.Attributes),
+			    le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
+			    tcon->tidStatus);
 		buf += length;        
-		if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_DISK)
+		if (dev_type == FILE_DEVICE_DISK)
 			length = sprintf(buf, " type: DISK ");
-		else if (tcon->fsDevInfo.DeviceType == FILE_DEVICE_CD_ROM)
+		else if (dev_type == FILE_DEVICE_CD_ROM)
 			length = sprintf(buf, " type: CDROM ");
 		else
 			length =
-			    sprintf(buf, " type: %d ",
-				    tcon->fsDevInfo.DeviceType);
+			    sprintf(buf, " type: %d ", dev_type);
 		buf += length;
 		if(tcon->tidStatus == CifsNeedReconnect) {
 			buf += sprintf(buf, "\tDISCONNECTED ");
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 8fdf3d79b..178231062 100755
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -61,7 +61,7 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses,
 	if((cifs_pdu == NULL) || (ses == NULL))
 		return -EINVAL;
 
-	if((le32_to_cpu(cifs_pdu->Flags2) & SMBFLG2_SECURITY_SIGNATURE) == 0) 
+	if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0) 
 		return rc;
 
 	spin_lock(&GlobalMid_Lock);
@@ -107,13 +107,11 @@ int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
 	if(memcmp(cifs_pdu->Signature.SecuritySignature,"BSRSPYL ",8)==0)
 		cFYI(1,("dummy signature received for smb command 0x%x",cifs_pdu->Command));
 
-	expected_sequence_number = cpu_to_le32(expected_sequence_number);
-
 	/* save off the origiginal signature so we can modify the smb and check
 		its signature against what the server sent */
 	memcpy(server_response_sig,cifs_pdu->Signature.SecuritySignature,8);
 
-	cifs_pdu->Signature.Sequence.SequenceNumber = expected_sequence_number;
+	cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(expected_sequence_number);
 	cifs_pdu->Signature.Sequence.Reserved = 0;
 
 	rc = cifs_calculate_signature(cifs_pdu, mac_key,
@@ -153,7 +151,7 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_
 	wchar_t * unicode_buf;
 	unsigned int i,user_name_len,dom_name_len;
 
-	if(ses)
+	if(ses == NULL)
 		return -EINVAL;
 
 	E_md4hash(ses->password, temp_hash);
@@ -167,7 +165,13 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_
 		return -EINVAL;
   
 	ucase_buf = kmalloc((MAX_USERNAME_SIZE+1), GFP_KERNEL);
+	if(ucase_buf == NULL)
+		return -ENOMEM;
 	unicode_buf = kmalloc((MAX_USERNAME_SIZE+1)*4, GFP_KERNEL);
+	if(unicode_buf == NULL) {
+		kfree(ucase_buf);
+		return -ENOMEM;
+	}
    
 	for(i=0;i<user_name_len;i++)
 		ucase_buf[i] = nls_info->charset2upper[(int)ses->userName[i]];
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index fbc737e2e..729cdba71 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -255,12 +255,14 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
 	if (cifs_sb) {
 		if (cifs_sb->tcon) {
 			seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName);
-			if ((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->userName))
-				seq_printf(s, ",username=%s",
+			if (cifs_sb->tcon->ses) {
+				if (cifs_sb->tcon->ses->userName)
+					seq_printf(s, ",username=%s",
 					   cifs_sb->tcon->ses->userName);
-			if(cifs_sb->tcon->ses->domainName)
-				seq_printf(s, ",domain=%s",
-					cifs_sb->tcon->ses->domainName);
+				if(cifs_sb->tcon->ses->domainName)
+					seq_printf(s, ",domain=%s",
+					   cifs_sb->tcon->ses->domainName);
+			}
 		}
 		seq_printf(s, ",rsize=%d",cifs_sb->rsize);
 		seq_printf(s, ",wsize=%d",cifs_sb->wsize);
@@ -510,8 +512,9 @@ struct inode_operations cifs_file_inode_ops = {
 };
 
 struct inode_operations cifs_symlink_inode_ops = {
-	.readlink = cifs_readlink,
+	.readlink = generic_readlink, 
 	.follow_link = cifs_follow_link,
+	.put_link = cifs_put_link,
 	.permission = cifs_permission,
 	/* BB add the following two eventually */
 	/* revalidate: cifs_revalidate,
@@ -561,7 +564,7 @@ cifs_init_inodecache(void)
 {
 	cifs_inode_cachep = kmem_cache_create("cifs_inode_cache",
 					      sizeof (struct cifsInodeInfo),
-					      0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					      0, SLAB_RECLAIM_ACCOUNT,
 					      cifs_init_once, NULL);
 	if (cifs_inode_cachep == NULL)
 		return -ENOMEM;
@@ -756,11 +759,14 @@ init_cifs(void)
 			if (!rc) {
 				rc = register_filesystem(&cifs_fs_type);
 				if (!rc) {                
-					kernel_thread(cifs_oplock_thread, NULL, 
+					rc = (int)kernel_thread(cifs_oplock_thread, NULL, 
 						CLONE_FS | CLONE_FILES | CLONE_VM);
-					return rc; /* Success */
-				} else
-					cifs_destroy_request_bufs();
+					if(rc > 0)
+						return 0;
+					else 
+						cERROR(1,("error %d create oplock thread",rc));
+				}
+				cifs_destroy_request_bufs();
 			}
 			cifs_destroy_mids();
 		}
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 866b68c8b..b1cbc68d0 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -81,6 +81,7 @@ extern struct dentry_operations cifs_dentry_ops;
 
 /* Functions related to symlinks */
 extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
+extern void cifs_put_link(struct dentry *direntry, struct nameidata *nd);
 extern int cifs_readlink(struct dentry *direntry, char __user *buffer, int buflen);
 extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
 			const char *symname);
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 21ac75cf0..150210c57 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -126,7 +126,7 @@ struct TCP_Server_Info {
 	enum protocolEnum protocolType;	
 	char versionMajor;
 	char versionMinor;
-	int svlocal:1;		/* local server or remote */
+	unsigned svlocal:1;	/* local server or remote */
 	atomic_t socketUseCount; /* number of open cifs sessions on socket */
 	atomic_t inFlight;  /* number of requests on the wire to server */
 	enum statusEnum tcpStatus; /* what we think the status is */
@@ -222,7 +222,7 @@ struct cifsTconInfo {
 	FILE_SYSTEM_DEVICE_INFO fsDevInfo;
 	FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo;	/* ok if file system name truncated */
 	FILE_SYSTEM_UNIX_INFO fsUnixInfo;
-	int retry:1;
+	unsigned retry:1;
 	/* BB add field for back pointer to sb struct? */
 };
 
@@ -250,10 +250,10 @@ struct cifsFileInfo {
 	/* lock scope id (0 if none) */
 	struct file * pfile; /* needed for writepage */
 	struct inode * pInode; /* needed for oplock break */
-	int endOfSearch:1;	/* we have reached end of search */
-	int closePend:1;	/* file is marked to close */
-	int emptyDir:1;
-	int invalidHandle:1;  /* file closed via session abend */
+	unsigned endOfSearch:1;	/* we have reached end of search */
+	unsigned closePend:1;	/* file is marked to close */
+	unsigned emptyDir:1;
+	unsigned invalidHandle:1;  /* file closed via session abend */
 	struct semaphore fh_sem; /* prevents reopen race after dead ses*/
 	char * search_resume_name;
 	unsigned int resume_name_length;
@@ -272,9 +272,9 @@ struct cifsInodeInfo {
 	__u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
 	atomic_t inUse;	 /* num concurrent users (local openers cifs) of file*/
 	unsigned long time;	/* jiffies of last update/check of inode */
-	int clientCanCacheRead:1; /* read oplock */
-	int clientCanCacheAll:1;  /* read and writebehind oplock */
-	int oplockPending:1;
+	unsigned clientCanCacheRead:1; /* read oplock */
+	unsigned clientCanCacheAll:1;  /* read and writebehind oplock */
+	unsigned oplockPending:1;
 	struct inode vfs_inode;
 };
 
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 94646af9f..20430a2d2 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -137,15 +137,15 @@
 /*
  * SMB flag2 definitions 
  */
-#define SMBFLG2_KNOWS_LONG_NAMES 0x0001	/* can send long (non-8.3) path names in response */
-#define SMBFLG2_KNOWS_EAS 0x0002
-#define SMBFLG2_SECURITY_SIGNATURE 0x0004
-#define SMBFLG2_IS_LONG_NAME 0x0040
-#define SMBFLG2_EXT_SEC 0x0800
-#define SMBFLG2_DFS 0x1000
-#define SMBFLG2_PAGING_IO 0x2000
-#define SMBFLG2_ERR_STATUS 0x4000
-#define SMBFLG2_UNICODE 0x8000
+#define SMBFLG2_KNOWS_LONG_NAMES cpu_to_le16(1)	/* can send long (non-8.3) path names in response */
+#define SMBFLG2_KNOWS_EAS cpu_to_le16(2)
+#define SMBFLG2_SECURITY_SIGNATURE cpu_to_le16(4)
+#define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40)
+#define SMBFLG2_EXT_SEC cpu_to_le16(0x80)
+#define SMBFLG2_DFS cpu_to_le16(0x1000)
+#define SMBFLG2_PAGING_IO cpu_to_le16(0x2000)
+#define SMBFLG2_ERR_STATUS cpu_to_le16(0x4000)
+#define SMBFLG2_UNICODE cpu_to_le16(0x8000)
 
 /*
  * These are the file access permission bits defined in CIFS for the
@@ -303,23 +303,23 @@ struct smb_hdr {
 		struct {
 			__u8 ErrorClass;
 			__u8 Reserved;
-			__u16 Error;	/* note: treated as little endian (le) on wire */
+			__le16 Error;
 		} DosError;
-		__u32 CifsError;	/* note: le */
+		__le32 CifsError;
 	} Status;
 	__u8 Flags;
-	__u16 Flags2;		/* note: le */
-	__u16 PidHigh;		/* note: le */
+	__le16 Flags2;		/* note: le */
+	__le16 PidHigh;
 	union {
 		struct {
-			__u32 SequenceNumber;  /* le */
+			__le32 SequenceNumber;  /* le */
 			__u32 Reserved; /* zero */
 		} Sequence;
 		__u8 SecuritySignature[8];	/* le */
 	} Signature;
 	__u8 pad[2];
 	__u16 Tid;
-	__u16 Pid;		/* note: le */
+	__le16 Pid;
 	__u16 Uid;
 	__u16 Mid;
 	__u8 WordCount;
@@ -328,7 +328,7 @@ struct smb_hdr {
 #define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) )
 
 /* given a pointer to an smb_hdr retrieve the pointer to the byte area */
-#define pByteArea(smb_var) ((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
+#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 )
 
 /*
  * Computer Name Length
@@ -373,23 +373,23 @@ struct smb_hdr {
 
 typedef struct negotiate_req {
 	struct smb_hdr hdr;	/* wct = 0 */
-	__u16 ByteCount;
+	__le16 ByteCount;
 	unsigned char DialectsArray[1];
 } NEGOTIATE_REQ;
 
 typedef struct negotiate_rsp {
 	struct smb_hdr hdr;	/* wct = 17 */
-	__u16 DialectIndex;
+	__le16 DialectIndex;
 	__u8 SecurityMode;
-	__u16 MaxMpxCount;
-	__u16 MaxNumberVcs;
-	__u32 MaxBufferSize;
-	__u32 MaxRawSize;
-	__u32 SessionKey;
-	__u32 Capabilities;	/* see below */
-	__u32 SystemTimeLow;
-	__u32 SystemTimeHigh;
-	__u16 ServerTimeZone;
+	__le16 MaxMpxCount;
+	__le16 MaxNumberVcs;
+	__le32 MaxBufferSize;
+	__le32 MaxRawSize;
+	__le32 SessionKey;
+	__le32 Capabilities;	/* see below */
+	__le32 SystemTimeLow;
+	__le32 SystemTimeHigh;
+	__le16 ServerTimeZone;
 	__u8 EncryptionKeyLength;
 	__u16 ByteCount;
 	union {
@@ -436,15 +436,15 @@ typedef union smb_com_session_setup_andx {
 		struct smb_hdr hdr;	/* wct = 12 */
 		__u8 AndXCommand;
 		__u8 AndXReserved;
-		__u16 AndXOffset;
-		__u16 MaxBufferSize;
-		__u16 MaxMpxCount;
-		__u16 VcNumber;
+		__le16 AndXOffset;
+		__le16 MaxBufferSize;
+		__le16 MaxMpxCount;
+		__le16 VcNumber;
 		__u32 SessionKey;
-		__u16 SecurityBlobLength;
+		__le16 SecurityBlobLength;
 		__u32 Reserved;
-		__u32 Capabilities;	/* see below */
-		__u16 ByteCount;
+		__le32 Capabilities;	/* see below */
+		__le16 ByteCount;
 		unsigned char SecurityBlob[1];	/* followed by */
 		/* STRING NativeOS */
 		/* STRING NativeLanMan */
@@ -454,16 +454,16 @@ typedef union smb_com_session_setup_andx {
 		struct smb_hdr hdr;	/* wct = 13 */
 		__u8 AndXCommand;
 		__u8 AndXReserved;
-		__u16 AndXOffset;
-		__u16 MaxBufferSize;
-		__u16 MaxMpxCount;
-		__u16 VcNumber;
+		__le16 AndXOffset;
+		__le16 MaxBufferSize;
+		__le16 MaxMpxCount;
+		__le16 VcNumber;
 		__u32 SessionKey;
-		__u16 CaseInsensitivePasswordLength;	/* ASCII password length */
-		__u16 CaseSensitivePasswordLength;	/* Unicode password length */
+		__le16 CaseInsensitivePasswordLength;	/* ASCII password length */
+		__le16 CaseSensitivePasswordLength;	/* Unicode password length */
 		__u32 Reserved;	/* see below */
-		__u32 Capabilities;
-		__u16 ByteCount;
+		__le32 Capabilities;
+		__le16 ByteCount;
 		unsigned char CaseInsensitivePassword[1];	/* followed by: */
 		/* unsigned char * CaseSensitivePassword; */
 		/* STRING AccountName */
@@ -476,9 +476,9 @@ typedef union smb_com_session_setup_andx {
 		struct smb_hdr hdr;	/* wct = 4 */
 		__u8 AndXCommand;
 		__u8 AndXReserved;
-		__u16 AndXOffset;
-		__u16 Action;	/* see below */
-		__u16 SecurityBlobLength;
+		__le16 AndXOffset;
+		__le16 Action;	/* see below */
+		__le16 SecurityBlobLength;
 		__u16 ByteCount;
 		unsigned char SecurityBlob[1];	/* followed by */
 /*      unsigned char  * NativeOS;      */
@@ -490,14 +490,14 @@ typedef union smb_com_session_setup_andx {
 		struct smb_hdr hdr;	/* wct = 10 */
 		__u8 AndXCommand;
 		__u8 AndXReserved;
-		__u16 AndXOffset;
-		__u16 MaxBufferSize;
-		__u16 MaxMpxCount;
-		__u16 VcNumber;
+		__le16 AndXOffset;
+		__le16 MaxBufferSize;
+		__le16 MaxMpxCount;
+		__le16 VcNumber;
 		__u32 SessionKey;
-		__u16 PassswordLength;
+		__le16 PassswordLength;
 		__u32 Reserved;
-		__u16 ByteCount;
+		__le16 ByteCount;
 		unsigned char AccountPassword[1];	/* followed by */
 		/* STRING AccountName */
 		/* STRING PrimaryDomain */
@@ -509,8 +509,8 @@ typedef union smb_com_session_setup_andx {
 		struct smb_hdr hdr;	/* wct = 3 */
 		__u8 AndXCommand;
 		__u8 AndXReserved;
-		__u16 AndXOffset;
-		__u16 Action;	/* see below */
+		__le16 AndXOffset;
+		__le16 Action;	/* see below */
 		__u16 ByteCount;
 		unsigned char NativeOS[1];	/* followed by */
 /*	unsigned char * NativeLanMan; */
@@ -537,10 +537,10 @@ typedef struct smb_com_tconx_req {
 	struct smb_hdr hdr;	/* wct = 4 */
 	__u8 AndXCommand;
 	__u8 AndXReserved;
-	__u16 AndXOffset;
-	__u16 Flags;		/* see below */
-	__u16 PasswordLength;
-	__u16 ByteCount;
+	__le16 AndXOffset;
+	__le16 Flags;		/* see below */
+	__le16 PasswordLength;
+	__le16 ByteCount;
 	unsigned char Password[1];	/* followed by */
 /* STRING Path    *//* \\server\share name */
 	/* STRING Service */
@@ -550,8 +550,8 @@ typedef struct smb_com_tconx_rsp {
 	struct smb_hdr hdr;	/* wct = 3 *//* note that Win2000 has sent wct=7 in some cases on responses. Four unspecified words followed OptionalSupport */
 	__u8 AndXCommand;
 	__u8 AndXReserved;
-	__u16 AndXOffset;
-	__u16 OptionalSupport;	/* see below */
+	__le16 AndXOffset;
+	__le16 OptionalSupport;	/* see below */
 	__u16 ByteCount;
 	unsigned char Service[1];	/* always ASCII, not Unicode */
 	/* STRING NativeFileSystem */
@@ -619,20 +619,20 @@ typedef struct smb_com_open_req {	/* also handles create */
 	struct smb_hdr hdr;	/* wct = 24 */
 	__u8 AndXCommand;
 	__u8 AndXReserved;
-	__u16 AndXOffset;
+	__le16 AndXOffset;
 	__u8 Reserved;		/* Must Be Zero */
-	__u16 NameLength;
-	__u32 OpenFlags;
-	__u32 RootDirectoryFid;
-	__u32 DesiredAccess;
-	__u64 AllocationSize;
-	__u32 FileAttributes;
-	__u32 ShareAccess;
-	__u32 CreateDisposition;
-	__u32 CreateOptions;
-	__u32 ImpersonationLevel;
+	__le16 NameLength;
+	__le32 OpenFlags;
+	__le32 RootDirectoryFid;
+	__le32 DesiredAccess;
+	__le64 AllocationSize;
+	__le32 FileAttributes;
+	__le32 ShareAccess;
+	__le32 CreateDisposition;
+	__le32 CreateOptions;
+	__le32 ImpersonationLevel;
 	__u8 SecurityFlags;
-	__u16 ByteCount;
+	__le16 ByteCount;
 	char fileName[1];
 } OPEN_REQ;
 
@@ -649,19 +649,19 @@ typedef struct smb_com_open_rsp {
 	struct smb_hdr hdr;	/* wct = 34 BB */
 	__u8 AndXCommand;
 	__u8 AndXReserved;
-	__u16 AndXOffset;
+	__le16 AndXOffset;
 	__u8 OplockLevel;
 	__u16 Fid;
-	__u32 CreateAction;
-	__u64 CreationTime;
-	__u64 LastAccessTime;
-	__u64 LastWriteTime;
-	__u64 ChangeTime;
-	__u32 FileAttributes;
-	__u64 AllocationSize;
-	__u64 EndOfFile;
-	__u16 FileType;
-	__u16 DeviceState;
+	__le32 CreateAction;
+	__le64 CreationTime;
+	__le64 LastAccessTime;
+	__le64 LastWriteTime;
+	__le64 ChangeTime;
+	__le32 FileAttributes;
+	__le64 AllocationSize;
+	__le64 EndOfFile;
+	__le16 FileType;
+	__le16 DeviceState;
 	__u8 DirectoryFlag;
 	__u16 ByteCount;	/* bct = 0 */
 } OPEN_RSP;
@@ -670,17 +670,17 @@ typedef struct smb_com_write_req {
 	struct smb_hdr hdr;	/* wct = 14 */
 	__u8 AndXCommand;
 	__u8 AndXReserved;
-	__u16 AndXOffset;
+	__le16 AndXOffset;
 	__u16 Fid;
-	__u32 OffsetLow;
+	__le32 OffsetLow;
 	__u32 Reserved;
-	__u16 WriteMode;
-	__u16 Remaining;
-	__u16 DataLengthHigh;
-	__u16 DataLengthLow;
-	__u16 DataOffset;
-	__u32 OffsetHigh;
-	__u16 ByteCount;
+	__le16 WriteMode;
+	__le16 Remaining;
+	__le16 DataLengthHigh;
+	__le16 DataLengthLow;
+	__le16 DataOffset;
+	__le32 OffsetHigh;
+	__le16 ByteCount;
 	__u8 Pad;		/* BB check for whether padded to DWORD boundary and optimum performance here */
 	char Data[1];
 } WRITE_REQ;
@@ -689,10 +689,10 @@ typedef struct smb_com_write_rsp {
 	struct smb_hdr hdr;	/* wct = 6 */
 	__u8 AndXCommand;
 	__u8 AndXReserved;
-	__u16 AndXOffset;
-	__u16 Count;
-	__u16 Remaining;
-	__u32 Reserved;
+	__le16 AndXOffset;
+	__le16 Count;
+	__le16 Remaining;
+	__le32 Reserved;
 	__u16 ByteCount;
 } WRITE_RSP;
 
@@ -700,28 +700,28 @@ typedef struct smb_com_read_req {
 	struct smb_hdr hdr;	/* wct = 12 */
 	__u8 AndXCommand;
 	__u8 AndXReserved;
-	__u16 AndXOffset;
+	__le16 AndXOffset;
 	__u16 Fid;
-	__u32 OffsetLow;
-	__u16 MaxCount;
-	__u16 MinCount;		/* obsolete */
-	__u32 MaxCountHigh;
-	__u16 Remaining;
-	__u32 OffsetHigh;
-	__u16 ByteCount;
+	__le32 OffsetLow;
+	__le16 MaxCount;
+	__le16 MinCount;		/* obsolete */
+	__le32 MaxCountHigh;
+	__le16 Remaining;
+	__le32 OffsetHigh;
+	__le16 ByteCount;
 } READ_REQ;
 
 typedef struct smb_com_read_rsp {
 	struct smb_hdr hdr;	/* wct = 12 */
 	__u8 AndXCommand;
 	__u8 AndXReserved;
-	__u16 AndXOffset;
-	__u16 Remaining;
-	__u16 DataCompactionMode;
-	__u16 Reserved;
-	__u16 DataLength;
-	__u16 DataOffset;
-	__u16 DataLengthHigh;
+	__le16 AndXOffset;
+	__le16 Remaining;
+	__le16 DataCompactionMode;
+	__le16 Reserved;
+	__le16 DataLength;
+	__le16 DataOffset;
+	__le16 DataLengthHigh;
 	__u64 Reserved2;
 	__u16 ByteCount;
 	__u8 Pad;		/* BB check for whether padded to DWORD boundary and optimum performance here */
@@ -729,12 +729,12 @@ typedef struct smb_com_read_rsp {
 } READ_RSP;
 
 typedef struct locking_andx_range {
-	__u16 Pid;
-	__u16 Pad;
-	__u32 OffsetHigh;
-	__u32 OffsetLow;
-	__u32 LengthHigh;
-	__u32 LengthLow;
+	__le16 Pid;
+	__le16 Pad;
+	__le32 OffsetHigh;
+	__le32 OffsetLow;
+	__le32 LengthHigh;
+	__le32 LengthLow;
 } LOCKING_ANDX_RANGE;
 
 #define LOCKING_ANDX_SHARED_LOCK     0x01
@@ -747,14 +747,14 @@ typedef struct smb_com_lock_req {
 	struct smb_hdr hdr;	/* wct = 8 */
 	__u8 AndXCommand;
 	__u8 AndXReserved;
-	__u16 AndXOffset;
+	__le16 AndXOffset;
 	__u16 Fid;
 	__u8 LockType;
 	__u8 OplockLevel;
-	__u32 Timeout;
-	__u16 NumberOfUnlocks;
-	__u16 NumberOfLocks;
-	__u16 ByteCount;
+	__le32 Timeout;
+	__le16 NumberOfUnlocks;
+	__le16 NumberOfLocks;
+	__le16 ByteCount;
 	LOCKING_ANDX_RANGE Locks[1];
 } LOCK_REQ;
 
@@ -762,14 +762,14 @@ typedef struct smb_com_lock_rsp {
 	struct smb_hdr hdr;	/* wct = 2 */
 	__u8 AndXCommand;
 	__u8 AndXReserved;
-	__u16 AndXOffset;
+	__le16 AndXOffset;
 	__u16 ByteCount;
 } LOCK_RSP;
 
 typedef struct smb_com_rename_req {
 	struct smb_hdr hdr;	/* wct = 1 */
-	__u16 SearchAttributes;	/* target file attributes */
-	__u16 ByteCount;
+	__le16 SearchAttributes;	/* target file attributes */
+	__le16 ByteCount;
 	__u8 BufferFormat;	/* 4 = ASCII or Unicode */
 	unsigned char OldFileName[1];
 	/* followed by __u8 BufferFormat2 */
@@ -787,9 +787,9 @@ typedef struct smb_com_rename_req {
 typedef struct smb_com_copy_req {
 	struct smb_hdr hdr;	/* wct = 3 */
 	__u16 Tid2;
-	__u16 OpenFunction;
-	__u16 Flags;
-	__u16 ByteCount;
+	__le16 OpenFunction;
+	__le16 Flags;
+	__le16 ByteCount;
 	__u8 BufferFormat;	/* 4 = ASCII or Unicode */ 
 	unsigned char OldFileName[1];
 	/* followed by __u8 BufferFormat2 */
@@ -798,7 +798,7 @@ typedef struct smb_com_copy_req {
 
 typedef struct smb_com_copy_rsp {
 	struct smb_hdr hdr;     /* wct = 1 */
-	__u16 CopyCount;    /* number of files copied */
+	__le16 CopyCount;    /* number of files copied */
 	__u16 ByteCount;    /* may be zero */
 	__u8 BufferFormat;  /* 0x04 - only present if errored file follows */
 	unsigned char ErrorFileName[1]; /* only present if error in copy */
@@ -810,10 +810,10 @@ typedef struct smb_com_copy_rsp {
 
 typedef struct smb_com_nt_rename_req {	/* A5 - also used for create hardlink */
 	struct smb_hdr hdr;	/* wct = 4 */
-	__u16 SearchAttributes;	/* target file attributes */
-	__u16 Flags;		/* spec says Information Level */
-	__u32 ClusterCount;
-	__u16 ByteCount;
+	__le16 SearchAttributes;	/* target file attributes */
+	__le16 Flags;		/* spec says Information Level */
+	__le32 ClusterCount;
+	__le16 ByteCount;
 	__u8 BufferFormat;	/* 4 = ASCII or Unicode */
 	unsigned char OldFileName[1];
 	/* followed by __u8 BufferFormat2 */
@@ -827,8 +827,8 @@ typedef struct smb_com_rename_rsp {
 
 typedef struct smb_com_delete_file_req {
 	struct smb_hdr hdr;	/* wct = 1 */
-	__u16 SearchAttributes;
-	__u16 ByteCount;
+	__le16 SearchAttributes;
+	__le16 ByteCount;
 	__u8 BufferFormat;	/* 4 = ASCII */
 	unsigned char fileName[1];
 } DELETE_FILE_REQ;
@@ -840,7 +840,7 @@ typedef struct smb_com_delete_file_rsp {
 
 typedef struct smb_com_delete_directory_req {
 	struct smb_hdr hdr;	/* wct = 0 */
-	__u16 ByteCount;
+	__le16 ByteCount;
 	__u8 BufferFormat;	/* 4 = ASCII */
 	unsigned char DirName[1];
 } DELETE_DIRECTORY_REQ;
@@ -852,7 +852,7 @@ typedef struct smb_com_delete_directory_rsp {
 
 typedef struct smb_com_create_directory_req {
 	struct smb_hdr hdr;	/* wct = 0 */
-	__u16 ByteCount;
+	__le16 ByteCount;
 	__u8 BufferFormat;	/* 4 = ASCII */
 	unsigned char DirName[1];
 } CREATE_DIRECTORY_REQ;
@@ -870,22 +870,22 @@ typedef struct smb_com_transaction_ioctl_req {
 	struct smb_hdr hdr;	/* wct = 23 */
 	__u8 MaxSetupCount;
 	__u16 Reserved;
-	__u32 TotalParameterCount;
-	__u32 TotalDataCount;
-	__u32 MaxParameterCount;
-	__u32 MaxDataCount;
-	__u32 ParameterCount;
-	__u32 ParameterOffset;
-	__u32 DataCount;
-	__u32 DataOffset;
+	__le32 TotalParameterCount;
+	__le32 TotalDataCount;
+	__le32 MaxParameterCount;
+	__le32 MaxDataCount;
+	__le32 ParameterCount;
+	__le32 ParameterOffset;
+	__le32 DataCount;
+	__le32 DataOffset;
 	__u8 SetupCount; /* four setup words follow subcommand */
 	/* SNIA spec incorrectly included spurious pad here */
-	__u16 SubCommand;/* 2 = IOCTL/FSCTL */
-	__u32 FunctionCode;
+	__le16 SubCommand;/* 2 = IOCTL/FSCTL */
+	__le32 FunctionCode;
 	__u16 Fid;
 	__u8 IsFsctl;    /* 1 = File System Control, 0 = device control (IOCTL)*/
 	__u8 IsRootFlag; /* 1 = apply command to root of share (must be DFS share)*/
-	__u16 ByteCount;
+	__le16 ByteCount;
 	__u8 Pad[3];
 	__u8 Data[1];
 } TRANSACT_IOCTL_REQ;
@@ -893,16 +893,16 @@ typedef struct smb_com_transaction_ioctl_req {
 typedef struct smb_com_transaction_ioctl_rsp {
 	struct smb_hdr hdr;	/* wct = 19 */
 	__u8 Reserved[3];
-	__u32 TotalParameterCount;
-	__u32 TotalDataCount;
-	__u32 ParameterCount;
-	__u32 ParameterOffset;
-	__u32 ParameterDisplacement;
-	__u32 DataCount;
-	__u32 DataOffset;
-	__u32 DataDisplacement;
+	__le32 TotalParameterCount;
+	__le32 TotalDataCount;
+	__le32 ParameterCount;
+	__le32 ParameterOffset;
+	__le32 ParameterDisplacement;
+	__le32 DataCount;
+	__le32 DataOffset;
+	__le32 DataDisplacement;
 	__u8 SetupCount;	/* 1 */
-	__u16 ReturnedDataLen;
+	__le16 ReturnedDataLen;
 	__u16 ByteCount;
 	__u8 Pad[3];
 } TRANSACT_IOCTL_RSP;
@@ -911,22 +911,22 @@ typedef struct smb_com_transaction_change_notify_req {
 	struct smb_hdr hdr;     /* wct = 23 */
 	__u8 MaxSetupCount;
 	__u16 Reserved;
-	__u32 TotalParameterCount;
-	__u32 TotalDataCount;
-	__u32 MaxParameterCount;
-	__u32 MaxDataCount;
-	__u32 ParameterCount;
-	__u32 ParameterOffset;
-	__u32 DataCount;
-	__u32 DataOffset;
+	__le32 TotalParameterCount;
+	__le32 TotalDataCount;
+	__le32 MaxParameterCount;
+	__le32 MaxDataCount;
+	__le32 ParameterCount;
+	__le32 ParameterOffset;
+	__le32 DataCount;
+	__le32 DataOffset;
 	__u8 SetupCount; /* four setup words follow subcommand */
 	/* SNIA spec incorrectly included spurious pad here */
-	__u16 SubCommand;/* 4 = Change Notify */
-	__u32 CompletionFilter;  /* operation to monitor */
+	__le16 SubCommand;/* 4 = Change Notify */
+	__le32 CompletionFilter;  /* operation to monitor */
 	__u16 Fid;
 	__u8 WatchTree;  /* 1 = Monitor subdirectories */
 	__u8 Reserved2;
-	__u16 ByteCount;
+	__le16 ByteCount;
 /* __u8 Pad[3];*/
 /*	__u8 Data[1];*/
 } TRANSACT_CHANGE_NOTIFY_REQ;
@@ -934,14 +934,14 @@ typedef struct smb_com_transaction_change_notify_req {
 typedef struct smb_com_transaction_change_notify_rsp {
 	struct smb_hdr hdr;	/* wct = 18 */
 	__u8 Reserved[3];
-	__u32 TotalParameterCount;
-	__u32 TotalDataCount;
-	__u32 ParameterCount;
-	__u32 ParameterOffset;
-	__u32 ParameterDisplacement;
-	__u32 DataCount;
-	__u32 DataOffset;
-	__u32 DataDisplacement;
+	__le32 TotalParameterCount;
+	__le32 TotalDataCount;
+	__le32 ParameterCount;
+	__le32 ParameterOffset;
+	__le32 ParameterDisplacement;
+	__le32 DataCount;
+	__le32 DataOffset;
+	__le32 DataDisplacement;
 	__u8 SetupCount;   /* 0 */
 	__u16 ByteCount;
 	/* __u8 Pad[3]; */
@@ -1090,40 +1090,40 @@ typedef union smb_com_transaction2 {
 
 typedef struct smb_com_transaction2_qpi_req {
 	struct smb_hdr hdr;	/* wct = 14+ */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
-	__u16 MaxParameterCount;
-	__u16 MaxDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
 	__u8 MaxSetupCount;
 	__u8 Reserved;
-	__u16 Flags;
-	__u32 Timeout;
+	__le16 Flags;
+	__le32 Timeout;
 	__u16 Reserved2;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 DataCount;
-	__u16 DataOffset;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 DataCount;
+	__le16 DataOffset;
 	__u8 SetupCount;
 	__u8 Reserved3;
-	__u16 SubCommand;	/* one setup word */
-	__u16 ByteCount;
+	__le16 SubCommand;	/* one setup word */
+	__le16 ByteCount;
 	__u8 Pad;
-	__u16 InformationLevel;
+	__le16 InformationLevel;
 	__u32 Reserved4;
 	char FileName[1];
 } TRANSACTION2_QPI_REQ;
 
 typedef struct smb_com_transaction2_qpi_rsp {
 	struct smb_hdr hdr;	/* wct = 10 + SetupCount */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
-	__u16 Reserved;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 ParameterDisplacement;
-	__u16 DataCount;
-	__u16 DataOffset;
-	__u16 DataDisplacement;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 Reserved;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 ParameterDisplacement;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__le16 DataDisplacement;
 	__u8 SetupCount;
 	__u8 Reserved1;		/* should be zero setup words following */
 	__u16 ByteCount;
@@ -1132,41 +1132,41 @@ typedef struct smb_com_transaction2_qpi_rsp {
 
 typedef struct smb_com_transaction2_spi_req {
 	struct smb_hdr hdr;	/* wct = 15 */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
-	__u16 MaxParameterCount;
-	__u16 MaxDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
 	__u8 MaxSetupCount;
 	__u8 Reserved;
-	__u16 Flags;
-	__u32 Timeout;
+	__le16 Flags;
+	__le32 Timeout;
 	__u16 Reserved2;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 DataCount;
-	__u16 DataOffset;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 DataCount;
+	__le16 DataOffset;
 	__u8 SetupCount;
 	__u8 Reserved3;
-	__u16 SubCommand;	/* one setup word */
-	__u16 ByteCount;
+	__le16 SubCommand;	/* one setup word */
+	__le16 ByteCount;
 	__u8 Pad;
 	__u16 Pad1;
-	__u16 InformationLevel;
+	__le16 InformationLevel;
 	__u32 Reserved4;
 	char FileName[1];
 } TRANSACTION2_SPI_REQ;
 
 typedef struct smb_com_transaction2_spi_rsp {
 	struct smb_hdr hdr;	/* wct = 10 + SetupCount */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
 	__u16 Reserved;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 ParameterDisplacement;
-	__u16 DataCount;
-	__u16 DataOffset;
-	__u16 DataDisplacement;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 ParameterDisplacement;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__le16 DataDisplacement;
 	__u8 SetupCount;
 	__u8 Reserved1;		/* should be zero setup words following */
 	__u16 ByteCount;
@@ -1174,49 +1174,49 @@ typedef struct smb_com_transaction2_spi_rsp {
 } TRANSACTION2_SPI_RSP;
 
 struct set_file_rename {
-	__u32 overwrite;   /* 1 = overwrite dest */
+	__le32 overwrite;   /* 1 = overwrite dest */
 	__u32 root_fid;   /* zero */
-	__u32 target_name_len;
+	__le32 target_name_len;
 	char  target_name[0];  /* Must be unicode */
 };
 
 struct smb_com_transaction2_sfi_req {
 	struct smb_hdr hdr;	/* wct = 15 */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
-	__u16 MaxParameterCount;
-	__u16 MaxDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
 	__u8 MaxSetupCount;
 	__u8 Reserved;
-	__u16 Flags;
-	__u32 Timeout;
+	__le16 Flags;
+	__le32 Timeout;
 	__u16 Reserved2;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 DataCount;
-	__u16 DataOffset;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 DataCount;
+	__le16 DataOffset;
 	__u8 SetupCount;
 	__u8 Reserved3;
-	__u16 SubCommand;	/* one setup word */
-	__u16 ByteCount;
+	__le16 SubCommand;	/* one setup word */
+	__le16 ByteCount;
 	__u8 Pad;
 	__u16 Pad1;
 	__u16 Fid;
-	__u16 InformationLevel;
+	__le16 InformationLevel;
 	__u16 Reserved4;	
 };
 
 struct smb_com_transaction2_sfi_rsp {
 	struct smb_hdr hdr;	/* wct = 10 + SetupCount */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
 	__u16 Reserved;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 ParameterDisplacement;
-	__u16 DataCount;
-	__u16 DataOffset;
-	__u16 DataDisplacement;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 ParameterDisplacement;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__le16 DataDisplacement;
 	__u8 SetupCount;
 	__u8 Reserved1;		/* should be zero setup words following */
 	__u16 ByteCount;
@@ -1240,43 +1240,43 @@ struct smb_com_transaction2_sfi_rsp {
 
 typedef struct smb_com_transaction2_ffirst_req {
 	struct smb_hdr hdr;	/* wct = 15 */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
-	__u16 MaxParameterCount;
-	__u16 MaxDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
 	__u8 MaxSetupCount;
 	__u8 Reserved;
-	__u16 Flags;
-	__u32 Timeout;
+	__le16 Flags;
+	__le32 Timeout;
 	__u16 Reserved2;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 DataCount;
-	__u16 DataOffset;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 DataCount;
+	__le16 DataOffset;
 	__u8 SetupCount;	/* one */
 	__u8 Reserved3;
-	__u16 SubCommand;	/* TRANS2_FIND_FIRST */
-	__u16 ByteCount;
+	__le16 SubCommand;	/* TRANS2_FIND_FIRST */
+	__le16 ByteCount;
 	__u8 Pad;
-	__u16 SearchAttributes;
-	__u16 SearchCount;
-	__u16 SearchFlags;
-	__u16 InformationLevel;
-	__u32 SearchStorageType;
+	__le16 SearchAttributes;
+	__le16 SearchCount;
+	__le16 SearchFlags;
+	__le16 InformationLevel;
+	__le32 SearchStorageType;
 	char FileName[1];
 } TRANSACTION2_FFIRST_REQ;
 
 typedef struct smb_com_transaction2_ffirst_rsp {
 	struct smb_hdr hdr;	/* wct = 10 */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
 	__u16 Reserved;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 ParameterDisplacement;
-	__u16 DataCount;
-	__u16 DataOffset;
-	__u16 DataDisplacement;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 ParameterDisplacement;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__le16 DataDisplacement;
 	__u8 SetupCount;
 	__u8 Reserved1;		/* should be zero setup words following */
 	__u16 ByteCount;
@@ -1284,61 +1284,61 @@ typedef struct smb_com_transaction2_ffirst_rsp {
 
 typedef struct smb_com_transaction2_ffirst_rsp_parms {
 	__u16 SearchHandle;
-	__u16 SearchCount;
-	__u16 EndofSearch;
-	__u16 EAErrorOffset;
-	__u16 LastNameOffset;
+	__le16 SearchCount;
+	__le16 EndofSearch;
+	__le16 EAErrorOffset;
+	__le16 LastNameOffset;
 } T2_FFIRST_RSP_PARMS;
 
 typedef struct smb_com_transaction2_fnext_req {
 	struct smb_hdr hdr;	/* wct = 15 */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
-	__u16 MaxParameterCount;
-	__u16 MaxDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
 	__u8 MaxSetupCount;
 	__u8 Reserved;
-	__u16 Flags;
-	__u32 Timeout;
+	__le16 Flags;
+	__le32 Timeout;
 	__u16 Reserved2;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 DataCount;
-	__u16 DataOffset;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 DataCount;
+	__le16 DataOffset;
 	__u8 SetupCount;	/* one */
 	__u8 Reserved3;
-	__u16 SubCommand;	/* TRANS2_FIND_NEXT */
-	__u16 ByteCount;
+	__le16 SubCommand;	/* TRANS2_FIND_NEXT */
+	__le16 ByteCount;
 	__u8 Pad;
 	__u16 SearchHandle;
-	__u16 SearchCount;
-	__u16 InformationLevel;
+	__le16 SearchCount;
+	__le16 InformationLevel;
 	__u32 ResumeKey;
-	__u16 SearchFlags;
+	__le16 SearchFlags;
 	char ResumeFileName[1];
 } TRANSACTION2_FNEXT_REQ;
 
 typedef struct smb_com_transaction2_fnext_rsp {
 	struct smb_hdr hdr;	/* wct = 10 */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
 	__u16 Reserved;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 ParameterDisplacement;
-	__u16 DataCount;
-	__u16 DataOffset;
-	__u16 DataDisplacement;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 ParameterDisplacement;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__le16 DataDisplacement;
 	__u8 SetupCount;
 	__u8 Reserved1;		/* should be zero setup words following */
 	__u16 ByteCount;
 } TRANSACTION2_FNEXT_RSP;
 
 typedef struct smb_com_transaction2_fnext_rsp_parms {
-	__u16 SearchCount;
-	__u16 EndofSearch;
-	__u16 EAErrorOffset;
-	__u16 LastNameOffset;
+	__le16 SearchCount;
+	__le16 EndofSearch;
+	__le16 EAErrorOffset;
+	__le16 LastNameOffset;
 } T2_FNEXT_RSP_PARMS;
 
 /* QFSInfo Levels */
@@ -1354,38 +1354,38 @@ typedef struct smb_com_transaction2_fnext_rsp_parms {
 
 typedef struct smb_com_transaction2_qfsi_req {
 	struct smb_hdr hdr;	/* wct = 14+ */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
-	__u16 MaxParameterCount;
-	__u16 MaxDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
 	__u8 MaxSetupCount;
 	__u8 Reserved;
-	__u16 Flags;
-	__u32 Timeout;
+	__le16 Flags;
+	__le32 Timeout;
 	__u16 Reserved2;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 DataCount;
-	__u16 DataOffset;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 DataCount;
+	__le16 DataOffset;
 	__u8 SetupCount;
 	__u8 Reserved3;
-	__u16 SubCommand;	/* one setup word */
-	__u16 ByteCount;
+	__le16 SubCommand;	/* one setup word */
+	__le16 ByteCount;
 	__u8 Pad;
-	__u16 InformationLevel;
+	__le16 InformationLevel;
 } TRANSACTION2_QFSI_REQ;
 
 typedef struct smb_com_transaction_qfsi_rsp {
 	struct smb_hdr hdr;	/* wct = 10 + SetupCount */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
 	__u16 Reserved;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 ParameterDisplacement;
-	__u16 DataCount;
-	__u16 DataOffset;
-	__u16 DataDisplacement;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 ParameterDisplacement;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__le16 DataDisplacement;
 	__u8 SetupCount;
 	__u8 Reserved1;		/* should be zero setup words following */
 	__u16 ByteCount;
@@ -1394,58 +1394,58 @@ typedef struct smb_com_transaction_qfsi_rsp {
 
 typedef struct smb_com_transaction2_get_dfs_refer_req {
 	struct smb_hdr hdr;	/* wct = 15 */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
-	__u16 MaxParameterCount;
-	__u16 MaxDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
+	__le16 MaxParameterCount;
+	__le16 MaxDataCount;
 	__u8 MaxSetupCount;
 	__u8 Reserved;
-	__u16 Flags;
-	__u32 Timeout;
+	__le16 Flags;
+	__le32 Timeout;
 	__u16 Reserved2;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 DataCount;
-	__u16 DataOffset;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 DataCount;
+	__le16 DataOffset;
 	__u8 SetupCount;
 	__u8 Reserved3;
-	__u16 SubCommand;	/* one setup word */
-	__u16 ByteCount;
+	__le16 SubCommand;	/* one setup word */
+	__le16 ByteCount;
 	__u8 Pad[3];		/* Win2K has sent 0x0F01 (max resp length perhaps?) followed by one byte pad - doesn't seem to matter though */
-	__u16 MaxReferralLevel;
+	__le16 MaxReferralLevel;
 	char RequestFileName[1];
 } TRANSACTION2_GET_DFS_REFER_REQ;
 
 typedef struct dfs_referral_level_3 {
-	__u16 VersionNumber;
-	__u16 ReferralSize;
-	__u16 ServerType;	/* 0x0001 = CIFS server */
-	__u16 ReferralFlags;	/* or proximity - not clear which since always set to zero - SNIA spec says 0x01 means strip off PathConsumed chars before submitting RequestFileName to remote node */
-	__u16 TimeToLive;
-	__u16 Proximity;
-	__u16 DfsPathOffset;
-	__u16 DfsAlternatePathOffset;
-	__u16 NetworkAddressOffset;
+	__le16 VersionNumber;
+	__le16 ReferralSize;
+	__le16 ServerType;	/* 0x0001 = CIFS server */
+	__le16 ReferralFlags;	/* or proximity - not clear which since always set to zero - SNIA spec says 0x01 means strip off PathConsumed chars before submitting RequestFileName to remote node */
+	__le16 TimeToLive;
+	__le16 Proximity;
+	__le16 DfsPathOffset;
+	__le16 DfsAlternatePathOffset;
+	__le16 NetworkAddressOffset;
 } REFERRAL3;
 
 typedef struct smb_com_transaction_get_dfs_refer_rsp {
 	struct smb_hdr hdr;	/* wct = 10 */
-	__u16 TotalParameterCount;
-	__u16 TotalDataCount;
+	__le16 TotalParameterCount;
+	__le16 TotalDataCount;
 	__u16 Reserved;
-	__u16 ParameterCount;
-	__u16 ParameterOffset;
-	__u16 ParameterDisplacement;
-	__u16 DataCount;
-	__u16 DataOffset;
-	__u16 DataDisplacement;
+	__le16 ParameterCount;
+	__le16 ParameterOffset;
+	__le16 ParameterDisplacement;
+	__le16 DataCount;
+	__le16 DataOffset;
+	__le16 DataDisplacement;
 	__u8 SetupCount;
 	__u8 Reserved1;		/* zero setup words following */
 	__u16 ByteCount;
 	__u8 Pad;
-	__u16 PathConsumed;
-	__u16 NumberOfReferrals;
-	__u16 DFSFlags;
+	__le16 PathConsumed;
+	__le16 NumberOfReferrals;
+	__le16 DFSFlags;
 	__u16 Pad2;
 	REFERRAL3 referrals[1];	/* array of level 3 dfs_referral structures */
 	/* followed by the strings pointed to by the referral structures */
@@ -1531,16 +1531,16 @@ struct aliasInfo92 {
 };
 
 typedef struct {
-	__u64 TotalAllocationUnits;
-	__u64 FreeAllocationUnits;
-	__u32 SectorsPerAllocationUnit;
-	__u32 BytesPerSector;
+	__le64 TotalAllocationUnits;
+	__le64 FreeAllocationUnits;
+	__le32 SectorsPerAllocationUnit;
+	__le32 BytesPerSector;
 } FILE_SYSTEM_INFO;		/* size info, level 0x103 */
 
 typedef struct {
-	__u16 MajorVersionNumber;
-	__u16 MinorVersionNumber;
-	__u64 Capability;
+	__le16 MajorVersionNumber;
+	__le16 MinorVersionNumber;
+	__le64 Capability;
 } FILE_SYSTEM_UNIX_INFO;	/* Unix extensions info, level 0x200 */
 /* Linux/Unix extensions capability flags */
 #define CIFS_UNIX_FCNTL_CAP             0x00000001 /* support for fcntl locks */
@@ -1567,55 +1567,55 @@ typedef struct {
 #define FILE_DEVICE_NETWORK_REDIRECTOR  0x00000028
 
 typedef struct {
-	__u32 DeviceType;
-	__u32 DeviceCharacteristics;
+	__le32 DeviceType;
+	__le32 DeviceCharacteristics;
 } FILE_SYSTEM_DEVICE_INFO;	/* device info, level 0x104 */
 
 typedef struct {
-	__u32 Attributes;
-	__u32 MaxPathNameComponentLength;
-	__u32 FileSystemNameLen;
+	__le32 Attributes;
+	__le32 MaxPathNameComponentLength;
+	__le32 FileSystemNameLen;
 	char FileSystemName[52];	/* do not really need to save this - so potentially get only subset of name */
 } FILE_SYSTEM_ATTRIBUTE_INFO;
 
 typedef struct {		/* data block encoding of response to level 263 QPathInfo */
-	__u64 CreationTime;
-	__u64 LastAccessTime;
-	__u64 LastWriteTime;
-	__u64 ChangeTime;
-	__u32 Attributes;
+	__le64 CreationTime;
+	__le64 LastAccessTime;
+	__le64 LastWriteTime;
+	__le64 ChangeTime;
+	__le32 Attributes;
 	__u32 Pad1;
-	__u64 AllocationSize;
-	__u64 EndOfFile;	/* size ie offset to first free byte in file */
-	__u32 NumberOfLinks;	/* hard links */
+	__le64 AllocationSize;
+	__le64 EndOfFile;	/* size ie offset to first free byte in file */
+	__le32 NumberOfLinks;	/* hard links */
 	__u8 DeletePending;
 	__u8 Directory;
 	__u16 Pad2;
 	__u64 IndexNumber;
-	__u32 EASize;
-	__u32 AccessFlags;
+	__le32 EASize;
+	__le32 AccessFlags;
 	__u64 IndexNumber1;
-	__u64 CurrentByteOffset;
-	__u32 Mode;
-	__u32 AlignmentRequirement;
-	__u32 FileNameLength;
+	__le64 CurrentByteOffset;
+	__le32 Mode;
+	__le32 AlignmentRequirement;
+	__le32 FileNameLength;
 	char FileName[1];
 } FILE_ALL_INFO;		/* level 263 QPathInfo */
 
 typedef struct {
-	__u64 EndOfFile;
-	__u64 NumOfBytes;
-	__u64 LastStatusChange;	/*SNIA spec says DCE time for the three time fields */
-	__u64 LastAccessTime;
-	__u64 LastModificationTime;
-	__u64 Uid;
-	__u64 Gid;
-	__u32 Type;
-	__u64 DevMajor;
-	__u64 DevMinor;
+	__le64 EndOfFile;
+	__le64 NumOfBytes;
+	__le64 LastStatusChange;	/*SNIA spec says DCE time for the three time fields */
+	__le64 LastAccessTime;
+	__le64 LastModificationTime;
+	__le64 Uid;
+	__le64 Gid;
+	__le32 Type;
+	__le64 DevMajor;
+	__le64 DevMinor;
 	__u64 UniqueId;
-	__u64 Permissions;
-	__u64 Nlinks;
+	__le64 Permissions;
+	__le64 Nlinks;
 } FILE_UNIX_BASIC_INFO;		/* level 512 QPathInfo */
 
 typedef struct {
@@ -1645,52 +1645,52 @@ typedef struct {
 #define UNIX_SOCKET    6
 
 typedef struct {
-	__u32 NextEntryOffset;
-	__u32 ResumeKey;
-	__u64 EndOfFile;
-	__u64 NumOfBytes;
-	__u64 LastStatusChange;	/*SNIA spec says DCE time for the three time fields */
-	__u64 LastAccessTime;
-	__u64 LastModificationTime;
-	__u64 Uid;
-	__u64 Gid;
-	__u32 Type;
-	__u64 DevMajor;
-	__u64 DevMinor;
-	__u64 UniqueId;
-	__u64 Permissions;
-	__u64 Nlinks;
+	__le32 NextEntryOffset;
+	__le32 ResumeKey;
+	__le64 EndOfFile;
+	__le64 NumOfBytes;
+	__le64 LastStatusChange;	/*SNIA spec says DCE time for the three time fields */
+	__le64 LastAccessTime;
+	__le64 LastModificationTime;
+	__le64 Uid;
+	__le64 Gid;
+	__le32 Type;
+	__le64 DevMajor;
+	__le64 DevMinor;
+	__le64 UniqueId;
+	__le64 Permissions;
+	__le64 Nlinks;
 	char FileName[1];
 } FILE_UNIX_INFO;
 
 typedef struct {
-	__u64 CreationTime;
-	__u64 LastAccessTime;
-	__u64 LastWriteTime;
-	__u64 ChangeTime;
-	__u32 Attributes;
+	__le64 CreationTime;
+	__le64 LastAccessTime;
+	__le64 LastWriteTime;
+	__le64 ChangeTime;
+	__le32 Attributes;
 	__u32 Pad;
 } FILE_BASIC_INFO;		/* size info, level 0x101 */
 
 struct file_allocation_info {
-	__u64 AllocationSize;
+	__le64 AllocationSize;
 };		/* size info, level 0x103 */
 
 struct file_end_of_file_info {
-	__u64 FileSize;		/* offset to end of file */
+	__le64 FileSize;		/* offset to end of file */
 };	/* size info, level 0x104 */
 
 typedef struct {
-	__u32 NextEntryOffset;
+	__le32 NextEntryOffset;
 	__u32 FileIndex;
-	__u64 CreationTime;
-	__u64 LastAccessTime;
-	__u64 LastWriteTime;
-	__u64 ChangeTime;
-	__u64 EndOfFile;
-	__u64 AllocationSize;
-	__u32 ExtFileAttributes;
-	__u32 FileNameLength;
+	__le64 CreationTime;
+	__le64 LastAccessTime;
+	__le64 LastWriteTime;
+	__le64 ChangeTime;
+	__le64 EndOfFile;
+	__le64 AllocationSize;
+	__le32 ExtFileAttributes;
+	__le32 FileNameLength;
 	char FileName[1];
 } FILE_DIRECTORY_INFO;   /* level 257 FF response data area */
 
@@ -1707,7 +1707,7 @@ struct gealist {
 struct fea {
 	unsigned char EA_flags;
 	__u8 name_len;
-	__u16 value_len;
+	__le16 value_len;
 	char name[1];
 	/* optionally followed by value */
 };
@@ -1715,7 +1715,7 @@ struct fea {
 #define FEA_NEEDEA         0x80	/* need EA bit */
 
 struct fealist {
-	__u32 list_len;
+	__le32 list_len;
 	struct fea list[1];
 };
 
@@ -1726,6 +1726,7 @@ struct data_blob {
 	void (*free) (struct data_blob * data_blob);
 };
 
+
 #ifdef CONFIG_CIFS_POSIX
 /* 
 	For better POSIX semantics from Linux client, (even better
@@ -1774,9 +1775,9 @@ struct data_blob {
 	
 	COPY (note support for copy across directories) - FUTURE, OPTIONAL
 	setting/getting OS/2 EAs - FUTURE (BB can this handle
-	        setting Linux xattrs perfectly)         - OPTIONAL
-    dnotify                                         - FUTURE, OPTIONAL
-    quota                                           - FUTURE, OPTIONAL
+	setting Linux xattrs perfectly)         - OPTIONAL
+	dnotify                                 - FUTURE, OPTIONAL
+	quota                                   - FUTURE, OPTIONAL
 			
 	Note that various requests implemented for NT interop such as 
 		NT_TRANSACT (IOCTL) QueryReparseInfo
@@ -1801,6 +1802,34 @@ struct data_blob {
 	
 	
  */
+
+/* xsymlink is a symlink format that can be used
+   to save symlink info in a regular file when 
+   mounted to operating systems that do not
+   support the cifs Unix extensions or EAs (for xattr
+   based symlinks).  For such a file to be recognized
+   as containing symlink data: 
+
+   1) file size must be 1067, 
+   2) signature must begin file data,
+   3) length field must be set to ASCII representation
+	of a number which is less than or equal to 1024, 
+   4) md5 must match that of the path data */
+
+struct xsymlink {
+	/* 1067 bytes */
+	char signature[4]; /* XSym */ /* not null terminated */
+	char cr0;         /* \n */
+/* ASCII representation of length (4 bytes decimal) terminated by \n not null */
+	char length[4];
+	char cr1;         /* \n */
+/* md5 of valid subset of path ie path[0] through path[length-1] */
+	__u8 md5[32];    
+	char cr2;        /* \n */
+/* if room left, then end with \n then 0x20s by convention but not required */
+	char path[1024];  
+};
+
 #endif 
 
 #pragma pack()			/* resume default structure packing */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 827370077..572b6a404 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -37,7 +37,7 @@ extern int smb_send(struct socket *, struct smb_hdr *,
 extern unsigned int _GetXid(void);
 extern void _FreeXid(unsigned int);
 #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
-#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,rc));}
+#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,(int)rc));}
 extern char *build_path_from_dentry(struct dentry *);
 extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
 extern void renew_parental_timestamps(struct dentry *direntry);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index dc9e0fd4e..8e1718538 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -183,6 +183,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
 	int rc = 0;
 	int bytes_returned;
 	struct TCP_Server_Info * server;
+	u16 count;
 
 	if(ses->server)
 		server = ses->server;
@@ -199,12 +200,12 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
 	if (extended_security)
 		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
 
-	pSMB->ByteCount = strlen(protocols[0].name) + 1;
+	count = strlen(protocols[0].name) + 1;
 	strncpy(pSMB->DialectsArray, protocols[0].name, 30);	
     /* null guaranteed to be at end of source and target buffers anyway */
 
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += count;
+	pSMB->ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -234,10 +235,12 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
 
 		/* BB might be helpful to save off the domain of server here */
 
-		if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) {
-			if (pSMBr->ByteCount < 16)
+		if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && 
+			(server->capabilities & CAP_EXTENDED_SECURITY)) {
+			count = pSMBr->ByteCount;
+			if (count < 16)
 				rc = -EIO;
-			else if (pSMBr->ByteCount == 16) {
+			else if (count == 16) {
 				server->secType = RawNTLMSSP;
 				if (server->socketUseCount.counter > 1) {
 					if (memcmp
@@ -260,8 +263,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
 				rc = decode_negTokenInit(pSMBr->u.
 							 extended_response.
 							 SecurityBlob,
-							 pSMBr->ByteCount -
-							 16, &server->secType);
+							 count - 16,
+							 &server->secType);
 			}
 		} else
 			server->capabilities &= ~CAP_EXTENDED_SECURITY;
@@ -365,9 +368,12 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
 
 	rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL /* no tcon anymore */,
 		 (void **) &pSMB, (void **) &smb_buffer_response);
-
-	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
-		pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+	
+	if(ses->server) {
+		if(ses->server->secMode & 
+		   (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+			pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+	}
 
 	if (rc) {
 		up(&ses->sesSem);
@@ -430,10 +436,9 @@ DelFileRetry:
 	}
 	pSMB->SearchAttributes =
 	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
-	pSMB->ByteCount = name_len + 1;
 	pSMB->BufferFormat = 0x04;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += name_len + 1;
+	pSMB->ByteCount = cpu_to_le16(name_len + 1);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -482,10 +487,9 @@ RmDirRetry:
 		strncpy(pSMB->DirName, dirName, name_len);
 	}
 
-	pSMB->ByteCount = name_len + 1;
 	pSMB->BufferFormat = 0x04;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += name_len + 1;
+	pSMB->ByteCount = cpu_to_le16(name_len + 1);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -533,10 +537,9 @@ MkDirRetry:
 		strncpy(pSMB->DirName, name, name_len);
 	}
 
-	pSMB->ByteCount = name_len + 1 /* for buf format */ ;
 	pSMB->BufferFormat = 0x04;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += name_len + 1;
+	pSMB->ByteCount = cpu_to_le16(name_len + 1);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -566,6 +569,7 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
 	OPEN_RSP *pSMBr = NULL;
 	int bytes_returned;
 	int name_len;
+	__u16 count;
 
 openRetry:
 	rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
@@ -576,7 +580,7 @@ openRetry:
 	pSMB->AndXCommand = 0xFF;	/* none */
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-		pSMB->ByteCount = 1;	/* account for one byte pad to word boundary */
+		count = 1;	/* account for one byte pad to word boundary */
 		name_len =
 		    cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
 				  fileName, 530
@@ -586,7 +590,7 @@ openRetry:
 		name_len *= 2;
 		pSMB->NameLength = cpu_to_le16(name_len);
 	} else {		/* BB improve the check for buffer overruns BB */
-		pSMB->ByteCount = 0;	/* no pad */
+		count = 0;	/* no pad */
 		name_len = strnlen(fileName, 530);
 		name_len++;	/* trailing null */
 		pSMB->NameLength = cpu_to_le16(name_len);
@@ -599,30 +603,29 @@ openRetry:
 	}
 	pSMB->DesiredAccess = cpu_to_le32(access_flags);
 	pSMB->AllocationSize = 0;
-	pSMB->FileAttributes = ATTR_NORMAL;
+	pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
 	/* XP does not handle ATTR_POSIX_SEMANTICS */
 	/* but it helps speed up case sensitive checks for other
 	servers such as Samba */
 	if (tcon->ses->capabilities & CAP_UNIX)
-		pSMB->FileAttributes |= ATTR_POSIX_SEMANTICS;
+		pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
 
 	/* if ((omode & S_IWUGO) == 0)
-		pSMB->FileAttributes |= ATTR_READONLY;*/
+		pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
 	/*  Above line causes problems due to vfs splitting create into two
 		pieces - need to set mode after file created not while it is
 		being created */
-	pSMB->FileAttributes = cpu_to_le32(pSMB->FileAttributes);
 	pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
 	pSMB->CreateDisposition = cpu_to_le32(openDisposition);
 	pSMB->CreateOptions = cpu_to_le32(create_options);
 	pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);	/* BB ??*/
 	pSMB->SecurityFlags =
-	    cpu_to_le32(SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY);
+	    SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
 
-	pSMB->ByteCount += name_len;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+	count += name_len;
+	pSMB->hdr.smb_buf_length += count;
 
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->ByteCount = cpu_to_le16(count);
 	/* long_op set to 1 to allow for oplock break timeouts */
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
@@ -694,24 +697,24 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
 	if (rc) {
 		cERROR(1, ("Send error in read = %d", rc));
 	} else {
-		pSMBr->DataLength = le16_to_cpu(pSMBr->DataLength);
-		*nbytes = pSMBr->DataLength;
+		__u16 data_length = le16_to_cpu(pSMBr->DataLength);
+		*nbytes = data_length;
 		/*check that DataLength would not go beyond end of SMB */
-		if ((pSMBr->DataLength > CIFS_MAX_MSGSIZE) 
-				|| (pSMBr->DataLength > count)) {
-			cFYI(1,("bad length %d for count %d",pSMBr->DataLength,count));
+		if ((data_length > CIFS_MAX_MSGSIZE) 
+				|| (data_length > count)) {
+			cFYI(1,("bad length %d for count %d",data_length,count));
 			rc = -EIO;
 			*nbytes = 0;
 		} else {
 			pReadData =
 			    (char *) (&pSMBr->hdr.Protocol) +
 			    le16_to_cpu(pSMBr->DataOffset);
-/*			if(rc = copy_to_user(buf, pReadData, pSMBr->DataLength)) {
+/*			if(rc = copy_to_user(buf, pReadData, data_length)) {
 				cERROR(1,("Faulting on read rc = %d",rc));
 				rc = -EFAULT;
 			}*/ /* can not use copy_to_user when using page cache*/
 			if(*buf)
-			    memcpy(*buf,pReadData,pSMBr->DataLength);
+			    memcpy(*buf,pReadData,data_length);
 		}
 	}
 	if (pSMB) {
@@ -736,6 +739,8 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
 	WRITE_REQ *pSMB = NULL;
 	WRITE_RSP *pSMBr = NULL;
 	int bytes_returned;
+	unsigned bytes_sent;
+	__u16 byte_count;
 
 	rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
 		      (void **) &pSMBr);
@@ -750,21 +755,20 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
 	pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
 	pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
 	pSMB->Remaining = 0;
-	if (count > ((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00))
-		pSMB->DataLengthLow =
-		    (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00;
-	else
-		pSMB->DataLengthLow = count;
+	bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF;
+	if (bytes_sent > count)
+		bytes_sent = count;
 	pSMB->DataLengthHigh = 0;
 	pSMB->DataOffset =
 	    cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
 
-	memcpy(pSMB->Data,buf,pSMB->DataLengthLow);
+	memcpy(pSMB->Data,buf,bytes_sent);
 
-	pSMB->ByteCount += pSMB->DataLengthLow + 1 /* pad */ ;
-	pSMB->DataLengthLow = cpu_to_le16(pSMB->DataLengthLow);
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	byte_count = bytes_sent + 1 /* pad */ ;
+	pSMB->DataLengthLow = cpu_to_le16(bytes_sent);
+	pSMB->DataLengthHigh = 0;
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
@@ -794,7 +798,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
 	LOCK_RSP *pSMBr = NULL;
 	int bytes_returned;
 	int timeout = 0;
-	__u64 temp;
+	__u16 count;
 
 	cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
 	rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
@@ -807,33 +811,31 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
 		pSMB->Timeout = 0;
 	} else if (waitFlag == TRUE) {
 		timeout = 3;  /* blocking operation, no timeout */
-		pSMB->Timeout = -1; /* blocking - do not time out */
+		pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
 	} else {
 		pSMB->Timeout = 0;
 	}
 
-	pSMB->NumberOfLocks = cpu_to_le32(numLock);
-	pSMB->NumberOfUnlocks = cpu_to_le32(numUnlock);
+	pSMB->NumberOfLocks = cpu_to_le16(numLock);
+	pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
 	pSMB->LockType = lockType;
 	pSMB->AndXCommand = 0xFF;	/* none */
 	pSMB->Fid = smb_file_id; /* netfid stays le */
 
-	if(numLock != 0) {
+	if((numLock != 0) || (numUnlock != 0)) {
 		pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
 		/* BB where to store pid high? */
-		temp = cpu_to_le64(len);
-		pSMB->Locks[0].LengthLow = (__u32)(temp & 0xFFFFFFFF);
-		pSMB->Locks[0].LengthHigh =  (__u32)(temp>>32);
-		temp = cpu_to_le64(offset);
-		pSMB->Locks[0].OffsetLow = (__u32)(temp & 0xFFFFFFFF);
-		pSMB->Locks[0].OffsetHigh = (__u32)(temp>>32);
-		pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE);
+		pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
+		pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
+		pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
+		pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
+		count = sizeof(LOCKING_ANDX_RANGE);
 	} else {
 		/* oplock break */
-		pSMB->ByteCount = 0;
+		count = 0;
 	}
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += count;
+	pSMB->ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
@@ -897,6 +899,7 @@ CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
 	RENAME_RSP *pSMBr = NULL;
 	int bytes_returned;
 	int name_len, name_len2;
+	__u16 count;
 
 	cFYI(1, ("In CIFSSMBRename"));
 renameRetry:
@@ -938,9 +941,9 @@ renameRetry:
 		name_len2++;	/* signature byte */
 	}
 
-	pSMB->ByteCount = 1 /* 1st signature byte */  + name_len + name_len2;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	count = 1 /* 1st signature byte */  + name_len + name_len2;
+	pSMB->hdr.smb_buf_length += count;
+	pSMB->ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -974,6 +977,7 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
 	int rc = 0;
 	int bytes_returned = 0;
 	int len_of_str;
+	__u16 params, param_offset, offset, count, byte_count;
 
 	cFYI(1, ("Rename to File by handle"));
 	rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
@@ -981,28 +985,27 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
 	if (rc)
 		return rc;
 
-	pSMB->ParameterCount = 6;
+	params = 6;
 	pSMB->MaxSetupCount = 0;
 	pSMB->Reserved = 0;
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
-				Fid) - 4;
-	pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+	offset = param_offset + params;
 
-	data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
+	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
 	rename_info = (struct set_file_rename *) data_offset;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
-	pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount;
-	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+	byte_count = 3 /* pad */  + params;
+	pSMB->ParameterCount = cpu_to_le16(params);
 	pSMB->TotalParameterCount = pSMB->ParameterCount;
-	pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
-	pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
 	/* construct random name ".cifs_tmp<inodenum><mid>" */
 	rename_info->overwrite = cpu_to_le32(1);
 	rename_info->root_fid  = 0;
@@ -1014,16 +1017,16 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
 		len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, 530, nls_codepage);
 	}
 	rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
-	pSMB->DataCount = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
-	pSMB->ByteCount += pSMB->DataCount;
-	pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+	count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
+	byte_count += count;
+	pSMB->DataCount = cpu_to_le16(count);
 	pSMB->TotalDataCount = pSMB->DataCount;
 	pSMB->Fid = netfid;
 	pSMB->InformationLevel =
 		cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -1053,6 +1056,7 @@ CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
 	COPY_RSP *pSMBr = NULL;
 	int bytes_returned;
 	int name_len, name_len2;
+	__u16 count;
 
 	cFYI(1, ("In CIFSSMBCopy"));
 copyRetry:
@@ -1064,9 +1068,7 @@ copyRetry:
 	pSMB->BufferFormat = 0x04;
 	pSMB->Tid2 = target_tid;
 
-	if(flags & COPY_TREE)
-		pSMB->Flags |= COPY_TREE;
-	pSMB->Flags = cpu_to_le16(pSMB->Flags);
+	pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
 
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName, 
@@ -1095,15 +1097,15 @@ copyRetry:
 		name_len2++;    /* signature byte */
 	}
 
-	pSMB->ByteCount = 1 /* 1st signature byte */  + name_len + name_len2;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	count = 1 /* 1st signature byte */  + name_len + name_len2;
+	pSMB->hdr.smb_buf_length += count;
+	pSMB->ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 		(struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cFYI(1, ("Send error in copy = %d with %d files copied",
-			rc, pSMBr->CopyCount));
+			rc, le16_to_cpu(pSMBr->CopyCount)));
 	}
 	if (pSMB)
 		cifs_buf_release(pSMB);
@@ -1126,6 +1128,7 @@ CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
 	int name_len_target;
 	int rc = 0;
 	int bytes_returned = 0;
+	__u16 params, param_offset, offset, byte_count;
 
 	cFYI(1, ("In Symlink Unix style"));
 createSymLinkRetry:
@@ -1147,17 +1150,17 @@ createSymLinkRetry:
 		name_len++;	/* trailing null */
 		strncpy(pSMB->FileName, fromName, name_len);
 	}
-	pSMB->ParameterCount = 6 + name_len;
+	params = 6 + name_len;
 	pSMB->MaxSetupCount = 0;
 	pSMB->Reserved = 0;
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+	param_offset = offsetof(struct smb_com_transaction2_spi_req,
                                      InformationLevel) - 4;
-	pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+	offset = param_offset + params;
 
-	data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
+	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len_target =
 		    cifs_strtoUCS((wchar_t *) data_offset, toName, 530
@@ -1171,24 +1174,23 @@ createSymLinkRetry:
 		strncpy(data_offset, toName, name_len_target);
 	}
 
-	pSMB->DataCount = name_len_target;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	/* BB find exact max on data count below from sess */
 	pSMB->MaxDataCount = cpu_to_le16(1000);
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
-	pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
-	pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
-	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+	byte_count = 3 /* pad */  + params + name_len_target;
+	pSMB->DataCount = cpu_to_le16(name_len_target);
+	pSMB->ParameterCount = cpu_to_le16(params);
 	pSMB->TotalDataCount = pSMB->DataCount;
 	pSMB->TotalParameterCount = pSMB->ParameterCount;
-	pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
-	pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -1218,6 +1220,7 @@ CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
 	int name_len_target;
 	int rc = 0;
 	int bytes_returned = 0;
+	__u16 params, param_offset, offset, byte_count;
 
 	cFYI(1, ("In Create Hard link Unix style"));
 createHardLinkRetry:
@@ -1238,17 +1241,17 @@ createHardLinkRetry:
 		name_len++;	/* trailing null */
 		strncpy(pSMB->FileName, toName, name_len);
 	}
-	pSMB->ParameterCount = 6 + name_len;
+	params = 6 + name_len;
 	pSMB->MaxSetupCount = 0;
 	pSMB->Reserved = 0;
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+	param_offset = offsetof(struct smb_com_transaction2_spi_req,
                                      InformationLevel) - 4;
-	pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+	offset = param_offset + params;
 
-	data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
+	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
 	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
 		name_len_target =
 		    cifs_strtoUCS((wchar_t *) data_offset, fromName, 530
@@ -1262,24 +1265,23 @@ createHardLinkRetry:
 		strncpy(data_offset, fromName, name_len_target);
 	}
 
-	pSMB->DataCount = name_len_target;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	/* BB find exact max on data count below from sess*/
 	pSMB->MaxDataCount = cpu_to_le16(1000);
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
-	pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
-	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+	byte_count = 3 /* pad */  + params + name_len_target;
+	pSMB->ParameterCount = cpu_to_le16(params);
 	pSMB->TotalParameterCount = pSMB->ParameterCount;
-	pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+	pSMB->DataCount = cpu_to_le16(name_len_target);
 	pSMB->TotalDataCount = pSMB->DataCount;
-	pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
-	pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -1304,6 +1306,7 @@ CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
 	RENAME_RSP *pSMBr = NULL;
 	int bytes_returned;
 	int name_len, name_len2;
+	__u16 count;
 
 	cFYI(1, ("In CIFSCreateHardLink"));
 winCreateHardLinkRetry:
@@ -1348,9 +1351,9 @@ winCreateHardLinkRetry:
 		name_len2++;	/* signature byte */
 	}
 
-	pSMB->ByteCount = 1 /* string type byte */  + name_len + name_len2;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	count = 1 /* string type byte */  + name_len + name_len2;
+	pSMB->hdr.smb_buf_length += count;
+	pSMB->ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -1377,6 +1380,7 @@ CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
 	int rc = 0;
 	int bytes_returned;
 	int name_len;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
 
@@ -1399,8 +1403,7 @@ querySymLinkRetry:
 		strncpy(pSMB->FileName, searchName, name_len);
 	}
 
-	pSMB->TotalParameterCount =
-	    2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
+	params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
 	pSMB->TotalDataCount = 0;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	/* BB find exact max data count below from sess structure BB */
@@ -1417,38 +1420,38 @@ querySymLinkRetry:
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
-	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
 	} else {		/* decode response */
-		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
-		pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
-		if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
+		__u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
+		__u16 count = le16_to_cpu(pSMBr->DataCount);
+		if ((pSMBr->ByteCount < 2) || (data_offset > 512))
 		/* BB also check enough total bytes returned */
 			rc = -EIO;	/* bad smb */
 		else {
 			if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
 				name_len = UniStrnlen((wchar_t *) ((char *)
-					&pSMBr->hdr.Protocol +pSMBr->DataOffset),
-					min_t(const int, buflen,pSMBr->DataCount) / 2);
+					&pSMBr->hdr.Protocol +data_offset),
+					min_t(const int, buflen,count) / 2);
 				cifs_strfromUCS_le(symlinkinfo,
 					(wchar_t *) ((char *)&pSMBr->hdr.Protocol +
-						pSMBr->DataOffset),
+						data_offset),
 					name_len, nls_codepage);
 			} else {
 				strncpy(symlinkinfo,
 					(char *) &pSMBr->hdr.Protocol + 
-						pSMBr->DataOffset,
-					min_t(const int, buflen, pSMBr->DataCount));
+						data_offset,
+					min_t(const int, buflen, count));
 			}
 			symlinkinfo[buflen] = 0;
 	/* just in case so calling code does not go off the end of buffer */
@@ -1505,16 +1508,16 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
 	if (rc) {
 		cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
 	} else {		/* decode response */
-		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
-		pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
-		if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
+		__u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
+		__u32 data_count = le32_to_cpu(pSMBr->DataCount);
+		if ((pSMBr->ByteCount < 2) || (data_offset > 512))
 		/* BB also check enough total bytes returned */
 			rc = -EIO;	/* bad smb */
 		else {
-			if(pSMBr->DataCount && (pSMBr->DataCount < 2048)) {
+			if(data_count && (data_count < 2048)) {
 		/* could also validate reparse tag && better check name length */
 				struct reparse_data * reparse_buf = (struct reparse_data *)
-					((char *)&pSMBr->hdr.Protocol + pSMBr->DataOffset);
+					((char *)&pSMBr->hdr.Protocol + data_offset);
 				if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
 					name_len = UniStrnlen((wchar_t *)
 							(reparse_buf->LinkNamesBuf + 
@@ -1559,6 +1562,7 @@ CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
 	int rc = 0;
 	int bytes_returned;
 	int name_len;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In QPathInfo path %s", searchName));
 QPathInfoRetry:
@@ -1580,8 +1584,7 @@ QPathInfoRetry:
 		strncpy(pSMB->FileName, searchName, name_len);
 	}
 
-	pSMB->TotalParameterCount = 2 /* level */  + 4 /* reserved */  +
-	    name_len /* includes null */ ;
+	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
 	pSMB->TotalDataCount = 0;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(4000);	/* BB find exact max SMB PDU from sess structure BB */
@@ -1597,29 +1600,29 @@ QPathInfoRetry:
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
-	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cFYI(1, ("Send error in QPathInfo = %d", rc));
 	} else {		/* decode response */
-		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+		__u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
 		/* BB also check enough total bytes returned */
 		/* BB we need to improve the validity checking
 		of these trans2 responses */
-		if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512)) 
+		if ((pSMBr->ByteCount < 40) || (data_offset > 512)) 
 			rc = -EIO;	/* bad smb */
 		else if (pFindData){
 			memcpy((char *) pFindData,
 			       (char *) &pSMBr->hdr.Protocol +
-			       pSMBr->DataOffset, sizeof (FILE_ALL_INFO));
+			       data_offset, sizeof (FILE_ALL_INFO));
 		} else
 		    rc = -ENOMEM;
 	}
@@ -1643,6 +1646,7 @@ CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
 	int rc = 0;
 	int bytes_returned = 0;
 	int name_len;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
 UnixQPathInfoRetry:
@@ -1664,8 +1668,7 @@ UnixQPathInfoRetry:
 		strncpy(pSMB->FileName, searchName, name_len);
 	}
 
-	pSMB->TotalParameterCount = 2 /* level */  + 4 /* reserved */  +
-	    name_len /* includes null */ ;
+	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
 	pSMB->TotalDataCount = 0;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	/* BB find exact max SMB PDU from sess structure BB */
@@ -1682,31 +1685,31 @@ UnixQPathInfoRetry:
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
-	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cFYI(1, ("Send error in QPathInfo = %d", rc));
 	} else {		/* decode response */
-		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+		__u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
 		/* BB also check if enough total bytes returned */
 		if ((pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO)) || 
-			(pSMBr->DataOffset > 512) || 
-			(pSMBr->DataOffset < sizeof(struct smb_hdr))) {
+			(data_offset > 512) || 
+			(data_offset < sizeof(struct smb_hdr))) {
 			cFYI(1,("UnixQPathinfo invalid data offset %d bytes returned %d",
-					(int)pSMBr->DataOffset,bytes_returned));
+					(int)data_offset,bytes_returned));
 			rc = -EIO;	/* bad smb */
 		} else {
 			memcpy((char *) pFindData,
 			       (char *) &pSMBr->hdr.Protocol +
-			       pSMBr->DataOffset,
+			       data_offset,
 			       sizeof (FILE_UNIX_BASIC_INFO));
 		}
 	}
@@ -1729,6 +1732,7 @@ CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
 	int rc = 0;
 	int bytes_returned;
 	int name_len;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In FindUnique"));
 findUniqueRetry:
@@ -1750,7 +1754,7 @@ findUniqueRetry:
 		strncpy(pSMB->FileName, searchName, name_len);
 	}
 
-	pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
+	params = 12 + name_len /* includes null */ ;
 	pSMB->TotalDataCount = 0;	/* no EAs */
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(4000);	/* BB find exact max SMB PDU from sess structure BB */
@@ -1766,8 +1770,8 @@ findUniqueRetry:
 	pSMB->SetupCount = 1;	/* one byte, no need to le convert */
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
-	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalDataCount);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
 	pSMB->SearchAttributes =
 	    cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
@@ -1776,8 +1780,8 @@ findUniqueRetry:
 	pSMB->SearchFlags = cpu_to_le16(1);
 	pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
 	pSMB->SearchStorageType = 0;	/* BB what should we set this to? BB */
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -1810,6 +1814,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
 	int rc = 0;
 	int bytes_returned;
 	int name_len;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In FindFirst"));
 findFirstRetry:
@@ -1831,7 +1836,7 @@ findFirstRetry:
 		strncpy(pSMB->FileName, searchName, name_len);
 	}
 
-	pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
+	params = 12 + name_len /* includes null */ ;
 	pSMB->TotalDataCount = 0;	/* no EAs */
 	pSMB->MaxParameterCount = cpu_to_le16(10);
 	pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
@@ -1841,8 +1846,8 @@ findFirstRetry:
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
 	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct 
         smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
@@ -1867,8 +1872,8 @@ findFirstRetry:
 		*pUnixFlag = FALSE;
 	}
 	pSMB->SearchStorageType = 0;	/* BB what should we set this to? It is not clear if it matters BB */
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -1885,11 +1890,6 @@ findFirstRetry:
 		       (char *) &pSMBr->hdr.Protocol +
 		       le16_to_cpu(pSMBr->ParameterOffset),
 		       sizeof (T2_FFIRST_RSP_PARMS));
-		/* search handle can stay LE and EAoffset not needed so not converted */
-		findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
-		findParms->LastNameOffset =
-		    le16_to_cpu(findParms->LastNameOffset);
-		findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
 		response_data =
 		    (char *) &pSMBr->hdr.Protocol +
 		    le16_to_cpu(pSMBr->DataOffset);
@@ -1916,6 +1916,7 @@ CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
 	char *response_data;
 	int rc = 0;
 	int bytes_returned;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In FindNext"));
 
@@ -1927,7 +1928,8 @@ CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
 	if (rc)
 		return rc;
 
-	pSMB->TotalParameterCount = 14;	/* includes 2 bytes of null string, converted to LE below */
+	params = 14;	/* includes 2 bytes of null string, converted to LE below */
+	byte_count = 0;
 	pSMB->TotalDataCount = 0;	/* no EAs */
 	pSMB->MaxParameterCount = cpu_to_le16(8);
 	pSMB->MaxDataCount =
@@ -1963,15 +1965,15 @@ CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
 	/* BB add check to make sure we do not cross end of smb */
 	if(name_len < CIFS_MAX_MSGSIZE) {
 		memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
-		pSMB->ByteCount += name_len;
+		byte_count += name_len;
 	}
-	pSMB->TotalParameterCount += name_len;
-	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+	params += name_len;
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
 	/* BB improve error handling here */
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -1991,10 +1993,6 @@ CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
 		       (char *) &pSMBr->hdr.Protocol +
 		       le16_to_cpu(pSMBr->ParameterOffset),
 		       sizeof (T2_FNEXT_RSP_PARMS));
-		findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
-		findParms->LastNameOffset =
-		    le16_to_cpu(findParms->LastNameOffset);
-		findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
 		response_data =
 		    (char *) &pSMBr->hdr.Protocol +
 		    le16_to_cpu(pSMBr->DataOffset);
@@ -2060,6 +2058,7 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
 	int name_len;
 	unsigned int i;
 	char * temp;
+	__u16 params, byte_count;
 	*number_of_UNC_in_array = 0;
 	*targetUNCs = NULL;
 
@@ -2096,7 +2095,7 @@ getDFSRetry:
 		strncpy(pSMB->RequestFileName, searchName, name_len);
 	}
 
-	pSMB->ParameterCount = 2 /* level */  + name_len /*includes null */ ;
+	params = 2 /* level */  + name_len /*includes null */ ;
 	pSMB->TotalDataCount = 0;
 	pSMB->DataCount = 0;
 	pSMB->DataOffset = 0;
@@ -2112,12 +2111,12 @@ getDFSRetry:
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
-	pSMB->ByteCount = pSMB->ParameterCount + 3 /* pad */ ;
-	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+	byte_count = params + 3 /* pad */ ;
+	pSMB->ParameterCount = cpu_to_le16(params);
 	pSMB->TotalParameterCount = pSMB->ParameterCount;
 	pSMB->MaxReferralLevel = cpu_to_le16(3);
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
@@ -2125,20 +2124,21 @@ getDFSRetry:
 		cFYI(1, ("Send error in GetDFSRefer = %d", rc));
 	} else {		/* decode response */
 /* BB Add logic to parse referrals here */
-		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
-		pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
+		__u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
+		__u16 data_count = le16_to_cpu(pSMBr->DataCount);
 		cFYI(1,
 		     ("Decoding GetDFSRefer response.  BCC: %d  Offset %d",
-		      pSMBr->ByteCount, pSMBr->DataOffset));
-		if ((pSMBr->ByteCount < 17) || (pSMBr->DataOffset > 512))	/* BB also check enough total bytes returned */
+		      pSMBr->ByteCount, data_offset));
+		if ((pSMBr->ByteCount < 17) || (data_offset > 512))	/* BB also check enough total bytes returned */
 			rc = -EIO;	/* bad smb */
 		else {
 			referrals = 
 			    (struct dfs_referral_level_3 *) 
 					(8 /* sizeof start of data block */ +
-					pSMBr->DataOffset +
+					data_offset +
 					(char *) &pSMBr->hdr.Protocol); 
-			cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",pSMBr->NumberOfReferrals,pSMBr->DFSFlags, referrals->ReferralSize,referrals->ServerType,referrals->ReferralFlags,referrals->TimeToLive));
+			cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",
+				le16_to_cpu(pSMBr->NumberOfReferrals),le16_to_cpu(pSMBr->DFSFlags), le16_to_cpu(referrals->ReferralSize),le16_to_cpu(referrals->ServerType),le16_to_cpu(referrals->ReferralFlags),le16_to_cpu(referrals->TimeToLive)));
 			/* BB This field is actually two bytes in from start of
 			   data block so we could do safety check that DataBlock
 			   begins at address of pSMBr->NumberOfReferrals */
@@ -2152,19 +2152,19 @@ getDFSRetry:
 			name_len = 0;
 			for(i=0;i<*number_of_UNC_in_array;i++) {
 				/* make sure that DfsPathOffset not past end */
-				referrals->DfsPathOffset = le16_to_cpu(referrals->DfsPathOffset);
-				if(referrals->DfsPathOffset > pSMBr->DataCount) {
+				__u16 offset = le16_to_cpu(referrals->DfsPathOffset);
+				if (offset > data_count) {
 					/* if invalid referral, stop here and do 
 					not try to copy any more */
 					*number_of_UNC_in_array = i;
 					break;
 				} 
-				temp = ((char *)referrals) + referrals->DfsPathOffset;
+				temp = ((char *)referrals) + offset;
 
 				if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
-					name_len += UniStrnlen((wchar_t *)temp,pSMBr->DataCount);
+					name_len += UniStrnlen((wchar_t *)temp,data_count);
 				} else {
-					name_len += strnlen(temp,pSMBr->DataCount);
+					name_len += strnlen(temp,data_count);
 				}
 				referrals++;
 				/* BB add check that referral pointer does not fall off end PDU */
@@ -2173,15 +2173,19 @@ getDFSRetry:
 			/* BB add check for name_len bigger than bcc */
 			*targetUNCs = 
 				kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
+			if(*targetUNCs == NULL) {
+				rc = -ENOMEM;
+				goto GetDFSRefExit;
+			}
 			/* copy the ref strings */
 			referrals =  
 			    (struct dfs_referral_level_3 *) 
 					(8 /* sizeof data hdr */ +
-					pSMBr->DataOffset + 
+					data_offset + 
 					(char *) &pSMBr->hdr.Protocol);
 
 			for(i=0;i<*number_of_UNC_in_array;i++) {
-				temp = ((char *)referrals) + referrals->DfsPathOffset;
+				temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
 				if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
 					cifs_strfromUCS_le(*targetUNCs,
 						(wchar_t *) temp, name_len, nls_codepage);
@@ -2196,6 +2200,7 @@ getDFSRetry:
 		}
 
 	}
+GetDFSRefExit:
 	if (pSMB)
 		cifs_buf_release(pSMB);
 
@@ -2215,6 +2220,7 @@ CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
 	FILE_SYSTEM_INFO *response_data;
 	int rc = 0;
 	int bytes_returned = 0;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In QFSInfo"));
 QFSInfoRetry:
@@ -2223,7 +2229,7 @@ QFSInfoRetry:
 	if (rc)
 		return rc;
 
-	pSMB->TotalParameterCount = 2;	/* level */
+	params = 2;	/* level */
 	pSMB->TotalDataCount = 0;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find exact max SMB PDU from sess structure BB */
@@ -2232,8 +2238,8 @@ QFSInfoRetry:
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
@@ -2243,25 +2249,25 @@ QFSInfoRetry:
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cERROR(1, ("Send error in QFSInfo = %d", rc));
 	} else {		/* decode response */
-		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+		__u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
 		cFYI(1,
 		     ("Decoding qfsinfo response.  BCC: %d  Offset %d",
-		      pSMBr->ByteCount, pSMBr->DataOffset));
-		if ((pSMBr->ByteCount < 24) || (pSMBr->DataOffset > 512))	/* BB also check enough total bytes returned */
+		      pSMBr->ByteCount, data_offset));
+		if ((pSMBr->ByteCount < 24) || (data_offset > 512))	/* BB also check enough total bytes returned */
 			rc = -EIO;	/* bad smb */
 		else {
 			response_data =
 			    (FILE_SYSTEM_INFO
 			     *) (((char *) &pSMBr->hdr.Protocol) +
-				 pSMBr->DataOffset);
+				 data_offset);
 			FSData->f_bsize =
 			    le32_to_cpu(response_data->BytesPerSector) *
 			    le32_to_cpu(response_data->
@@ -2296,6 +2302,7 @@ CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon,
 	FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
 	int rc = 0;
 	int bytes_returned = 0;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In QFSAttributeInfo"));
 QFSAttributeRetry:
@@ -2304,7 +2311,7 @@ QFSAttributeRetry:
 	if (rc)
 		return rc;
 
-	pSMB->TotalParameterCount = 2;	/* level */
+	params = 2;	/* level */
 	pSMB->TotalDataCount = 0;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find exact max SMB PDU from sess structure BB */
@@ -2313,8 +2320,8 @@ QFSAttributeRetry:
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
@@ -2324,27 +2331,22 @@ QFSAttributeRetry:
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
 	} else {		/* decode response */
-		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
-		if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {	/* BB also check enough bytes returned */
+		__u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
+		if ((pSMBr->ByteCount < 13) || (data_offset > 512)) {	/* BB also check enough bytes returned */
 			rc = -EIO;	/* bad smb */
 		} else {
 			response_data =
 			    (FILE_SYSTEM_ATTRIBUTE_INFO
 			     *) (((char *) &pSMBr->hdr.Protocol) +
-				 pSMBr->DataOffset);
-			response_data->Attributes = le32_to_cpu(response_data->Attributes);
-			response_data->MaxPathNameComponentLength = 
-				le32_to_cpu(response_data->MaxPathNameComponentLength);
-			response_data->FileSystemNameLen = 
-				le32_to_cpu(response_data->FileSystemNameLen);
+				 data_offset);
 			memcpy(&tcon->fsAttrInfo, response_data,
 			       sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
 		}
@@ -2368,6 +2370,7 @@ CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
 	FILE_SYSTEM_DEVICE_INFO *response_data;
 	int rc = 0;
 	int bytes_returned = 0;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In QFSDeviceInfo"));
 QFSDeviceRetry:
@@ -2376,7 +2379,7 @@ QFSDeviceRetry:
 	if (rc)
 		return rc;
 
-	pSMB->TotalParameterCount = 2;	/* level */
+	params = 2;	/* level */
 	pSMB->TotalDataCount = 0;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find exact max SMB PDU from sess structure BB */
@@ -2385,8 +2388,8 @@ QFSDeviceRetry:
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
 	pSMB->ParameterOffset = cpu_to_le16(offsetof(
         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
@@ -2397,27 +2400,23 @@ QFSDeviceRetry:
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
 	} else {		/* decode response */
-		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+		__u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
 		if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
-                 || (pSMBr->DataOffset > 512))
+                 || (data_offset > 512))
 			rc = -EIO;	/* bad smb */
 		else {
 			response_data =
 			    (FILE_SYSTEM_DEVICE_INFO
 			     *) (((char *) &pSMBr->hdr.Protocol) +
-				 pSMBr->DataOffset);
-			response_data->DeviceType = 
-				le32_to_cpu(response_data->DeviceType);
-			response_data->DeviceCharacteristics = 
-				le32_to_cpu(response_data->DeviceCharacteristics);
+				 data_offset);
 			memcpy(&tcon->fsDevInfo, response_data,
 			       sizeof (FILE_SYSTEM_DEVICE_INFO));
 		}
@@ -2441,6 +2440,7 @@ CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
 	FILE_SYSTEM_UNIX_INFO *response_data;
 	int rc = 0;
 	int bytes_returned = 0;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In QFSUnixInfo"));
 QFSUnixRetry:
@@ -2449,7 +2449,7 @@ QFSUnixRetry:
 	if (rc)
 		return rc;
 
-	pSMB->ParameterCount = 2;	/* level */
+	params = 2;	/* level */
 	pSMB->TotalDataCount = 0;
 	pSMB->DataCount = 0;
 	pSMB->DataOffset = 0;
@@ -2460,8 +2460,8 @@ QFSUnixRetry:
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ByteCount = pSMB->ParameterCount + 1 /* pad */ ;
-	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->ParameterCount = cpu_to_le16(params);
 	pSMB->TotalParameterCount = pSMB->ParameterCount;
 	pSMB->ParameterOffset = cpu_to_le16(offsetof(struct 
         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
@@ -2469,28 +2469,22 @@ QFSUnixRetry:
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
 	pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
 	} else {		/* decode response */
-		pSMBr->DataOffset = cpu_to_le16(pSMBr->DataOffset);
-		if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {
+		__u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
+		if ((pSMBr->ByteCount < 13) || (data_offset > 512)) {
 			rc = -EIO;	/* bad smb */
 		} else {
 			response_data =
 			    (FILE_SYSTEM_UNIX_INFO
 			     *) (((char *) &pSMBr->hdr.Protocol) +
-				 pSMBr->DataOffset);
-			response_data->MajorVersionNumber =
-				le16_to_cpu(response_data->MajorVersionNumber);
-			response_data->MinorVersionNumber =
-				le16_to_cpu(response_data->MinorVersionNumber);
-			response_data->Capability =
-				le64_to_cpu(response_data->Capability);
+				 data_offset);
 			memcpy(&tcon->fsUnixInfo, response_data,
 			       sizeof (FILE_SYSTEM_UNIX_INFO));
 		}
@@ -2521,6 +2515,7 @@ CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
 	int name_len;
 	int rc = 0;
 	int bytes_returned = 0;
+	__u16 params, byte_count, data_count, param_offset, offset;
 
 	cFYI(1, ("In SetEOF"));
 SetEOFRetry:
@@ -2541,8 +2536,8 @@ SetEOFRetry:
 		name_len++;	/* trailing null */
 		strncpy(pSMB->FileName, fileName, name_len);
 	}
-	pSMB->ParameterCount = 6 + name_len;
-	pSMB->DataCount = sizeof (struct file_end_of_file_info);
+	params = 6 + name_len;
+	data_count = sizeof (struct file_end_of_file_info);
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find max SMB size from sess */
 	pSMB->MaxSetupCount = 0;
@@ -2550,9 +2545,9 @@ SetEOFRetry:
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+	param_offset = offsetof(struct smb_com_transaction2_spi_req,
                                      InformationLevel) - 4;
-	pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+	offset = param_offset + params;
 	if(SetAllocation) {
         	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
 	            pSMB->InformationLevel =
@@ -2571,21 +2566,21 @@ SetEOFRetry:
 
 	parm_data =
 	    (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
-				       pSMB->DataOffset);
-	pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
-	pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+				       offset);
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
-	pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
-	pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+	byte_count = 3 /* pad */  + params + data_count;
+	pSMB->DataCount = cpu_to_le16(data_count);
 	pSMB->TotalDataCount = pSMB->DataCount;
-	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+	pSMB->ParameterCount = cpu_to_le16(params);
 	pSMB->TotalParameterCount = pSMB->ParameterCount;
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+	pSMB->hdr.smb_buf_length += byte_count;
 	parm_data->FileSize = cpu_to_le64(size);
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -2611,7 +2606,7 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
 	struct file_end_of_file_info *parm_data;
 	int rc = 0;
 	int bytes_returned = 0;
-	__u32 tmp;
+	__u16 params, param_offset, offset, byte_count, count;
 
 	cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
 			(long long)size));
@@ -2620,40 +2615,36 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
 	if (rc)
 		return rc;
 
-	tmp = cpu_to_le32(pid_of_opener);  /* override pid of current process
-                                         so network fid will be valid */
-	pSMB->hdr.Pid = tmp & 0xFFFF;
-	tmp >>= 16;
-	pSMB->hdr.PidHigh = tmp & 0xFFFF;
+	pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
+	pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
     
-	pSMB->ParameterCount = 6;
+	params = 6;
 	pSMB->MaxSetupCount = 0;
 	pSMB->Reserved = 0;
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
-                                     Fid) - 4;
-	pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+	offset = param_offset + params;
 
-	data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;	
+	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;	
 
-	pSMB->DataCount = sizeof(struct file_end_of_file_info);
+	count = sizeof(struct file_end_of_file_info);
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find max SMB PDU from sess */
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
-	pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
-	pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
-	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+	byte_count = 3 /* pad */  + params + count;
+	pSMB->DataCount = cpu_to_le16(count);
+	pSMB->ParameterCount = cpu_to_le16(params);
 	pSMB->TotalDataCount = pSMB->DataCount;
 	pSMB->TotalParameterCount = pSMB->ParameterCount;
-	pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
 	parm_data =
 		(struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
-			pSMB->DataOffset);
-	pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); /* now safe to change to le */
+			offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
 	parm_data->FileSize = cpu_to_le64(size);
 	pSMB->Fid = fid;
 	if(SetAllocation) {
@@ -2672,8 +2663,8 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
 		        cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
 	}
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -2702,6 +2693,7 @@ CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
 	int rc = 0;
 	int bytes_returned = 0;
 	char *data_offset;
+	__u16 params, param_offset, offset, byte_count, count;
 
 	cFYI(1, ("In SetTimes"));
 
@@ -2724,8 +2716,8 @@ SetTimesRetry:
 		strncpy(pSMB->FileName, fileName, name_len);
 	}
 
-	pSMB->ParameterCount = 6 + name_len;
-	pSMB->DataCount = sizeof (FILE_BASIC_INFO);
+	params = 6 + name_len;
+	count = sizeof (FILE_BASIC_INFO);
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find exact max SMB PDU from sess structure BB */
 	pSMB->MaxSetupCount = 0;
@@ -2733,19 +2725,19 @@ SetTimesRetry:
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+	param_offset = offsetof(struct smb_com_transaction2_spi_req,
                                      InformationLevel) - 4;
-	pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
-	data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
-	pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
-	pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+	offset = param_offset + params;
+	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
-	pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
+	byte_count = 3 /* pad */  + params + count;
 
-	pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
-	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+	pSMB->DataCount = cpu_to_le16(count);
+	pSMB->ParameterCount = cpu_to_le16(params);
 	pSMB->TotalDataCount = pSMB->DataCount;
 	pSMB->TotalParameterCount = pSMB->ParameterCount;
 	if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
@@ -2753,9 +2745,9 @@ SetTimesRetry:
 	else
 		pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+	pSMB->hdr.smb_buf_length += byte_count;
 	memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -2771,7 +2763,6 @@ SetTimesRetry:
 	return rc;
 }
 
-
 int
 CIFSSMBSetTimesLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
 		FILE_INFO_STANDARD * data, const struct nls_table *nls_codepage)
@@ -2782,6 +2773,7 @@ CIFSSMBSetTimesLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
 	int rc = 0;
 	int bytes_returned = 0;
 	char *data_offset;
+	__u16 params, param_offset, count, offset, byte_count;
 
 	cFYI(1, ("In SetTimesLegacy"));
 
@@ -2805,8 +2797,8 @@ SetTimesRetryLegacy:
 	}
 /* BB fixme - we have to map to FILE_STANDARD_INFO (level 1 info
 	in parent function, from the better and ususal FILE_BASIC_INFO */
-	pSMB->ParameterCount = 6 + name_len;
-	pSMB->DataCount = sizeof (FILE_INFO_STANDARD);
+	params = 6 + name_len;
+	count = sizeof (FILE_INFO_STANDARD);
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find exact max SMB PDU from sess structure BB */
 	pSMB->MaxSetupCount = 0;
@@ -2814,19 +2806,19 @@ SetTimesRetryLegacy:
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+	param_offset = offsetof(struct smb_com_transaction2_spi_req,
                                      InformationLevel) - 4;
-	pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
-	data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
-	pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
-	pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+	offset = param_offset + params;
+	data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
-	pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
+	byte_count = 3 /* pad */  + params + count;
 
-	pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
-	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+	pSMB->DataCount = cpu_to_le16(count);
+	pSMB->ParameterCount = cpu_to_le16(params);
 	pSMB->TotalDataCount = pSMB->DataCount;
 	pSMB->TotalParameterCount = pSMB->ParameterCount;
 	/* I doubt that passthrough levels apply to this old
@@ -2836,9 +2828,9 @@ SetTimesRetryLegacy:
 	else*/
 		pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+	pSMB->hdr.smb_buf_length += byte_count;
 	memcpy(data_offset, data, sizeof (FILE_INFO_STANDARD));
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -2865,6 +2857,7 @@ CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
 	int rc = 0;
 	int bytes_returned = 0;
 	FILE_UNIX_BASIC_INFO *data_offset;
+	__u16 params, param_offset, offset, count, byte_count;
 
 	cFYI(1, ("In SetUID/GID/Mode"));
 setPermsRetry:
@@ -2886,8 +2879,8 @@ setPermsRetry:
 		strncpy(pSMB->FileName, fileName, name_len);
 	}
 
-	pSMB->ParameterCount = 6 + name_len;
-	pSMB->DataCount = sizeof (FILE_UNIX_BASIC_INFO);
+	params = 6 + name_len;
+	count = sizeof (FILE_UNIX_BASIC_INFO);
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find exact max SMB PDU from sess structure BB */
 	pSMB->MaxSetupCount = 0;
@@ -2895,25 +2888,25 @@ setPermsRetry:
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+	param_offset = offsetof(struct smb_com_transaction2_spi_req,
                                      InformationLevel) - 4;
-	pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+	offset = param_offset + params;
 	data_offset =
 	    (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
-				      pSMB->DataOffset);
-	pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
-	pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
+				      offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
-	pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
-	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
-	pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
+	byte_count = 3 /* pad */  + params + count;
+	pSMB->ParameterCount = cpu_to_le16(params);
+	pSMB->DataCount = cpu_to_le16(count);
 	pSMB->TotalParameterCount = pSMB->ParameterCount;
 	pSMB->TotalDataCount = pSMB->DataCount;
 	pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
+	pSMB->hdr.smb_buf_length += byte_count;
 	data_offset->Uid = cpu_to_le64(uid);
 	data_offset->Gid = cpu_to_le64(gid);
 	/* better to leave device as zero when it is  */
@@ -2937,7 +2930,7 @@ setPermsRetry:
 		data_offset->Type = cpu_to_le32(UNIX_SOCKET);
 
 
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -2986,7 +2979,6 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
 	pSMB->Fid = netfid; /* file handle always le */
 	pSMB->ByteCount = 0;
 
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			(struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
@@ -3013,6 +3005,7 @@ CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
 	int name_len;
 	struct fea * temp_fea;
 	char * temp_ptr;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In Query All EAs path %s", searchName));
 QAllEAsRetry:
@@ -3034,8 +3027,7 @@ QAllEAsRetry:
 		strncpy(pSMB->FileName, searchName, name_len);
 	}
 
-	pSMB->TotalParameterCount = 2 /* level */  + 4 /* reserved */  +
-	    name_len /* includes null */ ;
+	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
 	pSMB->TotalDataCount = 0;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(4000);	/* BB find exact max SMB PDU from sess structure BB */
@@ -3051,29 +3043,29 @@ QAllEAsRetry:
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
-	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
 	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cFYI(1, ("Send error in QueryAllEAs = %d", rc));
 	} else {		/* decode response */
-		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+		__u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
 		/* BB also check enough total bytes returned */
 		/* BB we need to improve the validity checking
 		of these trans2 responses */
-		if ((pSMBr->ByteCount < 4) || (pSMBr->DataOffset > 512)) 
+		if ((pSMBr->ByteCount < 4) || (data_offset > 512)) 
 			rc = -EIO;	/* bad smb */
 	   /* else if (pFindData){
 			memcpy((char *) pFindData,
 			       (char *) &pSMBr->hdr.Protocol +
-			       pSMBr->DataOffset, kl);
+			       data_offset, kl);
 		}*/ else {
 			/* check that length of list is not more than bcc */
 			/* check that each entry does not go beyond length
@@ -3083,14 +3075,12 @@ QAllEAsRetry:
 			struct fealist * ea_response_data;
 			rc = 0;
 			/* validate_trans2_offsets() */
-			/* BB to check if(start of smb + pSMBr->DataOffset > &bcc+ bcc)*/
+			/* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
 			ea_response_data = (struct fealist *)
 				(((char *) &pSMBr->hdr.Protocol) +
-				pSMBr->DataOffset);
-			ea_response_data->list_len = 
-				cpu_to_le32(ea_response_data->list_len);
-			cFYI(1,("ea length %d",ea_response_data->list_len));
-			name_len = ea_response_data->list_len;
+				data_offset);
+			name_len = le32_to_cpu(ea_response_data->list_len);
+			cFYI(1,("ea length %d", name_len));
 			if(name_len <= 8) {
 			/* returned EA size zeroed at top of function */
 				cFYI(1,("empty EA list returned from server"));
@@ -3100,12 +3090,13 @@ QAllEAsRetry:
 				temp_fea = ea_response_data->list;
 				temp_ptr = (char *)temp_fea;
 				while(name_len > 0) {
+					__u16 value_len;
 					name_len -= 4;
 					temp_ptr += 4;
 					rc += temp_fea->name_len;
 				/* account for prefix user. and trailing null */
 					rc = rc + 5 + 1; 
-					if(rc<buf_size) {
+					if(rc<(int)buf_size) {
 						memcpy(EAData,"user.",5);
 						EAData+=5;
 						memcpy(EAData,temp_ptr,temp_fea->name_len);
@@ -3125,9 +3116,9 @@ QAllEAsRetry:
 					/* account for trailing null */
 					name_len--;
 					temp_ptr++;
-					temp_fea->value_len = cpu_to_le16(temp_fea->value_len);
-					name_len -= temp_fea->value_len;
-					temp_ptr += temp_fea->value_len;
+					value_len = le16_to_cpu(temp_fea->value_len);
+					name_len -= value_len;
+					temp_ptr += value_len;
 					/* BB check that temp_ptr is still within smb BB*/
 				/* no trailing null to account for in value len */
 					/* go on to next EA */
@@ -3141,7 +3132,7 @@ QAllEAsRetry:
 	if (rc == -EAGAIN)
 		goto QAllEAsRetry;
 
-	return rc;
+	return (ssize_t)rc;
 }
 
 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
@@ -3156,6 +3147,7 @@ ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
 	int name_len;
 	struct fea * temp_fea;
 	char * temp_ptr;
+	__u16 params, byte_count;
 
 	cFYI(1, ("In Query EA path %s", searchName));
 QEARetry:
@@ -3177,8 +3169,7 @@ QEARetry:
 		strncpy(pSMB->FileName, searchName, name_len);
 	}
 
-	pSMB->TotalParameterCount = 2 /* level */  + 4 /* reserved */  +
-	    name_len /* includes null */ ;
+	params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
 	pSMB->TotalDataCount = 0;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(4000);	/* BB find exact max SMB PDU from sess structure BB */
@@ -3194,29 +3185,29 @@ QEARetry:
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
-	pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
-	pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
+	byte_count = params + 1 /* pad */ ;
+	pSMB->TotalParameterCount = cpu_to_le16(params);
 	pSMB->ParameterCount = pSMB->TotalParameterCount;
 	pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
 		cFYI(1, ("Send error in Query EA = %d", rc));
 	} else {		/* decode response */
-		pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
+		__u16 data_offset = le16_to_cpu(pSMBr->DataOffset);
 		/* BB also check enough total bytes returned */
 		/* BB we need to improve the validity checking
 		of these trans2 responses */
-		if ((pSMBr->ByteCount < 4) || (pSMBr->DataOffset > 512)) 
+		if ((pSMBr->ByteCount < 4) || (data_offset > 512)) 
 			rc = -EIO;	/* bad smb */
 	   /* else if (pFindData){
 			memcpy((char *) pFindData,
 			       (char *) &pSMBr->hdr.Protocol +
-			       pSMBr->DataOffset, kl);
+			       data_offset, kl);
 		}*/ else {
 			/* check that length of list is not more than bcc */
 			/* check that each entry does not go beyond length
@@ -3226,14 +3217,12 @@ QEARetry:
 			struct fealist * ea_response_data;
 			rc = -ENOENT;
 			/* validate_trans2_offsets() */
-			/* BB to check if(start of smb + pSMBr->DataOffset > &bcc+ bcc)*/
+			/* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
 			ea_response_data = (struct fealist *)
 				(((char *) &pSMBr->hdr.Protocol) +
-				pSMBr->DataOffset);
-			ea_response_data->list_len = 
-				cpu_to_le32(ea_response_data->list_len);
-			cFYI(1,("ea length %d",ea_response_data->list_len));
-			name_len = ea_response_data->list_len;
+				data_offset);
+			name_len = le32_to_cpu(ea_response_data->list_len);
+			cFYI(1,("ea length %d", name_len));
 			if(name_len <= 8) {
 			/* returned EA size zeroed at top of function */
 				cFYI(1,("empty EA list returned from server"));
@@ -3245,17 +3234,18 @@ QEARetry:
 				/* loop through checking if we have a matching
 				name and then return the associated value */
 				while(name_len > 0) {
+					__u16 value_len;
 					name_len -= 4;
 					temp_ptr += 4;
-					temp_fea->value_len = cpu_to_le16(temp_fea->value_len);
+					value_len = le16_to_cpu(temp_fea->value_len);
 				/* BB validate that value_len falls within SMB, 
 				even though maximum for name_len is 255 */ 
 					if(memcmp(temp_fea->name,ea_name,
 						  temp_fea->name_len) == 0) {
 						/* found a match */
-						rc = temp_fea->value_len;
+						rc = value_len;
 				/* account for prefix user. and trailing null */
-						if(rc<=buf_size) {
+						if(rc<=(int)buf_size) {
 							memcpy(ea_value,
 								temp_fea->name+temp_fea->name_len+1,
 								rc);
@@ -3274,8 +3264,8 @@ QEARetry:
 					/* account for trailing null */
 					name_len--;
 					temp_ptr++;
-					name_len -= temp_fea->value_len;
-					temp_ptr += temp_fea->value_len;
+					name_len -= value_len;
+					temp_ptr += value_len;
 				/* no trailing null to account for in value len */
 					/* go on to next EA */
 					temp_fea = (struct fea *)temp_ptr;
@@ -3288,7 +3278,7 @@ QEARetry:
 	if (rc == -EAGAIN)
 		goto QEARetry;
 
-	return rc;
+	return (ssize_t)rc;
 }
 
 int
@@ -3302,6 +3292,7 @@ CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
 	int name_len;
 	int rc = 0;
 	int bytes_returned = 0;
+	__u16 params, param_offset, byte_count, offset, count;
 
 	cFYI(1, ("In SetEA"));
 SetEARetry:
@@ -3323,7 +3314,7 @@ SetEARetry:
 		strncpy(pSMB->FileName, fileName, name_len);
 	}
 
-	pSMB->ParameterCount = 6 + name_len;
+	params = 6 + name_len;
 
 	/* done calculating parms using name_len of file name,
 	now use name_len to calculate length of ea name
@@ -3333,7 +3324,7 @@ SetEARetry:
 	else
 		name_len = strnlen(ea_name,255);
 
-	pSMB->DataCount = sizeof(*parm_data) + ea_value_len + name_len + 1;
+	count = sizeof(*parm_data) + ea_value_len + name_len + 1;
 	pSMB->MaxParameterCount = cpu_to_le16(2);
 	pSMB->MaxDataCount = cpu_to_le16(1000);	/* BB find max SMB size from sess */
 	pSMB->MaxSetupCount = 0;
@@ -3341,23 +3332,23 @@ SetEARetry:
 	pSMB->Flags = 0;
 	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
-	pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
+	param_offset = offsetof(struct smb_com_transaction2_spi_req,
                                      InformationLevel) - 4;
-	pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
+	offset = param_offset + params;
 	pSMB->InformationLevel =
 		cpu_to_le16(SMB_SET_FILE_EA);
 
 	parm_data =
 		(struct fealist *) (((char *) &pSMB->hdr.Protocol) +
-				       pSMB->DataOffset);
-	pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
-	pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
+				       offset);
+	pSMB->ParameterOffset = cpu_to_le16(param_offset);
+	pSMB->DataOffset = cpu_to_le16(offset);
 	pSMB->SetupCount = 1;
 	pSMB->Reserved3 = 0;
 	pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
-	pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
-	pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
-	parm_data->list_len = (__u32)(pSMB->DataCount);
+	byte_count = 3 /* pad */  + params + count;
+	pSMB->DataCount = cpu_to_le16(count);
+	parm_data->list_len = cpu_to_le32(count);
 	parm_data->list[0].EA_flags = 0;
 	/* we checked above that name len is less than 255 */
 	parm_data->list[0].name_len = (__u8)name_len;;
@@ -3374,11 +3365,11 @@ SetEARetry:
 		memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
 
 	pSMB->TotalDataCount = pSMB->DataCount;
-	pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
+	pSMB->ParameterCount = cpu_to_le16(params);
 	pSMB->TotalParameterCount = pSMB->ParameterCount;
 	pSMB->Reserved4 = 0;
-	pSMB->hdr.smb_buf_length += pSMB->ByteCount;
-	pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
+	pSMB->hdr.smb_buf_length += byte_count;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
 	if (rc) {
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index bb6b0f3b2..e548bb3cf 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -64,11 +64,11 @@ struct smb_vol {
 	gid_t linux_gid;
 	mode_t file_mode;
 	mode_t dir_mode;
-	int rw:1;
-	int retry:1;
-	int intr:1;
-	int setuids:1;
-	int noperm:1;
+	unsigned rw:1;
+	unsigned retry:1;
+	unsigned intr:1;
+	unsigned setuids:1;
+	unsigned noperm:1;
 	unsigned int rsize;
 	unsigned int wsize;
 	unsigned int sockopt;
@@ -313,7 +313,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
 					connected to port 139 (the NACK is 
 					since we do not begin with RFC1001
 					session initialize frame) */
-					server->addr.sockAddr.sin_port = CIFS_PORT;
+					server->addr.sockAddr.sin_port = htons(CIFS_PORT);
 					cifs_reconnect(server);
 					csocket = server->ssocket;
 					wake_up(&server->response_q);
@@ -814,19 +814,23 @@ cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol
 }
 
 static struct cifsSesInfo *
-cifs_find_tcp_session(__u32 new_target_ip_addr,
+cifs_find_tcp_session(struct in_addr * target_ip_addr, 
+		struct in6_addr *target_ip6_addr,
 		 char *userName, struct TCP_Server_Info **psrvTcp)
 {
 	struct list_head *tmp;
 	struct cifsSesInfo *ses;
-
 	*psrvTcp = NULL;
 	read_lock(&GlobalSMBSeslock);
+
 	list_for_each(tmp, &GlobalSMBSessionList) {
 		ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
 		if (ses->server) {
-			if (ses->server->addr.sockAddr.sin_addr.s_addr ==
-			    new_target_ip_addr) {
+			if((target_ip_addr && 
+				(ses->server->addr.sockAddr.sin_addr.s_addr
+				  == target_ip_addr->s_addr)) || (target_ip6_addr
+				&& memcmp(&ses->server->addr.sockAddr6.sin6_addr,
+					target_ip6_addr,sizeof(*target_ip6_addr)))){
 				/* BB lock server and tcp session and increment use count here?? */
 				*psrvTcp = ses->server;	/* found a match on the TCP session */
 				/* BB check if reconnection needed */
@@ -845,7 +849,7 @@ cifs_find_tcp_session(__u32 new_target_ip_addr,
 }
 
 static struct cifsTconInfo *
-find_unc(__u32 new_target_ip_addr, char *uncName, char *userName)
+find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
 {
 	struct list_head *tmp;
 	struct cifsTconInfo *tcon;
@@ -964,7 +968,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
 {
 	int rc = 0;
 	int connected = 0;
-	unsigned short int orig_port = 0;
+	__be16 orig_port = 0;
 
 	if(*csocket == NULL) {
 		rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
@@ -1029,7 +1033,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
 
 	/* send RFC1001 sessinit */
 
-	if(psin_server->sin_port == htons(139)) {
+	if(psin_server->sin_port == htons(RFC1001_PORT)) {
 		/* some servers require RFC1001 sessinit before sending
 		negprot - BB check reconnection in case where second 
 		sessinit is sent but no second negprot */
@@ -1072,6 +1076,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
 {
 	int rc = 0;
 	int connected = 0;
+	__be16 orig_port = 0;
 
 	if(*csocket == NULL) {
 		rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
@@ -1097,6 +1102,10 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
 	} 
 
 	if(!connected) {
+		/* save original port so we can retry user specified port  
+			later if fall back ports fail this time  */
+
+		orig_port = psin_server->sin6_port;
 		/* do not retry on the same port we just failed on */
 		if(psin_server->sin6_port != htons(CIFS_PORT)) {
 			psin_server->sin6_port = htons(CIFS_PORT);
@@ -1119,6 +1128,8 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
 	/* give up here - unless we want to retry on different
 		protocol families some day */
 	if (!connected) {
+		if(orig_port)
+			psin_server->sin6_port = orig_port;
 		cFYI(1,("Error %d connecting to server via ipv6",rc));
 		sock_release(*csocket);
 		*csocket = NULL;
@@ -1138,6 +1149,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
 {
 	int rc = 0;
 	int xid;
+	int address_type = AF_INET;
 	struct socket *csocket = NULL;
 	struct sockaddr_in sin_server;
 	struct sockaddr_in6 sin_server6;
@@ -1179,12 +1191,16 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
 	if (volume_info.UNCip && volume_info.UNC) {
 		rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
 
-		if(rc == 0) {
+		if(rc <= 0) {
 			/* not ipv4 address, try ipv6 */
 			rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u); 
-		} 
+			if(rc > 0)
+				address_type = AF_INET6;
+		} else {
+			address_type = AF_INET;
+		}
        
-		if(rc != 1) {
+		if(rc <= 0) {
 			/* we failed translating address */
 			if(volume_info.UNC)
 				kfree(volume_info.UNC);
@@ -1234,9 +1250,24 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
 		}
 	}
 
-	existingCifsSes =
-	    cifs_find_tcp_session(sin_server.sin_addr.s_addr,
-			     volume_info.username, &srvTcp);
+	if(address_type == AF_INET)
+		existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
+			NULL /* no ipv6 addr */,
+			volume_info.username, &srvTcp);
+	else if(address_type == AF_INET6)
+		existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
+			&sin_server6.sin6_addr,
+			volume_info.username, &srvTcp);
+	else {
+		if(volume_info.UNC)
+			kfree(volume_info.UNC);
+		if(volume_info.password)
+			kfree(volume_info.password);
+		FreeXid(xid);
+		return -EINVAL;
+	}
+
+
 	if (srvTcp) {
 		cFYI(1, ("Existing tcp session with server found "));                
 	} else {	/* create socket */
@@ -1283,8 +1314,19 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
 			so no need to spinlock this init of tcpStatus */
 			srvTcp->tcpStatus = CifsNew;
 			init_MUTEX(&srvTcp->tcpSem);
-			kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
+			rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
 				      CLONE_FS | CLONE_FILES | CLONE_VM);
+			if(rc < 0) {
+				rc = -ENOMEM;
+				sock_release(csocket);
+				if(volume_info.UNC)
+					kfree(volume_info.UNC);
+				if(volume_info.password)
+					kfree(volume_info.password);
+				FreeXid(xid);
+				return rc;
+			} else
+				rc = 0;
 			memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
 		}
 	}
@@ -1464,15 +1506,20 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 	SESSION_SETUP_ANDX *pSMB;
 	SESSION_SETUP_ANDX *pSMBr;
 	char *bcc_ptr;
-	char *user = ses->userName;
-	char *domain = ses->domainName;
+	char *user;
+	char *domain;
 	int rc = 0;
 	int remaining_words = 0;
 	int bytes_returned = 0;
 	int len;
+	__u32 capabilities;
+	__u16 count;
 
 	cFYI(1, ("In sesssetup "));
-
+	if(ses == NULL)
+		return -EINVAL;
+	user = ses->userName;
+	domain = ses->domainName;
 	smb_buffer = cifs_buf_get();
 	if (smb_buffer == 0) {
 		return -ENOMEM;
@@ -1491,22 +1538,20 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
-	pSMB->req_no_secext.Capabilities =
-	    CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS;
+	capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS;
 	if (ses->capabilities & CAP_UNICODE) {
 		smb_buffer->Flags2 |= SMBFLG2_UNICODE;
-		pSMB->req_no_secext.Capabilities |= CAP_UNICODE;
+		capabilities |= CAP_UNICODE;
 	}
 	if (ses->capabilities & CAP_STATUS32) {
 		smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
-		pSMB->req_no_secext.Capabilities |= CAP_STATUS32;
+		capabilities |= CAP_STATUS32;
 	}
 	if (ses->capabilities & CAP_DFS) {
 		smb_buffer->Flags2 |= SMBFLG2_DFS;
-		pSMB->req_no_secext.Capabilities |= CAP_DFS;
+		capabilities |= CAP_DFS;
 	}
-	pSMB->req_no_secext.Capabilities =
-	    cpu_to_le32(pSMB->req_no_secext.Capabilities);
+	pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
 	/* pSMB->req_no_secext.CaseInsensitivePasswordLength =
 	   CIFS_SESSION_KEY_SIZE; */
 	pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
@@ -1578,9 +1623,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 		strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
 		bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
 	}
-	BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
-	smb_buffer->smb_buf_length += BCC(smb_buffer);
-	BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
+	count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
+	smb_buffer->smb_buf_length += count;
+	pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
 			 &bytes_returned, 1);
@@ -1588,114 +1633,106 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
 	} else if ((smb_buffer_response->WordCount == 3)
 		   || (smb_buffer_response->WordCount == 4)) {
-		pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
-		if (pSMBr->resp.Action & GUEST_LOGIN)
+		__u16 action = le16_to_cpu(pSMBr->resp.Action);
+		__u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
+		if (action & GUEST_LOGIN)
 			cFYI(1, (" Guest login"));	/* do we want to mark SesInfo struct ? */
-		if (ses) {
-			ses->Suid = smb_buffer_response->Uid;	/* UID left in wire format (le) */
-			cFYI(1, ("UID = %d ", ses->Suid));
+		ses->Suid = smb_buffer_response->Uid;	/* UID left in wire format (le) */
+		cFYI(1, ("UID = %d ", ses->Suid));
          /* response can have either 3 or 4 word count - Samba sends 3 */
-			bcc_ptr = pByteArea(smb_buffer_response);	
-			if ((pSMBr->resp.hdr.WordCount == 3)
-			    || ((pSMBr->resp.hdr.WordCount == 4)
-				&& (pSMBr->resp.SecurityBlobLength <
-				    pSMBr->resp.ByteCount))) {
-				if (pSMBr->resp.hdr.WordCount == 4)
-					bcc_ptr +=
-					    pSMBr->resp.SecurityBlobLength;
-
-				if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
-					if ((long) (bcc_ptr) % 2) {
-						remaining_words =
-						    (BCC(smb_buffer_response)
-						     - 1) / 2;
-						bcc_ptr++;	/* Unicode strings must be word aligned */
-					} else {
-						remaining_words =
-						    BCC
-						    (smb_buffer_response) / 2;
-					}
-					len =
-					    UniStrnlen((wchar_t *) bcc_ptr,
-						       remaining_words - 1);
+		bcc_ptr = pByteArea(smb_buffer_response);	
+		if ((pSMBr->resp.hdr.WordCount == 3)
+		    || ((pSMBr->resp.hdr.WordCount == 4)
+			&& (blob_len < pSMBr->resp.ByteCount))) {
+			if (pSMBr->resp.hdr.WordCount == 4)
+				bcc_ptr += blob_len;
+
+			if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
+				if ((long) (bcc_ptr) % 2) {
+					remaining_words =
+					    (BCC(smb_buffer_response) - 1) /2;
+					bcc_ptr++;	/* Unicode strings must be word aligned */
+				} else {
+					remaining_words =
+						BCC(smb_buffer_response) / 2;
+				}
+				len =
+				    UniStrnlen((wchar_t *) bcc_ptr,
+					       remaining_words - 1);
 /* We look for obvious messed up bcc or strings in response so we do not go off
    the end since (at least) WIN2K and Windows XP have a major bug in not null
    terminating last Unicode string in response  */
-					ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
-					cifs_strfromUCS_le(ses->serverOS,
-							   (wchar_t *)bcc_ptr, len,nls_codepage);
+				ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
+				cifs_strfromUCS_le(ses->serverOS,
+					   (wchar_t *)bcc_ptr, len,nls_codepage);
+				bcc_ptr += 2 * (len + 1);
+				remaining_words -= len + 1;
+				ses->serverOS[2 * len] = 0;
+				ses->serverOS[1 + (2 * len)] = 0;
+				if (remaining_words > 0) {
+					len = UniStrnlen((wchar_t *)bcc_ptr,
+							 remaining_words-1);
+					ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL);
+					cifs_strfromUCS_le(ses->serverNOS,
+							   (wchar_t *)bcc_ptr,len,nls_codepage);
 					bcc_ptr += 2 * (len + 1);
+					ses->serverNOS[2 * len] = 0;
+					ses->serverNOS[1 + (2 * len)] = 0;
 					remaining_words -= len + 1;
-					ses->serverOS[2 * len] = 0;
-					ses->serverOS[1 + (2 * len)] = 0;
 					if (remaining_words > 0) {
-						len = UniStrnlen((wchar_t *)bcc_ptr,
-								 remaining_words
-								 - 1);
-						ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL);
-						cifs_strfromUCS_le(ses->serverNOS,
-								   (wchar_t *)bcc_ptr,len,nls_codepage);
-						bcc_ptr += 2 * (len + 1);
-						ses->serverNOS[2 * len] = 0;
-						ses->serverNOS[1 + (2 * len)] = 0;
-						remaining_words -= len + 1;
-						if (remaining_words > 0) {
-							len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);	
+						len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);	
           /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
-							ses->serverDomain =
-							    cifs_kcalloc(2*(len+1),GFP_KERNEL);
-							cifs_strfromUCS_le(ses->serverDomain,
-							     (wchar_t *)bcc_ptr,len,nls_codepage);
-							bcc_ptr += 2 * (len + 1);
-							ses->serverDomain[2*len] = 0;
-							ses->serverDomain[1+(2*len)] = 0;
-						} /* else no more room so create dummy domain string */
-						else
-							ses->serverDomain =
-							    cifs_kcalloc(2,
-								    GFP_KERNEL);
-					} else {	/* no room so create dummy domain and NOS string */
 						ses->serverDomain =
-						    cifs_kcalloc(2, GFP_KERNEL);
-						ses->serverNOS =
-						    cifs_kcalloc(2, GFP_KERNEL);
-					}
-				} else {	/* ASCII */
-					len = strnlen(bcc_ptr, 1024);
-					if (((long) bcc_ptr + len) - (long)
-					    pByteArea(smb_buffer_response)
+						    cifs_kcalloc(2*(len+1),GFP_KERNEL);
+						cifs_strfromUCS_le(ses->serverDomain,
+						     (wchar_t *)bcc_ptr,len,nls_codepage);
+						bcc_ptr += 2 * (len + 1);
+						ses->serverDomain[2*len] = 0;
+						ses->serverDomain[1+(2*len)] = 0;
+					} /* else no more room so create dummy domain string */
+					else
+						ses->serverDomain =
+						    cifs_kcalloc(2,
+							    GFP_KERNEL);
+				} else {	/* no room so create dummy domain and NOS string */
+					ses->serverDomain =
+					    cifs_kcalloc(2, GFP_KERNEL);
+					ses->serverNOS =
+					    cifs_kcalloc(2, GFP_KERNEL);
+				}
+			} else {	/* ASCII */
+				len = strnlen(bcc_ptr, 1024);
+				if (((long) bcc_ptr + len) - (long)
+				    pByteArea(smb_buffer_response)
 					    <= BCC(smb_buffer_response)) {
-						ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
-						strncpy(ses->serverOS,bcc_ptr, len);
+					ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
+					strncpy(ses->serverOS,bcc_ptr, len);
 
-						bcc_ptr += len;
-						bcc_ptr[0] = 0;	/* null terminate the string */
-						bcc_ptr++;
+					bcc_ptr += len;
+					bcc_ptr[0] = 0;	/* null terminate the string */
+					bcc_ptr++;
 
-						len = strnlen(bcc_ptr, 1024);
-						ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
-						strncpy(ses->serverNOS, bcc_ptr, len);
-						bcc_ptr += len;
-						bcc_ptr[0] = 0;
-						bcc_ptr++;
+					len = strnlen(bcc_ptr, 1024);
+					ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
+					strncpy(ses->serverNOS, bcc_ptr, len);
+					bcc_ptr += len;
+					bcc_ptr[0] = 0;
+					bcc_ptr++;
 
-						len = strnlen(bcc_ptr, 1024);
-						ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
-						strncpy(ses->serverDomain, bcc_ptr, len);
-						bcc_ptr += len;
-						bcc_ptr[0] = 0;
-						bcc_ptr++;
-					} else
-						cFYI(1,
-						     ("Variable field of length %d extends beyond end of smb ",
-						      len));
-				}
-			} else {
-				cERROR(1,
-				       (" Security Blob Length extends beyond end of SMB"));
+					len = strnlen(bcc_ptr, 1024);
+					ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
+					strncpy(ses->serverDomain, bcc_ptr, len);
+					bcc_ptr += len;
+					bcc_ptr[0] = 0;
+					bcc_ptr++;
+				} else
+					cFYI(1,
+					     ("Variable field of length %d extends beyond end of smb ",
+					      len));
 			}
 		} else {
-			cERROR(1, ("No session structure passed in."));
+			cERROR(1,
+			       (" Security Blob Length extends beyond end of SMB"));
 		}
 	} else {
 		cERROR(1,
@@ -1720,14 +1757,20 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 	SESSION_SETUP_ANDX *pSMB;
 	SESSION_SETUP_ANDX *pSMBr;
 	char *bcc_ptr;
-	char *user = ses->userName;
-	char *domain = ses->domainName;
+	char *user;
+	char *domain;
 	int rc = 0;
 	int remaining_words = 0;
 	int bytes_returned = 0;
 	int len;
+	__u32 capabilities;
+	__u16 count;
 
 	cFYI(1, ("In spnego sesssetup "));
+	if(ses == NULL)
+		return -EINVAL;
+	user = ses->userName;
+	domain = ses->domainName;
 
 	smb_buffer = cifs_buf_get();
 	if (smb_buffer == 0) {
@@ -1747,22 +1790,21 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
-	pSMB->req.Capabilities =
-	    CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+	capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
 	    CAP_EXTENDED_SECURITY;
 	if (ses->capabilities & CAP_UNICODE) {
 		smb_buffer->Flags2 |= SMBFLG2_UNICODE;
-		pSMB->req.Capabilities |= CAP_UNICODE;
+		capabilities |= CAP_UNICODE;
 	}
 	if (ses->capabilities & CAP_STATUS32) {
 		smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
-		pSMB->req.Capabilities |= CAP_STATUS32;
+		capabilities |= CAP_STATUS32;
 	}
 	if (ses->capabilities & CAP_DFS) {
 		smb_buffer->Flags2 |= SMBFLG2_DFS;
-		pSMB->req.Capabilities |= CAP_DFS;
+		capabilities |= CAP_DFS;
 	}
-	pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
+	pSMB->req.Capabilities = cpu_to_le32(capabilities);
 
 	pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
 	bcc_ptr = pByteArea(smb_buffer);
@@ -1823,9 +1865,9 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 		strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
 		bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
 	}
-	BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
-	smb_buffer->smb_buf_length += BCC(smb_buffer);
-	BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
+	count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
+	smb_buffer->smb_buf_length += count;
+	pSMB->req.ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
 			 &bytes_returned, 1);
@@ -1833,10 +1875,10 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 /*    rc = map_smb_to_linux_error(smb_buffer_response);  *//* done in SendReceive now */
 	} else if ((smb_buffer_response->WordCount == 3)
 		   || (smb_buffer_response->WordCount == 4)) {
-		pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
-		pSMBr->resp.SecurityBlobLength =
+		__u16 action = le16_to_cpu(pSMBr->resp.Action);
+		__u16 blob_len =
 		    le16_to_cpu(pSMBr->resp.SecurityBlobLength);
-		if (pSMBr->resp.Action & GUEST_LOGIN)
+		if (action & GUEST_LOGIN)
 			cFYI(1, (" Guest login"));	/* BB do we want to set anything in SesInfo struct ? */
 		if (ses) {
 			ses->Suid = smb_buffer_response->Uid;	/* UID left in wire format (le) */
@@ -1847,14 +1889,14 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 
 			if ((pSMBr->resp.hdr.WordCount == 3)
 			    || ((pSMBr->resp.hdr.WordCount == 4)
-				&& (pSMBr->resp.SecurityBlobLength <
+				&& (blob_len <
 				    pSMBr->resp.ByteCount))) {
 				if (pSMBr->resp.hdr.WordCount == 4) {
 					bcc_ptr +=
-					    pSMBr->resp.SecurityBlobLength;
+					    blob_len;
 					cFYI(1,
 					     ("Security Blob Length %d ",
-					      pSMBr->resp.SecurityBlobLength));
+					      blob_len));
 				}
 
 				if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
@@ -1979,7 +2021,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
 	SESSION_SETUP_ANDX *pSMB;
 	SESSION_SETUP_ANDX *pSMBr;
 	char *bcc_ptr;
-	char *domain = ses->domainName;
+	char *domain;
 	int rc = 0;
 	int remaining_words = 0;
 	int bytes_returned = 0;
@@ -1987,8 +2029,13 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
 	int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
 	PNEGOTIATE_MESSAGE SecurityBlob;
 	PCHALLENGE_MESSAGE SecurityBlob2;
+	__u32 negotiate_flags, capabilities;
+	__u16 count;
 
 	cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
+	if(ses == NULL)
+		return -EINVAL;
+	domain = ses->domainName;
 	*pNTLMv2_flag = FALSE;
 	smb_buffer = cifs_buf_get();
 	if (smb_buffer == 0) {
@@ -2011,35 +2058,34 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
 	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
-	pSMB->req.Capabilities =
-	    CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+	capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
 	    CAP_EXTENDED_SECURITY;
 	if (ses->capabilities & CAP_UNICODE) {
 		smb_buffer->Flags2 |= SMBFLG2_UNICODE;
-		pSMB->req.Capabilities |= CAP_UNICODE;
+		capabilities |= CAP_UNICODE;
 	}
 	if (ses->capabilities & CAP_STATUS32) {
 		smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
-		pSMB->req.Capabilities |= CAP_STATUS32;
+		capabilities |= CAP_STATUS32;
 	}
 	if (ses->capabilities & CAP_DFS) {
 		smb_buffer->Flags2 |= SMBFLG2_DFS;
-		pSMB->req.Capabilities |= CAP_DFS;
+		capabilities |= CAP_DFS;
 	}
-	pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
+	pSMB->req.Capabilities = cpu_to_le32(capabilities);
 
 	bcc_ptr = (char *) &pSMB->req.SecurityBlob;
 	SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
 	strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
 	SecurityBlob->MessageType = NtLmNegotiate;
-	SecurityBlob->NegotiateFlags =
+	negotiate_flags =
 	    NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
 	    NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
 	    /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
 	if(sign_CIFS_PDUs)
-		SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
+		negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
 	if(ntlmv2_support)
-		SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
+		negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
 	/* setup pointers to domain name and workstation name */
 	bcc_ptr += SecurityBlobLength;
 
@@ -2052,20 +2098,20 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
 		SecurityBlob->DomainName.Length = 0;
 		SecurityBlob->DomainName.MaximumLength = 0;
 	} else {
-		SecurityBlob->NegotiateFlags |=
-		    NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
+		__u16 len;
+		negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
 		strncpy(bcc_ptr, domain, 63);
-		SecurityBlob->DomainName.Length = strnlen(domain, 64);
+		len = strnlen(domain, 64);
 		SecurityBlob->DomainName.MaximumLength =
-		    cpu_to_le16(SecurityBlob->DomainName.Length);
+		    cpu_to_le16(len);
 		SecurityBlob->DomainName.Buffer =
 		    cpu_to_le32((long) &SecurityBlob->
 				DomainString -
 				(long) &SecurityBlob->Signature);
-		bcc_ptr += SecurityBlob->DomainName.Length;
-		SecurityBlobLength += SecurityBlob->DomainName.Length;
+		bcc_ptr += len;
+		SecurityBlobLength += len;
 		SecurityBlob->DomainName.Length =
-		    cpu_to_le16(SecurityBlob->DomainName.Length);
+		    cpu_to_le16(len);
 	}
 	if (ses->capabilities & CAP_UNICODE) {
 		if ((long) bcc_ptr % 2) {
@@ -2102,28 +2148,27 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
 		bcc_ptr++;	/* empty domain field */
 		*bcc_ptr = 0;
 	}
-	SecurityBlob->NegotiateFlags =
-	    cpu_to_le32(SecurityBlob->NegotiateFlags);
+	SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
 	pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
-	BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
-	smb_buffer->smb_buf_length += BCC(smb_buffer);
-	BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
+	count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
+	smb_buffer->smb_buf_length += count;
+	pSMB->req.ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
 			 &bytes_returned, 1);
 
 	if (smb_buffer_response->Status.CifsError ==
-	    (NT_STATUS_MORE_PROCESSING_REQUIRED))
+	    cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
 		rc = 0;
 
 	if (rc) {
 /*    rc = map_smb_to_linux_error(smb_buffer_response);  *//* done in SendReceive now */
 	} else if ((smb_buffer_response->WordCount == 3)
 		   || (smb_buffer_response->WordCount == 4)) {
-		pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
-		pSMBr->resp.SecurityBlobLength =
-		    le16_to_cpu(pSMBr->resp.SecurityBlobLength);
-		if (pSMBr->resp.Action & GUEST_LOGIN)
+		__u16 action = le16_to_cpu(pSMBr->resp.Action);
+		__u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
+
+		if (action & GUEST_LOGIN)
 			cFYI(1, (" Guest login"));	
         /* Do we want to set anything in SesInfo struct when guest login? */
 
@@ -2140,14 +2185,14 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
 			cFYI(1, ("UID = %d ", ses->Suid));
 			if ((pSMBr->resp.hdr.WordCount == 3)
 			    || ((pSMBr->resp.hdr.WordCount == 4)
-				&& (pSMBr->resp.SecurityBlobLength <
+				&& (blob_len <
 				    pSMBr->resp.ByteCount))) {
+
 				if (pSMBr->resp.hdr.WordCount == 4) {
-					bcc_ptr +=
-					    pSMBr->resp.SecurityBlobLength;
+					bcc_ptr += blob_len;
 					cFYI(1,
 					     ("Security Blob Length %d ",
-					      pSMBr->resp.SecurityBlobLength));
+					      blob_len));
 				}
 
 				cFYI(1, ("NTLMSSP Challenge rcvd "));
@@ -2155,16 +2200,16 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
 				memcpy(ses->server->cryptKey,
 				       SecurityBlob2->Challenge,
 				       CIFS_CRYPTO_KEY_SIZE);
-				if(SecurityBlob2->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLMV2)
+				if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
 					*pNTLMv2_flag = TRUE;
 
 				if((SecurityBlob2->NegotiateFlags & 
-					NTLMSSP_NEGOTIATE_ALWAYS_SIGN) 
+					cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) 
 					|| (sign_CIFS_PDUs > 1))
 						ses->server->secMode |= 
 							SECMODE_SIGN_REQUIRED;	
 				if ((SecurityBlob2->NegotiateFlags & 
-					NTLMSSP_NEGOTIATE_SIGN) && (sign_CIFS_PDUs))
+					cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
 						ses->server->secMode |= 
 							SECMODE_SIGN_ENABLED;
 
@@ -2308,7 +2353,6 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
 
 	return rc;
 }
-
 static int
 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 		char *ntlm_session_key, int ntlmv2_flag,
@@ -2319,17 +2363,22 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 	SESSION_SETUP_ANDX *pSMB;
 	SESSION_SETUP_ANDX *pSMBr;
 	char *bcc_ptr;
-	char *user = ses->userName;
-	char *domain = ses->domainName;
+	char *user;
+	char *domain;
 	int rc = 0;
 	int remaining_words = 0;
 	int bytes_returned = 0;
 	int len;
 	int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
 	PAUTHENTICATE_MESSAGE SecurityBlob;
+	__u32 negotiate_flags, capabilities;
+	__u16 count;
 
 	cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
-
+	if(ses == NULL)
+		return -EINVAL;
+	user = ses->userName;
+	domain = ses->domainName;
 	smb_buffer = cifs_buf_get();
 	if (smb_buffer == 0) {
 		return -ENOMEM;
@@ -2352,36 +2401,35 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
 
-	pSMB->req.Capabilities =
-	    CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+	capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
 	    CAP_EXTENDED_SECURITY;
 	if (ses->capabilities & CAP_UNICODE) {
 		smb_buffer->Flags2 |= SMBFLG2_UNICODE;
-		pSMB->req.Capabilities |= CAP_UNICODE;
+		capabilities |= CAP_UNICODE;
 	}
 	if (ses->capabilities & CAP_STATUS32) {
 		smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
-		pSMB->req.Capabilities |= CAP_STATUS32;
+		capabilities |= CAP_STATUS32;
 	}
 	if (ses->capabilities & CAP_DFS) {
 		smb_buffer->Flags2 |= SMBFLG2_DFS;
-		pSMB->req.Capabilities |= CAP_DFS;
+		capabilities |= CAP_DFS;
 	}
-	pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
+	pSMB->req.Capabilities = cpu_to_le32(capabilities);
 
 	bcc_ptr = (char *) &pSMB->req.SecurityBlob;
 	SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
 	strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
 	SecurityBlob->MessageType = NtLmAuthenticate;
 	bcc_ptr += SecurityBlobLength;
-	SecurityBlob->NegotiateFlags =
+	negotiate_flags = 
 	    NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
 	    NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
 	    0x80000000 | NTLMSSP_NEGOTIATE_128;
 	if(sign_CIFS_PDUs)
-		SecurityBlob->NegotiateFlags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
+		negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
 	if(ntlmv2_flag)
-		SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
+		negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
 
 /* setup pointers to domain name and workstation name */
 
@@ -2412,36 +2460,36 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 			SecurityBlob->DomainName.Length = 0;
 			SecurityBlob->DomainName.MaximumLength = 0;
 		} else {
-			SecurityBlob->DomainName.Length =
+			__u16 len =
 			    cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
 					  nls_codepage);
-			SecurityBlob->DomainName.Length *= 2;
+			len *= 2;
 			SecurityBlob->DomainName.MaximumLength =
-			    cpu_to_le16(SecurityBlob->DomainName.Length);
+			    cpu_to_le16(len);
 			SecurityBlob->DomainName.Buffer =
 			    cpu_to_le32(SecurityBlobLength);
-			bcc_ptr += SecurityBlob->DomainName.Length;
-			SecurityBlobLength += SecurityBlob->DomainName.Length;
+			bcc_ptr += len;
+			SecurityBlobLength += len;
 			SecurityBlob->DomainName.Length =
-			    cpu_to_le16(SecurityBlob->DomainName.Length);
+			    cpu_to_le16(len);
 		}
 		if (user == NULL) {
 			SecurityBlob->UserName.Buffer = 0;
 			SecurityBlob->UserName.Length = 0;
 			SecurityBlob->UserName.MaximumLength = 0;
 		} else {
-			SecurityBlob->UserName.Length =
+			__u16 len =
 			    cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
 					  nls_codepage);
-			SecurityBlob->UserName.Length *= 2;
+			len *= 2;
 			SecurityBlob->UserName.MaximumLength =
-			    cpu_to_le16(SecurityBlob->UserName.Length);
+			    cpu_to_le16(len);
 			SecurityBlob->UserName.Buffer =
 			    cpu_to_le32(SecurityBlobLength);
-			bcc_ptr += SecurityBlob->UserName.Length;
-			SecurityBlobLength += SecurityBlob->UserName.Length;
+			bcc_ptr += len;
+			SecurityBlobLength += len;
 			SecurityBlob->UserName.Length =
-			    cpu_to_le16(SecurityBlob->UserName.Length);
+			    cpu_to_le16(len);
 		}
 
 		/* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
@@ -2481,34 +2529,33 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 			SecurityBlob->DomainName.Length = 0;
 			SecurityBlob->DomainName.MaximumLength = 0;
 		} else {
-			SecurityBlob->NegotiateFlags |=
-			    NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
+			__u16 len;
+			negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
 			strncpy(bcc_ptr, domain, 63);
-			SecurityBlob->DomainName.Length = strnlen(domain, 64);
+			len = strnlen(domain, 64);
 			SecurityBlob->DomainName.MaximumLength =
-			    cpu_to_le16(SecurityBlob->DomainName.Length);
+			    cpu_to_le16(len);
 			SecurityBlob->DomainName.Buffer =
 			    cpu_to_le32(SecurityBlobLength);
-			bcc_ptr += SecurityBlob->DomainName.Length;
-			SecurityBlobLength += SecurityBlob->DomainName.Length;
-			SecurityBlob->DomainName.Length =
-			    cpu_to_le16(SecurityBlob->DomainName.Length);
+			bcc_ptr += len;
+			SecurityBlobLength += len;
+			SecurityBlob->DomainName.Length = cpu_to_le16(len);
 		}
 		if (user == NULL) {
 			SecurityBlob->UserName.Buffer = 0;
 			SecurityBlob->UserName.Length = 0;
 			SecurityBlob->UserName.MaximumLength = 0;
 		} else {
+			__u16 len;
 			strncpy(bcc_ptr, user, 63);
-			SecurityBlob->UserName.Length = strnlen(user, 64);
+			len = strnlen(user, 64);
 			SecurityBlob->UserName.MaximumLength =
-			    cpu_to_le16(SecurityBlob->UserName.Length);
+			    cpu_to_le16(len);
 			SecurityBlob->UserName.Buffer =
 			    cpu_to_le32(SecurityBlobLength);
-			bcc_ptr += SecurityBlob->UserName.Length;
-			SecurityBlobLength += SecurityBlob->UserName.Length;
-			SecurityBlob->UserName.Length =
-			    cpu_to_le16(SecurityBlob->UserName.Length);
+			bcc_ptr += len;
+			SecurityBlobLength += len;
+			SecurityBlob->UserName.Length = cpu_to_le16(len);
 		}
 		/* BB fill in our workstation name if known BB */
 
@@ -2521,12 +2568,11 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 		bcc_ptr++;	/* null domain */
 		*bcc_ptr = 0;
 	}
-	SecurityBlob->NegotiateFlags =
-	    cpu_to_le32(SecurityBlob->NegotiateFlags);
+	SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
 	pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
-	BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
-	smb_buffer->smb_buf_length += BCC(smb_buffer);
-	BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
+	count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
+	smb_buffer->smb_buf_length += count;
+	pSMB->req.ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
 			 &bytes_returned, 1);
@@ -2534,10 +2580,10 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
 /*    rc = map_smb_to_linux_error(smb_buffer_response);  *//* done in SendReceive now */
 	} else if ((smb_buffer_response->WordCount == 3)
 		   || (smb_buffer_response->WordCount == 4)) {
-		pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
-		pSMBr->resp.SecurityBlobLength =
+		__u16 action = le16_to_cpu(pSMBr->resp.Action);
+		__u16 blob_len =
 		    le16_to_cpu(pSMBr->resp.SecurityBlobLength);
-		if (pSMBr->resp.Action & GUEST_LOGIN)
+		if (action & GUEST_LOGIN)
 			cFYI(1, (" Guest login"));	/* BB do we want to set anything in SesInfo struct ? */
 /*        if(SecurityBlob2->MessageType != NtLm??){                               
                  cFYI("Unexpected message type on auth response is %d ")); 
@@ -2551,14 +2597,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
             /* response can have either 3 or 4 word count - Samba sends 3 */
 			if ((pSMBr->resp.hdr.WordCount == 3)
 			    || ((pSMBr->resp.hdr.WordCount == 4)
-				&& (pSMBr->resp.SecurityBlobLength <
+				&& (blob_len <
 				    pSMBr->resp.ByteCount))) {
 				if (pSMBr->resp.hdr.WordCount == 4) {
 					bcc_ptr +=
-					    pSMBr->resp.SecurityBlobLength;
+					    blob_len;
 					cFYI(1,
 					     ("Security Blob Length %d ",
-					      pSMBr->resp.SecurityBlobLength));
+					      blob_len));
 				}
 
 				cFYI(1,
@@ -2699,9 +2745,10 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
 	struct smb_hdr *smb_buffer_response;
 	TCONX_REQ *pSMB;
 	TCONX_RSP *pSMBr;
-	char *bcc_ptr;
+	unsigned char *bcc_ptr;
 	int rc = 0;
 	int length;
+	__u16 count;
 
 	if (ses == NULL)
 		return -EIO;
@@ -2721,7 +2768,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
 	pSMB->AndXCommand = 0xFF;
 	pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
 	pSMB->PasswordLength = cpu_to_le16(1);	/* minimum */
-	bcc_ptr = &(pSMB->Password[0]);
+	bcc_ptr = &pSMB->Password[0];
 	bcc_ptr++;		/* skip password */
 
 	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
@@ -2747,16 +2794,16 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
 	strcpy(bcc_ptr, "?????");
 	bcc_ptr += strlen("?????");
 	bcc_ptr += 1;
-	BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
-	smb_buffer->smb_buf_length += BCC(smb_buffer);
-	BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
+	count = bcc_ptr - &pSMB->Password[0];
+	pSMB->hdr.smb_buf_length += count;
+	pSMB->ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
 
 	/* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
 	/* above now done in SendReceive */
 	if ((rc == 0) && (tcon != NULL)) {
-        tcon->tidStatus = CifsGood;
+		tcon->tidStatus = CifsGood;
 		tcon->tid = smb_buffer_response->Tid;
 		bcc_ptr = pByteArea(smb_buffer_response);
 		length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
@@ -2765,8 +2812,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
 		strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
 		if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
 			length = UniStrnlen((wchar_t *) bcc_ptr, 512);
-			if (((long) bcc_ptr + (2 * length)) -
-			    (long) pByteArea(smb_buffer_response) <=
+			if ((bcc_ptr + (2 * length)) -
+			     pByteArea(smb_buffer_response) <=
 			    BCC(smb_buffer_response)) {
 				if(tcon->nativeFileSystem)
 					kfree(tcon->nativeFileSystem);
@@ -2783,8 +2830,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
 			/* else do not bother copying these informational fields */
 		} else {
 			length = strnlen(bcc_ptr, 1024);
-			if (((long) bcc_ptr + length) -
-			    (long) pByteArea(smb_buffer_response) <=
+			if ((bcc_ptr + length) -
+			    pByteArea(smb_buffer_response) <=
 			    BCC(smb_buffer_response)) {
 				if(tcon->nativeFileSystem)
 					kfree(tcon->nativeFileSystem);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 73505c6cc..bd31d4e2a 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -148,7 +148,7 @@ cifs_open(struct inode *inode, struct file *file)
 	and the first handle has writebehind data, we might be 
 	able to simply do a filemap_fdatawrite/filemap_fdatawait first */
 	buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
-	if(buf==0) {
+	if(buf== NULL) {
 		if (full_path)
 			kfree(full_path);
 		FreeXid(xid);
@@ -569,6 +569,8 @@ cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
 			 netfid, length,
 			 pfLock->fl_start, numUnlock, numLock, lockType,
 			 wait_flag);
+	if (rc == 0 && (pfLock->fl_flags & FL_POSIX))
+		posix_lock_file(file, pfLock);
 	FreeXid(xid);
 	return rc;
 }
@@ -1346,12 +1348,11 @@ fill_in_inode(struct inode *tmp_inode,
 {
 	struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
 	struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
+	__u32 attr = le32_to_cpu(pfindData->ExtFileAttributes);
+	__u64 allocation_size = le64_to_cpu(pfindData->AllocationSize);
+	__u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);
 
-	pfindData->ExtFileAttributes =
-	    le32_to_cpu(pfindData->ExtFileAttributes);
-	pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
-	pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
-	cifsInfo->cifsAttrs = pfindData->ExtFileAttributes;
+	cifsInfo->cifsAttrs = attr;
 	cifsInfo->time = jiffies;
 
 	/* Linux can not store file creation time unfortunately so ignore it */
@@ -1374,12 +1375,12 @@ fill_in_inode(struct inode *tmp_inode,
 
 	cFYI(0,
 	     ("CIFS FFIRST: Attributes came in as 0x%x",
-	      pfindData->ExtFileAttributes));
-	if (pfindData->ExtFileAttributes & ATTR_REPARSE) {
+	      attr));
+	if (attr & ATTR_REPARSE) {
 		*pobject_type = DT_LNK;
 		/* BB can this and S_IFREG or S_IFDIR be set as in Windows? */
 		tmp_inode->i_mode |= S_IFLNK;
-	} else if (pfindData->ExtFileAttributes & ATTR_DIRECTORY) {
+	} else if (attr & ATTR_DIRECTORY) {
 		*pobject_type = DT_DIR;
 		/* override default perms since we do not lock dirs */
 		if(atomic_read(&cifsInfo->inUse) == 0) {
@@ -1389,7 +1390,7 @@ fill_in_inode(struct inode *tmp_inode,
 	} else {
 		*pobject_type = DT_REG;
 		tmp_inode->i_mode |= S_IFREG;
-		if(pfindData->ExtFileAttributes & ATTR_READONLY)
+		if(attr & ATTR_READONLY)
 			tmp_inode->i_mode &= ~(S_IWUGO);
 
 	}/* could add code here - to validate if device or weird share type? */
@@ -1402,14 +1403,14 @@ fill_in_inode(struct inode *tmp_inode,
 	if(is_size_safe_to_change(cifsInfo)) {
 		/* can not safely change the file size here if the 
 		client is writing to it due to potential races */
-		i_size_write(tmp_inode,pfindData->EndOfFile);
+		i_size_write(tmp_inode,end_of_file);
 
 	/* 512 bytes (2**9) is the fake blocksize that must be used */
 	/* for this calculation, even though the reported blocksize is larger */
-		tmp_inode->i_blocks = (512 - 1 + pfindData->AllocationSize) >> 9;
+		tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9;
 	}
 
-	if (pfindData->AllocationSize < pfindData->EndOfFile)
+	if (allocation_size < end_of_file)
 		cFYI(1, ("Possible sparse file: allocation size less than end of file "));
 	cFYI(1,
 	     ("File Size %ld and blocks %ld and blocksize %ld",
@@ -1439,6 +1440,9 @@ unix_fill_in_inode(struct inode *tmp_inode,
 		   FILE_UNIX_INFO * pfindData, int *pobject_type)
 {
 	struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
+	__u32 type = le32_to_cpu(pfindData->Type);
+	__u64 num_of_bytes = le64_to_cpu(pfindData->NumOfBytes);
+	__u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);
 	cifsInfo->time = jiffies;
 	atomic_inc(&cifsInfo->inUse);
 
@@ -1450,30 +1454,29 @@ unix_fill_in_inode(struct inode *tmp_inode,
 	    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
 
 	tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
-	pfindData->Type = le32_to_cpu(pfindData->Type);
-	if (pfindData->Type == UNIX_FILE) {
+	if (type == UNIX_FILE) {
 		*pobject_type = DT_REG;
 		tmp_inode->i_mode |= S_IFREG;
-	} else if (pfindData->Type == UNIX_SYMLINK) {
+	} else if (type == UNIX_SYMLINK) {
 		*pobject_type = DT_LNK;
 		tmp_inode->i_mode |= S_IFLNK;
-	} else if (pfindData->Type == UNIX_DIR) {
+	} else if (type == UNIX_DIR) {
 		*pobject_type = DT_DIR;
 		tmp_inode->i_mode |= S_IFDIR;
-	} else if (pfindData->Type == UNIX_CHARDEV) {
+	} else if (type == UNIX_CHARDEV) {
 		*pobject_type = DT_CHR;
 		tmp_inode->i_mode |= S_IFCHR;
 		tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
 				le64_to_cpu(pfindData->DevMinor) & MINORMASK);
-	} else if (pfindData->Type == UNIX_BLOCKDEV) {
+	} else if (type == UNIX_BLOCKDEV) {
 		*pobject_type = DT_BLK;
 		tmp_inode->i_mode |= S_IFBLK;
 		tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
 				le64_to_cpu(pfindData->DevMinor) & MINORMASK);
-	} else if (pfindData->Type == UNIX_FIFO) {
+	} else if (type == UNIX_FIFO) {
 		*pobject_type = DT_FIFO;
 		tmp_inode->i_mode |= S_IFIFO;
-	} else if (pfindData->Type == UNIX_SOCKET) {
+	} else if (type == UNIX_SOCKET) {
 		*pobject_type = DT_SOCK;
 		tmp_inode->i_mode |= S_IFSOCK;
 	}
@@ -1482,17 +1485,15 @@ unix_fill_in_inode(struct inode *tmp_inode,
 	tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
 	tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
 
-	pfindData->NumOfBytes = le64_to_cpu(pfindData->NumOfBytes);
 
 	if(is_size_safe_to_change(cifsInfo)) {
 		/* can not safely change the file size here if the 
 		client is writing to it due to potential races */
-		pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
-		i_size_write(tmp_inode,pfindData->EndOfFile);
+		i_size_write(tmp_inode,end_of_file);
 
 	/* 512 bytes (2**9) is the fake blocksize that must be used */
 	/* for this calculation, not the real blocksize */
-		tmp_inode->i_blocks = (512 - 1 + pfindData->NumOfBytes) >> 9;
+		tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
 	}
 
 	if (S_ISREG(tmp_inode->i_mode)) {
@@ -1606,7 +1607,7 @@ cifs_filldir(struct qstr *pqstring, FILE_DIRECTORY_INFO * pfindData,
 	int object_type,rc;
 
 	pqstring->name = pfindData->FileName;
-	pqstring->len = pfindData->FileNameLength;
+	/* pqstring->len is already set by caller */
 
 	construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
 	if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
@@ -1685,8 +1686,12 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
 	}
 	data = kmalloc(bufsize, GFP_KERNEL);
 	pfindData = (FILE_DIRECTORY_INFO *) data;
-
+	if(data == NULL) {
+		FreeXid(xid);
+		return -ENOMEM;
+	}
 	if(file->f_dentry == NULL) {
+		kfree(data);
 		FreeXid(xid);
 		return -EIO;
 	}
@@ -1694,7 +1699,11 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
 	full_path = build_wildcard_path_from_dentry(file->f_dentry);
 	up(&file->f_dentry->d_sb->s_vfs_rename_sem);
 
-
+	if(full_path == NULL) {
+		kfree(data);
+		FreeXid(xid);
+		return -ENOMEM;
+	}
 	cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos));
 
 	switch ((int) file->f_pos) {
@@ -1736,10 +1745,12 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
 		rc = CIFSFindFirst(xid, pTcon, full_path, pfindData,
 				&findParms, cifs_sb->local_nls,
 				&Unicode, &UnixSearch);
-		cFYI(1, ("Count: %d  End: %d ", findParms.SearchCount,
-			findParms.EndofSearch));
+		cFYI(1, ("Count: %d  End: %d ",
+			le16_to_cpu(findParms.SearchCount),
+			le16_to_cpu(findParms.EndofSearch)));
  
 		if (rc == 0) {
+			__u16 count = le16_to_cpu(findParms.SearchCount);
 			searchHandle = findParms.SearchHandle;
 			if(file->private_data == NULL)
 				file->private_data =
@@ -1760,7 +1771,7 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
 			renew_parental_timestamps(file->f_dentry);
 			lastFindData = 
 				(FILE_DIRECTORY_INFO *) ((char *) pfindData + 
-					findParms.LastNameOffset);
+					le16_to_cpu(findParms.LastNameOffset));
 			if((char *)lastFindData > (char *)pfindData + bufsize) {
 				cFYI(1,("last search entry past end of packet"));
 				rc = -EIO;
@@ -1782,6 +1793,10 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
 				cFYI(1,("Last file: %s with name %d bytes long",
 					lastFindData->FileName,
 					cifsFile->resume_name_length));
+				if(cifsFile->search_resume_name == NULL) {
+					rc = -ENOMEM;
+					break;
+				}
 				memcpy(cifsFile->search_resume_name,
 					lastFindData->FileName, 
 					cifsFile->resume_name_length);
@@ -1811,27 +1826,29 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
 				cFYI(1,("Last file: %s with name %d bytes long",
 					pfindDataUnix->FileName,
 					cifsFile->resume_name_length));
+				if(cifsFile->search_resume_name == NULL) {
+					rc = -ENOMEM;
+					break;
+				}
 				memcpy(cifsFile->search_resume_name,
 					pfindDataUnix->FileName, 
 					cifsFile->resume_name_length);
 			}
-			for (i = 2; i < (unsigned int)findParms.SearchCount + 2; i++) {
+			for (i = 2; i < count + 2; i++) {
 				if (UnixSearch == FALSE) {
-					pfindData->FileNameLength =
-					  le32_to_cpu(pfindData->FileNameLength);
+					__u32 len = le32_to_cpu(pfindData->FileNameLength);
 					if (Unicode == TRUE)
-						pfindData->FileNameLength =
+						len =
 						    cifs_strfromUCS_le
 						    (pfindData->FileName,
 						     (wchar_t *)
 						     pfindData->FileName,
-						     (pfindData->
-						      FileNameLength) / 2,
+						     len / 2,
 						     cifs_sb->local_nls);
-					qstring.len = pfindData->FileNameLength;
-					if (((qstring.len != 1)
+					qstring.len = len;
+					if (((len != 1)
 					     || (pfindData->FileName[0] != '.'))
-					    && ((qstring.len != 2)
+					    && ((len != 2)
 						|| (pfindData->
 						    FileName[0] != '.')
 						|| (pfindData->
@@ -1899,7 +1916,7 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
 			}	/* end for loop */
 			if ((findParms.EndofSearch != 0) && cifsFile) {
 				cifsFile->endOfSearch = TRUE;
-				if(findParms.SearchCount == 2)
+				if(findParms.SearchCount == cpu_to_le16(2))
 					cifsFile->emptyDir = TRUE;
 			}
 		} else {
@@ -1930,13 +1947,14 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
 				cifsFile->resume_key,
 				&Unicode, &UnixSearch);
 			cFYI(1,("Count: %d  End: %d ",
-			      findNextParms.SearchCount,
-			      findNextParms.EndofSearch));
+			      le16_to_cpu(findNextParms.SearchCount),
+			      le16_to_cpu(findNextParms.EndofSearch)));
 			if ((rc == 0) && (findNextParms.SearchCount != 0)) {
 			/* BB save off resume key, key name and name length  */
+				__u16 count = le16_to_cpu(findNextParms.SearchCount);
 				lastFindData = 
 					(FILE_DIRECTORY_INFO *) ((char *) pfindData 
-						+ findNextParms.LastNameOffset);
+					+ le16_to_cpu(findNextParms.LastNameOffset));
 				if((char *)lastFindData > (char *)pfindData + bufsize) {
 					cFYI(1,("last search entry past end of packet"));
 					rc = -EIO;
@@ -1964,6 +1982,11 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
 					cFYI(1,("Last file: %s with name %d bytes long",
 						lastFindData->FileName,
 						cifsFile->resume_name_length));
+					if(cifsFile->search_resume_name == NULL) {
+						rc = -ENOMEM;
+						break;
+					}
+					
 					memcpy(cifsFile->search_resume_name,
 						lastFindData->FileName, 
 						cifsFile->resume_name_length);
@@ -1999,29 +2022,31 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
 					cFYI(1,("fnext last file: %s with name %d bytes long",
 						pfindDataUnix->FileName,
 						cifsFile->resume_name_length));
+					if(cifsFile->search_resume_name == NULL) {
+						rc = -ENOMEM;
+						break;
+					}
 					memcpy(cifsFile->search_resume_name,
 						pfindDataUnix->FileName, 
 						cifsFile->resume_name_length);
 				}
 
-				for (i = 0; i < findNextParms.SearchCount; i++) {
-					pfindData->FileNameLength =
-					    le32_to_cpu(pfindData->
+				for (i = 0; i < count; i++) {
+					__u32 len = le32_to_cpu(pfindData->
 							FileNameLength);
 					if (UnixSearch == FALSE) {
 						if (Unicode == TRUE)
-							pfindData->FileNameLength =
+							len =
 							  cifs_strfromUCS_le
 							  (pfindData->FileName,
 							  (wchar_t *)
 							  pfindData->FileName,
-							  (pfindData->FileNameLength)/ 2,
+							  len / 2,
 							  cifs_sb->local_nls);
-						qstring.len = 
-							pfindData->FileNameLength;
-						if (((qstring.len != 1)
+						qstring.len = len;
+						if (((len != 1)
 						    || (pfindData->FileName[0] != '.'))
-						    && ((qstring.len != 2)
+						    && ((len != 2)
 							|| (pfindData->FileName[0] != '.')
 							|| (pfindData->FileName[1] !=
 							    '.'))) {
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index a2965cfd3..84d09d9f1 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -76,6 +76,9 @@ cifs_get_inode_info_unix(struct inode **pinode,
 
 	} else {
 		struct cifsInodeInfo *cifsInfo;
+		__u32 type = le32_to_cpu(findData.Type);
+		__u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes);
+		__u64 end_of_file = le64_to_cpu(findData.EndOfFile);
 
 		/* get new inode */
 		if (*pinode == NULL) {
@@ -101,37 +104,34 @@ cifs_get_inode_info_unix(struct inode **pinode,
 		inode->i_ctime =
 		    cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
 		inode->i_mode = le64_to_cpu(findData.Permissions);
-		findData.Type = le32_to_cpu(findData.Type);
-		if (findData.Type == UNIX_FILE) {
+		if (type == UNIX_FILE) {
 			inode->i_mode |= S_IFREG;
-		} else if (findData.Type == UNIX_SYMLINK) {
+		} else if (type == UNIX_SYMLINK) {
 			inode->i_mode |= S_IFLNK;
-		} else if (findData.Type == UNIX_DIR) {
+		} else if (type == UNIX_DIR) {
 			inode->i_mode |= S_IFDIR;
-		} else if (findData.Type == UNIX_CHARDEV) {
+		} else if (type == UNIX_CHARDEV) {
 			inode->i_mode |= S_IFCHR;
 			inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
 				le64_to_cpu(findData.DevMinor) & MINORMASK);
-		} else if (findData.Type == UNIX_BLOCKDEV) {
+		} else if (type == UNIX_BLOCKDEV) {
 			inode->i_mode |= S_IFBLK;
 			inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
 				le64_to_cpu(findData.DevMinor) & MINORMASK);
-		} else if (findData.Type == UNIX_FIFO) {
+		} else if (type == UNIX_FIFO) {
 			inode->i_mode |= S_IFIFO;
-		} else if (findData.Type == UNIX_SOCKET) {
+		} else if (type == UNIX_SOCKET) {
 			inode->i_mode |= S_IFSOCK;
 		}
 		inode->i_uid = le64_to_cpu(findData.Uid);
 		inode->i_gid = le64_to_cpu(findData.Gid);
 		inode->i_nlink = le64_to_cpu(findData.Nlinks);
-		findData.NumOfBytes = le64_to_cpu(findData.NumOfBytes);
-		findData.EndOfFile = le64_to_cpu(findData.EndOfFile);
 
 		if(is_size_safe_to_change(cifsInfo)) {
 		/* can not safely change the file size here if the 
 		   client is writing to it due to potential races */
 
-			i_size_write(inode,findData.EndOfFile);
+			i_size_write(inode, end_of_file);
 /* blksize needs to be multiple of two. So safer to default to blksize
 	and blkbits set in superblock so 2**blkbits and blksize will match */
 /*		inode->i_blksize =
@@ -143,14 +143,14 @@ cifs_get_inode_info_unix(struct inode **pinode,
 		 
 
 /*		inode->i_blocks = 
-	                (inode->i_blksize - 1 + findData.NumOfBytes) >> inode->i_blkbits;*/
+	                (inode->i_blksize - 1 + num_of_bytes) >> inode->i_blkbits;*/
 
 		/* 512 bytes (2**9) is the fake blocksize that must be used */
 		/* for this calculation */
-			inode->i_blocks = (512 - 1 + findData.NumOfBytes) >> 9;
+			inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
 		}
 
-		if (findData.NumOfBytes < findData.EndOfFile)
+		if (num_of_bytes < end_of_file)
 			cFYI(1, ("Server inconsistency Error: it says allocation size less than end of file "));
 		cFYI(1,
 		     ("Size %ld and blocks %ld ",
@@ -201,6 +201,8 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
 	/* if file info not passed in then get it from server */
 	if(pfindData == NULL) {
 		buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
+		if(buf == NULL)
+			return -ENOMEM;
 		pfindData = (FILE_ALL_INFO *)buf;
 	/* could do find first instead but this returns more info */
 		rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
@@ -235,6 +237,7 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
 		}
 	} else {
 		struct cifsInodeInfo *cifsInfo;
+		__u32 attr = le32_to_cpu(pfindData->Attributes);
 
 		/* get new inode */
 		if (*pinode == NULL) {
@@ -245,8 +248,7 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
 		}
 		inode = *pinode;
 		cifsInfo = CIFS_I(inode);
-		pfindData->Attributes = le32_to_cpu(pfindData->Attributes);
-		cifsInfo->cifsAttrs = pfindData->Attributes;
+		cifsInfo->cifsAttrs = attr;
 		cFYI(1, (" Old time %ld ", cifsInfo->time));
 		cifsInfo->time = jiffies;
 		cFYI(1, (" New time %ld ", cifsInfo->time));
@@ -264,17 +266,17 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
 		inode->i_ctime =
 		    cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
 		cFYI(0,
-		     (" Attributes came in as 0x%x ", pfindData->Attributes));
+		     (" Attributes came in as 0x%x ", attr));
 
 		/* set default mode. will override for dirs below */
 		if(atomic_read(&cifsInfo->inUse) == 0)
 			/* new inode, can safely set these fields */
 			inode->i_mode = cifs_sb->mnt_file_mode;
 
-		if (pfindData->Attributes & ATTR_REPARSE) {
+		if (attr & ATTR_REPARSE) {
 	/* Can IFLNK be set as it basically is on windows with IFREG or IFDIR? */
 			inode->i_mode |= S_IFLNK;
-		} else if (pfindData->Attributes & ATTR_DIRECTORY) {
+		} else if (attr & ATTR_DIRECTORY) {
 	/* override default perms since we do not do byte range locking on dirs */
 			inode->i_mode = cifs_sb->mnt_dir_mode;
 			inode->i_mode |= S_IFDIR;
@@ -293,10 +295,9 @@ cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
 
 		/* 512 bytes (2**9) is the fake blocksize that must be used */
 		/* for this calculation */
-			inode->i_blocks = (512 - 1 + pfindData->AllocationSize)
+			inode->i_blocks = (512 - 1 + le64_to_cpu(pfindData->AllocationSize))
 				 >> 9;
 		}
-		pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
 
 		inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
 
@@ -949,7 +950,7 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
 	} else
 		time_buf.ChangeTime = 0;
 
-	if (set_time | time_buf.Attributes) {
+	if (set_time || time_buf.Attributes) {
 		/* BB what if setting one attribute fails  
 			(such as size) but time setting works */
 		time_buf.CreationTime = 0;	/* do not change */
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 8d1c2cb3b..1455810ba 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -20,6 +20,7 @@
  */
 #include <linux/fs.h>
 #include <linux/stat.h>
+#include <linux/namei.h>
 #include "cifsfs.h"
 #include "cifspdu.h"
 #include "cifsglob.h"
@@ -94,7 +95,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
 	int rc = -EACCES;
 	int xid;
 	char *full_path = NULL;
-	char * target_path;
+	char * target_path = ERR_PTR(-ENOMEM);
 	struct cifs_sb_info *cifs_sb;
 	struct cifsTconInfo *pTcon;
 
@@ -104,22 +105,17 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
 	full_path = build_path_from_dentry(direntry);
 	up(&direntry->d_sb->s_vfs_rename_sem);
 
-	if(full_path == NULL) {
-		FreeXid(xid);
-		return -ENOMEM;
-	}
+	if (!full_path)
+		goto out_no_free;
+
 	cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
 	cifs_sb = CIFS_SB(inode->i_sb);
 	pTcon = cifs_sb->tcon;
 	target_path = kmalloc(PATH_MAX, GFP_KERNEL);
-	if(target_path == NULL) {
-		if (full_path)
-			kfree(full_path);
-		FreeXid(xid);
-		return -ENOMEM;
+	if (!target_path) {
+		target_path = ERR_PTR(-ENOMEM);
+		goto out;
 	}
-	/* can not call the following line due to EFAULT in vfs_readlink which is presumably expecting a user space buffer */
-	/* length = cifs_readlink(direntry,target_path, sizeof(target_path) - 1);    */
 
 /* BB add read reparse point symlink code and Unix extensions symlink code here BB */
 	if (pTcon->ses->capabilities & CAP_UNIX)
@@ -130,25 +126,25 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
 	else {
 		/* rc = CIFSSMBQueryReparseLinkInfo */
 		/* BB Add code to Query ReparsePoint info */
+		/* BB Add MAC style xsymlink check here if enabled */
 	}
-	/* BB Anything else to do to handle recursive links? */
-	/* BB Should we be using page symlink ops here? */
 
 	if (rc == 0) {
 
 /* BB Add special case check for Samba DFS symlinks */
 
 		target_path[PATH_MAX-1] = 0;
-		rc = vfs_follow_link(nd, target_path);
+	} else {
+		kfree(target_path);
+		target_path = ERR_PTR(rc);
 	}
-	/* else EACCESS */
 
-	if (target_path)
-		kfree(target_path);
-	if (full_path)
-		kfree(full_path);
+out:
+	kfree(full_path);
+out_no_free:
 	FreeXid(xid);
-	return rc;
+	nd_set_link(nd, target_path);
+	return 0;
 }
 
 int
@@ -297,10 +293,7 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
 					if(referrals)
 						kfree(referrals);
 					kfree(tmp_path);
-					if(referrals) {
-						kfree(referrals);
-					}
-				}
+}
 				/* BB add code like else decode referrals then memcpy to
 				  tmpbuffer and free referrals string array BB */
 			}
@@ -326,3 +319,10 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
 	FreeXid(xid);
 	return rc;
 }
+
+void cifs_put_link(struct dentry *direntry, struct nameidata *nd)
+{
+	char *p = nd_get_link(nd);
+	if (!IS_ERR(p))
+		kfree(p);
+}
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index f3e258d11..6bf6ee31d 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -189,7 +189,6 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
     )
 {
 	int i;
-	__u32 tmp;
 	struct list_head* temp_item;
 	struct cifsSesInfo * ses;
 	char *temp = (char *) buffer;
@@ -211,10 +210,8 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
 	buffer->Command = smb_command;
 	buffer->Flags = 0x00;	/* case sensitive */
 	buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES;
-	tmp = cpu_to_le32(current->tgid);
-	buffer->Pid = tmp & 0xFFFF;
-	tmp >>= 16;
-	buffer->PidHigh = tmp & 0xFFFF;
+	buffer->Pid = cpu_to_le16((__u16)current->tgid);
+	buffer->PidHigh = cpu_to_le16((__u16)(current->tgid >> 16));
 	spin_lock(&GlobalMid_Lock);
 	GlobalMid++;
 	buffer->Mid = GlobalMid;
@@ -276,7 +273,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
 		}
 		if (treeCon->Flags & SMB_SHARE_IS_IN_DFS)
 			buffer->Flags2 |= SMBFLG2_DFS;
-		if(treeCon->ses->server)
+		if((treeCon->ses) && (treeCon->ses->server))
 			if(treeCon->ses->server->secMode & 
 			  (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
 				buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
@@ -292,7 +289,7 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid)
 {
 	/* Make sure that this really is an SMB, that it is a response, 
 	   and that the message ids match */
-	if ((*(unsigned int *) smb->Protocol == cpu_to_le32(0x424d53ff)) && 
+	if ((*(__le32 *) smb->Protocol == cpu_to_le32(0x424d53ff)) && 
 		(mid == smb->Mid)) {    
 		if(smb->Flags & SMBFLG_RESPONSE)
 			return 0;                    
@@ -304,7 +301,7 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid)
 				cERROR(1, ("Rcvd Request not response "));         
 		}
 	} else { /* bad signature or mid */
-		if (*(unsigned int *) smb->Protocol != cpu_to_le32(0x424d53ff))
+		if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff))
 			cERROR(1,
 			       ("Bad protocol string signature header %x ",
 				*(unsigned int *) smb->Protocol));
@@ -318,12 +315,12 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid)
 int
 checkSMB(struct smb_hdr *smb, __u16 mid, int length)
 {
+	__u32 len = be32_to_cpu(smb->smb_buf_length);
 	cFYI(0,
 	     ("Entering checkSMB with Length: %x, smb_buf_length: %x ",
-	      length, ntohl(smb->smb_buf_length)));
-	if (((unsigned int)length < 2 + sizeof (struct smb_hdr))
-	    || (ntohl(smb->smb_buf_length) >
-		CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)) {
+	      length, len));
+	if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) ||
+	    (len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)) {
 		if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) {
 			cERROR(1, ("Length less than 2 + sizeof smb_hdr "));
 			if (((unsigned int)length >= sizeof (struct smb_hdr) - 1)
@@ -331,8 +328,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
 				return 0;	/* some error cases do not return wct and bcc */
 
 		}
-		if (ntohl(smb->smb_buf_length) >
-		    CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)
+		if (len > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)
 			cERROR(1,
 			       ("smb_buf_length greater than CIFS_MAX_MSGSIZE ... "));
 		cERROR(1,
@@ -344,8 +340,8 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length)
 	if (checkSMBhdr(smb, mid))
 		return 1;
 
-	if ((4 + ntohl(smb->smb_buf_length) != smbCalcSize(smb))
-	    || (4 + ntohl(smb->smb_buf_length) != (unsigned int)length)) {
+	if ((4 + len != smbCalcSize(smb))
+	    || (4 + len != (unsigned int)length)) {
 		return 0;
 	} else {
 		cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb)));
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index c8d1a56fe..a78ed0add 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -187,8 +187,8 @@ cifs_inet_pton(int address_family, char *cp,void *dst)
 	if (value > addr_class_max[end - bytes])
 		return 0;
 
-	address.s_addr = *((int *) bytes) | htonl(value);
-	*((int *)dst) = address.s_addr;
+	address.s_addr = *((__be32 *) bytes) | htonl(value);
+	*((__be32 *)dst) = address.s_addr;
 	return 1; /* success */
 }
 
@@ -810,16 +810,13 @@ map_smb_to_linux_error(struct smb_hdr *smb)
 
 	if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
 		/* translate the newer STATUS codes to old style errors and then to POSIX errors */
-		smb->Status.CifsError = le32_to_cpu(smb->Status.CifsError);
+		__u32 err = le32_to_cpu(smb->Status.CifsError);
 		if(cifsFYI)
-			cifs_print_status(smb->Status.CifsError);
-		ntstatus_to_dos(smb->Status.CifsError, &smberrclass,
-				&smberrcode);
+			cifs_print_status(err);
+		ntstatus_to_dos(err, &smberrclass, &smberrcode);
 	} else {
 		smberrclass = smb->Status.DosError.ErrorClass;
-		smb->Status.DosError.Error =
-		    le16_to_cpu(smb->Status.DosError.Error);
-		smberrcode = smb->Status.DosError.Error;
+		smberrcode = le16_to_cpu(smb->Status.DosError.Error);
 	}
 
 	/* old style errors */
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h
index f06edcbea..5b15cee2c 100644
--- a/fs/cifs/ntlmssp.h
+++ b/fs/cifs/ntlmssp.h
@@ -23,10 +23,10 @@
 
 #define NTLMSSP_SIGNATURE "NTLMSSP"
 /* Message Types */
-#define NtLmNegotiate     1
-#define NtLmChallenge     2
-#define NtLmAuthenticate  3
-#define UnknownMessage    8
+#define NtLmNegotiate     cpu_to_le32(1)
+#define NtLmChallenge     cpu_to_le32(2)
+#define NtLmAuthenticate  cpu_to_le32(3)
+#define UnknownMessage    cpu_to_le32(8)
 
 /* Negotiate Flags */
 #define NTLMSSP_NEGOTIATE_UNICODE       0x01	// Text strings are in unicode
@@ -60,15 +60,15 @@
 /* appearance */
 
 typedef struct _SECURITY_BUFFER {
-	__u16 Length;
-	__u16 MaximumLength;
-	__u32 Buffer;		/* offset to buffer */
+	__le16 Length;
+	__le16 MaximumLength;
+	__le32 Buffer;		/* offset to buffer */
 } SECURITY_BUFFER;
 
 typedef struct _NEGOTIATE_MESSAGE {
 	__u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
-	__u32 MessageType;     /* 1 */
-	__u32 NegotiateFlags;
+	__le32 MessageType;     /* 1 */
+	__le32 NegotiateFlags;
 	SECURITY_BUFFER DomainName;	/* RFC 1001 style and ASCII */
 	SECURITY_BUFFER WorkstationName;	/* RFC 1001 and ASCII */
 	char DomainString[0];
@@ -77,9 +77,9 @@ typedef struct _NEGOTIATE_MESSAGE {
 
 typedef struct _CHALLENGE_MESSAGE {
 	__u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
-	__u32 MessageType;   /* 2 */
+	__le32 MessageType;   /* 2 */
 	SECURITY_BUFFER TargetName;
-	__u32 NegotiateFlags;
+	__le32 NegotiateFlags;
 	__u8 Challenge[CIFS_CRYPTO_KEY_SIZE];
 	__u8 Reserved[8];
 	SECURITY_BUFFER TargetInfoArray;
@@ -87,14 +87,14 @@ typedef struct _CHALLENGE_MESSAGE {
 
 typedef struct _AUTHENTICATE_MESSAGE {
 	__u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
-	__u32 MessageType;  /* 3 */
+	__le32 MessageType;  /* 3 */
 	SECURITY_BUFFER LmChallengeResponse;
 	SECURITY_BUFFER NtChallengeResponse;
 	SECURITY_BUFFER DomainName;
 	SECURITY_BUFFER UserName;
 	SECURITY_BUFFER WorkstationName;
 	SECURITY_BUFFER SessionKey;
-	__u32 NegotiateFlags;
+	__le32 NegotiateFlags;
 	char UserString[0];
 } AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
 
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index cdc7ed342..a19f4a9c9 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -123,11 +123,12 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
 	int i = 0;
 	struct msghdr smb_msg;
 	struct kvec iov;
+	unsigned len = smb_buf_length + 4;
 
 	if(ssocket == NULL)
 		return -ENOTSOCK; /* BB eventually add reconnect code here */
 	iov.iov_base = smb_buffer;
-	iov.iov_len = smb_buf_length + 4;
+	iov.iov_len = len;
 
 	smb_msg.msg_name = sin;
 	smb_msg.msg_namelen = sizeof (struct sockaddr);
@@ -142,10 +143,10 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
 
 	smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
 	cFYI(1, ("Sending smb of length %d ", smb_buf_length));
-	dump_smb(smb_buffer, smb_buf_length + 4);
+	dump_smb(smb_buffer, len);
 
-	while(iov.iov_len > 0) {
-		rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, smb_buf_length + 4);
+	while (len > 0) {
+		rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
 		if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
 			i++;
 			if(i > 60) {
@@ -163,6 +164,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
 			break;
 		iov.iov_base += rc;
 		iov.iov_len -= rc;
+		len -= rc;
 	}
 
 	if (rc < 0) {
@@ -181,7 +183,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
 {
 	int rc = 0;
 	unsigned int receive_len;
-	long timeout;
+	unsigned long timeout;
 	struct mid_q_entry *midQ;
 
 	if (ses == NULL) {
@@ -272,9 +274,6 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
 		return -EIO;
 	}
 
-	if (in_buf->smb_buf_length > 12)
-		in_buf->Flags2 = cpu_to_le16(in_buf->Flags2);
-	
 	rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number);
 
 	midQ->midState = MID_REQUEST_SUBMITTED;
@@ -307,27 +306,29 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
 	if (signal_pending(current)) {
 		/* if signal pending do not hold up user for full smb timeout
 		but we still give response a change to complete */
-		if(midQ->midState & MID_REQUEST_SUBMITTED) {
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			timeout = sleep_on_timeout(&ses->server->response_q,2 * HZ);
-		}
-	} else { /* using normal timeout */
-		/* timeout = wait_event_interruptible_timeout(ses->server->response_q,
+		timeout = 2 * HZ;
+		
+	}   
+
+	/* No user interrupts in wait - wreaks havoc with performance */
+	if(timeout != MAX_SCHEDULE_TIMEOUT) {
+		timeout += jiffies;
+		wait_event(ses->server->response_q,
 			(midQ->midState & MID_RESPONSE_RECEIVED) || 
+			time_after(jiffies, timeout) || 
 			((ses->server->tcpStatus != CifsGood) &&
-			 (ses->server->tcpStatus != CifsNew)),
-			timeout); */ 
-		/* Can not allow user interrupts- wreaks havoc with performance */
-		if(midQ->midState & MID_REQUEST_SUBMITTED) {
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			timeout = sleep_on_timeout(&ses->server->response_q,timeout);
-		}
+			 (ses->server->tcpStatus != CifsNew)));
+	} else {
+		wait_event(ses->server->response_q,
+			(midQ->midState & MID_RESPONSE_RECEIVED) || 
+			((ses->server->tcpStatus != CifsGood) &&
+			 (ses->server->tcpStatus != CifsNew)));
 	}
-    
+
 	spin_lock(&GlobalMid_Lock);
 	if (midQ->resp_buf) {
 		spin_unlock(&GlobalMid_Lock);
-		receive_len = be32_to_cpu(midQ->resp_buf->smb_buf_length);
+		receive_len = be32_to_cpu(*(__be32 *)midQ->resp_buf);
 	} else {
 		cERROR(1,("No response buffer"));
 		if(midQ->midState == MID_REQUEST_SUBMITTED) {
@@ -366,29 +367,20 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
 
 		if (midQ->resp_buf && out_buf
 		    && (midQ->midState == MID_RESPONSE_RECEIVED)) {
-			memcpy(out_buf, midQ->resp_buf,
-			       receive_len +
-			       4 /* include 4 byte RFC1001 header */ );
+			out_buf->smb_buf_length = receive_len;
+			memcpy((char *)out_buf + 4,
+			       (char *)midQ->resp_buf + 4,
+			       receive_len);
 
 			dump_smb(out_buf, 92);
 			/* convert the length into a more usable form */
-			out_buf->smb_buf_length =
-			    be32_to_cpu(out_buf->smb_buf_length);
-			if((out_buf->smb_buf_length > 24) &&
+			if((receive_len > 24) &&
 			   (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) {
 				rc = cifs_verify_signature(out_buf, ses->mac_signing_key,midQ->sequence_number); /* BB fix BB */
 				if(rc)
 					cFYI(1,("Unexpected signature received from server"));
 			}
 
-			if (out_buf->smb_buf_length > 12)
-				out_buf->Flags2 = le16_to_cpu(out_buf->Flags2);
-			if (out_buf->smb_buf_length > 28)
-				out_buf->Pid = le16_to_cpu(out_buf->Pid);
-			if (out_buf->smb_buf_length > 28)
-				out_buf->PidHigh =
-				    le16_to_cpu(out_buf->PidHigh);
-
 			*pbytes_returned = out_buf->smb_buf_length;
 
 			/* BB special case reconnect tid and reconnect uid here? */
diff --git a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c
index 2a1a5cfc8..5597080cb 100644
--- a/fs/coda/coda_linux.c
+++ b/fs/coda/coda_linux.c
@@ -28,7 +28,7 @@ int coda_fake_statfs;
 char * coda_f2s(struct CodaFid *f)
 {
 	static char s[60];
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
  	sprintf(s, "(%08x.%08x.%08x)", f->opaque[0], f->opaque[1], f->opaque[2]);
 #else
  	sprintf(s, "(%08x.%08x.%08x.%08x)", f->opaque[0], f->opaque[1], f->opaque[2], f->opaque[3]);
diff --git a/fs/coda/file.c b/fs/coda/file.c
index f0c867c7e..ba4141a95 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -44,6 +44,23 @@ coda_file_read(struct file *coda_file, char __user *buf, size_t count, loff_t *p
 	return host_file->f_op->read(host_file, buf, count, ppos);
 }
 
+static ssize_t
+coda_file_sendfile(struct file *coda_file, loff_t *ppos, size_t count,
+		   read_actor_t actor, void *target)
+{
+	struct coda_file_info *cfi;
+	struct file *host_file;
+
+	cfi = CODA_FTOC(coda_file);
+	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
+	host_file = cfi->cfi_container;
+
+	if (!host_file->f_op || !host_file->f_op->sendfile)
+		return -EINVAL;
+
+	return host_file->f_op->sendfile(host_file, ppos, count, actor, target);
+}
+
 static ssize_t
 coda_file_write(struct file *coda_file, const char __user *buf, size_t count, loff_t *ppos)
 {
@@ -278,5 +295,6 @@ struct file_operations coda_file_operations = {
 	.flush		= coda_flush,
 	.release	= coda_release,
 	.fsync		= coda_fsync,
+	.sendfile	= coda_file_sendfile,
 };
 
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index 9d39ef496..11b7eb1e7 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -69,7 +69,7 @@ int coda_init_inodecache(void)
 {
 	coda_inode_cachep = kmem_cache_create("coda_inode_cache",
 				sizeof(struct coda_inode_info),
-				0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+				0, SLAB_RECLAIM_ACCOUNT,
 				init_once, NULL);
 	if (coda_inode_cachep == NULL)
 		return -ENOMEM;
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index 6793b3740..9051ac173 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -405,7 +405,7 @@ static int __init init_coda(void)
 	int status;
 	int i;
 	printk(KERN_INFO "Coda Kernel/Venus communications, "
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
 	       "v5.3.20"
 #else
 	       "v6.0.0"
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
index 79c8803fe..569e144c6 100644
--- a/fs/coda/upcall.c
+++ b/fs/coda/upcall.c
@@ -55,7 +55,7 @@ static void *alloc_upcall(int opcode, int size)
         inp->ih.opcode = opcode;
 	inp->ih.pid = current->pid;
 	inp->ih.pgid = process_group(current);
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
 	memset(&inp->ih.cred, 0, sizeof(struct coda_cred));
 	inp->ih.cred.cr_fsuid = current->fsuid;
 #else
@@ -172,7 +172,7 @@ int venus_store(struct super_block *sb, struct CodaFid *fid, int flags,
         union inputArgs *inp;
         union outputArgs *outp;
         int insize, outsize, error;
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
 	struct coda_cred cred = { 0, };
 	cred.cr_fsuid = uid;
 #endif
@@ -180,7 +180,7 @@ int venus_store(struct super_block *sb, struct CodaFid *fid, int flags,
 	insize = SIZE(store);
 	UPARG(CODA_STORE);
 	
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
 	memcpy(&(inp->ih.cred), &cred, sizeof(cred));
 #else
 	inp->ih.uid = uid;
@@ -219,7 +219,7 @@ int venus_close(struct super_block *sb, struct CodaFid *fid, int flags,
 	union inputArgs *inp;
 	union outputArgs *outp;
 	int insize, outsize, error;
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
 	struct coda_cred cred = { 0, };
 	cred.cr_fsuid = uid;
 #endif
@@ -227,7 +227,7 @@ int venus_close(struct super_block *sb, struct CodaFid *fid, int flags,
 	insize = SIZE(release);
 	UPARG(CODA_CLOSE);
 	
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
 	memcpy(&(inp->ih.cred), &cred, sizeof(cred));
 #else
 	inp->ih.uid = uid;
diff --git a/fs/compat.c b/fs/compat.c
index 07f06a307..7257be91b 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -41,6 +41,7 @@
 #include <linux/nfsd/nfsd.h>
 #include <linux/nfsd/syscall.h>
 #include <linux/personality.h>
+#include <linux/rwsem.h>
 
 #include <net/sock.h>		/* siocdevprivate_ioctl */
 
@@ -247,7 +248,8 @@ out:
 /* ioctl32 stuff, used by sparc64, parisc, s390x, ppc64, x86_64, MIPS */
 
 #define IOCTL_HASHSIZE 256
-struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE];
+static struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE];
+static DECLARE_RWSEM(ioctl32_sem);
 
 extern struct ioctl_trans ioctl_start[];
 extern int ioctl_table_size;
@@ -291,8 +293,8 @@ static int __init init_sys32_ioctl(void)
 
 __initcall(init_sys32_ioctl);
 
-int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int,
-				unsigned int, unsigned long, struct file *))
+int register_ioctl32_conversion(unsigned int cmd,
+				ioctl_trans_handler_t handler)
 {
 	struct ioctl_trans *t;
 	struct ioctl_trans *new_t;
@@ -302,12 +304,12 @@ int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int,
 	if (!new_t)
 		return -ENOMEM;
 
-	lock_kernel(); 
+	down_write(&ioctl32_sem);
 	for (t = ioctl32_hash_table[hash]; t; t = t->next) {
 		if (t->cmd == cmd) {
 			printk(KERN_ERR "Trying to register duplicated ioctl32 "
 					"handler %x\n", cmd);
-			unlock_kernel();
+			up_write(&ioctl32_sem);
 			kfree(new_t);
 			return -EINVAL; 
 		}
@@ -317,7 +319,7 @@ int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int,
 	new_t->handler = handler;
 	ioctl32_insert_translation(new_t);
 
-	unlock_kernel();
+	up_write(&ioctl32_sem);
 	return 0;
 }
 EXPORT_SYMBOL(register_ioctl32_conversion);
@@ -337,11 +339,11 @@ int unregister_ioctl32_conversion(unsigned int cmd)
 	unsigned long hash = ioctl32_hash(cmd);
 	struct ioctl_trans *t, *t1;
 
-	lock_kernel(); 
+	down_write(&ioctl32_sem);
 
 	t = ioctl32_hash_table[hash];
 	if (!t) { 
-		unlock_kernel();
+		up_write(&ioctl32_sem);
 		return -EINVAL;
 	} 
 
@@ -351,7 +353,7 @@ int unregister_ioctl32_conversion(unsigned int cmd)
 			       __builtin_return_address(0), cmd);
 		} else { 
 			ioctl32_hash_table[hash] = t->next;
-			unlock_kernel();
+			up_write(&ioctl32_sem);
 			kfree(t);
 			return 0;
 		}
@@ -366,7 +368,7 @@ int unregister_ioctl32_conversion(unsigned int cmd)
 				goto out;
 			} else { 
 				t->next = t1->next;
-				unlock_kernel();
+				up_write(&ioctl32_sem);
 				kfree(t1);
 				return 0;
 			}
@@ -376,7 +378,7 @@ int unregister_ioctl32_conversion(unsigned int cmd)
 	printk(KERN_ERR "Trying to free unknown 32bit ioctl handler %x\n",
 				cmd);
 out:
-	unlock_kernel();
+	up_write(&ioctl32_sem);
 	return -EINVAL;
 }
 EXPORT_SYMBOL(unregister_ioctl32_conversion); 
@@ -397,7 +399,7 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
 		goto out;
 	}
 
-	lock_kernel();
+	down_read(&ioctl32_sem);
 
 	t = ioctl32_hash_table[ioctl32_hash (cmd)];
 
@@ -405,14 +407,16 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
 		t = t->next;
 	if (t) {
 		if (t->handler) { 
+			lock_kernel();
 			error = t->handler(fd, cmd, arg, filp);
 			unlock_kernel();
+			up_read(&ioctl32_sem);
 		} else {
-			unlock_kernel();
+			up_read(&ioctl32_sem);
 			error = sys_ioctl(fd, cmd, arg);
 		}
 	} else {
-		unlock_kernel();
+		up_read(&ioctl32_sem);
 		if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
 			error = siocdevprivate_ioctl(fd, cmd, arg);
 		} else {
@@ -429,6 +433,8 @@ asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd,
 			       		fn = d_path(filp->f_dentry,
 						filp->f_vfsmnt, path,
 						PAGE_SIZE);
+					if (IS_ERR(fn))
+						fn = "?";
 				}
 
 				sprintf(buf,"'%c'", (cmd>>24) & 0x3f);
@@ -522,8 +528,15 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
 		ret = sys_fcntl(fd, cmd, (unsigned long)&f);
 		set_fs(old_fs);
 		if ((cmd == F_GETLK) && (ret == 0)) {
+			/* POSIX-2001 now defines negative l_len */
+			if (f.l_len < 0) {
+				f.l_start += f.l_len;
+				f.l_len = -f.l_len;
+			}
+			if (f.l_start < 0)
+				return -EINVAL;
 			if ((f.l_start >= COMPAT_OFF_T_MAX) ||
-			    ((f.l_start + f.l_len) >= COMPAT_OFF_T_MAX))
+			    ((f.l_start + f.l_len) > COMPAT_OFF_T_MAX))
 				ret = -EOVERFLOW;
 			if (ret == 0)
 				ret = put_compat_flock(&f, compat_ptr(arg));
@@ -543,8 +556,15 @@ asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
 				(unsigned long)&f);
 		set_fs(old_fs);
 		if ((cmd == F_GETLK64) && (ret == 0)) {
+			/* POSIX-2001 now defines negative l_len */
+			if (f.l_len < 0) {
+				f.l_start += f.l_len;
+				f.l_len = -f.l_len;
+			}
+			if (f.l_start < 0)
+				return -EINVAL;
 			if ((f.l_start >= COMPAT_LOFF_T_MAX) ||
-			    ((f.l_start + f.l_len) >= COMPAT_LOFF_T_MAX))
+			    ((f.l_start + f.l_len) > COMPAT_LOFF_T_MAX))
 				ret = -EOVERFLOW;
 			if (ret == 0)
 				ret = put_compat_flock64(&f, compat_ptr(arg));
@@ -979,19 +999,14 @@ static int compat_filldir64(void * __buf, const char * name, int namlen, loff_t
 	dirent = buf->previous;
 
 	if (dirent) {
-		if (__put_user(offset, (u32 __user *)&dirent->d_off))
-			goto efault;
-		if (__put_user(offset >> 32,
-				((u32 __user *)&dirent->d_off) + 1))
+		if (__put_user_unaligned(offset, &dirent->d_off))
 			goto efault;
 	}
 	dirent = buf->current_dir;
-	if ((__put_user(ino, (u32 __user *)&dirent->d_ino))
-	 || (__put_user(ino >> 32, ((u32 __user *)&dirent->d_ino) + 1)))
+	if (__put_user_unaligned(ino, &dirent->d_ino))
 		goto efault;
 	off = 0;
-	if ((__put_user(off, (u32 __user *)&dirent->d_off))
-	 || (__put_user(off >> 32, ((u32 __user *)&dirent->d_off) + 1)))
+	if (__put_user_unaligned(off, &dirent->d_off))
 		goto efault;
 	if (__put_user(reclen, &dirent->d_reclen))
 		goto efault;
@@ -1040,8 +1055,7 @@ asmlinkage long compat_sys_getdents64(unsigned int fd,
 	lastdirent = buf.previous;
 	if (lastdirent) {
 		typeof(lastdirent->d_off) d_off = file->f_pos;
-		__put_user(d_off, (u32 __user *)&lastdirent->d_off);
-		__put_user(d_off >> 32, ((u32 __user *)&lastdirent->d_off) + 1);
+		__put_user_unaligned(d_off, &lastdirent->d_off);
 		error = count - buf.count;
 	}
 
@@ -1368,97 +1382,99 @@ int compat_do_execve(char * filename,
 	compat_uptr_t __user *envp,
 	struct pt_regs * regs)
 {
-	struct linux_binprm bprm;
+	struct linux_binprm *bprm;
 	struct file *file;
 	int retval;
 	int i;
 
-	sched_balance_exec();
-
 	file = open_exec(filename);
 
 	retval = PTR_ERR(file);
 	if (IS_ERR(file))
 		return retval;
 
-	bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
-	memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0]));
-
-	bprm.file = file;
-	bprm.filename = filename;
-	bprm.interp = filename;
-	bprm.sh_bang = 0;
-	bprm.loader = 0;
-	bprm.exec = 0;
-	bprm.security = NULL;
-	bprm.mm = mm_alloc();
+	sched_exec();
+
 	retval = -ENOMEM;
-	if (!bprm.mm)
+	bprm = kmalloc(sizeof(*bprm), GFP_KERNEL);
+	if (!bprm)
+		goto out_ret;
+	memset(bprm, 0, sizeof(*bprm));
+
+	bprm->p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
+	bprm->file = file;
+	bprm->filename = filename;
+	bprm->interp = filename;
+	bprm->mm = mm_alloc();
+	if (!bprm->mm)
 		goto out_file;
 
-	retval = init_new_context(current, bprm.mm);
+	retval = init_new_context(current, bprm->mm);
 	if (retval < 0)
 		goto out_mm;
 
-	bprm.argc = compat_count(argv, bprm.p / sizeof(compat_uptr_t));
-	if ((retval = bprm.argc) < 0)
+	bprm->argc = compat_count(argv, bprm->p / sizeof(compat_uptr_t));
+	if ((retval = bprm->argc) < 0)
 		goto out_mm;
 
-	bprm.envc = compat_count(envp, bprm.p / sizeof(compat_uptr_t));
-	if ((retval = bprm.envc) < 0)
+	bprm->envc = compat_count(envp, bprm->p / sizeof(compat_uptr_t));
+	if ((retval = bprm->envc) < 0)
 		goto out_mm;
 
-	retval = security_bprm_alloc(&bprm);
+	retval = security_bprm_alloc(bprm);
 	if (retval)
 		goto out;
 
-	retval = prepare_binprm(&bprm);
+	retval = prepare_binprm(bprm);
 	if (retval < 0)
 		goto out;
 
-	retval = copy_strings_kernel(1, &bprm.filename, &bprm);
+	retval = copy_strings_kernel(1, &bprm->filename, bprm);
 	if (retval < 0)
 		goto out;
 
-	bprm.exec = bprm.p;
-	retval = compat_copy_strings(bprm.envc, envp, &bprm);
+	bprm->exec = bprm->p;
+	retval = compat_copy_strings(bprm->envc, envp, bprm);
 	if (retval < 0)
 		goto out;
 
-	retval = compat_copy_strings(bprm.argc, argv, &bprm);
+	retval = compat_copy_strings(bprm->argc, argv, bprm);
 	if (retval < 0)
 		goto out;
 
-	retval = search_binary_handler(&bprm,regs);
+	retval = search_binary_handler(bprm, regs);
 	if (retval >= 0) {
-		free_arg_pages(&bprm);
+		free_arg_pages(bprm);
 
 		/* execve success */
-		security_bprm_free(&bprm);
+		security_bprm_free(bprm);
+		kfree(bprm);
 		return retval;
 	}
 
 out:
 	/* Something went wrong, return the inode and free the argument pages*/
 	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
-		struct page * page = bprm.page[i];
+		struct page * page = bprm->page[i];
 		if (page)
 			__free_page(page);
 	}
 
-	if (bprm.security)
-		security_bprm_free(&bprm);
+	if (bprm->security)
+		security_bprm_free(bprm);
 
 out_mm:
-	if (bprm.mm)
-		mmdrop(bprm.mm);
+	if (bprm->mm)
+		mmdrop(bprm->mm);
 
 out_file:
-	if (bprm.file) {
-		allow_write_access(bprm.file);
-		fput(bprm.file);
+	if (bprm->file) {
+		allow_write_access(bprm->file);
+		fput(bprm->file);
 	}
+	kfree(bprm);
 
+out_ret:
 	return retval;
 }
 
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index dc1a2d2c4..2edf63444 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -15,6 +15,7 @@
 #include <linux/types.h>
 #include <linux/compat.h>
 #include <linux/kernel.h>
+#include <linux/compiler.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
@@ -115,6 +116,8 @@
 #include <linux/filter.h>
 #include <linux/msdos_fs.h>
 
+#include <linux/hiddev.h>
+
 #undef INCLUDES
 #endif
 
@@ -407,6 +410,7 @@ out:
 	return err;
 }
 
+#ifdef CONFIG_NET
 static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct compat_timeval __user *up = compat_ptr(arg);
@@ -461,7 +465,6 @@ struct ifconf32 {
         compat_caddr_t  ifcbuf;
 };
 
-#ifdef CONFIG_NET
 static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct net_device *dev;
@@ -481,7 +484,6 @@ static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
 	err = copy_to_user(compat_ptr(arg), &ifr32, sizeof(ifr32));
 	return (err ? -EFAULT : 0);
 }
-#endif
 
 static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
@@ -797,6 +799,7 @@ static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 
 	return ret;
 }
+#endif
 
 struct hd_geometry32 {
 	unsigned char heads;
@@ -1872,7 +1875,8 @@ static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg)
         return -EINVAL;
 }
 
-static int ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg)
+static __attribute_used__ int 
+ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	return -EINVAL;
 }
@@ -3162,7 +3166,6 @@ HANDLE_IOCTL(MEMREADOOB32, mtd_rw_oob)
 HANDLE_IOCTL(MEMWRITEOOB32, mtd_rw_oob)
 #ifdef CONFIG_NET
 HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32)
-#endif
 HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf)
 HANDLE_IOCTL(SIOCGIFFLAGS, dev_ifsioc)
 HANDLE_IOCTL(SIOCSIFFLAGS, dev_ifsioc)
@@ -3206,6 +3209,7 @@ HANDLE_IOCTL(SIOCBRDELIF, dev_ifsioc)
 /* Note SIOCRTMSG is no longer, so this is safe and * the user would have seen just an -EINVAL anyways. */
 HANDLE_IOCTL(SIOCRTMSG, ret_einval)
 HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp)
+#endif
 HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo)
 HANDLE_IOCTL(BLKRAGET, w_long)
 HANDLE_IOCTL(BLKGETSIZE, w_long)
diff --git a/fs/dcache.c b/fs/dcache.c
index 425c2e568..f938ad50f 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -144,6 +144,8 @@ void dput(struct dentry *dentry)
 		return;
 
 repeat:
+	if (atomic_read(&dentry->d_count) == 1)
+		might_sleep();
 	if (!atomic_dec_and_lock(&dentry->d_count, &dcache_lock))
 		return;
 
@@ -286,12 +288,11 @@ struct dentry * dget_locked(struct dentry *dentry)
  * any other hashed alias over that one.
  */
 
-struct dentry * d_find_alias(struct inode *inode)
+static struct dentry * __d_find_alias(struct inode *inode, int want_discon)
 {
 	struct list_head *head, *next, *tmp;
 	struct dentry *alias, *discon_alias=NULL;
 
-	spin_lock(&dcache_lock);
 	head = &inode->i_dentry;
 	next = inode->i_dentry.next;
 	while (next != head) {
@@ -302,19 +303,26 @@ struct dentry * d_find_alias(struct inode *inode)
  		if (!d_unhashed(alias)) {
 			if (alias->d_flags & DCACHE_DISCONNECTED)
 				discon_alias = alias;
-			else {
+			else if (!want_discon) {
 				__dget_locked(alias);
-				spin_unlock(&dcache_lock);
 				return alias;
 			}
 		}
 	}
 	if (discon_alias)
 		__dget_locked(discon_alias);
-	spin_unlock(&dcache_lock);
 	return discon_alias;
 }
 
+struct dentry * d_find_alias(struct inode *inode)
+{
+	struct dentry *de;
+	spin_lock(&dcache_lock);
+	de = __d_find_alias(inode, 0);
+	spin_unlock(&dcache_lock);
+	return de;
+}
+
 /*
  *	Try to kill dentries associated with this inode.
  * WARNING: you must own a reference to inode.
@@ -613,7 +621,7 @@ void shrink_dcache_parent(struct dentry * parent)
  *
  * Prune the dentries that are anonymous
  *
- * parsing d_hash list does not read_barrier_depends() as it
+ * parsing d_hash list does not hlist_for_each_rcu() as it
  * done under dcache_lock.
  *
  */
@@ -833,33 +841,27 @@ struct dentry * d_alloc_anon(struct inode *inode)
 	tmp->d_parent = tmp; /* make sure dput doesn't croak */
 	
 	spin_lock(&dcache_lock);
-	if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry)) {
-		/* A directory can only have one dentry.
-		 * This (now) has one, so use it.
-		 */
-		res = list_entry(inode->i_dentry.next, struct dentry, d_alias);
-		__dget_locked(res);
-	} else {
+	res = __d_find_alias(inode, 0);
+	if (!res) {
 		/* attach a disconnected dentry */
 		res = tmp;
 		tmp = NULL;
-		if (res) {
-			spin_lock(&res->d_lock);
-			res->d_sb = inode->i_sb;
-			res->d_parent = res;
-			res->d_inode = inode;
+		spin_lock(&res->d_lock);
+		res->d_sb = inode->i_sb;
+		res->d_parent = res;
+		res->d_inode = inode;
+
+		/*
+		 * Set d_bucket to an "impossible" bucket address so
+		 * that d_move() doesn't get a false positive
+		 */
+		res->d_bucket = NULL;
+		res->d_flags |= DCACHE_DISCONNECTED;
+		res->d_flags &= ~DCACHE_UNHASHED;
+		list_add(&res->d_alias, &inode->i_dentry);
+		hlist_add_head(&res->d_hash, &inode->i_sb->s_anon);
+		spin_unlock(&res->d_lock);
 
-			/*
-			 * Set d_bucket to an "impossible" bucket address so
-			 * that d_move() doesn't get a false positive
-			 */
-			res->d_bucket = NULL;
-			res->d_flags |= DCACHE_DISCONNECTED;
-			res->d_flags &= ~DCACHE_UNHASHED;
-			list_add(&res->d_alias, &inode->i_dentry);
-			hlist_add_head(&res->d_hash, &inode->i_sb->s_anon);
-			spin_unlock(&res->d_lock);
-		}
 		inode = NULL; /* don't drop reference */
 	}
 	spin_unlock(&dcache_lock);
@@ -881,7 +883,7 @@ struct dentry * d_alloc_anon(struct inode *inode)
  * DCACHE_DISCONNECTED), then d_move that in place of the given dentry
  * and return it, else simply d_add the inode to the dentry and return NULL.
  *
- * This is (will be) needed in the lookup routine of any filesystem that is exportable
+ * This is needed in the lookup routine of any filesystem that is exportable
  * (via knfsd) so that we can build dcache paths to directories effectively.
  *
  * If a dentry was found and moved, then it is returned.  Otherwise NULL
@@ -892,11 +894,11 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
 {
 	struct dentry *new = NULL;
 
-	if (inode && S_ISDIR(inode->i_mode)) {
+	if (inode) {
 		spin_lock(&dcache_lock);
-		if (!list_empty(&inode->i_dentry)) {
-			new = list_entry(inode->i_dentry.next, struct dentry, d_alias);
-			__dget_locked(new);
+		new = __d_find_alias(inode, 1);
+		if (new) {
+			BUG_ON(!(new->d_flags & DCACHE_DISCONNECTED));
 			spin_unlock(&dcache_lock);
 			security_d_instantiate(new, inode);
 			d_rehash(dentry);
@@ -970,11 +972,10 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name)
 
 	rcu_read_lock();
 	
-	hlist_for_each (node, head) { 
+	hlist_for_each_rcu(node, head) {
 		struct dentry *dentry; 
 		struct qstr *qstr;
 
-		smp_read_barrier_depends();
 		dentry = hlist_entry(node, struct dentry, d_hash);
 
 		smp_rmb();
@@ -1001,8 +1002,7 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name)
 		if (dentry->d_parent != parent)
 			goto next;
 
-		qstr = &dentry->d_name;
-		smp_read_barrier_depends();
+		qstr = rcu_dereference(&dentry->d_name);
 		if (parent->d_op && parent->d_op->d_compare) {
 			if (parent->d_op->d_compare(parent, qstr, name))
 				goto next;
@@ -1055,7 +1055,7 @@ int d_validate(struct dentry *dentry, struct dentry *dparent)
 	spin_lock(&dcache_lock);
 	base = d_hash(dparent, dentry->d_name.hash);
 	hlist_for_each(lhp,base) { 
-		/* read_barrier_depends() not required for d_hash list
+		/* hlist_for_each_rcu() not required for d_hash list
 		 * as it is parsed under dcache_lock
 		 */
 		if (dentry == hlist_entry(lhp, struct dentry, d_hash)) {
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index a429f2817..db40284e7 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -69,6 +69,68 @@ static int devpts_remount(struct super_block *sb, int *flags, char *data)
 	return 0;
 }
 
+static int devpts_readdir(struct file * filp, void * dirent, filldir_t filldir)
+{
+	struct dentry *dentry = filp->f_dentry;
+	struct dentry *cursor = filp->private_data;
+	struct list_head *p, *q = &cursor->d_child;
+	ino_t ino;
+	int i = filp->f_pos;
+
+	switch (i) {
+		case 0:
+			ino = dentry->d_inode->i_ino;
+			if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
+				break;
+			filp->f_pos++;
+			i++;
+			/* fallthrough */
+		case 1:
+			ino = parent_ino(dentry);
+			if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
+				break;
+			filp->f_pos++;
+			i++;
+			/* fallthrough */
+		default:
+			spin_lock(&dcache_lock);
+			if (filp->f_pos == 2) {
+				list_del(q);
+				list_add(q, &dentry->d_subdirs);
+			}
+			for (p=q->next; p != &dentry->d_subdirs; p=p->next) {
+				struct dentry *next;
+				next = list_entry(p, struct dentry, d_child);
+				if (d_unhashed(next) || !next->d_inode)
+					continue;
+				if (!vx_check(next->d_inode->i_xid, VX_IDENT))
+					continue;
+
+				spin_unlock(&dcache_lock);
+				if (filldir(dirent, next->d_name.name,
+					next->d_name.len, filp->f_pos,
+					next->d_inode->i_ino, DT_CHR) < 0)
+					return 0;
+				spin_lock(&dcache_lock);
+				/* next is still alive */
+				list_del(q);
+				list_add(q, p);
+				p = q;
+				filp->f_pos++;
+			}
+			spin_unlock(&dcache_lock);
+	}
+	return 0;
+}
+
+static struct file_operations devpts_dir_operations = {
+	.open		= dcache_dir_open,
+	.release	= dcache_dir_close,
+	.llseek		= dcache_dir_lseek,
+	.read		= generic_read_dir,
+	.readdir	= devpts_readdir,
+};
+
 static struct super_operations devpts_sops = {
 	.statfs		= simple_statfs,
 	.remount_fs	= devpts_remount,
@@ -94,7 +156,7 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
 	inode->i_uid = inode->i_gid = 0;
 	inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
 	inode->i_op = &simple_dir_inode_operations;
-	inode->i_fop = &simple_dir_operations;
+	inode->i_fop = &devpts_dir_operations;
 	inode->i_nlink = 2;
 	inode->i_xid = vx_current_xid();
 
@@ -137,7 +199,7 @@ static struct dentry *get_node(int num)
 static int devpts_permission(struct inode *inode, int mask, struct nameidata *nd)
 {
 	int ret = -EACCES;
-	
+
 	if (vx_check(inode->i_xid, VX_IDENT))
 		ret = vfs_permission(inode, mask);
 	return ret;
@@ -190,8 +252,12 @@ struct tty_struct *devpts_get_tty(int number)
 	struct dentry *dentry = get_node(number);
 	struct tty_struct *tty;
 
-	tty = (IS_ERR(dentry) || !dentry->d_inode) ? NULL :
-			dentry->d_inode->u.generic_ip;
+	tty = NULL;
+	if (!IS_ERR(dentry)) {
+		if (dentry->d_inode)
+			tty = dentry->d_inode->u.generic_ip;
+		dput(dentry);
+	}
 
 	up(&devpts_root->d_inode->i_sem);
 
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 37f593c42..afc38f43f 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -53,9 +53,12 @@
  * If blkfactor is zero then the user's request was aligned to the filesystem's
  * blocksize.
  *
- * needs_locking is set for regular files on direct-IO-naive filesystems.  It
- * determines whether we need to do the fancy locking which prevents direct-IO
- * from being able to read uninitialised disk blocks.
+ * lock_type is DIO_LOCKING for regular files on direct-IO-naive filesystems.
+ * This determines whether we need to do the fancy locking which prevents
+ * direct-IO from being able to read uninitialised disk blocks.  If its zero
+ * (blockdev) this locking is not done, and if it is DIO_OWN_LOCKING i_sem is
+ * not held for the entire direct write (taken briefly, initially, during a
+ * direct read though, but its never held for the duration of a direct-IO).
  */
 
 struct dio {
@@ -63,7 +66,7 @@ struct dio {
 	struct bio *bio;		/* bio under assembly */
 	struct inode *inode;
 	int rw;
-	int needs_locking;		/* doesn't change */
+	int lock_type;			/* doesn't change */
 	unsigned blkbits;		/* doesn't change */
 	unsigned blkfactor;		/* When we're using an alignment which
 					   is finer than the filesystem's soft
@@ -212,7 +215,7 @@ static void dio_complete(struct dio *dio, loff_t offset, ssize_t bytes)
 {
 	if (dio->end_io && dio->result)
 		dio->end_io(dio->inode, offset, bytes, dio->map_bh.b_private);
-	if (dio->needs_locking)
+	if (dio->lock_type != DIO_NO_LOCKING)
 		up_read(&dio->inode->i_alloc_sem);
 }
 
@@ -235,7 +238,8 @@ static void finished_one_bio(struct dio *dio)
 			dio_complete(dio, dio->block_in_file << dio->blkbits,
 					dio->result);
 			/* Complete AIO later if falling back to buffered i/o */
-			if (dio->result == dio->size || dio->rw == READ) {
+			if (dio->result == dio->size ||
+				((dio->rw == READ) && dio->result)) {
 				aio_complete(dio->iocb, dio->result, 0);
 				kfree(dio);
 				return;
@@ -492,7 +496,7 @@ static int get_more_blocks(struct dio *dio)
 	unsigned long fs_count;	/* Number of filesystem-sized blocks */
 	unsigned long dio_count;/* Number of dio_block-sized blocks */
 	unsigned long blkmask;
-	int beyond_eof = 0;
+	int create;
 
 	/*
 	 * If there was a memory error and we've overwritten all the
@@ -510,10 +514,13 @@ static int get_more_blocks(struct dio *dio)
 		if (dio_count & blkmask)	
 			fs_count++;
 
-		if (dio->needs_locking) {
-			if (dio->block_in_file >= (i_size_read(dio->inode) >>
+		create = dio->rw == WRITE;
+		if (dio->lock_type == DIO_LOCKING) {
+			if (dio->block_in_file < (i_size_read(dio->inode) >>
 							dio->blkbits))
-				beyond_eof = 1;
+				create = 0;
+		} else if (dio->lock_type == DIO_NO_LOCKING) {
+			create = 0;
 		}
 		/*
 		 * For writes inside i_size we forbid block creations: only
@@ -522,7 +529,7 @@ static int get_more_blocks(struct dio *dio)
 		 * writes.
 		 */
 		ret = (*dio->get_blocks)(dio->inode, fs_startblk, fs_count,
-				map_bh, (dio->rw == WRITE) && beyond_eof);
+						map_bh, create);
 	}
 	return ret;
 }
@@ -561,7 +568,11 @@ static int dio_bio_add_page(struct dio *dio)
 	ret = bio_add_page(dio->bio, dio->cur_page,
 			dio->cur_page_len, dio->cur_page_offset);
 	if (ret == dio->cur_page_len) {
-		dio->pages_in_io--;
+		/*
+		 * Decrement count only, if we are done with this page
+		 */
+		if ((dio->cur_page_len + dio->cur_page_offset) == PAGE_SIZE)
+			dio->pages_in_io--;
 		page_cache_get(dio->cur_page);
 		dio->final_block_in_bio = dio->cur_page_block +
 			(dio->cur_page_len >> dio->blkbits);
@@ -953,9 +964,21 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
 	dio->bio_list = NULL;
 	dio->waiter = NULL;
 
-	dio->pages_in_io = 0;
-	for (seg = 0; seg < nr_segs; seg++) 
-		dio->pages_in_io += (iov[seg].iov_len >> blkbits) + 2; 
+	/*
+	 * In case of non-aligned buffers, we may need 2 more
+	 * pages since we need to zero out first and last block.
+	 */
+	if (unlikely(dio->blkfactor))
+		dio->pages_in_io = 2;
+	else
+		dio->pages_in_io = 0;
+
+	for (seg = 0; seg < nr_segs; seg++) {
+		user_addr = (unsigned long)iov[seg].iov_base;
+		dio->pages_in_io +=
+			((user_addr+iov[seg].iov_len +PAGE_SIZE-1)/PAGE_SIZE
+				- user_addr/PAGE_SIZE);
+	}
 
 	for (seg = 0; seg < nr_segs; seg++) {
 		user_addr = (unsigned long)iov[seg].iov_base;
@@ -1024,7 +1047,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
 	 * we can let i_sem go now that its achieved its purpose
 	 * of protecting us from looking up uninitialized blocks.
 	 */
-	if ((rw == READ) && dio->needs_locking)
+	if ((rw == READ) && (dio->lock_type == DIO_LOCKING))
 		up(&dio->inode->i_sem);
 
 	/*
@@ -1111,7 +1134,7 @@ ssize_t
 __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
 	struct block_device *bdev, const struct iovec *iov, loff_t offset, 
 	unsigned long nr_segs, get_blocks_t get_blocks, dio_iodone_t end_io,
-	int needs_special_locking)
+	int dio_lock_type)
 {
 	int seg;
 	size_t size;
@@ -1122,7 +1145,6 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
 	ssize_t retval = -EINVAL;
 	loff_t end = offset;
 	struct dio *dio;
-	int needs_locking;
 
 	if (bdev)
 		bdev_blkbits = blksize_bits(bdev_hardsect_size(bdev));
@@ -1155,13 +1177,15 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
 		goto out;
 
 	/*
-	 * For regular files,
+	 * For regular files using DIO_LOCKING,
 	 *	readers need to grab i_sem and i_alloc_sem
 	 *	writers need to grab i_alloc_sem only (i_sem is already held)
+	 * For regular files using DIO_OWN_LOCKING,
+	 *	both readers and writers need to grab i_alloc_sem
+	 *	neither readers nor writers hold i_sem on entry (nor exit)
 	 */
-	needs_locking = 0;
-	if (S_ISREG(inode->i_mode) && needs_special_locking) {
-		needs_locking = 1;
+	dio->lock_type = dio_lock_type;
+	if (dio_lock_type != DIO_NO_LOCKING) {
 		if (rw == READ) {
 			struct address_space *mapping;
 
@@ -1173,10 +1197,13 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
 				kfree(dio);
 				goto out;
 			}
+			down_read(&inode->i_alloc_sem);
+			if (dio_lock_type == DIO_OWN_LOCKING)
+				up(&inode->i_sem);
+		} else {
+			down_read(&inode->i_alloc_sem);
 		}
-		down_read(&inode->i_alloc_sem);
 	}
-	dio->needs_locking = needs_locking;
 	/*
 	 * For file extending writes updating i_size before data
 	 * writeouts complete can expose uninitialized blocks. So
diff --git a/fs/dquot.c b/fs/dquot.c
index 35c84acdc..b035fc4b4 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -120,7 +120,7 @@
  * i_sem on quota files is special (it's below dqio_sem)
  */
 
-spinlock_t dq_list_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t dq_list_lock = SPIN_LOCK_UNLOCKED;
 spinlock_t dq_data_lock = SPIN_LOCK_UNLOCKED;
 
 static char *quotatypes[] = INITQFNAMES;
@@ -1792,7 +1792,6 @@ module_init(dquot_init);
 EXPORT_SYMBOL(register_quota_format);
 EXPORT_SYMBOL(unregister_quota_format);
 EXPORT_SYMBOL(dqstats);
-EXPORT_SYMBOL(dq_list_lock);
 EXPORT_SYMBOL(dq_data_lock);
 EXPORT_SYMBOL(vfs_quota_on);
 EXPORT_SYMBOL(vfs_quota_on_mount);
diff --git a/fs/efs/inode.c b/fs/efs/inode.c
index 2265e2ab1..180607f93 100644
--- a/fs/efs/inode.c
+++ b/fs/efs/inode.c
@@ -13,8 +13,6 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 
-
-extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 static int efs_readpage(struct file *file, struct page *page)
 {
 	return block_read_full_page(page,efs_get_block);
@@ -23,7 +21,7 @@ static sector_t _efs_bmap(struct address_space *mapping, sector_t block)
 {
 	return generic_block_bmap(mapping,block,efs_get_block);
 }
-struct address_space_operations efs_aops = {
+static struct address_space_operations efs_aops = {
 	.readpage = efs_readpage,
 	.sync_page = block_sync_page,
 	.bmap = _efs_bmap
diff --git a/fs/efs/super.c b/fs/efs/super.c
index d4910e43a..467e34b41 100644
--- a/fs/efs/super.c
+++ b/fs/efs/super.c
@@ -15,6 +15,9 @@
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
 
+static int efs_statfs(struct super_block *s, struct kstatfs *buf);
+static int efs_fill_super(struct super_block *s, void *d, int silent);
+
 static struct super_block *efs_get_sb(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *data)
 {
@@ -58,7 +61,7 @@ static int init_inodecache(void)
 {
 	efs_inode_cachep = kmem_cache_create("efs_inode_cache",
 				sizeof(struct efs_inode_info),
-				0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+				0, SLAB_RECLAIM_ACCOUNT,
 				init_once, NULL);
 	if (efs_inode_cachep == NULL)
 		return -ENOMEM;
@@ -71,7 +74,7 @@ static void destroy_inodecache(void)
 		printk(KERN_INFO "efs_inode_cache: not all structures were freed\n");
 }
 
-void efs_put_super(struct super_block *s)
+static void efs_put_super(struct super_block *s)
 {
 	kfree(s->s_fs_info);
 	s->s_fs_info = NULL;
@@ -118,7 +121,8 @@ module_exit(exit_efs_fs)
 
 static efs_block_t efs_validate_vh(struct volume_header *vh) {
 	int		i;
-	unsigned int	cs, csum, *ui;
+	__be32		cs, *ui;
+	int		csum;
 	efs_block_t	sblock = 0; /* shuts up gcc */
 	struct pt_types	*pt_entry;
 	int		pt_type, slice = -1;
@@ -132,8 +136,8 @@ static efs_block_t efs_validate_vh(struct volume_header *vh) {
 		return 0;
 	}
 
-	ui = ((unsigned int *) (vh + 1)) - 1;
-	for(csum = 0; ui >= ((unsigned int *) vh);) {
+	ui = ((__be32 *) (vh + 1)) - 1;
+	for(csum = 0; ui >= ((__be32 *) vh);) {
 		cs = *ui--;
 		csum += be32_to_cpu(cs);
 	}
@@ -213,7 +217,7 @@ static int efs_validate_super(struct efs_sb_info *sb, struct efs_super *super) {
 	return 0;    
 }
 
-int efs_fill_super(struct super_block *s, void *d, int silent)
+static int efs_fill_super(struct super_block *s, void *d, int silent)
 {
 	struct efs_sb_info *sb;
 	struct buffer_head *bh;
@@ -292,7 +296,7 @@ out_no_fs:
 	return -EINVAL;
 }
 
-int efs_statfs(struct super_block *s, struct kstatfs *buf) {
+static int efs_statfs(struct super_block *s, struct kstatfs *buf) {
 	struct efs_sb_info *sb = SUPER_INFO(s);
 
 	buf->f_type    = EFS_SUPER_MAGIC;	/* efs magic number */
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index c81ddcd31..7d6a12f66 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -148,6 +148,9 @@
 /* Get the "struct epitem" from an epoll queue wrapper */
 #define EP_ITEM_FROM_EPQUEUE(p) (container_of(p, struct ep_pqueue, pt)->epi)
 
+/* Tells if the epoll_ctl(2) operation needs an event copy from userspace */
+#define EP_OP_HASH_EVENT(op) ((op) != EPOLL_CTL_DEL)
+
 
 struct epoll_filefd {
 	struct file *file;
@@ -531,7 +534,8 @@ sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event)
 		     current, epfd, op, fd, event));
 
 	error = -EFAULT;
-	if (copy_from_user(&epds, event, sizeof(struct epoll_event)))
+	if (EP_OP_HASH_EVENT(op) &&
+	    copy_from_user(&epds, event, sizeof(struct epoll_event)))
 		goto eexit_1;
 
 	/* Get the "struct file *" for the eventpoll file */
diff --git a/fs/exec.c b/fs/exec.c
index 284207a1f..121b5a414 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -436,9 +436,9 @@ int setup_arg_pages(struct linux_binprm *bprm, int executable_stack)
 		mpnt->vm_flags |= mm->def_flags;
 		mpnt->vm_page_prot = protection_map[mpnt->vm_flags & 0x7];
 		insert_vm_struct(mm, mpnt);
-		// mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
-		vx_vmpages_sub(mm, mm->total_vm -
-			((mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT));
+		// mm->stack_vm = mm->total_vm = vma_pages(mpnt);
+		vx_vmpages_sub(mm, mm->total_vm - vma_pages(mpnt));
+		mm->stack_vm = mm->total_vm;
 	}
 
 	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
@@ -551,6 +551,7 @@ static int exec_mmap(struct mm_struct *mm)
 	tsk->active_mm = mm;
 	activate_mm(active_mm, mm);
 	task_unlock(tsk);
+	arch_pick_mmap_layout(mm);
 	if (old_mm) {
 		if (active_mm != old_mm) BUG();
 		mmput(old_mm);
@@ -745,8 +746,10 @@ no_thread_group:
 	spin_unlock(&oldsighand->siglock);
 	write_unlock_irq(&tasklist_lock);
 
-	if (newsig && atomic_dec_and_test(&oldsig->count))
+	if (newsig && atomic_dec_and_test(&oldsig->count)) {
+		exit_itimers(oldsig);
 		kmem_cache_free(signal_cachep, oldsig);
+	}
 
 	if (atomic_dec_and_test(&oldsighand->count))
 		kmem_cache_free(sighand_cachep, oldsighand);
@@ -791,11 +794,27 @@ static inline void flush_old_files(struct files_struct * files)
 	spin_unlock(&files->file_lock);
 }
 
+void get_task_comm(char *buf, struct task_struct *tsk)
+{
+	/* buf must be at least sizeof(tsk->comm) in size */
+	task_lock(tsk);
+	memcpy(buf, tsk->comm, sizeof(tsk->comm));
+	task_unlock(tsk);
+}
+
+void set_task_comm(struct task_struct *tsk, char *buf)
+{
+	task_lock(tsk);
+	strlcpy(tsk->comm, buf, sizeof(tsk->comm));
+	task_unlock(tsk);
+}
+
 int flush_old_exec(struct linux_binprm * bprm)
 {
 	char * name;
 	int i, ch, retval;
 	struct files_struct *files;
+	char tcomm[sizeof(current->comm)];
 
 	/*
 	 * Make sure we have a private signal table and that
@@ -836,10 +855,11 @@ int flush_old_exec(struct linux_binprm * bprm)
 		if (ch == '/')
 			i = 0;
 		else
-			if (i < 15)
-				current->comm[i++] = ch;
+			if (i < (sizeof(tcomm) - 1))
+				tcomm[i++] = ch;
 	}
-	current->comm[i] = '\0';
+	tcomm[i] = '\0';
+	set_task_comm(current, tcomm);
 
 	flush_thread();
 
@@ -1079,7 +1099,7 @@ int do_execve(char * filename,
 	char __user *__user *envp,
 	struct pt_regs * regs)
 {
-	struct linux_binprm bprm;
+	struct linux_binprm *bprm;
 	struct file *file;
 	int retval;
 	int i;
@@ -1090,87 +1110,89 @@ int do_execve(char * filename,
 	if (IS_ERR(file))
 		return retval;
 
-	sched_balance_exec();
-
-	bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
-	memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0]));
-
-	bprm.file = file;
-	bprm.filename = filename;
-	bprm.interp = filename;
-	bprm.interp_flags = 0;
-	bprm.interp_data = 0;
-	bprm.sh_bang = 0;
-	bprm.loader = 0;
-	bprm.exec = 0;
-	bprm.security = NULL;
-	bprm.mm = mm_alloc();
+	sched_exec();
+
 	retval = -ENOMEM;
-	if (!bprm.mm)
+	bprm = kmalloc(sizeof(*bprm), GFP_KERNEL);
+	if (!bprm)
+		goto out_ret;
+	memset(bprm, 0, sizeof(*bprm));
+
+	bprm->p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
+
+	bprm->file = file;
+	bprm->filename = filename;
+	bprm->interp = filename;
+	bprm->mm = mm_alloc();
+	if (!bprm->mm)
 		goto out_file;
 
-	retval = init_new_context(current, bprm.mm);
+	retval = init_new_context(current, bprm->mm);
 	if (retval < 0)
 		goto out_mm;
 
-	bprm.argc = count(argv, bprm.p / sizeof(void *));
-	if ((retval = bprm.argc) < 0)
+	bprm->argc = count(argv, bprm->p / sizeof(void *));
+	if ((retval = bprm->argc) < 0)
 		goto out_mm;
 
-	bprm.envc = count(envp, bprm.p / sizeof(void *));
-	if ((retval = bprm.envc) < 0)
+	bprm->envc = count(envp, bprm->p / sizeof(void *));
+	if ((retval = bprm->envc) < 0)
 		goto out_mm;
 
-	retval = security_bprm_alloc(&bprm);
+	retval = security_bprm_alloc(bprm);
 	if (retval)
 		goto out;
 
-	retval = prepare_binprm(&bprm);
+	retval = prepare_binprm(bprm);
 	if (retval < 0)
 		goto out;
 
-	retval = copy_strings_kernel(1, &bprm.filename, &bprm);
+	retval = copy_strings_kernel(1, &bprm->filename, bprm);
 	if (retval < 0)
 		goto out;
 
-	bprm.exec = bprm.p;
-	retval = copy_strings(bprm.envc, envp, &bprm);
+	bprm->exec = bprm->p;
+	retval = copy_strings(bprm->envc, envp, bprm);
 	if (retval < 0)
 		goto out;
 
-	retval = copy_strings(bprm.argc, argv, &bprm);
+	retval = copy_strings(bprm->argc, argv, bprm);
 	if (retval < 0)
 		goto out;
 
-	retval = search_binary_handler(&bprm,regs);
+	retval = search_binary_handler(bprm,regs);
 	if (retval >= 0) {
-		free_arg_pages(&bprm);
+		free_arg_pages(bprm);
 
 		/* execve success */
-		security_bprm_free(&bprm);
+		security_bprm_free(bprm);
+		kfree(bprm);
 		return retval;
 	}
 
 out:
 	/* Something went wrong, return the inode and free the argument pages*/
 	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
-		struct page * page = bprm.page[i];
+		struct page * page = bprm->page[i];
 		if (page)
 			__free_page(page);
 	}
 
-	if (bprm.security)
-		security_bprm_free(&bprm);
+	if (bprm->security)
+		security_bprm_free(bprm);
 
 out_mm:
-	if (bprm.mm)
-		mmdrop(bprm.mm);
+	if (bprm->mm)
+		mmdrop(bprm->mm);
 
 out_file:
-	if (bprm.file) {
-		allow_write_access(bprm.file);
-		fput(bprm.file);
+	if (bprm->file) {
+		allow_write_access(bprm->file);
+		fput(bprm->file);
 	}
+	kfree(bprm);
+
+out_ret:
 	return retval;
 }
 
@@ -1198,7 +1220,7 @@ EXPORT_SYMBOL(set_binfmt);
  * name into corename, which must have space for at least
  * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator.
  */
-void format_corename(char *corename, const char *pattern, long signr)
+static void format_corename(char *corename, const char *pattern, long signr)
 {
 	const char *pat_ptr = pattern;
 	char *out_ptr = corename;
@@ -1362,7 +1384,6 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 	struct file * file;
 	int retval = 0;
 
-	lock_kernel();
 	binfmt = current->binfmt;
 	if (!binfmt || !binfmt->core_dump)
 		goto fail;
@@ -1380,7 +1401,13 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 	if (current->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump)
 		goto fail_unlock;
 
- 	format_corename(corename, core_pattern, signr);
+	/*
+	 * lock_kernel() because format_corename() is controlled by sysctl, which
+	 * uses lock_kernel()
+	 */
+ 	lock_kernel();
+	format_corename(corename, core_pattern, signr);
+	unlock_kernel();
 	file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE, 0600);
 	if (IS_ERR(file))
 		goto fail_unlock;
@@ -1407,6 +1434,5 @@ close_fail:
 fail_unlock:
 	complete_all(&mm->core_done);
 fail:
-	unlock_kernel();
 	return retval;
 }
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index edde9a5d5..0a6f7b06b 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -1,5 +1,6 @@
 
 #include <linux/fs.h>
+#include <linux/file.h>
 #include <linux/module.h>
 #include <linux/smp_lock.h>
 #include <linux/namei.h>
@@ -282,7 +283,12 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent,
 
 	/* drat - I just cannot find anything acceptable */
 	dput(result);
-	return ERR_PTR(-ESTALE);
+	/* It might be justifiable to return ESTALE here,
+	 * but the filehandle at-least looks reasonable good
+	 * and it just be a permission problem, so returning
+	 * -EACCESS is safer
+	 */
+	return ERR_PTR(-EACCES);
 
  err_target:
 	dput(target_dir);
@@ -347,7 +353,7 @@ static int get_name(struct dentry *dentry, char *name,
 {
 	struct inode *dir = dentry->d_inode;
 	int error;
-	struct file file;
+	struct file *file;
 	struct getdents_callback buffer;
 
 	error = -ENOTDIR;
@@ -359,11 +365,13 @@ static int get_name(struct dentry *dentry, char *name,
 	/*
 	 * Open the directory ...
 	 */
-	error = open_private_file(&file, dentry, O_RDONLY);
-	if (error)
+	file = dentry_open(dget(dentry), NULL, O_RDONLY);
+	error = PTR_ERR(file);
+	if (IS_ERR(file))
 		goto out;
+
 	error = -EINVAL;
-	if (!file.f_op->readdir)
+	if (!file->f_op->readdir)
 		goto out_close;
 
 	buffer.name = name;
@@ -373,7 +381,7 @@ static int get_name(struct dentry *dentry, char *name,
 	while (1) {
 		int old_seq = buffer.sequence;
 
-		error = vfs_readdir(&file, filldir_one, &buffer);
+		error = vfs_readdir(file, filldir_one, &buffer);
 
 		if (error < 0)
 			break;
@@ -387,7 +395,7 @@ static int get_name(struct dentry *dentry, char *name,
 	}
 
 out_close:
-	close_private_file(&file);
+	fput(file);
 out:
 	return error;
 }
diff --git a/fs/ext2/acl.h b/fs/ext2/acl.h
index 01937daf1..b0a1c4b38 100644
--- a/fs/ext2/acl.h
+++ b/fs/ext2/acl.h
@@ -10,18 +10,18 @@
 #define EXT2_ACL_MAX_ENTRIES	32
 
 typedef struct {
-	__u16		e_tag;
-	__u16		e_perm;
-	__u32		e_id;
+	__le16		e_tag;
+	__le16		e_perm;
+	__le32		e_id;
 } ext2_acl_entry;
 
 typedef struct {
-	__u16		e_tag;
-	__u16		e_perm;
+	__le16		e_tag;
+	__le16		e_perm;
 } ext2_acl_entry_short;
 
 typedef struct {
-	__u32		a_version;
+	__le32		a_version;
 } ext2_acl_header;
 
 static inline size_t ext2_acl_size(int count)
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index 7b776af84..5fbe1ca0b 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -90,8 +90,8 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group)
 	if (!bh)
 		ext2_error (sb, "read_block_bitmap",
 			    "Cannot read block bitmap - "
-			    "block_group = %d, block_bitmap = %lu",
-			    block_group, (unsigned long) desc->bg_block_bitmap);
+			    "block_group = %d, block_bitmap = %u",
+			    block_group, le32_to_cpu(desc->bg_block_bitmap));
 error_out:
 	return bh;
 }
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index 6af27658b..bf30cbf57 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -251,7 +251,7 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
 	loff_t pos = filp->f_pos;
 	struct inode *inode = filp->f_dentry->d_inode;
 	struct super_block *sb = inode->i_sb;
-	unsigned offset = pos & ~PAGE_CACHE_MASK;
+	unsigned int offset = pos & ~PAGE_CACHE_MASK;
 	unsigned long n = pos >> PAGE_CACHE_SHIFT;
 	unsigned long npages = dir_pages(inode);
 	unsigned chunk_mask = ~(ext2_chunk_size(inode)-1);
@@ -270,8 +270,13 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
 		ext2_dirent *de;
 		struct page *page = ext2_get_page(inode, n);
 
-		if (IS_ERR(page))
+		if (IS_ERR(page)) {
+			ext2_error(sb, __FUNCTION__,
+				   "bad page in #%lu",
+				   inode->i_ino);
+			filp->f_pos += PAGE_CACHE_SIZE - offset;
 			continue;
+		}
 		kaddr = page_address(page);
 		if (need_revalidate) {
 			offset = ext2_validate_entry(kaddr, offset, chunk_mask);
@@ -303,6 +308,7 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
 					goto success;
 				}
 			}
+			filp->f_pos += le16_to_cpu(de->rec_len);
 		}
 		ext2_put_page(page);
 	}
@@ -310,7 +316,6 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
 success:
 	ret = 0;
 done:
-	filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
 	filp->f_version = inode->i_version;
 	return ret;
 }
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index 67f704ab1..80faa8694 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -5,7 +5,7 @@
  * second extended file system inode data in memory
  */
 struct ext2_inode_info {
-	__u32	i_data[15];
+	__le32	i_data[15];
 	__u32	i_flags;
 	__u32	i_faddr;
 	__u8	i_frag_no;
@@ -115,7 +115,7 @@ extern unsigned long ext2_count_free (struct buffer_head *, unsigned);
 
 /* inode.c */
 extern void ext2_read_inode (struct inode *);
-extern void ext2_write_inode (struct inode *, int);
+extern int ext2_write_inode (struct inode *, int);
 extern void ext2_put_inode (struct inode *);
 extern void ext2_delete_inode (struct inode *);
 extern int ext2_sync_inode (struct inode *);
@@ -131,9 +131,6 @@ extern int ext2_ioctl (struct inode *, struct file *, unsigned int,
 /* super.c */
 extern void ext2_error (struct super_block *, const char *, const char *, ...)
 	__attribute__ ((format (printf, 3, 4)));
-extern NORET_TYPE void ext2_panic (struct super_block *, const char *,
-				   const char *, ...)
-	__attribute__ ((NORET_AND format (printf, 3, 4)));
 extern void ext2_warning (struct super_block *, const char *, const char *, ...)
 	__attribute__ ((format (printf, 3, 4)));
 extern void ext2_update_dynamic_rev (struct super_block *sb);
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
index 1b1dce48f..3d9fa57ca 100644
--- a/fs/ext2/ialloc.c
+++ b/fs/ext2/ialloc.c
@@ -60,8 +60,8 @@ read_inode_bitmap(struct super_block * sb, unsigned long block_group)
 	if (!bh)
 		ext2_error(sb, "read_inode_bitmap",
 			    "Cannot read inode bitmap - "
-			    "block_group = %lu, inode_bitmap = %lu",
-			    block_group, (unsigned long) desc->bg_inode_bitmap);
+			    "block_group = %lu, inode_bitmap = %u",
+			    block_group, le32_to_cpu(desc->bg_inode_bitmap));
 error_out:
 	return bh;
 }
@@ -469,7 +469,7 @@ struct inode *ext2_new_inode(struct inode *dir, int mode)
 	if (!inode)
 		return ERR_PTR(-ENOMEM);
 
-        if (sb->s_flags & MS_TAGXID)
+	if (sb->s_flags & MS_TAGXID)
 		inode->i_xid = current->xid;
 	else
 		inode->i_xid = 0;
@@ -634,14 +634,14 @@ got:
 	return inode;
 
 fail2:
-	DLIMIT_FREE_INODE(sb, inode->i_xid);	
+	DLIMIT_FREE_INODE(sb, inode->i_xid);
 	inode->i_flags |= S_NOQUOTA;
 	inode->i_nlink = 0;
 	iput(inode);
 	return ERR_PTR(err);
 
 fail:
-	DLIMIT_FREE_INODE(sb, inode->i_xid);	
+	DLIMIT_FREE_INODE(sb, inode->i_xid);
 fail_dlim:
 	make_bad_inode(inode);
 	iput(inode);
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 1ef02bccb..a6edf5888 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -145,12 +145,12 @@ static int ext2_alloc_block (struct inode * inode, unsigned long goal, int *err)
 }
 
 typedef struct {
-	u32	*p;
-	u32	key;
+	__le32	*p;
+	__le32	key;
 	struct buffer_head *bh;
 } Indirect;
 
-static inline void add_chain(Indirect *p, struct buffer_head *bh, u32 *v)
+static inline void add_chain(Indirect *p, struct buffer_head *bh, __le32 *v)
 {
 	p->key = *(p->p = v);
 	p->bh = bh;
@@ -283,7 +283,7 @@ static Indirect *ext2_get_branch(struct inode *inode,
 		read_lock(&EXT2_I(inode)->i_meta_lock);
 		if (!verify_chain(chain, p))
 			goto changed;
-		add_chain(++p, bh, (u32*)bh->b_data + *++offsets);
+		add_chain(++p, bh, (__le32*)bh->b_data + *++offsets);
 		read_unlock(&EXT2_I(inode)->i_meta_lock);
 		if (!p->key)
 			goto no_block;
@@ -324,8 +324,8 @@ no_block:
 static unsigned long ext2_find_near(struct inode *inode, Indirect *ind)
 {
 	struct ext2_inode_info *ei = EXT2_I(inode);
-	u32 *start = ind->bh ? (u32*) ind->bh->b_data : ei->i_data;
-	u32 *p;
+	__le32 *start = ind->bh ? (__le32 *) ind->bh->b_data : ei->i_data;
+	__le32 *p;
 	unsigned long bg_start;
 	unsigned long colour;
 
@@ -443,7 +443,7 @@ static int ext2_alloc_branch(struct inode *inode,
 		lock_buffer(bh);
 		memset(bh->b_data, 0, blocksize);
 		branch[n].bh = bh;
-		branch[n].p = (u32*) bh->b_data + offsets[n];
+		branch[n].p = (__le32 *) bh->b_data + offsets[n];
 		*branch[n].p = branch[n].key;
 		set_buffer_uptodate(bh);
 		unlock_buffer(bh);
@@ -705,7 +705,7 @@ struct address_space_operations ext2_nobh_aops = {
  * or memcmp with zero_page, whatever is better for particular architecture.
  * Linus?
  */
-static inline int all_zeroes(u32 *p, u32 *q)
+static inline int all_zeroes(__le32 *p, __le32 *q)
 {
 	while (p < q)
 		if (*p++)
@@ -751,7 +751,7 @@ static Indirect *ext2_find_shared(struct inode *inode,
 				int depth,
 				int offsets[4],
 				Indirect chain[4],
-				u32 *top)
+				__le32 *top)
 {
 	Indirect *partial, *p;
 	int k, err;
@@ -771,7 +771,7 @@ static Indirect *ext2_find_shared(struct inode *inode,
 		write_unlock(&EXT2_I(inode)->i_meta_lock);
 		goto no_top;
 	}
-	for (p=partial; p>chain && all_zeroes((u32*)p->bh->b_data,p->p); p--)
+	for (p=partial; p>chain && all_zeroes((__le32*)p->bh->b_data,p->p); p--)
 		;
 	/*
 	 * OK, we've found the last block that must survive. The rest of our
@@ -806,7 +806,7 @@ no_top:
  *	stored as little-endian 32-bit) and updating @inode->i_blocks
  *	appropriately.
  */
-static inline void ext2_free_data(struct inode *inode, u32 *p, u32 *q)
+static inline void ext2_free_data(struct inode *inode, __le32 *p, __le32 *q)
 {
 	unsigned long block_to_free = 0, count = 0;
 	unsigned long nr;
@@ -846,7 +846,7 @@ static inline void ext2_free_data(struct inode *inode, u32 *p, u32 *q)
  *	stored as little-endian 32-bit) and updating @inode->i_blocks
  *	appropriately.
  */
-static void ext2_free_branches(struct inode *inode, u32 *p, u32 *q, int depth)
+static void ext2_free_branches(struct inode *inode, __le32 *p, __le32 *q, int depth)
 {
 	struct buffer_head * bh;
 	unsigned long nr;
@@ -870,8 +870,8 @@ static void ext2_free_branches(struct inode *inode, u32 *p, u32 *q, int depth)
 				continue;
 			}
 			ext2_free_branches(inode,
-					   (u32*)bh->b_data,
-					   (u32*)bh->b_data + addr_per_block,
+					   (__le32*)bh->b_data,
+					   (__le32*)bh->b_data + addr_per_block,
 					   depth);
 			bforget(bh);
 			ext2_free_blocks(inode, nr, 1);
@@ -883,12 +883,12 @@ static void ext2_free_branches(struct inode *inode, u32 *p, u32 *q, int depth)
 
 static void ext2_truncate_nocheck(struct inode * inode)
 {
-	u32 *i_data = EXT2_I(inode)->i_data;
+	__le32 *i_data = EXT2_I(inode)->i_data;
 	int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
 	int offsets[4];
 	Indirect chain[4];
 	Indirect *partial;
-	int nr = 0;
+	__le32 nr = 0;
 	int n;
 	long iblock;
 	unsigned blocksize;
@@ -934,7 +934,7 @@ static void ext2_truncate_nocheck(struct inode * inode)
 	while (partial > chain) {
 		ext2_free_branches(inode,
 				   partial->p + 1,
-				   (u32*)partial->bh->b_data + addr_per_block,
+				   (__le32*)partial->bh->b_data+addr_per_block,
 				   (chain+n-1) - partial);
 		mark_buffer_dirty_inode(partial->bh, inode);
 		brelse (partial->bh);
@@ -1270,9 +1270,9 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
 	return err;
 }
 
-void ext2_write_inode(struct inode *inode, int wait)
+int ext2_write_inode(struct inode *inode, int wait)
 {
-	ext2_update_inode(inode, wait);
+	return ext2_update_inode(inode, wait);
 }
 
 int ext2_sync_inode(struct inode *inode)
@@ -1290,7 +1290,7 @@ int ext2_setattr_flags(struct inode *inode, unsigned int flags)
 
 	oldflags = EXT2_I(inode)->i_flags;
 	newflags = oldflags &
-		~(EXT2_IMMUTABLE_FL | EXT2_IUNLINK_FL | EXT2_BARRIER_FL);	
+		~(EXT2_IMMUTABLE_FL | EXT2_IUNLINK_FL | EXT2_BARRIER_FL);
 	if (flags & ATTR_FLAG_IMMUTABLE)
 		newflags |= EXT2_IMMUTABLE_FL;
 	if (flags & ATTR_FLAG_IUNLINK)
diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
index 2520c2ff5..7bb50ca56 100644
--- a/fs/ext2/ioctl.c
+++ b/fs/ext2/ioctl.c
@@ -50,8 +50,8 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
 		 * This test looks nicer. Thanks to Pauline Middelink
 		 */
 		if ((oldflags & EXT2_IMMUTABLE_FL) ||
-			((flags ^ oldflags) &
-			(EXT2_APPEND_FL | EXT2_IMMUTABLE_FL))) {
+			((flags ^ oldflags) & (EXT2_APPEND_FL |
+			EXT2_IMMUTABLE_FL | EXT2_IUNLINK_FL))) {
 			if (!capable(CAP_LINUX_IMMUTABLE))
 				return -EPERM;
 		}
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 3e54fbeac..820581b03 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -37,8 +37,6 @@ static void ext2_sync_super(struct super_block *sb,
 static int ext2_remount (struct super_block * sb, int * flags, char * data);
 static int ext2_statfs (struct super_block * sb, struct kstatfs * buf);
 
-static char error_buf[1024];
-
 void ext2_error (struct super_block * sb, const char * function,
 		 const char * fmt, ...)
 {
@@ -52,39 +50,19 @@ void ext2_error (struct super_block * sb, const char * function,
 			cpu_to_le16(le16_to_cpu(es->s_state) | EXT2_ERROR_FS);
 		ext2_sync_super(sb, es);
 	}
-	va_start (args, fmt);
-	vsprintf (error_buf, fmt, args);
-	va_end (args);
-	if (test_opt (sb, ERRORS_PANIC))
-		panic ("EXT2-fs panic (device %s): %s: %s\n",
-		       sb->s_id, function, error_buf);
-	printk (KERN_CRIT "EXT2-fs error (device %s): %s: %s\n",
-		sb->s_id, function, error_buf);
-	if (test_opt (sb, ERRORS_RO)) {
-		printk ("Remounting filesystem read-only\n");
-		sb->s_flags |= MS_RDONLY;
-	}
-}
 
-NORET_TYPE void ext2_panic (struct super_block * sb, const char * function,
-			    const char * fmt, ...)
-{
-	va_list args;
-	struct ext2_sb_info *sbi = EXT2_SB(sb);
+	va_start(args, fmt);
+	printk(KERN_CRIT "EXT2-fs error (device %s): %s: ",sb->s_id, function);
+	vprintk(fmt, args);
+	printk("\n");
+	va_end(args);
 
-	if (!(sb->s_flags & MS_RDONLY)) {
-		sbi->s_mount_state |= EXT2_ERROR_FS;
-		sbi->s_es->s_state =
-			cpu_to_le16(le16_to_cpu(sbi->s_es->s_state) | EXT2_ERROR_FS);
-		mark_buffer_dirty(sbi->s_sbh);
-		sb->s_dirt = 1;
+	if (test_opt(sb, ERRORS_PANIC))
+		panic("EXT2-fs panic from previous error\n");
+	if (test_opt(sb, ERRORS_RO)) {
+		printk("Remounting filesystem read-only\n");
+		sb->s_flags |= MS_RDONLY;
 	}
-	va_start (args, fmt);
-	vsprintf (error_buf, fmt, args);
-	va_end (args);
-	sb->s_flags |= MS_RDONLY;
-	panic ("EXT2-fs panic (device %s): %s: %s\n",
-	       sb->s_id, function, error_buf);
 }
 
 void ext2_warning (struct super_block * sb, const char * function,
@@ -92,11 +70,12 @@ void ext2_warning (struct super_block * sb, const char * function,
 {
 	va_list args;
 
-	va_start (args, fmt);
-	vsprintf (error_buf, fmt, args);
-	va_end (args);
-	printk (KERN_WARNING "EXT2-fs warning (device %s): %s: %s\n",
-		sb->s_id, function, error_buf);
+	va_start(args, fmt);
+	printk(KERN_WARNING "EXT2-fs warning (device %s): %s: ",
+	       sb->s_id, function);
+	vprintk(fmt, args);
+	printk("\n");
+	va_end(args);
 }
 
 void ext2_update_dynamic_rev(struct super_block *sb)
@@ -134,7 +113,7 @@ static void ext2_put_super (struct super_block * sb)
 	if (!(sb->s_flags & MS_RDONLY)) {
 		struct ext2_super_block *es = sbi->s_es;
 
-		es->s_state = le16_to_cpu(sbi->s_mount_state);
+		es->s_state = cpu_to_le16(sbi->s_mount_state);
 		ext2_sync_super(sb, es);
 	}
 	db_count = sbi->s_gdb_count;
@@ -189,7 +168,7 @@ static int init_inodecache(void)
 {
 	ext2_inode_cachep = kmem_cache_create("ext2_inode_cache",
 					     sizeof(struct ext2_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (ext2_inode_cachep == NULL)
 		return -ENOMEM;
@@ -455,8 +434,8 @@ static int ext2_setup_super (struct super_block * sb,
 		(le32_to_cpu(es->s_lastcheck) + le32_to_cpu(es->s_checkinterval) <= get_seconds()))
 		printk ("EXT2-fs warning: checktime reached, "
 			"running e2fsck is recommended\n");
-	if (!(__s16) le16_to_cpu(es->s_max_mnt_count))
-		es->s_max_mnt_count = (__s16) cpu_to_le16(EXT2_DFL_MAX_MNT_COUNT);
+	if (!le16_to_cpu(es->s_max_mnt_count))
+		es->s_max_mnt_count = cpu_to_le16(EXT2_DFL_MAX_MNT_COUNT);
 	es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1);
 	ext2_write_super(sb);
 	if (test_opt (sb, DEBUG))
@@ -578,6 +557,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
 	int blocksize = BLOCK_SIZE;
 	int db_count;
 	int i, j;
+	__le32 features;
 
 	sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
 	if (!sbi)
@@ -669,17 +649,18 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
 	 * previously didn't change the revision level when setting the flags,
 	 * so there is a chance incompat flags are set on a rev 0 filesystem.
 	 */
-	if ((i = EXT2_HAS_INCOMPAT_FEATURE(sb, ~EXT2_FEATURE_INCOMPAT_SUPP))) {
+	features = EXT2_HAS_INCOMPAT_FEATURE(sb, ~EXT2_FEATURE_INCOMPAT_SUPP);
+	if (features) {
 		printk("EXT2-fs: %s: couldn't mount because of "
 		       "unsupported optional features (%x).\n",
-		       sb->s_id, i);
+		       sb->s_id, le32_to_cpu(features));
 		goto failed_mount;
 	}
 	if (!(sb->s_flags & MS_RDONLY) &&
-	    (i = EXT2_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP))){
+	    (features = EXT2_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP))){
 		printk("EXT2-fs: %s: couldn't mount RDWR because of "
 		       "unsupported optional features (%x).\n",
-		       sb->s_id, i);
+		       sb->s_id, le32_to_cpu(features));
 		goto failed_mount;
 	}
 	blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size);
@@ -702,7 +683,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
 		}
 		es = (struct ext2_super_block *) (((char *)bh->b_data) + offset);
 		sbi->s_es = es;
-		if (es->s_magic != le16_to_cpu(EXT2_SUPER_MAGIC)) {
+		if (es->s_magic != cpu_to_le16(EXT2_SUPER_MAGIC)) {
 			printk ("EXT2-fs: Magic mismatch, very weird !\n");
 			goto failed_mount;
 		}
@@ -945,12 +926,12 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
 		es->s_state = cpu_to_le16(sbi->s_mount_state);
 		es->s_mtime = cpu_to_le32(get_seconds());
 	} else {
-		int ret;
-		if ((ret = EXT2_HAS_RO_COMPAT_FEATURE(sb,
-					       ~EXT2_FEATURE_RO_COMPAT_SUPP))) {
+		__le32 ret = EXT2_HAS_RO_COMPAT_FEATURE(sb,
+					       ~EXT2_FEATURE_RO_COMPAT_SUPP);
+		if (ret) {
 			printk("EXT2-fs: %s: couldn't remount RDWR because of "
 			       "unsupported optional features (%x).\n",
-			       sb->s_id, ret);
+			       sb->s_id, le32_to_cpu(ret));
 			return -EROFS;
 		}
 		/*
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index ab8308a6d..701d84414 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -1078,7 +1078,7 @@ static inline void ext2_xattr_hash_entry(struct ext2_xattr_header *header,
 	}
 
 	if (entry->e_value_block == 0 && entry->e_value_size != 0) {
-		__u32 *value = (__u32 *)((char *)header +
+		__le32 *value = (__le32 *)((char *)header +
 			le16_to_cpu(entry->e_value_offs));
 		for (n = (le32_to_cpu(entry->e_value_size) +
 		     EXT2_XATTR_ROUND) >> EXT2_XATTR_PAD_BITS; n; n--) {
diff --git a/fs/ext2/xattr.h b/fs/ext2/xattr.h
index a113ead4a..6268bcdaf 100644
--- a/fs/ext2/xattr.h
+++ b/fs/ext2/xattr.h
@@ -26,20 +26,20 @@
 #define EXT2_XATTR_INDEX_SECURITY	        6
 
 struct ext2_xattr_header {
-	__u32	h_magic;	/* magic number for identification */
-	__u32	h_refcount;	/* reference count */
-	__u32	h_blocks;	/* number of disk blocks used */
-	__u32	h_hash;		/* hash value of all attributes */
+	__le32	h_magic;	/* magic number for identification */
+	__le32	h_refcount;	/* reference count */
+	__le32	h_blocks;	/* number of disk blocks used */
+	__le32	h_hash;		/* hash value of all attributes */
 	__u32	h_reserved[4];	/* zero right now */
 };
 
 struct ext2_xattr_entry {
 	__u8	e_name_len;	/* length of name */
 	__u8	e_name_index;	/* attribute name index */
-	__u16	e_value_offs;	/* offset in disk block of value */
-	__u32	e_value_block;	/* disk block attribute is stored on (n/i) */
-	__u32	e_value_size;	/* size of attribute value */
-	__u32	e_hash;		/* hash value of name and value */
+	__le16	e_value_offs;	/* offset in disk block of value */
+	__le32	e_value_block;	/* disk block attribute is stored on (n/i) */
+	__le32	e_value_size;	/* size of attribute value */
+	__le32	e_hash;		/* hash value of name and value */
 	char	e_name[0];	/* attribute name */
 };
 
diff --git a/fs/ext3/acl.h b/fs/ext3/acl.h
index 9d9d9d2e4..f83830d44 100644
--- a/fs/ext3/acl.h
+++ b/fs/ext3/acl.h
@@ -10,18 +10,18 @@
 #define EXT3_ACL_MAX_ENTRIES	32
 
 typedef struct {
-	__u16		e_tag;
-	__u16		e_perm;
-	__u32		e_id;
+	__le16		e_tag;
+	__le16		e_perm;
+	__le32		e_id;
 } ext3_acl_entry;
 
 typedef struct {
-	__u16		e_tag;
-	__u16		e_perm;
+	__le16		e_tag;
+	__le16		e_perm;
 } ext3_acl_entry_short;
 
 typedef struct {
-	__u32		a_version;
+	__le32		a_version;
 } ext3_acl_header;
 
 static inline size_t ext3_acl_size(int count)
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index 3b3160d8e..bc2a9b825 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -93,8 +93,8 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group)
 	if (!bh)
 		ext3_error (sb, "read_block_bitmap",
 			    "Cannot read block bitmap - "
-			    "block_group = %d, block_bitmap = %lu",
-			    block_group, (unsigned long) desc->bg_block_bitmap);
+			    "block_group = %d, block_bitmap = %u",
+			    block_group, le32_to_cpu(desc->bg_block_bitmap));
 error_out:
 	return bh;
 }
diff --git a/fs/ext3/fsync.c b/fs/ext3/fsync.c
index 0b6a45929..49382a208 100644
--- a/fs/ext3/fsync.c
+++ b/fs/ext3/fsync.c
@@ -49,10 +49,6 @@ int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync)
 
 	J_ASSERT(ext3_journal_current_handle() == 0);
 
-	smp_mb();		/* prepare for lockless i_state read */
-	if (!(inode->i_state & I_DIRTY))
-		goto out;
-
 	/*
 	 * data=writeback:
 	 *  The caller's filemap_fdatawrite()/wait will sync the data.
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index f30a4f41a..591eed030 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -65,8 +65,8 @@ read_inode_bitmap(struct super_block * sb, unsigned long block_group)
 	if (!bh)
 		ext3_error(sb, "read_inode_bitmap",
 			    "Cannot read inode bitmap - "
-			    "block_group = %lu, inode_bitmap = %lu",
-			    block_group, (unsigned long) desc->bg_inode_bitmap);
+			    "block_group = %lu, inode_bitmap = %u",
+			    block_group, le32_to_cpu(desc->bg_inode_bitmap));
 error_out:
 	return bh;
 }
@@ -98,7 +98,7 @@ void ext3_free_inode (handle_t *handle, struct inode * inode)
 	unsigned long bit;
 	struct ext3_group_desc * gdp;
 	struct ext3_super_block * es;
-	struct ext3_sb_info *sbi = EXT3_SB(sb);
+	struct ext3_sb_info *sbi;
 	int fatal = 0, err;
 
 	if (atomic_read(&inode->i_count) > 1) {
@@ -115,6 +115,7 @@ void ext3_free_inode (handle_t *handle, struct inode * inode)
 		printk("ext3_free_inode: inode on nonexistent device\n");
 		return;
 	}
+	sbi = EXT3_SB(sb);
 
 	ino = inode->i_ino;
 	ext3_debug ("freeing inode %lu\n", ino);
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index da40fc7c6..5e73846ef 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -67,6 +67,8 @@ int ext3_forget(handle_t *handle, int is_metadata,
 {
 	int err;
 
+	might_sleep();
+
 	BUFFER_TRACE(bh, "enter");
 
 	jbd_debug(4, "forgetting bh %p: is_metadata = %d, mode %o, "
@@ -306,12 +308,12 @@ static int ext3_alloc_block (handle_t *handle,
 
 
 typedef struct {
-	u32	*p;
-	u32	key;
+	__le32	*p;
+	__le32	key;
 	struct buffer_head *bh;
 } Indirect;
 
-static inline void add_chain(Indirect *p, struct buffer_head *bh, u32 *v)
+static inline void add_chain(Indirect *p, struct buffer_head *bh, __le32 *v)
 {
 	p->key = *(p->p = v);
 	p->bh = bh;
@@ -442,7 +444,7 @@ static Indirect *ext3_get_branch(struct inode *inode, int depth, int *offsets,
 		/* Reader: pointers */
 		if (!verify_chain(chain, p))
 			goto changed;
-		add_chain(++p, bh, (u32*)bh->b_data + *++offsets);
+		add_chain(++p, bh, (__le32*)bh->b_data + *++offsets);
 		/* Reader: end */
 		if (!p->key)
 			goto no_block;
@@ -483,8 +485,8 @@ no_block:
 static unsigned long ext3_find_near(struct inode *inode, Indirect *ind)
 {
 	struct ext3_inode_info *ei = EXT3_I(inode);
-	u32 *start = ind->bh ? (u32*) ind->bh->b_data : ei->i_data;
-	u32 *p;
+	__le32 *start = ind->bh ? (__le32*) ind->bh->b_data : ei->i_data;
+	__le32 *p;
 	unsigned long bg_start;
 	unsigned long colour;
 
@@ -612,7 +614,7 @@ static int ext3_alloc_branch(handle_t *handle, struct inode *inode,
 			}
 
 			memset(bh->b_data, 0, blocksize);
-			branch[n].p = (u32*) bh->b_data + offsets[n];
+			branch[n].p = (__le32*) bh->b_data + offsets[n];
 			*branch[n].p = branch[n].key;
 			BUFFER_TRACE(bh, "marking uptodate");
 			set_buffer_uptodate(bh);
@@ -1580,6 +1582,12 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,
 				 offset, nr_segs,
 				 ext3_direct_io_get_blocks, NULL);
 
+	/*
+	 * Reacquire the handle: ext3_direct_io_get_block() can restart the
+	 * transaction
+	 */
+	handle = journal_current_handle();
+
 out_stop:
 	if (handle) {
 		int err;
@@ -1768,7 +1776,7 @@ unlock:
  * or memcmp with zero_page, whatever is better for particular architecture.
  * Linus?
  */
-static inline int all_zeroes(u32 *p, u32 *q)
+static inline int all_zeroes(__le32 *p, __le32 *q)
 {
 	while (p < q)
 		if (*p++)
@@ -1815,7 +1823,7 @@ static Indirect *ext3_find_shared(struct inode *inode,
 				int depth,
 				int offsets[4],
 				Indirect chain[4],
-				u32 *top)
+				__le32 *top)
 {
 	Indirect *partial, *p;
 	int k, err;
@@ -1835,7 +1843,7 @@ static Indirect *ext3_find_shared(struct inode *inode,
 	if (!partial->key && *partial->p)
 		/* Writer: end */
 		goto no_top;
-	for (p=partial; p>chain && all_zeroes((u32*)p->bh->b_data,p->p); p--)
+	for (p=partial; p>chain && all_zeroes((__le32*)p->bh->b_data,p->p); p--)
 		;
 	/*
 	 * OK, we've found the last block that must survive. The rest of our
@@ -1874,9 +1882,9 @@ no_top:
 static void
 ext3_clear_blocks(handle_t *handle, struct inode *inode, struct buffer_head *bh,
 		unsigned long block_to_free, unsigned long count,
-		u32 *first, u32 *last)
+		__le32 *first, __le32 *last)
 {
-	u32 *p;
+	__le32 *p;
 	if (try_to_extend_transaction(handle, inode)) {
 		if (bh) {
 			BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
@@ -1932,15 +1940,16 @@ ext3_clear_blocks(handle_t *handle, struct inode *inode, struct buffer_head *bh,
  * block pointers.
  */
 static void ext3_free_data(handle_t *handle, struct inode *inode,
-			   struct buffer_head *this_bh, u32 *first, u32 *last)
+			   struct buffer_head *this_bh,
+			   __le32 *first, __le32 *last)
 {
 	unsigned long block_to_free = 0;    /* Starting block # of a run */
 	unsigned long count = 0;	    /* Number of blocks in the run */ 
-	u32 *block_to_free_p = NULL;	    /* Pointer into inode/ind
+	__le32 *block_to_free_p = NULL;	    /* Pointer into inode/ind
 					       corresponding to
 					       block_to_free */
 	unsigned long nr;		    /* Current block # */
-	u32 *p;				    /* Pointer into inode/ind
+	__le32 *p;			    /* Pointer into inode/ind
 					       for current block */
 	int err;
 
@@ -1999,10 +2008,10 @@ static void ext3_free_data(handle_t *handle, struct inode *inode,
  */
 static void ext3_free_branches(handle_t *handle, struct inode *inode,
 			       struct buffer_head *parent_bh,
-			       u32 *first, u32 *last, int depth)
+			       __le32 *first, __le32 *last, int depth)
 {
 	unsigned long nr;
-	u32 *p;
+	__le32 *p;
 
 	if (is_handle_aborted(handle))
 		return;
@@ -2032,8 +2041,9 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode,
 
 			/* This zaps the entire block.  Bottom up. */
 			BUFFER_TRACE(bh, "free child branches");
-			ext3_free_branches(handle, inode, bh, (u32*)bh->b_data,
-					   (u32*)bh->b_data + addr_per_block,
+			ext3_free_branches(handle, inode, bh,
+					   (__le32*)bh->b_data,
+					   (__le32*)bh->b_data + addr_per_block,
 					   depth);
 
 			/*
@@ -2138,13 +2148,13 @@ void ext3_truncate_nocheck(struct inode * inode)
 {
 	handle_t *handle;
 	struct ext3_inode_info *ei = EXT3_I(inode);
-	u32 *i_data = ei->i_data;
+	__le32 *i_data = ei->i_data;
 	int addr_per_block = EXT3_ADDR_PER_BLOCK(inode->i_sb);
 	struct address_space *mapping = inode->i_mapping;
 	int offsets[4];
 	Indirect chain[4];
 	Indirect *partial;
-	int nr = 0;
+	__le32 nr = 0;
 	int n;
 	long last_block;
 	unsigned blocksize = inode->i_sb->s_blocksize;
@@ -2249,7 +2259,7 @@ void ext3_truncate_nocheck(struct inode * inode)
 	/* Clear the ends of indirect blocks on the shared branch */
 	while (partial > chain) {
 		ext3_free_branches(handle, inode, partial->bh, partial->p + 1,
-				   (u32*)partial->bh->b_data + addr_per_block,
+				   (__le32*)partial->bh->b_data+addr_per_block,
 				   (chain+n-1) - partial);
 		BUFFER_TRACE(partial->bh, "call brelse");
 		brelse (partial->bh);
@@ -2767,21 +2777,21 @@ out_brelse:
  * `stuff()' is running, and the new i_size will be lost.  Plus the inode
  * will no longer be on the superblock's dirty inode list.
  */
-void ext3_write_inode(struct inode *inode, int wait)
+int ext3_write_inode(struct inode *inode, int wait)
 {
 	if (current->flags & PF_MEMALLOC)
-		return;
+		return 0;
 
 	if (ext3_journal_current_handle()) {
 		jbd_debug(0, "called recursively, non-PF_MEMALLOC!\n");
 		dump_stack();
-		return;
+		return -EIO;
 	}
 
 	if (!wait)
-		return;
+		return 0;
 
-	ext3_force_commit(inode->i_sb);
+	return ext3_force_commit(inode->i_sb);
 }
 
 int ext3_setattr_flags(struct inode *inode, unsigned int flags)
@@ -2791,7 +2801,7 @@ int ext3_setattr_flags(struct inode *inode, unsigned int flags)
 
 	oldflags = EXT3_I(inode)->i_flags;
 	newflags = oldflags &
-		~(EXT3_IMMUTABLE_FL | EXT3_IUNLINK_FL | EXT3_BARRIER_FL);	
+		~(EXT3_IMMUTABLE_FL | EXT3_IUNLINK_FL | EXT3_BARRIER_FL);
 	if (flags & ATTR_FLAG_IMMUTABLE)
 		newflags |= EXT3_IMMUTABLE_FL;
 	if (flags & ATTR_FLAG_IUNLINK)
@@ -2811,7 +2821,7 @@ int ext3_setattr_flags(struct inode *inode, unsigned int flags)
 		err = ext3_reserve_inode_write(handle, inode, &iloc);
 		if (err)
 			goto flags_err;
-		
+
 		EXT3_I(inode)->i_flags = newflags;
 		inode->i_ctime = CURRENT_TIME;
 
@@ -3039,6 +3049,7 @@ int ext3_mark_inode_dirty(handle_t *handle, struct inode *inode)
 	struct ext3_iloc iloc;
 	int err;
 
+	might_sleep();
 	err = ext3_reserve_inode_write(handle, inode, &iloc);
 	if (!err)
 		err = ext3_mark_iloc_dirty(handle, inode, &iloc);
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
index 7765ab0d5..82b4dcb25 100644
--- a/fs/ext3/ioctl.c
+++ b/fs/ext3/ioctl.c
@@ -59,8 +59,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
 		 * This test looks nicer. Thanks to Pauline Middelink
 		 */
 		if ((oldflags & EXT3_IMMUTABLE_FL) ||
-			((flags ^ oldflags) &
-			(EXT3_APPEND_FL | EXT3_IMMUTABLE_FL))) {
+			((flags ^ oldflags) & (EXT3_APPEND_FL |
+			EXT3_IMMUTABLE_FL | EXT3_IUNLINK_FL))) {
 			if (!capable(CAP_LINUX_IMMUTABLE))
 				return -EPERM;
 		}
@@ -169,7 +169,7 @@ flags_err:
 		if (!(inode->i_sb->s_flags & MS_TAGXID))
 			return -ENOSYS;
 		if (get_user(xid, (int *) arg))
-			return -EFAULT;	
+			return -EFAULT;
 
 		handle = ext3_journal_start(inode, 1);
 		if (IS_ERR(handle))
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 36e5b4ec3..e7e287e19 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -71,9 +71,6 @@ static struct buffer_head *ext3_append(handle_t *handle,
 #define swap(x, y) do { typeof(x) z = x; x = y; y = z; } while (0)
 #endif
 
-typedef struct { u32 v; } le_u32;
-typedef struct { u16 v; } le_u16;
-
 #ifdef DX_DEBUG
 #define dxtrace(command) command
 #else
@@ -82,22 +79,22 @@ typedef struct { u16 v; } le_u16;
 
 struct fake_dirent
 {
-	/*le*/u32 inode;
-	/*le*/u16 rec_len;
+	__le32 inode;
+	__le16 rec_len;
 	u8 name_len;
 	u8 file_type;
 };
 
 struct dx_countlimit
 {
-	le_u16 limit;
-	le_u16 count;
+	__le16 limit;
+	__le16 count;
 };
 
 struct dx_entry
 {
-	le_u32 hash;
-	le_u32 block;
+	__le32 hash;
+	__le32 block;
 };
 
 /*
@@ -114,7 +111,7 @@ struct dx_root
 	char dotdot_name[4];
 	struct dx_root_info
 	{
-		le_u32 reserved_zero;
+		__le32 reserved_zero;
 		u8 hash_version;
 		u8 info_length; /* 8 */
 		u8 indirect_levels;
@@ -184,42 +181,42 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
 
 static inline unsigned dx_get_block (struct dx_entry *entry)
 {
-	return le32_to_cpu(entry->block.v) & 0x00ffffff;
+	return le32_to_cpu(entry->block) & 0x00ffffff;
 }
 
 static inline void dx_set_block (struct dx_entry *entry, unsigned value)
 {
-	entry->block.v = cpu_to_le32(value);
+	entry->block = cpu_to_le32(value);
 }
 
 static inline unsigned dx_get_hash (struct dx_entry *entry)
 {
-	return le32_to_cpu(entry->hash.v);
+	return le32_to_cpu(entry->hash);
 }
 
 static inline void dx_set_hash (struct dx_entry *entry, unsigned value)
 {
-	entry->hash.v = cpu_to_le32(value);
+	entry->hash = cpu_to_le32(value);
 }
 
 static inline unsigned dx_get_count (struct dx_entry *entries)
 {
-	return le16_to_cpu(((struct dx_countlimit *) entries)->count.v);
+	return le16_to_cpu(((struct dx_countlimit *) entries)->count);
 }
 
 static inline unsigned dx_get_limit (struct dx_entry *entries)
 {
-	return le16_to_cpu(((struct dx_countlimit *) entries)->limit.v);
+	return le16_to_cpu(((struct dx_countlimit *) entries)->limit);
 }
 
 static inline void dx_set_count (struct dx_entry *entries, unsigned value)
 {
-	((struct dx_countlimit *) entries)->count.v = cpu_to_le16(value);
+	((struct dx_countlimit *) entries)->count = cpu_to_le16(value);
 }
 
 static inline void dx_set_limit (struct dx_entry *entries, unsigned value)
 {
-	((struct dx_countlimit *) entries)->limit.v = cpu_to_le16(value);
+	((struct dx_countlimit *) entries)->limit = cpu_to_le16(value);
 }
 
 static inline unsigned dx_root_limit (struct inode *dir, unsigned infosize)
@@ -2258,7 +2255,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
 	} else {
 		BUFFER_TRACE(new_bh, "get write access");
 		ext3_journal_get_write_access(handle, new_bh);
-		new_de->inode = le32_to_cpu(old_inode->i_ino);
+		new_de->inode = cpu_to_le32(old_inode->i_ino);
 		if (EXT3_HAS_INCOMPAT_FEATURE(new_dir->i_sb,
 					      EXT3_FEATURE_INCOMPAT_FILETYPE))
 			new_de->file_type = old_de->file_type;
@@ -2313,7 +2310,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
 	if (dir_bh) {
 		BUFFER_TRACE(dir_bh, "get_write_access");
 		ext3_journal_get_write_access(handle, dir_bh);
-		PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino);
+		PARENT_INO(dir_bh->b_data) = cpu_to_le32(new_dir->i_ino);
 		BUFFER_TRACE(dir_bh, "call ext3_journal_dirty_metadata");
 		ext3_journal_dirty_metadata(handle, dir_bh);
 		old_dir->i_nlink--;
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 27c0fe37d..8d6104ba1 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -118,8 +118,6 @@ void ext3_journal_abort_handle(const char *caller, const char *err_fn,
 		handle->h_err = err;
 }
 
-static char error_buf[1024];
-
 /* Deal with the reporting of failure conditions on a filesystem such as
  * inconsistencies detected or read IO failures.
  *
@@ -140,7 +138,7 @@ static void ext3_handle_error(struct super_block *sb)
 	struct ext3_super_block *es = EXT3_SB(sb)->s_es;
 
 	EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
-	es->s_state |= cpu_to_le32(EXT3_ERROR_FS);
+	es->s_state |= cpu_to_le16(EXT3_ERROR_FS);
 
 	if (sb->s_flags & MS_RDONLY)
 		return;
@@ -166,12 +164,11 @@ void ext3_error (struct super_block * sb, const char * function,
 {
 	va_list args;
 
-	va_start (args, fmt);
-	vsprintf (error_buf, fmt, args);
-	va_end (args);
-
-	printk (KERN_CRIT "EXT3-fs error (device %s): %s: %s\n",
-		sb->s_id, function, error_buf);
+	va_start(args, fmt);
+	printk(KERN_CRIT "EXT3-fs error (device %s): %s: ",sb->s_id, function);
+	vprintk(fmt, args);
+	printk("\n");
+	va_end(args);
 
 	ext3_handle_error(sb);
 }
@@ -240,21 +237,19 @@ void ext3_abort (struct super_block * sb, const char * function,
 
 	printk (KERN_CRIT "ext3_abort called.\n");
 
-	va_start (args, fmt);
-	vsprintf (error_buf, fmt, args);
-	va_end (args);
-
-	if (test_opt (sb, ERRORS_PANIC))
-		panic ("EXT3-fs panic (device %s): %s: %s\n",
-		       sb->s_id, function, error_buf);
+	va_start(args, fmt);
+	printk(KERN_CRIT "EXT3-fs error (device %s): %s: ",sb->s_id, function);
+	vprintk(fmt, args);
+	printk("\n");
+	va_end(args);
 
-	printk (KERN_CRIT "EXT3-fs abort (device %s): %s: %s\n",
-		sb->s_id, function, error_buf);
+	if (test_opt(sb, ERRORS_PANIC))
+		panic("EXT3-fs panic from previous error\n");
 
 	if (sb->s_flags & MS_RDONLY)
 		return;
 
-	printk (KERN_CRIT "Remounting filesystem read-only\n");
+	printk(KERN_CRIT "Remounting filesystem read-only\n");
 	EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS;
 	sb->s_flags |= MS_RDONLY;
 	EXT3_SB(sb)->s_mount_opt |= EXT3_MOUNT_ABORT;
@@ -272,15 +267,16 @@ NORET_TYPE void ext3_panic (struct super_block * sb, const char * function,
 {
 	va_list args;
 
-	va_start (args, fmt);
-	vsprintf (error_buf, fmt, args);
-	va_end (args);
+	va_start(args, fmt);
+	printk(KERN_CRIT "EXT3-fs error (device %s): %s: ",sb->s_id, function);
+	vprintk(fmt, args);
+	printk("\n");
+	va_end(args);
 
 	/* this is to prevent panic from syncing this filesystem */
 	/* AKPM: is this sufficient? */
 	sb->s_flags |= MS_RDONLY;
-	panic ("EXT3-fs panic (device %s): %s: %s\n",
-	       sb->s_id, function, error_buf);
+	panic ("EXT3-fs panic forced\n");
 }
 
 void ext3_warning (struct super_block * sb, const char * function,
@@ -288,11 +284,12 @@ void ext3_warning (struct super_block * sb, const char * function,
 {
 	va_list args;
 
-	va_start (args, fmt);
-	vsprintf (error_buf, fmt, args);
-	va_end (args);
-	printk (KERN_WARNING "EXT3-fs warning (device %s): %s: %s\n",
-		sb->s_id, function, error_buf);
+	va_start(args, fmt);
+	printk(KERN_WARNING "EXT3-fs warning (device %s): %s: ",
+	       sb->s_id, function);
+	vprintk(fmt, args);
+	printk("\n");
+	va_end(args);
 }
 
 void ext3_update_dynamic_rev(struct super_block *sb)
@@ -380,7 +377,7 @@ static void dump_orphan_list(struct super_block *sb, struct ext3_sb_info *sbi)
 		       "inode %s:%ld at %p: mode %o, nlink %d, next %d\n",
 		       inode->i_sb->s_id, inode->i_ino, inode,
 		       inode->i_mode, inode->i_nlink, 
-		       le32_to_cpu(NEXT_ORPHAN(inode)));
+		       NEXT_ORPHAN(inode));
 	}
 }
 
@@ -394,7 +391,7 @@ void ext3_put_super (struct super_block * sb)
 	journal_destroy(sbi->s_journal);
 	if (!(sb->s_flags & MS_RDONLY)) {
 		EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
-		es->s_state = le16_to_cpu(sbi->s_mount_state);
+		es->s_state = cpu_to_le16(sbi->s_mount_state);
 		BUFFER_TRACE(sbi->s_sbh, "marking dirty");
 		mark_buffer_dirty(sbi->s_sbh);
 		ext3_commit_super(sb, es, 1);
@@ -480,7 +477,7 @@ static int init_inodecache(void)
 {
 	ext3_inode_cachep = kmem_cache_create("ext3_inode_cache",
 					     sizeof(struct ext3_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (ext3_inode_cachep == NULL)
 		return -ENOMEM;
@@ -587,7 +584,7 @@ enum {
 	Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
 	Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
 	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0,
-	Opt_tagxid, Opt_ignore, Opt_err,
+	Opt_tagxid, Opt_barrier, Opt_ignore, Opt_err,
 };
 
 static match_table_t tokens = {
@@ -633,6 +630,7 @@ static match_table_t tokens = {
 	{Opt_ignore, "noquota"},
 	{Opt_ignore, "quota"},
 	{Opt_ignore, "usrquota"},
+	{Opt_barrier, "barrier=%u"},
 	{Opt_err, NULL}
 };
 
@@ -908,6 +906,14 @@ clear_qf_name:
 		case Opt_abort:
 			set_opt(sbi->s_mount_opt, ABORT);
 			break;
+		case Opt_barrier:
+			if (match_int(&args[0], &option))
+				return 0;
+			if (option)
+				set_opt(sbi->s_mount_opt, BARRIER);
+			else
+				clear_opt(sbi->s_mount_opt, BARRIER);
+			break;
 		case Opt_ignore:
 			break;
 		default:
@@ -969,8 +975,7 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es,
 	es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & ~EXT3_VALID_FS);
 #endif
 	if (!(__s16) le16_to_cpu(es->s_max_mnt_count))
-		es->s_max_mnt_count =
-			(__s16) cpu_to_le16(EXT3_DFL_MAX_MNT_COUNT);
+		es->s_max_mnt_count = cpu_to_le16(EXT3_DFL_MAX_MNT_COUNT);
 	es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1);
 	es->s_mtime = cpu_to_le32(get_seconds());
 	ext3_update_dynamic_rev(sb);
@@ -1226,6 +1231,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
 	int db_count;
 	int i;
 	int needs_recovery;
+	__le32 features;
 
 	sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
 	if (!sbi)
@@ -1320,17 +1326,18 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
 	 * previously didn't change the revision level when setting the flags,
 	 * so there is a chance incompat flags are set on a rev 0 filesystem.
 	 */
-	if ((i = EXT3_HAS_INCOMPAT_FEATURE(sb, ~EXT3_FEATURE_INCOMPAT_SUPP))) {
+	features = EXT3_HAS_INCOMPAT_FEATURE(sb, ~EXT3_FEATURE_INCOMPAT_SUPP);
+	if (features) {
 		printk(KERN_ERR "EXT3-fs: %s: couldn't mount because of "
 		       "unsupported optional features (%x).\n",
-		       sb->s_id, i);
+		       sb->s_id, le32_to_cpu(features));
 		goto failed_mount;
 	}
-	if (!(sb->s_flags & MS_RDONLY) &&
-	    (i = EXT3_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP))){
+	features = EXT3_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP);
+	if (!(sb->s_flags & MS_RDONLY) && features) {
 		printk(KERN_ERR "EXT3-fs: %s: couldn't mount RDWR because of "
 		       "unsupported optional features (%x).\n",
-		       sb->s_id, i);
+		       sb->s_id, le32_to_cpu(features));
 		goto failed_mount;
 	}
 	blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size);
@@ -1367,7 +1374,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
 		}
 		es = (struct ext3_super_block *)(((char *)bh->b_data) + offset);
 		sbi->s_es = es;
-		if (es->s_magic != le16_to_cpu(EXT3_SUPER_MAGIC)) {
+		if (es->s_magic != cpu_to_le16(EXT3_SUPER_MAGIC)) {
 			printk (KERN_ERR 
 				"EXT3-fs: Magic mismatch, very weird !\n");
 			goto failed_mount;
@@ -1612,16 +1619,23 @@ out_fail:
  * initial mount, once the journal has been initialised but before we've
  * done any recovery; and again on any subsequent remount. 
  */
-static void ext3_init_journal_params(struct ext3_sb_info *sbi, 
-				     journal_t *journal)
+static void ext3_init_journal_params(struct super_block *sb, journal_t *journal)
 {
+	struct ext3_sb_info *sbi = EXT3_SB(sb);
+
 	if (sbi->s_commit_interval)
 		journal->j_commit_interval = sbi->s_commit_interval;
 	/* We could also set up an ext3-specific default for the commit
 	 * interval here, but for now we'll just fall back to the jbd
 	 * default. */
-}
 
+	spin_lock(&journal->j_state_lock);
+	if (test_opt(sb, BARRIER))
+		journal->j_flags |= JFS_BARRIER;
+	else
+		journal->j_flags &= ~JFS_BARRIER;
+	spin_unlock(&journal->j_state_lock);
+}
 
 static journal_t *ext3_get_journal(struct super_block *sb, int journal_inum)
 {
@@ -1659,7 +1673,7 @@ static journal_t *ext3_get_journal(struct super_block *sb, int journal_inum)
 		return NULL;
 	}
 	journal->j_private = sb;
-	ext3_init_journal_params(EXT3_SB(sb), journal);
+	ext3_init_journal_params(sb, journal);
 	return journal;
 }
 
@@ -1737,14 +1751,14 @@ static journal_t *ext3_get_dev_journal(struct super_block *sb,
 		printk(KERN_ERR "EXT3-fs: I/O error on journal device\n");
 		goto out_journal;
 	}
-	if (ntohl(journal->j_superblock->s_nr_users) != 1) {
+	if (be32_to_cpu(journal->j_superblock->s_nr_users) != 1) {
 		printk(KERN_ERR "EXT3-fs: External journal has more than one "
 					"user (unsupported) - %d\n",
-			ntohl(journal->j_superblock->s_nr_users));
+			be32_to_cpu(journal->j_superblock->s_nr_users));
 		goto out_journal;
 	}
 	EXT3_SB(sb)->journal_bdev = bdev;
-	ext3_init_journal_params(EXT3_SB(sb), journal);
+	ext3_init_journal_params(sb, journal);
 	return journal;
 out_journal:
 	journal_destroy(journal);
@@ -2041,7 +2055,7 @@ int ext3_remount (struct super_block * sb, int * flags, char * data)
 
 	es = sbi->s_es;
 
-	ext3_init_journal_params(sbi, sbi->s_journal);
+	ext3_init_journal_params(sb, sbi->s_journal);
 
 	if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) {
 		if (sbi->s_mount_opt & EXT3_MOUNT_ABORT)
@@ -2065,13 +2079,13 @@ int ext3_remount (struct super_block * sb, int * flags, char * data)
 
 			ext3_mark_recovery_complete(sb, es);
 		} else {
-			int ret;
+			__le32 ret;
 			if ((ret = EXT3_HAS_RO_COMPAT_FEATURE(sb,
 					~EXT3_FEATURE_RO_COMPAT_SUPP))) {
 				printk(KERN_WARNING "EXT3-fs: %s: couldn't "
 				       "remount RDWR because of unsupported "
 				       "optional features (%x).\n",
-				       sb->s_id, ret);
+				       sb->s_id, le32_to_cpu(ret));
 				return -EROFS;
 			}
 			/*
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index b6c382c83..cedbcde3e 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -1137,7 +1137,7 @@ static inline void ext3_xattr_hash_entry(struct ext3_xattr_header *header,
 	}
 
 	if (entry->e_value_block == 0 && entry->e_value_size != 0) {
-		__u32 *value = (__u32 *)((char *)header +
+		__le32 *value = (__le32 *)((char *)header +
 			le16_to_cpu(entry->e_value_offs));
 		for (n = (le32_to_cpu(entry->e_value_size) +
 		     EXT3_XATTR_ROUND) >> EXT3_XATTR_PAD_BITS; n; n--) {
diff --git a/fs/ext3/xattr.h b/fs/ext3/xattr.h
index 9c71433c6..2aabe9f59 100644
--- a/fs/ext3/xattr.h
+++ b/fs/ext3/xattr.h
@@ -25,20 +25,20 @@
 #define EXT3_XATTR_INDEX_SECURITY	        6
 
 struct ext3_xattr_header {
-	__u32	h_magic;	/* magic number for identification */
-	__u32	h_refcount;	/* reference count */
-	__u32	h_blocks;	/* number of disk blocks used */
-	__u32	h_hash;		/* hash value of all attributes */
+	__le32	h_magic;	/* magic number for identification */
+	__le32	h_refcount;	/* reference count */
+	__le32	h_blocks;	/* number of disk blocks used */
+	__le32	h_hash;		/* hash value of all attributes */
 	__u32	h_reserved[4];	/* zero right now */
 };
 
 struct ext3_xattr_entry {
 	__u8	e_name_len;	/* length of name */
 	__u8	e_name_index;	/* attribute name index */
-	__u16	e_value_offs;	/* offset in disk block of value */
-	__u32	e_value_block;	/* disk block attribute is stored on (n/i) */
-	__u32	e_value_size;	/* size of attribute value */
-	__u32	e_hash;		/* hash value of name and value */
+	__le16	e_value_offs;	/* offset in disk block of value */
+	__le32	e_value_block;	/* disk block attribute is stored on (n/i) */
+	__le32	e_value_size;	/* size of attribute value */
+	__le32	e_hash;		/* hash value of name and value */
 	char	e_name[0];	/* attribute name */
 };
 
diff --git a/fs/fat/cache.c b/fs/fat/cache.c
index eec09901e..ad8ff5fc6 100644
--- a/fs/fat/cache.c
+++ b/fs/fat/cache.c
@@ -45,13 +45,13 @@ int __fat_access(struct super_block *sb, int nr, int new_value)
 	}
 	if (sbi->fat_bits == 32) {
 		p_first = p_last = NULL; /* GCC needs that stuff */
-		next = CF_LE_L(((__u32 *) bh->b_data)[(first &
+		next = CF_LE_L(((__le32 *) bh->b_data)[(first &
 		    (sb->s_blocksize - 1)) >> 2]);
 		/* Fscking Microsoft marketing department. Their "32" is 28. */
 		next &= 0x0fffffff;
 	} else if (sbi->fat_bits == 16) {
 		p_first = p_last = NULL; /* GCC needs that stuff */
-		next = CF_LE_W(((__u16 *) bh->b_data)[(first &
+		next = CF_LE_W(((__le16 *) bh->b_data)[(first &
 		    (sb->s_blocksize - 1)) >> 1]);
 	} else {
 		p_first = &((__u8 *)bh->b_data)[first & (sb->s_blocksize - 1)];
@@ -63,10 +63,10 @@ int __fat_access(struct super_block *sb, int nr, int new_value)
 	}
 	if (new_value != -1) {
 		if (sbi->fat_bits == 32) {
-			((__u32 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 2]
+			((__le32 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 2]
 				= CT_LE_L(new_value);
 		} else if (sbi->fat_bits == 16) {
-			((__u16 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 1]
+			((__le16 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 1]
 				= CT_LE_W(new_value);
 		} else {
 			if (nr & 1) {
@@ -146,7 +146,8 @@ void fat_cache_init(struct super_block *sb)
 	sbi->cache = sbi->cache_array;
 }
 
-void fat_cache_lookup(struct inode *inode, int cluster, int *f_clu, int *d_clu)
+static void
+fat_cache_lookup(struct inode *inode, int cluster, int *f_clu, int *d_clu)
 {
 	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
 	struct fat_cache *walk;
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index 27ee2ec82..993d50c0d 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -93,14 +93,6 @@ static void dump_de(struct msdos_dir_entry *de)
 }
 #endif
 
-static inline unsigned char
-fat_tolower(struct nls_table *t, unsigned char c)
-{
-	unsigned char nc = t->charset2lower[c];
-
-	return nc ? nc : c;
-}
-
 static inline int
 fat_short2uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *uni)
 {
@@ -140,17 +132,6 @@ fat_short2lower_uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *un
 	return charlen;
 }
 
-static int
-fat_strnicmp(struct nls_table *t, const unsigned char *s1,
-					const unsigned char *s2, int len)
-{
-	while(len--)
-		if (fat_tolower(t, *s1++) != fat_tolower(t, *s2++))
-			return 1;
-
-	return 0;
-}
-
 static inline int
 fat_shortname2uni(struct nls_table *nls, unsigned char *buf, int buf_size,
 		  wchar_t *uni_buf, unsigned short opt, int lower)
@@ -311,7 +292,7 @@ parse_long:
 			:uni16_to_x8(bufname, bufuname, uni_xlate, nls_io);
 		if (xlate_len == name_len)
 			if ((!anycase && !memcmp(name, bufname, xlate_len)) ||
-			    (anycase && !fat_strnicmp(nls_io, name, bufname,
+			    (anycase && !nls_strnicmp(nls_io, name, bufname,
 								xlate_len)))
 				goto Found;
 
@@ -322,7 +303,7 @@ parse_long:
 			if (xlate_len != name_len)
 				continue;
 			if ((!anycase && !memcmp(name, bufname, xlate_len)) ||
-			    (anycase && !fat_strnicmp(nls_io, name, bufname,
+			    (anycase && !nls_strnicmp(nls_io, name, bufname,
 								xlate_len)))
 				goto Found;
 		}
@@ -733,7 +714,7 @@ int fat_new_dir(struct inode *dir, struct inode *parent, int is_vfat)
 {
 	struct buffer_head *bh;
 	struct msdos_dir_entry *de;
-	__u16 date, time;
+	__le16 date, time;
 
 	bh = fat_extend_dir(dir);
 	if (IS_ERR(bh))
@@ -745,12 +726,12 @@ int fat_new_dir(struct inode *dir, struct inode *parent, int is_vfat)
 	memcpy(de[0].name,MSDOS_DOT,MSDOS_NAME);
 	memcpy(de[1].name,MSDOS_DOTDOT,MSDOS_NAME);
 	de[0].attr = de[1].attr = ATTR_DIR;
-	de[0].time = de[1].time = CT_LE_W(time);
-	de[0].date = de[1].date = CT_LE_W(date);
+	de[0].time = de[1].time = time;
+	de[0].date = de[1].date = date;
 	if (is_vfat) {	/* extra timestamps */
-		de[0].ctime = de[1].ctime = CT_LE_W(time);
+		de[0].ctime = de[1].ctime = time;
 		de[0].adate = de[0].cdate =
-			de[1].adate = de[1].cdate = CT_LE_W(date);
+			de[1].adate = de[1].cdate = date;
 	}
 	de[0].start = CT_LE_W(MSDOS_I(dir)->i_logstart);
 	de[0].starthi = CT_LE_W(MSDOS_I(dir)->i_logstart>>16);
diff --git a/fs/fat/file.c b/fs/fat/file.c
index ba1707a5c..3b48219ae 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -90,12 +90,6 @@ void fat_truncate(struct inode *inode)
 	const unsigned int cluster_size = sbi->cluster_size;
 	int nr_clusters;
 
-	/* Why no return value?  Surely the disk could fail... */
-	if (IS_RDONLY (inode))
-		return /* -EPERM */;
-	if (IS_IMMUTABLE(inode))
-		return /* -EPERM */;
-
 	/* 
 	 * This protects against truncating a file bigger than it was then
 	 * trying to write into the hole.
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index c0fc6b7d6..88368130e 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -59,7 +59,7 @@ static char fat_default_iocharset[] = CONFIG_FAT_DEFAULT_IOCHARSET;
 #define FAT_HASH_SIZE	(1UL << FAT_HASH_BITS)
 #define FAT_HASH_MASK	(FAT_HASH_SIZE-1)
 static struct list_head fat_inode_hashtable[FAT_HASH_SIZE];
-spinlock_t fat_inode_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t fat_inode_lock = SPIN_LOCK_UNLOCKED;
 
 void fat_hash_init(void)
 {
@@ -579,12 +579,11 @@ static int fat_read_root(struct inode *inode)
  * of i_logstart is used to store the directory entry offset.
  */
 
-struct dentry *fat_decode_fh(struct super_block *sb, __u32 *fh,
-			     int len, int fhtype, 
-			     int (*acceptable)(void *context, struct dentry *de),
-			     void *context)
+static struct dentry *
+fat_decode_fh(struct super_block *sb, __u32 *fh, int len, int fhtype, 
+	      int (*acceptable)(void *context, struct dentry *de),
+	      void *context)
 {
-
 	if (fhtype != 3)
 		return ERR_PTR(-ESTALE);
 	if (len < 5)
@@ -593,7 +592,7 @@ struct dentry *fat_decode_fh(struct super_block *sb, __u32 *fh,
 	return sb->s_export_op->find_exported_dentry(sb, fh, NULL, acceptable, context);
 }
 
-struct dentry *fat_get_dentry(struct super_block *sb, void *inump)
+static struct dentry *fat_get_dentry(struct super_block *sb, void *inump)
 {
 	struct inode *inode = NULL;
 	struct dentry *result;
@@ -653,7 +652,8 @@ struct dentry *fat_get_dentry(struct super_block *sb, void *inump)
 	return result;
 }
 
-int fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable)
+static int
+fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable)
 {
 	int len = *lenp;
 	struct inode *inode =  de->d_inode;
@@ -676,7 +676,7 @@ int fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable)
 	return 3;
 }
 
-struct dentry *fat_get_parent(struct dentry *child)
+static struct dentry *fat_get_parent(struct dentry *child)
 {
 	struct buffer_head *bh=NULL;
 	struct msdos_dir_entry *de = NULL;
@@ -744,7 +744,7 @@ int __init fat_init_inodecache(void)
 {
 	fat_inode_cachep = kmem_cache_create("fat_inode_cache",
 					     sizeof(struct msdos_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (fat_inode_cachep == NULL)
 		return -ENOMEM;
@@ -857,7 +857,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
 		brelse(bh);
 		goto out_invalid;
 	}
-	logical_sector_size = CF_LE_W(get_unaligned((u16 *)&b->sector_size));
+	logical_sector_size = CF_LE_W(get_unaligned((__le16 *)&b->sector_size));
 	if (!logical_sector_size
 	    || (logical_sector_size & (logical_sector_size - 1))
 	    || (logical_sector_size < 512)
@@ -957,7 +957,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
 	sbi->dir_per_block_bits = ffs(sbi->dir_per_block) - 1;
 
 	sbi->dir_start = sbi->fat_start + sbi->fats * sbi->fat_length;
-	sbi->dir_entries = CF_LE_W(get_unaligned((u16 *)&b->dir_entries));
+	sbi->dir_entries = CF_LE_W(get_unaligned((__le16 *)&b->dir_entries));
 	if (sbi->dir_entries & (sbi->dir_per_block - 1)) {
 		if (!silent)
 			printk(KERN_ERR "FAT: bogus directroy-entries per block"
@@ -969,7 +969,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
 	rootdir_sectors = sbi->dir_entries
 		* sizeof(struct msdos_dir_entry) / sb->s_blocksize;
 	sbi->data_start = sbi->dir_start + rootdir_sectors;
-	total_sectors = CF_LE_W(get_unaligned((u16 *)&b->sectors));
+	total_sectors = CF_LE_W(get_unaligned((__le16 *)&b->sectors));
 	if (total_sectors == 0)
 		total_sectors = CF_LE_L(b->total_sect);
 
@@ -1227,7 +1227,7 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
 	return 0;
 }
 
-void fat_write_inode(struct inode *inode, int wait)
+int fat_write_inode(struct inode *inode, int wait)
 {
 	struct super_block *sb = inode->i_sb;
 	struct buffer_head *bh;
@@ -1237,14 +1237,14 @@ void fat_write_inode(struct inode *inode, int wait)
 retry:
 	i_pos = MSDOS_I(inode)->i_pos;
 	if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) {
-		return;
+		return 0;
 	}
 	lock_kernel();
 	if (!(bh = sb_bread(sb, i_pos >> MSDOS_SB(sb)->dir_per_block_bits))) {
 		printk(KERN_ERR "FAT: unable to read inode block "
 		       "for updating (i_pos %lld)\n", i_pos);
 		unlock_kernel();
-		return /* -EIO */;
+		return -EIO;
 	}
 	spin_lock(&fat_inode_lock);
 	if (i_pos != MSDOS_I(inode)->i_pos) {
@@ -1268,19 +1268,16 @@ retry:
 	    MSDOS_I(inode)->i_attrs;
 	raw_entry->start = CT_LE_W(MSDOS_I(inode)->i_logstart);
 	raw_entry->starthi = CT_LE_W(MSDOS_I(inode)->i_logstart >> 16);
-	fat_date_unix2dos(inode->i_mtime.tv_sec,&raw_entry->time,&raw_entry->date);
-	raw_entry->time = CT_LE_W(raw_entry->time);
-	raw_entry->date = CT_LE_W(raw_entry->date);
+	fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date);
 	if (MSDOS_SB(sb)->options.isvfat) {
 		fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate);
 		raw_entry->ctime_ms = MSDOS_I(inode)->i_ctime_ms; /* use i_ctime.tv_nsec? */
-		raw_entry->ctime = CT_LE_W(raw_entry->ctime);
-		raw_entry->cdate = CT_LE_W(raw_entry->cdate);
 	}
 	spin_unlock(&fat_inode_lock);
 	mark_buffer_dirty(bh);
 	brelse(bh);
 	unlock_kernel();
+	return 0;
 }
 
 
diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index 413a41410..85a85ec5a 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -73,9 +73,9 @@ void fat_clusters_flush(struct super_block *sb)
 		       sbi->fsinfo_sector);
 	} else {
 		if (sbi->free_clusters != -1)
-			fsinfo->free_clusters = CF_LE_L(sbi->free_clusters);
+			fsinfo->free_clusters = cpu_to_le32(sbi->free_clusters);
 		if (sbi->prev_free != -1)
-			fsinfo->next_cluster = CF_LE_L(sbi->prev_free);
+			fsinfo->next_cluster = cpu_to_le32(sbi->prev_free);
 		mark_buffer_dirty(bh);
 	}
 	brelse(bh);
@@ -243,8 +243,7 @@ int date_dos2unix(unsigned short time,unsigned short date)
 
 /* Convert linear UNIX date to a MS-DOS time/date pair. */
 
-void fat_date_unix2dos(int unix_date,unsigned short *time,
-    unsigned short *date)
+void fat_date_unix2dos(int unix_date,__le16 *time, __le16 *date)
 {
 	int day,year,nl_day,month;
 
@@ -254,8 +253,8 @@ void fat_date_unix2dos(int unix_date,unsigned short *time,
 	if (unix_date < 315532800)
 		unix_date = 315532800;
 
-	*time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
-	    (((unix_date/3600) % 24) << 11);
+	*time = cpu_to_le16((unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
+	    (((unix_date/3600) % 24) << 11));
 	day = unix_date/86400-3652;
 	year = day/365;
 	if ((year+3)/4+365*year > day) year--;
@@ -269,7 +268,7 @@ void fat_date_unix2dos(int unix_date,unsigned short *time,
 		for (month = 0; month < 12; month++)
 			if (day_n[month] > nl_day) break;
 	}
-	*date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9);
+	*date = cpu_to_le16(nl_day-day_n[month-1]+1+(month << 5)+(year << 9));
 }
 
 
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 3d9a94866..4cac5ba47 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -497,16 +497,14 @@ void send_sigio(struct fown_struct *fown, int fd, int band)
 	
 	read_lock(&tasklist_lock);
 	if (pid > 0) {
-		p = find_task_by_pid(pid);
+		p = find_task_by_real_pid(pid);
 		if (p) {
 			send_sigio_to_task(p, fown, fd, band);
 		}
 	} else {
-		struct list_head *l;
-		struct pid *pidptr;
-		for_each_task_pid(-pid, PIDTYPE_PGID, p, l, pidptr) {
+		do_each_task_pid(-pid, PIDTYPE_PGID, p) {
 			send_sigio_to_task(p, fown, fd, band);
-		}
+		} while_each_task_pid(-pid, PIDTYPE_PGID, p);
 	}
 	read_unlock(&tasklist_lock);
  out_unlock_fown:
@@ -534,16 +532,14 @@ int send_sigurg(struct fown_struct *fown)
 	
 	read_lock(&tasklist_lock);
 	if (pid > 0) {
-		p = find_task_by_pid(pid);
+		p = find_task_by_real_pid(pid);
 		if (p) {
 			send_sigurg_to_task(p, fown);
 		}
 	} else {
-		struct list_head *l;
-		struct pid *pidptr;
-		for_each_task_pid(-pid, PIDTYPE_PGID, p, l, pidptr) {
+		do_each_task_pid(-pid, PIDTYPE_PGID, p) {
 			send_sigurg_to_task(p, fown);
-		}
+		} while_each_task_pid(-pid, PIDTYPE_PGID, p);
 	}
 	read_unlock(&tasklist_lock);
  out_unlock_fown:
diff --git a/fs/file_table.c b/fs/file_table.c
index 8996d4d11..9d71ae080 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -17,6 +17,7 @@
 #include <linux/mount.h>
 #include <linux/cdev.h>
 #include <linux/vs_limit.h>
+#include <linux/vs_context.h>
 
 /* sysctl tunables... */
 struct files_stat_struct files_stat = {
@@ -88,6 +89,8 @@ static int old_max;
 			f->f_owner.lock = RW_LOCK_UNLOCKED;
 			/* f->f_version: 0 */
 			INIT_LIST_HEAD(&f->f_list);
+			// set_vx_info(&f->f_vx_info, current->vx_info);
+			f->f_xid = current->xid;
 			vx_files_inc(f);
 			return f;
 		}
@@ -108,52 +111,6 @@ fail:
 
 EXPORT_SYMBOL(get_empty_filp);
 
-/*
- * Clear and initialize a (private) struct file for the given dentry,
- * allocate the security structure, and call the open function (if any).  
- * The file should be released using close_private_file.
- */
-int open_private_file(struct file *filp, struct dentry *dentry, int flags)
-{
-	int error;
-	memset(filp, 0, sizeof(*filp));
-	eventpoll_init_file(filp);
-	filp->f_flags  = flags;
-	filp->f_mode   = ((flags+1) & O_ACCMODE) | FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
-	atomic_set(&filp->f_count, 1);
-	filp->f_dentry = dentry;
-	filp->f_mapping = dentry->d_inode->i_mapping;
-	filp->f_uid    = current->fsuid;
-	filp->f_gid    = current->fsgid;
-	filp->f_op     = dentry->d_inode->i_fop;
-	INIT_LIST_HEAD(&filp->f_list);
-	error = security_file_alloc(filp);
-	if (!error)
-		if (filp->f_op && filp->f_op->open) {
-			error = filp->f_op->open(dentry->d_inode, filp);
-			if (error)
-				security_file_free(filp);
-		}
-	return error;
-}
-
-EXPORT_SYMBOL(open_private_file);
-
-/*
- * Release a private file by calling the release function (if any) and
- * freeing the security structure.
- */
-void close_private_file(struct file *file)
-{
-	struct inode * inode = file->f_dentry->d_inode;
-
-	if (file->f_op && file->f_op->release)
-		file->f_op->release(inode, file);
-	security_file_free(file);
-}
-
-EXPORT_SYMBOL(close_private_file);
-
 void fastcall fput(struct file *file)
 {
 	if (atomic_dec_and_test(&file->f_count))
@@ -171,6 +128,7 @@ void fastcall __fput(struct file *file)
 	struct vfsmount *mnt = file->f_vfsmnt;
 	struct inode *inode = dentry->d_inode;
 
+	might_sleep();
 	/*
 	 * The function eventpoll_release() should be the first called
 	 * in the file cleanup chain.
@@ -187,6 +145,7 @@ void fastcall __fput(struct file *file)
 	if (file->f_mode & FMODE_WRITE)
 		put_write_access(inode);
 	vx_files_dec(file);
+	file->f_xid = 0;
 	file_kill(file);
 	file->f_dentry = NULL;
 	file->f_vfsmnt = NULL;
@@ -242,6 +201,8 @@ void put_filp(struct file *file)
 {
 	if (atomic_dec_and_test(&file->f_count)) {
 		security_file_free(file);
+		vx_files_dec(file);
+		file->f_xid = 0;
 		file_kill(file);
 		file_free(file);
 	}
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h
index 0e4cc9ff5..d8be917f9 100644
--- a/fs/freevxfs/vxfs_extern.h
+++ b/fs/freevxfs/vxfs_extern.h
@@ -59,7 +59,7 @@ extern void			vxfs_put_fake_inode(struct inode *);
 extern struct vxfs_inode_info *	vxfs_blkiget(struct super_block *, u_long, ino_t);
 extern struct vxfs_inode_info *	vxfs_stiget(struct super_block *, ino_t);
 extern void			vxfs_read_inode(struct inode *);
-extern void			vxfs_put_inode(struct inode *);
+extern void			vxfs_clear_inode(struct inode *);
 
 /* vxfs_lookup.c */
 extern struct inode_operations	vxfs_dir_inode_ops;
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index f4b891eb0..9672d2fac 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -337,16 +337,15 @@ vxfs_read_inode(struct inode *ip)
 }
 
 /**
- * vxfs_put_inode - remove inode from main memory
+ * vxfs_clear_inode - remove inode from main memory
  * @ip:		inode to discard.
  *
  * Description:
- *  vxfs_put_inode() is called on each iput.  If we are the last
- *  link in memory, free the fspriv inode area.
+ *  vxfs_clear_inode() is called on the final iput and frees the private
+ *  inode area.
  */
 void
-vxfs_put_inode(struct inode *ip)
+vxfs_clear_inode(struct inode *ip)
 {
-	if (atomic_read(&ip->i_count) == 1)
-		kmem_cache_free(vxfs_inode_cachep, ip->u.generic_ip);
+	kmem_cache_free(vxfs_inode_cachep, ip->u.generic_ip);
 }
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index 8fcec56e9..0ae2c7b81 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -60,7 +60,7 @@ static int		vxfs_remount(struct super_block *, int *, char *);
 
 static struct super_operations vxfs_super_ops = {
 	.read_inode =		vxfs_read_inode,
-	.put_inode =		vxfs_put_inode,
+	.clear_inode =		vxfs_clear_inode,
 	.put_super =		vxfs_put_super,
 	.statfs =		vxfs_statfs,
 	.remount_fs =		vxfs_remount,
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 430afc37d..da522d511 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -133,10 +133,11 @@ out:
 
 EXPORT_SYMBOL(__mark_inode_dirty);
 
-static void write_inode(struct inode *inode, int sync)
+static int write_inode(struct inode *inode, int sync)
 {
 	if (inode->i_sb->s_op->write_inode && !is_bad_inode(inode))
-		inode->i_sb->s_op->write_inode(inode, sync);
+		return inode->i_sb->s_op->write_inode(inode, sync);
+	return 0;
 }
 
 /*
@@ -170,8 +171,11 @@ __sync_single_inode(struct inode *inode, struct writeback_control *wbc)
 	ret = do_writepages(mapping, wbc);
 
 	/* Don't write the inode if only I_DIRTY_PAGES was set */
-	if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC))
-		write_inode(inode, wait);
+	if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) {
+		int err = write_inode(inode, wait);
+		if (ret == 0)
+			ret = err;
+	}
 
 	if (wait) {
 		int err = filemap_fdatawait(mapping);
@@ -304,14 +308,20 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
 		long pages_skipped;
 
 		if (bdi->memory_backed) {
+			list_move(&inode->i_list, &sb->s_dirty);
 			if (sb == blockdev_superblock) {
 				/*
 				 * Dirty memory-backed blockdev: the ramdisk
-				 * driver does this.
+				 * driver does this.  Skip just this inode
 				 */
-				list_move(&inode->i_list, &sb->s_dirty);
 				continue;
 			}
+			/*
+			 * Dirty memory-backed inode against a filesystem other
+			 * than the kernel-internal bdev filesystem.  Skip the
+			 * entire superblock.
+			 */
+			break;
 		}
 
 		if (wbc->nonblocking && bdi_write_congested(bdi)) {
@@ -392,7 +402,7 @@ writeback_inodes(struct writeback_control *wbc)
 {
 	struct super_block *sb;
 
-	spin_lock(&inode_lock);
+	might_sleep();
 	spin_lock(&sb_lock);
 restart:
 	sb = sb_entry(super_blocks.prev);
@@ -407,19 +417,21 @@ restart:
 			 * be unmounted by the time it is released.
 			 */
 			if (down_read_trylock(&sb->s_umount)) {
-				if (sb->s_root)
+				if (sb->s_root) {
+					spin_lock(&inode_lock);
 					sync_sb_inodes(sb, wbc);
+					spin_unlock(&inode_lock);
+				}
 				up_read(&sb->s_umount);
 			}
 			spin_lock(&sb_lock);
-			if (__put_super(sb))
+			if (__put_super_and_need_restart(sb))
 				goto restart;
 		}
 		if (wbc->nr_to_write <= 0)
 			break;
 	}
 	spin_unlock(&sb_lock);
-	spin_unlock(&inode_lock);
 }
 
 /*
@@ -547,6 +559,7 @@ void write_inode_now(struct inode *inode, int sync)
 	if (inode->i_mapping->backing_dev_info->memory_backed)
 		return;
 
+	might_sleep();
 	spin_lock(&inode_lock);
 	__writeback_single_inode(inode, &wbc);
 	spin_unlock(&inode_lock);
diff --git a/fs/hfs/bfind.c b/fs/hfs/bfind.c
index af78ad64f..89450ae32 100644
--- a/fs/hfs/bfind.c
+++ b/fs/hfs/bfind.c
@@ -85,7 +85,8 @@ int hfs_brec_find(struct hfs_find_data *fd)
 {
 	struct hfs_btree *tree;
 	struct hfs_bnode *bnode;
-	u32 data, nidx, parent;
+	u32 nidx, parent;
+	__be32 data;
 	int height, res;
 
 	tree = fd->tree;
diff --git a/fs/hfs/bitmap.c b/fs/hfs/bitmap.c
index 117fe1e19..24e75798d 100644
--- a/fs/hfs/bitmap.c
+++ b/fs/hfs/bitmap.c
@@ -26,10 +26,11 @@
  *  Accesses memory in 32-bit aligned chunks of 32-bits and thus
  *  may read beyond the 'size'th bit.
  */
-static u32 hfs_find_set_zero_bits(u32 *bitmap, u32 size, u32 offset, u32 *max)
+static u32 hfs_find_set_zero_bits(__be32 *bitmap, u32 size, u32 offset, u32 *max)
 {
-	u32 *curr, *end;
-	u32 val, mask, start, len;
+	__be32 *curr, *end;
+	u32 mask, start, len, n;
+	__be32 val;
 	int i;
 
 	len = *max;
@@ -42,11 +43,11 @@ static u32 hfs_find_set_zero_bits(u32 *bitmap, u32 size, u32 offset, u32 *max)
 	/* scan the first partial u32 for zero bits */
 	val = *curr;
 	if (~val) {
-		val = be32_to_cpu(val);
+		n = be32_to_cpu(val);
 		i = offset % 32;
 		mask = (1U << 31) >> i;
 		for (; i < 32; mask >>= 1, i++) {
-			if (!(val & mask))
+			if (!(n & mask))
 				goto found;
 		}
 	}
@@ -55,10 +56,10 @@ static u32 hfs_find_set_zero_bits(u32 *bitmap, u32 size, u32 offset, u32 *max)
 	while (++curr < end) {
 		val = *curr;
 		if (~val) {
-			val = be32_to_cpu(val);
+			n = be32_to_cpu(val);
 			mask = 1 << 31;
 			for (i = 0; i < 32; mask >>= 1, i++) {
-				if (!(val & mask))
+				if (!(n & mask))
 					goto found;
 			}
 		}
@@ -72,38 +73,38 @@ found:
 	/* do any partial u32 at the start */
 	len = min(size - start, len);
 	while (1) {
-		val |= mask;
+		n |= mask;
 		if (++i >= 32)
 			break;
 		mask >>= 1;
-		if (!--len || val & mask)
+		if (!--len || n & mask)
 			goto done;
 	}
 	if (!--len)
 		goto done;
-	*curr++ = cpu_to_be32(val);
+	*curr++ = cpu_to_be32(n);
 	/* do full u32s */
 	while (1) {
-		val = be32_to_cpu(*curr);
+		n = be32_to_cpu(*curr);
 		if (len < 32)
 			break;
-		if (val) {
+		if (n) {
 			len = 32;
 			break;
 		}
-		*curr++ = 0xffffffffU;
+		*curr++ = cpu_to_be32(0xffffffff);
 		len -= 32;
 	}
 	/* do any partial u32 at end */
 	mask = 1U << 31;
 	for (i = 0; i < len; i++) {
-		if (val & mask)
+		if (n & mask)
 			break;
-		val |= mask;
+		n |= mask;
 		mask >>= 1;
 	}
 done:
-	*curr = cpu_to_be32(val);
+	*curr = cpu_to_be32(n);
 	*max = (curr - bitmap) * 32 + i - start;
 	return start;
 }
@@ -191,7 +192,7 @@ out:
  */
 int hfs_clear_vbm_bits(struct super_block *sb, u16 start, u16 count)
 {
-	u32 *curr;
+	__be32 *curr;
 	u32 mask;
 	int i, len;
 
diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c
index d0cf0a6f4..b47ab4283 100644
--- a/fs/hfs/bnode.c
+++ b/fs/hfs/bnode.c
@@ -29,7 +29,7 @@ void hfs_bnode_read(struct hfs_bnode *node, void *buf,
 
 u16 hfs_bnode_read_u16(struct hfs_bnode *node, int off)
 {
-	u16 data;
+	__be16 data;
 	// optimize later...
 	hfs_bnode_read(node, &data, off, 2);
 	return be16_to_cpu(data);
@@ -72,9 +72,9 @@ void hfs_bnode_write(struct hfs_bnode *node, void *buf, int off, int len)
 
 void hfs_bnode_write_u16(struct hfs_bnode *node, int off, u16 data)
 {
-	data = cpu_to_be16(data);
+	__be16 v = cpu_to_be16(data);
 	// optimize later...
-	hfs_bnode_write(node, &data, off, 2);
+	hfs_bnode_write(node, &v, off, 2);
 }
 
 void hfs_bnode_write_u8(struct hfs_bnode *node, int off, u8 data)
@@ -136,7 +136,7 @@ void hfs_bnode_move(struct hfs_bnode *node, int dst, int src, int len)
 void hfs_bnode_dump(struct hfs_bnode *node)
 {
 	struct hfs_bnode_desc desc;
-	u32 cnid;
+	__be32 cnid;
 	int i, off, key_off;
 
 	dprint(DBG_BNODE_MOD, "bnode: %d\n", node->this);
@@ -173,7 +173,7 @@ void hfs_bnode_unlink(struct hfs_bnode *node)
 {
 	struct hfs_btree *tree;
 	struct hfs_bnode *tmp;
-	u32 cnid;
+	__be32 cnid;
 
 	tree = node->tree;
 	if (node->prev) {
diff --git a/fs/hfs/brec.c b/fs/hfs/brec.c
index 5e54671dc..10e986c2f 100644
--- a/fs/hfs/brec.c
+++ b/fs/hfs/brec.c
@@ -13,7 +13,7 @@
 /* Get the length and offset of the given record in the given node */
 u16 hfs_brec_lenoff(struct hfs_bnode *node, u16 rec, u16 *off)
 {
-	u16 retval[2];
+	__be16 retval[2];
 	u16 dataoff;
 
 	dataoff = node->tree->node_size - (rec + 2) * 2;
@@ -55,7 +55,7 @@ int hfs_brec_insert(struct hfs_find_data *fd, void *entry, int entry_len)
 	int size, key_len, rec;
 	int data_off, end_off;
 	int idx_rec_off, data_rec_off, end_rec_off;
-	u32 cnid;
+	__be32 cnid;
 
 	tree = fd->tree;
 	if (!fd->bnode) {
@@ -391,7 +391,7 @@ skip:
 	node = parent;
 
 	if (new_node) {
-		u32 cnid;
+		__be32 cnid;
 
 		fd->bnode = hfs_bnode_find(tree, new_node->parent);
 		/* create index key and entry */
@@ -423,7 +423,7 @@ int hfs_btree_inc_height(struct hfs_btree *tree)
 	struct hfs_bnode *node, *new_node;
 	struct hfs_bnode_desc node_desc;
 	int key_size, rec;
-	u32 cnid;
+	__be32 cnid;
 
 	node = NULL;
 	if (tree->root) {
diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c
index 19f10cf9f..64354debf 100644
--- a/fs/hfs/btree.c
+++ b/fs/hfs/btree.c
@@ -154,7 +154,7 @@ static struct hfs_bnode *hfs_bmap_new_bmap(struct hfs_bnode *prev, u32 idx)
 	struct hfs_btree *tree = prev->tree;
 	struct hfs_bnode *node;
 	struct hfs_bnode_desc desc;
-	u32 cnid;
+	__be32 cnid;
 
 	node = hfs_bnode_create(tree, idx);
 	if (IS_ERR(node))
diff --git a/fs/hfs/btree.h b/fs/hfs/btree.h
index 266af5e54..87eaa9ff8 100644
--- a/fs/hfs/btree.h
+++ b/fs/hfs/btree.h
@@ -125,11 +125,11 @@ extern int hfs_brec_goto(struct hfs_find_data *, int);
 
 
 struct hfs_bnode_desc {
-	u32 next;		/* (V) Number of the next node at this level */
-	u32 prev;		/* (V) Number of the prev node at this level */
+	__be32 next;		/* (V) Number of the next node at this level */
+	__be32 prev;		/* (V) Number of the prev node at this level */
 	u8 type;		/* (F) The type of node */
 	u8 height;		/* (F) The level of this node (leaves=1) */
-	u16 num_recs;		/* (V) The number of records in this node */
+	__be16 num_recs;	/* (V) The number of records in this node */
 	u16 reserved;
 } __packed;
 
@@ -139,20 +139,20 @@ struct hfs_bnode_desc {
 #define HFS_NODE_LEAF	0xFF	/* A leaf (ndNHeight==1) node */
 
 struct hfs_btree_header_rec {
-	u16 depth;		/* (V) The number of levels in this B-tree */
-	u32 root;		/* (V) The node number of the root node */
-	u32 leaf_count;		/* (V) The number of leaf records */
-	u32 leaf_head;		/* (V) The number of the first leaf node */
-	u32 leaf_tail;		/* (V) The number of the last leaf node */
-	u16 node_size;		/* (F) The number of bytes in a node (=512) */
-	u16 max_key_len;	/* (F) The length of a key in an index node */
-	u32 node_count;		/* (V) The total number of nodes */
-	u32 free_nodes;		/* (V) The number of unused nodes */
+	__be16 depth;		/* (V) The number of levels in this B-tree */
+	__be32 root;		/* (V) The node number of the root node */
+	__be32 leaf_count;	/* (V) The number of leaf records */
+	__be32 leaf_head;	/* (V) The number of the first leaf node */
+	__be32 leaf_tail;	/* (V) The number of the last leaf node */
+	__be16 node_size;	/* (F) The number of bytes in a node (=512) */
+	__be16 max_key_len;	/* (F) The length of a key in an index node */
+	__be32 node_count;	/* (V) The total number of nodes */
+	__be32 free_nodes;	/* (V) The number of unused nodes */
 	u16 reserved1;
-	u32 clump_size;		/* (F) clump size. not usually used. */
+	__be32 clump_size;	/* (F) clump size. not usually used. */
 	u8 btree_type;		/* (F) BTree type */
 	u8 reserved2;
-	u32 attributes;		/* (F) attributes */
+	__be32 attributes;	/* (F) attributes */
 	u32 reserved3[16];
 } __packed;
 
diff --git a/fs/hfs/catalog.c b/fs/hfs/catalog.c
index d38e18c2f..b21c09b78 100644
--- a/fs/hfs/catalog.c
+++ b/fs/hfs/catalog.c
@@ -35,7 +35,7 @@ void hfs_cat_build_key(btree_key *key, u32 parent, struct qstr *name)
 
 int hfs_cat_build_record(hfs_cat_rec *rec, u32 cnid, struct inode *inode)
 {
-	u32 mtime = hfs_mtime();
+	__be32 mtime = hfs_mtime();
 
 	memset(rec, 0, sizeof(*rec));
 	if (S_ISDIR(inode->i_mode)) {
diff --git a/fs/hfs/extent.c b/fs/hfs/extent.c
index a9f4e23f7..b7ce3f048 100644
--- a/fs/hfs/extent.c
+++ b/fs/hfs/extent.c
@@ -279,13 +279,13 @@ int hfs_free_fork(struct super_block *sb, struct hfs_cat_file *file, int type)
 	int res, i;
 
 	if (type == HFS_FK_DATA) {
-		total_blocks = file->PyLen;
+		total_blocks = be32_to_cpu(file->PyLen);
 		extent = file->ExtRec;
 	} else {
-		total_blocks = file->RPyLen;
+		total_blocks = be32_to_cpu(file->RPyLen);
 		extent = file->RExtRec;
 	}
-	total_blocks = be32_to_cpu(total_blocks) / HFS_SB(sb)->alloc_blksz;
+	total_blocks /= HFS_SB(sb)->alloc_blksz;
 	if (!total_blocks)
 		return 0;
 
diff --git a/fs/hfs/hfs.h b/fs/hfs/hfs.h
index 73ac40810..df6b33ade 100644
--- a/fs/hfs/hfs.h
+++ b/fs/hfs/hfs.h
@@ -91,45 +91,45 @@ struct hfs_name {
 } __packed;
 
 struct hfs_point {
-	u16 v;
-	u16 h;
+	__be16 v;
+	__be16 h;
 } __packed;
 
 struct hfs_rect {
-	u16 top;
-	u16 left;
-	u16 bottom;
-	u16 right;
+	__be16 top;
+	__be16 left;
+	__be16 bottom;
+	__be16 right;
 } __packed;
 
 struct hfs_finfo {
-	u32 fdType;
-	u32 fdCreator;
-	u16 fdFlags;
+	__be32 fdType;
+	__be32 fdCreator;
+	__be16 fdFlags;
 	struct hfs_point fdLocation;
-	u16 fdFldr;
+	__be16 fdFldr;
 } __packed;
 
 struct hfs_fxinfo {
-	u16 fdIconID;
+	__be16 fdIconID;
 	u8 fdUnused[8];
-	u16 fdComment;
-	u32 fdPutAway;
+	__be16 fdComment;
+	__be32 fdPutAway;
 } __packed;
 
 struct hfs_dinfo {
 	struct hfs_rect frRect;
-	u16 frFlags;
+	__be16 frFlags;
 	struct hfs_point frLocation;
-	u16 frView;
+	__be16 frView;
 } __packed;
 
 struct hfs_dxinfo {
 	struct hfs_point frScroll;
-	u32 frOpenChain;
-	u16 frUnused;
-	u16 frComment;
-	u32 frPutAway;
+	__be32 frOpenChain;
+	__be16 frUnused;
+	__be16 frComment;
+	__be32 frPutAway;
 } __packed;
 
 union hfs_finder_info {
@@ -150,7 +150,7 @@ union hfs_finder_info {
 struct hfs_cat_key {
 	u8 key_len;		/* number of bytes in the key */
 	u8 reserved;		/* padding */
-	u32 ParID;		/* CNID of the parent dir */
+	__be32 ParID;		/* CNID of the parent dir */
 	struct hfs_name	CName;	/* The filename of the entry */
 } __packed;
 
@@ -158,8 +158,8 @@ struct hfs_cat_key {
 struct hfs_ext_key {
 	u8 key_len;		/* number of bytes in the key */
 	u8 FkType;		/* HFS_FK_{DATA,RSRC} */
-	u32 FNum;		/* The File ID of the file */
-	u16 FABN;		/* allocation blocks number*/
+	__be32 FNum;		/* The File ID of the file */
+	__be16 FABN;		/* allocation blocks number*/
 } __packed;
 
 typedef union hfs_btree_key {
@@ -171,8 +171,8 @@ typedef union hfs_btree_key {
 typedef union hfs_btree_key btree_key;
 
 struct hfs_extent {
-	u16 block;
-	u16 count;
+	__be16 block;
+	__be16 count;
 };
 typedef struct hfs_extent hfs_extent_rec[3];
 
@@ -183,18 +183,18 @@ struct hfs_cat_file {
 	u8 Flags;			/* Flags such as read-only */
 	s8 Typ;				/* file version number = 0 */
 	struct hfs_finfo UsrWds;	/* data used by the Finder */
-	u32 FlNum;			/* The CNID */
-	u16 StBlk;			/* obsolete */
-	u32 LgLen;			/* The logical EOF of the data fork*/
-	u32 PyLen;			/* The physical EOF of the data fork */
-	u16 RStBlk;			/* obsolete */
-	u32 RLgLen;			/* The logical EOF of the rsrc fork */
-	u32 RPyLen;			/* The physical EOF of the rsrc fork */
-	u32 CrDat;			/* The creation date */
-	u32 MdDat;			/* The modified date */
-	u32 BkDat;			/* The last backup date */
+	__be32 FlNum;			/* The CNID */
+	__be16 StBlk;			/* obsolete */
+	__be32 LgLen;			/* The logical EOF of the data fork*/
+	__be32 PyLen;			/* The physical EOF of the data fork */
+	__be16 RStBlk;			/* obsolete */
+	__be32 RLgLen;			/* The logical EOF of the rsrc fork */
+	__be32 RPyLen;			/* The physical EOF of the rsrc fork */
+	__be32 CrDat;			/* The creation date */
+	__be32 MdDat;			/* The modified date */
+	__be32 BkDat;			/* The last backup date */
 	struct hfs_fxinfo FndrInfo;	/* more data for the Finder */
-	u16 ClpSize;			/* number of bytes to allocate
+	__be16 ClpSize;			/* number of bytes to allocate
 					   when extending files */
 	hfs_extent_rec ExtRec;		/* first extent record
 					   for the data fork */
@@ -207,13 +207,13 @@ struct hfs_cat_file {
 struct hfs_cat_dir {
 	s8 type;			/* The type of entry */
 	u8 reserved;
-	u16 Flags;			/* flags */
-	u16 Val;			/* Valence: number of files and
+	__be16 Flags;			/* flags */
+	__be16 Val;			/* Valence: number of files and
 					   dirs in the directory */
-	u32 DirID;			/* The CNID */
-	u32 CrDat;			/* The creation date */
-	u32 MdDat;			/* The modification date */
-	u32 BkDat;			/* The last backup date */
+	__be32 DirID;			/* The CNID */
+	__be32 CrDat;			/* The creation date */
+	__be32 MdDat;			/* The modification date */
+	__be32 BkDat;			/* The last backup date */
 	struct hfs_dinfo UsrInfo;	/* data used by the Finder */
 	struct hfs_dxinfo FndrInfo;	/* more data used by Finder */
 	u8 Resrv[16];			/* reserved by Apple */
@@ -223,7 +223,7 @@ struct hfs_cat_dir {
 struct hfs_cat_thread {
 	s8 type;			/* The type of entry */
 	u8 reserved[9];			/* reserved by Apple */
-	u32 ParID;			/* CNID of parent directory */
+	__be32 ParID;			/* CNID of parent directory */
 	struct hfs_name CName;		/* The name of this entry */
 }  __packed;
 
@@ -236,43 +236,43 @@ typedef union hfs_cat_rec {
 } hfs_cat_rec;
 
 struct hfs_mdb {
-	u16 drSigWord;			/* Signature word indicating fs type */
-	u32 drCrDate;			/* fs creation date/time */
-	u32 drLsMod;			/* fs modification date/time */
-	u16 drAtrb;			/* fs attributes */
-	u16 drNmFls;			/* number of files in root directory */
-	u16 drVBMSt;			/* location (in 512-byte blocks)
+	__be16 drSigWord;		/* Signature word indicating fs type */
+	__be32 drCrDate;		/* fs creation date/time */
+	__be32 drLsMod;			/* fs modification date/time */
+	__be16 drAtrb;			/* fs attributes */
+	__be16 drNmFls;			/* number of files in root directory */
+	__be16 drVBMSt;			/* location (in 512-byte blocks)
 					   of the volume bitmap */
-	u16 drAllocPtr;			/* location (in allocation blocks)
+	__be16 drAllocPtr;		/* location (in allocation blocks)
 					   to begin next allocation search */
-	u16 drNmAlBlks;			/* number of allocation blocks */
-	u32 drAlBlkSiz;			/* bytes in an allocation block */
-	u32 drClpSiz;			/* clumpsize, the number of bytes to
+	__be16 drNmAlBlks;		/* number of allocation blocks */
+	__be32 drAlBlkSiz;		/* bytes in an allocation block */
+	__be32 drClpSiz;		/* clumpsize, the number of bytes to
 					   allocate when extending a file */
-	u16 drAlBlSt;			/* location (in 512-byte blocks)
+	__be16 drAlBlSt;		/* location (in 512-byte blocks)
 					   of the first allocation block */
-	u32 drNxtCNID;			/* CNID to assign to the next
+	__be32 drNxtCNID;		/* CNID to assign to the next
 					   file or directory created */
-	u16 drFreeBks;			/* number of free allocation blocks */
+	__be16 drFreeBks;		/* number of free allocation blocks */
 	u8 drVN[28];			/* the volume label */
-	u32 drVolBkUp;			/* fs backup date/time */
-	u16 drVSeqNum;			/* backup sequence number */
-	u32 drWrCnt;			/* fs write count */
-	u32 drXTClpSiz;			/* clumpsize for the extents B-tree */
-	u32 drCTClpSiz;			/* clumpsize for the catalog B-tree */
-	u16 drNmRtDirs;			/* number of directories in
+	__be32 drVolBkUp;		/* fs backup date/time */
+	__be16 drVSeqNum;		/* backup sequence number */
+	__be32 drWrCnt;			/* fs write count */
+	__be32 drXTClpSiz;		/* clumpsize for the extents B-tree */
+	__be32 drCTClpSiz;		/* clumpsize for the catalog B-tree */
+	__be16 drNmRtDirs;		/* number of directories in
 					   the root directory */
-	u32 drFilCnt;			/* number of files in the fs */
-	u32 drDirCnt;			/* number of directories in the fs */
+	__be32 drFilCnt;		/* number of files in the fs */
+	__be32 drDirCnt;		/* number of directories in the fs */
 	u8 drFndrInfo[32];		/* data used by the Finder */
-	u16 drEmbedSigWord;		/* embedded volume signature */
-	u32 drEmbedExtent;		/* starting block number (xdrStABN)
+	__be16 drEmbedSigWord;		/* embedded volume signature */
+	__be32 drEmbedExtent;		/* starting block number (xdrStABN)
 					   and number of allocation blocks
 					   (xdrNumABlks) occupied by embedded
 					   volume */
-	u32 drXTFlSize;			/* bytes in the extents B-tree */
+	__be32 drXTFlSize;		/* bytes in the extents B-tree */
 	hfs_extent_rec drXTExtRec;	/* extents B-tree's first 3 extents */
-	u32 drCTFlSize;			/* bytes in the catalog B-tree */
+	__be32 drCTFlSize;		/* bytes in the catalog B-tree */
 	hfs_extent_rec drCTExtRec;	/* catalog B-tree's first 3 extents */
 } __packed;
 
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index 33876db22..ecf33d875 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -90,7 +90,7 @@ struct hfs_sb_info {
 	struct buffer_head *alt_mdb_bh;		/* The hfs_buffer holding
 						   the alternate superblock */
 	struct hfs_mdb *alt_mdb;
-	u32 *bitmap;				/* The page holding the
+	__be32 *bitmap;				/* The page holding the
 						   allocation bitmap */
 	struct hfs_btree *ext_tree;			/* Information about
 						   the extents b-tree */
@@ -129,8 +129,8 @@ struct hfs_sb_info {
 						   "allocation block" */
 	int s_quiet;				/* Silent failure when
 						   changing owner or mode? */
-	u32 s_type;				/* Type for new files */
-	u32 s_creator;				/* Creator for new files */
+	__be32 s_type;				/* Type for new files */
+	__be32 s_creator;			/* Creator for new files */
 	umode_t s_file_umask;			/* The umask applied to the
 						   permissions on all files */
 	umode_t s_dir_umask;			/* The umask applied to the
@@ -197,11 +197,11 @@ extern struct address_space_operations hfs_aops;
 extern struct address_space_operations hfs_btree_aops;
 
 extern struct inode *hfs_new_inode(struct inode *, struct qstr *, int);
-extern void hfs_inode_write_fork(struct inode *, struct hfs_extent *, u32 *, u32 *);
-extern void hfs_write_inode(struct inode *, int);
+extern void hfs_inode_write_fork(struct inode *, struct hfs_extent *, __be32 *, __be32 *);
+extern int hfs_write_inode(struct inode *, int);
 extern int hfs_inode_setattr(struct dentry *, struct iattr *);
 extern void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext,
-				u32 log_size, u32 phys_size, u32 clump_size);
+			__be32 log_size, __be32 phys_size, u32 clump_size);
 extern struct inode *hfs_iget(struct super_block *, struct hfs_cat_key *, hfs_cat_rec *);
 extern void hfs_clear_inode(struct inode *);
 extern void hfs_delete_inode(struct inode *);
@@ -223,9 +223,6 @@ extern int hfs_strcmp(const unsigned char *, unsigned int,
 		      const unsigned char *, unsigned int);
 extern int hfs_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
 
-/* super.c */
-extern struct super_block *hfs_read_super(struct super_block *,void *,int);
-
 /* trans.c */
 extern void hfs_triv2mac(struct hfs_name *, struct qstr *);
 extern int hfs_mac2triv(char *, const struct hfs_name *);
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 4ff20bcc4..6c869f377 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -210,14 +210,14 @@ void hfs_delete_inode(struct inode *inode)
 	dprint(DBG_INODE, "delete_inode: %lu\n", inode->i_ino);
 	if (S_ISDIR(inode->i_mode)) {
 		HFS_SB(sb)->folder_count--;
-		if (HFS_I(inode)->cat_key.ParID == be32_to_cpu(HFS_ROOT_CNID))
+		if (HFS_I(inode)->cat_key.ParID == cpu_to_be32(HFS_ROOT_CNID))
 			HFS_SB(sb)->root_dirs--;
 		set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
 		sb->s_dirt = 1;
 		return;
 	}
 	HFS_SB(sb)->file_count--;
-	if (HFS_I(inode)->cat_key.ParID == be32_to_cpu(HFS_ROOT_CNID))
+	if (HFS_I(inode)->cat_key.ParID == cpu_to_be32(HFS_ROOT_CNID))
 		HFS_SB(sb)->root_files--;
 	if (S_ISREG(inode->i_mode)) {
 		if (!inode->i_nlink) {
@@ -230,9 +230,10 @@ void hfs_delete_inode(struct inode *inode)
 }
 
 void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext,
-			 u32 log_size, u32 phys_size, u32 clump_size)
+			 __be32 __log_size, __be32 phys_size, u32 clump_size)
 {
 	struct super_block *sb = inode->i_sb;
+	u32 log_size = be32_to_cpu(__log_size);
 	u16 count;
 	int i;
 
@@ -241,7 +242,6 @@ void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext,
 		count += be16_to_cpu(ext[i].count);
 	HFS_I(inode)->first_blocks = count;
 
-	log_size = be32_to_cpu(log_size);
 	inode->i_size = HFS_I(inode)->phys_size = log_size;
 	inode->i_blocks = (log_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
 	HFS_I(inode)->alloc_blocks = be32_to_cpu(phys_size) /
@@ -370,7 +370,7 @@ struct inode *hfs_iget(struct super_block *sb, struct hfs_cat_key *key, hfs_cat_
 }
 
 void hfs_inode_write_fork(struct inode *inode, struct hfs_extent *ext,
-			  u32 *log_size, u32 *phys_size)
+			  __be32 *log_size, __be32 *phys_size)
 {
 	memcpy(ext, HFS_I(inode)->first_extents, sizeof(hfs_extent_rec));
 
@@ -381,7 +381,7 @@ void hfs_inode_write_fork(struct inode *inode, struct hfs_extent *ext,
 					 HFS_SB(inode->i_sb)->alloc_blksz);
 }
 
-void hfs_write_inode(struct inode *inode, int unused)
+int hfs_write_inode(struct inode *inode, int unused)
 {
 	struct hfs_find_data fd;
 	hfs_cat_rec rec;
@@ -395,27 +395,27 @@ void hfs_write_inode(struct inode *inode, int unused)
 			break;
 		case HFS_EXT_CNID:
 			hfs_btree_write(HFS_SB(inode->i_sb)->ext_tree);
-			return;
+			return 0;
 		case HFS_CAT_CNID:
 			hfs_btree_write(HFS_SB(inode->i_sb)->cat_tree);
-			return;
+			return 0;
 		default:
 			BUG();
-			return;
+			return -EIO;
 		}
 	}
 
 	if (HFS_IS_RSRC(inode)) {
 		mark_inode_dirty(HFS_I(inode)->rsrc_inode);
-		return;
+		return 0;
 	}
 
 	if (!inode->i_nlink)
-		return;
+		return 0;
 
 	if (hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd))
 		/* panic? */
-		return;
+		return -EIO;
 
 	fd.search_key->cat = HFS_I(inode)->cat_key;
 	if (hfs_brec_find(&fd))
@@ -460,6 +460,7 @@ void hfs_write_inode(struct inode *inode, int unused)
 	}
 out:
 	hfs_find_exit(&fd);
+	return 0;
 }
 
 static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry,
@@ -609,6 +610,7 @@ struct file_operations hfs_file_operations = {
 	.read		= generic_file_read,
 	.write		= generic_file_write,
 	.mmap		= generic_file_mmap,
+	.sendfile	= generic_file_sendfile,
 	.fsync		= file_fsync,
 	.open		= hfs_file_open,
 	.release	= hfs_file_release,
diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c
index cedb9ab18..f90764f65 100644
--- a/fs/hfs/mdb.c
+++ b/fs/hfs/mdb.c
@@ -71,7 +71,7 @@ int hfs_mdb_get(struct super_block *sb)
 	int off2, len, size, sect;
 	sector_t part_start, part_size;
 	loff_t off;
-	u16 attrib;
+	__be16 attrib;
 
 	/* set the device driver to 512-byte blocks */
 	size = sb_min_blocksize(sb, HFS_SECTOR_SIZE);
@@ -164,7 +164,7 @@ int hfs_mdb_get(struct super_block *sb)
 		hfs_warn("hfs_fs: continuing without an alternate MDB\n");
 	}
 
-	HFS_SB(sb)->bitmap = (u32 *)__get_free_pages(GFP_KERNEL, PAGE_SIZE < 8192 ? 1 : 0);
+	HFS_SB(sb)->bitmap = (__be32 *)__get_free_pages(GFP_KERNEL, PAGE_SIZE < 8192 ? 1 : 0);
 	if (!HFS_SB(sb)->bitmap)
 		goto out;
 
diff --git a/fs/hfs/part_tbl.c b/fs/hfs/part_tbl.c
index 19c189dc7..36add537d 100644
--- a/fs/hfs/part_tbl.c
+++ b/fs/hfs/part_tbl.c
@@ -19,11 +19,11 @@
  * contiguous starting at block 1.
  */
 struct new_pmap {
-	u16	pmSig;		/* signature */
-	u16	reSigPad;	/* padding */
-	u32	pmMapBlkCnt;	/* partition blocks count */
-	u32	pmPyPartStart;	/* physical block start of partition */
-	u32	pmPartBlkCnt;	/* physical block count of partition */
+	__be16	pmSig;		/* signature */
+	__be16	reSigPad;	/* padding */
+	__be32	pmMapBlkCnt;	/* partition blocks count */
+	__be32	pmPyPartStart;	/* physical block start of partition */
+	__be32	pmPartBlkCnt;	/* physical block count of partition */
 	u8	pmPartName[32];	/* (null terminated?) string
 				   giving the name of this
 				   partition */
@@ -41,11 +41,11 @@ struct new_pmap {
  * one of these.
  */
 struct old_pmap {
-	u16		pdSig;	/* Signature bytes */
+	__be16		pdSig;	/* Signature bytes */
 	struct 	old_pmap_entry {
-		u32	pdStart;
-		u32	pdSize;
-		u32	pdFSID;
+		__be32	pdStart;
+		__be32	pdSize;
+		__be32	pdFSID;
 	}	pdEntry[42];
 } __packed;
 
@@ -59,7 +59,7 @@ int hfs_part_find(struct super_block *sb,
 		  sector_t *part_start, sector_t *part_size)
 {
 	struct buffer_head *bh;
-	u16 *data;
+	__be16 *data;
 	int i, size, res;
 
 	res = -ENOENT;
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 345651903..c773aa763 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -152,8 +152,7 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
 	hsb->s_gid = current->gid;
 	hsb->s_file_umask = 0644;
 	hsb->s_dir_umask = 0755;
-	hsb->s_type = 0x3f3f3f3f;	/* == '????' */
-	hsb->s_creator = 0x3f3f3f3f;	/* == '????' */
+	hsb->s_type = hsb->s_creator = cpu_to_be32(0x3f3f3f3f);	/* == '????' */
 	hsb->s_quiet = 0;
 	hsb->part = -1;
 	hsb->session = -1;
@@ -216,11 +215,11 @@ static int parse_options(char *options, struct hfs_sb_info *hsb)
 		} else if (!strcmp(this_char, "type") && value) {
 			if (strlen(value) != 4)
 				return 0;
-			hsb->s_type = *(u32 *)value;
+			memcpy(&hsb->s_type, value, 4);
 		} else if (!strcmp(this_char, "creator") && value) {
 			if (strlen(value) != 4)
 				return 0;
-			hsb->s_creator = *(u32 *)value;
+			memcpy(&hsb->s_creator, value, 4);
 	/* Boolean-valued options */
 		} else if (!strcmp(this_char, "quiet")) {
 			if (value)
diff --git a/fs/hfsplus/bfind.c b/fs/hfsplus/bfind.c
index d8305b7e1..257cdde05 100644
--- a/fs/hfsplus/bfind.c
+++ b/fs/hfsplus/bfind.c
@@ -85,7 +85,8 @@ int hfs_brec_find(struct hfs_find_data *fd)
 {
 	struct hfs_btree *tree;
 	struct hfs_bnode *bnode;
-	u32 data, nidx, parent;
+	u32 nidx, parent;
+	__be32 data;
 	int height, res;
 
 	tree = fd->tree;
diff --git a/fs/hfsplus/bitmap.c b/fs/hfsplus/bitmap.c
index 644dcb51a..c7d316455 100644
--- a/fs/hfsplus/bitmap.c
+++ b/fs/hfsplus/bitmap.c
@@ -19,8 +19,9 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma
 {
 	struct page *page;
 	struct address_space *mapping;
-	u32 *pptr, *curr, *end;
-	u32 val, mask, start, len;
+	__be32 *pptr, *curr, *end;
+	u32 mask, start, len, n;
+	__be32 val;
 	int i;
 
 	len = *max;
@@ -44,10 +45,10 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma
 	/* scan the first partial u32 for zero bits */
 	val = *curr;
 	if (~val) {
-		val = be32_to_cpu(val);
+		n = be32_to_cpu(val);
 		mask = (1U << 31) >> i;
 		for (; i < 32; mask >>= 1, i++) {
-			if (!(val & mask))
+			if (!(n & mask))
 				goto found;
 		}
 	}
@@ -58,10 +59,10 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma
 		while (curr < end) {
 			val = *curr;
 			if (~val) {
-				val = be32_to_cpu(val);
+				n = be32_to_cpu(val);
 				mask = 1 << 31;
 				for (i = 0; i < 32; mask >>= 1, i++) {
-					if (!(val & mask))
+					if (!(n & mask))
 						goto found;
 				}
 			}
@@ -92,27 +93,27 @@ found:
 	/* do any partial u32 at the start */
 	len = min(size - start, len);
 	while (1) {
-		val |= mask;
+		n |= mask;
 		if (++i >= 32)
 			break;
 		mask >>= 1;
-		if (!--len || val & mask)
+		if (!--len || n & mask)
 			goto done;
 	}
 	if (!--len)
 		goto done;
-	*curr++ = cpu_to_be32(val);
+	*curr++ = cpu_to_be32(n);
 	/* do full u32s */
 	while (1) {
 		while (curr < end) {
-			val = be32_to_cpu(*curr);
+			n = be32_to_cpu(*curr);
 			if (len < 32)
 				goto last;
-			if (val) {
+			if (n) {
 				len = 32;
 				goto last;
 			}
-			*curr++ = 0xffffffffU;
+			*curr++ = cpu_to_be32(0xffffffff);
 			len -= 32;
 		}
 		set_page_dirty(page);
@@ -128,13 +129,13 @@ last:
 	/* do any partial u32 at end */
 	mask = 1U << 31;
 	for (i = 0; i < len; i++) {
-		if (val & mask)
+		if (n & mask)
 			break;
-		val |= mask;
+		n |= mask;
 		mask >>= 1;
 	}
 done:
-	*curr = cpu_to_be32(val);
+	*curr = cpu_to_be32(n);
 	set_page_dirty(page);
 	kunmap(page);
 	*max = offset + (curr - pptr) * 32 + i - start;
@@ -150,7 +151,7 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count)
 {
 	struct page *page;
 	struct address_space *mapping;
-	u32 *pptr, *curr, *end;
+	__be32 *pptr, *curr, *end;
 	u32 mask, len, pnr;
 	int i;
 
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index 5ce5d7713..e0edb707c 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -44,7 +44,7 @@ void hfs_bnode_read(struct hfs_bnode *node, void *buf, int off, int len)
 
 u16 hfs_bnode_read_u16(struct hfs_bnode *node, int off)
 {
-	u16 data;
+	__be16 data;
 	// optimize later...
 	hfs_bnode_read(node, &data, off, 2);
 	return be16_to_cpu(data);
@@ -55,7 +55,7 @@ u8 hfs_bnode_read_u8(struct hfs_bnode *node, int off)
 	u8 data;
 	// optimize later...
 	hfs_bnode_read(node, &data, off, 1);
-	return be16_to_cpu(data);
+	return data;
 }
 
 void hfs_bnode_read_key(struct hfs_bnode *node, void *key, int off)
@@ -98,9 +98,9 @@ void hfs_bnode_write(struct hfs_bnode *node, void *buf, int off, int len)
 
 void hfs_bnode_write_u16(struct hfs_bnode *node, int off, u16 data)
 {
-	data = cpu_to_be16(data);
+	__be16 v = cpu_to_be16(data);
 	// optimize later...
-	hfs_bnode_write(node, &data, off, 2);
+	hfs_bnode_write(node, &v, off, 2);
 }
 
 void hfs_bnode_clear(struct hfs_bnode *node, int off, int len)
@@ -297,7 +297,7 @@ void hfs_bnode_move(struct hfs_bnode *node, int dst, int src, int len)
 void hfs_bnode_dump(struct hfs_bnode *node)
 {
 	struct hfs_bnode_desc desc;
-	u32 cnid;
+	__be32 cnid;
 	int i, off, key_off;
 
 	dprint(DBG_BNODE_MOD, "bnode: %d\n", node->this);
@@ -334,7 +334,7 @@ void hfs_bnode_unlink(struct hfs_bnode *node)
 {
 	struct hfs_btree *tree;
 	struct hfs_bnode *tmp;
-	u32 cnid;
+	__be32 cnid;
 
 	tree = node->tree;
 	if (node->prev) {
diff --git a/fs/hfsplus/brec.c b/fs/hfsplus/brec.c
index 8e1fc76ca..f5df0a3b2 100644
--- a/fs/hfsplus/brec.c
+++ b/fs/hfsplus/brec.c
@@ -14,7 +14,7 @@
 /* Get the length and offset of the given record in the given node */
 u16 hfs_brec_lenoff(struct hfs_bnode *node, u16 rec, u16 *off)
 {
-	u16 retval[2];
+	__be16 retval[2];
 	u16 dataoff;
 
 	dataoff = node->tree->node_size - (rec + 2) * 2;
@@ -53,7 +53,7 @@ int hfs_brec_insert(struct hfs_find_data *fd, void *entry, int entry_len)
 	int size, key_len, rec;
 	int data_off, end_off;
 	int idx_rec_off, data_rec_off, end_rec_off;
-	u32 cnid;
+	__be32 cnid;
 
 	tree = fd->tree;
 	if (!fd->bnode) {
@@ -387,7 +387,7 @@ skip:
 	node = parent;
 
 	if (new_node) {
-		u32 cnid;
+		__be32 cnid;
 
 		fd->bnode = hfs_bnode_find(tree, new_node->parent);
 		/* create index key and entry */
@@ -419,7 +419,7 @@ int hfs_btree_inc_height(struct hfs_btree *tree)
 	struct hfs_bnode *node, *new_node;
 	struct hfs_bnode_desc node_desc;
 	int key_size, rec;
-	u32 cnid;
+	__be32 cnid;
 
 	node = NULL;
 	if (tree->root) {
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
index b07136490..25119fd1a 100644
--- a/fs/hfsplus/btree.c
+++ b/fs/hfsplus/btree.c
@@ -142,7 +142,7 @@ static struct hfs_bnode *hfs_bmap_new_bmap(struct hfs_bnode *prev, u32 idx)
 	struct hfs_btree *tree = prev->tree;
 	struct hfs_bnode *node;
 	struct hfs_bnode_desc desc;
-	u32 cnid;
+	__be32 cnid;
 
 	node = hfs_bnode_create(tree, idx);
 	if (IS_ERR(node))
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index 9bb1055f1..b6c6cdb63 100644
--- a/fs/hfsplus/catalog.c
+++ b/fs/hfsplus/catalog.c
@@ -15,7 +15,7 @@
 
 int hfsplus_cat_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2)
 {
-	u32 k1p, k2p;
+	__be32 k1p, k2p;
 
 	k1p = k1->cat.parent;
 	k2p = k2->cat.parent;
@@ -34,8 +34,10 @@ void hfsplus_cat_build_key(hfsplus_btree_key *key, u32 parent,
 	if (str) {
 		hfsplus_asc2uni(&key->cat.name, str->name, str->len);
 		len = be16_to_cpu(key->cat.name.length);
-	} else
-		len = key->cat.name.length = 0;
+	} else {
+		key->cat.name.length = 0;
+		len = 0;
+	}
 	key->key_len = cpu_to_be16(6 + 2 * len);
 }
 
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
index 3cf272194..51d4b1255 100644
--- a/fs/hfsplus/extents.c
+++ b/fs/hfsplus/extents.c
@@ -19,8 +19,8 @@
 /* Compare two extents keys, returns 0 on same, pos/neg for difference */
 int hfsplus_ext_cmp_key(hfsplus_btree_key *k1, hfsplus_btree_key *k2)
 {
-	u32 k1id, k2id;
-	u32 k1s, k2s;
+	__be32 k1id, k2id;
+	__be32 k1s, k2s;
 
 	k1id = k1->ext.cnid;
 	k2id = k2->ext.cnid;
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 2e172a80f..57b6ec7bc 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -333,7 +333,7 @@ extern struct address_space_operations hfsplus_btree_aops;
 void hfsplus_inode_read_fork(struct inode *, struct hfsplus_fork_raw *);
 void hfsplus_inode_write_fork(struct inode *, struct hfsplus_fork_raw *);
 int hfsplus_cat_read_inode(struct inode *, struct hfs_find_data *);
-void hfsplus_cat_write_inode(struct inode *);
+int hfsplus_cat_write_inode(struct inode *);
 struct inode *hfsplus_new_inode(struct super_block *, int);
 void hfsplus_delete_inode(struct inode *);
 
@@ -344,7 +344,6 @@ int hfsplus_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
 /* options.c */
 int parse_options(char *, struct hfsplus_sb_info *);
 void fill_defaults(struct hfsplus_sb_info *);
-void fill_current(struct hfsplus_sb_info *, struct hfsplus_sb_info *);
 
 /* tables.c */
 extern u16 case_fold_table[];
diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h
index 696f06f8a..5bad37cfd 100644
--- a/fs/hfsplus/hfsplus_raw.h
+++ b/fs/hfsplus/hfsplus_raw.h
@@ -45,12 +45,12 @@
 
 /* Structures used on disk */
 
-typedef u32 hfsplus_cnid;
-typedef u16 hfsplus_unichr;
+typedef __be32 hfsplus_cnid;
+typedef __be16 hfsplus_unichr;
 
 /* A "string" as used in filenames, etc. */
 struct hfsplus_unistr {
-	u16 length;
+	__be16 length;
 	hfsplus_unichr unicode[255];
 } __packed;
 
@@ -58,12 +58,12 @@ struct hfsplus_unistr {
 
 /* POSIX permissions */
 struct hfsplus_perm {
-	u32 owner;
-	u32 group;
+	__be32 owner;
+	__be32 group;
 	u8  rootflags;
 	u8  userflags;
-	u16 mode;
-	u32 dev;
+	__be16 mode;
+	__be32 dev;
 } __packed;
 
 #define HFSPLUS_FLG_NODUMP	0x01
@@ -72,46 +72,46 @@ struct hfsplus_perm {
 
 /* A single contiguous area of a file */
 struct hfsplus_extent {
-	u32 start_block;
-	u32 block_count;
+	__be32 start_block;
+	__be32 block_count;
 } __packed;
 typedef struct hfsplus_extent hfsplus_extent_rec[8];
 
 /* Information for a "Fork" in a file */
 struct hfsplus_fork_raw {
-	u64 total_size;
-	u32 clump_size;
-	u32 total_blocks;
+	__be64 total_size;
+	__be32 clump_size;
+	__be32 total_blocks;
 	hfsplus_extent_rec extents;
 } __packed;
 
 /* HFS+ Volume Header */
 struct hfsplus_vh {
-	u16 signature;
-	u16 version;
-	u32 attributes;
-	u32 last_mount_vers;
+	__be16 signature;
+	__be16 version;
+	__be32 attributes;
+	__be32 last_mount_vers;
 	u32 reserved;
 
-	u32 create_date;
-	u32 modify_date;
-	u32 backup_date;
-	u32 checked_date;
+	__be32 create_date;
+	__be32 modify_date;
+	__be32 backup_date;
+	__be32 checked_date;
 
-	u32 file_count;
-	u32 folder_count;
+	__be32 file_count;
+	__be32 folder_count;
 
-	u32 blocksize;
-	u32 total_blocks;
-	u32 free_blocks;
+	__be32 blocksize;
+	__be32 total_blocks;
+	__be32 free_blocks;
 
-	u32 next_alloc;
-	u32 rsrc_clump_sz;
-	u32 data_clump_sz;
+	__be32 next_alloc;
+	__be32 rsrc_clump_sz;
+	__be32 data_clump_sz;
 	hfsplus_cnid next_cnid;
 
-	u32 write_count;
-	u64 encodings_bmp;
+	__be32 write_count;
+	__be64 encodings_bmp;
 
 	u8 finder_info[32];
 
@@ -131,11 +131,11 @@ struct hfsplus_vh {
 
 /* HFS+ BTree node descriptor */
 struct hfs_bnode_desc {
-	u32 next;
-	u32 prev;
+	__be32 next;
+	__be32 prev;
 	s8 type;
 	u8 height;
-	u16 num_recs;
+	__be16 num_recs;
 	u16 reserved;
 } __packed;
 
@@ -147,20 +147,20 @@ struct hfs_bnode_desc {
 
 /* HFS+ BTree header */
 struct hfs_btree_header_rec {
-	u16 depth;
-	u32 root;
-	u32 leaf_count;
-	u32 leaf_head;
-	u32 leaf_tail;
-	u16 node_size;
-	u16 max_key_len;
-	u32 node_count;
-	u32 free_nodes;
+	__be16 depth;
+	__be32 root;
+	__be32 leaf_count;
+	__be32 leaf_head;
+	__be32 leaf_tail;
+	__be16 node_size;
+	__be16 max_key_len;
+	__be32 node_count;
+	__be32 free_nodes;
 	u16 reserved1;
-	u32 clump_size;
+	__be32 clump_size;
 	u8 btree_type;
 	u8 reserved2;
-	u32 attributes;
+	__be32 attributes;
 	u32 reserved3[16];
 } __packed;
 
@@ -186,7 +186,7 @@ struct hfs_btree_header_rec {
 
 /* HFS+ catalog entry key */
 struct hfsplus_cat_key {
-	u16 key_len;
+	__be16 key_len;
 	hfsplus_cnid parent;
 	struct hfsplus_unistr name;
 } __packed;
@@ -194,83 +194,83 @@ struct hfsplus_cat_key {
 
 /* Structs from hfs.h */
 struct hfsp_point {
-	u16 v;
-	u16 h;
+	__be16 v;
+	__be16 h;
 } __packed;
 
 struct hfsp_rect {
-	u16 top;
-	u16 left;
-	u16 bottom;
-	u16 right;
+	__be16 top;
+	__be16 left;
+	__be16 bottom;
+	__be16 right;
 } __packed;
 
 
 /* HFS directory info (stolen from hfs.h */
 struct DInfo {
 	struct hfsp_rect frRect;
-	u16 frFlags;
+	__be16 frFlags;
 	struct hfsp_point frLocation;
-	u16 frView;
+	__be16 frView;
 } __packed;
 
 struct DXInfo {
 	struct hfsp_point frScroll;
-	u32 frOpenChain;
-	u16 frUnused;
-	u16 frComment;
-	u32 frPutAway;
+	__be32 frOpenChain;
+	__be16 frUnused;
+	__be16 frComment;
+	__be32 frPutAway;
 } __packed;
 
 /* HFS+ folder data (part of an hfsplus_cat_entry) */
 struct hfsplus_cat_folder {
-	s16 type;
-	u16 flags;
-	u32 valence;
+	__be16 type;
+	__be16 flags;
+	__be32 valence;
 	hfsplus_cnid id;
-	u32 create_date;
-	u32 content_mod_date;
-	u32 attribute_mod_date;
-	u32 access_date;
-	u32 backup_date;
+	__be32 create_date;
+	__be32 content_mod_date;
+	__be32 attribute_mod_date;
+	__be32 access_date;
+	__be32 backup_date;
 	struct hfsplus_perm permissions;
 	struct DInfo user_info;
 	struct DXInfo finder_info;
-	u32 text_encoding;
+	__be32 text_encoding;
 	u32 reserved;
 } __packed;
 
 /* HFS file info (stolen from hfs.h) */
 struct FInfo {
-	u32 fdType;
-	u32 fdCreator;
-	u16 fdFlags;
+	__be32 fdType;
+	__be32 fdCreator;
+	__be16 fdFlags;
 	struct hfsp_point fdLocation;
-	u16 fdFldr;
+	__be16 fdFldr;
 } __packed;
 
 struct FXInfo {
-	u16 fdIconID;
+	__be16 fdIconID;
 	u8 fdUnused[8];
-	u16 fdComment;
-	u32 fdPutAway;
+	__be16 fdComment;
+	__be32 fdPutAway;
 } __packed;
 
 /* HFS+ file data (part of a cat_entry) */
 struct hfsplus_cat_file {
-	s16 type;
-	u16 flags;
+	__be16 type;
+	__be16 flags;
 	u32 reserved1;
 	hfsplus_cnid id;
-	u32 create_date;
-	u32 content_mod_date;
-	u32 attribute_mod_date;
-	u32 access_date;
-	u32 backup_date;
+	__be32 create_date;
+	__be32 content_mod_date;
+	__be32 attribute_mod_date;
+	__be32 access_date;
+	__be32 backup_date;
 	struct hfsplus_perm permissions;
 	struct FInfo user_info;
 	struct FXInfo finder_info;
-	u32 text_encoding;
+	__be32 text_encoding;
 	u32 reserved2;
 
 	struct hfsplus_fork_raw data_fork;
@@ -283,7 +283,7 @@ struct hfsplus_cat_file {
 
 /* HFS+ catalog thread (part of a cat_entry) */
 struct hfsplus_cat_thread {
-	s16 type;
+	__be16 type;
 	s16 reserved;
 	hfsplus_cnid parentID;
 	struct hfsplus_unistr nodeName;
@@ -293,7 +293,7 @@ struct hfsplus_cat_thread {
 
 /* A data record in the catalog tree */
 typedef union {
-	s16 type;
+	__be16 type;
 	struct hfsplus_cat_folder folder;
 	struct hfsplus_cat_file file;
 	struct hfsplus_cat_thread thread;
@@ -307,18 +307,18 @@ typedef union {
 
 /* HFS+ extents tree key */
 struct hfsplus_ext_key {
-	u16 key_len;
+	__be16 key_len;
 	u8 fork_type;
 	u8 pad;
 	hfsplus_cnid cnid;
-	u32 start_block;
+	__be32 start_block;
 } __packed;
 
 #define HFSPLUS_EXT_KEYLEN 12
 
 /* HFS+ generic BTree key */
 typedef union {
-	u16 key_len;
+	__be16 key_len;
 	struct hfsplus_cat_key cat;
 	struct hfsplus_ext_key ext;
 } __packed hfsplus_btree_key;
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 5dc9bdbd1..eff1c987b 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -308,6 +308,7 @@ struct file_operations hfsplus_file_operations = {
 	.read		= generic_file_read,
 	.write		= generic_file_write,
 	.mmap		= generic_file_mmap,
+	.sendfile	= generic_file_sendfile,
 	.fsync		= file_fsync,
 	.open		= hfsplus_file_open,
 	.release	= hfsplus_file_release,
@@ -483,22 +484,22 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
 	return res;
 }
 
-void hfsplus_cat_write_inode(struct inode *inode)
+int hfsplus_cat_write_inode(struct inode *inode)
 {
 	struct hfs_find_data fd;
 	hfsplus_cat_entry entry;
 
 	if (HFSPLUS_IS_RSRC(inode)) {
 		mark_inode_dirty(HFSPLUS_I(inode).rsrc_inode);
-		return;
+		return 0;
 	}
 
 	if (!inode->i_nlink)
-		return;
+		return 0;
 
 	if (hfs_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd))
 		/* panic? */
-		return;
+		return -EIO;
 
 	if (hfsplus_find_cat(inode->i_sb, inode->i_ino, &fd))
 		/* panic? */
@@ -546,4 +547,5 @@ void hfsplus_cat_write_inode(struct inode *inode)
 	}
 out:
 	hfs_find_exit(&fd);
+	return 0;
 }
diff --git a/fs/hfsplus/part_tbl.c b/fs/hfsplus/part_tbl.c
index 3bc137f10..ae783066f 100644
--- a/fs/hfsplus/part_tbl.c
+++ b/fs/hfsplus/part_tbl.c
@@ -35,11 +35,11 @@
  * contiguous starting at block 1.
  */
 struct new_pmap {
-	u16	pmSig;		/* signature */
-	u16	reSigPad;	/* padding */
-	u32	pmMapBlkCnt;	/* partition blocks count */
-	u32	pmPyPartStart;	/* physical block start of partition */
-	u32	pmPartBlkCnt;	/* physical block count of partition */
+	__be16	pmSig;		/* signature */
+	__be16	reSigPad;	/* padding */
+	__be32	pmMapBlkCnt;	/* partition blocks count */
+	__be32	pmPyPartStart;	/* physical block start of partition */
+	__be32	pmPartBlkCnt;	/* physical block count of partition */
 	u8	pmPartName[32];	/* (null terminated?) string
 				   giving the name of this
 				   partition */
@@ -57,11 +57,11 @@ struct new_pmap {
  * one of these.
  */
 struct old_pmap {
-	u16		pdSig;	/* Signature bytes */
+	__be16		pdSig;	/* Signature bytes */
 	struct 	old_pmap_entry {
-		u32	pdStart;
-		u32	pdSize;
-		u32	pdFSID;
+		__be32	pdStart;
+		__be32	pdSize;
+		__be32	pdFSID;
 	}	pdEntry[42];
 } __packed;
 
@@ -75,7 +75,7 @@ int hfs_part_find(struct super_block *sb,
 		  sector_t *part_start, sector_t *part_size)
 {
 	struct buffer_head *bh;
-	u16 *data;
+	__be16 *data;
 	int i, size, res;
 
 	res = -ENOENT;
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 16e6dd8ca..4ff176a0b 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -94,20 +94,20 @@ static void hfsplus_read_inode(struct inode *inode)
 	make_bad_inode(inode);
 }
 
-void hfsplus_write_inode(struct inode *inode, int unused)
+int hfsplus_write_inode(struct inode *inode, int unused)
 {
 	struct hfsplus_vh *vhdr;
+	int ret = 0;
 
 	dprint(DBG_INODE, "hfsplus_write_inode: %lu\n", inode->i_ino);
 	hfsplus_ext_write_extent(inode);
 	if (inode->i_ino >= HFSPLUS_FIRSTUSER_CNID) {
-		hfsplus_cat_write_inode(inode);
-		return;
+		return hfsplus_cat_write_inode(inode);
 	}
 	vhdr = HFSPLUS_SB(inode->i_sb).s_vhdr;
 	switch (inode->i_ino) {
 	case HFSPLUS_ROOT_CNID:
-		hfsplus_cat_write_inode(inode);
+		ret = hfsplus_cat_write_inode(inode);
 		break;
 	case HFSPLUS_EXT_CNID:
 		if (vhdr->ext_file.total_size != cpu_to_be64(inode->i_size)) {
@@ -148,6 +148,7 @@ void hfsplus_write_inode(struct inode *inode, int unused)
 		hfs_btree_write(HFSPLUS_SB(inode->i_sb).attr_tree);
 		break;
 	}
+	return ret;
 }
 
 static void hfsplus_clear_inode(struct inode *inode)
diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c
index 777db1122..0c51d6338 100644
--- a/fs/hfsplus/wrapper.c
+++ b/fs/hfsplus/wrapper.c
@@ -30,22 +30,22 @@ static int hfsplus_read_mdb(void *bufptr, struct hfsplus_wd *wd)
 	u32 extent;
 	u16 attrib;
 
-	if (be16_to_cpu(*(u16 *)(bufptr + HFSP_WRAPOFF_EMBEDSIG)) != HFSPLUS_VOLHEAD_SIG)
+	if (be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_EMBEDSIG)) != HFSPLUS_VOLHEAD_SIG)
 		return 0;
 
-	attrib = be16_to_cpu(*(u16 *)(bufptr + HFSP_WRAPOFF_ATTRIB));
+	attrib = be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_ATTRIB));
 	if (!(attrib & HFSP_WRAP_ATTRIB_SLOCK) ||
 	   !(attrib & HFSP_WRAP_ATTRIB_SPARED))
 		return 0;
 
-	wd->ablk_size = be32_to_cpu(*(u32 *)(bufptr + HFSP_WRAPOFF_ABLKSIZE));
+	wd->ablk_size = be32_to_cpu(*(__be32 *)(bufptr + HFSP_WRAPOFF_ABLKSIZE));
 	if (wd->ablk_size < HFSPLUS_SECTOR_SIZE)
 		return 0;
 	if (wd->ablk_size % HFSPLUS_SECTOR_SIZE)
 		return 0;
-	wd->ablk_start = be16_to_cpu(*(u16 *)(bufptr + HFSP_WRAPOFF_ABLKSTART));
+	wd->ablk_start = be16_to_cpu(*(__be16 *)(bufptr + HFSP_WRAPOFF_ABLKSTART));
 
-	extent = be32_to_cpu(get_unaligned((u32 *)(bufptr + HFSP_WRAPOFF_EMBEDEXT)));
+	extent = be32_to_cpu(get_unaligned((__be32 *)(bufptr + HFSP_WRAPOFF_EMBEDEXT)));
 	wd->embed_start = (extent >> 16) & 0xFFFF;
 	wd->embed_count = extent & 0xFFFF;
 
diff --git a/fs/hostfs/Makefile b/fs/hostfs/Makefile
index 794292e0a..0f8e01cb3 100644
--- a/fs/hostfs/Makefile
+++ b/fs/hostfs/Makefile
@@ -1,4 +1,4 @@
-# 
+#
 # Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
 # Licensed under the GPL
 #
@@ -12,7 +12,7 @@ STAT64_INO_FIELD := $(shell grep -q __st_ino /usr/include/bits/stat.h && \
 
 hostfs-objs := hostfs_kern.o hostfs_user.o
 
-obj-y = 
+obj-y =
 obj-$(CONFIG_HOSTFS) += hostfs.o
 
 SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs))
diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h
index d1f6c339f..416761fce 100644
--- a/fs/hostfs/hostfs.h
+++ b/fs/hostfs/hostfs.h
@@ -3,7 +3,7 @@
 
 #include "os.h"
 
-/* These are exactly the same definitions as in fs.h, but the names are 
+/* These are exactly the same definitions as in fs.h, but the names are
  * changed so that this file can be included in both kernel and user files.
  */
 
@@ -31,16 +31,16 @@ struct hostfs_iattr {
 	unsigned int	ia_attr_flags;
 };
 
-extern int stat_file(const char *path, unsigned long long *inode_out, 
+extern int stat_file(const char *path, unsigned long long *inode_out,
 		     int *mode_out, int *nlink_out, int *uid_out, int *gid_out,
-		     unsigned long long *size_out, struct timespec *atime_out, 
-		     struct timespec *mtime_out, struct timespec *ctime_out, 
+		     unsigned long long *size_out, struct timespec *atime_out,
+		     struct timespec *mtime_out, struct timespec *ctime_out,
 		     int *blksize_out, unsigned long long *blocks_out);
 extern int access_file(char *path, int r, int w, int x);
 extern int open_file(char *path, int r, int w, int append);
-extern int file_type(const char *path, int *rdev);
+extern int file_type(const char *path, int *maj, int *min);
 extern void *open_dir(char *path, int *err_out);
-extern char *read_dir(void *stream, unsigned long long *pos, 
+extern char *read_dir(void *stream, unsigned long long *pos,
 		      unsigned long long *ino_out, int *len_out);
 extern void close_file(void *stream);
 extern void close_dir(void *stream);
@@ -48,7 +48,7 @@ extern int read_file(int fd, unsigned long long *offset, char *buf, int len);
 extern int write_file(int fd, unsigned long long *offset, const char *buf,
 		      int len);
 extern int lseek_file(int fd, long long offset, int whence);
-extern int file_create(char *name, int ur, int uw, int ux, int gr, 
+extern int file_create(char *name, int ur, int uw, int ux, int gr,
 		       int gw, int gx, int or, int ow, int ox);
 extern int set_attr(const char *file, struct hostfs_iattr *attrs);
 extern int make_symlink(const char *from, const char *to);
@@ -59,10 +59,10 @@ extern int do_mknod(const char *file, int mode, int dev);
 extern int link_file(const char *from, const char *to);
 extern int do_readlink(char *file, char *buf, int size);
 extern int rename_file(char *from, char *to);
-extern int do_statfs(char *root, long *bsize_out, long long *blocks_out, 
-		     long long *bfree_out, long long *bavail_out, 
-		     long long *files_out, long long *ffree_out, 
-		     void *fsid_out, int fsid_size, long *namelen_out, 
+extern int do_statfs(char *root, long *bsize_out, long long *blocks_out,
+		     long long *bfree_out, long long *bavail_out,
+		     long long *files_out, long long *ffree_out,
+		     void *fsid_out, int fsid_size, long *namelen_out,
 		     long *spare_out);
 
 #endif
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index ef5d5d1bf..7d42da0a3 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  *
@@ -18,6 +18,7 @@
 #include <linux/buffer_head.h>
 #include <linux/root_dev.h>
 #include <linux/statfs.h>
+#include <linux/kdev_t.h>
 #include <asm/uaccess.h>
 #include "hostfs.h"
 #include "kern_util.h"
@@ -59,6 +60,7 @@ static struct inode_operations hostfs_iops;
 static struct inode_operations hostfs_dir_iops;
 static struct address_space_operations hostfs_link_aops;
 
+#ifndef MODULE
 static int __init hostfs_args(char *options, int *add)
 {
 	char *ptr;
@@ -95,6 +97,7 @@ __uml_setup("hostfs=", hostfs_args,
 "    The only flag currently supported is 'append', which specifies that all\n"
 "    files opened by hostfs will be opened in append mode.\n\n"
 );
+#endif
 
 static char *dentry_name(struct dentry *dentry, int extra)
 {
@@ -108,7 +111,7 @@ static char *dentry_name(struct dentry *dentry, int extra)
 		len += parent->d_name.len + 1;
 		parent = parent->d_parent;
 	}
-	
+
 	root = HOSTFS_I(parent->d_inode)->host_filename;
 	len += strlen(root);
 	name = kmalloc(len + extra + 1, GFP_KERNEL);
@@ -119,7 +122,7 @@ static char *dentry_name(struct dentry *dentry, int extra)
 	while(parent->d_parent != parent){
 		len -= parent->d_name.len + 1;
 		name[len] = '/';
-		strncpy(&name[len + 1], parent->d_name.name, 
+		strncpy(&name[len + 1], parent->d_name.name,
 			parent->d_name.len);
 		parent = parent->d_parent;
 	}
@@ -147,10 +150,10 @@ static int read_name(struct inode *ino, char *name)
 	unsigned long long i_ino;
 	unsigned long long i_blocks;
 
-	err = stat_file(name, &i_ino, &i_mode, &i_nlink, &ino->i_uid, 
-			&ino->i_gid, &i_size, &ino->i_atime, &ino->i_mtime, 
+	err = stat_file(name, &i_ino, &i_mode, &i_nlink, &ino->i_uid,
+			&ino->i_gid, &i_size, &ino->i_atime, &ino->i_mtime,
 			&ino->i_ctime, &i_blksize, &i_blocks);
-	if(err) 
+	if(err)
 		return(err);
 
 	ino->i_ino = i_ino;
@@ -222,20 +225,20 @@ static int read_inode(struct inode *ino)
 	 */
 	if(list_empty(&ino->i_dentry))
 		goto out;
- 
+
 	err = -ENOMEM;
 	name = inode_name(ino, 0);
-	if(name == NULL) 
+	if(name == NULL)
 		goto out;
 
-	if(file_type(name, NULL) == OS_TYPE_SYMLINK){
+	if(file_type(name, NULL, NULL) == OS_TYPE_SYMLINK){
 		name = follow_link(name);
 		if(IS_ERR(name)){
 			err = PTR_ERR(name);
 			goto out;
 		}
 	}
-	
+
 	err = read_name(ino, name);
 	kfree(name);
  out:
@@ -257,7 +260,7 @@ int hostfs_statfs(struct super_block *sb, struct kstatfs *sf)
 
 	err = do_statfs(HOSTFS_I(sb->s_root->d_inode)->host_filename,
 			&sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files,
-			&f_ffree, &sf->f_fsid, sizeof(sf->f_fsid), 
+			&f_ffree, &sf->f_fsid, sizeof(sf->f_fsid),
 			&sf->f_namelen, sf->f_spare);
 	if(err) return(err);
 	sf->f_blocks = f_blocks;
@@ -274,7 +277,7 @@ static struct inode *hostfs_alloc_inode(struct super_block *sb)
 	struct hostfs_inode_info *hi;
 
 	hi = kmalloc(sizeof(*hi), GFP_KERNEL);
-	if(hi == NULL) 
+	if(hi == NULL)
 		return(NULL);
 
 	*hi = ((struct hostfs_inode_info) { .host_filename	= NULL,
@@ -284,13 +287,26 @@ static struct inode *hostfs_alloc_inode(struct super_block *sb)
 	return(&hi->vfs_inode);
 }
 
+static void hostfs_delete_inode(struct inode *inode)
+{
+	if(HOSTFS_I(inode)->fd != -1) {
+		close_file(&HOSTFS_I(inode)->fd);
+		HOSTFS_I(inode)->fd = -1;
+	}
+	clear_inode(inode);
+}
+
 static void hostfs_destroy_inode(struct inode *inode)
 {
-	if(HOSTFS_I(inode)->host_filename) 
+	if(HOSTFS_I(inode)->host_filename)
 		kfree(HOSTFS_I(inode)->host_filename);
 
-	if(HOSTFS_I(inode)->fd != -1) 
+	/*XXX: This should not happen, probably. The check is here for
+	 * additional safety.*/
+	if(HOSTFS_I(inode)->fd != -1) {
 		close_file(&HOSTFS_I(inode)->fd);
+		printk(KERN_DEBUG "Closing host fd in .destroy_inode\n");
+	}
 
 	kfree(HOSTFS_I(inode));
 }
@@ -300,8 +316,10 @@ static void hostfs_read_inode(struct inode *inode)
 	read_inode(inode);
 }
 
-static struct super_operations hostfs_sbops = { 
+static struct super_operations hostfs_sbops = {
 	.alloc_inode	= hostfs_alloc_inode,
+	.drop_inode	= generic_delete_inode,
+	.delete_inode   = hostfs_delete_inode,
 	.destroy_inode	= hostfs_destroy_inode,
 	.read_inode	= hostfs_read_inode,
 	.statfs		= hostfs_statfs,
@@ -321,7 +339,7 @@ int hostfs_readdir(struct file *file, void *ent, filldir_t filldir)
 	if(dir == NULL) return(-error);
 	next = file->f_pos;
 	while((name = read_dir(dir, &next, &ino, &len)) != NULL){
-		error = (*filldir)(ent, name, len, file->f_pos, 
+		error = (*filldir)(ent, name, len, file->f_pos,
 				   ino, DT_UNKNOWN);
 		if(error) break;
 		file->f_pos = next;
@@ -348,15 +366,15 @@ int hostfs_file_open(struct inode *ino, struct file *file)
 	}
 
 	HOSTFS_I(ino)->mode |= mode;
-	if(HOSTFS_I(ino)->mode & FMODE_READ) 
+	if(HOSTFS_I(ino)->mode & FMODE_READ)
 		r = 1;
-	if(HOSTFS_I(ino)->mode & FMODE_WRITE) 
+	if(HOSTFS_I(ino)->mode & FMODE_WRITE)
 		w = 1;
-	if(w) 
+	if(w)
 		r = 1;
 
 	name = dentry_name(file->f_dentry, 0);
-	if(name == NULL) 
+	if(name == NULL)
 		return(-ENOMEM);
 
 	fd = open_file(name, r, w, append);
@@ -413,14 +431,14 @@ int hostfs_writepage(struct page *page, struct writeback_control *wbc)
 		inode->i_size = base;
 
 	if (PageError(page))
-		ClearPageError(page);	
+		ClearPageError(page);
 	err = 0;
 
- out:	
+ out:
 	kunmap(page);
 
 	unlock_page(page);
-	return err; 
+	return err;
 }
 
 int hostfs_readpage(struct file *file, struct page *page)
@@ -447,7 +465,7 @@ int hostfs_readpage(struct file *file, struct page *page)
 	return(err);
 }
 
-int hostfs_prepare_write(struct file *file, struct page *page, 
+int hostfs_prepare_write(struct file *file, struct page *page,
 			 unsigned int from, unsigned int to)
 {
 	char *buffer;
@@ -466,7 +484,7 @@ int hostfs_prepare_write(struct file *file, struct page *page,
 		start += to;
 		err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer + to,
 				PAGE_CACHE_SIZE - to);
-		if(err < 0) goto out;		
+		if(err < 0) goto out;
 	}
 	err = 0;
  out:
@@ -485,7 +503,7 @@ int hostfs_commit_write(struct file *file, struct page *page, unsigned from,
 
 	start = (long long) (page->index << PAGE_CACHE_SHIFT) + from;
 	buffer = kmap(page);
-	err = write_file(FILE_HOSTFS_I(file)->fd, &start, buffer + from, 
+	err = write_file(FILE_HOSTFS_I(file)->fd, &start, buffer + from,
 			 to - from);
 	if(err > 0) err = 0;
 	if(!err && (start > inode->i_size))
@@ -506,13 +524,17 @@ static struct address_space_operations hostfs_aops = {
 static int init_inode(struct inode *inode, struct dentry *dentry)
 {
 	char *name;
-	int type, err = -ENOMEM, rdev;
+	int type, err = -ENOMEM;
+	int maj, min;
+	dev_t rdev = 0;
 
 	if(dentry){
 		name = dentry_name(dentry, 0);
 		if(name == NULL)
 			goto out;
-		type = file_type(name, &rdev);
+		type = file_type(name, &maj, &min);
+		/*Reencode maj and min with the kernel encoding.*/
+		rdev = MKDEV(maj, min);
 		kfree(name);
 	}
 	else type = OS_TYPE_DIR;
@@ -527,7 +549,7 @@ static int init_inode(struct inode *inode, struct dentry *dentry)
 	if(type == OS_TYPE_DIR) inode->i_fop = &hostfs_dir_fops;
 	else inode->i_fop = &hostfs_file_fops;
 
-	if(type == OS_TYPE_SYMLINK) 
+	if(type == OS_TYPE_SYMLINK)
 		inode->i_mapping->a_ops = &hostfs_link_aops;
 	else inode->i_mapping->a_ops = &hostfs_aops;
 
@@ -549,7 +571,7 @@ static int init_inode(struct inode *inode, struct dentry *dentry)
 	return(err);
 }
 
-int hostfs_create(struct inode *dir, struct dentry *dentry, int mode, 
+int hostfs_create(struct inode *dir, struct dentry *dentry, int mode,
                  struct nameidata *nd)
 {
 	struct inode *inode;
@@ -561,19 +583,19 @@ int hostfs_create(struct inode *dir, struct dentry *dentry, int mode,
 	if(inode == NULL) goto out;
 
 	error = init_inode(inode, dentry);
-	if(error) 
+	if(error)
 		goto out_put;
-	
+
 	error = -ENOMEM;
 	name = dentry_name(dentry, 0);
 	if(name == NULL)
 		goto out_put;
 
-	fd = file_create(name, 
-			 mode & S_IRUSR, mode & S_IWUSR, mode & S_IXUSR, 
-			 mode & S_IRGRP, mode & S_IWGRP, mode & S_IXGRP, 
+	fd = file_create(name,
+			 mode & S_IRUSR, mode & S_IWUSR, mode & S_IXUSR,
+			 mode & S_IRGRP, mode & S_IWGRP, mode & S_IXGRP,
 			 mode & S_IROTH, mode & S_IWOTH, mode & S_IXOTH);
-	if(fd < 0) 
+	if(fd < 0)
 		error = fd;
 	else error = read_name(inode, name);
 
@@ -592,7 +614,7 @@ int hostfs_create(struct inode *dir, struct dentry *dentry, int mode,
 	return(error);
 }
 
-struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry, 
+struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry,
                             struct nameidata *nd)
 {
 	struct inode *inode;
@@ -601,11 +623,11 @@ struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry,
 
 	err = -ENOMEM;
 	inode = iget(ino->i_sb, 0);
-	if(inode == NULL) 
+	if(inode == NULL)
 		goto out;
- 
+
 	err = init_inode(inode, dentry);
-	if(err) 
+	if(err)
 		goto out_put;
 
 	err = -ENOMEM;
@@ -651,7 +673,7 @@ int hostfs_link(struct dentry *to, struct inode *ino, struct dentry *from)
         char *from_name, *to_name;
         int err;
 
-        if((from_name = inode_dentry_name(ino, from)) == NULL) 
+        if((from_name = inode_dentry_name(ino, from)) == NULL)
                 return(-ENOMEM);
         to_name = dentry_name(to, 0);
 	if(to_name == NULL){
@@ -716,13 +738,13 @@ int hostfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
 	struct inode *inode;
 	char *name;
 	int err = -ENOMEM;
- 
+
 	inode = iget(dir->i_sb, 0);
-	if(inode == NULL) 
+	if(inode == NULL)
 		goto out;
 
 	err = init_inode(inode, dentry);
-	if(err) 
+	if(err)
 		goto out_put;
 
 	err = -ENOMEM;
@@ -795,8 +817,8 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
 	struct hostfs_iattr attrs;
 	char *name;
 	int err;
-	
-	if(append) 
+
+	if(append)
 		attr->ia_valid &= ~ATTR_SIZE;
 
 	attrs.ia_valid = 0;
@@ -805,14 +827,14 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
 		attrs.ia_mode = attr->ia_mode;
 	}
 	if(attr->ia_valid & ATTR_UID){
-		if((dentry->d_inode->i_sb->s_dev == ROOT_DEV) && 
+		if((dentry->d_inode->i_sb->s_dev == ROOT_DEV) &&
 		   (attr->ia_uid == 0))
 			attr->ia_uid = getuid();
 		attrs.ia_valid |= HOSTFS_ATTR_UID;
 		attrs.ia_uid = attr->ia_uid;
 	}
 	if(attr->ia_valid & ATTR_GID){
-		if((dentry->d_inode->i_sb->s_dev == ROOT_DEV) && 
+		if((dentry->d_inode->i_sb->s_dev == ROOT_DEV) &&
 		   (attr->ia_gid == 0))
 			attr->ia_gid = getuid();
 		attrs.ia_valid |= HOSTFS_ATTR_GID;
@@ -850,7 +872,7 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
 	return(inode_setattr(dentry->d_inode, attr));
 }
 
-int hostfs_getattr(struct vfsmount *mnt, struct dentry *dentry, 
+int hostfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
 	   struct kstat *stat)
 {
 	generic_fillattr(dentry->d_inode, stat);
@@ -928,12 +950,12 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
 	sb->s_magic = HOSTFS_SUPER_MAGIC;
 	sb->s_op = &hostfs_sbops;
 
-	if((data == NULL) || (*data == '\0')) 
+	if((data == NULL) || (*data == '\0'))
 		data = root_ino;
 
 	err = -ENOMEM;
 	name = kmalloc(strlen(data) + 1, GFP_KERNEL);
-	if(name == NULL) 
+	if(name == NULL)
 		goto out;
 
 	strcpy(name, data);
diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c
index c40626609..16974dc07 100644
--- a/fs/hostfs/hostfs_user.c
+++ b/fs/hostfs/hostfs_user.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
@@ -18,14 +18,14 @@
 #include "user.h"
 
 int stat_file(const char *path, unsigned long long *inode_out, int *mode_out,
-	      int *nlink_out, int *uid_out, int *gid_out, 
+	      int *nlink_out, int *uid_out, int *gid_out,
 	      unsigned long long *size_out, struct timespec *atime_out,
 	      struct timespec *mtime_out, struct timespec *ctime_out,
 	      int *blksize_out, unsigned long long *blocks_out)
 {
 	struct stat64 buf;
 
-	if(lstat64(path, &buf) < 0) 
+	if(lstat64(path, &buf) < 0)
 		return(-errno);
 
 	/* See the Makefile for why STAT64_INO_FIELD is passed in
@@ -54,14 +54,18 @@ int stat_file(const char *path, unsigned long long *inode_out, int *mode_out,
 	return(0);
 }
 
-int file_type(const char *path, int *rdev)
+int file_type(const char *path, int *maj, int *min)
 {
  	struct stat64 buf;
 
-	if(lstat64(path, &buf) < 0) 
+	if(lstat64(path, &buf) < 0)
 		return(-errno);
-	if(rdev != NULL) 
-		*rdev = buf.st_rdev;
+	/*We cannot pass rdev as is because glibc and the kernel disagree
+	 *about its definition.*/
+	if(maj != NULL)
+		*maj = major(buf.st_rdev);
+	if(min != NULL)
+		*min = minor(buf.st_rdev);
 
 	if(S_ISDIR(buf.st_mode)) return(OS_TYPE_DIR);
 	else if(S_ISLNK(buf.st_mode)) return(OS_TYPE_SYMLINK);
@@ -87,11 +91,11 @@ int open_file(char *path, int r, int w, int append)
 {
 	int mode = 0, fd;
 
-	if(r && !w) 
+	if(r && !w)
 		mode = O_RDONLY;
-	else if(!r && w) 
+	else if(!r && w)
 		mode = O_WRONLY;
-	else if(r && w) 
+	else if(r && w)
 		mode = O_RDWR;
 	else panic("Impossible mode in open_file");
 
@@ -112,7 +116,7 @@ void *open_dir(char *path, int *err_out)
 	return(dir);
 }
 
-char *read_dir(void *stream, unsigned long long *pos, 
+char *read_dir(void *stream, unsigned long long *pos,
 	       unsigned long long *ino_out, int *len_out)
 {
 	DIR *dir = stream;
@@ -166,7 +170,7 @@ void close_dir(void *stream)
 	closedir(stream);
 }
 
-int file_create(char *name, int ur, int uw, int ux, int gr, 
+int file_create(char *name, int ur, int uw, int ux, int gr,
 		int gw, int gx, int or, int ow, int ox)
 {
 	int mode, fd;
@@ -182,7 +186,7 @@ int file_create(char *name, int ur, int uw, int ux, int gr,
 	mode |= ow ? S_IWOTH : 0;
 	mode |= ox ? S_IXOTH : 0;
 	fd = open64(name, O_CREAT | O_RDWR, mode);
-	if(fd < 0) 
+	if(fd < 0)
 		return(-errno);
 	return(fd);
 }
@@ -214,30 +218,30 @@ int set_attr(const char *file, struct hostfs_iattr *attrs)
 		struct timespec ts;
 
 		if(attrs->ia_valid & HOSTFS_ATTR_ATIME_SET){
-			err = stat_file(file, NULL, NULL, NULL, NULL, NULL, 
+			err = stat_file(file, NULL, NULL, NULL, NULL, NULL,
 					NULL, NULL, &ts, NULL, NULL, NULL);
-			if(err != 0) 
+			if(err != 0)
 				return(err);
 			buf.actime = attrs->ia_atime.tv_sec;
 			buf.modtime = ts.tv_sec;
-			if(utime(file, &buf) != 0) 
+			if(utime(file, &buf) != 0)
 				return(-errno);
 		}
 		if(attrs->ia_valid & HOSTFS_ATTR_MTIME_SET){
-			err = stat_file(file, NULL, NULL, NULL, NULL, NULL, 
+			err = stat_file(file, NULL, NULL, NULL, NULL, NULL,
 					NULL, &ts, NULL, NULL, NULL, NULL);
-			if(err != 0) 
+			if(err != 0)
 				return(err);
 			buf.actime = ts.tv_sec;
 			buf.modtime = attrs->ia_mtime.tv_sec;
-			if(utime(file, &buf) != 0) 
+			if(utime(file, &buf) != 0)
 				return(-errno);
 		}
 	}
 	if(attrs->ia_valid & HOSTFS_ATTR_CTIME) ;
 	if(attrs->ia_valid & (HOSTFS_ATTR_ATIME | HOSTFS_ATTR_MTIME)){
-		err = stat_file(file, NULL, NULL, NULL, NULL, NULL, NULL, 
-				&attrs->ia_atime, &attrs->ia_mtime, NULL, 
+		err = stat_file(file, NULL, NULL, NULL, NULL, NULL, NULL,
+				&attrs->ia_atime, &attrs->ia_mtime, NULL,
 				NULL, NULL);
 		if(err != 0) return(err);
 	}
@@ -303,9 +307,9 @@ int do_readlink(char *file, char *buf, int size)
 	int n;
 
 	n = readlink(file, buf, size);
-	if(n < 0) 
+	if(n < 0)
 		return(-errno);
-	if(n < size) 
+	if(n < size)
 		buf[n] = '\0';
 	return(n);
 }
@@ -316,13 +320,13 @@ int rename_file(char *from, char *to)
 
 	err = rename(from, to);
 	if(err < 0) return(-errno);
-	return(0);	
+	return(0);
 }
 
-int do_statfs(char *root, long *bsize_out, long long *blocks_out, 
-	      long long *bfree_out, long long *bavail_out, 
+int do_statfs(char *root, long *bsize_out, long long *blocks_out,
+	      long long *bfree_out, long long *bavail_out,
 	      long long *files_out, long long *ffree_out,
-	      void *fsid_out, int fsid_size, long *namelen_out, 
+	      void *fsid_out, int fsid_size, long *namelen_out,
 	      long *spare_out)
 {
 	struct statfs64 buf;
@@ -336,8 +340,8 @@ int do_statfs(char *root, long *bsize_out, long long *blocks_out,
 	*bavail_out = buf.f_bavail;
 	*files_out = buf.f_files;
 	*ffree_out = buf.f_ffree;
-	memcpy(fsid_out, &buf.f_fsid, 
-	       sizeof(buf.f_fsid) > fsid_size ? fsid_size : 
+	memcpy(fsid_out, &buf.f_fsid,
+	       sizeof(buf.f_fsid) > fsid_size ? fsid_size :
 	       sizeof(buf.f_fsid));
 	*namelen_out = buf.f_namelen;
 	spare_out[0] = buf.f_spare[0];
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index 714f64447..34074b378 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -191,7 +191,7 @@ static int init_inodecache(void)
 {
 	hpfs_inode_cachep = kmem_cache_create("hpfs_inode_cache",
 					     sizeof(struct hpfs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (hpfs_inode_cachep == NULL)
 		return -ENOMEM;
diff --git a/fs/hppfs/Makefile b/fs/hppfs/Makefile
index e67f03848..a2d5c4d05 100644
--- a/fs/hppfs/Makefile
+++ b/fs/hppfs/Makefile
@@ -1,11 +1,11 @@
-# 
+#
 # Copyright (C) 2002, 2003 Jeff Dike (jdike@karaya.com)
 # Licensed under the GPL
 #
 
 hppfs-objs := hppfs_kern.o
 
-obj-y = 
+obj-y =
 obj-$(CONFIG_HPPFS) += hppfs.o
 
 clean:
diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c
index ebf08cb55..f8e0cbd0c 100644
--- a/fs/hppfs/hppfs_kern.c
+++ b/fs/hppfs/hppfs_kern.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
@@ -24,7 +24,7 @@ struct hppfs_data {
 };
 
 struct hppfs_private {
-	struct file proc_file;
+	struct file *proc_file;
 	int host_fd;
 	loff_t len;
 	struct hppfs_data *contents;
@@ -75,7 +75,7 @@ static char *dentry_name(struct dentry *dentry, int extra)
 		else len += parent->d_name.len + 1;
 		parent = parent->d_parent;
 	}
-	
+
 	root = "proc";
 	len += strlen(root);
 	name = kmalloc(len + extra + 1, GFP_KERNEL);
@@ -155,7 +155,7 @@ static void hppfs_read_inode(struct inode *ino)
 	ino->i_blocks = proc_ino->i_blocks;
 }
 
-static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, 
+static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
                                   struct nameidata *nd)
 {
 	struct dentry *proc_dentry, *new, *parent;
@@ -178,7 +178,7 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
 			up(&parent->d_inode->i_sem);
 			goto out;
 		}
-		new = (*parent->d_inode->i_op->lookup)(parent->d_inode, 
+		new = (*parent->d_inode->i_op->lookup)(parent->d_inode,
 						       proc_dentry, NULL);
 		if(new){
 			dput(proc_dentry);
@@ -191,13 +191,13 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
 		return(proc_dentry);
 
 	inode = iget(ino->i_sb, 0);
-	if(inode == NULL) 
+	if(inode == NULL)
 		goto out_dput;
 
 	err = init_inode(inode, proc_dentry);
-	if(err) 
+	if(err)
 		goto out_put;
-	
+
 	hppfs_read_inode(inode);
 
  	d_add(dentry, inode);
@@ -215,7 +215,7 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
 static struct inode_operations hppfs_file_iops = {
 };
 
-static ssize_t read_proc(struct file *file, char *buf, ssize_t count, 
+static ssize_t read_proc(struct file *file, char *buf, ssize_t count,
 			 loff_t *ppos, int is_user)
 {
 	ssize_t (*read)(struct file *, char *, size_t, loff_t *);
@@ -225,7 +225,7 @@ static ssize_t read_proc(struct file *file, char *buf, ssize_t count,
 
 	if(!is_user)
 		set_fs(KERNEL_DS);
-		
+
 	n = (*read)(file, buf, count, &file->f_pos);
 
 	if(!is_user)
@@ -273,7 +273,7 @@ static ssize_t hppfs_read_file(int fd, char *buf, ssize_t count)
 	return(n);
 }
 
-static ssize_t hppfs_read(struct file *file, char *buf, size_t count, 
+static ssize_t hppfs_read(struct file *file, char *buf, size_t count,
 			  loff_t *ppos)
 {
 	struct hppfs_private *hppfs = file->private_data;
@@ -307,16 +307,16 @@ static ssize_t hppfs_read(struct file *file, char *buf, size_t count,
 		if(count > 0)
 			*ppos += count;
 	}
-	else count = read_proc(&hppfs->proc_file, buf, count, ppos, 1);
+	else count = read_proc(hppfs->proc_file, buf, count, ppos, 1);
 
 	return(count);
 }
 
-static ssize_t hppfs_write(struct file *file, const char *buf, size_t len, 
+static ssize_t hppfs_write(struct file *file, const char *buf, size_t len,
 			   loff_t *ppos)
 {
 	struct hppfs_private *data = file->private_data;
-	struct file *proc_file = &data->proc_file;
+	struct file *proc_file = data->proc_file;
 	ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
 	int err;
 
@@ -361,9 +361,9 @@ static void free_contents(struct hppfs_data *head)
 	kfree(head);
 }
 
-static struct hppfs_data *hppfs_get_data(int fd, int filter, 
-					 struct file *proc_file, 
-					 struct file *hppfs_file, 
+static struct hppfs_data *hppfs_get_data(int fd, int filter,
+					 struct file *proc_file,
+					 struct file *hppfs_file,
 					 loff_t *size_out)
 {
 	struct hppfs_data *data, *new, *head;
@@ -414,7 +414,7 @@ static struct hppfs_data *hppfs_get_data(int fd, int filter,
 			err = -ENOMEM;
 			goto failed_free;
 		}
-	
+
 		INIT_LIST_HEAD(&new->list);
 		list_add(&new->list, &data->list);
 		data = new;
@@ -423,7 +423,7 @@ static struct hppfs_data *hppfs_get_data(int fd, int filter,
 
  failed_free:
 	free_contents(head);
- failed:		
+ failed:
 	return(ERR_PTR(err));
 }
 
@@ -471,15 +471,16 @@ static int hppfs_open(struct inode *inode, struct file *file)
 	proc_dentry = HPPFS_I(inode)->proc_dentry;
 
 	/* XXX This isn't closed anywhere */
-	err = open_private_file(&data->proc_file, proc_dentry, 
-				file_mode(file->f_mode));
-	if(err)
+	data->proc_file = dentry_open(dget(proc_dentry), NULL,
+				      file_mode(file->f_mode));
+	err = PTR_ERR(data->proc_file);
+	if(IS_ERR(data->proc_file))
 		goto out_free1;
 
 	type = os_file_type(host_file);
 	if(type == OS_TYPE_FILE){
 		fd = os_open_file(host_file, of_read(OPENFLAGS()), 0);
-		if(fd >= 0) 
+		if(fd >= 0)
 			data->host_fd = fd;
 		else printk("hppfs_open : failed to open '%s', errno = %d\n",
 			    host_file, -fd);
@@ -489,8 +490,8 @@ static int hppfs_open(struct inode *inode, struct file *file)
 	else if(type == OS_TYPE_DIR){
 		fd = open_host_sock(host_file, &filter);
 		if(fd > 0){
-			data->contents = hppfs_get_data(fd, filter, 
-							&data->proc_file, 
+			data->contents = hppfs_get_data(fd, filter,
+							&data->proc_file,
 							file, &data->len);
 			if(!IS_ERR(data->contents))
 				data->host_fd = fd;
@@ -524,9 +525,10 @@ static int hppfs_dir_open(struct inode *inode, struct file *file)
 		goto out;
 
 	proc_dentry = HPPFS_I(inode)->proc_dentry;
-	err = open_private_file(&data->proc_file, proc_dentry, 
-				file_mode(file->f_mode));
-	if(err)
+	data->proc_file = dentry_open(dget(proc_dentry), NULL,
+				      file_mode(file->f_mode));
+	err = PTR_ERR(data->proc_file);
+	if(IS_ERR(data->proc_file))
 		goto out_free;
 
 	file->private_data = data;
@@ -569,7 +571,7 @@ struct hppfs_dirent {
 	struct dentry *dentry;
 };
 
-static int hppfs_filldir(void *d, const char *name, int size, 
+static int hppfs_filldir(void *d, const char *name, int size,
 			 loff_t offset, ino_t inode, unsigned int type)
 {
 	struct hppfs_dirent *dirent = d;
@@ -577,7 +579,7 @@ static int hppfs_filldir(void *d, const char *name, int size,
 	if(file_removed(dirent->dentry, name))
 		return(0);
 
-	return((*dirent->filldir)(dirent->vfs_dirent, name, size, offset, 
+	return((*dirent->filldir)(dirent->vfs_dirent, name, size, offset,
 				  inode, type));
 }
 
@@ -629,7 +631,7 @@ static struct inode *hppfs_alloc_inode(struct super_block *sb)
 	struct hppfs_inode_info *hi;
 
 	hi = kmalloc(sizeof(*hi), GFP_KERNEL);
-	if(hi == NULL) 
+	if(hi == NULL)
 		return(NULL);
 
 	*hi = ((struct hppfs_inode_info) { .proc_dentry	= NULL });
@@ -647,7 +649,7 @@ static void hppfs_destroy_inode(struct inode *inode)
 	kfree(HPPFS_I(inode));
 }
 
-static struct super_operations hppfs_sbops = { 
+static struct super_operations hppfs_sbops = {
 	.alloc_inode	= hppfs_alloc_inode,
 	.destroy_inode	= hppfs_destroy_inode,
 	.read_inode	= hppfs_read_inode,
@@ -657,41 +659,43 @@ static struct super_operations hppfs_sbops = {
 
 static int hppfs_readlink(struct dentry *dentry, char *buffer, int buflen)
 {
-	struct file proc_file;
+	struct file *proc_file;
 	struct dentry *proc_dentry;
 	int (*readlink)(struct dentry *, char *, int);
 	int err, n;
 
 	proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
-	err = open_private_file(&proc_file, proc_dentry, O_RDONLY);
-	if(err) 
+	proc_file = dentry_open(dget(proc_dentry), NULL, O_RDONLY);
+	err = PTR_ERR(proc_dentry);
+	if(IS_ERR(proc_dentry))
 		return(err);
 
 	readlink = proc_dentry->d_inode->i_op->readlink;
 	n = (*readlink)(proc_dentry, buffer, buflen);
 
-	close_private_file(&proc_file);
-	
+	fput(proc_file);
+
 	return(n);
 }
 
 static int hppfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-	struct file proc_file;
+	struct file *proc_file;
 	struct dentry *proc_dentry;
 	int (*follow_link)(struct dentry *, struct nameidata *);
 	int err, n;
 
 	proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
-	err = open_private_file(&proc_file, proc_dentry, O_RDONLY);
-	if(err) 
+	proc_file = dentry_open(dget(proc_dentry), NULL, O_RDONLY);
+	err = PTR_ERR(proc_dentry);
+	if(IS_ERR(proc_dentry))
 		return(err);
 
 	follow_link = proc_dentry->d_inode->i_op->follow_link;
 	n = (*follow_link)(proc_dentry, nd);
 
-	close_private_file(&proc_file);
-	
+	fput(proc_file);
+
 	return(n);
 }
 
@@ -733,7 +737,7 @@ static int hppfs_fill_super(struct super_block *sb, void *d, int silent)
 
 	err = -ENOENT;
 	procfs = get_fs_type("proc");
-	if(procfs == NULL) 
+	if(procfs == NULL)
 		goto out;
 
 	if(list_empty(&procfs->fs_supers))
@@ -741,7 +745,7 @@ static int hppfs_fill_super(struct super_block *sb, void *d, int silent)
 
 	proc_sb = list_entry(procfs->fs_supers.next, struct super_block,
 			     s_instances);
-	
+
 	sb->s_blocksize = 1024;
 	sb->s_blocksize_bits = 10;
 	sb->s_magic = HPPFS_SUPER_MAGIC;
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 4ec428315..6e7aeff35 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -52,6 +52,9 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
 	loff_t len, vma_len;
 	int ret;
 
+	if ((vma->vm_flags & (VM_MAYSHARE | VM_WRITE)) == VM_WRITE)
+		return -EINVAL;
+
 	if (vma->vm_pgoff & (HPAGE_SIZE / PAGE_SIZE - 1))
 		return -EINVAL;
 
@@ -70,10 +73,19 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
 	file_accessed(file);
 	vma->vm_flags |= VM_HUGETLB | VM_RESERVED;
 	vma->vm_ops = &hugetlb_vm_ops;
+
+	ret = -ENOMEM;
+	len = vma_len + ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
+	if (!(vma->vm_flags & VM_WRITE) && len > inode->i_size)
+		goto out;
+
 	ret = hugetlb_prefault(mapping, vma);
-	len = vma_len +	((loff_t)vma->vm_pgoff << PAGE_SHIFT);
-	if (ret == 0 && inode->i_size < len)
+	if (ret)
+		goto out;
+
+	if (inode->i_size < len)
 		inode->i_size = len;
+out:
 	up(&inode->i_sem);
 
 	return ret;
@@ -272,11 +284,10 @@ static void hugetlbfs_drop_inode(struct inode *inode)
 static inline void
 hugetlb_vmtruncate_list(struct prio_tree_root *root, unsigned long h_pgoff)
 {
-	struct vm_area_struct *vma = NULL;
+	struct vm_area_struct *vma;
 	struct prio_tree_iter iter;
 
-	while ((vma = vma_prio_tree_next(vma, root, &iter,
-					h_pgoff, ULONG_MAX)) != NULL) {
+	vma_prio_tree_foreach(vma, &iter, root, h_pgoff, ULONG_MAX) {
 		unsigned long h_vm_pgoff;
 		unsigned long v_length;
 		unsigned long v_offset;
@@ -640,6 +651,7 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent)
 	sbinfo->free_blocks = config.nr_blocks;
 	sbinfo->max_inodes = config.nr_inodes;
 	sbinfo->free_inodes = config.nr_inodes;
+	sb->s_maxbytes = MAX_LFS_FILESIZE;
 	sb->s_blocksize = HPAGE_SIZE;
 	sb->s_blocksize_bits = HPAGE_SHIFT;
 	sb->s_magic = HUGETLBFS_MAGIC;
@@ -721,12 +733,13 @@ static unsigned long hugetlbfs_counter(void)
 static int can_do_hugetlb_shm(void)
 {
 	return likely(capable(CAP_IPC_LOCK) ||
-			in_group_p(sysctl_hugetlb_shm_group));
+			in_group_p(sysctl_hugetlb_shm_group) ||
+			can_do_mlock());
 }
 
 struct file *hugetlb_zero_setup(size_t size)
 {
-	int error;
+	int error = -ENOMEM;
 	struct file *file;
 	struct inode *inode;
 	struct dentry *dentry, *root;
@@ -739,6 +752,9 @@ struct file *hugetlb_zero_setup(size_t size)
 	if (!is_hugepage_mem_enough(size))
 		return ERR_PTR(-ENOMEM);
 
+	if (!user_shm_lock(size, current->user))
+		return ERR_PTR(-ENOMEM);
+
 	root = hugetlbfs_vfsmount->mnt_root;
 	snprintf(buf, 16, "%lu", hugetlbfs_counter());
 	quick_string.name = buf;
@@ -746,7 +762,7 @@ struct file *hugetlb_zero_setup(size_t size)
 	quick_string.hash = 0;
 	dentry = d_alloc(root, &quick_string);
 	if (!dentry)
-		return ERR_PTR(-ENOMEM);
+		goto out_shm_unlock;
 
 	error = -ENFILE;
 	file = get_empty_filp();
@@ -773,6 +789,8 @@ out_file:
 	put_filp(file);
 out_dentry:
 	dput(dentry);
+out_shm_unlock:
+	user_shm_unlock(size, current->user);
 	return ERR_PTR(error);
 }
 
@@ -783,8 +801,7 @@ static int __init init_hugetlbfs_fs(void)
 
 	hugetlbfs_inode_cachep = kmem_cache_create("hugetlbfs_inode_cache",
 					sizeof(struct hugetlbfs_inode_info),
-					0, SLAB_RECLAIM_ACCOUNT,
-					init_once, NULL);
+					0, 0, init_once, NULL);
 	if (hugetlbfs_inode_cachep == NULL)
 		return -ENOMEM;
 
diff --git a/fs/inode.c b/fs/inode.c
index 6a6f06f08..0134b6842 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -248,6 +248,7 @@ void __iget(struct inode * inode)
  */
 void clear_inode(struct inode *inode)
 {
+	might_sleep();
 	invalidate_inode_buffers(inode);
        
 	if (inode->i_data.nrpages)
@@ -490,8 +491,9 @@ static int shrink_icache_memory(int nr, unsigned int gfp_mask)
 		 * and we don't want to recurse into the FS that called us
 		 * in clear_inode() and friends..
 	 	 */
-		if (gfp_mask & __GFP_FS)
-			prune_icache(nr);
+		if (!(gfp_mask & __GFP_FS))
+			return -1;
+		prune_icache(nr);
 	}
 	return (inodes_stat.nr_unused / 100) * sysctl_vfs_cache_pressure;
 }
@@ -1377,8 +1379,7 @@ void __init inode_init(unsigned long mempages)
 
 	/* inode slab cache */
 	inode_cachep = kmem_cache_create("inode_cache", sizeof(struct inode),
-				0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, init_once,
-				NULL);
+				0, SLAB_PANIC, init_once, NULL);
 	set_shrinker(DEFAULT_SEEKS, shrink_icache_memory);
 }
 
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 64ffa90a2..c4d38f62f 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -18,7 +18,7 @@
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 
-#ifdef	CONFIG_VSERVER_LEGACY		
+#ifdef	CONFIG_VSERVER_LEGACY
 extern int vx_proc_ioctl(struct inode *, struct file *,
 	unsigned int, unsigned long);
 #endif
@@ -130,7 +130,7 @@ asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 			else
 				error = -ENOTTY;
 			break;
-#ifdef	CONFIG_VSERVER_LEGACY		
+#ifdef	CONFIG_VSERVER_LEGACY
 #ifndef CONFIG_INOXID_NONE
 		case FIOC_GETXID: {
 			struct inode *inode = filp->f_dentry->d_inode;
@@ -162,7 +162,7 @@ asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 			inode->i_xid = (xid & 0xFFFF);
 			inode->i_ctime = CURRENT_TIME;
 			mark_inode_dirty(inode);
-			break;	
+			break;
 		}
 #endif
 		case FIOC_GETXFLG:
diff --git a/fs/isofs/compress.c b/fs/isofs/compress.c
index 877b4e47d..0b5a3a0ed 100644
--- a/fs/isofs/compress.c
+++ b/fs/isofs/compress.c
@@ -132,7 +132,7 @@ static int zisofs_readpage(struct file *file, struct page *page)
 			brelse(ptrbh[1]);
 		goto eio;
 	}
-	cstart = le32_to_cpu(*(u32 *)(bh->b_data + (blockptr & bufmask)));
+	cstart = le32_to_cpu(*(__le32 *)(bh->b_data + (blockptr & bufmask)));
 
 	if ( indexblocks == 2 ) {
 		/* We just crossed a block boundary.  Switch to the next block */
@@ -144,7 +144,7 @@ static int zisofs_readpage(struct file *file, struct page *page)
 			goto eio;
 		}
 	}
-	cend = le32_to_cpu(*(u32 *)(bh->b_data + (blockendptr & bufmask)));
+	cend = le32_to_cpu(*(__le32 *)(bh->b_data + (blockendptr & bufmask)));
 	brelse(bh);
 
 	csize = cend-cstart;
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 491dcde30..0ee7beb9d 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -108,7 +108,7 @@ static int init_inodecache(void)
 {
 	isofs_inode_cachep = kmem_cache_create("isofs_inode_cache",
 					     sizeof(struct iso_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (isofs_inode_cachep == NULL)
 		return -ENOMEM;
@@ -715,6 +715,7 @@ root_found:
 	  }
 
 	s->s_magic = ISOFS_SUPER_MAGIC;
+	s->s_maxbytes = 0xffffffff; /* We can handle files up to 4 GB */
 
 	/* The CDROM is read-only, has no nodes (devices) on it, and since
 	   all of the files appear to be owned by root, we really do not want
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index c09d4bd4b..19d999fd4 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -62,7 +62,7 @@
 }                                     
 
 #define MAYBE_CONTINUE(LABEL,DEV) \
-  {if (buffer) kfree(buffer); \
+  {if (buffer) { kfree(buffer); buffer = NULL; } \
   if (cont_extent){ \
     int block, offset, offset1; \
     struct buffer_head * pbh; \
@@ -153,14 +153,17 @@ int get_rock_ridge_filename(struct iso_directory_record * de,
     }
   }
   MAYBE_CONTINUE(repeat,inode);
+  if (buffer) kfree(buffer);
   return retnamlen; /* If 0, this file did not have a NM field */
  out:
   if(buffer) kfree(buffer);
   return 0;
 }
 
-int parse_rock_ridge_inode_internal(struct iso_directory_record * de,
-			            struct inode * inode,int regard_xa){
+static int
+parse_rock_ridge_inode_internal(struct iso_directory_record *de,
+				struct inode *inode, int regard_xa)
+{
   int len;
   unsigned char * chr;
   int symlink_len = 0;
@@ -174,7 +177,7 @@ int parse_rock_ridge_inode_internal(struct iso_directory_record * de,
      chr+=14;
      len-=14;
      if (len<0) len=0;
-   };
+   }
    
  repeat:
   {
@@ -351,7 +354,6 @@ int parse_rock_ridge_inode_internal(struct iso_directory_record * de,
     }
   }
   MAYBE_CONTINUE(repeat,inode);
-  return 0;
  out:
   if(buffer) kfree(buffer);
   return 0;
@@ -435,9 +437,9 @@ int parse_rock_ridge_inode(struct iso_directory_record * de,
        &&(ISOFS_SB(inode->i_sb)->s_rock==2))
      {
 	result=parse_rock_ridge_inode_internal(de,inode,14);
-     };
+     }
    return result;
-};
+}
 
 /* readpage() for symlinks: reads symlink contents into the page and either
    makes it uptodate and returns 0 or returns error (-EIO) */
@@ -515,6 +517,8 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
 		}
 	}
 	MAYBE_CONTINUE(repeat, inode);
+	if (buffer)
+		kfree(buffer);
 
 	if (rpnt == link)
 		goto fail;
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index a540c7f03..f8a1dea56 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -405,9 +405,9 @@ write_out_data:
 			jbd_debug(4, "JBD: got buffer %llu (%p)\n",
 				(unsigned long long)bh->b_blocknr, bh->b_data);
 			header = (journal_header_t *)&bh->b_data[0];
-			header->h_magic     = htonl(JFS_MAGIC_NUMBER);
-			header->h_blocktype = htonl(JFS_DESCRIPTOR_BLOCK);
-			header->h_sequence  = htonl(commit_transaction->t_tid);
+			header->h_magic     = cpu_to_be32(JFS_MAGIC_NUMBER);
+			header->h_blocktype = cpu_to_be32(JFS_DESCRIPTOR_BLOCK);
+			header->h_sequence  = cpu_to_be32(commit_transaction->t_tid);
 
 			tagp = &bh->b_data[sizeof(journal_header_t)];
 			space_left = bh->b_size - sizeof(journal_header_t);
@@ -473,8 +473,8 @@ write_out_data:
 			tag_flag |= JFS_FLAG_SAME_UUID;
 
 		tag = (journal_block_tag_t *) tagp;
-		tag->t_blocknr = htonl(jh2bh(jh)->b_blocknr);
-		tag->t_flags = htonl(tag_flag);
+		tag->t_blocknr = cpu_to_be32(jh2bh(jh)->b_blocknr);
+		tag->t_flags = cpu_to_be32(tag_flag);
 		tagp += sizeof(journal_block_tag_t);
 		space_left -= sizeof(journal_block_tag_t);
 
@@ -498,7 +498,7 @@ write_out_data:
                            submitting the IOs.  "tag" still points to
                            the last tag we set up. */
 
-			tag->t_flags |= htonl(JFS_FLAG_LAST_TAG);
+			tag->t_flags |= cpu_to_be32(JFS_FLAG_LAST_TAG);
 
 start_journal_io:
 			for (i = 0; i < bufs; i++) {
@@ -631,18 +631,46 @@ wait_for_iobuf:
 	for (i = 0; i < jh2bh(descriptor)->b_size; i += 512) {
 		journal_header_t *tmp =
 			(journal_header_t*)jh2bh(descriptor)->b_data;
-		tmp->h_magic = htonl(JFS_MAGIC_NUMBER);
-		tmp->h_blocktype = htonl(JFS_COMMIT_BLOCK);
-		tmp->h_sequence = htonl(commit_transaction->t_tid);
+		tmp->h_magic = cpu_to_be32(JFS_MAGIC_NUMBER);
+		tmp->h_blocktype = cpu_to_be32(JFS_COMMIT_BLOCK);
+		tmp->h_sequence = cpu_to_be32(commit_transaction->t_tid);
 	}
 
 	JBUFFER_TRACE(descriptor, "write commit block");
 	{
 		struct buffer_head *bh = jh2bh(descriptor);
+		int ret;
+		int barrier_done = 0;
 
 		set_buffer_dirty(bh);
-		sync_dirty_buffer(bh);
-		if (unlikely(!buffer_uptodate(bh)))
+		if (journal->j_flags & JFS_BARRIER) {
+			set_buffer_ordered(bh);
+			barrier_done = 1;
+		}
+		ret = sync_dirty_buffer(bh);
+		/* is it possible for another commit to fail at roughly
+		 * the same time as this one?  If so, we don't want to
+		 * trust the barrier flag in the super, but instead want
+		 * to remember if we sent a barrier request
+		 */
+		if (ret == -EOPNOTSUPP && barrier_done) {
+			char b[BDEVNAME_SIZE];
+
+			printk(KERN_WARNING
+				"JBD: barrier-based sync failed on %s - "
+				"disabling barriers\n",
+				bdevname(journal->j_dev, b));
+			spin_lock(&journal->j_state_lock);
+			journal->j_flags &= ~JFS_BARRIER;
+			spin_unlock(&journal->j_state_lock);
+
+			/* And try again, without the barrier */
+			clear_buffer_ordered(bh);
+			set_buffer_uptodate(bh);
+			set_buffer_dirty(bh);
+			ret = sync_dirty_buffer(bh);
+		}
+		if (unlikely(ret == -EIO))
 			err = -EIO;
 		put_bh(bh);		/* One for getblk() */
 		journal_put_journal_head(descriptor);
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 1cf23ff17..cb9d794cc 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -34,6 +34,7 @@
 #include <linux/suspend.h>
 #include <linux/pagemap.h>
 #include <asm/uaccess.h>
+#include <asm/page.h>
 #include <linux/proc_fs.h>
 
 EXPORT_SYMBOL(journal_start);
@@ -325,8 +326,8 @@ repeat:
 	/*
 	 * Check for escaping
 	 */
-	if (*((unsigned int *)(mapped_data + new_offset)) ==
-				htonl(JFS_MAGIC_NUMBER)) {
+	if (*((__be32 *)(mapped_data + new_offset)) ==
+				cpu_to_be32(JFS_MAGIC_NUMBER)) {
 		need_copy_out = 1;
 		do_escape = 1;
 	}
@@ -808,8 +809,8 @@ static int journal_reset(journal_t *journal)
 	journal_superblock_t *sb = journal->j_superblock;
 	unsigned int first, last;
 
-	first = ntohl(sb->s_first);
-	last = ntohl(sb->s_maxlen);
+	first = be32_to_cpu(sb->s_first);
+	last = be32_to_cpu(sb->s_maxlen);
 
 	journal->j_first = first;
 	journal->j_last = last;
@@ -886,12 +887,12 @@ int journal_create(journal_t *journal)
 	/* OK, fill in the initial static fields in the new superblock */
 	sb = journal->j_superblock;
 
-	sb->s_header.h_magic	 = htonl(JFS_MAGIC_NUMBER);
-	sb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
+	sb->s_header.h_magic	 = cpu_to_be32(JFS_MAGIC_NUMBER);
+	sb->s_header.h_blocktype = cpu_to_be32(JFS_SUPERBLOCK_V2);
 
-	sb->s_blocksize	= htonl(journal->j_blocksize);
-	sb->s_maxlen	= htonl(journal->j_maxlen);
-	sb->s_first	= htonl(1);
+	sb->s_blocksize	= cpu_to_be32(journal->j_blocksize);
+	sb->s_maxlen	= cpu_to_be32(journal->j_maxlen);
+	sb->s_first	= cpu_to_be32(1);
 
 	journal->j_transaction_sequence = 1;
 
@@ -934,9 +935,9 @@ void journal_update_superblock(journal_t *journal, int wait)
 	jbd_debug(1,"JBD: updating superblock (start %ld, seq %d, errno %d)\n",
 		  journal->j_tail, journal->j_tail_sequence, journal->j_errno);
 
-	sb->s_sequence = htonl(journal->j_tail_sequence);
-	sb->s_start    = htonl(journal->j_tail);
-	sb->s_errno    = htonl(journal->j_errno);
+	sb->s_sequence = cpu_to_be32(journal->j_tail_sequence);
+	sb->s_start    = cpu_to_be32(journal->j_tail);
+	sb->s_errno    = cpu_to_be32(journal->j_errno);
 	spin_unlock(&journal->j_state_lock);
 
 	BUFFER_TRACE(bh, "marking dirty");
@@ -987,13 +988,13 @@ static int journal_get_superblock(journal_t *journal)
 
 	err = -EINVAL;
 
-	if (sb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
-	    sb->s_blocksize != htonl(journal->j_blocksize)) {
+	if (sb->s_header.h_magic != cpu_to_be32(JFS_MAGIC_NUMBER) ||
+	    sb->s_blocksize != cpu_to_be32(journal->j_blocksize)) {
 		printk(KERN_WARNING "JBD: no valid journal superblock found\n");
 		goto out;
 	}
 
-	switch(ntohl(sb->s_header.h_blocktype)) {
+	switch(be32_to_cpu(sb->s_header.h_blocktype)) {
 	case JFS_SUPERBLOCK_V1:
 		journal->j_format_version = 1;
 		break;
@@ -1005,9 +1006,9 @@ static int journal_get_superblock(journal_t *journal)
 		goto out;
 	}
 
-	if (ntohl(sb->s_maxlen) < journal->j_maxlen)
-		journal->j_maxlen = ntohl(sb->s_maxlen);
-	else if (ntohl(sb->s_maxlen) > journal->j_maxlen) {
+	if (be32_to_cpu(sb->s_maxlen) < journal->j_maxlen)
+		journal->j_maxlen = be32_to_cpu(sb->s_maxlen);
+	else if (be32_to_cpu(sb->s_maxlen) > journal->j_maxlen) {
 		printk (KERN_WARNING "JBD: journal file too short\n");
 		goto out;
 	}
@@ -1035,11 +1036,11 @@ static int load_superblock(journal_t *journal)
 
 	sb = journal->j_superblock;
 
-	journal->j_tail_sequence = ntohl(sb->s_sequence);
-	journal->j_tail = ntohl(sb->s_start);
-	journal->j_first = ntohl(sb->s_first);
-	journal->j_last = ntohl(sb->s_maxlen);
-	journal->j_errno = ntohl(sb->s_errno);
+	journal->j_tail_sequence = be32_to_cpu(sb->s_sequence);
+	journal->j_tail = be32_to_cpu(sb->s_start);
+	journal->j_first = be32_to_cpu(sb->s_first);
+	journal->j_last = be32_to_cpu(sb->s_maxlen);
+	journal->j_errno = be32_to_cpu(sb->s_errno);
 
 	return 0;
 }
@@ -1252,7 +1253,7 @@ int journal_update_format (journal_t *journal)
 
 	sb = journal->j_superblock;
 
-	switch (ntohl(sb->s_header.h_blocktype)) {
+	switch (be32_to_cpu(sb->s_header.h_blocktype)) {
 	case JFS_SUPERBLOCK_V2:
 		return 0;
 	case JFS_SUPERBLOCK_V1:
@@ -1274,7 +1275,7 @@ static int journal_convert_superblock_v1(journal_t *journal,
 
 	/* Pre-initialise new fields to zero */
 	offset = ((char *) &(sb->s_feature_compat)) - ((char *) sb);
-	blocksize = ntohl(sb->s_blocksize);
+	blocksize = be32_to_cpu(sb->s_blocksize);
 	memset(&sb->s_feature_compat, 0, blocksize-offset);
 
 	sb->s_nr_users = cpu_to_be32(1);
diff --git a/fs/jbd/recovery.c b/fs/jbd/recovery.c
index 8f1971290..4a3d494a3 100644
--- a/fs/jbd/recovery.c
+++ b/fs/jbd/recovery.c
@@ -191,10 +191,10 @@ static int count_tags(struct buffer_head *bh, int size)
 
 		nr++;
 		tagp += sizeof(journal_block_tag_t);
-		if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
+		if (!(tag->t_flags & cpu_to_be32(JFS_FLAG_SAME_UUID)))
 			tagp += 16;
 
-		if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
+		if (tag->t_flags & cpu_to_be32(JFS_FLAG_LAST_TAG))
 			break;
 	}
 
@@ -239,8 +239,8 @@ int journal_recover(journal_t *journal)
 
 	if (!sb->s_start) {
 		jbd_debug(1, "No recovery required, last transaction %d\n",
-			  ntohl(sb->s_sequence));
-		journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
+			  be32_to_cpu(sb->s_sequence));
+		journal->j_transaction_sequence = be32_to_cpu(sb->s_sequence) + 1;
 		return 0;
 	}
 
@@ -295,7 +295,7 @@ int journal_skip_recovery(journal_t *journal)
 		++journal->j_transaction_sequence;
 	} else {
 #ifdef CONFIG_JBD_DEBUG
-		int dropped = info.end_transaction - ntohl(sb->s_sequence);
+		int dropped = info.end_transaction - be32_to_cpu(sb->s_sequence);
 #endif
 		jbd_debug(0, 
 			  "JBD: ignoring %d transaction%s from the journal.\n",
@@ -331,8 +331,8 @@ static int do_one_pass(journal_t *journal,
 	 */
 
 	sb = journal->j_superblock;
-	next_commit_ID = ntohl(sb->s_sequence);
-	next_log_block = ntohl(sb->s_start);
+	next_commit_ID = be32_to_cpu(sb->s_sequence);
+	next_log_block = be32_to_cpu(sb->s_start);
 
 	first_commit_ID = next_commit_ID;
 	if (pass == PASS_SCAN)
@@ -385,13 +385,13 @@ static int do_one_pass(journal_t *journal,
 
 		tmp = (journal_header_t *)bh->b_data;
 
-		if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
+		if (tmp->h_magic != cpu_to_be32(JFS_MAGIC_NUMBER)) {
 			brelse(bh);
 			break;
 		}
 
-		blocktype = ntohl(tmp->h_blocktype);
-		sequence = ntohl(tmp->h_sequence);
+		blocktype = be32_to_cpu(tmp->h_blocktype);
+		sequence = be32_to_cpu(tmp->h_sequence);
 		jbd_debug(3, "Found magic %d, sequence %d\n", 
 			  blocktype, sequence);
 
@@ -427,7 +427,7 @@ static int do_one_pass(journal_t *journal,
 				unsigned long io_block;
 
 				tag = (journal_block_tag_t *) tagp;
-				flags = ntohl(tag->t_flags);
+				flags = be32_to_cpu(tag->t_flags);
 
 				io_block = next_log_block++;
 				wrap(journal, next_log_block);
@@ -444,7 +444,7 @@ static int do_one_pass(journal_t *journal,
 					unsigned long blocknr;
 
 					J_ASSERT(obh != NULL);
-					blocknr = ntohl(tag->t_blocknr);
+					blocknr = be32_to_cpu(tag->t_blocknr);
 
 					/* If the block has been
 					 * revoked, then we're all done
@@ -476,8 +476,8 @@ static int do_one_pass(journal_t *journal,
 					memcpy(nbh->b_data, obh->b_data,
 							journal->j_blocksize);
 					if (flags & JFS_FLAG_ESCAPE) {
-						*((unsigned int *)bh->b_data) =
-							htonl(JFS_MAGIC_NUMBER);
+						*((__be32 *)bh->b_data) =
+						cpu_to_be32(JFS_MAGIC_NUMBER);
 					}
 
 					BUFFER_TRACE(nbh, "marking dirty");
@@ -572,13 +572,13 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
 
 	header = (journal_revoke_header_t *) bh->b_data;
 	offset = sizeof(journal_revoke_header_t);
-	max = ntohl(header->r_count);
+	max = be32_to_cpu(header->r_count);
 
 	while (offset < max) {
 		unsigned long blocknr;
 		int err;
 
-		blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
+		blocknr = be32_to_cpu(* ((__be32 *) (bh->b_data+offset)));
 		offset += 4;
 		err = journal_set_revoke(journal, blocknr, sequence);
 		if (err)
diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c
index 87cd0501d..0bb60dba7 100644
--- a/fs/jbd/revoke.c
+++ b/fs/jbd/revoke.c
@@ -332,6 +332,7 @@ int journal_revoke(handle_t *handle, unsigned long blocknr,
 	struct block_device *bdev;
 	int err;
 
+	might_sleep();
 	if (bh_in)
 		BUFFER_TRACE(bh_in, "enter");
 
@@ -565,9 +566,9 @@ static void write_one_revoke_record(journal_t *journal,
 		if (!descriptor)
 			return;
 		header = (journal_header_t *) &jh2bh(descriptor)->b_data[0];
-		header->h_magic     = htonl(JFS_MAGIC_NUMBER);
-		header->h_blocktype = htonl(JFS_REVOKE_BLOCK);
-		header->h_sequence  = htonl(transaction->t_tid);
+		header->h_magic     = cpu_to_be32(JFS_MAGIC_NUMBER);
+		header->h_blocktype = cpu_to_be32(JFS_REVOKE_BLOCK);
+		header->h_sequence  = cpu_to_be32(transaction->t_tid);
 
 		/* Record it so that we can wait for IO completion later */
 		JBUFFER_TRACE(descriptor, "file as BJ_LogCtl");
@@ -577,8 +578,8 @@ static void write_one_revoke_record(journal_t *journal,
 		*descriptorp = descriptor;
 	}
 
-	* ((unsigned int *)(&jh2bh(descriptor)->b_data[offset])) = 
-		htonl(record->blocknr);
+	* ((__be32 *)(&jh2bh(descriptor)->b_data[offset])) = 
+		cpu_to_be32(record->blocknr);
 	offset += 4;
 	*offsetp = offset;
 }
@@ -603,7 +604,7 @@ static void flush_descriptor(journal_t *journal,
 	}
 
 	header = (journal_revoke_header_t *) jh2bh(descriptor)->b_data;
-	header->r_count = htonl(offset);
+	header->r_count = cpu_to_be32(offset);
 	set_buffer_jwrite(bh);
 	BUFFER_TRACE(bh, "write");
 	set_buffer_dirty(bh);
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index c37fb163e..257a06ea0 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -7,7 +7,7 @@
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
- * $Id: super.c,v 1.97 2004/07/16 15:17:57 dwmw2 Exp $
+ * $Id: super.c,v 1.99 2004/08/24 07:59:57 dwmw2 Exp $
  *
  */
 
@@ -130,7 +130,7 @@ static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type,
 		  mtd->index, mtd->name));
 
 	sb->s_op = &jffs2_super_operations;
-	sb->s_flags |= MS_NOATIME;
+	sb->s_flags = flags | MS_NOATIME;
 
 	ret = jffs2_do_fill_super(sb, data, (flags&MS_VERBOSE)?1:0);
 
@@ -302,7 +302,7 @@ static int __init init_jffs2_fs(void)
 
 	jffs2_inode_cachep = kmem_cache_create("jffs2_i",
 					     sizeof(struct jffs2_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     jffs2_i_init_once, NULL);
 	if (!jffs2_inode_cachep) {
 		printk(KERN_ERR "JFFS2 error: Failed to initialise inode cache\n");
@@ -330,6 +330,7 @@ static int __init init_jffs2_fs(void)
  out_compressors:
 	jffs2_compressors_exit();
  out:
+	kmem_cache_destroy(jffs2_inode_cachep);
 	return ret;
 }
 
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index 8353f48f7..fc584f219 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -1,7 +1,7 @@
 /*
- *   Copyright (c) International Business Machines  Corp., 2002
- *   Copyright (c) Andreas Gruenbacher, 2001
- *   Copyright (c) Linus Torvalds, 1991, 1992
+ *   Copyright (C) International Business Machines  Corp., 2002-2004
+ *   Copyright (C) Andreas Gruenbacher, 2001
+ *   Copyright (C) Linus Torvalds, 1991, 1992
  *
  *   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 +20,7 @@
 
 #include <linux/sched.h>
 #include <linux/fs.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_xattr.h"
 #include "jfs_acl.h"
@@ -281,6 +282,12 @@ int jfs_setattr(struct dentry *dentry, struct iattr *iattr)
 	if (rc)
 		return rc;
 
+	if ((iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) ||
+	    (iattr->ia_valid & ATTR_GID && iattr->ia_gid != inode->i_gid)) {
+		if (DQUOT_TRANSFER(inode, iattr))
+			return -EDQUOT;
+	}
+
 	rc = inode_setattr(inode, iattr);
 
 	if (!rc && (iattr->ia_valid & ATTR_MODE))
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 2b70f813e..d94abccb9 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -1,6 +1,6 @@
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2002
- *   Portions Copyright (c) Christoph Hellwig, 2001-2002
+ *   Copyright (C) International Business Machines Corp., 2000-2004
+ *   Portions Copyright (C) Christoph Hellwig, 2001-2002
  *
  *   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
@@ -21,6 +21,7 @@
 #include <linux/mpage.h>
 #include <linux/buffer_head.h>
 #include <linux/pagemap.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_imap.h"
@@ -105,10 +106,10 @@ int jfs_commit_inode(struct inode *inode, int wait)
 	return rc;
 }
 
-void jfs_write_inode(struct inode *inode, int wait)
+int jfs_write_inode(struct inode *inode, int wait)
 {
 	if (test_cflag(COMMIT_Nolink, inode))
-		return;
+		return 0;
 	/*
 	 * If COMMIT_DIRTY is not set, the inode isn't really dirty.
 	 * It has been committed since the last change, but was still
@@ -117,12 +118,14 @@ void jfs_write_inode(struct inode *inode, int wait)
 	 if (!test_cflag(COMMIT_Dirty, inode)) {
 		/* Make sure committed changes hit the disk */
 		jfs_flush_journal(JFS_SBI(inode->i_sb)->log, wait);
-		return;
+		return 0;
 	 }
 
 	if (jfs_commit_inode(inode, wait)) {
 		jfs_err("jfs_write_inode: jfs_commit_inode failed!");
-	}
+		return -EIO;
+	} else
+		return 0;
 }
 
 void jfs_delete_inode(struct inode *inode)
@@ -134,6 +137,13 @@ void jfs_delete_inode(struct inode *inode)
 
 	diFree(inode);
 
+	/*
+	 * Free the inode from the quota allocation.
+	 */
+	DQUOT_INIT(inode);
+	DQUOT_FREE_INODE(inode);
+	DQUOT_DROP(inode);
+
 	clear_inode(inode);
 }
 
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index 71e797774..29930b6cc 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -101,6 +101,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_superblock.h"
 #include "jfs_filsys.h"
@@ -380,7 +381,8 @@ static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot)
 		 * It's time to move the inline table to an external
 		 * page and begin to build the xtree
 		 */
-		if (dbAlloc(ip, 0, sbi->nbperpage, &xaddr))
+		if (DQUOT_ALLOC_BLOCK(ip, sbi->nbperpage) ||
+		    dbAlloc(ip, 0, sbi->nbperpage, &xaddr))
 			goto clean_up;	/* No space */
 
 		/*
@@ -405,7 +407,6 @@ static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot)
 			goto clean_up;
 		}
 		ip->i_size = PSIZE;
-		ip->i_blocks += LBLK2PBLK(sb, sbi->nbperpage);
 
 		if ((mp = get_index_page(ip, 0)) == 0) {
 			jfs_err("add_index: get_metapage failed!");
@@ -447,7 +448,6 @@ static u32 add_index(tid_t tid, struct inode *ip, s64 bn, int slot)
 			goto clean_up;
 		}
 		ip->i_size += PSIZE;
-		ip->i_blocks += LBLK2PBLK(sb, sbi->nbperpage);
 
 		if ((mp = get_index_page(ip, blkno)))
 			memset(mp->data, 0, PSIZE);	/* Just looks better */
@@ -946,6 +946,7 @@ static int dtSplitUp(tid_t tid,
 	struct dt_lock *dtlck;
 	struct tlock *tlck;
 	struct lv *lv;
+	int quota_allocation = 0;
 
 	/* get split page */
 	smp = split->mp;
@@ -992,7 +993,9 @@ static int dtSplitUp(tid_t tid,
 		split->pxdlist = &pxdlist;
 		rc = dtSplitRoot(tid, ip, split, &rmp);
 
-		if (!rc)
+		if (rc)
+			dbFree(ip, xaddr, xlen);
+		else
 			DT_PUTPAGE(rmp);
 
 		DT_PUTPAGE(smp);
@@ -1017,6 +1020,14 @@ static int dtSplitUp(tid_t tid,
 			n = xlen + (xlen << 1);
 		else
 			n = xlen;
+
+		/* Allocate blocks to quota. */
+		if (DQUOT_ALLOC_BLOCK(ip, n)) {
+			rc = -EDQUOT;
+			goto extendOut;
+		}
+		quota_allocation += n;
+
 		if ((rc = dbReAlloc(sbi->ipbmap, xaddr, (s64) xlen,
 				    (s64) n, &nxaddr)))
 			goto extendOut;
@@ -1285,6 +1296,10 @@ static int dtSplitUp(tid_t tid,
       freeKeyName:
 	kfree(key.name);
 
+	/* Rollback quota allocation */
+	if (rc && quota_allocation)
+		DQUOT_FREE_BLOCK(ip, quota_allocation);
+
       dtSplitUp_Exit:
 
 	return rc;
@@ -1305,7 +1320,6 @@ static int dtSplitUp(tid_t tid,
 static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
 	    struct metapage ** rmpp, dtpage_t ** rpp, pxd_t * rpxdp)
 {
-	struct super_block *sb = ip->i_sb;
 	int rc = 0;
 	struct metapage *smp;
 	dtpage_t *sp;
@@ -1344,6 +1358,12 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
 	if (rmp == NULL)
 		return -EIO;
 
+	/* Allocate blocks to quota. */
+	if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
+		release_metapage(rmp);
+		return -EDQUOT;
+	}
+
 	jfs_info("dtSplitPage: ip:0x%p smp:0x%p rmp:0x%p", ip, smp, rmp);
 
 	BT_MARK_DIRTY(rmp, ip);
@@ -1593,8 +1613,6 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
 	*rmpp = rmp;
 	*rpxdp = *pxd;
 
-	ip->i_blocks += LBLK2PBLK(sb, lengthPXD(pxd));
-
 	return rc;
 }
 
@@ -1823,16 +1841,6 @@ static int dtExtendPage(tid_t tid,
 	tpxd = (pxd_t *) & pp->slot[1];
 	*tpxd = *pxd;
 
-	/* Since the directory might have an EA and/or ACL associated with it
-	 * we need to make sure we take that into account when setting the
-	 * i_nblocks
-	 */
-	ip->i_blocks = LBLK2PBLK(ip->i_sb, xlen +
-				 ((JFS_IP(ip)->ea.flag & DXD_EXTENT) ?
-				  lengthDXD(&JFS_IP(ip)->ea) : 0) +
-				 ((JFS_IP(ip)->acl.flag & DXD_EXTENT) ?
-				  lengthDXD(&JFS_IP(ip)->acl) : 0));
-
 	DT_PUTPAGE(pmp);
 	return 0;
 }
@@ -1900,6 +1908,12 @@ static int dtSplitRoot(tid_t tid,
 
 	rp = rmp->data;
 
+	/* Allocate blocks to quota. */
+	if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
+		release_metapage(rmp);
+		return -EDQUOT;
+	}
+
 	BT_MARK_DIRTY(rmp, ip);
 	/*
 	 * acquire a transaction lock on the new right page
@@ -2042,7 +2056,6 @@ static int dtSplitRoot(tid_t tid,
 
 	*rmpp = rmp;
 
-	ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd));
 	return 0;
 }
 
@@ -2265,7 +2278,9 @@ static int dtDeleteUp(tid_t tid, struct inode *ip,
 	}
 
 	xlen = lengthPXD(&fp->header.self);
-	ip->i_blocks -= LBLK2PBLK(ip->i_sb, xlen);
+
+	/* Free quota allocation. */
+	DQUOT_FREE_BLOCK(ip, xlen);
 
 	/* free/invalidate its buffer page */
 	discard_metapage(fmp);
@@ -2339,7 +2354,9 @@ static int dtDeleteUp(tid_t tid, struct inode *ip,
 				}
 
 				xlen = lengthPXD(&p->header.self);
-				ip->i_blocks -= LBLK2PBLK(ip->i_sb, xlen);
+
+				/* Free quota allocation */
+				DQUOT_FREE_BLOCK(ip, xlen);
 
 				/* free/invalidate its buffer page */
 				discard_metapage(mp);
@@ -2877,14 +2894,6 @@ void dtInitRoot(tid_t tid, struct inode *ip, u32 idotdot)
 	/* init '..' entry */
 	p->header.idotdot = cpu_to_le32(idotdot);
 
-#if 0
-	ip->i_blocks = LBLK2PBLK(ip->i_sb,
-				 ((jfs_ip->ea.flag & DXD_EXTENT) ?
-				  lengthDXD(&jfs_ip->ea) : 0) +
-				 ((jfs_ip->acl.flag & DXD_EXTENT) ?
-				  lengthDXD(&jfs_ip->acl) : 0));
-#endif
-
 	return;
 }
 
diff --git a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c
index 2b411bc32..1953acb79 100644
--- a/fs/jfs/jfs_extent.c
+++ b/fs/jfs/jfs_extent.c
@@ -1,5 +1,5 @@
 /*
- *   Copyright (C) International Business Machines Corp., 2000-2003
+ *   Copyright (C) International Business Machines Corp., 2000-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
@@ -17,6 +17,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_superblock.h"
 #include "jfs_dmap.h"
@@ -144,6 +145,13 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, boolean_t abnr)
 		return (rc);
 	}
 
+	/* Allocate blocks to quota. */
+	if (DQUOT_ALLOC_BLOCK(ip, nxlen)) {
+		dbFree(ip, nxaddr, (s64) nxlen);
+		up(&JFS_IP(ip)->commit_sem);
+		return -EDQUOT;
+	}
+
 	/* determine the value of the extent flag */
 	xflag = (abnr == TRUE) ? XAD_NOTRECORDED : 0;
 
@@ -161,13 +169,11 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, boolean_t abnr)
 	 */
 	if (rc) {
 		dbFree(ip, nxaddr, nxlen);
+		DQUOT_FREE_BLOCK(ip, nxlen);
 		up(&JFS_IP(ip)->commit_sem);
 		return (rc);
 	}
 
-	/* update the number of blocks allocated to the file */
-	ip->i_blocks += LBLK2PBLK(ip->i_sb, nxlen);
-
 	/* set the results of the extent allocation */
 	XADaddress(xp, nxaddr);
 	XADlength(xp, nxlen);
@@ -254,6 +260,13 @@ int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, boolean_t abnr)
 	if ((rc = extBrealloc(ip, xaddr, xlen, &nxlen, &nxaddr)))
 		goto exit;
 
+	/* Allocat blocks to quota. */
+	if (DQUOT_ALLOC_BLOCK(ip, nxlen)) {
+		dbFree(ip, nxaddr, (s64) nxlen);
+		up(&JFS_IP(ip)->commit_sem);
+		return -EDQUOT;
+	}
+
 	delta = nxlen - xlen;
 
 	/* check if the extend page is not abnr but the request is abnr
@@ -289,6 +302,7 @@ int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, boolean_t abnr)
 		/* extend the extent */
 		if ((rc = xtExtend(0, ip, xoff + xlen, (int) nextend, 0))) {
 			dbFree(ip, xaddr + xlen, delta);
+			DQUOT_FREE_BLOCK(ip, nxlen);
 			goto exit;
 		}
 	} else {
@@ -299,6 +313,7 @@ int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, boolean_t abnr)
 		 */
 		if ((rc = xtTailgate(0, ip, xoff, (int) ntail, nxaddr, 0))) {
 			dbFree(ip, nxaddr, nxlen);
+			DQUOT_FREE_BLOCK(ip, nxlen);
 			goto exit;
 		}
 	}
@@ -320,9 +335,6 @@ int extRealloc(struct inode *ip, s64 nxlen, xad_t * xp, boolean_t abnr)
 		}
 	}
 
-	/* update the inode with the number of blocks allocated */
-	ip->i_blocks += LBLK2PBLK(sb, delta);
-
 	/* set the return results */
 	XADaddress(xp, nxaddr);
 	XADlength(xp, nxlen);
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index 6a6f147e8..084ec2633 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -1,5 +1,5 @@
 /*
- *   Copyright (C) International Business Machines Corp., 2000-2003
+ *   Copyright (C) International Business Machines Corp., 2000-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
@@ -44,6 +44,7 @@
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
 #include <linux/pagemap.h>
+#include <linux/quotaops.h>
 #include <linux/vserver/xid.h>
 
 #include "jfs_incore.h"
@@ -505,6 +506,9 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary)
 	ip->i_mapping->a_ops = &jfs_aops;
 	mapping_set_gfp_mask(ip->i_mapping, GFP_NOFS);
 
+	/* Allocations to metadata inodes should not affect quotas */
+	ip->i_flags |= S_NOQUOTA;
+
 	if ((inum == FILESYSTEM_I) && (JFS_IP(ip)->ipimap == sbi->ipaimap)) {
 		sbi->gengen = le32_to_cpu(dp->di_gengen);
 		sbi->inostamp = le32_to_cpu(dp->di_inostamp);
@@ -2602,28 +2606,11 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
 			iagp->inosmap[i] = ONES;
 
 		flush_metapage(mp);
-#ifdef _STILL_TO_PORT
-		/* synchronously write the iag page */
-		if (bmWrite(bp)) {
-			/* Free the blocks allocated for the iag since it was
-			 * not successfully added to the inode map
-			 */
-			dbFree(ipimap, xaddr, (s64) xlen);
-
-			/* release the inode map lock */
-			IWRITE_UNLOCK(ipimap);
-
-			rc = -EIO;
-			goto out;
-		}
-
-		/* Now the iag is on disk */
 
 		/*
 		 * start tyransaction of update of the inode map
 		 * addressing structure pointing to the new iag page;
 		 */
-#endif				/*  _STILL_TO_PORT */
 		tid = txBegin(sb, COMMIT_FORCE);
 		down(&JFS_IP(ipimap)->commit_sem);
 
@@ -2645,7 +2632,7 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp)
 
 		/* update the inode map's inode to reflect the extension */
 		ipimap->i_size += PSIZE;
-		ipimap->i_blocks += LBLK2PBLK(sb, xlen);
+		inode_add_bytes(ipimap, PSIZE);
 
 		/*
 		 * txCommit(COMMIT_FORCE) will synchronously write address 
@@ -3086,7 +3073,7 @@ static void duplicateIXtree(struct super_block *sb, s64 blkno,
 	}
 	/* update the inode map's inode to reflect the extension */
 	ip->i_size += PSIZE;
-	ip->i_blocks += LBLK2PBLK(sb, xlen);
+	inode_add_bytes(ip, PSIZE);
 	txCommit(tid, 1, &ip, COMMIT_FORCE);
       cleanup:
 	txEnd(tid);
@@ -3119,7 +3106,7 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip)
 	ip->i_uid = INOXID_UID(XID_TAG(ip), uid, gid);
 	ip->i_gid = INOXID_GID(XID_TAG(ip), uid, gid);
 	ip->i_xid = INOXID_XID(XID_TAG(ip), uid, gid, 0);
-	
+
 	ip->i_size = le64_to_cpu(dip->di_size);
 	ip->i_atime.tv_sec = le32_to_cpu(dip->di_atime.tv_sec);
 	ip->i_atime.tv_nsec = le32_to_cpu(dip->di_atime.tv_nsec);
diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
index 3e8592b9b..84f2459b2 100644
--- a/fs/jfs/jfs_inode.c
+++ b/fs/jfs/jfs_inode.c
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2002
+ *   Copyright (C) International Business Machines Corp., 2000-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
@@ -17,6 +17,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_imap.h"
@@ -60,6 +61,17 @@ struct inode *ialloc(struct inode *parent, umode_t mode)
 	} else
 		inode->i_gid = current->fsgid;
 
+	/*
+	 * Allocate inode to quota.
+	 */
+	if (DQUOT_ALLOC_INODE(inode)) {
+		DQUOT_DROP(inode);
+		inode->i_flags |= S_NOQUOTA;
+		inode->i_nlink = 0;
+		iput(inode);
+		return NULL;
+	}
+
 	inode->i_mode = mode;
 	if (S_ISDIR(mode))
 		jfs_inode->mode2 = IDIRECTORY | mode;
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index 831ee09c2..82ffeaadf 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -557,6 +557,7 @@ again:
 			if (page) {
 				block_invalidatepage(page, 0);
 				unlock_page(page);
+				page_cache_release(page);
 			}
 		}
 	}
diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c
index fad757e9e..aa871829b 100644
--- a/fs/jfs/jfs_mount.c
+++ b/fs/jfs/jfs_mount.c
@@ -197,9 +197,6 @@ int jfs_mount(struct super_block *sb)
 	/*
 	 *      unwind on error
 	 */
-//errout42: /* close fileset inode allocation map */
-	diUnmount(ipimap, 1);
-
       errout41:		/* close fileset inode allocation map inode */
 	diFreeSpecial(ipimap);
 
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index f4bd79b70..12e9ccffb 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -165,7 +165,6 @@ struct {
  * external references
  */
 extern int lmGroupCommit(struct jfs_log *, struct tblock *);
-extern void lmSync(struct jfs_log *);
 extern int jfs_commit_inode(struct inode *, int);
 extern int jfs_stop_threads;
 
@@ -2622,8 +2621,6 @@ void txAbort(tid_t tid, int dirty)
 	struct tblock *tblk = tid_to_tblock(tid);
 	struct tlock *tlck;
 
-	jfs_warn("txAbort: tid:%d dirty:0x%x", tid, dirty);
-
 	/*
 	 * free tlocks of the transaction
 	 */
diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
index 19913fcd4..b4dc15924 100644
--- a/fs/jfs/jfs_xtree.c
+++ b/fs/jfs/jfs_xtree.c
@@ -1,5 +1,5 @@
 /*
- *   Copyright (C) International Business Machines Corp., 2000-2003
+ *   Copyright (C) International Business Machines Corp., 2000-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
@@ -20,6 +20,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_metapage.h"
@@ -829,8 +830,12 @@ int xtInsert(tid_t tid,		/* transaction id */
 			hint = addressXAD(xad) + lengthXAD(xad) - 1;
 		} else
 			hint = 0;
-		if ((rc = dbAlloc(ip, hint, (s64) xlen, &xaddr)))
+		if ((rc = DQUOT_ALLOC_BLOCK(ip, xlen)))
 			goto out;
+		if ((rc = dbAlloc(ip, hint, (s64) xlen, &xaddr))) {
+			DQUOT_FREE_BLOCK(ip, xlen);
+			goto out;
+		}
 	}
 
 	/*
@@ -855,8 +860,10 @@ int xtInsert(tid_t tid,		/* transaction id */
 		split.pxdlist = NULL;
 		if ((rc = xtSplitUp(tid, ip, &split, &btstack))) {
 			/* undo data extent allocation */
-			if (*xaddrp == 0)
+			if (*xaddrp == 0) {
 				dbFree(ip, xaddr, (s64) xlen);
+				DQUOT_FREE_BLOCK(ip, xlen);
+			}
 			return rc;
 		}
 
@@ -1214,22 +1221,34 @@ xtSplitPage(tid_t tid, struct inode *ip,
 	pxd_t *pxd;
 	struct tlock *tlck;
 	struct xtlock *sxtlck = NULL, *rxtlck = NULL;
+	int quota_allocation = 0;
 
 	smp = split->mp;
 	sp = XT_PAGE(ip, smp);
 
 	INCREMENT(xtStat.split);
 
-	/*
-	 * allocate the new right page for the split
-	 */
 	pxdlist = split->pxdlist;
 	pxd = &pxdlist->pxd[pxdlist->npxd];
 	pxdlist->npxd++;
 	rbn = addressPXD(pxd);
+
+	/* Allocate blocks to quota. */
+       if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
+	       rc = -EDQUOT;
+	       goto clean_up;
+	}
+
+	quota_allocation += lengthPXD(pxd);
+
+	/*
+	 * allocate the new right page for the split
+	 */
 	rmp = get_metapage(ip, rbn, PSIZE, 1);
-	if (rmp == NULL)
-		return -EIO;
+	if (rmp == NULL) {
+		rc = -EIO;
+		goto clean_up;
+	}
 
 	jfs_info("xtSplitPage: ip:0x%p smp:0x%p rmp:0x%p", ip, smp, rmp);
 
@@ -1304,8 +1323,6 @@ xtSplitPage(tid_t tid, struct inode *ip,
 		*rmpp = rmp;
 		*rbnp = rbn;
 
-		ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd));
-
 		jfs_info("xtSplitPage: sp:0x%p rp:0x%p", sp, rp);
 		return 0;
 	}
@@ -1321,7 +1338,7 @@ xtSplitPage(tid_t tid, struct inode *ip,
 		XT_GETPAGE(ip, nextbn, mp, PSIZE, p, rc);
 		if (rc) {
 			XT_PUTPAGE(rmp);
-			return rc;
+			goto clean_up;
 		}
 
 		BT_MARK_DIRTY(mp, ip);
@@ -1420,10 +1437,16 @@ xtSplitPage(tid_t tid, struct inode *ip,
 	*rmpp = rmp;
 	*rbnp = rbn;
 
-	ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd));
-
 	jfs_info("xtSplitPage: sp:0x%p rp:0x%p", sp, rp);
 	return rc;
+
+      clean_up:
+
+	/* Rollback quota allocation. */
+	if (quota_allocation)
+		DQUOT_FREE_BLOCK(ip, quota_allocation);
+
+	return (rc);
 }
 
 
@@ -1478,6 +1501,12 @@ xtSplitRoot(tid_t tid,
 	if (rmp == NULL)
 		return -EIO;
 
+	/* Allocate blocks to quota. */
+	if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) {
+		release_metapage(rmp);
+		return -EDQUOT;
+	}
+
 	jfs_info("xtSplitRoot: ip:0x%p rmp:0x%p", ip, rmp);
 
 	/*
@@ -1561,8 +1590,6 @@ xtSplitRoot(tid_t tid,
 
 	*rmpp = rmp;
 
-	ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd));
-
 	jfs_info("xtSplitRoot: sp:0x%p rp:0x%p", sp, rp);
 	return 0;
 }
@@ -3909,8 +3936,8 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag)
 	else
 		ip->i_size = newsize;
 
-	/* update nblocks to reflect freed blocks */
-	ip->i_blocks -= LBLK2PBLK(ip->i_sb, nfreed);
+	/* update quota allocation to reflect freed blocks */
+	DQUOT_FREE_BLOCK(ip, nfreed);
 
 	/*
 	 * free tlock of invalidated pages
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 8c3a8e78d..e089615ad 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -19,6 +19,7 @@
 
 #include <linux/fs.h>
 #include <linux/ctype.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_superblock.h"
 #include "jfs_inode.h"
@@ -123,10 +124,10 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
 	 */
 	ino = ip->i_ino;
 	if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {
-		jfs_err("jfs_create: dtInsert returned %d", rc);
-		if (rc == -EIO)
+		if (rc == -EIO) {
+			jfs_err("jfs_create: dtInsert returned -EIO");
 			txAbort(tid, 1);	/* Marks Filesystem dirty */
-		else
+		} else
 			txAbort(tid, 0);	/* Filesystem full */
 		goto out3;
 	}
@@ -250,11 +251,10 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
 	 */
 	ino = ip->i_ino;
 	if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) {
-		jfs_err("jfs_mkdir: dtInsert returned %d", rc);
-
-		if (rc == -EIO)
+		if (rc == -EIO) {
+			jfs_err("jfs_mkdir: dtInsert returned -EIO");
 			txAbort(tid, 1);	/* Marks Filesystem dirty */
-		else
+		} else
 			txAbort(tid, 0);	/* Filesystem full */
 		goto out3;
 	}
@@ -330,6 +330,9 @@ static int jfs_rmdir(struct inode *dip, struct dentry *dentry)
 
 	jfs_info("jfs_rmdir: dip:0x%p name:%s", dip, dentry->d_name.name);
 
+	/* Init inode for quota operations. */
+	DQUOT_INIT(ip);
+
 	/* directory must be empty to be removed */
 	if (!dtEmpty(ip)) {
 		rc = -ENOTEMPTY;
@@ -455,6 +458,9 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry)
 
 	jfs_info("jfs_unlink: dip:0x%p name:%s", dip, dentry->d_name.name);
 
+	/* Init inode for quota operations. */
+	DQUOT_INIT(ip);
+
 	if ((rc = get_UCSname(&dname, dentry)))
 		goto out;
 
@@ -813,7 +819,10 @@ static int jfs_link(struct dentry *old_dentry,
 	iplist[1] = dir;
 	rc = txCommit(tid, 2, &iplist[0], 0);
 
-	if (!rc)
+	if (rc) {
+		ip->i_nlink--;
+		iput(ip);
+	} else
 		d_instantiate(dentry, ip);
 
       free_dname:
@@ -964,7 +973,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
 			mp = get_metapage(ip, xaddr, PSIZE, 1);
 
 			if (mp == NULL) {
-				dbFree(ip, extent, xlen);
+				xtTruncate(tid, ip, 0, COMMIT_PWMAP);
 				rc = -EIO;
 				txAbort(tid, 0);
 				goto out3;
@@ -975,7 +984,6 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
 			name += copy_size;
 			xaddr += JFS_SBI(sb)->nbperpage;
 		}
-		ip->i_blocks = LBLK2PBLK(sb, xlen);
 	}
 
 	/*
@@ -988,7 +996,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
 	}
 	if (rc) {
 		if (xlen)
-			dbFree(ip, extent, xlen);
+			xtTruncate(tid, ip, 0, COMMIT_PWMAP);
 		txAbort(tid, 0);
 		/* discard new inode */
 		goto out3;
@@ -1104,8 +1112,11 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 			rc = -EMLINK;
 			goto out3;
 		}
-	} else if (new_ip)
+	} else if (new_ip) {
 		IWRITE_LOCK(new_ip);
+		/* Init inode for quota operations. */
+		DQUOT_INIT(new_ip);
+	}
 
 	/*
 	 * The real work starts here
@@ -1174,8 +1185,8 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 		ino = old_ip->i_ino;
 		rc = dtInsert(tid, new_dir, &new_dname, &ino, &btstack);
 		if (rc) {
-			jfs_err("jfs_rename: dtInsert failed w/rc = %d",
-				rc);
+			if (rc == -EIO)
+				jfs_err("jfs_rename: dtInsert returned -EIO");
 			goto out4;
 		}
 		if (S_ISDIR(old_ip->i_mode))
diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c
index 71f675356..2eb6869b6 100644
--- a/fs/jfs/resize.c
+++ b/fs/jfs/resize.c
@@ -1,5 +1,5 @@
 /*
- *   Copyright (C) International Business Machines  Corp., 2000-2003
+ *   Copyright (C) International Business Machines  Corp., 2000-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
@@ -18,6 +18,7 @@
 
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_metapage.h"
@@ -390,7 +391,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
 	}
 	/* update bmap file size */
 	ipbmap->i_size += xlen << sbi->l2bsize;
-	ipbmap->i_blocks += LBLK2PBLK(sb, xlen);
+	inode_add_bytes(ipbmap, xlen << sbi->l2bsize);
 
 	iplist[0] = ipbmap;
 	rc = txCommit(tid, 1, &iplist[0], COMMIT_FORCE);
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 9615a83d7..7c91ccfe3 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -58,7 +58,7 @@ DECLARE_COMPLETION(jfsIOwait);
 
 #ifdef CONFIG_JFS_DEBUG
 int jfsloglevel = JFS_LOGLEVEL_WARN;
-module_param(jfsloglevel, int, 644);
+module_param(jfsloglevel, int, 0644);
 MODULE_PARM_DESC(jfsloglevel, "Specify JFS loglevel (0, 1 or 2)");
 #endif
 
@@ -77,7 +77,7 @@ extern int jfs_sync(void *);
 extern void jfs_read_inode(struct inode *inode);
 extern void jfs_dirty_inode(struct inode *inode);
 extern void jfs_delete_inode(struct inode *inode);
-extern void jfs_write_inode(struct inode *inode, int wait);
+extern int jfs_write_inode(struct inode *inode, int wait);
 
 extern struct dentry *jfs_get_parent(struct dentry *dentry);
 extern int jfs_extendfs(struct super_block *, s64, int);
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index cf3fba6e5..9c0e3a524 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -1,5 +1,5 @@
 /*
- *   Copyright (C) International Business Machines  Corp., 2000-2003
+ *   Copyright (C) International Business Machines  Corp., 2000-2004
  *   Copyright (C) Christoph Hellwig, 2002
  *
  *   This program is free software;  you can redistribute it and/or modify
@@ -19,6 +19,7 @@
 
 #include <linux/fs.h>
 #include <linux/xattr.h>
+#include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_superblock.h"
 #include "jfs_dmap.h"
@@ -251,9 +252,17 @@ static int ea_write(struct inode *ip, struct jfs_ea_list *ealist, int size,
 	/* figure out how many blocks we need */
 	nblocks = (size + (sb->s_blocksize - 1)) >> sb->s_blocksize_bits;
 
+	/* Allocate new blocks to quota. */
+	if (DQUOT_ALLOC_BLOCK(ip, nblocks)) {
+		return -EDQUOT;
+	}
+
 	rc = dbAlloc(ip, INOHINT(ip), nblocks, &blkno);
-	if (rc)
+	if (rc) {
+		/*Rollback quota allocation. */
+		DQUOT_FREE_BLOCK(ip, nblocks);
 		return rc;
+	}
 
 	/*
 	 * Now have nblocks worth of storage to stuff into the FEALIST.
@@ -315,6 +324,9 @@ static int ea_write(struct inode *ip, struct jfs_ea_list *ealist, int size,
 	return 0;
 
       failed:
+	/* Rollback quota allocation. */
+	DQUOT_FREE_BLOCK(ip, nblocks);
+
 	dbFree(ip, blkno, nblocks);
 	return rc;
 }
@@ -448,6 +460,7 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
 	int blocks_needed, current_blocks;
 	s64 blkno;
 	int rc;
+	int quota_allocation = 0;
 
 	/* When fsck.jfs clears a bad ea, it doesn't clear the size */
 	if (ji->ea.flag == 0)
@@ -517,10 +530,16 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
 	    sb->s_blocksize_bits;
 
 	if (blocks_needed > current_blocks) {
+		/* Allocate new blocks to quota. */
+		if (DQUOT_ALLOC_BLOCK(inode, blocks_needed))
+			return -EDQUOT;
+
+		quota_allocation = blocks_needed;
+
 		rc = dbAlloc(inode, INOHINT(inode), (s64) blocks_needed,
 			     &blkno);
 		if (rc)
-			return rc;
+			goto clean_up;
 
 		DXDlength(&ea_buf->new_ea, blocks_needed);
 		DXDaddress(&ea_buf->new_ea, blkno);
@@ -534,7 +553,8 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
 					  1);
 		if (ea_buf->mp == NULL) {
 			dbFree(inode, blkno, (s64) blocks_needed);
-			return -EIO;
+			rc = -EIO;
+			goto clean_up;
 		}
 		ea_buf->xattr = ea_buf->mp->data;
 		ea_buf->max_size = (min_size + sb->s_blocksize - 1) &
@@ -544,7 +564,7 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
 		if ((rc = ea_read(inode, ea_buf->xattr))) {
 			discard_metapage(ea_buf->mp);
 			dbFree(inode, blkno, (s64) blocks_needed);
-			return rc;
+			goto clean_up;
 		}
 		goto size_check;
 	}
@@ -552,8 +572,10 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
 	ea_buf->mp = read_metapage(inode, addressDXD(&ji->ea),
 				   lengthDXD(&ji->ea) << sb->s_blocksize_bits,
 				   1);
-	if (ea_buf->mp == NULL)
-		return -EIO;
+	if (ea_buf->mp == NULL) {
+		rc = -EIO;
+		goto clean_up;
+	}
 	ea_buf->xattr = ea_buf->mp->data;
 	ea_buf->max_size = (ea_size + sb->s_blocksize - 1) &
 	    ~(sb->s_blocksize - 1);
@@ -563,10 +585,18 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
 		printk(KERN_ERR "ea_get: invalid extended attribute\n");
 		dump_mem("xattr", ea_buf->xattr, ea_size);
 		ea_release(inode, ea_buf);
-		return -EIO;
+		rc = -EIO;
+		goto clean_up;
 	}
 
 	return ea_size;
+
+      clean_up:
+	/* Rollback quota allocation */
+	if (quota_allocation)
+		DQUOT_FREE_BLOCK(inode, quota_allocation);
+
+	return (rc);
 }
 
 static void ea_release(struct inode *inode, struct ea_buffer *ea_buf)
@@ -640,7 +670,10 @@ static int ea_put(struct inode *inode, struct ea_buffer *ea_buf, int new_size)
 		ji->ea.size = 0;
 	}
 
-	inode->i_blocks += LBLK2PBLK(inode->i_sb, new_blocks - old_blocks);
+	/* If old blocks exist, they must be removed from quota allocation. */
+	if (old_blocks)
+		DQUOT_FREE_BLOCK(inode, old_blocks);
+
 	inode->i_ctime = CURRENT_TIME;
 	rc = txCommit(tid, 1, &inode, 0);
 	txEnd(tid);
diff --git a/fs/libfs.c b/fs/libfs.c
index 205cfdbe2..5d3f82bbc 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -27,14 +27,27 @@ int simple_statfs(struct super_block *sb, struct kstatfs *buf)
 }
 
 /*
- * Lookup the data. This is trivial - if the dentry didn't already
- * exist, we know it is negative.
+ * Retaining negative dentries for an in-memory filesystem just wastes
+ * memory and lookup time: arrange for them to be deleted immediately.
  */
+static int simple_delete_dentry(struct dentry *dentry)
+{
+	return 1;
+}
 
+/*
+ * Lookup the data. This is trivial - if the dentry didn't already
+ * exist, we know it is negative.  Set d_op to delete negative dentries.
+ */
 struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
+	static struct dentry_operations simple_dentry_operations = {
+		.d_delete = simple_delete_dentry,
+	};
+
 	if (dentry->d_name.len > NAME_MAX)
 		return ERR_PTR(-ENAMETOOLONG);
+	dentry->d_op = &simple_dentry_operations;
 	d_add(dentry, NULL);
 	return NULL;
 }
@@ -456,6 +469,58 @@ ssize_t simple_read_from_buffer(void __user *to, size_t count, loff_t *ppos,
 	return count;
 }
 
+/*
+ * Transaction based IO.
+ * The file expects a single write which triggers the transaction, and then
+ * possibly a read which collects the result - which is stored in a
+ * file-local buffer.
+ */
+char *simple_transaction_get(struct file *file, const char __user *buf, size_t size)
+{
+	struct simple_transaction_argresp *ar;
+	static spinlock_t simple_transaction_lock = SPIN_LOCK_UNLOCKED;
+
+	if (size > SIMPLE_TRANSACTION_LIMIT - 1)
+		return ERR_PTR(-EFBIG);
+
+	ar = (struct simple_transaction_argresp *)get_zeroed_page(GFP_KERNEL);
+	if (!ar)
+		return ERR_PTR(-ENOMEM);
+
+	spin_lock(&simple_transaction_lock);
+
+	/* only one write allowed per open */
+	if (file->private_data) {
+		spin_unlock(&simple_transaction_lock);
+		free_page((unsigned long)ar);
+		return ERR_PTR(-EBUSY);
+	}
+
+	file->private_data = ar;
+
+	spin_unlock(&simple_transaction_lock);
+
+	if (copy_from_user(ar->data, buf, size))
+		return ERR_PTR(-EFAULT);
+
+	return ar->data;
+}
+
+ssize_t simple_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
+{
+	struct simple_transaction_argresp *ar = file->private_data;
+
+	if (!ar)
+		return 0;
+	return simple_read_from_buffer(buf, size, pos, ar->data, ar->size);
+}
+
+int simple_transaction_release(struct inode *inode, struct file *file)
+{
+	free_page((unsigned long)file->private_data);
+	return 0;
+}
+
 EXPORT_SYMBOL(dcache_dir_close);
 EXPORT_SYMBOL(dcache_dir_lseek);
 EXPORT_SYMBOL(dcache_dir_open);
@@ -479,3 +544,6 @@ EXPORT_SYMBOL(simple_statfs);
 EXPORT_SYMBOL(simple_sync_file);
 EXPORT_SYMBOL(simple_unlink);
 EXPORT_SYMBOL(simple_read_from_buffer);
+EXPORT_SYMBOL(simple_transaction_get);
+EXPORT_SYMBOL(simple_transaction_read);
+EXPORT_SYMBOL(simple_transaction_release);
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index 59c6c49fe..ef7103b8c 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -146,7 +146,7 @@ void nlmclnt_mark_reclaim(struct nlm_host *host)
 		inode = fl->fl_file->f_dentry->d_inode;
 		if (inode->i_sb->s_magic != NFS_SUPER_MAGIC)
 			continue;
-		if (fl->fl_u.nfs_fl.host != host)
+		if (fl->fl_u.nfs_fl.owner->host != host)
 			continue;
 		if (!(fl->fl_u.nfs_fl.flags & NFS_LCK_GRANTED))
 			continue;
@@ -215,7 +215,7 @@ restart:
 		inode = fl->fl_file->f_dentry->d_inode;
 		if (inode->i_sb->s_magic != NFS_SUPER_MAGIC)
 			continue;
-		if (fl->fl_u.nfs_fl.host != host)
+		if (fl->fl_u.nfs_fl.owner->host != host)
 			continue;
 		if (!(fl->fl_u.nfs_fl.flags & NFS_LCK_RECLAIM))
 			continue;
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 319e28fde..caad617be 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -27,6 +27,7 @@ static int	nlmclnt_unlock(struct nlm_rqst *, struct file_lock *);
 static void	nlmclnt_unlock_callback(struct rpc_task *);
 static void	nlmclnt_cancel_callback(struct rpc_task *);
 static int	nlm_stat_to_errno(u32 stat);
+static void	nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host);
 
 /*
  * Cookie counter for NLM requests
@@ -41,11 +42,83 @@ static inline void nlmclnt_next_cookie(struct nlm_cookie *c)
 	nlm_cookie++;
 }
 
+static struct nlm_lockowner *nlm_get_lockowner(struct nlm_lockowner *lockowner)
+{
+	atomic_inc(&lockowner->count);
+	return lockowner;
+}
+
+static void nlm_put_lockowner(struct nlm_lockowner *lockowner)
+{
+	if (!atomic_dec_and_lock(&lockowner->count, &lockowner->host->h_lock))
+		return;
+	list_del(&lockowner->list);
+	spin_unlock(&lockowner->host->h_lock);
+	nlm_release_host(lockowner->host);
+	kfree(lockowner);
+}
+
+static inline int nlm_pidbusy(struct nlm_host *host, uint32_t pid)
+{
+	struct nlm_lockowner *lockowner;
+	list_for_each_entry(lockowner, &host->h_lockowners, list) {
+		if (lockowner->pid == pid)
+			return -EBUSY;
+	}
+	return 0;
+}
+
+static inline uint32_t __nlm_alloc_pid(struct nlm_host *host)
+{
+	uint32_t res;
+	do {
+		res = host->h_pidcount++;
+	} while (nlm_pidbusy(host, res) < 0);
+	return res;
+}
+
+static struct nlm_lockowner *__nlm_find_lockowner(struct nlm_host *host, fl_owner_t owner)
+{
+	struct nlm_lockowner *lockowner;
+	list_for_each_entry(lockowner, &host->h_lockowners, list) {
+		if (lockowner->owner != owner)
+			continue;
+		return nlm_get_lockowner(lockowner);
+	}
+	return NULL;
+}
+
+static struct nlm_lockowner *nlm_find_lockowner(struct nlm_host *host, fl_owner_t owner)
+{
+	struct nlm_lockowner *res, *new = NULL;
+
+	spin_lock(&host->h_lock);
+	res = __nlm_find_lockowner(host, owner);
+	if (res == NULL) {
+		spin_unlock(&host->h_lock);
+		new = (struct nlm_lockowner *)kmalloc(sizeof(*new), GFP_KERNEL);
+		spin_lock(&host->h_lock);
+		res = __nlm_find_lockowner(host, owner);
+		if (res == NULL && new != NULL) {
+			res = new;
+			atomic_set(&new->count, 1);
+			new->owner = owner;
+			new->pid = __nlm_alloc_pid(host);
+			new->host = nlm_get_host(host);
+			list_add(&new->list, &host->h_lockowners);
+			new = NULL;
+		}
+	}
+	spin_unlock(&host->h_lock);
+	if (new != NULL)
+		kfree(new);
+	return res;
+}
+
 /*
  * Initialize arguments for TEST/LOCK/UNLOCK/CANCEL calls
  */
-static inline void
-nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
+static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
 {
 	struct nlm_args	*argp = &req->a_args;
 	struct nlm_lock	*lock = &argp->lock;
@@ -60,6 +133,14 @@ nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
 	locks_copy_lock(&lock->fl, fl);
 }
 
+static void nlmclnt_release_lockargs(struct nlm_rqst *req)
+{
+	struct file_lock *fl = &req->a_args.lock.fl;
+
+	if (fl->fl_ops && fl->fl_ops->fl_release_private)
+		fl->fl_ops->fl_release_private(fl);
+}
+
 /*
  * Initialize arguments for GRANTED call. The nlm_rqst structure
  * has been cleared already.
@@ -77,8 +158,10 @@ nlmclnt_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock)
 
 	if (lock->oh.len > NLMCLNT_OHSIZE) {
 		void *data = kmalloc(lock->oh.len, GFP_KERNEL);
-		if (!data)
+		if (!data) {
+			nlmclnt_freegrantargs(call);
 			return 0;
+		}
 		call->a_args.lock.oh.data = (u8 *) data;
 	}
 
@@ -89,12 +172,15 @@ nlmclnt_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock)
 void
 nlmclnt_freegrantargs(struct nlm_rqst *call)
 {
+	struct file_lock *fl = &call->a_args.lock.fl;
 	/*
 	 * Check whether we allocated memory for the owner.
 	 */
 	if (call->a_args.lock.oh.data != (u8 *) call->a_owner) {
 		kfree(call->a_args.lock.oh.data);
 	}
+	if (fl->fl_ops && fl->fl_ops->fl_release_private)
+		fl->fl_ops->fl_release_private(fl);
 }
 
 /*
@@ -165,6 +251,8 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl)
 	}
 	call->a_host = host;
 
+	nlmclnt_locks_init_private(fl, host);
+
 	/* Set up the argument struct */
 	nlmclnt_setlockargs(call, fl);
 
@@ -179,9 +267,6 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl)
 	else
 		status = -EINVAL;
 
-	if (status < 0 && (call->a_flags & RPC_TASK_ASYNC))
-		kfree(call);
-
  out_restore:
 	spin_lock_irqsave(&current->sighand->siglock, flags);
 	current->blocked = oldset;
@@ -382,7 +467,9 @@ nlmclnt_test(struct nlm_rqst *req, struct file_lock *fl)
 {
 	int	status;
 
-	if ((status = nlmclnt_call(req, NLMPROC_TEST)) < 0)
+	status = nlmclnt_call(req, NLMPROC_TEST);
+	nlmclnt_release_lockargs(req);
+	if (status < 0)
 		return status;
 
 	status = req->a_res.status;
@@ -391,10 +478,9 @@ nlmclnt_test(struct nlm_rqst *req, struct file_lock *fl)
 	} if (status == NLM_LCK_DENIED) {
 		/*
 		 * Report the conflicting lock back to the application.
-		 * FIXME: Is it OK to report the pid back as well?
 		 */
 		locks_copy_lock(fl, &req->a_res.lock.fl);
-		/* fl->fl_pid = 0; */
+		fl->fl_pid = 0;
 	} else {
 		return nlm_stat_to_errno(req->a_res.status);
 	}
@@ -402,18 +488,30 @@ nlmclnt_test(struct nlm_rqst *req, struct file_lock *fl)
 	return 0;
 }
 
-static
-void nlmclnt_insert_lock_callback(struct file_lock *fl)
+static void nlmclnt_locks_copy_lock(struct file_lock *new, struct file_lock *fl)
 {
-	nlm_get_host(fl->fl_u.nfs_fl.host);
+	memcpy(&new->fl_u.nfs_fl, &fl->fl_u.nfs_fl, sizeof(new->fl_u.nfs_fl));
+	nlm_get_lockowner(new->fl_u.nfs_fl.owner);
 }
-static
-void nlmclnt_remove_lock_callback(struct file_lock *fl)
+
+static void nlmclnt_locks_release_private(struct file_lock *fl)
 {
-	if (fl->fl_u.nfs_fl.host) {
-		nlm_release_host(fl->fl_u.nfs_fl.host);
-		fl->fl_u.nfs_fl.host = NULL;
-	}
+	nlm_put_lockowner(fl->fl_u.nfs_fl.owner);
+	fl->fl_ops = NULL;
+}
+
+static struct file_lock_operations nlmclnt_lock_ops = {
+	.fl_copy_lock = nlmclnt_locks_copy_lock,
+	.fl_release_private = nlmclnt_locks_release_private,
+};
+
+static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host)
+{
+	BUG_ON(fl->fl_ops != NULL);
+	fl->fl_u.nfs_fl.state = 0;
+	fl->fl_u.nfs_fl.flags = 0;
+	fl->fl_u.nfs_fl.owner = nlm_find_lockowner(host, fl->fl_owner);
+	fl->fl_ops = &nlmclnt_lock_ops;
 }
 
 /*
@@ -446,7 +544,8 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
 	if (!host->h_monitored && nsm_monitor(host) < 0) {
 		printk(KERN_NOTICE "lockd: failed to monitor %s\n",
 					host->h_name);
-		return -ENOLCK;
+		status = -ENOLCK;
+		goto out;
 	}
 
 	do {
@@ -456,18 +555,21 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
 			status = nlmclnt_block(host, fl, &resp->status);
 		}
 		if (status < 0)
-			return status;
+			goto out;
 	} while (resp->status == NLM_LCK_BLOCKED && req->a_args.block);
 
 	if (resp->status == NLM_LCK_GRANTED) {
 		fl->fl_u.nfs_fl.state = host->h_state;
 		fl->fl_u.nfs_fl.flags |= NFS_LCK_GRANTED;
-		fl->fl_u.nfs_fl.host = host;
-		fl->fl_insert = nlmclnt_insert_lock_callback;
-		fl->fl_remove = nlmclnt_remove_lock_callback;
+		fl->fl_flags |= FL_SLEEP;
+		if (posix_lock_file_wait(fl->fl_file, fl) < 0)
+				printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
+						__FUNCTION__);
 	}
-
-	return nlm_stat_to_errno(resp->status);
+	status = nlm_stat_to_errno(resp->status);
+out:
+	nlmclnt_release_lockargs(req);
+	return status;
 }
 
 /*
@@ -527,13 +629,24 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
 	fl->fl_u.nfs_fl.flags &= ~NFS_LCK_GRANTED;
 
 	if (req->a_flags & RPC_TASK_ASYNC) {
-		return nlmclnt_async_call(req, NLMPROC_UNLOCK,
+		status = nlmclnt_async_call(req, NLMPROC_UNLOCK,
 					nlmclnt_unlock_callback);
+		/* Hrmf... Do the unlock early since locks_remove_posix()
+		 * really expects us to free the lock synchronously */
+		posix_lock_file(fl->fl_file, fl);
+		if (status < 0) {
+			nlmclnt_release_lockargs(req);
+			kfree(req);
+		}
+		return status;
 	}
 
-	if ((status = nlmclnt_call(req, NLMPROC_UNLOCK)) < 0)
+	status = nlmclnt_call(req, NLMPROC_UNLOCK);
+	nlmclnt_release_lockargs(req);
+	if (status < 0)
 		return status;
 
+	posix_lock_file(fl->fl_file, fl);
 	if (resp->status == NLM_LCK_GRANTED)
 		return 0;
 
@@ -564,9 +677,9 @@ nlmclnt_unlock_callback(struct rpc_task *task)
 	}
 	if (status != NLM_LCK_GRANTED)
 		printk(KERN_WARNING "lockd: unexpected unlock status: %d\n", status);
-
 die:
 	nlm_release_host(req->a_host);
+	nlmclnt_release_lockargs(req);
 	kfree(req);
 	return;
  retry_rebind:
@@ -605,8 +718,10 @@ nlmclnt_cancel(struct nlm_host *host, struct file_lock *fl)
 
 	status = nlmclnt_async_call(req, NLMPROC_CANCEL,
 					nlmclnt_cancel_callback);
-	if (status < 0)
+	if (status < 0) {
+		nlmclnt_release_lockargs(req);
 		kfree(req);
+	}
 
 	spin_lock_irqsave(&current->sighand->siglock, flags);
 	current->blocked = oldset;
@@ -648,6 +763,7 @@ nlmclnt_cancel_callback(struct rpc_task *task)
 
 die:
 	nlm_release_host(req->a_host);
+	nlmclnt_release_lockargs(req);
 	kfree(req);
 	return;
 
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 6bf6befe6..fc4f414a8 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -119,13 +119,15 @@ nlm_lookup_host(int server, struct sockaddr_in *sin,
 	init_MUTEX(&host->h_sema);
 	host->h_nextrebind = jiffies + NLM_HOST_REBIND;
 	host->h_expires    = jiffies + NLM_HOST_EXPIRE;
-	host->h_count      = 1;
+	atomic_set(&host->h_count, 1);
 	init_waitqueue_head(&host->h_gracewait);
 	host->h_state      = 0;			/* pseudo NSM state */
 	host->h_nsmstate   = 0;			/* real NSM state */
 	host->h_server	   = server;
 	host->h_next       = nlm_hosts[hash];
 	nlm_hosts[hash]    = host;
+	INIT_LIST_HEAD(&host->h_lockowners);
+	spin_lock_init(&host->h_lock);
 
 	if (++nrhosts > NLM_HOST_MAX)
 		next_gc = 0;
@@ -235,7 +237,7 @@ struct nlm_host * nlm_get_host(struct nlm_host *host)
 {
 	if (host) {
 		dprintk("lockd: get host %s\n", host->h_name);
-		host->h_count ++;
+		atomic_inc(&host->h_count);
 		host->h_expires = jiffies + NLM_HOST_EXPIRE;
 	}
 	return host;
@@ -246,9 +248,10 @@ struct nlm_host * nlm_get_host(struct nlm_host *host)
  */
 void nlm_release_host(struct nlm_host *host)
 {
-	if (host && host->h_count) {
+	if (host != NULL) {
 		dprintk("lockd: release host %s\n", host->h_name);
-		host->h_count --;
+		atomic_dec(&host->h_count);
+		BUG_ON(atomic_read(&host->h_count) < 0);
 	}
 }
 
@@ -283,7 +286,7 @@ nlm_shutdown_hosts(void)
 		for (i = 0; i < NLM_HOST_NRHASH; i++) {
 			for (host = nlm_hosts[i]; host; host = host->h_next) {
 				dprintk("       %s (cnt %d use %d exp %ld)\n",
-					host->h_name, host->h_count,
+					host->h_name, atomic_read(&host->h_count),
 					host->h_inuse, host->h_expires);
 			}
 		}
@@ -314,10 +317,10 @@ nlm_gc_hosts(void)
 	for (i = 0; i < NLM_HOST_NRHASH; i++) {
 		q = &nlm_hosts[i];
 		while ((host = *q) != NULL) {
-			if (host->h_count || host->h_inuse
+			if (atomic_read(&host->h_count) || host->h_inuse
 			 || time_before(jiffies, host->h_expires)) {
 				dprintk("nlm_gc_hosts skipping %s (cnt %d use %d exp %ld)\n",
-					host->h_name, host->h_count,
+					host->h_name, atomic_read(&host->h_count),
 					host->h_inuse, host->h_expires);
 				q = &host->h_next;
 				continue;
@@ -336,6 +339,7 @@ nlm_gc_hosts(void)
 					rpc_destroy_client(host->h_rpcclnt);
 				}
 			}
+			BUG_ON(!list_empty(&host->h_lockowners));
 			kfree(host);
 			nrhosts--;
 		}
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 47c77137b..1bc0676a4 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -409,13 +409,13 @@ MODULE_DESCRIPTION("NFS file locking service version " LOCKD_VERSION ".");
 MODULE_LICENSE("GPL");
 
 module_param_call(nlm_grace_period, param_set_grace_period, param_get_ulong,
-		  &nlm_grace_period, 644);
+		  &nlm_grace_period, 0644);
 module_param_call(nlm_timeout, param_set_timeout, param_get_ulong,
-		  &nlm_timeout, 644);
+		  &nlm_timeout, 0644);
 module_param_call(nlm_udpport, param_set_port, param_get_int,
-		  &nlm_udpport, 644);
+		  &nlm_udpport, 0644);
 module_param_call(nlm_tcpport, param_set_port, param_get_int,
-		  &nlm_tcpport, 644);
+		  &nlm_tcpport, 0644);
 
 /*
  * Initialising and terminating the module.
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index a3d3b78f7..3afa2659b 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -53,8 +53,9 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
 		*filp = file;
 
 		/* Set up the missing parts of the file_lock structure */
-		lock->fl.fl_file  = &file->f_file;
+		lock->fl.fl_file  = file->f_file;
 		lock->fl.fl_owner = (fl_owner_t) host;
+		lock->fl.fl_lmops = &nlmsvc_lock_operations;
 	}
 
 	return 0;
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 2addc9200..80e7cc4d4 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -42,7 +42,6 @@
 static void	nlmsvc_insert_block(struct nlm_block *block, unsigned long);
 static int	nlmsvc_remove_block(struct nlm_block *block);
 static void	nlmsvc_grant_callback(struct rpc_task *task);
-static void	nlmsvc_notify_blocked(struct file_lock *);
 
 /*
  * The list of blocked locks to retry
@@ -193,7 +192,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file,
 		goto failed_free;
 
 	/* Set notifier function for VFS, and init args */
-	block->b_call.a_args.lock.fl.fl_notify = nlmsvc_notify_blocked;
+	block->b_call.a_args.lock.fl.fl_lmops = &nlmsvc_lock_operations;
 	block->b_call.a_args.cookie = *cookie;	/* see above */
 
 	dprintk("lockd: created block %p...\n", block);
@@ -238,8 +237,13 @@ nlmsvc_delete_block(struct nlm_block *block, int unlock)
 
 	/* Remove block from list */
 	nlmsvc_remove_block(block);
-	posix_unblock_lock(&file->f_file, fl);
-	block->b_granted = 0;
+	if (fl->fl_next)
+		posix_unblock_lock(file->f_file, fl);
+	if (unlock) {
+		fl->fl_type = F_UNLCK;
+		posix_lock_file(file->f_file, fl);
+		block->b_granted = 0;
+	}
 
 	/* If the block is in the middle of a GRANT callback,
 	 * don't kill it yet. */
@@ -299,8 +303,8 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
 	int			error;
 
 	dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n",
-				file->f_file.f_dentry->d_inode->i_sb->s_id,
-				file->f_file.f_dentry->d_inode->i_ino,
+				file->f_file->f_dentry->d_inode->i_sb->s_id,
+				file->f_file->f_dentry->d_inode->i_ino,
 				lock->fl.fl_type, lock->fl.fl_pid,
 				(long long)lock->fl.fl_start,
 				(long long)lock->fl.fl_end,
@@ -316,8 +320,8 @@ again:
 	/* Lock file against concurrent access */
 	down(&file->f_sema);
 
-	if (!(conflock = posix_test_lock(&file->f_file, &lock->fl))) {
-		error = posix_lock_file(&file->f_file, &lock->fl);
+	if (!(conflock = posix_test_lock(file->f_file, &lock->fl))) {
+		error = posix_lock_file(file->f_file, &lock->fl);
 
 		if (block)
 			nlmsvc_delete_block(block, 0);
@@ -382,13 +386,13 @@ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock,
 	struct file_lock	*fl;
 
 	dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n",
-				file->f_file.f_dentry->d_inode->i_sb->s_id,
-				file->f_file.f_dentry->d_inode->i_ino,
+				file->f_file->f_dentry->d_inode->i_sb->s_id,
+				file->f_file->f_dentry->d_inode->i_ino,
 				lock->fl.fl_type,
 				(long long)lock->fl.fl_start,
 				(long long)lock->fl.fl_end);
 
-	if ((fl = posix_test_lock(&file->f_file, &lock->fl)) != NULL) {
+	if ((fl = posix_test_lock(file->f_file, &lock->fl)) != NULL) {
 		dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n",
 				fl->fl_type, (long long)fl->fl_start,
 				(long long)fl->fl_end);
@@ -414,8 +418,8 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock)
 	int	error;
 
 	dprintk("lockd: nlmsvc_unlock(%s/%ld, pi=%d, %Ld-%Ld)\n",
-				file->f_file.f_dentry->d_inode->i_sb->s_id,
-				file->f_file.f_dentry->d_inode->i_ino,
+				file->f_file->f_dentry->d_inode->i_sb->s_id,
+				file->f_file->f_dentry->d_inode->i_ino,
 				lock->fl.fl_pid,
 				(long long)lock->fl.fl_start,
 				(long long)lock->fl.fl_end);
@@ -424,7 +428,7 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock)
 	nlmsvc_cancel_blocked(file, lock);
 
 	lock->fl.fl_type = F_UNLCK;
-	error = posix_lock_file(&file->f_file, &lock->fl);
+	error = posix_lock_file(file->f_file, &lock->fl);
 
 	return (error < 0)? nlm_lck_denied_nolocks : nlm_granted;
 }
@@ -442,8 +446,8 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
 	struct nlm_block	*block;
 
 	dprintk("lockd: nlmsvc_cancel(%s/%ld, pi=%d, %Ld-%Ld)\n",
-				file->f_file.f_dentry->d_inode->i_sb->s_id,
-				file->f_file.f_dentry->d_inode->i_ino,
+				file->f_file->f_dentry->d_inode->i_sb->s_id,
+				file->f_file->f_dentry->d_inode->i_ino,
 				lock->fl.fl_pid,
 				(long long)lock->fl.fl_start,
 				(long long)lock->fl.fl_end);
@@ -479,6 +483,16 @@ nlmsvc_notify_blocked(struct file_lock *fl)
 	printk(KERN_WARNING "lockd: notification for unknown block!\n");
 }
 
+static int nlmsvc_same_owner(struct file_lock *fl1, struct file_lock *fl2)
+{
+	return fl1->fl_owner == fl2->fl_owner && fl1->fl_pid == fl2->fl_pid;
+}
+
+struct lock_manager_operations nlmsvc_lock_operations = {
+	.fl_compare_owner = nlmsvc_same_owner,
+	.fl_notify = nlmsvc_notify_blocked,
+};
+
 /*
  * Try to claim a lock that was previously blocked.
  *
@@ -515,7 +529,7 @@ nlmsvc_grant_blocked(struct nlm_block *block)
 	}
 
 	/* Try the lock operation again */
-	if ((conflock = posix_test_lock(&file->f_file, &lock->fl)) != NULL) {
+	if ((conflock = posix_test_lock(file->f_file, &lock->fl)) != NULL) {
 		/* Bummer, we blocked again */
 		dprintk("lockd: lock still blocked\n");
 		nlmsvc_insert_block(block, NLM_NEVER);
@@ -528,7 +542,7 @@ nlmsvc_grant_blocked(struct nlm_block *block)
 	 * following yields an error, this is most probably due to low
 	 * memory. Retry the lock in a few seconds.
 	 */
-	if ((error = posix_lock_file(&file->f_file, &lock->fl)) < 0) {
+	if ((error = posix_lock_file(file->f_file, &lock->fl)) < 0) {
 		printk(KERN_WARNING "lockd: unexpected error %d in %s!\n",
 				-error, __FUNCTION__);
 		nlmsvc_insert_block(block, 10 * HZ);
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index b676e8ccd..3eca6cfdb 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -82,8 +82,9 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
 		*filp = file;
 
 		/* Set up the missing parts of the file_lock structure */
-		lock->fl.fl_file  = &file->f_file;
+		lock->fl.fl_file  = file->f_file;
 		lock->fl.fl_owner = (fl_owner_t) host;
+		lock->fl.fl_lmops = &nlmsvc_lock_operations;
 	}
 
 	return 0;
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index 0be7f080e..de7536358 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -67,7 +67,7 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
 	down(&nlm_file_sema);
 
 	for (file = nlm_files[hash]; file; file = file->f_next)
-		if (!memcmp(&file->f_handle, f, sizeof(*f)))
+		if (!nfs_compare_fh(&file->f_handle, f))
 			goto found;
 
 	dprintk("lockd: creating file for (%08x %08x %08x %08x %08x %08x)\n",
@@ -124,7 +124,7 @@ out_free:
 static inline void
 nlm_delete_file(struct nlm_file *file)
 {
-	struct inode *inode = file->f_file.f_dentry->d_inode;
+	struct inode *inode = file->f_file->f_dentry->d_inode;
 	struct nlm_file	**fp, *f;
 
 	dprintk("lockd: closing file %s/%ld\n",
@@ -133,7 +133,7 @@ nlm_delete_file(struct nlm_file *file)
 	while ((f = *fp) != NULL) {
 		if (f == file) {
 			*fp = file->f_next;
-			nlmsvc_ops->fclose(&file->f_file);
+			nlmsvc_ops->fclose(file->f_file);
 			kfree(file);
 			return;
 		}
@@ -176,7 +176,7 @@ again:
 			lock.fl_type  = F_UNLCK;
 			lock.fl_start = 0;
 			lock.fl_end   = OFFSET_MAX;
-			if (posix_lock_file(&file->f_file, &lock) < 0) {
+			if (posix_lock_file(file->f_file, &lock) < 0) {
 				printk("lockd: unlock failure in %s:%d\n",
 						__FILE__, __LINE__);
 				return 1;
@@ -230,7 +230,7 @@ nlm_traverse_files(struct nlm_host *host, int action)
 			if (!file->f_blocks && !file->f_locks
 			 && !file->f_shares && !file->f_count) {
 				*fp = file->f_next;
-				nlmsvc_ops->fclose(&file->f_file);
+				nlmsvc_ops->fclose(file->f_file);
 				kfree(file);
 			} else {
 				fp = &file->f_next;
diff --git a/fs/locks.c b/fs/locks.c
index 0204acb9f..47efea9a6 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -167,6 +167,13 @@ static inline void locks_free_lock(struct file_lock *fl)
 	if (!list_empty(&fl->fl_link))
 		panic("Attempting to free lock on active lock list");
 
+	if (fl->fl_ops) {
+		if (fl->fl_ops->fl_release_private)
+			fl->fl_ops->fl_release_private(fl);
+		fl->fl_ops = NULL;
+	}
+	fl->fl_lmops = NULL;
+
 	kmem_cache_free(filelock_cache, fl);
 }
 
@@ -183,9 +190,8 @@ void locks_init_lock(struct file_lock *fl)
 	fl->fl_flags = 0;
 	fl->fl_type = 0;
 	fl->fl_start = fl->fl_end = 0;
-	fl->fl_notify = NULL;
-	fl->fl_insert = NULL;
-	fl->fl_remove = NULL;
+	fl->fl_ops = NULL;
+	fl->fl_lmops = NULL;
 }
 
 EXPORT_SYMBOL(locks_init_lock);
@@ -217,10 +223,10 @@ void locks_copy_lock(struct file_lock *new, struct file_lock *fl)
 	new->fl_type = fl->fl_type;
 	new->fl_start = fl->fl_start;
 	new->fl_end = fl->fl_end;
-	new->fl_notify = fl->fl_notify;
-	new->fl_insert = fl->fl_insert;
-	new->fl_remove = fl->fl_remove;
-	new->fl_u = fl->fl_u;
+	new->fl_ops = fl->fl_ops;
+	new->fl_lmops = fl->fl_lmops;
+	if (fl->fl_ops && fl->fl_ops->fl_copy_lock)
+		fl->fl_ops->fl_copy_lock(new, fl);
 }
 
 EXPORT_SYMBOL(locks_copy_lock);
@@ -321,9 +327,8 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
 	fl->fl_pid = current->tgid;
 	fl->fl_file = filp;
 	fl->fl_flags = FL_POSIX;
-	fl->fl_notify = NULL;
-	fl->fl_insert = NULL;
-	fl->fl_remove = NULL;
+	fl->fl_ops = NULL;
+	fl->fl_lmops = NULL;
 
 	return assign_type(fl, l->l_type);
 }
@@ -361,9 +366,8 @@ static int flock64_to_posix_lock(struct file *filp, struct file_lock *fl,
 	fl->fl_pid = current->tgid;
 	fl->fl_file = filp;
 	fl->fl_flags = FL_POSIX;
-	fl->fl_notify = NULL;
-	fl->fl_insert = NULL;
-	fl->fl_remove = NULL;
+	fl->fl_ops = NULL;
+	fl->fl_lmops = NULL;
 
 	switch (l->l_type) {
 	case F_RDLCK:
@@ -397,9 +401,8 @@ static int lease_alloc(struct file *filp, int type, struct file_lock **flp)
 	}
 	fl->fl_start = 0;
 	fl->fl_end = OFFSET_MAX;
-	fl->fl_notify = NULL;
-	fl->fl_insert = NULL;
-	fl->fl_remove = NULL;
+	fl->fl_ops = NULL;
+	fl->fl_lmops = NULL;
 
 	*flp = fl;
 	return 0;
@@ -414,14 +417,15 @@ static inline int locks_overlap(struct file_lock *fl1, struct file_lock *fl2)
 }
 
 /*
- * Check whether two locks have the same owner.  The apparently superfluous
- * check for fl_pid enables us to distinguish between locks set by lockd.
+ * Check whether two locks have the same owner.
  */
 static inline int
 posix_same_owner(struct file_lock *fl1, struct file_lock *fl2)
 {
-	return (fl1->fl_owner == fl2->fl_owner) &&
-		(fl1->fl_pid == fl2->fl_pid);
+	if (fl1->fl_lmops && fl1->fl_lmops->fl_compare_owner)
+		return fl2->fl_lmops == fl1->fl_lmops &&
+			fl1->fl_lmops->fl_compare_owner(fl1, fl2);
+	return fl1->fl_owner == fl2->fl_owner;
 }
 
 /* Remove waiter from blocker's block list.
@@ -459,7 +463,8 @@ static void locks_insert_block(struct file_lock *blocker,
 	}
 	list_add_tail(&waiter->fl_block, &blocker->fl_block);
 	waiter->fl_next = blocker;
-	list_add(&waiter->fl_link, &blocked_list);
+	if (IS_POSIX(blocker))
+		list_add(&waiter->fl_link, &blocked_list);
 }
 
 /* Wake up processes blocked waiting for blocker.
@@ -472,8 +477,8 @@ static void locks_wake_up_blocks(struct file_lock *blocker)
 		struct file_lock *waiter = list_entry(blocker->fl_block.next,
 				struct file_lock, fl_block);
 		__locks_delete_block(waiter);
-		if (waiter->fl_notify)
-			waiter->fl_notify(waiter);
+		if (waiter->fl_lmops && waiter->fl_lmops->fl_notify)
+			waiter->fl_lmops->fl_notify(waiter);
 		else
 			wake_up(&waiter->fl_wait);
 	}
@@ -490,8 +495,8 @@ static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl)
 	fl->fl_next = *pos;
 	*pos = fl;
 
-	if (fl->fl_insert)
-		fl->fl_insert(fl);
+	if (fl->fl_ops && fl->fl_ops->fl_insert)
+		fl->fl_ops->fl_insert(fl);
 }
 
 /*
@@ -514,8 +519,8 @@ static void locks_delete_lock(struct file_lock **thisfl_p)
 		fl->fl_fasync = NULL;
 	}
 
-	if (fl->fl_remove)
-		fl->fl_remove(fl);
+	if (fl->fl_ops && fl->fl_ops->fl_remove)
+		fl->fl_ops->fl_remove(fl);
 
 	locks_wake_up_blocks(fl);
 	locks_free_lock(fl);
@@ -631,24 +636,15 @@ int posix_locks_deadlock(struct file_lock *caller_fl,
 				struct file_lock *block_fl)
 {
 	struct list_head *tmp;
-	fl_owner_t caller_owner, blocked_owner;
-	unsigned int	 caller_pid, blocked_pid;
-
-	caller_owner = caller_fl->fl_owner;
-	caller_pid = caller_fl->fl_pid;
-	blocked_owner = block_fl->fl_owner;
-	blocked_pid = block_fl->fl_pid;
 
 next_task:
-	if (caller_owner == blocked_owner && caller_pid == blocked_pid)
+	if (posix_same_owner(caller_fl, block_fl))
 		return 1;
 	list_for_each(tmp, &blocked_list) {
 		struct file_lock *fl = list_entry(tmp, struct file_lock, fl_link);
-		if ((fl->fl_owner == blocked_owner)
-		    && (fl->fl_pid == blocked_pid)) {
+		if (posix_same_owner(fl, block_fl)) {
 			fl = fl->fl_next;
-			blocked_owner = fl->fl_owner;
-			blocked_pid = fl->fl_pid;
+			block_fl = fl;
 			goto next_task;
 		}
 	}
@@ -911,6 +907,34 @@ int posix_lock_file(struct file *filp, struct file_lock *fl)
 	return __posix_lock_file(filp->f_dentry->d_inode, fl);
 }
 
+/**
+ * posix_lock_file_wait - Apply a POSIX-style lock to a file
+ * @filp: The file to apply the lock to
+ * @fl: The lock to be applied
+ *
+ * Add a POSIX style lock to a file.
+ * We merge adjacent & overlapping locks whenever possible.
+ * POSIX locks are sorted by owner task, then by starting address
+ */
+int posix_lock_file_wait(struct file *filp, struct file_lock *fl)
+{
+	int error;
+	might_sleep ();
+	for (;;) {
+		error = __posix_lock_file(filp->f_dentry->d_inode, fl);
+		if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP))
+			break;
+		error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
+		if (!error)
+			continue;
+
+		locks_delete_block(fl);
+		break;
+	}
+	return error;
+}
+EXPORT_SYMBOL(posix_lock_file_wait);
+
 /**
  * locks_mandatory_locked - Check for an active lock
  * @inode: the file to check
@@ -1294,6 +1318,33 @@ out_unlock:
 	return error;
 }
 
+/**
+ * flock_lock_file_wait - Apply a FLOCK-style lock to a file
+ * @filp: The file to apply the lock to
+ * @fl: The lock to be applied
+ *
+ * Add a FLOCK style lock to a file.
+ */
+int flock_lock_file_wait(struct file *filp, struct file_lock *fl)
+{
+	int error;
+	might_sleep();
+	for (;;) {
+		error = flock_lock_file(filp, fl);
+		if ((error != -EAGAIN) || !(fl->fl_flags & FL_SLEEP))
+			break;
+		error = wait_event_interruptible(fl->fl_wait, !fl->fl_next);
+		if (!error)
+			continue;
+
+		locks_delete_block(fl);
+		break;
+	}
+	return error;
+}
+
+EXPORT_SYMBOL(flock_lock_file_wait);
+
 /**
  *	sys_flock: - flock() system call.
  *	@fd: the file descriptor to lock.
@@ -1342,17 +1393,12 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd)
 	if (error)
 		goto out_free;
 
-	for (;;) {
-		error = flock_lock_file(filp, lock);
-		if ((error != -EAGAIN) || !can_sleep)
-			break;
-		error = wait_event_interruptible(lock->fl_wait, !lock->fl_next);
-		if (!error)
-			continue;
-
-		locks_delete_block(lock);
-		break;
-	}
+	if (filp->f_op && filp->f_op->flock)
+		error = filp->f_op->flock(filp,
+					  (can_sleep) ? F_SETLKW : F_SETLK,
+					  lock);
+	else
+		error = flock_lock_file_wait(filp, lock);
 
  out_free:
 	if (list_empty(&lock->fl_link)) {
@@ -1422,7 +1468,6 @@ int fcntl_getlk(struct file *filp, struct flock __user *l)
 	error = -EFAULT;
 	if (!copy_to_user(l, &flock, sizeof(flock)))
 		error = 0;
-  
 out:
 	return error;
 }
@@ -1489,8 +1534,7 @@ int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock __user *l)
 
 	if (filp->f_op && filp->f_op->lock != NULL) {
 		error = filp->f_op->lock(filp, cmd, file_lock);
-		if (error < 0)
-			goto out;
+		goto out;
 	}
 
 	for (;;) {
@@ -1624,8 +1668,7 @@ int fcntl_setlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l)
 
 	if (filp->f_op && filp->f_op->lock != NULL) {
 		error = filp->f_op->lock(filp, cmd, file_lock);
-		if (error < 0)
-			goto out;
+		goto out;
 	}
 
 	for (;;) {
@@ -1672,10 +1715,12 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
 	lock.fl_owner = owner;
 	lock.fl_pid = current->tgid;
 	lock.fl_file = filp;
+	lock.fl_ops = NULL;
+	lock.fl_lmops = NULL;
 
 	if (filp->f_op && filp->f_op->lock != NULL) {
 		filp->f_op->lock(filp, F_SETLK, &lock);
-		/* Ignore any error -- we must remove the locks anyway */
+		goto out;
 	}
 
 	/* Can't use posix_lock_file here; we need to remove it no matter
@@ -1684,13 +1729,16 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner)
 	lock_kernel();
 	while (*before != NULL) {
 		struct file_lock *fl = *before;
-		if (IS_POSIX(fl) && (fl->fl_owner == owner)) {
+		if (IS_POSIX(fl) && posix_same_owner(fl, &lock)) {
 			locks_delete_lock(before);
 			continue;
 		}
 		before = &fl->fl_next;
 	}
 	unlock_kernel();
+out:
+	if (lock.fl_ops && lock.fl_ops->fl_release_private)
+		lock.fl_ops->fl_release_private(&lock);
 }
 
 EXPORT_SYMBOL(locks_remove_posix);
@@ -1707,12 +1755,23 @@ void locks_remove_flock(struct file *filp)
 	if (!inode->i_flock)
 		return;
 
+	if (filp->f_op && filp->f_op->flock) {
+		struct file_lock fl = { .fl_flags = FL_FLOCK,
+					.fl_type = F_UNLCK };
+		filp->f_op->flock(filp, F_SETLKW, &fl);
+	}
+
 	lock_kernel();
 	before = &inode->i_flock;
 
 	while ((fl = *before) != NULL) {
 		if (fl->fl_file == filp) {
-			if (IS_FLOCK(fl)) {
+			/*
+			 * We might have a POSIX lock that was created at the same time
+			 * the filp was closed for the last time. Just remove that too,
+			 * regardless of ownership, since nobody can own it.
+			 */
+			if (IS_FLOCK(fl) || IS_POSIX(fl)) {
 				locks_delete_lock(before);
 				continue;
 			}
@@ -1720,9 +1779,7 @@ void locks_remove_flock(struct file *filp)
 				lease_modify(before, F_UNLCK);
 				continue;
 			}
-			/* FL_POSIX locks of this process have already been
-			 * removed in filp_close->locks_remove_posix.
-			 */
+			/* What? */
 			BUG();
  		}
 		before = &fl->fl_next;
@@ -2038,4 +2095,4 @@ static int __init filelock_init(void)
 	return 0;
 }
 
-module_init(filelock_init)
+core_initcall(filelock_init);
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 9295de94d..3f18c2119 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -18,7 +18,7 @@
 #include <linux/vfs.h>
 
 static void minix_read_inode(struct inode * inode);
-static void minix_write_inode(struct inode * inode, int wait);
+static int minix_write_inode(struct inode * inode, int wait);
 static int minix_statfs(struct super_block *sb, struct kstatfs *buf);
 static int minix_remount (struct super_block * sb, int * flags, char * data);
 
@@ -79,7 +79,7 @@ static int init_inodecache(void)
 {
 	minix_inode_cachep = kmem_cache_create("minix_inode_cache",
 					     sizeof(struct minix_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (minix_inode_cachep == NULL)
 		return -ENOMEM;
@@ -505,9 +505,10 @@ static struct buffer_head *minix_update_inode(struct inode *inode)
 		return V2_minix_update_inode(inode);
 }
 
-static void minix_write_inode(struct inode * inode, int wait)
+static int minix_write_inode(struct inode * inode, int wait)
 {
 	brelse(minix_update_inode(inode));
+	return 0;
 }
 
 int minix_sync_inode(struct inode * inode)
diff --git a/fs/minix/itree_common.c b/fs/minix/itree_common.c
index f8e9bd831..5a4b51dbf 100644
--- a/fs/minix/itree_common.c
+++ b/fs/minix/itree_common.c
@@ -358,5 +358,5 @@ static inline unsigned nblocks(loff_t size)
 		res += blocks;
 		direct = 1;
 	}
-	return blocks;
+	return res;
 }
diff --git a/fs/mpage.c b/fs/mpage.c
index 71c7ca3a4..4bbf15ee9 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -290,7 +290,8 @@ do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages,
 alloc_new:
 	if (bio == NULL) {
 		bio = mpage_alloc(bdev, blocks[0] << (blkbits - 9),
-					nr_pages, GFP_KERNEL);
+			  	min_t(int, nr_pages, bio_get_nr_vecs(bdev)),
+				GFP_KERNEL);
 		if (bio == NULL)
 			goto confused;
 	}
@@ -627,7 +628,9 @@ mpage_writepages(struct address_space *mapping,
 	struct pagevec pvec;
 	int nr_pages;
 	pgoff_t index;
+	pgoff_t end = -1;		/* Inclusive */
 	int scanned = 0;
+	int is_range = 0;
 
 	if (wbc->nonblocking && bdi_write_congested(bdi)) {
 		wbc->encountered_congestion = 1;
@@ -645,9 +648,17 @@ mpage_writepages(struct address_space *mapping,
 		index = 0;			  /* whole-file sweep */
 		scanned = 1;
 	}
+	if (wbc->start || wbc->end) {
+		index = wbc->start >> PAGE_CACHE_SHIFT;
+		end = wbc->end >> PAGE_CACHE_SHIFT;
+		is_range = 1;
+		scanned = 1;
+	}
 retry:
-	while (!done && (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
-					PAGECACHE_TAG_DIRTY, PAGEVEC_SIZE))) {
+	while (!done && (index <= end) &&
+			(nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
+			PAGECACHE_TAG_DIRTY,
+			min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1))) {
 		unsigned i;
 
 		scanned = 1;
@@ -664,10 +675,21 @@ retry:
 
 			lock_page(page);
 
+			if (unlikely(page->mapping != mapping)) {
+				unlock_page(page);
+				continue;
+			}
+
+			if (unlikely(is_range) && page->index > end) {
+				done = 1;
+				unlock_page(page);
+				continue;
+			}
+
 			if (wbc->sync_mode != WB_SYNC_NONE)
 				wait_on_page_writeback(page);
 
-			if (page->mapping != mapping || PageWriteback(page) ||
+			if (PageWriteback(page) ||
 					!clear_page_dirty_for_io(page)) {
 				unlock_page(page);
 				continue;
@@ -706,7 +728,8 @@ retry:
 		index = 0;
 		goto retry;
 	}
-	mapping->writeback_index = index;
+	if (!is_range)
+		mapping->writeback_index = index;
 	if (bio)
 		mpage_bio_submit(WRITE, bio);
 	return ret;
diff --git a/fs/namei.c b/fs/namei.c
index 8a1943d4f..aac450261 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -886,29 +886,31 @@ static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
 		return 0;		/* something went wrong... */
 
 	if (!nd->dentry->d_inode || S_ISDIR(nd->dentry->d_inode->i_mode)) {
-		struct nameidata nd_root;
+		struct dentry *old_dentry = nd->dentry;
+		struct vfsmount *old_mnt = nd->mnt;
+		struct qstr last = nd->last;
+		int last_type = nd->last_type;
 		/*
 		 * NAME was not found in alternate root or it's a directory.  Try to find
 		 * it in the normal root:
 		 */
-		nd_root.last_type = LAST_ROOT;
-		nd_root.flags = nd->flags;
-		nd_root.depth = 0;
-		memcpy(&nd_root.intent, &nd->intent, sizeof(nd_root.intent));
+		nd->last_type = LAST_ROOT;
 		read_lock(&current->fs->lock);
-		nd_root.mnt = mntget(current->fs->rootmnt);
-		nd_root.dentry = dget(current->fs->root);
+		nd->mnt = mntget(current->fs->rootmnt);
+		nd->dentry = dget(current->fs->root);
 		read_unlock(&current->fs->lock);
-		if (path_walk(name, &nd_root))
-			return 1;
-		if (nd_root.dentry->d_inode) {
+		if (path_walk(name, nd) == 0) {
+			if (nd->dentry->d_inode) {
+				dput(old_dentry);
+				mntput(old_mnt);
+				return 1;
+			}
 			path_release(nd);
-			nd->dentry = nd_root.dentry;
-			nd->mnt = nd_root.mnt;
-			nd->last = nd_root.last;
-			return 1;
 		}
-		path_release(&nd_root);
+		nd->dentry = old_dentry;
+		nd->mnt = old_mnt;
+		nd->last = last;
+		nd->last_type = last_type;
 	}
 	return 1;
 }
@@ -961,8 +963,7 @@ int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata
 		}
 		nd->mnt = mntget(current->fs->rootmnt);
 		nd->dentry = dget(current->fs->root);
-	}
-	else{
+	} else {
 		nd->mnt = mntget(current->fs->pwdmnt);
 		nd->dentry = dget(current->fs->pwd);
 	}
@@ -1112,8 +1113,12 @@ static inline int check_sticky(struct inode *dir, struct inode *inode)
 static inline int may_delete(struct inode *dir,struct dentry *victim,int isdir)
 {
 	int error;
-	if (!victim->d_inode || victim->d_parent->d_inode != dir)
+
+	if (!victim->d_inode)
 		return -ENOENT;
+
+	BUG_ON(victim->d_parent->d_inode != dir);
+
 	error = permission(dir,MAY_WRITE | MAY_EXEC, NULL);
 	if (error)
 		return error;
@@ -1677,7 +1682,7 @@ out:
  * if it cannot handle the case of removing a directory
  * that is still in use by something else..
  */
-static void d_unhash(struct dentry *dentry)
+void dentry_unhash(struct dentry *dentry)
 {
 	dget(dentry);
 	spin_lock(&dcache_lock);
@@ -1707,7 +1712,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
 	DQUOT_INIT(dir);
 
 	down(&dentry->d_inode->i_sem);
-	d_unhash(dentry);
+	dentry_unhash(dentry);
 	if (d_mountpoint(dentry))
 		error = -EBUSY;
 	else {
@@ -1838,13 +1843,12 @@ asmlinkage long sys_unlink(const char __user * pathname)
 		dput(dentry);
 	}
 	up(&nd.dentry->d_inode->i_sem);
+	if (inode)
+		iput(inode);	/* truncate the inode here */
 exit1:
 	path_release(&nd);
 exit:
 	putname(name);
-
-	if (inode)
-		iput(inode);	/* truncate the inode here */
 	return error;
 
 slashes:
@@ -2050,7 +2054,7 @@ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
 	target = new_dentry->d_inode;
 	if (target) {
 		down(&target->i_sem);
-		d_unhash(new_dentry);
+		dentry_unhash(new_dentry);
 	}
 	if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
 		error = -EBUSY;
@@ -2317,12 +2321,8 @@ int page_readlink(struct dentry *dentry, char __user *buffer, int buflen)
 int page_follow_link_light(struct dentry *dentry, struct nameidata *nd)
 {
 	struct page *page;
-	char *s = page_getlink(dentry, &page);
-	if (!IS_ERR(s)) {
-		nd_set_link(nd, s);
-		s = NULL;
-	}
-	return PTR_ERR(s);
+	nd_set_link(nd, page_getlink(dentry, &page));
+	return 0;
 }
 
 void page_put_link(struct dentry *dentry, struct nameidata *nd)
@@ -2428,4 +2428,5 @@ EXPORT_SYMBOL(vfs_rename);
 EXPORT_SYMBOL(vfs_rmdir);
 EXPORT_SYMBOL(vfs_symlink);
 EXPORT_SYMBOL(vfs_unlink);
+EXPORT_SYMBOL(dentry_unhash);
 EXPORT_SYMBOL(generic_readlink);
diff --git a/fs/namespace.c b/fs/namespace.c
index 9b7d73b2b..5a8b80085 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -22,6 +22,7 @@
 #include <linux/security.h>
 #include <linux/mount.h>
 #include <linux/vs_base.h>
+#include <linux/vserver/namespace.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -244,6 +245,8 @@ static int show_vfsmnt(struct seq_file *m, void *v)
 
 	if (vx_flags(VXF_HIDE_MOUNT, 0))
 		return 0;
+	if (!vx_check_vfsmount(current->vx_info, mnt))
+		return 0;
 
 	mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none");
 	seq_putc(m, ' ');
@@ -699,7 +702,7 @@ static int do_remount(struct nameidata *nd, int flags, int mnt_flags,
 	int err;
 	struct super_block * sb = nd->mnt->mnt_sb;
 
-	if (!capable(CAP_SYS_ADMIN))
+	if (!capable(CAP_SYS_ADMIN) && !vx_ccaps(VXC_SECURE_REMOUNT))
 		return -EPERM;
 
 	if (!check_mnt(nd->mnt))
@@ -708,6 +711,8 @@ static int do_remount(struct nameidata *nd, int flags, int mnt_flags,
 	if (nd->dentry != nd->mnt->mnt_root)
 		return -EINVAL;
 
+	if (vx_ccaps(VXC_SECURE_REMOUNT))
+		mnt_flags |= MNT_NODEV;
 	down_write(&sb->s_umount);
 	err = do_remount_sb(sb, flags, data, 0);
 	if (!err)
@@ -723,7 +728,7 @@ static int do_move_mount(struct nameidata *nd, char *old_name)
 	struct nameidata old_nd, parent_nd;
 	struct vfsmount *p;
 	int err = 0;
-	if (!capable(CAP_SYS_ADMIN))
+	if (!capable(CAP_SYS_ADMIN) && !vx_ccaps(VXC_SECURE_MOUNT))
 		return -EPERM;
 	if (!old_name || !*old_name)
 		return -EINVAL;
@@ -956,7 +961,35 @@ void mark_mounts_for_expiry(struct list_head *mounts)
 
 EXPORT_SYMBOL_GPL(mark_mounts_for_expiry);
 
-int copy_mount_options (const void __user *data, unsigned long *where)
+/*
+ * Some copy_from_user() implementations do not return the exact number of
+ * bytes remaining to copy on a fault.  But copy_mount_options() requires that.
+ * Note that this function differs from copy_from_user() in that it will oops
+ * on bad values of `to', rather than returning a short copy.
+ */
+static long
+exact_copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+	char *t = to;
+	const char __user *f = from;
+	char c;
+
+	if (!access_ok(VERIFY_READ, from, n))
+		return n;
+
+	while (n) {
+		if (__get_user(c, f)) {
+			memset(t, 0, n);
+			break;
+		}
+		*t++ = c;
+		f++;
+		n--;
+	}
+	return n;
+}
+
+int copy_mount_options(const void __user *data, unsigned long *where)
 {
 	int i;
 	unsigned long page;
@@ -978,7 +1011,7 @@ int copy_mount_options (const void __user *data, unsigned long *where)
 	if (size > PAGE_SIZE)
 		size = PAGE_SIZE;
 
-	i = size - copy_from_user((void *)page, data, size);
+	i = size - exact_copy_from_user((void *)page, data, size);
 	if (!i) {
 		free_page(page); 
 		return -EFAULT;
@@ -1076,7 +1109,7 @@ int copy_namespace(int flags, struct task_struct *tsk)
 	if (!(flags & CLONE_NEWNS))
 		return 0;
 
-	if (!capable(CAP_SYS_ADMIN)) {
+	if (!capable(CAP_SYS_ADMIN) && !vx_ccaps(VXC_SECURE_MOUNT)) {
 		put_namespace(namespace);
 		return -EPERM;
 	}
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index cfb6c2938..2dc2d8693 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -174,7 +174,7 @@ ncp_force_unlink(struct inode *dir, struct dentry* dentry)
 {
         int res=0x9c,res2;
 	struct nw_modify_dos_info info;
-	__u32 old_nwattr;
+	__le32 old_nwattr;
 	struct inode *inode;
 
 	memset(&info, 0, sizeof(info));
@@ -211,8 +211,8 @@ ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_na
 	struct nw_modify_dos_info info;
         int res=0x90,res2;
 	struct inode *old_inode = old_dentry->d_inode;
-	__u32 old_nwattr = NCP_FINFO(old_inode)->nwattr;
-	__u32 new_nwattr = 0; /* shut compiler warning */
+	__le32 old_nwattr = NCP_FINFO(old_inode)->nwattr;
+	__le32 new_nwattr = 0; /* shut compiler warning */
 	int old_nwattr_changed = 0;
 	int new_nwattr_changed = 0;
 
@@ -395,8 +395,7 @@ static time_t ncp_obtain_mtime(struct dentry *dentry)
 	if (ncp_obtain_info(server, inode, NULL, &i))
 		return 0;
 
-	return ncp_date_dos2unix(le16_to_cpu(i.modifyTime),
-						le16_to_cpu(i.modifyDate));
+	return ncp_date_dos2unix(i.modifyTime, i.modifyDate);
 }
 
 static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
@@ -767,7 +766,9 @@ int ncp_conn_logged_in(struct super_block *sb)
 	if (ncp_single_volume(server)) {
 		int len;
 		struct dentry* dent;
-		__u32 volNumber, dirEntNum, DosDirNum;
+		__u32 volNumber;
+		__le32 dirEntNum;
+		__le32 DosDirNum;
 		__u8 __name[NCP_MAXPATHLEN + 1];
 
 		len = sizeof(__name);
@@ -886,7 +887,7 @@ out_close:
 }
 
 int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
-		   dev_t rdev, int attributes)
+		   dev_t rdev, __le32 attributes)
 {
 	struct ncp_server *server = NCP_SERVER(dir);
 	struct ncp_entry_info finfo;
@@ -979,7 +980,8 @@ static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
 	error = -EACCES;
 	if (ncp_open_create_file_or_subdir(server, dir, __name,
-					   OC_MODE_CREATE, aDIR, 0xffff,
+					   OC_MODE_CREATE, aDIR,
+					   cpu_to_le16(0xffff),
 					   &finfo) == 0)
 	{
 		if (ncp_is_nfs_extras(server, finfo.volume)) {
@@ -1213,8 +1215,9 @@ static int local2utc(int time)
 
 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
 int
-ncp_date_dos2unix(unsigned short time, unsigned short date)
+ncp_date_dos2unix(__le16 t, __le16 d)
 {
+	unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d);
 	int month, year, secs;
 
 	/* first subtract and mask after that... Otherwise, if
@@ -1231,13 +1234,14 @@ ncp_date_dos2unix(unsigned short time, unsigned short date)
 
 /* Convert linear UNIX date to a MS-DOS time/date pair. */
 void
-ncp_date_unix2dos(int unix_date, unsigned short *time, unsigned short *date)
+ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
 {
 	int day, year, nl_day, month;
 
 	unix_date = utc2local(unix_date);
-	*time = (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
-	    (((unix_date / 3600) % 24) << 11);
+	*time = cpu_to_le16(
+		(unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
+		(((unix_date / 3600) % 24) << 11));
 	day = unix_date / 86400 - 3652;
 	year = day / 365;
 	if ((year + 3) / 4 + 365 * year > day)
@@ -1252,5 +1256,5 @@ ncp_date_unix2dos(int unix_date, unsigned short *time, unsigned short *date)
 			if (day_n[month] > nl_day)
 				break;
 	}
-	*date = nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9);
+	*date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));
 }
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index c1745b6f1..4947d9b11 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -115,11 +115,6 @@ ncp_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 
 	if (!ncp_conn_valid(NCP_SERVER(inode)))
 		return -EIO;
-	if (!S_ISREG(inode->i_mode)) {
-		DPRINTK("ncp_file_read: read from non-file, mode %07o\n",
-			inode->i_mode);
-		return -EINVAL;
-	}
 
 	pos = *ppos;
 
@@ -175,10 +170,8 @@ ncp_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 
 	*ppos = pos;
 
-	if (!IS_RDONLY(inode)) {
-		inode->i_atime = CURRENT_TIME;
-	}
-	
+	file_accessed(file);
+
 	DPRINTK("ncp_file_read: exit %s/%s\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 outrel:
@@ -201,11 +194,6 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 	if (!ncp_conn_valid(NCP_SERVER(inode)))
 		return -EIO;
-	if (!S_ISREG(inode->i_mode)) {
-		DPRINTK("ncp_file_write: write to non-file, mode %07o\n",
-			inode->i_mode);
-		return -EINVAL;
-	}
 	if ((ssize_t) count < 0)
 		return -EINVAL;
 	pos = *ppos;
@@ -273,8 +261,9 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *
 		}
 	}
 	vfree(bouncebuffer);
-	inode->i_mtime = inode->i_atime = CURRENT_TIME;
-	
+
+	inode_update_time(inode, 1);
+
 	*ppos = pos;
 
 	if (pos > inode->i_size) {
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index bea651fd2..44795d2f4 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -72,7 +72,7 @@ static int init_inodecache(void)
 {
 	ncp_inode_cachep = kmem_cache_create("ncp_inode_cache",
 					     sizeof(struct ncp_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (ncp_inode_cachep == NULL)
 		return -ENOMEM;
@@ -142,12 +142,9 @@ static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi)
 
 	inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
 
-	inode->i_mtime.tv_sec = ncp_date_dos2unix(le16_to_cpu(nwi->modifyTime),
-					   le16_to_cpu(nwi->modifyDate));
-	inode->i_ctime.tv_sec = ncp_date_dos2unix(le16_to_cpu(nwi->creationTime),
-					   le16_to_cpu(nwi->creationDate));
-	inode->i_atime.tv_sec = ncp_date_dos2unix(0,
-					   le16_to_cpu(nwi->lastAccessDate));
+	inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate);
+	inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate);
+	inode->i_atime.tv_sec = ncp_date_dos2unix(0, nwi->lastAccessDate);
 	inode->i_atime.tv_nsec = 0;
 	inode->i_mtime.tv_nsec = 0;
 	inode->i_ctime.tv_nsec = 0;
@@ -235,8 +232,9 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
 
 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
 static struct inode_operations ncp_symlink_inode_operations = {
-	.readlink	= page_readlink,
-	.follow_link	= page_follow_link,
+	.readlink	= generic_readlink,
+	.follow_link	= page_follow_link_light,
+	.put_link	= page_put_link,
 	.setattr	= ncp_notify_change,
 };
 #endif
@@ -462,7 +460,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
 			break;
 		default:
 			error = -ECHRNG;
-			if (*(__u32*)raw_data == cpu_to_be32(0x76657273)) {
+			if (memcmp(raw_data, "vers", 4) == 0) {
 				error = ncp_parse_options(&data, raw_data);
 			}
 			if (error)
@@ -625,7 +623,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
 
 	memset(&finfo, 0, sizeof(finfo));
 	finfo.i.attributes	= aDIR;
-	finfo.i.dataStreamSize	= NCP_BLOCK_SIZE;
+	finfo.i.dataStreamSize	= 0;	/* ignored */
 	finfo.i.dirEntNum	= 0;
 	finfo.i.DosDirNum	= 0;
 #ifdef CONFIG_NCPFS_SMALLDOS
@@ -794,7 +792,7 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
 {
 	struct inode *inode = dentry->d_inode;
 	int result = 0;
-	int info_mask;
+	__le32 info_mask;
 	struct nw_modify_dos_info info;
 	struct ncp_server *server;
 
@@ -917,23 +915,18 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
 	if ((attr->ia_valid & ATTR_CTIME) != 0) {
 		info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
 		ncp_date_unix2dos(attr->ia_ctime.tv_sec,
-			     &(info.creationTime), &(info.creationDate));
-		info.creationTime = le16_to_cpu(info.creationTime);
-		info.creationDate = le16_to_cpu(info.creationDate);
+			     &info.creationTime, &info.creationDate);
 	}
 	if ((attr->ia_valid & ATTR_MTIME) != 0) {
 		info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
 		ncp_date_unix2dos(attr->ia_mtime.tv_sec,
-				  &(info.modifyTime), &(info.modifyDate));
-		info.modifyTime = le16_to_cpu(info.modifyTime);
-		info.modifyDate = le16_to_cpu(info.modifyDate);
+				  &info.modifyTime, &info.modifyDate);
 	}
 	if ((attr->ia_valid & ATTR_ATIME) != 0) {
-		__u16 dummy;
+		__le16 dummy;
 		info_mask |= (DM_LAST_ACCESS_DATE);
 		ncp_date_unix2dos(attr->ia_atime.tv_sec,
-				  &(dummy), &(info.lastAccessDate));
-		info.lastAccessDate = le16_to_cpu(info.lastAccessDate);
+				  &dummy, &info.lastAccessDate);
 	}
 	if (info_mask != 0) {
 		result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
index a7eb88163..88df79356 100644
--- a/fs/ncpfs/ioctl.c
+++ b/fs/ncpfs/ioctl.c
@@ -299,7 +299,9 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
 	case NCP_IOC_SETROOT:
 		{
 			struct ncp_setroot_ioctl sr;
-			__u32 vnum, de, dosde;
+			__u32 vnum;
+			__le32 de;
+			__le32 dosde;
 			struct dentry* dentry;
 
 			if (!capable(CAP_SYS_ADMIN))
diff --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c
index 5fb8e8716..52d60c3d8 100644
--- a/fs/ncpfs/mmap.c
+++ b/fs/ncpfs/mmap.c
@@ -110,23 +110,19 @@ int ncp_mmap(struct file *file, struct vm_area_struct *vma)
 	
 	DPRINTK("ncp_mmap: called\n");
 
-	if (!ncp_conn_valid(NCP_SERVER(inode))) {
+	if (!ncp_conn_valid(NCP_SERVER(inode)))
 		return -EIO;
-	}
+
 	/* only PAGE_COW or read-only supported now */
 	if (vma->vm_flags & VM_SHARED)
 		return -EINVAL;
-	if (!inode->i_sb || !S_ISREG(inode->i_mode))
-		return -EACCES;
 	/* we do not support files bigger than 4GB... We eventually 
 	   supports just 4GB... */
 	if (((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff 
 	   > (1U << (32 - PAGE_SHIFT)))
 		return -EFBIG;
-	if (!IS_RDONLY(inode)) {
-		inode->i_atime = CURRENT_TIME;
-	}
 
 	vma->vm_ops = &ncp_file_mmap;
+	file_accessed(file);
 	return 0;
 }
diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c
index ad99ac0ec..51969f278 100644
--- a/fs/ncpfs/ncplib_kernel.c
+++ b/fs/ncpfs/ncplib_kernel.c
@@ -29,22 +29,36 @@ static void ncp_add_byte(struct ncp_server *server, __u8 x)
 	return;
 }
 
-static void ncp_add_word(struct ncp_server *server, __u16 x)
+static void ncp_add_word(struct ncp_server *server, __le16 x)
 {
 	assert_server_locked(server);
-	put_unaligned(x, (__u16 *) (&(server->packet[server->current_size])));
+	put_unaligned(x, (__le16 *) (&(server->packet[server->current_size])));
 	server->current_size += 2;
 	return;
 }
 
-static void ncp_add_dword(struct ncp_server *server, __u32 x)
+static void ncp_add_be16(struct ncp_server *server, __u16 x)
 {
 	assert_server_locked(server);
-	put_unaligned(x, (__u32 *) (&(server->packet[server->current_size])));
+	put_unaligned(cpu_to_be16(x), (__be16 *) (&(server->packet[server->current_size])));
+	server->current_size += 2;
+}
+
+static void ncp_add_dword(struct ncp_server *server, __le32 x)
+{
+	assert_server_locked(server);
+	put_unaligned(x, (__le32 *) (&(server->packet[server->current_size])));
 	server->current_size += 4;
 	return;
 }
 
+static void ncp_add_be32(struct ncp_server *server, __u32 x)
+{
+	assert_server_locked(server);
+	put_unaligned(cpu_to_be32(x), (__be32 *)(&(server->packet[server->current_size])));
+	server->current_size += 4;
+}
+
 static inline void ncp_add_dword_lh(struct ncp_server *server, __u32 x) {
 	ncp_add_dword(server, cpu_to_le32(x));
 }
@@ -107,24 +121,30 @@ static __u8
 
 static inline __u16 WVAL_LH(void* data)
 {
-	return le16_to_cpu(get_unaligned((__u16*)data));
+	return le16_to_cpu(get_unaligned((__le16*)data));
 }
 
 static __u16
- ncp_reply_word(struct ncp_server *server, int offset)
+ ncp_reply_le16(struct ncp_server *server, int offset)
 {
-	return get_unaligned((__u16 *) ncp_reply_data(server, offset));
+	return le16_to_cpu(get_unaligned((__le16 *) ncp_reply_data(server, offset)));
+}
+
+static __u16
+ ncp_reply_be16(struct ncp_server *server, int offset)
+{
+	return be16_to_cpu(get_unaligned((__be16 *) ncp_reply_data(server, offset)));
 }
 
 static inline __u32 DVAL_LH(void* data)
 {
-	return le32_to_cpu(get_unaligned((__u32*)data));
+	return le32_to_cpu(get_unaligned((__le32*)data));
 }
 
-static __u32
+static __le32
  ncp_reply_dword(struct ncp_server *server, int offset)
 {
-	return get_unaligned((__u32 *) ncp_reply_data(server, offset));
+	return get_unaligned((__le32 *) ncp_reply_data(server, offset));
 }
 
 static inline __u32 ncp_reply_dword_lh(struct ncp_server* server, int offset) {
@@ -137,13 +157,13 @@ ncp_negotiate_buffersize(struct ncp_server *server, int size, int *target)
 	int result;
 
 	ncp_init_request(server);
-	ncp_add_word(server, htons(size));
+	ncp_add_be16(server, size);
 
 	if ((result = ncp_request(server, 33)) != 0) {
 		ncp_unlock_server(server);
 		return result;
 	}
-	*target = min_t(unsigned int, ntohs(ncp_reply_word(server, 0)), size);
+	*target = min_t(unsigned int, ncp_reply_be16(server, 0), size);
 
 	ncp_unlock_server(server);
 	return 0;
@@ -163,7 +183,7 @@ ncp_negotiate_size_and_options(struct ncp_server *server,
 	if (size < NCP_BLOCK_SIZE) size = NCP_BLOCK_SIZE;
 
 	ncp_init_request(server);
-	ncp_add_word(server, htons(size));
+	ncp_add_be16(server, size);
 	ncp_add_byte(server, options);
 	
 	if ((result = ncp_request(server, 0x61)) != 0)
@@ -173,7 +193,7 @@ ncp_negotiate_size_and_options(struct ncp_server *server,
 	}
 
 	/* NCP over UDP returns 0 (!!!) */
-	result = ntohs(ncp_reply_word(server, 0));
+	result = ncp_reply_be16(server, 0);
 	if (result >= NCP_BLOCK_SIZE)
 		size = min(result, size);
 	*ret_size = size;
@@ -286,7 +306,7 @@ ncp_make_closed(struct inode *inode)
 }
 
 static void ncp_add_handle_path(struct ncp_server *server, __u8 vol_num,
-				__u32 dir_base, int have_dir_base, 
+				__le32 dir_base, int have_dir_base, 
 				const char *path)
 {
 	ncp_add_byte(server, vol_num);
@@ -304,7 +324,7 @@ static void ncp_add_handle_path(struct ncp_server *server, __u8 vol_num,
 	}
 }
 
-int ncp_dirhandle_alloc(struct ncp_server* server, __u8 volnum, __u32 dirent,
+int ncp_dirhandle_alloc(struct ncp_server* server, __u8 volnum, __le32 dirent,
 			__u8* dirhandle) {
 	int result;
 
@@ -403,7 +423,7 @@ int ncp_obtain_info(struct ncp_server *server, struct inode *dir, char *path,
 			struct nw_info_struct *target)
 {
 	__u8  volnum = NCP_FINFO(dir)->volNumber;
-	__u32 dirent = NCP_FINFO(dir)->dirEntNum;
+	__le32 dirent = NCP_FINFO(dir)->dirEntNum;
 	int result;
 
 	if (target == NULL) {
@@ -414,7 +434,7 @@ int ncp_obtain_info(struct ncp_server *server, struct inode *dir, char *path,
 	ncp_add_byte(server, 6);	/* subfunction */
 	ncp_add_byte(server, server->name_space[volnum]);
 	ncp_add_byte(server, server->name_space[volnum]); /* N.B. twice ?? */
-	ncp_add_word(server, htons(0x0680));	/* get all */
+	ncp_add_word(server, cpu_to_le16(0x8006));	/* get all */
 	ncp_add_dword(server, RIM_ALL);
 	ncp_add_handle_path(server, volnum, dirent, 1, path);
 
@@ -434,9 +454,9 @@ out:
 #ifdef CONFIG_NCPFS_NFS_NS
 static int
 ncp_obtain_DOS_dir_base(struct ncp_server *server,
-		__u8 volnum, __u32 dirent,
+		__u8 volnum, __le32 dirent,
 		char *path, /* At most 1 component */
-		__u32 *DOS_dir_base)
+		__le32 *DOS_dir_base)
 {
 	int result;
 
@@ -444,7 +464,7 @@ ncp_obtain_DOS_dir_base(struct ncp_server *server,
 	ncp_add_byte(server, 6); /* subfunction */
 	ncp_add_byte(server, server->name_space[volnum]);
 	ncp_add_byte(server, server->name_space[volnum]);
-	ncp_add_word(server, htons(0x0680)); /* get all */
+	ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */
 	ncp_add_dword(server, RIM_DIRECTORY);
 	ncp_add_handle_path(server, volnum, dirent, 1, path);
 
@@ -476,7 +496,7 @@ ncp_get_known_namespace(struct ncp_server *server, __u8 volume)
 	}
 
 	result = NW_NS_DOS;
-	no_namespaces = le16_to_cpu(ncp_reply_word(server, 0));
+	no_namespaces = ncp_reply_le16(server, 0);
 	namespace = ncp_reply_data(server, 2);
 
 	while (no_namespaces > 0) {
@@ -507,9 +527,9 @@ ncp_get_known_namespace(struct ncp_server *server, __u8 volume)
 
 static int
 ncp_ObtainSpecificDirBase(struct ncp_server *server,
-		__u8 nsSrc, __u8 nsDst, __u8 vol_num, __u32 dir_base,
+		__u8 nsSrc, __u8 nsDst, __u8 vol_num, __le32 dir_base,
 		char *path, /* At most 1 component */
-		__u32 *dirEntNum, __u32 *DosDirNum)
+		__le32 *dirEntNum, __le32 *DosDirNum)
 {
 	int result;
 
@@ -517,7 +537,7 @@ ncp_ObtainSpecificDirBase(struct ncp_server *server,
 	ncp_add_byte(server, 6); /* subfunction */
 	ncp_add_byte(server, nsSrc);
 	ncp_add_byte(server, nsDst);
-	ncp_add_word(server, htons(0x0680)); /* get all */
+	ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */
 	ncp_add_dword(server, RIM_ALL);
 	ncp_add_handle_path(server, vol_num, dir_base, 1, path);
 
@@ -537,8 +557,8 @@ ncp_ObtainSpecificDirBase(struct ncp_server *server,
 
 int
 ncp_mount_subdir(struct ncp_server *server,
-		 __u8 volNumber, __u8 srcNS, __u32 dirEntNum,
-		 __u32* volume, __u32* newDirEnt, __u32* newDosEnt)
+		 __u8 volNumber, __u8 srcNS, __le32 dirEntNum,
+		 __u32* volume, __le32* newDirEnt, __le32* newDosEnt)
 {
 	int dstNS;
 	int result;
@@ -558,7 +578,7 @@ ncp_mount_subdir(struct ncp_server *server,
 
 int 
 ncp_get_volume_root(struct ncp_server *server, const char *volname,
-		    __u32* volume, __u32* dirent, __u32* dosdirent)
+		    __u32* volume, __le32* dirent, __le32* dosdirent)
 {
 	int result;
 	__u8 volnum;
@@ -620,18 +640,18 @@ ncp_lookup_volume(struct ncp_server *server, const char *volname,
 int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *server,
 					    struct inode *dir,
 					    const char *path,
-					    __u32 info_mask,
+					    __le32 info_mask,
 					    const struct nw_modify_dos_info *info)
 {
 	__u8  volnum = NCP_FINFO(dir)->volNumber;
-	__u32 dirent = NCP_FINFO(dir)->dirEntNum;
+	__le32 dirent = NCP_FINFO(dir)->dirEntNum;
 	int result;
 
 	ncp_init_request(server);
 	ncp_add_byte(server, 7);	/* subfunction */
 	ncp_add_byte(server, server->name_space[volnum]);
 	ncp_add_byte(server, 0);	/* reserved */
-	ncp_add_word(server, htons(0x0680));	/* search attribs: all */
+	ncp_add_word(server, cpu_to_le16(0x8006));	/* search attribs: all */
 
 	ncp_add_dword(server, info_mask);
 	ncp_add_mem(server, info, sizeof(*info));
@@ -644,7 +664,7 @@ int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *server,
 
 int ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
 				       struct inode *dir,
-				       __u32 info_mask,
+				       __le32 info_mask,
 				       const struct nw_modify_dos_info *info)
 {
 	return ncp_modify_file_or_subdir_dos_info_path(server, dir, NULL,
@@ -652,7 +672,7 @@ int ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
 }
 
 #ifdef CONFIG_NCPFS_NFS_NS
-int ncp_modify_nfs_info(struct ncp_server *server, __u8 volnum, __u32 dirent,
+int ncp_modify_nfs_info(struct ncp_server *server, __u8 volnum, __le32 dirent,
 			       __u32 mode, __u32 rdev)
 
 {
@@ -681,8 +701,8 @@ int ncp_modify_nfs_info(struct ncp_server *server, __u8 volnum, __u32 dirent,
 
 static int
 ncp_DeleteNSEntry(struct ncp_server *server,
-		  __u8 have_dir_base, __u8 volnum, __u32 dirent,
-		  char* name, __u8 ns, int attr)
+		  __u8 have_dir_base, __u8 volnum, __le32 dirent,
+		  char* name, __u8 ns, __le16 attr)
 {
 	int result;
 
@@ -704,7 +724,7 @@ ncp_del_file_or_subdir2(struct ncp_server *server,
 {
 	struct inode *inode = dentry->d_inode;
 	__u8  volnum;
-	__u32 dirent;
+	__le32 dirent;
 
 	if (!inode) {
 #ifdef CONFIG_NCPFS_DEBUGDENTRY
@@ -714,7 +734,7 @@ ncp_del_file_or_subdir2(struct ncp_server *server,
 	}
 	volnum = NCP_FINFO(inode)->volNumber;
 	dirent = NCP_FINFO(inode)->DosDirNum;
-	return ncp_DeleteNSEntry(server, 1, volnum, dirent, NULL, NW_NS_DOS, htons(0x0680));
+	return ncp_DeleteNSEntry(server, 1, volnum, dirent, NULL, NW_NS_DOS, cpu_to_le16(0x8006));
 }
 
 int
@@ -722,7 +742,7 @@ ncp_del_file_or_subdir(struct ncp_server *server,
 		       struct inode *dir, char *name)
 {
 	__u8  volnum = NCP_FINFO(dir)->volNumber;
-	__u32 dirent = NCP_FINFO(dir)->dirEntNum;
+	__le32 dirent = NCP_FINFO(dir)->dirEntNum;
 
 #ifdef CONFIG_NCPFS_NFS_NS
 	if (server->name_space[volnum]==NW_NS_NFS)
@@ -731,18 +751,19 @@ ncp_del_file_or_subdir(struct ncp_server *server,
  
  		result=ncp_obtain_DOS_dir_base(server, volnum, dirent, name, &dirent);
  		if (result) return result;
- 		return ncp_DeleteNSEntry(server, 1, volnum, dirent, NULL, NW_NS_DOS, htons(0x0680));
+ 		return ncp_DeleteNSEntry(server, 1, volnum, dirent, NULL, NW_NS_DOS, cpu_to_le16(0x8006));
  	}
  	else
 #endif	/* CONFIG_NCPFS_NFS_NS */
- 		return ncp_DeleteNSEntry(server, 1, volnum, dirent, name, server->name_space[volnum], htons(0x0680));
+ 		return ncp_DeleteNSEntry(server, 1, volnum, dirent, name, server->name_space[volnum], cpu_to_le16(0x8006));
 }
 
-static inline void ConvertToNWfromDWORD(__u32 sfd, __u8 ret[6])
+static inline void ConvertToNWfromDWORD(__u16 v0, __u16 v1, __u8 ret[6])
 {
-	__u16 *dest = (__u16 *) ret;
-	memcpy(ret + 2, &sfd, 4);
-	dest[0] = cpu_to_le16((le16_to_cpu(dest[1]) + le16_to_cpu(1)));
+	__le16 *dest = (__le16 *) ret;
+	dest[1] = cpu_to_le16(v0);
+	dest[2] = cpu_to_le16(v1);
+	dest[0] = cpu_to_le16(v0 + 1);
 	return;
 }
 
@@ -751,20 +772,20 @@ static inline void ConvertToNWfromDWORD(__u32 sfd, __u8 ret[6])
 int ncp_open_create_file_or_subdir(struct ncp_server *server,
 				   struct inode *dir, char *name,
 				   int open_create_mode,
-				   __u32 create_attributes,
-				   int desired_acc_rights,
+				   __le32 create_attributes,
+				   __le16 desired_acc_rights,
 				   struct ncp_entry_info *target)
 {
-	__u16 search_attribs = ntohs(0x0600);
+	__le16 search_attribs = cpu_to_le16(0x0006);
 	__u8  volnum;
-	__u32 dirent;
+	__le32 dirent;
 	int result;
 
 	volnum = NCP_FINFO(dir)->volNumber;
 	dirent = NCP_FINFO(dir)->dirEntNum;
 
 	if ((create_attributes & aDIR) != 0) {
-		search_attribs |= ntohs(0x0080);
+		search_attribs |= cpu_to_le16(0x8000);
 	}
 	ncp_init_request(server);
 	ncp_add_byte(server, 1);	/* subfunction */
@@ -786,7 +807,9 @@ int ncp_open_create_file_or_subdir(struct ncp_server *server,
 	/* in target there's a new finfo to fill */
 	ncp_extract_file_info(ncp_reply_data(server, 6), &(target->i));
 	target->volume = target->i.volNumber;
-	ConvertToNWfromDWORD(ncp_reply_dword(server, 0), target->file_handle);
+	ConvertToNWfromDWORD(ncp_reply_le16(server, 0),
+			     ncp_reply_le16(server, 2),
+			     target->file_handle);
 	
 	ncp_unlock_server(server);
 
@@ -803,7 +826,7 @@ ncp_initialize_search(struct ncp_server *server, struct inode *dir,
 			struct nw_search_sequence *target)
 {
 	__u8  volnum = NCP_FINFO(dir)->volNumber;
-	__u32 dirent = NCP_FINFO(dir)->dirEntNum;
+	__le32 dirent = NCP_FINFO(dir)->dirEntNum;
 	int result;
 
 	ncp_init_request(server);
@@ -833,7 +856,7 @@ int ncp_search_for_file_or_subdir(struct ncp_server *server,
 	ncp_add_byte(server, 3);	/* subfunction */
 	ncp_add_byte(server, server->name_space[seq->volNumber]);
 	ncp_add_byte(server, 0);	/* data stream (???) */
-	ncp_add_word(server, htons(0x0680));	/* Search attribs */
+	ncp_add_word(server, cpu_to_le16(0x8006));	/* Search attribs */
 	ncp_add_dword(server, RIM_ALL);		/* return info mask */
 	ncp_add_mem(server, seq, 9);
 #ifdef CONFIG_NCPFS_NFS_NS
@@ -877,9 +900,9 @@ int ncp_search_for_fileset(struct ncp_server *server,
 	ncp_add_byte(server, 20);
 	ncp_add_byte(server, server->name_space[seq->volNumber]);
 	ncp_add_byte(server, 0);		/* datastream */
-	ncp_add_word(server, htons(0x0680));
+	ncp_add_word(server, cpu_to_le16(0x8006));
 	ncp_add_dword(server, RIM_ALL);
-	ncp_add_word(server, 32767);		/* max returned items */
+	ncp_add_word(server, cpu_to_le16(32767));	/* max returned items */
 	ncp_add_mem(server, seq, 9);
 #ifdef CONFIG_NCPFS_NFS_NS
 	if (server->name_space[seq->volNumber] == NW_NS_NFS) {
@@ -912,7 +935,7 @@ int ncp_search_for_fileset(struct ncp_server *server,
 
 int
 ncp_RenameNSEntry(struct ncp_server *server,
-		  struct inode *old_dir, char *old_name, int old_type,
+		  struct inode *old_dir, char *old_name, __le16 old_type,
 		  struct inode *new_dir, char *new_name)
 {
 	int result = -EINVAL;
@@ -955,14 +978,14 @@ int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
 				struct inode *new_dir, char *new_name)
 {
         int result;
-        int old_type = htons(0x0600);
+        __le16 old_type = cpu_to_le16(0x06);
 
 /* If somebody can do it atomic, call me... vandrove@vc.cvut.cz */
 	result = ncp_RenameNSEntry(server, old_dir, old_name, old_type,
 	                                   new_dir, new_name);
         if (result == 0xFF)	/* File Not Found, try directory */
 	{
-		old_type = htons(0x1600);
+		old_type = cpu_to_le16(0x16);
 		result = ncp_RenameNSEntry(server, old_dir, old_name, old_type,
 						   new_dir, new_name);
 	}
@@ -986,13 +1009,13 @@ ncp_read_kernel(struct ncp_server *server, const char *file_id,
 	ncp_init_request(server);
 	ncp_add_byte(server, 0);
 	ncp_add_mem(server, file_id, 6);
-	ncp_add_dword(server, htonl(offset));
-	ncp_add_word(server, htons(to_read));
+	ncp_add_be32(server, offset);
+	ncp_add_be16(server, to_read);
 
 	if ((result = ncp_request(server, 72)) != 0) {
 		goto out;
 	}
-	*bytes_read = ntohs(ncp_reply_word(server, 0));
+	*bytes_read = ncp_reply_be16(server, 0);
 	source = ncp_reply_data(server, 2 + (offset & 1));
 
 	memcpy(target, source, *bytes_read);
@@ -1022,12 +1045,12 @@ ncp_read_bounce(struct ncp_server *server, const char *file_id,
 	ncp_init_request(server);
 	ncp_add_byte(server, 0);
 	ncp_add_mem(server, file_id, 6);
-	ncp_add_dword(server, htonl(offset));
-	ncp_add_word(server, htons(to_read));
+	ncp_add_be32(server, offset);
+	ncp_add_be16(server, to_read);
 	result = ncp_request2(server, 72, bounce, bufsize);
 	ncp_unlock_server(server);
 	if (!result) {
-		int len = be16_to_cpu(get_unaligned((__u16*)((char*)bounce + 
+		int len = be16_to_cpu(get_unaligned((__be16*)((char*)bounce + 
 			  sizeof(struct ncp_reply_header))));
 		result = -EIO;
 		if (len <= to_read) {
@@ -1055,8 +1078,8 @@ ncp_write_kernel(struct ncp_server *server, const char *file_id,
 	ncp_init_request(server);
 	ncp_add_byte(server, 0);
 	ncp_add_mem(server, file_id, 6);
-	ncp_add_dword(server, htonl(offset));
-	ncp_add_word(server, htons(to_write));
+	ncp_add_be32(server, offset);
+	ncp_add_be16(server, to_write);
 	ncp_add_mem(server, source, to_write);
 	
 	if ((result = ncp_request(server, 73)) == 0)
@@ -1075,9 +1098,9 @@ ncp_LogPhysicalRecord(struct ncp_server *server, const char *file_id,
 	ncp_init_request(server);
 	ncp_add_byte(server, locktype);
 	ncp_add_mem(server, file_id, 6);
-	ncp_add_dword(server, htonl(offset));
-	ncp_add_dword(server, htonl(length));
-	ncp_add_word(server, htons(timeout));
+	ncp_add_be32(server, offset);
+	ncp_add_be32(server, length);
+	ncp_add_be16(server, timeout);
 
 	if ((result = ncp_request(server, 0x1A)) != 0)
 	{
@@ -1097,8 +1120,8 @@ ncp_ClearPhysicalRecord(struct ncp_server *server, const char *file_id,
 	ncp_init_request(server);
 	ncp_add_byte(server, 0);	/* who knows... lanalyzer says that */
 	ncp_add_mem(server, file_id, 6);
-	ncp_add_dword(server, htonl(offset));
-	ncp_add_dword(server, htonl(length));
+	ncp_add_be32(server, offset);
+	ncp_add_be32(server, length);
 
 	if ((result = ncp_request(server, 0x1E)) != 0)
 	{
@@ -1115,22 +1138,6 @@ ncp_ClearPhysicalRecord(struct ncp_server *server, const char *file_id,
  * from the vfat file system and hints from Petr Vandrovec.
  */
 
-inline unsigned char
-ncp__tolower(struct nls_table *t, unsigned char c)
-{
-	unsigned char nc = t->charset2lower[c];
-
-	return nc ? nc : c;
-}
-
-inline unsigned char
-ncp__toupper(struct nls_table *t, unsigned char c)
-{
-	unsigned char nc = t->charset2upper[c];
-
-	return nc ? nc : c;
-}
-
 int
 ncp__io2vol(struct ncp_server *server, unsigned char *vname, unsigned int *vlen,
 		const unsigned char *iname, unsigned int ilen, int cc)
@@ -1346,16 +1353,3 @@ ncp__vol2io(unsigned char *iname, unsigned int *ilen,
 }
 
 #endif
-
-inline int
-ncp_strnicmp(struct nls_table *t, const unsigned char *s1,
-					const unsigned char *s2, int n)
-{
-	int i;
-
-	for (i=0; i<n; i++)
-		if (ncp_tolower(t, s1[i]) != ncp_tolower(t, s2[i]))
-			return 1;
-
-	return 0;
-}
diff --git a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h
index 7edb9e131..05ec2e9d9 100644
--- a/fs/ncpfs/ncplib_kernel.h
+++ b/fs/ncpfs/ncplib_kernel.h
@@ -71,19 +71,19 @@ int ncp_obtain_info(struct ncp_server *server, struct inode *, char *,
 		struct nw_info_struct *target);
 int ncp_obtain_nfs_info(struct ncp_server *server, struct nw_info_struct *target);
 int ncp_get_volume_root(struct ncp_server *server, const char *volname,
-			__u32 *volume, __u32 *dirent, __u32 *dosdirent);
+			__u32 *volume, __le32 *dirent, __le32 *dosdirent);
 int ncp_lookup_volume(struct ncp_server *, const char *, struct nw_info_struct *);
 int ncp_modify_file_or_subdir_dos_info(struct ncp_server *, struct inode *,
-	 __u32, const struct nw_modify_dos_info *info);
+	 __le32, const struct nw_modify_dos_info *info);
 int ncp_modify_file_or_subdir_dos_info_path(struct ncp_server *, struct inode *,
-	 const char* path, __u32, const struct nw_modify_dos_info *info);
-int ncp_modify_nfs_info(struct ncp_server *, __u8 volnum, __u32 dirent,
+	 const char* path, __le32, const struct nw_modify_dos_info *info);
+int ncp_modify_nfs_info(struct ncp_server *, __u8 volnum, __le32 dirent,
 			__u32 mode, __u32 rdev);
 
 int ncp_del_file_or_subdir2(struct ncp_server *, struct dentry*);
 int ncp_del_file_or_subdir(struct ncp_server *, struct inode *, char *);
 int ncp_open_create_file_or_subdir(struct ncp_server *, struct inode *, char *,
-				int, __u32, int, struct ncp_entry_info *);
+				int, __le32, __le16, struct ncp_entry_info *);
 
 int ncp_initialize_search(struct ncp_server *, struct inode *,
 		      struct nw_search_sequence *target);
@@ -113,13 +113,13 @@ ncp_ClearPhysicalRecord(struct ncp_server *server,
 #endif	/* CONFIG_NCPFS_IOCTL_LOCKING */
 
 int
-ncp_mount_subdir(struct ncp_server *, __u8, __u8, __u32,
-		 __u32* volume, __u32* dirent, __u32* dosdirent);
-int ncp_dirhandle_alloc(struct ncp_server *, __u8 vol, __u32 dirent, __u8 *dirhandle);
+ncp_mount_subdir(struct ncp_server *, __u8, __u8, __le32,
+		 __u32* volume, __le32* dirent, __le32* dosdirent);
+int ncp_dirhandle_alloc(struct ncp_server *, __u8 vol, __le32 dirent, __u8 *dirhandle);
 int ncp_dirhandle_free(struct ncp_server *, __u8 dirhandle);
 
 int ncp_create_new(struct inode *dir, struct dentry *dentry,
-                          int mode, dev_t rdev, int attributes);
+                          int mode, dev_t rdev, __le32 attributes);
 
 static inline int ncp_is_nfs_extras(struct ncp_server* server, unsigned int volnum) {
 #ifdef CONFIG_NCPFS_NFS_NS
@@ -132,8 +132,6 @@ static inline int ncp_is_nfs_extras(struct ncp_server* server, unsigned int voln
 
 #ifdef CONFIG_NCPFS_NLS
 
-unsigned char ncp__tolower(struct nls_table *, unsigned char);
-unsigned char ncp__toupper(struct nls_table *, unsigned char);
 int ncp__io2vol(struct ncp_server *, unsigned char *, unsigned int *,
 				const unsigned char *, unsigned int, int);
 int ncp__vol2io(struct ncp_server *, unsigned char *, unsigned int *,
@@ -141,8 +139,10 @@ int ncp__vol2io(struct ncp_server *, unsigned char *, unsigned int *,
 
 #define NCP_ESC			':'
 #define NCP_IO_TABLE(dentry)	(NCP_SERVER((dentry)->d_inode)->nls_io)
-#define ncp_tolower(t, c)	ncp__tolower(t, c)
-#define ncp_toupper(t, c)	ncp__toupper(t, c)
+#define ncp_tolower(t, c)	nls_tolower(t, c)
+#define ncp_toupper(t, c)	nls_toupper(t, c)
+#define ncp_strnicmp(t, s1, s2, len) \
+	nls_strnicmp(t, s1, s2, len)
 #define ncp_io2vol(S,m,i,n,k,U)	ncp__io2vol(S,m,i,n,k,U)
 #define ncp_vol2io(S,m,i,n,k,U)	ncp__vol2io(S,m,i,n,k,U)
 
@@ -159,11 +159,19 @@ int ncp__vol2io(unsigned char *, unsigned int *,
 #define ncp_io2vol(S,m,i,n,k,U)	ncp__io2vol(m,i,n,k,U)
 #define ncp_vol2io(S,m,i,n,k,U)	ncp__vol2io(m,i,n,k,U)
 
-#endif /* CONFIG_NCPFS_NLS */
 
-int
-ncp_strnicmp(struct nls_table *,
-		const unsigned char *, const unsigned char *, int);
+static inline int ncp_strnicmp(struct nls_table *t, const unsigned char *s1,
+		const unsigned char *s2, int len)
+{
+	while (len--) {
+		if (tolower(*s1++) != tolower(*s2++))
+			return 1;
+	}
+
+	return 0;
+}
+
+#endif /* CONFIG_NCPFS_NLS */
 
 #define NCP_GET_AGE(dentry)	(jiffies - (dentry)->d_time)
 #define NCP_MAX_AGE(server)	((server)->dentry_ttl)
diff --git a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c
index 845bfe43e..6593a5ca8 100644
--- a/fs/ncpfs/sock.c
+++ b/fs/ncpfs/sock.c
@@ -337,7 +337,7 @@ static void info_server(struct ncp_server *server, unsigned int id, const void *
 {
 	if (server->info_sock) {
 		struct kvec iov[2];
-		__u32 hdr[2];
+		__be32 hdr[2];
 	
 		hdr[0] = cpu_to_be32(len + 8);
 		hdr[1] = cpu_to_be32(id);
diff --git a/fs/ncpfs/symlink.c b/fs/ncpfs/symlink.c
index 15697bc00..e935f1b34 100644
--- a/fs/ncpfs/symlink.c
+++ b/fs/ncpfs/symlink.c
@@ -36,8 +36,8 @@
 /* these magic numbers must appear in the symlink file -- this makes it a bit
    more resilient against the magic attributes being set on random files. */
 
-#define NCP_SYMLINK_MAGIC0	le32_to_cpu(0x6c6d7973)     /* "symlnk->" */
-#define NCP_SYMLINK_MAGIC1	le32_to_cpu(0x3e2d6b6e)
+#define NCP_SYMLINK_MAGIC0	cpu_to_le32(0x6c6d7973)     /* "symlnk->" */
+#define NCP_SYMLINK_MAGIC1	cpu_to_le32(0x3e2d6b6e)
 
 /* ----- read a symbolic link ------------------------------------------ */
 
@@ -67,8 +67,8 @@ static int ncp_symlink_readpage(struct file *file, struct page *page)
 
 	if (NCP_FINFO(inode)->flags & NCPI_KLUDGE_SYMLINK) {
 		if (length<NCP_MIN_SYMLINK_SIZE || 
-		    ((__u32 *)rawlink)[0]!=NCP_SYMLINK_MAGIC0 ||
-		    ((__u32 *)rawlink)[1]!=NCP_SYMLINK_MAGIC1)
+		    ((__le32 *)rawlink)[0]!=NCP_SYMLINK_MAGIC0 ||
+		    ((__le32 *)rawlink)[1]!=NCP_SYMLINK_MAGIC1)
 		    	goto failEIO;
 		link = rawlink + 8;
 		length -= 8;
@@ -110,7 +110,8 @@ int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
 	char *rawlink;
 	int length, err, i, outlen;
 	int kludge;
-	int mode, attr;
+	int mode;
+	__le32 attr;
 	unsigned int hdr;
 
 	DPRINTK("ncp_symlink(dir=%p,dentry=%p,symname=%s)\n",dir,dentry,symname);
@@ -133,8 +134,8 @@ int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
 	if (kludge) {
 		mode = 0;
 		attr = aSHARED | aHIDDEN;
-		((__u32 *)rawlink)[0]=NCP_SYMLINK_MAGIC0;
-		((__u32 *)rawlink)[1]=NCP_SYMLINK_MAGIC1;
+		((__le32 *)rawlink)[0]=NCP_SYMLINK_MAGIC0;
+		((__le32 *)rawlink)[1]=NCP_SYMLINK_MAGIC1;
 		hdr = 8;
 	} else {
 		mode = S_IFLNK | S_IRWXUGO;
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index d85ccd52a..b4baa031e 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -9,6 +9,7 @@ nfs-y 			:= dir.o file.o inode.o nfs2xdr.o pagelist.o \
 nfs-$(CONFIG_ROOT_NFS)	+= nfsroot.o mount_clnt.o      
 nfs-$(CONFIG_NFS_V3)	+= nfs3proc.o nfs3xdr.o
 nfs-$(CONFIG_NFS_V4)	+= nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
-			   idmap.o
+			   delegation.o idmap.o \
+			   callback.o callback_xdr.o callback_proc.o
 nfs-$(CONFIG_NFS_DIRECTIO) += direct.o
 nfs-objs		:= $(nfs-y)
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index f061e70cd..626252aec 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -32,6 +32,8 @@
 #include <linux/smp_lock.h>
 #include <linux/namei.h>
 
+#include "delegation.h"
+
 #define NFS_PARANOIA 1
 /* #define NFS_DEBUG_VERBOSE 1 */
 
@@ -49,12 +51,14 @@ static int nfs_link(struct dentry *, struct inode *, struct dentry *);
 static int nfs_mknod(struct inode *, struct dentry *, int, dev_t);
 static int nfs_rename(struct inode *, struct dentry *,
 		      struct inode *, struct dentry *);
+static int nfs_fsync_dir(struct file *, struct dentry *, int);
 
 struct file_operations nfs_dir_operations = {
 	.read		= generic_read_dir,
 	.readdir	= nfs_readdir,
 	.open		= nfs_opendir,
 	.release	= nfs_release,
+	.fsync		= nfs_fsync_dir,
 };
 
 struct inode_operations nfs_dir_inode_operations = {
@@ -490,6 +494,15 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 	return 0;
 }
 
+/*
+ * All directory operations under NFS are synchronous, so fsync()
+ * is a dummy operation.
+ */
+int nfs_fsync_dir(struct file *filp, struct dentry *dentry, int datasync)
+{
+	return 0;
+}
+
 /*
  * A check for whether or not the parent directory has changed.
  * In the case it has, we assume that the dentries are untrustworthy
@@ -610,7 +623,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
 	verifier = nfs_save_change_attribute(dir);
 	error = nfs_cached_lookup(dir, dentry, &fhandle, &fattr);
 	if (!error) {
-		if (memcmp(NFS_FH(inode), &fhandle, sizeof(struct nfs_fh))!= 0)
+		if (nfs_compare_fh(NFS_FH(inode), &fhandle))
 			goto out_bad;
 		if (nfs_lookup_verify_inode(inode, isopen))
 			goto out_zap_parent;
@@ -623,7 +636,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
 	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
 	if (error)
 		goto out_bad;
-	if (memcmp(NFS_FH(inode), &fhandle, sizeof(struct nfs_fh))!= 0)
+	if (nfs_compare_fh(NFS_FH(inode), &fhandle))
 		goto out_bad;
 	if ((error = nfs_refresh_inode(inode, &fattr)) != 0)
 		goto out_bad;
@@ -850,22 +863,22 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
 	unsigned long verifier;
 	int openflags, ret = 0;
 
-	/* NFS only supports OPEN for regular files */
-	if (inode && !S_ISREG(inode->i_mode))
-		goto no_open;
 	parent = dget_parent(dentry);
 	dir = parent->d_inode;
 	if (!is_atomic_open(dir, nd))
 		goto no_open;
+	/* We can't create new files in nfs_open_revalidate(), so we
+	 * optimize away revalidation of negative dentries.
+	 */
+	if (inode == NULL)
+		goto out;
+	/* NFS only supports OPEN on regular files */
+	if (!S_ISREG(inode->i_mode))
+		goto no_open;
 	openflags = nd->intent.open.flags;
-	if (openflags & O_CREAT) {
-		/* If this is a negative dentry, just drop it */
-		if (!inode)
-			goto out;
-		/* If this is exclusive open, just revalidate */
-		if (openflags & O_EXCL)
-			goto no_open;
-	}
+	/* We cannot do exclusive creation on a positive dentry */
+	if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
+		goto no_open;
 	/* We can't create new files, or truncate existing ones here */
 	openflags &= ~(O_CREAT|O_TRUNC);
 
@@ -887,6 +900,8 @@ out:
 	return ret;
 no_open:
 	dput(parent);
+	if (inode != NULL && nfs_have_delegation(inode, FMODE_READ))
+		return 1;
 	return nfs_lookup_revalidate(dentry, nd);
 }
 #endif /* CONFIG_NFSV4 */
@@ -982,12 +997,18 @@ static int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
 	/* We may have been initialized further down */
 	if (dentry->d_inode)
 		return 0;
-	if (fhandle->size == 0 || !(fattr->valid & NFS_ATTR_FATTR)) {
+	if (fhandle->size == 0) {
 		struct inode *dir = dentry->d_parent->d_inode;
 		error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
 		if (error)
 			goto out_err;
 	}
+	if (!(fattr->valid & NFS_ATTR_FATTR)) {
+		struct nfs_server *server = NFS_SB(dentry->d_sb);
+		error = server->rpc_ops->getattr(server, fhandle, fattr);
+		if (error < 0)
+			goto out_err;
+	}
 	inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
 	if (inode) {
 		d_instantiate(dentry, inode);
@@ -1299,19 +1320,6 @@ nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
 	dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s)\n", dir->i_sb->s_id,
 		dir->i_ino, dentry->d_name.name, symname);
 
-	error = -ENAMETOOLONG;
-	switch (NFS_PROTO(dir)->version) {
-		case 2:
-			if (strlen(symname) > NFS2_MAXPATHLEN)
-				goto out;
-			break;
-		case 3:
-			if (strlen(symname) > NFS3_MAXPATHLEN)
-				goto out;
-		default:
-			break;
-	}
-
 #ifdef NFS_PARANOIA
 if (dentry->d_inode)
 printk("nfs_proc_symlink: %s/%s not negative!\n",
@@ -1341,8 +1349,6 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
 		d_drop(dentry);
 	}
 	unlock_kernel();
-
-out:
 	return error;
 }
 
@@ -1498,10 +1504,56 @@ out:
 	return error;
 }
 
-int
-nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
+int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs_access_entry *res)
+{
+	struct nfs_access_entry *cache = &NFS_I(inode)->cache_access;
+
+	if (cache->cred != cred
+			|| time_after(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode))
+			|| (NFS_FLAGS(inode) & NFS_INO_INVALID_ATTR))
+		return -ENOENT;
+	memcpy(res, cache, sizeof(*res));
+	return 0;
+}
+
+void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set)
+{
+	struct nfs_access_entry *cache = &NFS_I(inode)->cache_access;
+
+	if (cache->cred != set->cred) {
+		if (cache->cred)
+			put_rpccred(cache->cred);
+		cache->cred = get_rpccred(set->cred);
+	}
+	cache->jiffies = set->jiffies;
+	cache->mask = set->mask;
+}
+
+static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
+{
+	struct nfs_access_entry cache;
+	int status;
+
+	status = nfs_access_get_cached(inode, cred, &cache);
+	if (status == 0)
+		goto out;
+
+	/* Be clever: ask server to check for all possible rights */
+	cache.mask = MAY_EXEC | MAY_WRITE | MAY_READ;
+	cache.cred = cred;
+	cache.jiffies = jiffies;
+	status = NFS_PROTO(inode)->access(inode, &cache);
+	if (status != 0)
+		return status;
+	nfs_access_add_cache(inode, &cache);
+out:
+	if ((cache.mask & mask) == mask)
+		return 0;
+	return -EACCES;
+}
+
+int nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
 {
-	struct nfs_access_cache *cache = &NFS_I(inode)->cache_access;
 	struct rpc_cred *cred;
 	int mode = inode->i_mode;
 	int res;
@@ -1542,24 +1594,7 @@ nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
 		goto out_notsup;
 
 	cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
-	if (cache->cred == cred
-	    && time_before(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode))
-	    && !(NFS_FLAGS(inode) & NFS_INO_INVALID_ATTR)) {
-		if (!(res = cache->err)) {
-			/* Is the mask a subset of an accepted mask? */
-			if ((cache->mask & mask) == mask)
-				goto out;
-		} else {
-			/* ...or is it a superset of a rejected mask? */
-			if ((cache->mask & mask) == cache->mask)
-				goto out;
-		}
-	}
-
-	res = NFS_PROTO(inode)->access(inode, cred, mask);
-	if (!res || res == -EACCES)
-		goto add_cache;
-out:
+	res = nfs_do_access(inode, cred, mask);
 	put_rpccred(cred);
 	unlock_kernel();
 	return res;
@@ -1568,15 +1603,6 @@ out_notsup:
 	res = vfs_permission(inode, mask);
 	unlock_kernel();
 	return res;
-add_cache:
-	cache->jiffies = jiffies;
-	if (cache->cred)
-		put_rpccred(cache->cred);
-	cache->cred = cred;
-	cache->mask = mask;
-	cache->err = res;
-	unlock_kernel();
-	return res;
 }
 
 /*
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index e4e228ea9..21c3c4d39 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -110,7 +110,7 @@ nfs_free_user_pages(struct page **pages, int npages, int do_dirty)
  * nfs_direct_read_seg - Read in one iov segment.  Generate separate
  *                        read RPCs for each "rsize" bytes.
  * @inode: target inode
- * @file: target file (may be NULL)
+ * @ctx: target file open context
  * user_addr: starting address of this segment of user's buffer
  * count: size of this segment
  * file_offset: offset in file to begin the operation
@@ -118,7 +118,7 @@ nfs_free_user_pages(struct page **pages, int npages, int do_dirty)
  * nr_pages: size of pages array
  */
 static int
-nfs_direct_read_seg(struct inode *inode, struct file *file,
+nfs_direct_read_seg(struct inode *inode, struct nfs_open_context *ctx,
 		unsigned long user_addr, size_t count, loff_t file_offset,
 		struct page **pages, int nr_pages)
 {
@@ -127,9 +127,10 @@ nfs_direct_read_seg(struct inode *inode, struct file *file,
 	int curpage = 0;
 	struct nfs_read_data	rdata = {
 		.inode		= inode,
+		.cred		= ctx->cred,
 		.args		= {
 			.fh		= NFS_FH(inode),
-			.lockowner	= current->files,
+			.context	= ctx,
 		},
 		.res		= {
 			.fattr		= &rdata.fattr,
@@ -151,7 +152,7 @@ nfs_direct_read_seg(struct inode *inode, struct file *file,
 			user_addr + tot_bytes, rdata.args.pgbase, curpage);
 
 		lock_kernel();
-		result = NFS_PROTO(inode)->read(&rdata, file);
+		result = NFS_PROTO(inode)->read(&rdata);
 		unlock_kernel();
 
 		if (result <= 0) {
@@ -183,7 +184,7 @@ nfs_direct_read_seg(struct inode *inode, struct file *file,
  * nfs_direct_read - For each iov segment, map the user's buffer
  *                   then generate read RPCs.
  * @inode: target inode
- * @file: target file (may be NULL)
+ * @ctx: target file open context
  * @iov: array of vectors that define I/O buffer
  * file_offset: offset in file to begin the operation
  * nr_segs: size of iovec array
@@ -193,7 +194,7 @@ nfs_direct_read_seg(struct inode *inode, struct file *file,
  * server.
  */
 static ssize_t
-nfs_direct_read(struct inode *inode, struct file *file,
+nfs_direct_read(struct inode *inode, struct nfs_open_context *ctx,
 		const struct iovec *iov, loff_t file_offset,
 		unsigned long nr_segs)
 {
@@ -216,7 +217,7 @@ nfs_direct_read(struct inode *inode, struct file *file,
                         return page_count;
                 }
 
-		result = nfs_direct_read_seg(inode, file, user_addr, size,
+		result = nfs_direct_read_seg(inode, ctx, user_addr, size,
 				file_offset, pages, page_count);
 
 		nfs_free_user_pages(pages, page_count, 1);
@@ -239,7 +240,7 @@ nfs_direct_read(struct inode *inode, struct file *file,
  * nfs_direct_write_seg - Write out one iov segment.  Generate separate
  *                        write RPCs for each "wsize" bytes, then commit.
  * @inode: target inode
- * @file: target file (may be NULL)
+ * @ctx: target file open context
  * user_addr: starting address of this segment of user's buffer
  * count: size of this segment
  * file_offset: offset in file to begin the operation
@@ -247,7 +248,7 @@ nfs_direct_read(struct inode *inode, struct file *file,
  * nr_pages: size of pages array
  */
 static int
-nfs_direct_write_seg(struct inode *inode, struct file *file,
+nfs_direct_write_seg(struct inode *inode, struct nfs_open_context *ctx,
 		unsigned long user_addr, size_t count, loff_t file_offset,
 		struct page **pages, int nr_pages)
 {
@@ -257,9 +258,10 @@ nfs_direct_write_seg(struct inode *inode, struct file *file,
 	struct nfs_writeverf first_verf;
 	struct nfs_write_data	wdata = {
 		.inode		= inode,
+		.cred		= ctx->cred,
 		.args		= {
 			.fh		= NFS_FH(inode),
-			.lockowner	= current->files,
+			.context	= ctx,
 		},
 		.res		= {
 			.fattr		= &wdata.fattr,
@@ -290,7 +292,7 @@ retry:
 			user_addr + tot_bytes, wdata.args.pgbase, curpage);
 
 		lock_kernel();
-		result = NFS_PROTO(inode)->write(&wdata, file);
+		result = NFS_PROTO(inode)->write(&wdata);
 		unlock_kernel();
 
 		if (result <= 0) {
@@ -325,7 +327,7 @@ retry:
 		wdata.args.offset = file_offset;
 
 		lock_kernel();
-		result = NFS_PROTO(inode)->commit(&wdata, file);
+		result = NFS_PROTO(inode)->commit(&wdata);
 		unlock_kernel();
 
 		if (result < 0 || memcmp(&first_verf.verifier,
@@ -349,7 +351,7 @@ sync_retry:
  * nfs_direct_write - For each iov segment, map the user's buffer
  *                    then generate write and commit RPCs.
  * @inode: target inode
- * @file: target file (may be NULL)
+ * @ctx: target file open context
  * @iov: array of vectors that define I/O buffer
  * file_offset: offset in file to begin the operation
  * nr_segs: size of iovec array
@@ -358,8 +360,7 @@ sync_retry:
  * that non-direct readers might access, so they will pick up these
  * writes immediately.
  */
-static ssize_t
-nfs_direct_write(struct inode *inode, struct file *file,
+static int nfs_direct_write(struct inode *inode, struct nfs_open_context *ctx,
 		const struct iovec *iov, loff_t file_offset,
 		unsigned long nr_segs)
 {
@@ -382,7 +383,7 @@ nfs_direct_write(struct inode *inode, struct file *file,
                         return page_count;
                 }
 
-		result = nfs_direct_write_seg(inode, file, user_addr, size,
+		result = nfs_direct_write_seg(inode, ctx, user_addr, size,
 				file_offset, pages, page_count);
 		nfs_free_user_pages(pages, page_count, 0);
 
@@ -414,6 +415,7 @@ nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
 {
 	ssize_t result = -EINVAL;
 	struct file *file = iocb->ki_filp;
+	struct nfs_open_context *ctx;
 	struct dentry *dentry = file->f_dentry;
 	struct inode *inode = dentry->d_inode;
 
@@ -423,19 +425,20 @@ nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
 	if (!is_sync_kiocb(iocb))
 		return result;
 
+	ctx = (struct nfs_open_context *)file->private_data;
 	switch (rw) {
 	case READ:
 		dprintk("NFS: direct_IO(read) (%s) off/no(%Lu/%lu)\n",
 				dentry->d_name.name, file_offset, nr_segs);
 
-		result = nfs_direct_read(inode, file, iov,
+		result = nfs_direct_read(inode, ctx, iov,
 						file_offset, nr_segs);
 		break;
 	case WRITE:
 		dprintk("NFS: direct_IO(write) (%s) off/no(%Lu/%lu)\n",
 				dentry->d_name.name, file_offset, nr_segs);
 
-		result = nfs_direct_write(inode, file, iov,
+		result = nfs_direct_write(inode, ctx, iov,
 						file_offset, nr_segs);
 		break;
 	default:
@@ -471,6 +474,8 @@ nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t
 	ssize_t retval = -EINVAL;
 	loff_t *ppos = &iocb->ki_pos;
 	struct file *file = iocb->ki_filp;
+	struct nfs_open_context *ctx =
+			(struct nfs_open_context *) file->private_data;
 	struct dentry *dentry = file->f_dentry;
 	struct address_space *mapping = file->f_mapping;
 	struct inode *inode = mapping->host;
@@ -502,7 +507,7 @@ nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t
 			goto out;
 	}
 
-	retval = nfs_direct_read(inode, file, &iov, pos, 1);
+	retval = nfs_direct_read(inode, ctx, &iov, pos, 1);
 	if (retval > 0)
 		*ppos = pos + retval;
 
@@ -542,6 +547,8 @@ nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count,
 	loff_t *ppos = &iocb->ki_pos;
 	unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
 	struct file *file = iocb->ki_filp;
+	struct nfs_open_context *ctx =
+			(struct nfs_open_context *) file->private_data;
 	struct dentry *dentry = file->f_dentry;
 	struct address_space *mapping = file->f_mapping;
 	struct inode *inode = mapping->host;
@@ -589,7 +596,7 @@ nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count,
 			goto out;
 	}
 
-	retval = nfs_direct_write(inode, file, &iov, pos, 1);
+	retval = nfs_direct_write(inode, ctx, &iov, pos, 1);
 	if (mapping->nrpages)
 		invalidate_inode_pages2(mapping);
 	if (retval > 0)
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index ee2addb5c..21071ddd4 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -31,6 +31,8 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
+#include "delegation.h"
+
 #define NFSDBG_FACILITY		NFSDBG_FILE
 
 static int nfs_file_open(struct inode *, struct file *);
@@ -72,7 +74,7 @@ struct inode_operations nfs_file_inode_operations = {
 
 static int nfs_check_flags(int flags)
 {
-	if (flags & (O_APPEND | O_DIRECT))
+	if ((flags & (O_APPEND | O_DIRECT)) == (O_APPEND | O_DIRECT))
 		return -EINVAL;
 
 	return 0;
@@ -89,7 +91,7 @@ nfs_file_open(struct inode *inode, struct file *filp)
 	int res;
 
 	res = nfs_check_flags(filp->f_flags);
-	if (!res)
+	if (res)
 		return res;
 
 	lock_kernel();
@@ -113,6 +115,7 @@ nfs_file_release(struct inode *inode, struct file *filp)
 static int
 nfs_file_flush(struct file *file)
 {
+	struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
 	struct inode	*inode = file->f_dentry->d_inode;
 	int		status;
 
@@ -124,9 +127,9 @@ nfs_file_flush(struct file *file)
 	/* Ensure that data+attribute caches are up to date after close() */
 	status = nfs_wb_all(inode);
 	if (!status) {
-		status = file->f_error;
-		file->f_error = 0;
-		if (!status)
+		status = ctx->error;
+		ctx->error = 0;
+		if (!status && !nfs_have_delegation(inode, FMODE_READ))
 			__nfs_revalidate_inode(NFS_SERVER(inode), inode);
 	}
 	unlock_kernel();
@@ -197,6 +200,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
 static int
 nfs_fsync(struct file *file, struct dentry *dentry, int datasync)
 {
+	struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
 	struct inode *inode = dentry->d_inode;
 	int status;
 
@@ -205,8 +209,8 @@ nfs_fsync(struct file *file, struct dentry *dentry, int datasync)
 	lock_kernel();
 	status = nfs_wb_all(inode);
 	if (!status) {
-		status = file->f_error;
-		file->f_error = 0;
+		status = ctx->error;
+		ctx->error = 0;
 	}
 	unlock_kernel();
 	return status;
@@ -288,6 +292,90 @@ out_swapfile:
 	goto out;
 }
 
+static int do_getlk(struct file *filp, int cmd, struct file_lock *fl)
+{
+	struct inode *inode = filp->f_mapping->host;
+	int status;
+
+	lock_kernel();
+	status = NFS_PROTO(inode)->lock(filp, cmd, fl);
+	unlock_kernel();
+	return status;
+}
+
+static int do_unlk(struct file *filp, int cmd, struct file_lock *fl)
+{
+	struct inode *inode = filp->f_mapping->host;
+	sigset_t oldset;
+	int status;
+
+	rpc_clnt_sigmask(NFS_CLIENT(inode), &oldset);
+	/*
+	 * Flush all pending writes before doing anything
+	 * with locks..
+	 */
+	filemap_fdatawrite(filp->f_mapping);
+	down(&inode->i_sem);
+	nfs_wb_all(inode);
+	up(&inode->i_sem);
+	filemap_fdatawait(filp->f_mapping);
+
+	/* NOTE: special case
+	 * 	If we're signalled while cleaning up locks on process exit, we
+	 * 	still need to complete the unlock.
+	 */
+	lock_kernel();
+	status = NFS_PROTO(inode)->lock(filp, cmd, fl);
+	rpc_clnt_sigunmask(NFS_CLIENT(inode), &oldset);
+	return status;
+}
+
+static int do_setlk(struct file *filp, int cmd, struct file_lock *fl)
+{
+	struct inode *inode = filp->f_mapping->host;
+	int status;
+
+	/*
+	 * Flush all pending writes before doing anything
+	 * with locks..
+	 */
+	status = filemap_fdatawrite(filp->f_mapping);
+	if (status == 0) {
+		down(&inode->i_sem);
+		status = nfs_wb_all(inode);
+		up(&inode->i_sem);
+		if (status == 0)
+			status = filemap_fdatawait(filp->f_mapping);
+	}
+	if (status < 0)
+		return status;
+
+	lock_kernel();
+	status = NFS_PROTO(inode)->lock(filp, cmd, fl);
+	/* If we were signalled we still need to ensure that
+	 * we clean up any state on the server. We therefore
+	 * record the lock call as having succeeded in order to
+	 * ensure that locks_remove_posix() cleans it out when
+	 * the process exits.
+	 */
+	if (status == -EINTR || status == -ERESTARTSYS)
+		posix_lock_file(filp, fl);
+	unlock_kernel();
+	if (status < 0)
+		return status;
+	/*
+	 * Make sure we clear the cache whenever we try to get the lock.
+	 * This makes locking act as a cache coherency point.
+	 */
+	filemap_fdatawrite(filp->f_mapping);
+	down(&inode->i_sem);
+	nfs_wb_all(inode);	/* we may have slept */
+	up(&inode->i_sem);
+	filemap_fdatawait(filp->f_mapping);
+	nfs_zap_caches(inode);
+	return 0;
+}
+
 /*
  * Lock a (portion of) a file
  */
@@ -295,8 +383,6 @@ int
 nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
 {
 	struct inode * inode = filp->f_mapping->host;
-	int	status = 0;
-	int	status2;
 
 	dprintk("NFS: nfs_lock(f=%s/%ld, t=%x, fl=%x, r=%Ld:%Ld)\n",
 			inode->i_sb->s_id, inode->i_ino,
@@ -314,8 +400,8 @@ nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
 		/* Fake OK code if mounted without NLM support */
 		if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM) {
 			if (IS_GETLK(cmd))
-				status = LOCK_USE_CLNT;
-			goto out_ok;
+				return LOCK_USE_CLNT;
+			return 0;
 		}
 	}
 
@@ -329,42 +415,9 @@ nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
 	if (!fl->fl_owner || !(fl->fl_flags & FL_POSIX))
 		return -ENOLCK;
 
-	/*
-	 * Flush all pending writes before doing anything
-	 * with locks..
-	 */
-	status = filemap_fdatawrite(filp->f_mapping);
-	down(&inode->i_sem);
-	status2 = nfs_wb_all(inode);
-	if (!status)
-		status = status2;
-	up(&inode->i_sem);
-	status2 = filemap_fdatawait(filp->f_mapping);
-	if (!status)
-		status = status2;
-	if (status < 0)
-		return status;
-
-	lock_kernel();
-	status = NFS_PROTO(inode)->lock(filp, cmd, fl);
-	unlock_kernel();
-	if (status < 0)
-		return status;
-	
-	status = 0;
-
-	/*
-	 * Make sure we clear the cache whenever we try to get the lock.
-	 * This makes locking act as a cache coherency point.
-	 */
- out_ok:
-	if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) {
-		filemap_fdatawrite(filp->f_mapping);
-		down(&inode->i_sem);
-		nfs_wb_all(inode);      /* we may have slept */
-		up(&inode->i_sem);
-		filemap_fdatawait(filp->f_mapping);
-		nfs_zap_caches(inode);
-	}
-	return status;
+	if (IS_GETLK(cmd))
+		return do_getlk(filp, cmd, fl);
+	if (fl->fl_type == F_UNLCK)
+		return do_unlk(filp, cmd, fl);
+	return do_setlk(filp, cmd, fl);
 }
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 7f25c31fd..60b307478 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -40,6 +40,8 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
+#include "delegation.h"
+
 #define NFSDBG_FACILITY		NFSDBG_VFS
 #define NFS_PARANOIA 1
 
@@ -56,9 +58,8 @@ static int nfs_update_inode(struct inode *, struct nfs_fattr *, unsigned long);
 
 static struct inode *nfs_alloc_inode(struct super_block *sb);
 static void nfs_destroy_inode(struct inode *);
-static void nfs_write_inode(struct inode *,int);
+static int nfs_write_inode(struct inode *,int);
 static void nfs_delete_inode(struct inode *);
-static void nfs_put_super(struct super_block *);
 static void nfs_clear_inode(struct inode *);
 static void nfs_umount_begin(struct super_block *);
 static int  nfs_statfs(struct super_block *, struct kstatfs *);
@@ -69,7 +70,6 @@ static struct super_operations nfs_sops = {
 	.destroy_inode	= nfs_destroy_inode,
 	.write_inode	= nfs_write_inode,
 	.delete_inode	= nfs_delete_inode,
-	.put_super	= nfs_put_super,
 	.statfs		= nfs_statfs,
 	.clear_inode	= nfs_clear_inode,
 	.umount_begin	= nfs_umount_begin,
@@ -111,12 +111,16 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr)
 	return nfs_fileid_to_ino_t(fattr->fileid);
 }
 
-static void
+static int
 nfs_write_inode(struct inode *inode, int sync)
 {
 	int flags = sync ? FLUSH_WAIT : 0;
+	int ret;
 
-	nfs_commit_inode(inode, 0, 0, flags);
+	ret = nfs_commit_inode(inode, 0, 0, flags);
+	if (ret < 0)
+		return ret;
+	return 0;
 }
 
 static void
@@ -124,8 +128,9 @@ nfs_delete_inode(struct inode * inode)
 {
 	dprintk("NFS: delete_inode(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino);
 
+	nfs_wb_all(inode);
 	/*
-	 * The following can never actually happen...
+	 * The following should never happen...
 	 */
 	if (nfs_have_writebacks(inode)) {
 		printk(KERN_ERR "nfs_delete_inode: inode %ld has pending RPC requests\n", inode->i_ino);
@@ -142,37 +147,16 @@ static void
 nfs_clear_inode(struct inode *inode)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
-	struct rpc_cred *cred = nfsi->mm_cred;
+	struct rpc_cred *cred;
 
-	if (cred)
-		put_rpccred(cred);
+	nfs_wb_all(inode);
+	BUG_ON (!list_empty(&nfsi->open_files));
 	cred = nfsi->cache_access.cred;
 	if (cred)
 		put_rpccred(cred);
 	BUG_ON(atomic_read(&nfsi->data_updates) != 0);
 }
 
-void
-nfs_put_super(struct super_block *sb)
-{
-	struct nfs_server *server = NFS_SB(sb);
-
-	nfs4_renewd_prepare_shutdown(server);
-
-	if (server->client != NULL)
-		rpc_shutdown_client(server->client);
-	if (server->client_sys != NULL)
-		rpc_shutdown_client(server->client_sys);
-
-	if (!(server->flags & NFS_MOUNT_NONLM))
-		lockd_down();	/* release rpc.lockd */
-	rpciod_down();		/* release rpciod */
-
-	destroy_nfsv4_state(server);
-
-	kfree(server->hostname);
-}
-
 void
 nfs_umount_begin(struct super_block *sb)
 {
@@ -294,14 +278,6 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
 		server->rsize = nfs_block_size(fsinfo.rtpref, NULL);
 	if (server->wsize == 0)
 		server->wsize = nfs_block_size(fsinfo.wtpref, NULL);
-	if (sb->s_blocksize == 0) {
-		if (fsinfo.wtmult == 0) {
-			sb->s_blocksize = 512;
-			sb->s_blocksize_bits = 9;
-		} else
-			sb->s_blocksize = nfs_block_bits(fsinfo.wtmult,
-							 &sb->s_blocksize_bits);
-	}
 
 	if (fsinfo.rtmax >= 512 && server->rsize > fsinfo.rtmax)
 		server->rsize = nfs_block_size(fsinfo.rtmax, NULL);
@@ -320,6 +296,11 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
                 server->wsize = server->wpages << PAGE_CACHE_SHIFT;
 	}
 
+	if (sb->s_blocksize == 0)
+		sb->s_blocksize = nfs_block_bits(server->wsize,
+							 &sb->s_blocksize_bits);
+	server->wtmult = nfs_block_bits(fsinfo.wtmult, NULL);
+
 	server->dtsize = nfs_block_size(fsinfo.dtpref, NULL);
 	if (server->dtsize > PAGE_CACHE_SIZE)
 		server->dtsize = PAGE_CACHE_SIZE;
@@ -410,7 +391,6 @@ static int
 nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
 {
 	struct nfs_server	*server;
-	int			err = -EIO;
 	rpc_authflavor_t	authflavor;
 
 	server           = NFS_SB(sb);
@@ -429,10 +409,14 @@ nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
 	server->acdirmin = data->acdirmin*HZ;
 	server->acdirmax = data->acdirmax*HZ;
 
+	/* Start lockd here, before we might error out */
+	if (!(server->flags & NFS_MOUNT_NONLM))
+		lockd_up();
+
 	server->namelen  = data->namlen;
 	server->hostname = kmalloc(strlen(data->hostname) + 1, GFP_KERNEL);
 	if (!server->hostname)
-		goto out_fail;
+		return -ENOMEM;
 	strcpy(server->hostname, data->hostname);
 
 	/* Check NFS protocol revision and initialize RPC op vector
@@ -443,11 +427,11 @@ nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
 		server->caps |= NFS_CAP_READDIRPLUS;
 		if (data->version < 4) {
 			printk(KERN_NOTICE "NFS: NFSv3 not supported by mount program.\n");
-			goto out_fail;
+			return -EIO;
 		}
 #else
 		printk(KERN_NOTICE "NFS: NFSv3 not supported.\n");
-		goto out_fail;
+		return -EIO;
 #endif
 	} else {
 		server->rpc_ops = &nfs_v2_clientops;
@@ -462,30 +446,19 @@ nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
 	/* Create RPC client handles */
 	server->client = nfs_create_client(server, data);
 	if (IS_ERR(server->client))
-		goto out_fail;
+		return PTR_ERR(server->client);
 	/* RFC 2623, sec 2.3.2 */
 	if (authflavor != RPC_AUTH_UNIX) {
 		server->client_sys = rpc_clone_client(server->client);
-		if (server->client_sys == NULL)
-			goto out_shutdown;
+		if (IS_ERR(server->client_sys))
+			return PTR_ERR(server->client_sys);
 		if (!rpcauth_create(RPC_AUTH_UNIX, server->client_sys))
-			goto out_shutdown;
+			return -ENOMEM;
 	} else {
 		atomic_inc(&server->client->cl_count);
 		server->client_sys = server->client;
 	}
 
-	/* Fire up rpciod if not yet running */
-	if (rpciod_up() != 0) {
-		printk(KERN_WARNING "NFS: couldn't start rpciod!\n");
-		goto out_shutdown;
-	}
-
-	sb->s_op = &nfs_sops;
-	err = nfs_sb_init(sb, authflavor);
-	if (err != 0)
-		goto out_noinit;
-
 	if (server->flags & NFS_MOUNT_VER3) {
 		if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)
 			server->namelen = NFS3_MAXNAMLEN;
@@ -494,21 +467,8 @@ nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
 			server->namelen = NFS2_MAXNAMLEN;
 	}
 
-	/* Check whether to start the lockd process */
-	if (!(server->flags & NFS_MOUNT_NONLM))
-		lockd_up();
-	return 0;
-out_noinit:
-	rpciod_down();
-out_shutdown:
-	if (server->client)
-		rpc_shutdown_client(server->client);
-	if (server->client_sys)
-		rpc_shutdown_client(server->client_sys);
-out_fail:
-	if (server->hostname)
-		kfree(server->hostname);
-	return err;
+	sb->s_op = &nfs_sops;
+	return nfs_sb_init(sb, authflavor);
 }
 
 static int
@@ -531,6 +491,7 @@ nfs_statfs(struct super_block *sb, struct kstatfs *buf)
 	if (error < 0)
 		goto out_err;
 
+	buf->f_frsize = server->wtmult;
 	buf->f_bsize = sb->s_blocksize;
 	blockbits = sb->s_blocksize_bits;
 	blockres = (1 << blockbits) - 1;
@@ -648,7 +609,7 @@ nfs_find_actor(struct inode *inode, void *opaque)
 
 	if (NFS_FILEID(inode) != fattr->fileid)
 		return 0;
-	if (memcmp(NFS_FH(inode), fh, sizeof(struct nfs_fh)) != 0)
+	if (nfs_compare_fh(NFS_FH(inode), fh))
 		return 0;
 	if (is_bad_inode(inode))
 		return 0;
@@ -659,11 +620,10 @@ static int
 nfs_init_locked(struct inode *inode, void *opaque)
 {
 	struct nfs_find_desc	*desc = (struct nfs_find_desc *)opaque;
-	struct nfs_fh		*fh = desc->fh;
 	struct nfs_fattr	*fattr = desc->fattr;
 
 	NFS_FILEID(inode) = fattr->fileid;
-	memcpy(NFS_FH(inode), fh, sizeof(struct nfs_fh));
+	nfs_copy_fh(NFS_FH(inode), desc->fh);
 	return 0;
 }
 
@@ -765,8 +725,8 @@ out:
 	return inode;
 /*
 fail_dlim:
-        make_bad_inode(inode);
-        iput(inode);
+	make_bad_inode(inode);
+	iput(inode);
 	inode = NULL;
 */
 out_no_inode:
@@ -774,8 +734,7 @@ out_no_inode:
 	goto out;
 }
 
-#define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_XID|ATTR_SIZE|\
-			 ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET)
+#define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET)
 
 int
 nfs_setattr(struct dentry *dentry, struct iattr *attr)
@@ -875,53 +834,114 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 	return err;
 }
 
+struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rpc_cred *cred)
+{
+	struct nfs_open_context *ctx;
+
+	ctx = (struct nfs_open_context *)kmalloc(sizeof(*ctx), GFP_KERNEL);
+	if (ctx != NULL) {
+		atomic_set(&ctx->count, 1);
+		ctx->dentry = dget(dentry);
+		ctx->cred = get_rpccred(cred);
+		ctx->state = NULL;
+		ctx->lockowner = current->files;
+		ctx->error = 0;
+		init_waitqueue_head(&ctx->waitq);
+	}
+	return ctx;
+}
+
+struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx)
+{
+	if (ctx != NULL)
+		atomic_inc(&ctx->count);
+	return ctx;
+}
+
+void put_nfs_open_context(struct nfs_open_context *ctx)
+{
+	if (atomic_dec_and_test(&ctx->count)) {
+		if (ctx->state != NULL)
+			nfs4_close_state(ctx->state, ctx->mode);
+		if (ctx->cred != NULL)
+			put_rpccred(ctx->cred);
+		dput(ctx->dentry);
+		kfree(ctx);
+	}
+}
+
 /*
  * Ensure that mmap has a recent RPC credential for use when writing out
  * shared pages
  */
-void
-nfs_set_mmcred(struct inode *inode, struct rpc_cred *cred)
+void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
+{
+	struct inode *inode = filp->f_dentry->d_inode;
+	struct nfs_inode *nfsi = NFS_I(inode);
+
+	filp->private_data = get_nfs_open_context(ctx);
+	spin_lock(&inode->i_lock);
+	list_add(&ctx->list, &nfsi->open_files);
+	spin_unlock(&inode->i_lock);
+}
+
+struct nfs_open_context *nfs_find_open_context(struct inode *inode, int mode)
 {
-	struct rpc_cred **p = &NFS_I(inode)->mm_cred,
-			*oldcred = *p;
+	struct nfs_inode *nfsi = NFS_I(inode);
+	struct nfs_open_context *pos, *ctx = NULL;
+
+	spin_lock(&inode->i_lock);
+	list_for_each_entry(pos, &nfsi->open_files, list) {
+		if ((pos->mode & mode) == mode) {
+			ctx = get_nfs_open_context(pos);
+			break;
+		}
+	}
+	spin_unlock(&inode->i_lock);
+	return ctx;
+}
 
-	*p = get_rpccred(cred);
-	if (oldcred)
-		put_rpccred(oldcred);
+void nfs_file_clear_open_context(struct file *filp)
+{
+	struct inode *inode = filp->f_dentry->d_inode;
+	struct nfs_open_context *ctx = (struct nfs_open_context *)filp->private_data;
+
+	if (ctx) {
+		filp->private_data = NULL;
+		spin_lock(&inode->i_lock);
+		list_del(&ctx->list);
+		spin_unlock(&inode->i_lock);
+		put_nfs_open_context(ctx);
+	}
 }
 
 /*
- * These are probably going to contain hooks for
- * allocating and releasing RPC credentials for
- * the file. I'll have to think about Tronds patch
- * a bit more..
+ * These allocate and release file read/write context information.
  */
 int nfs_open(struct inode *inode, struct file *filp)
 {
-	struct rpc_auth *auth;
+	struct nfs_open_context *ctx;
 	struct rpc_cred *cred;
 
-	auth = NFS_CLIENT(inode)->cl_auth;
-	cred = rpcauth_lookupcred(auth, 0);
-	filp->private_data = cred;
-	if ((filp->f_mode & FMODE_WRITE) != 0) {
-		nfs_set_mmcred(inode, cred);
+	if ((cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0)) == NULL)
+		return -ENOMEM;
+	ctx = alloc_nfs_open_context(filp->f_dentry, cred);
+	put_rpccred(cred);
+	if (ctx == NULL)
+		return -ENOMEM;
+	ctx->mode = filp->f_mode;
+	nfs_file_set_open_context(filp, ctx);
+	put_nfs_open_context(ctx);
+	if ((filp->f_mode & FMODE_WRITE) != 0)
 		nfs_begin_data_update(inode);
-	}
 	return 0;
 }
 
 int nfs_release(struct inode *inode, struct file *filp)
 {
-	struct rpc_cred *cred;
-
-	lock_kernel();
 	if ((filp->f_mode & FMODE_WRITE) != 0)
 		nfs_end_data_update(inode);
-	cred = nfs_file_cred(filp);
-	if (cred)
-		put_rpccred(cred);
-	unlock_kernel();
+	nfs_file_clear_open_context(filp);
 	return 0;
 }
 
@@ -962,7 +982,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 
 	/* Protect against RPC races by saving the change attribute */
 	verifier = nfs_save_change_attribute(inode);
-	status = NFS_PROTO(inode)->getattr(inode, &fattr);
+	status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr);
 	if (status) {
 		dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n",
 			 inode->i_sb->s_id,
@@ -1018,6 +1038,30 @@ out:
 	return status;
 }
 
+int nfs_attribute_timeout(struct inode *inode)
+{
+	struct nfs_inode *nfsi = NFS_I(inode);
+
+	if (nfs_have_delegation(inode, FMODE_READ))
+		return 0;
+	return time_after(jiffies, nfsi->read_cache_jiffies+nfsi->attrtimeo);
+}
+
+/**
+ * nfs_revalidate_inode - Revalidate the inode attributes
+ * @server - pointer to nfs_server struct
+ * @inode - pointer to inode struct
+ *
+ * Updates inode attribute information by retrieving the data from the server.
+ */
+int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
+{
+	if (!(NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))
+			&& !nfs_attribute_timeout(inode))
+		return NFS_STALE(inode) ? -ESTALE : 0;
+	return __nfs_revalidate_inode(server, inode);
+}
+
 /**
  * nfs_begin_data_update
  * @inode - pointer to inode
@@ -1039,11 +1083,13 @@ void nfs_end_data_update(struct inode *inode)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 
-	/* Mark the attribute cache for revalidation */
-	nfsi->flags |= NFS_INO_INVALID_ATTR;
-	/* Directories and symlinks: invalidate page cache too */
-	if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
-		nfsi->flags |= NFS_INO_INVALID_DATA;
+	if (!nfs_have_delegation(inode, FMODE_READ)) {
+		/* Mark the attribute cache for revalidation */
+		nfsi->flags |= NFS_INO_INVALID_ATTR;
+		/* Directories and symlinks: invalidate page cache too */
+		if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
+			nfsi->flags |= NFS_INO_INVALID_DATA;
+	}
 	nfsi->cache_change_attribute ++;
 	atomic_dec(&nfsi->data_updates);
 }
@@ -1087,6 +1133,10 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
 	gid_t gid;
 	xid_t xid = 0;
 
+	/* Do we hold a delegation? */
+	if (nfs_have_delegation(inode, FMODE_READ))
+		return 0;
+
 	/* Are we in the process of updating data on the server? */
 	data_unstable = nfs_caches_unstable(inode);
 
@@ -1298,7 +1348,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
 				|| S_ISLNK(inode->i_mode)))
 		invalid &= ~NFS_INO_INVALID_DATA;
-	nfsi->flags |= invalid;
+	if (!nfs_have_delegation(inode, FMODE_READ))
+		nfsi->flags |= invalid;
 
 	return 0;
  out_changed:
@@ -1338,7 +1389,7 @@ static int nfs_compare_super(struct super_block *sb, void *data)
 		return 0;
 	if (old->addr.sin_port != server->addr.sin_port)
 		return 0;
-	return !memcmp(&old->fh, &server->fh, sizeof(struct nfs_fh));
+	return !nfs_compare_fh(&old->fh, &server->fh);
 }
 
 static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
@@ -1362,11 +1413,6 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
 	/* Zero out the NFS state stuff */
 	init_nfsv4_state(server);
 
-	root = &server->fh;
-	memcpy(root, &data->root, sizeof(*root));
-	if (root->size < sizeof(root->data))
-		memset(root->data+root->size, 0, sizeof(root->data)-root->size);
-
 	if (data->version != NFS_MOUNT_VERSION) {
 		printk("nfs warning: mount version %s than kernel\n",
 			data->version < NFS_MOUNT_VERSION ? "older" : "newer");
@@ -1376,19 +1422,25 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
 			data->bsize  = 0;
 		if (data->version < 4) {
 			data->flags &= ~NFS_MOUNT_VER3;
-			memset(root, 0, sizeof(*root));
-			root->size = NFS2_FHSIZE;
-			memcpy(root->data, data->old_root.data, NFS2_FHSIZE);
+			data->root.size = NFS2_FHSIZE;
+			memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
 		}
 		if (data->version < 5)
 			data->flags &= ~NFS_MOUNT_SECFLAVOUR;
 	}
 
+	root = &server->fh;
+	if (data->flags & NFS_MOUNT_VER3)
+		root->size = data->root.size;
+	else
+		root->size = NFS2_FHSIZE;
 	if (root->size > sizeof(root->data)) {
 		printk("nfs_get_sb: invalid root filehandle\n");
 		kfree(server);
 		return ERR_PTR(-EINVAL);
 	}
+	memcpy(root->data, data->root.data, root->size);
+
 	/* We now require that the mount process passes the remote address */
 	memcpy(&server->addr, &data->addr, sizeof(server->addr));
 	if (server->addr.sin_addr.s_addr == INADDR_ANY) {
@@ -1406,6 +1458,13 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
 
 	s->s_flags = flags;
 
+	/* Fire up rpciod if not yet running */
+	if (rpciod_up() != 0) {
+		printk(KERN_WARNING "NFS: couldn't start rpciod!\n");
+		kfree(server);
+		return ERR_PTR(-EIO);
+	}
+
 	error = nfs_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
 	if (error) {
 		up_write(&s->s_umount);
@@ -1419,7 +1478,25 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
 static void nfs_kill_super(struct super_block *s)
 {
 	struct nfs_server *server = NFS_SB(s);
+
 	kill_anon_super(s);
+
+	nfs4_renewd_prepare_shutdown(server);
+
+	if (server->client != NULL && !IS_ERR(server->client))
+		rpc_shutdown_client(server->client);
+	if (server->client_sys != NULL && !IS_ERR(server->client_sys))
+		rpc_shutdown_client(server->client_sys);
+
+	if (!(server->flags & NFS_MOUNT_NONLM))
+		lockd_down();	/* release rpc.lockd */
+
+	rpciod_down();		/* release rpciod */
+
+	destroy_nfsv4_state(server);
+
+	if (server->hostname != NULL)
+		kfree(server->hostname);
 	kfree(server);
 }
 
@@ -1435,12 +1512,12 @@ static struct file_system_type nfs_fs_type = {
 
 static void nfs4_clear_inode(struct inode *);
 
+
 static struct super_operations nfs4_sops = { 
 	.alloc_inode	= nfs_alloc_inode,
 	.destroy_inode	= nfs_destroy_inode,
 	.write_inode	= nfs_write_inode,
 	.delete_inode	= nfs_delete_inode,
-	.put_super	= nfs_put_super,
 	.statfs		= nfs_statfs,
 	.clear_inode	= nfs4_clear_inode,
 	.umount_begin	= nfs_umount_begin,
@@ -1456,6 +1533,12 @@ static void nfs4_clear_inode(struct inode *inode)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 
+	/* If we are holding a delegation, return it! */
+	if (nfsi->delegation != NULL)
+		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;
 		
@@ -1470,8 +1553,6 @@ static void nfs4_clear_inode(struct inode *inode)
 		BUG_ON(atomic_read(&state->count) != 1);
 		nfs4_close_state(state, state->state);
 	}
-	/* Now call standard NFS clear_inode() code */
-	nfs_clear_inode(inode);
 }
 
 
@@ -1531,7 +1612,7 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
 	clp = nfs4_get_client(&server->addr.sin_addr);
 	if (!clp) {
 		printk(KERN_WARNING "NFS: failed to create NFS4 client.\n");
-		goto out_fail;
+		return -EIO;
 	}
 
 	/* Now create transport and client */
@@ -1569,8 +1650,13 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
 		memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr));
 		nfs_idmap_new(clp);
 	}
-	if (list_empty(&clp->cl_superblocks))
-		clear_bit(NFS4CLNT_OK, &clp->cl_state);
+	if (list_empty(&clp->cl_superblocks)) {
+		err = nfs4_init_client(clp);
+		if (err != 0) {
+			up_write(&clp->cl_sem);
+			goto out_fail;
+		}
+	}
 	list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks);
 	clnt = rpc_clone_client(clp->cl_rpcclient);
 	if (!IS_ERR(clnt))
@@ -1580,45 +1666,29 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
 
 	if (IS_ERR(clnt)) {
 		printk(KERN_WARNING "NFS: cannot create RPC client.\n");
-		err = PTR_ERR(clnt);
-		goto out_remove_list;
+		return PTR_ERR(clnt);
 	}
 
 	clnt->cl_intr     = (server->flags & NFS4_MOUNT_INTR) ? 1 : 0;
 	clnt->cl_softrtry = (server->flags & NFS4_MOUNT_SOFT) ? 1 : 0;
 	server->client    = clnt;
 
-	err = -ENOMEM;
 	if (server->nfs4_state->cl_idmap == NULL) {
 		printk(KERN_WARNING "NFS: failed to create idmapper.\n");
-		goto out_shutdown;
+		return -ENOMEM;
 	}
 
 	if (clnt->cl_auth->au_flavor != authflavour) {
 		if (rpcauth_create(authflavour, clnt) == NULL) {
 			printk(KERN_WARNING "NFS: couldn't create credcache!\n");
-			goto out_shutdown;
+			return -ENOMEM;
 		}
 	}
 
-	/* Fire up rpciod if not yet running */
-	if (rpciod_up() != 0) {
-		printk(KERN_WARNING "NFS: couldn't start rpciod!\n");
-		goto out_shutdown;
-	}
-
 	sb->s_op = &nfs4_sops;
 	err = nfs_sb_init(sb, authflavour);
 	if (err == 0)
 		return 0;
-	rpciod_down();
-out_shutdown:
-	rpc_shutdown_client(server->client);
-out_remove_list:
-	down_write(&server->nfs4_state->cl_sem);
-	list_del_init(&server->nfs4_siblings);
-	up_write(&server->nfs4_state->cl_sem);
-	destroy_nfsv4_state(server);
 out_fail:
 	if (clp)
 		nfs4_put_client(clp);
@@ -1724,6 +1794,13 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
 
 	s->s_flags = flags;
 
+	/* Fire up rpciod if not yet running */
+	if (rpciod_up() != 0) {
+		printk(KERN_WARNING "NFS: couldn't start rpciod!\n");
+		s = ERR_PTR(-EIO);
+		goto out_free;
+	}
+
 	error = nfs4_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
 	if (error) {
 		up_write(&s->s_umount);
@@ -1743,22 +1820,31 @@ out_free:
 	return s;
 }
 
+static void nfs4_kill_super(struct super_block *sb)
+{
+	nfs_return_all_delegations(sb);
+	nfs_kill_super(sb);
+}
+
 static struct file_system_type nfs4_fs_type = {
 	.owner		= THIS_MODULE,
 	.name		= "nfs4",
 	.get_sb		= nfs4_get_sb,
-	.kill_sb	= nfs_kill_super,
+	.kill_sb	= nfs4_kill_super,
 	.fs_flags	= FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
 };
 
-#define nfs4_zero_state(nfsi) \
+#define nfs4_init_once(nfsi) \
 	do { \
 		INIT_LIST_HEAD(&(nfsi)->open_states); \
+		nfsi->delegation = NULL; \
+		nfsi->delegation_state = 0; \
+		init_rwsem(&nfsi->rwsem); \
 	} while(0)
 #define register_nfs4fs() register_filesystem(&nfs4_fs_type)
 #define unregister_nfs4fs() unregister_filesystem(&nfs4_fs_type)
 #else
-#define nfs4_zero_state(nfsi) \
+#define nfs4_init_once(nfsi) \
 	do { } while (0)
 #define register_nfs4fs() (0)
 #define unregister_nfs4fs()
@@ -1780,8 +1866,6 @@ static struct inode *nfs_alloc_inode(struct super_block *sb)
 	if (!nfsi)
 		return NULL;
 	nfsi->flags = 0;
-	nfsi->mm_cred = NULL;
-	nfs4_zero_state(nfsi);
 	return &nfsi->vfs_inode;
 }
 
@@ -1797,14 +1881,17 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
 	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
 	    SLAB_CTOR_CONSTRUCTOR) {
 		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_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC);
 		atomic_set(&nfsi->data_updates, 0);
 		nfsi->ndirty = 0;
 		nfsi->ncommit = 0;
 		nfsi->npages = 0;
 		init_waitqueue_head(&nfsi->nfs_i_wait);
+		nfs4_init_once(nfsi);
 	}
 }
  
@@ -1812,7 +1899,7 @@ int nfs_init_inodecache(void)
 {
 	nfs_inode_cachep = kmem_cache_create("nfs_inode_cache",
 					     sizeof(struct nfs_inode),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (nfs_inode_cachep == NULL)
 		return -ENOMEM;
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index a2ddc6c5e..857e3ea4c 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -108,7 +108,6 @@ xdr_decode_fhstatus(struct rpc_rqst *req, u32 *p, struct mnt_fhstatus *res)
 {
 	struct nfs_fh *fh = res->fh;
 
-	memset((void *)fh, 0, sizeof(*fh));
 	if ((res->status = ntohl(*p++)) == 0) {
 		fh->size = NFS2_FHSIZE;
 		memcpy(fh->data, p, NFS2_FHSIZE);
@@ -121,7 +120,6 @@ xdr_decode_fhstatus3(struct rpc_rqst *req, u32 *p, struct mnt_fhstatus *res)
 {
 	struct nfs_fh *fh = res->fh;
 
-	memset((void *)fh, 0, sizeof(*fh));
 	if ((res->status = ntohl(*p++)) == 0) {
 		int size = ntohl(*p++);
 		if (size <= NFS3_FHSIZE) {
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index 01aebbf13..d91b69044 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -57,7 +57,7 @@ extern int			nfs_stat_to_errno(int stat);
 
 #define NFS_attrstat_sz		(1+NFS_fattr_sz)
 #define NFS_diropres_sz		(1+NFS_fhandle_sz+NFS_fattr_sz)
-#define NFS_readlinkres_sz	(1)
+#define NFS_readlinkres_sz	(2)
 #define NFS_readres_sz		(1+NFS_fattr_sz+1)
 #define NFS_writeres_sz         (NFS_attrstat_sz)
 #define NFS_stat_sz		(1)
@@ -77,8 +77,6 @@ xdr_encode_fhandle(u32 *p, struct nfs_fh *fhandle)
 static inline u32 *
 xdr_decode_fhandle(u32 *p, struct nfs_fh *fhandle)
 {
-	/* Zero handle first to allow comparisons */
-	memset(fhandle, 0, sizeof(*fhandle));
 	/* NFSv2 handles have a fixed length */
 	fhandle->size = NFS2_FHSIZE;
 	memcpy(fhandle->data, p, NFS2_FHSIZE);
@@ -94,6 +92,23 @@ xdr_encode_time(u32 *p, struct timespec *timep)
 	return p;
 }
 
+static inline u32*
+xdr_encode_current_server_time(u32 *p, struct timespec *timep)
+{
+	/*
+	 * Passing the invalid value useconds=1000000 is a
+	 * Sun convention for "set to current server time".
+	 * It's needed to make permissions checks for the
+	 * "touch" program across v2 mounts to Solaris and
+	 * Irix boxes work correctly. See description of
+	 * sattr in section 6.1 of "NFS Illustrated" by
+	 * Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5
+	 */
+	*p++ = htonl(timep->tv_sec);
+	*p++ = htonl(1000000);
+	return p;
+}
+
 static inline u32*
 xdr_decode_time(u32 *p, struct timespec *timep)
 {
@@ -142,15 +157,19 @@ xdr_encode_sattr(u32 *p, struct iattr *attr)
 	SATTR(p, attr, ATTR_GID, ia_gid);
 	SATTR(p, attr, ATTR_SIZE, ia_size);
 
-	if (attr->ia_valid & (ATTR_ATIME|ATTR_ATIME_SET)) {
+	if (attr->ia_valid & ATTR_ATIME_SET) {
 		p = xdr_encode_time(p, &attr->ia_atime);
+	} else if (attr->ia_valid & ATTR_ATIME) {
+		p = xdr_encode_current_server_time(p, &attr->ia_atime);
 	} else {
 		*p++ = ~(u32) 0;
 		*p++ = ~(u32) 0;
 	}
 
-	if (attr->ia_valid & (ATTR_MTIME|ATTR_MTIME_SET)) {
+	if (attr->ia_valid & ATTR_MTIME_SET) {
 		p = xdr_encode_time(p, &attr->ia_mtime);
+	} else if (attr->ia_valid & ATTR_MTIME) {
+		p = xdr_encode_current_server_time(p, &attr->ia_mtime);
 	} else {
 		*p++ = ~(u32) 0;	
 		*p++ = ~(u32) 0;
@@ -511,7 +530,6 @@ static int
 nfs_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_readlinkargs *args)
 {
 	struct rpc_auth *auth = req->rq_task->tk_auth;
-	unsigned int count = args->count - 5;
 	unsigned int replen;
 
 	p = xdr_encode_fhandle(p, args->fh);
@@ -519,7 +537,7 @@ nfs_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_readlinkargs *args
 
 	/* Inline the page array */
 	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readlinkres_sz) << 2;
-	xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
+	xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);
 	return 0;
 }
 
@@ -531,32 +549,38 @@ nfs_xdr_readlinkres(struct rpc_rqst *req, u32 *p, void *dummy)
 {
 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
 	struct kvec *iov = rcvbuf->head;
-	unsigned int hdrlen;
-	u32	*strlen, len;
-	char	*string;
+	int hdrlen, len, recvd;
+	char	*kaddr;
 	int	status;
 
 	if ((status = ntohl(*p++)))
 		return -nfs_stat_to_errno(status);
+	/* Convert length of symlink */
+	len = ntohl(*p++);
+	if (len >= rcvbuf->page_len || len <= 0) {
+		dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
+		return -ENAMETOOLONG;
+	}
 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
-	if (iov->iov_len > hdrlen) {
+	if (iov->iov_len < hdrlen) {
+		printk(KERN_WARNING "NFS: READLINK reply header overflowed:"
+				"length %d > %Zu\n", hdrlen, iov->iov_len);
+		return -errno_NFSERR_IO;
+	} else if (iov->iov_len != hdrlen) {
 		dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
 		xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
 	}
-
-	strlen = (u32*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
-	/* Convert length of symlink */
-	len = ntohl(*strlen);
-	if (len > rcvbuf->page_len) {
-		dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
-		kunmap_atomic(strlen, KM_USER0);
-		return -ENAMETOOLONG;
+	recvd = req->rq_rcv_buf.len - hdrlen;
+	if (recvd < len) {
+		printk(KERN_WARNING "NFS: server cheating in readlink reply: "
+				"count %u > recvd %u\n", len, recvd);
+		return -EIO;
 	}
-	*strlen = len;
+
 	/* NULL terminate the string we got */
-	string = (char *)(strlen + 1);
-	string[len] = '\0';
-	kunmap_atomic(strlen, KM_USER0);
+	kaddr = (char *)kmap_atomic(rcvbuf->pages[0], KM_USER0);
+	kaddr[len+rcvbuf->page_base] = '\0';
+	kunmap_atomic(kaddr, KM_USER0);
 	return 0;
 }
 
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index a759f5a5f..6be08f678 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -68,18 +68,6 @@ nfs3_async_handle_jukebox(struct rpc_task *task)
 	return 1;
 }
 
-static struct rpc_cred *
-nfs_cred(struct inode *inode, struct file *filp)
-{
-	struct rpc_cred *cred = NULL;
-
-	if (filp)
-		cred = (struct rpc_cred *)filp->private_data;
-	if (!cred)
-		cred = NFS_I(inode)->mm_cred;
-	return cred;
-}
-
 /*
  * Bare-bones access to getattr: this is for nfs_read_super.
  */
@@ -104,14 +92,15 @@ nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
  * One function for each procedure in the NFS protocol.
  */
 static int
-nfs3_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
+nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
+		struct nfs_fattr *fattr)
 {
 	int	status;
 
 	dprintk("NFS call  getattr\n");
 	fattr->valid = 0;
-	status = rpc_call(NFS_CLIENT(inode), NFS3PROC_GETATTR,
-			  NFS_FH(inode), fattr, 0);
+	status = rpc_call(server->client, NFS3PROC_GETATTR,
+			  fhandle, fattr, 0);
 	dprintk("NFS reply getattr\n");
 	return status;
 }
@@ -164,8 +153,7 @@ nfs3_proc_lookup(struct inode *dir, struct qstr *name,
 	return status;
 }
 
-static int
-nfs3_proc_access(struct inode *inode, struct rpc_cred *cred, int mode)
+static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry)
 {
 	struct nfs_fattr	fattr;
 	struct nfs3_accessargs	arg = {
@@ -178,9 +166,10 @@ nfs3_proc_access(struct inode *inode, struct rpc_cred *cred, int mode)
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_ACCESS],
 		.rpc_argp	= &arg,
 		.rpc_resp	= &res,
-		.rpc_cred	= cred
+		.rpc_cred	= entry->cred
 	};
-	int	status;
+	int mode = entry->mask;
+	int status;
 
 	dprintk("NFS call  access\n");
 	fattr.valid = 0;
@@ -200,20 +189,27 @@ nfs3_proc_access(struct inode *inode, struct rpc_cred *cred, int mode)
 	}
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
 	nfs_refresh_inode(inode, &fattr);
-	dprintk("NFS reply access\n");
-
-	if (status == 0 && (arg.access & res.access) != arg.access)
-		status = -EACCES;
+	if (status == 0) {
+		entry->mask = 0;
+		if (res.access & NFS3_ACCESS_READ)
+			entry->mask |= MAY_READ;
+		if (res.access & (NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND | NFS3_ACCESS_DELETE))
+			entry->mask |= MAY_WRITE;
+		if (res.access & (NFS3_ACCESS_LOOKUP|NFS3_ACCESS_EXECUTE))
+			entry->mask |= MAY_EXEC;
+	}
+	dprintk("NFS reply access, status = %d\n", status);
 	return status;
 }
 
-static int
-nfs3_proc_readlink(struct inode *inode, struct page *page)
+static int nfs3_proc_readlink(struct inode *inode, struct page *page,
+		unsigned int pgbase, unsigned int pglen)
 {
 	struct nfs_fattr	fattr;
 	struct nfs3_readlinkargs args = {
 		.fh		= NFS_FH(inode),
-		.count		= PAGE_CACHE_SIZE,
+		.pgbase		= pgbase,
+		.pglen		= pglen,
 		.pages		= &page
 	};
 	int			status;
@@ -227,8 +223,7 @@ nfs3_proc_readlink(struct inode *inode, struct page *page)
 	return status;
 }
 
-static int
-nfs3_proc_read(struct nfs_read_data *rdata, struct file *filp)
+static int nfs3_proc_read(struct nfs_read_data *rdata)
 {
 	int			flags = rdata->flags;
 	struct inode *		inode = rdata->inode;
@@ -237,13 +232,13 @@ nfs3_proc_read(struct nfs_read_data *rdata, struct file *filp)
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_READ],
 		.rpc_argp	= &rdata->args,
 		.rpc_resp	= &rdata->res,
+		.rpc_cred	= rdata->cred,
 	};
 	int			status;
 
 	dprintk("NFS call  read %d @ %Ld\n", rdata->args.count,
 			(long long) rdata->args.offset);
 	fattr->valid = 0;
-	msg.rpc_cred = nfs_cred(inode, filp);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
 	if (status >= 0)
 		nfs_refresh_inode(inode, fattr);
@@ -251,8 +246,7 @@ nfs3_proc_read(struct nfs_read_data *rdata, struct file *filp)
 	return status;
 }
 
-static int
-nfs3_proc_write(struct nfs_write_data *wdata, struct file *filp)
+static int nfs3_proc_write(struct nfs_write_data *wdata)
 {
 	int			rpcflags = wdata->flags;
 	struct inode *		inode = wdata->inode;
@@ -261,13 +255,13 @@ nfs3_proc_write(struct nfs_write_data *wdata, struct file *filp)
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_WRITE],
 		.rpc_argp	= &wdata->args,
 		.rpc_resp	= &wdata->res,
+		.rpc_cred	= wdata->cred,
 	};
 	int			status;
 
 	dprintk("NFS call  write %d @ %Ld\n", wdata->args.count,
 			(long long) wdata->args.offset);
 	fattr->valid = 0;
-	msg.rpc_cred = nfs_cred(inode, filp);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags);
 	if (status >= 0)
 		nfs_refresh_inode(inode, fattr);
@@ -275,8 +269,7 @@ nfs3_proc_write(struct nfs_write_data *wdata, struct file *filp)
 	return status < 0? status : wdata->res.count;
 }
 
-static int
-nfs3_proc_commit(struct nfs_write_data *cdata, struct file *filp)
+static int nfs3_proc_commit(struct nfs_write_data *cdata)
 {
 	struct inode *		inode = cdata->inode;
 	struct nfs_fattr *	fattr = cdata->res.fattr;
@@ -284,13 +277,13 @@ nfs3_proc_commit(struct nfs_write_data *cdata, struct file *filp)
 		.rpc_proc	= &nfs3_procedures[NFS3PROC_COMMIT],
 		.rpc_argp	= &cdata->args,
 		.rpc_resp	= &cdata->res,
+		.rpc_cred	= cdata->cred,
 	};
 	int			status;
 
 	dprintk("NFS call  commit %d @ %Ld\n", cdata->args.count,
 			(long long) cdata->args.offset);
 	fattr->valid = 0;
-	msg.rpc_cred = nfs_cred(inode, filp);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
 	if (status >= 0)
 		nfs_refresh_inode(inode, fattr);
@@ -425,20 +418,21 @@ nfs3_proc_remove(struct inode *dir, struct qstr *name)
 static int
 nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr *name)
 {
-	struct nfs3_diropargs	*arg;
-	struct nfs_fattr	*res;
+	struct unlinkxdr {
+		struct nfs3_diropargs arg;
+		struct nfs_fattr res;
+	} *ptr;
 
-	arg = (struct nfs3_diropargs *)kmalloc(sizeof(*arg)+sizeof(*res), GFP_KERNEL);
-	if (!arg)
+	ptr = (struct unlinkxdr *)kmalloc(sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
 		return -ENOMEM;
-	res = (struct nfs_fattr*)(arg + 1);
-	arg->fh = NFS_FH(dir->d_inode);
-	arg->name = name->name;
-	arg->len = name->len;
-	res->valid = 0;
+	ptr->arg.fh = NFS_FH(dir->d_inode);
+	ptr->arg.name = name->name;
+	ptr->arg.len = name->len;
+	ptr->res.valid = 0;
 	msg->rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE];
-	msg->rpc_argp = arg;
-	msg->rpc_resp = res;
+	msg->rpc_argp = &ptr->arg;
+	msg->rpc_resp = &ptr->res;
 	return 0;
 }
 
@@ -534,6 +528,8 @@ nfs3_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
 	};
 	int			status;
 
+	if (path->len > NFS3_MAXPATHLEN)
+		return -ENAMETOOLONG;
 	dprintk("NFS call  symlink %s -> %s\n", name->name, path->name);
 	dir_attr.valid = 0;
 	fattr->valid = 0;
@@ -832,27 +828,6 @@ nfs3_proc_commit_setup(struct nfs_write_data *data, int how)
 	rpc_call_setup(task, &msg, 0);
 }
 
-/*
- * Set up the nfspage struct with the right credentials
- */
-void
-nfs3_request_init(struct nfs_page *req, struct file *filp)
-{
-	req->wb_cred = get_rpccred(nfs_cred(req->wb_inode, filp));
-}
-
-static int
-nfs3_request_compatible(struct nfs_page *req, struct file *filp, struct page *page)
-{
-	if (req->wb_file != filp)
-		return 0;
-	if (req->wb_page != page)
-		return 0;
-	if (req->wb_cred != nfs_file_cred(filp))
-		return 0;
-	return 1;
-}
-
 static int
 nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
 {
@@ -892,7 +867,5 @@ struct nfs_rpc_ops	nfs_v3_clientops = {
 	.commit_setup	= nfs3_proc_commit_setup,
 	.file_open	= nfs_open,
 	.file_release	= nfs_release,
-	.request_init	= nfs3_request_init,
-	.request_compatible = nfs3_request_compatible,
 	.lock		= nfs3_proc_lock,
 };
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index ebfc60759..640316a47 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -68,7 +68,7 @@ extern int			nfs_stat_to_errno(int);
 #define NFS3_wccstat_sz		(1+NFS3_wcc_data_sz)
 #define NFS3_lookupres_sz	(1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
 #define NFS3_accessres_sz	(1+NFS3_post_op_attr_sz+1)
-#define NFS3_readlinkres_sz	(1+NFS3_post_op_attr_sz)
+#define NFS3_readlinkres_sz	(1+NFS3_post_op_attr_sz+1)
 #define NFS3_readres_sz		(1+NFS3_post_op_attr_sz+3)
 #define NFS3_writeres_sz	(1+NFS3_wcc_data_sz+4)
 #define NFS3_createres_sz	(1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
@@ -110,10 +110,6 @@ xdr_encode_fhandle(u32 *p, struct nfs_fh *fh)
 static inline u32 *
 xdr_decode_fhandle(u32 *p, struct nfs_fh *fh)
 {
-	/*
-	 * Zero all nonused bytes
-	 */
-	memset((u8 *)fh, 0, sizeof(*fh));
 	if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) {
 		memcpy(fh->data, p, fh->size);
 		return p + XDR_QUADLEN(fh->size);
@@ -710,7 +706,6 @@ static int
 nfs3_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_readlinkargs *args)
 {
 	struct rpc_auth *auth = req->rq_task->tk_auth;
-	unsigned int count = args->count - 5;
 	unsigned int replen;
 
 	p = xdr_encode_fhandle(p, args->fh);
@@ -718,7 +713,7 @@ nfs3_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_readlinkargs *ar
 
 	/* Inline the page array */
 	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2;
-	xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
+	xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);
 	return 0;
 }
 
@@ -730,9 +725,8 @@ nfs3_xdr_readlinkres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
 {
 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
 	struct kvec *iov = rcvbuf->head;
-	unsigned int hdrlen;
-	u32	*strlen, len;
-	char	*string;
+	int hdrlen, len, recvd;
+	char	*kaddr;
 	int	status;
 
 	status = ntohl(*p++);
@@ -741,25 +735,33 @@ nfs3_xdr_readlinkres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
 	if (status != 0)
 		return -nfs_stat_to_errno(status);
 
+	/* Convert length of symlink */
+	len = ntohl(*p++);
+	if (len >= rcvbuf->page_len || len <= 0) {
+		dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
+		return -ENAMETOOLONG;
+	}
+
 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
-	if (iov->iov_len > hdrlen) {
+	if (iov->iov_len < hdrlen) {
+		printk(KERN_WARNING "NFS: READLINK reply header overflowed:"
+				"length %d > %Zu\n", hdrlen, iov->iov_len);
+		return -errno_NFSERR_IO;
+	} else if (iov->iov_len != hdrlen) {
 		dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
 		xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
 	}
-
-	strlen = (u32*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
-	/* Convert length of symlink */
-	len = ntohl(*strlen);
-	if (len > rcvbuf->page_len) {
-		dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
-		kunmap_atomic(strlen, KM_USER0);
-		return -ENAMETOOLONG;
+	recvd = req->rq_rcv_buf.len - hdrlen;
+	if (recvd < len) {
+		printk(KERN_WARNING "NFS: server cheating in readlink reply: "
+				"count %u > recvd %u\n", len, recvd);
+		return -EIO;
 	}
-	*strlen = len;
+
 	/* NULL terminate the string we got */
-	string = (char *)(strlen + 1);
-	string[len] = '\0';
-	kunmap_atomic(strlen, KM_USER0);
+	kaddr = (char*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
+	kaddr[len+rcvbuf->page_base] = '\0';
+	kunmap_atomic(kaddr, KM_USER0);
 	return 0;
 }
 
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 2eb124475..7509bd2ae 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -47,12 +47,16 @@
 #include <linux/smp_lock.h>
 #include <linux/namei.h>
 
+#include "delegation.h"
+
 #define NFSDBG_FACILITY		NFSDBG_PROC
 
-#define NFS4_POLL_RETRY_TIME	(15*HZ)
+#define NFS4_POLL_RETRY_MIN	(1*HZ)
+#define NFS4_POLL_RETRY_MAX	(15*HZ)
 
 static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
 static int nfs4_async_handle_error(struct rpc_task *, struct nfs_server *);
+static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry);
 extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
 extern struct rpc_procinfo nfs4_procedures[];
 
@@ -189,53 +193,296 @@ static void update_changeattr(struct inode *inode, struct nfs4_change_info *cinf
  * 	reclaim state on the server after a reboot.
  * 	Assumes caller is holding the sp->so_sem
  */
-int
-nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
+static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
 {
 	struct inode *inode = state->inode;
 	struct nfs_server *server = NFS_SERVER(inode);
-	struct nfs_fattr fattr = {
-		.valid = 0,
-	};
-	struct nfs_open_reclaimargs o_arg = {
+	struct nfs_delegation *delegation = NFS_I(inode)->delegation;
+	struct nfs_openargs o_arg = {
 		.fh = NFS_FH(inode),
 		.seqid = sp->so_seqid,
 		.id = sp->so_id,
-		.share_access = state->state,
+		.open_flags = state->state,
 		.clientid = server->nfs4_state->cl_clientid,
 		.claim = NFS4_OPEN_CLAIM_PREVIOUS,
 		.bitmask = server->attr_bitmask,
 	};
 	struct nfs_openres o_res = {
-		.f_attr = &fattr,
 		.server = server,	/* Grrr */
 	};
 	struct rpc_message msg = {
-		.rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_OPEN_RECLAIM],
+		.rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR],
 		.rpc_argp       = &o_arg,
 		.rpc_resp	= &o_res,
 		.rpc_cred	= sp->so_cred,
 	};
 	int status;
 
-	status = rpc_call_sync(server->client, &msg, 0);
+	if (delegation != NULL) {
+		if (!(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) {
+			memcpy(&state->stateid, &delegation->stateid,
+					sizeof(state->stateid));
+			set_bit(NFS_DELEGATED_STATE, &state->flags);
+			return 0;
+		}
+		o_arg.u.delegation_type = delegation->type;
+	}
+	status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
 	nfs4_increment_seqid(status, sp);
-	if (status == 0)
+	if (status == 0) {
 		memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid));
-	/* Update the inode attributes */
-	nfs_refresh_inode(inode, &fattr);
+		if (o_res.delegation_type != 0) {
+			nfs_inode_reclaim_delegation(inode, sp->so_cred, &o_res);
+			/* Did the server issue an immediate delegation recall? */
+			if (o_res.do_recall)
+				nfs_async_inode_return_delegation(inode, &o_res.stateid);
+		}
+	}
+	clear_bit(NFS_DELEGATED_STATE, &state->flags);
+	/* Ensure we update the inode attributes */
+	NFS_CACHEINV(inode);
 	return status;
 }
 
+int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
+{
+	struct nfs_server *server = NFS_SERVER(state->inode);
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = _nfs4_open_reclaim(sp, state);
+		switch (err) {
+			case 0:
+			case -NFS4ERR_STALE_CLIENTID:
+			case -NFS4ERR_STALE_STATEID:
+			case -NFS4ERR_EXPIRED:
+				return err;
+		}
+		err = nfs4_handle_exception(server, err, &exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
+{
+	struct nfs4_state_owner  *sp  = state->owner;
+	struct inode *inode = dentry->d_inode;
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct dentry *parent = dget_parent(dentry);
+	struct nfs_openargs arg = {
+		.fh = NFS_FH(parent->d_inode),
+		.clientid = server->nfs4_state->cl_clientid,
+		.name = &dentry->d_name,
+		.id = sp->so_id,
+		.server = server,
+		.bitmask = server->attr_bitmask,
+		.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR,
+	};
+	struct nfs_openres res = {
+		.server = server,
+	};
+	struct 	rpc_message msg = {
+		.rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR],
+		.rpc_argp       = &arg,
+		.rpc_resp       = &res,
+		.rpc_cred	= sp->so_cred,
+	};
+	int status = 0;
+
+	down(&sp->so_sema);
+	if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
+		goto out;
+	if (state->state == 0)
+		goto out;
+	arg.seqid = sp->so_seqid;
+	arg.open_flags = state->state;
+	memcpy(arg.u.delegation.data, state->stateid.data, sizeof(arg.u.delegation.data));
+	status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
+	nfs4_increment_seqid(status, sp);
+	if (status >= 0) {
+		memcpy(state->stateid.data, res.stateid.data,
+				sizeof(state->stateid.data));
+		clear_bit(NFS_DELEGATED_STATE, &state->flags);
+	}
+out:
+	up(&sp->so_sema);
+	dput(parent);
+	return status;
+}
+
+int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state)
+{
+	struct nfs4_exception exception = { };
+	struct nfs_server *server = NFS_SERVER(dentry->d_inode);
+	int err;
+	do {
+		err = _nfs4_open_delegation_recall(dentry, state);
+		switch (err) {
+			case 0:
+				return err;
+			case -NFS4ERR_STALE_CLIENTID:
+			case -NFS4ERR_STALE_STATEID:
+			case -NFS4ERR_EXPIRED:
+				/* Don't recall a delegation if it was lost */
+				nfs4_schedule_state_recovery(server->nfs4_state);
+				return err;
+		}
+		err = nfs4_handle_exception(server, err, &exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid)
+{
+	struct nfs_open_confirmargs arg = {
+		.fh             = fh,
+		.seqid          = sp->so_seqid,
+		.stateid	= *stateid,
+	};
+	struct nfs_open_confirmres res;
+	struct 	rpc_message msg = {
+		.rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM],
+		.rpc_argp       = &arg,
+		.rpc_resp       = &res,
+		.rpc_cred	= sp->so_cred,
+	};
+	int status;
+
+	status = rpc_call_sync(clnt, &msg, RPC_TASK_NOINTR);
+	nfs4_increment_seqid(status, sp);
+	if (status >= 0)
+		memcpy(stateid, &res.stateid, sizeof(*stateid));
+	return status;
+}
+
+static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
+{
+	struct nfs_access_entry cache;
+	int status;
+
+	status = nfs_access_get_cached(inode, cred, &cache);
+	if (status == 0)
+		goto out;
+
+	/* Be clever: ask server to check for all possible rights */
+	cache.mask = MAY_EXEC | MAY_WRITE | MAY_READ;
+	cache.cred = cred;
+	cache.jiffies = jiffies;
+	status = _nfs4_proc_access(inode, &cache);
+	if (status != 0)
+		return status;
+	nfs_access_add_cache(inode, &cache);
+out:
+	if ((cache.mask & mask) == mask)
+		return 0;
+	return -EACCES;
+}
+
+/*
+ * Returns an nfs4_state + an extra reference to the inode
+ */
+int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred, struct nfs4_state **res)
+{
+	struct nfs_delegation *delegation;
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct nfs4_client *clp = server->nfs4_state;
+	struct nfs_inode *nfsi = NFS_I(inode);
+	struct nfs4_state_owner *sp = NULL;
+	struct nfs4_state *state = NULL;
+	int open_flags = flags & (FMODE_READ|FMODE_WRITE);
+	int mask = 0;
+	int err;
+
+	/* Protect against reboot recovery - NOTE ORDER! */
+	down_read(&clp->cl_sem);
+	/* Protect against delegation recall */
+	down_read(&nfsi->rwsem);
+	delegation = NFS_I(inode)->delegation;
+	err = -ENOENT;
+	if (delegation == NULL || (delegation->type & open_flags) != open_flags)
+		goto out_err;
+	err = -ENOMEM;
+	if (!(sp = nfs4_get_state_owner(server, cred))) {
+		dprintk("%s: nfs4_get_state_owner failed!\n", __FUNCTION__);
+		goto out_err;
+	}
+	down(&sp->so_sema);
+	state = nfs4_get_open_state(inode, sp);
+	if (state == NULL)
+		goto out_err;
+
+	err = -ENOENT;
+	if ((state->state & open_flags) == open_flags) {
+		spin_lock(&inode->i_lock);
+		if (open_flags & FMODE_READ)
+			state->nreaders++;
+		if (open_flags & FMODE_WRITE)
+			state->nwriters++;
+		spin_unlock(&inode->i_lock);
+		goto out_ok;
+	} else if (state->state != 0)
+		goto out_err;
+
+	lock_kernel();
+	err = _nfs4_do_access(inode, cred, mask);
+	unlock_kernel();
+	if (err != 0)
+		goto out_err;
+	spin_lock(&inode->i_lock);
+	memcpy(state->stateid.data, delegation->stateid.data,
+			sizeof(state->stateid.data));
+	state->state |= open_flags;
+	if (open_flags & FMODE_READ)
+		state->nreaders++;
+	if (open_flags & FMODE_WRITE)
+		state->nwriters++;
+	set_bit(NFS_DELEGATED_STATE, &state->flags);
+	spin_unlock(&inode->i_lock);
+out_ok:
+	up(&sp->so_sema);
+	nfs4_put_state_owner(sp);
+	up_read(&nfsi->rwsem);
+	up_read(&clp->cl_sem);
+	igrab(inode);
+	*res = state;
+	return 0; 
+out_err:
+	if (sp != NULL) {
+		if (state != NULL)
+			nfs4_put_open_state(state);
+		up(&sp->so_sema);
+		nfs4_put_state_owner(sp);
+	}
+	up_read(&nfsi->rwsem);
+	up_read(&clp->cl_sem);
+	return err;
+}
+
+static struct nfs4_state *nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred)
+{
+	struct nfs4_exception exception = { };
+	struct nfs4_state *res;
+	int err;
+
+	do {
+		err = _nfs4_open_delegated(inode, flags, cred, &res);
+		if (err == 0)
+			break;
+		res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(inode),
+					err, &exception));
+	} while (exception.retry);
+	return res;
+}
+
 /*
  * Returns an nfs4_state + an referenced inode
  */
-struct nfs4_state *
-nfs4_do_open(struct inode *dir, struct qstr *name, int flags, struct iattr *sattr, struct rpc_cred *cred)
+static int _nfs4_do_open(struct inode *dir, struct qstr *name, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res)
 {
 	struct nfs4_state_owner  *sp;
 	struct nfs4_state     *state = NULL;
 	struct nfs_server       *server = NFS_SERVER(dir);
+	struct nfs4_client *clp = server->nfs4_state;
 	struct inode *inode = NULL;
 	int                     status;
 	struct nfs_fattr        f_attr = {
@@ -243,12 +490,11 @@ nfs4_do_open(struct inode *dir, struct qstr *name, int flags, struct iattr *satt
 	};
 	struct nfs_openargs o_arg = {
 		.fh             = NFS_FH(dir),
-		.share_access   = flags & (FMODE_READ|FMODE_WRITE),
-		.opentype       = (flags & O_CREAT) ? NFS4_OPEN_CREATE : NFS4_OPEN_NOCREATE,
-		.createmode     = (flags & O_EXCL) ? NFS4_CREATE_EXCLUSIVE : NFS4_CREATE_UNCHECKED,
+		.open_flags	= flags,
 		.name           = name,
 		.server         = server,
 		.bitmask = server->attr_bitmask,
+		.claim = NFS4_OPEN_CLAIM_NULL,
 	};
 	struct nfs_openres o_res = {
 		.f_attr         = &f_attr,
@@ -261,60 +507,50 @@ nfs4_do_open(struct inode *dir, struct qstr *name, int flags, struct iattr *satt
 		.rpc_cred	= cred,
 	};
 
-retry:
+	/* Protect against reboot recovery conflicts */
+	down_read(&clp->cl_sem);
 	status = -ENOMEM;
-	if (!(sp = nfs4_get_state_owner(NFS_SERVER(dir), cred))) {
+	if (!(sp = nfs4_get_state_owner(server, cred))) {
 		dprintk("nfs4_do_open: nfs4_get_state_owner failed!\n");
-		goto out;
+		goto out_err;
 	}
-	if (o_arg.createmode & NFS4_CREATE_EXCLUSIVE){
+	if (flags & O_EXCL) {
 		u32 *p = (u32 *) o_arg.u.verifier.data;
 		p[0] = jiffies;
 		p[1] = current->pid;
-	} else if (o_arg.createmode == NFS4_CREATE_UNCHECKED) {
+	} else
 		o_arg.u.attrs = sattr;
-	}
 	/* Serialization for the sequence id */
 	down(&sp->so_sema);
 	o_arg.seqid = sp->so_seqid;
 	o_arg.id = sp->so_id;
-	o_arg.clientid = NFS_SERVER(dir)->nfs4_state->cl_clientid,
+	o_arg.clientid = clp->cl_clientid,
 
-	status = rpc_call_sync(server->client, &msg, 0);
+	status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
 	nfs4_increment_seqid(status, sp);
 	if (status)
-		goto out_up;
+		goto out_err;
 	update_changeattr(dir, &o_res.cinfo);
+	if(o_res.rflags & NFS4_OPEN_RESULT_CONFIRM) {
+		status = _nfs4_proc_open_confirm(server->client, &o_res.fh,
+				sp, &o_res.stateid);
+		if (status != 0)
+			goto out_err;
+	}
+	if (!(f_attr.valid & NFS_ATTR_FATTR)) {
+		status = server->rpc_ops->getattr(server, &o_res.fh, &f_attr);
+		if (status < 0)
+			goto out_err;
+	}
 
 	status = -ENOMEM;
 	inode = nfs_fhget(dir->i_sb, &o_res.fh, &f_attr);
 	if (!inode)
-		goto out_up;
+		goto out_err;
 	state = nfs4_get_open_state(inode, sp);
 	if (!state)
-		goto out_up;
-
-	if(o_res.rflags & NFS4_OPEN_RESULT_CONFIRM) {
-		struct nfs_open_confirmargs oc_arg = {
-			.fh             = &o_res.fh,
-			.seqid          = sp->so_seqid,
-		};
-		struct nfs_open_confirmres oc_res;
-		struct 	rpc_message msg = {
-			.rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM],
-			.rpc_argp       = &oc_arg,
-			.rpc_resp       = &oc_res,
-			.rpc_cred	= cred,
-		};
-
-		memcpy(&oc_arg.stateid, &o_res.stateid, sizeof(oc_arg.stateid));
-		status = rpc_call_sync(server->client, &msg, 0);
-		nfs4_increment_seqid(status, sp);
-		if (status)
-			goto out_up;
-		memcpy(&state->stateid, &oc_res.stateid, sizeof(state->stateid));
-	} else
-		memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid));
+		goto out_err;
+	memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid));
 	spin_lock(&inode->i_lock);
 	if (flags & FMODE_READ)
 		state->nreaders++;
@@ -322,47 +558,62 @@ retry:
 		state->nwriters++;
 	state->state |= flags & (FMODE_READ|FMODE_WRITE);
 	spin_unlock(&inode->i_lock);
-
+	if (o_res.delegation_type != 0)
+		nfs_inode_set_delegation(inode, cred, &o_res);
 	up(&sp->so_sema);
 	nfs4_put_state_owner(sp);
-	return state;
-
-out_up:
-	up(&sp->so_sema);
-	nfs4_put_state_owner(sp);
-	if (state) {
-		nfs4_put_open_state(state);
-		state = NULL;
+	up_read(&clp->cl_sem);
+	*res = state;
+	return 0;
+out_err:
+	if (sp != NULL) {
+		if (state != NULL)
+			nfs4_put_open_state(state);
+		up(&sp->so_sema);
+		nfs4_put_state_owner(sp);
 	}
-	if (inode) {
+	/* Note: clp->cl_sem must be released before nfs4_put_open_state()! */
+	up_read(&clp->cl_sem);
+	if (inode != NULL)
 		iput(inode);
-		inode = NULL;
-	}
-	/* NOTE: BAD_SEQID means the server and client disagree about the
-	 * book-keeping w.r.t. state-changing operations
-	 * (OPEN/CLOSE/LOCK/LOCKU...)
-	 * It is actually a sign of a bug on the client or on the server.
-	 *
-	 * If we receive a BAD_SEQID error in the particular case of
-	 * doing an OPEN, we assume that nfs4_increment_seqid() will
-	 * have unhashed the old state_owner for us, and that we can
-	 * therefore safely retry using a new one. We should still warn
-	 * the user though...
-	 */
-	if (status == -NFS4ERR_BAD_SEQID) {
-		printk(KERN_WARNING "NFS: v4 server returned a bad sequence-id error!\n");
-		goto retry;
-	}
-	status = nfs4_handle_error(server, status);
-	if (!status)
-		goto retry;
-	BUG_ON(status < -1000 || status > 0);
-out:
-	return ERR_PTR(status);
+	*res = NULL;
+	return status;
 }
 
-int
-nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
+
+struct nfs4_state *nfs4_do_open(struct inode *dir, struct qstr *name, int flags, struct iattr *sattr, struct rpc_cred *cred)
+{
+	struct nfs4_exception exception = { };
+	struct nfs4_state *res;
+	int status;
+
+	do {
+		status = _nfs4_do_open(dir, name, flags, sattr, cred, &res);
+		if (status == 0)
+			break;
+		/* NOTE: BAD_SEQID means the server and client disagree about the
+		 * book-keeping w.r.t. state-changing operations
+		 * (OPEN/CLOSE/LOCK/LOCKU...)
+		 * It is actually a sign of a bug on the client or on the server.
+		 *
+		 * If we receive a BAD_SEQID error in the particular case of
+		 * doing an OPEN, we assume that nfs4_increment_seqid() will
+		 * have unhashed the old state_owner for us, and that we can
+		 * therefore safely retry using a new one. We should still warn
+		 * the user though...
+		 */
+		if (status == -NFS4ERR_BAD_SEQID) {
+			printk(KERN_WARNING "NFS: v4 server returned a bad sequence-id error!\n");
+			exception.retry = 1;
+			continue;
+		}
+		res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(dir),
+					status, &exception));
+	} while (exception.retry);
+	return res;
+}
+
+static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
                 struct nfs_fh *fhandle, struct iattr *sattr,
                 struct nfs4_state *state)
 {
@@ -381,9 +632,7 @@ nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
                 .rpc_argp       = &arg,
                 .rpc_resp       = &res,
         };
-	int status;
 
-retry:
         fattr->valid = 0;
 
 	if (sattr->ia_valid & ATTR_SIZE)
@@ -391,13 +640,22 @@ retry:
 	else
 		memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));
 
-	status = rpc_call_sync(server->client, &msg, 0);
-	if (status) {
-		status = nfs4_handle_error(server, status);
-		if (!status)
-			goto retry;
-	}
-	return status;
+	return rpc_call_sync(server->client, &msg, 0);
+}
+
+int nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
+                struct nfs_fh *fhandle, struct iattr *sattr,
+                struct nfs4_state *state)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(server,
+				_nfs4_do_setattr(server, fattr, fhandle, sattr,
+					state),
+				&exception);
+	} while (exception.retry);
+	return err;
 }
 
 /* 
@@ -411,8 +669,7 @@ retry:
  *
  * NOTE: Caller must be holding the sp->so_owner semaphore!
  */
-int
-nfs4_do_close(struct inode *inode, struct nfs4_state *state) 
+static int _nfs4_do_close(struct inode *inode, struct nfs4_state *state) 
 {
 	struct nfs4_state_owner *sp = state->owner;
 	int status = 0;
@@ -426,10 +683,12 @@ nfs4_do_close(struct inode *inode, struct nfs4_state *state)
 		.rpc_resp	= &res,
 	};
 
+	if (test_bit(NFS_DELEGATED_STATE, &state->flags))
+		return 0;
 	memcpy(&arg.stateid, &state->stateid, sizeof(arg.stateid));
 	/* Serialization for the sequence id */
 	arg.seqid = sp->so_seqid,
-	status = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0);
+	status = rpc_call_sync(NFS_SERVER(inode)->client, &msg, RPC_TASK_NOINTR);
 
         /* hmm. we are done with the inode, and in the process of freeing
 	 * the state_owner. we keep this around to process errors
@@ -441,15 +700,34 @@ nfs4_do_close(struct inode *inode, struct nfs4_state *state)
 	return status;
 }
 
-int
-nfs4_do_downgrade(struct inode *inode, struct nfs4_state *state, mode_t mode) 
+int nfs4_do_close(struct inode *inode, struct nfs4_state *state) 
+{
+	struct nfs_server *server = NFS_SERVER(state->inode);
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = _nfs4_do_close(inode, state);
+		switch (err) {
+			case -NFS4ERR_STALE_STATEID:
+			case -NFS4ERR_EXPIRED:
+				nfs4_schedule_state_recovery(server->nfs4_state);
+				err = 0;
+			default:
+				state->state = 0;
+		}
+		err = nfs4_handle_exception(server, err, &exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_do_downgrade(struct inode *inode, struct nfs4_state *state, mode_t mode) 
 {
 	struct nfs4_state_owner *sp = state->owner;
 	int status = 0;
 	struct nfs_closeargs arg = {
 		.fh		= NFS_FH(inode),
 		.seqid		= sp->so_seqid,
-		.share_access	= mode,
+		.open_flags	= mode,
 	};
 	struct nfs_closeres res;
 	struct rpc_message msg = {
@@ -458,8 +736,10 @@ nfs4_do_downgrade(struct inode *inode, struct nfs4_state *state, mode_t mode)
 		.rpc_resp	= &res,
 	};
 
+	if (test_bit(NFS_DELEGATED_STATE, &state->flags))
+		return 0;
 	memcpy(&arg.stateid, &state->stateid, sizeof(arg.stateid));
-	status = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0);
+	status = rpc_call_sync(NFS_SERVER(inode)->client, &msg, RPC_TASK_NOINTR);
 	nfs4_increment_seqid(status, sp);
 	if (!status)
 		memcpy(&state->stateid, &res.stateid, sizeof(state->stateid));
@@ -467,6 +747,26 @@ nfs4_do_downgrade(struct inode *inode, struct nfs4_state *state, mode_t mode)
 	return status;
 }
 
+int nfs4_do_downgrade(struct inode *inode, struct nfs4_state *state, mode_t mode) 
+{
+	struct nfs_server *server = NFS_SERVER(state->inode);
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = _nfs4_do_downgrade(inode, state, mode);
+		switch (err) {
+			case -NFS4ERR_STALE_STATEID:
+			case -NFS4ERR_EXPIRED:
+				nfs4_schedule_state_recovery(server->nfs4_state);
+				err = 0;
+			default:
+				state->state = mode;
+		}
+		err = nfs4_handle_exception(server, err, &exception);
+	} while (exception.retry);
+	return err;
+}
+
 struct inode *
 nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
@@ -500,7 +800,9 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags)
 	struct inode *inode;
 
 	cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
-	state = nfs4_do_open(dir, &dentry->d_name, openflags, NULL, cred);
+	state = nfs4_open_delegated(dentry->d_inode, openflags, cred);
+	if (IS_ERR(state))
+		state = nfs4_do_open(dir, &dentry->d_name, openflags, NULL, cred);
 	put_rpccred(cred);
 	if (state == ERR_PTR(-ENOENT) && dentry->d_inode == 0)
 		return 1;
@@ -518,7 +820,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags)
 }
 
 
-static int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
+static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
 {
 	struct nfs4_server_caps_res res = {};
 	struct rpc_message msg = {
@@ -542,7 +844,19 @@ static int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fh
 	return status;
 }
 
-static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
+static int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(server,
+				_nfs4_server_capabilities(server, fhandle),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
 		struct nfs_fsinfo *info)
 {
 	struct nfs_fattr *	fattr = info->fattr;
@@ -563,6 +877,19 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
 	return rpc_call_sync(server->client, &msg, 0);
 }
 
+static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
+		struct nfs_fsinfo *info)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(server,
+				_nfs4_lookup_root(server, fhandle, info),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
 static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
 		struct nfs_fsinfo *info)
 {
@@ -597,6 +924,8 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
 
 	p = server->mnt_path;
 	for (;;) {
+		struct nfs4_exception exception = { };
+
 		while (*p == '/')
 			p++;
 		if (!*p)
@@ -606,9 +935,13 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
 			p++;
 		q.len = p - q.name;
 
-		fattr->valid = 0;
-		status = rpc_call_sync(server->client, &msg, 0);
-		if (!status)
+		do {
+			fattr->valid = 0;
+			status = nfs4_handle_exception(server,
+					rpc_call_sync(server->client, &msg, 0),
+					&exception);
+		} while (exception.retry);
+		if (status == 0)
 			continue;
 		if (status == -ENOENT) {
 			printk(KERN_NOTICE "NFS: mount path %s does not exist!\n", server->mnt_path);
@@ -621,14 +954,13 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
 	if (status == 0)
 		status = nfs4_do_fsinfo(server, fhandle, info);
 out:
-	return nfs4_map_errors(status);
+	return status;
 }
 
-static int nfs4_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
+static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
-	struct nfs_server *server = NFS_SERVER(inode);
 	struct nfs4_getattr_arg args = {
-		.fh = NFS_FH(inode),
+		.fh = fhandle,
 		.bitmask = server->attr_bitmask,
 	};
 	struct nfs4_getattr_res res = {
@@ -642,8 +974,19 @@ static int nfs4_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
 	};
 	
 	fattr->valid = 0;
+	return rpc_call_sync(server->client, &msg, 0);
+}
 
-	return nfs4_map_errors(rpc_call_sync(NFS_CLIENT(inode), &msg, 0));
+static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(server,
+				_nfs4_proc_getattr(server, fhandle, fattr),
+				&exception);
+	} while (exception.retry);
+	return err;
 }
 
 /* 
@@ -678,9 +1021,13 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 	if (size_change) {
 		struct rpc_cred *cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
 		state = nfs4_find_state(inode, cred, FMODE_WRITE);
-		if (!state) {
-			state = nfs4_do_open(dentry->d_parent->d_inode, 
-				&dentry->d_name, FMODE_WRITE, NULL, cred);
+		if (state == NULL) {
+			state = nfs4_open_delegated(dentry->d_inode,
+					FMODE_WRITE, cred);
+			if (IS_ERR(state))
+				state = nfs4_do_open(dentry->d_parent->d_inode,
+						&dentry->d_name, FMODE_WRITE,
+						NULL, cred);
 			need_iput = 1;
 		}
 		put_rpccred(cred);
@@ -705,7 +1052,7 @@ out:
 	return status;
 }
 
-static int nfs4_proc_lookup(struct inode *dir, struct qstr *name,
+static int _nfs4_proc_lookup(struct inode *dir, struct qstr *name,
 		struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
 	int		       status;
@@ -731,12 +1078,23 @@ static int nfs4_proc_lookup(struct inode *dir, struct qstr *name,
 	dprintk("NFS call  lookup %s\n", name->name);
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 	dprintk("NFS reply lookup: %d\n", status);
-	return nfs4_map_errors(status);
+	return status;
 }
 
-static int nfs4_proc_access(struct inode *inode, struct rpc_cred *cred, int mode)
+static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(dir),
+				_nfs4_proc_lookup(dir, name, fhandle, fattr),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
 {
-	int			status;
 	struct nfs4_accessargs args = {
 		.fh = NFS_FH(inode),
 	};
@@ -745,8 +1103,10 @@ static int nfs4_proc_access(struct inode *inode, struct rpc_cred *cred, int mode
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ACCESS],
 		.rpc_argp = &args,
 		.rpc_resp = &res,
-		.rpc_cred = cred,
+		.rpc_cred = entry->cred,
 	};
+	int mode = entry->mask;
+	int status;
 
 	/*
 	 * Determine which access bits we want to ask for...
@@ -758,8 +1118,7 @@ static int nfs4_proc_access(struct inode *inode, struct rpc_cred *cred, int mode
 			args.access |= NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND | NFS4_ACCESS_DELETE;
 		if (mode & MAY_EXEC)
 			args.access |= NFS4_ACCESS_LOOKUP;
-	}
-	else {
+	} else {
 		if (mode & MAY_WRITE)
 			args.access |= NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND;
 		if (mode & MAY_EXEC)
@@ -767,13 +1126,27 @@ static int nfs4_proc_access(struct inode *inode, struct rpc_cred *cred, int mode
 	}
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
 	if (!status) {
-		if (args.access != res.supported) {
-			printk(KERN_NOTICE "NFS: server didn't support all access bits!\n");
-			status = -ENOTSUPP;
-		} else if ((args.access & res.access) != args.access)
-			status = -EACCES;
+		entry->mask = 0;
+		if (res.access & NFS4_ACCESS_READ)
+			entry->mask |= MAY_READ;
+		if (res.access & (NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND | NFS4_ACCESS_DELETE))
+			entry->mask |= MAY_WRITE;
+		if (res.access & (NFS4_ACCESS_LOOKUP|NFS4_ACCESS_EXECUTE))
+			entry->mask |= MAY_EXEC;
 	}
-	return nfs4_map_errors(status);
+	return status;
+}
+
+static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(inode),
+				_nfs4_proc_access(inode, entry),
+				&exception);
+	} while (exception.retry);
+	return err;
 }
 
 /*
@@ -800,11 +1173,13 @@ static int nfs4_proc_access(struct inode *inode, struct rpc_cred *cred, int mode
  * Both of these changes to the XDR layer would in fact be quite
  * minor, but I decided to leave them for a subsequent patch.
  */
-static int nfs4_proc_readlink(struct inode *inode, struct page *page)
+static int _nfs4_proc_readlink(struct inode *inode, struct page *page,
+		unsigned int pgbase, unsigned int pglen)
 {
 	struct nfs4_readlink args = {
 		.fh       = NFS_FH(inode),
-		.count    = PAGE_CACHE_SIZE,
+		.pgbase	  = pgbase,
+		.pglen    = pglen,
 		.pages    = &page,
 	};
 	struct rpc_message msg = {
@@ -813,11 +1188,23 @@ static int nfs4_proc_readlink(struct inode *inode, struct page *page)
 		.rpc_resp = NULL,
 	};
 
-	return nfs4_map_errors(rpc_call_sync(NFS_CLIENT(inode), &msg, 0));
+	return rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
 }
 
-static int
-nfs4_proc_read(struct nfs_read_data *rdata, struct file *filp)
+static int nfs4_proc_readlink(struct inode *inode, struct page *page,
+		unsigned int pgbase, unsigned int pglen)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(inode),
+				_nfs4_proc_readlink(inode, page, pgbase, pglen),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_proc_read(struct nfs_read_data *rdata)
 {
 	int flags = rdata->flags;
 	struct inode *inode = rdata->inode;
@@ -827,6 +1214,7 @@ nfs4_proc_read(struct nfs_read_data *rdata, struct file *filp)
 		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_READ],
 		.rpc_argp	= &rdata->args,
 		.rpc_resp	= &rdata->res,
+		.rpc_cred	= rdata->cred,
 	};
 	unsigned long timestamp = jiffies;
 	int status;
@@ -834,29 +1222,27 @@ nfs4_proc_read(struct nfs_read_data *rdata, struct file *filp)
 	dprintk("NFS call  read %d @ %Ld\n", rdata->args.count,
 			(long long) rdata->args.offset);
 
-	/*
-	 * Try first to use O_RDONLY, then O_RDWR stateid.
-	 */
-	if (filp) {
-		struct nfs4_state *state;
-		state = (struct nfs4_state *)filp->private_data;
-		rdata->args.state = state;
-		msg.rpc_cred = state->owner->so_cred;
-	} else {
-		rdata->args.state = NULL;
-		msg.rpc_cred = NFS_I(inode)->mm_cred;
-	}
-
 	fattr->valid = 0;
 	status = rpc_call_sync(server->client, &msg, flags);
 	if (!status)
 		renew_lease(server, timestamp);
 	dprintk("NFS reply read: %d\n", status);
-	return nfs4_map_errors(status);
+	return status;
 }
 
-static int
-nfs4_proc_write(struct nfs_write_data *wdata, struct file *filp)
+static int nfs4_proc_read(struct nfs_read_data *rdata)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(rdata->inode),
+				_nfs4_proc_read(rdata),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_proc_write(struct nfs_write_data *wdata)
 {
 	int rpcflags = wdata->flags;
 	struct inode *inode = wdata->inode;
@@ -866,33 +1252,32 @@ nfs4_proc_write(struct nfs_write_data *wdata, struct file *filp)
 		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_WRITE],
 		.rpc_argp	= &wdata->args,
 		.rpc_resp	= &wdata->res,
+		.rpc_cred	= wdata->cred,
 	};
 	int status;
 
 	dprintk("NFS call  write %d @ %Ld\n", wdata->args.count,
 			(long long) wdata->args.offset);
 
-	/*
-	 * Try first to use O_WRONLY, then O_RDWR stateid.
-	 */
-	if (filp) {
-		struct nfs4_state *state;
-		state = (struct nfs4_state *)filp->private_data;
-		wdata->args.state = state;
-		msg.rpc_cred = state->owner->so_cred;
-	} else {
-		wdata->args.state = NULL;
-		msg.rpc_cred = NFS_I(inode)->mm_cred;
-	}
-
 	fattr->valid = 0;
 	status = rpc_call_sync(server->client, &msg, rpcflags);
 	dprintk("NFS reply write: %d\n", status);
-	return nfs4_map_errors(status);
+	return status;
 }
 
-static int
-nfs4_proc_commit(struct nfs_write_data *cdata, struct file *filp)
+static int nfs4_proc_write(struct nfs_write_data *wdata)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(wdata->inode),
+				_nfs4_proc_write(wdata),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_proc_commit(struct nfs_write_data *cdata)
 {
 	struct inode *inode = cdata->inode;
 	struct nfs_fattr *fattr = cdata->res.fattr;
@@ -901,24 +1286,29 @@ nfs4_proc_commit(struct nfs_write_data *cdata, struct file *filp)
 		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_COMMIT],
 		.rpc_argp	= &cdata->args,
 		.rpc_resp	= &cdata->res,
+		.rpc_cred	= cdata->cred,
 	};
 	int status;
 
 	dprintk("NFS call  commit %d @ %Ld\n", cdata->args.count,
 			(long long) cdata->args.offset);
 
-	/*
-	 * Try first to use O_WRONLY, then O_RDWR stateid.
-	 */
-	if (filp)
-		msg.rpc_cred = ((struct nfs4_state *)filp->private_data)->owner->so_cred;
-	else
-		msg.rpc_cred = NFS_I(inode)->mm_cred;
-
 	fattr->valid = 0;
 	status = rpc_call_sync(server->client, &msg, 0);
 	dprintk("NFS reply commit: %d\n", status);
-	return nfs4_map_errors(status);
+	return status;
+}
+
+static int nfs4_proc_commit(struct nfs_write_data *cdata)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(cdata->inode),
+				_nfs4_proc_commit(cdata),
+				&exception);
+	} while (exception.retry);
+	return err;
 }
 
 /*
@@ -965,7 +1355,7 @@ nfs4_proc_create(struct inode *dir, struct qstr *name, struct iattr *sattr,
 	return inode;
 }
 
-static int nfs4_proc_remove(struct inode *dir, struct qstr *name)
+static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
 {
 	struct nfs4_remove_arg args = {
 		.fh = NFS_FH(dir),
@@ -982,7 +1372,19 @@ static int nfs4_proc_remove(struct inode *dir, struct qstr *name)
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 	if (status == 0)
 		update_changeattr(dir, &res);
-	return nfs4_map_errors(status);
+	return status;
+}
+
+static int nfs4_proc_remove(struct inode *dir, struct qstr *name)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(dir),
+				_nfs4_proc_remove(dir, name),
+				&exception);
+	} while (exception.retry);
+	return err;
 }
 
 struct unlink_desc {
@@ -1023,7 +1425,7 @@ static int nfs4_proc_unlink_done(struct dentry *dir, struct rpc_task *task)
 	return 0;
 }
 
-static int nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
+static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
 		struct inode *new_dir, struct qstr *new_name)
 {
 	struct nfs4_rename_arg arg = {
@@ -1046,10 +1448,24 @@ static int nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
 		update_changeattr(old_dir, &res.old_cinfo);
 		update_changeattr(new_dir, &res.new_cinfo);
 	}
-	return nfs4_map_errors(status);
+	return status;
 }
 
-static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
+static int nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
+		struct inode *new_dir, struct qstr *new_name)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(old_dir),
+				_nfs4_proc_rename(old_dir, old_name,
+					new_dir, new_name),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
 {
 	struct nfs4_link_arg arg = {
 		.fh     = NFS_FH(inode),
@@ -1068,10 +1484,22 @@ static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *n
 	if (!status)
 		update_changeattr(dir, &cinfo);
 
-	return nfs4_map_errors(status);
+	return status;
 }
 
-static int nfs4_proc_symlink(struct inode *dir, struct qstr *name,
+static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(inode),
+				_nfs4_proc_link(inode, dir, name),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name,
 		struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle,
 		struct nfs_fattr *fattr)
 {
@@ -1090,22 +1518,39 @@ static int nfs4_proc_symlink(struct inode *dir, struct qstr *name,
 		.fattr = fattr,
 	};
 	struct rpc_message msg = {
-		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
+		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK],
 		.rpc_argp = &arg,
 		.rpc_resp = &res,
 	};
 	int			status;
 
+	if (path->len > NFS4_MAXPATHLEN)
+		return -ENAMETOOLONG;
 	arg.u.symlink = path;
 	fattr->valid = 0;
 	
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 	if (!status)
 		update_changeattr(dir, &res.dir_cinfo);
-	return nfs4_map_errors(status);
+	return status;
 }
 
-static int nfs4_proc_mkdir(struct inode *dir, struct qstr *name,
+static int nfs4_proc_symlink(struct inode *dir, struct qstr *name,
+		struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle,
+		struct nfs_fattr *fattr)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(dir),
+				_nfs4_proc_symlink(dir, name, path, sattr,
+					fhandle, fattr),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_proc_mkdir(struct inode *dir, struct qstr *name,
 		struct iattr *sattr, struct nfs_fh *fhandle,
 		struct nfs_fattr *fattr)
 {
@@ -1135,10 +1580,25 @@ static int nfs4_proc_mkdir(struct inode *dir, struct qstr *name,
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 	if (!status)
 		update_changeattr(dir, &res.dir_cinfo);
-	return nfs4_map_errors(status);
+	return status;
 }
 
-static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
+static int nfs4_proc_mkdir(struct inode *dir, struct qstr *name,
+		struct iattr *sattr, struct nfs_fh *fhandle,
+		struct nfs_fattr *fattr)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(dir),
+				_nfs4_proc_mkdir(dir, name, sattr,
+					fhandle, fattr),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
                   u64 cookie, struct page *page, unsigned int count, int plus)
 {
 	struct inode		*dir = dentry->d_inode;
@@ -1164,10 +1624,24 @@ static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
 	if (status == 0)
 		memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE);
 	unlock_kernel();
-	return nfs4_map_errors(status);
+	return status;
 }
 
-static int nfs4_proc_mknod(struct inode *dir, struct qstr *name,
+static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
+                  u64 cookie, struct page *page, unsigned int count, int plus)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(dentry->d_inode),
+				_nfs4_proc_readdir(dentry, cred, cookie,
+					page, count, plus),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_proc_mknod(struct inode *dir, struct qstr *name,
 		struct iattr *sattr, dev_t rdev, struct nfs_fh *fh,
 		struct nfs_fattr *fattr)
 {
@@ -1214,10 +1688,25 @@ static int nfs4_proc_mknod(struct inode *dir, struct qstr *name,
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
 	if (!status)
 		update_changeattr(dir, &res.dir_cinfo);
-	return nfs4_map_errors(status);
+	return status;
+}
+
+static int nfs4_proc_mknod(struct inode *dir, struct qstr *name,
+		struct iattr *sattr, dev_t rdev, struct nfs_fh *fh,
+		struct nfs_fattr *fattr)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(dir),
+				_nfs4_proc_mknod(dir, name, sattr, rdev,
+					fh, fattr),
+				&exception);
+	} while (exception.retry);
+	return err;
 }
 
-static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
+static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
 		 struct nfs_fsstat *fsstat)
 {
 	struct nfs4_statfs_arg args = {
@@ -1231,10 +1720,22 @@ static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
 	};
 
 	fsstat->fattr->valid = 0;
-	return nfs4_map_errors(rpc_call_sync(server->client, &msg, 0));
+	return rpc_call_sync(server->client, &msg, 0);
 }
 
-static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
+static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat)
+{
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = nfs4_handle_exception(server,
+				_nfs4_proc_statfs(server, fhandle, fsstat),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
 		struct nfs_fsinfo *fsinfo)
 {
 	struct nfs4_fsinfo_arg args = {
@@ -1247,16 +1748,29 @@ static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
 		.rpc_resp = fsinfo,
 	};
 
-	return nfs4_map_errors(rpc_call_sync(server->client, &msg, 0));
+	return rpc_call_sync(server->client, &msg, 0);
+}
+
+static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
+{
+	struct nfs4_exception exception = { };
+	int err;
+
+	do {
+		err = nfs4_handle_exception(server,
+				_nfs4_do_fsinfo(server, fhandle, fsinfo),
+				&exception);
+	} while (exception.retry);
+	return err;
 }
 
 static int nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
 {
 	fsinfo->fattr->valid = 0;
-	return nfs4_map_errors(nfs4_do_fsinfo(server, fhandle, fsinfo));
+	return nfs4_do_fsinfo(server, fhandle, fsinfo);
 }
 
-static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
+static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
 		struct nfs_pathconf *pathconf)
 {
 	struct nfs4_pathconf_arg args = {
@@ -1276,7 +1790,21 @@ static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
 	}
 
 	pathconf->fattr->valid = 0;
-	return nfs4_map_errors(rpc_call_sync(server->client, &msg, 0));
+	return rpc_call_sync(server->client, &msg, 0);
+}
+
+static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
+		struct nfs_pathconf *pathconf)
+{
+	struct nfs4_exception exception = { };
+	int err;
+
+	do {
+		err = nfs4_handle_exception(server,
+				_nfs4_proc_pathconf(server, fhandle, pathconf),
+				&exception);
+	} while (exception.retry);
+	return err;
 }
 
 static void
@@ -1415,9 +1943,11 @@ renew_done(struct rpc_task *task)
 	if (task->tk_status < 0) {
 		switch (task->tk_status) {
 			case -NFS4ERR_STALE_CLIENTID:
+			case -NFS4ERR_EXPIRED:
+			case -NFS4ERR_CB_PATH_DOWN:
 				nfs4_schedule_state_recovery(clp);
-				return;
 		}
+		return;
 	}
 	spin_lock(&clp->cl_lock);
 	if (time_before(clp->cl_last_renewal,timestamp))
@@ -1450,11 +1980,13 @@ nfs4_proc_renew(struct nfs4_client *clp)
 	int status;
 
 	status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+	if (status < 0)
+		return status;
 	spin_lock(&clp->cl_lock);
 	if (time_before(clp->cl_last_renewal,now))
 		clp->cl_last_renewal = now;
 	spin_unlock(&clp->cl_lock);
-	return status;
+	return 0;
 }
 
 /*
@@ -1467,8 +1999,10 @@ static int
 nfs4_proc_file_open(struct inode *inode, struct file *filp)
 {
 	struct dentry *dentry = filp->f_dentry;
-	struct nfs4_state *state;
+	struct nfs_open_context *ctx;
+	struct nfs4_state *state = NULL;
 	struct rpc_cred *cred;
+	int status = -ENOMEM;
 
 	dprintk("nfs4_proc_file_open: starting on (%.*s/%.*s)\n",
 	                       (int)dentry->d_parent->d_name.len,
@@ -1478,21 +2012,28 @@ nfs4_proc_file_open(struct inode *inode, struct file *filp)
 
 	/* Find our open stateid */
 	cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
-	state = nfs4_find_state(inode, cred, filp->f_mode);
+	if (unlikely(cred == NULL))
+		return -ENOMEM;
+	ctx = alloc_nfs_open_context(dentry, cred);
 	put_rpccred(cred);
-	if (state == NULL) {
-		printk(KERN_WARNING "NFS: v4 raced in function %s\n", __FUNCTION__);
-		return -EIO; /* ERACE actually */
-	}
+	if (unlikely(ctx == NULL))
+		return -ENOMEM;
+	status = -EIO; /* ERACE actually */
+	state = nfs4_find_state(inode, cred, filp->f_mode);
+	if (unlikely(state == NULL))
+		goto no_state;
+	ctx->state = state;
 	nfs4_close_state(state, filp->f_mode);
-	if (filp->f_mode & FMODE_WRITE) {
-		lock_kernel();
-		nfs_set_mmcred(inode, state->owner->so_cred);
+	ctx->mode = filp->f_mode;
+	nfs_file_set_open_context(filp, ctx);
+	put_nfs_open_context(ctx);
+	if (filp->f_mode & FMODE_WRITE)
 		nfs_begin_data_update(inode);
-		unlock_kernel();
-	}
-	filp->private_data = state;
 	return 0;
+no_state:
+	printk(KERN_WARNING "NFS: v4 raced in function %s\n", __FUNCTION__);
+	put_nfs_open_context(ctx);
+	return status;
 }
 
 /*
@@ -1501,37 +2042,12 @@ nfs4_proc_file_open(struct inode *inode, struct file *filp)
 static int
 nfs4_proc_file_release(struct inode *inode, struct file *filp)
 {
-	struct nfs4_state *state = (struct nfs4_state *)filp->private_data;
-
-	if (state)
-		nfs4_close_state(state, filp->f_mode);
-	if (filp->f_mode & FMODE_WRITE) {
-		lock_kernel();
+	if (filp->f_mode & FMODE_WRITE)
 		nfs_end_data_update(inode);
-		unlock_kernel();
-	}
+	nfs_file_clear_open_context(filp);
 	return 0;
 }
 
-/*
- * Set up the nfspage struct with the right state info and credentials
- */
-static void
-nfs4_request_init(struct nfs_page *req, struct file *filp)
-{
-	struct nfs4_state *state;
-
-	if (!filp) {
-		req->wb_cred = get_rpccred(NFS_I(req->wb_inode)->mm_cred);
-		req->wb_state = NULL;
-		return;
-	}
-	state = (struct nfs4_state *)filp->private_data;
-	req->wb_state = state;
-	req->wb_cred = get_rpccred(state->owner->so_cred);
-	req->wb_lockowner = current->files;
-}
-
 static int
 nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server)
 {
@@ -1545,11 +2061,13 @@ nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server)
 		case -NFS4ERR_EXPIRED:
 			rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL, NULL);
 			nfs4_schedule_state_recovery(clp);
+			if (test_bit(NFS4CLNT_OK, &clp->cl_state))
+				rpc_wake_up_task(task);
 			task->tk_status = 0;
 			return -EAGAIN;
 		case -NFS4ERR_GRACE:
 		case -NFS4ERR_DELAY:
-			rpc_delay(task, NFS4_POLL_RETRY_TIME);
+			rpc_delay(task, NFS4_POLL_RETRY_MAX);
 			task->tk_status = 0;
 			return -EAGAIN;
 		case -NFS4ERR_OLD_STATEID:
@@ -1560,12 +2078,11 @@ nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server)
 	return 0;
 }
 
-int
-nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp)
+int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp)
 {
 	DEFINE_WAIT(wait);
 	sigset_t oldset;
-	int interruptible, res;
+	int interruptible, res = 0;
 
 	might_sleep();
 
@@ -1573,101 +2090,85 @@ nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp)
 	interruptible = TASK_UNINTERRUPTIBLE;
 	if (clnt->cl_intr)
 		interruptible = TASK_INTERRUPTIBLE;
-	do {
-		res = 0;
-		prepare_to_wait(&clp->cl_waitq, &wait, interruptible);
-		nfs4_schedule_state_recovery(clp);
-		if (test_bit(NFS4CLNT_OK, &clp->cl_state) &&
-				!test_bit(NFS4CLNT_SETUP_STATE, &clp->cl_state))
-			break;
-		if (clnt->cl_intr && signalled()) {
-			res = -ERESTARTSYS;
-			break;
-		}
+	prepare_to_wait(&clp->cl_waitq, &wait, interruptible);
+	nfs4_schedule_state_recovery(clp);
+	if (clnt->cl_intr && signalled())
+		res = -ERESTARTSYS;
+	else if (!test_bit(NFS4CLNT_OK, &clp->cl_state))
 		schedule();
-	} while(!test_bit(NFS4CLNT_OK, &clp->cl_state));
 	finish_wait(&clp->cl_waitq, &wait);
 	rpc_clnt_sigunmask(clnt, &oldset);
 	return res;
 }
 
-static int
-nfs4_delay(struct rpc_clnt *clnt)
+static int nfs4_delay(struct rpc_clnt *clnt, long *timeout)
 {
 	sigset_t oldset;
 	int res = 0;
 
 	might_sleep();
 
+	if (*timeout <= 0)
+		*timeout = NFS4_POLL_RETRY_MIN;
+	if (*timeout > NFS4_POLL_RETRY_MAX)
+		*timeout = NFS4_POLL_RETRY_MAX;
 	rpc_clnt_sigmask(clnt, &oldset);
 	if (clnt->cl_intr) {
 		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(NFS4_POLL_RETRY_TIME);
+		schedule_timeout(*timeout);
 		if (signalled())
 			res = -ERESTARTSYS;
 	} else {
 		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(NFS4_POLL_RETRY_TIME);
+		schedule_timeout(*timeout);
 	}
 	rpc_clnt_sigunmask(clnt, &oldset);
+	*timeout <<= 1;
 	return res;
 }
 
 /* This is the error handling routine for processes that are allowed
  * to sleep.
  */
-int
-nfs4_handle_error(struct nfs_server *server, int errorcode)
+int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception)
 {
 	struct nfs4_client *clp = server->nfs4_state;
 	int ret = errorcode;
 
+	exception->retry = 0;
 	switch(errorcode) {
+		case 0:
+			return 0;
 		case -NFS4ERR_STALE_CLIENTID:
 		case -NFS4ERR_STALE_STATEID:
 		case -NFS4ERR_EXPIRED:
 			ret = nfs4_wait_clnt_recover(server->client, clp);
+			if (ret == 0)
+				exception->retry = 1;
 			break;
 		case -NFS4ERR_GRACE:
 		case -NFS4ERR_DELAY:
-			ret = nfs4_delay(server->client);
+			ret = nfs4_delay(server->client, &exception->timeout);
+			if (ret == 0)
+				exception->retry = 1;
 			break;
 		case -NFS4ERR_OLD_STATEID:
-			ret = 0;
+			if (ret == 0)
+				exception->retry = 1;
 	}
 	/* We failed to handle the error */
 	return nfs4_map_errors(ret);
 }
 
-
-static int
-nfs4_request_compatible(struct nfs_page *req, struct file *filp, struct page *page)
-{
-	struct nfs4_state *state = NULL;
-	struct rpc_cred *cred = NULL;
-
-	if (req->wb_file != filp)
-		return 0;
-	if (req->wb_page != page)
-		return 0;
-	state = (struct nfs4_state *)filp->private_data;
-	if (req->wb_state != state)
-		return 0;
-	if (req->wb_lockowner != current->files)
-		return 0;
-	cred = state->owner->so_cred;
-	if (req->wb_cred != cred)
-		return 0;
-	return 1;
-}
-
-int
-nfs4_proc_setclientid(struct nfs4_client *clp,
-		u32 program, unsigned short port)
+int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short port)
 {
-	u32 *p;
-	struct nfs4_setclientid setclientid;
-	struct timespec tv;
+	static nfs4_verifier sc_verifier;
+	static int initialized;
+	
+	struct nfs4_setclientid setclientid = {
+		.sc_verifier = &sc_verifier,
+		.sc_prog = program,
+	};
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID],
 		.rpc_argp = &setclientid,
@@ -1675,15 +2176,24 @@ nfs4_proc_setclientid(struct nfs4_client *clp,
 		.rpc_cred = clp->cl_cred,
 	};
 
-	tv = CURRENT_TIME;
-	p = (u32*)setclientid.sc_verifier.data;
-	*p++ = (u32)tv.tv_sec;
-	*p = (u32)tv.tv_nsec;
-	setclientid.sc_name = clp->cl_ipaddr;
-	sprintf(setclientid.sc_netid, "tcp");
-	sprintf(setclientid.sc_uaddr, "%s.%d.%d", clp->cl_ipaddr, port >> 8, port & 255);
-	setclientid.sc_prog = htonl(program);
-	setclientid.sc_cb_ident = 0;
+	if (!initialized) {
+		struct timespec boot_time;
+		u32 *p;
+
+		initialized = 1;
+		boot_time = CURRENT_TIME;
+		p = (u32*)sc_verifier.data;
+		*p++ = htonl((u32)boot_time.tv_sec);
+		*p = htonl((u32)boot_time.tv_nsec);
+	}
+	setclientid.sc_name_len = scnprintf(setclientid.sc_name,
+			sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u",
+			clp->cl_ipaddr, NIPQUAD(clp->cl_addr.s_addr));
+	setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
+			sizeof(setclientid.sc_netid), "tcp");
+	setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr,
+			sizeof(setclientid.sc_uaddr), "%s.%d.%d",
+			clp->cl_ipaddr, port >> 8, port & 255);
 
 	return rpc_call_sync(clp->cl_rpcclient, &msg, 0);
 }
@@ -1712,6 +2222,40 @@ nfs4_proc_setclientid_confirm(struct nfs4_client *clp)
 	return status;
 }
 
+static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid)
+{
+	struct nfs4_delegreturnargs args = {
+		.fhandle = NFS_FH(inode),
+		.stateid = stateid,
+	};
+	struct rpc_message msg = {
+		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DELEGRETURN],
+		.rpc_argp = &args,
+		.rpc_cred = cred,
+	};
+
+	return rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+}
+
+int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid)
+{
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct nfs4_exception exception = { };
+	int err;
+	do {
+		err = _nfs4_proc_delegreturn(inode, cred, stateid);
+		switch (err) {
+			case -NFS4ERR_STALE_STATEID:
+			case -NFS4ERR_EXPIRED:
+				nfs4_schedule_state_recovery(server->nfs4_state);
+			case 0:
+				return 0;
+		}
+		err = nfs4_handle_exception(server, err, &exception);
+	} while (exception.retry);
+	return err;
+}
+
 #define NFS4_LOCK_MINTIMEOUT (1 * HZ)
 #define NFS4_LOCK_MAXTIMEOUT (30 * HZ)
 
@@ -1753,8 +2297,7 @@ nfs4_lck_length(struct file_lock *request)
 	return request->fl_end - request->fl_start + 1;
 }
 
-int
-nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request)
+static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request)
 {
 	struct inode *inode = state->inode;
 	struct nfs_server *server = NFS_SERVER(inode);
@@ -1778,6 +2321,7 @@ nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request)
 	struct nfs4_lock_state *lsp;
 	int status;
 
+	down_read(&clp->cl_sem);
 	nlo.clientid = clp->cl_clientid;
 	down(&state->lock_sema);
 	lsp = nfs4_find_lock_state(state, request->fl_owner);
@@ -1811,14 +2355,28 @@ nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request)
 	if (lsp)
 		nfs4_put_lock_state(lsp);
 	up(&state->lock_sema);
-	return nfs4_map_errors(status);
+	up_read(&clp->cl_sem);
+	return status;
 }
 
-int
-nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
+static int nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request)
+{
+	struct nfs4_exception exception = { };
+	int err;
+
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(state->inode),
+				_nfs4_proc_getlk(state, cmd, request),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
 {
 	struct inode *inode = state->inode;
 	struct nfs_server *server = NFS_SERVER(inode);
+	struct nfs4_client *clp = server->nfs4_state;
 	struct nfs_lockargs arg = {
 		.fh = NFS_FH(inode),
 		.type = nfs4_lck_type(cmd, request),
@@ -1838,29 +2396,48 @@ nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
 	struct nfs_locku_opargs luargs;
 	int status = 0;
 			
+	down_read(&clp->cl_sem);
 	down(&state->lock_sema);
 	lsp = nfs4_find_lock_state(state, request->fl_owner);
 	if (!lsp)
 		goto out;
-	luargs.seqid = lsp->ls_seqid;
-	memcpy(&luargs.stateid, &lsp->ls_stateid, sizeof(luargs.stateid));
-	arg.u.locku = &luargs;
-	status = rpc_call_sync(server->client, &msg, 0);
-	nfs4_increment_lock_seqid(status, lsp);
+	/* We might have lost the locks! */
+	if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) {
+		luargs.seqid = lsp->ls_seqid;
+		memcpy(&luargs.stateid, &lsp->ls_stateid, sizeof(luargs.stateid));
+		arg.u.locku = &luargs;
+		status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
+		nfs4_increment_lock_seqid(status, lsp);
+	}
 
 	if (status == 0) {
 		memcpy(&lsp->ls_stateid,  &res.u.stateid, 
 				sizeof(lsp->ls_stateid));
-		nfs4_notify_unlck(inode, request, lsp);
+		nfs4_notify_unlck(state, request, lsp);
 	}
 	nfs4_put_lock_state(lsp);
 out:
 	up(&state->lock_sema);
-	return nfs4_map_errors(status);
+	if (status == 0)
+		posix_lock_file(request->fl_file, request);
+	up_read(&clp->cl_sem);
+	return status;
 }
 
-static int
-nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
+static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
+{
+	struct nfs4_exception exception = { };
+	int err;
+
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(state->inode),
+				_nfs4_proc_unlck(state, cmd, request),
+				&exception);
+	} while (exception.retry);
+	return err;
+}
+
+static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *request, int reclaim)
 {
 	struct inode *inode = state->inode;
 	struct nfs_server *server = NFS_SERVER(inode);
@@ -1881,23 +2458,22 @@ nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
 		.rpc_cred	= state->owner->so_cred,
 	};
 	struct nfs_lock_opargs largs = {
+		.reclaim = reclaim,
 		.new_lock_owner = 0,
 	};
 	int status;
 
-	down(&state->lock_sema);
-	lsp = nfs4_find_lock_state(state, request->fl_owner);
-	if (lsp == NULL) {
+	lsp = nfs4_get_lock_state(state, request->fl_owner);
+	if (lsp == NULL)
+		return -ENOMEM;
+	if (!(lsp->ls_flags & NFS_LOCK_INITIALIZED)) {
 		struct nfs4_state_owner *owner = state->owner;
 		struct nfs_open_to_lock otl = {
 			.lock_owner = {
 				.clientid = server->nfs4_state->cl_clientid,
 			},
 		};
-		status = -ENOMEM;
-		lsp = nfs4_alloc_lock_state(state, request->fl_owner);
-		if (!lsp)
-			goto out;
+
 		otl.lock_seqid = lsp->ls_seqid;
 		otl.lock_owner.id = lsp->ls_id;
 		memcpy(&otl.open_stateid, &state->stateid, sizeof(otl.open_stateid));
@@ -1906,7 +2482,7 @@ nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
 		arg.u.lock = &largs;
 		down(&owner->so_sema);
 		otl.open_seqid = owner->so_seqid;
-		status = rpc_call_sync(server->client, &msg, 0);
+		status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
 		/* increment open_owner seqid on success, and 
 		* seqid mutating errors */
 		nfs4_increment_seqid(status, owner);
@@ -1919,32 +2495,70 @@ nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
 		largs.u.exist_lock = &el;
 		largs.new_lock_owner = 0;
 		arg.u.lock = &largs;
-		status = rpc_call_sync(server->client, &msg, 0);
+		status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
 	}
 	/* increment seqid on success, and * seqid mutating errors*/
 	nfs4_increment_lock_seqid(status, lsp);
 	/* save the returned stateid. */
 	if (status == 0) {
 		memcpy(&lsp->ls_stateid, &res.u.stateid, sizeof(nfs4_stateid));
-		nfs4_notify_setlk(inode, request, lsp);
+		lsp->ls_flags |= NFS_LOCK_INITIALIZED;
+		if (!reclaim)
+			nfs4_notify_setlk(state, request, lsp);
 	} else if (status == -NFS4ERR_DENIED)
 		status = -EAGAIN;
 	nfs4_put_lock_state(lsp);
-out:
+	return status;
+}
+
+int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
+{
+	return _nfs4_do_setlk(state, F_SETLK, request, 1);
+}
+
+static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
+{
+	struct nfs4_client *clp = state->owner->so_client;
+	int status;
+
+	down_read(&clp->cl_sem);
+	down(&state->lock_sema);
+	status = _nfs4_do_setlk(state, cmd, request, 0);
 	up(&state->lock_sema);
-	return nfs4_map_errors(status);
+	if (status == 0) {
+		/* Note: we always want to sleep here! */
+		request->fl_flags |= FL_SLEEP;
+		if (posix_lock_file_wait(request->fl_file, request) < 0)
+			printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
+	}
+	up_read(&clp->cl_sem);
+	return status;
+}
+
+static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
+{
+	struct nfs4_exception exception = { };
+	int err;
+
+	do {
+		err = nfs4_handle_exception(NFS_SERVER(state->inode),
+				_nfs4_proc_setlk(state, cmd, request),
+				&exception);
+	} while (exception.retry);
+	return err;
 }
 
 static int
 nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
 {
+	struct nfs_open_context *ctx;
 	struct nfs4_state *state;
 	unsigned long timeout = NFS4_LOCK_MINTIMEOUT;
 	int status;
 
 	/* verify open state */
-	state = (struct nfs4_state *)filp->private_data;
-	BUG_ON(!state);
+	ctx = (struct nfs_open_context *)filp->private_data;
+	state = ctx->state;
 
 	if (request->fl_start < 0 || request->fl_end < 0)
 		return -EINVAL;
@@ -2004,8 +2618,6 @@ struct nfs_rpc_ops	nfs_v4_clientops = {
 	.commit_setup	= nfs4_proc_commit_setup,
 	.file_open      = nfs4_proc_file_open,
 	.file_release   = nfs4_proc_file_release,
-	.request_init	= nfs4_request_init,
-	.request_compatible = nfs4_request_compatible,
 	.lock		= nfs4_proc_lock,
 };
 
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 0a8d90899..91e9bd77e 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -40,11 +40,15 @@
 
 #include <linux/config.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_idmap.h>
 #include <linux/workqueue.h>
 #include <linux/bitops.h>
 
+#include "callback.h"
+#include "delegation.h"
+
 #define OPENOWNER_POOL_SIZE	8
 
 static spinlock_t		state_spinlock = SPIN_LOCK_UNLOCKED;
@@ -93,21 +97,26 @@ nfs4_alloc_client(struct in_addr *addr)
 {
 	struct nfs4_client *clp;
 
-	if ((clp = kmalloc(sizeof(*clp), GFP_KERNEL))) {
-		memset(clp, 0, sizeof(*clp));
-		memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr));
-		init_rwsem(&clp->cl_sem);
-		INIT_LIST_HEAD(&clp->cl_state_owners);
-		INIT_LIST_HEAD(&clp->cl_unused);
-		spin_lock_init(&clp->cl_lock);
-		atomic_set(&clp->cl_count, 1);
-		INIT_WORK(&clp->cl_recoverd, nfs4_recover_state, clp);
-		INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp);
-		INIT_LIST_HEAD(&clp->cl_superblocks);
-		init_waitqueue_head(&clp->cl_waitq);
-		rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client");
-		clp->cl_state = 1 << NFS4CLNT_NEW;
+	if (nfs_callback_up() < 0)
+		return NULL;
+	if ((clp = kmalloc(sizeof(*clp), GFP_KERNEL)) == NULL) {
+		nfs_callback_down();
+		return NULL;
 	}
+	memset(clp, 0, sizeof(*clp));
+	memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr));
+	init_rwsem(&clp->cl_sem);
+	INIT_LIST_HEAD(&clp->cl_delegations);
+	INIT_LIST_HEAD(&clp->cl_state_owners);
+	INIT_LIST_HEAD(&clp->cl_unused);
+	spin_lock_init(&clp->cl_lock);
+	atomic_set(&clp->cl_count, 1);
+	INIT_WORK(&clp->cl_recoverd, nfs4_recover_state, clp);
+	INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp);
+	INIT_LIST_HEAD(&clp->cl_superblocks);
+	init_waitqueue_head(&clp->cl_waitq);
+	rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client");
+	clp->cl_state = 1 << NFS4CLNT_OK;
 	return clp;
 }
 
@@ -130,25 +139,52 @@ nfs4_free_client(struct nfs4_client *clp)
 	if (clp->cl_rpcclient)
 		rpc_shutdown_client(clp->cl_rpcclient);
 	kfree(clp);
+	nfs_callback_down();
+}
+
+static struct nfs4_client *__nfs4_find_client(struct in_addr *addr)
+{
+	struct nfs4_client *clp;
+	list_for_each_entry(clp, &nfs4_clientid_list, cl_servers) {
+		if (memcmp(&clp->cl_addr, addr, sizeof(clp->cl_addr)) == 0) {
+			atomic_inc(&clp->cl_count);
+			return clp;
+		}
+	}
+	return NULL;
+}
+
+struct nfs4_client *nfs4_find_client(struct in_addr *addr)
+{
+	struct nfs4_client *clp;
+	spin_lock(&state_spinlock);
+	clp = __nfs4_find_client(addr);
+	spin_unlock(&state_spinlock);
+	return clp;
 }
 
 struct nfs4_client *
 nfs4_get_client(struct in_addr *addr)
 {
-	struct nfs4_client *new, *clp = NULL;
+	struct nfs4_client *clp, *new = NULL;
 
-	new = nfs4_alloc_client(addr);
 	spin_lock(&state_spinlock);
-	list_for_each_entry(clp, &nfs4_clientid_list, cl_servers) {
-		if (memcmp(&clp->cl_addr, addr, sizeof(clp->cl_addr)) == 0)
-			goto found;
+	for (;;) {
+		clp = __nfs4_find_client(addr);
+		if (clp != NULL)
+			break;
+		clp = new;
+		if (clp != NULL) {
+			list_add(&clp->cl_servers, &nfs4_clientid_list);
+			new = NULL;
+			break;
+		}
+		spin_unlock(&state_spinlock);
+		new = nfs4_alloc_client(addr);
+		spin_lock(&state_spinlock);
+		if (new == NULL)
+			break;
 	}
-	if (new)
-		list_add(&new->cl_servers, &nfs4_clientid_list);
-	spin_unlock(&state_spinlock);
-	return new;
-found:
-	atomic_inc(&clp->cl_count);
 	spin_unlock(&state_spinlock);
 	if (new)
 		nfs4_free_client(new);
@@ -169,6 +205,16 @@ nfs4_put_client(struct nfs4_client *clp)
 	nfs4_free_client(clp);
 }
 
+int nfs4_init_client(struct nfs4_client *clp)
+{
+	int status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, nfs_callback_tcpport);
+	if (status == 0)
+		status = nfs4_proc_setclientid_confirm(clp);
+	if (status == 0)
+		nfs4_schedule_state_renewal(clp);
+	return status;
+}
+
 u32
 nfs4_alloc_lockowner_id(struct nfs4_client *clp)
 {
@@ -185,7 +231,6 @@ nfs4_client_grab_unused(struct nfs4_client *clp, struct rpc_cred *cred)
 		atomic_inc(&sp->so_count);
 		sp->so_cred = cred;
 		list_move(&sp->so_list, &clp->cl_state_owners);
-		sp->so_generation = clp->cl_generation;
 		clp->cl_nunused--;
 	}
 	return sp;
@@ -224,6 +269,7 @@ nfs4_alloc_state_owner(void)
 	init_MUTEX(&sp->so_sema);
 	sp->so_seqid = 0;                 /* arbitrary */
 	INIT_LIST_HEAD(&sp->so_states);
+	INIT_LIST_HEAD(&sp->so_delegations);
 	atomic_set(&sp->so_count, 1);
 	return sp;
 }
@@ -237,8 +283,11 @@ nfs4_unhash_state_owner(struct nfs4_state_owner *sp)
 	spin_unlock(&clp->cl_lock);
 }
 
-struct nfs4_state_owner *
-nfs4_get_state_owner(struct nfs_server *server, struct rpc_cred *cred)
+/*
+ * Note: must be called with clp->cl_sem held in order to prevent races
+ *       with reboot recovery!
+ */
+struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct rpc_cred *cred)
 {
 	struct nfs4_client *clp = server->nfs4_state;
 	struct nfs4_state_owner *sp, *new;
@@ -254,23 +303,23 @@ nfs4_get_state_owner(struct nfs_server *server, struct rpc_cred *cred)
 		new->so_client = clp;
 		new->so_id = nfs4_alloc_lockowner_id(clp);
 		new->so_cred = cred;
-		new->so_generation = clp->cl_generation;
 		sp = new;
 		new = NULL;
 	}
 	spin_unlock(&clp->cl_lock);
 	if (new)
 		kfree(new);
-	if (sp) {
-		if (!test_bit(NFS4CLNT_OK, &clp->cl_state))
-			nfs4_wait_clnt_recover(server->client, clp);
-	} else
-		put_rpccred(cred);
-	return sp;
+	if (sp != NULL)
+		return sp;
+	put_rpccred(cred);
+	return NULL;
 }
 
-void
-nfs4_put_state_owner(struct nfs4_state_owner *sp)
+/*
+ * Must be called with clp->cl_sem held in order to avoid races
+ * with state recovery...
+ */
+void nfs4_put_state_owner(struct nfs4_state_owner *sp)
 {
 	struct nfs4_client *clp = sp->so_client;
 	struct rpc_cred *cred = sp->so_cred;
@@ -330,8 +379,6 @@ __nfs4_find_state(struct inode *inode, struct rpc_cred *cred, mode_t mode)
 			continue;
 		if ((state->state & mode) != mode)
 			continue;
-		/* Add the state to the head of the inode's list */
-		list_move(&state->inode_states, &nfsi->open_states);
 		atomic_inc(&state->count);
 		if (mode & FMODE_READ)
 			state->nreaders++;
@@ -353,8 +400,6 @@ __nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner)
 		if (state->nreaders == 0 && state->nwriters == 0)
 			continue;
 		if (state->owner == owner) {
-			/* Add the state to the head of the inode's list */
-			list_move(&state->inode_states, &nfsi->open_states);
 			atomic_inc(&state->count);
 			return state;
 		}
@@ -411,51 +456,40 @@ out:
 	return state;
 }
 
-static void
-__nfs4_put_open_state(struct nfs4_state *state)
+/*
+ * Beware! Caller must be holding exactly one
+ * reference to clp->cl_sem and owner->so_sema!
+ */
+void nfs4_put_open_state(struct nfs4_state *state)
 {
 	struct inode *inode = state->inode;
 	struct nfs4_state_owner *owner = state->owner;
-	int status = 0;
 
-	if (!atomic_dec_and_lock(&state->count, &inode->i_lock)) {
-		up(&owner->so_sema);
+	if (!atomic_dec_and_lock(&state->count, &inode->i_lock))
 		return;
-	}
 	if (!list_empty(&state->inode_states))
 		list_del(&state->inode_states);
 	spin_unlock(&inode->i_lock);
 	list_del(&state->open_states);
-	if (state->state != 0) {
-		do {
-			status = nfs4_do_close(inode, state);
-			if (!status)
-				break;
-			up(&owner->so_sema);
-			status = nfs4_handle_error(NFS_SERVER(inode), status);
-			down(&owner->so_sema);
-		} while (!status);
-	}
-	up(&owner->so_sema);
+	BUG_ON (state->state != 0);
 	nfs4_free_open_state(state);
 	nfs4_put_state_owner(owner);
 }
 
-void
-nfs4_put_open_state(struct nfs4_state *state)
-{
-	down(&state->owner->so_sema);
-	__nfs4_put_open_state(state);
-}
-
-void
-nfs4_close_state(struct nfs4_state *state, mode_t mode)
+/*
+ * Beware! Caller must be holding no references to clp->cl_sem!
+ * of owner->so_sema!
+ */
+void nfs4_close_state(struct nfs4_state *state, mode_t mode)
 {
 	struct inode *inode = state->inode;
 	struct nfs4_state_owner *owner = state->owner;
+	struct nfs4_client *clp = owner->so_client;
 	int newstate;
 	int status = 0;
 
+	atomic_inc(&owner->so_count);
+	down_read(&clp->cl_sem);
 	down(&owner->so_sema);
 	/* Protect against nfs4_find_state() */
 	spin_lock(&inode->i_lock);
@@ -466,29 +500,24 @@ nfs4_close_state(struct nfs4_state *state, mode_t mode)
 	if (state->nwriters == 0 && state->nreaders == 0)
 		list_del_init(&state->inode_states);
 	spin_unlock(&inode->i_lock);
-	do {
-		newstate = 0;
-		if (state->state == 0)
-			break;
+	newstate = 0;
+	if (state->state != 0) {
 		if (state->nreaders)
 			newstate |= FMODE_READ;
 		if (state->nwriters)
 			newstate |= FMODE_WRITE;
 		if (state->state == newstate)
-			break;
+			goto out;
 		if (newstate != 0)
 			status = nfs4_do_downgrade(inode, state, newstate);
 		else
 			status = nfs4_do_close(inode, state);
-		if (!status) {
-			state->state = newstate;
-			break;
-		}
-		up(&owner->so_sema);
-		status = nfs4_handle_error(NFS_SERVER(inode), status);
-		down(&owner->so_sema);
-	} while (!status);
-	__nfs4_put_open_state(state);
+	}
+out:
+	nfs4_put_open_state(state);
+	up(&owner->so_sema);
+	nfs4_put_state_owner(owner);
+	up_read(&clp->cl_sem);
 }
 
 /*
@@ -524,8 +553,7 @@ nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
  *
  * The caller must be holding state->lock_sema
  */
-struct nfs4_lock_state *
-nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
+static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
 {
 	struct nfs4_lock_state *lsp;
 	struct nfs4_client *clp = state->owner->so_client;
@@ -533,12 +561,12 @@ nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
 	lsp = kmalloc(sizeof(*lsp), GFP_KERNEL);
 	if (lsp == NULL)
 		return NULL;
+	lsp->ls_flags = 0;
 	lsp->ls_seqid = 0;	/* arbitrary */
 	lsp->ls_id = -1; 
 	memset(lsp->ls_stateid.data, 0, sizeof(lsp->ls_stateid.data));
 	atomic_set(&lsp->ls_count, 1);
 	lsp->ls_owner = fl_owner;
-	lsp->ls_parent = state;
 	INIT_LIST_HEAD(&lsp->ls_locks);
 	spin_lock(&clp->cl_lock);
 	lsp->ls_id = nfs4_alloc_lockowner_id(clp);
@@ -546,6 +574,22 @@ nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
 	return lsp;
 }
 
+/*
+ * Return a compatible lock_state. If no initialized lock_state structure
+ * exists, return an uninitialized one.
+ *
+ * The caller must be holding state->lock_sema and clp->cl_sem
+ */
+struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner)
+{
+	struct nfs4_lock_state * lsp;
+	
+	lsp = nfs4_find_lock_state(state, owner);
+	if (lsp == NULL)
+		lsp = nfs4_alloc_lock_state(state, owner);
+	return lsp;
+}
+
 /*
  * Byte-range lock aware utility to initialize the stateid of read/write
  * requests.
@@ -567,10 +611,9 @@ nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_own
 }
 
 /*
-* Called with state->lock_sema held.
+* Called with state->lock_sema and clp->cl_sem held.
 */
-void
-nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *lsp)
+void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *lsp)
 {
 	if (status == NFS_OK || seqid_mutating_err(-status))
 		lsp->ls_seqid++;
@@ -597,13 +640,11 @@ nfs4_check_unlock(struct file_lock *fl, struct file_lock *request)
 /*
  * Post an initialized lock_state on the state->lock_states list.
  */
-void
-nfs4_notify_setlk(struct inode *inode, struct file_lock *request, struct nfs4_lock_state *lsp)
+void nfs4_notify_setlk(struct nfs4_state *state, struct file_lock *request, struct nfs4_lock_state *lsp)
 {
-	struct nfs4_state *state = lsp->ls_parent;
-
 	if (!list_empty(&lsp->ls_locks))
 		return;
+	atomic_inc(&lsp->ls_count);
 	write_lock(&state->state_lock);
 	list_add(&lsp->ls_locks, &state->lock_states);
 	set_bit(LK_STATE_IN_USE, &state->flags);
@@ -620,9 +661,9 @@ nfs4_notify_setlk(struct inode *inode, struct file_lock *request, struct nfs4_lo
  *
  */
 void
-nfs4_notify_unlck(struct inode *inode, struct file_lock *request, struct nfs4_lock_state *lsp)
+nfs4_notify_unlck(struct nfs4_state *state, struct file_lock *request, struct nfs4_lock_state *lsp)
 {
-	struct nfs4_state *state = lsp->ls_parent;
+	struct inode *inode = state->inode;
 	struct file_lock *fl;
 
 	for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
@@ -640,6 +681,7 @@ nfs4_notify_unlck(struct inode *inode, struct file_lock *request, struct nfs4_lo
 	if (list_empty(&state->lock_states))
 		clear_bit(LK_STATE_IN_USE, &state->flags);
 	write_unlock(&state->state_lock);
+	nfs4_put_lock_state(lsp);
 }
 
 /*
@@ -651,20 +693,18 @@ nfs4_put_lock_state(struct nfs4_lock_state *lsp)
 {
 	if (!atomic_dec_and_test(&lsp->ls_count))
 		return;
-	if (!list_empty(&lsp->ls_locks))
-		return;
+	BUG_ON (!list_empty(&lsp->ls_locks));
 	kfree(lsp);
 }
 
 /*
-* Called with sp->so_sema held.
+* Called with sp->so_sema and clp->cl_sem held.
 *
 * Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or
 * failed with a seqid incrementing error -
 * see comments nfs_fs.h:seqid_mutating_error()
 */
-void
-nfs4_increment_seqid(int status, struct nfs4_state_owner *sp)
+void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp)
 {
 	if (status == NFS_OK || seqid_mutating_err(-status))
 		sp->so_seqid++;
@@ -693,21 +733,14 @@ nfs4_recover_state(void *data)
 
 	init_completion(&args.complete);
 
-	down_read(&clp->cl_sem);
-	if (test_and_set_bit(NFS4CLNT_SETUP_STATE, &clp->cl_state))
-		goto out_failed;
 	if (kernel_thread(reclaimer, &args, CLONE_KERNEL) < 0)
 		goto out_failed_clear;
 	wait_for_completion(&args.complete);
 	return;
 out_failed_clear:
-	smp_mb__before_clear_bit();
-	clear_bit(NFS4CLNT_SETUP_STATE, &clp->cl_state);
-	smp_mb__after_clear_bit();
+	set_bit(NFS4CLNT_OK, &clp->cl_state);
 	wake_up_all(&clp->cl_waitq);
 	rpc_wake_up(&clp->cl_rpcwaitq);
-out_failed:
-	up_read(&clp->cl_sem);
 }
 
 /*
@@ -718,24 +751,66 @@ nfs4_schedule_state_recovery(struct nfs4_client *clp)
 {
 	if (!clp)
 		return;
-	smp_mb__before_clear_bit();
-	clear_bit(NFS4CLNT_OK, &clp->cl_state);
-	smp_mb__after_clear_bit();
-	schedule_work(&clp->cl_recoverd);
+	if (test_and_clear_bit(NFS4CLNT_OK, &clp->cl_state))
+		schedule_work(&clp->cl_recoverd);
 }
 
-static int
-nfs4_reclaim_open_state(struct nfs4_state_owner *sp)
+static int nfs4_reclaim_locks(struct nfs4_state *state)
+{
+	struct inode *inode = state->inode;
+	struct file_lock *fl;
+	int status = 0;
+
+	for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) {
+		if (!(fl->fl_flags & FL_POSIX))
+			continue;
+		if (((struct nfs_open_context *)fl->fl_file->private_data)->state != state)
+			continue;
+		status = nfs4_lock_reclaim(state, fl);
+		if (status >= 0)
+			continue;
+		switch (status) {
+			default:
+				printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n",
+						__FUNCTION__, status);
+			case -NFS4ERR_EXPIRED:
+			case -NFS4ERR_NO_GRACE:
+			case -NFS4ERR_RECLAIM_BAD:
+			case -NFS4ERR_RECLAIM_CONFLICT:
+				/* kill_proc(fl->fl_owner, SIGLOST, 1); */
+				break;
+			case -NFS4ERR_STALE_CLIENTID:
+				goto out_err;
+		}
+	}
+	return 0;
+out_err:
+	return status;
+}
+
+static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp)
 {
 	struct nfs4_state *state;
+	struct nfs4_lock_state *lock;
 	int status = 0;
 
 	list_for_each_entry(state, &sp->so_states, open_states) {
 		if (state->state == 0)
 			continue;
 		status = nfs4_open_reclaim(sp, state);
-		if (status >= 0)
+		list_for_each_entry(lock, &state->lock_states, ls_locks)
+			lock->ls_flags &= ~NFS_LOCK_INITIALIZED;
+		if (status >= 0) {
+			status = nfs4_reclaim_locks(state);
+			if (status < 0)
+				goto out_err;
+			list_for_each_entry(lock, &state->lock_states, ls_locks) {
+				if (!(lock->ls_flags & NFS_LOCK_INITIALIZED))
+					printk("%s: Lock reclaim failed!\n",
+							__FUNCTION__);
+			}
 			continue;
+		}
 		switch (status) {
 			default:
 				printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n",
@@ -762,75 +837,57 @@ out_err:
 	return status;
 }
 
-static int
-reclaimer(void *ptr)
+static int reclaimer(void *ptr)
 {
 	struct reclaimer_args *args = (struct reclaimer_args *)ptr;
 	struct nfs4_client *clp = args->clp;
 	struct nfs4_state_owner *sp;
-	int generation;
-	int status;
+	int status = 0;
 
 	daemonize("%u.%u.%u.%u-reclaim", NIPQUAD(clp->cl_addr));
 	allow_signal(SIGKILL);
 
+	atomic_inc(&clp->cl_count);
 	complete(&args->complete);
 
+	/* Ensure exclusive access to NFSv4 state */
+	lock_kernel();
+	down_write(&clp->cl_sem);
 	/* Are there any NFS mounts out there? */
 	if (list_empty(&clp->cl_superblocks))
 		goto out;
-	if (!test_bit(NFS4CLNT_NEW, &clp->cl_state)) {
-		status = nfs4_proc_renew(clp);
-		if (status == 0) {
-			set_bit(NFS4CLNT_OK, &clp->cl_state);
-			goto out;
-		}
-	}
-	status = nfs4_proc_setclientid(clp, 0, 0);
-	if (status)
-		goto out_error;
-	status = nfs4_proc_setclientid_confirm(clp);
+restart_loop:
+	status = nfs4_proc_renew(clp);
+	if (status == 0 || status == -NFS4ERR_CB_PATH_DOWN)
+		goto out;
+	status = nfs4_init_client(clp);
 	if (status)
 		goto out_error;
-	generation = ++(clp->cl_generation);
-	clear_bit(NFS4CLNT_NEW, &clp->cl_state);
-	set_bit(NFS4CLNT_OK, &clp->cl_state);
-	up_read(&clp->cl_sem);
-	nfs4_schedule_state_renewal(clp);
-restart_loop:
-	spin_lock(&clp->cl_lock);
+	/* Mark all delagations for reclaim */
+	nfs_delegation_mark_reclaim(clp);
+	/* Note: list is protected by exclusive lock on cl->cl_sem */
 	list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
-		if (sp->so_generation - generation >= 0)
-			continue;
-		atomic_inc(&sp->so_count);
-		spin_unlock(&clp->cl_lock);
-		down(&sp->so_sema);
-		if (sp->so_generation - generation < 0) {
-			smp_rmb();
-			sp->so_generation = clp->cl_generation;
-			status = nfs4_reclaim_open_state(sp);
-		}
-		up(&sp->so_sema);
-		nfs4_put_state_owner(sp);
+		status = nfs4_reclaim_open_state(sp);
 		if (status < 0) {
 			if (status == -NFS4ERR_STALE_CLIENTID)
-				nfs4_schedule_state_recovery(clp);
-			goto out;
+				goto restart_loop;
+			goto out_error;
 		}
-		goto restart_loop;
 	}
-	spin_unlock(&clp->cl_lock);
+	nfs_delegation_reap_unclaimed(clp);
 out:
-	smp_mb__before_clear_bit();
-	clear_bit(NFS4CLNT_SETUP_STATE, &clp->cl_state);
-	smp_mb__after_clear_bit();
+	set_bit(NFS4CLNT_OK, &clp->cl_state);
+	up_write(&clp->cl_sem);
+	unlock_kernel();
 	wake_up_all(&clp->cl_waitq);
 	rpc_wake_up(&clp->cl_rpcwaitq);
+	if (status == -NFS4ERR_CB_PATH_DOWN)
+		nfs_handle_cb_pathdown(clp);
+	nfs4_put_client(clp);
 	return 0;
 out_error:
-	printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %u.%u.%u.%u\n",
-				NIPQUAD(clp->cl_addr.s_addr));
-	up_read(&clp->cl_sem);
+	printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %u.%u.%u.%u with error %d\n",
+				NIPQUAD(clp->cl_addr.s_addr), -status);
 	goto out;
 }
 
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index a14079f53..481cb0396 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -84,6 +84,7 @@ static int nfs_stat_to_errno(int);
 				((3+NFS4_FHSIZE) >> 2))
 #define encode_getattr_maxsz    (op_encode_hdr_maxsz + 3)
 #define nfs4_name_maxsz		(1 + ((3 + NFS4_MAXNAMLEN) >> 2))
+#define nfs4_path_maxsz		(1 + ((3 + NFS4_MAXPATHLEN) >> 2))
 #define nfs4_fattr_bitmap_maxsz (36 + 2 * nfs4_name_maxsz)
 #define decode_getattr_maxsz    (op_decode_hdr_maxsz + 3 + \
                                 nfs4_fattr_bitmap_maxsz)
@@ -118,10 +119,17 @@ static int nfs_stat_to_errno(int);
 #define encode_link_maxsz	(op_encode_hdr_maxsz + \
 				nfs4_name_maxsz)
 #define decode_link_maxsz	(op_decode_hdr_maxsz + 5)
+#define encode_symlink_maxsz	(op_encode_hdr_maxsz + \
+				1 + nfs4_name_maxsz + \
+				nfs4_path_maxsz + \
+				nfs4_fattr_bitmap_maxsz)
+#define decode_symlink_maxsz	(op_decode_hdr_maxsz + 8)
 #define encode_create_maxsz	(op_encode_hdr_maxsz + \
-				2 + 2 * nfs4_name_maxsz + \
+				2 + nfs4_name_maxsz + \
 				nfs4_fattr_bitmap_maxsz)
 #define decode_create_maxsz	(op_decode_hdr_maxsz + 8)
+#define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4)
+#define decode_delegreturn_maxsz (op_decode_hdr_maxsz)
 #define NFS4_enc_compound_sz	(1024)  /* XXX: large enough? */
 #define NFS4_dec_compound_sz	(1024)  /* XXX: large enough? */
 #define NFS4_enc_read_sz	(compound_encode_hdr_maxsz + \
@@ -172,16 +180,14 @@ static int nfs_stat_to_errno(int);
 #define NFS4_dec_open_confirm_sz        (compound_decode_hdr_maxsz + \
                                         decode_putfh_maxsz + \
                                         op_decode_hdr_maxsz + 4)
-#define NFS4_enc_open_reclaim_sz	(compound_encode_hdr_maxsz + \
+#define NFS4_enc_open_noattr_sz	(compound_encode_hdr_maxsz + \
 					encode_putfh_maxsz + \
 					op_encode_hdr_maxsz + \
-					11 + \
-					encode_getattr_maxsz)
-#define NFS4_dec_open_reclaim_sz	(compound_decode_hdr_maxsz + \
+					11)
+#define NFS4_dec_open_noattr_sz	(compound_decode_hdr_maxsz + \
 					decode_putfh_maxsz + \
 					op_decode_hdr_maxsz + \
-					4 + 5 + 2 + 3 + \
-					decode_getattr_maxsz)
+					4 + 5 + 2 + 3)
 #define NFS4_enc_open_downgrade_sz \
 				(compound_encode_hdr_maxsz + \
                                 encode_putfh_maxsz + \
@@ -313,6 +319,16 @@ static int nfs_stat_to_errno(int);
 				decode_savefh_maxsz + \
 				decode_putfh_maxsz + \
 				decode_link_maxsz)
+#define NFS4_enc_symlink_sz	(compound_encode_hdr_maxsz + \
+				encode_putfh_maxsz + \
+				encode_symlink_maxsz + \
+				encode_getattr_maxsz + \
+				encode_getfh_maxsz)
+#define NFS4_dec_symlink_sz	(compound_decode_hdr_maxsz + \
+				decode_putfh_maxsz + \
+				decode_symlink_maxsz + \
+				decode_getattr_maxsz + \
+				decode_getfh_maxsz)
 #define NFS4_enc_create_sz	(compound_encode_hdr_maxsz + \
 				encode_putfh_maxsz + \
 				encode_create_maxsz + \
@@ -339,6 +355,11 @@ static int nfs_stat_to_errno(int);
 				encode_getattr_maxsz)
 #define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \
 				decode_getattr_maxsz)
+#define NFS4_enc_delegreturn_sz	(compound_encode_hdr_maxsz + \
+				encode_putfh_maxsz + \
+				encode_delegreturn_maxsz)
+#define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \
+				decode_delegreturn_maxsz)
 
 static struct {
 	unsigned int	mode;
@@ -388,6 +409,15 @@ struct compound_hdr {
 	BUG_ON(!p);						\
 } while (0)
 
+static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
+{
+	uint32_t *p;
+
+	p = xdr_reserve_space(xdr, 4 + len);
+	BUG_ON(p == NULL);
+	xdr_encode_opaque(p, str, len);
+}
+
 static int encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
 {
 	uint32_t *p;
@@ -402,6 +432,15 @@ static int encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
 	return 0;
 }
 
+static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *verf)
+{
+	uint32_t *p;
+
+	p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE);
+	BUG_ON(p == NULL);
+	xdr_encode_opaque_fixed(p, verf->data, NFS4_VERIFIER_SIZE);
+}
+
 static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const struct nfs_server *server)
 {
 	char owner_name[IDMAP_NAMESZ];
@@ -742,19 +781,12 @@ static int encode_lookup(struct xdr_stream *xdr, const struct qstr *name)
 	return 0;
 }
 
-static int encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg)
+static void encode_share_access(struct xdr_stream *xdr, int open_flags)
 {
-	int status;
 	uint32_t *p;
 
- /*
- * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4,
- * owner 4, opentype 4 = 36
- */
-	RESERVE_SPACE(36);
-	WRITE32(OP_OPEN);
-	WRITE32(arg->seqid);
-	switch (arg->share_access) {
+	RESERVE_SPACE(8);
+	switch (open_flags & (FMODE_READ|FMODE_WRITE)) {
 		case FMODE_READ:
 			WRITE32(NFS4_SHARE_ACCESS_READ);
 			break;
@@ -767,84 +799,135 @@ static int encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg)
 		default:
 			BUG();
 	}
-	WRITE32(0);                  /* for linux, share_deny = 0 always */
+	WRITE32(0);		/* for linux, share_deny = 0 always */
+}
+
+static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_openargs *arg)
+{
+	uint32_t *p;
+ /*
+ * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4,
+ * owner 4 = 32
+ */
+	RESERVE_SPACE(8);
+	WRITE32(OP_OPEN);
+	WRITE32(arg->seqid);
+	encode_share_access(xdr, arg->open_flags);
+	RESERVE_SPACE(16);
 	WRITE64(arg->clientid);
 	WRITE32(4);
 	WRITE32(arg->id);
-	WRITE32(arg->opentype);
+}
 
-	if (arg->opentype == NFS4_OPEN_CREATE) {
-		if (arg->createmode == NFS4_CREATE_EXCLUSIVE) {
-			RESERVE_SPACE(12);
-			WRITE32(arg->createmode);
-			WRITEMEM(arg->u.verifier.data, sizeof(arg->u.verifier.data));
-		}
-		else if (arg->u.attrs) {
-			RESERVE_SPACE(4);
-			WRITE32(arg->createmode);
-			if ((status = encode_attrs(xdr, arg->u.attrs, arg->server)))
-				return status;
-		}
-		else {
-			RESERVE_SPACE(12);
-			WRITE32(arg->createmode);
-			WRITE32(0);
-			WRITE32(0);
-		}
+static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg)
+{
+	uint32_t *p;
+
+	RESERVE_SPACE(4);
+	switch(arg->open_flags & O_EXCL) {
+		case 0:
+			WRITE32(NFS4_CREATE_UNCHECKED);
+			encode_attrs(xdr, arg->u.attrs, arg->server);
+			break;
+		default:
+			WRITE32(NFS4_CREATE_EXCLUSIVE);
+			encode_nfs4_verifier(xdr, &arg->u.verifier);
 	}
+}
 
-	RESERVE_SPACE(8 + arg->name->len);
-	WRITE32(NFS4_OPEN_CLAIM_NULL);
-	WRITE32(arg->name->len);
-	WRITEMEM(arg->name->name, arg->name->len);
+static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *arg)
+{
+	uint32_t *p;
 
-	return 0;
+	RESERVE_SPACE(4);
+	switch (arg->open_flags & O_CREAT) {
+		case 0:
+			WRITE32(NFS4_OPEN_NOCREATE);
+			break;
+		default:
+			BUG_ON(arg->claim != NFS4_OPEN_CLAIM_NULL);
+			WRITE32(NFS4_OPEN_CREATE);
+			encode_createmode(xdr, arg);
+	}
 }
 
-static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg)
+static inline void encode_delegation_type(struct xdr_stream *xdr, int delegation_type)
 {
 	uint32_t *p;
 
-	RESERVE_SPACE(8+sizeof(arg->stateid.data));
-	WRITE32(OP_OPEN_CONFIRM);
-	WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data));
-	WRITE32(arg->seqid);
+	RESERVE_SPACE(4);
+	switch (delegation_type) {
+		case 0:
+			WRITE32(NFS4_OPEN_DELEGATE_NONE);
+			break;
+		case FMODE_READ:
+			WRITE32(NFS4_OPEN_DELEGATE_READ);
+			break;
+		case FMODE_WRITE|FMODE_READ:
+			WRITE32(NFS4_OPEN_DELEGATE_WRITE);
+			break;
+		default:
+			BUG();
+	}
+}
 
-	return 0;
+static inline void encode_claim_null(struct xdr_stream *xdr, const struct qstr *name)
+{
+	uint32_t *p;
+
+	RESERVE_SPACE(4);
+	WRITE32(NFS4_OPEN_CLAIM_NULL);
+	encode_string(xdr, name->len, name->name);
 }
 
+static inline void encode_claim_previous(struct xdr_stream *xdr, int type)
+{
+	uint32_t *p;
+
+	RESERVE_SPACE(4);
+	WRITE32(NFS4_OPEN_CLAIM_PREVIOUS);
+	encode_delegation_type(xdr, type);
+}
 
-static int encode_open_reclaim(struct xdr_stream *xdr, const struct nfs_open_reclaimargs *arg)
+static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struct qstr *name, const nfs4_stateid *stateid)
 {
 	uint32_t *p;
 
- /*
- * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4,
- * owner 4, opentype 4, claim 4, delegation_type 4 = 44
- */
-	RESERVE_SPACE(44);
-	WRITE32(OP_OPEN);
-	WRITE32(arg->seqid);
-	switch (arg->share_access) {
-		case FMODE_READ:
-			WRITE32(NFS4_SHARE_ACCESS_READ);
+	RESERVE_SPACE(4+sizeof(stateid->data));
+	WRITE32(NFS4_OPEN_CLAIM_DELEGATE_CUR);
+	WRITEMEM(stateid->data, sizeof(stateid->data));
+	encode_string(xdr, name->len, name->name);
+}
+
+static int encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg)
+{
+	encode_openhdr(xdr, arg);
+	encode_opentype(xdr, arg);
+	switch (arg->claim) {
+		case NFS4_OPEN_CLAIM_NULL:
+			encode_claim_null(xdr, arg->name);
 			break;
-		case FMODE_WRITE:
-			WRITE32(NFS4_SHARE_ACCESS_WRITE);
+		case NFS4_OPEN_CLAIM_PREVIOUS:
+			encode_claim_previous(xdr, arg->u.delegation_type);
 			break;
-		case FMODE_READ|FMODE_WRITE:
-			WRITE32(NFS4_SHARE_ACCESS_BOTH);
+		case NFS4_OPEN_CLAIM_DELEGATE_CUR:
+			encode_claim_delegate_cur(xdr, arg->name, &arg->u.delegation);
 			break;
 		default:
 			BUG();
 	}
-	WRITE32(0);                  /* for linux, share_deny = 0 always */
-	WRITE64(arg->clientid);
-	WRITE32(4);
-	WRITE32(arg->id);
-	WRITE32(NFS4_OPEN_NOCREATE);
-	WRITE32(NFS4_OPEN_CLAIM_PREVIOUS);
-	WRITE32(NFS4_OPEN_DELEGATE_NONE);
+	return 0;
+}
+
+static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg)
+{
+	uint32_t *p;
+
+	RESERVE_SPACE(8+sizeof(arg->stateid.data));
+	WRITE32(OP_OPEN_CONFIRM);
+	WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data));
+	WRITE32(arg->seqid);
+
 	return 0;
 }
 
@@ -852,14 +935,11 @@ static int encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closea
 {
 	uint32_t *p;
 
-	RESERVE_SPACE(16+sizeof(arg->stateid.data));
+	RESERVE_SPACE(8+sizeof(arg->stateid.data));
 	WRITE32(OP_OPEN_DOWNGRADE);
 	WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data));
 	WRITE32(arg->seqid);
-	WRITE32(arg->share_access);
-	/* No deny modes */
-	WRITE32(0);
-
+	encode_share_access(xdr, arg->open_flags);
 	return 0;
 }
 
@@ -887,15 +967,15 @@ static int encode_putrootfh(struct xdr_stream *xdr)
         return 0;
 }
 
-static void encode_stateid(struct xdr_stream *xdr, struct nfs4_state *state, fl_owner_t lockowner)
+static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx)
 {
 	extern nfs4_stateid zero_stateid;
 	nfs4_stateid stateid;
 	uint32_t *p;
 
 	RESERVE_SPACE(16);
-	if (state != NULL) {
-		nfs4_copy_stateid(&stateid, state, lockowner);
+	if (ctx->state != NULL) {
+		nfs4_copy_stateid(&stateid, ctx->state, ctx->lockowner);
 		WRITEMEM(stateid.data, sizeof(stateid.data));
 	} else
 		WRITEMEM(zero_stateid.data, sizeof(zero_stateid.data));
@@ -908,7 +988,7 @@ static int encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args)
 	RESERVE_SPACE(4);
 	WRITE32(OP_READ);
 
-	encode_stateid(xdr, args->state, args->lockowner);
+	encode_stateid(xdr, args->context);
 
 	RESERVE_SPACE(12);
 	WRITE64(args->offset);
@@ -927,7 +1007,7 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
 	WRITE32(OP_READDIR);
 	WRITE64(readdir->cookie);
 	WRITEMEM(readdir->verifier.data, sizeof(readdir->verifier.data));
-	WRITE32(readdir->count >> 5);  /* meaningless "dircount" field */
+	WRITE32(readdir->count >> 1);  /* We're not doing readdirplus */
 	WRITE32(readdir->count);
 	WRITE32(2);
 	WRITE32(FATTR4_WORD0_FILEID);
@@ -947,7 +1027,6 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
 static int encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req)
 {
 	struct rpc_auth *auth = req->rq_task->tk_auth;
-	unsigned int count = readlink->count - 5;
 	unsigned int replen;
 	uint32_t *p;
 
@@ -956,10 +1035,11 @@ static int encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *r
 
 	/* set up reply kvec
 	 *    toplevel_status + taglen + rescount + OP_PUTFH + status
-	 *      + OP_READLINK + status  = 7
+	 *      + OP_READLINK + status + string length = 8
 	 */
-	replen = (RPC_REPHDRSIZE + auth->au_rslack + 7) << 2;
-	xdr_inline_pages(&req->rq_rcv_buf, replen, readlink->pages, 0, count);
+	replen = (RPC_REPHDRSIZE + auth->au_rslack + 8) << 2;
+	xdr_inline_pages(&req->rq_rcv_buf, replen, readlink->pages,
+			readlink->pgbase, readlink->pglen);
 	
 	return 0;
 }
@@ -1031,26 +1111,18 @@ static int encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *
 
 static int encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid)
 {
-	uint32_t total_len;
-	uint32_t len1, len2, len3;
 	uint32_t *p;
 
-	len1 = strlen(setclientid->sc_name);
-	len2 = strlen(setclientid->sc_netid);
-	len3 = strlen(setclientid->sc_uaddr);
-	total_len = XDR_QUADLEN(len1) + XDR_QUADLEN(len2) + XDR_QUADLEN(len3);
-	total_len = (total_len << 2) + 24 + sizeof(setclientid->sc_verifier.data);
-
-	RESERVE_SPACE(total_len);
+	RESERVE_SPACE(4 + sizeof(setclientid->sc_verifier->data));
 	WRITE32(OP_SETCLIENTID);
-	WRITEMEM(setclientid->sc_verifier.data, sizeof(setclientid->sc_verifier.data));
-	WRITE32(len1);
-	WRITEMEM(setclientid->sc_name, len1);
+	WRITEMEM(setclientid->sc_verifier->data, sizeof(setclientid->sc_verifier->data));
+
+	encode_string(xdr, setclientid->sc_name_len, setclientid->sc_name);
+	RESERVE_SPACE(4);
 	WRITE32(setclientid->sc_prog);
-	WRITE32(len2);
-	WRITEMEM(setclientid->sc_netid, len2);
-	WRITE32(len3);
-	WRITEMEM(setclientid->sc_uaddr, len3);
+	encode_string(xdr, setclientid->sc_netid_len, setclientid->sc_netid);
+	encode_string(xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr);
+	RESERVE_SPACE(4);
 	WRITE32(setclientid->sc_cb_ident);
 
 	return 0;
@@ -1075,7 +1147,7 @@ static int encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args
 	RESERVE_SPACE(4);
 	WRITE32(OP_WRITE);
 
-	encode_stateid(xdr, args->state, args->lockowner);
+	encode_stateid(xdr, args->context);
 
 	RESERVE_SPACE(16);
 	WRITE64(args->offset);
@@ -1086,6 +1158,18 @@ static int encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args
 
 	return 0;
 }
+
+static int encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid)
+{
+	uint32_t *p;
+
+	RESERVE_SPACE(20);
+
+	WRITE32(OP_DELEGRETURN);
+	WRITEMEM(stateid->data, sizeof(stateid->data));
+	return 0;
+
+}
 /*
  * END OF "GENERIC" ENCODE ROUTINES.
  */
@@ -1236,13 +1320,21 @@ static int nfs4_xdr_enc_create(struct rpc_rqst *req, uint32_t *p, const struct n
 		goto out;
 	if ((status = encode_create(&xdr, args)) != 0)
 		goto out;
-	if ((status = encode_getfattr(&xdr, args->bitmask)) != 0)
+	if ((status = encode_getfh(&xdr)) != 0)
 		goto out;
-	status = encode_getfh(&xdr);
+	status = encode_getfattr(&xdr, args->bitmask);
 out:
 	return status;
 }
 
+/*
+ * Encode SYMLINK request
+ */
+static int nfs4_xdr_enc_symlink(struct rpc_rqst *req, uint32_t *p, const struct nfs4_create_arg *args)
+{
+	return nfs4_xdr_enc_create(req, p, args);
+}
+
 /*
  * Encode GETATTR request
  */
@@ -1301,10 +1393,10 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, uint32_t *p, struct nfs_opena
 	status = encode_open(&xdr, args);
 	if (status)
 		goto out;
-	status = encode_getfattr(&xdr, args->bitmask);
+	status = encode_getfh(&xdr);
 	if (status)
 		goto out;
-	status = encode_getfh(&xdr);
+	status = encode_getfattr(&xdr, args->bitmask);
 out:
 	return status;
 }
@@ -1331,13 +1423,13 @@ out:
 }
 
 /*
- * Encode an OPEN request
+ * Encode an OPEN request with no attributes.
  */
-static int nfs4_xdr_enc_open_reclaim(struct rpc_rqst *req, uint32_t *p, struct nfs_open_reclaimargs *args)
+static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, uint32_t *p, struct nfs_openargs *args)
 {
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
-		.nops   = 3,
+		.nops   = 2,
 	};
 	int status;
 
@@ -1346,10 +1438,7 @@ static int nfs4_xdr_enc_open_reclaim(struct rpc_rqst *req, uint32_t *p, struct n
 	status = encode_putfh(&xdr, args->fh);
 	if (status)
 		goto out;
-	status = encode_open_reclaim(&xdr, args);
-	if (status)
-		goto out;
-	status = encode_getfattr(&xdr, args->bitmask);
+	status = encode_open(&xdr, args);
 out:
 	return status;
 }
@@ -1715,6 +1804,24 @@ static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, s
 	return status;
 }
 
+/*
+ * DELEGRETURN request
+ */
+static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, uint32_t *p, const struct nfs4_delegreturnargs *args)
+{
+	struct xdr_stream xdr;
+	struct compound_hdr hdr = {
+		.nops = 2,
+	};
+	int status;
+
+	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+	encode_compound_hdr(&xdr, &hdr);
+	if ((status = encode_putfh(&xdr, args->fhandle)) == 0)
+		status = encode_delegreturn(&xdr, args->stateid);
+	return status;
+}
+
 /*
  * START OF "GENERIC" DECODE ROUTINES.
  *   These may look a little ugly since they are imported from a "generic"
@@ -1749,6 +1856,17 @@ static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, s
 	} \
 } while (0)
 
+static int decode_opaque_inline(struct xdr_stream *xdr, uint32_t *len, char **string)
+{
+	uint32_t *p;
+
+	READ_BUF(4);
+	READ32(*len);
+	READ_BUF(*len);
+	*string = (char *)p;
+	return 0;
+}
+
 static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
 {
 	uint32_t *p;
@@ -1785,6 +1903,17 @@ static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
 	return 0;
 }
 
+/* Dummy routine */
+static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs4_client *clp)
+{
+	uint32_t *p;
+	uint32_t strlen;
+	char *str;
+
+	READ_BUF(12);
+	return decode_opaque_inline(xdr, &strlen, &str);
+}
+
 static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
 {
 	uint32_t bmlen, *p;
@@ -2717,10 +2846,56 @@ static int decode_lookup(struct xdr_stream *xdr)
 	return decode_op_hdr(xdr, OP_LOOKUP);
 }
 
+/* This is too sick! */
+static int decode_space_limit(struct xdr_stream *xdr, u64 *maxsize)
+{
+        uint32_t *p;
+	uint32_t limit_type, nblocks, blocksize;
+
+	READ_BUF(12);
+	READ32(limit_type);
+	switch (limit_type) {
+		case 1:
+			READ64(*maxsize);
+			break;
+		case 2:
+			READ32(nblocks);
+			READ32(blocksize);
+			*maxsize = (uint64_t)nblocks * (uint64_t)blocksize;
+	}
+	return 0;
+}
+
+static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
+{
+        uint32_t *p;
+        uint32_t delegation_type;
+
+	READ_BUF(4);
+	READ32(delegation_type);
+	if (delegation_type == NFS4_OPEN_DELEGATE_NONE) {
+		res->delegation_type = 0;
+		return 0;
+	}
+	READ_BUF(20);
+	COPYMEM(res->delegation.data, sizeof(res->delegation.data));
+	READ32(res->do_recall);
+	switch (delegation_type) {
+		case NFS4_OPEN_DELEGATE_READ:
+			res->delegation_type = FMODE_READ;
+			break;
+		case NFS4_OPEN_DELEGATE_WRITE:
+			res->delegation_type = FMODE_WRITE|FMODE_READ;
+			if (decode_space_limit(xdr, &res->maxsize) < 0)
+				return -EIO;
+	}
+	return decode_ace(xdr, NULL, res->server->nfs4_state);
+}
+
 static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
 {
         uint32_t *p;
-        uint32_t bmlen, delegation_type;
+        uint32_t bmlen;
         int status;
 
         status = decode_op_hdr(xdr, OP_OPEN);
@@ -2737,11 +2912,9 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
         if (bmlen > 10)
                 goto xdr_error;
 
-        READ_BUF((bmlen << 2) + 4);
+        READ_BUF(bmlen << 2);
         p += bmlen;
-        READ32(delegation_type);
-        if (delegation_type == NFS4_OPEN_DELEGATE_NONE)
-		return 0;
+	return decode_delegation(xdr, res);
 xdr_error:
 	printk(KERN_NOTICE "%s: xdr error!\n", __FUNCTION__);
 	return -EIO;
@@ -2817,8 +2990,8 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
 	struct kvec	*iov = rcvbuf->head;
 	unsigned int	nr, pglen = rcvbuf->page_len;
 	uint32_t	*end, *entry, *p, *kaddr;
-	uint32_t	len, attrlen, word;
-	int 		i, hdrlen, recvd, status;
+	uint32_t	len, attrlen;
+	int 		hdrlen, recvd, status;
 
 	status = decode_op_hdr(xdr, OP_READDIR);
 	if (status)
@@ -2839,42 +3012,24 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
 	for (nr = 0; *p++; nr++) {
 		if (p + 3 > end)
 			goto short_pkt;
-		p += 2;     /* cookie */
-		len = ntohl(*p++);  /* filename length */
+		p += 2;			/* cookie */
+		len = ntohl(*p++);	/* filename length */
 		if (len > NFS4_MAXNAMLEN) {
 			printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len);
 			goto err_unmap;
 		}
-			
 		p += XDR_QUADLEN(len);
 		if (p + 1 > end)
 			goto short_pkt;
-		len = ntohl(*p++);  /* bitmap length */
-		if (len > 10) {
-			printk(KERN_WARNING "NFS: giant bitmap in readdir (len 0x%x)\n", len);
-			goto err_unmap;
-		}
-		if (p + len + 1 > end)
-			goto short_pkt;
-		attrlen = 0;
-		for (i = 0; i < len; i++) {
-			word = ntohl(*p++);
-			if (!word)
-				continue;
-			else if (i == 0 && word == FATTR4_WORD0_FILEID) {
-				attrlen = 8;
-				continue;
-			}
-			printk(KERN_WARNING "NFS: unexpected bitmap word in readdir (0x%x)\n", word);
-			goto err_unmap;
-		}
-		if (ntohl(*p++) != attrlen) {
-			printk(KERN_WARNING "NFS: unexpected attrlen in readdir\n");
-			goto err_unmap;
-		}
-		p += XDR_QUADLEN(attrlen);
+		len = ntohl(*p++);	/* bitmap length */
+		p += len;
 		if (p + 1 > end)
 			goto short_pkt;
+		attrlen = XDR_QUADLEN(ntohl(*p++));
+		p += attrlen;		/* attributes */
+		if (p + 2 > end)
+			goto short_pkt;
+		entry = p;
 	}
 	if (!nr && (entry[0] != 0 || entry[1] == 0))
 		goto short_pkt;
@@ -2898,21 +3053,30 @@ static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
 {
 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
 	struct kvec *iov = rcvbuf->head;
-	uint32_t *strlen;
-	unsigned int hdrlen, len;
-	char *string;
+	int hdrlen, len, recvd;
+	uint32_t *p;
+	char *kaddr;
 	int status;
 
 	status = decode_op_hdr(xdr, OP_READLINK);
 	if (status)
 		return status;
 
+	/* Convert length of symlink */
+	READ_BUF(4);
+	READ32(len);
+	if (len >= rcvbuf->page_len || len <= 0) {
+		dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
+		return -ENAMETOOLONG;
+	}
 	hdrlen = (char *) xdr->p - (char *) iov->iov_base;
-	if (iov->iov_len > hdrlen) {
-		dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
-		xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
-
+	recvd = req->rq_rcv_buf.len - hdrlen;
+	if (recvd < len) {
+		printk(KERN_WARNING "NFS: server cheating in readlink reply: "
+				"count %u > recvd %u\n", len, recvd);
+		return -EIO;
 	}
+	xdr_read_pages(xdr, len);
 	/*
 	 * The XDR encode routine has set things up so that
 	 * the link text will be copied directly into the
@@ -2920,18 +3084,9 @@ static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
 	 * and and null-terminate the text (the VFS expects
 	 * null-termination).
 	 */
-	strlen = (uint32_t *) kmap_atomic(rcvbuf->pages[0], KM_USER0);
-	len = ntohl(*strlen);
-	if (len > rcvbuf->page_len) {
-		dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
-		kunmap_atomic(strlen, KM_USER0);
-		return -ENAMETOOLONG;
-	}
-	*strlen = len;
-
-	string = (char *)(strlen + 1);
-	string[len] = '\0';
-	kunmap_atomic(strlen, KM_USER0);
+	kaddr = (char *)kmap_atomic(rcvbuf->pages[0], KM_USER0);
+	kaddr[len+rcvbuf->page_base] = '\0';
+	kunmap_atomic(kaddr, KM_USER0);
 	return 0;
 }
 
@@ -3048,6 +3203,11 @@ static int decode_write(struct xdr_stream *xdr, struct nfs_writeres *res)
 	return 0;
 }
 
+static int decode_delegreturn(struct xdr_stream *xdr)
+{
+	return decode_op_hdr(xdr, OP_DELEGRETURN);
+}
+
 /*
  * Decode OPEN_DOWNGRADE response
  */
@@ -3214,13 +3374,23 @@ static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_
 		goto out;
 	if ((status = decode_create(&xdr,&res->dir_cinfo)) != 0)
 		goto out;
-	if ((status = decode_getfattr(&xdr, res->fattr, res->server)) != 0)
+	if ((status = decode_getfh(&xdr, res->fh)) != 0)
 		goto out;
-	status = decode_getfh(&xdr, res->fh);
+	status = decode_getfattr(&xdr, res->fattr, res->server);
+	if (status == NFS4ERR_DELAY)
+		status = 0;
 out:
 	return status;
 }
 
+/*
+ * Decode SYMLINK response
+ */
+static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_create_res *res)
+{
+	return nfs4_xdr_dec_create(rqstp, p, res);
+}
+
 /*
  * Decode GETATTR response
  */
@@ -3282,12 +3452,14 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_ope
         if (status)
                 goto out;
         status = decode_open(&xdr, res);
-        if (status)
-                goto out;
-	status = decode_getfattr(&xdr, res->f_attr, res->server);
         if (status)
                 goto out;
 	status = decode_getfh(&xdr, &res->fh);
+        if (status)
+		goto out;
+	status = decode_getfattr(&xdr, res->f_attr, res->server);
+	if (status == NFS4ERR_DELAY)
+		status = 0;
 out:
         return status;
 }
@@ -3314,9 +3486,9 @@ out:
 }
 
 /*
- * Decode OPEN_RECLAIM response
+ * Decode OPEN response
  */
-static int nfs4_xdr_dec_open_reclaim(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_openres *res)
+static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_openres *res)
 {
         struct xdr_stream xdr;
         struct compound_hdr hdr;
@@ -3330,9 +3502,6 @@ static int nfs4_xdr_dec_open_reclaim(struct rpc_rqst *rqstp, uint32_t *p, struct
         if (status)
                 goto out;
         status = decode_open(&xdr, res);
-        if (status)
-                goto out;
-	status = decode_getfattr(&xdr, res->f_attr, res->server);
 out:
         return status;
 }
@@ -3357,6 +3526,8 @@ static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_
         if (status)
                 goto out;
 	status = decode_getfattr(&xdr, res->fattr, res->server);
+	if (status == NFS4ERR_DELAY)
+		status = 0;
 out:
         return status;
 }
@@ -3665,8 +3836,28 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, s
 	return status;
 }
 
+/*
+ * DELEGRETURN request
+ */
+static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, uint32_t *p, void *dummy)
+{
+	struct xdr_stream xdr;
+	struct compound_hdr hdr;
+	int status;
+
+	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+	status = decode_compound_hdr(&xdr, &hdr);
+	if (status == 0) {
+		status = decode_putfh(&xdr);
+		if (status == 0)
+			status = decode_delegreturn(&xdr);
+	}
+	return status;
+}
+
 uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus)
 {
+	uint32_t bitmap[1] = {0};
 	uint32_t len;
 
 	if (!*p++) {
@@ -3689,11 +3880,17 @@ uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus)
 	 */
 	entry->ino = 1;
 
-	len = ntohl(*p++);             /* bitmap length */
-	p += len;
-	len = ntohl(*p++);             /* attribute buffer length */
-	if (len)
-		p = xdr_decode_hyper(p, &entry->ino);
+	len = ntohl(*p++);		/* bitmap length */
+	if (len > 0) {
+		bitmap[0] = ntohl(*p);
+		p += len;
+	}
+	len = XDR_QUADLEN(ntohl(*p++));	/* attribute buffer length */
+	if (len > 0) {
+		if (bitmap[0] == FATTR4_WORD0_FILEID)
+			xdr_decode_hyper(p, &entry->ino);
+		p += len;
+	}
 
 	entry->eof = !p[0] && p[1];
 	return p;
@@ -3756,7 +3953,7 @@ nfs_stat_to_errno(int stat)
 		if (nfs_errtbl[i].stat == stat)
 			return nfs_errtbl[i].errno;
 	}
-	if (stat < 0) {
+	if (stat <= 10000 || stat > 10100) {
 		/* The server is looney tunes. */
 		return ESERVERFAULT;
 	}
@@ -3786,7 +3983,7 @@ struct rpc_procinfo	nfs4_procedures[] = {
   PROC(COMMIT,		enc_commit,	dec_commit),
   PROC(OPEN,		enc_open,	dec_open),
   PROC(OPEN_CONFIRM,	enc_open_confirm,	dec_open_confirm),
-  PROC(OPEN_RECLAIM,	enc_open_reclaim,	dec_open_reclaim),
+  PROC(OPEN_NOATTR,	enc_open_noattr,	dec_open_noattr),
   PROC(OPEN_DOWNGRADE,	enc_open_downgrade,	dec_open_downgrade),
   PROC(CLOSE,		enc_close,	dec_close),
   PROC(SETATTR,		enc_setattr,	dec_setattr),
@@ -3804,12 +4001,14 @@ struct rpc_procinfo	nfs4_procedures[] = {
   PROC(REMOVE,		enc_remove,	dec_remove),
   PROC(RENAME,		enc_rename,	dec_rename),
   PROC(LINK,		enc_link,	dec_link),
+  PROC(SYMLINK,		enc_symlink,	dec_symlink),
   PROC(CREATE,		enc_create,	dec_create),
   PROC(PATHCONF,	enc_pathconf,	dec_pathconf),
   PROC(STATFS,		enc_statfs,	dec_statfs),
   PROC(READLINK,	enc_readlink,	dec_readlink),
   PROC(READDIR,		enc_readdir,	dec_readdir),
   PROC(SERVER_CAPS,	enc_server_caps, dec_server_caps),
+  PROC(DELEGRETURN,	enc_delegreturn, dec_delegreturn),
 };
 
 struct rpc_version		nfs_version4 = {
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index c82fc8528..4f1ba7238 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -21,11 +21,6 @@
 
 #define NFS_PARANOIA 1
 
-/*
- * Spinlock
- */
-spinlock_t nfs_wreq_lock = SPIN_LOCK_UNLOCKED;
-
 static kmem_cache_t *nfs_page_cachep;
 
 static inline struct nfs_page *
@@ -36,7 +31,6 @@ nfs_page_alloc(void)
 	if (p) {
 		memset(p, 0, sizeof(*p));
 		INIT_LIST_HEAD(&p->wb_list);
-		init_waitqueue_head(&p->wb_wait);
 	}
 	return p;
 }
@@ -62,7 +56,7 @@ nfs_page_free(struct nfs_page *p)
  * User should ensure it is safe to sleep in this function.
  */
 struct nfs_page *
-nfs_create_request(struct file *file, struct inode *inode,
+nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
 		   struct page *page,
 		   unsigned int offset, unsigned int count)
 {
@@ -94,33 +88,38 @@ nfs_create_request(struct file *file, struct inode *inode,
 	req->wb_offset  = offset;
 	req->wb_pgbase	= offset;
 	req->wb_bytes   = count;
-	req->wb_inode   = inode;
-	req->wb_count   = 1;
-	server->rpc_ops->request_init(req, file);
+	atomic_set(&req->wb_count, 1);
+	req->wb_context = get_nfs_open_context(ctx);
 
 	return req;
 }
 
+/**
+ * nfs_unlock_request - Unlock request and wake up sleepers.
+ * @req:
+ */
+void nfs_unlock_request(struct nfs_page *req)
+{
+	if (!NFS_WBACK_BUSY(req)) {
+		printk(KERN_ERR "NFS: Invalid unlock attempted\n");
+		BUG();
+	}
+	smp_mb__before_clear_bit();
+	clear_bit(PG_BUSY, &req->wb_flags);
+	smp_mb__after_clear_bit();
+	wake_up_all(&req->wb_context->waitq);
+	nfs_release_request(req);
+}
+
 /**
  * nfs_clear_request - Free up all resources allocated to the request
  * @req:
  *
- * Release all resources associated with a write request after it
+ * Release page resources associated with a write request after it
  * has completed.
  */
 void nfs_clear_request(struct nfs_page *req)
 {
-	if (req->wb_state)
-		req->wb_state = NULL;
-	/* Release struct file or cached credential */
-	if (req->wb_file) {
-		fput(req->wb_file);
-		req->wb_file = NULL;
-	}
-	if (req->wb_cred) {
-		put_rpccred(req->wb_cred);
-		req->wb_cred = NULL;
-	}
 	if (req->wb_page) {
 		page_cache_release(req->wb_page);
 		req->wb_page = NULL;
@@ -137,12 +136,8 @@ void nfs_clear_request(struct nfs_page *req)
 void
 nfs_release_request(struct nfs_page *req)
 {
-	spin_lock(&nfs_wreq_lock);
-	if (--req->wb_count) {
-		spin_unlock(&nfs_wreq_lock);
+	if (!atomic_dec_and_test(&req->wb_count))
 		return;
-	}
-	spin_unlock(&nfs_wreq_lock);
 
 #ifdef NFS_PARANOIA
 	BUG_ON (!list_empty(&req->wb_list));
@@ -151,6 +146,7 @@ nfs_release_request(struct nfs_page *req)
 
 	/* Release struct file or cached credential */
 	nfs_clear_request(req);
+	put_nfs_open_context(req->wb_context);
 	nfs_page_free(req);
 }
 
@@ -194,12 +190,12 @@ nfs_list_add_request(struct nfs_page *req, struct list_head *head)
 int
 nfs_wait_on_request(struct nfs_page *req)
 {
-	struct inode	*inode = req->wb_inode;
+	struct inode	*inode = req->wb_context->dentry->d_inode;
         struct rpc_clnt	*clnt = NFS_CLIENT(inode);
 
 	if (!NFS_WBACK_BUSY(req))
 		return 0;
-	return nfs_wait_event(clnt, req->wb_wait, !NFS_WBACK_BUSY(req));
+	return nfs_wait_event(clnt, req->wb_context->waitq, !NFS_WBACK_BUSY(req));
 }
 
 /**
@@ -224,7 +220,11 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst,
 
 		req = nfs_list_entry(head->next);
 		if (prev) {
-			if (req->wb_cred != prev->wb_cred)
+			if (req->wb_context->cred != prev->wb_context->cred)
+				break;
+			if (req->wb_context->lockowner != prev->wb_context->lockowner)
+				break;
+			if (req->wb_context->state != prev->wb_context->state)
 				break;
 			if (req->wb_index != (prev->wb_index + 1))
 				break;
@@ -254,7 +254,7 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst,
  * If the number of requests is set to 0, the entire address_space
  * starting at index idx_start, is scanned.
  * The requests are *not* checked to ensure that they form a contiguous set.
- * You must be holding the nfs_wreq_lock when calling this function
+ * You must be holding the inode's req_lock when calling this function
  */
 int
 nfs_scan_list(struct list_head *head, struct list_head *dst,
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 8dc6a981c..ae9500199 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -49,18 +49,6 @@
 
 extern struct rpc_procinfo nfs_procedures[];
 
-static struct rpc_cred *
-nfs_cred(struct inode *inode, struct file *filp)
-{
-	struct rpc_cred *cred = NULL;
-
-	if (filp)
-		cred = (struct rpc_cred *)filp->private_data;
-	if (!cred)
-		cred = NFS_I(inode)->mm_cred;
-	return cred;
-}
-
 /*
  * Bare-bones access to getattr: this is for nfs_read_super.
  */
@@ -99,14 +87,15 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
  * One function for each procedure in the NFS protocol.
  */
 static int
-nfs_proc_getattr(struct inode *inode, struct nfs_fattr *fattr)
+nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
+		struct nfs_fattr *fattr)
 {
 	int	status;
 
 	dprintk("NFS call  getattr\n");
 	fattr->valid = 0;
-	status = rpc_call(NFS_CLIENT(inode), NFSPROC_GETATTR,
-				NFS_FH(inode), fattr, 0);
+	status = rpc_call(server->client, NFSPROC_GETATTR,
+				fhandle, fattr, 0);
 	dprintk("NFS reply getattr\n");
 	return status;
 }
@@ -151,12 +140,13 @@ nfs_proc_lookup(struct inode *dir, struct qstr *name,
 	return status;
 }
 
-static int
-nfs_proc_readlink(struct inode *inode, struct page *page)
+static int nfs_proc_readlink(struct inode *inode, struct page *page,
+		unsigned int pgbase, unsigned int pglen)
 {
 	struct nfs_readlinkargs	args = {
 		.fh		= NFS_FH(inode),
-		.count		= PAGE_CACHE_SIZE,
+		.pgbase		= pgbase,
+		.pglen		= pglen,
 		.pages		= &page
 	};
 	int			status;
@@ -167,8 +157,7 @@ nfs_proc_readlink(struct inode *inode, struct page *page)
 	return status;
 }
 
-static int
-nfs_proc_read(struct nfs_read_data *rdata, struct file *filp)
+static int nfs_proc_read(struct nfs_read_data *rdata)
 {
 	int			flags = rdata->flags;
 	struct inode *		inode = rdata->inode;
@@ -177,15 +166,14 @@ nfs_proc_read(struct nfs_read_data *rdata, struct file *filp)
 		.rpc_proc	= &nfs_procedures[NFSPROC_READ],
 		.rpc_argp	= &rdata->args,
 		.rpc_resp	= &rdata->res,
+		.rpc_cred	= rdata->cred,
 	};
 	int			status;
 
 	dprintk("NFS call  read %d @ %Ld\n", rdata->args.count,
 			(long long) rdata->args.offset);
 	fattr->valid = 0;
-	msg.rpc_cred = nfs_cred(inode, filp);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
-
 	if (status >= 0) {
 		nfs_refresh_inode(inode, fattr);
 		/* Emulate the eof flag, which isn't normally needed in NFSv2
@@ -198,8 +186,7 @@ nfs_proc_read(struct nfs_read_data *rdata, struct file *filp)
 	return status;
 }
 
-static int
-nfs_proc_write(struct nfs_write_data *wdata, struct file *filp)
+static int nfs_proc_write(struct nfs_write_data *wdata)
 {
 	int			flags = wdata->flags;
 	struct inode *		inode = wdata->inode;
@@ -208,13 +195,13 @@ nfs_proc_write(struct nfs_write_data *wdata, struct file *filp)
 		.rpc_proc	= &nfs_procedures[NFSPROC_WRITE],
 		.rpc_argp	= &wdata->args,
 		.rpc_resp	= &wdata->res,
+		.rpc_cred	= wdata->cred,
 	};
 	int			status;
 
 	dprintk("NFS call  write %d @ %Ld\n", wdata->args.count,
 			(long long) wdata->args.offset);
 	fattr->valid = 0;
-	msg.rpc_cred = nfs_cred(inode, filp);
 	status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
 	if (status >= 0) {
 		nfs_refresh_inode(inode, fattr);
@@ -400,8 +387,11 @@ nfs_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
 	};
 	int			status;
 
+	if (path->len > NFS2_MAXPATHLEN)
+		return -ENAMETOOLONG;
 	dprintk("NFS call  symlink %s -> %s\n", name->name, path->name);
 	fattr->valid = 0;
+	fhandle->size = 0;
 	status = rpc_call(NFS_CLIENT(dir), NFSPROC_SYMLINK, &arg, NULL, 0);
 	dprintk("NFS reply symlink: %d\n", status);
 	return status;
@@ -619,27 +609,6 @@ nfs_proc_commit_setup(struct nfs_write_data *data, int how)
 	BUG();
 }
 
-/*
- * Set up the nfspage struct with the right credentials
- */
-static void
-nfs_request_init(struct nfs_page *req, struct file *filp)
-{
-	req->wb_cred = get_rpccred(nfs_cred(req->wb_inode, filp));
-}
-
-static int
-nfs_request_compatible(struct nfs_page *req, struct file *filp, struct page *page)
-{
-	if (req->wb_file != filp)
-		return 0;
-	if (req->wb_page != page)
-		return 0;
-	if (req->wb_cred != nfs_file_cred(filp))
-		return 0;
-	return 1;
-}
-
 static int
 nfs_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
 {
@@ -680,7 +649,5 @@ struct nfs_rpc_ops	nfs_v2_clientops = {
 	.commit_setup	= nfs_proc_commit_setup,
 	.file_open	= nfs_open,
 	.file_release	= nfs_release,
-	.request_init	= nfs_request_init,
-	.request_compatible = nfs_request_compatible,
 	.lock		= nfs_proc_lock,
 };
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 2d32aba43..0de2e2d12 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -91,8 +91,8 @@ int nfs_return_empty_page(struct page *page)
 /*
  * Read a page synchronously.
  */
-static int
-nfs_readpage_sync(struct file *file, struct inode *inode, struct page *page)
+static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode,
+		struct page *page)
 {
 	unsigned int	rsize = NFS_SERVER(inode)->rsize;
 	unsigned int	count = PAGE_CACHE_SIZE;
@@ -105,10 +105,11 @@ nfs_readpage_sync(struct file *file, struct inode *inode, struct page *page)
 
 	memset(rdata, 0, sizeof(*rdata));
 	rdata->flags = (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
+	rdata->cred = ctx->cred;
 	rdata->inode = inode;
 	INIT_LIST_HEAD(&rdata->pages);
 	rdata->args.fh = NFS_FH(inode);
-	rdata->args.lockowner = current->files;
+	rdata->args.context = ctx;
 	rdata->args.pages = &page;
 	rdata->args.pgbase = 0UL;
 	rdata->args.count = rsize;
@@ -134,7 +135,7 @@ nfs_readpage_sync(struct file *file, struct inode *inode, struct page *page)
 			rdata->args.count);
 
 		lock_kernel();
-		result = NFS_PROTO(inode)->read(rdata, file);
+		result = NFS_PROTO(inode)->read(rdata);
 		unlock_kernel();
 
 		/*
@@ -169,8 +170,8 @@ io_error:
 	return result;
 }
 
-static int
-nfs_readpage_async(struct file *file, struct inode *inode, struct page *page)
+static int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
+		struct page *page)
 {
 	LIST_HEAD(one_request);
 	struct nfs_page	*new;
@@ -179,7 +180,7 @@ nfs_readpage_async(struct file *file, struct inode *inode, struct page *page)
 	len = nfs_page_length(inode, page);
 	if (len == 0)
 		return nfs_return_empty_page(page);
-	new = nfs_create_request(file, inode, page, 0, len);
+	new = nfs_create_request(ctx, inode, page, 0, len);
 	if (IS_ERR(new)) {
 		unlock_page(page);
 		return PTR_ERR(new);
@@ -202,8 +203,8 @@ static void nfs_readpage_release(struct nfs_page *req)
 	nfs_unlock_request(req);
 
 	dprintk("NFS: read done (%s/%Ld %d@%Ld)\n",
-			req->wb_inode->i_sb->s_id,
-			(long long)NFS_FILEID(req->wb_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));
 }
@@ -217,16 +218,15 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
 	struct inode		*inode;
 
 	data->req	  = req;
-	data->inode	  = inode = req->wb_inode;
-	data->cred	  = req->wb_cred;
+	data->inode	  = inode = req->wb_context->dentry->d_inode;
+	data->cred	  = req->wb_context->cred;
 
 	data->args.fh     = NFS_FH(inode);
 	data->args.offset = req_offset(req) + offset;
 	data->args.pgbase = req->wb_pgbase + offset;
 	data->args.pages  = data->pagevec;
 	data->args.count  = count;
-	data->args.lockowner = req->wb_lockowner;
-	data->args.state  = req->wb_state;
+	data->args.context = req->wb_context;
 
 	data->res.fattr   = &data->fattr;
 	data->res.count   = count;
@@ -396,7 +396,7 @@ nfs_pagein_list(struct list_head *head, int rpages)
 	while (!list_empty(head)) {
 		pages += nfs_coalesce_requests(head, &one_request, rpages);
 		req = nfs_list_entry(one_request.next);
-		error = nfs_pagein_one(&one_request, req->wb_inode);
+		error = nfs_pagein_one(&one_request, req->wb_context->dentry->d_inode);
 		if (error < 0)
 			break;
 	}
@@ -500,9 +500,9 @@ void nfs_readpage_result(struct rpc_task *task)
  *  -	The error flag is set for this page. This happens only when a
  *	previous async read operation failed.
  */
-int
-nfs_readpage(struct file *file, struct page *page)
+int nfs_readpage(struct file *file, struct page *page)
 {
+	struct nfs_open_context *ctx;
 	struct inode *inode = page->mapping->host;
 	int		error;
 
@@ -519,25 +519,33 @@ nfs_readpage(struct file *file, struct page *page)
 	if (error)
 		goto out_error;
 
+	if (file == NULL) {
+		ctx = nfs_find_open_context(inode, FMODE_READ);
+		if (ctx == NULL)
+			return -EBADF;
+	} else
+		ctx = get_nfs_open_context((struct nfs_open_context *)
+				file->private_data);
 	if (!IS_SYNC(inode)) {
-		error = nfs_readpage_async(file, inode, page);
+		error = nfs_readpage_async(ctx, inode, page);
 		goto out;
 	}
 
-	error = nfs_readpage_sync(file, inode, page);
+	error = nfs_readpage_sync(ctx, inode, page);
 	if (error < 0 && IS_SWAPFILE(inode))
 		printk("Aiee.. nfs swap-in of page failed!\n");
 out:
+	put_nfs_open_context(ctx);
 	return error;
 
 out_error:
 	unlock_page(page);
-	goto out;
+	return error;
 }
 
 struct nfs_readdesc {
 	struct list_head *head;
-	struct file *filp;
+	struct nfs_open_context *ctx;
 };
 
 static int
@@ -552,7 +560,7 @@ readpage_async_filler(void *data, struct page *page)
 	len = nfs_page_length(inode, page);
 	if (len == 0)
 		return nfs_return_empty_page(page);
-	new = nfs_create_request(desc->filp, inode, page, 0, len);
+	new = nfs_create_request(desc->ctx, inode, page, 0, len);
 	if (IS_ERR(new)) {
 			SetPageError(page);
 			unlock_page(page);
@@ -565,13 +573,11 @@ readpage_async_filler(void *data, struct page *page)
 	return 0;
 }
 
-int
-nfs_readpages(struct file *filp, struct address_space *mapping,
+int nfs_readpages(struct file *filp, struct address_space *mapping,
 		struct list_head *pages, unsigned nr_pages)
 {
 	LIST_HEAD(head);
 	struct nfs_readdesc desc = {
-		.filp		= filp,
 		.head		= &head,
 	};
 	struct inode *inode = mapping->host;
@@ -583,12 +589,20 @@ nfs_readpages(struct file *filp, struct address_space *mapping,
 			(long long)NFS_FILEID(inode),
 			nr_pages);
 
+	if (filp == NULL) {
+		desc.ctx = nfs_find_open_context(inode, FMODE_READ);
+		if (desc.ctx == NULL)
+			return -EBADF;
+	} else
+		desc.ctx = get_nfs_open_context((struct nfs_open_context *)
+				filp->private_data);
 	ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc);
 	if (!list_empty(&head)) {
 		int err = nfs_pagein_list(&head, server->rpages);
 		if (!ret)
 			ret = err;
 	}
+	put_nfs_open_context(desc.ctx);
 	return ret;
 }
 
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
index fabadfbfd..35f106599 100644
--- a/fs/nfs/symlink.c
+++ b/fs/nfs/symlink.c
@@ -23,20 +23,30 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/smp_lock.h>
+#include <linux/namei.h>
 
 /* Symlink caching in the page cache is even more simplistic
  * and straight-forward than readdir caching.
+ *
+ * At the beginning of the page we store pointer to struct page in question,
+ * simplifying nfs_put_link() (if inode got invalidated we can't find the page
+ * to be freed via pagecache lookup).
+ * The NUL-terminated string follows immediately thereafter.
  */
+
+struct nfs_symlink {
+	struct page *page;
+	char body[0];
+};
+
 static int nfs_symlink_filler(struct inode *inode, struct page *page)
 {
+	const unsigned int pgbase = offsetof(struct nfs_symlink, body);
+	const unsigned int pglen = PAGE_SIZE - pgbase;
 	int error;
 
-	/* We place the length at the beginning of the page,
-	 * in host byte order, followed by the string.  The
-	 * XDR response verification will NULL terminate it.
-	 */
 	lock_kernel();
-	error = NFS_PROTO(inode)->readlink(inode, page);
+	error = NFS_PROTO(inode)->readlink(inode, page, pgbase, pglen);
 	unlock_kernel();
 	if (error < 0)
 		goto error;
@@ -50,61 +60,58 @@ error:
 	return -EIO;
 }
 
-static char *nfs_getlink(struct inode *inode, struct page **ppage)
+static int nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
+	struct inode *inode = dentry->d_inode;
 	struct page *page;
-	u32 *p;
-
-	page = ERR_PTR(nfs_revalidate_inode(NFS_SERVER(inode), inode));
-	if (page)
+	struct nfs_symlink *p;
+	void *err = ERR_PTR(nfs_revalidate_inode(NFS_SERVER(inode), inode));
+	if (err)
 		goto read_failed;
 	page = read_cache_page(&inode->i_data, 0,
 				(filler_t *)nfs_symlink_filler, inode);
-	if (IS_ERR(page))
+	if (IS_ERR(page)) {
+		err = page;
 		goto read_failed;
-	if (!PageUptodate(page))
+	}
+	if (!PageUptodate(page)) {
+		err = ERR_PTR(-EIO);
 		goto getlink_read_error;
-	*ppage = page;
+	}
 	p = kmap(page);
-	return (char*)(p+1);
+	p->page = page;
+	nd_set_link(nd, p->body);
+	return 0;
 
 getlink_read_error:
 	page_cache_release(page);
-	page = ERR_PTR(-EIO);
 read_failed:
-	return (char*)page;
+	nd_set_link(nd, err);
+	return 0;
 }
 
-static int nfs_readlink(struct dentry *dentry, char __user *buffer, int buflen)
+static void nfs_put_link(struct dentry *dentry, struct nameidata *nd)
 {
-	struct inode *inode = dentry->d_inode;
-	struct page *page = NULL;
-	int res = vfs_readlink(dentry,buffer,buflen,nfs_getlink(inode,&page));
-	if (page) {
-		kunmap(page);
-		page_cache_release(page);
-	}
-	return res;
-}
+	char *s = nd_get_link(nd);
+	if (!IS_ERR(s)) {
+		struct nfs_symlink *p;
+		struct page *page;
+
+		p = container_of(s, struct nfs_symlink, body[0]);
+		page = p->page;
 
-static int nfs_follow_link(struct dentry *dentry, struct nameidata *nd)
-{
-	struct inode *inode = dentry->d_inode;
-	struct page *page = NULL;
-	int res = vfs_follow_link(nd, nfs_getlink(inode,&page));
-	if (page) {
 		kunmap(page);
 		page_cache_release(page);
 	}
-	return res;
 }
 
 /*
  * symlinks can't do much...
  */
 struct inode_operations nfs_symlink_inode_operations = {
-	.readlink	= nfs_readlink,
+	.readlink	= generic_readlink,
 	.follow_link	= nfs_follow_link,
+	.put_link	= nfs_put_link,
 	.getattr	= nfs_getattr,
 	.setattr	= nfs_setattr,
 };
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index a01a2fa0a..847b77d4c 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -63,6 +63,8 @@
 #include <linux/smp_lock.h>
 #include <linux/mempool.h>
 
+#include "delegation.h"
+
 #define NFSDBG_FACILITY		NFSDBG_PAGECACHE
 
 #define MIN_POOL_WRITE		(32)
@@ -71,7 +73,8 @@
 /*
  * Local function declarations
  */
-static struct nfs_page * nfs_update_request(struct file*, struct inode *,
+static struct nfs_page * nfs_update_request(struct nfs_open_context*,
+					    struct inode *,
 					    struct page *,
 					    unsigned int, unsigned int);
 static void nfs_writeback_done_partial(struct nfs_write_data *, int);
@@ -173,7 +176,7 @@ static void nfs_mark_uptodate(struct page *page, unsigned int base, unsigned int
  * Write a page synchronously.
  * Offset is the data offset within the page.
  */
-static int nfs_writepage_sync(struct file *file, struct inode *inode,
+static int nfs_writepage_sync(struct nfs_open_context *ctx, struct inode *inode,
 		struct page *page, unsigned int offset, unsigned int count,
 		int how)
 {
@@ -187,9 +190,10 @@ static int nfs_writepage_sync(struct file *file, struct inode *inode,
 
 	memset(wdata, 0, sizeof(*wdata));
 	wdata->flags = how;
+	wdata->cred = ctx->cred;
 	wdata->inode = inode;
 	wdata->args.fh = NFS_FH(inode);
-	wdata->args.lockowner = current->files;
+	wdata->args.context = ctx;
 	wdata->args.pages = &page;
 	wdata->args.stable = NFS_FILE_SYNC;
 	wdata->args.pgbase = offset;
@@ -208,7 +212,7 @@ static int nfs_writepage_sync(struct file *file, struct inode *inode,
 			wdata->args.count = count;
 		wdata->args.offset = page_offset(page) + wdata->args.pgbase;
 
-		result = NFS_PROTO(inode)->write(wdata, file);
+		result = NFS_PROTO(inode)->write(wdata);
 
 		if (result < 0) {
 			/* Must mark the page invalid after I/O error */
@@ -234,20 +238,19 @@ static int nfs_writepage_sync(struct file *file, struct inode *inode,
 
 io_error:
 	nfs_end_data_update_defer(inode);
-	if (wdata->cred)
-		put_rpccred(wdata->cred);
 
 	kfree(wdata);
 	return written ? written : result;
 }
 
-static int nfs_writepage_async(struct file *file, struct inode *inode,
-		struct page *page, unsigned int offset, unsigned int count)
+static int nfs_writepage_async(struct nfs_open_context *ctx,
+		struct inode *inode, struct page *page,
+		unsigned int offset, unsigned int count)
 {
 	struct nfs_page	*req;
 	int		status;
 
-	req = nfs_update_request(file, inode, page, offset, count);
+	req = nfs_update_request(ctx, inode, page, offset, count);
 	status = (IS_ERR(req)) ? PTR_ERR(req) : 0;
 	if (status < 0)
 		goto out;
@@ -274,6 +277,7 @@ static int wb_priority(struct writeback_control *wbc)
  */
 int nfs_writepage(struct page *page, struct writeback_control *wbc)
 {
+	struct nfs_open_context *ctx;
 	struct inode *inode = page->mapping->host;
 	unsigned long end_index;
 	unsigned offset = PAGE_CACHE_SIZE;
@@ -308,16 +312,21 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc)
 	if (page->index >= end_index+1 || !offset)
 		goto out;
 do_it:
+	ctx = nfs_find_open_context(inode, FMODE_WRITE);
+	if (ctx == NULL) {
+		err = -EBADF;
+		goto out;
+	}
 	lock_kernel();
 	if (!IS_SYNC(inode) && inode_referenced) {
-		err = nfs_writepage_async(NULL, inode, page, 0, offset);
+		err = nfs_writepage_async(ctx, inode, page, 0, offset);
 		if (err >= 0) {
 			err = 0;
 			if (wbc->for_reclaim)
 				nfs_flush_inode(inode, 0, 0, FLUSH_STABLE);
 		}
 	} else {
-		err = nfs_writepage_sync(NULL, inode, page, 0,
+		err = nfs_writepage_sync(ctx, inode, page, 0,
 						offset, priority);
 		if (err >= 0) {
 			if (err != offset)
@@ -326,6 +335,7 @@ do_it:
 		}
 	}
 	unlock_kernel();
+	put_nfs_open_context(ctx);
 out:
 	unlock_page(page);
 	if (inode_referenced)
@@ -374,8 +384,7 @@ out:
 /*
  * Insert a write request into an inode
  */
-static inline int
-nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
+static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 	int error;
@@ -387,33 +396,33 @@ nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
 	if (!nfsi->npages) {
 		igrab(inode);
 		nfs_begin_data_update(inode);
+		if (nfs_have_delegation(inode, FMODE_WRITE))
+			nfsi->change_attr++;
 	}
 	nfsi->npages++;
-	req->wb_count++;
+	atomic_inc(&req->wb_count);
 	return 0;
 }
 
 /*
  * Insert a write request into an inode
  */
-static void
-nfs_inode_remove_request(struct nfs_page *req)
+static void nfs_inode_remove_request(struct nfs_page *req)
 {
-	struct nfs_inode *nfsi;
-	struct inode *inode;
+	struct inode *inode = req->wb_context->dentry->d_inode;
+	struct nfs_inode *nfsi = NFS_I(inode);
 
 	BUG_ON (!NFS_WBACK_BUSY(req));
-	spin_lock(&nfs_wreq_lock);
-	inode = req->wb_inode;
-	nfsi = NFS_I(inode);
+
+	spin_lock(&nfsi->req_lock);
 	radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index);
 	nfsi->npages--;
 	if (!nfsi->npages) {
-		spin_unlock(&nfs_wreq_lock);
+		spin_unlock(&nfsi->req_lock);
 		nfs_end_data_update_defer(inode);
 		iput(inode);
 	} else
-		spin_unlock(&nfs_wreq_lock);
+		spin_unlock(&nfsi->req_lock);
 	nfs_clear_request(req);
 	nfs_release_request(req);
 }
@@ -429,7 +438,7 @@ _nfs_find_request(struct inode *inode, unsigned long index)
 
 	req = (struct nfs_page*)radix_tree_lookup(&nfsi->nfs_page_tree, index);
 	if (req)
-		req->wb_count++;
+		atomic_inc(&req->wb_count);
 	return req;
 }
 
@@ -437,10 +446,11 @@ static struct nfs_page *
 nfs_find_request(struct inode *inode, unsigned long index)
 {
 	struct nfs_page		*req;
+	struct nfs_inode	*nfsi = NFS_I(inode);
 
-	spin_lock(&nfs_wreq_lock);
+	spin_lock(&nfsi->req_lock);
 	req = _nfs_find_request(inode, index);
-	spin_unlock(&nfs_wreq_lock);
+	spin_unlock(&nfsi->req_lock);
 	return req;
 }
 
@@ -450,13 +460,13 @@ nfs_find_request(struct inode *inode, unsigned long index)
 static void
 nfs_mark_request_dirty(struct nfs_page *req)
 {
-	struct inode *inode = req->wb_inode;
+	struct inode *inode = req->wb_context->dentry->d_inode;
 	struct nfs_inode *nfsi = NFS_I(inode);
 
-	spin_lock(&nfs_wreq_lock);
+	spin_lock(&nfsi->req_lock);
 	nfs_list_add_request(req, &nfsi->dirty);
 	nfsi->ndirty++;
-	spin_unlock(&nfs_wreq_lock);
+	spin_unlock(&nfsi->req_lock);
 	inc_page_state(nr_dirty);
 	mark_inode_dirty(inode);
 }
@@ -467,7 +477,7 @@ nfs_mark_request_dirty(struct nfs_page *req)
 static inline int
 nfs_dirty_request(struct nfs_page *req)
 {
-	struct nfs_inode *nfsi = NFS_I(req->wb_inode);
+	struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode);
 	return !list_empty(&req->wb_list) && req->wb_list_head == &nfsi->dirty;
 }
 
@@ -478,13 +488,13 @@ nfs_dirty_request(struct nfs_page *req)
 static void
 nfs_mark_request_commit(struct nfs_page *req)
 {
-	struct inode *inode = req->wb_inode;
+	struct inode *inode = req->wb_context->dentry->d_inode;
 	struct nfs_inode *nfsi = NFS_I(inode);
 
-	spin_lock(&nfs_wreq_lock);
+	spin_lock(&nfsi->req_lock);
 	nfs_list_add_request(req, &nfsi->commit);
 	nfsi->ncommit++;
-	spin_unlock(&nfs_wreq_lock);
+	spin_unlock(&nfsi->req_lock);
 	inc_page_state(nr_unstable);
 	mark_inode_dirty(inode);
 }
@@ -509,7 +519,7 @@ nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, unsigned int
 	else
 		idx_end = idx_start + npages - 1;
 
-	spin_lock(&nfs_wreq_lock);
+	spin_lock(&nfsi->req_lock);
 	next = idx_start;
 	while (radix_tree_gang_lookup(&nfsi->nfs_page_tree, (void **)&req, next, 1)) {
 		if (req->wb_index > idx_end)
@@ -519,16 +529,16 @@ nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, unsigned int
 		if (!NFS_WBACK_BUSY(req))
 			continue;
 
-		req->wb_count++;
-		spin_unlock(&nfs_wreq_lock);
+		atomic_inc(&req->wb_count);
+		spin_unlock(&nfsi->req_lock);
 		error = nfs_wait_on_request(req);
 		nfs_release_request(req);
 		if (error < 0)
 			return error;
-		spin_lock(&nfs_wreq_lock);
+		spin_lock(&nfsi->req_lock);
 		res++;
 	}
-	spin_unlock(&nfs_wreq_lock);
+	spin_unlock(&nfsi->req_lock);
 	return res;
 }
 
@@ -619,11 +629,12 @@ static int nfs_wait_on_write_congestion(struct address_space *mapping, int intr)
  *
  * Note: Should always be called with the Page Lock held!
  */
-static struct nfs_page *
-nfs_update_request(struct file* file, struct inode *inode, struct page *page,
-		   unsigned int offset, unsigned int bytes)
+static struct nfs_page * nfs_update_request(struct nfs_open_context* ctx,
+		struct inode *inode, struct page *page,
+		unsigned int offset, unsigned int bytes)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
+	struct nfs_inode *nfsi = NFS_I(inode);
 	struct nfs_page		*req, *new = NULL;
 	unsigned long		rqend, end;
 
@@ -635,19 +646,19 @@ nfs_update_request(struct file* file, struct inode *inode, struct page *page,
 		/* Loop over all inode entries and see if we find
 		 * A request for the page we wish to update
 		 */
-		spin_lock(&nfs_wreq_lock);
+		spin_lock(&nfsi->req_lock);
 		req = _nfs_find_request(inode, page->index);
 		if (req) {
 			if (!nfs_lock_request_dontget(req)) {
 				int error;
-				spin_unlock(&nfs_wreq_lock);
+				spin_unlock(&nfsi->req_lock);
 				error = nfs_wait_on_request(req);
 				nfs_release_request(req);
 				if (error < 0)
 					return ERR_PTR(error);
 				continue;
 			}
-			spin_unlock(&nfs_wreq_lock);
+			spin_unlock(&nfsi->req_lock);
 			if (new)
 				nfs_release_request(new);
 			break;
@@ -658,23 +669,19 @@ nfs_update_request(struct file* file, struct inode *inode, struct page *page,
 			nfs_lock_request_dontget(new);
 			error = nfs_inode_add_request(inode, new);
 			if (error) {
-				spin_unlock(&nfs_wreq_lock);
+				spin_unlock(&nfsi->req_lock);
 				nfs_unlock_request(new);
 				return ERR_PTR(error);
 			}
-			spin_unlock(&nfs_wreq_lock);
+			spin_unlock(&nfsi->req_lock);
 			nfs_mark_request_dirty(new);
 			return new;
 		}
-		spin_unlock(&nfs_wreq_lock);
+		spin_unlock(&nfsi->req_lock);
 
-		new = nfs_create_request(file, inode, page, offset, bytes);
+		new = nfs_create_request(ctx, inode, page, offset, bytes);
 		if (IS_ERR(new))
 			return new;
-		if (file) {
-			new->wb_file = file;
-			get_file(file);
-		}
 	}
 
 	/* We have a request for our page.
@@ -684,7 +691,7 @@ nfs_update_request(struct file* file, struct inode *inode, struct page *page,
 	 * request.
 	 */
 	rqend = req->wb_offset + req->wb_bytes;
-	if (req->wb_file != file
+	if (req->wb_context != ctx
 	    || req->wb_page != page
 	    || !nfs_dirty_request(req)
 	    || offset > rqend || end < req->wb_offset) {
@@ -705,9 +712,9 @@ nfs_update_request(struct file* file, struct inode *inode, struct page *page,
 	return req;
 }
 
-int
-nfs_flush_incompatible(struct file *file, struct page *page)
+int nfs_flush_incompatible(struct file *file, struct page *page)
 {
+	struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
 	struct inode	*inode = page->mapping->host;
 	struct nfs_page	*req;
 	int		status = 0;
@@ -721,7 +728,7 @@ nfs_flush_incompatible(struct file *file, struct page *page)
 	 */
 	req = nfs_find_request(inode, page->index);
 	if (req) {
-		if (!NFS_PROTO(inode)->request_compatible(req, file, page))
+		if (req->wb_page != page || ctx != req->wb_context)
 			status = nfs_wb_page(inode, page);
 		nfs_release_request(req);
 	}
@@ -737,6 +744,7 @@ nfs_flush_incompatible(struct file *file, struct page *page)
 int nfs_updatepage(struct file *file, struct page *page,
 		unsigned int offset, unsigned int count)
 {
+	struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
 	struct dentry	*dentry = file->f_dentry;
 	struct inode	*inode = page->mapping->host;
 	struct nfs_page	*req;
@@ -747,7 +755,7 @@ int nfs_updatepage(struct file *file, struct page *page,
 		count, (long long)(page_offset(page) +offset));
 
 	if (IS_SYNC(inode)) {
-		status = nfs_writepage_sync(file, inode, page, offset, count, 0);
+		status = nfs_writepage_sync(ctx, inode, page, offset, count, 0);
 		if (status > 0) {
 			if (offset == 0 && status == PAGE_CACHE_SIZE)
 				SetPageUptodate(page);
@@ -784,7 +792,7 @@ int nfs_updatepage(struct file *file, struct page *page,
 	 * it out now.
 	 */
 	do {
-		req = nfs_update_request(file, inode, page, offset, count);
+		req = nfs_update_request(ctx, inode, page, offset, count);
 		status = (IS_ERR(req)) ? PTR_ERR(req) : 0;
 		if (status != -EBUSY)
 			break;
@@ -860,16 +868,15 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
 	 * NB: take care not to mess about with data->commit et al. */
 
 	data->req = req;
-	data->inode = inode = req->wb_inode;
-	data->cred = req->wb_cred;
+	data->inode = inode = req->wb_context->dentry->d_inode;
+	data->cred = req->wb_context->cred;
 
 	data->args.fh     = NFS_FH(inode);
 	data->args.offset = req_offset(req) + offset;
 	data->args.pgbase = req->wb_pgbase + offset;
 	data->args.pages  = data->pagevec;
 	data->args.count  = count;
-	data->args.lockowner = req->wb_lockowner;
-	data->args.state  = req->wb_state;
+	data->args.context = req->wb_context;
 
 	data->res.fattr   = &data->fattr;
 	data->res.count   = count;
@@ -1029,7 +1036,7 @@ nfs_flush_list(struct list_head *head, int wpages, int how)
 	while (!list_empty(head)) {
 		pages += nfs_coalesce_requests(head, &one_request, wpages);
 		req = nfs_list_entry(one_request.next);
-		error = nfs_flush_one(&one_request, req->wb_inode, how);
+		error = nfs_flush_one(&one_request, req->wb_context->dentry->d_inode, how);
 		if (error < 0)
 			break;
 	}
@@ -1054,16 +1061,15 @@ static void nfs_writeback_done_partial(struct nfs_write_data *data, int status)
 	struct page		*page = req->wb_page;
 
 	dprintk("NFS: write (%s/%Ld %d@%Ld)",
-		req->wb_inode->i_sb->s_id,
-		(long long)NFS_FILEID(req->wb_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 (status < 0) {
 		ClearPageUptodate(page);
 		SetPageError(page);
-		if (req->wb_file)
-			req->wb_file->f_error = status;
+		req->wb_context->error = status;
 		dprintk(", error = %d\n", status);
 	} else {
 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
@@ -1104,16 +1110,15 @@ static void nfs_writeback_done_full(struct nfs_write_data *data, int status)
 		page = req->wb_page;
 
 		dprintk("NFS: write (%s/%Ld %d@%Ld)",
-			req->wb_inode->i_sb->s_id,
-			(long long)NFS_FILEID(req->wb_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 (status < 0) {
 			ClearPageUptodate(page);
 			SetPageError(page);
-			if (req->wb_file)
-				req->wb_file->f_error = status;
+			req->wb_context->error = status;
 			end_page_writeback(page);
 			nfs_inode_remove_request(req);
 			dprintk(", error = %d\n", status);
@@ -1232,7 +1237,7 @@ static void nfs_commit_rpcsetup(struct list_head *head,
 	list_splice_init(head, &data->pages);
 	first = nfs_list_entry(data->pages.next);
 	last = nfs_list_entry(data->pages.prev);
-	inode = first->wb_inode;
+	inode = first->wb_context->dentry->d_inode;
 
 	/*
 	 * Determine the offset range of requests in the COMMIT call.
@@ -1246,7 +1251,7 @@ static void nfs_commit_rpcsetup(struct list_head *head,
 		len = 0;
 
 	data->inode	  = inode;
-	data->cred	  = first->wb_cred;
+	data->cred	  = first->wb_context->cred;
 
 	data->args.fh     = NFS_FH(data->inode);
 	data->args.offset = start;
@@ -1313,13 +1318,12 @@ nfs_commit_done(struct rpc_task *task)
 		nfs_list_remove_request(req);
 
 		dprintk("NFS: commit (%s/%Ld %d@%Ld)",
-			req->wb_inode->i_sb->s_id,
-			(long long)NFS_FILEID(req->wb_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) {
-			if (req->wb_file)
-				req->wb_file->f_error = task->tk_status;
+			req->wb_context->error = task->tk_status;
 			nfs_inode_remove_request(req);
 			dprintk(", error = %d\n", task->tk_status);
 			goto next;
@@ -1347,13 +1351,14 @@ nfs_commit_done(struct rpc_task *task)
 int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
 		   unsigned int npages, int how)
 {
+	struct nfs_inode *nfsi = NFS_I(inode);
 	LIST_HEAD(head);
 	int			res,
 				error = 0;
 
-	spin_lock(&nfs_wreq_lock);
+	spin_lock(&nfsi->req_lock);
 	res = nfs_scan_dirty(inode, &head, idx_start, npages);
-	spin_unlock(&nfs_wreq_lock);
+	spin_unlock(&nfsi->req_lock);
 	if (res)
 		error = nfs_flush_list(&head, NFS_SERVER(inode)->wpages, how);
 	if (error < 0)
@@ -1365,18 +1370,19 @@ int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
 int nfs_commit_inode(struct inode *inode, unsigned long idx_start,
 		    unsigned int npages, int how)
 {
+	struct nfs_inode *nfsi = NFS_I(inode);
 	LIST_HEAD(head);
 	int			res,
 				error = 0;
 
-	spin_lock(&nfs_wreq_lock);
+	spin_lock(&nfsi->req_lock);
 	res = nfs_scan_commit(inode, &head, idx_start, npages);
 	if (res) {
 		res += nfs_scan_commit(inode, &head, 0, 0);
-		spin_unlock(&nfs_wreq_lock);
+		spin_unlock(&nfsi->req_lock);
 		error = nfs_commit_list(&head, how);
 	} else
-		spin_unlock(&nfs_wreq_lock);
+		spin_unlock(&nfsi->req_lock);
 	if (error < 0)
 		return error;
 	return res;
diff --git a/fs/nfsd/Makefile b/fs/nfsd/Makefile
index 4c47c0003..87d4cc2cf 100644
--- a/fs/nfsd/Makefile
+++ b/fs/nfsd/Makefile
@@ -7,5 +7,6 @@ obj-$(CONFIG_NFSD)	+= nfsd.o
 nfsd-y 			:= nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \
 			   export.o auth.o lockd.o nfscache.o nfsxdr.o stats.o
 nfsd-$(CONFIG_NFSD_V3)	+= nfs3proc.o nfs3xdr.o
-nfsd-$(CONFIG_NFSD_V4)	+= nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o
+nfsd-$(CONFIG_NFSD_V4)	+= nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o \
+			   nfs4acl.o
 nfsd-objs		:= $(nfsd-y)
diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
index 8d35f45d9..8637b5f85 100644
--- a/fs/nfsd/auth.c
+++ b/fs/nfsd/auth.c
@@ -50,7 +50,7 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
 		current->fsgid = INOXID_GID(1, cred->cr_uid, cred->cr_gid);
 	else
 		current->fsgid = exp->ex_anon_gid;
-	
+
 	current->xid = INOXID_XID(1, cred->cr_uid, cred->cr_gid, 0);
 
 	if (!cred->cr_group_info)
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 3b9e865c4..1a53ff65d 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -294,6 +294,11 @@ void svc_export_request(struct cache_detail *cd,
 
 	qword_add(bpp, blen, exp->ex_client->name);
 	pth = d_path(exp->ex_dentry, exp->ex_mnt, *bpp, *blen);
+	if (IS_ERR(pth)) {
+		/* is this correct? */
+		(*bpp)[0] = '\n';
+		return;
+	}
 	qword_add(bpp, blen, pth);
 	(*bpp)[-1] = '\n';
 }
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 479835b16..3397bec47 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -10,6 +10,7 @@
 
 #include <linux/types.h>
 #include <linux/fs.h>
+#include <linux/file.h>
 #include <linux/mount.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/svc.h>
@@ -22,7 +23,7 @@
  * Note: we hold the dentry use count while the file is open.
  */
 static u32
-nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file *filp)
+nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)
 {
 	u32		nfserr;
 	struct svc_fh	fh;
@@ -35,10 +36,6 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file *filp)
 
 	exp_readlock();
 	nfserr = nfsd_open(rqstp, &fh, S_IFREG, MAY_LOCK, filp);
-	if (!nfserr) {
-		dget(filp->f_dentry);
-		mntget(filp->f_vfsmnt);
-	}
 	fh_put(&fh);
 	rqstp->rq_client = NULL;
 	exp_readunlock();
@@ -60,9 +57,7 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file *filp)
 static void
 nlm_fclose(struct file *filp)
 {
-	nfsd_close(filp);
-	dput(filp->f_dentry);
-	mntput(filp->f_vfsmnt);
+	fput(filp);
 }
 
 struct nlmsvc_binding		nfsd_nlm_ops = {
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 941ceaec1..effcd1913 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -492,8 +492,16 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
 		count += PAGE_SIZE;
 	}
 	resp->count = count >> 2;
-	if (resp->offset)
-		xdr_encode_hyper(resp->offset, offset);
+	if (resp->offset) {
+		if (unlikely(resp->offset1)) {
+			/* we ended up with offset on a page boundary */
+			*resp->offset = htonl(offset >> 32);
+			*resp->offset1 = htonl(offset & 0xffffffff);
+			resp->offset1 = NULL;
+		} else {
+			xdr_encode_hyper(resp->offset, offset);
+		}
+	}
 
 	RETURN_STATUS(nfserr);
 }
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index d102365fa..95a6e29f8 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -770,10 +770,16 @@ nfs3svc_encode_readdirres(struct svc_rqst *rqstp, u32 *p,
 		/* stupid readdir cookie */
 		memcpy(p, resp->verf, 8); p += 2;
 		xdr_ressize_check(rqstp, p);
-		p = resp->buffer;
+		if (rqstp->rq_res.head[0].iov_len + (2<<2) > PAGE_SIZE)
+			return 1; /*No room for trailer */
+		rqstp->rq_res.page_len = (resp->count) << 2;
+
+		/* add the 'tail' to the end of the 'head' page - page 0. */
+		rqstp->rq_restailpage = 0;
+		rqstp->rq_res.tail[0].iov_base = p;
 		*p++ = 0;		/* no more entries */
 		*p++ = htonl(resp->common.err == nfserr_eof);
-		rqstp->rq_res.page_len = (resp->count + 2) << 2;
+		rqstp->rq_res.tail[0].iov_len = 2<<2;
 		return 1;
 	} else
 		return xdr_ressize_check(rqstp, p);
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index ff8c203e0..55835414f 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -52,6 +52,7 @@
 #include <linux/nfs4.h>
 #include <linux/nfsd/state.h>
 #include <linux/nfsd/xdr4.h>
+#include <linux/nfs4_acl.h>
 
 #define NFSDDBG_FACILITY		NFSDDBG_PROC
 
@@ -620,7 +621,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se
 		status = nfserr_bad_stateid;
 		if (ZERO_STATEID(&setattr->sa_stateid) || ONE_STATEID(&setattr->sa_stateid)) {
 			dprintk("NFSD: nfsd4_setattr: magic stateid!\n");
-			return status;
+			goto out;
 		}
 
 		nfs4_lock_state();
@@ -628,17 +629,25 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se
 						&setattr->sa_stateid, 
 						CHECK_FH | RDWR_STATE, &stp))) {
 			dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
-			goto out;
+			goto out_unlock;
 		}
 		status = nfserr_openmode;
 		if (!access_bits_permit_write(stp->st_access_bmap)) {
 			dprintk("NFSD: nfsd4_setattr: not opened for write!\n");
-			goto out;
+			goto out_unlock;
 		}
 		nfs4_unlock_state();
 	}
-	return (nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr, 0, (time_t)0));
+	status = nfs_ok;
+	if (setattr->sa_acl != NULL)
+		status = nfsd4_set_nfs4_acl(rqstp, current_fh, setattr->sa_acl);
+	if (status)
+		goto out;
+	status = nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr,
+				0, (time_t)0);
 out:
+	return status;
+out_unlock:
 	nfs4_unlock_state();
 	return status;
 }
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 0ff4425ca..1ca8ce8f6 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -236,7 +236,7 @@ static struct nfs4_client *
 create_client(struct xdr_netobj name) {
 	struct nfs4_client *clp;
 
-	if(!(clp = alloc_client(name)))
+	if (!(clp = alloc_client(name)))
 		goto out;
 	INIT_LIST_HEAD(&clp->cl_idhash);
 	INIT_LIST_HEAD(&clp->cl_strhash);
@@ -268,7 +268,7 @@ copy_cred(struct svc_cred *target, struct svc_cred *source) {
 
 static int
 cmp_name(struct xdr_netobj *n1, struct xdr_netobj *n2) {
-	if(!n1 || !n2)
+	if (!n1 || !n2)
 		return 0;
 	return((n1->len == n2->len) && !memcmp(n1->data, n2->data, n2->len));
 }
@@ -399,7 +399,7 @@ parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigne
 			return 0;
 		}
 		cbaddr |= (temp << shift);
-		if(shift > 0)
+		if (shift > 0)
 		shift -= 8;
 	}
 	*cbaddrp = cbaddr;
@@ -411,7 +411,7 @@ parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigne
 			return 0;
 		}
 		cbport |= (temp << shift);
-		if(shift > 0)
+		if (shift > 0)
 			shift -= 8;
 	}
 	*cbportp = cbport;
@@ -423,7 +423,7 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
 {
 	struct nfs4_callback *cb = &clp->cl_callback;
 
-	if( !(parse_ipv4(se->se_callback_addr_len, se->se_callback_addr_val,
+	if ( !(parse_ipv4(se->se_callback_addr_len, se->se_callback_addr_val,
 		         &cb->cb_addr, &cb->cb_port))) {
 		printk(KERN_INFO "NFSD: BAD callback address. client will not receive delegations\n");
 		cb->cb_parsed = 0;
@@ -431,9 +431,9 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
 	}
 	cb->cb_netid.len = se->se_callback_netid_len;
 	cb->cb_netid.data = se->se_callback_netid_val;
-        cb->cb_prog = se->se_callback_prog;
-        cb->cb_ident = se->se_callback_ident;
-        cb->cb_parsed = 1;
+	cb->cb_prog = se->se_callback_prog;
+	cb->cb_ident = se->se_callback_ident;
+	cb->cb_parsed = 1;
 }
 
 /*
@@ -812,7 +812,7 @@ alloc_init_file(unsigned int hashval, struct inode *ino) {
 		alloc_file++;
 		return fp;
 	}
-	return (struct nfs4_file *)NULL;
+	return NULL;
 }
 
 static void
@@ -825,7 +825,7 @@ release_all_files(void)
 		while (!list_empty(&file_hashtbl[i])) {
 			fp = list_entry(file_hashtbl[i].next, struct nfs4_file, fi_hash);
 			/* this should never be more than once... */
-			if(!list_empty(&fp->fi_perfile)) {
+			if (!list_empty(&fp->fi_perfile)) {
 				printk("ERROR: release_all_files: file %p is open, creating dangling state !!!\n",fp);
 			}
 			release_file(fp);
@@ -839,20 +839,20 @@ alloc_stateowner(struct xdr_netobj *owner)
 	struct nfs4_stateowner *sop;
 
 	if ((sop = kmalloc(sizeof(struct nfs4_stateowner),GFP_KERNEL))) {
-		if((sop->so_owner.data = kmalloc(owner->len, GFP_KERNEL))) {
+		if ((sop->so_owner.data = kmalloc(owner->len, GFP_KERNEL))) {
 			memcpy(sop->so_owner.data, owner->data, owner->len);
 			sop->so_owner.len = owner->len;
 			return sop;
 		} 
 		kfree(sop);
 	}
-	return (struct nfs4_stateowner *)NULL;
+	return NULL;
 }
 
 /* should use a slab cache */
 static void
 free_stateowner(struct nfs4_stateowner *sop) {
-	if(sop) {
+	if (sop) {
 		kfree(sop->so_owner.data);
 		kfree(sop);
 		sop = NULL;
@@ -867,7 +867,7 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
 	unsigned int idhashval;
 
 	if (!(sop = alloc_stateowner(&open->op_owner)))
-		return (struct nfs4_stateowner *)NULL;
+		return NULL;
 	idhashval = ownerid_hashval(current_ownerid);
 	INIT_LIST_HEAD(&sop->so_idhash);
 	INIT_LIST_HEAD(&sop->so_strhash);
@@ -908,7 +908,7 @@ release_stateid_lockowner(struct nfs4_stateid *open_stp)
 }
 
 static void
-release_stateowner(struct nfs4_stateowner *sop)
+unhash_stateowner(struct nfs4_stateowner *sop)
 {
 	struct nfs4_stateid *stp;
 
@@ -916,16 +916,22 @@ release_stateowner(struct nfs4_stateowner *sop)
 	list_del(&sop->so_strhash);
 	list_del(&sop->so_perclient);
 	list_del(&sop->so_perlockowner);
-	list_del(&sop->so_close_lru);
 	del_perclient++;
 	while (!list_empty(&sop->so_perfilestate)) {
 		stp = list_entry(sop->so_perfilestate.next, 
 			struct nfs4_stateid, st_perfilestate);
-		if(sop->so_is_open_owner)
+		if (sop->so_is_open_owner)
 			release_stateid(stp, OPEN_STATE);
 		else
 			release_stateid(stp, LOCK_STATE);
 	}
+}
+
+static void
+release_stateowner(struct nfs4_stateowner *sop)
+{
+	unhash_stateowner(sop);
+	list_del(&sop->so_close_lru);
 	free_stateowner(sop);
 }
 
@@ -960,14 +966,12 @@ release_stateid(struct nfs4_stateid *stp, int flags) {
 	list_del_perfile++;
 	list_del(&stp->st_perfile);
 	list_del(&stp->st_perfilestate);
-	if((stp->st_vfs_set) && (flags & OPEN_STATE)) {
+	if ((stp->st_vfs_set) && (flags & OPEN_STATE)) {
 		release_stateid_lockowner(stp);
-		nfsd_close(&stp->st_vfs_file);
+		nfsd_close(stp->st_vfs_file);
 		vfsclose++;
-		dput(stp->st_vfs_file.f_dentry);
-		mntput(stp->st_vfs_file.f_vfsmnt);
 	} else if ((stp->st_vfs_set) && (flags & LOCK_STATE)) {
-		struct file *filp = &stp->st_vfs_file;
+		struct file *filp = stp->st_vfs_file;
 
 		locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
 	}
@@ -988,13 +992,10 @@ void
 move_to_close_lru(struct nfs4_stateowner *sop)
 {
 	dprintk("NFSD: move_to_close_lru nfs4_stateowner %p\n", sop);
-	/* remove stateowner from all other hash lists except perclient */
-	list_del_init(&sop->so_idhash);
-	list_del_init(&sop->so_strhash);
-	list_del_init(&sop->so_perlockowner);
 
-        list_add_tail(&sop->so_close_lru, &close_lru);
-        sop->so_time = get_seconds();
+	unhash_stateowner(sop);
+	list_add_tail(&sop->so_close_lru, &close_lru);
+	sop->so_time = get_seconds();
 }
 
 void
@@ -1032,7 +1033,7 @@ find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, struct nf
 	struct nfs4_stateowner *local = NULL;
 
 	list_for_each_entry(local, &ownerstr_hashtbl[hashval], so_strhash) {
-		if(!cmp_owner_str(local, &open->op_owner, &open->op_clientid)) 
+		if (!cmp_owner_str(local, &open->op_owner, &open->op_clientid))
 			continue;
 		*op = local;
 		return(1);
@@ -1080,7 +1081,7 @@ set_access(unsigned int *access, unsigned long bmap) {
 
 	*access = 0;
 	for (i = 1; i < 4; i++) {
-		if(test_bit(i, &bmap))
+		if (test_bit(i, &bmap))
 			*access |= i;
 	}
 }
@@ -1091,7 +1092,7 @@ set_deny(unsigned int *deny, unsigned long bmap) {
 
 	*deny = 0;
 	for (i = 0; i < 4; i++) {
-		if(test_bit(i, &bmap))
+		if (test_bit(i, &bmap))
 			*deny |= i ;
 	}
 }
@@ -1280,7 +1281,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
 		/* Search for conflicting share reservations */
 		status = nfserr_share_denied;
 		list_for_each_entry(stq, &fp->fi_perfile, st_perfile) {
-			if(stq->st_stateowner == sop) {
+			if (stq->st_stateowner == sop) {
 				stp = stq;
 				continue;
 			}
@@ -1315,8 +1316,6 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
 			goto out_free;
 
 		vfsopen++;
-		dget(stp->st_vfs_file.f_dentry);
-		mntget(stp->st_vfs_file.f_vfsmnt);
 
 		init_stateid(stp, fp, sop, open);
 		stp->st_vfs_set = 1;
@@ -1331,7 +1330,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
 		share_access &= open->op_share_access;
 
 		/* update the struct file */
-		if ((status = nfs4_file_upgrade(&stp->st_vfs_file, share_access)))
+		if ((status = nfs4_file_upgrade(stp->st_vfs_file, share_access)))
 			goto out;
 		/* remember the open */
 		set_bit(open->op_share_access, &stp->st_access_bmap);
@@ -1460,7 +1459,8 @@ nfs4_laundromat(void)
 		}
 		dprintk("NFSD: purging unused open stateowner (so_id %d)\n",
 			sop->so_id);
-		release_stateowner(sop);
+		list_del(&sop->so_close_lru);
+		free_stateowner(sop);
 	}
 	if (clientid_val < NFSD_LAUNDROMAT_MINTIMEOUT)
 		clientid_val = NFSD_LAUNDROMAT_MINTIMEOUT;
@@ -1488,7 +1488,7 @@ find_openstateowner_id(u32 st_id, int flags) {
 	dprintk("NFSD: find_openstateowner_id %d\n", st_id);
 	if (flags & CLOSE_STATE) {
 		list_for_each_entry(local, &close_lru, so_close_lru) {
-			if(local->so_id == st_id)
+			if (local->so_id == st_id)
 				return local;
 		}
 	}
@@ -1499,7 +1499,7 @@ static inline int
 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp)
 {
 	return (stp->st_vfs_set == 0 ||
-		fhp->fh_dentry->d_inode != stp->st_vfs_file.f_dentry->d_inode);
+		fhp->fh_dentry->d_inode != stp->st_vfs_file->f_dentry->d_inode);
 }
 
 static int
@@ -1816,7 +1816,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct n
 		goto out;
 	}
 	set_access(&share_access, stp->st_access_bmap);
-	nfs4_file_downgrade(&stp->st_vfs_file, 
+	nfs4_file_downgrade(stp->st_vfs_file,
 	                    share_access & ~od->od_share_access);
 
 	reset_union_bmap_access(od->od_share_access, &stp->st_access_bmap);
@@ -1892,16 +1892,16 @@ find_stateid(stateid_t *stid, int flags)
 	if ((flags & LOCK_STATE) || (flags & RDWR_STATE)) {
 		hashval = stateid_hashval(st_id, f_id);
 		list_for_each_entry(local, &lockstateid_hashtbl[hashval], st_hash) {
-			if((local->st_stateid.si_stateownerid == st_id) &&
-			   (local->st_stateid.si_fileid == f_id))
+			if ((local->st_stateid.si_stateownerid == st_id) &&
+			    (local->st_stateid.si_fileid == f_id))
 				return local;
 		}
 	} 
 	if ((flags & OPEN_STATE) || (flags & RDWR_STATE)) {
 		hashval = stateid_hashval(st_id, f_id);
 		list_for_each_entry(local, &stateid_hashtbl[hashval], st_hash) {
-			if((local->st_stateid.si_stateownerid == st_id) &&
-			   (local->st_stateid.si_fileid == f_id))
+			if ((local->st_stateid.si_stateownerid == st_id) &&
+			    (local->st_stateid.si_fileid == f_id))
 				return local;
 		}
 	} else
@@ -1950,9 +1950,10 @@ static inline void
 nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny)
 {
 	struct nfs4_stateowner *sop = (struct nfs4_stateowner *) fl->fl_owner;
+	unsigned int hval = lockownerid_hashval(sop->so_id);
 
 	deny->ld_sop = NULL;
-	if (nfs4_verify_lock_stateowner(sop, fl->fl_pid))
+	if (nfs4_verify_lock_stateowner(sop, hval))
 		deny->ld_sop = sop;
 	deny->ld_start = fl->fl_start;
 	deny->ld_length = ~(u64)0;
@@ -1971,7 +1972,7 @@ find_lockstateowner(struct xdr_netobj *owner, clientid_t *clid)
 
 	for (i = 0; i < LOCK_HASH_SIZE; i++) {
 		list_for_each_entry(local, &lock_ownerid_hashtbl[i], so_idhash) {
-			if(!cmp_owner_str(local, owner, clid))
+			if (!cmp_owner_str(local, owner, clid))
 				continue;
 			return local;
 		}
@@ -1984,7 +1985,7 @@ find_lockstateowner_str(unsigned int hashval, struct xdr_netobj *owner, clientid
 	struct nfs4_stateowner *local = NULL;
 
 	list_for_each_entry(local, &lock_ownerstr_hashtbl[hashval], so_strhash) {
-		if(!cmp_owner_str(local, owner, clid)) 
+		if (!cmp_owner_str(local, owner, clid))
 			continue;
 		*op = local;
 		return(1);
@@ -2009,7 +2010,7 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
 	unsigned int idhashval;
 
 	if (!(sop = alloc_stateowner(&lock->lk_new_owner)))
-		return (struct nfs4_stateowner *)NULL;
+		return NULL;
 	idhashval = lockownerid_hashval(current_ownerid);
 	INIT_LIST_HEAD(&sop->so_idhash);
 	INIT_LIST_HEAD(&sop->so_strhash);
@@ -2059,7 +2060,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
 	stp->st_stateid.si_stateownerid = sop->so_id;
 	stp->st_stateid.si_fileid = fp->fi_id;
 	stp->st_stateid.si_generation = 0;
-	stp->st_vfs_file = open_stp->st_vfs_file;
+	stp->st_vfs_file = open_stp->st_vfs_file; /* FIXME refcount?? */
 	stp->st_vfs_set = open_stp->st_vfs_set;
 	stp->st_access_bmap = open_stp->st_access_bmap;
 	stp->st_deny_bmap = open_stp->st_deny_bmap;
@@ -2072,7 +2073,7 @@ int
 check_lock_length(u64 offset, u64 length)
 {
 	return ((length == 0)  || ((length != ~(u64)0) &&
- 	     LOFF_OVERFLOW(offset, length)));
+	     LOFF_OVERFLOW(offset, length)));
 }
 
 /*
@@ -2157,8 +2158,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
 		if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, open_sop->so_client, open_stp, lock)))
 			goto out;
 		if ((lock_stp = alloc_init_lock_stateid(lock->lk_stateowner, 
-						fp, open_stp)) == NULL)
+						fp, open_stp)) == NULL) {
+			release_stateowner(lock->lk_stateowner);
 			goto out;
+		}
 		/* bump the open seqid used to create the lock */
 		open_sop->so_seqid++;
 	} else {
@@ -2172,13 +2175,14 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
 			goto out;
 	}
 	/* lock->lk_stateowner and lock_stp have been created or found */
-	filp = &lock_stp->st_vfs_file;
+	filp = lock_stp->st_vfs_file;
 
 	if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
 		printk("NFSD: nfsd4_lock: permission denied!\n");
 		goto out;
 	}
 
+	locks_init_lock(&file_lock);
 	switch (lock->lk_type) {
 		case NFS4_READ_LT:
 		case NFS4_READW_LT:
@@ -2193,12 +2197,9 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
 		goto out;
 	}
 	file_lock.fl_owner = (fl_owner_t) lock->lk_stateowner;
-	file_lock.fl_pid = lockownerid_hashval(lock->lk_stateowner->so_id);
+	file_lock.fl_pid = current->tgid;
 	file_lock.fl_file = filp;
 	file_lock.fl_flags = FL_POSIX;
-	file_lock.fl_notify = NULL;
-	file_lock.fl_insert = NULL;
-	file_lock.fl_remove = NULL;
 
 	file_lock.fl_start = lock->lk_offset;
 	if ((lock->lk_length == ~(u64)0) || 
@@ -2214,7 +2215,9 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
 	*/
 
 	status = posix_lock_file(filp, &file_lock);
-	dprintk("NFSD: nfsd4_lock: posix_test_lock passed. posix_lock_file status %d\n",status);
+	if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
+		file_lock.fl_ops->fl_release_private(&file_lock);
+	dprintk("NFSD: nfsd4_lock: posix_lock_file status %d\n",status);
 	switch (-status) {
 	case 0: /* success! */
 		update_stateid(&lock_stp->st_stateid);
@@ -2265,7 +2268,6 @@ int
 nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lockt *lockt)
 {
 	struct inode *inode;
-	struct nfs4_stateowner *sop;
 	struct file file;
 	struct file_lock file_lock;
 	struct file_lock *conflicting_lock;
@@ -2295,6 +2297,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
 	}
 
 	inode = current_fh->fh_dentry->d_inode;
+	locks_init_lock(&file_lock);
 	switch (lockt->lt_type) {
 		case NFS4_READ_LT:
 		case NFS4_READW_LT:
@@ -2316,14 +2319,9 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
 	find_lockstateowner_str(strhashval, &lockt->lt_owner,
 					&lockt->lt_clientid, 
 					&lockt->lt_stateowner);
-	sop = lockt->lt_stateowner;
-	if (sop) {
-		file_lock.fl_owner = (fl_owner_t) sop;
-		file_lock.fl_pid = lockownerid_hashval(sop->so_id);
-	} else {
-		file_lock.fl_owner = NULL;
-		file_lock.fl_pid = 0;
-	}
+	if (lockt->lt_stateowner)
+		file_lock.fl_owner = (fl_owner_t)lockt->lt_stateowner;
+	file_lock.fl_pid = current->tgid;
 	file_lock.fl_flags = FL_POSIX;
 
 	file_lock.fl_start = lockt->lt_offset;
@@ -2378,16 +2376,14 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
 					&locku->lu_stateowner, &stp, NULL)))
 		goto out;
 
-	filp = &stp->st_vfs_file;
+	filp = stp->st_vfs_file;
 	BUG_ON(!filp);
+	locks_init_lock(&file_lock);
 	file_lock.fl_type = F_UNLCK;
 	file_lock.fl_owner = (fl_owner_t) locku->lu_stateowner;
-	file_lock.fl_pid = lockownerid_hashval(locku->lu_stateowner->so_id);
+	file_lock.fl_pid = current->tgid;
 	file_lock.fl_file = filp;
 	file_lock.fl_flags = FL_POSIX; 
-	file_lock.fl_notify = NULL;
-	file_lock.fl_insert = NULL;
-	file_lock.fl_remove = NULL;
 	file_lock.fl_start = locku->lu_offset;
 
 	if ((locku->lu_length == ~(u64)0) || LOFF_OVERFLOW(locku->lu_offset, locku->lu_length))
@@ -2400,6 +2396,8 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
 	*  Try to unlock the file in the VFS.
 	*/
 	status = posix_lock_file(filp, &file_lock); 
+	if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
+		file_lock.fl_ops->fl_release_private(&file_lock);
 	if (status) {
 		printk("NFSD: nfs4_locku: posix_lock_file failed!\n");
 		goto out_nfserr;
@@ -2462,7 +2460,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *
 
 	nfs4_lock_state();
 
-        status = nfs_ok;
+	status = nfs_ok;
 	local = find_lockstateowner(owner, clid);
 	if (local) {
 		struct nfs4_stateid *stp;
@@ -2472,8 +2470,8 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *
 		status = nfserr_locks_held;
 		list_for_each_entry(stp, &local->so_perfilestate,
 				st_perfilestate) {
-			if(stp->st_vfs_set) {
-				if (check_for_locks(&stp->st_vfs_file, local))
+			if (stp->st_vfs_set) {
+				if (check_for_locks(stp->st_vfs_file, local))
 					goto out;
 			}
 		}
@@ -2499,7 +2497,7 @@ alloc_reclaim(int namelen)
 		kfree(crp);
 		return NULL;
 	}
-       	return crp;
+	return crp;
 }
 
 /*
@@ -2569,7 +2567,7 @@ nfs4_find_reclaim_client(clientid_t *clid)
 	strhashval = clientstr_hashval(client->cl_name.data,
 	                              client->cl_name.len);
 	list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) {
-		if(cmp_name(&crp->cr_name, &client->cl_name)) {
+		if (cmp_name(&crp->cr_name, &client->cl_name)) {
 			return crp;
 		}
 	}
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index e95b02a70..af0c9bc92 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -55,6 +55,8 @@
 #include <linux/nfsd/state.h>
 #include <linux/nfsd/xdr4.h>
 #include <linux/nfsd_idmap.h>
+#include <linux/nfs4.h>
+#include <linux/nfs4_acl.h>
 #include <linux/vserver/xid.h>
 
 #define NFSDDBG_FACILITY		NFSDDBG_XDR
@@ -349,7 +351,8 @@ nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
 }
 
 static int
-nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *iattr)
+nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *iattr,
+    struct nfs4_acl **acl)
 {
 	int expected_len, len = 0;
 	u32 dummy32;
@@ -378,6 +381,51 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia
 		READ64(iattr->ia_size);
 		iattr->ia_valid |= ATTR_SIZE;
 	}
+	if (bmval[0] & FATTR4_WORD0_ACL) {
+		int nace, i;
+		struct nfs4_ace ace;
+
+		READ_BUF(4); len += 4;
+		READ32(nace);
+
+		*acl = nfs4_acl_new();
+		if (*acl == NULL) {
+			status = -ENOMEM;
+			goto out_nfserr;
+		}
+		defer_free(argp, (void (*)(const void *))nfs4_acl_free, *acl);
+
+		for (i = 0; i < nace; i++) {
+			READ_BUF(16); len += 16;
+			READ32(ace.type);
+			READ32(ace.flag);
+			READ32(ace.access_mask);
+			READ32(dummy32);
+			READ_BUF(dummy32);
+			len += XDR_QUADLEN(dummy32) << 2;
+			READMEM(buf, dummy32);
+			if (check_utf8(buf, dummy32))
+				return nfserr_inval;
+			ace.whotype = nfs4_acl_get_whotype(buf, dummy32);
+			status = 0;
+			if (ace.whotype != NFS4_ACL_WHO_NAMED)
+				ace.who = 0;
+			else if (ace.flag & NFS4_ACE_IDENTIFIER_GROUP)
+				status = nfsd_map_name_to_gid(argp->rqstp,
+						buf, dummy32, &ace.who);
+			else
+				status = nfsd_map_name_to_uid(argp->rqstp,
+						buf, dummy32, &ace.who);
+			if (status)
+				goto out_nfserr;
+			if (nfs4_acl_add_ace(*acl, ace.type, ace.flag,
+				 ace.access_mask, ace.whotype, ace.who) != 0) {
+				status = -ENOMEM;
+				goto out_nfserr;
+			}
+		}
+	} else
+		*acl = NULL;
 	if (bmval[1] & FATTR4_WORD1_MODE) {
 		READ_BUF(4);
 		len += 4;
@@ -563,7 +611,7 @@ nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create
 	if ((status = check_filename(create->cr_name, create->cr_namelen, nfserr_inval)))
 		return status;
 
-	if ((status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr)))
+	if ((status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr, &create->cr_acl)))
 		goto out;
 
 	DECODE_TAIL;
@@ -712,7 +760,7 @@ nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
 		switch (open->op_createmode) {
 		case NFS4_CREATE_UNCHECKED:
 		case NFS4_CREATE_GUARDED:
-			if ((status = nfsd4_decode_fattr(argp, open->op_bmval, &open->op_iattr)))
+			if ((status = nfsd4_decode_fattr(argp, open->op_bmval, &open->op_iattr, &open->op_acl)))
 				goto out;
 			break;
 		case NFS4_CREATE_EXCLUSIVE:
@@ -889,7 +937,7 @@ nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *seta
 	READ_BUF(sizeof(stateid_t));
 	READ32(setattr->sa_stateid.si_generation);
 	COPYMEM(&setattr->sa_stateid.si_opaque, sizeof(stateid_opaque_t));
-	if ((status = nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr)))
+	if ((status = nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr, &setattr->sa_acl)))
 		goto out;
 
 	DECODE_TAIL;
@@ -1303,14 +1351,16 @@ static u32 nfs4_ftypes[16] = {
 };
 
 static int
-nfsd4_encode_name(struct svc_rqst *rqstp, int group, uid_t id,
+nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
 			u32 **p, int *buflen)
 {
 	int status;
 
 	if (*buflen < (XDR_QUADLEN(IDMAP_NAMESZ) << 2) + 4)
 		return nfserr_resource;
-	if (group)
+	if (whotype != NFS4_ACL_WHO_NAMED)
+		status = nfs4_acl_write_who(whotype, (u8 *)(*p + 1));
+	else if (group)
 		status = nfsd_map_gid_to_name(rqstp, id, (u8 *)(*p + 1));
 	else
 		status = nfsd_map_uid_to_name(rqstp, id, (u8 *)(*p + 1));
@@ -1325,13 +1375,20 @@ nfsd4_encode_name(struct svc_rqst *rqstp, int group, uid_t id,
 static inline int
 nfsd4_encode_user(struct svc_rqst *rqstp, uid_t uid, u32 **p, int *buflen)
 {
-	return nfsd4_encode_name(rqstp, uid, 0, p, buflen);
+	return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, uid, 0, p, buflen);
 }
 
 static inline int
 nfsd4_encode_group(struct svc_rqst *rqstp, uid_t gid, u32 **p, int *buflen)
 {
-	return nfsd4_encode_name(rqstp, gid, 1, p, buflen);
+	return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, gid, 1, p, buflen);
+}
+
+static inline int
+nfsd4_encode_aclname(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
+		u32 **p, int *buflen)
+{
+	return nfsd4_encode_name(rqstp, whotype, id, group, p, buflen);
 }
 
 
@@ -1358,6 +1415,8 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
 	u64 dummy64;
 	u32 *p = buffer;
 	int status;
+	int aclsupport = 0;
+	struct nfs4_acl *acl = NULL;
 
 	BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
 	BUG_ON(bmval0 & ~NFSD_SUPPORTED_ATTRS_WORD0);
@@ -1380,6 +1439,17 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
 			goto out;
 		fhp = &tempfh;
 	}
+	if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT
+			| FATTR4_WORD0_SUPPORTED_ATTRS)) {
+		status = nfsd4_get_nfs4_acl(rqstp, dentry, &acl);
+		aclsupport = (status == 0);
+		if (bmval0 & FATTR4_WORD0_ACL) {
+			if (status == -EOPNOTSUPP)
+				bmval0 &= ~FATTR4_WORD0_ACL;
+			else if (status != 0)
+				goto out_nfserr;
+		}
+	}
 	if ((buflen -= 16) < 0)
 		goto out_resource;
 
@@ -1392,7 +1462,9 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
 		if ((buflen -= 12) < 0)
 			goto out_resource;
 		WRITE32(2);
-		WRITE32(NFSD_SUPPORTED_ATTRS_WORD0);
+		WRITE32(aclsupport ?
+			NFSD_SUPPORTED_ATTRS_WORD0 :
+			NFSD_SUPPORTED_ATTRS_WORD0 & ~FATTR4_WORD0_ACL);
 		WRITE32(NFSD_SUPPORTED_ATTRS_WORD1);
 	}
 	if (bmval0 & FATTR4_WORD0_TYPE) {
@@ -1463,10 +1535,44 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
 			goto out_resource;
 		WRITE32(0);
 	}
+	if (bmval0 & FATTR4_WORD0_ACL) {
+		struct nfs4_ace *ace;
+		struct list_head *h;
+
+		if (acl == NULL) {
+			if ((buflen -= 4) < 0)
+				goto out_resource;
+
+			WRITE32(0);
+			goto out_acl;
+		}
+		if ((buflen -= 4) < 0)
+			goto out_resource;
+		WRITE32(acl->naces);
+
+		list_for_each(h, &acl->ace_head) {
+			ace = list_entry(h, struct nfs4_ace, l_ace);
+
+			if ((buflen -= 4*3) < 0)
+				goto out_resource;
+			WRITE32(ace->type);
+			WRITE32(ace->flag);
+			WRITE32(ace->access_mask & NFS4_ACE_MASK_ALL);
+			status = nfsd4_encode_aclname(rqstp, ace->whotype,
+				ace->who, ace->flag & NFS4_ACE_IDENTIFIER_GROUP,
+				&p, &buflen);
+			if (status == nfserr_resource)
+				goto out_resource;
+			if (status)
+				goto out;
+		}
+	}
+out_acl:
 	if (bmval0 & FATTR4_WORD0_ACLSUPPORT) {
 		if ((buflen -= 4) < 0)
 			goto out_resource;
-		WRITE32(0);
+		WRITE32(aclsupport ?
+			ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL : 0);
 	}
 	if (bmval0 & FATTR4_WORD0_CANSETTIME) {
 		if ((buflen -= 4) < 0)
@@ -1653,6 +1759,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
 	status = nfs_ok;
 
 out:
+	nfs4_acl_free(acl);
 	if (fhp == &tempfh)
 		fh_put(&tempfh);
 	return status;
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 9c9399258..161afdcb8 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -80,101 +80,31 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
 	[NFSD_Leasetime] = write_leasetime,
 };
 
-/* an argresp is stored in an allocated page and holds the 
- * size of the argument or response, along with its content
- */
-struct argresp {
-	ssize_t size;
-	char data[0];
-};
-
-/*
- * transaction based IO methods.
- * The file expects a single write which triggers the transaction, and then
- * possibly a read which collects the result - which is stored in a 
- * file-local buffer.
- */
-static ssize_t TA_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
+static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
 {
 	ino_t ino =  file->f_dentry->d_inode->i_ino;
-	struct argresp *ar;
-	ssize_t rv = 0;
+	char *data;
+	ssize_t rv;
 
 	if (ino >= sizeof(write_op)/sizeof(write_op[0]) || !write_op[ino])
 		return -EINVAL;
-	if (file->private_data) 
-		return -EINVAL; /* only one write allowed per open */
-	if (size > PAGE_SIZE - sizeof(struct argresp))
-		return -EFBIG;
 
-	ar = kmalloc(PAGE_SIZE, GFP_KERNEL);
-	if (!ar)
-		return -ENOMEM;
-	ar->size = 0;
-	down(&file->f_dentry->d_inode->i_sem);
-	if (file->private_data)
-		rv = -EINVAL;
-	else
-		file->private_data = ar;
-	up(&file->f_dentry->d_inode->i_sem);
-	if (rv) {
-		kfree(ar);
-		return rv;
-	}
-	if (copy_from_user(ar->data, buf, size))
-		return -EFAULT;
-	
-	rv =  write_op[ino](file, ar->data, size);
+	data = simple_transaction_get(file, buf, size);
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	rv =  write_op[ino](file, data, size);
 	if (rv>0) {
-		ar->size = rv;
+		simple_transaction_set(file, rv);
 		rv = size;
 	}
 	return rv;
 }
 
-
-static ssize_t TA_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
-{
-	struct argresp *ar;
-	ssize_t rv = 0;
-	
-	if (file->private_data == NULL)
-		rv = TA_write(file, buf, 0, pos);
-	if (rv < 0)
-		return rv;
-
-	ar = file->private_data;
-	if (!ar)
-		return 0;
-	if (*pos >= ar->size)
-		return 0;
-	if (*pos + size > ar->size)
-		size = ar->size - *pos;
-	if (copy_to_user(buf, ar->data + *pos, size))
-		return -EFAULT;
-	*pos += size;
-	return size;
-}
-
-static int TA_open(struct inode *inode, struct file *file)
-{
-	file->private_data = NULL;
-	return 0;
-}
-
-static int TA_release(struct inode *inode, struct file *file)
-{
-	void *p = file->private_data;
-	file->private_data = NULL;
-	kfree(p);
-	return 0;
-}
-
 static struct file_operations transaction_ops = {
-	.write		= TA_write,
-	.read		= TA_read,
-	.open		= TA_open,
-	.release	= TA_release,
+	.write		= nfsctl_transaction_write,
+	.read		= simple_transaction_read,
+	.release	= simple_transaction_release,
 };
 
 extern struct seq_operations nfs_exports_op;
@@ -366,7 +296,7 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
 	if (len)
 		return len;
 	
-	mesg = buf; len = PAGE_SIZE-sizeof(struct argresp);
+	mesg = buf; len = SIMPLE_TRANSACTION_LIMIT;
 	qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size);
 	mesg[-1] = '\n';
 	return mesg - buf;	
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 8e8c2342b..db0020491 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -190,10 +190,10 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
 			dentry = dget(exp->ex_dentry);
 		else {
 			struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op;
-				dentry = CALL(nop,decode_fh)(exp->ex_mnt->mnt_sb,
-							     datap, data_left,
-							     fileid_type,
-							     nfsd_acceptable, exp);
+			dentry = CALL(nop,decode_fh)(exp->ex_mnt->mnt_sb,
+						     datap, data_left,
+						     fileid_type,
+						     nfsd_acceptable, exp);
 		}
 		if (dentry == NULL)
 			goto out;
@@ -339,13 +339,16 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st
 			ref_fh_fsid_type = ref_fh->fh_handle.fh_fsid_type;
 		if (ref_fh_fsid_type > 3)
 			ref_fh_fsid_type = 0;
-	}
-	/* make sure ref_fh type works for given export */
-	if (ref_fh_fsid_type == 1 &&
-	    !(exp->ex_flags & NFSEXP_FSID)) {
-		/* if we don't have an fsid, we cannot provide one... */
-		ref_fh_fsid_type = 0;
-	}
+
+		/* make sure ref_fh type works for given export */
+		if (ref_fh_fsid_type == 1 &&
+		    !(exp->ex_flags & NFSEXP_FSID)) {
+			/* if we don't have an fsid, we cannot provide one... */
+			ref_fh_fsid_type = 0;
+		}
+	} else if (exp->ex_flags & NFSEXP_FSID)
+		ref_fh_fsid_type = 1;
+
 	if (!old_valid_dev(ex_dev) && ref_fh_fsid_type == 0) {
 		/* for newer device numbers, we must use a newer fsid format */
 		ref_fh_version = 1;
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index d34a59d28..13ff22ad2 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -586,6 +586,7 @@ nfserrno (int errno)
 		{ nfserr_dquot, -EDQUOT },
 #endif
 		{ nfserr_stale, -ESTALE },
+		{ nfserr_jukebox, -EWOULDBLOCK },
 		{ nfserr_jukebox, -ETIMEDOUT },
 		{ nfserr_dropit, -EAGAIN },
 		{ nfserr_dropit, -ENOMEM },
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index b783620ff..8a06919c7 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -328,6 +328,8 @@ nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp)
 
 	/* Now call the procedure handler, and encode NFS status. */
 	nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);
+	if (nfserr == nfserr_jukebox && rqstp->rq_vers == 2)
+		nfserr = nfserr_dropit;
 	if (nfserr == nfserr_dropit) {
 		dprintk("nfsd: Dropping request due to malloc failure!\n");
 		nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index d50269bc5..1db1af42e 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -21,6 +21,7 @@
 #include <linux/time.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
+#include <linux/file.h>
 #include <linux/mount.h>
 #include <linux/major.h>
 #include <linux/ext2_fs.h>
@@ -44,6 +45,16 @@
 #include <linux/nfsd/nfsfh.h>
 #include <linux/quotaops.h>
 #include <linux/dnotify.h>
+#ifdef CONFIG_NFSD_V4
+#include <linux/posix_acl.h>
+#include <linux/posix_acl_xattr.h>
+#include <linux/xattr_acl.h>
+#include <linux/xattr.h>
+#include <linux/nfs4.h>
+#include <linux/nfs4_acl.h>
+#include <linux/nfsd_idmap.h>
+#include <linux/security.h>
+#endif /* CONFIG_NFSD_V4 */
 
 #include <asm/uaccess.h>
 
@@ -69,6 +80,7 @@ struct raparms {
 	unsigned int		p_count;
 	ino_t			p_ino;
 	dev_t			p_dev;
+	int			p_set;
 	struct file_ra_state	p_ra;
 };
 
@@ -291,8 +303,8 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
 		 * If we are changing the size of the file, then
 		 * we need to break all leases.
 		 */
-		err = break_lease(inode, FMODE_WRITE);
-		if (err)
+		err = break_lease(inode, FMODE_WRITE | O_NONBLOCK);
+		if (err) /* ENOMEM or EWOULDBLOCK */
 			goto out_nfserr;
 
 		err = get_write_access(inode);
@@ -344,6 +356,177 @@ out_nfserr:
 	goto out;
 }
 
+#if defined(CONFIG_NFSD_V4)
+
+static int
+set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
+{
+	int len;
+	size_t buflen;
+	char *buf = NULL;
+	int error = 0;
+	struct inode *inode = dentry->d_inode;
+
+	buflen = posix_acl_xattr_size(pacl->a_count);
+	buf = kmalloc(buflen, GFP_KERNEL);
+	error = -ENOMEM;
+	if (buf == NULL)
+		goto out;
+
+	len = posix_acl_to_xattr(pacl, buf, buflen);
+	if (len < 0) {
+		error = len;
+		goto out;
+	}
+
+	error = -EOPNOTSUPP;
+	if (inode->i_op && inode->i_op->setxattr) {
+		down(&inode->i_sem);
+		security_inode_setxattr(dentry, key, buf, len, 0);
+		error = inode->i_op->setxattr(dentry, key, buf, len, 0);
+		if (!error)
+			security_inode_post_setxattr(dentry, key, buf, len, 0);
+		up(&inode->i_sem);
+	}
+out:
+	kfree(buf);
+	return (error);
+}
+
+int
+nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
+    struct nfs4_acl *acl)
+{
+	int error;
+	struct dentry *dentry;
+	struct inode *inode;
+	struct posix_acl *pacl = NULL, *dpacl = NULL;
+	unsigned int flags = 0;
+
+	/* Get inode */
+	error = fh_verify(rqstp, fhp, 0 /* S_IFREG */, MAY_SATTR);
+	if (error)
+		goto out;
+
+	dentry = fhp->fh_dentry;
+	inode = dentry->d_inode;
+	if (S_ISDIR(inode->i_mode))
+		flags = NFS4_ACL_DIR;
+
+	error = nfs4_acl_nfsv4_to_posix(acl, &pacl, &dpacl, flags);
+	if (error < 0)
+		goto out_nfserr;
+
+	if (pacl) {
+		error = set_nfsv4_acl_one(dentry, pacl, XATTR_NAME_ACL_ACCESS);
+		if (error < 0)
+			goto out_nfserr;
+	}
+
+	if (dpacl) {
+		error = set_nfsv4_acl_one(dentry, dpacl, XATTR_NAME_ACL_DEFAULT);
+		if (error < 0)
+			goto out_nfserr;
+	}
+
+	error = nfs_ok;
+
+out:
+	posix_acl_release(pacl);
+	posix_acl_release(dpacl);
+	return (error);
+out_nfserr:
+	error = nfserrno(error);
+	goto out;
+}
+
+static struct posix_acl *
+_get_posix_acl(struct dentry *dentry, char *key)
+{
+	struct inode *inode = dentry->d_inode;
+	char *buf = NULL;
+	int buflen, error = 0;
+	struct posix_acl *pacl = NULL;
+
+	down(&inode->i_sem);
+
+	buflen = inode->i_op->getxattr(dentry, key, NULL, 0);
+	if (buflen <= 0) {
+		error = buflen < 0 ? buflen : -ENODATA;
+		goto out_sem;
+	}
+
+	buf = kmalloc(buflen, GFP_KERNEL);
+	if (buf == NULL) {
+		error = -ENOMEM;
+		goto out_sem;
+	}
+
+	error = -EOPNOTSUPP;
+	if (inode->i_op && inode->i_op->getxattr) {
+		error = security_inode_getxattr(dentry, key);
+		if (error)
+			goto out_sem;
+		error = inode->i_op->getxattr(dentry, key, buf, buflen);
+	}
+	if (error < 0)
+		goto out_sem;
+
+	error = 0;
+	up(&inode->i_sem);
+
+	pacl = posix_acl_from_xattr(buf, buflen);
+ out:
+	kfree(buf);
+	return pacl;
+ out_sem:
+	up(&inode->i_sem);
+	pacl = ERR_PTR(error);
+	goto out;
+}
+
+int
+nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_acl **acl)
+{
+	struct inode *inode = dentry->d_inode;
+	int error = 0;
+	struct posix_acl *pacl = NULL, *dpacl = NULL;
+	unsigned int flags = 0;
+
+	pacl = _get_posix_acl(dentry, XATTR_NAME_ACL_ACCESS);
+	if (IS_ERR(pacl) && PTR_ERR(pacl) == -ENODATA)
+		pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
+	if (IS_ERR(pacl)) {
+		error = PTR_ERR(pacl);
+		pacl = NULL;
+		goto out;
+	}
+
+	if (S_ISDIR(inode->i_mode)) {
+		dpacl = _get_posix_acl(dentry, XATTR_NAME_ACL_DEFAULT);
+		if (IS_ERR(dpacl) && PTR_ERR(dpacl) == -ENODATA)
+			dpacl = NULL;
+		else if (IS_ERR(dpacl)) {
+			error = PTR_ERR(dpacl);
+			dpacl = NULL;
+			goto out;
+		}
+		flags = NFS4_ACL_DIR;
+	}
+
+	*acl = nfs4_acl_posix_to_nfsv4(pacl, dpacl, flags);
+	if (IS_ERR(*acl)) {
+		error = PTR_ERR(*acl);
+		*acl = NULL;
+	}
+ out:
+	posix_acl_release(pacl);
+	posix_acl_release(dpacl);
+	return error;
+}
+
+#endif /* defined(CONFIG_NFS_V4) */
+
 #ifdef CONFIG_NFSD_V3
 /*
  * Check server access rights to a file system object
@@ -376,12 +559,13 @@ static struct accessmap	nfs3_anyaccess[] = {
 	 * to the server to check for access for things like /dev/null
 	 * (which really, the server doesn't care about).  So
 	 * We provide simple access checking for them, looking
-	 * mainly at mode bits
+	 * mainly at mode bits, and we make sure to ignore read-only
+	 * filesystem checks
 	 */
     {	NFS3_ACCESS_READ,	MAY_READ			},
     {	NFS3_ACCESS_EXECUTE,	MAY_EXEC			},
-    {	NFS3_ACCESS_MODIFY,	MAY_WRITE			},
-    {	NFS3_ACCESS_EXTEND,	MAY_WRITE			},
+    {	NFS3_ACCESS_MODIFY,	MAY_WRITE|MAY_LOCAL_ACCESS	},
+    {	NFS3_ACCESS_EXTEND,	MAY_WRITE|MAY_LOCAL_ACCESS	},
 
     {	0,			0				}
 };
@@ -454,7 +638,7 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *suppor
  */
 int
 nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
-			int access, struct file *filp)
+			int access, struct file **filp)
 {
 	struct dentry	*dentry;
 	struct inode	*inode;
@@ -485,26 +669,18 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
 	 * Check to see if there are any leases on this file.
 	 * This may block while leases are broken.
 	 */
-	err = break_lease(inode, (access & MAY_WRITE) ? FMODE_WRITE : 0);
-	if (err)
+	err = break_lease(inode, O_NONBLOCK | ((access & MAY_WRITE) ? FMODE_WRITE : 0));
+	if (err) /* NOMEM or WOULDBLOCK */
 		goto out_nfserr;
 
 	if (access & MAY_WRITE) {
-		err = get_write_access(inode);
-		if (err)
-			goto out_nfserr;
-
 		flags = O_WRONLY|O_LARGEFILE;
 
 		DQUOT_INIT(inode);
 	}
-
-	err = open_private_file(filp, dentry, flags);
-	if (!err) {
-		filp->f_vfsmnt = fhp->fh_export->ex_mnt;
-	} else if (access & MAY_WRITE)
-		put_write_access(inode);
-
+	*filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_mnt), flags);
+	if (IS_ERR(*filp))
+		err = PTR_ERR(*filp);
 out_nfserr:
 	if (err)
 		err = nfserrno(err);
@@ -518,12 +694,7 @@ out:
 void
 nfsd_close(struct file *filp)
 {
-	struct dentry	*dentry = filp->f_dentry;
-	struct inode	*inode = dentry->d_inode;
-
-	close_private_file(filp);
-	if (filp->f_mode & FMODE_WRITE)
-		put_write_access(inode);
+	fput(filp);
 }
 
 /*
@@ -567,7 +738,7 @@ nfsd_sync_dir(struct dentry *dp)
 static spinlock_t ra_lock = SPIN_LOCK_UNLOCKED;
 
 static inline struct raparms *
-nfsd_get_raparms(dev_t dev, ino_t ino, struct address_space *mapping)
+nfsd_get_raparms(dev_t dev, ino_t ino)
 {
 	struct raparms	*ra, **rap, **frap = NULL;
 	int depth = 0;
@@ -589,7 +760,7 @@ nfsd_get_raparms(dev_t dev, ino_t ino, struct address_space *mapping)
 	ra = *frap;
 	ra->p_dev = dev;
 	ra->p_ino = ino;
-	file_ra_state_init(&ra->p_ra, mapping);
+	ra->p_set = 0;
 found:
 	if (rap != &raparm_cache) {
 		*rap = ra->p_next;
@@ -646,14 +817,14 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
 	struct raparms	*ra;
 	mm_segment_t	oldfs;
 	int		err;
-	struct file	file;
+	struct file	*file;
 	struct inode	*inode;
 
 	err = nfsd_open(rqstp, fhp, S_IFREG, MAY_READ, &file);
 	if (err)
 		goto out;
 	err = nfserr_perm;
-	inode = file.f_dentry->d_inode;
+	inode = file->f_dentry->d_inode;
 #ifdef MSNFS
 	if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
 		(!lock_may_read(inode, offset, *count)))
@@ -661,38 +832,40 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
 #endif
 
 	/* Get readahead parameters */
-	ra = nfsd_get_raparms(inode->i_sb->s_dev, inode->i_ino,
-			      inode->i_mapping->host->i_mapping);
-	if (ra)
-		file.f_ra = ra->p_ra;
+	ra = nfsd_get_raparms(inode->i_sb->s_dev, inode->i_ino);
 
-	if (file.f_op->sendfile) {
+	if (ra && ra->p_set)
+		file->f_ra = ra->p_ra;
+
+	if (file->f_op->sendfile) {
 		svc_pushback_unused_pages(rqstp);
-		err = file.f_op->sendfile(&file, &offset, *count,
+		err = file->f_op->sendfile(file, &offset, *count,
 						 nfsd_read_actor, rqstp);
 	} else {
 		oldfs = get_fs();
 		set_fs(KERNEL_DS);
-		err = vfs_readv(&file, (struct iovec __user *)vec, vlen, &offset);
+		err = vfs_readv(file, (struct iovec __user *)vec, vlen, &offset);
 		set_fs(oldfs);
 	}
 
 	/* Write back readahead params */
 	if (ra) {
 		spin_lock(&ra_lock);
-		ra->p_ra = file.f_ra;
+		ra->p_ra = file->f_ra;
+		ra->p_set = 1;
 		ra->p_count--;
 		spin_unlock(&ra_lock);
 	}
+
 	if (err >= 0) {
 		nfsdstats.io_read += err;
 		*count = err;
 		err = 0;
-		dnotify_parent(file.f_dentry, DN_ACCESS);
+		dnotify_parent(file->f_dentry, DN_ACCESS);
 	} else 
 		err = nfserrno(err);
 out_close:
-	nfsd_close(&file);
+	nfsd_close(file);
 out:
 	return err;
 }
@@ -708,7 +881,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
 	   			unsigned long cnt, int *stablep)
 {
 	struct svc_export	*exp;
-	struct file		file;
+	struct file		*file;
 	struct dentry		*dentry;
 	struct inode		*inode;
 	mm_segment_t		oldfs;
@@ -724,11 +897,11 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
 
 #ifdef MSNFS
 	if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
-		(!lock_may_write(file.f_dentry->d_inode, offset, cnt)))
+		(!lock_may_write(file->f_dentry->d_inode, offset, cnt)))
 		goto out_close;
 #endif
 
-	dentry = file.f_dentry;
+	dentry = file->f_dentry;
 	inode = dentry->d_inode;
 	exp   = fhp->fh_export;
 
@@ -741,7 +914,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
 	 * flushing the data to disk is handled separately below.
 	 */
 
-	if (file.f_op->fsync == 0) {/* COMMIT3 cannot work */
+	if (file->f_op->fsync == 0) {/* COMMIT3 cannot work */
 	       stable = 2;
 	       *stablep = 2; /* FILE_SYNC */
 	}
@@ -749,15 +922,15 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
 	if (!EX_ISSYNC(exp))
 		stable = 0;
 	if (stable && !EX_WGATHER(exp))
-		file.f_flags |= O_SYNC;
+		file->f_flags |= O_SYNC;
 
 	/* Write the data. */
 	oldfs = get_fs(); set_fs(KERNEL_DS);
-	err = vfs_writev(&file, (struct iovec __user *)vec, vlen, &offset);
+	err = vfs_writev(file, (struct iovec __user *)vec, vlen, &offset);
 	set_fs(oldfs);
 	if (err >= 0) {
 		nfsdstats.io_write += cnt;
-		dnotify_parent(file.f_dentry, DN_MODIFY);
+		dnotify_parent(file->f_dentry, DN_MODIFY);
 	}
 
 	/* clear setuid/setgid flag after write */
@@ -797,7 +970,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
 
 			if (inode->i_state & I_DIRTY) {
 				dprintk("nfsd: write sync %d\n", current->pid);
-				nfsd_sync(&file);
+				nfsd_sync(file);
 			}
 #if 0
 			wake_up(&inode->i_wait);
@@ -813,7 +986,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
 	else 
 		err = nfserrno(err);
 out_close:
-	nfsd_close(&file);
+	nfsd_close(file);
 out:
 	return err;
 }
@@ -832,7 +1005,7 @@ int
 nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
                loff_t offset, unsigned long count)
 {
-	struct file	file;
+	struct file	*file;
 	int		err;
 
 	if ((u64)count > ~(u64)offset)
@@ -841,14 +1014,14 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
 	if ((err = nfsd_open(rqstp, fhp, S_IFREG, MAY_WRITE, &file)) != 0)
 		return err;
 	if (EX_ISSYNC(fhp->fh_export)) {
-		if (file.f_op && file.f_op->fsync) {
-			nfsd_sync(&file);
+		if (file->f_op && file->f_op->fsync) {
+			nfsd_sync(file);
 		} else {
 			err = nfserr_notsupp;
 		}
 	}
 
-	nfsd_close(&file);
+	nfsd_close(file);
 	return err;
 }
 #endif /* CONFIG_NFSD_V3 */
@@ -1471,14 +1644,14 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp,
 	     struct readdir_cd *cdp, encode_dent_fn func)
 {
 	int		err;
-	struct file	file;
+	struct file	*file;
 	loff_t		offset = *offsetp;
 
 	err = nfsd_open(rqstp, fhp, S_IFDIR, MAY_READ, &file);
 	if (err)
 		goto out;
 
-	offset = vfs_llseek(&file, offset, 0);
+	offset = vfs_llseek(file, offset, 0);
 	if (offset < 0) {
 		err = nfserrno((int)offset);
 		goto out_close;
@@ -1492,18 +1665,18 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t *offsetp,
 
 	do {
 		cdp->err = nfserr_eof; /* will be cleared on successful read */
-		err = vfs_readdir(&file, (filldir_t) func, cdp);
+		err = vfs_readdir(file, (filldir_t) func, cdp);
 	} while (err >=0 && cdp->err == nfs_ok);
 	if (err)
 		err = nfserrno(err);
 	else
 		err = cdp->err;
-	*offsetp = vfs_llseek(&file, 0, 1);
+	*offsetp = vfs_llseek(file, 0, 1);
 
 	if (err == nfserr_eof || err == nfserr_toosmall)
 		err = nfs_ok; /* can still be found in ->err */
 out_close:
-	nfsd_close(&file);
+	nfsd_close(file);
 out:
 	return err;
 }
diff --git a/fs/nls/nls_cp932.c b/fs/nls/nls_cp932.c
index af796a763..e5d10162a 100644
--- a/fs/nls/nls_cp932.c
+++ b/fs/nls/nls_cp932.c
@@ -1619,6 +1619,33 @@ static wchar_t *page_charset2uni[256] = {
 	NULL,   NULL,   c2u_FA, c2u_FB, c2u_FC, NULL,   NULL,   NULL,   
 };
 
+static unsigned char u2c_00hi[256 - 0xA0][2] = {
+	{0x00, 0x00}, {0x00, 0x00}, {0x81, 0x91}, {0x81, 0x92},/* 0xA0-0xA3 */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x81, 0x98},/* 0xA4-0xA7 */
+	{0x81, 0x4E}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xA8-0xAB */
+	{0x81, 0xCA}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xAC-0xAF */
+	{0x81, 0x8B}, {0x81, 0x7D}, {0x00, 0x00}, {0x00, 0x00},/* 0xB0-0xB3 */
+	{0x81, 0x4C}, {0x00, 0x00}, {0x81, 0xF7}, {0x00, 0x00},/* 0xB4-0xB7 */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xB8-0xBB */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xBC-0xBF */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xC0-0xC3 */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xC4-0xC7 */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xC8-0xCB */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xCC-0xCF */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xD0-0xD3 */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x81, 0x7E},/* 0xD4-0xD7 */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xD8-0xDB */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xDC-0xDF */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xE0-0xE3 */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xE4-0xE7 */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xE8-0xEB */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xEC-0xEF */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xF0-0xF3 */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x81, 0x80},/* 0xF4-0xF7 */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xF8-0xFB */
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},/* 0xFC-0xFF */
+};
+
 static unsigned char u2c_03[512] = {
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x03 */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x04-0x07 */
@@ -7708,7 +7735,7 @@ static unsigned char u2c_FF[512] = {
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xD4-0xD7 */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xD8-0xDB */
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xDC-0xDF */
-	0x81, 0x91, 0x81, 0x92, 0xEE, 0xF9, 0x81, 0x50, /* 0xE0-0xE3 */
+	0x81, 0x91, 0x81, 0x92, 0x81, 0xCA, 0x81, 0x50, /* 0xE0-0xE3 */
 	0xEE, 0xFA, 0x81, 0x8F, 0x00, 0x00, 0x00, 0x00, /* 0xE4-0xE7 */
 };
 
@@ -7842,9 +7869,17 @@ static int uni2char(const wchar_t uni,
 		if (out[0] == 0x00 && out[1] == 0x00)
 			return -EINVAL;
 		return 2;
-	} else if ((ch == 0) && (cl <= 0x7F)) {
-		out[0] = cl;
-		return 1;
+	} else if (ch == 0) {
+		if (cl <= 0x7F) {
+			out[0] = cl;
+			return 1;
+		} else if (0xA0 <= cl) {
+			out[0] = u2c_00hi[cl - 0xA0][0];
+			out[1] = u2c_00hi[cl - 0xA0][1];
+			if (out[0] && out[1])
+				return 2;
+		}
+		return -EINVAL;
 	}
 	else
 		return -EINVAL;
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
index fa1442d2f..0302c3512 100644
--- a/fs/ntfs/ChangeLog
+++ b/fs/ntfs/ChangeLog
@@ -1,11 +1,6 @@
 ToDo/Notes:
 	- Find and fix bugs.
 	- Checkpoint or disable the user space journal ($UsnJrnl).
-	- Implement sops->dirty_inode() to implement {a,m,c}time updates and
-	  such things.  This should probably just flag the ntfs inode such that
-	  sops->write_inode(), i.e. ntfs_write_inode(), will copy the times
-	  when it is invoked rather than having to update the mft record
-	  every time.
 	- In between ntfs_prepare/commit_write, need exclusion between
 	  simultaneous file extensions. Need perhaps an NInoResizeUnderway()
 	  flag which we can set in ntfs_prepare_write() and clear again in
@@ -26,6 +21,114 @@ ToDo/Notes:
 	- Enable the code for setting the NT4 compatibility flag when we start
 	  making NTFS 1.2 specific modifications.
 
+2.1.20 - Fix a stupid bug in ntfs_attr_reinit_search_ctx().
+
+	- Fix stupid bug in fs/ntfs/attrib.c::ntfs_attr_reinit_search_ctx()
+	  where we did not clear ctx->al_entry but it was still set due to
+	  changes in ntfs_attr_lookup() and ntfs_external_attr_find() in
+	  particular.
+	- Fix another stupid bug in fs/ntfs/attrib.c::ntfs_external_attr_find()
+	  where we forgot to unmap the extent mft record when we had finished
+	  enumerating an attribute which caused a bug check to trigger when the
+	  VFS calls ->clear_inode.
+
+2.1.19 - Many cleanups, improvements, and a minor bug fix.
+
+	- Update ->setattr (fs/ntfs/inode.c::ntfs_setattr()) to refuse to
+	  change the uid, gid, and mode of an inode as we do not support NTFS
+	  ACLs yet.
+	- Remove BKL use from ntfs_setattr() syncing up with the rest of the
+	  kernel.
+	- Get rid of the ugly transparent union in fs/ntfs/dir.c::ntfs_readdir()
+	  and ntfs_filldir() as per suggestion from Al Viro.
+	- Change '\0' and L'\0' to simply 0 as per advice from Linus Torvalds.
+	- Update ->truncate (fs/ntfs/inode.c::ntfs_truncate()) to check if the
+	  inode size has changed and to only output an error if so.
+	- Rename fs/ntfs/attrib.h::attribute_value_length() to ntfs_attr_size().
+	- Add le{16,32,64} as well as sle{16,32,64} data types to
+	  fs/ntfs/types.h.
+	- Change ntfschar to be le16 instead of u16 in fs/ntfs/types.h.
+	- Add le versions of VCN, LCN, and LSN called leVCN, leLCN, and leLSN,
+	  respectively, to fs/ntfs/types.h.
+	- Update endianness conversion macros in fs/ntfs/endian.h to use the
+	  new types as appropriate.
+	- Do proper type casting when using sle64_to_cpup() in fs/ntfs/dir.c
+	  and index.c.
+	- Add leMFT_REF data type to fs/ntfs/layout.h.
+	- Update all NTFS header files with the new little endian data types.
+	  Affected files are fs/ntfs/layout.h, logfile.h, and time.h.
+	- Do proper type casting when using ntfs_is_*_recordp() in
+	  fs/ntfs/logfile.c, mft.c, and super.c. 
+	- Fix all the sparse bitwise warnings.  Had to change all the typedef
+	  enums storing little endian values to simple enums plus a typedef for
+	  the datatype to make sparse happy.
+	- Fix a bug found by the new sparse bitwise warnings where the default
+	  upcase table was defined as a pointer to wchar_t rather than ntfschar
+	  in fs/ntfs/ntfs.h and super.c.
+	- Change {const_,}cpu_to_le{16,32}(0) to just 0 as suggested by Al Viro.
+
+2.1.18 - Fix scheduling latencies at mount time as well as an endianness bug.
+
+	- Remove vol->nr_mft_records as it was pretty meaningless and optimize
+	  the calculation of total/free inodes as used by statfs().
+	- Fix scheduling latencies in ntfs_fill_super() by dropping the BKL
+	  because the code itself is using the ntfs_lock semaphore which
+	  provides safe locking.  (Ingo Molnar)
+	- Fix a potential bug in fs/ntfs/mft.c::map_extent_mft_record() that
+	  could occur in the future for when we start closing/freeing extent
+	  inodes if we don't set base_ni->ext.extent_ntfs_inos to NULL after
+	  we free it.
+	- Rename {find,lookup}_attr() to ntfs_attr_{find,lookup}() as well as
+	  find_external_attr() to ntfs_external_attr_find() to cleanup the
+	  namespace a bit and to be more consistent with libntfs.
+	- Rename {{re,}init,get,put}_attr_search_ctx() to
+	  ntfs_attr_{{re,}init,get,put}_search_ctx() as well as the type
+	  attr_search_context to ntfs_attr_search_ctx.
+	- Force use of ntfs_attr_find() in ntfs_attr_lookup() when searching
+	  for the attribute list attribute itself.
+	- Fix endianness bug in ntfs_external_attr_find().
+	- Change ntfs_{external_,}attr_find() to return 0 on success, -ENOENT
+	  if the attribute is not found, and -EIO on real error.  In the case
+	  of -ENOENT, the search context is updated to describe the attribute
+	  before which the attribute being searched for would need to be
+	  inserted if such an action were to be desired and in the case of
+	  ntfs_external_attr_find() the search context is also updated to
+	  indicate the attribute list entry before which the attribute list
+	  entry of the attribute being searched for would need to be inserted
+	  if such an action were to be desired.  Also make ntfs_find_attr()
+	  static and remove its prototype from attrib.h as it is not used
+	  anywhere other than attrib.c.  Update ntfs_attr_lookup() and all
+	  callers of ntfs_{external,}attr_{find,lookup}() for the new return
+	  values.
+	- Minor cleanup of fs/ntfs/inode.c::ntfs_init_locked_inode().
+
+2.1.17 - Fix bugs in mount time error code paths and other updates.
+
+	- Implement bitmap modification code (fs/ntfs/bitmap.[hc]).  This
+	  includes functions to set/clear a single bit or a run of bits.
+	- Add fs/ntfs/attrib.[hc]::ntfs_find_vcn() which returns the locked
+	  runlist element containing a particular vcn.  It also takes care of
+	  mapping any needed runlist fragments.
+	- Implement cluster (de-)allocation code (fs/ntfs/lcnalloc.[hc]).
+	- Load attribute definition table from $AttrDef at mount time.
+	- Fix bugs in mount time error code paths involving (de)allocation of
+	  the default and volume upcase tables.
+	- Remove ntfs_nr_mounts as it is no longer used.
+
+2.1.16 - Implement access time updates, file sync, async io, and read/writev.
+
+	- Add support for readv/writev and aio_read/aio_write (fs/ntfs/file.c).
+	  This is done by setting the appropriate file operations pointers to
+	  the generic helper functions provided by mm/filemap.c.
+	- Implement fsync, fdatasync, and msync both for files (fs/ntfs/file.c)
+	  and directories (fs/ntfs/dir.c).
+	- Add support for {a,m,c}time updates to inode.c::ntfs_write_inode().
+	  Note, except for the root directory and any other system files opened
+	  by the user, the system files will not have their access times
+	  updated as they are only accessed at the inode level an hence the
+	  file level functions which cause the times to be updated are never
+	  invoked.
+
 2.1.15 - Invalidate quotas when (re)mounting read-write.
 
 	- Add new element itype.index.collation_rule to the ntfs inode
@@ -434,7 +537,7 @@ ToDo/Notes:
 	  cannot set any write related options when the driver is compiled
 	  read-only.
 	- Optimize block resolution in fs/ntfs/aops.c::ntfs_read_block() to
-	  cache the current run list element. This should improve performance
+	  cache the current runlist element. This should improve performance
 	  when reading very large and/or very fragmented data.
 
 2.0.16 - Convert access to $MFT/$BITMAP to attribute inode API.
@@ -482,9 +585,9 @@ ToDo/Notes:
 	- Change fs/ntfs/super.c::ntfs_statfs() to not rely on BKL by moving
 	  the locking out of super.c::get_nr_free_mft_records() and taking and
 	  dropping the mftbmp_lock rw_semaphore in ntfs_statfs() itself.
-	- Bring attribute run list merging code (fs/ntfs/attrib.c) in sync with
+	- Bring attribute runlist merging code (fs/ntfs/attrib.c) in sync with
 	  current userspace ntfs library code. This means that if a merge
-	  fails the original run lists are always left unmodified instead of
+	  fails the original runlists are always left unmodified instead of
 	  being silently corrupted.
 	- Misc typo fixes.
 
@@ -676,7 +779,7 @@ ToDo/Notes:
 	  appropriately.
 	- Update to 2.5.9 kernel (preserving backwards compatibility) by
 	  replacing all occurences of page->buffers with page_buffers(page).
-	- Fix minor bugs in run list merging, also minor cleanup.
+	- Fix minor bugs in runlist merging, also minor cleanup.
 	- Updates to bootsector layout and mft mirror contents descriptions.
 	- Small bug fix in error detection in unistr.c and some cleanups.
 	- Grow name buffer allocations in unistr.c in aligned mutlipled of 64
@@ -699,12 +802,12 @@ ToDo/Notes:
 	  initialized_size vs data_size (i.e. i_size). Done are
 	  mft.c::ntfs_mft_readpage(), aops.c::end_buffer_read_index_async(),
 	  and attrib.c::load_attribute_list().
-	- Lock the run list in attrib.c::load_attribute_list() while using it.
+	- Lock the runlist in attrib.c::load_attribute_list() while using it.
 	- Fix memory leak in ntfs_file_read_compressed_block() and generally
 	  clean up compress.c a little, removing some uncommented/unused debug
 	  code.
 	- Tidy up dir.c a little bit.
-	- Don't bother getting the run list in inode.c::ntfs_read_inode().
+	- Don't bother getting the runlist in inode.c::ntfs_read_inode().
 	- Merge mft.c::ntfs_mft_readpage() and aops.c::ntfs_index_readpage()
 	  creating aops.c::ntfs_mst_readpage(), improving the handling of
 	  holes and overflow in the process and implementing the correct
@@ -734,7 +837,7 @@ tng-0.0.8 - 08/03/2002 - Now using BitKeeper, http://linux-ntfs.bkbits.net/
 	- Apply kludge in ntfs_read_inode(), setting i_nlink to 1 for
 	  directories. Without this the "find" utility gets very upset which is
 	  fair enough as Linux/Unix do not support directory hard links.
-	- Further run list merging work. (Richard Russon)
+	- Further runlist merging work. (Richard Russon)
 	- Backwards compatibility for gcc-2.95. (Richard Russon)
 	- Update to kernel 2.5.5-pre1 and rediff the now tiny patch.
 	- Convert to new file system declaration using ->ntfs_get_sb() and
@@ -789,7 +892,7 @@ tng-0.0.8 - 08/03/2002 - Now using BitKeeper, http://linux-ntfs.bkbits.net/
 	  which is then referenced but not copied.
 	- Rename run_list structure to run_list_element and create a new
 	  run_list structure containing a pointer to a run_list_element
-	  structure and a read/write semaphore. Adapt all users of run lists
+	  structure and a read/write semaphore. Adapt all users of runlists
 	  to new scheme and take and release the lock as needed. This fixes a
 	  nasty race as the run_list changes even when inodes are locked for
 	  reading and even when the inode isn't locked at all, so we really
@@ -820,7 +923,7 @@ tng-0.0.7 - 13/02/2002 - The driver is now feature complete for read-only!
 	- Cleanup mft.c and it's debug/error output in particular. Fix a minor
 	  bug in mapping of extent inodes. Update all the comments to fit all
 	  the recent code changes.
-	- Modify vcn_to_lcn() to cope with entirely unmapped run lists.
+	- Modify vcn_to_lcn() to cope with entirely unmapped runlists.
 	- Cleanups in compress.c, mostly comments and folding help.
 	- Implement attrib.c::map_run_list() as a generic helper.
 	- Make compress.c::ntfs_file_read_compressed_block() use map_run_list()
@@ -846,11 +949,11 @@ tng-0.0.7 - 13/02/2002 - The driver is now feature complete for read-only!
 	  pass in the upcase table and its length. These can be gotten from
 	  ctx->ntfs_ino->vol->upcase{_len}. Update all callers.
 	- Cleanups in attrib.c.
-	- Implement merging of run lists, attrib.c::merge_run_lists() and its
+	- Implement merging of runlists, attrib.c::merge_run_lists() and its
 	  helpers. (Richard Russon)
-	- Attribute lists part 2, attribute extents and multi part run lists:
+	- Attribute lists part 2, attribute extents and multi part runlists:
 	  enable proper support for LCN_RL_NOT_MAPPED and automatic mapping of
-	  further run list parts via attrib.c::map_run_list().
+	  further runlist parts via attrib.c::map_run_list().
 	- Tiny endianness bug fix in decompress_mapping_pairs().
 
 tng-0.0.6 - Encrypted directories, bug fixes, cleanups, debugging enhancements.
@@ -882,7 +985,7 @@ tng-0.0.6 - Encrypted directories, bug fixes, cleanups, debugging enhancements.
 	  support dollar signs in the names of variables/constants. Attribute
 	  types now start with AT_ instead of $ and $I30 is now just I30.
 	- Cleanup ntfs_lookup() and add consistency check of sequence numbers.
-	- Load complete run list for $MFT/$BITMAP during mount and cleanup
+	- Load complete runlist for $MFT/$BITMAP during mount and cleanup
 	  access functions. This means we now cope with $MFT/$BITMAP being
 	  spread accross several mft records.
 	- Disable modification of mft_zone_multiplier on remount. We can always
@@ -915,11 +1018,11 @@ tng-0.0.4 - Big changes, getting in line with Al Viro's comments.
 	  parameter list. Pass either READ or WRITE to this, each has the
 	  obvious meaning.
 	- General cleanups to allow for easier folding in vi.
-	- attrib.c::decompress_mapping_pairs() now accepts the old run list
+	- attrib.c::decompress_mapping_pairs() now accepts the old runlist
 	  argument, and invokes attrib.c::merge_run_lists() to merge the old
-	  and the new run lists.
+	  and the new runlists.
 	- Removed attrib.c::find_first_attr().
-	- Implemented loading of attribute list and complete run list for $MFT.
+	- Implemented loading of attribute list and complete runlist for $MFT.
 	  This means we now cope with $MFT being spread across several mft
 	  records.
 	- Adapt to 2.5.2-pre9 and the changed create_empty_buffers() syntax.
@@ -957,7 +1060,7 @@ tng-0.0.4 - Big changes, getting in line with Al Viro's comments.
 tng-0.0.3 - Cleanups, enhancements, bug fixes.
 
 	- Work on attrib.c::decompress_mapping_pairs() to detect base extents
-	  and setup the run list appropriately using knowledge provided by the
+	  and setup the runlist appropriately using knowledge provided by the
 	  sizes in the base attribute record.
 	- Balance the get_/put_attr_search_ctx() calls so we don't leak memory
 	  any more.
diff --git a/fs/ntfs/Makefile b/fs/ntfs/Makefile
index 0e3fd2f01..28e8ac163 100644
--- a/fs/ntfs/Makefile
+++ b/fs/ntfs/Makefile
@@ -6,7 +6,7 @@ ntfs-objs := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \
 	     index.o inode.o mft.o mst.o namei.o super.o sysctl.o unistr.o \
 	     upcase.o
 
-EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.15\"
+EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.20\"
 
 ifeq ($(CONFIG_NTFS_DEBUG),y)
 EXTRA_CFLAGS += -DDEBUG
@@ -15,5 +15,5 @@ endif
 ifeq ($(CONFIG_NTFS_RW),y)
 EXTRA_CFLAGS += -DNTFS_RW
 
-ntfs-objs += logfile.o quota.o
+ntfs-objs += bitmap.o lcnalloc.o logfile.o quota.o
 endif
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
index 0ffc1d19c..edcc9fbf6 100644
--- a/fs/ntfs/aops.c
+++ b/fs/ntfs/aops.c
@@ -170,7 +170,7 @@ static int ntfs_read_block(struct page *page)
 	LCN lcn;
 	ntfs_inode *ni;
 	ntfs_volume *vol;
-	run_list_element *rl;
+	runlist_element *rl;
 	struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
 	sector_t iblock, lblock, zblock;
 	unsigned int blocksize, vcn_ofs;
@@ -196,8 +196,8 @@ static int ntfs_read_block(struct page *page)
 	zblock = (ni->initialized_size + blocksize - 1) >> blocksize_bits;
 
 #ifdef DEBUG
-	if (unlikely(!ni->run_list.rl && !ni->mft_no && !NInoAttr(ni)))
-		panic("NTFS: $MFT/$DATA run list has been unmapped! This is a "
+	if (unlikely(!ni->runlist.rl && !ni->mft_no && !NInoAttr(ni)))
+		panic("NTFS: $MFT/$DATA runlist has been unmapped! This is a "
 				"very serious bug! Cannot continue...");
 #endif
 
@@ -225,14 +225,14 @@ static int ntfs_read_block(struct page *page)
 					vol->cluster_size_mask;
 			if (!rl) {
 lock_retry_remap:
-				down_read(&ni->run_list.lock);
-				rl = ni->run_list.rl;
+				down_read(&ni->runlist.lock);
+				rl = ni->runlist.rl;
 			}
 			if (likely(rl != NULL)) {
 				/* Seek to element containing target vcn. */
 				while (rl->length && rl[1].vcn <= vcn)
 					rl++;
-				lcn = vcn_to_lcn(rl, vcn);
+				lcn = ntfs_vcn_to_lcn(rl, vcn);
 			} else
 				lcn = (LCN)LCN_RL_NOT_MAPPED;
 			/* Successful remap. */
@@ -252,29 +252,29 @@ lock_retry_remap:
 			/* It is a hole, need to zero it. */
 			if (lcn == LCN_HOLE)
 				goto handle_hole;
-			/* If first try and run list unmapped, map and retry. */
+			/* If first try and runlist unmapped, map and retry. */
 			if (!is_retry && lcn == LCN_RL_NOT_MAPPED) {
 				is_retry = TRUE;
 				/*
-				 * Attempt to map run list, dropping lock for
+				 * Attempt to map runlist, dropping lock for
 				 * the duration.
 				 */
-				up_read(&ni->run_list.lock);
-				if (!map_run_list(ni, vcn))
+				up_read(&ni->runlist.lock);
+				if (!ntfs_map_runlist(ni, vcn))
 					goto lock_retry_remap;
 				rl = NULL;
 			}
 			/* Hard error, zero out region. */
 			SetPageError(page);
-			ntfs_error(vol->sb, "vcn_to_lcn(vcn = 0x%llx) failed "
-					"with error code 0x%llx%s.",
+			ntfs_error(vol->sb, "ntfs_vcn_to_lcn(vcn = 0x%llx) "
+					"failed with error code 0x%llx%s.",
 					(unsigned long long)vcn,
 					(unsigned long long)-lcn,
 					is_retry ? " even after retrying" : "");
 			// FIXME: Depending on vol->on_errors, do something.
 		}
 		/*
-		 * Either iblock was outside lblock limits or vcn_to_lcn()
+		 * Either iblock was outside lblock limits or ntfs_vcn_to_lcn()
 		 * returned error. Just zero that portion of the page and set
 		 * the buffer uptodate.
 		 */
@@ -291,7 +291,7 @@ handle_zblock:
 
 	/* Release the lock if we took it. */
 	if (rl)
-		up_read(&ni->run_list.lock);
+		up_read(&ni->runlist.lock);
 
 	/* Check we have at least one buffer ready for i/o. */
 	if (nr) {
@@ -348,7 +348,7 @@ int ntfs_readpage(struct file *file, struct page *page)
 	s64 attr_pos;
 	ntfs_inode *ni, *base_ni;
 	u8 *kaddr;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	MFT_RECORD *mrec;
 	u32 attr_len;
 	int err = 0;
@@ -393,20 +393,19 @@ int ntfs_readpage(struct file *file, struct page *page)
 
 	/* Map, pin, and lock the mft record. */
 	mrec = map_mft_record(base_ni);
-	if (unlikely(IS_ERR(mrec))) {
+	if (IS_ERR(mrec)) {
 		err = PTR_ERR(mrec);
 		goto err_out;
 	}
-	ctx = get_attr_search_ctx(base_ni, mrec);
+	ctx = ntfs_attr_get_search_ctx(base_ni, mrec);
 	if (unlikely(!ctx)) {
 		err = -ENOMEM;
 		goto unm_err_out;
 	}
-	if (unlikely(!lookup_attr(ni->type, ni->name, ni->name_len,
-			CASE_SENSITIVE, 0, NULL, 0, ctx))) {
-		err = -ENOENT;
+	err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
+			CASE_SENSITIVE, 0, NULL, 0, ctx);
+	if (unlikely(err))
 		goto put_unm_err_out;
-	}
 
 	/* Starting position of the page within the attribute value. */
 	attr_pos = page->index << PAGE_CACHE_SHIFT;
@@ -433,7 +432,7 @@ int ntfs_readpage(struct file *file, struct page *page)
 
 	SetPageUptodate(page);
 put_unm_err_out:
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 unm_err_out:
 	unmap_mft_record(base_ni);
 err_out:
@@ -473,7 +472,7 @@ static int ntfs_write_block(struct writeback_control *wbc, struct page *page)
 	struct inode *vi;
 	ntfs_inode *ni;
 	ntfs_volume *vol;
-	run_list_element *rl;
+	runlist_element *rl;
 	struct buffer_head *bh, *head;
 	unsigned int blocksize, vcn_ofs;
 	int err;
@@ -631,14 +630,14 @@ static int ntfs_write_block(struct writeback_control *wbc, struct page *page)
 				vol->cluster_size_mask;
 		if (!rl) {
 lock_retry_remap:
-			down_read(&ni->run_list.lock);
-			rl = ni->run_list.rl;
+			down_read(&ni->runlist.lock);
+			rl = ni->runlist.rl;
 		}
 		if (likely(rl != NULL)) {
 			/* Seek to element containing target vcn. */
 			while (rl->length && rl[1].vcn <= vcn)
 				rl++;
-			lcn = vcn_to_lcn(rl, vcn);
+			lcn = ntfs_vcn_to_lcn(rl, vcn);
 		} else
 			lcn = (LCN)LCN_RL_NOT_MAPPED;
 		/* Successful remap. */
@@ -659,22 +658,22 @@ lock_retry_remap:
 			err = -EOPNOTSUPP;
 			break;
 		}
-		/* If first try and run list unmapped, map and retry. */
+		/* If first try and runlist unmapped, map and retry. */
 		if (!is_retry && lcn == LCN_RL_NOT_MAPPED) {
 			is_retry = TRUE;
 			/*
-			 * Attempt to map run list, dropping lock for
+			 * Attempt to map runlist, dropping lock for
 			 * the duration.
 			 */
-			up_read(&ni->run_list.lock);
-			err = map_run_list(ni, vcn);
+			up_read(&ni->runlist.lock);
+			err = ntfs_map_runlist(ni, vcn);
 			if (likely(!err))
 				goto lock_retry_remap;
 			rl = NULL;
 		}
 		/* Failed to map the buffer, even after retrying. */
 		bh->b_blocknr = -1UL;
-		ntfs_error(vol->sb, "vcn_to_lcn(vcn = 0x%llx) failed "
+		ntfs_error(vol->sb, "ntfs_vcn_to_lcn(vcn = 0x%llx) failed "
 				"with error code 0x%llx%s.",
 				(unsigned long long)vcn,
 				(unsigned long long)-lcn,
@@ -687,7 +686,7 @@ lock_retry_remap:
 
 	/* Release the lock if we took it. */
 	if (rl)
-		up_read(&ni->run_list.lock);
+		up_read(&ni->runlist.lock);
 
 	/* For the error case, need to reset bh to the beginning. */
 	bh = head;
@@ -1030,7 +1029,7 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
 	struct inode *vi;
 	ntfs_inode *ni, *base_ni;
 	char *kaddr;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	MFT_RECORD *m;
 	u32 attr_len, bytes;
 	int err;
@@ -1111,22 +1110,21 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
 
 	/* Map, pin, and lock the mft record. */
 	m = map_mft_record(base_ni);
-	if (unlikely(IS_ERR(m))) {
+	if (IS_ERR(m)) {
 		err = PTR_ERR(m);
 		m = NULL;
 		ctx = NULL;
 		goto err_out;
 	}
-	ctx = get_attr_search_ctx(base_ni, m);
+	ctx = ntfs_attr_get_search_ctx(base_ni, m);
 	if (unlikely(!ctx)) {
 		err = -ENOMEM;
 		goto err_out;
 	}
-	if (unlikely(!lookup_attr(ni->type, ni->name, ni->name_len,
-			CASE_SENSITIVE, 0, NULL, 0, ctx))) {
-		err = -ENOENT;
+	err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
+			CASE_SENSITIVE, 0, NULL, 0, ctx);
+	if (unlikely(err))
 		goto err_out;
-	}
 
 	/* Starting position of the page within the attribute value. */
 	attr_pos = page->index << PAGE_CACHE_SHIFT;
@@ -1201,7 +1199,7 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
 	/* Mark the mft record dirty, so it gets written back. */
 	mark_mft_record_dirty(ctx->ntfs_ino);
 
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(base_ni);
 	return 0;
 err_out:
@@ -1221,7 +1219,7 @@ err_out:
 	}
 	unlock_page(page);
 	if (ctx)
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 	if (m)
 		unmap_mft_record(base_ni);
 	return err;
@@ -1240,7 +1238,7 @@ static int ntfs_prepare_nonresident_write(struct page *page,
 	struct inode *vi;
 	ntfs_inode *ni;
 	ntfs_volume *vol;
-	run_list_element *rl;
+	runlist_element *rl;
 	struct buffer_head *bh, *head, *wait[2], **wait_bh = wait;
 	unsigned int vcn_ofs, block_start, block_end, blocksize;
 	int err;
@@ -1397,14 +1395,14 @@ static int ntfs_prepare_nonresident_write(struct page *page,
 			is_retry = FALSE;
 			if (!rl) {
 lock_retry_remap:
-				down_read(&ni->run_list.lock);
-				rl = ni->run_list.rl;
+				down_read(&ni->runlist.lock);
+				rl = ni->runlist.rl;
 			}
 			if (likely(rl != NULL)) {
 				/* Seek to element containing target vcn. */
 				while (rl->length && rl[1].vcn <= vcn)
 					rl++;
-				lcn = vcn_to_lcn(rl, vcn);
+				lcn = ntfs_vcn_to_lcn(rl, vcn);
 			} else
 				lcn = (LCN)LCN_RL_NOT_MAPPED;
 			if (unlikely(lcn < 0)) {
@@ -1439,11 +1437,11 @@ lock_retry_remap:
 						lcn == LCN_RL_NOT_MAPPED) {
 					is_retry = TRUE;
 					/*
-					 * Attempt to map run list, dropping
+					 * Attempt to map runlist, dropping
 					 * lock for the duration.
 					 */
-					up_read(&ni->run_list.lock);
-					err = map_run_list(ni, vcn);
+					up_read(&ni->runlist.lock);
+					err = ntfs_map_runlist(ni, vcn);
 					if (likely(!err))
 						goto lock_retry_remap;
 					rl = NULL;
@@ -1453,9 +1451,9 @@ lock_retry_remap:
 				 * retrying.
 				 */
 				bh->b_blocknr = -1UL;
-				ntfs_error(vol->sb, "vcn_to_lcn(vcn = 0x%llx) "
-						"failed with error code "
-						"0x%llx%s.",
+				ntfs_error(vol->sb, "ntfs_vcn_to_lcn(vcn = "
+						"0x%llx) failed with error "
+						"code 0x%llx%s.",
 						(unsigned long long)vcn,
 						(unsigned long long)-lcn,
 						is_retry ? " even after "
@@ -1530,7 +1528,7 @@ lock_retry_remap:
 
 	/* Release the lock if we took it. */
 	if (rl) {
-		up_read(&ni->run_list.lock);
+		up_read(&ni->runlist.lock);
 		rl = NULL;
 	}
 
@@ -1576,7 +1574,7 @@ err_out:
 	if (is_retry)
 		flush_dcache_page(page);
 	if (rl)
-		up_read(&ni->run_list.lock);
+		up_read(&ni->runlist.lock);
 	return err;
 }
 
@@ -1683,9 +1681,9 @@ static int ntfs_prepare_write(struct file *file, struct page *page,
 	 * We thus defer the uptodate bringing of the page region outside the
 	 * region written to to ntfs_commit_write(). The reason for doing this
 	 * is that we save one round of:
-	 *	map_mft_record(), get_attr_search_ctx(), lookup_attr(),
-	 *	kmap_atomic(), kunmap_atomic(), put_attr_search_ctx(),
-	 *	unmap_mft_record().
+	 *	map_mft_record(), ntfs_attr_get_search_ctx(),
+	 *	ntfs_attr_lookup(), kmap_atomic(), kunmap_atomic(),
+	 *	ntfs_attr_put_search_ctx(), unmap_mft_record().
 	 * Which is obviously a very worthwhile save.
 	 *
 	 * Thus we just return success now...
@@ -1804,7 +1802,7 @@ static int ntfs_commit_write(struct file *file, struct page *page,
 	struct inode *vi;
 	ntfs_inode *ni, *base_ni;
 	char *kaddr, *kattr;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	MFT_RECORD *m;
 	u32 attr_len, bytes;
 	int err;
@@ -1885,22 +1883,21 @@ static int ntfs_commit_write(struct file *file, struct page *page,
 
 	/* Map, pin, and lock the mft record. */
 	m = map_mft_record(base_ni);
-	if (unlikely(IS_ERR(m))) {
+	if (IS_ERR(m)) {
 		err = PTR_ERR(m);
 		m = NULL;
 		ctx = NULL;
 		goto err_out;
 	}
-	ctx = get_attr_search_ctx(base_ni, m);
+	ctx = ntfs_attr_get_search_ctx(base_ni, m);
 	if (unlikely(!ctx)) {
 		err = -ENOMEM;
 		goto err_out;
 	}
-	if (unlikely(!lookup_attr(ni->type, ni->name, ni->name_len,
-			CASE_SENSITIVE, 0, NULL, 0, ctx))) {
-		err = -ENOENT;
+	err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
+			CASE_SENSITIVE, 0, NULL, 0, ctx);
+	if (unlikely(err))
 		goto err_out;
-	}
 
 	/* Starting position of the page within the attribute value. */
 	attr_pos = page->index << PAGE_CACHE_SHIFT;
@@ -1966,7 +1963,7 @@ static int ntfs_commit_write(struct file *file, struct page *page,
 	/* Mark the mft record dirty, so it gets written back. */
 	mark_mft_record_dirty(ctx->ntfs_ino);
 
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(base_ni);
 	ntfs_debug("Done.");
 	return 0;
@@ -1993,7 +1990,7 @@ err_out:
 		SetPageError(page);
 	}
 	if (ctx)
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 	if (m)
 		unmap_mft_record(base_ni);
 	return err;
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
index 55686f7bd..fdf20b85c 100644
--- a/fs/ntfs/attrib.c
+++ b/fs/ntfs/attrib.c
@@ -27,11 +27,11 @@
 /* Temporary helper functions -- might become macros */
 
 /**
- * ntfs_rl_mm - run_list memmove
+ * ntfs_rl_mm - runlist memmove
  *
- * It is up to the caller to serialize access to the run list @base.
+ * It is up to the caller to serialize access to the runlist @base.
  */
-static inline void ntfs_rl_mm(run_list_element *base, int dst, int src,
+static inline void ntfs_rl_mm(runlist_element *base, int dst, int src,
 		int size)
 {
 	if (likely((dst != src) && (size > 0)))
@@ -39,42 +39,42 @@ static inline void ntfs_rl_mm(run_list_element *base, int dst, int src,
 }
 
 /**
- * ntfs_rl_mc - run_list memory copy
+ * ntfs_rl_mc - runlist memory copy
  *
- * It is up to the caller to serialize access to the run lists @dstbase and
+ * It is up to the caller to serialize access to the runlists @dstbase and
  * @srcbase.
  */
-static inline void ntfs_rl_mc(run_list_element *dstbase, int dst,
-		run_list_element *srcbase, int src, int size)
+static inline void ntfs_rl_mc(runlist_element *dstbase, int dst,
+		runlist_element *srcbase, int src, int size)
 {
 	if (likely(size > 0))
 		memcpy(dstbase + dst, srcbase + src, size * sizeof(*dstbase));
 }
 
 /**
- * ntfs_rl_realloc - Reallocate memory for run_lists
- * @rl:		original run list
- * @old_size:	number of run list elements in the original run list @rl
- * @new_size:	number of run list elements we need space for
+ * ntfs_rl_realloc - Reallocate memory for runlists
+ * @rl:		original runlist
+ * @old_size:	number of runlist elements in the original runlist @rl
+ * @new_size:	number of runlist elements we need space for
  *
- * As the run_lists grow, more memory will be required.  To prevent the
+ * As the runlists grow, more memory will be required.  To prevent the
  * kernel having to allocate and reallocate large numbers of small bits of
  * memory, this function returns and entire page of memory.
  *
- * It is up to the caller to serialize access to the run list @rl.
+ * It is up to the caller to serialize access to the runlist @rl.
  *
  * N.B.  If the new allocation doesn't require a different number of pages in
  *       memory, the function will return the original pointer.
  *
  * On success, return a pointer to the newly allocated, or recycled, memory.
  * On error, return -errno. The following error codes are defined:
- *	-ENOMEM	- Not enough memory to allocate run list array.
+ *	-ENOMEM	- Not enough memory to allocate runlist array.
  *	-EINVAL	- Invalid parameters were passed in.
  */
-static inline run_list_element *ntfs_rl_realloc(run_list_element *rl,
+static inline runlist_element *ntfs_rl_realloc(runlist_element *rl,
 		int old_size, int new_size)
 {
-	run_list_element *new_rl;
+	runlist_element *new_rl;
 
 	old_size = PAGE_ALIGN(old_size * sizeof(*rl));
 	new_size = PAGE_ALIGN(new_size * sizeof(*rl));
@@ -95,20 +95,20 @@ static inline run_list_element *ntfs_rl_realloc(run_list_element *rl,
 }
 
 /**
- * ntfs_are_rl_mergeable - test if two run lists can be joined together
- * @dst:	original run list
- * @src:	new run list to test for mergeability with @dst
+ * ntfs_are_rl_mergeable - test if two runlists can be joined together
+ * @dst:	original runlist
+ * @src:	new runlist to test for mergeability with @dst
  *
- * Test if two run lists can be joined together. For this, their VCNs and LCNs
+ * Test if two runlists can be joined together. For this, their VCNs and LCNs
  * must be adjacent.
  *
- * It is up to the caller to serialize access to the run lists @dst and @src.
+ * It is up to the caller to serialize access to the runlists @dst and @src.
  *
- * Return: TRUE   Success, the run lists can be merged.
- *	   FALSE  Failure, the run lists cannot be merged.
+ * Return: TRUE   Success, the runlists can be merged.
+ *	   FALSE  Failure, the runlists cannot be merged.
  */
-static inline BOOL ntfs_are_rl_mergeable(run_list_element *dst,
-		run_list_element *src)
+static inline BOOL ntfs_are_rl_mergeable(runlist_element *dst,
+		runlist_element *src)
 {
 	BUG_ON(!dst);
 	BUG_ON(!src);
@@ -124,37 +124,37 @@ static inline BOOL ntfs_are_rl_mergeable(run_list_element *dst,
 }
 
 /**
- * __ntfs_rl_merge - merge two run lists without testing if they can be merged
- * @dst:	original, destination run list
- * @src:	new run list to merge with @dst
+ * __ntfs_rl_merge - merge two runlists without testing if they can be merged
+ * @dst:	original, destination runlist
+ * @src:	new runlist to merge with @dst
  *
- * Merge the two run lists, writing into the destination run list @dst. The
- * caller must make sure the run lists can be merged or this will corrupt the
- * destination run list.
+ * Merge the two runlists, writing into the destination runlist @dst. The
+ * caller must make sure the runlists can be merged or this will corrupt the
+ * destination runlist.
  *
- * It is up to the caller to serialize access to the run lists @dst and @src.
+ * It is up to the caller to serialize access to the runlists @dst and @src.
  */
-static inline void __ntfs_rl_merge(run_list_element *dst, run_list_element *src)
+static inline void __ntfs_rl_merge(runlist_element *dst, runlist_element *src)
 {
 	dst->length += src->length;
 }
 
 /**
- * ntfs_rl_merge - test if two run lists can be joined together and merge them
- * @dst:	original, destination run list
- * @src:	new run list to merge with @dst
+ * ntfs_rl_merge - test if two runlists can be joined together and merge them
+ * @dst:	original, destination runlist
+ * @src:	new runlist to merge with @dst
  *
- * Test if two run lists can be joined together. For this, their VCNs and LCNs
+ * Test if two runlists can be joined together. For this, their VCNs and LCNs
  * must be adjacent. If they can be merged, perform the merge, writing into
- * the destination run list @dst.
+ * the destination runlist @dst.
  *
- * It is up to the caller to serialize access to the run lists @dst and @src.
+ * It is up to the caller to serialize access to the runlists @dst and @src.
  *
- * Return: TRUE   Success, the run lists have been merged.
- *	   FALSE  Failure, the run lists cannot be merged and have not been
+ * Return: TRUE   Success, the runlists have been merged.
+ *	   FALSE  Failure, the runlists cannot be merged and have not been
  *		  modified.
  */
-static inline BOOL ntfs_rl_merge(run_list_element *dst, run_list_element *src)
+static inline BOOL ntfs_rl_merge(runlist_element *dst, runlist_element *src)
 {
 	BOOL merge = ntfs_are_rl_mergeable(dst, src);
 
@@ -164,31 +164,31 @@ static inline BOOL ntfs_rl_merge(run_list_element *dst, run_list_element *src)
 }
 
 /**
- * ntfs_rl_append - append a run list after a given element
- * @dst:	original run list to be worked on
+ * ntfs_rl_append - append a runlist after a given element
+ * @dst:	original runlist to be worked on
  * @dsize:	number of elements in @dst (including end marker)
- * @src:	run list to be inserted into @dst
+ * @src:	runlist to be inserted into @dst
  * @ssize:	number of elements in @src (excluding end marker)
- * @loc:	append the new run list @src after this element in @dst
+ * @loc:	append the new runlist @src after this element in @dst
  *
- * Append the run list @src after element @loc in @dst.  Merge the right end of
- * the new run list, if necessary. Adjust the size of the hole before the
- * appended run list.
+ * Append the runlist @src after element @loc in @dst.  Merge the right end of
+ * the new runlist, if necessary. Adjust the size of the hole before the
+ * appended runlist.
  *
- * It is up to the caller to serialize access to the run lists @dst and @src.
+ * It is up to the caller to serialize access to the runlists @dst and @src.
  *
- * On success, return a pointer to the new, combined, run list. Note, both
- * run lists @dst and @src are deallocated before returning so you cannot use
- * the pointers for anything any more. (Strictly speaking the returned run list
+ * On success, return a pointer to the new, combined, runlist. Note, both
+ * runlists @dst and @src are deallocated before returning so you cannot use
+ * the pointers for anything any more. (Strictly speaking the returned runlist
  * may be the same as @dst but this is irrelevant.)
  *
- * On error, return -errno. Both run lists are left unmodified. The following
+ * On error, return -errno. Both runlists are left unmodified. The following
  * error codes are defined:
- *	-ENOMEM	- Not enough memory to allocate run list array.
+ *	-ENOMEM	- Not enough memory to allocate runlist array.
  *	-EINVAL	- Invalid parameters were passed in.
  */
-static inline run_list_element *ntfs_rl_append(run_list_element *dst,
-		int dsize, run_list_element *src, int ssize, int loc)
+static inline runlist_element *ntfs_rl_append(runlist_element *dst,
+		int dsize, runlist_element *src, int ssize, int loc)
 {
 	BOOL right;
 	int magic;
@@ -205,7 +205,7 @@ static inline run_list_element *ntfs_rl_append(run_list_element *dst,
 		return dst;
 	/*
 	 * We are guaranteed to succeed from here so can start modifying the
-	 * original run lists.
+	 * original runlists.
 	 */
 
 	/* First, merge the right hand end, if necessary. */
@@ -229,31 +229,31 @@ static inline run_list_element *ntfs_rl_append(run_list_element *dst,
 }
 
 /**
- * ntfs_rl_insert - insert a run list into another
- * @dst:	original run list to be worked on
+ * ntfs_rl_insert - insert a runlist into another
+ * @dst:	original runlist to be worked on
  * @dsize:	number of elements in @dst (including end marker)
- * @src:	new run list to be inserted
+ * @src:	new runlist to be inserted
  * @ssize:	number of elements in @src (excluding end marker)
- * @loc:	insert the new run list @src before this element in @dst
+ * @loc:	insert the new runlist @src before this element in @dst
  *
- * Insert the run list @src before element @loc in the run list @dst. Merge the
- * left end of the new run list, if necessary. Adjust the size of the hole
- * after the inserted run list.
+ * Insert the runlist @src before element @loc in the runlist @dst. Merge the
+ * left end of the new runlist, if necessary. Adjust the size of the hole
+ * after the inserted runlist.
  *
- * It is up to the caller to serialize access to the run lists @dst and @src.
+ * It is up to the caller to serialize access to the runlists @dst and @src.
  *
- * On success, return a pointer to the new, combined, run list. Note, both
- * run lists @dst and @src are deallocated before returning so you cannot use
- * the pointers for anything any more. (Strictly speaking the returned run list
+ * On success, return a pointer to the new, combined, runlist. Note, both
+ * runlists @dst and @src are deallocated before returning so you cannot use
+ * the pointers for anything any more. (Strictly speaking the returned runlist
  * may be the same as @dst but this is irrelevant.)
  *
- * On error, return -errno. Both run lists are left unmodified. The following
+ * On error, return -errno. Both runlists are left unmodified. The following
  * error codes are defined:
- *	-ENOMEM	- Not enough memory to allocate run list array.
+ *	-ENOMEM	- Not enough memory to allocate runlist array.
  *	-EINVAL	- Invalid parameters were passed in.
  */
-static inline run_list_element *ntfs_rl_insert(run_list_element *dst,
-		int dsize, run_list_element *src, int ssize, int loc)
+static inline runlist_element *ntfs_rl_insert(runlist_element *dst,
+		int dsize, runlist_element *src, int ssize, int loc)
 {
 	BOOL left = FALSE;
 	BOOL disc = FALSE;	/* Discontinuity */
@@ -290,7 +290,7 @@ static inline run_list_element *ntfs_rl_insert(run_list_element *dst,
 		return dst;
 	/*
 	 * We are guaranteed to succeed from here so can start modifying the
-	 * original run list.
+	 * original runlist.
 	 */
 
 	if (left)
@@ -336,30 +336,30 @@ static inline run_list_element *ntfs_rl_insert(run_list_element *dst,
 }
 
 /**
- * ntfs_rl_replace - overwrite a run_list element with another run list
- * @dst:	original run list to be worked on
+ * ntfs_rl_replace - overwrite a runlist element with another runlist
+ * @dst:	original runlist to be worked on
  * @dsize:	number of elements in @dst (including end marker)
- * @src:	new run list to be inserted
+ * @src:	new runlist to be inserted
  * @ssize:	number of elements in @src (excluding end marker)
- * @loc:	index in run list @dst to overwrite with @src
+ * @loc:	index in runlist @dst to overwrite with @src
  *
- * Replace the run list element @dst at @loc with @src. Merge the left and
- * right ends of the inserted run list, if necessary.
+ * Replace the runlist element @dst at @loc with @src. Merge the left and
+ * right ends of the inserted runlist, if necessary.
  *
- * It is up to the caller to serialize access to the run lists @dst and @src.
+ * It is up to the caller to serialize access to the runlists @dst and @src.
  *
- * On success, return a pointer to the new, combined, run list. Note, both
- * run lists @dst and @src are deallocated before returning so you cannot use
- * the pointers for anything any more. (Strictly speaking the returned run list
+ * On success, return a pointer to the new, combined, runlist. Note, both
+ * runlists @dst and @src are deallocated before returning so you cannot use
+ * the pointers for anything any more. (Strictly speaking the returned runlist
  * may be the same as @dst but this is irrelevant.)
  *
- * On error, return -errno. Both run lists are left unmodified. The following
+ * On error, return -errno. Both runlists are left unmodified. The following
  * error codes are defined:
- *	-ENOMEM	- Not enough memory to allocate run list array.
+ *	-ENOMEM	- Not enough memory to allocate runlist array.
  *	-EINVAL	- Invalid parameters were passed in.
  */
-static inline run_list_element *ntfs_rl_replace(run_list_element *dst,
-		int dsize, run_list_element *src, int ssize, int loc)
+static inline runlist_element *ntfs_rl_replace(runlist_element *dst,
+		int dsize, runlist_element *src, int ssize, int loc)
 {
 	BOOL left = FALSE;
 	BOOL right;
@@ -380,7 +380,7 @@ static inline run_list_element *ntfs_rl_replace(run_list_element *dst,
 		return dst;
 	/*
 	 * We are guaranteed to succeed from here so can start modifying the
-	 * original run lists.
+	 * original runlists.
 	 */
 	if (right)
 		__ntfs_rl_merge(src + ssize - 1, dst + loc + 1);
@@ -401,31 +401,31 @@ static inline run_list_element *ntfs_rl_replace(run_list_element *dst,
 }
 
 /**
- * ntfs_rl_split - insert a run list into the centre of a hole
- * @dst:	original run list to be worked on
+ * ntfs_rl_split - insert a runlist into the centre of a hole
+ * @dst:	original runlist to be worked on
  * @dsize:	number of elements in @dst (including end marker)
- * @src:	new run list to be inserted
+ * @src:	new runlist to be inserted
  * @ssize:	number of elements in @src (excluding end marker)
- * @loc:	index in run list @dst at which to split and insert @src
+ * @loc:	index in runlist @dst at which to split and insert @src
  *
- * Split the run list @dst at @loc into two and insert @new in between the two
- * fragments. No merging of run lists is necessary. Adjust the size of the
+ * Split the runlist @dst at @loc into two and insert @new in between the two
+ * fragments. No merging of runlists is necessary. Adjust the size of the
  * holes either side.
  *
- * It is up to the caller to serialize access to the run lists @dst and @src.
+ * It is up to the caller to serialize access to the runlists @dst and @src.
  *
- * On success, return a pointer to the new, combined, run list. Note, both
- * run lists @dst and @src are deallocated before returning so you cannot use
- * the pointers for anything any more. (Strictly speaking the returned run list
+ * On success, return a pointer to the new, combined, runlist. Note, both
+ * runlists @dst and @src are deallocated before returning so you cannot use
+ * the pointers for anything any more. (Strictly speaking the returned runlist
  * may be the same as @dst but this is irrelevant.)
  *
- * On error, return -errno. Both run lists are left unmodified. The following
+ * On error, return -errno. Both runlists are left unmodified. The following
  * error codes are defined:
- *	-ENOMEM	- Not enough memory to allocate run list array.
+ *	-ENOMEM	- Not enough memory to allocate runlist array.
  *	-EINVAL	- Invalid parameters were passed in.
  */
-static inline run_list_element *ntfs_rl_split(run_list_element *dst, int dsize,
-		run_list_element *src, int ssize, int loc)
+static inline runlist_element *ntfs_rl_split(runlist_element *dst, int dsize,
+		runlist_element *src, int ssize, int loc)
 {
 	BUG_ON(!dst);
 	BUG_ON(!src);
@@ -436,7 +436,7 @@ static inline run_list_element *ntfs_rl_split(run_list_element *dst, int dsize,
 		return dst;
 	/*
 	 * We are guaranteed to succeed from here so can start modifying the
-	 * original run lists.
+	 * original runlists.
 	 */
 
 	/* Move the tail of @dst out of the way, then copy in @src. */
@@ -452,17 +452,17 @@ static inline run_list_element *ntfs_rl_split(run_list_element *dst, int dsize,
 }
 
 /**
- * ntfs_merge_run_lists - merge two run_lists into one
- * @drl:	original run list to be worked on
- * @srl:	new run list to be merged into @drl
+ * ntfs_merge_runlists - merge two runlists into one
+ * @drl:	original runlist to be worked on
+ * @srl:	new runlist to be merged into @drl
  *
- * First we sanity check the two run lists @srl and @drl to make sure that they
- * are sensible and can be merged. The run list @srl must be either after the
- * run list @drl or completely within a hole (or unmapped region) in @drl.
+ * First we sanity check the two runlists @srl and @drl to make sure that they
+ * are sensible and can be merged. The runlist @srl must be either after the
+ * runlist @drl or completely within a hole (or unmapped region) in @drl.
  *
- * It is up to the caller to serialize access to the run lists @drl and @srl.
+ * It is up to the caller to serialize access to the runlists @drl and @srl.
  *
- * Merging of run lists is necessary in two cases:
+ * Merging of runlists is necessary in two cases:
  *   1. When attribute lists are used and a further extent is being mapped.
  *   2. When new clusters are allocated to fill a hole or extend a file.
  *
@@ -471,22 +471,22 @@ static inline run_list_element *ntfs_rl_split(run_list_element *dst, int dsize,
  *	- split the hole in two and be inserted between the two fragments,
  *	- be appended at the end of a hole, or it can
  *	- replace the whole hole.
- * It can also be appended to the end of the run list, which is just a variant
+ * It can also be appended to the end of the runlist, which is just a variant
  * of the insert case.
  *
- * On success, return a pointer to the new, combined, run list. Note, both
- * run lists @drl and @srl are deallocated before returning so you cannot use
- * the pointers for anything any more. (Strictly speaking the returned run list
+ * On success, return a pointer to the new, combined, runlist. Note, both
+ * runlists @drl and @srl are deallocated before returning so you cannot use
+ * the pointers for anything any more. (Strictly speaking the returned runlist
  * may be the same as @dst but this is irrelevant.)
  *
- * On error, return -errno. Both run lists are left unmodified. The following
+ * On error, return -errno. Both runlists are left unmodified. The following
  * error codes are defined:
- *	-ENOMEM	- Not enough memory to allocate run list array.
+ *	-ENOMEM	- Not enough memory to allocate runlist array.
  *	-EINVAL	- Invalid parameters were passed in.
- *	-ERANGE	- The run lists overlap and cannot be merged.
+ *	-ERANGE	- The runlists overlap and cannot be merged.
  */
-run_list_element *ntfs_merge_run_lists(run_list_element *drl,
-		run_list_element *srl)
+runlist_element *ntfs_merge_runlists(runlist_element *drl,
+		runlist_element *srl)
 {
 	int di, si;		/* Current index into @[ds]rl. */
 	int sstart;		/* First index with lcn > LCN_RL_NOT_MAPPED. */
@@ -507,21 +507,21 @@ run_list_element *ntfs_merge_run_lists(run_list_element *drl,
 	/* Check for silly calling... */
 	if (unlikely(!srl))
 		return drl;
-	if (unlikely(IS_ERR(srl) || IS_ERR(drl)))
+	if (IS_ERR(srl) || IS_ERR(drl))
 		return ERR_PTR(-EINVAL);
 
 	/* Check for the case where the first mapping is being done now. */
 	if (unlikely(!drl)) {
 		drl = srl;
-		/* Complete the source run list if necessary. */
+		/* Complete the source runlist if necessary. */
 		if (unlikely(drl[0].vcn)) {
-			/* Scan to the end of the source run list. */
+			/* Scan to the end of the source runlist. */
 			for (dend = 0; likely(drl[dend].length); dend++)
 				;
 			drl = ntfs_rl_realloc(drl, dend, dend + 1);
 			if (IS_ERR(drl))
 				return drl;
-			/* Insert start element at the front of the run list. */
+			/* Insert start element at the front of the runlist. */
 			ntfs_rl_mm(drl, 1, 0, dend);
 			drl[0].vcn = 0;
 			drl[0].lcn = LCN_RL_NOT_MAPPED;
@@ -532,11 +532,11 @@ run_list_element *ntfs_merge_run_lists(run_list_element *drl,
 
 	si = di = 0;
 
-	/* Skip any unmapped start element(s) in the source run_list. */
+	/* Skip any unmapped start element(s) in the source runlist. */
 	while (srl[si].length && srl[si].lcn < (LCN)LCN_HOLE)
 		si++;
 
-	/* Can't have an entirely unmapped source run list. */
+	/* Can't have an entirely unmapped source runlist. */
 	BUG_ON(!srl[si].length);
 
 	/* Record the starting points. */
@@ -560,7 +560,7 @@ run_list_element *ntfs_merge_run_lists(run_list_element *drl,
 		return ERR_PTR(-ERANGE);
 	}
 
-	/* Scan to the end of both run lists in order to know their sizes. */
+	/* Scan to the end of both runlists in order to know their sizes. */
 	for (send = si; srl[send].length; send++)
 		;
 	for (dend = di; drl[dend].length; dend++)
@@ -631,7 +631,7 @@ run_list_element *ntfs_merge_run_lists(run_list_element *drl,
 				goto finished;
 			}
 			/*
-			 * We need to create an unmapped run list element in
+			 * We need to create an unmapped runlist element in
 			 * @drl or extend an existing one before adding the
 			 * ENOENT terminator.
 			 */
@@ -640,7 +640,7 @@ run_list_element *ntfs_merge_run_lists(run_list_element *drl,
 				slots = 1;
 			}
 			if (drl[ds].lcn != (LCN)LCN_RL_NOT_MAPPED) {
-				/* Add an unmapped run list element. */
+				/* Add an unmapped runlist element. */
 				if (!slots) {
 					/* FIXME/TODO: We need to have the
 					 * extra memory already! (AIA) */
@@ -677,7 +677,7 @@ run_list_element *ntfs_merge_run_lists(run_list_element *drl,
 
 finished:
 	/* The merge was completed successfully. */
-	ntfs_debug("Merged run list:");
+	ntfs_debug("Merged runlist:");
 	ntfs_debug_dump_runlist(drl);
 	return drl;
 
@@ -688,45 +688,45 @@ critical_error:
 }
 
 /**
- * decompress_mapping_pairs - convert mapping pairs array to run list
+ * decompress_mapping_pairs - convert mapping pairs array to runlist
  * @vol:	ntfs volume on which the attribute resides
  * @attr:	attribute record whose mapping pairs array to decompress
- * @old_rl:	optional run list in which to insert @attr's run list
+ * @old_rl:	optional runlist in which to insert @attr's runlist
  *
- * It is up to the caller to serialize access to the run list @old_rl.
+ * It is up to the caller to serialize access to the runlist @old_rl.
  *
- * Decompress the attribute @attr's mapping pairs array into a run list. On
- * success, return the decompressed run list.
+ * Decompress the attribute @attr's mapping pairs array into a runlist. On
+ * success, return the decompressed runlist.
  *
- * If @old_rl is not NULL, decompressed run list is inserted into the
- * appropriate place in @old_rl and the resultant, combined run list is
+ * If @old_rl is not NULL, decompressed runlist is inserted into the
+ * appropriate place in @old_rl and the resultant, combined runlist is
  * returned. The original @old_rl is deallocated.
  *
  * On error, return -errno. @old_rl is left unmodified in that case.
  *
  * The following error codes are defined:
- *	-ENOMEM	- Not enough memory to allocate run list array.
- *	-EIO	- Corrupt run list.
+ *	-ENOMEM	- Not enough memory to allocate runlist array.
+ *	-EIO	- Corrupt runlist.
  *	-EINVAL	- Invalid parameters were passed in.
- *	-ERANGE	- The two run lists overlap.
+ *	-ERANGE	- The two runlists overlap.
  *
  * FIXME: For now we take the conceptionally simplest approach of creating the
- * new run list disregarding the already existing one and then splicing the
+ * new runlist disregarding the already existing one and then splicing the
  * two into one, if that is possible (we check for overlap and discard the new
- * run list if overlap present before returning ERR_PTR(-ERANGE)).
+ * runlist if overlap present before returning ERR_PTR(-ERANGE)).
  */
-run_list_element *decompress_mapping_pairs(const ntfs_volume *vol,
-		const ATTR_RECORD *attr, run_list_element *old_rl)
+runlist_element *decompress_mapping_pairs(const ntfs_volume *vol,
+		const ATTR_RECORD *attr, runlist_element *old_rl)
 {
 	VCN vcn;		/* Current vcn. */
 	LCN lcn;		/* Current lcn. */
 	s64 deltaxcn;		/* Change in [vl]cn. */
-	run_list_element *rl;	/* The output run list. */
+	runlist_element *rl;	/* The output runlist. */
 	u8 *buf;		/* Current position in mapping pairs array. */
 	u8 *attr_end;		/* End of attribute. */
-	int rlsize;		/* Size of run list buffer. */
-	u16 rlpos;		/* Current run list position in units of
-				   run_list_elements. */
+	int rlsize;		/* Size of runlist buffer. */
+	u16 rlpos;		/* Current runlist position in units of
+				   runlist_elements. */
 	u8 b;			/* Current byte offset in buf. */
 
 #ifdef DEBUG
@@ -748,9 +748,9 @@ run_list_element *decompress_mapping_pairs(const ntfs_volume *vol,
 		ntfs_error(vol->sb, "Corrupt attribute.");
 		return ERR_PTR(-EIO);
 	}
-	/* Current position in run list array. */
+	/* Current position in runlist array. */
 	rlpos = 0;
-	/* Allocate first page and set current run list size to one page. */
+	/* Allocate first page and set current runlist size to one page. */
 	rl = ntfs_malloc_nofs(rlsize = PAGE_SIZE);
 	if (unlikely(!rl))
 		return ERR_PTR(-ENOMEM);
@@ -768,7 +768,7 @@ run_list_element *decompress_mapping_pairs(const ntfs_volume *vol,
 		 * operates on whole pages only.
 		 */
 		if (((rlpos + 3) * sizeof(*old_rl)) > rlsize) {
-			run_list_element *rl2;
+			runlist_element *rl2;
 
 			rl2 = ntfs_malloc_nofs(rlsize + (int)PAGE_SIZE);
 			if (unlikely(!rl2)) {
@@ -780,7 +780,7 @@ run_list_element *decompress_mapping_pairs(const ntfs_volume *vol,
 			rl = rl2;
 			rlsize += PAGE_SIZE;
 		}
-		/* Enter the current vcn into the current run_list element. */
+		/* Enter the current vcn into the current runlist element. */
 		rl[rlpos].vcn = vcn;
 		/*
 		 * Get the change in vcn, i.e. the run length in clusters.
@@ -810,7 +810,7 @@ run_list_element *decompress_mapping_pairs(const ntfs_volume *vol,
 			goto err_out;
 		}
 		/*
-		 * Enter the current run length into the current run list
+		 * Enter the current run length into the current runlist
 		 * element.
 		 */
 		rl[rlpos].length = deltaxcn;
@@ -854,10 +854,10 @@ run_list_element *decompress_mapping_pairs(const ntfs_volume *vol,
 						"mapping pairs array.");
 				goto err_out;
 			}
-			/* Enter the current lcn into the run_list element. */
+			/* Enter the current lcn into the runlist element. */
 			rl[rlpos].lcn = lcn;
 		}
-		/* Get to the next run_list element. */
+		/* Get to the next runlist element. */
 		rlpos++;
 		/* Increment the buffer position to the next mapping pair. */
 		buf += (*buf & 0xf) + ((*buf >> 4) & 0xf) + 1;
@@ -866,7 +866,7 @@ run_list_element *decompress_mapping_pairs(const ntfs_volume *vol,
 		goto io_error;
 	/*
 	 * If there is a highest_vcn specified, it must be equal to the final
-	 * vcn in the run list - 1, or something has gone badly wrong.
+	 * vcn in the runlist - 1, or something has gone badly wrong.
 	 */
 	deltaxcn = sle64_to_cpu(attr->data.non_resident.highest_vcn);
 	if (unlikely(deltaxcn && vcn - 1 != deltaxcn)) {
@@ -875,7 +875,7 @@ mpa_err:
 				"non-resident attribute.");
 		goto err_out;
 	}
-	/* Setup not mapped run list element if this is the base extent. */
+	/* Setup not mapped runlist element if this is the base extent. */
 	if (!attr->data.non_resident.lowest_vcn) {
 		VCN max_cluster;
 
@@ -885,7 +885,7 @@ mpa_err:
 				vol->cluster_size_bits;
 		/*
 		 * If there is a difference between the highest_vcn and the
-		 * highest cluster, the run list is either corrupt or, more
+		 * highest cluster, the runlist is either corrupt or, more
 		 * likely, there are more extents following this one.
 		 */
 		if (deltaxcn < --max_cluster) {
@@ -908,21 +908,21 @@ mpa_err:
 	} else /* Not the base extent. There may be more extents to follow. */
 		rl[rlpos].lcn = (LCN)LCN_RL_NOT_MAPPED;
 
-	/* Setup terminating run_list element. */
+	/* Setup terminating runlist element. */
 	rl[rlpos].vcn = vcn;
 	rl[rlpos].length = (s64)0;
-	/* If no existing run list was specified, we are done. */
+	/* If no existing runlist was specified, we are done. */
 	if (!old_rl) {
 		ntfs_debug("Mapping pairs array successfully decompressed:");
 		ntfs_debug_dump_runlist(rl);
 		return rl;
 	}
-	/* Now combine the new and old run lists checking for overlaps. */
-	old_rl = ntfs_merge_run_lists(old_rl, rl);
+	/* Now combine the new and old runlists checking for overlaps. */
+	old_rl = ntfs_merge_runlists(old_rl, rl);
 	if (likely(!IS_ERR(old_rl)))
 		return old_rl;
 	ntfs_free(rl);
-	ntfs_error(vol->sb, "Failed to merge run lists.");
+	ntfs_error(vol->sb, "Failed to merge runlists.");
 	return old_rl;
 io_error:
 	ntfs_error(vol->sb, "Corrupt attribute.");
@@ -932,22 +932,25 @@ err_out:
 }
 
 /**
- * map_run_list - map (a part of) a run list of an ntfs inode
- * @ni:		ntfs inode for which to map (part of) a run list
- * @vcn:	map run list part containing this vcn
+ * ntfs_map_runlist - map (a part of) a runlist of an ntfs inode
+ * @ni:		ntfs inode for which to map (part of) a runlist
+ * @vcn:	map runlist part containing this vcn
  *
- * Map the part of a run list containing the @vcn of an the ntfs inode @ni.
+ * Map the part of a runlist containing the @vcn of the ntfs inode @ni.
  *
  * Return 0 on success and -errno on error.
+ *
+ * Locking: - The runlist must be unlocked on entry and is unlocked on return.
+ *	    - This function takes the lock for writing and modifies the runlist.
  */
-int map_run_list(ntfs_inode *ni, VCN vcn)
+int ntfs_map_runlist(ntfs_inode *ni, VCN vcn)
 {
 	ntfs_inode *base_ni;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	MFT_RECORD *mrec;
 	int err = 0;
 
-	ntfs_debug("Mapping run list part containing vcn 0x%llx.",
+	ntfs_debug("Mapping runlist part containing vcn 0x%llx.",
 			(unsigned long long)vcn);
 
 	if (!NInoAttr(ni))
@@ -958,69 +961,67 @@ int map_run_list(ntfs_inode *ni, VCN vcn)
 	mrec = map_mft_record(base_ni);
 	if (IS_ERR(mrec))
 		return PTR_ERR(mrec);
-	ctx = get_attr_search_ctx(base_ni, mrec);
-	if (!ctx) {
+	ctx = ntfs_attr_get_search_ctx(base_ni, mrec);
+	if (unlikely(!ctx)) {
 		err = -ENOMEM;
 		goto err_out;
 	}
-	if (!lookup_attr(ni->type, ni->name, ni->name_len, CASE_SENSITIVE, vcn,
-			NULL, 0, ctx)) {
-		put_attr_search_ctx(ctx);
-		err = -ENOENT;
-		goto err_out;
-	}
+	err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
+			CASE_SENSITIVE, vcn, NULL, 0, ctx);
+	if (unlikely(err))
+		goto put_err_out;
 
-	down_write(&ni->run_list.lock);
+	down_write(&ni->runlist.lock);
 	/* Make sure someone else didn't do the work while we were sleeping. */
-	if (likely(vcn_to_lcn(ni->run_list.rl, vcn) <= LCN_RL_NOT_MAPPED)) {
-		run_list_element *rl;
+	if (likely(ntfs_vcn_to_lcn(ni->runlist.rl, vcn) <= LCN_RL_NOT_MAPPED)) {
+		runlist_element *rl;
 
 		rl = decompress_mapping_pairs(ni->vol, ctx->attr,
-				ni->run_list.rl);
-		if (unlikely(IS_ERR(rl)))
+				ni->runlist.rl);
+		if (IS_ERR(rl))
 			err = PTR_ERR(rl);
 		else
-			ni->run_list.rl = rl;
+			ni->runlist.rl = rl;
 	}
-	up_write(&ni->run_list.lock);
+	up_write(&ni->runlist.lock);
 
-	put_attr_search_ctx(ctx);
+put_err_out:
+	ntfs_attr_put_search_ctx(ctx);
 err_out:
 	unmap_mft_record(base_ni);
 	return err;
 }
 
 /**
- * vcn_to_lcn - convert a vcn into a lcn given a run list
- * @rl:		run list to use for conversion
+ * ntfs_vcn_to_lcn - convert a vcn into a lcn given a runlist
+ * @rl:		runlist to use for conversion
  * @vcn:	vcn to convert
  *
  * Convert the virtual cluster number @vcn of an attribute into a logical
- * cluster number (lcn) of a device using the run list @rl to map vcns to their
+ * cluster number (lcn) of a device using the runlist @rl to map vcns to their
  * corresponding lcns.
  *
- * It is up to the caller to serialize access to the run list @rl.
+ * It is up to the caller to serialize access to the runlist @rl.
  *
  * Since lcns must be >= 0, we use negative return values with special meaning:
  *
  * Return value			Meaning / Description
  * ==================================================
  *  -1 = LCN_HOLE		Hole / not allocated on disk.
- *  -2 = LCN_RL_NOT_MAPPED	This is part of the run list which has not been
- *				inserted into the run list yet.
+ *  -2 = LCN_RL_NOT_MAPPED	This is part of the runlist which has not been
+ *				inserted into the runlist yet.
  *  -3 = LCN_ENOENT		There is no such vcn in the attribute.
- *  -4 = LCN_EINVAL		Input parameter error (if debug enabled).
+ *
+ * Locking: - The caller must have locked the runlist (for reading or writing).
+ *	    - This function does not touch the lock.
  */
-LCN vcn_to_lcn(const run_list_element *rl, const VCN vcn)
+LCN ntfs_vcn_to_lcn(const runlist_element *rl, const VCN vcn)
 {
 	int i;
 
-#ifdef DEBUG
-	if (vcn < (VCN)0)
-		return (LCN)LCN_EINVAL;
-#endif
+	BUG_ON(vcn < 0);
 	/*
-	 * If rl is NULL, assume that we have found an unmapped run list. The
+	 * If rl is NULL, assume that we have found an unmapped runlist. The
 	 * caller can then attempt to map it and fail appropriately if
 	 * necessary.
 	 */
@@ -1049,7 +1050,104 @@ LCN vcn_to_lcn(const run_list_element *rl, const VCN vcn)
 }
 
 /**
- * find_attr - find (next) attribute in mft record
+ * ntfs_find_vcn - find a vcn in the runlist described by an ntfs inode
+ * @ni:		ntfs inode describing the runlist to search
+ * @vcn:	vcn to find
+ * @need_write:	if false, lock for reading and if true, lock for writing
+ *
+ * Find the virtual cluster number @vcn in the runlist described by the ntfs
+ * inode @ni and return the address of the runlist element containing the @vcn.
+ * The runlist is left locked and the caller has to unlock it.  If @need_write
+ * is true, the runlist is locked for writing and if @need_write is false, the
+ * runlist is locked for reading.  In the error case, the runlist is not left
+ * locked.
+ *
+ * Note you need to distinguish between the lcn of the returned runlist element
+ * being >= 0 and LCN_HOLE.  In the later case you have to return zeroes on
+ * read and allocate clusters on write.
+ *
+ * Return the runlist element containing the @vcn on success and
+ * ERR_PTR(-errno) on error.  You need to test the return value with IS_ERR()
+ * to decide if the return is success or failure and PTR_ERR() to get to the
+ * error code if IS_ERR() is true.
+ *
+ * The possible error return codes are:
+ *	-ENOENT - No such vcn in the runlist, i.e. @vcn is out of bounds.
+ *	-ENOMEM - Not enough memory to map runlist.
+ *	-EIO	- Critical error (runlist/file is corrupt, i/o error, etc).
+ *
+ * Locking: - The runlist must be unlocked on entry.
+ *	    - On failing return, the runlist is unlocked.
+ *	    - On successful return, the runlist is locked.  If @need_write us
+ *	      true, it is locked for writing.  Otherwise is is locked for
+ *	      reading.
+ */
+runlist_element *ntfs_find_vcn(ntfs_inode *ni, const VCN vcn,
+		const BOOL need_write)
+{
+	runlist_element *rl;
+	int err = 0;
+	BOOL is_retry = FALSE;
+
+	ntfs_debug("Entering for i_ino 0x%lx, vcn 0x%llx, lock for %sing.",
+			ni->mft_no, (unsigned long long)vcn,
+			!need_write ? "read" : "writ");
+	BUG_ON(!ni);
+	BUG_ON(!NInoNonResident(ni));
+	BUG_ON(vcn < 0);
+lock_retry_remap:
+	if (!need_write)
+		down_read(&ni->runlist.lock);
+	else
+		down_write(&ni->runlist.lock);
+	rl = ni->runlist.rl;
+	if (likely(rl && vcn >= rl[0].vcn)) {
+		while (likely(rl->length)) {
+			if (likely(vcn < rl[1].vcn)) {
+				if (likely(rl->lcn >= (LCN)LCN_HOLE)) {
+					ntfs_debug("Done.");
+					return rl;
+				}
+				break;
+			}
+			rl++;
+		}
+		if (likely(rl->lcn != (LCN)LCN_RL_NOT_MAPPED)) {
+			if (likely(rl->lcn == (LCN)LCN_ENOENT))
+				err = -ENOENT;
+			else
+				err = -EIO;
+		}
+	}
+	if (!need_write)
+		up_read(&ni->runlist.lock);
+	else
+		up_write(&ni->runlist.lock);
+	if (!err && !is_retry) {
+		/*
+		 * The @vcn is in an unmapped region, map the runlist and
+		 * retry.
+		 */
+		err = ntfs_map_runlist(ni, vcn);
+		if (likely(!err)) {
+			is_retry = TRUE;
+			goto lock_retry_remap;
+		}
+		/*
+		 * -EINVAL and -ENOENT coming from a failed mapping attempt are
+		 * equivalent to i/o errors for us as they should not happen in
+		 * our code paths.
+		 */
+		if (err == -EINVAL || err == -ENOENT)
+			err = -EIO;
+	} else if (!err)
+		err = -EIO;
+	ntfs_error(ni->vol->sb, "Failed with error code %i.", err);
+	return ERR_PTR(err);
+}
+
+/**
+ * ntfs_attr_find - find (next) attribute in mft record
  * @type:	attribute type to find
  * @name:	attribute name to find (optional, i.e. NULL means don't care)
  * @name_len:	attribute name length (only needed if @name present)
@@ -1058,47 +1156,56 @@ LCN vcn_to_lcn(const run_list_element *rl, const VCN vcn)
  * @val_len:	attribute value length
  * @ctx:	search context with mft record and attribute to search from
  *
- * You shouldn't need to call this function directly. Use lookup_attr() instead.
+ * You should not need to call this function directly.  Use ntfs_attr_lookup()
+ * instead.
  *
- * find_attr() takes a search context @ctx as parameter and searches the mft
- * record specified by @ctx->mrec, beginning at @ctx->attr, for an attribute of
- * @type, optionally @name and @val. If found, find_attr() returns TRUE and
- * @ctx->attr will point to the found attribute. If not found, find_attr()
- * returns FALSE and @ctx->attr is undefined (i.e. do not rely on it not
- * changing).
+ * ntfs_attr_find() takes a search context @ctx as parameter and searches the
+ * mft record specified by @ctx->mrec, beginning at @ctx->attr, for an
+ * attribute of @type, optionally @name and @val.
  *
- * If @ctx->is_first is TRUE, the search begins with @ctx->attr itself. If it
+ * If the attribute is found, ntfs_attr_find() returns 0 and @ctx->attr will
+ * point to the found attribute.
+ *
+ * If the attribute is not found, ntfs_attr_find() returns -ENOENT and
+ * @ctx->attr will point to the attribute before which the attribute being
+ * searched for would need to be inserted if such an action were to be desired.
+ *
+ * On actual error, ntfs_attr_find() returns -EIO.  In this case @ctx->attr is
+ * undefined and in particular do not rely on it not changing.
+ *
+ * If @ctx->is_first is TRUE, the search begins with @ctx->attr itself.  If it
  * is FALSE, the search begins after @ctx->attr.
  *
  * If @ic is IGNORE_CASE, the @name comparisson is not case sensitive and
  * @ctx->ntfs_ino must be set to the ntfs inode to which the mft record
- * @ctx->mrec belongs. This is so we can get at the ntfs volume and hence at
- * the upcase table. If @ic is CASE_SENSITIVE, the comparison is case
- * sensitive. When @name is present, @name_len is the @name length in Unicode
+ * @ctx->mrec belongs.  This is so we can get at the ntfs volume and hence at
+ * the upcase table.  If @ic is CASE_SENSITIVE, the comparison is case
+ * sensitive.  When @name is present, @name_len is the @name length in Unicode
  * characters.
  *
  * If @name is not present (NULL), we assume that the unnamed attribute is
  * being searched for.
  *
- * Finally, the resident attribute value @val is looked for, if present. If @val
- * is not present (NULL), @val_len is ignored.
+ * Finally, the resident attribute value @val is looked for, if present.  If
+ * @val is not present (NULL), @val_len is ignored.
  *
- * find_attr() only searches the specified mft record and it ignores the
+ * ntfs_attr_find() only searches the specified mft record and it ignores the
  * presence of an attribute list attribute (unless it is the one being searched
- * for, obviously). If you need to take attribute lists into consideration, use
- * lookup_attr() instead (see below). This also means that you cannot use
- * find_attr() to search for extent records of non-resident attributes, as
- * extents with lowest_vcn != 0 are usually described by the attribute list
- * attribute only. - Note that it is possible that the first extent is only in
- * the attribute list while the last extent is in the base mft record, so don't
- * rely on being able to find the first extent in the base mft record.
+ * for, obviously).  If you need to take attribute lists into consideration,
+ * use ntfs_attr_lookup() instead (see below).  This also means that you cannot
+ * use ntfs_attr_find() to search for extent records of non-resident
+ * attributes, as extents with lowest_vcn != 0 are usually described by the
+ * attribute list attribute only. - Note that it is possible that the first
+ * extent is only in the attribute list while the last extent is in the base
+ * mft record, so do not rely on being able to find the first extent in the
+ * base mft record.
  *
  * Warning: Never use @val when looking for attribute types which can be
  *	    non-resident as this most likely will result in a crash!
  */
-BOOL find_attr(const ATTR_TYPES type, const ntfschar *name, const u32 name_len,
-		const IGNORE_CASE_BOOL ic, const u8 *val, const u32 val_len,
-		attr_search_context *ctx)
+static int ntfs_attr_find(const ATTR_TYPE type, const ntfschar *name,
+		const u32 name_len, const IGNORE_CASE_BOOL ic,
+		const u8 *val, const u32 val_len, ntfs_attr_search_ctx *ctx)
 {
 	ATTR_RECORD *a;
 	ntfs_volume *vol;
@@ -1129,21 +1236,21 @@ BOOL find_attr(const ATTR_TYPES type, const ntfschar *name, const u32 name_len,
 				le32_to_cpu(ctx->mrec->bytes_allocated))
 			break;
 		ctx->attr = a;
-		/* We catch $END with this more general check, too... */
-		if (le32_to_cpu(a->type) > le32_to_cpu(type))
-			return FALSE;
+		if (unlikely(le32_to_cpu(a->type) > le32_to_cpu(type) ||
+				a->type == AT_END))
+			return -ENOENT;
 		if (unlikely(!a->length))
 			break;
 		if (a->type != type)
 			continue;
 		/*
-		 * If @name is present, compare the two names. If @name is
+		 * If @name is present, compare the two names.  If @name is
 		 * missing, assume we want an unnamed attribute.
 		 */
 		if (!name) {
 			/* The search failed if the found attribute is named. */
 			if (a->name_length)
-				return FALSE;
+				return -ENOENT;
 		} else if (!ntfs_are_names_equal(name, name_len,
 			    (ntfschar*)((u8*)a + le16_to_cpu(a->name_offset)),
 			    a->name_length, ic, upcase, upcase_len)) {
@@ -1151,7 +1258,7 @@ BOOL find_attr(const ATTR_TYPES type, const ntfschar *name, const u32 name_len,
 
 			rc = ntfs_collate_names(name, name_len,
 					(ntfschar*)((u8*)a +
-						le16_to_cpu(a->name_offset)),
+					le16_to_cpu(a->name_offset)),
 					a->name_length, 1, IGNORE_CASE,
 					upcase, upcase_len);
 			/*
@@ -1159,67 +1266,66 @@ BOOL find_attr(const ATTR_TYPES type, const ntfschar *name, const u32 name_len,
 			 * matching attribute.
 			 */
 			if (rc == -1)
-				return FALSE;
+				return -ENOENT;
 			/* If the strings are not equal, continue search. */
 			if (rc)
 				continue;
 			rc = ntfs_collate_names(name, name_len,
 					(ntfschar*)((u8*)a +
-						le16_to_cpu(a->name_offset)),
+					le16_to_cpu(a->name_offset)),
 					a->name_length, 1, CASE_SENSITIVE,
 					upcase, upcase_len);
 			if (rc == -1)
-				return FALSE;
+				return -ENOENT;
 			if (rc)
 				continue;
 		}
 		/*
 		 * The names match or @name not present and attribute is
-		 * unnamed. If no @val specified, we have found the attribute
+		 * unnamed.  If no @val specified, we have found the attribute
 		 * and are done.
 		 */
 		if (!val)
-			return TRUE;
+			return 0;
 		/* @val is present; compare values. */
 		else {
-			u32 vl;
 			register int rc;
 
-			vl = le32_to_cpu(a->data.resident.value_length);
-			if (vl > val_len)
-				vl = val_len;
-
 			rc = memcmp(val, (u8*)a + le16_to_cpu(
-					a->data.resident.value_offset), vl);
+					a->data.resident.value_offset),
+					min_t(u32, val_len, le32_to_cpu(
+					a->data.resident.value_length)));
 			/*
 			 * If @val collates before the current attribute's
 			 * value, there is no matching attribute.
 			 */
 			if (!rc) {
 				register u32 avl;
+
 				avl = le32_to_cpu(
 						a->data.resident.value_length);
 				if (val_len == avl)
-					return TRUE;
+					return 0;
 				if (val_len < avl)
-					return FALSE;
+					return -ENOENT;
 			} else if (rc < 0)
-				return FALSE;
+				return -ENOENT;
 		}
 	}
-	ntfs_error(NULL, "Inode is corrupt. Run chkdsk.");
-	return FALSE;
+	ntfs_error(NULL, "Inode is corrupt.  Run chkdsk.");
+	NVolSetErrors(vol);
+	return -EIO;
 }
 
 /**
  * load_attribute_list - load an attribute list into memory
  * @vol:		ntfs volume from which to read
- * @run_list:		run list of the attribute list
+ * @runlist:		runlist of the attribute list
  * @al_start:		destination buffer
  * @size:		size of the destination buffer in bytes
  * @initialized_size:	initialized size of the attribute list
  *
- * Walk the run list @run_list and load all clusters from it copying them into
+ * Walk the runlist @runlist and load all clusters from it copying them into
  * the linear buffer @al. The maximum number of bytes copied to @al is @size
  * bytes. Note, @size does not need to be a multiple of the cluster size. If
  * @initialized_size is less than @size, the region in @al between
@@ -1227,13 +1333,13 @@ BOOL find_attr(const ATTR_TYPES type, const ntfschar *name, const u32 name_len,
  *
  * Return 0 on success or -errno on error.
  */
-int load_attribute_list(ntfs_volume *vol, run_list *run_list, u8 *al_start,
+int load_attribute_list(ntfs_volume *vol, runlist *runlist, u8 *al_start,
 		const s64 size, const s64 initialized_size)
 {
 	LCN lcn;
 	u8 *al = al_start;
 	u8 *al_end = al + initialized_size;
-	run_list_element *rl;
+	runlist_element *rl;
 	struct buffer_head *bh;
 	struct super_block *sb;
 	unsigned long block_size;
@@ -1242,7 +1348,7 @@ int load_attribute_list(ntfs_volume *vol, run_list *run_list, u8 *al_start,
 	unsigned char block_size_bits;
 
 	ntfs_debug("Entering.");
-	if (!vol || !run_list || !al || size <= 0 || initialized_size < 0 ||
+	if (!vol || !runlist || !al || size <= 0 || initialized_size < 0 ||
 			initialized_size > size)
 		return -EINVAL;
 	if (!initialized_size) {
@@ -1252,17 +1358,17 @@ int load_attribute_list(ntfs_volume *vol, run_list *run_list, u8 *al_start,
 	sb = vol->sb;
 	block_size = sb->s_blocksize;
 	block_size_bits = sb->s_blocksize_bits;
-	down_read(&run_list->lock);
-	rl = run_list->rl;
-	/* Read all clusters specified by the run list one run at a time. */
+	down_read(&runlist->lock);
+	rl = runlist->rl;
+	/* Read all clusters specified by the runlist one run at a time. */
 	while (rl->length) {
-		lcn = vcn_to_lcn(rl, rl->vcn);
+		lcn = ntfs_vcn_to_lcn(rl, rl->vcn);
 		ntfs_debug("Reading vcn = 0x%llx, lcn = 0x%llx.",
 				(unsigned long long)rl->vcn,
 				(unsigned long long)lcn);
 		/* The attribute list cannot be sparse. */
 		if (lcn < 0) {
-			ntfs_error(sb, "vcn_to_lcn() failed. Cannot read "
+			ntfs_error(sb, "ntfs_vcn_to_lcn() failed. Cannot read "
 					"attribute list.");
 			goto err_out;
 		}
@@ -1292,7 +1398,7 @@ initialize:
 		memset(al_start + initialized_size, 0, size - initialized_size);
 	}
 done:
-	up_read(&run_list->lock);
+	up_read(&runlist->lock);
 	return err;
 do_final:
 	if (al < al_end) {
@@ -1320,7 +1426,7 @@ err_out:
 }
 
 /**
- * find_external_attr - find an attribute in the attribute list of an ntfs inode
+ * ntfs_external_attr_find - find an attribute in the attribute list of an inode
  * @type:	attribute type to find
  * @name:	attribute name to find (optional, i.e. NULL means don't care)
  * @name_len:	attribute name length (only needed if @name present)
@@ -1330,34 +1436,49 @@ err_out:
  * @val_len:	attribute value length
  * @ctx:	search context with mft record and attribute to search from
  *
- * You shouldn't need to call this function directly. Use lookup_attr() instead.
+ * You should not need to call this function directly.  Use ntfs_attr_lookup()
+ * instead.
  *
  * Find an attribute by searching the attribute list for the corresponding
- * attribute list entry. Having found the entry, map the mft record for read
- * if the attribute is in a different mft record/inode, find_attr the attribute
+ * attribute list entry.  Having found the entry, map the mft record if the
+ * attribute is in a different mft record/inode, ntfs_attr_find() the attribute
  * in there and return it.
  *
  * On first search @ctx->ntfs_ino must be the base mft record and @ctx must
- * have been obtained from a call to get_attr_search_ctx(). On subsequent calls
- * @ctx->ntfs_ino can be any extent inode, too (@ctx->base_ntfs_ino is then the
- * base inode).
+ * have been obtained from a call to ntfs_attr_get_search_ctx().  On subsequent
+ * calls @ctx->ntfs_ino can be any extent inode, too (@ctx->base_ntfs_ino is
+ * then the base inode).
  *
  * After finishing with the attribute/mft record you need to call
- * put_attr_search_ctx() to cleanup the search context (unmapping any mapped
- * inodes, etc).
- *
- * Return TRUE if the search was successful and FALSE if not. When TRUE,
- * @ctx->attr is the found attribute and it is in mft record @ctx->mrec. When
- * FALSE, @ctx->attr is the attribute which collates just after the attribute
- * being searched for in the base ntfs inode, i.e. if one wants to add the
- * attribute to the mft record this is the correct place to insert it into
- * and if there is not enough space, the attribute should be placed in an
- * extent mft record.
+ * ntfs_attr_put_search_ctx() to cleanup the search context (unmapping any
+ * mapped inodes, etc).
+ *
+ * If the attribute is found, ntfs_external_attr_find() returns 0 and
+ * @ctx->attr will point to the found attribute.  @ctx->mrec will point to the
+ * mft record in which @ctx->attr is located and @ctx->al_entry will point to
+ * the attribute list entry for the attribute.
+ *
+ * If the attribute is not found, ntfs_external_attr_find() returns -ENOENT and
+ * @ctx->attr will point to the attribute in the base mft record before which
+ * the attribute being searched for would need to be inserted if such an action
+ * were to be desired.  @ctx->mrec will point to the mft record in which
+ * @ctx->attr is located and @ctx->al_entry will point to the attribute list
+ * entry of the attribute before which the attribute being searched for would
+ * need to be inserted if such an action were to be desired.
+ *
+ * Thus to insert the not found attribute, one wants to add the attribute to
+ * @ctx->mrec (the base mft record) and if there is not enough space, the
+ * attribute should be placed in a newly allocated extent mft record.  The
+ * attribute list entry for the inserted attribute should be inserted in the
+ * attribute list attribute at @ctx->al_entry.
+ *
+ * On actual error, ntfs_external_attr_find() returns -EIO.  In this case
+ * @ctx->attr is undefined and in particular do not rely on it not changing.
  */
-static BOOL find_external_attr(const ATTR_TYPES type, const ntfschar *name,
-		const u32 name_len, const IGNORE_CASE_BOOL ic,
-		const VCN lowest_vcn, const u8 *val, const u32 val_len,
-		attr_search_context *ctx)
+static int ntfs_external_attr_find(const ATTR_TYPE type,
+		const ntfschar *name, const u32 name_len,
+		const IGNORE_CASE_BOOL ic, const VCN lowest_vcn,
+		const u8 *val, const u32 val_len, ntfs_attr_search_ctx *ctx)
 {
 	ntfs_inode *base_ni, *ni;
 	ntfs_volume *vol;
@@ -1366,6 +1487,8 @@ static BOOL find_external_attr(const ATTR_TYPES type, const ntfschar *name,
 	ATTR_RECORD *a;
 	ntfschar *al_name;
 	u32 al_name_len;
+	int err = 0;
+	static const char *es = " Unmount and run chkdsk.";
 
 	ni = ctx->ntfs_ino;
 	base_ni = ctx->base_ntfs_ino;
@@ -1377,6 +1500,8 @@ static BOOL find_external_attr(const ATTR_TYPES type, const ntfschar *name,
 	}
 	if (ni == base_ni)
 		ctx->base_attr = ctx->attr;
+	if (type == AT_END)
+		goto not_found;
 	vol = base_ni->vol;
 	al_start = base_ni->attr_list;
 	al_end = al_start + base_ni->attr_list_size;
@@ -1413,7 +1538,7 @@ static BOOL find_external_attr(const ATTR_TYPES type, const ntfschar *name,
 		if (type != al_entry->type)
 			continue;
 		/*
-		 * If @name is present, compare the two names. If @name is
+		 * If @name is present, compare the two names.  If @name is
 		 * missing, assume we want an unnamed attribute.
 		 */
 		al_name_len = al_entry->name_length;
@@ -1439,10 +1564,11 @@ static BOOL find_external_attr(const ATTR_TYPES type, const ntfschar *name,
 				continue;
 			/*
 			 * FIXME: Reverse engineering showed 0, IGNORE_CASE but
-			 * that is inconsistent with find_attr(). The subsequent
-			 * rc checks were also different. Perhaps I made a
-			 * mistake in one of the two. Need to recheck which is
-			 * correct or at least see what is going on... (AIA)
+			 * that is inconsistent with ntfs_attr_find().  The
+			 * subsequent rc checks were also different.  Perhaps I
+			 * made a mistake in one of the two.  Need to recheck
+			 * which is correct or at least see what is going on...
+			 * (AIA)
 			 */
 			rc = ntfs_collate_names(name, name_len, al_name,
 					al_name_len, 1, CASE_SENSITIVE,
@@ -1454,8 +1580,8 @@ static BOOL find_external_attr(const ATTR_TYPES type, const ntfschar *name,
 		}
 		/*
 		 * The names match or @name not present and attribute is
-		 * unnamed. Now check @lowest_vcn. Continue search if the
-		 * next attribute list entry still fits @lowest_vcn. Otherwise
+		 * unnamed.  Now check @lowest_vcn.  Continue search if the
+		 * next attribute list entry still fits @lowest_vcn.  Otherwise
 		 * we have reached the right one or the search has failed.
 		 */
 		if (lowest_vcn && (u8*)next_al_entry >= al_start	    &&
@@ -1463,7 +1589,7 @@ static BOOL find_external_attr(const ATTR_TYPES type, const ntfschar *name,
 				(u8*)next_al_entry + le16_to_cpu(
 					next_al_entry->length) <= al_end    &&
 				sle64_to_cpu(next_al_entry->lowest_vcn) <=
-					sle64_to_cpu(lowest_vcn)	    &&
+					lowest_vcn			    &&
 				next_al_entry->type == al_entry->type	    &&
 				next_al_entry->name_length == al_name_len   &&
 				ntfs_are_names_equal((ntfschar*)((u8*)
@@ -1476,7 +1602,10 @@ static BOOL find_external_attr(const ATTR_TYPES type, const ntfschar *name,
 		if (MREF_LE(al_entry->mft_reference) == ni->mft_no) {
 			if (MSEQNO_LE(al_entry->mft_reference) != ni->seq_no) {
 				ntfs_error(vol->sb, "Found stale mft "
-						"reference in attribute list!");
+						"reference in attribute list "
+						"of base inode 0x%lx.%s",
+						base_ni->mft_no, es);
+				err = -EIO;
 				break;
 			}
 		} else { /* Mft references do not match. */
@@ -1491,13 +1620,20 @@ static BOOL find_external_attr(const ATTR_TYPES type, const ntfschar *name,
 			} else {
 				/* We want an extent record. */
 				ctx->mrec = map_extent_mft_record(base_ni,
-						al_entry->mft_reference, &ni);
+						le64_to_cpu(
+						al_entry->mft_reference), &ni);
 				ctx->ntfs_ino = ni;
 				if (IS_ERR(ctx->mrec)) {
-					ntfs_error(vol->sb, "Failed to map mft "
-							"record, error code "
-							"%ld.",
-							-PTR_ERR(ctx->mrec));
+					ntfs_error(vol->sb, "Failed to map "
+							"extent mft record "
+							"0x%lx of base inode "
+							"0x%lx.%s",
+							MREF_LE(al_entry->
+							mft_reference),
+							base_ni->mft_no, es);
+					err = PTR_ERR(ctx->mrec);
+					if (err == -ENOENT)
+						err = -EIO;
 					break;
 				}
 			}
@@ -1510,14 +1646,14 @@ static BOOL find_external_attr(const ATTR_TYPES type, const ntfschar *name,
 		 * current al_entry.
 		 */
 		/*
-		 * We could call into find_attr() to find the right attribute
-		 * in this mft record but this would be less efficient and not
-		 * quite accurate as find_attr() ignores the attribute instance
-		 * numbers for example which become important when one plays
-		 * with attribute lists. Also, because a proper match has been
-		 * found in the attribute list entry above, the comparison can
-		 * now be optimized. So it is worth re-implementing a
-		 * simplified find_attr() here.
+		 * We could call into ntfs_attr_find() to find the right
+		 * attribute in this mft record but this would be less
+		 * efficient and not quite accurate as ntfs_attr_find() ignores
+		 * the attribute instance numbers for example which become
+		 * important when one plays with attribute lists.  Also,
+		 * because a proper match has been found in the attribute list
+		 * entry above, the comparison can now be optimized.  So it is
+		 * worth re-implementing a simplified ntfs_attr_find() here.
 		 */
 		a = ctx->attr;
 		/*
@@ -1534,18 +1670,18 @@ do_next_attr_loop:
 			break;
 		if (al_entry->instance != a->instance)
 			goto do_next_attr;
+		/*
+		 * If the type and/or the name are mismatched between the
+		 * attribute list entry and the attribute record, there is
+		 * corruption so we break and return error EIO.
+		 */
 		if (al_entry->type != a->type)
-			continue;
-		if (name) {
-			if (a->name_length != al_name_len)
-				continue;
-			if (!ntfs_are_names_equal((ntfschar*)((u8*)a +
-					le16_to_cpu(a->name_offset)),
-					a->name_length, al_name, al_name_len,
-					CASE_SENSITIVE, vol->upcase,
-					vol->upcase_len))
-				continue;
-		}
+			break;
+		if (!ntfs_are_names_equal((ntfschar*)((u8*)a +
+				le16_to_cpu(a->name_offset)), a->name_length,
+				al_name, al_name_len, CASE_SENSITIVE,
+				vol->upcase, vol->upcase_len))
+			break;
 		ctx->attr = a;
 		/*
 		 * If no @val specified or @val specified and it matches, we
@@ -1557,46 +1693,78 @@ do_next_attr_loop:
 				le16_to_cpu(a->data.resident.value_offset),
 				val, val_len))) {
 			ntfs_debug("Done, found.");
-			return TRUE;
+			return 0;
 		}
 do_next_attr:
 		/* Proceed to the next attribute in the current mft record. */
 		a = (ATTR_RECORD*)((u8*)a + le32_to_cpu(a->length));
 		goto do_next_attr_loop;
 	}
-	ntfs_error(base_ni->vol->sb, "Inode contains corrupt attribute list "
-			"attribute.");
+	if (!err) {
+		ntfs_error(vol->sb, "Base inode 0x%lx contains corrupt "
+				"attribute list attribute.%s", base_ni->mft_no,
+				es);
+		err = -EIO;
+	}
 	if (ni != base_ni) {
 		unmap_extent_mft_record(ni);
 		ctx->ntfs_ino = base_ni;
 		ctx->mrec = ctx->base_mrec;
 		ctx->attr = ctx->base_attr;
 	}
+	if (err != -ENOMEM)
+		NVolSetErrors(vol);
+	return err;
+not_found:
 	/*
-	 * FIXME: We absolutely have to return ERROR status instead of just
-	 * false or we will blow up or even worse cause corruption when we add
-	 * write support and we reach this code path!
+	 * If we were looking for AT_END, we reset the search context @ctx and
+	 * use ntfs_attr_find() to seek to the end of the base mft record.
 	 */
-	printk(KERN_CRIT "NTFS: FIXME: Hit unfinished error code path!!!\n");
-	return FALSE;
-not_found:
+	if (type == AT_END) {
+		ntfs_attr_reinit_search_ctx(ctx);
+		return ntfs_attr_find(AT_END, name, name_len, ic, val, val_len,
+				ctx);
+	}
+	/*
+	 * The attribute was not found.  Before we return, we want to ensure
+	 * @ctx->mrec and @ctx->attr indicate the position at which the
+	 * attribute should be inserted in the base mft record.  Since we also
+	 * want to preserve @ctx->al_entry we cannot reinitialize the search
+	 * context using ntfs_attr_reinit_search_ctx() as this would set
+	 * @ctx->al_entry to NULL.  Thus we do the necessary bits manually (see
+	 * ntfs_attr_init_search_ctx() below).  Note, we _only_ preserve
+	 * @ctx->al_entry as the remaining fields (base_*) are identical to
+	 * their non base_ counterparts and we cannot set @ctx->base_attr
+	 * correctly yet as we do not know what @ctx->attr will be set to by
+	 * the call to ntfs_attr_find() below.
+	 */
+	if (ni != base_ni)
+		unmap_extent_mft_record(ni);
+	ctx->mrec = ctx->base_mrec;
+	ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec +
+			le16_to_cpu(ctx->mrec->attrs_offset));
+	ctx->is_first = TRUE;
+	ctx->ntfs_ino = base_ni;
+	ctx->base_ntfs_ino = NULL;
+	ctx->base_mrec = NULL;
+	ctx->base_attr = NULL;
 	/*
-	 * Seek to the end of the base mft record, i.e. when we return false,
-	 * ctx->mrec and ctx->attr indicate where the attribute should be
-	 * inserted into the attribute record.
-	 * And of course ctx->al_entry points to the end of the attribute
-	 * list inside NTFS_I(ctx->base_vfs_ino)->attr_list.
-	 *
-	 * FIXME: Do we really want to do this here? Think about it... (AIA)
+	 * In case there are multiple matches in the base mft record, need to
+	 * keep enumerating until we get an attribute not found response (or
+	 * another error), otherwise we would keep returning the same attribute
+	 * over and over again and all programs using us for enumeration would
+	 * lock up in a tight loop.
 	 */
-	reinit_attr_search_ctx(ctx);
-	find_attr(type, name, name_len, ic, val, val_len, ctx);
+	do {
+		err = ntfs_attr_find(type, name, name_len, ic, val, val_len,
+				ctx);
+	} while (!err);
 	ntfs_debug("Done, not found.");
-	return FALSE;
+	return err;
 }
 
 /**
- * lookup_attr - find an attribute in an ntfs inode
+ * ntfs_attr_lookup - find an attribute in an ntfs inode
  * @type:	attribute type to find
  * @name:	attribute name to find (optional, i.e. NULL means don't care)
  * @name_len:	attribute name length (only needed if @name present)
@@ -1606,27 +1774,38 @@ not_found:
  * @val_len:	attribute value length
  * @ctx:	search context with mft record and attribute to search from
  *
- * Find an attribute in an ntfs inode. On first search @ctx->ntfs_ino must
+ * Find an attribute in an ntfs inode.  On first search @ctx->ntfs_ino must
  * be the base mft record and @ctx must have been obtained from a call to
- * get_attr_search_ctx().
+ * ntfs_attr_get_search_ctx().
  *
  * This function transparently handles attribute lists and @ctx is used to
  * continue searches where they were left off at.
  *
  * After finishing with the attribute/mft record you need to call
- * put_attr_search_ctx() to cleanup the search context (unmapping any mapped
- * inodes, etc).
- *
- * Return TRUE if the search was successful and FALSE if not. When TRUE,
- * @ctx->attr is the found attribute and it is in mft record @ctx->mrec. When
- * FALSE, @ctx->attr is the attribute which collates just after the attribute
- * being searched for, i.e. if one wants to add the attribute to the mft
- * record this is the correct place to insert it into.
+ * ntfs_attr_put_search_ctx() to cleanup the search context (unmapping any
+ * mapped inodes, etc).
+ *
+ * Return 0 if the search was successful and -errno if not.
+ *
+ * When 0, @ctx->attr is the found attribute and it is in mft record
+ * @ctx->mrec.  If an attribute list attribute is present, @ctx->al_entry is
+ * the attribute list entry of the found attribute.
+ *
+ * When -ENOENT, @ctx->attr is the attribute which collates just after the
+ * attribute being searched for, i.e. if one wants to add the attribute to the
+ * mft record this is the correct place to insert it into.  If an attribute
+ * list attribute is present, @ctx->al_entry is the attribute list entry which
+ * collates just after the attribute list entry of the attribute being searched
+ * for, i.e. if one wants to add the attribute to the mft record this is the
+ * correct place to insert its attribute list entry into.
+ *
+ * When -errno != -ENOENT, an error occured during the lookup.  @ctx->attr is
+ * then undefined and in particular you should not rely on it not changing.
  */
-BOOL lookup_attr(const ATTR_TYPES type, const ntfschar *name,
+int ntfs_attr_lookup(const ATTR_TYPE type, const ntfschar *name,
 		const u32 name_len, const IGNORE_CASE_BOOL ic,
 		const VCN lowest_vcn, const u8 *val, const u32 val_len,
-		attr_search_context *ctx)
+		ntfs_attr_search_ctx *ctx)
 {
 	ntfs_inode *base_ni;
 
@@ -1637,21 +1816,22 @@ BOOL lookup_attr(const ATTR_TYPES type, const ntfschar *name,
 		base_ni = ctx->ntfs_ino;
 	/* Sanity check, just for debugging really. */
 	BUG_ON(!base_ni);
-	if (!NInoAttrList(base_ni))
-		return find_attr(type, name, name_len, ic, val, val_len, ctx);
-	return find_external_attr(type, name, name_len, ic, lowest_vcn, val,
-			val_len, ctx);
+	if (!NInoAttrList(base_ni) || type == AT_ATTRIBUTE_LIST)
+		return ntfs_attr_find(type, name, name_len, ic, val, val_len,
+				ctx);
+	return ntfs_external_attr_find(type, name, name_len, ic, lowest_vcn,
+			val, val_len, ctx);
 }
 
 /**
- * init_attr_search_ctx - initialize an attribute search context
+ * ntfs_attr_init_search_ctx - initialize an attribute search context
  * @ctx:	attribute search context to initialize
  * @ni:		ntfs inode with which to initialize the search context
  * @mrec:	mft record with which to initialize the search context
  *
  * Initialize the attribute search context @ctx with @ni and @mrec.
  */
-static inline void init_attr_search_ctx(attr_search_context *ctx,
+static inline void ntfs_attr_init_search_ctx(ntfs_attr_search_ctx *ctx,
 		ntfs_inode *ni, MFT_RECORD *mrec)
 {
 	ctx->mrec = mrec;
@@ -1666,7 +1846,7 @@ static inline void init_attr_search_ctx(attr_search_context *ctx,
 }
 
 /**
- * reinit_attr_search_ctx - reinitialize an attribute search context
+ * ntfs_attr_reinit_search_ctx - reinitialize an attribute search context
  * @ctx:	attribute search context to reinitialize
  *
  * Reinitialize the attribute search context @ctx, unmapping an associated
@@ -1675,7 +1855,7 @@ static inline void init_attr_search_ctx(attr_search_context *ctx,
  * This is used when a search for a new attribute is being started to reset
  * the search context to the beginning.
  */
-void reinit_attr_search_ctx(attr_search_context *ctx)
+void ntfs_attr_reinit_search_ctx(ntfs_attr_search_ctx *ctx)
 {
 	if (likely(!ctx->base_ntfs_ino)) {
 		/* No attribute list. */
@@ -1683,44 +1863,48 @@ void reinit_attr_search_ctx(attr_search_context *ctx)
 		/* Sanity checks are performed elsewhere. */
 		ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec +
 				le16_to_cpu(ctx->mrec->attrs_offset));
+		/*
+		 * This needs resetting due to ntfs_external_attr_find() which
+		 * can leave it set despite having zeroed ctx->base_ntfs_ino.
+		 */
+		ctx->al_entry = NULL;
 		return;
 	} /* Attribute list. */
 	if (ctx->ntfs_ino != ctx->base_ntfs_ino)
 		unmap_extent_mft_record(ctx->ntfs_ino);
-	init_attr_search_ctx(ctx, ctx->base_ntfs_ino, ctx->base_mrec);
+	ntfs_attr_init_search_ctx(ctx, ctx->base_ntfs_ino, ctx->base_mrec);
 	return;
 }
 
 /**
- * get_attr_search_ctx - allocate and initialize a new attribute search context
+ * ntfs_attr_get_search_ctx - allocate/initialize a new attribute search context
  * @ni:		ntfs inode with which to initialize the search context
  * @mrec:	mft record with which to initialize the search context
  *
  * Allocate a new attribute search context, initialize it with @ni and @mrec,
  * and return it. Return NULL if allocation failed.
  */
-attr_search_context *get_attr_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec)
+ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec)
 {
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 
 	ctx = kmem_cache_alloc(ntfs_attr_ctx_cache, SLAB_NOFS);
 	if (ctx)
-		init_attr_search_ctx(ctx, ni, mrec);
+		ntfs_attr_init_search_ctx(ctx, ni, mrec);
 	return ctx;
 }
 
 /**
- * put_attr_search_ctx - release an attribute search context
+ * ntfs_attr_put_search_ctx - release an attribute search context
  * @ctx:	attribute search context to free
  *
  * Release the attribute search context @ctx, unmapping an associated extent
  * mft record if present.
  */
-void put_attr_search_ctx(attr_search_context *ctx)
+void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx)
 {
 	if (ctx->base_ntfs_ino && ctx->ntfs_ino != ctx->base_ntfs_ino)
 		unmap_extent_mft_record(ctx->ntfs_ino);
 	kmem_cache_free(ntfs_attr_ctx_cache, ctx);
 	return;
 }
-
diff --git a/fs/ntfs/attrib.h b/fs/ntfs/attrib.h
index bbdc9deca..92899f4ff 100644
--- a/fs/ntfs/attrib.h
+++ b/fs/ntfs/attrib.h
@@ -30,7 +30,7 @@
 #include "types.h"
 #include "layout.h"
 
-static inline void init_run_list(run_list *rl)
+static inline void init_runlist(runlist *rl)
 {
 	rl->rl = NULL;
 	init_rwsem(&rl->lock);
@@ -40,14 +40,13 @@ typedef enum {
 	LCN_HOLE		= -1,	/* Keep this as highest value or die! */
 	LCN_RL_NOT_MAPPED	= -2,
 	LCN_ENOENT		= -3,
-	LCN_EINVAL		= -4,
 } LCN_SPECIAL_VALUES;
 
 /**
- * attr_search_context - used in attribute search functions
+ * ntfs_attr_search_ctx - used in attribute search functions
  * @mrec:	buffer containing mft record to search
  * @attr:	attribute record in @mrec where to begin/continue search
- * @is_first:	if true lookup_attr() begins search with @attr, else after @attr
+ * @is_first:	if true ntfs_attr_lookup() begins search with @attr, else after
  *
  * Structure must be initialized to zero before the first call to one of the
  * attribute search functions. Initialize @mrec to point to the mft record to
@@ -70,37 +69,36 @@ typedef struct {
 	ntfs_inode *base_ntfs_ino;
 	MFT_RECORD *base_mrec;
 	ATTR_RECORD *base_attr;
-} attr_search_context;
+} ntfs_attr_search_ctx;
 
-extern run_list_element *decompress_mapping_pairs(const ntfs_volume *vol,
-		const ATTR_RECORD *attr, run_list_element *old_rl);
+extern runlist_element *decompress_mapping_pairs(const ntfs_volume *vol,
+		const ATTR_RECORD *attr, runlist_element *old_rl);
 
-extern int map_run_list(ntfs_inode *ni, VCN vcn);
+extern int ntfs_map_runlist(ntfs_inode *ni, VCN vcn);
 
-extern LCN vcn_to_lcn(const run_list_element *rl, const VCN vcn);
+extern LCN ntfs_vcn_to_lcn(const runlist_element *rl, const VCN vcn);
 
-extern BOOL find_attr(const ATTR_TYPES type, const ntfschar *name,
-		const u32 name_len, const IGNORE_CASE_BOOL ic, const u8 *val,
-		const u32 val_len, attr_search_context *ctx);
+extern runlist_element *ntfs_find_vcn(ntfs_inode *ni, const VCN vcn,
+		const BOOL need_write);
 
-BOOL lookup_attr(const ATTR_TYPES type, const ntfschar *name,
+int ntfs_attr_lookup(const ATTR_TYPE type, const ntfschar *name,
 		const u32 name_len, const IGNORE_CASE_BOOL ic,
 		const VCN lowest_vcn, const u8 *val, const u32 val_len,
-		attr_search_context *ctx);
+		ntfs_attr_search_ctx *ctx);
 
-extern int load_attribute_list(ntfs_volume *vol, run_list *rl, u8 *al_start,
+extern int load_attribute_list(ntfs_volume *vol, runlist *rl, u8 *al_start,
 		const s64 size, const s64 initialized_size);
 
-static inline s64 attribute_value_length(const ATTR_RECORD *a)
+static inline s64 ntfs_attr_size(const ATTR_RECORD *a)
 {
 	if (!a->non_resident)
 		return (s64)le32_to_cpu(a->data.resident.value_length);
 	return sle64_to_cpu(a->data.non_resident.data_size);
 }
 
-extern void reinit_attr_search_ctx(attr_search_context *ctx);
-extern attr_search_context *get_attr_search_ctx(ntfs_inode *ni,
+extern void ntfs_attr_reinit_search_ctx(ntfs_attr_search_ctx *ctx);
+extern ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni,
 		MFT_RECORD *mrec);
-extern void put_attr_search_ctx(attr_search_context *ctx);
+extern void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx);
 
 #endif /* _LINUX_NTFS_ATTRIB_H */
diff --git a/fs/ntfs/collate.c b/fs/ntfs/collate.c
index 2a4a25f0e..31dd894a4 100644
--- a/fs/ntfs/collate.c
+++ b/fs/ntfs/collate.c
@@ -97,24 +97,26 @@ static ntfs_collate_func_t ntfs_do_collate0x1[4] = {
  * For speed we use the collation rule @cr as an index into two tables of
  * function pointers to call the appropriate collation function.
  */
-int ntfs_collate(ntfs_volume *vol, COLLATION_RULES cr,
+int ntfs_collate(ntfs_volume *vol, COLLATION_RULE cr,
 		const void *data1, const int data1_len,
 		const void *data2, const int data2_len) {
+	int i;
+
 	ntfs_debug("Entering.");
 	/*
 	 * FIXME:  At the moment we only support COLLATION_BINARY and
 	 * COLLATION_NTOFS_ULONG, so we BUG() for everything else for now.
 	 */
 	BUG_ON(cr != COLLATION_BINARY && cr != COLLATION_NTOFS_ULONG);
-	cr = le32_to_cpu(cr);
-	BUG_ON(cr < 0);
-	if (cr <= 0x02)
-		return ntfs_do_collate0x0[cr](vol, data1, data1_len,
+	i = le32_to_cpu(cr);
+	BUG_ON(i < 0);
+	if (i <= 0x02)
+		return ntfs_do_collate0x0[i](vol, data1, data1_len,
 				data2, data2_len);
-	BUG_ON(cr < 0x10);
-	cr -= 0x10;
-	if (likely(cr <= 3))
-		return ntfs_do_collate0x1[cr](vol, data1, data1_len,
+	BUG_ON(i < 0x10);
+	i -= 0x10;
+	if (likely(i <= 3))
+		return ntfs_do_collate0x1[i](vol, data1, data1_len,
 				data2, data2_len);
 	BUG();
 	return 0;
diff --git a/fs/ntfs/collate.h b/fs/ntfs/collate.h
index 14a67a61b..e027f36fc 100644
--- a/fs/ntfs/collate.h
+++ b/fs/ntfs/collate.h
@@ -26,7 +26,9 @@
 #include "types.h"
 #include "volume.h"
 
-static inline BOOL ntfs_is_collation_rule_supported(COLLATION_RULES cr) {
+static inline BOOL ntfs_is_collation_rule_supported(COLLATION_RULE cr) {
+	int i;
+
 	/*
 	 * FIXME:  At the moment we only support COLLATION_BINARY and
 	 * COLLATION_NTOFS_ULONG, so we return false for everything else for
@@ -34,14 +36,14 @@ static inline BOOL ntfs_is_collation_rule_supported(COLLATION_RULES cr) {
 	 */
 	if (unlikely(cr != COLLATION_BINARY && cr != COLLATION_NTOFS_ULONG))
 		return FALSE;
-	cr = le32_to_cpu(cr);
-	if (likely(((cr >= 0) && (cr <= 0x02)) ||
-			((cr >= 0x10) && (cr <= 0x13))))
+	i = le32_to_cpu(cr);
+	if (likely(((i >= 0) && (i <= 0x02)) ||
+			((i >= 0x10) && (i <= 0x13))))
 		return TRUE;
 	return FALSE;
 }
 
-extern int ntfs_collate(ntfs_volume *vol, COLLATION_RULES cr,
+extern int ntfs_collate(ntfs_volume *vol, COLLATION_RULE cr,
 		const void *data1, const int data1_len,
 		const void *data2, const int data2_len);
 
diff --git a/fs/ntfs/compress.c b/fs/ntfs/compress.c
index c39391bab..cc3aac147 100644
--- a/fs/ntfs/compress.c
+++ b/fs/ntfs/compress.c
@@ -203,7 +203,7 @@ do_next_sb:
 	 * position in the compression block is one byte before its end so the
 	 * first two checks do not detect it.
 	 */
-	if (cb == cb_end || !le16_to_cpup((u16*)cb) ||
+	if (cb == cb_end || !le16_to_cpup((le16*)cb) ||
 			(*dest_index == dest_max_index &&
 			*dest_ofs == dest_max_ofs)) {
 		int i;
@@ -255,7 +255,7 @@ return_error:
 
 	/* Setup the current sub-block source pointers and validate range. */
 	cb_sb_start = cb;
-	cb_sb_end = cb_sb_start + (le16_to_cpup((u16*)cb) & NTFS_SB_SIZE_MASK)
+	cb_sb_end = cb_sb_start + (le16_to_cpup((le16*)cb) & NTFS_SB_SIZE_MASK)
 			+ 3;
 	if (cb_sb_end > cb_end)
 		goto return_overflow;
@@ -277,7 +277,7 @@ return_error:
 	dp_addr = (u8*)page_address(dp) + do_sb_start;
 
 	/* Now, we are ready to process the current sub-block (sb). */
-	if (!(le16_to_cpup((u16*)cb) & NTFS_SB_IS_COMPRESSED)) {
+	if (!(le16_to_cpup((le16*)cb) & NTFS_SB_IS_COMPRESSED)) {
 		ntfs_debug("Found uncompressed sub-block.");
 		/* This sb is not compressed, just copy it into destination. */
 
@@ -382,7 +382,7 @@ do_next_tag:
 			lg++;
 
 		/* Get the phrase token into i. */
-		pt = le16_to_cpup((u16*)cb);
+		pt = le16_to_cpup((le16*)cb);
 
 		/*
 		 * Calculate starting position of the byte sequence in
@@ -478,7 +478,7 @@ int ntfs_read_compressed_block(struct page *page)
 	ntfs_inode *ni = NTFS_I(mapping->host);
 	ntfs_volume *vol = ni->vol;
 	struct super_block *sb = vol->sb;
-	run_list_element *rl;
+	runlist_element *rl;
 	unsigned long block_size = sb->s_blocksize;
 	unsigned char block_size_bits = sb->s_blocksize_bits;
 	u8 *cb, *cb_pos, *cb_end;
@@ -575,7 +575,7 @@ int ntfs_read_compressed_block(struct page *page)
 	}
 
 	/*
-	 * We have the run list, and all the destination pages we need to fill.
+	 * We have the runlist, and all the destination pages we need to fill.
 	 * Now read the first compression block.
 	 */
 	cur_page = 0;
@@ -593,14 +593,14 @@ do_next_cb:
 
 		if (!rl) {
 lock_retry_remap:
-			down_read(&ni->run_list.lock);
-			rl = ni->run_list.rl;
+			down_read(&ni->runlist.lock);
+			rl = ni->runlist.rl;
 		}
 		if (likely(rl != NULL)) {
 			/* Seek to element containing target vcn. */
 			while (rl->length && rl[1].vcn <= vcn)
 				rl++;
-			lcn = vcn_to_lcn(rl, vcn);
+			lcn = ntfs_vcn_to_lcn(rl, vcn);
 		} else
 			lcn = (LCN)LCN_RL_NOT_MAPPED;
 		ntfs_debug("Reading vcn = 0x%llx, lcn = 0x%llx.",
@@ -617,11 +617,11 @@ lock_retry_remap:
 				goto rl_err;
 			is_retry = TRUE;
 			/*
-			 * Attempt to map run list, dropping lock for the
+			 * Attempt to map runlist, dropping lock for the
 			 * duration.
 			 */
-			up_read(&ni->run_list.lock);
-			if (!map_run_list(ni, vcn))
+			up_read(&ni->runlist.lock);
+			if (!ntfs_map_runlist(ni, vcn))
 				goto lock_retry_remap;
 			goto map_rl_err;
 		}
@@ -638,7 +638,7 @@ lock_retry_remap:
 
 	/* Release the lock if we took it. */
 	if (rl)
-		up_read(&ni->run_list.lock);
+		up_read(&ni->runlist.lock);
 
 	/* Setup and initiate io on all buffer heads. */
 	for (i = 0; i < nr_bhs; i++) {
@@ -920,18 +920,18 @@ read_err:
 	goto err_out;
 
 map_rl_err:
-	ntfs_error(vol->sb, "map_run_list() failed. Cannot read compression "
-			"block.");
+	ntfs_error(vol->sb, "ntfs_map_runlist() failed. Cannot read "
+			"compression block.");
 	goto err_out;
 
 rl_err:
-	up_read(&ni->run_list.lock);
-	ntfs_error(vol->sb, "vcn_to_lcn() failed. Cannot read compression "
-			"block.");
+	up_read(&ni->runlist.lock);
+	ntfs_error(vol->sb, "ntfs_vcn_to_lcn() failed. Cannot read "
+			"compression block.");
 	goto err_out;
 
 getblk_err:
-	up_read(&ni->run_list.lock);
+	up_read(&ni->runlist.lock);
 	ntfs_error(vol->sb, "getblk() failed. Cannot read compression block.");
 
 err_out:
diff --git a/fs/ntfs/debug.c b/fs/ntfs/debug.c
index 8ba061051..6723f1826 100644
--- a/fs/ntfs/debug.c
+++ b/fs/ntfs/debug.c
@@ -127,22 +127,21 @@ void __ntfs_debug (const char *file, int line, const char *function,
 	va_start(args, fmt);
 	vsnprintf(err_buf, sizeof(err_buf), fmt, args);
 	va_end(args);
-	printk(KERN_DEBUG "NTFS-fs DEBUG (%s, %d): %s: %s\n",
+	printk(KERN_DEBUG "NTFS-fs DEBUG (%s, %d): %s(): %s\n",
 		file, line, flen ? function : "", err_buf);
 	spin_unlock(&err_buf_lock);
 }
 
-/* Dump a run list. Caller has to provide synchronisation for @rl. */
-void ntfs_debug_dump_runlist(const run_list_element *rl)
+/* Dump a runlist. Caller has to provide synchronisation for @rl. */
+void ntfs_debug_dump_runlist(const runlist_element *rl)
 {
 	int i;
 	const char *lcn_str[5] = { "LCN_HOLE         ", "LCN_RL_NOT_MAPPED",
-				   "LCN_ENOENT       ", "LCN_EINVAL       ",
-				   "LCN_unknown      " };
+				   "LCN_ENOENT       ", "LCN_unknown      " };
 
 	if (!debug_msgs)
 		return;
-	printk(KERN_DEBUG "NTFS-fs DEBUG: Dumping run list (values "
+	printk(KERN_DEBUG "NTFS-fs DEBUG: Dumping runlist (values "
 			"in hex):\n");
 	if (!rl) {
 		printk(KERN_DEBUG "Run list not present.\n");
@@ -155,17 +154,17 @@ void ntfs_debug_dump_runlist(const run_list_element *rl)
 		if (lcn < (LCN)0) {
 			int index = -lcn - 1;
 
-			if (index > -LCN_EINVAL - 1)
-				index = 4;
+			if (index > -LCN_ENOENT - 1)
+				index = 3;
 			printk(KERN_DEBUG "%-16Lx %s %-16Lx%s\n",
 				(rl + i)->vcn, lcn_str[index],
 				(rl + i)->length, (rl + i)->length ?
-				"" : " (run list end)");
+				"" : " (runlist end)");
 		} else
 			printk(KERN_DEBUG "%-16Lx %-16Lx  %-16Lx%s\n",
 				(rl + i)->vcn, (rl + i)->lcn,
 				(rl + i)->length, (rl + i)->length ?
-				"" : " (run list end)");
+				"" : " (runlist end)");
 		if (!(rl + i)->length)
 			break;
 	}
diff --git a/fs/ntfs/debug.h b/fs/ntfs/debug.h
index e90da5153..63c626022 100644
--- a/fs/ntfs/debug.h
+++ b/fs/ntfs/debug.h
@@ -51,7 +51,7 @@ extern void __ntfs_debug (const char *file, int line, const char *function,
 #define ntfs_debug(f, a...)						\
 	__ntfs_debug(__FILE__, __LINE__, __FUNCTION__, f, ##a)
 
-extern void ntfs_debug_dump_runlist(const run_list_element *rl);
+extern void ntfs_debug_dump_runlist(const runlist_element *rl);
 
 #else	/* !DEBUG */
 
diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c
index 246862279..ed9838e0c 100644
--- a/fs/ntfs/dir.c
+++ b/fs/ntfs/dir.c
@@ -28,8 +28,7 @@
  * The little endian Unicode string $I30 as a global constant.
  */
 ntfschar I30[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('I'),
-		const_cpu_to_le16('3'),	const_cpu_to_le16('0'),
-		const_cpu_to_le16(0) };
+		const_cpu_to_le16('3'),	const_cpu_to_le16('0'), 0 };
 
 /**
  * ntfs_lookup_inode_by_name - find an inode in a directory given its name
@@ -83,7 +82,7 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const ntfschar *uname,
 	INDEX_ALLOCATION *ia;
 	u8 *index_end;
 	u64 mref;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	int err, rc;
 	VCN vcn, old_vcn;
 	struct address_space *ia_mapping;
@@ -95,22 +94,26 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const ntfschar *uname,
 	BUG_ON(NInoAttr(dir_ni));
 	/* Get hold of the mft record for the directory. */
 	m = map_mft_record(dir_ni);
-	if (unlikely(IS_ERR(m))) {
+	if (IS_ERR(m)) {
 		ntfs_error(sb, "map_mft_record() failed with error code %ld.",
 				-PTR_ERR(m));
 		return ERR_MREF(PTR_ERR(m));
 	}
-	ctx = get_attr_search_ctx(dir_ni, m);
+	ctx = ntfs_attr_get_search_ctx(dir_ni, m);
 	if (unlikely(!ctx)) {
 		err = -ENOMEM;
 		goto err_out;
 	}
 	/* Find the index root attribute in the mft record. */
-	if (!lookup_attr(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL, 0,
-			ctx)) {
-		ntfs_error(sb, "Index root attribute missing in directory "
-				"inode 0x%lx.", dir_ni->mft_no);
-		err = -EIO;
+	err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL,
+			0, ctx);
+	if (unlikely(err)) {
+		if (err == -ENOENT) {
+			ntfs_error(sb, "Index root attribute missing in "
+					"directory inode 0x%lx.",
+					dir_ni->mft_no);
+			err = -EIO;
+		}
 		goto err_out;
 	}
 	/* Get to the index root value (it's been verified in read_inode). */
@@ -179,7 +182,7 @@ found_it:
 				*res = NULL;
 			}
 			mref = le64_to_cpu(ie->data.dir.indexed_file);
-			put_attr_search_ctx(ctx);
+			ntfs_attr_put_search_ctx(ctx);
 			unmap_mft_record(dir_ni);
 			return mref;
 		}
@@ -278,7 +281,7 @@ found_it:
 	 */
 	if (!(ie->flags & INDEX_ENTRY_NODE)) {
 		if (name) {
-			put_attr_search_ctx(ctx);
+			ntfs_attr_put_search_ctx(ctx);
 			unmap_mft_record(dir_ni);
 			return name->mref;
 		}
@@ -295,13 +298,13 @@ found_it:
 		goto err_out;
 	}
 	/* Get the starting vcn of the index_block holding the child node. */
-	vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8);
+	vcn = sle64_to_cpup((sle64*)((u8*)ie + le16_to_cpu(ie->length) - 8));
 	ia_mapping = VFS_I(dir_ni)->i_mapping;
 	/*
 	 * We are done with the index root and the mft record. Release them,
 	 * otherwise we deadlock with ntfs_map_page().
 	 */
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(dir_ni);
 	m = NULL;
 	ctx = NULL;
@@ -547,7 +550,8 @@ found_it2:
 		}
 		/* Child node present, descend into it. */
 		old_vcn = vcn;
-		vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8);
+		vcn = sle64_to_cpup((sle64*)((u8*)ie +
+				le16_to_cpu(ie->length) - 8));
 		if (vcn >= 0) {
 			/* If vcn is in the same page cache page as old_vcn we
 			 * recycle the mapped page. */
@@ -582,7 +586,7 @@ unm_err_out:
 	ntfs_unmap_page(page);
 err_out:
 	if (ctx)
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 	if (m)
 		unmap_mft_record(dir_ni);
 	if (name) {
@@ -634,7 +638,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const ntfschar *uname,
 	INDEX_ALLOCATION *ia;
 	u8 *index_end;
 	u64 mref;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	int err, rc;
 	IGNORE_CASE_BOOL ic;
 	VCN vcn, old_vcn;
@@ -649,17 +653,21 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const ntfschar *uname,
 				-PTR_ERR(m));
 		return ERR_MREF(PTR_ERR(m));
 	}
-	ctx = get_attr_search_ctx(dir_ni, m);
+	ctx = ntfs_attr_get_search_ctx(dir_ni, m);
 	if (!ctx) {
 		err = -ENOMEM;
 		goto err_out;
 	}
 	/* Find the index root attribute in the mft record. */
-	if (!lookup_attr(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL, 0,
-			ctx)) {
-		ntfs_error(sb, "Index root attribute missing in directory "
-				"inode 0x%lx.", dir_ni->mft_no);
-		err = -EIO;
+	err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL,
+			0, ctx);
+	if (unlikely(err)) {
+		if (err == -ENOENT) {
+			ntfs_error(sb, "Index root attribute missing in "
+					"directory inode 0x%lx.",
+					dir_ni->mft_no);
+			err = -EIO;
+		}
 		goto err_out;
 	}
 	/* Get to the index root value (it's been verified in read_inode). */
@@ -710,7 +718,7 @@ u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const ntfschar *uname,
 				vol->upcase, vol->upcase_len)) {
 found_it:
 			mref = le64_to_cpu(ie->data.dir.indexed_file);
-			put_attr_search_ctx(ctx);
+			ntfs_attr_put_search_ctx(ctx);
 			unmap_mft_record(dir_ni);
 			return mref;
 		}
@@ -776,7 +784,7 @@ found_it:
 	 * We are done with the index root and the mft record. Release them,
 	 * otherwise we deadlock with ntfs_map_page().
 	 */
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(dir_ni);
 	m = NULL;
 	ctx = NULL;
@@ -979,7 +987,7 @@ unm_err_out:
 	ntfs_unmap_page(page);
 err_out:
 	if (ctx)
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 	if (m)
 		unmap_mft_record(dir_ni);
 	return ERR_MREF(err);
@@ -991,23 +999,11 @@ dir_err_out:
 
 #endif
 
-typedef union {
-	INDEX_ROOT *ir;
-	INDEX_ALLOCATION *ia;
-} index_union __attribute__ ((__transparent_union__));
-
-typedef enum {
-	INDEX_TYPE_ROOT,	/* index root */
-	INDEX_TYPE_ALLOCATION,	/* index allocation */
-} INDEX_TYPE;
-
 /**
  * ntfs_filldir - ntfs specific filldir method
  * @vol:	current ntfs volume
  * @fpos:	position in the directory
  * @ndir:	ntfs inode of current directory
- * @index_type:	specifies whether @iu is an index root or an index allocation
- * @iu:		index root or index allocation attribute to which @ie belongs
  * @ia_page:	page in which the index allocation buffer @ie is in resides
  * @ie:		current index entry
  * @name:	buffer to use for the converted name
@@ -1017,9 +1013,8 @@ typedef enum {
  * Convert the Unicode @name to the loaded NLS and pass it to the @filldir
  * callback.
  *
- * If @index_type is INDEX_TYPE_ALLOCATION, @ia_page is the locked page
- * containing the index allocation block containing the index entry @ie.
- * Otherwise, @ia_page is NULL.
+ * If @ia_page is not NULL it is the locked page containing the index
+ * allocation block containing the index entry @ie.
  *
  * Note, we drop (and then reacquire) the page lock on @ia_page across the
  * @filldir() call otherwise we would deadlock with NFSd when it calls ->lookup
@@ -1027,9 +1022,8 @@ typedef enum {
  * retake the lock if we are returning a non-zero value as ntfs_readdir()
  * would need to drop the lock immediately anyway.
  */
-static inline int ntfs_filldir(ntfs_volume *vol, loff_t *fpos,
-		ntfs_inode *ndir, const INDEX_TYPE index_type,
-		index_union iu, struct page *ia_page, INDEX_ENTRY *ie,
+static inline int ntfs_filldir(ntfs_volume *vol, loff_t fpos,
+		ntfs_inode *ndir, struct page *ia_page, INDEX_ENTRY *ie,
 		u8 *name, void *dirent, filldir_t filldir)
 {
 	unsigned long mref;
@@ -1037,14 +1031,6 @@ static inline int ntfs_filldir(ntfs_volume *vol, loff_t *fpos,
 	unsigned dt_type;
 	FILE_NAME_TYPE_FLAGS name_type;
 
-	/* Advance the position even if going to skip the entry. */
-	if (index_type == INDEX_TYPE_ALLOCATION)
-		*fpos = (u8*)ie - (u8*)iu.ia +
-				(sle64_to_cpu(iu.ia->index_block_vcn) <<
-				ndir->itype.index.vcn_size_bits) +
-				vol->mft_record_size;
-	else /* if (index_type == INDEX_TYPE_ROOT) */
-		*fpos = (u8*)ie - (u8*)iu.ir;
 	name_type = ie->key.file_name.file_name_type;
 	if (name_type == FILE_NAME_DOS) {
 		ntfs_debug("Skipping DOS name space entry.");
@@ -1076,14 +1062,14 @@ static inline int ntfs_filldir(ntfs_volume *vol, loff_t *fpos,
 	 * Drop the page lock otherwise we deadlock with NFS when it calls
 	 * ->lookup since ntfs_lookup() will lock the same page.
 	 */
-	if (index_type == INDEX_TYPE_ALLOCATION)
+	if (ia_page)
 		unlock_page(ia_page);
 	ntfs_debug("Calling filldir for %s with len %i, fpos 0x%llx, inode "
-			"0x%lx, DT_%s.", name, name_len, *fpos, mref,
+			"0x%lx, DT_%s.", name, name_len, fpos, mref,
 			dt_type == DT_DIR ? "DIR" : "REG");
-	rc = filldir(dirent, name, name_len, *fpos, mref, dt_type);
+	rc = filldir(dirent, name, name_len, fpos, mref, dt_type);
 	/* Relock the page but not if we are aborting ->readdir. */
-	if (!rc && index_type == INDEX_TYPE_ALLOCATION)
+	if (!rc && ia_page)
 		lock_page(ia_page);
 	return rc;
 }
@@ -1125,7 +1111,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 	struct address_space *ia_mapping, *bmp_mapping;
 	struct page *bmp_page = NULL, *ia_page = NULL;
 	u8 *kaddr, *bmp, *index_end;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 
 	fpos = filp->f_pos;
 	ntfs_debug("Entering for inode 0x%lx, fpos 0x%llx.",
@@ -1170,12 +1156,12 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 		goto skip_index_root;
 	/* Get hold of the mft record for the directory. */
 	m = map_mft_record(ndir);
-	if (unlikely(IS_ERR(m))) {
+	if (IS_ERR(m)) {
 		err = PTR_ERR(m);
 		m = NULL;
 		goto err_out;
 	}
-	ctx = get_attr_search_ctx(ndir, m);
+	ctx = ntfs_attr_get_search_ctx(ndir, m);
 	if (unlikely(!ctx)) {
 		err = -ENOMEM;
 		goto err_out;
@@ -1183,8 +1169,9 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 	/* Get the offset into the index root attribute. */
 	ir_pos = (s64)fpos;
 	/* Find the index root attribute in the mft record. */
-	if (unlikely(!lookup_attr(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0,
-			NULL, 0, ctx))) {
+	err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL,
+			0, ctx);
+	if (unlikely(err)) {
 		ntfs_error(sb, "Index root attribute missing in directory "
 				"inode 0x%lx.", vdir->i_ino);
 		goto err_out;
@@ -1208,7 +1195,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 	/* Copy the index root value (it has been verified in read_inode). */
 	memcpy(ir, (u8*)ctx->attr +
 			le16_to_cpu(ctx->attr->data.resident.value_offset), rc);
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(ndir);
 	ctx = NULL;
 	m = NULL;
@@ -1235,9 +1222,11 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 		/* Skip index root entry if continuing previous readdir. */
 		if (ir_pos > (u8*)ie - (u8*)ir)
 			continue;
+		/* Advance the position even if going to skip the entry. */
+		fpos = (u8*)ie - (u8*)ir;
 		/* Submit the name to the filldir callback. */
-		rc = ntfs_filldir(vol, &fpos, ndir, INDEX_TYPE_ROOT, ir, NULL,
-				ie, name, dirent, filldir);
+		rc = ntfs_filldir(vol, fpos, ndir, NULL, ie, name, dirent,
+				filldir);
 		if (rc) {
 			kfree(ir);
 			goto abort;
@@ -1261,7 +1250,7 @@ skip_index_root:
 	if (unlikely(!bmp_vi)) {
 		ntfs_debug("Inode 0x%lx, regetting index bitmap.", vdir->i_ino);
 		bmp_vi = ntfs_attr_iget(vdir, AT_BITMAP, I30, 4);
-		if (unlikely(IS_ERR(bmp_vi))) {
+		if (IS_ERR(bmp_vi)) {
 			ntfs_error(sb, "Failed to get bitmap attribute.");
 			err = PTR_ERR(bmp_vi);
 			goto err_out;
@@ -1286,7 +1275,7 @@ get_next_bmp_page:
 			((PAGE_CACHE_SIZE * 8) - 1));
 	bmp_page = ntfs_map_page(bmp_mapping,
 			bmp_pos >> (3 + PAGE_CACHE_SHIFT));
-	if (unlikely(IS_ERR(bmp_page))) {
+	if (IS_ERR(bmp_page)) {
 		ntfs_error(sb, "Reading index bitmap failed.");
 		err = PTR_ERR(bmp_page);
 		bmp_page = NULL;
@@ -1327,7 +1316,7 @@ find_next_index_buffer:
 		 * reading it from disk if necessary.
 		 */
 		ia_page = ntfs_map_page(ia_mapping, ia_pos >> PAGE_CACHE_SHIFT);
-		if (unlikely(IS_ERR(ia_page))) {
+		if (IS_ERR(ia_page)) {
 			ntfs_error(sb, "Reading index allocation data failed.");
 			err = PTR_ERR(ia_page);
 			ia_page = NULL;
@@ -1411,14 +1400,19 @@ find_next_index_buffer:
 		/* Skip index block entry if continuing previous readdir. */
 		if (ia_pos - ia_start > (u8*)ie - (u8*)ia)
 			continue;
+		/* Advance the position even if going to skip the entry. */
+		fpos = (u8*)ie - (u8*)ia +
+				(sle64_to_cpu(ia->index_block_vcn) <<
+				ndir->itype.index.vcn_size_bits) +
+				vol->mft_record_size;
 		/*
 		 * Submit the name to the @filldir callback.  Note,
 		 * ntfs_filldir() drops the lock on @ia_page but it retakes it
 		 * before returning, unless a non-zero value is returned in
 		 * which case the page is left unlocked.
 		 */
-		rc = ntfs_filldir(vol, &fpos, ndir, INDEX_TYPE_ALLOCATION, ia,
-				ia_page, ie, name, dirent, filldir);
+		rc = ntfs_filldir(vol, fpos, ndir, ia_page, ie, name, dirent,
+				filldir);
 		if (rc) {
 			/* @ia_page is already unlocked in this case. */
 			ntfs_unmap_page(ia_page);
@@ -1460,7 +1454,7 @@ err_out:
 	if (name)
 		kfree(name);
 	if (ctx)
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 	if (m)
 		unmap_mft_record(ndir);
 	if (!err)
@@ -1495,10 +1489,69 @@ static int ntfs_dir_open(struct inode *vi, struct file *filp)
 	return 0;
 }
 
+#ifdef NTFS_RW
+
+/**
+ * ntfs_dir_fsync - sync a directory to disk
+ * @filp:	directory to be synced
+ * @dentry:	dentry describing the directory to sync
+ * @datasync:	if non-zero only flush user data and not metadata
+ *
+ * Data integrity sync of a directory to disk.  Used for fsync, fdatasync, and
+ * msync system calls.  This function is based on file.c::ntfs_file_fsync().
+ *
+ * Write the mft record and all associated extent mft records as well as the
+ * $INDEX_ALLOCATION and $BITMAP attributes and then sync the block device.
+ *
+ * If @datasync is true, we do not wait on the inode(s) to be written out
+ * but we always wait on the page cache pages to be written out.
+ *
+ * Note: In the past @filp could be NULL so we ignore it as we don't need it
+ * anyway.
+ *
+ * Locking: Caller must hold i_sem on the inode.
+ *
+ * TODO: We should probably also write all attribute/index inodes associated
+ * with this inode but since we have no simple way of getting to them we ignore
+ * this problem for now.  We do write the $BITMAP attribute if it is present
+ * which is the important one for a directory so things are not too bad.
+ */
+static int ntfs_dir_fsync(struct file *filp, struct dentry *dentry,
+		int datasync)
+{
+	struct inode *vi = dentry->d_inode;
+	ntfs_inode *ni = NTFS_I(vi);
+	int err, ret;
+
+	ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
+	BUG_ON(!S_ISDIR(vi->i_mode));
+	if (NInoIndexAllocPresent(ni) && ni->itype.index.bmp_ino)
+		write_inode_now(ni->itype.index.bmp_ino, !datasync);
+	ret = ntfs_write_inode(vi, 1);
+	write_inode_now(vi, !datasync);
+	err = sync_blockdev(vi->i_sb->s_bdev);
+	if (unlikely(err && !ret))
+		ret = err;
+	if (likely(!ret))
+		ntfs_debug("Done.");
+	else
+		ntfs_warning(vi->i_sb, "Failed to f%ssync inode 0x%lx.  Error "
+				"%u.", datasync ? "data" : "", vi->i_ino, -ret);
+	return ret;
+}
+
+#endif /* NTFS_RW */
+
 struct file_operations ntfs_dir_ops = {
 	.llseek		= generic_file_llseek,	/* Seek inside directory. */
 	.read		= generic_read_dir,	/* Return -EISDIR. */
 	.readdir	= ntfs_readdir,		/* Read directory contents. */
+#ifdef NTFS_RW
+	.fsync		= ntfs_dir_fsync,	/* Sync a directory to disk. */
+	/*.aio_fsync	= ,*/			/* Sync all outstanding async
+						   i/o operations on a kiocb. */
+#endif /* NTFS_RW */
+	/*.ioctl	= ,*/			/* Perform function on the
+						   mounted filesystem. */
 	.open		= ntfs_dir_open,	/* Open directory. */
 };
-
diff --git a/fs/ntfs/endian.h b/fs/ntfs/endian.h
index 98909576a..927b5bf04 100644
--- a/fs/ntfs/endian.h
+++ b/fs/ntfs/endian.h
@@ -24,24 +24,70 @@
 #define _LINUX_NTFS_ENDIAN_H
 
 #include <asm/byteorder.h>
+#include "types.h"
 
 /*
- * Signed endianness conversion defines.
+ * Signed endianness conversion functions.
  */
-#define sle16_to_cpu(x)		((s16)__le16_to_cpu((s16)(x)))
-#define sle32_to_cpu(x)		((s32)__le32_to_cpu((s32)(x)))
-#define sle64_to_cpu(x)		((s64)__le64_to_cpu((s64)(x)))
 
-#define sle16_to_cpup(x)	((s16)__le16_to_cpu(*(s16*)(x)))
-#define sle32_to_cpup(x)	((s32)__le32_to_cpu(*(s32*)(x)))
-#define sle64_to_cpup(x)	((s64)__le64_to_cpu(*(s64*)(x)))
+static inline s16 sle16_to_cpu(sle16 x)
+{
+	return le16_to_cpu((__force le16)x);
+}
 
-#define cpu_to_sle16(x)		((s16)__cpu_to_le16((s16)(x)))
-#define cpu_to_sle32(x)		((s32)__cpu_to_le32((s32)(x)))
-#define cpu_to_sle64(x)		((s64)__cpu_to_le64((s64)(x)))
+static inline s32 sle32_to_cpu(sle32 x)
+{
+	return le32_to_cpu((__force le32)x);
+}
 
-#define cpu_to_sle16p(x)	((s16)__cpu_to_le16(*(s16*)(x)))
-#define cpu_to_sle32p(x)	((s32)__cpu_to_le32(*(s32*)(x)))
-#define cpu_to_sle64p(x)	((s64)__cpu_to_le64(*(s64*)(x)))
+static inline s64 sle64_to_cpu(sle64 x)
+{
+	return le64_to_cpu((__force le64)x);
+}
+
+static inline s16 sle16_to_cpup(sle16 *x)
+{
+	return le16_to_cpu(*(__force le16*)x);
+}
+
+static inline s32 sle32_to_cpup(sle32 *x)
+{
+	return le32_to_cpu(*(__force le32*)x);
+}
+
+static inline s64 sle64_to_cpup(sle64 *x)
+{
+	return le64_to_cpu(*(__force le64*)x);
+}
+
+static inline sle16 cpu_to_sle16(s16 x)
+{
+	return (__force sle16)cpu_to_le16(x);
+}
+
+static inline sle32 cpu_to_sle32(s32 x)
+{
+	return (__force sle32)cpu_to_le32(x);
+}
+
+static inline sle64 cpu_to_sle64(s64 x)
+{
+	return (__force sle64)cpu_to_le64(x);
+}
+
+static inline sle16 cpu_to_sle16p(s16 *x)
+{
+	return (__force sle16)cpu_to_le16(*x);
+}
+
+static inline sle32 cpu_to_sle32p(s32 *x)
+{
+	return (__force sle32)cpu_to_le32(*x);
+}
+
+static inline sle64 cpu_to_sle64p(s64 *x)
+{
+	return (__force sle64)cpu_to_le64(*x);
+}
 
 #endif /* _LINUX_NTFS_ENDIAN_H */
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index f034d826d..c7880d55b 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -48,26 +48,101 @@ static int ntfs_file_open(struct inode *vi, struct file *filp)
 	return generic_file_open(vi, filp);
 }
 
+#ifdef NTFS_RW
+
+/**
+ * ntfs_file_fsync - sync a file to disk
+ * @filp:	file to be synced
+ * @dentry:	dentry describing the file to sync
+ * @datasync:	if non-zero only flush user data and not metadata
+ *
+ * Data integrity sync of a file to disk.  Used for fsync, fdatasync, and msync
+ * system calls.  This function is inspired by fs/buffer.c::file_fsync().
+ *
+ * If @datasync is false, write the mft record and all associated extent mft
+ * records as well as the $DATA attribute and then sync the block device.
+ *
+ * If @datasync is true and the attribute is non-resident, we skip the writing
+ * of the mft record and all associated extent mft records (this might still
+ * happen due to the write_inode_now() call).
+ *
+ * Also, if @datasync is true, we do not wait on the inode to be written out
+ * but we always wait on the page cache pages to be written out.
+ *
+ * Note: In the past @filp could be NULL so we ignore it as we don't need it
+ * anyway.
+ *
+ * Locking: Caller must hold i_sem on the inode.
+ *
+ * TODO: We should probably also write all attribute/index inodes associated
+ * with this inode but since we have no simple way of getting to them we ignore
+ * this problem for now.
+ */
+static int ntfs_file_fsync(struct file *filp, struct dentry *dentry,
+		int datasync)
+{
+	struct inode *vi = dentry->d_inode;
+	int err, ret = 0;
+
+	ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
+	BUG_ON(S_ISDIR(vi->i_mode));
+	if (!datasync || !NInoNonResident(NTFS_I(vi)))
+		ret = ntfs_write_inode(vi, 1);
+	write_inode_now(vi, !datasync);
+	err = sync_blockdev(vi->i_sb->s_bdev);
+	if (unlikely(err && !ret))
+		ret = err;
+	if (likely(!ret))
+		ntfs_debug("Done.");
+	else
+		ntfs_warning(vi->i_sb, "Failed to f%ssync inode 0x%lx.  Error "
+				"%u.", datasync ? "data" : "", vi->i_ino, -ret);
+	return ret;
+}
+
+#endif /* NTFS_RW */
+
 struct file_operations ntfs_file_ops = {
-	.llseek		= generic_file_llseek,	/* Seek inside file. */
-	.read		= generic_file_read,	/* Read from file. */
+	.llseek		= generic_file_llseek,	  /* Seek inside file. */
+	.read		= generic_file_read,	  /* Read from file. */
+	.aio_read	= generic_file_aio_read,  /* Async read from file. */
+	.readv		= generic_file_readv,	  /* Read from file. */
 #ifdef NTFS_RW
-	.write		= generic_file_write,	/* Write to a file. */
-#endif
-	.mmap		= generic_file_mmap,	/* Mmap file. */
-	.sendfile	= generic_file_sendfile,/* Zero-copy data send with the
-						   data source being on the
-						   ntfs partition. We don't
-						   need to care about the data
-						   destination. */
-	.open		= ntfs_file_open,	/* Open file. */
+	.write		= generic_file_write,	  /* Write to file. */
+	.aio_write	= generic_file_aio_write, /* Async write to file. */
+	.writev		= generic_file_writev,	  /* Write to file. */
+	/*.release	= ,*/			  /* Last file is closed.  See
+						     fs/ext2/file.c::
+						     ext2_release_file() for
+						     how to use this to discard
+						     preallocated space for
+						     write opened files. */
+	.fsync		= ntfs_file_fsync,	  /* Sync a file to disk. */
+	/*.aio_fsync	= ,*/			  /* Sync all outstanding async
+						     i/o operations on a
+						     kiocb. */
+#endif /* NTFS_RW */
+	/*.ioctl	= ,*/			  /* Perform function on the
+						     mounted filesystem. */
+	.mmap		= generic_file_mmap,	  /* Mmap file. */
+	.open		= ntfs_file_open,	  /* Open file. */
+	.sendfile	= generic_file_sendfile,  /* Zero-copy data send with
+						     the data source being on
+						     the ntfs partition.  We
+						     do not need to care about
+						     the data destination. */
+	/*.sendpage	= ,*/			  /* Zero-copy data send with
+						     the data destination being
+						     on the ntfs partition.  We
+						     do not need to care about
+						     the data source. */
 };
 
 struct inode_operations ntfs_file_inode_ops = {
 #ifdef NTFS_RW
 	.truncate	= ntfs_truncate,
 	.setattr	= ntfs_setattr,
-#endif
+#endif /* NTFS_RW */
 };
 
 struct file_operations ntfs_empty_file_ops = {};
diff --git a/fs/ntfs/index.c b/fs/ntfs/index.c
index f4396a02a..b19a4882b 100644
--- a/fs/ntfs/index.c
+++ b/fs/ntfs/index.c
@@ -65,7 +65,7 @@ void ntfs_index_ctx_put(ntfs_index_context *ictx)
 	if (ictx->entry) {
 		if (ictx->is_in_root) {
 			if (ictx->actx)
-				put_attr_search_ctx(ictx->actx);
+				ntfs_attr_put_search_ctx(ictx->actx);
 			if (ictx->base_ni)
 				unmap_mft_record(ictx->base_ni);
 		} else {
@@ -125,6 +125,7 @@ void ntfs_index_ctx_put(ntfs_index_context *ictx)
 int ntfs_index_lookup(const void *key, const int key_len,
 		ntfs_index_context *ictx)
 {
+	VCN vcn, old_vcn;
 	ntfs_inode *idx_ni = ictx->idx_ni;
 	ntfs_volume *vol = idx_ni->vol;
 	struct super_block *sb = vol->sb;
@@ -133,13 +134,11 @@ int ntfs_index_lookup(const void *key, const int key_len,
 	INDEX_ROOT *ir;
 	INDEX_ENTRY *ie;
 	INDEX_ALLOCATION *ia;
-	u8 *index_end;
-	attr_search_context *actx;
-	int rc, err = 0;
-	VCN vcn, old_vcn;
+	u8 *index_end, *kaddr;
+	ntfs_attr_search_ctx *actx;
 	struct address_space *ia_mapping;
 	struct page *page;
-	u8 *kaddr;
+	int rc, err = 0;
 
 	ntfs_debug("Entering.");
 	BUG_ON(!NInoAttr(idx_ni));
@@ -157,22 +156,25 @@ int ntfs_index_lookup(const void *key, const int key_len,
 	}
 	/* Get hold of the mft record for the index inode. */
 	m = map_mft_record(base_ni);
-	if (unlikely(IS_ERR(m))) {
+	if (IS_ERR(m)) {
 		ntfs_error(sb, "map_mft_record() failed with error code %ld.",
 				-PTR_ERR(m));
 		return PTR_ERR(m);
 	}
-	actx = get_attr_search_ctx(base_ni, m);
+	actx = ntfs_attr_get_search_ctx(base_ni, m);
 	if (unlikely(!actx)) {
 		err = -ENOMEM;
 		goto err_out;
 	}
 	/* Find the index root attribute in the mft record. */
-	if (!lookup_attr(AT_INDEX_ROOT, idx_ni->name, idx_ni->name_len,
-			CASE_SENSITIVE, 0, NULL, 0, actx)) {
-		ntfs_error(sb, "Index root attribute missing in inode 0x%lx.",
-				idx_ni->mft_no);
-		err = -EIO;
+	err = ntfs_attr_lookup(AT_INDEX_ROOT, idx_ni->name, idx_ni->name_len,
+			CASE_SENSITIVE, 0, NULL, 0, actx);
+	if (unlikely(err)) {
+		if (err == -ENOENT) {
+			ntfs_error(sb, "Index root attribute missing in inode "
+					"0x%lx.", idx_ni->mft_no);
+			err = -EIO;
+		}
 		goto err_out;
 	}
 	/* Get to the index root value (it has been verified in read_inode). */
@@ -263,13 +265,13 @@ done:
 		goto err_out;
 	}
 	/* Get the starting vcn of the index_block holding the child node. */
-	vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8);
+	vcn = sle64_to_cpup((sle64*)((u8*)ie + le16_to_cpu(ie->length) - 8));
 	ia_mapping = VFS_I(idx_ni)->i_mapping;
 	/*
 	 * We are done with the index root and the mft record.  Release them,
 	 * otherwise we deadlock with ntfs_map_page().
 	 */
-	put_attr_search_ctx(actx);
+	ntfs_attr_put_search_ctx(actx);
 	unmap_mft_record(base_ni);
 	m = NULL;
 	actx = NULL;
@@ -425,7 +427,7 @@ ia_done:
 	}
 	/* Child node present, descend into it. */
 	old_vcn = vcn;
-	vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8);
+	vcn = sle64_to_cpup((sle64*)((u8*)ie + le16_to_cpu(ie->length) - 8));
 	if (vcn >= 0) {
 		/*
 		 * If vcn is in the same page cache page as old_vcn we recycle
@@ -448,7 +450,7 @@ unm_err_out:
 	ntfs_unmap_page(page);
 err_out:
 	if (actx)
-		put_attr_search_ctx(actx);
+		ntfs_attr_put_search_ctx(actx);
 	if (m)
 		unmap_mft_record(base_ni);
 	return err;
diff --git a/fs/ntfs/index.h b/fs/ntfs/index.h
index 8ed943655..159442dfa 100644
--- a/fs/ntfs/index.h
+++ b/fs/ntfs/index.h
@@ -78,7 +78,7 @@ typedef struct {
 	u16 data_len;
 	BOOL is_in_root;
 	INDEX_ROOT *ir;
-	attr_search_context *actx;
+	ntfs_attr_search_ctx *actx;
 	ntfs_inode *base_ni;
 	INDEX_ALLOCATION *ia;
 	struct page *page;
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index 686d5bbb5..873c25d98 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -105,8 +105,11 @@ static int ntfs_init_locked_inode(struct inode *vi, ntfs_attr *na)
 	ni->name_len = na->name_len;
 
 	/* If initializing a normal inode, we are done. */
-	if (likely(na->type == AT_UNUSED))
+	if (likely(na->type == AT_UNUSED)) {
+		BUG_ON(na->name);
+		BUG_ON(na->name_len);
 		return 0;
+	}
 
 	/* It is a fake inode. */
 	NInoSetAttr(ni);
@@ -118,15 +121,16 @@ static int ntfs_init_locked_inode(struct inode *vi, ntfs_attr *na)
 	 * thus the fraction of named attributes with name != I30 is actually
 	 * absolutely tiny.
 	 */
-	if (na->name && na->name_len && na->name != I30) {
+	if (na->name_len && na->name != I30) {
 		unsigned int i;
 
+		BUG_ON(!na->name);
 		i = na->name_len * sizeof(ntfschar);
 		ni->name = (ntfschar*)kmalloc(i + sizeof(ntfschar), GFP_ATOMIC);
 		if (!ni->name)
 			return -ENOMEM;
 		memcpy(ni->name, na->name, i);
-		ni->name[i] = cpu_to_le16('\0');
+		ni->name[i] = 0;
 	}
 	return 0;
 }
@@ -210,7 +214,7 @@ struct inode *ntfs_iget(struct super_block *sb, unsigned long mft_no)
  * value with IS_ERR() and if true, the function failed and the error code is
  * obtained from PTR_ERR().
  */
-struct inode *ntfs_attr_iget(struct inode *base_vi, ATTR_TYPES type,
+struct inode *ntfs_attr_iget(struct inode *base_vi, ATTR_TYPE type,
 		ntfschar *name, u32 name_len)
 {
 	struct inode *vi;
@@ -372,13 +376,13 @@ static void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni)
 	ni->seq_no = 0;
 	atomic_set(&ni->count, 1);
 	ni->vol = NTFS_SB(sb);
-	init_run_list(&ni->run_list);
+	init_runlist(&ni->runlist);
 	init_MUTEX(&ni->mrec_lock);
 	ni->page = NULL;
 	ni->page_ofs = 0;
 	ni->attr_list_size = 0;
 	ni->attr_list = NULL;
-	init_run_list(&ni->attr_list_rl);
+	init_runlist(&ni->attr_list_rl);
 	ni->itype.index.bmp_ino = NULL;
 	ni->itype.index.block_size = 0;
 	ni->itype.index.vcn_size = 0;
@@ -428,20 +432,21 @@ inline ntfs_inode *ntfs_new_extent_inode(struct super_block *sb,
  * Return values:
  *	   1: file is in $Extend directory
  *	   0: file is not in $Extend directory
- *	-EIO: file is corrupt
+ *    -errno: failed to determine if the file is in the $Extend directory
  */
-static int ntfs_is_extended_system_file(attr_search_context *ctx)
+static int ntfs_is_extended_system_file(ntfs_attr_search_ctx *ctx)
 {
-	int nr_links;
+	int nr_links, err;
 
 	/* Restart search. */
-	reinit_attr_search_ctx(ctx);
+	ntfs_attr_reinit_search_ctx(ctx);
 
 	/* Get number of hard links. */
 	nr_links = le16_to_cpu(ctx->mrec->link_count);
 
 	/* Loop through all hard links. */
-	while (lookup_attr(AT_FILE_NAME, NULL, 0, 0, 0, NULL, 0, ctx)) {
+	while (!(err = ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, 0, 0, NULL, 0,
+			ctx))) {
 		FILE_NAME_ATTR *file_name_attr;
 		ATTR_RECORD *attr = ctx->attr;
 		u8 *p, *p2;
@@ -484,7 +489,9 @@ err_corrupt_attr:
 		if (MREF_LE(file_name_attr->parent_directory) == FILE_Extend)
 			return 1;	/* YES, it's an extended system file. */
 	}
-	if (nr_links) {
+	if (unlikely(err != -ENOENT))
+		return err;
+	if (unlikely(nr_links)) {
 		ntfs_error(ctx->ntfs_ino->vol->sb, "Inode hard link count "
 				"doesn't match number of name attributes. You "
 				"should run chkdsk.");
@@ -525,7 +532,7 @@ static int ntfs_read_locked_inode(struct inode *vi)
 	ntfs_inode *ni;
 	MFT_RECORD *m;
 	STANDARD_INFORMATION *si;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	int err = 0;
 
 	ntfs_debug("Entering for i_ino 0x%lx.", vi->i_ino);
@@ -557,7 +564,7 @@ static int ntfs_read_locked_inode(struct inode *vi)
 		err = PTR_ERR(m);
 		goto err_out;
 	}
-	ctx = get_attr_search_ctx(ni, m);
+	ctx = ntfs_attr_get_search_ctx(ni, m);
 	if (!ctx) {
 		err = -ENOMEM;
 		goto unm_err_out;
@@ -608,21 +615,25 @@ static int ntfs_read_locked_inode(struct inode *vi)
 	 * in fact fail if the standard information is in an extent record, but
 	 * I don't think this actually ever happens.
 	 */
-	if (!lookup_attr(AT_STANDARD_INFORMATION, NULL, 0, 0, 0, NULL, 0,
-			ctx)) {
-		/*
-		 * TODO: We should be performing a hot fix here (if the recover
-		 * mount option is set) by creating a new attribute.
-		 */
-		ntfs_error(vi->i_sb, "$STANDARD_INFORMATION attribute is "
-				"missing.");
+	err = ntfs_attr_lookup(AT_STANDARD_INFORMATION, NULL, 0, 0, 0, NULL, 0,
+			ctx);
+	if (unlikely(err)) {
+		if (err == -ENOENT) {
+			/*
+			 * TODO: We should be performing a hot fix here (if the
+			 * recover mount option is set) by creating a new
+			 * attribute.
+			 */
+			ntfs_error(vi->i_sb, "$STANDARD_INFORMATION attribute "
+					"is missing.");
+		}
 		goto unm_err_out;
 	}
 	/* Get the standard information attribute value. */
 	si = (STANDARD_INFORMATION*)((char*)ctx->attr +
 			le16_to_cpu(ctx->attr->data.resident.value_offset));
 
-	/* Transfer information from the standard information into vfs_ino. */
+	/* Transfer information from the standard information into vi. */
 	/*
 	 * Note: The i_?times do not quite map perfectly onto the NTFS times,
 	 * but they are close enough, and in the end it doesn't really matter
@@ -646,8 +657,15 @@ static int ntfs_read_locked_inode(struct inode *vi)
 	vi->i_atime = ntfs2utc(si->last_access_time);
 
 	/* Find the attribute list attribute if present. */
-	reinit_attr_search_ctx(ctx);
-	if (lookup_attr(AT_ATTRIBUTE_LIST, NULL, 0, 0, 0, NULL, 0, ctx)) {
+	ntfs_attr_reinit_search_ctx(ctx);
+	err = ntfs_attr_lookup(AT_ATTRIBUTE_LIST, NULL, 0, 0, 0, NULL, 0, ctx);
+	if (err) {
+		if (unlikely(err != -ENOENT)) {
+			ntfs_error(vi->i_sb, "Failed to lookup attribute list "
+					"attribute. You should run chkdsk.");
+			goto unm_err_out;
+		}
+	} else /* if (!err) */ {
 		if (vi->i_ino == FILE_MFT)
 			goto skip_attr_list_load;
 		ntfs_debug("Attribute list found in inode 0x%lx.", vi->i_ino);
@@ -662,7 +680,7 @@ static int ntfs_read_locked_inode(struct inode *vi)
 			goto unm_err_out;
 		}
 		/* Now allocate memory for the attribute list. */
-		ni->attr_list_size = (u32)attribute_value_length(ctx->attr);
+		ni->attr_list_size = (u32)ntfs_attr_size(ctx->attr);
 		ni->attr_list = ntfs_malloc_nofs(ni->attr_list_size);
 		if (!ni->attr_list) {
 			ntfs_error(vi->i_sb, "Not enough memory to allocate "
@@ -680,7 +698,7 @@ static int ntfs_read_locked_inode(struct inode *vi)
 				goto unm_err_out;
 			}
 			/*
-			 * Setup the run list. No need for locking as we have
+			 * Setup the runlist. No need for locking as we have
 			 * exclusive access to the inode at this time.
 			 */
 			ni->attr_list_rl.rl = decompress_mapping_pairs(vol,
@@ -733,13 +751,17 @@ skip_attr_list_load:
 		char *ir_end, *index_end;
 
 		/* It is a directory, find index root attribute. */
-		reinit_attr_search_ctx(ctx);
-		if (!lookup_attr(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0,
-				NULL, 0, ctx)) {
-			// FIXME: File is corrupt! Hot-fix with empty index
-			// root attribute if recovery option is set.
-			ntfs_error(vi->i_sb, "$INDEX_ROOT attribute is "
-					"missing.");
+		ntfs_attr_reinit_search_ctx(ctx);
+		err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE,
+				0, NULL, 0, ctx);
+		if (unlikely(err)) {
+			if (err == -ENOENT) {
+				// FIXME: File is corrupt! Hot-fix with empty
+				// index root attribute if recovery option is
+				// set.
+				ntfs_error(vi->i_sb, "$INDEX_ROOT attribute "
+						"is missing.");
+			}
 			goto unm_err_out;
 		}
 		/* Set up the state. */
@@ -841,7 +863,7 @@ skip_attr_list_load:
 			vi->i_size = ni->initialized_size =
 					ni->allocated_size = 0;
 			/* We are done with the mft record, so we release it. */
-			put_attr_search_ctx(ctx);
+			ntfs_attr_put_search_ctx(ctx);
 			unmap_mft_record(ni);
 			m = NULL;
 			ctx = NULL;
@@ -849,12 +871,19 @@ skip_attr_list_load:
 		} /* LARGE_INDEX: Index allocation present. Setup state. */
 		NInoSetIndexAllocPresent(ni);
 		/* Find index allocation attribute. */
-		reinit_attr_search_ctx(ctx);
-		if (!lookup_attr(AT_INDEX_ALLOCATION, I30, 4, CASE_SENSITIVE,
-				0, NULL, 0, ctx)) {
-			ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute "
-					"is not present but $INDEX_ROOT "
-					"indicated it is.");
+		ntfs_attr_reinit_search_ctx(ctx);
+		err = ntfs_attr_lookup(AT_INDEX_ALLOCATION, I30, 4,
+				CASE_SENSITIVE, 0, NULL, 0, ctx);
+		if (unlikely(err)) {
+			if (err == -ENOENT)
+				ntfs_error(vi->i_sb, "$INDEX_ALLOCATION "
+						"attribute is not present but "
+						"$INDEX_ROOT indicated it "
+						"is.");
+			else
+				ntfs_error(vi->i_sb, "Failed to lookup "
+						"$INDEX_ALLOCATION "
+						"attribute.");
 			goto unm_err_out;
 		}
 		if (!ctx->attr->non_resident) {
@@ -894,13 +923,13 @@ skip_attr_list_load:
 		 * We are done with the mft record, so we release it. Otherwise
 		 * we would deadlock in ntfs_attr_iget().
 		 */
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 		unmap_mft_record(ni);
 		m = NULL;
 		ctx = NULL;
 		/* Get the index bitmap attribute inode. */
 		bvi = ntfs_attr_iget(vi, AT_BITMAP, I30, 4);
-		if (unlikely(IS_ERR(bvi))) {
+		if (IS_ERR(bvi)) {
 			ntfs_error(vi->i_sb, "Failed to get bitmap attribute.");
 			err = PTR_ERR(bvi);
 			goto unm_err_out;
@@ -938,7 +967,7 @@ skip_large_dir_stuff:
 		vi->i_mapping->a_ops = &ntfs_mst_aops;
 	} else {
 		/* It is a file. */
-		reinit_attr_search_ctx(ctx);
+		ntfs_attr_reinit_search_ctx(ctx);
 
 		/* Setup the data attribute, even if not present. */
 		ni->type = AT_DATA;
@@ -946,9 +975,15 @@ skip_large_dir_stuff:
 		ni->name_len = 0;
 
 		/* Find first extent of the unnamed data attribute. */
-		if (!lookup_attr(AT_DATA, NULL, 0, 0, 0, NULL, 0, ctx)) {
+		err = ntfs_attr_lookup(AT_DATA, NULL, 0, 0, 0, NULL, 0, ctx);
+		if (unlikely(err)) {
 			vi->i_size = ni->initialized_size =
-					ni->allocated_size = 0LL;
+					ni->allocated_size = 0;
+			if (err != -ENOENT) {
+				ntfs_error(vi->i_sb, "Failed to lookup $DATA "
+						"attribute.");
+				goto unm_err_out;
+			}
 			/*
 			 * FILE_Secure does not have an unnamed $DATA
 			 * attribute, so we special case it here.
@@ -1059,7 +1094,7 @@ skip_large_dir_stuff:
 		}
 no_data_attr_special_case:
 		/* We are done with the mft record, so we release it. */
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 		unmap_mft_record(ni);
 		m = NULL;
 		ctx = NULL;
@@ -1098,7 +1133,7 @@ unm_err_out:
 	if (!err)
 		err = -EIO;
 	if (ctx)
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 	if (m)
 		unmap_mft_record(ni);
 err_out:
@@ -1133,7 +1168,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
 	ntfs_volume *vol = NTFS_SB(vi->i_sb);
 	ntfs_inode *ni, *base_ni;
 	MFT_RECORD *m;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	int err = 0;
 
 	ntfs_debug("Entering for i_ino 0x%lx.", vi->i_ino);
@@ -1162,15 +1197,16 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
 		err = PTR_ERR(m);
 		goto err_out;
 	}
-	ctx = get_attr_search_ctx(base_ni, m);
+	ctx = ntfs_attr_get_search_ctx(base_ni, m);
 	if (!ctx) {
 		err = -ENOMEM;
 		goto unm_err_out;
 	}
 
 	/* Find the attribute. */
-	if (!lookup_attr(ni->type, ni->name, ni->name_len, CASE_SENSITIVE, 0,
-			NULL, 0, ctx))
+	err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
+			CASE_SENSITIVE, 0, NULL, 0, ctx);
+	if (unlikely(err))
 		goto unm_err_out;
 
 	if (!ctx->attr->non_resident) {
@@ -1333,7 +1369,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
 	ni->ext.base_ntfs_ino = base_ni;
 	ni->nr_extents = -1;
 
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(base_ni);
 
 	ntfs_debug("Done.");
@@ -1343,7 +1379,7 @@ unm_err_out:
 	if (!err)
 		err = -EIO;
 	if (ctx)
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(base_ni);
 err_out:
 	ntfs_error(vi->i_sb, "Failed with error code %i while reading "
@@ -1392,7 +1428,7 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
 	ntfs_inode *ni, *base_ni, *bni;
 	struct inode *bvi;
 	MFT_RECORD *m;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	INDEX_ROOT *ir;
 	u8 *ir_end, *index_end;
 	int err = 0;
@@ -1419,15 +1455,18 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
 		err = PTR_ERR(m);
 		goto err_out;
 	}
-	ctx = get_attr_search_ctx(base_ni, m);
+	ctx = ntfs_attr_get_search_ctx(base_ni, m);
 	if (!ctx) {
 		err = -ENOMEM;
 		goto unm_err_out;
 	}
 	/* Find the index root attribute. */
-	if (!lookup_attr(AT_INDEX_ROOT, ni->name, ni->name_len, CASE_SENSITIVE,
-			0, NULL, 0, ctx)) {
-		ntfs_error(vi->i_sb, "$INDEX_ROOT attribute is missing.");
+	err = ntfs_attr_lookup(AT_INDEX_ROOT, ni->name, ni->name_len,
+			CASE_SENSITIVE, 0, NULL, 0, ctx);
+	if (unlikely(err)) {
+		if (err == -ENOENT)
+			ntfs_error(vi->i_sb, "$INDEX_ROOT attribute is "
+					"missing.");
 		goto unm_err_out;
 	}
 	/* Set up the state. */
@@ -1497,7 +1536,7 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
 		/* No index allocation. */
 		vi->i_size = ni->initialized_size = ni->allocated_size = 0;
 		/* We are done with the mft record, so we release it. */
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 		unmap_mft_record(base_ni);
 		m = NULL;
 		ctx = NULL;
@@ -1505,11 +1544,17 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
 	} /* LARGE_INDEX:  Index allocation present.  Setup state. */
 	NInoSetIndexAllocPresent(ni);
 	/* Find index allocation attribute. */
-	reinit_attr_search_ctx(ctx);
-	if (!lookup_attr(AT_INDEX_ALLOCATION, ni->name, ni->name_len,
-			CASE_SENSITIVE, 0, NULL, 0, ctx)) {
-		ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is not "
-				"present but $INDEX_ROOT indicated it is.");
+	ntfs_attr_reinit_search_ctx(ctx);
+	err = ntfs_attr_lookup(AT_INDEX_ALLOCATION, ni->name, ni->name_len,
+			CASE_SENSITIVE, 0, NULL, 0, ctx);
+	if (unlikely(err)) {
+		if (err == -ENOENT)
+			ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is "
+					"not present but $INDEX_ROOT "
+					"indicated it is.");
+		else
+			ntfs_error(vi->i_sb, "Failed to lookup "
+					"$INDEX_ALLOCATION attribute.");
 		goto unm_err_out;
 	}
 	if (!ctx->attr->non_resident) {
@@ -1546,13 +1591,13 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
 	 * We are done with the mft record, so we release it.  Otherwise
 	 * we would deadlock in ntfs_attr_iget().
 	 */
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(base_ni);
 	m = NULL;
 	ctx = NULL;
 	/* Get the index bitmap attribute inode. */
 	bvi = ntfs_attr_iget(base_vi, AT_BITMAP, ni->name, ni->name_len);
-	if (unlikely(IS_ERR(bvi))) {
+	if (IS_ERR(bvi)) {
 		ntfs_error(vi->i_sb, "Failed to get bitmap attribute.");
 		err = PTR_ERR(bvi);
 		goto unm_err_out;
@@ -1597,7 +1642,7 @@ unm_err_out:
 	if (!err)
 		err = -EIO;
 	if (ctx)
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 	if (m)
 		unmap_mft_record(base_ni);
 err_out:
@@ -1619,16 +1664,16 @@ err_out:
  * is not initialized and hence we cannot get at the contents of mft records
  * by calling map_mft_record*().
  *
- * Further it needs to cope with the circular references problem, i.e. can't
+ * Further it needs to cope with the circular references problem, i.e. cannot
  * load any attributes other than $ATTRIBUTE_LIST until $DATA is loaded, because
- * we don't know where the other extent mft records are yet and again, because
- * we cannot call map_mft_record*() yet. Obviously this applies only when an
+ * we do not know where the other extent mft records are yet and again, because
+ * we cannot call map_mft_record*() yet.  Obviously this applies only when an
  * attribute list is actually present in $MFT inode.
  *
  * We solve these problems by starting with the $DATA attribute before anything
- * else and iterating using lookup_attr($DATA) over all extents. As each extent
- * is found, we decompress_mapping_pairs() including the implied
- * merge_run_lists(). Each step of the iteration necessarily provides
+ * else and iterating using ntfs_attr_lookup($DATA) over all extents.  As each
+ * extent is found, we decompress_mapping_pairs() including the implied
+ * ntfs_merge_runlists().  Each step of the iteration necessarily provides
  * sufficient information for the next step to complete.
  *
  * This should work but there are two possible pit falls (see inline comments
@@ -1644,7 +1689,7 @@ int ntfs_read_inode_mount(struct inode *vi)
 	ntfs_inode *ni;
 	MFT_RECORD *m = NULL;
 	ATTR_RECORD *attr;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	unsigned int i, nr_blocks;
 	int err;
 
@@ -1719,14 +1764,21 @@ int ntfs_read_inode_mount(struct inode *vi)
 	/* Provides readpage() and sync_page() for map_mft_record(). */
 	vi->i_mapping->a_ops = &ntfs_mft_aops;
 
-	ctx = get_attr_search_ctx(ni, m);
+	ctx = ntfs_attr_get_search_ctx(ni, m);
 	if (!ctx) {
 		err = -ENOMEM;
 		goto err_out;
 	}
 
 	/* Find the attribute list attribute if present. */
-	if (lookup_attr(AT_ATTRIBUTE_LIST, NULL, 0, 0, 0, NULL, 0, ctx)) {
+	err = ntfs_attr_lookup(AT_ATTRIBUTE_LIST, NULL, 0, 0, 0, NULL, 0, ctx);
+	if (err) {
+		if (unlikely(err != -ENOENT)) {
+			ntfs_error(sb, "Failed to lookup attribute list "
+					"attribute. You should run chkdsk.");
+			goto put_err_out;
+		}
+	} else /* if (!err) */ {
 		ATTR_LIST_ENTRY *al_entry, *next_al_entry;
 		u8 *al_end;
 
@@ -1742,7 +1794,7 @@ int ntfs_read_inode_mount(struct inode *vi)
 			goto put_err_out;
 		}
 		/* Now allocate memory for the attribute list. */
-		ni->attr_list_size = (u32)attribute_value_length(ctx->attr);
+		ni->attr_list_size = (u32)ntfs_attr_size(ctx->attr);
 		ni->attr_list = ntfs_malloc_nofs(ni->attr_list_size);
 		if (!ni->attr_list) {
 			ntfs_error(sb, "Not enough memory to allocate buffer "
@@ -1757,7 +1809,7 @@ int ntfs_read_inode_mount(struct inode *vi)
 						"You should run chkdsk.");
 				goto put_err_out;
 			}
-			/* Setup the run list. */
+			/* Setup the runlist. */
 			ni->attr_list_rl.rl = decompress_mapping_pairs(vol,
 					ctx->attr, NULL);
 			if (IS_ERR(ni->attr_list_rl.rl)) {
@@ -1855,13 +1907,14 @@ int ntfs_read_inode_mount(struct inode *vi)
 		}
 	}
 
-	reinit_attr_search_ctx(ctx);
+	ntfs_attr_reinit_search_ctx(ctx);
 
 	/* Now load all attribute extents. */
 	attr = NULL;
 	next_vcn = last_vcn = highest_vcn = 0;
-	while (lookup_attr(AT_DATA, NULL, 0, 0, next_vcn, NULL, 0, ctx)) {
-		run_list_element *nrl;
+	while (!(err = ntfs_attr_lookup(AT_DATA, NULL, 0, 0, next_vcn, NULL, 0,
+			ctx))) {
+		runlist_element *nrl;
 
 		/* Cache the current attribute. */
 		attr = ctx->attr;
@@ -1885,23 +1938,21 @@ int ntfs_read_inode_mount(struct inode *vi)
 		}
 		/*
 		 * Decompress the mapping pairs array of this extent and merge
-		 * the result into the existing run list. No need for locking
+		 * the result into the existing runlist. No need for locking
 		 * as we have exclusive access to the inode at this time and we
 		 * are a mount in progress task, too.
 		 */
-		nrl = decompress_mapping_pairs(vol, attr, ni->run_list.rl);
+		nrl = decompress_mapping_pairs(vol, attr, ni->runlist.rl);
 		if (IS_ERR(nrl)) {
 			ntfs_error(sb, "decompress_mapping_pairs() failed with "
 					"error code %ld. $MFT is corrupt.",
 					PTR_ERR(nrl));
 			goto put_err_out;
 		}
-		ni->run_list.rl = nrl;
+		ni->runlist.rl = nrl;
 
 		/* Are we in the first extent? */
 		if (!next_vcn) {
-			u64 ll;
-
 			if (attr->data.non_resident.lowest_vcn) {
 				ntfs_error(sb, "First extent of $DATA "
 						"attribute has non zero "
@@ -1920,19 +1971,17 @@ int ntfs_read_inode_mount(struct inode *vi)
 					non_resident.initialized_size);
 			ni->allocated_size = sle64_to_cpu(
 					attr->data.non_resident.allocated_size);
-			/* Set the number of mft records. */
-			ll = vi->i_size >> vol->mft_record_size_bits;
 			/*
 			 * Verify the number of mft records does not exceed
 			 * 2^32 - 1.
 			 */
-			if (ll >= (1ULL << 32)) {
+			if ((vi->i_size >> vol->mft_record_size_bits) >=
+					(1ULL << 32)) {
 				ntfs_error(sb, "$MFT is too big! Aborting.");
 				goto put_err_out;
 			}
-			vol->nr_mft_records = ll;
 			/*
-			 * We have got the first extent of the run_list for
+			 * We have got the first extent of the runlist for
 			 * $MFT which means it is now relatively safe to call
 			 * the normal ntfs_read_inode() function.
 			 * Complete reading the inode, this will actually
@@ -1959,7 +2008,7 @@ int ntfs_read_inode_mount(struct inode *vi)
 						"saw this message to "
 						"linux-ntfs-dev@lists."
 						"sourceforge.net");
-				put_attr_search_ctx(ctx);
+				ntfs_attr_put_search_ctx(ctx);
 				/* Revert to the safe super operations. */
 				ntfs_free(m);
 				return -1;
@@ -1995,21 +2044,26 @@ int ntfs_read_inode_mount(struct inode *vi)
 			goto put_err_out;
 		}
 	}
+	if (err != -ENOENT) {
+		ntfs_error(sb, "Failed to lookup $MFT/$DATA attribute extent. "
+				"$MFT is corrupt. Run chkdsk.");
+		goto put_err_out;
+	}
 	if (!attr) {
 		ntfs_error(sb, "$MFT/$DATA attribute not found. $MFT is "
 				"corrupt. Run chkdsk.");
 		goto put_err_out;
 	}
 	if (highest_vcn && highest_vcn != last_vcn - 1) {
-		ntfs_error(sb, "Failed to load the complete run list "
-				"for $MFT/$DATA. Driver bug or "
-				"corrupt $MFT. Run chkdsk.");
+		ntfs_error(sb, "Failed to load the complete runlist for "
+				"$MFT/$DATA. Driver bug or corrupt $MFT. "
+				"Run chkdsk.");
 		ntfs_debug("highest_vcn = 0x%llx, last_vcn - 1 = 0x%llx",
 				(unsigned long long)highest_vcn,
 				(unsigned long long)last_vcn - 1);
 		goto put_err_out;
 	}
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 	ntfs_debug("Done.");
 	ntfs_free(m);
 	return 0;
@@ -2018,7 +2072,7 @@ em_put_err_out:
 	ntfs_error(sb, "Couldn't find first extent of $DATA attribute in "
 			"attribute list. $MFT is corrupt. Run chkdsk.");
 put_err_out:
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 err_out:
 	ntfs_error(sb, "Failed. Marking inode as bad.");
 	make_bad_inode(vi);
@@ -2073,12 +2127,12 @@ void ntfs_put_inode(struct inode *vi)
 void __ntfs_clear_inode(ntfs_inode *ni)
 {
 	/* Free all alocated memory. */
-	down_write(&ni->run_list.lock);
-	if (ni->run_list.rl) {
-		ntfs_free(ni->run_list.rl);
-		ni->run_list.rl = NULL;
+	down_write(&ni->runlist.lock);
+	if (ni->runlist.rl) {
+		ntfs_free(ni->runlist.rl);
+		ni->runlist.rl = NULL;
 	}
-	up_write(&ni->run_list.lock);
+	up_write(&ni->runlist.lock);
 
 	if (ni->attr_list) {
 		ntfs_free(ni->attr_list);
@@ -2216,16 +2270,71 @@ int ntfs_show_options(struct seq_file *sf, struct vfsmount *mnt)
  *
  * We don't support i_size changes yet.
  *
- * Called with ->i_sem held.
+ * The kernel guarantees that @vi is a regular file (S_ISREG() is true) and
+ * that the change is allowed.
+ *
+ * This implies for us that @vi is a file inode rather than a directory, index,
+ * or attribute inode as well as that @vi is a base inode.
+ *
+ * Called with ->i_sem held.  In all but one case ->i_alloc_sem is held for
+ * writing.  The only case where ->i_alloc_sem is not held is
+ * mm/filemap.c::generic_file_buffered_write() where vmtruncate() is called
+ * with the current i_size as the offset which means that it is a noop as far
+ * as ntfs_truncate() is concerned.
  */
 void ntfs_truncate(struct inode *vi)
 {
-	// TODO: Implement...
-	ntfs_warning(vi->i_sb, "Eeek: i_size may have changed! If you see "
-			"this right after a message from "
-			"ntfs_{prepare,commit}_{,nonresident_}write() then "
-			"just ignore it. Otherwise it is bad news.");
-	// TODO: reset i_size now!
+	ntfs_inode *ni = NTFS_I(vi);
+	ntfs_attr_search_ctx *ctx;
+	MFT_RECORD *m;
+	int err;
+
+	m = map_mft_record(ni);
+	if (IS_ERR(m)) {
+		ntfs_error(vi->i_sb, "Failed to map mft record for inode 0x%lx "
+				"(error code %ld).", vi->i_ino, PTR_ERR(m));
+		if (PTR_ERR(m) != ENOMEM)
+			make_bad_inode(vi);
+		return;
+	}
+	ctx = ntfs_attr_get_search_ctx(ni, m);
+	if (unlikely(!ctx)) {
+		ntfs_error(vi->i_sb, "Failed to allocate a search context: "
+				"Not enough memory");
+		// FIXME: We can't report an error code upstream.  So what do
+		// we do?!?  make_bad_inode() seems a bit harsh...
+		unmap_mft_record(ni);
+		return;
+	}
+	err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
+			CASE_SENSITIVE, 0, NULL, 0, ctx);
+	if (unlikely(err)) {
+		if (err == -ENOENT) {
+			ntfs_error(vi->i_sb, "Open attribute is missing from "
+					"mft record.  Inode 0x%lx is corrupt.  "
+					"Run chkdsk.", vi->i_ino);
+			make_bad_inode(vi);
+		} else {
+			ntfs_error(vi->i_sb, "Failed to lookup attribute in "
+					"inode 0x%lx (error code %d).",
+					vi->i_ino, err);
+			// FIXME: We can't report an error code upstream.  So
+			// what do we do?!?  make_bad_inode() seems a bit
+			// harsh...
+		}
+		goto out;
+	}
+	/* If the size has not changed there is nothing to do. */
+	if (ntfs_attr_size(ctx->attr) == i_size_read(vi))
+		goto out;
+	// TODO: Implement the truncate...
+	ntfs_error(vi->i_sb, "Inode size has changed but this is not "
+			"implemented yet.  Resetting inode size to old value. "
+			" This is most likely a bug in the ntfs driver!");
+	i_size_write(vi, ntfs_attr_size(ctx->attr)); 
+out:
+	ntfs_attr_put_search_ctx(ctx);
+	unmap_mft_record(ni);
 	return;
 }
 
@@ -2235,67 +2344,62 @@ void ntfs_truncate(struct inode *vi)
  * @attr:	structure describing the attributes and the changes
  *
  * We have to trap VFS attempts to truncate the file described by @dentry as
- * soon as possible, because we do not implement changes in i_size yet. So we
+ * soon as possible, because we do not implement changes in i_size yet.  So we
  * abort all i_size changes here.
  *
- * Called with ->i_sem held.
+ * We also abort all changes of user, group, and mode as we do not implement
+ * the NTFS ACLs yet.
+ *
+ * Called with ->i_sem held.  For the ATTR_SIZE (i.e. ->truncate) case, also
+ * called with ->i_alloc_sem held for writing.
  *
  * Basically this is a copy of generic notify_change() and inode_setattr()
  * functionality, except we intercept and abort changes in i_size.
  */
 int ntfs_setattr(struct dentry *dentry, struct iattr *attr)
 {
-	struct inode *vi;
+	struct inode *vi = dentry->d_inode;
 	int err;
 	unsigned int ia_valid = attr->ia_valid;
 
-	vi = dentry->d_inode;
-
 	err = inode_change_ok(vi, attr);
 	if (err)
 		return err;
 
-	if ((ia_valid & ATTR_UID && attr->ia_uid != vi->i_uid) ||
-			(ia_valid & ATTR_GID && attr->ia_gid != vi->i_gid)) {
-		err = DQUOT_TRANSFER(vi, attr) ? -EDQUOT : 0;
-		if (err)
-			return err;
+	/* We do not support NTFS ACLs yet. */
+	if (ia_valid & (ATTR_UID | ATTR_GID | ATTR_MODE)) {
+		ntfs_warning(vi->i_sb, "Changes in user/group/mode are not "
+				"supported yet, ignoring.");
+		err = -EOPNOTSUPP;
+		goto out;
 	}
 
-	lock_kernel();
-
 	if (ia_valid & ATTR_SIZE) {
-		ntfs_error(vi->i_sb, "Changes in i_size are not supported "
-				"yet. Sorry.");
-		// TODO: Implement...
-		// err = vmtruncate(vi, attr->ia_size);
-		err = -EOPNOTSUPP;
-		if (err)
-			goto trunc_err;
+		if (attr->ia_size != i_size_read(vi)) {
+			ntfs_warning(vi->i_sb, "Changes in inode size are not "
+					"supported yet, ignoring.");
+			err = -EOPNOTSUPP;
+			// TODO: Implement...
+			// err = vmtruncate(vi, attr->ia_size);
+			if (err || ia_valid == ATTR_SIZE)
+				goto out;
+		} else {
+			/*
+			 * We skipped the truncate but must still update
+			 * timestamps.
+			 */
+			ia_valid |= ATTR_MTIME|ATTR_CTIME;
+		}
 	}
 
-	if (ia_valid & ATTR_UID)
-		vi->i_uid = attr->ia_uid;
-	if (ia_valid & ATTR_GID)
-		vi->i_gid = attr->ia_gid;
 	if (ia_valid & ATTR_ATIME)
 		vi->i_atime = attr->ia_atime;
 	if (ia_valid & ATTR_MTIME)
 		vi->i_mtime = attr->ia_mtime;
 	if (ia_valid & ATTR_CTIME)
 		vi->i_ctime = attr->ia_ctime;
-	if (ia_valid & ATTR_MODE) {
-		vi->i_mode = attr->ia_mode;
-		if (!in_group_p(vi->i_gid) &&
-				!capable(CAP_FSETID))
-			vi->i_mode &= ~S_ISGID;
-	}
 	mark_inode_dirty(vi);
-
-trunc_err:
-
-	unlock_kernel();
-
+out:
 	return err;
 }
 
@@ -2314,67 +2418,93 @@ trunc_err:
  * marking the page (and in this case mft record) dirty but we do not implement
  * this yet as write_mft_record() largely ignores the @sync parameter and
  * always performs synchronous writes.
+ *
+ * Return 0 on success and -errno on error.
  */
-void ntfs_write_inode(struct inode *vi, int sync)
+int ntfs_write_inode(struct inode *vi, int sync)
 {
+	sle64 nt;
 	ntfs_inode *ni = NTFS_I(vi);
-#if 0
-	attr_search_context *ctx;
-#endif
+	ntfs_attr_search_ctx *ctx;
 	MFT_RECORD *m;
+	STANDARD_INFORMATION *si;
 	int err = 0;
+	BOOL modified = FALSE;
 
 	ntfs_debug("Entering for %sinode 0x%lx.", NInoAttr(ni) ? "attr " : "",
 			vi->i_ino);
 	/*
 	 * Dirty attribute inodes are written via their real inodes so just
-	 * clean them here.  TODO:  Take care of access time updates.
+	 * clean them here.  Access time updates are taken care off when the
+	 * real inode is written.
 	 */
 	if (NInoAttr(ni)) {
 		NInoClearDirty(ni);
-		return;
+		ntfs_debug("Done.");
+		return 0;
 	}
 	/* Map, pin, and lock the mft record belonging to the inode. */
 	m = map_mft_record(ni);
-	if (unlikely(IS_ERR(m))) {
+	if (IS_ERR(m)) {
 		err = PTR_ERR(m);
 		goto err_out;
 	}
-#if 0
-	/* Obtain the standard information attribute. */
-	ctx = get_attr_search_ctx(ni, m);
+	/* Update the access times in the standard information attribute. */
+	ctx = ntfs_attr_get_search_ctx(ni, m);
 	if (unlikely(!ctx)) {
 		err = -ENOMEM;
 		goto unm_err_out;
 	}
-	if (unlikely(!lookup_attr(AT_STANDARD_INFORMATION, NULL, 0,
-			CASE_SENSITIVE, 0, NULL, 0, ctx))) {
-		put_attr_search_ctx(ctx);
-		err = -ENOENT;
+	err = ntfs_attr_lookup(AT_STANDARD_INFORMATION, NULL, 0,
+			CASE_SENSITIVE, 0, NULL, 0, ctx);
+	if (unlikely(err)) {
+		ntfs_attr_put_search_ctx(ctx);
 		goto unm_err_out;
 	}
-	// TODO:  Update the access times in the standard information attribute
-	// which is now in ctx->attr.
-	// - Probably want to have use sops->dirty_inode() to set a flag that
-	//   we need to update the times here rather than having to blindly do
-	//   it every time.  Or even don't do it here at all and do it in
-	//   sops->dirty_inode() instead.  Problem with this would be that
-	//   sops->dirty_inode() must be atomic under certain circumstances
-	//   and mapping mft records and such like is not atomic.
-	// - For atime updates also need to check whether they are enabled in
-	//   the superblock flags.
-	ntfs_warning(vi->i_sb, "Access time updates not implement yet.");
+	si = (STANDARD_INFORMATION*)((u8*)ctx->attr +
+			le16_to_cpu(ctx->attr->data.resident.value_offset));
+	/* Update the access times if they have changed. */
+	nt = utc2ntfs(vi->i_mtime);
+	if (si->last_data_change_time != nt) {
+		ntfs_debug("Updating mtime for inode 0x%lx: old = 0x%llx, "
+				"new = 0x%llx", vi->i_ino,
+				sle64_to_cpu(si->last_data_change_time),
+				sle64_to_cpu(nt));
+		si->last_data_change_time = nt;
+		modified = TRUE;
+	}
+	nt = utc2ntfs(vi->i_ctime);
+	if (si->last_mft_change_time != nt) {
+		ntfs_debug("Updating ctime for inode 0x%lx: old = 0x%llx, "
+				"new = 0x%llx", vi->i_ino,
+				sle64_to_cpu(si->last_mft_change_time),
+				sle64_to_cpu(nt));
+		si->last_mft_change_time = nt;
+		modified = TRUE;
+	}
+	nt = utc2ntfs(vi->i_atime);
+	if (si->last_access_time != nt) {
+		ntfs_debug("Updating atime for inode 0x%lx: old = 0x%llx, "
+				"new = 0x%llx", vi->i_ino,
+				sle64_to_cpu(si->last_access_time),
+				sle64_to_cpu(nt));
+		si->last_access_time = nt;
+		modified = TRUE;
+	}
 	/*
-	 * We just modified the mft record containing the standard information
-	 * attribute.  So need to mark the mft record dirty, too, but we do it
-	 * manually so that mark_inode_dirty() is not called again.
-	 * TODO:  Only do this if there was a change in any of the times!
+	 * If we just modified the standard information attribute we need to
+	 * mark the mft record it is in dirty.  We do this manually so that
+	 * mark_inode_dirty() is not called which would redirty the inode and
+	 * hence result in an infinite loop of trying to write the inode.
+	 * There is no need to mark the base inode nor the base mft record
+	 * dirty, since we are going to write this mft record below in any case
+	 * and the base mft record may actually not have been modified so it
+	 * might not need to be written out.
 	 */
-	if (!NInoTestSetDirty(ctx->ntfs_ino))
+	if (modified && !NInoTestSetDirty(ctx->ntfs_ino))
 		__set_page_dirty_nobuffers(ctx->ntfs_ino->page);
-	put_attr_search_ctx(ctx);
-#endif
-	/* Write this base mft record. */
+	ntfs_attr_put_search_ctx(ctx);
+	/* Now the access times are updated, write the base mft record. */
 	if (NInoDirty(ni))
 		err = write_mft_record(ni, m, sync);
 	/* Write all attached extent mft records. */
@@ -2391,7 +2521,7 @@ void ntfs_write_inode(struct inode *vi, int sync)
 				MFT_RECORD *tm = map_mft_record(tni);
 				int ret;
 
-				if (unlikely(IS_ERR(tm))) {
+				if (IS_ERR(tm)) {
 					if (!err || err == -ENOMEM)
 						err = PTR_ERR(tm);
 					continue;
@@ -2410,11 +2540,9 @@ void ntfs_write_inode(struct inode *vi, int sync)
 	if (unlikely(err))
 		goto err_out;
 	ntfs_debug("Done.");
-	return;
-#if 0
+	return 0;
 unm_err_out:
 	unmap_mft_record(ni);
-#endif
 err_out:
 	if (err == -ENOMEM) {
 		ntfs_warning(vi->i_sb, "Not enough memory to write inode.  "
@@ -2426,7 +2554,7 @@ err_out:
 				"as bad.  You should run chkdsk.", -err);
 		make_bad_inode(vi);
 	}
-	return;
+	return err;
 }
 
 #endif /* NTFS_RW */
diff --git a/fs/ntfs/inode.h b/fs/ntfs/inode.h
index 465bef639..3aa7b873f 100644
--- a/fs/ntfs/inode.h
+++ b/fs/ntfs/inode.h
@@ -53,21 +53,21 @@ struct _ntfs_inode {
 	 * name_len = 0 for files and name = I30 (global constant) and
 	 * name_len = 4 for directories.
 	 */
-	ATTR_TYPES type;	/* Attribute type of this fake inode. */
+	ATTR_TYPE type;	/* Attribute type of this fake inode. */
 	ntfschar *name;		/* Attribute name of this fake inode. */
 	u32 name_len;		/* Attribute name length of this fake inode. */
-	run_list run_list;	/* If state has the NI_NonResident bit set,
-				   the run list of the unnamed data attribute
+	runlist runlist;	/* If state has the NI_NonResident bit set,
+				   the runlist of the unnamed data attribute
 				   (if a file) or of the index allocation
 				   attribute (directory) or of the attribute
 				   described by the fake inode (if NInoAttr()).
-				   If run_list.rl is NULL, the run list has not
+				   If runlist.rl is NULL, the runlist has not
 				   been read in yet or has been unmapped. If
 				   NI_NonResident is clear, the attribute is
 				   resident (file and fake inode) or there is
 				   no $I30 index allocation attribute
 				   (small directory). In the latter case
-				   run_list.rl is always NULL.*/
+				   runlist.rl is always NULL.*/
 	/*
 	 * The following fields are only valid for real inodes and extent
 	 * inodes.
@@ -88,7 +88,7 @@ struct _ntfs_inode {
 	 */
 	u32 attr_list_size;	/* Length of attribute list value in bytes. */
 	u8 *attr_list;		/* Attribute list value itself. */
-	run_list attr_list_rl;	/* Run list for the attribute list value. */
+	runlist attr_list_rl;	/* Run list for the attribute list value. */
 	union {
 		struct { /* It is a directory, $MFT, or an index inode. */
 			struct inode *bmp_ino;	/* Attribute inode for the
@@ -96,7 +96,7 @@ struct _ntfs_inode {
 			u32 block_size;		/* Size of an index block. */
 			u32 vcn_size;		/* Size of a vcn in this
 						   index. */
-			COLLATION_RULES collation_rule; /* The collation rule
+			COLLATION_RULE collation_rule; /* The collation rule
 						   for the index. */
 			u8 block_size_bits; 	/* Log2 of the above. */
 			u8 vcn_size_bits;	/* Log2 of the above. */
@@ -252,7 +252,7 @@ typedef struct {
 	unsigned long mft_no;
 	ntfschar *name;
 	u32 name_len;
-	ATTR_TYPES type;
+	ATTR_TYPE type;
 } ntfs_attr;
 
 typedef int (*test_t)(struct inode *, void *);
@@ -260,7 +260,7 @@ typedef int (*test_t)(struct inode *, void *);
 extern int ntfs_test_inode(struct inode *vi, ntfs_attr *na);
 
 extern struct inode *ntfs_iget(struct super_block *sb, unsigned long mft_no);
-extern struct inode *ntfs_attr_iget(struct inode *base_vi, ATTR_TYPES type,
+extern struct inode *ntfs_attr_iget(struct inode *base_vi, ATTR_TYPE type,
 		ntfschar *name, u32 name_len);
 extern struct inode *ntfs_index_iget(struct inode *base_vi, ntfschar *name,
 		u32 name_len);
@@ -285,7 +285,7 @@ extern void ntfs_truncate(struct inode *vi);
 
 extern int ntfs_setattr(struct dentry *dentry, struct iattr *attr);
 
-extern void ntfs_write_inode(struct inode *vi, int sync);
+extern int ntfs_write_inode(struct inode *vi, int sync);
 
 static inline void ntfs_commit_inode(struct inode *vi)
 {
diff --git a/fs/ntfs/layout.h b/fs/ntfs/layout.h
index b2b6161eb..57f3a8893 100644
--- a/fs/ntfs/layout.h
+++ b/fs/ntfs/layout.h
@@ -60,18 +60,18 @@
  * BIOS parameter block (bpb) structure.
  */
 typedef struct {
-	u16 bytes_per_sector;		/* Size of a sector in bytes. */
+	le16 bytes_per_sector;		/* Size of a sector in bytes. */
 	u8  sectors_per_cluster;	/* Size of a cluster in sectors. */
-	u16 reserved_sectors;		/* zero */
+	le16 reserved_sectors;		/* zero */
 	u8  fats;			/* zero */
-	u16 root_entries;		/* zero */
-	u16 sectors;			/* zero */
+	le16 root_entries;		/* zero */
+	le16 sectors;			/* zero */
 	u8  media_type;			/* 0xf8 = hard disk */
-	u16 sectors_per_fat;		/* zero */
-	u16 sectors_per_track;		/* irrelevant */
-	u16 heads;			/* irrelevant */
-	u32 hidden_sectors;		/* zero */
-	u32 large_sectors;		/* zero */
+	le16 sectors_per_fat;		/* zero */
+	le16 sectors_per_track;		/* irrelevant */
+	le16 heads;			/* irrelevant */
+	le32 hidden_sectors;		/* zero */
+	le32 large_sectors;		/* zero */
 } __attribute__ ((__packed__)) BIOS_PARAMETER_BLOCK;
 
 /*
@@ -79,7 +79,7 @@ typedef struct {
  */
 typedef struct {
 	u8  jump[3];			/* Irrelevant (jump to boot up code).*/
-	u64 oem_id;			/* Magic "NTFS    ". */
+	le64 oem_id;			/* Magic "NTFS    ". */
 	BIOS_PARAMETER_BLOCK bpb;	/* See BIOS_PARAMETER_BLOCK. */
 	u8  unused[4];			/* zero, NTFS diskedit.exe states that
 					   this is actually:
@@ -89,21 +89,21 @@ typedef struct {
 									// 0x80
 						__u8 unused;		// zero
 					 */
-/*0x28*/s64 number_of_sectors;		/* Number of sectors in volume. Gives
+/*0x28*/sle64 number_of_sectors;	/* Number of sectors in volume. Gives
 					   maximum volume size of 2^63 sectors.
 					   Assuming standard sector size of 512
 					   bytes, the maximum byte size is
 					   approx. 4.7x10^21 bytes. (-; */
-	s64 mft_lcn;			/* Cluster location of mft data. */
-	s64 mftmirr_lcn;		/* Cluster location of copy of mft. */
+	sle64 mft_lcn;			/* Cluster location of mft data. */
+	sle64 mftmirr_lcn;		/* Cluster location of copy of mft. */
 	s8  clusters_per_mft_record;	/* Mft record size in clusters. */
 	u8  reserved0[3];		/* zero */
 	s8  clusters_per_index_record;	/* Index block size in clusters. */
 	u8  reserved1[3];		/* zero */
-	u64 volume_serial_number;	/* Irrelevant (serial number). */
-	u32 checksum;			/* Boot sector checksum. */
+	le64 volume_serial_number;	/* Irrelevant (serial number). */
+	le32 checksum;			/* Boot sector checksum. */
 /*0x54*/u8  bootstrap[426];		/* Irrelevant (boot up code). */
-	u16 end_of_sector_marker;	/* End of bootsector magic. Always is
+	le16 end_of_sector_marker;	/* End of bootsector magic. Always is
 					   0xaa55 in little endian. */
 /* sizeof() = 512 (0x200) bytes */
 } __attribute__ ((__packed__)) NTFS_BOOT_SECTOR;
@@ -112,7 +112,7 @@ typedef struct {
  * Magic identifiers present at the beginning of all ntfs record containing
  * records (like mft records for example).
  */
-typedef enum {
+enum {
 	/* Found in $MFT/$DATA. */
 	magic_FILE = const_cpu_to_le32(0x454c4946), /* Mft entry. */
 	magic_INDX = const_cpu_to_le32(0x58444e49), /* Index buffer. */
@@ -128,72 +128,80 @@ typedef enum {
 	/* Found in all ntfs record containing records. */
 	magic_BAAD = const_cpu_to_le32(0x44414142), /* Failed multi sector
 						       transfer was detected. */
-
 	/*
-	 * Found in $LogFile/$DATA when a page is full or 0xff bytes and is
-	 * thus not initialized.  User has to initialize the page before using
-	 * it.
+	 * Found in $LogFile/$DATA when a page is full of 0xff bytes and is
+	 * thus not initialized.  Page must be initialized before using it.
 	 */
-	magic_empty = const_cpu_to_le32(0xffffffff),/* Record is empty and has
-						       to be initialized before
-						       it can be used. */
-} NTFS_RECORD_TYPES;
+	magic_empty = const_cpu_to_le32(0xffffffff) /* Record is empty. */
+};
+
+typedef le32 NTFS_RECORD_TYPE;
 
 /*
  * Generic magic comparison macros. Finally found a use for the ## preprocessor
  * operator! (-8
  */
-#define ntfs_is_magic(x, m)	(   (u32)(x) == magic_##m )
-#define ntfs_is_magicp(p, m)	( *(u32*)(p) == magic_##m )
+
+static inline BOOL __ntfs_is_magic(le32 x, NTFS_RECORD_TYPE r)
+{
+	return (x == r);
+}
+#define ntfs_is_magic(x, m)	__ntfs_is_magic(x, magic_##m)
+
+static inline BOOL __ntfs_is_magicp(le32 *p, NTFS_RECORD_TYPE r)
+{
+	return (*p == r);
+}
+#define ntfs_is_magicp(p, m)	__ntfs_is_magicp(p, magic_##m)
 
 /*
- * Specialised magic comparison macros for the NTFS_RECORD_TYPES defined above.
+ * Specialised magic comparison macros for the NTFS_RECORD_TYPEs defined above.
  */
-#define ntfs_is_file_record(x)	( ntfs_is_magic (x, FILE) )
-#define ntfs_is_file_recordp(p)	( ntfs_is_magicp(p, FILE) )
-#define ntfs_is_mft_record(x)	( ntfs_is_file_record(x) )
-#define ntfs_is_mft_recordp(p)	( ntfs_is_file_recordp(p) )
-#define ntfs_is_indx_record(x)	( ntfs_is_magic (x, INDX) )
-#define ntfs_is_indx_recordp(p)	( ntfs_is_magicp(p, INDX) )
-#define ntfs_is_hole_record(x)	( ntfs_is_magic (x, HOLE) )
-#define ntfs_is_hole_recordp(p)	( ntfs_is_magicp(p, HOLE) )
+#define ntfs_is_file_record(x)		( ntfs_is_magic (x, FILE) )
+#define ntfs_is_file_recordp(p)		( ntfs_is_magicp(p, FILE) )
+#define ntfs_is_mft_record(x)		( ntfs_is_file_record (x) )
+#define ntfs_is_mft_recordp(p)		( ntfs_is_file_recordp(p) )
+#define ntfs_is_indx_record(x)		( ntfs_is_magic (x, INDX) )
+#define ntfs_is_indx_recordp(p)		( ntfs_is_magicp(p, INDX) )
+#define ntfs_is_hole_record(x)		( ntfs_is_magic (x, HOLE) )
+#define ntfs_is_hole_recordp(p)		( ntfs_is_magicp(p, HOLE) )
 
-#define ntfs_is_rstr_record(x)	( ntfs_is_magic (x, RSTR) )
-#define ntfs_is_rstr_recordp(p)	( ntfs_is_magicp(p, RSTR) )
-#define ntfs_is_rcrd_record(x)	( ntfs_is_magic (x, RCRD) )
-#define ntfs_is_rcrd_recordp(p)	( ntfs_is_magicp(p, RCRD) )
+#define ntfs_is_rstr_record(x)		( ntfs_is_magic (x, RSTR) )
+#define ntfs_is_rstr_recordp(p)		( ntfs_is_magicp(p, RSTR) )
+#define ntfs_is_rcrd_record(x)		( ntfs_is_magic (x, RCRD) )
+#define ntfs_is_rcrd_recordp(p)		( ntfs_is_magicp(p, RCRD) )
 
-#define ntfs_is_chkd_record(x)	( ntfs_is_magic (x, CHKD) )
-#define ntfs_is_chkd_recordp(p)	( ntfs_is_magicp(p, CHKD) )
+#define ntfs_is_chkd_record(x)		( ntfs_is_magic (x, CHKD) )
+#define ntfs_is_chkd_recordp(p)		( ntfs_is_magicp(p, CHKD) )
 
-#define ntfs_is_baad_record(x)	( ntfs_is_magic (x, BAAD) )
-#define ntfs_is_baad_recordp(p)	( ntfs_is_magicp(p, BAAD) )
+#define ntfs_is_baad_record(x)		( ntfs_is_magic (x, BAAD) )
+#define ntfs_is_baad_recordp(p)		( ntfs_is_magicp(p, BAAD) )
 
 #define ntfs_is_empty_record(x)		( ntfs_is_magic (x, empty) )
 #define ntfs_is_empty_recordp(p)	( ntfs_is_magicp(p, empty) )
 
 /*
- * The Update Sequence Array (usa) is an array of the u16 values which belong
+ * The Update Sequence Array (usa) is an array of the le16 values which belong
  * to the end of each sector protected by the update sequence record in which
  * this array is contained. Note that the first entry is the Update Sequence
  * Number (usn), a cyclic counter of how many times the protected record has
  * been written to disk. The values 0 and -1 (ie. 0xffff) are not used. All
- * last u16's of each sector have to be equal to the usn (during reading) or
+ * last le16's of each sector have to be equal to the usn (during reading) or
  * are set to it (during writing). If they are not, an incomplete multi sector
  * transfer has occurred when the data was written.
  * The maximum size for the update sequence array is fixed to:
  *	maximum size = usa_ofs + (usa_count * 2) = 510 bytes
- * The 510 bytes comes from the fact that the last u16 in the array has to
- * (obviously) finish before the last u16 of the first 512-byte sector.
+ * The 510 bytes comes from the fact that the last le16 in the array has to
+ * (obviously) finish before the last le16 of the first 512-byte sector.
  * This formula can be used as a consistency check in that usa_ofs +
  * (usa_count * 2) has to be less than or equal to 510.
  */
 typedef struct {
-	NTFS_RECORD_TYPES magic;	/* A four-byte magic identifying the
-					   record type and/or status. */
-	u16 usa_ofs;		/* Offset to the Update Sequence Array (usa)
+	NTFS_RECORD_TYPE magic;	/* A four-byte magic identifying the record
+				   type and/or status. */
+	le16 usa_ofs;		/* Offset to the Update Sequence Array (usa)
 				   from the start of the ntfs record. */
-	u16 usa_count;		/* Number of u16 sized entries in the usa
+	le16 usa_count;		/* Number of le16 sized entries in the usa
 				   including the Update Sequence Number (usn),
 				   thus the number of fixups is the usa_count
 				   minus 1. */
@@ -249,11 +257,12 @@ typedef enum {
  * These are the so far known MFT_RECORD_* flags (16-bit) which contain
  * information about the mft record in which they are present.
  */
-typedef enum {
+enum {
 	MFT_RECORD_IN_USE	= const_cpu_to_le16(0x0001),
-	MFT_RECORD_IS_DIRECTORY	= const_cpu_to_le16(0x0002),
-	MFT_REC_SPACE_FILLER	= 0xffff	/* Just to make flags 16-bit. */
-} __attribute__ ((__packed__)) MFT_RECORD_FLAGS;
+	MFT_RECORD_IS_DIRECTORY = const_cpu_to_le16(0x0002),
+};
+
+typedef le16 MFT_RECORD_FLAGS;
 
 /*
  * mft references (aka file references or file record segment references) are
@@ -305,6 +314,7 @@ typedef enum {
 } MFT_REF_CONSTS;
 
 typedef u64 MFT_REF;
+typedef le64 leMFT_REF;
 
 #define MREF(x)		((unsigned long)((x) & MFT_REF_MASK_CPU))
 #define MSEQNO(x)	((u16)(((x) >> 48) & 0xffff))
@@ -325,18 +335,18 @@ typedef u64 MFT_REF;
 typedef struct {
 /*Ofs*/
 /*  0	NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
-	NTFS_RECORD_TYPES magic;/* Usually the magic is "FILE". */
-	u16 usa_ofs;		/* See NTFS_RECORD definition above. */
-	u16 usa_count;		/* See NTFS_RECORD definition above. */
+	NTFS_RECORD_TYPE magic;	/* Usually the magic is "FILE". */
+	le16 usa_ofs;		/* See NTFS_RECORD definition above. */
+	le16 usa_count;		/* See NTFS_RECORD definition above. */
 
-/*  8*/	u64 lsn;		/* $LogFile sequence number for this record.
+/*  8*/	le64 lsn;		/* $LogFile sequence number for this record.
 				   Changed every time the record is modified. */
-/* 16*/	u16 sequence_number;	/* Number of times this mft record has been
+/* 16*/	le16 sequence_number;	/* Number of times this mft record has been
 				   reused. (See description for MFT_REF
 				   above.) NOTE: The increment (skipping zero)
 				   is done when the file is deleted. NOTE: If
 				   this is zero it is left zero. */
-/* 18*/	u16 link_count;		/* Number of hard links, i.e. the number of
+/* 18*/	le16 link_count;	/* Number of hard links, i.e. the number of
 				   directory entries referencing this record.
 				   NOTE: Only used in mft base records.
 				   NOTE: When deleting a directory entry we
@@ -346,18 +356,18 @@ typedef struct {
 				   directory entry from the mft record and
 				   decrement the link_count.
 				   FIXME: Careful with Win32 + DOS names! */
-/* 20*/	u16 attrs_offset;	/* Byte offset to the first attribute in this
+/* 20*/	le16 attrs_offset;	/* Byte offset to the first attribute in this
 				   mft record from the start of the mft record.
 				   NOTE: Must be aligned to 8-byte boundary. */
 /* 22*/	MFT_RECORD_FLAGS flags;	/* Bit array of MFT_RECORD_FLAGS. When a file
 				   is deleted, the MFT_RECORD_IN_USE flag is
 				   set to zero. */
-/* 24*/	u32 bytes_in_use;	/* Number of bytes used in this mft record.
+/* 24*/	le32 bytes_in_use;	/* Number of bytes used in this mft record.
 				   NOTE: Must be aligned to 8-byte boundary. */
-/* 28*/	u32 bytes_allocated;	/* Number of bytes allocated for this mft
+/* 28*/	le32 bytes_allocated;	/* Number of bytes allocated for this mft
 				   record. This should be equal to the mft
 				   record size. */
-/* 32*/	MFT_REF base_mft_record; /* This is zero for base mft records.
+/* 32*/	leMFT_REF base_mft_record;/* This is zero for base mft records.
 				   When it is not zero it is a mft reference
 				   pointing to the base mft record to which
 				   this record belongs (this is then used to
@@ -369,17 +379,16 @@ typedef struct {
 				   attribute list also means finding the other
 				   potential extents, belonging to the non-base
 				   mft record). */
-/* 40*/	u16 next_attr_instance;	/* The instance number that will be
-				   assigned to the next attribute added to this
-				   mft record. NOTE: Incremented each time
-				   after it is used. NOTE: Every time the mft
-				   record is reused this number is set to zero.
-				   NOTE: The first instance number is always 0.
-				 */
+/* 40*/	le16 next_attr_instance;/* The instance number that will be assigned to
+				   the next attribute added to this mft record.
+				   NOTE: Incremented each time after it is used.
+				   NOTE: Every time the mft record is reused
+				   this number is set to zero.  NOTE: The first
+				   instance number is always 0. */
 /* sizeof() = 42 bytes */
 /* NTFS 3.1+ (Windows XP and above) introduce the following additions. */
-/* 42*/ //u16 reserved;		/* Reserved/alignment. */
-/* 44*/ //u32 mft_record_number;/* Number of this mft record. */
+/* 42*/ //le16 reserved;	/* Reserved/alignment. */
+/* 44*/ //le32 mft_record_number;/* Number of this mft record. */
 /* sizeof() = 48 bytes */
 /*
  * When (re)using the mft record, we place the update sequence array at this
@@ -393,15 +402,15 @@ typedef struct {
 } __attribute__ ((__packed__)) MFT_RECORD;
 
 /*
- * System defined attributes (32-bit). Each attribute type has a corresponding
+ * System defined attributes (32-bit).  Each attribute type has a corresponding
  * attribute name (Unicode string of maximum 64 character length) as described
  * by the attribute definitions present in the data attribute of the $AttrDef
- * system file. On NTFS 3.0 volumes the names are just as the types are named
- * in the below enum exchanging AT_ for the dollar sign ($). If that isn't a
- * revealing choice of symbol... (-;
+ * system file.  On NTFS 3.0 volumes the names are just as the types are named
+ * in the below defines exchanging AT_ for the dollar sign ($).  If that is not
+ * a revealing choice of symbol I do not know what is... (-;
  */
-typedef enum {
-	AT_UNUSED			= const_cpu_to_le32(	     0),
+enum {
+	AT_UNUSED			= const_cpu_to_le32(         0),
 	AT_STANDARD_INFORMATION		= const_cpu_to_le32(      0x10),
 	AT_ATTRIBUTE_LIST		= const_cpu_to_le32(      0x20),
 	AT_FILE_NAME			= const_cpu_to_le32(      0x30),
@@ -419,12 +428,16 @@ typedef enum {
 	AT_PROPERTY_SET			= const_cpu_to_le32(      0xf0),
 	AT_LOGGED_UTILITY_STREAM	= const_cpu_to_le32(     0x100),
 	AT_FIRST_USER_DEFINED_ATTRIBUTE	= const_cpu_to_le32(    0x1000),
-	AT_END				= const_cpu_to_le32(0xffffffff),
-} ATTR_TYPES;
+	AT_END				= const_cpu_to_le32(0xffffffff)
+};
+
+typedef le32 ATTR_TYPE;
 
 /*
  * The collation rules for sorting views/indexes/etc (32-bit).
  *
+ * COLLATION_BINARY - Collate by binary compare where the first byte is most
+ *	significant.
  * COLLATION_UNICODE_STRING - Collate Unicode strings by comparing their binary
  *	Unicode values, except that when a character can be uppercased, the
  *	upper case value collates before the lower case one.
@@ -435,63 +448,59 @@ typedef enum {
  *	unistr.c::ntfs_collate_names() and unistr.c::legal_ansi_char_array[]
  *	for what I mean but COLLATION_UNICODE_STRING would not give any special
  *	treatment to any characters at all, but this is speculation.
- * COLLATION_NTOFS_ULONG - Sorting is done according to ascending u32 key
+ * COLLATION_NTOFS_ULONG - Sorting is done according to ascending le32 key
  *	values. E.g. used for $SII index in FILE_Secure, which sorts by
- *	security_id (u32).
+ *	security_id (le32).
  * COLLATION_NTOFS_SID - Sorting is done according to ascending SID values.
  *	E.g. used for $O index in FILE_Extend/$Quota.
  * COLLATION_NTOFS_SECURITY_HASH - Sorting is done first by ascending hash
  *	values and second by ascending security_id values. E.g. used for $SDH
  *	index in FILE_Secure.
  * COLLATION_NTOFS_ULONGS - Sorting is done according to a sequence of ascending
- *	u32 key values. E.g. used for $O index in FILE_Extend/$ObjId, which
+ *	le32 key values. E.g. used for $O index in FILE_Extend/$ObjId, which
  *	sorts by object_id (16-byte), by splitting up the object_id in four
- *	u32 values and using them as individual keys. E.g. take the following
+ *	le32 values and using them as individual keys. E.g. take the following
  *	two security_ids, stored as follows on disk:
  *		1st: a1 61 65 b7 65 7b d4 11 9e 3d 00 e0 81 10 42 59
  *		2nd: 38 14 37 d2 d2 f3 d4 11 a5 21 c8 6b 79 b1 97 45
- *	To compare them, they are split into four u32 values each, like so:
+ *	To compare them, they are split into four le32 values each, like so:
  *		1st: 0xb76561a1 0x11d47b65 0xe0003d9e 0x59421081
  *		2nd: 0xd2371438 0x11d4f3d2 0x6bc821a5 0x4597b179
  *	Now, it is apparent why the 2nd object_id collates after the 1st: the
- *	first u32 value of the 1st object_id is less than the first u32 of
- *	the 2nd object_id. If the first u32 values of both object_ids were
- *	equal then the second u32 values would be compared, etc.
- */
-typedef enum {
-	COLLATION_BINARY	 = const_cpu_to_le32(0x00), /* Collate by
-					binary compare where the first byte is
-					most significant. */
-	COLLATION_FILE_NAME	 = const_cpu_to_le32(0x01), /* Collate file
-					names as Unicode strings. */
-	COLLATION_UNICODE_STRING = const_cpu_to_le32(0x02), /* Collate Unicode
-					strings by comparing their binary
-					Unicode values, except that when a
-					character can be uppercased, the upper
-					case value collates before the lower
-					case one. */
+ *	first le32 value of the 1st object_id is less than the first le32 of
+ *	the 2nd object_id. If the first le32 values of both object_ids were
+ *	equal then the second le32 values would be compared, etc.
+ */
+enum {
+	COLLATION_BINARY		= const_cpu_to_le32(0x00),
+	COLLATION_FILE_NAME		= const_cpu_to_le32(0x01),
+	COLLATION_UNICODE_STRING	= const_cpu_to_le32(0x02),
 	COLLATION_NTOFS_ULONG		= const_cpu_to_le32(0x10),
 	COLLATION_NTOFS_SID		= const_cpu_to_le32(0x11),
 	COLLATION_NTOFS_SECURITY_HASH	= const_cpu_to_le32(0x12),
-	COLLATION_NTOFS_ULONGS		= const_cpu_to_le32(0x13),
-} COLLATION_RULES;
+	COLLATION_NTOFS_ULONGS		= const_cpu_to_le32(0x13)
+};
+
+typedef le32 COLLATION_RULE;
 
 /*
  * The flags (32-bit) describing attribute properties in the attribute
- * definition structure. FIXME: This information is from Regis's information
+ * definition structure.  FIXME: This information is from Regis's information
  * and, according to him, it is not certain and probably incomplete.
  * The INDEXABLE flag is fairly certainly correct as only the file name
  * attribute has this flag set and this is the only attribute indexed in NT4.
  */
-typedef enum {
-	INDEXABLE	    = const_cpu_to_le32(0x02),	/* Attribute can be
-							   indexed. */
-	NEED_TO_REGENERATE  = const_cpu_to_le32(0x40),	/* Need to regenerate
-							   during regeneration
-							   phase. */
-	CAN_BE_NON_RESIDENT = const_cpu_to_le32(0x80),	/* Attribute can be
-							   non-resident. */
-} ATTR_DEF_FLAGS;
+enum {
+	INDEXABLE	    = const_cpu_to_le32(0x02), /* Attribute can be
+							  indexed. */
+	NEED_TO_REGENERATE  = const_cpu_to_le32(0x40), /* Need to regenerate
+							  during regeneration
+							  phase. */
+	CAN_BE_NON_RESIDENT = const_cpu_to_le32(0x80), /* Attribute can be
+							  non-resident. */
+};
+
+typedef le32 ATTR_DEF_FLAGS;
 
 /*
  * The data attribute of FILE_AttrDef contains a sequence of attribute
@@ -506,27 +515,29 @@ typedef struct {
 /*hex ofs*/
 /*  0*/	ntfschar name[0x40];		/* Unicode name of the attribute. Zero
 					   terminated. */
-/* 80*/	ATTR_TYPES type;		/* Type of the attribute. */
-/* 84*/	u32 display_rule;		/* Default display rule.
+/* 80*/	ATTR_TYPE type;			/* Type of the attribute. */
+/* 84*/	le32 display_rule;		/* Default display rule.
 					   FIXME: What does it mean? (AIA) */
-/* 88*/ COLLATION_RULES collation_rule;	/* Default collation rule. */
+/* 88*/ COLLATION_RULE collation_rule;	/* Default collation rule. */
 /* 8c*/	ATTR_DEF_FLAGS flags;		/* Flags describing the attribute. */
-/* 90*/	u64 min_size;			/* Optional minimum attribute size. */
-/* 98*/	u64 max_size;			/* Maximum size of attribute. */
+/* 90*/	le64 min_size;			/* Optional minimum attribute size. */
+/* 98*/	le64 max_size;			/* Maximum size of attribute. */
 /* sizeof() = 0xa0 or 160 bytes */
 } __attribute__ ((__packed__)) ATTR_DEF;
 
 /*
  * Attribute flags (16-bit).
  */
-typedef enum {
-	ATTR_IS_COMPRESSED	= const_cpu_to_le16(0x0001),
-	ATTR_COMPRESSION_MASK	= const_cpu_to_le16(0x00ff),  /* Compression
-						method mask. Also, first
-						illegal value. */
-	ATTR_IS_ENCRYPTED	= const_cpu_to_le16(0x4000),
-	ATTR_IS_SPARSE		= const_cpu_to_le16(0x8000),
-} __attribute__ ((__packed__)) ATTR_FLAGS;
+enum {
+	ATTR_IS_COMPRESSED    = const_cpu_to_le16(0x0001),
+	ATTR_COMPRESSION_MASK = const_cpu_to_le16(0x00ff), /* Compression method
+							      mask.  Also, first
+							      illegal value. */
+	ATTR_IS_ENCRYPTED     = const_cpu_to_le16(0x4000),
+	ATTR_IS_SPARSE	      = const_cpu_to_le16(0x8000),
+} __attribute__ ((__packed__));
+
+typedef le16 ATTR_FLAGS;
 
 /*
  * Attribute compression.
@@ -545,7 +556,7 @@ typedef enum {
  * can be stored:
  *
  *   1) The data in the block is all zero (a sparse block):
- *	  This is stored as a sparse block in the run list, i.e. the run list
+ *	  This is stored as a sparse block in the runlist, i.e. the runlist
  *	  entry has length = X and lcn = -1. The mapping pairs array actually
  *	  uses a delta_lcn value length of 0, i.e. delta_lcn is not present at
  *	  all, which is then interpreted by the driver as lcn = -1.
@@ -558,7 +569,7 @@ typedef enum {
  *	  in clusters. I.e. if compression has a small effect so that the
  *	  compressed data still occupies X clusters, then the uncompressed data
  *	  is stored in the block.
- *	  This case is recognised by the fact that the run list entry has
+ *	  This case is recognised by the fact that the runlist entry has
  *	  length = X and lcn >= 0. The mapping pairs array stores this as
  *	  normal with a run length of X and some specific delta_lcn, i.e.
  *	  delta_lcn has to be present.
@@ -567,7 +578,7 @@ typedef enum {
  *	  The common case. This case is recognised by the fact that the run
  *	  list entry has length L < X and lcn >= 0. The mapping pairs array
  *	  stores this as normal with a run length of X and some specific
- *	  delta_lcn, i.e. delta_lcn has to be present. This run list entry is
+ *	  delta_lcn, i.e. delta_lcn has to be present. This runlist entry is
  *	  immediately followed by a sparse entry with length = X - L and
  *	  lcn = -1. The latter entry is to make up the vcn counting to the
  *	  full compression block size X.
@@ -575,15 +586,15 @@ typedef enum {
  * In fact, life is more complicated because adjacent entries of the same type
  * can be coalesced. This means that one has to keep track of the number of
  * clusters handled and work on a basis of X clusters at a time being one
- * block. An example: if length L > X this means that this particular run list
+ * block. An example: if length L > X this means that this particular runlist
  * entry contains a block of length X and part of one or more blocks of length
  * L - X. Another example: if length L < X, this does not necessarily mean that
  * the block is compressed as it might be that the lcn changes inside the block
- * and hence the following run list entry describes the continuation of the
+ * and hence the following runlist entry describes the continuation of the
  * potentially compressed block. The block would be compressed if the
- * following run list entry describes at least X - L sparse clusters, thus
+ * following runlist entry describes at least X - L sparse clusters, thus
  * making up the compression block length as described in point 3 above. (Of
- * course, there can be several run list entries with small lengths so that the
+ * course, there can be several runlist entries with small lengths so that the
  * sparse entry does not follow the first data containing entry with
  * length < X.)
  *
@@ -598,26 +609,28 @@ typedef enum {
 /*
  * Flags of resident attributes (8-bit).
  */
-typedef enum {
+enum {
 	RESIDENT_ATTR_IS_INDEXED = 0x01, /* Attribute is referenced in an index
 					    (has implications for deleting and
 					    modifying the attribute). */
-} __attribute__ ((__packed__)) RESIDENT_ATTR_FLAGS;
+} __attribute__ ((__packed__));
+
+typedef u8 RESIDENT_ATTR_FLAGS;
 
 /*
  * Attribute record header. Always aligned to 8-byte boundary.
  */
 typedef struct {
 /*Ofs*/
-/*  0*/	ATTR_TYPES type;	/* The (32-bit) type of the attribute. */
-/*  4*/	u32 length;		/* Byte size of the resident part of the
+/*  0*/	ATTR_TYPE type;		/* The (32-bit) type of the attribute. */
+/*  4*/	le32 length;		/* Byte size of the resident part of the
 				   attribute (aligned to 8-byte boundary).
 				   Used to get to the next attribute. */
 /*  8*/	u8 non_resident;	/* If 0, attribute is resident.
 				   If 1, attribute is non-resident. */
 /*  9*/	u8 name_length;		/* Unicode character size of name of attribute.
 				   0 if unnamed. */
-/* 10*/	u16 name_offset;	/* If name_length != 0, the byte offset to the
+/* 10*/	le16 name_offset;	/* If name_length != 0, the byte offset to the
 				   beginning of the name from the attribute
 				   record. Note that the name is stored as a
 				   Unicode string. When creating, place offset
@@ -627,15 +640,15 @@ typedef struct {
 				   respectively, aligning to an 8-byte
 				   boundary. */
 /* 12*/	ATTR_FLAGS flags;	/* Flags describing the attribute. */
-/* 14*/	u16 instance;		/* The instance of this attribute record. This
+/* 14*/	le16 instance;		/* The instance of this attribute record. This
 				   number is unique within this mft record (see
 				   MFT_RECORD/next_attribute_instance notes in
 				   in mft.h for more details). */
 /* 16*/	union {
 		/* Resident attributes. */
 		struct {
-/* 16 */		u32 value_length; /* Byte size of attribute value. */
-/* 20 */		u16 value_offset; /* Byte offset of the attribute
+/* 16 */		le32 value_length;/* Byte size of attribute value. */
+/* 20 */		le16 value_offset;/* Byte offset of the attribute
 					     value from the start of the
 					     attribute record. When creating,
 					     align to 8-byte boundary if we
@@ -648,18 +661,18 @@ typedef struct {
 		} __attribute__ ((__packed__)) resident;
 		/* Non-resident attributes. */
 		struct {
-/* 16*/			VCN lowest_vcn;	/* Lowest valid virtual cluster number
+/* 16*/			leVCN lowest_vcn;/* Lowest valid virtual cluster number
 				for this portion of the attribute value or
 				0 if this is the only extent (usually the
 				case). - Only when an attribute list is used
 				does lowest_vcn != 0 ever occur. */
-/* 24*/			VCN highest_vcn; /* Highest valid vcn of this extent of
+/* 24*/			leVCN highest_vcn;/* Highest valid vcn of this extent of
 				the attribute value. - Usually there is only one
 				portion, so this usually equals the attribute
 				value size in clusters minus 1. Can be -1 for
 				zero length files. Can be 0 for "single extent"
 				attributes. */
-/* 32*/			u16 mapping_pairs_offset; /* Byte offset from the
+/* 32*/			le16 mapping_pairs_offset; /* Byte offset from the
 				beginning of the structure to the mapping pairs
 				array which contains the mappings between the
 				vcns and the logical cluster numbers (lcns).
@@ -674,7 +687,7 @@ typedef struct {
 /* 35*/			u8 reserved[5];		/* Align to 8-byte boundary. */
 /* The sizes below are only used when lowest_vcn is zero, as otherwise it would
    be difficult to keep them up-to-date.*/
-/* 40*/			s64 allocated_size;	/* Byte size of disk space
+/* 40*/			sle64 allocated_size;	/* Byte size of disk space
 				allocated to hold the attribute value. Always
 				is a multiple of the cluster size. When a file
 				is compressed, this field is a multiple of the
@@ -682,14 +695,14 @@ typedef struct {
 				it represents the logically allocated space
 				rather than the actual on disk usage. For this
 				use the compressed_size (see below). */
-/* 48*/			s64 data_size;	/* Byte size of the attribute
+/* 48*/			sle64 data_size;	/* Byte size of the attribute
 				value. Can be larger than allocated_size if
 				attribute value is compressed or sparse. */
-/* 56*/			s64 initialized_size;	/* Byte size of initialized
+/* 56*/			sle64 initialized_size;	/* Byte size of initialized
 				portion of the attribute value. Usually equals
 				data_size. */
 /* sizeof(uncompressed attr) = 64*/
-/* 64*/			s64 compressed_size;	/* Byte size of the attribute
+/* 64*/			sle64 compressed_size;	/* Byte size of the attribute
 				value after compression. Only present when
 				compressed. Always is a multiple of the
 				cluster size. Represents the actual amount of
@@ -704,19 +717,19 @@ typedef ATTR_RECORD ATTR_REC;
 /*
  * File attribute flags (32-bit).
  */
-typedef enum {
+enum {
 	/*
-	 * These flags are only present in the STANDARD_INFORMATION attribute
-	 * (in the field file_attributes).
+	 * The following flags are only present in the STANDARD_INFORMATION
+	 * attribute (in the field file_attributes).
 	 */
 	FILE_ATTR_READONLY		= const_cpu_to_le32(0x00000001),
 	FILE_ATTR_HIDDEN		= const_cpu_to_le32(0x00000002),
 	FILE_ATTR_SYSTEM		= const_cpu_to_le32(0x00000004),
-	/* Old DOS volid. Unused in NT.	= cpu_to_le32(0x00000008), */
+	/* Old DOS volid. Unused in NT.	= const_cpu_to_le32(0x00000008), */
 
 	FILE_ATTR_DIRECTORY		= const_cpu_to_le32(0x00000010),
-	/* FILE_ATTR_DIRECTORY is not considered valid in NT. It is reserved
-	   for the DOS SUBDIRECTORY flag. */
+	/* Note, FILE_ATTR_DIRECTORY is not considered valid in NT.  It is
+	   reserved for the DOS SUBDIRECTORY flag. */
 	FILE_ATTR_ARCHIVE		= const_cpu_to_le32(0x00000020),
 	FILE_ATTR_DEVICE		= const_cpu_to_le32(0x00000040),
 	FILE_ATTR_NORMAL		= const_cpu_to_le32(0x00000080),
@@ -731,29 +744,31 @@ typedef enum {
 	FILE_ATTR_ENCRYPTED		= const_cpu_to_le32(0x00004000),
 
 	FILE_ATTR_VALID_FLAGS		= const_cpu_to_le32(0x00007fb7),
-	/* FILE_ATTR_VALID_FLAGS masks out the old DOS VolId and the
-	   FILE_ATTR_DEVICE and preserves everything else. This mask
-	   is used to obtain all flags that are valid for reading. */
+	/* Note, FILE_ATTR_VALID_FLAGS masks out the old DOS VolId and the
+	   FILE_ATTR_DEVICE and preserves everything else.  This mask is used
+	   to obtain all flags that are valid for reading. */
 	FILE_ATTR_VALID_SET_FLAGS	= const_cpu_to_le32(0x000031a7),
-	/* FILE_ATTR_VALID_SET_FLAGS masks out the old DOS VolId, the
+	/* Note, FILE_ATTR_VALID_SET_FLAGS masks out the old DOS VolId, the
 	   F_A_DEVICE, F_A_DIRECTORY, F_A_SPARSE_FILE, F_A_REPARSE_POINT,
-	   F_A_COMPRESSED and F_A_ENCRYPTED and preserves the rest. This mask
+	   F_A_COMPRESSED, and F_A_ENCRYPTED and preserves the rest.  This mask
 	   is used to to obtain all flags that are valid for setting. */
 
 	/*
-	 * These flags are only present in the FILE_NAME attribute (in the
-	 * field file_attributes).
+	 * The following flags are only present in the FILE_NAME attribute (in
+	 * the field file_attributes).
 	 */
 	FILE_ATTR_DUP_FILE_NAME_INDEX_PRESENT	= const_cpu_to_le32(0x10000000),
-	/* This is a copy of the corresponding bit from the mft record, telling
-	   us whether this is a directory or not, i.e. whether it has an
-	   index root attribute or not. */
+	/* Note, this is a copy of the corresponding bit from the mft record,
+	   telling us whether this is a directory or not, i.e. whether it has
+	   an index root attribute or not. */
 	FILE_ATTR_DUP_VIEW_INDEX_PRESENT	= const_cpu_to_le32(0x20000000),
-	/* This is a copy of the corresponding bit from the mft record, telling
-	   us whether this file has a view index present (eg. object id index,
-	   quota index, one of the security indexes or the encrypting file
-	   system related indexes). */
-} FILE_ATTR_FLAGS;
+	/* Note, this is a copy of the corresponding bit from the mft record,
+	   telling us whether this file has a view index present (eg. object id
+	   index, quota index, one of the security indexes or the encrypting
+	   file system related indexes). */
+};
+
+typedef le32 FILE_ATTR_FLAGS;
 
 /*
  * NOTE on times in NTFS: All times are in MS standard time format, i.e. they
@@ -774,13 +789,13 @@ typedef enum {
  */
 typedef struct {
 /*Ofs*/
-/*  0*/	s64 creation_time;		/* Time file was created. Updated when
+/*  0*/	sle64 creation_time;		/* Time file was created. Updated when
 					   a filename is changed(?). */
-/*  8*/	s64 last_data_change_time;	/* Time the data attribute was last
+/*  8*/	sle64 last_data_change_time;	/* Time the data attribute was last
 					   modified. */
-/* 16*/	s64 last_mft_change_time;	/* Time this mft record was last
+/* 16*/	sle64 last_mft_change_time;	/* Time this mft record was last
 					   modified. */
-/* 24*/	s64 last_access_time;		/* Approximate time when the file was
+/* 24*/	sle64 last_access_time;		/* Approximate time when the file was
 					   last accessed (obviously this is not
 					   updated on read-only volumes). In
 					   Windows this is only updated when
@@ -817,23 +832,23 @@ typedef struct {
  * views that as a corruption, assuming that it behaves like this for all
  * attributes.
  */
-		/* 36*/	u32 maximum_versions;	/* Maximum allowed versions for
+		/* 36*/	le32 maximum_versions;	/* Maximum allowed versions for
 				file. Zero if version numbering is disabled. */
-		/* 40*/	u32 version_number;	/* This file's version (if any).
+		/* 40*/	le32 version_number;	/* This file's version (if any).
 				Set to zero if maximum_versions is zero. */
-		/* 44*/	u32 class_id;		/* Class id from bidirectional
+		/* 44*/	le32 class_id;		/* Class id from bidirectional
 				class id index (?). */
-		/* 48*/	u32 owner_id;		/* Owner_id of the user owning
+		/* 48*/	le32 owner_id;		/* Owner_id of the user owning
 				the file. Translate via $Q index in FILE_Extend
 				/$Quota to the quota control entry for the user
 				owning the file. Zero if quotas are disabled. */
-		/* 52*/	u32 security_id;	/* Security_id for the file.
+		/* 52*/	le32 security_id;	/* Security_id for the file.
 				Translate via $SII index and $SDS data stream
 				in FILE_Secure to the security descriptor. */
-		/* 56*/	u64 quota_charged;	/* Byte size of the charge to
+		/* 56*/	le64 quota_charged;	/* Byte size of the charge to
 				the quota for all streams of the file. Note: Is
 				zero if quotas are disabled. */
-		/* 64*/	u64 usn;		/* Last update sequence number
+		/* 64*/	le64 usn;		/* Last update sequence number
 				of the file. This is a direct index into the
 				change (aka usn) journal file. It is zero if
 				the usn journal is disabled.
@@ -886,14 +901,14 @@ typedef struct {
  */
 typedef struct {
 /*Ofs*/
-/*  0*/	ATTR_TYPES type;	/* Type of referenced attribute. */
-/*  4*/	u16 length;		/* Byte size of this entry (8-byte aligned). */
+/*  0*/	ATTR_TYPE type;		/* Type of referenced attribute. */
+/*  4*/	le16 length;		/* Byte size of this entry (8-byte aligned). */
 /*  6*/	u8 name_length;		/* Size in Unicode chars of the name of the
 				   attribute or 0 if unnamed. */
 /*  7*/	u8 name_offset;		/* Byte offset to beginning of attribute name
 				   (always set this to where the name would
 				   start even if unnamed). */
-/*  8*/	VCN lowest_vcn;		/* Lowest virtual cluster number of this portion
+/*  8*/	leVCN lowest_vcn;	/* Lowest virtual cluster number of this portion
 				   of the attribute value. This is usually 0. It
 				   is non-zero for the case where one attribute
 				   does not fit into one mft record and thus
@@ -905,10 +920,10 @@ typedef struct {
 				   value! The windows driver uses cmp, followed
 				   by jg when comparing this, thus it treats it
 				   as signed. */
-/* 16*/	MFT_REF mft_reference;	/* The reference of the mft record holding
+/* 16*/	leMFT_REF mft_reference;/* The reference of the mft record holding
 				   the ATTR_RECORD for this portion of the
 				   attribute value. */
-/* 24*/	u16 instance;		/* If lowest_vcn = 0, the instance of the
+/* 24*/	le16 instance;		/* If lowest_vcn = 0, the instance of the
 				   attribute being referenced; otherwise 0. */
 /* 26*/	ntfschar name[0];	/* Use when creating only. When reading use
 				   name_offset to determine the location of the
@@ -924,28 +939,28 @@ typedef struct {
 /*
  * Possible namespaces for filenames in ntfs (8-bit).
  */
-typedef enum {
-	FILE_NAME_POSIX			= 0x00,
-		/* This is the largest namespace. It is case sensitive and
-		   allows all Unicode characters except for: '\0' and '/'.
-		   Beware that in WinNT/2k files which eg have the same name
-		   except for their case will not be distinguished by the
-		   standard utilities and thus a "del filename" will delete
-		   both "filename" and "fileName" without warning. */
-	FILE_NAME_WIN32			= 0x01,
-		/* The standard WinNT/2k NTFS long filenames. Case insensitive.
-		   All Unicode chars except: '\0', '"', '*', '/', ':', '<',
-		   '>', '?', '\' and '|'. Further, names cannot end with a '.'
-		   or a space. */
-	FILE_NAME_DOS			= 0x02,
-		/* The standard DOS filenames (8.3 format). Uppercase only.
-		   All 8-bit characters greater space, except: '"', '*', '+',
-		   ',', '/', ':', ';', '<', '=', '>', '?' and '\'. */
-	FILE_NAME_WIN32_AND_DOS		= 0x03,
-		/* 3 means that both the Win32 and the DOS filenames are
-		   identical and hence have been saved in this single filename
-		   record. */
-} __attribute__ ((__packed__)) FILE_NAME_TYPE_FLAGS;
+enum {
+	FILE_NAME_POSIX		= 0x00,
+	/* This is the largest namespace. It is case sensitive and allows all
+	   Unicode characters except for: '\0' and '/'.  Beware that in
+	   WinNT/2k files which eg have the same name except for their case
+	   will not be distinguished by the standard utilities and thus a "del
+	   filename" will delete both "filename" and "fileName" without
+	   warning. */
+	FILE_NAME_WIN32		= 0x01,
+	/* The standard WinNT/2k NTFS long filenames. Case insensitive.  All
+	   Unicode chars except: '\0', '"', '*', '/', ':', '<', '>', '?', '\',
+	   and '|'.  Further, names cannot end with a '.' or a space. */
+	FILE_NAME_DOS		= 0x02,
+	/* The standard DOS filenames (8.3 format). Uppercase only.  All 8-bit
+	   characters greater space, except: '"', '*', '+', ',', '/', ':', ';',
+	   '<', '=', '>', '?', and '\'. */
+	FILE_NAME_WIN32_AND_DOS	= 0x03,
+	/* 3 means that both the Win32 and the DOS filenames are identical and
+	   hence have been saved in this single filename record. */
+} __attribute__ ((__packed__));
+
+typedef u8 FILE_NAME_TYPE_FLAGS;
 
 /*
  * Attribute: Filename (0x30).
@@ -962,30 +977,30 @@ typedef enum {
  */
 typedef struct {
 /*hex ofs*/
-/*  0*/	MFT_REF parent_directory;	/* Directory this filename is
+/*  0*/	leMFT_REF parent_directory;	/* Directory this filename is
 					   referenced from. */
-/*  8*/	s64 creation_time;		/* Time file was created. */
-/* 10*/	s64 last_data_change_time;	/* Time the data attribute was last
+/*  8*/	sle64 creation_time;		/* Time file was created. */
+/* 10*/	sle64 last_data_change_time;	/* Time the data attribute was last
 					   modified. */
-/* 18*/	s64 last_mft_change_time;	/* Time this mft record was last
+/* 18*/	sle64 last_mft_change_time;	/* Time this mft record was last
 					   modified. */
-/* 20*/	s64 last_access_time;		/* Time this mft record was last
+/* 20*/	sle64 last_access_time;		/* Time this mft record was last
 					   accessed. */
-/* 28*/	s64 allocated_size;		/* Byte size of allocated space for the
+/* 28*/	sle64 allocated_size;		/* Byte size of allocated space for the
 					   data attribute. NOTE: Is a multiple
 					   of the cluster size. */
-/* 30*/	s64 data_size;			/* Byte size of actual data in data
+/* 30*/	sle64 data_size;		/* Byte size of actual data in data
 					   attribute. */
 /* 38*/	FILE_ATTR_FLAGS file_attributes;	/* Flags describing the file. */
 /* 3c*/	union {
 	/* 3c*/	struct {
-		/* 3c*/	u16 packed_ea_size;	/* Size of the buffer needed to
+		/* 3c*/	le16 packed_ea_size;	/* Size of the buffer needed to
 						   pack the extended attributes
 						   (EAs), if such are present.*/
-		/* 3e*/	u16 reserved;		/* Reserved for alignment. */
+		/* 3e*/	le16 reserved;		/* Reserved for alignment. */
 		} __attribute__ ((__packed__)) ea;
 	/* 3c*/	struct {
-		/* 3c*/	u32 reparse_point_tag;	/* Type of reparse point,
+		/* 3c*/	le32 reparse_point_tag;	/* Type of reparse point,
 						   present only in reparse
 						   points and only if there are
 						   no EAs. */
@@ -1007,9 +1022,9 @@ typedef struct {
  *	1F010768-5A73-BC91-0010A52216A7
  */
 typedef struct {
-	u32 data1;	/* The first eight hexadecimal digits of the GUID. */
-	u16 data2;	/* The first group of four hexadecimal digits. */
-	u16 data3;	/* The second group of four hexadecimal digits. */
+	le32 data1;	/* The first eight hexadecimal digits of the GUID. */
+	le16 data2;	/* The first group of four hexadecimal digits. */
+	le16 data3;	/* The second group of four hexadecimal digits. */
 	u8 data4[8];	/* The first two bytes are the third group of four
 			   hexadecimal digits. The remaining six bytes are the
 			   final 12 hexadecimal digits. */
@@ -1027,7 +1042,7 @@ typedef struct {
  *	domain_id	- Reserved (always zero).
  */
 typedef struct {
-	MFT_REF mft_reference;	/* Mft record containing the object_id in
+	leMFT_REF mft_reference;/* Mft record containing the object_id in
 				   the index entry key. */
 	union {
 		struct {
@@ -1195,13 +1210,16 @@ typedef enum {					/* Identifier authority. */
 
 /*
  * The SID_IDENTIFIER_AUTHORITY is a 48-bit value used in the SID structure.
+ *
+ * NOTE: This is stored as a big endian number, hence the high_part comes
+ * before the low_part.
  */
 typedef union {
 	struct {
-		u32 low;	/* Low 32-bits. */
-		u16 high;	/* High 16-bits. */
+		u16 high_part;	/* High 16-bits. */
+		u32 low_part;	/* Low 32-bits. */
 	} __attribute__ ((__packed__)) parts;
-	u8 value[6];			/* Value as individual bytes. */
+	u8 value[6];		/* Value as individual bytes. */
 } __attribute__ ((__packed__)) SID_IDENTIFIER_AUTHORITY;
 
 /*
@@ -1232,7 +1250,7 @@ typedef struct {
 	u8 revision;
 	u8 sub_authority_count;
 	SID_IDENTIFIER_AUTHORITY identifier_authority;
-	u32 sub_authority[1];		/* At least one sub_authority. */
+	le32 sub_authority[1];		/* At least one sub_authority. */
 } __attribute__ ((__packed__)) SID;
 
 /*
@@ -1248,7 +1266,7 @@ typedef enum {
 /*
  * The predefined ACE types (8-bit, see below).
  */
-typedef enum {
+enum {
 	ACCESS_MIN_MS_ACE_TYPE		= 0,
 	ACCESS_ALLOWED_ACE_TYPE		= 0,
 	ACCESS_DENIED_ACE_TYPE		= 1,
@@ -1269,9 +1287,11 @@ typedef enum {
 
 	ACCESS_MAX_MS_V4_ACE_TYPE	= 8,
 
-	/* This one is for WinNT&2k. */
+	/* This one is for WinNT/2k. */
 	ACCESS_MAX_MS_ACE_TYPE		= 8,
-} __attribute__ ((__packed__)) ACE_TYPES;
+} __attribute__ ((__packed__));
+
+typedef u8 ACE_TYPES;
 
 /*
  * The ACE flags (8-bit) for audit and inheritance (see below).
@@ -1283,7 +1303,7 @@ typedef enum {
  * FAILED_ACCESS_ACE_FLAG is only used with system audit and alarm ACE types
  * to indicate that a message is generated (in Windows!) for failed accesses.
  */
-typedef enum {
+enum {
 	/* The inheritance flags. */
 	OBJECT_INHERIT_ACE		= 0x01,
 	CONTAINER_INHERIT_ACE		= 0x02,
@@ -1295,7 +1315,9 @@ typedef enum {
 	/* The audit flags. */
 	SUCCESSFUL_ACCESS_ACE_FLAG	= 0x40,
 	FAILED_ACCESS_ACE_FLAG		= 0x80,
-} __attribute__ ((__packed__)) ACE_FLAGS;
+} __attribute__ ((__packed__));
+
+typedef u8 ACE_FLAGS;
 
 /*
  * An ACE is an access-control entry in an access-control list (ACL).
@@ -1312,18 +1334,16 @@ typedef struct {
 /*Ofs*/
 /*  0*/	ACE_TYPES type;		/* Type of the ACE. */
 /*  1*/	ACE_FLAGS flags;	/* Flags describing the ACE. */
-/*  2*/	u16 size;		/* Size in bytes of the ACE. */
+/*  2*/	le16 size;		/* Size in bytes of the ACE. */
 } __attribute__ ((__packed__)) ACE_HEADER;
 
 /*
  * The access mask (32-bit). Defines the access rights.
+ *
+ * The specific rights (bits 0 to 15).  These depend on the type of the object
+ * being secured by the ACE.
  */
-typedef enum {
-	/*
-	 * The specific rights (bits 0 to 15). Depend on the type of the
-	 * object being secured by the ACE.
-	 */
-
+enum {
 	/* Specific rights for files and directories are as follows: */
 
 	/* Right to read data from the file. (FILE) */
@@ -1365,8 +1385,8 @@ typedef enum {
 	FILE_WRITE_ATTRIBUTES		= const_cpu_to_le32(0x00000100),
 
 	/*
-	 * The standard rights (bits 16 to 23). Are independent of the type of
-	 * object being secured.
+	 * The standard rights (bits 16 to 23).  These are independent of the
+	 * type of object being secured.
 	 */
 
 	/* Right to delete the object. */
@@ -1374,7 +1394,7 @@ typedef enum {
 
 	/*
 	 * Right to read the information in the object's security descriptor,
-	 * not including the information in the SACL. I.e. right to read the
+	 * not including the information in the SACL, i.e. right to read the
 	 * security descriptor and owner.
 	 */
 	READ_CONTROL			= const_cpu_to_le32(0x00020000),
@@ -1386,8 +1406,8 @@ typedef enum {
 	WRITE_OWNER			= const_cpu_to_le32(0x00080000),
 
 	/*
-	 * Right to use the object for synchronization. Enables a process to
-	 * wait until the object is in the signalled state. Some object types
+	 * Right to use the object for synchronization.  Enables a process to
+	 * wait until the object is in the signalled state.  Some object types
 	 * do not support this access right.
 	 */
 	SYNCHRONIZE			= const_cpu_to_le32(0x00100000),
@@ -1419,7 +1439,7 @@ typedef enum {
 	MAXIMUM_ALLOWED			= const_cpu_to_le32(0x02000000),
 
 	/*
-	 * The generic rights (bits 28 to 31). These map onto the standard and
+	 * The generic rights (bits 28 to 31).  These map onto the standard and
 	 * specific rights.
 	 */
 
@@ -1430,23 +1450,25 @@ typedef enum {
 	GENERIC_EXECUTE			= const_cpu_to_le32(0x20000000),
 
 	/*
-	 * Write access. For files, this maps onto:
+	 * Write access.  For files, this maps onto:
 	 *	FILE_APPEND_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA |
 	 *	FILE_WRITE_EA | STANDARD_RIGHTS_WRITE | SYNCHRONIZE
-	 * For directories, the mapping has the same numberical value. See
+	 * For directories, the mapping has the same numerical value.  See
 	 * above for the descriptions of the rights granted.
 	 */
 	GENERIC_WRITE			= const_cpu_to_le32(0x40000000),
 
 	/*
-	 * Read access. For files, this maps onto:
+	 * Read access.  For files, this maps onto:
 	 *	FILE_READ_ATTRIBUTES | FILE_READ_DATA | FILE_READ_EA |
 	 *	STANDARD_RIGHTS_READ | SYNCHRONIZE
-	 * For directories, the mapping has the same numberical value. See
+	 * For directories, the mapping has the same numberical value.  See
 	 * above for the descriptions of the rights granted.
 	 */
 	GENERIC_READ			= const_cpu_to_le32(0x80000000),
-} ACCESS_MASK;
+};
+
+typedef le32 ACCESS_MASK;
 
 /*
  * The generic mapping array. Used to denote the mapping of each generic
@@ -1472,7 +1494,7 @@ typedef struct {
 /*  0	ACE_HEADER; -- Unfolded here as gcc doesn't like unnamed structs. */
 	ACE_TYPES type;		/* Type of the ACE. */
 	ACE_FLAGS flags;	/* Flags describing the ACE. */
-	u16 size;		/* Size in bytes of the ACE. */
+	le16 size;		/* Size in bytes of the ACE. */
 /*  4*/	ACCESS_MASK mask;	/* Access mask associated with the ACE. */
 
 /*  8*/	SID sid;		/* The SID associated with the ACE. */
@@ -1482,16 +1504,18 @@ typedef struct {
 /*
  * The object ACE flags (32-bit).
  */
-typedef enum {
+enum {
 	ACE_OBJECT_TYPE_PRESENT			= const_cpu_to_le32(1),
 	ACE_INHERITED_OBJECT_TYPE_PRESENT	= const_cpu_to_le32(2),
-} OBJECT_ACE_FLAGS;
+};
+
+typedef le32 OBJECT_ACE_FLAGS;
 
 typedef struct {
 /*  0	ACE_HEADER; -- Unfolded here as gcc doesn't like unnamed structs. */
 	ACE_TYPES type;		/* Type of the ACE. */
 	ACE_FLAGS flags;	/* Flags describing the ACE. */
-	u16 size;		/* Size in bytes of the ACE. */
+	le16 size;		/* Size in bytes of the ACE. */
 /*  4*/	ACCESS_MASK mask;	/* Access mask associated with the ACE. */
 
 /*  8*/	OBJECT_ACE_FLAGS object_flags;	/* Flags describing the object ACE. */
@@ -1514,10 +1538,10 @@ typedef struct {
 typedef struct {
 	u8 revision;	/* Revision of this ACL. */
 	u8 alignment1;
-	u16 size;	/* Allocated space in bytes for ACL. Includes this
+	le16 size;	/* Allocated space in bytes for ACL. Includes this
 			   header, the ACEs and the remaining free space. */
-	u16 ace_count;	/* Number of ACEs in the ACL. */
-	u16 alignment2;
+	le16 ace_count;	/* Number of ACEs in the ACL. */
+	le16 alignment2;
 /* sizeof() = 8 bytes */
 } __attribute__ ((__packed__)) ACL;
 
@@ -1582,22 +1606,27 @@ typedef enum {
  *	security descriptor are contiguous in memory and all pointer fields are
  *	expressed as offsets from the beginning of the security descriptor.
  */
-typedef enum {
+enum {
 	SE_OWNER_DEFAULTED		= const_cpu_to_le16(0x0001),
 	SE_GROUP_DEFAULTED		= const_cpu_to_le16(0x0002),
 	SE_DACL_PRESENT			= const_cpu_to_le16(0x0004),
 	SE_DACL_DEFAULTED		= const_cpu_to_le16(0x0008),
+
 	SE_SACL_PRESENT			= const_cpu_to_le16(0x0010),
 	SE_SACL_DEFAULTED		= const_cpu_to_le16(0x0020),
+
 	SE_DACL_AUTO_INHERIT_REQ	= const_cpu_to_le16(0x0100),
 	SE_SACL_AUTO_INHERIT_REQ	= const_cpu_to_le16(0x0200),
 	SE_DACL_AUTO_INHERITED		= const_cpu_to_le16(0x0400),
 	SE_SACL_AUTO_INHERITED		= const_cpu_to_le16(0x0800),
+
 	SE_DACL_PROTECTED		= const_cpu_to_le16(0x1000),
 	SE_SACL_PROTECTED		= const_cpu_to_le16(0x2000),
 	SE_RM_CONTROL_VALID		= const_cpu_to_le16(0x4000),
-	SE_SELF_RELATIVE		= const_cpu_to_le16(0x8000),
-} __attribute__ ((__packed__)) SECURITY_DESCRIPTOR_CONTROL;
+	SE_SELF_RELATIVE		= const_cpu_to_le16(0x8000)
+} __attribute__ ((__packed__));
+
+typedef le16 SECURITY_DESCRIPTOR_CONTROL;
 
 /*
  * Self-relative security descriptor. Contains the owner and group SIDs as well
@@ -1608,17 +1637,17 @@ typedef struct {
 	u8 alignment;
 	SECURITY_DESCRIPTOR_CONTROL control; /* Flags qualifying the type of
 			   the descriptor as well as the following fields. */
-	u32 owner;	/* Byte offset to a SID representing an object's
+	le32 owner;	/* Byte offset to a SID representing an object's
 			   owner. If this is NULL, no owner SID is present in
 			   the descriptor. */
-	u32 group;	/* Byte offset to a SID representing an object's
+	le32 group;	/* Byte offset to a SID representing an object's
 			   primary group. If this is NULL, no primary group
 			   SID is present in the descriptor. */
-	u32 sacl;	/* Byte offset to a system ACL. Only valid, if
+	le32 sacl;	/* Byte offset to a system ACL. Only valid, if
 			   SE_SACL_PRESENT is set in the control field. If
 			   SE_SACL_PRESENT is set but sacl is NULL, a NULL ACL
 			   is specified. */
-	u32 dacl;	/* Byte offset to a discretionary ACL. Only valid, if
+	le32 dacl;	/* Byte offset to a discretionary ACL. Only valid, if
 			   SE_DACL_PRESENT is set in the control field. If
 			   SE_DACL_PRESENT is set but dacl is NULL, a NULL ACL
 			   (unconditionally granting access) is specified. */
@@ -1721,10 +1750,10 @@ typedef SECURITY_DESCRIPTOR_RELATIVE SECURITY_DESCRIPTOR_ATTR;
  * This is also the index entry data part of both the $SII and $SDH indexes.
  */
 typedef struct {
-	u32 hash;	   /* Hash of the security descriptor. */
-	u32 security_id;   /* The security_id assigned to the descriptor. */
-	u64 offset;	   /* Byte offset of this entry in the $SDS stream. */
-	u32 length;	   /* Size in bytes of this entry in $SDS stream. */
+	le32 hash;	  /* Hash of the security descriptor. */
+	le32 security_id; /* The security_id assigned to the descriptor. */
+	le64 offset;	  /* Byte offset of this entry in the $SDS stream. */
+	le32 length;	  /* Size in bytes of this entry in $SDS stream. */
 } __attribute__ ((__packed__)) SECURITY_DESCRIPTOR_HEADER;
 
 /*
@@ -1742,10 +1771,10 @@ typedef struct {
 /*Ofs*/
 /*  0	SECURITY_DESCRIPTOR_HEADER; -- Unfolded here as gcc doesn't like
 				       unnamed structs. */
-	u32 hash;	   /* Hash of the security descriptor. */
-	u32 security_id;   /* The security_id assigned to the descriptor. */
-	u64 offset;	   /* Byte offset of this entry in the $SDS stream. */
-	u32 length;	   /* Size in bytes of this entry in $SDS stream. */
+	le32 hash;	  /* Hash of the security descriptor. */
+	le32 security_id; /* The security_id assigned to the descriptor. */
+	le64 offset;	  /* Byte offset of this entry in the $SDS stream. */
+	le32 length;	  /* Size in bytes of this entry in $SDS stream. */
 /* 20*/	SECURITY_DESCRIPTOR_RELATIVE sid; /* The self-relative security
 					     descriptor. */
 } __attribute__ ((__packed__)) SDS_ENTRY;
@@ -1755,7 +1784,7 @@ typedef struct {
  * COLLATION_NTOFS_ULONG.
  */
 typedef struct {
-	u32 security_id; /* The security_id assigned to the descriptor. */
+	le32 security_id; /* The security_id assigned to the descriptor. */
 } __attribute__ ((__packed__)) SII_INDEX_KEY;
 
 /*
@@ -1764,8 +1793,8 @@ typedef struct {
  * COLLATION_NTOFS_SECURITY_HASH.
  */
 typedef struct {
-	u32 hash;	   /* Hash of the security descriptor. */
-	u32 security_id;   /* The security_id assigned to the descriptor. */
+	le32 hash;	  /* Hash of the security descriptor. */
+	le32 security_id; /* The security_id assigned to the descriptor. */
 } __attribute__ ((__packed__)) SDH_INDEX_KEY;
 
 /*
@@ -1781,19 +1810,24 @@ typedef struct {
 /*
  * Possible flags for the volume (16-bit).
  */
-typedef enum {
+enum {
 	VOLUME_IS_DIRTY			= const_cpu_to_le16(0x0001),
 	VOLUME_RESIZE_LOG_FILE		= const_cpu_to_le16(0x0002),
 	VOLUME_UPGRADE_ON_MOUNT		= const_cpu_to_le16(0x0004),
 	VOLUME_MOUNTED_ON_NT4		= const_cpu_to_le16(0x0008),
+
 	VOLUME_DELETE_USN_UNDERWAY	= const_cpu_to_le16(0x0010),
 	VOLUME_REPAIR_OBJECT_ID		= const_cpu_to_le16(0x0020),
+
 	VOLUME_MODIFIED_BY_CHKDSK	= const_cpu_to_le16(0x8000),
+
 	VOLUME_FLAGS_MASK		= const_cpu_to_le16(0x803f),
 
 	/* To make our life easier when checking if we must mount read-only. */
 	VOLUME_MUST_MOUNT_RO_MASK	= const_cpu_to_le16(0x8037),
-} __attribute__ ((__packed__)) VOLUME_FLAGS;
+} __attribute__ ((__packed__));
+
+typedef le16 VOLUME_FLAGS;
 
 /*
  * Attribute: Volume information (0x70).
@@ -1804,7 +1838,7 @@ typedef enum {
  *	 NTFS 1.2. I haven't personally seen other values yet.
  */
 typedef struct {
-	u64 reserved;		/* Not used (yet?). */
+	le64 reserved;		/* Not used (yet?). */
 	u8 major_ver;		/* Major version of the ntfs format. */
 	u8 minor_ver;		/* Minor version of the ntfs format. */
 	VOLUME_FLAGS flags;	/* Bit array of VOLUME_* flags. */
@@ -1824,24 +1858,28 @@ typedef struct {
 /*
  * Index header flags (8-bit).
  */
-typedef enum {
-	/* When index header is in an index root attribute: */
-	SMALL_INDEX	= 0, /* The index is small enough to fit inside the
-				index root attribute and there is no index
-				allocation attribute present. */
-	LARGE_INDEX	= 1, /* The index is too large to fit in the index
-				root attribute and/or an index allocation
-				attribute is present. */
+enum {
+	/*
+	 * When index header is in an index root attribute:
+	 */
+	SMALL_INDEX = 0, /* The index is small enough to fit inside the index
+			    root attribute and there is no index allocation
+			    attribute present. */
+	LARGE_INDEX = 1, /* The index is too large to fit in the index root
+			    attribute and/or an index allocation attribute is
+			    present. */
 	/*
 	 * When index header is in an index block, i.e. is part of index
 	 * allocation attribute:
 	 */
-	LEAF_NODE	= 0, /* This is a leaf node, i.e. there are no more
-				nodes branching off it. */
-	INDEX_NODE	= 1, /* This node indexes other nodes, i.e. is not a
-				leaf node. */
-	NODE_MASK	= 1, /* Mask for accessing the *_NODE bits. */
-} __attribute__ ((__packed__)) INDEX_HEADER_FLAGS;
+	LEAF_NODE  = 0, /* This is a leaf node, i.e. there are no more nodes
+			   branching off it. */
+	INDEX_NODE = 1, /* This node indexes other nodes, i.e. it is not a leaf
+			   node. */
+	NODE_MASK  = 1, /* Mask for accessing the *_NODE bits. */
+} __attribute__ ((__packed__));
+
+typedef u8 INDEX_HEADER_FLAGS;
 
 /*
  * This is the header for indexes, describing the INDEX_ENTRY records, which
@@ -1853,12 +1891,12 @@ typedef enum {
  * start of the index root or index allocation structures themselves.
  */
 typedef struct {
-	u32 entries_offset;		/* Byte offset to first INDEX_ENTRY
+	le32 entries_offset;		/* Byte offset to first INDEX_ENTRY
 					   aligned to 8-byte boundary. */
-	u32 index_length;		/* Data size of the index in bytes,
+	le32 index_length;		/* Data size of the index in bytes,
 					   i.e. bytes used from allocated
 					   size, aligned to 8-byte boundary. */
-	u32 allocated_size;		/* Byte size of this index (block),
+	le32 allocated_size;		/* Byte size of this index (block),
 					   multiple of 8 bytes. */
 	/* NOTE: For the index root attribute, the above two numbers are always
 	   equal, as the attribute is resident and it is resized as needed. In
@@ -1891,14 +1929,14 @@ typedef struct {
  * dircetories do not contain entries for themselves, though.
  */
 typedef struct {
-	ATTR_TYPES type;		/* Type of the indexed attribute. Is
+	ATTR_TYPE type;			/* Type of the indexed attribute. Is
 					   $FILE_NAME for directories, zero
 					   for view indexes. No other values
 					   allowed. */
-	COLLATION_RULES collation_rule;	/* Collation rule used to sort the
+	COLLATION_RULE collation_rule;	/* Collation rule used to sort the
 					   index entries. If type is $FILE_NAME,
 					   this must be COLLATION_FILE_NAME. */
-	u32 index_block_size;		/* Size of each index block in bytes (in
+	le32 index_block_size;		/* Size of each index block in bytes (in
 					   the index allocation attribute). */
 	u8 clusters_per_index_block;	/* Cluster size of each index block (in
 					   the index allocation attribute), when
@@ -1924,13 +1962,13 @@ typedef struct {
  */
 typedef struct {
 /*  0	NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
-	NTFS_RECORD_TYPES magic;/* Magic is "INDX". */
-	u16 usa_ofs;		/* See NTFS_RECORD definition. */
-	u16 usa_count;		/* See NTFS_RECORD definition. */
+	NTFS_RECORD_TYPE magic;	/* Magic is "INDX". */
+	le16 usa_ofs;		/* See NTFS_RECORD definition. */
+	le16 usa_count;		/* See NTFS_RECORD definition. */
 
-/*  8*/	s64 lsn;		/* $LogFile sequence number of the last
+/*  8*/	sle64 lsn;		/* $LogFile sequence number of the last
 				   modification of this index block. */
-/* 16*/	VCN index_block_vcn;	/* Virtual cluster number of the index block.
+/* 16*/	leVCN index_block_vcn;	/* Virtual cluster number of the index block.
 				   If the cluster_size on the volume is <= the
 				   index_block_size of the directory,
 				   index_block_vcn counts in units of clusters,
@@ -1960,34 +1998,40 @@ typedef INDEX_BLOCK INDEX_ALLOCATION;
  * primary key / is not a key at all. (AIA)
  */
 typedef struct {
-	u32 reparse_tag;	/* Reparse point type (inc. flags). */
-	MFT_REF file_id;	/* Mft record of the file containing the
+	le32 reparse_tag;	/* Reparse point type (inc. flags). */
+	leMFT_REF file_id;	/* Mft record of the file containing the
 				   reparse point attribute. */
 } __attribute__ ((__packed__)) REPARSE_INDEX_KEY;
 
 /*
  * Quota flags (32-bit).
+ *
+ * The user quota flags.  Names explain meaning.
  */
-typedef enum {
-	/* The user quota flags. Names explain meaning. */
+enum {
 	QUOTA_FLAG_DEFAULT_LIMITS	= const_cpu_to_le32(0x00000001),
 	QUOTA_FLAG_LIMIT_REACHED	= const_cpu_to_le32(0x00000002),
 	QUOTA_FLAG_ID_DELETED		= const_cpu_to_le32(0x00000004),
 
 	QUOTA_FLAG_USER_MASK		= const_cpu_to_le32(0x00000007),
-		/* Bit mask for user quota flags. */
+	/* This is a bit mask for the user quota flags. */
 
-	/* These flags are only present in the quota defaults index entry,
-	   i.e. in the entry where owner_id = QUOTA_DEFAULTS_ID. */
+	/*
+	 * These flags are only present in the quota defaults index entry, i.e.
+	 * in the entry where owner_id = QUOTA_DEFAULTS_ID.
+	 */
 	QUOTA_FLAG_TRACKING_ENABLED	= const_cpu_to_le32(0x00000010),
 	QUOTA_FLAG_ENFORCEMENT_ENABLED	= const_cpu_to_le32(0x00000020),
 	QUOTA_FLAG_TRACKING_REQUESTED	= const_cpu_to_le32(0x00000040),
 	QUOTA_FLAG_LOG_THRESHOLD	= const_cpu_to_le32(0x00000080),
+
 	QUOTA_FLAG_LOG_LIMIT		= const_cpu_to_le32(0x00000100),
 	QUOTA_FLAG_OUT_OF_DATE		= const_cpu_to_le32(0x00000200),
 	QUOTA_FLAG_CORRUPT		= const_cpu_to_le32(0x00000400),
 	QUOTA_FLAG_PENDING_DELETES	= const_cpu_to_le32(0x00000800),
-} QUOTA_FLAGS;
+};
+
+typedef le32 QUOTA_FLAGS;
 
 /*
  * The system file FILE_Extend/$Quota contains two indexes $O and $Q. Quotas
@@ -2011,13 +2055,13 @@ typedef enum {
  * The $Q index entry data is the quota control entry and is defined below.
  */
 typedef struct {
-	u32 version;		/* Currently equals 2. */
+	le32 version;		/* Currently equals 2. */
 	QUOTA_FLAGS flags;	/* Flags describing this quota entry. */
-	u64 bytes_used;		/* How many bytes of the quota are in use. */
-	s64 change_time;	/* Last time this quota entry was changed. */
-	s64 threshold;		/* Soft quota (-1 if not limited). */
-	s64 limit;		/* Hard quota (-1 if not limited). */
-	s64 exceeded_time;	/* How long the soft quota has been exceeded. */
+	le64 bytes_used;	/* How many bytes of the quota are in use. */
+	sle64 change_time;	/* Last time this quota entry was changed. */
+	sle64 threshold;	/* Soft quota (-1 if not limited). */
+	sle64 limit;		/* Hard quota (-1 if not limited). */
+	sle64 exceeded_time;	/* How long the soft quota has been exceeded. */
 	SID sid;		/* The SID of the user/object associated with
 				   this quota entry.  Equals zero for the quota
 				   defaults entry (and in fact on a WinXP
@@ -2027,11 +2071,11 @@ typedef struct {
 /*
  * Predefined owner_id values (32-bit).
  */
-typedef enum {
+enum {
 	QUOTA_INVALID_ID	= const_cpu_to_le32(0x00000000),
 	QUOTA_DEFAULTS_ID	= const_cpu_to_le32(0x00000001),
 	QUOTA_FIRST_USER_ID	= const_cpu_to_le32(0x00000100),
-} PREDEFINED_OWNER_IDS;
+};
 
 /*
  * Current constants for quota control entries.
@@ -2044,18 +2088,19 @@ typedef enum {
 /*
  * Index entry flags (16-bit).
  */
-typedef enum {
+enum {
 	INDEX_ENTRY_NODE = const_cpu_to_le16(1), /* This entry contains a
-					      sub-node, i.e. a reference to an
-					      index block in form of a virtual
-					      cluster number (see below). */
+			sub-node, i.e. a reference to an index block in form of
+			a virtual cluster number (see below). */
 	INDEX_ENTRY_END  = const_cpu_to_le16(2), /* This signifies the last
-					      entry in an index block.  The
-					      index entry does not represent a
-					      file but it can point to a
-					      sub-node. */
-	INDEX_ENTRY_SPACE_FILLER = 0xffff, /* Just to force 16-bit width. */
-} __attribute__ ((__packed__)) INDEX_ENTRY_FLAGS;
+			entry in an index block.  The index entry does not
+			represent a file but it can point to a sub-node. */
+
+	INDEX_ENTRY_SPACE_FILLER = const_cpu_to_le16(0xffff), /* gcc: Force
+			enum bit width to 16-bit. */
+} __attribute__ ((__packed__));
+
+typedef le16 INDEX_ENTRY_FLAGS;
 
 /*
  * This the index entry header (see below).
@@ -2063,26 +2108,26 @@ typedef enum {
 typedef struct {
 /*  0*/	union {
 		struct { /* Only valid when INDEX_ENTRY_END is not set. */
-			MFT_REF indexed_file;	/* The mft reference of the file
+			leMFT_REF indexed_file;	/* The mft reference of the file
 						   described by this index
 						   entry. Used for directory
 						   indexes. */
 		} __attribute__ ((__packed__)) dir;
 		struct { /* Used for views/indexes to find the entry's data. */
-			u16 data_offset;	/* Data byte offset from this
+			le16 data_offset;	/* Data byte offset from this
 						   INDEX_ENTRY. Follows the
 						   index key. */
-			u16 data_length;	/* Data length in bytes. */
-			u32 reservedV;		/* Reserved (zero). */
+			le16 data_length;	/* Data length in bytes. */
+			le32 reservedV;		/* Reserved (zero). */
 		} __attribute__ ((__packed__)) vi;
 	} __attribute__ ((__packed__)) data;
-/*  8*/	u16 length;		 /* Byte size of this index entry, multiple of
+/*  8*/	le16 length;		 /* Byte size of this index entry, multiple of
 				    8-bytes. */
-/* 10*/	u16 key_length;		 /* Byte size of the key value, which is in the
+/* 10*/	le16 key_length;	 /* Byte size of the key value, which is in the
 				    index entry. It follows field reserved. Not
 				    multiple of 8-bytes. */
 /* 12*/	INDEX_ENTRY_FLAGS flags; /* Bit field of INDEX_ENTRY_* flags. */
-/* 14*/	u16 reserved;		 /* Reserved/align to 8-byte boundary. */
+/* 14*/	le16 reserved;		 /* Reserved/align to 8-byte boundary. */
 /* sizeof() = 16 bytes */
 } __attribute__ ((__packed__)) INDEX_ENTRY_HEADER;
 
@@ -2098,26 +2143,26 @@ typedef struct {
 /*  0	INDEX_ENTRY_HEADER; -- Unfolded here as gcc dislikes unnamed structs. */
 	union {
 		struct { /* Only valid when INDEX_ENTRY_END is not set. */
-			MFT_REF indexed_file;	/* The mft reference of the file
+			leMFT_REF indexed_file;	/* The mft reference of the file
 						   described by this index
 						   entry. Used for directory
 						   indexes. */
 		} __attribute__ ((__packed__)) dir;
 		struct { /* Used for views/indexes to find the entry's data. */
-			u16 data_offset;	/* Data byte offset from this
+			le16 data_offset;	/* Data byte offset from this
 						   INDEX_ENTRY. Follows the
 						   index key. */
-			u16 data_length;	/* Data length in bytes. */
-			u32 reservedV;		/* Reserved (zero). */
+			le16 data_length;	/* Data length in bytes. */
+			le32 reservedV;		/* Reserved (zero). */
 		} __attribute__ ((__packed__)) vi;
 	} __attribute__ ((__packed__)) data;
-	u16 length;		 /* Byte size of this index entry, multiple of
+	le16 length;		 /* Byte size of this index entry, multiple of
 				    8-bytes. */
-	u16 key_length;		 /* Byte size of the key value, which is in the
+	le16 key_length;	 /* Byte size of the key value, which is in the
 				    index entry. It follows field reserved. Not
 				    multiple of 8-bytes. */
 	INDEX_ENTRY_FLAGS flags; /* Bit field of INDEX_ENTRY_* flags. */
-	u16 reserved;		 /* Reserved/align to 8-byte boundary. */
+	le16 reserved;		 /* Reserved/align to 8-byte boundary. */
 
 /* 16*/	union {		/* The key of the indexed attribute. NOTE: Only present
 			   if INDEX_ENTRY_END bit in flags is not set. NOTE: On
@@ -2134,13 +2179,13 @@ typedef struct {
 						   FILE_Extend/$Reparse. */
 		SID sid;		/* $O index in FILE_Extend/$Quota:
 					   SID of the owner of the user_id. */
-		u32 owner_id;		/* $Q index in FILE_Extend/$Quota:
+		le32 owner_id;		/* $Q index in FILE_Extend/$Quota:
 					   user_id of the owner of the quota
 					   control entry in the data part of
 					   the index. */
 	} __attribute__ ((__packed__)) key;
 	/* The (optional) index data is inserted here when creating. */
-	// VCN vcn;	/* If INDEX_ENTRY_NODE bit in flags is set, the last
+	// leVCN vcn;	/* If INDEX_ENTRY_NODE bit in flags is set, the last
 	//		   eight bytes of this index entry contain the virtual
 	//		   cluster number of the index block that holds the
 	//		   entries immediately preceding the current entry (the
@@ -2185,8 +2230,10 @@ typedef struct {
  *		be slow. (E.g. the data is stored on a tape drive.)
  *	bit 31: Microsoft bit. If set, the tag is owned by Microsoft. User
  *		defined tags have to use zero here.
+ *
+ * These are the predefined reparse point tags:
  */
-typedef enum {
+enum {
 	IO_REPARSE_TAG_IS_ALIAS		= const_cpu_to_le32(0x20000000),
 	IO_REPARSE_TAG_IS_HIGH_LATENCY	= const_cpu_to_le32(0x40000000),
 	IO_REPARSE_TAG_IS_MICROSOFT	= const_cpu_to_le32(0x80000000),
@@ -2207,7 +2254,7 @@ typedef enum {
 	IO_REPARSE_TAG_SYMBOLIC_LINK	= const_cpu_to_le32(0xe8000000),
 
 	IO_REPARSE_TAG_VALID_VALUES	= const_cpu_to_le32(0xe000ffff),
-} PREDEFINED_REPARSE_TAGS;
+};
 
 /*
  * Attribute: Reparse point (0xc0).
@@ -2215,9 +2262,9 @@ typedef enum {
  * NOTE: Can be resident or non-resident.
  */
 typedef struct {
-	u32 reparse_tag;		/* Reparse point type (inc. flags). */
-	u16 reparse_data_length;	/* Byte size of reparse data. */
-	u16 reserved;			/* Align to 8-byte boundary. */
+	le32 reparse_tag;		/* Reparse point type (inc. flags). */
+	le16 reparse_data_length;	/* Byte size of reparse data. */
+	le16 reserved;			/* Align to 8-byte boundary. */
 	u8 reparse_data[0];		/* Meaning depends on reparse_tag. */
 } __attribute__ ((__packed__)) REPARSE_POINT;
 
@@ -2227,11 +2274,11 @@ typedef struct {
  * NOTE: Always resident. (Is this true???)
  */
 typedef struct {
-	u16 ea_length;		/* Byte size of the packed extended
+	le16 ea_length;		/* Byte size of the packed extended
 				   attributes. */
-	u16 need_ea_count;	/* The number of extended attributes which have
+	le16 need_ea_count;	/* The number of extended attributes which have
 				   the NEED_EA bit set. */
-	u32 ea_query_length;	/* Byte size of the buffer required to query
+	le32 ea_query_length;	/* Byte size of the buffer required to query
 				   the extended attributes when calling
 				   ZwQueryEaFile() in Windows NT/2k. I.e. the
 				   byte size of the unpacked extended
@@ -2241,9 +2288,11 @@ typedef struct {
 /*
  * Extended attribute flags (8-bit).
  */
-typedef enum {
-	NEED_EA	= 0x80,
-} __attribute__ ((__packed__)) EA_FLAGS;
+enum {
+	NEED_EA	= 0x80
+} __attribute__ ((__packed__));
+
+typedef u8 EA_FLAGS;
 
 /*
  * Attribute: Extended attribute (EA) (0xe0).
@@ -2256,10 +2305,10 @@ typedef enum {
  * FIXME: It appears weird that the EA name is not unicode. Is it true?
  */
 typedef struct {
-	u32 next_entry_offset;	/* Offset to the next EA_ATTR. */
+	le32 next_entry_offset;	/* Offset to the next EA_ATTR. */
 	EA_FLAGS flags;		/* Flags describing the EA. */
 	u8 ea_name_length;	/* Length of the name of the EA in bytes. */
-	u16 ea_value_length;	/* Byte size of the EA's value. */
+	le16 ea_value_length;	/* Byte size of the EA's value. */
 	u8 ea_name[0];		/* Name of the EA. */
 	u8 ea_value[0];		/* The value of the EA. Immediately follows
 				   the name. */
diff --git a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c
index 5b448b184..1869a4375 100644
--- a/fs/ntfs/logfile.c
+++ b/fs/ntfs/logfile.c
@@ -497,7 +497,7 @@ BOOL ntfs_check_logfile(struct inode *log_vi)
 		 * empty block after a non-empty block has been encountered
 		 * means we are done.
 		 */
-		if (!ntfs_is_empty_recordp(kaddr))
+		if (!ntfs_is_empty_recordp((le32*)kaddr))
 			logfile_is_empty = FALSE;
 		else if (!logfile_is_empty)
 			break;
@@ -505,20 +505,20 @@ BOOL ntfs_check_logfile(struct inode *log_vi)
 		 * A log record page means there cannot be a restart page after
 		 * this so no need to continue searching.
 		 */
-		if (ntfs_is_rcrd_recordp(kaddr))
+		if (ntfs_is_rcrd_recordp((le32*)kaddr))
 			break;
 		/*
 		 * A modified by chkdsk restart page means we cannot handle
 		 * this log file.
 		 */
-		if (ntfs_is_chkd_recordp(kaddr)) {
+		if (ntfs_is_chkd_recordp((le32*)kaddr)) {
 			ntfs_error(vol->sb, "$LogFile has been modified by "
 					"chkdsk.  Mount this volume in "
 					"Windows.");
 			goto err_out;
 		}
 		/* If not a restart page, continue. */
-		if (!ntfs_is_rstr_recordp(kaddr)) {
+		if (!ntfs_is_rstr_recordp((le32*)kaddr)) {
 			/* Skip to the minimum page size for the next one. */
 			if (!pos)
 				pos = NTFS_BLOCK_SIZE >> 1;
diff --git a/fs/ntfs/logfile.h b/fs/ntfs/logfile.h
index e5e003a90..4ee4378de 100644
--- a/fs/ntfs/logfile.h
+++ b/fs/ntfs/logfile.h
@@ -67,34 +67,34 @@
 typedef struct {
 /*Ofs*/
 /*  0	NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
-/*  0*/	NTFS_RECORD_TYPES magic;/* The magic is "RSTR". */
-/*  4*/	u16 usa_ofs;		/* See NTFS_RECORD definition in layout.h.
+/*  0*/	NTFS_RECORD_TYPE magic;	/* The magic is "RSTR". */
+/*  4*/	le16 usa_ofs;		/* See NTFS_RECORD definition in layout.h.
 				   When creating, set this to be immediately
 				   after this header structure (without any
 				   alignment). */
-/*  6*/	u16 usa_count;		/* See NTFS_RECORD definition in layout.h. */
+/*  6*/	le16 usa_count;		/* See NTFS_RECORD definition in layout.h. */
 
-/*  8*/	LSN chkdsk_lsn;		/* The last log file sequence number found by
+/*  8*/	leLSN chkdsk_lsn;	/* The last log file sequence number found by
 				   chkdsk.  Only used when the magic is changed
 				   to "CHKD".  Otherwise this is zero. */
-/* 16*/	u32 system_page_size;	/* Byte size of system pages when the log file
+/* 16*/	le32 system_page_size;	/* Byte size of system pages when the log file
 				   was created, has to be >= 512 and a power of
 				   2.  Use this to calculate the required size
 				   of the usa (usa_count) and add it to usa_ofs.
 				   Then verify that the result is less than the
 				   value of the restart_area_offset. */
-/* 20*/	u32 log_page_size;	/* Byte size of log file pages, has to be >=
+/* 20*/	le32 log_page_size;	/* Byte size of log file pages, has to be >=
 				   512 and a power of 2.  The default is 4096
 				   and is used when the system page size is
 				   between 4096 and 8192.  Otherwise this is
 				   set to the system page size instead. */
-/* 24*/	u16 restart_area_offset;/* Byte offset from the start of this header to
+/* 24*/	le16 restart_area_offset;/* Byte offset from the start of this header to
 				   the RESTART_AREA.  Value has to be aligned
 				   to 8-byte boundary.  When creating, set this
 				   to be after the usa. */
-/* 26*/	s16 minor_ver;		/* Log file minor version.  Only check if major
+/* 26*/	sle16 minor_ver;	/* Log file minor version.  Only check if major
 				   version is 1. */
-/* 28*/	s16 major_ver;		/* Log file major version.  We only support
+/* 28*/	sle16 major_ver;	/* Log file major version.  We only support
 				   version 1.1. */
 /* sizeof() = 30 (0x1e) bytes */
 } __attribute__ ((__packed__)) RESTART_PAGE_HEADER;
@@ -111,10 +111,12 @@ typedef struct {
  * These are the so far known RESTART_AREA_* flags (16-bit) which contain
  * information about the log file in which they are present.
  */
-typedef enum {
+enum {
 	RESTART_VOLUME_IS_CLEAN	= const_cpu_to_le16(0x0002),
-	REST_AREA_SPACE_FILLER	= 0xffff	/* Just to make flags 16-bit. */
-} __attribute__ ((__packed__)) RESTART_AREA_FLAGS;
+	RESTART_SPACE_FILLER	= 0xffff, /* gcc: Force enum bit width to 16. */
+} __attribute__ ((__packed__));
+
+typedef le16 RESTART_AREA_FLAGS;
 
 /*
  * Log file restart area record.  The offset of this record is found by adding
@@ -123,16 +125,16 @@ typedef enum {
  */
 typedef struct {
 /*Ofs*/
-/*  0*/	LSN current_lsn;	/* The current, i.e. last LSN inside the log
+/*  0*/	leLSN current_lsn;	/* The current, i.e. last LSN inside the log
 				   when the restart area was last written.
 				   This happens often but what is the interval?
 				   Is it just fixed time or is it every time a
 				   check point is written or somethine else?
 				   On create set to 0. */
-/*  8*/	u16 log_clients;	/* Number of log client records in the array of
+/*  8*/	le16 log_clients;	/* Number of log client records in the array of
 				   log client records which follows this
 				   restart area.  Must be 1.  */
-/* 10*/	u16 client_free_list;	/* The index of the first free log client record
+/* 10*/	le16 client_free_list;	/* The index of the first free log client record
 				   in the array of log client records.
 				   LOGFILE_NO_CLIENT means that there are no
 				   free log client records in the array.
@@ -148,7 +150,7 @@ typedef struct {
 				   and presumably later, the logfile is always
 				   open, even on clean shutdown so this should
 				   always be LOGFILE_NO_CLIENT. */
-/* 12*/	u16 client_in_use_list;	/* The index of the first in-use log client
+/* 12*/	le16 client_in_use_list;/* The index of the first in-use log client
 				   record in the array of log client records.
 				   LOGFILE_NO_CLIENT means that there are no
 				   in-use log client records in the array.  If
@@ -181,13 +183,13 @@ typedef struct {
 				   clean.  If on the other hand the logfile is
 				   open and this bit is clear, we can be almost
 				   certain that the logfile is dirty. */
-/* 16*/	u32 seq_number_bits;	/* How many bits to use for the sequence
+/* 16*/	le32 seq_number_bits;	/* How many bits to use for the sequence
 				   number.  This is calculated as 67 - the
 				   number of bits required to store the logfile
 				   size in bytes and this can be used in with
 				   the specified file_size as a consistency
 				   check. */
-/* 20*/	u16 restart_area_length;/* Length of the restart area including the
+/* 20*/	le16 restart_area_length;/* Length of the restart area including the
 				   client array.  Following checks required if
 				   version matches.  Otherwise, skip them.
 				   restart_area_offset + restart_area_length
@@ -195,7 +197,7 @@ typedef struct {
 				   restart_area_length has to be >=
 				   client_array_offset + (log_clients *
 				   sizeof(log client record)). */
-/* 22*/	u16 client_array_offset;/* Offset from the start of this record to
+/* 22*/	le16 client_array_offset;/* Offset from the start of this record to
 				   the first log client record if versions are
 				   matched.  When creating, set this to be
 				   after this restart area structure, aligned
@@ -217,7 +219,7 @@ typedef struct {
 				   the client array.  This probably means that
 				   the RESTART_AREA record is actually bigger
 				   in WinXP and later. */
-/* 24*/	s64 file_size;		/* Usable byte size of the log file.  If the
+/* 24*/	sle64 file_size;	/* Usable byte size of the log file.  If the
 				   restart_area_offset + the offset of the
 				   file_size are > 510 then corruption has
 				   occured.  This is the very first check when
@@ -230,28 +232,28 @@ typedef struct {
 				   then it has to be at least big enough to
 				   store the two restart pages and 48 (0x30)
 				   log record pages. */
-/* 32*/	u32 last_lsn_data_length;/* Length of data of last LSN, not including
+/* 32*/	le32 last_lsn_data_length;/* Length of data of last LSN, not including
 				   the log record header.  On create set to
 				   0. */
-/* 36*/	u16 log_record_header_length;/* Byte size of the log record header.  If
-				   the version matches then check that the
+/* 36*/	le16 log_record_header_length;/* Byte size of the log record header.
+				   If the version matches then check that the
 				   value of log_record_header_length is a
 				   multiple of 8, i.e.
 				   (log_record_header_length + 7) & ~7 ==
 				   log_record_header_length.  When creating set
 				   it to sizeof(LOG_RECORD_HEADER), aligned to
 				   8 bytes. */
-/* 38*/	u16 log_page_data_offset;/* Offset to the start of data in a log record
+/* 38*/	le16 log_page_data_offset;/* Offset to the start of data in a log record
 				   page.  Must be a multiple of 8.  On create
 				   set it to immediately after the update
 				   sequence array of the log record page. */
-/* 40*/	u32 restart_log_open_count;/* A counter that gets incremented every time
-				   the logfile is restarted which happens at
-				   mount time when the logfile is opened.  When
-				   creating set to a random value.  Win2k sets
-				   it to the low 32 bits of the current system
-				   time in NTFS format (see time.h). */
-/* 44*/	u32 reserved;		/* Reserved/alignment to 8-byte boundary. */
+/* 40*/	le32 restart_log_open_count;/* A counter that gets incremented every
+				   time the logfile is restarted which happens
+				   at mount time when the logfile is opened.
+				   When creating set to a random value.  Win2k
+				   sets it to the low 32 bits of the current
+				   system time in NTFS format (see time.h). */
+/* 44*/	le32 reserved;		/* Reserved/alignment to 8-byte boundary. */
 /* sizeof() = 48 (0x30) bytes */
 } __attribute__ ((__packed__)) RESTART_AREA;
 
@@ -261,32 +263,32 @@ typedef struct {
  */
 typedef struct {
 /*Ofs*/
-/*  0*/	LSN oldest_lsn;		/* Oldest LSN needed by this client.  On create
+/*  0*/	leLSN oldest_lsn;	/* Oldest LSN needed by this client.  On create
 				   set to 0. */
-/*  8*/	LSN client_restart_lsn;	/* LSN at which this client needs to restart
+/*  8*/	leLSN client_restart_lsn;/* LSN at which this client needs to restart
 				   the volume, i.e. the current position within
 				   the log file.  At present, if clean this
 				   should = current_lsn in restart area but it
 				   probably also = current_lsn when dirty most
 				   of the time.  At create set to 0. */
-/* 16*/	u16 prev_client;	/* The offset to the previous log client record
+/* 16*/	le16 prev_client;	/* The offset to the previous log client record
 				   in the array of log client records.
 				   LOGFILE_NO_CLIENT means there is no previous
 				   client record, i.e. this is the first one.
 				   This is always LOGFILE_NO_CLIENT. */
-/* 18*/	u16 next_client;	/* The offset to the next log client record in
+/* 18*/	le16 next_client;	/* The offset to the next log client record in
 				   the array of log client records.
 				   LOGFILE_NO_CLIENT means there are no next
 				   client records, i.e. this is the last one.
 				   This is always LOGFILE_NO_CLIENT. */
-/* 20*/	u16 seq_number;		/* On Win2k and presumably earlier, this is set
+/* 20*/	le16 seq_number;	/* On Win2k and presumably earlier, this is set
 				   to zero every time the logfile is restarted
 				   and it is incremented when the logfile is
 				   closed at dismount time.  Thus it is 0 when
 				   dirty and 1 when clean.  On WinXP and
 				   presumably later, this is always 0. */
 /* 22*/	u8 reserved[6];		/* Reserved/alignment. */
-/* 28*/	u32 client_name_length; /* Length of client name in bytes.  Should
+/* 28*/	le32 client_name_length;/* Length of client name in bytes.  Should
 				   always be 8. */
 /* 32*/	ntfschar client_name[64];/* Name of the client in Unicode.  Should
 				   always be "NTFS" with the remaining bytes
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c
index 712f7ad0a..9192bbdf2 100644
--- a/fs/ntfs/mft.c
+++ b/fs/ntfs/mft.c
@@ -44,14 +44,14 @@ static void __format_mft_record(MFT_RECORD *m, const int size,
 	m->usa_ofs = cpu_to_le16((sizeof(MFT_RECORD) + 1) & ~1);
 	m->usa_count = cpu_to_le16(size / NTFS_BLOCK_SIZE + 1);
 	/* Set the update sequence number to 1. */
-	*(u16*)((char*)m + ((sizeof(MFT_RECORD) + 1) & ~1)) = cpu_to_le16(1);
+	*(le16*)((char*)m + ((sizeof(MFT_RECORD) + 1) & ~1)) = cpu_to_le16(1);
 	m->lsn = cpu_to_le64(0LL);
 	m->sequence_number = cpu_to_le16(1);
-	m->link_count = cpu_to_le16(0);
+	m->link_count = 0;
 	/* Aligned to 8-byte boundary. */
 	m->attrs_offset = cpu_to_le16((le16_to_cpu(m->usa_ofs) +
 			(le16_to_cpu(m->usa_count) << 1) + 7) & ~7);
-	m->flags = cpu_to_le16(0);
+	m->flags = 0;
 	/*
 	 * Using attrs_offset plus eight bytes (for the termination attribute),
 	 * aligned to 8-byte boundary.
@@ -60,10 +60,10 @@ static void __format_mft_record(MFT_RECORD *m, const int size,
 			~7);
 	m->bytes_allocated = cpu_to_le32(size);
 	m->base_mft_record = cpu_to_le64((MFT_REF)0);
-	m->next_attr_instance = cpu_to_le16(0);
+	m->next_attr_instance = 0;
 	a = (ATTR_RECORD*)((char*)m + le16_to_cpu(m->attrs_offset));
 	a->type = AT_END;
-	a->length = cpu_to_le32(0);
+	a->length = 0;
 }
 
 /**
@@ -311,11 +311,11 @@ void unmap_mft_record(ntfs_inode *ni)
 /**
  * map_extent_mft_record - load an extent inode and attach it to its base
  * @base_ni:	base ntfs inode
- * @mref:	mft reference of the extent inode to load (in little endian)
+ * @mref:	mft reference of the extent inode to load
  * @ntfs_ino:	on successful return, pointer to the ntfs_inode structure
  *
  * Load the extent mft record @mref and attach it to its base inode @base_ni.
- * Return the mapped extent mft record if IS_ERR(result) is false. Otherwise
+ * Return the mapped extent mft record if IS_ERR(result) is false.  Otherwise
  * PTR_ERR(result) gives the negative error code.
  *
  * On successful return, @ntfs_ino contains a pointer to the ntfs_inode
@@ -328,8 +328,8 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
 	ntfs_inode *ni = NULL;
 	ntfs_inode **extent_nis = NULL;
 	int i;
-	unsigned long mft_no = MREF_LE(mref);
-	u16 seq_no = MSEQNO_LE(mref);
+	unsigned long mft_no = MREF(mref);
+	u16 seq_no = MSEQNO(mref);
 	BOOL destroy_ni = FALSE;
 
 	ntfs_debug("Mapping extent mft record 0x%lx (base mft record 0x%lx).",
@@ -391,7 +391,7 @@ map_err_out:
 	ni->ext.base_ntfs_ino = base_ni;
 	/* Now map the record. */
 	m = map_mft_record(ni);
-	if (unlikely(IS_ERR(m))) {
+	if (IS_ERR(m)) {
 		up(&base_ni->extent_lock);
 		atomic_dec(&base_ni->count);
 		ntfs_clear_extent_inode(ni);
@@ -418,7 +418,8 @@ map_err_out:
 			m = ERR_PTR(-ENOMEM);
 			goto unm_err_out;
 		}
-		if (base_ni->ext.extent_ntfs_inos) {
+		if (base_ni->nr_extents) {
+			BUG_ON(!base_ni->ext.extent_ntfs_inos);
 			memcpy(tmp, base_ni->ext.extent_ntfs_inos, new_size -
 					4 * sizeof(ntfs_inode *));
 			kfree(base_ni->ext.extent_ntfs_inos);
@@ -571,7 +572,7 @@ static int sync_mft_mirror(ntfs_inode *ni, MFT_RECORD *m, int sync)
 	/* Get the page containing the mirror copy of the mft record @m. */
 	page = ntfs_map_page(vol->mftmirr_ino->i_mapping, ni->mft_no >>
 			(PAGE_CACHE_SHIFT - vol->mft_record_size_bits));
-	if (unlikely(IS_ERR(page))) {
+	if (IS_ERR(page)) {
 		ntfs_error(vol->sb, "Failed to map mft mirror page.");
 		err = PTR_ERR(page);
 		goto err_out;
@@ -979,7 +980,7 @@ static int ntfs_mft_writepage(struct page *page, struct writeback_control *wbc)
 		ntfs_debug("Inode 0x%lx is not in icache.", mft_no);
 		/* The inode is not in icache. */
 		/* Skip the record if it is not a mft record (type "FILE"). */
-		if (!ntfs_is_mft_recordp(maddr)) {
+		if (!ntfs_is_mft_recordp((le32*)maddr)) {
 			ntfs_debug("Mft record 0x%lx is not a FILE record, "
 					"continuing search.", mft_no);
 			continue;
diff --git a/fs/ntfs/mst.c b/fs/ntfs/mst.c
index 871548cf7..5a858d839 100644
--- a/fs/ntfs/mst.c
+++ b/fs/ntfs/mst.c
@@ -122,8 +122,9 @@ int post_read_mst_fixup(NTFS_RECORD *b, const u32 size)
  */
 int pre_write_mst_fixup(NTFS_RECORD *b, const u32 size)
 {
+	le16 *usa_pos, *data_pos;
 	u16 usa_ofs, usa_count, usn;
-	u16 *usa_pos, *data_pos;
+	le16 le_usn;
 
 	/* Sanity check + only fixup if it makes sense. */
 	if (!b || ntfs_is_baad_record(b->magic) ||
@@ -140,7 +141,7 @@ int pre_write_mst_fixup(NTFS_RECORD *b, const u32 size)
 	     (size >> NTFS_BLOCK_SIZE_BITS) != usa_count)
 		return -EINVAL;
 	/* Position of usn in update sequence array. */
-	usa_pos = (u16*)((u8*)b + usa_ofs);
+	usa_pos = (le16*)((u8*)b + usa_ofs);
 	/*
 	 * Cyclically increment the update sequence number
 	 * (skipping 0 and -1, i.e. 0xffff).
@@ -148,10 +149,10 @@ int pre_write_mst_fixup(NTFS_RECORD *b, const u32 size)
 	usn = le16_to_cpup(usa_pos) + 1;
 	if (usn == 0xffff || !usn)
 		usn = 1;
-	usn = cpu_to_le16(usn);
-	*usa_pos = usn;
+	le_usn = cpu_to_le16(usn);
+	*usa_pos = le_usn;
 	/* Position in data of first u16 that needs fixing up. */
-	data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1;
+	data_pos = (le16*)b + NTFS_BLOCK_SIZE/sizeof(le16) - 1;
 	/* Fixup all sectors. */
 	while (usa_count--) {
 		/*
@@ -160,9 +161,9 @@ int pre_write_mst_fixup(NTFS_RECORD *b, const u32 size)
 		 */
 		*(++usa_pos) = *data_pos;
 		/* Apply fixup to data. */
-		*data_pos = usn;
+		*data_pos = le_usn;
 		/* Increment position in data as well. */
-		data_pos += NTFS_BLOCK_SIZE/sizeof(u16);
+		data_pos += NTFS_BLOCK_SIZE/sizeof(le16);
 	}
 	return 0;
 }
@@ -177,16 +178,16 @@ int pre_write_mst_fixup(NTFS_RECORD *b, const u32 size)
  */
 void post_write_mst_fixup(NTFS_RECORD *b)
 {
-	u16 *usa_pos, *data_pos;
+	le16 *usa_pos, *data_pos;
 
 	u16 usa_ofs = le16_to_cpu(b->usa_ofs);
 	u16 usa_count = le16_to_cpu(b->usa_count) - 1;
 
 	/* Position of usn in update sequence array. */
-	usa_pos = (u16*)b + usa_ofs/sizeof(u16);
+	usa_pos = (le16*)b + usa_ofs/sizeof(le16);
 
 	/* Position in protected data of first u16 that needs fixing up. */
-	data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1;
+	data_pos = (le16*)b + NTFS_BLOCK_SIZE/sizeof(le16) - 1;
 
 	/* Fixup all sectors. */
 	while (usa_count--) {
@@ -197,6 +198,6 @@ void post_write_mst_fixup(NTFS_RECORD *b)
 		*data_pos = *(++usa_pos);
 
 		/* Increment position in data as well. */
-		data_pos += NTFS_BLOCK_SIZE/sizeof(u16);
+		data_pos += NTFS_BLOCK_SIZE/sizeof(le16);
 	}
 }
diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c
index c5ab58086..70b503a85 100644
--- a/fs/ntfs/namei.c
+++ b/fs/ntfs/namei.c
@@ -171,7 +171,7 @@ handle_name:
    {
 	struct dentry *real_dent, *new_dent;
 	MFT_RECORD *m;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	ntfs_inode *ni = NTFS_I(dent_inode);
 	int err;
 	struct qstr nls_name;
@@ -196,8 +196,8 @@ handle_name:
 			ctx = NULL;
 			goto err_out;
 		}
-		ctx = get_attr_search_ctx(ni, m);
-		if (!ctx) {
+		ctx = ntfs_attr_get_search_ctx(ni, m);
+		if (unlikely(!ctx)) {
 			err = -ENOMEM;
 			goto err_out;
 		}
@@ -205,12 +205,14 @@ handle_name:
 			ATTR_RECORD *a;
 			u32 val_len;
 
-			if (!lookup_attr(AT_FILE_NAME, NULL, 0, 0, 0, NULL, 0,
-					ctx)) {
+			err = ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, 0, 0,
+					NULL, 0, ctx);
+			if (unlikely(err)) {
 				ntfs_error(vol->sb, "Inode corrupt: No WIN32 "
 						"namespace counterpart to DOS "
 						"file name. Run chkdsk.");
-				err = -EIO;
+				if (err == -ENOENT)
+					err = -EIO;
 				goto err_out;
 			}
 			/* Consistency checks. */
@@ -233,7 +235,7 @@ handle_name:
 				(ntfschar*)&fn->file_name, fn->file_name_length,
 				(unsigned char**)&nls_name.name, 0);
 
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 		unmap_mft_record(ni);
 	}
 	m = NULL;
@@ -329,7 +331,7 @@ eio_err_out:
 	err = -EIO;
 err_out:
 	if (ctx)
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 	if (m)
 		unmap_mft_record(ni);
 	iput(dent_inode);
@@ -366,32 +368,36 @@ struct dentry *ntfs_get_parent(struct dentry *child_dent)
 	struct inode *vi = child_dent->d_inode;
 	ntfs_inode *ni = NTFS_I(vi);
 	MFT_RECORD *mrec;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	ATTR_RECORD *attr;
 	FILE_NAME_ATTR *fn;
 	struct inode *parent_vi;
 	struct dentry *parent_dent;
 	unsigned long parent_ino;
+	int err;
 
 	ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
 	/* Get the mft record of the inode belonging to the child dentry. */
 	mrec = map_mft_record(ni);
-	if (unlikely(IS_ERR(mrec)))
+	if (IS_ERR(mrec))
 		return (struct dentry *)mrec;
 	/* Find the first file name attribute in the mft record. */
-	ctx = get_attr_search_ctx(ni, mrec);
+	ctx = ntfs_attr_get_search_ctx(ni, mrec);
 	if (unlikely(!ctx)) {
 		unmap_mft_record(ni);
 		return ERR_PTR(-ENOMEM);
 	}
 try_next:
-	if (unlikely(!lookup_attr(AT_FILE_NAME, NULL, 0, CASE_SENSITIVE, 0,
-			NULL, 0, ctx))) {
-		put_attr_search_ctx(ctx);
+	err = ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, CASE_SENSITIVE, 0, NULL,
+			0, ctx);
+	if (unlikely(err)) {
+		ntfs_attr_put_search_ctx(ctx);
 		unmap_mft_record(ni);
-		ntfs_error(vi->i_sb, "Inode 0x%lx does not have a file name "
-				"attribute. Run chkdsk.", vi->i_ino);
-		return ERR_PTR(-ENOENT);
+		if (err == -ENOENT)
+			ntfs_error(vi->i_sb, "Inode 0x%lx does not have a "
+					"file name attribute.  Run chkdsk.",
+					vi->i_ino);
+		return ERR_PTR(err);
 	}
 	attr = ctx->attr;
 	if (unlikely(attr->non_resident))
@@ -404,11 +410,11 @@ try_next:
 	/* Get the inode number of the parent directory. */
 	parent_ino = MREF_LE(fn->parent_directory);
 	/* Release the search context and the mft record of the child. */
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(ni);
 	/* Get the inode of the parent directory. */
 	parent_vi = ntfs_iget(vi->i_sb, parent_ino);
-	if (unlikely(IS_ERR(parent_vi) || is_bad_inode(parent_vi))) {
+	if (IS_ERR(parent_vi) || unlikely(is_bad_inode(parent_vi))) {
 		if (!IS_ERR(parent_vi))
 			iput(parent_vi);
 		ntfs_error(vi->i_sb, "Failed to get parent directory inode "
@@ -451,7 +457,7 @@ struct dentry *ntfs_get_dentry(struct super_block *sb, void *fh)
 
 	ntfs_debug("Entering for inode 0x%lx, generation 0x%x.", ino, gen);
 	vi = ntfs_iget(sb, ino);
-	if (unlikely(IS_ERR(vi))) {
+	if (IS_ERR(vi)) {
 		ntfs_error(sb, "Failed to get inode 0x%lx.", ino);
 		return (struct dentry *)vi;
 	}
diff --git a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h
index abc057ecc..c3fda1715 100644
--- a/fs/ntfs/ntfs.h
+++ b/fs/ntfs/ntfs.h
@@ -156,9 +156,8 @@ extern int ntfs_read_compressed_block(struct page *page);
 
 /* From fs/ntfs/super.c */
 #define default_upcase_len 0x10000
-extern wchar_t *default_upcase;
+extern ntfschar *default_upcase;
 extern unsigned long ntfs_nr_upcase_users;
-extern unsigned long ntfs_nr_mounts;
 extern struct semaphore ntfs_lock;
 
 typedef struct {
diff --git a/fs/ntfs/quota.c b/fs/ntfs/quota.c
index d66ca9ebe..b72a85dd4 100644
--- a/fs/ntfs/quota.c
+++ b/fs/ntfs/quota.c
@@ -37,7 +37,7 @@ BOOL ntfs_mark_quotas_out_of_date(ntfs_volume *vol)
 {
 	ntfs_index_context *ictx;
 	QUOTA_CONTROL_ENTRY *qce;
-	const u32 qid = QUOTA_DEFAULTS_ID;
+	const le32 qid = QUOTA_DEFAULTS_ID;
 	int err;
 
 	ntfs_debug("Entering.");
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index e49428592..2c93c5918 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -28,6 +28,8 @@
 #include <linux/backing-dev.h>
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
+#include <linux/moduleparam.h>
+#include <linux/smp_lock.h>
 
 #include "ntfs.h"
 #include "sysctl.h"
@@ -143,7 +145,7 @@ static BOOL parse_options(ntfs_volume *vol, char *opt)
 	ntfs_debug("Entering with mount options string: %s", opt);
 	while ((p = strsep(&opt, ","))) {
 		if ((v = strchr(p, '=')))
-			*v++ = '\0';
+			*v++ = 0;
 		NTFS_GETOPT("uid", uid)
 		else NTFS_GETOPT("gid", gid)
 		else NTFS_GETOPT("umask", fmask = dmask)
@@ -316,11 +318,11 @@ static int ntfs_write_volume_flags(ntfs_volume *vol, const VOLUME_FLAGS flags)
 	ntfs_inode *ni = NTFS_I(vol->vol_ino);
 	MFT_RECORD *m;
 	VOLUME_INFORMATION *vi;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 	int err;
 
 	ntfs_debug("Entering, old flags = 0x%x, new flags = 0x%x.",
-			vol->vol_flags, flags);
+			le16_to_cpu(vol->vol_flags), le16_to_cpu(flags));
 	if (vol->vol_flags == flags)
 		goto done;
 	BUG_ON(!ni);
@@ -329,28 +331,28 @@ static int ntfs_write_volume_flags(ntfs_volume *vol, const VOLUME_FLAGS flags)
 		err = PTR_ERR(m);
 		goto err_out;
 	}
-	ctx = get_attr_search_ctx(ni, m);
+	ctx = ntfs_attr_get_search_ctx(ni, m);
 	if (!ctx) {
 		err = -ENOMEM;
 		goto put_unm_err_out;
 	}
-	if (!lookup_attr(AT_VOLUME_INFORMATION, NULL, 0, 0, 0, NULL, 0, ctx)) {
-		err = -EIO;
+	err = ntfs_attr_lookup(AT_VOLUME_INFORMATION, NULL, 0, 0, 0, NULL, 0,
+			ctx);
+	if (err)
 		goto put_unm_err_out;
-	}
 	vi = (VOLUME_INFORMATION*)((u8*)ctx->attr +
 			le16_to_cpu(ctx->attr->data.resident.value_offset));
 	vol->vol_flags = vi->flags = flags;
 	flush_dcache_mft_record_page(ctx->ntfs_ino);
 	mark_mft_record_dirty(ctx->ntfs_ino);
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(ni);
 done:
 	ntfs_debug("Done.");
 	return 0;
 put_unm_err_out:
 	if (ctx)
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(ni);
 err_out:
 	ntfs_error(vol->sb, "Failed with error code %i.", -err);
@@ -384,7 +386,8 @@ static inline int ntfs_set_volume_flags(ntfs_volume *vol, VOLUME_FLAGS flags)
 static inline int ntfs_clear_volume_flags(ntfs_volume *vol, VOLUME_FLAGS flags)
 {
 	flags &= VOLUME_FLAGS_MASK;
-	return ntfs_write_volume_flags(vol, vol->vol_flags & ~flags);
+	flags = vol->vol_flags & cpu_to_le16(~le16_to_cpu(flags));
+	return ntfs_write_volume_flags(vol, flags);
 }
 
 #endif /* NTFS_RW */
@@ -409,7 +412,7 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
 #ifndef NTFS_RW
 	/* For read-only compiled driver, enforce all read-only flags. */
 	*flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
-#else /* ! NTFS_RW */
+#else /* NTFS_RW */
 	/*
 	 * For the read-write compiled driver, if we are remounting read-write,
 	 * make sure there are no volume errors and that no unsupported volume
@@ -479,28 +482,7 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
 						"flags.  Run chkdsk.");
 		}
 	}
-	// TODO:  For now we enforce no atime and dir atime updates as they are
-	// not implemented.
-	if ((sb->s_flags & MS_NOATIME) && !(*flags & MS_NOATIME))
-		ntfs_warning(sb, "Atime updates are not implemented yet.  "
-				"Leaving them disabled.");
-	else if ((sb->s_flags & MS_NODIRATIME) && !(*flags & MS_NODIRATIME))
-		ntfs_warning(sb, "Directory atime updates are not implemented "
-				"yet.  Leaving them disabled.");
-	*flags |= MS_NOATIME | MS_NODIRATIME;
-#endif /* ! NTFS_RW */
-
-	// FIXME/TODO: If left like this we will have problems with rw->ro and
-	// ro->rw, as well as with sync->async and vice versa remounts.
-	// Note: The VFS already checks that there are no pending deletes and
-	// no open files for writing. So we only need to worry about dirty
-	// inode pages and dirty system files (which include dirty inodes).
-	// Either handle by flushing the whole volume NOW or by having the
-	// write routines work on MS_RDONLY fs and guarantee we don't mark
-	// anything as dirty if MS_RDONLY is set. That way the dirty data
-	// would get flushed but no new dirty data would appear. This is
-	// probably best but we need to be careful not to mark anything dirty
-	// or the MS_RDONLY will be leaking writes.
+#endif /* NTFS_RW */
 
 	// TODO: Deal with *flags.
 
@@ -530,8 +512,10 @@ static BOOL is_boot_sector_ntfs(const struct super_block *sb,
 	 * field. If checksum is zero, no checking is done.
 	 */
 	if ((void*)b < (void*)&b->checksum && b->checksum) {
-		u32 i, *u;
-		for (i = 0, u = (u32*)b; u < (u32*)(&b->checksum); ++u)
+		le32 *u;
+		u32 i;
+
+		for (i = 0, u = (le32*)b; u < (le32*)(&b->checksum); ++u)
 			i += le32_to_cpup(u);
 		if (le32_to_cpu(b->checksum) != i)
 			goto not_ntfs;
@@ -540,7 +524,7 @@ static BOOL is_boot_sector_ntfs(const struct super_block *sb,
 	if (b->oem_id != magicNTFS)
 		goto not_ntfs;
 	/* Check bytes per sector value is between 256 and 4096. */
-	if (le16_to_cpu(b->bpb.bytes_per_sector) <  0x100 ||
+	if (le16_to_cpu(b->bpb.bytes_per_sector) < 0x100 ||
 			le16_to_cpu(b->bpb.bytes_per_sector) > 0x1000)
 		goto not_ntfs;
 	/* Check sectors per cluster value is valid. */
@@ -839,37 +823,86 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b)
 	vol->serial_no = le64_to_cpu(b->volume_serial_number);
 	ntfs_debug("vol->serial_no = 0x%llx",
 			(unsigned long long)vol->serial_no);
-	/*
-	 * Determine MFT zone size. This is not strictly the right place to do
-	 * this, but I am too lazy to create a function especially for it...
-	 */
-	vol->mft_zone_end = vol->nr_clusters;
+	return TRUE;
+}
+
+/**
+ * setup_lcn_allocator - initialize the cluster allocator
+ * @vol:	volume structure for which to setup the lcn allocator
+ *
+ * Setup the cluster (lcn) allocator to the starting values.
+ */
+static void setup_lcn_allocator(ntfs_volume *vol)
+{
+#ifdef NTFS_RW
+	LCN mft_zone_size, mft_lcn;
+#endif /* NTFS_RW */
+
+	ntfs_debug("vol->mft_zone_multiplier = 0x%x",
+			vol->mft_zone_multiplier);
+#ifdef NTFS_RW
+	/* Determine the size of the MFT zone. */
+	mft_zone_size = vol->nr_clusters;
 	switch (vol->mft_zone_multiplier) {  /* % of volume size in clusters */
 	case 4:
-		vol->mft_zone_end = vol->mft_zone_end >> 1;	/* 50%   */
+		mft_zone_size >>= 1;			/* 50%   */
 		break;
 	case 3:
-		vol->mft_zone_end = (vol->mft_zone_end +
-				(vol->mft_zone_end >> 1)) >> 2;	/* 37.5% */
+		mft_zone_size = (mft_zone_size +
+				(mft_zone_size >> 1)) >> 2;	/* 37.5% */
 		break;
 	case 2:
-		vol->mft_zone_end = vol->mft_zone_end >> 2;	/* 25%   */
+		mft_zone_size >>= 2;			/* 25%   */
 		break;
+	/* case 1: */
 	default:
-		vol->mft_zone_multiplier = 1;
-		/* Fall through into case 1. */
-	case 1:
-		vol->mft_zone_end = vol->mft_zone_end >> 3;	/* 12.5% */
+		mft_zone_size >>= 3;			/* 12.5% */
 		break;
 	}
-	ntfs_debug("vol->mft_zone_multiplier = 0x%x",
-			vol->mft_zone_multiplier);
-	vol->mft_zone_start = vol->mft_lcn;
-	vol->mft_zone_end += vol->mft_lcn;
+	/* Setup the mft zone. */
+	vol->mft_zone_start = vol->mft_zone_pos = vol->mft_lcn;
+	ntfs_debug("vol->mft_zone_pos = 0x%llx",
+			(unsigned long long)vol->mft_zone_pos);
+	/*
+	 * Calculate the mft_lcn for an unmodified NTFS volume (see mkntfs
+	 * source) and if the actual mft_lcn is in the expected place or even
+	 * further to the front of the volume, extend the mft_zone to cover the
+	 * beginning of the volume as well.  This is in order to protect the
+	 * area reserved for the mft bitmap as well within the mft_zone itself.
+	 * On non-standard volumes we do not protect it as the overhead would
+	 * be higher than the speed increase we would get by doing it.
+	 */
+	mft_lcn = (8192 + 2 * vol->cluster_size - 1) / vol->cluster_size;
+	if (mft_lcn * vol->cluster_size < 16 * 1024)
+		mft_lcn = (16 * 1024 + vol->cluster_size - 1) /
+				vol->cluster_size;
+	if (vol->mft_zone_start <= mft_lcn)
+		vol->mft_zone_start = 0;
 	ntfs_debug("vol->mft_zone_start = 0x%llx",
-			(long long)vol->mft_zone_start);
-	ntfs_debug("vol->mft_zone_end = 0x%llx", (long long)vol->mft_zone_end);
-	return TRUE;
+			(unsigned long long)vol->mft_zone_start);
+	/*
+	 * Need to cap the mft zone on non-standard volumes so that it does
+	 * not point outside the boundaries of the volume.  We do this by
+	 * halving the zone size until we are inside the volume.
+	 */
+	vol->mft_zone_end = vol->mft_lcn + mft_zone_size;
+	while (vol->mft_zone_end >= vol->nr_clusters) {
+		mft_zone_size >>= 1;
+		vol->mft_zone_end = vol->mft_lcn + mft_zone_size;
+	}
+	ntfs_debug("vol->mft_zone_end = 0x%llx",
+			(unsigned long long)vol->mft_zone_end);
+	/*
+	 * Set the current position within each data zone to the start of the
+	 * respective zone.
+	 */
+	vol->data1_zone_pos = vol->mft_zone_end;
+	ntfs_debug("vol->data1_zone_pos = 0x%llx",
+			(unsigned long long)vol->data1_zone_pos);
+	vol->data2_zone_pos = 0;
+	ntfs_debug("vol->data2_zone_pos = 0x%llx",
+			(unsigned long long)vol->data2_zone_pos);
+#endif /* NTFS_RW */
 }
 
 #ifdef NTFS_RW
@@ -934,7 +967,7 @@ static BOOL check_mft_mirror(ntfs_volume *vol)
 	ntfs_inode *mirr_ni;
 	struct page *mft_page, *mirr_page;
 	u8 *kmft, *kmirr;
-	run_list_element *rl, rl2[2];
+	runlist_element *rl, rl2[2];
 	int mrecs_per_page, i;
 
 	ntfs_debug("Entering.");
@@ -973,7 +1006,7 @@ static BOOL check_mft_mirror(ntfs_volume *vol)
 			++index;
 		}
 		/* Make sure the record is ok. */
-		if (ntfs_is_baad_recordp(kmft)) {
+		if (ntfs_is_baad_recordp((le32*)kmft)) {
 			ntfs_error(sb, "Incomplete multi sector transfer "
 					"detected in mft record %i.", i);
 mm_unmap_out:
@@ -982,7 +1015,7 @@ mft_unmap_out:
 			ntfs_unmap_page(mft_page);
 			return FALSE;
 		}
-		if (ntfs_is_baad_recordp(kmirr)) {
+		if (ntfs_is_baad_recordp((le32*)kmirr)) {
 			ntfs_error(sb, "Incomplete multi sector transfer "
 					"detected in mft mirror record %i.", i);
 			goto mm_unmap_out;
@@ -1007,7 +1040,7 @@ mft_unmap_out:
 	ntfs_unmap_page(mft_page);
 	ntfs_unmap_page(mirr_page);
 
-	/* Construct the mft mirror run list by hand. */
+	/* Construct the mft mirror runlist by hand. */
 	rl2[0].vcn = 0;
 	rl2[0].lcn = vol->mftmirr_lcn;
 	rl2[0].length = (vol->mftmirr_size * vol->mft_record_size +
@@ -1017,23 +1050,23 @@ mft_unmap_out:
 	rl2[1].length = 0;
 	/*
 	 * Because we have just read all of the mft mirror, we know we have
-	 * mapped the full run list for it.
+	 * mapped the full runlist for it.
 	 */
 	mirr_ni = NTFS_I(vol->mftmirr_ino);
-	down_read(&mirr_ni->run_list.lock);
-	rl = mirr_ni->run_list.rl;
-	/* Compare the two run lists.  They must be identical. */
+	down_read(&mirr_ni->runlist.lock);
+	rl = mirr_ni->runlist.rl;
+	/* Compare the two runlists.  They must be identical. */
 	i = 0;
 	do {
 		if (rl2[i].vcn != rl[i].vcn || rl2[i].lcn != rl[i].lcn ||
 				rl2[i].length != rl[i].length) {
 			ntfs_error(sb, "$MFTMirr location mismatch.  "
 					"Run chkdsk.");
-			up_read(&mirr_ni->run_list.lock);
+			up_read(&mirr_ni->runlist.lock);
 			return FALSE;
 		}
 	} while (rl2[i++].length);
-	up_read(&mirr_ni->run_list.lock);
+	up_read(&mirr_ni->runlist.lock);
 	ntfs_debug("Done.");
 	return TRUE;
 }
@@ -1081,9 +1114,9 @@ static BOOL load_and_init_quota(ntfs_volume *vol)
 	static const ntfschar Quota[7] = { const_cpu_to_le16('$'),
 			const_cpu_to_le16('Q'), const_cpu_to_le16('u'),
 			const_cpu_to_le16('o'), const_cpu_to_le16('t'),
-			const_cpu_to_le16('a'), const_cpu_to_le16(0) };
+			const_cpu_to_le16('a'), 0 };
 	static ntfschar Q[3] = { const_cpu_to_le16('$'),
-			const_cpu_to_le16('Q'), const_cpu_to_le16(0) };
+			const_cpu_to_le16('Q'), 0 };
 
 	ntfs_debug("Entering.");
 	/*
@@ -1136,6 +1169,66 @@ static BOOL load_and_init_quota(ntfs_volume *vol)
 	return TRUE;
 }
 
+/**
+ * load_and_init_attrdef - load the attribute definitions table for a volume
+ * @vol:	ntfs super block describing device whose attrdef to load
+ *
+ * Return TRUE on success or FALSE on error.
+ */
+static BOOL load_and_init_attrdef(ntfs_volume *vol)
+{
+	struct super_block *sb = vol->sb;
+	struct inode *ino;
+	struct page *page;
+	unsigned long index, max_index;
+	unsigned int size;
+
+	ntfs_debug("Entering.");
+	/* Read attrdef table and setup vol->attrdef and vol->attrdef_size. */
+	ino = ntfs_iget(sb, FILE_AttrDef);
+	if (IS_ERR(ino) || is_bad_inode(ino)) {
+		if (!IS_ERR(ino))
+			iput(ino);
+		goto failed;
+	}
+	/* The size of FILE_AttrDef must be above 0 and fit inside 31 bits. */
+	if (!ino->i_size || ino->i_size > 0x7fffffff)
+		goto iput_failed;
+	vol->attrdef = (ATTR_DEF*)ntfs_malloc_nofs(ino->i_size);
+	if (!vol->attrdef)
+		goto iput_failed;
+	index = 0;
+	max_index = ino->i_size >> PAGE_CACHE_SHIFT;
+	size = PAGE_CACHE_SIZE;
+	while (index < max_index) {
+		/* Read the attrdef table and copy it into the linear buffer. */
+read_partial_attrdef_page:
+		page = ntfs_map_page(ino->i_mapping, index);
+		if (IS_ERR(page))
+			goto free_iput_failed;
+		memcpy((u8*)vol->attrdef + (index++ << PAGE_CACHE_SHIFT),
+				page_address(page), size);
+		ntfs_unmap_page(page);
+	};
+	if (size == PAGE_CACHE_SIZE) {
+		size = ino->i_size & ~PAGE_CACHE_MASK;
+		if (size)
+			goto read_partial_attrdef_page;
+	}
+	vol->attrdef_size = ino->i_size;
+	ntfs_debug("Read %llu bytes from $AttrDef.", ino->i_size);
+	iput(ino);
+	return TRUE;
+free_iput_failed:
+	ntfs_free(vol->attrdef);
+	vol->attrdef = NULL;
+iput_failed:
+	iput(ino);
+failed:
+	ntfs_error(sb, "Failed to initialize attribute definition table.");
+	return FALSE;
+}
+
 #endif /* NTFS_RW */
 
 /**
@@ -1236,7 +1329,7 @@ upcase_failed:
 		return TRUE;
 	}
 	up(&ntfs_lock);
-	ntfs_error(sb, "Failed to initialized upcase table.");
+	ntfs_error(sb, "Failed to initialize upcase table.");
 	return FALSE;
 }
 
@@ -1252,10 +1345,9 @@ upcase_failed:
 static BOOL load_system_files(ntfs_volume *vol)
 {
 	struct super_block *sb = vol->sb;
-	struct inode *tmp_ino;
 	MFT_RECORD *m;
 	VOLUME_INFORMATION *vi;
-	attr_search_context *ctx;
+	ntfs_attr_search_ctx *ctx;
 
 	ntfs_debug("Entering.");
 #ifdef NTFS_RW
@@ -1296,6 +1388,14 @@ static BOOL load_system_files(ntfs_volume *vol)
 	/* Read upcase table and setup @vol->upcase and @vol->upcase_len. */
 	if (!load_and_init_upcase(vol))
 		goto iput_mftbmp_err_out;
+#ifdef NTFS_RW
+	/*
+	 * Read attribute definitions table and setup @vol->attrdef and
+	 * @vol->attrdef_size.
+	 */
+	if (!load_and_init_attrdef(vol))
+		goto iput_upcase_err_out;
+#endif /* NTFS_RW */
 	/*
 	 * Get the cluster allocation bitmap inode and verify the size, no
 	 * need for any locking at this stage as we are already running
@@ -1311,7 +1411,7 @@ static BOOL load_system_files(ntfs_volume *vol)
 		iput(vol->lcnbmp_ino);
 bitmap_failed:
 		ntfs_error(sb, "Failed to load $Bitmap.");
-		goto iput_mirr_err_out;
+		goto iput_attrdef_err_out;
 	}
 	/*
 	 * Get the volume inode and setup our cache of the volume flags and
@@ -1331,14 +1431,14 @@ iput_volume_failed:
 		iput(vol->vol_ino);
 		goto volume_failed;
 	}
-	if (!(ctx = get_attr_search_ctx(NTFS_I(vol->vol_ino), m))) {
+	if (!(ctx = ntfs_attr_get_search_ctx(NTFS_I(vol->vol_ino), m))) {
 		ntfs_error(sb, "Failed to get attribute search context.");
 		goto get_ctx_vol_failed;
 	}
-	if (!lookup_attr(AT_VOLUME_INFORMATION, NULL, 0, 0, 0, NULL, 0, ctx) ||
-			ctx->attr->non_resident || ctx->attr->flags) {
+	if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, NULL, 0, 0, 0, NULL, 0,
+			ctx) || ctx->attr->non_resident || ctx->attr->flags) {
 err_put_vol:
-		put_attr_search_ctx(ctx);
+		ntfs_attr_put_search_ctx(ctx);
 get_ctx_vol_failed:
 		unmap_mft_record(NTFS_I(vol->vol_ino));
 		goto iput_volume_failed;
@@ -1354,7 +1454,7 @@ get_ctx_vol_failed:
 	vol->vol_flags = vi->flags;
 	vol->major_ver = vi->major_ver;
 	vol->minor_ver = vi->minor_ver;
-	put_attr_search_ctx(ctx);
+	ntfs_attr_put_search_ctx(ctx);
 	unmap_mft_record(NTFS_I(vol->vol_ino));
 	printk(KERN_INFO "NTFS volume version %i.%i.\n", vol->major_ver,
 			vol->minor_ver);
@@ -1483,19 +1583,6 @@ get_ctx_vol_failed:
 		NVolSetErrors(vol);
 	}
 #endif /* NTFS_RW */
-	/*
-	 * Get the inode for the attribute definitions file and parse the
-	 * attribute definitions.
-	 */
-	tmp_ino = ntfs_iget(sb, FILE_AttrDef);
-	if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) {
-		if (!IS_ERR(tmp_ino))
-			iput(tmp_ino);
-		ntfs_error(sb, "Failed to load $AttrDef.");
-		goto iput_logfile_err_out;
-	}
-	// FIXME: Parse the attribute definitions.
-	iput(tmp_ino);
 	/* Get the root directory inode. */
 	vol->root_ino = ntfs_iget(sb, FILE_root);
 	if (IS_ERR(vol->root_ino) || is_bad_inode(vol->root_ino)) {
@@ -1591,6 +1678,26 @@ iput_vol_err_out:
 	iput(vol->vol_ino);
 iput_lcnbmp_err_out:
 	iput(vol->lcnbmp_ino);
+iput_attrdef_err_out:
+	vol->attrdef_size = 0;
+	if (vol->attrdef) {
+		ntfs_free(vol->attrdef);
+		vol->attrdef = NULL;
+	}
+#ifdef NTFS_RW
+iput_upcase_err_out:
+#endif /* NTFS_RW */
+	vol->upcase_len = 0;
+	down(&ntfs_lock);
+	if (vol->upcase == default_upcase) {
+		ntfs_nr_upcase_users--;
+		vol->upcase = NULL;
+	}
+	up(&ntfs_lock);
+	if (vol->upcase) {
+		ntfs_free(vol->upcase);
+		vol->upcase = NULL;
+	}
 iput_mftbmp_err_out:
 	iput(vol->mftbmp_ino);
 iput_mirr_err_out:
@@ -1762,14 +1869,18 @@ static void ntfs_put_super(struct super_block *sb)
 	iput(vol->mft_ino);
 	vol->mft_ino = NULL;
 
+	/* Throw away the table of attribute definitions. */
+	vol->attrdef_size = 0;
+	if (vol->attrdef) {
+		ntfs_free(vol->attrdef);
+		vol->attrdef = NULL;
+	}
 	vol->upcase_len = 0;
 	/*
-	 * Decrease the number of mounts and destroy the global default upcase
-	 * table if necessary.  Also decrease the number of upcase users if we
-	 * are a user.
+	 * Destroy the global default upcase table if necessary.  Also decrease
+	 * the number of upcase users if we are a user.
 	 */
 	down(&ntfs_lock);
-	ntfs_nr_mounts--;
 	if (vol->upcase == default_upcase) {
 		ntfs_nr_upcase_users--;
 		vol->upcase = NULL;
@@ -1906,7 +2017,7 @@ static s64 get_nr_free_clusters(ntfs_volume *vol)
  */
 static unsigned long __get_nr_free_mft_records(ntfs_volume *vol)
 {
-	s64 nr_free = vol->nr_mft_records;
+	s64 nr_free;
 	u32 *kaddr;
 	struct address_space *mapping = vol->mftbmp_ino->i_mapping;
 	filler_t *readpage = (filler_t*)mapping->a_ops->readpage;
@@ -1915,13 +2026,16 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol)
 	unsigned int max_size;
 
 	ntfs_debug("Entering.");
+	/* Number of mft records in file system (at this point in time). */
+	nr_free = vol->mft_ino->i_size >> vol->mft_record_size_bits;
 	/*
-	 * Convert the number of bits into bytes rounded up, then convert into
-	 * multiples of PAGE_CACHE_SIZE, rounding up so that if we have one
-	 * full and one partial page max_index = 2.
+	 * Convert the maximum number of set bits into bytes rounded up, then
+	 * convert into multiples of PAGE_CACHE_SIZE, rounding up so that if we
+	 * have one full and one partial page max_index = 2.
 	 */
-	max_index = (((vol->nr_mft_records + 7) >> 3) + PAGE_CACHE_SIZE - 1) >>
-			PAGE_CACHE_SHIFT;
+	max_index = ((((NTFS_I(vol->mft_ino)->initialized_size >>
+			vol->mft_record_size_bits) + 7) >> 3) +
+			PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 	/* Use multiples of 4 bytes. */
 	max_size = PAGE_CACHE_SIZE >> 2;
 	ntfs_debug("Reading $MFT/$BITMAP, max_index = 0x%lx, max_size = "
@@ -2016,9 +2130,9 @@ static int ntfs_statfs(struct super_block *sb, struct kstatfs *sfs)
 	sfs->f_bavail = sfs->f_bfree = size;
 	/* Serialize accesses to the inode bitmap. */
 	down_read(&vol->mftbmp_lock);
-	/* Total file nodes in file system (at this moment in time). */
-	sfs->f_files  = vol->mft_ino->i_size >> vol->mft_record_size_bits;
-	/* Free file nodes in fs (based on current total count). */
+	/* Number of inodes in file system (at this point in time). */
+	sfs->f_files = vol->mft_ino->i_size >> vol->mft_record_size_bits;
+	/* Free inodes in fs (based on current total count). */
 	sfs->f_ffree = __get_nr_free_mft_records(vol);
 	up_read(&vol->mftbmp_lock);
 	/*
@@ -2139,15 +2253,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
 	ntfs_debug("Entering.");
 #ifndef NTFS_RW
 	sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
-#else
-	if (!(sb->s_flags & MS_NOATIME))
-		ntfs_warning(sb, "Atime updates are not implemented yet.  "
-				"Disabling them.");
-	else if (!(sb->s_flags & MS_NODIRATIME))
-		ntfs_warning(sb, "Directory atime updates are not implemented "
-				"yet.  Disabling them.");
-	sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
-#endif
+#endif /* ! NTFS_RW */
 	/* Allocate a new ntfs_volume and place it in sb->s_fs_info. */
 	sb->s_fs_info = kmalloc(sizeof(ntfs_volume), GFP_NOFS);
 	vol = NTFS_SB(sb);
@@ -2161,6 +2267,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
 	memset(vol, 0, sizeof(ntfs_volume));
 	vol->sb = sb;
 	vol->upcase = NULL;
+	vol->attrdef = NULL;
 	vol->mft_ino = NULL;
 	vol->mftbmp_ino = NULL;
 	init_rwsem(&vol->mftbmp_lock);
@@ -2188,6 +2295,8 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
 	vol->fmask = 0177;
 	vol->dmask = 0077;
 
+	unlock_kernel();
+
 	/* Important to get the mount options dealt with now. */
 	if (!parse_options(vol, (char*)opt))
 		goto err_out_now;
@@ -2225,6 +2334,9 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
 	 */
 	result = parse_ntfs_boot_sector(vol, (NTFS_BOOT_SECTOR*)bh->b_data);
 
+	/* Initialize the cluster allocator. */
+	setup_lcn_allocator(vol);
+
 	brelse(bh);
 
 	if (!result) {
@@ -2289,14 +2401,13 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
 		}
 	}
 	/*
-	 * Increment the number of mounts and generate the global default
-	 * upcase table if necessary. Also temporarily increment the number of
-	 * upcase users to avoid race conditions with concurrent (u)mounts.
+	 * Generate the global default upcase table if necessary.  Also
+	 * temporarily increment the number of upcase users to avoid race
+	 * conditions with concurrent (u)mounts.
 	 */
-	if (!ntfs_nr_mounts++)
+	if (!default_upcase)
 		default_upcase = generate_default_upcase();
 	ntfs_nr_upcase_users++;
-
 	up(&ntfs_lock);
 	/*
 	 * From now on, ignore @silent parameter. If we fail below this line,
@@ -2322,6 +2433,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
 		}
 		up(&ntfs_lock);
 		sb->s_export_op = &ntfs_export_ops;
+		lock_kernel();
 		return 0;
 	}
 	ntfs_error(sb, "Failed to allocate root directory.");
@@ -2368,10 +2480,23 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
 		vol->mftmirr_ino = NULL;
 	}
 #endif /* NTFS_RW */
+	/* Throw away the table of attribute definitions. */
+	vol->attrdef_size = 0;
+	if (vol->attrdef) {
+		ntfs_free(vol->attrdef);
+		vol->attrdef = NULL;
+	}
 	vol->upcase_len = 0;
-	if (vol->upcase != default_upcase)
+	down(&ntfs_lock);
+	if (vol->upcase == default_upcase) {
+		ntfs_nr_upcase_users--;
+		vol->upcase = NULL;
+	}
+	up(&ntfs_lock);
+	if (vol->upcase) {
 		ntfs_free(vol->upcase);
-	vol->upcase = NULL;
+		vol->upcase = NULL;
+	}
 	if (vol->nls_map) {
 		unload_nls(vol->nls_map);
 		vol->nls_map = NULL;
@@ -2379,11 +2504,10 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
 	/* Error exit code path. */
 unl_upcase_iput_tmp_ino_err_out_now:
 	/*
-	 * Decrease the number of mounts and destroy the global default upcase
-	 * table if necessary.
+	 * Decrease the number of upcase users and destroy the global default
+	 * upcase table if necessary.
 	 */
 	down(&ntfs_lock);
-	ntfs_nr_mounts--;
 	if (!--ntfs_nr_upcase_users && default_upcase) {
 		ntfs_free(default_upcase);
 		default_upcase = NULL;
@@ -2413,6 +2537,7 @@ iput_tmp_ino_err_out_now:
 	}
 	/* Errors at this stage are irrelevant. */
 err_out_now:
+	lock_kernel();
 	sb->s_fs_info = NULL;
 	kfree(vol);
 	ntfs_debug("Failed, returning -EINVAL.");
@@ -2449,12 +2574,9 @@ kmem_cache_t *ntfs_attr_ctx_cache;
 kmem_cache_t *ntfs_index_ctx_cache;
 
 /* A global default upcase table and a corresponding reference count. */
-wchar_t *default_upcase = NULL;
+ntfschar *default_upcase = NULL;
 unsigned long ntfs_nr_upcase_users = 0;
 
-/* The number of mounted filesystems. */
-unsigned long ntfs_nr_mounts = 0;
-
 /* Driver wide semaphore. */
 DECLARE_MUTEX(ntfs_lock);
 
@@ -2509,7 +2631,7 @@ static int __init init_ntfs_fs(void)
 		goto ictx_err_out;
 	}
 	ntfs_attr_ctx_cache = kmem_cache_create(ntfs_attr_ctx_cache_name,
-			sizeof(attr_search_context), 0 /* offset */,
+			sizeof(ntfs_attr_search_ctx), 0 /* offset */,
 			SLAB_HWCACHE_ALIGN, NULL /* ctor */, NULL /* dtor */);
 	if (!ntfs_attr_ctx_cache) {
 		printk(KERN_CRIT "NTFS: Failed to create %s!\n",
@@ -2528,7 +2650,7 @@ static int __init init_ntfs_fs(void)
 
 	ntfs_inode_cache = kmem_cache_create(ntfs_inode_cache_name,
 			sizeof(ntfs_inode), 0,
-			SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, NULL, NULL);
+			SLAB_RECLAIM_ACCOUNT, NULL, NULL);
 	if (!ntfs_inode_cache) {
 		printk(KERN_CRIT "NTFS: Failed to create %s!\n",
 				ntfs_inode_cache_name);
@@ -2614,7 +2736,7 @@ MODULE_AUTHOR("Anton Altaparmakov <aia21@cantab.net>");
 MODULE_DESCRIPTION("NTFS 1.2/3.x driver - Copyright (c) 2001-2004 Anton Altaparmakov");
 MODULE_LICENSE("GPL");
 #ifdef DEBUG
-MODULE_PARM(debug_msgs, "i");
+module_param(debug_msgs, bool, 0);
 MODULE_PARM_DESC(debug_msgs, "Enable debug messages.");
 #endif
 
diff --git a/fs/ntfs/time.h b/fs/ntfs/time.h
index b0a7dbafc..a09a51dab 100644
--- a/fs/ntfs/time.h
+++ b/fs/ntfs/time.h
@@ -45,7 +45,7 @@
  * measured as the number of 100-nano-second intervals since 1st January 1601,
  * 00:00:00 UTC.
  */
-static inline s64 utc2ntfs(const struct timespec ts)
+static inline sle64 utc2ntfs(const struct timespec ts)
 {
 	/*
 	 * Convert the seconds to 100ns intervals, add the nano-seconds
@@ -61,7 +61,7 @@ static inline s64 utc2ntfs(const struct timespec ts)
  * Get the current time from the Linux kernel, convert it to its corresponding
  * NTFS time and return that in little endian format.
  */
-static inline s64 get_current_ntfs_time(void)
+static inline sle64 get_current_ntfs_time(void)
 {
 	return utc2ntfs(current_kernel_time());
 }
@@ -82,7 +82,7 @@ static inline s64 get_current_ntfs_time(void)
  * measured as the number of 100 nano-second intervals since 1st January 1601,
  * 00:00:00 UTC.
  */
-static inline struct timespec ntfs2utc(const s64 time)
+static inline struct timespec ntfs2utc(const sle64 time)
 {
 	struct timespec ts;
 
diff --git a/fs/ntfs/types.h b/fs/ntfs/types.h
index a33fc637f..a98731ece 100644
--- a/fs/ntfs/types.h
+++ b/fs/ntfs/types.h
@@ -23,8 +23,17 @@
 #ifndef _LINUX_NTFS_TYPES_H
 #define _LINUX_NTFS_TYPES_H
 
+#include <linux/types.h>
+
+typedef __le16 le16;
+typedef __le32 le32;
+typedef __le64 le64;
+typedef __u16 __bitwise sle16;
+typedef __u32 __bitwise sle32;
+typedef __u64 __bitwise sle64;
+
 /* 2-byte Unicode character type. */
-typedef u16 ntfschar;
+typedef le16 ntfschar;
 #define UCHAR_T_SIZE_BITS 1
 
 /*
@@ -32,7 +41,9 @@ typedef u16 ntfschar;
  * and VCN, to allow for type checking and better code readability.
  */
 typedef s64 VCN;
+typedef sle64 leVCN;
 typedef s64 LCN;
+typedef sle64 leLCN;
 
 /*
  * The NTFS journal $LogFile uses log sequence numbers which are signed 64-bit
@@ -40,9 +51,10 @@ typedef s64 LCN;
  * code readability.
  */
 typedef s64 LSN;
+typedef sle64 leLSN;
 
 /**
- * run_list_element - in memory vcn to lcn mapping array element
+ * runlist_element - in memory vcn to lcn mapping array element
  * @vcn:	starting vcn of the current array element
  * @lcn:	starting lcn of the current array element
  * @length:	length in clusters of the current array element
@@ -56,18 +68,18 @@ typedef struct {	/* In memory vcn to lcn mapping structure element. */
 	VCN vcn;	/* vcn = Starting virtual cluster number. */
 	LCN lcn;	/* lcn = Starting logical cluster number. */
 	s64 length;	/* Run length in clusters. */
-} run_list_element;
+} runlist_element;
 
 /**
- * run_list - in memory vcn to lcn mapping array including a read/write lock
- * @rl:		pointer to an array of run list elements
+ * runlist - in memory vcn to lcn mapping array including a read/write lock
+ * @rl:		pointer to an array of runlist elements
  * @lock:	read/write spinlock for serializing access to @rl
  *
  */
 typedef struct {
-	run_list_element *rl;
+	runlist_element *rl;
 	struct rw_semaphore lock;
-} run_list;
+} runlist;
 
 typedef enum {
 	FALSE = 0,
diff --git a/fs/ntfs/unistr.c b/fs/ntfs/unistr.c
index 507f836f9..ec7405a80 100644
--- a/fs/ntfs/unistr.c
+++ b/fs/ntfs/unistr.c
@@ -96,7 +96,7 @@ int ntfs_collate_names(const ntfschar *name1, const u32 name1_len,
 		const ntfschar *upcase, const u32 upcase_len)
 {
 	u32 cnt, min_len;
-	ntfschar c1, c2;
+	u16 c1, c2;
 
 	min_len = name1_len;
 	if (name1_len > name2_len)
@@ -144,7 +144,7 @@ int ntfs_collate_names(const ntfschar *name1, const u32 name1_len,
  */
 int ntfs_ucsncmp(const ntfschar *s1, const ntfschar *s2, size_t n)
 {
-	ntfschar c1, c2;
+	u16 c1, c2;
 	size_t i;
 
 	for (i = 0; i < n; ++i) {
@@ -181,8 +181,8 @@ int ntfs_ucsncmp(const ntfschar *s1, const ntfschar *s2, size_t n)
 int ntfs_ucsncasecmp(const ntfschar *s1, const ntfschar *s2, size_t n,
 		const ntfschar *upcase, const u32 upcase_size)
 {
-	ntfschar c1, c2;
 	size_t i;
+	u16 c1, c2;
 
 	for (i = 0; i < n; ++i) {
 		if ((c1 = le16_to_cpu(s1[i])) < upcase_size)
@@ -203,7 +203,7 @@ void ntfs_upcase_name(ntfschar *name, u32 name_len, const ntfschar *upcase,
 		const u32 upcase_len)
 {
 	u32 i;
-	ntfschar u;
+	u16 u;
 
 	for (i = 0; i < name_len; i++)
 		if ((u = le16_to_cpu(name[i])) < upcase_len)
@@ -276,7 +276,7 @@ int ntfs_nlstoucs(const ntfs_volume *vol, const char *ins,
 				} /* else (wc_len < 0) */
 				goto conversion_err;
 			}
-			ucs[o] = cpu_to_le16('\0');
+			ucs[o] = 0;
 			*outs = ucs;
 			return o;
 		} /* else (!ucs) */
@@ -362,7 +362,7 @@ retry:			wc = nls->uni2char(le16_to_cpu(ins[i]), ns + o,
 			} /* wc < 0, real error. */
 			goto conversion_err;
 		}
-		ns[o] = '\0';
+		ns[o] = 0;
 		*outs = ns;
 		return o;
 	} /* else (!ins) */
diff --git a/fs/ntfs/upcase.c b/fs/ntfs/upcase.c
index 5481f2de8..276ed9798 100644
--- a/fs/ntfs/upcase.c
+++ b/fs/ntfs/upcase.c
@@ -3,7 +3,7 @@
  *	      Part of the Linux-NTFS project.
  *
  * Copyright (c) 2001 Richard Russon <ntfs@flatcap.org>
- * Copyright (c) 2001-2003 Anton Altaparmakov
+ * Copyright (c) 2001-2004 Anton Altaparmakov
  *
  * Modified for mkntfs inclusion 9 June 2001 by Anton Altaparmakov.
  * Modified for kernel inclusion 10 September 2001 by Anton Altparmakov.
@@ -87,4 +87,3 @@ ntfschar *generate_default_upcase(void)
 		uc[uc_word_table[r][0]] = cpu_to_le16(uc_word_table[r][1]);
 	return uc;
 }
-
diff --git a/fs/ntfs/volume.h b/fs/ntfs/volume.h
index 330c3a229..9775fa658 100644
--- a/fs/ntfs/volume.h
+++ b/fs/ntfs/volume.h
@@ -73,16 +73,28 @@ typedef struct {
 	/* Mount specific NTFS information. */
 	u32 upcase_len;			/* Number of entries in upcase[]. */
 	ntfschar *upcase;		/* The upcase table. */
+
+	s32 attrdef_size;		/* Size of the attribute definition
+					   table in bytes. */
+	ATTR_DEF *attrdef;		/* Table of attribute definitions.
+					   Obtained from FILE_AttrDef. */
+
+#ifdef NTFS_RW
+	/* Variables used by the cluster and mft allocators. */
 	LCN mft_zone_start;		/* First cluster of the mft zone. */
 	LCN mft_zone_end;		/* First cluster beyond the mft zone. */
+	LCN mft_zone_pos;		/* Current position in the mft zone. */
+	LCN data1_zone_pos;		/* Current position in the first data
+					   zone. */
+	LCN data2_zone_pos;		/* Current position in the second data
+					   zone. */
+#endif /* NTFS_RW */
+
 	struct inode *mft_ino;		/* The VFS inode of $MFT. */
 
 	struct inode *mftbmp_ino;	/* Attribute inode for $MFT/$BITMAP. */
 	struct rw_semaphore mftbmp_lock; /* Lock for serializing accesses to the
 					    mft record bitmap ($MFT/$BITMAP). */
-	unsigned long nr_mft_records;	/* Number of mft records == number of
-					   bits in mft bitmap. */
-
 #ifdef NTFS_RW
 	struct inode *mftmirr_ino;	/* The VFS inode of $MFTMirr. */
 	int mftmirr_size;		/* Size of mft mirror in mft records. */
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
index d6d65be61..5910d6bf8 100644
--- a/fs/openpromfs/inode.c
+++ b/fs/openpromfs/inode.c
@@ -79,7 +79,7 @@ static ssize_t nodenum_read(struct file *file, char __user *buf,
 		count = 9 - file->f_pos;
 	if (copy_to_user(buf, buffer + file->f_pos, count))
 		return -EFAULT;
-	file->f_pos += count;
+	*ppos += count;
 	return count;
 }
 
@@ -94,7 +94,7 @@ static ssize_t property_read(struct file *filp, char __user *buf,
 	openprom_property *op;
 	char buffer[64];
 	
-	if (filp->f_pos >= 0xffffff || count >= 0xffffff)
+	if (*ppos >= 0xffffff || count >= 0xffffff)
 		return -EINVAL;
 	if (!filp->private_data) {
 		node = nodes[(u16)((long)inode->u.generic_ip)].node;
@@ -180,7 +180,7 @@ static ssize_t property_read(struct file *filp, char __user *buf,
 	} else {
 		i = (op->len << 1) + 1;
 	}
-	k = filp->f_pos;
+	k = *ppos;
 	if (k >= i) return 0;
 	if (count > i - k) count = i - k;
 	if (op->flag & OPP_STRING) {
@@ -197,7 +197,7 @@ static ssize_t property_read(struct file *filp, char __user *buf,
 			j = count;
 
 		if (j >= 0) {
-			if (copy_to_user(buf + k - filp->f_pos,
+			if (copy_to_user(buf + k - *ppos,
 					 op->value + k - 1, j))
 				return -EFAULT;
 			count -= j;
@@ -205,11 +205,11 @@ static ssize_t property_read(struct file *filp, char __user *buf,
 		}
 
 		if (count) {
-			if (put_user('\'', &buf [k++ - filp->f_pos]))
+			if (put_user('\'', &buf [k++ - *ppos]))
 				return -EFAULT;
 		}
 		if (count > 1) {
-			if (put_user('\n', &buf [k++ - filp->f_pos]))
+			if (put_user('\n', &buf [k++ - *ppos]))
 				return -EFAULT;
 		}
 	} else if (op->flag & OPP_STRINGLIST) {
@@ -287,7 +287,7 @@ static ssize_t property_read(struct file *filp, char __user *buf,
 		if ((k < i - 1) && (k & 1)) {
 			sprintf (buffer, "%02x",
 				 (unsigned char) *(op->value + (k >> 1)) & 0xff);
-			if (put_user(buffer[1], &buf[k++ - filp->f_pos]))
+			if (put_user(buffer[1], &buf[k++ - *ppos]))
 				return -EFAULT;
 			count--;
 		}
@@ -295,7 +295,7 @@ static ssize_t property_read(struct file *filp, char __user *buf,
 		for (; (count > 1) && (k < i - 1); k += 2) {
 			sprintf (buffer, "%02x",
 				 (unsigned char) *(op->value + (k >> 1)) & 0xff);
-			if (copy_to_user(buf + k - filp->f_pos, buffer, 2))
+			if (copy_to_user(buf + k - *ppos, buffer, 2))
 				return -EFAULT;
 			count -= 2;
 		}
@@ -303,18 +303,18 @@ static ssize_t property_read(struct file *filp, char __user *buf,
 		if (count && (k < i - 1)) {
 			sprintf (buffer, "%02x",
 				 (unsigned char) *(op->value + (k >> 1)) & 0xff);
-			if (put_user(buffer[0], &buf[k++ - filp->f_pos]))
+			if (put_user(buffer[0], &buf[k++ - *ppos]))
 				return -EFAULT;
 			count--;
 		}
 
 		if (count) {
-			if (put_user('\n', &buf [k++ - filp->f_pos]))
+			if (put_user('\n', &buf [k++ - *ppos]))
 				return -EFAULT;
 		}
 	}
-	count = k - filp->f_pos;
-	filp->f_pos = k;
+	count = k - *ppos;
+	*ppos = k;
 	return count;
 }
 
@@ -327,14 +327,14 @@ static ssize_t property_write(struct file *filp, const char __user *buf,
 	void *b;
 	openprom_property *op;
 	
-	if (filp->f_pos >= 0xffffff || count >= 0xffffff)
+	if (*ppos >= 0xffffff || count >= 0xffffff)
 		return -EINVAL;
 	if (!filp->private_data) {
 		i = property_read (filp, NULL, 0, NULL);
 		if (i)
 			return i;
 	}
-	k = filp->f_pos;
+	k = *ppos;
 	op = (openprom_property *)filp->private_data;
 	if (!(op->flag & OPP_STRING)) {
 		u32 *first, *last;
@@ -462,7 +462,7 @@ static ssize_t property_write(struct file *filp, const char __user *buf,
 				op->len = i;
 		} else
 			op->len = i;
-		filp->f_pos += count;
+		*ppos += count;
 	}
 write_try_string:
 	if (!(op->flag & OPP_BINARY)) {
@@ -480,7 +480,7 @@ write_try_string:
 				op->flag |= OPP_QUOTED;
 				buf++;
 				count--;
-				filp->f_pos++;
+				(*ppos)++;
 				if (!count) {
 					op->flag |= OPP_STRING;
 					return 1;
@@ -489,9 +489,9 @@ write_try_string:
 				op->flag |= OPP_NOTQUOTED;
 		}
 		op->flag |= OPP_STRING;
-		if (op->alloclen <= count + filp->f_pos) {
+		if (op->alloclen <= count + *ppos) {
 			b = kmalloc (sizeof (openprom_property)
-				     + 2 * (count + filp->f_pos), GFP_KERNEL);
+				     + 2 * (count + *ppos), GFP_KERNEL);
 			if (!b)
 				return -ENOMEM;
 			memcpy (b, filp->private_data,
@@ -499,14 +499,14 @@ write_try_string:
 				+ strlen (op->name) + op->alloclen);
 			memset (((char *)b) + sizeof (openprom_property)
 				+ strlen (op->name) + op->alloclen, 
-				0, 2*(count - filp->f_pos) - op->alloclen);
+				0, 2*(count - *ppos) - op->alloclen);
 			op = (openprom_property *)b;
-			op->alloclen = 2*(count + filp->f_pos);
+			op->alloclen = 2*(count + *ppos);
 			b = filp->private_data;
 			filp->private_data = (void *)op;
 			kfree (b);
 		}
-		p = op->value + filp->f_pos - ((op->flag & OPP_QUOTED) ? 1 : 0);
+		p = op->value + *ppos - ((op->flag & OPP_QUOTED) ? 1 : 0);
 		if (copy_from_user(p, buf, count))
 			return -EFAULT;
 		op->flag |= OPP_DIRTY;
@@ -517,17 +517,17 @@ write_try_string:
 			}
 		if (i < count) {
 			op->len = p - op->value;
-			filp->f_pos += i + 1;
+			*ppos += i + 1;
 			if ((p > op->value) && (op->flag & OPP_QUOTED)
 			    && (*(p - 1) == '\''))
 				op->len--;
 		} else {
 			if (p - op->value > op->len)
 				op->len = p - op->value;
-			filp->f_pos += count;
+			*ppos += count;
 		}
 	}
-	return filp->f_pos - k;
+	return *ppos - k;
 }
 
 int property_release (struct inode *inode, struct file *filp)
diff --git a/fs/partitions/acorn.c b/fs/partitions/acorn.c
index 6b494abe0..c05085710 100644
--- a/fs/partitions/acorn.c
+++ b/fs/partitions/acorn.c
@@ -53,16 +53,16 @@ adfs_partition(struct parsed_partitions *state, char *name, char *data,
 #ifdef CONFIG_ACORN_PARTITION_RISCIX
 
 struct riscix_part {
-	__u32	start;
-	__u32	length;
-	__u32	one;
+	__le32	start;
+	__le32	length;
+	__le32	one;
 	char	name[16];
 };
 
 struct riscix_record {
-	__u32	magic;
-#define RISCIX_MAGIC	(0x4a657320)
-	__u32	date;
+	__le32	magic;
+#define RISCIX_MAGIC	cpu_to_le32(0x4a657320)
+	__le32	date;
 	struct riscix_part part[8];
 };
 
@@ -111,9 +111,9 @@ riscix_partition(struct parsed_partitions *state, struct block_device *bdev,
 #define LINUX_SWAP_MAGIC   0xdeafab1e
 
 struct linux_part {
-	__u32 magic;
-	__u32 start_sect;
-	__u32 nr_sects;
+	__le32 magic;
+	__le32 start_sect;
+	__le32 nr_sects;
 };
 
 static int
@@ -306,8 +306,8 @@ adfspart_check_ADFS(struct parsed_partitions *state, struct block_device *bdev)
 #ifdef CONFIG_ACORN_PARTITION_ICS
 
 struct ics_part {
-	__u32 start;
-	__s32 size;
+	__le32 start;
+	__le32 size;
 };
 
 static int adfspart_check_ICSLinux(struct block_device *bdev, unsigned long block)
@@ -336,7 +336,7 @@ static inline int valid_ics_sector(const unsigned char *data)
 	for (i = 0, sum = 0x50617274; i < 508; i++)
 		sum += data[i];
 
-	sum -= le32_to_cpu(*(__u32 *)(&data[508]));
+	sum -= le32_to_cpu(*(__le32 *)(&data[508]));
 
 	return sum == 0;
 }
@@ -412,11 +412,11 @@ adfspart_check_ICS(struct parsed_partitions *state, struct block_device *bdev)
 
 #ifdef CONFIG_ACORN_PARTITION_POWERTEC
 struct ptec_part {
-	__u32 unused1;
-	__u32 unused2;
-	__u32 start;
-	__u32 size;
-	__u32 unused5;
+	__le32 unused1;
+	__le32 unused2;
+	__le32 start;
+	__le32 size;
+	__le32 unused5;
 	char type[8];
 };
 
@@ -486,10 +486,10 @@ adfspart_check_POWERTEC(struct parsed_partitions *state, struct block_device *bd
 struct eesox_part {
 	char	magic[6];
 	char	name[10];
-	u32	start;
-	u32	unused6;
-	u32	unused7;
-	u32	unused8;
+	__le32	start;
+	__le32	unused6;
+	__le32	unused7;
+	__le32	unused8;
 };
 
 /*
diff --git a/fs/partitions/amiga.c b/fs/partitions/amiga.c
index dfc1329f9..306852889 100644
--- a/fs/partitions/amiga.c
+++ b/fs/partitions/amiga.c
@@ -14,7 +14,7 @@
 #include "amiga.h"
 
 static __inline__ u32
-checksum_block(u32 *m, int size)
+checksum_block(__be32 *m, int size)
 {
 	u32 sum = 0;
 
@@ -31,6 +31,7 @@ amiga_partition(struct parsed_partitions *state, struct block_device *bdev)
 	struct RigidDiskBlock *rdb;
 	struct PartitionBlock *pb;
 	int start_sect, nr_sects, blk, part, res = 0;
+	int blksize = 1;	/* Multiplier for disk block size */
 	int slot = 1;
 	char b[BDEVNAME_SIZE];
 
@@ -44,17 +45,17 @@ amiga_partition(struct parsed_partitions *state, struct block_device *bdev)
 				       bdevname(bdev, b), blk);
 			goto rdb_done;
 		}
-		if (*(u32 *)data != cpu_to_be32(IDNAME_RIGIDDISK))
+		if (*(__be32 *)data != cpu_to_be32(IDNAME_RIGIDDISK))
 			continue;
 
 		rdb = (struct RigidDiskBlock *)data;
-		if (checksum_block((u32 *)data, be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F) == 0)
+		if (checksum_block((__be32 *)data, be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F) == 0)
 			break;
 		/* Try again with 0xdc..0xdf zeroed, Windows might have
 		 * trashed it.
 		 */
-		*(u32 *)(data+0xdc) = 0;
-		if (checksum_block((u32 *)data,
+		*(__be32 *)(data+0xdc) = 0;
+		if (checksum_block((__be32 *)data,
 				be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)==0) {
 			printk("Warning: Trashed word at 0xd0 in block %d "
 				"ignored in checksum calculation\n",blk);
@@ -65,10 +66,14 @@ amiga_partition(struct parsed_partitions *state, struct block_device *bdev)
 			       bdevname(bdev, b), blk);
 	}
 
-	printk(" RDSK");
+	/* blksize is blocks per 512 byte standard block */
+	blksize = be32_to_cpu( rdb->rdb_BlockBytes ) / 512;
+
+	printk(" RDSK (%d)", blksize * 512);	/* Be more informative */
 	blk = be32_to_cpu(rdb->rdb_PartitionList);
 	put_dev_sector(sect);
 	for (part = 1; blk>0 && part<=16; part++, put_dev_sector(sect)) {
+		blk *= blksize;	/* Read in terms partition table understands */
 		data = read_dev_sector(bdev, blk, &sect);
 		if (!data) {
 			if (warn_no_part)
@@ -80,7 +85,7 @@ amiga_partition(struct parsed_partitions *state, struct block_device *bdev)
 		blk = be32_to_cpu(pb->pb_Next);
 		if (pb->pb_ID != cpu_to_be32(IDNAME_PARTITION))
 			continue;
-		if (checksum_block((u32 *)pb, be32_to_cpu(pb->pb_SummedLongs) & 0x7F) != 0 )
+		if (checksum_block((__be32 *)pb, be32_to_cpu(pb->pb_SummedLongs) & 0x7F) != 0 )
 			continue;
 
 		/* Tell Kernel about it */
@@ -88,13 +93,32 @@ amiga_partition(struct parsed_partitions *state, struct block_device *bdev)
 		nr_sects = (be32_to_cpu(pb->pb_Environment[10]) + 1 -
 			    be32_to_cpu(pb->pb_Environment[9])) *
 			   be32_to_cpu(pb->pb_Environment[3]) *
-			   be32_to_cpu(pb->pb_Environment[5]);
+			   be32_to_cpu(pb->pb_Environment[5]) *
+			   blksize;
 		if (!nr_sects)
 			continue;
 		start_sect = be32_to_cpu(pb->pb_Environment[9]) *
 			     be32_to_cpu(pb->pb_Environment[3]) *
-			     be32_to_cpu(pb->pb_Environment[5]);
+			     be32_to_cpu(pb->pb_Environment[5]) *
+			     blksize;
 		put_partition(state,slot++,start_sect,nr_sects);
+		{
+			/* Be even more informative to aid mounting */
+			char dostype[4];
+			__be32 *dt = (__be32 *)dostype;
+			*dt = pb->pb_Environment[16];
+			if (dostype[3] < ' ')
+				printk(" (%c%c%c^%c)",
+					dostype[0], dostype[1],
+					dostype[2], dostype[3] + '@' );
+			else
+				printk(" (%c%c%c%c)",
+					dostype[0], dostype[1],
+					dostype[2], dostype[3]);
+			printk("(res %d spb %d)",
+				be32_to_cpu(pb->pb_Environment[6]),
+				be32_to_cpu(pb->pb_Environment[4]));
+		}
 		res = 1;
 	}
 	printk("\n");
diff --git a/fs/partitions/atari.h b/fs/partitions/atari.h
index 314d4dbd3..63186b00e 100644
--- a/fs/partitions/atari.h
+++ b/fs/partitions/atari.h
@@ -15,8 +15,8 @@ struct partition_info
 {
   u8 flg;			/* bit 0: active; bit 7: bootable */
   char id[3];			/* "GEM", "BGM", "XGM", or other */
-  u32 st;			/* start of partition */
-  u32 siz;			/* length of partition */
+  __be32 st;			/* start of partition */
+  __be32 siz;			/* length of partition */
 };
 
 struct rootsector
diff --git a/fs/partitions/efi.h b/fs/partitions/efi.h
index 9b2670e85..c44fb0561 100644
--- a/fs/partitions/efi.h
+++ b/fs/partitions/efi.h
@@ -66,20 +66,20 @@
               0xa2, 0x3c, 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28)
 
 typedef struct _gpt_header {
-	u64 signature;
-	u32 revision;
-	u32 header_size;
-	u32 header_crc32;
-	u32 reserved1;
-	u64 my_lba;
-	u64 alternate_lba;
-	u64 first_usable_lba;
-	u64 last_usable_lba;
+	__le64 signature;
+	__le32 revision;
+	__le32 header_size;
+	__le32 header_crc32;
+	__le32 reserved1;
+	__le64 my_lba;
+	__le64 alternate_lba;
+	__le64 first_usable_lba;
+	__le64 last_usable_lba;
 	efi_guid_t disk_guid;
-	u64 partition_entry_lba;
-	u32 num_partition_entries;
-	u32 sizeof_partition_entry;
-	u32 partition_entry_array_crc32;
+	__le64 partition_entry_lba;
+	__le32 num_partition_entries;
+	__le32 sizeof_partition_entry;
+	__le32 partition_entry_array_crc32;
 	u8 reserved2[GPT_BLOCK_SIZE - 92];
 } __attribute__ ((packed)) gpt_header;
 
@@ -92,18 +92,18 @@ typedef struct _gpt_entry_attributes {
 typedef struct _gpt_entry {
 	efi_guid_t partition_type_guid;
 	efi_guid_t unique_partition_guid;
-	u64 starting_lba;
-	u64 ending_lba;
+	__le64 starting_lba;
+	__le64 ending_lba;
 	gpt_entry_attributes attributes;
 	efi_char16_t partition_name[72 / sizeof (efi_char16_t)];
 } __attribute__ ((packed)) gpt_entry;
 
 typedef struct _legacy_mbr {
 	u8 boot_code[440];
-	u32 unique_mbr_signature;
-	u16 unknown;
+	__le32 unique_mbr_signature;
+	__le16 unknown;
 	struct partition partition_record[4];
-	u16 signature;
+	__le16 signature;
 } __attribute__ ((packed)) legacy_mbr;
 
 /* Functions */
diff --git a/fs/partitions/ldm.c b/fs/partitions/ldm.c
index 4d5145636..7ab1c11dc 100644
--- a/fs/partitions/ldm.c
+++ b/fs/partitions/ldm.c
@@ -2,7 +2,7 @@
  * ldm - Support for Windows Logical Disk Manager (Dynamic Disks)
  *
  * Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org>
- * Copyright (C) 2001      Anton Altaparmakov <aia21@cantab.net>
+ * Copyright (c) 2001-2004 Anton Altaparmakov
  * Copyright (C) 2001,2002 Jakob Kemi <jakob.kemi@telia.com>
  *
  * Documentation is available at http://linux-ntfs.sf.net/ldm
@@ -517,9 +517,15 @@ static BOOL ldm_validate_vmdb (struct block_device *bdev, unsigned long base,
 	if (vm->vblk_offset != 512)
 		ldm_info ("VBLKs start at offset 0x%04x.", vm->vblk_offset);
 
-	/* FIXME: How should we handle this situation? */
-	if ((vm->vblk_size * vm->last_vblk_seq) != (toc->bitmap1_size << 9))
-		ldm_info ("VMDB and TOCBLOCK don't agree on the database size.");
+	/*
+	 * The last_vblkd_seq can be before the end of the vmdb, just make sure
+	 * it is not out of bounds.
+	 */
+	if ((vm->vblk_size * vm->last_vblk_seq) > (toc->bitmap1_size << 9)) {
+		ldm_crit ("VMDB exceeds allowed size specified by TOCBLOCK.  "
+				"Database is corrupt.  Aborting.");
+		goto out;
+	}
 
 	result = TRUE;
 out:
@@ -560,7 +566,7 @@ static BOOL ldm_validate_partition_table (struct block_device *bdev)
 		return FALSE;
 	}
 
-	if (*(u16*) (data + 0x01FE) != cpu_to_le16 (MSDOS_LABEL_MAGIC))
+	if (*(__le16*) (data + 0x01FE) != cpu_to_le16 (MSDOS_LABEL_MAGIC))
 		goto out;
 
 	p = (struct partition*)(data + 0x01BE);
diff --git a/fs/partitions/ldm.h b/fs/partitions/ldm.h
index 14abedb99..6e8d7952b 100644
--- a/fs/partitions/ldm.h
+++ b/fs/partitions/ldm.h
@@ -99,9 +99,9 @@ struct parsed_partitions;
 #define TOC_BITMAP2		"log"		/* bitmaps in the TOCBLOCK. */
 
 /* Most numbers we deal with are big-endian and won't be aligned. */
-#define BE16(x)			((u16)be16_to_cpu(get_unaligned((u16*)(x))))
-#define BE32(x)			((u32)be32_to_cpu(get_unaligned((u32*)(x))))
-#define BE64(x)			((u64)be64_to_cpu(get_unaligned((u64*)(x))))
+#define BE16(x)			((u16)be16_to_cpu(get_unaligned((__be16*)(x))))
+#define BE32(x)			((u32)be32_to_cpu(get_unaligned((__be32*)(x))))
+#define BE64(x)			((u64)be64_to_cpu(get_unaligned((__be64*)(x))))
 
 /* Borrowed from msdos.c */
 #define SYS_IND(p)		(get_unaligned(&(p)->sys_ind))
diff --git a/fs/partitions/mac.h b/fs/partitions/mac.h
index 9b0a0d242..bbf26e138 100644
--- a/fs/partitions/mac.h
+++ b/fs/partitions/mac.h
@@ -8,23 +8,23 @@
 #define APPLE_AUX_TYPE	"Apple_UNIX_SVR2"
 
 struct mac_partition {
-	__u16	signature;	/* expected to be MAC_PARTITION_MAGIC */
-	__u16	res1;
-	__u32	map_count;	/* # blocks in partition map */
-	__u32	start_block;	/* absolute starting block # of partition */
-	__u32	block_count;	/* number of blocks in partition */
+	__be16	signature;	/* expected to be MAC_PARTITION_MAGIC */
+	__be16	res1;
+	__be32	map_count;	/* # blocks in partition map */
+	__be32	start_block;	/* absolute starting block # of partition */
+	__be32	block_count;	/* number of blocks in partition */
 	char	name[32];	/* partition name */
 	char	type[32];	/* string type description */
-	__u32	data_start;	/* rel block # of first data block */
-	__u32	data_count;	/* number of data blocks */
-	__u32	status;		/* partition status bits */
-	__u32	boot_start;
-	__u32	boot_size;
-	__u32	boot_load;
-	__u32	boot_load2;
-	__u32	boot_entry;
-	__u32	boot_entry2;
-	__u32	boot_cksum;
+	__be32	data_start;	/* rel block # of first data block */
+	__be32	data_count;	/* number of data blocks */
+	__be32	status;		/* partition status bits */
+	__be32	boot_start;
+	__be32	boot_size;
+	__be32	boot_load;
+	__be32	boot_load2;
+	__be32	boot_entry;
+	__be32	boot_entry2;
+	__be32	boot_cksum;
 	char	processor[16];	/* identifies ISA of boot */
 	/* there is more stuff after this that we don't need */
 };
@@ -35,9 +35,9 @@ struct mac_partition {
 
 /* Driver descriptor structure, in block 0 */
 struct mac_driver_desc {
-	__u16	signature;	/* expected to be MAC_DRIVER_MAGIC */
-	__u16	block_size;
-	__u32	block_count;
+	__be16	signature;	/* expected to be MAC_DRIVER_MAGIC */
+	__be16	block_size;
+	__be32	block_count;
     /* ... more stuff */
 };
 
diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c
index 100fa7548..ff77a954c 100644
--- a/fs/partitions/msdos.c
+++ b/fs/partitions/msdos.c
@@ -246,6 +246,9 @@ parse_bsd(struct parsed_partitions *state, struct block_device *bdev,
 		put_partition(state, state->next++, bsd_start, bsd_size);
 	}
 	put_dev_sector(sect);
+	if (le16_to_cpu(l->d_npartitions) > max_partitions)
+		printk(" (ignored %d more)",
+		       le16_to_cpu(l->d_npartitions) - max_partitions);
 	printk(" >\n");
 }
 #endif
diff --git a/fs/partitions/osf.c b/fs/partitions/osf.c
index e9af7808c..c05c17bc5 100644
--- a/fs/partitions/osf.c
+++ b/fs/partitions/osf.c
@@ -17,34 +17,34 @@ int osf_partition(struct parsed_partitions *state, struct block_device *bdev)
 	Sector sect;
 	unsigned char *data;
 	struct disklabel {
-		u32 d_magic;
-		u16 d_type,d_subtype;
+		__le32 d_magic;
+		__le16 d_type,d_subtype;
 		u8 d_typename[16];
 		u8 d_packname[16];
-		u32 d_secsize;
-		u32 d_nsectors;
-		u32 d_ntracks;
-		u32 d_ncylinders;
-		u32 d_secpercyl;
-		u32 d_secprtunit;
-		u16 d_sparespertrack;
-		u16 d_sparespercyl;
-		u32 d_acylinders;
-		u16 d_rpm, d_interleave, d_trackskew, d_cylskew;
-		u32 d_headswitch, d_trkseek, d_flags;
-		u32 d_drivedata[5];
-		u32 d_spare[5];
-		u32 d_magic2;
-		u16 d_checksum;
-		u16 d_npartitions;
-		u32 d_bbsize, d_sbsize;
+		__le32 d_secsize;
+		__le32 d_nsectors;
+		__le32 d_ntracks;
+		__le32 d_ncylinders;
+		__le32 d_secpercyl;
+		__le32 d_secprtunit;
+		__le16 d_sparespertrack;
+		__le16 d_sparespercyl;
+		__le32 d_acylinders;
+		__le16 d_rpm, d_interleave, d_trackskew, d_cylskew;
+		__le32 d_headswitch, d_trkseek, d_flags;
+		__le32 d_drivedata[5];
+		__le32 d_spare[5];
+		__le32 d_magic2;
+		__le16 d_checksum;
+		__le16 d_npartitions;
+		__le32 d_bbsize, d_sbsize;
 		struct d_partition {
-			u32 p_size;
-			u32 p_offset;
-			u32 p_fsize;
+			__le32 p_size;
+			__le32 p_offset;
+			__le32 p_fsize;
 			u8  p_fstype;
 			u8  p_frag;
-			u16 p_cpg;
+			__le16 p_cpg;
 		} d_partitions[8];
 	} * label;
 	struct d_partition * partition;
diff --git a/fs/partitions/sgi.c b/fs/partitions/sgi.c
index f1ad8bc62..bace1ceac 100644
--- a/fs/partitions/sgi.c
+++ b/fs/partitions/sgi.c
@@ -8,30 +8,32 @@
 #include "sgi.h"
 
 struct sgi_disklabel {
-	s32 magic_mushroom;		/* Big fat spliff... */
-	s16 root_part_num;		/* Root partition number */
-	s16 swap_part_num;		/* Swap partition number */
+	__be32 magic_mushroom;		/* Big fat spliff... */
+	__be16 root_part_num;		/* Root partition number */
+	__be16 swap_part_num;		/* Swap partition number */
 	s8 boot_file[16];		/* Name of boot file for ARCS */
 	u8 _unused0[48];		/* Device parameter useless crapola.. */
 	struct sgi_volume {
 		s8 name[8];		/* Name of volume */
-		s32 block_num;		/* Logical block number */
-		s32 num_bytes;		/* How big, in bytes */
+		__be32 block_num;		/* Logical block number */
+		__be32 num_bytes;		/* How big, in bytes */
 	} volume[15];
 	struct sgi_partition {
-		u32 num_blocks;		/* Size in logical blocks */
-		u32 first_block;	/* First logical block */
-		s32 type;		/* Type of this partition */
+		__be32 num_blocks;		/* Size in logical blocks */
+		__be32 first_block;	/* First logical block */
+		__be32 type;		/* Type of this partition */
 	} partitions[16];
-	s32 csum;			/* Disk label checksum */
-	s32 _unused1;			/* Padding */
+	__be32 csum;			/* Disk label checksum */
+	__be32 _unused1;			/* Padding */
 };
 
 int sgi_partition(struct parsed_partitions *state, struct block_device *bdev)
 {
-	int i, csum, magic;
+	int i, csum;
+	__be32 magic;
 	int slot = 1;
-	unsigned int *ui, start, blocks, cs;
+	unsigned int start, blocks;
+	__be32 *ui, cs;
 	Sector sect;
 	struct sgi_disklabel *label;
 	struct sgi_partition *p;
@@ -44,12 +46,12 @@ int sgi_partition(struct parsed_partitions *state, struct block_device *bdev)
 	magic = label->magic_mushroom;
 	if(be32_to_cpu(magic) != SGI_LABEL_MAGIC) {
 		/*printk("Dev %s SGI disklabel: bad magic %08x\n",
-		       bdevname(bdev, b), magic);*/
+		       bdevname(bdev, b), be32_to_cpu(magic));*/
 		put_dev_sector(sect);
 		return 0;
 	}
-	ui = ((unsigned int *) (label + 1)) - 1;
-	for(csum = 0; ui >= ((unsigned int *) label);) {
+	ui = ((__be32 *) (label + 1)) - 1;
+	for(csum = 0; ui >= ((__be32 *) label);) {
 		cs = *ui--;
 		csum += be32_to_cpu(cs);
 	}
diff --git a/fs/partitions/sun.c b/fs/partitions/sun.c
index 204826e0d..abe91ca03 100644
--- a/fs/partitions/sun.c
+++ b/fs/partitions/sun.c
@@ -12,9 +12,10 @@
 
 int sun_partition(struct parsed_partitions *state, struct block_device *bdev)
 {
-	int i, csum;
+	int i;
+	__be16 csum;
 	int slot = 1;
-	unsigned short *ush;
+	__be16 *ush;
 	Sector sect;
 	struct sun_disklabel {
 		unsigned char info[128];   /* Informative text string */
@@ -26,22 +27,22 @@ int sun_partition(struct parsed_partitions *state, struct block_device *bdev)
 			unsigned char flags;
 		} infos[8];
 		unsigned char spare[246];  /* Boot information etc. */
-		unsigned short rspeed;     /* Disk rotational speed */
-		unsigned short pcylcount;  /* Physical cylinder count */
-		unsigned short sparecyl;   /* extra sects per cylinder */
+		__be16 rspeed;     /* Disk rotational speed */
+		__be16 pcylcount;  /* Physical cylinder count */
+		__be16 sparecyl;   /* extra sects per cylinder */
 		unsigned char spare2[4];   /* More magic... */
-		unsigned short ilfact;     /* Interleave factor */
-		unsigned short ncyl;       /* Data cylinder count */
-		unsigned short nacyl;      /* Alt. cylinder count */
-		unsigned short ntrks;      /* Tracks per cylinder */
-		unsigned short nsect;      /* Sectors per track */
+		__be16 ilfact;     /* Interleave factor */
+		__be16 ncyl;       /* Data cylinder count */
+		__be16 nacyl;      /* Alt. cylinder count */
+		__be16 ntrks;      /* Tracks per cylinder */
+		__be16 nsect;      /* Sectors per track */
 		unsigned char spare3[4];   /* Even more magic... */
 		struct sun_partition {
-			__u32 start_cylinder;
-			__u32 num_sectors;
+			__be32 start_cylinder;
+			__be32 num_sectors;
 		} partitions[8];
-		unsigned short magic;      /* Magic number */
-		unsigned short csum;       /* Label xor'd checksum */
+		__be16 magic;      /* Magic number */
+		__be16 csum;       /* Label xor'd checksum */
 	} * label;		
 	struct sun_partition *p;
 	unsigned long spc;
@@ -59,8 +60,8 @@ int sun_partition(struct parsed_partitions *state, struct block_device *bdev)
 		return 0;
 	}
 	/* Look at the checksum */
-	ush = ((unsigned short *) (label+1)) - 1;
-	for (csum = 0; ush >= ((unsigned short *) label);)
+	ush = ((__be16 *) (label+1)) - 1;
+	for (csum = 0; ush >= ((__be16 *) label);)
 		csum ^= *ush--;
 	if (csum) {
 		printk("Dev %s Sun disklabel: Csum bad, label corrupted\n",
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 190ba24f3..41990f07d 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -92,10 +92,13 @@ static inline char * task_name(struct task_struct *p, char * buf)
 {
 	int i;
 	char * name;
+	char tcomm[sizeof(p->comm)];
+
+	get_task_comm(tcomm, p);
 
 	ADDBUF(buf, "Name:\t");
-	name = p->comm;
-	i = sizeof(p->comm);
+	name = tcomm;
+	i = sizeof(tcomm);
 	do {
 		unsigned char c = *name;
 		name++;
@@ -131,9 +134,10 @@ static const char *task_state_array[] = {
 	"S (sleeping)",		/*  1 */
 	"D (disk sleep)",	/*  2 */
 	"T (stopped)",		/*  4 */
-	"Z (zombie)",		/*  8 */
-	"X (dead)",		/* 16 */
-	"H (on hold)"		/* 32 */
+	"T (tracing stop)",	/*  8 */
+	"Z (zombie)",		/* 16 */
+	"X (dead)",		/* 32 */
+	"H (on hold)"		/* 64 */
 };
 
 static inline const char * get_task_state(struct task_struct *tsk)
@@ -144,6 +148,7 @@ static inline const char * get_task_state(struct task_struct *tsk)
 					   TASK_ZOMBIE |
 					   TASK_DEAD |
 					   TASK_STOPPED |
+					   TASK_TRACED |
 					   TASK_ONHOLD);
 	const char **p = &task_state_array[0];
 
@@ -158,12 +163,13 @@ static inline char * task_state(struct task_struct *p, char *buffer)
 {
 	struct group_info *group_info;
 	int g;
-	pid_t pid, ppid, tgid;
+	pid_t pid, ppid, tppid, tgid;
 
 	read_lock(&tasklist_lock);
-	tgid = vx_map_tgid(current->vx_info, p->tgid);
-	pid = vx_map_tgid(current->vx_info, p->pid);
-	ppid = vx_map_tgid(current->vx_info, p->real_parent->pid);
+	tgid = vx_map_tgid(p->tgid);
+	pid = vx_map_pid(p->pid);
+	ppid = vx_map_pid(p->real_parent->pid);
+	tppid = vx_map_pid(p->parent->pid);
 	buffer += sprintf(buffer,
 		"State:\t%s\n"
 		"SleepAVG:\t%lu%%\n"
@@ -175,8 +181,8 @@ static inline char * task_state(struct task_struct *p, char *buffer)
 		"Gid:\t%d\t%d\t%d\t%d\n",
 		get_task_state(p),
 		(p->sleep_avg/1024)*100/(1020000000/1024),
-		tgid, pid, p->pid ? ppid : 0,
-		p->pid && p->ptrace ? p->parent->pid : 0,
+		tgid, pid, (pid > 1) ? ppid : 0,
+		p->pid && p->ptrace ? tppid : 0,
 		p->uid, p->euid, p->suid, p->fsuid,
 		p->gid, p->egid, p->sgid, p->fsgid);
 	read_unlock(&tasklist_lock);
@@ -284,11 +290,10 @@ static inline char *task_cap(struct task_struct *p, char *buffer)
 			    cap_t(p->cap_effective));
 }
 
-extern char *task_mem(struct mm_struct *, char *);
 int proc_pid_status(struct task_struct *task, char * buffer)
 {
 	char * orig = buffer;
-#ifdef	CONFIG_VSERVER_LEGACY		
+#ifdef	CONFIG_VSERVER_LEGACY
 	struct vx_info *vxi;
 	struct nx_info *nxi;
 #endif
@@ -304,7 +309,7 @@ int proc_pid_status(struct task_struct *task, char * buffer)
 	buffer = task_sig(task, buffer);
 	buffer = task_cap(task, buffer);
 
-#ifdef	CONFIG_VSERVER_LEGACY		
+#ifdef	CONFIG_VSERVER_LEGACY
 	buffer += sprintf (buffer,"s_context: %d\n", vx_task_xid(task));
 	vxi = task_get_vx_info(task);
 	if (vxi) {
@@ -342,12 +347,11 @@ int proc_pid_status(struct task_struct *task, char * buffer)
 	return buffer - orig;
 }
 
-extern unsigned long task_vsize(struct mm_struct *);
 int proc_pid_stat(struct task_struct *task, char * buffer)
 {
 	unsigned long vsize, eip, esp, wchan;
 	long priority, nice;
-	unsigned long long bias_jiffies;
+	unsigned long long bias_uptime = 0;
 	int tty_pgrp = -1, tty_nr = 0;
 	sigset_t sigign, sigcatch;
 	char state;
@@ -356,32 +360,19 @@ int proc_pid_stat(struct task_struct *task, char * buffer)
 	int num_threads = 0;
 	struct mm_struct *mm;
 	unsigned long long start_time;
+	unsigned long cmin_flt = 0, cmaj_flt = 0, cutime = 0, cstime = 0;
+	char tcomm[sizeof(task->comm)];
 
 	state = *get_task_state(task);
 	vsize = eip = esp = 0;
-	bias_jiffies = INITIAL_JIFFIES;
-
-	task_lock(task);
-	if (__vx_task_flags(task, VXF_VIRT_UPTIME, 0)) {
-		bias_jiffies = task->vx_info->cvirt.bias_jiffies;
-		/* hmm, do we need that? */
-		if (bias_jiffies > task->start_time)
-			bias_jiffies = task->start_time;
-	}
-	pid = vx_map_tgid(task->vx_info, task->pid);
-
-	mm = task->mm;
-	if(mm)
-		mm = mmgrab(mm);
-	task_unlock(task);
+	mm = get_task_mm(task);
 	if (mm) {
-		down_read(&mm->mmap_sem);
 		vsize = task_vsize(mm);
 		eip = KSTK_EIP(task);
 		esp = KSTK_ESP(task);
-		up_read(&mm->mmap_sem);
 	}
 
+	get_task_comm(tcomm, task);
 	wchan = get_wchan(task);
 
 	sigemptyset(&sigign);
@@ -400,6 +391,14 @@ int proc_pid_stat(struct task_struct *task, char * buffer)
 		}
 		pgid = process_group(task);
 		sid = task->signal->session;
+		cmin_flt = task->signal->cmin_flt;
+		cmaj_flt = task->signal->cmaj_flt;
+		cutime = task->signal->cutime;
+		cstime = task->signal->cstime;
+	}
+	if (task_vx_flags(task, VXF_VIRT_UPTIME, 0)) {
+		bias_uptime = task->vx_info->cvirt.bias_uptime.tv_sec * NSEC_PER_SEC
+			+ task->vx_info->cvirt.bias_uptime.tv_nsec;
 	}
 	read_unlock(&tasklist_lock);
 
@@ -409,17 +408,24 @@ int proc_pid_stat(struct task_struct *task, char * buffer)
 	nice = task_nice(task);
 
 	read_lock(&tasklist_lock);
-	ppid = task->pid ? task->real_parent->pid : 0;
+	pid = vx_info_map_pid(task->vx_info, task->pid);
+	ppid = (!(pid > 1)) ? 0 :
+		vx_info_map_pid(task->vx_info, task->real_parent->pid);
+	pgid = vx_info_map_pid(task->vx_info, pgid);
 	read_unlock(&tasklist_lock);
 
 	/* Temporary variable needed for gcc-2.96 */
-	start_time = jiffies_64_to_clock_t(task->start_time - bias_jiffies);
+	/* convert timespec -> 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 - bias_uptime);
 
 	res = sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
 %lu %lu %lu %lu %lu %ld %ld %ld %ld %d %ld %llu %lu %ld %lu %lu %lu %lu %lu \
 %lu %lu %lu %lu %lu %lu %lu %lu %d %d %lu %lu\n",
 		pid,
-		task->comm,
+		tcomm,
 		state,
 		ppid,
 		pgid,
@@ -428,13 +434,13 @@ int proc_pid_stat(struct task_struct *task, char * buffer)
 		tty_pgrp,
 		task->flags,
 		task->min_flt,
-		task->cmin_flt,
+		cmin_flt,
 		task->maj_flt,
-		task->cmaj_flt,
+		cmaj_flt,
 		jiffies_to_clock_t(task->utime),
 		jiffies_to_clock_t(task->stime),
-		jiffies_to_clock_t(task->cutime),
-		jiffies_to_clock_t(task->cstime),
+		jiffies_to_clock_t(cutime),
+		jiffies_to_clock_t(cstime),
 		priority,
 		nice,
 		num_threads,
@@ -468,17 +474,13 @@ int proc_pid_stat(struct task_struct *task, char * buffer)
 	return res;
 }
 
-extern int task_statm(struct mm_struct *, int *, int *, int *, int *);
 int proc_pid_statm(struct task_struct *task, char *buffer)
 {
 	int size = 0, resident = 0, shared = 0, text = 0, lib = 0, data = 0;
 	struct mm_struct *mm = get_task_mm(task);
 	
 	if (mm) {
-		down_read(&mm->mmap_sem);
 		size = task_statm(mm, &shared, &text, &data, &resident);
-		up_read(&mm->mmap_sem);
-
 		mmput(mm);
 	}
 
diff --git a/fs/proc/base.c b/fs/proc/base.c
index e1c3a5d9b..434ecb495 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -33,7 +33,6 @@
 #include <linux/security.h>
 #include <linux/ptrace.h>
 #include <linux/vs_network.h>
-#include <linux/vs_cvirt.h>
 
 /*
  * For hysterical raisins we keep the same inumbers as in the old procfs.
@@ -62,6 +61,9 @@ enum pid_directory_inos {
 	PROC_TGID_MAPS,
 	PROC_TGID_MOUNTS,
 	PROC_TGID_WCHAN,
+#ifdef CONFIG_SCHEDSTATS
+	PROC_TGID_SCHEDSTAT,
+#endif
 #ifdef CONFIG_SECURITY
 	PROC_TGID_ATTR,
 	PROC_TGID_ATTR_CURRENT,
@@ -87,6 +89,9 @@ enum pid_directory_inos {
 	PROC_TID_MAPS,
 	PROC_TID_MOUNTS,
 	PROC_TID_WCHAN,
+#ifdef CONFIG_SCHEDSTATS
+	PROC_TID_SCHEDSTAT,
+#endif
 #ifdef CONFIG_SECURITY
 	PROC_TID_ATTR,
 	PROC_TID_ATTR_CURRENT,
@@ -128,6 +133,9 @@ static struct pid_entry tgid_base_stuff[] = {
 #endif
 #ifdef CONFIG_KALLSYMS
 	E(PROC_TGID_WCHAN,     "wchan",   S_IFREG|S_IRUGO),
+#endif
+#ifdef CONFIG_SCHEDSTATS
+	E(PROC_TGID_SCHEDSTAT, "schedstat", S_IFREG|S_IRUGO),
 #endif
 	E(PROC_TGID_VX_INFO,   "vinfo",   S_IFREG|S_IRUGO),
 	E(PROC_TGID_IP_INFO,   "ninfo",   S_IFREG|S_IRUGO),
@@ -152,6 +160,9 @@ static struct pid_entry tid_base_stuff[] = {
 #endif
 #ifdef CONFIG_KALLSYMS
 	E(PROC_TID_WCHAN,      "wchan",   S_IFREG|S_IRUGO),
+#endif
+#ifdef CONFIG_SCHEDSTATS
+	E(PROC_TID_SCHEDSTAT, "schedstat",S_IFREG|S_IRUGO),
 #endif
 	E(PROC_TID_VX_INFO,    "vinfo",   S_IFREG|S_IRUGO),
 	E(PROC_TID_IP_INFO,    "ninfo",   S_IFREG|S_IRUGO),
@@ -190,7 +201,6 @@ static inline int proc_type(struct inode *inode)
 int proc_pid_stat(struct task_struct*,char*);
 int proc_pid_status(struct task_struct*,char*);
 int proc_pid_statm(struct task_struct*,char*);
-int proc_pid_cpu(struct task_struct*,char*);
 
 static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
 {
@@ -286,7 +296,8 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf
 #define MAY_PTRACE(task) \
 	(task == current || \
 	(task->parent == current && \
-	(task->ptrace & PT_PTRACED) &&  task->state == TASK_STOPPED && \
+	(task->ptrace & PT_PTRACED) && \
+	 (task->state == TASK_STOPPED || task->state == TASK_TRACED) && \
 	 security_ptrace(current,task) == 0))
 
 static int may_ptrace_attach(struct task_struct *task)
@@ -339,6 +350,8 @@ static int proc_pid_cmdline(struct task_struct *task, char * buffer)
 	struct mm_struct *mm = get_task_mm(task);
 	if (!mm)
 		goto out;
+	if (!mm->arg_end)
+		goto out;	/* Shh! No looking before we're done */
 
  	len = mm->arg_end - mm->arg_start;
  
@@ -349,7 +362,7 @@ static int proc_pid_cmdline(struct task_struct *task, char * buffer)
 
 	// If the nul at the end of args has been overwritten, then
 	// assume application is using setproctitle(3).
-	if (res > 0 && buffer[res-1] != '\0') {
+	if (res > 0 && buffer[res-1] != '\0' && len < PAGE_SIZE) {
 		len = strnlen(buffer, res);
 		if (len < res) {
 		    res = len;
@@ -407,6 +420,19 @@ static int proc_pid_wchan(struct task_struct *task, char *buffer)
 }
 #endif /* CONFIG_KALLSYMS */
 
+#ifdef CONFIG_SCHEDSTATS
+/*
+ * Provides /proc/PID/schedstat
+ */
+static int proc_pid_schedstat(struct task_struct *task, char *buffer)
+{
+	return sprintf(buffer, "%lu %lu %lu\n",
+			task->sched_info.cpu_time,
+			task->sched_info.run_delay,
+			task->sched_info.pcnt);
+}
+#endif
+
 /************************************************************************/
 /*                       Here the fs part begins                        */
 /************************************************************************/
@@ -527,7 +553,6 @@ static ssize_t proc_info_read(struct file * file, char __user * buf,
 	struct inode * inode = file->f_dentry->d_inode;
 	unsigned long page;
 	ssize_t length;
-	ssize_t end;
 	struct task_struct *task = proc_task(inode);
 
 	if (count > PROC_BLOCK_SIZE)
@@ -537,24 +562,10 @@ static ssize_t proc_info_read(struct file * file, char __user * buf,
 
 	length = PROC_I(inode)->op.proc_read(task, (char*)page);
 
-	if (length < 0) {
-		free_page(page);
-		return length;
-	}
-	/* Static 4kB (or whatever) block capacity */
-	if (*ppos >= length) {
-		free_page(page);
-		return 0;
-	}
-	if (count + *ppos > length)
-		count = length - *ppos;
-	end = count + *ppos;
-	if (copy_to_user(buf, (char *) page + *ppos, count))
-		count = -EFAULT;
-	else
-		*ppos = end;
+	if (length >= 0)
+		length = simple_read_from_buffer(buf, count, ppos, (char *)page, length);
 	free_page(page);
-	return count;
+	return length;
 }
 
 static struct file_operations proc_info_file_operations = {
@@ -777,10 +788,9 @@ static struct inode_operations proc_pid_link_inode_operations = {
 	.follow_link	= proc_pid_follow_link
 };
 
-static int pid_alive(struct task_struct *p)
+static inline int pid_alive(struct task_struct *p)
 {
-	BUG_ON(p->pids[PIDTYPE_PID].pidptr != &p->pids[PIDTYPE_PID].pid);
-	return atomic_read(&p->pids[PIDTYPE_PID].pid.count);
+	return p->pids[PIDTYPE_PID].nr != 0;
 }
 
 #define NUMBUF 10
@@ -1185,7 +1195,6 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
 	struct inode * inode = file->f_dentry->d_inode;
 	unsigned long page;
 	ssize_t length;
-	ssize_t end;
 	struct task_struct *task = proc_task(inode);
 
 	if (count > PAGE_SIZE)
@@ -1196,24 +1205,10 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
 	length = security_getprocattr(task, 
 				      (char*)file->f_dentry->d_name.name, 
 				      (void*)page, count);
-	if (length < 0) {
-		free_page(page);
-		return length;
-	}
-	/* Static 4kB (or whatever) block capacity */
-	if (*ppos >= length) {
-		free_page(page);
-		return 0;
-	}
-	if (count + *ppos > length)
-		count = length - *ppos;
-	end = count + *ppos;
-	if (copy_to_user(buf, (char *) page + *ppos, count))
-		count = -EFAULT;
-	else
-		*ppos = end;
+	if (length >= 0)
+		length = simple_read_from_buffer(buf, count, ppos, (char *)page, length);
 	free_page(page);
-	return count;
+	return length;
 }
 
 static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
@@ -1391,6 +1386,13 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
 			inode->i_fop = &proc_info_file_operations;
 			ei->op.proc_read = proc_pid_wchan;
 			break;
+#endif
+#ifdef CONFIG_SCHEDSTATS
+		case PROC_TID_SCHEDSTAT:
+		case PROC_TGID_SCHEDSTAT:
+			inode->i_fop = &proc_info_file_operations;
+			ei->op.proc_read = proc_pid_schedstat;
+			break;
 #endif
 		case PROC_TID_VX_INFO:
 		case PROC_TGID_VX_INFO:
@@ -1494,14 +1496,14 @@ static int proc_self_readlink(struct dentry *dentry, char __user *buffer,
 			      int buflen)
 {
 	char tmp[30];
-	sprintf(tmp, "%d", current->tgid);
+	sprintf(tmp, "%d", vx_map_pid(current->tgid));
 	return vfs_readlink(dentry,buffer,buflen,tmp);
 }
 
 static int proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
 	char tmp[30];
-	sprintf(tmp, "%d", current->tgid);
+	sprintf(tmp, "%d", vx_map_pid(current->tgid));
 	return vfs_follow_link(nd,tmp);
 }	
 
@@ -1553,6 +1555,7 @@ struct dentry *proc_pid_unhash(struct task_struct *p)
 	
 void proc_pid_flush(struct dentry *proc_dentry)
 {
+	might_sleep();
 	if(proc_dentry != NULL) {
 		shrink_dcache_parent(proc_dentry);
 		dput(proc_dentry);
@@ -1583,7 +1586,7 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct
 		d_add(dentry, inode);
 		return NULL;
 	}
-	tgid = vx_rmap_tgid(current->vx_info, name_to_int(dentry));
+	tgid = name_to_int(dentry);
 	if (tgid == ~0U)
 		goto out;
 
@@ -1595,14 +1598,13 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct
 	if (!task)
 		goto out;
 
-	inode = NULL;
-	if (vx_check(vx_task_xid(task), VX_WATCH|VX_IDENT))
-		inode = proc_pid_make_inode(dir->i_sb, task, PROC_TGID_INO);
+	if (!vx_check(vx_task_xid(task), VX_WATCH|VX_IDENT))
+		goto out_drop_task;
+
+	inode = proc_pid_make_inode(dir->i_sb, task, PROC_TGID_INO);
+	if (!inode)
+		goto out_drop_task;
 
-	if (!inode) {
-		put_task_struct(task);
-		goto out;
-	}
 	inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
 	inode->i_op = &proc_tgid_base_inode_operations;
 	inode->i_fop = &proc_tgid_base_operations;
@@ -1627,6 +1629,8 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct
 		goto out;
 	}
 	return NULL;
+out_drop_task:
+	put_task_struct(task);
 out:
 	return ERR_PTR(-ENOENT);
 }
@@ -1639,11 +1643,11 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry
 	struct inode *inode;
 	unsigned tid;
 
-	tid = vx_rmap_tgid(current->vx_info, name_to_int(dentry));
+	tid = name_to_int(dentry);
 	if (tid == ~0U)
 		goto out;
-
-/*	handle fakeinit */
+	if (vx_current_initpid(tid))
+		goto out;
 
 	read_lock(&tasklist_lock);
 	task = find_task_by_pid(tid);
@@ -1655,12 +1659,13 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry
 	if (leader->tgid != task->tgid)
 		goto out_drop_task;
 
-	inode = NULL;
-	if (vx_check(vx_task_xid(task), VX_WATCH|VX_IDENT))
-		inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_INO);
+	if (!vx_check(vx_task_xid(task), VX_WATCH|VX_IDENT))
+		goto out_drop_task;
 
+	inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_INO);
 	if (!inode)
 		goto out_drop_task;
+
 	inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
 	inode->i_op = &proc_tid_base_inode_operations;
 	inode->i_fop = &proc_tid_base_operations;
@@ -1696,8 +1701,8 @@ static int get_tgid_list(int index, unsigned long version, unsigned int *tgids)
 	read_lock(&tasklist_lock);
 	p = NULL;
 	if (version) {
-		p = find_task_by_pid(version);
-		if (!thread_group_leader(p))
+		p = find_task_by_real_pid(version);
+		if (p && !thread_group_leader(p))
 			p = NULL;
 	}
 
@@ -1715,7 +1720,7 @@ static int get_tgid_list(int index, unsigned long version, unsigned int *tgids)
 			continue;
 		if (--index >= 0)
 			continue;
-		tgids[nr_tgids] = vx_map_tgid(current->vx_info, tgid);
+		tgids[nr_tgids] = vx_map_tgid(tgid);
 		nr_tgids++;
 		if (nr_tgids >= PROC_MAXPIDS)
 			break;
@@ -1749,7 +1754,7 @@ static int get_tid_list(int index, unsigned int *tids, struct inode *dir)
 			continue;
 		if (--index >= 0)
 			continue;
-		tids[nr_tids] = vx_map_tgid(current->vx_info, tid);
+		tids[nr_tids] = vx_map_pid(tid);
 		nr_tids++;
 		if (nr_tids >= PROC_MAXPIDS)
 			break;
@@ -1765,6 +1770,7 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
 	char buf[PROC_NUMBUF];
 	unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY;
 	unsigned int nr_tgids, i;
+	int next_tgid;
 
 	if (!nr) {
 		ino_t ino = fake_ino(0,PROC_TGID_INO);
@@ -1774,26 +1780,45 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
 		nr++;
 	}
 
-	/*
-	 * f_version caches the last tgid which was returned from readdir
+	/* f_version caches the tgid value that the last readdir call couldn't
+	 * return. lseek aka telldir automagically resets f_version to 0.
 	 */
-	nr_tgids = get_tgid_list(nr, filp->f_version, tgid_array);
+	next_tgid = filp->f_version;
+	filp->f_version = 0;
+	for (;;) {
+		nr_tgids = get_tgid_list(nr, next_tgid, tgid_array);
+		if (!nr_tgids) {
+			/* no more entries ! */
+			break;
+		}
+		next_tgid = 0;
 
-	for (i = 0; i < nr_tgids; i++) {
-		int tgid = tgid_array[i];
-		ino_t ino = fake_ino(tgid,PROC_TGID_INO);
-		unsigned long j = PROC_NUMBUF;
+		/* do not use the last found pid, reserve it for next_tgid */
+		if (nr_tgids == PROC_MAXPIDS) {
+			nr_tgids--;
+			next_tgid = tgid_array[nr_tgids];
+		}
 
-		do
-			buf[--j] = '0' + (tgid % 10);
-		while ((tgid /= 10) != 0);
+		for (i=0;i<nr_tgids;i++) {
+			int tgid = tgid_array[i];
+			ino_t ino = fake_ino(tgid,PROC_TGID_INO);
+			unsigned long j = PROC_NUMBUF;
 
-		if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino, DT_DIR) < 0) {
-			filp->f_version = tgid;
-			break;
+			do
+				buf[--j] = '0' + (tgid % 10);
+			while ((tgid /= 10) != 0);
+
+			if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino, DT_DIR) < 0) {
+				/* returning this tgid failed, save it as the first
+				 * pid for the next readir call */
+				filp->f_version = tgid_array[i];
+				goto out;
+			}
+			filp->f_pos++;
+			nr++;
 		}
-		filp->f_pos++;
 	}
+out:
 	return 0;
 }
 
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index bf090daaf..b4d3e5480 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -120,7 +120,7 @@ int __init proc_init_inodecache(void)
 {
 	proc_inode_cachep = kmem_cache_create("proc_inode_cache",
 					     sizeof(struct proc_inode),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (proc_inode_cachep == NULL)
 		return -ENOMEM;
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index d94d5960b..3ee238d29 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -84,17 +84,32 @@ static int proc_calc_metrics(char *page, char **start, off_t off,
 static int loadavg_read_proc(char *page, char **start, off_t off,
 				 int count, int *eof, void *data)
 {
+	unsigned int running, threads;
 	int a, b, c;
 	int len;
 
-	a = avenrun[0] + (FIXED_1/200);
-	b = avenrun[1] + (FIXED_1/200);
-	c = avenrun[2] + (FIXED_1/200);
-	len = sprintf(page,"%d.%02d %d.%02d %d.%02d %ld/%d %d\n",
+	if (vx_flags(VXF_VIRT_LOAD, 0)) {
+		struct vx_info *vxi = current->vx_info;
+
+		a = vxi->cvirt.load[0] + (FIXED_1/200);
+		b = vxi->cvirt.load[1] + (FIXED_1/200);
+		c = vxi->cvirt.load[2] + (FIXED_1/200);
+
+		running = atomic_read(&vxi->cvirt.nr_running);
+		threads = atomic_read(&vxi->cvirt.nr_threads);
+	} else {
+		a = avenrun[0] + (FIXED_1/200);
+		b = avenrun[1] + (FIXED_1/200);
+		c = avenrun[2] + (FIXED_1/200);
+
+		running = nr_running();
+		threads = nr_threads;
+	}
+	len = sprintf(page,"%d.%02d %d.%02d %d.%02d %d/%d %d\n",
 		LOAD_INT(a), LOAD_FRAC(a),
 		LOAD_INT(b), LOAD_FRAC(b),
 		LOAD_INT(c), LOAD_FRAC(c),
-		nr_running(), nr_threads, last_pid);
+		running, threads, last_pid);
 	return proc_calc_metrics(page, start, off, count, eof, len);
 }
 
@@ -547,70 +562,6 @@ static int execdomains_read_proc(char *page, char **start, off_t off,
 	return proc_calc_metrics(page, start, off, count, eof, len);
 }
 
-/*
- * This function accesses profiling information. The returned data is
- * binary: the sampling step and the actual contents of the profile
- * buffer. Use of the program readprofile is recommended in order to
- * get meaningful info out of these data.
- */
-static ssize_t
-read_profile(struct file *file, char __user *buf, size_t count, loff_t *ppos)
-{
-	unsigned long p = *ppos;
-	ssize_t read;
-	char * pnt;
-	unsigned int sample_step = 1 << prof_shift;
-
-	if (p >= (prof_len+1)*sizeof(unsigned int))
-		return 0;
-	if (count > (prof_len+1)*sizeof(unsigned int) - p)
-		count = (prof_len+1)*sizeof(unsigned int) - p;
-	read = 0;
-
-	while (p < sizeof(unsigned int) && count > 0) {
-		put_user(*((char *)(&sample_step)+p),buf);
-		buf++; p++; count--; read++;
-	}
-	pnt = (char *)prof_buffer + p - sizeof(unsigned int);
-	if (copy_to_user(buf,(void *)pnt,count))
-		return -EFAULT;
-	read += count;
-	*ppos += read;
-	return read;
-}
-
-/*
- * Writing to /proc/profile resets the counters
- *
- * Writing a 'profiling multiplier' value into it also re-sets the profiling
- * interrupt frequency, on architectures that support this.
- */
-static ssize_t write_profile(struct file *file, const char __user *buf,
-			     size_t count, loff_t *ppos)
-{
-#ifdef CONFIG_SMP
-	extern int setup_profiling_timer (unsigned int multiplier);
-
-	if (count == sizeof(int)) {
-		unsigned int multiplier;
-
-		if (copy_from_user(&multiplier, buf, sizeof(int)))
-			return -EFAULT;
-
-		if (setup_profiling_timer(multiplier))
-			return -EINVAL;
-	}
-#endif
-
-	memset(prof_buffer, 0, prof_len * sizeof(*prof_buffer));
-	return count;
-}
-
-static struct file_operations proc_profile_operations = {
-	.read		= read_profile,
-	.write		= write_profile,
-};
-
 #ifdef CONFIG_MAGIC_SYSRQ
 /*
  * writing 'C' to /proc/sysrq-trigger is like sysrq-C
@@ -687,6 +638,9 @@ void __init proc_misc_init(void)
 #ifdef CONFIG_MODULES
 	create_seq_entry("modules", 0, &proc_modules_operations);
 #endif
+#ifdef CONFIG_SCHEDSTATS
+	create_seq_entry("schedstat", 0, &proc_schedstat_operations);
+#endif
 #ifdef CONFIG_PROC_KCORE
 	proc_root_kcore = create_proc_entry("kcore", S_IRUSR, NULL);
 	if (proc_root_kcore) {
@@ -695,13 +649,6 @@ void __init proc_misc_init(void)
 				(size_t)high_memory - PAGE_OFFSET + PAGE_SIZE;
 	}
 #endif
-	if (prof_on) {
-		entry = create_proc_entry("profile", S_IWUSR | S_IRUGO, NULL);
-		if (entry) {
-			entry->proc_fops = &proc_profile_operations;
-			entry->size = (1+prof_len) * sizeof(unsigned int);
-		}
-	}
 #ifdef CONFIG_MAGIC_SYSRQ
 	entry = create_proc_entry("sysrq-trigger", S_IWUSR, NULL);
 	if (entry)
diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c
index a0d4404cc..93cbcbaf6 100644
--- a/fs/proc/proc_tty.c
+++ b/fs/proc/proc_tty.c
@@ -15,9 +15,6 @@
 #include <linux/seq_file.h>
 #include <asm/bitops.h>
 
-extern struct tty_ldisc ldiscs[];
-
-
 static int tty_ldiscs_read_proc(char *page, char **start, off_t off,
 				int count, int *eof, void *data);
 
@@ -159,12 +156,15 @@ static int tty_ldiscs_read_proc(char *page, char **start, off_t off,
 	int	i;
 	int	len = 0;
 	off_t	begin = 0;
-
+	struct tty_ldisc *ld;
+	
 	for (i=0; i < NR_LDISCS; i++) {
-		if (!(ldiscs[i].flags & LDISC_FLAG_DEFINED))
+		ld = tty_ldisc_get(i);
+		if (ld == NULL)
 			continue;
 		len += sprintf(page+len, "%-10s %2d\n",
-			       ldiscs[i].name ? ldiscs[i].name : "???", i);
+			       ld->name ? ld->name : "???", i);
+		tty_ldisc_put(i);
 		if (len+begin > off+count)
 			break;
 		if (len+begin < off) {
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 6d8492bc6..6eac8db42 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -18,7 +18,7 @@
 #include <asm/bitops.h>
 #include <linux/smp_lock.h>
 
-struct proc_dir_entry *proc_net, *proc_bus, *proc_root_fs, *proc_root_driver;
+struct proc_dir_entry *proc_net, *proc_net_stat, *proc_bus, *proc_root_fs, *proc_root_driver;
 
 #ifdef CONFIG_SYSCTL
 struct proc_dir_entry *proc_sys_root;
@@ -56,6 +56,8 @@ void __init proc_root_init(void)
 	}
 	proc_misc_init();
 	proc_net = proc_mkdir("net", NULL);
+	proc_net_stat = proc_mkdir("net/stat", NULL);
+
 #ifdef CONFIG_SYSVIPC
 	proc_mkdir("sysvipc", NULL);
 #endif
@@ -161,5 +163,6 @@ 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 --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index bbdfc9431..7998fa562 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -6,27 +6,11 @@
 
 char *task_mem(struct mm_struct *mm, char *buffer)
 {
-	unsigned long data = 0, stack = 0, exec = 0, lib = 0;
-	struct vm_area_struct *vma;
+	unsigned long data, text, lib;
 
-	down_read(&mm->mmap_sem);
-	for (vma = mm->mmap; vma; vma = vma->vm_next) {
-		unsigned long len = (vma->vm_end - vma->vm_start) >> 10;
-		if (!vma->vm_file) {
-			data += len;
-			if (vma->vm_flags & VM_GROWSDOWN)
-				stack += len;
-			continue;
-		}
-		if (vma->vm_flags & VM_WRITE)
-			continue;
-		if (vma->vm_flags & VM_EXEC) {
-			exec += len;
-			if (vma->vm_flags & VM_EXECUTABLE)
-				continue;
-			lib += len;
-		}
-	}
+	data = mm->total_vm - mm->shared_vm - mm->stack_vm;
+	text = (mm->end_code - mm->start_code) >> 10;
+	lib = (mm->exec_vm << (PAGE_SHIFT-10)) - text;
 	buffer += sprintf(buffer,
 		"VmSize:\t%8lu kB\n"
 		"VmLck:\t%8lu kB\n"
@@ -35,12 +19,11 @@ char *task_mem(struct mm_struct *mm, char *buffer)
 		"VmStk:\t%8lu kB\n"
 		"VmExe:\t%8lu kB\n"
 		"VmLib:\t%8lu kB\n",
-		mm->total_vm << (PAGE_SHIFT-10),
+		(mm->total_vm - mm->reserved_vm) << (PAGE_SHIFT-10),
 		mm->locked_vm << (PAGE_SHIFT-10),
 		mm->rss << (PAGE_SHIFT-10),
-		data - stack, stack,
-		exec - lib, lib);
-	up_read(&mm->mmap_sem);
+		data << (PAGE_SHIFT-10),
+		mm->stack_vm << (PAGE_SHIFT-10), text, lib);
 	return buffer;
 }
 
@@ -52,28 +35,11 @@ unsigned long task_vsize(struct mm_struct *mm)
 int task_statm(struct mm_struct *mm, int *shared, int *text,
 	       int *data, int *resident)
 {
-	struct vm_area_struct *vma;
-	int size = 0;
-
+	*shared = mm->shared_vm;
+	*text = (mm->end_code - mm->start_code) >> PAGE_SHIFT;
+	*data = mm->total_vm - mm->shared_vm - *text;
 	*resident = mm->rss;
-	for (vma = mm->mmap; vma; vma = vma->vm_next) {
-		int pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
-
-		size += pages;
-		if (is_vm_hugetlb_page(vma)) {
-			if (!(vma->vm_flags & VM_DONTCOPY))
-				*shared += pages;
-			continue;
-		}
-		if (vma->vm_file)
-			*shared += pages;
-		if (vma->vm_flags & VM_EXECUTABLE)
-			*text += pages;
-		else
-			*data += pages;
-	}
-
-	return size;
+	return mm->total_vm;
 }
 
 static int show_map(struct seq_file *m, void *v)
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
index 126db9797..275dedc91 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
@@ -68,11 +68,12 @@ unsigned long task_vsize(struct mm_struct *mm)
 	struct mm_tblock_struct *tbp;
 	unsigned long vsize = 0;
 
+	down_read(&mm->mmap_sem);
 	for (tbp = &mm->context.tblock; tbp; tbp = tbp->next) {
 		if (tbp->rblock)
 			vsize += kobjsize(tbp->rblock->kblock);
 	}
-
+	up_read(&mm->mmap_sem);
 	return vsize;
 }
 
@@ -81,7 +82,8 @@ int task_statm(struct mm_struct *mm, int *shared, int *text,
 {
 	struct mm_tblock_struct *tbp;
 	int size = kobjsize(mm);
-	
+
+	down_read(&mm->mmap_sem);
 	for (tbp = &mm->context.tblock; tbp; tbp = tbp->next) {
 		if (tbp->next)
 			size += kobjsize(tbp->next);
@@ -93,7 +95,7 @@ int task_statm(struct mm_struct *mm, int *shared, int *text,
 
 	size += (*text = mm->end_code - mm->start_code);
 	size += (*data = mm->start_stack - mm->start_data);
-
+	up_read(&mm->mmap_sem);
 	*resident = size;
 	return size;
 }
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index 19b7d5a05..664bb1464 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -78,7 +78,7 @@ static void qnx4_write_super(struct super_block *sb)
 	unlock_kernel();
 }
 
-static void qnx4_write_inode(struct inode *inode, int unused)
+static int qnx4_write_inode(struct inode *inode, int unused)
 {
 	struct qnx4_inode_entry *raw_inode;
 	int block, ino;
@@ -87,12 +87,12 @@ static void qnx4_write_inode(struct inode *inode, int unused)
 
 	QNX4DEBUG(("qnx4: write inode 1.\n"));
 	if (inode->i_nlink == 0) {
-		return;
+		return 0;
 	}
 	if (!ino) {
 		printk("qnx4: bad inode number on dev %s: %d is out of range\n",
 		       inode->i_sb->s_id, ino);
-		return;
+		return -EIO;
 	}
 	QNX4DEBUG(("qnx4: write inode 2.\n"));
 	block = ino / QNX4_INODES_PER_BLOCK;
@@ -101,7 +101,7 @@ static void qnx4_write_inode(struct inode *inode, int unused)
 		printk("qnx4: major problem: unable to read inode from dev "
 		       "%s\n", inode->i_sb->s_id);
 		unlock_kernel();
-		return;
+		return -EIO;
 	}
 	raw_inode = ((struct qnx4_inode_entry *) bh->b_data) +
 	    (ino % QNX4_INODES_PER_BLOCK);
@@ -117,6 +117,7 @@ static void qnx4_write_inode(struct inode *inode, int unused)
 	mark_buffer_dirty(bh);
 	brelse(bh);
 	unlock_kernel();
+	return 0;
 }
 
 #endif
@@ -544,7 +545,7 @@ static int init_inodecache(void)
 {
 	qnx4_inode_cachep = kmem_cache_create("qnx4_inode_cache",
 					     sizeof(struct qnx4_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (qnx4_inode_cachep == NULL)
 		return -ENOMEM;
diff --git a/fs/quota_v1.c b/fs/quota_v1.c
index 7c7de9102..a6cffdab7 100644
--- a/fs/quota_v1.c
+++ b/fs/quota_v1.c
@@ -115,8 +115,8 @@ out:
 
 /* Header of new quota format */
 struct v2_disk_dqheader {
-	__u32 dqh_magic;        /* Magic number identifying file */
-	__u32 dqh_version;      /* File version */
+	__le32 dqh_magic;        /* Magic number identifying file */
+	__le32 dqh_version;      /* File version */
 };
 
 static int v1_check_quota_file(struct super_block *sb, int type)
diff --git a/fs/quota_v2.c b/fs/quota_v2.c
index 679d31aca..e12ca82ce 100644
--- a/fs/quota_v2.c
+++ b/fs/quota_v2.c
@@ -357,7 +357,7 @@ static int do_insert_tree(struct dquot *dquot, uint *treeblk, int depth)
 	struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
 	dqbuf_t buf;
 	int ret = 0, newson = 0, newact = 0;
-	u32 *ref;
+	__le32 *ref;
 	uint newblk;
 
 	if (!(buf = getdqbuf()))
@@ -376,14 +376,14 @@ static int do_insert_tree(struct dquot *dquot, uint *treeblk, int depth)
 			goto out_buf;
 		}
 	}
-	ref = (u32 *)buf;
+	ref = (__le32 *)buf;
 	newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
 	if (!newblk)
 		newson = 1;
 	if (depth == V2_DQTREEDEPTH-1) {
 #ifdef __QUOTA_V2_PARANOIA
 		if (newblk) {
-			printk(KERN_ERR "VFS: Inserting already present quota entry (block %u).\n", ref[GETIDINDEX(dquot->dq_id, depth)]);
+			printk(KERN_ERR "VFS: Inserting already present quota entry (block %u).\n", le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]));
 			ret = -EIO;
 			goto out_buf;
 		}
@@ -510,7 +510,7 @@ static int remove_tree(struct dquot *dquot, uint *blk, int depth)
 	dqbuf_t buf = getdqbuf();
 	int ret = 0;
 	uint newblk;
-	u32 *ref = (u32 *)buf;
+	__le32 *ref = (__le32 *)buf;
 	
 	if (!buf)
 		return -ENOMEM;
@@ -595,7 +595,7 @@ static loff_t find_tree_dqentry(struct dquot *dquot, uint blk, int depth)
 	struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
 	dqbuf_t buf = getdqbuf();
 	loff_t ret = 0;
-	u32 *ref = (u32 *)buf;
+	__le32 *ref = (__le32 *)buf;
 
 	if (!buf)
 		return -ENOMEM;
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index c8e04d6c5..fd4353f2d 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -31,6 +31,7 @@
 #include <linux/string.h>
 #include <linux/smp_lock.h>
 #include <linux/backing-dev.h>
+#include <linux/ramfs.h>
 
 #include <asm/uaccess.h>
 
@@ -39,7 +40,6 @@
 
 static struct super_operations ramfs_ops;
 static struct address_space_operations ramfs_aops;
-static struct file_operations ramfs_file_operations;
 static struct inode_operations ramfs_file_inode_operations;
 static struct inode_operations ramfs_dir_inode_operations;
 
@@ -48,7 +48,7 @@ static struct backing_dev_info ramfs_backing_dev_info = {
 	.memory_backed	= 1,	/* Does not contribute to dirty memory */
 };
 
-static struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
+struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
 {
 	struct inode * inode = new_inode(sb);
 
@@ -146,7 +146,7 @@ static struct address_space_operations ramfs_aops = {
 	.commit_write	= simple_commit_write
 };
 
-static struct file_operations ramfs_file_operations = {
+struct file_operations ramfs_file_operations = {
 	.read		= generic_file_read,
 	.write		= generic_file_write,
 	.mmap		= generic_file_mmap,
@@ -199,7 +199,7 @@ static int ramfs_fill_super(struct super_block * sb, void * data, int silent)
 	return 0;
 }
 
-static struct super_block *ramfs_get_sb(struct file_system_type *fs_type,
+struct super_block *ramfs_get_sb(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *data)
 {
 	return get_sb_nodev(fs_type, flags, data, ramfs_fill_super);
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index f52b701fc..8ad8d877e 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -89,15 +89,16 @@ static int reiserfs_sync_file(
 			      ) {
   struct inode * p_s_inode = p_s_dentry->d_inode;
   int n_err;
-
-  reiserfs_write_lock(p_s_inode->i_sb);
+  int barrier_done;
 
   if (!S_ISREG(p_s_inode->i_mode))
       BUG ();
-
   n_err = sync_mapping_buffers(p_s_inode->i_mapping) ;
-  reiserfs_commit_for_inode(p_s_inode) ;
+  reiserfs_write_lock(p_s_inode->i_sb);
+  barrier_done = reiserfs_commit_for_inode(p_s_inode);
   reiserfs_write_unlock(p_s_inode->i_sb);
+  if (barrier_done != 1)
+      blkdev_issue_flush(p_s_inode->i_sb->s_bdev, NULL);
   return ( n_err < 0 ) ? -EIO : 0;
 }
 
@@ -1098,7 +1099,7 @@ ssize_t reiserfs_file_write( struct file *file, /* the file we are going to writ
 {
     size_t already_written = 0; // Number of bytes already written to the file.
     loff_t pos; // Current position in the file.
-    size_t res; // return value of various functions that we call.
+    ssize_t res; // return value of various functions that we call.
     struct inode *inode = file->f_dentry->d_inode; // Inode of the file that we are writing to.
 				/* To simplify coding at this time, we store
 				   locked pages in array for now */
@@ -1107,7 +1108,7 @@ ssize_t reiserfs_file_write( struct file *file, /* the file we are going to writ
     th.t_trans_id = 0;
 
     if ( file->f_flags & O_DIRECT) { // Direct IO needs treatment
-	int result, after_file_end = 0;
+	ssize_t result, after_file_end = 0;
 	if ( (*ppos + count >= inode->i_size) || (file->f_flags & O_APPEND) ) {
 	    /* If we are appending a file, we need to put this savelink in here.
 	       If we will crash while doing direct io, finish_unfinished will
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 8f983da39..72abbaa61 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -1514,7 +1514,7 @@ int reiserfs_encode_fh(struct dentry *dentry, __u32 *data, int *lenp, int need_p
 ** to properly mark inodes for datasync and such, but only actually
 ** does something when called for a synchronous update.
 */
-void reiserfs_write_inode (struct inode * inode, int do_sync) {
+int reiserfs_write_inode (struct inode * inode, int do_sync) {
     struct reiserfs_transaction_handle th ;
     int jbegin_count = 1 ;
 
@@ -1522,7 +1522,7 @@ void reiserfs_write_inode (struct inode * inode, int do_sync) {
         reiserfs_warning (inode->i_sb,
 			  "clm-6005: writing inode %lu on readonly FS",
 			  inode->i_ino) ;
-        return ;
+        return -EROFS;
     }
     /* memory pressure can sometimes initiate write_inode calls with sync == 1,
     ** these cases are just when the system needs ram, not when the 
@@ -1536,6 +1536,7 @@ void reiserfs_write_inode (struct inode * inode, int do_sync) {
 	journal_end_sync(&th, inode->i_sb, jbegin_count) ;
 	reiserfs_write_unlock(inode->i_sb);
     }
+    return 0;
 }
 
 /* FIXME: no need any more. right? */
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c
index 6885230ec..286d81214 100644
--- a/fs/reiserfs/ioctl.c
+++ b/fs/reiserfs/ioctl.c
@@ -64,7 +64,7 @@ int reiserfs_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
 				if( result )
 					return result;
 		}
-		
+
 		flags = flags & REISERFS_FL_USER_MODIFYABLE;
 		flags |= oldflags & ~REISERFS_FL_USER_MODIFYABLE;
 		sd_attrs_to_i_attrs( flags, inode );
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 7ced01070..6f8051f2e 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -127,6 +127,12 @@ static int reiserfs_clean_and_file_buffer(struct buffer_head *bh) {
   return 0 ;
 }
 
+static void disable_barrier(struct super_block *s)
+{
+    REISERFS_SB(s)->s_mount_opt &= ~(1 << REISERFS_BARRIER_FLUSH);
+    printk("reiserfs: disabling flush barriers on %s\n", reiserfs_bdevname(s));
+}
+
 static struct reiserfs_bitmap_node *
 allocate_bitmap_node(struct super_block *p_s_sb) {
   struct reiserfs_bitmap_node *bn ;
@@ -640,6 +646,26 @@ static void submit_ordered_buffer(struct buffer_head *bh) {
     submit_bh(WRITE, bh) ;
 }
 
+static int submit_barrier_buffer(struct buffer_head *bh) {
+    get_bh(bh) ;
+    bh->b_end_io = reiserfs_end_ordered_io;
+    clear_buffer_dirty(bh) ;
+    if (!buffer_uptodate(bh))
+        BUG();
+    return submit_bh(WRITE_BARRIER, bh) ;
+}
+
+static void check_barrier_completion(struct super_block *s,
+                                     struct buffer_head *bh) {
+    if (buffer_eopnotsupp(bh)) {
+	clear_buffer_eopnotsupp(bh);
+	disable_barrier(s);
+	set_buffer_uptodate(bh);
+	set_buffer_dirty(bh);
+	sync_dirty_buffer(bh);
+    }
+}
+
 #define CHUNK_SIZE 32
 struct buffer_chunk {
     struct buffer_head *bh[CHUNK_SIZE];
@@ -909,6 +935,7 @@ static int flush_commit_list(struct super_block *s, struct reiserfs_journal_list
   int bn ;
   struct buffer_head *tbh = NULL ;
   unsigned long trans_id = jl->j_trans_id;
+  int barrier = 0;
 
   reiserfs_check_lock_depth(s, "flush_commit_list") ;
 
@@ -973,7 +1000,20 @@ static int flush_commit_list(struct super_block *s, struct reiserfs_journal_list
   }
   atomic_dec(&SB_JOURNAL(s)->j_async_throttle);
 
-  /* wait on everything written so far before writing the commit */
+  /* wait on everything written so far before writing the commit
+   * if we are in barrier mode, send the commit down now
+   */
+  barrier = reiserfs_barrier_flush(s);
+  if (barrier) {
+      int ret;
+      lock_buffer(jl->j_commit_bh);
+      ret = submit_barrier_buffer(jl->j_commit_bh);
+      if (ret == -EOPNOTSUPP) {
+	  set_buffer_uptodate(jl->j_commit_bh);
+          disable_barrier(s);
+	  barrier = 0;
+      }
+  }
   for (i = 0 ;  i < (jl->j_len + 1) ; i++) {
     bn = SB_ONDISK_JOURNAL_1st_BLOCK(s) +
 	 (jl->j_start + i) % SB_ONDISK_JOURNAL_SIZE(s) ;
@@ -995,10 +1035,15 @@ static int flush_commit_list(struct super_block *s, struct reiserfs_journal_list
   if (atomic_read(&(jl->j_commit_left)) != 1)
     BUG();
 
-  if (buffer_dirty(jl->j_commit_bh))
-    BUG();
-  mark_buffer_dirty(jl->j_commit_bh) ;
-  sync_dirty_buffer(jl->j_commit_bh) ;
+  if (!barrier) {
+      if (buffer_dirty(jl->j_commit_bh))
+	BUG();
+      mark_buffer_dirty(jl->j_commit_bh) ;
+      sync_dirty_buffer(jl->j_commit_bh) ;
+  } else
+      wait_on_buffer(jl->j_commit_bh);
+
+  check_barrier_completion(s, jl->j_commit_bh);
   if (!buffer_uptodate(jl->j_commit_bh)) {
     reiserfs_panic(s, "journal-615: buffer write failed\n") ;
   }
@@ -1098,8 +1143,23 @@ static int _update_journal_header_block(struct super_block *p_s_sb, unsigned lon
     jh->j_last_flush_trans_id = cpu_to_le32(trans_id) ;
     jh->j_first_unflushed_offset = cpu_to_le32(offset) ;
     jh->j_mount_id = cpu_to_le32(SB_JOURNAL(p_s_sb)->j_mount_id) ;
-    set_buffer_dirty(SB_JOURNAL(p_s_sb)->j_header_bh) ;
-    sync_dirty_buffer(SB_JOURNAL(p_s_sb)->j_header_bh) ;
+
+    if (reiserfs_barrier_flush(p_s_sb)) {
+	int ret;
+	lock_buffer(SB_JOURNAL(p_s_sb)->j_header_bh);
+	ret = submit_barrier_buffer(SB_JOURNAL(p_s_sb)->j_header_bh);
+	if (ret == -EOPNOTSUPP) {
+	    set_buffer_uptodate(SB_JOURNAL(p_s_sb)->j_header_bh);
+	    disable_barrier(p_s_sb);
+	    goto sync;
+	}
+	wait_on_buffer(SB_JOURNAL(p_s_sb)->j_header_bh);
+	check_barrier_completion(p_s_sb, SB_JOURNAL(p_s_sb)->j_header_bh);
+    } else {
+sync:
+	set_buffer_dirty(SB_JOURNAL(p_s_sb)->j_header_bh) ;
+	sync_dirty_buffer(SB_JOURNAL(p_s_sb)->j_header_bh) ;
+    }
     if (!buffer_uptodate(SB_JOURNAL(p_s_sb)->j_header_bh)) {
       reiserfs_warning (p_s_sb, "journal-837: IO error during journal replay");
       return -EIO ;
@@ -3184,11 +3244,16 @@ void reiserfs_update_inode_transaction(struct inode *inode) {
   REISERFS_I(inode)->i_trans_id = SB_JOURNAL(inode->i_sb)->j_trans_id ;
 }
 
-static void __commit_trans_jl(struct inode *inode, unsigned long id,
+/*
+ * returns -1 on error, 0 if no commits/barriers were done and 1
+ * if a transaction was actually committed and the barrier was done
+ */
+static int __commit_trans_jl(struct inode *inode, unsigned long id,
                                  struct reiserfs_journal_list *jl)
 {
     struct reiserfs_transaction_handle th ;
     struct super_block *sb = inode->i_sb ;
+    int ret = 0;
 
     /* is it from the current transaction, or from an unknown transaction? */
     if (id == SB_JOURNAL(sb)->j_trans_id) {
@@ -3210,6 +3275,7 @@ static void __commit_trans_jl(struct inode *inode, unsigned long id,
 	}
 
 	journal_end_sync(&th, sb, 1) ;
+	ret = 1;
 
     } else {
 	/* this gets tricky, we have to make sure the journal list in
@@ -3218,13 +3284,21 @@ static void __commit_trans_jl(struct inode *inode, unsigned long id,
 	 */
 flush_commit_only:
 	if (journal_list_still_alive(inode->i_sb, id)) {
+	    /*
+	     * we only set ret to 1 when we know for sure
+	     * the barrier hasn't been started yet on the commit
+	     * block.
+	     */
+	    if (atomic_read(&jl->j_commit_left) > 1)
+	        ret = 1;
 	    flush_commit_list(sb, jl, 1) ;
 	}
     }
     /* otherwise the list is gone, and long since committed */
+    return ret;
 }
 
-void reiserfs_commit_for_inode(struct inode *inode) {
+int reiserfs_commit_for_inode(struct inode *inode) {
     unsigned long id = REISERFS_I(inode)->i_trans_id;
     struct reiserfs_journal_list *jl = REISERFS_I(inode)->i_jl;
 
@@ -3237,7 +3311,7 @@ void reiserfs_commit_for_inode(struct inode *inode) {
 	/* jl will be updated in __commit_trans_jl */
     }
 
-    __commit_trans_jl(inode, id, jl);
+   return __commit_trans_jl(inode, id, jl);
 }
 
 void reiserfs_restore_prepared_buffer(struct super_block *p_s_sb, 
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 71eaa0651..3a7f6c64c 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -444,7 +444,7 @@ static int init_inodecache(void)
 {
 	reiserfs_inode_cachep = kmem_cache_create("reiser_inode_cache",
 					     sizeof(struct reiserfs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (reiserfs_inode_cachep == NULL)
 		return -ENOMEM;
@@ -549,6 +549,13 @@ static const arg_desc_t logging_mode[] = {
     {NULL, 0}
 };
 
+/* possible values for -o barrier= */
+static const arg_desc_t barrier_mode[] = {
+    {"none", 1<<REISERFS_BARRIER_NONE, 1<<REISERFS_BARRIER_FLUSH},
+    {"flush", 1<<REISERFS_BARRIER_FLUSH, 1<<REISERFS_BARRIER_NONE},
+    {NULL, 0}
+};
+
 /* possible values for "-o block-allocator=" and bits which are to be set in
    s_mount_opt of reiserfs specific part of in-core super block */
 static const arg_desc_t balloc[] = {
@@ -712,6 +719,7 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st
 	{"replayonly",	.setmask = 1<<REPLAYONLY},
 	{"block-allocator", .arg_required = 'a', .values = balloc},
 	{"data",	.arg_required = 'd', .values = logging_mode},
+	{"barrier",	.arg_required = 'b', .values = barrier_mode},
 	{"resize",	.arg_required = 'r', .values = NULL},
 	{"jdev",	.arg_required = 'j', .values = NULL},
 	{"nolargeio",	.arg_required = 'w', .values = NULL},
@@ -811,6 +819,23 @@ static void handle_data_mode(struct super_block *s, unsigned long mount_options)
     }
 }
 
+static void handle_barrier_mode(struct super_block *s, unsigned long bits) {
+    int flush = (1 << REISERFS_BARRIER_FLUSH);
+    int none = (1 << REISERFS_BARRIER_NONE);
+    int all_barrier = flush | none;
+
+    if (bits & all_barrier) {
+        REISERFS_SB(s)->s_mount_opt &= ~all_barrier;
+	if (bits & flush) {
+	    REISERFS_SB(s)->s_mount_opt |= flush;
+	    printk("reiserfs: enabling write barrier flush mode\n");
+	} else if (bits & none) {
+	    REISERFS_SB(s)->s_mount_opt |= none;
+	    printk("reiserfs: write barriers turned off\n");
+	}
+   }
+}
+
 static void handle_attrs( struct super_block *s )
 {
 	struct reiserfs_super_block * rs;
@@ -855,6 +880,8 @@ static int reiserfs_remount (struct super_block * s, int * mount_flags, char * a
   safe_mask |= 1 << REISERFS_ATTRS;
   safe_mask |= 1 << REISERFS_XATTRS_USER;
   safe_mask |= 1 << REISERFS_POSIXACL;
+  safe_mask |= 1 << REISERFS_BARRIER_FLUSH;
+  safe_mask |= 1 << REISERFS_BARRIER_NONE;
 
   /* Update the bitmask, taking care to keep
    * the bits we're not allowed to change here */
@@ -901,6 +928,7 @@ static int reiserfs_remount (struct super_block * s, int * mount_flags, char * a
     }
 
     handle_data_mode(s, mount_options);
+    handle_barrier_mode(s, mount_options);
     REISERFS_SB(s)->s_mount_state = sb_umount_state(rs) ;
     s->s_flags &= ~MS_RDONLY ; /* now it is safe to call journal_begin */
     journal_begin(&th, s, 10) ;
@@ -1414,6 +1442,9 @@ static int reiserfs_fill_super (struct super_block * s, void * data, int silent)
     } else {
         reiserfs_info (s, "using writeback data mode\n");
     }
+    if (reiserfs_barrier_flush(s)) {
+    	printk("reiserfs: using flush barriers\n");
+    }
 
     // set_device_ro(s->s_dev, 1) ;
     if( journal_init(s, jdev_name, old_format, commit_max_age) ) {
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 7ef7b4545..39d0d9630 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -589,8 +589,14 @@ open_file:
             break;
     }
 
-    inode->i_ctime = CURRENT_TIME;
-    mark_inode_dirty (inode);
+    /* We can't mark the inode dirty if it's not hashed. This is the case
+     * when we're inheriting the default ACL. If we dirty it, the inode
+     * gets marked dirty, but won't (ever) make it onto the dirty list until
+     * it's synced explicitly to clear I_DIRTY. This is bad. */
+    if (!hlist_unhashed(&inode->i_hash)) {
+        inode->i_ctime = CURRENT_TIME;
+        mark_inode_dirty (inode);
+    }
 
 out_filp:
     up (&xinode->i_sem);
@@ -761,6 +767,11 @@ reiserfs_xattr_del (struct inode *inode, const char *name)
     err = __reiserfs_xattr_del (dir, name, strlen (name));
     dput (dir);
 
+    if (!err) {
+        inode->i_ctime = CURRENT_TIME;
+        mark_inode_dirty (inode);
+    }
+
 out:
     return err;
 }
@@ -1240,8 +1251,10 @@ xattr_lookup_poison (struct dentry *dentry, struct qstr *q1, struct qstr *name)
         name->hash == priv_root->d_name.hash &&
         !memcmp (name->name, priv_root->d_name.name, name->len)) {
             return -ENOENT;
-    }
-    return 0;
+    } else if (q1->len == name->len &&
+               !memcmp(q1->name, name->name, name->len))
+        return 0;
+    return 1;
 }
 
 static struct dentry_operations xattr_lookup_poison_ops = {
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index 623139f06..b600930ff 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -289,8 +289,14 @@ reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
             error = reiserfs_xattr_set(inode, name, value, size, 0);
 	} else {
             error = reiserfs_xattr_del (inode, name);
-            if (error == -ENODATA)
+            if (error == -ENODATA) {
+                /* This may seem odd here, but it means that the ACL was set
+                 * with a value representable with mode bits. If there was
+                 * an ACL before, reiserfs_xattr_del already dirtied the inode.
+                 */
+                mark_inode_dirty (inode);
                 error = 0;
+            }
         }
 
 	if (value)
@@ -502,11 +508,11 @@ posix_acl_access_list (struct inode *inode, const char *name, int namelen, char
 }
 
 struct reiserfs_xattr_handler posix_acl_access_handler = {
-    prefix: XATTR_NAME_ACL_ACCESS,
-    get: posix_acl_access_get,
-    set: posix_acl_access_set,
-    del: posix_acl_access_del,
-    list: posix_acl_access_list,
+	.prefix = XATTR_NAME_ACL_ACCESS,
+	.get = posix_acl_access_get,
+	.set = posix_acl_access_set,
+	.del = posix_acl_access_del,
+	.list = posix_acl_access_list,
 };
 
 static int
@@ -555,9 +561,9 @@ posix_acl_default_list (struct inode *inode, const char *name, int namelen, char
 }
 
 struct reiserfs_xattr_handler posix_acl_default_handler = {
-    prefix: XATTR_NAME_ACL_DEFAULT,
-    get: posix_acl_default_get,
-    set: posix_acl_default_set,
-    del: posix_acl_default_del,
-    list: posix_acl_default_list,
+	.prefix = XATTR_NAME_ACL_DEFAULT,
+	.get = posix_acl_default_get,
+	.set = posix_acl_default_set,
+	.del = posix_acl_default_del,
+	.list = posix_acl_default_list,
 };
diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c
index eacbdca43..e044d5117 100644
--- a/fs/reiserfs/xattr_security.c
+++ b/fs/reiserfs/xattr_security.c
@@ -61,9 +61,9 @@ security_list (struct inode *inode, const char *name, int namelen, char *out)
 
 
 struct reiserfs_xattr_handler security_handler = {
-    prefix: XATTR_SECURITY_PREFIX,
-    get: security_get,
-    set: security_set,
-    del: security_del,
-    list: security_list,
+	.prefix = XATTR_SECURITY_PREFIX,
+	.get = security_get,
+	.set = security_set,
+	.del = security_del,
+	.list = security_list,
 };
diff --git a/fs/reiserfs/xattr_trusted.c b/fs/reiserfs/xattr_trusted.c
index 39a10ec8c..43762197f 100644
--- a/fs/reiserfs/xattr_trusted.c
+++ b/fs/reiserfs/xattr_trusted.c
@@ -73,9 +73,9 @@ trusted_list (struct inode *inode, const char *name, int namelen, char *out)
 
 
 struct reiserfs_xattr_handler trusted_handler = {
-    prefix: XATTR_TRUSTED_PREFIX,
-    get: trusted_get,
-    set: trusted_set,
-    del: trusted_del,
-    list: trusted_list,
+	.prefix = XATTR_TRUSTED_PREFIX,
+	.get = trusted_get,
+	.set = trusted_set,
+	.del = trusted_del,
+	.list = trusted_list,
 };
diff --git a/fs/reiserfs/xattr_user.c b/fs/reiserfs/xattr_user.c
index 38779f3fd..077280646 100644
--- a/fs/reiserfs/xattr_user.c
+++ b/fs/reiserfs/xattr_user.c
@@ -91,9 +91,9 @@ user_list (struct inode *inode, const char *name, int namelen, char *out)
 }
 
 struct reiserfs_xattr_handler user_handler = {
-    prefix: XATTR_USER_PREFIX,
-    get: user_get,
-    set: user_set,
-    del: user_del,
-    list: user_list,
+	.prefix = XATTR_USER_PREFIX,
+	.get = user_get,
+	.set = user_set,
+	.del = user_del,
+	.list = user_list,
 };
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c
index 28c863a2e..3076d56f6 100644
--- a/fs/romfs/inode.c
+++ b/fs/romfs/inode.c
@@ -95,15 +95,16 @@ static inline struct romfs_inode_info *ROMFS_I(struct inode *inode)
 	return list_entry(inode, struct romfs_inode_info, vfs_inode);
 }
 
-static __s32
+static __u32
 romfs_checksum(void *data, int size)
 {
-	__s32 sum, *ptr;
+	__u32 sum;
+	__be32 *ptr;
 
 	sum = 0; ptr = data;
 	size>>=2;
 	while (size>0) {
-		sum += ntohl(*ptr++);
+		sum += be32_to_cpu(*ptr++);
 		size--;
 	}
 	return sum;
@@ -131,7 +132,7 @@ static int romfs_fill_super(struct super_block *s, void *data, int silent)
 	}
 
 	rsb = (struct romfs_super_block *)bh->b_data;
-	sz = ntohl(rsb->size);
+	sz = be32_to_cpu(rsb->size);
 	if (rsb->word0 != ROMSB_WORD0 || rsb->word1 != ROMSB_WORD1
 	   || sz < ROMFH_SIZE) {
 		if (!silent)
@@ -292,7 +293,7 @@ romfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 		offset = i->i_ino & ROMFH_MASK;
 		if (romfs_copyfrom(i, &ri, offset, ROMFH_SIZE) <= 0)
 			goto out;
-		offset = ntohl(ri.spec) & ROMFH_MASK;
+		offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
 	}
 
 	/* Not really failsafe, but we are read-only... */
@@ -316,9 +317,9 @@ romfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 		romfs_copyfrom(i, fsname, offset+ROMFH_SIZE, j);
 
 		ino = offset;
-		nextfh = ntohl(ri.next);
+		nextfh = be32_to_cpu(ri.next);
 		if ((nextfh & ROMFH_TYPE) == ROMFH_HRD)
-			ino = ntohl(ri.spec);
+			ino = be32_to_cpu(ri.spec);
 		if (filldir(dirent, fsname, j, offset, ino,
 			    romfs_dtype_table[nextfh & ROMFH_TYPE]) < 0) {
 			goto out;
@@ -349,7 +350,7 @@ romfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 		goto out;
 
 	maxoff = romfs_maxsize(dir->i_sb);
-	offset = ntohl(ri.spec) & ROMFH_MASK;
+	offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
 
 	/* OK, now find the file whose name is in "dentry" in the
 	 * directory specified by "dir".  */
@@ -382,12 +383,12 @@ romfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 			}
 		}
 		/* next entry */
-		offset = ntohl(ri.next) & ROMFH_MASK;
+		offset = be32_to_cpu(ri.next) & ROMFH_MASK;
 	}
 
 	/* Hard link handling */
-	if ((ntohl(ri.next) & ROMFH_TYPE) == ROMFH_HRD)
-		offset = ntohl(ri.spec) & ROMFH_MASK;
+	if ((be32_to_cpu(ri.next) & ROMFH_TYPE) == ROMFH_HRD)
+		offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
 
 	if ((inode = iget(dir->i_sb, offset)))
 		goto outi;
@@ -495,15 +496,15 @@ romfs_read_inode(struct inode *i)
 		}
 		/* XXX: do romfs_checksum here too (with name) */
 
-		nextfh = ntohl(ri.next);
+		nextfh = be32_to_cpu(ri.next);
 		if ((nextfh & ROMFH_TYPE) != ROMFH_HRD)
 			break;
 
-		ino = ntohl(ri.spec) & ROMFH_MASK;
+		ino = be32_to_cpu(ri.spec) & ROMFH_MASK;
 	}
 
 	i->i_nlink = 1;		/* Hard to decide.. */
-	i->i_size = ntohl(ri.size);
+	i->i_size = be32_to_cpu(ri.size);
 	i->i_mtime.tv_sec = i->i_atime.tv_sec = i->i_ctime.tv_sec = 0;
 	i->i_mtime.tv_nsec = i->i_atime.tv_nsec = i->i_ctime.tv_nsec = 0;
 	i->i_uid = i->i_gid = 0;
@@ -544,7 +545,7 @@ romfs_read_inode(struct inode *i)
 			break;
 		default:
 			/* depending on MBZ for sock/fifos */
-			nextfh = ntohl(ri.spec);
+			nextfh = be32_to_cpu(ri.spec);
 			init_special_inode(i, ino,
 					MKDEV(nextfh>>16,nextfh&0xffff));
 	}
@@ -579,7 +580,7 @@ static int init_inodecache(void)
 {
 	romfs_inode_cachep = kmem_cache_create("romfs_inode_cache",
 					     sizeof(struct romfs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (romfs_inode_cachep == NULL)
 		return -ENOMEM;
diff --git a/fs/select.c b/fs/select.c
index 16fc1ef95..dfff0ad1b 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -118,15 +118,11 @@ void __pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *
 	}
 }
 
+#define FDS_IN(fds, n)		(fds->in + n)
+#define FDS_OUT(fds, n)		(fds->out + n)
+#define FDS_EX(fds, n)		(fds->ex + n)
 
-#define __IN(fds, n)		(fds->in + n)
-#define __OUT(fds, n)		(fds->out + n)
-#define __EX(fds, n)		(fds->ex + n)
-#define __RES_IN(fds, n)	(fds->res_in + n)
-#define __RES_OUT(fds, n)	(fds->res_out + n)
-#define __RES_EX(fds, n)	(fds->res_ex + n)
-
-#define BITS(fds, n)		(*__IN(fds, n)|*__OUT(fds, n)|*__EX(fds, n))
+#define BITS(fds, n)	(*FDS_IN(fds, n)|*FDS_OUT(fds, n)|*FDS_EX(fds, n))
 
 static int max_select_fd(unsigned long n, fd_set_bits *fds)
 {
@@ -377,9 +373,10 @@ sys_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, s
 		ret = 0;
 	}
 
-	set_fd_set(n, inp, fds.res_in);
-	set_fd_set(n, outp, fds.res_out);
-	set_fd_set(n, exp, fds.res_ex);
+	if (set_fd_set(n, inp, fds.res_in) ||
+	    set_fd_set(n, outp, fds.res_out) ||
+	    set_fd_set(n, exp, fds.res_ex))
+		ret = -EFAULT;
 
 out:
 	select_bits_free(bits, size);
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index c8ca98ab2..1001a64b3 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -80,7 +80,7 @@ static int init_inodecache(void)
 {
 	smb_inode_cachep = kmem_cache_create("smb_inode_cache",
 					     sizeof(struct smb_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (smb_inode_cachep == NULL)
 		return -ENOMEM;
diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c
index 8096d7492..418c0c36a 100644
--- a/fs/smbfs/proc.c
+++ b/fs/smbfs/proc.c
@@ -2076,6 +2076,8 @@ out:
 
 void smb_decode_unix_basic(struct smb_fattr *fattr, char *p)
 {
+	u64 size, disk_bytes;
+
 	/* FIXME: verify nls support. all is sent as utf8? */
 
 	fattr->f_unix = 1;
@@ -2093,8 +2095,19 @@ void smb_decode_unix_basic(struct smb_fattr *fattr, char *p)
 	/* 84 L permissions */
 	/* 92 L link count */
 
-	fattr->f_size = LVAL(p, 0);
-	fattr->f_blocks = LVAL(p, 8);
+	size = LVAL(p, 0);
+	disk_bytes = LVAL(p, 8);
+
+	/*
+	 * Some samba versions round up on-disk byte usage
+	 * to 1MB boundaries, making it useless. When seeing
+	 * that, use the size instead.
+	 */
+	if (!(disk_bytes & 0xfffff))
+		disk_bytes = size+511;
+
+	fattr->f_size = size;
+	fattr->f_blocks = disk_bytes >> 9;
 	fattr->f_ctime = smb_ntutc2unixutc(LVAL(p, 16));
 	fattr->f_atime = smb_ntutc2unixutc(LVAL(p, 24));
 	fattr->f_mtime = smb_ntutc2unixutc(LVAL(p, 32));
diff --git a/fs/super.c b/fs/super.c
index 37b76d7cf..998fc473e 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -118,6 +118,27 @@ int __put_super(struct super_block *sb)
 	return ret;
 }
 
+/*
+ * Drop a superblock's refcount.
+ * Returns non-zero if the superblock is about to be destroyed and
+ * at least is already removed from super_blocks list, so if we are
+ * making a loop through super blocks then we need to restart.
+ * The caller must hold sb_lock.
+ */
+int __put_super_and_need_restart(struct super_block *sb)
+{
+	/* check for race with generic_shutdown_super() */
+	if (list_empty(&sb->s_list)) {
+		/* super block is removed, need to restart... */
+		__put_super(sb);
+		return 1;
+	}
+	/* can't be the last, since s_list is still in use */
+	sb->s_count--;
+	BUG_ON(sb->s_count == 0);
+	return 0;
+}
+
 /**
  *	put_super	-	drop a temporary reference to superblock
  *	@s: superblock in question
@@ -231,7 +252,8 @@ void generic_shutdown_super(struct super_block *sb)
 		unlock_super(sb);
 	}
 	spin_lock(&sb_lock);
-	list_del(&sb->s_list);
+	/* should be initialized for __put_super_and_need_restart() */
+	list_del_init(&sb->s_list);
 	list_del(&sb->s_instances);
 	spin_unlock(&sb_lock);
 	up_write(&sb->s_umount);
@@ -284,7 +306,7 @@ retry:
 	}
 	s->s_type = type;
 	strlcpy(s->s_id, type->name, sizeof(s->s_id));
-	list_add(&s->s_list, super_blocks.prev);
+	list_add_tail(&s->s_list, &super_blocks);
 	list_add(&s->s_instances, &type->fs_supers);
 	spin_unlock(&sb_lock);
 	get_filesystem(type);
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index c8bfec6b7..3169fe516 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -5,12 +5,14 @@
 #include <linux/fs.h>
 #include <linux/module.h>
 #include <linux/kobject.h>
+#include <linux/namei.h>
 
 #include "sysfs.h"
 
 static struct inode_operations sysfs_symlink_inode_operations = {
-	.readlink = sysfs_readlink,
+	.readlink = generic_readlink,
 	.follow_link = sysfs_follow_link,
+	.put_link = sysfs_put_link,
 };
 
 static int init_symlink(struct inode * inode)
@@ -140,38 +142,21 @@ static int sysfs_getlink(struct dentry *dentry, char * path)
 
 }
 
-int sysfs_readlink(struct dentry *dentry, char __user *buffer, int buflen)
+int sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-	int error = 0;
+	int error = -ENOMEM;
 	unsigned long page = get_zeroed_page(GFP_KERNEL);
-
-	if (!page)
-		return -ENOMEM;
-
-	error = sysfs_getlink(dentry, (char *) page);
-	if (!error)
-	        error = vfs_readlink(dentry, buffer, buflen, (char *) page);
-
-	free_page(page);
-
-	return error;
+	if (page)
+		error = sysfs_getlink(dentry, (char *) page); 
+	nd_set_link(nd, error ? ERR_PTR(error) : (char *)page);
+	return 0;
 }
 
-int sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+void sysfs_put_link(struct dentry *dentry, struct nameidata *nd)
 {
-	int error = 0;
-	unsigned long page = get_zeroed_page(GFP_KERNEL);
-
-	if (!page)
-		return -ENOMEM;
-
-	error = sysfs_getlink(dentry, (char *) page); 
-	if (!error)
-	        error = vfs_follow_link(nd, (char *) page);
-
-	free_page(page);
-
-	return error;
+	char *page = nd_get_link(nd);
+	if (!IS_ERR(page))
+		free_page((unsigned long)page);
 }
 
 EXPORT_SYMBOL(sysfs_create_link);
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index ff5d1478a..4a8c21544 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -12,8 +12,8 @@ extern void sysfs_hash_and_remove(struct dentry * dir, const char * name);
 extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **);
 extern void sysfs_remove_subdir(struct dentry *);
 
-extern int sysfs_readlink(struct dentry *, char __user *, int );
 extern int sysfs_follow_link(struct dentry *, struct nameidata *);
+extern void sysfs_put_link(struct dentry *, struct nameidata *);
 extern struct rw_semaphore sysfs_rename_sem;
 
 static inline struct kobject *sysfs_get_kobject(struct dentry *dentry)
diff --git a/fs/sysv/balloc.c b/fs/sysv/balloc.c
index 8184570f2..9a6ad96ac 100644
--- a/fs/sysv/balloc.c
+++ b/fs/sysv/balloc.c
@@ -27,23 +27,23 @@
    sb->sv_sbd2->s_tfree = *sb->sv_free_blocks
    but we nevertheless keep it up to date. */
 
-static inline u32 *get_chunk(struct super_block *sb, struct buffer_head *bh)
+static inline sysv_zone_t *get_chunk(struct super_block *sb, struct buffer_head *bh)
 {
 	char *bh_data = bh->b_data;
 
 	if (SYSV_SB(sb)->s_type == FSTYPE_SYSV4)
-		return (u32*)(bh_data+4);
+		return (sysv_zone_t*)(bh_data+4);
 	else
-		return (u32*)(bh_data+2);
+		return (sysv_zone_t*)(bh_data+2);
 }
 
 /* NOTE NOTE NOTE: nr is a block number _as_ _stored_ _on_ _disk_ */
 
-void sysv_free_block(struct super_block * sb, u32 nr)
+void sysv_free_block(struct super_block * sb, sysv_zone_t nr)
 {
 	struct sysv_sb_info * sbi = SYSV_SB(sb);
 	struct buffer_head * bh;
-	u32 *blocks = sbi->s_bcache;
+	sysv_zone_t *blocks = sbi->s_bcache;
 	unsigned count;
 	unsigned block = fs32_to_cpu(sbi, nr);
 
@@ -81,7 +81,7 @@ void sysv_free_block(struct super_block * sb, u32 nr)
 			return;
 		}
 		memset(bh->b_data, 0, sb->s_blocksize);
-		*(u16*)bh->b_data = cpu_to_fs16(sbi, count);
+		*(__fs16*)bh->b_data = cpu_to_fs16(sbi, count);
 		memcpy(get_chunk(sb,bh), blocks, count * sizeof(sysv_zone_t));
 		mark_buffer_dirty(bh);
 		set_buffer_uptodate(bh);
@@ -96,11 +96,11 @@ void sysv_free_block(struct super_block * sb, u32 nr)
 	unlock_super(sb);
 }
 
-u32 sysv_new_block(struct super_block * sb)
+sysv_zone_t sysv_new_block(struct super_block * sb)
 {
 	struct sysv_sb_info *sbi = SYSV_SB(sb);
 	unsigned int block;
-	u32 nr;
+	sysv_zone_t nr;
 	struct buffer_head * bh;
 	unsigned count;
 
@@ -133,7 +133,7 @@ u32 sysv_new_block(struct super_block * sb)
 			*sbi->s_bcache_count = cpu_to_fs16(sbi, 1);
 			goto Enospc;
 		}
-		count = fs16_to_cpu(sbi, *(u16*)bh->b_data);
+		count = fs16_to_cpu(sbi, *(__fs16*)bh->b_data);
 		if (count > sbi->s_flc_size) {
 			printk("sysv_new_block: free-list block with >flc_size entries\n");
 			brelse(bh);
@@ -161,7 +161,7 @@ unsigned long sysv_count_free_blocks(struct super_block * sb)
 	int sb_count;
 	int count;
 	struct buffer_head * bh = NULL;
-	u32 *blocks;
+	sysv_zone_t *blocks;
 	unsigned block;
 	int n;
 
@@ -184,15 +184,16 @@ unsigned long sysv_count_free_blocks(struct super_block * sb)
 	n = fs16_to_cpu(sbi, *sbi->s_bcache_count);
 	blocks = sbi->s_bcache;
 	while (1) {
+		sysv_zone_t zone;
 		if (n > sbi->s_flc_size)
 			goto E2big;
-		block = 0;
-		while (n && (block = blocks[--n]) != 0)
+		zone = 0;
+		while (n && (zone = blocks[--n]) != 0)
 			count++;
-		if (block == 0)
+		if (zone == 0)
 			break;
 
-		block = fs32_to_cpu(sbi, block);
+		block = fs32_to_cpu(sbi, zone);
 		if (bh)
 			brelse(bh);
 
@@ -202,7 +203,7 @@ unsigned long sysv_count_free_blocks(struct super_block * sb)
 		bh = sb_bread(sb, block);
 		if (!bh)
 			goto Eio;
-		n = fs16_to_cpu(sbi, *(u16*)bh->b_data);
+		n = fs16_to_cpu(sbi, *(__fs16*)bh->b_data);
 		blocks = get_chunk(sb, bh);
 	}
 	if (bh)
diff --git a/fs/sysv/ialloc.c b/fs/sysv/ialloc.c
index d63b58039..5b1295cde 100644
--- a/fs/sysv/ialloc.c
+++ b/fs/sysv/ialloc.c
@@ -137,7 +137,7 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)
 	struct super_block *sb = dir->i_sb;
 	struct sysv_sb_info *sbi = SYSV_SB(sb);
 	struct inode *inode;
-	u16 ino;
+	sysv_ino_t ino;
 	unsigned count;
 
 	inode = new_inode(sb);
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
index 2be44b7a9..0530077d9 100644
--- a/fs/sysv/inode.c
+++ b/fs/sysv/inode.c
@@ -260,13 +260,14 @@ static struct buffer_head * sysv_update_inode(struct inode * inode)
 	return bh;
 }
 
-void sysv_write_inode(struct inode * inode, int wait)
+int sysv_write_inode(struct inode * inode, int wait)
 {
 	struct buffer_head *bh;
 	lock_kernel();
 	bh = sysv_update_inode(inode);
 	brelse(bh);
 	unlock_kernel();
+	return 0;
 }
 
 int sysv_sync_inode(struct inode * inode)
@@ -340,7 +341,7 @@ int __init sysv_init_icache(void)
 {
 	sysv_inode_cachep = kmem_cache_create("sysv_inode_cache",
 			sizeof(struct sysv_inode_info), 0,
-			SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, 
+			SLAB_RECLAIM_ACCOUNT,
 			init_once, NULL);
 	if (!sysv_inode_cachep)
 		return -ENOMEM;
diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c
index 490188b38..49d945cf4 100644
--- a/fs/sysv/itree.c
+++ b/fs/sysv/itree.c
@@ -50,20 +50,20 @@ static int block_to_path(struct inode *inode, long block, int offsets[DEPTH])
 	return n;
 }
 
-static inline int block_to_cpu(struct sysv_sb_info *sbi, u32 nr)
+static inline int block_to_cpu(struct sysv_sb_info *sbi, sysv_zone_t nr)
 {
 	return sbi->s_block_base + fs32_to_cpu(sbi, nr);
 }
 
 typedef struct {
-	u32     *p;
-	u32     key;
+	sysv_zone_t     *p;
+	sysv_zone_t     key;
 	struct buffer_head *bh;
 } Indirect;
 
 static rwlock_t pointers_lock = RW_LOCK_UNLOCKED;
 
-static inline void add_chain(Indirect *p, struct buffer_head *bh, u32 *v)
+static inline void add_chain(Indirect *p, struct buffer_head *bh, sysv_zone_t *v)
 {
 	p->key = *(p->p = v);
 	p->bh = bh;
@@ -76,9 +76,9 @@ static inline int verify_chain(Indirect *from, Indirect *to)
 	return (from > to);
 }
 
-static inline u32 *block_end(struct buffer_head *bh)
+static inline sysv_zone_t *block_end(struct buffer_head *bh)
 {
-	return (u32*)((char*)bh->b_data + bh->b_size);
+	return (sysv_zone_t*)((char*)bh->b_data + bh->b_size);
 }
 
 /*
@@ -105,7 +105,7 @@ static Indirect *get_branch(struct inode *inode,
 			goto failure;
 		if (!verify_chain(chain, p))
 			goto changed;
-		add_chain(++p, bh, (u32*)bh->b_data + *++offsets);
+		add_chain(++p, bh, (sysv_zone_t*)bh->b_data + *++offsets);
 		if (!p->key)
 			goto no_block;
 	}
@@ -147,7 +147,7 @@ static int alloc_branch(struct inode *inode,
 		lock_buffer(bh);
 		memset(bh->b_data, 0, blocksize);
 		branch[n].bh = bh;
-		branch[n].p = (u32*) bh->b_data + offsets[n];
+		branch[n].p = (sysv_zone_t*) bh->b_data + offsets[n];
 		*branch[n].p = branch[n].key;
 		set_buffer_uptodate(bh);
 		unlock_buffer(bh);
@@ -265,7 +265,7 @@ changed:
 	goto reread;
 }
 
-static inline int all_zeroes(u32 *p, u32 *q)
+static inline int all_zeroes(sysv_zone_t *p, sysv_zone_t *q)
 {
 	while (p < q)
 		if (*p++)
@@ -277,7 +277,7 @@ static Indirect *find_shared(struct inode *inode,
 				int depth,
 				int offsets[],
 				Indirect chain[],
-				u32 *top)
+				sysv_zone_t *top)
 {
 	Indirect *partial, *p;
 	int k, err;
@@ -298,7 +298,7 @@ static Indirect *find_shared(struct inode *inode,
 		write_unlock(&pointers_lock);
 		goto no_top;
 	}
-	for (p=partial; p>chain && all_zeroes((u32*)p->bh->b_data,p->p); p--)
+	for (p=partial; p>chain && all_zeroes((sysv_zone_t*)p->bh->b_data,p->p); p--)
 		;
 	/*
 	 * OK, we've found the last block that must survive. The rest of our
@@ -322,10 +322,10 @@ no_top:
 	return partial;
 }
 
-static inline void free_data(struct inode *inode, u32 *p, u32 *q)
+static inline void free_data(struct inode *inode, sysv_zone_t *p, sysv_zone_t *q)
 {
 	for ( ; p < q ; p++) {
-		u32 nr = *p;
+		sysv_zone_t nr = *p;
 		if (nr) {
 			*p = 0;
 			sysv_free_block(inode->i_sb, nr);
@@ -334,7 +334,7 @@ static inline void free_data(struct inode *inode, u32 *p, u32 *q)
 	}
 }
 
-static void free_branches(struct inode *inode, u32 *p, u32 *q, int depth)
+static void free_branches(struct inode *inode, sysv_zone_t *p, sysv_zone_t *q, int depth)
 {
 	struct buffer_head * bh;
 	struct super_block *sb = inode->i_sb;
@@ -342,7 +342,7 @@ static void free_branches(struct inode *inode, u32 *p, u32 *q, int depth)
 	if (depth--) {
 		for ( ; p < q ; p++) {
 			int block;
-			u32 nr = *p;
+			sysv_zone_t nr = *p;
 			if (!nr)
 				continue;
 			*p = 0;
@@ -350,7 +350,7 @@ static void free_branches(struct inode *inode, u32 *p, u32 *q, int depth)
 			bh = sb_bread(sb, block);
 			if (!bh)
 				continue;
-			free_branches(inode, (u32*)bh->b_data,
+			free_branches(inode, (sysv_zone_t*)bh->b_data,
 					block_end(bh), depth);
 			bforget(bh);
 			sysv_free_block(sb, nr);
@@ -362,11 +362,11 @@ static void free_branches(struct inode *inode, u32 *p, u32 *q, int depth)
 
 void sysv_truncate (struct inode * inode)
 {
-	u32 *i_data = SYSV_I(inode)->i_data;
+	sysv_zone_t *i_data = SYSV_I(inode)->i_data;
 	int offsets[DEPTH];
 	Indirect chain[DEPTH];
 	Indirect *partial;
-	int nr = 0;
+	sysv_zone_t nr = 0;
 	int n;
 	long iblock;
 	unsigned blocksize;
diff --git a/fs/sysv/super.c b/fs/sysv/super.c
index f0e99fc61..59e76b511 100644
--- a/fs/sysv/super.c
+++ b/fs/sysv/super.c
@@ -178,16 +178,22 @@ static void detected_v7(struct sysv_sb_info *sbi)
 static int detect_xenix(struct sysv_sb_info *sbi, struct buffer_head *bh)
 {
 	struct xenix_super_block *sbd = (struct xenix_super_block *)bh->b_data;
-	if (sbd->s_magic == cpu_to_le32(0x2b5544))
+	if (*(__le32 *)&sbd->s_magic == cpu_to_le32(0x2b5544))
 		sbi->s_bytesex = BYTESEX_LE;
-	else if (sbd->s_magic == cpu_to_be32(0x2b5544))
+	else if (*(__be32 *)&sbd->s_magic == cpu_to_be32(0x2b5544))
 		sbi->s_bytesex = BYTESEX_BE;
 	else
 		return 0;
-	if (sbd->s_type > 2 || sbd->s_type < 1)
+	switch (fs32_to_cpu(sbi, sbd->s_type)) {
+	case 1:
+		sbi->s_type = FSTYPE_XENIX;
+		return 1;
+	case 2:
+		sbi->s_type = FSTYPE_XENIX;
+		return 2;
+	default:
 		return 0;
-	sbi->s_type = FSTYPE_XENIX;
-	return sbd->s_type;
+	}
 }
 
 static int detect_sysv(struct sysv_sb_info *sbi, struct buffer_head *bh)
@@ -195,14 +201,17 @@ static int detect_sysv(struct sysv_sb_info *sbi, struct buffer_head *bh)
 	struct super_block *sb = sbi->s_sb;
 	/* All relevant fields are at the same offsets in R2 and R4 */
 	struct sysv4_super_block * sbd;
+	u32 type;
 
 	sbd = (struct sysv4_super_block *) (bh->b_data + BLOCK_SIZE/2);
-	if (sbd->s_magic == cpu_to_le32(0xfd187e20))
+	if (*(__le32 *)&sbd->s_magic == cpu_to_le32(0xfd187e20))
 		sbi->s_bytesex = BYTESEX_LE;
-	else if (sbd->s_magic == cpu_to_be32(0xfd187e20))
+	else if (*(__be32 *)&sbd->s_magic == cpu_to_be32(0xfd187e20))
 		sbi->s_bytesex = BYTESEX_BE;
 	else
 		return 0;
+
+	type = fs32_to_cpu(sbi, sbd->s_type);
  
  	if (fs16_to_cpu(sbi, sbd->s_nfree) == 0xffff) {
  		sbi->s_type = FSTYPE_AFS;
@@ -212,18 +221,17 @@ static int detect_sysv(struct sysv_sb_info *sbi, struct buffer_head *bh)
  				"forcing read-only mode.\n", 
  				sb->s_id);
  		}
- 		return sbd->s_type;
+ 		return type;
  	}
  
 	if (fs32_to_cpu(sbi, sbd->s_time) < JAN_1_1980) {
 		/* this is likely to happen on SystemV2 FS */
-		if (sbd->s_type > 3 || sbd->s_type < 1)
+		if (type > 3 || type < 1)
 			return 0;
 		sbi->s_type = FSTYPE_SYSV2;
-		return sbd->s_type;
+		return type;
 	}
-	if ((sbd->s_type > 3 || sbd->s_type < 1) &&
-	    (sbd->s_type > 0x30 || sbd->s_type < 0x10))
+	if ((type > 3 || type < 1) && (type > 0x30 || type < 0x10))
 		return 0;
 
 	/* On Interactive Unix (ISC) Version 4.0/3.x s_type field = 0x10,
@@ -231,14 +239,14 @@ static int detect_sysv(struct sysv_sb_info *sbi, struct buffer_head *bh)
 	   filename limit is gone. Due to lack of information about this
            feature read-only mode seems to be a reasonable approach... -KGB */
 
-	if (sbd->s_type >= 0x10) {
+	if (type >= 0x10) {
 		printk("SysV FS: can't handle long file names on %s, "
 		       "forcing read-only mode.\n", sb->s_id);
 		sbi->s_forced_ro = 1;
 	}
 
 	sbi->s_type = FSTYPE_SYSV4;
-	return sbd->s_type >= 0x10 ? (sbd->s_type >> 4) : sbd->s_type;
+	return type >= 0x10 ? type >> 4 : type;
 }
 
 static int detect_coherent(struct sysv_sb_info *sbi, struct buffer_head *bh)
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h
index 493b0a6a4..b7f9b4a42 100644
--- a/fs/sysv/sysv.h
+++ b/fs/sysv/sysv.h
@@ -2,6 +2,10 @@
 #define _SYSV_H
 
 #include <linux/buffer_head.h>
+
+typedef __u16 __bitwise __fs16;
+typedef __u32 __bitwise __fs32;
+
 #include <linux/sysv_fs.h>
 
 /*
@@ -38,14 +42,14 @@ struct sysv_sb_info {
 	   different superblock layout. */
 	char *         s_sbd1;		/* entire superblock data, for part 1 */
 	char *         s_sbd2;		/* entire superblock data, for part 2 */
-	u16            *s_sb_fic_count;	/* pointer to s_sbd->s_ninode */
-        u16            *s_sb_fic_inodes; /* pointer to s_sbd->s_inode */
-	u16            *s_sb_total_free_inodes; /* pointer to s_sbd->s_tinode */
-	u16            *s_bcache_count;	/* pointer to s_sbd->s_nfree */
-	u32	       *s_bcache;	/* pointer to s_sbd->s_free */
-	u32            *s_free_blocks;	/* pointer to s_sbd->s_tfree */
-	u32            *s_sb_time;	/* pointer to s_sbd->s_time */
-	u32            *s_sb_state;	/* pointer to s_sbd->s_state, only FSTYPE_SYSV */
+	__fs16         *s_sb_fic_count;	/* pointer to s_sbd->s_ninode */
+        sysv_ino_t     *s_sb_fic_inodes; /* pointer to s_sbd->s_inode */
+	__fs16         *s_sb_total_free_inodes; /* pointer to s_sbd->s_tinode */
+	__fs16         *s_bcache_count;	/* pointer to s_sbd->s_nfree */
+	sysv_zone_t    *s_bcache;	/* pointer to s_sbd->s_free */
+	__fs32         *s_free_blocks;	/* pointer to s_sbd->s_tfree */
+	__fs32         *s_sb_time;	/* pointer to s_sbd->s_time */
+	__fs32         *s_sb_state;	/* pointer to s_sbd->s_state, only FSTYPE_SYSV */
 	/* We keep those superblock entities that don't change here;
 	   this saves us an indirection and perhaps a conversion. */
 	u32            s_firstinodezone; /* index of first inode zone */
@@ -61,7 +65,7 @@ struct sysv_sb_info {
  * SystemV/V7/Coherent FS inode data in memory
  */
 struct sysv_inode_info {
-	u32		i_data[13];
+	__fs32		i_data[13];
 	u32		i_dir_start_lookup;
 	struct inode	vfs_inode;
 };
@@ -126,15 +130,15 @@ extern void sysv_free_inode(struct inode *);
 extern unsigned long sysv_count_free_inodes(struct super_block *);
 
 /* balloc.c */
-extern u32 sysv_new_block(struct super_block *);
-extern void sysv_free_block(struct super_block *, u32);
+extern sysv_zone_t sysv_new_block(struct super_block *);
+extern void sysv_free_block(struct super_block *, sysv_zone_t);
 extern unsigned long sysv_count_free_blocks(struct super_block *);
 
 /* itree.c */
 extern void sysv_truncate(struct inode *);
 
 /* inode.c */
-extern void sysv_write_inode(struct inode *, int);
+extern int sysv_write_inode(struct inode *, int);
 extern int sysv_sync_inode(struct inode *);
 extern int sysv_sync_file(struct file *, struct dentry *, int);
 extern void sysv_set_inode(struct inode *, dev_t);
@@ -181,58 +185,60 @@ static inline u32 PDP_swab(u32 x)
 #endif
 }
 
-static inline u32 fs32_to_cpu(struct sysv_sb_info *sbi, u32 n)
+static inline __u32 fs32_to_cpu(struct sysv_sb_info *sbi, __fs32 n)
 {
 	if (sbi->s_bytesex == BYTESEX_PDP)
-		return PDP_swab(n);
+		return PDP_swab((__force __u32)n);
 	else if (sbi->s_bytesex == BYTESEX_LE)
-		return le32_to_cpu(n);
+		return le32_to_cpu((__force __le32)n);
 	else
-		return be32_to_cpu(n);
+		return be32_to_cpu((__force __be32)n);
 }
 
-static inline u32 cpu_to_fs32(struct sysv_sb_info *sbi, u32 n)
+static inline __fs32 cpu_to_fs32(struct sysv_sb_info *sbi, __u32 n)
 {
 	if (sbi->s_bytesex == BYTESEX_PDP)
-		return PDP_swab(n);
+		return (__force __fs32)PDP_swab(n);
 	else if (sbi->s_bytesex == BYTESEX_LE)
-		return cpu_to_le32(n);
+		return (__force __fs32)cpu_to_le32(n);
 	else
-		return cpu_to_be32(n);
+		return (__force __fs32)cpu_to_be32(n);
 }
 
-static inline u32 fs32_add(struct sysv_sb_info *sbi, u32 *n, int d)
+static inline __fs32 fs32_add(struct sysv_sb_info *sbi, __fs32 *n, int d)
 {
 	if (sbi->s_bytesex == BYTESEX_PDP)
-		return *n = PDP_swab(PDP_swab(*n)+d);
+		*(__u32*)n = PDP_swab(PDP_swab(*(__u32*)n)+d);
 	else if (sbi->s_bytesex == BYTESEX_LE)
-		return *n = cpu_to_le32(le32_to_cpu(*n)+d);
+		*(__le32*)n = cpu_to_le32(le32_to_cpu(*(__le32*)n)+d);
 	else
-		return *n = cpu_to_be32(be32_to_cpu(*n)+d);
+		*(__be32*)n = cpu_to_be32(be32_to_cpu(*(__be32*)n)+d);
+	return *n;
 }
 
-static inline u16 fs16_to_cpu(struct sysv_sb_info *sbi, u16 n)
+static inline __u16 fs16_to_cpu(struct sysv_sb_info *sbi, __fs16 n)
 {
 	if (sbi->s_bytesex != BYTESEX_BE)
-		return le16_to_cpu(n);
+		return le16_to_cpu((__force __le16)n);
 	else
-		return be16_to_cpu(n);
+		return be16_to_cpu((__force __be16)n);
 }
 
-static inline u16 cpu_to_fs16(struct sysv_sb_info *sbi, u16 n)
+static inline __fs16 cpu_to_fs16(struct sysv_sb_info *sbi, __u16 n)
 {
 	if (sbi->s_bytesex != BYTESEX_BE)
-		return cpu_to_le16(n);
+		return (__force __fs16)cpu_to_le16(n);
 	else
-		return cpu_to_be16(n);
+		return (__force __fs16)cpu_to_be16(n);
 }
 
-static inline u16 fs16_add(struct sysv_sb_info *sbi, u16 *n, int d)
+static inline __fs16 fs16_add(struct sysv_sb_info *sbi, __fs16 *n, int d)
 {
 	if (sbi->s_bytesex != BYTESEX_BE)
-		return *n = cpu_to_le16(le16_to_cpu(*n)+d);
+		*(__le16*)n = cpu_to_le16(le16_to_cpu(*(__le16 *)n)+d);
 	else
-		return *n = cpu_to_be16(be16_to_cpu(*n)+d);
+		*(__be16*)n = cpu_to_be16(be16_to_cpu(*(__be16 *)n)+d);
+	return *n;
 }
 
 #endif /* _SYSV_H */
diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c
index 8f7d9eff5..235418f35 100644
--- a/fs/udf/balloc.c
+++ b/fs/udf/balloc.c
@@ -44,13 +44,13 @@
 #define xleNUM_to_cpup(x,y) (le ## x ## _to_cpup(y))
 #define uintBPL_t uint(BITS_PER_LONG)
 #define uint(x) xuint(x)
-#define xuint(x) uint ## x ## _t
+#define xuint(x) __le ## x
 
 extern inline int find_next_one_bit (void * addr, int size, int offset)
 {
 	uintBPL_t * p = ((uintBPL_t *) addr) + (offset / BITS_PER_LONG);
-	uintBPL_t result = offset & ~(BITS_PER_LONG-1);
-	uintBPL_t tmp;
+	int result = offset & ~(BITS_PER_LONG-1);
+	unsigned long tmp;
 
 	if (offset >= size)
 		return size;
@@ -91,7 +91,7 @@ static int read_block_bitmap(struct super_block * sb,
 {
 	struct buffer_head *bh = NULL;
 	int retval = 0;
-	lb_addr loc;
+	kernel_lb_addr loc;
 
 	loc.logicalBlockNum = bitmap->s_extPosition;
 	loc.partitionReferenceNum = UDF_SB_PARTITION(sb);
@@ -145,7 +145,8 @@ static inline int load_block_bitmap(struct super_block * sb,
 
 static void udf_bitmap_free_blocks(struct super_block * sb,
 	struct inode * inode,
-	struct udf_bitmap *bitmap, lb_addr bloc, uint32_t offset, uint32_t count)
+	struct udf_bitmap *bitmap,
+	kernel_lb_addr bloc, uint32_t offset, uint32_t count)
 {
 	struct buffer_head * bh = NULL;
 	unsigned long block;
@@ -424,11 +425,12 @@ error_return:
 
 static void udf_table_free_blocks(struct super_block * sb,
 	struct inode * inode,
-	struct inode * table, lb_addr bloc, uint32_t offset, uint32_t count)
+	struct inode * table,
+	kernel_lb_addr bloc, uint32_t offset, uint32_t count)
 {
 	uint32_t start, end;
 	uint32_t nextoffset, oextoffset, elen;
-	lb_addr nbloc, obloc, eloc;
+	kernel_lb_addr nbloc, obloc, eloc;
 	struct buffer_head *obh, *nbh;
 	int8_t etype;
 	int i;
@@ -678,7 +680,7 @@ static int udf_table_prealloc_blocks(struct super_block * sb,
 {
 	int alloc_count = 0;
 	uint32_t extoffset, elen, adsize;
-	lb_addr bloc, eloc;
+	kernel_lb_addr bloc, eloc;
 	struct buffer_head *bh;
 	int8_t etype = -1;
 
@@ -748,7 +750,7 @@ static int udf_table_new_block(struct super_block * sb,
 	uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF;
 	uint32_t newblock = 0, adsize;
 	uint32_t extoffset, goal_extoffset, elen, goal_elen = 0;
-	lb_addr bloc, goal_bloc, eloc, goal_eloc;
+	kernel_lb_addr bloc, goal_bloc, eloc, goal_eloc;
 	struct buffer_head *bh, *goal_bh;
 	int8_t etype;
 
@@ -854,7 +856,7 @@ static int udf_table_new_block(struct super_block * sb,
 
 inline void udf_free_blocks(struct super_block * sb,
 	struct inode * inode,
-	lb_addr bloc, uint32_t offset, uint32_t count)
+	kernel_lb_addr bloc, uint32_t offset, uint32_t count)
 {
 	uint16_t partition = bloc.partitionReferenceNum;
 
diff --git a/fs/udf/dir.c b/fs/udf/dir.c
index 33228f149..82440b731 100644
--- a/fs/udf/dir.c
+++ b/fs/udf/dir.c
@@ -117,7 +117,7 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
 	uint8_t lfi;
 	loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
 	struct buffer_head * bh = NULL, * tmp, * bha[16];
-	lb_addr bloc, eloc;
+	kernel_lb_addr bloc, eloc;
 	uint32_t extoffset, elen, offset;
 	int i, num;
 	unsigned int dt_type;
@@ -237,7 +237,7 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
 		}
 		else
 		{
-			lb_addr tloc = lelb_to_cpu(cfi.icb.extLocation);
+			kernel_lb_addr tloc = lelb_to_cpu(cfi.icb.extLocation);
 
 			iblock = udf_get_lb_pblock(dir->i_sb, tloc, 0);
 			flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
diff --git a/fs/udf/directory.c b/fs/udf/directory.c
index 00384653e..9a61ecc54 100644
--- a/fs/udf/directory.c
+++ b/fs/udf/directory.c
@@ -23,8 +23,11 @@
 #include <linux/string.h>
 #include <linux/buffer_head.h>
 
-uint8_t * udf_filead_read(struct inode *dir, uint8_t *tmpad, uint8_t ad_size,
-	lb_addr fe_loc, int *pos, int *offset, struct buffer_head **bh, int *error)
+#if 0
+static uint8_t *
+udf_filead_read(struct inode *dir, uint8_t *tmpad, uint8_t ad_size,
+		kernel_lb_addr fe_loc, int *pos, int *offset,
+		struct buffer_head **bh, int *error)
 {
 	int loffset = *offset;
 	int block;
@@ -71,13 +74,14 @@ uint8_t * udf_filead_read(struct inode *dir, uint8_t *tmpad, uint8_t ad_size,
 	}
 	return ad;
 }
+#endif
 
 struct fileIdentDesc *
 udf_fileident_read(struct inode *dir, loff_t *nf_pos,
 	struct udf_fileident_bh *fibh,
 	struct fileIdentDesc *cfi,
-	lb_addr *bloc, uint32_t *extoffset, 
-	lb_addr *eloc, uint32_t *elen,
+	kernel_lb_addr *bloc, uint32_t *extoffset, 
+	kernel_lb_addr *eloc, uint32_t *elen,
 	uint32_t *offset, struct buffer_head **bh)
 {
 	struct fileIdentDesc *fi;
@@ -259,7 +263,8 @@ udf_get_fileident(void * buffer, int bufsize, int * offset)
 	return fi;
 }
 
-extent_ad *
+#if 0
+static extent_ad *
 udf_get_fileextent(void * buffer, int bufsize, int * offset)
 {
 	extent_ad * ext;
@@ -293,6 +298,7 @@ udf_get_fileextent(void * buffer, int bufsize, int * offset)
 	*offset = *offset + sizeof(extent_ad);
 	return ext;
 }
+#endif
 
 short_ad *
 udf_get_fileshortad(uint8_t *ptr, int maxoffset, int *offset, int inc)
diff --git a/fs/udf/ecma_167.h b/fs/udf/ecma_167.h
index 9132ff515..f81f2ebbf 100644
--- a/fs/udf/ecma_167.h
+++ b/fs/udf/ecma_167.h
@@ -58,6 +58,20 @@ typedef struct
 typedef uint8_t		dstring;
 
 /* Timestamp (ECMA 167r3 1/7.3) */
+typedef struct
+{
+	__le16		typeAndTimezone;
+	__le16		year;
+	uint8_t		month;
+	uint8_t		day;
+	uint8_t		hour;
+	uint8_t		minute;
+	uint8_t		second;
+	uint8_t		centiseconds;
+	uint8_t		hundredsOfMicroseconds;
+	uint8_t		microseconds;
+} __attribute__ ((packed)) timestamp;
+
 typedef struct
 {
 	uint16_t	typeAndTimezone;
@@ -70,7 +84,7 @@ typedef struct
 	uint8_t		centiseconds;
 	uint8_t		hundredsOfMicroseconds;
 	uint8_t		microseconds;
-} __attribute__ ((packed)) timestamp;
+} __attribute__ ((packed)) kernel_timestamp;
 
 /* Type and Time Zone (ECMA 167r3 1/7.3.1) */
 #define TIMESTAMP_TYPE_MASK		0xF000
@@ -139,12 +153,12 @@ struct bootDesc
 	uint8_t		reserved1;
 	regid		archType;
 	regid		bootIdent;
-	uint32_t	bootExtLocation;
-	uint32_t	bootExtLength;
-	uint64_t	loadAddress;
-	uint64_t	startAddress;
+	__le32		bootExtLocation;
+	__le32		bootExtLength;
+	__le64		loadAddress;
+	__le64		startAddress;
 	timestamp	descCreationDateAndTime;
-	uint16_t	flags;
+	__le16		flags;
 	uint8_t		reserved2[32];
 	uint8_t		bootUse[1906];
 } __attribute__ ((packed));
@@ -153,23 +167,29 @@ struct bootDesc
 #define BOOT_FLAGS_ERASE		0x01
 
 /* Extent Descriptor (ECMA 167r3 3/7.1) */
+typedef struct
+{
+	__le32		extLength;
+	__le32		extLocation;
+} __attribute__ ((packed)) extent_ad;
+
 typedef struct
 {
 	uint32_t	extLength;
 	uint32_t	extLocation;
-} __attribute__ ((packed)) extent_ad;
+} kernel_extent_ad;
 
 /* Descriptor Tag (ECMA 167r3 3/7.2) */
 typedef struct
 {
-	uint16_t	tagIdent;
-	uint16_t	descVersion;
+	__le16		tagIdent;
+	__le16		descVersion;
 	uint8_t		tagChecksum;
 	uint8_t		reserved;
-	uint16_t	tagSerialNum;
-	uint16_t	descCRC;
-	uint16_t	descCRCLength;
-	uint32_t	tagLocation;
+	__le16		tagSerialNum;
+	__le16		descCRC;
+	__le16		descCRCLength;
+	__le32		tagLocation;
 } __attribute__ ((packed)) tag;
 
 /* Tag Identifier (ECMA 167r3 3/7.2.1) */
@@ -197,15 +217,15 @@ struct NSRDesc
 struct primaryVolDesc
 {
 	tag		descTag;
-	uint32_t	volDescSeqNum;
-	uint32_t	primaryVolDescNum;
+	__le32		volDescSeqNum;
+	__le32		primaryVolDescNum;
 	dstring		volIdent[32];
-	uint16_t	volSeqNum;
-	uint16_t	maxVolSeqNum;
-	uint16_t	interchangeLvl;
-	uint16_t	maxInterchangeLvl;
-	uint32_t	charSetList;
-	uint32_t	maxCharSetList;
+	__le16		volSeqNum;
+	__le16		maxVolSeqNum;
+	__le16		interchangeLvl;
+	__le16		maxInterchangeLvl;
+	__le32		charSetList;
+	__le32		maxCharSetList;
 	dstring		volSetIdent[128];
 	charspec	descCharSet;
 	charspec	explanatoryCharSet;
@@ -215,8 +235,8 @@ struct primaryVolDesc
 	timestamp	recordingDateAndTime;
 	regid		impIdent;
 	uint8_t		impUse[64];
-	uint32_t	predecessorVolDescSeqLocation;
-	uint16_t	flags;
+	__le32		predecessorVolDescSeqLocation;
+	__le16		flags;
 	uint8_t		reserved[22];
 } __attribute__ ((packed));
 
@@ -236,7 +256,7 @@ struct anchorVolDescPtr
 struct volDescPtr
 {
 	tag		descTag;
-	uint32_t	volDescSeqNum;
+	__le32		volDescSeqNum;
 	extent_ad	nextVolDescSeqExt;
 	uint8_t		reserved[484];
 } __attribute__ ((packed));
@@ -245,7 +265,7 @@ struct volDescPtr
 struct impUseVolDesc
 {
 	tag		descTag;
-	uint32_t	volDescSeqNum;
+	__le32		volDescSeqNum;
 	regid		impIdent;
 	uint8_t		impUse[460];
 } __attribute__ ((packed));
@@ -254,14 +274,14 @@ struct impUseVolDesc
 struct partitionDesc
 {
 	tag		descTag;
-	uint32_t	volDescSeqNum;
-	uint16_t	partitionFlags;
-	uint16_t	partitionNumber;
+	__le32		volDescSeqNum;
+	__le16		partitionFlags;
+	__le16		partitionNumber;
 	regid		partitionContents;
 	uint8_t		partitionContentsUse[128];
-	uint32_t	accessType;
-	uint32_t	partitionStartingLocation;
-	uint32_t	partitionLength;
+	__le32		accessType;
+	__le32		partitionStartingLocation;
+	__le32		partitionLength;
 	regid		impIdent;
 	uint8_t		impUse[128];
 	uint8_t		reserved[156];
@@ -290,14 +310,14 @@ struct partitionDesc
 struct logicalVolDesc
 {
 	tag		descTag;
-	uint32_t	volDescSeqNum;
+	__le32		volDescSeqNum;
 	charspec	descCharSet;
 	dstring		logicalVolIdent[128];
-	uint32_t	logicalBlockSize;
+	__le32		logicalBlockSize;
 	regid		domainIdent;
 	uint8_t		logicalVolContentsUse[16];
-	uint32_t	mapTableLength;
-	uint32_t	numPartitionMaps;
+	__le32		mapTableLength;
+	__le32		numPartitionMaps;
 	regid		impIdent;
 	uint8_t		impUse[128];
 	extent_ad	integritySeqExt;
@@ -322,8 +342,8 @@ struct genericPartitionMap1
 {
 	uint8_t		partitionMapType;
 	uint8_t		partitionMapLength;
-	uint16_t	volSeqNum;
-	uint16_t	partitionNum;
+	__le16		volSeqNum;
+	__le16		partitionNum;
 } __attribute__ ((packed));
 
 /* Type 2 Partition Map (ECMA 167r3 3/10.7.3) */
@@ -338,8 +358,8 @@ struct genericPartitionMap2
 struct unallocSpaceDesc
 {
 	tag		descTag;
-	uint32_t	volDescSeqNum;
-	uint32_t	numAllocDescs;
+	__le32		volDescSeqNum;
+	__le32		numAllocDescs;
 	extent_ad	allocDescs[0];
 } __attribute__ ((packed));
 
@@ -355,13 +375,13 @@ struct logicalVolIntegrityDesc
 {
 	tag		descTag;
 	timestamp	recordingDateAndTime;
-	uint32_t	integrityType;
+	__le32		integrityType;
 	extent_ad	nextIntegrityExt;
 	uint8_t		logicalVolContentsUse[32];
-	uint32_t	numOfPartitions;
-	uint32_t	lengthOfImpUse;
-	uint32_t	freeSpaceTable[0];
-	uint32_t	sizeTable[0];
+	__le32		numOfPartitions;
+	__le32		lengthOfImpUse;
+	__le32		freeSpaceTable[0];
+	__le32		sizeTable[0];
 	uint8_t		impUse[0];
 } __attribute__ ((packed));
 
@@ -372,33 +392,55 @@ struct logicalVolIntegrityDesc
 /* Recorded Address (ECMA 167r3 4/7.1) */
 typedef struct 
 {
-	uint32_t	logicalBlockNum;
-	uint16_t	partitionReferenceNum;
+	__le32		logicalBlockNum;
+	__le16	 	partitionReferenceNum;
 } __attribute__ ((packed)) lb_addr;
 
+/* ... and its in-core analog */
+typedef struct 
+{
+	uint32_t		logicalBlockNum;
+	uint16_t	 	partitionReferenceNum;
+} kernel_lb_addr;
+
 /* Short Allocation Descriptor (ECMA 167r3 4/14.14.1) */
 typedef struct
 {
-        uint32_t	extLength;
-        uint32_t	extPosition;
+        __le32		extLength;
+        __le32		extPosition;
 } __attribute__ ((packed)) short_ad;
 
 /* Long Allocation Descriptor (ECMA 167r3 4/14.14.2) */
 typedef struct
 {
-	uint32_t	extLength;
+	__le32		extLength;
 	lb_addr		extLocation;
 	uint8_t		impUse[6];
 } __attribute__ ((packed)) long_ad;
 
+typedef struct
+{
+	uint32_t	extLength;
+	kernel_lb_addr	extLocation;
+	uint8_t		impUse[6];
+} kernel_long_ad;
+
 /* Extended Allocation Descriptor (ECMA 167r3 4/14.14.3) */
+typedef struct
+{
+	__le32		extLength;
+	__le32		recordedLength;
+	__le32		informationLength;
+	lb_addr		extLocation;
+} __attribute__ ((packed)) ext_ad;
+
 typedef struct
 {
 	uint32_t	extLength;
 	uint32_t	recordedLength;
 	uint32_t	informationLength;
-	lb_addr		extLocation;
-} __attribute__ ((packed)) ext_ad;
+	kernel_lb_addr	extLocation;
+} kernel_ext_ad;
 
 /* Descriptor Tag (ECMA 167r3 4/7.2 - See 3/7.2) */
 
@@ -420,12 +462,12 @@ struct fileSetDesc
 {
 	tag		descTag;
 	timestamp	recordingDateAndTime;
-	uint16_t	interchangeLvl;
-	uint16_t	maxInterchangeLvl;
-	uint32_t	charSetList;
-	uint32_t	maxCharSetList;
-	uint32_t	fileSetNum;
-	uint32_t	fileSetDescNum;
+	__le16		interchangeLvl;
+	__le16		maxInterchangeLvl;
+	__le32		charSetList;
+	__le32		maxCharSetList;
+	__le32		fileSetNum;
+	__le32		fileSetDescNum;
 	charspec	logicalVolIdentCharSet;
 	dstring		logicalVolIdent[128];
 	charspec	fileSetCharSet;
@@ -454,11 +496,11 @@ struct partitionHeaderDesc
 struct fileIdentDesc
 {
 	tag		descTag;
-	uint16_t	fileVersionNum;
+	__le16		fileVersionNum;
 	uint8_t		fileCharacteristics;
 	uint8_t		lengthFileIdent;
 	long_ad		icb;
-	uint16_t	lengthOfImpUse;
+	__le16		lengthOfImpUse;
 	uint8_t		impUse[0];
 	uint8_t		fileIdent[0];
 	uint8_t		padding[0];
@@ -475,21 +517,21 @@ struct fileIdentDesc
 struct allocExtDesc
 {
 	tag		descTag;
-	uint32_t	previousAllocExtLocation;
-	uint32_t	lengthAllocDescs;
+	__le32		previousAllocExtLocation;
+	__le32		lengthAllocDescs;
 } __attribute__ ((packed));
 
 /* ICB Tag (ECMA 167r3 4/14.6) */
 typedef struct
 {
-	uint32_t	priorRecordedNumDirectEntries;
-	uint16_t	strategyType;
-	uint16_t	strategyParameter;
-	uint16_t	numEntries;
+	__le32		priorRecordedNumDirectEntries;
+	__le16		strategyType;
+	__le16		strategyParameter;
+	__le16		numEntries;
 	uint8_t		reserved;
 	uint8_t		fileType;
 	lb_addr		parentICBLocation;
-	uint16_t	flags;
+	__le16		flags;
 } __attribute__ ((packed)) icbtag;
 
 /* Strategy Type (ECMA 167r3 4/14.6.2) */
@@ -553,24 +595,24 @@ struct fileEntry
 {
 	tag		descTag;
 	icbtag		icbTag;
-	uint32_t	uid;
-	uint32_t	gid;
-	uint32_t	permissions;
-	uint16_t	fileLinkCount;
+	__le32		uid;
+	__le32		gid;
+	__le32		permissions;
+	__le16		fileLinkCount;
 	uint8_t		recordFormat;
 	uint8_t		recordDisplayAttr;
-	uint32_t	recordLength;
-	uint64_t	informationLength;
-	uint64_t	logicalBlocksRecorded;
+	__le32		recordLength;
+	__le64		informationLength;
+	__le64		logicalBlocksRecorded;
 	timestamp	accessTime;
 	timestamp	modificationTime;
 	timestamp	attrTime;
-	uint32_t	checkpoint;
+	__le32		checkpoint;
 	long_ad		extendedAttrICB;
 	regid		impIdent;
-	uint64_t	uniqueID;
-	uint32_t	lengthExtendedAttr;
-	uint32_t	lengthAllocDescs;
+	__le64		uniqueID;
+	__le32		lengthExtendedAttr;
+	__le32		lengthAllocDescs;
 	uint8_t		extendedAttr[0];
 	uint8_t		allocDescs[0];
 } __attribute__ ((packed));
@@ -616,28 +658,28 @@ struct fileEntry
 struct extendedAttrHeaderDesc
 {
 	tag		descTag;
-	uint32_t	impAttrLocation;
-	uint32_t	appAttrLocation;
+	__le32		impAttrLocation;
+	__le32		appAttrLocation;
 } __attribute__ ((packed));
 
 /* Generic Format (ECMA 167r3 4/14.10.2) */
 struct genericFormat
 {
-	uint32_t	attrType;
+	__le32		attrType;
 	uint8_t		attrSubtype;
 	uint8_t		reserved[3];
-	uint32_t	attrLength;
+	__le32		attrLength;
 	uint8_t		attrData[0];
 } __attribute__ ((packed));
 
 /* Character Set Information (ECMA 167r3 4/14.10.3) */
 struct charSetInfo
 {
-	uint32_t	attrType;
+	__le32		attrType;
 	uint8_t		attrSubtype;
 	uint8_t		reserved[3];
-	uint32_t	attrLength;
-	uint32_t	escapeSeqLength;
+	__le32		attrLength;
+	__le32		escapeSeqLength;
 	uint8_t		charSetType;
 	uint8_t		escapeSeq[0];
 } __attribute__ ((packed));
@@ -645,24 +687,24 @@ struct charSetInfo
 /* Alternate Permissions (ECMA 167r3 4/14.10.4) */
 struct altPerms
 {
-	uint32_t	attrType;
+	__le32		attrType;
 	uint8_t		attrSubtype;
 	uint8_t		reserved[3];
-	uint32_t	attrLength;
-	uint16_t	ownerIdent;
-	uint16_t	groupIdent;
-	uint16_t	permission;
+	__le32		attrLength;
+	__le16		ownerIdent;
+	__le16		groupIdent;
+	__le16		permission;
 } __attribute__ ((packed));
 
 /* File Times Extended Attribute (ECMA 167r3 4/14.10.5) */
 struct fileTimesExtAttr
 {
-	uint32_t	attrType;
+	__le32		attrType;
 	uint8_t		attrSubtype;
 	uint8_t		reserved[3];
-	uint32_t	attrLength;
-	uint32_t	dataLength;
-	uint32_t	fileTimeExistence;
+	__le32		attrLength;
+	__le32		dataLength;
+	__le32		fileTimeExistence;
 	uint8_t		fileTimes;
 } __attribute__ ((packed));
 
@@ -675,36 +717,36 @@ struct fileTimesExtAttr
 /* Information Times Extended Attribute (ECMA 167r3 4/14.10.6) */
 struct infoTimesExtAttr
 {
-	uint32_t	attrType;
+	__le32		attrType;
 	uint8_t		attrSubtype;
 	uint8_t		reserved[3];
-	uint32_t	attrLength;
-	uint32_t	dataLength;
-	uint32_t	infoTimeExistence;
+	__le32		attrLength;
+	__le32		dataLength;
+	__le32		infoTimeExistence;
 	uint8_t		infoTimes[0];
 } __attribute__ ((packed));
 
 /* Device Specification (ECMA 167r3 4/14.10.7) */
 struct deviceSpec
 {
-	uint32_t	attrType;
+	__le32		attrType;
 	uint8_t		attrSubtype;
 	uint8_t		reserved[3];
-	uint32_t	attrLength;
-	uint32_t	impUseLength;
-	uint32_t	majorDeviceIdent;
-	uint32_t	minorDeviceIdent;
+	__le32		attrLength;
+	__le32		impUseLength;
+	__le32		majorDeviceIdent;
+	__le32		minorDeviceIdent;
 	uint8_t		impUse[0];
 } __attribute__ ((packed));
 
 /* Implementation Use Extended Attr (ECMA 167r3 4/14.10.8) */
 struct impUseExtAttr
 {
-	uint32_t	attrType;
+	__le32		attrType;
 	uint8_t		attrSubtype;
 	uint8_t		reserved[3];
-	uint32_t	attrLength;
-	uint32_t	impUseLength;
+	__le32		attrLength;
+	__le32		impUseLength;
 	regid		impIdent;
 	uint8_t		impUse[0];
 } __attribute__ ((packed));
@@ -712,11 +754,11 @@ struct impUseExtAttr
 /* Application Use Extended Attribute (ECMA 167r3 4/14.10.9) */
 struct appUseExtAttr
 {
-	uint32_t	attrType;
+	__le32		attrType;
 	uint8_t		attrSubtype;
 	uint8_t		reserved[3];
-	uint32_t	attrLength;
-	uint32_t	appUseLength;
+	__le32		attrLength;
+	__le32		appUseLength;
 	regid		appIdent;
 	uint8_t		appUse[0];
 } __attribute__ ((packed));
@@ -735,7 +777,7 @@ struct unallocSpaceEntry
 {
 	tag		descTag;
 	icbtag		icbTag;
-	uint32_t	lengthAllocDescs;
+	__le32		lengthAllocDescs;
 	uint8_t		allocDescs[0];
 } __attribute__ ((packed));
 
@@ -743,8 +785,8 @@ struct unallocSpaceEntry
 struct spaceBitmapDesc
 {
 	tag		descTag;
-	uint32_t	numOfBits;
-	uint32_t	numOfBytes;
+	__le32		numOfBits;
+	__le32		numOfBytes;
 	uint8_t		bitmap[0];
 } __attribute__ ((packed));
 
@@ -775,7 +817,7 @@ struct partitionIntegrityEntry
 /* Logical Volume Header Descriptor (ECMA 167r3 4/14.15) */
 struct logicalVolHeaderDesc
 {
-	uint64_t	uniqueID;
+	__le64		uniqueID;
 	uint8_t		reserved[24];
 } __attribute__ ((packed));
 
@@ -784,7 +826,7 @@ struct pathComponent
 {
 	uint8_t		componentType;
 	uint8_t		lengthComponentIdent;
-	uint16_t	componentFileVersionNum;
+	__le16		componentFileVersionNum;
 	dstring		componentIdent[0];
 } __attribute__ ((packed));
 
@@ -793,28 +835,28 @@ struct extendedFileEntry
 {
 	tag		descTag;
 	icbtag		icbTag;
-	uint32_t	uid;
-	uint32_t	gid;
-	uint32_t	permissions;
-	uint16_t	fileLinkCount;
+	__le32		uid;
+	__le32		gid;
+	__le32		permissions;
+	__le16		fileLinkCount;
 	uint8_t		recordFormat;
 	uint8_t		recordDisplayAttr;
-	uint32_t	recordLength;
-	uint64_t	informationLength;
-	uint64_t	objectSize;
-	uint64_t	logicalBlocksRecorded;
+	__le32		recordLength;
+	__le64		informationLength;
+	__le64		objectSize;
+	__le64		logicalBlocksRecorded;
 	timestamp	accessTime;
 	timestamp	modificationTime;
 	timestamp	createTime;
 	timestamp	attrTime;
-	uint32_t	checkpoint;
-	uint32_t	reserved;
+	__le32		checkpoint;
+	__le32		reserved;
 	long_ad		extendedAttrICB;
 	long_ad		streamDirectoryICB;
 	regid		impIdent;
-	uint64_t	uniqueID;
-	uint32_t	lengthExtendedAttr;
-	uint32_t	lengthAllocDescs;
+	__le64		uniqueID;
+	__le32		lengthExtendedAttr;
+	__le32		lengthAllocDescs;
 	uint8_t		extendedAttr[0];
 	uint8_t		allocDescs[0];
 } __attribute__ ((packed));
diff --git a/fs/udf/fsync.c b/fs/udf/fsync.c
index e81448d0c..2dde6b888 100644
--- a/fs/udf/fsync.c
+++ b/fs/udf/fsync.c
@@ -28,6 +28,8 @@
 #include <linux/fs.h>
 #include <linux/smp_lock.h>
 
+static int udf_fsync_inode(struct inode *, int);
+
 /*
  *	File may be NULL when we are called. Perhaps we shouldn't
  *	even pass file to fsync ?
@@ -39,7 +41,7 @@ int udf_fsync_file(struct file * file, struct dentry *dentry, int datasync)
 	return udf_fsync_inode(inode, datasync);
 }
 
-int udf_fsync_inode(struct inode *inode, int datasync)
+static int udf_fsync_inode(struct inode *inode, int datasync)
 {
 	int err;
 
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index f4724459a..68245ca6e 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -54,16 +54,19 @@ MODULE_LICENSE("GPL");
 static mode_t udf_convert_permissions(struct fileEntry *);
 static int udf_update_inode(struct inode *, int);
 static void udf_fill_inode(struct inode *, struct buffer_head *);
-static struct buffer_head *inode_getblk(struct inode *, long, int *, long *, int *);
+static struct buffer_head *inode_getblk(struct inode *, long, int *,
+	long *, int *);
+static int8_t udf_insert_aext(struct inode *, kernel_lb_addr, int,
+	kernel_lb_addr, uint32_t, struct buffer_head *);
 static void udf_split_extents(struct inode *, int *, int, int,
-	long_ad [EXTENT_MERGE_SIZE], int *);
+	kernel_long_ad [EXTENT_MERGE_SIZE], int *);
 static void udf_prealloc_extents(struct inode *, int, int,
-	 long_ad [EXTENT_MERGE_SIZE], int *);
+	 kernel_long_ad [EXTENT_MERGE_SIZE], int *);
 static void udf_merge_extents(struct inode *,
-	 long_ad [EXTENT_MERGE_SIZE], int *);
+	 kernel_long_ad [EXTENT_MERGE_SIZE], int *);
 static void udf_update_extents(struct inode *,
-	long_ad [EXTENT_MERGE_SIZE], int, int,
-	lb_addr, uint32_t, struct buffer_head **);
+	kernel_long_ad [EXTENT_MERGE_SIZE], int, int,
+	kernel_lb_addr, uint32_t, struct buffer_head **);
 static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
 /*
@@ -213,7 +216,7 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
 {
 	int newblock;
 	struct buffer_head *sbh = NULL, *dbh = NULL;
-	lb_addr bloc, eloc;
+	kernel_lb_addr bloc, eloc;
 	uint32_t elen, extoffset;
 	uint8_t alloctype;
 
@@ -268,12 +271,12 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
 			return NULL;
 		}
 		UDF_I_ALLOCTYPE(inode) = alloctype;
-		sfi->descTag.tagLocation = *block;
+		sfi->descTag.tagLocation = cpu_to_le32(*block);
 		dfibh.soffset = dfibh.eoffset;
 		dfibh.eoffset += (sfibh.eoffset - sfibh.soffset);
 		dfi = (struct fileIdentDesc *)(dbh->b_data + dfibh.soffset);
 		if (udf_write_fi(inode, sfi, dfi, &dfibh, sfi->impUse,
-			sfi->fileIdent + sfi->lengthOfImpUse))
+			sfi->fileIdent + le16_to_cpu(sfi->lengthOfImpUse)))
 		{
 			UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
 			udf_release_data(dbh);
@@ -349,8 +352,8 @@ abort_negative:
 	goto abort;
 }
 
-struct buffer_head * udf_getblk(struct inode * inode, long block,
-	int create, int * err)
+static struct buffer_head *
+udf_getblk(struct inode *inode, long block, int create, int *err)
 {
 	struct buffer_head dummy;
 
@@ -378,11 +381,11 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
 	int *err, long *phys, int *new)
 {
 	struct buffer_head *pbh = NULL, *cbh = NULL, *nbh = NULL, *result = NULL;
-	long_ad laarr[EXTENT_MERGE_SIZE];
+	kernel_long_ad laarr[EXTENT_MERGE_SIZE];
 	uint32_t pextoffset = 0, cextoffset = 0, nextoffset = 0;
 	int count = 0, startnum = 0, endnum = 0;
 	uint32_t elen = 0;
-	lb_addr eloc, pbloc, cbloc, nbloc;
+	kernel_lb_addr eloc, pbloc, cbloc, nbloc;
 	int c = 1;
 	uint64_t lbcount = 0, b_off = 0;
 	uint32_t newblocknum, newblock, offset = 0;
@@ -476,7 +479,7 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
 		c = !c;
 		laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
 			((offset + 1) << inode->i_sb->s_blocksize_bits);
-		memset(&laarr[c].extLocation, 0x00, sizeof(lb_addr));
+		memset(&laarr[c].extLocation, 0x00, sizeof(kernel_lb_addr));
 		count ++;
 		endnum ++;
 		lastblock = 1;
@@ -575,7 +578,7 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
 }
 
 static void udf_split_extents(struct inode *inode, int *c, int offset, int newblocknum,
-	long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
+	kernel_long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
 {
 	if ((laarr[*c].extLength >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30) ||
 		(laarr[*c].extLength >> 30) == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))
@@ -637,7 +640,7 @@ static void udf_split_extents(struct inode *inode, int *c, int offset, int newbl
 }
 
 static void udf_prealloc_extents(struct inode *inode, int c, int lastblock,
-	 long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
+	 kernel_long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
 {
 	int start, length = 0, currlength = 0, i;
 
@@ -729,7 +732,7 @@ static void udf_prealloc_extents(struct inode *inode, int c, int lastblock,
 }
 
 static void udf_merge_extents(struct inode *inode,
-	 long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
+	 kernel_long_ad laarr[EXTENT_MERGE_SIZE], int *endnum)
 {
 	int i;
 
@@ -814,11 +817,11 @@ static void udf_merge_extents(struct inode *inode,
 }
 
 static void udf_update_extents(struct inode *inode,
-	long_ad laarr[EXTENT_MERGE_SIZE], int startnum, int endnum,
-	lb_addr pbloc, uint32_t pextoffset, struct buffer_head **pbh)
+	kernel_long_ad laarr[EXTENT_MERGE_SIZE], int startnum, int endnum,
+	kernel_lb_addr pbloc, uint32_t pextoffset, struct buffer_head **pbh)
 {
 	int start = 0, i;
-	lb_addr tmploc;
+	kernel_lb_addr tmploc;
 	uint32_t tmplen;
 
 	if (startnum > endnum)
@@ -938,10 +941,10 @@ void udf_truncate(struct inode * inode)
 void
 udf_read_inode(struct inode *inode)
 {
-	memset(&UDF_I_LOCATION(inode), 0xFF, sizeof(lb_addr));
+	memset(&UDF_I_LOCATION(inode), 0xFF, sizeof(kernel_lb_addr));
 }
 
-void
+static void
 __udf_read_inode(struct inode *inode)
 {
 	struct buffer_head *bh = NULL;
@@ -994,7 +997,7 @@ __udf_read_inode(struct inode *inode)
 		{
 			if (ibh)
 			{
-				lb_addr loc;
+				kernel_lb_addr loc;
 				ie = (struct indirectEntry *)ibh->b_data;
 	
 				loc = lelb_to_cpu(ie->indirectICB.extLocation);
@@ -1005,7 +1008,7 @@ __udf_read_inode(struct inode *inode)
 					if (ident == TAG_IDENT_FE ||
 						ident == TAG_IDENT_EFE)
 					{
-						memcpy(&UDF_I_LOCATION(inode), &loc, sizeof(lb_addr));
+						memcpy(&UDF_I_LOCATION(inode), &loc, sizeof(kernel_lb_addr));
 						udf_release_data(bh);
 						udf_release_data(ibh);
 						udf_release_data(nbh);
@@ -1313,11 +1316,13 @@ udf_convert_permissions(struct fileEntry *fe)
  *	Written, tested, and released.
  */
 
-void udf_write_inode(struct inode * inode, int sync)
+int udf_write_inode(struct inode * inode, int sync)
 {
+	int ret;
 	lock_kernel();
-	udf_update_inode(inode, sync);
+	ret = udf_update_inode(inode, sync);
 	unlock_kernel();
+	return ret;
 }
 
 int udf_sync_inode(struct inode * inode)
@@ -1335,7 +1340,7 @@ udf_update_inode(struct inode *inode, int do_sync)
 	uint16_t icbflags;
 	uint16_t crclen;
 	int i;
-	timestamp cpu_time;
+	kernel_timestamp cpu_time;
 	int err = 0;
 
 	bh = udf_tread(inode->i_sb,
@@ -1411,11 +1416,11 @@ udf_update_inode(struct inode *inode, int do_sync)
 				udf_add_extendedattr(inode,
 					sizeof(struct deviceSpec) +
 					sizeof(regid), 12, 0x3);
-			dsea->attrType = 12;
+			dsea->attrType = cpu_to_le32(12);
 			dsea->attrSubtype = 1;
-			dsea->attrLength = sizeof(struct deviceSpec) +
-				sizeof(regid);
-			dsea->impUseLength = sizeof(regid);
+			dsea->attrLength = cpu_to_le32(sizeof(struct deviceSpec) +
+				sizeof(regid));
+			dsea->impUseLength = cpu_to_le32(sizeof(regid));
 		}
 		eid = (regid *)dsea->impUse;
 		memset(eid, 0, sizeof(regid));
@@ -1446,7 +1451,7 @@ udf_update_inode(struct inode *inode, int do_sync)
 		fe->uniqueID = cpu_to_le64(UDF_I_UNIQUE(inode));
 		fe->lengthExtendedAttr = cpu_to_le32(UDF_I_LENEATTR(inode));
 		fe->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
-		fe->descTag.tagIdent = le16_to_cpu(TAG_IDENT_FE);
+		fe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_FE);
 		crclen = sizeof(struct fileEntry);
 	}
 	else
@@ -1492,7 +1497,7 @@ udf_update_inode(struct inode *inode, int do_sync)
 		efe->uniqueID = cpu_to_le64(UDF_I_UNIQUE(inode));
 		efe->lengthExtendedAttr = cpu_to_le32(UDF_I_LENEATTR(inode));
 		efe->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
-		efe->descTag.tagIdent = le16_to_cpu(TAG_IDENT_EFE);
+		efe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EFE);
 		crclen = sizeof(struct extendedFileEntry);
 	}
 	if (UDF_I_STRAT4096(inode))
@@ -1578,7 +1583,7 @@ udf_update_inode(struct inode *inode, int do_sync)
  * 12/19/98 dgb  Added semaphore and changed to be a wrapper of iget
  */
 struct inode *
-udf_iget(struct super_block *sb, lb_addr ino)
+udf_iget(struct super_block *sb, kernel_lb_addr ino)
 {
 	struct inode *inode;
 	unsigned long block;
@@ -1603,7 +1608,7 @@ udf_iget(struct super_block *sb, lb_addr ino)
 	else if (UDF_I_LOCATION(inode).logicalBlockNum == 0xFFFFFFFF &&
 		UDF_I_LOCATION(inode).partitionReferenceNum == 0xFFFF)
 	{
-		memcpy(&UDF_I_LOCATION(inode), &ino, sizeof(lb_addr));
+		memcpy(&UDF_I_LOCATION(inode), &ino, sizeof(kernel_lb_addr));
 		__udf_read_inode(inode);
 		if (is_bad_inode(inode))
 		{
@@ -1624,8 +1629,8 @@ udf_iget(struct super_block *sb, lb_addr ino)
 	return inode;
 }
 
-int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
-	lb_addr eloc, uint32_t elen, struct buffer_head **bh, int inc)
+int8_t udf_add_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
+	kernel_lb_addr eloc, uint32_t elen, struct buffer_head **bh, int inc)
 {
 	int adsize;
 	short_ad *sad = NULL;
@@ -1651,7 +1656,7 @@ int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
 		char *sptr, *dptr;
 		struct buffer_head *nbh;
 		int err, loffset;
-		lb_addr obloc = *bloc;
+		kernel_lb_addr obloc = *bloc;
 
 		if (!(bloc->logicalBlockNum = udf_new_block(inode->i_sb, NULL,
 			obloc.partitionReferenceNum, obloc.logicalBlockNum, &err)))
@@ -1764,8 +1769,8 @@ int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
 	return etype;
 }
 
-int8_t udf_write_aext(struct inode *inode, lb_addr bloc, int *extoffset,
-    lb_addr eloc, uint32_t elen, struct buffer_head *bh, int inc)
+int8_t udf_write_aext(struct inode *inode, kernel_lb_addr bloc, int *extoffset,
+    kernel_lb_addr eloc, uint32_t elen, struct buffer_head *bh, int inc)
 {
 	int adsize;
 	uint8_t *ptr;
@@ -1820,8 +1825,8 @@ int8_t udf_write_aext(struct inode *inode, lb_addr bloc, int *extoffset,
 	return (elen >> 30);
 }
 
-int8_t udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
-	lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
+int8_t udf_next_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
+	kernel_lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
 {
 	int8_t etype;
 
@@ -1842,8 +1847,8 @@ int8_t udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
 	return etype;
 }
 
-int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
-	lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
+int8_t udf_current_aext(struct inode *inode, kernel_lb_addr *bloc, int *extoffset,
+	kernel_lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
 {
 	int alen;
 	int8_t etype;
@@ -1901,10 +1906,11 @@ int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
 	return etype;
 }
 
-int8_t udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset,
-	lb_addr neloc, uint32_t nelen, struct buffer_head *bh)
+static int8_t
+udf_insert_aext(struct inode *inode, kernel_lb_addr bloc, int extoffset,
+		kernel_lb_addr neloc, uint32_t nelen, struct buffer_head *bh)
 {
-	lb_addr oeloc;
+	kernel_lb_addr oeloc;
 	uint32_t oelen;
 	int8_t etype;
 
@@ -1923,11 +1929,11 @@ int8_t udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset,
 	return (nelen >> 30);
 }
 
-int8_t udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
-	lb_addr eloc, uint32_t elen, struct buffer_head *nbh)
+int8_t udf_delete_aext(struct inode *inode, kernel_lb_addr nbloc, int nextoffset,
+	kernel_lb_addr eloc, uint32_t elen, struct buffer_head *nbh)
 {
 	struct buffer_head *obh;
-	lb_addr obloc;
+	kernel_lb_addr obloc;
 	int oextoffset, adsize;
 	int8_t etype;
 	struct allocExtDesc *aed;
@@ -1964,7 +1970,7 @@ int8_t udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
 			oextoffset = nextoffset - adsize;
 		}
 	}
-	memset(&eloc, 0x00, sizeof(lb_addr));
+	memset(&eloc, 0x00, sizeof(kernel_lb_addr));
 	elen = 0;
 
 	if (nbh != obh)
@@ -2015,8 +2021,8 @@ int8_t udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
 	return (elen >> 30);
 }
 
-int8_t inode_bmap(struct inode *inode, int block, lb_addr *bloc, uint32_t *extoffset,
-	lb_addr *eloc, uint32_t *elen, uint32_t *offset, struct buffer_head **bh)
+int8_t inode_bmap(struct inode *inode, int block, kernel_lb_addr *bloc, uint32_t *extoffset,
+	kernel_lb_addr *eloc, uint32_t *elen, uint32_t *offset, struct buffer_head **bh)
 {
 	uint64_t lbcount = 0, bcount = (uint64_t)block << inode->i_sb->s_blocksize_bits;
 	int8_t etype;
@@ -2054,7 +2060,7 @@ int8_t inode_bmap(struct inode *inode, int block, lb_addr *bloc, uint32_t *extof
 
 long udf_block_map(struct inode *inode, long block)
 {
-	lb_addr eloc, bloc;
+	kernel_lb_addr eloc, bloc;
 	uint32_t offset, extoffset, elen;
 	struct buffer_head *bh = NULL;
 	int ret;
diff --git a/fs/udf/misc.c b/fs/udf/misc.c
index 174d7a3ec..fd321f9ac 100644
--- a/fs/udf/misc.c
+++ b/fs/udf/misc.c
@@ -273,7 +273,7 @@ error_out:
 }
 
 struct buffer_head *
-udf_read_ptagged(struct super_block *sb, lb_addr loc, uint32_t offset, uint16_t *ident)
+udf_read_ptagged(struct super_block *sb, kernel_lb_addr loc, uint32_t offset, uint16_t *ident)
 {
 	return udf_read_tagged(sb, udf_get_lb_pblock(sb, loc, offset),
 		loc.logicalBlockNum + offset, ident);
@@ -293,8 +293,8 @@ void udf_update_tag(char *data, int length)
 	length -= sizeof(tag);
 
 	tptr->tagChecksum = 0;
-	tptr->descCRCLength = le16_to_cpu(length);
-	tptr->descCRC = le16_to_cpu(udf_crc(data + sizeof(tag), length, 0));
+	tptr->descCRCLength = cpu_to_le16(length);
+	tptr->descCRC = cpu_to_le16(udf_crc(data + sizeof(tag), length, 0));
 
 	for (i=0; i<16; i++)
 		if (i != 4)
@@ -305,9 +305,9 @@ void udf_new_tag(char *data, uint16_t ident, uint16_t version, uint16_t snum,
 	uint32_t loc, int length)
 {
 	tag *tptr = (tag *)data;
-	tptr->tagIdent = le16_to_cpu(ident);
-	tptr->descVersion = le16_to_cpu(version);
-	tptr->tagSerialNum = le16_to_cpu(snum);
-	tptr->tagLocation = le32_to_cpu(loc);
+	tptr->tagIdent = cpu_to_le16(ident);
+	tptr->descVersion = cpu_to_le16(version);
+	tptr->tagSerialNum = cpu_to_le16(snum);
+	tptr->tagLocation = cpu_to_le32(loc);
 	udf_update_tag(data, length);
 }
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index 86cf34e77..a0e9b733b 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -119,7 +119,7 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
 		crc = udf_crc(fibh->ebh->b_data, fibh->eoffset, crc);
 	}
 
-	cfi->descTag.descCRC = cpu_to_le32(crc);
+	cfi->descTag.descCRC = cpu_to_le16(crc);
 	cfi->descTag.descCRCLength = cpu_to_le16(crclen);
 
 	for (i=0; i<16; i++)
@@ -160,7 +160,7 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
 	uint8_t lfi;
 	uint16_t liu;
 	loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
-	lb_addr bloc, eloc;
+	kernel_lb_addr bloc, eloc;
 	uint32_t extoffset, elen, offset;
 	struct buffer_head *bh = NULL;
 
@@ -314,7 +314,7 @@ udf_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 	/* temporary shorthand for specifying files by inode number */
 	if (!strncmp(dentry->d_name.name, ".B=", 3) )
 	{
-		lb_addr lb = { 0, simple_strtoul(dentry->d_name.name+3, NULL, 0) };
+		kernel_lb_addr lb = { 0, simple_strtoul(dentry->d_name.name+3, NULL, 0) };
 		inode = udf_iget(dir->i_sb, lb);
 		if (!inode)
 		{
@@ -360,7 +360,7 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
 	uint8_t lfi;
 	uint16_t liu;
 	int block;
-	lb_addr bloc, eloc;
+	kernel_lb_addr bloc, eloc;
 	uint32_t extoffset, elen, offset;
 	struct buffer_head *bh = NULL;
 
@@ -655,7 +655,7 @@ static int udf_create(struct inode *dir, struct dentry *dentry, int mode, struct
 	}
 	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
 	cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
-	*(uint32_t *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
+	*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
 		cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL);
 	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
 	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
@@ -698,7 +698,7 @@ static int udf_mknod(struct inode * dir, struct dentry * dentry, int mode, dev_t
 	}
 	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
 	cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
-	*(uint32_t *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
+	*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
 		cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL);
 	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
 	if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
@@ -746,7 +746,7 @@ static int udf_mkdir(struct inode * dir, struct dentry * dentry, int mode)
 	inode->i_nlink = 2;
 	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
 	cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(dir));
-	*(uint32_t *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
+	*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
 		cpu_to_le32(UDF_I_UNIQUE(dir) & 0x00000000FFFFFFFFUL);
 	cfi.fileCharacteristics = FID_FILE_CHAR_DIRECTORY | FID_FILE_CHAR_PARENT;
 	udf_write_fi(inode, &cfi, fi, &fibh, NULL, NULL);
@@ -765,7 +765,7 @@ static int udf_mkdir(struct inode * dir, struct dentry * dentry, int mode)
 	}
 	cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
 	cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
-	*(uint32_t *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
+	*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
 		cpu_to_le32(UDF_I_UNIQUE(inode) & 0x00000000FFFFFFFFUL);
 	cfi.fileCharacteristics |= FID_FILE_CHAR_DIRECTORY;
 	udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
@@ -788,7 +788,7 @@ static int empty_dir(struct inode *dir)
 	loff_t f_pos;
 	loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
 	int block;
-	lb_addr bloc, eloc;
+	kernel_lb_addr bloc, eloc;
 	uint32_t extoffset, elen, offset;
 	struct buffer_head *bh = NULL;
 
@@ -861,7 +861,7 @@ static int udf_rmdir(struct inode * dir, struct dentry * dentry)
 	struct inode * inode = dentry->d_inode;
 	struct udf_fileident_bh fibh;
 	struct fileIdentDesc *fi, cfi;
-	lb_addr tloc;
+	kernel_lb_addr tloc;
 
 	retval = -ENOENT;
 	lock_kernel();
@@ -906,7 +906,7 @@ static int udf_unlink(struct inode * dir, struct dentry * dentry)
 	struct udf_fileident_bh fibh;
 	struct fileIdentDesc *fi;
 	struct fileIdentDesc cfi;
-	lb_addr tloc;
+	kernel_lb_addr tloc;
 
 	retval = -ENOENT;
 	lock_kernel();
@@ -971,7 +971,7 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
 	if (UDF_I_ALLOCTYPE(inode) != ICBTAG_FLAG_AD_IN_ICB)
 	{
 		struct buffer_head *bh = NULL;
-		lb_addr bloc, eloc;
+		kernel_lb_addr bloc, eloc;
 		uint32_t elen, extoffset;
 
 		block = udf_new_block(inode->i_sb, inode,
@@ -1085,7 +1085,7 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
 		uint64_t uniqueID;
 		lvhd = (struct logicalVolHeaderDesc *)(UDF_SB_LVID(inode->i_sb)->logicalVolContentsUse);
 		uniqueID = le64_to_cpu(lvhd->uniqueID);
-		*(uint32_t *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
+		*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
 			cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL);
 		if (!(++uniqueID & 0x00000000FFFFFFFFUL))
 			uniqueID += 16;
@@ -1142,7 +1142,7 @@ static int udf_link(struct dentry * old_dentry, struct inode * dir,
 		uint64_t uniqueID;
 		lvhd = (struct logicalVolHeaderDesc *)(UDF_SB_LVID(inode->i_sb)->logicalVolContentsUse);
 		uniqueID = le64_to_cpu(lvhd->uniqueID);
-		*(uint32_t *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
+		*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
 			cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL);
 		if (!(++uniqueID & 0x00000000FFFFFFFFUL))
 			uniqueID += 16;
@@ -1178,7 +1178,7 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
 	struct fileIdentDesc *ofi = NULL, *nfi = NULL, *dir_fi = NULL, ocfi, ncfi;
 	struct buffer_head *dir_bh = NULL;
 	int retval = -ENOENT;
-	lb_addr tloc;
+	kernel_lb_addr tloc;
 
 	lock_kernel();
 	if ((ofi = udf_find_entry(old_dir, old_dentry, &ofibh, &ocfi)))
@@ -1231,7 +1231,7 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
 		}
 		if (!dir_fi)
 			goto end_rename;
-		tloc = cpu_to_lelb(dir_fi->icb.extLocation);
+		tloc = lelb_to_cpu(dir_fi->icb.extLocation);
 		if (udf_get_lb_pblock(old_inode->i_sb, tloc, 0)
 					!= old_dir->i_ino)
 			goto end_rename;
@@ -1277,9 +1277,9 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
 
 	if (dir_fi)
 	{
-		dir_fi->icb.extLocation = lelb_to_cpu(UDF_I_LOCATION(new_dir));
+		dir_fi->icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(new_dir));
 		udf_update_tag((char *)dir_fi, (sizeof(struct fileIdentDesc) +
-			cpu_to_le16(dir_fi->lengthOfImpUse) + 3) & ~3);
+			le16_to_cpu(dir_fi->lengthOfImpUse) + 3) & ~3);
 		if (UDF_I_ALLOCTYPE(old_inode) == ICBTAG_FLAG_AD_IN_ICB)
 		{
 			mark_inode_dirty(old_inode);
diff --git a/fs/udf/osta_udf.h b/fs/udf/osta_udf.h
index 037d0b7e3..e82aae652 100644
--- a/fs/udf/osta_udf.h
+++ b/fs/udf/osta_udf.h
@@ -67,7 +67,7 @@
 
 struct UDFIdentSuffix
 {
-	uint16_t	UDFRevision;
+	__le16		UDFRevision;
 	uint8_t		OSClass;
 	uint8_t		OSIdentifier;
 	uint8_t		reserved[4];
@@ -90,11 +90,11 @@ struct appIdentSuffix
 struct logicalVolIntegrityDescImpUse
 {
 	regid		impIdent;
-	uint32_t	numFiles;
-	uint32_t	numDirs;
-	uint16_t	minUDFReadRev;
-	uint16_t	minUDFWriteRev;
-	uint16_t	maxUDFWriteRev;
+	__le32		numFiles;
+	__le32		numDirs;
+	__le16		minUDFReadRev;
+	__le16		minUDFWriteRev;
+	__le16		maxUDFWriteRev;
 	uint8_t		impUse[0];
 } __attribute__ ((packed));
 
@@ -117,8 +117,8 @@ struct udfPartitionMap2
 	uint8_t		partitionMapLength;
 	uint8_t		reserved1[2];
 	regid		partIdent;
-	uint16_t	volSeqNum;
-	uint16_t	partitionNum;
+	__le16		volSeqNum;
+	__le16		partitionNum;
 } __attribute__ ((packed));
 
 /* Virtual Partition Map (UDF 2.50 2.2.8) */
@@ -128,8 +128,8 @@ struct virtualPartitionMap
 	uint8_t		partitionMapLength;
 	uint8_t		reserved1[2];
 	regid		partIdent;
-	uint16_t	volSeqNum;
-	uint16_t	partitionNum;
+	__le16		volSeqNum;
+	__le16		partitionNum;
 	uint8_t		reserved2[24];
 } __attribute__ ((packed));
 
@@ -140,13 +140,13 @@ struct sparablePartitionMap
 	uint8_t		partitionMapLength;
 	uint8_t		reserved1[2];
 	regid		partIdent;
-	uint16_t	volSeqNum;
-	uint16_t	partitionNum;
-	uint16_t	packetLength;
+	__le16		volSeqNum;
+	__le16		partitionNum;
+	__le16		packetLength;
 	uint8_t		numSparingTables;
 	uint8_t		reserved2[1];
-	uint32_t	sizeSparingTable;
-	uint32_t	locSparingTable[4];
+	__le32		sizeSparingTable;
+	__le32		locSparingTable[4];
 } __attribute__ ((packed));
 
 /* Metadata Partition Map (UDF 2.4.0 2.2.10) */
@@ -156,13 +156,13 @@ struct metadataPartitionMap
 	uint8_t		partitionMapLength;
 	uint8_t		reserved1[2];
 	regid		partIdent;
-	uint16_t	volSeqNum;
-	uint16_t	partitionNum;
-	uint32_t	metadataFileLoc;
-	uint32_t	metadataMirrorFileLoc;
-	uint32_t	metadataBitmapFileLoc;
-	uint32_t	allocUnitSize;
-	uint16_t	alignUnitSize;
+	__le16		volSeqNum;
+	__le16		partitionNum;
+	__le32		metadataFileLoc;
+	__le32		metadataMirrorFileLoc;
+	__le32		metadataBitmapFileLoc;
+	__le32		allocUnitSize;
+	__le16		alignUnitSize;
 	uint8_t		flags;
 	uint8_t		reserved2[5];
 } __attribute__ ((packed));
@@ -170,9 +170,9 @@ struct metadataPartitionMap
 /* Virtual Allocation Table (UDF 1.5 2.2.10) */
 struct virtualAllocationTable15
 {
-	uint32_t	VirtualSector[0];
+	__le32		VirtualSector[0];
 	regid		vatIdent;
-	uint32_t	previousVATICBLoc;
+	__le32		previousVATICBLoc;
 } __attribute__ ((packed));  
 
 #define ICBTAG_FILE_TYPE_VAT15		0x00U
@@ -180,18 +180,18 @@ struct virtualAllocationTable15
 /* Virtual Allocation Table (UDF 2.50 2.2.11) */
 struct virtualAllocationTable20
 {
-	uint16_t	lengthHeader;
-	uint16_t	lengthImpUse;
+	__le16		lengthHeader;
+	__le16		lengthImpUse;
 	dstring		logicalVolIdent[128];
-	uint32_t	previousVATICBLoc;
-	uint32_t	numFiles;
-	uint32_t	numDirs;
-	uint16_t	minReadRevision;
-	uint16_t	minWriteRevision;
-	uint16_t	maxWriteRevision;
-	uint16_t	reserved;
+	__le32		previousVATICBLoc;
+	__le32		numFiles;
+	__le32		numDirs;
+	__le16		minReadRevision;
+	__le16		minWriteRevision;
+	__le16		maxWriteRevision;
+	__le16		reserved;
 	uint8_t		impUse[0];
-	uint32_t	vatEntry[0];
+	__le32		vatEntry[0];
 } __attribute__ ((packed));
 
 #define ICBTAG_FILE_TYPE_VAT20		0xF8U
@@ -199,17 +199,17 @@ struct virtualAllocationTable20
 /* Sparing Table (UDF 2.50 2.2.12) */
 struct sparingEntry
 {
-	uint32_t	origLocation;
-	uint32_t	mappedLocation;
+	__le32		origLocation;
+	__le32		mappedLocation;
 } __attribute__ ((packed));
 
 struct sparingTable
 {
 	tag 		descTag;
 	regid		sparingIdent;
-	uint16_t	reallocationTableLen;
-	uint16_t	reserved;
-	uint32_t	sequenceNum;
+	__le16		reallocationTableLen;
+	__le16		reserved;
+	__le32		sequenceNum;
 	struct sparingEntry
 			mapEntry[0];
 } __attribute__ ((packed));
@@ -222,7 +222,7 @@ struct sparingTable
 /* struct long_ad ICB - ADImpUse (UDF 2.50 2.2.4.3) */
 struct allocDescImpUse
 {
-	uint16_t	flags;
+	__le16		flags;
 	uint8_t		impUse[4];
 } __attribute__ ((packed));
 
@@ -235,14 +235,14 @@ struct allocDescImpUse
 /* FreeEASpace (UDF 2.50 3.3.4.5.1.1) */
 struct freeEaSpace
 {
-	uint16_t	headerChecksum;
+	__le16		headerChecksum;
 	uint8_t		freeEASpace[0];
 } __attribute__ ((packed));
 
 /* DVD Copyright Management Information (UDF 2.50 3.3.4.5.1.2) */
 struct DVDCopyrightImpUse 
 {
-	uint16_t	headerChecksum;
+	__le16		headerChecksum;
 	uint8_t		CGMSInfo;
 	uint8_t		dataType;
 	uint8_t		protectionSystemInfo[4];
@@ -252,7 +252,7 @@ struct DVDCopyrightImpUse
 /* FreeAppEASpace (UDF 2.50 3.3.4.6.1) */
 struct freeAppEASpace
 {
-	uint16_t	headerChecksum;
+	__le16		headerChecksum;
 	uint8_t		freeEASpace[0];
 } __attribute__ ((packed));
 
diff --git a/fs/udf/partition.c b/fs/udf/partition.c
index e182fb8a8..4d36f264b 100644
--- a/fs/udf/partition.c
+++ b/fs/udf/partition.c
@@ -84,7 +84,7 @@ uint32_t udf_get_pblock_virt15(struct super_block *sb, uint32_t block, uint16_t
 		return 0xFFFFFFFF;
 	}
 
-	loc = le32_to_cpu(((uint32_t *)bh->b_data)[index]);
+	loc = le32_to_cpu(((__le32 *)bh->b_data)[index]);
 
 	udf_release_data(bh);
 
@@ -119,7 +119,7 @@ uint32_t udf_get_pblock_spar15(struct super_block *sb, uint32_t block, uint16_t
 
 	if (st)
 	{
-		for (i=0; i<st->reallocationTableLen; i++)
+		for (i=0; i<le16_to_cpu(st->reallocationTableLen); i++)
 		{
 			if (le32_to_cpu(st->mapEntry[i].origLocation) >= 0xFFFFFFF0)
 				break;
@@ -163,7 +163,7 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
 			if (!st)
 				return 1;
 
-			for (k=0; k<st->reallocationTableLen; k++)
+			for (k=0; k<le16_to_cpu(st->reallocationTableLen); k++)
 			{
 				if (le32_to_cpu(st->mapEntry[k].origLocation) == 0xFFFFFFFF)
 				{
@@ -173,7 +173,7 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
 						{
 							st = (struct sparingTable *)sdata->s_spar_map[j]->b_data;
 							st->mapEntry[k].origLocation = cpu_to_le32(packet);
-							udf_update_tag((char *)st, sizeof(struct sparingTable) + st->reallocationTableLen * sizeof(struct sparingEntry));
+							udf_update_tag((char *)st, sizeof(struct sparingTable) + le16_to_cpu(st->reallocationTableLen) * sizeof(struct sparingEntry));
 							mark_buffer_dirty(sdata->s_spar_map[j]);
 						}
 					}
@@ -190,7 +190,7 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
 				else if (le32_to_cpu(st->mapEntry[k].origLocation) > packet)
 					break;
 			}
-			for (l=k; l<st->reallocationTableLen; l++)
+			for (l=k; l<le16_to_cpu(st->reallocationTableLen); l++)
 			{
 				if (le32_to_cpu(st->mapEntry[l].origLocation) == 0xFFFFFFFF)
 				{
@@ -203,7 +203,7 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
 							mapEntry.origLocation = cpu_to_le32(packet);
 							memmove(&st->mapEntry[k+1], &st->mapEntry[k], (l-k)*sizeof(struct sparingEntry));
 							st->mapEntry[k] = mapEntry;
-							udf_update_tag((char *)st, sizeof(struct sparingTable) + st->reallocationTableLen * sizeof(struct sparingEntry));
+							udf_update_tag((char *)st, sizeof(struct sparingTable) + le16_to_cpu(st->reallocationTableLen) * sizeof(struct sparingEntry));
 							mark_buffer_dirty(sdata->s_spar_map[j]);
 						}
 					}
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 54e1ecffa..1865c5a44 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -85,13 +85,13 @@ static void udf_write_super(struct super_block *);
 static int udf_remount_fs(struct super_block *, int *, char *);
 static int udf_check_valid(struct super_block *, int, int);
 static int udf_vrs(struct super_block *sb, int silent);
-static int udf_load_partition(struct super_block *, lb_addr *);
-static int udf_load_logicalvol(struct super_block *, struct buffer_head *, lb_addr *);
-static void udf_load_logicalvolint(struct super_block *, extent_ad);
+static int udf_load_partition(struct super_block *, kernel_lb_addr *);
+static int udf_load_logicalvol(struct super_block *, struct buffer_head *, kernel_lb_addr *);
+static void udf_load_logicalvolint(struct super_block *, kernel_extent_ad);
 static void udf_find_anchor(struct super_block *);
-static int udf_find_fileset(struct super_block *, lb_addr *, lb_addr *);
+static int udf_find_fileset(struct super_block *, kernel_lb_addr *, kernel_lb_addr *);
 static void udf_load_pvoldesc(struct super_block *, struct buffer_head *);
-static void udf_load_fileset(struct super_block *, struct buffer_head *, lb_addr *);
+static void udf_load_fileset(struct super_block *, struct buffer_head *, kernel_lb_addr *);
 static void udf_load_partdesc(struct super_block *, struct buffer_head *);
 static void udf_open_lvid(struct super_block *);
 static void udf_close_lvid(struct super_block *);
@@ -145,7 +145,7 @@ static int init_inodecache(void)
 {
 	udf_inode_cachep = kmem_cache_create("udf_inode_cache",
 					     sizeof(struct udf_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (udf_inode_cachep == NULL)
 		return -ENOMEM;
@@ -194,7 +194,6 @@ struct udf_options
 static int __init init_udf_fs(void)
 {
 	int err;
-	printk(KERN_NOTICE "udf: registering filesystem\n");
 	err = init_inodecache();
 	if (err)
 		goto out1;
@@ -210,7 +209,6 @@ out1:
 
 static void __exit exit_udf_fs(void)
 {
-	printk(KERN_NOTICE "udf: unregistering filesystem\n");
 	unregister_filesystem(&udf_fstype);
 	destroy_inodecache();
 }
@@ -771,7 +769,7 @@ udf_find_anchor(struct super_block *sb)
 }
 
 static int 
-udf_find_fileset(struct super_block *sb, lb_addr *fileset, lb_addr *root)
+udf_find_fileset(struct super_block *sb, kernel_lb_addr *fileset, kernel_lb_addr *root)
 {
 	struct buffer_head *bh = NULL;
 	long lastblock;
@@ -794,7 +792,7 @@ udf_find_fileset(struct super_block *sb, lb_addr *fileset, lb_addr *root)
 
 	if (!bh) /* Search backwards through the partitions */
 	{
-		lb_addr newfileset;
+		kernel_lb_addr newfileset;
 
 		return 1;
 		
@@ -876,7 +874,7 @@ udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh)
 	if ( udf_stamp_to_time(&recording, &recording_usec,
 		lets_to_cpu(pvoldesc->recordingDateAndTime)) )
 	{
-		timestamp ts;
+		kernel_timestamp ts;
 		ts = lets_to_cpu(pvoldesc->recordingDateAndTime);
 		udf_debug("recording time %ld/%ld, %04u/%02u/%02u %02u:%02u (%x)\n",
 			recording, recording_usec,
@@ -903,7 +901,7 @@ udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh)
 }
 
 static void 
-udf_load_fileset(struct super_block *sb, struct buffer_head *bh, lb_addr *root)
+udf_load_fileset(struct super_block *sb, struct buffer_head *bh, kernel_lb_addr *root)
 {
 	struct fileSetDesc *fset;
 
@@ -950,7 +948,7 @@ udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
 				phd = (struct partitionHeaderDesc *)(p->partitionContentsUse);
 				if (phd->unallocSpaceTable.extLength)
 				{
-					lb_addr loc = { le32_to_cpu(phd->unallocSpaceTable.extPosition), i };
+					kernel_lb_addr loc = { le32_to_cpu(phd->unallocSpaceTable.extPosition), i };
 
 					UDF_SB_PARTMAPS(sb)[i].s_uspace.s_table =
 						udf_iget(sb, loc);
@@ -976,7 +974,7 @@ udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
 					udf_debug("partitionIntegrityTable (part %d)\n", i);
 				if (phd->freedSpaceTable.extLength)
 				{
-					lb_addr loc = { le32_to_cpu(phd->freedSpaceTable.extPosition), i };
+					kernel_lb_addr loc = { le32_to_cpu(phd->freedSpaceTable.extPosition), i };
 
 					UDF_SB_PARTMAPS(sb)[i].s_fspace.s_table =
 						udf_iget(sb, loc);
@@ -1015,7 +1013,7 @@ udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
 }
 
 static int 
-udf_load_logicalvol(struct super_block *sb, struct buffer_head * bh, lb_addr *fileset)
+udf_load_logicalvol(struct super_block *sb, struct buffer_head * bh, kernel_lb_addr *fileset)
 {
 	struct logicalVolDesc *lvd;
 	int i, j, offset;
@@ -1043,12 +1041,12 @@ udf_load_logicalvol(struct super_block *sb, struct buffer_head * bh, lb_addr *fi
 			struct udfPartitionMap2 *upm2 = (struct udfPartitionMap2 *)&(lvd->partitionMaps[offset]);
 			if (!strncmp(upm2->partIdent.ident, UDF_ID_VIRTUAL, strlen(UDF_ID_VIRTUAL)))
 			{
-				if (le16_to_cpu(((uint16_t *)upm2->partIdent.identSuffix)[0]) == 0x0150)
+				if (le16_to_cpu(((__le16 *)upm2->partIdent.identSuffix)[0]) == 0x0150)
 				{
 					UDF_SB_PARTTYPE(sb,i) = UDF_VIRTUAL_MAP15;
 					UDF_SB_PARTFUNC(sb,i) = udf_get_pblock_virt15;
 				}
-				else if (le16_to_cpu(((uint16_t *)upm2->partIdent.identSuffix)[0]) == 0x0200)
+				else if (le16_to_cpu(((__le16 *)upm2->partIdent.identSuffix)[0]) == 0x0200)
 				{
 					UDF_SB_PARTTYPE(sb,i) = UDF_VIRTUAL_MAP20;
 					UDF_SB_PARTFUNC(sb,i) = udf_get_pblock_virt20;
@@ -1112,7 +1110,7 @@ udf_load_logicalvol(struct super_block *sb, struct buffer_head * bh, lb_addr *fi
  *
  */
 static void
-udf_load_logicalvolint(struct super_block *sb, extent_ad loc)
+udf_load_logicalvolint(struct super_block *sb, kernel_extent_ad loc)
 {
 	struct buffer_head *bh = NULL;
 	uint16_t ident;
@@ -1152,7 +1150,7 @@ udf_load_logicalvolint(struct super_block *sb, extent_ad loc)
  *	Written, tested, and released.
  */
 static  int
-udf_process_sequence(struct super_block *sb, long block, long lastblock, lb_addr *fileset)
+udf_process_sequence(struct super_block *sb, long block, long lastblock, kernel_lb_addr *fileset)
 {
 	struct buffer_head *bh = NULL;
 	struct udf_vds_record vds[VDS_POS_LENGTH];
@@ -1295,7 +1293,7 @@ udf_check_valid(struct super_block *sb, int novrs, int silent)
 }
 
 static int
-udf_load_partition(struct super_block *sb, lb_addr *fileset)
+udf_load_partition(struct super_block *sb, kernel_lb_addr *fileset)
 {
 	struct anchorVolDescPtr *anchor;
 	uint16_t ident;
@@ -1352,7 +1350,7 @@ udf_load_partition(struct super_block *sb, lb_addr *fileset)
 			case UDF_VIRTUAL_MAP15:
 			case UDF_VIRTUAL_MAP20:
 			{
-				lb_addr ino;
+				kernel_lb_addr ino;
 
 				if (!UDF_SB_LASTBLOCK(sb))
 				{
@@ -1417,7 +1415,7 @@ static void udf_open_lvid(struct super_block *sb)
 	if (UDF_SB_LVIDBH(sb))
 	{
 		int i;
-		timestamp cpu_time;
+		kernel_timestamp cpu_time;
 
 		UDF_SB_LVIDIU(sb)->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
 		UDF_SB_LVIDIU(sb)->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
@@ -1445,7 +1443,7 @@ static void udf_close_lvid(struct super_block *sb)
 		UDF_SB_LVID(sb)->integrityType == LVID_INTEGRITY_TYPE_OPEN)
 	{
 		int i;
-		timestamp cpu_time;
+		kernel_timestamp cpu_time;
 
 		UDF_SB_LVIDIU(sb)->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
 		UDF_SB_LVIDIU(sb)->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
@@ -1457,7 +1455,7 @@ static void udf_close_lvid(struct super_block *sb)
 			UDF_SB_LVIDIU(sb)->minUDFReadRev = cpu_to_le16(UDF_SB_UDFREV(sb));
 		if (UDF_SB_UDFREV(sb) > le16_to_cpu(UDF_SB_LVIDIU(sb)->minUDFWriteRev))
 			UDF_SB_LVIDIU(sb)->minUDFWriteRev = cpu_to_le16(UDF_SB_UDFREV(sb));
-		UDF_SB_LVID(sb)->integrityType = LVID_INTEGRITY_TYPE_CLOSE;
+		UDF_SB_LVID(sb)->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE);
 
 		UDF_SB_LVID(sb)->descTag.descCRC =
 			cpu_to_le16(udf_crc((char *)UDF_SB_LVID(sb) + sizeof(tag),
@@ -1494,7 +1492,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
 	int i;
 	struct inode *inode=NULL;
 	struct udf_options uopt;
-	lb_addr rootdir, fileset;
+	kernel_lb_addr rootdir, fileset;
 	struct udf_sb_info *sbi;
 
 	uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT);
@@ -1587,7 +1585,8 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
 		if (minUDFReadRev > UDF_MAX_READ_VERSION)
 		{
 			printk("UDF-fs: minUDFReadRev=%x (max is %x)\n",
-				UDF_SB_LVIDIU(sb)->minUDFReadRev, UDF_MAX_READ_VERSION);
+				le16_to_cpu(UDF_SB_LVIDIU(sb)->minUDFReadRev),
+				UDF_MAX_READ_VERSION);
 			goto error_out;
 		}
 		else if (minUDFWriteRev > UDF_MAX_WRITE_VERSION)
@@ -1617,7 +1616,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
 
 	if (!silent)
 	{
-		timestamp ts;
+		kernel_timestamp ts;
 		udf_time_to_stamp(&ts, UDF_SB_RECORDTIME(sb));
 		udf_info("UDF %s (%s) Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
 			UDFFS_VERSION, UDFFS_DATE,
@@ -1800,7 +1799,7 @@ udf_count_free_bitmap(struct super_block *sb, struct udf_bitmap *bitmap)
 	unsigned int accum = 0;
 	int index;
 	int block = 0, newblock;
-	lb_addr loc;
+	kernel_lb_addr loc;
 	uint32_t bytes;
 	uint8_t value;
 	uint8_t *ptr;
@@ -1826,7 +1825,7 @@ udf_count_free_bitmap(struct super_block *sb, struct udf_bitmap *bitmap)
 	}
 
 	bm = (struct spaceBitmapDesc *)bh->b_data;
-	bytes = bm->numOfBytes;
+	bytes = le32_to_cpu(bm->numOfBytes);
 	index = sizeof(struct spaceBitmapDesc); /* offset in first block only */
 	ptr = (uint8_t *)bh->b_data;
 
@@ -1867,7 +1866,7 @@ udf_count_free_table(struct super_block *sb, struct inode * table)
 {
 	unsigned int accum = 0;
 	uint32_t extoffset, elen;
-	lb_addr bloc, eloc;
+	kernel_lb_addr bloc, eloc;
 	int8_t etype;
 	struct buffer_head *bh = NULL;
 
diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c
index b51ea9cf0..7dc8a5572 100644
--- a/fs/udf/truncate.c
+++ b/fs/udf/truncate.c
@@ -33,10 +33,10 @@
 #include "udf_i.h"
 #include "udf_sb.h"
 
-static void extent_trunc(struct inode * inode, lb_addr bloc, int extoffset,
-	lb_addr eloc, int8_t etype, uint32_t elen, struct buffer_head *bh, uint32_t nelen)
+static void extent_trunc(struct inode * inode, kernel_lb_addr bloc, int extoffset,
+	kernel_lb_addr eloc, int8_t etype, uint32_t elen, struct buffer_head *bh, uint32_t nelen)
 {
-	lb_addr neloc = { 0, 0 };
+	kernel_lb_addr neloc = { 0, 0 };
 	int last_block = (elen + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
 	int first_block = (nelen + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
 
@@ -68,7 +68,7 @@ static void extent_trunc(struct inode * inode, lb_addr bloc, int extoffset,
 
 void udf_discard_prealloc(struct inode * inode)
 {
-	lb_addr bloc, eloc;
+	kernel_lb_addr bloc, eloc;
 	uint32_t extoffset = 0, elen, nelen;
 	uint64_t lbcount = 0;
 	int8_t etype = -1, netype;
@@ -129,7 +129,7 @@ void udf_discard_prealloc(struct inode * inode)
 
 void udf_truncate_extents(struct inode * inode)
 {
-	lb_addr bloc, eloc, neloc = { 0, 0 };
+	kernel_lb_addr bloc, eloc, neloc = { 0, 0 };
 	uint32_t extoffset, elen, offset, nelen = 0, lelen = 0, lenalloc;
 	int8_t etype;
 	int first_block = inode->i_size >> inode->i_sb->s_blocksize_bits;
@@ -254,7 +254,7 @@ void udf_truncate_extents(struct inode * inode)
 			}
 			else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30))
 			{
-				lb_addr neloc = { 0, 0 };
+				kernel_lb_addr neloc = { 0, 0 };
 				extoffset -= adsize;
 				nelen = EXT_NOT_RECORDED_NOT_ALLOCATED |
 					((elen + offset + inode->i_sb->s_blocksize - 1) &
@@ -272,7 +272,7 @@ void udf_truncate_extents(struct inode * inode)
 						~(inode->i_sb->s_blocksize - 1));
 					udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 1);
 				}
-				memset(&eloc, 0x00, sizeof(lb_addr));
+				memset(&eloc, 0x00, sizeof(kernel_lb_addr));
 				elen = EXT_NOT_RECORDED_NOT_ALLOCATED | offset;
 				udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1);
 			}
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index ecff2e19f..87a9331ba 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -68,7 +68,7 @@ struct udf_vds_record
 struct generic_desc
 {
 	tag		descTag;
-	uint32_t	volDescSeqNum;
+	__le32		volDescSeqNum;
 };
 
 struct ustr
@@ -89,35 +89,32 @@ extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *, struct file
 extern int udf_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
 
 /* inode.c */
-extern struct inode *udf_iget(struct super_block *, lb_addr);
+extern struct inode *udf_iget(struct super_block *, kernel_lb_addr);
 extern int udf_sync_inode(struct inode *);
 extern void udf_expand_file_adinicb(struct inode *, int, int *);
 extern struct buffer_head * udf_expand_dir_adinicb(struct inode *, int *, int *);
-extern struct buffer_head * udf_getblk(struct inode *, long, int, int *);
 extern struct buffer_head * udf_bread(struct inode *, int, int, int *);
 extern void udf_truncate(struct inode *);
 extern void udf_read_inode(struct inode *);
 extern void udf_put_inode(struct inode *);
 extern void udf_delete_inode(struct inode *);
 extern void udf_clear_inode(struct inode *);
-extern void udf_write_inode(struct inode *, int);
+extern int udf_write_inode(struct inode *, int);
 extern long udf_block_map(struct inode *, long);
-extern int8_t inode_bmap(struct inode *, int, lb_addr *, uint32_t *, lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
-extern int8_t udf_add_aext(struct inode *, lb_addr *, int *, lb_addr, uint32_t, struct buffer_head **, int);
-extern int8_t udf_write_aext(struct inode *, lb_addr, int *, lb_addr, uint32_t, struct buffer_head *, int);
-extern int8_t udf_insert_aext(struct inode *, lb_addr, int, lb_addr, uint32_t, struct buffer_head *);
-extern int8_t udf_delete_aext(struct inode *, lb_addr, int, lb_addr, uint32_t, struct buffer_head *);
-extern int8_t udf_next_aext(struct inode *, lb_addr *, int *, lb_addr *, uint32_t *, struct buffer_head **, int);
-extern int8_t udf_current_aext(struct inode *, lb_addr *, int *, lb_addr *, uint32_t *, struct buffer_head **, int);
+extern int8_t inode_bmap(struct inode *, int, kernel_lb_addr *, uint32_t *, kernel_lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
+extern int8_t udf_add_aext(struct inode *, kernel_lb_addr *, int *, kernel_lb_addr, uint32_t, struct buffer_head **, int);
+extern int8_t udf_write_aext(struct inode *, kernel_lb_addr, int *, kernel_lb_addr, uint32_t, struct buffer_head *, int);
+extern int8_t udf_delete_aext(struct inode *, kernel_lb_addr, int, kernel_lb_addr, uint32_t, struct buffer_head *);
+extern int8_t udf_next_aext(struct inode *, kernel_lb_addr *, int *, kernel_lb_addr *, uint32_t *, struct buffer_head **, int);
+extern int8_t udf_current_aext(struct inode *, kernel_lb_addr *, int *, kernel_lb_addr *, uint32_t *, struct buffer_head **, int);
 
 /* misc.c */
-extern int udf_read_tagged_data(char *, int size, int fd, int block, int partref);
 extern struct buffer_head *udf_tgetblk(struct super_block *, int);
 extern struct buffer_head *udf_tread(struct super_block *, int);
 extern struct genericFormat *udf_add_extendedattr(struct inode *, uint32_t, uint32_t, uint8_t);
 extern struct genericFormat *udf_get_extendedattr(struct inode *, uint32_t, uint8_t);
 extern struct buffer_head *udf_read_tagged(struct super_block *, uint32_t, uint32_t, uint16_t *);
-extern struct buffer_head *udf_read_ptagged(struct super_block *, lb_addr, uint32_t, uint16_t *);
+extern struct buffer_head *udf_read_ptagged(struct super_block *, kernel_lb_addr, uint32_t, uint16_t *);
 extern void udf_release_data(struct buffer_head *);
 extern void udf_update_tag(char *, int);
 extern void udf_new_tag(char *, uint16_t, uint16_t, uint16_t, uint32_t, int);
@@ -148,28 +145,24 @@ extern void udf_discard_prealloc(struct inode *);
 extern void udf_truncate_extents(struct inode *);
 
 /* balloc.c */
-extern void udf_free_blocks(struct super_block *, struct inode *, lb_addr, uint32_t, uint32_t);
+extern void udf_free_blocks(struct super_block *, struct inode *, kernel_lb_addr, uint32_t, uint32_t);
 extern int udf_prealloc_blocks(struct super_block *, struct inode *, uint16_t, uint32_t, uint32_t);
 extern int udf_new_block(struct super_block *, struct inode *, uint16_t, uint32_t, int *);
 
 /* fsync.c */
 extern int udf_fsync_file(struct file *, struct dentry *, int);
-extern int udf_fsync_inode(struct inode *, int);
 
 /* directory.c */
-extern uint8_t * udf_filead_read(struct inode *, uint8_t *, uint8_t, lb_addr, int *, int *, struct buffer_head **, int *);
-extern struct fileIdentDesc * udf_fileident_read(struct inode *, loff_t *, struct udf_fileident_bh *, struct fileIdentDesc *, lb_addr *, uint32_t *, lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
+extern struct fileIdentDesc * udf_fileident_read(struct inode *, loff_t *, struct udf_fileident_bh *, struct fileIdentDesc *, kernel_lb_addr *, uint32_t *, kernel_lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
 extern struct fileIdentDesc * udf_get_fileident(void * buffer, int bufsize, int * offset);
-extern extent_ad * udf_get_fileextent(void * buffer, int bufsize, int * offset);
 extern long_ad * udf_get_filelongad(uint8_t *, int, int *, int);
 extern short_ad * udf_get_fileshortad(uint8_t *, int, int *, int);
-extern uint8_t * udf_get_filead(struct fileEntry *, uint8_t *, int, int, int, int *);
 
 /* crc.c */
 extern uint16_t udf_crc(uint8_t *, uint32_t, uint16_t);
 
 /* udftime.c */
-extern time_t *udf_stamp_to_time(time_t *, long *, timestamp);
-extern timestamp *udf_time_to_stamp(timestamp *, struct timespec);
+extern time_t *udf_stamp_to_time(time_t *, long *, kernel_timestamp);
+extern kernel_timestamp *udf_time_to_stamp(kernel_timestamp *, struct timespec);
 
 #endif /* __UDF_DECL_H */
diff --git a/fs/udf/udfend.h b/fs/udf/udfend.h
index 6313daab0..17d378879 100644
--- a/fs/udf/udfend.h
+++ b/fs/udf/udfend.h
@@ -4,15 +4,15 @@
 #include <asm/byteorder.h>
 #include <linux/string.h>
 
-static inline lb_addr lelb_to_cpu(lb_addr in)
+static inline kernel_lb_addr lelb_to_cpu(lb_addr in)
 {
-	lb_addr out;
+	kernel_lb_addr out;
 	out.logicalBlockNum = le32_to_cpu(in.logicalBlockNum);
 	out.partitionReferenceNum = le16_to_cpu(in.partitionReferenceNum);
 	return out;
 }
 
-static inline lb_addr cpu_to_lelb(lb_addr in)
+static inline lb_addr cpu_to_lelb(kernel_lb_addr in)
 {
 	lb_addr out;
 	out.logicalBlockNum = cpu_to_le32(in.logicalBlockNum);
@@ -20,9 +20,9 @@ static inline lb_addr cpu_to_lelb(lb_addr in)
 	return out;
 }
 
-static inline timestamp lets_to_cpu(timestamp in)
+static inline kernel_timestamp lets_to_cpu(timestamp in)
 {
-	timestamp out;
+	kernel_timestamp out;
 	memcpy(&out, &in, sizeof(timestamp));
 	out.typeAndTimezone = le16_to_cpu(in.typeAndTimezone);
 	out.year = le16_to_cpu(in.year);
@@ -45,15 +45,15 @@ static inline short_ad cpu_to_lesa(short_ad in)
 	return out;
 }
 
-static inline long_ad lela_to_cpu(long_ad in)
+static inline kernel_long_ad lela_to_cpu(long_ad in)
 {
-	long_ad out;
+	kernel_long_ad out;
 	out.extLength = le32_to_cpu(in.extLength);
 	out.extLocation = lelb_to_cpu(in.extLocation);
 	return out;
 }
 
-static inline long_ad cpu_to_lela(long_ad in)
+static inline long_ad cpu_to_lela(kernel_long_ad in)
 {
 	long_ad out;
 	out.extLength = cpu_to_le32(in.extLength);
@@ -61,15 +61,15 @@ static inline long_ad cpu_to_lela(long_ad in)
 	return out;
 }
 
-static inline extent_ad leea_to_cpu(extent_ad in)
+static inline kernel_extent_ad leea_to_cpu(extent_ad in)
 {
-	extent_ad out;
+	kernel_extent_ad out;
 	out.extLength = le32_to_cpu(in.extLength);
 	out.extLocation = le32_to_cpu(in.extLocation);
 	return out;
 }
 
-static inline timestamp cpu_to_lets(timestamp in)
+static inline timestamp cpu_to_lets(kernel_timestamp in)
 {
 	timestamp out;
 	memcpy(&out, &in, sizeof(timestamp));
diff --git a/fs/udf/udftime.c b/fs/udf/udftime.c
index 3722d7d38..c2634bda6 100644
--- a/fs/udf/udftime.c
+++ b/fs/udf/udftime.c
@@ -58,7 +58,7 @@ const unsigned short int __mon_yday[2][13] =
 #define SPD 0x15180 /*3600*24*/
 #define SPY(y,l,s) (SPD * (365*y+l)+s)
 
-time_t year_seconds[MAX_YEAR_SECONDS]= {
+static time_t year_seconds[MAX_YEAR_SECONDS]= {
 /*1970*/ SPY( 0, 0,0), SPY( 1, 0,0), SPY( 2, 0,0), SPY( 3, 1,0), 
 /*1974*/ SPY( 4, 1,0), SPY( 5, 1,0), SPY( 6, 1,0), SPY( 7, 2,0), 
 /*1978*/ SPY( 8, 2,0), SPY( 9, 2,0), SPY(10, 2,0), SPY(11, 3,0), 
@@ -85,7 +85,7 @@ extern struct timezone sys_tz;
 #define SECS_PER_DAY	(SECS_PER_HOUR * 24)
 
 time_t *
-udf_stamp_to_time(time_t *dest, long *dest_usec, timestamp src)
+udf_stamp_to_time(time_t *dest, long *dest_usec, kernel_timestamp src)
 {
 	int yday;
 	uint8_t type = src.typeAndTimezone >> 12;
@@ -120,8 +120,8 @@ udf_stamp_to_time(time_t *dest, long *dest_usec, timestamp src)
 }
 
 
-timestamp *
-udf_time_to_stamp(timestamp *dest, struct timespec ts)
+kernel_timestamp *
+udf_time_to_stamp(kernel_timestamp *dest, struct timespec ts)
 {
 	long int days, rem, y;
 	const unsigned short int *ip;
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
index 2e90984b0..9195c9dfa 100644
--- a/fs/ufs/balloc.c
+++ b/fs/ufs/balloc.c
@@ -28,12 +28,12 @@
 #define UFSD(x)
 #endif
 
-unsigned ufs_add_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
-unsigned ufs_alloc_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
-unsigned ufs_alloccg_block (struct inode *, struct ufs_cg_private_info *, unsigned, int *);
-unsigned ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, unsigned, unsigned);
+static unsigned ufs_add_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
+static unsigned ufs_alloc_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
+static unsigned ufs_alloccg_block (struct inode *, struct ufs_cg_private_info *, unsigned, int *);
+static unsigned ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, unsigned, unsigned);
 static unsigned char ufs_fragtable_8fpb[], ufs_fragtable_other[];
-void ufs_clusteracct(struct super_block *, struct ufs_cg_private_info *, unsigned, int);
+static void ufs_clusteracct(struct super_block *, struct ufs_cg_private_info *, unsigned, int);
 
 /*
  * Free 'count' fragments from fragment number 'fragment'
@@ -235,7 +235,7 @@ failed:
 		brelse (bh); \
 	}
 
-unsigned ufs_new_fragments (struct inode * inode, u32 * p, unsigned fragment,
+unsigned ufs_new_fragments (struct inode * inode, __fs32 * p, unsigned fragment,
 	unsigned goal, unsigned count, int * err )
 {
 	struct super_block * sb;
@@ -393,8 +393,9 @@ unsigned ufs_new_fragments (struct inode * inode, u32 * p, unsigned fragment,
 	return 0;
 }		
 
-unsigned ufs_add_fragments (struct inode * inode, unsigned fragment,
-	unsigned oldcount, unsigned newcount, int * err)
+static unsigned
+ufs_add_fragments (struct inode * inode, unsigned fragment,
+		   unsigned oldcount, unsigned newcount, int * err)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
@@ -411,7 +412,7 @@ unsigned ufs_add_fragments (struct inode * inode, unsigned fragment,
 	count = newcount - oldcount;
 	
 	cgno = ufs_dtog(fragment);
-	if (UFS_SB(sb)->fs_cs(cgno).cs_nffree < count)
+	if (fs32_to_cpu(sb, UFS_SB(sb)->fs_cs(cgno).cs_nffree) < count)
 		return 0;
 	if ((ufs_fragnum (fragment) + newcount) > uspi->s_fpb)
 		return 0;
@@ -477,7 +478,7 @@ unsigned ufs_add_fragments (struct inode * inode, unsigned fragment,
 		if (fs32_to_cpu(sb, ucg->cg_frsum[k])) \
 			goto cg_found; 
 
-unsigned ufs_alloc_fragments (struct inode * inode, unsigned cgno,
+static unsigned ufs_alloc_fragments (struct inode * inode, unsigned cgno,
 	unsigned goal, unsigned count, int * err)
 {
 	struct super_block * sb;
@@ -595,7 +596,7 @@ succed:
 	return result;
 }
 
-unsigned ufs_alloccg_block (struct inode * inode,
+static unsigned ufs_alloccg_block (struct inode * inode,
 	struct ufs_cg_private_info * ucpi, unsigned goal, int * err)
 {
 	struct super_block * sb;
@@ -653,7 +654,7 @@ gotit:
 	return result;
 }
 
-unsigned ufs_bitmap_search (struct super_block * sb,
+static unsigned ufs_bitmap_search (struct super_block * sb,
 	struct ufs_cg_private_info * ucpi, unsigned goal, unsigned count)
 {
 	struct ufs_sb_private_info * uspi;
@@ -724,7 +725,7 @@ unsigned ufs_bitmap_search (struct super_block * sb,
 	return (unsigned)-1;
 }
 
-void ufs_clusteracct(struct super_block * sb, 
+static void ufs_clusteracct(struct super_block * sb,
 	struct ufs_cg_private_info * ucpi, unsigned blkno, int cnt)
 {
 	struct ufs_sb_private_info * uspi;
@@ -770,11 +771,11 @@ void ufs_clusteracct(struct super_block * sb,
 	i = back + forw + 1;
 	if (i > uspi->s_contigsumsize)
 		i = uspi->s_contigsumsize;
-	fs32_add(sb, (u32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (i << 2)), cnt);
+	fs32_add(sb, (__fs32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (i << 2)), cnt);
 	if (back > 0)
-		fs32_sub(sb, (u32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (back << 2)), cnt);
+		fs32_sub(sb, (__fs32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (back << 2)), cnt);
 	if (forw > 0)
-		fs32_sub(sb, (u32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (forw << 2)), cnt);
+		fs32_sub(sb, (__fs32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (forw << 2)), cnt);
 }
 
 
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c
index da9d316ca..3d6a263ea 100644
--- a/fs/ufs/dir.c
+++ b/fs/ufs/dir.c
@@ -31,6 +31,9 @@
 #define UFSD(x)
 #endif
 
+static int
+ufs_check_dir_entry (const char *, struct inode *, struct ufs_dir_entry *,
+		     struct buffer_head *, unsigned long);
 
 
 /*
@@ -292,9 +295,10 @@ failed:
 	return NULL;
 }
 
-int ufs_check_dir_entry (const char * function,	struct inode * dir,
-	struct ufs_dir_entry * de, struct buffer_head * bh, 
-	unsigned long offset)
+static int
+ufs_check_dir_entry (const char *function, struct inode *dir,
+		     struct ufs_dir_entry *de, struct buffer_head *bh,
+		     unsigned long offset)
 {
 	struct super_block *sb = dir->i_sb;
 	const char *error_msg = NULL;
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index 06415ae89..2e8d46690 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -99,8 +99,8 @@ u64  ufs_frag_map(struct inode *inode, sector_t frag)
 	sector_t offsets[4], *p;
 	int depth = ufs_block_to_path(inode, frag >> uspi->s_fpbshift, offsets);
 	u64  ret = 0L;
-	u32 block;
-	u64 u2_block = 0L;
+	__fs32 block;
+	__fs64 u2_block = 0L;
 	unsigned flags = UFS_SB(sb)->s_flags;
 	u64 temp = 0L;
 
@@ -126,7 +126,7 @@ u64  ufs_frag_map(struct inode *inode, sector_t frag)
 		bh = sb_bread(sb, uspi->s_sbbase + fs32_to_cpu(sb, block)+(n>>shift));
 		if (!bh)
 			goto out;
-		block = ((u32*) bh->b_data)[n & mask];
+		block = ((__fs32 *) bh->b_data)[n & mask];
 		brelse (bh);
 		if (!block)
 			goto out;
@@ -148,7 +148,7 @@ ufs2:
 		bh = sb_bread(sb, temp +(u64) (n>>shift));
 		if (!bh)
 			goto out;
-		u2_block = ((u64*)bh->b_data)[n & mask];
+		u2_block = ((__fs64 *)bh->b_data)[n & mask];
 		brelse(bh);
 		if (!u2_block)
 			goto out;
@@ -171,7 +171,7 @@ static struct buffer_head * ufs_inode_getfrag (struct inode *inode,
 	struct buffer_head * result;
 	unsigned block, blockoff, lastfrag, lastblock, lastblockoff;
 	unsigned tmp, goal;
-	u32 * p, * p2;
+	__fs32 * p, * p2;
 	unsigned flags = 0;
 
 	UFSD(("ENTER, ino %lu, fragment %u, new_fragment %u, required %u\n",
@@ -303,7 +303,7 @@ static struct buffer_head * ufs_block_getfrag (struct inode *inode,
 	struct ufs_sb_private_info * uspi;
 	struct buffer_head * result;
 	unsigned tmp, goal, block, blockoff;
-	u32 * p;
+	__fs32 * p;
 
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
@@ -322,7 +322,7 @@ static struct buffer_head * ufs_block_getfrag (struct inode *inode,
 			goto out;
 	}
 
-	p = (u32 *) bh->b_data + block;
+	p = (__fs32 *) bh->b_data + block;
 repeat:
 	tmp = fs32_to_cpu(sb, *p);
 	if (tmp) {
@@ -338,7 +338,7 @@ repeat:
 		}
 	}
 
-	if (block && (tmp = fs32_to_cpu(sb, ((u32*)bh->b_data)[block-1]) + uspi->s_fpb))
+	if (block && (tmp = fs32_to_cpu(sb, ((__fs32*)bh->b_data)[block-1]) + uspi->s_fpb))
 		goal = tmp + uspi->s_fpb;
 	else
 		goal = bh->b_blocknr + uspi->s_fpb;
@@ -788,11 +788,13 @@ static int ufs_update_inode(struct inode * inode, int do_sync)
 	return 0;
 }
 
-void ufs_write_inode (struct inode * inode, int wait)
+int ufs_write_inode (struct inode * inode, int wait)
 {
+	int ret;
 	lock_kernel();
-	ufs_update_inode (inode, wait);
+	ret = ufs_update_inode (inode, wait);
 	unlock_kernel();
+	return ret;
 }
 
 int ufs_sync_inode (struct inode *inode)
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 43475183b..4ff38a0ab 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -388,7 +388,7 @@ static int ufs_parse_options (char * options, unsigned * mount_options)
 /*
  * Read on-disk structures associated with cylinder groups
  */
-int ufs_read_cylinder_structures (struct super_block * sb) {
+static int ufs_read_cylinder_structures (struct super_block *sb) {
 	struct ufs_sb_info * sbi = UFS_SB(sb);
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block *usb;
@@ -488,7 +488,7 @@ failed:
  * Put on-disk structures associated with cylinder groups and 
  * write them back to disk
  */
-void ufs_put_cylinder_structures (struct super_block * sb) {
+static void ufs_put_cylinder_structures (struct super_block *sb) {
 	struct ufs_sb_info * sbi = UFS_SB(sb);
 	struct ufs_sb_private_info * uspi;
 	struct ufs_buffer_head * ubh;
@@ -743,22 +743,22 @@ again:
 	/*
 	 * Check ufs magic number
 	 */
-	switch ((uspi->fs_magic = __constant_le32_to_cpu(usb3->fs_magic))) {
+	sbi->s_bytesex = BYTESEX_LE;
+	switch ((uspi->fs_magic = fs32_to_cpu(sb, usb3->fs_magic))) {
 		case UFS_MAGIC:
 		case UFS2_MAGIC:
 		case UFS_MAGIC_LFN:
 	        case UFS_MAGIC_FEA:
 	        case UFS_MAGIC_4GB:
-			sbi->s_bytesex = BYTESEX_LE;
 			goto magic_found;
 	}
-	switch ((uspi->fs_magic = __constant_be32_to_cpu(usb3->fs_magic))) {
+	sbi->s_bytesex = BYTESEX_BE;
+	switch ((uspi->fs_magic = fs32_to_cpu(sb, usb3->fs_magic))) {
 		case UFS_MAGIC:
 		case UFS2_MAGIC:
 		case UFS_MAGIC_LFN:
 	        case UFS_MAGIC_FEA:
 	        case UFS_MAGIC_4GB:
-			sbi->s_bytesex = BYTESEX_BE;
 			goto magic_found;
 	}
 
@@ -993,7 +993,7 @@ failed_nomem:
 	return -ENOMEM;
 }
 
-void ufs_write_super (struct super_block * sb) {
+static void ufs_write_super (struct super_block *sb) {
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
 	struct ufs_super_block_third * usb3;
@@ -1020,7 +1020,7 @@ void ufs_write_super (struct super_block * sb) {
 	unlock_kernel();
 }
 
-void ufs_put_super (struct super_block * sb)
+static void ufs_put_super (struct super_block *sb)
 {
 	struct ufs_sb_info * sbi = UFS_SB(sb);
 		
@@ -1037,7 +1037,7 @@ void ufs_put_super (struct super_block * sb)
 }
 
 
-int ufs_remount (struct super_block * sb, int * mount_flags, char * data)
+static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
 {
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
@@ -1112,7 +1112,7 @@ int ufs_remount (struct super_block * sb, int * mount_flags, char * data)
 	return 0;
 }
 
-int ufs_statfs (struct super_block * sb, struct kstatfs * buf)
+static int ufs_statfs (struct super_block *sb, struct kstatfs *buf)
 {
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
@@ -1129,7 +1129,7 @@ int ufs_statfs (struct super_block * sb, struct kstatfs * buf)
 	flags = UFS_SB(sb)->s_flags;
 	if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
 		buf->f_type = UFS2_MAGIC;
-		buf->f_blocks = usb->fs_u11.fs_u2.fs_dsize;
+		buf->f_blocks = fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_dsize);
 		buf->f_bfree = ufs_blkstofrags(fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_cstotal.cs_nbfree)) +
 			fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_cstotal.cs_nffree);
 		buf->f_ffree = fs64_to_cpu(sb,
@@ -1183,7 +1183,7 @@ static int init_inodecache(void)
 {
 	ufs_inode_cachep = kmem_cache_create("ufs_inode_cache",
 					     sizeof(struct ufs_inode_info),
-					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     0, SLAB_RECLAIM_ACCOUNT,
 					     init_once, NULL);
 	if (ufs_inode_cachep == NULL)
 		return -ENOMEM;
diff --git a/fs/ufs/swab.h b/fs/ufs/swab.h
index a19000f8d..1683d2bee 100644
--- a/fs/ufs/swab.h
+++ b/fs/ufs/swab.h
@@ -22,22 +22,22 @@ enum {
 	BYTESEX_BE
 };
 
-static __inline u64
-fs64_to_cpu(struct super_block *sbp, u64 n)
+static inline u64
+fs64_to_cpu(struct super_block *sbp, __fs64 n)
 {
 	if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-		return le64_to_cpu(n);
+		return le64_to_cpu((__force __le64)n);
 	else
-		return be64_to_cpu(n);
+		return be64_to_cpu((__force __be64)n);
 }
 
-static __inline u64
+static inline __fs64
 cpu_to_fs64(struct super_block *sbp, u64 n)
 {
 	if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-		return cpu_to_le64(n);
+		return (__force __fs64)cpu_to_le64(n);
 	else
-		return cpu_to_be64(n);
+		return (__force __fs64)cpu_to_be64(n);
 }
 
 static __inline u32
@@ -59,75 +59,75 @@ fs64_sub(struct super_block *sbp, u32 *n, int d)
 }
 
 static __inline u32
-fs32_to_cpu(struct super_block *sbp, u32 n)
+fs32_to_cpu(struct super_block *sbp, __fs32 n)
 {
 	if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-		return le32_to_cpu(n);
+		return le32_to_cpu((__force __le32)n);
 	else
-		return be32_to_cpu(n);
+		return be32_to_cpu((__force __be32)n);
 }
 
-static __inline u32
+static inline __fs32
 cpu_to_fs32(struct super_block *sbp, u32 n)
 {
 	if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-		return cpu_to_le32(n);
+		return (__force __fs32)cpu_to_le32(n);
 	else
-		return cpu_to_be32(n);
+		return (__force __fs32)cpu_to_be32(n);
 }
 
-static __inline u32
-fs32_add(struct super_block *sbp, u32 *n, int d)
+static inline void
+fs32_add(struct super_block *sbp, __fs32 *n, int d)
 {
 	if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-		return *n = cpu_to_le32(le32_to_cpu(*n)+d);
+		*(__le32 *)n = cpu_to_le32(le32_to_cpu(*(__le32 *)n)+d);
 	else
-		return *n = cpu_to_be32(be32_to_cpu(*n)+d);
+		*(__be32 *)n = cpu_to_be32(be32_to_cpu(*(__be32 *)n)+d);
 }
 
-static __inline u32
-fs32_sub(struct super_block *sbp, u32 *n, int d)
+static inline void
+fs32_sub(struct super_block *sbp, __fs32 *n, int d)
 {
 	if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-		return *n = cpu_to_le32(le32_to_cpu(*n)-d);
+		*(__le32 *)n = cpu_to_le32(le32_to_cpu(*(__le32 *)n)-d);
 	else
-		return *n = cpu_to_be32(be32_to_cpu(*n)-d);
+		*(__be32 *)n = cpu_to_be32(be32_to_cpu(*(__be32 *)n)-d);
 }
 
-static __inline u16
-fs16_to_cpu(struct super_block *sbp, u16 n)
+static inline u16
+fs16_to_cpu(struct super_block *sbp, __fs16 n)
 {
 	if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-		return le16_to_cpu(n);
+		return le16_to_cpu((__force __le16)n);
 	else
-		return be16_to_cpu(n);
+		return be16_to_cpu((__force __be16)n);
 }
 
-static __inline u16
+static inline __fs16
 cpu_to_fs16(struct super_block *sbp, u16 n)
 {
 	if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-		return cpu_to_le16(n);
+		return (__force __fs16)cpu_to_le16(n);
 	else
-		return cpu_to_be16(n);
+		return (__force __fs16)cpu_to_be16(n);
 }
 
-static __inline u16
-fs16_add(struct super_block *sbp, u16 *n, int d)
+static inline void
+fs16_add(struct super_block *sbp, __fs16 *n, int d)
 {
 	if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-		return *n = cpu_to_le16(le16_to_cpu(*n)+d);
+		*(__le16 *)n = cpu_to_le16(le16_to_cpu(*(__le16 *)n)+d);
 	else
-		return *n = cpu_to_be16(be16_to_cpu(*n)+d);
+		*(__be16 *)n = cpu_to_be16(be16_to_cpu(*(__be16 *)n)+d);
 }
 
-static __inline u16
-fs16_sub(struct super_block *sbp, u16 *n, int d)
+static inline void
+fs16_sub(struct super_block *sbp, __fs16 *n, int d)
 {
 	if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE)
-		return *n = cpu_to_le16(le16_to_cpu(*n)-d);
+		*(__le16 *)n = cpu_to_le16(le16_to_cpu(*(__le16 *)n)-d);
 	else
-		return *n = cpu_to_be16(be16_to_cpu(*n)-d);
+		*(__be16 *)n = cpu_to_be16(be16_to_cpu(*(__be16 *)n)-d);
 }
 
 #endif /* _UFS_SWAB_H */
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c
index b22169e7b..2a2987c90 100644
--- a/fs/ufs/truncate.c
+++ b/fs/ufs/truncate.c
@@ -74,7 +74,7 @@ static int ufs_trunc_direct (struct inode * inode)
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct buffer_head * bh;
-	u32 * p;
+	__fs32 * p;
 	unsigned frag1, frag2, frag3, frag4, block1, block2;
 	unsigned frag_to_free, free_count;
 	unsigned i, j, tmp;
@@ -199,13 +199,13 @@ next2:;
 }
 
 
-static int ufs_trunc_indirect (struct inode * inode, unsigned offset, u32 * p)
+static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct ufs_buffer_head * ind_ubh;
 	struct buffer_head * bh;
-	u32 * ind;
+	__fs32 * ind;
 	unsigned indirect_block, i, j, tmp;
 	unsigned frag_to_free, free_count;
 	int retry;
@@ -296,13 +296,13 @@ next:;
 	return retry;
 }
 
-static int ufs_trunc_dindirect (struct inode * inode, unsigned offset, u32 * p)
+static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct ufs_buffer_head * dind_bh;
 	unsigned i, tmp, dindirect_block;
-	u32 * dind;
+	__fs32 * dind;
 	int retry = 0;
 	
 	UFSD(("ENTER\n"))
@@ -371,7 +371,7 @@ static int ufs_trunc_tindirect (struct inode * inode)
 	struct ufs_sb_private_info * uspi;
 	struct ufs_buffer_head * tind_bh;
 	unsigned tindirect_block, tmp, i;
-	u32 * tind, * p;
+	__fs32 * tind, * p;
 	int retry;
 	
 	UFSD(("ENTER\n"))
@@ -449,9 +449,9 @@ void ufs_truncate (struct inode * inode)
 	while (1) {
 		retry = ufs_trunc_direct(inode);
 		retry |= ufs_trunc_indirect (inode, UFS_IND_BLOCK,
-			(u32 *) &ufsi->i_u1.i_data[UFS_IND_BLOCK]);
+			(__fs32 *) &ufsi->i_u1.i_data[UFS_IND_BLOCK]);
 		retry |= ufs_trunc_dindirect (inode, UFS_IND_BLOCK + uspi->s_apb,
-			(u32 *) &ufsi->i_u1.i_data[UFS_DIND_BLOCK]);
+			(__fs32 *) &ufsi->i_u1.i_data[UFS_DIND_BLOCK]);
 		retry |= ufs_trunc_tindirect (inode);
 		if (!retry)
 			break;
diff --git a/fs/ufs/util.h b/fs/ufs/util.h
index ad72b7fbe..58770d27b 100644
--- a/fs/ufs/util.h
+++ b/fs/ufs/util.h
@@ -72,20 +72,20 @@ ufs_get_fs_npsect(struct super_block *sb, struct ufs_super_block_first *usb1,
 static inline u64
 ufs_get_fs_qbmask(struct super_block *sb, struct ufs_super_block_third *usb3)
 {
-	u64 tmp;
+	__fs64 tmp;
 
 	switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
 	case UFS_ST_SUN:
-		((u32 *)&tmp)[0] = usb3->fs_u2.fs_sun.fs_qbmask[0];
-		((u32 *)&tmp)[1] = usb3->fs_u2.fs_sun.fs_qbmask[1];
+		((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_sun.fs_qbmask[0];
+		((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_sun.fs_qbmask[1];
 		break;
 	case UFS_ST_SUNx86:
-		((u32 *)&tmp)[0] = usb3->fs_u2.fs_sunx86.fs_qbmask[0];
-		((u32 *)&tmp)[1] = usb3->fs_u2.fs_sunx86.fs_qbmask[1];
+		((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_sunx86.fs_qbmask[0];
+		((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_sunx86.fs_qbmask[1];
 		break;
 	case UFS_ST_44BSD:
-		((u32 *)&tmp)[0] = usb3->fs_u2.fs_44.fs_qbmask[0];
-		((u32 *)&tmp)[1] = usb3->fs_u2.fs_44.fs_qbmask[1];
+		((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_44.fs_qbmask[0];
+		((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_44.fs_qbmask[1];
 		break;
 	}
 
@@ -95,20 +95,20 @@ ufs_get_fs_qbmask(struct super_block *sb, struct ufs_super_block_third *usb3)
 static inline u64
 ufs_get_fs_qfmask(struct super_block *sb, struct ufs_super_block_third *usb3)
 {
-	u64 tmp;
+	__fs64 tmp;
 
 	switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
 	case UFS_ST_SUN:
-		((u32 *)&tmp)[0] = usb3->fs_u2.fs_sun.fs_qfmask[0];
-		((u32 *)&tmp)[1] = usb3->fs_u2.fs_sun.fs_qfmask[1];
+		((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_sun.fs_qfmask[0];
+		((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_sun.fs_qfmask[1];
 		break;
 	case UFS_ST_SUNx86:
-		((u32 *)&tmp)[0] = usb3->fs_u2.fs_sunx86.fs_qfmask[0];
-		((u32 *)&tmp)[1] = usb3->fs_u2.fs_sunx86.fs_qfmask[1];
+		((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_sunx86.fs_qfmask[0];
+		((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_sunx86.fs_qfmask[1];
 		break;
 	case UFS_ST_44BSD:
-		((u32 *)&tmp)[0] = usb3->fs_u2.fs_44.fs_qfmask[0];
-		((u32 *)&tmp)[1] = usb3->fs_u2.fs_44.fs_qfmask[1];
+		((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_44.fs_qfmask[0];
+		((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_44.fs_qfmask[1];
 		break;
 	}
 
@@ -273,11 +273,11 @@ extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head
 	((begin) & ~uspi->s_fmask))
 
 #define ubh_get_addr16(ubh,begin) \
-	(((u16*)((ubh)->bh[(begin) >> (uspi->s_fshift-1)]->b_data)) + \
+	(((__fs16*)((ubh)->bh[(begin) >> (uspi->s_fshift-1)]->b_data)) + \
 	((begin) & (uspi->fsize>>1) - 1)))
 
 #define ubh_get_addr32(ubh,begin) \
-	(((u32*)((ubh)->bh[(begin) >> (uspi->s_fshift-2)]->b_data)) + \
+	(((__fs32*)((ubh)->bh[(begin) >> (uspi->s_fshift-2)]->b_data)) + \
 	((begin) & ((uspi->s_fsize>>2) - 1)))
 
 #define ubh_get_addr ubh_get_addr8
@@ -315,10 +315,10 @@ extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head
  * Macros to access cylinder group array structures
  */
 #define ubh_cg_blktot(ucpi,cylno) \
-	(*((__u32*)ubh_get_addr(UCPI_UBH, (ucpi)->c_btotoff + ((cylno) << 2))))
+	(*((__fs32*)ubh_get_addr(UCPI_UBH, (ucpi)->c_btotoff + ((cylno) << 2))))
 
 #define ubh_cg_blks(ucpi,cylno,rpos) \
-	(*((__u16*)ubh_get_addr(UCPI_UBH, \
+	(*((__fs16*)ubh_get_addr(UCPI_UBH, \
 	(ucpi)->c_boff + (((cylno) * uspi->s_nrpos + (rpos)) << 1 ))))
 
 /*
@@ -476,7 +476,7 @@ static inline void _ubh_setblock_(struct ufs_sb_private_info * uspi,
 }
 
 static inline void ufs_fragacct (struct super_block * sb, unsigned blockmap,
-	unsigned * fraglist, int cnt)
+	__fs32 * fraglist, int cnt)
 {
 	struct ufs_sb_private_info * uspi;
 	unsigned fragsize, pos;
diff --git a/fs/umsdos/inode.c b/fs/umsdos/inode.c
index 061c9bc36..778feedf4 100644
--- a/fs/umsdos/inode.c
+++ b/fs/umsdos/inode.c
@@ -312,11 +312,12 @@ out:
 /*
  * Update the disk with the inode content
  */
-void UMSDOS_write_inode (struct inode *inode, int wait)
+int UMSDOS_write_inode (struct inode *inode, int wait)
 {
 	struct iattr newattrs;
+	int ret;
 
-	fat_write_inode (inode, wait);
+	ret = fat_write_inode (inode, wait);
 	newattrs.ia_mtime = inode->i_mtime;
 	newattrs.ia_atime = inode->i_atime;
 	newattrs.ia_ctime = inode->i_ctime;
@@ -330,6 +331,7 @@ void UMSDOS_write_inode (struct inode *inode, int wait)
  * UMSDOS_notify_change (inode, &newattrs);
 
  * inode->i_state &= ~I_DIRTY; / * FIXME: this doesn't work.  We need to remove ourselves from list on dirty inodes. /mn/ */
+	return ret;
 }
 
 
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index 85f78ea87..eea6d3f27 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -73,33 +73,6 @@ static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd)
 	return ret;
 }
 
-static inline unsigned char
-vfat_tolower(struct nls_table *t, unsigned char c)
-{
-	unsigned char nc = t->charset2lower[c];
-
-	return nc ? nc : c;
-}
-
-static inline unsigned char
-vfat_toupper(struct nls_table *t, unsigned char c)
-{
-	unsigned char nc = t->charset2upper[c];
-
-	return nc ? nc : c;
-}
-
-static inline int
-vfat_strnicmp(struct nls_table *t, const unsigned char *s1,
-					const unsigned char *s2, int len)
-{
-	while(len--)
-		if (vfat_tolower(t, *s1++) != vfat_tolower(t, *s2++))
-			return 1;
-
-	return 0;
-}
-
 /* returns the length of a struct qstr, ignoring trailing dots */
 static unsigned int vfat_striptail_len(struct qstr *qstr)
 {
@@ -142,7 +115,7 @@ static int vfat_hashi(struct dentry *dentry, struct qstr *qstr)
 
 	hash = init_name_hash();
 	while (len--)
-		hash = partial_name_hash(vfat_tolower(t, *name++), hash);
+		hash = partial_name_hash(nls_tolower(t, *name++), hash);
 	qstr->hash = end_name_hash(hash);
 
 	return 0;
@@ -160,7 +133,7 @@ static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b)
 	alen = vfat_striptail_len(a);
 	blen = vfat_striptail_len(b);
 	if (alen == blen) {
-		if (vfat_strnicmp(t, a->name, b->name, alen) == 0)
+		if (nls_strnicmp(t, a->name, b->name, alen) == 0)
 			return 0;
 	}
 	return 1;
@@ -341,7 +314,7 @@ static inline int to_shortname_char(struct nls_table *nls,
 			info->upper = 0;
 		}
 
-		buf[0] = vfat_toupper(nls, buf[0]);
+		buf[0] = nls_toupper(nls, buf[0]);
 		if (isalpha(buf[0])) {
 			if (buf[0] == prev)
 				info->lower = 0;
@@ -704,7 +677,8 @@ shortname:
 	de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
 	de->lcase = lcase;
 	de->adate = de->cdate = de->date = 0;
-	de->ctime_ms = de->ctime = de->time = 0;
+	de->ctime = de->time = 0;
+	de->ctime_ms = 0;
 	de->start = 0;
 	de->starthi = 0;
 	de->size = 0;
@@ -1073,8 +1047,8 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
 
 	if (is_dir) {
 		int start = MSDOS_I(new_dir)->i_logstart;
-		dotdot_de->start = CT_LE_W(start);
-		dotdot_de->starthi = CT_LE_W(start>>16);
+		dotdot_de->start = cpu_to_le16(start);
+		dotdot_de->starthi = cpu_to_le16(start>>16);
 		mark_buffer_dirty(dotdot_bh);
 		old_dir->i_nlink--;
 		if (new_inode) {
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index 09f81b379..bb714c1dc 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -67,10 +67,9 @@ endif
 
 xfs-$(CONFIG_XFS_RT)		+= xfs_rtalloc.o
 xfs-$(CONFIG_XFS_POSIX_ACL)	+= xfs_acl.o
-xfs-$(CONFIG_XFS_POSIX_CAP)	+= xfs_cap.o
-xfs-$(CONFIG_XFS_POSIX_MAC)	+= xfs_mac.o
 xfs-$(CONFIG_PROC_FS)		+= linux-2.6/xfs_stats.o
 xfs-$(CONFIG_SYSCTL)		+= linux-2.6/xfs_sysctl.o
+xfs-$(CONFIG_COMPAT)		+= linux-2.6/xfs_ioctl32.o
 
 
 xfs-y				+= xfs_alloc.o \
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 7122efdba..29fc5b35c 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -234,6 +234,7 @@ xfs_map_at_offset(
 	sector_shift = block_bits - BBSHIFT;
 	bn = iomapp->iomap_bn >> sector_shift;
 	bn += delta;
+	BUG_ON(!bn && !(iomapp->iomap_flags & IOMAP_REALTIME));
 	ASSERT((bn << sector_shift) >= iomapp->iomap_bn);
 
 	lock_buffer(bh);
@@ -264,7 +265,7 @@ xfs_probe_unwritten_page(
 
 	page = find_trylock_page(mapping, index);
 	if (!page)
-		return 0;
+		return NULL;
 	if (PageWriteback(page))
 		goto out;
 
@@ -549,19 +550,23 @@ enough:
 STATIC void
 xfs_submit_page(
 	struct page		*page,
+	struct writeback_control *wbc,
 	struct buffer_head	*bh_arr[],
-	int			cnt)
+	int			bh_count,
+	int			probed_page,
+	int			clear_dirty)
 {
 	struct buffer_head	*bh;
 	int			i;
 
 	BUG_ON(PageWriteback(page));
 	set_page_writeback(page);
-	clear_page_dirty(page);
+	if (clear_dirty)
+		clear_page_dirty(page);
 	unlock_page(page);
 
-	if (cnt) {
-		for (i = 0; i < cnt; i++) {
+	if (bh_count) {
+		for (i = 0; i < bh_count; i++) {
 			bh = bh_arr[i];
 			mark_buffer_async_write(bh);
 			if (buffer_unwritten(bh))
@@ -570,10 +575,15 @@ xfs_submit_page(
 			clear_buffer_dirty(bh);
 		}
 
-		for (i = 0; i < cnt; i++)
+		for (i = 0; i < bh_count; i++)
 			submit_bh(WRITE, bh_arr[i]);
-	} else
+
+		if (probed_page && clear_dirty)
+			wbc->nr_to_write--;	/* Wrote an "extra" page */
+	} else {
 		end_page_writeback(page);
+		wbc->pages_skipped++;	/* We didn't write this page */
+	}
 }
 
 /*
@@ -608,11 +618,13 @@ xfs_convert_page(
 	bh = head = page_buffers(page);
 	do {
 		offset = i << bbits;
+		if (offset >= end)
+			break;
 		if (!(PageUptodate(page) || buffer_uptodate(bh)))
 			continue;
 		if (buffer_mapped(bh) && all_bh &&
-		    !buffer_unwritten(bh) && !buffer_delay(bh)) {
-			if (startio && (offset < end)) {
+		    !(buffer_unwritten(bh) || buffer_delay(bh))) {
+			if (startio) {
 				lock_buffer(bh);
 				bh_arr[index++] = bh;
 			}
@@ -640,7 +652,7 @@ xfs_convert_page(
 				ASSERT(private);
 			}
 		}
-		if (startio && (offset < end)) {
+		if (startio) {
 			bh_arr[index++] = bh;
 		} else {
 			set_buffer_dirty(bh);
@@ -650,8 +662,7 @@ xfs_convert_page(
 	} while (i++, (bh = bh->b_this_page) != head);
 
 	if (startio) {
-		wbc->nr_to_write--;
-		xfs_submit_page(page, bh_arr, index);
+		xfs_submit_page(page, wbc, bh_arr, index, 1, index == i);
 	} else {
 		unlock_page(page);
 	}
@@ -863,7 +874,7 @@ xfs_page_state_convert(
 		SetPageUptodate(page);
 
 	if (startio)
-		xfs_submit_page(page, bh_arr, cnt);
+		xfs_submit_page(page, wbc, bh_arr, cnt, 0, 1);
 
 	if (iomp) {
 		tlast = (iomp->iomap_offset + iomp->iomap_bsize - 1) >>
@@ -938,9 +949,8 @@ linvfs_get_block_core(
 
 			bn = iomap.iomap_bn >> (inode->i_blkbits - BBSHIFT);
 			bn += delta;
-
+			BUG_ON(!bn && !(iomap.iomap_flags & IOMAP_REALTIME));
 			bh_result->b_blocknr = bn;
-			bh_result->b_bdev = iomap.iomap_target->pbr_bdev;
 			set_buffer_mapped(bh_result);
 		}
 		if (create && (iomap.iomap_flags & IOMAP_UNWRITTEN)) {
@@ -965,21 +975,18 @@ linvfs_get_block_core(
 	}
 
 	if (iomap.iomap_flags & IOMAP_DELAY) {
-		if (unlikely(direct))
-			BUG();
+		BUG_ON(direct);
 		if (create) {
 			set_buffer_mapped(bh_result);
 			set_buffer_uptodate(bh_result);
 		}
-		bh_result->b_bdev = iomap.iomap_target->pbr_bdev;
 		set_buffer_delay(bh_result);
 	}
 
 	if (blocks) {
-		loff_t iosize;
-		iosize = (iomap.iomap_bsize - iomap.iomap_delta);
-		bh_result->b_size =
-		    (ssize_t)min(iosize, (loff_t)(blocks << inode->i_blkbits));
+		bh_result->b_size = (ssize_t)min(
+			(loff_t)(iomap.iomap_bsize - iomap.iomap_delta),
+			(loff_t)(blocks << inode->i_blkbits));
 	}
 
 	return 0;
@@ -996,17 +1003,6 @@ linvfs_get_block(
 					create, 0, BMAPI_WRITE);
 }
 
-STATIC int
-linvfs_get_block_sync(
-	struct inode		*inode,
-	sector_t		iblock,
-	struct buffer_head	*bh_result,
-	int			create)
-{
-	return linvfs_get_block_core(inode, iblock, 0, bh_result,
-					create, 0, BMAPI_SYNC|BMAPI_WRITE);
-}
-
 STATIC int
 linvfs_get_blocks_direct(
 	struct inode		*inode,
@@ -1038,7 +1034,7 @@ linvfs_direct_IO(
 	if (error)
 		return -error;
 
-	return blockdev_direct_IO_no_locking(rw, iocb, inode,
+	return blockdev_direct_IO_own_locking(rw, iocb, inode,
 		iomap.iomap_target->pbr_bdev,
 		iov, offset, nr_segs,
 		linvfs_get_blocks_direct,
@@ -1185,7 +1181,7 @@ linvfs_writepage(
 	return 0;
 
 out_fail:
-	set_page_dirty(page);
+	redirty_page_for_writepage(wbc, page);
 	unlock_page(page);
 	return 0;
 out_unlock:
@@ -1261,13 +1257,7 @@ linvfs_prepare_write(
 	unsigned int		from,
 	unsigned int		to)
 {
-	if (file && (file->f_flags & O_SYNC)) {
-		return block_prepare_write(page, from, to,
-						linvfs_get_block_sync);
-	} else {
-		return block_prepare_write(page, from, to,
-						linvfs_get_block);
-	}
+	return block_prepare_write(page, from, to, linvfs_get_block);
 }
 
 struct address_space_operations linvfs_aops = {
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index ed8abf22d..4c0a72c30 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -626,11 +626,8 @@ pagebuf_get(				/* allocate a buffer		*/
 	pb = _pagebuf_find(target, ioff, isize, flags, new_pb);
 	if (pb == new_pb) {
 		error = _pagebuf_lookup_pages(pb, flags);
-		if (unlikely(error)) {
-			printk(KERN_WARNING
-			       "pagebuf_get: failed to lookup pages\n");
+		if (error)
 			goto no_buffer;
-		}
 	} else {
 		pagebuf_deallocate(new_pb);
 		if (unlikely(pb == NULL))
@@ -1484,6 +1481,7 @@ xfs_free_buftarg(
 	xfs_flush_buftarg(btp, 1);
 	if (external)
 		xfs_blkdev_put(btp->pbr_bdev);
+	iput(btp->pbr_mapping->host);
 	kmem_free(btp, sizeof(*btp));
 }
 
@@ -1497,7 +1495,7 @@ xfs_incore_relse(
 	truncate_inode_pages(btp->pbr_mapping, 0LL);
 }
 
-void
+int
 xfs_setsize_buftarg(
 	xfs_buftarg_t		*btp,
 	unsigned int		blocksize,
@@ -1511,7 +1509,42 @@ xfs_setsize_buftarg(
 		printk(KERN_WARNING
 			"XFS: Cannot set_blocksize to %u on device %s\n",
 			sectorsize, XFS_BUFTARG_NAME(btp));
+		return EINVAL;
 	}
+	return 0;
+}
+
+STATIC int
+xfs_mapping_buftarg(
+	xfs_buftarg_t		*btp,
+	struct block_device	*bdev)
+{
+	struct backing_dev_info	*bdi;
+	struct inode		*inode;
+	struct address_space	*mapping;
+	static struct address_space_operations mapping_aops = {
+		.sync_page = block_sync_page,
+	};
+
+	inode = new_inode(bdev->bd_inode->i_sb);
+	if (!inode) {
+		printk(KERN_WARNING
+			"XFS: Cannot allocate mapping inode for device %s\n",
+			XFS_BUFTARG_NAME(btp));
+		return ENOMEM;
+	}
+	inode->i_mode = S_IFBLK;
+	inode->i_bdev = bdev;
+	inode->i_rdev = bdev->bd_dev;
+	bdi = blk_get_backing_dev_info(bdev);
+	if (!bdi)
+		bdi = &default_backing_dev_info;
+	mapping = &inode->i_data;
+	mapping->a_ops = &mapping_aops;
+	mapping->backing_dev_info = bdi;
+	mapping_set_gfp_mask(mapping, GFP_KERNEL);
+	btp->pbr_mapping = mapping;
+	return 0;
 }
 
 xfs_buftarg_t *
@@ -1524,10 +1557,15 @@ xfs_alloc_buftarg(
 
 	btp->pbr_dev =  bdev->bd_dev;
 	btp->pbr_bdev = bdev;
-	btp->pbr_mapping = bdev->bd_inode->i_mapping;
-	xfs_setsize_buftarg(btp, PAGE_CACHE_SIZE, bdev_hardsect_size(bdev));
-
+	if (xfs_setsize_buftarg(btp, PAGE_CACHE_SIZE, bdev_hardsect_size(bdev)))
+		goto error;
+	if (xfs_mapping_buftarg(btp, bdev))
+		goto error;
 	return btp;
+
+error:
+	kmem_free(btp, sizeof(*btp));
+	return NULL;
 }
 
 
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index 7bebfd65a..242ba07d6 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/fs/xfs/linux-2.6/xfs_buf.h
@@ -566,7 +566,7 @@ static inline int xfs_bdwrite(void *mp, xfs_buf_t *bp)
 
 extern xfs_buftarg_t *xfs_alloc_buftarg(struct block_device *);
 extern void xfs_free_buftarg(xfs_buftarg_t *, int);
-extern void xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
+extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
 extern void xfs_incore_relse(xfs_buftarg_t *, int, int);
 extern int xfs_flush_buftarg(xfs_buftarg_t *, int);
 
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index e8e02f501..910d5bc47 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -61,7 +61,7 @@ static struct vm_operations_struct linvfs_file_vm_ops;
 STATIC inline ssize_t
 __linvfs_read(
 	struct kiocb		*iocb,
-	char __user		*buf,
+	char			__user *buf,
 	int			ioflags,
 	size_t			count,
 	loff_t			pos)
@@ -83,7 +83,7 @@ __linvfs_read(
 STATIC ssize_t
 linvfs_read(
 	struct kiocb		*iocb,
-	char __user		*buf,
+	char			__user *buf,
 	size_t			count,
 	loff_t			pos)
 {
@@ -93,7 +93,7 @@ linvfs_read(
 STATIC ssize_t
 linvfs_read_invis(
 	struct kiocb		*iocb,
-	char __user		*buf,
+	char			__user *buf,
 	size_t			count,
 	loff_t			pos)
 {
@@ -104,29 +104,22 @@ linvfs_read_invis(
 STATIC inline ssize_t
 __linvfs_write(
 	struct kiocb	*iocb,
-	const char 	*buf,
+	const char	__user *buf,
 	int		ioflags,
 	size_t		count,
 	loff_t		pos)
 {
-	struct iovec	iov = {(void *)buf, count};
+	struct iovec	iov = {(void __user *)buf, count};
 	struct file	*file = iocb->ki_filp;
 	struct inode	*inode = file->f_mapping->host;
 	vnode_t		*vp = LINVFS_GET_VP(inode);
 	ssize_t		rval;
 
 	BUG_ON(iocb->ki_pos != pos);
-	if (unlikely(file->f_flags & O_DIRECT)) {
+	if (unlikely(file->f_flags & O_DIRECT))
 		ioflags |= IO_ISDIRECT;
-		VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos,
-				ioflags, NULL, rval);
-	} else {
-		down(&inode->i_sem);
-		VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos,
-				ioflags, NULL, rval);
-		up(&inode->i_sem);
-	}
 
+	VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL, rval);
 	return rval;
 }
 
@@ -134,7 +127,7 @@ __linvfs_write(
 STATIC ssize_t
 linvfs_write(
 	struct kiocb		*iocb,
-	const char __user	*buf,
+	const char		__user *buf,
 	size_t			count,
 	loff_t			pos)
 {
@@ -144,7 +137,7 @@ linvfs_write(
 STATIC ssize_t
 linvfs_write_invis(
 	struct kiocb		*iocb,
-	const char __user	*buf,
+	const char		__user *buf,
 	size_t			count,
 	loff_t			pos)
 {
@@ -171,8 +164,6 @@ __linvfs_readv(
 	if (unlikely(file->f_flags & O_DIRECT))
 		ioflags |= IO_ISDIRECT;
 	VOP_READ(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, rval);
-	if (rval == -EIOCBQUEUED)
-		rval = wait_on_sync_kiocb(&kiocb);
 
 	*ppos = kiocb.ki_pos;
 	return rval;
@@ -214,19 +205,10 @@ __linvfs_writev(
 
 	init_sync_kiocb(&kiocb, file);
 	kiocb.ki_pos = *ppos;
-	if (unlikely(file->f_flags & O_DIRECT)) {
+	if (unlikely(file->f_flags & O_DIRECT))
 		ioflags |= IO_ISDIRECT;
-		VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos,
-				ioflags, NULL, rval);
-	} else {
-		down(&inode->i_sem);
-		VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos,
-				ioflags, NULL, rval);
-		up(&inode->i_sem);
-	}
 
-	if (rval == -EIOCBQUEUED)
-		rval = wait_on_sync_kiocb(&kiocb);
+	VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, rval);
 
 	*ppos = kiocb.ki_pos;
 	return rval;
@@ -427,6 +409,8 @@ linvfs_file_mmap(
 	vma->vm_ops = &linvfs_file_vm_ops;
 
 	VOP_SETATTR(vp, &va, XFS_AT_UPDATIME, NULL, error);
+	if (!error)
+		vn_revalidate(vp);	/* update Linux inode flags */
 	return 0;
 }
 
@@ -442,7 +426,7 @@ linvfs_ioctl(
 	vnode_t		*vp = LINVFS_GET_VP(inode);
 
 	unlock_kernel();
-	VOP_IOCTL(vp, inode, filp, 0, cmd, arg, error);
+	VOP_IOCTL(vp, inode, filp, 0, cmd, (void __user *)arg, error);
 	VMODIFY(vp);
 	lock_kernel();
 
@@ -467,7 +451,7 @@ linvfs_ioctl_invis(
 
 	unlock_kernel();
 	ASSERT(vp);
-	VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, arg, error);
+	VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, (void __user *)arg, error);
 	VMODIFY(vp);
 	lock_kernel();
 
diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.h b/fs/xfs/linux-2.6/xfs_fs_subr.h
index 198b8dd78..2db9ddbd4 100644
--- a/fs/xfs/linux-2.6/xfs_fs_subr.h
+++ b/fs/xfs/linux-2.6/xfs_fs_subr.h
@@ -40,7 +40,6 @@ struct cred;
 
 extern int	fs_noerr(void);
 extern int	fs_nosys(void);
-extern int	fs_nodev(void);
 extern void	fs_noval(void);
 extern void	fs_tosspages(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
 extern void	fs_flushinval_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
diff --git a/fs/xfs/linux-2.6/xfs_globals.c b/fs/xfs/linux-2.6/xfs_globals.c
index cbcdec4af..b9c4bbf4e 100644
--- a/fs/xfs/linux-2.6/xfs_globals.c
+++ b/fs/xfs/linux-2.6/xfs_globals.c
@@ -63,6 +63,7 @@ xfs_param_t xfs_params = {
 	.inherit_noatim = {	0,		1,		1	},
 	.xfs_buf_timer	= {	100/2,		1*100,		30*100	},
 	.xfs_buf_age	= {	1*100,		15*100,		7200*100},
+	.inherit_nosym	= {	0,		0,		1	},
 };
 
 /*
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index 8b7ccc407..f29c51059 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -72,14 +72,6 @@
 #include <linux/namei.h>
 #include <linux/pagemap.h>
 
-/*
- * ioctl commands that are used by Linux filesystems
- */
-#define XFS_IOC_GETXFLAGS	_IOR('f', 1, long)
-#define XFS_IOC_SETXFLAGS	_IOW('f', 2, long)
-#define XFS_IOC_GETVERSION	_IOR('v', 1, long)
-
-
 /*
  * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to
  * a file or fs handle.
@@ -94,7 +86,7 @@
 STATIC int
 xfs_find_handle(
 	unsigned int		cmd,
-	unsigned long		arg)
+	void			__user *arg)
 {
 	int			hsize;
 	xfs_handle_t		handle;
@@ -102,7 +94,7 @@ xfs_find_handle(
 	struct inode		*inode;
 	struct vnode		*vp;
 
-	if (copy_from_user(&hreq, (xfs_fsop_handlereq_t *)arg, sizeof(hreq)))
+	if (copy_from_user(&hreq, arg, sizeof(hreq)))
 		return -XFS_ERROR(EFAULT);
 
 	memset((char *)&handle, 0, sizeof(handle));
@@ -113,7 +105,7 @@ xfs_find_handle(
 		struct nameidata	nd;
 		int			error;
 
-		error = user_path_walk_link(hreq.path, &nd);
+		error = user_path_walk_link((const char __user *)hreq.path, &nd);
 		if (error)
 			return error;
 
@@ -185,7 +177,7 @@ xfs_find_handle(
 	}
 
 	/* now copy our handle into the user buffer & write out the size */
-	if (copy_to_user((xfs_handle_t *)hreq.ohandle, &handle, hsize) ||
+	if (copy_to_user(hreq.ohandle, &handle, hsize) ||
 	    copy_to_user(hreq.ohandlen, &hsize, sizeof(__s32))) {
 		iput(inode);
 		return -XFS_ERROR(EFAULT);
@@ -211,14 +203,14 @@ xfs_vget_fsop_handlereq(
 	xfs_mount_t		*mp,
 	struct inode		*parinode,	/* parent inode pointer    */
 	int			cap,		/* capability level for op */
-	unsigned long		arg,		/* userspace data pointer  */
+	void			__user *arg,	/* userspace data pointer  */
 	unsigned long		size,		/* size of expected struct */
 	/* output arguments */
 	xfs_fsop_handlereq_t	*hreq,
 	vnode_t			**vp,
 	struct inode		**inode)
 {
-	void			*hanp;
+	void			__user *hanp;
 	size_t			hlen;
 	xfs_fid_t		*xfid;
 	xfs_handle_t		*handlep;
@@ -243,7 +235,7 @@ xfs_vget_fsop_handlereq(
 	 * Copy the handle down from the user and validate
 	 * that it looks to be in the correct format.
 	 */
-	if (copy_from_user(hreq, (struct xfs_fsop_handlereq *)arg, size))
+	if (copy_from_user(hreq, arg, size))
 		return XFS_ERROR(EFAULT);
 
 	hanp = hreq->ihandle;
@@ -300,7 +292,7 @@ xfs_vget_fsop_handlereq(
 STATIC int
 xfs_open_by_handle(
 	xfs_mount_t		*mp,
-	unsigned long		arg,
+	void			__user *arg,
 	struct file		*parfilp,
 	struct inode		*parinode)
 {
@@ -383,7 +375,7 @@ xfs_open_by_handle(
 STATIC int
 xfs_readlink_by_handle(
 	xfs_mount_t		*mp,
-	unsigned long		arg,
+	void			__user *arg,
 	struct file		*parfilp,
 	struct inode		*parinode)
 {
@@ -429,7 +421,7 @@ xfs_readlink_by_handle(
 STATIC int
 xfs_fssetdm_by_handle(
 	xfs_mount_t		*mp,
-	unsigned long		arg,
+	void			__user *arg,
 	struct file		*parfilp,
 	struct inode		*parinode)
 {
@@ -469,7 +461,7 @@ xfs_fssetdm_by_handle(
 STATIC int
 xfs_attrlist_by_handle(
 	xfs_mount_t		*mp,
-	unsigned long		arg,
+	void			__user *arg,
 	struct file		*parfilp,
 	struct inode		*parinode)
 {
@@ -498,7 +490,7 @@ xfs_attrlist_by_handle(
 STATIC int
 xfs_attrmulti_by_handle(
 	xfs_mount_t		*mp,
-	unsigned long		arg,
+	void			__user *arg,
 	struct file		*parfilp,
 	struct inode		*parinode)
 {
@@ -577,23 +569,23 @@ xfs_ioc_space(
 	struct file		*filp,
 	int			flags,
 	unsigned int		cmd,
-	unsigned long		arg);
+	void			__user *arg);
 
 STATIC int
 xfs_ioc_bulkstat(
 	xfs_mount_t		*mp,
 	unsigned int		cmd,
-	unsigned long		arg);
+	void			__user *arg);
 
 STATIC int
 xfs_ioc_fsgeometry_v1(
 	xfs_mount_t		*mp,
-	unsigned long		arg);
+	void			__user *arg);
 
 STATIC int
 xfs_ioc_fsgeometry(
 	xfs_mount_t		*mp,
-	unsigned long		arg);
+	void			__user *arg);
 
 STATIC int
 xfs_ioc_xattr(
@@ -601,7 +593,7 @@ xfs_ioc_xattr(
 	xfs_inode_t		*ip,
 	struct file		*filp,
 	unsigned int		cmd,
-	unsigned long		arg);
+	void			__user *arg);
 
 STATIC int
 xfs_ioc_getbmap(
@@ -609,12 +601,12 @@ xfs_ioc_getbmap(
 	struct file		*filp,
 	int			flags,
 	unsigned int		cmd,
-	unsigned long		arg);
+	void			__user *arg);
 
 STATIC int
 xfs_ioc_getbmapx(
 	bhv_desc_t		*bdp,
-	unsigned long		arg);
+	void			__user *arg);
 
 int
 xfs_ioctl(
@@ -623,7 +615,7 @@ xfs_ioctl(
 	struct file		*filp,
 	int			ioflags,
 	unsigned int		cmd,
-	unsigned long		arg)
+	void			__user *arg)
 {
 	int			error;
 	vnode_t			*vp;
@@ -667,7 +659,7 @@ xfs_ioctl(
 		/* The size dio will do in one go */
 		da.d_maxiosz = 64 * PAGE_CACHE_SIZE;
 
-		if (copy_to_user((struct dioattr *)arg, &da, sizeof(da)))
+		if (copy_to_user(arg, &da, sizeof(da)))
 			return -XFS_ERROR(EFAULT);
 		return 0;
 	}
@@ -694,7 +686,7 @@ xfs_ioctl(
 	case XFS_IOC_FSSETDM: {
 		struct fsdmidata	dmi;
 
-		if (copy_from_user(&dmi, (struct fsdmidata *)arg, sizeof(dmi)))
+		if (copy_from_user(&dmi, arg, sizeof(dmi)))
 			return -XFS_ERROR(EFAULT);
 
 		error = xfs_set_dmattrs(bdp, dmi.fsd_dmevmask, dmi.fsd_dmstate,
@@ -730,7 +722,7 @@ xfs_ioctl(
 		return xfs_attrmulti_by_handle(mp, arg, filp, inode);
 
 	case XFS_IOC_SWAPEXT: {
-		error = xfs_swapext((struct xfs_swapext *)arg);
+		error = xfs_swapext((struct xfs_swapext __user *)arg);
 		return -error;
 	}
 
@@ -741,7 +733,7 @@ xfs_ioctl(
 		if (error)
 			return -error;
 
-		if (copy_to_user((char *)arg, &out, sizeof(out)))
+		if (copy_to_user(arg, &out, sizeof(out)))
 			return -XFS_ERROR(EFAULT);
 		return 0;
 	}
@@ -753,7 +745,7 @@ xfs_ioctl(
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 
-		if (copy_from_user(&inout, (char *)arg, sizeof(inout)))
+		if (copy_from_user(&inout, arg, sizeof(inout)))
 			return -XFS_ERROR(EFAULT);
 
 		/* input parameter is passed in resblks field of structure */
@@ -762,7 +754,7 @@ xfs_ioctl(
 		if (error)
 			return -error;
 
-		if (copy_to_user((char *)arg, &inout, sizeof(inout)))
+		if (copy_to_user(arg, &inout, sizeof(inout)))
 			return -XFS_ERROR(EFAULT);
 		return 0;
 	}
@@ -777,7 +769,7 @@ xfs_ioctl(
 		if (error)
 			return -error;
 
-		if (copy_to_user((char *)arg, &out, sizeof(out)))
+		if (copy_to_user(arg, &out, sizeof(out)))
 			return -XFS_ERROR(EFAULT);
 
 		return 0;
@@ -789,7 +781,7 @@ xfs_ioctl(
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 
-		if (copy_from_user(&in, (char *)arg, sizeof(in)))
+		if (copy_from_user(&in, arg, sizeof(in)))
 			return -XFS_ERROR(EFAULT);
 
 		error = xfs_growfs_data(mp, &in);
@@ -802,7 +794,7 @@ xfs_ioctl(
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 
-		if (copy_from_user(&in, (char *)arg, sizeof(in)))
+		if (copy_from_user(&in, arg, sizeof(in)))
 			return -XFS_ERROR(EFAULT);
 
 		error = xfs_growfs_log(mp, &in);
@@ -815,7 +807,7 @@ xfs_ioctl(
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 
-		if (copy_from_user(&in, (char *)arg, sizeof(in)))
+		if (copy_from_user(&in, arg, sizeof(in)))
 			return -XFS_ERROR(EFAULT);
 
 		error = xfs_growfs_rt(mp, &in);
@@ -826,13 +818,15 @@ xfs_ioctl(
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 
-		freeze_bdev(inode->i_sb->s_bdev);
+		if (inode->i_sb->s_frozen == SB_UNFROZEN)
+			freeze_bdev(inode->i_sb->s_bdev);
 		return 0;
 
 	case XFS_IOC_THAW:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		thaw_bdev(inode->i_sb->s_bdev, inode->i_sb);
+		if (inode->i_sb->s_frozen != SB_UNFROZEN)
+			thaw_bdev(inode->i_sb->s_bdev, inode->i_sb);
 		return 0;
 
 	case XFS_IOC_GOINGDOWN: {
@@ -841,7 +835,7 @@ xfs_ioctl(
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 
-		if (get_user(in, (__uint32_t *)arg))
+		if (get_user(in, (__uint32_t __user *)arg))
 			return -XFS_ERROR(EFAULT);
 
 		error = xfs_fs_goingdown(mp, in);
@@ -854,7 +848,7 @@ xfs_ioctl(
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 
-		if (copy_from_user(&in, (char *)arg, sizeof(in)))
+		if (copy_from_user(&in, arg, sizeof(in)))
 			return -XFS_ERROR(EFAULT);
 
 		error = xfs_errortag_add(in.errtag, mp);
@@ -880,7 +874,7 @@ xfs_ioc_space(
 	struct file		*filp,
 	int			ioflags,
 	unsigned int		cmd,
-	unsigned long		arg)
+	void			__user *arg)
 {
 	xfs_flock64_t		bf;
 	int			attr_flags = 0;
@@ -895,7 +889,7 @@ xfs_ioc_space(
 	if (vp->v_type != VREG)
 		return -XFS_ERROR(EINVAL);
 
-	if (copy_from_user(&bf, (xfs_flock64_t *)arg, sizeof(bf)))
+	if (copy_from_user(&bf, arg, sizeof(bf)))
 		return -XFS_ERROR(EFAULT);
 
 	if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
@@ -912,7 +906,7 @@ STATIC int
 xfs_ioc_bulkstat(
 	xfs_mount_t		*mp,
 	unsigned int		cmd,
-	unsigned long		arg)
+	void			__user *arg)
 {
 	xfs_fsop_bulkreq_t	bulkreq;
 	int			count;	/* # of records returned */
@@ -929,12 +923,10 @@ xfs_ioc_bulkstat(
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return -XFS_ERROR(EIO);
 
-	if (copy_from_user(&bulkreq, (xfs_fsop_bulkreq_t *)arg,
-					sizeof(xfs_fsop_bulkreq_t)))
+	if (copy_from_user(&bulkreq, arg, sizeof(xfs_fsop_bulkreq_t)))
 		return -XFS_ERROR(EFAULT);
 
-	if (copy_from_user(&inlast, (__s64 *)bulkreq.lastip,
-						sizeof(__s64)))
+	if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64)))
 		return -XFS_ERROR(EFAULT);
 
 	if ((count = bulkreq.icount) <= 0)
@@ -963,12 +955,11 @@ xfs_ioc_bulkstat(
 		return -error;
 
 	if (bulkreq.ocount != NULL) {
-		if (copy_to_user((xfs_ino_t *)bulkreq.lastip, &inlast,
+		if (copy_to_user(bulkreq.lastip, &inlast,
 						sizeof(xfs_ino_t)))
 			return -XFS_ERROR(EFAULT);
 
-		if (copy_to_user((__s32 *)bulkreq.ocount, &count,
-						sizeof(count)))
+		if (copy_to_user(bulkreq.ocount, &count, sizeof(count)))
 			return -XFS_ERROR(EFAULT);
 	}
 
@@ -978,7 +969,7 @@ xfs_ioc_bulkstat(
 STATIC int
 xfs_ioc_fsgeometry_v1(
 	xfs_mount_t		*mp,
-	unsigned long		arg)
+	void			__user *arg)
 {
 	xfs_fsop_geom_v1_t	fsgeo;
 	int			error;
@@ -987,7 +978,7 @@ xfs_ioc_fsgeometry_v1(
 	if (error)
 		return -error;
 
-	if (copy_to_user((xfs_fsop_geom_t *)arg, &fsgeo, sizeof(fsgeo)))
+	if (copy_to_user(arg, &fsgeo, sizeof(fsgeo)))
 		return -XFS_ERROR(EFAULT);
 	return 0;
 }
@@ -995,7 +986,7 @@ xfs_ioc_fsgeometry_v1(
 STATIC int
 xfs_ioc_fsgeometry(
 	xfs_mount_t		*mp,
-	unsigned long		arg)
+	void			__user *arg)
 {
 	xfs_fsop_geom_t		fsgeo;
 	int			error;
@@ -1004,7 +995,7 @@ xfs_ioc_fsgeometry(
 	if (error)
 		return -error;
 
-	if (copy_to_user((xfs_fsop_geom_t *)arg, &fsgeo, sizeof(fsgeo)))
+	if (copy_to_user(arg, &fsgeo, sizeof(fsgeo)))
 		return -XFS_ERROR(EFAULT);
 	return 0;
 }
@@ -1080,7 +1071,7 @@ xfs_ioc_xattr(
 	xfs_inode_t		*ip,
 	struct file		*filp,
 	unsigned int		cmd,
-	unsigned long		arg)
+	void			__user *arg)
 {
 	struct fsxattr		fa;
 	vattr_t			va;
@@ -1099,13 +1090,13 @@ xfs_ioc_xattr(
 		fa.fsx_extsize	= va.va_extsize;
 		fa.fsx_nextents = va.va_nextents;
 
-		if (copy_to_user((struct fsxattr *)arg, &fa, sizeof(fa)))
+		if (copy_to_user(arg, &fa, sizeof(fa)))
 			return -XFS_ERROR(EFAULT);
 		return 0;
 	}
 
 	case XFS_IOC_FSSETXATTR: {
-		if (copy_from_user(&fa, (struct fsxattr *)arg, sizeof(fa)))
+		if (copy_from_user(&fa, arg, sizeof(fa)))
 			return -XFS_ERROR(EFAULT);
 
 		attr_flags = 0;
@@ -1132,20 +1123,20 @@ xfs_ioc_xattr(
 		fa.fsx_extsize	= va.va_extsize;
 		fa.fsx_nextents = va.va_anextents;
 
-		if (copy_to_user((struct fsxattr *)arg, &fa, sizeof(fa)))
+		if (copy_to_user(arg, &fa, sizeof(fa)))
 			return -XFS_ERROR(EFAULT);
 		return 0;
 	}
 
 	case XFS_IOC_GETXFLAGS: {
 		flags = xfs_di2lxflags(ip->i_d.di_flags);
-		if (copy_to_user((unsigned int *)arg, &flags, sizeof(flags)))
+		if (copy_to_user(arg, &flags, sizeof(flags)))
 			return -XFS_ERROR(EFAULT);
 		return 0;
 	}
 
 	case XFS_IOC_SETXFLAGS: {
-		if (copy_from_user(&flags, (unsigned int *)arg, sizeof(flags)))
+		if (copy_from_user(&flags, arg, sizeof(flags)))
 			return -XFS_ERROR(EFAULT);
 
 		if (flags & ~(LINUX_XFLAG_IMMUTABLE | LINUX_XFLAG_APPEND | \
@@ -1169,7 +1160,7 @@ xfs_ioc_xattr(
 
 	case XFS_IOC_GETVERSION: {
 		flags = LINVFS_GET_IP(vp)->i_generation;
-		if (copy_to_user((unsigned int *)arg, &flags, sizeof(flags)))
+		if (copy_to_user(arg, &flags, sizeof(flags)))
 			return -XFS_ERROR(EFAULT);
 		return 0;
 	}
@@ -1185,13 +1176,13 @@ xfs_ioc_getbmap(
 	struct file		*filp,
 	int			ioflags,
 	unsigned int		cmd,
-	unsigned long		arg)
+	void			__user *arg)
 {
 	struct getbmap		bm;
 	int			iflags;
 	int			error;
 
-	if (copy_from_user(&bm, (struct getbmap *)arg, sizeof(bm)))
+	if (copy_from_user(&bm, arg, sizeof(bm)))
 		return -XFS_ERROR(EFAULT);
 
 	if (bm.bmv_count < 2)
@@ -1201,11 +1192,11 @@ xfs_ioc_getbmap(
 	if (ioflags & IO_INVIS)
 		iflags |= BMV_IF_NO_DMAPI_READ;
 
-	error = xfs_getbmap(bdp, &bm, (struct getbmap *)arg+1, iflags);
+	error = xfs_getbmap(bdp, &bm, (struct getbmap __user *)arg+1, iflags);
 	if (error)
 		return -error;
 
-	if (copy_to_user((struct getbmap *)arg, &bm, sizeof(bm)))
+	if (copy_to_user(arg, &bm, sizeof(bm)))
 		return -XFS_ERROR(EFAULT);
 	return 0;
 }
@@ -1213,14 +1204,14 @@ xfs_ioc_getbmap(
 STATIC int
 xfs_ioc_getbmapx(
 	bhv_desc_t		*bdp,
-	unsigned long		arg)
+	void			__user *arg)
 {
 	struct getbmapx		bmx;
 	struct getbmap		bm;
 	int			iflags;
 	int			error;
 
-	if (copy_from_user(&bmx, (struct getbmapx *)arg, sizeof(bmx)))
+	if (copy_from_user(&bmx, arg, sizeof(bmx)))
 		return -XFS_ERROR(EFAULT);
 
 	if (bmx.bmv_count < 2)
@@ -1239,13 +1230,13 @@ xfs_ioc_getbmapx(
 
 	iflags |= BMV_IF_EXTENDED;
 
-	error = xfs_getbmap(bdp, &bm, (struct getbmapx *)arg+1, iflags);
+	error = xfs_getbmap(bdp, &bm, (struct getbmapx __user *)arg+1, iflags);
 	if (error)
 		return -error;
 
 	GETBMAP_CONVERT(bm, bmx);
 
-	if (copy_to_user((struct getbmapx *)arg, &bmx, sizeof(bmx)))
+	if (copy_to_user(arg, &bmx, sizeof(bmx)))
 		return -XFS_ERROR(EFAULT);
 
 	return 0;
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 962cf8d6b..069dec844 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -174,8 +174,9 @@ linvfs_mknod(
 				 */
 				teardown.d_inode = ip = LINVFS_GET_IP(vp);
 				teardown.d_name = dentry->d_name;
-				remove_inode_hash(ip);
-				make_bad_inode(ip);
+
+				vn_mark_bad(vp);
+				
 				if (S_ISDIR(mode))
 					VOP_RMDIR(dvp, &teardown, NULL, err2);
 				else
@@ -225,26 +226,21 @@ linvfs_lookup(
 	struct dentry	*dentry,
 	struct nameidata *nd)
 {
-	struct inode	*ip = NULL;
-	vnode_t		*vp, *cvp = NULL;
+	struct vnode	*vp = LINVFS_GET_VP(dir), *cvp;
 	int		error;
 
 	if (dentry->d_name.len >= MAXNAMELEN)
 		return ERR_PTR(-ENAMETOOLONG);
 
-	vp = LINVFS_GET_VP(dir);
 	VOP_LOOKUP(vp, dentry, &cvp, 0, NULL, NULL, error);
-	if (!error) {
-		ASSERT(cvp);
-		ip = LINVFS_GET_IP(cvp);
-		if (!ip) {
-			VN_RELE(cvp);
-			return ERR_PTR(-EACCES);
-		}
+	if (error) {
+		if (unlikely(error != ENOENT))
+			return ERR_PTR(-error);
+		d_add(dentry, NULL);
+		return NULL;
 	}
-	if (error && (error != ENOENT))
-		return ERR_PTR(-error);
-	return d_splice_alias(ip, dentry);
+
+	return d_splice_alias(LINVFS_GET_IP(cvp), dentry);
 }
 
 STATIC int
@@ -304,7 +300,7 @@ linvfs_symlink(
 {
 	struct inode	*ip;
 	vattr_t		va;
-	vnode_t		*dvp;	/* directory containing name to remove */
+	vnode_t		*dvp;	/* directory containing name of symlink */
 	vnode_t		*cvp;	/* used to lookup symlink to put in dentry */
 	int		error;
 
@@ -376,7 +372,7 @@ linvfs_rename(
 STATIC int
 linvfs_readlink(
 	struct dentry	*dentry,
-	char		*buf,
+	char		__user *buf,
 	int		size)
 {
 	vnode_t		*vp = LINVFS_GET_VP(dentry->d_inode);
diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h
index f0f5c870f..6a69a62c3 100644
--- a/fs/xfs/linux-2.6/xfs_iops.h
+++ b/fs/xfs/linux-2.6/xfs_iops.h
@@ -46,6 +46,6 @@ extern int linvfs_get_block(struct inode *, sector_t, struct buffer_head *, int)
 extern void linvfs_unwritten_done(struct buffer_head *, int);
 
 extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *,
-                        int, unsigned int, unsigned long);
+                        int, unsigned int, void __user *);
 
 #endif /* __XFS_IOPS_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index ecaa3c00b..bbf4ef470 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -85,6 +85,7 @@
 #include <linux/vfs.h>
 #include <linux/seq_file.h>
 #include <linux/init.h>
+#include <linux/list.h>
 #include <linux/proc_fs.h>
 #include <linux/version.h>
 
@@ -140,6 +141,7 @@ static inline void set_buffer_unwritten_io(struct buffer_head *bh)
 #define xfs_inherit_noatime	xfs_params.inherit_noatim.val
 #define xfs_buf_timer_centisecs	xfs_params.xfs_buf_timer.val
 #define xfs_buf_age_centisecs	xfs_params.xfs_buf_age.val
+#define xfs_inherit_nosymlinks	xfs_params.inherit_nosym.val
 
 #define current_cpu()		smp_processor_id()
 #define current_pid()		(current->pid)
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index c45e9639c..903e60e59 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -74,6 +74,7 @@
 #include "xfs_iomap.h"
 
 #include <linux/capability.h>
+#include <linux/writeback.h>
 
 
 #if defined(XFS_RW_TRACE)
@@ -81,7 +82,7 @@ void
 xfs_rw_enter_trace(
 	int			tag,
 	xfs_iocore_t		*io,
-	const struct iovec	*iovp,
+	void			*data,
 	size_t			segs,
 	loff_t			offset,
 	int			ioflags)
@@ -95,7 +96,7 @@ xfs_rw_enter_trace(
 		(void *)ip,
 		(void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)),
 		(void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)),
-		(void *)(__psint_t)iovp,
+		(void *)data,
 		(void *)((unsigned long)segs),
 		(void *)((unsigned long)((offset >> 32) & 0xffffffff)),
 		(void *)((unsigned long)(offset & 0xffffffff)),
@@ -225,40 +226,11 @@ xfs_inval_cached_pages(
 	int		write,
 	int		relock)
 {
-	xfs_mount_t	*mp;
-
-	if (!VN_CACHED(vp)) {
-		return;
-	}
-
-	mp = io->io_mount;
-
-	/*
-	 * We need to get the I/O lock exclusively in order
-	 * to safely invalidate pages and mappings.
-	 */
-	if (relock) {
-		XFS_IUNLOCK(mp, io, XFS_IOLOCK_SHARED);
-		XFS_ILOCK(mp, io, XFS_IOLOCK_EXCL);
-	}
-
-	/* Writing beyond EOF creates a hole that must be zeroed */
-	if (write && (offset > XFS_SIZE(mp, io))) {
-		xfs_fsize_t	isize;
-
-		XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
-		isize = XFS_SIZE(mp, io);
-		if (offset > isize) {
-			xfs_zero_eof(vp, io, offset, isize, offset);
-		}
-		XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
+	if (VN_CACHED(vp)) {
+		xfs_inval_cached_trace(io, offset, -1, ctooff(offtoct(offset)), -1);
+		VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(offset)), -1, FI_REMAPF_LOCKED);
 	}
 
-	xfs_inval_cached_trace(io, offset, -1, ctooff(offtoct(offset)), -1);
-	VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(offset)), -1, FI_REMAPF_LOCKED);
-	if (relock) {
-		XFS_ILOCK_DEMOTE(mp, io, XFS_IOLOCK_EXCL);
-	}
 }
 
 ssize_t			/* bytes read, or (-)  error */
@@ -324,11 +296,6 @@ xfs_read(
 		return -EIO;
 	}
 
-	/* OK so we are holding the I/O lock for the duration
-	 * of the submission, then what happens if the I/O
-	 * does not really happen here, but is scheduled 
-	 * later?
-	 */
 	xfs_ilock(ip, XFS_IOLOCK_SHARED);
 
 	if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
@@ -345,8 +312,11 @@ xfs_read(
 	}
 
 	xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore,
-				iovp, segs, *offset, ioflags);
+				(void *)iovp, segs, *offset, ioflags);
 	ret = __generic_file_aio_read(iocb, iovp, segs, offset);
+	if (ret == -EIOCBQUEUED)
+		ret = wait_on_sync_kiocb(iocb);
+
 	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
 
 	if (ret > 0)
@@ -406,12 +376,17 @@ xfs_sendfile(
 		}
 	}
 	xfs_rw_enter_trace(XFS_SENDFILE_ENTER, &ip->i_iocore,
-				target, count, *offset, ioflags);
+		   (void *)(unsigned long)target, count, *offset, ioflags);
 	ret = generic_file_sendfile(filp, offset, count, actor, target);
+
 	xfs_iunlock(ip, XFS_IOLOCK_SHARED);
 
-	XFS_STATS_ADD(xs_read_bytes, ret);
-	xfs_ichgtime(ip, XFS_ICHGTIME_ACC);
+	if (ret > 0)
+		XFS_STATS_ADD(xs_read_bytes, ret);
+
+	if (likely(!(ioflags & IO_INVIS)))
+		xfs_ichgtime(ip, XFS_ICHGTIME_ACC);
+
 	return ret;
 }
 
@@ -637,32 +612,34 @@ xfs_write(
 	bhv_desc_t		*bdp,
 	struct kiocb		*iocb,
 	const struct iovec	*iovp,
-	unsigned int		segs,
+	unsigned int		nsegs,
 	loff_t			*offset,
 	int			ioflags,
 	cred_t			*credp)
 {
 	struct file		*file = iocb->ki_filp;
-	size_t			size = 0;
+	struct address_space	*mapping = file->f_mapping;
+	struct inode		*inode = mapping->host;
+	unsigned long		segs = nsegs;
 	xfs_inode_t		*xip;
 	xfs_mount_t		*mp;
-	ssize_t			ret;
-	int			error = 0;
+	ssize_t			ret = 0, error = 0;
 	xfs_fsize_t		isize, new_size;
-	xfs_fsize_t		n, limit;
 	xfs_iocore_t		*io;
 	vnode_t			*vp;
 	unsigned long		seg;
 	int			iolock;
 	int			eventsent = 0;
 	vrwlock_t		locktype;
+	size_t			ocount = 0, count;
+	loff_t			pos;
+	int			need_isem = 1, need_flush = 0;
 
 	XFS_STATS_INC(xs_write_calls);
 
 	vp = BHV_TO_VNODE(bdp);
 	xip = XFS_BHVTOI(bdp);
 
-	/* START copy & waste from filemap.c */
 	for (seg = 0; seg < segs; seg++) {
 		const struct iovec *iv = &iovp[seg];
 
@@ -670,73 +647,90 @@ xfs_write(
 		 * If any segment has a negative length, or the cumulative
 		 * length ever wraps negative then return -EINVAL.
 		 */
-		size += iv->iov_len;
-		if (unlikely((ssize_t)(size|iv->iov_len) < 0))
-			return XFS_ERROR(-EINVAL);
+		ocount += iv->iov_len;
+		if (unlikely((ssize_t)(ocount|iv->iov_len) < 0))
+			return -EINVAL;
+		if (access_ok(VERIFY_READ, iv->iov_base, iv->iov_len))
+			continue;
+		if (seg == 0)
+			return -EFAULT;
+		segs = seg;
+		ocount -= iv->iov_len;  /* This segment is no good */
+		break;
 	}
-	/* END copy & waste from filemap.c */
 
-	if (size == 0)
+	count = ocount;
+	pos = *offset;
+
+	if (count == 0)
 		return 0;
 
 	io = &xip->i_iocore;
 	mp = io->io_mount;
 
-	if (XFS_FORCED_SHUTDOWN(mp)) {
+	if (XFS_FORCED_SHUTDOWN(mp))
 		return -EIO;
-	}
 
 	if (ioflags & IO_ISDIRECT) {
 		xfs_buftarg_t	*target =
 			(xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
 				mp->m_rtdev_targp : mp->m_ddev_targp;
 
-		if ((*offset & target->pbr_smask) ||
-		    (size & target->pbr_smask)) {
+		if ((pos & target->pbr_smask) || (count & target->pbr_smask))
 			return XFS_ERROR(-EINVAL);
-		}
-		iolock = XFS_IOLOCK_SHARED;
-		locktype = VRWLOCK_WRITE_DIRECT;
-	} else {
+
+		if (!VN_CACHED(vp) && pos < i_size_read(inode))
+			need_isem = 0;
+
+		if (VN_CACHED(vp))
+			need_flush = 1;
+	}
+
+relock:
+	if (need_isem) {
 		iolock = XFS_IOLOCK_EXCL;
 		locktype = VRWLOCK_WRITE;
+
+		down(&inode->i_sem);
+	} else {
+		iolock = XFS_IOLOCK_SHARED;
+		locktype = VRWLOCK_WRITE_DIRECT;
 	}
 
 	xfs_ilock(xip, XFS_ILOCK_EXCL|iolock);
 
-	isize = xip->i_d.di_size;
-	limit = XFS_MAXIOFFSET(mp);
+	isize = i_size_read(inode);
 
 	if (file->f_flags & O_APPEND)
 		*offset = isize;
 
 start:
-	n = limit - *offset;
-	if (n <= 0) {
+	error = -generic_write_checks(file, &pos, &count,
+					S_ISBLK(inode->i_mode));
+	if (error) {
 		xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
-		return -EFBIG;
+		goto out_unlock_isem;
 	}
 
-	if (n < size)
-		size = n;
-
-	new_size = *offset + size;
-	if (new_size > isize) {
+	new_size = pos + count;
+	if (new_size > isize)
 		io->io_new_size = new_size;
-	}
 
 	if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) &&
 	    !(ioflags & IO_INVIS) && !eventsent)) {
-		loff_t		savedsize = *offset;
-		int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
+		loff_t		savedsize = pos;
+		int		dmflags = FILP_DELAY_FLAG(file);
+
+		if (need_isem)
+			dmflags |= DM_FLAGS_ISEM;
 
 		xfs_iunlock(xip, XFS_ILOCK_EXCL);
 		error = XFS_SEND_DATA(xip->i_mount, DM_EVENT_WRITE, vp,
-				      *offset, size,
+				      pos, count,
 				      dmflags, &locktype);
 		if (error) {
 			xfs_iunlock(xip, iolock);
-			return -error;
+			goto out_unlock_isem;
 		}
 		xfs_ilock(xip, XFS_ILOCK_EXCL);
 		eventsent = 1;
@@ -748,9 +742,8 @@ start:
 		 * event prevents another call to XFS_SEND_DATA, which is
 		 * what allows the size to change in the first place.
 		 */
-		if ((file->f_flags & O_APPEND) &&
-		    savedsize != xip->i_d.di_size) {
-			*offset = isize = xip->i_d.di_size;
+		if ((file->f_flags & O_APPEND) && savedsize != isize) {
+			pos = isize = xip->i_d.di_size;
 			goto start;
 		}
 	}
@@ -761,8 +754,10 @@ start:
 	 *
 	 * We must update xfs' times since revalidate will overcopy xfs.
 	 */
-	if (size && !(ioflags & IO_INVIS))
+	if (!(ioflags & IO_INVIS)) {
 		xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+		inode_update_time(inode, 1);
+	}
 
 	/*
 	 * If the offset is beyond the size of the file, we have a couple
@@ -773,12 +768,12 @@ start:
 	 * to zero it out up to the new size.
 	 */
 
-	if (!(ioflags & IO_ISDIRECT) && (*offset > isize && isize)) {
-		error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, *offset,
-			isize, *offset + size);
+	if (pos > isize) {
+		error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos,
+					isize, pos + count);
 		if (error) {
 			xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
-			return(-error);
+			goto out_unlock_isem;
 		}
 	}
 	xfs_iunlock(xip, XFS_ILOCK_EXCL);
@@ -795,22 +790,67 @@ start:
 		(S_ISGID | S_IXGRP))) &&
 	     !capable(CAP_FSETID)) {
 		error = xfs_write_clear_setuid(xip);
-		if (error) {
+		if (likely(!error))
+			error = -remove_suid(file->f_dentry);
+		if (unlikely(error)) {
 			xfs_iunlock(xip, iolock);
-			return -error;
+			goto out_unlock_isem;
 		}
 	}
 
 retry:
-	if (ioflags & IO_ISDIRECT) {
-		xfs_inval_cached_pages(vp, io, *offset, 1, 1);
-		xfs_rw_enter_trace(XFS_DIOWR_ENTER,
-				io, iovp, segs, *offset, ioflags);
+	/* We can write back this queue in page reclaim */
+	current->backing_dev_info = mapping->backing_dev_info;
+
+	if ((ioflags & IO_ISDIRECT)) {
+		if (need_flush) {
+			xfs_inval_cached_trace(io, pos, -1,
+					ctooff(offtoct(pos)), -1);
+			VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(pos)),
+					-1, FI_REMAPF_LOCKED);
+		}
+
+		if (need_isem) {
+			/* demote the lock now the cached pages are gone */
+			XFS_ILOCK_DEMOTE(mp, io, XFS_IOLOCK_EXCL);
+			up(&inode->i_sem);
+
+			iolock = XFS_IOLOCK_SHARED;
+			locktype = VRWLOCK_WRITE_DIRECT;
+			need_isem = 0;
+		}
+
+ 		xfs_rw_enter_trace(XFS_DIOWR_ENTER, io, (void *)iovp, segs,
+				*offset, ioflags);
+		ret = generic_file_direct_write(iocb, iovp,
+				&segs, pos, offset, count, ocount);
+
+		/*
+		 * direct-io write to a hole: fall through to buffered I/O
+		 * for completing the rest of the request.
+		 */
+		if (ret >= 0 && ret != count) {
+			XFS_STATS_ADD(xs_write_bytes, ret);
+
+			pos += ret;
+			count -= ret;
+
+			need_isem = 1;
+			ioflags &= ~IO_ISDIRECT;
+			xfs_iunlock(xip, iolock);
+			goto relock;
+		}
 	} else {
-		xfs_rw_enter_trace(XFS_WRITE_ENTER,
-				io, iovp, segs, *offset, ioflags);
+		xfs_rw_enter_trace(XFS_WRITE_ENTER, io, (void *)iovp, segs,
+				*offset, ioflags);
+		ret = generic_file_buffered_write(iocb, iovp, segs,
+				pos, offset, count, ret);
 	}
-	ret = generic_file_aio_write_nolock(iocb, iovp, segs, offset);
+
+	current->backing_dev_info = NULL;
+
+	if (ret == -EIOCBQUEUED)
+		ret = wait_on_sync_kiocb(iocb);
 
 	if ((ret == -ENOSPC) &&
 	    DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_NOSPACE) &&
@@ -821,17 +861,15 @@ retry:
 				DM_RIGHT_NULL, vp, DM_RIGHT_NULL, NULL, NULL,
 				0, 0, 0); /* Delay flag intentionally  unused */
 		if (error)
-			return -error;
+			goto out_unlock_isem;
 		xfs_rwlock(bdp, locktype);
-		*offset = xip->i_d.di_size;
+		pos = xip->i_d.di_size;
 		goto retry;
 	}
 
 	if (*offset > xip->i_d.di_size) {
 		xfs_ilock(xip, XFS_ILOCK_EXCL);
 		if (*offset > xip->i_d.di_size) {
-			struct inode	*inode = LINVFS_GET_IP(vp);
-
 			xip->i_d.di_size = *offset;
 			i_size_write(inode, *offset);
 			xip->i_update_core = 1;
@@ -840,23 +878,22 @@ retry:
 		xfs_iunlock(xip, XFS_ILOCK_EXCL);
 	}
 
-	if (ret <= 0) {
-		xfs_rwunlock(bdp, locktype);
-		return ret;
-	}
+	error = -ret;
+	if (ret <= 0)
+		goto out_unlock_internal;
 
 	XFS_STATS_ADD(xs_write_bytes, ret);
 
 	/* Handle various SYNC-type writes */
-	if ((file->f_flags & O_SYNC) || IS_SYNC(file->f_dentry->d_inode)) {
-
+	if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) {
 		/*
 		 * If we're treating this as O_DSYNC and we have not updated the
 		 * size, force the log.
 		 */
+		if (!(mp->m_flags & XFS_MOUNT_OSYNCISOSYNC) &&
+		    !(xip->i_update_size)) {
+			xfs_inode_log_item_t	*iip = xip->i_itemp;
 
-		if (!(mp->m_flags & XFS_MOUNT_OSYNCISOSYNC)
-			&& !(xip->i_update_size)) {
 			/*
 			 * If an allocation transaction occurred
 			 * without extending the size, then we have to force
@@ -876,14 +913,8 @@ retry:
 			 * all changes affecting the inode are permanent
 			 * when we return.
 			 */
-
-			xfs_inode_log_item_t *iip;
-			xfs_lsn_t lsn;
-
-			iip = xip->i_itemp;
 			if (iip && iip->ili_last_lsn) {
-				lsn = iip->ili_last_lsn;
-				xfs_log_force(mp, lsn,
+				xfs_log_force(mp, iip->ili_last_lsn,
 						XFS_LOG_FORCE | XFS_LOG_SYNC);
 			} else if (xfs_ipincount(xip) > 0) {
 				xfs_log_force(mp, (xfs_lsn_t)0,
@@ -924,12 +955,27 @@ retry:
 				xfs_trans_set_sync(tp);
 				error = xfs_trans_commit(tp, 0, NULL);
 				xfs_iunlock(xip, XFS_ILOCK_EXCL);
+				if (error)
+					goto out_unlock_internal;
 			}
 		}
-	} /* (ioflags & O_SYNC) */
+	
+		xfs_rwunlock(bdp, locktype);
+		if (need_isem)
+			up(&inode->i_sem);
+
+		error = sync_page_range(inode, mapping, pos, ret);
+		if (!error)
+			error = ret;
+		return error;
+	}
 
+ out_unlock_internal:
 	xfs_rwunlock(bdp, locktype);
-	return(ret);
+ out_unlock_isem:
+	if (need_isem)
+		up(&inode->i_sem);
+	return -error;
 }
 
 /*
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
index faf0afc70..d723e3525 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.h
+++ b/fs/xfs/linux-2.6/xfs_lrw.h
@@ -74,11 +74,11 @@ struct xfs_iomap;
 #define	XFS_IOMAP_ALLOC_MAP	25
 #define	XFS_IOMAP_UNWRITTEN	26
 extern void xfs_rw_enter_trace(int, struct xfs_iocore *,
-			const struct iovec *, size_t, loff_t, int);
+				void *, size_t, loff_t, int);
 extern void xfs_inval_cached_trace(struct xfs_iocore *,
-			xfs_off_t, xfs_off_t, xfs_off_t, xfs_off_t);
+				xfs_off_t, xfs_off_t, xfs_off_t, xfs_off_t);
 #else
-#define xfs_rw_enter_trace(tag, io, iovec, segs, offset, ioflags)
+#define xfs_rw_enter_trace(tag, io, data, size, offset, ioflags)
 #define xfs_inval_cached_trace(io, offset, len, first, last)
 #endif
 
diff --git a/fs/xfs/linux-2.6/xfs_stats.c b/fs/xfs/linux-2.6/xfs_stats.c
index 86b633e7a..aaf5ddba4 100644
--- a/fs/xfs/linux-2.6/xfs_stats.c
+++ b/fs/xfs/linux-2.6/xfs_stats.c
@@ -119,9 +119,9 @@ xfs_read_xfsstats(
 void
 xfs_init_procfs(void)
 {
-	if (!proc_mkdir("fs/xfs", 0))
+	if (!proc_mkdir("fs/xfs", NULL))
 		return;
-	create_proc_read_entry("fs/xfs/stat", 0, 0, xfs_read_xfsstats, NULL);
+	create_proc_read_entry("fs/xfs/stat", 0, NULL, xfs_read_xfsstats, NULL);
 }
 
 void
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 3a2e961ea..eb81476f7 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -66,6 +66,7 @@
 #include "xfs_buf_item.h"
 #include "xfs_utils.h"
 #include "xfs_version.h"
+#include "xfs_ioctl32.h"
 
 #include <linux/namei.h>
 #include <linux/init.h>
@@ -140,7 +141,7 @@ xfs_set_inodeops(
 	vnode_t			*vp = LINVFS_GET_VP(inode);
 
 	if (vp->v_type == VNON) {
-		make_bad_inode(inode);
+		vn_mark_bad(vp);
 	} else if (S_ISREG(inode->i_mode)) {
 		inode->i_op = &linvfs_file_inode_operations;
 		inode->i_fop = &linvfs_file_operations;
@@ -230,42 +231,21 @@ xfs_initialize_vnode(
 		bhv_insert(VN_BHV_HEAD(vp), inode_bhv);
 	}
 
-	vp->v_type = IFTOVT(ip->i_d.di_mode);
-
-	/* Have we been called during the new inode create process,
-	 * in which case we are too early to fill in the Linux inode.
-	 */
-	if (vp->v_type == VNON)
-		return;
-
-	xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip);
-
-	/* For new inodes we need to set the ops vectors,
-	 * and unlock the inode.
+	/*
+	 * We need to set the ops vectors, and unlock the inode, but if
+	 * we have been called during the new inode create process, it is
+	 * too early to fill in the Linux inode.  We will get called a
+	 * second time once the inode is properly set up, and then we can
+	 * finish our work.
 	 */
-	if (unlock && (inode->i_state & I_NEW)) {
+	if (ip->i_d.di_mode != 0 && unlock && (inode->i_state & I_NEW)) {
+		vp->v_type = IFTOVT(ip->i_d.di_mode);
+		xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip);
 		xfs_set_inodeops(inode);
 		unlock_new_inode(inode);
 	}
 }
 
-void
-xfs_flush_inode(
-	xfs_inode_t	*ip)
-{
-	struct inode	*inode = LINVFS_GET_IP(XFS_ITOV(ip));
-
-	filemap_flush(inode->i_mapping);
-}
-
-void
-xfs_flush_device(
-	xfs_inode_t	*ip)
-{
-	sync_blockdev(XFS_ITOV(ip)->v_vfsp->vfs_super->s_bdev);
-	xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
-}
-
 int
 xfs_blkdev_get(
 	xfs_mount_t		*mp,
@@ -319,7 +299,6 @@ xfs_inode_shake(
 {
 	int		pages;
 
-	
 	pages = kmem_zone_shrink(linvfs_inode_zone);
 	pages += kmem_zone_shrink(xfs_inode_zone);
 	return pages;
@@ -342,10 +321,8 @@ STATIC int
 init_inodecache( void )
 {
 	linvfs_inode_zone = kmem_cache_create("linvfs_icache",
-				sizeof(vnode_t), 0,
-				SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+				sizeof(vnode_t), 0, SLAB_RECLAIM_ACCOUNT,
 				init_once, NULL);
-
 	if (linvfs_inode_zone == NULL)
 		return -ENOMEM;
 	return 0;
@@ -364,13 +341,13 @@ destroy_inodecache( void )
  * at the point when it is unpinned after a log write,
  * since this is when the inode itself becomes flushable. 
  */
-STATIC void
+STATIC int
 linvfs_write_inode(
 	struct inode		*inode,
 	int			sync)
 {
 	vnode_t			*vp = LINVFS_GET_VP(inode);
-	int			error, flags = FLUSH_INODE;
+	int			error = 0, flags = FLUSH_INODE;
 
 	if (vp) {
 		vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
@@ -378,6 +355,8 @@ linvfs_write_inode(
 			flags |= FLUSH_SYNC;
 		VOP_IFLUSH(vp, flags, error);
 	}
+
+	return -error;
 }
 
 STATIC void
@@ -397,36 +376,152 @@ linvfs_clear_inode(
 }
 
 
+/*
+ * Enqueue a work item to be picked up by the vfs xfssyncd thread.
+ * Doing this has two advantages:
+ * - It saves on stack space, which is tight in certain situations
+ * - It can be used (with care) as a mechanism to avoid deadlocks.
+ * Flushing while allocating in a full filesystem requires both.
+ */
+STATIC void
+xfs_syncd_queue_work(
+	struct vfs	*vfs,
+	void		*data,
+	void		(*syncer)(vfs_t *, void *))
+{
+	vfs_sync_work_t	*work;
+
+	work = kmem_alloc(sizeof(struct vfs_sync_work), KM_SLEEP);
+	INIT_LIST_HEAD(&work->w_list);
+	work->w_syncer = syncer;
+	work->w_data = data;
+	work->w_vfs = vfs;
+	spin_lock(&vfs->vfs_sync_lock);
+	list_add_tail(&work->w_list, &vfs->vfs_sync_list);
+	spin_unlock(&vfs->vfs_sync_lock);
+	wake_up_process(vfs->vfs_sync_task);
+}
+
+/*
+ * Flush delayed allocate data, attempting to free up reserved space
+ * from existing allocations.  At this point a new allocation attempt
+ * has failed with ENOSPC and we are in the process of scratching our
+ * heads, looking about for more room...
+ */
+STATIC void
+xfs_flush_inode_work(
+	vfs_t		*vfs,
+	void		*inode)
+{
+	filemap_flush(((struct inode *)inode)->i_mapping);
+	iput((struct inode *)inode);
+}
+
+void
+xfs_flush_inode(
+	xfs_inode_t	*ip)
+{
+	struct inode	*inode = LINVFS_GET_IP(XFS_ITOV(ip));
+	struct vfs	*vfs = XFS_MTOVFS(ip->i_mount);
+
+	igrab(inode);
+	xfs_syncd_queue_work(vfs, inode, xfs_flush_inode_work);
+	delay(HZ/2);
+}
+
+/*
+ * This is the "bigger hammer" version of xfs_flush_inode_work...
+ * (IOW, "If at first you don't succeed, use a Bigger Hammer").
+ */
+STATIC void
+xfs_flush_device_work(
+	vfs_t		*vfs,
+	void		*inode)
+{
+	sync_blockdev(vfs->vfs_super->s_bdev);
+	iput((struct inode *)inode);
+}
+
+void
+xfs_flush_device(
+	xfs_inode_t	*ip)
+{
+	struct inode	*inode = LINVFS_GET_IP(XFS_ITOV(ip));
+	struct vfs	*vfs = XFS_MTOVFS(ip->i_mount);
+
+	igrab(inode);
+	xfs_syncd_queue_work(vfs, inode, xfs_flush_device_work);
+	delay(HZ/2);
+	xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
+}
+
 #define SYNCD_FLAGS	(SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR)
+STATIC void
+vfs_sync_worker(
+	vfs_t		*vfsp,
+	void		*unused)
+{
+	int		error;
+
+	if (!(vfsp->vfs_flag & VFS_RDONLY))
+		VFS_SYNC(vfsp, SYNCD_FLAGS, NULL, error);
+	vfsp->vfs_sync_seq++;
+	wmb();
+	wake_up(&vfsp->vfs_wait_single_sync_task);
+}
 
 STATIC int
 xfssyncd(
 	void			*arg)
 {
+	long			timeleft;
 	vfs_t			*vfsp = (vfs_t *) arg;
-	int			error;
+	struct list_head	tmp;
+	struct vfs_sync_work	*work, *n;
 
 	daemonize("xfssyncd");
 
+	vfsp->vfs_sync_work.w_vfs = vfsp;
+	vfsp->vfs_sync_work.w_syncer = vfs_sync_worker;
 	vfsp->vfs_sync_task = current;
 	wmb();
 	wake_up(&vfsp->vfs_wait_sync_task);
 
+	INIT_LIST_HEAD(&tmp);
+	timeleft = (xfs_syncd_centisecs * HZ) / 100;
 	for (;;) {
 		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout((xfs_syncd_centisecs * HZ) / 100);
+		timeleft = schedule_timeout(timeleft);
 		/* swsusp */
 		if (current->flags & PF_FREEZE)
 			refrigerator(PF_FREEZE);
 		if (vfsp->vfs_flag & VFS_UMOUNT)
 			break;
-		if (vfsp->vfs_flag & VFS_RDONLY)
-			continue;
-		VFS_SYNC(vfsp, SYNCD_FLAGS, NULL, error);
 
-		vfsp->vfs_sync_seq++;
-		wmb();
-		wake_up(&vfsp->vfs_wait_single_sync_task);
+		spin_lock(&vfsp->vfs_sync_lock);
+		/*
+		 * We can get woken by laptop mode, to do a sync -
+		 * that's the (only!) case where the list would be
+		 * empty with time remaining.
+		 */
+		if (!timeleft || list_empty(&vfsp->vfs_sync_list)) {
+			if (!timeleft)
+				timeleft = (xfs_syncd_centisecs * HZ) / 100;
+			INIT_LIST_HEAD(&vfsp->vfs_sync_work.w_list);
+			list_add_tail(&vfsp->vfs_sync_work.w_list,
+					&vfsp->vfs_sync_list);
+		}
+		list_for_each_entry_safe(work, n, &vfsp->vfs_sync_list, w_list)
+			list_move(&work->w_list, &tmp);
+		spin_unlock(&vfsp->vfs_sync_lock);
+
+		list_for_each_entry_safe(work, n, &tmp, w_list) {
+			(*work->w_syncer)(vfsp, work->w_data);
+			list_del(&work->w_list);
+			if (work == &vfsp->vfs_sync_work)
+				continue;
+			kmem_free(work, sizeof(struct vfs_sync_work));
+		}
 	}
 
 	vfsp->vfs_sync_task = NULL;
@@ -514,9 +609,10 @@ linvfs_sync_super(
 
 	if (unlikely(laptop_mode)) {
 		int	prev_sync_seq = vfsp->vfs_sync_seq;
+
 		/*
 		 * The disk must be active because we're syncing.
-		 * We schedule syncd now (now that the disk is
+		 * We schedule xfssyncd now (now that the disk is
 		 * active) instead of later (when it might not be).
 		 */
 		wake_up_process(vfsp->vfs_sync_task);
@@ -576,31 +672,22 @@ linvfs_get_parent(
 	int			error;
 	vnode_t			*vp, *cvp;
 	struct dentry		*parent;
-	struct inode		*ip = NULL;
 	struct dentry		dotdot;
 
 	dotdot.d_name.name = "..";
 	dotdot.d_name.len = 2;
-	dotdot.d_inode = 0;
+	dotdot.d_inode = NULL;
 
 	cvp = NULL;
 	vp = LINVFS_GET_VP(child->d_inode);
 	VOP_LOOKUP(vp, &dotdot, &cvp, 0, NULL, NULL, error);
-
-	if (!error) {
-		ASSERT(cvp);
-		ip = LINVFS_GET_IP(cvp);
-		if (!ip) {
-			VN_RELE(cvp);
-			return ERR_PTR(-EACCES);
-		}
-	}
-	if (error)
+	if (unlikely(error))
 		return ERR_PTR(-error);
-	parent = d_alloc_anon(ip);
-	if (!parent) {
+
+	parent = d_alloc_anon(LINVFS_GET_IP(cvp));
+	if (unlikely(!parent)) {
 		VN_RELE(cvp);
-		parent = ERR_PTR(-ENOMEM);
+		return ERR_PTR(-ENOMEM);
 	}
 	return parent;
 }
@@ -865,6 +952,10 @@ init_xfs_fs( void )
 		goto undo_shaker;
 	}
 
+	error = xfs_ioctl32_init();
+	if (error)
+		goto undo_ioctl32;
+
 	error = register_filesystem(&xfs_fs_type);
 	if (error)
 		goto undo_register;
@@ -872,6 +963,9 @@ init_xfs_fs( void )
 	return 0;
 
 undo_register:
+	xfs_ioctl32_exit();
+
+undo_ioctl32:
 	kmem_shake_deregister(xfs_inode_shaker);
 
 undo_shaker:
@@ -890,6 +984,7 @@ exit_xfs_fs( void )
 	vfs_exitquota();
 	XFS_DM_EXIT(&xfs_fs_type);
 	unregister_filesystem(&xfs_fs_type);
+	xfs_ioctl32_exit();
 	kmem_shake_deregister(xfs_inode_shaker);
 	xfs_cleanup();
 	pagebuf_terminate();
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c
index 4a173d3d8..c24529657 100644
--- a/fs/xfs/linux-2.6/xfs_sysctl.c
+++ b/fs/xfs/linux-2.6/xfs_sysctl.c
@@ -45,7 +45,7 @@ xfs_stats_clear_proc_handler(
 	ctl_table	*ctl,
 	int		write,
 	struct file	*filp,
-	void		*buffer,
+	void		__user *buffer,
 	size_t		*lenp,
 	loff_t		*ppos)
 {
@@ -129,6 +129,11 @@ STATIC ctl_table xfs_table[] = {
 	&sysctl_intvec, NULL,
 	&xfs_params.xfs_buf_age.min, &xfs_params.xfs_buf_age.max},
 
+	{XFS_INHERIT_NOSYM, "inherit_nosymlinks", &xfs_params.inherit_nosym.val,
+	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
+	&sysctl_intvec, NULL,
+	&xfs_params.inherit_nosym.min, &xfs_params.inherit_nosym.max},
+
 	/* please keep this the last entry */
 #ifdef CONFIG_PROC_FS
 	{XFS_STATS_CLEAR, "stats_clear", &xfs_params.stats_clear.val,
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.h b/fs/xfs/linux-2.6/xfs_sysctl.h
index 872014bef..5ff61bb56 100644
--- a/fs/xfs/linux-2.6/xfs_sysctl.h
+++ b/fs/xfs/linux-2.6/xfs_sysctl.h
@@ -59,6 +59,7 @@ typedef struct xfs_param {
 	xfs_sysctl_val_t inherit_noatim;/* Inherit the "noatime" inode flag. */
 	xfs_sysctl_val_t xfs_buf_timer;	/* Interval between xfsbufd wakeups. */
 	xfs_sysctl_val_t xfs_buf_age;	/* Metadata buffer age before flush. */
+	xfs_sysctl_val_t inherit_nosym;	/* Inherit the "nosymlinks" flag. */
 } xfs_param_t;
 
 /*
@@ -95,6 +96,7 @@ enum {
 	XFS_BUF_TIMER = 16,
 	XFS_BUF_AGE = 17,
 	/* XFS_IO_BYPASS = 18 */
+	XFS_INHERIT_NOSYM = 19,
 };
 
 extern xfs_param_t	xfs_params;
diff --git a/fs/xfs/linux-2.6/xfs_vfs.c b/fs/xfs/linux-2.6/xfs_vfs.c
index 897b9dc8d..855e91488 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.c
+++ b/fs/xfs/linux-2.6/xfs_vfs.c
@@ -249,6 +249,8 @@ vfs_allocate( void )
 
 	vfsp = kmem_zalloc(sizeof(vfs_t), KM_SLEEP);
 	bhv_head_init(VFS_BHVHEAD(vfsp), "vfs");
+	INIT_LIST_HEAD(&vfsp->vfs_sync_list);
+	vfsp->vfs_sync_lock = SPIN_LOCK_UNLOCKED;
 	init_waitqueue_head(&vfsp->vfs_wait_sync_task);
 	init_waitqueue_head(&vfsp->vfs_wait_single_sync_task);
 	return vfsp;
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h
index 3c7ca8468..aab70136c 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.h
+++ b/fs/xfs/linux-2.6/xfs_vfs.h
@@ -36,6 +36,7 @@
 #include "xfs_fs.h"
 
 struct fid;
+struct vfs;
 struct cred;
 struct vnode;
 struct kstatfs;
@@ -45,14 +46,24 @@ struct xfs_mount_args;
 
 typedef struct kstatfs xfs_statfs_t;
 
+typedef struct vfs_sync_work {
+	struct list_head	w_list;
+	struct vfs		*w_vfs;
+	void			*w_data;	/* syncer routine argument */
+	void			(*w_syncer)(struct vfs *, void *);
+} vfs_sync_work_t;
+
 typedef struct vfs {
 	u_int			vfs_flag;	/* flags */
 	xfs_fsid_t		vfs_fsid;	/* file system ID */
 	xfs_fsid_t		*vfs_altfsid;	/* An ID fixed for life of FS */
 	bhv_head_t		vfs_bh;		/* head of vfs behavior chain */
-	struct super_block	*vfs_super;	/* Linux superblock structure */
-	struct task_struct	*vfs_sync_task;	/* xfssyncd process */
-	int 			vfs_sync_seq;	/* xfssyncd generation number */
+	struct super_block	*vfs_super;	/* generic superblock pointer */
+	struct task_struct	*vfs_sync_task;	/* generalised sync thread */
+	vfs_sync_work_t		vfs_sync_work;	/* work item for VFS_SYNC */
+	struct list_head	vfs_sync_list;	/* sync thread work item list */
+	spinlock_t		vfs_sync_lock;	/* work item list lock */
+	int 			vfs_sync_seq;	/* sync thread generation no. */
 	wait_queue_head_t	vfs_wait_single_sync_task;
 	wait_queue_head_t	vfs_wait_sync_task;
 } vfs_t;
@@ -205,4 +216,8 @@ extern void bhv_insert_all_vfsops(struct vfs *);
 extern void bhv_remove_all_vfsops(struct vfs *, int);
 extern void bhv_remove_vfsops(struct vfs *, int);
 
+#define fs_frozen(vfsp)		((vfsp)->vfs_super->s_frozen)
+#define fs_check_frozen(vfsp, level) \
+	vfs_check_frozen(vfsp->vfs_super, level);
+
 #endif	/* __XFS_VFS_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c
index 44ba5e5f4..e8094d24a 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.c
+++ b/fs/xfs/linux-2.6/xfs_vnode.c
@@ -187,6 +187,53 @@ vn_get(
 	return vp;
 }
 
+/*
+ * Revalidate the Linux inode from the vattr.
+ * Note: i_size _not_ updated; we must hold the inode
+ * semaphore when doing that - callers responsibility.
+ */
+void
+vn_revalidate_core(
+	struct vnode	*vp,
+	vattr_t		*vap)
+{
+	struct inode	*inode = LINVFS_GET_IP(vp);
+
+	inode = LINVFS_GET_IP(vp);
+	inode->i_mode	    = VTTOIF(vap->va_type) | vap->va_mode;
+	inode->i_nlink	    = vap->va_nlink;
+	inode->i_uid	    = vap->va_uid;
+	inode->i_gid	    = vap->va_gid;
+	inode->i_blocks	    = vap->va_nblocks;
+	inode->i_mtime	    = vap->va_mtime;
+	inode->i_ctime	    = vap->va_ctime;
+	inode->i_atime	    = vap->va_atime;
+	if (vap->va_xflags & XFS_XFLAG_IMMUTABLE)
+		inode->i_flags |= S_IMMUTABLE;
+	else
+		inode->i_flags &= ~S_IMMUTABLE;
+	if (vap->va_xflags & XFS_XFLAG_IUNLINK)
+		inode->i_flags |= S_IUNLINK;
+	else
+		inode->i_flags &= ~S_IUNLINK;
+	if (vap->va_xflags & XFS_XFLAG_BARRIER)
+		inode->i_flags |= S_BARRIER;
+	else
+		inode->i_flags &= ~S_BARRIER;
+	if (vap->va_xflags & XFS_XFLAG_APPEND)
+		inode->i_flags |= S_APPEND;
+	else
+		inode->i_flags &= ~S_APPEND;
+	if (vap->va_xflags & XFS_XFLAG_SYNC)
+		inode->i_flags |= S_SYNC;
+	else
+		inode->i_flags &= ~S_SYNC;
+	if (vap->va_xflags & XFS_XFLAG_NOATIME)
+		inode->i_flags |= S_NOATIME;
+	else
+		inode->i_flags &= ~S_NOATIME;
+}
+
 /*
  * Revalidate the Linux inode from the vnode.
  */
@@ -194,7 +241,6 @@ int
 vn_revalidate(
 	struct vnode	*vp)
 {
-	struct inode	*inode;
 	vattr_t		va;
 	int		error;
 
@@ -204,39 +250,7 @@ vn_revalidate(
 	va.va_mask = XFS_AT_STAT|XFS_AT_XFLAGS;
 	VOP_GETATTR(vp, &va, 0, NULL, error);
 	if (!error) {
-		inode = LINVFS_GET_IP(vp);
-		inode->i_mode	    = VTTOIF(va.va_type) | va.va_mode;
-		inode->i_nlink	    = va.va_nlink;
-		inode->i_uid	    = va.va_uid;
-		inode->i_gid	    = va.va_gid;
-		inode->i_blocks	    = va.va_nblocks;
-		inode->i_mtime	    = va.va_mtime;
-		inode->i_ctime	    = va.va_ctime;
-		inode->i_atime	    = va.va_atime;
-		if (va.va_xflags & XFS_XFLAG_IMMUTABLE)
-			inode->i_flags |= S_IMMUTABLE;
-		else
-			inode->i_flags &= ~S_IMMUTABLE;
-		if (va.va_xflags & XFS_XFLAG_IUNLINK)
-			inode->i_flags |= S_IUNLINK;
-		else
-			inode->i_flags &= ~S_IUNLINK;
-		if (va.va_xflags & XFS_XFLAG_BARRIER)
-			inode->i_flags |= S_BARRIER;
-		else
-			inode->i_flags &= ~S_BARRIER;
-		if (va.va_xflags & XFS_XFLAG_APPEND)
-			inode->i_flags |= S_APPEND;
-		else
-			inode->i_flags &= ~S_APPEND;
-		if (va.va_xflags & XFS_XFLAG_SYNC)
-			inode->i_flags |= S_SYNC;
-		else
-			inode->i_flags &= ~S_SYNC;
-		if (va.va_xflags & XFS_XFLAG_NOATIME)
-			inode->i_flags |= S_NOATIME;
-		else
-			inode->i_flags &= ~S_NOATIME;
+		vn_revalidate_core(vp, &va);
 		VUNMODIFY(vp);
 	}
 	return -error;
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index af0b65fe5..3466465fa 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -194,7 +194,7 @@ typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *,
 				loff_t *, int, size_t, read_actor_t,
 				void *, struct cred *);
 typedef int	(*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *,
-				int, unsigned int, unsigned long);
+				int, unsigned int, void __user *);
 typedef int	(*vop_getattr_t)(bhv_desc_t *, struct vattr *, int,
 				struct cred *);
 typedef int	(*vop_setattr_t)(bhv_desc_t *, struct vattr *, int,
@@ -532,6 +532,7 @@ typedef struct vnode_map {
 extern void	vn_purge(struct vnode *, vmap_t *);
 extern vnode_t	*vn_get(struct vnode *, vmap_t *);
 extern int	vn_revalidate(struct vnode *);
+extern void	vn_revalidate_core(struct vnode *, vattr_t *);
 extern void	vn_remove(struct vnode *);
 
 static inline int vn_count(struct vnode *vp)
@@ -593,6 +594,19 @@ static __inline__ void vn_flagclr(struct vnode *vp, uint flag)
 #define VN_ATIMESET(vp, tvp)	(LINVFS_GET_IP(vp)->i_atime = *(tvp))
 #define VN_CTIMESET(vp, tvp)	(LINVFS_GET_IP(vp)->i_ctime = *(tvp))
 
+/*
+ * Dealing with bad inodes
+ */
+static inline void vn_mark_bad(struct vnode *vp)
+{
+	make_bad_inode(LINVFS_GET_IP(vp));
+}
+
+static inline int VN_BAD(struct vnode *vp)
+{
+	return is_bad_inode(LINVFS_GET_IP(vp));
+}
+
 /*
  * Some useful predicates.
  */
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index d1368c92d..fbfb24c70 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -145,7 +145,7 @@ xfs_qm_dqinit(
 		 dqp->q_res_icount = 0;
 		 dqp->q_res_rtbcount = 0;
 		 dqp->q_pincount = 0;
-		 dqp->q_hash = 0;
+		 dqp->q_hash = NULL;
 		 ASSERT(dqp->dq_flnext == dqp->dq_flprev);
 
 #ifdef XFS_DQUOT_TRACE
@@ -187,9 +187,9 @@ xfs_qm_dqdestroy(
  */
 STATIC void
 xfs_qm_dqinit_core(
-	xfs_dqid_t	 id,
-	uint		 type,
-	xfs_dqblk_t	 *d)
+	xfs_dqid_t	id,
+	uint		type,
+	xfs_dqblk_t	*d)
 {
 	/*
 	 * Caller has zero'd the entire dquot 'chunk' already.
@@ -249,6 +249,36 @@ __xfs_dqtrace_entry(
 #endif
 
 
+/*
+ * If default limits are in force, push them into the dquot now.
+ * We overwrite the dquot limits only if they are zero and this
+ * is not the root dquot.
+ */
+void
+xfs_qm_adjust_dqlimits(
+	xfs_mount_t		*mp,
+	xfs_disk_dquot_t	*d)
+{
+	xfs_quotainfo_t		*q = mp->m_quotainfo;
+
+	ASSERT(!INT_ISZERO(d->d_id, ARCH_CONVERT));
+
+	if (q->qi_bsoftlimit && INT_ISZERO(d->d_blk_softlimit, ARCH_CONVERT))
+		INT_SET(d->d_blk_softlimit, ARCH_CONVERT, q->qi_bsoftlimit);
+	if (q->qi_bhardlimit && INT_ISZERO(d->d_blk_hardlimit, ARCH_CONVERT))
+		INT_SET(d->d_blk_hardlimit, ARCH_CONVERT, q->qi_bhardlimit);
+	if (q->qi_isoftlimit && INT_ISZERO(d->d_ino_softlimit, ARCH_CONVERT))
+		INT_SET(d->d_ino_softlimit, ARCH_CONVERT, q->qi_isoftlimit);
+	if (q->qi_ihardlimit && INT_ISZERO(d->d_ino_hardlimit, ARCH_CONVERT))
+		INT_SET(d->d_ino_hardlimit, ARCH_CONVERT, q->qi_ihardlimit);
+	if (q->qi_rtbsoftlimit &&
+	    INT_ISZERO(d->d_rtb_softlimit, ARCH_CONVERT))
+		INT_SET(d->d_rtb_softlimit, ARCH_CONVERT, q->qi_rtbsoftlimit);
+	if (q->qi_rtbhardlimit &&
+	    INT_ISZERO(d->d_rtb_hardlimit, ARCH_CONVERT))
+		INT_SET(d->d_rtb_hardlimit, ARCH_CONVERT, q->qi_rtbhardlimit);
+}
+
 /*
  * Check the limits and timers of a dquot and start or reset timers
  * if necessary.
@@ -265,53 +295,81 @@ xfs_qm_adjust_dqtimers(
 	xfs_mount_t		*mp,
 	xfs_disk_dquot_t	*d)
 {
-	/*
-	 * The dquot had better be locked. We are modifying it here.
-	 */
-
-	/*
-	 * root's limits are not real limits.
-	 */
-	if (INT_ISZERO(d->d_id, ARCH_CONVERT))
-		return;
+	ASSERT(!INT_ISZERO(d->d_id, ARCH_CONVERT));
 
 #ifdef QUOTADEBUG
 	if (INT_GET(d->d_blk_hardlimit, ARCH_CONVERT))
-		ASSERT(INT_GET(d->d_blk_softlimit, ARCH_CONVERT) <= INT_GET(d->d_blk_hardlimit, ARCH_CONVERT));
+		ASSERT(INT_GET(d->d_blk_softlimit, ARCH_CONVERT) <=
+			INT_GET(d->d_blk_hardlimit, ARCH_CONVERT));
 	if (INT_GET(d->d_ino_hardlimit, ARCH_CONVERT))
-		ASSERT(INT_GET(d->d_ino_softlimit, ARCH_CONVERT) <= INT_GET(d->d_ino_hardlimit, ARCH_CONVERT));
+		ASSERT(INT_GET(d->d_ino_softlimit, ARCH_CONVERT) <=
+			INT_GET(d->d_ino_hardlimit, ARCH_CONVERT));
+	if (INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT))
+		ASSERT(INT_GET(d->d_rtb_softlimit, ARCH_CONVERT) <=
+			INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT));
 #endif
 	if (INT_ISZERO(d->d_btimer, ARCH_CONVERT)) {
 		if ((INT_GET(d->d_blk_softlimit, ARCH_CONVERT) &&
-		    (INT_GET(d->d_bcount, ARCH_CONVERT) >= INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) ||
+		    (INT_GET(d->d_bcount, ARCH_CONVERT) >=
+				INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) ||
 		    (INT_GET(d->d_blk_hardlimit, ARCH_CONVERT) &&
-		    (INT_GET(d->d_bcount, ARCH_CONVERT) >= INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
-			INT_SET(d->d_btimer, ARCH_CONVERT, get_seconds() + XFS_QI_BTIMELIMIT(mp));
+		    (INT_GET(d->d_bcount, ARCH_CONVERT) >=
+				INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
+			INT_SET(d->d_btimer, ARCH_CONVERT,
+				get_seconds() + XFS_QI_BTIMELIMIT(mp));
 		}
 	} else {
 		if ((INT_ISZERO(d->d_blk_softlimit, ARCH_CONVERT) ||
-		    (INT_GET(d->d_bcount, ARCH_CONVERT) < INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) &&
+		    (INT_GET(d->d_bcount, ARCH_CONVERT) <
+				INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) &&
 		    (INT_ISZERO(d->d_blk_hardlimit, ARCH_CONVERT) ||
-		    (INT_GET(d->d_bcount, ARCH_CONVERT) < INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
+		    (INT_GET(d->d_bcount, ARCH_CONVERT) <
+				INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
 			INT_ZERO(d->d_btimer, ARCH_CONVERT);
 		}
 	}
 
 	if (INT_ISZERO(d->d_itimer, ARCH_CONVERT)) {
 		if ((INT_GET(d->d_ino_softlimit, ARCH_CONVERT) &&
-		    (INT_GET(d->d_icount, ARCH_CONVERT) >= INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) ||
+		    (INT_GET(d->d_icount, ARCH_CONVERT) >=
+				INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) ||
 		    (INT_GET(d->d_ino_hardlimit, ARCH_CONVERT) &&
-		    (INT_GET(d->d_icount, ARCH_CONVERT) >= INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
-			INT_SET(d->d_itimer, ARCH_CONVERT, get_seconds() + XFS_QI_ITIMELIMIT(mp));
+		    (INT_GET(d->d_icount, ARCH_CONVERT) >=
+				INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
+			INT_SET(d->d_itimer, ARCH_CONVERT,
+				get_seconds() + XFS_QI_ITIMELIMIT(mp));
 		}
 	} else {
 		if ((INT_ISZERO(d->d_ino_softlimit, ARCH_CONVERT) ||
-		    (INT_GET(d->d_icount, ARCH_CONVERT) < INT_GET(d->d_ino_softlimit, ARCH_CONVERT)))  &&
+		    (INT_GET(d->d_icount, ARCH_CONVERT) <
+				INT_GET(d->d_ino_softlimit, ARCH_CONVERT)))  &&
 		    (INT_ISZERO(d->d_ino_hardlimit, ARCH_CONVERT) ||
-		    (INT_GET(d->d_icount, ARCH_CONVERT) < INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
+		    (INT_GET(d->d_icount, ARCH_CONVERT) <
+				INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
 			INT_ZERO(d->d_itimer, ARCH_CONVERT);
 		}
 	}
+
+	if (INT_ISZERO(d->d_rtbtimer, ARCH_CONVERT)) {
+		if ((INT_GET(d->d_rtb_softlimit, ARCH_CONVERT) &&
+		    (INT_GET(d->d_rtbcount, ARCH_CONVERT) >=
+				INT_GET(d->d_rtb_softlimit, ARCH_CONVERT))) ||
+		    (INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT) &&
+		    (INT_GET(d->d_rtbcount, ARCH_CONVERT) >=
+				INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT)))) {
+			INT_SET(d->d_rtbtimer, ARCH_CONVERT,
+				get_seconds() + XFS_QI_RTBTIMELIMIT(mp));
+		}
+	} else {
+		if ((INT_ISZERO(d->d_rtb_softlimit, ARCH_CONVERT) ||
+		    (INT_GET(d->d_rtbcount, ARCH_CONVERT) <
+				INT_GET(d->d_rtb_softlimit, ARCH_CONVERT))) &&
+		    (INT_ISZERO(d->d_rtb_hardlimit, ARCH_CONVERT) ||
+		    (INT_GET(d->d_rtbcount, ARCH_CONVERT) <
+				INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT)))) {
+			INT_ZERO(d->d_rtbtimer, ARCH_CONVERT);
+		}
+	}
 }
 
 /*
diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h
index 9964605ac..0c3fe3175 100644
--- a/fs/xfs/quota/xfs_dquot.h
+++ b/fs/xfs/quota/xfs_dquot.h
@@ -209,6 +209,8 @@ extern int		xfs_qm_dqflock_nowait(xfs_dquot_t *);
 extern void		xfs_qm_dqflock_pushbuf_wait(xfs_dquot_t *dqp);
 extern void		xfs_qm_adjust_dqtimers(xfs_mount_t *,
 					xfs_disk_dquot_t *);
+extern void		xfs_qm_adjust_dqlimits(xfs_mount_t *,
+					xfs_disk_dquot_t *);
 extern int		xfs_qm_dqwarn(xfs_disk_dquot_t *, uint);
 extern int		xfs_qm_dqget(xfs_mount_t *, xfs_inode_t *,
 					xfs_dqid_t, uint, uint, xfs_dquot_t **);
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 0088d7de4..918b7e874 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -229,11 +229,8 @@ xfs_qm_hold_quotafs_ref(
 	 */
 	XFS_QM_LOCK(xfs_Gqm);
 
-	if (xfs_Gqm == NULL) {
-		if ((xfs_Gqm = xfs_Gqm_init()) == NULL) {
-			return (XFS_ERROR(EINVAL));
-		}
-	}
+	if (xfs_Gqm == NULL)
+		xfs_Gqm = xfs_Gqm_init();
 	/*
 	 * We can keep a list of all filesystems with quotas mounted for
 	 * debugging and statistical purposes, but ...
@@ -1216,22 +1213,46 @@ xfs_qm_init_quotainfo(
 			     XFS_QMOPT_DQSUSER|XFS_QMOPT_DOWARN,
 			     &dqp);
 	if (! error) {
+		xfs_disk_dquot_t	*ddqp = &dqp->q_core;
+
 		/*
 		 * The warnings and timers set the grace period given to
 		 * a user or group before he or she can not perform any
 		 * more writing. If it is zero, a default is used.
 		 */
-		qinf->qi_btimelimit = INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT) ?
-			INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT) : XFS_QM_BTIMELIMIT;
-		qinf->qi_itimelimit = INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT) ?
-			INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT) : XFS_QM_ITIMELIMIT;
-		qinf->qi_rtbtimelimit = INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT) ?
-			INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT) : XFS_QM_RTBTIMELIMIT;
-		qinf->qi_bwarnlimit = INT_GET(dqp->q_core.d_bwarns, ARCH_CONVERT) ?
-			INT_GET(dqp->q_core.d_bwarns, ARCH_CONVERT) : XFS_QM_BWARNLIMIT;
-		qinf->qi_iwarnlimit = INT_GET(dqp->q_core.d_iwarns, ARCH_CONVERT) ?
-			INT_GET(dqp->q_core.d_iwarns, ARCH_CONVERT) : XFS_QM_IWARNLIMIT;
-
+		qinf->qi_btimelimit =
+				INT_GET(ddqp->d_btimer, ARCH_CONVERT) ?
+				INT_GET(ddqp->d_btimer, ARCH_CONVERT) :
+				XFS_QM_BTIMELIMIT;
+		qinf->qi_itimelimit =
+				INT_GET(ddqp->d_itimer, ARCH_CONVERT) ?
+				INT_GET(ddqp->d_itimer, ARCH_CONVERT) :
+				XFS_QM_ITIMELIMIT;
+		qinf->qi_rtbtimelimit =
+				INT_GET(ddqp->d_rtbtimer, ARCH_CONVERT) ?
+				INT_GET(ddqp->d_rtbtimer, ARCH_CONVERT) :
+				XFS_QM_RTBTIMELIMIT;
+		qinf->qi_bwarnlimit =
+				INT_GET(ddqp->d_bwarns, ARCH_CONVERT) ?
+				INT_GET(ddqp->d_bwarns, ARCH_CONVERT) :
+				XFS_QM_BWARNLIMIT;
+		qinf->qi_iwarnlimit =
+				INT_GET(ddqp->d_iwarns, ARCH_CONVERT) ?
+				INT_GET(ddqp->d_iwarns, ARCH_CONVERT) :
+				XFS_QM_IWARNLIMIT;
+		qinf->qi_bhardlimit =
+				INT_GET(ddqp->d_blk_hardlimit, ARCH_CONVERT);
+		qinf->qi_bsoftlimit =
+				INT_GET(ddqp->d_blk_softlimit, ARCH_CONVERT);
+		qinf->qi_ihardlimit =
+				INT_GET(ddqp->d_ino_hardlimit, ARCH_CONVERT);
+		qinf->qi_isoftlimit =
+				INT_GET(ddqp->d_ino_softlimit, ARCH_CONVERT);
+		qinf->qi_rtbhardlimit =
+				INT_GET(ddqp->d_rtb_hardlimit, ARCH_CONVERT);
+		qinf->qi_rtbsoftlimit =
+				INT_GET(ddqp->d_rtb_softlimit, ARCH_CONVERT);
+ 
 		/*
 		 * We sent the XFS_QMOPT_DQSUSER flag to dqget because
 		 * we don't want this dquot cached. We haven't done a
@@ -1691,10 +1712,12 @@ xfs_qm_quotacheck_dqadjust(
 	}
 
 	/*
-	 * Adjust the timers since we just changed usages
+	 * Set default limits, adjust timers (since we changed usages)
 	 */
-	if (! XFS_IS_SUSER_DQUOT(dqp))
+	if (! XFS_IS_SUSER_DQUOT(dqp)) {
+		xfs_qm_adjust_dqlimits(dqp->q_mount, &dqp->q_core);
 		xfs_qm_adjust_dqtimers(dqp->q_mount, &dqp->q_core);
+	}
 
 	dqp->dq_flags |= XFS_DQ_DIRTY;
 }
@@ -1735,7 +1758,7 @@ STATIC int
 xfs_qm_dqusage_adjust(
 	xfs_mount_t	*mp,		/* mount point for filesystem */
 	xfs_ino_t	ino,		/* inode number to get data for */
-	void		*buffer,	/* not used */
+	void		__user *buffer,	/* not used */
 	int		ubsize,		/* not used */
 	void		*private_data,	/* not used */
 	xfs_daddr_t	bno,		/* starting block of inode cluster */
diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h
index 4924a1116..f539e9226 100644
--- a/fs/xfs/quota/xfs_qm.h
+++ b/fs/xfs/quota/xfs_qm.h
@@ -136,9 +136,14 @@ typedef struct xfs_quotainfo {
 	xfs_qwarncnt_t	 qi_bwarnlimit;	 /* limit for num warnings */
 	xfs_qwarncnt_t	 qi_iwarnlimit;	 /* limit for num warnings */
 	mutex_t		 qi_quotaofflock;/* to serialize quotaoff */
-	/* Some useful precalculated constants */
 	xfs_filblks_t	 qi_dqchunklen;	 /* # BBs in a chunk of dqs */
 	uint		 qi_dqperchunk;	 /* # ondisk dqs in above chunk */
+	xfs_qcnt_t	 qi_bhardlimit;	 /* default data blk hard limit */
+	xfs_qcnt_t	 qi_bsoftlimit;	 /* default data blk soft limit */
+	xfs_qcnt_t	 qi_ihardlimit;	 /* default inode count hard limit */
+	xfs_qcnt_t	 qi_isoftlimit;	 /* default inode count soft limit */
+	xfs_qcnt_t	 qi_rtbhardlimit;/* default realtime blk hard limit */
+	xfs_qcnt_t	 qi_rtbsoftlimit;/* default realtime blk soft limit */
 } xfs_quotainfo_t;
 
 
@@ -187,7 +192,6 @@ extern int		xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t);
 extern int		xfs_qm_sync(xfs_mount_t *, short);
 
 /* dquot stuff */
-extern void		xfs_qm_dqunlink(xfs_dquot_t *);
 extern boolean_t	xfs_qm_dqalloc_incore(xfs_dquot_t **);
 extern int		xfs_qm_dqattach(xfs_inode_t *, uint);
 extern void		xfs_qm_dqdetach(xfs_inode_t *);
diff --git a/fs/xfs/quota/xfs_qm_stats.c b/fs/xfs/quota/xfs_qm_stats.c
index d3553ea4a..29978e037 100644
--- a/fs/xfs/quota/xfs_qm_stats.c
+++ b/fs/xfs/quota/xfs_qm_stats.c
@@ -137,8 +137,8 @@ xfs_qm_read_stats(
 void
 xfs_qm_init_procfs(void)
 {
-	create_proc_read_entry("fs/xfs/xqmstat", 0, 0, xfs_qm_read_stats, NULL);
-	create_proc_read_entry("fs/xfs/xqm", 0, 0, xfs_qm_read_xfsquota, NULL);
+	create_proc_read_entry("fs/xfs/xqmstat", 0, NULL, xfs_qm_read_stats, NULL);
+	create_proc_read_entry("fs/xfs/xqm", 0, NULL, xfs_qm_read_xfsquota, NULL);
 }
 
 void
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index 5a0f1ad94..b722dad83 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -648,8 +648,11 @@ xfs_qm_scall_setqlim(
 	if (hard == 0 || hard >= soft) {
 		INT_SET(ddq->d_blk_hardlimit, ARCH_CONVERT, hard);
 		INT_SET(ddq->d_blk_softlimit, ARCH_CONVERT, soft);
-	}
-	else {
+		if (id == 0) {
+			mp->m_quotainfo->qi_bhardlimit = hard;
+			mp->m_quotainfo->qi_bsoftlimit = soft;
+		}
+	} else {
 		qdprintk("blkhard %Ld < blksoft %Ld\n", hard, soft);
 	}
 	hard = (newlim->d_fieldmask & FS_DQ_RTBHARD) ?
@@ -661,40 +664,49 @@ xfs_qm_scall_setqlim(
 	if (hard == 0 || hard >= soft) {
 		INT_SET(ddq->d_rtb_hardlimit, ARCH_CONVERT, hard);
 		INT_SET(ddq->d_rtb_softlimit, ARCH_CONVERT, soft);
-	}
-	else
+		if (id == 0) {
+			mp->m_quotainfo->qi_rtbhardlimit = hard;
+			mp->m_quotainfo->qi_rtbsoftlimit = soft;
+		}
+	} else {
 		qdprintk("rtbhard %Ld < rtbsoft %Ld\n", hard, soft);
+	}
 
 	hard = (newlim->d_fieldmask & FS_DQ_IHARD) ?
 		(xfs_qcnt_t) newlim->d_ino_hardlimit :
-		INT_GET(ddq->d_ino_hardlimit, ARCH_CONVERT);
+			INT_GET(ddq->d_ino_hardlimit, ARCH_CONVERT);
 	soft = (newlim->d_fieldmask & FS_DQ_ISOFT) ?
 		(xfs_qcnt_t) newlim->d_ino_softlimit :
-		INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT);
+			INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT);
 	if (hard == 0 || hard >= soft) {
 		INT_SET(ddq->d_ino_hardlimit, ARCH_CONVERT, hard);
 		INT_SET(ddq->d_ino_softlimit, ARCH_CONVERT, soft);
-	}
-	else
+		if (id == 0) {
+			mp->m_quotainfo->qi_ihardlimit = hard;
+			mp->m_quotainfo->qi_isoftlimit = soft;
+		}
+	} else {
 		qdprintk("ihard %Ld < isoft %Ld\n", hard, soft);
+	}
 
 	if (id == 0) {
 		/*
 		 * Timelimits for the super user set the relative time
 		 * the other users can be over quota for this file system.
-		 * If it is zero a default is used.
+		 * If it is zero a default is used.  Ditto for the default
+		 * soft and hard limit values (already done, above).
 		 */
 		if (newlim->d_fieldmask & FS_DQ_BTIMER) {
 			mp->m_quotainfo->qi_btimelimit = newlim->d_btimer;
-			INT_SET(dqp->q_core.d_btimer, ARCH_CONVERT, newlim->d_btimer);
+			INT_SET(ddq->d_btimer, ARCH_CONVERT, newlim->d_btimer);
 		}
 		if (newlim->d_fieldmask & FS_DQ_ITIMER) {
 			mp->m_quotainfo->qi_itimelimit = newlim->d_itimer;
-			INT_SET(dqp->q_core.d_itimer, ARCH_CONVERT, newlim->d_itimer);
+			INT_SET(ddq->d_itimer, ARCH_CONVERT, newlim->d_itimer);
 		}
 		if (newlim->d_fieldmask & FS_DQ_RTBTIMER) {
 			mp->m_quotainfo->qi_rtbtimelimit = newlim->d_rtbtimer;
-			INT_SET(dqp->q_core.d_rtbtimer, ARCH_CONVERT, newlim->d_rtbtimer);
+			INT_SET(ddq->d_rtbtimer, ARCH_CONVERT, newlim->d_rtbtimer);
 		}
 	} else /* if (XFS_IS_QUOTA_ENFORCED(mp)) */ {
 		/*
@@ -1114,7 +1126,7 @@ mutex_t	      qcheck_lock;
 	  cmn_err(CE_DEBUG, "%s (#%d)", title, (int) (l)->qh_nelems); \
 	  for (dqp = (xfs_dqtest_t *)(l)->qh_next; dqp != NULL; \
 	       dqp = (xfs_dqtest_t *)dqp->NXT) { \
-		cmn_err(CE_DEBUG, "  %d\. \"%d (%s)\"  bcnt = %d, icnt = %d", \
+		cmn_err(CE_DEBUG, "  %d. \"%d (%s)\"  bcnt = %d, icnt = %d", \
 			 ++i, dqp->d_id, DQFLAGTO_TYPESTR(dqp),	     \
 			 dqp->d_bcount, dqp->d_icount); } \
 }
@@ -1299,7 +1311,7 @@ STATIC int
 xfs_qm_internalqcheck_adjust(
 	xfs_mount_t	*mp,		/* mount point for filesystem */
 	xfs_ino_t	ino,		/* inode number to get data for */
-	void		*buffer,	/* not used */
+	void		__user *buffer,	/* not used */
 	int		ubsize,		/* not used */
 	void		*private_data,	/* not used */
 	xfs_daddr_t	bno,		/* starting block of inode cluster */
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c
index 416cc95b4..25079b572 100644
--- a/fs/xfs/quota/xfs_trans_dquot.c
+++ b/fs/xfs/quota/xfs_trans_dquot.c
@@ -452,9 +452,13 @@ xfs_trans_apply_dquot_deltas(
 				INT_MOD(d->d_rtbcount, ARCH_CONVERT, (xfs_qcnt_t)totalrtbdelta);
 
 			/*
+			 * Get any default limits in use.
 			 * Start/reset the timer(s) if needed.
 			 */
-			xfs_qm_adjust_dqtimers(tp->t_mountp, d);
+			if (!INT_ISZERO(d->d_id, ARCH_CONVERT)) {
+				xfs_qm_adjust_dqlimits(tp->t_mountp, d);
+				xfs_qm_adjust_dqtimers(tp->t_mountp, d);
+			}
 
 			dqp->dq_flags |= XFS_DQ_DIRTY;
 			/*
@@ -625,6 +629,7 @@ xfs_trans_unreserve_and_mod_dquots(
 STATIC int
 xfs_trans_dqresv(
 	xfs_trans_t	*tp,
+	xfs_mount_t	*mp,
 	xfs_dquot_t	*dqp,
 	long		nblks,
 	long		ninos,
@@ -635,6 +640,7 @@ xfs_trans_dqresv(
 	xfs_qcnt_t	softlimit;
 	time_t		btimer;
 	xfs_qcnt_t	*resbcountp;
+	xfs_quotainfo_t	*q = mp->m_quotainfo;
 
 	if (! (flags & XFS_QMOPT_DQLOCK)) {
 		xfs_dqlock(dqp);
@@ -642,13 +648,21 @@ xfs_trans_dqresv(
 	ASSERT(XFS_DQ_IS_LOCKED(dqp));
 	if (flags & XFS_TRANS_DQ_RES_BLKS) {
 		hardlimit = INT_GET(dqp->q_core.d_blk_hardlimit, ARCH_CONVERT);
+		if (!hardlimit)
+			hardlimit = q->qi_bhardlimit;
 		softlimit = INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT);
+		if (!softlimit)
+			softlimit = q->qi_bsoftlimit;
 		btimer = INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT);
 		resbcountp = &dqp->q_res_bcount;
 	} else {
 		ASSERT(flags & XFS_TRANS_DQ_RES_RTBLKS);
 		hardlimit = INT_GET(dqp->q_core.d_rtb_hardlimit, ARCH_CONVERT);
+		if (!hardlimit)
+			hardlimit = q->qi_rtbhardlimit;
 		softlimit = INT_GET(dqp->q_core.d_rtb_softlimit, ARCH_CONVERT);
+		if (!softlimit)
+			softlimit = q->qi_rtbsoftlimit;
 		btimer = INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT);
 		resbcountp = &dqp->q_res_rtbcount;
 	}
@@ -689,14 +703,18 @@ xfs_trans_dqresv(
 			}
 		}
 		if (ninos > 0) {
-			if (INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT) > 0ULL &&
-			    INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >=
-			    INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT)) {
+			hardlimit = INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT);
+			if (!hardlimit)
+				hardlimit = q->qi_ihardlimit;
+			softlimit = INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT);
+			if (!softlimit)
+				softlimit = q->qi_isoftlimit;
+			if (hardlimit > 0ULL &&
+			    INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= hardlimit) {
 				error = EDQUOT;
 				goto error_return;
-			} else if (INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT) > 0ULL &&
-				   INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >=
-				   INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT)) {
+			} else if (softlimit > 0ULL &&
+				   INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= softlimit) {
 				/*
 				 * If timer or warnings has expired,
 				 * return EDQUOT
@@ -786,19 +804,20 @@ xfs_trans_reserve_quota_bydquots(
 	resvd = 0;
 
 	if (udqp) {
-		if (xfs_trans_dqresv(tp, udqp, nblks, ninos, flags))
+		if (xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, flags))
 			return (EDQUOT);
 		resvd = 1;
 	}
 
 	if (gdqp) {
-		if (xfs_trans_dqresv(tp, gdqp, nblks, ninos, flags)) {
+		if (xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags)) {
 			/*
 			 * can't do it, so backout previous reservation
 			 */
 			if (resvd) {
-				xfs_trans_dqresv(tp, udqp,  -nblks, -ninos,
-						 flags);
+				flags |= XFS_QMOPT_FORCE_RES;
+				xfs_trans_dqresv(tp, mp, udqp,
+						 -nblks, -ninos, flags);
 			}
 			return (EDQUOT);
 		}
diff --git a/fs/xfs/support/ktrace.c b/fs/xfs/support/ktrace.c
index 852a92dc0..3dae14c8c 100644
--- a/fs/xfs/support/ktrace.c
+++ b/fs/xfs/support/ktrace.c
@@ -30,14 +30,7 @@
  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
  */
 
-#include <linux/types.h>
-#include <linux/slab.h>
-
-#include <xfs_types.h>
-#include "kmem.h"
-#include "spin.h"
-#include "debug.h"
-#include "ktrace.h"
+#include <xfs.h>
 
 static kmem_zone_t *ktrace_hdr_zone;
 static kmem_zone_t *ktrace_ent_zone;
diff --git a/fs/xfs/support/move.c b/fs/xfs/support/move.c
index 9f3d2ebb1..15b5194f1 100644
--- a/fs/xfs/support/move.c
+++ b/fs/xfs/support/move.c
@@ -30,13 +30,7 @@
  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
  */
 
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <asm/uaccess.h>
-
-#include <xfs_types.h>
-#include "debug.h"
-#include "move.h"
+#include <xfs.h>
 
 /* Read from kernel buffer at src to user/kernel buffer defined
  * by the uio structure. Advance the pointer in the uio struct
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h
index 35e56b7f0..0363eb46d 100644
--- a/fs/xfs/xfs_acl.h
+++ b/fs/xfs/xfs_acl.h
@@ -74,8 +74,6 @@ extern struct kmem_zone *xfs_acl_zone;
 
 extern int xfs_acl_inherit(struct vnode *, struct vattr *, xfs_acl_t *);
 extern int xfs_acl_iaccess(struct xfs_inode *, mode_t, cred_t *);
-extern int xfs_acl_get(struct vnode *, xfs_acl_t *, xfs_acl_t *);
-extern int xfs_acl_set(struct vnode *, xfs_acl_t *, xfs_acl_t *);
 extern int xfs_acl_vtoacl(struct vnode *, xfs_acl_t *, xfs_acl_t *);
 extern int xfs_acl_vhasacl_access(struct vnode *);
 extern int xfs_acl_vhasacl_default(struct vnode *);
@@ -95,7 +93,7 @@ extern int xfs_acl_vremove(struct vnode *vp, int);
 #define _ACL_XFS_IACCESS(i,m,c) (XFS_IFORK_Q(i) ? xfs_acl_iaccess(i,m,c) : -1)
 
 #define _ACL_ALLOC(a)		((a) = kmem_zone_alloc(xfs_acl_zone, KM_SLEEP))
-#define _ACL_FREE(a)		((a)? kmem_zone_free(xfs_acl_zone, (a)) : 0)
+#define _ACL_FREE(a)		((a)? kmem_zone_free(xfs_acl_zone, (a)):(void)0)
 
 #else
 #define xfs_acl_zone_init(zone,name)
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 74cad985b..02337c2a4 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -665,7 +665,7 @@ xfs_alloc_ag_vextent_exact(
 	 * Allocate/initialize a cursor for the by-number freespace btree.
 	 */
 	bno_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-		args->agno, XFS_BTNUM_BNO, 0, 0);
+		args->agno, XFS_BTNUM_BNO, NULL, 0);
 	/*
 	 * Lookup bno and minlen in the btree (minlen is irrelevant, really).
 	 * Look for the closest free block <= bno, it must contain bno
@@ -721,7 +721,7 @@ xfs_alloc_ag_vextent_exact(
 	 * Allocate/initialize a cursor for the by-size btree.
 	 */
 	cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-		args->agno, XFS_BTNUM_CNT, 0, 0);
+		args->agno, XFS_BTNUM_CNT, NULL, 0);
 	ASSERT(args->agbno + args->len <=
 		INT_GET(XFS_BUF_TO_AGF(args->agbp)->agf_length,
 			ARCH_CONVERT));
@@ -788,7 +788,7 @@ xfs_alloc_ag_vextent_near(
 	 * Get a cursor for the by-size btree.
 	 */
 	cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-		args->agno, XFS_BTNUM_CNT, 0, 0);
+		args->agno, XFS_BTNUM_CNT, NULL, 0);
 	ltlen = 0;
 	bno_cur_lt = bno_cur_gt = NULL;
 	/*
@@ -916,7 +916,7 @@ xfs_alloc_ag_vextent_near(
 		 * Set up a cursor for the by-bno tree.
 		 */
 		bno_cur_lt = xfs_btree_init_cursor(args->mp, args->tp,
-			args->agbp, args->agno, XFS_BTNUM_BNO, 0, 0);
+			args->agbp, args->agno, XFS_BTNUM_BNO, NULL, 0);
 		/*
 		 * Fix up the btree entries.
 		 */
@@ -944,7 +944,7 @@ xfs_alloc_ag_vextent_near(
 	 * Allocate and initialize the cursor for the leftward search.
 	 */
 	bno_cur_lt = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-		args->agno, XFS_BTNUM_BNO, 0, 0);
+		args->agno, XFS_BTNUM_BNO, NULL, 0);
 	/*
 	 * Lookup <= bno to find the leftward search's starting point.
 	 */
@@ -956,7 +956,7 @@ xfs_alloc_ag_vextent_near(
 		 * search.
 		 */
 		bno_cur_gt = bno_cur_lt;
-		bno_cur_lt = 0;
+		bno_cur_lt = NULL;
 	}
 	/*
 	 * Found something.  Duplicate the cursor for the rightward search.
@@ -1301,7 +1301,7 @@ xfs_alloc_ag_vextent_size(
 	 * Allocate and initialize a cursor for the by-size btree.
 	 */
 	cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-		args->agno, XFS_BTNUM_CNT, 0, 0);
+		args->agno, XFS_BTNUM_CNT, NULL, 0);
 	bno_cur = NULL;
 	/*
 	 * Look for an entry >= maxlen+alignment-1 blocks.
@@ -1406,7 +1406,7 @@ xfs_alloc_ag_vextent_size(
 	 * Allocate and initialize a cursor for the by-block tree.
 	 */
 	bno_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp,
-		args->agno, XFS_BTNUM_BNO, 0, 0);
+		args->agno, XFS_BTNUM_BNO, NULL, 0);
 	if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen,
 			rbno, rlen, XFSA_FIXUP_CNT_OK)))
 		goto error0;
@@ -1553,7 +1553,7 @@ xfs_free_ag_extent(
 	/*
 	 * Allocate and initialize a cursor for the by-block btree.
 	 */
-	bno_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_BNO, 0,
+	bno_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_BNO, NULL,
 		0);
 	cnt_cur = NULL;
 	/*
@@ -1613,7 +1613,7 @@ xfs_free_ag_extent(
 	/*
 	 * Now allocate and initialize a cursor for the by-size tree.
 	 */
-	cnt_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_CNT, 0,
+	cnt_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_CNT, NULL,
 		0);
 	/*
 	 * Have both left and right contiguous neighbors.
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c
index 55c405cc5..6b5de3a28 100644
--- a/fs/xfs/xfs_alloc_btree.c
+++ b/fs/xfs/xfs_alloc_btree.c
@@ -263,7 +263,7 @@ xfs_alloc_delrec(
 			/*
 			 * Update the cursor so there's one fewer level.
 			 */
-			xfs_btree_setbuf(cur, level, 0);
+			xfs_btree_setbuf(cur, level, NULL);
 			cur->bc_nlevels--;
 		} else if (level > 0 &&
 			   (error = xfs_alloc_decrement(cur, level, &i)))
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index f1ccb5890..6cd3b5846 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -104,7 +104,6 @@ STATIC int xfs_attr_rmtval_set(xfs_da_args_t *args);
 STATIC int xfs_attr_rmtval_remove(xfs_da_args_t *args);
 
 #define ATTR_RMTVALUE_MAPSIZE	1	/* # of map entries at once */
-#define ATTR_RMTVALUE_TRANSBLKS	8	/* max # of blks in a transaction */
 
 #if defined(XFS_ATTR_TRACE)
 ktrace_t *xfs_attr_trace_buf;
@@ -122,22 +121,14 @@ xfs_attr_fetch(xfs_inode_t *ip, char *name, int namelen,
 	xfs_da_args_t   args;
 	int             error;
 
-	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
-		return(EIO);
-
 	if ((XFS_IFORK_Q(ip) == 0) ||
 	    (ip->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
 	     ip->i_d.di_anextents == 0))
 		return(ENOATTR);
 
-	if (!(flags & ATTR_KERNACCESS)) {
-		xfs_ilock(ip, XFS_ILOCK_SHARED);
-
-		if (!(flags & ATTR_SECURE) &&
-		    ((error = xfs_iaccess(ip, S_IRUSR, cred)))) {
-			xfs_iunlock(ip, XFS_ILOCK_SHARED);
+	if (!(flags & (ATTR_KERNACCESS|ATTR_SECURE))) {
+		if ((error = xfs_iaccess(ip, S_IRUSR, cred)))
 			return(XFS_ERROR(error));
-		}
 	}
 
 	/*
@@ -168,9 +159,6 @@ xfs_attr_fetch(xfs_inode_t *ip, char *name, int namelen,
 		error = xfs_attr_node_get(&args);
 	}
 
-	if (!(flags & ATTR_KERNACCESS))
-		xfs_iunlock(ip, XFS_ILOCK_SHARED);
-
 	/*
 	 * Return the number of bytes in the value to the caller.
 	 */
@@ -186,7 +174,7 @@ xfs_attr_get(bhv_desc_t *bdp, char *name, char *value, int *valuelenp,
 	     int flags, struct cred *cred)
 {
 	xfs_inode_t	*ip = XFS_BHVTOI(bdp);
-	int		namelen;
+	int		error, namelen;
 
 	XFS_STATS_INC(xs_attr_get);
 
@@ -196,7 +184,13 @@ xfs_attr_get(bhv_desc_t *bdp, char *name, char *value, int *valuelenp,
 	if (namelen >= MAXNAMELEN)
 		return(EFAULT);		/* match IRIX behaviour */
 
-	return xfs_attr_fetch(ip, name, namelen, value, valuelenp, flags, cred);
+	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+		return(EIO);
+
+	xfs_ilock(ip, XFS_ILOCK_SHARED);
+	error = xfs_attr_fetch(ip, name, namelen, value, valuelenp, flags, cred);
+	xfs_iunlock(ip, XFS_ILOCK_SHARED);
+	return(error);
 }
 
 /*ARGSUSED*/
@@ -719,16 +713,15 @@ xfs_attr_inactive(xfs_inode_t *dp)
 	mp = dp->i_mount;
 	ASSERT(! XFS_NOT_DQATTACHED(mp, dp));
 
-	/* XXXsup - why on earth are we taking ILOCK_EXCL here??? */
-	xfs_ilock(dp, XFS_ILOCK_EXCL);
+	xfs_ilock(dp, XFS_ILOCK_SHARED);
 	if ((XFS_IFORK_Q(dp) == 0) ||
 	    (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) ||
 	    (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
 	     dp->i_d.di_anextents == 0)) {
-		xfs_iunlock(dp, XFS_ILOCK_EXCL);
+		xfs_iunlock(dp, XFS_ILOCK_SHARED);
 		return(0);
 	}
-	xfs_iunlock(dp, XFS_ILOCK_EXCL);
+	xfs_iunlock(dp, XFS_ILOCK_SHARED);
 
 	/*
 	 * Start our first transaction of the day.
diff --git a/fs/xfs/xfs_attr_leaf.h b/fs/xfs/xfs_attr_leaf.h
index 97bac75c6..b1480e0b3 100644
--- a/fs/xfs/xfs_attr_leaf.h
+++ b/fs/xfs/xfs_attr_leaf.h
@@ -246,7 +246,6 @@ int	xfs_attr_shortform_getvalue(struct xfs_da_args *args);
 int	xfs_attr_shortform_to_leaf(struct xfs_da_args *args);
 int	xfs_attr_shortform_remove(struct xfs_da_args *remove);
 int	xfs_attr_shortform_list(struct xfs_attr_list_context *context);
-int	xfs_attr_shortform_replace(struct xfs_da_args *args);
 int	xfs_attr_shortform_allfit(struct xfs_dabuf *bp, struct xfs_inode *dp);
 
 /*
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index d797f406e..4b0738238 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * 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
@@ -203,8 +203,6 @@ STATIC void
 xfs_bmap_check_extents(
 	xfs_inode_t		*ip,		/* incore inode pointer */
 	int			whichfork);	/* data or attr fork */
-#else
-#define	xfs_bmap_check_extents(ip,w)
 #endif
 
 /*
@@ -3429,6 +3427,20 @@ xfs_bmap_do_search_extents(
 	int		high;		/* high index of binary search */
 	int		low;		/* low index of binary search */
 
+	/*
+	 * Initialize the extent entry structure to catch access to
+	 * uninitialized br_startblock field.
+	 */
+	got.br_startoff = 0xffa5a5a5a5a5a5a5LL;
+	got.br_blockcount = 0xa55a5a5a5a5a5a5aLL;
+	got.br_state = XFS_EXT_INVALID;
+
+#if XFS_BIG_BLKNOS
+	got.br_startblock = 0xffffa5a5a5a5a5a5LL;
+#else
+	got.br_startblock = 0xffffa5a5;
+#endif
+
 	if (lastx != NULLEXTNUM && lastx < nextents)
 		ep = base + lastx;
 	else
@@ -3527,6 +3539,8 @@ xfs_bmap_search_extents(
 	xfs_bmbt_rec_t  *base;          /* base of extent list */
 	xfs_extnum_t    lastx;          /* last extent index used */
 	xfs_extnum_t    nextents;       /* extent list size */
+	xfs_bmbt_rec_t  *ep;            /* extent list entry pointer */
+	int		rt;		/* realtime flag    */
 
 	XFS_STATS_INC(xs_look_exlist);
 	ifp = XFS_IFORK_PTR(ip, whichfork);
@@ -3534,8 +3548,18 @@ xfs_bmap_search_extents(
 	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
 	base = &ifp->if_u1.if_extents[0];
 
-	return xfs_bmap_do_search_extents(base, lastx, nextents, bno, eofp,
+	ep = xfs_bmap_do_search_extents(base, lastx, nextents, bno, eofp,
 					  lastxp, gotp, prevp);
+	rt = ip->i_d.di_flags & XFS_DIFLAG_REALTIME;
+	if(!rt && !gotp->br_startblock && (*lastxp != NULLEXTNUM)) {
+                cmn_err(CE_PANIC,"Access to block zero: fs: <%s> inode: %lld "
+			"start_block : %llx start_off : %llx blkcnt : %llx "
+			"extent-state : %x \n",
+			(ip->i_mount)->m_fsname,(long long)ip->i_ino,
+			gotp->br_startblock, gotp->br_startoff,
+			gotp->br_blockcount,gotp->br_state);
+        }
+        return ep;
 }
 
 
@@ -4689,8 +4713,41 @@ xfs_bmapi(
 					}
 					break;
 				}
+
+				/*
+				 * Split changing sb for alen and indlen since
+				 * they could be coming from different places.
+				 */
+				if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) {
+					xfs_extlen_t	extsz;
+					xfs_extlen_t	ralen;
+					if (!(extsz = ip->i_d.di_extsize))
+						extsz = mp->m_sb.sb_rextsize;
+					ralen = roundup(alen, extsz);
+					ralen = ralen / mp->m_sb.sb_rextsize;
+					if (xfs_mod_incore_sb(mp,
+						XFS_SBS_FREXTENTS,
+						-(ralen), rsvd)) {
+						if (XFS_IS_QUOTA_ON(ip->i_mount))
+							XFS_TRANS_UNRESERVE_BLKQUOTA(
+						     		mp, NULL, ip,
+								(long)alen);
+						break;
+					}
+				} else {
+					if (xfs_mod_incore_sb(mp,
+							      XFS_SBS_FDBLOCKS,
+							      -(alen), rsvd)) {
+						if (XFS_IS_QUOTA_ON(ip->i_mount))
+							XFS_TRANS_UNRESERVE_BLKQUOTA(
+								mp, NULL, ip,
+								(long)alen);
+						break;
+					}
+				}
+
 				if (xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
-						-(alen + indlen), rsvd)) {
+						-(indlen), rsvd)) {
 					XFS_TRANS_UNRESERVE_BLKQUOTA(
 						mp, NULL, ip, (long)alen);
 					break;
@@ -5445,7 +5502,7 @@ int						/* error code */
 xfs_getbmap(
 	bhv_desc_t		*bdp,		/* XFS behavior descriptor*/
 	struct getbmap		*bmv,		/* user bmap structure */
-	void			*ap,		/* pointer to user's array */
+	void			__user *ap,	/* pointer to user's array */
 	int			interface)	/* interface flags */
 {
 	__int64_t		bmvend;		/* last block requested */
@@ -5634,8 +5691,10 @@ xfs_getbmap(
 					(__int64_t)(bmvend - bmv->bmv_offset));
 				bmv->bmv_entries++;
 				ap = (interface & BMV_IF_EXTENDED) ?
-					(void *)((struct getbmapx *)ap + 1) :
-					(void *)((struct getbmap *)ap + 1);
+						(void __user *)
+					((struct getbmapx __user *)ap + 1) :
+						(void __user *)
+					((struct getbmap __user *)ap + 1);
 			}
 		}
 	} while (nmap && nexleft && bmv->bmv_length);
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index 479e0d559..f1bc22fb2 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -328,7 +328,7 @@ int						/* error code */
 xfs_getbmap(
 	bhv_desc_t		*bdp,		/* XFS behavior descriptor*/
 	struct getbmap		*bmv,		/* user bmap structure */
-	void			*ap,		/* pointer to user's array */
+	void			__user *ap,	/* pointer to user's array */
 	int			iflags);	/* interface flags */
 
 /*
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index ed83f855d..0ed189102 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -1953,7 +1953,7 @@ xfs_bmbt_get_block(
 		*bpp = cur->bc_bufs[level];
 		rval = XFS_BUF_TO_BMBT_BLOCK(*bpp);
 	} else {
-		*bpp = 0;
+		*bpp = NULL;
 		ifp = XFS_IFORK_PTR(cur->bc_private.b.ip,
 			cur->bc_private.b.whichfork);
 		rval = ifp->if_broot;
diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h
index e2150f703..1c0904d08 100644
--- a/fs/xfs/xfs_bmap_btree.h
+++ b/fs/xfs/xfs_bmap_btree.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000,2002-2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * 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
@@ -153,7 +153,7 @@ typedef enum {
  */
 typedef enum {
 	XFS_EXT_NORM, XFS_EXT_UNWRITTEN,
-	XFS_EXT_DMAPI_OFFLINE
+	XFS_EXT_DMAPI_OFFLINE, XFS_EXT_INVALID
 } xfs_exntst_t;
 
 /*
@@ -551,13 +551,6 @@ xfs_bmbt_insert(
 	struct xfs_btree_cur *,
 	int *);
 
-int
-xfs_bmbt_insert_many(
-	struct xfs_btree_cur *,
-	int,
-	xfs_bmbt_rec_t *,
-	int *);
-
 void
 xfs_bmbt_log_block(
 	struct xfs_btree_cur *,
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index d550aa030..9ab0039f0 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -55,8 +55,6 @@
 #include "xfs_error.h"
 
 
-#define	ROUNDUPNBWORD(x)	(((x) + (NBWORD - 1)) & ~(NBWORD - 1))
-
 kmem_zone_t	*xfs_buf_item_zone;
 
 #ifdef XFS_TRANS_DEBUG
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index f0431b7e6..bbe00dc55 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -2092,7 +2092,7 @@ xfs_da_do_buf(
 	int		caller,
 	inst_t		*ra)
 {
-	xfs_buf_t	*bp = 0;
+	xfs_buf_t	*bp = NULL;
 	xfs_buf_t	**bplist;
 	int		error=0;
 	int		i;
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index f3bc48fe0..08d551a17 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -65,7 +65,7 @@
  */
 int
 xfs_swapext(
-	xfs_swapext_t   *sxp)
+	xfs_swapext_t	__user *sxp)
 {
 	xfs_swapext_t	sx;
 	xfs_inode_t     *ip=NULL, *tip=NULL, *ips[2];
diff --git a/fs/xfs/xfs_dfrag.h b/fs/xfs/xfs_dfrag.h
index 0e1c26fba..904860594 100644
--- a/fs/xfs/xfs_dfrag.h
+++ b/fs/xfs/xfs_dfrag.h
@@ -60,7 +60,7 @@ typedef struct xfs_swapext
 /*
  * Syscall interface for xfs_swapext
  */
-int	xfs_swapext(struct xfs_swapext *sx);
+int	xfs_swapext(struct xfs_swapext __user *sx);
 
 #endif	/* __KERNEL__ */
 
diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h
index f8f6e0fe6..705b487b3 100644
--- a/fs/xfs/xfs_dinode.h
+++ b/fs/xfs/xfs_dinode.h
@@ -456,8 +456,11 @@ xfs_dinode_t *xfs_buf_to_dinode(struct xfs_buf *bp);
 #define XFS_DIFLAG_SYNC_BIT      5	/* inode is written synchronously */
 #define XFS_DIFLAG_NOATIME_BIT   6	/* do not update atime */
 #define XFS_DIFLAG_NODUMP_BIT    7	/* do not dump */
-#define XFS_DIFLAG_BARRIER_BIT   10	/* chroot() barrier */
-#define XFS_DIFLAG_IUNLINK_BIT   11	/* inode has iunlink */
+#define XFS_DIFLAG_RTINHERIT_BIT 8	/* create with realtime bit set */
+#define XFS_DIFLAG_PROJINHERIT_BIT  9	/* create with parents projid */
+#define XFS_DIFLAG_NOSYMLINKS_BIT  10	/* disallow symlink creation */
+#define XFS_DIFLAG_BARRIER_BIT	 12	/* chroot() barrier */
+#define XFS_DIFLAG_IUNLINK_BIT	 13	/* inode has iunlink */
 
 #define XFS_DIFLAG_REALTIME      (1 << XFS_DIFLAG_REALTIME_BIT)
 #define XFS_DIFLAG_PREALLOC      (1 << XFS_DIFLAG_PREALLOC_BIT)
@@ -467,8 +470,17 @@ xfs_dinode_t *xfs_buf_to_dinode(struct xfs_buf *bp);
 #define XFS_DIFLAG_SYNC          (1 << XFS_DIFLAG_SYNC_BIT)
 #define XFS_DIFLAG_NOATIME       (1 << XFS_DIFLAG_NOATIME_BIT)
 #define XFS_DIFLAG_NODUMP        (1 << XFS_DIFLAG_NODUMP_BIT)
-#define XFS_DIFLAG_BARRIER       (1 << XFS_DIFLAG_BARRIER_BIT)
-#define XFS_DIFLAG_IUNLINK       (1 << XFS_DIFLAG_IUNLINK_BIT)
-
+#define XFS_DIFLAG_RTINHERIT     (1 << XFS_DIFLAG_RTINHERIT_BIT)
+#define XFS_DIFLAG_PROJINHERIT   (1 << XFS_DIFLAG_PROJINHERIT_BIT)
+#define XFS_DIFLAG_NOSYMLINKS    (1 << XFS_DIFLAG_NOSYMLINKS_BIT)
+#define XFS_DIFLAG_BARRIER	 (1 << XFS_DIFLAG_BARRIER_BIT)
+#define XFS_DIFLAG_IUNLINK	 (1 << XFS_DIFLAG_IUNLINK_BIT)
+
+
+#define XFS_DIFLAG_ANY \
+	(XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \
+	 XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \
+	 XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT | \
+	 XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS)
 
 #endif	/* __XFS_DINODE_H__ */
diff --git a/fs/xfs/xfs_dir2_trace.c b/fs/xfs/xfs_dir2_trace.c
index c6747162f..9d6417393 100644
--- a/fs/xfs/xfs_dir2_trace.c
+++ b/fs/xfs/xfs_dir2_trace.c
@@ -211,7 +211,7 @@ xfs_dir2_trace_args_s(
 		(void *)((unsigned long)(args->inumber >> 32)),
 		(void *)((unsigned long)(args->inumber & 0xFFFFFFFF)),
 		(void *)args->dp, (void *)args->trans,
-		(void *)(unsigned long)args->justcheck, (void *)(long)s, 0);
+		(void *)(unsigned long)args->justcheck, (void *)(long)s, NULL);
 }
 
 void
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index 7e1b82c4f..8290ea7fb 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -76,6 +76,9 @@ struct fsxattr {
 #define XFS_XFLAG_SYNC		0x00000020	/* all writes synchronous */
 #define XFS_XFLAG_NOATIME	0x00000040	/* do not update access time */
 #define XFS_XFLAG_NODUMP	0x00000080	/* do not include in backups */
+#define XFS_XFLAG_RTINHERIT	0x00000100	/* create with rt bit set */
+#define XFS_XFLAG_PROJINHERIT	0x00000200	/* create with parents projid */
+#define XFS_XFLAG_NOSYMLINKS	0x00000400	/* disallow symlink creation */
 #define XFS_XFLAG_BARRIER	0x00004000	/* chroot() barrier */
 #define XFS_XFLAG_IUNLINK	0x00008000	/* Immutable unlink */
 #define XFS_XFLAG_HASATTR	0x80000000	/* no DIFLAG for this	*/
@@ -166,7 +169,7 @@ typedef struct xfs_flock64 {
 	__s64		l_start;
 	__s64		l_len;		/* len == 0 means until end of file */
 	__s32		l_sysid;
-	pid_t		l_pid;
+	__u32		l_pid;
 	__s32		l_pad[4];	/* reserve area			    */
 } xfs_flock64_t;
 
@@ -315,10 +318,10 @@ typedef struct xfs_bstat {
  * The user-level BulkStat Request interface structure.
  */
 typedef struct xfs_fsop_bulkreq {
-	__u64		*lastip;	/* last inode # pointer		*/
+	__u64		__user *lastip;	/* last inode # pointer		*/
 	__s32		icount;		/* count of entries in buffer	*/
-	void		*ubuffer;	/* user buffer for inode desc.	*/
-	__s32		*ocount;	/* output count pointer		*/
+	void		__user *ubuffer;/* user buffer for inode desc.	*/
+	__s32		__user *ocount;	/* output count pointer		*/
 } xfs_fsop_bulkreq_t;
 
 
@@ -346,12 +349,12 @@ typedef struct xfs_error_injection {
  */
 typedef struct xfs_fsop_handlereq {
 	__u32		fd;		/* fd for FD_TO_HANDLE		*/
-	void		*path;		/* user pathname		*/
+	void		__user *path;	/* user pathname		*/
 	__u32		oflags;		/* open flags			*/
-	void		*ihandle;	/* user supplied handle		*/
+	void		__user *ihandle;/* user supplied handle		*/
 	__u32		ihandlen;	/* user supplied length		*/
-	void		*ohandle;	/* user buffer for handle	*/
-	__u32		*ohandlen;	/* user buffer length		*/
+	void		__user *ohandle;/* user buffer for handle	*/
+	__u32		__user *ohandlen;/* user buffer length		*/
 } xfs_fsop_handlereq_t;
 
 /*
@@ -362,35 +365,35 @@ typedef struct xfs_fsop_handlereq {
  */
 
 typedef struct xfs_fsop_setdm_handlereq {
-	struct xfs_fsop_handlereq hreq; /* handle interface structure */
-	struct fsdmidata *data;		/* DMAPI data to set	      */
+	struct xfs_fsop_handlereq	hreq;	/* handle information	*/
+	struct fsdmidata		__user *data;	/* DMAPI data	*/
 } xfs_fsop_setdm_handlereq_t;
 
 typedef struct xfs_attrlist_cursor {
-	__u32	opaque[4];
+	__u32		opaque[4];
 } xfs_attrlist_cursor_t;
 
 typedef struct xfs_fsop_attrlist_handlereq {
-	struct xfs_fsop_handlereq hreq; /* handle interface structure */
-	struct xfs_attrlist_cursor pos; /* opaque cookie, list offset */
-	__u32 flags;			/* flags, use ROOT/USER names */
-	__u32 buflen;			/* length of buffer supplied  */
-	void *buffer;			/* attrlist data to return    */
+	struct xfs_fsop_handlereq	hreq; /* handle interface structure */
+	struct xfs_attrlist_cursor	pos; /* opaque cookie, list offset */
+	__u32				flags;	/* which namespace to use */
+	__u32				buflen;	/* length of buffer supplied */
+	void				__user *buffer;	/* returned names */
 } xfs_fsop_attrlist_handlereq_t;
 
 typedef struct xfs_attr_multiop {
-	__u32	am_opcode;
-	__s32	am_error;
-	void	*am_attrname;
-	void	*am_attrvalue;
-	__u32	am_length;
-	__u32	am_flags;
+	__u32		am_opcode;
+	__s32		am_error;
+	void		__user *am_attrname;
+	void		__user *am_attrvalue;
+	__u32		am_length;
+	__u32		am_flags;
 } xfs_attr_multiop_t;
 
 typedef struct xfs_fsop_attrmulti_handlereq {
-	struct xfs_fsop_handlereq hreq; /* handle interface structure */
-	__u32 opcount;			/* count of following multiop */
-	struct xfs_attr_multiop *ops;	/* attr_multi data to get/set */
+	struct xfs_fsop_handlereq	hreq; /* handle interface structure */
+	__u32				opcount;/* count of following multiop */
+	struct xfs_attr_multiop		__user *ops; /* attr_multi data */
 } xfs_fsop_attrmulti_handlereq_t;
 
 /*
@@ -446,6 +449,13 @@ typedef struct xfs_handle {
 #define XFS_FSOP_GOING_FLAGS_LOGFLUSH		0x1	/* flush log but not data */
 #define XFS_FSOP_GOING_FLAGS_NOLOGFLUSH		0x2	/* don't flush log nor data */
 
+/*
+ * ioctl commands that are used by Linux filesystems
+ */
+#define XFS_IOC_GETXFLAGS	_IOR('f', 1, long)
+#define XFS_IOC_SETXFLAGS	_IOW('f', 2, long)
+#define XFS_IOC_GETVERSION	_IOR('v', 1, long)
+
 /*
  * ioctl commands that replace IRIX fcntl()'s
  * For 'documentation' purposed more than anything else,
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index 36bb461b6..ebc2f27ce 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -142,6 +142,7 @@ xfs_growfs_data_private(
 	int			dpct;
 	int			error;
 	xfs_agnumber_t		nagcount;
+	xfs_agnumber_t		nagimax = 0;
 	xfs_rfsblock_t		nb, nb_mod;
 	xfs_rfsblock_t		new;
 	xfs_rfsblock_t		nfree;
@@ -183,7 +184,7 @@ xfs_growfs_data_private(
 		memset(&mp->m_perag[oagcount], 0,
 			(nagcount - oagcount) * sizeof(xfs_perag_t));
 		mp->m_flags |= XFS_MOUNT_32BITINODES;
-		xfs_initialize_perag(mp, nagcount);
+		nagimax = xfs_initialize_perag(mp, nagcount);
 		up_write(&mp->m_peraglock);
 	}
 	tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS);
@@ -372,6 +373,9 @@ xfs_growfs_data_private(
 	if (error) {
 		return error;
 	}
+	/* New allocation groups fully initialized, so update mount struct */
+	if (nagimax)
+		mp->m_maxagi = nagimax;
 	if (mp->m_sb.sb_imax_pct) {
 		__uint64_t icount = mp->m_sb.sb_dblocks * mp->m_sb.sb_imax_pct;
 		do_div(icount, 100);
@@ -507,9 +511,9 @@ xfs_reserve_blocks(
 	__uint64_t              *inval,
 	xfs_fsop_resblks_t      *outval)
 {
-	__uint64_t              lcounter, delta;
-	__uint64_t              request;
-	unsigned long s;
+	__int64_t		lcounter, delta;
+	__uint64_t		request;
+	unsigned long		s;
 
 	/* If inval is null, report current values and return */
 
@@ -536,8 +540,7 @@ xfs_reserve_blocks(
 		mp->m_resblks = request;
 	} else {
 		delta = request - mp->m_resblks;
-		lcounter = mp->m_sb.sb_fdblocks;
-		lcounter -= delta;
+		lcounter = mp->m_sb.sb_fdblocks - delta;
 		if (lcounter < 0) {
 			/* We can't satisfy the request, just get what we can */
 			mp->m_resblks += mp->m_sb.sb_fdblocks;
@@ -587,9 +590,6 @@ xfs_fs_goingdown(
 	xfs_mount_t	*mp,
 	__uint32_t	inflags)
 {
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
 	switch (inflags) {
 	case XFS_FSOP_GOING_FLAGS_DEFAULT: {
 		struct vfs *vfsp = XFS_MTOVFS(mp);
@@ -599,7 +599,7 @@ xfs_fs_goingdown(
 			xfs_force_shutdown(mp, XFS_FORCE_UMOUNT);
 			thaw_bdev(sb->s_bdev, sb);
 		}
-
+	
 		break;
 	}
 	case XFS_FSOP_GOING_FLAGS_LOGFLUSH:
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index d3a53b67b..07641fc90 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -457,7 +457,7 @@ inode_allocate:
 			error = xfs_iget_core(vp, mp, tp, ino,
 						lock_flags, ipp, bno);
 			if (error) {
-				make_bad_inode(inode);
+				vn_mark_bad(vp);
 				if (inode->i_state & I_NEW)
 					unlock_new_inode(inode);
 				iput(inode);
@@ -576,11 +576,8 @@ xfs_iput_new(xfs_inode_t	*ip,
 
 	vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address);
 
-	/* We shouldn't get here without this being true, but just in case */
-	if (inode->i_state & I_NEW) {
-		make_bad_inode(inode);
+	if (inode->i_state & I_NEW)
 		unlock_new_inode(inode);
-	}
 	if (lock_flags)
 		xfs_iunlock(ip, lock_flags);
 	VN_RELE(vp);
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 8a821fed5..c661c948b 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -860,25 +860,32 @@ xfs_dic2xflags(
 	xfs_arch_t		arch)
 {
 	__uint16_t		di_flags;
-	uint			flags = 0;
+	uint			flags;
 
 	di_flags = INT_GET(dic->di_flags, arch);
-	if (di_flags & XFS_DIFLAG_REALTIME)
-		flags |= XFS_XFLAG_REALTIME;
-	if (di_flags & XFS_DIFLAG_PREALLOC)
-		flags |= XFS_XFLAG_PREALLOC;
-	if (di_flags & XFS_DIFLAG_IMMUTABLE)
-		flags |= XFS_XFLAG_IMMUTABLE;
-	if (di_flags & XFS_DIFLAG_APPEND)
-		flags |= XFS_XFLAG_APPEND;
-	if (di_flags & XFS_DIFLAG_SYNC)
-		flags |= XFS_XFLAG_SYNC;
-	if (di_flags & XFS_DIFLAG_NOATIME)
-		flags |= XFS_XFLAG_NOATIME;
-	if (di_flags & XFS_DIFLAG_NODUMP)
-		flags |= XFS_XFLAG_NODUMP;
-	if (XFS_CFORK_Q_ARCH(dic, arch))
-		flags |= XFS_XFLAG_HASATTR;
+	flags = XFS_CFORK_Q_ARCH(dic, arch) ? XFS_XFLAG_HASATTR : 0;
+	if (di_flags & XFS_DIFLAG_ANY) {
+		if (di_flags & XFS_DIFLAG_REALTIME)
+			flags |= XFS_XFLAG_REALTIME;
+		if (di_flags & XFS_DIFLAG_PREALLOC)
+			flags |= XFS_XFLAG_PREALLOC;
+		if (di_flags & XFS_DIFLAG_IMMUTABLE)
+			flags |= XFS_XFLAG_IMMUTABLE;
+		if (di_flags & XFS_DIFLAG_APPEND)
+			flags |= XFS_XFLAG_APPEND;
+		if (di_flags & XFS_DIFLAG_SYNC)
+			flags |= XFS_XFLAG_SYNC;
+		if (di_flags & XFS_DIFLAG_NOATIME)
+			flags |= XFS_XFLAG_NOATIME;
+		if (di_flags & XFS_DIFLAG_NODUMP)
+			flags |= XFS_XFLAG_NODUMP;
+		if (di_flags & XFS_DIFLAG_RTINHERIT)
+			flags |= XFS_XFLAG_RTINHERIT;
+		if (di_flags & XFS_DIFLAG_PROJINHERIT)
+			flags |= XFS_XFLAG_PROJINHERIT;
+		if (di_flags & XFS_DIFLAG_NOSYMLINKS)
+			flags |= XFS_XFLAG_NOSYMLINKS;
+	}
 	return flags;
 }
 
@@ -1236,8 +1243,15 @@ xfs_ialloc(
 		break;
 	case S_IFREG:
 	case S_IFDIR:
-		if (pip->i_d.di_flags &
-		    (XFS_DIFLAG_NOATIME|XFS_DIFLAG_NODUMP|XFS_DIFLAG_SYNC)) {
+		if (unlikely(pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
+			if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) {
+				if ((mode & S_IFMT) == S_IFDIR) {
+					ip->i_d.di_flags |= XFS_DIFLAG_RTINHERIT;
+				} else {
+					ip->i_d.di_flags |= XFS_DIFLAG_REALTIME;
+					ip->i_iocore.io_flags |= XFS_IOCORE_RT;
+				}
+			}
 			if ((pip->i_d.di_flags & XFS_DIFLAG_NOATIME) &&
 			    xfs_inherit_noatime)
 				ip->i_d.di_flags |= XFS_DIFLAG_NOATIME;
@@ -1247,7 +1261,11 @@ xfs_ialloc(
 			if ((pip->i_d.di_flags & XFS_DIFLAG_SYNC) &&
 			    xfs_inherit_sync)
 				ip->i_d.di_flags |= XFS_DIFLAG_SYNC;
+			if ((pip->i_d.di_flags & XFS_DIFLAG_NOSYMLINKS) &&
+			    xfs_inherit_nosymlinks)
+				ip->i_d.di_flags |= XFS_DIFLAG_NOSYMLINKS;
 		}
+		/* FALLTHROUGH */
 	case S_IFLNK:
 		ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS;
 		ip->i_df.if_flags = XFS_IFEXTENTS;
@@ -3579,6 +3597,7 @@ corrupt_out:
 	return XFS_ERROR(EFSCORRUPTED);
 }
 
+
 /*
  * Flush all inactive inodes in mp.  Return true if no user references
  * were found, false otherwise.
@@ -3634,7 +3653,6 @@ xfs_iflush_all(
 					continue;
 				}
 				if (!(flag & XFS_FLUSH_ALL)) {
-					ASSERT(0);
 					busy = 1;
 					done = 1;
 					break;
@@ -3851,6 +3869,6 @@ xfs_ilock_trace(xfs_inode_t *ip, int lock, unsigned int lockflags, inst_t *ra)
 		     (void *)ra,		/* caller of ilock */
 		     (void *)(unsigned long)current_cpu(),
 		     (void *)(unsigned long)current_pid(),
-		     0,0,0,0,0,0,0,0,0,0);
+		     NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
 }
 #endif
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index f606073ad..dc32e4aa8 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -508,7 +508,6 @@ void		xfs_xlate_dinode_core(xfs_caddr_t, struct xfs_dinode_core *,
 uint		xfs_dic2xflags(struct xfs_dinode_core *, xfs_arch_t);
 int		xfs_ifree(struct xfs_trans *, xfs_inode_t *,
 			   struct xfs_bmap_free *);
-int		xfs_atruncate_start(xfs_inode_t *);
 void		xfs_itruncate_start(xfs_inode_t *, uint, xfs_fsize_t);
 int		xfs_itruncate_finish(struct xfs_trans **, xfs_inode_t *,
 				     xfs_fsize_t, int, int);
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 7e1c1290a..3826e8f0e 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -165,20 +165,24 @@ xfs_imap_to_bmap(
 		nisize = io->io_new_size;
 
 	for (pbm = 0; imaps && pbm < iomaps; imaps--, iomapp++, imap++, pbm++) {
-		iomapp->iomap_target = io->io_flags & XFS_IOCORE_RT ?
-			mp->m_rtdev_targp : mp->m_ddev_targp;
 		iomapp->iomap_offset = XFS_FSB_TO_B(mp, imap->br_startoff);
 		iomapp->iomap_delta = offset - iomapp->iomap_offset;
 		iomapp->iomap_bsize = XFS_FSB_TO_B(mp, imap->br_blockcount);
 		iomapp->iomap_flags = flags;
 
+		if (io->io_flags & XFS_IOCORE_RT) {
+			iomapp->iomap_flags |= IOMAP_REALTIME;
+			iomapp->iomap_target = mp->m_rtdev_targp;
+		} else {
+			iomapp->iomap_target = mp->m_ddev_targp;
+		}
 		start_block = imap->br_startblock;
 		if (start_block == HOLESTARTBLOCK) {
 			iomapp->iomap_bn = IOMAP_DADDR_NULL;
-			iomapp->iomap_flags = IOMAP_HOLE;
+			iomapp->iomap_flags |= IOMAP_HOLE;
 		} else if (start_block == DELAYSTARTBLOCK) {
 			iomapp->iomap_bn = IOMAP_DADDR_NULL;
-			iomapp->iomap_flags = IOMAP_DELAY;
+			iomapp->iomap_flags |= IOMAP_DELAY;
 		} else {
 			iomapp->iomap_bn = XFS_FSB_TO_DB_IO(io, start_block);
 			if (ISUNWRITTEN(imap))
@@ -512,6 +516,15 @@ xfs_iomap_write_direct(
 
 	*ret_imap = imap[0];
 	*nmaps = 1;
+	if ( !(io->io_flags & XFS_IOCORE_RT)  && !ret_imap->br_startblock) {
+                cmn_err(CE_PANIC,"Access to block zero:  fs <%s> inode: %lld "
+                        "start_block : %llx start_off : %llx blkcnt : %llx "
+                        "extent-state : %x \n",
+                        (ip->i_mount)->m_fsname,
+                        (long long)ip->i_ino,
+                        ret_imap->br_startblock, ret_imap->br_startoff,
+                        ret_imap->br_blockcount,ret_imap->br_state);
+        }
 	return 0;
 
  error0:	/* Cancel bmap, unlock inode, and cancel trans */
@@ -572,8 +585,10 @@ retry:
 	 * out to the file system's write iosize.  We clean up any extra
 	 * space left over when the file is closed in xfs_inactive().
 	 *
-	 * We don't bother with this for sync writes, because we need
-	 * to minimize the amount we write for good performance.
+	 * For sync writes, we are flushing delayed allocate space to
+	 * try to make additional space available for allocation near
+	 * the filesystem full boundary - preallocation hurts in that
+	 * situation, of course.
 	 */
 	if (!(ioflag & BMAPI_SYNC) && ((offset + count) > ip->i_d.di_size)) {
 		xfs_off_t	aligned_offset;
@@ -598,6 +613,20 @@ retry:
 				return error;
 			}
 			for (n = 0; n < nimaps; n++) {
+				if ( !(io->io_flags & XFS_IOCORE_RT)  && 
+					!imap[n].br_startblock) {
+					cmn_err(CE_PANIC,"Access to block "
+						"zero:  fs <%s> inode: %lld "
+						"start_block : %llx start_off "
+						": %llx blkcnt : %llx "
+						"extent-state : %x \n",
+						(ip->i_mount)->m_fsname,
+						(long long)ip->i_ino,
+						imap[n].br_startblock,
+						imap[n].br_startoff,
+						imap[n].br_blockcount,
+						imap[n].br_state);
+        			}
 				if ((imap[n].br_startblock != HOLESTARTBLOCK) &&
 				    (imap[n].br_startblock != DELAYSTARTBLOCK)) {
 					goto write_map;
@@ -621,7 +650,8 @@ write_map:
 	 * request to a stripe width boundary if the file size is >=
 	 * stripe width and we are allocating past the allocation eof.
 	 */
-	if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC)
+	if (!(io->io_flags & XFS_IOCORE_RT) && mp->m_swidth 
+	    && (mp->m_flags & XFS_MOUNT_SWALLOC)
 	    && (isize >= XFS_FSB_TO_B(mp, mp->m_swidth)) && aeof) {
 		int eof;
 		xfs_fileoff_t new_last_fsb;
@@ -639,8 +669,8 @@ write_map:
 	 * if the file size is >= stripe unit size, and we are allocating past
 	 * the allocation eof.
 	 */
-	} else if (mp->m_dalign && (isize >= XFS_FSB_TO_B(mp, mp->m_dalign))
-		   && aeof) {
+	} else if (!(io->io_flags & XFS_IOCORE_RT) && mp->m_dalign &&
+		   (isize >= XFS_FSB_TO_B(mp, mp->m_dalign)) && aeof) {
 		int eof;
 		xfs_fileoff_t new_last_fsb;
 		new_last_fsb = roundup_64(last_fsb, mp->m_dalign);
@@ -651,8 +681,22 @@ write_map:
 		if (eof) {
 			last_fsb = new_last_fsb;
 		}
-	}
+	/*
+	 * Round up the allocation request to a real-time extent boundary
+	 * if the file is on the real-time subvolume.
+	 */
+	} else if (io->io_flags & XFS_IOCORE_RT && aeof) {
+		int eof;
+		xfs_fileoff_t new_last_fsb;
 
+		new_last_fsb = roundup_64(last_fsb, mp->m_sb.sb_rextsize);
+		error = XFS_BMAP_EOF(mp, io, new_last_fsb, XFS_DATA_FORK, &eof);
+		if (error) {
+			return error;
+		}
+		if (eof)
+			last_fsb = new_last_fsb;
+	}
 	error = xfs_bmapi(NULL, ip, offset_fsb,
 			  (xfs_filblks_t)(last_fsb - offset_fsb),
 			  XFS_BMAPI_DELAY | XFS_BMAPI_WRITE |
@@ -680,6 +724,15 @@ write_map:
 
 	*ret_imap = imap[0];
 	*nmaps = 1;
+	if ( !(io->io_flags & XFS_IOCORE_RT)  && !ret_imap->br_startblock) {
+		cmn_err(CE_PANIC,"Access to block zero:  fs <%s> inode: %lld "
+                        "start_block : %llx start_off : %llx blkcnt : %llx "
+                        "extent-state : %x \n",
+                        (ip->i_mount)->m_fsname,
+                        (long long)ip->i_ino,
+                        ret_imap->br_startblock, ret_imap->br_startoff,
+                        ret_imap->br_blockcount,ret_imap->br_state);
+	}
 	return 0;
 }
 
@@ -697,6 +750,7 @@ xfs_iomap_write_allocate(
 	int		*retmap)
 {
 	xfs_mount_t	*mp = ip->i_mount;
+	xfs_iocore_t    *io = &ip->i_iocore;
 	xfs_fileoff_t	offset_fsb, last_block;
 	xfs_fileoff_t	end_fsb, map_start_fsb;
 	xfs_fsblock_t	first_block;
@@ -802,6 +856,18 @@ xfs_iomap_write_allocate(
 		 */
 
 		for (i = 0; i < nimaps; i++) {
+			if ( !(io->io_flags & XFS_IOCORE_RT)  && 
+				!imap[i].br_startblock) {
+				cmn_err(CE_PANIC,"Access to block zero:  "
+					"fs <%s> inode: %lld "
+					"start_block : %llx start_off : %llx " 
+					"blkcnt : %llx extent-state : %x \n",
+					(ip->i_mount)->m_fsname,
+					(long long)ip->i_ino,
+					imap[i].br_startblock,
+					imap[i].br_startoff,
+				        imap[i].br_blockcount,imap[i].br_state);
+                        }
 			if ((map->br_startoff >= imap[i].br_startoff) &&
 			    (map->br_startoff < (imap[i].br_startoff +
 						 imap[i].br_blockcount))) {
@@ -837,6 +903,7 @@ xfs_iomap_write_unwritten(
 	size_t		count)
 {
 	xfs_mount_t	*mp = ip->i_mount;
+	xfs_iocore_t    *io = &ip->i_iocore;
 	xfs_trans_t	*tp;
 	xfs_fileoff_t	offset_fsb;
 	xfs_filblks_t	count_fsb;
@@ -853,7 +920,8 @@ xfs_iomap_write_unwritten(
 				&ip->i_iocore, offset, count);
 
 	offset_fsb = XFS_B_TO_FSBT(mp, offset);
-	count_fsb = XFS_B_TO_FSB(mp, count);
+	count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count);
+	count_fsb = (xfs_filblks_t)(count_fsb - offset_fsb);
 
 	do {
 		nres = XFS_DIOSTRAT_SPACE_RES(mp, 0);
@@ -898,6 +966,16 @@ xfs_iomap_write_unwritten(
 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
 		if (error)
 			goto error0;
+		
+		if ( !(io->io_flags & XFS_IOCORE_RT)  && !imap.br_startblock) {
+			cmn_err(CE_PANIC,"Access to block zero:  fs <%s> "
+				"inode: %lld start_block : %llx start_off : "
+				"%llx blkcnt : %llx extent-state : %x \n",
+				(ip->i_mount)->m_fsname,
+				(long long)ip->i_ino,
+				imap.br_startblock,imap.br_startoff,
+				imap.br_blockcount,imap.br_state);
+        	}
 
 		if ((numblks_fsb = imap.br_blockcount) == 0) {
 			/*
diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h
index 673410c56..31c91087c 100644
--- a/fs/xfs/xfs_iomap.h
+++ b/fs/xfs/xfs_iomap.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2003,2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * 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
@@ -42,6 +42,7 @@ typedef enum {				/* iomap_flags values */
 	IOMAP_EOF =		0x01,	/* mapping contains EOF   */
 	IOMAP_HOLE =		0x02,	/* mapping covers a hole  */
 	IOMAP_DELAY =		0x04,	/* mapping covers delalloc region  */
+	IOMAP_REALTIME =	0x10,	/* mapping on the realtime device  */
 	IOMAP_UNWRITTEN =	0x20,	/* mapping covers allocated */
 					/* but uninitialized file data  */
 	IOMAP_NEW =		0x40	/* just allocate */
@@ -57,7 +58,7 @@ typedef enum {
 	BMAPI_IGNSTATE = (1 << 4),	/* ignore unwritten state on read */
 	BMAPI_DIRECT = (1 << 5),		/* direct instead of buffered write */
 	BMAPI_MMAP = (1 << 6),		/* allocate for mmap write */
-	BMAPI_SYNC = (1 << 7),		/* sync write */
+	BMAPI_SYNC = (1 << 7),		/* sync write to flush delalloc space */
 	BMAPI_TRYLOCK = (1 << 8),	/* non-blocking request */
 	BMAPI_DEVICE = (1 << 9),	/* we only want to know the device */
 } bmapi_flags_t;
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 01fae1abb..36dc09c8c 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -68,7 +68,7 @@ int		       		/* error status */
 xfs_bulkstat_one(
 	xfs_mount_t	*mp,		/* mount point for filesystem */
 	xfs_ino_t	ino,		/* inode number to get data for */
-	void		*buffer,	/* buffer to place output in */
+	void		__user *buffer,	/* buffer to place output in */
 	int		ubsize,		/* size of buffer */
 	void		*private_data,	/* my private data */
 	xfs_daddr_t	bno,		/* starting bno of inode cluster */
@@ -231,7 +231,7 @@ xfs_bulkstat(
 	bulkstat_one_pf		formatter, /* func that'd fill a single buf */
 	void			*private_data,/* private data for formatter */
 	size_t			statstruct_size, /* sizeof struct filling */
-	xfs_caddr_t		ubuffer, /* buffer with inode stats */
+	char			__user *ubuffer, /* buffer with inode stats */
 	int			flags,	/* defined in xfs_itable.h */
 	int			*done)	/* 1 if there're more stats to get */
 {
@@ -265,7 +265,7 @@ xfs_bulkstat(
 	int			tmp;	/* result value from btree calls */
 	int			ubcount; /* size of user's buffer */
 	int			ubleft;	/* bytes left in user's buffer */
-	xfs_caddr_t		ubufp;	/* current pointer into user's buffer */
+	char			__user *ubufp;	/* pointer into user's buffer */
 	int			ubelem;	/* spaces used in user's buffer */
 	int			ubused;	/* bytes used by formatter */
 	xfs_buf_t		*bp;	/* ptr to on-disk inode cluster buf */
@@ -633,7 +633,7 @@ int					/* error status */
 xfs_bulkstat_single(
 	xfs_mount_t		*mp,	/* mount point for filesystem */
 	xfs_ino_t		*lastinop, /* inode to return */
-	xfs_caddr_t		buffer,	/* buffer with inode stats */
+	char			__user *buffer, /* buffer with inode stats */
 	int			*done)	/* 1 if there're more stats to get */
 {
 	int			count;	/* count value for bulkstat call */
@@ -682,7 +682,7 @@ xfs_inumbers(
 	xfs_mount_t	*mp,		/* mount point for filesystem */
 	xfs_ino_t	*lastino,	/* last inode returned */
 	int		*count,		/* size of buffer/count returned */
-	xfs_caddr_t	ubuffer)	/* buffer with inode descriptions */
+	xfs_inogrp_t	__user *ubuffer)/* buffer with inode descriptions */
 {
 	xfs_buf_t	*agbp;
 	xfs_agino_t	agino;
@@ -766,7 +766,7 @@ xfs_inumbers(
 				error = XFS_ERROR(EFAULT);
 				break;
 			}
-			ubuffer += bufidx * sizeof(*buffer);
+			ubuffer += bufidx;
 			*count += bufidx;
 			bufidx = 0;
 		}
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
index 476e531a9..2be9d1805 100644
--- a/fs/xfs/xfs_itable.h
+++ b/fs/xfs/xfs_itable.h
@@ -40,7 +40,7 @@
  */
 typedef int (*bulkstat_one_pf)(struct xfs_mount	*mp,
 			       xfs_ino_t	ino,
-			       void		*buffer,
+			       void		__user *buffer,
 			       int		ubsize,
 			       void		*private_data,
 			       xfs_daddr_t	bno,
@@ -73,7 +73,7 @@ xfs_bulkstat(
 	bulkstat_one_pf formatter,	/* func that'd fill a single buf */
 	void		*private_data,	/* private data for formatter */
 	size_t		statstruct_size,/* sizeof struct that we're filling */
-	xfs_caddr_t	ubuffer,	/* buffer with inode stats */
+	char		__user *ubuffer,/* buffer with inode stats */
 	int		flags,		/* flag to control access method */
 	int		*done);		/* 1 if there're more stats to get */
 
@@ -81,14 +81,14 @@ int
 xfs_bulkstat_single(
 	xfs_mount_t		*mp,
 	xfs_ino_t		*lastinop,
-	xfs_caddr_t		buffer,
+	char			__user *buffer,
 	int			*done);
 
 int
 xfs_bulkstat_one(
 	xfs_mount_t		*mp,
 	xfs_ino_t		ino,
-	void			*buffer,
+	void			__user *buffer,
 	int			ubsize,
 	void			*private_data,
 	xfs_daddr_t		bno,
@@ -101,6 +101,6 @@ xfs_inumbers(
 	xfs_mount_t		*mp,	/* mount point for filesystem */
 	xfs_ino_t		*last,	/* last inode returned */
 	int			*count,	/* size of buffer/count returned */
-	xfs_caddr_t		buffer);/* buffer with inode descriptions */
+	xfs_inogrp_t		__user *buffer);/* buffer with inode info */
 
 #endif	/* __XFS_ITABLE_H__ */
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 212d4e837..7db33af12 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -122,7 +122,6 @@ STATIC void		xlog_ticket_put(xlog_t *log, xlog_ticket_t *ticket);
 /* local debug functions */
 #if defined(DEBUG) && !defined(XLOG_NOLOG)
 STATIC void	xlog_verify_dest_ptr(xlog_t *log, __psint_t ptr);
-STATIC void	xlog_verify_disk_cycle_no(xlog_t *log, xlog_in_core_t *iclog);
 STATIC void	xlog_verify_grant_head(xlog_t *log, int equals);
 STATIC void	xlog_verify_iclog(xlog_t *log, xlog_in_core_t *iclog,
 				  int count, boolean_t syncing);
@@ -130,7 +129,6 @@ STATIC void	xlog_verify_tail_lsn(xlog_t *log, xlog_in_core_t *iclog,
 				     xfs_lsn_t tail_lsn);
 #else
 #define xlog_verify_dest_ptr(a,b)
-#define xlog_verify_disk_cycle_no(a,b)
 #define xlog_verify_grant_head(a,b)
 #define xlog_verify_iclog(a,b,c,d)
 #define xlog_verify_tail_lsn(a,b,c)
@@ -356,13 +354,13 @@ xfs_log_notify(xfs_mount_t	  *mp,		/* mount of partition */
 	if (!xlog_debug && xlog_target == log->l_targ)
 		return 0;
 #endif
-	cb->cb_next = 0;
+	cb->cb_next = NULL;
 	spl = LOG_LOCK(log);
 	abortflg = (iclog->ic_state & XLOG_STATE_IOERROR);
 	if (!abortflg) {
 		ASSERT_ALWAYS((iclog->ic_state == XLOG_STATE_ACTIVE) ||
 			      (iclog->ic_state == XLOG_STATE_WANT_SYNC));
-		cb->cb_next = 0;
+		cb->cb_next = NULL;
 		*(iclog->ic_callback_tail) = cb;
 		iclog->ic_callback_tail = &(cb->cb_next);
 	}
@@ -564,7 +562,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
 	xlog_in_core_t	 *first_iclog;
 #endif
 	xfs_log_iovec_t  reg[1];
-	xfs_log_ticket_t tic = 0;
+	xfs_log_ticket_t tic = NULL;
 	xfs_lsn_t	 lsn;
 	int		 error;
 	SPLDECL(s);
@@ -813,7 +811,7 @@ xfs_log_need_covered(xfs_mount_t *mp)
 	xlog_t		*log = mp->m_log;
 	vfs_t		*vfsp = XFS_MTOVFS(mp);
 
-	if (vfsp->vfs_super->s_frozen || XFS_FORCED_SHUTDOWN(mp) ||
+	if (fs_frozen(vfsp) || XFS_FORCED_SHUTDOWN(mp) ||
 	    (vfsp->vfs_flag & VFS_RDONLY))
 		return 0;
 
@@ -1277,7 +1275,7 @@ xlog_commit_record(xfs_mount_t  *mp,
 	int		error;
 	xfs_log_iovec_t	reg[1];
 
-	reg[0].i_addr = 0;
+	reg[0].i_addr = NULL;
 	reg[0].i_len = 0;
 
 	ASSERT_ALWAYS(iclog);
@@ -1413,9 +1411,13 @@ xlog_sync(xlog_t		*log,
 	xlog_pack_data(log, iclog);       /* put cycle number in every block */
 
 	/* real byte length */
-	INT_SET(iclog->ic_header.h_len, 
-		ARCH_CONVERT,
-		iclog->ic_offset + iclog->ic_roundoff);
+	if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
+		INT_SET(iclog->ic_header.h_len, 
+			ARCH_CONVERT,
+			iclog->ic_offset + iclog->ic_roundoff);
+	} else {
+		INT_SET(iclog->ic_header.h_len, ARCH_CONVERT, iclog->ic_offset);
+	}
 
 	/* put ops count in correct order */
 	ops = iclog->ic_header.h_num_logops;
@@ -1857,7 +1859,7 @@ xlog_state_clean_log(xlog_t *log)
 		if (iclog->ic_state == XLOG_STATE_DIRTY) {
 			iclog->ic_state	= XLOG_STATE_ACTIVE;
 			iclog->ic_offset       = 0;
-			iclog->ic_callback	= 0;   /* don't need to free */
+			iclog->ic_callback	= NULL;   /* don't need to free */
 			/*
 			 * If the number of ops in this iclog indicate it just
 			 * contains the dummy transaction, we can
@@ -2080,7 +2082,7 @@ xlog_state_do_callback(
 
 			while (cb != 0) {
 				iclog->ic_callback_tail = &(iclog->ic_callback);
-				iclog->ic_callback = 0;
+				iclog->ic_callback = NULL;
 				LOG_UNLOCK(log, s);
 
 				/* perform callbacks in the order given */
@@ -3098,7 +3100,7 @@ xlog_state_ticket_alloc(xlog_t *log)
 		log->l_ticket_cnt++;
 		log->l_ticket_tcnt++;
 	}
-	t_list->t_next = 0;
+	t_list->t_next = NULL;
 	log->l_tail = t_list;
 	LOG_UNLOCK(log, s);
 }	/* xlog_state_ticket_alloc */
@@ -3126,7 +3128,7 @@ xlog_ticket_put(xlog_t		*log,
 	/* no need to clear fields */
 #else
 	/* When we debug, it is easier if tickets are cycled */
-	ticket->t_next     = 0;
+	ticket->t_next     = NULL;
 	if (log->l_tail != 0) {
 		log->l_tail->t_next = ticket;
 	} else {
@@ -3242,33 +3244,6 @@ xlog_verify_dest_ptr(xlog_t     *log,
 		xlog_panic("xlog_verify_dest_ptr: invalid ptr");
 }	/* xlog_verify_dest_ptr */
 
-
-#ifdef DEBUG
-/* check split LR write */
-STATIC void
-xlog_verify_disk_cycle_no(xlog_t	 *log,
-			  xlog_in_core_t *iclog)
-{
-    xfs_buf_t	*bp;
-    uint	cycle_no;
-    xfs_caddr_t ptr;
-    xfs_daddr_t	i;
-
-    if (BLOCK_LSN(iclog->ic_header.h_lsn, ARCH_CONVERT) < 10) {
-	cycle_no = CYCLE_LSN(iclog->ic_header.h_lsn, ARCH_CONVERT);
-	bp = xlog_get_bp(log, 1);
-	ASSERT(bp);
-	for (i = 0; i < BLOCK_LSN(iclog->ic_header.h_lsn, ARCH_CONVERT); i++) {
-	    xlog_bread(log, i, 1, bp);
-	    ptr = xlog_align(log, i, 1, bp);
-	    if (GET_CYCLE(ptr, ARCH_CONVERT) != cycle_no)
-		xlog_warn("XFS: xlog_verify_disk_cycle_no: bad cycle no");
-	}
-	xlog_put_bp(bp);
-    }
-}	/* xlog_verify_disk_cycle_no */
-#endif
-
 STATIC void
 xlog_verify_grant_head(xlog_t *log, int equals)
 {
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index 052de386e..7d91f70bd 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -543,7 +543,6 @@ extern int	 xlog_find_tail(xlog_t	*log,
 				xfs_daddr_t *head_blk,
 				xfs_daddr_t *tail_blk,
 				int readonly);
-extern int	 xlog_print_find_oldest(xlog_t *log, xfs_daddr_t *last_blk);
 extern int	 xlog_recover(xlog_t *log, int readonly);
 extern int	 xlog_recover_finish(xlog_t *log, int mfsi_flags);
 extern void	 xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog);
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 2e5ab6af8..028685574 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -2047,12 +2047,11 @@ xfs_qm_dqcheck(
 		errs++;
 	}
 
-	if (! errs) {
+	if (! errs && !INT_ISZERO(ddq->d_id, ARCH_CONVERT)) {
 		if (INT_GET(ddq->d_blk_softlimit, ARCH_CONVERT) &&
 		    INT_GET(ddq->d_bcount, ARCH_CONVERT) >=
 				INT_GET(ddq->d_blk_softlimit, ARCH_CONVERT)) {
-			if (INT_ISZERO(ddq->d_btimer, ARCH_CONVERT) &&
-			    !INT_ISZERO(ddq->d_id, ARCH_CONVERT)) {
+			if (INT_ISZERO(ddq->d_btimer, ARCH_CONVERT)) {
 				if (flags & XFS_QMOPT_DOWARN)
 					cmn_err(CE_ALERT,
 					"%s : Dquot ID 0x%x (0x%p) "
@@ -2065,8 +2064,7 @@ xfs_qm_dqcheck(
 		if (INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT) &&
 		    INT_GET(ddq->d_icount, ARCH_CONVERT) >=
 				INT_GET(ddq->d_ino_softlimit, ARCH_CONVERT)) {
-			if (INT_ISZERO(ddq->d_itimer, ARCH_CONVERT) &&
-			    !INT_ISZERO(ddq->d_id, ARCH_CONVERT)) {
+			if (INT_ISZERO(ddq->d_itimer, ARCH_CONVERT)) {
 				if (flags & XFS_QMOPT_DOWARN)
 					cmn_err(CE_ALERT,
 					"%s : Dquot ID 0x%x (0x%p) "
@@ -2076,6 +2074,19 @@ xfs_qm_dqcheck(
 				errs++;
 			}
 		}
+		if (INT_GET(ddq->d_rtb_softlimit, ARCH_CONVERT) &&
+		    INT_GET(ddq->d_rtbcount, ARCH_CONVERT) >=
+				INT_GET(ddq->d_rtb_softlimit, ARCH_CONVERT)) {
+			if (INT_ISZERO(ddq->d_rtbtimer, ARCH_CONVERT)) {
+				if (flags & XFS_QMOPT_DOWARN)
+					cmn_err(CE_ALERT,
+					"%s : Dquot ID 0x%x (0x%p) "
+					"RTBLK TIMER NOT STARTED",
+					str, (int)
+					INT_GET(ddq->d_id, ARCH_CONVERT), ddq);
+				errs++;
+			}
+		}
 	}
 
 	if (!errs || !(flags & XFS_QMOPT_DQREPAIR))
@@ -2319,7 +2330,7 @@ xlog_recover_do_inode_trans(
 		 * invalidate the buffer when we write it out below.
 		 */
 		imap.im_blkno = 0;
-		xfs_imap(log->l_mp, 0, ino, &imap, 0);
+		xfs_imap(log->l_mp, NULL, ino, &imap, 0);
 	}
 
 	/*
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 93c544ee5..9c8e7c5a7 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -278,17 +278,22 @@ xfs_mount_validate_sb(
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
-#if !XFS_BIG_BLKNOS
+	ASSERT(PAGE_SHIFT >= sbp->sb_blocklog);
+	ASSERT(sbp->sb_blocklog >= BBSHIFT);
+
+#if XFS_BIG_BLKNOS     /* Limited by ULONG_MAX of page cache index */
+	if (unlikely(
+	    (sbp->sb_dblocks >> (PAGE_SHIFT - sbp->sb_blocklog)) > ULONG_MAX ||
+	    (sbp->sb_rblocks >> (PAGE_SHIFT - sbp->sb_blocklog)) > ULONG_MAX)) {
+#else                  /* Limited by UINT_MAX of sectors */
 	if (unlikely(
-	    (sbp->sb_dblocks << (__uint64_t)(sbp->sb_blocklog - BBSHIFT))
-		> UINT_MAX ||
-	    (sbp->sb_rblocks << (__uint64_t)(sbp->sb_blocklog - BBSHIFT))
-		> UINT_MAX)) {
+	    (sbp->sb_dblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX ||
+	    (sbp->sb_rblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX)) {
+#endif
 		cmn_err(CE_WARN,
 	"XFS: File system is too large to be mounted on this system.");
 		return XFS_ERROR(E2BIG);
 	}
-#endif
 
 	if (unlikely(sbp->sb_inprogress)) {
 		cmn_err(CE_WARN, "XFS: file system busy");
@@ -313,10 +318,10 @@ xfs_mount_validate_sb(
 	return 0;
 }
 
-void
-xfs_initialize_perag(xfs_mount_t *mp, int agcount)
+xfs_agnumber_t
+xfs_initialize_perag(xfs_mount_t *mp, xfs_agnumber_t agcount)
 {
-	int		index, max_metadata;
+	xfs_agnumber_t	index, max_metadata;
 	xfs_perag_t	*pag;
 	xfs_agino_t	agino;
 	xfs_ino_t	ino;
@@ -372,7 +377,7 @@ xfs_initialize_perag(xfs_mount_t *mp, int agcount)
 			pag->pagi_inodeok = 1;
 		}
 	}
-	mp->m_maxagi = index;
+	return index;
 }
 
 /*
@@ -633,9 +638,8 @@ xfs_mountfs(
 	xfs_buf_t	*bp;
 	xfs_sb_t	*sbp = &(mp->m_sb);
 	xfs_inode_t	*rip;
-	vnode_t		*rvp = 0;
+	vnode_t		*rvp = NULL;
 	int		readio_log, writeio_log;
-	vmap_t		vmap;
 	xfs_daddr_t	d;
 	__uint64_t	ret64;
 	__int64_t	update_flags;
@@ -947,7 +951,7 @@ xfs_mountfs(
 	mp->m_perag =
 		kmem_zalloc(sbp->sb_agcount * sizeof(xfs_perag_t), KM_SLEEP);
 
-	xfs_initialize_perag(mp, sbp->sb_agcount);
+	mp->m_maxagi = xfs_initialize_perag(mp, sbp->sb_agcount);
 
 	/*
 	 * log's mount-time initialization. Perform 1st part recovery if needed
@@ -979,7 +983,6 @@ xfs_mountfs(
 
 	ASSERT(rip != NULL);
 	rvp = XFS_ITOV(rip);
-	VMAP(rvp, vmap);
 
 	if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) {
 		cmn_err(CE_WARN, "XFS: corrupted root inode");
@@ -1043,7 +1046,6 @@ xfs_mountfs(
 	 * Free up the root inode.
 	 */
 	VN_RELE(rvp);
-	vn_purge(rvp, &vmap);
  error3:
 	xfs_log_unmount_dealloc(mp);
  error2:
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index f51ec1296..c194b8ef0 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -551,7 +551,7 @@ extern int	xfs_readsb(xfs_mount_t *mp);
 extern void	xfs_freesb(xfs_mount_t *);
 extern void	xfs_do_force_shutdown(bhv_desc_t *, int, char *, int);
 extern int	xfs_syncsub(xfs_mount_t *, int, int, int *);
-extern void	xfs_initialize_perag(xfs_mount_t *, int);
+extern xfs_agnumber_t	xfs_initialize_perag(xfs_mount_t *, xfs_agnumber_t);
 extern void	xfs_xlatesb(void *, struct xfs_sb *, int, xfs_arch_t,
 			__int64_t);
 
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 8cddc1639..703ec4efc 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -309,23 +309,27 @@ typedef struct xfs_dqtrxops {
 } xfs_dqtrxops_t;
 
 #define XFS_DQTRXOP(mp, tp, op, args...) \
-			((mp)->m_qm_ops.xfs_dqtrxops ? \
-			((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : 0)
+		((mp)->m_qm_ops.xfs_dqtrxops ? \
+		((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : 0)
+
+#define XFS_DQTRXOP_VOID(mp, tp, op, args...) \
+		((mp)->m_qm_ops.xfs_dqtrxops ? \
+		((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : (void)0)
 
 #define XFS_TRANS_DUP_DQINFO(mp, otp, ntp) \
-	XFS_DQTRXOP(mp, otp, qo_dup_dqinfo, ntp)
+	XFS_DQTRXOP_VOID(mp, otp, qo_dup_dqinfo, ntp)
 #define XFS_TRANS_FREE_DQINFO(mp, tp) \
-	XFS_DQTRXOP(mp, tp, qo_free_dqinfo)
+	XFS_DQTRXOP_VOID(mp, tp, qo_free_dqinfo)
 #define XFS_TRANS_MOD_DQUOT_BYINO(mp, tp, ip, field, delta) \
-	XFS_DQTRXOP(mp, tp, qo_mod_dquot_byino, ip, field, delta)
+	XFS_DQTRXOP_VOID(mp, tp, qo_mod_dquot_byino, ip, field, delta)
 #define XFS_TRANS_APPLY_DQUOT_DELTAS(mp, tp) \
-	XFS_DQTRXOP(mp, tp, qo_apply_dquot_deltas)
+	XFS_DQTRXOP_VOID(mp, tp, qo_apply_dquot_deltas)
 #define XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, ninos, fl) \
 	XFS_DQTRXOP(mp, tp, qo_reserve_quota_nblks, mp, ip, nblks, ninos, fl)
 #define XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp, ud, gd, nb, ni, fl) \
 	XFS_DQTRXOP(mp, tp, qo_reserve_quota_bydquots, mp, ud, gd, nb, ni, fl)
 #define XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(mp, tp) \
-	XFS_DQTRXOP(mp, tp, qo_unreserve_and_mod_dquots)
+	XFS_DQTRXOP_VOID(mp, tp, qo_unreserve_and_mod_dquots)
 
 #define XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, nblks) \
 	XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, 0, \
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index c130d4259..431c8f450 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -1966,7 +1966,8 @@ xfs_growfs_rt(
 	/*
 	 * Calculate new parameters.  These are the final values to be reached.
 	 */
-	nrextents = do_div(nrblocks, in->extsize);
+	nrextents = nrblocks;
+	do_div(nrextents, in->extsize);
 	nrbmblocks = roundup_64(nrextents, NBBY * sbp->sb_blocksize);
 	nrextslog = xfs_highbit32(nrextents);
 	nrsumlevels = nrextslog + 1;
@@ -2021,7 +2022,8 @@ xfs_growfs_rt(
 			XFS_RTMIN(nrblocks,
 				  nsbp->sb_rbmblocks * NBBY *
 				  nsbp->sb_blocksize * nsbp->sb_rextsize);
-		nsbp->sb_rextents = do_div(nsbp->sb_rblocks, nsbp->sb_rextsize);
+		nsbp->sb_rextents = nsbp->sb_rblocks;
+		do_div(nsbp->sb_rextents, nsbp->sb_rextsize);
 		nsbp->sb_rextslog = xfs_highbit32(nsbp->sb_rextents);
 		nrsumlevels = nmp->m_rsumlevels = nsbp->sb_rextslog + 1;
 		nrsumsize =
@@ -2353,13 +2355,7 @@ xfs_rtmount_inodes(
 	ASSERT(sbp->sb_rsumino != NULLFSINO);
 	error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, &mp->m_rsumip, 0);
 	if (error) {
-		vnode_t		*rbmvp;		/* vnode for bitmap file */
-		vmap_t		vmap;		/* vmap to delete vnode */
-
-		rbmvp = XFS_ITOV(mp->m_rbmip);
-		VMAP(rbmvp, vmap);
-		VN_RELE(rbmvp);
-		vn_purge(rbmvp, &vmap);
+		VN_RELE(XFS_ITOV(mp->m_rbmip));
 		return error;
 	}
 	ASSERT(mp->m_rsumip != NULL);
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h
index 9e0adf4c4..ad090a834 100644
--- a/fs/xfs/xfs_sb.h
+++ b/fs/xfs/xfs_sb.h
@@ -250,9 +250,9 @@ int xfs_sb_good_version(xfs_sb_t *sbp);
 	((((sbp)->sb_versionnum >= XFS_SB_VERSION_1) && \
 	  ((sbp)->sb_versionnum <= XFS_SB_VERSION_3)) || \
 	   ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \
-	    !(((sbp)->sb_versionnum & ~XFS_SB_VERSION_OKREALBITS) && \
-	      ((sbp)->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) && \
-	      ((sbp)->sb_features2 & ~XFS_SB_VERSION2_OKREALBITS))
+	    !(((sbp)->sb_versionnum & ~XFS_SB_VERSION_OKREALBITS) || \
+	      (((sbp)->sb_versionnum & XFS_SB_VERSION_MOREBITSBIT) && \
+	       ((sbp)->sb_features2 & ~XFS_SB_VERSION2_OKREALBITS)))
 
 #ifdef __KERNEL__
 #define	XFS_SB_GOOD_VERSION(sbp)	\
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 818857739..3db0e2200 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -131,7 +131,7 @@ xfs_trans_alloc(
 	xfs_mount_t	*mp,
 	uint		type)
 {
-	vfs_check_frozen(XFS_MTOVFS(mp)->vfs_super, SB_FREEZE_TRANS);
+	fs_check_frozen(XFS_MTOVFS(mp), SB_FREEZE_TRANS);
 	atomic_inc(&mp->m_active_trans);
 
 	return (_xfs_trans_alloc(mp, type));
@@ -491,6 +491,9 @@ xfs_trans_apply_sb_deltas(
 	if (tp->t_frextents_delta != 0) {
 		INT_MOD(sbp->sb_frextents, ARCH_CONVERT, tp->t_frextents_delta);
 	}
+	if (tp->t_res_frextents_delta != 0) {
+		INT_MOD(sbp->sb_frextents, ARCH_CONVERT, tp->t_res_frextents_delta);
+	}
 	if (tp->t_dblocks_delta != 0) {
 		INT_MOD(sbp->sb_dblocks, ARCH_CONVERT, tp->t_dblocks_delta);
 		whole = 1;
diff --git a/fs/xfs/xfs_trans_item.c b/fs/xfs/xfs_trans_item.c
index 767af4810..1b8a756d8 100644
--- a/fs/xfs/xfs_trans_item.c
+++ b/fs/xfs/xfs_trans_item.c
@@ -290,7 +290,7 @@ xfs_trans_next_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp)
 	}
 	ASSERT(0);
 	/* NOTREACHED */
-	return 0; /* keep gcc quite */
+	return NULL; /* keep gcc quite */
 }
 
 /*
diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h
index 8d6aac750..04609d27e 100644
--- a/fs/xfs/xfs_types.h
+++ b/fs/xfs/xfs_types.h
@@ -58,7 +58,7 @@ typedef enum { B_FALSE,B_TRUE }	boolean_t;
 typedef __int64_t		prid_t;		/* project ID */
 typedef __uint32_t		inst_t;		/* an instruction */
 
-typedef __u64			xfs_off_t;
+typedef __s64			xfs_off_t;	/* <file offset> type */
 typedef __u64			xfs_ino_t;	/* <inode> type */
 typedef __s64			xfs_daddr_t;	/* <disk address> type */
 typedef char *			xfs_caddr_t;	/* <core address> type */
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 114c53a76..dc6037a46 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -430,6 +430,16 @@ xfs_mount(
 	ddev = vfsp->vfs_super->s_bdev;
 	logdev = rtdev = NULL;
 
+	/*
+	 * Setup xfs_mount function vectors from available behaviors
+	 */
+	p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM);
+	mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub;
+	p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM);
+	mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub;
+	p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
+	mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
+
 	/*
 	 * Open real time and log devices - order is important.
 	 */
@@ -454,69 +464,74 @@ xfs_mount(
 		}
 	}
 
-	/*
-	 * Setup xfs_mount function vectors from available behaviors
-	 */
-	p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM);
-	mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub;
-	p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM);
-	mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub;
-	p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
-	mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
-
 	/*
 	 * Setup xfs_mount buffer target pointers
 	 */
+	error = ENOMEM;
 	mp->m_ddev_targp = xfs_alloc_buftarg(ddev);
-	if (rtdev)
+	if (!mp->m_ddev_targp) {
+		xfs_blkdev_put(logdev);
+		xfs_blkdev_put(rtdev);
+		return error;
+	}
+	if (rtdev) {
 		mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev);
+		if (!mp->m_rtdev_targp)
+			goto error0;
+	}
 	mp->m_logdev_targp = (logdev && logdev != ddev) ?
 				xfs_alloc_buftarg(logdev) : mp->m_ddev_targp;
+	if (!mp->m_logdev_targp)
+		goto error0;
 
 	/*
 	 * Setup flags based on mount(2) options and then the superblock
 	 */
 	error = xfs_start_flags(vfsp, args, mp);
 	if (error)
-		goto error;
+		goto error1;
 	error = xfs_readsb(mp);
 	if (error)
-		goto error;
+		goto error1;
 	error = xfs_finish_flags(vfsp, args, mp);
-	if (error) {
-		xfs_freesb(mp);
-		goto error;
-	}
+	if (error)
+		goto error2;
 
 	/*
 	 * Setup xfs_mount buffer target pointers based on superblock
 	 */
-	xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize,
-			    mp->m_sb.sb_sectsize);
-	if (logdev && logdev != ddev) {
+	error = xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize,
+				    mp->m_sb.sb_sectsize);
+	if (!error && logdev && logdev != ddev) {
 		unsigned int	log_sector_size = BBSIZE;
 
 		if (XFS_SB_VERSION_HASSECTOR(&mp->m_sb))
 			log_sector_size = mp->m_sb.sb_logsectsize;
-		xfs_setsize_buftarg(mp->m_logdev_targp, mp->m_sb.sb_blocksize,
-				    log_sector_size);
+		error = xfs_setsize_buftarg(mp->m_logdev_targp,
+					    mp->m_sb.sb_blocksize,
+					    log_sector_size);
 	}
-	if (rtdev)
-		xfs_setsize_buftarg(mp->m_rtdev_targp, mp->m_sb.sb_blocksize,
-				    mp->m_sb.sb_blocksize);
+	if (!error && rtdev)
+		error = xfs_setsize_buftarg(mp->m_rtdev_targp,
+					    mp->m_sb.sb_blocksize,
+					    mp->m_sb.sb_sectsize);
+	if (error)
+		goto error2;
 
-	if (!(error = XFS_IOINIT(vfsp, args, flags)))
+	error = XFS_IOINIT(vfsp, args, flags);
+	if (!error)
 		return 0;
-
- error:
+error2:
+	if (mp->m_sb_bp)
+		xfs_freesb(mp);
+error1:
 	xfs_binval(mp->m_ddev_targp);
-	if (logdev != NULL && logdev != ddev) {
+	if (logdev && logdev != ddev)
 		xfs_binval(mp->m_logdev_targp);
-	}
-	if (rtdev != NULL) {
+	if (rtdev)
 		xfs_binval(mp->m_rtdev_targp);
-	}
-	xfs_unmountfs_close(mp, NULL);
+error0:
+	xfs_unmountfs_close(mp, credp);
 	return error;
 }
 
@@ -1040,6 +1055,11 @@ xfs_sync_inodes(
 			continue;
 		}
 
+		if (VN_BAD(vp)) {
+			ip = ip->i_mnext;
+			continue;
+		}
+
 		if (XFS_FORCED_SHUTDOWN(mp) && !(flags & SYNC_CLOSE)) {
 			XFS_MOUNT_IUNLOCK(mp);
 			kmem_free(ipointer, sizeof(xfs_iptr_t));
@@ -1567,31 +1587,35 @@ xfs_vget(
 	vnode_t		**vpp,
 	fid_t		*fidp)
 {
-	xfs_fid_t	*xfid;
+	xfs_mount_t	*mp = XFS_BHVTOM(bdp);
+	xfs_fid_t	*xfid = (struct xfs_fid *)fidp;
 	xfs_inode_t	*ip;
 	int		error;
 	xfs_ino_t	ino;
 	unsigned int	igen;
-	xfs_mount_t	*mp;
 
-	xfid  = (struct xfs_fid *)fidp;
-	if (xfid->xfs_fid_len == sizeof(*xfid) - sizeof(xfid->xfs_fid_len)) {
-		ino  = xfid->xfs_fid_ino;
-		igen = xfid->xfs_fid_gen;
-	} else {
-		/*
-		 * Invalid.  Since handles can be created in user space
-		 * and passed in via gethandle(), this is not cause for
-		 * a panic.
-		 */
+	/*
+	 * Invalid.  Since handles can be created in user space and passed in
+	 * via gethandle(), this is not cause for a panic.
+	 */
+	if (xfid->xfs_fid_len != sizeof(*xfid) - sizeof(xfid->xfs_fid_len))
 		return XFS_ERROR(EINVAL);
-	}
-	mp = XFS_BHVTOM(bdp);
+
+	ino  = xfid->xfs_fid_ino;
+	igen = xfid->xfs_fid_gen;
+
+	/*
+	 * NFS can sometimes send requests for ino 0.  Fail them gracefully.
+	 */
+	if (ino == 0)
+		return XFS_ERROR(ESTALE);
+
 	error = xfs_iget(mp, NULL, ino, XFS_ILOCK_SHARED, &ip, 0);
 	if (error) {
 		*vpp = NULL;
 		return error;
 	}
+
 	if (ip == NULL) {
 		*vpp = NULL;
 		return XFS_ERROR(EIO);
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 05ab682c6..95fea44c4 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -283,7 +283,7 @@ xfs_getattr(
 /*
  * xfs_setattr
  */
-STATIC int
+int
 xfs_setattr(
 	bhv_desc_t		*bdp,
 	vattr_t			*vap,
@@ -305,6 +305,7 @@ xfs_setattr(
 	int			mandlock_before, mandlock_after;
 	struct xfs_dquot	*udqp, *gdqp, *olddquot1, *olddquot2;
 	int			file_owner;
+	int			need_iolock = (flags & ATTR_DMI) == 0;
 
 	vp = BHV_TO_VNODE(bdp);
 	vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
@@ -406,7 +407,8 @@ xfs_setattr(
 				goto error_return;
 			}
 		}
-		lock_flags |= XFS_IOLOCK_EXCL;
+		if (need_iolock)
+			lock_flags |= XFS_IOLOCK_EXCL;
 	}
 
 	xfs_ilock(ip, lock_flags);
@@ -678,7 +680,8 @@ xfs_setattr(
 					     XFS_TRANS_PERM_LOG_RES,
 					     XFS_ITRUNCATE_LOG_COUNT))) {
 			xfs_trans_cancel(tp, 0);
-			xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+			if (need_iolock)
+				xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 			return code;
 		}
 		commit_flags = XFS_TRANS_RELEASE_LOG_RES;
@@ -823,26 +826,38 @@ xfs_setattr(
 				mp->m_sb.sb_blocklog;
 		}
 		if (mask & XFS_AT_XFLAGS) {
-			ip->i_d.di_flags = 0;
-			if (vap->va_xflags & XFS_XFLAG_REALTIME) {
-				ip->i_d.di_flags |= XFS_DIFLAG_REALTIME;
-				ip->i_iocore.io_flags |= XFS_IOCORE_RT;
-			}
+			uint	di_flags;
+
+			/* can't set PREALLOC this way, just preserve it */
+			di_flags = (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC);
 			if (vap->va_xflags & XFS_XFLAG_IMMUTABLE)
-				ip->i_d.di_flags |= XFS_DIFLAG_IMMUTABLE;
+				di_flags |= XFS_DIFLAG_IMMUTABLE;
 			if (vap->va_xflags & XFS_XFLAG_IUNLINK)
-				ip->i_d.di_flags |= XFS_DIFLAG_IUNLINK;
+				di_flags |= XFS_DIFLAG_IUNLINK;
 			if (vap->va_xflags & XFS_XFLAG_BARRIER)
-				ip->i_d.di_flags |= XFS_DIFLAG_BARRIER;
+				di_flags |= XFS_DIFLAG_BARRIER;
 			if (vap->va_xflags & XFS_XFLAG_APPEND)
-				ip->i_d.di_flags |= XFS_DIFLAG_APPEND;
+				di_flags |= XFS_DIFLAG_APPEND;
 			if (vap->va_xflags & XFS_XFLAG_SYNC)
-				ip->i_d.di_flags |= XFS_DIFLAG_SYNC;
+				di_flags |= XFS_DIFLAG_SYNC;
 			if (vap->va_xflags & XFS_XFLAG_NOATIME)
-				ip->i_d.di_flags |= XFS_DIFLAG_NOATIME;
+				di_flags |= XFS_DIFLAG_NOATIME;
 			if (vap->va_xflags & XFS_XFLAG_NODUMP)
-				ip->i_d.di_flags |= XFS_DIFLAG_NODUMP;
-			/* can't set PREALLOC this way, just ignore it */
+				di_flags |= XFS_DIFLAG_NODUMP;
+			if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
+				if (vap->va_xflags & XFS_XFLAG_RTINHERIT)
+					di_flags |= XFS_DIFLAG_RTINHERIT;
+				if (vap->va_xflags & XFS_XFLAG_NOSYMLINKS)
+					di_flags |= XFS_DIFLAG_NOSYMLINKS;
+			} else {
+				if (vap->va_xflags & XFS_XFLAG_REALTIME) {
+					di_flags |= XFS_DIFLAG_REALTIME;
+					ip->i_iocore.io_flags |= XFS_IOCORE_RT;
+				} else {
+					ip->i_iocore.io_flags &= ~XFS_IOCORE_RT;
+				}
+			}
+			ip->i_d.di_flags = di_flags;
 		}
 		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 		timeflags |= XFS_ICHGTIME_CHG;
@@ -1600,7 +1615,7 @@ xfs_inactive(
 	 * If the inode is already free, then there can be nothing
 	 * to clean up here.
 	 */
-	if (ip->i_d.di_mode == 0) {
+	if (ip->i_d.di_mode == 0 || VN_BAD(vp)) {
 		ASSERT(ip->i_df.if_real_bytes == 0);
 		ASSERT(ip->i_df.if_broot_bytes == 0);
 		return VN_INACTIVE_CACHE;
@@ -1826,8 +1841,6 @@ xfs_lookup(
 }
 
 
-#define	XFS_CREATE_NEW_MAXTRIES	10000
-
 /*
  * xfs_create (create a new file).
  */
@@ -3385,6 +3398,14 @@ xfs_symlink(
 
 	xfs_ilock(dp, XFS_ILOCK_EXCL);
 
+	/*
+	 * Check whether the directory allows new symlinks or not.
+	 */
+	if (dp->i_d.di_flags & XFS_DIFLAG_NOSYMLINKS) {
+		error = XFS_ERROR(EPERM);
+		goto error_return;
+	}
+
 	/*
 	 * Reserve disk quota : blocks and inode.
 	 */
@@ -3791,11 +3812,17 @@ xfs_reclaim(
 	vnode_t		*vp;
 
 	vp = BHV_TO_VNODE(bdp);
+	ip = XFS_BHVTOI(bdp);
 
 	vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
 
 	ASSERT(!VN_MAPPED(vp));
-	ip = XFS_BHVTOI(bdp);
+
+	/* bad inode, get out here ASAP */
+	if (VN_BAD(vp)) {
+		xfs_ireclaim(ip);
+		return 0;
+	}
 
 	if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
 		if (ip->i_d.di_size > 0) {
@@ -3873,8 +3900,12 @@ xfs_finish_reclaim(
 	int		sync_mode)
 {
 	xfs_ihash_t	*ih = ip->i_hash;
+	vnode_t		*vp = XFS_ITOV_NULL(ip);
 	int		error;
 
+	if (vp && VN_BAD(vp))
+		return 0;
+
 	/* The hash lock here protects a thread in xfs_iget_core from
 	 * racing with us on linking the inode back with a vnode.
 	 * Once we have the XFS_IRECLAIM flag set it will not touch
@@ -3882,8 +3913,7 @@ xfs_finish_reclaim(
 	 */
 	write_lock(&ih->ih_lock);
 	if ((ip->i_flags & XFS_IRECLAIM) ||
-	    (!(ip->i_flags & XFS_IRECLAIMABLE) &&
-	      (XFS_ITOV_NULL(ip) == NULL))) {
+	    (!(ip->i_flags & XFS_IRECLAIMABLE) && vp == NULL)) {
 		write_unlock(&ih->ih_lock);
 		if (locked) {
 			xfs_ifunlock(ip);
@@ -3950,15 +3980,13 @@ int
 xfs_finish_reclaim_all(xfs_mount_t *mp, int noblock)
 {
 	int		purged;
-	struct list_head	*curr, *next;
-	xfs_inode_t	*ip;
+	xfs_inode_t	*ip, *n;
 	int		done = 0;
 
 	while (!done) {
 		purged = 0;
 		XFS_MOUNT_ILOCK(mp);
-		list_for_each_safe(curr, next, &mp->m_del_inodes) {
-			ip = list_entry(curr, xfs_inode_t, i_reclaim);
+		list_for_each_entry_safe(ip, n, &mp->m_del_inodes, i_reclaim) {
 			if (noblock) {
 				if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL) == 0)
 					continue;
@@ -4296,6 +4324,7 @@ xfs_free_file_space(
 	int			rt;
 	xfs_fileoff_t		startoffset_fsb;
 	xfs_trans_t		*tp;
+	int			need_iolock = (attr_flags & ATTR_DMI) == 0;
 
 	vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
 	mp = ip->i_mount;
@@ -4323,7 +4352,8 @@ xfs_free_file_space(
 			return(error);
 	}
 
-	xfs_ilock(ip, XFS_IOLOCK_EXCL);
+	if (need_iolock)
+		xfs_ilock(ip, XFS_IOLOCK_EXCL);
 	rounding = MAX((__uint8_t)(1 << mp->m_sb.sb_blocklog),
 			(__uint8_t)NBPP);
 	ilen = len + (offset & (rounding - 1));
@@ -4342,7 +4372,7 @@ xfs_free_file_space(
 		error = xfs_bmapi(NULL, ip, startoffset_fsb, 1, 0, NULL, 0,
 			&imap, &nimap, NULL);
 		if (error)
-			return error;
+			goto out_unlock_iolock;
 		ASSERT(nimap == 0 || nimap == 1);
 		if (nimap && imap.br_startblock != HOLESTARTBLOCK) {
 			xfs_daddr_t	block;
@@ -4357,7 +4387,7 @@ xfs_free_file_space(
 		error = xfs_bmapi(NULL, ip, endoffset_fsb - 1, 1, 0, NULL, 0,
 			&imap, &nimap, NULL);
 		if (error)
-			return error;
+			goto out_unlock_iolock;
 		ASSERT(nimap == 0 || nimap == 1);
 		if (nimap && imap.br_startblock != HOLESTARTBLOCK) {
 			ASSERT(imap.br_startblock != DELAYSTARTBLOCK);
@@ -4446,14 +4476,17 @@ xfs_free_file_space(
 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
 	}
 
-	xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+ out_unlock_iolock:
+	if (need_iolock)
+		xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 	return error;
 
  error0:
 	xfs_bmap_cancel(&free_list);
  error1:
 	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
-	xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
+	xfs_iunlock(ip, need_iolock ? (XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL) :
+		    XFS_ILOCK_EXCL);
 	return error;
 }
 
@@ -4610,20 +4643,21 @@ xfs_change_file_space(
 	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
 	xfs_trans_ihold(tp, ip);
 
-	ip->i_d.di_mode &= ~S_ISUID;
-
-	/*
-	 * Note that we don't have to worry about mandatory
-	 * file locking being disabled here because we only
-	 * clear the S_ISGID bit if the Group execute bit is
-	 * on, but if it was on then mandatory locking wouldn't
-	 * have been enabled.
-	 */
-	if (ip->i_d.di_mode & S_IXGRP)
-		ip->i_d.di_mode &= ~S_ISGID;
+	if ((attr_flags & ATTR_DMI) == 0) {
+		ip->i_d.di_mode &= ~S_ISUID;
 
-	xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+		/*
+		 * Note that we don't have to worry about mandatory
+		 * file locking being disabled here because we only
+		 * clear the S_ISGID bit if the Group execute bit is
+		 * on, but if it was on then mandatory locking wouldn't
+		 * have been enabled.
+		 */
+		if (ip->i_d.di_mode & S_IXGRP)
+			ip->i_d.di_mode &= ~S_ISGID;
 
+		xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
+	}
 	if (setprealloc)
 		ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC;
 	else if (clrprealloc)
diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h
index fa0c9b5d4..e4a0f1e6f 100644
--- a/include/acpi/acconfig.h
+++ b/include/acpi/acconfig.h
@@ -64,11 +64,21 @@
 
 /* Version string */
 
-#define ACPI_CA_VERSION                 0x20040326
+#define ACPI_CA_VERSION                 0x20040816
+
+/*
+ * OS name, used for the _OS object.  The _OS object is essentially obsolete,
+ * but there is a large base of ASL/AML code in existing machines that check
+ * for the string below.  The use of this string usually guarantees that
+ * the ASL will execute down the most tested code path.  Also, there is some
+ * code that will not execute the _OSI method unless _OS matches the string
+ * below.  Therefore, change this string at your own risk.
+ */
+#define ACPI_OS_NAME                    "Microsoft Windows NT"
 
 /* Maximum objects in the various object caches */
 
-#define ACPI_MAX_STATE_CACHE_DEPTH      64          /* State objects for stacks */
+#define ACPI_MAX_STATE_CACHE_DEPTH      64          /* State objects */
 #define ACPI_MAX_PARSE_CACHE_DEPTH      96          /* Parse tree objects */
 #define ACPI_MAX_EXTPARSE_CACHE_DEPTH   64          /* Parse tree objects */
 #define ACPI_MAX_OBJECT_CACHE_DEPTH     64          /* Interpreter operand objects */
@@ -152,10 +162,11 @@
 
 /* Constants used in searching for the RSDP in low memory */
 
-#define ACPI_LO_RSDP_WINDOW_BASE        0           /* Physical Address */
-#define ACPI_HI_RSDP_WINDOW_BASE        0xE0000     /* Physical Address */
-#define ACPI_LO_RSDP_WINDOW_SIZE        0x400
-#define ACPI_HI_RSDP_WINDOW_SIZE        0x20000
+#define ACPI_EBDA_PTR_LOCATION          0x0000040E     /* Physical Address */
+#define ACPI_EBDA_PTR_LENGTH            2
+#define ACPI_EBDA_WINDOW_SIZE           1024
+#define ACPI_HI_RSDP_WINDOW_BASE        0x000E0000     /* Physical Address */
+#define ACPI_HI_RSDP_WINDOW_SIZE        0x00020000
 #define ACPI_RSDP_SCAN_STEP             16
 
 /* Operation regions */
@@ -187,7 +198,7 @@
 
 /* Number of strings associated with the _OSI reserved method */
 
-#define ACPI_NUM_OSI_STRINGS            4
+#define ACPI_NUM_OSI_STRINGS            9
 
 
 /******************************************************************************
diff --git a/include/acpi/acdebug.h b/include/acpi/acdebug.h
index bb8411e89..658c5f505 100644
--- a/include/acpi/acdebug.h
+++ b/include/acpi/acdebug.h
@@ -106,6 +106,10 @@ acpi_db_method_end (
  * dbcmds - debug commands and output routines
  */
 
+acpi_status
+acpi_db_disassemble_method (
+	char                            *name);
+
 void
 acpi_db_display_table_info (
 	char                            *table_arg);
@@ -164,6 +168,10 @@ void
 acpi_db_set_scope (
 	char                            *name);
 
+acpi_status
+acpi_db_sleep (
+	char                            *object_arg);
+
 void
 acpi_db_find_references (
 	char                            *object_arg);
diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h
index 220bd1b35..67f6c5cfd 100644
--- a/include/acpi/acdisasm.h
+++ b/include/acpi/acdisasm.h
@@ -52,6 +52,13 @@
 #define BLOCK_BRACE             2
 #define BLOCK_COMMA_LIST        4
 
+struct acpi_external_list
+{
+	char                                *path;
+	struct acpi_external_list           *next;
+};
+
+extern struct acpi_external_list        *acpi_gbl_external_list;
 extern const char                       *acpi_gbl_io_decode[2];
 extern const char                       *acpi_gbl_word_decode[4];
 extern const char                       *acpi_gbl_consume_decode[2];
@@ -399,4 +406,12 @@ acpi_dm_vendor_small_descriptor (
 	u32                             level);
 
 
+/*
+ * dmutils
+ */
+
+void
+acpi_dm_add_to_external_list (
+	char                            *path);
+
 #endif  /* __ACDISASM_H__ */
diff --git a/include/acpi/acdispat.h b/include/acpi/acdispat.h
index 2a09e926c..e003a4f3f 100644
--- a/include/acpi/acdispat.h
+++ b/include/acpi/acdispat.h
@@ -437,8 +437,7 @@ acpi_ds_init_aml_walk (
 	struct acpi_namespace_node      *method_node,
 	u8                              *aml_start,
 	u32                             aml_length,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_obj_desc,
+	struct acpi_parameter_info      *info,
 	u32                             pass_number);
 
 acpi_status
diff --git a/include/acpi/acevents.h b/include/acpi/acevents.h
index 4ab99b2fd..124c392e4 100644
--- a/include/acpi/acevents.h
+++ b/include/acpi/acevents.h
@@ -46,11 +46,11 @@
 
 
 acpi_status
-acpi_ev_initialize (
+acpi_ev_initialize_events (
 	void);
 
 acpi_status
-acpi_ev_handler_initialize (
+acpi_ev_install_xrupt_handlers (
 	void);
 
 
@@ -111,12 +111,27 @@ acpi_ev_notify_dispatch (
 
 acpi_status
 acpi_ev_walk_gpe_list (
-	ACPI_GPE_CALLBACK       gpe_walk_callback);
+	ACPI_GPE_CALLBACK       gpe_walk_callback,
+	u32                             flags);
 
 u8
 acpi_ev_valid_gpe_event (
 	struct acpi_gpe_event_info      *gpe_event_info);
 
+acpi_status
+acpi_ev_update_gpe_enable_masks (
+	struct acpi_gpe_event_info      *gpe_event_info,
+	u8                              type);
+
+acpi_status
+acpi_ev_enable_gpe (
+	struct acpi_gpe_event_info      *gpe_event_info,
+	u8                              write_to_hardware);
+
+acpi_status
+acpi_ev_disable_gpe (
+	struct acpi_gpe_event_info      *gpe_event_info);
+
 struct acpi_gpe_event_info *
 acpi_ev_get_gpe_event_info (
 	acpi_handle                     gpe_device,
@@ -139,6 +154,11 @@ acpi_status
 acpi_ev_delete_gpe_block (
 	struct acpi_gpe_block_info      *gpe_block);
 
+acpi_status
+acpi_ev_delete_gpe_handlers (
+	struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
+	struct acpi_gpe_block_info      *gpe_block);
+
 u32
 acpi_ev_gpe_dispatch (
 	struct acpi_gpe_event_info      *gpe_event_info,
@@ -148,12 +168,25 @@ u32
 acpi_ev_gpe_detect (
 	struct acpi_gpe_xrupt_info      *gpe_xrupt_list);
 
+acpi_status
+acpi_ev_set_gpe_type (
+	struct acpi_gpe_event_info      *gpe_event_info,
+	u8                              type);
+
+acpi_status
+acpi_ev_check_for_wake_only_gpe (
+	struct acpi_gpe_event_info      *gpe_event_info);
+
 /*
  * Evregion - Address Space handling
  */
 
 acpi_status
-acpi_ev_init_address_spaces (
+acpi_ev_install_region_handlers (
+	void);
+
+acpi_status
+acpi_ev_initialize_op_regions (
 	void);
 
 acpi_status
@@ -182,6 +215,19 @@ acpi_ev_detach_region (
 	union acpi_operand_object      *region_obj,
 	u8                              acpi_ns_is_locked);
 
+acpi_status
+acpi_ev_install_space_handler (
+	struct acpi_namespace_node      *node,
+	acpi_adr_space_type             space_id,
+	acpi_adr_space_handler          handler,
+	acpi_adr_space_setup            setup,
+	void                            *context);
+
+acpi_status
+acpi_ev_execute_reg_methods (
+	struct acpi_namespace_node      *node,
+	acpi_adr_space_type             space_id);
+
 acpi_status
 acpi_ev_execute_reg_method (
 	union acpi_operand_object      *region_obj,
diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h
index 9441f5c1a..1022cc2da 100644
--- a/include/acpi/acexcep.h
+++ b/include/acpi/acexcep.h
@@ -95,8 +95,9 @@
 #define AE_LOGICAL_ADDRESS              (acpi_status) (0x001B | AE_CODE_ENVIRONMENTAL)
 #define AE_ABORT_METHOD                 (acpi_status) (0x001C | AE_CODE_ENVIRONMENTAL)
 #define AE_SAME_HANDLER                 (acpi_status) (0x001D | AE_CODE_ENVIRONMENTAL)
+#define AE_WAKE_ONLY_GPE                (acpi_status) (0x001E | AE_CODE_ENVIRONMENTAL)
 
-#define AE_CODE_ENV_MAX                 0x001D
+#define AE_CODE_ENV_MAX                 0x001E
 
 /*
  * Programmer exceptions
@@ -165,7 +166,7 @@
 #define AE_AML_CIRCULAR_REFERENCE       (acpi_status) (0x0020 | AE_CODE_AML)
 #define AE_AML_BAD_RESOURCE_LENGTH      (acpi_status) (0x0021 | AE_CODE_AML)
 
-#define AE_CODE_AML_MAX                 0x0020
+#define AE_CODE_AML_MAX                 0x0021
 
 /*
  * Internal exceptions used for control
@@ -222,7 +223,8 @@ char const   *acpi_gbl_exception_names_env[] =
 	"AE_NO_GLOBAL_LOCK",
 	"AE_LOGICAL_ADDRESS",
 	"AE_ABORT_METHOD",
-	"AE_SAME_HANDLER"
+	"AE_SAME_HANDLER",
+	"AE_WAKE_ONLY_GPE"
 };
 
 char const   *acpi_gbl_exception_names_pgm[] =
diff --git a/include/acpi/acglobal.h b/include/acpi/acglobal.h
index a19c6fc7a..eb16ee22e 100644
--- a/include/acpi/acglobal.h
+++ b/include/acpi/acglobal.h
@@ -46,15 +46,17 @@
 
 
 /*
- * Ensure that the globals are actually defined only once.
+ * Ensure that the globals are actually defined and initialized only once.
  *
- * The use of these defines allows a single list of globals (here) in order
+ * The use of these macros allows a single list of globals (here) in order
  * to simplify maintenance of the code.
  */
 #ifdef DEFINE_ACPI_GLOBALS
 #define ACPI_EXTERN
+#define ACPI_INIT_GLOBAL(a,b) a=b
 #else
 #define ACPI_EXTERN extern
+#define ACPI_INIT_GLOBAL(a,b) a
 #endif
 
 /*
@@ -64,6 +66,7 @@
 ACPI_EXTERN struct acpi_generic_address         acpi_gbl_xpm1a_enable;
 ACPI_EXTERN struct acpi_generic_address         acpi_gbl_xpm1b_enable;
 
+
 /*****************************************************************************
  *
  * Debug support
@@ -79,15 +82,42 @@ extern      u32                                 acpi_dbg_layer;
 
 extern      u32                                 acpi_gbl_nesting_level;
 
+
 /*****************************************************************************
  *
- * Runtime configuration
+ * Runtime configuration (static defaults that can be overriden at runtime)
  *
  ****************************************************************************/
 
-ACPI_EXTERN u8                                  acpi_gbl_create_osi_method;
-ACPI_EXTERN u8                                  acpi_gbl_all_methods_serialized;
-ACPI_EXTERN u8                                  acpi_gbl_leave_wake_gpes_disabled;
+/*
+ * Enable "slack" in the AML interpreter?  Default is FALSE, and the
+ * interpreter strictly follows the ACPI specification.  Setting to TRUE
+ * allows the interpreter to forgive certain bad AML constructs.
+ */
+ACPI_EXTERN u8       ACPI_INIT_GLOBAL (acpi_gbl_enable_interpreter_slack, FALSE);
+
+/*
+ * Automatically serialize ALL control methods? Default is FALSE, meaning
+ * to use the Serialized/not_serialized method flags on a per method basis.
+ * Only change this if the ASL code is poorly written and cannot handle
+ * reentrancy even though methods are marked "not_serialized".
+ */
+ACPI_EXTERN u8       ACPI_INIT_GLOBAL (acpi_gbl_all_methods_serialized, FALSE);
+
+/*
+ * Create the predefined _OSI method in the namespace? Default is TRUE
+ * because ACPI CA is fully compatible with other ACPI implementations.
+ * Changing this will revert ACPI CA (and machine ASL) to pre-OSI behavior.
+ */
+ACPI_EXTERN u8       ACPI_INIT_GLOBAL (acpi_gbl_create_osi_method, TRUE);
+
+/*
+ * Disable wakeup GPEs during runtime? Default is TRUE because WAKE and
+ * RUNTIME GPEs should never be shared, and WAKE GPEs should typically only
+ * be enabled just before going to sleep.
+ */
+ACPI_EXTERN u8       ACPI_INIT_GLOBAL (acpi_gbl_leave_wake_gpes_disabled, TRUE);
+
 
 /*****************************************************************************
  *
@@ -102,7 +132,6 @@ ACPI_EXTERN u8                                  acpi_gbl_leave_wake_gpes_disable
  *
  * These tables are single-table only; meaning that there can be at most one
  * of each in the system.  Each global points to the actual table.
- *
  */
 ACPI_EXTERN u32                                 acpi_gbl_table_flags;
 ACPI_EXTERN u32                                 acpi_gbl_rsdt_table_count;
@@ -170,6 +199,7 @@ ACPI_EXTERN u8                                  acpi_gbl_step_to_next_call;
 ACPI_EXTERN u8                                  acpi_gbl_acpi_hardware_present;
 ACPI_EXTERN u8                                  acpi_gbl_global_lock_present;
 ACPI_EXTERN u8                                  acpi_gbl_events_initialized;
+ACPI_EXTERN u8                                  acpi_gbl_system_awake_and_running;
 
 extern u8                                       acpi_gbl_shutdown;
 extern u32                                      acpi_gbl_startup_flags;
diff --git a/include/acpi/achware.h b/include/acpi/achware.h
index 2281f27ea..cf55493dc 100644
--- a/include/acpi/achware.h
+++ b/include/acpi/achware.h
@@ -114,15 +114,7 @@ acpi_hw_clear_acpi_status (
 /* GPE support */
 
 acpi_status
-acpi_hw_enable_gpe (
-	struct acpi_gpe_event_info      *gpe_event_info);
-
-void
-acpi_hw_enable_gpe_for_wakeup (
-	struct acpi_gpe_event_info      *gpe_event_info);
-
-acpi_status
-acpi_hw_disable_gpe (
+acpi_hw_write_gpe_enable_reg (
 	struct acpi_gpe_event_info      *gpe_event_info);
 
 acpi_status
@@ -130,10 +122,6 @@ acpi_hw_disable_gpe_block (
 	struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
 	struct acpi_gpe_block_info      *gpe_block);
 
-void
-acpi_hw_disable_gpe_for_wakeup (
-	struct acpi_gpe_event_info      *gpe_event_info);
-
 acpi_status
 acpi_hw_clear_gpe (
 	struct acpi_gpe_event_info      *gpe_event_info);
@@ -149,12 +137,26 @@ acpi_hw_get_gpe_status (
 	acpi_event_status               *event_status);
 
 acpi_status
-acpi_hw_prepare_gpes_for_sleep (
-	void);
+acpi_hw_disable_all_gpes (
+	u32                             flags);
 
 acpi_status
-acpi_hw_restore_gpes_on_wake (
-	void);
+acpi_hw_enable_all_runtime_gpes (
+	u32                             flags);
+
+acpi_status
+acpi_hw_enable_all_wakeup_gpes (
+	u32                             flags);
+
+acpi_status
+acpi_hw_enable_runtime_gpe_block (
+	struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
+	struct acpi_gpe_block_info      *gpe_block);
+
+acpi_status
+acpi_hw_enable_wakeup_gpe_block (
+	struct acpi_gpe_xrupt_info      *gpe_xrupt_info,
+	struct acpi_gpe_block_info      *gpe_block);
 
 
 /* ACPI Timer prototypes */
diff --git a/include/acpi/acinterp.h b/include/acpi/acinterp.h
index 0bcb194c0..a43e91fb9 100644
--- a/include/acpi/acinterp.h
+++ b/include/acpi/acinterp.h
@@ -117,6 +117,12 @@ acpi_ex_convert_to_ascii (
  * exfield - ACPI AML (p-code) execution - field manipulation
  */
 
+acpi_status
+acpi_ex_common_buffer_setup (
+	union acpi_operand_object       *obj_desc,
+	u32                             buffer_length,
+	u32                             *datum_count);
+
 acpi_status
 acpi_ex_extract_from_field (
 	union acpi_operand_object       *obj_desc,
@@ -240,8 +246,8 @@ acpi_ex_do_concatenate (
 u8
 acpi_ex_do_logical_op (
 	u16                             opcode,
-	acpi_integer                    operand0,
-	acpi_integer                    operand1);
+	union acpi_operand_object       *obj_desc,
+	union acpi_operand_object       *obj_desc2);
 
 acpi_integer
 acpi_ex_do_math_op (
@@ -563,8 +569,11 @@ acpi_status
 acpi_ex_store_object_to_node (
 	union acpi_operand_object       *source_desc,
 	struct acpi_namespace_node      *node,
-	struct acpi_walk_state          *walk_state);
+	struct acpi_walk_state          *walk_state,
+	u8                              implicit_conversion);
 
+#define ACPI_IMPLICIT_CONVERSION        TRUE
+#define ACPI_NO_IMPLICIT_CONVERSION     FALSE
 
 /*
  * exstoren
diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h
index eb1b957ed..2afff1148 100644
--- a/include/acpi/aclocal.h
+++ b/include/acpi/aclocal.h
@@ -189,8 +189,6 @@ struct acpi_namespace_node
 	u8                                  type;           /* Type associated with this name */
 	u16                                 owner_id;
 	union acpi_name_union               name;           /* ACPI Name, always 4 chars per ACPI spec */
-
-
 	union acpi_operand_object           *object;        /* Pointer to attached ACPI object (optional) */
 	struct acpi_namespace_node          *child;         /* First child */
 	struct acpi_namespace_node          *peer;          /* Next peer*/
@@ -211,10 +209,8 @@ struct acpi_namespace_node
 #define ANOBJ_METHOD_LOCAL              0x10
 #define ANOBJ_METHOD_NO_RETVAL          0x20
 #define ANOBJ_METHOD_SOME_NO_RETVAL     0x40
-
 #define ANOBJ_IS_BIT_OFFSET             0x80
 
-
 /*
  * ACPI Table Descriptor.  One per ACPI table
  */
@@ -309,16 +305,31 @@ struct acpi_create_field_info
  *
  ****************************************************************************/
 
-/* Information about a GPE, one per each GPE in an array */
+/* Dispatch info for each GPE -- either a method or handler, cannot be both */
 
-struct acpi_gpe_event_info
+struct acpi_handler_info
 {
-	struct acpi_namespace_node              *method_node;   /* Method node for this GPE level */
-	acpi_gpe_handler                        handler;        /* Address of handler, if any */
+	acpi_event_handler                      address;        /* Address of handler, if any */
 	void                                    *context;       /* Context to be passed to handler */
+	struct acpi_namespace_node              *method_node;   /* Method node for this GPE level (saved) */
+};
+
+union acpi_gpe_dispatch_info
+{
+	struct acpi_namespace_node              *method_node;   /* Method node for this GPE level */
+	struct acpi_handler_info                *handler;
+};
+
+/*
+ * Information about a GPE, one per each GPE in an array.
+ * NOTE: Important to keep this struct as small as possible.
+ */
+struct acpi_gpe_event_info
+{
+	union acpi_gpe_dispatch_info    dispatch;       /* Either Method or Handler */
 	struct acpi_gpe_register_info           *register_info; /* Backpointer to register info */
-	u8                                      flags;          /* Level or Edge */
-	u8                                      bit_mask;       /* This GPE within the register */
+	u8                                      flags;          /* Misc info about this GPE */
+	u8                                      register_bit;   /* This GPE bit within the register */
 };
 
 /* Information about a GPE register pair, one per each status/enable pair in an array */
@@ -327,9 +338,8 @@ struct acpi_gpe_register_info
 {
 	struct acpi_generic_address             status_address; /* Address of status reg */
 	struct acpi_generic_address             enable_address; /* Address of enable reg */
-	u8                                      status;         /* Current value of status reg */
-	u8                                      enable;         /* Current value of enable reg */
-	u8                                      wake_enable;    /* Mask of bits to keep enabled when sleeping */
+	u8                                      enable_for_wake; /* GPEs to keep enabled when sleeping */
+	u8                                      enable_for_run; /* GPEs to keep enabled when running */
 	u8                                      base_gpe_number; /* Base GPE number for this register */
 };
 
@@ -339,6 +349,7 @@ struct acpi_gpe_register_info
  */
 struct acpi_gpe_block_info
 {
+	struct acpi_namespace_node              *node;
 	struct acpi_gpe_block_info              *previous;
 	struct acpi_gpe_block_info              *next;
 	struct acpi_gpe_xrupt_info              *xrupt_block;   /* Backpointer to interrupt block */
@@ -502,7 +513,7 @@ struct acpi_thread_state
 	struct acpi_walk_state              *walk_state_list;       /* Head of list of walk_states for this thread */
 	union acpi_operand_object           *acquired_mutex_list;   /* List of all currently acquired mutexes */
 	u32                                 thread_id;              /* Running thread ID */
-	u16                                 current_sync_level;     /* Mutex Sync (nested acquire) level */
+	u8                                  current_sync_level;     /* Mutex Sync (nested acquire) level */
 };
 
 
diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h
index 245bc0bc5..43c474ab8 100644
--- a/include/acpi/acmacros.h
+++ b/include/acpi/acmacros.h
@@ -53,6 +53,9 @@
 #define ACPI_LOBYTE(l)                  ((u8)(u16)(l))
 #define ACPI_HIBYTE(l)                  ((u8)((((u16)(l)) >> 8) & 0xFF))
 
+#define ACPI_SET_BIT(target,bit)        ((target) |= (bit))
+#define ACPI_CLEAR_BIT(target,bit)      ((target) &= ~(bit))
+
 
 #if ACPI_MACHINE_WIDTH == 16
 
@@ -97,7 +100,7 @@
  * printf() format helpers
  */
 
-/* Split 64-bit integer into two 32-bit values. use with %8,8_x%8.8X */
+/* Split 64-bit integer into two 32-bit values. Use with %8.8X%8.8X */
 
 #define ACPI_FORMAT_UINT64(i)           ACPI_HIDWORD(i),ACPI_LODWORD(i)
 
@@ -361,24 +364,6 @@
 
 #define ACPI_IS_OCTAL_DIGIT(d)               (((char)(d) >= '0') && ((char)(d) <= '7'))
 
-/* Macros for GAS addressing */
-
-#if ACPI_MACHINE_WIDTH != 16
-
-#define ACPI_PCI_DEVICE(a)              (u16) ((ACPI_HIDWORD ((a))) & 0x0000FFFF)
-#define ACPI_PCI_FUNCTION(a)            (u16) ((ACPI_LODWORD ((a))) >> 16)
-#define ACPI_PCI_REGISTER(a)            (u16) ((ACPI_LODWORD ((a))) & 0x0000FFFF)
-
-#else
-
-/* No support for GAS and PCI IDs in 16-bit mode  */
-
-#define ACPI_PCI_FUNCTION(a)            (u16) ((a) & 0xFFFF0000)
-#define ACPI_PCI_DEVICE(a)              (u16) ((a) & 0x0000FFFF)
-#define ACPI_PCI_REGISTER(a)            (u16) ((a) & 0x0000FFFF)
-
-#endif
-
 
 /* Bitfields within ACPI registers */
 
diff --git a/include/acpi/acnamesp.h b/include/acpi/acnamesp.h
index de54ba7ba..8cfd1afba 100644
--- a/include/acpi/acnamesp.h
+++ b/include/acpi/acnamesp.h
@@ -278,33 +278,25 @@ acpi_ns_dump_objects (
 
 acpi_status
 acpi_ns_evaluate_by_handle (
-	struct acpi_namespace_node      *prefix_node,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_object);
+	struct acpi_parameter_info      *info);
 
 acpi_status
 acpi_ns_evaluate_by_name (
 	char                            *pathname,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_object);
+	struct acpi_parameter_info      *info);
 
 acpi_status
 acpi_ns_evaluate_relative (
-	struct acpi_namespace_node      *prefix_node,
 	char                            *pathname,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_object);
+	struct acpi_parameter_info      *info);
 
 acpi_status
 acpi_ns_execute_control_method (
-	struct acpi_namespace_node      *method_node,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_obj_desc);
+	struct acpi_parameter_info      *info);
 
 acpi_status
 acpi_ns_get_object_value (
-	struct acpi_namespace_node      *object_node,
-	union acpi_operand_object       **return_obj_desc);
+	struct acpi_parameter_info      *info);
 
 
 /*
diff --git a/include/acpi/acobject.h b/include/acpi/acobject.h
index 51abddaf1..0d479722f 100644
--- a/include/acpi/acobject.h
+++ b/include/acpi/acobject.h
@@ -204,13 +204,14 @@ struct acpi_object_method
 struct acpi_object_mutex
 {
 	ACPI_OBJECT_COMMON_HEADER
-	u16                                     sync_level;
-	u16                                     acquisition_depth;
-	struct acpi_thread_state                *owner_thread;
-	void                                    *semaphore;
+	u8                                      sync_level;         /* 0-15, specified in Mutex() call */
+	u16                                     acquisition_depth;  /* Allow multiple Acquires, same thread */
+	struct acpi_thread_state                *owner_thread;      /* Current owner of the mutex */
+	void                                    *semaphore;         /* Actual OS synchronization object */
 	union acpi_operand_object               *prev;              /* Link for list of acquired mutexes */
 	union acpi_operand_object               *next;              /* Link for list of acquired mutexes */
-	struct acpi_namespace_node              *node;              /* containing object */
+	struct acpi_namespace_node              *node;              /* Containing namespace node */
+	u8                                      original_sync_level; /* Owner's original sync level (0-15) */
 };
 
 
@@ -220,7 +221,7 @@ struct acpi_object_region
 
 	u8                                      space_id;
 	union acpi_operand_object               *handler;           /* Handler for region access */
-	struct acpi_namespace_node              *node;              /* containing object */
+	struct acpi_namespace_node              *node;              /* Containing namespace node */
 	union acpi_operand_object               *next;
 	u32                                     length;
 	acpi_physical_address                   address;
diff --git a/include/acpi/acparser.h b/include/acpi/acparser.h
index 562e66002..42cc5b4d3 100644
--- a/include/acpi/acparser.h
+++ b/include/acpi/acparser.h
@@ -73,9 +73,7 @@ acpi_psx_load_table (
 
 acpi_status
 acpi_psx_execute (
-	struct acpi_namespace_node      *method_node,
-	union acpi_operand_object       **params,
-	union acpi_operand_object       **return_obj_desc);
+	struct acpi_parameter_info      *info);
 
 
 /******************************************************************************
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index af33ae5a2..86513a0fd 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -157,7 +157,8 @@ struct acpi_device_flags {
 	u32			suprise_removal_ok:1;
 	u32			power_manageable:1;
 	u32			performance_manageable:1;
-	u32			reserved:21;
+	u32			wake_capable:1; /* Wakeup(_PRW) supported? */
+	u32			reserved:20;
 };
 
 
@@ -203,10 +204,8 @@ struct acpi_device_power_flags {
 	u32			explicit_get:1;		     /* _PSC present? */
 	u32			power_resources:1;	   /* Power resources */
 	u32			inrush_current:1;	  /* Serialize Dx->D0 */
-	u32			wake_capable:1;		 /* Wakeup supported? */
-	u32			wake_enabled:1;		/* Enabled for wakeup */
 	u32			power_removed:1;	   /* Optimize Dx->D0 */
-	u32			reserved:26;
+	u32			reserved:28;
 };
 
 struct acpi_device_power_state {
@@ -250,6 +249,25 @@ struct acpi_device_perf {
 	struct acpi_device_perf_state *states;
 };
 
+/* Wakeup Management */
+struct acpi_device_wakeup_flags {
+	u8	valid:1; /* Can successfully enable wakeup? */
+	u8	run_wake:1; /* Run-Wake GPE devices */
+};
+
+struct acpi_device_wakeup_state {
+	u8	enabled:1;
+	u8	active:1;
+};
+
+struct acpi_device_wakeup {
+	acpi_handle		gpe_device;
+	acpi_integer		gpe_number;;
+	acpi_integer		sleep_state;
+	struct acpi_handle_list	resources;
+	struct acpi_device_wakeup_state	state;
+	struct acpi_device_wakeup_flags	flags;
+};
 
 /* Device */
 
@@ -258,11 +276,13 @@ struct acpi_device {
 	struct acpi_device	*parent;
 	struct list_head	children;
 	struct list_head	node;
+	struct list_head	wakeup_list;
 	struct list_head	g_list;
 	struct acpi_device_status status;
 	struct acpi_device_flags flags;
 	struct acpi_device_pnp	pnp;
 	struct acpi_device_power power;
+	struct acpi_device_wakeup wakeup;
 	struct acpi_device_perf	performance;
 	struct acpi_device_dir	dir;
 	struct acpi_device_ops	ops;
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index c4d9a8ebb..09097bb3e 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -81,7 +81,8 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_device *device, int domain, int b
    -------------------------------------------------------------------------- */
 
 #ifdef CONFIG_ACPI_POWER
-
+int acpi_enable_wakeup_device_power (struct acpi_device *dev);
+int acpi_disable_wakeup_device_power (struct acpi_device *dev);
 int acpi_power_get_inferred_state (struct acpi_device *device);
 int acpi_power_transition (struct acpi_device *device, int state);
 #endif
@@ -105,59 +106,4 @@ int acpi_ec_ecdt_probe (void);
 int acpi_processor_set_thermal_limit(acpi_handle handle, int type);
 
 
-/* --------------------------------------------------------------------------
-                                Debug Support
-   -------------------------------------------------------------------------- */
-
-#define ACPI_DEBUG_RESTORE	0
-#define ACPI_DEBUG_LOW		1
-#define ACPI_DEBUG_MEDIUM	2
-#define ACPI_DEBUG_HIGH		3
-#define ACPI_DEBUG_DRIVERS	4
-
-extern u32 acpi_dbg_level;
-extern u32 acpi_dbg_layer;
-
-static inline void
-acpi_set_debug (
-	u32			flag)
-{
-	static u32		layer_save;
-	static u32		level_save;
-
-	switch (flag) {
-	case ACPI_DEBUG_RESTORE:
-		acpi_dbg_layer = layer_save;
-		acpi_dbg_level = level_save;
-		break;
-	case ACPI_DEBUG_LOW:
-	case ACPI_DEBUG_MEDIUM:
-	case ACPI_DEBUG_HIGH:
-	case ACPI_DEBUG_DRIVERS:
-		layer_save = acpi_dbg_layer;
-		level_save = acpi_dbg_level;
-		break;
-	}
-
-	switch (flag) {
-	case ACPI_DEBUG_LOW:
-		acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS;
-		acpi_dbg_level = ACPI_DEBUG_DEFAULT;
-		break;
-	case ACPI_DEBUG_MEDIUM:
-		acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS;
-		acpi_dbg_level = ACPI_LV_FUNCTIONS | ACPI_LV_ALL_EXCEPTIONS;
-		break;
-	case ACPI_DEBUG_HIGH:
-		acpi_dbg_layer = 0xFFFFFFFF;
-		acpi_dbg_level = 0xFFFFFFFF;
-		break;
-	case ACPI_DEBUG_DRIVERS:
-		acpi_dbg_layer = ACPI_ALL_DRIVERS;
-		acpi_dbg_level = 0xFFFFFFFF;
-		break;
-	}
-}
-
-
 #endif /*__ACPI_DRIVERS_H__*/
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 243727d03..a76c952f8 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -169,11 +169,11 @@ acpi_status
 acpi_os_map_memory (
 	acpi_physical_address           physical_address,
 	acpi_size                       size,
-	void                            **logical_address);
+	void __iomem                  **logical_address);
 
 void
 acpi_os_unmap_memory (
-	void                            *logical_address,
+	void __iomem                  *logical_address,
 	acpi_size                       size);
 
 acpi_status
@@ -189,13 +189,13 @@ acpi_os_get_physical_address (
 acpi_status
 acpi_os_install_interrupt_handler (
 	u32                             gsi,
-	OSD_HANDLER                     service_routine,
+	acpi_osd_handler                service_routine,
 	void                            *context);
 
 acpi_status
 acpi_os_remove_interrupt_handler (
-	u32                             interrupt_number,
-	OSD_HANDLER                     service_routine);
+	u32                             gsi,
+	acpi_osd_handler                service_routine);
 
 
 /*
@@ -209,7 +209,7 @@ acpi_os_get_thread_id (
 acpi_status
 acpi_os_queue_for_execution (
 	u32                             priority,
-	OSD_EXECUTION_CALLBACK  function,
+	acpi_osd_exec_callback          function,
 	void                            *context);
 
 void
@@ -262,25 +262,28 @@ acpi_os_write_memory (
 
 /*
  * Platform and hardware-independent PCI configuration space access
+ * Note: Can't use "Register" as a parameter, changed to "Reg" --
+ * certain compilers complain.
  */
 
 acpi_status
 acpi_os_read_pci_configuration (
 	struct acpi_pci_id              *pci_id,
-	u32                             register,
+	u32                             reg,
 	void                            *value,
 	u32                             width);
 
 acpi_status
 acpi_os_write_pci_configuration (
 	struct acpi_pci_id              *pci_id,
-	u32                             register,
+	u32                             reg,
 	acpi_integer                    value,
 	u32                             width);
 
 /*
  * Interim function needed for PCI IRQ routing
  */
+
 void
 acpi_os_derive_pci_id(
 	acpi_handle                     rhandle,
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index e53a91867..54ae84dcf 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -296,7 +296,7 @@ acpi_install_gpe_handler (
 	acpi_handle                     gpe_device,
 	u32                             gpe_number,
 	u32                             type,
-	acpi_gpe_handler                handler,
+	acpi_event_handler              address,
 	void                            *context);
 
 acpi_status
@@ -312,7 +312,7 @@ acpi_status
 acpi_remove_gpe_handler (
 	acpi_handle                     gpe_device,
 	u32                             gpe_number,
-	acpi_gpe_handler                handler);
+	acpi_event_handler              address);
 
 acpi_status
 acpi_enable_event (
@@ -333,6 +333,12 @@ acpi_get_event_status (
 	u32                             event,
 	acpi_event_status               *event_status);
 
+acpi_status
+acpi_set_gpe_type (
+	acpi_handle                     gpe_device,
+	u32                             gpe_number,
+	u8                              type);
+
 acpi_status
 acpi_enable_gpe (
 	acpi_handle                     gpe_device,
diff --git a/include/acpi/acstruct.h b/include/acpi/acstruct.h
index 56a3782cd..e9a2b32e6 100644
--- a/include/acpi/acstruct.h
+++ b/include/acpi/acstruct.h
@@ -69,13 +69,14 @@
 struct acpi_walk_state
 {
 	u8                                  data_type;                          /* To differentiate various internal objs MUST BE FIRST!*/\
+	u8                                  walk_type;
 	acpi_owner_id                       owner_id;                           /* Owner of objects created during the walk */
 	u8                                  last_predicate;                     /* Result of last predicate */
+	u8                                  reserved;                           /* For alignment */
 	u8                                  current_result;                     /* */
 	u8                                  next_op_info;                       /* Info about next_op */
 	u8                                  num_operands;                       /* Stack pointer for Operands[] array */
 	u8                                  return_used;
-	u8                                  walk_type;
 	u16                                 opcode;                             /* Current AML opcode */
 	u8                                  scope_depth;
 	u8                                  reserved1;
@@ -91,7 +92,8 @@ struct acpi_walk_state
 	struct acpi_namespace_node          arguments[ACPI_METHOD_NUM_ARGS];    /* Control method arguments */
 	union acpi_operand_object           **caller_return_desc;
 	union acpi_generic_state            *control_state;                     /* List of control states (nested IFs) */
-	struct acpi_namespace_node          *deferred_node;                      /* Used when executing deferred opcodes */
+	struct acpi_namespace_node          *deferred_node;                     /* Used when executing deferred opcodes */
+	struct acpi_gpe_event_info          *gpe_event_info;                    /* Info for GPE (_Lxx/_Exx methods only */
 	struct acpi_namespace_node          local_variables[ACPI_METHOD_NUM_LOCALS];    /* Control method locals */
 	struct acpi_namespace_node          *method_call_node;                  /* Called method Node*/
 	union acpi_parse_object             *method_call_op;                    /* method_call Op if running a method */
@@ -200,4 +202,21 @@ union acpi_aml_operands
 };
 
 
+/* Internal method parameter list */
+
+struct acpi_parameter_info
+{
+	struct acpi_namespace_node      *node;
+	union acpi_operand_object       **parameters;
+	union acpi_operand_object       *return_object;
+	u8                              parameter_type;
+	u8                              return_object_type;
+};
+
+/* Types for parameter_type above */
+
+#define ACPI_PARAM_ARGS                 0
+#define ACPI_PARAM_GPE                  1
+
+
 #endif
diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h
index 55680ad34..b380c2358 100644
--- a/include/acpi/actbl.h
+++ b/include/acpi/actbl.h
@@ -288,19 +288,6 @@ struct smart_battery_table
 };
 
 
-/*
- * High performance timer
- */
-struct hpet_table
-{
-	ACPI_TABLE_HEADER_DEF
-	u32                             hardware_id;
-	u32                             base_address [3];
-	u8                              hpet_number;
-	u16                             clock_tick;
-	u8                              attributes;
-};
-
 #pragma pack()
 
 
@@ -344,4 +331,20 @@ struct acpi_table_support
 #include "actbl2.h"   /* Acpi 2.0 table definitions */
 
 
+#pragma pack(1)
+/*
+ * High performance timer
+ */
+struct hpet_table
+{
+	ACPI_TABLE_HEADER_DEF
+	u32                             hardware_id;
+	struct acpi_generic_address     base_address;
+	u8                              hpet_number;
+	u16                             clock_tick;
+	u8                              attributes;
+};
+
+#pragma pack()
+
 #endif /* __ACTBL_H__ */
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index e6120c879..8bee457d8 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -557,34 +557,56 @@ typedef u32                                     acpi_event_status;
 #define ACPI_GPE_MAX                    0xFF
 #define ACPI_NUM_GPE                    256
 
+#define ACPI_GPE_ENABLE                 0
+#define ACPI_GPE_DISABLE                1
+
+
 /*
  * GPE info flags - Per GPE
- * +---------+-+-+-+
- * |Bits 8:3 |2|1|0|
- * +---------+-+-+-+
- *          | | | |
- *          | | | +- Edge or Level Triggered
- *          | | +--- Type: Wake or Runtime
- *          | +----- Enabled for wake?
- *          +--------<Reserved>
+ * +-+-+-+---+---+-+
+ * |7|6|5|4:3|2:1|0|
+ * +-+-+-+---+---+-+
+ *  | | |  |   |  |
+ *  | | |  |   |  +--- Interrupt type: Edge or Level Triggered
+ *  | | |  |   +--- Type: Wake-only, Runtime-only, or wake/runtime
+ *  | | |  +--- Type of dispatch -- to method, handler, or none
+ *  | | +--- Enabled for runtime?
+ *  | +--- Enabled for wake?
+ *  +--- System state when GPE ocurred (running/waking)
  */
-#define ACPI_GPE_XRUPT_TYPE_MASK        (u8) 1
-#define ACPI_GPE_LEVEL_TRIGGERED        (u8) 1
-#define ACPI_GPE_EDGE_TRIGGERED         (u8) 0
+#define ACPI_GPE_XRUPT_TYPE_MASK        (u8) 0x01
+#define ACPI_GPE_LEVEL_TRIGGERED        (u8) 0x01
+#define ACPI_GPE_EDGE_TRIGGERED         (u8) 0x00
+
+#define ACPI_GPE_TYPE_MASK              (u8) 0x06
+#define ACPI_GPE_TYPE_WAKE_RUN          (u8) 0x06
+#define ACPI_GPE_TYPE_WAKE              (u8) 0x02
+#define ACPI_GPE_TYPE_RUNTIME           (u8) 0x04    /* Default */
+
+#define ACPI_GPE_DISPATCH_MASK          (u8) 0x18
+#define ACPI_GPE_DISPATCH_HANDLER       (u8) 0x08
+#define ACPI_GPE_DISPATCH_METHOD        (u8) 0x10
+#define ACPI_GPE_DISPATCH_NOT_USED      (u8) 0x00    /* Default */
+
+#define ACPI_GPE_RUN_ENABLE_MASK        (u8) 0x20
+#define ACPI_GPE_RUN_ENABLED            (u8) 0x20
+#define ACPI_GPE_RUN_DISABLED           (u8) 0x00    /* Default */
 
-#define ACPI_GPE_TYPE_MASK              (u8) 2
-#define ACPI_GPE_TYPE_WAKE              (u8) 2
-#define ACPI_GPE_TYPE_RUNTIME           (u8) 0       /* Default */
+#define ACPI_GPE_WAKE_ENABLE_MASK       (u8) 0x40
+#define ACPI_GPE_WAKE_ENABLED           (u8) 0x40
+#define ACPI_GPE_WAKE_DISABLED          (u8) 0x00    /* Default */
 
-#define ACPI_GPE_ENABLE_MASK            (u8) 4
-#define ACPI_GPE_ENABLED                (u8) 4
-#define ACPI_GPE_DISABLED               (u8) 0       /* Default */
+#define ACPI_GPE_ENABLE_MASK            (u8) 0x60    /* Both run/wake */
+
+#define ACPI_GPE_SYSTEM_MASK            (u8) 0x80
+#define ACPI_GPE_SYSTEM_RUNNING         (u8) 0x80
+#define ACPI_GPE_SYSTEM_WAKING          (u8) 0x00
 
 /*
  * Flags for GPE and Lock interfaces
  */
-#define ACPI_EVENT_WAKE_ENABLE          0x2
-#define ACPI_EVENT_WAKE_DISABLE         0x2
+#define ACPI_EVENT_WAKE_ENABLE          0x2             /* acpi_gpe_enable */
+#define ACPI_EVENT_WAKE_DISABLE         0x2             /* acpi_gpe_disable */
 
 #define ACPI_NOT_ISR                    0x1
 #define ACPI_ISR                        0x0
@@ -592,9 +614,10 @@ typedef u32                                     acpi_event_status;
 
 /* Notify types */
 
-#define ACPI_SYSTEM_NOTIFY              0
-#define ACPI_DEVICE_NOTIFY              1
-#define ACPI_MAX_NOTIFY_HANDLER_TYPE    1
+#define ACPI_SYSTEM_NOTIFY              0x1
+#define ACPI_DEVICE_NOTIFY              0x2
+#define ACPI_ALL_NOTIFY                 0x3
+#define ACPI_MAX_NOTIFY_HANDLER_TYPE    0x3
 
 #define ACPI_MAX_SYS_NOTIFY             0x7f
 
@@ -775,11 +798,11 @@ struct acpi_system_info
  */
 
 typedef u32
-(ACPI_SYSTEM_XFACE *OSD_HANDLER) (
+(ACPI_SYSTEM_XFACE *acpi_osd_handler) (
 	void                            *context);
 
 typedef void
-(ACPI_SYSTEM_XFACE *OSD_EXECUTION_CALLBACK) (
+(ACPI_SYSTEM_XFACE *acpi_osd_exec_callback) (
 	void                            *context);
 
 /*
@@ -789,10 +812,6 @@ typedef
 u32 (*acpi_event_handler) (
 	void                                *context);
 
-typedef
-void (*acpi_gpe_handler) (
-	void                                *context);
-
 typedef
 void (*acpi_notify_handler) (
 	acpi_handle                         device,
@@ -880,6 +899,7 @@ struct acpi_compatible_id_list
 #define ACPI_VALID_HID                  0x0004
 #define ACPI_VALID_UID                  0x0008
 #define ACPI_VALID_CID                  0x0010
+#define ACPI_VALID_SXDS                 0x0020
 
 
 #define ACPI_COMMON_OBJ_INFO \
@@ -899,12 +919,12 @@ struct acpi_device_info
 {
 	ACPI_COMMON_OBJ_INFO;
 
-	u8                                  highest_dstates[4]; /* _sx_d values 0xFF indicates not valid */
 	u32                                 valid;              /* Indicates which fields below are valid */
 	u32                                 current_status;     /* _STA value */
 	acpi_integer                        address;            /* _ADR value if any */
 	struct acpi_device_id               hardware_id;        /* _HID value if any */
 	struct acpi_device_id               unique_id;          /* _UID value if any */
+	u8                                  highest_dstates[4]; /* _sx_d values: 0xFF indicates not valid */
 	struct acpi_compatible_id_list      compatibility_id;   /* List of _CIDs if any */
 };
 
diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h
index 9a0cd4108..7964aaf6b 100644
--- a/include/acpi/platform/acenv.h
+++ b/include/acpi/platform/acenv.h
@@ -152,12 +152,8 @@
 #define COMPILER_DEPENDENT_INT64   long long
 #define COMPILER_DEPENDENT_UINT64  unsigned long long
 
-
-/* Name of host operating system (returned by the _OS_ namespace object) */
-
-#define ACPI_OS_NAME         "Intel ACPI/CA Core Subsystem"
-
-/* This macro is used to tag functions as "printf-like" because
+/*
+ * This macro is used to tag functions as "printf-like" because
  * some compilers can catch printf format string problems. MSVC
  * doesn't, so this is proprocessed away.
  */
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h
index 82db061af..f0b87de71 100644
--- a/include/acpi/platform/aclinux.h
+++ b/include/acpi/platform/aclinux.h
@@ -44,8 +44,6 @@
 #ifndef __ACLINUX_H__
 #define __ACLINUX_H__
 
-#define ACPI_OS_NAME                "Linux"
-
 #define ACPI_USE_SYSTEM_CLIBRARY
 #define ACPI_USE_DO_WHILE_0
 
diff --git a/include/asm-alpha/a.out.h b/include/asm-alpha/a.out.h
index 709ea3e38..d97daf427 100644
--- a/include/asm-alpha/a.out.h
+++ b/include/asm-alpha/a.out.h
@@ -95,7 +95,7 @@ struct exec
    Worse, we have to notice the start address before swapping to use
    /sbin/loader, which of course is _not_ a TASO application.  */
 #define SET_AOUT_PERSONALITY(BFPM, EX) \
-	set_personality (((BFPM->sh_bang || EX.ah.entry < 0x100000000 \
+	set_personality (((BFPM->sh_bang || EX.ah.entry < 0x100000000L \
 			   ? ADDR_LIMIT_32BIT : 0) | PER_OSF4))
 
 #define STACK_TOP \
diff --git a/include/asm-alpha/bitops.h b/include/asm-alpha/bitops.h
index 22ecbf95f..87c43e519 100644
--- a/include/asm-alpha/bitops.h
+++ b/include/asm-alpha/bitops.h
@@ -2,7 +2,6 @@
 #define _ALPHA_BITOPS_H
 
 #include <linux/config.h>
-#include <linux/kernel.h>
 #include <asm/compiler.h>
 
 /*
@@ -324,7 +323,7 @@ static inline int fls(int word)
 #endif
 
 /* Compute powers of two for the given integer.  */
-static inline int floor_log2(unsigned long word)
+static inline long floor_log2(unsigned long word)
 {
 #if defined(__alpha_cix__) && defined(__alpha_fix__)
 	return 63 - __kernel_ctlz(word);
@@ -336,7 +335,7 @@ static inline int floor_log2(unsigned long word)
 #endif
 }
 
-static inline int ceil_log2(unsigned int word)
+static inline long ceil_log2(unsigned long word)
 {
 	long bit = floor_log2(word);
 	return bit + (word > (1UL << bit));
diff --git a/include/asm-alpha/bug.h b/include/asm-alpha/bug.h
index 61bd72ea8..ae1e0a5fa 100644
--- a/include/asm-alpha/bug.h
+++ b/include/asm-alpha/bug.h
@@ -9,15 +9,7 @@
   __asm__ __volatile__("call_pal %0  # bugchk\n\t"".long %1\n\t.8byte %2" \
 		       : : "i" (PAL_bugchk), "i"(__LINE__), "i"(__FILE__))
 
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define PAGE_BUG(page)	BUG()
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-alpha/cache.h b/include/asm-alpha/cache.h
index f74d7ece1..e69b29501 100644
--- a/include/asm-alpha/cache.h
+++ b/include/asm-alpha/cache.h
@@ -20,6 +20,6 @@
 
 #define L1_CACHE_ALIGN(x)  (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
 #define SMP_CACHE_BYTES    L1_CACHE_BYTES
-#define L1_CACHE_SHIFT_MAX 6	/* largest L1 which this arch supports */
+#define L1_CACHE_SHIFT_MAX L1_CACHE_SHIFT
 
 #endif
diff --git a/include/asm-alpha/compiler.h b/include/asm-alpha/compiler.h
index dcfa94b87..399c33b7b 100644
--- a/include/asm-alpha/compiler.h
+++ b/include/asm-alpha/compiler.h
@@ -17,9 +17,9 @@
 # define __kernel_extbl(val, shift)	__builtin_alpha_extbl(val, shift)
 # define __kernel_extwl(val, shift)	__builtin_alpha_extwl(val, shift)
 # define __kernel_cmpbge(a, b)		__builtin_alpha_cmpbge(a, b)
-# define __kernel_cttz(x)		__builtin_ctz(x)
-# define __kernel_ctlz(x)		__builtin_clz(x)
-# define __kernel_ctpop(x)		__builtin_popcount(x)
+# define __kernel_cttz(x)		__builtin_ctzl(x)
+# define __kernel_ctlz(x)		__builtin_clzl(x)
+# define __kernel_ctpop(x)		__builtin_popcountl(x)
 #else
 # define __kernel_insbl(val, shift)					\
   ({ unsigned long __kir;						\
@@ -90,4 +90,14 @@
   __asm__("stw %1,%0" : "=m"(mem) : "r"(val))
 #endif
 
+/* Some idiots over in <linux/compiler.h> thought inline should imply
+   always_inline.  This breaks stuff.  We'll include this file whenever
+   we run into such problems.  */
+
+#include <linux/compiler.h>
+#undef inline
+#undef __inline__
+#undef __inline
+
+
 #endif /* __ALPHA_COMPILER_H */
diff --git a/include/asm-alpha/core_apecs.h b/include/asm-alpha/core_apecs.h
index b32084e51..6785ff7e0 100644
--- a/include/asm-alpha/core_apecs.h
+++ b/include/asm-alpha/core_apecs.h
@@ -370,178 +370,142 @@ struct el_apecs_procdata
  * data to/from the right byte-lanes.
  */
 
-#define vip	volatile int *
-#define vuip	volatile unsigned int *
-#define vulp	volatile unsigned long *
-
-__EXTERN_INLINE u8 apecs_inb(unsigned long addr)
+#define vip	volatile int __force *
+#define vuip	volatile unsigned int __force *
+#define vulp	volatile unsigned long __force *
+
+#define APECS_SET_HAE						\
+	do {							\
+		if (addr >= (1UL << 24)) {			\
+			unsigned long msb = addr & 0xf8000000;	\
+			addr -= msb;				\
+			set_hae(msb);				\
+		}						\
+	} while (0)
+
+__EXTERN_INLINE unsigned int apecs_ioread8(void __iomem *xaddr)
 {
-	long result = *(vip) ((addr << 5) + APECS_IO + 0x00);
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long result, base_and_type;
+
+	if (addr >= APECS_DENSE_MEM) {
+		addr -= APECS_DENSE_MEM;
+		APECS_SET_HAE;
+		base_and_type = APECS_SPARSE_MEM + 0x00;
+	} else {
+		addr -= APECS_IO;
+		base_and_type = APECS_IO + 0x00;
+	}
+
+	result = *(vip) ((addr << 5) + base_and_type);
 	return __kernel_extbl(result, addr & 3);
 }
 
-__EXTERN_INLINE void apecs_outb(u8 b, unsigned long addr)
+__EXTERN_INLINE void apecs_iowrite8(u8 b, void __iomem *xaddr)
 {
-	unsigned long w;
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long w, base_and_type;
+
+	if (addr >= APECS_DENSE_MEM) {
+		addr -= APECS_DENSE_MEM;
+		APECS_SET_HAE;
+		base_and_type = APECS_SPARSE_MEM + 0x00;
+	} else {
+		addr -= APECS_IO;
+		base_and_type = APECS_IO + 0x00;
+	}
 
 	w = __kernel_insbl(b, addr & 3);
-	*(vuip) ((addr << 5) + APECS_IO + 0x00) = w;
-	mb();
-}
-
-__EXTERN_INLINE u16 apecs_inw(unsigned long addr)
-{
-	long result = *(vip) ((addr << 5) + APECS_IO + 0x08);
-	return __kernel_extwl(result, addr & 3);
+	*(vuip) ((addr << 5) + base_and_type) = w;
 }
 
-__EXTERN_INLINE void apecs_outw(u16 b, unsigned long addr)
-{
-	unsigned long w;
-
-	w = __kernel_inswl(b, addr & 3);
-	*(vuip) ((addr << 5) + APECS_IO + 0x08) = w;
-	mb();
-}
-
-__EXTERN_INLINE u32 apecs_inl(unsigned long addr)
-{
-	return *(vuip) ((addr << 5) + APECS_IO + 0x18);
-}
-
-__EXTERN_INLINE void apecs_outl(u32 b, unsigned long addr)
-{
-	*(vuip) ((addr << 5) + APECS_IO + 0x18) = b;
-	mb();
-}
-
-
-/*
- * Memory functions.  64-bit and 32-bit accesses are done through
- * dense memory space, everything else through sparse space.
- */
-
-__EXTERN_INLINE u8 apecs_readb(unsigned long addr)
+__EXTERN_INLINE unsigned int apecs_ioread16(void __iomem *xaddr)
 {
-	unsigned long result, msb;
-
-	addr -= APECS_DENSE_MEM;
-	if (addr >= (1UL << 24)) {
-		msb = addr & 0xf8000000;
-		addr -= msb;
-		set_hae(msb);
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long result, base_and_type;
+
+	if (addr >= APECS_DENSE_MEM) {
+		addr -= APECS_DENSE_MEM;
+		APECS_SET_HAE;
+		base_and_type = APECS_SPARSE_MEM + 0x08;
+	} else {
+		addr -= APECS_IO;
+		base_and_type = APECS_IO + 0x08;
 	}
-	result = *(vip) ((addr << 5) + APECS_SPARSE_MEM + 0x00);
-	return __kernel_extbl(result, addr & 3);
-}
 
-__EXTERN_INLINE u16 apecs_readw(unsigned long addr)
-{
-	unsigned long result, msb;
-
-	addr -= APECS_DENSE_MEM;
-	if (addr >= (1UL << 24)) {
-		msb = addr & 0xf8000000;
-		addr -= msb;
-		set_hae(msb);
-	}
-	result = *(vip) ((addr << 5) + APECS_SPARSE_MEM + 0x08);
+	result = *(vip) ((addr << 5) + base_and_type);
 	return __kernel_extwl(result, addr & 3);
 }
 
-__EXTERN_INLINE u32 apecs_readl(unsigned long addr)
-{
-	return (*(vuip)addr) & 0xffffffff;
-}
-
-__EXTERN_INLINE u64 apecs_readq(unsigned long addr)
-{
-	return *(vulp)addr;
-}
-
-__EXTERN_INLINE void apecs_writeb(u8 b, unsigned long addr)
+__EXTERN_INLINE void apecs_iowrite16(u16 b, void __iomem *xaddr)
 {
-	unsigned long msb;
-
-	addr -= APECS_DENSE_MEM;
-	if (addr >= (1UL << 24)) {
-		msb = addr & 0xf8000000;
-		addr -= msb;
-		set_hae(msb);
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long w, base_and_type;
+
+	if (addr >= APECS_DENSE_MEM) {
+		addr -= APECS_DENSE_MEM;
+		APECS_SET_HAE;
+		base_and_type = APECS_SPARSE_MEM + 0x08;
+	} else {
+		addr -= APECS_IO;
+		base_and_type = APECS_IO + 0x08;
 	}
-	*(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x00) = b * 0x01010101;
+
+	w = __kernel_inswl(b, addr & 3);
+	*(vuip) ((addr << 5) + base_and_type) = w;
 }
 
-__EXTERN_INLINE void apecs_writew(u16 b, unsigned long addr)
+__EXTERN_INLINE unsigned int apecs_ioread32(void __iomem *xaddr)
 {
-	unsigned long msb;
-
-	addr -= APECS_DENSE_MEM;
-	if (addr >= (1UL << 24)) {
-		msb = addr & 0xf8000000;
-		addr -= msb;
-		set_hae(msb);
-	}
-	*(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x08) = b * 0x00010001;
+	unsigned long addr = (unsigned long) xaddr;
+	if (addr < APECS_DENSE_MEM)
+		addr = ((addr - APECS_IO) << 5) + APECS_IO + 0x18;
+	return *(vuip)addr;
 }
 
-__EXTERN_INLINE void apecs_writel(u32 b, unsigned long addr)
+__EXTERN_INLINE void apecs_iowrite32(u32 b, void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
+	if (addr < APECS_DENSE_MEM)
+		addr = ((addr - APECS_IO) << 5) + APECS_IO + 0x18;
 	*(vuip)addr = b;
 }
 
-__EXTERN_INLINE void apecs_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE void __iomem *apecs_ioportmap(unsigned long addr)
 {
-	*(vulp)addr = b;
+	return (void __iomem *)(addr + APECS_IO);
 }
 
-__EXTERN_INLINE unsigned long apecs_ioremap(unsigned long addr,
-					    unsigned long size
-					    __attribute__((unused)))
+__EXTERN_INLINE void __iomem *apecs_ioremap(unsigned long addr,
+					    unsigned long size)
 {
-	return addr + APECS_DENSE_MEM;
+	return (void __iomem *)(addr + APECS_DENSE_MEM);
 }
 
-__EXTERN_INLINE void apecs_iounmap(unsigned long addr)
+__EXTERN_INLINE int apecs_is_ioaddr(unsigned long addr)
 {
-	return;
+	return addr >= IDENT_ADDR + 0x180000000UL;
 }
 
-__EXTERN_INLINE int apecs_is_ioaddr(unsigned long addr)
+__EXTERN_INLINE int apecs_is_mmio(const volatile void __iomem *addr)
 {
-	return addr >= IDENT_ADDR + 0x180000000UL;
+	return (unsigned long)addr >= APECS_DENSE_MEM;
 }
 
+#undef APECS_SET_HAE
+
 #undef vip
 #undef vuip
 #undef vulp
 
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)		apecs_inb((unsigned long)(p))
-#define __inw(p)		apecs_inw((unsigned long)(p))
-#define __inl(p)		apecs_inl((unsigned long)(p))
-#define __outb(x,p)		apecs_outb((x),(unsigned long)(p))
-#define __outw(x,p)		apecs_outw((x),(unsigned long)(p))
-#define __outl(x,p)		apecs_outl((x),(unsigned long)(p))
-#define __readb(a)		apecs_readb((unsigned long)(a))
-#define __readw(a)		apecs_readw((unsigned long)(a))
-#define __readl(a)		apecs_readl((unsigned long)(a))
-#define __readq(a)		apecs_readq((unsigned long)(a))
-#define __writeb(x,a)		apecs_writeb((x),(unsigned long)(a))
-#define __writew(x,a)		apecs_writew((x),(unsigned long)(a))
-#define __writel(x,a)		apecs_writel((x),(unsigned long)(a))
-#define __writeq(x,a)		apecs_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)		apecs_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)		apecs_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)		apecs_is_ioaddr((unsigned long)(a))
-
-#define __raw_readl(a)		__readl(a)
-#define __raw_readq(a)		__readq(a)
-#define __raw_writel(v,a)	__writel((v),(a))
-#define __raw_writeq(v,a)	__writeq((v),(a))
-
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX		apecs
+#define apecs_trivial_io_bw	0
+#define apecs_trivial_io_lq	0
+#define apecs_trivial_rw_bw	2
+#define apecs_trivial_rw_lq	1
+#define apecs_trivial_iounmap	1
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
diff --git a/include/asm-alpha/core_cia.h b/include/asm-alpha/core_cia.h
index e5eca2dbf..549550fee 100644
--- a/include/asm-alpha/core_cia.h
+++ b/include/asm-alpha/core_cia.h
@@ -306,90 +306,6 @@ struct el_CIA_sysdata_mcheck {
  * get at PCI memory and I/O.
  */
 
-#define vucp	volatile unsigned char *
-#define vusp	volatile unsigned short *
-#define vip	volatile int *
-#define vuip	volatile unsigned int *
-#define vulp	volatile unsigned long *
-
-__EXTERN_INLINE u8 cia_inb(unsigned long addr)
-{
-	long result;
-	result = *(vip) ((addr << 5) + CIA_IO + 0x00);
-	return __kernel_extbl(result, addr & 3);
-}
-
-__EXTERN_INLINE void cia_outb(u8 b, unsigned long addr)
-{
-	unsigned long w = __kernel_insbl(b, addr & 3);
-	*(vuip) ((addr << 5) + CIA_IO + 0x00) = w;
-	mb();
-}
-
-__EXTERN_INLINE u16 cia_inw(unsigned long addr)
-{
-	long result;
-	result = *(vip) ((addr << 5) + CIA_IO + 0x08);
-	return __kernel_extwl(result, addr & 3);
-}
-
-__EXTERN_INLINE void cia_outw(u16 b, unsigned long addr)
-{
-	unsigned long w = __kernel_inswl(b, addr & 3);
-	*(vuip) ((addr << 5) + CIA_IO + 0x08) = w;
-	mb();
-}
-
-__EXTERN_INLINE u32 cia_inl(unsigned long addr)
-{
-	return *(vuip) ((addr << 5) + CIA_IO + 0x18);
-}
-
-__EXTERN_INLINE void cia_outl(u32 b, unsigned long addr)
-{
-	*(vuip) ((addr << 5) + CIA_IO + 0x18) = b;
-	mb();
-}
-
-__EXTERN_INLINE u8 cia_bwx_inb(unsigned long addr)
-{
-	/* ??? I wish I could get rid of this.  But there's no ioremap
-	   equivalent for I/O space.  PCI I/O can be forced into the
-	   CIA BWX I/O region, but that doesn't take care of legacy
-	   ISA crap.  */
-
-	return __kernel_ldbu(*(vucp)(addr+CIA_BW_IO));
-}
-
-__EXTERN_INLINE void cia_bwx_outb(u8 b, unsigned long addr)
-{
-	__kernel_stb(b, *(vucp)(addr+CIA_BW_IO));
-	mb();
-}
-
-__EXTERN_INLINE u16 cia_bwx_inw(unsigned long addr)
-{
-	return __kernel_ldwu(*(vusp)(addr+CIA_BW_IO));
-}
-
-__EXTERN_INLINE void cia_bwx_outw(u16 b, unsigned long addr)
-{
-	__kernel_stw(b, *(vusp)(addr+CIA_BW_IO));
-	mb();
-}
-
-__EXTERN_INLINE u32 cia_bwx_inl(unsigned long addr)
-{
-	return *(vuip)(addr+CIA_BW_IO);
-}
-
-__EXTERN_INLINE void cia_bwx_outl(u32 b, unsigned long addr)
-{
-	*(vuip)(addr+CIA_BW_IO) = b;
-	mb();
-}
-
-
 /*
  * Memory functions.  64-bit and 32-bit accesses are done through
  * dense memory space, everything else through sparse space.
@@ -422,195 +338,158 @@ __EXTERN_INLINE void cia_bwx_outl(u32 b, unsigned long addr)
  *
  */
 
-__EXTERN_INLINE u8 cia_readb(unsigned long addr)
+#define vip	volatile int __force *
+#define vuip	volatile unsigned int __force *
+#define vulp	volatile unsigned long __force *
+
+__EXTERN_INLINE unsigned int cia_ioread8(void __iomem *xaddr)
 {
-	unsigned long result;
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long result, base_and_type;
 
+	/* We can use CIA_MEM_R1_MASK for io ports too, since it is large
+	   enough to cover all io ports, and smaller than CIA_IO.  */
 	addr &= CIA_MEM_R1_MASK;
-	result = *(vip) ((addr << 5) + CIA_SPARSE_MEM + 0x00);
+	if (addr >= CIA_DENSE_MEM)
+		base_and_type = CIA_SPARSE_MEM + 0x00;
+	else
+		base_and_type = CIA_IO + 0x00;
+
+	result = *(vip) ((addr << 5) + base_and_type);
 	return __kernel_extbl(result, addr & 3);
 }
 
-__EXTERN_INLINE u16 cia_readw(unsigned long addr)
+__EXTERN_INLINE void cia_iowrite8(u8 b, void __iomem *xaddr)
 {
-	unsigned long result;
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long w, base_and_type;
 
 	addr &= CIA_MEM_R1_MASK;
-	result = *(vip) ((addr << 5) + CIA_SPARSE_MEM + 0x08);
-	return __kernel_extwl(result, addr & 3);
-}
+	if (addr >= CIA_DENSE_MEM)
+		base_and_type = CIA_SPARSE_MEM + 0x00;
+	else
+		base_and_type = CIA_IO + 0x00;
 
-__EXTERN_INLINE void cia_writeb(u8 b, unsigned long addr)
-{
-	unsigned long w;
-
-	addr &= CIA_MEM_R1_MASK;
 	w = __kernel_insbl(b, addr & 3);
-	*(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x00) = w;
+	*(vuip) ((addr << 5) + base_and_type) = w;
 }
 
-__EXTERN_INLINE void cia_writew(u16 b, unsigned long addr)
+__EXTERN_INLINE unsigned int cia_ioread16(void __iomem *xaddr)
 {
-	unsigned long w;
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long result, base_and_type;
 
 	addr &= CIA_MEM_R1_MASK;
-	w = __kernel_inswl(b, addr & 3);
-	*(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x08) = w;
-}
-
-__EXTERN_INLINE u32 cia_readl(unsigned long addr)
-{
-	return *(vuip)addr;
-}
-
-__EXTERN_INLINE u64 cia_readq(unsigned long addr)
-{
-	return *(vulp)addr;
-}
-
-__EXTERN_INLINE void cia_writel(u32 b, unsigned long addr)
-{
-	*(vuip)addr = b;
-}
+	if (addr >= CIA_DENSE_MEM)
+		base_and_type = CIA_SPARSE_MEM + 0x08;
+	else
+		base_and_type = CIA_IO + 0x08;
 
-__EXTERN_INLINE void cia_writeq(u64 b, unsigned long addr)
-{
-	*(vulp)addr = b;
+	result = *(vip) ((addr << 5) + base_and_type);
+	return __kernel_extwl(result, addr & 3);
 }
 
-__EXTERN_INLINE unsigned long cia_ioremap(unsigned long addr,
-					  unsigned long size
-					  __attribute__((unused)))
+__EXTERN_INLINE void cia_iowrite16(u16 b, void __iomem *xaddr)
 {
-	return addr + CIA_DENSE_MEM;
-}
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long w, base_and_type;
 
-__EXTERN_INLINE void cia_iounmap(unsigned long addr)
-{
-	return;
-}
+	addr &= CIA_MEM_R1_MASK;
+	if (addr >= CIA_DENSE_MEM)
+		base_and_type = CIA_SPARSE_MEM + 0x08;
+	else
+		base_and_type = CIA_IO + 0x08;
 
-__EXTERN_INLINE u8 cia_bwx_readb(unsigned long addr)
-{
-	return __kernel_ldbu(*(vucp)addr);
+	w = __kernel_inswl(b, addr & 3);
+	*(vuip) ((addr << 5) + base_and_type) = w;
 }
 
-__EXTERN_INLINE u16 cia_bwx_readw(unsigned long addr)
+__EXTERN_INLINE unsigned int cia_ioread32(void __iomem *xaddr)
 {
-	return __kernel_ldwu(*(vusp)addr);
+	unsigned long addr = (unsigned long) xaddr;
+	if (addr < CIA_DENSE_MEM)
+		addr = ((addr - CIA_IO) << 5) + CIA_IO + 0x18;
+	return *(vuip)addr;
 }
 
-__EXTERN_INLINE u32 cia_bwx_readl(unsigned long addr)
+__EXTERN_INLINE void cia_iowrite32(u32 b, void __iomem *xaddr)
 {
-	return *(vuip)addr;
+	unsigned long addr = (unsigned long) xaddr;
+	if (addr < CIA_DENSE_MEM)
+		addr = ((addr - CIA_IO) << 5) + CIA_IO + 0x18;
+	*(vuip)addr = b;
 }
 
-__EXTERN_INLINE u64 cia_bwx_readq(unsigned long addr)
+__EXTERN_INLINE void __iomem *cia_ioportmap(unsigned long addr)
 {
-	return *(vulp)addr;
+	return (void __iomem *)(addr + CIA_IO);
 }
 
-__EXTERN_INLINE void cia_bwx_writeb(u8 b, unsigned long addr)
+__EXTERN_INLINE void __iomem *cia_ioremap(unsigned long addr,
+					  unsigned long size)
 {
-	__kernel_stb(b, *(vucp)addr);
+	return (void __iomem *)(addr + CIA_DENSE_MEM);
 }
 
-__EXTERN_INLINE void cia_bwx_writew(u16 b, unsigned long addr)
+__EXTERN_INLINE int cia_is_ioaddr(unsigned long addr)
 {
-	__kernel_stw(b, *(vusp)addr);
+	return addr >= IDENT_ADDR + 0x8000000000UL;
 }
 
-__EXTERN_INLINE void cia_bwx_writel(u32 b, unsigned long addr)
+__EXTERN_INLINE int cia_is_mmio(const volatile void __iomem *addr)
 {
-	*(vuip)addr = b;
+	return (unsigned long)addr >= CIA_DENSE_MEM;
 }
 
-__EXTERN_INLINE void cia_bwx_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE void __iomem *cia_bwx_ioportmap(unsigned long addr)
 {
-	*(vulp)addr = b;
+	return (void __iomem *)(addr + CIA_BW_IO);
 }
 
-__EXTERN_INLINE unsigned long cia_bwx_ioremap(unsigned long addr,
+__EXTERN_INLINE void __iomem *cia_bwx_ioremap(unsigned long addr,
 					      unsigned long size)
 {
-	return addr + CIA_BW_MEM;
+	return (void __iomem *)(addr + CIA_BW_MEM);
 }
 
-__EXTERN_INLINE void cia_bwx_iounmap(unsigned long addr)
+__EXTERN_INLINE int cia_bwx_is_ioaddr(unsigned long addr)
 {
-	return;
+	return addr >= IDENT_ADDR + 0x8000000000UL;
 }
 
-__EXTERN_INLINE int cia_is_ioaddr(unsigned long addr)
+__EXTERN_INLINE int cia_bwx_is_mmio(const volatile void __iomem *addr)
 {
-	return addr >= IDENT_ADDR + 0x8000000000UL;
+	return (unsigned long)addr < CIA_BW_IO;
 }
 
-#undef vucp
-#undef vusp
 #undef vip
 #undef vuip
 #undef vulp
 
-#ifdef __WANT_IO_DEF
-
+#undef __IO_PREFIX
+#define __IO_PREFIX		cia
+#define cia_trivial_rw_bw	2
+#define cia_trivial_rw_lq	1
+#define cia_trivial_io_bw	0
+#define cia_trivial_io_lq	0
+#define cia_trivial_iounmap	1
+#include <asm/io_trivial.h>
+
+#undef __IO_PREFIX
+#define __IO_PREFIX		cia_bwx
+#define cia_bwx_trivial_rw_bw	1
+#define cia_bwx_trivial_rw_lq	1
+#define cia_bwx_trivial_io_bw	1
+#define cia_bwx_trivial_io_lq	1
+#define cia_bwx_trivial_iounmap	1
+#include <asm/io_trivial.h>
+
+#undef __IO_PREFIX
 #ifdef CONFIG_ALPHA_PYXIS
-# define __inb(p)		cia_bwx_inb((unsigned long)(p))
-# define __inw(p)		cia_bwx_inw((unsigned long)(p))
-# define __inl(p)		cia_bwx_inl((unsigned long)(p))
-# define __outb(x,p)		cia_bwx_outb((x),(unsigned long)(p))
-# define __outw(x,p)		cia_bwx_outw((x),(unsigned long)(p))
-# define __outl(x,p)		cia_bwx_outl((x),(unsigned long)(p))
-# define __readb(a)		cia_bwx_readb((unsigned long)(a))
-# define __readw(a)		cia_bwx_readw((unsigned long)(a))
-# define __readl(a)		cia_bwx_readl((unsigned long)(a))
-# define __readq(a)		cia_bwx_readq((unsigned long)(a))
-# define __writeb(x,a)		cia_bwx_writeb((x),(unsigned long)(a))
-# define __writew(x,a)		cia_bwx_writew((x),(unsigned long)(a))
-# define __writel(x,a)		cia_bwx_writel((x),(unsigned long)(a))
-# define __writeq(x,a)		cia_bwx_writeq((x),(unsigned long)(a))
-# define __ioremap(a,s)		cia_bwx_ioremap((unsigned long)(a),(s))
-# define __iounmap(a)           cia_bwx_iounmap((unsigned long)(a))
-# define inb(p)			__inb(p)
-# define inw(p)			__inw(p)
-# define inl(p)			__inl(p)
-# define outb(x,p)		__outb((x),(p))
-# define outw(x,p)		__outw((x),(p))
-# define outl(x,p)		__outl((x),(p))
-# define __raw_readb(a)		__readb(a)
-# define __raw_readw(a)		__readw(a)
-# define __raw_readl(a)		__readl(a)
-# define __raw_readq(a)		__readq(a)
-# define __raw_writeb(x,a)	__writeb((x),(a))
-# define __raw_writew(x,a)	__writew((x),(a))
-# define __raw_writel(x,a)	__writel((x),(a))
-# define __raw_writeq(x,a)	__writeq((x),(a))
+#define __IO_PREFIX		cia_bwx
 #else
-# define __inb(p)		cia_inb((unsigned long)(p))
-# define __inw(p)		cia_inw((unsigned long)(p))
-# define __inl(p)		cia_inl((unsigned long)(p))
-# define __outb(x,p)		cia_outb((x),(unsigned long)(p))
-# define __outw(x,p)		cia_outw((x),(unsigned long)(p))
-# define __outl(x,p)		cia_outl((x),(unsigned long)(p))
-# define __readb(a)		cia_readb((unsigned long)(a))
-# define __readw(a)		cia_readw((unsigned long)(a))
-# define __readl(a)		cia_readl((unsigned long)(a))
-# define __readq(a)		cia_readq((unsigned long)(a))
-# define __writeb(x,a)		cia_writeb((x),(unsigned long)(a))
-# define __writew(x,a)		cia_writew((x),(unsigned long)(a))
-# define __writel(x,a)		cia_writel((x),(unsigned long)(a))
-# define __writeq(x,a)		cia_writeq((x),(unsigned long)(a))
-# define __ioremap(a,s)		cia_ioremap((unsigned long)(a),(s))
-# define __iounmap(a)           cia_iounmap((unsigned long)(a))
-# define __raw_readl(a)		__readl(a)
-# define __raw_readq(a)		__readq(a)
-# define __raw_writel(v,a)	__writel((v),(a))
-# define __raw_writeq(v,a)	__writeq((v),(a))
-#endif /* PYXIS */
-
-#define __is_ioaddr(a)		cia_is_ioaddr((unsigned long)(a))
-
-#endif /* __WANT_IO_DEF */
+#define __IO_PREFIX		cia
+#endif
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
diff --git a/include/asm-alpha/core_irongate.h b/include/asm-alpha/core_irongate.h
index 9b9a49feb..24b2db541 100644
--- a/include/asm-alpha/core_irongate.h
+++ b/include/asm-alpha/core_irongate.h
@@ -190,137 +190,37 @@ struct el_IRONGATE_sysdata_mcheck {
  * K7 can only use linear accesses to get at PCI memory and I/O spaces.
  */
 
-#define vucp	volatile unsigned char *
-#define vusp	volatile unsigned short *
-#define vuip	volatile unsigned int *
-#define vulp	volatile unsigned long *
-
-__EXTERN_INLINE u8 irongate_inb(unsigned long addr)
-{
-	return __kernel_ldbu(*(vucp)(addr + IRONGATE_IO));
-}
-
-__EXTERN_INLINE void irongate_outb(u8 b, unsigned long addr)
-{
-        __kernel_stb(b, *(vucp)(addr + IRONGATE_IO));
-	mb();
-}
-
-__EXTERN_INLINE u16 irongate_inw(unsigned long addr)
-{
-	return __kernel_ldwu(*(vusp)(addr + IRONGATE_IO));
-}
-
-__EXTERN_INLINE void irongate_outw(u16 b, unsigned long addr)
-{
-        __kernel_stw(b, *(vusp)(addr + IRONGATE_IO));
-	mb();
-}
-
-__EXTERN_INLINE u32 irongate_inl(unsigned long addr)
-{
-	return *(vuip)(addr + IRONGATE_IO);
-}
-
-__EXTERN_INLINE void irongate_outl(u32 b, unsigned long addr)
-{
-        *(vuip)(addr + IRONGATE_IO) = b;
-	mb();
-}
-
 /*
  * Memory functions.  All accesses are done through linear space.
  */
 
-__EXTERN_INLINE u8 irongate_readb(unsigned long addr)
+__EXTERN_INLINE void __iomem *irongate_ioportmap(unsigned long addr)
 {
-	return __kernel_ldbu(*(vucp)addr);
+	return (void __iomem *)(addr + IRONGATE_IO);
 }
 
-__EXTERN_INLINE u16 irongate_readw(unsigned long addr)
-{
-	return __kernel_ldwu(*(vusp)addr);
-}
+extern void __iomem *irongate_ioremap(unsigned long addr, unsigned long size);
+extern void irongate_iounmap(volatile void __iomem *addr);
 
-__EXTERN_INLINE u32 irongate_readl(unsigned long addr)
-{
-	return (*(vuip)addr) & 0xffffffff;
-}
-
-__EXTERN_INLINE u64 irongate_readq(unsigned long addr)
-{
-	return *(vulp)addr;
-}
-
-__EXTERN_INLINE void irongate_writeb(u8 b, unsigned long addr)
-{
-	__kernel_stb(b, *(vucp)addr);
-}
-
-__EXTERN_INLINE void irongate_writew(u16 b, unsigned long addr)
-{
-	__kernel_stw(b, *(vusp)addr);
-}
-
-__EXTERN_INLINE void irongate_writel(u32 b, unsigned long addr)
-{
-	*(vuip)addr = b;
-}
-
-__EXTERN_INLINE void irongate_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE int irongate_is_ioaddr(unsigned long addr)
 {
-	*(vulp)addr = b;
+	return addr >= IRONGATE_MEM;
 }
 
-extern unsigned long irongate_ioremap(unsigned long addr, unsigned long size);
-extern void irongate_iounmap(unsigned long addr);
-
-__EXTERN_INLINE int irongate_is_ioaddr(unsigned long addr)
+__EXTERN_INLINE int irongate_is_mmio(const volatile void __iomem *xaddr)
 {
-	return addr >= IRONGATE_MEM;
+	unsigned long addr = (unsigned long)xaddr;
+	return addr < IRONGATE_IO || addr >= IRONGATE_CONF;
 }
 
-#undef vucp
-#undef vusp
-#undef vuip
-#undef vulp
-
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)		irongate_inb((unsigned long)(p))
-#define __inw(p)		irongate_inw((unsigned long)(p))
-#define __inl(p)		irongate_inl((unsigned long)(p))
-#define __outb(x,p)		irongate_outb((x),(unsigned long)(p))
-#define __outw(x,p)		irongate_outw((x),(unsigned long)(p))
-#define __outl(x,p)		irongate_outl((x),(unsigned long)(p))
-#define __readb(a)		irongate_readb((unsigned long)(a))
-#define __readw(a)		irongate_readw((unsigned long)(a))
-#define __readl(a)		irongate_readl((unsigned long)(a))
-#define __readq(a)		irongate_readq((unsigned long)(a))
-#define __writeb(x,a)		irongate_writeb((x),(unsigned long)(a))
-#define __writew(x,a)		irongate_writew((x),(unsigned long)(a))
-#define __writel(x,a)		irongate_writel((x),(unsigned long)(a))
-#define __writeq(x,a)		irongate_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)		irongate_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)		irongate_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)		irongate_is_ioaddr((unsigned long)(a))
-
-#define inb(p)			__inb(p)
-#define inw(p)			__inw(p)
-#define inl(p)			__inl(p)
-#define outb(x,p)		__outb((x),(p))
-#define outw(x,p)		__outw((x),(p))
-#define outl(x,p)		__outl((x),(p))
-#define __raw_readb(a)		__readb(a)
-#define __raw_readw(a)		__readw(a)
-#define __raw_readl(a)		__readl(a)
-#define __raw_readq(a)		__readq(a)
-#define __raw_writeb(v,a)	__writeb((v),(a))
-#define __raw_writew(v,a)	__writew((v),(a))
-#define __raw_writel(v,a)	__writel((v),(a))
-#define __raw_writeq(v,a)	__writeq((v),(a))
-
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX			irongate
+#define irongate_trivial_rw_bw		1
+#define irongate_trivial_rw_lq		1
+#define irongate_trivial_io_bw		1
+#define irongate_trivial_io_lq		1
+#define irongate_trivial_iounmap	0
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
diff --git a/include/asm-alpha/core_lca.h b/include/asm-alpha/core_lca.h
index a2a55b54a..f7cb4b460 100644
--- a/include/asm-alpha/core_lca.h
+++ b/include/asm-alpha/core_lca.h
@@ -215,145 +215,117 @@ union el_lca {
  * data to/from the right byte-lanes.
  */
 
-#define vip	volatile int *
-#define vuip	volatile unsigned int *
-#define vulp	volatile unsigned long *
+#define vip	volatile int __force *
+#define vuip	volatile unsigned int __force *
+#define vulp	volatile unsigned long __force *
 
-__EXTERN_INLINE u8 lca_inb(unsigned long addr)
-{
-	long result = *(vip) ((addr << 5) + LCA_IO + 0x00);
-	return __kernel_extbl(result, addr & 3);
-}
+#define LCA_SET_HAE						\
+	do {							\
+		if (addr >= (1UL << 24)) {			\
+			unsigned long msb = addr & 0xf8000000;	\
+			addr -= msb;				\
+			set_hae(msb);				\
+		}						\
+	} while (0)
 
-__EXTERN_INLINE void lca_outb(u8 b, unsigned long addr)
-{
-	unsigned long w;
-
-	w = __kernel_insbl(b, addr & 3);
-	*(vuip) ((addr << 5) + LCA_IO + 0x00) = w;
-	mb();
-}
-
-__EXTERN_INLINE u16 lca_inw(unsigned long addr)
-{
-	long result = *(vip) ((addr << 5) + LCA_IO + 0x08);
-	return __kernel_extwl(result, addr & 3);
-}
 
-__EXTERN_INLINE void lca_outw(u16 b, unsigned long addr)
+__EXTERN_INLINE unsigned int lca_ioread8(void __iomem *xaddr)
 {
-	unsigned long w;
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long result, base_and_type;
+
+	if (addr >= LCA_DENSE_MEM) {
+		addr -= LCA_DENSE_MEM;
+		LCA_SET_HAE;
+		base_and_type = LCA_SPARSE_MEM + 0x00;
+	} else {
+		addr -= LCA_IO;
+		base_and_type = LCA_IO + 0x00;
+	}
 
-	w = __kernel_inswl(b, addr & 3);
-	*(vuip) ((addr << 5) + LCA_IO + 0x08) = w;
-	mb();
+	result = *(vip) ((addr << 5) + base_and_type);
+	return __kernel_extbl(result, addr & 3);
 }
 
-__EXTERN_INLINE u32 lca_inl(unsigned long addr)
+__EXTERN_INLINE void lca_iowrite8(u8 b, void __iomem *xaddr)
 {
-	return *(vuip) ((addr << 5) + LCA_IO + 0x18);
-}
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long w, base_and_type;
+
+	if (addr >= LCA_DENSE_MEM) {
+		addr -= LCA_DENSE_MEM;
+		LCA_SET_HAE;
+		base_and_type = LCA_SPARSE_MEM + 0x00;
+	} else {
+		addr -= LCA_IO;
+		base_and_type = LCA_IO + 0x00;
+	}
 
-__EXTERN_INLINE void lca_outl(u32 b, unsigned long addr)
-{
-	*(vuip) ((addr << 5) + LCA_IO + 0x18) = b;
-	mb();
+	w = __kernel_insbl(b, addr & 3);
+	*(vuip) ((addr << 5) + base_and_type) = w;
 }
 
-
-/*
- * Memory functions.  64-bit and 32-bit accesses are done through
- * dense memory space, everything else through sparse space.
- */
-
-__EXTERN_INLINE u8 lca_readb(unsigned long addr)
+__EXTERN_INLINE unsigned int lca_ioread16(void __iomem *xaddr)
 {
-	unsigned long result, msb;
-
-	addr -= LCA_DENSE_MEM;
-	if (addr >= (1UL << 24)) {
-		msb = addr & 0xf8000000;
-		addr -= msb;
-		set_hae(msb);
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long result, base_and_type;
+
+	if (addr >= LCA_DENSE_MEM) {
+		addr -= LCA_DENSE_MEM;
+		LCA_SET_HAE;
+		base_and_type = LCA_SPARSE_MEM + 0x08;
+	} else {
+		addr -= LCA_IO;
+		base_and_type = LCA_IO + 0x08;
 	}
-	result = *(vip) ((addr << 5) + LCA_SPARSE_MEM + 0x00);
-	return __kernel_extbl(result, addr & 3);
-}
 
-__EXTERN_INLINE u16 lca_readw(unsigned long addr)
-{
-	unsigned long result, msb;
-
-	addr -= LCA_DENSE_MEM;
-	if (addr >= (1UL << 24)) {
-		msb = addr & 0xf8000000;
-		addr -= msb;
-		set_hae(msb);
-	}
-	result = *(vip) ((addr << 5) + LCA_SPARSE_MEM + 0x08);
+	result = *(vip) ((addr << 5) + base_and_type);
 	return __kernel_extwl(result, addr & 3);
 }
 
-__EXTERN_INLINE u32 lca_readl(unsigned long addr)
+__EXTERN_INLINE void lca_iowrite16(u16 b, void __iomem *xaddr)
 {
-	return (*(vuip)addr) & 0xffffffff;
-}
-
-__EXTERN_INLINE u64 lca_readq(unsigned long addr)
-{
-	return *(vulp)addr;
-}
-
-__EXTERN_INLINE void lca_writeb(u8 b, unsigned long addr)
-{
-	unsigned long msb;
-	unsigned long w;
-
-	addr -= LCA_DENSE_MEM;
-	if (addr >= (1UL << 24)) {
-		msb = addr & 0xf8000000;
-		addr -= msb;
-		set_hae(msb);
+	unsigned long addr = (unsigned long) xaddr;
+	unsigned long w, base_and_type;
+
+	if (addr >= LCA_DENSE_MEM) {
+		addr -= LCA_DENSE_MEM;
+		LCA_SET_HAE;
+		base_and_type = LCA_SPARSE_MEM + 0x08;
+	} else {
+		addr -= LCA_IO;
+		base_and_type = LCA_IO + 0x08;
 	}
-	w = __kernel_insbl(b, addr & 3);
-	*(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x00) = w;
-}
 
-__EXTERN_INLINE void lca_writew(u16 b, unsigned long addr)
-{
-	unsigned long msb;
-	unsigned long w;
-
-	addr -= LCA_DENSE_MEM;
-	if (addr >= (1UL << 24)) {
-		msb = addr & 0xf8000000;
-		addr -= msb;
-		set_hae(msb);
-	}
 	w = __kernel_inswl(b, addr & 3);
-	*(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x08) = w;
+	*(vuip) ((addr << 5) + base_and_type) = w;
 }
 
-__EXTERN_INLINE void lca_writel(u32 b, unsigned long addr)
+__EXTERN_INLINE unsigned int lca_ioread32(void __iomem *xaddr)
 {
-	*(vuip)addr = b;
+	unsigned long addr = (unsigned long) xaddr;
+	if (addr < LCA_DENSE_MEM)
+		addr = ((addr - LCA_IO) << 5) + LCA_IO + 0x18;
+	return *(vuip)addr;
 }
 
-__EXTERN_INLINE void lca_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE void lca_iowrite32(u32 b, void __iomem *xaddr)
 {
-	*(vulp)addr = b;
+	unsigned long addr = (unsigned long) xaddr;
+	if (addr < LCA_DENSE_MEM)
+		addr = ((addr - LCA_IO) << 5) + LCA_IO + 0x18;
+	*(vuip)addr = b;
 }
 
-__EXTERN_INLINE unsigned long lca_ioremap(unsigned long addr,
-					  unsigned long size
-					  __attribute__((unused)))
+__EXTERN_INLINE void __iomem *lca_ioportmap(unsigned long addr)
 {
-	return addr + LCA_DENSE_MEM;
+	return (void __iomem *)(addr + LCA_IO);
 }
 
-__EXTERN_INLINE void lca_iounmap(unsigned long addr)
+__EXTERN_INLINE void __iomem *lca_ioremap(unsigned long addr,
+					  unsigned long size)
 {
-	return;
+	return (void __iomem *)(addr + LCA_DENSE_MEM);
 }
 
 __EXTERN_INLINE int lca_is_ioaddr(unsigned long addr)
@@ -361,36 +333,23 @@ __EXTERN_INLINE int lca_is_ioaddr(unsigned long addr)
 	return addr >= IDENT_ADDR + 0x120000000UL;
 }
 
+__EXTERN_INLINE int lca_is_mmio(const volatile void __iomem *addr)
+{
+	return (unsigned long)addr >= LCA_DENSE_MEM;
+}
+
 #undef vip
 #undef vuip
 #undef vulp
 
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)		lca_inb((unsigned long)(p))
-#define __inw(p)		lca_inw((unsigned long)(p))
-#define __inl(p)		lca_inl((unsigned long)(p))
-#define __outb(x,p)		lca_outb((x),(unsigned long)(p))
-#define __outw(x,p)		lca_outw((x),(unsigned long)(p))
-#define __outl(x,p)		lca_outl((x),(unsigned long)(p))
-#define __readb(a)		lca_readb((unsigned long)(a))
-#define __readw(a)		lca_readw((unsigned long)(a))
-#define __readl(a)		lca_readl((unsigned long)(a))
-#define __readq(a)		lca_readq((unsigned long)(a))
-#define __writeb(x,a)		lca_writeb((x),(unsigned long)(a))
-#define __writew(x,a)		lca_writew((x),(unsigned long)(a))
-#define __writel(x,a)		lca_writel((x),(unsigned long)(a))
-#define __writeq(x,a)		lca_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)		lca_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)		lca_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)		lca_is_ioaddr((unsigned long)(a))
-
-#define __raw_readl(a)		__readl(a)
-#define __raw_readq(a)		__readq(a)
-#define __raw_writel(v,a)	__writel((v),(a))
-#define __raw_writeq(v,a)	__writeq((v),(a))
-
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX		lca
+#define lca_trivial_rw_bw	2
+#define lca_trivial_rw_lq	1
+#define lca_trivial_io_bw	0
+#define lca_trivial_io_lq	0
+#define lca_trivial_iounmap	1
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
diff --git a/include/asm-alpha/core_marvel.h b/include/asm-alpha/core_marvel.h
index a1f2482cf..30d55fe7a 100644
--- a/include/asm-alpha/core_marvel.h
+++ b/include/asm-alpha/core_marvel.h
@@ -325,249 +325,48 @@ struct io7 {
  * I/O functions. All access through linear space.
  */
 
-#define vucp	volatile unsigned char *
-#define vusp	volatile unsigned short *
-#define vuip	volatile unsigned int *
-#define vulp	volatile unsigned long *
-
-#ifdef CONFIG_VGA_HOSE
-extern struct pci_controller *pci_vga_hose;
-
-# define __marvel_is_port_vga(a)	\
-        (((a) >= 0x3b0) && ((a) < 0x3e0) && ((a) != 0x3b3) && ((a) != 0x3d3))
-# define __marvel_is_mem_vga(a)	(((a) >= 0xa0000) && ((a) <= 0xc0000))
-# define FIXUP_IOADDR_VGA(a) do {			\
-	if (pci_vga_hose && __marvel_is_port_vga(a))	\
-		a += pci_vga_hose->io_space->start;	\
-    } while(0)
-#else
-# define FIXUP_IOADDR_VGA(a)
-#endif 
-
-#define __marvel_is_port_kbd(a)	(((a) == 0x60) || ((a) == 0x64))
-#define __marvel_is_port_rtc(a)	(((a) == 0x70) || ((a) == 0x71))
-
-#define FIXUP_IOADDR_LEGACY(a)
-
-#define FIXUP_IOADDR(a) do {				\
-	FIXUP_IOADDR_VGA(a);				\
-        FIXUP_IOADDR_LEGACY(a);				\
-    } while(0)
-
-#if 0
-# define IOBUG(x) printk x
-# define IOBUG_FILTER_IOADDR(a, x)	\
-    if (!__marvel_is_port_kbd(a) && !__marvel_is_port_rtc(a)) IOBUG(x)
-#else
-# define IOBUG(x)
-# define IOBUG_FILTER_IOADDR(a, x)
-#endif
-
-extern u8 __marvel_rtc_io(int write, u8 b, unsigned long addr);
-#define __marvel_rtc_inb(a)	__marvel_rtc_io(0, 0, (a))
-#define __marvel_rtc_outb(b, a)	__marvel_rtc_io(1, (b), (a))
-
-__EXTERN_INLINE int marvel_is_ioaddr(unsigned long addr)
-{
-	return (addr & (1UL << 40)) != 0; /*FIXME - hardwire*/
-}
-
-__EXTERN_INLINE u8 marvel_inb(unsigned long addr)
-{
-	FIXUP_IOADDR(addr);
-	if (!marvel_is_ioaddr(addr)) {
-		if (__marvel_is_port_kbd(addr))
-			return (u8)0;
-		if (__marvel_is_port_rtc(addr))
-			return __marvel_rtc_inb(addr);
-		IOBUG_FILTER_IOADDR(addr, 
-				    ("Bad IO addr %lx - reading -1\n", addr));
-		return (u8)-1;
-	}
-	return __kernel_ldbu(*(vucp)addr);
-}
-
-__EXTERN_INLINE void marvel_outb(u8 b, unsigned long addr)
-{
-	FIXUP_IOADDR(addr);
-	if (!marvel_is_ioaddr(addr)) {
-		if (__marvel_is_port_rtc(addr)) 
-			return (void)__marvel_rtc_outb(b, addr);
-		IOBUG_FILTER_IOADDR(addr, 
-				    ("Bad IO addr %lx - reading -1\n", addr));
-		return;
-	}
-	__kernel_stb(b, *(vucp)addr);
-	mb();
-}
-
-__EXTERN_INLINE u16 marvel_inw(unsigned long addr)
-{
-	FIXUP_IOADDR(addr);
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG_FILTER_IOADDR(addr, 
-				    ("Bad IO addr %lx - reading -1\n", addr));
-		return (u16)-1;
-	}
-	return __kernel_ldwu(*(vusp)addr);
-}
-
-__EXTERN_INLINE void marvel_outw(u16 w, unsigned long addr)
-{
-	FIXUP_IOADDR(addr);
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG_FILTER_IOADDR(addr, 
-				    ("Bad IO addr %lx - reading -1\n", addr));
-		return;
-	}
-	__kernel_stw(w, *(vusp)addr);
-	mb();
-}
-
-__EXTERN_INLINE u32 marvel_inl(unsigned long addr)
-{
-	FIXUP_IOADDR(addr);
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG_FILTER_IOADDR(addr, 
-				    ("Bad IO addr %lx - reading -1\n", addr));
-		return (u32)-1;
-	}
-	return *(vuip)addr;
-}
-
-__EXTERN_INLINE void marvel_outl(u32 l, unsigned long addr)
-{
-	FIXUP_IOADDR(addr);
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG_FILTER_IOADDR(addr, 
-				    ("Bad IO addr %lx - reading -1\n", addr));
-		return;
-	}
-	*(vuip)addr = l;
-	mb();
-}
-
 /*
  * Memory functions.  All accesses through linear space.
  */
 
-extern unsigned long marvel_ioremap(unsigned long addr, unsigned long size);
-extern void marvel_iounmap(unsigned long addr);
+#define vucp	volatile unsigned char __force *
+#define vusp	volatile unsigned short __force *
 
-__EXTERN_INLINE u8 marvel_readb(unsigned long addr)
-{
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG(("Bad MEM addr %lx - reading -1\n", addr));
-		return (u8)-1;
-	}
-	return __kernel_ldbu(*(vucp)addr);
-}
+extern unsigned int marvel_ioread8(void __iomem *);
+extern void marvel_iowrite8(u8 b, void __iomem *);
 
-__EXTERN_INLINE u16 marvel_readw(unsigned long addr)
+__EXTERN_INLINE unsigned int marvel_ioread16(void __iomem *addr)
 {
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG(("Bad MEM addr %lx - reading -1\n", addr));
-		return (u16)-1;
-	}
 	return __kernel_ldwu(*(vusp)addr);
 }
 
-__EXTERN_INLINE u32 marvel_readl(unsigned long addr)
-{
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG(("Bad MEM addr %lx - reading -1\n", addr));
-		return (u32)-1;
-	}
-	return *(vuip)addr;
-}
-
-__EXTERN_INLINE u64 marvel_readq(unsigned long addr)
+__EXTERN_INLINE void marvel_iowrite16(u16 b, void __iomem *addr)
 {
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG(("Bad MEM addr %lx - reading -1\n", addr));
-		return (u64)-1;
-	}
-	return *(vulp)addr;
+	__kernel_stw(b, *(vusp)addr);
 }
 
-__EXTERN_INLINE void marvel_writeb(u8 b, unsigned long addr)
-{
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG(("Bad MEM addr %lx - dropping store\n", addr));
-		return;
-	}
-	__kernel_stb(b, *(vucp)addr);
-}
-
-__EXTERN_INLINE void marvel_writew(u16 w, unsigned long addr)
-{
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG(("Bad MEM addr %lx - dropping store\n", addr));
-		return;
-	}
-	__kernel_stw(w, *(vusp)addr);
-}
+extern void __iomem *marvel_ioremap(unsigned long addr, unsigned long size);
+extern void marvel_iounmap(volatile void __iomem *addr);
+extern void __iomem *marvel_ioportmap (unsigned long addr);
 
-__EXTERN_INLINE void marvel_writel(u32 l, unsigned long addr)
-{
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG(("Bad MEM addr %lx - dropping store\n", addr));
-		return;
-	}
-	*(vuip)addr = l;
-}
-
-__EXTERN_INLINE void marvel_writeq(u64 q, unsigned long addr)
+__EXTERN_INLINE int marvel_is_ioaddr(unsigned long addr)
 {
-	if (!marvel_is_ioaddr(addr)) {
-		IOBUG(("Bad MEM addr %lx - dropping store\n", addr));
-		return;
-	}
-	*(vulp)addr = q;
+	return (addr >> 40) & 1;
 }
 
-#undef FIXUP_IOADDR
-#undef FIXUP_IOADDR_LEGACY
-#undef FIXUP_IOADDR_VGA
+extern int marvel_is_mmio(const volatile void __iomem *);
 
 #undef vucp
 #undef vusp
-#undef vuip
-#undef vulp
-
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)		marvel_inb((unsigned long)(p))
-#define __inw(p)		marvel_inw((unsigned long)(p))
-#define __inl(p)		marvel_inl((unsigned long)(p))
-#define __outb(x,p)		marvel_outb((x),(unsigned long)(p))
-#define __outw(x,p)		marvel_outw((x),(unsigned long)(p))
-#define __outl(x,p)		marvel_outl((x),(unsigned long)(p))
-#define __readb(a)		marvel_readb((unsigned long)(a))
-#define __readw(a)		marvel_readw((unsigned long)(a))
-#define __readl(a)		marvel_readl((unsigned long)(a))
-#define __readq(a)		marvel_readq((unsigned long)(a))
-#define __writeb(x,a)		marvel_writeb((x),(unsigned long)(a))
-#define __writew(x,a)		marvel_writew((x),(unsigned long)(a))
-#define __writel(x,a)		marvel_writel((x),(unsigned long)(a))
-#define __writeq(x,a)		marvel_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)		marvel_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)		marvel_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)		marvel_is_ioaddr((unsigned long)(a))
-
-/* Disable direct inlining of these calls with the debug checks present.  */
-#if 0
-#define __raw_readb(a)		__readb(a)
-#define __raw_readw(a)		__readw(a)
-#define __raw_readl(a)		__readl(a)
-#define __raw_readq(a)		__readq(a)
-#define __raw_writeb(v,a)	__writeb(v,a)
-#define __raw_writew(v,a)	__writew(v,a)
-#define __raw_writel(v,a)	__writel(v,a)
-#define __raw_writeq(v,a)	__writeq(v,a)
-#endif
 
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX		marvel
+#define marvel_trivial_rw_bw	1
+#define marvel_trivial_rw_lq	1
+#define marvel_trivial_io_bw	0
+#define marvel_trivial_io_lq	1
+#define marvel_trivial_iounmap	0
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 # undef __EXTERN_INLINE
diff --git a/include/asm-alpha/core_mcpcia.h b/include/asm-alpha/core_mcpcia.h
index db03753ed..980a3c51b 100644
--- a/include/asm-alpha/core_mcpcia.h
+++ b/include/asm-alpha/core_mcpcia.h
@@ -211,91 +211,6 @@ struct el_MCPCIA_uncorrected_frame_mcheck {
  * Unfortunately, we can't use BWIO with EV5, so for now, we always use SPARSE.
  */
 
-#define vucp	volatile unsigned char *
-#define vusp	volatile unsigned short *
-#define vip	volatile int *
-#define vuip	volatile unsigned int *
-#define vulp	volatile unsigned long *
-
-__EXTERN_INLINE u8 mcpcia_inb(unsigned long in_addr)
-{
-	unsigned long addr, hose, result;
-
-	addr = in_addr & 0xffffUL;
-	hose = in_addr & ~0xffffUL;
-
-	/* ??? I wish I could get rid of this.  But there's no ioremap
-	   equivalent for I/O space.  PCI I/O can be forced into the
-	   correct hose's I/O region, but that doesn't take care of
-	   legacy ISA crap.  */
-	hose += MCPCIA_IO_BIAS;
-
-	result = *(vip) ((addr << 5) + hose + 0x00);
-	return __kernel_extbl(result, addr & 3);
-}
-
-__EXTERN_INLINE void mcpcia_outb(u8 b, unsigned long in_addr)
-{
-	unsigned long addr, hose, w;
-
-	addr = in_addr & 0xffffUL;
-	hose = in_addr & ~0xffffUL;
-	hose += MCPCIA_IO_BIAS;
-
-	w = __kernel_insbl(b, addr & 3);
-	*(vuip) ((addr << 5) + hose + 0x00) = w;
-	mb();
-}
-
-__EXTERN_INLINE u16 mcpcia_inw(unsigned long in_addr)
-{
-	unsigned long addr, hose, result;
-
-	addr = in_addr & 0xffffUL;
-	hose = in_addr & ~0xffffUL;
-	hose += MCPCIA_IO_BIAS;
-
-	result = *(vip) ((addr << 5) + hose + 0x08);
-	return __kernel_extwl(result, addr & 3);
-}
-
-__EXTERN_INLINE void mcpcia_outw(u16 b, unsigned long in_addr)
-{
-	unsigned long addr, hose, w;
-
-	addr = in_addr & 0xffffUL;
-	hose = in_addr & ~0xffffUL;
-	hose += MCPCIA_IO_BIAS;
-
-	w = __kernel_inswl(b, addr & 3);
-	*(vuip) ((addr << 5) + hose + 0x08) = w;
-	mb();
-}
-
-__EXTERN_INLINE u32 mcpcia_inl(unsigned long in_addr)
-{
-	unsigned long addr, hose;
-
-	addr = in_addr & 0xffffUL;
-	hose = in_addr & ~0xffffUL;
-	hose += MCPCIA_IO_BIAS;
-
-	return *(vuip) ((addr << 5) + hose + 0x18);
-}
-
-__EXTERN_INLINE void mcpcia_outl(u32 b, unsigned long in_addr)
-{
-	unsigned long addr, hose;
-
-	addr = in_addr & 0xffffUL;
-	hose = in_addr & ~0xffffUL;
-	hose += MCPCIA_IO_BIAS;
-
-	*(vuip) ((addr << 5) + hose + 0x18) = b;
-	mb();
-}
-
-
 /*
  * Memory functions.  64-bit and 32-bit accesses are done through
  * dense memory space, everything else through sparse space.
@@ -328,149 +243,131 @@ __EXTERN_INLINE void mcpcia_outl(u32 b, unsigned long in_addr)
  *
  */
 
-__EXTERN_INLINE unsigned long mcpcia_ioremap(unsigned long addr,
-					     unsigned long size
-					     __attribute__((unused)))
-{
-	return addr + MCPCIA_MEM_BIAS;
-}
+#define vip	volatile int __force *
+#define vuip	volatile unsigned int __force *
+
+#ifdef MCPCIA_ONE_HAE_WINDOW
+#define MCPCIA_FROB_MMIO						\
+	if (__mcpcia_is_mmio(hose)) {					\
+		set_hae(hose & 0xffffffff);				\
+		hose = hose - MCPCIA_DENSE(4) + MCPCIA_SPARSE(4);	\
+	}
+#else
+#define MCPCIA_FROB_MMIO						\
+	if (__mcpcia_is_mmio(hose)) {					\
+		hose = hose - MCPCIA_DENSE(4) + MCPCIA_SPARSE(4);	\
+	}
+#endif
 
-__EXTERN_INLINE void mcpcia_iounmap(unsigned long addr)
+static inline int __mcpcia_is_mmio(unsigned long addr)
 {
-	return;
+	return (addr & 0x80000000UL) == 0;
 }
 
-__EXTERN_INLINE int mcpcia_is_ioaddr(unsigned long addr)
+__EXTERN_INLINE unsigned int mcpcia_ioread8(void __iomem *xaddr)
 {
-	return addr >= MCPCIA_SPARSE(0);
+	unsigned long addr = (unsigned long)xaddr & MCPCIA_MEM_MASK;
+	unsigned long hose = (unsigned long)xaddr & ~MCPCIA_MEM_MASK;
+	unsigned long result;
+
+	MCPCIA_FROB_MMIO;
+
+	result = *(vip) ((addr << 5) + hose + 0x00);
+	return __kernel_extbl(result, addr & 3);
 }
 
-__EXTERN_INLINE u8 mcpcia_readb(unsigned long in_addr)
+__EXTERN_INLINE void mcpcia_iowrite8(u8 b, void __iomem *xaddr)
 {
-	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = in_addr & ~0xffffffffUL;
-	unsigned long result, work;
+	unsigned long addr = (unsigned long)xaddr & MCPCIA_MEM_MASK;
+	unsigned long hose = (unsigned long)xaddr & ~MCPCIA_MEM_MASK;
+	unsigned long w;
 
-#ifndef MCPCIA_ONE_HAE_WINDOW
-	unsigned long msb;
-	msb = addr & ~MCPCIA_MEM_MASK;
-	set_hae(msb);
-#endif
-	addr = addr & MCPCIA_MEM_MASK;
+	MCPCIA_FROB_MMIO;
 
-	hose = hose - MCPCIA_DENSE(4) + MCPCIA_SPARSE(4);
-	work = ((addr << 5) + hose + 0x00);
-	result = *(vip) work;
-	return __kernel_extbl(result, addr & 3);
+	w = __kernel_insbl(b, addr & 3);
+	*(vuip) ((addr << 5) + hose + 0x00) = w;
 }
 
-__EXTERN_INLINE u16 mcpcia_readw(unsigned long in_addr)
+__EXTERN_INLINE unsigned int mcpcia_ioread16(void __iomem *xaddr)
 {
-	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = in_addr & ~0xffffffffUL;
-	unsigned long result, work;
+	unsigned long addr = (unsigned long)xaddr & MCPCIA_MEM_MASK;
+	unsigned long hose = (unsigned long)xaddr & ~MCPCIA_MEM_MASK;
+	unsigned long result;
 
-#ifndef MCPCIA_ONE_HAE_WINDOW
-	unsigned long msb;
-	msb = addr & ~MCPCIA_MEM_MASK;
-	set_hae(msb);
-#endif
-	addr = addr & MCPCIA_MEM_MASK;
+	MCPCIA_FROB_MMIO;
 
-	hose = hose - MCPCIA_DENSE(4) + MCPCIA_SPARSE(4);
-	work = ((addr << 5) + hose + 0x08);
-	result = *(vip) work;
+	result = *(vip) ((addr << 5) + hose + 0x08);
 	return __kernel_extwl(result, addr & 3);
 }
 
-__EXTERN_INLINE void mcpcia_writeb(u8 b, unsigned long in_addr)
+__EXTERN_INLINE void mcpcia_iowrite16(u16 b, void __iomem *xaddr)
 {
-	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = in_addr & ~0xffffffffUL;
+	unsigned long addr = (unsigned long)xaddr & MCPCIA_MEM_MASK;
+	unsigned long hose = (unsigned long)xaddr & ~MCPCIA_MEM_MASK;
 	unsigned long w;
 
-#ifndef MCPCIA_ONE_HAE_WINDOW
-	unsigned long msb;
-	msb = addr & ~MCPCIA_MEM_MASK;
-	set_hae(msb);
-#endif
-	addr = addr & MCPCIA_MEM_MASK;
+	MCPCIA_FROB_MMIO;
 
-	w = __kernel_insbl(b, in_addr & 3);
-	hose = hose - MCPCIA_DENSE(4) + MCPCIA_SPARSE(4);
-	*(vuip) ((addr << 5) + hose + 0x00) = w;
+	w = __kernel_inswl(b, addr & 3);
+	*(vuip) ((addr << 5) + hose + 0x08) = w;
 }
 
-__EXTERN_INLINE void mcpcia_writew(u16 b, unsigned long in_addr)
+__EXTERN_INLINE unsigned int mcpcia_ioread32(void __iomem *xaddr)
 {
-	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = in_addr & ~0xffffffffUL;
-	unsigned long w;
+	unsigned long addr = (unsigned long)xaddr;
 
-#ifndef MCPCIA_ONE_HAE_WINDOW
-	unsigned long msb;
-	msb = addr & ~MCPCIA_MEM_MASK;
-	set_hae(msb);
-#endif
-	addr = addr & MCPCIA_MEM_MASK;
+	if (!__mcpcia_is_mmio(addr))
+		addr = ((addr & 0xffff) << 5) + (addr & ~0xfffful) + 0x18;
 
-	w = __kernel_inswl(b, in_addr & 3);
-	hose = hose - MCPCIA_DENSE(4) + MCPCIA_SPARSE(4);
-	*(vuip) ((addr << 5) + hose + 0x08) = w;
+	return *(vuip)addr;
+}
+
+__EXTERN_INLINE void mcpcia_iowrite32(u32 b, void __iomem *xaddr)
+{
+	unsigned long addr = (unsigned long)xaddr;
+
+	if (!__mcpcia_is_mmio(addr))
+		addr = ((addr & 0xffff) << 5) + (addr & ~0xfffful) + 0x18;
+
+	*(vuip)addr = b;
 }
 
-__EXTERN_INLINE u32 mcpcia_readl(unsigned long addr)
+
+__EXTERN_INLINE void __iomem *mcpcia_ioportmap(unsigned long addr)
 {
-	return (*(vuip)addr) & 0xffffffff;
+	return (void __iomem *)(addr + MCPCIA_IO_BIAS);
 }
 
-__EXTERN_INLINE u64 mcpcia_readq(unsigned long addr)
+__EXTERN_INLINE void __iomem *mcpcia_ioremap(unsigned long addr,
+					     unsigned long size)
 {
-	return *(vulp)addr;
+	return (void __iomem *)(addr + MCPCIA_MEM_BIAS);
 }
 
-__EXTERN_INLINE void mcpcia_writel(u32 b, unsigned long addr)
+__EXTERN_INLINE int mcpcia_is_ioaddr(unsigned long addr)
 {
-	*(vuip)addr = b;
+	return addr >= MCPCIA_SPARSE(0);
 }
 
-__EXTERN_INLINE void mcpcia_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE int mcpcia_is_mmio(const volatile void __iomem *xaddr)
 {
-	*(vulp)addr = b;
+	unsigned long addr = (unsigned long) xaddr;
+	return __mcpcia_is_mmio(addr);
 }
 
-#undef vucp
-#undef vusp
+#undef MCPCIA_FROB_MMIO
+
 #undef vip
 #undef vuip
-#undef vulp
-
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)		mcpcia_inb((unsigned long)(p))
-#define __inw(p)		mcpcia_inw((unsigned long)(p))
-#define __inl(p)		mcpcia_inl((unsigned long)(p))
-#define __outb(x,p)		mcpcia_outb((x),(unsigned long)(p))
-#define __outw(x,p)		mcpcia_outw((x),(unsigned long)(p))
-#define __outl(x,p)		mcpcia_outl((x),(unsigned long)(p))
-#define __readb(a)		mcpcia_readb((unsigned long)(a))
-#define __readw(a)		mcpcia_readw((unsigned long)(a))
-#define __readl(a)		mcpcia_readl((unsigned long)(a))
-#define __readq(a)		mcpcia_readq((unsigned long)(a))
-#define __writeb(x,a)		mcpcia_writeb((x),(unsigned long)(a))
-#define __writew(x,a)		mcpcia_writew((x),(unsigned long)(a))
-#define __writel(x,a)		mcpcia_writel((x),(unsigned long)(a))
-#define __writeq(x,a)		mcpcia_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)		mcpcia_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)		mcpcia_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)		mcpcia_is_ioaddr((unsigned long)(a))
-
-#define __raw_readl(a)		__readl(a)
-#define __raw_readq(a)		__readq(a)
-#define __raw_writel(v,a)	__writel((v),(a))
-#define __raw_writeq(v,a)	__writeq((v),(a))
-
-#endif /* __WANT_IO_DEF */
+
+#undef __IO_PREFIX
+#define __IO_PREFIX		mcpcia
+#define mcpcia_trivial_rw_bw	2
+#define mcpcia_trivial_rw_lq	1
+#define mcpcia_trivial_io_bw	0
+#define mcpcia_trivial_io_lq	0
+#define mcpcia_trivial_iounmap	1
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
diff --git a/include/asm-alpha/core_polaris.h b/include/asm-alpha/core_polaris.h
index dca0341b0..2f966b646 100644
--- a/include/asm-alpha/core_polaris.h
+++ b/include/asm-alpha/core_polaris.h
@@ -63,49 +63,6 @@ struct el_POLARIS_sysdata_mcheck {
  * However, we will support only the BWX form.
  */
 
-#define vucp	volatile unsigned char *
-#define vusp	volatile unsigned short *
-#define vuip	volatile unsigned int  *
-#define vulp	volatile unsigned long  *
-
-__EXTERN_INLINE u8 polaris_inb(unsigned long addr)
-{
-	/* ??? I wish I could get rid of this.  But there's no ioremap
-	   equivalent for I/O space.  PCI I/O can be forced into the
-	   POLARIS I/O region, but that doesn't take care of legacy
-	   ISA crap.  */
-
-	return __kernel_ldbu(*(vucp)(addr + POLARIS_DENSE_IO_BASE));
-}
-
-__EXTERN_INLINE void polaris_outb(u8 b, unsigned long addr)
-{
-	__kernel_stb(b, *(vucp)(addr + POLARIS_DENSE_IO_BASE));
-	mb();
-}
-
-__EXTERN_INLINE u16 polaris_inw(unsigned long addr)
-{
-	return __kernel_ldwu(*(vusp)(addr + POLARIS_DENSE_IO_BASE));
-}
-
-__EXTERN_INLINE void polaris_outw(u16 b, unsigned long addr)
-{
-	__kernel_stw(b, *(vusp)(addr + POLARIS_DENSE_IO_BASE));
-	mb();
-}
-
-__EXTERN_INLINE u32 polaris_inl(unsigned long addr)
-{
-	return *(vuip)(addr + POLARIS_DENSE_IO_BASE);
-}
-
-__EXTERN_INLINE void polaris_outl(u32 b, unsigned long addr)
-{
-	*(vuip)(addr + POLARIS_DENSE_IO_BASE) = b;
-	mb();
-}
-
 /*
  * Memory functions.  Polaris allows all accesses (byte/word
  * as well as long/quad) to be done through dense space.
@@ -113,104 +70,35 @@ __EXTERN_INLINE void polaris_outl(u32 b, unsigned long addr)
  * We will only support DENSE access via BWX insns.
  */
 
-__EXTERN_INLINE u8 polaris_readb(unsigned long addr)
-{
-	return __kernel_ldbu(*(vucp)addr);
-}
-
-__EXTERN_INLINE u16 polaris_readw(unsigned long addr)
+__EXTERN_INLINE void __iomem *polaris_ioportmap(unsigned long addr)
 {
-	return __kernel_ldwu(*(vusp)addr);
+	return (void __iomem *)(addr + POLARIS_DENSE_IO_BASE);
 }
 
-__EXTERN_INLINE u32 polaris_readl(unsigned long addr)
+__EXTERN_INLINE void __iomem *polaris_ioremap(unsigned long addr,
+					      unsigned long size)
 {
-	return (*(vuip)addr) & 0xffffffff;
+	return (void __iomem *)(addr + POLARIS_DENSE_MEM_BASE);
 }
 
-__EXTERN_INLINE u64 polaris_readq(unsigned long addr)
-{
-	return *(vulp)addr;
-}
-
-__EXTERN_INLINE void polaris_writeb(u8 b, unsigned long addr)
-{
-	__kernel_stb(b, *(vucp)addr);
-}
-
-__EXTERN_INLINE void polaris_writew(u16 b, unsigned long addr)
-{
-	__kernel_stw(b, *(vusp)addr);
-}
-
-__EXTERN_INLINE void polaris_writel(u32 b, unsigned long addr)
-{
-	*(vuip)addr = b;
-}
-
-__EXTERN_INLINE void polaris_writeq(u64 b, unsigned long addr)
-{
-	*(vulp)addr = b;
-}
-
-__EXTERN_INLINE unsigned long polaris_ioremap(unsigned long addr,
-					      unsigned long size
-					      __attribute__((unused)))
-{
-	return addr + POLARIS_DENSE_MEM_BASE;
-}
-
-__EXTERN_INLINE void polaris_iounmap(unsigned long addr)
+__EXTERN_INLINE int polaris_is_ioaddr(unsigned long addr)
 {
-	return;
+	return addr >= POLARIS_SPARSE_MEM_BASE;
 }
 
-__EXTERN_INLINE int polaris_is_ioaddr(unsigned long addr)
+__EXTERN_INLINE int polaris_is_mmio(const volatile void __iomem *addr)
 {
-	return addr >= POLARIS_SPARSE_MEM_BASE;
+	return (unsigned long)addr < POLARIS_SPARSE_IO_BASE;
 }
 
-#undef vucp
-#undef vusp
-#undef vuip
-#undef vulp
-
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)		polaris_inb((unsigned long)(p))
-#define __inw(p)		polaris_inw((unsigned long)(p))
-#define __inl(p)		polaris_inl((unsigned long)(p))
-#define __outb(x,p)		polaris_outb((x),(unsigned long)(p))
-#define __outw(x,p)		polaris_outw((x),(unsigned long)(p))
-#define __outl(x,p)		polaris_outl((x),(unsigned long)(p))
-#define __readb(a)		polaris_readb((unsigned long)(a))
-#define __readw(a)		polaris_readw((unsigned long)(a))
-#define __readl(a)		polaris_readl((unsigned long)(a))
-#define __readq(a)		polaris_readq((unsigned long)(a))
-#define __writeb(x,a)		polaris_writeb((x),(unsigned long)(a))
-#define __writew(x,a)		polaris_writew((x),(unsigned long)(a))
-#define __writel(x,a)		polaris_writel((x),(unsigned long)(a))
-#define __writeq(x,a)		polaris_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)		polaris_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)		polaris_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)		polaris_is_ioaddr((unsigned long)(a))
-
-#define inb(p)			__inb(p)
-#define inw(p)			__inw(p)
-#define inl(p)			__inl(p)
-#define outb(x,p)		__outb((x),(p))
-#define outw(x,p)		__outw((x),(p))
-#define outl(x,p)		__outl((x),(p))
-#define __raw_readb(a)		__readb(a)
-#define __raw_readw(a)		__readw(a)
-#define __raw_readl(a)		__readl(a)
-#define __raw_readq(a)		__readq(a)
-#define __raw_writeb(v,a)	__writeb((v),(a))
-#define __raw_writew(v,a)	__writew((v),(a))
-#define __raw_writel(v,a)	__writel((v),(a))
-#define __raw_writeq(v,a)	__writeq((v),(a))
-
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX		polaris
+#define polaris_trivial_rw_bw	1
+#define polaris_trivial_rw_lq	1
+#define polaris_trivial_io_bw	1
+#define polaris_trivial_io_lq	1
+#define polaris_trivial_iounmap	1
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
diff --git a/include/asm-alpha/core_t2.h b/include/asm-alpha/core_t2.h
index ce5ae2a5c..5c1c40338 100644
--- a/include/asm-alpha/core_t2.h
+++ b/include/asm-alpha/core_t2.h
@@ -199,8 +199,8 @@ struct el_t2_procdata_mcheck {
 
 struct el_t2_logout_header {
 	unsigned int	elfl_size;	/* size in bytes of logout area. */
-	int		elfl_sbz1:31;	/* Should be zero. */
-	char		elfl_retry:1;	/* Retry flag. */
+	unsigned int	elfl_sbz1:31;	/* Should be zero. */
+	unsigned int	elfl_retry:1;	/* Retry flag. */
 	unsigned int	elfl_procoffset; /* Processor-specific offset. */
 	unsigned int	elfl_sysoffset;	 /* Offset of system-specific. */
 	unsigned int	elfl_error_type;	/* PAL error type code. */
@@ -357,13 +357,13 @@ struct el_t2_frame_corrected {
 #define vip	volatile int *
 #define vuip	volatile unsigned int *
 
-__EXTERN_INLINE u8 t2_inb(unsigned long addr)
+static inline u8 t2_inb(unsigned long addr)
 {
 	long result = *(vip) ((addr << 5) + T2_IO + 0x00);
 	return __kernel_extbl(result, addr & 3);
 }
 
-__EXTERN_INLINE void t2_outb(u8 b, unsigned long addr)
+static inline void t2_outb(u8 b, unsigned long addr)
 {
 	unsigned long w;
 
@@ -372,13 +372,13 @@ __EXTERN_INLINE void t2_outb(u8 b, unsigned long addr)
 	mb();
 }
 
-__EXTERN_INLINE u16 t2_inw(unsigned long addr)
+static inline u16 t2_inw(unsigned long addr)
 {
 	long result = *(vip) ((addr << 5) + T2_IO + 0x08);
 	return __kernel_extwl(result, addr & 3);
 }
 
-__EXTERN_INLINE void t2_outw(u16 b, unsigned long addr)
+static inline void t2_outw(u16 b, unsigned long addr)
 {
 	unsigned long w;
 
@@ -387,12 +387,12 @@ __EXTERN_INLINE void t2_outw(u16 b, unsigned long addr)
 	mb();
 }
 
-__EXTERN_INLINE u32 t2_inl(unsigned long addr)
+static inline u32 t2_inl(unsigned long addr)
 {
 	return *(vuip) ((addr << 5) + T2_IO + 0x18);
 }
 
-__EXTERN_INLINE void t2_outl(u32 b, unsigned long addr)
+static inline void t2_outl(u32 b, unsigned long addr)
 {
 	*(vuip) ((addr << 5) + T2_IO + 0x18) = b;
 	mb();
@@ -438,8 +438,9 @@ __EXTERN_INLINE void t2_outl(u32 b, unsigned long addr)
 
 static spinlock_t t2_hae_lock = SPIN_LOCK_UNLOCKED;
 
-__EXTERN_INLINE u8 t2_readb(unsigned long addr)
+__EXTERN_INLINE u8 t2_readb(const volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	unsigned long result, msb;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -451,8 +452,9 @@ __EXTERN_INLINE u8 t2_readb(unsigned long addr)
 	return __kernel_extbl(result, addr & 3);
 }
 
-__EXTERN_INLINE u16 t2_readw(unsigned long addr)
+__EXTERN_INLINE u16 t2_readw(const volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	unsigned long result, msb;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -468,8 +470,9 @@ __EXTERN_INLINE u16 t2_readw(unsigned long addr)
  * On SABLE with T2, we must use SPARSE memory even for 32-bit access,
  * because we cannot access all of DENSE without changing its HAE.
  */
-__EXTERN_INLINE u32 t2_readl(unsigned long addr)
+__EXTERN_INLINE u32 t2_readl(const volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	unsigned long result, msb;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -481,8 +484,9 @@ __EXTERN_INLINE u32 t2_readl(unsigned long addr)
 	return result & 0xffffffffUL;
 }
 
-__EXTERN_INLINE u64 t2_readq(unsigned long addr)
+__EXTERN_INLINE u64 t2_readq(const volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	unsigned long r0, r1, work, msb;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -496,8 +500,9 @@ __EXTERN_INLINE u64 t2_readq(unsigned long addr)
 	return r1 << 32 | r0;
 }
 
-__EXTERN_INLINE void t2_writeb(u8 b, unsigned long addr)
+__EXTERN_INLINE void t2_writeb(u8 b, volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	unsigned long msb, w;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -509,8 +514,9 @@ __EXTERN_INLINE void t2_writeb(u8 b, unsigned long addr)
 	spin_unlock_irqrestore(&t2_hae_lock, flags);
 }
 
-__EXTERN_INLINE void t2_writew(u16 b, unsigned long addr)
+__EXTERN_INLINE void t2_writew(u16 b, volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	unsigned long msb, w;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -526,8 +532,9 @@ __EXTERN_INLINE void t2_writew(u16 b, unsigned long addr)
  * On SABLE with T2, we must use SPARSE memory even for 32-bit access,
  * because we cannot access all of DENSE without changing its HAE.
  */
-__EXTERN_INLINE void t2_writel(u32 b, unsigned long addr)
+__EXTERN_INLINE void t2_writel(u32 b, volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	unsigned long msb;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -538,8 +545,9 @@ __EXTERN_INLINE void t2_writel(u32 b, unsigned long addr)
 	spin_unlock_irqrestore(&t2_hae_lock, flags);
 }
 
-__EXTERN_INLINE void t2_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE void t2_writeq(u64 b, volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	unsigned long msb, work;
 	unsigned long flags;
 	spin_lock_irqsave(&t2_hae_lock, flags);
@@ -552,16 +560,15 @@ __EXTERN_INLINE void t2_writeq(u64 b, unsigned long addr)
 	spin_unlock_irqrestore(&t2_hae_lock, flags);
 }
 
-__EXTERN_INLINE unsigned long t2_ioremap(unsigned long addr, 
-					 unsigned long size
-					 __attribute__((unused)))
+__EXTERN_INLINE void __iomem *t2_ioportmap(unsigned long addr)
 {
-	return addr;
+	return (void __iomem *)(addr + T2_IO);
 }
 
-__EXTERN_INLINE void t2_iounmap(unsigned long addr)
+__EXTERN_INLINE void __iomem *t2_ioremap(unsigned long addr, 
+					 unsigned long size)
 {
-	return;
+	return (void __iomem *)(addr + T2_DENSE_MEM);
 }
 
 __EXTERN_INLINE int t2_is_ioaddr(unsigned long addr)
@@ -569,30 +576,47 @@ __EXTERN_INLINE int t2_is_ioaddr(unsigned long addr)
 	return (long)addr >= 0;
 }
 
+__EXTERN_INLINE int t2_is_mmio(const volatile void __iomem *addr)
+{
+	return (unsigned long)addr >= T2_DENSE_MEM;
+}
+
+/* New-style ioread interface.  The mmio routines are so ugly for T2 that
+   it doesn't make sense to merge the pio and mmio routines.  */
+
+#define IOPORT(OS, NS)							\
+__EXTERN_INLINE unsigned int t2_ioread##NS(void __iomem *xaddr)		\
+{									\
+	if (t2_is_mmio(xaddr))						\
+		return t2_read##OS(xaddr - T2_DENSE_MEM);		\
+	else								\
+		return t2_in##OS((unsigned long)xaddr - T2_IO);		\
+}									\
+__EXTERN_INLINE void t2_iowrite##NS(u##NS b, void __iomem *xaddr)	\
+{									\
+	if (t2_is_mmio(xaddr))						\
+		t2_write##OS(b, xaddr - T2_DENSE_MEM);			\
+	else								\
+		t2_out##OS(b, (unsigned long)xaddr - T2_IO);		\
+}
+
+IOPORT(b, 8)
+IOPORT(w, 16)
+IOPORT(l, 32)
+
+#undef IOPORT
+
 #undef vip
 #undef vuip
 
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)		t2_inb((unsigned long)(p))
-#define __inw(p)		t2_inw((unsigned long)(p))
-#define __inl(p)		t2_inl((unsigned long)(p))
-#define __outb(x,p)		t2_outb((x),(unsigned long)(p))
-#define __outw(x,p)		t2_outw((x),(unsigned long)(p))
-#define __outl(x,p)		t2_outl((x),(unsigned long)(p))
-#define __readb(a)		t2_readb((unsigned long)(a))
-#define __readw(a)		t2_readw((unsigned long)(a))
-#define __readl(a)		t2_readl((unsigned long)(a))
-#define __readq(a)		t2_readq((unsigned long)(a))
-#define __writeb(x,a)		t2_writeb((x),(unsigned long)(a))
-#define __writew(x,a)		t2_writew((x),(unsigned long)(a))
-#define __writel(x,a)		t2_writel((x),(unsigned long)(a))
-#define __writeq(x,a)		t2_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)		t2_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)		t2_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)		t2_is_ioaddr((unsigned long)(a))
-
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX		t2
+#define t2_trivial_rw_bw	0
+#define t2_trivial_rw_lq	0
+#define t2_trivial_io_bw	0
+#define t2_trivial_io_lq	0
+#define t2_trivial_iounmap	1
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
diff --git a/include/asm-alpha/core_titan.h b/include/asm-alpha/core_titan.h
index 39959ed0e..a64ccbff7 100644
--- a/include/asm-alpha/core_titan.h
+++ b/include/asm-alpha/core_titan.h
@@ -377,149 +377,33 @@ struct el_PRIVATEER_envdata_mcheck {
  * can only use linear accesses to get at PCI/AGP memory and I/O spaces.
  */
 
-#define vucp	volatile unsigned char *
-#define vusp	volatile unsigned short *
-#define vuip	volatile unsigned int *
-#define vulp	volatile unsigned long *
-
-__EXTERN_INLINE u8 titan_inb(unsigned long addr)
-{
-	/* ??? I wish I could get rid of this.  But there's no ioremap
-	   equivalent for I/O space.  PCI I/O can be forced into the
-	   correct hose's I/O region, but that doesn't take care of
-	   legacy ISA crap.  */
-
-	addr += TITAN_IO_BIAS;
-	return __kernel_ldbu(*(vucp)addr);
-}
-
-__EXTERN_INLINE void titan_outb(u8 b, unsigned long addr)
-{
-	addr += TITAN_IO_BIAS;
-	__kernel_stb(b, *(vucp)addr);
-	mb();
-}
-
-__EXTERN_INLINE u16 titan_inw(unsigned long addr)
-{
-	addr += TITAN_IO_BIAS;
-	return __kernel_ldwu(*(vusp)addr);
-}
-
-__EXTERN_INLINE void titan_outw(u16 b, unsigned long addr)
-{
-	addr += TITAN_IO_BIAS;
-	__kernel_stw(b, *(vusp)addr);
-	mb();
-}
-
-__EXTERN_INLINE u32 titan_inl(unsigned long addr)
-{
-	addr += TITAN_IO_BIAS;
-	return *(vuip)addr;
-}
-
-__EXTERN_INLINE void titan_outl(u32 b, unsigned long addr)
-{
-	addr += TITAN_IO_BIAS;
-	*(vuip)addr = b;
-	mb();
-}
-
 /*
  * Memory functions.  all accesses are done through linear space.
  */
 
-extern unsigned long titan_ioremap(unsigned long addr, unsigned long size);
-extern void titan_iounmap(unsigned long addr);
-
-__EXTERN_INLINE int titan_is_ioaddr(unsigned long addr)
-{
-	return addr >= TITAN_BASE;
-}
-
-__EXTERN_INLINE u8 titan_readb(unsigned long addr)
-{
-	return __kernel_ldbu(*(vucp)addr);
-}
-
-__EXTERN_INLINE u16 titan_readw(unsigned long addr)
-{
-	return __kernel_ldwu(*(vusp)addr);
-}
-
-__EXTERN_INLINE u32 titan_readl(unsigned long addr)
-{
-	return (*(vuip)addr) & 0xffffffff;
-}
-
-__EXTERN_INLINE u64 titan_readq(unsigned long addr)
+__EXTERN_INLINE void __iomem *titan_ioportmap(unsigned long addr)
 {
-	return *(vulp)addr;
+	return (void __iomem *)(addr + TITAN_IO_BIAS);
 }
 
-__EXTERN_INLINE void titan_writeb(u8 b, unsigned long addr)
-{
-	__kernel_stb(b, *(vucp)addr);
-}
+extern void __iomem *titan_ioremap(unsigned long addr, unsigned long size);
+extern void titan_iounmap(volatile void __iomem *addr);
 
-__EXTERN_INLINE void titan_writew(u16 b, unsigned long addr)
-{
-	__kernel_stw(b, *(vusp)addr);
-}
-
-__EXTERN_INLINE void titan_writel(u32 b, unsigned long addr)
+__EXTERN_INLINE int titan_is_ioaddr(unsigned long addr)
 {
-	*(vuip)addr = b;
+	return addr >= TITAN_BASE;
 }
 
-__EXTERN_INLINE void titan_writeq(u64 b, unsigned long addr)
-{
-	*(vulp)addr = b;
-}
+extern int titan_is_mmio(const volatile void __iomem *addr);
 
-#undef vucp
-#undef vusp
-#undef vuip
-#undef vulp
-
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)		titan_inb((unsigned long)(p))
-#define __inw(p)		titan_inw((unsigned long)(p))
-#define __inl(p)		titan_inl((unsigned long)(p))
-#define __outb(x,p)		titan_outb((x),(unsigned long)(p))
-#define __outw(x,p)		titan_outw((x),(unsigned long)(p))
-#define __outl(x,p)		titan_outl((x),(unsigned long)(p))
-#define __readb(a)		titan_readb((unsigned long)(a))
-#define __readw(a)		titan_readw((unsigned long)(a))
-#define __readl(a)		titan_readl((unsigned long)(a))
-#define __readq(a)		titan_readq((unsigned long)(a))
-#define __writeb(x,a)		titan_writeb((x),(unsigned long)(a))
-#define __writew(x,a)		titan_writew((x),(unsigned long)(a))
-#define __writel(x,a)		titan_writel((x),(unsigned long)(a))
-#define __writeq(x,a)		titan_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)		titan_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)		titan_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)		titan_is_ioaddr((unsigned long)(a))
-
-#define inb(port) 		__inb((port))
-#define inw(port) 		__inw((port))
-#define inl(port) 		__inl((port))
-#define outb(v, port) 		__outb((v),(port))
-#define outw(v, port) 		__outw((v),(port))
-#define outl(v, port) 		__outl((v),(port))
-
-#define __raw_readb(a)		__readb((unsigned long)(a))
-#define __raw_readw(a)		__readw((unsigned long)(a))
-#define __raw_readl(a)		__readl((unsigned long)(a))
-#define __raw_readq(a)		__readq((unsigned long)(a))
-#define __raw_writeb(v,a)	__writeb((v),(unsigned long)(a))
-#define __raw_writew(v,a)	__writew((v),(unsigned long)(a))
-#define __raw_writel(v,a)	__writel((v),(unsigned long)(a))
-#define __raw_writeq(v,a)	__writeq((v),(unsigned long)(a))
-
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX		titan
+#define titan_trivial_rw_bw	1
+#define titan_trivial_rw_lq	1
+#define titan_trivial_io_bw	1
+#define titan_trivial_io_lq	1
+#define titan_trivial_iounmap	0
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
diff --git a/include/asm-alpha/core_tsunami.h b/include/asm-alpha/core_tsunami.h
index 7c815eb42..44e635d2c 100644
--- a/include/asm-alpha/core_tsunami.h
+++ b/include/asm-alpha/core_tsunami.h
@@ -299,69 +299,19 @@ struct el_TSUNAMI_sysdata_mcheck {
  * can only use linear accesses to get at PCI memory and I/O spaces.
  */
 
-#define vucp	volatile unsigned char *
-#define vusp	volatile unsigned short *
-#define vuip	volatile unsigned int *
-#define vulp	volatile unsigned long *
-
-__EXTERN_INLINE u8 tsunami_inb(unsigned long addr)
-{
-	/* ??? I wish I could get rid of this.  But there's no ioremap
-	   equivalent for I/O space.  PCI I/O can be forced into the
-	   correct hose's I/O region, but that doesn't take care of
-	   legacy ISA crap.  */
-
-	addr += TSUNAMI_IO_BIAS;
-	return __kernel_ldbu(*(vucp)addr);
-}
-
-__EXTERN_INLINE void tsunami_outb(u8 b, unsigned long addr)
-{
-	addr += TSUNAMI_IO_BIAS;
-	__kernel_stb(b, *(vucp)addr);
-	mb();
-}
-
-__EXTERN_INLINE u16 tsunami_inw(unsigned long addr)
-{
-	addr += TSUNAMI_IO_BIAS;
-	return __kernel_ldwu(*(vusp)addr);
-}
-
-__EXTERN_INLINE void tsunami_outw(u16 b, unsigned long addr)
-{
-	addr += TSUNAMI_IO_BIAS;
-	__kernel_stw(b, *(vusp)addr);
-	mb();
-}
-
-__EXTERN_INLINE u32 tsunami_inl(unsigned long addr)
-{
-	addr += TSUNAMI_IO_BIAS;
-	return *(vuip)addr;
-}
-
-__EXTERN_INLINE void tsunami_outl(u32 b, unsigned long addr)
-{
-	addr += TSUNAMI_IO_BIAS;
-	*(vuip)addr = b;
-	mb();
-}
-
 /*
  * Memory functions.  all accesses are done through linear space.
  */
 
-__EXTERN_INLINE unsigned long tsunami_ioremap(unsigned long addr, 
-					      unsigned long size
-					      __attribute__((unused)))
+__EXTERN_INLINE void __iomem *tsunami_ioportmap(unsigned long addr)
 {
-	return addr + TSUNAMI_MEM_BIAS;
+	return (void __iomem *)(addr + TSUNAMI_IO_BIAS);
 }
 
-__EXTERN_INLINE void tsunami_iounmap(unsigned long addr)
+__EXTERN_INLINE void __iomem *tsunami_ioremap(unsigned long addr, 
+					      unsigned long size)
 {
-	return;
+	return (void __iomem *)(addr + TSUNAMI_MEM_BIAS);
 }
 
 __EXTERN_INLINE int tsunami_is_ioaddr(unsigned long addr)
@@ -369,87 +319,20 @@ __EXTERN_INLINE int tsunami_is_ioaddr(unsigned long addr)
 	return addr >= TSUNAMI_BASE;
 }
 
-__EXTERN_INLINE u8 tsunami_readb(unsigned long addr)
-{
-	return __kernel_ldbu(*(vucp)addr);
-}
-
-__EXTERN_INLINE u16 tsunami_readw(unsigned long addr)
-{
-	return __kernel_ldwu(*(vusp)addr);
-}
-
-__EXTERN_INLINE u32 tsunami_readl(unsigned long addr)
-{
-	return *(vuip)addr;
-}
-
-__EXTERN_INLINE u64 tsunami_readq(unsigned long addr)
-{
-	return *(vulp)addr;
-}
-
-__EXTERN_INLINE void tsunami_writeb(u8 b, unsigned long addr)
-{
-	__kernel_stb(b, *(vucp)addr);
-}
-
-__EXTERN_INLINE void tsunami_writew(u16 b, unsigned long addr)
-{
-	__kernel_stw(b, *(vusp)addr);
-}
-
-__EXTERN_INLINE void tsunami_writel(u32 b, unsigned long addr)
-{
-	*(vuip)addr = b;
-}
-
-__EXTERN_INLINE void tsunami_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE int tsunami_is_mmio(const volatile void __iomem *xaddr)
 {
-	*(vulp)addr = b;
+	unsigned long addr = (unsigned long) xaddr;
+	return (addr & 0x100000000UL) == 0;
 }
 
-#undef vucp
-#undef vusp
-#undef vuip
-#undef vulp
-
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)		tsunami_inb((unsigned long)(p))
-#define __inw(p)		tsunami_inw((unsigned long)(p))
-#define __inl(p)		tsunami_inl((unsigned long)(p))
-#define __outb(x,p)		tsunami_outb((x),(unsigned long)(p))
-#define __outw(x,p)		tsunami_outw((x),(unsigned long)(p))
-#define __outl(x,p)		tsunami_outl((x),(unsigned long)(p))
-#define __readb(a)		tsunami_readb((unsigned long)(a))
-#define __readw(a)		tsunami_readw((unsigned long)(a))
-#define __readl(a)		tsunami_readl((unsigned long)(a))
-#define __readq(a)		tsunami_readq((unsigned long)(a))
-#define __writeb(x,a)		tsunami_writeb((x),(unsigned long)(a))
-#define __writew(x,a)		tsunami_writew((x),(unsigned long)(a))
-#define __writel(x,a)		tsunami_writel((x),(unsigned long)(a))
-#define __writeq(x,a)		tsunami_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)		tsunami_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)		tsunami_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)		tsunami_is_ioaddr((unsigned long)(a))
-
-#define inb(p)			__inb(p)
-#define inw(p)			__inw(p)
-#define inl(p)			__inl(p)
-#define outb(x,p)		__outb((x),(p))
-#define outw(x,p)		__outw((x),(p))
-#define outl(x,p)		__outl((x),(p))
-#define __raw_readb(a)		__readb(a)
-#define __raw_readw(a)		__readw(a)
-#define __raw_readl(a)		__readl(a)
-#define __raw_readq(a)		__readq(a)
-#define __raw_writeb(v,a)	__writeb((v),(a))
-#define __raw_writew(v,a)	__writew((v),(a))
-#define __raw_writel(v,a)	__writel((v),(a))
-#define __raw_writeq(v,a)	__writeq((v),(a))
-
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX		tsunami
+#define tsunami_trivial_rw_bw	1
+#define tsunami_trivial_rw_lq	1
+#define tsunami_trivial_io_bw	1
+#define tsunami_trivial_io_lq	1
+#define tsunami_trivial_iounmap	1
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
diff --git a/include/asm-alpha/core_wildfire.h b/include/asm-alpha/core_wildfire.h
index 7b8bbd117..12af803d4 100644
--- a/include/asm-alpha/core_wildfire.h
+++ b/include/asm-alpha/core_wildfire.h
@@ -273,69 +273,19 @@ typedef struct {
 #define __IO_EXTERN_INLINE
 #endif
 
-#define vucp	volatile unsigned char *
-#define vusp	volatile unsigned short *
-#define vuip	volatile unsigned int *
-#define vulp	volatile unsigned long *
-
-__EXTERN_INLINE u8 wildfire_inb(unsigned long addr)
-{
-	/* ??? I wish I could get rid of this.  But there's no ioremap
-	   equivalent for I/O space.  PCI I/O can be forced into the
-	   correct hose's I/O region, but that doesn't take care of
-	   legacy ISA crap.  */
-
-	addr += WILDFIRE_IO_BIAS;
-	return __kernel_ldbu(*(vucp)addr);
-}
-
-__EXTERN_INLINE void wildfire_outb(u8 b, unsigned long addr)
-{
-	addr += WILDFIRE_IO_BIAS;
-	__kernel_stb(b, *(vucp)addr);
-	mb();
-}
-
-__EXTERN_INLINE u16 wildfire_inw(unsigned long addr)
-{
-	addr += WILDFIRE_IO_BIAS;
-	return __kernel_ldwu(*(vusp)addr);
-}
-
-__EXTERN_INLINE void wildfire_outw(u16 b, unsigned long addr)
-{
-	addr += WILDFIRE_IO_BIAS;
-	__kernel_stw(b, *(vusp)addr);
-	mb();
-}
-
-__EXTERN_INLINE u32 wildfire_inl(unsigned long addr)
-{
-	addr += WILDFIRE_IO_BIAS;
-	return *(vuip)addr;
-}
-
-__EXTERN_INLINE void wildfire_outl(u32 b, unsigned long addr)
-{
-	addr += WILDFIRE_IO_BIAS;
-	*(vuip)addr = b;
-	mb();
-}
-
 /*
  * Memory functions.  all accesses are done through linear space.
  */
 
-__EXTERN_INLINE unsigned long wildfire_ioremap(unsigned long addr, 
-					       unsigned long size
-					       __attribute__((unused)))
+__EXTERN_INLINE void __iomem *wildfire_ioportmap(unsigned long addr)
 {
-	return addr + WILDFIRE_MEM_BIAS;
+	return (void __iomem *)(addr + WILDFIRE_IO_BIAS);
 }
 
-__EXTERN_INLINE void wildfire_iounmap(unsigned long addr)
+__EXTERN_INLINE void __iomem *wildfire_ioremap(unsigned long addr, 
+					       unsigned long size)
 {
-	return;
+	return (void __iomem *)(addr + WILDFIRE_MEM_BIAS);
 }
 
 __EXTERN_INLINE int wildfire_is_ioaddr(unsigned long addr)
@@ -343,87 +293,20 @@ __EXTERN_INLINE int wildfire_is_ioaddr(unsigned long addr)
 	return addr >= WILDFIRE_BASE;
 }
 
-__EXTERN_INLINE u8 wildfire_readb(unsigned long addr)
-{
-	return __kernel_ldbu(*(vucp)addr);
-}
-
-__EXTERN_INLINE u16 wildfire_readw(unsigned long addr)
-{
-	return __kernel_ldwu(*(vusp)addr);
-}
-
-__EXTERN_INLINE u32 wildfire_readl(unsigned long addr)
-{
-	return (*(vuip)addr) & 0xffffffff;
-}
-
-__EXTERN_INLINE u64 wildfire_readq(unsigned long addr)
-{
-	return *(vulp)addr;
-}
-
-__EXTERN_INLINE void wildfire_writeb(u8 b, unsigned long addr)
-{
-	__kernel_stb(b, *(vucp)addr);
-}
-
-__EXTERN_INLINE void wildfire_writew(u16 b, unsigned long addr)
-{
-	__kernel_stw(b, *(vusp)addr);
-}
-
-__EXTERN_INLINE void wildfire_writel(u32 b, unsigned long addr)
-{
-	*(vuip)addr = b;
-}
-
-__EXTERN_INLINE void wildfire_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE int wildfire_is_mmio(const volatile void __iomem *xaddr)
 {
-	*(vulp)addr = b;
+	unsigned long addr = (unsigned long)addr;
+	return (addr & 0x100000000UL) == 0;
 }
 
-#undef vucp
-#undef vusp
-#undef vuip
-#undef vulp
-
-#ifdef __WANT_IO_DEF
-
-#define __inb(p)		wildfire_inb((unsigned long)(p))
-#define __inw(p)		wildfire_inw((unsigned long)(p))
-#define __inl(p)		wildfire_inl((unsigned long)(p))
-#define __outb(x,p)		wildfire_outb((x),(unsigned long)(p))
-#define __outw(x,p)		wildfire_outw((x),(unsigned long)(p))
-#define __outl(x,p)		wildfire_outl((x),(unsigned long)(p))
-#define __readb(a)		wildfire_readb((unsigned long)(a))
-#define __readw(a)		wildfire_readw((unsigned long)(a))
-#define __readl(a)		wildfire_readl((unsigned long)(a))
-#define __readq(a)		wildfire_readq((unsigned long)(a))
-#define __writeb(x,a)		wildfire_writeb((x),(unsigned long)(a))
-#define __writew(x,a)		wildfire_writew((x),(unsigned long)(a))
-#define __writel(x,a)		wildfire_writel((x),(unsigned long)(a))
-#define __writeq(x,a)		wildfire_writeq((x),(unsigned long)(a))
-#define __ioremap(a,s)		wildfire_ioremap((unsigned long)(a),(s))
-#define __iounmap(a)		wildfire_iounmap((unsigned long)(a))
-#define __is_ioaddr(a)		wildfire_is_ioaddr((unsigned long)(a))
-
-#define inb(p)			__inb(p)
-#define inw(p)			__inw(p)
-#define inl(p)			__inl(p)
-#define outb(x,p)		__outb((x),(p))
-#define outw(x,p)		__outw((x),(p))
-#define outl(x,p)		__outl((x),(p))
-#define __raw_readb(a)		__readb(a)
-#define __raw_readw(a)		__readw(a)
-#define __raw_readl(a)		__readl(a)
-#define __raw_readq(a)		__readq(a)
-#define __raw_writeb(v,a)	__writeb((v),(a))
-#define __raw_writew(v,a)	__writew((v),(a))
-#define __raw_writel(v,a)	__writel((v),(a))
-#define __raw_writeq(v,a)	__writeq((v),(a))
-
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX			wildfire
+#define wildfire_trivial_rw_bw		1
+#define wildfire_trivial_rw_lq		1
+#define wildfire_trivial_io_bw		1
+#define wildfire_trivial_io_lq		1
+#define wildfire_trivial_iounmap	1
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
diff --git a/include/asm-alpha/dma-mapping.h b/include/asm-alpha/dma-mapping.h
index e7e16901f..0faad459a 100644
--- a/include/asm-alpha/dma-mapping.h
+++ b/include/asm-alpha/dma-mapping.h
@@ -1 +1,63 @@
-#include <asm-generic/dma-mapping.h>
+#ifndef _ALPHA_DMA_MAPPING_H
+#define _ALPHA_DMA_MAPPING_H
+
+#include <linux/config.h>
+
+#ifdef CONFIG_PCI
+
+#include <linux/pci.h>
+
+#define dma_map_single(dev, va, size, dir)		\
+		pci_map_single(alpha_gendev_to_pci(dev), va, size, dir)
+#define dma_unmap_single(dev, addr, size, dir)		\
+		pci_unmap_single(alpha_gendev_to_pci(dev), addr, size, dir)
+#define dma_alloc_coherent(dev, size, addr, gfp)	\
+		pci_alloc_consistent(alpha_gendev_to_pci(dev), size, addr)
+#define dma_free_coherent(dev, size, va, addr)		\
+		pci_free_consistent(alpha_gendev_to_pci(dev), size, va, addr)
+#define dma_map_page(dev, page, off, size, dir)		\
+		pci_map_single(alpha_gendev_to_pci(dev), page, off, size, dir)
+#define dma_unmap_page(dev, addr, size, dir)		\
+		pci_unmap_page(alpha_gendev_to_pci(dev), addr, size, dir)
+#define dma_map_sg(dev, sg, nents, dir)			\
+		pci_map_sg(alpha_gendev_to_pci(dev), sg, nents, dir)
+#define dma_unmap_sg(dev, sg, nents, dir)		\
+		pci_unmap_sg(alpha_gendev_to_pci(dev), sg, nents, dir)
+#define dma_supported(dev, mask)			\
+		pci_dma_supported(alpha_gendev_to_pci(dev), mask)
+
+#else	/* no PCI - no IOMMU. */
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+			 dma_addr_t *dma_handle, int gfp);
+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+	       enum dma_data_direction direction);
+
+#define dma_free_coherent(dev, size, va, addr)		\
+		free_pages((unsigned long)va, get_order(size))
+#define dma_supported(dev, mask)		(mask < 0x00ffffffUL ? 0 : 1)
+#define dma_map_single(dev, va, size, dir)	virt_to_phys(va)
+#define dma_map_page(dev, page, off, size, dir)	(page_to_pa(page) + off)
+
+#define dma_unmap_single(dev, addr, size, dir)	do { } while (0)
+#define dma_unmap_page(dev, addr, size, dir)	do { } while (0)
+#define dma_unmap_sg(dev, sg, nents, dir)	do { } while (0)
+
+#endif	/* !CONFIG_PCI */
+
+#define dma_alloc_noncoherent(d, s, h, f)	dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h)	dma_free_coherent(d, s, v, h)
+#define dma_is_consistent(dev)			(1)
+
+int dma_set_mask(struct device *dev, u64 mask);
+
+#define dma_sync_single_for_cpu(dev, addr, size, dir)	  do { } while (0)
+#define dma_sync_single_for_device(dev, addr, size, dir)  do { } while (0)
+#define dma_sync_single_range(dev, addr, off, size, dir)  do { } while (0)
+#define dma_sync_sg_for_cpu(dev, sg, nents, dir)	  do { } while (0)
+#define dma_sync_sg_for_device(dev, sg, nents, dir)	  do { } while (0)
+#define dma_cache_sync(va, size, dir)			  do { } while (0)
+
+#define dma_get_cache_alignment()			  L1_CACHE_BYTES
+
+#endif	/* _ALPHA_DMA_MAPPING_H */
diff --git a/include/asm-alpha/hardirq.h b/include/asm-alpha/hardirq.h
index e188ed9cf..10be402fc 100644
--- a/include/asm-alpha/hardirq.h
+++ b/include/asm-alpha/hardirq.h
@@ -39,20 +39,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially nestable IRQ sources in the system
@@ -64,28 +50,7 @@ typedef struct {
 #error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
-
-
-#ifdef CONFIG_PREEMPT
-#define in_atomic()	(preempt_count() != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-#define in_atomic()	(preempt_count() != 0)
-#define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-# endif
 #define irq_exit()						\
 do {								\
 		preempt_count() -= IRQ_EXIT_OFFSET;		\
@@ -95,10 +60,4 @@ do {								\
 		preempt_enable_no_resched();			\
 } while (0)
 
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else
-  extern void synchronize_irq(unsigned int irq);
-#endif /* CONFIG_SMP */
-
 #endif /* _ALPHA_HARDIRQ_H */
diff --git a/include/asm-alpha/io.h b/include/asm-alpha/io.h
index 5f4a74357..9e9de8e27 100644
--- a/include/asm-alpha/io.h
+++ b/include/asm-alpha/io.h
@@ -1,6 +1,20 @@
 #ifndef __ALPHA_IO_H
 #define __ALPHA_IO_H
 
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <asm/compiler.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/machvec.h>
+#include <asm/hwrpb.h>
+
+/* The generic header contains only prototypes.  Including it ensures that
+   the implementation we have here matches that interface.  */
+#include <asm-generic/iomap.h>
+
 /* We don't use IO slowdowns on the Alpha, but.. */
 #define __SLOW_DOWN_IO	do { } while (0)
 #define SLOW_DOWN_IO	do { } while (0)
@@ -14,14 +28,6 @@
 #define IDENT_ADDR     0xfffffc0000000000UL
 #endif
 
-#ifdef __KERNEL__
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/machvec.h>
-#include <asm/hwrpb.h>
-
 /*
  * We try to avoid hae updates (thus the cache), but when we
  * do need to update the hae, we need to do it atomically, so
@@ -88,6 +94,9 @@ static inline void * phys_to_virt(unsigned long address)
 /* This depends on working iommu.  */
 #define BIO_VMERGE_BOUNDARY	(alpha_mv.mv_pci_tbi ? PAGE_SIZE : 0)
 
+/* Maximum PIO space address supported?  */
+#define IO_SPACE_LIMIT 0xffff
+
 /*
  * Change addresses as seen by the kernel (virtual) to addresses as
  * seen by a device (bus), and vice versa.
@@ -118,67 +127,81 @@ static inline void *bus_to_virt(unsigned long address)
 	return (long)address <= 0 ? NULL : virt;
 }
 
-#else /* !__KERNEL__ */
-
-/*
- * Define actual functions in private name-space so it's easier to
- * accommodate things like XFree or svgalib that like to define their
- * own versions of inb etc.
- */
-extern void __sethae (unsigned long addr);	/* syscall */
-extern void _sethae (unsigned long addr);	/* cached version */
-
-#endif /* !__KERNEL__ */
-
 /*
  * There are different chipsets to interface the Alpha CPUs to the world.
  */
 
-#ifdef __KERNEL__
+#define IO_CONCAT(a,b)	_IO_CONCAT(a,b)
+#define _IO_CONCAT(a,b)	a ## _ ## b
+
 #ifdef CONFIG_ALPHA_GENERIC
 
 /* In a generic kernel, we always go through the machine vector.  */
 
-# define __inb(p)	alpha_mv.mv_inb((unsigned long)(p))
-# define __inw(p)	alpha_mv.mv_inw((unsigned long)(p))
-# define __inl(p)	alpha_mv.mv_inl((unsigned long)(p))
-# define __outb(x,p)	alpha_mv.mv_outb((x),(unsigned long)(p))
-# define __outw(x,p)	alpha_mv.mv_outw((x),(unsigned long)(p))
-# define __outl(x,p)	alpha_mv.mv_outl((x),(unsigned long)(p))
-
-# define __readb(a)	alpha_mv.mv_readb((unsigned long)(a))
-# define __readw(a)	alpha_mv.mv_readw((unsigned long)(a))
-# define __readl(a)	alpha_mv.mv_readl((unsigned long)(a))
-# define __readq(a)	alpha_mv.mv_readq((unsigned long)(a))
-# define __writeb(v,a)	alpha_mv.mv_writeb((v),(unsigned long)(a))
-# define __writew(v,a)	alpha_mv.mv_writew((v),(unsigned long)(a))
-# define __writel(v,a)	alpha_mv.mv_writel((v),(unsigned long)(a))
-# define __writeq(v,a)	alpha_mv.mv_writeq((v),(unsigned long)(a))
-
-# define __ioremap(a,s)	alpha_mv.mv_ioremap((unsigned long)(a),(s))
-# define __iounmap(a)   alpha_mv.mv_iounmap((unsigned long)(a))
-# define __is_ioaddr(a)	alpha_mv.mv_is_ioaddr((unsigned long)(a))
-
-# define inb		__inb
-# define inw		__inw
-# define inl		__inl
-# define outb		__outb
-# define outw		__outw
-# define outl		__outl
-
-# define __raw_readb	__readb
-# define __raw_readw	__readw
-# define __raw_readl	__readl
-# define __raw_readq	__readq
-# define __raw_writeb	__writeb
-# define __raw_writew	__writew
-# define __raw_writel	__writel
-# define __raw_writeq	__writeq
+#define REMAP1(TYPE, NAME, QUAL)					\
+static inline TYPE generic_##NAME(QUAL void __iomem *addr)		\
+{									\
+	return alpha_mv.mv_##NAME(addr);				\
+}
+
+#define REMAP2(TYPE, NAME, QUAL)					\
+static inline void generic_##NAME(TYPE b, QUAL void __iomem *addr)	\
+{									\
+	alpha_mv.mv_##NAME(b, addr);					\
+}
 
-#else
+REMAP1(unsigned int, ioread8, /**/)
+REMAP1(unsigned int, ioread16, /**/)
+REMAP1(unsigned int, ioread32, /**/)
+REMAP1(u8, readb, const volatile)
+REMAP1(u16, readw, const volatile)
+REMAP1(u32, readl, const volatile)
+REMAP1(u64, readq, const volatile)
+
+REMAP2(u8, iowrite8, /**/)
+REMAP2(u16, iowrite16, /**/)
+REMAP2(u32, iowrite32, /**/)
+REMAP2(u8, writeb, volatile)
+REMAP2(u16, writew, volatile)
+REMAP2(u32, writel, volatile)
+REMAP2(u64, writeq, volatile)
+
+#undef REMAP1
+#undef REMAP2
+
+static inline void __iomem *generic_ioportmap(unsigned long a)
+{
+	return alpha_mv.mv_ioportmap(a);
+}
+
+static inline void __iomem *generic_ioremap(unsigned long a, unsigned long s)
+{
+	return alpha_mv.mv_ioremap(a, s);
+}
+
+static inline void generic_iounmap(volatile void __iomem *a)
+{
+	return alpha_mv.mv_iounmap(a);
+}
+
+static inline int generic_is_ioaddr(unsigned long a)
+{
+	return alpha_mv.mv_is_ioaddr(a);
+}
 
-/* Control how and what gets defined within the core logic headers.  */
-#define __WANT_IO_DEF
+static inline int generic_is_mmio(const volatile void __iomem *a)
+{
+	return alpha_mv.mv_is_mmio(a);
+}
+
+#define __IO_PREFIX		generic
+#define generic_trivial_rw_bw	0
+#define generic_trivial_rw_lq	0
+#define generic_trivial_io_bw	0
+#define generic_trivial_io_lq	0
+#define generic_trivial_iounmap	0
+
+#else
 
 #if defined(CONFIG_ALPHA_APECS)
 # include <asm/core_apecs.h>
@@ -208,245 +231,281 @@ extern void _sethae (unsigned long addr);	/* cached version */
 #error "What system is this?"
 #endif
 
-#undef __WANT_IO_DEF
-
 #endif /* GENERIC */
-#endif /* __KERNEL__ */
 
 /*
- * The convention used for inb/outb etc. is that names starting with
- * two underscores are the inline versions, names starting with a
- * single underscore are proper functions, and names starting with a
- * letter are macros that map in some way to inline or proper function
- * versions.  Not all that pretty, but before you change it, be sure
- * to convince yourself that it won't break anything (in particular
- * module support).
+ * We always have external versions of these routines.
  */
-extern u8		_inb (unsigned long port);
-extern u16		_inw (unsigned long port);
-extern u32		_inl (unsigned long port);
-extern void		_outb (u8 b,unsigned long port);
-extern void		_outw (u16 w,unsigned long port);
-extern void		_outl (u32 l,unsigned long port);
-extern u8		_readb(unsigned long addr);
-extern u16		_readw(unsigned long addr);
-extern u32		_readl(unsigned long addr);
-extern u64		_readq(unsigned long addr);
-extern void		_writeb(u8 b, unsigned long addr);
-extern void		_writew(u16 b, unsigned long addr);
-extern void		_writel(u32 b, unsigned long addr);
-extern void		_writeq(u64 b, unsigned long addr);
+extern u8		inb(unsigned long port);
+extern u16		inw(unsigned long port);
+extern u32		inl(unsigned long port);
+extern void		outb(u8 b, unsigned long port);
+extern void		outw(u16 b, unsigned long port);
+extern void		outl(u32 b, unsigned long port);
+
+extern u8		readb(const volatile void __iomem *addr);
+extern u16		readw(const volatile void __iomem *addr);
+extern u32		readl(const volatile void __iomem *addr);
+extern u64		readq(const volatile void __iomem *addr);
+extern void		writeb(u8 b, volatile void __iomem *addr);
+extern void		writew(u16 b, volatile void __iomem *addr);
+extern void		writel(u32 b, volatile void __iomem *addr);
+extern void		writeq(u64 b, volatile void __iomem *addr);
+
+extern u8		__raw_readb(const volatile void __iomem *addr);
+extern u16		__raw_readw(const volatile void __iomem *addr);
+extern u32		__raw_readl(const volatile void __iomem *addr);
+extern u64		__raw_readq(const volatile void __iomem *addr);
+extern void		__raw_writeb(u8 b, volatile void __iomem *addr);
+extern void		__raw_writew(u16 b, volatile void __iomem *addr);
+extern void		__raw_writel(u32 b, volatile void __iomem *addr);
+extern void		__raw_writeq(u64 b, volatile void __iomem *addr);
 
-#ifdef __KERNEL__
 /*
- * The platform header files may define some of these macros to use
- * the inlined versions where appropriate.  These macros may also be
- * redefined by userlevel programs.
+ * Mapping from port numbers to __iomem space is pretty easy.
  */
-#ifndef inb
-# define inb(p)		_inb(p)
-#endif
-#ifndef inw
-# define inw(p)		_inw(p)
-#endif
-#ifndef inl
-# define inl(p)		_inl(p)
-#endif
-#ifndef outb
-# define outb(b,p)	_outb((b),(p))
-#endif
-#ifndef outw
-# define outw(w,p)	_outw((w),(p))
-#endif
-#ifndef outl
-# define outl(l,p)	_outl((l),(p))
-#endif
 
-#ifndef inb_p
-# define inb_p		inb
-#endif
-#ifndef inw_p
-# define inw_p		inw
-#endif
-#ifndef inl_p
-# define inl_p		inl
-#endif
+/* These two have to be extern inline because of the extern prototype from
+   <asm-generic/iomap.h>.  It is not legal to mix "extern" and "static" for
+   the same declaration.  */
+extern inline void __iomem *ioport_map(unsigned long port, unsigned int size)
+{
+	return IO_CONCAT(__IO_PREFIX,ioportmap) (port);
+}
 
-#ifndef outb_p
-# define outb_p		outb
-#endif
-#ifndef outw_p
-# define outw_p		outw
-#endif
-#ifndef outl_p
-# define outl_p		outl
-#endif
+extern inline void ioport_unmap(void __iomem *addr)
+{
+}
 
-#define IO_SPACE_LIMIT 0xffff
+static inline void __iomem *ioremap(unsigned long port, unsigned long size)
+{
+	return IO_CONCAT(__IO_PREFIX,ioremap) (port, size);
+}
 
-#else 
+static inline void __iomem * ioremap_nocache(unsigned long offset,
+					     unsigned long size)
+{
+	return ioremap(offset, size);
+} 
 
-/* Userspace declarations.  Kill in 2.5. */
+static inline void iounmap(volatile void __iomem *addr)
+{
+	IO_CONCAT(__IO_PREFIX,iounmap)(addr);
+}
 
-extern unsigned int	inb(unsigned long port);
-extern unsigned int	inw(unsigned long port);
-extern unsigned int	inl(unsigned long port);
-extern void		outb(unsigned char b,unsigned long port);
-extern void		outw(unsigned short w,unsigned long port);
-extern void		outl(unsigned int l,unsigned long port);
-extern unsigned long	readb(unsigned long addr);
-extern unsigned long	readw(unsigned long addr);
-extern unsigned long	readl(unsigned long addr);
-extern void		writeb(unsigned char b, unsigned long addr);
-extern void		writew(unsigned short b, unsigned long addr);
-extern void		writel(unsigned int b, unsigned long addr);
+static inline int __is_ioaddr(unsigned long addr)
+{
+	return IO_CONCAT(__IO_PREFIX,is_ioaddr)(addr);
+}
+#define __is_ioaddr(a)		__is_ioaddr((unsigned long)(a))
 
-#endif /* __KERNEL__ */
+static inline int __is_mmio(const volatile void __iomem *addr)
+{
+	return IO_CONCAT(__IO_PREFIX,is_mmio)(addr);
+}
 
-#ifdef __KERNEL__
 
 /*
- * On Alpha, we have the whole of I/O space mapped at all times, but
- * at odd and sometimes discontinuous addresses.  Note that the 
- * discontinuities are all across busses, so we need not care for that
- * for any one device.
- *
- * The DRM drivers need to be able to map contiguously a (potentially)
- * discontiguous set of I/O pages. This set of pages is scatter-gather
- * mapped contiguously from the perspective of the bus, but we can't
- * directly access DMA addresses from the CPU, these addresses need to
- * have a real ioremap. Therefore, iounmap and the size argument to
- * ioremap are needed to give the platforms the ability to fully implement
- * ioremap.
- *
- * Map the I/O space address into the kernel's virtual address space.
+ * If the actual I/O bits are sufficiently trivial, then expand inline.
  */
-static inline void * ioremap(unsigned long offset, unsigned long size)
+
+#if IO_CONCAT(__IO_PREFIX,trivial_io_bw)
+extern inline unsigned int ioread8(void __iomem *addr)
 {
-	return (void *) __ioremap(offset, size);
-} 
+	unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr);
+	mb();
+	return ret;
+}
 
-static inline void iounmap(void *addr)
+extern inline unsigned int ioread16(void __iomem *addr)
 {
-	__iounmap(addr);
+	unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr);
+	mb();
+	return ret;
 }
 
-static inline void * ioremap_nocache(unsigned long offset, unsigned long size)
+extern inline void iowrite8(u8 b, void __iomem *addr)
 {
-	return ioremap(offset, size);
-} 
+	IO_CONCAT(__IO_PREFIX,iowrite8)(b, addr);
+	mb();
+}
 
-/* Indirect back to the macros provided.  */
+extern inline void iowrite16(u16 b, void __iomem *addr)
+{
+	IO_CONCAT(__IO_PREFIX,iowrite16)(b, addr);
+	mb();
+}
 
-extern u8		___raw_readb(unsigned long addr);
-extern u16		___raw_readw(unsigned long addr);
-extern u32		___raw_readl(unsigned long addr);
-extern u64		___raw_readq(unsigned long addr);
-extern void		___raw_writeb(u8 b, unsigned long addr);
-extern void		___raw_writew(u16 b, unsigned long addr);
-extern void		___raw_writel(u32 b, unsigned long addr);
-extern void		___raw_writeq(u64 b, unsigned long addr);
+extern inline u8 inb(unsigned long port)
+{
+	return ioread8(ioport_map(port, 1));
+}
 
-#ifdef __raw_readb
-# define readb(a)	({ u8 r_ = __raw_readb(a); mb(); r_; })
-#endif
-#ifdef __raw_readw
-# define readw(a)	({ u16 r_ = __raw_readw(a); mb(); r_; })
-#endif
-#ifdef __raw_readl
-# define readl(a)	({ u32 r_ = __raw_readl(a); mb(); r_; })
-#endif
-#ifdef __raw_readq
-# define readq(a)	({ u64 r_ = __raw_readq(a); mb(); r_; })
-#endif
+extern inline u16 inw(unsigned long port)
+{
+	return ioread16(ioport_map(port, 2));
+}
 
-#ifdef __raw_writeb
-# define writeb(v,a)	({ __raw_writeb((v),(a)); mb(); })
-#endif
-#ifdef __raw_writew
-# define writew(v,a)	({ __raw_writew((v),(a)); mb(); })
-#endif
-#ifdef __raw_writel
-# define writel(v,a)	({ __raw_writel((v),(a)); mb(); })
-#endif
-#ifdef __raw_writeq
-# define writeq(v,a)	({ __raw_writeq((v),(a)); mb(); })
-#endif
+extern inline void outb(u8 b, unsigned long port)
+{
+	iowrite8(b, ioport_map(port, 1));
+}
 
-#ifndef __raw_readb
-# define __raw_readb(a)	___raw_readb((unsigned long)(a))
-#endif
-#ifndef __raw_readw
-# define __raw_readw(a)	___raw_readw((unsigned long)(a))
-#endif
-#ifndef __raw_readl
-# define __raw_readl(a)	___raw_readl((unsigned long)(a))
-#endif
-#ifndef __raw_readq
-# define __raw_readq(a)	___raw_readq((unsigned long)(a))
+extern inline void outw(u16 b, unsigned long port)
+{
+	iowrite16(b, ioport_map(port, 2));
+}
 #endif
 
-#ifndef __raw_writeb
-# define __raw_writeb(v,a)  ___raw_writeb((v),(unsigned long)(a))
-#endif
-#ifndef __raw_writew
-# define __raw_writew(v,a)  ___raw_writew((v),(unsigned long)(a))
-#endif
-#ifndef __raw_writel
-# define __raw_writel(v,a)  ___raw_writel((v),(unsigned long)(a))
-#endif
-#ifndef __raw_writeq
-# define __raw_writeq(v,a)  ___raw_writeq((v),(unsigned long)(a))
-#endif
+#if IO_CONCAT(__IO_PREFIX,trivial_io_lq)
+extern inline unsigned int ioread32(void __iomem *addr)
+{
+	unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr);
+	mb();
+	return ret;
+}
 
-#ifndef readb
-# define readb(a)	_readb((unsigned long)(a))
-#endif
-#ifndef readw
-# define readw(a)	_readw((unsigned long)(a))
-#endif
-#ifndef readl
-# define readl(a)	_readl((unsigned long)(a))
-#endif
-#ifndef readq
-# define readq(a)	_readq((unsigned long)(a))
-#endif
+extern inline void iowrite32(u32 b, void __iomem *addr)
+{
+	IO_CONCAT(__IO_PREFIX,iowrite32)(b, addr);
+	mb();
+}
 
-#define readb_relaxed(addr) readb(addr)
-#define readw_relaxed(addr) readw(addr)
-#define readl_relaxed(addr) readl(addr)
-#define readq_relaxed(addr) readq(addr)
+extern inline u32 inl(unsigned long port)
+{
+	return ioread32(ioport_map(port, 4));
+}
 
-#ifndef writeb
-# define writeb(v,a)	_writeb((v),(unsigned long)(a))
-#endif
-#ifndef writew
-# define writew(v,a)	_writew((v),(unsigned long)(a))
+extern inline void outl(u32 b, unsigned long port)
+{
+	iowrite32(b, ioport_map(port, 4));
+}
 #endif
-#ifndef writel
-# define writel(v,a)	_writel((v),(unsigned long)(a))
+
+#if IO_CONCAT(__IO_PREFIX,trivial_rw_bw) == 1
+extern inline u8 __raw_readb(const volatile void __iomem *addr)
+{
+	return IO_CONCAT(__IO_PREFIX,readb)(addr);
+}
+
+extern inline u16 __raw_readw(const volatile void __iomem *addr)
+{
+	return IO_CONCAT(__IO_PREFIX,readw)(addr);
+}
+
+extern inline void __raw_writeb(u8 b, volatile void __iomem *addr)
+{
+	IO_CONCAT(__IO_PREFIX,writeb)(b, addr);
+}
+
+extern inline void __raw_writew(u16 b, volatile void __iomem *addr)
+{
+	IO_CONCAT(__IO_PREFIX,writew)(b, addr);
+}
+
+extern inline u8 readb(const volatile void __iomem *addr)
+{
+	u8 ret = __raw_readb(addr);
+	mb();
+	return ret;
+}
+
+extern inline u16 readw(const volatile void __iomem *addr)
+{
+	u16 ret = __raw_readw(addr);
+	mb();
+	return ret;
+}
+
+extern inline void writeb(u8 b, volatile void __iomem *addr)
+{
+	__raw_writeb(b, addr);
+	mb();
+}
+
+extern inline void writew(u16 b, volatile void __iomem *addr)
+{
+	__raw_writew(b, addr);
+	mb();
+}
 #endif
-#ifndef writeq
-# define writeq(v,a)	_writeq((v),(unsigned long)(a))
+
+#if IO_CONCAT(__IO_PREFIX,trivial_rw_lq) == 1
+extern inline u32 __raw_readl(const volatile void __iomem *addr)
+{
+	return IO_CONCAT(__IO_PREFIX,readl)(addr);
+}
+
+extern inline u64 __raw_readq(const volatile void __iomem *addr)
+{
+	return IO_CONCAT(__IO_PREFIX,readq)(addr);
+}
+
+extern inline void __raw_writel(u32 b, volatile void __iomem *addr)
+{
+	IO_CONCAT(__IO_PREFIX,writel)(b, addr);
+}
+
+extern inline void __raw_writeq(u64 b, volatile void __iomem *addr)
+{
+	IO_CONCAT(__IO_PREFIX,writeq)(b, addr);
+}
+
+extern inline u32 readl(const volatile void __iomem *addr)
+{
+	u32 ret = __raw_readl(addr);
+	mb();
+	return ret;
+}
+
+extern inline u64 readq(const volatile void __iomem *addr)
+{
+	u64 ret = __raw_readq(addr);
+	mb();
+	return ret;
+}
+
+extern inline void writel(u32 b, volatile void __iomem *addr)
+{
+	__raw_writel(b, addr);
+	mb();
+}
+
+extern inline void writeq(u64 b, volatile void __iomem *addr)
+{
+	__raw_writeq(b, addr);
+	mb();
+}
 #endif
 
+#define inb_p		inb
+#define inw_p		inw
+#define inl_p		inl
+#define outb_p		outb
+#define outw_p		outw
+#define outl_p		outl
+#define readb_relaxed(addr) __raw_readb(addr)
+#define readw_relaxed(addr) __raw_readw(addr)
+#define readl_relaxed(addr) __raw_readl(addr)
+#define readq_relaxed(addr) __raw_readq(addr)
+
 /*
  * String version of IO memory access ops:
  */
-extern void _memcpy_fromio(void *, unsigned long, long);
-extern void _memcpy_toio(unsigned long, const void *, long);
-extern void _memset_c_io(unsigned long, unsigned long, long);
+extern void memcpy_fromio(void *, const volatile void __iomem *, long);
+extern void memcpy_toio(volatile void __iomem *, const void *, long);
+extern void _memset_c_io(volatile void __iomem *, unsigned long, long);
 
-#define memcpy_fromio(to,from,len) \
-  _memcpy_fromio((to),(unsigned long)(from),(len))
-#define memcpy_toio(to,from,len) \
-  _memcpy_toio((unsigned long)(to),(from),(len))
-#define memset_io(addr,c,len) \
-  _memset_c_io((unsigned long)(addr),0x0101010101010101UL*(u8)(c),(len))
+static inline void memset_io(volatile void __iomem *addr, u8 c, long len)
+{
+	_memset_c_io(addr, 0x0101010101010101UL * c, len);
+}
 
 #define __HAVE_ARCH_MEMSETW_IO
-#define memsetw_io(addr,c,len) \
-  _memset_c_io((unsigned long)(addr),0x0001000100010001UL*(u16)(c),(len))
+static inline void memsetw_io(volatile void __iomem *addr, u16 c, long len)
+{
+	_memset_c_io(addr, 0x0001000100010001UL * c, len);
+}
 
 /*
  * String versions of in/out ops:
@@ -465,26 +524,22 @@ extern void outsl (unsigned long port, const void *src, unsigned long count);
  */
 
 #define eth_io_copy_and_sum(skb,src,len,unused) \
-  memcpy_fromio((skb)->data,(src),(len))
+  memcpy_fromio((skb)->data,src,len)
 
 #define isa_eth_io_copy_and_sum(skb,src,len,unused) \
-  isa_memcpy_fromio((skb)->data,(src),(len))
+  isa_memcpy_fromio((skb)->data,src,len)
 
 static inline int
-check_signature(unsigned long io_addr, const unsigned char *signature,
-		int length)
+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;
+			return 0;
 		io_addr++;
 		signature++;
-		length--;
-	} while (length);
-	retval = 1;
-out:
-	return retval;
+	} while (--length);
+	return 1;
 }
 
 
@@ -492,31 +547,89 @@ out:
  * ISA space is mapped to some machine-specific location on Alpha.
  * Call into the existing hooks to get the address translated.
  */
-#define isa_readb(a)			readb(__ioremap((a),1))
-#define isa_readw(a)			readw(__ioremap((a),2))
-#define isa_readl(a)			readl(__ioremap((a),4))
-#define isa_writeb(b,a)			writeb((b),__ioremap((a),1))
-#define isa_writew(w,a)			writew((w),__ioremap((a),2))
-#define isa_writel(l,a)			writel((l),__ioremap((a),4))
-#define isa_memset_io(a,b,c)		memset_io(__ioremap((a),(c)),(b),(c))
-#define isa_memcpy_fromio(a,b,c)	memcpy_fromio((a),__ioremap((b),(c)),(c))
-#define isa_memcpy_toio(a,b,c)		memcpy_toio(__ioremap((a),(c)),(b),(c))
+
+static inline u8
+isa_readb(unsigned long offset)
+{
+	void __iomem *addr = ioremap(offset, 1);
+	u8 ret = readb(addr);
+	iounmap(addr);
+	return ret;
+}
+
+static inline u16
+isa_readw(unsigned long offset)
+{
+	void __iomem *addr = ioremap(offset, 2);
+	u16 ret = readw(addr);
+	iounmap(addr);
+	return ret;
+}
+
+static inline u32
+isa_readl(unsigned long offset)
+{
+	void __iomem *addr = ioremap(offset, 2);
+	u32 ret = readl(addr);
+	iounmap(addr);
+	return ret;
+}
+
+static inline void
+isa_writeb(u8 b, unsigned long offset)
+{
+	void __iomem *addr = ioremap(offset, 2);
+	writeb(b, addr);
+	iounmap(addr);
+}
+
+static inline void
+isa_writew(u16 w, unsigned long offset)
+{
+	void __iomem *addr = ioremap(offset, 2);
+	writew(w, addr);
+	iounmap(addr);
+}
+
+static inline void
+isa_writel(u32 l, unsigned long offset)
+{
+	void __iomem *addr = ioremap(offset, 2);
+	writel(l, addr);
+	iounmap(addr);
+}
+
+static inline void
+isa_memset_io(unsigned long offset, u8 val, long n)
+{
+	void __iomem *addr = ioremap(offset, n);
+	memset_io(addr, val, n);
+	iounmap(addr);
+}
+
+static inline void
+isa_memcpy_fromio(void *dest, unsigned long offset, long n)
+{
+	void __iomem *addr = ioremap(offset, n);
+	memcpy_fromio(dest, addr, n);
+	iounmap(addr);
+}
+
+static inline void
+isa_memcpy_toio(unsigned long offset, const void *src, long n)
+{
+	void __iomem *addr = ioremap(offset, n);
+	memcpy_toio(addr, src, n);
+	iounmap(addr);
+}
 
 static inline int
-isa_check_signature(unsigned long io_addr, const unsigned char *signature,
-		int length)
+isa_check_signature(unsigned long offset, const unsigned char *sig, long len)
 {
-	int retval = 0;
-	do {
-		if (isa_readb(io_addr) != *signature)
-			goto out;
-		io_addr++;
-		signature++;
-		length--;
-	} while (length);
-	retval = 1;
-out:
-	return retval;
+	void __iomem *addr = ioremap(offset, len);
+	int ret = check_signature(addr, sig, len);
+	iounmap(addr);
+	return ret;
 }
 
 
diff --git a/include/asm-alpha/jensen.h b/include/asm-alpha/jensen.h
index 7e6c35b14..964b06ead 100644
--- a/include/asm-alpha/jensen.h
+++ b/include/asm-alpha/jensen.h
@@ -200,8 +200,9 @@ __EXTERN_INLINE void jensen_outl(u32 b, unsigned long addr)
  * Memory functions.
  */
 
-__EXTERN_INLINE u8 jensen_readb(unsigned long addr)
+__EXTERN_INLINE u8 jensen_readb(const volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	long result;
 
 	jensen_set_hae(addr);
@@ -211,8 +212,9 @@ __EXTERN_INLINE u8 jensen_readb(unsigned long addr)
 	return 0xffUL & result;
 }
 
-__EXTERN_INLINE u16 jensen_readw(unsigned long addr)
+__EXTERN_INLINE u16 jensen_readw(const volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	long result;
 
 	jensen_set_hae(addr);
@@ -222,15 +224,17 @@ __EXTERN_INLINE u16 jensen_readw(unsigned long addr)
 	return 0xffffUL & result;
 }
 
-__EXTERN_INLINE u32 jensen_readl(unsigned long addr)
+__EXTERN_INLINE u32 jensen_readl(const volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	jensen_set_hae(addr);
 	addr &= JENSEN_HAE_MASK;
 	return *(vuip) ((addr << 7) + EISA_MEM + 0x60);
 }
 
-__EXTERN_INLINE u64 jensen_readq(unsigned long addr)
+__EXTERN_INLINE u64 jensen_readq(const volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	unsigned long r0, r1;
 
 	jensen_set_hae(addr);
@@ -241,29 +245,33 @@ __EXTERN_INLINE u64 jensen_readq(unsigned long addr)
 	return r1 << 32 | r0;
 }
 
-__EXTERN_INLINE void jensen_writeb(u8 b, unsigned long addr)
+__EXTERN_INLINE void jensen_writeb(u8 b, volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	jensen_set_hae(addr);
 	addr &= JENSEN_HAE_MASK;
 	*(vuip) ((addr << 7) + EISA_MEM + 0x00) = b * 0x01010101;
 }
 
-__EXTERN_INLINE void jensen_writew(u16 b, unsigned long addr)
+__EXTERN_INLINE void jensen_writew(u16 b, volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	jensen_set_hae(addr);
 	addr &= JENSEN_HAE_MASK;
 	*(vuip) ((addr << 7) + EISA_MEM + 0x20) = b * 0x00010001;
 }
 
-__EXTERN_INLINE void jensen_writel(u32 b, unsigned long addr)
+__EXTERN_INLINE void jensen_writel(u32 b, volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	jensen_set_hae(addr);
 	addr &= JENSEN_HAE_MASK;
 	*(vuip) ((addr << 7) + EISA_MEM + 0x60) = b;
 }
 
-__EXTERN_INLINE void jensen_writeq(u64 b, unsigned long addr)
+__EXTERN_INLINE void jensen_writeq(u64 b, volatile void __iomem *xaddr)
 {
+	unsigned long addr = (unsigned long) xaddr;
 	jensen_set_hae(addr);
 	addr &= JENSEN_HAE_MASK;
 	addr = (addr << 7) + EISA_MEM + 0x60;
@@ -271,15 +279,15 @@ __EXTERN_INLINE void jensen_writeq(u64 b, unsigned long addr)
 	*(vuip) (addr + (4 << 7)) = b >> 32;
 }
 
-__EXTERN_INLINE unsigned long jensen_ioremap(unsigned long addr, 
-					     unsigned long size)
+__EXTERN_INLINE void __iomem *jensen_ioportmap(unsigned long addr)
 {
-	return addr;
+	return (void __iomem *)addr;
 }
 
-__EXTERN_INLINE void jensen_iounmap(unsigned long addr)
+__EXTERN_INLINE void __iomem *jensen_ioremap(unsigned long addr,
+					     unsigned long size)
 {
-	return;
+	return (void __iomem *)(addr + 0x100000000ul);
 }
 
 __EXTERN_INLINE int jensen_is_ioaddr(unsigned long addr)
@@ -287,39 +295,46 @@ __EXTERN_INLINE int jensen_is_ioaddr(unsigned long addr)
 	return (long)addr >= 0;
 }
 
-#undef vuip
+__EXTERN_INLINE int jensen_is_mmio(const volatile void __iomem *addr)
+{
+	return (unsigned long)addr >= 0x100000000ul;
+}
 
-#ifdef __WANT_IO_DEF
-
-#define __inb		jensen_inb
-#define __inw		jensen_inw
-#define __inl		jensen_inl
-#define __outb		jensen_outb
-#define __outw		jensen_outw
-#define __outl		jensen_outl
-#define __readb		jensen_readb
-#define __readw		jensen_readw
-#define __writeb	jensen_writeb
-#define __writew	jensen_writew
-#define __readl		jensen_readl
-#define __readq		jensen_readq
-#define __writel	jensen_writel
-#define __writeq	jensen_writeq
-#define __ioremap	jensen_ioremap
-#define __iounmap(a)	jensen_iounmap((unsigned long)a)
-#define __is_ioaddr	jensen_is_ioaddr
+/* New-style ioread interface.  All the routines are so ugly for Jensen
+   that it doesn't make sense to merge them.  */
+
+#define IOPORT(OS, NS)							\
+__EXTERN_INLINE unsigned int jensen_ioread##NS(void __iomem *xaddr)	\
+{									\
+	if (jensen_is_mmio(xaddr))					\
+		return jensen_read##OS(xaddr - 0x100000000ul);		\
+	else								\
+		return jensen_in##OS((unsigned long)xaddr);		\
+}									\
+__EXTERN_INLINE void jensen_iowrite##NS(u##NS b, void __iomem *xaddr)	\
+{									\
+	if (jensen_is_mmio(xaddr))					\
+		jensen_write##OS(b, xaddr - 0x100000000ul);		\
+	else								\
+		jensen_out##OS(b, (unsigned long)xaddr);		\
+}
 
-/*
- * The above have so much overhead that it probably doesn't make
- * sense to have them inlined (better icache behaviour).
- */
-#define inb(port) \
-(__builtin_constant_p((port))?__inb(port):_inb(port))
+IOPORT(b, 8)
+IOPORT(w, 16)
+IOPORT(l, 32)
 
-#define outb(x, port) \
-(__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
+#undef IOPORT
+
+#undef vuip
 
-#endif /* __WANT_IO_DEF */
+#undef __IO_PREFIX
+#define __IO_PREFIX		jensen
+#define jensen_trivial_rw_bw	0
+#define jensen_trivial_rw_lq	0
+#define jensen_trivial_io_bw	0
+#define jensen_trivial_io_lq	0
+#define jensen_trivial_iounmap	1
+#include <asm/io_trivial.h>
 
 #ifdef __IO_EXTERN_INLINE
 #undef __EXTERN_INLINE
diff --git a/include/asm-alpha/machvec.h b/include/asm-alpha/machvec.h
index f09f71909..ece166a20 100644
--- a/include/asm-alpha/machvec.h
+++ b/include/asm-alpha/machvec.h
@@ -45,27 +45,29 @@ struct alpha_machine_vector
 	void (*mv_pci_tbi)(struct pci_controller *hose,
 			   dma_addr_t start, dma_addr_t end);
 
-	u8 (*mv_inb)(unsigned long);
-	u16 (*mv_inw)(unsigned long);
-	u32 (*mv_inl)(unsigned long);
-
-	void (*mv_outb)(u8, unsigned long);
-	void (*mv_outw)(u16, unsigned long);
-	void (*mv_outl)(u32, unsigned long);
-	
-	u8 (*mv_readb)(unsigned long);
-	u16 (*mv_readw)(unsigned long);
-	u32 (*mv_readl)(unsigned long);
-	u64 (*mv_readq)(unsigned long);
-
-	void (*mv_writeb)(u8, unsigned long);
-	void (*mv_writew)(u16, unsigned long);
-	void (*mv_writel)(u32, unsigned long);
-	void (*mv_writeq)(u64, unsigned long);
-
-	unsigned long (*mv_ioremap)(unsigned long, unsigned long);
-	void (*mv_iounmap)(unsigned long);
+	unsigned int (*mv_ioread8)(void __iomem *);
+	unsigned int (*mv_ioread16)(void __iomem *);
+	unsigned int (*mv_ioread32)(void __iomem *);
+
+	void (*mv_iowrite8)(u8, void __iomem *);
+	void (*mv_iowrite16)(u16, void __iomem *);
+	void (*mv_iowrite32)(u32, void __iomem *);
+
+	u8 (*mv_readb)(const volatile void __iomem *);
+	u16 (*mv_readw)(const volatile void __iomem *);
+	u32 (*mv_readl)(const volatile void __iomem *);
+	u64 (*mv_readq)(const volatile void __iomem *);
+
+	void (*mv_writeb)(u8, volatile void __iomem *);
+	void (*mv_writew)(u16, volatile void __iomem *);
+	void (*mv_writel)(u32, volatile void __iomem *);
+	void (*mv_writeq)(u64, volatile void __iomem *);
+
+	void __iomem *(*mv_ioportmap)(unsigned long);
+	void __iomem *(*mv_ioremap)(unsigned long, unsigned long);
+	void (*mv_iounmap)(volatile void __iomem *);
 	int (*mv_is_ioaddr)(unsigned long);
+	int (*mv_is_mmio)(const volatile void __iomem *);
 
 	void (*mv_switch_mm)(struct mm_struct *, struct mm_struct *,
 			     struct task_struct *);
diff --git a/include/asm-alpha/mmu_context.h b/include/asm-alpha/mmu_context.h
index 3ae6408ac..a714d0cdc 100644
--- a/include/asm-alpha/mmu_context.h
+++ b/include/asm-alpha/mmu_context.h
@@ -10,6 +10,7 @@
 #include <linux/config.h>
 #include <asm/system.h>
 #include <asm/machvec.h>
+#include <asm/compiler.h>
 
 /*
  * Force a context reload. This is needed when we change the page
diff --git a/include/asm-alpha/page.h b/include/asm-alpha/page.h
index b316fc6a0..56006caed 100644
--- a/include/asm-alpha/page.h
+++ b/include/asm-alpha/page.h
@@ -1,6 +1,7 @@
 #ifndef _ALPHA_PAGE_H
 #define _ALPHA_PAGE_H
 
+#include <linux/config.h>
 #include <asm/pal.h>
 
 /* PAGE_SHIFT determines the page size */
diff --git a/include/asm-alpha/pci.h b/include/asm-alpha/pci.h
index 5cd3779b0..bbefe1238 100644
--- a/include/asm-alpha/pci.h
+++ b/include/asm-alpha/pci.h
@@ -169,7 +169,7 @@ pci_dma_sync_single_for_cpu(struct pci_dev *dev, dma_addr_t dma_addr,
 
 static inline void
 pci_dma_sync_single_for_device(struct pci_dev *dev, dma_addr_t dma_addr,
-			       long size, int direction)
+			       size_t size, int direction)
 {
 	/* Nothing to do.  */
 }
@@ -246,6 +246,8 @@ pcibios_add_platform_entries(struct pci_dev *dev)
 {
 }
 
+struct pci_dev *alpha_gendev_to_pci(struct device *dev);
+
 #endif /* __KERNEL__ */
 
 /* Values for the `which' argument to sys_pciconfig_iobase.  */
diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h
index 8707a399b..3f1ed39d2 100644
--- a/include/asm-alpha/pgtable.h
+++ b/include/asm-alpha/pgtable.h
@@ -328,7 +328,7 @@ extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
 #endif
 
 #define io_remap_page_range(vma, start, busaddr, size, prot) \
-    remap_page_range(vma, start, virt_to_phys(__ioremap(busaddr, size)), size, prot)
+    remap_page_range(vma, start, virt_to_phys((void *)__ioremap(busaddr, size)), size, prot)
 
 #define pte_ERROR(e) \
 	printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e))
diff --git a/include/asm-alpha/ptrace.h b/include/asm-alpha/ptrace.h
index e77230f32..d462c5e14 100644
--- a/include/asm-alpha/ptrace.h
+++ b/include/asm-alpha/ptrace.h
@@ -69,6 +69,7 @@ struct switch_stack {
 #ifdef __KERNEL__
 #define user_mode(regs) (((regs)->ps & 8) != 0)
 #define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 
 #define alpha_task_regs(task) \
diff --git a/include/asm-alpha/resource.h b/include/asm-alpha/resource.h
index b94759c61..bfacb0aa2 100644
--- a/include/asm-alpha/resource.h
+++ b/include/asm-alpha/resource.h
@@ -41,7 +41,7 @@
     {INR_OPEN, INR_OPEN},			/* RLIMIT_NOFILE */	\
     {LONG_MAX, LONG_MAX},			/* RLIMIT_AS */		\
     {LONG_MAX, LONG_MAX},			/* RLIMIT_NPROC */	\
-    {LONG_MAX, LONG_MAX},			/* RLIMIT_MEMLOCK */	\
+    {MLOCK_LIMIT, MLOCK_LIMIT },		/* RLIMIT_MEMLOCK */	\
     {LONG_MAX, LONG_MAX},			/* RLIMIT_LOCKS */	\
     {MAX_SIGPENDING, MAX_SIGPENDING},		/* RLIMIT_SIGPENDING */ \
     {MQ_BYTES_MAX, MQ_BYTES_MAX},		/* RLIMIT_MSGQUEUE */	\
diff --git a/include/asm-alpha/semaphore.h b/include/asm-alpha/semaphore.h
index 1f1978428..eb2cbd97d 100644
--- a/include/asm-alpha/semaphore.h
+++ b/include/asm-alpha/semaphore.h
@@ -18,21 +18,13 @@
 struct semaphore {
 	atomic_t count;
 	wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name)		, (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count)		\
-	{ ATOMIC_INIT(count),				\
-	  __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
-	  __SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)			\
+{								\
+	.count	= ATOMIC_INIT(n),				\
+  	.wait	= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait),	\
+}
 
 #define __MUTEX_INITIALIZER(name)			\
 	__SEMAPHORE_INITIALIZER(name,1)
@@ -53,9 +45,6 @@ static inline void sema_init(struct semaphore *sem, int val)
 
 	atomic_set(&sem->count, val);
 	init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -142,7 +131,7 @@ static inline void __up(struct semaphore *sem)
 		__up_wakeup(sem);
 }
 
-#if !defined(WAITQUEUE_DEBUG) && !defined(CONFIG_DEBUG_SEMAPHORE)
+#if !defined(CONFIG_DEBUG_SEMAPHORE)
 extern inline void down(struct semaphore *sem)
 {
 	__down(sem);
diff --git a/include/asm-alpha/socket.h b/include/asm-alpha/socket.h
index 88912c4c8..d00259d3d 100644
--- a/include/asm-alpha/socket.h
+++ b/include/asm-alpha/socket.h
@@ -55,20 +55,4 @@
 #define SO_SECURITY_ENCRYPTION_TRANSPORT	20
 #define SO_SECURITY_ENCRYPTION_NETWORK		21
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-alpha/spinlock.h b/include/asm-alpha/spinlock.h
index 1fc53a935..b5f355444 100644
--- a/include/asm-alpha/spinlock.h
+++ b/include/asm-alpha/spinlock.h
@@ -95,7 +95,7 @@ static inline int _raw_spin_trylock(spinlock_t *lock)
 /***********************************************************/
 
 typedef struct {
-	volatile int write_lock:1, read_counter:31;
+	volatile unsigned int write_lock:1, read_counter:31;
 } /*__attribute__((aligned(32)))*/ rwlock_t;
 
 #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
@@ -124,7 +124,7 @@ static inline void _raw_write_lock(rwlock_t * lock)
 	"	br	1b\n"
 	".previous"
 	: "=m" (*lock), "=&r" (regx)
-	: "0" (*lock) : "memory");
+	: "m" (*lock) : "memory");
 }
 
 static inline void _raw_read_lock(rwlock_t * lock)
@@ -148,6 +148,29 @@ static inline void _raw_read_lock(rwlock_t * lock)
 }
 #endif /* CONFIG_DEBUG_RWLOCK */
 
+static inline int _raw_write_trylock(rwlock_t * lock)
+{
+	long regx;
+	int success;
+
+	__asm__ __volatile__(
+	"1:	ldl_l	%1,%0\n"
+	"	lda	%2,0\n"
+	"	bne	%1,2f\n"
+	"	or	$31,1,%1\n"
+	"	stl_c	%1,%0\n"
+	"	beq	%1,6f\n"
+	"	lda	%2,1\n"
+	"2:	mb\n"
+	".subsection 2\n"
+	"6:	br	1b\n"
+	".previous"
+	: "=m" (*lock), "=&r" (regx), "=&r" (success)
+	: "m" (*lock) : "memory");
+
+	return success;
+}
+
 static inline void _raw_write_unlock(rwlock_t * lock)
 {
 	mb();
diff --git a/include/asm-alpha/sysinfo.h b/include/asm-alpha/sysinfo.h
index 1c65a021a..086aba284 100644
--- a/include/asm-alpha/sysinfo.h
+++ b/include/asm-alpha/sysinfo.h
@@ -18,6 +18,7 @@
 #define SSI_IEEE_FP_CONTROL		14
 #define SSI_IEEE_STATE_AT_SIGNAL	15
 #define SSI_IEEE_IGNORE_STATE_AT_SIGNAL	16
+#define SSI_IEEE_RAISE_EXCEPTION	1001	/* linux specific */
 
 #define SSIN_UACPROC			6
 
diff --git a/include/asm-alpha/system.h b/include/asm-alpha/system.h
index 1e5ac92d2..bba276c50 100644
--- a/include/asm-alpha/system.h
+++ b/include/asm-alpha/system.h
@@ -55,9 +55,9 @@
  */
 struct el_common {
 	unsigned int	size;		/* size in bytes of logout area */
-	int		sbz1	: 30;	/* should be zero */
-	int		err2	:  1;	/* second error */
-	int		retry	:  1;	/* retry flag */
+	unsigned int	sbz1	: 30;	/* should be zero */
+	unsigned int	err2	:  1;	/* second error */
+	unsigned int	retry	:  1;	/* retry flag */
 	unsigned int	proc_offset;	/* processor-specific offset */
 	unsigned int	sys_offset;	/* system-specific offset */
 	unsigned int	code;		/* machine check code */
diff --git a/include/asm-alpha/thread_info.h b/include/asm-alpha/thread_info.h
index 1f19c2add..c433512ba 100644
--- a/include/asm-alpha/thread_info.h
+++ b/include/asm-alpha/thread_info.h
@@ -19,7 +19,7 @@ struct thread_info {
 
 	struct exec_domain	*exec_domain;	/* execution domain */
 	mm_segment_t		addr_limit;	/* thread address space */
-	long			cpu;		/* current CPU */
+	unsigned		cpu;		/* current CPU */
 	int			preempt_count; /* 0 => preemptable, <0 => BUG */
 
 	int bpt_nsaved;
diff --git a/include/asm-alpha/tlbflush.h b/include/asm-alpha/tlbflush.h
index 736a4f61d..9d484c1fd 100644
--- a/include/asm-alpha/tlbflush.h
+++ b/include/asm-alpha/tlbflush.h
@@ -3,6 +3,7 @@
 
 #include <linux/config.h>
 #include <linux/mm.h>
+#include <asm/compiler.h>
 
 #ifndef __EXTERN_INLINE
 #define __EXTERN_INLINE extern inline
@@ -86,7 +87,7 @@ flush_tlb(void)
 static inline void
 flush_tlb_other(struct mm_struct *mm)
 {
-	long *mmc = &mm->context[smp_processor_id()];
+	unsigned long *mmc = &mm->context[smp_processor_id()];
 	/* Check it's not zero first to avoid cacheline ping pong
 	   when possible.  */
 	if (*mmc) *mmc = 0;
diff --git a/include/asm-alpha/uaccess.h b/include/asm-alpha/uaccess.h
index c9bb9f103..474d06689 100644
--- a/include/asm-alpha/uaccess.h
+++ b/include/asm-alpha/uaccess.h
@@ -108,7 +108,6 @@ extern void __get_user_unknown(void);
 ({									\
 	long __gu_err = -EFAULT, __gu_val = 0;				\
 	const __typeof__(*(ptr)) __user *__gu_addr = (ptr);		\
-	__chk_user_ptr(ptr);						\
 	if (__access_ok((unsigned long)__gu_addr,size,segment)) {	\
 		__gu_err = 0;						\
 		switch (size) {						\
@@ -223,7 +222,6 @@ extern void __put_user_unknown(void);
 ({									\
 	long __pu_err = -EFAULT;					\
 	__typeof__(*(ptr)) __user *__pu_addr = (ptr);			\
-	__chk_user_ptr(ptr);						\
 	if (__access_ok((unsigned long)__pu_addr,size,segment)) {	\
 		__pu_err = 0;						\
 		switch (size) {						\
@@ -395,6 +393,10 @@ __copy_tofrom_user(void *to, const void *from, long len, const void __user *vali
 	__copy_tofrom_user_nocheck((to),(__force void *)(from),(n));	\
 })
 
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
+
 extern inline long
 copy_to_user(void __user *to, const void *from, long n)
 {
diff --git a/include/asm-alpha/unistd.h b/include/asm-alpha/unistd.h
index aae3ab664..9aca27ea7 100644
--- a/include/asm-alpha/unistd.h
+++ b/include/asm-alpha/unistd.h
@@ -374,8 +374,9 @@
 #define __NR_mq_timedreceive		435
 #define __NR_mq_notify			436
 #define __NR_mq_getsetattr		437
+#define __NR_waitid			438
 
-#define NR_SYSCALLS			438
+#define NR_SYSCALLS			439
 
 #if defined(__GNUC__)
 
@@ -618,7 +619,7 @@ static inline long read(int fd, char * buf, size_t nr)
 	return sys_read(fd, buf, nr);
 }
 
-extern long execve(char *, char **, char **);
+extern int execve(char *, char **, char **);
 
 static inline long setsid(void)
 {
diff --git a/include/asm-alpha/vga.h b/include/asm-alpha/vga.h
index 0f3d10eaa..8ca4f6b2d 100644
--- a/include/asm-alpha/vga.h
+++ b/include/asm-alpha/vga.h
@@ -15,24 +15,24 @@
 
 extern inline void scr_writew(u16 val, volatile u16 *addr)
 {
-	if (__is_ioaddr((unsigned long) addr))
-		__raw_writew(val, (unsigned long) addr);
+	if (__is_ioaddr(addr))
+		__raw_writew(val, (volatile u16 __iomem *) addr);
 	else
 		*addr = val;
 }
 
 extern inline u16 scr_readw(volatile const u16 *addr)
 {
-	if (__is_ioaddr((unsigned long) addr))
-		return __raw_readw((unsigned long) addr);
+	if (__is_ioaddr(addr))
+		return __raw_readw((volatile const u16 __iomem *) addr);
 	else
 		return *addr;
 }
 
 extern inline void scr_memsetw(u16 *s, u16 c, unsigned int count)
 {
-	if (__is_ioaddr((unsigned long) s))
-		memsetw_io(s, c, count);
+	if (__is_ioaddr(s))
+		memsetw_io((u16 __iomem *) s, c, count);
 	else
 		memsetw(s, c, count);
 }
@@ -43,9 +43,9 @@ extern void scr_memcpyw(u16 *d, const u16 *s, unsigned int count);
 /* ??? These are currently only used for downloading character sets.  As
    such, they don't need memory barriers.  Is this all they are intended
    to be used for?  */
-#define vga_readb	readb
-#define vga_writeb	writeb
+#define vga_readb(a)	readb((u8 __iomem *)(a))
+#define vga_writeb(v,a)	writeb(v, (u8 __iomem *)(a))
 
-#define VGA_MAP_MEM(x)	((unsigned long) ioremap((x), 0))
+#define VGA_MAP_MEM(x)	((unsigned long) ioremap(x, 0))
 
 #endif
diff --git a/include/asm-arm/apm.h b/include/asm-arm/apm.h
index 4d9f87418..3a50eb759 100644
--- a/include/asm-arm/apm.h
+++ b/include/asm-arm/apm.h
@@ -14,24 +14,7 @@
 #define ARM_ASM_SA1100_APM_H
 
 #include <linux/config.h>
-
-#ifdef CONFIG_APM
-
-
-#define APM_AC_OFFLINE 0
-#define APM_AC_ONLINE 1
-#define APM_AC_BACKUP 2
-#define APM_AC_UNKNOWN 0xFF
-
-#define APM_BATTERY_STATUS_HIGH 0
-#define APM_BATTERY_STATUS_LOW  1
-#define APM_BATTERY_STATUS_CRITICAL 2
-#define APM_BATTERY_STATUS_CHARGING 3
-#define APM_BATTERY_STATUS_UNKNOWN 0xFF
-
-#define APM_BATTERY_LIFE_UNKNOWN 0xFFFF
-#define APM_BATTERY_LIFE_MINUTES 0x8000
-#define APM_BATTERY_LIFE_VALUE_MASK 0x7FFF
+#include <linux/apm_bios.h>
 
 /*
  * This structure gets filled in by the machine specific 'get_power_status'
@@ -39,18 +22,44 @@
  */
 struct apm_power_info {
 	unsigned char	ac_line_status;
+#define APM_AC_OFFLINE			0
+#define APM_AC_ONLINE			1
+#define APM_AC_BACKUP			2
+#define APM_AC_UNKNOWN			0xff
+
 	unsigned char	battery_status;
+#define APM_BATTERY_STATUS_HIGH		0
+#define APM_BATTERY_STATUS_LOW		1
+#define APM_BATTERY_STATUS_CRITICAL	2
+#define APM_BATTERY_STATUS_CHARGING	3
+#define APM_BATTERY_STATUS_NOT_PRESENT	4
+#define APM_BATTERY_STATUS_UNKNOWN	0xff
+
 	unsigned char	battery_flag;
-	unsigned char	battery_life;
+#define APM_BATTERY_FLAG_HIGH		(1 << 0)
+#define APM_BATTERY_FLAG_LOW		(1 << 1)
+#define APM_BATTERY_FLAG_CRITICAL	(1 << 2)
+#define APM_BATTERY_FLAG_CHARGING	(1 << 3)
+#define APM_BATTERY_FLAG_NOT_PRESENT	(1 << 7)
+#define APM_BATTERY_FLAG_UNKNOWN	0xff
+
+	int		battery_life;
 	int		time;
 	int		units;
+#define APM_UNITS_MINS			0
+#define APM_UNITS_SECS			1
+#define APM_UNITS_UNKNOWN		-1
+
 };
 
 /*
  * This allows machines to provide their own "apm get power status" function.
  */
 extern void (*apm_get_power_status)(struct apm_power_info *);
-#endif
 
+/*
+ * Queue an event (APM_SYS_SUSPEND or APM_CRITICAL_SUSPEND)
+ */
+void apm_queue_event(apm_event_t event);
 
 #endif
diff --git a/include/asm-arm/arch-cl7500/uncompress.h b/include/asm-arm/arch-cl7500/uncompress.h
index fffaabdbb..68601b3e3 100644
--- a/include/asm-arm/arch-cl7500/uncompress.h
+++ b/include/asm-arm/arch-cl7500/uncompress.h
@@ -16,7 +16,7 @@ static __inline__ void putc(char c)
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	while (*s) {
 		putc(*s);
diff --git a/include/asm-arm/arch-clps711x/uncompress.h b/include/asm-arm/arch-clps711x/uncompress.h
index 152fef0ee..7d0ab791b 100644
--- a/include/asm-arm/arch-clps711x/uncompress.h
+++ b/include/asm-arm/arch-clps711x/uncompress.h
@@ -40,7 +40,7 @@
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	char c;
 
diff --git a/include/asm-arm/arch-ebsa110/param.h b/include/asm-arm/arch-ebsa110/param.h
index 13a9fc1b7..be19b08d1 100644
--- a/include/asm-arm/arch-ebsa110/param.h
+++ b/include/asm-arm/arch-ebsa110/param.h
@@ -1,4 +1,4 @@
 /*
  *  linux/include/asm-arm/arch-ebsa110/param.h
  */
-#define __KERNEL_HZ	200
+#define HZ	200
diff --git a/include/asm-arm/arch-ebsa110/uncompress.h b/include/asm-arm/arch-ebsa110/uncompress.h
index 1d7d841ef..eee95581a 100644
--- a/include/asm-arm/arch-ebsa110/uncompress.h
+++ b/include/asm-arm/arch-ebsa110/uncompress.h
@@ -11,7 +11,7 @@
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	unsigned long tmp1, tmp2;
 	__asm__ __volatile__(
diff --git a/include/asm-arm/arch-ebsa285/uncompress.h b/include/asm-arm/arch-ebsa285/uncompress.h
index 351cc7b2c..c2fd84e2d 100644
--- a/include/asm-arm/arch-ebsa285/uncompress.h
+++ b/include/asm-arm/arch-ebsa285/uncompress.h
@@ -29,7 +29,7 @@ static __inline__ void putc(char c)
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	while (*s) {
 		putc(*s);
diff --git a/include/asm-arm/arch-epxa10db/uncompress.h b/include/asm-arm/arch-epxa10db/uncompress.h
index f30a31fa5..d33ad6a93 100644
--- a/include/asm-arm/arch-epxa10db/uncompress.h
+++ b/include/asm-arm/arch-epxa10db/uncompress.h
@@ -26,7 +26,7 @@
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	while (*s) {
 		while ((*UART_TSR(EXC_UART00_BASE) &
diff --git a/include/asm-arm/arch-integrator/uncompress.h b/include/asm-arm/arch-integrator/uncompress.h
index 284a4aeb6..395740274 100644
--- a/include/asm-arm/arch-integrator/uncompress.h
+++ b/include/asm-arm/arch-integrator/uncompress.h
@@ -28,7 +28,7 @@
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	while (*s) {
 		while (AMBA_UART_FR & (1 << 5));
diff --git a/include/asm-arm/arch-iop3xx/dma.h b/include/asm-arm/arch-iop3xx/dma.h
index 45e157101..797f9e6fc 100644
--- a/include/asm-arm/arch-iop3xx/dma.h
+++ b/include/asm-arm/arch-iop3xx/dma.h
@@ -1,109 +1,16 @@
 /*
- * linux/include/asm-arm/arch-iop80310/dma.h
+ * linux/include/asm-arm/arch-iop3xx/dma.h
  *
- *  Copyright (C) 2001 MontaVista Software, Inc.
+ *  Copyright (C) 2004 Intel Corp.
  *
  * 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 _IOP310_DMA_H_
-#define _IOP310_DMA_H_
-
-/* 2 DMA on primary PCI and 1 on secondary for 80310 */
-#define MAX_IOP310_DMA_CHANNEL   3
-#define MAX_DMA_DESC        	64	/*128 */
-
-/*
- * Make the generic DMA bits go away since we don't use it
- */
-#define MAX_DMA_CHANNELS	0
+#ifndef _IOP3XX_DMA_H_P
+#define _IOP3XX_DMA_H_P
 
 #define MAX_DMA_ADDRESS		0xffffffff
 
-#define IOP310_DMA_P0      	0
-#define IOP310_DMA_P1		1
-#define IOP310_DMA_S0      	2
-
-#define DMA_MOD_READ        	0x0001
-#define DMA_MOD_WRITE		0x0002
-#define DMA_MOD_CACHED		0x0004
-#define DMA_MOD_NONCACHED	0x0008
-
-
-#define DMA_DESC_DONE   	0x0010
-#define DMA_INCOMPLETE  	0x0020
-#define DMA_HOLD		0x0040
-#define DMA_END_CHAIN		0x0080
-#define DMA_COMPLETE		0x0100
-#define DMA_NOTIFY		0x0200
-#define DMA_NEW_HEAD		0x0400
-
-#define DMA_USER_MASK	(DMA_NOTIFY | DMA_INCOMPLETE | \
-						 DMA_HOLD | DMA_COMPLETE)
-
-#define DMA_DCR_DAC		0x00000020	/* Dual Addr Cycle Enab */
-#define DMA_DCR_IE		0x00000010	/* Interrupt Enable */
-#define DMA_DCR_PCI_IOR		0x00000002	/* I/O Read */
-#define DMA_DCR_PCI_IOW		0x00000003	/* I/O Write */
-#define DMA_DCR_PCI_MR		0x00000006	/* Memory Read */
-#define DMA_DCR_PCI_MW		0x00000007	/* Memory Write */
-#define DMA_DCR_PCI_CR		0x0000000A	/* Configuration Read */
-#define DMA_DCR_PCI_CW		0x0000000B	/* Configuration Write */
-#define DMA_DCR_PCI_MRM		0x0000000C	/* Memory Read Multiple */
-#define DMA_DCR_PCI_MRL		0x0000000E	/* Memory Read Line */
-#define DMA_DCR_PCI_MWI		0x0000000F	/* Mem Write and Inval */
-
-#define DMA_USER_CMD_IE		0x00000001	/* user request int */
-#define DMA_USER_END_CHAIN	0x00000002	/* end of sgl chain flag */
-
-/* ATU defines */
-#define     IOP310_ATUCR_PRIM_OUT_ENAB  /* Configuration   */      0x00000002
-#define     IOP310_ATUCR_DIR_ADDR_ENAB  /* Configuration   */      0x00000080
-
-
-typedef void (*dma_callback_t) (void *buf_context);
-/*
- * DMA Descriptor
- */
-typedef struct _dma_desc
-{
-	u32 NDAR;					/* next descriptor address */
-	u32 PDAR;					/* PCI address */
-	u32 PUADR;					/* upper PCI address */
-	u32 LADR;					/* local address */
-	u32 BC;						/* byte count */
-	u32 DC;						/* descriptor control */
-} dma_desc_t;
-
-typedef struct _dma_sgl
-{
-	dma_desc_t dma_desc;		/* DMA descriptor pointer */
-	u32 status;					/* descriptor status */
-	void *data;					/* local virt */
-	struct _dma_sgl *next;		/* next descriptor */
-} dma_sgl_t;
-
-/* dma sgl head */
-typedef struct _dma_head
-{
-	u32 total;					/* total elements in SGL */
-	u32 status;					/* status of sgl */
-	u32 mode;					/* read or write mode */
-	dma_sgl_t *list;			/* pointer to list */
-	dma_callback_t callback;	/* callback function */
-} dma_head_t;
-
-/* function prototypes */
-int dma_request(dmach_t, const char *);
-int dma_queue_buffer(dmach_t, dma_head_t *);
-int dma_suspend(dmach_t);
-int dma_resume(dmach_t);
-int dma_flush_all(dmach_t);
-void dma_free(dmach_t);
-void dma_set_irq_threshold(dmach_t, int);
-dma_sgl_t *dma_get_buffer(dmach_t, int);
-void dma_return_buffer(dmach_t, dma_sgl_t *);
-
-#endif /* _ASM_ARCH_DMA_H */
+#endif /* _ASM_ARCH_DMA_H_P */
diff --git a/include/asm-arm/arch-iop3xx/hardware.h b/include/asm-arm/arch-iop3xx/hardware.h
index 03338ca25..6c15fde86 100644
--- a/include/asm-arm/arch-iop3xx/hardware.h
+++ b/include/asm-arm/arch-iop3xx/hardware.h
@@ -1,10 +1,10 @@
 /*
- * linux/include/asm-arm/arch-iop80310/hardware.h
+ * linux/include/asm-arm/arch-iop3xx/hardware.h
  */
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
-#include <linux/config.h>
+#include <asm/types.h>
 
 /*
  * Note about PCI IO space mappings
@@ -15,41 +15,42 @@
  * The PCI IO space is located at virtual 0xfe000000 from physical
  * 0x90000000.  The PCI BARs must be programmed with physical addresses,
  * but when we read them, we convert them to virtual addresses.  See
- * arch/arm/mach-iop310/iop310-pci.c
+ * arch/arm/mach-iop3xx/iop3xx-pci.c
  */
 
 #define pcibios_assign_all_busses() 1
 
-#ifdef CONFIG_ARCH_IOP310
+
 /*
- * these are the values for the secondary PCI bus on the 80312 chip.  I will
- * have to do some fixup in the bus/dev fixup code
+ * The min PCI I/O and MEM space are dependent on what specific
+ * chipset/platform we are running on, so instead of hardcoding with
+ * #ifdefs, we just fill these in the platform level PCI init code.
  */
-#define PCIBIOS_MIN_IO      0
-#define PCIBIOS_MIN_MEM     0x88000000
-
-// Generic chipset bits
-#include "iop310.h"
+#ifndef __ASSEMBLY__
+extern unsigned long iop3xx_pcibios_min_io;
+extern unsigned long iop3xx_pcibios_min_mem;
 
-// Board specific
-#if defined(CONFIG_ARCH_IQ80310)
-#include "iq80310.h"
+extern unsigned int processor_id;
 #endif
-#endif
-
-#ifdef CONFIG_ARCH_IOP321
 
-#define PCIBIOS_MIN_IO		0x90000000
-#define PCIBIOS_MIN_MEM		0x80000000
+/*
+ * We just set these to zero since they are really bogus anyways
+ */
+#define PCIBIOS_MIN_IO      (iop3xx_pcibios_min_io)
+#define PCIBIOS_MIN_MEM     (iop3xx_pcibios_min_mem)
 
+/*
+ * Generic chipset bits
+ *
+ */
 #include "iop321.h"
+#include "iop331.h"
 
-#ifdef CONFIG_ARCH_IQ80321
+/*
+ * Board specific bits
+ */
 #include "iq80321.h"
-#endif
-#endif
-
-
-
+#include "iq31244.h"
+#include "iq80331.h"
 
 #endif  /* _ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-iop3xx/iop321-irqs.h b/include/asm-arm/arch-iop3xx/iop321-irqs.h
index 9d5518da5..2fcc1654c 100644
--- a/include/asm-arm/arch-iop3xx/iop321-irqs.h
+++ b/include/asm-arm/arch-iop3xx/iop321-irqs.h
@@ -9,8 +9,8 @@
  * published by the Free Software Foundation.
  *
  */
-
-#include <linux/config.h>
+#ifndef _IOP321_IRQS_H_
+#define _IOP321_IRQS_H_
 
 /*
  * IOP80321 chipset interrupts
@@ -62,7 +62,6 @@
 /*
  * Interrupts available on the IQ80321 board
  */
-#ifdef CONFIG_ARCH_IQ80321
 
 /*
  * On board devices
@@ -78,7 +77,24 @@
 #define	IRQ_IQ80321_INTC	IRQ_IOP321_XINT2
 #define	IRQ_IQ80321_INTD	IRQ_IOP321_XINT3
 
-#endif // CONFIG_ARCH_IQ80321
+/*
+ * Interrupts on the IQ31244 board
+ */
+
+/*
+ * On board devices
+ */
+#define IRQ_IQ31244_UART	IRQ_IOP321_XINT1
+#define	IRQ_IQ31244_I82546	IRQ_IOP321_XINT0
+#define IRQ_IQ31244_SATA	IRQ_IOP321_XINT2
+#define	IRQ_IQ31244_PCIX_SLOT	IRQ_IOP321_XINT3
 
-#define XSCALE_PMU_IRQ	IRQ_IOP321_CORE_PMU
+/*
+ * PCI interrupts
+ */
+#define	IRQ_IQ31244_INTA	IRQ_IOP321_XINT0
+#define	IRQ_IQ31244_INTB	IRQ_IOP321_XINT1
+#define	IRQ_IQ31244_INTC	IRQ_IOP321_XINT2
+#define	IRQ_IQ31244_INTD	IRQ_IOP321_XINT3
 
+#endif // _IOP321_IRQ_H_
diff --git a/include/asm-arm/arch-iop3xx/iop321.h b/include/asm-arm/arch-iop3xx/iop321.h
index dcf2c7ff9..98908a02c 100644
--- a/include/asm-arm/arch-iop3xx/iop321.h
+++ b/include/asm-arm/arch-iop3xx/iop321.h
@@ -20,23 +20,29 @@
  * IOP3xx variants but behave slightly differently on each.
  */
 #ifndef __ASSEMBLY__
-#define iop_is_321() ((processor_id & 0xfffff7e0) == 0x69052420)
+#ifdef	CONFIG_ARCH_IOP321
+#define iop_is_321() (((processor_id & 0xfffff5e0) == 0x69052420))
+#else
+#define	iop_is_321()	0
+#endif
 #endif
-
 
 /*
  * IOP321 I/O and Mem space regions for PCI autoconfiguration
  */
+#define IOP321_PCI_LOWER_IO             0x90000000
+#define IOP321_PCI_UPPER_IO             0x9000ffff
+#define IOP321_PCI_LOWER_MEM            0x80000000
+#define IOP321_PCI_UPPER_MEM            0x83ffffff
+
+#define IOP321_PCI_WINDOW_SIZE          64 * 0x100000
 
-#define	IOP321_PCI_IO_BASE		0x90000000
-#define	IOP321_PCI_IO_SIZE		0x00010000
-#define IOP321_PCI_MEM_BASE		0x40000000
-#define IOP321_PCI_MEM_SIZE		0x40000000
 
 /*
  * IOP321 chipset registers
  */
-#define IOP321_VIRT_MEM_BASE 0xfff00000  /* chip virtual mem address*/
+#define IOP321_VIRT_MEM_BASE 0xfeffe000  /* chip virtual mem address*/
+//#define IOP321_VIRT_MEM_BASE 0xfff00000  /* chip virtual mem address*/
 
 #define IOP321_PHY_MEM_BASE  0xffffe000  /* chip physical memory address */
 #define IOP321_REG_ADDR(reg) (IOP321_VIRT_MEM_BASE | (reg))
@@ -134,6 +140,16 @@
 #define IOP321_OPHPR      (volatile u32 *)IOP321_REG_ADDR(0x00000378)
 #define IOP321_OPTPR      (volatile u32 *)IOP321_REG_ADDR(0x0000037C)
 #define IOP321_IAR        (volatile u32 *)IOP321_REG_ADDR(0x00000380)
+
+#define IOP321_IIxR_MASK	0x7f /* masks all */
+#define IOP321_IIxR_IRI		0x40 /* RC Index Register Interrupt */
+#define IOP321_IIxR_OFQF	0x20 /* RC Output Free Q Full (ERROR) */
+#define IOP321_IIxR_ipq		0x10 /* RC Inbound Post Q (post) */
+#define IOP321_IIxR_ERRDI	0x08 /* RO Error Doorbell Interrupt */
+#define IOP321_IIxR_IDI		0x04 /* RO Inbound Doorbell Interrupt */
+#define IOP321_IIxR_IM1		0x02 /* RC Inbound Message 1 Interrupt */
+#define IOP321_IIxR_IM0		0x01 /* RC Inbound Message 0 Interrupt */
+
 /* Reserved 0x00000384 through 0x000003FF */
 
 /* DMA Controller 0x00000400 through 0x000004FF */
@@ -186,10 +202,21 @@
 
 #define IOP321_PBISR_BOOR_ERR 0x1
 
+/* Peripheral performance monitoring unit 0x00000700 through 0x00077F */
+#define IOP321_GTMR	(volatile u32 *)IOP321_REG_ADDR(0x00000700)
+#define IOP321_ESR	(volatile u32 *)IOP321_REG_ADDR(0x00000704)
+#define IOP321_EMISR	(volatile u32 *)IOP321_REG_ADDR(0x00000708)
+/* reserved 0x00000070c */
+#define IOP321_GTSR	(volatile u32 *)IOP321_REG_ADDR(0x00000710)
+/* PERC0 DOESN'T EXIST - index from 1! */
+#define IOP321_PERCR0	(volatile u32 *)IOP321_REG_ADDR(0x00000710)
 
+#define IOP321_GTMR_NGCE	0x04 /* (Not) Global Counter Enable */
 
-/* Peripheral performance monitoring unit 0x00000700 through 0x00077F */
 /* Internal arbitration unit 0x00000780 through 0x0007BF */
+#define IOP321_IACR	(volatile u32 *)IOP321_REG_ADDR(0x00000780)
+#define IOP321_MTTR1	(volatile u32 *)IOP321_REG_ADDR(0x00000784)
+#define IOP321_MTTR2	(volatile u32 *)IOP321_REG_ADDR(0x00000788)
 
 /* General Purpose I/O Registers */
 #define IOP321_GPOE       (volatile u32 *)IOP321_REG_ADDR(0x000007C4)
@@ -207,6 +234,17 @@
 #define IOP321_TU_TMR0		(volatile u32 *)IOP321_REG_ADDR(0x000007E0)
 #define IOP321_TU_TMR1		(volatile u32 *)IOP321_REG_ADDR(0x000007E4)
 
+#ifdef CONFIG_ARCH_IQ80321
+#define	IOP321_TICK_RATE	200000000	/* 200 MHz clock */
+#elif defined(CONFIG_ARCH_IQ31244)
+#define IOP321_TICK_RATE	198000000	/* 33.000 MHz crystal */
+#endif
+
+#ifdef CONFIG_ARCH_EP80219
+#undef IOP321_TICK_RATE
+#define IOP321_TICK_RATE 200000000 /* 33.333333 Mhz crystal */
+#endif
+
 #define IOP321_TMR_TC		0x01
 #define	IOP321_TMR_EN		0x02
 #define IOP321_TMR_RELOAD	0x04
@@ -224,15 +262,43 @@
 #define IOP321_TU_TISR    (volatile u32 *)IOP321_REG_ADDR(0x000007F8)
 #define IOP321_TU_WDTCR   (volatile u32 *)IOP321_REG_ADDR(0x000007FC)
 
-
-
 /* Application accelerator unit 0x00000800 - 0x000008FF */
 #define IOP321_AAU_ACR     (volatile u32 *)IOP321_REG_ADDR(0x00000800)
 #define IOP321_AAU_ASR     (volatile u32 *)IOP321_REG_ADDR(0x00000804)
 #define IOP321_AAU_ADAR    (volatile u32 *)IOP321_REG_ADDR(0x00000808)
 #define IOP321_AAU_ANDAR   (volatile u32 *)IOP321_REG_ADDR(0x0000080C)
 #define IOP321_AAU_SAR1    (volatile u32 *)IOP321_REG_ADDR(0x00000810)
-/* SAR2...SAR32 0x00000814 - 0x000008A4 */
+#define IOP321_AAU_SAR2    (volatile u32 *)IOP321_REG_ADDR(0x00000814)
+#define IOP321_AAU_SAR3    (volatile u32 *)IOP321_REG_ADDR(0x00000818)
+#define IOP321_AAU_SAR4    (volatile u32 *)IOP321_REG_ADDR(0x0000081C)
+#define IOP321_AAU_SAR5    (volatile u32 *)IOP321_REG_ADDR(0x0000082C)
+#define IOP321_AAU_SAR6    (volatile u32 *)IOP321_REG_ADDR(0x00000830)
+#define IOP321_AAU_SAR7    (volatile u32 *)IOP321_REG_ADDR(0x00000834)
+#define IOP321_AAU_SAR8    (volatile u32 *)IOP321_REG_ADDR(0x00000838)
+#define IOP321_AAU_SAR9    (volatile u32 *)IOP321_REG_ADDR(0x00000840)
+#define IOP321_AAU_SAR10   (volatile u32 *)IOP321_REG_ADDR(0x00000844)
+#define IOP321_AAU_SAR11   (volatile u32 *)IOP321_REG_ADDR(0x00000848)
+#define IOP321_AAU_SAR12   (volatile u32 *)IOP321_REG_ADDR(0x0000084C)
+#define IOP321_AAU_SAR13   (volatile u32 *)IOP321_REG_ADDR(0x00000850)
+#define IOP321_AAU_SAR14   (volatile u32 *)IOP321_REG_ADDR(0x00000854)
+#define IOP321_AAU_SAR15   (volatile u32 *)IOP321_REG_ADDR(0x00000858)
+#define IOP321_AAU_SAR16   (volatile u32 *)IOP321_REG_ADDR(0x0000085C)
+#define IOP321_AAU_SAR17   (volatile u32 *)IOP321_REG_ADDR(0x00000864)
+#define IOP321_AAU_SAR18   (volatile u32 *)IOP321_REG_ADDR(0x00000868)
+#define IOP321_AAU_SAR19   (volatile u32 *)IOP321_REG_ADDR(0x0000086C)
+#define IOP321_AAU_SAR20   (volatile u32 *)IOP321_REG_ADDR(0x00000870)
+#define IOP321_AAU_SAR21   (volatile u32 *)IOP321_REG_ADDR(0x00000874)
+#define IOP321_AAU_SAR22   (volatile u32 *)IOP321_REG_ADDR(0x00000878)
+#define IOP321_AAU_SAR23   (volatile u32 *)IOP321_REG_ADDR(0x0000087C)
+#define IOP321_AAU_SAR24   (volatile u32 *)IOP321_REG_ADDR(0x00000880)
+#define IOP321_AAU_SAR25   (volatile u32 *)IOP321_REG_ADDR(0x00000888)
+#define IOP321_AAU_SAR26   (volatile u32 *)IOP321_REG_ADDR(0x0000088C)
+#define IOP321_AAU_SAR27   (volatile u32 *)IOP321_REG_ADDR(0x00000890)
+#define IOP321_AAU_SAR28   (volatile u32 *)IOP321_REG_ADDR(0x00000894)
+#define IOP321_AAU_SAR29   (volatile u32 *)IOP321_REG_ADDR(0x00000898)
+#define IOP321_AAU_SAR30   (volatile u32 *)IOP321_REG_ADDR(0x0000089C)
+#define IOP321_AAU_SAR31   (volatile u32 *)IOP321_REG_ADDR(0x000008A0)
+#define IOP321_AAU_SAR32   (volatile u32 *)IOP321_REG_ADDR(0x000008A4)
 #define IOP321_AAU_DAR     (volatile u32 *)IOP321_REG_ADDR(0x00000820)
 #define IOP321_AAU_ABCR    (volatile u32 *)IOP321_REG_ADDR(0x00000824)
 #define IOP321_AAU_ADCR    (volatile u32 *)IOP321_REG_ADDR(0x00000828)
@@ -260,4 +326,11 @@
 
 /* for I2C bit defs see drivers/i2c/i2c-iop3xx.h */
 
+
+#ifndef __ASSEMBLY__
+extern void iop321_map_io(void);
+extern void iop321_init_irq(void);
+extern void iop321_time_init(void);
+#endif
+
 #endif // _IOP321_HW_H_
diff --git a/include/asm-arm/arch-iop3xx/iq80321.h b/include/asm-arm/arch-iop3xx/iq80321.h
index 8a94ce8ff..e1c543039 100644
--- a/include/asm-arm/arch-iop3xx/iq80321.h
+++ b/include/asm-arm/arch-iop3xx/iq80321.h
@@ -1,17 +1,35 @@
 /*
  * linux/include/asm/arch-iop3xx/iq80321.h
  *
- * Intel IQ-80321 evaluation board registers
+ * Intel IQ80321 evaluation board registers
  */
 
 #ifndef _IQ80321_H_
 #define _IQ80321_H_
 
-#define IQ80321_RAMBASE      0xa0000000
-#define IQ80321_UART1        0xfe800000    /* UART #1 */
-#define IQ80321_7SEG_1       0xfe840000    /* 7-Segment MSB */
-#define IQ80321_7SEG_0       0xfe850000    /* 7-Segment LSB (WO) */
-#define IQ80321_ROTARY_SW    0xfe8d0000    /* Rotary Switch */
-#define IQ80321_BATT_STAT    0xfe8f0000    /* Battery Status */
+#define IQ80321_RAMBASE		0xa0000000
+
+#define	IQ80321_FLASHBASE	0xf0000000	/* Flash */
+#define	IQ80321_FLASHSIZE	0x00800000
+#define	IQ80321_FLASHWIDTH	1
+
+#define IQ80321_UART		0xfe800000	/* UART #1 */
+#define IQ80321_7SEG_1		0xfe840000	/* 7-Segment MSB */
+#define IQ80321_7SEG_0		0xfe850000	/* 7-Segment LSB (WO) */
+#define IQ80321_ROTARY_SW	0xfe8d0000	/* Rotary Switch */
+#define IQ80321_BATT_STAT	0xfe8f0000	/* Battery Status */
+
+/*
+ * IQ80321 PCI I/O and Mem space regions
+ */
+#define IQ80321_PCI_IO_BASE	0x90000000
+#define IQ80321_PCI_IO_SIZE	0x00010000
+#define IQ80321_PCI_MEM_BASE	0x80000000
+#define IQ80321_PCI_MEM_SIZE	0x04000000
+#define	IQ80321_PCI_IO_OFFSET	0x6e000000
+
+#ifndef __ASSEMBLY__
+extern void iq80321_map_io(void);
+#endif
 
 #endif	// _IQ80321_H_
diff --git a/include/asm-arm/arch-iop3xx/irqs.h b/include/asm-arm/arch-iop3xx/irqs.h
index 1df33024c..b2c03f4c2 100644
--- a/include/asm-arm/arch-iop3xx/irqs.h
+++ b/include/asm-arm/arch-iop3xx/irqs.h
@@ -1,27 +1,21 @@
 /*
  * linux/include/asm-arm/arch-iop3xx/irqs.h
  *
- * Copyright:	(C) 2001 MontaVista Software Inc.
+ * Copyright:	(C) 2001-2003 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/config.h>
-
 /*
- * Whic iop3xx implementation is this?
+ * Chipset-specific bits
  */
-#ifdef CONFIG_ARCH_IOP310
-
-#include "iop310-irqs.h"
-
-#else
-
+#ifdef CONFIG_ARCH_IOP321
 #include "iop321-irqs.h"
-
 #endif
 
+#ifdef CONFIG_ARCH_IOP331
+#include "iop331-irqs.h"
+#endif
diff --git a/include/asm-arm/arch-iop3xx/memory.h b/include/asm-arm/arch-iop3xx/memory.h
index a2d077a3b..dc4735cb0 100644
--- a/include/asm-arm/arch-iop3xx/memory.h
+++ b/include/asm-arm/arch-iop3xx/memory.h
@@ -1,41 +1,39 @@
 /*
- * linux/include/asm-arm/arch-iop80310/memory.h
+ * linux/include/asm-arm/arch-iop3xx/memory.h
  */
 
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
 #include <linux/config.h>
-#include <asm/arch/iop310.h>
-#include <asm/arch/iop321.h>
+#include <asm/hardware.h>
 
 /*
  * Physical DRAM offset.
  */
+#ifndef CONFIG_ARCH_IOP331
 #define PHYS_OFFSET	(0xa0000000UL)
+#else
+#define PHYS_OFFSET	(0x00000000UL)
+#endif
 
 /*
- * Virtual view <-> DMA view memory address translations
+ * Virtual view <-> PCI DMA view memory address translations
  * virt_to_bus: Used to translate the virtual address to an
  *		address suitable to be passed to set_dma_addr
  * bus_to_virt: Used to convert an address for DMA operations
  *		to an address that the kernel can use.
  */
-#ifdef CONFIG_ARCH_IOP310
-
-#define __virt_to_bus(x)	(((__virt_to_phys(x)) & ~(*IOP310_SIATVR)) | ((*IOP310_SIABAR) & 0xfffffff0))
-#define __bus_to_virt(x)    (__phys_to_virt(((x) & ~(*IOP310_SIALR)) | ( *IOP310_SIATVR)))
-
-#elif defined(CONFIG_ARCH_IOP321)
+#if defined(CONFIG_ARCH_IOP321)
 
 #define __virt_to_bus(x)	(((__virt_to_phys(x)) & ~(*IOP321_IATVR2)) | ((*IOP321_IABAR2) & 0xfffffff0))
 #define __bus_to_virt(x)    (__phys_to_virt(((x) & ~(*IOP321_IALR2)) | ( *IOP321_IATVR2)))
 
-#endif
+#elif defined(CONFIG_ARCH_IOP331)
+
+#define __virt_to_bus(x)	(((__virt_to_phys(x)) & ~(*IOP331_IATVR2)) | ((*IOP331_IABAR2) & 0xfffffff0))
+#define __bus_to_virt(x)    (__phys_to_virt(((x) & ~(*IOP331_IALR2)) | ( *IOP331_IATVR2)))
 
-/* boot mem allocate global pointer for MU circular queues QBAR */
-#ifdef CONFIG_IOP3XX_MU
-extern void *mu_mem;
 #endif
 
 #define PFN_TO_NID(addr)	(0)
diff --git a/include/asm-arm/arch-iop3xx/param.h b/include/asm-arm/arch-iop3xx/param.h
index 56a1672f1..acf404e87 100644
--- a/include/asm-arm/arch-iop3xx/param.h
+++ b/include/asm-arm/arch-iop3xx/param.h
@@ -1,3 +1,3 @@
 /*
- *  linux/include/asm-arm/arch-iop80310/param.h
+ *  linux/include/asm-arm/arch-iop3xx/param.h
  */
diff --git a/include/asm-arm/arch-iop3xx/serial.h b/include/asm-arm/arch-iop3xx/serial.h
index 8217c12b8..61192f98c 100644
--- a/include/asm-arm/arch-iop3xx/serial.h
+++ b/include/asm-arm/arch-iop3xx/serial.h
@@ -15,26 +15,61 @@
 /* Standard COM flags */
 #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
 
-#ifdef CONFIG_ARCH_IQ80310
+#ifdef CONFIG_ARCH_IQ80321
+
+#define IRQ_UART1	IRQ_IQ80321_UART
 
-#define IRQ_UART1	IRQ_IQ80310_UART1
-#define IRQ_UART2	IRQ_IQ80310_UART2
+#define RS_TABLE_SIZE 1
 
 #define STD_SERIAL_PORT_DEFNS			\
        /* UART CLK      PORT        IRQ        FLAGS        */			\
-	{ 0, BASE_BAUD, IQ80310_UART2, IRQ_UART2, STD_COM_FLAGS },  /* ttyS0 */	\
-	{ 0, BASE_BAUD, IQ80310_UART1, IRQ_UART1, STD_COM_FLAGS }  /* ttyS1 */
+	{ 0, BASE_BAUD, 0xfe800000, IRQ_UART1, STD_COM_FLAGS },  /* ttyS0 */
+#endif // CONFIG_ARCH_IQ80321
 
-#endif // CONFIG_ARCH_IQ80310
+#ifdef CONFIG_ARCH_IQ31244
 
-#ifdef CONFIG_ARCH_IQ80321
+#define IRQ_UART1	IRQ_IQ31244_UART
 
-#define IRQ_UART1	IRQ_IQ80321_UART
+#define RS_TABLE_SIZE 1
 
 #define STD_SERIAL_PORT_DEFNS			\
        /* UART CLK      PORT        IRQ        FLAGS        */			\
 	{ 0, BASE_BAUD, 0xfe800000, IRQ_UART1, STD_COM_FLAGS },  /* ttyS0 */
-#endif // CONFIG_ARCH_IQ80321
+#endif // CONFIG_ARCH_IQ31244
+
+#ifdef CONFIG_ARCH_IQ80331
+
+#undef BASE_BAUD
+
+#define BASE_BAUD ( 33334000 / 16 )
+
+#define IRQ_UART0	IRQ_IQ80331_UART0
+#define IRQ_UART1	IRQ_IQ80331_UART1
+
+#define RS_TABLE_SIZE 2
+
+#define STD_SERIAL_PORT_DEFNS				\
+	{						\
+	  /*type: PORT_XSCALE,*/			\
+	  /*xmit_fifo_size: 32,*/			\
+	  baud_base: BASE_BAUD,				\
+	  irq: IRQ_UART0,			  	\
+	  flags: STD_COM_FLAGS,				\
+	  iomem_base: IQ80331_UART0_VIRT,		\
+	  io_type: SERIAL_IO_MEM,			\
+	  iomem_reg_shift: 2				\
+	}, /* ttyS0 */					\
+	{						\
+	  /*type: PORT_XSCALE,*/			\
+	  /*xmit_fifo_size: 32,*/			\
+	  baud_base: BASE_BAUD,				\
+	  irq: IRQ_UART1,			  	\
+	  flags: STD_COM_FLAGS,				\
+	  iomem_base: IQ80331_UART1_VIRT,		\
+	  io_type: SERIAL_IO_MEM,			\
+	  iomem_reg_shift: 2				\
+	} /* ttyS1 */
+#endif // CONFIG_ARCH_IQ80331
 
 
 #define EXTRA_SERIAL_PORT_DEFNS
diff --git a/include/asm-arm/arch-iop3xx/system.h b/include/asm-arm/arch-iop3xx/system.h
index 54a101b39..af6ae8cd3 100644
--- a/include/asm-arm/arch-iop3xx/system.h
+++ b/include/asm-arm/arch-iop3xx/system.h
@@ -1,5 +1,5 @@
 /*
- * linux/include/asm-arm/arch-iop80310/system.h
+ * linux/include/asm-arm/arch-iop3xx/system.h
  *
  *  Copyright (C) 2001 MontaVista Software, Inc.
  *
@@ -16,6 +16,14 @@ static inline void arch_idle(void)
 
 static inline void arch_reset(char mode)
 {
+#ifdef CONFIG_ARCH_IOP321
+    *IOP321_PCSR = 0x30;
+#endif
+
+#ifdef CONFIG_ARCH_IOP331
+    *IOP331_PCSR = 0x30;
+#endif
+
 	if ( 1 && mode == 's') {
 		/* Jump into ROM at address 0 */
 		cpu_reset(0);
diff --git a/include/asm-arm/arch-iop3xx/timex.h b/include/asm-arm/arch-iop3xx/timex.h
index 2aec85775..d9dbb443c 100644
--- a/include/asm-arm/arch-iop3xx/timex.h
+++ b/include/asm-arm/arch-iop3xx/timex.h
@@ -1,24 +1,18 @@
 /*
  * linux/include/asm-arm/arch-iop3xx/timex.h
  *
- * IOP310 architecture timex specifications
+ * IOP3xx architecture timex specifications
  */
 #include <linux/config.h>
 
 
-#ifdef CONFIG_ARCH_IQ80310
+#if defined(CONFIG_ARCH_IQ80321) || defined(CONFIG_ARCH_IQ31244)
 
-#ifndef CONFIG_XSCALE_PMU_TIMER
-/* This is for the on-board timer */
-#define CLOCK_TICK_RATE 33000000 /* Underlying HZ */
-#else
-/* This is for the underlying xs80200 PMU clock. We run the core @ 733MHz */
-#define CLOCK_TICK_RATE	733000000
-#endif // IQ80310
+#define CLOCK_TICK_RATE IOP321_TICK_RATE
 
-#elif defined(CONFIG_ARCH_IQ80321)
+#elif defined(CONFIG_ARCH_IQ80331)
 
-#define CLOCK_TICK_RATE 200000000
+#define CLOCK_TICK_RATE IOP331_TICK_RATE
 
 #else
 
diff --git a/include/asm-arm/arch-iop3xx/uncompress.h b/include/asm-arm/arch-iop3xx/uncompress.h
index fd7e72b7d..673fabc1f 100644
--- a/include/asm-arm/arch-iop3xx/uncompress.h
+++ b/include/asm-arm/arch-iop3xx/uncompress.h
@@ -1,26 +1,32 @@
 /*
- *  linux/include/asm-arm/arch-iop80310/uncompress.h
+ *  linux/include/asm-arm/arch-iop3xx/uncompress.h
  */
 #include <linux/config.h>
+#include <asm/types.h>
+#include <asm/mach-types.h>
 #include <linux/serial_reg.h>
 #include <asm/hardware.h>
 
-#ifdef CONFIG_ARCH_IQ80310
-#define UART2_BASE    ((volatile unsigned char *)IQ80310_UART2)
-#elif defined(CONFIG_ARCH_IQ80321)
-#define UART2_BASE    ((volatile unsigned char *)IQ80321_UART1)
+#ifdef CONFIG_ARCH_IOP321
+#define UTYPE unsigned char *
+#else
+#define UTYPE u32 *
 #endif
 
+static volatile UTYPE uart_base;
+
+#define TX_DONE (UART_LSR_TEMT|UART_LSR_THRE)
+
 static __inline__ void putc(char c)
 {
-	while ((UART2_BASE[5] & 0x60) != 0x60);
-	UART2_BASE[0] = c;
+	while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE);
+	*uart_base = c;
 }
 
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	while (*s) {
 		putc(*s);
@@ -30,8 +36,20 @@ static void puts(const char *s)
 	}
 }
 
+static __inline__ void __arch_decomp_setup(unsigned long arch_id)
+{
+        if(machine_is_iq80321())
+			uart_base = (volatile UTYPE)IQ80321_UART;
+		else if(machine_is_iq31244())
+			uart_base = (volatile UTYPE)IQ31244_UART;
+		else if(machine_is_iq80331())
+			uart_base = (volatile UTYPE)IQ80331_UART0_PHYS;
+		else
+			uart_base = (volatile UTYPE)0xfe800000;
+}
+
 /*
  * nothing to do
  */
-#define arch_decomp_setup()
+#define arch_decomp_setup()	__arch_decomp_setup(arch_id)
 #define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-iop3xx/vmalloc.h b/include/asm-arm/arch-iop3xx/vmalloc.h
index e15797db6..d59dfeda9 100644
--- a/include/asm-arm/arch-iop3xx/vmalloc.h
+++ b/include/asm-arm/arch-iop3xx/vmalloc.h
@@ -12,4 +12,5 @@
  */
 #define VMALLOC_OFFSET	  (8*1024*1024)
 #define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
 #define VMALLOC_END       (0xe8000000)
diff --git a/include/asm-arm/arch-ixp4xx/io.h b/include/asm-arm/arch-ixp4xx/io.h
index 91d25c25d..5400ab0ba 100644
--- a/include/asm-arm/arch-ixp4xx/io.h
+++ b/include/asm-arm/arch-ixp4xx/io.h
@@ -73,7 +73,7 @@ __ixp4xx_iounmap(void *addr)
 {
 	extern void __iounmap(void *addr);
 
-	if ((u32)addr > VMALLOC_START)
+	if ((u32)addr >= VMALLOC_START)
 		__iounmap(addr);
 }
 
@@ -101,7 +101,7 @@ __ixp4xx_writeb(u8 value, u32 addr)
 {
 	u32 n, byte_enables, data;
 
-	if (addr > VMALLOC_START) {
+	if (addr >= VMALLOC_START) {
 		__raw_writeb(value, addr);
 		return;
 	}
@@ -124,7 +124,7 @@ __ixp4xx_writew(u16 value, u32 addr)
 {
 	u32 n, byte_enables, data;
 
-	if (addr > VMALLOC_START) {
+	if (addr >= VMALLOC_START) {
 		__raw_writew(value, addr);
 		return;
 	}
@@ -145,7 +145,7 @@ __ixp4xx_writesw(u32 bus_addr, u16 *vaddr, int count)
 static inline void 
 __ixp4xx_writel(u32 value, u32 addr)
 {
-	if (addr > VMALLOC_START) {
+	if (addr >= VMALLOC_START) {
 		__raw_writel(value, addr);
 		return;
 	}
@@ -165,7 +165,7 @@ __ixp4xx_readb(u32 addr)
 {
 	u32 n, byte_enables, data;
 
-	if (addr > VMALLOC_START)
+	if (addr >= VMALLOC_START)
 		return __raw_readb(addr);
 
 	n = addr % 4;
@@ -188,7 +188,7 @@ __ixp4xx_readw(u32 addr)
 {
 	u32 n, byte_enables, data;
 
-	if (addr > VMALLOC_START)
+	if (addr >= VMALLOC_START)
 		return __raw_readw(addr);
 
 	n = addr % 4;
@@ -211,7 +211,7 @@ __ixp4xx_readl(u32 addr)
 {
 	u32 data;
 
-	if (addr > VMALLOC_START)
+	if (addr >= VMALLOC_START)
 		return __raw_readl(addr);
 
 	if (ixp4xx_pci_read(addr, NP_CMD_MEMREAD, &data))
diff --git a/include/asm-arm/arch-ixp4xx/uncompress.h b/include/asm-arm/arch-ixp4xx/uncompress.h
index 29692ecbd..0535098e1 100644
--- a/include/asm-arm/arch-ixp4xx/uncompress.h
+++ b/include/asm-arm/arch-ixp4xx/uncompress.h
@@ -32,7 +32,7 @@ static __inline__ void putc(char c)
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	while (*s)
 	{
diff --git a/include/asm-arm/arch-l7200/param.h b/include/asm-arm/arch-l7200/param.h
index 98786ad71..9962a12ab 100644
--- a/include/asm-arm/arch-l7200/param.h
+++ b/include/asm-arm/arch-l7200/param.h
@@ -16,4 +16,4 @@
 /*
  * See 'time.h' for how the RTC HZ rate is set
  */
-#define __KERNEL_HZ 128
+#define HZ 128
diff --git a/include/asm-arm/arch-l7200/uncompress.h b/include/asm-arm/arch-l7200/uncompress.h
index d7ac5f65e..1caa2b560 100644
--- a/include/asm-arm/arch-l7200/uncompress.h
+++ b/include/asm-arm/arch-l7200/uncompress.h
@@ -23,7 +23,7 @@ static __inline__ void putc(char c)
 	__raw_writeb(c, IO_UART + 0x00);
 }
 
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	while (*s) {
 		if (*s == 10) {			/* If a LF, add CR */
diff --git a/include/asm-arm/arch-lh7a40x/uncompress.h b/include/asm-arm/arch-lh7a40x/uncompress.h
index c31796f78..ec8ab6712 100644
--- a/include/asm-arm/arch-lh7a40x/uncompress.h
+++ b/include/asm-arm/arch-lh7a40x/uncompress.h
@@ -29,7 +29,7 @@ static __inline__ void putc (char ch)
 	UART_DATA = ch;
 }
 
-static void puts (const char* sz)
+static void putstr (const char* sz)
 {
 	for (; *sz; ++sz) {
 		putc (*sz);
diff --git a/include/asm-arm/arch-omap/board-h2.h b/include/asm-arm/arch-omap/board-h2.h
index fe2c06dde..e51f24888 100644
--- a/include/asm-arm/arch-omap/board-h2.h
+++ b/include/asm-arm/arch-omap/board-h2.h
@@ -31,5 +31,15 @@
 
 /* Placeholder for H2 specific defines */
 
+/* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
+#define OMAP1610_ETHR_BASE		0xE8000000
+#define OMAP1610_ETHR_SIZE		SZ_4K
+#define OMAP1610_ETHR_START		0x04000000
+
+/* Intel STRATA NOR flash at CS3 */
+#define OMAP1610_NOR_FLASH_BASE		0xD8000000
+#define OMAP1610_NOR_FLASH_SIZE		SZ_32M
+#define OMAP1610_NOR_FLASH_START	0x0C000000
+
 #endif /*  __ASM_ARCH_OMAP_H2_H */
 
diff --git a/include/asm-arm/arch-omap/board-h3.h b/include/asm-arm/arch-omap/board-h3.h
index f08276f89..80c37bf3b 100644
--- a/include/asm-arm/arch-omap/board-h3.h
+++ b/include/asm-arm/arch-omap/board-h3.h
@@ -1,9 +1,8 @@
 /*
  * linux/include/asm-arm/arch-omap/board-h3.h
  *
- * Hardware definitions for TI OMAP1610 H3 board.
- *
- * Initial creation by Dirk Behme <dirk.behme@de.bosch.com>
+ * Copyright (C) 2001 RidgeRun, Inc.
+ * Copyright (C) 2004 Texas Instruments, 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
@@ -25,11 +24,84 @@
  * with this program; if not, write  to the Free Software Foundation, Inc.,
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-
 #ifndef __ASM_ARCH_OMAP_H3_H
 #define __ASM_ARCH_OMAP_H3_H
 
-/* Placeholder for H3 specific defines */
+/* In OMAP1710 H3 the Ethernet is directly connected to CS1 */
+#define OMAP1710_ETHR_BASE		0xE8000000
+#define OMAP1710_ETHR_SIZE		SZ_4K
+#define OMAP1710_ETHR_START		0x04000000
 
-#endif /*  __ASM_ARCH_OMAP_H3_H */
+/* Intel STRATA NOR flash at CS3 */
+#define OMAP_NOR_FLASH_BASE		0xD8000000
+#define OMAP_NOR_FLASH_SIZE		SZ_32M
+#define OMAP_NOR_FLASH_START		0x00000000
+
+#define MAXIRQNUM			(IH_BOARD_BASE)
+#define MAXFIQNUM			MAXIRQNUM
+#define MAXSWINUM			MAXIRQNUM
 
+#define NR_IRQS				(MAXIRQNUM + 1)
+
+#define OMAP_MCBSP1_BASE		OMAP1610_MCBSP1_BASE
+#define AUDIO_DRR2  (OMAP_MCBSP1_BASE + 0x00)
+#define AUDIO_DRR1  (OMAP_MCBSP1_BASE + 0x02)
+#define AUDIO_DXR2  (OMAP_MCBSP1_BASE + 0x04)
+#define AUDIO_DXR1  (OMAP_MCBSP1_BASE + 0x06)
+#define AUDIO_SPCR2 (OMAP_MCBSP1_BASE + 0x08)
+#define AUDIO_SPCR1 (OMAP_MCBSP1_BASE + 0x0a)
+#define AUDIO_RCR2  (OMAP_MCBSP1_BASE + 0x0c)
+#define AUDIO_RCR1  (OMAP_MCBSP1_BASE + 0x0e)
+#define AUDIO_XCR2  (OMAP_MCBSP1_BASE + 0x10)
+#define AUDIO_XCR1  (OMAP_MCBSP1_BASE + 0x12)
+#define AUDIO_SRGR2 (OMAP_MCBSP1_BASE + 0x14)
+#define AUDIO_SRGR1 (OMAP_MCBSP1_BASE + 0x16)
+#define AUDIO_MCR2  (OMAP_MCBSP1_BASE + 0x18)
+#define AUDIO_MCR1  (OMAP_MCBSP1_BASE + 0x1a)
+#define AUDIO_RCERA (OMAP_MCBSP1_BASE + 0x1c)
+#define AUDIO_RCERB (OMAP_MCBSP1_BASE + 0x1e)
+#define AUDIO_XCERA (OMAP_MCBSP1_BASE + 0x20)
+#define AUDIO_XCERB (OMAP_MCBSP1_BASE + 0x22)
+#define AUDIO_PCR0  (OMAP_MCBSP1_BASE + 0x24)
+
+/* UART3 Registers Maping through MPU bus */
+#define OMAP_MPU_UART3_BASE     0xFFFB9800      /* UART3 through MPU bus */
+#define UART3_RHR               (OMAP_MPU_UART3_BASE + 0)
+#define UART3_THR               (OMAP_MPU_UART3_BASE + 0)
+#define UART3_DLL               (OMAP_MPU_UART3_BASE + 0)
+#define UART3_IER               (OMAP_MPU_UART3_BASE + 4)
+#define UART3_DLH               (OMAP_MPU_UART3_BASE + 4)
+#define UART3_IIR               (OMAP_MPU_UART3_BASE + 8)
+#define UART3_FCR               (OMAP_MPU_UART3_BASE + 8)
+#define UART3_EFR               (OMAP_MPU_UART3_BASE + 8)
+#define UART3_LCR               (OMAP_MPU_UART3_BASE + 0x0C)
+#define UART3_MCR               (OMAP_MPU_UART3_BASE + 0x10)
+#define UART3_XON1_ADDR1        (OMAP_MPU_UART3_BASE + 0x10)
+#define UART3_XON2_ADDR2        (OMAP_MPU_UART3_BASE + 0x14)
+#define UART3_LSR               (OMAP_MPU_UART3_BASE + 0x14)
+#define UART3_TCR               (OMAP_MPU_UART3_BASE + 0x18)
+#define UART3_MSR               (OMAP_MPU_UART3_BASE + 0x18)
+#define UART3_XOFF1             (OMAP_MPU_UART3_BASE + 0x18)
+#define UART3_XOFF2             (OMAP_MPU_UART3_BASE + 0x1C)
+#define UART3_SPR               (OMAP_MPU_UART3_BASE + 0x1C)
+#define UART3_TLR               (OMAP_MPU_UART3_BASE + 0x1C)
+#define UART3_MDR1              (OMAP_MPU_UART3_BASE + 0x20)
+#define UART3_MDR2              (OMAP_MPU_UART3_BASE + 0x24)
+#define UART3_SFLSR             (OMAP_MPU_UART3_BASE + 0x28)
+#define UART3_TXFLL             (OMAP_MPU_UART3_BASE + 0x28)
+#define UART3_RESUME            (OMAP_MPU_UART3_BASE + 0x2C)
+#define UART3_TXFLH             (OMAP_MPU_UART3_BASE + 0x2C)
+#define UART3_SFREGL            (OMAP_MPU_UART3_BASE + 0x30)
+#define UART3_RXFLL             (OMAP_MPU_UART3_BASE + 0x30)
+#define UART3_SFREGH            (OMAP_MPU_UART3_BASE + 0x34)
+#define UART3_RXFLH             (OMAP_MPU_UART3_BASE + 0x34)
+#define UART3_BLR               (OMAP_MPU_UART3_BASE + 0x38)
+#define UART3_ACREG             (OMAP_MPU_UART3_BASE + 0x3C)
+#define UART3_DIV16             (OMAP_MPU_UART3_BASE + 0x3C)
+#define UART3_SCR               (OMAP_MPU_UART3_BASE + 0x40)
+#define UART3_SSR               (OMAP_MPU_UART3_BASE + 0x44)
+#define UART3_EBLR              (OMAP_MPU_UART3_BASE + 0x48)
+#define UART3_OSC_12M_SEL       (OMAP_MPU_UART3_BASE + 0x4C)
+#define UART3_MVR               (OMAP_MPU_UART3_BASE + 0x50)
+
+#endif /*  __ASM_ARCH_OMAP_H3_H */
diff --git a/include/asm-arm/arch-omap/board-innovator.h b/include/asm-arm/arch-omap/board-innovator.h
index 50671ba47..87e45d929 100644
--- a/include/asm-arm/arch-omap/board-innovator.h
+++ b/include/asm-arm/arch-omap/board-innovator.h
@@ -28,92 +28,6 @@
 
 #if defined (CONFIG_ARCH_OMAP1510)
 
-/*
- * ---------------------------------------------------------------------------
- *  OMAP-1510 FPGA
- * ---------------------------------------------------------------------------
- */
-#define OMAP1510_FPGA_BASE			0xE8000000	/* Virtual */
-#define OMAP1510_FPGA_SIZE			SZ_4K
-#define OMAP1510_FPGA_START			0x08000000	/* Physical */
-
-/* Revision */
-#define OMAP1510_FPGA_REV_LOW			(OMAP1510_FPGA_BASE + 0x0)
-#define OMAP1510_FPGA_REV_HIGH			(OMAP1510_FPGA_BASE + 0x1)
-
-#define OMAP1510_FPGA_LCD_PANEL_CONTROL		(OMAP1510_FPGA_BASE + 0x2)
-#define OMAP1510_FPGA_LED_DIGIT			(OMAP1510_FPGA_BASE + 0x3)
-#define INNOVATOR_FPGA_HID_SPI			(OMAP1510_FPGA_BASE + 0x4)
-#define OMAP1510_FPGA_POWER			(OMAP1510_FPGA_BASE + 0x5)
-
-/* Interrupt status */
-#define OMAP1510_FPGA_ISR_LO			(OMAP1510_FPGA_BASE + 0x6)
-#define OMAP1510_FPGA_ISR_HI			(OMAP1510_FPGA_BASE + 0x7)
-
-/* Interrupt mask */
-#define OMAP1510_FPGA_IMR_LO			(OMAP1510_FPGA_BASE + 0x8)
-#define OMAP1510_FPGA_IMR_HI			(OMAP1510_FPGA_BASE + 0x9)
-
-/* Reset registers */
-#define OMAP1510_FPGA_HOST_RESET		(OMAP1510_FPGA_BASE + 0xa)
-#define OMAP1510_FPGA_RST			(OMAP1510_FPGA_BASE + 0xb)
-
-#define OMAP1510_FPGA_AUDIO			(OMAP1510_FPGA_BASE + 0xc)
-#define OMAP1510_FPGA_DIP			(OMAP1510_FPGA_BASE + 0xe)
-#define OMAP1510_FPGA_FPGA_IO			(OMAP1510_FPGA_BASE + 0xf)
-#define OMAP1510_FPGA_UART1			(OMAP1510_FPGA_BASE + 0x14)
-#define OMAP1510_FPGA_UART2			(OMAP1510_FPGA_BASE + 0x15)
-#define OMAP1510_FPGA_OMAP1510_STATUS		(OMAP1510_FPGA_BASE + 0x16)
-#define OMAP1510_FPGA_BOARD_REV			(OMAP1510_FPGA_BASE + 0x18)
-#define OMAP1510P1_PPT_DATA			(OMAP1510_FPGA_BASE + 0x100)
-#define OMAP1510P1_PPT_STATUS			(OMAP1510_FPGA_BASE + 0x101)
-#define OMAP1510P1_PPT_CONTROL			(OMAP1510_FPGA_BASE + 0x102)
-
-#define OMAP1510_FPGA_TOUCHSCREEN		(OMAP1510_FPGA_BASE + 0x204)
-
-#define INNOVATOR_FPGA_INFO			(OMAP1510_FPGA_BASE + 0x205)
-#define INNOVATOR_FPGA_LCD_BRIGHT_LO		(OMAP1510_FPGA_BASE + 0x206)
-#define INNOVATOR_FPGA_LCD_BRIGHT_HI		(OMAP1510_FPGA_BASE + 0x207)
-#define INNOVATOR_FPGA_LED_GRN_LO		(OMAP1510_FPGA_BASE + 0x208)
-#define INNOVATOR_FPGA_LED_GRN_HI		(OMAP1510_FPGA_BASE + 0x209)
-#define INNOVATOR_FPGA_LED_RED_LO		(OMAP1510_FPGA_BASE + 0x20a)
-#define INNOVATOR_FPGA_LED_RED_HI		(OMAP1510_FPGA_BASE + 0x20b)
-#define INNOVATOR_FPGA_CAM_USB_CONTROL		(OMAP1510_FPGA_BASE + 0x20c)
-#define INNOVATOR_FPGA_EXP_CONTROL		(OMAP1510_FPGA_BASE + 0x20d)
-#define INNOVATOR_FPGA_ISR2			(OMAP1510_FPGA_BASE + 0x20e)
-#define INNOVATOR_FPGA_IMR2			(OMAP1510_FPGA_BASE + 0x210)
-
-#define OMAP1510_FPGA_ETHR_START		(OMAP1510_FPGA_START + 0x300)
-#define OMAP1510_FPGA_ETHR_BASE			(OMAP1510_FPGA_BASE + 0x300)
-
-/*
- * Power up Giga UART driver, turn on HID clock.
- * Turn off BT power, since we're not using it and it
- * draws power.
- */
-#define OMAP1510_FPGA_RESET_VALUE		0x42
-
-#define OMAP1510_FPGA_PCR_IF_PD0		(1 << 7)
-#define OMAP1510_FPGA_PCR_COM2_EN		(1 << 6)
-#define OMAP1510_FPGA_PCR_COM1_EN		(1 << 5)
-#define OMAP1510_FPGA_PCR_EXP_PD0		(1 << 4)
-#define OMAP1510_FPGA_PCR_EXP_PD1		(1 << 3)
-#define OMAP1510_FPGA_PCR_48MHZ_CLK		(1 << 2)
-#define OMAP1510_FPGA_PCR_4MHZ_CLK		(1 << 1)
-#define OMAP1510_FPGA_PCR_RSRVD_BIT0		(1 << 0)
-
-/*
- * Innovator/OMAP1510 FPGA HID register bit definitions
- */
-#define FPGA_HID_SCLK	(1<<0)	/* output */
-#define FPGA_HID_MOSI	(1<<1)	/* output */
-#define FPGA_HID_nSS	(1<<2)	/* output 0/1 chip idle/select */
-#define FPGA_HID_nHSUS	(1<<3)	/* output 0/1 host active/suspended */
-#define FPGA_HID_MISO	(1<<4)	/* input */
-#define FPGA_HID_ATN	(1<<5)	/* input  0/1 chip idle/ATN */
-#define FPGA_HID_rsrvd	(1<<6)
-#define FPGA_HID_RESETn (1<<7)	/* output - 0/1 USAR reset/run */
-
 #ifndef OMAP_SDRAM_DEVICE
 #define OMAP_SDRAM_DEVICE			D256M_1X16_4B
 #endif
@@ -147,37 +61,8 @@
 #define OMAP_FLASH_1_START	0x01000000
 #define OMAP_FLASH_1_SIZE	SZ_16M
 
-/* The FPGA IRQ is cascaded through GPIO_13 */
-#define INT_FPGA		(IH_GPIO_BASE + 13)
-
-/* IRQ Numbers for interrupts muxed through the FPGA */
-#define IH_FPGA_BASE		IH_BOARD_BASE
-#define INT_FPGA_ATN		(IH_FPGA_BASE + 0)
-#define INT_FPGA_ACK		(IH_FPGA_BASE + 1)
-#define INT_FPGA2		(IH_FPGA_BASE + 2)
-#define INT_FPGA3		(IH_FPGA_BASE + 3)
-#define INT_FPGA4		(IH_FPGA_BASE + 4)
-#define INT_FPGA5		(IH_FPGA_BASE + 5)
-#define INT_FPGA6		(IH_FPGA_BASE + 6)
-#define INT_FPGA7		(IH_FPGA_BASE + 7)
-#define INT_FPGA8		(IH_FPGA_BASE + 8)
-#define INT_FPGA9		(IH_FPGA_BASE + 9)
-#define INT_FPGA10		(IH_FPGA_BASE + 10)
-#define INT_FPGA11		(IH_FPGA_BASE + 11)
-#define INT_FPGA12		(IH_FPGA_BASE + 12)
-#define INT_ETHER		(IH_FPGA_BASE + 13)
-#define INT_FPGAUART1		(IH_FPGA_BASE + 14)
-#define INT_FPGAUART2		(IH_FPGA_BASE + 15)
-#define INT_FPGA_TS		(IH_FPGA_BASE + 16)
-#define INT_FPGA17		(IH_FPGA_BASE + 17)
-#define INT_FPGA_CAM		(IH_FPGA_BASE + 18)
-#define INT_FPGA_RTC_A		(IH_FPGA_BASE + 19)
-#define INT_FPGA_RTC_B		(IH_FPGA_BASE + 20)
-#define INT_FPGA_CD		(IH_FPGA_BASE + 21)
-#define INT_FPGA22		(IH_FPGA_BASE + 22)
-#define INT_FPGA23		(IH_FPGA_BASE + 23)
-
-#define NR_FPGA_IRQS		 24
+#define NR_FPGA_IRQS		24
+#define NR_IRQS                 IH_BOARD_BASE + NR_FPGA_IRQS
 
 #ifndef __ASSEMBLY__
 void fpga_write(unsigned char val, int reg);
diff --git a/include/asm-arm/arch-omap/board-perseus2.h b/include/asm-arm/arch-omap/board-perseus2.h
index 4839c4451..0c224cc74 100644
--- a/include/asm-arm/arch-omap/board-perseus2.h
+++ b/include/asm-arm/arch-omap/board-perseus2.h
@@ -2,8 +2,7 @@
  *  linux/include/asm-arm/arch-omap/board-perseus2.h
  *
  *  Copyright 2003 by Texas Instruments Incorporated
- *    OMAP730 / P2-sample additions
- *    Author: Jean Pihet
+ *    OMAP730 / Perseus2 support by Jean Pihet
  *
  * Copyright (C) 2001 RidgeRun, Inc. (http://www.ridgerun.com)
  * Author: RidgeRun, Inc.
@@ -28,46 +27,10 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-#ifndef __ASM_ARCH_OMAP_P2SAMPLE_H
-#define __ASM_ARCH_OMAP_P2SAMPLE_H
+#ifndef __ASM_ARCH_OMAP_PERSEUS2_H
+#define __ASM_ARCH_OMAP_PERSEUS2_H
 
-#if defined(CONFIG_ARCH_OMAP730) && defined (CONFIG_MACH_OMAP_PERSEUS2)
-
-/*
- * NOTE:  ALL DEFINITIONS IN THIS FILE NEED TO BE PREFIXED BY IDENTIFIER
- *	  P2SAMPLE_ since they are specific to the EVM and not the chip.
- */
-
-/* ---------------------------------------------------------------------------
- *  OMAP730 Debug Board FPGA
- * ---------------------------------------------------------------------------
- */
-
-/* maps in the FPGA registers and the ETHR registers */
-#define OMAP730_FPGA_BASE		0xE8000000	/* VA */
-#define OMAP730_FPGA_SIZE		SZ_4K		/* SIZE */
-#define OMAP730_FPGA_START		0x04000000	/* PA */
-
-#define OMAP730_FPGA_ETHR_START		OMAP730_FPGA_START
-#define OMAP730_FPGA_ETHR_BASE		OMAP730_FPGA_BASE
-#define OMAP730_FPGA_FPGA_REV		(OMAP730_FPGA_BASE + 0x10)	/* FPGA Revision */
-#define OMAP730_FPGA_BOARD_REV		(OMAP730_FPGA_BASE + 0x12)	/* Board Revision */
-#define OMAP730_FPGA_GPIO		(OMAP730_FPGA_BASE + 0x14)	/* GPIO outputs */
-#define OMAP730_FPGA_LEDS		(OMAP730_FPGA_BASE + 0x16)	/* LEDs outputs */
-#define OMAP730_FPGA_MISC_INPUTS	(OMAP730_FPGA_BASE + 0x18)	/* Misc inputs */
-#define OMAP730_FPGA_LAN_STATUS		(OMAP730_FPGA_BASE + 0x1A)	/* LAN Status line */
-#define OMAP730_FPGA_LAN_RESET		(OMAP730_FPGA_BASE + 0x1C)	/* LAN Reset line */
-
-// LEDs definition on debug board (16 LEDs)
-#define OMAP730_FPGA_LED_CLAIMRELEASE	(1 << 15)
-#define OMAP730_FPGA_LED_STARTSTOP	(1 << 14)
-#define OMAP730_FPGA_LED_HALTED		(1 << 13)
-#define OMAP730_FPGA_LED_IDLE		(1 << 12)
-#define OMAP730_FPGA_LED_TIMER		(1 << 11)
-// cpu0 load-meter LEDs
-#define OMAP730_FPGA_LOAD_METER		(1 << 0)	// A bit of fun on our board ...
-#define OMAP730_FPGA_LOAD_METER_SIZE	11
-#define OMAP730_FPGA_LOAD_METER_MASK	((1 << OMAP730_FPGA_LOAD_METER_SIZE) - 1)
+#include <asm/arch/fpga.h>
 
 #ifndef OMAP_SDRAM_DEVICE
 #define OMAP_SDRAM_DEVICE		D256M_1X16_4B
@@ -86,22 +49,10 @@
 #define OMAP_FLASH_0_START	0x00000000	/* PA */
 #define OMAP_FLASH_0_SIZE	SZ_32M
 
-/* The Ethernet Controller IRQ is cascaded to MPU_EXT_nIRQ througb the FPGA */
-#define INT_ETHER		INT_730_MPU_EXT_NIRQ
-
 #define MAXIRQNUM		IH_BOARD_BASE
 #define MAXFIQNUM		MAXIRQNUM
 #define MAXSWINUM		MAXIRQNUM
 
 #define NR_IRQS			(MAXIRQNUM + 1)
 
-#ifndef __ASSEMBLY__
-void fpga_write(unsigned char val, int reg);
-unsigned char fpga_read(int reg);
-#endif
-
-#else
-#error "Only OMAP730 Perseus2 supported!"
-#endif
-
 #endif
diff --git a/include/asm-arm/arch-omap/board.h b/include/asm-arm/arch-omap/board.h
index fe21fc817..a24193510 100644
--- a/include/asm-arm/arch-omap/board.h
+++ b/include/asm-arm/arch-omap/board.h
@@ -17,32 +17,69 @@
 #define OMAP_TAG_CLOCK		0x4f01
 #define OMAP_TAG_MMC		0x4f02
 #define OMAP_TAG_UART		0x4f03
+#define OMAP_TAG_USB            0x4f04
 
-struct omap_clock_info {
+struct omap_clock_config {
 	/* 0 for 12 MHz, 1 for 13 MHz and 2 for 19.2 MHz */
 	u8 system_clock_type;
 };
 
-struct omap_mmc_info {
+struct omap_mmc_config {
 	u8 mmc_blocks;
 	s8 mmc1_power_pin, mmc2_power_pin;
 	s8 mmc1_switch_pin, mmc2_switch_pin;
 };
 
-struct omap_uart_info {
+struct omap_uart_config {
 	u8 console_uart;
 	u32 console_speed;
 };
 
-struct omap_board_info_entry {
+struct omap_usb_config {
+	/* Configure drivers according to the connectors on your board:
+	 *  - "A" connector (rectagular)
+	 *	... for host/OHCI use, set "register_host".
+	 *  - "B" connector (squarish) or "Mini-B"
+	 *	... for device/gadget use, set "register_dev".
+	 *  - "Mini-AB" connector (very similar to Mini-B)
+	 *	... for OTG use as device OR host, initialize "otg"
+	 */
+	unsigned	register_host:1;
+	unsigned	register_dev:1;
+	u8		otg;	/* port number, 1-based:  usb1 == 2 */
+
+	u8		hmc_mode;
+
+	/* implicitly true if otg:  host supports remote wakeup? */
+	u8		rwc;
+
+	/* signaling pins used to talk to transceiver on usbN:
+	 *  0 == usbN unused
+	 *  2 == usb0-only, using internal transceiver
+	 *  3 == 3 wire bidirectional
+	 *  4 == 4 wire bidirectional
+	 *  6 == 6 wire unidirectional (or TLL)
+	 */
+	u8		pins[3];
+};
+
+struct omap_board_config_entry {
 	u16 tag;
 	u16 len;
 	u8  data[0];
 };
 
-extern const void *__omap_get_per_info(u16 tag, size_t len);
+struct omap_board_config_kernel {
+	u16 tag;
+	const void *data;
+};
+
+extern const void *__omap_get_config(u16 tag, size_t len);
+
+#define omap_get_config(tag, type) \
+	((const type *) __omap_get_config((tag), sizeof(type)))
 
-#define omap_get_per_info(tag, type) \
-	((const type *) __omap_get_per_info((tag), sizeof(type)))
+extern struct omap_board_config_kernel *omap_board_config;
+extern int omap_board_config_size;
 
 #endif
diff --git a/include/asm-arm/arch-omap/fpga.h b/include/asm-arm/arch-omap/fpga.h
index 565a87f17..dc9f61a43 100644
--- a/include/asm-arm/arch-omap/fpga.h
+++ b/include/asm-arm/arch-omap/fpga.h
@@ -19,8 +19,161 @@
 #ifndef __ASM_ARCH_OMAP_FPGA_H
 #define __ASM_ARCH_OMAP_FPGA_H
 
-extern void fpga_init_irq(void);
-extern unsigned char fpga_read(int reg);
-extern void fpga_write(unsigned char val, int reg);
+#if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP1510)
+extern void omap1510_fpga_init_irq(void);
+#else
+#define omap1510_fpga_init_irq()	(0)
+#endif
+
+#define fpga_read(reg)			__raw_readb(reg)
+#define fpga_write(val, reg)		__raw_writeb(val, reg)
+
+/*
+ * ---------------------------------------------------------------------------
+ *  H2/P2 Debug board FPGA
+ * ---------------------------------------------------------------------------
+ */
+/* maps in the FPGA registers and the ETHR registers */
+#define H2P2_DBG_FPGA_BASE		0xE8000000	/* VA */
+#define H2P2_DBG_FPGA_SIZE		SZ_4K		/* SIZE */
+#define H2P2_DBG_FPGA_START		0x04000000	/* PA */
+
+#define H2P2_DBG_FPGA_ETHR_START	H2P2_DBG_FPGA_START
+#define H2P2_DBG_FPGA_ETHR_BASE		H2P2_DBG_FPGA_BASE
+#define H2P2_DBG_FPGA_FPGA_REV		(H2P2_DBG_FPGA_BASE + 0x10)	/* FPGA Revision */
+#define H2P2_DBG_FPGA_BOARD_REV		(H2P2_DBG_FPGA_BASE + 0x12)	/* Board Revision */
+#define H2P2_DBG_FPGA_GPIO		(H2P2_DBG_FPGA_BASE + 0x14)	/* GPIO outputs */
+#define H2P2_DBG_FPGA_LEDS		(H2P2_DBG_FPGA_BASE + 0x16)	/* LEDs outputs */
+#define H2P2_DBG_FPGA_MISC_INPUTS	(H2P2_DBG_FPGA_BASE + 0x18)	/* Misc inputs */
+#define H2P2_DBG_FPGA_LAN_STATUS	(H2P2_DBG_FPGA_BASE + 0x1A)	/* LAN Status line */
+#define H2P2_DBG_FPGA_LAN_RESET		(H2P2_DBG_FPGA_BASE + 0x1C)	/* LAN Reset line */
+
+/* LEDs definition on debug board (16 LEDs) */
+#define H2P2_DBG_FPGA_LED_CLAIMRELEASE	(1 << 15)
+#define H2P2_DBG_FPGA_LED_STARTSTOP	(1 << 14)
+#define H2P2_DBG_FPGA_LED_HALTED	(1 << 13)
+#define H2P2_DBG_FPGA_LED_IDLE		(1 << 12)
+#define H2P2_DBG_FPGA_LED_TIMER		(1 << 11)
+/*  cpu0 load-meter LEDs */
+#define H2P2_DBG_FPGA_LOAD_METER	(1 << 0)	// A bit of fun on our board ...
+#define H2P2_DBG_FPGA_LOAD_METER_SIZE	11
+#define H2P2_DBG_FPGA_LOAD_METER_MASK	((1 << H2P2_DBG_FPGA_LOAD_METER_SIZE) - 1)
+
+
+/*
+ * ---------------------------------------------------------------------------
+ *  OMAP-1510 FPGA
+ * ---------------------------------------------------------------------------
+ */
+#define OMAP1510_FPGA_BASE			0xE8000000	/* Virtual */
+#define OMAP1510_FPGA_SIZE			SZ_4K
+#define OMAP1510_FPGA_START			0x08000000	/* Physical */
+
+/* Revision */
+#define OMAP1510_FPGA_REV_LOW			(OMAP1510_FPGA_BASE + 0x0)
+#define OMAP1510_FPGA_REV_HIGH			(OMAP1510_FPGA_BASE + 0x1)
+
+#define OMAP1510_FPGA_LCD_PANEL_CONTROL		(OMAP1510_FPGA_BASE + 0x2)
+#define OMAP1510_FPGA_LED_DIGIT			(OMAP1510_FPGA_BASE + 0x3)
+#define INNOVATOR_FPGA_HID_SPI			(OMAP1510_FPGA_BASE + 0x4)
+#define OMAP1510_FPGA_POWER			(OMAP1510_FPGA_BASE + 0x5)
+
+/* Interrupt status */
+#define OMAP1510_FPGA_ISR_LO			(OMAP1510_FPGA_BASE + 0x6)
+#define OMAP1510_FPGA_ISR_HI			(OMAP1510_FPGA_BASE + 0x7)
+
+/* Interrupt mask */
+#define OMAP1510_FPGA_IMR_LO			(OMAP1510_FPGA_BASE + 0x8)
+#define OMAP1510_FPGA_IMR_HI			(OMAP1510_FPGA_BASE + 0x9)
+
+/* Reset registers */
+#define OMAP1510_FPGA_HOST_RESET		(OMAP1510_FPGA_BASE + 0xa)
+#define OMAP1510_FPGA_RST			(OMAP1510_FPGA_BASE + 0xb)
+
+#define OMAP1510_FPGA_AUDIO			(OMAP1510_FPGA_BASE + 0xc)
+#define OMAP1510_FPGA_DIP			(OMAP1510_FPGA_BASE + 0xe)
+#define OMAP1510_FPGA_FPGA_IO			(OMAP1510_FPGA_BASE + 0xf)
+#define OMAP1510_FPGA_UART1			(OMAP1510_FPGA_BASE + 0x14)
+#define OMAP1510_FPGA_UART2			(OMAP1510_FPGA_BASE + 0x15)
+#define OMAP1510_FPGA_OMAP1510_STATUS		(OMAP1510_FPGA_BASE + 0x16)
+#define OMAP1510_FPGA_BOARD_REV			(OMAP1510_FPGA_BASE + 0x18)
+#define OMAP1510P1_PPT_DATA			(OMAP1510_FPGA_BASE + 0x100)
+#define OMAP1510P1_PPT_STATUS			(OMAP1510_FPGA_BASE + 0x101)
+#define OMAP1510P1_PPT_CONTROL			(OMAP1510_FPGA_BASE + 0x102)
+
+#define OMAP1510_FPGA_TOUCHSCREEN		(OMAP1510_FPGA_BASE + 0x204)
+
+#define INNOVATOR_FPGA_INFO			(OMAP1510_FPGA_BASE + 0x205)
+#define INNOVATOR_FPGA_LCD_BRIGHT_LO		(OMAP1510_FPGA_BASE + 0x206)
+#define INNOVATOR_FPGA_LCD_BRIGHT_HI		(OMAP1510_FPGA_BASE + 0x207)
+#define INNOVATOR_FPGA_LED_GRN_LO		(OMAP1510_FPGA_BASE + 0x208)
+#define INNOVATOR_FPGA_LED_GRN_HI		(OMAP1510_FPGA_BASE + 0x209)
+#define INNOVATOR_FPGA_LED_RED_LO		(OMAP1510_FPGA_BASE + 0x20a)
+#define INNOVATOR_FPGA_LED_RED_HI		(OMAP1510_FPGA_BASE + 0x20b)
+#define INNOVATOR_FPGA_CAM_USB_CONTROL		(OMAP1510_FPGA_BASE + 0x20c)
+#define INNOVATOR_FPGA_EXP_CONTROL		(OMAP1510_FPGA_BASE + 0x20d)
+#define INNOVATOR_FPGA_ISR2			(OMAP1510_FPGA_BASE + 0x20e)
+#define INNOVATOR_FPGA_IMR2			(OMAP1510_FPGA_BASE + 0x210)
+
+#define OMAP1510_FPGA_ETHR_START		(OMAP1510_FPGA_START + 0x300)
+#define OMAP1510_FPGA_ETHR_BASE			(OMAP1510_FPGA_BASE + 0x300)
+
+/*
+ * Power up Giga UART driver, turn on HID clock.
+ * Turn off BT power, since we're not using it and it
+ * draws power.
+ */
+#define OMAP1510_FPGA_RESET_VALUE		0x42
+
+#define OMAP1510_FPGA_PCR_IF_PD0		(1 << 7)
+#define OMAP1510_FPGA_PCR_COM2_EN		(1 << 6)
+#define OMAP1510_FPGA_PCR_COM1_EN		(1 << 5)
+#define OMAP1510_FPGA_PCR_EXP_PD0		(1 << 4)
+#define OMAP1510_FPGA_PCR_EXP_PD1		(1 << 3)
+#define OMAP1510_FPGA_PCR_48MHZ_CLK		(1 << 2)
+#define OMAP1510_FPGA_PCR_4MHZ_CLK		(1 << 1)
+#define OMAP1510_FPGA_PCR_RSRVD_BIT0		(1 << 0)
+
+/*
+ * Innovator/OMAP1510 FPGA HID register bit definitions
+ */
+#define OMAP1510_FPGA_HID_SCLK	(1<<0)	/* output */
+#define OMAP1510_FPGA_HID_MOSI	(1<<1)	/* output */
+#define OMAP1510_FPGA_HID_nSS	(1<<2)	/* output 0/1 chip idle/select */
+#define OMAP1510_FPGA_HID_nHSUS	(1<<3)	/* output 0/1 host active/suspended */
+#define OMAP1510_FPGA_HID_MISO	(1<<4)	/* input */
+#define OMAP1510_FPGA_HID_ATN	(1<<5)	/* input  0/1 chip idle/ATN */
+#define OMAP1510_FPGA_HID_rsrvd	(1<<6)
+#define OMAP1510_FPGA_HID_RESETn (1<<7)	/* output - 0/1 USAR reset/run */
+
+/* The FPGA IRQ is cascaded through GPIO_13 */
+#define OMAP1510_INT_FPGA		(IH_GPIO_BASE + 13)
+
+/* IRQ Numbers for interrupts muxed through the FPGA */
+#define OMAP1510_IH_FPGA_BASE		IH_BOARD_BASE
+#define OMAP1510_INT_FPGA_ATN		(OMAP1510_IH_FPGA_BASE + 0)
+#define OMAP1510_INT_FPGA_ACK		(OMAP1510_IH_FPGA_BASE + 1)
+#define OMAP1510_INT_FPGA2		(OMAP1510_IH_FPGA_BASE + 2)
+#define OMAP1510_INT_FPGA3		(OMAP1510_IH_FPGA_BASE + 3)
+#define OMAP1510_INT_FPGA4		(OMAP1510_IH_FPGA_BASE + 4)
+#define OMAP1510_INT_FPGA5		(OMAP1510_IH_FPGA_BASE + 5)
+#define OMAP1510_INT_FPGA6		(OMAP1510_IH_FPGA_BASE + 6)
+#define OMAP1510_INT_FPGA7		(OMAP1510_IH_FPGA_BASE + 7)
+#define OMAP1510_INT_FPGA8		(OMAP1510_IH_FPGA_BASE + 8)
+#define OMAP1510_INT_FPGA9		(OMAP1510_IH_FPGA_BASE + 9)
+#define OMAP1510_INT_FPGA10		(OMAP1510_IH_FPGA_BASE + 10)
+#define OMAP1510_INT_FPGA11		(OMAP1510_IH_FPGA_BASE + 11)
+#define OMAP1510_INT_FPGA12		(OMAP1510_IH_FPGA_BASE + 12)
+#define OMAP1510_INT_ETHER		(OMAP1510_IH_FPGA_BASE + 13)
+#define OMAP1510_INT_FPGAUART1		(OMAP1510_IH_FPGA_BASE + 14)
+#define OMAP1510_INT_FPGAUART2		(OMAP1510_IH_FPGA_BASE + 15)
+#define OMAP1510_INT_FPGA_TS		(OMAP1510_IH_FPGA_BASE + 16)
+#define OMAP1510_INT_FPGA17		(OMAP1510_IH_FPGA_BASE + 17)
+#define OMAP1510_INT_FPGA_CAM		(OMAP1510_IH_FPGA_BASE + 18)
+#define OMAP1510_INT_FPGA_RTC_A		(OMAP1510_IH_FPGA_BASE + 19)
+#define OMAP1510_INT_FPGA_RTC_B		(OMAP1510_IH_FPGA_BASE + 20)
+#define OMAP1510_INT_FPGA_CD		(OMAP1510_IH_FPGA_BASE + 21)
+#define OMAP1510_INT_FPGA22		(OMAP1510_IH_FPGA_BASE + 22)
+#define OMAP1510_INT_FPGA23		(OMAP1510_IH_FPGA_BASE + 23)
 
 #endif
diff --git a/include/asm-arm/arch-omap/hardware.h b/include/asm-arm/arch-omap/hardware.h
index 348072bc4..fe0286912 100644
--- a/include/asm-arm/arch-omap/hardware.h
+++ b/include/asm-arm/arch-omap/hardware.h
@@ -178,6 +178,7 @@
 #define IRQ_CONTROL_REG_OFFSET	0x18
 #define IRQ_ISR_REG_OFFSET	0x9c
 #define IRQ_ILR0_REG_OFFSET	0x1c
+#define IRQ_GMR_REG_OFFSET	0xa0
 
 /*
  * ---------------------------------------------------------------------------
@@ -185,22 +186,23 @@
  * ---------------------------------------------------------------------------
  */
 #define TCMIF_BASE		0xfffecc00
-#define IMIF_PRIO		(TCMIF_BASE + 0x00)
-#define EMIFS_PRIO		(TCMIF_BASE + 0x04)
-#define EMIFF_PRIO		(TCMIF_BASE + 0x08)
-#define EMIFS_CONFIG		(TCMIF_BASE + 0x0c)
-#define EMIFS_CS0_CONFIG	(TCMIF_BASE + 0x10)
-#define EMIFS_CS1_CONFIG	(TCMIF_BASE + 0x14)
-#define EMIFS_CS2_CONFIG	(TCMIF_BASE + 0x18)
-#define EMIFS_CS3_CONFIG	(TCMIF_BASE + 0x1c)
-#define EMIFF_SDRAM_CONFIG	(TCMIF_BASE + 0x20)
-#define EMIFF_MRS		(TCMIF_BASE + 0x24)
-#define TC_TIMEOUT1		(TCMIF_BASE + 0x28)
-#define TC_TIMEOUT2		(TCMIF_BASE + 0x2c)
-#define TC_TIMEOUT3		(TCMIF_BASE + 0x30)
-#define TC_ENDIANISM		(TCMIF_BASE + 0x34)
-#define EMIFF_SDRAM_CONFIG_2	(TCMIF_BASE + 0x3c)
-#define EMIF_CFG_DYNAMIC_WS	(TCMIF_BASE + 0x40)
+#define IMIF_PRIO_REG		__REG32(TCMIF_BASE + 0x00)
+#define EMIFS_PRIO_REG		__REG32(TCMIF_BASE + 0x04)
+#define EMIFF_PRIO_REG		__REG32(TCMIF_BASE + 0x08)
+#define EMIFS_CONFIG_REG	__REG32(TCMIF_BASE + 0x0c)
+#define EMIFS_CS0_CONFIG_REG	__REG32(TCMIF_BASE + 0x10)
+#define EMIFS_CS1_CONFIG_REG	__REG32(TCMIF_BASE + 0x14)
+#define EMIFS_CS2_CONFIG_REG	__REG32(TCMIF_BASE + 0x18)
+#define EMIFS_CS3_CONFIG_REG	__REG32(TCMIF_BASE + 0x1c)
+#define EMIFF_SDRAM_CONFIG_REG	__REG32(TCMIF_BASE + 0x20)
+#define EMIFF_MRS_REG		__REG32(TCMIF_BASE + 0x24)
+#define TC_TIMEOUT1_REG		__REG32(TCMIF_BASE + 0x28)
+#define TC_TIMEOUT2_REG		__REG32(TCMIF_BASE + 0x2c)
+#define TC_TIMEOUT3_REG		__REG32(TCMIF_BASE + 0x30)
+#define TC_ENDIANISM_REG	__REG32(TCMIF_BASE + 0x34)
+#define EMIFF_SDRAM_CONFIG_2_REG __REG32(TCMIF_BASE + 0x3c)
+#define EMIF_CFG_DYNAMIC_WS_REG	__REG32(TCMIF_BASE + 0x40)
+
 /*
  * ----------------------------------------------------------------------------
  * System control registers
@@ -290,6 +292,7 @@
 #define OMAP_ID_1610		0x3576
 #define OMAP_ID_1710		0x35F7
 #define OMAP_ID_5912		0x358C
+#define OMAP_ID_1611            0x358C
 
 #ifdef CONFIG_ARCH_OMAP730
 #include "omap730.h"
@@ -307,12 +310,16 @@
 
 #ifdef CONFIG_ARCH_OMAP1610
 #include "omap1610.h"
-#define cpu_is_omap1710()       (((OMAP_ID_REG >> ID_SHIFT) & ID_MASK) == OMAP_ID_1710)
-/* Detect 1710 as 1610 for now */
-#define cpu_is_omap1610()	(((OMAP_ID_REG >> ID_SHIFT) & ID_MASK) == OMAP_ID_1610 \
-				|| cpu_is_omap1710())
+#define cpu_is_omap1610()	(((OMAP_ID_REG >> ID_SHIFT) & ID_MASK) == OMAP_ID_1610) || \
+				(((OMAP_ID_REG >> ID_SHIFT) & ID_MASK) == OMAP_ID_1611)
 #else
 #define cpu_is_omap1610()	0
+#endif
+
+#ifdef CONFIG_ARCH_OMAP1710
+#include "omap1610.h"
+#define cpu_is_omap1710()       (((OMAP_ID_REG >> ID_SHIFT) & ID_MASK) == OMAP_ID_1710)
+#else
 #define cpu_is_omap1710()	0
 #endif
 
@@ -343,7 +350,6 @@
 
 #ifdef CONFIG_MACH_OMAP_H3
 #include "board-h3.h"
-#error "Support for H3 board not yet implemented."
 #endif
 
 #ifdef CONFIG_MACH_OMAP_H4
diff --git a/include/asm-arm/arch-omap/memory.h b/include/asm-arm/arch-omap/memory.h
index 4f9e8c842..c93c05288 100644
--- a/include/asm-arm/arch-omap/memory.h
+++ b/include/asm-arm/arch-omap/memory.h
@@ -64,7 +64,7 @@
 
 #define virt_to_lbus(x)		((x) - PAGE_OFFSET + OMAP1510_LB_OFFSET)
 #define lbus_to_virt(x)		((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)
-#define is_lbus_device(dev)	(cpu_is_omap1510() && dev->coherent_dma_mask == 0x0fffffff)
+#define is_lbus_device(dev)	(cpu_is_omap1510() && dev && dev->coherent_dma_mask == 0x0fffffff)
 
 #define __arch_page_to_dma(dev, page)	({is_lbus_device(dev) ? \
 					(dma_addr_t)virt_to_lbus(page_address(page)) : \
diff --git a/include/asm-arm/arch-omap/mux.h b/include/asm-arm/arch-omap/mux.h
index 405395706..d0fdf9833 100644
--- a/include/asm-arm/arch-omap/mux.h
+++ b/include/asm-arm/arch-omap/mux.h
@@ -135,6 +135,10 @@ typedef enum {
 	UART3_CLKREQ,
 	UART3_BCLK,	/* 12MHz clock out */
 
+	/* PWT & PWL */
+	PWT,
+	PWL,
+
 	/* USB master generic */
 	R18_USB_VBUS,
 	R18_1510_USB_GPIO0,
@@ -154,6 +158,7 @@ typedef enum {
 	USB1_RCV,
 	USB1_SPEED,
 	R13_1610_USB1_SPEED,
+	R13_1710_USB1_SE0,
 
 	/* USB2 master */
 	USB2_SUSP,
@@ -169,6 +174,10 @@ typedef enum {
 	R19_1510_GPIO1,
 	M14_1510_GPIO2,
 
+	/* OMAP-1710 GPIO */
+	R18_1710_GPIO0,
+	W15_1710_GPIO40,
+
 	/* MPUIO */
 	MPUIO2,
 	MPUIO4,
@@ -225,6 +234,7 @@ typedef enum {
 	P10_1610_GPIO22,
 	V5_1610_GPIO24,
 	AA20_1610_GPIO_41,
+	W19_1610_GPIO48,
 
 	/* OMAP-1610 uWire */
 	V19_1610_UWIRE_SCLK,
@@ -242,6 +252,11 @@ typedef enum {
 	MMC_CLK,
 	MMC_DAT3,
 
+	/* OMAP-1710 MMC CMDDIR and DATDIR0 */
+	M15_1710_MMC_CLKI,
+	P19_1710_MMC_CMDDIR,
+	P20_1710_MMC_DATDIR0,
+
 	/* OMAP-1610 USB0 alternate pin configuration */
 	W9_USB0_TXEN,
 	AA9_USB0_VP,
@@ -317,6 +332,10 @@ MUX_CFG("UART3_RTS",		 5,   15,    2,	  0,  25,   0,	 NA,	 0,  0)
 MUX_CFG("UART3_CLKREQ",		 9,   27,    0,	  2,   5,   0,	 NA,	 0,  0)
 MUX_CFG("UART3_BCLK",		 A,    0,    0,	  2,   6,   0,	 NA,	 0,  0)
 
+/* PWT & PWL, conflicts with UART3 */
+MUX_CFG("PWT",		 	 6,    0,    2,	  0,  30,   0,	 NA,	 0,  0)
+MUX_CFG("PWL",		 	 6,    3,    1,	  0,  31,   1,	 NA,	 0,  0)
+
 /* USB internal master generic */
 MUX_CFG("R18_USB_VBUS",		 7,    9,    2,	  1,  11,   0,	 NA,	 0,  1)
 MUX_CFG("R18_1510_USB_GPIO0",	 7,    9,    0,	  1,  11,   1,	 NA,	 0,  1)
@@ -336,6 +355,7 @@ MUX_CFG("USB1_VM",		 A,    6,    1,	  2,   8,   0,	 NA,	 0,  1)
 MUX_CFG("USB1_RCV",		 A,    9,    1,	  2,   9,   0,	 NA,	 0,  1)
 MUX_CFG("USB1_SPEED",		 A,   12,    2,	  2,  10,   0,	 NA,	 0,  1)
 MUX_CFG("R13_1610_USB1_SPEED",	 A,   12,    5,	  2,  10,   0,	 NA,	 0,  1)
+MUX_CFG("R13_1710_USB1_SEO",	 A,   12,    5,   2,  10,   0,   NA,     0,  1)
 
 /* USB2 master */
 MUX_CFG("USB2_SUSP",		 B,    3,    1,	  2,  17,   0,	 NA,	 0,  1)
@@ -347,9 +367,13 @@ MUX_CFG("USB2_SE0",		 C,   24,    2,	  3,   2,   0,	 NA,	 0,  1)
 MUX_CFG("USB2_TXD",		 C,   27,    2,	  3,   3,   0,	 NA,	 0,  1)
 
 /* OMAP-1510 GPIO */
-MUX_CFG("R18_1510_GPIO0",	 7,    9,   0,	  1,  11,   1,	  0,	 0,  1)
-MUX_CFG("R19_1510_GPIO1",	 7,    6,   0,	  1,  10,   1,	  0,	 0,  1)
-MUX_CFG("M14_1510_GPIO2",	 7,    3,   0,	  1,   9,   1,	  0,	 0,  1)
+MUX_CFG("R18_1510_GPIO0",	 7,    9,    0,   1,  11,   1,    0,     0,  1)
+MUX_CFG("R19_1510_GPIO1",	 7,    6,    0,   1,  10,   1,    0,     0,  1)
+MUX_CFG("M14_1510_GPIO2",	 7,    3,    0,   1,   9,   1,    0,     0,  1)
+
+/* OMAP-1710 GPIO */
+MUX_CFG("R18_1710_GPIO0",	 7,    9,    0,   1,  11,   1,    1,     1,  1)
+MUX_CFG("W15_1710_GPIO40",	 9,   27,    7,   2,   5,   1,    2,     1,  1)
 
 /* MPUIO */
 MUX_CFG("MPUIO2",		 7,   18,    0,	  1,   1,   1,	 NA,	 0,  1)
@@ -408,6 +432,7 @@ MUX_CFG("N19_1610_GPIO13",	 6,   12,    0,	  1,   2,   0,	  1,	 1,  1)
 MUX_CFG("P10_1610_GPIO22",	 C,    0,    7,	  2,  26,   0,	  2,	 1,  1)
 MUX_CFG("V5_1610_GPIO24",	 B,   15,    7,	  2,  21,   0,	  2,	 1,  1)
 MUX_CFG("AA20_1610_GPIO_41",	 9,    9,    7,	  1,  31,   0,	  1,	 1,  1)
+MUX_CFG("W19_1610_GPIO48",	 8,   15,    7,   1,  23,   1,    1,     0,  1)
 
 /* OMAP-1610 uWire */
 MUX_CFG("V19_1610_UWIRE_SCLK",	 8,    6,    0,	  1,  20,   0,	  1,	 1,  1)
@@ -417,13 +442,16 @@ MUX_CFG("N14_1610_UWIRE_CS0",	 8,    9,    1,	  1,  21,   0,	  1,	 1,  1)
 MUX_CFG("P15_1610_UWIRE_CS3",	 8,   12,    1,	  1,  22,   0,	  1,	 1,  1)
 MUX_CFG("N15_1610_UWIRE_CS1",	 7,   18,    2,	  1,  14,   0,	 NA,	 0,  1)
 
-/* First MMC interface, same on 1510 and 1610 */
+/* First MMC interface, same on 1510, 1610 and 1710 */
 MUX_CFG("MMC_CMD",		 A,   27,    0,	  2,  15,   1,	  2,	 1,  1)
 MUX_CFG("MMC_DAT1",		 A,   24,    0,	  2,  14,   1,	  2,	 1,  1)
 MUX_CFG("MMC_DAT2",		 A,   18,    0,	  2,  12,   1,	  2,	 1,  1)
 MUX_CFG("MMC_DAT0",		 B,    0,    0,	  2,  16,   1,	  2,	 1,  1)
 MUX_CFG("MMC_CLK",		 A,   21,    0,	 NA,   0,   0,	 NA,	 0,  1)
 MUX_CFG("MMC_DAT3",		10,   15,    0,	  3,   8,   1,	  3,	 1,  1)
+MUX_CFG("M15_1710_MMC_CLKI",	 6,   21,    2,   0,   0,   0,   NA,     0,  1)
+MUX_CFG("P19_1710_MMC_CMDDIR",	 6,   24,    6,   0,   0,   0,   NA,     0,  1)
+MUX_CFG("P20_1710_MMC_DATDIR0",	 6,   27,    5,   0,   0,   0,   NA,     0,  1)
 
 /* OMAP-1610 USB0 alternate configuration */
 MUX_CFG("W9_USB0_TXEN",		 B,   9,     5,	  2,  19,   0,	  2,	 0,  1)
diff --git a/include/asm-arm/arch-omap/omap1510.h b/include/asm-arm/arch-omap/omap1510.h
index b13584662..f491a48ef 100644
--- a/include/asm-arm/arch-omap/omap1510.h
+++ b/include/asm-arm/arch-omap/omap1510.h
@@ -40,16 +40,6 @@
 #define OMAP1510_SRAM_SIZE	(SZ_128K + SZ_64K)
 #define OMAP1510_SRAM_START	0x20000000
 
-#define OMAP1510_MCBSP1_BASE	0xE1011000
-#define OMAP1510_MCBSP1_SIZE	SZ_4K
-#define OMAP1510_MCBSP1_START	0xE1011000
-
-#define OMAP1510_MCBSP2_BASE	0xFFFB1000
-
-#define OMAP1510_MCBSP3_BASE	0xE1017000
-#define OMAP1510_MCBSP3_SIZE	SZ_4K
-#define OMAP1510_MCBSP3_START	0xE1017000
-
 #define OMAP1510_DSP_BASE	0xE0000000
 #define OMAP1510_DSP_SIZE	0x28000
 #define OMAP1510_DSP_START	0xE0000000
@@ -58,5 +48,14 @@
 #define OMAP1510_DSPREG_SIZE	SZ_128K
 #define OMAP1510_DSPREG_START	0xE1000000
 
+/*
+ * ----------------------------------------------------------------------------
+ * Memory used by power management
+ * ----------------------------------------------------------------------------
+ */
+
+#define OMAP1510_SRAM_IDLE_SUSPEND	(OMAP1510_SRAM_BASE + OMAP1510_SRAM_SIZE - 0x200)
+#define OMAP1510_SRAM_API_SUSPEND	(OMAP1510_SRAM_IDLE_SUSPEND + 0x100)
+
 #endif /*  __ASM_ARCH_OMAP1510_H */
 
diff --git a/include/asm-arm/arch-omap/omap1610.h b/include/asm-arm/arch-omap/omap1610.h
index 667a6f697..6b36752f4 100644
--- a/include/asm-arm/arch-omap/omap1610.h
+++ b/include/asm-arm/arch-omap/omap1610.h
@@ -48,6 +48,15 @@
 #define OMAP1610_DSPREG_SIZE	SZ_128K
 #define OMAP1610_DSPREG_START	0xE1000000
 
+/*
+ * ----------------------------------------------------------------------------
+ * Memory used by power management
+ * ----------------------------------------------------------------------------
+ */
+
+#define OMAP1610_SRAM_IDLE_SUSPEND	(OMAP1610_SRAM_BASE + OMAP1610_SRAM_SIZE - 0x200)
+#define OMAP1610_SRAM_API_SUSPEND	(OMAP1610_SRAM_IDLE_SUSPEND + 0x100)
+
 /*
  * ---------------------------------------------------------------------------
  * Interrupts
diff --git a/include/asm-arm/arch-omap/omap5912.h b/include/asm-arm/arch-omap/omap5912.h
index f996af7c1..76b554ee0 100644
--- a/include/asm-arm/arch-omap/omap5912.h
+++ b/include/asm-arm/arch-omap/omap5912.h
@@ -49,6 +49,15 @@
 #define OMAP5912_DSPREG_SIZE	SZ_128K
 #define OMAP5912_DSPREG_START	0xE1000000
 
+/*
+ * ----------------------------------------------------------------------------
+ * Memory used by power management
+ * ----------------------------------------------------------------------------
+ */
+
+#define OMAP5912_SRAM_IDLE_SUSPEND	(OMAP5912_SRAM_BASE + OMAP5912_SRAM_SIZE - 0x200)
+#define OMAP5912_SRAM_API_SUSPEND	(OMAP5912_SRAM_IDLE_SUSPEND + 0x100)
+
 /*
  * ---------------------------------------------------------------------------
  * Interrupts
diff --git a/include/asm-arm/arch-omap/omap730.h b/include/asm-arm/arch-omap/omap730.h
index 8ca763687..599ab00f5 100644
--- a/include/asm-arm/arch-omap/omap730.h
+++ b/include/asm-arm/arch-omap/omap730.h
@@ -40,12 +40,6 @@
 #define OMAP730_SRAM_SIZE	(SZ_128K + SZ_64K + SZ_8K)
 #define OMAP730_SRAM_START	0x20000000
 
-#define OMAP730_MCBSP1_BASE	0xfffb1000
-#define OMAP730_MCBSP1_SIZE	(SZ_1K * 2)
-#define OMAP730_MCBSP1_START	0xfffb1000
-
-#define OMAP730_MCBSP2_BASE	0xfffb1800
-
 #define OMAP730_DSP_BASE	0xE0000000
 #define OMAP730_DSP_SIZE	0x50000
 #define OMAP730_DSP_START	0xE0000000
diff --git a/include/asm-arm/arch-omap/uncompress.h b/include/asm-arm/arch-omap/uncompress.h
index 9b287366d..7da2d6e4c 100644
--- a/include/asm-arm/arch-omap/uncompress.h
+++ b/include/asm-arm/arch-omap/uncompress.h
@@ -28,7 +28,7 @@
 #define omap_get_id() ((*(volatile unsigned int *)(0xfffed404)) >> 12) & ID_MASK
 
 static void
-puts(const char *s)
+putstr(const char *s)
 {
 	volatile u8 * uart = 0;
 	int shift = 0;
diff --git a/include/asm-arm/arch-pxa/dma.h b/include/asm-arm/arch-pxa/dma.h
index df4bc6628..56db3d49b 100644
--- a/include/asm-arm/arch-pxa/dma.h
+++ b/include/asm-arm/arch-pxa/dma.h
@@ -22,7 +22,7 @@
  * Note: this structure must always be aligned to a 16-byte boundary.
  */
 
-typedef struct {
+typedef struct pxa_dma_desc {
 	volatile u32 ddadr;	/* Points to the next descriptor + flags */
 	volatile u32 dsadr;	/* DSADR value for the current transfer */
 	volatile u32 dtadr;	/* DTADR value for the current transfer */
diff --git a/include/asm-arm/arch-pxa/hardware.h b/include/asm-arm/arch-pxa/hardware.h
index 127fc1af1..72b04d846 100644
--- a/include/asm-arm/arch-pxa/hardware.h
+++ b/include/asm-arm/arch-pxa/hardware.h
@@ -59,10 +59,9 @@ typedef struct { volatile u32 offset[4096]; } __regbase;
 # define __REG(x)	__REGP(io_p2v(x))
 #endif
 
-/* Let's kick gcc's ass again... */
-# define __REG2(x,y)	\
-	( __builtin_constant_p(y) ? (__REG((x) + (y))) \
-				  : (*(volatile u32 *)((u32)&__REG(x) + (y))) )
+/* With indexed regs we don't want to feed the index through io_p2v()
+   especially if it is a variable, otherwise horrible code will result. */
+# define __REG2(x,y)     (*(volatile u32 *)((u32)&__REG(x) + (y)))
 
 # define __PREG(x)	(io_v2p((u32)&(x)))
 
@@ -73,8 +72,6 @@ typedef struct { volatile u32 offset[4096]; } __regbase;
 
 #endif
 
-#include "pxa-regs.h"
-
 #ifndef __ASSEMBLY__
 
 /*
diff --git a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h
index 29164556b..3d9b92a46 100644
--- a/include/asm-arm/arch-pxa/irqs.h
+++ b/include/asm-arm/arch-pxa/irqs.h
@@ -12,19 +12,34 @@
 
 #include <linux/config.h>
 
-#define PXA_IRQ_SKIP	7	/* The first 7 IRQs are not yet used */
+#ifdef CONFIG_PXA27x
+#define PXA_IRQ_SKIP	0
+#else
+#define PXA_IRQ_SKIP	7
+#endif
+
 #define PXA_IRQ(x)	((x) - PXA_IRQ_SKIP)
 
-#define IRQ_HWUART	PXA_IRQ(7)	/* HWUART Transmit/Receive/Error */
+#define IRQ_SSP3	PXA_IRQ(0)	/* SSP3 service request */
+#define IRQ_MSL		PXA_IRQ(1)	/* MSL Interface interrupt */
+#define IRQ_USBH2	PXA_IRQ(2)	/* USB Host interrupt 1 (OHCI) */
+#define IRQ_USBH1	PXA_IRQ(3)	/* USB Host interrupt 2 (non-OHCI) */
+#define IRQ_KEYPAD	PXA_IRQ(4)	/* Key pad controller */
+#define IRQ_MEMSTK	PXA_IRQ(5)	/* Memory Stick interrupt */
+#define IRQ_PWRI2C	PXA_IRQ(6)	/* Power I2C interrupt */
+#define IRQ_HWUART	PXA_IRQ(7)	/* HWUART Transmit/Receive/Error (PXA26x) */
+#define IRQ_OST_4_11	PXA_IRQ(7)	/* OS timer 4-11 matches (PXA27x) */
 #define	IRQ_GPIO0	PXA_IRQ(8)	/* GPIO0 Edge Detect */
 #define	IRQ_GPIO1	PXA_IRQ(9)	/* GPIO1 Edge Detect */
-#define	IRQ_GPIO_2_80	PXA_IRQ(10)	/* GPIO[2-80] Edge Detect */
+#define	IRQ_GPIO_2_x	PXA_IRQ(10)	/* GPIO[2-x] Edge Detect */
 #define	IRQ_USB		PXA_IRQ(11)	/* USB Service */
 #define	IRQ_PMU		PXA_IRQ(12)	/* Performance Monitoring Unit */
 #define	IRQ_I2S		PXA_IRQ(13)	/* I2S Interrupt */
 #define	IRQ_AC97	PXA_IRQ(14)	/* AC97 Interrupt */
-#define IRQ_ASSP	PXA_IRQ(15)	/* Audio SSP Service Request */
-#define IRQ_NSSP	PXA_IRQ(16)	/* Network SSP Service Request */
+#define IRQ_ASSP	PXA_IRQ(15)	/* Audio SSP Service Request (PXA25x) */
+#define IRQ_USIM	PXA_IRQ(15)     /* Smart Card interface interrupt (PXA27x) */
+#define IRQ_NSSP	PXA_IRQ(16)	/* Network SSP Service Request (PXA25x) */
+#define IRQ_SSP2	PXA_IRQ(16)	/* SSP2 interrupt (PXA27x) */
 #define	IRQ_LCD		PXA_IRQ(17)	/* LCD Controller Service Request */
 #define	IRQ_I2C		PXA_IRQ(18)	/* I2C Service Request */
 #define	IRQ_ICP		PXA_IRQ(19)	/* ICP Transmit/Receive/Error */
@@ -41,13 +56,28 @@
 #define	IRQ_RTC1Hz	PXA_IRQ(30)	/* RTC HZ Clock Tick */
 #define	IRQ_RTCAlrm	PXA_IRQ(31)	/* RTC Alarm */
 
-#define GPIO_2_80_TO_IRQ(x)	\
-			PXA_IRQ((x) - 2 + 32)
-#define IRQ_GPIO(x)	(((x) < 2) ? (IRQ_GPIO0 + (x)) : GPIO_2_80_TO_IRQ(x))
+#ifdef CONFIG_PXA27x
+#define IRQ_TPM		PXA_IRQ(32)	/* TPM interrupt */
+#define IRQ_CAMERA	PXA_IRQ(33)	/* Camera Interface */
 
-#define IRQ_TO_GPIO_2_80(i)	\
-			((i) - PXA_IRQ(32) + 2)
-#define IRQ_TO_GPIO(i)	((i) - (((i) > IRQ_GPIO1) ? IRQ_GPIO(2) - 2 : IRQ_GPIO(0)))
+#define PXA_INTERNAL_IRQS 34
+#else
+#define PXA_INTERNAL_IRQS 32
+#endif
+
+#define GPIO_2_x_TO_IRQ(x)	\
+			PXA_IRQ((x) - 2 + PXA_INTERNAL_IRQS)
+#define IRQ_GPIO(x)	(((x) < 2) ? (IRQ_GPIO0 + (x)) : GPIO_2_x_TO_IRQ(x))
+
+#define IRQ_TO_GPIO_2_x(i)	\
+			((i) - IRQ_GPIO(2) + 2)
+#define IRQ_TO_GPIO(i)	(((i) < IRQ_GPIO(2)) ? ((i) - IRQ_GPIO0) : IRQ_TO_GPIO_2_x(i))
+
+#if defined(CONFIG_PXA25x)
+#define PXA_LAST_GPIO	80
+#elif defined(CONFIG_PXA27x)
+#define PXA_LAST_GPIO	127
+#endif
 
 /*
  * The next 16 interrupts are for board specific purposes.  Since
@@ -55,7 +85,7 @@
  * these.  If you need more, increase IRQ_BOARD_END, but keep it
  * within sensible limits.
  */
-#define IRQ_BOARD_START		(IRQ_GPIO(80) + 1)
+#define IRQ_BOARD_START		(IRQ_GPIO(PXA_LAST_GPIO) + 1)
 #define IRQ_BOARD_END		(IRQ_BOARD_START + 16)
 
 #define IRQ_SA1111_START	(IRQ_BOARD_END)
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index d0f64e3f7..4ff0d00e1 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -15,17 +15,6 @@
 
 #include <linux/config.h>
 
-// FIXME hack so that SA-1111.h will work [cb]
-
-#ifndef __ASSEMBLY__
-typedef unsigned short  Word16 ;
-typedef unsigned int    Word32 ;
-typedef Word32          Word ;
-typedef Word            Quad [4] ;
-typedef void            *Address ;
-typedef void            (*ExcpHndlr) (void) ;
-#endif
-
 /*
  * PXA Chip selects
  */
@@ -962,7 +951,7 @@ typedef void            (*ExcpHndlr) (void) ;
 #define ICCR0_LBM	(1 << 1)	/* Loopback mode */
 #define ICCR0_ITR	(1 << 0)	/* IrDA transmission */
 
-#ifdef CONFIG_CPU_BULVERDE
+#ifdef CONFIG_PXA27x
 #define ICCR2_RXP       (1 << 3)	/* Receive Pin Polarity select */
 #define ICCR2_TXP       (1 << 2)	/* Transmit Pin Polarity select */
 #define ICCR2_TRIG	(3 << 0)	/* Receive FIFO Trigger threshold */
@@ -971,7 +960,7 @@ typedef void            (*ExcpHndlr) (void) ;
 #define ICCR2_TRIG_32   (2 << 0)	/*	>= 32 bytes */
 #endif
 
-#ifdef CONFIG_CPU_BULVERDE
+#ifdef CONFIG_PXA27x
 #define ICSR0_EOC	(1 << 6)	/* DMA End of Descriptor Chain */
 #endif
 #define ICSR0_FRE	(1 << 5)	/* Framing error */
@@ -1134,15 +1123,15 @@ typedef void            (*ExcpHndlr) (void) ;
 #define _GEDR(x)	__REG2(0x40E00048, ((x) & 0x60) >> 3)
 #define _GAFR(x)	__REG2(0x40E00054, ((x) & 0x70) >> 2)
 
-#define GPLR(x) 	((((x) & 0x7f) < 96) ? _GPLR(x) : GPLR3)
-#define GPDR(x)		((((x) & 0x7f) < 96) ? _GPDR(x) : GPDR3)
-#define GPSR(x)		((((x) & 0x7f) < 96) ? _GPSR(x) : GPSR3)
-#define GPCR(x)		((((x) & 0x7f) < 96) ? _GPCR(x) : GPCR3)
-#define GRER(x)		((((x) & 0x7f) < 96) ? _GRER(x) : GRER3)
-#define GFER(x)		((((x) & 0x7f) < 96) ? _GFER(x) : GFER3)
-#define GEDR(x)		((((x) & 0x7f) < 96) ? _GEDR(x) : GEDR3)
-#define GAFR(x)		((((x) & 0x7f) < 96) ? _GAFR(x) : \
-			 ((((x) & 0x7f) < 112) ? GAFR3_L : GAFR3_U))
+#define GPLR(x) 	(*((((x) & 0x7f) < 96) ? &_GPLR(x) : &GPLR3))
+#define GPDR(x)		(*((((x) & 0x7f) < 96) ? &_GPDR(x) : &GPDR3))
+#define GPSR(x)		(*((((x) & 0x7f) < 96) ? &_GPSR(x) : &GPSR3))
+#define GPCR(x)		(*((((x) & 0x7f) < 96) ? &_GPCR(x) : &GPCR3))
+#define GRER(x)		(*((((x) & 0x7f) < 96) ? &_GRER(x) : &GRER3))
+#define GFER(x)		(*((((x) & 0x7f) < 96) ? &_GFER(x) : &GFER3))
+#define GEDR(x)		(*((((x) & 0x7f) < 96) ? &_GEDR(x) : &GEDR3))
+#define GAFR(x)		(*((((x) & 0x7f) < 96) ? &_GAFR(x) : \
+			 ((((x) & 0x7f) < 112) ? &GAFR3_L : &GAFR3_U)))
 #else
 
 #define GPLR(x)		__REG2(0x40E00000, ((x) & 0x60) >> 3)
@@ -1185,6 +1174,7 @@ typedef void            (*ExcpHndlr) (void) ;
 #define GPIO30_SDATA_OUT	30	/* AC97/I2S Sdata_out */
 #define GPIO31_SYNC		31	/* AC97/I2S sync */
 #define GPIO32_SDATA_IN1	32	/* AC97 Sdata_in1 */
+#define GPIO32_MMCCLK		32	/* MMC Clock (PXA270) */
 #define GPIO33_nCS_5		33	/* chip select 5 */
 #define GPIO34_FFRXD		34	/* FFUART receive */
 #define GPIO34_MMCCS0		34	/* MMC Chip Select 0 */
@@ -1213,6 +1203,7 @@ typedef void            (*ExcpHndlr) (void) ;
 #define GPIO53_MMCCLK		53	/* MMC Clock */
 #define GPIO54_MMCCLK		54	/* MMC Clock */
 #define GPIO54_pSKTSEL		54	/* Socket Select for Card Space */
+#define GPIO54_nPCE_2		54	/* Card Enable for Card Space (PXA27x) */
 #define GPIO55_nPREG		55	/* Card Address bit 26 */
 #define GPIO56_nPWAIT		56	/* Wait signal for Card Space */
 #define GPIO57_nIOIS16		57	/* Bus Width select for I/O Card Space */
@@ -1247,6 +1238,15 @@ typedef void            (*ExcpHndlr) (void) ;
 #define GPIO78_nCS_2		78	/* chip select 2 */
 #define GPIO79_nCS_3		79	/* chip select 3 */
 #define GPIO80_nCS_4		80	/* chip select 4 */
+#define GPIO85_nPCE_1		85	/* Card Enable for Card Space (PXA27x) */
+#define GPIO92_MMCDAT0		92	/* MMC DAT0 (PXA27x) */
+#define GPIO109_MMCDAT1		109	/* MMC DAT1 (PXA27x) */
+#define GPIO110_MMCDAT2		110	/* MMC DAT2 (PXA27x) */
+#define GPIO110_MMCCS0		110	/* MMC Chip Select 0 (PXA27x) */
+#define GPIO111_MMCDAT3		111	/* MMC DAT3 (PXA27x) */
+#define GPIO111_MMCCS1		111	/* MMC Chip Select 1 (PXA27x) */
+#define GPIO112_MMCCMD		112	/* MMC CMD (PXA27x) */
+#define GPIO113_AC97_RESET_N	113	/* AC97 NRESET on (PXA27x) */
 
 /* GPIO alternate function mode & direction */
 
@@ -1292,6 +1292,7 @@ typedef void            (*ExcpHndlr) (void) ;
 #define GPIO31_SYNC_AC97_MD	(31 | GPIO_ALT_FN_2_OUT)
 #define GPIO31_SYNC_I2S_MD	(31 | GPIO_ALT_FN_1_OUT)
 #define GPIO32_SDATA_IN1_AC97_MD	(32 | GPIO_ALT_FN_1_IN)
+#define GPIO32_MMCCLK_MD		( 32 | GPIO_ALT_FN_2_OUT)
 #define GPIO33_nCS_5_MD		(33 | GPIO_ALT_FN_2_OUT)
 #define GPIO34_FFRXD_MD		(34 | GPIO_ALT_FN_1_IN)
 #define GPIO34_MMCCS0_MD	(34 | GPIO_ALT_FN_2_OUT)
@@ -1319,6 +1320,7 @@ typedef void            (*ExcpHndlr) (void) ;
 #define GPIO53_nPCE_2_MD	(53 | GPIO_ALT_FN_2_OUT)
 #define GPIO53_MMCCLK_MD	(53 | GPIO_ALT_FN_1_OUT)
 #define GPIO54_MMCCLK_MD	(54 | GPIO_ALT_FN_1_OUT)
+#define GPIO54_nPCE_2_MD	(54 | GPIO_ALT_FN_2_OUT)
 #define GPIO54_pSKTSEL_MD	(54 | GPIO_ALT_FN_2_OUT)
 #define GPIO55_nPREG_MD		(55 | GPIO_ALT_FN_2_OUT)
 #define GPIO56_nPWAIT_MD	(56 | GPIO_ALT_FN_1_IN)
@@ -1353,7 +1355,17 @@ typedef void            (*ExcpHndlr) (void) ;
 #define GPIO77_LCD_ACBIAS_MD	(77 | GPIO_ALT_FN_2_OUT)
 #define GPIO78_nCS_2_MD		(78 | GPIO_ALT_FN_2_OUT)
 #define GPIO79_nCS_3_MD		(79 | GPIO_ALT_FN_2_OUT)
+#define GPIO79_pSKTSEL_MD	(79 | GPIO_ALT_FN_1_OUT)
 #define GPIO80_nCS_4_MD		(80 | GPIO_ALT_FN_2_OUT)
+#define GPIO85_nPCE_1_MD	(85 | GPIO_ALT_FN_1_OUT)
+#define GPIO92_MMCDAT0_MD	(92 | GPIO_ALT_FN_1_OUT)
+#define GPIO109_MMCDAT1_MD	(109 | GPIO_ALT_FN_1_OUT)
+#define GPIO110_MMCDAT2_MD	(110 | GPIO_ALT_FN_1_OUT)
+#define GPIO110_MMCCS0_MD	(110 | GPIO_ALT_FN_1_OUT)
+#define GPIO111_MMCDAT3_MD	(111 | GPIO_ALT_FN_1_OUT)
+#define GPIO110_MMCCS1_MD	(111 | GPIO_ALT_FN_1_OUT)
+#define GPIO112_MMCCMD_MD	(112 | GPIO_ALT_FN_1_OUT)
+#define GPIO113_AC97_RESET_N_MD	(113 | GPIO_ALT_FN_2_OUT)
 
 
 /*
diff --git a/include/asm-arm/arch-pxa/serial.h b/include/asm-arm/arch-pxa/serial.h
index 3ef5d802b..1d06b3b23 100644
--- a/include/asm-arm/arch-pxa/serial.h
+++ b/include/asm-arm/arch-pxa/serial.h
@@ -9,6 +9,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <asm/arch/pxa-regs.h>
 
 #define BAUD_BASE	921600
 
diff --git a/include/asm-arm/arch-pxa/system.h b/include/asm-arm/arch-pxa/system.h
index 8d4664404..840a46bfb 100644
--- a/include/asm-arm/arch-pxa/system.h
+++ b/include/asm-arm/arch-pxa/system.h
@@ -11,6 +11,7 @@
  */
 
 #include "hardware.h"
+#include "pxa-regs.h"
 
 static inline void arch_idle(void)
 {
diff --git a/include/asm-arm/arch-pxa/uncompress.h b/include/asm-arm/arch-pxa/uncompress.h
index c4b906dc8..4428d3eb7 100644
--- a/include/asm-arm/arch-pxa/uncompress.h
+++ b/include/asm-arm/arch-pxa/uncompress.h
@@ -25,7 +25,7 @@ static __inline__ void putc(char c)
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	while (*s) {
 		putc(*s);
diff --git a/include/asm-arm/arch-rpc/io.h b/include/asm-arm/arch-rpc/io.h
index 3f7a2366c..939aa6a60 100644
--- a/include/asm-arm/arch-rpc/io.h
+++ b/include/asm-arm/arch-rpc/io.h
@@ -22,40 +22,40 @@
  */
 #define __arch_base_getb(b,o)			\
  ({						\
-	unsigned int v, r = (b);		\
+	unsigned int __v, __r = (b);		\
 	__asm__ __volatile__(			\
 		"ldrb	%0, [%1, %2]"		\
-		: "=r" (v)			\
-		: "r" (r), "Ir" (o));		\
-	v;					\
+		: "=r" (__v)			\
+		: "r" (__r), "Ir" (o));		\
+	__v;					\
  })
 
 #define __arch_base_getl(b,o)			\
  ({						\
-	unsigned int v, r = (b);		\
+	unsigned int __v, __r = (b);		\
 	__asm__ __volatile__(			\
 		"ldr	%0, [%1, %2]"		\
-		: "=r" (v)			\
-		: "r" (r), "Ir" (o));		\
-	v;					\
+		: "=r" (__v)			\
+		: "r" (__r), "Ir" (o));		\
+	__v;					\
  })
 
 #define __arch_base_putb(v,b,o)			\
  ({						\
-	unsigned int r = (b);			\
+	unsigned int __r = (b);			\
 	__asm__ __volatile__(			\
 		"strb	%0, [%1, %2]"		\
 		:				\
-		: "r" (v), "r" (r), "Ir" (o));	\
+		: "r" (v), "r" (__r), "Ir" (o));\
  })
 
 #define __arch_base_putl(v,b,o)			\
  ({						\
-	unsigned int r = (b);			\
+	unsigned int __r = (b);			\
 	__asm__ __volatile__(			\
 		"str	%0, [%1, %2]"		\
 		:				\
-		: "r" (v), "r" (r), "Ir" (o));	\
+		: "r" (v), "r" (__r), "Ir" (o));\
  })
 
 /*
@@ -176,15 +176,15 @@ DECLARE_IO(int,l,"")
 
 #define __outwc(value,port)							\
 ({										\
-	unsigned long v = value;						\
+	unsigned long __v = value;						\
 	if (__PORT_PCIO((port)))						\
 		__asm__ __volatile__(						\
 		"str	%0, [%1, %2]	@ outwc"				\
-		: : "r" (v|v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2));	\
+		: : "r" (__v|__v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2));	\
 	else									\
 		__asm__ __volatile__(						\
 		"str	%0, [%1, %2]	@ outwc"				\
-		: : "r" (v|v<<16), "r" (IO_BASE), "r" ((port) << 2));		\
+		: : "r" (__v|__v<<16), "r" (IO_BASE), "r" ((port) << 2));		\
 })
 
 #define __inwc(port)								\
@@ -203,15 +203,15 @@ DECLARE_IO(int,l,"")
 
 #define __outlc(value,port)							\
 ({										\
-	unsigned long v = value;						\
+	unsigned long __v = value;						\
 	if (__PORT_PCIO((port)))						\
 		__asm__ __volatile__(						\
 		"str	%0, [%1, %2]	@ outlc"				\
-		: : "r" (v), "r" (PCIO_BASE), "Jr" ((port) << 2));		\
+		: : "r" (__v), "r" (PCIO_BASE), "Jr" ((port) << 2));		\
 	else									\
 		__asm__ __volatile__(						\
 		"str	%0, [%1, %2]	@ outlc"				\
-		: : "r" (v), "r" (IO_BASE), "r" ((port) << 2));			\
+		: : "r" (__v), "r" (IO_BASE), "r" ((port) << 2));			\
 })
 
 #define __inlc(port)								\
@@ -250,6 +250,6 @@ DECLARE_IO(int,l,"")
 /*
  * 1:1 mapping for ioremapped regions.
  */
-#define __mem_pci(x)	(x)
+#define __mem_pci(x)	((unsigned long)(x))
 
 #endif
diff --git a/include/asm-arm/arch-rpc/uncompress.h b/include/asm-arm/arch-rpc/uncompress.h
index 845db9498..43035fec6 100644
--- a/include/asm-arm/arch-rpc/uncompress.h
+++ b/include/asm-arm/arch-rpc/uncompress.h
@@ -60,14 +60,14 @@ static const unsigned long palette_4[16] = {
  * params_phys is a linker defined symbol - see
  * arch/arm/boot/compressed/Makefile
  */
-extern struct param_struct params_phys;
-#define params (&params_phys)
+extern __attribute__((pure)) struct param_struct *params(void);
+#define params (params())
 
 #ifndef STANDALONE_DEBUG 
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	extern void ll_write_char(char *, char c, char white);
 	int x,y;
diff --git a/include/asm-arm/arch-s3c2410/bast-cpld.h b/include/asm-arm/arch-s3c2410/bast-cpld.h
index cb1430a98..e28ca51a4 100644
--- a/include/asm-arm/arch-s3c2410/bast-cpld.h
+++ b/include/asm-arm/arch-s3c2410/bast-cpld.h
@@ -1,6 +1,6 @@
 /* linux/include/asm-arm/arch-s3c2410/bast-cpld.h
  *
- * (c) 2003 Simtec Electronics
+ * (c) 2003,2004 Simtec Electronics
  *  Ben Dooks <ben@simtec.co.uk>
  *
  * BAST - CPLD control constants
@@ -11,15 +11,48 @@
  *
  * Changelog:
  *  25-May-2003 BJD  Created file, added CTRL1 registers
+ *  30-Aug-2004 BJD  Updated definitions from 2.4.26 port
+ *  30-Aug-2004 BJD  Added CTRL3 and CTRL4 definitions
 */
 
 #ifndef __ASM_ARCH_BASTCPLD_H
 #define __ASM_ARCH_BASTCPLD_H
 
+/* CTRL1 - Audio LR routing */
+
 #define BAST_CPLD_CTRL1_LRCOFF	    (0x00)
 #define BAST_CPLD_CTRL1_LRCADC	    (0x01)
 #define BAST_CPLD_CTRL1_LRCDAC	    (0x02)
 #define BAST_CPLD_CTRL1_LRCARM	    (0x03)
 #define BAST_CPLD_CTRL1_LRMASK	    (0x03)
 
+/* CTRL2 - NAND WP control, IDE Reset assert/check */
+
+#define BAST_CPLD_CTRL2_WNAND       (0x04)
+#define BAST_CPLD_CTLR2_IDERST      (0x08)
+
+/* CTRL3 - rom write control, CPLD identity */
+
+#define BAST_CPLD_CTRL3_IDMASK      (0x0e)
+#define BAST_CPLD_CTRL3_ROMWEN      (0x01)
+
+/* CTRL4 - 8bit LCD interface control/status */
+
+#define BAST_CPLD_CTRL4_LLAT	    (0x01)
+#define BAST_CPLD_CTRL4_LCDRW	    (0x02)
+#define BAST_CPLD_CTRL4_LCDCMD	    (0x04)
+#define BAST_CPLD_CTRL4_LCDE2	    (0x01)
+
+/* CTRL5 - DMA routing */
+
+#define BAST_CPLD_DMA0_PRIIDE      (0<<0)
+#define BAST_CPLD_DMA0_SECIDE      (1<<0)
+#define BAST_CPLD_DMA0_ISA15       (2<<0)
+#define BAST_CPLD_DMA0_ISA36       (3<<0)
+
+#define BAST_CPLD_DMA1_PRIIDE      (0<<2)
+#define BAST_CPLD_DMA1_SECIDE      (1<<2)
+#define BAST_CPLD_DMA1_ISA15       (2<<2)
+#define BAST_CPLD_DMA1_ISA36       (3<<2)
+
 #endif /* __ASM_ARCH_BASTCPLD_H */
diff --git a/include/asm-arm/arch-s3c2410/bast-irq.h b/include/asm-arm/arch-s3c2410/bast-irq.h
index 5d74ca6bb..b79b47f0d 100644
--- a/include/asm-arm/arch-s3c2410/bast-irq.h
+++ b/include/asm-arm/arch-s3c2410/bast-irq.h
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  *
  * Changelog:
+ *  14-Sep-2004 BJD  Fixed IRQ_USBOC definition
  *  06-Jan-2003 BJD  Linux 2.6.0 version
  */
 
@@ -18,7 +19,7 @@
 
 /* irq numbers to onboard peripherals */
 
-#define IRQ_USBOC      IRQ_EINT19
+#define IRQ_USBOC      IRQ_EINT18
 #define IRQ_IDE0       IRQ_EINT16
 #define IRQ_IDE1       IRQ_EINT17
 #define IRQ_PCSERIAL1  IRQ_EINT15
diff --git a/include/asm-arm/arch-s3c2410/dma.h b/include/asm-arm/arch-s3c2410/dma.h
index ea084c784..9cae3822a 100644
--- a/include/asm-arm/arch-s3c2410/dma.h
+++ b/include/asm-arm/arch-s3c2410/dma.h
@@ -27,7 +27,7 @@
  *
  */
 #define MAX_DMA_ADDRESS		0x20000000
-#define MAX_DMA_TRANSFER_SIZE	0x100000 /* Data Unit is half word  */
+#define MAX_DMA_TRANSFER_SIZE   0x100000 /* Data Unit is half word  */
 
 
 /* according to the samsung port, we cannot use the regular
@@ -39,131 +39,282 @@
 
 
 /* we have 4 dma channels */
-#define S3C2410_DMA_CHANNELS	    (4)
+#define S3C2410_DMA_CHANNELS        (4)
 
+/* types */
+
+typedef enum {
+	S3C2410_DMA_IDLE,
+	S3C2410_DMA_RUNNING,
+	S3C2410_DMA_PAUSED
+} s3c2410_dma_state_t;
+
+
+/* s3c2410_dma_loadst_t
+ *
+ * This represents the state of the DMA engine, wrt to the loaded / running
+ * transfers. Since we don't have any way of knowing exactly the state of
+ * the DMA transfers, we need to know the state to make decisions on wether
+ * we can
+ *
+ * S3C2410_DMA_NONE
+ *
+ * There are no buffers loaded (the channel should be inactive)
+ *
+ * S3C2410_DMA_1LOADED
+ *
+ * There is one buffer loaded, however it has not been confirmed to be
+ * loaded by the DMA engine. This may be because the channel is not
+ * yet running, or the DMA driver decided that it was too costly to
+ * sit and wait for it to happen.
+ *
+ * S3C2410_DMA_1RUNNING
+ *
+ * The buffer has been confirmed running, and not finisged
+ *
+ * S3C2410_DMA_1LOADED_1RUNNING
+ *
+ * There is a buffer waiting to be loaded by the DMA engine, and one
+ * currently running.
+*/
+
+typedef enum {
+	S3C2410_DMALOAD_NONE,
+	S3C2410_DMALOAD_1LOADED,
+	S3C2410_DMALOAD_1RUNNING,
+	S3C2410_DMALOAD_1LOADED_1RUNNING,
+} s3c2410_dma_loadst_t;
+
+typedef enum {
+	S3C2410_RES_OK,
+	S3C2410_RES_ERR,
+	S3C2410_RES_ABORT
+} s3c2410_dma_buffresult_t;
+
+
+typedef enum s3c2410_dmasrc_e s3c2410_dmasrc_t;
+
+enum s3c2410_dmasrc_e {
+	S3C2410_DMASRC_HW,      /* source is memory */
+	S3C2410_DMASRC_MEM      /* source is hardware */
+};
+
+/* enum s3c2410_chan_op_e
+ *
+ * operation codes passed to the DMA code by the user, and also used
+ * to inform the current channel owner of any changes to the system state
+*/
+
+enum s3c2410_chan_op_e {
+	S3C2410_DMAOP_START,
+	S3C2410_DMAOP_STOP,
+	S3C2410_DMAOP_PAUSE,
+	S3C2410_DMAOP_RESUME,
+	S3C2410_DMAOP_FLUSH,
+	S3C2410_DMAOP_TIMEOUT,           /* internal signal to handler */
+};
+
+typedef enum s3c2410_chan_op_e s3c2410_chan_op_t;
+
+/* flags */
+
+#define S3C2410_DMAF_SLOW         (1<<0)   /* slow, so don't worry about
+					    * waiting for reloads */
+#define S3C2410_DMAF_AUTOSTART    (1<<1)   /* auto-start if buffer queued */
 
 /* dma buffer */
 
 typedef struct s3c2410_dma_buf_s s3c2410_dma_buf_t;
 
+struct s3c2410_dma_client {
+	char                *name;
+};
+
+typedef struct s3c2410_dma_client s3c2410_dma_client_t;
+
+/* s3c2410_dma_buf_s
+ *
+ * internally used buffer structure to describe a queued or running
+ * buffer.
+*/
+
 struct s3c2410_dma_buf_s {
 	s3c2410_dma_buf_t   *next;
-	int		     magic;	   /* magic */
-	int		     size;	   /* buffer size in bytes */
-	dma_addr_t	     data;	   /* start of DMA data */
-	dma_addr_t	     ptr;	   /* where the DMA got to [1] */
-	int		     ref;
-	void		     *id;	   /* client's id */
-	unsigned char	     no_callback;  /* disable callback for buffer */
+	int                  magic;        /* magic */
+	int                  size;         /* buffer size in bytes */
+	dma_addr_t           data;         /* start of DMA data */
+	dma_addr_t           ptr;          /* where the DMA got to [1] */
+	void                *id;           /* client's id */
 };
 
 /* [1] is this updated for both recv/send modes? */
 
 typedef struct s3c2410_dma_chan_s s3c2410_dma_chan_t;
 
-typedef void (*s3c2410_dma_cbfn_t)(s3c2410_dma_chan_t *, void *buf, int size);
-typedef void (*s3c2410_dma_enfn_t)(s3c2410_dma_chan_t *, int on);
-typedef void (*s3c2410_dma_pausefn_t)(s3c2410_dma_chan_t *, int on);
+/* s3c2410_dma_cbfn_t
+ *
+ * buffer callback routine type
+*/
+
+typedef void (*s3c2410_dma_cbfn_t)(s3c2410_dma_chan_t *, void *buf, int size,
+				   s3c2410_dma_buffresult_t result);
+
+typedef int  (*s3c2410_dma_opfn_t)(s3c2410_dma_chan_t *,
+				   s3c2410_chan_op_t );
+
+struct s3c2410_dma_stats_s {
+	unsigned long          loads;
+	unsigned long          timeout_longest;
+	unsigned long          timeout_shortest;
+	unsigned long          timeout_avg;
+	unsigned long          timeout_failed;
+};
+
+typedef struct s3c2410_dma_stats_s s3c2410_dma_stats_t;
+
+/* struct s3c2410_dma_chan_s
+ *
+ * full state information for each DMA channel
+*/
 
 struct s3c2410_dma_chan_s {
-	/* channel state flags */
-	unsigned char	       number;	      /* number of this dma channel */
-	unsigned char	       in_use;	      /* channel allocated */
-	unsigned char	       started;	      /* channel has been started */
-	unsigned char	       stopped;	      /* channel stopped */
-	unsigned char	       sleeping;
-	unsigned char	       xfer_unit;     /* size of an transfer */
-	unsigned char	       irq_claimed;
+	/* channel state flags and information */
+	unsigned char          number;      /* number of this dma channel */
+	unsigned char          in_use;      /* channel allocated */
+	unsigned char          irq_claimed; /* irq claimed for channel */
+	unsigned char          irq_enabled; /* irq enabled for channel */
+	unsigned char          xfer_unit;   /* size of an transfer */
+
+	/* channel state */
+
+	s3c2410_dma_state_t    state;
+	s3c2410_dma_loadst_t   load_state;
+	s3c2410_dma_client_t  *client;
+
+	/* channel configuration */
+	s3c2410_dmasrc_t       source;
+	unsigned long          dev_addr;
+	unsigned long          load_timeout;
+	unsigned int           flags;        /* channel flags */
 
 	/* channel's hardware position and configuration */
-	unsigned long	       regs;	      /* channels registers */
-	unsigned int	       irq;	      /* channel irq */
-	unsigned long	       addr_reg;      /* data address register for buffs */
-	unsigned long	       dcon;	      /* default value of DCON */
+	unsigned long          regs;         /* channels registers */
+	unsigned int           irq;          /* channel irq */
+	unsigned long          addr_reg;     /* data address register */
+	unsigned long          dcon;         /* default value of DCON */
 
-	/* driver handlers for channel */
-	s3c2410_dma_cbfn_t     callback_fn;   /* callback function for buf-done */
-	s3c2410_dma_enfn_t     enable_fn;     /* channel enable function */
-	s3c2410_dma_pausefn_t  pause_fn;      /* channel pause function */
+	/* driver handles */
+	s3c2410_dma_cbfn_t     callback_fn;  /* buffer done callback */
+	s3c2410_dma_opfn_t     op_fn;        /* channel operation callback */
 
-	/* buffer list and information */
-	s3c2410_dma_buf_t      *curr;	      /* current dma buffer */
-	s3c2410_dma_buf_t      *next;	      /* next buffer to load */
-	s3c2410_dma_buf_t      *end;	      /* end of queue */
+	/* stats gathering */
+	s3c2410_dma_stats_t   *stats;
+	s3c2410_dma_stats_t    stats_store;
 
-	int		       queue_count;   /* number of items in queue */
-	int		       loaded_count;  /* number of loaded buffers */
+	/* buffer list and information */
+	s3c2410_dma_buf_t      *curr;        /* current dma buffer */
+	s3c2410_dma_buf_t      *next;        /* next buffer to load */
+	s3c2410_dma_buf_t      *end;         /* end of queue */
 };
 
-/* note, we don't really use dma_deivce_t at the moment */
+/* the currently allocated channel information */
+extern s3c2410_dma_chan_t s3c2410_chans[];
+
+/* note, we don't really use dma_device_t at the moment */
 typedef unsigned long dma_device_t;
 
-typedef enum s3c2410_dmasrc_e s3c2410_dmasrc_t;
+/* functions --------------------------------------------------------------- */
 
-/* these two defines control the source for the dma channel,
- * wether it is from memory or an device
+/* s3c2410_dma_request
+ *
+ * request a dma channel exclusivley
 */
 
-enum s3c2410_dmasrc_e {
-  S3C2410_DMASRC_HW,	  /* source is memory */
-  S3C2410_DMASRC_MEM	  /* source is hardware */
-};
+extern int s3c2410_dma_request(dmach_t channel,
+			       s3c2410_dma_client_t *, void *dev);
+
+
+/* s3c2410_dma_ctrl
+ *
+ * change the state of the dma channel
+*/
+
+extern int s3c2410_dma_ctrl(dmach_t channel, s3c2410_chan_op_t op);
+
+/* s3c2410_dma_setflags
+ *
+ * set the channel's flags to a given state
+*/
 
-/* dma control routines */
+extern int s3c2410_dma_setflags(dmach_t channel,
+				unsigned int flags);
 
-extern int s3c2410_request_dma(dmach_t channel, const char *devid, void *dev);
-extern int s3c2410_free_dma(dmach_t channel);
-extern int s3c2410_dma_flush_all(dmach_t channel);
+/* s3c2410_dma_free
+ *
+ * free the dma channel (will also abort any outstanding operations)
+*/
 
-extern int s3c2410_dma_stop(dmach_t channel);
-extern int s3c2410_dma_resume(dmach_t channel);
+extern int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *);
 
-extern int s3c2410_dma_queue(dmach_t channel, void *id,
-			     dma_addr_t data, int size);
+/* s3c2410_dma_enqueue
+ *
+ * place the given buffer onto the queue of operations for the channel.
+ * The buffer must be allocated from dma coherent memory, or the Dcache/WB
+ * drained before the buffer is given to the DMA system.
+*/
 
-#define s3c2410_dma_queue_buffer s3c2410_dma_queue
+extern int s3c2410_dma_enqueue(dmach_t channel, void *id,
+			       dma_addr_t data, int size);
 
-/* channel configuration */
+/* s3c2410_dma_config
+ *
+ * configure the dma channel
+*/
 
 extern int s3c2410_dma_config(dmach_t channel, int xferunit, int dcon);
 
+/* s3c2410_dma_devconfig
+ *
+ * configure the device we're talking to
+*/
+
 extern int s3c2410_dma_devconfig(int channel, s3c2410_dmasrc_t source,
 				 int hwcfg, unsigned long devaddr);
 
-extern int s3c2410_dma_set_enablefn(dmach_t, s3c2410_dma_enfn_t rtn);
-extern int s3c2410_dma_set_pausefn(dmach_t, s3c2410_dma_pausefn_t rtn);
-extern int s3c2410_dma_set_callbackfn(dmach_t, s3c2410_dma_cbfn_t rtn);
+extern int s3c2410_dma_set_opfn(dmach_t, s3c2410_dma_opfn_t rtn);
+extern int s3c2410_dma_set_buffdone_fn(dmach_t, s3c2410_dma_cbfn_t rtn);
 
-#define s3c2410_dma_set_callback s3c2410_dma_set_callbackfn
+/* DMA Register definitions */
 
-#define S3C2410_DMA_DISRC	(0x00)
-#define S3C2410_DMA_DISRCC	(0x04)
-#define S3C2410_DMA_DIDST	(0x08)
-#define S3C2410_DMA_DIDSTC	(0x0C)
-#define S3C2410_DMA_DCON	(0x10)
-#define S3C2410_DMA_DSTAT	(0x14)
-#define S3C2410_DMA_DCSRC	(0x18)
-#define S3C2410_DMA_DCDST	(0x1C)
-#define S3C2410_DMA_DMASKTRIG	(0x20)
+#define S3C2410_DMA_DISRC       (0x00)
+#define S3C2410_DMA_DISRCC      (0x04)
+#define S3C2410_DMA_DIDST       (0x08)
+#define S3C2410_DMA_DIDSTC      (0x0C)
+#define S3C2410_DMA_DCON        (0x10)
+#define S3C2410_DMA_DSTAT       (0x14)
+#define S3C2410_DMA_DCSRC       (0x18)
+#define S3C2410_DMA_DCDST       (0x1C)
+#define S3C2410_DMA_DMASKTRIG   (0x20)
 
-#define S3C2410_DMASKTRIG_STOP	 (1<<2)
-#define S3C2410_DMASKTRIG_ON	 (1<<1)
+#define S3C2410_DMASKTRIG_STOP   (1<<2)
+#define S3C2410_DMASKTRIG_ON     (1<<1)
 #define S3C2410_DMASKTRIG_SWTRIG (1<<0)
 
-#define S3C2410_DCOM_DEMAND	(0<<31)
+#define S3C2410_DCOM_DEMAND     (0<<31)
 #define S3C2410_DCON_HANDSHAKE  (1<<31)
 #define S3C2410_DCON_SYNC_PCLK  (0<<30)
 #define S3C2410_DCON_SYNC_HCLK  (1<<30)
 
-#define S3C2410_DCON_INTREQ	(1<<29)
+#define S3C2410_DCON_INTREQ     (1<<29)
 
-#define S3C2410_DCON_SRCSHIFT	(24)
+#define S3C2410_DCON_SRCSHIFT   (24)
 
-#define S3C2410_DCON_BYTE	(0<<20)
-#define S3C2410_DCON_HALFWORD	(1<<20)
-#define S3C2410_DCON_WORD	(2<<20)
+#define S3C2410_DCON_BYTE       (0<<20)
+#define S3C2410_DCON_HALFWORD   (1<<20)
+#define S3C2410_DCON_WORD       (2<<20)
 
 #define S3C2410_DCON_AUTORELOAD (0<<22)
-#define S3C2410_DCON_HWTRIG	(1<<23)
+#define S3C2410_DCON_NORELOAD   (1<<22)
+#define S3C2410_DCON_HWTRIG     (1<<23)
 
 #endif /* __ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-s3c2410/hardware.h b/include/asm-arm/arch-s3c2410/hardware.h
index d434d77fe..5b58f2aea 100644
--- a/include/asm-arm/arch-s3c2410/hardware.h
+++ b/include/asm-arm/arch-s3c2410/hardware.h
@@ -14,6 +14,8 @@
  *  06-Jun-2003 BJD  Added CPU frequency settings
  *  03-Sep-2003 BJD  Linux v2.6 support
  *  12-Mar-2004 BJD  Fixed include protection, fixed type of clock vars
+ *  14-Sep-2004 BJD  Added misccr and getpin to gpio
+ *  01-Oct-2004 BJD  Added the new gpio functions
 */
 
 #ifndef __ASM_ARCH_HARDWARE_H
@@ -44,6 +46,35 @@ extern unsigned long s3c2410_fclk;
 
 extern void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function);
 
+extern unsigned int s3c2410_gpio_getcfg(unsigned int pin);
+
+/* s3c2410_gpio_getirq
+ *
+ * turn the given pin number into the corresponding IRQ number
+ *
+ * returns:
+ *	< 0 = no interrupt for this pin
+ *	>=0 = interrupt number for the pin
+*/
+
+extern int s3c2410_gpio_getirq(unsigned int pin);
+
+/* s3c2410_gpio_irqfilter
+ *
+ * set the irq filtering on the given pin
+ *
+ * on = 0 => disable filtering
+ *      1 => enable filtering
+ *
+ * config = S3C2410_EINTFLT_PCLK or S3C2410_EINTFLT_EXTCLK orred with
+ *          width of filter (0 through 63)
+ *
+ *
+*/
+
+extern int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
+				  unsigned int config);
+
 /* s3c2410_gpio_pullup
  *
  * configure the pull-up control on the given pin
@@ -61,6 +92,10 @@ extern void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
 
 extern void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
 
+extern unsigned int s3c2410_gpio_getpin(unsigned int pin);
+
+extern unsigned int s3c2410_modify_misccr(unsigned int clr, unsigned int chg);
+
 #endif /* __ASSEMBLY__ */
 
 #include <asm/sizes.h>
diff --git a/include/asm-arm/arch-s3c2410/param.h b/include/asm-arm/arch-s3c2410/param.h
index 9a5fcde9f..483d3f149 100644
--- a/include/asm-arm/arch-s3c2410/param.h
+++ b/include/asm-arm/arch-s3c2410/param.h
@@ -22,6 +22,6 @@
  * add a software pre-scaler to the evil timer systems.
 */
 
-#define __KERNEL_HZ   200
+#define HZ   200
 
 #endif /* __ASM_ARCH_PARAM_H */
diff --git a/include/asm-arm/arch-s3c2410/regs-clock.h b/include/asm-arm/arch-s3c2410/regs-clock.h
index a82d55cc6..0cc629fe1 100644
--- a/include/asm-arm/arch-s3c2410/regs-clock.h
+++ b/include/asm-arm/arch-s3c2410/regs-clock.h
@@ -1,6 +1,6 @@
 /* linux/include/asm/arch-s3c2410/regs-clock.h
  *
- * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
+ * Copyright (c) 2003,2004 Simtec Electronics <linux@simtec.co.uk>
  *		      http://www.simtec.co.uk/products/SWLINUX/
  *
  * This program is free software; you can redistribute it and/or modify
@@ -10,12 +10,13 @@
  * S3C2410 clock register definitions
  *
  *  Changelog:
- *    19-06-2003     BJD     Created file
- *    12-03-2004     BJD     Updated include protection
+ *    18-Aug-2004 Ben Dooks      Added 2440 definitions
+ *    08-Aug-2004 Herbert Pötzl  Added CLKCON definitions
+ *    19-06-2003  Ben Dooks      Created file
+ *    12-03-2004  Ben Dooks      Updated include protection
+ *    29-Sep-2004 Ben Dooks	 Fixed usage for assembly inclusion
  */
 
-
-
 #ifndef __ASM_ARM_REGS_CLOCK
 #define __ASM_ARM_REGS_CLOCK "$Id: clock.h,v 1.4 2003/04/30 14:50:51 ben Exp $"
 
@@ -30,6 +31,24 @@
 #define S3C2410_CLKSLOW	    S3C2410_CLKREG(0x10)
 #define S3C2410_CLKDIVN	    S3C2410_CLKREG(0x14)
 
+#define S3C2410_CLKCON_IDLE	     (1<<2)
+#define S3C2410_CLKCON_POWER	     (1<<3)
+#define S3C2410_CLKCON_NAND	     (1<<4)
+#define S3C2410_CLKCON_LCDC	     (1<<5)
+#define S3C2410_CLKCON_USBH	     (1<<6)
+#define S3C2410_CLKCON_USBD	     (1<<7)
+#define S3C2410_CLKCON_PWMT	     (1<<8)
+#define S3C2410_CLKCON_SDI	     (1<<9)
+#define S3C2410_CLKCON_UART0	     (1<<10)
+#define S3C2410_CLKCON_UART1	     (1<<11)
+#define S3C2410_CLKCON_UART2	     (1<<12)
+#define S3C2410_CLKCON_GPIO	     (1<<13)
+#define S3C2410_CLKCON_RTC	     (1<<14)
+#define S3C2410_CLKCON_ADC	     (1<<15)
+#define S3C2410_CLKCON_IIC	     (1<<16)
+#define S3C2410_CLKCON_IIS	     (1<<17)
+#define S3C2410_CLKCON_SPI	     (1<<18)
+
 #define S3C2410_PLLCON_MDIVSHIFT     12
 #define S3C2410_PLLCON_PDIVSHIFT     4
 #define S3C2410_PLLCON_SDIVSHIFT     0
@@ -53,6 +72,8 @@
 #define S3C2410_CLKDIVN_PDIVN	     (1<<0)
 #define S3C2410_CLKDIVN_HDIVN	     (1<<1)
 
+#ifndef __ASSEMBLY__
+
 static inline unsigned int
 s3c2410_get_pll(int pllval, int baseclk)
 {
@@ -69,4 +90,31 @@ s3c2410_get_pll(int pllval, int baseclk)
   return (baseclk * (mdiv + 8)) / ((pdiv + 2) << sdiv);
 }
 
+#endif /* __ASSEMBLY__ */
+
+#ifdef CONFIG_CPU_S3C2440
+
+/* extra registers */
+#define S3C2440_CAMDIVN	    S3C2410_CLKREG(0x14)
+
+#define S3C2440_CLKCON_CAMERA        (1<<19)
+#define S3C2440_CLKCON_AC97          (1<<20)
+
+#define S3C2440_CLKDIVN_PDIVN	     (1<<0)
+#define S3C2440_CLKDIVN_HDIVN_MASK   (3<<1)
+#define S3C2440_CLKDIVN_HDIVN_1      (0<<1)
+#define S3C2440_CLKDIVN_HDIVN_2      (1<<1)
+#define S3C2440_CLKDIVN_HDIVN_4_8    (2<<1)
+#define S3C2440_CLKDIVN_HDIVN_3_6    (3<<1)
+#define S3C2440_CLKDIVN_UCLK         (1<<3)
+
+#define S3C2440_CAMDIVN_CAMCLK_MASK  (0xf<<0)
+#define S3C2440_CAMDIVN_CAMCLK_SEL   (1<<4)
+#define S3C2440_CAMDIVN_HCLK3_HALF   (1<<8)
+#define S3C2440_CAMDIVN_HCLK4_HALF   (1<<9)
+#define S3C2440_CAMDIVN_DVSEN        (1<<12)
+
+#endif /* CONFIG_CPU_S3C2440 */
+
+
 #endif /* __ASM_ARM_REGS_CLOCK */
diff --git a/include/asm-arm/arch-s3c2410/regs-gpio.h b/include/asm-arm/arch-s3c2410/regs-gpio.h
index 661cf97ac..05eb11628 100644
--- a/include/asm-arm/arch-s3c2410/regs-gpio.h
+++ b/include/asm-arm/arch-s3c2410/regs-gpio.h
@@ -14,7 +14,8 @@
  *    23-06-2003     BJD     Updated GSTATUS registers
  *    12-03-2004     BJD     Updated include protection
  *    20-07-2004     BJD     Added GPIO pin numbers, added Port A definitions
- */
+ *    04-10-2004     BJD     Fixed number of bugs, added EXT IRQ filter defs
+*/
 
 
 #ifndef __ASM_ARCH_REGS_GPIO_H
@@ -614,34 +615,34 @@
 #define S3C2410_GPG10_OUTP    (0x01 << 20)
 #define S3C2410_GPG10_EINT18  (0x02 << 20)
 
-#define S3C2410_GPG10         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 10)
+#define S3C2410_GPG11         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 11)
 #define S3C2410_GPG11_INP     (0x00 << 22)
 #define S3C2410_GPG11_OUTP    (0x01 << 22)
 #define S3C2410_GPG11_EINT19  (0x02 << 22)
 #define S3C2410_GPG11_TCLK1   (0x03 << 22)
 
-#define S3C2410_GPG10         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 10)
+#define S3C2410_GPG12         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 12)
 #define S3C2410_GPG12_INP     (0x00 << 24)
 #define S3C2410_GPG12_OUTP    (0x01 << 24)
-#define S3C2410_GPG12_EINT18  (0x02 << 24)
+#define S3C2410_GPG12_EINT20  (0x02 << 24)
 #define S3C2410_GPG12_XMON    (0x03 << 24)
 
-#define S3C2410_GPG10         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 10)
+#define S3C2410_GPG13         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 13)
 #define S3C2410_GPG13_INP     (0x00 << 26)
 #define S3C2410_GPG13_OUTP    (0x01 << 26)
-#define S3C2410_GPG13_EINT18  (0x02 << 26)
+#define S3C2410_GPG13_EINT21  (0x02 << 26)
 #define S3C2410_GPG13_nXPON   (0x03 << 26)
 
-#define S3C2410_GPG10         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 10)
+#define S3C2410_GPG14         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 14)
 #define S3C2410_GPG14_INP     (0x00 << 28)
 #define S3C2410_GPG14_OUTP    (0x01 << 28)
-#define S3C2410_GPG14_EINT18  (0x02 << 28)
+#define S3C2410_GPG14_EINT22  (0x02 << 28)
 #define S3C2410_GPG14_YMON    (0x03 << 28)
 
-#define S3C2410_GPG10         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 10)
+#define S3C2410_GPG15         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 15)
 #define S3C2410_GPG15_INP     (0x00 << 30)
 #define S3C2410_GPG15_OUTP    (0x01 << 30)
-#define S3C2410_GPG15_EINT18  (0x02 << 30)
+#define S3C2410_GPG15_EINT23  (0x02 << 30)
 #define S3C2410_GPG15_nYPON   (0x03 << 30)
 
 
@@ -751,6 +752,11 @@
 
 #define S3C2410_MISCCR_nRSTCON	    (1<<16)
 
+#define S3C2410_MISCCR_nEN_SCLK0    (1<<17)
+#define S3C2410_MISCCR_nEN_SCLK1    (1<<18)
+#define S3C2410_MISCCR_nEN_SCLKE    (1<<19)
+#define S3C2410_MISCCR_SDSLEEP	    (7<<17)
+
 /* external interrupt control... */
 /* S3C2410_EXTINT0 -> irq sense control for EINT0..EINT7
  * S3C2410_EXTINT1 -> irq sense control for EINT8..EINT15
@@ -778,6 +784,11 @@
 #define S3C2410_EINFLT2	   S3C2410_GPIOREG(0x9C)
 #define S3C2410_EINFLT3	   S3C2410_GPIOREG(0xA0)
 
+/* values for interrupt filtering */
+#define S3C2410_EINTFLT_PCLK		(0x00)
+#define S3C2410_EINTFLT_EXTCLK		(1<<7)
+#define S3C2410_EINTFLT_WIDTHMSK(x)	((x) & 0x3f)
+
 /* removed EINTxxxx defs from here, not meant for this */
 
 /* GSTATUS have miscellaneous information in them
diff --git a/include/asm-arm/arch-s3c2410/regs-timer.h b/include/asm-arm/arch-s3c2410/regs-timer.h
index 75c5955fd..b5b4aaf3d 100644
--- a/include/asm-arm/arch-s3c2410/regs-timer.h
+++ b/include/asm-arm/arch-s3c2410/regs-timer.h
@@ -29,6 +29,8 @@
 #define S3C2410_TCFG_PRESCALER0_MASK (255<<0)
 #define S3C2410_TCFG_PRESCALER1_MASK (255<<8)
 #define S3C2410_TCFG_PRESCALER1_SHIFT (8)
+#define S3C2410_TCFG_DEADZONE_MASK   (255<<16)
+#define S3C2410_TCFG_DEADZONE_SHIFT  (16)
 
 #define S3C2410_TCFG1_MUX4_DIV2	  (0<<16)
 #define S3C2410_TCFG1_MUX4_DIV4	  (1<<16)
diff --git a/include/asm-arm/arch-s3c2410/uncompress.h b/include/asm-arm/arch-s3c2410/uncompress.h
index ab01f5391..023f22b14 100644
--- a/include/asm-arm/arch-s3c2410/uncompress.h
+++ b/include/asm-arm/arch-s3c2410/uncompress.h
@@ -100,7 +100,7 @@ putc(char ch)
 }
 
 static void
-puts(const char *ptr)
+putstr(const char *ptr)
 {
 	for (; *ptr != '\0'; ptr++) {
 		putc(*ptr);
diff --git a/include/asm-arm/arch-sa1100/uncompress.h b/include/asm-arm/arch-sa1100/uncompress.h
index 42d28b2b3..43453501e 100644
--- a/include/asm-arm/arch-sa1100/uncompress.h
+++ b/include/asm-arm/arch-sa1100/uncompress.h
@@ -17,7 +17,7 @@
 
 #define UART(x)		(*(volatile unsigned long *)(serial_port + (x)))
 
-static void puts( const char *s )
+static void putstr( const char *s )
 {
 	unsigned long serial_port;
 
diff --git a/include/asm-arm/arch-shark/uncompress.h b/include/asm-arm/arch-shark/uncompress.h
index 162a75ab9..910a8e0a0 100644
--- a/include/asm-arm/arch-shark/uncompress.h
+++ b/include/asm-arm/arch-shark/uncompress.h
@@ -21,7 +21,7 @@ static __inline__ void putc(char c)
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	while (*s) {
 		putc(*s);
diff --git a/include/asm-arm/arch-versatile/uncompress.h b/include/asm-arm/arch-versatile/uncompress.h
index 0397911fe..2f57499c7 100644
--- a/include/asm-arm/arch-versatile/uncompress.h
+++ b/include/asm-arm/arch-versatile/uncompress.h
@@ -25,7 +25,7 @@
 /*
  * This does not append a newline
  */
-static void puts(const char *s)
+static void putstr(const char *s)
 {
 	while (*s) {
 		while (AMBA_UART_FR & (1 << 5))
diff --git a/include/asm-arm/atomic.h b/include/asm-arm/atomic.h
index 257d32f09..24208a2da 100644
--- a/include/asm-arm/atomic.h
+++ b/include/asm-arm/atomic.h
@@ -44,21 +44,6 @@ static inline void atomic_set(atomic_t *v, int i)
 	: "cc");
 }
 
-static inline void atomic_add(int i, atomic_t *v)
-{
-	unsigned long tmp, tmp2;
-
-	__asm__ __volatile__("@ atomic_add\n"
-"1:	ldrex	%0, [%2]\n"
-"	add	%0, %0, %3\n"
-"	strex	%1, %0, [%2]\n"
-"	teq	%1, #0\n"
-"	bne	1b"
-	: "=&r" (tmp), "=&r" (tmp2)
-	: "r" (&v->counter), "Ir" (i)
-	: "cc");
-}
-
 static inline int atomic_add_return(int i, atomic_t *v)
 {
 	unsigned long tmp;
@@ -77,21 +62,6 @@ static inline int atomic_add_return(int i, atomic_t *v)
 	return result;
 }
 
-static inline void atomic_sub(int i, atomic_t *v)
-{
-	unsigned long tmp, tmp2;
-
-	__asm__ __volatile__("@ atomic_sub\n"
-"1:	ldrex	%0, [%2]\n"
-"	sub	%0, %0, %3\n"
-"	strex	%1, %0, [%2]\n"
-"	teq	%1, #0\n"
-"	bne	1b"
-	: "=&r" (tmp), "=&r" (tmp2)
-	: "r" (&v->counter), "Ir" (i)
-	: "cc");
-}
-
 static inline int atomic_sub_return(int i, atomic_t *v)
 {
 	unsigned long tmp;
@@ -135,15 +105,6 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
 
 #define atomic_set(v,i)	(((v)->counter) = (i))
 
-static inline void atomic_add(int i, atomic_t *v)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	v->counter += i;
-	local_irq_restore(flags);
-}
-
 static inline int atomic_add_return(int i, atomic_t *v)
 {
 	unsigned long flags;
@@ -157,15 +118,6 @@ static inline int atomic_add_return(int i, atomic_t *v)
 	return val;
 }
 
-static inline void atomic_sub(int i, atomic_t *v)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	v->counter -= i;
-	local_irq_restore(flags);
-}
-
 static inline int atomic_sub_return(int i, atomic_t *v)
 {
 	unsigned long flags;
@@ -190,8 +142,10 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
 
 #endif /* __LINUX_ARM_ARCH__ */
 
-#define atomic_inc(v)		atomic_add(1, v)
-#define atomic_dec(v)		atomic_sub(1, v)
+#define atomic_add(i, v)	(void) atomic_add_return(i, v)
+#define atomic_inc(v)		(void) atomic_add_return(1, v)
+#define atomic_sub(i, v)	(void) atomic_sub_return(i, v)
+#define atomic_dec(v)		(void) atomic_sub_return(1, v)
 
 #define atomic_inc_and_test(v)	(atomic_add_return(1, v) == 0)
 #define atomic_dec_and_test(v)	(atomic_sub_return(1, v) == 0)
diff --git a/include/asm-arm/bitops.h b/include/asm-arm/bitops.h
index 5f1c975e0..994e0aeff 100644
--- a/include/asm-arm/bitops.h
+++ b/include/asm-arm/bitops.h
@@ -345,7 +345,7 @@ static inline unsigned long __ffs(unsigned long word)
 extern __inline__ int generic_fls(int x);
 #define fls(x) \
 	( __builtin_constant_p(x) ? generic_fls(x) : \
-	  ({ int __r; asm("clz%?\t%0, %1" : "=r"(__r) : "r"(x)); 32-__r; }) )
+	  ({ int __r; asm("clz\t%0, %1" : "=r"(__r) : "r"(x) : "cc"); 32-__r; }) )
 #define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
 #define __ffs(x) (ffs(x) - 1)
 #define ffz(x) __ffs( ~(x) )
diff --git a/include/asm-arm/bug.h b/include/asm-arm/bug.h
index a1afde728..5e91b90a8 100644
--- a/include/asm-arm/bug.h
+++ b/include/asm-arm/bug.h
@@ -8,23 +8,15 @@ extern volatile void __bug(const char *file, int line, void *data);
 
 /* give file/line information */
 #define BUG()		__bug(__FILE__, __LINE__, NULL)
-#define PAGE_BUG(page)	__bug(__FILE__, __LINE__, page)
 
 #else
 
-/* these just cause an oops */
+/* this just causes an oops */
 #define BUG()		(*(int *)0 = 0)
-#define PAGE_BUG(page)	(*(int *)0 = 0)
 
 #endif
 
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
index 84d875206..250d09ca5 100644
--- a/include/asm-arm/cacheflush.h
+++ b/include/asm-arm/cacheflush.h
@@ -157,6 +157,7 @@ struct cpu_cache_fns {
 	void (*flush_user_range)(unsigned long, unsigned long, unsigned int);
 
 	void (*coherent_kern_range)(unsigned long, unsigned long);
+	void (*coherent_user_range)(unsigned long, unsigned long);
 	void (*flush_kern_dcache_page)(void *);
 
 	void (*dma_inv_range)(unsigned long, unsigned long);
@@ -175,6 +176,7 @@ extern struct cpu_cache_fns cpu_cache;
 #define __cpuc_flush_user_all		cpu_cache.flush_user_all
 #define __cpuc_flush_user_range		cpu_cache.flush_user_range
 #define __cpuc_coherent_kern_range	cpu_cache.coherent_kern_range
+#define __cpuc_coherent_user_range	cpu_cache.coherent_user_range
 #define __cpuc_flush_dcache_page	cpu_cache.flush_kern_dcache_page
 
 /*
@@ -193,12 +195,14 @@ extern struct cpu_cache_fns cpu_cache;
 #define __cpuc_flush_user_all		__glue(_CACHE,_flush_user_cache_all)
 #define __cpuc_flush_user_range		__glue(_CACHE,_flush_user_cache_range)
 #define __cpuc_coherent_kern_range	__glue(_CACHE,_coherent_kern_range)
+#define __cpuc_coherent_user_range	__glue(_CACHE,_coherent_user_range)
 #define __cpuc_flush_dcache_page	__glue(_CACHE,_flush_kern_dcache_page)
 
 extern void __cpuc_flush_kern_all(void);
 extern void __cpuc_flush_user_all(void);
 extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int);
 extern void __cpuc_coherent_kern_range(unsigned long, unsigned long);
+extern void __cpuc_coherent_user_range(unsigned long, unsigned long);
 extern void __cpuc_flush_dcache_page(void *);
 
 /*
@@ -233,11 +237,17 @@ extern void dmac_flush_range(unsigned long, unsigned long);
  * space" model to handle this.
  */
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-do { memcpy(dst, src, len); \
-     flush_icache_user_range(vma, page, vaddr, len); \
-} while (0)
+	do {					\
+		flush_cache_page(vma, vaddr);	\
+		memcpy(dst, src, len);		\
+		flush_dcache_page(page);	\
+	} while (0)
+
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
+	do {					\
+		flush_cache_page(vma, vaddr);	\
+		memcpy(dst, src, len);		\
+	} while (0)
 
 /*
  * Convert calls to our calling convention.
@@ -267,6 +277,14 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr)
 	}
 }
 
+/*
+ * flush_cache_user_range is used when we want to ensure that the
+ * Harvard caches are synchronised for the user space address range.
+ * This is used for the ARM private sys_cacheflush system call.
+ */
+#define flush_cache_user_range(vma,start,end) \
+	__cpuc_coherent_user_range((start) & PAGE_MASK, PAGE_ALIGN(end))
+
 /*
  * Perform necessary cache operations to ensure that data previously
  * stored within this range of addresses can be executed by the CPU.
diff --git a/include/asm-arm/checksum.h b/include/asm-arm/checksum.h
index f82f595c7..d4256d5f3 100644
--- a/include/asm-arm/checksum.h
+++ b/include/asm-arm/checksum.h
@@ -37,7 +37,7 @@ unsigned int
 csum_partial_copy_nocheck(const char *src, char *dst, int len, int sum);
 
 unsigned int
-csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *err_ptr);
+csum_partial_copy_from_user(const char __user *src, char *dst, int len, int sum, int *err_ptr);
 
 /*
  * This is the old (and unsafe) way of doing checksums, a warning message will
diff --git a/include/asm-arm/elf.h b/include/asm-arm/elf.h
index b67e06c0f..29533be8b 100644
--- a/include/asm-arm/elf.h
+++ b/include/asm-arm/elf.h
@@ -1,6 +1,8 @@
 #ifndef __ASMARM_ELF_H
 #define __ASMARM_ELF_H
 
+#include <linux/config.h>
+
 /*
  * ELF register definitions..
  */
@@ -14,6 +16,7 @@ typedef unsigned long elf_freg_t[3];
 
 #define EM_ARM	40
 #define EF_ARM_APCS26 0x08
+#define EF_ARM_SOFT_FLOAT 0x200
 
 #define R_ARM_NONE	0
 #define R_ARM_PC24	1
@@ -91,6 +94,8 @@ extern char elf_platform[];
 	(( (elf_hwcap & HWCAP_26BIT) && (x)->e_flags & EF_ARM_APCS26) || \
 	  ((x)->e_flags & EF_ARM_APCS26) == 0)
 
+#ifndef CONFIG_IWMMXT
+
 /* Old NetWinder binaries were compiled in such a way that the iBCS
    heuristic always trips on them.  Until these binaries become uncommon
    enough not to care, don't trust the `ibcs' flag here.  In any case
@@ -99,6 +104,28 @@ extern char elf_platform[];
 #define SET_PERSONALITY(ex,ibcs2) \
 	set_personality(((ex).e_flags&EF_ARM_APCS26 ?PER_LINUX :PER_LINUX_32BIT))
 
+#else
+
+/*
+ * All iWMMXt capable CPUs don't support 26-bit mode.  Yet they can run
+ * legacy binaries which used to contain FPA11 floating point instructions
+ * that have always been emulated by the kernel.  PFA11 and iWMMXt overlap
+ * on coprocessor 1 space though.  We therefore must decide if given task
+ * is allowed to use CP 0 and 1 for iWMMXt, or if they should be blocked
+ * at all times for the prefetch exception handler to catch FPA11 opcodes
+ * and emulate them.  The best indication to discriminate those two cases
+ * is the SOFT_FLOAT flag in the ELF header.
+ */
+
+#define SET_PERSONALITY(ex,ibcs2) \
+do { \
+	set_personality(PER_LINUX_32BIT); \
+	if ((ex).e_flags & EF_ARM_SOFT_FLOAT) \
+		set_thread_flag(TIF_USING_IWMMXT); \
+} while (0)
+
+#endif
+
 #endif
 
 #endif
diff --git a/include/asm-arm/fpstate.h b/include/asm-arm/fpstate.h
index 7492cfa21..f7430e3aa 100644
--- a/include/asm-arm/fpstate.h
+++ b/include/asm-arm/fpstate.h
@@ -11,7 +11,7 @@
 #ifndef __ASM_ARM_FPSTATE_H
 #define __ASM_ARM_FPSTATE_H
 
-#define FP_SIZE 35
+#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 
@@ -43,19 +43,32 @@ union vfp_state {
 extern void vfp_flush_thread(union vfp_state *);
 extern void vfp_release_thread(union vfp_state *);
 
+#define FP_HARD_SIZE 35
+
 struct fp_hard_struct {
-	unsigned int save[FP_SIZE];		/* as yet undefined */
+	unsigned int save[FP_HARD_SIZE];		/* as yet undefined */
 };
 
+#define FP_SOFT_SIZE 35
+
 struct fp_soft_struct {
-	unsigned int save[FP_SIZE];		/* undefined information */
+	unsigned int save[FP_SOFT_SIZE];		/* undefined information */
+};
+
+struct iwmmxt_struct {
+	unsigned int save[0x98/sizeof(int) + 1];
 };
 
 union fp_state {
 	struct fp_hard_struct	hard;
 	struct fp_soft_struct	soft;
+#ifdef CONFIG_IWMMXT
+	struct iwmmxt_struct	iwmmxt;
+#endif
 };
 
+#define FP_SIZE (sizeof(union fp_state) / sizeof(int))
+
 #endif
 
 #endif
diff --git a/include/asm-arm/hardirq.h b/include/asm-arm/hardirq.h
index cb8c5257d..3f734c4de 100644
--- a/include/asm-arm/hardirq.h
+++ b/include/asm-arm/hardirq.h
@@ -22,31 +22,25 @@ typedef struct {
  *
  * - bits 0-7 are the preemption count (max depth: 256)
  * - bits 8-15 are the softirq count (max # of softirqs: 256)
- * - bits 16-23 are the hardirq count (max # of hardirqs: 256)
+ * - bits 16-24 are the hardirq count (max # of hardirqs: 512)
  * - bit 26 is the PREEMPT_ACTIVE flag
+ *
+ * We optimize HARDIRQ_BITS for immediate constant, and only
+ * increase it if really needed.
  */
 #define PREEMPT_BITS	8
 #define SOFTIRQ_BITS	8
+
+#if NR_IRQS > 256
+#define HARDIRQ_BITS	9
+#else
 #define HARDIRQ_BITS	8
+#endif
 
 #define PREEMPT_SHIFT	0
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK|SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have space
  * for potentially all IRQ sources in the system nesting
@@ -56,29 +50,9 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 
-#ifdef CONFIG_PREEMPT
-# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #ifndef CONFIG_SMP
-
 extern asmlinkage void __do_softirq(void);
 
 #define irq_exit()							\
@@ -88,10 +62,6 @@ extern asmlinkage void __do_softirq(void);
 			__do_softirq();					\
 		preempt_enable_no_resched();				\
 	} while (0)
-
-#define synchronize_irq(irq)	barrier()
-#else
-extern void synchronize_irq(unsigned int irq);
 #endif
 
 #endif /* __ASM_HARDIRQ_H */
diff --git a/include/asm-arm/hardware.h b/include/asm-arm/hardware.h
index 283dde118..1fd1a5b65 100644
--- a/include/asm-arm/hardware.h
+++ b/include/asm-arm/hardware.h
@@ -15,13 +15,4 @@
 
 #include <asm/arch/hardware.h>
 
-#ifndef __ASSEMBLY__
-
-struct platform_device;
-
-extern int platform_add_devices(struct platform_device **, int);
-extern int platform_add_device(struct platform_device *);
-
-#endif
-
 #endif
diff --git a/include/asm-arm/hardware/clock.h b/include/asm-arm/hardware/clock.h
index 9dfc0624b..4983449ff 100644
--- a/include/asm-arm/hardware/clock.h
+++ b/include/asm-arm/hardware/clock.h
@@ -64,7 +64,7 @@ int clk_use(struct clk *clk);
 void clk_unuse(struct clk *clk);
 
 /**
- * clk_get_rate - obtain the current clock rate for a clock source.
+ * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
  *		  This is only valid once the clock source has been enabled.
  * @clk: clock source
  */
@@ -85,16 +85,16 @@ void clk_put(struct clk *clk);
 /**
  * clk_round_rate - adjust a rate to the exact rate a clock can provide
  * @clk: clock source
- * @rate: desired clock rate in kHz
+ * @rate: desired clock rate in Hz
  *
- * Returns rounded clock rate, or negative errno.
+ * Returns rounded clock rate in Hz, or negative errno.
  */
 long clk_round_rate(struct clk *clk, unsigned long rate);
  
 /**
  * clk_set_rate - set the clock rate for a clock source
  * @clk: clock source
- * @rate: desired clock rate in kHz
+ * @rate: desired clock rate in Hz
  *
  * Returns success (0) or negative errno.
  */
diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h
index 93aa555cf..1855fb73c 100644
--- a/include/asm-arm/io.h
+++ b/include/asm-arm/io.h
@@ -271,10 +271,12 @@ extern void __iounmap(void *addr);
 #ifndef __arch_ioremap
 #define ioremap(cookie,size)		__ioremap(cookie,size,0,1)
 #define ioremap_nocache(cookie,size)	__ioremap(cookie,size,0,1)
+#define ioremap_cached(cookie,size)	__ioremap(cookie,size,L_PTE_CACHEABLE,1)
 #define iounmap(cookie)			__iounmap(cookie)
 #else
 #define ioremap(cookie,size)		__arch_ioremap((cookie),(size),0,1)
 #define ioremap_nocache(cookie,size)	__arch_ioremap((cookie),(size),0,1)
+#define ioremap_cached(cookie,size)	__arch_ioremap((cookie),(size),L_PTE_CACHEABLE,1)
 #define iounmap(cookie)			__arch_iounmap(cookie)
 #endif
 
diff --git a/include/asm-arm/mach/pci.h b/include/asm-arm/mach/pci.h
index ea0b992ee..25d540ed0 100644
--- a/include/asm-arm/mach/pci.h
+++ b/include/asm-arm/mach/pci.h
@@ -52,14 +52,14 @@ void pci_common_init(struct hw_pci *);
 /*
  * PCI controllers
  */
-extern int iop310_setup(int nr, struct pci_sys_data *);
-extern struct pci_bus *iop310_scan_bus(int nr, struct pci_sys_data *);
-extern void iop310_init(void);
-
 extern int iop321_setup(int nr, struct pci_sys_data *);
 extern struct pci_bus *iop321_scan_bus(int nr, struct pci_sys_data *);
 extern void iop321_init(void);
 
+extern int iop331_setup(int nr, struct pci_sys_data *);
+extern struct pci_bus *iop331_scan_bus(int nr, struct pci_sys_data *);
+extern void iop331_init(void);
+
 extern int dc21285_setup(int nr, struct pci_sys_data *);
 extern struct pci_bus *dc21285_scan_bus(int nr, struct pci_sys_data *);
 extern void dc21285_preinit(void);
diff --git a/include/asm-arm/mach/time.h b/include/asm-arm/mach/time.h
index edb6fcc6a..51728edf7 100644
--- a/include/asm-arm/mach/time.h
+++ b/include/asm-arm/mach/time.h
@@ -13,8 +13,11 @@
 extern void (*init_arch_time)(void);
 
 extern int (*set_rtc)(void);
-extern unsigned long(*gettimeoffset)(void);
+extern unsigned long (*gettimeoffset)(void);
 
-void timer_tick(struct pt_regs *);
+extern void timer_tick(struct pt_regs *);
+
+extern void save_time_delta(struct timespec *delta, struct timespec *rtc);
+extern void restore_time_delta(struct timespec *delta, struct timespec *rtc);
 
 #endif
diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h
index 41f117fb5..e47bea7d1 100644
--- a/include/asm-arm/memory.h
+++ b/include/asm-arm/memory.h
@@ -13,6 +13,7 @@
 #define __ASM_ARM_MEMORY_H
 
 #include <linux/config.h>
+#include <linux/compiler.h>
 #include <asm/arch/memory.h>
 
 #ifndef TASK_SIZE
@@ -108,10 +109,18 @@ static inline void *phys_to_virt(unsigned long x)
 /*
  * Virtual <-> DMA view memory address translations
  * Again, these are *only* valid on the kernel direct mapped RAM
- * memory.  Use of these is *deprecated*.
+ * memory.  Use of these is *deprecated* (and that doesn't mean
+ * use the __ prefixed forms instead.)  See dma-mapping.h.
  */
-#define virt_to_bus(x)		(__virt_to_bus((unsigned long)(x)))
-#define bus_to_virt(x)		((void *)(__bus_to_virt((unsigned long)(x))))
+static inline __deprecated unsigned long virt_to_bus(void *x)
+{
+	return __virt_to_bus((unsigned long)x);
+}
+
+static inline __deprecated void *bus_to_virt(unsigned long x)
+{
+	return (void *)__bus_to_virt(x);
+}
 
 /*
  * Conversion between a struct page and a physical address.
@@ -177,9 +186,9 @@ static inline void *phys_to_virt(unsigned long x)
  * We should really eliminate virt_to_bus() here - it's deprecated.
  */
 #ifndef __arch_page_to_dma
-#define page_to_dma(dev, page)		((dma_addr_t)__virt_to_bus(page_address(page)))
-#define dma_to_virt(dev, addr)		(__bus_to_virt(addr))
-#define virt_to_dma(dev, addr)		(__virt_to_bus(addr))
+#define page_to_dma(dev, page)		((dma_addr_t)__virt_to_bus((unsigned long)page_address(page)))
+#define dma_to_virt(dev, addr)		((void *)__bus_to_virt(addr))
+#define virt_to_dma(dev, addr)		((dma_addr_t)__virt_to_bus((unsigned long)(addr)))
 #else
 #define page_to_dma(dev, page)		(__arch_page_to_dma(dev, page))
 #define dma_to_virt(dev, addr)		(__arch_dma_to_virt(dev, addr))
diff --git a/include/asm-arm/page.h b/include/asm-arm/page.h
index bb8666883..a270052fe 100644
--- a/include/asm-arm/page.h
+++ b/include/asm-arm/page.h
@@ -133,7 +133,7 @@ extern void __cpu_copy_user_page(void *to, const void *from,
 	} while (0)
 
 #define clear_page(page)	memzero((void *)(page), PAGE_SIZE)
-extern void copy_page(void *to, void *from);
+extern void copy_page(void *to, const void *from);
 
 #undef STRICT_MM_TYPECHECKS
 
diff --git a/include/asm-arm/param.h b/include/asm-arm/param.h
index 41a2f4fcf..94223d4d7 100644
--- a/include/asm-arm/param.h
+++ b/include/asm-arm/param.h
@@ -10,14 +10,13 @@
 #ifndef __ASM_PARAM_H
 #define __ASM_PARAM_H
 
-#include <asm/arch/param.h>	/* for HZ */
+#ifdef __KERNEL__
+# include <asm/arch/param.h>		/* for kernel version of HZ */
 
-#ifndef __KERNEL_HZ
-#define __KERNEL_HZ	100
-#endif
+# ifndef HZ
+#  define HZ		100		/* Internal kernel timer frequency */
+# endif
 
-#ifdef __KERNEL__
-# define HZ		__KERNEL_HZ	/* Internal kernel timer frequency */
 # define USER_HZ	100		/* User interfaces are in "ticks" */
 # define CLOCKS_PER_SEC	(USER_HZ)	/* like times() */
 #else
diff --git a/include/asm-arm/ptrace.h b/include/asm-arm/ptrace.h
index 162c45663..f227d7d0a 100644
--- a/include/asm-arm/ptrace.h
+++ b/include/asm-arm/ptrace.h
@@ -131,6 +131,12 @@ static inline int valid_user_regs(struct pt_regs *regs)
 #define instruction_pointer(regs) \
 	(pc_pointer((regs)->ARM_pc))
 
+#ifdef CONFIG_SMP
+extern unsigned long profile_pc(struct pt_regs *regs);
+#else
+#define profile_pc(regs) instruction_pointer(regs)
+#endif
+
 #ifdef __KERNEL__
 extern void show_regs(struct pt_regs *);
 
diff --git a/include/asm-arm/resource.h b/include/asm-arm/resource.h
index 748c660ed..354afada3 100644
--- a/include/asm-arm/resource.h
+++ b/include/asm-arm/resource.h
@@ -39,7 +39,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },	\
 	{ 0,             0             },	\
 	{ INR_OPEN,      INR_OPEN      },	\
-	{ RLIM_INFINITY, RLIM_INFINITY },	\
+	{ MLOCK_LIMIT,	 MLOCK_LIMIT   },	\
 	{ RLIM_INFINITY, RLIM_INFINITY },	\
 	{ RLIM_INFINITY, RLIM_INFINITY },	\
 	{ MAX_SIGPENDING, MAX_SIGPENDING},	\
diff --git a/include/asm-arm/semaphore.h b/include/asm-arm/semaphore.h
index 2e47880be..60f33e6eb 100644
--- a/include/asm-arm/semaphore.h
+++ b/include/asm-arm/semaphore.h
@@ -16,21 +16,12 @@ struct semaphore {
 	atomic_t count;
 	int sleepers;
 	wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name)	.__magic = (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INIT(name,cnt) {				\
+#define __SEMAPHORE_INIT(name, cnt)				\
+{								\
 	.count	= ATOMIC_INIT(cnt),				\
 	.wait	= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait),	\
-	__SEM_DEBUG_INIT(name)					\
 }
 
 #define __MUTEX_INITIALIZER(name) __SEMAPHORE_INIT(name,1)
@@ -46,9 +37,6 @@ static inline void sema_init(struct semaphore *sem, int val)
 	atomic_set(&sem->count, val);
 	sem->sleepers = 0;
 	init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX(struct semaphore *sem)
@@ -85,9 +73,6 @@ extern void __up(struct semaphore * sem);
  */
 static inline void down(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	__down_op(sem, __down_failed);
 }
@@ -98,19 +83,12 @@ static inline void down(struct semaphore * sem)
  */
 static inline int down_interruptible (struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	return __down_op_ret(sem, __down_interruptible_failed);
 }
 
 static inline int down_trylock(struct semaphore *sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	return __down_op_ret(sem, __down_trylock_failed);
 }
 
@@ -122,10 +100,6 @@ static inline int down_trylock(struct semaphore *sem)
  */
 static inline void up(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	__up_op(sem, __up_wakeup);
 }
 
diff --git a/include/asm-arm/socket.h b/include/asm-arm/socket.h
index b05e71739..46d20585d 100644
--- a/include/asm-arm/socket.h
+++ b/include/asm-arm/socket.h
@@ -47,20 +47,4 @@
 
 #define SO_PEERSEC		31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h
index d500cc940..7572ac4ff 100644
--- a/include/asm-arm/system.h
+++ b/include/asm-arm/system.h
@@ -50,11 +50,45 @@
 #define read_cpuid(reg)							\
 	({								\
 		unsigned int __val;					\
-		asm("mrc%? p15, 0, %0, c0, c0, " __stringify(reg)	\
-		    : "=r" (__val));					\
+		asm("mrc	p15, 0, %0, c0, c0, " __stringify(reg)	\
+		    : "=r" (__val)					\
+		    :							\
+		    : "cc");						\
 		__val;							\
 	})
 
+#define __cacheid_present(val)		(val != read_cpuid(CPUID_ID))
+#define __cacheid_vivt(val)		((val & (15 << 25)) != (14 << 25))
+#define __cacheid_vipt(val)		((val & (15 << 25)) == (14 << 25))
+#define __cacheid_vipt_nonaliasing(val)	((val & (15 << 25 | 1 << 23)) == (14 << 25))
+#define __cacheid_vipt_aliasing(val)	((val & (15 << 25 | 1 << 23)) == (14 << 25 | 1 << 23))
+
+#define cache_is_vivt()							\
+	({								\
+		unsigned int __val = read_cpuid(CPUID_CACHETYPE);	\
+		(!__cacheid_present(__val)) || __cacheid_vivt(__val);	\
+	})
+		
+#define cache_is_vipt()							\
+	({								\
+		unsigned int __val = read_cpuid(CPUID_CACHETYPE);	\
+		__cacheid_present(__val) && __cacheid_vipt(__val);	\
+	})
+
+#define cache_is_vipt_nonaliasing()					\
+	({								\
+		unsigned int __val = read_cpuid(CPUID_CACHETYPE);	\
+		__cacheid_present(__val) &&				\
+		 __cacheid_vipt_nonaliasing(__val);			\
+	})
+
+#define cache_is_vipt_aliasing()					\
+	({								\
+		unsigned int __val = read_cpuid(CPUID_CACHETYPE);	\
+		__cacheid_present(__val) &&				\
+		 __cacheid_vipt_aliasing(__val);			\
+	})
+
 /*
  * This is used to ensure the compiler did actually allocate the register we
  * asked it for some inline assembly sequences.  Apparently we can't trust
@@ -66,9 +100,10 @@
 
 #ifndef __ASSEMBLY__
 
-#include <linux/kernel.h>
+#include <linux/linkage.h>
 
 struct thread_info;
+struct task_struct;
 
 /* information about the system we're running on */
 extern unsigned int system_rev;
@@ -171,8 +206,6 @@ do {									\
  * `prev' will never be the same as `next'.  schedule() itself
  * contains the memory barrier to tell GCC not to cache `current'.
  */
-struct thread_info;
-struct task_struct;
 extern struct task_struct *__switch_to(struct task_struct *, struct thread_info *, struct thread_info *);
 
 #define switch_to(prev,next,last)					\
diff --git a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h
index b3ef76481..1a362ca41 100644
--- a/include/asm-arm/thread_info.h
+++ b/include/asm-arm/thread_info.h
@@ -100,23 +100,18 @@ extern void free_thread_info(struct thread_info *);
 #define thread_saved_fp(tsk)	\
 	((unsigned long)((tsk)->thread_info->cpu_context.fp))
 
-#else /* !__ASSEMBLY__ */
-
-#define TI_FLAGS	0
-#define TI_PREEMPT	4
-#define TI_ADDR_LIMIT	8
-#define TI_TASK		12
-#define TI_EXEC_DOMAIN	16
-#define TI_CPU		20
-#define TI_CPU_DOMAIN	24
-#define TI_CPU_SAVE	28
-#define TI_USED_CP	76
-#define TI_FPSTATE	(TI_USED_CP+16)
-#define TI_VFPSTATE	(TI_FPSTATE+FP_SIZE*4)
+extern void iwmmxt_task_disable(struct thread_info *);
+extern void iwmmxt_task_copy(struct thread_info *, void *);
+extern void iwmmxt_task_restore(struct thread_info *, void *);
+extern void iwmmxt_task_release(struct thread_info *);
 
 #endif
 
-#define PREEMPT_ACTIVE	0x04000000
+/*
+ * We use bit 30 of the preempt_count to indicate that kernel
+ * preemption is occuring.  See include/asm-arm/hardirq.h.
+ */
+#define PREEMPT_ACTIVE	0x40000000
 
 /*
  * thread information flags:
@@ -131,15 +126,15 @@ extern void free_thread_info(struct thread_info *);
 #define TIF_SIGPENDING		1
 #define TIF_NEED_RESCHED	2
 #define TIF_SYSCALL_TRACE	8
-#define TIF_USED_FPU		16
-#define TIF_POLLING_NRFLAG	17
+#define TIF_POLLING_NRFLAG	16
+#define TIF_USING_IWMMXT	17
 
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
-#define _TIF_USED_FPU		(1 << TIF_USED_FPU)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
+#define _TIF_USING_IWMMXT	(1 << TIF_USING_IWMMXT)
 
 /*
  * Change these and you break ASM code in entry-common.S
diff --git a/include/asm-arm/uaccess.h b/include/asm-arm/uaccess.h
index 51bc2a968..f36715246 100644
--- a/include/asm-arm/uaccess.h
+++ b/include/asm-arm/uaccess.h
@@ -394,6 +394,9 @@ static inline unsigned long __copy_to_user(void __user *to, const void *from, un
 	return __arch_copy_to_user(to, from, n);
 }
 
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
 static inline unsigned long clear_user (void __user *to, unsigned long n)
 {
 	if (access_ok(VERIFY_WRITE, to, n))
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index 1435eb396..28d53f0d6 100644
--- a/include/asm-arm/unistd.h
+++ b/include/asm-arm/unistd.h
@@ -299,6 +299,13 @@
 #define __NR_pciconfig_iobase		(__NR_SYSCALL_BASE+271)
 #define __NR_pciconfig_read		(__NR_SYSCALL_BASE+272)
 #define __NR_pciconfig_write		(__NR_SYSCALL_BASE+273)
+#define __NR_mq_open			(__NR_SYSCALL_BASE+274)
+#define __NR_mq_unlink			(__NR_SYSCALL_BASE+275)
+#define __NR_mq_timedsend		(__NR_SYSCALL_BASE+276)
+#define __NR_mq_timedreceive		(__NR_SYSCALL_BASE+277)
+#define __NR_mq_notify			(__NR_SYSCALL_BASE+278)
+#define __NR_mq_getsetattr		(__NR_SYSCALL_BASE+279)
+#define __NR_waitid			(__NR_SYSCALL_BASE+280)
 
 /*
  * The following SWIs are ARM private.
@@ -475,51 +482,6 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6
 #include <linux/types.h>
 #include <linux/syscalls.h>
 
-static inline pid_t setsid(void)
-{
-	return sys_setsid();
-}
-
-static inline long write(int fd, const char *buf, off_t count)
-{
-	return sys_write(fd, buf, count);
-}
-
-static inline long read(int fd, char *buf, off_t count)
-{
-	return sys_read(fd, buf, count);
-}
-
-static inline off_t lseek(int fd, off_t offset, int count)
-{
-	return sys_lseek(fd, offset, count);
-}
-
-static inline long dup(int fd)
-{
-	return sys_dup(fd);
-}
-
-static inline long open(const char *file, int flag, int mode)
-{
-	return sys_open(file, flag, mode);
-}
-
-static inline long close(int fd)
-{
-	return sys_close(fd);
-}
-
-static inline long _exit(int exitcode)
-{
-	return sys_exit(exitcode);
-}
-
-static inline pid_t waitpid(pid_t pid, int *wait_stat, int options)
-{
-	return sys_wait4((int)pid, wait_stat, options, NULL);
-}
-
 extern long execve(const char *file, char **argv, char **envp);
 
 struct pt_regs;
diff --git a/include/asm-arm26/bug.h b/include/asm-arm26/bug.h
index a1afde728..920b70533 100644
--- a/include/asm-arm26/bug.h
+++ b/include/asm-arm26/bug.h
@@ -5,26 +5,13 @@
 
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 extern volatile void __bug(const char *file, int line, void *data);
-
 /* give file/line information */
 #define BUG()		__bug(__FILE__, __LINE__, NULL)
-#define PAGE_BUG(page)	__bug(__FILE__, __LINE__, page)
-
 #else
-
-/* these just cause an oops */
 #define BUG()		(*(int *)0 = 0)
-#define PAGE_BUG(page)	(*(int *)0 = 0)
-
 #endif
 
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-arm26/hardirq.h b/include/asm-arm26/hardirq.h
index 623b5f8fb..52feb957f 100644
--- a/include/asm-arm26/hardirq.h
+++ b/include/asm-arm26/hardirq.h
@@ -32,20 +32,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK|SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have space
  * for potentially all IRQ sources in the system nesting
@@ -55,26 +41,8 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 
-#ifdef CONFIG_PREEMPT
-# define in_atomic()    ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()    (preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #ifndef CONFIG_SMP
 #define irq_exit()							\
 	do {								\
@@ -84,9 +52,6 @@ typedef struct {
 		preempt_enable_no_resched();				\
 	} while (0)
 
-#define synchronize_irq(irq)	barrier()
-#else
-#error SMP not supported
 #endif
 
 #endif /* __ASM_HARDIRQ_H */
diff --git a/include/asm-arm26/ptrace.h b/include/asm-arm26/ptrace.h
index 05aa6e25f..6a46b5ae1 100644
--- a/include/asm-arm26/ptrace.h
+++ b/include/asm-arm26/ptrace.h
@@ -30,6 +30,7 @@
 
 #define pc_pointer(v) ((v) & ~PCMASK)   /* convert v to pc type address */
 #define instruction_pointer(regs) (pc_pointer((regs)->ARM_pc)) /* get pc */
+#define profile_pc(regs) instruction_pointer(regs)
 
 /* this struct defines the way the registers are stored on the
    stack during a system call. */
diff --git a/include/asm-arm26/resource.h b/include/asm-arm26/resource.h
index 748c660ed..354afada3 100644
--- a/include/asm-arm26/resource.h
+++ b/include/asm-arm26/resource.h
@@ -39,7 +39,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },	\
 	{ 0,             0             },	\
 	{ INR_OPEN,      INR_OPEN      },	\
-	{ RLIM_INFINITY, RLIM_INFINITY },	\
+	{ MLOCK_LIMIT,	 MLOCK_LIMIT   },	\
 	{ RLIM_INFINITY, RLIM_INFINITY },	\
 	{ RLIM_INFINITY, RLIM_INFINITY },	\
 	{ MAX_SIGPENDING, MAX_SIGPENDING},	\
diff --git a/include/asm-arm26/semaphore.h b/include/asm-arm26/semaphore.h
index 49946274a..c1b6a1eda 100644
--- a/include/asm-arm26/semaphore.h
+++ b/include/asm-arm26/semaphore.h
@@ -16,22 +16,14 @@ struct semaphore {
 	atomic_t count;
 	int sleepers;
 	wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#if WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INIT(name,count)			\
-	{ ATOMIC_INIT(count), 0,			\
-	  __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
-	  __SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INIT(name, n)					\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.sleepers	= 0,						\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait),	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INIT(name,1)
@@ -47,9 +39,6 @@ static inline void sema_init(struct semaphore *sem, int val)
 	atomic_set(&sem->count, val);
 	sem->sleepers = 0;
 	init_waitqueue_head(&sem->wait);
-#if WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX(struct semaphore *sem)
@@ -81,9 +70,6 @@ extern void __up(struct semaphore * sem);
  */
 static inline void down(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	__down_op(sem, __down_failed);
 }
@@ -94,19 +80,12 @@ static inline void down(struct semaphore * sem)
  */
 static inline int down_interruptible (struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	return __down_op_ret(sem, __down_interruptible_failed);
 }
 
 static inline int down_trylock(struct semaphore *sem)
 {
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	return __down_op_ret(sem, __down_trylock_failed);
 }
 
@@ -118,10 +97,6 @@ static inline int down_trylock(struct semaphore *sem)
  */
 static inline void up(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	__up_op(sem, __up_wakeup);
 }
 
diff --git a/include/asm-arm26/socket.h b/include/asm-arm26/socket.h
index b05e71739..46d20585d 100644
--- a/include/asm-arm26/socket.h
+++ b/include/asm-arm26/socket.h
@@ -47,20 +47,4 @@
 
 #define SO_PEERSEC		31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-arm26/tlb.h b/include/asm-arm26/tlb.h
index 2da30180a..acfdbe8b6 100644
--- a/include/asm-arm26/tlb.h
+++ b/include/asm-arm26/tlb.h
@@ -39,7 +39,7 @@ tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
 
         if (rss < freed)
                 freed = rss;
-        // mm->rss = rss - freed;
+	// mm->rss = rss - freed;
 	vx_rsspages_sub(mm, freed);
 
         if (freed) {
diff --git a/include/asm-arm26/uaccess.h b/include/asm-arm26/uaccess.h
index ae557c081..3818aa939 100644
--- a/include/asm-arm26/uaccess.h
+++ b/include/asm-arm26/uaccess.h
@@ -217,6 +217,9 @@ static __inline__ unsigned long __copy_to_user(void *to, const void *from, unsig
 	return n;
 }
 
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
 static __inline__ unsigned long clear_user (void *to, unsigned long n)
 {
 	if (access_ok(VERIFY_WRITE, to, n))
diff --git a/include/asm-cris/arch-v10/ptrace.h b/include/asm-cris/arch-v10/ptrace.h
index 939d98464..fb14c5ee3 100644
--- a/include/asm-cris/arch-v10/ptrace.h
+++ b/include/asm-cris/arch-v10/ptrace.h
@@ -109,6 +109,7 @@ struct switch_stack {
 /* bit 8 is user-mode flag */
 #define user_mode(regs) (((regs)->dccr & 0x100) != 0)
 #define instruction_pointer(regs) ((regs)->irp)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 
 #endif
diff --git a/include/asm-cris/bug.h b/include/asm-cris/bug.h
index d6286c265..8dd6b23c1 100644
--- a/include/asm-cris/bug.h
+++ b/include/asm-cris/bug.h
@@ -1,21 +1,4 @@
 #ifndef _CRIS_BUG_H
 #define _CRIS_BUG_H
-
-#define BUG() do { \
-  printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
-} while (0)
-
-#define PAGE_BUG(page) do { \
-         BUG(); \
-} while (0)
-
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
-
+#include <asm-generic/bug.h>
 #endif
diff --git a/include/asm-cris/hardirq.h b/include/asm-cris/hardirq.h
index c75100f83..4e28c8332 100644
--- a/include/asm-cris/hardirq.h
+++ b/include/asm-cris/hardirq.h
@@ -40,20 +40,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -63,27 +49,7 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
 #define irq_exit()							\
 do {									\
 		preempt_count() -= IRQ_EXIT_OFFSET;			\
@@ -92,6 +58,4 @@ do {									\
 		preempt_enable_no_resched();				\
 } while (0)
 
-#define synchronize_irq(irq)	barrier()
-
 #endif /* __ASM_HARDIRQ_H */
diff --git a/include/asm-cris/resource.h b/include/asm-cris/resource.h
index e33ada08d..7a83ad536 100644
--- a/include/asm-cris/resource.h
+++ b/include/asm-cris/resource.h
@@ -39,7 +39,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
-	{ RLIM_INFINITY, RLIM_INFINITY },               \
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },               \
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff --git a/include/asm-cris/semaphore.h b/include/asm-cris/semaphore.h
index 9ee66b9d5..605aa7eaa 100644
--- a/include/asm-cris/semaphore.h
+++ b/include/asm-cris/semaphore.h
@@ -24,21 +24,14 @@ struct semaphore {
 	atomic_t count;
 	atomic_t waking;
 	wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#if WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name)         , (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count)             \
-        { ATOMIC_INIT(count), ATOMIC_INIT(0),           \
-          __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
-          __SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.waking		= ATOMIC_INIT(0),				\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
+}
 
 #define __MUTEX_INITIALIZER(name) \
         __SEMAPHORE_INITIALIZER(name,1)
@@ -76,9 +69,6 @@ extern inline void down(struct semaphore * sem)
 	unsigned long flags;
 	int failed;
 
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	/* atomically decrement the semaphores count, and if its negative, we wait */
@@ -102,9 +92,6 @@ extern inline int down_interruptible(struct semaphore * sem)
 	unsigned long flags;
 	int failed;
 
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	/* atomically decrement the semaphores count, and if its negative, we wait */
@@ -122,10 +109,6 @@ extern inline int down_trylock(struct semaphore * sem)
 	unsigned long flags;
 	int failed;
 
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	local_save_flags(flags);
 	local_irq_disable();
 	failed = --(sem->count.counter) < 0;
@@ -146,10 +129,6 @@ extern inline void up(struct semaphore * sem)
 	unsigned long flags;
 	int wakeup;
 
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	/* atomically increment the semaphores count, and if it was negative, we wake people */
 	local_save_flags(flags);
 	local_irq_disable();
diff --git a/include/asm-cris/socket.h b/include/asm-cris/socket.h
index b4421808b..f159b4f16 100644
--- a/include/asm-cris/socket.h
+++ b/include/asm-cris/socket.h
@@ -49,21 +49,6 @@
 
 #define SO_PEERSEC             31
 
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM     1               /* stream (connection) socket   */
-#define SOCK_DGRAM      2               /* datagram (conn.less) socket  */
-#define SOCK_RAW        3               /* raw socket                   */
-#define SOCK_RDM        4               /* reliably-delivered message   */
-#define SOCK_SEQPACKET  5               /* sequential packet socket     */
-#define SOCK_PACKET     10              /* linux specific way of        */
-                                        /* getting packets at the dev   */
-                                        /* level.  For writing rarp and */
-                                        /* other similar things on the  */
-                                        /* user level.                  */
-#define        SOCK_MAX        (SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
 
 
diff --git a/include/asm-cris/uaccess.h b/include/asm-cris/uaccess.h
index 7532cd76d..2f58e19df 100644
--- a/include/asm-cris/uaccess.h
+++ b/include/asm-cris/uaccess.h
@@ -434,6 +434,8 @@ __generic_clear_user_nocheck(void *to, unsigned long n)
 
 #define __copy_to_user(to,from,n)   __generic_copy_to_user_nocheck((to),(from),(n))
 #define __copy_from_user(to,from,n) __generic_copy_from_user_nocheck((to),(from),(n))
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 #define __clear_user(to,n) __generic_clear_user_nocheck((to),(n))
 
 #define strlen_user(str)	strnlen_user((str), 0x7ffffffe)
diff --git a/include/asm-generic/ide_iops.h b/include/asm-generic/ide_iops.h
index 8574de4bd..1b91d0681 100644
--- a/include/asm-generic/ide_iops.h
+++ b/include/asm-generic/ide_iops.h
@@ -5,7 +5,7 @@
 #define __ide_outsw	outsw
 #define __ide_outsl	outsl
 
-static __inline__ void __ide_mm_insw(unsigned long port, void *addr, u32 count)
+static __inline__ void __ide_mm_insw(void __iomem *port, void *addr, u32 count)
 {
 	while (count--) {
 		*(u16 *)addr = readw(port);
@@ -13,7 +13,7 @@ static __inline__ void __ide_mm_insw(unsigned long port, void *addr, u32 count)
 	}
 }
 
-static __inline__ void __ide_mm_insl(unsigned long port, void *addr, u32 count)
+static __inline__ void __ide_mm_insl(void __iomem *port, void *addr, u32 count)
 {
 	while (count--) {
 		*(u32 *)addr = readl(port);
@@ -21,7 +21,7 @@ static __inline__ void __ide_mm_insl(unsigned long port, void *addr, u32 count)
 	}
 }
 
-static __inline__ void __ide_mm_outsw(unsigned long port, void *addr, u32 count)
+static __inline__ void __ide_mm_outsw(void __iomem *port, void *addr, u32 count)
 {
 	while (count--) {
 		writew(*(u16 *)addr, port);
@@ -29,7 +29,7 @@ static __inline__ void __ide_mm_outsw(unsigned long port, void *addr, u32 count)
 	}
 }
 
-static __inline__ void __ide_mm_outsl(unsigned long port, void *addr, u32 count)
+static __inline__ void __ide_mm_outsl(void __iomem * port, void *addr, u32 count)
 {
 	while (count--) {
 		writel(*(u32 *)addr, port);
diff --git a/include/asm-generic/local.h b/include/asm-generic/local.h
index c814b2f84..16fc00360 100644
--- a/include/asm-generic/local.h
+++ b/include/asm-generic/local.h
@@ -3,8 +3,8 @@
 
 #include <linux/config.h>
 #include <linux/percpu.h>
+#include <linux/hardirq.h>
 #include <asm/types.h>
-#include <asm/hardirq.h>
 
 /* An unsigned long type for operations which are atomic for a single
  * CPU.  Usually used in combination with per-cpu variables. */
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 29573197c..cf791b073 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -13,11 +13,19 @@
  * Note: the old pte is known to not be writable, so we don't need to
  * worry about dirty bits etc getting lost.
  */
+#ifndef __HAVE_ARCH_SET_PTE_ATOMIC
 #define ptep_establish(__vma, __address, __ptep, __entry)		\
 do {				  					\
 	set_pte(__ptep, __entry);					\
 	flush_tlb_page(__vma, __address);				\
 } while (0)
+#else /* __HAVE_ARCH_SET_PTE_ATOMIC */
+#define ptep_establish(__vma, __address, __ptep, __entry)		\
+do {				  					\
+	set_pte_atomic(__ptep, __entry);				\
+	flush_tlb_page(__vma, __address);				\
+} while (0)
+#endif /* __HAVE_ARCH_SET_PTE_ATOMIC */
 #endif
 
 #ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
diff --git a/include/asm-generic/siginfo.h b/include/asm-generic/siginfo.h
index f757d2d51..3a3f35d75 100644
--- a/include/asm-generic/siginfo.h
+++ b/include/asm-generic/siginfo.h
@@ -3,6 +3,7 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
+#include <linux/resource.h>
 
 typedef union sigval {
 	int sival_int;
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 918b02d6c..bb340cb5c 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -16,6 +16,16 @@
 		*(.rodata1)						\
 	}								\
 									\
+	/* PCI quirks */						\
+	.pci_fixup        : AT(ADDR(.pci_fixup) - LOAD_OFFSET) {	\
+		VMLINUX_SYMBOL(__start_pci_fixups_header) = .;		\
+		*(.pci_fixup_header)					\
+		VMLINUX_SYMBOL(__end_pci_fixups_header) = .;		\
+		VMLINUX_SYMBOL(__start_pci_fixups_final) = .;		\
+		*(.pci_fixup_final)					\
+		VMLINUX_SYMBOL(__end_pci_fixups_final) = .;		\
+	}								\
+									\
 	/* Kernel symbol table: Normal symbols */			\
 	__ksymtab         : AT(ADDR(__ksymtab) - LOAD_OFFSET) {		\
 		VMLINUX_SYMBOL(__start___ksymtab) = .;			\
@@ -47,6 +57,13 @@
 	/* Kernel symbol table: strings */				\
         __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) {	\
 		*(__ksymtab_strings)					\
+	}								\
+									\
+	/* Built-in module parameters. */				\
+	__param : AT(ADDR(__param) - LOAD_OFFSET) {			\
+		VMLINUX_SYMBOL(__start___param) = .;			\
+		*(__param)						\
+		VMLINUX_SYMBOL(__stop___param) = .;			\
 	}
 
 #define SECURITY_INIT							\
@@ -60,3 +77,8 @@
 		VMLINUX_SYMBOL(__sched_text_start) = .;			\
 		*(.sched.text)						\
 		VMLINUX_SYMBOL(__sched_text_end) = .;
+
+#define LOCK_TEXT							\
+		VMLINUX_SYMBOL(__lock_text_start) = .;			\
+		*(.spinlock.text)					\
+		VMLINUX_SYMBOL(__lock_text_end) = .;
diff --git a/include/asm-h8300/bitops.h b/include/asm-h8300/bitops.h
index 893e6f1c7..94b7a46a6 100644
--- a/include/asm-h8300/bitops.h
+++ b/include/asm-h8300/bitops.h
@@ -273,6 +273,8 @@ found_middle:
 	return result + __ffs(tmp);
 }
 
+#define find_first_bit(addr, size) find_next_bit(addr, size, 0)
+
 /*
  * Every architecture must define this function. It's the fastest
  * way of searching a 140-bit bitmap where the first 100 bits are
diff --git a/include/asm-h8300/bug.h b/include/asm-h8300/bug.h
index 3b6f0102f..edddf5b08 100644
--- a/include/asm-h8300/bug.h
+++ b/include/asm-h8300/bug.h
@@ -1,21 +1,4 @@
 #ifndef _H8300_BUG_H
 #define _H8300_BUG_H
-
-#define BUG() do { \
-  printk("%s(%d): kernel BUG!\n", __FILE__, __LINE__); \
-} while (0)
-
-#define PAGE_BUG(page) do { \
-         BUG(); \
-} while (0)
-
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
-
+#include <asm-generic/bug.h>
 #endif
diff --git a/include/asm-h8300/hardirq.h b/include/asm-h8300/hardirq.h
index c0941a080..c878cc44b 100644
--- a/include/asm-h8300/hardirq.h
+++ b/include/asm-h8300/hardirq.h
@@ -38,20 +38,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -61,27 +47,7 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #define irq_exit()							\
 do {									\
 		preempt_count() -= IRQ_EXIT_OFFSET;			\
@@ -90,10 +56,4 @@ do {									\
 		preempt_enable_no_resched();				\
 } while (0)
 
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else
-# error h8300 SMP is not available
-#endif /* CONFIG_SMP */
-
 #endif
diff --git a/include/asm-h8300/ptrace.h b/include/asm-h8300/ptrace.h
index 5effc8d14..c2e05e4b5 100644
--- a/include/asm-h8300/ptrace.h
+++ b/include/asm-h8300/ptrace.h
@@ -57,6 +57,7 @@ struct pt_regs {
 
 #define user_mode(regs) (!((regs)->ccr & PS_S))
 #define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
diff --git a/include/asm-h8300/resource.h b/include/asm-h8300/resource.h
index a87720b14..2031e3ce4 100644
--- a/include/asm-h8300/resource.h
+++ b/include/asm-h8300/resource.h
@@ -39,7 +39,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
-	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff --git a/include/asm-h8300/semaphore.h b/include/asm-h8300/semaphore.h
index 9efd009de..fe6ef3774 100644
--- a/include/asm-h8300/semaphore.h
+++ b/include/asm-h8300/semaphore.h
@@ -26,21 +26,14 @@ struct semaphore {
 	atomic_t count;
 	int sleepers;
 	wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#if WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.sleepers	= 0,						\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name,1)
@@ -87,9 +80,6 @@ static inline void down(struct semaphore * sem)
 {
 	register atomic_t *count asm("er0");
 
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	count = &(sem->count);
@@ -116,9 +106,6 @@ static inline int down_interruptible(struct semaphore * sem)
 {
 	register atomic_t *count asm("er0");
 
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	count = &(sem->count);
@@ -147,10 +134,6 @@ static inline int down_trylock(struct semaphore * sem)
 {
 	register atomic_t *count asm("er0");
 
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	count = &(sem->count);
 	__asm__ __volatile__(
 		"stc ccr,r3l\n\t"
@@ -187,10 +170,6 @@ static inline void up(struct semaphore * sem)
 {
 	register atomic_t *count asm("er0");
 
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	count = &(sem->count);
 	__asm__ __volatile__(
 		"stc ccr,r3l\n\t"
diff --git a/include/asm-h8300/socket.h b/include/asm-h8300/socket.h
index 070d46d23..af33b8525 100644
--- a/include/asm-h8300/socket.h
+++ b/include/asm-h8300/socket.h
@@ -47,20 +47,4 @@
 
 #define SO_PEERSEC		31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-h8300/uaccess.h b/include/asm-h8300/uaccess.h
index 46c026150..f3f4ffe0b 100644
--- a/include/asm-h8300/uaccess.h
+++ b/include/asm-h8300/uaccess.h
@@ -123,6 +123,8 @@ extern int __get_user_bad(void);
 
 #define __copy_from_user(to, from, n) copy_from_user(to, from, n)
 #define __copy_to_user(to, from, n) copy_to_user(to, from, n)
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 
 #define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; })
 
diff --git a/include/asm-i386/acpi.h b/include/asm-i386/acpi.h
index 42164a6d5..338c34291 100644
--- a/include/asm-i386/acpi.h
+++ b/include/asm-i386/acpi.h
@@ -101,6 +101,17 @@ __acpi_release_global_lock (unsigned int *lock)
         :"=r"(n_hi), "=r"(n_lo)     \
         :"0"(n_hi), "1"(n_lo))
 
+/*
+ * Refer Intel ACPI _PDC support document for bit definitions
+ */
+#define ACPI_PDC_EST_CAPABILITY_SMP	0xa
+#define ACPI_PDC_EST_CAPABILITY_MSR	0x1
+
+/*
+ * Refer Intel ACPI _PDC support document for bit definitions
+ */
+#define ACPI_PDC_EST_CAPABILITY_SMP 	0xa
+#define ACPI_PDC_EST_CAPABILITY_MSR	0x1
 
 #ifdef CONFIG_ACPI_BOOT 
 extern int acpi_lapic;
@@ -178,6 +189,8 @@ extern void acpi_reserve_bootmem(void);
 
 #endif /*CONFIG_ACPI_SLEEP*/
 
+extern u8 x86_acpiid_to_apicid[];
+
 #endif /*__KERNEL__*/
 
 #endif /*_ASM_ACPI_H*/
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
index 95cc9c1ba..8135c7c29 100644
--- a/include/asm-i386/apic.h
+++ b/include/asm-i386/apic.h
@@ -7,13 +7,28 @@
 #include <asm/apicdef.h>
 #include <asm/system.h>
 
-#define APIC_DEBUG 0
-
-#if APIC_DEBUG
-#define Dprintk(x...) printk(x)
-#else
 #define Dprintk(x...)
-#endif
+
+/*
+ * Debugging macros
+ */
+#define APIC_QUIET   0
+#define APIC_VERBOSE 1
+#define APIC_DEBUG   2
+
+extern int apic_verbosity;
+
+/*
+ * Define the default level of output to be very little
+ * This can be turned up by using apic=verbose for more
+ * information and apic=debug for _lots_ of information.
+ * apic_verbosity is defined in apic.c
+ */
+#define apic_printk(v, s, a...) do {       \
+		if ((v) <= apic_verbosity) \
+			printk(s, ##a);    \
+	} while (0)
+
 
 #ifdef CONFIG_X86_LOCAL_APIC
 
diff --git a/include/asm-i386/bitops.h b/include/asm-i386/bitops.h
index 8fd938fa9..9db0b712d 100644
--- a/include/asm-i386/bitops.h
+++ b/include/asm-i386/bitops.h
@@ -31,6 +31,11 @@
  *
  * This function is atomic and may not be reordered.  See __set_bit()
  * if you do not require the atomic guarantees.
+ *
+ * Note: there are no guarantees that this function will not be reordered
+ * on non x86 architectures, so if you are writting portable code,
+ * make sure not to rely on its reordering guarantees.
+ *
  * Note that @nr may be almost arbitrarily large; this function is not
  * restricted to acting on a single-word quantity.
  */
@@ -109,7 +114,8 @@ static inline void __change_bit(int nr, volatile unsigned long * addr)
  * @nr: Bit to change
  * @addr: Address to start counting from
  *
- * change_bit() is atomic and may not be reordered.
+ * change_bit() is atomic and may not be reordered. It may be
+ * reordered on other architectures than x86.
  * Note that @nr may be almost arbitrarily large; this function is not
  * restricted to acting on a single-word quantity.
  */
@@ -127,6 +133,7 @@ static inline void change_bit(int nr, volatile unsigned long * addr)
  * @addr: Address to count from
  *
  * This operation is atomic and cannot be reordered.  
+ * It may be reordered on other architectures than x86.
  * It also implies a memory barrier.
  */
 static inline int test_and_set_bit(int nr, volatile unsigned long * addr)
@@ -165,7 +172,8 @@ static inline int __test_and_set_bit(int nr, volatile unsigned long * addr)
  * @nr: Bit to clear
  * @addr: Address to count from
  *
- * This operation is atomic and cannot be reordered.  
+ * This operation is atomic and cannot be reordered.
+ * It can be reorderdered on other architectures other than x86.
  * It also implies a memory barrier.
  */
 static inline int test_and_clear_bit(int nr, volatile unsigned long * addr)
diff --git a/include/asm-i386/bug.h b/include/asm-i386/bug.h
index 433a6e525..c9f0bf343 100644
--- a/include/asm-i386/bug.h
+++ b/include/asm-i386/bug.h
@@ -19,17 +19,7 @@
 #define BUG() __asm__ __volatile__("ud2\n")
 #endif
 
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define PAGE_BUG(page) do { \
-	BUG(); \
-} while (0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-i386/checksum.h b/include/asm-i386/checksum.h
index 96e4b2df8..def093bc8 100644
--- a/include/asm-i386/checksum.h
+++ b/include/asm-i386/checksum.h
@@ -43,10 +43,12 @@ unsigned int csum_partial_copy_nocheck ( const char *src, char *dst,
 }
 
 static __inline__
-unsigned int csum_partial_copy_from_user ( const char __user *src, char *dst,
+unsigned int csum_partial_copy_from_user(const char __user *src, char *dst,
 						int len, int sum, int *err_ptr)
 {
-	return csum_partial_copy_generic ( (__force char *)src, dst, len, sum, err_ptr, NULL);
+	might_sleep();
+	return csum_partial_copy_generic((__force char *)src, dst,
+					len, sum, err_ptr, NULL);
 }
 
 /*
@@ -177,6 +179,7 @@ static __inline__ unsigned int csum_and_copy_to_user(const char *src,
 						     int len, int sum, 
 						     int *err_ptr)
 {
+	might_sleep();
 	if (access_ok(VERIFY_WRITE, dst, len))
 		return csum_partial_copy_generic(src, (__force char *)dst, len, sum, NULL, err_ptr);
 
diff --git a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h
index d6005e6e8..fdbd65ca6 100644
--- a/include/asm-i386/cpufeature.h
+++ b/include/asm-i386/cpufeature.h
@@ -71,9 +71,13 @@
 #define X86_FEATURE_P4		(3*32+ 7) /* P4 */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
-#define X86_FEATURE_EST		(4*32+ 7) /* Enhanced SpeedStep */
+#define X86_FEATURE_XMM3	(4*32+ 0) /* Streaming SIMD Extensions-3 */
 #define X86_FEATURE_MWAIT	(4*32+ 3) /* Monitor/Mwait support */
-
+#define X86_FEATURE_DSCPL	(4*32+ 4) /* CPL Qualified Debug Store */
+#define X86_FEATURE_EST		(4*32+ 7) /* Enhanced SpeedStep */
+#define X86_FEATURE_TM2		(4*32+ 8) /* Thermal Monitor 2 */
+#define X86_FEATURE_CID		(4*32+10) /* Context ID */
+#define X86_FEATURE_XTPR	(4*32+14) /* Send Task Priority Messages */
 
 /* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
 #define X86_FEATURE_XSTORE	(5*32+ 2) /* on-CPU RNG present (xstore insn) */
@@ -92,13 +96,14 @@
 #define cpu_has_tsc		boot_cpu_has(X86_FEATURE_TSC)
 #define cpu_has_pae		boot_cpu_has(X86_FEATURE_PAE)
 #define cpu_has_pge		boot_cpu_has(X86_FEATURE_PGE)
-#define cpu_has_sse2		boot_cpu_has(X86_FEATURE_XMM2)
 #define cpu_has_apic		boot_cpu_has(X86_FEATURE_APIC)
 #define cpu_has_sep		boot_cpu_has(X86_FEATURE_SEP)
 #define cpu_has_mtrr		boot_cpu_has(X86_FEATURE_MTRR)
 #define cpu_has_mmx		boot_cpu_has(X86_FEATURE_MMX)
 #define cpu_has_fxsr		boot_cpu_has(X86_FEATURE_FXSR)
 #define cpu_has_xmm		boot_cpu_has(X86_FEATURE_XMM)
+#define cpu_has_xmm2		boot_cpu_has(X86_FEATURE_XMM2)
+#define cpu_has_xmm3		boot_cpu_has(X86_FEATURE_XMM3)
 #define cpu_has_ht		boot_cpu_has(X86_FEATURE_HT)
 #define cpu_has_mp		boot_cpu_has(X86_FEATURE_MP)
 #define cpu_has_nx		boot_cpu_has(X86_FEATURE_NX)
@@ -106,7 +111,9 @@
 #define cpu_has_cyrix_arr	boot_cpu_has(X86_FEATURE_CYRIX_ARR)
 #define cpu_has_centaur_mcr	boot_cpu_has(X86_FEATURE_CENTAUR_MCR)
 #define cpu_has_xstore		boot_cpu_has(X86_FEATURE_XSTORE)
+#define cpu_has_xstore_enabled	boot_cpu_has(X86_FEATURE_XSTORE_EN)
 #define cpu_has_xcrypt		boot_cpu_has(X86_FEATURE_XCRYPT)
+#define cpu_has_xcrypt_enabled	boot_cpu_has(X86_FEATURE_XCRYPT_EN)
 
 #endif /* __ASM_I386_CPUFEATURE_H */
 
diff --git a/include/asm-i386/desc.h b/include/asm-i386/desc.h
index 5d126f733..3077bafa9 100644
--- a/include/asm-i386/desc.h
+++ b/include/asm-i386/desc.h
@@ -8,10 +8,12 @@
 
 #include <linux/preempt.h>
 #include <linux/smp.h>
+#include <linux/percpu.h>
 
 #include <asm/mmu.h>
 
-extern struct desc_struct cpu_gdt_table[NR_CPUS][GDT_ENTRIES];
+extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
+DECLARE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]);
 
 struct Xgt_desc_struct {
 	unsigned short size;
@@ -44,7 +46,7 @@ __asm__ __volatile__ ("movw %w3,0(%2)\n\t" \
 
 static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, void *addr)
 {
-	_set_tssldt_desc(&cpu_gdt_table[cpu][entry], (int)addr,
+	_set_tssldt_desc(&per_cpu(cpu_gdt_table, cpu)[entry], (int)addr,
 		offsetof(struct tss_struct, __cacheline_filler) - 1, 0x89);
 }
 
@@ -52,7 +54,7 @@ static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, void *ad
 
 static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int size)
 {
-	_set_tssldt_desc(&cpu_gdt_table[cpu][GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82);
+	_set_tssldt_desc(&per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82);
 }
 
 #define LDT_entry_a(info) \
@@ -86,7 +88,7 @@ static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int size)
 
 static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
 {
-#define C(i) cpu_gdt_table[cpu][GDT_ENTRY_TLS_MIN + i] = t->tls_array[i]
+#define C(i) per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i]
 	C(0); C(1); C(2);
 #undef C
 }
diff --git a/include/asm-i386/dma-mapping.h b/include/asm-i386/dma-mapping.h
index 79bfab5cb..8d432bd90 100644
--- a/include/asm-i386/dma-mapping.h
+++ b/include/asm-i386/dma-mapping.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_I386_DMA_MAPPING_H
 #define _ASM_I386_DMA_MAPPING_H
 
-#include <linux/device.h>
 #include <linux/mm.h>
 
 #include <asm/cache.h>
@@ -163,4 +162,16 @@ dma_cache_sync(void *vaddr, size_t size,
 	flush_write_buffers();
 }
 
+#define ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
+extern int
+dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+			    dma_addr_t device_addr, size_t size, int flags);
+
+extern void
+dma_release_declared_memory(struct device *dev);
+
+extern void *
+dma_mark_declared_memory_occupied(struct device *dev,
+				  dma_addr_t device_addr, size_t size);
+
 #endif
diff --git a/include/asm-i386/elf.h b/include/asm-i386/elf.h
index a53f1fc65..1309fd1fd 100644
--- a/include/asm-i386/elf.h
+++ b/include/asm-i386/elf.h
@@ -70,7 +70,7 @@ typedef struct user_fxsr_struct elf_fpxregset_t;
    the loader.  We need to make sure that it is out of the way of the program
    that it will "exec", and that there is sufficient room for the brk.  */
 
-#define ELF_ET_DYN_BASE         (TASK_SIZE / 3 * 2)
+#define ELF_ET_DYN_BASE		((TASK_UNMAPPED_BASE) * 2)
 
 /* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
    now struct_user_regs, they are different) */
@@ -123,7 +123,7 @@ typedef struct user_fxsr_struct elf_fpxregset_t;
  * An executable for which elf_read_implies_exec() returns TRUE will
  * have the READ_IMPLIES_EXEC personality flag set automatically.
  */
-#define elf_read_implies_exec_binary(ex, have_pt_gnu_stack)	(!(have_pt_gnu_stack))
+#define elf_read_implies_exec(ex, have_pt_gnu_stack)	(!(have_pt_gnu_stack))
 
 extern int dump_task_regs (struct task_struct *, elf_gregset_t *);
 extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
diff --git a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h
index 07d4c64ae..805a0dd16 100644
--- a/include/asm-i386/fixmap.h
+++ b/include/asm-i386/fixmap.h
@@ -14,6 +14,15 @@
 #define _ASM_FIXMAP_H
 
 #include <linux/config.h>
+
+/* used by vmalloc.c, vsyscall.lds.S.
+ *
+ * Leave one empty page between vmalloc'ed areas and
+ * the start of the fixmap.
+ */
+#define __FIXADDR_TOP	0xfffff000
+
+#ifndef __ASSEMBLY__
 #include <linux/kernel.h>
 #include <asm/acpi.h>
 #include <asm/apicdef.h>
@@ -97,13 +106,8 @@ extern void __set_fixmap (enum fixed_addresses idx,
 #define clear_fixmap(idx) \
 		__set_fixmap(idx, 0, __pgprot(0))
 
-/*
- * used by vmalloc.c.
- *
- * Leave one empty page between vmalloc'ed areas and
- * the start of the fixmap.
- */
-#define FIXADDR_TOP	(0xfffff000UL)
+#define FIXADDR_TOP	((unsigned long)__FIXADDR_TOP)
+
 #define __FIXADDR_SIZE	(__end_of_permanent_fixed_addresses << PAGE_SHIFT)
 #define FIXADDR_START	(FIXADDR_TOP - __FIXADDR_SIZE)
 
@@ -125,7 +129,7 @@ extern void __this_fixmap_does_not_exist(void);
  * directly without tranlation, we catch the bug with a NULL-deference
  * kernel oops. Illegal ranges of incoming indices are caught too.
  */
-static inline unsigned long fix_to_virt(const unsigned int idx)
+static __always_inline unsigned long fix_to_virt(const unsigned int idx)
 {
 	/*
 	 * this branch gets completely eliminated after inlining,
@@ -148,4 +152,5 @@ static inline unsigned long virt_to_fix(const unsigned long vaddr)
 	return __virt_to_fix(vaddr);
 }
 
+#endif /* !__ASSEMBLY__ */
 #endif
diff --git a/include/asm-i386/hardirq.h b/include/asm-i386/hardirq.h
index 52fe4d993..8f5a07555 100644
--- a/include/asm-i386/hardirq.h
+++ b/include/asm-i386/hardirq.h
@@ -37,20 +37,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -60,30 +46,10 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
-#define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 #define nmi_enter()		(irq_enter())
 #define nmi_exit()		(preempt_count() -= HARDIRQ_OFFSET)
 
-#ifdef CONFIG_PREEMPT
-# include <linux/smp_lock.h>
-# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
+#define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 #define irq_exit()							\
 do {									\
 		preempt_count() -= IRQ_EXIT_OFFSET;			\
@@ -92,10 +58,4 @@ do {									\
 		preempt_enable_no_resched();				\
 } while (0)
 
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else
-  extern void synchronize_irq(unsigned int irq);
-#endif /* CONFIG_SMP */
-
 #endif /* __ASM_HARDIRQ_H */
diff --git a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h
index 25b7baadb..e04162a2a 100644
--- a/include/asm-i386/hw_irq.h
+++ b/include/asm-i386/hw_irq.h
@@ -68,46 +68,6 @@ extern atomic_t irq_mis_count;
 
 #define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs))
 
-/*
- * The profiling function is SMP safe. (nothing can mess
- * around with "current", and the profiling counters are
- * updated with atomic operations). This is especially
- * useful with a profiling multiplier != 1
- */
-static inline void x86_do_profile(struct pt_regs * regs)
-{
-	unsigned long eip;
-	extern unsigned long prof_cpu_mask;
- 
-	profile_hook(regs);
- 
-	if (user_mode(regs))
-		return;
- 
-	if (!prof_buffer)
-		return;
-
-	eip = regs->eip;
- 
-	/*
-	 * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
-	 * (default is all CPUs.)
-	 */
-	if (!((1<<smp_processor_id()) & prof_cpu_mask))
-		return;
-
-	eip -= (unsigned long)_stext;
-	eip >>= prof_shift;
-	/*
-	 * Don't ignore out-of-bounds EIP values silently,
-	 * put them into the last histogram slot, so if
-	 * present, they will show up as a sharp peak.
-	 */
-	if (eip > prof_len-1)
-		eip = prof_len-1;
-	atomic_inc((atomic_t *)&prof_buffer[eip]);
-}
- 
 #if defined(CONFIG_X86_IO_APIC)
 static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i)
 {
diff --git a/include/asm-i386/io.h b/include/asm-i386/io.h
index 1d9fa560d..083e3b8f8 100644
--- a/include/asm-i386/io.h
+++ b/include/asm-i386/io.h
@@ -2,6 +2,8 @@
 #define _ASM_IO_H
 
 #include <linux/config.h>
+#include <linux/string.h>
+#include <linux/compiler.h>
 
 /*
  * This file contains the definitions for the x86 IO instructions
@@ -43,6 +45,8 @@
 
 #ifdef __KERNEL__
 
+#include <asm-generic/iomap.h>
+
 #include <linux/vmalloc.h>
 
 /**
@@ -86,7 +90,7 @@ static inline void * phys_to_virt(unsigned long address)
  */
 #define page_to_phys(page)    ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
 
-extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
+extern void __iomem * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
 
 /**
  * ioremap     -   map bus memory into CPU space
@@ -100,13 +104,13 @@ extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long
  * address. 
  */
 
-static inline void * ioremap (unsigned long offset, unsigned long size)
+static inline void __iomem * ioremap(unsigned long offset, unsigned long size)
 {
 	return __ioremap(offset, size, 0);
 }
 
-extern void * ioremap_nocache (unsigned long offset, unsigned long size);
-extern void iounmap(void *addr);
+extern void __iomem * ioremap_nocache(unsigned long offset, unsigned long size);
+extern void iounmap(volatile void __iomem *addr);
 
 /*
  * bt_ioremap() and bt_iounmap() are for temporary early boot-time
@@ -139,9 +143,18 @@ extern void bt_iounmap(void *addr, unsigned long size);
  * memory location directly.
  */
 
-#define readb(addr) (*(volatile unsigned char *) (addr))
-#define readw(addr) (*(volatile unsigned short *) (addr))
-#define readl(addr) (*(volatile unsigned int *) (addr))
+static inline unsigned char readb(const volatile void __iomem *addr)
+{
+	return *(volatile unsigned char __force *) addr;
+}
+static inline unsigned short readw(const volatile void __iomem *addr)
+{
+	return *(volatile unsigned short __force *) addr;
+}
+static inline unsigned int readl(const volatile void __iomem *addr)
+{
+	return *(volatile unsigned int __force *) addr;
+}
 #define readb_relaxed(addr) readb(addr)
 #define readw_relaxed(addr) readw(addr)
 #define readl_relaxed(addr) readl(addr)
@@ -149,16 +162,34 @@ extern void bt_iounmap(void *addr, unsigned long size);
 #define __raw_readw readw
 #define __raw_readl readl
 
-#define writeb(b,addr) (*(volatile unsigned char *) (addr) = (b))
-#define writew(b,addr) (*(volatile unsigned short *) (addr) = (b))
-#define writel(b,addr) (*(volatile unsigned int *) (addr) = (b))
+static inline void writeb(unsigned char b, volatile void __iomem *addr)
+{
+	*(volatile unsigned char __force *) addr = b;
+}
+static inline void writew(unsigned short b, volatile void __iomem *addr)
+{
+	*(volatile unsigned short __force *) addr = b;
+}
+static inline void writel(unsigned int b, volatile void __iomem *addr)
+{
+	*(volatile unsigned int __force *) addr = b;
+}
 #define __raw_writeb writeb
 #define __raw_writew writew
 #define __raw_writel writel
 
-#define memset_io(a,b,c)	memset((void *)(a),(b),(c))
-#define memcpy_fromio(a,b,c)	__memcpy((a),(void *)(b),(c))
-#define memcpy_toio(a,b,c)	__memcpy((void *)(a),(b),(c))
+static inline void memset_io(volatile void __iomem *addr, unsigned char val, int count)
+{
+	memset((void __force *) addr, val, count);
+}
+static inline void memcpy_fromio(void *dst, volatile void __iomem *src, int count)
+{
+	__memcpy(dst, (void __force *) src, count);
+}
+static inline void memcpy_toio(volatile void __iomem *dst, const void *src, int count)
+{
+	__memcpy((void __force *) dst, src, count);
+}
 
 /*
  * ISA space is 'always mapped' on a typical x86 system, no need to
@@ -168,7 +199,7 @@ extern void bt_iounmap(void *addr, unsigned long size);
  * used as the IO-area pointer (it can be iounmapped as well, so the
  * analogy with PCI is quite large):
  */
-#define __ISA_IO_base ((char *)(PAGE_OFFSET))
+#define __ISA_IO_base ((char __iomem *)(PAGE_OFFSET))
 
 #define isa_readb(a) readb(__ISA_IO_base + (a))
 #define isa_readw(a) readw(__ISA_IO_base + (a))
@@ -185,8 +216,8 @@ extern void bt_iounmap(void *addr, unsigned long size);
  * Again, i386 does not require mem IO specific function.
  */
 
-#define eth_io_copy_and_sum(a,b,c,d)		eth_copy_and_sum((a),(void *)(b),(c),(d))
-#define isa_eth_io_copy_and_sum(a,b,c,d)	eth_copy_and_sum((a),(void *)(__ISA_IO_base + (b)),(c),(d))
+#define eth_io_copy_and_sum(a,b,c,d)		eth_copy_and_sum((a),(void __force *)(b),(c),(d))
+#define isa_eth_io_copy_and_sum(a,b,c,d)	eth_copy_and_sum((a),(void __force *)(__ISA_IO_base + (b)),(c),(d))
 
 /**
  *	check_signature		-	find BIOS signatures
@@ -199,7 +230,7 @@ extern void bt_iounmap(void *addr, unsigned long size);
  *	Returns 1 on a match.
  */
  
-static inline int check_signature(unsigned long io_addr,
+static inline int check_signature(volatile void __iomem * io_addr,
 	const unsigned char *signature, int length)
 {
 	int retval = 0;
diff --git a/include/asm-i386/linkage.h b/include/asm-i386/linkage.h
index e48009fd9..af3d8571c 100644
--- a/include/asm-i386/linkage.h
+++ b/include/asm-i386/linkage.h
@@ -5,6 +5,10 @@
 #define FASTCALL(x)	x __attribute__((regparm(3)))
 #define fastcall	__attribute__((regparm(3)))
 
+#ifdef CONFIG_REGPARM
+# define prevent_tail_call(ret) __asm__ ("" : "=r" (ret) : "0" (ret))
+#endif
+
 #ifdef CONFIG_X86_ALIGNMENT_16
 #define __ALIGN .align 16,0x90
 #define __ALIGN_STR ".align 16,0x90"
diff --git a/include/asm-i386/mach-bigsmp/mach_ipi.h b/include/asm-i386/mach-bigsmp/mach_ipi.h
index 4cb4ba486..9404c535b 100644
--- a/include/asm-i386/mach-bigsmp/mach_ipi.h
+++ b/include/asm-i386/mach-bigsmp/mach_ipi.h
@@ -1,7 +1,7 @@
 #ifndef __ASM_MACH_IPI_H
 #define __ASM_MACH_IPI_H
 
-inline void send_IPI_mask_sequence(cpumask_t mask, int vector);
+void send_IPI_mask_sequence(cpumask_t mask, int vector);
 
 static inline void send_IPI_mask(cpumask_t mask, int vector)
 {
diff --git a/include/asm-i386/mach-default/do_timer.h b/include/asm-i386/mach-default/do_timer.h
index 8ac79726f..9eb6c9dde 100644
--- a/include/asm-i386/mach-default/do_timer.h
+++ b/include/asm-i386/mach-default/do_timer.h
@@ -22,7 +22,7 @@ static inline void do_timer_interrupt_hook(struct pt_regs *regs)
  * system, in that case we have to call the local interrupt handler.
  */
 #ifndef CONFIG_X86_LOCAL_APIC
-	x86_do_profile(regs);
+	profile_tick(CPU_PROFILING, regs);
 #else
 	if (!using_apic_timer)
 		smp_local_timer_interrupt(regs);
diff --git a/include/asm-i386/mach-default/mach_ipi.h b/include/asm-i386/mach-default/mach_ipi.h
index d41949849..6f2b17a20 100644
--- a/include/asm-i386/mach-default/mach_ipi.h
+++ b/include/asm-i386/mach-default/mach_ipi.h
@@ -1,8 +1,8 @@
 #ifndef __ASM_MACH_IPI_H
 #define __ASM_MACH_IPI_H
 
-inline void send_IPI_mask_bitmask(cpumask_t mask, int vector);
-inline void __send_IPI_shortcut(unsigned int shortcut, int vector);
+void send_IPI_mask_bitmask(cpumask_t mask, int vector);
+void __send_IPI_shortcut(unsigned int shortcut, int vector);
 
 static inline void send_IPI_mask(cpumask_t mask, int vector)
 {
diff --git a/include/asm-i386/mach-es7000/mach_ipi.h b/include/asm-i386/mach-es7000/mach_ipi.h
index cb8a2fdb5..5e61bd220 100644
--- a/include/asm-i386/mach-es7000/mach_ipi.h
+++ b/include/asm-i386/mach-es7000/mach_ipi.h
@@ -1,7 +1,7 @@
 #ifndef __ASM_MACH_IPI_H
 #define __ASM_MACH_IPI_H
 
-inline void send_IPI_mask_sequence(cpumask_t mask, int vector);
+void send_IPI_mask_sequence(cpumask_t mask, int vector);
 
 static inline void send_IPI_mask(cpumask_t mask, int vector)
 {
diff --git a/include/asm-i386/mach-es7000/mach_mpparse.h b/include/asm-i386/mach-es7000/mach_mpparse.h
index 0aae26413..85809e089 100644
--- a/include/asm-i386/mach-es7000/mach_mpparse.h
+++ b/include/asm-i386/mach-es7000/mach_mpparse.h
@@ -21,7 +21,8 @@ static inline int mps_oem_check(struct mp_config_table *mpc, char *oem,
 	if (mpc->mpc_oemptr) {
 		struct mp_config_oemtable *oem_table = 
 			(struct mp_config_oemtable *)mpc->mpc_oemptr;
-		return parse_unisys_oem((char *)oem_table, oem_table->oem_length);
+		if (!strncmp(oem, "UNISYS", 6))
+			return parse_unisys_oem((char *)oem_table, oem_table->oem_length);
 	}
 	return 0;
 }
diff --git a/include/asm-i386/mach-es7000/mach_mpspec.h b/include/asm-i386/mach-es7000/mach_mpspec.h
index 6b5dadcf1..b1f5039d4 100644
--- a/include/asm-i386/mach-es7000/mach_mpspec.h
+++ b/include/asm-i386/mach-es7000/mach_mpspec.h
@@ -3,6 +3,6 @@
 
 #define MAX_IRQ_SOURCES 256
 
-#define MAX_MP_BUSSES 32
+#define MAX_MP_BUSSES 256
 
 #endif /* __ASM_MACH_MPSPEC_H */
diff --git a/include/asm-i386/mach-numaq/mach_ipi.h b/include/asm-i386/mach-numaq/mach_ipi.h
index 29aabcd99..1b46fd3f2 100644
--- a/include/asm-i386/mach-numaq/mach_ipi.h
+++ b/include/asm-i386/mach-numaq/mach_ipi.h
@@ -1,7 +1,7 @@
 #ifndef __ASM_MACH_IPI_H
 #define __ASM_MACH_IPI_H
 
-static inline void send_IPI_mask_sequence(cpumask_t, int vector);
+inline void send_IPI_mask_sequence(cpumask_t, int vector);
 
 static inline void send_IPI_mask(cpumask_t mask, int vector)
 {
diff --git a/include/asm-i386/mach-summit/mach_apic.h b/include/asm-i386/mach-summit/mach_apic.h
index 214263a48..74e9cbc8c 100644
--- a/include/asm-i386/mach-summit/mach_apic.h
+++ b/include/asm-i386/mach-summit/mach_apic.h
@@ -19,11 +19,15 @@
 
 static inline cpumask_t target_cpus(void)
 {
-	return CPU_MASK_ALL;
+	/* CPU_MASK_ALL (0xff) has undefined behaviour with
+	 * dest_LowestPrio mode logical clustered apic interrupt routing
+	 * Just start on cpu 0.  IRQ balancing will spread load
+	 */
+	return cpumask_of_cpu(0);
 } 
 #define TARGET_CPUS	(target_cpus())
 
-#define INT_DELIVERY_MODE (dest_Fixed)
+#define INT_DELIVERY_MODE (dest_LowestPrio)
 #define INT_DEST_MODE 1     /* logical delivery broadcast to all procs */
 
 static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid)
diff --git a/include/asm-i386/mach-summit/mach_ipi.h b/include/asm-i386/mach-summit/mach_ipi.h
index 4cb4ba486..9404c535b 100644
--- a/include/asm-i386/mach-summit/mach_ipi.h
+++ b/include/asm-i386/mach-summit/mach_ipi.h
@@ -1,7 +1,7 @@
 #ifndef __ASM_MACH_IPI_H
 #define __ASM_MACH_IPI_H
 
-inline void send_IPI_mask_sequence(cpumask_t mask, int vector);
+void send_IPI_mask_sequence(cpumask_t mask, int vector);
 
 static inline void send_IPI_mask(cpumask_t mask, int vector)
 {
diff --git a/include/asm-i386/mach-visws/do_timer.h b/include/asm-i386/mach-visws/do_timer.h
index 24d510a2f..172873269 100644
--- a/include/asm-i386/mach-visws/do_timer.h
+++ b/include/asm-i386/mach-visws/do_timer.h
@@ -15,7 +15,7 @@ static inline void do_timer_interrupt_hook(struct pt_regs *regs)
  * system, in that case we have to call the local interrupt handler.
  */
 #ifndef CONFIG_X86_LOCAL_APIC
-	x86_do_profile(regs);
+	profile_tick(CPU_PROFILING, regs);
 #else
 	if (!using_apic_timer)
 		smp_local_timer_interrupt(regs);
diff --git a/include/asm-i386/mach-visws/mach_apic.h b/include/asm-i386/mach-visws/mach_apic.h
index c367d820f..4e6cdfb8b 100644
--- a/include/asm-i386/mach-visws/mach_apic.h
+++ b/include/asm-i386/mach-visws/mach_apic.h
@@ -2,6 +2,7 @@
 #define __ASM_MACH_APIC_H
 
 #include <mach_apicdef.h>
+#include <asm/smp.h>
 
 #define APIC_DFR_VALUE	(APIC_DFR_FLAT)
 
diff --git a/include/asm-i386/mmu_context.h b/include/asm-i386/mmu_context.h
index 99cff6506..bf0821835 100644
--- a/include/asm-i386/mmu_context.h
+++ b/include/asm-i386/mmu_context.h
@@ -18,8 +18,8 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
 #ifdef CONFIG_SMP
 	unsigned cpu = smp_processor_id();
-	if (cpu_tlbstate[cpu].state == TLBSTATE_OK)
-		cpu_tlbstate[cpu].state = TLBSTATE_LAZY;	
+	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK)
+		per_cpu(cpu_tlbstate, cpu).state = TLBSTATE_LAZY;
 #endif
 }
 
@@ -33,8 +33,8 @@ static inline void switch_mm(struct mm_struct *prev,
 		/* stop flush ipis for the previous mm */
 		cpu_clear(cpu, prev->cpu_vm_mask);
 #ifdef CONFIG_SMP
-		cpu_tlbstate[cpu].state = TLBSTATE_OK;
-		cpu_tlbstate[cpu].active_mm = next;
+		per_cpu(cpu_tlbstate, cpu).state = TLBSTATE_OK;
+		per_cpu(cpu_tlbstate, cpu).active_mm = next;
 #endif
 		cpu_set(cpu, next->cpu_vm_mask);
 
@@ -49,8 +49,8 @@ static inline void switch_mm(struct mm_struct *prev,
 	}
 #ifdef CONFIG_SMP
 	else {
-		cpu_tlbstate[cpu].state = TLBSTATE_OK;
-		BUG_ON(cpu_tlbstate[cpu].active_mm != next);
+		per_cpu(cpu_tlbstate, cpu).state = TLBSTATE_OK;
+		BUG_ON(per_cpu(cpu_tlbstate, cpu).active_mm != next);
 
 		if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) {
 			/* We were in lazy tlb mode and leave_mm disabled 
diff --git a/include/asm-i386/mtrr.h b/include/asm-i386/mtrr.h
index 46c5561cb..5b6ceda68 100644
--- a/include/asm-i386/mtrr.h
+++ b/include/asm-i386/mtrr.h
@@ -67,8 +67,6 @@ struct mtrr_gentry
 
 #ifdef __KERNEL__
 
-extern char *mtrr_strings[]; 
-
 /*  The following functions are for use by other drivers  */
 # ifdef CONFIG_MTRR
 extern int mtrr_add (unsigned long base, unsigned long size,
diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h
index eb0e11f10..527578b79 100644
--- a/include/asm-i386/page.h
+++ b/include/asm-i386/page.h
@@ -94,13 +94,13 @@ typedef struct { unsigned long pgprot; } pgprot_t;
  * and CONFIG_HIGHMEM64G options in the kernel configuration.
  */
 
+#ifndef __ASSEMBLY__
+
 /*
  * This much address space is reserved for vmalloc() and iomap()
  * as well as fixmap mappings.
  */
-#define __VMALLOC_RESERVE	(128 << 20)
-
-#ifndef __ASSEMBLY__
+extern unsigned int __VMALLOC_RESERVE;
 
 /* Pure 2^n version of get_order */
 static __inline__ int get_order(unsigned long size)
@@ -116,18 +116,27 @@ static __inline__ int get_order(unsigned long size)
 	return order;
 }
 
+extern int sysctl_legacy_va_layout;
+
 #endif /* __ASSEMBLY__ */
 
-#ifdef __ASSEMBLY__
+#if   defined(CONFIG_SPLIT_3GB)
 #define __PAGE_OFFSET		(0xC0000000)
-#else
-#define __PAGE_OFFSET		(0xC0000000UL)
+#elif defined(CONFIG_SPLIT_25GB)
+#define __PAGE_OFFSET		(0xA0000000)
+#elif defined(CONFIG_SPLIT_2GB)
+#define __PAGE_OFFSET		(0x80000000)
+#elif defined(CONFIG_SPLIT_15GB)
+#define __PAGE_OFFSET		(0x60000000)
+#elif defined(CONFIG_SPLIT_1GB)
+#define __PAGE_OFFSET		(0x40000000)
 #endif
 
-
 #define PAGE_OFFSET		((unsigned long)__PAGE_OFFSET)
 #define VMALLOC_RESERVE		((unsigned long)__VMALLOC_RESERVE)
-#define MAXMEM			(-__PAGE_OFFSET-__VMALLOC_RESERVE)
+#define __MAXMEM		(-__PAGE_OFFSET-__VMALLOC_RESERVE)
+#define MAXMEM			((unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE))
+
 #define __pa(x)			((unsigned long)(x)-PAGE_OFFSET)
 #define __va(x)			((void *)((unsigned long)(x)+PAGE_OFFSET))
 #define pfn_to_kaddr(pfn)      __va((pfn) << PAGE_SHIFT)
diff --git a/include/asm-i386/pgtable-2level.h b/include/asm-i386/pgtable-2level.h
index de5111056..58867b62f 100644
--- a/include/asm-i386/pgtable-2level.h
+++ b/include/asm-i386/pgtable-2level.h
@@ -75,4 +75,11 @@ static inline int pte_exec_kernel(pte_t pte)
 #define pgoff_to_pte(off) \
 	((pte_t) { (((off) & 0x1f) << 1) + (((off) >> 5) << 8) + _PAGE_FILE })
 
+/* Encode and de-code a swap entry */
+#define __swp_type(x)			(((x).val >> 1) & 0x1f)
+#define __swp_offset(x)			((x).val >> 8)
+#define __swp_entry(type, offset)	((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
+#define __pte_to_swp_entry(pte)		((swp_entry_t) { (pte).pte_low })
+#define __swp_entry_to_pte(x)		((pte_t) { (x).val })
+
 #endif /* _I386_PGTABLE_2LEVEL_H */
diff --git a/include/asm-i386/pgtable-3level.h b/include/asm-i386/pgtable-3level.h
index d78e3493d..80a24b01d 100644
--- a/include/asm-i386/pgtable-3level.h
+++ b/include/asm-i386/pgtable-3level.h
@@ -54,6 +54,7 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
 	smp_wmb();
 	ptep->pte_low = pte.pte_low;
 }
+#define __HAVE_ARCH_SET_PTE_ATOMIC
 #define set_pte_atomic(pteptr,pteval) \
 		set_64bit((unsigned long long *)(pteptr),pte_val(pteval))
 #define set_pmd(pmdptr,pmdval) \
@@ -134,4 +135,11 @@ static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
 #define pgoff_to_pte(off) ((pte_t) { _PAGE_FILE, (off) })
 #define PTE_FILE_MAX_BITS       32
 
+/* Encode and de-code a swap entry */
+#define __swp_type(x)			(((x).val) & 0x1f)
+#define __swp_offset(x)			((x).val >> 5)
+#define __swp_entry(type, offset)	((swp_entry_t){(type) | (offset) << 5})
+#define __pte_to_swp_entry(pte)		((swp_entry_t){ (pte).pte_high })
+#define __swp_entry_to_pte(x)		((pte_t){ 0, (x).val })
+
 #endif /* _I386_PGTABLE_3LEVEL_H */
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
index 8f9fcab61..b4ba1fd6f 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -398,13 +398,6 @@ extern pte_t *lookup_address(unsigned long address);
 		}							  \
 	} while (0)
 
-/* Encode and de-code a swap entry */
-#define __swp_type(x)			(((x).val >> 1) & 0x1f)
-#define __swp_offset(x)			((x).val >> 8)
-#define __swp_entry(type, offset)	((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
-#define __pte_to_swp_entry(pte)		((swp_entry_t) { (pte).pte_low })
-#define __swp_entry_to_pte(x)		((pte_t) { (x).val })
-
 #endif /* !__ASSEMBLY__ */
 
 #ifndef CONFIG_DISCONTIGMEM
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 6fcdb7d1d..e4165087e 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -19,6 +19,7 @@
 #include <linux/cache.h>
 #include <linux/config.h>
 #include <linux/threads.h>
+#include <asm/percpu.h>
 
 /* flag for disabling the tsc */
 extern int tsc_disable;
@@ -84,8 +85,8 @@ struct cpuinfo_x86 {
 
 extern struct cpuinfo_x86 boot_cpu_data;
 extern struct cpuinfo_x86 new_cpu_data;
-extern struct tss_struct init_tss[NR_CPUS];
 extern struct tss_struct doublefault_tss;
+DECLARE_PER_CPU(struct tss_struct, init_tss);
 
 #ifdef CONFIG_SMP
 extern struct cpuinfo_x86 cpu_data[];
@@ -287,15 +288,18 @@ extern unsigned int BIOS_revision;
 extern unsigned int mca_pentium_flag;
 
 /*
- * User space process size: 3GB (default).
+ * User space process size: (3GB default).
  */
-#define TASK_SIZE	(PAGE_OFFSET)
+#define __TASK_SIZE		(__PAGE_OFFSET)
+#define TASK_SIZE		((unsigned long)__TASK_SIZE)
 
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
 #define TASK_UNMAPPED_BASE	(PAGE_ALIGN(TASK_SIZE / 3))
 
+#define HAVE_ARCH_PICK_MMAP_LAYOUT
+
 /*
  * Size of io_bitmap.
  */
@@ -304,6 +308,7 @@ extern unsigned int mca_pentium_flag;
 #define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long))
 #define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap)
 #define INVALID_IO_BITMAP_OFFSET 0x8000
+#define INVALID_IO_BITMAP_OFFSET_LAZY 0x9000
 
 struct i387_fsave_struct {
 	long	cwd;
@@ -357,6 +362,8 @@ typedef struct {
 	unsigned long seg;
 } mm_segment_t;
 
+struct thread_struct;
+
 struct tss_struct {
 	unsigned short	back_link,__blh;
 	unsigned long	esp0;
@@ -388,10 +395,15 @@ struct tss_struct {
 	 * be within the limit.
 	 */
 	unsigned long	io_bitmap[IO_BITMAP_LONGS + 1];
+	/*
+	 * Cache the current maximum and the last task that used the bitmap:
+	 */
+	unsigned long io_bitmap_max;
+	struct thread_struct *io_bitmap_owner;
 	/*
 	 * pads the TSS to be cacheline-aligned (size is 0x100)
 	 */
-	unsigned long __cacheline_filler[37];
+	unsigned long __cacheline_filler[35];
 	/*
 	 * .. and then another 0x100 bytes for emergency kernel stack
 	 */
@@ -422,6 +434,8 @@ struct thread_struct {
 	unsigned int		saved_fs, saved_gs;
 /* IO permissions */
 	unsigned long	*io_bitmap_ptr;
+/* max allowed port in the bitmap, in bytes: */
+	unsigned long	io_bitmap_max;
 };
 
 #define INIT_THREAD  {							\
@@ -439,7 +453,6 @@ struct thread_struct {
 #define INIT_TSS  {							\
 	.esp0		= sizeof(init_stack) + (long)&init_stack,	\
 	.ss0		= __KERNEL_DS,					\
-	.esp1		= sizeof(init_tss[0]) + (long)&init_tss[0],	\
 	.ss1		= __KERNEL_CS,					\
 	.ldt		= GDT_ENTRY_LDT,				\
 	.io_bitmap_base	= INVALID_IO_BITMAP_OFFSET,			\
@@ -645,9 +658,4 @@ extern void select_idle_routine(const struct cpuinfo_x86 *c);
 
 #define cache_line_size() (boot_cpu_data.x86_cache_alignment)
 
-#ifdef CONFIG_SCHED_SMT
-#define ARCH_HAS_SCHED_DOMAIN
-#define ARCH_HAS_SCHED_WAKE_IDLE
-#endif
-
 #endif /* __ASM_I386_PROCESSOR_H */
diff --git a/include/asm-i386/ptrace.h b/include/asm-i386/ptrace.h
index d80fd6557..2d673afe7 100644
--- a/include/asm-i386/ptrace.h
+++ b/include/asm-i386/ptrace.h
@@ -57,6 +57,11 @@ struct pt_regs {
 #ifdef __KERNEL__
 #define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs))
 #define instruction_pointer(regs) ((regs)->eip)
+#if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER)
+extern unsigned long profile_pc(struct pt_regs *regs);
+#else
+#define profile_pc(regs) instruction_pointer(regs)
+#endif
 #endif
 
 #endif
diff --git a/include/asm-i386/resource.h b/include/asm-i386/resource.h
index 3e391b2e9..5c3505a4a 100644
--- a/include/asm-i386/resource.h
+++ b/include/asm-i386/resource.h
@@ -40,7 +40,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
-	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff --git a/include/asm-i386/rwlock.h b/include/asm-i386/rwlock.h
index 291091dda..b57cc7afd 100644
--- a/include/asm-i386/rwlock.h
+++ b/include/asm-i386/rwlock.h
@@ -22,25 +22,19 @@
 
 #define __build_read_lock_ptr(rw, helper)   \
 	asm volatile(LOCK "subl $1,(%0)\n\t" \
-		     "js 2f\n" \
+		     "jns 1f\n" \
+		     "call " helper "\n\t" \
 		     "1:\n" \
-		     LOCK_SECTION_START("") \
-		     "2:\tcall " helper "\n\t" \
-		     "jmp 1b\n" \
-		     LOCK_SECTION_END \
 		     ::"a" (rw) : "memory")
 
 #define __build_read_lock_const(rw, helper)   \
 	asm volatile(LOCK "subl $1,%0\n\t" \
-		     "js 2f\n" \
-		     "1:\n" \
-		     LOCK_SECTION_START("") \
-		     "2:\tpushl %%eax\n\t" \
+		     "jns 1f\n" \
+		     "pushl %%eax\n\t" \
 		     "leal %0,%%eax\n\t" \
 		     "call " helper "\n\t" \
 		     "popl %%eax\n\t" \
-		     "jmp 1b\n" \
-		     LOCK_SECTION_END \
+		     "1:\n" \
 		     :"=m" (*(volatile int *)rw) : : "memory")
 
 #define __build_read_lock(rw, helper)	do { \
@@ -52,25 +46,19 @@
 
 #define __build_write_lock_ptr(rw, helper) \
 	asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \
-		     "jnz 2f\n" \
+		     "jz 1f\n" \
+		     "call " helper "\n\t" \
 		     "1:\n" \
-		     LOCK_SECTION_START("") \
-		     "2:\tcall " helper "\n\t" \
-		     "jmp 1b\n" \
-		     LOCK_SECTION_END \
 		     ::"a" (rw) : "memory")
 
 #define __build_write_lock_const(rw, helper) \
 	asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",%0\n\t" \
-		     "jnz 2f\n" \
-		     "1:\n" \
-		     LOCK_SECTION_START("") \
-		     "2:\tpushl %%eax\n\t" \
+		     "jz 1f\n" \
+		     "pushl %%eax\n\t" \
 		     "leal %0,%%eax\n\t" \
 		     "call " helper "\n\t" \
 		     "popl %%eax\n\t" \
-		     "jmp 1b\n" \
-		     LOCK_SECTION_END \
+		     "1:\n" \
 		     :"=m" (*(volatile int *)rw) : : "memory")
 
 #define __build_write_lock(rw, helper)	do { \
diff --git a/include/asm-i386/semaphore.h b/include/asm-i386/semaphore.h
index 986da200e..1db03a686 100644
--- a/include/asm-i386/semaphore.h
+++ b/include/asm-i386/semaphore.h
@@ -45,21 +45,15 @@ struct semaphore {
 	atomic_t count;
 	int sleepers;
 	wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (int)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
 
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.sleepers	= 0,						\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name,1)
@@ -81,9 +75,6 @@ static inline void sema_init (struct semaphore *sem, int val)
 	atomic_set(&sem->count, val);
 	sem->sleepers = 0;
 	init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-	sem->__magic = (int)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -113,9 +104,6 @@ asmlinkage void __up(struct semaphore * sem);
  */
 static inline void down(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	__asm__ __volatile__(
 		"# atomic down operation\n\t"
@@ -139,9 +127,6 @@ static inline int down_interruptible(struct semaphore * sem)
 {
 	int result;
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	__asm__ __volatile__(
 		"# atomic interruptible down operation\n\t"
@@ -167,10 +152,6 @@ static inline int down_trylock(struct semaphore * sem)
 {
 	int result;
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	__asm__ __volatile__(
 		"# atomic interruptible down operation\n\t"
 		LOCK "decl %1\n\t"     /* --sem->count */
@@ -195,9 +176,6 @@ static inline int down_trylock(struct semaphore * sem)
  */
 static inline void up(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	__asm__ __volatile__(
 		"# atomic up operation\n\t"
 		LOCK "incl %0\n\t"     /* ++sem->count */
diff --git a/include/asm-i386/smp.h b/include/asm-i386/smp.h
index 88c461e5e..ba7eccc97 100644
--- a/include/asm-i386/smp.h
+++ b/include/asm-i386/smp.h
@@ -43,6 +43,7 @@ extern void (*mtrr_hook) (void);
 extern void zap_low_mappings (void);
 
 #define MAX_APICID 256
+extern u8 x86_cpu_to_apicid[];
 
 /*
  * This function is needed by all SMP systems. It must _always_ be valid
diff --git a/include/asm-i386/socket.h b/include/asm-i386/socket.h
index 711f90619..07f6b38ad 100644
--- a/include/asm-i386/socket.h
+++ b/include/asm-i386/socket.h
@@ -47,20 +47,4 @@
 
 #define SO_PEERSEC		31
 
-/* Nasty libc5 fixup - bletch */
-#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h
index d6dbfd469..89ad2d7b5 100644
--- a/include/asm-i386/spinlock.h
+++ b/include/asm-i386/spinlock.h
@@ -46,20 +46,18 @@ typedef struct {
 #define spin_lock_string \
 	"\n1:\t" \
 	"lock ; decb %0\n\t" \
-	"js 2f\n" \
-	LOCK_SECTION_START("") \
+	"jns 3f\n" \
 	"2:\t" \
 	"rep;nop\n\t" \
 	"cmpb $0,%0\n\t" \
 	"jle 2b\n\t" \
 	"jmp 1b\n" \
-	LOCK_SECTION_END
+	"3:\n\t"
 
 #define spin_lock_string_flags \
 	"\n1:\t" \
 	"lock ; decb %0\n\t" \
-	"js 2f\n\t" \
-	LOCK_SECTION_START("") \
+	"jns 4f\n\t" \
 	"2:\t" \
 	"testl $0x200, %1\n\t" \
 	"jz 3f\n\t" \
@@ -70,7 +68,7 @@ typedef struct {
 	"jle 3b\n\t" \
 	"cli\n\t" \
 	"jmp 1b\n" \
-	LOCK_SECTION_END
+	"4:\n\t"
 
 /*
  * This works. Despite all the confusion.
@@ -130,10 +128,8 @@ static inline int _raw_spin_trylock(spinlock_t *lock)
 static inline void _raw_spin_lock(spinlock_t *lock)
 {
 #ifdef CONFIG_DEBUG_SPINLOCK
-	__label__ here;
-here:
 	if (unlikely(lock->magic != SPINLOCK_MAGIC)) {
-		printk("eip: %p\n", &&here);
+		printk("eip: %p\n", __builtin_return_address(0));
 		BUG();
 	}
 #endif
@@ -145,10 +141,8 @@ here:
 static inline void _raw_spin_lock_flags (spinlock_t *lock, unsigned long flags)
 {
 #ifdef CONFIG_DEBUG_SPINLOCK
-	__label__ here;
-here:
 	if (unlikely(lock->magic != SPINLOCK_MAGIC)) {
-		printk("eip: %p\n", &&here);
+		printk("eip: %p\n", __builtin_return_address(0));
 		BUG();
 	}
 #endif
diff --git a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
index 4ef147f97..93460648d 100644
--- a/include/asm-i386/thread_info.h
+++ b/include/asm-i386/thread_info.h
@@ -157,7 +157,7 @@ static inline unsigned long current_stack_pointer(void)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK \
-  (0x0000FFFF & ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT))
+  (0x0000FFFF & ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP))
 #define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
 
 /*
diff --git a/include/asm-i386/timer.h b/include/asm-i386/timer.h
index 585d947ca..24381b8b5 100644
--- a/include/asm-i386/timer.h
+++ b/include/asm-i386/timer.h
@@ -28,6 +28,7 @@ struct timer_opts{
 
 extern struct timer_opts* select_timer(void);
 extern void clock_fallback(void);
+void setup_pit_timer(void);
 
 /* Modifiers for buggy PIT handling */
 
diff --git a/include/asm-i386/timex.h b/include/asm-i386/timex.h
index e73772931..6d5d757b1 100644
--- a/include/asm-i386/timex.h
+++ b/include/asm-i386/timex.h
@@ -7,7 +7,7 @@
 #define _ASMi386_TIMEX_H
 
 #include <linux/config.h>
-#include <asm/msr.h>
+#include <asm/processor.h>
 
 #ifdef CONFIG_X86_ELAN
 #  define CLOCK_TICK_RATE 1189200 /* AMD Elan has different frequency! */
@@ -40,14 +40,17 @@ extern cycles_t cacheflush_time;
 
 static inline cycles_t get_cycles (void)
 {
+	unsigned long long ret=0;
+
 #ifndef CONFIG_X86_TSC
-	return 0;
-#else
-	unsigned long long ret;
+	if (!cpu_has_tsc)
+		return 0;
+#endif
 
+#if defined(CONFIG_X86_GENERIC) || defined(CONFIG_X86_TSC)
 	rdtscll(ret);
-	return ret;
 #endif
+	return ret;
 }
 
 extern unsigned long cpu_khz;
diff --git a/include/asm-i386/tlbflush.h b/include/asm-i386/tlbflush.h
index 2f4c8ee2c..f22fab0ce 100644
--- a/include/asm-i386/tlbflush.h
+++ b/include/asm-i386/tlbflush.h
@@ -131,7 +131,7 @@ struct tlb_state
 	int state;
 	char __cacheline_padding[L1_CACHE_BYTES-8];
 };
-extern struct tlb_state cpu_tlbstate[NR_CPUS];
+DECLARE_PER_CPU(struct tlb_state, cpu_tlbstate);
 
 
 #endif
diff --git a/include/asm-i386/topology.h b/include/asm-i386/topology.h
index 582cd32a7..cb8ab7407 100644
--- a/include/asm-i386/topology.h
+++ b/include/asm-i386/topology.h
@@ -67,7 +67,7 @@ static inline cpumask_t pcibus_to_cpumask(int bus)
 }
 
 /* Node-to-Node distance */
-#define node_distance(from, to) (from != to)
+#define node_distance(from, to) ((from) != (to))
 
 /* Cross-node load balancing interval. */
 #define NODE_BALANCE_RATE 100
diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h
index bb202d212..3553bec12 100644
--- a/include/asm-i386/uaccess.h
+++ b/include/asm-i386/uaccess.h
@@ -375,8 +375,10 @@ do {									\
 		: "m"(__m(addr)), "i"(errret), "0"(err))
 
 
-unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned long n);
-unsigned long __copy_from_user_ll(void *to, const void __user *from, unsigned long n);
+unsigned long __must_check __copy_to_user_ll(void __user *to,
+				const void *from, unsigned long n);
+unsigned long __must_check __copy_from_user_ll(void *to,
+				const void __user *from, unsigned long n);
 
 /*
  * Here we special-case 1, 2 and 4-byte copy_*_user invocations.  On a fault
@@ -399,8 +401,8 @@ unsigned long __copy_from_user_ll(void *to, const void __user *from, unsigned lo
  * Returns number of bytes that could not be copied.
  * On success, this will be zero.
  */
-static inline unsigned long
-__copy_to_user(void __user *to, const void *from, unsigned long n)
+static inline unsigned long __must_check
+__copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
 {
 	if (__builtin_constant_p(n)) {
 		unsigned long ret;
@@ -420,6 +422,13 @@ __copy_to_user(void __user *to, const void *from, unsigned long n)
 	return __copy_to_user_ll(to, from, n);
 }
 
+static inline unsigned long __must_check
+__copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+       might_sleep();
+       return __copy_to_user_inatomic(to, from, n);
+}
+
 /**
  * __copy_from_user: - Copy a block of data from user space, with less checking.
  * @to:   Destination address, in kernel space.
@@ -438,7 +447,7 @@ __copy_to_user(void __user *to, const void *from, unsigned long n)
  * data to the requested size using zero bytes.
  */
 static inline unsigned long
-__copy_from_user(void *to, const void __user *from, unsigned long n)
+__copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
 {
 	if (__builtin_constant_p(n)) {
 		unsigned long ret;
@@ -458,11 +467,20 @@ __copy_from_user(void *to, const void __user *from, unsigned long n)
 	return __copy_from_user_ll(to, from, n);
 }
 
-unsigned long copy_to_user(void __user *to, const void *from, unsigned long n);
-unsigned long copy_from_user(void *to,
-			const void __user *from, unsigned long n);
-long strncpy_from_user(char *dst, const char __user *src, long count);
-long __strncpy_from_user(char *dst, const char __user *src, long count);
+static inline unsigned long
+__copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+       might_sleep();
+       return __copy_from_user_inatomic(to, from, n);
+}
+unsigned long __must_check copy_to_user(void __user *to,
+				const void *from, unsigned long n);
+unsigned long __must_check copy_from_user(void *to,
+				const void __user *from, unsigned long n);
+long __must_check strncpy_from_user(char *dst, const char __user *src,
+				long count);
+long __must_check __strncpy_from_user(char *dst,
+				const char __user *src, long count);
 
 /**
  * strlen_user: - Get the size of a string in user space.
@@ -481,7 +499,7 @@ long __strncpy_from_user(char *dst, const char __user *src, long count);
 #define strlen_user(str) strnlen_user(str, ~0UL >> 1)
 
 long strnlen_user(const char __user *str, long n);
-unsigned long clear_user(void __user *mem, unsigned long len);
-unsigned long __clear_user(void __user *mem, unsigned long len);
+unsigned long __must_check clear_user(void __user *mem, unsigned long len);
+unsigned long __must_check __clear_user(void __user *mem, unsigned long len);
 
 #endif /* __i386_UACCESS_H */
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index ef936b861..be8c6ac56 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -289,8 +289,9 @@
 #define __NR_mq_notify		(__NR_mq_open+4)
 #define __NR_mq_getsetattr	(__NR_mq_open+5)
 #define __NR_sys_kexec_load	283
+#define __NR_waitid		284
 
-#define NR_syscalls 284
+#define NR_syscalls 285
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
 
diff --git a/include/asm-ia64/acpi.h b/include/asm-ia64/acpi.h
index 3e13984cf..d5c639454 100644
--- a/include/asm-ia64/acpi.h
+++ b/include/asm-ia64/acpi.h
@@ -89,13 +89,13 @@ ia64_acpi_release_global_lock (unsigned int *lock)
 	((Acq) = ia64_acpi_release_global_lock((unsigned int *) GLptr))
 
 #define acpi_disabled 0	/* ACPI always enabled on IA64 */
+#define acpi_noirq 0	/* ACPI always enabled on IA64 */
 #define acpi_pci_disabled 0 /* ACPI PCI always enabled on IA64 */
 #define acpi_strict 1	/* no ACPI spec workarounds on IA64 */
 static inline void disable_acpi(void) { }
 
 const char *acpi_get_sysname (void);
 int acpi_request_vector (u32 int_type);
-int acpi_register_irq (u32 gsi, u32 polarity, u32 trigger);
 int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
 
 #ifdef CONFIG_ACPI_NUMA
@@ -105,6 +105,8 @@ extern int __initdata pxm_to_nid_map[MAX_PXM_DOMAINS];
 extern int __initdata nid_to_pxm_map[MAX_NUMNODES];
 #endif
 
+extern u16 ia64_acpiid_to_sapicid[];
+
 #endif /*__KERNEL__*/
 
 #endif /*_ASM_ACPI_H*/
diff --git a/include/asm-ia64/bug.h b/include/asm-ia64/bug.h
index abbf37a44..2c0cd51e8 100644
--- a/include/asm-ia64/bug.h
+++ b/include/asm-ia64/bug.h
@@ -8,15 +8,8 @@
 #endif
 #define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); ia64_abort(); } while (0)
 
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define PAGE_BUG(page) do { BUG(); } while (0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
+/* should this BUG should be made generic? */
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-ia64/compat.h b/include/asm-ia64/compat.h
index 60ef0bab3..cc0ff0a4b 100644
--- a/include/asm-ia64/compat.h
+++ b/include/asm-ia64/compat.h
@@ -182,17 +182,17 @@ struct compat_shmid64_ds {
  */
 typedef	u32		compat_uptr_t;
 
-static inline void *
+static inline void __user *
 compat_ptr (compat_uptr_t uptr)
 {
-	return (void *) (unsigned long) uptr;
+	return (void __user *) (unsigned long) uptr;
 }
 
-static __inline__ void *
+static __inline__ void __user *
 compat_alloc_user_space (long len)
 {
 	struct pt_regs *regs = ia64_task_regs(current);
-	return (void *) (((regs->r12 & 0xffffffff) & -16) - len);
+	return (void __user *) (((regs->r12 & 0xffffffff) & -16) - len);
 }
 
 #endif /* _ASM_IA64_COMPAT_H */
diff --git a/include/asm-ia64/dma-mapping.h b/include/asm-ia64/dma-mapping.h
index 8a6d5d72b..6347c9845 100644
--- a/include/asm-ia64/dma-mapping.h
+++ b/include/asm-ia64/dma-mapping.h
@@ -5,7 +5,7 @@
  * Copyright (C) 2003-2004 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
-
+#include <linux/config.h>
 #include <asm/machvec.h>
 
 #define dma_alloc_coherent	platform_dma_alloc_coherent
diff --git a/include/asm-ia64/elf.h b/include/asm-ia64/elf.h
index 9557b4998..8373c3990 100644
--- a/include/asm-ia64/elf.h
+++ b/include/asm-ia64/elf.h
@@ -4,7 +4,7 @@
 /*
  * ELF-specific definitions.
  *
- * Copyright (C) 1998-1999, 2002-2003 Hewlett-Packard Co
+ * Copyright (C) 1998-1999, 2002-2004 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
@@ -40,7 +40,7 @@
  * the way of the program that it will "exec", and that there is
  * sufficient room for the brk.
  */
-#define ELF_ET_DYN_BASE		(TASK_UNMAPPED_BASE + 0x800000000)
+#define ELF_ET_DYN_BASE		(TASK_UNMAPPED_BASE + 0x800000000UL)
 
 #define PT_IA_64_UNWIND		0x70000001
 
@@ -175,7 +175,7 @@ extern void ia64_elf_core_copy_regs (struct pt_regs *src, elf_gregset_t dst);
 /* This macro yields a string that ld.so will use to load
    implementation specific libraries for optimization.  Not terribly
    relevant until we have real hardware to play with... */
-#define ELF_PLATFORM	0
+#define ELF_PLATFORM	NULL
 
 /*
  * Architecture-neutral AT_ values are in the range 0-17.  Leave some room for more of
diff --git a/include/asm-ia64/gcc_intrin.h b/include/asm-ia64/gcc_intrin.h
index 7d2b1e4cd..7c357dfba 100644
--- a/include/asm-ia64/gcc_intrin.h
+++ b/include/asm-ia64/gcc_intrin.h
@@ -259,35 +259,35 @@ register unsigned long ia64_r13 asm ("r13") __attribute_used__;
 	ia64_intri_res;								\
 })
 
-#define ia64_xchg1(ptr,x)						\
-({									\
-	__u64 ia64_intri_res;						\
-	asm __volatile ("xchg1 %0=[%1],%2" : "=r" (ia64_intri_res)	\
-			    : "r" (ptr), "r" (x) : "memory");		\
-	ia64_intri_res;							\
+#define ia64_xchg1(ptr,x)							\
+({										\
+	__u64 ia64_intri_res;							\
+	asm volatile ("xchg1 %0=[%1],%2"					\
+		      : "=r" (ia64_intri_res) : "r" (ptr), "r" (x) : "memory");	\
+	ia64_intri_res;								\
 })
 
 #define ia64_xchg2(ptr,x)						\
 ({									\
 	__u64 ia64_intri_res;						\
-	asm __volatile ("xchg2 %0=[%1],%2" : "=r" (ia64_intri_res)	\
-			    : "r" (ptr), "r" (x) : "memory");		\
+	asm volatile ("xchg2 %0=[%1],%2" : "=r" (ia64_intri_res)	\
+		      : "r" (ptr), "r" (x) : "memory");			\
 	ia64_intri_res;							\
 })
 
 #define ia64_xchg4(ptr,x)						\
 ({									\
 	__u64 ia64_intri_res;						\
-	asm __volatile ("xchg4 %0=[%1],%2" : "=r" (ia64_intri_res)	\
-			    : "r" (ptr), "r" (x) : "memory");		\
+	asm volatile ("xchg4 %0=[%1],%2" : "=r" (ia64_intri_res)	\
+		      : "r" (ptr), "r" (x) : "memory");			\
 	ia64_intri_res;							\
 })
 
 #define ia64_xchg8(ptr,x)						\
 ({									\
 	__u64 ia64_intri_res;						\
-	asm __volatile ("xchg8 %0=[%1],%2" : "=r" (ia64_intri_res)	\
-			    : "r" (ptr), "r" (x) : "memory");		\
+	asm volatile ("xchg8 %0=[%1],%2" : "=r" (ia64_intri_res)	\
+		      : "r" (ptr), "r" (x) : "memory");			\
 	ia64_intri_res;							\
 })
 
diff --git a/include/asm-ia64/hardirq.h b/include/asm-ia64/hardirq.h
index ec603240e..491996a79 100644
--- a/include/asm-ia64/hardirq.h
+++ b/include/asm-ia64/hardirq.h
@@ -52,20 +52,6 @@
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have space for potentially all IRQ sources
  * in the system nesting on a single CPU:
@@ -74,31 +60,6 @@
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context?
- * Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
-#ifdef CONFIG_PREEMPT
-# include <linux/smp_lock.h>
-# define in_atomic()		((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()		(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
-#ifdef CONFIG_SMP
-  extern void synchronize_irq (unsigned int irq);
-#else
-# define synchronize_irq(irq)	barrier()
-#endif /* CONFIG_SMP */
+extern void __iomem *ipi_base_addr;
 
 #endif /* _ASM_IA64_HARDIRQ_H */
diff --git a/include/asm-ia64/hw_irq.h b/include/asm-ia64/hw_irq.h
index a72134370..f4e5a4bf1 100644
--- a/include/asm-ia64/hw_irq.h
+++ b/include/asm-ia64/hw_irq.h
@@ -78,8 +78,6 @@ enum {
 extern __u8 isa_irq_to_vector_map[16];
 #define isa_irq_to_vector(x)	isa_irq_to_vector_map[(x)]
 
-extern unsigned long ipi_base_addr;
-
 extern struct hw_interrupt_type irq_type_ia64_lsapic;	/* CPU-internal interrupt controller */
 
 extern int assign_irq_vector (int irq);	/* allocate a free vector */
diff --git a/include/asm-ia64/ia32.h b/include/asm-ia64/ia32.h
index 4fa4b8e12..8e746b241 100644
--- a/include/asm-ia64/ia32.h
+++ b/include/asm-ia64/ia32.h
@@ -6,7 +6,7 @@
 #include <asm/ptrace.h>
 #include <asm/signal.h>
 
-#define IA32_NR_syscalls		283	/* length of syscall table */
+#define IA32_NR_syscalls		285	/* length of syscall table */
 #define IA32_PAGE_SHIFT			12	/* 4KB pages */
 
 #ifndef __ASSEMBLY__
@@ -14,7 +14,7 @@
 # ifdef CONFIG_IA32_SUPPORT
 
 extern void ia32_cpu_init (void);
-extern void ia32_boot_gdt_init (void);
+extern void ia32_mem_init (void);
 extern void ia32_gdt_init (void);
 extern int ia32_exception (struct pt_regs *regs, unsigned long isr);
 extern int ia32_intercept (struct pt_regs *regs, unsigned long isr);
diff --git a/include/asm-ia64/io.h b/include/asm-ia64/io.h
index 8b6d0ae22..4d19a5b24 100644
--- a/include/asm-ia64/io.h
+++ b/include/asm-ia64/io.h
@@ -23,7 +23,7 @@
 #define __SLOW_DOWN_IO	do { } while (0)
 #define SLOW_DOWN_IO	do { } while (0)
 
-#define __IA64_UNCACHED_OFFSET	0xc000000000000000	/* region 6 */
+#define __IA64_UNCACHED_OFFSET	0xc000000000000000UL	/* region 6 */
 
 /*
  * The legacy I/O space defined by the ia64 architecture supports only 65536 ports, but
@@ -248,7 +248,7 @@ __outsw (unsigned long port, const void *src, unsigned long count)
 }
 
 static inline void
-__outsl (unsigned long port, void *src, unsigned long count)
+__outsl (unsigned long port, const void *src, unsigned long count)
 {
 	const unsigned int *sp = src;
 
@@ -290,51 +290,51 @@ __outsl (unsigned long port, void *src, unsigned long count)
  * hopefully it'll stay that way).
  */
 static inline unsigned char
-___ia64_readb (void *addr)
+___ia64_readb (const volatile void __iomem *addr)
 {
-	return *(volatile unsigned char *)addr;
+	return *(volatile unsigned char __force *)addr;
 }
 
 static inline unsigned short
-___ia64_readw (void *addr)
+___ia64_readw (const volatile void __iomem *addr)
 {
-	return *(volatile unsigned short *)addr;
+	return *(volatile unsigned short __force *)addr;
 }
 
 static inline unsigned int
-___ia64_readl (void *addr)
+___ia64_readl (const volatile void __iomem *addr)
 {
-	return *(volatile unsigned int *) addr;
+	return *(volatile unsigned int __force *) addr;
 }
 
 static inline unsigned long
-___ia64_readq (void *addr)
+___ia64_readq (const volatile void __iomem *addr)
 {
-	return *(volatile unsigned long *) addr;
+	return *(volatile unsigned long __force *) addr;
 }
 
 static inline void
-__writeb (unsigned char val, void *addr)
+__writeb (unsigned char val, volatile void __iomem *addr)
 {
-	*(volatile unsigned char *) addr = val;
+	*(volatile unsigned char __force *) addr = val;
 }
 
 static inline void
-__writew (unsigned short val, void *addr)
+__writew (unsigned short val, volatile void __iomem *addr)
 {
-	*(volatile unsigned short *) addr = val;
+	*(volatile unsigned short __force *) addr = val;
 }
 
 static inline void
-__writel (unsigned int val, void *addr)
+__writel (unsigned int val, volatile void __iomem *addr)
 {
-	*(volatile unsigned int *) addr = val;
+	*(volatile unsigned int __force *) addr = val;
 }
 
 static inline void
-__writeq (unsigned long val, void *addr)
+__writeq (unsigned long val, volatile void __iomem *addr)
 {
-	*(volatile unsigned long *) addr = val;
+	*(volatile unsigned long __force *) addr = val;
 }
 
 #define __readb		platform_readb
@@ -346,14 +346,14 @@ __writeq (unsigned long val, void *addr)
 #define __readl_relaxed	platform_readl_relaxed
 #define __readq_relaxed	platform_readq_relaxed
 
-#define readb(a)	__readb((void *)(a))
-#define readw(a)	__readw((void *)(a))
-#define readl(a)	__readl((void *)(a))
-#define readq(a)	__readq((void *)(a))
-#define readb_relaxed(a)	__readb_relaxed((void *)(a))
-#define readw_relaxed(a)	__readw_relaxed((void *)(a))
-#define readl_relaxed(a)	__readl_relaxed((void *)(a))
-#define readq_relaxed(a)	__readq_relaxed((void *)(a))
+#define readb(a)	__readb((a))
+#define readw(a)	__readw((a))
+#define readl(a)	__readl((a))
+#define readq(a)	__readq((a))
+#define readb_relaxed(a)	__readb_relaxed((a))
+#define readw_relaxed(a)	__readw_relaxed((a))
+#define readl_relaxed(a)	__readl_relaxed((a))
+#define readq_relaxed(a)	__readq_relaxed((a))
 #define __raw_readb	readb
 #define __raw_readw	readw
 #define __raw_readl	readl
@@ -362,10 +362,10 @@ __writeq (unsigned long val, void *addr)
 #define __raw_readw_relaxed	readw_relaxed
 #define __raw_readl_relaxed	readl_relaxed
 #define __raw_readq_relaxed	readq_relaxed
-#define writeb(v,a)	__writeb((v), (void *) (a))
-#define writew(v,a)	__writew((v), (void *) (a))
-#define writel(v,a)	__writel((v), (void *) (a))
-#define writeq(v,a)	__writeq((v), (void *) (a))
+#define writeb(v,a)	__writeb((v), (a))
+#define writew(v,a)	__writew((v), (a))
+#define writel(v,a)	__writel((v), (a))
+#define writeq(v,a)	__writeq((v), (a))
 #define __raw_writeb	writeb
 #define __raw_writew	writew
 #define __raw_writel	writel
@@ -397,14 +397,14 @@ __writeq (unsigned long val, void *addr)
  *
  * On ia-64, we access the physical I/O memory space through the uncached kernel region.
  */
-static inline void *
+static inline void __iomem *
 ioremap (unsigned long offset, unsigned long size)
 {
-	return (void *) (__IA64_UNCACHED_OFFSET | (offset));
+	return (void __iomem *) (__IA64_UNCACHED_OFFSET | (offset));
 }
 
 static inline void
-iounmap (void *addr)
+iounmap (volatile void __iomem *addr)
 {
 }
 
@@ -415,17 +415,14 @@ iounmap (void *addr)
 /*
  * String version of IO memory access ops:
  */
-extern void __ia64_memcpy_fromio (void *, unsigned long, long);
-extern void __ia64_memcpy_toio (unsigned long, void *, long);
-extern void __ia64_memset_c_io (unsigned long, unsigned long, long);
-
-#define memcpy_fromio(to,from,len) \
-  __ia64_memcpy_fromio((to),(unsigned long)(from),(len))
-#define memcpy_toio(to,from,len) \
-  __ia64_memcpy_toio((unsigned long)(to),(from),(len))
-#define memset_io(addr,c,len) \
-  __ia64_memset_c_io((unsigned long)(addr),0x0101010101010101UL*(u8)(c),(len))
-
+extern void __ia64_memcpy_fromio (void *, volatile void __iomem *, long);
+extern void __ia64_memcpy_toio (volatile void __iomem *, void *, long);
+extern void __ia64_memset_c_io (volatile void __iomem *, unsigned long, long);
+
+#define memcpy_fromio(to,from,len)	__ia64_memcpy_fromio((to), (from),(len))
+#define memcpy_toio(to,from,len)	__ia64_memcpy_toio((to),(from),(len))
+#define memset_io(addr,c,len)		__ia64_memset_c_io((addr), 0x0101010101010101UL*(u8)(c), \
+							   (len))
 
 #define dma_cache_inv(_start,_size)             do { } while (0)
 #define dma_cache_wback(_start,_size)           do { } while (0)
diff --git a/include/asm-ia64/iosapic.h b/include/asm-ia64/iosapic.h
index 3fac17e98..b169975bb 100644
--- a/include/asm-ia64/iosapic.h
+++ b/include/asm-ia64/iosapic.h
@@ -53,19 +53,19 @@
 
 #define NR_IOSAPICS			256
 
-static inline unsigned int iosapic_read(char *iosapic, unsigned int reg)
+static inline unsigned int iosapic_read(char __iomem *iosapic, unsigned int reg)
 {
 	writel(reg, iosapic + IOSAPIC_REG_SELECT);
 	return readl(iosapic + IOSAPIC_WINDOW);
 }
 
-static inline void iosapic_write(char *iosapic, unsigned int reg, u32 val)
+static inline void iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val)
 {
 	writel(reg, iosapic + IOSAPIC_REG_SELECT);
 	writel(val, iosapic + IOSAPIC_WINDOW);
 }
 
-static inline void iosapic_eoi(char *iosapic, u32 vector)
+static inline void iosapic_eoi(char __iomem *iosapic, u32 vector)
 {
 	writel(vector, iosapic + IOSAPIC_EOI);
 }
@@ -87,9 +87,12 @@ extern int __init iosapic_register_platform_intr (u32 int_type,
 					   u16 eid, u16 id,
 					   unsigned long polarity,
 					   unsigned long trigger);
-extern unsigned int iosapic_version (char *addr);
+extern unsigned int iosapic_version (char __iomem *addr);
 
 extern void iosapic_pci_fixup (int);
+#ifdef CONFIG_NUMA
+extern void __init map_iosapic_to_node (unsigned int, int);
+#endif
 #else
 #define iosapic_system_init(pcat_compat)			do { } while (0)
 #define iosapic_init(address,gsi_base)				do { } while (0)
diff --git a/include/asm-ia64/mca.h b/include/asm-ia64/mca.h
index 0957e2ab6..1d000699e 100644
--- a/include/asm-ia64/mca.h
+++ b/include/asm-ia64/mca.h
@@ -22,6 +22,11 @@
 
 #define IA64_MCA_RENDEZ_TIMEOUT		(20 * 1000)	/* value in milliseconds - 20 seconds */
 
+typedef struct ia64_fptr {
+	unsigned long fp;
+	unsigned long gp;
+} ia64_fptr_t;
+
 typedef union cmcv_reg_u {
 	u64	cmcv_regval;
 	struct	{
@@ -114,6 +119,8 @@ extern void ia64_mca_ucmc_handler(void);
 extern void ia64_monarch_init_handler(void);
 extern void ia64_slave_init_handler(void);
 extern void ia64_mca_cmc_vector_setup(void);
+extern int  ia64_reg_MCA_extension(void*);
+extern void ia64_unreg_MCA_extension(void);
 
 #endif /* !__ASSEMBLY__ */
 #endif /* _ASM_IA64_MCA_H */
diff --git a/include/asm-ia64/mca_asm.h b/include/asm-ia64/mca_asm.h
index 2aa8437dc..55deddd7e 100644
--- a/include/asm-ia64/mca_asm.h
+++ b/include/asm-ia64/mca_asm.h
@@ -162,9 +162,6 @@
 	;;							\
 	srlz.d;							\
 	mov	r13 = ar.k6;					\
-	;;							\
-	DATA_PA_TO_VA(r13,temp1);				\
-	;;							\
 	mov	temp2 = ar.bspstore;				\
 	;;							\
 	DATA_PA_TO_VA(temp2,temp1);				\
diff --git a/include/asm-ia64/mmu_context.h b/include/asm-ia64/mmu_context.h
index 51558c0f0..0096e7e05 100644
--- a/include/asm-ia64/mmu_context.h
+++ b/include/asm-ia64/mmu_context.h
@@ -28,36 +28,6 @@
 
 #include <asm/processor.h>
 
-#define MMU_CONTEXT_DEBUG	0
-
-#if MMU_CONTEXT_DEBUG
-
-#include <ia64intrin.h>
-
-extern struct mmu_trace_entry {
-	char op;
-	u8 cpu;
-	u32 context;
-	void *mm;
-} mmu_tbuf[1024];
-
-extern volatile int mmu_tbuf_index;
-
-# define MMU_TRACE(_op,_cpu,_mm,_ctx)							\
-do {											\
-	int i = __sync_fetch_and_add(&mmu_tbuf_index, 1) % ARRAY_SIZE(mmu_tbuf);	\
-	struct mmu_trace_entry e;							\
-	e.op = (_op);									\
-	e.cpu = (_cpu);									\
-	e.mm = (_mm);									\
-	e.context = (_ctx);								\
-	mmu_tbuf[i] = e;								\
-} while (0)
-
-#else
-# define MMU_TRACE(op,cpu,mm,ctx)	do { ; } while (0)
-#endif
-
 struct ia64_ctx {
 	spinlock_t lock;
 	unsigned int next;	/* next context number to use */
@@ -123,7 +93,6 @@ get_mmu_context (struct mm_struct *mm)
 static inline int
 init_new_context (struct task_struct *p, struct mm_struct *mm)
 {
-	MMU_TRACE('N', smp_processor_id(), mm, 0);
 	mm->context = 0;
 	return 0;
 }
@@ -132,7 +101,6 @@ static inline void
 destroy_context (struct mm_struct *mm)
 {
 	/* Nothing to do.  */
-	MMU_TRACE('D', smp_processor_id(), mm, mm->context);
 }
 
 static inline void
@@ -142,7 +110,7 @@ reload_context (mm_context_t context)
 	unsigned long rid_incr = 0;
 	unsigned long rr0, rr1, rr2, rr3, rr4, old_rr4;
 
-	old_rr4 = ia64_get_rr(0x8000000000000000);
+	old_rr4 = ia64_get_rr(0x8000000000000000UL);
 	rid = context << 3;	/* make space for encoding the region number */
 	rid_incr = 1 << 8;
 
@@ -156,11 +124,11 @@ reload_context (mm_context_t context)
 	rr4 = (rr4 & (~(0xfcUL))) | (old_rr4 & 0xfc);
 #endif
 
-	ia64_set_rr(0x0000000000000000, rr0);
-	ia64_set_rr(0x2000000000000000, rr1);
-	ia64_set_rr(0x4000000000000000, rr2);
-	ia64_set_rr(0x6000000000000000, rr3);
-	ia64_set_rr(0x8000000000000000, rr4);
+	ia64_set_rr(0x0000000000000000UL, rr0);
+	ia64_set_rr(0x2000000000000000UL, rr1);
+	ia64_set_rr(0x4000000000000000UL, rr2);
+	ia64_set_rr(0x6000000000000000UL, rr3);
+	ia64_set_rr(0x8000000000000000UL, rr4);
 	ia64_srlz_i();			/* srlz.i implies srlz.d */
 }
 
@@ -171,19 +139,14 @@ activate_context (struct mm_struct *mm)
 
 	do {
 		context = get_mmu_context(mm);
-		MMU_TRACE('A', smp_processor_id(), mm, context);
 		if (!cpu_isset(smp_processor_id(), mm->cpu_vm_mask))
 			cpu_set(smp_processor_id(), mm->cpu_vm_mask);
 		reload_context(context);
-		MMU_TRACE('a', smp_processor_id(), mm, context);
 		/* in the unlikely event of a TLB-flush by another thread, redo the load: */
 	} while (unlikely(context != mm->context));
 }
 
-#define deactivate_mm(tsk,mm)					\
-do {								\
-	MMU_TRACE('d', smp_processor_id(), mm, mm->context);	\
-} while (0)
+#define deactivate_mm(tsk,mm)	do { } while (0)
 
 /*
  * Switch from address space PREV to address space NEXT.
diff --git a/include/asm-ia64/mmzone.h b/include/asm-ia64/mmzone.h
index f28f0b285..89c392d2d 100644
--- a/include/asm-ia64/mmzone.h
+++ b/include/asm-ia64/mmzone.h
@@ -27,12 +27,6 @@
 # define NR_NODE_MEMBLKS	(NR_NODES * 4)
 #endif
 
-extern unsigned long max_low_pfn;
-
-#define pfn_valid(pfn)		(((pfn) < max_low_pfn) && ia64_pfn_valid(pfn))
-#define page_to_pfn(page)	((unsigned long) (page - vmem_map))
-#define pfn_to_page(pfn)	(vmem_map + (pfn))
-
 #else /* CONFIG_DISCONTIGMEM */
 # define NR_NODE_MEMBLKS	4
 #endif /* CONFIG_DISCONTIGMEM */
diff --git a/include/asm-ia64/numa.h b/include/asm-ia64/numa.h
index 6459f619a..f62773284 100644
--- a/include/asm-ia64/numa.h
+++ b/include/asm-ia64/numa.h
@@ -59,7 +59,7 @@ extern struct node_cpuid_s node_cpuid[NR_CPUS];
  */
 
 extern u8 numa_slit[MAX_NUMNODES * MAX_NUMNODES];
-#define node_distance(from,to) (numa_slit[from * numnodes + to])
+#define node_distance(from,to) (numa_slit[(from) * numnodes + (to)])
 
 extern int paddr_to_nid(unsigned long paddr);
 
diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h
index 315a86310..0936ebcc2 100644
--- a/include/asm-ia64/page.h
+++ b/include/asm-ia64/page.h
@@ -84,10 +84,16 @@ extern int ia64_pfn_valid (unsigned long pfn);
 #endif
 
 #ifndef CONFIG_DISCONTIGMEM
-#define pfn_valid(pfn)		(((pfn) < max_mapnr) && ia64_pfn_valid(pfn))
-#define page_to_pfn(page)	((unsigned long) (page - mem_map))
-#define pfn_to_page(pfn)	(mem_map + (pfn))
-#endif /* CONFIG_DISCONTIGMEM */
+# define pfn_valid(pfn)		(((pfn) < max_mapnr) && ia64_pfn_valid(pfn))
+# define page_to_pfn(page)	((unsigned long) (page - mem_map))
+# define pfn_to_page(pfn)	(mem_map + (pfn))
+#else
+extern struct page *vmem_map;
+extern unsigned long max_low_pfn;
+# define pfn_valid(pfn)		(((pfn) < max_low_pfn) && ia64_pfn_valid(pfn))
+# define page_to_pfn(page)	((unsigned long) (page - vmem_map))
+# define pfn_to_page(pfn)	(vmem_map + (pfn))
+#endif
 
 #define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
@@ -117,7 +123,7 @@ typedef union ia64_va {
 #define REGION_KERNEL		7
 
 #ifdef CONFIG_HUGETLB_PAGE
-# define htlbpage_to_page(x)	((REGION_NUMBER(x) << 61)				\
+# define htlbpage_to_page(x)	(((unsigned long) REGION_NUMBER(x) << 61)			\
 				 | (REGION_OFFSET(x) >> (HPAGE_SHIFT-PAGE_SHIFT)))
 # define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
 # define is_hugepage_only_range(addr, len)		\
@@ -180,7 +186,7 @@ get_order (unsigned long size)
 # define __pgprot(x)	(x)
 #endif /* !STRICT_MM_TYPECHECKS */
 
-#define PAGE_OFFSET			0xe000000000000000
+#define PAGE_OFFSET			__IA64_UL_CONST(0xe000000000000000)
 
 #define VM_DATA_DEFAULT_FLAGS		(VM_READ | VM_WRITE |					\
 					 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC |		\
diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
index 843396653..085ef89df 100644
--- a/include/asm-ia64/pgtable.h
+++ b/include/asm-ia64/pgtable.h
@@ -206,18 +206,18 @@ ia64_phys_addr_valid (unsigned long addr)
 #define RGN_SIZE	(1UL << 61)
 #define RGN_KERNEL	7
 
-#define VMALLOC_START		0xa000000200000000
+#define VMALLOC_START		0xa000000200000000UL
 #ifdef CONFIG_VIRTUAL_MEM_MAP
-# define VMALLOC_END_INIT	(0xa000000000000000 + (1UL << (4*PAGE_SHIFT - 9)))
+# define VMALLOC_END_INIT	(0xa000000000000000UL + (1UL << (4*PAGE_SHIFT - 9)))
 # define VMALLOC_END		vmalloc_end
   extern unsigned long vmalloc_end;
 #else
-# define VMALLOC_END		(0xa000000000000000 + (1UL << (4*PAGE_SHIFT - 9)))
+# define VMALLOC_END		(0xa000000000000000UL + (1UL << (4*PAGE_SHIFT - 9)))
 #endif
 
 /* fs/proc/kcore.c */
-#define	kc_vaddr_to_offset(v) ((v) - 0xa000000000000000)
-#define	kc_offset_to_vaddr(o) ((o) + 0xa000000000000000)
+#define	kc_vaddr_to_offset(v) ((v) - 0xa000000000000000UL)
+#define	kc_offset_to_vaddr(o) ((o) + 0xa000000000000000UL)
 
 /*
  * Conversion functions: convert page frame number (pfn) and a protection value to a page
@@ -520,7 +520,7 @@ do {											\
 #  ifdef CONFIG_VIRTUAL_MEM_MAP
   /* arch mem_map init routine is needed due to holes in a virtual mem_map */
 #   define __HAVE_ARCH_MEMMAP_INIT
-    extern void memmap_init (struct page *start, unsigned long size, int nid, unsigned long zone,
+    extern void memmap_init (unsigned long size, int nid, unsigned long zone,
 			     unsigned long start_pfn);
 #  endif /* CONFIG_VIRTUAL_MEM_MAP */
 # endif /* !__ASSEMBLY__ */
diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
index f62f93c29..9e1b61be5 100644
--- a/include/asm-ia64/processor.h
+++ b/include/asm-ia64/processor.h
@@ -28,8 +28,8 @@
 #define IA64_NUM_PMC_REGS	32
 #define IA64_NUM_PMD_REGS	32
 
-#define DEFAULT_MAP_BASE	0x2000000000000000
-#define DEFAULT_TASK_SIZE	0xa000000000000000
+#define DEFAULT_MAP_BASE	__IA64_UL_CONST(0x2000000000000000)
+#define DEFAULT_TASK_SIZE	__IA64_UL_CONST(0xa000000000000000)
 
 /*
  * TASK_SIZE really is a mis-named.  It really is the maximum user
@@ -200,7 +200,7 @@ typedef struct {
 #define GET_UNALIGN_CTL(task,addr)								\
 ({												\
 	put_user(((task)->thread.flags & IA64_THREAD_UAC_MASK) >> IA64_THREAD_UAC_SHIFT,	\
-		 (int *) (addr));								\
+		 (int __user *) (addr));							\
 })
 
 #define SET_FPEMU_CTL(task,value)								\
@@ -212,7 +212,7 @@ typedef struct {
 #define GET_FPEMU_CTL(task,addr)								\
 ({												\
 	put_user(((task)->thread.flags & IA64_THREAD_FPEMU_MASK) >> IA64_THREAD_FPEMU_SHIFT,	\
-		 (int *) (addr));								\
+		 (int __user *) (addr));							\
 })
 
 #ifdef CONFIG_IA32_SUPPORT
@@ -262,7 +262,7 @@ struct thread_struct {
 				.fdr =		0,			\
 				.old_k1 =	0,			\
 				.old_iob =	0,			\
-				.ppl =		0,
+				.ppl =		NULL,
 #else
 # define INIT_THREAD_IA32
 #endif /* CONFIG_IA32_SUPPORT */
@@ -334,6 +334,26 @@ struct task_struct;
 /* Prepare to copy thread state - unlazy all lazy status */
 #define prepare_to_copy(tsk)	do { } while (0)
 
+#ifdef CONFIG_NUMA
+#define SD_NODE_INIT (struct sched_domain) {		\
+	.span			= CPU_MASK_NONE,	\
+	.parent			= NULL,			\
+	.groups			= NULL,			\
+	.min_interval		= 80,			\
+	.max_interval		= 320,			\
+	.busy_factor		= 320,			\
+	.imbalance_pct		= 125,			\
+	.cache_hot_time		= (10*1000000),		\
+	.cache_nice_tries	= 1,			\
+	.per_cpu_gain		= 100,			\
+	.flags			= SD_BALANCE_EXEC	\
+				| SD_WAKE_BALANCE,	\
+	.last_balance		= jiffies,		\
+	.balance_interval	= 10,			\
+	.nr_balance_failed	= 0,			\
+}
+#endif
+
 /*
  * This is the mechanism for creating a new kernel thread.
  *
diff --git a/include/asm-ia64/ptrace.h b/include/asm-ia64/ptrace.h
index 48398a30d..2af819be1 100644
--- a/include/asm-ia64/ptrace.h
+++ b/include/asm-ia64/ptrace.h
@@ -229,6 +229,15 @@ struct switch_stack {
  * the canonical representation by adding to instruction pointer.
  */
 # define instruction_pointer(regs) ((regs)->cr_iip + ia64_psr(regs)->ri)
+/* Conserve space in histogram by encoding slot bits in address
+ * bits 2 and 3 rather than bits 0 and 1.
+ */
+#define profile_pc(regs)						\
+({									\
+	unsigned long __ip = instruction_pointer(regs);			\
+	(__ip & ~3UL) + ((__ip & 3UL) << 2);				\
+})
+
   /* given a pointer to a task_struct, return the user's pt_regs */
 # define ia64_task_regs(t)		(((struct pt_regs *) ((char *) (t) + IA64_STK_OFFSET)) - 1)
 # define ia64_psr(regs)			((struct ia64_psr *) &(regs)->cr_ipsr)
diff --git a/include/asm-ia64/resource.h b/include/asm-ia64/resource.h
index 76345b5c1..52a737eab 100644
--- a/include/asm-ia64/resource.h
+++ b/include/asm-ia64/resource.h
@@ -46,7 +46,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
-	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff --git a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h
index b372de029..f468596f4 100644
--- a/include/asm-ia64/sal.h
+++ b/include/asm-ia64/sal.h
@@ -364,7 +364,7 @@ typedef struct sal_processor_static_info {
 	u64 cr[128];
 	u64 ar[128];
 	u64 rr[8];
-	struct ia64_fpreg fr[128];
+	struct ia64_fpreg __attribute__ ((packed)) fr[128];
 } sal_processor_static_info_t;
 
 struct sal_cpuid_info {
@@ -819,6 +819,16 @@ struct sal_ret_values {
 	long r8; long r9; long r10; long r11;
 };
 
+#define IA64_SAL_OEMFUNC_MIN		0x02000000
+#define IA64_SAL_OEMFUNC_MAX		0x03ffffff
+
+extern int ia64_sal_oemcall(struct ia64_sal_retval *, u64, u64, u64, u64, u64,
+			    u64, u64, u64);
+extern int ia64_sal_oemcall_nolock(struct ia64_sal_retval *, u64, u64, u64,
+				   u64, u64, u64, u64, u64);
+extern int ia64_sal_oemcall_reentrant(struct ia64_sal_retval *, u64, u64, u64,
+				      u64, u64, u64, u64, u64);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_IA64_SAL_H */
diff --git a/include/asm-ia64/semaphore.h b/include/asm-ia64/semaphore.h
index 44165a637..3a2f0f3f7 100644
--- a/include/asm-ia64/semaphore.h
+++ b/include/asm-ia64/semaphore.h
@@ -15,21 +15,13 @@ struct semaphore {
 	atomic_t count;
 	int sleepers;
 	wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
-	long __magic;		/* initialized by __SEM_DEBUG_INIT() */
-#endif
 };
 
-#if WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name)		, (long) &(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count)					\
-{										\
-	ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
-	__SEM_DEBUG_INIT(name)							\
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.sleepers	= 0,						\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
 }
 
 #define __MUTEX_INITIALIZER(name)	__SEMAPHORE_INITIALIZER(name,1)
@@ -70,9 +62,6 @@ extern void __up (struct semaphore * sem);
 static inline void
 down (struct semaphore *sem)
 {
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	if (atomic_dec_return(&sem->count) < 0)
 		__down(sem);
@@ -87,9 +76,6 @@ down_interruptible (struct semaphore * sem)
 {
 	int ret = 0;
 
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	if (atomic_dec_return(&sem->count) < 0)
 		ret = __down_interruptible(sem);
@@ -101,9 +87,6 @@ down_trylock (struct semaphore *sem)
 {
 	int ret = 0;
 
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	if (atomic_dec_return(&sem->count) < 0)
 		ret = __down_trylock(sem);
 	return ret;
@@ -112,9 +95,6 @@ down_trylock (struct semaphore *sem)
 static inline void
 up (struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	if (atomic_inc_return(&sem->count) <= 0)
 		__up(sem);
 }
diff --git a/include/asm-ia64/siginfo.h b/include/asm-ia64/siginfo.h
index 52cce1d3d..d55f139cb 100644
--- a/include/asm-ia64/siginfo.h
+++ b/include/asm-ia64/siginfo.h
@@ -60,7 +60,7 @@ typedef struct siginfo {
 
 		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
 		struct {
-			void *_addr;		/* faulting insn/memory ref. */
+			void __user *_addr;	/* faulting insn/memory ref. */
 			int _imm;		/* immediate value for "break" */
 			unsigned int _flags;	/* see below */
 			unsigned long _isr;	/* isr */
diff --git a/include/asm-ia64/signal.h b/include/asm-ia64/signal.h
index f24615df3..e051dc399 100644
--- a/include/asm-ia64/signal.h
+++ b/include/asm-ia64/signal.h
@@ -144,10 +144,10 @@
 struct siginfo;
 
 /* Type of a signal handler.  */
-typedef void (*__sighandler_t)(int);
+typedef void __user (*__sighandler_t)(int);
 
 typedef struct sigaltstack {
-	void *ss_sp;
+	void __user *ss_sp;
 	int ss_flags;
 	size_t ss_size;
 } stack_t;
diff --git a/include/asm-ia64/smp.h b/include/asm-ia64/smp.h
index 513c704d1..d6838c9b7 100644
--- a/include/asm-ia64/smp.h
+++ b/include/asm-ia64/smp.h
@@ -39,7 +39,7 @@ extern struct smp_boot_data {
 extern char no_int_routing __devinitdata;
 
 extern cpumask_t cpu_online_map;
-extern unsigned long ipi_base_addr;
+extern void __iomem *ipi_base_addr;
 extern unsigned char smp_int_redirect;
 
 extern volatile int ia64_cpu_to_sapicid[];
@@ -73,21 +73,21 @@ static inline void
 min_xtp (void)
 {
 	if (smp_int_redirect & SMP_IRQ_REDIRECTION)
-		writeb(0x00, ipi_base_addr | XTP_OFFSET); /* XTP to min */
+		writeb(0x00, ipi_base_addr + XTP_OFFSET); /* XTP to min */
 }
 
 static inline void
 normal_xtp (void)
 {
 	if (smp_int_redirect & SMP_IRQ_REDIRECTION)
-		writeb(0x08, ipi_base_addr | XTP_OFFSET); /* XTP normal */
+		writeb(0x08, ipi_base_addr + XTP_OFFSET); /* XTP normal */
 }
 
 static inline void
 max_xtp (void)
 {
 	if (smp_int_redirect & SMP_IRQ_REDIRECTION)
-		writeb(0x0f, ipi_base_addr | XTP_OFFSET); /* Set XTP to max */
+		writeb(0x0f, ipi_base_addr + XTP_OFFSET); /* Set XTP to max */
 }
 
 static inline unsigned int
diff --git a/include/asm-ia64/sn/sn2/shubio.h b/include/asm-ia64/sn/sn2/shubio.h
index ac3b00a2d..e984c5718 100644
--- a/include/asm-ia64/sn/sn2/shubio.h
+++ b/include/asm-ia64/sn/sn2/shubio.h
@@ -3384,7 +3384,7 @@ typedef ii_icrb0_e_u_t icrbe_t;
 
 #define IO_PERF_SETS	32
 
-#if __KERNEL__
+#ifdef __KERNEL__
 #include <asm/sn/dmamap.h>
 #include <asm/sn/driver.h>
 #include <asm/sn/xtalk/xtalk.h>
diff --git a/include/asm-ia64/sn/sn_cpuid.h b/include/asm-ia64/sn/sn_cpuid.h
index 6f1128f1e..529e4f5a4 100644
--- a/include/asm-ia64/sn/sn_cpuid.h
+++ b/include/asm-ia64/sn/sn_cpuid.h
@@ -4,7 +4,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved.
  */
 
 
@@ -93,6 +93,7 @@
  */
 #define cpu_physical_id_to_nasid(cpi)		((cpi) &0xfff)
 #define cpu_physical_id_to_slice(cpi)		((cpi>>12) & 3)
+#define cpu_physical_id_to_coherence_id(cpi)	(cpu_physical_id_to_nasid(cpi) >> 9)
 #define get_nasid()				((ia64_getreg(_IA64_REG_CR_LID) >> 16) & 0xfff)
 #define get_slice()				((ia64_getreg(_IA64_REG_CR_LID) >> 28) & 0xf)
 #define get_node_number(addr)			(((unsigned long)(addr)>>38) & 0x7ff)
@@ -172,6 +173,11 @@ extern short physical_node_map[];			/* indexed by nasid to get cnode */
 
 #define smp_physical_node_id()			(cpuid_to_nasid(smp_processor_id()))
 
+/*
+ * cpuid_to_coherence_id - convert a cpuid to the coherence domain id it
+ * resides on
+ */
+#define cpuid_to_coherence_id(cpuid)	cpu_physical_id_to_coherence_id(cpu_physical_id(cpuid))
 
 #endif /* _ASM_IA64_SN_SN_CPUID_H */
 
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
index 5bd9b3335..3d3d324a2 100644
--- a/include/asm-ia64/sn/sn_sal.h
+++ b/include/asm-ia64/sn/sn_sal.h
@@ -8,7 +8,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All rights reserved.
+ * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All rights reserved.
  */
 
 
@@ -34,6 +34,7 @@
 #define  SN_SAL_NO_FAULT_ZONE_PHYSICAL		   0x02000011
 #define  SN_SAL_PRINT_ERROR			   0x02000012
 #define  SN_SAL_SET_ERROR_HANDLING_FEATURES	   0x0200001a	// reentrant
+#define  SN_SAL_GET_FIT_COMPT			   0x0200001b	// reentrant
 #define  SN_SAL_CONSOLE_PUTC                       0x02000021
 #define  SN_SAL_CONSOLE_GETC                       0x02000022
 #define  SN_SAL_CONSOLE_PUTS                       0x02000023
@@ -60,6 +61,8 @@
 #define  SN_SAL_SYSCTL_FRU_CAPTURE		   0x0200003f
 
 #define  SN_SAL_SYSCTL_IOBRICK_PCI_OP		   0x02000042	// reentrant
+#define	 SN_SAL_IROUTER_OP			   0x02000043
+#define  SN_SAL_HWPERF_OP			   0x02000050   // lock
 
 /*
  * Service-specific constants
@@ -86,12 +89,32 @@
 #endif	/* CONFIG_HOTPLUG_PCI_SGI */
 
 /*
- * SN_SAL_GET_PARTITION_ADDR return constants
+ * IRouter (i.e. generalized system controller) operations
+ */
+#define SAL_IROUTER_OPEN	0	/* open a subchannel */
+#define SAL_IROUTER_CLOSE	1	/* close a subchannel */
+#define SAL_IROUTER_SEND	2	/* send part of an IRouter packet */
+#define SAL_IROUTER_RECV	3	/* receive part of an IRouter packet */
+#define SAL_IROUTER_INTR_STATUS	4	/* check the interrupt status for
+					 * an open subchannel
+					 */
+#define SAL_IROUTER_INTR_ON	5	/* enable an interrupt */
+#define SAL_IROUTER_INTR_OFF	6	/* disable an interrupt */
+#define SAL_IROUTER_INIT	7	/* initialize IRouter driver */
+
+/* IRouter interrupt mask bits */
+#define SAL_IROUTER_INTR_XMIT	SAL_CONSOLE_INTR_XMIT
+#define SAL_IROUTER_INTR_RECV	SAL_CONSOLE_INTR_RECV
+
+
+/*
+ * SAL Error Codes
  */
 #define SALRET_MORE_PASSES	1
 #define SALRET_OK		0
-#define SALRET_INVALID_ARG	-2
-#define SALRET_ERROR		-3
+#define SALRET_NOT_IMPLEMENTED	(-1)
+#define SALRET_INVALID_ARG	(-2)
+#define SALRET_ERROR		(-3)
 
 /*
  * SN_SAL_SET_ERROR_HANDLING_FEATURES bit settings
@@ -704,4 +727,169 @@ ia64_sn_set_error_handling_features(const u64 *feature_bits)
 	return rv.status;
 }
 
+
+/*
+ * Open a subchannel for sending arbitrary data to the system
+ * controller network via the system controller device associated with
+ * 'nasid'.  Return the subchannel number or a negative error code.
+ */
+static inline int
+ia64_sn_irtr_open(nasid_t nasid)
+{
+	struct ia64_sal_retval rv;
+	SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_OPEN, nasid,
+			   0, 0, 0, 0, 0);
+	return (int) rv.v0;
+}
+
+/*
+ * Close system controller subchannel 'subch' previously opened on 'nasid'.
+ */
+static inline int
+ia64_sn_irtr_close(nasid_t nasid, int subch)
+{
+	struct ia64_sal_retval rv;
+	SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_CLOSE,
+			   (u64) nasid, (u64) subch, 0, 0, 0, 0);
+	return (int) rv.status;
+}
+
+/*
+ * Read data from system controller associated with 'nasid' on
+ * subchannel 'subch'.  The buffer to be filled is pointed to by
+ * 'buf', and its capacity is in the integer pointed to by 'len'.  The
+ * referent of 'len' is set to the number of bytes read by the SAL
+ * call.  The return value is either SALRET_OK (for bytes read) or
+ * SALRET_ERROR (for error or "no data available").
+ */
+static inline int
+ia64_sn_irtr_recv(nasid_t nasid, int subch, char *buf, int *len)
+{
+	struct ia64_sal_retval rv;
+	SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_RECV,
+			   (u64) nasid, (u64) subch, (u64) buf, (u64) len,
+			   0, 0);
+	return (int) rv.status;
+}
+
+/*
+ * Write data to the system controller network via the system
+ * controller associated with 'nasid' on suchannel 'subch'.  The
+ * buffer to be written out is pointed to by 'buf', and 'len' is the
+ * number of bytes to be written.  The return value is either the
+ * number of bytes written (which could be zero) or a negative error
+ * code.
+ */
+static inline int
+ia64_sn_irtr_send(nasid_t nasid, int subch, char *buf, int len)
+{
+	struct ia64_sal_retval rv;
+	SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_SEND,
+			   (u64) nasid, (u64) subch, (u64) buf, (u64) len,
+			   0, 0);
+	return (int) rv.v0;
+}
+
+/*
+ * Check whether any interrupts are pending for the system controller
+ * associated with 'nasid' and its subchannel 'subch'.  The return
+ * value is a mask of pending interrupts (SAL_IROUTER_INTR_XMIT and/or
+ * SAL_IROUTER_INTR_RECV).
+ */
+static inline int
+ia64_sn_irtr_intr(nasid_t nasid, int subch)
+{
+	struct ia64_sal_retval rv;
+	SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_INTR_STATUS,
+			   (u64) nasid, (u64) subch, 0, 0, 0, 0);
+	return (int) rv.v0;
+}
+
+/*
+ * Enable the interrupt indicated by the intr parameter (either
+ * SAL_IROUTER_INTR_XMIT or SAL_IROUTER_INTR_RECV).
+ */
+static inline int
+ia64_sn_irtr_intr_enable(nasid_t nasid, int subch, u64 intr)
+{
+	struct ia64_sal_retval rv;
+	SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_INTR_ON,
+			   (u64) nasid, (u64) subch, intr, 0, 0, 0);
+	return (int) rv.v0;
+}
+
+/*
+ * Disable the interrupt indicated by the intr parameter (either
+ * SAL_IROUTER_INTR_XMIT or SAL_IROUTER_INTR_RECV).
+ */
+static inline int
+ia64_sn_irtr_intr_disable(nasid_t nasid, int subch, u64 intr)
+{
+	struct ia64_sal_retval rv;
+	SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_INTR_OFF,
+			   (u64) nasid, (u64) subch, intr, 0, 0, 0);
+	return (int) rv.v0;
+}
+
+/**
+ * ia64_sn_get_fit_compt - read a FIT entry from the PROM header
+ * @nasid: NASID of node to read
+ * @index: FIT entry index to be retrieved (0..n)
+ * @fitentry: 16 byte buffer where FIT entry will be stored.
+ * @banbuf: optional buffer for retrieving banner
+ * @banlen: length of banner buffer
+ *
+ * Access to the physical PROM chips needs to be serialized since reads and
+ * writes can't occur at the same time, so we need to call into the SAL when
+ * we want to look at the FIT entries on the chips.
+ *
+ * Returns:
+ *	%SALRET_OK if ok
+ *	%SALRET_INVALID_ARG if index too big
+ *	%SALRET_NOT_IMPLEMENTED if running on older PROM
+ *	??? if nasid invalid OR banner buffer not large enough
+ */
+static inline int
+ia64_sn_get_fit_compt(u64 nasid, u64 index, void *fitentry, void *banbuf,
+		      u64 banlen)
+{
+	struct ia64_sal_retval rv;
+	SAL_CALL_NOLOCK(rv, SN_SAL_GET_FIT_COMPT, nasid, index, fitentry,
+			banbuf, banlen, 0, 0);
+	return (int) rv.status;
+}
+
+/*
+ * Initialize the SAL components of the system controller
+ * communication driver; specifically pass in a sizable buffer that
+ * can be used for allocation of subchannel queues as new subchannels
+ * are opened.  "buf" points to the buffer, and "len" specifies its
+ * length.
+ */
+static inline int
+ia64_sn_irtr_init(nasid_t nasid, void *buf, int len)
+{
+	struct ia64_sal_retval rv;
+	SAL_CALL_REENTRANT(rv, SN_SAL_IROUTER_OP, SAL_IROUTER_INIT,
+			   (u64) nasid, (u64) buf, (u64) len, 0, 0, 0);
+	return (int) rv.status;
+}
+
+/*
+ * This is the access point to the Altix PROM hardware performance
+ * and status monitoring interface. For info on using this, see
+ * include/asm-ia64/sn/sn2/sn_hwperf.h
+ */
+static inline int
+ia64_sn_hwperf_op(nasid_t nasid, u64 opcode, u64 a0, u64 a1, u64 a2,
+                  u64 a3, u64 a4, int *v0)
+{
+	struct ia64_sal_retval rv;
+	SAL_CALL_NOLOCK(rv, SN_SAL_HWPERF_OP, (u64)nasid,
+		opcode, a0, a1, a2, a3, a4);
+	if (v0)
+		*v0 = (int) rv.v0;
+	return (int) rv.status;
+}
+
 #endif /* _ASM_IA64_SN_SN_SAL_H */
diff --git a/include/asm-ia64/sn/xtalk/xtalk.h b/include/asm-ia64/sn/xtalk/xtalk.h
index b65da047b..5475454b7 100644
--- a/include/asm-ia64/sn/xtalk/xtalk.h
+++ b/include/asm-ia64/sn/xtalk/xtalk.h
@@ -55,7 +55,7 @@ typedef struct xtalk_piomap_s *xtalk_piomap_t;
 /*
  * Kernel/driver only definitions
  */
-#if __KERNEL__
+#ifdef __KERNEL__
 
 #include <asm/types.h>
 #include <asm/sn/types.h>
diff --git a/include/asm-ia64/sn/xtalk/xwidget.h b/include/asm-ia64/sn/xtalk/xwidget.h
index 15a298a58..d265bcc6b 100644
--- a/include/asm-ia64/sn/xtalk/xwidget.h
+++ b/include/asm-ia64/sn/xtalk/xwidget.h
@@ -183,7 +183,7 @@ typedef struct xwidget_hwid_s {
 
 
 /* Generic crosstalk widget initialization interface */
-#if __KERNEL__
+#ifdef __KERNEL__
 
 extern int              xwidget_driver_register(xwidget_part_num_t part_num,
 						xwidget_mfg_num_t mfg_num,
diff --git a/include/asm-ia64/socket.h b/include/asm-ia64/socket.h
index bf4434e26..21a9f10d6 100644
--- a/include/asm-ia64/socket.h
+++ b/include/asm-ia64/socket.h
@@ -56,20 +56,4 @@
 
 #define SO_PEERSEC             31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_IA64_SOCKET_H */
diff --git a/include/asm-ia64/spinlock.h b/include/asm-ia64/spinlock.h
index 40f939c5b..a56a06665 100644
--- a/include/asm-ia64/spinlock.h
+++ b/include/asm-ia64/spinlock.h
@@ -114,8 +114,8 @@ do {											\
 #define spin_unlock_wait(x)	do { barrier(); } while ((x)->lock)
 
 typedef struct {
-	volatile int read_counter	: 31;
-	volatile int write_lock		:  1;
+	volatile unsigned int read_counter	: 31;
+	volatile unsigned int write_lock	:  1;
 } rwlock_t;
 #define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
 
diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h
index 83b2c1bc0..fdefa16fa 100644
--- a/include/asm-ia64/system.h
+++ b/include/asm-ia64/system.h
@@ -19,12 +19,12 @@
 #include <asm/pal.h>
 #include <asm/percpu.h>
 
-#define GATE_ADDR		(0xa000000000000000)
+#define GATE_ADDR		__IA64_UL_CONST(0xa000000000000000)
 /*
  * 0xa000000000000000+2*PERCPU_PAGE_SIZE
  * - 0xa000000000000000+3*PERCPU_PAGE_SIZE remain unmapped (guard page)
  */
-#define KERNEL_START		 0xa000000100000000
+#define KERNEL_START		 __IA64_UL_CONST(0xa000000100000000)
 #define PERCPU_ADDR		(-PERCPU_PAGE_SIZE)
 
 #ifndef __ASSEMBLY__
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
index 665623bf4..168319049 100644
--- a/include/asm-ia64/thread_info.h
+++ b/include/asm-ia64/thread_info.h
@@ -9,14 +9,6 @@
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 
-#define TI_TASK			0x00
-#define TI_EXEC_DOMAIN		0x08
-#define TI_FLAGS		0x10
-#define TI_CPU			0x14
-#define TI_ADDR_LIMIT		0x18
-#define TI_PRE_COUNT		0x20
-#define TI_RESTART_BLOCK	0x28
-
 #define PREEMPT_ACTIVE_BIT 30
 #define PREEMPT_ACTIVE	(1 << PREEMPT_ACTIVE_BIT)
 
diff --git a/include/asm-ia64/tlb.h b/include/asm-ia64/tlb.h
index d5c39f752..54d3355a9 100644
--- a/include/asm-ia64/tlb.h
+++ b/include/asm-ia64/tlb.h
@@ -39,7 +39,9 @@
  */
 #include <linux/config.h>
 #include <linux/mm.h>
+#include <linux/pagemap.h>
 #include <linux/swap.h>
+#include <linux/vs_memory.h>
 
 #include <asm/pgalloc.h>
 #include <asm/processor.h>
diff --git a/include/asm-ia64/tlbflush.h b/include/asm-ia64/tlbflush.h
index 049c69845..b65c62702 100644
--- a/include/asm-ia64/tlbflush.h
+++ b/include/asm-ia64/tlbflush.h
@@ -48,22 +48,19 @@ local_finish_flush_tlb_mm (struct mm_struct *mm)
 static inline void
 flush_tlb_mm (struct mm_struct *mm)
 {
-	MMU_TRACE('F', smp_processor_id(), mm, mm->context);
 	if (!mm)
-		goto out;
+		return;
 
 	mm->context = 0;
 
 	if (atomic_read(&mm->mm_users) == 0)
-		goto out;		/* happens as a result of exit_mmap() */
+		return;		/* happens as a result of exit_mmap() */
 
 #ifdef CONFIG_SMP
 	smp_flush_tlb_mm(mm);
 #else
 	local_finish_flush_tlb_mm(mm);
 #endif
-  out:
-	MMU_TRACE('f', smp_processor_id(), mm, mm->context);
 }
 
 extern void flush_tlb_range (struct vm_area_struct *vma, unsigned long start, unsigned long end);
diff --git a/include/asm-ia64/uaccess.h b/include/asm-ia64/uaccess.h
index 31d60e5e7..68f0e1dee 100644
--- a/include/asm-ia64/uaccess.h
+++ b/include/asm-ia64/uaccess.h
@@ -60,14 +60,17 @@
  * address TASK_SIZE is never valid.  We also need to make sure that the address doesn't
  * point inside the virtually mapped linear page table.
  */
-#define __access_ok(addr, size, segment)					\
-	(likely((unsigned long) (addr) <= (segment).seg)			\
-	 && ((segment).seg == KERNEL_DS.seg					\
-	     || likely(REGION_OFFSET((unsigned long) (addr)) < RGN_MAP_LIMIT)))
+#define __access_ok(addr, size, segment)						\
+({											\
+	__chk_user_ptr(addr);								\
+	(likely((unsigned long) (addr) <= (segment).seg)				\
+	 && ((segment).seg == KERNEL_DS.seg						\
+	     || likely(REGION_OFFSET((unsigned long) (addr)) < RGN_MAP_LIMIT)));	\
+})
 #define access_ok(type, addr, size)	__access_ok((addr), (size), get_fs())
 
 static inline int
-verify_area (int type, const void *addr, unsigned long size)
+verify_area (int type, const void __user *addr, unsigned long size)
 {
 	return access_ok(type, addr, size) ? 0 : -EFAULT;
 }
@@ -91,6 +94,42 @@ verify_area (int type, const void *addr, unsigned long size)
 #define __put_user(x, ptr)	__put_user_nocheck((__typeof__(*(ptr))) (x), (ptr), sizeof(*(ptr)))
 #define __get_user(x, ptr)	__get_user_nocheck((x), (ptr), sizeof(*(ptr)))
 
+extern long __put_user_unaligned_unknown (void);
+
+#define __put_user_unaligned(x, ptr)								\
+({												\
+	long __ret;										\
+	switch (sizeof(*(ptr))) {								\
+		case 1: __ret = __put_user((x), (ptr)); break;					\
+		case 2: __ret = (__put_user((x), (u8 __user *)(ptr)))				\
+			| (__put_user((x) >> 8, ((u8 __user *)(ptr) + 1))); break;		\
+		case 4: __ret = (__put_user((x), (u16 __user *)(ptr)))				\
+			| (__put_user((x) >> 16, ((u16 __user *)(ptr) + 1))); break;		\
+		case 8: __ret = (__put_user((x), (u32 __user *)(ptr)))				\
+			| (__put_user((x) >> 32, ((u32 __user *)(ptr) + 1))); break;		\
+		default: __ret = __put_user_unaligned_unknown();				\
+	}											\
+	__ret;											\
+})
+
+extern long __get_user_unaligned_unknown (void);
+
+#define __get_user_unaligned(x, ptr)								\
+({												\
+	long __ret;										\
+	switch (sizeof(*(ptr))) {								\
+		case 1: __ret = __get_user((x), (ptr)); break;					\
+		case 2: __ret = (__get_user((x), (u8 __user *)(ptr)))				\
+			| (__get_user((x) >> 8, ((u8 __user *)(ptr) + 1))); break;		\
+		case 4: __ret = (__get_user((x), (u16 __user *)(ptr)))				\
+			| (__get_user((x) >> 16, ((u16 __user *)(ptr) + 1))); break;		\
+		case 8: __ret = (__get_user((x), (u32 __user *)(ptr)))				\
+			| (__get_user((x) >> 32, ((u32 __user *)(ptr) + 1))); break;		\
+		default: __ret = __get_user_unaligned_unknown();				\
+	}											\
+	__ret;											\
+})
+
 #ifdef ASM_SUPPORTED
   struct __large_struct { unsigned long buf[100]; };
 # define __m(x) (*(struct __large_struct *)(x))
@@ -149,11 +188,11 @@ extern void __get_user_unknown (void);
  */
 #define __do_get_user(check, x, ptr, size, segment)					\
 ({											\
-	const __typeof__(*(ptr)) *__gu_ptr = (ptr);					\
+	const __typeof__(*(ptr)) __user *__gu_ptr = (ptr);				\
 	__typeof__ (size) __gu_size = (size);						\
 	long __gu_err = -EFAULT, __gu_val = 0;						\
 											\
-	if (!check || __access_ok((long) __gu_ptr, size, segment))			\
+	if (!check || __access_ok(__gu_ptr, size, segment))				\
 		switch (__gu_size) {							\
 		      case 1: __get_user_size(__gu_val, __gu_ptr, 1, __gu_err); break;	\
 		      case 2: __get_user_size(__gu_val, __gu_ptr, 2, __gu_err); break;	\
@@ -177,11 +216,11 @@ extern void __put_user_unknown (void);
 #define __do_put_user(check, x, ptr, size, segment)					\
 ({											\
 	__typeof__ (x) __pu_x = (x);							\
-	__typeof__ (*(ptr)) *__pu_ptr = (ptr);						\
+	__typeof__ (*(ptr)) __user *__pu_ptr = (ptr);					\
 	__typeof__ (size) __pu_size = (size);						\
 	long __pu_err = -EFAULT;							\
 											\
-	if (!check || __access_ok((long) __pu_ptr, __pu_size, segment))			\
+	if (!check || __access_ok(__pu_ptr, __pu_size, segment))			\
 		switch (__pu_size) {							\
 		      case 1: __put_user_size(__pu_x, __pu_ptr, 1, __pu_err); break;	\
 		      case 2: __put_user_size(__pu_x, __pu_ptr, 2, __pu_err); break;	\
@@ -198,43 +237,64 @@ extern void __put_user_unknown (void);
 /*
  * Complex access routines
  */
-extern unsigned long __copy_user (void *to, const void *from, unsigned long count);
+extern unsigned long __must_check __copy_user (void __user *to, const void __user *from,
+					       unsigned long count);
+
+static inline unsigned long
+__copy_to_user (void __user *to, const void *from, unsigned long count)
+{
+	return __copy_user(to, (void __user *) from, count);
+}
 
-#define __copy_to_user(to, from, n)	__copy_user((to), (from), (n))
-#define __copy_from_user(to, from, n)	__copy_user((to), (from), (n))
+static inline unsigned long
+__copy_from_user (void *to, const void __user *from, unsigned long count)
+{
+	return __copy_user((void __user *) to, from, count);
+}
 
-#define copy_to_user(to, from, n)	__copy_tofrom_user((to), (from), (n), 1)
-#define copy_from_user(to, from, n)	__copy_tofrom_user((to), (from), (n), 0)
+#define __copy_to_user_inatomic		__copy_to_user
+#define __copy_from_user_inatomic	__copy_from_user
+#define copy_to_user(to, from, n)							\
+({											\
+	void __user *__cu_to = (to);							\
+	const void *__cu_from = (from);							\
+	long __cu_len = (n);								\
+											\
+	if (__access_ok(__cu_to, __cu_len, get_fs()))					\
+		__cu_len = __copy_user(__cu_to, (void __user *) __cu_from, __cu_len);	\
+	__cu_len;									\
+})
 
-#define __copy_tofrom_user(to, from, n, check_to)					\
+#define copy_from_user(to, from, n)							\
 ({											\
 	void *__cu_to = (to);								\
-	const void *__cu_from = (from);							\
+	const void __user *__cu_from = (from);						\
 	long __cu_len = (n);								\
 											\
-	if (__access_ok((long) ((check_to) ? __cu_to : __cu_from), __cu_len, get_fs()))	\
-		__cu_len = __copy_user(__cu_to, __cu_from, __cu_len);			\
+	__chk_user_ptr(__cu_from);							\
+	if (__access_ok(__cu_from, __cu_len, get_fs()))					\
+		__cu_len = __copy_user((void __user *) __cu_to, __cu_from, __cu_len);	\
 	__cu_len;									\
 })
 
 #define __copy_in_user(to, from, size)	__copy_user((to), (from), (size))
 
 static inline unsigned long
-copy_in_user (void *to, const void *from, unsigned long n)
+copy_in_user (void __user *to, const void __user *from, unsigned long n)
 {
 	if (likely(access_ok(VERIFY_READ, from, n) && access_ok(VERIFY_WRITE, to, n)))
 		n = __copy_user(to, from, n);
 	return n;
 }
 
-extern unsigned long __do_clear_user (void *, unsigned long);
+extern unsigned long __do_clear_user (void __user *, unsigned long);
 
 #define __clear_user(to, n)		__do_clear_user(to, n)
 
 #define clear_user(to, n)					\
 ({								\
 	unsigned long __cu_len = (n);				\
-	if (__access_ok((long) to, __cu_len, get_fs()))		\
+	if (__access_ok(to, __cu_len, get_fs()))		\
 		__cu_len = __do_clear_user(to, __cu_len);	\
 	__cu_len;						\
 })
@@ -244,25 +304,25 @@ extern unsigned long __do_clear_user (void *, unsigned long);
  * Returns: -EFAULT if exception before terminator, N if the entire buffer filled, else
  * strlen.
  */
-extern long __strncpy_from_user (char *to, const char *from, long to_len);
+extern long __must_check __strncpy_from_user (char *to, const char __user *from, long to_len);
 
 #define strncpy_from_user(to, from, n)					\
 ({									\
-	const char * __sfu_from = (from);				\
+	const char __user * __sfu_from = (from);			\
 	long __sfu_ret = -EFAULT;					\
-	if (__access_ok((long) __sfu_from, 0, get_fs()))		\
+	if (__access_ok(__sfu_from, 0, get_fs()))			\
 		__sfu_ret = __strncpy_from_user((to), __sfu_from, (n));	\
 	__sfu_ret;							\
 })
 
 /* Returns: 0 if bad, string length+1 (memory size) of string if ok */
-extern unsigned long __strlen_user (const char *);
+extern unsigned long __strlen_user (const char __user *);
 
 #define strlen_user(str)				\
 ({							\
-	const char *__su_str = (str);			\
+	const char __user *__su_str = (str);		\
 	unsigned long __su_ret = 0;			\
-	if (__access_ok((long) __su_str, 0, get_fs()))	\
+	if (__access_ok(__su_str, 0, get_fs()))		\
 		__su_ret = __strlen_user(__su_str);	\
 	__su_ret;					\
 })
@@ -272,13 +332,13 @@ extern unsigned long __strlen_user (const char *);
  * (N), a value greater than N if the limit would be exceeded, else
  * strlen.
  */
-extern unsigned long __strnlen_user (const char *, long);
+extern unsigned long __strnlen_user (const char __user *, long);
 
 #define strnlen_user(str, len)					\
 ({								\
-	const char *__su_str = (str);				\
+	const char __user *__su_str = (str);			\
 	unsigned long __su_ret = 0;				\
-	if (__access_ok((long) __su_str, 0, get_fs()))		\
+	if (__access_ok(__su_str, 0, get_fs()))			\
 		__su_ret = __strnlen_user(__su_str, len);	\
 	__su_ret;						\
 })
diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
index d46f47f97..84e6989d6 100644
--- a/include/asm-ia64/unistd.h
+++ b/include/asm-ia64/unistd.h
@@ -369,8 +369,8 @@ asmlinkage unsigned long sys_mmap2(
 				int fd, long pgoff);
 struct pt_regs;
 struct sigaction;
-asmlinkage long sys_execve(char *filename, char **argv, char **envp,
-				struct pt_regs *regs);
+asmlinkage long sys_execve(char __user *filename, char __user * __user *argv,
+			   char __user * __user *envp, struct pt_regs *regs);
 asmlinkage long sys_pipe(long arg0, long arg1, long arg2, long arg3,
 			long arg4, long arg5, long arg6, long arg7, long stack);
 asmlinkage long sys_ptrace(long request, pid_t pid,
diff --git a/include/asm-m68k/bug.h b/include/asm-m68k/bug.h
index 1f21b0d19..3e1d2266f 100644
--- a/include/asm-m68k/bug.h
+++ b/include/asm-m68k/bug.h
@@ -21,20 +21,7 @@
 } while (0)
 #endif
 
-#define BUG_ON(condition) do { \
-	if (unlikely((condition)!=0)) \
-		BUG(); \
-} while(0)
-
-#define PAGE_BUG(page) do { \
-	BUG(); \
-} while (0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-m68k/cacheflush.h b/include/asm-m68k/cacheflush.h
index da8399855..3b2e5205b 100644
--- a/include/asm-m68k/cacheflush.h
+++ b/include/asm-m68k/cacheflush.h
@@ -132,10 +132,18 @@ static inline void __flush_page_to_ram(void *vaddr)
 #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
 #define flush_icache_page(vma, page)	__flush_page_to_ram(page_address(page))
 #define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
+
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
+	do {					\
+		flush_cache_page(vma, vaddr);	\
+		memcpy(dst, src, len);		\
+	} while (0)
+
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
+	do {					\
+		flush_cache_page(vma, vaddr);	\
+		memcpy(dst, src, len);		\
+	} while (0)
 
 extern void flush_icache_range(unsigned long address, unsigned long endaddr);
 
diff --git a/include/asm-m68k/hardirq.h b/include/asm-m68k/hardirq.h
index 80c86ec3b..c74ad7709 100644
--- a/include/asm-m68k/hardirq.h
+++ b/include/asm-m68k/hardirq.h
@@ -35,20 +35,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -58,27 +44,7 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# define in_atomic()	(preempt_count() != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
 #define irq_exit()							\
 do {									\
 		preempt_count() -= IRQ_EXIT_OFFSET;			\
@@ -87,6 +53,4 @@ do {									\
 		preempt_enable_no_resched();				\
 } while (0)
 
-#define synchronize_irq(irq)	barrier()
-
 #endif
diff --git a/include/asm-m68k/ptrace.h b/include/asm-m68k/ptrace.h
index f62c54ea2..57e763d79 100644
--- a/include/asm-m68k/ptrace.h
+++ b/include/asm-m68k/ptrace.h
@@ -73,6 +73,7 @@ struct switch_stack {
 
 #define user_mode(regs) (!((regs)->sr & PS_S))
 #define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
diff --git a/include/asm-m68k/resource.h b/include/asm-m68k/resource.h
index 8362001c2..92a8ff5c8 100644
--- a/include/asm-m68k/resource.h
+++ b/include/asm-m68k/resource.h
@@ -39,7 +39,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
-	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff --git a/include/asm-m68k/semaphore.h b/include/asm-m68k/semaphore.h
index 213d4f796..ab94cf3ed 100644
--- a/include/asm-m68k/semaphore.h
+++ b/include/asm-m68k/semaphore.h
@@ -27,21 +27,14 @@ struct semaphore {
 	atomic_t count;
 	atomic_t waking;
 	wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), ATOMIC_INIT(0), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.waking		= ATOMIC_INIT(0),				\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name,1)
@@ -86,9 +79,6 @@ static inline void down(struct semaphore *sem)
 {
 	register struct semaphore *sem1 __asm__ ("%a1") = sem;
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	__asm__ __volatile__(
 		"| atomic down operation\n\t"
@@ -109,9 +99,6 @@ static inline int down_interruptible(struct semaphore *sem)
 	register struct semaphore *sem1 __asm__ ("%a1") = sem;
 	register int result __asm__ ("%d0");
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	__asm__ __volatile__(
 		"| atomic interruptible down operation\n\t"
@@ -134,10 +121,6 @@ static inline int down_trylock(struct semaphore *sem)
 	register struct semaphore *sem1 __asm__ ("%a1") = sem;
 	register int result __asm__ ("%d0");
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	__asm__ __volatile__(
 		"| atomic down trylock operation\n\t"
 		"subql #1,%1@\n\t"
@@ -164,10 +147,6 @@ static inline void up(struct semaphore *sem)
 {
 	register struct semaphore *sem1 __asm__ ("%a1") = sem;
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	__asm__ __volatile__(
 		"| atomic up operation\n\t"
 		"addql #1,%0@\n\t"
diff --git a/include/asm-m68k/socket.h b/include/asm-m68k/socket.h
index 68a33bfba..8d0b9fc2d 100644
--- a/include/asm-m68k/socket.h
+++ b/include/asm-m68k/socket.h
@@ -47,20 +47,4 @@
 
 #define SO_PEERSEC             31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-m68k/system.h b/include/asm-m68k/system.h
index 5a9c74c09..f0f36fca1 100644
--- a/include/asm-m68k/system.h
+++ b/include/asm-m68k/system.h
@@ -51,7 +51,7 @@ asmlinkage void resume(void);
 #if 0
 #define local_irq_enable() asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory")
 #else
-#include <asm/hardirq.h>
+#include <linux/hardirq.h>
 #define local_irq_enable() ({							\
 	if (MACH_IS_Q40 || !hardirq_count())					\
 		asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory");	\
diff --git a/include/asm-m68k/uaccess.h b/include/asm-m68k/uaccess.h
index 5ea8444e5..38388dc47 100644
--- a/include/asm-m68k/uaccess.h
+++ b/include/asm-m68k/uaccess.h
@@ -521,6 +521,9 @@ __constant_copy_from_user(void *to, const void *from, unsigned long n)
 	 : "0"(to), "1"(from), "2"(n/4)			\
 	 : "d0", "memory")
 
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
 static inline unsigned long
 __constant_copy_to_user(void *to, const void *from, unsigned long n)
 {
diff --git a/include/asm-m68knommu/bug.h b/include/asm-m68knommu/bug.h
index bc027eadb..70e7dc0af 100644
--- a/include/asm-m68knommu/bug.h
+++ b/include/asm-m68knommu/bug.h
@@ -1,24 +1,4 @@
 #ifndef _M68KNOMMU_BUG_H
 #define _M68KNOMMU_BUG_H
-
-#define BUG() do { \
-  printk("%s(%d): kernel BUG!\n", __FILE__, __LINE__); \
-} while (0)
-
-#define BUG_ON(condition) do { \
-	if (unlikely((condition)!=0)) \
-		BUG(); \
-} while(0)
-
-#define PAGE_BUG(page) do { \
-         BUG(); \
-} while (0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
-
+#include <asm-generic/bug.h>
 #endif
diff --git a/include/asm-m68knommu/hardirq.h b/include/asm-m68knommu/hardirq.h
index f8dbdf2de..840eac281 100644
--- a/include/asm-m68knommu/hardirq.h
+++ b/include/asm-m68knommu/hardirq.h
@@ -36,20 +36,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -59,33 +45,7 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
-#ifdef CONFIG_PREEMPT
-# define in_atomic()	(preempt_count() != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #define irq_exit()							\
 do {									\
 		preempt_count() -= IRQ_EXIT_OFFSET;			\
@@ -94,10 +54,4 @@ do {									\
 		preempt_enable_no_resched();				\
 } while (0)
 
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else
-# error m68knommu SMP is not available
-#endif /* CONFIG_SMP */
-
 #endif /* __M68K_HARDIRQ_H */
diff --git a/include/asm-m68knommu/ptrace.h b/include/asm-m68knommu/ptrace.h
index ac386868f..f65bd9074 100644
--- a/include/asm-m68knommu/ptrace.h
+++ b/include/asm-m68knommu/ptrace.h
@@ -84,6 +84,7 @@ struct switch_stack {
 
 #define user_mode(regs) (!((regs)->sr & PS_S))
 #define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 #endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
diff --git a/include/asm-m68knommu/semaphore.h b/include/asm-m68knommu/semaphore.h
index f85d311bc..febe85add 100644
--- a/include/asm-m68knommu/semaphore.h
+++ b/include/asm-m68knommu/semaphore.h
@@ -26,21 +26,14 @@ struct semaphore {
 	atomic_t count;
 	atomic_t waking;
 	wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#if WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), ATOMIC_INIT(0), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.waking		= ATOMIC_INIT(0),				\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name,1)
@@ -85,9 +78,6 @@ extern spinlock_t semaphore_wake_lock;
  */
 extern inline void down(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	__asm__ __volatile__(
 		"| atomic down operation\n\t"
@@ -105,9 +95,6 @@ extern inline int down_interruptible(struct semaphore * sem)
 {
 	int ret;
 
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	__asm__ __volatile__(
 		"| atomic down operation\n\t"
@@ -128,10 +115,6 @@ extern inline int down_trylock(struct semaphore * sem)
 	register struct semaphore *sem1 __asm__ ("%a1") = sem;
 	register int result __asm__ ("%d0");
 
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	__asm__ __volatile__(
 		"| atomic down trylock operation\n\t"
 		"subql #1,%1@\n\t"
@@ -157,10 +140,6 @@ extern inline int down_trylock(struct semaphore * sem)
  */
 extern inline void up(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	__asm__ __volatile__(
 		"| atomic up operation\n\t"
 		"movel	%0, %%a1\n\t"
diff --git a/include/asm-m68knommu/uaccess.h b/include/asm-m68knommu/uaccess.h
index 9f890ed45..9bda78751 100644
--- a/include/asm-m68knommu/uaccess.h
+++ b/include/asm-m68knommu/uaccess.h
@@ -134,6 +134,8 @@ extern int __get_user_bad(void);
 
 #define __copy_from_user(to, from, n) copy_from_user(to, from, n)
 #define __copy_to_user(to, from, n) copy_to_user(to, from, n)
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 
 #define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; })
 
diff --git a/include/asm-mips/bug.h b/include/asm-mips/bug.h
index f1f483d4f..eb94bb96c 100644
--- a/include/asm-mips/bug.h
+++ b/include/asm-mips/bug.h
@@ -7,14 +7,8 @@
 do {									\
 	__asm__ __volatile__("break %0" : : "i" (BRK_BUG));		\
 } while (0)
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-#define PAGE_BUG(page) do {  BUG(); } while (0)
 
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-	dump_stack(); \
-	} \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-mips/dma-mapping.h b/include/asm-mips/dma-mapping.h
index a11cf994d..716951187 100644
--- a/include/asm-mips/dma-mapping.h
+++ b/include/asm-mips/dma-mapping.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_DMA_MAPPING_H
 #define _ASM_DMA_MAPPING_H
 
-#include <linux/device.h>
 #include <asm/scatterlist.h>
 #include <asm/cache.h>
 
diff --git a/include/asm-mips/hardirq.h b/include/asm-mips/hardirq.h
index a045970eb..7562703b4 100644
--- a/include/asm-mips/hardirq.h
+++ b/include/asm-mips/hardirq.h
@@ -43,20 +43,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -66,27 +52,7 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# include <linux/smp_lock.h>
-# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
 #define irq_exit()                                                     \
 do {                                                                   \
 	preempt_count() -= IRQ_EXIT_OFFSET;                     \
@@ -95,10 +61,4 @@ do {                                                                   \
 	preempt_enable_no_resched();                            \
 } while (0)
 
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else
-  extern void synchronize_irq(unsigned int irq);
-#endif /* CONFIG_SMP */
-
 #endif /* _ASM_HARDIRQ_H */
diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h
index 19cadb657..2a090cf36 100644
--- a/include/asm-mips/ptrace.h
+++ b/include/asm-mips/ptrace.h
@@ -66,6 +66,7 @@ struct pt_regs {
 #define user_mode(regs) (((regs)->cp0_status & KU_MASK) == KU_USER)
 
 #define instruction_pointer(regs) ((regs)->cp0_epc)
+#define profile_pc(regs) instruction_pointer(regs)
 
 extern void show_regs(struct pt_regs *);
 
diff --git a/include/asm-mips/resource.h b/include/asm-mips/resource.h
index 2453e0d1c..62e1ce028 100644
--- a/include/asm-mips/resource.h
+++ b/include/asm-mips/resource.h
@@ -53,7 +53,7 @@
 	{ INR_OPEN,      INR_OPEN      },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
-	{ 0,             0             },		\
+	{ MLOCK_LIMIT,     MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff --git a/include/asm-mips/semaphore.h b/include/asm-mips/semaphore.h
index ed9a3d774..c2c97dec6 100644
--- a/include/asm-mips/semaphore.h
+++ b/include/asm-mips/semaphore.h
@@ -37,22 +37,13 @@ struct semaphore {
 	 */
 	atomic_t count;
 	wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name, count) \
-	{ ATOMIC_INIT(count), \
-	  __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	  __SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name, 1)
@@ -67,9 +58,6 @@ static inline void sema_init (struct semaphore *sem, int val)
 {
 	atomic_set(&sem->count, val);
 	init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -88,9 +76,6 @@ extern void __up(struct semaphore * sem);
 
 static inline void down(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	/*
@@ -104,9 +89,6 @@ static inline int down_interruptible(struct semaphore * sem)
 {
 	int ret = 0;
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	if (unlikely(atomic_dec_return(&sem->count) < 0))
@@ -116,19 +98,11 @@ static inline int down_interruptible(struct semaphore * sem)
 
 static inline int down_trylock(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	return atomic_dec_if_positive(&sem->count) < 0;
 }
 
 static inline void up(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	if (unlikely(atomic_inc_return(&sem->count) <= 0))
 		__up(sem);
 }
diff --git a/include/asm-mips/siginfo.h b/include/asm-mips/siginfo.h
index c980cb9a9..fec216976 100644
--- a/include/asm-mips/siginfo.h
+++ b/include/asm-mips/siginfo.h
@@ -47,8 +47,8 @@ typedef struct siginfo {
 		struct {
 			pid_t _pid;		/* which child */
 			uid_t _uid;		/* sender's uid */
-			clock_t _utime;
 			int _status;		/* exit code */
+			clock_t _utime;
 			clock_t _stime;
 		} _sigchld;
 
diff --git a/include/asm-mips/socket.h b/include/asm-mips/socket.h
index 6556c10be..eba99d2ac 100644
--- a/include/asm-mips/socket.h
+++ b/include/asm-mips/socket.h
@@ -68,20 +68,31 @@ To add: #define SO_REUSEPORT 0x0200	/* Allow local address and port reuse.  */
 
 #define SO_PEERSEC		30
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_DGRAM	1		/* datagram (conn.less) socket	*/
-#define SOCK_STREAM	2		/* stream (connection) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
+/** sock_type - Socket types
+ *
+ * Please notice that for binary compat reasons MIPS has to
+ * override the enum sock_type in include/linux/net.h, so
+ * we define ARCH_HAS_SOCKET_TYPES here.
+ *
+ * @SOCK_DGRAM - datagram (conn.less) socket
+ * @SOCK_STREAM - stream (connection) socket
+ * @SOCK_RAW - raw socket
+ * @SOCK_RDM - reliably-delivered message
+ * @SOCK_SEQPACKET - sequential packet socket 
+ * @SOCK_PACKET - linux specific way of getting packets at the dev level.
+ *		  For writing rarp and other similar things on the user level.
+ */
+enum sock_type {
+	SOCK_DGRAM	= 1,
+	SOCK_STREAM	= 2,
+	SOCK_RAW	= 3,
+	SOCK_RDM	= 4,
+	SOCK_SEQPACKET	= 5,
+	SOCK_PACKET	= 10,
+};
+
+#define SOCK_MAX (SOCK_PACKET + 1)
+
+#define ARCH_HAS_SOCKET_TYPES
 
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-mips/uaccess.h b/include/asm-mips/uaccess.h
index e143e4ec6..adbb24bd9 100644
--- a/include/asm-mips/uaccess.h
+++ b/include/asm-mips/uaccess.h
@@ -13,6 +13,7 @@
 #include <linux/compiler.h>
 #include <linux/errno.h>
 #include <linux/thread_info.h>
+#include <asm-generic/uaccess.h>
 
 /*
  * The fs value determines whether argument validity checking should be
@@ -463,6 +464,9 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
 	__cu_len;							\
 })
 
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
 /*
  * copy_to_user: - Copy a block of data into user space.
  * @to:   Destination address, in user space.
diff --git a/include/asm-mips/vr41xx/vrc4173.h b/include/asm-mips/vr41xx/vrc4173.h
index b14ef0377..591b81b7a 100644
--- a/include/asm-mips/vr41xx/vrc4173.h
+++ b/include/asm-mips/vr41xx/vrc4173.h
@@ -48,6 +48,8 @@
 /*
  * PCI I/O accesses
  */
+#ifdef CONFIG_VRC4173
+
 extern unsigned long vrc4173_io_offset;
 
 #define set_vrc4173_io_offset(offset)	do { vrc4173_io_offset = (offset); } while (0)
@@ -74,6 +76,34 @@ extern unsigned long vrc4173_io_offset;
 #define vrc4173_insw(port,addr,count)	insw(vrc4173_io_offset+(port),(addr),(count))
 #define vrc4173_insl(port,addr,count)	insl(vrc4173_io_offset+(port),(addr),(count))
 
+#else
+
+#define set_vrc4173_io_offset(offset)	do {} while (0)
+
+#define vrc4173_outb(val,port)		do {} while (0)
+#define vrc4173_outw(val,port)		do {} while (0)
+#define vrc4173_outl(val,port)		do {} while (0)
+#define vrc4173_outb_p(val,port)	do {} while (0)
+#define vrc4173_outw_p(val,port)	do {} while (0)
+#define vrc4173_outl_p(val,port)	do {} while (0)
+
+#define vrc4173_inb(port)		0
+#define vrc4173_inw(port)		0
+#define vrc4173_inl(port)		0
+#define vrc4173_inb_p(port)		0
+#define vrc4173_inw_p(port)		0
+#define vrc4173_inl_p(port)		0
+
+#define vrc4173_outsb(port,addr,count)	do {} while (0)
+#define vrc4173_outsw(port,addr,count)	do {} while (0)
+#define vrc4173_outsl(port,addr,count)	do {} while (0)
+
+#define vrc4173_insb(port,addr,count)	do {} while (0)
+#define vrc4173_insw(port,addr,count)	do {} while (0)
+#define vrc4173_insl(port,addr,count)	do {} while (0)
+
+#endif
+
 /*
  * Clock Mask Unit
  */
@@ -92,9 +122,77 @@ typedef enum vrc4173_clock {
 	VRC4173_48MHz_CLOCK,
 } vrc4173_clock_t;
 
+#ifdef CONFIG_VRC4173
+
 extern void vrc4173_supply_clock(vrc4173_clock_t clock);
 extern void vrc4173_mask_clock(vrc4173_clock_t clock);
 
+#else
+
+static inline void vrc4173_supply_clock(vrc4173_clock_t clock) {}
+static inline void vrc4173_mask_clock(vrc4173_clock_t clock) {}
+
+#endif
+
+/*
+ * Interupt Control Unit
+ */
+
+#define VRC4173_PIUINT_COMMAND		0x0040
+#define VRC4173_PIUINT_DATA		0x0020
+#define VRC4173_PIUINT_PAGE1		0x0010
+#define VRC4173_PIUINT_PAGE0		0x0008
+#define VRC4173_PIUINT_DATALOST		0x0004
+#define VRC4173_PIUINT_STATUSCHANGE	0x0001
+
+#ifdef CONFIG_VRC4173
+
+extern void vrc4173_enable_piuint(uint16_t mask);
+extern void vrc4173_disable_piuint(uint16_t mask);
+
+#else
+
+static inline void vrc4173_enable_piuint(uint16_t mask) {}
+static inline void vrc4173_disable_piuint(uint16_t mask) {}
+
+#endif
+
+#define VRC4173_AIUINT_INPUT_DMAEND	0x0800
+#define VRC4173_AIUINT_INPUT_DMAHALT	0x0400
+#define VRC4173_AIUINT_INPUT_DATALOST	0x0200
+#define VRC4173_AIUINT_INPUT_DATA	0x0100
+#define VRC4173_AIUINT_OUTPUT_DMAEND	0x0008
+#define VRC4173_AIUINT_OUTPUT_DMAHALT	0x0004
+#define VRC4173_AIUINT_OUTPUT_NODATA	0x0002
+
+#ifdef CONFIG_VRC4173
+
+extern void vrc4173_enable_aiuint(uint16_t mask);
+extern void vrc4173_disable_aiuint(uint16_t mask);
+
+#else
+
+static inline void vrc4173_enable_aiuint(uint16_t mask) {}
+static inline void vrc4173_disable_aiuint(uint16_t mask) {}
+
+#endif
+
+#define VRC4173_KIUINT_DATALOST		0x0004
+#define VRC4173_KIUINT_DATAREADY	0x0002
+#define VRC4173_KIUINT_SCAN		0x0001
+
+#ifdef CONFIG_VRC4173
+
+extern void vrc4173_enable_kiuint(uint16_t mask);
+extern void vrc4173_disable_kiuint(uint16_t mask);
+
+#else
+
+static inline void vrc4173_enable_kiuint(uint16_t mask) {}
+static inline void vrc4173_disable_kiuint(uint16_t mask) {}
+
+#endif
+
 /*
  * General-Purpose I/O Unit
  */
@@ -109,6 +207,14 @@ typedef enum vrc4173_function {
 	GPIO_16_20PINS,
 } vrc4173_function_t;
 
+#ifdef CONFIG_VRC4173
+
 extern void vrc4173_select_function(vrc4173_function_t function);
 
+#else
+
+static inline void vrc4173_select_function(vrc4173_function_t function) {}
+
+#endif
+
 #endif /* __NEC_VRC4173_H */
diff --git a/include/asm-parisc/bug.h b/include/asm-parisc/bug.h
index 00d6aa7f0..98d36ad3c 100644
--- a/include/asm-parisc/bug.h
+++ b/include/asm-parisc/bug.h
@@ -1,29 +1,4 @@
 #ifndef _PARISC_BUG_H
 #define _PARISC_BUG_H
-
-/*
- * Tell the user there is some problem.
- */
-#define BUG() do { \
-	extern void dump_stack(void); \
-	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
-	dump_stack(); \
-} while (0)
-
-#define BUG_ON(condition) do { \
-	if (unlikely((condition)!=0)) \
-		BUG(); \
-} while(0)
-
-#define PAGE_BUG(page) do { \
-	BUG(); \
-} while (0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
-
+#include <asm-generic/bug.h>
 #endif
diff --git a/include/asm-parisc/cacheflush.h b/include/asm-parisc/cacheflush.h
index 3086cdaf4..af0626dfa 100644
--- a/include/asm-parisc/cacheflush.h
+++ b/include/asm-parisc/cacheflush.h
@@ -77,11 +77,17 @@ extern void flush_dcache_page(struct page *page);
 #define flush_icache_range(s,e)		do { flush_kernel_dcache_range_asm(s,e); flush_kernel_icache_range_asm(s,e); } while (0)
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-do { memcpy(dst, src, len); \
-     flush_kernel_dcache_range_asm((unsigned long)dst, (unsigned long)dst + len); \
+do { \
+	flush_cache_page(vma, vaddr); \
+	memcpy(dst, src, len); \
+	flush_kernel_dcache_range_asm((unsigned long)dst, (unsigned long)dst + len); \
 } while (0)
+
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
+do { \
+	flush_cache_page(vma, vaddr); \
+	memcpy(dst, src, len); \
+} while (0)
 
 static inline void flush_cache_range(struct vm_area_struct *vma,
 		unsigned long start, unsigned long end)
diff --git a/include/asm-parisc/hardirq.h b/include/asm-parisc/hardirq.h
index dc9b4b738..7ebdebbe5 100644
--- a/include/asm-parisc/hardirq.h
+++ b/include/asm-parisc/hardirq.h
@@ -51,20 +51,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have space for potentially all IRQ sources
  * in the system nesting on a single CPU:
@@ -73,29 +59,7 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context?
- * Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# error CONFIG_PREEMT currently not supported.
-# define in_atomic()	 BUG()
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #define irq_exit()								\
 do {										\
 		preempt_count() -= IRQ_EXIT_OFFSET;				\
@@ -104,10 +68,4 @@ do {										\
 		preempt_enable_no_resched();					\
 } while (0)
 
-#ifdef CONFIG_SMP
-  extern void synchronize_irq (unsigned int irq);
-#else
-# define synchronize_irq(irq)	barrier()
-#endif /* CONFIG_SMP */
-
 #endif /* _PARISC_HARDIRQ_H */
diff --git a/include/asm-parisc/ptrace.h b/include/asm-parisc/ptrace.h
index 181fc75a0..c276c096c 100644
--- a/include/asm-parisc/ptrace.h
+++ b/include/asm-parisc/ptrace.h
@@ -48,6 +48,7 @@ struct pt_regs {
 /* XXX should we use iaoq[1] or iaoq[0] ? */
 #define user_mode(regs)			(((regs)->iaoq[0] &  3) ? 1 : 0)
 #define instruction_pointer(regs)	((regs)->iaoq[0] & ~3)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 #endif
 
diff --git a/include/asm-parisc/resource.h b/include/asm-parisc/resource.h
index 59a446534..491f29e49 100644
--- a/include/asm-parisc/resource.h
+++ b/include/asm-parisc/resource.h
@@ -39,7 +39,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
-	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff --git a/include/asm-parisc/semaphore.h b/include/asm-parisc/semaphore.h
index f9ab172f6..f78bb2e34 100644
--- a/include/asm-parisc/semaphore.h
+++ b/include/asm-parisc/semaphore.h
@@ -40,21 +40,14 @@ struct semaphore {
 	spinlock_t	sentry;
 	int		count;
 	wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#if WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ SPIN_LOCK_UNLOCKED, count, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.sentry		= SPIN_LOCK_UNLOCKED,				\
+	.count		= n,						\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name,1)
@@ -95,9 +88,6 @@ asmlinkage void __up(struct semaphore * sem);
 
 extern __inline__ void down(struct semaphore * sem)
 {
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	spin_lock_irq(&sem->sentry);
 	if (sem->count > 0) {
@@ -111,9 +101,6 @@ extern __inline__ void down(struct semaphore * sem)
 extern __inline__ int down_interruptible(struct semaphore * sem)
 {
 	int ret = 0;
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 	spin_lock_irq(&sem->sentry);
 	if (sem->count > 0) {
@@ -132,9 +119,6 @@ extern __inline__ int down_interruptible(struct semaphore * sem)
 extern __inline__ int down_trylock(struct semaphore * sem)
 {
 	int flags, count;
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 
 	spin_lock_irqsave(&sem->sentry, flags);
 	count = sem->count - 1;
@@ -151,9 +135,6 @@ extern __inline__ int down_trylock(struct semaphore * sem)
 extern __inline__ void up(struct semaphore * sem)
 {
 	int flags;
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	spin_lock_irqsave(&sem->sentry, flags);
 	if (sem->count < 0) {
 		__up(sem);
diff --git a/include/asm-parisc/socket.h b/include/asm-parisc/socket.h
index fd3f0f29e..4a77996c1 100644
--- a/include/asm-parisc/socket.h
+++ b/include/asm-parisc/socket.h
@@ -47,18 +47,4 @@
 
 #define SO_PEERSEC		0x401d
 
-#if defined(__KERNEL__)
-#define SOCK_STREAM	1	/* stream (connection) socket	*/
-#define SOCK_DGRAM	2	/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3	/* raw socket			*/
-#define SOCK_RDM	4	/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5	/* sequential packet socket	*/
-#define SOCK_PACKET	10	/* linux specific way of	*/
-				/* getting packets at the dev	*/
-				/* level.  For writing rarp and	*/
-				/* other similar things on the	*/
-				/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-parisc/uaccess.h b/include/asm-parisc/uaccess.h
index f147bac9d..ee2e2a5f0 100644
--- a/include/asm-parisc/uaccess.h
+++ b/include/asm-parisc/uaccess.h
@@ -279,5 +279,7 @@ extern long lstrnlen_user(const char __user *,long);
 #define __copy_to_user lcopy_to_user
 #define copy_in_user lcopy_in_user
 #define __copy_in_user lcopy_in_user
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 
 #endif /* __PARISC_UACCESS_H */
diff --git a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h
index 2a3434de2..ccff9198e 100644
--- a/include/asm-parisc/unistd.h
+++ b/include/asm-parisc/unistd.h
@@ -730,7 +730,7 @@
 
 #define __NR_vserver		(__NR_Linux + 273)
 
-#define __NR_Linux_syscalls     273
+#define __NR_Linux_syscalls	273
 
 #define HPUX_GATEWAY_ADDR       0xC0000004
 #define LINUX_GATEWAY_ADDR      0x100
diff --git a/include/asm-ppc/bug.h b/include/asm-ppc/bug.h
index 6b2579d9d..e99c6cb9d 100644
--- a/include/asm-ppc/bug.h
+++ b/include/asm-ppc/bug.h
@@ -35,8 +35,6 @@ struct bug_entry {
 	}								\
 } while (0)
 
-#define PAGE_BUG(page)	BUG()
-
 #define WARN_ON(x) do {							\
 	if (!__builtin_constant_p(x) || (x)) {				\
 		__asm__ __volatile__(					\
@@ -49,4 +47,9 @@ struct bug_entry {
 	}								\
 } while (0)
 
+#define HAVE_ARCH_BUG
+#define HAVE_ARCH_BUG_ON
+#define HAVE_ARCH_WARN_ON
+#include <asm-generic/bug.h>
+
 #endif
diff --git a/include/asm-ppc/checksum.h b/include/asm-ppc/checksum.h
index d98a93d82..cf953a92c 100644
--- a/include/asm-ppc/checksum.h
+++ b/include/asm-ppc/checksum.h
@@ -33,7 +33,7 @@ extern unsigned int csum_partial_copy_generic(const char *src, char *dst,
 					      int *src_err, int *dst_err);
 
 #define csum_partial_copy_from_user(src, dst, len, sum, errp)	\
-	csum_partial_copy_generic((src), (dst), (len), (sum), (errp), NULL)
+	csum_partial_copy_generic((__force void *)(src), (dst), (len), (sum), (errp), NULL)
 
 /* FIXME: this needs to be written to really do no check -- Cort */
 #define csum_partial_copy_nocheck(src, dst, len, sum)	\
diff --git a/include/asm-ppc/dma-mapping.h b/include/asm-ppc/dma-mapping.h
index 9be4f7297..7f0487afe 100644
--- a/include/asm-ppc/dma-mapping.h
+++ b/include/asm-ppc/dma-mapping.h
@@ -8,7 +8,6 @@
 #include <linux/config.h>
 /* need struct page definitions */
 #include <linux/mm.h>
-#include <linux/device.h>
 #include <asm/scatterlist.h>
 #include <asm/io.h>
 
diff --git a/include/asm-ppc/fsl_ocp.h b/include/asm-ppc/fsl_ocp.h
index 9f88999d4..050fbba8d 100644
--- a/include/asm-ppc/fsl_ocp.h
+++ b/include/asm-ppc/fsl_ocp.h
@@ -48,7 +48,7 @@ struct ocp_fs_i2c_data {
 
 /* Flags for I2C */
 #define FS_I2C_SEPARATE_DFSRR	0x02
-#define FS_I2C_32BIT		0x01
+#define FS_I2C_CLOCK_5200	0x01
 
 #endif	/* __ASM_FS_OCP_H__ */
 #endif	/* __KERNEL__ */
diff --git a/include/asm-ppc/hardirq.h b/include/asm-ppc/hardirq.h
index 2531c3bdb..dfb847253 100644
--- a/include/asm-ppc/hardirq.h
+++ b/include/asm-ppc/hardirq.h
@@ -44,20 +44,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -67,31 +53,7 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define preemptible()	(preempt_count() == 0 && !irqs_disabled())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define preemptible()	0
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #define irq_exit()							\
 do {									\
 	preempt_count() -= IRQ_EXIT_OFFSET;				\
@@ -100,11 +62,5 @@ do {									\
 	preempt_enable_no_resched();					\
 } while (0)
 
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else
-  extern void synchronize_irq(unsigned int irq);
-#endif /* CONFIG_SMP */
-
 #endif /* __ASM_HARDIRQ_H */
 #endif /* __KERNEL__ */
diff --git a/include/asm-ppc/ibm44x.h b/include/asm-ppc/ibm44x.h
index bed6a7e01..2aea5c891 100644
--- a/include/asm-ppc/ibm44x.h
+++ b/include/asm-ppc/ibm44x.h
@@ -94,8 +94,8 @@
 #define DCRN_SDR_CONFIG_DATA	0xf
 #define DCRN_SDR_PFC0		0x4100
 #define DCRN_SDR_PFC1		0x4101
-#define DCRN_SDR_PFC1_EPS	0x1c000000
-#define DCRN_SDR_PFC1_EPS_SHIFT	26
+#define DCRN_SDR_PFC1_EPS	0x1c00000
+#define DCRN_SDR_PFC1_EPS_SHIFT	22
 #define DCRN_SDR_PFC1_RMII	0x02000000
 #define DCRN_SDR_MFR		0x4300
 #define DCRN_SDR_MFR_TAH0 	0x80000000  	/* TAHOE0 Enable */
diff --git a/include/asm-ppc/ide.h b/include/asm-ppc/ide.h
index 6c091582d..7d6e6599f 100644
--- a/include/asm-ppc/ide.h
+++ b/include/asm-ppc/ide.h
@@ -24,10 +24,10 @@
 #include <linux/ioport.h>
 #include <asm/io.h>
 
-extern void __ide_mm_insw(unsigned long port, void *addr, u32 count);
-extern void __ide_mm_outsw(unsigned long port, void *addr, u32 count);
-extern void __ide_mm_insl(unsigned long port, void *addr, u32 count);
-extern void __ide_mm_outsl(unsigned long port, void *addr, u32 count);
+extern void __ide_mm_insw(void __iomem *port, void *addr, u32 count);
+extern void __ide_mm_outsw(void __iomem *port, void *addr, u32 count);
+extern void __ide_mm_insl(void __iomem *port, void *addr, u32 count);
+extern void __ide_mm_outsl(void __iomem *port, void *addr, u32 count);
 
 struct ide_machdep_calls {
         int         (*default_irq)(unsigned long base);
diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h
index a893418be..5abdd426b 100644
--- a/include/asm-ppc/io.h
+++ b/include/asm-ppc/io.h
@@ -4,7 +4,6 @@
 
 #include <linux/config.h>
 #include <linux/types.h>
-#include <linux/mm.h>
 
 #include <asm/page.h>
 #include <asm/byteorder.h>
@@ -399,6 +398,79 @@ static inline int isa_check_signature(unsigned long io_addr,
 	return 0;
 }
 
+/*
+ * Here comes the ppc implementation of the IOMAP 
+ * interfaces.
+ */
+static inline unsigned int ioread8(void __iomem *addr)
+{
+	return readb(addr);
+}
+
+static inline unsigned int ioread16(void __iomem *addr)
+{
+	return readw(addr);
+}
+
+static inline unsigned int ioread32(void __iomem *addr)
+{
+	return readl(addr);
+}
+
+static inline void iowrite8(u8 val, void __iomem *addr)
+{
+	writeb(val, addr);
+}
+
+static inline void iowrite16(u16 val, void __iomem *addr)
+{
+	writew(val, addr);
+}
+
+static inline void iowrite32(u32 val, void __iomem *addr)
+{
+	writel(val, addr);
+}
+
+static inline void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	_insb((u8 __force *) addr, dst, count);
+}
+
+static inline void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	_insw_ns((u16 __force *) addr, dst, count);
+}
+
+static inline void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	_insl_ns((u32 __force *) addr, dst, count);
+}
+
+static inline void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	_outsb((u8 __force *) addr, src, count);
+}
+
+static inline void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	_outsw_ns((u16 __force *) addr, src, count);
+}
+
+static inline void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	_outsl_ns((u32 __force *) addr, src, count);
+}
+
+/* Create a virtual mapping cookie for an IO port range */
+extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
+extern void ioport_unmap(void __iomem *);
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+struct pci_dev;
+extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
+extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
+
 #endif /* _PPC_IO_H */
 
 #ifdef CONFIG_8260_PCI9
diff --git a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
index 4fb6e572b..76e4402f7 100644
--- a/include/asm-ppc/mpc52xx.h
+++ b/include/asm-ppc/mpc52xx.h
@@ -42,6 +42,7 @@ struct ocp_def;
 #define MPC52xx_MBAR_VIRT	0xf0000000	/* Virt address */
 
 #define MPC52xx_MMAP_CTL	(MPC52xx_MBAR + 0x0000)
+#define MPC52xx_SDRAM		(MPC52xx_MBAR + 0x0100)
 #define MPC52xx_CDM		(MPC52xx_MBAR + 0x0200)
 #define MPC52xx_SFTRST		(MPC52xx_MBAR + 0x0220)
 #define MPC52xx_SFTRST_BIT	0x01000000
@@ -51,6 +52,7 @@ struct ocp_def;
 #define MPC52xx_MSCAN1		(MPC52xx_MBAR + 0x0900)
 #define MPC52xx_MSCAN2		(MPC52xx_MBAR + 0x0980)
 #define MPC52xx_GPIO		(MPC52xx_MBAR + 0x0b00)
+#define MPC52xx_GPIO_WKUP	(MPC52xx_MBAR + 0x0c00)
 #define MPC52xx_PCI		(MPC52xx_MBAR + 0x0d00)
 #define MPC52xx_USB_OHCI	(MPC52xx_MBAR + 0x1000)
 #define MPC52xx_SDMA		(MPC52xx_MBAR + 0x1200)
@@ -71,10 +73,6 @@ struct ocp_def;
 /* SRAM used for SDMA */
 #define MPC52xx_SRAM		(MPC52xx_MBAR + 0x8000)
 #define MPC52xx_SRAM_SIZE	(16*1024)
-#define MPC52xx_SDMA_MAX_TASKS	16
-
-	/* Memory allocation block size */
-#define MPC52xx_SDRAM_UNIT	0x8000		/* 32K byte */
 
 
 /* ======================================================================== */
@@ -137,206 +135,240 @@ struct ocp_def;
 
 /* Memory Mapping Control */
 struct mpc52xx_mmap_ctl {
-	volatile u32	mbar;		/* MMAP_CTRL + 0x00 */
-
-	volatile u32	cs0_start;	/* MMAP_CTRL + 0x04 */
-	volatile u32	cs0_stop;	/* MMAP_CTRL + 0x08 */
-	volatile u32	cs1_start;	/* MMAP_CTRL + 0x0c */
-	volatile u32	cs1_stop;	/* MMAP_CTRL + 0x10 */
-	volatile u32	cs2_start;	/* MMAP_CTRL + 0x14 */
-	volatile u32	cs2_stop;	/* MMAP_CTRL + 0x18 */
-	volatile u32	cs3_start;	/* MMAP_CTRL + 0x1c */
-	volatile u32	cs3_stop;	/* MMAP_CTRL + 0x20 */
-	volatile u32	cs4_start;	/* MMAP_CTRL + 0x24 */
-	volatile u32	cs4_stop;	/* MMAP_CTRL + 0x28 */
-	volatile u32	cs5_start;	/* MMAP_CTRL + 0x2c */
-	volatile u32	cs5_stop;	/* MMAP_CTRL + 0x30 */
-
-	volatile u32	sdram0;		/* MMAP_CTRL + 0x34 */
-	volatile u32	sdram1;		/* MMAP_CTRL + 0X38 */
-
-	volatile u32	reserved[4];	/* MMAP_CTRL + 0x3c .. 0x48 */
-
-	volatile u32	boot_start;	/* MMAP_CTRL + 0x4c */
-	volatile u32	boot_stop;	/* MMAP_CTRL + 0x50 */
-	
-	volatile u32	ipbi_ws_ctrl;	/* MMAP_CTRL + 0x54 */
-	
-	volatile u32	cs6_start;	/* MMAP_CTRL + 0x58 */
-	volatile u32	cs6_stop;	/* MMAP_CTRL + 0x5c */
-	volatile u32	cs7_start;	/* MMAP_CTRL + 0x60 */
-	volatile u32	cs7_stop;	/* MMAP_CTRL + 0x60 */
+	u32	mbar;		/* MMAP_CTRL + 0x00 */
+
+	u32	cs0_start;	/* MMAP_CTRL + 0x04 */
+	u32	cs0_stop;	/* MMAP_CTRL + 0x08 */
+	u32	cs1_start;	/* MMAP_CTRL + 0x0c */
+	u32	cs1_stop;	/* MMAP_CTRL + 0x10 */
+	u32	cs2_start;	/* MMAP_CTRL + 0x14 */
+	u32	cs2_stop;	/* MMAP_CTRL + 0x18 */
+	u32	cs3_start;	/* MMAP_CTRL + 0x1c */
+	u32	cs3_stop;	/* MMAP_CTRL + 0x20 */
+	u32	cs4_start;	/* MMAP_CTRL + 0x24 */
+	u32	cs4_stop;	/* MMAP_CTRL + 0x28 */
+	u32	cs5_start;	/* MMAP_CTRL + 0x2c */
+	u32	cs5_stop;	/* MMAP_CTRL + 0x30 */
+
+	u32	sdram0;		/* MMAP_CTRL + 0x34 */
+	u32	sdram1;		/* MMAP_CTRL + 0X38 */
+
+	u32	reserved[4];	/* MMAP_CTRL + 0x3c .. 0x48 */
+
+	u32	boot_start;	/* MMAP_CTRL + 0x4c */
+	u32	boot_stop;	/* MMAP_CTRL + 0x50 */
+
+	u32	ipbi_ws_ctrl;	/* MMAP_CTRL + 0x54 */
+
+	u32	cs6_start;	/* MMAP_CTRL + 0x58 */
+	u32	cs6_stop;	/* MMAP_CTRL + 0x5c */
+	u32	cs7_start;	/* MMAP_CTRL + 0x60 */
+	u32	cs7_stop;	/* MMAP_CTRL + 0x60 */
+};
+
+/* SDRAM control */
+struct mpc52xx_sdram {
+	u32	mode;		/* SDRAM + 0x00 */
+	u32	ctrl;		/* SDRAM + 0x04 */
+	u32	config1;	/* SDRAM + 0x08 */
+	u32	config2;	/* SDRAM + 0x0c */
 };
 
 /* Interrupt controller */
 struct mpc52xx_intr {
-	volatile u32	per_mask;	/* INTR + 0x00 */
-	volatile u32	per_pri1;	/* INTR + 0x04 */
-	volatile u32	per_pri2;	/* INTR + 0x08 */
-	volatile u32	per_pri3;	/* INTR + 0x0c */
-	volatile u32	ctrl;		/* INTR + 0x10 */
-	volatile u32	main_mask;	/* INTR + 0x14 */
-	volatile u32	main_pri1;	/* INTR + 0x18 */
-	volatile u32	main_pri2;	/* INTR + 0x1c */
-	volatile u32	reserved1;	/* INTR + 0x20 */
-	volatile u32	enc_status;	/* INTR + 0x24 */
-	volatile u32	crit_status;	/* INTR + 0x28 */
-	volatile u32	main_status;	/* INTR + 0x2c */
-	volatile u32	per_status;	/* INTR + 0x30 */
-	volatile u32	reserved2;	/* INTR + 0x34 */
-	volatile u32	per_error;	/* INTR + 0x38 */
+	u32	per_mask;	/* INTR + 0x00 */
+	u32	per_pri1;	/* INTR + 0x04 */
+	u32	per_pri2;	/* INTR + 0x08 */
+	u32	per_pri3;	/* INTR + 0x0c */
+	u32	ctrl;		/* INTR + 0x10 */
+	u32	main_mask;	/* INTR + 0x14 */
+	u32	main_pri1;	/* INTR + 0x18 */
+	u32	main_pri2;	/* INTR + 0x1c */
+	u32	reserved1;	/* INTR + 0x20 */
+	u32	enc_status;	/* INTR + 0x24 */
+	u32	crit_status;	/* INTR + 0x28 */
+	u32	main_status;	/* INTR + 0x2c */
+	u32	per_status;	/* INTR + 0x30 */
+	u32	reserved2;	/* INTR + 0x34 */
+	u32	per_error;	/* INTR + 0x38 */
 };
 
 /* SDMA */
 struct mpc52xx_sdma {
-	volatile u32	taskBar;	/* SDMA + 0x00 */
-	volatile u32	currentPointer;	/* SDMA + 0x04 */
-	volatile u32	endPointer;	/* SDMA + 0x08 */
-	volatile u32	variablePointer;/* SDMA + 0x0c */
-
-	volatile u8	IntVect1;	/* SDMA + 0x10 */
-	volatile u8	IntVect2;	/* SDMA + 0x11 */
-	volatile u16	PtdCntrl;	/* SDMA + 0x12 */
-
-	volatile u32	IntPend;	/* SDMA + 0x14 */
-	volatile u32	IntMask;	/* SDMA + 0x18 */
-	
-	volatile u16	tcr[16];	/* SDMA + 0x1c .. 0x3a */
-
-	volatile u8	ipr[31];	/* SDMA + 0x3c .. 5b */
-
-	volatile u32	res1;		/* SDMA + 0x5c */
-	volatile u32	task_size0;	/* SDMA + 0x60 */
-	volatile u32	task_size1;	/* SDMA + 0x64 */
-	volatile u32	MDEDebug;	/* SDMA + 0x68 */
-	volatile u32	ADSDebug;	/* SDMA + 0x6c */
-	volatile u32	Value1;		/* SDMA + 0x70 */
-	volatile u32	Value2;		/* SDMA + 0x74 */
-	volatile u32	Control;	/* SDMA + 0x78 */
-	volatile u32	Status;		/* SDMA + 0x7c */
+	u32	taskBar;	/* SDMA + 0x00 */
+	u32	currentPointer;	/* SDMA + 0x04 */
+	u32	endPointer;	/* SDMA + 0x08 */
+	u32	variablePointer;/* SDMA + 0x0c */
+
+	u8	IntVect1;	/* SDMA + 0x10 */
+	u8	IntVect2;	/* SDMA + 0x11 */
+	u16	PtdCntrl;	/* SDMA + 0x12 */
+
+	u32	IntPend;	/* SDMA + 0x14 */
+	u32	IntMask;	/* SDMA + 0x18 */
+
+	u16	tcr[16];	/* SDMA + 0x1c .. 0x3a */
+
+	u8	ipr[32];	/* SDMA + 0x3c .. 5b */
+
+	u32	cReqSelect;	/* SDMA + 0x5c */
+	u32	task_size0;	/* SDMA + 0x60 */
+	u32	task_size1;	/* SDMA + 0x64 */
+	u32	MDEDebug;	/* SDMA + 0x68 */
+	u32	ADSDebug;	/* SDMA + 0x6c */
+	u32	Value1;		/* SDMA + 0x70 */
+	u32	Value2;		/* SDMA + 0x74 */
+	u32	Control;	/* SDMA + 0x78 */
+	u32	Status;		/* SDMA + 0x7c */
+	u32	PTDDebug;	/* SDMA + 0x80 */
 };
 
 /* GPT */
 struct mpc52xx_gpt {
-	volatile u32	mode;		/* GPTx + 0x00 */
-	volatile u32	count;		/* GPTx + 0x04 */
-	volatile u32	pwm;		/* GPTx + 0x08 */
-	volatile u32	status;		/* GPTx + 0X0c */
+	u32	mode;		/* GPTx + 0x00 */
+	u32	count;		/* GPTx + 0x04 */
+	u32	pwm;		/* GPTx + 0x08 */
+	u32	status;		/* GPTx + 0X0c */
 };
 
 /* RTC */
 struct mpc52xx_rtc {
-	volatile u32	time_set;	/* RTC + 0x00 */
-	volatile u32	date_set;	/* RTC + 0x04 */
-	volatile u32	stopwatch;	/* RTC + 0x08 */
-	volatile u32	int_enable;	/* RTC + 0x0c */
-	volatile u32	time;		/* RTC + 0x10 */
-	volatile u32	date;		/* RTC + 0x14 */
-	volatile u32	stopwatch_intr;	/* RTC + 0x18 */
-	volatile u32	bus_error;	/* RTC + 0x1c */
-	volatile u32	dividers;	/* RTC + 0x20 */
+	u32	time_set;	/* RTC + 0x00 */
+	u32	date_set;	/* RTC + 0x04 */
+	u32	stopwatch;	/* RTC + 0x08 */
+	u32	int_enable;	/* RTC + 0x0c */
+	u32	time;		/* RTC + 0x10 */
+	u32	date;		/* RTC + 0x14 */
+	u32	stopwatch_intr;	/* RTC + 0x18 */
+	u32	bus_error;	/* RTC + 0x1c */
+	u32	dividers;	/* RTC + 0x20 */
 };
 
 /* GPIO */
 struct mpc52xx_gpio {
-	volatile u32	port_config;	/* GPIO + 0x00 */
-	volatile u32	simple_gpioe;	/* GPIO + 0x04 */
-	volatile u32	simple_ode;	/* GPIO + 0x08 */
-	volatile u32	simple_ddr;	/* GPIO + 0x0c */
-	volatile u32	simple_dvo;	/* GPIO + 0x10 */
-	volatile u32	simple_ival;	/* GPIO + 0x14 */
-	volatile u8	outo_gpioe;	/* GPIO + 0x18 */
-	volatile u8	reserved1[3];	/* GPIO + 0x19 */
-	volatile u8	outo_dvo;	/* GPIO + 0x1c */
-	volatile u8	reserved2[3];	/* GPIO + 0x1d */
-	volatile u8	sint_gpioe;	/* GPIO + 0x20 */
-	volatile u8	reserved3[3];	/* GPIO + 0x21 */
-	volatile u8	sint_ode;	/* GPIO + 0x24 */
-	volatile u8	reserved4[3];	/* GPIO + 0x25 */
-	volatile u8	sint_ddr;	/* GPIO + 0x28 */
-	volatile u8	reserved5[3];	/* GPIO + 0x29 */
-	volatile u8	sint_dvo;	/* GPIO + 0x2c */
-	volatile u8	reserved6[3];	/* GPIO + 0x2d */
-	volatile u8	sint_inten;	/* GPIO + 0x30 */
-	volatile u8	reserved7[3];	/* GPIO + 0x31 */
-	volatile u16	sint_itype;	/* GPIO + 0x34 */
-	volatile u16	reserved8;	/* GPIO + 0x36 */
-	volatile u8	gpio_control;	/* GPIO + 0x38 */
-	volatile u8	reserved9[3];	/* GPIO + 0x39 */
-	volatile u8	sint_istat;	/* GPIO + 0x3c */
-	volatile u8	sint_ival;	/* GPIO + 0x3d */
-	volatile u8	bus_errs;	/* GPIO + 0x3e */
-	volatile u8	reserved10;	/* GPIO + 0x3f */
+	u32	port_config;	/* GPIO + 0x00 */
+	u32	simple_gpioe;	/* GPIO + 0x04 */
+	u32	simple_ode;	/* GPIO + 0x08 */
+	u32	simple_ddr;	/* GPIO + 0x0c */
+	u32	simple_dvo;	/* GPIO + 0x10 */
+	u32	simple_ival;	/* GPIO + 0x14 */
+	u8	outo_gpioe;	/* GPIO + 0x18 */
+	u8	reserved1[3];	/* GPIO + 0x19 */
+	u8	outo_dvo;	/* GPIO + 0x1c */
+	u8	reserved2[3];	/* GPIO + 0x1d */
+	u8	sint_gpioe;	/* GPIO + 0x20 */
+	u8	reserved3[3];	/* GPIO + 0x21 */
+	u8	sint_ode;	/* GPIO + 0x24 */
+	u8	reserved4[3];	/* GPIO + 0x25 */
+	u8	sint_ddr;	/* GPIO + 0x28 */
+	u8	reserved5[3];	/* GPIO + 0x29 */
+	u8	sint_dvo;	/* GPIO + 0x2c */
+	u8	reserved6[3];	/* GPIO + 0x2d */
+	u8	sint_inten;	/* GPIO + 0x30 */
+	u8	reserved7[3];	/* GPIO + 0x31 */
+	u16	sint_itype;	/* GPIO + 0x34 */
+	u16	reserved8;	/* GPIO + 0x36 */
+	u8	gpio_control;	/* GPIO + 0x38 */
+	u8	reserved9[3];	/* GPIO + 0x39 */
+	u8	sint_istat;	/* GPIO + 0x3c */
+	u8	sint_ival;	/* GPIO + 0x3d */
+	u8	bus_errs;	/* GPIO + 0x3e */
+	u8	reserved10;	/* GPIO + 0x3f */
 };
 
 #define MPC52xx_GPIO_PSC_CONFIG_UART_WITHOUT_CD	4
 #define MPC52xx_GPIO_PSC_CONFIG_UART_WITH_CD	5
 #define MPC52xx_GPIO_PCI_DIS			(1<<15)
 
+/* GPIO with WakeUp*/
+struct mpc52xx_gpio_wkup {
+	u8	wkup_gpioe;	/* GPIO_WKUP + 0x00 */
+	u8	reserved1[3];	/* GPIO_WKUP + 0x03 */
+	u8	wkup_ode;	/* GPIO_WKUP + 0x04 */
+	u8	reserved2[3];	/* GPIO_WKUP + 0x05 */
+	u8	wkup_ddr;	/* GPIO_WKUP + 0x08 */
+	u8	reserved3[3];	/* GPIO_WKUP + 0x09 */
+	u8	wkup_dvo;	/* GPIO_WKUP + 0x0C */
+	u8	reserved4[3];	/* GPIO_WKUP + 0x0D */
+	u8	wkup_inten;	/* GPIO_WKUP + 0x10 */
+	u8	reserved5[3];	/* GPIO_WKUP + 0x11 */
+	u8	wkup_iinten;	/* GPIO_WKUP + 0x14 */
+	u8	reserved6[3];	/* GPIO_WKUP + 0x15 */
+	u16	wkup_itype;	/* GPIO_WKUP + 0x18 */
+	u8	reserved7[2];	/* GPIO_WKUP + 0x1A */
+	u8	wkup_maste;	/* GPIO_WKUP + 0x1C */
+	u8	reserved8[3];	/* GPIO_WKUP + 0x1D */
+	u8	wkup_ival;	/* GPIO_WKUP + 0x20 */
+	u8	reserved9[3];	/* GPIO_WKUP + 0x21 */
+	u8	wkup_istat;	/* GPIO_WKUP + 0x24 */
+	u8	reserved10[3];	/* GPIO_WKUP + 0x25 */
+};
+
 /* XLB Bus control */
 struct mpc52xx_xlb {
-	volatile u8 reserved[0x40];
-	volatile u32 config;		/* XLB + 0x40 */
-	volatile u32 version;		/* XLB + 0x44 */
-	volatile u32 status;		/* XLB + 0x48 */
-	volatile u32 int_enable;	/* XLB + 0x4c */
-	volatile u32 addr_capture;	/* XLB + 0x50 */
-	volatile u32 bus_sig_capture;	/* XLB + 0x54 */
-	volatile u32 addr_timeout;	/* XLB + 0x58 */
-	volatile u32 data_timeout;	/* XLB + 0x5c */
-	volatile u32 bus_act_timeout;	/* XLB + 0x60 */
-	volatile u32 master_pri_enable;	/* XLB + 0x64 */
-	volatile u32 master_priority;	/* XLB + 0x68 */
-	volatile u32 base_address;	/* XLB + 0x6c */
-	volatile u32 snoop_window;	/* XLB + 0x70 */
+	u8	reserved[0x40];
+	u32	config;			/* XLB + 0x40 */
+	u32	version;		/* XLB + 0x44 */
+	u32	status;			/* XLB + 0x48 */
+	u32	int_enable;		/* XLB + 0x4c */
+	u32	addr_capture;		/* XLB + 0x50 */
+	u32	bus_sig_capture;	/* XLB + 0x54 */
+	u32	addr_timeout;		/* XLB + 0x58 */
+	u32	data_timeout;		/* XLB + 0x5c */
+	u32	bus_act_timeout;	/* XLB + 0x60 */
+	u32	master_pri_enable;	/* XLB + 0x64 */
+	u32	master_priority;	/* XLB + 0x68 */
+	u32	base_address;		/* XLB + 0x6c */
+	u32	snoop_window;		/* XLB + 0x70 */
 };
 
+#define MPC52xx_XLB_CFG_SNOOP		(1 << 15)
 
 /* Clock Distribution control */
 struct mpc52xx_cdm {
-	volatile u32	jtag_id;	/* MBAR_CDM + 0x00  reg0 read only */
-	volatile u32	rstcfg;		/* MBAR_CDM + 0x04  reg1 read only */
-	volatile u32	breadcrumb;	/* MBAR_CDM + 0x08  reg2 */
-
-	volatile u8	mem_clk_sel;	/* MBAR_CDM + 0x0c  reg3 byte0 */
-	volatile u8	xlb_clk_sel;	/* MBAR_CDM + 0x0d  reg3 byte1 read only */
-	volatile u8	ipb_clk_sel;	/* MBAR_CDM + 0x0e  reg3 byte2 */
-	volatile u8	pci_clk_sel;	/* MBAR_CDM + 0x0f  reg3 byte3 */
-
-	volatile u8	ext_48mhz_en;	/* MBAR_CDM + 0x10  reg4 byte0 */
-	volatile u8	fd_enable;	/* MBAR_CDM + 0x11  reg4 byte1 */
-	volatile u16	fd_counters;	/* MBAR_CDM + 0x12  reg4 byte2,3 */
-
-	volatile u32	clk_enables;	/* MBAR_CDM + 0x14  reg5 */
-
-	volatile u8	osc_disable;	/* MBAR_CDM + 0x18  reg6 byte0 */
-	volatile u8	reserved0[3];	/* MBAR_CDM + 0x19  reg6 byte1,2,3 */
-
-	volatile u8	ccs_sleep_enable;/* MBAR_CDM + 0x1c  reg7 byte0 */
-	volatile u8	osc_sleep_enable;/* MBAR_CDM + 0x1d  reg7 byte1 */
-	volatile u8	reserved1;	/* MBAR_CDM + 0x1e  reg7 byte2 */
-	volatile u8	ccs_qreq_test;	/* MBAR_CDM + 0x1f  reg7 byte3 */
-
-	volatile u8	soft_reset;	/* MBAR_CDM + 0x20  u8 byte0 */
-	volatile u8	no_ckstp;	/* MBAR_CDM + 0x21  u8 byte0 */
-	volatile u8	reserved2[2];	/* MBAR_CDM + 0x22  u8 byte1,2,3 */
-
-	volatile u8	pll_lock;	/* MBAR_CDM + 0x24  reg9 byte0 */
-	volatile u8	pll_looselock;	/* MBAR_CDM + 0x25  reg9 byte1 */
-	volatile u8	pll_sm_lockwin;	/* MBAR_CDM + 0x26  reg9 byte2 */
-	volatile u8	reserved3;	/* MBAR_CDM + 0x27  reg9 byte3 */
-
-	volatile u16	reserved4;	/* MBAR_CDM + 0x28  reg10 byte0,1 */
-	volatile u16	mclken_div_psc1;/* MBAR_CDM + 0x2a  reg10 byte2,3 */
-    
-	volatile u16	reserved5;	/* MBAR_CDM + 0x2c  reg11 byte0,1 */
-	volatile u16	mclken_div_psc2;/* MBAR_CDM + 0x2e  reg11 byte2,3 */
-		
-	volatile u16	reserved6;	/* MBAR_CDM + 0x30  reg12 byte0,1 */
-	volatile u16	mclken_div_psc3;/* MBAR_CDM + 0x32  reg12 byte2,3 */
-    
-	volatile u16	reserved7;	/* MBAR_CDM + 0x34  reg13 byte0,1 */
-	volatile u16	mclken_div_psc6;/* MBAR_CDM + 0x36  reg13 byte2,3 */
+	u32	jtag_id;		/* CDM + 0x00  reg0 read only */
+	u32	rstcfg;			/* CDM + 0x04  reg1 read only */
+	u32	breadcrumb;		/* CDM + 0x08  reg2 */
+
+	u8	mem_clk_sel;		/* CDM + 0x0c  reg3 byte0 */
+	u8	xlb_clk_sel;		/* CDM + 0x0d  reg3 byte1 read only */
+	u8	ipb_clk_sel;		/* CDM + 0x0e  reg3 byte2 */
+	u8	pci_clk_sel;		/* CDM + 0x0f  reg3 byte3 */
+
+	u8	ext_48mhz_en;		/* CDM + 0x10  reg4 byte0 */
+	u8	fd_enable;		/* CDM + 0x11  reg4 byte1 */
+	u16	fd_counters;		/* CDM + 0x12  reg4 byte2,3 */
+
+	u32	clk_enables;		/* CDM + 0x14  reg5 */
+
+	u8	osc_disable;		/* CDM + 0x18  reg6 byte0 */
+	u8	reserved0[3];		/* CDM + 0x19  reg6 byte1,2,3 */
+
+	u8	ccs_sleep_enable;	/* CDM + 0x1c  reg7 byte0 */
+	u8	osc_sleep_enable;	/* CDM + 0x1d  reg7 byte1 */
+	u8	reserved1;		/* CDM + 0x1e  reg7 byte2 */
+	u8	ccs_qreq_test;		/* CDM + 0x1f  reg7 byte3 */
+
+	u8	soft_reset;		/* CDM + 0x20  u8 byte0 */
+	u8	no_ckstp;		/* CDM + 0x21  u8 byte0 */
+	u8	reserved2[2];		/* CDM + 0x22  u8 byte1,2,3 */
+
+	u8	pll_lock;		/* CDM + 0x24  reg9 byte0 */
+	u8	pll_looselock;		/* CDM + 0x25  reg9 byte1 */
+	u8	pll_sm_lockwin;		/* CDM + 0x26  reg9 byte2 */
+	u8	reserved3;		/* CDM + 0x27  reg9 byte3 */
+
+	u16	reserved4;		/* CDM + 0x28  reg10 byte0,1 */
+	u16	mclken_div_psc1;	/* CDM + 0x2a  reg10 byte2,3 */
+
+	u16	reserved5;		/* CDM + 0x2c  reg11 byte0,1 */
+	u16	mclken_div_psc2;	/* CDM + 0x2e  reg11 byte2,3 */
+
+	u16	reserved6;		/* CDM + 0x30  reg12 byte0,1 */
+	u16	mclken_div_psc3;	/* CDM + 0x32  reg12 byte2,3 */
+
+	u16	reserved7;		/* CDM + 0x34  reg13 byte0,1 */
+	u16	mclken_div_psc6;	/* CDM + 0x36  reg13 byte2,3 */
 };
 
 #endif /* __ASSEMBLY__ */
diff --git a/include/asm-ppc/mpc52xx_psc.h b/include/asm-ppc/mpc52xx_psc.h
index 483102ea6..9d850b2b2 100644
--- a/include/asm-ppc/mpc52xx_psc.h
+++ b/include/asm-ppc/mpc52xx_psc.h
@@ -19,8 +19,8 @@
  * kind, whether express or implied.
  */
 
-#ifndef __MPC52xx_PSC_H__
-#define __MPC52xx_PSC_H__
+#ifndef __ASM_MPC52xx_PSC_H__
+#define __ASM_MPC52xx_PSC_H__
 
 #include <asm/types.h>
 
@@ -95,97 +95,97 @@
 
 /* Structure of the hardware registers */
 struct mpc52xx_psc {
-	volatile u8		mode;		/* PSC + 0x00 */
-	volatile u8		reserved0[3];
-	union {					/* PSC + 0x04 */
-		volatile u16	status;
-		volatile u16	clock_select;
+	u8		mode;		/* PSC + 0x00 */
+	u8		reserved0[3];
+	union {				/* PSC + 0x04 */
+		u16	status;
+		u16	clock_select;
 	} sr_csr;
 #define mpc52xx_psc_status	sr_csr.status
-#define mpc52xx_psc_clock_select	sr_csr.clock_select
-	volatile u16		reserved1;
-	volatile u8		command;	/* PSC + 0x08 */
-volatile u8		reserved2[3];
-	union {					/* PSC + 0x0c */
-		volatile u8	buffer_8;
-		volatile u16	buffer_16;
-		volatile u32	buffer_32;
+#define mpc52xx_psc_clock_select sr_csr.clock_select
+	u16		reserved1;
+	u8		command;	/* PSC + 0x08 */
+	u8		reserved2[3];
+	union {				/* PSC + 0x0c */
+		u8	buffer_8;
+		u16	buffer_16;
+		u32	buffer_32;
 	} buffer;
 #define mpc52xx_psc_buffer_8	buffer.buffer_8
 #define mpc52xx_psc_buffer_16	buffer.buffer_16
 #define mpc52xx_psc_buffer_32	buffer.buffer_32
-	union {					/* PSC + 0x10 */
-		volatile u8	ipcr;
-		volatile u8	acr;
+	union {				/* PSC + 0x10 */
+		u8	ipcr;
+		u8	acr;
 	} ipcr_acr;
 #define mpc52xx_psc_ipcr	ipcr_acr.ipcr
 #define mpc52xx_psc_acr		ipcr_acr.acr
-	volatile u8		reserved3[3];
-	union {					/* PSC + 0x14 */
-		volatile u16	isr;
-		volatile u16	imr;
+	u8		reserved3[3];
+	union {				/* PSC + 0x14 */
+		u16	isr;
+		u16	imr;
 	} isr_imr;
 #define mpc52xx_psc_isr		isr_imr.isr
 #define mpc52xx_psc_imr		isr_imr.imr
-	volatile u16		reserved4;
-	volatile u8		ctur;		/* PSC + 0x18 */
-	volatile u8		reserved5[3];
-	volatile u8		ctlr;		/* PSC + 0x1c */
-	volatile u8		reserved6[3];
-	volatile u16		ccr;		/* PSC + 0x20 */
-	volatile u8		reserved7[14];
-	volatile u8		ivr;		/* PSC + 0x30 */
-	volatile u8		reserved8[3];
-	volatile u8		ip;		/* PSC + 0x34 */
-	volatile u8		reserved9[3];
-	volatile u8		op1;		/* PSC + 0x38 */
-	volatile u8		reserved10[3];
-	volatile u8		op0;		/* PSC + 0x3c */
-	volatile u8		reserved11[3];
-	volatile u32		sicr;		/* PSC + 0x40 */
-	volatile u8		ircr1;		/* PSC + 0x44 */
-	volatile u8		reserved13[3];
-	volatile u8		ircr2;		/* PSC + 0x44 */
-	volatile u8		reserved14[3];
-	volatile u8		irsdr;		/* PSC + 0x4c */
-	volatile u8		reserved15[3];
-	volatile u8		irmdr;		/* PSC + 0x50 */
-	volatile u8		reserved16[3];
-	volatile u8		irfdr;		/* PSC + 0x54 */
-	volatile u8		reserved17[3];
-	volatile u16		rfnum;		/* PSC + 0x58 */
-	volatile u16		reserved18;
-	volatile u16		tfnum;		/* PSC + 0x5c */
-	volatile u16		reserved19;
-	volatile u32		rfdata;		/* PSC + 0x60 */
-	volatile u16		rfstat;		/* PSC + 0x64 */
-	volatile u16		reserved20;
-	volatile u8		rfcntl;		/* PSC + 0x68 */
-	volatile u8		reserved21[5];
-	volatile u16		rfalarm;	/* PSC + 0x6e */
-	volatile u16		reserved22;
-	volatile u16		rfrptr;		/* PSC + 0x72 */
-	volatile u16		reserved23;
-	volatile u16		rfwptr;		/* PSC + 0x76 */
-	volatile u16		reserved24;
-	volatile u16		rflrfptr;	/* PSC + 0x7a */
-	volatile u16		reserved25;
-	volatile u16		rflwfptr;	/* PSC + 0x7e */
-	volatile u32		tfdata;		/* PSC + 0x80 */
-	volatile u16		tfstat;		/* PSC + 0x84 */
-	volatile u16		reserved26;
-	volatile u8		tfcntl;		/* PSC + 0x88 */
-	volatile u8		reserved27[5];
-	volatile u16		tfalarm;	/* PSC + 0x8e */
-	volatile u16		reserved28;
-	volatile u16		tfrptr;		/* PSC + 0x92 */
-	volatile u16		reserved29;
-	volatile u16		tfwptr;		/* PSC + 0x96 */
-	volatile u16		reserved30;
-	volatile u16		tflrfptr;	/* PSC + 0x9a */
-	volatile u16		reserved31;
-	volatile u16		tflwfptr;	/* PSC + 0x9e */
+	u16		reserved4;
+	u8		ctur;		/* PSC + 0x18 */
+	u8		reserved5[3];
+	u8		ctlr;		/* PSC + 0x1c */
+	u8		reserved6[3];
+	u16		ccr;		/* PSC + 0x20 */
+	u8		reserved7[14];
+	u8		ivr;		/* PSC + 0x30 */
+	u8		reserved8[3];
+	u8		ip;		/* PSC + 0x34 */
+	u8		reserved9[3];
+	u8		op1;		/* PSC + 0x38 */
+	u8		reserved10[3];
+	u8		op0;		/* PSC + 0x3c */
+	u8		reserved11[3];
+	u32		sicr;		/* PSC + 0x40 */
+	u8		ircr1;		/* PSC + 0x44 */
+	u8		reserved13[3];
+	u8		ircr2;		/* PSC + 0x44 */
+	u8		reserved14[3];
+	u8		irsdr;		/* PSC + 0x4c */
+	u8		reserved15[3];
+	u8		irmdr;		/* PSC + 0x50 */
+	u8		reserved16[3];
+	u8		irfdr;		/* PSC + 0x54 */
+	u8		reserved17[3];
+	u16		rfnum;		/* PSC + 0x58 */
+	u16		reserved18;
+	u16		tfnum;		/* PSC + 0x5c */
+	u16		reserved19;
+	u32		rfdata;		/* PSC + 0x60 */
+	u16		rfstat;		/* PSC + 0x64 */
+	u16		reserved20;
+	u8		rfcntl;		/* PSC + 0x68 */
+	u8		reserved21[5];
+	u16		rfalarm;	/* PSC + 0x6e */
+	u16		reserved22;
+	u16		rfrptr;		/* PSC + 0x72 */
+	u16		reserved23;
+	u16		rfwptr;		/* PSC + 0x76 */
+	u16		reserved24;
+	u16		rflrfptr;	/* PSC + 0x7a */
+	u16		reserved25;
+	u16		rflwfptr;	/* PSC + 0x7e */
+	u32		tfdata;		/* PSC + 0x80 */
+	u16		tfstat;		/* PSC + 0x84 */
+	u16		reserved26;
+	u8		tfcntl;		/* PSC + 0x88 */
+	u8		reserved27[5];
+	u16		tfalarm;	/* PSC + 0x8e */
+	u16		reserved28;
+	u16		tfrptr;		/* PSC + 0x92 */
+	u16		reserved29;
+	u16		tfwptr;		/* PSC + 0x96 */
+	u16		reserved30;
+	u16		tflrfptr;	/* PSC + 0x9a */
+	u16		reserved31;
+	u16		tflwfptr;	/* PSC + 0x9e */
 };
 
 
-#endif  /* __MPC52xx_PSC_H__ */
+#endif  /* __ASM_MPC52xx_PSC_H__ */
diff --git a/include/asm-ppc/mpc8260.h b/include/asm-ppc/mpc8260.h
index 61b6a191a..219af7fd0 100644
--- a/include/asm-ppc/mpc8260.h
+++ b/include/asm-ppc/mpc8260.h
@@ -40,6 +40,10 @@
 #include <platforms/pq2ads.h>
 #endif
 
+#ifdef CONFIG_PCI_8260
+#include <syslib/m8260_pci.h>
+#endif
+
 /* Make sure the memory translation stuff is there if PCI not used.
  */
 #ifndef _IO_BASE
diff --git a/include/asm-ppc/open_pic.h b/include/asm-ppc/open_pic.h
index 38d8edb1b..289761f85 100644
--- a/include/asm-ppc/open_pic.h
+++ b/include/asm-ppc/open_pic.h
@@ -23,7 +23,7 @@
 
 #define OPENPIC_VEC_TIMER	110	/* and up */
 #define OPENPIC_VEC_IPI		118	/* and up */
-#define OPENPIC_VEC_SPURIOUS	127
+#define OPENPIC_VEC_SPURIOUS	255
 
 /* OpenPIC IRQ controller structure */
 extern struct hw_interrupt_type open_pic;
diff --git a/include/asm-ppc/ppcboot.h b/include/asm-ppc/ppcboot.h
index ca2c16b8c..c2a4b94e4 100644
--- a/include/asm-ppc/ppcboot.h
+++ b/include/asm-ppc/ppcboot.h
@@ -30,20 +30,6 @@
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
 
-typedef void (interrupt_handler_t)(void *);
-
-typedef struct monitor_functions {
-	int	(*getc)(void);
-	int	(*tstc)(void);
-	void	(*putc)(const char c);
-	void	(*puts)(const char *s);
-	void	(*printf)(const char *fmt, ...);
-	void	(*install_hdlr)(int, interrupt_handler_t *, void *);
-	void	(*free_hdlr)(int);
-	void	*(*malloc)(size_t);
-	void	(*free)(void *);
-} mon_fnc_t;
-
 typedef struct bd_info {
 	unsigned long	bi_memstart;	/* start of DRAM memory */
 	unsigned long	bi_memsize;	/* size	 of DRAM memory in bytes */
@@ -75,7 +61,7 @@ typedef struct bd_info {
 	unsigned long   bi_pcifreq;     /* PCI Bus Freq, in MHz */
 #endif
 	unsigned long	bi_baudrate;	/* Console Baudrate */
-#if defined(CONFIG_405GP)
+#if defined(CONFIG_4xx)
 	unsigned char	bi_s_version[4];	/* Version of this structure */
 	unsigned char	bi_r_version[32];	/* Version of the ROM (IBM) */
 	unsigned int	bi_procfreq;	/* CPU (Internal) Freq, in Hz */
@@ -86,12 +72,26 @@ typedef struct bd_info {
 #if defined(CONFIG_HYMOD)
 	hymod_conf_t	bi_hymod_conf;	/* hymod configuration information */
 #endif
-#if defined(CONFIG_EVB64260) || defined(CONFIG_85xx)
-	/* the board has three onboard ethernet ports */
+#if defined(CONFIG_EVB64260) || defined(CONFIG_44x) || defined(CONFIG_85xx)
+	/* second onboard ethernet port */
 	unsigned char	bi_enet1addr[6];
+#endif
+#if defined(CONFIG_EVB64260) || defined(CONFIG_440GX) || defined(CONFIG_85xx)
+	/* third onboard ethernet ports */
 	unsigned char	bi_enet2addr[6];
 #endif
-	mon_fnc_t	*bi_mon_fnc;	/* Pointer to monitor functions	*/
+#if defined(CONFIG_440GX)
+	/* fourth onboard ethernet ports */
+	unsigned char	bi_enet3addr[6];
+#endif
+#if defined(CONFIG_4xx)
+	unsigned int	bi_opbfreq;		/* OB clock in Hz */
+	int		bi_iic_fast[2];		/* Use fast i2c mode */
+#endif
+#if defined(CONFIG_440GX)
+	int		bi_phynum[4];		/* phy mapping */
+	int		bi_phymode[4];		/* phy mode */
+#endif
 } bd_t;
 
 #endif /* __ASSEMBLY__ */
diff --git a/include/asm-ppc/ptrace.h b/include/asm-ppc/ptrace.h
index 2576a7f90..9d4e4ea53 100644
--- a/include/asm-ppc/ptrace.h
+++ b/include/asm-ppc/ptrace.h
@@ -47,6 +47,12 @@ struct pt_regs {
 
 #ifndef __ASSEMBLY__
 #define instruction_pointer(regs) ((regs)->nip)
+#ifdef CONFIG_SMP
+extern unsigned long profile_pc(struct pt_regs *regs);
+#else
+#define profile_pc(regs) instruction_pointer(regs)
+#endif
+
 #define user_mode(regs) (((regs)->msr & MSR_PR) != 0)
 
 #define force_successful_syscall_return()   \
diff --git a/include/asm-ppc/reg_booke.h b/include/asm-ppc/reg_booke.h
index 474abb894..0741b75da 100644
--- a/include/asm-ppc/reg_booke.h
+++ b/include/asm-ppc/reg_booke.h
@@ -123,9 +123,10 @@ do {						\
 #define SPRN_PID2	0x27A	/* Process ID Register 2 */
 #define SPRN_TLB0CFG	0x2B0	/* TLB 0 Config Register */
 #define SPRN_TLB1CFG	0x2B1	/* TLB 1 Config Register */
+#define SPRN_CCR1	0x378	/* Core Configuration Register 1 */
 #define SPRN_ZPR	0x3B0	/* Zone Protection Register (40x) */
 #define SPRN_MMUCR	0x3B2	/* MMU Control Register */
-#define SPRN_CCR0	0x3B3	/* Core Configuration Register */
+#define SPRN_CCR0	0x3B3	/* Core Configuration Register 0 */
 #define SPRN_SGR	0x3B9	/* Storage Guarded Register */
 #define SPRN_DCWR	0x3BA	/* Data Cache Write-thru Register */
 #define SPRN_SLER	0x3BB	/* Little-endian real mode */
@@ -179,6 +180,9 @@ do {						\
 #define SPRN_CSRR1	SPRN_SRR3 /* Critical Save and Restore Register 1 */
 #endif
 
+/* Bit definitions for CCR1. */
+#define	CCR1_TCS	0x00000080 /* Timer Clock Select */
+
 /* Bit definitions for the MCSR. */
 #ifdef CONFIG_440A
 #define MCSR_MCS	0x80000000 /* Machine Check Summary */
diff --git a/include/asm-ppc/residual.h b/include/asm-ppc/residual.h
index 42317589b..934810d25 100644
--- a/include/asm-ppc/residual.h
+++ b/include/asm-ppc/residual.h
@@ -315,11 +315,20 @@ typedef struct _RESIDUAL {
   } RESIDUAL;
 
 
+/*
+ * Forward declaration - we can't include <linux/pci.h> because it
+ * breaks the boot loader
+ */
+struct pci_dev;
+
 extern RESIDUAL *res;
 extern void print_residual_device_info(void);
 extern PPC_DEVICE *residual_find_device(unsigned long BusMask,
 					unsigned char * DevID, int BaseType,
 					int SubType, int Interface, int n);
+extern int residual_pcidev_irq(struct pci_dev *dev);
+extern void residual_irq_mask(char *irq_edge_mask_lo, char *irq_edge_mask_hi);
+extern unsigned int residual_isapic_addr(void);
 extern PnP_TAG_PACKET *PnP_find_packet(unsigned char *p, unsigned packet_tag,
 				       int n);
 extern PnP_TAG_PACKET *PnP_find_small_vendor_packet(unsigned char *p,
@@ -328,6 +337,13 @@ extern PnP_TAG_PACKET *PnP_find_small_vendor_packet(unsigned char *p,
 extern PnP_TAG_PACKET *PnP_find_large_vendor_packet(unsigned char *p,
 						    unsigned packet_type,
 						    int n);
+
+#ifdef CONFIG_PREP_RESIDUAL
+#define have_residual_data	(res && res->ResidualLength)
+#else
+#define have_residual_data	0
+#endif
+
 #endif /* __ASSEMBLY__ */
 #endif  /* ndef _RESIDUAL_ */
 
diff --git a/include/asm-ppc/resource.h b/include/asm-ppc/resource.h
index 3d2991455..2953d9bdc 100644
--- a/include/asm-ppc/resource.h
+++ b/include/asm-ppc/resource.h
@@ -36,7 +36,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
-	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff --git a/include/asm-ppc/semaphore.h b/include/asm-ppc/semaphore.h
index 87616e1cc..89e6e73be 100644
--- a/include/asm-ppc/semaphore.h
+++ b/include/asm-ppc/semaphore.h
@@ -29,22 +29,13 @@ struct semaphore {
 	 */
 	atomic_t count;
 	wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name, count) \
-	{ ATOMIC_INIT(count), \
-	  __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	  __SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name, 1)
@@ -59,9 +50,6 @@ static inline void sema_init (struct semaphore *sem, int val)
 {
 	atomic_set(&sem->count, val);
 	init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -80,9 +68,6 @@ extern void __up(struct semaphore * sem);
 
 extern inline void down(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	/*
@@ -97,9 +82,6 @@ extern inline int down_interruptible(struct semaphore * sem)
 {
 	int ret = 0;
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	if (atomic_dec_return(&sem->count) < 0)
@@ -112,10 +94,6 @@ extern inline int down_trylock(struct semaphore * sem)
 {
 	int ret;
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	ret = atomic_dec_if_positive(&sem->count) < 0;
 	smp_wmb();
 	return ret;
@@ -123,10 +101,6 @@ extern inline int down_trylock(struct semaphore * sem)
 
 extern inline void up(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	smp_wmb();
 	if (atomic_inc_return(&sem->count) <= 0)
 		__up(sem);
diff --git a/include/asm-ppc/serial.h b/include/asm-ppc/serial.h
index 310206e28..affec9786 100644
--- a/include/asm-ppc/serial.h
+++ b/include/asm-ppc/serial.h
@@ -13,17 +13,17 @@
 #elif defined(CONFIG_GEMINI)
 #include <platforms/gemini_serial.h>
 #elif defined(CONFIG_POWERPMC250)
-#include <platforms/powerpmc250_serial.h>
+#include <platforms/powerpmc250.h>
 #elif defined(CONFIG_LOPEC)
-#include <platforms/lopec_serial.h>
+#include <platforms/lopec.h>
 #elif defined(CONFIG_MCPN765)
-#include <platforms/mcpn765_serial.h>
+#include <platforms/mcpn765.h>
 #elif defined(CONFIG_MVME5100)
-#include <platforms/mvme5100_serial.h>
+#include <platforms/mvme5100.h>
 #elif defined(CONFIG_PRPMC750)
-#include <platforms/prpmc750_serial.h>
+#include <platforms/prpmc750.h>
 #elif defined(CONFIG_PRPMC800)
-#include <platforms/prpmc800_serial.h>
+#include <platforms/prpmc800.h>
 #elif defined(CONFIG_SANDPOINT)
 #include <platforms/sandpoint.h>
 #elif defined(CONFIG_SPRUCE)
diff --git a/include/asm-ppc/socket.h b/include/asm-ppc/socket.h
index bad94c36f..4134376b0 100644
--- a/include/asm-ppc/socket.h
+++ b/include/asm-ppc/socket.h
@@ -53,20 +53,4 @@
 
 #define SO_PEERSEC		31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-ppc/thread_info.h b/include/asm-ppc/thread_info.h
index 62aeec980..340235dfc 100644
--- a/include/asm-ppc/thread_info.h
+++ b/include/asm-ppc/thread_info.h
@@ -65,16 +65,6 @@ static inline struct thread_info *current_thread_info(void)
  */
 #define THREAD_SIZE		8192	/* 2 pages */
 
-/*
- * Offsets in thread_info structure, used in assembly code
- */
-#define TI_TASK		0
-#define TI_EXECDOMAIN	4
-#define TI_FLAGS	8
-#define TI_LOCAL_FLAGS	12
-#define TI_CPU		16
-#define TI_PREEMPT	20
-
 #define PREEMPT_ACTIVE		0x4000000
 
 /*
diff --git a/include/asm-ppc/uaccess.h b/include/asm-ppc/uaccess.h
index b9d763e0d..10aeae03b 100644
--- a/include/asm-ppc/uaccess.h
+++ b/include/asm-ppc/uaccess.h
@@ -331,6 +331,8 @@ copy_to_user(void __user *to, const void *from, unsigned long n)
 	__copy_tofrom_user((void __user *)(to), (from), (size))
 #define __copy_to_user(to, from, size) \
 	__copy_tofrom_user((to), (void __user *)(from), (size))
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 
 extern unsigned long __clear_user(void __user *addr, unsigned long size);
 
diff --git a/include/asm-ppc64/bitops.h b/include/asm-ppc64/bitops.h
index 6d820e7ea..a0f831224 100644
--- a/include/asm-ppc64/bitops.h
+++ b/include/asm-ppc64/bitops.h
@@ -22,6 +22,15 @@
  * it will be a bad memory reference since we want to store in chunks
  * of unsigned long (64 bits here) size.
  *
+ * There are a few little-endian macros used mostly for filesystem bitmaps,
+ * these work on similar bit arrays layouts, but byte-oriented:
+ *
+ *   |7...0|15...8|23...16|31...24|39...32|47...40|55...48|63...56|
+ *
+ * The main difference is that bit 3-5 in the bit number field needs to be
+ * reversed compared to the big-endian bit fields. This can be achieved
+ * by XOR with 0b111000 (0x38).
+ *
  * 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
@@ -306,71 +315,34 @@ static __inline__ int test_le_bit(unsigned long nr, __const__ unsigned long * ad
 	return (ADDR[nr >> 3] >> (nr & 7)) & 1;
 }
 
+#define test_and_clear_le_bit(nr, addr) \
+	test_and_clear_bit((nr) ^ 0x38, (addr))
+#define test_and_set_le_bit(nr, addr) \
+	test_and_set_bit((nr) ^ 0x38, (addr))
+
 /*
  * non-atomic versions
  */
-static __inline__ void __set_le_bit(unsigned long nr, unsigned long *addr)
-{
-	unsigned char *ADDR = (unsigned char *)addr;
-
-	ADDR += nr >> 3;
-	*ADDR |= 1 << (nr & 0x07);
-}
-
-static __inline__ void __clear_le_bit(unsigned long nr, unsigned long *addr)
-{
-	unsigned char *ADDR = (unsigned char *)addr;
 
-	ADDR += nr >> 3;
-	*ADDR &= ~(1 << (nr & 0x07));
-}
-
-static __inline__ int __test_and_set_le_bit(unsigned long nr, unsigned long *addr)
-{
-	int mask, retval;
-	unsigned char *ADDR = (unsigned char *)addr;
-
-	ADDR += nr >> 3;
-	mask = 1 << (nr & 0x07);
-	retval = (mask & *ADDR) != 0;
-	*ADDR |= mask;
-	return retval;
-}
-
-static __inline__ int __test_and_clear_le_bit(unsigned long nr, unsigned long *addr)
-{
-	int mask, retval;
-	unsigned char *ADDR = (unsigned char *)addr;
-
-	ADDR += nr >> 3;
-	mask = 1 << (nr & 0x07);
-	retval = (mask & *ADDR) != 0;
-	*ADDR &= ~mask;
-	return retval;
-}
+#define __set_le_bit(nr, addr) \
+	__set_bit((nr) ^ 0x38, (addr))
+#define __clear_le_bit(nr, addr) \
+	__clear_bit((nr) ^ 0x38, (addr))
+#define __test_and_clear_le_bit(nr, addr) \
+	__test_and_clear_bit((nr) ^ 0x38, (addr))
+#define __test_and_set_le_bit(nr, addr) \
+	__test_and_set_bit((nr) ^ 0x38, (addr))
 
 #define ext2_set_bit(nr,addr) \
-	__test_and_set_le_bit((nr),(unsigned long*)addr)
+	__test_and_set_le_bit((nr), (unsigned long*)addr)
 #define ext2_clear_bit(nr, addr) \
-	__test_and_clear_le_bit((nr),(unsigned long*)addr)
-
-#define ext2_set_bit_atomic(lock, nr, addr)		\
-	({						\
-		int ret;				\
-		spin_lock(lock);			\
-		ret = ext2_set_bit((nr), (addr));	\
-		spin_unlock(lock);			\
-		ret;					\
-	})
-
-#define ext2_clear_bit_atomic(lock, nr, addr)		\
-	({						\
-		int ret;				\
-		spin_lock(lock);			\
-		ret = ext2_clear_bit((nr), (addr));	\
-		spin_unlock(lock);			\
-		ret;					\
-	})
+	__test_and_clear_le_bit((nr), (unsigned long*)addr)
+
+#define ext2_set_bit_atomic(lock, nr, addr) \
+	test_and_set_le_bit((nr), (unsigned long*)addr)
+#define ext2_clear_bit_atomic(lock, nr, addr) \
+	test_and_clear_le_bit((nr), (unsigned long*)addr)
+
 
 #define ext2_test_bit(nr, addr)      test_le_bit((nr),(unsigned long*)addr)
 #define ext2_find_first_zero_bit(addr, size) \
diff --git a/include/asm-ppc64/btext.h b/include/asm-ppc64/btext.h
index ba6b5b3ae..67aef0cc7 100644
--- a/include/asm-ppc64/btext.h
+++ b/include/asm-ppc64/btext.h
@@ -7,23 +7,20 @@
 #define __PPC_BTEXT_H
 #ifdef __KERNEL__
 
-#include <asm/bootx.h>
-
 extern void btext_clearscreen(void);
 extern void btext_flushscreen(void);
 
-extern boot_infos_t disp_bi;
 extern int boot_text_mapped;
 
-void btext_setup_display(int width, int height, int depth, int pitch,
-			 unsigned long address);
-void map_boot_text(void);
-void btext_update_display(unsigned long phys, int width, int height,
-			  int depth, int pitch);
+extern int btext_initialize(struct device_node *np);
+
+extern void map_boot_text(void);
+extern void btext_update_display(unsigned long phys, int width, int height,
+				 int depth, int pitch);
 
-void btext_drawchar(char c);
-void btext_drawstring(const char *str);
-void btext_drawhex(unsigned long v);
+extern void btext_drawchar(char c);
+extern void btext_drawstring(const char *str);
+extern void btext_drawhex(unsigned long v);
 
 #endif /* __KERNEL__ */
 #endif /* __PPC_BTEXT_H */
diff --git a/include/asm-ppc64/bug.h b/include/asm-ppc64/bug.h
index 9e439ee1e..790bc5609 100644
--- a/include/asm-ppc64/bug.h
+++ b/include/asm-ppc64/bug.h
@@ -43,8 +43,6 @@ struct bug_entry {
 		    "i" (__FUNCTION__));			\
 } while (0)
 
-#define PAGE_BUG(page) do { BUG(); } while (0)
-
 #define WARN_ON(x) do {						\
 	__asm__ __volatile__(					\
 		"1:	tdnei %0,0\n"				\
@@ -56,4 +54,10 @@ struct bug_entry {
 } while (0)
 
 #endif
+
+#define HAVE_ARCH_BUG
+#define HAVE_ARCH_BUG_ON
+#define HAVE_ARCH_WARN_ON
+#include <asm-generic/bug.h>
+
 #endif
diff --git a/include/asm-ppc64/checksum.h b/include/asm-ppc64/checksum.h
index 5ae7cdbe8..d22d4469d 100644
--- a/include/asm-ppc64/checksum.h
+++ b/include/asm-ppc64/checksum.h
@@ -84,10 +84,10 @@ static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
 }
 
 #define csum_partial_copy_from_user(src, dst, len, sum, errp)   \
-        csum_partial_copy_generic((src), (dst), (len), (sum), (errp), 0)
+        csum_partial_copy_generic((src), (dst), (len), (sum), (errp), NULL)
 
 #define csum_partial_copy_nocheck(src, dst, len, sum)   \
-        csum_partial_copy_generic((src), (dst), (len), (sum), 0, 0)
+        csum_partial_copy_generic((src), (dst), (len), (sum), NULL, NULL)
 
 static inline u32 csum_tcpudp_nofold(u32 saddr,
                                      u32 daddr,
diff --git a/include/asm-ppc64/dma-mapping.h b/include/asm-ppc64/dma-mapping.h
index 0cdc5346f..1e05f389e 100644
--- a/include/asm-ppc64/dma-mapping.h
+++ b/include/asm-ppc64/dma-mapping.h
@@ -8,7 +8,6 @@
 #define _ASM_DMA_MAPPING_H
 
 #include <linux/types.h>
-#include <linux/device.h>
 #include <linux/cache.h>
 /* need struct page definitions */
 #include <linux/mm.h>
diff --git a/include/asm-ppc64/eeh.h b/include/asm-ppc64/eeh.h
index a877ce9aa..85bc6850f 100644
--- a/include/asm-ppc64/eeh.h
+++ b/include/asm-ppc64/eeh.h
@@ -26,26 +26,19 @@
 struct pci_dev;
 struct device_node;
 
-/* I/O addresses are converted to EEH "tokens" such that a driver will cause
- * a bad page fault if the address is used directly (i.e. these addresses are
- * never actually mapped.  Translation between IO <-> EEH region is 1 to 1.
- */
-#define IO_TOKEN_TO_ADDR(token) \
-	(((unsigned long)(token) & ~(0xfUL << REGION_SHIFT)) | \
-	(IO_REGION_ID << REGION_SHIFT))
-
-#define IO_ADDR_TO_TOKEN(addr) \
-	(((unsigned long)(addr) & ~(0xfUL << REGION_SHIFT)) | \
-	(EEH_REGION_ID << REGION_SHIFT))
-
 /* Values for eeh_mode bits in device_node */
 #define EEH_MODE_SUPPORTED	(1<<0)
 #define EEH_MODE_NOCHECK	(1<<1)
 
+#ifdef CONFIG_PPC_PSERIES
 extern void __init eeh_init(void);
-unsigned long eeh_check_failure(void *token, unsigned long val);
-void *eeh_ioremap(unsigned long addr, void *vaddr);
+unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val);
+int eeh_dn_check_failure (struct device_node *dn, struct pci_dev *dev);
+void __iomem *eeh_ioremap(unsigned long addr, void __iomem *vaddr);
 void __init pci_addr_cache_build(void);
+#else
+#define eeh_check_failure(token, val) (val)
+#endif
 
 /**
  * eeh_add_device_early
@@ -78,113 +71,107 @@ int eeh_set_option(struct pci_dev *dev, int options);
 /*
  * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure.
  *
- * Order this macro for performance.
- * If EEH is off for a device and it is a memory BAR, ioremap will
- * map it to the IOREGION.  In this case addr == vaddr and since these
- * should be in registers we compare them first.  Next we check for
- * ff's which indicates a (very) possible failure.
- *
  * If this macro yields TRUE, the caller relays to eeh_check_failure()
  * which does further tests out of line.
  */
-#define EEH_POSSIBLE_IO_ERROR(val, type)	((val) == (type)~0)
+#define EEH_POSSIBLE_ERROR(val, type)	((val) == (type)~0)
 
-/* The vaddr will equal the addr if EEH checking is disabled for
- * this device.  This is because eeh_ioremap() will not have
- * remapped to 0xA0, and thus both vaddr and addr will be 0xE0...
+/*
+ * Reads from a device which has been isolated by EEH will return
+ * all 1s.  This macro gives an all-1s value of the given size (in
+ * bytes: 1, 2, or 4) for comparing with the result of a read.
  */
-#define EEH_POSSIBLE_ERROR(addr, vaddr, val, type) \
-		((vaddr) != (addr) && EEH_POSSIBLE_IO_ERROR(val, type))
+#define EEH_IO_ERROR_VALUE(size)	(~0U >> ((4 - (size)) * 8))
 
 /* 
  * MMIO read/write operations with EEH support.
  */
-static inline u8 eeh_readb(void *addr) {
-	volatile u8 *vaddr = (volatile u8 *)IO_TOKEN_TO_ADDR(addr);
+static inline u8 eeh_readb(const volatile void __iomem *addr) {
+	volatile u8 *vaddr = (volatile u8 __force *) addr;
 	u8 val = in_8(vaddr);
-	if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u8))
+	if (EEH_POSSIBLE_ERROR(val, u8))
 		return eeh_check_failure(addr, val);
 	return val;
 }
-static inline void eeh_writeb(u8 val, void *addr) {
-	volatile u8 *vaddr = (volatile u8 *)IO_TOKEN_TO_ADDR(addr);
+static inline void eeh_writeb(u8 val, volatile void __iomem *addr) {
+	volatile u8 *vaddr = (volatile u8 __force *) addr;
 	out_8(vaddr, val);
 }
 
-static inline u16 eeh_readw(void *addr) {
-	volatile u16 *vaddr = (volatile u16 *)IO_TOKEN_TO_ADDR(addr);
+static inline u16 eeh_readw(const volatile void __iomem *addr) {
+	volatile u16 *vaddr = (volatile u16 __force *) addr;
 	u16 val = in_le16(vaddr);
-	if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u16))
+	if (EEH_POSSIBLE_ERROR(val, u16))
 		return eeh_check_failure(addr, val);
 	return val;
 }
-static inline void eeh_writew(u16 val, void *addr) {
-	volatile u16 *vaddr = (volatile u16 *)IO_TOKEN_TO_ADDR(addr);
+static inline void eeh_writew(u16 val, volatile void __iomem *addr) {
+	volatile u16 *vaddr = (volatile u16 __force *) addr;
 	out_le16(vaddr, val);
 }
-static inline u16 eeh_raw_readw(void *addr) {
-	volatile u16 *vaddr = (volatile u16 *)IO_TOKEN_TO_ADDR(addr);
+static inline u16 eeh_raw_readw(const volatile void __iomem *addr) {
+	volatile u16 *vaddr = (volatile u16 __force *) addr;
 	u16 val = in_be16(vaddr);
-	if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u16))
+	if (EEH_POSSIBLE_ERROR(val, u16))
 		return eeh_check_failure(addr, val);
 	return val;
 }
-static inline void eeh_raw_writew(u16 val, void *addr) {
-	volatile u16 *vaddr = (volatile u16 *)IO_TOKEN_TO_ADDR(addr);
+static inline void eeh_raw_writew(u16 val, volatile void __iomem *addr) {
+	volatile u16 *vaddr = (volatile u16 __force *) addr;
 	out_be16(vaddr, val);
 }
 
-static inline u32 eeh_readl(void *addr) {
-	volatile u32 *vaddr = (volatile u32 *)IO_TOKEN_TO_ADDR(addr);
+static inline u32 eeh_readl(const volatile void __iomem *addr) {
+	volatile u32 *vaddr = (volatile u32 __force *) addr;
 	u32 val = in_le32(vaddr);
-	if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u32))
+	if (EEH_POSSIBLE_ERROR(val, u32))
 		return eeh_check_failure(addr, val);
 	return val;
 }
-static inline void eeh_writel(u32 val, void *addr) {
-	volatile u32 *vaddr = (volatile u32 *)IO_TOKEN_TO_ADDR(addr);
+static inline void eeh_writel(u32 val, volatile void __iomem *addr) {
+	volatile u32 *vaddr = (volatile u32 __force *) addr;
 	out_le32(vaddr, val);
 }
-static inline u32 eeh_raw_readl(void *addr) {
-	volatile u32 *vaddr = (volatile u32 *)IO_TOKEN_TO_ADDR(addr);
+static inline u32 eeh_raw_readl(const volatile void __iomem *addr) {
+	volatile u32 *vaddr = (volatile u32 __force *) addr;
 	u32 val = in_be32(vaddr);
-	if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u32))
+	if (EEH_POSSIBLE_ERROR(val, u32))
 		return eeh_check_failure(addr, val);
 	return val;
 }
-static inline void eeh_raw_writel(u32 val, void *addr) {
-	volatile u32 *vaddr = (volatile u32 *)IO_TOKEN_TO_ADDR(addr);
+static inline void eeh_raw_writel(u32 val, volatile void __iomem *addr) {
+	volatile u32 *vaddr = (volatile u32 __force *) addr;
 	out_be32(vaddr, val);
 }
 
-static inline u64 eeh_readq(void *addr) {
-	volatile u64 *vaddr = (volatile u64 *)IO_TOKEN_TO_ADDR(addr);
+static inline u64 eeh_readq(const volatile void __iomem *addr) {
+	volatile u64 *vaddr = (volatile u64 __force *) addr;
 	u64 val = in_le64(vaddr);
-	if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u64))
+	if (EEH_POSSIBLE_ERROR(val, u64))
 		return eeh_check_failure(addr, val);
 	return val;
 }
-static inline void eeh_writeq(u64 val, void *addr) {
-	volatile u64 *vaddr = (volatile u64 *)IO_TOKEN_TO_ADDR(addr);
+static inline void eeh_writeq(u64 val, volatile void __iomem *addr) {
+	volatile u64 *vaddr = (volatile u64 __force *) addr;
 	out_le64(vaddr, val);
 }
-static inline u64 eeh_raw_readq(void *addr) {
-	volatile u64 *vaddr = (volatile u64 *)IO_TOKEN_TO_ADDR(addr);
+static inline u64 eeh_raw_readq(const volatile void __iomem *addr) {
+	volatile u64 *vaddr = (volatile u64 __force *) addr;
 	u64 val = in_be64(vaddr);
-	if (EEH_POSSIBLE_ERROR(addr, vaddr, val, u64))
+	if (EEH_POSSIBLE_ERROR(val, u64))
 		return eeh_check_failure(addr, val);
 	return val;
 }
-static inline void eeh_raw_writeq(u64 val, void *addr) {
-	volatile u64 *vaddr = (volatile u64 *)IO_TOKEN_TO_ADDR(addr);
+static inline void eeh_raw_writeq(u64 val, volatile void __iomem *addr) {
+	volatile u64 *vaddr = (volatile u64 __force *) addr;
 	out_be64(vaddr, val);
 }
 
 #define EEH_CHECK_ALIGN(v,a) \
 	((((unsigned long)(v)) & ((a) - 1)) == 0)
 
-static inline void eeh_memset_io(void *addr, int c, unsigned long n) {
-	void *vaddr = (void *)IO_TOKEN_TO_ADDR(addr);
+static inline void eeh_memset_io(volatile void __iomem *addr, int c, unsigned long n) {
+	void *vaddr = (void __force *) addr;
 	u32 lc = c;
 	lc |= lc << 8;
 	lc |= lc << 16;
@@ -206,9 +193,9 @@ static inline void eeh_memset_io(void *addr, int c, unsigned long n) {
 	}
 	__asm__ __volatile__ ("sync" : : : "memory");
 }
-static inline void eeh_memcpy_fromio(void *dest, void *src, unsigned long n) {
-	void *vsrc = (void *)IO_TOKEN_TO_ADDR(src);
-	void *vsrcsave = vsrc, *destsave = dest, *srcsave = src;
+static inline void eeh_memcpy_fromio(void *dest, const volatile void __iomem *src, unsigned long n) {
+	void *vsrc = (void __force *) src;
+	void *destsave = dest;
 	unsigned long nsave = n;
 
 	while(n && (!EEH_CHECK_ALIGN(vsrc, 4) || !EEH_CHECK_ALIGN(dest, 4))) {
@@ -238,14 +225,13 @@ static inline void eeh_memcpy_fromio(void *dest, void *src, unsigned long n) {
 	 * were copied. Check all four bytes.
 	 */
 	if ((nsave >= 4) &&
-		(EEH_POSSIBLE_ERROR(srcsave, vsrcsave, (*((u32 *) destsave+nsave-4)),
-				    u32))) {
-		eeh_check_failure(srcsave, (*((u32 *) destsave+nsave-4)));
+		(EEH_POSSIBLE_ERROR((*((u32 *) destsave+nsave-4)), u32))) {
+		eeh_check_failure(src, (*((u32 *) destsave+nsave-4)));
 	}
 }
 
-static inline void eeh_memcpy_toio(void *dest, void *src, unsigned long n) {
-	void *vdest = (void *)IO_TOKEN_TO_ADDR(dest);
+static inline void eeh_memcpy_toio(volatile void __iomem *dest, const void *src, unsigned long n) {
+	void *vdest = (void __force *) dest;
 
 	while(n && (!EEH_CHECK_ALIGN(vdest, 4) || !EEH_CHECK_ALIGN(src, 4))) {
 		*((volatile u8 *)vdest) = *((u8 *)src);
@@ -279,8 +265,8 @@ static inline u8 eeh_inb(unsigned long port) {
 	if (!_IO_IS_VALID(port))
 		return ~0;
 	val = in_8((u8 *)(port+pci_io_base));
-	if (EEH_POSSIBLE_IO_ERROR(val, u8))
-		return eeh_check_failure((void*)(port), val);
+	if (EEH_POSSIBLE_ERROR(val, u8))
+		return eeh_check_failure((void __iomem *)(port), val);
 	return val;
 }
 
@@ -294,8 +280,8 @@ static inline u16 eeh_inw(unsigned long port) {
 	if (!_IO_IS_VALID(port))
 		return ~0;
 	val = in_le16((u16 *)(port+pci_io_base));
-	if (EEH_POSSIBLE_IO_ERROR(val, u16))
-		return eeh_check_failure((void*)(port), val);
+	if (EEH_POSSIBLE_ERROR(val, u16))
+		return eeh_check_failure((void __iomem *)(port), val);
 	return val;
 }
 
@@ -309,8 +295,8 @@ static inline u32 eeh_inl(unsigned long port) {
 	if (!_IO_IS_VALID(port))
 		return ~0;
 	val = in_le32((u32 *)(port+pci_io_base));
-	if (EEH_POSSIBLE_IO_ERROR(val, u32))
-		return eeh_check_failure((void*)(port), val);
+	if (EEH_POSSIBLE_ERROR(val, u32))
+		return eeh_check_failure((void __iomem *)(port), val);
 	return val;
 }
 
@@ -322,20 +308,20 @@ static inline void eeh_outl(u32 val, unsigned long port) {
 /* in-string eeh macros */
 static inline void eeh_insb(unsigned long port, void * buf, int ns) {
 	_insb((u8 *)(port+pci_io_base), buf, ns);
-	if (EEH_POSSIBLE_IO_ERROR((*(((u8*)buf)+ns-1)), u8))
-		eeh_check_failure((void*)(port), *(u8*)buf);
+	if (EEH_POSSIBLE_ERROR((*(((u8*)buf)+ns-1)), u8))
+		eeh_check_failure((void __iomem *)(port), *(u8*)buf);
 }
 
 static inline void eeh_insw_ns(unsigned long port, void * buf, int ns) {
 	_insw_ns((u16 *)(port+pci_io_base), buf, ns);
-	if (EEH_POSSIBLE_IO_ERROR((*(((u16*)buf)+ns-1)), u16))
-		eeh_check_failure((void*)(port), *(u16*)buf);
+	if (EEH_POSSIBLE_ERROR((*(((u16*)buf)+ns-1)), u16))
+		eeh_check_failure((void __iomem *)(port), *(u16*)buf);
 }
 
 static inline void eeh_insl_ns(unsigned long port, void * buf, int nl) {
 	_insl_ns((u32 *)(port+pci_io_base), buf, nl);
-	if (EEH_POSSIBLE_IO_ERROR((*(((u32*)buf)+nl-1)), u32))
-		eeh_check_failure((void*)(port), *(u32*)buf);
+	if (EEH_POSSIBLE_ERROR((*(((u32*)buf)+nl-1)), u32))
+		eeh_check_failure((void __iomem *)(port), *(u32*)buf);
 }
 
 #endif /* _PPC64_EEH_H */
diff --git a/include/asm-ppc64/hardirq.h b/include/asm-ppc64/hardirq.h
index e1a2fec9f..c09a7486d 100644
--- a/include/asm-ppc64/hardirq.h
+++ b/include/asm-ppc64/hardirq.h
@@ -1,4 +1,3 @@
-#ifdef __KERNEL__
 #ifndef __ASM_HARDIRQ_H
 #define __ASM_HARDIRQ_H
 
@@ -43,20 +42,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __HARDIRQ_MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__HARDIRQ_MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define SOFTIRQ_MASK	(__HARDIRQ_MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-#define HARDIRQ_MASK	(__HARDIRQ_MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -66,29 +51,7 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define preemptible()	(preempt_count() == 0 && !irqs_disabled())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define preemptible()	0
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
 #define irq_exit()							\
 do {									\
 		preempt_count() -= IRQ_EXIT_OFFSET;			\
@@ -97,12 +60,4 @@ do {									\
 		preempt_enable_no_resched();				\
 } while (0)
 
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else
-  extern void synchronize_irq(unsigned int irq);
-#endif /* CONFIG_SMP */
-
-#endif /* __KERNEL__ */
-	
 #endif /* __ASM_HARDIRQ_H */
diff --git a/include/asm-ppc64/hvcall.h b/include/asm-ppc64/hvcall.h
index f47cc0329..6ce5ef9c1 100644
--- a/include/asm-ppc64/hvcall.h
+++ b/include/asm-ppc64/hvcall.h
@@ -101,10 +101,12 @@
 #define H_VIO_SIGNAL		0x104
 #define H_SEND_CRQ		0x108
 #define H_COPY_RDMA             0x110
-#define H_POLL_PENDING	        0x1D8
+#define H_STUFF_TCE		0x138
+#define H_PUT_TCE_INDIRECT	0x13C
 #define H_VTERM_PARTNER_INFO	0x150
-#define H_REGISTER_VTERM		0x154
-#define H_FREE_VTERM			0x158
+#define H_REGISTER_VTERM	0x154
+#define H_FREE_VTERM		0x158
+#define H_POLL_PENDING	        0x1D8
 
 /* plpar_hcall() -- Generic call interface using above opcodes
  *
diff --git a/include/asm-ppc64/hvconsole.h b/include/asm-ppc64/hvconsole.h
index 17154864f..d89d94c91 100644
--- a/include/asm-ppc64/hvconsole.h
+++ b/include/asm-ppc64/hvconsole.h
@@ -22,9 +22,19 @@
 #ifndef _PPC64_HVCONSOLE_H
 #define _PPC64_HVCONSOLE_H
 
-extern int hvc_get_chars(int index, char *buf, int count);
-extern int hvc_put_chars(int index, const char *buf, int count);
-extern int hvc_count(int *start_termno);
+/*
+ * This is the max number of console adapters that can/will be found as
+ * console devices on first stage console init.  Any number beyond this range
+ * can't be used as a console device but is still a valid tty device.
+ */
+#define MAX_NR_HVC_CONSOLES	16
 
-#endif /* _PPC64_HVCONSOLE_H */
+extern int hvc_get_chars(uint32_t vtermno, char *buf, int count);
+extern int hvc_put_chars(uint32_t vtermno, const char *buf, int count);
 
+/* Early discovery of console adapters. */
+extern int hvc_find_vtys(void);
+
+/* Implemented by a console driver */
+extern int hvc_instantiate(uint32_t vtermno, int index);
+#endif /* _PPC64_HVCONSOLE_H */
diff --git a/include/asm-ppc64/hvcserver.h b/include/asm-ppc64/hvcserver.h
index cee9a14a2..aecba9665 100644
--- a/include/asm-ppc64/hvcserver.h
+++ b/include/asm-ppc64/hvcserver.h
@@ -27,18 +27,31 @@
 /* Converged Location Code length */
 #define HVCS_CLC_LENGTH	79
 
+/**
+ * hvcs_partner_info - an element in a list of partner info
+ * @node: list_head denoting this partner_info struct's position in the list of
+ *	partner info.
+ * @unit_address: The partner unit address of this entry.
+ * @partition_ID: The partner partition ID of this entry.
+ * @location_code: The converged location code of this entry + 1 char for the
+ *	null-term.
+ *
+ * This structure outlines the format that partner info is presented to a caller
+ * of the hvcs partner info fetching functions.  These are strung together into
+ * a list using linux kernel lists.
+ */
 struct hvcs_partner_info {
 	struct list_head node;
-	unsigned int unit_address;
-	unsigned int partition_ID;
+	uint32_t unit_address;
+	uint32_t partition_ID;
 	char location_code[HVCS_CLC_LENGTH + 1]; /* CLC + 1 null-term char */
 };
 
 extern int hvcs_free_partner_info(struct list_head *head);
-extern int hvcs_get_partner_info(unsigned int unit_address,
+extern int hvcs_get_partner_info(uint32_t unit_address,
 		struct list_head *head, unsigned long *pi_buff);
-extern int hvcs_register_connection(unsigned int unit_address,
-		unsigned int p_partition_ID, unsigned int p_unit_address);
-extern int hvcs_free_connection(unsigned int unit_address);
+extern int hvcs_register_connection(uint32_t unit_address,
+		uint32_t p_partition_ID, uint32_t p_unit_address);
+extern int hvcs_free_connection(uint32_t unit_address);
 
 #endif /* _PPC64_HVCSERVER_H */
diff --git a/include/asm-ppc64/iSeries/iSeries_io.h b/include/asm-ppc64/iSeries/iSeries_io.h
index 96b07b146..f52b7599b 100644
--- a/include/asm-ppc64/iSeries/iSeries_io.h
+++ b/include/asm-ppc64/iSeries/iSeries_io.h
@@ -31,16 +31,16 @@
 /*   Created December 28, 2000                                          */
 /* End Change Activity                                                  */
 /************************************************************************/
-extern u8   iSeries_Read_Byte(void* IoAddress);
-extern u16  iSeries_Read_Word(void* IoAddress);
-extern u32  iSeries_Read_Long(void* IoAddress);
-extern void iSeries_Write_Byte(u8  IoData,void* IoAddress);
-extern void iSeries_Write_Word(u16 IoData,void* IoAddress);
-extern void iSeries_Write_Long(u32 IoData,void* IoAddress);
+extern u8   iSeries_Read_Byte(const volatile void __iomem * IoAddress);
+extern u16  iSeries_Read_Word(const volatile void __iomem * IoAddress);
+extern u32  iSeries_Read_Long(const volatile void __iomem * IoAddress);
+extern void iSeries_Write_Byte(u8  IoData, volatile void __iomem * IoAddress);
+extern void iSeries_Write_Word(u16 IoData, volatile void __iomem * IoAddress);
+extern void iSeries_Write_Long(u32 IoData, volatile void __iomem * IoAddress);
 
-extern void* iSeries_memset_io(void *dest, char x, size_t n);
-extern void* iSeries_memcpy_toio(void *dest, void *source, size_t n);
-extern void* iSeries_memcpy_fromio(void *dest, void *source, size_t n);
+extern void iSeries_memset_io(volatile void __iomem *dest, char x, size_t n);
+extern void iSeries_memcpy_toio(volatile void __iomem *dest, void *source, size_t n);
+extern void iSeries_memcpy_fromio(void *dest, const volatile void __iomem *source, size_t n);
 
 #endif /* CONFIG_PPC_ISERIES */
 #endif /* _ISERIES_IO_H */
diff --git a/include/asm-ppc64/io.h b/include/asm-ppc64/io.h
index f6262bad7..46d47573d 100644
--- a/include/asm-ppc64/io.h
+++ b/include/asm-ppc64/io.h
@@ -9,6 +9,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/compiler.h>
 #include <asm/page.h>
 #include <asm/byteorder.h>
 #ifdef CONFIG_PPC_ISERIES 
@@ -17,6 +18,8 @@
 #include <asm/memory.h>
 #include <asm/delay.h>
 
+#include <asm-generic/iomap.h>
+
 #define __ide_mm_insw(p, a, c) _insw_ns((volatile u16 *)(p), (a), (c))
 #define __ide_mm_insl(p, a, c) _insl_ns((volatile u32 *)(p), (a), (c))
 #define __ide_mm_outsw(p, a, c) _outsw_ns((volatile u16 *)(p), (a), (c))
@@ -41,21 +44,22 @@ extern unsigned long pci_io_base;
 #define __raw_writew(v, addr)   { BUG(); 0; }
 #define __raw_writel(v, addr)   { BUG(); 0; }
 #define __raw_writeq(v, addr)   { BUG(); 0; }
-#define readb(addr)		iSeries_Read_Byte((void*)(addr))  
-#define readw(addr)		iSeries_Read_Word((void*)(addr))  
-#define readl(addr)		iSeries_Read_Long((void*)(addr))
-#define writeb(data, addr)	iSeries_Write_Byte(data,((void*)(addr)))
-#define writew(data, addr)	iSeries_Write_Word(data,((void*)(addr)))
-#define writel(data, addr)	iSeries_Write_Long(data,((void*)(addr)))
-#define memset_io(a,b,c)	iSeries_memset_io((void *)(a),(b),(c))
-#define memcpy_fromio(a,b,c)	iSeries_memcpy_fromio((void *)(a), (void *)(b), (c))
-#define memcpy_toio(a,b,c)	iSeries_memcpy_toio((void *)(a), (void *)(b), (c))
-#define inb(addr)		readb(((unsigned long)(addr)))  
-#define inw(addr)		readw(((unsigned long)(addr)))  
-#define inl(addr)		readl(((unsigned long)(addr)))
-#define outb(data,addr)		writeb(data,((unsigned long)(addr)))  
-#define outw(data,addr)		writew(data,((unsigned long)(addr)))  
-#define outl(data,addr)		writel(data,((unsigned long)(addr)))
+#define readb(addr)		iSeries_Read_Byte(addr)
+#define readw(addr)		iSeries_Read_Word(addr)
+#define readl(addr)		iSeries_Read_Long(addr)
+#define writeb(data, addr)	iSeries_Write_Byte((data),(addr))
+#define writew(data, addr)	iSeries_Write_Word((data),(addr))
+#define writel(data, addr)	iSeries_Write_Long((data),(addr))
+#define memset_io(a,b,c)	iSeries_memset_io((a),(b),(c))
+#define memcpy_fromio(a,b,c)	iSeries_memcpy_fromio((a), (b), (c))
+#define memcpy_toio(a,b,c)	iSeries_memcpy_toio((a), (b), (c))
+
+#define inb(addr)		readb(((void __iomem *)(long)(addr)))
+#define inw(addr)		readw(((void __iomem *)(long)(addr)))
+#define inl(addr)		readl(((void __iomem *)(long)(addr)))
+#define outb(data,addr)		writeb(data,((void __iomem *)(long)(addr)))
+#define outw(data,addr)		writew(data,((void __iomem *)(long)(addr)))
+#define outl(data,addr)		writel(data,((void __iomem *)(long)(addr)))
 /*
  * The *_ns versions below don't do byte-swapping.
  * Neither do the standard versions now, these are just here
@@ -64,25 +68,50 @@ extern unsigned long pci_io_base;
 #define insw_ns(port, buf, ns)	_insw_ns((u16 *)((port)+pci_io_base), (buf), (ns))
 #define insl_ns(port, buf, nl)	_insl_ns((u32 *)((port)+pci_io_base), (buf), (nl))
 #else
-#define __raw_readb(addr)       (*(volatile unsigned char *)(addr))
-#define __raw_readw(addr)       (*(volatile unsigned short *)(addr))
-#define __raw_readl(addr)       (*(volatile unsigned int *)(addr))
-#define __raw_readq(addr)       (*(volatile unsigned long *)(addr))
-#define __raw_writeb(v, addr)   (*(volatile unsigned char *)(addr) = (v))
-#define __raw_writew(v, addr)   (*(volatile unsigned short *)(addr) = (v))
-#define __raw_writel(v, addr)   (*(volatile unsigned int *)(addr) = (v))
-#define __raw_writeq(v, addr)   (*(volatile unsigned long *)(addr) = (v))
-#define readb(addr)		eeh_readb((void*)(addr))  
-#define readw(addr)		eeh_readw((void*)(addr))  
-#define readl(addr)		eeh_readl((void*)(addr))
-#define readq(addr)		eeh_readq((void*)(addr))
-#define writeb(data, addr)	eeh_writeb((data), ((void*)(addr)))
-#define writew(data, addr)	eeh_writew((data), ((void*)(addr)))
-#define writel(data, addr)	eeh_writel((data), ((void*)(addr)))
-#define writeq(data, addr)	eeh_writeq((data), ((void*)(addr)))
-#define memset_io(a,b,c)	eeh_memset_io((void *)(a),(b),(c))
-#define memcpy_fromio(a,b,c)	eeh_memcpy_fromio((a),(void *)(b),(c))
-#define memcpy_toio(a,b,c)	eeh_memcpy_toio((void *)(a),(b),(c))
+
+static inline unsigned char __raw_readb(const volatile void __iomem *addr)
+{
+	return *(volatile unsigned char __force *)addr;
+}
+static inline unsigned short __raw_readw(const volatile void __iomem *addr)
+{
+	return *(volatile unsigned short __force *)addr;
+}
+static inline unsigned int __raw_readl(const volatile void __iomem *addr)
+{
+	return *(volatile unsigned int __force *)addr;
+}
+static inline unsigned long __raw_readq(const volatile void __iomem *addr)
+{
+	return *(volatile unsigned long __force *)addr;
+}
+static inline void __raw_writeb(unsigned char v, volatile void __iomem *addr)
+{
+	*(volatile unsigned char __force *)addr = v;
+}
+static inline void __raw_writew(unsigned short v, volatile void __iomem *addr)
+{
+	*(volatile unsigned short __force *)addr = v;
+}
+static inline void __raw_writel(unsigned int v, volatile void __iomem *addr)
+{
+	*(volatile unsigned int __force *)addr = v;
+}
+static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr)
+{
+	*(volatile unsigned long __force *)addr = v;
+}
+#define readb(addr)		eeh_readb(addr)
+#define readw(addr)		eeh_readw(addr)
+#define readl(addr)		eeh_readl(addr)
+#define readq(addr)		eeh_readq(addr)
+#define writeb(data, addr)	eeh_writeb((data), (addr))
+#define writew(data, addr)	eeh_writew((data), (addr))
+#define writel(data, addr)	eeh_writel((data), (addr))
+#define writeq(data, addr)	eeh_writeq((data), (addr))
+#define memset_io(a,b,c)	eeh_memset_io((a),(b),(c))
+#define memcpy_fromio(a,b,c)	eeh_memcpy_fromio((a),(b),(c))
+#define memcpy_toio(a,b,c)	eeh_memcpy_toio((a),(b),(c))
 #define inb(port)		eeh_inb((unsigned long)port)
 #define outb(val, port)		eeh_outb(val, (unsigned long)port)
 #define inw(port)		eeh_inw((unsigned long)port)
@@ -149,7 +178,7 @@ extern void _outsl_ns(volatile u32 *port, const void *buf, int nl);
 #ifdef __KERNEL__
 extern int __ioremap_explicit(unsigned long p_addr, unsigned long v_addr,
 		     	      unsigned long size, unsigned long flags);
-extern void *__ioremap(unsigned long address, unsigned long size,
+extern void __iomem *__ioremap(unsigned long address, unsigned long size,
 		       unsigned long flags);
 
 /**
@@ -163,11 +192,11 @@ extern void *__ioremap(unsigned long address, unsigned long size,
  * address is not guaranteed to be usable directly as a virtual
  * address.
  */
-extern void *ioremap(unsigned long address, unsigned long size);
+extern void __iomem *ioremap(unsigned long address, unsigned long size);
 
 #define ioremap_nocache(addr, size)	ioremap((addr), (size))
-extern int iounmap_explicit(void *addr, unsigned long size);
-extern void iounmap(void *addr);
+extern int iounmap_explicit(volatile void __iomem *addr, unsigned long size);
+extern void iounmap(volatile void __iomem *addr);
 extern void * reserve_phb_iospace(unsigned long size);
 
 /**
@@ -377,7 +406,7 @@ static inline void out_be64(volatile unsigned long *addr, unsigned long val)
  *	address should have been obtained by ioremap.
  *	Returns 1 on a match.
  */
-static inline int check_signature(unsigned long io_addr,
+static inline int check_signature(const volatile void __iomem * io_addr,
 	const unsigned char *signature, int length)
 {
 	int retval = 0;
diff --git a/include/asm-ppc64/iommu.h b/include/asm-ppc64/iommu.h
index 8530fb673..e67575457 100644
--- a/include/asm-ppc64/iommu.h
+++ b/include/asm-ppc64/iommu.h
@@ -104,16 +104,19 @@ extern struct iommu_table vio_tce_table;      /* Tce table for virtual bus */
 
 struct scatterlist;
 
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_MULTIPLATFORM
+
 /* Walks all buses and creates iommu tables */
 extern void iommu_setup_pSeries(void);
-extern void iommu_setup_pmac(void);
+extern void iommu_setup_u3(void);
 
 /* Creates table for an individual device node */
 extern void iommu_devnode_init(struct device_node *dn);
-#endif /* CONFIG_PPC_PSERIES */
+
+#endif /* CONFIG_PPC_MULTIPLATFORM */
 
 #ifdef CONFIG_PPC_ISERIES
+
 /* Walks all buses and creates iommu tables */
 extern void iommu_setup_iSeries(void);
 
@@ -123,8 +126,8 @@ extern void __init iommu_vio_init(void);
 struct iSeries_Device_Node;
 /* Creates table for an individual device node */
 extern void iommu_devnode_init(struct iSeries_Device_Node *dn);
-#endif /* CONFIG_PPC_ISERIES */
 
+#endif /* CONFIG_PPC_ISERIES */
 
 /* Initializes an iommu_table based in values set in the passed-in
  * structure
@@ -152,6 +155,8 @@ extern void tce_init_iSeries(void);
 extern void pci_iommu_init(void);
 extern void pci_dma_init_direct(void);
 
+extern void alloc_u3_dart_table(void);
+
 extern int ppc64_iommu_off;
 
 #endif /* _ASM_IOMMU_H */
diff --git a/include/asm-ppc64/lmb.h b/include/asm-ppc64/lmb.h
index 43a2f70cf..f1c1f0a38 100644
--- a/include/asm-ppc64/lmb.h
+++ b/include/asm-ppc64/lmb.h
@@ -20,12 +20,6 @@ extern unsigned long reloc_offset(void);
 
 #define MAX_LMB_REGIONS 128
 
-union lmb_reg_property { 
-	struct reg_property32	 addr32[MAX_LMB_REGIONS];
-	struct reg_property64	 addr64[MAX_LMB_REGIONS];
-	struct reg_property_pmac addrPM[MAX_LMB_REGIONS];
-};
-
 #define LMB_ALLOC_ANYWHERE	0
 
 struct lmb_property {
@@ -47,7 +41,7 @@ struct lmb {
 	struct lmb_region reserved;
 };
 
-extern struct lmb lmb __initdata;
+extern struct lmb lmb;
 
 extern void __init lmb_init(void);
 extern void __init lmb_analyze(void);
@@ -60,6 +54,8 @@ extern unsigned long __init lmb_phys_mem_size(void);
 extern unsigned long __init lmb_end_of_DRAM(void);
 extern unsigned long __init lmb_abs_to_phys(unsigned long);
 
+extern void lmb_dump_all(void);
+
 extern unsigned long io_hole_start;
 
 #endif /* _PPC64_LMB_H */
diff --git a/include/asm-ppc64/machdep.h b/include/asm-ppc64/machdep.h
index 020c7922f..e3b860769 100644
--- a/include/asm-ppc64/machdep.h
+++ b/include/asm-ppc64/machdep.h
@@ -56,6 +56,9 @@ struct machdep_calls {
 	void		(*flush_hash_range)(unsigned long context,
 					    unsigned long number,
 					    int local);
+	/* special for kexec, to be called in real mode, linar mapping is
+	 * destroyed as well */
+	void		(*hpte_clear_all)(void);
 
 	void		(*tce_build)(struct iommu_table * tbl,
 				     long index,
@@ -67,7 +70,9 @@ struct machdep_calls {
 				    long npages);
 	void		(*tce_flush)(struct iommu_table *tbl);
 
+	int		(*probe)(int platform);
 	void		(*setup_arch)(void);
+	void		(*init_early)(void);
 	/* Optional, may be NULL. */
 	void		(*get_cpuinfo)(struct seq_file *m);
 
@@ -77,9 +82,6 @@ struct machdep_calls {
 	/* PCI stuff */
 	void		(*pcibios_fixup)(void);
 
-	/* Optional, may be NULL. */
-	void		(*init)(void);
-
 	void		(*restart)(char *cmd);
 	void		(*power_off)(void);
 	void		(*halt)(void);
diff --git a/include/asm-ppc64/memory.h b/include/asm-ppc64/memory.h
index 40c4a6e4a..56e09face 100644
--- a/include/asm-ppc64/memory.h
+++ b/include/asm-ppc64/memory.h
@@ -56,14 +56,4 @@ static inline void isync(void)
 #define HMT_MEDIUM_HIGH "\tor   5,5,5           # medium high priority\n"
 #define HMT_HIGH	"\tor	3,3,3		# high priority\n"
 
-/* 
- * Various operational modes for SMT
- * Off    : never run threaded
- * On     : always run threaded
- * Dynamic: Allow the system to switch modes as needed
- */
-#define SMT_OFF      0
-#define SMT_ON       1
-#define SMT_DYNAMIC  2
-
 #endif
diff --git a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h
index 3b66f32b6..616389dc8 100644
--- a/include/asm-ppc64/mmu.h
+++ b/include/asm-ppc64/mmu.h
@@ -15,6 +15,7 @@
 
 #include <linux/config.h>
 #include <asm/page.h>
+#include <linux/stringify.h>
 
 #ifndef __ASSEMBLY__
 
@@ -27,43 +28,17 @@ typedef struct {
 #endif
 } mm_context_t;
 
-#ifdef CONFIG_HUGETLB_PAGE
-#define KERNEL_LOW_HPAGES	.htlb_segs = 0,
-#else
-#define KERNEL_LOW_HPAGES
-#endif
+#define STE_ESID_V	0x80
+#define STE_ESID_KS	0x20
+#define STE_ESID_KP	0x10
+#define STE_ESID_N	0x08
 
-#define KERNEL_CONTEXT(ea) ({ \
-		mm_context_t ctx = { .id = REGION_ID(ea), KERNEL_LOW_HPAGES}; \
-		ctx; })
-
-typedef struct {
-	unsigned long esid: 36; /* Effective segment ID */
-	unsigned long resv0:20; /* Reserved */
-	unsigned long v:     1; /* Entry valid (v=1) or invalid */
-	unsigned long resv1: 1; /* Reserved */
-	unsigned long ks:    1; /* Supervisor (privileged) state storage key */
-	unsigned long kp:    1; /* Problem state storage key */
-	unsigned long n:     1; /* No-execute if n=1 */
-	unsigned long resv2: 3; /* padding to a 64b boundary */
-} ste_dword0;
-
-typedef struct {
-	unsigned long vsid: 52; /* Virtual segment ID */
-	unsigned long resv0:12; /* Padding to a 64b boundary */
-} ste_dword1;
-
-typedef struct _STE {
-	union {
-		unsigned long dword0;
-		ste_dword0    dw0;
-	} dw0;
+#define STE_VSID_SHIFT	12
 
-	union {
-		unsigned long dword1;
-		ste_dword1    dw1;
-	} dw1;
-} STE;
+struct stab_entry {
+	unsigned long esid_data;
+	unsigned long vsid_data;
+};
 
 /* Hardware Page Table Entry */
 
@@ -132,20 +107,6 @@ typedef struct {
 
 extern HTAB htab_data;
 
-void invalidate_hpte( unsigned long slot );
-long select_hpte_slot( unsigned long vpn );
-void create_valid_hpte( unsigned long slot, unsigned long vpn,
-			unsigned long prpn, unsigned hash,
-			void * ptep, unsigned hpteflags,
-			unsigned bolted );
-
-#define PD_SHIFT (10+12)		/* Page directory */
-#define PD_MASK  0x02FF
-#define PT_SHIFT (12)			/* Page Table */
-#define PT_MASK  0x02FF
-
-#define LARGE_PAGE_SHIFT 24
-
 static inline unsigned long hpt_hash(unsigned long vpn, int large)
 {
 	unsigned long vsid;
@@ -224,7 +185,7 @@ extern void htab_finish_init(void);
 #define STAB0_PHYS_ADDR	(STAB0_PAGE<<PAGE_SHIFT)
 #define STAB0_VIRT_ADDR	(KERNELBASE+STAB0_PHYS_ADDR)
 
-#define SLB_NUM_BOLTED		2
+#define SLB_NUM_BOLTED		3
 #define SLB_CACHE_ENTRIES	8
 
 /* Bits in the SLB ESID word */
@@ -241,156 +202,43 @@ extern void htab_finish_init(void);
 #define SLB_VSID_KERNEL		(SLB_VSID_KP|SLB_VSID_C)
 #define SLB_VSID_USER		(SLB_VSID_KP|SLB_VSID_KS)
 
-#define VSID_RANDOMIZER ASM_CONST(42470972311)
-#define VSID_MASK	0xfffffffffUL
-/* Because we never access addresses below KERNELBASE as kernel
- * addresses, this VSID is never used for anything real, and will
- * never have pages hashed into it */
-#define BAD_VSID	ASM_CONST(0)
-
-/* 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
-
-/* Used to set up SDR1 register */
-#define HASH_TABLE_SIZE_64K	0x00010000
-#define HASH_TABLE_SIZE_128K	0x00020000
-#define HASH_TABLE_SIZE_256K	0x00040000
-#define HASH_TABLE_SIZE_512K	0x00080000
-#define HASH_TABLE_SIZE_1M	0x00100000
-#define HASH_TABLE_SIZE_2M	0x00200000
-#define HASH_TABLE_SIZE_4M	0x00400000
-#define HASH_TABLE_MASK_64K	0x000   
-#define HASH_TABLE_MASK_128K	0x001   
-#define HASH_TABLE_MASK_256K	0x003   
-#define HASH_TABLE_MASK_512K	0x007
-#define HASH_TABLE_MASK_1M	0x00F   
-#define HASH_TABLE_MASK_2M	0x01F   
-#define HASH_TABLE_MASK_4M	0x03F   
-
-/* These are the Ks and Kp from the PowerPC books.  For proper operation,
- * Ks = 0, Kp = 1.
- */
-#define MI_AP		786
-#define MI_Ks		0x80000000	/* Should not be set */
-#define MI_Kp		0x40000000	/* Should always be set */
-
-/* The effective page number register.  When read, contains the information
- * about the last instruction TLB miss.  When MI_RPN is written, bits in
- * this register are used to create the TLB entry.
- */
-#define MI_EPN		787
-#define MI_EPNMASK	0xfffff000	/* Effective page number for entry */
-#define MI_EVALID	0x00000200	/* Entry is valid */
-#define MI_ASIDMASK	0x0000000f	/* ASID match value */
-					/* Reset value is undefined */
-
-/* A "level 1" or "segment" or whatever you want to call it register.
- * For the instruction TLB, it contains bits that get loaded into the
- * TLB entry when the MI_RPN is written.
- */
-#define MI_TWC		789
-#define MI_APG		0x000001e0	/* Access protection group (0) */
-#define MI_GUARDED	0x00000010	/* Guarded storage */
-#define MI_PSMASK	0x0000000c	/* Mask of page size bits */
-#define MI_PS8MEG	0x0000000c	/* 8M page size */
-#define MI_PS512K	0x00000004	/* 512K page size */
-#define MI_PS4K_16K	0x00000000	/* 4K or 16K page size */
-#define MI_SVALID	0x00000001	/* Segment entry is valid */
-					/* Reset value is undefined */
-
-/* Real page number.  Defined by the pte.  Writing this register
- * causes a TLB entry to be created for the instruction TLB, using
- * additional information from the MI_EPN, and MI_TWC registers.
- */
-#define MI_RPN		790
-
-/* Define an RPN value for mapping kernel memory to large virtual
- * pages for boot initialization.  This has real page number of 0,
- * large page size, shared page, cache enabled, and valid.
- * Also mark all subpages valid and write access.
- */
-#define MI_BOOTINIT	0x000001fd
-
-#define MD_CTR		792	/* Data TLB control register */
-#define MD_GPM		0x80000000	/* Set domain manager mode */
-#define MD_PPM		0x40000000	/* Set subpage protection */
-#define MD_CIDEF	0x20000000	/* Set cache inhibit when MMU dis */
-#define MD_WTDEF	0x10000000	/* Set writethrough when MMU dis */
-#define MD_RSV4I	0x08000000	/* Reserve 4 TLB entries */
-#define MD_TWAM		0x04000000	/* Use 4K page hardware assist */
-#define MD_PPCS		0x02000000	/* Use MI_RPN prob/priv state */
-#define MD_IDXMASK	0x00001f00	/* TLB index to be loaded */
-#define MD_RESETVAL	0x04000000	/* Value of register at reset */
-
-#define M_CASID		793	/* Address space ID (context) to match */
-#define MC_ASIDMASK	0x0000000f	/* Bits used for ASID value */
-
+#define VSID_MULTIPLIER	ASM_CONST(200730139)	/* 28-bit prime */
+#define VSID_BITS	36
+#define VSID_MODULUS	((1UL<<VSID_BITS)-1)
 
-/* These are the Ks and Kp from the PowerPC books.  For proper operation,
- * Ks = 0, Kp = 1.
- */
-#define MD_AP		794
-#define MD_Ks		0x80000000	/* Should not be set */
-#define MD_Kp		0x40000000	/* Should always be set */
+#define CONTEXT_BITS	20
+#define USER_ESID_BITS	15
 
-/* The effective page number register.  When read, contains the information
- * about the last instruction TLB miss.  When MD_RPN is written, bits in
- * this register are used to create the TLB entry.
- */
-#define MD_EPN		795
-#define MD_EPNMASK	0xfffff000	/* Effective page number for entry */
-#define MD_EVALID	0x00000200	/* Entry is valid */
-#define MD_ASIDMASK	0x0000000f	/* ASID match value */
-					/* Reset value is undefined */
-
-/* The pointer to the base address of the first level page table.
- * During a software tablewalk, reading this register provides the address
- * of the entry associated with MD_EPN.
- */
-#define M_TWB		796
-#define	M_L1TB		0xfffff000	/* Level 1 table base address */
-#define M_L1INDX	0x00000ffc	/* Level 1 index, when read */
-					/* Reset value is undefined */
-
-/* A "level 1" or "segment" or whatever you want to call it register.
- * For the data TLB, it contains bits that get loaded into the TLB entry
- * when the MD_RPN is written.  It is also provides the hardware assist
- * for finding the PTE address during software tablewalk.
- */
-#define MD_TWC		797
-#define MD_L2TB		0xfffff000	/* Level 2 table base address */
-#define MD_L2INDX	0xfffffe00	/* Level 2 index (*pte), when read */
-#define MD_APG		0x000001e0	/* Access protection group (0) */
-#define MD_GUARDED	0x00000010	/* Guarded storage */
-#define MD_PSMASK	0x0000000c	/* Mask of page size bits */
-#define MD_PS8MEG	0x0000000c	/* 8M page size */
-#define MD_PS512K	0x00000004	/* 512K page size */
-#define MD_PS4K_16K	0x00000000	/* 4K or 16K page size */
-#define MD_WT		0x00000002	/* Use writethrough page attribute */
-#define MD_SVALID	0x00000001	/* Segment entry is valid */
-					/* Reset value is undefined */
-
-
-/* Real page number.  Defined by the pte.  Writing this register
- * causes a TLB entry to be created for the data TLB, using
- * additional information from the MD_EPN, and MD_TWC registers.
- */
-#define MD_RPN		798
-
-/* This is a temporary storage register that could be used to save
- * a processor working register during a tablewalk.
+/*
+ * This macro generates asm code to compute the VSID scramble
+ * function.  Used in slb_allocate() and do_stab_bolted.  The function
+ * computed is: (protovsid*VSID_MULTIPLIER) % VSID_MODULUS
+ *
+ *	rt = register continaing the proto-VSID and into which the
+ *		VSID will be stored
+ *	rx = scratch register (clobbered)
+ *
+ * 	- rt and rx must be different registers
+ * 	- The answer will end up in the low 36 bits of rt.  The higher
+ * 	  bits may contain other garbage, so you may need to mask the
+ * 	  result.
  */
-#define M_TW		799
+#define ASM_VSID_SCRAMBLE(rt, rx)	\
+	lis	rx,VSID_MULTIPLIER@h;					\
+	ori	rx,rx,VSID_MULTIPLIER@l;				\
+	mulld	rt,rt,rx;		/* rt = rt * MULTIPLIER */	\
+									\
+	srdi	rx,rt,VSID_BITS;					\
+	clrldi	rt,rt,(64-VSID_BITS);					\
+	add	rt,rt,rx;		/* add high and low bits */	\
+	/* Now, r3 == VSID (mod 2^36-1), and lies between 0 and		\
+	 * 2^36-1+2^28-1.  That in particular means that if r3 >=	\
+	 * 2^36-1, then r3+1 has the 2^36 bit set.  So, if r3+1 has	\
+	 * the bit clear, r3 already has the answer we want, if it	\
+	 * doesn't, the answer is the low 36 bits of r3+1.  So in all	\
+	 * cases the answer is the low 36 bits of (r3 + ((r3+1) >> 36))*/\
+	addi	rx,rt,1;						\
+	srdi	rx,rx,VSID_BITS;	/* extract 2^36 bit */		\
+	add	rt,rt,rx
 
 #endif /* _PPC64_MMU_H_ */
diff --git a/include/asm-ppc64/mmu_context.h b/include/asm-ppc64/mmu_context.h
index 03561b589..bfce35705 100644
--- a/include/asm-ppc64/mmu_context.h
+++ b/include/asm-ppc64/mmu_context.h
@@ -2,11 +2,9 @@
 #define __PPC64_MMU_CONTEXT_H
 
 #include <linux/config.h>
-#include <linux/spinlock.h>	
 #include <linux/kernel.h>	
 #include <linux/mm.h>	
 #include <asm/mmu.h>	
-#include <asm/ppcdebug.h>	
 #include <asm/cputable.h>
 
 /*
@@ -33,109 +31,17 @@ static inline int sched_find_first_bit(unsigned long *b)
 	return __ffs(b[2]) + 128;
 }
 
-#define NO_CONTEXT		0
-#define FIRST_USER_CONTEXT	0x10    /* First 16 reserved for kernel */
-#define LAST_USER_CONTEXT	0x8000  /* Same as PID_MAX for now... */
-#define NUM_USER_CONTEXT	(LAST_USER_CONTEXT-FIRST_USER_CONTEXT)
-
-/* Choose whether we want to implement our context
- * number allocator as a LIFO or FIFO queue.
- */
-#if 1
-#define MMU_CONTEXT_LIFO
-#else
-#define MMU_CONTEXT_FIFO
-#endif
-
-struct mmu_context_queue_t {
-	spinlock_t lock;
-	long head;
-	long tail;
-	long size;
-	mm_context_id_t elements[LAST_USER_CONTEXT];
-};
-
-extern struct mmu_context_queue_t mmu_context_queue;
-
-static inline void
-enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
-{
-}
-
-/*
- * The context number queue has underflowed.
- * Meaning: we tried to push a context number that was freed
- * back onto the context queue and the queue was already full.
- */
-static inline void
-mmu_context_underflow(void)
-{
-	printk(KERN_DEBUG "mmu_context_underflow\n");
-	panic("mmu_context_underflow");
-}
-
-/*
- * Set up the context for a new address space.
- */
-static inline int
-init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
-	long head;
-	unsigned long flags;
-	/* This does the right thing across a fork (I hope) */
-
-	spin_lock_irqsave(&mmu_context_queue.lock, flags);
-
-	if (mmu_context_queue.size <= 0) {
-		spin_unlock_irqrestore(&mmu_context_queue.lock, flags);
-		return -ENOMEM;
-	}
-
-	head = mmu_context_queue.head;
-	mm->context.id = mmu_context_queue.elements[head];
-
-	head = (head < LAST_USER_CONTEXT-1) ? head+1 : 0;
-	mmu_context_queue.head = head;
-	mmu_context_queue.size--;
-
-	spin_unlock_irqrestore(&mmu_context_queue.lock, flags);
-
-	return 0;
 }
 
-/*
- * We're finished using the context for an address space.
- */
-static inline void
-destroy_context(struct mm_struct *mm)
-{
-	long index;
-	unsigned long flags;
-
-	spin_lock_irqsave(&mmu_context_queue.lock, flags);
+#define NO_CONTEXT	0
+#define MAX_CONTEXT	(0x100000-1)
 
-	if (mmu_context_queue.size >= NUM_USER_CONTEXT) {
-		spin_unlock_irqrestore(&mmu_context_queue.lock, flags);
-		mmu_context_underflow();
-	}
+extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
+extern void destroy_context(struct mm_struct *mm);
 
-#ifdef MMU_CONTEXT_LIFO
-	index = mmu_context_queue.head;
-	index = (index > 0) ? index-1 : LAST_USER_CONTEXT-1;
-	mmu_context_queue.head = index;
-#else
-	index = mmu_context_queue.tail;
-	index = (index < LAST_USER_CONTEXT-1) ? index+1 : 0;
-	mmu_context_queue.tail = index;
-#endif
-
-	mmu_context_queue.size++;
-	mmu_context_queue.elements[index] = mm->context.id;
-
-	spin_unlock_irqrestore(&mmu_context_queue.lock, flags);
-}
-
-extern void flush_stab(struct task_struct *tsk, struct mm_struct *mm);
+extern void switch_stab(struct task_struct *tsk, struct mm_struct *mm);
 extern void switch_slb(struct task_struct *tsk, struct mm_struct *mm);
 
 /*
@@ -163,7 +69,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 	if (cur_cpu_spec->cpu_features & CPU_FTR_SLB)
 		switch_slb(tsk, next);
 	else
-		flush_stab(tsk, next);
+		switch_stab(tsk, next);
 }
 
 #define deactivate_mm(tsk,mm)	do { } while (0)
@@ -181,46 +87,86 @@ static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
 	local_irq_restore(flags);
 }
 
-/* This is only valid for kernel (including vmalloc, imalloc and bolted) EA's
+/* VSID allocation
+ * ===============
+ *
+ * We first generate a 36-bit "proto-VSID".  For kernel addresses this
+ * is equal to the ESID, for user addresses it is:
+ *	(context << 15) | (esid & 0x7fff)
+ *
+ * The two forms are distinguishable because the top bit is 0 for user
+ * addresses, whereas the top two bits are 1 for kernel addresses.
+ * Proto-VSIDs with the top two bits equal to 0b10 are reserved for
+ * now.
+ *
+ * The proto-VSIDs are then scrambled into real VSIDs with the
+ * multiplicative hash:
+ *
+ *	VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS
+ *	where	VSID_MULTIPLIER = 268435399 = 0xFFFFFC7
+ *		VSID_MODULUS = 2^36-1 = 0xFFFFFFFFF
+ *
+ * This scramble is only well defined for proto-VSIDs below
+ * 0xFFFFFFFFF, so both proto-VSID and actual VSID 0xFFFFFFFFF are
+ * reserved.  VSID_MULTIPLIER is prime, so in particular it is
+ * co-prime to VSID_MODULUS, making this a 1:1 scrambling function.
+ * Because the modulus is 2^n-1 we can compute it efficiently without
+ * a divide or extra multiply (see below).
+ *
+ * This scheme has several advantages over older methods:
+ *
+ * 	- We have VSIDs allocated for every kernel address
+ * (i.e. everything above 0xC000000000000000), except the very top
+ * segment, which simplifies several things.
+ *
+ * 	- We allow for 15 significant bits of ESID and 20 bits of
+ * context for user addresses.  i.e. 8T (43 bits) of address space for
+ * up to 1M contexts (although the page table structure and context
+ * allocation will need changes to take advantage of this).
+ *
+ * 	- The scramble function gives robust scattering in the hash
+ * table (at least based on some initial results).  The previous
+ * method was more susceptible to pathological cases giving excessive
+ * hash collisions.
  */
-static inline unsigned long
-get_kernel_vsid( unsigned long ea )
-{
-	unsigned long ordinal, vsid;
-	
-	ordinal = (((ea >> 28) & 0x1fff) * LAST_USER_CONTEXT) | (ea >> 60);
-	vsid = (ordinal * VSID_RANDOMIZER) & VSID_MASK;
-
-#ifdef HTABSTRESS
-	/* For debug, this path creates a very poor vsid distribuition.
-	 * A user program can access virtual addresses in the form
-	 * 0x0yyyyxxxx000 where yyyy = xxxx to cause multiple mappings
-	 * to hash to the same page table group.
-	 */
-	ordinal = ((ea >> 28) & 0x1fff) | (ea >> 44);
-	vsid = ordinal & VSID_MASK;
-#endif /* HTABSTRESS */
-
-	return vsid;
-} 
-
-/* This is only valid for user EA's (user EA's do not exceed 2^41 (EADDR_SIZE))
+
+/*
+ * WARNING - If you change these you must make sure the asm
+ * implementations in slb_allocate(), do_stab_bolted and mmu.h
+ * (ASM_VSID_SCRAMBLE macro) are changed accordingly.
+ *
+ * You'll also need to change the precomputed VSID values in head.S
+ * which are used by the iSeries firmware.
  */
-static inline unsigned long
-get_vsid( unsigned long context, unsigned long ea )
-{
-	unsigned long ordinal, vsid;
 
-	ordinal = (((ea >> 28) & 0x1fff) * LAST_USER_CONTEXT) | context;
-	vsid = (ordinal * VSID_RANDOMIZER) & VSID_MASK;
+static inline unsigned long vsid_scramble(unsigned long protovsid)
+{
+#if 0
+	/* The code below is equivalent to this function for arguments
+	 * < 2^VSID_BITS, which is all this should ever be called
+	 * with.  However gcc is not clever enough to compute the
+	 * modulus (2^n-1) without a second multiply. */
+	return ((protovsid * VSID_MULTIPLIER) % VSID_MODULUS);
+#else /* 1 */
+	unsigned long x;
+
+	x = protovsid * VSID_MULTIPLIER;
+	x = (x >> VSID_BITS) + (x & VSID_MODULUS);
+	return (x + ((x+1) >> VSID_BITS)) & VSID_MODULUS;
+#endif /* 1 */
+}
 
-#ifdef HTABSTRESS
-	/* See comment above. */
-	ordinal = ((ea >> 28) & 0x1fff) | (context << 16);
-	vsid = ordinal & VSID_MASK;
-#endif /* HTABSTRESS */
+/* This is only valid for addresses >= KERNELBASE */
+static inline unsigned long get_kernel_vsid(unsigned long ea)
+{
+	return vsid_scramble(ea >> SID_SHIFT);
+}
 
-	return vsid;
+/* This is only valid for user addresses (which are below 2^41) */
+static inline unsigned long get_vsid(unsigned long context, unsigned long ea)
+{
+	return vsid_scramble((context << USER_ESID_BITS)
+			     | (ea >> SID_SHIFT));
 }
 
 #endif /* __PPC64_MMU_CONTEXT_H */
diff --git a/include/asm-ppc64/mmzone.h b/include/asm-ppc64/mmzone.h
index 6903024ff..0619a41a3 100644
--- a/include/asm-ppc64/mmzone.h
+++ b/include/asm-ppc64/mmzone.h
@@ -12,7 +12,7 @@
 
 #ifdef CONFIG_DISCONTIGMEM
 
-extern struct pglist_data node_data[];
+extern struct pglist_data *node_data[];
 
 /*
  * Following are specific to this numa platform.
@@ -52,7 +52,7 @@ static inline int pa_to_nid(unsigned long pa)
 /*
  * Return a pointer to the node data for node n.
  */
-#define NODE_DATA(nid)		(&node_data[nid])
+#define NODE_DATA(nid)		(node_data[nid])
 
 #define node_localnr(pfn, nid)	((pfn) - NODE_DATA(nid)->node_start_pfn)
 
diff --git a/include/asm-ppc64/naca.h b/include/asm-ppc64/naca.h
index 3c0b8d3a5..04541849f 100644
--- a/include/asm-ppc64/naca.h
+++ b/include/asm-ppc64/naca.h
@@ -37,9 +37,6 @@ struct naca_struct {
 	u32 dCacheL1LinesPerPage;	/* L1 d-cache lines / page   0x64 */
 	u32 iCacheL1LogLineSize;	/* L1 i-cache line size Log2 0x68 */
 	u32 iCacheL1LinesPerPage;	/* L1 i-cache lines / page   0x6c */
-	u8  smt_state;                  /* 0 = SMT off               0x70 */
-	                                /* 1 = SMT on                     */
-	                                /* 2 = SMT dynamic                */
 	u8  resv0[15];                  /* Reserved           0x71 - 0x7F */
 };
 
diff --git a/include/asm-ppc64/paca.h b/include/asm-ppc64/paca.h
index 851082cd2..71de51ac9 100644
--- a/include/asm-ppc64/paca.h
+++ b/include/asm-ppc64/paca.h
@@ -16,6 +16,7 @@
  * 2 of the License, or (at your option) any later version.
  */    
 
+#include	<linux/config.h>
 #include	<asm/types.h>
 #include	<asm/iSeries/ItLpPaca.h>
 #include	<asm/iSeries/ItLpRegSave.h>
@@ -78,7 +79,6 @@ struct paca_struct {
 	u64 exmc[8];		/* used for machine checks */
 	u64 exslb[8];		/* used for SLB/segment table misses
 				 * on the linear mapping */
-	u64 slb_r3;		/* spot to save R3 on SLB miss */
 	mm_context_t context;
 	u16 slb_cache[SLB_CACHE_ENTRIES];
 	u16 slb_cache_ptr;
@@ -104,22 +104,9 @@ struct paca_struct {
 	 * The lppaca is also used on POWER5 pSeries boxes.
 	 */
 	struct ItLpPaca lppaca __attribute__((aligned(0x80)));
+#ifdef CONFIG_PPC_ISERIES
 	struct ItLpRegSave reg_save;
-
-	/*
-	 * iSeries profiling support
-	 *
-	 * FIXME: do we still want this, or can we ditch it in favour
-	 * of oprofile?
-	 */
-	u32 *prof_buffer;		/* iSeries profiling buffer */
-	u32 *prof_stext;		/* iSeries start of kernel text */
-	u32 prof_multiplier;
-	u32 prof_counter;
-	u32 prof_shift;			/* iSeries shift for profile
-					 * bucket size */
-	u32 prof_len;			/* iSeries length of profile */
-	u8 prof_enabled;		/* 1=iSeries profiling enabled */
+#endif
 };
 
 #endif /* _PPC64_PACA_H */
diff --git a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h
index a30e2a97b..ac098722a 100644
--- a/include/asm-ppc64/page.h
+++ b/include/asm-ppc64/page.h
@@ -30,11 +30,12 @@
 #define ESID_MASK	0xfffffffff0000000UL
 #define GET_ESID(x)     (((x) >> SID_SHIFT) & SID_MASK)
 
-#ifdef CONFIG_HUGETLB_PAGE
-
 #define HPAGE_SHIFT	24
 #define HPAGE_SIZE	((1UL) << HPAGE_SHIFT)
 #define HPAGE_MASK	(~(HPAGE_SIZE - 1))
+
+#ifdef CONFIG_HUGETLB_PAGE
+
 #define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
 
 /* For 64-bit processes the hugepage range is 1T-1.5T */
@@ -181,8 +182,7 @@ static inline int get_order(unsigned long size)
 
 #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
 
-/* Not 100% correct, for use by /dev/mem only */
-extern int page_is_ram(unsigned long physaddr);
+extern int page_is_ram(unsigned long pfn);
 
 #endif /* __ASSEMBLY__ */
 
@@ -202,9 +202,9 @@ extern int page_is_ram(unsigned long physaddr);
 /*             to change!                               */
 #define PAGE_OFFSET     ASM_CONST(0xC000000000000000)
 #define KERNELBASE      PAGE_OFFSET
-#define VMALLOCBASE     0xD000000000000000UL
-#define IOREGIONBASE    0xE000000000000000UL
-#define EEHREGIONBASE   0xA000000000000000UL
+#define VMALLOCBASE     ASM_CONST(0xD000000000000000)
+#define IOREGIONBASE    ASM_CONST(0xE000000000000000)
+#define EEHREGIONBASE   ASM_CONST(0xA000000000000000)
 
 #define IO_REGION_ID       (IOREGIONBASE>>REGION_SHIFT)
 #define EEH_REGION_ID      (EEHREGIONBASE>>REGION_SHIFT)
@@ -213,17 +213,6 @@ extern int page_is_ram(unsigned long physaddr);
 #define USER_REGION_ID     (0UL)
 #define REGION_ID(X)	   (((unsigned long)(X))>>REGION_SHIFT)
 
-/*
- * Define valid/invalid EA bits (for all ranges)
- */
-#define VALID_EA_BITS   (0x000001ffffffffffUL)
-#define INVALID_EA_BITS (~(REGION_MASK|VALID_EA_BITS))
-
-#define IS_VALID_REGION_ID(x) \
-        (((x) == USER_REGION_ID) || ((x) >= KERNEL_REGION_ID))
-#define IS_VALID_EA(x) \
-        ((!((x) & INVALID_EA_BITS)) && IS_VALID_REGION_ID(REGION_ID(x)))
-
 #define __bpn_to_ba(x) ((((unsigned long)(x))<<PAGE_SHIFT) + KERNELBASE)
 #define __ba_to_bpn(x) ((((unsigned long)(x)) & ~REGION_MASK) >> PAGE_SHIFT)
 
@@ -240,6 +229,7 @@ extern int page_is_ram(unsigned long physaddr);
 #endif
 
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
 
 #define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 
diff --git a/include/asm-ppc64/pci-bridge.h b/include/asm-ppc64/pci-bridge.h
index acb6aff2a..a51c604b9 100644
--- a/include/asm-ppc64/pci-bridge.h
+++ b/include/asm-ppc64/pci-bridge.h
@@ -33,9 +33,9 @@ enum phb_types {
 struct pci_controller {
 	char what[8];                     /* Eye catcher      */
 	enum phb_types type;              /* Type of hardware */
-	struct pci_controller *next;
 	struct pci_bus *bus;
 	void *arch_data;
+	struct list_head list_node;
 
 	int first_busno;
 	int last_busno;
@@ -70,8 +70,8 @@ struct pci_controller {
  * for a device on a PCI bus, given its device_node struct.
  * It returns 0 if OK, -1 on error.
  */
-int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr,
-		   unsigned char *devfn_ptr);
+extern int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr,
+			  unsigned char *devfn_ptr);
 
 struct device_node *fetch_dev_dn(struct pci_dev *dev);
 
@@ -87,6 +87,9 @@ static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev)
 		return fetch_dev_dn(dev);
 }
 
+extern void pci_process_bridge_OF_ranges(struct pci_controller *hose,
+					 struct device_node *dev, int primary);
+
 /* Use this macro after the PCI bus walk for max performance when it
  * is known that sysdata is correct.
  */
diff --git a/include/asm-ppc64/pgalloc.h b/include/asm-ppc64/pgalloc.h
index 8b79f3626..dd717c2bb 100644
--- a/include/asm-ppc64/pgalloc.h
+++ b/include/asm-ppc64/pgalloc.h
@@ -7,6 +7,7 @@
 #include <linux/percpu.h>
 #include <asm/processor.h>
 #include <asm/tlb.h>
+#include <asm/page.h>
 
 extern kmem_cache_t *zero_cache;
 
diff --git a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h
index 8499868b2..5a4a18043 100644
--- a/include/asm-ppc64/pgtable.h
+++ b/include/asm-ppc64/pgtable.h
@@ -44,11 +44,17 @@
 #define EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \
                     PGD_INDEX_SIZE + PAGE_SHIFT) 
 
+/*
+ * Size of EA range mapped by our pagetables.
+ */
+#define PGTABLE_EA_BITS	41
+#define PGTABLE_EA_MASK	((1UL<<PGTABLE_EA_BITS)-1)
+
 /*
  * Define the address range of the vmalloc VM area.
  */
 #define VMALLOC_START (0xD000000000000000ul)
-#define VMALLOC_END   (VMALLOC_START + VALID_EA_BITS)
+#define VMALLOC_END   (VMALLOC_START + PGTABLE_EA_MASK)
 
 /*
  * Define the address range of the imalloc VM area.
@@ -58,19 +64,19 @@
 #define IMALLOC_VMADDR(x) ((unsigned long)(x))
 #define PHBS_IO_BASE  	  (0xE000000000000000ul)	/* Reserve 2 gigs for PHBs */
 #define IMALLOC_BASE      (0xE000000080000000ul)  
-#define IMALLOC_END       (IMALLOC_BASE + VALID_EA_BITS)
+#define IMALLOC_END       (IMALLOC_BASE + PGTABLE_EA_MASK)
 
 /*
  * Define the address range mapped virt <-> physical
  */
 #define KRANGE_START KERNELBASE
-#define KRANGE_END   (KRANGE_START + VALID_EA_BITS)
+#define KRANGE_END   (KRANGE_START + PGTABLE_EA_MASK)
 
 /*
  * Define the user address range
  */
 #define USER_START (0UL)
-#define USER_END   (USER_START + VALID_EA_BITS)
+#define USER_END   (USER_START + PGTABLE_EA_MASK)
 
 
 /*
@@ -167,6 +173,7 @@ int hash_huge_page(struct mm_struct *mm, unsigned long access,
 #endif /* __ASSEMBLY__ */
 
 #define HAVE_ARCH_UNMAPPED_AREA
+#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
 #else
 
 #define hash_huge_page(mm,a,ea,vsid,local)	-1
@@ -489,7 +496,8 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
 
 void pgtable_cache_init(void);
 
-extern void hpte_init_pSeries(void);
+extern void hpte_init_native(void);
+extern void hpte_init_lpar(void);
 extern void hpte_init_iSeries(void);
 
 /* imalloc region types */
@@ -497,20 +505,21 @@ extern void hpte_init_iSeries(void);
 #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);
 unsigned long im_free(void *addr);
 
-long pSeries_lpar_hpte_insert(unsigned long hpte_group,
-			      unsigned long va, unsigned long prpn,
-			      int secondary, unsigned long hpteflags,
-			      int bolted, int large);
+extern long pSeries_lpar_hpte_insert(unsigned long hpte_group,
+				     unsigned long va, unsigned long prpn,
+				     int secondary, unsigned long hpteflags,
+				     int bolted, int large);
 
-long pSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
-			 unsigned long prpn, int secondary,
-			 unsigned long hpteflags, int bolted, int large);
+extern long native_hpte_insert(unsigned long hpte_group, unsigned long va,
+			       unsigned long prpn, int secondary,
+			       unsigned long hpteflags, int bolted, int large);
 
 /*
  * find_linux_pte returns the address of a linux pte for a given 
diff --git a/include/asm-ppc64/ppc32.h b/include/asm-ppc64/ppc32.h
index f4a36ea03..1d0404897 100644
--- a/include/asm-ppc64/ppc32.h
+++ b/include/asm-ppc64/ppc32.h
@@ -14,30 +14,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-/* Use this to get at 32-bit user passed pointers. */
-/* Things to consider: the low-level assembly stub does
-   srl x, 0, x for first four arguments, so if you have
-   pointer to something in the first four arguments, just
-   declare it as a pointer, not u32. On the other side, 
-   arguments from 5th onwards should be declared as u32
-   for pointers, and need AA() around each usage.
-   A() macro should be used for places where you e.g.
-   have some internal variable u32 and just want to get
-   rid of a compiler warning. AA() has to be used in
-   places where you want to convert a function argument
-   to 32bit pointer or when you e.g. access pt_regs
-   structure and want to consider 32bit registers only.
-   -
- */
-#define A(__x) ((unsigned long)(__x))
-#define AA(__x)				\
-({	unsigned long __ret;		\
-	__asm__ ("clrldi	%0, %0, 32"	\
-		 : "=r" (__ret)		\
-		 : "0" (__x));		\
-	__ret;				\
-})
-
 /* These are here to support 32-bit syscalls on a 64-bit kernel. */
 
 typedef struct compat_siginfo {
@@ -56,8 +32,10 @@ typedef struct compat_siginfo {
 
 		/* POSIX.1b timers */
 		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
+			timer_t _tid;			/* timer id */
+			int _overrun;			/* overrun count */
+			compat_sigval_t _sigval;		/* same as below */
+			int _sys_private;		/* not to be passed to user */
 		} _timer;
 
 		/* POSIX.1b signals */
diff --git a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h
index d5e383732..19ef02511 100644
--- a/include/asm-ppc64/processor.h
+++ b/include/asm-ppc64/processor.h
@@ -20,12 +20,6 @@
 #include <asm/ptrace.h>
 #include <asm/types.h>
 
-/*
- * Default implementation of macro that returns current
- * instruction pointer ("program counter").
- */
-#define current_text_addr() ({ __label__ _l; _l: &&_l;})
-
 /* Machine State Register (MSR) Fields */
 #define MSR_SF_LG	63              /* Enable 64 bit mode */
 #define MSR_ISF_LG	61              /* Interrupt 64b mode valid on 630 */
@@ -410,6 +404,12 @@
 #define XGLUE(a,b) a##b
 #define GLUE(a,b) XGLUE(a,b)
 
+/* iSeries CTRL register (for runlatch) */
+
+#define CTRLT		0x098
+#define CTRLF		0x088
+#define RUNLATCH	0x0001
+
 #ifdef __ASSEMBLY__
 
 #define _GLOBAL(name) \
@@ -438,8 +438,13 @@ name: \
 	.type GLUE(.,name),@function; \
 GLUE(.,name):
 
-#endif /* __ASSEMBLY__ */
+#else /* __ASSEMBLY__ */
 
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l;})
 
 /* Macros for setting and retrieving special purpose registers */
 
@@ -461,20 +466,9 @@ GLUE(.,name):
 #define mttbl(v)	asm volatile("mttbl %0":: "r"(v))
 #define mttbu(v)	asm volatile("mttbu %0":: "r"(v))
 
-/* iSeries CTRL register (for runlatch) */
-
-#define CTRLT		0x098
-#define CTRLF		0x088
-#define RUNLATCH	0x0001
-
-/* Size of an exception stack frame contained in the paca. */
-#define EXC_FRAME_SIZE 64
-
 #define mfasr()		({unsigned long rval; \
 			asm volatile("mfasr %0" : "=r" (rval)); rval;})
 
-#ifndef __ASSEMBLY__
-
 static inline void set_tb(unsigned int upper, unsigned int lower)
 {
 	mttbl(0);
@@ -485,6 +479,8 @@ static inline void set_tb(unsigned int upper, unsigned int lower)
 #define __get_SP()	({unsigned long sp; \
 			asm volatile("mr %0,1": "=r" (sp)); sp;})
 
+#ifdef __KERNEL__
+
 extern int have_of;
 
 struct task_struct;
@@ -507,8 +503,6 @@ extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
 extern struct task_struct *last_task_used_math;
 extern struct task_struct *last_task_used_altivec;
 
-
-#ifdef __KERNEL__
 /* 64-bit user address space is 41-bits (2TBs user VM) */
 #define TASK_SIZE_USER64 (0x0000020000000000UL)
 
@@ -520,8 +514,6 @@ extern struct task_struct *last_task_used_altivec;
 
 #define TASK_SIZE (test_thread_flag(TIF_32BIT) ? \
 		TASK_SIZE_USER32 : TASK_SIZE_USER64)
-#endif /* __KERNEL__ */
-
 
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
@@ -538,6 +530,7 @@ typedef struct {
 
 struct thread_struct {
 	unsigned long	ksp;		/* Kernel stack pointer */
+	unsigned long	ksp_vsid;
 	struct pt_regs	*regs;		/* Pointer to saved register state */
 	mm_segment_t	fs;		/* for get_fs() validation */
 	double		fpr[32];	/* Complete floating point set */
@@ -559,12 +552,12 @@ struct thread_struct {
 #define INIT_SP		(sizeof(init_stack) + (unsigned long) &init_stack)
 
 #define INIT_THREAD  { \
-	INIT_SP, /* ksp */ \
-	(struct pt_regs *)INIT_SP - 1, /* regs */ \
-	KERNEL_DS, /*fs*/ \
-	{0}, /* fpr */ \
-	0, /* fpscr */ \
-	MSR_FE0|MSR_FE1, /* fpexc_mode */ \
+	.ksp = INIT_SP, \
+	.regs = (struct pt_regs *)INIT_SP - 1, \
+	.fs = KERNEL_DS, \
+	.fpr = {0}, \
+	.fpscr = 0, \
+	.fpexc_mode = MSR_FE0|MSR_FE1, \
 }
 
 /*
@@ -626,12 +619,11 @@ static inline void prefetchw(const void *x)
 
 #define spin_lock_prefetch(x)	prefetchw(x)
 
-#ifdef CONFIG_SCHED_SMT
-#define ARCH_HAS_SCHED_DOMAIN
-#define ARCH_HAS_SCHED_WAKE_IDLE
-#endif
+#define HAVE_ARCH_PICK_MMAP_LAYOUT
+
+#endif /* __KERNEL__ */
 
-#endif /* ASSEMBLY */
+#endif /* __ASSEMBLY__ */
 
 /*
  * Number of entries in the SLB. If this ever changes we should handle
diff --git a/include/asm-ppc64/prom.h b/include/asm-ppc64/prom.h
index 87db2ece0..482f9f60d 100644
--- a/include/asm-ppc64/prom.h
+++ b/include/asm-ppc64/prom.h
@@ -24,14 +24,47 @@
 #define LONG_LSW(X) (((unsigned long)X) & 0xffffffff)
 #define LONG_MSW(X) (((unsigned long)X) >> 32)
 
+/* Definitions used by the flattened device tree */
+#define OF_DT_HEADER		0xd00dfeed	/* 4: version, 4: total size */
+#define OF_DT_BEGIN_NODE	0x1		/* Start node: full name */
+#define OF_DT_END_NODE		0x2		/* End node */
+#define OF_DT_PROP		0x3		/* Property: name off, size, content */
+#define OF_DT_END		0x9
+
+#define OF_DT_VERSION		1
+
+/*
+ * This is what gets passed to the kernel by prom_init or kexec
+ *
+ * The dt struct contains the device tree structure, full pathes and
+ * property contents. The dt strings contain a separate block with just
+ * the strings for the property names, and is fully page aligned and
+ * self contained in a page, so that it can be kept around by the kernel,
+ * each property name appears only once in this page (cheap compression)
+ *
+ * the mem_rsvmap contains a map of reserved ranges of physical memory,
+ * passing it here instead of in the device-tree itself greatly simplifies
+ * the job of everybody. It's just a list of u64 pairs (base/size) that
+ * ends when size is 0
+ */
+struct boot_param_header
+{
+	u32	magic;			/* magic word OF_DT_HEADER */
+	u32	totalsize;		/* total size of DT block */
+	u32	off_dt_struct;		/* offset to structure */
+	u32	off_dt_strings;		/* offset to strings */
+	u32	off_mem_rsvmap;		/* offset to memory reserve map */
+	u32	version;		/* format version */
+	u32	last_comp_version;	/* last compatible version */
+};
+
+
+
 typedef u32 phandle;
 typedef u32 ihandle;
 typedef u32 phandle32;
 typedef u32 ihandle32;
 
-extern char *prom_display_paths[];
-extern unsigned int prom_num_displays;
-
 struct address_range {
 	unsigned long space;
 	unsigned long address;
@@ -136,6 +169,7 @@ struct property {
  */
 struct pci_controller;
 struct iommu_table;
+
 struct device_node {
 	char	*name;
 	char	*type;
@@ -171,6 +205,8 @@ struct device_node {
 	unsigned long _flags;
 };
 
+extern struct device_node *of_chosen;
+
 /* flag descriptions */
 #define OF_STALE   0 /* node is slated for deletion */
 #define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */
@@ -202,34 +238,6 @@ static void inline set_node_addr_link(struct device_node *dn, struct proc_dir_en
 	dn->addr_link = de;
 }
 
-typedef u32 prom_arg_t;
-
-struct prom_args {
-        u32 service;
-        u32 nargs;
-        u32 nret;
-        prom_arg_t args[10];
-        prom_arg_t *rets;     /* Pointer to return values in args[16]. */
-};
-
-struct prom_t {
-	unsigned long entry;
-	ihandle root;
-	ihandle chosen;
-	int cpu;
-	ihandle stdout;
-	ihandle disp_node;
-	struct prom_args args;
-	unsigned long version;
-	unsigned long encode_phys_size;
-	struct bi_record *bi_recs;
-};
-
-extern struct prom_t prom;
-extern char *of_stdout_device;
-
-extern int boot_cpuid;
-
 /* OBSOLETE: Old stlye node lookup */
 extern struct device_node *find_devices(const char *name);
 extern struct device_node *find_type_devices(const char *type);
@@ -246,6 +254,7 @@ extern struct device_node *of_find_node_by_type(struct device_node *from,
 extern struct device_node *of_find_compatible_node(struct device_node *from,
 	const char *type, const char *compat);
 extern struct device_node *of_find_node_by_path(const char *path);
+extern struct device_node *of_find_node_by_phandle(phandle handle);
 extern struct device_node *of_find_all_nodes(struct device_node *prev);
 extern struct device_node *of_get_parent(const struct device_node *node);
 extern struct device_node *of_get_next_child(const struct device_node *node,
diff --git a/include/asm-ppc64/ptrace.h b/include/asm-ppc64/ptrace.h
index 2ec5d7bc4..c96aad28f 100644
--- a/include/asm-ppc64/ptrace.h
+++ b/include/asm-ppc64/ptrace.h
@@ -60,15 +60,21 @@ struct pt_regs32 {
 	PPC_REG_32 result; 	/* Result of a system call */
 };
 
+#define instruction_pointer(regs) ((regs)->nip)
+#ifdef CONFIG_SMP
+extern unsigned long profile_pc(struct pt_regs *regs);
+#else
+#define profile_pc(regs) instruction_pointer(regs)
 #endif
 
+#endif /* __ASSEMBLY__ */
+
 #define STACK_FRAME_OVERHEAD	112	/* size of minimum stack frame */
 
 /* Size of dummy stack frame allocated when calling signal handler. */
 #define __SIGNAL_FRAMESIZE	128
 #define __SIGNAL_FRAMESIZE32	64
 
-#define instruction_pointer(regs) ((regs)->nip)
 #define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1)
 
 #define force_successful_syscall_return()   \
diff --git a/include/asm-ppc64/resource.h b/include/asm-ppc64/resource.h
index c54e9d69d..f5d6b2e8c 100644
--- a/include/asm-ppc64/resource.h
+++ b/include/asm-ppc64/resource.h
@@ -45,7 +45,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
-	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff --git a/include/asm-ppc64/rtas.h b/include/asm-ppc64/rtas.h
index d596ec5b4..414b75525 100644
--- a/include/asm-ppc64/rtas.h
+++ b/include/asm-ppc64/rtas.h
@@ -22,12 +22,13 @@
 /* Buffer size for ppc_rtas system call. */
 #define RTAS_RMOBUF_MAX (64 * 1024)
 
-/* RTAS return codes */
-#define RTAS_BUSY		-2	/* RTAS Return Status - Busy */
-#define RTAS_EXTENDED_DELAY_MIN 9900
-#define RTAS_EXTENDED_DELAY_MAX 9905
+/* RTAS return status codes */
+#define RTAS_BUSY		-2    /* RTAS Busy */
+#define RTAS_NO_SUCH_INDICATOR	-3    /* No such indicator implemented */
+#define RTAS_EXTENDED_DELAY_MIN	9900
+#define RTAS_EXTENDED_DELAY_MAX	9905
 
-#define RTAS_UNKNOWN_OP		-1099	/* Return Status - Unknown RTAS Token */
+#define RTAS_UNKNOWN_OP		-1099 /* Unknown RTAS Token */
 
 /*
  * In general to call RTAS use rtas_token("string") to lookup
@@ -65,67 +66,78 @@ struct rtas_t {
 	struct device_node *dev;	/* virtual address pointer */
 };
 
-/* Event classes */
+/* RTAS event classes */
 #define RTAS_INTERNAL_ERROR		0x80000000 /* set bit 0 */
 #define RTAS_EPOW_WARNING		0x40000000 /* set bit 1 */
 #define RTAS_POWERMGM_EVENTS		0x20000000 /* set bit 2 */
 #define RTAS_HOTPLUG_EVENTS		0x10000000 /* set bit 3 */
 #define RTAS_EVENT_SCAN_ALL_EVENTS	0xf0000000
 
-/* event-scan returns */
-#define SEVERITY_FATAL		0x5
-#define SEVERITY_ERROR		0x4
-#define SEVERITY_ERROR_SYNC	0x3
-#define SEVERITY_WARNING	0x2
-#define SEVERITY_EVENT		0x1
-#define SEVERITY_NO_ERROR	0x0
-#define DISP_FULLY_RECOVERED	0x0
-#define DISP_LIMITED_RECOVERY	0x1
-#define DISP_NOT_RECOVERED	0x2
-#define PART_PRESENT		0x0
-#define PART_NOT_PRESENT	0x1
-#define INITIATOR_UNKNOWN	0x0
-#define INITIATOR_CPU		0x1
-#define INITIATOR_PCI		0x2
-#define INITIATOR_ISA		0x3
-#define INITIATOR_MEMORY	0x4
-#define INITIATOR_POWERMGM	0x5
-#define TARGET_UNKNOWN		0x0
-#define TARGET_CPU		0x1
-#define TARGET_PCI		0x2
-#define TARGET_ISA		0x3
-#define TARGET_MEMORY		0x4
-#define TARGET_POWERMGM		0x5
-#define TYPE_RETRY		0x01
-#define TYPE_TCE_ERR		0x02
-#define TYPE_INTERN_DEV_FAIL	0x03
-#define TYPE_TIMEOUT		0x04
-#define TYPE_DATA_PARITY	0x05
-#define TYPE_ADDR_PARITY	0x06
-#define TYPE_CACHE_PARITY	0x07
-#define TYPE_ADDR_INVALID	0x08
-#define TYPE_ECC_UNCORR		0x09
-#define TYPE_ECC_CORR		0x0a
-#define TYPE_EPOW		0x40
+/* RTAS event severity */
+#define RTAS_SEVERITY_FATAL		0x5
+#define RTAS_SEVERITY_ERROR		0x4
+#define RTAS_SEVERITY_ERROR_SYNC	0x3
+#define RTAS_SEVERITY_WARNING		0x2
+#define RTAS_SEVERITY_EVENT		0x1
+#define RTAS_SEVERITY_NO_ERROR		0x0
+
+/* RTAS event disposition */
+#define RTAS_DISP_FULLY_RECOVERED	0x0
+#define RTAS_DISP_LIMITED_RECOVERY	0x1
+#define RTAS_DISP_NOT_RECOVERED		0x2
+
+/* RTAS event initiator */
+#define RTAS_INITIATOR_UNKNOWN		0x0
+#define RTAS_INITIATOR_CPU		0x1
+#define RTAS_INITIATOR_PCI		0x2
+#define RTAS_INITIATOR_ISA		0x3
+#define RTAS_INITIATOR_MEMORY		0x4
+#define RTAS_INITIATOR_POWERMGM		0x5
+
+/* RTAS event target */
+#define RTAS_TARGET_UNKNOWN		0x0
+#define RTAS_TARGET_CPU			0x1
+#define RTAS_TARGET_PCI			0x2
+#define RTAS_TARGET_ISA			0x3
+#define RTAS_TARGET_MEMORY		0x4
+#define RTAS_TARGET_POWERMGM		0x5
+
+/* RTAS event type */
+#define RTAS_TYPE_RETRY			0x01
+#define RTAS_TYPE_TCE_ERR		0x02
+#define RTAS_TYPE_INTERN_DEV_FAIL	0x03
+#define RTAS_TYPE_TIMEOUT		0x04
+#define RTAS_TYPE_DATA_PARITY		0x05
+#define RTAS_TYPE_ADDR_PARITY		0x06
+#define RTAS_TYPE_CACHE_PARITY		0x07
+#define RTAS_TYPE_ADDR_INVALID		0x08
+#define RTAS_TYPE_ECC_UNCORR		0x09
+#define RTAS_TYPE_ECC_CORR		0x0a
+#define RTAS_TYPE_EPOW			0x40
+#define RTAS_TYPE_PLATFORM		0xE0
+#define RTAS_TYPE_IO			0xE1
+#define RTAS_TYPE_INFO			0xE2
+#define RTAS_TYPE_DEALLOC		0xE3
+#define RTAS_TYPE_DUMP			0xE4
 /* I don't add PowerMGM events right now, this is a different topic */ 
-#define TYPE_PMGM_POWER_SW_ON	0x60
-#define TYPE_PMGM_POWER_SW_OFF	0x61
-#define TYPE_PMGM_LID_OPEN	0x62
-#define TYPE_PMGM_LID_CLOSE	0x63
-#define TYPE_PMGM_SLEEP_BTN	0x64
-#define TYPE_PMGM_WAKE_BTN	0x65
-#define TYPE_PMGM_BATTERY_WARN	0x66
-#define TYPE_PMGM_BATTERY_CRIT	0x67
-#define TYPE_PMGM_SWITCH_TO_BAT	0x68
-#define TYPE_PMGM_SWITCH_TO_AC	0x69
-#define TYPE_PMGM_KBD_OR_MOUSE	0x6a
-#define TYPE_PMGM_ENCLOS_OPEN	0x6b
-#define TYPE_PMGM_ENCLOS_CLOSED	0x6c
-#define TYPE_PMGM_RING_INDICATE	0x6d
-#define TYPE_PMGM_LAN_ATTENTION	0x6e
-#define TYPE_PMGM_TIME_ALARM	0x6f
-#define TYPE_PMGM_CONFIG_CHANGE	0x70
-#define TYPE_PMGM_SERVICE_PROC	0x71
+#define RTAS_TYPE_PMGM_POWER_SW_ON	0x60
+#define RTAS_TYPE_PMGM_POWER_SW_OFF	0x61
+#define RTAS_TYPE_PMGM_LID_OPEN		0x62
+#define RTAS_TYPE_PMGM_LID_CLOSE	0x63
+#define RTAS_TYPE_PMGM_SLEEP_BTN	0x64
+#define RTAS_TYPE_PMGM_WAKE_BTN		0x65
+#define RTAS_TYPE_PMGM_BATTERY_WARN	0x66
+#define RTAS_TYPE_PMGM_BATTERY_CRIT	0x67
+#define RTAS_TYPE_PMGM_SWITCH_TO_BAT	0x68
+#define RTAS_TYPE_PMGM_SWITCH_TO_AC	0x69
+#define RTAS_TYPE_PMGM_KBD_OR_MOUSE	0x6a
+#define RTAS_TYPE_PMGM_ENCLOS_OPEN	0x6b
+#define RTAS_TYPE_PMGM_ENCLOS_CLOSED	0x6c
+#define RTAS_TYPE_PMGM_RING_INDICATE	0x6d
+#define RTAS_TYPE_PMGM_LAN_ATTENTION	0x6e
+#define RTAS_TYPE_PMGM_TIME_ALARM	0x6f
+#define RTAS_TYPE_PMGM_CONFIG_CHANGE	0x70
+#define RTAS_TYPE_PMGM_SERVICE_PROC	0x71
 
 struct rtas_error_log {
 	unsigned long version:8;		/* Architectural version */
@@ -168,7 +180,7 @@ extern struct rtas_t rtas;
 extern void enter_rtas(unsigned long);
 extern int rtas_token(const char *service);
 extern int rtas_call(int token, int, int, int *, ...);
-extern void call_rtas_display_status(char);
+extern void call_rtas_display_status(unsigned char);
 extern void rtas_restart(char *cmd);
 extern void rtas_power_off(void);
 extern void rtas_halt(void);
@@ -177,6 +189,7 @@ extern int rtas_get_sensor(int sensor, int index, int *state);
 extern int rtas_get_power_level(int powerdomain, int *level);
 extern int rtas_set_power_level(int powerdomain, int level, int *setlevel);
 extern int rtas_set_indicator(int indicator, int index, int new_value);
+extern void rtas_initialize(void);
 
 /* Given an RTAS status code of 9900..9905 compute the hinted delay */
 unsigned int rtas_extended_busy_delay_time(int status);
@@ -199,8 +212,14 @@ extern void pSeries_log_error(char *buf, unsigned int err_type, int fatal);
 #define RTAS_DEBUG KERN_DEBUG "RTAS: "
  
 #define RTAS_ERROR_LOG_MAX 2048
- 
- 
+
+/*
+ * Return the firmware-specified size of the error log buffer
+ *  for all rtas calls that require an error buffer argument.
+ *  This includes 'check-exception' and 'rtas-last-error'.
+ */
+extern int rtas_get_error_log_max(void);
+
 /* Event Scan Parameters */
 #define EVENT_SCAN_ALL_EVENTS	0xf0000000
 #define SURVEILLANCE_TOKEN	9000
diff --git a/include/asm-ppc64/semaphore.h b/include/asm-ppc64/semaphore.h
index 22dfee71d..aefe7753e 100644
--- a/include/asm-ppc64/semaphore.h
+++ b/include/asm-ppc64/semaphore.h
@@ -23,22 +23,13 @@ struct semaphore {
 	 */
 	atomic_t count;
 	wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name, count) \
-	{ ATOMIC_INIT(count), \
-	  __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	  __SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name, 1)
@@ -53,9 +44,6 @@ static inline void sema_init (struct semaphore *sem, int val)
 {
 	atomic_set(&sem->count, val);
 	init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -74,9 +62,6 @@ extern void __up(struct semaphore * sem);
 
 static inline void down(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	/*
@@ -90,9 +75,6 @@ static inline int down_interruptible(struct semaphore * sem)
 {
 	int ret = 0;
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	if (unlikely(atomic_dec_return(&sem->count) < 0))
@@ -102,19 +84,11 @@ static inline int down_interruptible(struct semaphore * sem)
 
 static inline int down_trylock(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	return atomic_dec_if_positive(&sem->count) < 0;
 }
 
 static inline void up(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	if (unlikely(atomic_inc_return(&sem->count) <= 0))
 		__up(sem);
 }
diff --git a/include/asm-ppc64/smp.h b/include/asm-ppc64/smp.h
index 139e88e50..b5573ab36 100644
--- a/include/asm-ppc64/smp.h
+++ b/include/asm-ppc64/smp.h
@@ -26,6 +26,8 @@
 
 #include <asm/paca.h>
 
+extern int boot_cpuid;
+
 #ifdef CONFIG_SMP
 
 extern void smp_send_debugger_break(int cpu);
@@ -36,22 +38,7 @@ extern void smp_message_recv(int, struct pt_regs *);
 #define smp_processor_id() (get_paca()->paca_index)
 #define hard_smp_processor_id() (get_paca()->hw_cpu_id)
 
-/*
- * Retrieve the state of a CPU:
- * online:          CPU is in a normal run state
- * possible:        CPU is a candidate to be made online
- * available:       CPU is candidate for the 'possible' pool
- *                  Used to get SMT threads started at boot time.
- * present_at_boot: CPU was available at boot time.  Used in DLPAR
- *                  code to handle special cases for processor start up.
- */
-extern cpumask_t cpu_present_at_boot;
-extern cpumask_t cpu_online_map;
-extern cpumask_t cpu_possible_map;
-extern cpumask_t cpu_available_map;
-
-#define cpu_present_at_boot(cpu) cpu_isset(cpu, cpu_present_at_boot)
-#define cpu_available(cpu)       cpu_isset(cpu, cpu_available_map) 
+extern cpumask_t cpu_sibling_map[NR_CPUS];
 
 /* Since OpenPIC has only 4 IPIs, we use slightly different message numbers.
  *
@@ -73,11 +60,14 @@ void smp_init_pSeries(void);
 extern int __cpu_disable(void);
 extern void __cpu_die(unsigned int cpu);
 extern void cpu_die(void) __attribute__((noreturn));
+extern int query_cpu_stopped(unsigned int pcpu);
 #endif /* !(CONFIG_SMP) */
 
 #define get_hard_smp_processor_id(CPU) (paca[(CPU)].hw_cpu_id)
 #define set_hard_smp_processor_id(CPU, VAL) \
-	do { (paca[(CPU)].hw_proc_num = (VAL)); } while (0)
+	do { (paca[(CPU)].hw_cpu_id = (VAL)); } while (0)
+
+extern int smt_enabled_at_boot;
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/include/asm-ppc64/socket.h b/include/asm-ppc64/socket.h
index 1021a5268..59e00dfc8 100644
--- a/include/asm-ppc64/socket.h
+++ b/include/asm-ppc64/socket.h
@@ -54,20 +54,4 @@
 
 #define SO_PEERSEC             31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-ppc64/spinlock.h b/include/asm-ppc64/spinlock.h
index d2074c44f..45a6f7545 100644
--- a/include/asm-ppc64/spinlock.h
+++ b/include/asm-ppc64/spinlock.h
@@ -6,6 +6,8 @@
  *
  * Copyright (C) 2001-2004 Paul Mackerras <paulus@au.ibm.com>, IBM
  * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
+ * Copyright (C) 2002 Dave Engebretsen <engebret@us.ibm.com>, IBM
+ *	Rework to support virtual processors
  *
  * Type of int is used as a full 64b word is not necessary.
  *
@@ -16,11 +18,17 @@
  */
 #include <linux/config.h>
 #include <asm/paca.h>
+#include <asm/hvcall.h>
+#include <asm/iSeries/HvCall.h>
 
 typedef struct {
 	volatile unsigned int lock;
 } spinlock_t;
 
+typedef struct {
+	volatile signed int lock;
+} rwlock_t;
+
 #ifdef __KERNEL__
 #define SPIN_LOCK_UNLOCKED	(spinlock_t) { 0 }
 
@@ -34,101 +42,91 @@ static __inline__ void _raw_spin_unlock(spinlock_t *lock)
 }
 
 /*
- * Normally we use the spinlock functions in arch/ppc64/lib/locks.c.
- * For special applications such as profiling, we can have the
- * spinlock functions inline by defining CONFIG_SPINLINE.
- * This is not recommended on partitioned systems with shared
- * processors, since the inline spinlock functions don't include
- * the code for yielding the CPU to the lock holder.
+ * On a system with shared processors (that is, where a physical
+ * processor is multiplexed between several virtual processors),
+ * there is no point spinning on a lock if the holder of the lock
+ * isn't currently scheduled on a physical processor.  Instead
+ * we detect this situation and ask the hypervisor to give the
+ * rest of our timeslice to the lock holder.
+ *
+ * So that we can tell which virtual processor is holding a lock,
+ * we put 0x80000000 | smp_processor_id() in the lock when it is
+ * held.  Conveniently, we have a word in the paca that holds this
+ * value.
  */
 
-#ifndef CONFIG_SPINLINE
-extern int _raw_spin_trylock(spinlock_t *lock);
-extern void _raw_spin_lock(spinlock_t *lock);
-extern void _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags);
+#if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES)
+/* We only yield to the hypervisor if we are in shared processor mode */
+#define SHARED_PROCESSOR (get_paca()->lppaca.xSharedProc)
+extern void __spin_yield(spinlock_t *lock);
+extern void __rw_yield(rwlock_t *lock);
+#else /* SPLPAR || ISERIES */
+#define __spin_yield(x)	barrier()
+#define __rw_yield(x)	barrier()
+#define SHARED_PROCESSOR	0
+#endif
 extern void spin_unlock_wait(spinlock_t *lock);
 
-#else
-
-static __inline__ int _raw_spin_trylock(spinlock_t *lock)
+/*
+ * This returns the old value in the lock, so we succeeded
+ * in getting the lock if the return value is 0.
+ */
+static __inline__ unsigned long __spin_trylock(spinlock_t *lock)
 {
-	unsigned int tmp, tmp2;
+	unsigned long tmp, tmp2;
 
 	__asm__ __volatile__(
-"1:	lwarx		%0,0,%2		# spin_trylock\n\
+"	lwz		%1,%3(13)		# __spin_trylock\n\
+1:	lwarx		%0,0,%2\n\
 	cmpwi		0,%0,0\n\
 	bne-		2f\n\
-	lwz		%1,%3(13)\n\
 	stwcx.		%1,0,%2\n\
 	bne-		1b\n\
 	isync\n\
-2:"	: "=&r"(tmp), "=&r"(tmp2)
-	: "r"(&lock->lock), "i"(offsetof(struct paca_struct, lock_token))
+2:"	: "=&r" (tmp), "=&r" (tmp2)
+	: "r" (&lock->lock), "i" (offsetof(struct paca_struct, lock_token))
 	: "cr0", "memory");
 
-	return tmp == 0;
+	return tmp;
 }
 
-static __inline__ void _raw_spin_lock(spinlock_t *lock)
+static int __inline__ _raw_spin_trylock(spinlock_t *lock)
 {
-	unsigned int tmp;
-
-	__asm__ __volatile__(
-	"b		2f		# spin_lock\n\
-1:"
-	HMT_LOW
-"	lwzx		%0,0,%1\n\
-	cmpwi		0,%0,0\n\
-	bne+		1b\n"
-	HMT_MEDIUM
-"2:	lwarx		%0,0,%1\n\
-	cmpwi		0,%0,0\n\
-	bne-		1b\n\
-	lwz		%0,%2(13)\n\
-	stwcx.		%0,0,%1\n\
-	bne-		2b\n\
-	isync"
-	: "=&r"(tmp)
-	: "r"(&lock->lock), "i"(offsetof(struct paca_struct, lock_token))
-	: "cr0", "memory");
+	return __spin_trylock(lock) == 0;
 }
 
-/*
- * Note: if we ever want to inline the spinlocks on iSeries,
- * we will have to change the irq enable/disable stuff in here.
- */
-static __inline__ void _raw_spin_lock_flags(spinlock_t *lock,
-					    unsigned long flags)
+static void __inline__ _raw_spin_lock(spinlock_t *lock)
 {
-	unsigned int tmp;
-	unsigned long tmp2;
-
-	__asm__ __volatile__(
-	"b		3f		# spin_lock\n\
-1:	mfmsr		%1\n\
-	mtmsrd		%3,1\n\
-2:"	HMT_LOW
-"	lwzx		%0,0,%2\n\
-	cmpwi		0,%0,0\n\
-	bne+		2b\n"
-	HMT_MEDIUM
-"	mtmsrd		%1,1\n\
-3:	lwarx		%0,0,%2\n\
-	cmpwi		0,%0,0\n\
-	bne-		1b\n\
-	lwz		%1,%4(13)\n\
-	stwcx.		%1,0,%2\n\
-	bne-		3b\n\
-	isync"
-	: "=&r"(tmp), "=&r"(tmp2)
-	: "r"(&lock->lock), "r"(flags),
-	  "i" (offsetof(struct paca_struct, lock_token))
-	: "cr0", "memory");
+	while (1) {
+		if (likely(__spin_trylock(lock) == 0))
+			break;
+		do {
+			HMT_low();
+			if (SHARED_PROCESSOR)
+				__spin_yield(lock);
+		} while (likely(lock->lock != 0));
+		HMT_medium();
+	}
 }
 
-#define spin_unlock_wait(x)	do { cpu_relax(); } while (spin_is_locked(x))
-
-#endif /* CONFIG_SPINLINE */
+static void __inline__ _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags)
+{
+	unsigned long flags_dis;
+
+	while (1) {
+		if (likely(__spin_trylock(lock) == 0))
+			break;
+		local_save_flags(flags_dis);
+		local_irq_restore(flags);
+		do {
+			HMT_low();
+			if (SHARED_PROCESSOR)
+				__spin_yield(lock);
+		} while (likely(lock->lock != 0));
+		HMT_medium();
+		local_irq_restore(flags_dis);
+	}
+}
 
 /*
  * Read-write spinlocks, allowing multiple readers
@@ -140,10 +138,6 @@ static __inline__ void _raw_spin_lock_flags(spinlock_t *lock,
  * irq-safe write-lock, but readers can get non-irqsafe
  * read-locks.
  */
-typedef struct {
-	volatile signed int lock;
-} rwlock_t;
-
 #define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
 
 #define rwlock_init(x)		do { *(x) = RW_LOCK_UNLOCKED; } while(0)
@@ -165,67 +159,54 @@ static __inline__ void _raw_write_unlock(rwlock_t *rw)
 	rw->lock = 0;
 }
 
-#ifndef CONFIG_SPINLINE
-extern int _raw_read_trylock(rwlock_t *rw);
-extern void _raw_read_lock(rwlock_t *rw);
-extern void _raw_read_unlock(rwlock_t *rw);
-extern int _raw_write_trylock(rwlock_t *rw);
-extern void _raw_write_lock(rwlock_t *rw);
-extern void _raw_write_unlock(rwlock_t *rw);
-
-#else
-static __inline__ int _raw_read_trylock(rwlock_t *rw)
+/*
+ * This returns the old value in the lock + 1,
+ * so we got a read lock if the return value is > 0.
+ */
+static long __inline__ __read_trylock(rwlock_t *rw)
 {
-	unsigned int tmp;
-	unsigned int ret;
+	long tmp;
 
 	__asm__ __volatile__(
-"1:	lwarx		%0,0,%2		# read_trylock\n\
-	li		%1,0\n\
+"1:	lwarx		%0,0,%1		# read_trylock\n\
 	extsw		%0,%0\n\
 	addic.		%0,%0,1\n\
 	ble-		2f\n\
-	stwcx.		%0,0,%2\n\
+	stwcx.		%0,0,%1\n\
 	bne-		1b\n\
-	li		%1,1\n\
 	isync\n\
-2:"	: "=&r"(tmp), "=&r"(ret)
-	: "r"(&rw->lock)
-	: "cr0", "memory");
+2:"	: "=&r" (tmp)
+	: "r" (&rw->lock)
+	: "cr0", "xer", "memory");
 
-	return ret;
+	return tmp;
 }
 
-static __inline__ void _raw_read_lock(rwlock_t *rw)
+static int __inline__ _raw_read_trylock(rwlock_t *rw)
 {
-	unsigned int tmp;
+	return __read_trylock(rw) > 0;
+}
 
-	__asm__ __volatile__(
-	"b		2f		# read_lock\n\
-1:"
-	HMT_LOW
-"	lwax		%0,0,%1\n\
-	cmpwi		0,%0,0\n\
-	blt+		1b\n"
-	HMT_MEDIUM
-"2:	lwarx		%0,0,%1\n\
-	extsw		%0,%0\n\
-	addic.		%0,%0,1\n\
-	ble-		1b\n\
-	stwcx.		%0,0,%1\n\
-	bne-		2b\n\
-	isync"
-	: "=&r"(tmp)
-	: "r"(&rw->lock)
-	: "cr0", "memory");
+static void __inline__ _raw_read_lock(rwlock_t *rw)
+{
+	while (1) {
+		if (likely(__read_trylock(rw) > 0))
+			break;
+		do {
+			HMT_low();
+			if (SHARED_PROCESSOR)
+				__rw_yield(rw);
+		} while (likely(rw->lock < 0));
+		HMT_medium();
+	}
 }
 
-static __inline__ void _raw_read_unlock(rwlock_t *rw)
+static void __inline__ _raw_read_unlock(rwlock_t *rw)
 {
-	unsigned int tmp;
+	long tmp;
 
 	__asm__ __volatile__(
-	"lwsync				# read_unlock\n\
+	"eieio				# read_unlock\n\
 1:	lwarx		%0,0,%1\n\
 	addic		%0,%0,-1\n\
 	stwcx.		%0,0,%1\n\
@@ -235,50 +216,47 @@ static __inline__ void _raw_read_unlock(rwlock_t *rw)
 	: "cr0", "memory");
 }
 
-static __inline__ int _raw_write_trylock(rwlock_t *rw)
+/*
+ * This returns the old value in the lock,
+ * so we got the write lock if the return value is 0.
+ */
+static __inline__ long __write_trylock(rwlock_t *rw)
 {
-	unsigned int tmp;
-	unsigned int ret;
+	long tmp, tmp2;
 
 	__asm__ __volatile__(
-"1:	lwarx		%0,0,%2		# write_trylock\n\
+"	lwz		%1,%3(13)	# write_trylock\n\
+1:	lwarx		%0,0,%2\n\
 	cmpwi		0,%0,0\n\
-	li		%1,0\n\
 	bne-		2f\n\
-	stwcx.		%3,0,%2\n\
+	stwcx.		%1,0,%2\n\
 	bne-		1b\n\
-	li		%1,1\n\
 	isync\n\
-2:"	: "=&r"(tmp), "=&r"(ret)
-	: "r"(&rw->lock), "r"(-1)
+2:"	: "=&r" (tmp), "=&r" (tmp2)
+	: "r" (&rw->lock), "i" (offsetof(struct paca_struct, lock_token))
 	: "cr0", "memory");
 
-	return ret;
+	return tmp;
 }
 
-static __inline__ void _raw_write_lock(rwlock_t *rw)
+static int __inline__ _raw_write_trylock(rwlock_t *rw)
 {
-	unsigned int tmp;
+	return __write_trylock(rw) == 0;
+}
 
-	__asm__ __volatile__(
-	"b		2f		# write_lock\n\
-1:"
-	HMT_LOW
-	"lwax		%0,0,%1\n\
-	cmpwi		0,%0,0\n\
-	bne+		1b\n"
-	HMT_MEDIUM
-"2:	lwarx		%0,0,%1\n\
-	cmpwi		0,%0,0\n\
-	bne-		1b\n\
-	stwcx.		%2,0,%1\n\
-	bne-		2b\n\
-	isync"
-	: "=&r"(tmp)
-	: "r"(&rw->lock), "r"(-1)
-	: "cr0", "memory");
+static void __inline__ _raw_write_lock(rwlock_t *rw)
+{
+	while (1) {
+		if (likely(__write_trylock(rw) == 0))
+			break;
+		do {
+			HMT_low();
+			if (SHARED_PROCESSOR)
+				__rw_yield(rw);
+		} while (likely(rw->lock != 0));
+		HMT_medium();
+	}
 }
-#endif /* CONFIG_SPINLINE */
 
 #endif /* __KERNEL__ */
 #endif /* __ASM_SPINLOCK_H */
diff --git a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h
index 276bfa813..dc3153fa4 100644
--- a/include/asm-ppc64/system.h
+++ b/include/asm-ppc64/system.h
@@ -105,6 +105,7 @@ extern int fix_alignment(struct pt_regs *regs);
 extern void bad_page_fault(struct pt_regs *regs, unsigned long address,
 			   int sig);
 extern void show_regs(struct pt_regs * regs);
+extern void low_hash_fault(struct pt_regs *regs, unsigned long address);
 extern int die(const char *str, struct pt_regs *regs, long err);
 
 extern void flush_instruction_cache(void);
@@ -128,6 +129,8 @@ static inline void flush_altivec_to_thread(struct task_struct *t)
 }
 #endif
 
+extern int mem_init_done;	/* set on boot once kmalloc can be called */
+
 /* EBCDIC -> ASCII conversion for [0-9A-Z] on iSeries */
 extern unsigned char e2a(unsigned char);
 
diff --git a/include/asm-ppc64/systemcfg.h b/include/asm-ppc64/systemcfg.h
index 7cefeef2b..b7d6e0f34 100644
--- a/include/asm-ppc64/systemcfg.h
+++ b/include/asm-ppc64/systemcfg.h
@@ -59,54 +59,7 @@ struct systemcfg {
 
 #ifdef __KERNEL__
 extern struct systemcfg *systemcfg;
-#else
-
-/* Processor Version Register (PVR) field extraction */
-#define PVR_VER(pvr)  (((pvr) >>  16) & 0xFFFF) /* Version field */
-#define PVR_REV(pvr)  (((pvr) >>   0) & 0xFFFF) /* Revison field */
-
-/* Processor Version Numbers */
-#define PV_NORTHSTAR    0x0033
-#define PV_PULSAR       0x0034
-#define PV_POWER4       0x0035
-#define PV_ICESTAR      0x0036
-#define PV_SSTAR        0x0037
-#define PV_POWER4p      0x0038
-#define PV_GPUL		0x0039
-#define PV_POWER5	0x003a
-#define PV_970FX	0x003c
-#define PV_630          0x0040
-#define PV_630p         0x0041
-
-/* Platforms supported by PPC64 */
-#define PLATFORM_PSERIES      0x0100
-#define PLATFORM_PSERIES_LPAR 0x0101
-#define PLATFORM_ISERIES_LPAR 0x0201
-#define PLATFORM_POWERMAC     0x0400
-
-/* Compatibility with drivers coming from PPC32 world */
-#define _machine	(systemcfg->platform)
-#define _MACH_Pmac	PLATFORM_POWERMAC
-
-
-static inline volatile struct systemcfg *systemcfg_init(void)
-{
-	int fd = open("/proc/ppc64/systemcfg", O_RDONLY);
-	volatile struct systemcfg *ret;
-
-	if (fd == -1)
-		return 0;
-	ret = mmap(0, sizeof(struct systemcfg), PROT_READ, MAP_SHARED, fd, 0);
-	close(fd);
-	if (!ret)
-		return 0;
-	if (ret->version.major != SYSTEMCFG_MAJOR || ret->version.minor < SYSTEMCFG_MINOR) {
-		munmap((void *)ret, sizeof(struct systemcfg));
-		return 0;
-	}
-	return ret;
-}
-#endif /* __KERNEL__ */
+#endif
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/include/asm-ppc64/tlb.h b/include/asm-ppc64/tlb.h
index 6fafb87dc..97cb696ce 100644
--- a/include/asm-ppc64/tlb.h
+++ b/include/asm-ppc64/tlb.h
@@ -15,7 +15,14 @@
 #include <asm/tlbflush.h>
 
 struct mmu_gather;
-static inline void tlb_flush(struct mmu_gather *tlb);
+
+extern void pte_free_finish(void);
+
+static inline void tlb_flush(struct mmu_gather *tlb)
+{
+	flush_tlb_pending();
+	pte_free_finish();
+}
 
 /* Avoid pulling in another include just for this */
 #define check_pgt_cache()	do { } while (0)
@@ -29,12 +36,4 @@ static inline void tlb_flush(struct mmu_gather *tlb);
 
 #define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0)
 
-extern void pte_free_finish(void);
-
-static inline void tlb_flush(struct mmu_gather *tlb)
-{
-	flush_tlb_pending();
-	pte_free_finish();
-}
-
 #endif /* _PPC64_TLB_H */
diff --git a/include/asm-ppc64/uaccess.h b/include/asm-ppc64/uaccess.h
index 77906c935..58eec5324 100644
--- a/include/asm-ppc64/uaccess.h
+++ b/include/asm-ppc64/uaccess.h
@@ -111,6 +111,9 @@ extern unsigned long search_exception_table(unsigned long);
 #define __put_user(x,ptr) \
   __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 
+#define __get_user_unaligned __get_user
+#define __put_user_unaligned __put_user
+
 extern long __put_user_bad(void);
 
 #define __put_user_nocheck(x,ptr,size)				\
@@ -281,6 +284,9 @@ extern unsigned long copy_in_user(void __user *to, const void __user *from,
 
 extern unsigned long __clear_user(void __user *addr, unsigned long size);
 
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
 static inline unsigned long
 clear_user(void __user *addr, unsigned long size)
 {
diff --git a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h
index 414c0373c..588f48acb 100644
--- a/include/asm-ppc64/unistd.h
+++ b/include/asm-ppc64/unistd.h
@@ -269,9 +269,9 @@
 /* Number 256 is reserved for sys_debug_setcontext */
 #define __NR_vserver		257
 /* Number 258 is reserved for new sys_remap_file_pages */
-/* Number 259 is reserved for new sys_mbind */
-/* Number 260 is reserved for new sys_get_mempolicy */
-/* Number 261 is reserved for new sys_set_mempolicy */
+#define __NR_mbind		259
+#define __NR_get_mempolicy	260
+#define __NR_set_mempolicy	261
 #define __NR_mq_open		262
 #define __NR_mq_unlink		263
 #define __NR_mq_timedsend	264
diff --git a/include/asm-s390/bug.h b/include/asm-s390/bug.h
index d59639386..2b8d6d4df 100644
--- a/include/asm-s390/bug.h
+++ b/include/asm-s390/bug.h
@@ -6,22 +6,9 @@
 #define BUG() do { \
         printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
         __asm__ __volatile__(".long 0"); \
-} while (0)                                       
-
-#define BUG_ON(condition) do { \
-	if (unlikely((condition)!=0)) \
-		BUG(); \
-} while(0)
-
-#define PAGE_BUG(page) do { \
-        BUG(); \
-} while (0)                      
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
 } while (0)
 
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
+
 #endif
diff --git a/include/asm-s390/dma-mapping.h b/include/asm-s390/dma-mapping.h
index 87edaa953..09bb7b04f 100644
--- a/include/asm-s390/dma-mapping.h
+++ b/include/asm-s390/dma-mapping.h
@@ -9,17 +9,6 @@
 #ifndef _ASM_DMA_MAPPING_H
 #define _ASM_DMA_MAPPING_H
 
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-			 dma_addr_t *dma_handle, int flag)
-{
-	BUG();
-	return 0;
-}
-
-static inline void dma_free_coherent(struct device *dev, size_t size,
-		       void *vaddr, dma_addr_t dma_handle)
-{
-	BUG();
-}
+#include <asm-generic/dma-mapping-broken.h>
 
 #endif /* _ASM_DMA_MAPPING_H */
diff --git a/include/asm-s390/hardirq.h b/include/asm-s390/hardirq.h
index 1092143b8..363b0a897 100644
--- a/include/asm-s390/hardirq.h
+++ b/include/asm-s390/hardirq.h
@@ -61,57 +61,20 @@ softirq_pending(unsigned int cpu)
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
+extern void account_ticks(struct pt_regs *);
 
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
+#define __ARCH_HAS_DO_SOFTIRQ
 
 #define irq_enter()							\
 do {									\
 	(preempt_count() += HARDIRQ_OFFSET);				\
 } while(0)
-	
-
-extern void do_call_softirq(void);
-extern void account_ticks(struct pt_regs *);
-
-#define invoke_softirq() do_call_softirq()
-
-#ifdef CONFIG_PREEMPT
-# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #define irq_exit()							\
 do {									\
 	preempt_count() -= IRQ_EXIT_OFFSET;				\
 	if (!in_interrupt() && local_softirq_pending())			\
 		/* Use the async. stack for softirq */			\
-		do_call_softirq();					\
+		do_softirq();						\
 	preempt_enable_no_resched();					\
 } while (0)
 
diff --git a/include/asm-s390/idals.h b/include/asm-s390/idals.h
index 8f72c9b1c..8038858b8 100644
--- a/include/asm-s390/idals.h
+++ b/include/asm-s390/idals.h
@@ -35,7 +35,7 @@ static inline int
 idal_is_needed(void *vaddr, unsigned int length)
 {
 #ifdef __s390x__
-	return ((__pa(vaddr) + length) >> 31) != 0;
+	return ((__pa(vaddr) + length - 1) >> 31) != 0;
 #else
 	return 0;
 #endif
diff --git a/include/asm-s390/irq.h b/include/asm-s390/irq.h
index cac6b3080..916a1aa0b 100644
--- a/include/asm-s390/irq.h
+++ b/include/asm-s390/irq.h
@@ -2,7 +2,7 @@
 #define _ASM_IRQ_H
 
 #ifdef __KERNEL__
-#include <asm/hardirq.h>
+#include <linux/hardirq.h>
 
 /*
  * the definition of irqs has changed in 2.5.46:
diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h
index 1430f4dba..0aa1c0f1e 100644
--- a/include/asm-s390/lowcore.h
+++ b/include/asm-s390/lowcore.h
@@ -68,6 +68,7 @@
 #define __LC_ASYNC_STACK                0xC48
 #define __LC_KERNEL_ASCE		0xC4C
 #define __LC_USER_ASCE			0xC50
+#define __LC_PANIC_STACK                0xC54
 #define __LC_CPUID                      0xC60
 #define __LC_CPUADDR                    0xC68
 #define __LC_IPLDEV                     0xC7C
@@ -80,6 +81,7 @@
 #define __LC_ASYNC_STACK                0xD50
 #define __LC_KERNEL_ASCE		0xD58
 #define __LC_USER_ASCE			0xD60
+#define __LC_PANIC_STACK                0xD68
 #define __LC_CPUID                      0xD90
 #define __LC_CPUADDR                    0xD98
 #define __LC_IPLDEV                     0xDB8
@@ -176,7 +178,8 @@ struct _lowcore
 	__u32        async_stack;              /* 0xc48 */
 	__u32        kernel_asce;              /* 0xc4c */
 	__u32        user_asce;                /* 0xc50 */
-	__u8         pad10[0xc60-0xc54];       /* 0xc54 */
+	__u32        panic_stack;              /* 0xc54 */
+	__u8         pad10[0xc60-0xc58];       /* 0xc58 */
 	/* entry.S sensitive area start */
 	struct       cpuinfo_S390 cpu_data;    /* 0xc60 */
 	__u32        ipl_device;               /* 0xc7c */
@@ -257,7 +260,8 @@ struct _lowcore
 	__u64        async_stack;              /* 0xd50 */
 	__u64        kernel_asce;              /* 0xd58 */
 	__u64        user_asce;                /* 0xd60 */
-	__u8         pad10[0xd80-0xd68];       /* 0xd68 */
+	__u64        panic_stack;              /* 0xd68 */
+	__u8         pad10[0xd80-0xd70];       /* 0xd70 */
 	/* entry.S sensitive area start */
 	struct       cpuinfo_S390 cpu_data;    /* 0xd80 */
 	__u32        ipl_device;               /* 0xdb8 */
diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h
index 6bed8d919..88d73375b 100644
--- a/include/asm-s390/page.h
+++ b/include/asm-s390/page.h
@@ -162,6 +162,25 @@ typedef struct { unsigned long pgd; } pgd_t;
 #define __pgd(x)        ((pgd_t) { (x) } )
 #define __pgprot(x)     ((pgprot_t) { (x) } )
 
+/* default storage key used for all pages */
+extern unsigned int default_storage_key;
+
+static inline void
+page_set_storage_key(unsigned long addr, unsigned int skey)
+{
+	asm volatile ( "sske %0,%1" : : "d" (skey), "a" (addr) );
+}
+
+static inline unsigned int
+page_get_storage_key(unsigned long addr)
+{
+	unsigned int skey;
+
+	asm volatile ( "iske %0,%1" : "=d" (skey) : "a" (addr), "0" (0) );
+
+	return skey;
+}
+
 #endif /* !__ASSEMBLY__ */
 
 /* to align the pointer to the (next) page boundary */
diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
index 05ac76fd3..c74a47e90 100644
--- a/include/asm-s390/pgtable.h
+++ b/include/asm-s390/pgtable.h
@@ -597,17 +597,13 @@ ptep_establish(struct vm_area_struct *vma,
  * should therefore only be called if it is not mapped in any
  * address space.
  */
-#define page_test_and_clear_dirty(page)					  \
+#define page_test_and_clear_dirty(_page)				  \
 ({									  \
-	struct page *__page = (page);					  \
+	struct page *__page = (_page);					  \
 	unsigned long __physpage = __pa((__page-mem_map) << PAGE_SHIFT);  \
-	int __skey;							  \
-	asm volatile ("iske %0,%1" : "=d" (__skey) : "a" (__physpage));   \
-	if (__skey & _PAGE_CHANGED) {					  \
-		asm volatile ("sske %0,%1"				  \
-			      : : "d" (__skey & ~_PAGE_CHANGED),	  \
-			          "a" (__physpage));			  \
-	}								  \
+	int __skey = page_get_storage_key(__physpage);			  \
+	if (__skey & _PAGE_CHANGED)					  \
+		page_set_storage_key(__physpage, __skey & ~_PAGE_CHANGED);\
 	(__skey & _PAGE_CHANGED);					  \
 })
 
@@ -655,11 +651,10 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
 })
 
 #define SetPageUptodate(_page) \
-	do {								  \
-		struct page *__page = (_page);				  \
-		if (!test_and_set_bit(PG_uptodate, &__page->flags))	  \
-			asm volatile ("sske %0,%1" : : "d" (0),		  \
-			      "a" (__pa((__page-mem_map) << PAGE_SHIFT)));\
+	do {								      \
+		struct page *__page = (_page);				      \
+		if (!test_and_set_bit(PG_uptodate, &__page->flags))	      \
+			page_test_and_clear_dirty(_page);		      \
 	} while (0)
 
 #ifdef __s390x__
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
index 4c9d60702..cbbd11471 100644
--- a/include/asm-s390/processor.h
+++ b/include/asm-s390/processor.h
@@ -76,6 +76,8 @@ extern struct task_struct *last_task_used_math;
 
 #define MM_VM_SIZE(mm)		DEFAULT_TASK_SIZE
 
+#define HAVE_ARCH_PICK_MMAP_LAYOUT
+
 typedef struct {
         __u32 ar4;
 } mm_segment_t;
@@ -101,6 +103,25 @@ struct thread_struct {
 
 typedef struct thread_struct thread_struct;
 
+/*
+ * Stack layout of a C stack frame.
+ */
+#ifndef __PACK_STACK
+struct stack_frame {
+	unsigned long back_chain;
+	unsigned long empty1[5];
+	unsigned long gprs[10];
+	unsigned int  empty2[8];
+};
+#else
+struct stack_frame {
+	unsigned long empty1[5];
+	unsigned int  empty2[8];
+	unsigned long gprs[10];
+	unsigned long back_chain;
+};
+#endif
+
 #define ARCH_MIN_TASKALIGN	8
 
 #ifndef __s390x__
diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h
index fe6e1e311..1dc80666e 100644
--- a/include/asm-s390/ptrace.h
+++ b/include/asm-s390/ptrace.h
@@ -466,6 +466,7 @@ struct user_regs_struct
 #ifdef __KERNEL__
 #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
 #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs * regs);
 #endif
 
diff --git a/include/asm-s390/resource.h b/include/asm-s390/resource.h
index 5f0f2ba95..05720dbdf 100644
--- a/include/asm-s390/resource.h
+++ b/include/asm-s390/resource.h
@@ -47,7 +47,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{ INR_OPEN, INR_OPEN },                         \
-	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff --git a/include/asm-s390/socket.h b/include/asm-s390/socket.h
index 1855ec7a1..0e96eeca4 100644
--- a/include/asm-s390/socket.h
+++ b/include/asm-s390/socket.h
@@ -55,20 +55,4 @@
 
 #define SO_PEERSEC		31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-s390/thread_info.h b/include/asm-s390/thread_info.h
index b4b2d323d..45f43bda1 100644
--- a/include/asm-s390/thread_info.h
+++ b/include/asm-s390/thread_info.h
@@ -11,6 +11,30 @@
 
 #ifdef __KERNEL__
 
+/*
+ * Size of kernel stack for each process
+ */
+#ifndef __s390x__
+#ifndef __SMALL_STACK
+#define THREAD_ORDER 1
+#define ASYNC_ORDER  1
+#else
+#define THREAD_ORDER 0
+#define ASYNC_ORDER  0
+#endif
+#else /* __s390x__ */
+#ifndef __SMALL_STACK
+#define THREAD_ORDER 2
+#define ASYNC_ORDER  2
+#else
+#define THREAD_ORDER 1
+#define ASYNC_ORDER  1
+#endif
+#endif /* __s390x__ */
+
+#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
+#define ASYNC_SIZE  (PAGE_SIZE << ASYNC_ORDER)
+
 #ifndef __ASSEMBLY__
 #include <asm/processor.h>
 #include <asm/lowcore.h>
@@ -47,20 +71,6 @@ struct thread_info {
 #define init_thread_info	(init_thread_union.thread_info)
 #define init_stack		(init_thread_union.stack)
 
-/*
- * Size of kernel stack for each process
- */
-#ifndef __s390x__
-#define THREAD_ORDER 1
-#define ASYNC_ORDER  1
-#else /* __s390x__ */
-#define THREAD_ORDER 2
-#define ASYNC_ORDER  2
-#endif /* __s390x__ */
-
-#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
-#define ASYNC_SIZE  (PAGE_SIZE << ASYNC_ORDER)
-
 /* how to get the thread information struct from C */
 static inline struct thread_info *current_thread_info(void)
 {
diff --git a/include/asm-s390/timer.h b/include/asm-s390/timer.h
index bb49c6999..454d1ea85 100644
--- a/include/asm-s390/timer.h
+++ b/include/asm-s390/timer.h
@@ -45,6 +45,4 @@ extern void add_virt_timer_periodic(void *new);
 extern int mod_virt_timer(struct vtimer_list *timer, __u64 expires);
 extern int del_virt_timer(struct vtimer_list *timer);
 
-int stop_timers(void);
-
 #endif
diff --git a/include/asm-s390/uaccess.h b/include/asm-s390/uaccess.h
index bec57b750..5eda2c334 100644
--- a/include/asm-s390/uaccess.h
+++ b/include/asm-s390/uaccess.h
@@ -250,6 +250,9 @@ extern int __put_user_bad(void);
 
 extern int __get_user_bad(void);
 
+#define __put_user_unaligned __put_user
+#define __get_user_unaligned __get_user
+
 extern long __copy_to_user_asm(const void *from, long n, void __user *to);
 
 /**
@@ -272,6 +275,9 @@ __copy_to_user(void __user *to, const void *from, unsigned long n)
 	return __copy_to_user_asm(from, n, to);
 }
 
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
 /**
  * copy_to_user: - Copy a block of data into user space.
  * @to:   Destination address, in user space.
diff --git a/include/asm-sh/bug.h b/include/asm-sh/bug.h
index 0ffc7087c..ea41e17bb 100644
--- a/include/asm-sh/bug.h
+++ b/include/asm-sh/bug.h
@@ -11,20 +11,7 @@
 	asm volatile("nop"); \
 } while (0)
 
-#define BUG_ON(condition) do { \
-	if (unlikely((condition)!=0)) \
-		BUG(); \
-} while(0)
-
-#define PAGE_BUG(page) do { \
-	BUG(); \
-} while (0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-sh/cacheflush.h b/include/asm-sh/cacheflush.h
index 24ce48670..beb860ae7 100644
--- a/include/asm-sh/cacheflush.h
+++ b/include/asm-sh/cacheflush.h
@@ -14,10 +14,16 @@ extern void __flush_invalidate_region(void *start, int size);
 #define flush_cache_vunmap(start, end)		flush_cache_all()
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-do { memcpy(dst, src, len); \
-     flush_icache_user_range(vma, page, vaddr, len); \
-} while (0)
+	do {							\
+		flush_cache_page(vma, vaddr);			\
+		memcpy(dst, src, len);				\
+		flush_icache_user_range(vma, page, vaddr, len);	\
+	} while (0)
+
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
+	do {							\
+		flush_cache_page(vma, vaddr);			\
+		memcpy(dst, src, len);				\
+	} while (0)
 
 #endif /* __ASM_SH_CACHEFLUSH_H */
diff --git a/include/asm-sh/dma-mapping.h b/include/asm-sh/dma-mapping.h
index 8f149477e..8876ec7b0 100644
--- a/include/asm-sh/dma-mapping.h
+++ b/include/asm-sh/dma-mapping.h
@@ -3,7 +3,6 @@
 
 #include <linux/config.h>
 #include <linux/mm.h>
-#include <linux/device.h>
 #include <asm/scatterlist.h>
 #include <asm/io.h>
 
diff --git a/include/asm-sh/hardirq.h b/include/asm-sh/hardirq.h
index a57b94d22..1d7135a7d 100644
--- a/include/asm-sh/hardirq.h
+++ b/include/asm-sh/hardirq.h
@@ -35,20 +35,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -58,29 +44,10 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we in an interrupt context? Either doing bottom half
- * or hardware interrupt processing?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
-#define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 #define nmi_enter()		(irq_enter())
 #define nmi_exit()		(preempt_count() -= HARDIRQ_OFFSET)
 
-#ifdef CONFIG_PREEMPT
-# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
+#define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 #define irq_exit()							\
 do {									\
 		preempt_count() -= IRQ_EXIT_OFFSET;			\
@@ -89,10 +56,4 @@ do {									\
 		preempt_enable_no_resched();				\
 } while (0)
 
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else
-extern void synchronize_irq(unsigned int irq);
-#endif /* CONFIG_SMP */
-
 #endif /* __ASM_SH_HARDIRQ_H */
diff --git a/include/asm-sh/ptrace.h b/include/asm-sh/ptrace.h
index d0ca02c92..0f75e16a7 100644
--- a/include/asm-sh/ptrace.h
+++ b/include/asm-sh/ptrace.h
@@ -90,6 +90,15 @@ struct pt_dspregs {
 #define user_mode(regs) (((regs)->sr & 0x40000000)==0)
 #define instruction_pointer(regs) ((regs)->pc)
 extern void show_regs(struct pt_regs *);
+
+static inline unsigned long profile_pc(struct pt_regs *regs)
+{
+	unsigned long pc = instruction_pointer(regs);
+
+	if (pc >= 0xa0000000UL && pc < 0xc0000000UL)
+		pc -= 0x20000000;
+	return pc;
+}
 #endif
 
 #endif /* __ASM_SH_PTRACE_H */
diff --git a/include/asm-sh/resource.h b/include/asm-sh/resource.h
index 73e517a3e..bf6152e11 100644
--- a/include/asm-sh/resource.h
+++ b/include/asm-sh/resource.h
@@ -39,7 +39,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
-	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff --git a/include/asm-sh/semaphore.h b/include/asm-sh/semaphore.h
index dc8955e34..b923a77a8 100644
--- a/include/asm-sh/semaphore.h
+++ b/include/asm-sh/semaphore.h
@@ -24,21 +24,14 @@ struct semaphore {
 	atomic_t count;
 	int sleepers;
 	wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (int)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.sleepers	= 0,						\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name,1)
@@ -60,9 +53,6 @@ static inline void sema_init (struct semaphore *sem, int val)
 	atomic_set(&sem->count, val);
 	sem->sleepers = 0;
 	init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-	sem->__magic = (int)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -91,10 +81,6 @@ extern spinlock_t semaphore_wake_lock;
 
 static inline void down(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	might_sleep();
 	if (atomic_dec_return(&sem->count) < 0)
 		__down(sem);
@@ -103,9 +89,6 @@ static inline void down(struct semaphore * sem)
 static inline int down_interruptible(struct semaphore * sem)
 {
 	int ret = 0;
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 
 	might_sleep();
 	if (atomic_dec_return(&sem->count) < 0)
@@ -116,9 +99,6 @@ static inline int down_interruptible(struct semaphore * sem)
 static inline int down_trylock(struct semaphore * sem)
 {
 	int ret = 0;
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 
 	if (atomic_dec_return(&sem->count) < 0)
 		ret = __down_trylock(sem);
@@ -131,9 +111,6 @@ static inline int down_trylock(struct semaphore * sem)
  */
 static inline void up(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	if (atomic_inc_return(&sem->count) <= 0)
 		__up(sem);
 }
diff --git a/include/asm-sh/socket.h b/include/asm-sh/socket.h
index 2b9469472..dde696c3b 100644
--- a/include/asm-sh/socket.h
+++ b/include/asm-sh/socket.h
@@ -47,20 +47,4 @@
 
 #define SO_PEERSEC		31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* __ASM_SH_SOCKET_H */
diff --git a/include/asm-sh/uaccess.h b/include/asm-sh/uaccess.h
index 9186bbabe..df9a9b28e 100644
--- a/include/asm-sh/uaccess.h
+++ b/include/asm-sh/uaccess.h
@@ -446,6 +446,10 @@ __copy_res; })
 	__copy_user((void *)(to),		\
 		    (void *)(from), n)
 
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
+
 #define copy_from_user(to,from,n) ({ \
 void *__copy_to = (void *) (to); \
 void *__copy_from = (void *) (from); \
diff --git a/include/asm-sh64/cacheflush.h b/include/asm-sh64/cacheflush.h
index 6dcc87213..877c12fcd 100644
--- a/include/asm-sh64/cacheflush.h
+++ b/include/asm-sh64/cacheflush.h
@@ -30,13 +30,17 @@ extern void flush_icache_user_range(struct vm_area_struct *vma,
 #define flush_icache_page(vma, page)	do { } while (0)
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-do { memcpy(dst, src, len); \
-     flush_icache_user_range(vma, page, vaddr, len); \
-} while (0)
+	do {							\
+		flush_cache_page(vma, vaddr);			\
+		memcpy(dst, src, len);				\
+		flush_icache_user_range(vma, page, vaddr, len);	\
+	} while (0)
 
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
-
+	do {							\
+		flush_cache_page(vma, vaddr);			\
+		memcpy(dst, src, len);				\
+	} while (0)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/include/asm-sh64/dma-mapping.h b/include/asm-sh64/dma-mapping.h
index 3a6424986..b8d26fe67 100644
--- a/include/asm-sh64/dma-mapping.h
+++ b/include/asm-sh64/dma-mapping.h
@@ -3,7 +3,6 @@
 
 #include <linux/config.h>
 #include <linux/mm.h>
-#include <linux/device.h>
 #include <asm/scatterlist.h>
 #include <asm/io.h>
 
diff --git a/include/asm-sh64/ptrace.h b/include/asm-sh64/ptrace.h
index 56f836e1c..56190f521 100644
--- a/include/asm-sh64/ptrace.h
+++ b/include/asm-sh64/ptrace.h
@@ -28,6 +28,7 @@ struct pt_regs {
 #ifdef __KERNEL__
 #define user_mode(regs) (((regs)->sr & 0x40000000)==0)
 #define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 extern void show_regs(struct pt_regs *);
 #endif
 
diff --git a/include/asm-sh64/semaphore.h b/include/asm-sh64/semaphore.h
index 3e97ead32..fce22bb9a 100644
--- a/include/asm-sh64/semaphore.h
+++ b/include/asm-sh64/semaphore.h
@@ -31,21 +31,14 @@ struct semaphore {
 	atomic_t count;
 	int sleepers;
 	wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (int)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.sleepers	= 0,						\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name,1)
@@ -67,9 +60,6 @@ static inline void sema_init (struct semaphore *sem, int val)
 	atomic_set(&sem->count, val);
 	sem->sleepers = 0;
 	init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-	sem->__magic = (int)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -98,10 +88,6 @@ extern spinlock_t semaphore_wake_lock;
 
 static inline void down(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	if (atomic_dec_return(&sem->count) < 0)
 		__down(sem);
 }
@@ -109,9 +95,6 @@ static inline void down(struct semaphore * sem)
 static inline int down_interruptible(struct semaphore * sem)
 {
 	int ret = 0;
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 
 	if (atomic_dec_return(&sem->count) < 0)
 		ret = __down_interruptible(sem);
@@ -121,9 +104,6 @@ static inline int down_interruptible(struct semaphore * sem)
 static inline int down_trylock(struct semaphore * sem)
 {
 	int ret = 0;
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 
 	if (atomic_dec_return(&sem->count) < 0)
 		ret = __down_trylock(sem);
@@ -136,9 +116,6 @@ static inline int down_trylock(struct semaphore * sem)
  */
 static inline void up(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	if (atomic_inc_return(&sem->count) <= 0)
 		__up(sem);
 }
diff --git a/include/asm-sh64/uaccess.h b/include/asm-sh64/uaccess.h
index 0207bae93..588065c63 100644
--- a/include/asm-sh64/uaccess.h
+++ b/include/asm-sh64/uaccess.h
@@ -261,6 +261,9 @@ if (__copy_from_user(to,from,n)) \
 	return retval; \
 })
 
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
 /* XXX: Not sure it works well..
    should be such that: 4byte clear and the rest. */
 extern __kernel_size_t __clear_user(void *addr, __kernel_size_t size);
diff --git a/include/asm-sparc/bug.h b/include/asm-sparc/bug.h
index 1f321b091..0d30a67d8 100644
--- a/include/asm-sparc/bug.h
+++ b/include/asm-sparc/bug.h
@@ -25,20 +25,7 @@ extern void do_BUG(const char *file, int line);
 #define BUG()		__bug_trap()
 #endif
 
-#define BUG_ON(condition) do { \
-	if (unlikely((condition)!=0)) \
-		BUG(); \
-} while(0)
-
-#define PAGE_BUG(page) do { \
-	BUG(); \
-} while (0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-sparc/cacheflush.h b/include/asm-sparc/cacheflush.h
index a5f7fc33b..a91fe62b3 100644
--- a/include/asm-sparc/cacheflush.h
+++ b/include/asm-sparc/cacheflush.h
@@ -57,9 +57,15 @@ BTFIXUPDEF_CALL(void, flush_cache_page, struct vm_area_struct *, unsigned long)
 #define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
+	do {					\
+		flush_cache_page(vma, vaddr);	\
+		memcpy(dst, src, len);		\
+	} while (0)
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
+	do {					\
+		flush_cache_page(vma, vaddr);	\
+		memcpy(dst, src, len);		\
+	} while (0)
 
 BTFIXUPDEF_CALL(void, __flush_page_to_ram, unsigned long)
 BTFIXUPDEF_CALL(void, flush_sig_insns, struct mm_struct *, unsigned long)
diff --git a/include/asm-sparc/dma-mapping.h b/include/asm-sparc/dma-mapping.h
index 08ede04f7..2dc5bb8ef 100644
--- a/include/asm-sparc/dma-mapping.h
+++ b/include/asm-sparc/dma-mapping.h
@@ -2,7 +2,6 @@
 #define _ASM_SPARC_DMA_MAPPING_H
 
 #include <linux/config.h>
-#include <linux/device.h>
 
 #ifdef CONFIG_PCI
 #include <asm-generic/dma-mapping.h>
diff --git a/include/asm-sparc/hardirq.h b/include/asm-sparc/hardirq.h
index e882cf490..548b44167 100644
--- a/include/asm-sparc/hardirq.h
+++ b/include/asm-sparc/hardirq.h
@@ -42,42 +42,7 @@ typedef struct {
 #define SOFTIRQ_SHIFT   (PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT   (SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)       ((1UL << (x))-1)
-
-#define PREEMPT_MASK    (__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK    (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK    (__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count() (preempt_count() & HARDIRQ_MASK)
-#define softirq_count() (preempt_count() & SOFTIRQ_MASK)
-#define irq_count()     (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET  (1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET  (1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET  (1UL << HARDIRQ_SHIFT)
-
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()                (hardirq_count())
-#define in_softirq()            (softirq_count())
-#define in_interrupt()          (irq_count())
-
-
-#define hardirq_trylock()       (!in_interrupt())
-#define hardirq_endlock()       do { } while (0)
-
 #define irq_enter()             (preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-#include <linux/smp_lock.h>
-# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
 #define irq_exit()                                                      \
 do {                                                                    \
                 preempt_count() -= IRQ_EXIT_OFFSET;                     \
@@ -86,10 +51,4 @@ do {                                                                    \
                 preempt_enable_no_resched();                            \
 } while (0)
 
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else /* SMP */
-extern void synchronize_irq(unsigned int irq);
-#endif /* SMP */
-
 #endif /* __SPARC_HARDIRQ_H */
diff --git a/include/asm-sparc/ptrace.h b/include/asm-sparc/ptrace.h
index 68ecd7825..dd9d94d7e 100644
--- a/include/asm-sparc/ptrace.h
+++ b/include/asm-sparc/ptrace.h
@@ -62,6 +62,7 @@ struct sparc_stackf {
 #ifdef __KERNEL__
 #define user_mode(regs) (!((regs)->psr & PSR_PS))
 #define instruction_pointer(regs) ((regs)->pc)
+unsigned long profile_pc(struct pt_regs *);
 extern void show_regs(struct pt_regs *);
 #endif
 
diff --git a/include/asm-sparc/resource.h b/include/asm-sparc/resource.h
index 58e90f72c..d4fb2b4d3 100644
--- a/include/asm-sparc/resource.h
+++ b/include/asm-sparc/resource.h
@@ -44,7 +44,7 @@
     {       0, RLIM_INFINITY},		\
     {RLIM_INFINITY, RLIM_INFINITY},	\
     {INR_OPEN, INR_OPEN}, {0, 0},	\
-    {RLIM_INFINITY, RLIM_INFINITY},	\
+    {MLOCK_LIMIT,   MLOCK_LIMIT},	\
     {RLIM_INFINITY, RLIM_INFINITY},	\
     {RLIM_INFINITY, RLIM_INFINITY},	\
     {MAX_SIGPENDING, MAX_SIGPENDING},	\
diff --git a/include/asm-sparc/semaphore.h b/include/asm-sparc/semaphore.h
index e8e9ae601..60ac5fd9e 100644
--- a/include/asm-sparc/semaphore.h
+++ b/include/asm-sparc/semaphore.h
@@ -13,21 +13,14 @@ struct semaphore {
 	atomic24_t count;
 	int sleepers;
 	wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (long)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC24_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC24_INIT(n),				\
+	.sleepers	= 0,						\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name,1)
@@ -43,9 +36,6 @@ static inline void sema_init (struct semaphore *sem, int val)
 	atomic24_set(&sem->count, val);
 	sem->sleepers = 0;
 	init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -68,9 +58,6 @@ static inline void down(struct semaphore * sem)
 	register volatile int *ptr asm("g1");
 	register int increment asm("g2");
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	ptr = &(sem->count.counter);
@@ -105,9 +92,6 @@ static inline int down_interruptible(struct semaphore * sem)
 	register volatile int *ptr asm("g1");
 	register int increment asm("g2");
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	ptr = &(sem->count.counter);
@@ -145,10 +129,6 @@ static inline int down_trylock(struct semaphore * sem)
 	register volatile int *ptr asm("g1");
 	register int increment asm("g2");
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	ptr = &(sem->count.counter);
 	increment = 1;
 
@@ -184,10 +164,6 @@ static inline void up(struct semaphore * sem)
 	register volatile int *ptr asm("g1");
 	register int increment asm("g2");
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	ptr = &(sem->count.counter);
 	increment = 1;
 
diff --git a/include/asm-sparc/sigcontext.h b/include/asm-sparc/sigcontext.h
index ff9ccda16..86dc000ad 100644
--- a/include/asm-sparc/sigcontext.h
+++ b/include/asm-sparc/sigcontext.h
@@ -57,20 +57,6 @@ typedef struct {
 	} si_fpqueue [16];
 } __siginfo_fpu_t;
 
-#ifdef __KERNEL__
-
-/* This magic should be in g_upper[0] for all upper parts
-   to be valid.
-   This is generated by sparc64 only, but for 32bit processes,
-   so we define it here as well.  */
-#define SIGINFO_EXTRA_V8PLUS_MAGIC      0x130e269
-typedef struct {
-	unsigned   int g_upper[8];
-	unsigned   int o_upper[8];
-} siginfo_extra_v8plus_t;
-
-#endif
-
 #endif /* !(__ASSEMBLY__) */
 
 #endif /* !(__SPARC_SIGCONTEXT_H) */
diff --git a/include/asm-sparc/socket.h b/include/asm-sparc/socket.h
index cfa529d9b..c1154e3ec 100644
--- a/include/asm-sparc/socket.h
+++ b/include/asm-sparc/socket.h
@@ -52,20 +52,4 @@
 #define SO_SECURITY_ENCRYPTION_TRANSPORT	0x5002
 #define SO_SECURITY_ENCRYPTION_NETWORK		0x5004
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-sparc/uaccess.h b/include/asm-sparc/uaccess.h
index 8ef47f13c..b6a87c2e1 100644
--- a/include/asm-sparc/uaccess.h
+++ b/include/asm-sparc/uaccess.h
@@ -322,6 +322,9 @@ static inline unsigned long __copy_from_user(void *to, const void __user *from,
 	return __copy_user((void __user *) to, from, n);
 }
 
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
 static inline unsigned long __clear_user(void __user *addr, unsigned long size)
 {
 	unsigned long ret;
diff --git a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h
index b742c9f4d..9034e2d60 100644
--- a/include/asm-sparc/unistd.h
+++ b/include/asm-sparc/unistd.h
@@ -290,11 +290,12 @@
 #define __NR_io_cancel		271
 #define __NR_io_getevents	272
 #define __NR_mq_open		273
-#define __NR_mq_unlink		(__NR_mq_open+1)
-#define __NR_mq_timedsend	(__NR_mq_open+2)
-#define __NR_mq_timedreceive	(__NR_mq_open+3)
-#define __NR_mq_notify		(__NR_mq_open+4)
-#define __NR_mq_getsetattr	(__NR_mq_open+5)
+#define __NR_mq_unlink		274
+#define __NR_mq_timedsend	275
+#define __NR_mq_timedreceive	276
+#define __NR_mq_notify		277
+#define __NR_mq_getsetattr	278
+#define __NR_waitid		279
 
 /* WARNING: You MAY NOT add syscall numbers larger than 282, since
  *          all of the syscall tables in the Sparc kernel are
diff --git a/include/asm-sparc/vaddrs.h b/include/asm-sparc/vaddrs.h
index d74f4dfc3..91097392c 100644
--- a/include/asm-sparc/vaddrs.h
+++ b/include/asm-sparc/vaddrs.h
@@ -33,9 +33,9 @@
 
 #define SUN4M_IOBASE_VADDR	0xfd000000 /* Base for mapping pages */
 #define IOBASE_VADDR		0xfe000000
-#define IOBASE_END		0xfe300000
+#define IOBASE_END		0xfe600000
 
-#define VMALLOC_START		0xfe300000
+#define VMALLOC_START		0xfe600000
 
 /* XXX Alter this when I get around to fixing sun4c - Anton */
 #define VMALLOC_END		0xffc00000
diff --git a/include/asm-sparc64/bitops.h b/include/asm-sparc64/bitops.h
index f13765454..1289af241 100644
--- a/include/asm-sparc64/bitops.h
+++ b/include/asm-sparc64/bitops.h
@@ -228,13 +228,10 @@ extern unsigned long find_next_zero_bit(unsigned long *, unsigned long, unsigned
 #define find_first_zero_bit(addr, size) \
         find_next_zero_bit((addr), (size), 0)
 
-extern long ___test_and_set_le_bit(int nr, volatile unsigned long *addr);
-extern long ___test_and_clear_le_bit(int nr, volatile unsigned long *addr);
-
-#define test_and_set_le_bit(nr,addr)	({___test_and_set_le_bit(nr,addr)!=0;})
-#define test_and_clear_le_bit(nr,addr)	({___test_and_clear_le_bit(nr,addr)!=0;})
-#define set_le_bit(nr,addr)		((void)___test_and_set_le_bit(nr,addr))
-#define clear_le_bit(nr,addr)		((void)___test_and_clear_le_bit(nr,addr))
+#define test_and_set_le_bit(nr,addr)	\
+	({ ___test_and_set_bit((nr) ^ 0x38, (addr)) != 0; })
+#define test_and_clear_le_bit(nr,addr)	\
+	({ ___test_and_clear_bit((nr) ^ 0x38, (addr)) != 0; })
 
 static __inline__ int test_le_bit(int nr, __const__ unsigned long * addr)
 {
@@ -253,22 +250,30 @@ extern unsigned long find_next_zero_le_bit(unsigned long *, unsigned long, unsig
 
 #ifdef __KERNEL__
 
-#define ext2_set_bit(nr,addr)		test_and_set_le_bit((nr),(unsigned long *)(addr))
-#define ext2_set_bit_atomic(lock,nr,addr) test_and_set_le_bit((nr),(unsigned long *)(addr))
-#define ext2_clear_bit(nr,addr)		test_and_clear_le_bit((nr),(unsigned long *)(addr))
-#define ext2_clear_bit_atomic(lock,nr,addr) test_and_clear_le_bit((nr),(unsigned long *)(addr))
-#define ext2_test_bit(nr,addr)		test_le_bit((nr),(unsigned long *)(addr))
+#define ext2_set_bit(nr,addr)	\
+	test_and_set_le_bit((nr),(unsigned long *)(addr))
+#define ext2_set_bit_atomic(lock,nr,addr) \
+	test_and_set_le_bit((nr),(unsigned long *)(addr))
+#define ext2_clear_bit(nr,addr)	\
+	test_and_clear_le_bit((nr),(unsigned long *)(addr))
+#define ext2_clear_bit_atomic(lock,nr,addr) \
+	test_and_clear_le_bit((nr),(unsigned long *)(addr))
+#define ext2_test_bit(nr,addr)	\
+	test_le_bit((nr),(unsigned long *)(addr))
 #define ext2_find_first_zero_bit(addr, size) \
 	find_first_zero_le_bit((unsigned long *)(addr), (size))
 #define ext2_find_next_zero_bit(addr, size, off) \
 	find_next_zero_le_bit((unsigned long *)(addr), (size), (off))
 
 /* Bitmap functions for the minix filesystem.  */
-#define minix_test_and_set_bit(nr,addr)	test_and_set_bit((nr),(unsigned long *)(addr))
-#define minix_set_bit(nr,addr)		set_bit((nr),(unsigned long *)(addr))
+#define minix_test_and_set_bit(nr,addr)	\
+	test_and_set_bit((nr),(unsigned long *)(addr))
+#define minix_set_bit(nr,addr)	\
+	set_bit((nr),(unsigned long *)(addr))
 #define minix_test_and_clear_bit(nr,addr) \
 	test_and_clear_bit((nr),(unsigned long *)(addr))
-#define minix_test_bit(nr,addr)		test_bit((nr),(unsigned long *)(addr))
+#define minix_test_bit(nr,addr)	\
+	test_bit((nr),(unsigned long *)(addr))
 #define minix_find_first_zero_bit(addr,size) \
 	find_first_zero_bit((unsigned long *)(addr),(size))
 
diff --git a/include/asm-sparc64/bug.h b/include/asm-sparc64/bug.h
index bfac1afa9..25c5b1dfe 100644
--- a/include/asm-sparc64/bug.h
+++ b/include/asm-sparc64/bug.h
@@ -1,5 +1,3 @@
-/* $Id$ */
-
 #ifndef _SPARC64_BUG_H
 #define _SPARC64_BUG_H
 
@@ -15,20 +13,7 @@ extern void do_BUG(const char *file, int line);
 #define BUG()		__builtin_trap()
 #endif
 
-#define BUG_ON(condition) do { \
-	if (unlikely((condition)!=0)) \
-		BUG(); \
-} while(0)
-
-#define PAGE_BUG(page) do { \
-	BUG(); \
-} while (0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-sparc64/cacheflush.h b/include/asm-sparc64/cacheflush.h
index b04024ff5..f4b1df6a5 100644
--- a/include/asm-sparc64/cacheflush.h
+++ b/include/asm-sparc64/cacheflush.h
@@ -38,9 +38,16 @@ extern void __flush_dcache_range(unsigned long start, unsigned long end);
 #define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
+	do {					\
+		flush_cache_page(vma, vaddr);	\
+		memcpy(dst, src, len);		\
+	} while (0)
+
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	memcpy(dst, src, len)
+	do {					\
+		flush_cache_page(vma, vaddr);	\
+		memcpy(dst, src, len);		\
+	} while (0)
 
 extern void flush_dcache_page(struct page *page);
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
diff --git a/include/asm-sparc64/checksum.h b/include/asm-sparc64/checksum.h
index c388e6e06..daff14e72 100644
--- a/include/asm-sparc64/checksum.h
+++ b/include/asm-sparc64/checksum.h
@@ -40,7 +40,7 @@ extern unsigned int csum_partial(const unsigned char * buff, int len, unsigned i
  */
 extern unsigned int csum_partial_copy_sparc64(const char *src, char *dst, int len, unsigned int sum);
 			
-static __inline__ unsigned int 
+static inline unsigned int 
 csum_partial_copy_nocheck (const char *src, char *dst, int len, 
 			   unsigned int sum)
 {
@@ -52,22 +52,23 @@ csum_partial_copy_nocheck (const char *src, char *dst, int len,
 	return ret;
 }
 
-static __inline__ unsigned int 
-csum_partial_copy_from_user(const char *src, char *dst, int len, 
+static inline unsigned int 
+csum_partial_copy_from_user(const char __user *src, char *dst, int len, 
 			    unsigned int sum, int *err)
 {
 	__asm__ __volatile__ ("stx	%0, [%%sp + 0x7ff + 128]"
 			      : : "r" (err));
-	return csum_partial_copy_sparc64(src, dst, len, sum);
+	return csum_partial_copy_sparc64((__force const char *) src,
+					 dst, len, sum);
 }
 
 /* 
  *	Copy and checksum to user
  */
 #define HAVE_CSUM_COPY_USER
-extern unsigned int csum_partial_copy_user_sparc64(const char *src, char *dst, int len, unsigned int sum);
+extern unsigned int csum_partial_copy_user_sparc64(const char *src, char __user *dst, int len, unsigned int sum);
 
-static __inline__ unsigned int 
+static inline unsigned int 
 csum_and_copy_to_user(const char *src, char __user *dst, int len, 
 		      unsigned int sum, int *err)
 {
@@ -83,7 +84,7 @@ extern unsigned short ip_fast_csum(__const__ unsigned char *iph,
 				   unsigned int ihl);
 
 /* Fold a partial checksum without adding pseudo headers. */
-static __inline__ unsigned short csum_fold(unsigned int sum)
+static inline unsigned short csum_fold(unsigned int sum)
 {
 	unsigned int tmp;
 
@@ -98,11 +99,11 @@ static __inline__ unsigned short csum_fold(unsigned int sum)
 	return (sum & 0xffff);
 }
 
-static __inline__ unsigned long csum_tcpudp_nofold(unsigned long saddr,
-						   unsigned long daddr,
-						   unsigned int len,
-						   unsigned short proto,
-						   unsigned int sum)
+static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
+					       unsigned long daddr,
+					       unsigned int len,
+					       unsigned short proto,
+					       unsigned int sum)
 {
 	__asm__ __volatile__(
 "	addcc		%1, %0, %0\n"
@@ -130,11 +131,11 @@ static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
 
 #define _HAVE_ARCH_IPV6_CSUM
 
-static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
-						     struct in6_addr *daddr,
-						     __u32 len,
-						     unsigned short proto,
-						     unsigned int sum) 
+static inline unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
+						 struct in6_addr *daddr,
+						 __u32 len,
+						 unsigned short proto,
+						 unsigned int sum) 
 {
 	__asm__ __volatile__ (
 "	addcc		%3, %4, %%g7\n"
@@ -165,7 +166,7 @@ static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
 }
 
 /* this routine is used for miscellaneous IP-like checksums, mainly in icmp.c */
-static __inline__ unsigned short ip_compute_csum(unsigned char * buff, int len)
+static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
 {
 	return csum_fold(csum_partial(buff, len, 0));
 }
diff --git a/include/asm-sparc64/delay.h b/include/asm-sparc64/delay.h
index 13de4b10f..2901ea0c3 100644
--- a/include/asm-sparc64/delay.h
+++ b/include/asm-sparc64/delay.h
@@ -1,7 +1,11 @@
-/* $Id: delay.h,v 1.13 2002/02/02 03:33:48 kanoj Exp $
- * delay.h: Linux delay routines on the V9.
+/* delay.h: Linux delay routines on sparc64.
  *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu).
+ * Copyright (C) 1996, 2004 David S. Miller (davem@davemloft.net).
+ *
+ * Based heavily upon x86 variant which is:
+ * Copyright (C) 1993 Linus Torvalds
+ *
+ * Delay routines calling functions in arch/sparc64/lib/delay.c
  */
 
 #ifndef __SPARC64_DELAY_H
@@ -13,50 +17,21 @@
 
 #ifndef __ASSEMBLY__
 
-static __inline__ void __delay(unsigned long loops)
-{
-	__asm__ __volatile__(
-"	b,pt	%%xcc, 1f\n"
-"	 cmp	%0, 0\n"
-"	.align	32\n"
-"1:\n"
-"	bne,pt	%%xcc, 1b\n"
-"	 subcc	%0, 1, %0\n"
-	: "=&r" (loops)
-	: "0" (loops)
-	: "cc");
-}
-
-static __inline__ void __udelay(unsigned long usecs, unsigned long lps)
-{
-	usecs *= 0x00000000000010c6UL;		/* 2**32 / 1000000 */
-
-	__asm__ __volatile__(
-"	mulx	%1, %2, %0\n"
-"	srlx	%0, 32, %0\n"
-	: "=r" (usecs)
-	: "r" (usecs), "r" (lps));
-
-	__delay(usecs * HZ);
-}
-
-extern __inline__ void __ndelay(unsigned long usecs, unsigned long lps)
-{
-	usecs *= 0x0000000000000005UL;		/* 2**32 / 10000 */
-
-	__asm__ __volatile__(
-"	mulx	%1, %2, %0\n"
-"	srlx	%0, 32, %0\n"
-	: "=r" (usecs)
-	: "r" (usecs), "r" (lps));
-
-	__delay(usecs * HZ);
-}
-
-#define __udelay_val cpu_data(smp_processor_id()).udelay_val
-
-#define udelay(usecs) __udelay((usecs),__udelay_val)
-#define ndelay(usecs) __ndelay((usecs),__udelay_val)
+extern void __bad_udelay(void);
+extern void __bad_ndelay(void);
+
+extern void __udelay(unsigned long usecs);
+extern void __ndelay(unsigned long nsecs);
+extern void __const_udelay(unsigned long usecs);
+extern void __delay(unsigned long loops);
+
+#define udelay(n) (__builtin_constant_p(n) ? \
+	((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \
+	__udelay(n))
+	
+#define ndelay(n) (__builtin_constant_p(n) ? \
+	((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
+	__ndelay(n))
 
 #endif /* !__ASSEMBLY__ */
 
diff --git a/include/asm-sparc64/dma.h b/include/asm-sparc64/dma.h
index b80f2f7ab..1aab3c8dc 100644
--- a/include/asm-sparc64/dma.h
+++ b/include/asm-sparc64/dma.h
@@ -62,7 +62,7 @@ enum dvma_rev {
 struct sbus_dma {
 	struct sbus_dma *next;
 	struct sbus_dev *sdev;
-	unsigned long regs;
+	void __iomem *regs;
 
 	/* Status, misc info */
 	int node;                /* Prom node for this DMA device */
diff --git a/include/asm-sparc64/ebus.h b/include/asm-sparc64/ebus.h
index 82e837643..543e4e500 100644
--- a/include/asm-sparc64/ebus.h
+++ b/include/asm-sparc64/ebus.h
@@ -53,7 +53,7 @@ struct linux_ebus {
 
 struct ebus_dma_info {
 	spinlock_t	lock;
-	unsigned long	regs;
+	void __iomem	*regs;
 
 	unsigned int	flags;
 #define EBUS_DMA_FLAG_USE_EBDMA_HANDLER		0x00000001
diff --git a/include/asm-sparc64/elf.h b/include/asm-sparc64/elf.h
index 88a7ee8db..914581182 100644
--- a/include/asm-sparc64/elf.h
+++ b/include/asm-sparc64/elf.h
@@ -94,12 +94,12 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 #define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs)	\
 do {	unsigned long *dest = &(__elf_regs[0]);		\
 	struct pt_regs *src = (__pt_regs);		\
-	unsigned long *sp;				\
+	unsigned long __user *sp;			\
 	int i;						\
 	for(i = 0; i < 16; i++)				\
 		dest[i] = src->u_regs[i];		\
 	/* Don't try this at home kids... */		\
-	sp = (unsigned long *)				\
+	sp = (unsigned long __user *)			\
 	 ((src->u_regs[14] + STACK_BIAS)		\
 	  & 0xfffffffffffffff8UL);			\
 	for(i = 0; i < 16; i++)				\
diff --git a/include/asm-sparc64/hardirq.h b/include/asm-sparc64/hardirq.h
index cae78abf2..ac63de550 100644
--- a/include/asm-sparc64/hardirq.h
+++ b/include/asm-sparc64/hardirq.h
@@ -41,42 +41,7 @@ typedef struct {
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# include <linux/smp_lock.h>
-# define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()	(preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
 #define irq_exit()							\
 do {									\
 		preempt_count() -= IRQ_EXIT_OFFSET;			\
@@ -85,10 +50,4 @@ do {									\
 		preempt_enable_no_resched();				\
 } while (0)
 
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else
-  extern void synchronize_irq(unsigned int irq);
-#endif /* CONFIG_SMP */
-
 #endif /* !(__SPARC64_HARDIRQ_H) */
diff --git a/include/asm-sparc64/ide.h b/include/asm-sparc64/ide.h
index f850b61ab..6b3274022 100644
--- a/include/asm-sparc64/ide.h
+++ b/include/asm-sparc64/ide.h
@@ -38,7 +38,7 @@
 #define __ide_mm_outsw	__ide_outsw
 #define __ide_mm_outsl	__ide_outsl
 
-static __inline__ unsigned int inw_be(unsigned long addr)
+static inline unsigned int inw_be(void __iomem *addr)
 {
 	unsigned int ret;
 
@@ -49,9 +49,7 @@ static __inline__ unsigned int inw_be(unsigned long addr)
 	return ret;
 }
 
-static __inline__ void __ide_insw(unsigned long port,
-				  void *dst,
-				  u32 count)
+static inline void __ide_insw(void __iomem *port, void *dst, u32 count)
 {
 #if (L1DCACHE_SIZE > PAGE_SIZE)		/* is there D$ aliasing problem */
 	unsigned long end = (unsigned long)dst + (count << 1);
@@ -81,16 +79,14 @@ static __inline__ void __ide_insw(unsigned long port,
 #endif
 }
 
-static __inline__ void outw_be(unsigned short w, unsigned long addr)
+static inline void outw_be(unsigned short w, void __iomem *addr)
 {
 	__asm__ __volatile__("stha %0, [%1] %2"
 			     : /* no outputs */
 			     : "r" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
 }
 
-static __inline__ void __ide_outsw(unsigned long port,
-				   void *src,
-				   u32 count)
+static inline void __ide_outsw(void __iomem *port, void *src, u32 count)
 {
 #if (L1DCACHE_SIZE > PAGE_SIZE)		/* is there D$ aliasing problem */
 	unsigned long end = (unsigned long)src + (count << 1);
diff --git a/include/asm-sparc64/io.h b/include/asm-sparc64/io.h
index 94a8a70cd..7861627d9 100644
--- a/include/asm-sparc64/io.h
+++ b/include/asm-sparc64/io.h
@@ -3,6 +3,7 @@
 #define __SPARC64_IO_H
 
 #include <linux/kernel.h>
+#include <linux/compiler.h>
 #include <linux/types.h>
 
 #include <asm/page.h>      /* IO address mapping routines need this */
@@ -99,28 +100,31 @@ static __inline__ void _outl(u32 l, unsigned long addr)
 #define inl_p(__addr)		inl(__addr)
 #define outl_p(__l, __addr)	outl(__l, __addr)
 
-extern void outsb(unsigned long addr, const void *src, unsigned long count);
-extern void outsw(unsigned long addr, const void *src, unsigned long count);
-extern void outsl(unsigned long addr, const void *src, unsigned long count);
-extern void insb(unsigned long addr, void *dst, unsigned long count);
-extern void insw(unsigned long addr, void *dst, unsigned long count);
-extern void insl(unsigned long addr, void *dst, unsigned long count);
+extern void outsb(void __iomem *addr, const void *src, unsigned long count);
+extern void outsw(void __iomem *addr, const void *src, unsigned long count);
+extern void outsl(void __iomem *addr, const void *src, unsigned long count);
+extern void insb(void __iomem *addr, void *dst, unsigned long count);
+extern void insw(void __iomem *addr, void *dst, unsigned long count);
+extern void insl(void __iomem *addr, void *dst, unsigned long count);
+#define ioread8_rep(a,d,c)	insb(a,d,c)
+#define ioread16_rep(a,d,c)	insw(a,d,c)
+#define ioread32_rep(a,d,c)	insl(a,d,c)
+#define iowrite8_rep(a,s,c)	outsb(a,s,c)
+#define iowrite16_rep(a,s,c)	outsw(a,s,c)
+#define iowrite32_rep(a,s,c)	outsl(a,s,c)
 
 /* Memory functions, same as I/O accesses on Ultra. */
-static __inline__ u8 _readb(unsigned long addr)
-{
-	u8 ret;
+static inline u8 _readb(void __iomem *addr)
+{	u8 ret;
 
 	__asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_readb */"
 			     : "=r" (ret)
 			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
-
 	return ret;
 }
 
-static __inline__ u16 _readw(unsigned long addr)
-{
-	u16 ret;
+static inline u16 _readw(void __iomem *addr)
+{	u16 ret;
 
 	__asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_readw */"
 			     : "=r" (ret)
@@ -129,9 +133,8 @@ static __inline__ u16 _readw(unsigned long addr)
 	return ret;
 }
 
-static __inline__ u32 _readl(unsigned long addr)
-{
-	u32 ret;
+static inline u32 _readl(void __iomem *addr)
+{	u32 ret;
 
 	__asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_readl */"
 			     : "=r" (ret)
@@ -140,9 +143,8 @@ static __inline__ u32 _readl(unsigned long addr)
 	return ret;
 }
 
-static __inline__ u64 _readq(unsigned long addr)
-{
-	u64 ret;
+static inline u64 _readq(void __iomem *addr)
+{	u64 ret;
 
 	__asm__ __volatile__("ldxa\t[%1] %2, %0\t/* pci_readq */"
 			     : "=r" (ret)
@@ -151,46 +153,46 @@ static __inline__ u64 _readq(unsigned long addr)
 	return ret;
 }
 
-static __inline__ void _writeb(u8 b, unsigned long addr)
+static inline void _writeb(u8 b, void __iomem *addr)
 {
 	__asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_writeb */"
 			     : /* no outputs */
 			     : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 }
 
-static __inline__ void _writew(u16 w, unsigned long addr)
+static inline void _writew(u16 w, void __iomem *addr)
 {
 	__asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_writew */"
 			     : /* no outputs */
 			     : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 }
 
-static __inline__ void _writel(u32 l, unsigned long addr)
+static inline void _writel(u32 l, void __iomem *addr)
 {
 	__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_writel */"
 			     : /* no outputs */
 			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 }
 
-static __inline__ void _writeq(u64 q, unsigned long addr)
+static inline void _writeq(u64 q, void __iomem *addr)
 {
 	__asm__ __volatile__("stxa\t%r0, [%1] %2\t/* pci_writeq */"
 			     : /* no outputs */
 			     : "Jr" (q), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 }
 
-#define readb(__addr)		(_readb((unsigned long)(__addr)))
-#define readw(__addr)		(_readw((unsigned long)(__addr)))
-#define readl(__addr)		(_readl((unsigned long)(__addr)))
-#define readq(__addr)		(_readq((unsigned long)(__addr)))
-#define readb_relaxed(a)	readb(a)
-#define readw_relaxed(a)	readw(a)
-#define readl_relaxed(a)	readl(a)
-#define readq_relaxed(a)	readq(a)
-#define writeb(__b, __addr)	(_writeb((u8)(__b), (unsigned long)(__addr)))
-#define writew(__w, __addr)	(_writew((u16)(__w), (unsigned long)(__addr)))
-#define writel(__l, __addr)	(_writel((u32)(__l), (unsigned long)(__addr)))
-#define writeq(__q, __addr)	(_writeq((u64)(__q), (unsigned long)(__addr)))
+#define readb(__addr)		_readb(__addr)
+#define readw(__addr)		_readw(__addr)
+#define readl(__addr)		_readl(__addr)
+#define readq(__addr)		_readq(__addr)
+#define readb_relaxed(__addr)	_readb(__addr)
+#define readw_relaxed(__addr)	_readw(__addr)
+#define readl_relaxed(__addr)	_readl(__addr)
+#define readq_relaxed(__addr)	_readq(__addr)
+#define writeb(__b, __addr)	_writeb(__b, __addr)
+#define writew(__w, __addr)	_writew(__w, __addr)
+#define writel(__l, __addr)	_writel(__l, __addr)
+#define writeq(__q, __addr)	_writeq(__q, __addr)
 
 /* Now versions without byte-swapping. */
 static __inline__ u8 _raw_readb(unsigned long addr)
@@ -282,7 +284,7 @@ static __inline__ void _raw_writeq(u64 q, unsigned long addr)
 /* Now, SBUS variants, only difference from PCI is that we do
  * not use little-endian ASIs.
  */
-static __inline__ u8 _sbus_readb(unsigned long addr)
+static inline u8 _sbus_readb(void __iomem *addr)
 {
 	u8 ret;
 
@@ -293,7 +295,7 @@ static __inline__ u8 _sbus_readb(unsigned long addr)
 	return ret;
 }
 
-static __inline__ u16 _sbus_readw(unsigned long addr)
+static inline u16 _sbus_readw(void __iomem *addr)
 {
 	u16 ret;
 
@@ -304,7 +306,7 @@ static __inline__ u16 _sbus_readw(unsigned long addr)
 	return ret;
 }
 
-static __inline__ u32 _sbus_readl(unsigned long addr)
+static inline u32 _sbus_readl(void __iomem *addr)
 {
 	u32 ret;
 
@@ -315,7 +317,7 @@ static __inline__ u32 _sbus_readl(unsigned long addr)
 	return ret;
 }
 
-static __inline__ u64 _sbus_readq(unsigned long addr)
+static inline u64 _sbus_readq(void __iomem *addr)
 {
 	u64 ret;
 
@@ -326,44 +328,45 @@ static __inline__ u64 _sbus_readq(unsigned long addr)
 	return ret;
 }
 
-static __inline__ void _sbus_writeb(u8 b, unsigned long addr)
+static inline void _sbus_writeb(u8 b, void __iomem *addr)
 {
 	__asm__ __volatile__("stba\t%r0, [%1] %2\t/* sbus_writeb */"
 			     : /* no outputs */
 			     : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
 }
 
-static __inline__ void _sbus_writew(u16 w, unsigned long addr)
+static inline void _sbus_writew(u16 w, void __iomem *addr)
 {
 	__asm__ __volatile__("stha\t%r0, [%1] %2\t/* sbus_writew */"
 			     : /* no outputs */
 			     : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
 }
 
-static __inline__ void _sbus_writel(u32 l, unsigned long addr)
+static inline void _sbus_writel(u32 l, void __iomem *addr)
 {
 	__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* sbus_writel */"
 			     : /* no outputs */
 			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
 }
 
-static __inline__ void _sbus_writeq(u64 l, unsigned long addr)
+static inline void _sbus_writeq(u64 l, void __iomem *addr)
 {
 	__asm__ __volatile__("stxa\t%r0, [%1] %2\t/* sbus_writeq */"
 			     : /* no outputs */
 			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
 }
 
-#define sbus_readb(__addr)		(_sbus_readb((unsigned long)(__addr)))
-#define sbus_readw(__addr)		(_sbus_readw((unsigned long)(__addr)))
-#define sbus_readl(__addr)		(_sbus_readl((unsigned long)(__addr)))
-#define sbus_readq(__addr)		(_sbus_readq((unsigned long)(__addr)))
-#define sbus_writeb(__b, __addr)	(_sbus_writeb((__b), (unsigned long)(__addr)))
-#define sbus_writew(__w, __addr)	(_sbus_writew((__w), (unsigned long)(__addr)))
-#define sbus_writel(__l, __addr)	(_sbus_writel((__l), (unsigned long)(__addr)))
-#define sbus_writeq(__l, __addr)	(_sbus_writeq((__l), (unsigned long)(__addr)))
+#define sbus_readb(__addr)		_sbus_readb(__addr)
+#define sbus_readw(__addr)		_sbus_readw(__addr)
+#define sbus_readl(__addr)		_sbus_readl(__addr)
+#define sbus_readq(__addr)		_sbus_readq(__addr)
+#define sbus_writeb(__b, __addr)	_sbus_writeb(__b, __addr)
+#define sbus_writew(__w, __addr)	_sbus_writew(__w, __addr)
+#define sbus_writel(__l, __addr)	_sbus_writel(__l, __addr)
+#define sbus_writeq(__l, __addr)	_sbus_writeq(__l, __addr)
 
-static inline void *_sbus_memset_io(unsigned long dst, int c, __kernel_size_t n)
+static inline void __iomem*_sbus_memset_io(void __iomem *dst, int c,
+					   __kernel_size_t n)
 {
 	while(n--) {
 		sbus_writeb(c, dst);
@@ -372,13 +375,12 @@ static inline void *_sbus_memset_io(unsigned long dst, int c, __kernel_size_t n)
 	return (void *) dst;
 }
 
-#define sbus_memset_io(d,c,sz)	\
-	_sbus_memset_io((unsigned long)d,(int)c,(__kernel_size_t)sz)
+#define sbus_memset_io(d,c,sz)	_sbus_memset_io(d,c,sz)
 
-static inline void *
-_memset_io(void *dst, int c, __kernel_size_t n)
+static inline void __iomem *
+_memset_io(void __iomem *dst, int c, __kernel_size_t n)
 {
-	char *d = dst;
+	void __iomem *d = dst;
 
 	while (n--) {
 		writeb(c, d);
@@ -388,11 +390,10 @@ _memset_io(void *dst, int c, __kernel_size_t n)
 	return dst;
 }
 
-#define memset_io(d,c,sz)	\
-	_memset_io((void *)d,(int)c,(__kernel_size_t)sz)
+#define memset_io(d,c,sz)	_memset_io(d,c,sz)
 
-static inline void *
-_memcpy_fromio(void *dst, unsigned long src, __kernel_size_t n)
+static inline void __iomem *
+_memcpy_fromio(void *dst, void __iomem *src, __kernel_size_t n)
 {
 	char *d = dst;
 
@@ -405,25 +406,23 @@ _memcpy_fromio(void *dst, unsigned long src, __kernel_size_t n)
 	return dst;
 }
 
-#define memcpy_fromio(d,s,sz)	\
-	_memcpy_fromio((void *)d,(unsigned long)s,(__kernel_size_t)sz)
+#define memcpy_fromio(d,s,sz)	_memcpy_fromio(d,s,sz)
 
-static inline void *
-_memcpy_toio(unsigned long dst, const void *src, __kernel_size_t n)
+static inline void __iomem *
+_memcpy_toio(void __iomem *dst, const void *src, __kernel_size_t n)
 {
 	const char *s = src;
-	unsigned long d = dst;
+	void __iomem *d = dst;
 
 	while (n--) {
 		char tmp = *s++;
 		writeb(tmp, d);
 		d++;
 	}
-	return (void *)dst;
+	return dst;
 }
 
-#define memcpy_toio(d,s,sz)	\
-	_memcpy_toio((unsigned long)d,(const void *)s,(__kernel_size_t)sz)
+#define memcpy_toio(d,s,sz)	_memcpy_toio(d,s,sz)
 
 static inline int check_signature(unsigned long io_addr,
 				  const unsigned char *signature,
@@ -431,8 +430,9 @@ static inline int check_signature(unsigned long io_addr,
 {
 	int retval = 0;
 	do {
-		if (readb(io_addr++) != *signature++)
+		if (readb((void __iomem *)io_addr) != *signature++)
 			goto out;
+		io_addr++;
 	} while (--length);
 	retval = 1;
 out:
@@ -444,10 +444,26 @@ out:
 /* On sparc64 we have the whole physical IO address space accessible
  * using physically addressed loads and stores, so this does nothing.
  */
-#define ioremap(__offset, __size)	((void *)(__offset))
+#define ioremap(__offset, __size)	((void __iomem *)(__offset))
 #define ioremap_nocache(X,Y)		ioremap((X),(Y))
 #define iounmap(__addr)			do { (void)(__addr); } while(0)
 
+#define ioread8(X)			readb(X)
+#define ioread16(X)			readw(X)
+#define ioread32(X)			readl(X)
+#define iowrite8(val,X)			writeb(val,X)
+#define iowrite16(val,X)		writew(val,X)
+#define iowrite32(val,X)		writel(val,X)
+
+/* Create a virtual mapping cookie for an IO port range */
+extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
+extern void ioport_unmap(void __iomem *);
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+struct pci_dev;
+extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
+extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
+
 /* Similarly for SBUS. */
 #define sbus_ioremap(__res, __offset, __size, __name) \
 ({	unsigned long __ret; \
@@ -455,11 +471,11 @@ out:
 	__ret += (unsigned long) (__offset); \
 	if (! request_region((__ret), (__size), (__name))) \
 		__ret = 0UL; \
-	__ret; \
+	(void __iomem *) __ret; \
 })
 
 #define sbus_iounmap(__addr, __size)	\
-	release_region((__addr), (__size))
+	release_region((unsigned long)(__addr), (__size))
 
 /* Nothing to do */
 
diff --git a/include/asm-sparc64/kdebug.h b/include/asm-sparc64/kdebug.h
index 65862f7c4..f70d3dad0 100644
--- a/include/asm-sparc64/kdebug.h
+++ b/include/asm-sparc64/kdebug.h
@@ -1,9 +1,52 @@
 #ifndef _SPARC64_KDEBUG_H
 #define _SPARC64_KDEBUG_H
 
-/* 
- * No kernel debugger on sparc64. Kept here because drivers/sbus/char/
- * includes it for sparc32 sake.
+/* Nearly identical to x86_64/i386 code. */
+
+#include <linux/notifier.h>
+
+struct pt_regs;
+
+struct die_args {
+	struct pt_regs *regs;
+	const char *str;
+	long err;
+	int trapnr;
+	int signr;
+};
+
+/* Note - you should never unregister because that can race with NMIs.
+ * If you really want to do it first unregister - then synchronize_kernel
+ * - then free.
  */
+int register_die_notifier(struct notifier_block *nb);
+extern struct notifier_block *sparc64die_chain;
+
+extern void bad_trap(struct pt_regs *, long);
+
+/* Grossly misnamed. */
+enum die_val {
+	DIE_OOPS = 1,
+	DIE_DEBUG,	/* ta 0x70 */
+	DIE_DEBUG_2,	/* ta 0x71 */
+	DIE_DIE,
+	DIE_TRAP,
+	DIE_TRAP_TL1,
+	DIE_GPF,
+	DIE_CALL,
+	DIE_PAGE_FAULT,
+};
+
+static inline int notify_die(enum die_val val,char *str, struct pt_regs *regs,
+			     long err, int trap, int sig)
+{
+	struct die_args args = { .regs		= regs,
+				 .str		= str,
+				 .err		= err,
+				 .trapnr	= trap,
+				 .signr		= sig };
+
+	return notifier_call_chain(&sparc64die_chain, val, &args);
+}
 
 #endif
diff --git a/include/asm-sparc64/parport.h b/include/asm-sparc64/parport.h
index 676f67e3f..ab88349dd 100644
--- a/include/asm-sparc64/parport.h
+++ b/include/asm-sparc64/parport.h
@@ -126,10 +126,14 @@ static int parport_pc_find_nonpci_ports (int autoirq, int autodma)
 			if (ebus_ecpp_p(edev)) {
 				unsigned long base = edev->resource[0].start;
 				unsigned long config = edev->resource[1].start;
+				unsigned long d_base = edev->resource[2].start;
+				unsigned long d_len;
 
 				spin_lock_init(&sparc_ebus_dmas[count].info.lock);
+				d_len = (edev->resource[2].end -
+					 d_base) + 1;
 				sparc_ebus_dmas[count].info.regs =
-					edev->resource[2].start;
+					ioremap(d_base, d_len);
 				if (!sparc_ebus_dmas[count].info.regs)
 					continue;
 				sparc_ebus_dmas[count].info.flags = 0;
diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h
index 0cddbd2bf..92999631c 100644
--- a/include/asm-sparc64/pbm.h
+++ b/include/asm-sparc64/pbm.h
@@ -70,6 +70,13 @@ struct pci_iommu {
 	 */
 	u32		lowest_consistent_map;
 
+	/* In order to deal with some buggy third-party PCI bridges that
+	 * do wrong prefetching, we never mark valid mappings as invalid.
+	 * Instead we point them at this dummy page.
+	 */
+	unsigned long	dummy_page;
+	unsigned long	dummy_page_pa;
+
 	/* If PBM_NCLUSTERS is ever decreased to 4 or lower,
 	 * or if largest supported page_table_sz * 8K goes above
 	 * 2GB, you must increase the size of the type of
@@ -93,6 +100,8 @@ struct pci_iommu {
 	u32 dma_addr_mask;
 };
 
+extern void pci_iommu_table_init(struct pci_iommu *, int);
+
 /* This describes a PCI bus module's streaming buffer. */
 struct pci_strbuf {
 	int		strbuf_enabled;		/* Present and using it? */
diff --git a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h
index c679d2c21..2d2b5a113 100644
--- a/include/asm-sparc64/ptrace.h
+++ b/include/asm-sparc64/ptrace.h
@@ -98,6 +98,11 @@ struct sparc_trapf {
 	set_thread_flag(TIF_SYSCALL_SUCCESS)
 #define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
 #define instruction_pointer(regs) ((regs)->tpc)
+#ifdef CONFIG_SMP
+extern unsigned long profile_pc(struct pt_regs *);
+#else
+#define profile_pc(regs) instruction_pointer(regs)
+#endif
 extern void show_regs(struct pt_regs *);
 #endif
 
diff --git a/include/asm-sparc64/resource.h b/include/asm-sparc64/resource.h
index 4a77dd620..f33d38bcc 100644
--- a/include/asm-sparc64/resource.h
+++ b/include/asm-sparc64/resource.h
@@ -43,7 +43,7 @@
     {       0, RLIM_INFINITY},		\
     {RLIM_INFINITY, RLIM_INFINITY},	\
     {INR_OPEN, INR_OPEN}, {0, 0},	\
-    {RLIM_INFINITY, RLIM_INFINITY},	\
+    {  MLOCK_LIMIT,   MLOCK_LIMIT},	\
     {RLIM_INFINITY, RLIM_INFINITY},	\
     {RLIM_INFINITY, RLIM_INFINITY},	\
     {MAX_SIGPENDING, MAX_SIGPENDING},	\
diff --git a/include/asm-sparc64/sigcontext.h b/include/asm-sparc64/sigcontext.h
index d7128a875..d8073373d 100644
--- a/include/asm-sparc64/sigcontext.h
+++ b/include/asm-sparc64/sigcontext.h
@@ -83,18 +83,6 @@ struct sigcontext {
 	unsigned long		sigc_mask;
 };
 
-#ifdef __KERNEL__
-
-/* This magic should be in g_upper[0] for all upper parts
-   to be valid.  */
-#define SIGINFO_EXTRA_V8PLUS_MAGIC	0x130e269
-typedef struct {
-	unsigned   int g_upper[8];
-	unsigned   int o_upper[8];
-} siginfo_extra_v8plus_t;
-
-#endif
-
 #endif /* !(__ASSEMBLY__) */
 
 #endif /* !(__SPARC64_SIGCONTEXT_H) */
diff --git a/include/asm-sparc64/siginfo.h b/include/asm-sparc64/siginfo.h
index fde85211a..94b272f5d 100644
--- a/include/asm-sparc64/siginfo.h
+++ b/include/asm-sparc64/siginfo.h
@@ -24,57 +24,8 @@ typedef union sigval32 {
 	u32 sival_ptr;
 } sigval_t32;
 
-typedef struct siginfo32 {
-	int si_signo;
-	int si_errno;
-	int si_code;
+struct siginfo32;
 
-	union {
-		int _pad[SI_PAD_SIZE32];
-
-		/* kill() */
-		struct {
-			compat_pid_t _pid;		/* sender's pid */
-			unsigned int _uid;		/* sender's uid */
-		} _kill;
-
-		/* POSIX.1b timers */
-		struct {
-			timer_t _tid;			/* timer id */
-			int _overrun;			/* overrun count */
-			sigval_t32 _sigval;		/* same as below */
-			int _sys_private;		/* not to be passed to user */
-		} _timer;
-
-		/* POSIX.1b signals */
-		struct {
-			compat_pid_t _pid;		/* sender's pid */
-			unsigned int _uid;		/* sender's uid */
-			sigval_t32 _sigval;
-		} _rt;
-
-		/* SIGCHLD */
-		struct {
-			compat_pid_t _pid;		/* which child */
-			unsigned int _uid;		/* sender's uid */
-			int _status;			/* exit code */
-			compat_clock_t _utime;
-			compat_clock_t _stime;
-		} _sigchld;
-
-		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
-		struct {
-			u32 _addr; /* faulting insn/memory ref. */
-			int _trapno;
-		} _sigfault;
-
-		/* SIGPOLL */
-		struct {
-			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
-			int _fd;
-		} _sigpoll;
-	} _sifields;
-} siginfo_t32;
 #endif /* CONFIG_COMPAT */
 
 #endif /* __KERNEL__ */
@@ -105,7 +56,8 @@ typedef struct sigevent32 {
 	} _sigev_un;
 } sigevent_t32;
 
-extern int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from);
+extern int copy_siginfo_to_user32(struct siginfo32 __user *to, siginfo_t *from);
+extern int copy_siginfo_to_kernel32(siginfo_t *to, struct siginfo32 __user *from);
 
 #endif /* CONFIG_COMPAT */
 
diff --git a/include/asm-sparc64/socket.h b/include/asm-sparc64/socket.h
index ba2230ba1..865547a23 100644
--- a/include/asm-sparc64/socket.h
+++ b/include/asm-sparc64/socket.h
@@ -52,20 +52,4 @@
 #define SO_SECURITY_ENCRYPTION_TRANSPORT	0x5002
 #define SO_SECURITY_ENCRYPTION_NETWORK		0x5004
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-sparc64/spinlock.h b/include/asm-sparc64/spinlock.h
index a995805ba..fb7c5b0ea 100644
--- a/include/asm-sparc64/spinlock.h
+++ b/include/asm-sparc64/spinlock.h
@@ -41,30 +41,70 @@ typedef unsigned char spinlock_t;
 do {	membar("#LoadLoad");	\
 } while(*((volatile unsigned char *)lock))
 
-/* arch/sparc64/lib/spinlock.S */
-extern void _raw_spin_lock(spinlock_t *lock);
+static inline void _raw_spin_lock(spinlock_t *lock)
+{
+	unsigned long tmp;
+
+	__asm__ __volatile__(
+"1:	ldstub		[%1], %0\n"
+"	brnz,pn		%0, 2f\n"
+"	 membar		#StoreLoad | #StoreStore\n"
+"	.subsection	2\n"
+"2:	ldub		[%1], %0\n"
+"	brnz,pt		%0, 2b\n"
+"	 membar		#LoadLoad\n"
+"	ba,a,pt		%%xcc, 1b\n"
+"	.previous"
+	: "=&r" (tmp)
+	: "r" (lock)
+	: "memory");
+}
 
-static __inline__ int _raw_spin_trylock(spinlock_t *lock)
+static inline int _raw_spin_trylock(spinlock_t *lock)
 {
-	unsigned int result;
-	__asm__ __volatile__("ldstub [%1], %0\n\t"
-			     "membar #StoreLoad | #StoreStore"
-			     : "=r" (result)
-			     : "r" (lock)
-			     : "memory");
-	return (result == 0);
+	unsigned long result;
+
+	__asm__ __volatile__(
+"	ldstub		[%1], %0\n"
+"	membar		#StoreLoad | #StoreStore"
+	: "=r" (result)
+	: "r" (lock)
+	: "memory");
+
+	return (result == 0UL);
 }
 
-static __inline__ void _raw_spin_unlock(spinlock_t *lock)
+static inline void _raw_spin_unlock(spinlock_t *lock)
 {
-	__asm__ __volatile__("membar	#StoreStore | #LoadStore\n\t"
-			     "stb	%%g0, [%0]"
-			     : /* No outputs */
-			     : "r" (lock)
-			     : "memory");
+	__asm__ __volatile__(
+"	membar		#StoreStore | #LoadStore\n"
+"	stb		%%g0, [%0]"
+	: /* No outputs */
+	: "r" (lock)
+	: "memory");
 }
 
-extern void _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags);
+static inline void _raw_spin_lock_flags(spinlock_t *lock, unsigned long flags)
+{
+	unsigned long tmp1, tmp2;
+
+	__asm__ __volatile__(
+"1:	ldstub		[%2], %0\n"
+"	brnz,pn		%0, 2f\n"
+"	membar		#StoreLoad | #StoreStore\n"
+"	.subsection	2\n"
+"2:	rdpr		%%pil, %1\n"
+"	wrpr		%3, %%pil\n"
+"3:	ldub		[%2], %0\n"
+"	brnz,pt		%0, 3b\n"
+"	membar		#LoadLoad\n"
+"	ba,pt		%%xcc, 1b\n"
+"	wrpr		%1, %%pil\n"
+"	.previous"
+	: "=&r" (tmp1), "=&r" (tmp2)
+	: "r"(lock), "r"(flags)
+	: "memory");
+}
 
 #else /* !(CONFIG_DEBUG_SPINLOCK) */
 
@@ -86,9 +126,9 @@ do { \
 
 extern void _do_spin_lock (spinlock_t *lock, char *str);
 extern void _do_spin_unlock (spinlock_t *lock);
-extern int _spin_trylock (spinlock_t *lock);
+extern int _do_spin_trylock (spinlock_t *lock);
 
-#define _raw_spin_trylock(lp)	_spin_trylock(lp)
+#define _raw_spin_trylock(lp)	_do_spin_trylock(lp)
 #define _raw_spin_lock(lock)	_do_spin_lock(lock, "spin_lock")
 #define _raw_spin_unlock(lock)	_do_spin_unlock(lock)
 #define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
@@ -104,11 +144,103 @@ typedef unsigned int rwlock_t;
 #define rwlock_init(lp) do { *(lp) = RW_LOCK_UNLOCKED; } while(0)
 #define rwlock_is_locked(x) (*(x) != RW_LOCK_UNLOCKED)
 
-extern void __read_lock(rwlock_t *);
-extern void __read_unlock(rwlock_t *);
-extern void __write_lock(rwlock_t *);
-extern void __write_unlock(rwlock_t *);
-extern int __write_trylock(rwlock_t *);
+static void inline __read_lock(rwlock_t *lock)
+{
+	unsigned long tmp1, tmp2;
+
+	__asm__ __volatile__ (
+"1:	ldsw		[%2], %0\n"
+"	brlz,pn		%0, 2f\n"
+"4:	 add		%0, 1, %1\n"
+"	cas		[%2], %0, %1\n"
+"	cmp		%0, %1\n"
+"	bne,pn		%%icc, 1b\n"
+"	 membar		#StoreLoad | #StoreStore\n"
+"	.subsection	2\n"
+"2:	ldsw		[%2], %0\n"
+"	brlz,pt		%0, 2b\n"
+"	 membar		#LoadLoad\n"
+"	ba,a,pt		%%xcc, 4b\n"
+"	.previous"
+	: "=&r" (tmp1), "=&r" (tmp2)
+	: "r" (lock)
+	: "memory");
+}
+
+static void inline __read_unlock(rwlock_t *lock)
+{
+	unsigned long tmp1, tmp2;
+
+	__asm__ __volatile__(
+"1:	lduw	[%2], %0\n"
+"	sub	%0, 1, %1\n"
+"	cas	[%2], %0, %1\n"
+"	cmp	%0, %1\n"
+"	bne,pn	%%xcc, 1b\n"
+"	 membar	#StoreLoad | #StoreStore"
+	: "=&r" (tmp1), "=&r" (tmp2)
+	: "r" (lock)
+	: "memory");
+}
+
+static void inline __write_lock(rwlock_t *lock)
+{
+	unsigned long mask, tmp1, tmp2;
+
+	mask = 0x80000000UL;
+
+	__asm__ __volatile__(
+"1:	lduw		[%2], %0\n"
+"	brnz,pn		%0, 2f\n"
+"4:	 or		%0, %3, %1\n"
+"	cas		[%2], %0, %1\n"
+"	cmp		%0, %1\n"
+"	bne,pn		%%icc, 1b\n"
+"	 membar		#StoreLoad | #StoreStore\n"
+"	.subsection	2\n"
+"2:	lduw		[%2], %0\n"
+"	brnz,pt		%0, 2b\n"
+"	 membar		#LoadLoad\n"
+"	ba,a,pt		%%xcc, 4b\n"
+"	.previous"
+	: "=&r" (tmp1), "=&r" (tmp2)
+	: "r" (lock), "r" (mask)
+	: "memory");
+}
+
+static void inline __write_unlock(rwlock_t *lock)
+{
+	__asm__ __volatile__(
+"	membar		#LoadStore | #StoreStore\n"
+"	stw		%%g0, [%0]"
+	: /* no outputs */
+	: "r" (lock)
+	: "memory");
+}
+
+static int inline __write_trylock(rwlock_t *lock)
+{
+	unsigned long mask, tmp1, tmp2, result;
+
+	mask = 0x80000000UL;
+
+	__asm__ __volatile__(
+"	mov		0, %2\n"
+"1:	lduw		[%3], %0\n"
+"	brnz,pn		%0, 2f\n"
+"	 or		%0, %4, %1\n"
+"	cas		[%3], %0, %1\n"
+"	cmp		%0, %1\n"
+"	bne,pn		%%icc, 1b\n"
+"	 membar		#StoreLoad | #StoreStore\n"
+"	mov		1, %2\n"
+"2:"
+	: "=&r" (tmp1), "=&r" (tmp2), "=&r" (result)
+	: "r" (lock), "r" (mask)
+	: "memory");
+
+	return result;
+}
 
 #define _raw_read_lock(p)	__read_lock(p)
 #define _raw_read_unlock(p)	__read_unlock(p)
diff --git a/include/asm-sparc64/string.h b/include/asm-sparc64/string.h
index c1a4f1df8..c7d88622c 100644
--- a/include/asm-sparc64/string.h
+++ b/include/asm-sparc64/string.h
@@ -15,35 +15,25 @@
 
 #include <asm/asi.h>
 
-extern void __memmove(void *,const void *,__kernel_size_t);
 extern void *__memset(void *,int,__kernel_size_t);
-extern void *__builtin_memset(void *,int,__kernel_size_t);
 
 #ifndef EXPORT_SYMTAB_STROPS
 
 /* First the mem*() things. */
-#define __HAVE_ARCH_BCOPY
 #define __HAVE_ARCH_MEMMOVE
-
-#undef memmove
-#define memmove(_to, _from, _n) \
-({ \
-	void *_t = (_to); \
-	__memmove(_t, (_from), (_n)); \
-	_t; \
-})
+extern void *memmove(void *, const void *, __kernel_size_t);
 
 #define __HAVE_ARCH_MEMCPY
-
-extern void * memcpy(void *,const void *,__kernel_size_t);
+extern void *memcpy(void *, const void *, __kernel_size_t);
 
 #define __HAVE_ARCH_MEMSET
+extern void *__builtin_memset(void *,int,__kernel_size_t);
 
 static inline void *__constant_memset(void *s, int c, __kernel_size_t count)
 {
 	extern __kernel_size_t __bzero(void *, __kernel_size_t);
 
-	if(!c) {
+	if (!c) {
 		__bzero(s, count);
 		return s;
 	} else
@@ -61,19 +51,19 @@ static inline void *__constant_memset(void *s, int c, __kernel_size_t count)
 #define __HAVE_ARCH_MEMSCAN
 
 #undef memscan
-#define memscan(__arg0, __char, __arg2)						\
-({										\
-	extern void *__memscan_zero(void *, size_t);				\
-	extern void *__memscan_generic(void *, int, size_t);			\
-	void *__retval, *__addr = (__arg0);					\
-	size_t __size = (__arg2);						\
-										\
-	if(__builtin_constant_p(__char) && !(__char))				\
-		__retval = __memscan_zero(__addr, __size);			\
-	else									\
-		__retval = __memscan_generic(__addr, (__char), __size);		\
-										\
-	__retval;								\
+#define memscan(__arg0, __char, __arg2)					\
+({									\
+	extern void *__memscan_zero(void *, size_t);			\
+	extern void *__memscan_generic(void *, int, size_t);		\
+	void *__retval, *__addr = (__arg0);				\
+	size_t __size = (__arg2);					\
+									\
+	if(__builtin_constant_p(__char) && !(__char))			\
+		__retval = __memscan_zero(__addr, __size);		\
+	else								\
+		__retval = __memscan_generic(__addr, (__char), __size);	\
+									\
+	__retval;							\
 })
 
 #define __HAVE_ARCH_MEMCMP
@@ -81,73 +71,10 @@ extern int memcmp(const void *,const void *,__kernel_size_t);
 
 /* Now the str*() stuff... */
 #define __HAVE_ARCH_STRLEN
-
-extern __kernel_size_t __strlen(const char *);
 extern __kernel_size_t strlen(const char *);
 
 #define __HAVE_ARCH_STRNCMP
-
-extern int __strncmp(const char *, const char *, __kernel_size_t);
-
-static inline int __constant_strncmp(const char *src, const char *dest, __kernel_size_t count)
-{
-	register int retval;
-	switch(count) {
-	case 0: return 0;
-	case 1: return (src[0] - dest[0]);
-	case 2: retval = (src[0] - dest[0]);
-		if(!retval && src[0])
-		  retval = (src[1] - dest[1]);
-		return retval;
-	case 3: retval = (src[0] - dest[0]);
-		if(!retval && src[0]) {
-		  retval = (src[1] - dest[1]);
-		  if(!retval && src[1])
-		    retval = (src[2] - dest[2]);
-		}
-		return retval;
-	case 4: retval = (src[0] - dest[0]);
-		if(!retval && src[0]) {
-		  retval = (src[1] - dest[1]);
-		  if(!retval && src[1]) {
-		    retval = (src[2] - dest[2]);
-		    if (!retval && src[2])
-		      retval = (src[3] - dest[3]);
-		  }
-		}
-		return retval;
-	case 5: retval = (src[0] - dest[0]);
-		if(!retval && src[0]) {
-		  retval = (src[1] - dest[1]);
-		  if(!retval && src[1]) {
-		    retval = (src[2] - dest[2]);
-		    if (!retval && src[2]) {
-		      retval = (src[3] - dest[3]);
-		      if (!retval && src[3])
-		        retval = (src[4] - dest[4]);
-		    }
-		  }
-		}
-		return retval;
-	default:
-		retval = (src[0] - dest[0]);
-		if(!retval && src[0]) {
-		  retval = (src[1] - dest[1]);
-		  if(!retval && src[1]) {
-		    retval = (src[2] - dest[2]);
-		    if(!retval && src[2])
-		      retval = __strncmp(src+3,dest+3,count-3);
-		  }
-		}
-		return retval;
-	}
-}
-
-#undef strncmp
-#define strncmp(__arg0, __arg1, __arg2)	\
-(__builtin_constant_p(__arg2) ?	\
- __constant_strncmp(__arg0, __arg1, __arg2) : \
- __strncmp(__arg0, __arg1, __arg2))
+extern int strncmp(const char *, const char *, __kernel_size_t);
 
 #endif /* !EXPORT_SYMTAB_STROPS */
 
diff --git a/include/asm-sparc64/tlb.h b/include/asm-sparc64/tlb.h
index 874a46373..d224b21bc 100644
--- a/include/asm-sparc64/tlb.h
+++ b/include/asm-sparc64/tlb.h
@@ -3,6 +3,8 @@
 
 #include <linux/config.h>
 #include <linux/swap.h>
+#include <linux/vs_memory.h>
+
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/mmu_context.h>
diff --git a/include/asm-sparc64/ttable.h b/include/asm-sparc64/ttable.h
index 2b454ef67..2784f8009 100644
--- a/include/asm-sparc64/ttable.h
+++ b/include/asm-sparc64/ttable.h
@@ -176,6 +176,12 @@
 	ba,pt	%xcc, rtrap_clr_l6;					\
 	 stx	%l2, [%sp + PTREGS_OFF + PT_V9_TNPC];
 	        
+#ifdef CONFIG_KPROBES
+#define KPROBES_TRAP(lvl) TRAP_IRQ(kprobe_trap, lvl)
+#else
+#define KPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
+#endif
+
 /* Before touching these macros, you owe it to yourself to go and
  * see how arch/sparc64/kernel/winfixup.S works... -DaveM
  *
diff --git a/include/asm-sparc64/uaccess.h b/include/asm-sparc64/uaccess.h
index e1ce87c86..1aff19cd0 100644
--- a/include/asm-sparc64/uaccess.h
+++ b/include/asm-sparc64/uaccess.h
@@ -14,6 +14,7 @@
 #include <asm/asi.h>
 #include <asm/system.h>
 #include <asm/spitfire.h>
+#include <asm-generic/uaccess.h>
 #endif
 
 #ifndef __ASSEMBLY__
@@ -252,18 +253,50 @@ __asm__ __volatile__(							\
 
 extern int __get_user_bad(void);
 
-extern unsigned long __copy_from_user(void *to, const void __user *from,
-				      unsigned long size);
+extern unsigned long ___copy_from_user(void *to, const void __user *from,
+				       unsigned long size);
+extern unsigned long copy_from_user_fixup(void *to, const void __user *from,
+					  unsigned long size);
+static inline unsigned long copy_from_user(void *to, const void __user *from,
+					   unsigned long size)
+{
+	unsigned long ret = ___copy_from_user(to, from, size);
 
-extern unsigned long __copy_to_user(void __user *to, const void *from,
-				    unsigned long size);
+	if (ret)
+		ret = copy_from_user_fixup(to, from, size);
+	return ret;
+}
+#define __copy_from_user copy_from_user
+
+extern unsigned long ___copy_to_user(void __user *to, const void *from,
+				     unsigned long size);
+extern unsigned long copy_to_user_fixup(void __user *to, const void *from,
+					unsigned long size);
+static inline unsigned long copy_to_user(void __user *to, const void *from,
+					 unsigned long size)
+{
+	unsigned long ret = ___copy_to_user(to, from, size);
 
-extern unsigned long __copy_in_user(void __user *to, const void __user *from,
-				    unsigned long size);
+	if (ret)
+		ret = copy_to_user_fixup(to, from, size);
+	return ret;
+}
+#define __copy_to_user copy_to_user
+
+extern unsigned long ___copy_in_user(void __user *to, const void __user *from,
+				     unsigned long size);
+extern unsigned long copy_in_user_fixup(void __user *to, void __user *from,
+					unsigned long size);
+static inline unsigned long copy_in_user(void __user *to, void __user *from,
+					 unsigned long size)
+{
+	unsigned long ret = ___copy_in_user(to, from, size);
 
-#define copy_from_user __copy_from_user
-#define copy_to_user __copy_to_user
-#define copy_in_user __copy_in_user
+	if (ret)
+		ret = copy_in_user_fixup(to, from, size);
+	return ret;
+}
+#define __copy_in_user copy_in_user
 
 extern unsigned long __bzero_noasi(void __user *, unsigned long);
 
@@ -284,6 +317,8 @@ extern long __strnlen_user(const char __user *, long len);
 
 #define strlen_user __strlen_user
 #define strnlen_user __strnlen_user
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
 
 #endif  /* __ASSEMBLY__ */
 
diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
index 0a06763b8..df2430bee 100644
--- a/include/asm-sparc64/unistd.h
+++ b/include/asm-sparc64/unistd.h
@@ -292,11 +292,13 @@
 #define __NR_io_cancel		271
 #define __NR_io_getevents	272
 #define __NR_mq_open		273
-#define __NR_mq_unlink		(__NR_mq_open+1)
-#define __NR_mq_timedsend	(__NR_mq_open+2)
-#define __NR_mq_timedreceive	(__NR_mq_open+3)
-#define __NR_mq_notify		(__NR_mq_open+4)
-#define __NR_mq_getsetattr	(__NR_mq_open+5)
+#define __NR_mq_unlink		274
+#define __NR_mq_timedsend	275
+#define __NR_mq_timedreceive	276
+#define __NR_mq_notify		277
+#define __NR_mq_getsetattr	278
+#define __NR_waitid		279
+
 /* WARNING: You MAY NOT add syscall numbers larger than 282, since
  *          all of the syscall tables in the Sparc kernel are
  *          sized to have 283 entries (starting at zero).  Therefore
diff --git a/include/asm-sparc64/vga.h b/include/asm-sparc64/vga.h
index c2f5529c5..9c57eb363 100644
--- a/include/asm-sparc64/vga.h
+++ b/include/asm-sparc64/vga.h
@@ -11,6 +11,9 @@
 
 #define VT_BUF_HAVE_RW
 
+#undef scr_writew
+#undef scr_readw
+
 static inline void scr_writew(u16 val, u16 *addr)
 {
 	BUG_ON((long) addr >= 0);
diff --git a/include/asm-um/archparam-i386.h b/include/asm-um/archparam-i386.h
index a23261baa..85fd03358 100644
--- a/include/asm-um/archparam-i386.h
+++ b/include/asm-um/archparam-i386.h
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Licensed under the GPL
  */
 
@@ -56,6 +56,93 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 	pr_reg[16] = PT_REGS_SS(regs);		\
 } while(0);
 
+#if 0 /* Turn this back on when UML has VSYSCALL working */
+#define VSYSCALL_BASE	(__fix_to_virt(FIX_VSYSCALL))
+#else
+#define VSYSCALL_BASE	0
+#endif
+
+#define VSYSCALL_EHDR	((const struct elfhdr *) VSYSCALL_BASE)
+#define VSYSCALL_ENTRY	((unsigned long) &__kernel_vsyscall)
+extern void *__kernel_vsyscall;
+
+/*
+ * Architecture-neutral AT_ values in 0-17, leave some room
+ * for more of them, start the x86-specific ones at 32.
+ */
+#define AT_SYSINFO		32
+#define AT_SYSINFO_EHDR		33
+
+#define ARCH_DLINFO						\
+do {								\
+		NEW_AUX_ENT(AT_SYSINFO,	VSYSCALL_ENTRY);	\
+		NEW_AUX_ENT(AT_SYSINFO_EHDR, VSYSCALL_BASE);	\
+} while (0)
+
+/*
+ * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out
+ * extra segments containing the vsyscall DSO contents.  Dumping its
+ * contents makes post-mortem fully interpretable later without matching up
+ * the same kernel and hardware config to see what PC values meant.
+ * Dumping its extra ELF program headers includes all the other information
+ * a debugger needs to easily find how the vsyscall DSO was being used.
+ */
+#if 0
+#define ELF_CORE_EXTRA_PHDRS		(VSYSCALL_EHDR->e_phnum)
+#endif
+
+#undef ELF_CORE_EXTRA_PHDRS
+
+#if 0
+#define ELF_CORE_WRITE_EXTRA_PHDRS					      \
+do {									      \
+	const struct elf_phdr *const vsyscall_phdrs =			      \
+		(const struct elf_phdr *) (VSYSCALL_BASE		      \
+					   + VSYSCALL_EHDR->e_phoff);	      \
+	int i;								      \
+	Elf32_Off ofs = 0;						      \
+	for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) {			      \
+		struct elf_phdr phdr = vsyscall_phdrs[i];		      \
+		if (phdr.p_type == PT_LOAD) {				      \
+			ofs = phdr.p_offset = offset;			      \
+			offset += phdr.p_filesz;			      \
+		}							      \
+		else							      \
+			phdr.p_offset += ofs;				      \
+		phdr.p_paddr = 0; /* match other core phdrs */		      \
+		DUMP_WRITE(&phdr, sizeof(phdr));			      \
+	}								      \
+} while (0)
+#define ELF_CORE_WRITE_EXTRA_DATA					      \
+do {									      \
+	const struct elf_phdr *const vsyscall_phdrs =			      \
+		(const struct elf_phdr *) (VSYSCALL_BASE		      \
+					   + VSYSCALL_EHDR->e_phoff);	      \
+	int i;								      \
+	for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) {			      \
+		if (vsyscall_phdrs[i].p_type == PT_LOAD)		      \
+			DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr,	      \
+				   vsyscall_phdrs[i].p_filesz);		      \
+	}								      \
+} while (0)
+#endif
+
+#undef ELF_CORE_WRITE_EXTRA_PHDRS
+#undef ELF_CORE_WRITE_EXTRA_DATA
+
+#define R_386_NONE	0
+#define R_386_32	1
+#define R_386_PC32	2
+#define R_386_GOT32	3
+#define R_386_PLT32	4
+#define R_386_COPY	5
+#define R_386_GLOB_DAT	6
+#define R_386_JMP_SLOT	7
+#define R_386_RELATIVE	8
+#define R_386_GOTOFF	9
+#define R_386_GOTPC	10
+#define R_386_NUM	11
+
 /********* Bits for asm-um/delay.h **********/
 
 typedef unsigned long um_udelay_t;
diff --git a/include/asm-um/bug.h b/include/asm-um/bug.h
index f5836c5ae..1e22fa26f 100644
--- a/include/asm-um/bug.h
+++ b/include/asm-um/bug.h
@@ -1,30 +1,4 @@
 #ifndef __UM_BUG_H
 #define __UM_BUG_H
-
-#ifndef __ASSEMBLY__
-
-#define BUG() do { \
-	panic("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
-} while (0)
-
-#define BUG_ON(condition) do { \
-	if (unlikely((condition)!=0)) \
-		BUG(); \
-} while(0)
-
-#define PAGE_BUG(page) do { \
-	BUG(); \
-} while (0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
-
-extern int foo;
-
-#endif
-
+#include <asm-generic/bug.h>
 #endif
diff --git a/include/asm-um/common.lds.S b/include/asm-um/common.lds.S
index d2517a04c..a3d6aab0e 100644
--- a/include/asm-um/common.lds.S
+++ b/include/asm-um/common.lds.S
@@ -1,3 +1,5 @@
+#include <asm-generic/vmlinux.lds.h>
+
   .fini      : { *(.fini)    } =0x9090
   _etext = .;
   PROVIDE (etext = .);
@@ -13,18 +15,6 @@
 
   RODATA
 
-  __start___ksymtab = .;	/* Kernel symbol table */
-  __ksymtab : { *(__ksymtab) }
-  __stop___ksymtab = .;
-
-  __start___gpl_ksymtab = .;	/* Kernel symbol table:	GPL-only symbols */
-  __gpl_ksymtab : { *(__gpl_ksymtab) }
-  __stop___gpl_ksymtab = .;
-
-  __start___kallsyms = .;       /* All kernel symbols */
-  __kallsyms : { *(__kallsyms) }
-  __stop___kallsyms = .;
-
   .unprotected : { *(.unprotected) }
   . = ALIGN(4096);
   PROVIDE (_unprotected_end = .);
@@ -46,10 +36,6 @@
   .init.setup : { *(.init.setup) }
   __setup_end = .;
 
-  __start___param = .;
-  __param : { *(__param) }
-  __stop___param = .;
-
   . = ALIGN(32);
   __per_cpu_start = . ; 
   .data.percpu : { *(.data.percpu) }
@@ -67,11 +53,17 @@
   }
   __initcall_end = .;
 
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
+
   __uml_initcall_start = .;
   .uml.initcall.init : { *(.uml.initcall.init) }
   __uml_initcall_end = .;
   __init_end = .;
 
+  SECURITY_INIT
+
   __exitcall_begin = .;
   .exitcall : { *(.exitcall.exit) }
   __exitcall_end = .;
@@ -80,7 +72,33 @@
   .uml.exitcall : { *(.uml.exitcall.exit) }
   __uml_exitcall_end = .;
 
-  . = ALIGN(4096);
+  . = ALIGN(4);
+  __alt_instructions = .;
+  .altinstructions : { *(.altinstructions) }
+  __alt_instructions_end = .;
+  .altinstr_replacement : { *(.altinstr_replacement) }
+  /* .exit.text is discard at runtime, not link time, to deal with references
+     from .altinstructions and .eh_frame */
+  .exit.text : { *(.exit.text) }
+  .exit.data : { *(.exit.data) }
+
+  __preinit_array_start = .;
+  .preinit_array : { *(.preinit_array) }
+  __preinit_array_end = .;
+  __init_array_start = .;
+  .init_array : { *(.init_array) }
+  __init_array_end = .;
+  __fini_array_start = .;
+  .fini_array : { *(.fini_array) }
+  __fini_array_end = .;
+
+   . = ALIGN(4096);
   __initramfs_start = .;
   .init.ramfs : { *(.init.ramfs) }
   __initramfs_end = .;
+
+  /* Sections to be discarded */
+  /DISCARD/ : {
+ 	*(.exitcall.exit)
+  }
+
diff --git a/include/asm-um/current.h b/include/asm-um/current.h
index adfe568cf..72a4cbd91 100644
--- a/include/asm-um/current.h
+++ b/include/asm-um/current.h
@@ -16,8 +16,10 @@ struct thread_info;
 #define CURRENT_THREAD(dummy) (((unsigned long) &dummy) & \
 			        (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER))
 
-#define current ({ int dummy; \
-                   ((struct thread_info *) CURRENT_THREAD(dummy))->task; })
+#define current_thread \
+	({ int dummy; ((struct thread_info *) CURRENT_THREAD(dummy)); })
+
+#define current (current_thread->task)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/include/asm-um/dma-mapping.h b/include/asm-um/dma-mapping.h
index e7e16901f..13e6291f7 100644
--- a/include/asm-um/dma-mapping.h
+++ b/include/asm-um/dma-mapping.h
@@ -1 +1,121 @@
-#include <asm-generic/dma-mapping.h>
+#ifndef _ASM_DMA_MAPPING_H
+#define _ASM_DMA_MAPPING_H
+
+#include <asm/scatterlist.h>
+
+static inline int
+dma_supported(struct device *dev, u64 mask)
+{
+	BUG();
+	return(0);
+}
+
+static inline int
+dma_set_mask(struct device *dev, u64 dma_mask)
+{
+	BUG();
+	return(0);
+}
+
+static inline void *
+dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+		   int flag)
+{
+	BUG();
+	return((void *) 0);
+}
+
+static inline void
+dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
+		  dma_addr_t dma_handle)
+{
+	BUG();
+}
+
+static inline dma_addr_t
+dma_map_single(struct device *dev, void *cpu_addr, size_t size,
+	       enum dma_data_direction direction)
+{
+	BUG();
+	return(0);
+}
+
+static inline void
+dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+		 enum dma_data_direction direction)
+{
+	BUG();
+}
+
+static inline dma_addr_t
+dma_map_page(struct device *dev, struct page *page,
+	     unsigned long offset, size_t size,
+	     enum dma_data_direction direction)
+{
+	BUG();
+	return(0);
+}
+
+static inline void
+dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+	       enum dma_data_direction direction)
+{
+	BUG();
+}
+
+static inline int
+dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+	   enum dma_data_direction direction)
+{
+	BUG();
+	return(0);
+}
+
+static inline void
+dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+	     enum dma_data_direction direction)
+{
+	BUG();
+}
+
+static inline void
+dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size,
+		enum dma_data_direction direction)
+{
+	BUG();
+}
+
+static inline void
+dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems,
+	    enum dma_data_direction direction)
+{
+	BUG();
+}
+
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+#define dma_is_consistent(d) (1)
+
+static inline int
+dma_get_cache_alignment(void)
+{
+	BUG();
+	return(0);
+}
+
+static inline void
+dma_sync_single_range(struct device *dev, dma_addr_t dma_handle,
+		      unsigned long offset, size_t size,
+		      enum dma_data_direction direction)
+{
+	BUG();
+}
+
+static inline void
+dma_cache_sync(void *vaddr, size_t size,
+	       enum dma_data_direction direction)
+{
+	BUG();
+}
+
+#endif
diff --git a/include/asm-um/elf.h b/include/asm-um/elf.h
index f33a3533f..c96c5eb92 100644
--- a/include/asm-um/elf.h
+++ b/include/asm-um/elf.h
@@ -15,4 +15,17 @@
 
 #define USE_ELF_CORE_DUMP
 
+#define R_386_NONE	0
+#define R_386_32	1
+#define R_386_PC32	2
+#define R_386_GOT32	3
+#define R_386_PLT32	4
+#define R_386_COPY	5
+#define R_386_GLOB_DAT	6
+#define R_386_JMP_SLOT	7
+#define R_386_RELATIVE	8
+#define R_386_GOTOFF	9
+#define R_386_GOTPC	10
+#define R_386_NUM	11
+
 #endif
diff --git a/include/asm-um/fixmap.h b/include/asm-um/fixmap.h
index 0e8a4c1ac..ef4890b11 100644
--- a/include/asm-um/fixmap.h
+++ b/include/asm-um/fixmap.h
@@ -34,6 +34,7 @@ enum fixed_addresses {
 	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
 	FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
 #endif
+	FIX_VSYSCALL,
 	__end_of_fixed_addresses
 };
 
@@ -63,6 +64,13 @@ extern unsigned long get_kmem_end(void);
 #define __fix_to_virt(x)	(FIXADDR_TOP - ((x) << PAGE_SHIFT))
 #define __virt_to_fix(x)      ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
 
+/*
+ * This is the range that is readable by user mode, and things
+ * acting like user mode such as get_user_pages.
+ */
+#define FIXADDR_USER_START	(__fix_to_virt(FIX_VSYSCALL))
+#define FIXADDR_USER_END	(FIXADDR_USER_START + PAGE_SIZE)
+
 extern void __this_fixmap_does_not_exist(void);
 
 /*
diff --git a/include/asm-um/irq.h b/include/asm-um/irq.h
index 8300c209a..de389a477 100644
--- a/include/asm-um/irq.h
+++ b/include/asm-um/irq.h
@@ -1,15 +1,6 @@
 #ifndef __UM_IRQ_H
 #define __UM_IRQ_H
 
-/* The i386 irq.h has a struct task_struct in a prototype without including
- * sched.h.  This forward declaration kills the resulting warning.
- */
-struct task_struct;
-
-#include "asm/ptrace.h"
-
-#undef NR_IRQS
-
 #define TIMER_IRQ		0
 #define UMN_IRQ			1
 #define CONSOLE_IRQ		2
@@ -28,13 +19,4 @@ struct task_struct;
 #define LAST_IRQ XTERM_IRQ
 #define NR_IRQS (LAST_IRQ + 1)
 
-extern int um_request_irq(unsigned int irq, int fd, int type,
-			  void (*handler)(int, void *, struct pt_regs *),
-			  unsigned long irqflags,  const char * devname,
-			  void *dev_id);
-
-struct irqaction;
-struct pt_regs;
-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-
 #endif
diff --git a/include/asm-um/mmu_context.h b/include/asm-um/mmu_context.h
index 4ddffc1a7..89bff310b 100644
--- a/include/asm-um/mmu_context.h
+++ b/include/asm-um/mmu_context.h
@@ -26,8 +26,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 	unsigned cpu = smp_processor_id();
 
 	if(prev != next){
-		clear_bit(cpu, &prev->cpu_vm_mask);
-		set_bit(cpu, &next->cpu_vm_mask);
+		cpu_clear(cpu, prev->cpu_vm_mask);
+		cpu_set(cpu, next->cpu_vm_mask);
 		if(next != &init_mm)
 			CHOOSE_MODE((void) 0, 
 				    switch_mm_skas(next->context.skas.mm_fd));
diff --git a/include/asm-um/page.h b/include/asm-um/page.h
index ad97bc0a6..f69b0f1c2 100644
--- a/include/asm-um/page.h
+++ b/include/asm-um/page.h
@@ -1,10 +1,14 @@
+/*
+ *  Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
 #ifndef __UM_PAGE_H
 #define __UM_PAGE_H
 
 struct page;
 
 #include "asm/arch/page.h"
-#include "asm/bug.h"
 
 #undef __pa
 #undef __va
@@ -24,25 +28,25 @@ extern unsigned long uml_physmem;
 
 #define __va_space (8*1024*1024)
 
-extern unsigned long region_pa(void *virt);
-extern void *region_va(unsigned long phys);
-
-#define __pa(virt) region_pa((void *) (virt))
-#define __va(phys) region_va((unsigned long) (phys))
-
-extern unsigned long page_to_pfn(struct page *page);
-extern struct page *pfn_to_page(unsigned long pfn);
+extern unsigned long to_phys(void *virt);
+extern void *to_virt(unsigned long phys);
 
-extern struct page *phys_to_page(unsigned long phys);
+#define __pa(virt) to_phys((void *) virt)
+#define __va(phys) to_virt((unsigned long) phys)
 
-#define virt_to_page(v) (phys_to_page(__pa(v)))
+#define page_to_pfn(page) ((page) - mem_map)
+#define pfn_to_page(pfn) (mem_map + (pfn))
 
-extern struct page *page_mem_map(struct page *page);
-
-#define pfn_valid(pfn) (page_mem_map(pfn_to_page(pfn)) != NULL)
-#define virt_addr_valid(v) pfn_valid(__pa(v) >> PAGE_SHIFT)
+#define phys_to_pfn(p) ((p) >> PAGE_SHIFT)
+#define pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT)
 
+#define pfn_valid(pfn) ((pfn) < max_mapnr)
+#define virt_addr_valid(v) pfn_valid(phys_to_pfn(__pa(v)))
+  
 extern struct page *arch_validate(struct page *page, int mask, int order);
 #define HAVE_ARCH_VALIDATE
 
+extern void arch_free_page(struct page *page, int order);
+#define HAVE_ARCH_FREE_PAGE
+
 #endif
diff --git a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h
index 148dd8e42..d013cc376 100644
--- a/include/asm-um/pgtable.h
+++ b/include/asm-um/pgtable.h
@@ -12,8 +12,6 @@
 #include "asm/page.h"
 #include "asm/fixmap.h"
 
-extern pgd_t swapper_pg_dir[1024];
-
 extern void *um_virt_to_phys(struct task_struct *task, unsigned long virt,
 			     pte_t *pte_out);
 
@@ -49,6 +47,8 @@ extern unsigned long *empty_zero_page;
 #define pgd_ERROR(e) \
         printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
 
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
 /*
  * pgd entries used up by user/kernel:
  */
@@ -65,10 +65,10 @@ extern unsigned long *empty_zero_page;
  * area for the same reason. ;)
  */
 
-extern unsigned long high_physmem;
+extern unsigned long end_iomem;
 
 #define VMALLOC_OFFSET	(__va_space)
-#define VMALLOC_START	(((unsigned long) high_physmem + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_START	((end_iomem + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 
 #ifdef CONFIG_HIGHMEM
 # define VMALLOC_END	(PKMAP_BASE-2*PAGE_SIZE)
@@ -78,12 +78,13 @@ extern unsigned long high_physmem;
 
 #define _PAGE_PRESENT	0x001
 #define _PAGE_NEWPAGE	0x002
-#define _PAGE_PROTNONE	0x004	/* If not present */
-#define _PAGE_RW	0x008
-#define _PAGE_USER	0x010
-#define _PAGE_ACCESSED	0x020
-#define _PAGE_DIRTY	0x040
-#define _PAGE_NEWPROT   0x080
+#define _PAGE_NEWPROT   0x004
+#define _PAGE_FILE	0x008   /* set:pagecache unset:swap */
+#define _PAGE_PROTNONE	0x010	/* If not present */
+#define _PAGE_RW	0x020
+#define _PAGE_USER	0x040
+#define _PAGE_ACCESSED	0x080
+#define _PAGE_DIRTY	0x100
 
 #define REGION_MASK	0xf0000000
 #define REGION_SHIFT	28
@@ -143,7 +144,8 @@ extern pte_t * __bad_pagetable(void);
 
 #define BAD_PAGETABLE __bad_pagetable()
 #define BAD_PAGE __bad_page()
-#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
+#define ZERO_PAGE(vaddr) virt_to_page(empty_zero_page)
 
 /* number of bits that fit into a memory pointer */
 #define BITS_PER_PTR			(8*sizeof(unsigned long))
@@ -164,9 +166,6 @@ extern pte_t * __bad_pagetable(void);
 
 #define pte_clear(xp)	do { pte_val(*(xp)) = _PAGE_NEWPAGE; } while (0)
 
-#define phys_region_index(x) (((x) & REGION_MASK) >> REGION_SHIFT)
-#define pte_region_index(x) phys_region_index(pte_val(x))
-
 #define pmd_none(x)	(!(pmd_val(x) & ~_PAGE_NEWPAGE))
 #define	pmd_bad(x)	((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
 #define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
@@ -188,19 +187,25 @@ static inline void pgd_clear(pgd_t * pgdp)	{ }
 
 #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
 
-extern struct page *pte_mem_map(pte_t pte);
-extern struct page *phys_mem_map(unsigned long phys);
-extern unsigned long phys_to_pfn(unsigned long p);
-extern unsigned long pfn_to_phys(unsigned long pfn);
+#define pte_page(pte) phys_to_page(pte_val(pte))
+#define pmd_page(pmd) phys_to_page(pmd_val(pmd) & PAGE_MASK)
 
-#define pte_page(x) pfn_to_page(pte_pfn(x))
-#define pte_address(x) (__va(pte_val(x) & PAGE_MASK))
-#define mk_phys(a, r) ((a) + (r << REGION_SHIFT))
-#define phys_addr(p) ((p) & ~REGION_MASK)
-#define phys_page(p) (phys_mem_map(p) + ((phys_addr(p)) >> PAGE_SHIFT))
 #define pte_pfn(x) phys_to_pfn(pte_val(x))
 #define pfn_pte(pfn, prot) __pte(pfn_to_phys(pfn) | pgprot_val(prot))
-#define pfn_pmd(pfn, prot) __pmd(pfn_to_phys(pfn) | pgprot_val(prot))
+
+extern struct page *phys_to_page(const unsigned long phys);
+extern struct page *__virt_to_page(const unsigned long virt);
+#define virt_to_page(addr) __virt_to_page((const unsigned long) addr)
+
+/*
+ * Bits 0 through 3 are taken
+ */
+#define PTE_FILE_MAX_BITS	28
+
+#define pte_to_pgoff(pte) ((pte).pte_low >> 4)
+
+#define pgoff_to_pte(off) \
+	((pte_t) { ((off) << 4) + _PAGE_FILE })
 
 static inline pte_t pte_mknewprot(pte_t pte)
 {
@@ -235,6 +240,12 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval)
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
+static inline int pte_user(pte_t pte)
+{
+	return((pte_val(pte) & _PAGE_USER) &&
+	       !(pte_val(pte) & _PAGE_PROTNONE));
+}
+
 static inline int pte_read(pte_t pte)
 { 
 	return((pte_val(pte) & _PAGE_USER) && 
@@ -252,6 +263,14 @@ static inline int pte_write(pte_t pte)
 	       !(pte_val(pte) & _PAGE_PROTNONE));
 }
 
+/*
+ * The following only works if pte_present() is not true.
+ */
+static inline int pte_file(pte_t pte)
+{
+	return (pte).pte_low & _PAGE_FILE;
+}
+
 static inline int pte_dirty(pte_t pte)	{ return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte)	{ return pte_val(pte) & _PAGE_ACCESSED; }
 static inline int pte_newpage(pte_t pte) { return pte_val(pte) & _PAGE_NEWPAGE; }
@@ -334,14 +353,7 @@ extern unsigned long page_to_phys(struct page *page);
  * and a page entry and page directory to the page they refer to.
  */
 
-#define mk_pte(page, pgprot) \
-({					\
-	pte_t __pte;                    \
-                                        \
-	pte_val(__pte) = page_to_phys(page) + pgprot_val(pgprot);\
-	if(pte_present(__pte)) pte_mknewprot(pte_mknewpage(__pte)); \
-	__pte;                          \
-})
+extern pte_t mk_pte(struct page *page, pgprot_t pgprot);
 
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
@@ -351,17 +363,27 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 }
 
 #define pmd_page_kernel(pmd) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
-#define pmd_page(pmd) (phys_mem_map(pmd_val(pmd) & PAGE_MASK) + \
-		       ((phys_addr(pmd_val(pmd)) >> PAGE_SHIFT)))
 
-/* to find an entry in a page-table-directory. */
+/*
+ * the pgd page can be thought of an array like this: pgd_t[PTRS_PER_PGD]
+ *
+ * this macro returns the index of the entry in the pgd page which would
+ * control the given virtual address
+ */
 #define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
 
-/* to find an entry in a page-table-directory */
+/*
+ * pgd_offset() returns a (pgd_t *)
+ * pgd_index() is used get the offset into the pgd page's array of pgd_t's;
+ */
 #define pgd_offset(mm, address) \
 ((mm)->pgd + ((address) >> PGDIR_SHIFT))
 
-/* to find an entry in a kernel page-table-directory */
+
+/*
+ * a shortcut which implies the use of the kernel's pgd, instead
+ * of a process's
+ */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
 #define pmd_index(address) \
@@ -373,7 +395,12 @@ static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
 	return (pmd_t *) dir;
 }
 
-/* Find an entry in the third-level page table.. */ 
+/*
+ * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
+ *
+ * this macro returns the index of the entry in the pte page which would
+ * control the given virtual address
+ */
 #define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 #define pte_offset_kernel(dir, address) \
 	((pte_t *) pmd_page_kernel(*(dir)) +  pte_index(address))
@@ -387,11 +414,11 @@ static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
 #define update_mmu_cache(vma,address,pte) do ; while (0)
 
 /* Encode and de-code a swap entry */
-#define __swp_type(x)			(((x).val >> 3) & 0x7f)
-#define __swp_offset(x)			((x).val >> 10)
+#define __swp_type(x)			(((x).val >> 4) & 0x3f)
+#define __swp_offset(x)			((x).val >> 11)
 
 #define __swp_entry(type, offset) \
-	((swp_entry_t) { ((type) << 3) | ((offset) << 10) })
+	((swp_entry_t) { ((type) << 4) | ((offset) << 11) })
 #define __pte_to_swp_entry(pte) \
 	((swp_entry_t) { pte_val(pte_mkuptodate(pte)) })
 #define __swp_entry_to_pte(x)		((pte_t) { (x).val })
diff --git a/include/asm-um/processor-generic.h b/include/asm-um/processor-generic.h
index 618a49030..fa39a3985 100644
--- a/include/asm-um/processor-generic.h
+++ b/include/asm-um/processor-generic.h
@@ -11,41 +11,20 @@ struct pt_regs;
 struct task_struct;
 
 #include "linux/config.h"
-#include "linux/signal.h"
 #include "asm/ptrace.h"
-#include "asm/siginfo.h"
 #include "choose-mode.h"
 
 struct mm_struct;
 
-#define current_text_addr() ((void *) 0)
-
-#define cpu_relax()	do ; while (0)
-
-#ifdef CONFIG_MODE_TT
-struct proc_tt_mode {
-	int extern_pid;
-	int tracing;
-	int switch_pipe[2];
-	int singlestep_syscall;
-	int vm_seq;
-};
-#endif
-
-#ifdef CONFIG_MODE_SKAS
-struct proc_skas_mode {
-	void *switch_buf;
-	void *fork_buf;
-};
-#endif
+#define cpu_relax()   barrier()
 
 struct thread_struct {
 	int forking;
-	unsigned long kernel_stack;
 	int nsyscalls;
 	struct pt_regs regs;
 	unsigned long cr2;
 	int err;
+	unsigned long trap_no;
 	void *fault_addr;
 	void *fault_catcher;
 	struct task_struct *prev_sched;
@@ -54,10 +33,20 @@ struct thread_struct {
 	struct arch_thread arch;
 	union {
 #ifdef CONFIG_MODE_TT
-		struct proc_tt_mode tt;
+		struct {
+			int extern_pid;
+			int tracing;
+			int switch_pipe[2];
+			int singlestep_syscall;
+			int vm_seq;
+		} tt;
 #endif
 #ifdef CONFIG_MODE_SKAS
-		struct proc_skas_mode skas;
+		struct {
+			void *switch_buf;
+			void *fork_buf;
+			int mm_count;
+		} skas;
 #endif
 	} mode;
 	struct {
@@ -81,7 +70,6 @@ struct thread_struct {
 #define INIT_THREAD \
 { \
 	.forking		= 0, \
-	.kernel_stack		= 0, \
 	.nsyscalls		= 0, \
         .regs		   	= EMPTY_REGS, \
 	.cr2			= 0, \
@@ -99,14 +87,19 @@ typedef struct {
 } mm_segment_t;
 
 extern struct task_struct *alloc_task_struct(void);
-extern void free_task_struct(struct task_struct *task);
 
 extern void release_thread(struct task_struct *);
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 extern void dump_thread(struct pt_regs *regs, struct user *u);
+extern void prepare_to_copy(struct task_struct *tsk);
 
 extern unsigned long thread_saved_pc(struct task_struct *t);
 
+static inline void mm_copy_segments(struct mm_struct *from_mm,
+				    struct mm_struct *new_mm)
+{
+}
+
 #define init_stack	(init_thread_union.stack)
 
 /*
diff --git a/include/asm-um/processor-i386.h b/include/asm-um/processor-i386.h
index 02decdcc1..b276481cc 100644
--- a/include/asm-um/processor-i386.h
+++ b/include/asm-um/processor-i386.h
@@ -6,8 +6,8 @@
 #ifndef __UM_PROCESSOR_I386_H
 #define __UM_PROCESSOR_I386_H
 
-extern int cpu_has_xmm;
-extern int cpu_has_cmov;
+extern int host_has_xmm;
+extern int host_has_cmov;
 
 struct arch_thread {
 	unsigned long debugregs[8];
@@ -19,6 +19,13 @@ struct arch_thread {
 
 #include "asm/arch/user.h"
 
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter"). Stolen
+ * from asm-i386/processor.h
+ */
+#define current_text_addr() ({ void *pc; __asm__("movl $1f,%0\n1:":"=g" (pc)); pc; })
+
 #include "asm/processor-generic.h"
 
 #endif
diff --git a/include/asm-um/ptrace-generic.h b/include/asm-um/ptrace-generic.h
index c5a13e609..8c472ebbb 100644
--- a/include/asm-um/ptrace-generic.h
+++ b/include/asm-um/ptrace-generic.h
@@ -45,6 +45,8 @@ struct pt_regs {
 
 #define PT_REGS_SC(r) UPT_SC(&(r)->regs)
 
+#define instruction_pointer(regs) PT_REGS_IP(regs)
+
 struct task_struct;
 
 extern unsigned long getreg(struct task_struct *child, int regno);
diff --git a/include/asm-um/smp.h b/include/asm-um/smp.h
index 4629de866..4412d5d9c 100644
--- a/include/asm-um/smp.h
+++ b/include/asm-um/smp.h
@@ -8,17 +8,13 @@
 #include "asm/current.h"
 #include "linux/cpumask.h"
 
-extern cpumask_t cpu_online_map;
-
-#define smp_processor_id() (current->thread_info->cpu)
+#define smp_processor_id() (current_thread->cpu)
 #define cpu_logical_map(n) (n)
 #define cpu_number_map(n) (n)
 #define PROC_CHANGE_PENALTY	15 /* Pick a number, any number */
 extern int hard_smp_processor_id(void);
 #define NO_PROC_ID -1
 
-#define cpu_online(cpu) cpu_isset(cpu, cpu_online_map)
-
 extern int ncpus;
 
 
diff --git a/include/asm-um/spinlock.h b/include/asm-um/spinlock.h
index bd6c35d48..f18c82886 100644
--- a/include/asm-um/spinlock.h
+++ b/include/asm-um/spinlock.h
@@ -1,10 +1,6 @@
 #ifndef __UM_SPINLOCK_H
 #define __UM_SPINLOCK_H
 
-#include "linux/config.h"
-
-#ifdef CONFIG_SMP
 #include "asm/arch/spinlock.h"
-#endif
 
 #endif
diff --git a/include/asm-um/system-generic.h b/include/asm-um/system-generic.h
index 80b24a31b..5bcfa35e7 100644
--- a/include/asm-um/system-generic.h
+++ b/include/asm-um/system-generic.h
@@ -23,8 +23,10 @@ extern int get_signals(void);
 extern void block_signals(void);
 extern void unblock_signals(void);
 
-#define local_save_flags(flags) do { (flags) = get_signals(); } while(0)
-#define local_irq_restore(flags) do { set_signals(flags); } while(0)
+#define local_save_flags(flags) do { typecheck(unsigned long, flags); \
+				     (flags) = get_signals(); } while(0)
+#define local_irq_restore(flags) do { typecheck(unsigned long, flags); \
+				      set_signals(flags); } while(0)
 
 #define local_irq_save(flags) do { local_save_flags(flags); \
                                    local_irq_disable(); } while(0)
@@ -39,4 +41,7 @@ extern void unblock_signals(void);
         (flags == 0);                   \
 })
 
+extern void *_switch_to(void *prev, void *next, void *last);
+#define switch_to(prev, next, last) prev = _switch_to(prev, next, last)
+
 #endif
diff --git a/include/asm-um/system-i386.h b/include/asm-um/system-i386.h
index 4d71ed390..c436263e6 100644
--- a/include/asm-um/system-i386.h
+++ b/include/asm-um/system-i386.h
@@ -2,36 +2,5 @@
 #define __UM_SYSTEM_I386_H
 
 #include "asm/system-generic.h"
-
-static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
-				      unsigned long new, int size)
-{
-	unsigned long prev;
-	switch (size) {
-	case 1:
-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
-				     : "=a"(prev)
-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
-				     : "memory");
-		return prev;
-	case 2:
-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
-				     : "=a"(prev)
-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
-				     : "memory");
-		return prev;
-	case 4:
-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
-				     : "=a"(prev)
-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
-				     : "memory");
-		return prev;
-	}
-	return old;
-}
-
-#define cmpxchg(ptr,o,n)\
-	((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
-					(unsigned long)(n),sizeof(*(ptr))))
     
 #endif
diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h
index 6a606bf0b..c52830772 100644
--- a/include/asm-um/thread_info.h
+++ b/include/asm-um/thread_info.h
@@ -9,6 +9,7 @@
 #ifndef __ASSEMBLY__
 
 #include <asm/processor.h>
+#include <asm/types.h>
 
 struct thread_info {
 	struct task_struct	*task;		/* main task structure */
@@ -43,15 +44,18 @@ struct thread_info {
 static inline struct thread_info *current_thread_info(void)
 {
 	struct thread_info *ti;
-	__asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~16383UL));
+	unsigned long mask = PAGE_SIZE *
+		(1 << CONFIG_KERNEL_STACK_ORDER) - 1;
+	__asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~mask));
 	return ti;
 }
 
 /* thread information allocation */
-#define THREAD_SIZE (4*PAGE_SIZE)
-#define alloc_thread_info(tsk) ((struct thread_info *) \
-	__get_free_pages(GFP_KERNEL,2))
-#define free_thread_info(ti) free_pages((unsigned long) (ti), 2)
+#define THREAD_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE)
+#define alloc_thread_info(tsk) \
+	((struct thread_info *) kmalloc(THREAD_SIZE, GFP_KERNEL))
+#define free_thread_info(ti) kfree(ti)
+
 #define get_thread_info(ti) get_task_struct((ti)->task)
 #define put_thread_info(ti) put_task_struct((ti)->task)
 
@@ -65,11 +69,13 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_POLLING_NRFLAG      3       /* true if poll_idle() is polling 
 					 * TIF_NEED_RESCHED 
 					 */
+#define TIF_RESTART_BLOCK 	4
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG     (1 << TIF_POLLING_NRFLAG)
+#define _TIF_RESTART_BLOCK	(1 << TIF_RESTART_BLOCK)
 
 #endif
 
diff --git a/include/asm-um/timex.h b/include/asm-um/timex.h
index 6a873133a..580581172 100644
--- a/include/asm-um/timex.h
+++ b/include/asm-um/timex.h
@@ -1,8 +1,6 @@
 #ifndef __UM_TIMEX_H
 #define __UM_TIMEX_H
 
-#include "linux/time.h"
-
 typedef unsigned long cycles_t;
 
 #define cacheflush_time (0)
diff --git a/include/asm-um/uaccess.h b/include/asm-um/uaccess.h
index e1dfea108..d42d5f8dc 100644
--- a/include/asm-um/uaccess.h
+++ b/include/asm-um/uaccess.h
@@ -6,6 +6,8 @@
 #ifndef __UM_UACCESS_H
 #define __UM_UACCESS_H
 
+#include "linux/sched.h"
+
 #define VERIFY_READ 0
 #define VERIFY_WRITE 1
 
@@ -34,6 +36,9 @@
 
 #define __copy_to_user(to, from, n) copy_to_user(to, from, n)
 
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
 #define __get_user(x, ptr) \
 ({ \
         const __typeof__(ptr) __private_ptr = ptr; \
@@ -50,7 +55,7 @@
 
 #define get_user(x, ptr) \
 ({ \
-        const __typeof__((*ptr)) *private_ptr = (ptr); \
+        const __typeof__((*(ptr))) *private_ptr = (ptr); \
         (access_ok(VERIFY_READ, private_ptr, sizeof(*private_ptr)) ? \
 	 __get_user(x, private_ptr) : ((x) = 0, -EFAULT)); \
 })
diff --git a/include/asm-um/unistd.h b/include/asm-um/unistd.h
index 5850620bb..512f2257c 100644
--- a/include/asm-um/unistd.h
+++ b/include/asm-um/unistd.h
@@ -48,7 +48,10 @@ extern int um_execve(const char *file, char *const argv[], char *const env[]);
 	set_fs(KERNEL_DS);			\
 	ret = sys(args);			\
 	set_fs(fs);				\
-	return ret;
+	if (ret >= 0)				\
+		return ret;			\
+	errno = -(long)ret;			\
+	return -1;
 
 static inline long open(const char *pathname, int flags, int mode) 
 {
diff --git a/include/asm-v850/bug.h b/include/asm-v850/bug.h
index ce68b9aba..c778916bf 100644
--- a/include/asm-v850/bug.h
+++ b/include/asm-v850/bug.h
@@ -16,15 +16,7 @@
 
 extern void __bug (void) __attribute__ ((noreturn));
 #define BUG()		__bug()
-#define PAGE_BUG(page)	__bug()
-
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
+#define HAVE_ARCH_BUG
+#include <asm-generic/bug.h>
 
 #endif /* __V850_BUG_H__ */
diff --git a/include/asm-v850/hardirq.h b/include/asm-v850/hardirq.h
index a997f9f8f..7493d6d48 100644
--- a/include/asm-v850/hardirq.h
+++ b/include/asm-v850/hardirq.h
@@ -36,20 +36,6 @@ typedef struct {
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -59,27 +45,7 @@ typedef struct {
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
 #define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
-
-#ifdef CONFIG_PREEMPT
-# define in_atomic()    (preempt_count() != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()    (preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
-
 #define irq_exit()							      \
 do {									      \
 	preempt_count() -= IRQ_EXIT_OFFSET;				      \
@@ -88,10 +54,4 @@ do {									      \
 	preempt_enable_no_resched();					      \
 } while (0)
 
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else
-# error v850nommu SMP is not available
-#endif /* CONFIG_SMP */
-
 #endif /* __V850_HARDIRQ_H__ */
diff --git a/include/asm-v850/ptrace.h b/include/asm-v850/ptrace.h
index 62b2b3822..7bf72bb50 100644
--- a/include/asm-v850/ptrace.h
+++ b/include/asm-v850/ptrace.h
@@ -76,6 +76,7 @@ struct pt_regs
 
 
 #define instruction_pointer(regs)	((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
 #define user_mode(regs)			(!(regs)->kernel_mode)
 
 /* When a struct pt_regs is used to save user state for a system call in
diff --git a/include/asm-v850/resource.h b/include/asm-v850/resource.h
index 9f4ca4ae6..adcbbb896 100644
--- a/include/asm-v850/resource.h
+++ b/include/asm-v850/resource.h
@@ -39,7 +39,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
-	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff --git a/include/asm-v850/socket.h b/include/asm-v850/socket.h
index 7d7f80efa..213b852af 100644
--- a/include/asm-v850/socket.h
+++ b/include/asm-v850/socket.h
@@ -47,20 +47,4 @@
 
 #define SO_PEERSEC		31
 
-/* Nast libc5 fixup - bletch */
-#if defined(__KERNEL__)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* __V850_SOCKET_H__ */
diff --git a/include/asm-v850/uaccess.h b/include/asm-v850/uaccess.h
index 1db90103b..7068dfcff 100644
--- a/include/asm-v850/uaccess.h
+++ b/include/asm-v850/uaccess.h
@@ -112,6 +112,9 @@ extern int bad_user_access_length (void);
 #define __copy_from_user(to, from, n)	(memcpy (to, from, n), 0)
 #define __copy_to_user(to, from, n)	(memcpy(to, from, n), 0)
 
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
 #define copy_from_user(to, from, n)	__copy_from_user (to, from, n)
 #define copy_to_user(to, from, n) 	__copy_to_user(to, from, n)
 
diff --git a/include/asm-x86_64/acpi.h b/include/asm-x86_64/acpi.h
index 22a130b59..015faa095 100644
--- a/include/asm-x86_64/acpi.h
+++ b/include/asm-x86_64/acpi.h
@@ -99,6 +99,11 @@ __acpi_release_global_lock (unsigned int *lock)
         :"=r"(n_hi), "=r"(n_lo)     \
         :"0"(n_hi), "1"(n_lo))
 
+/*
+ * Refer Intel ACPI _PDC support document for bit definitions
+ */
+#define ACPI_PDC_EST_CAPABILITY_SMP 	0xa
+#define ACPI_PDC_EST_CAPABILITY_MSR	0x1
 
 #ifdef CONFIG_ACPI_BOOT
 extern int acpi_lapic;
@@ -159,6 +164,8 @@ extern void acpi_reserve_bootmem(void);
 extern int acpi_disabled;
 extern int acpi_pci_disabled;
 
+extern u8 x86_acpiid_to_apicid[];
+
 #endif /*__KERNEL__*/
 
 #endif /*_ASM_ACPI_H*/
diff --git a/include/asm-x86_64/apic.h b/include/asm-x86_64/apic.h
index 44ec801f9..62ccf888a 100644
--- a/include/asm-x86_64/apic.h
+++ b/include/asm-x86_64/apic.h
@@ -7,15 +7,29 @@
 #include <asm/apicdef.h>
 #include <asm/system.h>
 
-#ifdef CONFIG_X86_LOCAL_APIC
+#define Dprintk(x...)
 
-#define APIC_DEBUG 0
+/*
+ * Debugging macros
+ */
+#define APIC_QUIET   0
+#define APIC_VERBOSE 1
+#define APIC_DEBUG   2
 
-#if APIC_DEBUG
-#define Dprintk(x...) printk(x)
-#else
-#define Dprintk(x...)
-#endif
+extern int apic_verbosity;
+
+/*
+ * Define the default level of output to be very little
+ * This can be turned up by using apic=verbose for more
+ * information and apic=debug for _lots_ of information.
+ * apic_verbosity is defined in apic.c
+ */
+#define apic_printk(v, s, a...) do {       \
+		if ((v) <= apic_verbosity) \
+			printk(s, ##a);    \
+	} while (0)
+
+#ifdef CONFIG_X86_LOCAL_APIC
 
 struct pt_regs;
 
diff --git a/include/asm-x86_64/apicdef.h b/include/asm-x86_64/apicdef.h
index 8ba1d6ef1..4852d9a28 100644
--- a/include/asm-x86_64/apicdef.h
+++ b/include/asm-x86_64/apicdef.h
@@ -108,7 +108,7 @@
 
 #define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
 
-#define MAX_IO_APICS 16
+#define MAX_IO_APICS 32
 
 /*
  * the local APIC register structure, memory mapped. Not terribly well
diff --git a/include/asm-x86_64/atomic.h b/include/asm-x86_64/atomic.h
index baf472fb5..e2b1f4879 100644
--- a/include/asm-x86_64/atomic.h
+++ b/include/asm-x86_64/atomic.h
@@ -178,6 +178,166 @@ static __inline__ int atomic_add_negative(int i, atomic_t *v)
 	return c;
 }
 
+/* An 64bit atomic type */
+
+typedef struct { volatile long counter; } atomic64_t;
+
+#define ATOMIC64_INIT(i)	{ (i) }
+
+/**
+ * atomic64_read - read atomic64 variable
+ * @v: pointer of type atomic64_t
+ *
+ * Atomically reads the value of @v.
+ * Doesn't imply a read memory barrier.
+ */
+#define atomic64_read(v)		((v)->counter)
+
+/**
+ * atomic64_set - set atomic64 variable
+ * @v: pointer to type atomic64_t
+ * @i: required value
+ *
+ * Atomically sets the value of @v to @i.
+ */
+#define atomic64_set(v,i)		(((v)->counter) = (i))
+
+/**
+ * atomic64_add - add integer to atomic64 variable
+ * @i: integer value to add
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically adds @i to @v.
+ */
+static __inline__ void atomic64_add(long i, atomic64_t *v)
+{
+	__asm__ __volatile__(
+		LOCK "addq %1,%0"
+		:"=m" (v->counter)
+		:"ir" (i), "m" (v->counter));
+}
+
+/**
+ * atomic64_sub - subtract the atomic64 variable
+ * @i: integer value to subtract
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically subtracts @i from @v.
+ */
+static __inline__ void atomic64_sub(long i, atomic64_t *v)
+{
+	__asm__ __volatile__(
+		LOCK "subq %1,%0"
+		:"=m" (v->counter)
+		:"ir" (i), "m" (v->counter));
+}
+
+/**
+ * atomic64_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically subtracts @i from @v and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+static __inline__ int atomic64_sub_and_test(long i, atomic64_t *v)
+{
+	unsigned char c;
+
+	__asm__ __volatile__(
+		LOCK "subq %2,%0; sete %1"
+		:"=m" (v->counter), "=qm" (c)
+		:"ir" (i), "m" (v->counter) : "memory");
+	return c;
+}
+
+/**
+ * atomic64_inc - increment atomic64 variable
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically increments @v by 1.
+ */
+static __inline__ void atomic64_inc(atomic64_t *v)
+{
+	__asm__ __volatile__(
+		LOCK "incq %0"
+		:"=m" (v->counter)
+		:"m" (v->counter));
+}
+
+/**
+ * atomic64_dec - decrement atomic64 variable
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically decrements @v by 1.
+ */
+static __inline__ void atomic64_dec(atomic64_t *v)
+{
+	__asm__ __volatile__(
+		LOCK "decq %0"
+		:"=m" (v->counter)
+		:"m" (v->counter));
+}
+
+/**
+ * atomic64_dec_and_test - decrement and test
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+ */
+static __inline__ int atomic64_dec_and_test(atomic64_t *v)
+{
+	unsigned char c;
+
+	__asm__ __volatile__(
+		LOCK "decq %0; sete %1"
+		:"=m" (v->counter), "=qm" (c)
+		:"m" (v->counter) : "memory");
+	return c != 0;
+}
+
+/**
+ * atomic64_inc_and_test - increment and test
+ * @v: pointer to type atomic64_t
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+static __inline__ int atomic64_inc_and_test(atomic64_t *v)
+{
+	unsigned char c;
+
+	__asm__ __volatile__(
+		LOCK "incq %0; sete %1"
+		:"=m" (v->counter), "=qm" (c)
+		:"m" (v->counter) : "memory");
+	return c != 0;
+}
+
+/**
+ * atomic64_add_negative - add and test if negative
+ * @v: pointer to atomic64_t
+ * @i: integer value to add
+ *
+ * Atomically adds @i to @v and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+ */
+static __inline__ long atomic64_add_negative(long i, atomic64_t *v)
+{
+	unsigned char c;
+
+	__asm__ __volatile__(
+		LOCK "addq %2,%0; sets %1"
+		:"=m" (v->counter), "=qm" (c)
+		:"ir" (i), "m" (v->counter) : "memory");
+	return c;
+}
+
 /* These are x86-specific, used by some header files */
 #define atomic_clear_mask(mask, addr) \
 __asm__ __volatile__(LOCK "andl %0,%1" \
diff --git a/include/asm-x86_64/bitops.h b/include/asm-x86_64/bitops.h
index c91f028db..c44e168f1 100644
--- a/include/asm-x86_64/bitops.h
+++ b/include/asm-x86_64/bitops.h
@@ -25,10 +25,10 @@
  * Note that @nr may be almost arbitrarily large; this function is not
  * restricted to acting on a single-word quantity.
  */
-static __inline__ void set_bit(long nr, volatile void * addr)
+static __inline__ void set_bit(int nr, volatile void * addr)
 {
 	__asm__ __volatile__( LOCK_PREFIX
-		"btsq %1,%0"
+		"btsl %1,%0"
 		:"=m" (ADDR)
 		:"dIr" (nr) : "memory");
 }
@@ -254,128 +254,37 @@ static __inline__ int variable_test_bit(int nr, volatile const void * addr)
 
 #undef ADDR
 
-/**
- * find_first_zero_bit - find the first zero bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
- *
- * Returns the bit-number of the first zero bit, not the number of the byte
- * containing a bit.
- */
-static __inline__ int find_first_zero_bit(const unsigned long * addr, unsigned size)
-{
-	int d0, d1, d2;
-	int res;
-
-	if (!size)
-		return 0;
-	__asm__ __volatile__(
-		"movl $-1,%%eax\n\t"
-		"xorl %%edx,%%edx\n\t"
-		"repe; scasl\n\t"
-		"je 1f\n\t"
-		"xorl -4(%%rdi),%%eax\n\t"
-		"subq $4,%%rdi\n\t"
-		"bsfl %%eax,%%edx\n"
-		"1:\tsubq %%rbx,%%rdi\n\t"
-		"shlq $3,%%rdi\n\t"
-		"addq %%rdi,%%rdx"
-		:"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
-		:"1" ((size + 31) >> 5), "2" (addr), "b" (addr) : "memory");
-	return res;
-}
+extern long find_first_zero_bit(const unsigned long * addr, unsigned long size);
+extern long find_next_zero_bit (const unsigned long * addr, long size, long offset);
+extern long find_first_bit(const unsigned long * addr, unsigned long size);
+extern long find_next_bit(const unsigned long * addr, long size, long offset);
 
-/**
- * find_next_zero_bit - find the first zero bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-static __inline__ int find_next_zero_bit (const unsigned long * addr, int size, int offset)
+/* return index of first bet set in val or max when no bit is set */
+static inline unsigned long __scanbit(unsigned long val, unsigned long max)
 {
-	unsigned long * p = ((unsigned long *) addr) + (offset >> 6);
-	unsigned long set = 0;
-	unsigned long res, bit = offset&63;
-	
-	if (bit) {
-		/*
-		 * Look for zero in first word
-		 */
-		__asm__("bsfq %1,%0\n\t"
-			"cmoveq %2,%0"
-			: "=r" (set)
-			: "r" (~(*p >> bit)), "r"(64L));
-		if (set < (64 - bit))
-			return set + offset;
-		set = 64 - bit;
-		p++;
-	}
-	/*
-	 * No zero yet, search remaining full words for a zero
-	 */
-	res = find_first_zero_bit ((const unsigned long *)p, size - 64 * (p - (unsigned long *) addr));
-	return (offset + set + res);
+	asm("bsfq %1,%0 ; cmovz %2,%0" : "=&r" (val) : "r" (val), "r" (max));
+	return val;
 }
 
+#define find_first_bit(addr,size) \
+((__builtin_constant_p(size) && size <= BITS_PER_LONG ? \
+  (__scanbit(*(unsigned long *)addr,(size))) : \
+  find_first_bit(addr,size)))
 
-/**
- * find_first_bit - find the first set bit in a memory region
- * @addr: The address to start the search at
- * @size: The maximum size to search
- *
- * Returns the bit-number of the first set bit, not the number of the byte
- * containing a bit.
- */
-static __inline__ int find_first_bit(const unsigned long * addr, unsigned size)
-{
-	int d0, d1;
-	int res;
-
-	/* This looks at memory. Mark it volatile to tell gcc not to move it around */
-	__asm__ __volatile__(
-		"xorl %%eax,%%eax\n\t"
-		"repe; scasl\n\t"
-		"jz 1f\n\t"
-		"leaq -4(%%rdi),%%rdi\n\t"
-		"bsfl (%%rdi),%%eax\n"
-		"1:\tsubq %%rbx,%%rdi\n\t"
-		"shll $3,%%edi\n\t"
-		"addl %%edi,%%eax"
-		:"=a" (res), "=&c" (d0), "=&D" (d1)
-		:"1" ((size + 31) >> 5), "2" (addr), "b" (addr) : "memory");
-	return res;
-}
+#define find_next_bit(addr,size,off) \
+((__builtin_constant_p(size) && size <= BITS_PER_LONG ? 	  \
+  ((off) + (__scanbit((*(unsigned long *)addr) >> (off),(size)-(off)))) : \
+	find_next_bit(addr,size,off)))
 
-/**
- * find_next_bit - find the first set bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-static __inline__ int find_next_bit(const unsigned long * addr, int size, int offset)
-{
-	const unsigned long * p = addr + (offset >> 6);
-	unsigned long set = 0, bit = offset & 63, res;
+#define find_first_zero_bit(addr,size) \
+((__builtin_constant_p(size) && size <= BITS_PER_LONG ? \
+  (__scanbit(~*(unsigned long *)addr,(size))) : \
+  	find_first_zero_bit(addr,size)))
 	
-	if (bit) {
-		/*
-		 * Look for nonzero in the first 64 bits:
-		 */
-		__asm__("bsfq %1,%0\n\t"
-			"cmoveq %2,%0\n\t"
-			: "=r" (set)
-			: "r" (*p >> bit), "r" (64L));
-		if (set < (64 - bit))
-			return set + offset;
-		set = 64 - bit;
-		p++;
-	}
-	/*
-	 * No set bit yet, search remaining full words for a bit
-	 */
-	res = find_first_bit (p, size - 64 * (p - addr));
-	return (offset + set + res);
-}
+#define find_next_zero_bit(addr,size,off) \
+((__builtin_constant_p(size) && size <= BITS_PER_LONG ? 	  \
+  ((off)+(__scanbit(~(((*(unsigned long *)addr)) >> (off)),(size)-(off)))) : \
+	find_next_zero_bit(addr,size,off)))
 
 /* 
  * Find string of zero bits in a bitmap. -1 when not found.
diff --git a/include/asm-x86_64/bug.h b/include/asm-x86_64/bug.h
index 44d70dea0..d2032f56e 100644
--- a/include/asm-x86_64/bug.h
+++ b/include/asm-x86_64/bug.h
@@ -6,27 +6,20 @@
 /*
  * Tell the user there is some problem.  The exception handler decodes 
  * this frame.
- */ 
-struct bug_frame { 
-       unsigned char ud2[2];          
+ */
+struct bug_frame {
+       unsigned char ud2[2];
 	/* should use 32bit offset instead, but the assembler doesn't 
-	   like it */ 
-	char *filename;   
-	unsigned short line; 
-} __attribute__((packed)); 
+	   like it */
+	char *filename;
+	unsigned short line;
+} __attribute__((packed));
 
+#define HAVE_ARCH_BUG
 #define BUG() \
 	asm volatile("ud2 ; .quad %c1 ; .short %c0" :: \
 		     "i"(__LINE__), "i" (__stringify(KBUILD_BASENAME)))
-#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
-#define PAGE_BUG(page) BUG()
 void out_of_line_bug(void);
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
+#include <asm-generic/bug.h>
 
 #endif
diff --git a/include/asm-x86_64/cpufeature.h b/include/asm-x86_64/cpufeature.h
index d82d84032..8a1025f7a 100644
--- a/include/asm-x86_64/cpufeature.h
+++ b/include/asm-x86_64/cpufeature.h
@@ -7,7 +7,7 @@
 #ifndef __ASM_X8664_CPUFEATURE_H
 #define __ASM_X8664_CPUFEATURE_H
 
-#define NCAPINTS	5	/* Currently we have 4 32-bit words worth of info */
+#define NCAPINTS	6
 
 /* Intel-defined CPU features, CPUID level 0x00000001, word 0 */
 #define X86_FEATURE_FPU		(0*32+ 0) /* Onboard FPU */
@@ -63,8 +63,17 @@
 #define X86_FEATURE_K8_C	(3*32+ 4) /* C stepping K8 */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
-#define X86_FEATURE_EST		(4*32+ 7) /* Enhanced SpeedStep */
+#define X86_FEATURE_XMM3	(4*32+ 0) /* Streaming SIMD Extensions-3 */
 #define X86_FEATURE_MWAIT	(4*32+ 3) /* Monitor/Mwait support */
+#define X86_FEATURE_DSCPL	(4*32+ 4) /* CPL Qualified Debug Store */
+#define X86_FEATURE_EST		(4*32+ 7) /* Enhanced SpeedStep */
+#define X86_FEATURE_TM2		(4*32+ 8) /* Thermal Monitor 2 */
+#define X86_FEATURE_CID		(4*32+10) /* Context ID */
+#define X86_FEATURE_CX16	(4*32+13) /* CMPXCHG16B */
+#define X86_FEATURE_XTPR	(4*32+14) /* Send Task Priority Messages */
+
+/* More extended AMD flags: CPUID level 0x80000001, ecx, word 5 */
+#define X86_FEATURE_HTVALID	(5*32+ 0) /* HyperThreading valid, otherwise CMP */
 
 #define cpu_has(c, bit)                test_bit(bit, (c)->x86_capability)
 #define boot_cpu_has(bit)      test_bit(bit, boot_cpu_data.x86_capability)
@@ -81,6 +90,8 @@
 #define cpu_has_mmx            1
 #define cpu_has_fxsr           1
 #define cpu_has_xmm            1
+#define cpu_has_xmm2           1
+#define cpu_has_xmm3           boot_cpu_has(X86_FEATURE_XMM3)
 #define cpu_has_ht             boot_cpu_has(X86_FEATURE_HT)
 #define cpu_has_mp             1 /* XXX */
 #define cpu_has_k6_mtrr        0
diff --git a/include/asm-x86_64/desc.h b/include/asm-x86_64/desc.h
index b4543649b..004888f2f 100644
--- a/include/asm-x86_64/desc.h
+++ b/include/asm-x86_64/desc.h
@@ -128,13 +128,13 @@ static inline void set_tss_desc(unsigned cpu, void *addr)
 { 
 	set_tssldt_descriptor(&cpu_gdt_table[cpu][GDT_ENTRY_TSS], (unsigned long)addr, 
 			      DESC_TSS,
-			      sizeof(struct tss_struct)); 
+			      sizeof(struct tss_struct) - 1);
 } 
 
 static inline void set_ldt_desc(unsigned cpu, void *addr, int size)
 { 
 	set_tssldt_descriptor(&cpu_gdt_table[cpu][GDT_ENTRY_LDT], (unsigned long)addr, 
-			      DESC_LDT, size * 8);
+			      DESC_LDT, size * 8 - 1);
 }
 
 static inline void set_seg_base(unsigned cpu, int entry, void *base)
diff --git a/include/asm-x86_64/dma-mapping.h b/include/asm-x86_64/dma-mapping.h
index 414efa3c3..a416dc316 100644
--- a/include/asm-x86_64/dma-mapping.h
+++ b/include/asm-x86_64/dma-mapping.h
@@ -1,6 +1,138 @@
 #ifndef _X8664_DMA_MAPPING_H
 #define _X8664_DMA_MAPPING_H 1
 
-#include <asm-generic/dma-mapping.h>
+/*
+ * IOMMU interface. See Documentation/DMA-mapping.txt and DMA-API.txt for
+ * documentation.
+ */
+
+#include <linux/config.h>
+
+#include <asm/scatterlist.h>
+#include <asm/io.h>
+#include <asm/swiotlb.h>
+
+extern dma_addr_t bad_dma_address;
+#define dma_mapping_error(x) \
+	(swiotlb ? swiotlb_dma_mapping_error(x) : ((x) == bad_dma_address))
+
+void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+			 unsigned gfp);
+void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+			 dma_addr_t dma_handle);
+
+#ifdef CONFIG_GART_IOMMU
+
+extern dma_addr_t dma_map_single(struct device *hwdev, void *ptr, size_t size,
+				 int direction);
+extern void dma_unmap_single(struct device *dev, dma_addr_t addr,size_t size,
+			     int direction);
+
+#else
+
+/* No IOMMU */
+
+static inline dma_addr_t dma_map_single(struct device *hwdev, void *ptr,
+					size_t size, int direction)
+{
+	dma_addr_t addr;
+
+	if (direction == DMA_NONE)
+		out_of_line_bug();
+	addr = virt_to_bus(ptr);
+
+	if ((addr+size) & ~*hwdev->dma_mask)
+		out_of_line_bug();
+	return addr;
+}
+
+static inline void dma_unmap_single(struct device *hwdev, dma_addr_t dma_addr,
+				    size_t size, int direction)
+{
+	if (direction == DMA_NONE)
+		out_of_line_bug();
+	/* Nothing to do */
+}
+
+#endif
+
+#define dma_map_page(dev,page,offset,size,dir) \
+	dma_map_single((dev), page_address(page)+(offset), (size), (dir))
+
+static inline void dma_sync_single_for_cpu(struct device *hwdev,
+					       dma_addr_t dma_handle,
+					       size_t size, int direction)
+{
+	if (direction == DMA_NONE)
+		out_of_line_bug();
+
+	if (swiotlb)
+		return swiotlb_sync_single_for_cpu(hwdev,dma_handle,size,direction);
+
+	flush_write_buffers();
+}
+
+static inline void dma_sync_single_for_device(struct device *hwdev,
+						  dma_addr_t dma_handle,
+						  size_t size, int direction)
+{
+        if (direction == DMA_NONE)
+		out_of_line_bug();
+
+	if (swiotlb)
+		return swiotlb_sync_single_for_device(hwdev,dma_handle,size,direction);
+
+	flush_write_buffers();
+}
+
+static inline void dma_sync_sg_for_cpu(struct device *hwdev,
+				       struct scatterlist *sg,
+				       int nelems, int direction)
+{
+	if (direction == DMA_NONE)
+		out_of_line_bug();
+
+	if (swiotlb)
+		return swiotlb_sync_sg_for_cpu(hwdev,sg,nelems,direction);
+
+	flush_write_buffers();
+}
+
+static inline void dma_sync_sg_for_device(struct device *hwdev,
+					  struct scatterlist *sg,
+					  int nelems, int direction)
+{
+	if (direction == DMA_NONE)
+		out_of_line_bug();
+
+	if (swiotlb)
+		return swiotlb_sync_sg_for_device(hwdev,sg,nelems,direction);
+
+	flush_write_buffers();
+}
+
+extern int dma_map_sg(struct device *hwdev, struct scatterlist *sg,
+		      int nents, int direction);
+extern void dma_unmap_sg(struct device *hwdev, struct scatterlist *sg,
+			 int nents, int direction);
+
+#define dma_unmap_page dma_unmap_single
+
+extern int dma_supported(struct device *hwdev, u64 mask);
+extern int dma_get_cache_alignment(void);
+#define dma_is_consistent(h) 1
+
+static inline int dma_set_mask(struct device *dev, u64 mask)
+{
+	if (!dev->dma_mask || !dma_supported(dev, mask))
+		return -EIO;
+	*dev->dma_mask = mask;
+	return 0;
+}
+
+static inline void dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction dir)
+{
+	flush_write_buffers();
+}
 
 #endif
diff --git a/include/asm-x86_64/elf.h b/include/asm-x86_64/elf.h
index e72f10fef..9839b92d2 100644
--- a/include/asm-x86_64/elf.h
+++ b/include/asm-x86_64/elf.h
@@ -144,6 +144,13 @@ typedef struct user_i387_struct elf_fpregset_t;
 extern void set_personality_64bit(void);
 #define SET_PERSONALITY(ex, ibcs2) set_personality_64bit()
 	
+/*
+ * An executable for which elf_read_implies_exec() returns TRUE will
+ * have the READ_IMPLIES_EXEC personality flag set automatically.
+ */
+#define elf_read_implies_exec_binary(ex, have_pt_gnu_stack)   \
+	 (!(have_pt_gnu_stack))
+
 extern int dump_task_regs (struct task_struct *, elf_gregset_t *);
 extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
 
diff --git a/include/asm-x86_64/hardirq.h b/include/asm-x86_64/hardirq.h
index d3c08b2a0..9ce1a7808 100644
--- a/include/asm-x86_64/hardirq.h
+++ b/include/asm-x86_64/hardirq.h
@@ -37,20 +37,6 @@
 #define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
 #define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
 
-#define __MASK(x)	((1UL << (x))-1)
-
-#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
-#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
-
-#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
-#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
-#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
-
-#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
-#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
-#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
-
 /*
  * The hardirq mask has to be large enough to have
  * space for potentially all IRQ sources in the system
@@ -60,31 +46,10 @@
 # error HARDIRQ_BITS is too low!
 #endif
 
-/*
- * Are we doing bottom half or hardware interrupt processing?
- * Are we in a softirq context? Interrupt context?
- */
-#define in_irq()		(hardirq_count())
-#define in_softirq()		(softirq_count())
-#define in_interrupt()		(irq_count())
-
-
-#define hardirq_trylock()	(!in_interrupt())
-#define hardirq_endlock()	do { } while (0)
-
-#define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 #define nmi_enter()		(irq_enter())
 #define nmi_exit()		(preempt_count() -= HARDIRQ_OFFSET)
 
-
-#ifdef CONFIG_PREEMPT
-# include <linux/smp_lock.h>
-# define in_atomic()   ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
-# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
-#else
-# define in_atomic()   (preempt_count() != 0)
-# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
-#endif
+#define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 #define irq_exit()							\
 do {									\
 		preempt_count() -= IRQ_EXIT_OFFSET;			\
@@ -93,10 +58,4 @@ do {									\
 		preempt_enable_no_resched();				\
 } while (0)
 
-#ifndef CONFIG_SMP
-# define synchronize_irq(irq)	barrier()
-#else
-  extern void synchronize_irq(unsigned int irq);
-#endif /* CONFIG_SMP */
-
 #endif /* __ASM_HARDIRQ_H */
diff --git a/include/asm-x86_64/hw_irq.h b/include/asm-x86_64/hw_irq.h
index 2df689dd6..4a4281652 100644
--- a/include/asm-x86_64/hw_irq.h
+++ b/include/asm-x86_64/hw_irq.h
@@ -101,6 +101,7 @@ extern void disable_IO_APIC(void);
 extern void print_IO_APIC(void);
 extern int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn);
 extern void send_IPI(int dest, int vector);
+extern void setup_ioapic_dest(void);
 
 extern unsigned long io_apic_irqs;
 
@@ -129,40 +130,6 @@ __asm__( \
 	"push $" #nr "-256 ; " \
 	"jmp common_interrupt");
 
-static inline void x86_do_profile (struct pt_regs *regs) 
-{
-	unsigned long rip;
-	extern unsigned long prof_cpu_mask;
-	extern char _stext[];
- 
-	profile_hook(regs);
-
-	if (user_mode(regs))
-		return;
-	if (!prof_buffer)
-		return;
-
-	rip = regs->rip;
-
-	/*
-	 * Only measure the CPUs specified by /proc/irq/prof_cpu_mask.
-	 * (default is all CPUs.)
-	 */
-	if (!((1<<smp_processor_id()) & prof_cpu_mask))
-		return;
-
-	rip -= (unsigned long) &_stext;
-	rip >>= prof_shift;
-	/*
-	 * Don't ignore out-of-bounds EIP values silently,
-	 * put them into the last histogram slot, so if
-	 * present, they will show up as a sharp peak.
-	 */
-	if (rip > prof_len-1)
-		rip = prof_len-1;
-	atomic_inc((atomic_t *)&prof_buffer[rip]);
-}
-
 #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP)
 static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {
 	if (IO_APIC_IRQ(i))
diff --git a/include/asm-x86_64/i387.h b/include/asm-x86_64/i387.h
index 229401824..e613b8b16 100644
--- a/include/asm-x86_64/i387.h
+++ b/include/asm-x86_64/i387.h
@@ -39,16 +39,25 @@ static inline int need_signal_i387(struct task_struct *me)
  * FPU lazy state save handling...
  */
 
-#define kernel_fpu_end() stts()
-
 #define unlazy_fpu(tsk) do { \
 	if ((tsk)->thread_info->status & TS_USEDFPU) \
 		save_init_fpu(tsk); \
 } while (0)
 
+/* Ignore delayed exceptions from user space */
+static inline void tolerant_fwait(void)
+{
+	asm volatile("1: fwait\n"
+		     "2:\n"
+		     "   .section __ex_table,\"a\"\n"
+		     "	.align 8\n"
+		     "	.quad 1b,2b\n"
+		     "	.previous\n");
+}
+
 #define clear_fpu(tsk) do { \
 	if ((tsk)->thread_info->status & TS_USEDFPU) {		\
-		asm volatile("fnclex ; fwait");			\
+		tolerant_fwait();				\
 		(tsk)->thread_info->status &= ~TS_USEDFPU;	\
 		stts();						\
 	}							\
@@ -116,6 +125,7 @@ static inline int save_i387_checking(struct i387_fxsave_struct __user *fx)
 static inline void kernel_fpu_begin(void)
 {
 	struct thread_info *me = current_thread_info();
+	preempt_disable();
 	if (me->status & TS_USEDFPU) { 
 		asm volatile("rex64 ; fxsave %0 ; fnclex"
 			      : "=m" (me->task->thread.i387.fxsave));
@@ -125,9 +135,15 @@ static inline void kernel_fpu_begin(void)
 	clts();
 }
 
+static inline void kernel_fpu_end(void)
+{
+	stts();
+	preempt_enable();
+}
+
 static inline void save_init_fpu( struct task_struct *tsk )
 {
-	asm volatile( "fxsave %0 ; fnclex"
+	asm volatile( "rex64 ; fxsave %0 ; fnclex"
 		      : "=m" (tsk->thread.i387.fxsave));
 	tsk->thread_info->status &= ~TS_USEDFPU;
 	stts();
diff --git a/include/asm-x86_64/ia32.h b/include/asm-x86_64/ia32.h
index a680d0356..73319a9a8 100644
--- a/include/asm-x86_64/ia32.h
+++ b/include/asm-x86_64/ia32.h
@@ -78,12 +78,6 @@ struct stat64 {
 	unsigned long long	st_ino;
 } __attribute__((packed));
 
-
-typedef union sigval32 {
-	int sival_int;
-	unsigned int sival_ptr;
-} sigval_t32;
-
 typedef struct siginfo32 {
 	int si_signo;
 	int si_errno;
@@ -102,7 +96,7 @@ typedef struct siginfo32 {
 		struct {
 			int _tid;		/* timer id */
 			int _overrun;		/* overrun count */
-			sigval_t32 _sigval;	/* same as below */
+			compat_sigval_t _sigval;	/* same as below */
 			int _sys_private;	/* not to be passed to user */
 			int _overrun_incr;	/* amount to add to overrun */
 		} _timer;
@@ -111,7 +105,7 @@ typedef struct siginfo32 {
 		struct {
 			unsigned int _pid;	/* sender's pid */
 			unsigned int _uid;	/* sender's uid */
-			sigval_t32 _sigval;
+			compat_sigval_t _sigval;
 		} _rt;
 
 		/* SIGCHLD */
diff --git a/include/asm-x86_64/ia32_unistd.h b/include/asm-x86_64/ia32_unistd.h
index ff0309c2e..26e56c27f 100644
--- a/include/asm-x86_64/ia32_unistd.h
+++ b/include/asm-x86_64/ia32_unistd.h
@@ -289,7 +289,8 @@
 #define __NR_ia32_mq_notify		(__NR_ia32_mq_open+4)
 #define __NR_ia32_mq_getsetattr	(__NR_ia32_mq_open+5)
 #define __NR_ia32_kexec		283
+#define __NR_ia32_waitid		284
 
-#define IA32_NR_syscalls 287	/* must be > than biggest syscall! */
+#define IA32_NR_syscalls 285	/* must be > than biggest syscall! */
 
 #endif /* _ASM_X86_64_IA32_UNISTD_H_ */
diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
index 1ddce4b4a..d5a214064 100644
--- a/include/asm-x86_64/io.h
+++ b/include/asm-x86_64/io.h
@@ -135,9 +135,9 @@ extern inline void * phys_to_virt(unsigned long address)
 #define page_to_phys(page)	((page - mem_map) << PAGE_SHIFT)
 #endif
 
-extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
+extern void __iomem *__ioremap(unsigned long offset, unsigned long size, unsigned long flags);
 
-extern inline void * ioremap (unsigned long offset, unsigned long size)
+extern inline void __iomem * ioremap (unsigned long offset, unsigned long size)
 {
 	return __ioremap(offset, size, 0);
 }
@@ -147,8 +147,8 @@ extern inline void * ioremap (unsigned long offset, unsigned long size)
  * it's useful if some control registers are in such an area and write combining
  * or read caching is not desirable:
  */
-extern void * ioremap_nocache (unsigned long offset, unsigned long size);
-extern void iounmap(void *addr);
+extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size);
+extern void iounmap(void __iomem *addr);
 
 /*
  * ISA I/O bus memory addresses are 1:1 with the physical address.
@@ -173,10 +173,10 @@ extern void iounmap(void *addr);
  * memory location directly.
  */
 
-#define readb(addr) (*(volatile unsigned char *) (addr))
-#define readw(addr) (*(volatile unsigned short *) (addr))
-#define readl(addr) (*(volatile unsigned int *) (addr))
-#define readq(addr) (*(volatile unsigned long *) (addr))
+#define readb(addr) (*(__force volatile __u8 *) (__u8 __iomem *)(addr))
+#define readw(addr) (*(__force volatile __u16 *) (__u16 __iomem *)(addr))
+#define readl(addr) (*(__force volatile __u32 *) (__u32 __iomem *)(addr))
+#define readq(addr) (*(__force volatile __u64 *) (__u64 __iomem *)(addr))
 #define readb_relaxed(a) readb(a)
 #define readw_relaxed(a) readw(a)
 #define readl_relaxed(a) readl(a)
@@ -186,10 +186,30 @@ extern void iounmap(void *addr);
 #define __raw_readl readl
 #define __raw_readq readq
 
-#define writeb(b,addr) (*(volatile unsigned char *) (addr) = (b))
-#define writew(b,addr) (*(volatile unsigned short *) (addr) = (b))
-#define writel(b,addr) (*(volatile unsigned int *) (addr) = (b))
-#define writeq(b,addr) (*(volatile unsigned long *) (addr) = (b))
+#ifdef CONFIG_UNORDERED_IO
+static inline void __writel(__u32 val, void __iomem *addr)
+{
+	volatile __u32 __iomem *target = addr;
+	asm volatile("movnti %1,%0"
+		     : "=m" (*target)
+		     : "r" (val) : "memory");
+}
+
+static inline void __writeq(__u64 val, void __iomem *addr)
+{
+	volatile __u64 *target = addr;
+	asm volatile("movnti %1,%0"
+		     : "=m" (*target)
+		     : "r" (val) : "memory");
+}
+#define writeq(val,addr) __writeq((val),(void __iomem *)(addr))
+#define writel(val,addr) __writel((val),(void __iomem *)(addr))
+#else
+#define writel(b,addr) (*(__force volatile __u32 *)(__u32 __iomem *)(addr) = (b))
+#define writeq(b,addr) (*(__force volatile __u64 *)(__u64 __iomem *)(addr) = (b))
+#endif
+#define writeb(b,addr) (*(__force volatile __u8 *)(__u8 __iomem *)(addr) = (b))
+#define writew(b,addr) (*(__force volatile __u16 *)(__u16 __iomem *)(addr) = (b))
 #define __raw_writeb writeb
 #define __raw_writew writew
 #define __raw_writel writel
@@ -199,10 +219,10 @@ void *__memcpy_fromio(void*,unsigned long,unsigned);
 void *__memcpy_toio(unsigned long,const void*,unsigned);
 
 #define memcpy_fromio(to,from,len) \
-  __memcpy_fromio((to),(unsigned long)(from),(len))
+  __memcpy_fromio((to),(unsigned long)(void __iomem *)(from),(len))
 #define memcpy_toio(to,from,len) \
-  __memcpy_toio((unsigned long)(to),(from),(len))
-#define memset_io(a,b,c)	memset((void *)(a),(b),(c))
+  __memcpy_toio((unsigned long)(void __iomem *)(to),(from),(len))
+#define memset_io(a,b,c)	memset((__force void *)(void __iomem *)(a),(b),(c))
 
 /*
  * ISA space is 'always mapped' on a typical x86 system, no need to
@@ -212,7 +232,7 @@ void *__memcpy_toio(unsigned long,const void*,unsigned);
  * used as the IO-area pointer (it can be iounmapped as well, so the
  * analogy with PCI is quite large):
  */
-#define __ISA_IO_base ((char *)(PAGE_OFFSET))
+#define __ISA_IO_base ((char __iomem *)(PAGE_OFFSET))
 
 #define isa_readb(a) readb(__ISA_IO_base + (a))
 #define isa_readw(a) readw(__ISA_IO_base + (a))
@@ -299,11 +319,8 @@ out:
 
 #define flush_write_buffers() 
 
-/* Disable vmerge for now. Need to fix the block layer code
-   to check for non iommu addresses first.
-   When the IOMMU is force it is safe to enable. */
-extern int iommu_merge;
-#define BIO_VMERGE_BOUNDARY (iommu_merge ? 4096 : 0)
+extern int iommu_bio_merge;
+#define BIO_VMERGE_BOUNDARY iommu_bio_merge
 
 #endif /* __KERNEL__ */
 
diff --git a/include/asm-x86_64/mpspec.h b/include/asm-x86_64/mpspec.h
index 2768b7c83..98aa63e6b 100644
--- a/include/asm-x86_64/mpspec.h
+++ b/include/asm-x86_64/mpspec.h
@@ -156,8 +156,8 @@ struct mpc_config_lintsrc
  *	7	2 CPU MCA+PCI
  */
 
+#define MAX_MP_BUSSES 270
 #define MAX_IRQ_SOURCES 256
-#define MAX_MP_BUSSES 32
 enum mp_bustype {
 	MP_BUS_ISA = 1,
 	MP_BUS_EISA,
@@ -166,7 +166,6 @@ enum mp_bustype {
 };
 extern unsigned char mp_bus_id_to_type [MAX_MP_BUSSES];
 extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
-extern cpumask_t pci_bus_to_cpumask [256];
 
 extern unsigned int boot_cpu_physical_apicid;
 extern int smp_found_config;
diff --git a/include/asm-x86_64/msi.h b/include/asm-x86_64/msi.h
index e0e1e9b3b..9932d0b76 100644
--- a/include/asm-x86_64/msi.h
+++ b/include/asm-x86_64/msi.h
@@ -7,10 +7,11 @@
 #define ASM_MSI_H
 
 #include <asm/desc.h>
+#include <asm/smp.h>
 
 #define LAST_DEVICE_VECTOR		232
 #define MSI_DEST_MODE			MSI_LOGICAL_MODE
 #define MSI_TARGET_CPU_SHIFT		12
-#define MSI_TARGET_CPU			TARGET_CPUS
+#define MSI_TARGET_CPU			logical_smp_processor_id()
 
 #endif /* ASM_MSI_H */
diff --git a/include/asm-x86_64/mtrr.h b/include/asm-x86_64/mtrr.h
index 5e20e10dd..aa4f76c90 100644
--- a/include/asm-x86_64/mtrr.h
+++ b/include/asm-x86_64/mtrr.h
@@ -71,8 +71,6 @@ struct mtrr_gentry
 
 #ifdef __KERNEL__
 
-extern char *mtrr_strings[MTRR_NUM_TYPES];
-
 /*  The following functions are for use by other drivers  */
 # ifdef CONFIG_MTRR
 extern int mtrr_add (unsigned long base, unsigned long size,
diff --git a/include/asm-x86_64/pci.h b/include/asm-x86_64/pci.h
index ac9e9581d..1b2423fdc 100644
--- a/include/asm-x86_64/pci.h
+++ b/include/asm-x86_64/pci.h
@@ -44,81 +44,25 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq);
 #include <asm/io.h>
 #include <asm/page.h>
 
-struct pci_dev;
-
 extern int iommu_setup(char *opt);
 
-extern dma_addr_t bad_dma_address;
-#define pci_dma_mapping_error(x) ((x) == bad_dma_address)
-
-/* Allocate and map kernel buffer using consistent mode DMA for a device.
- * hwdev should be valid struct pci_dev pointer for PCI devices,
- * NULL for PCI-like buses (ISA, EISA).
- * Returns non-NULL cpu-view pointer to the buffer if successful and
- * sets *dma_addrp to the pci side dma address as well, else *dma_addrp
- * is undefined.
- */
-extern void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
-				  dma_addr_t *dma_handle);
-
-/* Free and unmap a consistent DMA buffer.
- * cpu_addr is what was returned from pci_alloc_consistent,
- * size must be the same as what as passed into pci_alloc_consistent,
- * and likewise dma_addr must be the same as what *dma_addrp was set to.
- *
- * References to the memory and mappings associated with cpu_addr/dma_addr
- * past this call are illegal.
- */
-extern void pci_free_consistent(struct pci_dev *hwdev, size_t size,
-				void *vaddr, dma_addr_t dma_handle);
-
-#ifdef CONFIG_SWIOTLB
-extern int swiotlb; 
-extern dma_addr_t swiotlb_map_single (struct device *hwdev, void *ptr, size_t size, 
-				      int dir);
-extern void swiotlb_unmap_single (struct device *hwdev, dma_addr_t dev_addr,
-				  size_t size, int dir);
-extern void swiotlb_sync_single_for_cpu (struct device *hwdev,
-					 dma_addr_t dev_addr,
-					 size_t size, int dir);
-extern void swiotlb_sync_single_for_device (struct device *hwdev,
-					    dma_addr_t dev_addr,
-					    size_t size, int dir);
-extern void swiotlb_sync_sg_for_cpu (struct device *hwdev,
-				     struct scatterlist *sg, int nelems,
-				     int dir);
-extern void swiotlb_sync_sg_for_device (struct device *hwdev,
-					struct scatterlist *sg, int nelems,
-					int dir);
-extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg,
-		      int nents, int direction);
-extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg,
-			 int nents, int direction);
-
-#endif
-
 #ifdef CONFIG_GART_IOMMU
-
-/* Map a single buffer of the indicated size for DMA in streaming mode.
- * The 32-bit bus address to use is returned.
+/* The PCI address space does equal the physical memory
+ * address space.  The networking and block device layers use
+ * this boolean for bounce buffer decisions
  *
- * Once the device is given the dma address, the device owns this memory
- * until either pci_unmap_single or pci_dma_sync_single_for_cpu is performed.
+ * On AMD64 it mostly equals, but we set it to zero to tell some subsystems
+ * that an IOMMU is available.
  */
-extern dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, 
-				 int direction);
-
-
-void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t addr,
-				   size_t size, int direction);
+#define PCI_DMA_BUS_IS_PHYS	(no_iommu ? 1 : 0)
 
 /*
- * pci_{map,unmap}_single_page maps a kernel page to a dma_addr_t. identical
- * to pci_map_single, but takes a struct page instead of a virtual address
+ * x86-64 always supports DAC, but sometimes it is useful to force
+ * devices through the IOMMU to get automatic sg list merging.
+ * Optional right now.
  */
-
-#define pci_map_page(dev,page,offset,size,dir) \
-	pci_map_single((dev), page_address(page)+(offset), (size), (dir)) 
+extern int iommu_sac_force;
+#define pci_dac_dma_supported(pci_dev, mask)	(!iommu_sac_force)
 
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	\
 	dma_addr_t ADDR_NAME;
@@ -133,113 +77,12 @@ void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t addr,
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
 	(((PTR)->LEN_NAME) = (VAL))
 
-static inline void pci_dma_sync_single_for_cpu(struct pci_dev *hwdev,
-					       dma_addr_t dma_handle,
-					       size_t size, int direction)
-{
-	BUG_ON(direction == PCI_DMA_NONE); 
-
-#ifdef CONFIG_SWIOTLB
-	if (swiotlb)
-		return swiotlb_sync_single_for_cpu(&hwdev->dev,dma_handle,size,direction);
-#endif
-
-	flush_write_buffers();
-} 
-
-static inline void pci_dma_sync_single_for_device(struct pci_dev *hwdev,
-						  dma_addr_t dma_handle,
-						  size_t size, int direction)
-{
-	BUG_ON(direction == PCI_DMA_NONE);
-
-#ifdef CONFIG_SWIOTLB
-	if (swiotlb)
-		return swiotlb_sync_single_for_device(&hwdev->dev,dma_handle,size,direction);
-#endif
-
-	flush_write_buffers();
-}
-
-static inline void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev,
-					   struct scatterlist *sg,
-					   int nelems, int direction)
-{
-	BUG_ON(direction == PCI_DMA_NONE);
-
-#ifdef CONFIG_SWIOTLB
-	if (swiotlb)
-		return swiotlb_sync_sg_for_cpu(&hwdev->dev,sg,nelems,direction);
-#endif
-	flush_write_buffers();
-}
-
-static inline void pci_dma_sync_sg_for_device(struct pci_dev *hwdev,
-					      struct scatterlist *sg,
-					      int nelems, int direction)
-{ 
-	BUG_ON(direction == PCI_DMA_NONE); 
-
-#ifdef CONFIG_SWIOTLB
-	if (swiotlb)
-		return swiotlb_sync_sg_for_device(&hwdev->dev,sg,nelems,direction);
-#endif
-	flush_write_buffers();
-} 
-
-/* The PCI address space does equal the physical memory
- * address space.  The networking and block device layers use
- * this boolean for bounce buffer decisions
- *
- * On AMD64 it mostly equals, but we set it to zero to tell some subsystems
- * that an IOMMU is available.
- */
-#define PCI_DMA_BUS_IS_PHYS	(no_iommu ? 1 : 0) 
-
-/* We lie slightly when the IOMMU is forced to get the device to 
-   use SAC instead of DAC. */
-#define pci_dac_dma_supported(pci_dev, mask)	(force_iommu ? 0 : 1)
-
 #else
-static inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr,
-					size_t size, int direction)
-{
-	dma_addr_t addr; 
+/* No IOMMU */
 
-	if (direction == PCI_DMA_NONE)
-		out_of_line_bug();	
-	addr = virt_to_bus(ptr); 
-
-	/* 
-	 * This is gross, but what should I do.
-	 * Unfortunately drivers do not test the return value of this.
- */
-	if ((addr+size) & ~hwdev->dma_mask) 
-		out_of_line_bug(); 
-	return addr;
-}
-
-static inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
-				    size_t size, int direction)
-{
-	if (direction == PCI_DMA_NONE)
-		out_of_line_bug();
-	/* Nothing to do */
-}
-
-static inline dma_addr_t pci_map_page(struct pci_dev *hwdev, struct page *page,
-				      unsigned long offset, size_t size, int direction)
-{
-	dma_addr_t addr;
-	if (direction == PCI_DMA_NONE)
-		out_of_line_bug();	
- 	addr = page_to_pfn(page) * PAGE_SIZE + offset;
-	if ((addr+size) & ~hwdev->dma_mask) 
-		out_of_line_bug();
-	return addr;
-}
+#define PCI_DMA_BUS_IS_PHYS	1
+#define pci_dac_dma_supported(pci_dev, mask)    1
 
-/* pci_unmap_{page,single} is a nop so... */
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
 #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
 #define pci_unmap_addr(PTR, ADDR_NAME)		(0)
@@ -247,74 +90,9 @@ static inline dma_addr_t pci_map_page(struct pci_dev *hwdev, struct page *page,
 #define pci_unmap_len(PTR, LEN_NAME)		(0)
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
 
-/* Make physical memory consistent for a single
- * streaming mode DMA translation after a transfer.
- *
- * If you perform a pci_map_single() but wish to interrogate the
- * buffer using the cpu, yet do not wish to teardown the PCI dma
- * mapping, you must call this function before doing so.  At the
- * next point you give the PCI dma address back to the card, you
- * must first perform a pci_dma_sync_for_device, and then the
- * device again owns the buffer.
- */
-static inline void pci_dma_sync_single_for_cpu(struct pci_dev *hwdev,
-					       dma_addr_t dma_handle,
-					       size_t size, int direction)
-{
-	if (direction == PCI_DMA_NONE)
-		out_of_line_bug();
-}
-
-static inline void pci_dma_sync_single_for_device(struct pci_dev *hwdev,
-						  dma_addr_t dma_handle,
-						  size_t size, int direction)
-{
-	if (direction == PCI_DMA_NONE)
-		out_of_line_bug();
-	flush_write_buffers();
-}
-
-/* Make physical memory consistent for a set of streaming
- * mode DMA translations after a transfer.
- *
- * The same as pci_dma_sync_single_* but for a scatter-gather list,
- * same rules and usage.
- */
-static inline void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev,
-					   struct scatterlist *sg,
-					   int nelems, int direction)
-{
-	if (direction == PCI_DMA_NONE)
-		out_of_line_bug();
-}
-
-static inline void pci_dma_sync_sg_for_device(struct pci_dev *hwdev,
-					      struct scatterlist *sg,
-					      int nelems, int direction)
-{
-	if (direction == PCI_DMA_NONE)
-		out_of_line_bug();
-	flush_write_buffers();
-}
-
-#define PCI_DMA_BUS_IS_PHYS	1
-
-#define pci_dac_dma_supported(pci_dev, mask)	1
 #endif
 
-extern int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-		      int nents, int direction);
-extern void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-			 int nents, int direction);
-
-#define pci_unmap_page pci_unmap_single
-
-/* Return whether the given PCI device DMA address mask can
- * be supported properly.  For example, if your device can
- * only drive the low 24-bits during PCI bus mastering, then
- * you would pass 0x00ffffff as the mask to this function.
- */
-extern int pci_dma_supported(struct pci_dev *hwdev, u64 mask);
+#include <asm-generic/pci-dma-compat.h>
 
 static inline dma64_addr_t
 pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page, unsigned long offset, int direction)
@@ -359,7 +137,6 @@ static inline void pcibios_add_platform_entries(struct pci_dev *dev)
 /* generic pci stuff */
 #ifdef CONFIG_PCI
 #include <asm-generic/pci.h>
-#include <linux/dma-mapping.h>
 #endif
 
 #endif /* __x8664_PCI_H */
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
index 934828c82..b42eec0e1 100644
--- a/include/asm-x86_64/processor.h
+++ b/include/asm-x86_64/processor.h
@@ -18,6 +18,7 @@
 #include <asm/current.h>
 #include <asm/system.h>
 #include <asm/mmsegment.h>
+#include <asm/percpu.h>
 #include <linux/personality.h>
 
 #define TF_MASK		0x00000100
@@ -60,6 +61,8 @@ struct cpuinfo_x86 {
 	int	x86_cache_alignment;
 	int	x86_tlbsize;	/* number of 4K pages in DTLB/ITLB combined(in pages)*/
         __u8    x86_virt_bits, x86_phys_bits;
+	__u8	x86_num_cores;
+	__u8	x86_apicid;
         __u32   x86_power; 	
 	unsigned long loops_per_jiffy;
 } ____cacheline_aligned;
@@ -75,14 +78,11 @@ struct cpuinfo_x86 {
 #define X86_VENDOR_NUM 8
 #define X86_VENDOR_UNKNOWN 0xff
 
-extern struct cpuinfo_x86 boot_cpu_data;
-extern struct tss_struct init_tss[NR_CPUS];
-
 #ifdef CONFIG_SMP
 extern struct cpuinfo_x86 cpu_data[];
 #define current_cpu_data cpu_data[smp_processor_id()]
 #else
-#define cpu_data &boot_cpu_data
+#define cpu_data (&boot_cpu_data)
 #define current_cpu_data boot_cpu_data
 #endif
 
@@ -227,6 +227,9 @@ struct tss_struct {
 	unsigned long io_bitmap[IO_BITMAP_LONGS + 1];
 } __attribute__((packed)) ____cacheline_aligned;
 
+extern struct cpuinfo_x86 boot_cpu_data;
+DECLARE_PER_CPU(struct tss_struct,init_tss);
+
 #define ARCH_MIN_TASKALIGN	16
 
 struct thread_struct {
@@ -251,6 +254,7 @@ struct thread_struct {
    switch faster for a limited number of ioperm using tasks. -AK */
 	int		ioperm;
 	unsigned long	*io_bitmap_ptr;
+	unsigned io_bitmap_max;
 /* cached TLS descriptors. */
 	u64 tls_array[GDT_ENTRY_TLS_ENTRIES];
 } __attribute__((aligned(16)));
@@ -456,9 +460,4 @@ static inline void __mwait(unsigned long eax, unsigned long ecx)
 
 #define cache_line_size() (boot_cpu_data.x86_cache_alignment)
 
-#ifdef CONFIG_SCHED_SMT
-#define ARCH_HAS_SCHED_DOMAIN
-#define ARCH_HAS_SCHED_WAKE_IDLE
-#endif
-
 #endif /* __ASM_X86_64_PROCESSOR_H */
diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h
index 25faf9faa..f2223067a 100644
--- a/include/asm-x86_64/proto.h
+++ b/include/asm-x86_64/proto.h
@@ -70,6 +70,7 @@ extern void __show_regs(struct pt_regs * regs);
 extern void show_regs(struct pt_regs * regs);
 
 extern int map_syscall32(struct mm_struct *mm, unsigned long address);
+extern int __map_syscall32(struct mm_struct *mm, unsigned long address);
 extern char *syscall32_page;
 extern void syscall32_cpu_init(void);
 
@@ -82,7 +83,6 @@ extern int unhandled_signal(struct task_struct *tsk, int sig);
 
 extern void select_idle_routine(const struct cpuinfo_x86 *c);
 extern void swiotlb_init(void);
-extern int swiotlb;
 
 extern unsigned long max_mapnr;
 extern unsigned long end_pfn; 
@@ -103,6 +103,8 @@ extern int fallback_aper_force;
 extern int iommu_aperture;
 extern int iommu_aperture_disabled;
 extern int iommu_aperture_allowed;
+extern int fix_aperture;
+extern int force_iommu;
 
 extern void smp_local_timer_interrupt(struct pt_regs * regs);
 
diff --git a/include/asm-x86_64/ptrace.h b/include/asm-x86_64/ptrace.h
index cbc19a778..c7865cfed 100644
--- a/include/asm-x86_64/ptrace.h
+++ b/include/asm-x86_64/ptrace.h
@@ -83,6 +83,7 @@ struct pt_regs {
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__) 
 #define user_mode(regs) (!!((regs)->cs & 3))
 #define instruction_pointer(regs) ((regs)->rip)
+extern unsigned long profile_pc(struct pt_regs *regs);
 void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
 
 enum {
diff --git a/include/asm-x86_64/resource.h b/include/asm-x86_64/resource.h
index 9628f7717..f1b71c320 100644
--- a/include/asm-x86_64/resource.h
+++ b/include/asm-x86_64/resource.h
@@ -39,7 +39,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
 	{      INR_OPEN,     INR_OPEN  },		\
-	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{   MLOCK_LIMIT,   MLOCK_LIMIT },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ MAX_SIGPENDING, MAX_SIGPENDING },		\
diff --git a/include/asm-x86_64/semaphore.h b/include/asm-x86_64/semaphore.h
index 278883422..f325e39bf 100644
--- a/include/asm-x86_64/semaphore.h
+++ b/include/asm-x86_64/semaphore.h
@@ -47,21 +47,14 @@ struct semaphore {
 	atomic_t count;
 	int sleepers;
 	wait_queue_head_t wait;
-#ifdef WAITQUEUE_DEBUG
-	long __magic;
-#endif
 };
 
-#ifdef WAITQUEUE_DEBUG
-# define __SEM_DEBUG_INIT(name) \
-		, (int)&(name).__magic
-#else
-# define __SEM_DEBUG_INIT(name)
-#endif
-
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, n)				\
+{									\
+	.count		= ATOMIC_INIT(n),				\
+	.sleepers	= 0,						\
+	.wait		= __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+}
 
 #define __MUTEX_INITIALIZER(name) \
 	__SEMAPHORE_INITIALIZER(name,1)
@@ -83,9 +76,6 @@ static inline void sema_init (struct semaphore *sem, int val)
 	atomic_set(&sem->count, val);
 	sem->sleepers = 0;
 	init_waitqueue_head(&sem->wait);
-#ifdef WAITQUEUE_DEBUG
-	sem->__magic = (int)&sem->__magic;
-#endif
 }
 
 static inline void init_MUTEX (struct semaphore *sem)
@@ -115,9 +105,6 @@ asmlinkage void __up(struct semaphore * sem);
  */
 static inline void down(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	__asm__ __volatile__(
@@ -142,9 +129,6 @@ static inline int down_interruptible(struct semaphore * sem)
 {
 	int result;
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	might_sleep();
 
 	__asm__ __volatile__(
@@ -171,10 +155,6 @@ static inline int down_trylock(struct semaphore * sem)
 {
 	int result;
 
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
 	__asm__ __volatile__(
 		"# atomic interruptible down operation\n\t"
 		LOCK "decl %1\n\t"     /* --sem->count */
@@ -199,9 +179,6 @@ static inline int down_trylock(struct semaphore * sem)
  */
 static inline void up(struct semaphore * sem)
 {
-#ifdef WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
 	__asm__ __volatile__(
 		"# atomic up operation\n\t"
 		LOCK "incl %0\n\t"     /* ++sem->count */
diff --git a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h
index c210e398a..03841bec8 100644
--- a/include/asm-x86_64/smp.h
+++ b/include/asm-x86_64/smp.h
@@ -110,9 +110,13 @@ static inline int cpu_present_to_apicid(int mps_cpu)
 
 #endif
 #define INT_DELIVERY_MODE 1     /* logical delivery */
-#define TARGET_CPUS 1
 
 #ifndef ASSEMBLY
+#ifdef CONFIG_SMP
+#define TARGET_CPUS cpu_online_map
+#else
+#define TARGET_CPUS cpumask_of_cpu(0)
+#endif
 static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
 {
 	return cpus_addr(cpumask)[0];
@@ -133,5 +137,13 @@ static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
 })
 #endif
 
+#ifndef __ASSEMBLY__
+static __inline int logical_smp_processor_id(void)
+{
+	/* we don't want to mark this access volatile - bad code generation */
+	return GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR));
+}
+#endif
+
 #endif
 
diff --git a/include/asm-x86_64/socket.h b/include/asm-x86_64/socket.h
index 373e7abad..d9a252ea8 100644
--- a/include/asm-x86_64/socket.h
+++ b/include/asm-x86_64/socket.h
@@ -47,20 +47,4 @@
 
 #define SO_PEERSEC             31
 
-/* Nasty libc5 fixup - bletch */
-#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
-/* Socket types. */
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
-#define	SOCK_MAX	(SOCK_PACKET+1)
-#endif
-
 #endif /* _ASM_SOCKET_H */
diff --git a/include/asm-x86_64/spinlock.h b/include/asm-x86_64/spinlock.h
index 3177138f9..185e087e8 100644
--- a/include/asm-x86_64/spinlock.h
+++ b/include/asm-x86_64/spinlock.h
@@ -113,10 +113,8 @@ static inline int _raw_spin_trylock(spinlock_t *lock)
 static inline void _raw_spin_lock(spinlock_t *lock)
 {
 #ifdef CONFIG_DEBUG_SPINLOCK
-	__label__ here;
-here:
 	if (lock->magic != SPINLOCK_MAGIC) {
-printk("eip: %p\n", &&here);
+		printk("eip: %p\n", __builtin_return_address(0));
 		BUG();
 	}
 #endif
diff --git a/include/asm-x86_64/system.h b/include/asm-x86_64/system.h
index 6abaf66e6..6671eb655 100644
--- a/include/asm-x86_64/system.h
+++ b/include/asm-x86_64/system.h
@@ -297,11 +297,11 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
 #define mb() 	asm volatile("mfence":::"memory")
 #define rmb()	asm volatile("lfence":::"memory")
 
-/* could use SFENCE here, but it would be only needed for unordered SSE
-   store instructions and we always do an explicit sfence with them currently.
-   the ordering of normal stores is serialized enough. Just make it a compile
-   barrier. */
+#ifdef CONFIG_UNORDERED_IO
+#define wmb()	asm volatile("sfence" ::: "memory")
+#else
 #define wmb()	asm volatile("" ::: "memory")
+#endif
 #define read_barrier_depends()	do {} while(0)
 #define set_mb(var, value) do { xchg(&var, value); } while (0)
 #define set_wmb(var, value) do { var = value; wmb(); } while (0)
diff --git a/include/asm-x86_64/topology.h b/include/asm-x86_64/topology.h
index dbc3f1579..84f24e7a7 100644
--- a/include/asm-x86_64/topology.h
+++ b/include/asm-x86_64/topology.h
@@ -14,18 +14,23 @@ extern cpumask_t cpu_online_map;
 
 extern unsigned char cpu_to_node[];
 extern cpumask_t     node_to_cpumask[];
+extern cpumask_t pci_bus_to_cpumask[];
 
 #define cpu_to_node(cpu)		(cpu_to_node[cpu])
 #define parent_node(node)		(node)
 #define node_to_first_cpu(node) 	(__ffs(node_to_cpumask[node]))
 #define node_to_cpumask(node)		(node_to_cpumask[node])
 
-static inline cpumask_t pcibus_to_cpumask(int bus)
+static inline cpumask_t __pcibus_to_cpumask(int bus)
 {
+	cpumask_t busmask = pci_bus_to_cpumask[bus];
+	cpumask_t online = cpu_online_map;
 	cpumask_t res;
-	cpus_and(res,  pci_bus_to_cpumask[bus], cpu_online_map);
+	cpus_and(res, busmask, online);
 	return res;
 }
+/* broken generic file uses #ifndef later on this */
+#define pcibus_to_cpumask(bus) __pcibus_to_cpumask(bus)
 
 #define NODE_BALANCE_RATE 30	/* CHECKME */ 
 
diff --git a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h
index ba3d49d8a..a7b9d3305 100644
--- a/include/asm-x86_64/uaccess.h
+++ b/include/asm-x86_64/uaccess.h
@@ -137,6 +137,9 @@ extern void __put_user_bad(void);
 #define __put_user(x,ptr) \
   __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 
+#define __get_user_unaligned __get_user
+#define __put_user_unaligned __put_user
+
 #define __put_user_nocheck(x,ptr,size)			\
 ({							\
 	int __pu_err;					\
@@ -351,4 +354,7 @@ long strlen_user(const char __user *str);
 unsigned long clear_user(void __user *mem, unsigned long len);
 unsigned long __clear_user(void __user *mem, unsigned long len);
 
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
 #endif /* __X86_64_UACCESS_H */
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index 311e25a4f..030c41a14 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -552,8 +552,10 @@ __SYSCALL(__NR_mq_notify, sys_mq_notify)
 __SYSCALL(__NR_mq_getsetattr, sys_mq_getsetattr)
 #define __NR_kexec_load 	246
 __SYSCALL(__NR_kexec_load, sys_ni_syscall)
+#define __NR_waitid		247
+__SYSCALL(__NR_waitid, sys_waitid)
 
-#define __NR_syscall_max __NR_kexec_load
+#define __NR_syscall_max __NR_waitid
 #ifndef __NO_STUBS
 
 /* user-visible error numbers are in the range -1 - -4095 */
diff --git a/include/linux/acct.h b/include/linux/acct.h
index b46ce1ac1..a6ab17c49 100644
--- a/include/linux/acct.h
+++ b/include/linux/acct.h
@@ -172,17 +172,24 @@ static inline u32 jiffies_to_AHZ(unsigned long x)
 #endif
 }
 
-static inline u64 jiffies_64_to_AHZ(u64 x)
+static inline u64 nsec_to_AHZ(u64 x)
 {
-#if (TICK_NSEC % (NSEC_PER_SEC / AHZ)) == 0
-#if HZ != AHZ
-	do_div(x, HZ / AHZ);
-#endif
-#else
-	x *= TICK_NSEC;
+#if (NSEC_PER_SEC % AHZ) == 0
 	do_div(x, (NSEC_PER_SEC / AHZ));
+#elif (AHZ % 512) == 0
+	x *= AHZ/512;
+	do_div(x, (NSEC_PER_SEC / 512));
+#else
+	/*
+         * max relative error 5.7e-8 (1.8s per year) for AHZ <= 1024,
+         * overflow after 64.99 years.
+         * exact for AHZ=60, 72, 90, 120, 144, 180, 300, 600, 900, ...
+         */
+	x *= 9;
+	do_div(x, (unsigned long)((9ull * NSEC_PER_SEC + (AHZ/2))
+	                          / AHZ));
 #endif
-       return x;
+	return x;
 }
 
 #endif  /* __KERNEL */
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index f82aa67ea..041f660ec 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -453,14 +453,15 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver);
 
 #ifdef CONFIG_ACPI_EC
 
-int ec_read(u8 addr, u8 *val);
-int ec_write(u8 addr, u8 val);
+extern int ec_read(u8 addr, u8 *val);
+extern int ec_write(u8 addr, u8 val);
 
 #endif /*CONFIG_ACPI_EC*/
 
 #ifdef CONFIG_ACPI_INTERPRETER
 
-int acpi_blacklisted(void);
+extern int acpi_blacklisted(void);
+extern void acpi_bios_year(char *s);
 
 #else /*!CONFIG_ACPI_INTERPRETER*/
 
diff --git a/include/linux/adfs_fs.h b/include/linux/adfs_fs.h
index 9b49e9fcf..4a5d50c2b 100644
--- a/include/linux/adfs_fs.h
+++ b/include/linux/adfs_fs.h
@@ -17,20 +17,20 @@ struct adfs_discrecord {
     __u8  bootoption;
     __u8  lowsector;
     __u8  nzones;
-    __u16 zone_spare;
-    __u32 root;
-    __u32 disc_size;
-    __u16 disc_id;
+    __le16 zone_spare;
+    __le32 root;
+    __le32 disc_size;
+    __le16 disc_id;
     __u8  disc_name[10];
-    __u32 disc_type;
-    __u32 disc_size_high;
+    __le32 disc_type;
+    __le32 disc_size_high;
     __u8  log2sharesize:4;
     __u8  unused40:4;
     __u8  big_flag:1;
     __u8  unused41:1;
     __u8  nzones_high;
-    __u32 format_version;
-    __u32 root_size;
+    __le32 format_version;
+    __le32 root_size;
     __u8  unused52[60 - 52];
 };
 
diff --git a/include/linux/adfs_fs_i.h b/include/linux/adfs_fs_i.h
index 6341f7059..cb543034e 100644
--- a/include/linux/adfs_fs_i.h
+++ b/include/linux/adfs_fs_i.h
@@ -17,7 +17,7 @@ struct adfs_inode_info {
 	__u32		execaddr;	/* RISC OS exec address		*/
 	unsigned int	filetype;	/* RISC OS file type		*/
 	unsigned int	attr;		/* RISC OS permissions		*/
-	int		stamped:1;	/* RISC OS file has date/time	*/
+	unsigned int	stamped:1;	/* RISC OS file has date/time	*/
 	struct inode vfs_inode;
 };
 
diff --git a/include/linux/adfs_fs_sb.h b/include/linux/adfs_fs_sb.h
index 30082c823..d9bf05c02 100644
--- a/include/linux/adfs_fs_sb.h
+++ b/include/linux/adfs_fs_sb.h
@@ -31,7 +31,7 @@ struct adfs_sb_info {
 	unsigned long	s_size;		/* total size (in blocks) of this fs	 */
 	signed int	s_map2blk;	/* shift left by this for map->sector	 */
 	unsigned int	s_log2sharesize;/* log2 share size			 */
-	unsigned int	s_version;	/* disc format version			 */
+	__le32		s_version;	/* disc format version			 */
 	unsigned int	s_namelen;	/* maximum number of characters in name	 */
 };
 
diff --git a/include/linux/affs_fs.h b/include/linux/affs_fs.h
index 5ba9d6205..b52f1320f 100644
--- a/include/linux/affs_fs.h
+++ b/include/linux/affs_fs.h
@@ -32,7 +32,6 @@ extern int	affs_copy_name(unsigned char *bstr, struct dentry *dentry);
 
 /* bitmap. c */
 
-extern u32	affs_count_free_bits(u32 blocksize, const void *data);
 extern u32	affs_count_free_blocks(struct super_block *s);
 extern void	affs_free_block(struct super_block *sb, u32 block);
 extern u32	affs_alloc_block(struct inode *inode, u32 goal);
@@ -63,7 +62,7 @@ extern void			 affs_put_inode(struct inode *inode);
 extern void			 affs_delete_inode(struct inode *inode);
 extern void			 affs_clear_inode(struct inode *inode);
 extern void			 affs_read_inode(struct inode *inode);
-extern void			 affs_write_inode(struct inode *inode, int);
+extern int			 affs_write_inode(struct inode *inode, int);
 extern int			 affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s32 type);
 
 /* super.c */
diff --git a/include/linux/affs_hardblocks.h b/include/linux/affs_hardblocks.h
index ae893e022..3fb869939 100644
--- a/include/linux/affs_hardblocks.h
+++ b/include/linux/affs_hardblocks.h
@@ -5,13 +5,13 @@
 
 struct RigidDiskBlock {
 	u32	rdb_ID;
-	u32	rdb_SummedLongs;
+	__be32	rdb_SummedLongs;
 	s32	rdb_ChkSum;
 	u32	rdb_HostID;
-	u32	rdb_BlockBytes;
+	__be32	rdb_BlockBytes;
 	u32	rdb_Flags;
 	u32	rdb_BadBlockList;
-	u32	rdb_PartitionList;
+	__be32	rdb_PartitionList;
 	u32	rdb_FileSysHeaderList;
 	u32	rdb_DriveInit;
 	u32	rdb_Reserved1[6];
@@ -45,17 +45,17 @@ struct RigidDiskBlock {
 #define	IDNAME_RIGIDDISK	0x5244534B	/* "RDSK" */
 
 struct PartitionBlock {
-	u32	pb_ID;
-	u32	pb_SummedLongs;
+	__be32	pb_ID;
+	__be32	pb_SummedLongs;
 	s32	pb_ChkSum;
 	u32	pb_HostID;
-	u32	pb_Next;
+	__be32	pb_Next;
 	u32	pb_Flags;
 	u32	pb_Reserved1[2];
 	u32	pb_DevFlags;
 	u8	pb_DriveName[32];
 	u32	pb_Reserved2[15];
-	u32	pb_Environment[17];
+	__be32	pb_Environment[17];
 	u32	pb_EReserved[15];
 };
 
diff --git a/include/linux/aio.h b/include/linux/aio.h
index 461a3b073..a4d5af907 100644
--- a/include/linux/aio.h
+++ b/include/linux/aio.h
@@ -52,7 +52,7 @@ struct kiocb {
 	struct file		*ki_filp;
 	struct kioctx		*ki_ctx;	/* may be NULL for sync ops */
 	int			(*ki_cancel)(struct kiocb *, struct io_event *);
-	long			(*ki_retry)(struct kiocb *);
+	ssize_t			(*ki_retry)(struct kiocb *);
 	void			(*ki_dtor)(struct kiocb *);
 
 	struct list_head	ki_list;	/* the aio core uses this
@@ -64,6 +64,16 @@ struct kiocb {
 	} ki_obj;
 	__u64			ki_user_data;	/* user's data for completion */
 	loff_t			ki_pos;
+	/* State that we remember to be able to restart/retry  */
+	unsigned short		ki_opcode;
+	size_t			ki_nbytes; 	/* copy of iocb->aio_nbytes */
+	char 			__user *ki_buf;	/* remaining iocb->aio_buf */
+	size_t			ki_left; 	/* remaining bytes */
+	wait_queue_t		ki_wait;
+	long			ki_retried; 	/* just for testing */
+	long			ki_kicked; 	/* just for testing */
+	long			ki_queued; 	/* just for testing */
+
 	void			*private;
 };
 
@@ -79,6 +89,8 @@ struct kiocb {
 		(x)->ki_cancel = NULL;			\
 		(x)->ki_dtor = NULL;			\
 		(x)->ki_obj.tsk = tsk;			\
+		(x)->ki_user_data = 0;                  \
+		init_wait((&(x)->ki_wait));             \
 	} while (0)
 
 #define AIO_RING_MAGIC			0xa10a10a1
@@ -161,6 +173,20 @@ int FASTCALL(io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
 #define get_ioctx(kioctx)	do { if (unlikely(atomic_read(&(kioctx)->users) <= 0)) BUG(); atomic_inc(&(kioctx)->users); } while (0)
 #define put_ioctx(kioctx)	do { if (unlikely(atomic_dec_and_test(&(kioctx)->users))) __put_ioctx(kioctx); else if (unlikely(atomic_read(&(kioctx)->users) < 0)) BUG(); } while (0)
 
+#define in_aio() !is_sync_wait(current->io_wait)
+/* may be used for debugging */
+#define warn_if_async()							\
+do {									\
+	if (in_aio()) {							\
+		printk(KERN_ERR "%s(%s:%d) called in async context!\n",	\
+			__FUNCTION__, __FILE__, __LINE__);		\
+		dump_stack();						\
+	}								\
+} while (0)
+
+#define io_wait_to_kiocb(wait) container_of(wait, struct kiocb, ki_wait)
+#define is_retried_kiocb(iocb) ((iocb)->ki_retried > 1)
+
 #include <linux/aio_abi.h>
 
 static inline struct kiocb *list_kiocb(struct list_head *h)
diff --git a/include/linux/amigaffs.h b/include/linux/amigaffs.h
index 6fb6bb5c6..b9a0ee68c 100644
--- a/include/linux/amigaffs.h
+++ b/include/linux/amigaffs.h
@@ -80,14 +80,14 @@ affs_brelse(struct buffer_head *bh)
 static inline void
 affs_adjust_checksum(struct buffer_head *bh, u32 val)
 {
-	u32 tmp = be32_to_cpu(((u32 *)bh->b_data)[5]);
-	((u32 *)bh->b_data)[5] = cpu_to_be32(tmp - val);
+	u32 tmp = be32_to_cpu(((__be32 *)bh->b_data)[5]);
+	((__be32 *)bh->b_data)[5] = cpu_to_be32(tmp - val);
 }
 static inline void
 affs_adjust_bitmapchecksum(struct buffer_head *bh, u32 val)
 {
-	u32 tmp = be32_to_cpu(((u32 *)bh->b_data)[0]);
-	((u32 *)bh->b_data)[0] = cpu_to_be32(tmp - val);
+	u32 tmp = be32_to_cpu(((__be32 *)bh->b_data)[0]);
+	((__be32 *)bh->b_data)[0] = cpu_to_be32(tmp - val);
 }
 
 static inline void
@@ -164,89 +164,89 @@ affs_unlock_ext(struct inode *inode)
 #define AFFS_DATA(bh)		(((struct affs_data_head *)(bh)->b_data)->data)
 
 struct affs_date {
-	u32 days;
-	u32 mins;
-	u32 ticks;
+	__be32 days;
+	__be32 mins;
+	__be32 ticks;
 };
 
 struct affs_short_date {
-	u16 days;
-	u16 mins;
-	u16 ticks;
+	__be16 days;
+	__be16 mins;
+	__be16 ticks;
 };
 
 struct affs_root_head {
-	u32 ptype;
-	u32 spare1;
-	u32 spare2;
-	u32 hash_size;
-	u32 spare3;
-	u32 checksum;
-	u32 hashtable[1];
+	__be32 ptype;
+	__be32 spare1;
+	__be32 spare2;
+	__be32 hash_size;
+	__be32 spare3;
+	__be32 checksum;
+	__be32 hashtable[1];
 };
 
 struct affs_root_tail {
-	u32 bm_flag;
-	u32 bm_blk[AFFS_ROOT_BMAPS];
-	u32 bm_ext;
+	__be32 bm_flag;
+	__be32 bm_blk[AFFS_ROOT_BMAPS];
+	__be32 bm_ext;
 	struct affs_date root_change;
 	u8 disk_name[32];
-	u32 spare1;
-	u32 spare2;
+	__be32 spare1;
+	__be32 spare2;
 	struct affs_date disk_change;
 	struct affs_date disk_create;
-	u32 spare3;
-	u32 spare4;
-	u32 dcache;
-	u32 stype;
+	__be32 spare3;
+	__be32 spare4;
+	__be32 dcache;
+	__be32 stype;
 };
 
 struct affs_head {
-	u32 ptype;
-	u32 key;
-	u32 block_count;
-	u32 spare1;
-	u32 first_data;
-	u32 checksum;
-	u32 table[1];
+	__be32 ptype;
+	__be32 key;
+	__be32 block_count;
+	__be32 spare1;
+	__be32 first_data;
+	__be32 checksum;
+	__be32 table[1];
 };
 
 struct affs_tail {
-	u32 spare1;
-	u16 uid;
-	u16 gid;
-	u32 protect;
-	u32 size;
+	__be32 spare1;
+	__be16 uid;
+	__be16 gid;
+	__be32 protect;
+	__be32 size;
 	u8 comment[92];
 	struct affs_date change;
 	u8 name[32];
-	u32 spare2;
-	u32 original;
-	u32 link_chain;
-	u32 spare[5];
-	u32 hash_chain;
-	u32 parent;
-	u32 extension;
-	u32 stype;
+	__be32 spare2;
+	__be32 original;
+	__be32 link_chain;
+	__be32 spare[5];
+	__be32 hash_chain;
+	__be32 parent;
+	__be32 extension;
+	__be32 stype;
 };
 
 struct slink_front
 {
-	u32 ptype;
-	u32 key;
-	u32 spare1[3];
-	u32 checksum;
+	__be32 ptype;
+	__be32 key;
+	__be32 spare1[3];
+	__be32 checksum;
 	u8 symname[1];	/* depends on block size */
 };
 
 struct affs_data_head
 {
-	u32 ptype;
-	u32 key;
-	u32 sequence;
-	u32 size;
-	u32 next;
-	u32 checksum;
+	__be32 ptype;
+	__be32 key;
+	__be32 sequence;
+	__be32 size;
+	__be32 next;
+	__be32 checksum;
 	u8 data[1];	/* depends on block size */
 };
 
diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h
index 3a3759fce..9d2429f07 100644
--- a/include/linux/arcdevice.h
+++ b/include/linux/arcdevice.h
@@ -305,7 +305,7 @@ struct arcnet_local {
 					void *buf, int count);
 	} hw;
 
-	void *mem_start;	/* pointer to ioremap'ed MMIO */
+	void __iomem *mem_start;	/* pointer to ioremap'ed MMIO */
 };
 
 
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 4b6d0e417..af917959a 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -42,6 +42,7 @@ enum {
 	ATA_ID_SERNO_OFS	= 10,
 	ATA_ID_MAJOR_VER	= 80,
 	ATA_ID_PIO_MODES	= 64,
+	ATA_ID_MWDMA_MODES	= 63,
 	ATA_ID_UDMA_MODES	= 88,
 	ATA_ID_PIO4		= (1 << 1),
 
@@ -133,13 +134,20 @@ enum {
 	XFER_UDMA_2		= 0x42,
 	XFER_UDMA_1		= 0x41,
 	XFER_UDMA_0		= 0x40,
+	XFER_MW_DMA_2		= 0x22,
+	XFER_MW_DMA_1		= 0x21,
+	XFER_MW_DMA_0		= 0x20,
 	XFER_PIO_4		= 0x0C,
 	XFER_PIO_3		= 0x0B,
+	XFER_PIO_2		= 0x0A,
+	XFER_PIO_1		= 0x09,
+	XFER_PIO_0		= 0x08,
 
 	/* ATAPI stuff */
 	ATAPI_PKT_DMA		= (1 << 0),
 	ATAPI_DMADIR		= (1 << 2),	/* ATAPI data dir:
 						   0=to device, 1=to host */
+	ATAPI_CDB_LEN		= 16,
 
 	/* cable types */
 	ATA_CBL_NONE		= 0,
@@ -169,16 +177,22 @@ enum ata_tf_protocols {
 	ATA_PROT_PIO,		/* PIO single sector */
 	ATA_PROT_PIO_MULT,	/* PIO multiple sector */
 	ATA_PROT_DMA,		/* DMA */
-	ATA_PROT_ATAPI,		/* packet command */
+	ATA_PROT_ATAPI,		/* packet command, PIO data xfer*/
+	ATA_PROT_ATAPI_NODATA,	/* packet command, no data */
 	ATA_PROT_ATAPI_DMA,	/* packet command with special DMA sauce */
 };
 
+enum ata_ioctls {
+	ATA_IOC_GET_IO32	= 0x309,
+	ATA_IOC_SET_IO32	= 0x324,
+};
+
 /* core structures */
 
 struct ata_prd {
 	u32			addr;
 	u32			flags_len;
-} __attribute__((packed));
+};
 
 struct ata_taskfile {
 	unsigned long		flags;		/* ATA_TFLAG_xxx */
@@ -206,6 +220,8 @@ struct ata_taskfile {
 #define ata_id_is_ata(dev)	(((dev)->id[0] & (1 << 15)) == 0)
 #define ata_id_rahead_enabled(dev) ((dev)->id[85] & (1 << 6))
 #define ata_id_wcache_enabled(dev) ((dev)->id[85] & (1 << 5))
+#define ata_id_has_flush(dev) ((dev)->id[83] & (1 << 12))
+#define ata_id_has_flush_ext(dev) ((dev)->id[83] & (1 << 13))
 #define ata_id_has_lba48(dev)	((dev)->id[83] & (1 << 10))
 #define ata_id_has_wcache(dev)	((dev)->id[82] & (1 << 5))
 #define ata_id_has_pm(dev)	((dev)->id[82] & (1 << 3))
@@ -220,9 +236,20 @@ struct ata_taskfile {
 	  ((u64) dev->id[(n) + 1] << 16) |	\
 	  ((u64) dev->id[(n) + 0]) )
 
+static inline int atapi_cdb_len(u16 *dev_id)
+{
+	u16 tmp = dev_id[0] & 0x3;
+	switch (tmp) {
+	case 0:		return 12;
+	case 1:		return 16;
+	default:	return -1;
+	}
+}
+
 static inline int is_atapi_taskfile(struct ata_taskfile *tf)
 {
 	return (tf->protocol == ATA_PROT_ATAPI) ||
+	       (tf->protocol == ATA_PROT_ATAPI_NODATA) ||
 	       (tf->protocol == ATA_PROT_ATAPI_DMA);
 }
 
diff --git a/include/linux/atalk.h b/include/linux/atalk.h
index c4d2a0949..2a9b82002 100644
--- a/include/linux/atalk.h
+++ b/include/linux/atalk.h
@@ -191,10 +191,13 @@ extern int		 aarp_send_ddp(struct net_device *dev,
 extern void		 aarp_send_probe(struct net_device *dev,
 					 struct atalk_addr *addr);
 extern void		 aarp_device_down(struct net_device *dev);
+extern void		 aarp_probe_network(struct atalk_iface *atif);
+extern int 		 aarp_proxy_probe_network(struct atalk_iface *atif,
+				     struct atalk_addr *sa);
+extern void		 aarp_proxy_remove(struct net_device *dev,
+					   struct atalk_addr *sa);
 
-#ifdef MODULE
-extern void aarp_cleanup_module(void);
-#endif /* MODULE */
+extern void		aarp_cleanup_module(void);
 
 #define at_sk(__sk) ((struct atalk_sock *)(__sk)->sk_protinfo)
 
@@ -209,8 +212,28 @@ extern rwlock_t atalk_interfaces_lock;
 
 extern struct atalk_route atrtr_default;
 
+extern struct file_operations atalk_seq_arp_fops;
+
+extern int sysctl_aarp_expiry_time;
+extern int sysctl_aarp_tick_time;
+extern int sysctl_aarp_retransmit_limit;
+extern int sysctl_aarp_resolve_time;
+
+#ifdef CONFIG_SYSCTL
+extern void atalk_register_sysctl(void);
+extern void atalk_unregister_sysctl(void);
+#else
+#define atalk_register_sysctl()		do { } while(0)
+#define atalk_unregister_sysctl()	do { } while(0)
+#endif
+
+#ifdef CONFIG_PROC_FS
 extern int atalk_proc_init(void);
 extern void atalk_proc_exit(void);
+#else
+#define atalk_proc_init()	0
+#define atalk_proc_exit()	do { } while(0)
+#endif /* CONFIG_PROC_FS */
 
 #endif /* __KERNEL__ */
 #endif /* __LINUX_ATALK_H__ */
diff --git a/include/linux/bio.h b/include/linux/bio.h
index b90e06c17..2585402c2 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -121,6 +121,7 @@ struct bio {
 #define BIO_CLONED	4	/* doesn't own data */
 #define BIO_BOUNCED	5	/* bio is a bounce bio */
 #define BIO_USER_MAPPED 6	/* contains user pages */
+#define BIO_EOPNOTSUPP	7	/* not supported */
 #define bio_flagged(bio, flag)	((bio)->bi_flags & (1 << (flag)))
 
 /*
@@ -160,6 +161,8 @@ struct bio {
 #define bio_data(bio)		(page_address(bio_page((bio))) + bio_offset((bio)))
 #define bio_barrier(bio)	((bio)->bi_rw & (1 << BIO_RW_BARRIER))
 #define bio_sync(bio)		((bio)->bi_rw & (1 << BIO_RW_SYNC))
+#define bio_failfast(bio)	((bio)->bi_rw & (1 << BIO_RW_FAILFAST))
+#define bio_rw_ahead(bio)	((bio)->bi_rw & (1 << BIO_RW_AHEAD))
 
 /*
  * will die
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 9dadd08e2..77401c155 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -98,6 +98,9 @@ extern int bitmap_scnprintf(char *buf, unsigned int len,
 			const unsigned long *src, int nbits);
 extern int bitmap_parse(const char __user *ubuf, unsigned int ulen,
 			unsigned long *dst, int nbits);
+extern int bitmap_find_free_region(unsigned long *bitmap, int bits, int order);
+extern void bitmap_release_region(unsigned long *bitmap, int pos, int order);
+extern int bitmap_allocate_region(unsigned long *bitmap, int pos, int order);
 
 #define BITMAP_LAST_WORD_MASK(nbits)					\
 (									\
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index eb4d10be7..4efe45d1a 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -195,6 +195,8 @@ enum rq_flag_bits {
 	__REQ_PM_SUSPEND,	/* suspend request */
 	__REQ_PM_RESUME,	/* resume request */
 	__REQ_PM_SHUTDOWN,	/* shutdown request */
+	__REQ_BAR_PREFLUSH,	/* barrier pre-flush done */
+	__REQ_BAR_POSTFLUSH,	/* barrier post-flush */
 	__REQ_NR_BITS,		/* stops here */
 };
 
@@ -220,6 +222,8 @@ enum rq_flag_bits {
 #define REQ_PM_SUSPEND	(1 << __REQ_PM_SUSPEND)
 #define REQ_PM_RESUME	(1 << __REQ_PM_RESUME)
 #define REQ_PM_SHUTDOWN	(1 << __REQ_PM_SHUTDOWN)
+#define REQ_BAR_PREFLUSH	(1 << __REQ_BAR_PREFLUSH)
+#define REQ_BAR_POSTFLUSH	(1 << __REQ_BAR_POSTFLUSH)
 
 /*
  * State information carried for REQ_PM_SUSPEND and REQ_PM_RESUME
@@ -248,6 +252,7 @@ typedef void (unplug_fn) (request_queue_t *);
 struct bio_vec;
 typedef int (merge_bvec_fn) (request_queue_t *, struct bio *, struct bio_vec *);
 typedef void (activity_fn) (void *data, int rw);
+typedef int (issue_flush_fn) (request_queue_t *, struct gendisk *, sector_t *);
 
 enum blk_queue_state {
 	Queue_down,
@@ -290,6 +295,7 @@ struct request_queue
 	unplug_fn		*unplug_fn;
 	merge_bvec_fn		*merge_bvec_fn;
 	activity_fn		*activity_fn;
+	issue_flush_fn		*issue_flush_fn;
 
 	/*
 	 * Auto-unplugging state
@@ -338,6 +344,7 @@ struct request_queue
 	unsigned int		nr_congestion_off;
 
 	unsigned short		max_sectors;
+	unsigned short		max_hw_sectors;
 	unsigned short		max_phys_segments;
 	unsigned short		max_hw_segments;
 	unsigned short		hardsect_size;
@@ -373,6 +380,7 @@ struct request_queue
 #define QUEUE_FLAG_DEAD		5	/* queue being torn down */
 #define QUEUE_FLAG_REENTER	6	/* Re-entrancy avoidance */
 #define QUEUE_FLAG_PLUGGED	7	/* queue is plugged */
+#define QUEUE_FLAG_ORDERED	8	/* supports ordered writes */
 
 #define blk_queue_plugged(q)	test_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags)
 #define blk_queue_tagged(q)	test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags)
@@ -390,6 +398,10 @@ struct request_queue
 #define blk_pm_request(rq)	\
 	((rq)->flags & (REQ_PM_SUSPEND | REQ_PM_RESUME))
 
+#define blk_barrier_rq(rq)	((rq)->flags & REQ_HARDBARRIER)
+#define blk_barrier_preflush(rq)	((rq)->flags & REQ_BAR_PREFLUSH)
+#define blk_barrier_postflush(rq)	((rq)->flags & REQ_BAR_POSTFLUSH)
+
 #define list_entry_rq(ptr)	list_entry((ptr), struct request, queuelist)
 
 #define rq_data_dir(rq)		((rq)->flags & 1)
@@ -560,6 +572,14 @@ extern void end_that_request_last(struct request *);
 extern int process_that_request_first(struct request *, unsigned int);
 extern void end_request(struct request *req, int uptodate);
 
+/*
+ * end_that_request_first/chunk() takes an uptodate argument. we account
+ * any value <= as an io error. 0 means -EIO for compatability reasons,
+ * any other < 0 value is the direct error type. An uptodate value of
+ * 1 indicates successful io completion
+ */
+#define end_io_error(uptodate)	(unlikely((uptodate) <= 0))
+
 static inline void blkdev_dequeue_request(struct request *req)
 {
 	BUG_ON(list_empty(&req->queuelist));
@@ -588,6 +608,9 @@ extern void blk_queue_prep_rq(request_queue_t *, prep_rq_fn *pfn);
 extern void blk_queue_merge_bvec(request_queue_t *, merge_bvec_fn *);
 extern void blk_queue_dma_alignment(request_queue_t *, int);
 extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev);
+extern void blk_queue_ordered(request_queue_t *, int);
+extern void blk_queue_issue_flush_fn(request_queue_t *, issue_flush_fn *);
+extern int blkdev_scsi_issue_flush_fn(request_queue_t *, struct gendisk *, sector_t *);
 
 extern int blk_rq_map_sg(request_queue_t *, struct request *, struct scatterlist *);
 extern void blk_dump_rq_flags(struct request *, char *);
@@ -616,6 +639,7 @@ extern long blk_congestion_wait(int rw, long timeout);
 
 extern void blk_rq_bio_prep(request_queue_t *, struct request *, struct bio *);
 extern void blk_rq_prep_restart(struct request *);
+extern int blkdev_issue_flush(struct block_device *, sector_t *);
 
 #define MAX_PHYS_SEGMENTS 128
 #define MAX_HW_SEGMENTS 128
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
index e038f9a3d..376a5500a 100644
--- a/include/linux/bootmem.h
+++ b/include/linux/bootmem.h
@@ -67,6 +67,9 @@ extern void * __init __alloc_bootmem_node (pg_data_t *pgdat, unsigned long size,
 	__alloc_bootmem_node((pgdat), (x), PAGE_SIZE, 0)
 #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */
 
+extern unsigned long __initdata nr_kernel_pages;
+extern unsigned long __initdata nr_all_pages;
+
 extern void *__init alloc_large_system_hash(const char *tablename,
 					    unsigned long bucketsize,
 					    unsigned long numentries,
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 6d70bd539..367a8a313 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -26,6 +26,8 @@ enum bh_state_bits {
 	BH_Delay,	/* Buffer is not yet allocated on disk */
 	BH_Boundary,	/* Block is followed by a discontiguity */
 	BH_Write_EIO,	/* I/O error on write */
+	BH_Ordered,	/* ordered write */
+	BH_Eopnotsupp,	/* operation not supported (barrier) */
 
 	BH_PrivateStart,/* not a state bit, but the first bit available
 			 * for private allocation by other entities
@@ -47,12 +49,12 @@ typedef void (bh_end_io_t)(struct buffer_head *bh, int uptodate);
 struct buffer_head {
 	/* First cache line: */
 	unsigned long b_state;		/* buffer state bitmap (see above) */
-	atomic_t b_count;		/* users using this block */
 	struct buffer_head *b_this_page;/* circular list of page's buffers */
 	struct page *b_page;		/* the page this bh is mapped to */
+	atomic_t b_count;		/* users using this block */
+	u32 b_size;			/* block size */
 
 	sector_t b_blocknr;		/* block number */
-	u32 b_size;			/* block size */
 	char *b_data;			/* pointer to data block */
 
 	struct block_device *b_bdev;
@@ -110,7 +112,9 @@ BUFFER_FNS(Async_Read, async_read)
 BUFFER_FNS(Async_Write, async_write)
 BUFFER_FNS(Delay, delay)
 BUFFER_FNS(Boundary, boundary)
-BUFFER_FNS(Write_EIO,write_io_error)
+BUFFER_FNS(Write_EIO, write_io_error)
+BUFFER_FNS(Ordered, ordered)
+BUFFER_FNS(Eopnotsupp, eopnotsupp)
 
 #define bh_offset(bh)		((unsigned long)(bh)->b_data & ~PAGE_MASK)
 #define touch_buffer(bh)	mark_page_accessed(bh->b_page)
@@ -139,17 +143,13 @@ void end_buffer_write_sync(struct buffer_head *bh, int uptodate);
 void end_buffer_async_write(struct buffer_head *bh, int uptodate);
 
 /* Things to do with buffers at mapping->private_list */
-void buffer_insert_list(spinlock_t *lock,
-			struct buffer_head *, struct list_head *);
 void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode);
 int inode_has_buffers(struct inode *);
 void invalidate_inode_buffers(struct inode *);
 int remove_inode_buffers(struct inode *inode);
-int fsync_buffers_list(spinlock_t *lock, struct list_head *);
 int sync_mapping_buffers(struct address_space *mapping);
 void unmap_underlying_metadata(struct block_device *bdev, sector_t block);
 
-void mark_buffer_async_read(struct buffer_head *bh);
 void mark_buffer_async_write(struct buffer_head *bh);
 void invalidate_bdev(struct block_device *, int);
 int sync_blockdev(struct block_device *bdev);
@@ -172,8 +172,8 @@ void free_buffer_head(struct buffer_head * bh);
 void FASTCALL(unlock_buffer(struct buffer_head *bh));
 void FASTCALL(__lock_buffer(struct buffer_head *bh));
 void ll_rw_block(int, int, struct buffer_head * bh[]);
-void sync_dirty_buffer(struct buffer_head *bh);
-void submit_bh(int, struct buffer_head *);
+int sync_dirty_buffer(struct buffer_head *bh);
+int submit_bh(int, struct buffer_head *);
 void write_boundary_block(struct block_device *bdev,
 			sector_t bblock, unsigned blocksize);
 
@@ -202,12 +202,6 @@ int nobh_prepare_write(struct page*, unsigned, unsigned, get_block_t*);
 int nobh_commit_write(struct file *, struct page *, unsigned, unsigned);
 int nobh_truncate_page(struct address_space *, loff_t);
 
-#define OSYNC_METADATA	(1<<0)
-#define OSYNC_DATA	(1<<1)
-#define OSYNC_INODE	(1<<2)
-int generic_osync_inode(struct inode *, struct address_space *, int);
-
-
 /*
  * inline definitions
  */
@@ -274,12 +268,14 @@ map_bh(struct buffer_head *bh, struct super_block *sb, sector_t block)
  */
 static inline void wait_on_buffer(struct buffer_head *bh)
 {
+	might_sleep();
 	if (buffer_locked(bh) || atomic_read(&bh->b_count) == 0)
 		__wait_on_buffer(bh);
 }
 
 static inline void lock_buffer(struct buffer_head *bh)
 {
+	might_sleep();
 	if (test_set_buffer_locked(bh))
 		__lock_buffer(bh);
 }
diff --git a/include/linux/byteorder/big_endian.h b/include/linux/byteorder/big_endian.h
index b84efd74c..40d40b479 100644
--- a/include/linux/byteorder/big_endian.h
+++ b/include/linux/byteorder/big_endian.h
@@ -8,48 +8,86 @@
 #define __BIG_ENDIAN_BITFIELD
 #endif
 
+#include <linux/types.h>
 #include <linux/byteorder/swab.h>
 
-#define __constant_htonl(x) ((__u32)(x))
-#define __constant_ntohl(x) ((__u32)(x))
-#define __constant_htons(x) ((__u16)(x))
-#define __constant_ntohs(x) ((__u16)(x))
-#define __constant_cpu_to_le64(x) ___constant_swab64((x))
-#define __constant_le64_to_cpu(x) ___constant_swab64((x))
-#define __constant_cpu_to_le32(x) ___constant_swab32((x))
-#define __constant_le32_to_cpu(x) ___constant_swab32((x))
-#define __constant_cpu_to_le16(x) ___constant_swab16((x))
-#define __constant_le16_to_cpu(x) ___constant_swab16((x))
-#define __constant_cpu_to_be64(x) ((__u64)(x))
-#define __constant_be64_to_cpu(x) ((__u64)(x))
-#define __constant_cpu_to_be32(x) ((__u32)(x))
-#define __constant_be32_to_cpu(x) ((__u32)(x))
-#define __constant_cpu_to_be16(x) ((__u16)(x))
-#define __constant_be16_to_cpu(x) ((__u16)(x))
-#define __cpu_to_le64(x) __swab64((x))
-#define __le64_to_cpu(x) __swab64((x))
-#define __cpu_to_le32(x) __swab32((x))
-#define __le32_to_cpu(x) __swab32((x))
-#define __cpu_to_le16(x) __swab16((x))
-#define __le16_to_cpu(x) __swab16((x))
-#define __cpu_to_be64(x) ((__u64)(x))
-#define __be64_to_cpu(x) ((__u64)(x))
-#define __cpu_to_be32(x) ((__u32)(x))
-#define __be32_to_cpu(x) ((__u32)(x))
-#define __cpu_to_be16(x) ((__u16)(x))
-#define __be16_to_cpu(x) ((__u16)(x))
-#define __cpu_to_le64p(x) __swab64p((x))
-#define __le64_to_cpup(x) __swab64p((x))
-#define __cpu_to_le32p(x) __swab32p((x))
-#define __le32_to_cpup(x) __swab32p((x))
-#define __cpu_to_le16p(x) __swab16p((x))
-#define __le16_to_cpup(x) __swab16p((x))
-#define __cpu_to_be64p(x) (*(__u64*)(x))
-#define __be64_to_cpup(x) (*(__u64*)(x))
-#define __cpu_to_be32p(x) (*(__u32*)(x))
-#define __be32_to_cpup(x) (*(__u32*)(x))
-#define __cpu_to_be16p(x) (*(__u16*)(x))
-#define __be16_to_cpup(x) (*(__u16*)(x))
+#define __constant_htonl(x) ((__force __be32)(__u32)(x))
+#define __constant_ntohl(x) ((__force __u32)(__be32)(x))
+#define __constant_htons(x) ((__force __be16)(__u16)(x))
+#define __constant_ntohs(x) ((__force __u16)(__be16)(x))
+#define __constant_cpu_to_le64(x) ((__force __le64)___constant_swab64((x)))
+#define __constant_le64_to_cpu(x) ___constant_swab64((__force __u64)(__le64)(x))
+#define __constant_cpu_to_le32(x) ((__force __le32)___constant_swab32((x)))
+#define __constant_le32_to_cpu(x) ___constant_swab32((__force __u32)(__le32)(x))
+#define __constant_cpu_to_le16(x) ((__force __le16)___constant_swab16((x)))
+#define __constant_le16_to_cpu(x) ___constant_swab16((__force __u16)(__le16)(x))
+#define __constant_cpu_to_be64(x) ((__force __be64)(__u64)(x))
+#define __constant_be64_to_cpu(x) ((__force __u64)(__be64)(x))
+#define __constant_cpu_to_be32(x) ((__force __be32)(__u32)(x))
+#define __constant_be32_to_cpu(x) ((__force __u32)(__be32)(x))
+#define __constant_cpu_to_be16(x) ((__force __be16)(__u16)(x))
+#define __constant_be16_to_cpu(x) ((__force __u16)(__be16)(x))
+#define __cpu_to_le64(x) ((__force __le64)___swab64((x)))
+#define __le64_to_cpu(x) ___swab64((__force __u64)(__le64)(x))
+#define __cpu_to_le32(x) ((__force __le32)___swab32((x)))
+#define __le32_to_cpu(x) ___swab32((__force __u32)(__le32)(x))
+#define __cpu_to_le16(x) ((__force __le16)___swab16((x)))
+#define __le16_to_cpu(x) ___swab16((__force __u16)(__le16)(x))
+#define __cpu_to_be64(x) ((__force __be64)(__u64)(x))
+#define __be64_to_cpu(x) ((__force __u64)(__be64)(x))
+#define __cpu_to_be32(x) ((__force __be32)(__u32)(x))
+#define __be32_to_cpu(x) ((__force __u32)(__be32)(x))
+#define __cpu_to_be16(x) ((__force __be16)(__u16)(x))
+#define __be16_to_cpu(x) ((__force __u16)(__be16)(x))
+
+static inline __le64 __cpu_to_le64p(const __u64 *p)
+{
+	return (__force __le64)__swab64p(p);
+}
+static inline __u64 __le64_to_cpup(const __le64 *p)
+{
+	return __swab64p((__u64 *)p);
+}
+static inline __le32 __cpu_to_le32p(const __u32 *p)
+{
+	return (__force __le32)__swab32p(p);
+}
+static inline __u32 __le32_to_cpup(const __le32 *p)
+{
+	return __swab32p((__u32 *)p);
+}
+static inline __le16 __cpu_to_le16p(const __u16 *p)
+{
+	return (__force __le16)__swab16p(p);
+}
+static inline __u16 __le16_to_cpup(const __le16 *p)
+{
+	return __swab16p((__u16 *)p);
+}
+static inline __be64 __cpu_to_be64p(const __u64 *p)
+{
+	return (__force __be64)*p;
+}
+static inline __u64 __be64_to_cpup(const __be64 *p)
+{
+	return (__force __u64)*p;
+}
+static inline __be32 __cpu_to_be32p(const __u32 *p)
+{
+	return (__force __be32)*p;
+}
+static inline __u32 __be32_to_cpup(const __be32 *p)
+{
+	return (__force __u32)*p;
+}
+static inline __be16 __cpu_to_be16p(const __u16 *p)
+{
+	return (__force __be16)*p;
+}
+static inline __u16 __be16_to_cpup(const __be16 *p)
+{
+	return (__force __u16)*p;
+}
 #define __cpu_to_le64s(x) __swab64s((x))
 #define __le64_to_cpus(x) __swab64s((x))
 #define __cpu_to_le32s(x) __swab32s((x))
diff --git a/include/linux/byteorder/generic.h b/include/linux/byteorder/generic.h
index 5f33f565d..5fde6f4d6 100644
--- a/include/linux/byteorder/generic.h
+++ b/include/linux/byteorder/generic.h
@@ -147,10 +147,10 @@
  * Do the prototypes. Somebody might want to take the
  * address or some such sick thing..
  */
-extern __u32			ntohl(__u32);
-extern __u32			htonl(__u32);
-extern unsigned short int	ntohs(unsigned short int);
-extern unsigned short int	htons(unsigned short int);
+extern __u32			ntohl(__be32);
+extern __be32			htonl(__u32);
+extern __u16			ntohs(__be16);
+extern __be16			htons(__u16);
 
 #if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__)
 
diff --git a/include/linux/byteorder/little_endian.h b/include/linux/byteorder/little_endian.h
index 143166362..c05349b84 100644
--- a/include/linux/byteorder/little_endian.h
+++ b/include/linux/byteorder/little_endian.h
@@ -8,48 +8,86 @@
 #define __LITTLE_ENDIAN_BITFIELD
 #endif
 
+#include <linux/types.h>
 #include <linux/byteorder/swab.h>
 
-#define __constant_htonl(x) ___constant_swab32((x))
-#define __constant_ntohl(x) ___constant_swab32((x))
-#define __constant_htons(x) ___constant_swab16((x))
-#define __constant_ntohs(x) ___constant_swab16((x))
-#define __constant_cpu_to_le64(x) ((__u64)(x))
-#define __constant_le64_to_cpu(x) ((__u64)(x))
-#define __constant_cpu_to_le32(x) ((__u32)(x))
-#define __constant_le32_to_cpu(x) ((__u32)(x))
-#define __constant_cpu_to_le16(x) ((__u16)(x))
-#define __constant_le16_to_cpu(x) ((__u16)(x))
-#define __constant_cpu_to_be64(x) ___constant_swab64((x))
-#define __constant_be64_to_cpu(x) ___constant_swab64((x))
-#define __constant_cpu_to_be32(x) ___constant_swab32((x))
-#define __constant_be32_to_cpu(x) ___constant_swab32((x))
-#define __constant_cpu_to_be16(x) ___constant_swab16((x))
-#define __constant_be16_to_cpu(x) ___constant_swab16((x))
-#define __cpu_to_le64(x) ((__u64)(x))
-#define __le64_to_cpu(x) ((__u64)(x))
-#define __cpu_to_le32(x) ((__u32)(x))
-#define __le32_to_cpu(x) ((__u32)(x))
-#define __cpu_to_le16(x) ((__u16)(x))
-#define __le16_to_cpu(x) ((__u16)(x))
-#define __cpu_to_be64(x) __swab64((x))
-#define __be64_to_cpu(x) __swab64((x))
-#define __cpu_to_be32(x) __swab32((x))
-#define __be32_to_cpu(x) __swab32((x))
-#define __cpu_to_be16(x) __swab16((x))
-#define __be16_to_cpu(x) __swab16((x))
-#define __cpu_to_le64p(x) (*(__u64*)(x))
-#define __le64_to_cpup(x) (*(__u64*)(x))
-#define __cpu_to_le32p(x) (*(__u32*)(x))
-#define __le32_to_cpup(x) (*(__u32*)(x))
-#define __cpu_to_le16p(x) (*(__u16*)(x))
-#define __le16_to_cpup(x) (*(__u16*)(x))
-#define __cpu_to_be64p(x) __swab64p((x))
-#define __be64_to_cpup(x) __swab64p((x))
-#define __cpu_to_be32p(x) __swab32p((x))
-#define __be32_to_cpup(x) __swab32p((x))
-#define __cpu_to_be16p(x) __swab16p((x))
-#define __be16_to_cpup(x) __swab16p((x))
+#define __constant_htonl(x) ((__force __be32)___constant_swab32((x)))
+#define __constant_ntohl(x) ___constant_swab32((__force __be32)(x))
+#define __constant_htons(x) ((__force __be16)___constant_swab16((x)))
+#define __constant_ntohs(x) ___constant_swab16((__force __be16)(x))
+#define __constant_cpu_to_le64(x) ((__force __le64)(__u64)(x))
+#define __constant_le64_to_cpu(x) ((__force __u64)(__le64)(x))
+#define __constant_cpu_to_le32(x) ((__force __le32)(__u32)(x))
+#define __constant_le32_to_cpu(x) ((__force __u32)(__le32)(x))
+#define __constant_cpu_to_le16(x) ((__force __le16)(__u16)(x))
+#define __constant_le16_to_cpu(x) ((__force __u16)(__le16)(x))
+#define __constant_cpu_to_be64(x) ((__force __be64)___constant_swab64((x)))
+#define __constant_be64_to_cpu(x) ___constant_swab64((__force __u64)(__be64)(x))
+#define __constant_cpu_to_be32(x) ((__force __be32)___constant_swab32((x)))
+#define __constant_be32_to_cpu(x) ___constant_swab32((__force __u32)(__be32)(x))
+#define __constant_cpu_to_be16(x) ((__force __be16)___constant_swab16((x)))
+#define __constant_be16_to_cpu(x) ___constant_swab16((__force __u16)(__be16)(x))
+#define __cpu_to_le64(x) ((__force __le64)(__u64)(x))
+#define __le64_to_cpu(x) ((__force __u64)(__le64)(x))
+#define __cpu_to_le32(x) ((__force __le32)(__u32)(x))
+#define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
+#define __cpu_to_le16(x) ((__force __le16)(__u16)(x))
+#define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
+#define __cpu_to_be64(x) ((__force __be64)___swab64((x)))
+#define __be64_to_cpu(x) ___swab64((__force __u64)(__be64)(x))
+#define __cpu_to_be32(x) ((__force __be32)___swab32((x)))
+#define __be32_to_cpu(x) ___swab32((__force __u32)(__be32)(x))
+#define __cpu_to_be16(x) ((__force __be16)___swab16((x)))
+#define __be16_to_cpu(x) ___swab16((__force __u16)(__be16)(x))
+
+static inline __le64 __cpu_to_le64p(const __u64 *p)
+{
+	return (__force __le64)*p;
+}
+static inline __u64 __le64_to_cpup(const __le64 *p)
+{
+	return (__force __u64)*p;
+}
+static inline __le32 __cpu_to_le32p(const __u32 *p)
+{
+	return (__force __le32)*p;
+}
+static inline __u32 __le32_to_cpup(const __le32 *p)
+{
+	return (__force __u32)*p;
+}
+static inline __le16 __cpu_to_le16p(const __u16 *p)
+{
+	return (__force __le16)*p;
+}
+static inline __u16 __le16_to_cpup(const __le16 *p)
+{
+	return (__force __u16)*p;
+}
+static inline __be64 __cpu_to_be64p(const __u64 *p)
+{
+	return (__force __be64)__swab64p(p);
+}
+static inline __u64 __be64_to_cpup(const __be64 *p)
+{
+	return __swab64p((__u64 *)p);
+}
+static inline __be32 __cpu_to_be32p(const __u32 *p)
+{
+	return (__force __be32)__swab32p(p);
+}
+static inline __u32 __be32_to_cpup(const __be32 *p)
+{
+	return __swab32p((__u32 *)p);
+}
+static inline __be16 __cpu_to_be16p(const __u16 *p)
+{
+	return (__force __be16)__swab16p(p);
+}
+static inline __u16 __be16_to_cpup(const __be16 *p)
+{
+	return __swab16p((__u16 *)p);
+}
 #define __cpu_to_le64s(x) do {} while (0)
 #define __le64_to_cpus(x) do {} while (0)
 #define __cpu_to_le32s(x) do {} while (0)
diff --git a/include/linux/capability.h b/include/linux/capability.h
index 7798d2c26..105aaeefa 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -288,7 +288,7 @@ typedef __u32 kernel_cap_t;
 /* Allow context manipulations */
 /* Allow changing context info on files */
 
-#define CAP_CONTEXT          29
+#define CAP_CONTEXT	     29
 
 #ifdef __KERNEL__
 /* 
diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h
index 0e46b2d0d..bcc941076 100644
--- a/include/linux/cdrom.h
+++ b/include/linux/cdrom.h
@@ -466,9 +466,10 @@ struct cdrom_generic_command
 #define GPCMD_REPORT_KEY		    0xa4
 #define GPCMD_REQUEST_SENSE		    0x03
 #define GPCMD_RESERVE_RZONE_TRACK	    0x53
+#define GPCMD_SEND_CUE_SHEET		    0x5d
 #define GPCMD_SCAN			    0xba
 #define GPCMD_SEEK			    0x2b
-#define GPCMD_SEND_DVD_STRUCTURE	    0xad
+#define GPCMD_SEND_DVD_STRUCTURE	    0xbf
 #define GPCMD_SEND_EVENT		    0xa2
 #define GPCMD_SEND_KEY			    0xa3
 #define GPCMD_SEND_OPC			    0x54
diff --git a/include/linux/coda.h b/include/linux/coda.h
index eb921d6de..309cbbe35 100644
--- a/include/linux/coda.h
+++ b/include/linux/coda.h
@@ -200,7 +200,7 @@ typedef u_int32_t vuid_t;
 typedef u_int32_t vgid_t;
 #endif /*_VUID_T_ */
 
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
 struct CodaFid {
 	u_int32_t opaque[3];
 };
@@ -220,7 +220,7 @@ struct coda_cred {
     vgid_t cr_groupid, cr_egid, cr_sgid, cr_fsgid; /* same for groups */
 };
 
-#else /* not defined(CODA_FS_OLD_API) */
+#else /* not defined(CONFIG_CODA_FS_OLD_API) */
 
 struct CodaFid {
 	u_int32_t opaque[4];
@@ -318,7 +318,7 @@ struct coda_statfs {
 #define CODA_KERNEL_VERSION 0 /* don't care about kernel version number */
 #define CODA_KERNEL_VERSION 1 /* The old venus 4.6 compatible interface */
 #endif
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
 #define CODA_KERNEL_VERSION 2 /* venus_lookup got an extra parameter */
 #else
 #define CODA_KERNEL_VERSION 3 /* 128-bit file identifiers */
@@ -330,7 +330,7 @@ struct coda_statfs {
 struct coda_in_hdr {
     u_int32_t opcode;
     u_int32_t unique;	    /* Keep multiple outstanding msgs distinct */
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
     u_int16_t pid;	    /* Common to all */
     u_int16_t pgid;	    /* Common to all */
     u_int16_t sid;          /* Common to all */
@@ -614,7 +614,7 @@ struct coda_vget_out {
 /* CODA_PURGEUSER is a venus->kernel call */
 struct coda_purgeuser_out {
     struct coda_out_hdr oh;
-#ifdef CODA_FS_OLD_API
+#ifdef CONFIG_CODA_FS_OLD_API
     struct coda_cred cred;
 #else
     vuid_t uid;
diff --git a/include/linux/compat.h b/include/linux/compat.h
index e45c0f905..e1e78bb97 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -79,6 +79,8 @@ struct compat_rusage {
 	compat_long_t	ru_nivcsw;
 };
 
+extern int put_compat_rusage(const struct rusage *, struct compat_rusage __user *);
+
 struct compat_dirent {
 	u32		d_ino;
 	compat_off_t	d_off;
@@ -130,5 +132,15 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
 		compat_ulong_t __user *outp, compat_ulong_t __user *exp,
 		struct compat_timeval __user *tvp);
 
+#define BITS_PER_COMPAT_LONG    (8*sizeof(compat_long_t))
+
+#define BITS_TO_COMPAT_LONGS(bits) \
+	(((bits)+BITS_PER_COMPAT_LONG-1)/BITS_PER_COMPAT_LONG)
+
+long compat_get_bitmap(unsigned long *mask, compat_ulong_t __user *umask,
+		       unsigned long bitmap_size);
+long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
+		       unsigned long bitmap_size);
+
 #endif /* CONFIG_COMPAT */
 #endif /* _LINUX_COMPAT_H */
diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h
index f8159ddb6..77f59742c 100644
--- a/include/linux/compat_ioctl.h
+++ b/include/linux/compat_ioctl.h
@@ -384,6 +384,7 @@ COMPATIBLE_IOCTL(DVD_WRITE_STRUCT)
 COMPATIBLE_IOCTL(DVD_AUTH)
 /* Big L */
 ULONG_IOCTL(LOOP_SET_FD)
+ULONG_IOCTL(LOOP_CHANGE_FD)
 COMPATIBLE_IOCTL(LOOP_CLR_FD)
 COMPATIBLE_IOCTL(LOOP_GET_STATUS64)
 COMPATIBLE_IOCTL(LOOP_SET_STATUS64)
@@ -592,13 +593,15 @@ COMPATIBLE_IOCTL(ATMTCP_CREATE)
 COMPATIBLE_IOCTL(ATMTCP_REMOVE)
 COMPATIBLE_IOCTL(ATMMPC_CTRL)
 COMPATIBLE_IOCTL(ATMMPC_DATA)
-/* Big W */
-/* WIOC_GETSUPPORT not yet implemented -E */
+/* Watchdog */
+COMPATIBLE_IOCTL(WDIOC_GETSUPPORT)
 COMPATIBLE_IOCTL(WDIOC_GETSTATUS)
 COMPATIBLE_IOCTL(WDIOC_GETBOOTSTATUS)
 COMPATIBLE_IOCTL(WDIOC_GETTEMP)
 COMPATIBLE_IOCTL(WDIOC_SETOPTIONS)
 COMPATIBLE_IOCTL(WDIOC_KEEPALIVE)
+COMPATIBLE_IOCTL(WDIOC_SETTIMEOUT)
+COMPATIBLE_IOCTL(WDIOC_GETTIMEOUT)
 /* Big R */
 COMPATIBLE_IOCTL(RNDGETENTCNT)
 COMPATIBLE_IOCTL(RNDADDTOENTCNT)
@@ -732,3 +735,20 @@ COMPATIBLE_IOCTL(SIOCSIWRETRY)
 COMPATIBLE_IOCTL(SIOCGIWRETRY)
 COMPATIBLE_IOCTL(SIOCSIWPOWER)
 COMPATIBLE_IOCTL(SIOCGIWPOWER)
+/* hiddev */
+COMPATIBLE_IOCTL(HIDIOCGVERSION)
+COMPATIBLE_IOCTL(HIDIOCAPPLICATION)
+COMPATIBLE_IOCTL(HIDIOCGDEVINFO)
+COMPATIBLE_IOCTL(HIDIOCGSTRING)
+COMPATIBLE_IOCTL(HIDIOCINITREPORT)
+COMPATIBLE_IOCTL(HIDIOCGREPORT)
+COMPATIBLE_IOCTL(HIDIOCSREPORT)
+COMPATIBLE_IOCTL(HIDIOCGREPORTINFO)
+COMPATIBLE_IOCTL(HIDIOCGFIELDINFO)
+COMPATIBLE_IOCTL(HIDIOCGUSAGE)
+COMPATIBLE_IOCTL(HIDIOCSUSAGE)
+COMPATIBLE_IOCTL(HIDIOCGUCODE)
+COMPATIBLE_IOCTL(HIDIOCGFLAG)
+COMPATIBLE_IOCTL(HIDIOCSFLAG)
+COMPATIBLE_IOCTL(HIDIOCGCOLLECTIONINDEX)
+COMPATIBLE_IOCTL(HIDIOCGCOLLECTIONINFO)
diff --git a/include/linux/compiler-gcc+.h b/include/linux/compiler-gcc+.h
index 5629cf5cd..6b9308541 100644
--- a/include/linux/compiler-gcc+.h
+++ b/include/linux/compiler-gcc+.h
@@ -6,9 +6,9 @@
  */
 #include <linux/compiler-gcc.h>
 
-#define inline			__inline__ __attribute__((always_inline))
-#define __inline__		__inline__ __attribute__((always_inline))
-#define __inline		__inline__ __attribute__((always_inline))
+#define inline			inline		__attribute__((always_inline))
+#define __inline__		__inline__	__attribute__((always_inline))
+#define __inline		__inline	__attribute__((always_inline))
 #define __deprecated		__attribute__((deprecated))
 #define __attribute_used__	__attribute__((__used__))
 #define __attribute_pure__	__attribute__((pure))
diff --git a/include/linux/compiler-gcc3.h b/include/linux/compiler-gcc3.h
index 7965ae53d..eec2f88c4 100644
--- a/include/linux/compiler-gcc3.h
+++ b/include/linux/compiler-gcc3.h
@@ -3,10 +3,10 @@
 /* These definitions are for GCC v3.x.  */
 #include <linux/compiler-gcc.h>
 
-#if __GNUC_MINOR__ >= 1  && __GNUC_MINOR__ < 4
-# define inline		__inline__ __attribute__((always_inline))
-# define __inline__	__inline__ __attribute__((always_inline))
-# define __inline	__inline__ __attribute__((always_inline))
+#if __GNUC_MINOR__ >= 1
+# define inline		inline		__attribute__((always_inline))
+# define __inline__	__inline__	__attribute__((always_inline))
+# define __inline	__inline	__attribute__((always_inline))
 #endif
 
 #if __GNUC_MINOR__ > 0
@@ -28,3 +28,7 @@
 #if __GNUC_MINOR__ >= 4
 #define __must_check __attribute__((warn_unused_result))
 #endif
+
+#if __GNUC_MINOR__ >= 5
+#define __compiler_offsetof(a,b) __builtin_offsetof(a,b)
+#endif
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 22d83706f..62949aa63 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -6,13 +6,17 @@
 # define __kernel	/* default address space */
 # define __safe		__attribute__((safe))
 # define __force	__attribute__((force))
+# define __iomem	__attribute__((noderef, address_space(2)))
 extern void __chk_user_ptr(void __user *);
+extern void __chk_io_ptr(void __iomem *);
 #else
 # define __user
 # define __kernel
 # define __safe
 # define __force
+# define __iomem
 # define __chk_user_ptr(x) (void)0
+# define __chk_io_ptr(x) (void)0
 #endif
 
 #ifdef __KERNEL__
@@ -124,4 +128,8 @@ extern void __chk_user_ptr(void __user *);
 #define noinline
 #endif
 
+#ifndef __always_inline
+#define __always_inline inline
+#endif
+
 #endif /* __LINUX_COMPILER_H */
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 5925e83d9..7130cef0f 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -74,7 +74,7 @@ int cpu_down(unsigned int cpu);
 #define hotcpu_notifier(fn, pri)
 
 /* CPUs don't go offline once they're online w/o CONFIG_HOTPLUG_CPU */
-#define cpu_is_offline(cpu) 0
+static inline int cpu_is_offline(int cpu) { return 0; }
 #endif
 
 #endif /* _LINUX_CPU_H_ */
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index b4204dc7e..48a23f158 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -209,13 +209,6 @@ struct cpufreq_driver {
 #define CPUFREQ_CONST_LOOPS 	0x02	/* loops_per_jiffy or other kernel
 					 * "constants" aren't affected by
 					 * frequency transitions */
-#define CPUFREQ_PANIC_OUTOFSYNC	0x04	/* panic if cpufreq's opinion of
-					 * current frequency differs from
-					 * actual frequency */
-#define CPUFREQ_PANIC_RESUME_OUTOFSYNC 0x08 /* panic if cpufreq's opinion of
-					 * current frequency differs from
-					 * actual frequency on resume
-					 * from sleep. */
 
 
 int cpufreq_register_driver(struct cpufreq_driver *driver_data);
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 7109aa6e5..1ff1e85f6 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -73,6 +73,7 @@
  *    inside a macro, the way we do the other calls.
  */
 
+#include <linux/kernel.h>
 #include <linux/threads.h>
 #include <linux/bitmap.h>
 #include <asm/bug.h>
@@ -207,13 +208,13 @@ static inline void __cpus_shift_left(cpumask_t *dstp,
 #define first_cpu(src) __first_cpu(&(src), NR_CPUS)
 static inline int __first_cpu(const cpumask_t *srcp, int nbits)
 {
-	return find_first_bit(srcp->bits, nbits);
+	return min_t(int, nbits, find_first_bit(srcp->bits, nbits));
 }
 
 #define next_cpu(n, src) __next_cpu((n), &(src), NR_CPUS)
 static inline int __next_cpu(int n, const cpumask_t *srcp, int nbits)
 {
-	return find_next_bit(srcp->bits, nbits, n+1);
+	return min_t(int, nbits, find_next_bit(srcp->bits, nbits, n+1));
 }
 
 #define cpumask_of_cpu(cpu)						\
diff --git a/include/linux/cyclades.h b/include/linux/cyclades.h
index cc598507b..46d8254c1 100644
--- a/include/linux/cyclades.h
+++ b/include/linux/cyclades.h
@@ -511,8 +511,8 @@ struct resource;
 struct cyclades_card {
     unsigned long base_phys;
     unsigned long ctl_phys;
-    unsigned long base_addr;
-    unsigned long ctl_addr;
+    void __iomem *base_addr;
+    void __iomem *ctl_addr;
     int irq;
     int num_chips;	/* 0 if card absent, -1 if Z/PCI, else Y */
     int first_line;	/* minor number of first channel on card */
@@ -539,9 +539,9 @@ struct cyclades_chip {
  * (required to support Alpha systems) *
  ***************************************/
 
-#define cy_writeb(port,val)     {writeb((ucchar)(val),(ulong)(port)); mb();}
-#define cy_writew(port,val)     {writew((ushort)(val),(ulong)(port)); mb();}
-#define cy_writel(port,val)     {writel((uclong)(val),(ulong)(port)); mb();}
+#define cy_writeb(port,val)     {writeb((val),(port)); mb();}
+#define cy_writew(port,val)     {writew((val),(port)); mb();}
+#define cy_writel(port,val)     {writel((val),(port)); mb();}
 
 #define cy_readb(port)  readb(port)
 #define cy_readw(port)  readw(port)
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 66e273284..b378e57b2 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -33,8 +33,8 @@ struct vfsmount;
  */
 struct qstr {
 	unsigned int hash;
-	const unsigned char *name;
 	unsigned int len;
+	const unsigned char *name;
 };
 
 struct dentry_stat_t {
@@ -101,11 +101,11 @@ struct dentry {
 	unsigned long d_time;		/* used by d_revalidate */
 	struct dentry_operations *d_op;
 	struct super_block *d_sb;	/* The root of the dentry tree */
-	int d_mounted;
 	void *d_fsdata;			/* fs-specific data */
  	struct rcu_head d_rcu;
 	struct dcookie_struct *d_cookie; /* cookie, if any */
 	struct hlist_node d_hash;	/* lookup hash list */	
+	int d_mounted;
 	unsigned char d_iname[DNAME_INLINE_LEN_MIN];	/* small names */
 };
 
diff --git a/include/linux/delay.h b/include/linux/delay.h
index f5610919d..5c43c336c 100644
--- a/include/linux/delay.h
+++ b/include/linux/delay.h
@@ -39,5 +39,11 @@ extern unsigned long loops_per_jiffy;
 #endif
 
 void msleep(unsigned int msecs);
+unsigned long msleep_interruptible(unsigned int msecs);
+
+static inline void ssleep(unsigned int seconds)
+{
+	msleep(seconds * 1000);
+}
 
 #endif /* defined(_LINUX_DELAY_H) */
diff --git a/include/linux/device.h b/include/linux/device.h
index 49d3865aa..4bb694c67 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -59,7 +59,6 @@ struct bus_type {
 	struct driver_attribute	* drv_attrs;
 
 	int		(*match)(struct device * dev, struct device_driver * drv);
-	struct device * (*add)	(struct device * parent, char * bus_id);
 	int		(*hotplug) (struct device *dev, char **envp, 
 				    int num_envp, char *buffer, int buffer_size);
 	int		(*suspend)(struct device * dev, u32 state);
@@ -285,6 +284,9 @@ struct device {
 
 	struct list_head	dma_pools;	/* dma pools (if dma'ble) */
 
+	struct dma_coherent_mem	*dma_mem; /* internal for coherent mem
+					     override */
+
 	void	(*release)(struct device * dev);
 };
 
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 43f6c726c..806c30533 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -1,6 +1,9 @@
 #ifndef _ASM_LINUX_DMA_MAPPING_H
 #define _ASM_LINUX_DMA_MAPPING_H
 
+#include <linux/device.h>
+#include <linux/err.h>
+
 /* These definitions mirror those in pci.h, so they can be used
  * interchangeably with their PCI_ counterparts */
 enum dma_data_direction {
@@ -21,6 +24,33 @@ enum dma_data_direction {
 
 extern u64 dma_get_required_mask(struct device *dev);
 
+/* flags for the coherent memory api */
+#define	DMA_MEMORY_MAP			0x01
+#define DMA_MEMORY_IO			0x02
+#define DMA_MEMORY_INCLUDES_CHILDREN	0x04
+#define DMA_MEMORY_EXCLUSIVE		0x08
+
+#ifndef ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
+static inline int
+dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+			    dma_addr_t device_addr, size_t size, int flags)
+{
+	return 0;
+}
+
+static inline void
+dma_release_declared_memory(struct device *dev)
+{
+}
+
+static inline void *
+dma_mark_declared_memory_occupied(struct device *dev,
+				  dma_addr_t device_addr, size_t size)
+{
+	return ERR_PTR(-EBUSY);
+}
+#endif
+
 #endif
 
 
diff --git a/include/linux/dqblk_xfs.h b/include/linux/dqblk_xfs.h
index 330f23e0c..bf2d65765 100644
--- a/include/linux/dqblk_xfs.h
+++ b/include/linux/dqblk_xfs.h
@@ -1,34 +1,22 @@
 /*
- * Copyright (c) 1995-2001 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 1995-2001,2004 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2.1 of the GNU Lesser General Public License
  * as published by the Free Software Foundation.
  *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 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.
  *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like.  Any license provided herein, whether implied or
- * otherwise, applies only to this software file.  Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
+ * 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
  *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
- * USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA  94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ * Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ * Mountain View, CA 94043, USA, or: http://www.sgi.com
  */
 #ifndef _LINUX_DQBLK_XFS_H
 #define _LINUX_DQBLK_XFS_H
@@ -40,12 +28,12 @@
  */
 
 #define XQM_CMD(x)	(('X'<<8)+(x))	/* note: forms first QCMD argument */
-#define Q_XQUOTAON	XQM_CMD(0x1)	/* enable accounting/enforcement */
-#define Q_XQUOTAOFF	XQM_CMD(0x2)	/* disable accounting/enforcement */
-#define Q_XGETQUOTA	XQM_CMD(0x3)	/* get disk limits and usage */
-#define Q_XSETQLIM	XQM_CMD(0x4)	/* set disk limits */
-#define Q_XGETQSTAT	XQM_CMD(0x5)	/* get quota subsystem status */
-#define Q_XQUOTARM	XQM_CMD(0x6)	/* free disk space used by dquots */
+#define Q_XQUOTAON	XQM_CMD(1)	/* enable accounting/enforcement */
+#define Q_XQUOTAOFF	XQM_CMD(2)	/* disable accounting/enforcement */
+#define Q_XGETQUOTA	XQM_CMD(3)	/* get disk limits and usage */
+#define Q_XSETQLIM	XQM_CMD(4)	/* set disk limits */
+#define Q_XGETQSTAT	XQM_CMD(5)	/* get quota subsystem status */
+#define Q_XQUOTARM	XQM_CMD(6)	/* free disk space used by dquots */
 
 /*
  * fs_disk_quota structure:
@@ -104,6 +92,19 @@ typedef struct fs_disk_quota {
 #define FS_DQ_RTBTIMER 	(1<<8)
 #define FS_DQ_TIMER_MASK	(FS_DQ_BTIMER | FS_DQ_ITIMER | FS_DQ_RTBTIMER)
 
+/*
+ * Warning counts are set in both super user's dquot and others. For others,
+ * warnings are set/cleared by the administrators (or automatically by going
+ * below the soft limit).  Superusers warning values set the warning limits
+ * for the rest.  In case these values are zero, the DQ_{F,B}WARNLIMIT values
+ * defined below are used. 
+ * These values also apply only to the d_fieldmask field for Q_XSETQLIM.
+ */
+#define FS_DQ_BWARNS	(1<<9)
+#define FS_DQ_IWARNS	(1<<10)
+#define FS_DQ_RTBWARNS	(1<<11)
+#define FS_DQ_WARNS_MASK	(FS_DQ_BWARNS | FS_DQ_IWARNS | FS_DQ_RTBWARNS)
+
 /*
  * Various flags related to quotactl(2).  Only relevant to XFS filesystems.
  */
@@ -111,9 +112,11 @@ typedef struct fs_disk_quota {
 #define XFS_QUOTA_UDQ_ENFD	(1<<1)  /* user quota limits enforcement */
 #define XFS_QUOTA_GDQ_ACCT	(1<<2)  /* group quota accounting */
 #define XFS_QUOTA_GDQ_ENFD	(1<<3)  /* group quota limits enforcement */
+#define XFS_QUOTA_PDQ_ACCT	(1<<4)  /* project quota accounting */
+#define XFS_QUOTA_PDQ_ENFD	(1<<5)  /* project quota limits enforcement */
 
 #define XFS_USER_QUOTA		(1<<0)	/* user quota type */
-#define XFS_PROJ_QUOTA		(1<<1)	/* (IRIX) project quota type */
+#define XFS_PROJ_QUOTA		(1<<1)	/* project quota type */
 #define XFS_GROUP_QUOTA		(1<<2)	/* group quota type */
 
 /*
diff --git a/include/linux/efs_dir.h b/include/linux/efs_dir.h
index 331524130..a09ec0105 100644
--- a/include/linux/efs_dir.h
+++ b/include/linux/efs_dir.h
@@ -11,7 +11,7 @@
 #define EFS_DIRBSIZE		(1 << EFS_DIRBSIZE_BITS)
 
 struct efs_dentry {
-	unsigned int	inode;
+	__be32		inode;
 	unsigned char	namelen;
 	char		name[3];
 };
@@ -23,7 +23,7 @@ struct efs_dentry {
 #define EFS_DIRBLK_MAGIC	0xbeef	/* moo */
 
 struct efs_dir {
-	unsigned short	magic;
+	__be16	magic;
 	unsigned char	firstused;
 	unsigned char	slots;
 
diff --git a/include/linux/efs_fs.h b/include/linux/efs_fs.h
index 1640eb875..f7c844623 100644
--- a/include/linux/efs_fs.h
+++ b/include/linux/efs_fs.h
@@ -40,11 +40,9 @@ extern struct inode_operations efs_dir_inode_operations;
 extern struct file_operations efs_dir_operations;
 extern struct address_space_operations efs_symlink_aops;
 
-extern int efs_fill_super(struct super_block *, void *, int);
-extern int efs_statfs(struct super_block *, struct kstatfs *);
-
 extern void efs_read_inode(struct inode *);
 extern efs_block_t efs_map_block(struct inode *, efs_block_t);
+extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
 extern struct dentry *efs_lookup(struct inode *, struct dentry *, struct nameidata *);
 extern int efs_bmap(struct inode *, int);
diff --git a/include/linux/efs_fs_i.h b/include/linux/efs_fs_i.h
index 64fe538ac..617c474ca 100644
--- a/include/linux/efs_fs_i.h
+++ b/include/linux/efs_fs_i.h
@@ -28,8 +28,8 @@ typedef union extent_u {
 } efs_extent;
 
 typedef struct edevs {
-	short		odev;
-	unsigned int	ndev;
+	__be16		odev;
+	__be32		ndev;
 } efs_devs;
 
 /*
@@ -37,16 +37,16 @@ typedef struct edevs {
  * is exactly 128 bytes long.
  */
 struct	efs_dinode {
-	u_short		di_mode;	/* mode and type of file */
-	short		di_nlink;	/* number of links to file */
-	u_short		di_uid;		/* owner's user id */
-	u_short		di_gid;		/* owner's group id */
-	int32_t		di_size;	/* number of bytes in file */
-	int32_t		di_atime;	/* time last accessed */
-	int32_t		di_mtime;	/* time last modified */
-	int32_t		di_ctime;	/* time created */
-	uint32_t	di_gen;		/* generation number */
-	short		di_numextents;	/* # of extents */
+	__be16		di_mode;	/* mode and type of file */
+	__be16		di_nlink;	/* number of links to file */
+	__be16		di_uid;		/* owner's user id */
+	__be16		di_gid;		/* owner's group id */
+	__be32		di_size;	/* number of bytes in file */
+	__be32		di_atime;	/* time last accessed */
+	__be32		di_mtime;	/* time last modified */
+	__be32		di_ctime;	/* time created */
+	__be32		di_gen;		/* generation number */
+	__be16		di_numextents;	/* # of extents */
 	u_char		di_version;	/* version of inode */
 	u_char		di_spare;	/* spare - used by AFS */
 	union di_addr {
diff --git a/include/linux/efs_fs_sb.h b/include/linux/efs_fs_sb.h
index 21d01d0d4..c76088bae 100644
--- a/include/linux/efs_fs_sb.h
+++ b/include/linux/efs_fs_sb.h
@@ -23,39 +23,39 @@
 
 /* efs superblock on disk */
 struct efs_super {
-	int32_t		fs_size;        /* size of filesystem, in sectors */
-	int32_t		fs_firstcg;     /* bb offset to first cg */
-	int32_t		fs_cgfsize;     /* size of cylinder group in bb's */
-	short		fs_cgisize;     /* bb's of inodes per cylinder group */
-	short		fs_sectors;     /* sectors per track */
-	short		fs_heads;       /* heads per cylinder */
-	short		fs_ncg;         /* # of cylinder groups in filesystem */
-	short		fs_dirty;       /* fs needs to be fsck'd */
-	int32_t		fs_time;        /* last super-block update */
-	int32_t		fs_magic;       /* magic number */
+	__be32		fs_size;        /* size of filesystem, in sectors */
+	__be32		fs_firstcg;     /* bb offset to first cg */
+	__be32		fs_cgfsize;     /* size of cylinder group in bb's */
+	__be16		fs_cgisize;     /* bb's of inodes per cylinder group */
+	__be16		fs_sectors;     /* sectors per track */
+	__be16		fs_heads;       /* heads per cylinder */
+	__be16		fs_ncg;         /* # of cylinder groups in filesystem */
+	__be16		fs_dirty;       /* fs needs to be fsck'd */
+	__be32		fs_time;        /* last super-block update */
+	__be32		fs_magic;       /* magic number */
 	char		fs_fname[6];    /* file system name */
 	char		fs_fpack[6];    /* file system pack name */
-	int32_t		fs_bmsize;      /* size of bitmap in bytes */
-	int32_t		fs_tfree;       /* total free data blocks */
-	int32_t		fs_tinode;      /* total free inodes */
-	int32_t		fs_bmblock;     /* bitmap location. */
-	int32_t		fs_replsb;      /* Location of replicated superblock. */
-	int32_t		fs_lastialloc;  /* last allocated inode */
+	__be32		fs_bmsize;      /* size of bitmap in bytes */
+	__be32		fs_tfree;       /* total free data blocks */
+	__be32		fs_tinode;      /* total free inodes */
+	__be32		fs_bmblock;     /* bitmap location. */
+	__be32		fs_replsb;      /* Location of replicated superblock. */
+	__be32		fs_lastialloc;  /* last allocated inode */
 	char		fs_spare[20];   /* space for expansion - MUST BE ZERO */
-	int32_t		fs_checksum;    /* checksum of volume portion of fs */
+	__be32		fs_checksum;    /* checksum of volume portion of fs */
 };
 
 /* efs superblock information in memory */
 struct efs_sb_info {
-	int32_t	fs_magic;	/* superblock magic number */
-	int32_t	fs_start;	/* first block of filesystem */
-	int32_t	first_block;	/* first data block in filesystem */
-	int32_t	total_blocks;	/* total number of blocks in filesystem */
-	int32_t	group_size;	/* # of blocks a group consists of */ 
-	int32_t	data_free;	/* # of free data blocks */
-	int32_t	inode_free;	/* # of free inodes */
-	short	inode_blocks;	/* # of blocks used for inodes in every grp */
-	short	total_groups;	/* # of groups */
+	__u32	fs_magic;	/* superblock magic number */
+	__u32	fs_start;	/* first block of filesystem */
+	__u32	first_block;	/* first data block in filesystem */
+	__u32	total_blocks;	/* total number of blocks in filesystem */
+	__u32	group_size;	/* # of blocks a group consists of */ 
+	__u32	data_free;	/* # of free data blocks */
+	__u32	inode_free;	/* # of free inodes */
+	__u16	inode_blocks;	/* # of blocks used for inodes in every grp */
+	__u16	total_groups;	/* # of groups */
 };
 
 #endif /* __EFS_FS_SB_H__ */
diff --git a/include/linux/efs_vh.h b/include/linux/efs_vh.h
index b9d7e4dda..b3df61ef2 100644
--- a/include/linux/efs_vh.h
+++ b/include/linux/efs_vh.h
@@ -17,26 +17,26 @@
 
 struct volume_directory {
 	char	vd_name[VDNAMESIZE];	/* name */
-	int	vd_lbn;			/* logical block number */
-	int	vd_nbytes;		/* file length in bytes */
+	__be32	vd_lbn;			/* logical block number */
+	__be32	vd_nbytes;		/* file length in bytes */
 };
 
 struct partition_table {	/* one per logical partition */
-	int	pt_nblks;	/* # of logical blks in partition */
-	int	pt_firstlbn;	/* first lbn of partition */
-	int	pt_type;	/* use of partition */
+	__be32	pt_nblks;	/* # of logical blks in partition */
+	__be32	pt_firstlbn;	/* first lbn of partition */
+	__be32	pt_type;	/* use of partition */
 };
 
 struct volume_header {
-	int	vh_magic;			/* identifies volume header */
-	short	vh_rootpt;			/* root partition number */
-	short	vh_swappt;			/* swap partition number */
+	__be32	vh_magic;			/* identifies volume header */
+	__be16	vh_rootpt;			/* root partition number */
+	__be16	vh_swappt;			/* swap partition number */
 	char	vh_bootfile[BFNAMESIZE];	/* name of file to boot */
 	char	pad[48];			/* device param space */
 	struct volume_directory vh_vd[NVDIR];	/* other vol hdr contents */
 	struct partition_table  vh_pt[NPARTAB];	/* device partition layout */
-	int	vh_csum;			/* volume header checksum */
-	int	vh_fill;			/* fill out to 512 bytes */
+	__be32	vh_csum;			/* volume header checksum */
+	__be32	vh_fill;			/* fill out to 512 bytes */
 };
 
 /* partition type sysv is used for EFS format CD-ROM partitions */
diff --git a/include/linux/elf.h b/include/linux/elf.h
index 8d0dd82cc..052b7401e 100644
--- a/include/linux/elf.h
+++ b/include/linux/elf.h
@@ -88,7 +88,9 @@ typedef __s64	Elf64_Sxword;
 
 #define EM_V850		87	/* NEC v850 */
 
-#define EM_H8_300       46      /* Hitachi H8/300,300H,H8S */
+#define EM_M32R		88	/* Renesas M32R */
+
+#define EM_H8_300       46      /* Renesas H8/300,300H,H8S */
 
 /*
  * This is an interim value that we will use until the committee comes
@@ -99,6 +101,9 @@ typedef __s64	Elf64_Sxword;
 /* Bogus old v850 magic number, used by old tools.  */
 #define EM_CYGNUS_V850	0x9080
 
+/* Bogus old m32r magic number, used by old tools.  */
+#define EM_CYGNUS_M32R	0x9041
+
 /*
  * This is the old interim value for S/390 architecture
  */
diff --git a/include/linux/err.h b/include/linux/err.h
index 92cab64fd..17c55df13 100644
--- a/include/linux/err.h
+++ b/include/linux/err.h
@@ -1,6 +1,8 @@
 #ifndef _LINUX_ERR_H
 #define _LINUX_ERR_H
 
+#include <linux/compiler.h>
+
 #include <asm/errno.h>
 
 /*
@@ -23,7 +25,7 @@ static inline long PTR_ERR(const void *ptr)
 
 static inline long IS_ERR(const void *ptr)
 {
-	return (unsigned long)ptr > (unsigned long)-1000L;
+	return unlikely((unsigned long)ptr > (unsigned long)-1000L);
 }
 
 #endif /* _LINUX_ERR_H */
diff --git a/include/linux/errno.h b/include/linux/errno.h
index a1f948f0a..d90b80f9b 100644
--- a/include/linux/errno.h
+++ b/include/linux/errno.h
@@ -22,6 +22,7 @@
 #define EBADTYPE	527	/* Type not supported by server */
 #define EJUKEBOX	528	/* Request initiated, but will not complete before timeout */
 #define EIOCBQUEUED	529	/* iocb queued, will get completion event */
+#define EIOCBRETRY	530	/* iocb queued, will trigger a retry */
 
 #endif
 
diff --git a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h
index 7c6f650c9..c2bd10f1f 100644
--- a/include/linux/ext2_fs.h
+++ b/include/linux/ext2_fs.h
@@ -135,14 +135,14 @@ static inline struct ext2_sb_info *EXT2_SB(struct super_block *sb)
  */
 struct ext2_group_desc
 {
-	__u32	bg_block_bitmap;		/* Blocks bitmap block */
-	__u32	bg_inode_bitmap;		/* Inodes bitmap block */
-	__u32	bg_inode_table;		/* Inodes table block */
-	__u16	bg_free_blocks_count;	/* Free blocks count */
-	__u16	bg_free_inodes_count;	/* Free inodes count */
-	__u16	bg_used_dirs_count;	/* Directories count */
-	__u16	bg_pad;
-	__u32	bg_reserved[3];
+	__le32	bg_block_bitmap;		/* Blocks bitmap block */
+	__le32	bg_inode_bitmap;		/* Inodes bitmap block */
+	__le32	bg_inode_table;		/* Inodes table block */
+	__le16	bg_free_blocks_count;	/* Free blocks count */
+	__le16	bg_free_inodes_count;	/* Free inodes count */
+	__le16	bg_used_dirs_count;	/* Directories count */
+	__le16	bg_pad;
+	__le32	bg_reserved[3];
 };
 
 /*
@@ -196,8 +196,13 @@ struct ext2_group_desc
 #define EXT2_IUNLINK_FL			0x08000000 /* Immutable unlink */
 #define EXT2_RESERVED_FL		0x80000000 /* reserved for ext2 lib */
 
+#ifdef CONFIG_VSERVER_LEGACY
+#define EXT2_FL_USER_VISIBLE		0x0803DFFF /* User visible flags */
+#define EXT2_FL_USER_MODIFIABLE		0x080380FF /* User modifiable flags */
+#else
 #define EXT2_FL_USER_VISIBLE		0x0003DFFF /* User visible flags */
 #define EXT2_FL_USER_MODIFIABLE		0x000380FF /* User modifiable flags */
+#endif
 
 /*
  * ioctl commands
@@ -211,49 +216,49 @@ struct ext2_group_desc
  * Structure of an inode on the disk
  */
 struct ext2_inode {
-	__u16	i_mode;		/* File mode */
-	__u16	i_uid;		/* Low 16 bits of Owner Uid */
-	__u32	i_size;		/* Size in bytes */
-	__u32	i_atime;	/* Access time */
-	__u32	i_ctime;	/* Creation time */
-	__u32	i_mtime;	/* Modification time */
-	__u32	i_dtime;	/* Deletion Time */
-	__u16	i_gid;		/* Low 16 bits of Group Id */
-	__u16	i_links_count;	/* Links count */
-	__u32	i_blocks;	/* Blocks count */
-	__u32	i_flags;	/* File flags */
+	__le16	i_mode;		/* File mode */
+	__le16	i_uid;		/* Low 16 bits of Owner Uid */
+	__le32	i_size;		/* Size in bytes */
+	__le32	i_atime;	/* Access time */
+	__le32	i_ctime;	/* Creation time */
+	__le32	i_mtime;	/* Modification time */
+	__le32	i_dtime;	/* Deletion Time */
+	__le16	i_gid;		/* Low 16 bits of Group Id */
+	__le16	i_links_count;	/* Links count */
+	__le32	i_blocks;	/* Blocks count */
+	__le32	i_flags;	/* File flags */
 	union {
 		struct {
-			__u32  l_i_reserved1;
+			__le32  l_i_reserved1;
 		} linux1;
 		struct {
-			__u32  h_i_translator;
+			__le32  h_i_translator;
 		} hurd1;
 		struct {
-			__u32  m_i_reserved1;
+			__le32  m_i_reserved1;
 		} masix1;
 	} osd1;				/* OS dependent 1 */
-	__u32	i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
-	__u32	i_generation;	/* File version (for NFS) */
-	__u32	i_file_acl;	/* File ACL */
-	__u32	i_dir_acl;	/* Directory ACL */
-	__u32	i_faddr;	/* Fragment address */
+	__le32	i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
+	__le32	i_generation;	/* File version (for NFS) */
+	__le32	i_file_acl;	/* File ACL */
+	__le32	i_dir_acl;	/* Directory ACL */
+	__le32	i_faddr;	/* Fragment address */
 	union {
 		struct {
 			__u8	l_i_frag;	/* Fragment number */
 			__u8	l_i_fsize;	/* Fragment size */
 			__u16	l_i_xid;	/* LRU Context */
-			__u16	l_i_uid_high;	/* these 2 fields    */
-			__u16	l_i_gid_high;	/* were reserved2[0] */
+			__le16	l_i_uid_high;	/* these 2 fields    */
+			__le16	l_i_gid_high;	/* were reserved2[0] */
 			__u32	l_i_reserved2;
 		} linux2;
 		struct {
 			__u8	h_i_frag;	/* Fragment number */
 			__u8	h_i_fsize;	/* Fragment size */
-			__u16	h_i_mode_high;
-			__u16	h_i_uid_high;
-			__u16	h_i_gid_high;
-			__u32	h_i_author;
+			__le16	h_i_mode_high;
+			__le16	h_i_uid_high;
+			__le16	h_i_gid_high;
+			__le32	h_i_author;
 		} hurd2;
 		struct {
 			__u8	m_i_frag;	/* Fragment number */
@@ -339,31 +344,31 @@ struct ext2_inode {
  * Structure of the super block
  */
 struct ext2_super_block {
-	__u32	s_inodes_count;		/* Inodes count */
-	__u32	s_blocks_count;		/* Blocks count */
-	__u32	s_r_blocks_count;	/* Reserved blocks count */
-	__u32	s_free_blocks_count;	/* Free blocks count */
-	__u32	s_free_inodes_count;	/* Free inodes count */
-	__u32	s_first_data_block;	/* First Data Block */
-	__u32	s_log_block_size;	/* Block size */
-	__s32	s_log_frag_size;	/* Fragment size */
-	__u32	s_blocks_per_group;	/* # Blocks per group */
-	__u32	s_frags_per_group;	/* # Fragments per group */
-	__u32	s_inodes_per_group;	/* # Inodes per group */
-	__u32	s_mtime;		/* Mount time */
-	__u32	s_wtime;		/* Write time */
-	__u16	s_mnt_count;		/* Mount count */
-	__s16	s_max_mnt_count;	/* Maximal mount count */
-	__u16	s_magic;		/* Magic signature */
-	__u16	s_state;		/* File system state */
-	__u16	s_errors;		/* Behaviour when detecting errors */
-	__u16	s_minor_rev_level; 	/* minor revision level */
-	__u32	s_lastcheck;		/* time of last check */
-	__u32	s_checkinterval;	/* max. time between checks */
-	__u32	s_creator_os;		/* OS */
-	__u32	s_rev_level;		/* Revision level */
-	__u16	s_def_resuid;		/* Default uid for reserved blocks */
-	__u16	s_def_resgid;		/* Default gid for reserved blocks */
+	__le32	s_inodes_count;		/* Inodes count */
+	__le32	s_blocks_count;		/* Blocks count */
+	__le32	s_r_blocks_count;	/* Reserved blocks count */
+	__le32	s_free_blocks_count;	/* Free blocks count */
+	__le32	s_free_inodes_count;	/* Free inodes count */
+	__le32	s_first_data_block;	/* First Data Block */
+	__le32	s_log_block_size;	/* Block size */
+	__le32	s_log_frag_size;	/* Fragment size */
+	__le32	s_blocks_per_group;	/* # Blocks per group */
+	__le32	s_frags_per_group;	/* # Fragments per group */
+	__le32	s_inodes_per_group;	/* # Inodes per group */
+	__le32	s_mtime;		/* Mount time */
+	__le32	s_wtime;		/* Write time */
+	__le16	s_mnt_count;		/* Mount count */
+	__le16	s_max_mnt_count;	/* Maximal mount count */
+	__le16	s_magic;		/* Magic signature */
+	__le16	s_state;		/* File system state */
+	__le16	s_errors;		/* Behaviour when detecting errors */
+	__le16	s_minor_rev_level; 	/* minor revision level */
+	__le32	s_lastcheck;		/* time of last check */
+	__le32	s_checkinterval;	/* max. time between checks */
+	__le32	s_creator_os;		/* OS */
+	__le32	s_rev_level;		/* Revision level */
+	__le16	s_def_resuid;		/* Default uid for reserved blocks */
+	__le16	s_def_resgid;		/* Default gid for reserved blocks */
 	/*
 	 * These fields are for EXT2_DYNAMIC_REV superblocks only.
 	 *
@@ -377,16 +382,16 @@ struct ext2_super_block {
 	 * feature set, it must abort and not try to meddle with
 	 * things it doesn't understand...
 	 */
-	__u32	s_first_ino; 		/* First non-reserved inode */
-	__u16   s_inode_size; 		/* size of inode structure */
-	__u16	s_block_group_nr; 	/* block group # of this superblock */
-	__u32	s_feature_compat; 	/* compatible feature set */
-	__u32	s_feature_incompat; 	/* incompatible feature set */
-	__u32	s_feature_ro_compat; 	/* readonly-compatible feature set */
+	__le32	s_first_ino; 		/* First non-reserved inode */
+	__le16   s_inode_size; 		/* size of inode structure */
+	__le16	s_block_group_nr; 	/* block group # of this superblock */
+	__le32	s_feature_compat; 	/* compatible feature set */
+	__le32	s_feature_incompat; 	/* incompatible feature set */
+	__le32	s_feature_ro_compat; 	/* readonly-compatible feature set */
 	__u8	s_uuid[16];		/* 128-bit uuid for volume */
 	char	s_volume_name[16]; 	/* volume name */
 	char	s_last_mounted[64]; 	/* directory where last mounted */
-	__u32	s_algorithm_usage_bitmap; /* For compression */
+	__le32	s_algorithm_usage_bitmap; /* For compression */
 	/*
 	 * Performance hints.  Directory preallocation should only
 	 * happen if the EXT2_COMPAT_PREALLOC flag is on.
@@ -405,8 +410,8 @@ struct ext2_super_block {
 	__u8	s_def_hash_version;	/* Default hash version to use */
 	__u8	s_reserved_char_pad;
 	__u16	s_reserved_word_pad;
-	__u32	s_default_mount_opts;
- 	__u32	s_first_meta_bg; 	/* First metablock block group */
+	__le32	s_default_mount_opts;
+ 	__le32	s_first_meta_bg; 	/* First metablock block group */
 	__u32	s_reserved[190];	/* Padding to the end of the block */
 };
 
@@ -508,9 +513,9 @@ struct ext2_super_block {
 #define EXT2_NAME_LEN 255
 
 struct ext2_dir_entry {
-	__u32	inode;			/* Inode number */
-	__u16	rec_len;		/* Directory entry length */
-	__u16	name_len;		/* Name length */
+	__le32	inode;			/* Inode number */
+	__le16	rec_len;		/* Directory entry length */
+	__le16	name_len;		/* Name length */
 	char	name[EXT2_NAME_LEN];	/* File name */
 };
 
@@ -521,8 +526,8 @@ struct ext2_dir_entry {
  * file_type field.
  */
 struct ext2_dir_entry_2 {
-	__u32	inode;			/* Inode number */
-	__u16	rec_len;		/* Directory entry length */
+	__le32	inode;			/* Inode number */
+	__le16	rec_len;		/* Directory entry length */
 	__u8	name_len;		/* Name length */
 	__u8	file_type;
 	char	name[EXT2_NAME_LEN];	/* File name */
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index 9a5137606..ab9c0378e 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -129,14 +129,14 @@ struct statfs;
  */
 struct ext3_group_desc
 {
-	__u32	bg_block_bitmap;		/* Blocks bitmap block */
-	__u32	bg_inode_bitmap;		/* Inodes bitmap block */
-	__u32	bg_inode_table;		/* Inodes table block */
-	__u16	bg_free_blocks_count;	/* Free blocks count */
-	__u16	bg_free_inodes_count;	/* Free inodes count */
-	__u16	bg_used_dirs_count;	/* Directories count */
+	__le32	bg_block_bitmap;		/* Blocks bitmap block */
+	__le32	bg_inode_bitmap;		/* Inodes bitmap block */
+	__le32	bg_inode_table;		/* Inodes table block */
+	__le16	bg_free_blocks_count;	/* Free blocks count */
+	__le16	bg_free_inodes_count;	/* Free inodes count */
+	__le16	bg_used_dirs_count;	/* Directories count */
 	__u16	bg_pad;
-	__u32	bg_reserved[3];
+	__le32	bg_reserved[3];
 };
 
 /*
@@ -189,8 +189,13 @@ struct ext3_group_desc
 #define EXT3_IUNLINK_FL			0x08000000 /* Immutable unlink */
 #define EXT3_RESERVED_FL		0x80000000 /* reserved for ext3 lib */
 
+#ifdef CONFIG_VSERVER_LEGACY
+#define EXT3_FL_USER_VISIBLE		0x0803DFFF /* User visible flags */
+#define EXT3_FL_USER_MODIFIABLE		0x080380FF /* User modifiable flags */
+#else
 #define EXT3_FL_USER_VISIBLE		0x0003DFFF /* User visible flags */
 #define EXT3_FL_USER_MODIFIABLE		0x000380FF /* User modifiable flags */
+#endif
 
 /*
  * Inode dynamic state flags
@@ -210,7 +215,7 @@ struct ext3_group_desc
 #ifdef CONFIG_JBD_DEBUG
 #define EXT3_IOC_WAIT_FOR_READONLY	_IOR('f', 99, long)
 #endif
-#ifdef	CONFIG_VSERVER_LEGACY		
+#ifdef	CONFIG_VSERVER_LEGACY
 #define EXT3_IOC_SETXID			FIOC_SETXIDJ
 #endif
 
@@ -218,17 +223,17 @@ struct ext3_group_desc
  * Structure of an inode on the disk
  */
 struct ext3_inode {
-	__u16	i_mode;		/* File mode */
-	__u16	i_uid;		/* Low 16 bits of Owner Uid */
-	__u32	i_size;		/* Size in bytes */
-	__u32	i_atime;	/* Access time */
-	__u32	i_ctime;	/* Creation time */
-	__u32	i_mtime;	/* Modification time */
-	__u32	i_dtime;	/* Deletion Time */
-	__u16	i_gid;		/* Low 16 bits of Group Id */
-	__u16	i_links_count;	/* Links count */
-	__u32	i_blocks;	/* Blocks count */
-	__u32	i_flags;	/* File flags */
+	__le16	i_mode;		/* File mode */
+	__le16	i_uid;		/* Low 16 bits of Owner Uid */
+	__le32	i_size;		/* Size in bytes */
+	__le32	i_atime;	/* Access time */
+	__le32	i_ctime;	/* Creation time */
+	__le32	i_mtime;	/* Modification time */
+	__le32	i_dtime;	/* Deletion Time */
+	__le16	i_gid;		/* Low 16 bits of Group Id */
+	__le16	i_links_count;	/* Links count */
+	__le32	i_blocks;	/* Blocks count */
+	__le32	i_flags;	/* File flags */
 	union {
 		struct {
 			__u32  l_i_reserved1;
@@ -240,18 +245,18 @@ struct ext3_inode {
 			__u32  m_i_reserved1;
 		} masix1;
 	} osd1;				/* OS dependent 1 */
-	__u32	i_block[EXT3_N_BLOCKS];/* Pointers to blocks */
-	__u32	i_generation;	/* File version (for NFS) */
-	__u32	i_file_acl;	/* File ACL */
-	__u32	i_dir_acl;	/* Directory ACL */
-	__u32	i_faddr;	/* Fragment address */
+	__le32	i_block[EXT3_N_BLOCKS];/* Pointers to blocks */
+	__le32	i_generation;	/* File version (for NFS) */
+	__le32	i_file_acl;	/* File ACL */
+	__le32	i_dir_acl;	/* Directory ACL */
+	__le32	i_faddr;	/* Fragment address */
 	union {
 		struct {
 			__u8	l_i_frag;	/* Fragment number */
 			__u8	l_i_fsize;	/* Fragment size */
 			__u16	l_i_xid;	/* LRU Context */
-			__u16	l_i_uid_high;	/* these 2 fields    */
-			__u16	l_i_gid_high;	/* were reserved2[0] */
+			__le16	l_i_uid_high;	/* these 2 fields    */
+			__le16	l_i_gid_high;	/* were reserved2[0] */
 			__u32	l_i_reserved2;
 		} linux2;
 		struct {
@@ -330,6 +335,7 @@ struct ext3_inode {
 #define EXT3_MOUNT_NO_UID32		0x2000  /* Disable 32-bit UIDs */
 #define EXT3_MOUNT_XATTR_USER		0x4000	/* Extended user attributes */
 #define EXT3_MOUNT_POSIX_ACL		0x8000	/* POSIX Access Control Lists */
+#define EXT3_MOUNT_BARRIER		0x10000 /* Use block barriers */
 #define EXT3_MOUNT_TAG_XID		(1<<16) /* Enable Context Tags */
 
 /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
@@ -370,31 +376,31 @@ struct ext3_inode {
  * Structure of the super block
  */
 struct ext3_super_block {
-/*00*/	__u32	s_inodes_count;		/* Inodes count */
-	__u32	s_blocks_count;		/* Blocks count */
-	__u32	s_r_blocks_count;	/* Reserved blocks count */
-	__u32	s_free_blocks_count;	/* Free blocks count */
-/*10*/	__u32	s_free_inodes_count;	/* Free inodes count */
-	__u32	s_first_data_block;	/* First Data Block */
-	__u32	s_log_block_size;	/* Block size */
-	__s32	s_log_frag_size;	/* Fragment size */
-/*20*/	__u32	s_blocks_per_group;	/* # Blocks per group */
-	__u32	s_frags_per_group;	/* # Fragments per group */
-	__u32	s_inodes_per_group;	/* # Inodes per group */
-	__u32	s_mtime;		/* Mount time */
-/*30*/	__u32	s_wtime;		/* Write time */
-	__u16	s_mnt_count;		/* Mount count */
-	__s16	s_max_mnt_count;	/* Maximal mount count */
-	__u16	s_magic;		/* Magic signature */
-	__u16	s_state;		/* File system state */
-	__u16	s_errors;		/* Behaviour when detecting errors */
-	__u16	s_minor_rev_level;	/* minor revision level */
-/*40*/	__u32	s_lastcheck;		/* time of last check */
-	__u32	s_checkinterval;	/* max. time between checks */
-	__u32	s_creator_os;		/* OS */
-	__u32	s_rev_level;		/* Revision level */
-/*50*/	__u16	s_def_resuid;		/* Default uid for reserved blocks */
-	__u16	s_def_resgid;		/* Default gid for reserved blocks */
+/*00*/	__le32	s_inodes_count;		/* Inodes count */
+	__le32	s_blocks_count;		/* Blocks count */
+	__le32	s_r_blocks_count;	/* Reserved blocks count */
+	__le32	s_free_blocks_count;	/* Free blocks count */
+/*10*/	__le32	s_free_inodes_count;	/* Free inodes count */
+	__le32	s_first_data_block;	/* First Data Block */
+	__le32	s_log_block_size;	/* Block size */
+	__le32	s_log_frag_size;	/* Fragment size */
+/*20*/	__le32	s_blocks_per_group;	/* # Blocks per group */
+	__le32	s_frags_per_group;	/* # Fragments per group */
+	__le32	s_inodes_per_group;	/* # Inodes per group */
+	__le32	s_mtime;		/* Mount time */
+/*30*/	__le32	s_wtime;		/* Write time */
+	__le16	s_mnt_count;		/* Mount count */
+	__le16	s_max_mnt_count;	/* Maximal mount count */
+	__le16	s_magic;		/* Magic signature */
+	__le16	s_state;		/* File system state */
+	__le16	s_errors;		/* Behaviour when detecting errors */
+	__le16	s_minor_rev_level;	/* minor revision level */
+/*40*/	__le32	s_lastcheck;		/* time of last check */
+	__le32	s_checkinterval;	/* max. time between checks */
+	__le32	s_creator_os;		/* OS */
+	__le32	s_rev_level;		/* Revision level */
+/*50*/	__le16	s_def_resuid;		/* Default uid for reserved blocks */
+	__le16	s_def_resgid;		/* Default gid for reserved blocks */
 	/*
 	 * These fields are for EXT3_DYNAMIC_REV superblocks only.
 	 *
@@ -408,16 +414,16 @@ struct ext3_super_block {
 	 * feature set, it must abort and not try to meddle with
 	 * things it doesn't understand...
 	 */
-	__u32	s_first_ino;		/* First non-reserved inode */
-	__u16   s_inode_size;		/* size of inode structure */
-	__u16	s_block_group_nr;	/* block group # of this superblock */
-	__u32	s_feature_compat;	/* compatible feature set */
-/*60*/	__u32	s_feature_incompat;	/* incompatible feature set */
-	__u32	s_feature_ro_compat;	/* readonly-compatible feature set */
+	__le32	s_first_ino;		/* First non-reserved inode */
+	__le16   s_inode_size;		/* size of inode structure */
+	__le16	s_block_group_nr;	/* block group # of this superblock */
+	__le32	s_feature_compat;	/* compatible feature set */
+/*60*/	__le32	s_feature_incompat;	/* incompatible feature set */
+	__le32	s_feature_ro_compat;	/* readonly-compatible feature set */
 /*68*/	__u8	s_uuid[16];		/* 128-bit uuid for volume */
 /*78*/	char	s_volume_name[16];	/* volume name */
 /*88*/	char	s_last_mounted[64];	/* directory where last mounted */
-/*C8*/	__u32	s_algorithm_usage_bitmap; /* For compression */
+/*C8*/	__le32	s_algorithm_usage_bitmap; /* For compression */
 	/*
 	 * Performance hints.  Directory preallocation should only
 	 * happen if the EXT3_FEATURE_COMPAT_DIR_PREALLOC flag is on.
@@ -429,15 +435,15 @@ struct ext3_super_block {
 	 * Journaling support valid if EXT3_FEATURE_COMPAT_HAS_JOURNAL set.
 	 */
 /*D0*/	__u8	s_journal_uuid[16];	/* uuid of journal superblock */
-/*E0*/	__u32	s_journal_inum;		/* inode number of journal file */
-	__u32	s_journal_dev;		/* device number of journal file */
-	__u32	s_last_orphan;		/* start of list of inodes to delete */
-	__u32	s_hash_seed[4];		/* HTREE hash seed */
+/*E0*/	__le32	s_journal_inum;		/* inode number of journal file */
+	__le32	s_journal_dev;		/* device number of journal file */
+	__le32	s_last_orphan;		/* start of list of inodes to delete */
+	__le32	s_hash_seed[4];		/* HTREE hash seed */
 	__u8	s_def_hash_version;	/* Default hash version to use */
 	__u8	s_reserved_char_pad;
 	__u16	s_reserved_word_pad;
-	__u32	s_default_mount_opts;
-	__u32	s_first_meta_bg; 	/* First metablock block group */
+	__le32	s_default_mount_opts;
+	__le32	s_first_meta_bg; 	/* First metablock block group */
 	__u32	s_reserved[190];	/* Padding to the end of the block */
 };
 
@@ -552,9 +558,9 @@ static inline struct ext3_inode_info *EXT3_I(struct inode *inode)
 #define EXT3_NAME_LEN 255
 
 struct ext3_dir_entry {
-	__u32	inode;			/* Inode number */
-	__u16	rec_len;		/* Directory entry length */
-	__u16	name_len;		/* Name length */
+	__le32	inode;			/* Inode number */
+	__le16	rec_len;		/* Directory entry length */
+	__le16	name_len;		/* Name length */
 	char	name[EXT3_NAME_LEN];	/* File name */
 };
 
@@ -565,8 +571,8 @@ struct ext3_dir_entry {
  * file_type field.
  */
 struct ext3_dir_entry_2 {
-	__u32	inode;			/* Inode number */
-	__u16	rec_len;		/* Directory entry length */
+	__le32	inode;			/* Inode number */
+	__le16	rec_len;		/* Directory entry length */
 	__u8	name_len;		/* Name length */
 	__u8	file_type;
 	char	name[EXT3_NAME_LEN];	/* File name */
@@ -730,7 +736,7 @@ extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int,
 extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
 
 extern void ext3_read_inode (struct inode *);
-extern void ext3_write_inode (struct inode *, int);
+extern int  ext3_write_inode (struct inode *, int);
 extern int  ext3_setattr (struct dentry *, struct iattr *);
 extern void ext3_put_inode (struct inode *);
 extern void ext3_delete_inode (struct inode *);
diff --git a/include/linux/ext3_fs_i.h b/include/linux/ext3_fs_i.h
index 7451cdcfb..48baa3f4b 100644
--- a/include/linux/ext3_fs_i.h
+++ b/include/linux/ext3_fs_i.h
@@ -22,7 +22,7 @@
  * second extended file system inode data in memory
  */
 struct ext3_inode_info {
-	__u32	i_data[15];
+	__le32	i_data[15];	/* unconverted */
 	__u32	i_flags;
 #ifdef EXT3_FRAGMENTS
 	__u32	i_faddr;
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 9186883fc..c38132231 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -158,6 +158,7 @@ struct fb_bitfield {
 #define FB_CHANGE_CMAP_VBL     32	/* change colormap on vbl	*/
 #define FB_ACTIVATE_ALL	       64	/* change all VCs on this fb	*/
 #define FB_ACTIVATE_FORCE     128	/* force apply even when no change*/
+#define FB_ACTIVATE_INV_MODE  256       /* invalidate videomode */
 
 #define FB_ACCELF_TEXT		1	/* (OBSOLETE) see fb_info.flags and vc_mode */
 
@@ -241,73 +242,6 @@ struct fb_con2fbmap {
 #define VESA_HSYNC_SUSPEND      2
 #define VESA_POWERDOWN          3
 
-/* Definitions below are used in the parsed monitor specs */
-#define FB_DPMS_ACTIVE_OFF	1
-#define FB_DPMS_SUSPEND		2
-#define FB_DPMS_STANDBY		4
-
-#define FB_DISP_DDI		1
-#define FB_DISP_ANA_700_300	2
-#define FB_DISP_ANA_714_286	4
-#define FB_DISP_ANA_1000_400	8
-#define FB_DISP_ANA_700_000	16
-
-#define FB_DISP_MONO		32
-#define FB_DISP_RGB		64
-#define FB_DISP_MULTI		128
-#define FB_DISP_UNKNOWN		256
-
-#define FB_SIGNAL_NONE		0
-#define FB_SIGNAL_BLANK_BLANK	1
-#define FB_SIGNAL_SEPARATE	2
-#define FB_SIGNAL_COMPOSITE	4
-#define FB_SIGNAL_SYNC_ON_GREEN	8
-#define FB_SIGNAL_SERRATION_ON	16
-
-#define FB_MISC_PRIM_COLOR	1
-#define FB_MISC_1ST_DETAIL	2	/* First Detailed Timing is preferred */
-
-struct fb_chroma {
-	__u32 redx;	/* in fraction of 1024 */
-	__u32 greenx;
-	__u32 bluex;
-	__u32 whitex;
-	__u32 redy;
-	__u32 greeny;
-	__u32 bluey;
-	__u32 whitey;
-};
-
-struct fb_monspecs {
-	struct fb_chroma chroma;
-	struct fb_videomode *modedb;	/* mode database */
-	__u8  manufacturer[4];		/* Manufacturer */
-	__u8  monitor[14];		/* Monitor String */
-	__u8  serial_no[14];		/* Serial Number */
-	__u8  ascii[14];		/* ? */
-	__u32 modedb_len;		/* mode database length */
-	__u32 model;			/* Monitor Model */
-	__u32 serial;			/* Serial Number - Integer */
-	__u32 year;			/* Year manufactured */
-	__u32 week;			/* Week Manufactured */
-	__u32 hfmin;			/* hfreq lower limit (Hz) */
-	__u32 hfmax;			/* hfreq upper limit (Hz) */
-	__u32 dclkmin;			/* pixelclock lower limit (Hz) */
-	__u32 dclkmax;			/* pixelclock upper limit (Hz) */
-	__u16 input;			/* display type - see FB_DISP_* */
-	__u16 dpms;			/* DPMS support - see FB_DPMS_ */
-	__u16 signal;			/* Signal Type - see FB_SIGNAL_* */
-	__u16 vfmin;			/* vfreq lower limit (Hz) */
-	__u16 vfmax;			/* vfreq upper limit (Hz) */
-	__u16 gamma;			/* Gamma - in fractions of 100 */
-	__u16 gtf	: 1;		/* supports GTF */
-	__u16 misc;			/* Misc flags - see FB_MISC_* */
-	__u8  version;			/* EDID version... */
-	__u8  revision;			/* ...and revision */
-	__u8  max_x;			/* Maximum horizontal size (cm) */
-	__u8  max_y;			/* Maximum vertical size (cm) */
-};
-
 #define FB_VBLANK_VBLANKING	0x001	/* currently in a vertical blank */
 #define FB_VBLANK_HBLANKING	0x002	/* currently in a horizontal blank */
 #define FB_VBLANK_HAVE_VBLANK	0x004	/* vertical blanks can be detected */
@@ -383,6 +317,8 @@ struct fb_cursor {
 	const char *mask;	/* cursor mask bits */
 	struct fbcurpos hot;	/* cursor hot spot */
 	struct fb_image	image;	/* Cursor image */
+/* all fields below are for fbcon use only */
+	char  *data;             /* copy of bitmap */
 };
 
 #ifdef __KERNEL__
@@ -394,6 +330,7 @@ struct fb_cursor {
 #include <linux/workqueue.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/notifier.h>
+#include <linux/list.h>
 #include <asm/io.h>
 
 struct vm_area_struct;
@@ -401,6 +338,72 @@ struct fb_info;
 struct device;
 struct file;
 
+/* Definitions below are used in the parsed monitor specs */
+#define FB_DPMS_ACTIVE_OFF	1
+#define FB_DPMS_SUSPEND		2
+#define FB_DPMS_STANDBY		4
+
+#define FB_DISP_DDI		1
+#define FB_DISP_ANA_700_300	2
+#define FB_DISP_ANA_714_286	4
+#define FB_DISP_ANA_1000_400	8
+#define FB_DISP_ANA_700_000	16
+
+#define FB_DISP_MONO		32
+#define FB_DISP_RGB		64
+#define FB_DISP_MULTI		128
+#define FB_DISP_UNKNOWN		256
+
+#define FB_SIGNAL_NONE		0
+#define FB_SIGNAL_BLANK_BLANK	1
+#define FB_SIGNAL_SEPARATE	2
+#define FB_SIGNAL_COMPOSITE	4
+#define FB_SIGNAL_SYNC_ON_GREEN	8
+#define FB_SIGNAL_SERRATION_ON	16
+
+#define FB_MISC_PRIM_COLOR	1
+#define FB_MISC_1ST_DETAIL	2	/* First Detailed Timing is preferred */
+struct fb_chroma {
+	__u32 redx;	/* in fraction of 1024 */
+	__u32 greenx;
+	__u32 bluex;
+	__u32 whitex;
+	__u32 redy;
+	__u32 greeny;
+	__u32 bluey;
+	__u32 whitey;
+};
+
+struct fb_monspecs {
+	struct fb_chroma chroma;
+	struct fb_videomode *modedb;	/* mode database */
+	__u8  manufacturer[4];		/* Manufacturer */
+	__u8  monitor[14];		/* Monitor String */
+	__u8  serial_no[14];		/* Serial Number */
+	__u8  ascii[14];		/* ? */
+	__u32 modedb_len;		/* mode database length */
+	__u32 model;			/* Monitor Model */
+	__u32 serial;			/* Serial Number - Integer */
+	__u32 year;			/* Year manufactured */
+	__u32 week;			/* Week Manufactured */
+	__u32 hfmin;			/* hfreq lower limit (Hz) */
+	__u32 hfmax;			/* hfreq upper limit (Hz) */
+	__u32 dclkmin;			/* pixelclock lower limit (Hz) */
+	__u32 dclkmax;			/* pixelclock upper limit (Hz) */
+	__u16 input;			/* display type - see FB_DISP_* */
+	__u16 dpms;			/* DPMS support - see FB_DPMS_ */
+	__u16 signal;			/* Signal Type - see FB_SIGNAL_* */
+	__u16 vfmin;			/* vfreq lower limit (Hz) */
+	__u16 vfmax;			/* vfreq upper limit (Hz) */
+	__u16 gamma;			/* Gamma - in fractions of 100 */
+	__u16 gtf	: 1;		/* supports GTF */
+	__u16 misc;			/* Misc flags - see FB_MISC_* */
+	__u8  version;			/* EDID version... */
+	__u8  revision;			/* ...and revision */
+	__u8  max_x;			/* Maximum horizontal size (cm) */
+	__u8  max_y;			/* Maximum vertical size (cm) */
+};
+
 struct fb_cmap_user {
 	__u32 start;			/* First entry	*/
 	__u32 len;			/* Number of entries */
@@ -445,6 +448,21 @@ struct fb_cursor_user {
  *	if you own it
  */
 #define FB_EVENT_RESUME			0x03
+/*      An entry from the modelist was removed */
+#define FB_EVENT_MODE_DELETE            0x04
+/*      A driver registered itself */
+#define FB_EVENT_FB_REGISTERED          0x05
+/*      get console to framebuffer mapping */
+#define FB_EVENT_GET_CONSOLE_MAP        0x06
+/*      set console to framebuffer mapping */
+#define FB_EVENT_SET_CONSOLE_MAP        0x07
+
+
+struct fb_event {
+	struct fb_info *info;
+	void *data;
+};
+
 
 extern int fb_register_client(struct notifier_block *nb);
 extern int fb_unregister_client(struct notifier_block *nb);
@@ -581,8 +599,10 @@ struct fb_info {
 	struct fb_pixmap pixmap;	/* Image hardware mapper */
 	struct fb_pixmap sprite;	/* Cursor hardware mapper */
 	struct fb_cmap cmap;		/* Current cmap */
+	struct list_head modelist;      /* mode list */
 	struct fb_ops *fbops;
-	char *screen_base;		/* Virtual address */
+	char __iomem *screen_base;	/* Virtual address */
+	unsigned long screen_size;	/* Amount of ioremapped VRAM or 0 */ 
 	int currcon;			/* Current VC. */
 	void *pseudo_palette;		/* Fake palette of 16 colors */ 
 #define FBINFO_STATE_RUNNING	0
@@ -687,6 +707,8 @@ extern void fb_sysmove_buf_aligned(struct fb_info *info, struct fb_pixmap *buf,
 				u32 height);
 extern void fb_load_cursor_image(struct fb_info *);
 extern void fb_set_suspend(struct fb_info *info, int state);
+extern int fb_get_color_depth(struct fb_info *info);
+extern int fb_get_options(char *name, char **option);
 
 extern struct fb_info *registered_fb[FB_MAX];
 extern int num_registered_fb;
@@ -708,6 +730,7 @@ extern void framebuffer_release(struct fb_info *info);
 #define FB_MODE_IS_VESA		4
 #define FB_MODE_IS_CALCULATED	8
 #define FB_MODE_IS_FIRST	16
+#define FB_MODE_IS_FROM_VAR     32
 
 extern int fbmon_valid_timings(u_int pixclock, u_int htotal, u_int vtotal,
 			       const struct fb_info *fb_info);
@@ -726,6 +749,22 @@ extern void fb_destroy_modedb(struct fb_videomode *modedb);
 /* drivers/video/modedb.c */
 #define VESA_MODEDB_SIZE 34
 extern const struct fb_videomode vesa_modes[];
+extern void fb_var_to_videomode(struct fb_videomode *mode,
+				struct fb_var_screeninfo *var);
+extern void fb_videomode_to_var(struct fb_var_screeninfo *var,
+				struct fb_videomode *mode);
+extern int fb_mode_is_equal(struct fb_videomode *mode1,
+			    struct fb_videomode *mode2);
+extern int fb_add_videomode(struct fb_videomode *mode, struct list_head *head);
+extern void fb_delete_videomode(struct fb_videomode *mode,
+				struct list_head *head);
+extern struct fb_videomode *fb_match_mode(struct fb_var_screeninfo *var,
+					  struct list_head *head);
+extern struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var,
+					      struct list_head *head);
+extern void fb_destroy_modelist(struct list_head *head);
+extern void fb_videomode_to_modelist(struct fb_videomode *modedb, int num,
+				     struct list_head *head);
 
 /* drivers/video/fbcmap.c */
 extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);
@@ -754,6 +793,11 @@ struct fb_videomode {
 	u32 flag;
 };
 
+struct fb_modelist {
+	struct list_head list;
+	struct fb_videomode mode;
+};
+
 extern int fb_find_mode(struct fb_var_screeninfo *var,
 			struct fb_info *info, const char *mode_option,
 			const struct fb_videomode *db,
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 1e60528ca..e7ddd967d 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -88,6 +88,7 @@ extern int leases_enable, dir_notify_enable, lease_break_time;
 #define SPECIAL 4	/* For non-blockdevice requests in request queue */
 #define READ_SYNC	(READ | (1 << BIO_RW_SYNC))
 #define WRITE_SYNC	(WRITE | (1 << BIO_RW_SYNC))
+#define WRITE_BARRIER	((1 << BIO_RW) | (1 << BIO_RW_BARRIER))
 
 #define SEL_IN		1
 #define SEL_OUT		2
@@ -119,7 +120,7 @@ extern int leases_enable, dir_notify_enable, lease_break_time;
 #define MS_VERBOSE	32768
 #define MS_POSIXACL	(1<<16)	/* VFS does not apply the umask */
 #define MS_ONE_SECOND	(1<<17)	/* fs has 1 sec a/m/ctime resolution */
-#define MS_TAGXID	(1<<24)	/* tag inodes with context information */
+#define MS_TAGXID	(1<<24) /* tag inodes with context information */
 #define MS_ACTIVE	(1<<30)
 #define MS_NOUSER	(1<<31)
 
@@ -345,14 +346,14 @@ struct address_space {
 	struct inode		*host;		/* owner: inode, block_device */
 	struct radix_tree_root	page_tree;	/* radix tree of all pages */
 	spinlock_t		tree_lock;	/* and spinlock protecting it */
-	unsigned long		nrpages;	/* number of total pages */
-	pgoff_t			writeback_index;/* writeback starts here */
-	struct address_space_operations *a_ops;	/* methods */
-	struct prio_tree_root	i_mmap;		/* tree of private mappings */
 	unsigned int		i_mmap_writable;/* count VM_SHARED mappings */
+	struct prio_tree_root	i_mmap;		/* tree of private and shared mappings */
 	struct list_head	i_mmap_nonlinear;/*list VM_NONLINEAR mappings */
 	spinlock_t		i_mmap_lock;	/* protect tree, count, list */
 	atomic_t		truncate_count;	/* Cover race condition with truncate */
+	unsigned long		nrpages;	/* number of total pages */
+	pgoff_t			writeback_index;/* writeback starts here */
+	struct address_space_operations *a_ops;	/* methods */
 	unsigned long		flags;		/* error bits/gfp mask */
 	struct backing_dev_info *backing_dev_info; /* device readahead, etc */
 	spinlock_t		private_lock;	/* for use by the address_space */
@@ -448,6 +449,7 @@ struct inode {
 	unsigned long		i_version;
 	unsigned long		i_blocks;
 	unsigned short          i_bytes;
+	unsigned char		i_sock;
 	spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */
 	struct semaphore	i_sem;
 	struct rw_semaphore	i_alloc_sem;
@@ -467,6 +469,8 @@ struct inode {
 	struct cdev		*i_cdev;
 	int			i_cindex;
 
+	__u32			i_generation;
+
 	unsigned long		i_dnotify_mask; /* Directory notify events */
 	struct dnotify_struct	*i_dnotify; /* for directory notifications */
 
@@ -474,11 +478,9 @@ struct inode {
 	unsigned long		dirtied_when;	/* jiffies of first dirtying */
 
 	unsigned int		i_flags;
-	unsigned char		i_sock;
 
 	atomic_t		i_writecount;
 	void			*i_security;
-	__u32			i_generation;
 	union {
 		void		*generic_ip;
 	} u;
@@ -566,8 +568,8 @@ struct file_ra_state {
 	unsigned long prev_page;	/* Cache last read() position */
 	unsigned long ahead_start;	/* Ahead window */
 	unsigned long ahead_size;
-	unsigned long serial_cnt;	/* measure of sequentiality */
-	unsigned long average;		/* another measure of sequentiality */
+	unsigned long currnt_wnd_hit;	/* locality in the current window */
+	unsigned long average;		/* size of next current window */
 	unsigned long ra_pages;		/* Maximum readahead window */
 	unsigned long mmap_hit;		/* Cache hit stat for mmap accesses */
 	unsigned long mmap_miss;	/* Cache miss stat for mmap accesses */
@@ -587,6 +589,8 @@ struct file {
 	unsigned int		f_uid, f_gid;
 	struct file_ra_state	f_ra;
 
+	xid_t			f_xid;
+
 	unsigned long		f_version;
 	void			*f_security;
 
@@ -607,11 +611,6 @@ extern spinlock_t files_lock;
 #define get_file(x)	atomic_inc(&(x)->f_count)
 #define file_count(x)	atomic_read(&(x)->f_count)
 
-/* Initialize and open a private file and allocate its security structure. */
-extern int open_private_file(struct file *, struct dentry *, int);
-/* Release a private file and free its security structure. */
-extern void close_private_file(struct file *file);
-
 #define	MAX_NON_LFS	((1UL<<31) - 1)
 
 /* Page cache limit. The filesystems should put that into their s_maxbytes 
@@ -638,6 +637,18 @@ extern void close_private_file(struct file *file);
  */
 typedef struct files_struct *fl_owner_t;
 
+struct file_lock_operations {
+	void (*fl_insert)(struct file_lock *);	/* lock insertion callback */
+	void (*fl_remove)(struct file_lock *);	/* lock removal callback */
+	void (*fl_copy_lock)(struct file_lock *, struct file_lock *);
+	void (*fl_release_private)(struct file_lock *);
+};
+
+struct lock_manager_operations {
+	int (*fl_compare_owner)(struct file_lock *, struct file_lock *);
+	void (*fl_notify)(struct file_lock *);	/* unblock callback */
+};
+
 /* that will die - we need it for nfs_lock_info */
 #include <linux/nfs_fs_i.h>
 
@@ -654,13 +665,11 @@ struct file_lock {
 	loff_t fl_start;
 	loff_t fl_end;
 
-	void (*fl_notify)(struct file_lock *);	/* unblock callback */
-	void (*fl_insert)(struct file_lock *);	/* lock insertion callback */
-	void (*fl_remove)(struct file_lock *);	/* lock removal callback */
-
 	struct fasync_struct *	fl_fasync; /* for lease break notifications */
 	unsigned long fl_break_time;	/* for nonblocking lease breaks */
 
+	struct file_lock_operations *fl_ops;	/* Callbacks for filesystems */
+	struct lock_manager_operations *fl_lmops;	/* Callbacks for lockmanagers */
 	union {
 		struct nfs_lock_info	nfs_fl;
 	} fl_u;
@@ -696,9 +705,11 @@ extern void locks_remove_posix(struct file *, fl_owner_t);
 extern void locks_remove_flock(struct file *);
 extern struct file_lock *posix_test_lock(struct file *, struct file_lock *);
 extern int posix_lock_file(struct file *, struct file_lock *);
+extern int posix_lock_file_wait(struct file *, struct file_lock *);
 extern void posix_block_lock(struct file_lock *, struct file_lock *);
 extern void posix_unblock_lock(struct file *, struct file_lock *);
 extern int posix_locks_deadlock(struct file_lock *, struct file_lock *);
+extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl);
 extern int __break_lease(struct inode *inode, unsigned int flags);
 extern void lease_get_mtime(struct inode *, struct timespec *time);
 extern int lock_may_read(struct inode *, loff_t start, unsigned long count);
@@ -822,6 +833,11 @@ extern int vfs_rmdir(struct inode *, struct dentry *);
 extern int vfs_unlink(struct inode *, struct dentry *);
 extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
 
+/*
+ * VFS dentry helper functions.
+ */
+extern void dentry_unhash(struct dentry *dentry);
+
 /*
  * File types
  *
@@ -838,6 +854,11 @@ extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct de
 #define DT_SOCK		12
 #define DT_WHT		14
 
+#define OSYNC_METADATA	(1<<0)
+#define OSYNC_DATA	(1<<1)
+#define OSYNC_INODE	(1<<2)
+int generic_osync_inode(struct inode *, struct address_space *, int);
+
 /*
  * This is the "filldir" function type, used by readdir() to let
  * the kernel specify what kind of dirent layout it wants to have.
@@ -906,6 +927,7 @@ struct file_operations {
 	unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 	int (*check_flags)(int);
 	int (*dir_notify)(struct file *filp, unsigned long arg);
+	int (*flock) (struct file *, int, struct file_lock *);
 };
 
 struct inode_operations {
@@ -952,7 +974,7 @@ struct super_operations {
 	void (*read_inode) (struct inode *);
   
    	void (*dirty_inode) (struct inode *);
-	void (*write_inode) (struct inode *, int);
+	int (*write_inode) (struct inode *, int);
 	void (*put_inode) (struct inode *);
 	void (*drop_inode) (struct inode *);
 	void (*delete_inode) (struct inode *);
@@ -1141,6 +1163,7 @@ struct super_block *sget(struct file_system_type *type,
 struct super_block *get_sb_pseudo(struct file_system_type *, char *,
 			struct super_operations *ops, unsigned long);
 int __put_super(struct super_block *sb);
+int __put_super_and_need_restart(struct super_block *sb);
 void unnamed_dev_init(void);
 
 /* Alas, no aliases. Too much hassle with bringing module.h everywhere */
@@ -1423,7 +1446,11 @@ extern ssize_t generic_file_aio_read(struct kiocb *, char __user *, size_t, loff
 extern ssize_t __generic_file_aio_read(struct kiocb *, const struct iovec *, unsigned long, loff_t *);
 extern ssize_t generic_file_aio_write(struct kiocb *, const char __user *, size_t, loff_t);
 extern ssize_t generic_file_aio_write_nolock(struct kiocb *, const struct iovec *,
-				unsigned long, loff_t *);
+		unsigned long, loff_t *);
+extern ssize_t generic_file_direct_write(struct kiocb *, const struct iovec *,
+		unsigned long *, loff_t, loff_t *, size_t, size_t);
+extern ssize_t generic_file_buffered_write(struct kiocb *, const struct iovec *,
+		unsigned long, loff_t, loff_t *, size_t, ssize_t);
 extern ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos);
 extern ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos);
 ssize_t generic_file_write_nolock(struct file *file, const struct iovec *iov,
@@ -1461,18 +1488,21 @@ static inline void do_generic_file_read(struct file * filp, loff_t *ppos,
 ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
 	struct block_device *bdev, const struct iovec *iov, loff_t offset,
 	unsigned long nr_segs, get_blocks_t get_blocks, dio_iodone_t end_io,
-	int needs_special_locking);
+	int lock_type);
+
+enum {
+	DIO_LOCKING = 1, /* need locking between buffered and direct access */
+	DIO_NO_LOCKING,  /* bdev; no locking at all between buffered/direct */
+	DIO_OWN_LOCKING, /* filesystem locks buffered and direct internally */
+};
 
-/*
- * For filesystems which need locking between buffered and direct access
- */
 static inline ssize_t blockdev_direct_IO(int rw, struct kiocb *iocb,
 	struct inode *inode, struct block_device *bdev, const struct iovec *iov,
 	loff_t offset, unsigned long nr_segs, get_blocks_t get_blocks,
 	dio_iodone_t end_io)
 {
 	return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset,
-				nr_segs, get_blocks, end_io, 1);
+				nr_segs, get_blocks, end_io, DIO_LOCKING);
 }
 
 static inline ssize_t blockdev_direct_IO_no_locking(int rw, struct kiocb *iocb,
@@ -1481,7 +1511,16 @@ static inline ssize_t blockdev_direct_IO_no_locking(int rw, struct kiocb *iocb,
 	dio_iodone_t end_io)
 {
 	return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset,
-				nr_segs, get_blocks, end_io, 0);
+				nr_segs, get_blocks, end_io, DIO_NO_LOCKING);
+}
+
+static inline ssize_t blockdev_direct_IO_own_locking(int rw, struct kiocb *iocb,
+	struct inode *inode, struct block_device *bdev, const struct iovec *iov,
+	loff_t offset, unsigned long nr_segs, get_blocks_t get_blocks,
+	dio_iodone_t end_io)
+{
+	return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset,
+				nr_segs, get_blocks, end_io, DIO_OWN_LOCKING);
 }
 
 extern struct file_operations generic_ro_fops;
@@ -1562,6 +1601,39 @@ static inline ino_t parent_ino(struct dentry *dentry)
 /* kernel/fork.c */
 extern int unshare_files(void);
 
+/* Transaction based IO helpers */
+
+/*
+ * An argresp is stored in an allocated page and holds the
+ * size of the argument or response, along with its content
+ */
+struct simple_transaction_argresp {
+	ssize_t size;
+	char data[0];
+};
+
+#define SIMPLE_TRANSACTION_LIMIT (PAGE_SIZE - sizeof(struct simple_transaction_argresp))
+
+char *simple_transaction_get(struct file *file, const char __user *buf,
+				size_t size);
+ssize_t simple_transaction_read(struct file *file, char __user *buf,
+				size_t size, loff_t *pos);
+int simple_transaction_release(struct inode *inode, struct file *file);
+
+static inline void simple_transaction_set(struct file *file, size_t n)
+{
+	struct simple_transaction_argresp *ar = file->private_data;
+
+	BUG_ON(n > SIMPLE_TRANSACTION_LIMIT);
+
+	/*
+	 * The barrier ensures that ar->size will really remain zero until
+	 * ar->data is ready for reading.
+	 */
+	smp_mb();
+	ar->size = n;
+}
+
 #ifdef CONFIG_SECURITY
 static inline char *alloc_secdata(void)
 {
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 884d18df6..749992dc7 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -42,6 +42,8 @@ enum {
 	UNIXWARE_PARTITION = 0x63,	/* Same as GNU_HURD and SCO Unix */
 };
 
+#ifndef __KERNEL__
+
 struct partition {
 	unsigned char boot_ind;		/* 0x80 - active */
 	unsigned char head;		/* starting head */
@@ -55,7 +57,22 @@ struct partition {
 	unsigned int nr_sects;		/* nr of sectors in partition */
 } __attribute__((packed));
 
+#endif
+
 #ifdef __KERNEL__
+struct partition {
+	unsigned char boot_ind;		/* 0x80 - active */
+	unsigned char head;		/* starting head */
+	unsigned char sector;		/* starting sector */
+	unsigned char cyl;		/* starting cylinder */
+	unsigned char sys_ind;		/* What partition type */
+	unsigned char end_head;		/* end head */
+	unsigned char end_sector;	/* end sector */
+	unsigned char end_cyl;		/* end cylinder */
+	__le32 start_sect;	/* starting sector counting from 0 */
+	__le32 nr_sects;		/* nr of sectors in partition */
+} __attribute__((packed));
+
 struct hd_struct {
 	sector_t start_sect;
 	sector_t nr_sects;
@@ -100,7 +117,7 @@ struct gendisk {
 	struct timer_rand_state *random;
 	int policy;
 
-	unsigned sync_io;		/* RAID */
+	atomic_t sync_io;		/* RAID */
 	unsigned long stamp, stamp_idle;
 	int in_flight;
 #ifdef	CONFIG_SMP
@@ -218,19 +235,19 @@ static inline void set_capacity(struct gendisk *disk, sector_t size)
 #define SOLARIS_X86_VTOC_SANE	(0x600DDEEEUL)
 
 struct solaris_x86_slice {
-	ushort	s_tag;			/* ID tag of partition */
-	ushort	s_flag;			/* permission flags */
-	unsigned int s_start;		/* start sector no of partition */
-	unsigned int s_size;		/* # of blocks in partition */
+	__le16 s_tag;		/* ID tag of partition */
+	__le16 s_flag;		/* permission flags */
+	__le32 s_start;		/* start sector no of partition */
+	__le32 s_size;		/* # of blocks in partition */
 };
 
 struct solaris_x86_vtoc {
 	unsigned int v_bootinfo[3];	/* info needed by mboot (unsupported) */
-	unsigned int v_sanity;		/* to verify vtoc sanity */
-	unsigned int v_version;		/* layout version */
+	__le32 v_sanity;		/* to verify vtoc sanity */
+	__le32 v_version;		/* layout version */
 	char	v_volume[8];		/* volume name */
-	ushort	v_sectorsz;		/* sector size in bytes */
-	ushort	v_nparts;		/* number of partitions */
+	__le16	v_sectorsz;		/* sector size in bytes */
+	__le16	v_nparts;		/* number of partitions */
 	unsigned int v_reserved[10];	/* free space */
 	struct solaris_x86_slice
 		v_slice[SOLARIS_X86_NUMSLICE]; /* slice headers */
@@ -249,11 +266,11 @@ struct solaris_x86_vtoc {
 /* check against BSD src/sys/sys/disklabel.h for consistency */
 
 #define BSD_DISKMAGIC	(0x82564557UL)	/* The disk magic number */
-#define BSD_MAXPARTITIONS	8
+#define BSD_MAXPARTITIONS	16
 #define OPENBSD_MAXPARTITIONS	16
 #define BSD_FS_UNUSED		0	/* disklabel unused partition entry ID */
 struct bsd_disklabel {
-	__u32	d_magic;		/* the magic number */
+	__le32	d_magic;		/* the magic number */
 	__s16	d_type;			/* drive type */
 	__s16	d_subtype;		/* controller/d_type specific */
 	char	d_typename[16];		/* type name, e.g. "eagle" */
@@ -278,20 +295,20 @@ struct bsd_disklabel {
 	__u32	d_drivedata[NDDATA];	/* drive-type specific information */
 #define NSPARE 5
 	__u32	d_spare[NSPARE];	/* reserved for future use */
-	__u32	d_magic2;		/* the magic number (again) */
-	__u16	d_checksum;		/* xor of data incl. partitions */
+	__le32	d_magic2;		/* the magic number (again) */
+	__le16	d_checksum;		/* xor of data incl. partitions */
 
 			/* filesystem and partition information: */
-	__u16	d_npartitions;		/* number of partitions in following */
-	__u32	d_bbsize;		/* size of boot area at sn0, bytes */
-	__u32	d_sbsize;		/* max size of fs superblock, bytes */
+	__le16	d_npartitions;		/* number of partitions in following */
+	__le32	d_bbsize;		/* size of boot area at sn0, bytes */
+	__le32	d_sbsize;		/* max size of fs superblock, bytes */
 	struct	bsd_partition {		/* the partition table */
-		__u32	p_size;		/* number of sectors in partition */
-		__u32	p_offset;	/* starting sector */
-		__u32	p_fsize;	/* filesystem basic fragment size */
+		__le32	p_size;		/* number of sectors in partition */
+		__le32	p_offset;	/* starting sector */
+		__le32	p_fsize;	/* filesystem basic fragment size */
 		__u8	p_fstype;	/* filesystem type, see below */
 		__u8	p_frag;		/* filesystem fragments per block */
-		__u16	p_cpg;		/* filesystem cylinders per group */
+		__le16	p_cpg;		/* filesystem cylinders per group */
 	} d_partitions[BSD_MAXPARTITIONS];	/* actually may be more */
 };
 
@@ -309,40 +326,40 @@ struct bsd_disklabel {
 #define UNIXWARE_FS_UNUSED     0		/* Unused slice entry ID */
 
 struct unixware_slice {
-	__u16   s_label;	/* label */
-	__u16   s_flags;	/* permission flags */
-	__u32   start_sect;	/* starting sector */
-	__u32   nr_sects;	/* number of sectors in slice */
+	__le16   s_label;	/* label */
+	__le16   s_flags;	/* permission flags */
+	__le32   start_sect;	/* starting sector */
+	__le32   nr_sects;	/* number of sectors in slice */
 };
 
 struct unixware_disklabel {
-	__u32   d_type;               	/* drive type */
-	__u32   d_magic;                /* the magic number */
-	__u32   d_version;              /* version number */
+	__le32   d_type;               	/* drive type */
+	__le32   d_magic;                /* the magic number */
+	__le32   d_version;              /* version number */
 	char    d_serial[12];           /* serial number of the device */
-	__u32   d_ncylinders;           /* # of data cylinders per device */
-	__u32   d_ntracks;              /* # of tracks per cylinder */
-	__u32   d_nsectors;             /* # of data sectors per track */
-	__u32   d_secsize;              /* # of bytes per sector */
-	__u32   d_part_start;           /* # of first sector of this partition */
-	__u32   d_unknown1[12];         /* ? */
- 	__u32	d_alt_tbl;              /* byte offset of alternate table */
- 	__u32	d_alt_len;              /* byte length of alternate table */
- 	__u32	d_phys_cyl;             /* # of physical cylinders per device */
- 	__u32	d_phys_trk;             /* # of physical tracks per cylinder */
- 	__u32	d_phys_sec;             /* # of physical sectors per track */
- 	__u32	d_phys_bytes;           /* # of physical bytes per sector */
- 	__u32	d_unknown2;             /* ? */
-	__u32   d_unknown3;             /* ? */
-	__u32	d_pad[8];               /* pad */
+	__le32   d_ncylinders;           /* # of data cylinders per device */
+	__le32   d_ntracks;              /* # of tracks per cylinder */
+	__le32   d_nsectors;             /* # of data sectors per track */
+	__le32   d_secsize;              /* # of bytes per sector */
+	__le32   d_part_start;           /* # of first sector of this partition */
+	__le32   d_unknown1[12];         /* ? */
+ 	__le32	d_alt_tbl;              /* byte offset of alternate table */
+ 	__le32	d_alt_len;              /* byte length of alternate table */
+ 	__le32	d_phys_cyl;             /* # of physical cylinders per device */
+ 	__le32	d_phys_trk;             /* # of physical tracks per cylinder */
+ 	__le32	d_phys_sec;             /* # of physical sectors per track */
+ 	__le32	d_phys_bytes;           /* # of physical bytes per sector */
+ 	__le32	d_unknown2;             /* ? */
+	__le32   d_unknown3;             /* ? */
+	__le32	d_pad[8];               /* pad */
 
 	struct unixware_vtoc {
-		__u32	v_magic;		/* the magic number */
-		__u32	v_version;		/* version number */
+		__le32	v_magic;		/* the magic number */
+		__le32	v_version;		/* version number */
 		char	v_name[8];		/* volume name */
-		__u16	v_nslices;		/* # of slices */
-		__u16	v_unknown1;		/* ? */
-		__u32	v_reserved[10];		/* reserved */
+		__le16	v_nslices;		/* # of slices */
+		__le16	v_unknown1;		/* ? */
+		__le32	v_reserved[10];		/* reserved */
 		struct unixware_slice
 			v_slice[UNIXWARE_NUMSLICE];	/* slice headers */
 	} vtoc;
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 8980d1fd7..600f83c80 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -73,6 +73,11 @@ struct vm_area_struct;
  * For the normal case of non-DISCONTIGMEM systems the NODE_DATA() gets
  * optimized to &contig_page_data at compile-time.
  */
+
+#ifndef HAVE_ARCH_FREE_PAGE
+static inline void arch_free_page(struct page *page, int order) { }
+#endif
+
 extern struct page *
 FASTCALL(__alloc_pages(unsigned int, unsigned int, struct zonelist *));
 
diff --git a/include/linux/hdreg.h b/include/linux/hdreg.h
index 3d53bea7d..54ad63b1d 100644
--- a/include/linux/hdreg.h
+++ b/include/linux/hdreg.h
@@ -449,9 +449,8 @@ enum {
 /* hd/ide ctl's that pass (arg) ptrs to user space are numbered 0x033n/0x033n */
 /* 0x330 is reserved - used to be HDIO_GETGEO_BIG */
 /* 0x331 is reserved - used to be HDIO_GETGEO_BIG_RAW */
-
-#define HDIO_SET_IDE_SCSI      0x0338
-#define HDIO_SET_SCSI_IDE      0x0339
+/* 0x338 is reserved - used to be HDIO_SET_IDE_SCSI */
+/* 0x339 is reserved - used to be HDIO_SET_SCSI_IDE */
 
 #define __NEW_HD_DRIVE_ID
 
diff --git a/include/linux/hiddev.h b/include/linux/hiddev.h
index 75c1fa0d2..695423da4 100644
--- a/include/linux/hiddev.h
+++ b/include/linux/hiddev.h
@@ -128,10 +128,11 @@ struct hiddev_usage_ref {
 
 /* hiddev_usage_ref_multi is used for sending multiple bytes to a control.
  * It really manifests itself as setting the value of consecutive usages */
+#define HID_MAX_MULTI_USAGES 1024
 struct hiddev_usage_ref_multi {
 	struct hiddev_usage_ref uref;
 	__u32 num_values;
-	__s32 values[HID_MAX_USAGES];
+	__s32 values[HID_MAX_MULTI_USAGES];
 };
 
 /* FIELD_INDEX_NONE is returned in read() data from the kernel when flags
@@ -212,6 +213,11 @@ struct hiddev_usage_ref_multi {
  * In-kernel definitions.
  */
 
+struct hid_device;
+struct hid_usage;
+struct hid_field;
+struct hid_report;
+
 #ifdef CONFIG_USB_HIDDEV
 int hiddev_connect(struct hid_device *);
 void hiddev_disconnect(struct hid_device *);
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index 232d8fdb5..7153aef34 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -40,6 +40,8 @@ static inline void clear_user_highpage(struct page *page, unsigned long vaddr)
 	void *addr = kmap_atomic(page, KM_USER0);
 	clear_user_page(addr, vaddr, page);
 	kunmap_atomic(addr, KM_USER0);
+	/* Make sure this page is cleared on other CPU's too before using it */
+	smp_wmb();
 }
 
 static inline void clear_highpage(struct page *page)
@@ -73,6 +75,8 @@ static inline void copy_user_highpage(struct page *to, struct page *from, unsign
 	copy_user_page(vto, vfrom, vaddr, to);
 	kunmap_atomic(vfrom, KM_USER0);
 	kunmap_atomic(vto, KM_USER1);
+	/* Make sure this page is cleared on other CPU's too before using it */
+	smp_wmb();
 }
 
 static inline void copy_highpage(struct page *to, struct page *from)
diff --git a/include/linux/highuid.h b/include/linux/highuid.h
index 811cac9db..53ecac390 100644
--- a/include/linux/highuid.h
+++ b/include/linux/highuid.h
@@ -44,8 +44,8 @@ extern void __bad_gid(void);
 #ifdef CONFIG_UID16
 
 /* prevent uid mod 65536 effect by returning a default value for high UIDs */
-#define high2lowuid(uid) ((uid) > 65535 ? (old_uid_t)overflowuid : (old_uid_t)(uid))
-#define high2lowgid(gid) ((gid) > 65535 ? (old_gid_t)overflowgid : (old_gid_t)(gid))
+#define high2lowuid(uid) ((uid) & ~0xFFFF ? (old_uid_t)overflowuid : (old_uid_t)(uid))
+#define high2lowgid(gid) ((gid) & ~0xFFFF ? (old_gid_t)overflowgid : (old_gid_t)(gid))
 /*
  * -1 is different in 16 bits than it is in 32 bits
  * these macros are used by chown(), setreuid(), ...,
@@ -89,8 +89,8 @@ extern int fs_overflowgid;
  * Since these macros are used in architectures that only need limited
  * 16-bit UID back compatibility, we won't use old_uid_t and old_gid_t
  */
-#define fs_high2lowuid(uid) ((uid) > 65535 ? (uid16_t)fs_overflowuid : (uid16_t)(uid))
-#define fs_high2lowgid(gid) ((gid) > 65535 ? (gid16_t)fs_overflowgid : (gid16_t)(gid))
+#define fs_high2lowuid(uid) ((uid) & ~0xFFFF ? (uid16_t)fs_overflowuid : (uid16_t)(uid))
+#define fs_high2lowgid(gid) ((gid) & ~0xFFFF ? (gid16_t)fs_overflowgid : (gid16_t)(gid))
 
 #define low_16_bits(x)	((x) & 0xFFFF)
 #define high_16_bits(x)	(((x) & 0xFFFF0000) >> 16)
diff --git a/include/linux/hpet.h b/include/linux/hpet.h
index af4da7d30..142de4a93 100644
--- a/include/linux/hpet.h
+++ b/include/linux/hpet.h
@@ -1,6 +1,8 @@
 #ifndef	__HPET__
 #define	__HPET__ 1
 
+#include <linux/compiler.h>
+
 /*
  * Offsets into HPET Registers
  */
@@ -110,7 +112,7 @@ struct hpet_task {
 };
 
 struct hpet_data {
-	unsigned long hd_address;
+	void __iomem *hd_address;
 	unsigned short hd_nirqs;
 	unsigned short hd_flags;
 	unsigned int hd_state;	/* timer allocated */
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index 520fe7220..c75219a37 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -194,6 +194,7 @@
 #define I2C_ALGO_OCP    0x120000	/* IBM or otherwise On-chip I2C algorithm */
 #define I2C_ALGO_BITHS	0x130000	/* enhanced bit style adapters	*/
 #define I2C_ALGO_OCP_IOP3XX  0x140000	/* XSCALE IOP3XX On-chip I2C alg */
+#define I2C_ALGO_PCA	0x150000	/* PCA 9564 style adapters	*/
 
 #define I2C_ALGO_EXP	0x800000	/* experimental			*/
 
@@ -239,6 +240,9 @@
 #define I2C_HW_P_ISA	0x01	/* generic ISA Bus inteface card	*/
 #define I2C_HW_P_ELEK	0x02	/* Elektor ISA Bus inteface card	*/
 
+/* --- PCA 9564 based algorithms */
+#define I2C_HW_A_ISA	0x00	/* generic ISA Bus interface card	*/
+
 /* --- ACPI Embedded controller algorithms                              */
 #define I2C_HW_ACPI_EC          0x00
 
diff --git a/include/linux/i2c-vid.h b/include/linux/i2c-vid.h
index 86ed11781..62424092e 100644
--- a/include/linux/i2c-vid.h
+++ b/include/linux/i2c-vid.h
@@ -35,12 +35,15 @@
     to avoid floating point in the kernel.
 */
 
+int i2c_which_vrm(void);
+
 #define DEFAULT_VRM	82
 
 static inline int vid_from_reg(int val, int vrm)
 {
 	switch(vrm) {
-
+	case  0:
+		return 0;
 	case 91:		/* VRM 9.1 */
 	case 90:		/* VRM 9.0 */
 		return(val == 0x1f ? 0 :
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 0c3cf0e2f..caac24868 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -566,7 +566,9 @@ union i2c_smbus_data {
 
 #define I2C_CLIENT_MODULE_PARM(var,desc) \
   static unsigned short var[I2C_CLIENT_MAX_OPTS] = I2C_CLIENT_DEFAULTS; \
-  MODULE_PARM(var,I2C_CLIENT_MODPARM); \
+  static unsigned int var##_num; \
+  /*MODULE_PARM(var,I2C_CLIENT_MODPARM);*/ \
+  module_param_array(var, short, var##_num, 0); \
   MODULE_PARM_DESC(var,desc)
 
 /* This is the one you want to use in your own modules */
diff --git a/include/linux/i2o-dev.h b/include/linux/i2o-dev.h
index 9ef82bf1a..ef7f644dd 100644
--- a/include/linux/i2o-dev.h
+++ b/include/linux/i2o-dev.h
@@ -1,13 +1,13 @@
 /*
  * I2O user space accessible structures/APIs
- * 
+ *
  * (c) Copyright 1999, 2000 Red Hat Software
  *
- * 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 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 header file defines the I2O APIs that are available to both
@@ -23,7 +23,7 @@
 /* How many controllers are we allowing */
 #define MAX_I2O_CONTROLLERS	32
 
-#include <linux/ioctl.h>
+//#include <linux/ioctl.h>
 
 /*
  * I2O Control IOCTLs and structures
@@ -42,22 +42,25 @@
 #define I2OEVTREG		_IOW(I2O_MAGIC_NUMBER,10,struct i2o_evt_id)
 #define I2OEVTGET		_IOR(I2O_MAGIC_NUMBER,11,struct i2o_evt_info)
 #define I2OPASSTHRU		_IOR(I2O_MAGIC_NUMBER,12,struct i2o_cmd_passthru)
+#define I2OPASSTHRU32		_IOR(I2O_MAGIC_NUMBER,12,struct i2o_cmd_passthru32)
+
+struct i2o_cmd_passthru32 {
+	unsigned int iop;	/* IOP unit number */
+	u32 msg;		/* message */
+};
 
-struct i2o_cmd_passthru
-{
+struct i2o_cmd_passthru {
 	unsigned int iop;	/* IOP unit number */
 	void __user *msg;	/* message */
 };
 
-struct i2o_cmd_hrtlct
-{
+struct i2o_cmd_hrtlct {
 	unsigned int iop;	/* IOP unit number */
 	void __user *resbuf;	/* Buffer for result */
 	unsigned int __user *reslen;	/* Buffer length in bytes */
 };
 
-struct i2o_cmd_psetget
-{
+struct i2o_cmd_psetget {
 	unsigned int iop;	/* IOP unit number */
 	unsigned int tid;	/* Target device TID */
 	void __user *opbuf;	/* Operation List buffer */
@@ -66,8 +69,7 @@ struct i2o_cmd_psetget
 	unsigned int __user *reslen;	/* Result List buffer length in bytes */
 };
 
-struct i2o_sw_xfer
-{
+struct i2o_sw_xfer {
 	unsigned int iop;	/* IOP unit number */
 	unsigned char flags;	/* Flags field */
 	unsigned char sw_type;	/* Software type */
@@ -78,21 +80,19 @@ struct i2o_sw_xfer
 	unsigned int __user *curfrag;	/* Current fragment count */
 };
 
-struct i2o_html
-{
+struct i2o_html {
 	unsigned int iop;	/* IOP unit number */
 	unsigned int tid;	/* Target device ID */
 	unsigned int page;	/* HTML page */
-	void __user *resbuf;		/* Buffer for reply HTML page */
+	void __user *resbuf;	/* Buffer for reply HTML page */
 	unsigned int __user *reslen;	/* Length in bytes of reply buffer */
-	void __user *qbuf;		/* Pointer to HTTP query string */
+	void __user *qbuf;	/* Pointer to HTTP query string */
 	unsigned int qlen;	/* Length in bytes of query string buffer */
 };
 
 #define I2O_EVT_Q_LEN 32
 
-struct i2o_evt_id
-{
+struct i2o_evt_id {
 	unsigned int iop;
 	unsigned int tid;
 	unsigned int evt_mask;
@@ -101,21 +101,18 @@ struct i2o_evt_id
 /* Event data size = frame size - message header + evt indicator */
 #define I2O_EVT_DATA_SIZE 88
 
-struct i2o_evt_info
-{
+struct i2o_evt_info {
 	struct i2o_evt_id id;
 	unsigned char evt_data[I2O_EVT_DATA_SIZE];
 	unsigned int data_size;
 };
 
-struct i2o_evt_get
-{
+struct i2o_evt_get {
 	struct i2o_evt_info info;
 	int pending;
 	int lost;
 };
 
-
 /**************************************************************************
  * HRT related constants and structures
  **************************************************************************/
@@ -135,139 +132,127 @@ typedef unsigned char u8;
 typedef unsigned short u16;
 typedef unsigned int u32;
 
-#endif /* __KERNEL__ */
+#endif				/* __KERNEL__ */
 
-typedef struct _i2o_pci_bus
-{
-	u8	PciFunctionNumber;
-	u8	PciDeviceNumber;
-	u8	PciBusNumber;
-	u8	reserved;
-	u16	PciVendorID;
-	u16	PciDeviceID;
+typedef struct _i2o_pci_bus {
+	u8 PciFunctionNumber;
+	u8 PciDeviceNumber;
+	u8 PciBusNumber;
+	u8 reserved;
+	u16 PciVendorID;
+	u16 PciDeviceID;
 } i2o_pci_bus;
 
-typedef struct _i2o_local_bus
-{
-	u16	LbBaseIOPort;
-	u16	reserved;
-	u32	LbBaseMemoryAddress;
+typedef struct _i2o_local_bus {
+	u16 LbBaseIOPort;
+	u16 reserved;
+	u32 LbBaseMemoryAddress;
 } i2o_local_bus;
 
-typedef struct _i2o_isa_bus
-{
-	u16	IsaBaseIOPort;
-	u8	CSN;
-	u8	reserved;
-	u32	IsaBaseMemoryAddress;
+typedef struct _i2o_isa_bus {
+	u16 IsaBaseIOPort;
+	u8 CSN;
+	u8 reserved;
+	u32 IsaBaseMemoryAddress;
 } i2o_isa_bus;
 
-typedef struct _i2o_eisa_bus_info
-{
-	u16	EisaBaseIOPort;
-	u8	reserved;
-	u8	EisaSlotNumber;
-	u32	EisaBaseMemoryAddress;
+typedef struct _i2o_eisa_bus_info {
+	u16 EisaBaseIOPort;
+	u8 reserved;
+	u8 EisaSlotNumber;
+	u32 EisaBaseMemoryAddress;
 } i2o_eisa_bus;
 
-typedef struct _i2o_mca_bus
-{
-	u16	McaBaseIOPort;
-	u8	reserved;
-	u8	McaSlotNumber;
-	u32	McaBaseMemoryAddress;
+typedef struct _i2o_mca_bus {
+	u16 McaBaseIOPort;
+	u8 reserved;
+	u8 McaSlotNumber;
+	u32 McaBaseMemoryAddress;
 } i2o_mca_bus;
 
-typedef struct _i2o_other_bus
-{
+typedef struct _i2o_other_bus {
 	u16 BaseIOPort;
 	u16 reserved;
 	u32 BaseMemoryAddress;
 } i2o_other_bus;
 
-typedef struct _i2o_hrt_entry
-{
-	u32	adapter_id;
-	u32	parent_tid:12;
-	u32 	state:4;
-	u32	bus_num:8;
-	u32	bus_type:8;
-	union
-	{
-		i2o_pci_bus	pci_bus;
-		i2o_local_bus	local_bus;
-		i2o_isa_bus	isa_bus;
-		i2o_eisa_bus	eisa_bus;
-		i2o_mca_bus	mca_bus;
-		i2o_other_bus	other_bus;
+typedef struct _i2o_hrt_entry {
+	u32 adapter_id;
+	u32 parent_tid:12;
+	u32 state:4;
+	u32 bus_num:8;
+	u32 bus_type:8;
+	union {
+		i2o_pci_bus pci_bus;
+		i2o_local_bus local_bus;
+		i2o_isa_bus isa_bus;
+		i2o_eisa_bus eisa_bus;
+		i2o_mca_bus mca_bus;
+		i2o_other_bus other_bus;
 	} bus;
 } i2o_hrt_entry;
 
-typedef struct _i2o_hrt
-{
-	u16	num_entries;
-	u8	entry_len;
-	u8	hrt_version;
-	u32	change_ind;
+typedef struct _i2o_hrt {
+	u16 num_entries;
+	u8 entry_len;
+	u8 hrt_version;
+	u32 change_ind;
 	i2o_hrt_entry hrt_entry[1];
 } i2o_hrt;
 
-typedef struct _i2o_lct_entry
-{
-	u32	entry_size:16;
-	u32	tid:12;
-	u32	reserved:4;
-	u32	change_ind;
-	u32	device_flags;
-	u32	class_id:12;
-	u32	version:4;
-	u32	vendor_id:16;
-	u32	sub_class;
-	u32	user_tid:12;
-	u32	parent_tid:12;
-	u32	bios_info:8;
-	u8	identity_tag[8];
-	u32	event_capabilities;
+typedef struct _i2o_lct_entry {
+	u32 entry_size:16;
+	u32 tid:12;
+	u32 reserved:4;
+	u32 change_ind;
+	u32 device_flags;
+	u32 class_id:12;
+	u32 version:4;
+	u32 vendor_id:16;
+	u32 sub_class;
+	u32 user_tid:12;
+	u32 parent_tid:12;
+	u32 bios_info:8;
+	u8 identity_tag[8];
+	u32 event_capabilities;
 } i2o_lct_entry;
 
-typedef struct _i2o_lct
-{
-	u32	table_size:16;
-	u32	boot_tid:12;
-	u32	lct_ver:4;
-	u32	iop_flags;
-	u32	change_ind;
+typedef struct _i2o_lct {
+	u32 table_size:16;
+	u32 boot_tid:12;
+	u32 lct_ver:4;
+	u32 iop_flags;
+	u32 change_ind;
 	i2o_lct_entry lct_entry[1];
 } i2o_lct;
 
-typedef struct _i2o_status_block
-{
-	u16	org_id;
-	u16	reserved;
-	u16	iop_id:12;
-	u16	reserved1:4;
-	u16	host_unit_id;
-	u16	segment_number:12;
-	u16	i2o_version:4;
-	u8	iop_state;
-	u8	msg_type;
-	u16	inbound_frame_size;
-	u8	init_code;
-	u8	reserved2;
-	u32	max_inbound_frames;
-	u32	cur_inbound_frames;
-	u32	max_outbound_frames;
-	char	product_id[24];
-	u32	expected_lct_size;
-	u32	iop_capabilities;
-	u32	desired_mem_size;
-	u32	current_mem_size;
-	u32	current_mem_base;
-	u32	desired_io_size;
-	u32	current_io_size;
-	u32	current_io_base;
-	u32	reserved3:24;
-	u32	cmd_status:8;
+typedef struct _i2o_status_block {
+	u16 org_id;
+	u16 reserved;
+	u16 iop_id:12;
+	u16 reserved1:4;
+	u16 host_unit_id;
+	u16 segment_number:12;
+	u16 i2o_version:4;
+	u8 iop_state;
+	u8 msg_type;
+	u16 inbound_frame_size;
+	u8 init_code;
+	u8 reserved2;
+	u32 max_inbound_frames;
+	u32 cur_inbound_frames;
+	u32 max_outbound_frames;
+	char product_id[24];
+	u32 expected_lct_size;
+	u32 iop_capabilities;
+	u32 desired_mem_size;
+	u32 current_mem_size;
+	u32 current_mem_base;
+	u32 desired_io_size;
+	u32 current_io_size;
+	u32 current_io_base;
+	u32 reserved3:24;
+	u32 cmd_status:8;
 } i2o_status_block;
 
 /* Event indicator mask flags */
@@ -351,14 +336,15 @@ typedef struct _i2o_status_block
 #define I2O_CLASS_BUS_ADAPTER_PORT		0x080
 #define I2O_CLASS_PEER_TRANSPORT_AGENT		0x090
 #define I2O_CLASS_PEER_TRANSPORT		0x091
+#define	I2O_CLASS_END				0xfff
 
-/* 
+/*
  *  Rest of 0x092 - 0x09f reserved for peer-to-peer classes
  */
 
 #define I2O_CLASS_MATCH_ANYCLASS		0xffffffff
 
-/* 
+/*
  *  Subclasses
  */
 
@@ -380,7 +366,7 @@ typedef struct _i2o_status_block
 #define I2O_PARAMS_TABLE_CLEAR			0x000A
 
 /*
- * I2O serial number conventions / formats 
+ * I2O serial number conventions / formats
  * (circa v1.5)
  */
 
@@ -391,7 +377,7 @@ typedef struct _i2o_status_block
 #define I2O_SNFORMAT_LAN48_MAC			4
 #define I2O_SNFORMAT_WAN			5
 
-/* 
+/*
  * Plus new in v2.0 (Yellowstone pdf doc)
  */
 
@@ -402,7 +388,7 @@ typedef struct _i2o_status_block
 #define I2O_SNFORMAT_UNKNOWN2			0xff
 
 /*
- *	I2O Get Status State values 
+ *	I2O Get Status State values
  */
 
 #define ADAPTER_STATE_INITIALIZING		0x01
@@ -413,4 +399,4 @@ typedef struct _i2o_status_block
 #define ADAPTER_STATE_FAILED			0x10
 #define ADAPTER_STATE_FAULTED			0x11
 
-#endif /* _I2O_DEV_H */
+#endif				/* _I2O_DEV_H */
diff --git a/include/linux/i2o.h b/include/linux/i2o.h
index 9104dd403..a68437640 100644
--- a/include/linux/i2o.h
+++ b/include/linux/i2o.h
@@ -1,16 +1,16 @@
 /*
  * I2O kernel space accessible structures/APIs
- * 
+ *
  * (c) Copyright 1999, 2000 Red Hat Software
  *
- * 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 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 header file defined the I2O APIs/structures for use by 
+ * This header file defined the I2O APIs/structures for use by
  * the I2O kernel modules.
  *
  */
@@ -18,309 +18,586 @@
 #ifndef _I2O_H
 #define _I2O_H
 
-#ifdef __KERNEL__ /* This file to be included by kernel only */
+#ifdef __KERNEL__		/* This file to be included by kernel only */
 
 #include <linux/i2o-dev.h>
 
 /* How many different OSM's are we allowing */
-#define MAX_I2O_MODULES		4
-
-/* How many OSMs can register themselves for device status updates? */
-#define I2O_MAX_MANAGERS	4
+#define I2O_MAX_DRIVERS		4
 
+#include <asm/io.h>
 #include <asm/semaphore.h>	/* Needed for MUTEX init macros */
-#include <linux/config.h>
-#include <linux/notifier.h>
-#include <asm/atomic.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+
+/* message queue empty */
+#define I2O_QUEUE_EMPTY		0xffffffff
 
 /*
  *	Message structures
  */
-struct i2o_message
-{
-	u8	version_offset;
-	u8	flags;
-	u16	size;
-	u32	target_tid:12;
-	u32	init_tid:12;
-	u32	function:8;
-	u32	initiator_context;
+struct i2o_message {
+	union {
+		struct {
+			u8 version_offset;
+			u8 flags;
+			u16 size;
+			u32 target_tid:12;
+			u32 init_tid:12;
+			u32 function:8;
+			u32 icntxt;	/* initiator context */
+			u32 tcntxt;	/* transaction context */
+		} s;
+		u32 head[4];
+	} u;
 	/* List follows */
+	u32 body[0];
 };
 
 /*
- *	Each I2O device entity has one or more of these. There is one
- *	per device.
+ *	Each I2O device entity has one of these. There is one per device.
  */
-struct i2o_device
-{
-	i2o_lct_entry lct_data;		/* Device LCT information */
-	u32 flags;
-	int i2oversion;			/* I2O version supported. Actually
-					 * there should be high and low
-					 * version */
+struct i2o_device {
+	i2o_lct_entry lct_data;	/* Device LCT information */
 
-	struct proc_dir_entry *proc_entry;	/* /proc dir */
+	struct i2o_controller *iop;	/* Controlling IOP */
+	struct list_head list;	/* node in IOP devices list */
+
+	struct device device;
+
+	struct semaphore lock;	/* device lock */
+
+	struct class_device classdev;	/* i2o device class */
+};
+
+/*
+ *	Event structure provided to the event handling function
+ */
+struct i2o_event {
+	struct work_struct work;
+	struct i2o_device *i2o_dev;	/* I2O device pointer from which the
+					   event reply was initiated */
+	u16 size;		/* Size of data in 32-bit words */
+	u32 tcntxt;		/* Transaction context used at
+				   registration */
+	u32 event_indicator;	/* Event indicator from reply */
+	u32 data[0];		/* Event data from reply */
+};
+
+/*
+ *	I2O classes which could be handled by the OSM
+ */
+struct i2o_class_id {
+	u16 class_id:12;
+};
+
+/*
+ *	I2O driver structure for OSMs
+ */
+struct i2o_driver {
+	char *name;		/* OSM name */
+	int context;		/* Low 8 bits of the transaction info */
+	struct i2o_class_id *classes;	/* I2O classes that this OSM handles */
+
+	/* Message reply handler */
+	int (*reply) (struct i2o_controller *, u32, struct i2o_message *);
+
+	/* Event handler */
+	void (*event) (struct i2o_event *);
+
+	struct workqueue_struct *event_queue;	/* Event queue */
+
+	struct device_driver driver;
 
-	/* Primary user */
-	struct i2o_handler *owner;
+	/* notification of changes */
+	void (*notify_controller_add) (struct i2o_controller *);
+	void (*notify_controller_remove) (struct i2o_controller *);
+	void (*notify_device_add) (struct i2o_device *);
+	void (*notify_device_remove) (struct i2o_device *);
 
-	/* Management users */
-	struct i2o_handler *managers[I2O_MAX_MANAGERS];
-	int num_managers;
+	struct semaphore lock;
+};
 
-	struct i2o_controller *controller;	/* Controlling IOP */
-	struct i2o_device *next;	/* Chain */
-	struct i2o_device *prev;
-	char dev_name[8];		/* linux /dev name if available */
+/*
+ *	Contains all information which are necessary for DMA operations
+ */
+struct i2o_dma {
+	void *virt;
+	dma_addr_t phys;
+	u32 len;
 };
 
 /*
- * context queue entry, used for 32-bit context on 64-bit systems
+ *	Context queue entry, used for 32-bit context on 64-bit systems
  */
 struct i2o_context_list_element {
-	struct i2o_context_list_element *next;
+	struct list_head list;
 	u32 context;
 	void *ptr;
-	unsigned int flags;
+	unsigned long timestamp;
 };
 
 /*
  * Each I2O controller has one of these objects
  */
-struct i2o_controller
-{
+struct i2o_controller {
 	char name[16];
 	int unit;
 	int type;
-	int enabled;
-	
-	struct pci_dev *pdev;		/* PCI device */
-	int		irq;
-	int		short_req:1;	/* Use small block sizes        */
-	int		dpt:1;		/* Don't quiesce                */
-	int		raptor:1;	/* split bar                    */
-	int		promise:1;	/* Promise controller		*/
+
+	struct pci_dev *pdev;	/* PCI device */
+
+	int short_req:1;	/* use small block sizes */
+	int no_quiesce:1;	/* dont quiesce before reset */
+	int raptor:1;		/* split bar */
+	int promise:1;		/* Promise controller */
+
 #ifdef CONFIG_MTRR
-	int		mtrr_reg0;
-	int		mtrr_reg1;
+	int mtrr_reg0;
+	int mtrr_reg1;
 #endif
 
+	struct list_head devices;	/* list of I2O devices */
+
 	struct notifier_block *event_notifer;	/* Events */
 	atomic_t users;
-	struct i2o_device *devices;		/* I2O device chain */
-	struct i2o_controller *next;		/* Controller chain */
-	void *post_port;			/* Inbout port address */
-	void *reply_port;			/* Outbound port address */
-	void *irq_mask;				/* Interrupt register address */
+	struct list_head list;	/* Controller list */
+	void *post_port;	/* Inbout port address */
+	void *reply_port;	/* Outbound port address */
+	void *irq_mask;		/* Interrupt register address */
 
 	/* Dynamic LCT related data */
-	struct semaphore lct_sem;
-	int lct_pid;
-	int lct_running;
 
-	i2o_status_block *status_block;		/* IOP status block */
-	dma_addr_t status_block_phys;
-	i2o_lct *lct;				/* Logical Config Table */
-	dma_addr_t lct_phys;
-	i2o_lct *dlct;				/* Temp LCT */
-	dma_addr_t dlct_phys;
-	i2o_hrt *hrt;				/* HW Resource Table */
-	dma_addr_t hrt_phys;
-	u32 hrt_len;
+	struct i2o_dma status;	/* status of IOP */
 
-	void *base_virt;			/* base virtual address */
-	unsigned long base_phys;		/* base physical address */
+	struct i2o_dma hrt;	/* HW Resource Table */
+	i2o_lct *lct;		/* Logical Config Table */
+	struct i2o_dma dlct;	/* Temp LCT */
+	struct semaphore lct_lock;	/* Lock for LCT updates */
+	struct i2o_dma status_block;	/* IOP status block */
 
-	void *msg_virt;				/* messages virtual address */
-	unsigned long msg_phys;			/* messages physical address */
+	struct i2o_dma base;	/* controller messaging unit */
+	struct i2o_dma in_queue;	/* inbound message queue Host->IOP */
+	struct i2o_dma out_queue;	/* outbound message queue IOP->Host */
 
-	int battery:1;				/* Has a battery backup */
-	int io_alloc:1;				/* An I/O resource was allocated */
-	int mem_alloc:1;			/* A memory resource was allocated */
+	int battery:1;		/* Has a battery backup */
+	int io_alloc:1;		/* An I/O resource was allocated */
+	int mem_alloc:1;	/* A memory resource was allocated */
 
-	struct resource io_resource;		/* I/O resource allocated to the IOP */
-	struct resource mem_resource;		/* Mem resource allocated to the IOP */
+	struct resource io_resource;	/* I/O resource allocated to the IOP */
+	struct resource mem_resource;	/* Mem resource allocated to the IOP */
 
 	struct proc_dir_entry *proc_entry;	/* /proc dir */
 
-
-	void *page_frame;			/* Message buffers */
-	dma_addr_t page_frame_map;		/* Cache map */
+	struct list_head bus_list;	/* list of busses on IOP */
+	struct device device;
+	struct i2o_device *exec;	/* Executive */
 #if BITS_PER_LONG == 64
-	spinlock_t context_list_lock;		/* lock for context_list */
-	struct i2o_context_list_element *context_list; /* list of context id's
-						    and pointers */
+	spinlock_t context_list_lock;	/* lock for context_list */
+	atomic_t context_list_counter;	/* needed for unique contexts */
+	struct list_head context_list;	/* list of context id's
+					   and pointers */
 #endif
+	spinlock_t lock;	/* lock for controller
+				   configuration */
+
+	void *driver_data[I2O_MAX_DRIVERS];	/* storage for drivers */
 };
 
 /*
- * OSM resgistration block
+ * I2O System table entry
  *
- * Each OSM creates at least one of these and registers it with the
- * I2O core through i2o_register_handler.  An OSM may want to
- * register more than one if it wants a fast path to a reply
- * handler by having a separate initiator context for each 
- * class function.
+ * The system table contains information about all the IOPs in the
+ * system.  It is sent to all IOPs so that they can create peer2peer
+ * connections between them.
  */
-struct i2o_handler
+struct i2o_sys_tbl_entry {
+	u16 org_id;
+	u16 reserved1;
+	u32 iop_id:12;
+	u32 reserved2:20;
+	u16 seg_num:12;
+	u16 i2o_version:4;
+	u8 iop_state;
+	u8 msg_type;
+	u16 frame_size;
+	u16 reserved3;
+	u32 last_changed;
+	u32 iop_capabilities;
+	u32 inbound_low;
+	u32 inbound_high;
+};
+
+struct i2o_sys_tbl {
+	u8 num_entries;
+	u8 version;
+	u16 reserved1;
+	u32 change_ind;
+	u32 reserved2;
+	u32 reserved3;
+	struct i2o_sys_tbl_entry iops[0];
+};
+
+extern struct list_head i2o_controllers;
+
+/* Message functions */
+static inline u32 i2o_msg_get(struct i2o_controller *, struct i2o_message **);
+extern u32 i2o_msg_get_wait(struct i2o_controller *, struct i2o_message **,
+			    int);
+static inline void i2o_msg_post(struct i2o_controller *, u32);
+static inline int i2o_msg_post_wait(struct i2o_controller *, u32,
+				    unsigned long);
+extern int i2o_msg_post_wait_mem(struct i2o_controller *, u32, unsigned long,
+				 struct i2o_dma *);
+extern void i2o_msg_nop(struct i2o_controller *, u32);
+static inline void i2o_flush_reply(struct i2o_controller *, u32);
+
+/* DMA handling functions */
+static inline int i2o_dma_alloc(struct device *, struct i2o_dma *, size_t,
+				unsigned int);
+static inline void i2o_dma_free(struct device *, struct i2o_dma *);
+int i2o_dma_realloc(struct device *, struct i2o_dma *, size_t, unsigned int);
+
+static inline int i2o_dma_map(struct device *, struct i2o_dma *);
+static inline void i2o_dma_unmap(struct device *, struct i2o_dma *);
+
+/* IOP functions */
+extern int i2o_status_get(struct i2o_controller *);
+extern int i2o_hrt_get(struct i2o_controller *);
+
+extern int i2o_event_register(struct i2o_device *, struct i2o_driver *, int,
+			      u32);
+extern struct i2o_device *i2o_iop_find_device(struct i2o_controller *, u16);
+extern struct i2o_controller *i2o_find_iop(int);
+
+/* Functions needed for handling 64-bit pointers in 32-bit context */
+#if BITS_PER_LONG == 64
+extern u32 i2o_cntxt_list_add(struct i2o_controller *, void *);
+extern void *i2o_cntxt_list_get(struct i2o_controller *, u32);
+extern u32 i2o_cntxt_list_remove(struct i2o_controller *, void *);
+extern u32 i2o_cntxt_list_get_ptr(struct i2o_controller *, void *);
+
+static inline u32 i2o_ptr_low(void *ptr)
 {
-	/* Message reply handler */
-	void (*reply)(struct i2o_handler *, struct i2o_controller *,
-		      struct i2o_message *);
+	return (u32) (u64) ptr;
+};
 
-	/* New device notification handler */
-	void (*new_dev_notify)(struct i2o_controller *, struct i2o_device *);
+static inline u32 i2o_ptr_high(void *ptr)
+{
+	return (u32) ((u64) ptr >> 32);
+};
+#else
+static inline u32 i2o_cntxt_list_add(struct i2o_controller *c, void *ptr)
+{
+	return (u32) ptr;
+};
 
-	/* Device deltion handler */
-	void (*dev_del_notify)(struct i2o_controller *, struct i2o_device *);
+static inline void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context)
+{
+	return (void *)context;
+};
 
-	/* Reboot notification handler */
-	void (*reboot_notify)(void);
+static inline u32 i2o_cntxt_list_remove(struct i2o_controller *c, void *ptr)
+{
+	return (u32) ptr;
+};
 
-	char *name;		/* OSM name */
-	int context;		/* Low 8 bits of the transaction info */
-	u32 class;		/* I2O classes that this driver handles */
-	/* User data follows */
+static inline u32 i2o_cntxt_list_get_ptr(struct i2o_controller *c, void *ptr)
+{
+	return (u32) ptr;
 };
 
-#ifdef MODULE
-/*
- * Used by bus specific modules to communicate with the core
+static inline u32 i2o_ptr_low(void *ptr)
+{
+	return (u32) ptr;
+};
+
+static inline u32 i2o_ptr_high(void *ptr)
+{
+	return 0;
+};
+#endif
+
+/* I2O driver (OSM) functions */
+extern int i2o_driver_register(struct i2o_driver *);
+extern void i2o_driver_unregister(struct i2o_driver *);
+
+/**
+ *	i2o_driver_notify_controller_add - Send notification of added controller
+ *					   to a single I2O driver
  *
- * This is needed because the bus modules cannot make direct
- * calls to the core as this results in the i2o_bus_specific_module
- * being dependent on the core, not the otherway around.
- * In that case, a 'modprobe i2o_lan' loads i2o_core & i2o_lan,
- * but _not_ i2o_pci...which makes the whole thing pretty useless :)
+ *	Send notification of added controller to a single registered driver.
+ */
+static inline void i2o_driver_notify_controller_add(struct i2o_driver *drv,
+						    struct i2o_controller *c)
+{
+	if (drv->notify_controller_add)
+		drv->notify_controller_add(c);
+};
+
+/**
+ *	i2o_driver_notify_controller_remove - Send notification of removed
+ *					      controller to a single I2O driver
  *
+ *	Send notification of removed controller to a single registered driver.
  */
-struct i2o_core_func_table
+static inline void i2o_driver_notify_controller_remove(struct i2o_driver *drv,
+						       struct i2o_controller *c)
 {
-	int	(*install)(struct i2o_controller *);
-	int	(*activate)(struct i2o_controller *);
-	struct i2o_controller *(*find)(int);
-	void	(*unlock)(struct i2o_controller *);
-	void	(*run_queue)(struct i2o_controller * c);
-	int	(*delete)(struct i2o_controller *);
+	if (drv->notify_controller_remove)
+		drv->notify_controller_remove(c);
 };
-#endif /* MODULE */
 
-/*
- * I2O System table entry
+/**
+ *	i2o_driver_notify_device_add - Send notification of added device to a
+ *				       single I2O driver
  *
- * The system table contains information about all the IOPs in the
- * system.  It is sent to all IOPs so that they can create peer2peer
- * connections between them.
+ *	Send notification of added device to a single registered driver.
  */
-struct i2o_sys_tbl_entry
+static inline void i2o_driver_notify_device_add(struct i2o_driver *drv,
+						struct i2o_device *i2o_dev)
 {
-	u16	org_id;
-	u16	reserved1;
-	u32	iop_id:12;
-	u32	reserved2:20;
-	u16	seg_num:12;
-	u16	i2o_version:4;
-	u8	iop_state;
-	u8	msg_type;
-	u16	frame_size;
-	u16	reserved3;
-	u32	last_changed;
-	u32	iop_capabilities;
-	u32	inbound_low;
-	u32	inbound_high;
-};
-
-struct i2o_sys_tbl
+	if (drv->notify_device_add)
+		drv->notify_device_add(i2o_dev);
+};
+
+/**
+ *	i2o_driver_notify_device_remove - Send notification of removed device
+ *					  to a single I2O driver
+ *
+ *	Send notification of removed device to a single registered driver.
+ */
+static inline void i2o_driver_notify_device_remove(struct i2o_driver *drv,
+						   struct i2o_device *i2o_dev)
 {
-	u8	num_entries;
-	u8	version;
-	u16	reserved1;
-	u32	change_ind;
-	u32	reserved2;
-	u32	reserved3;
-	struct i2o_sys_tbl_entry iops[0];
+	if (drv->notify_device_remove)
+		drv->notify_device_remove(i2o_dev);
 };
 
+extern void i2o_driver_notify_controller_add_all(struct i2o_controller *);
+extern void i2o_driver_notify_controller_remove_all(struct i2o_controller *);
+extern void i2o_driver_notify_device_add_all(struct i2o_device *);
+extern void i2o_driver_notify_device_remove_all(struct i2o_device *);
+
+/* I2O device functions */
+extern int i2o_device_claim(struct i2o_device *);
+extern int i2o_device_claim_release(struct i2o_device *);
+
+/* Exec OSM functions */
+extern int i2o_exec_lct_get(struct i2o_controller *);
+extern int i2o_exec_lct_notify(struct i2o_controller *, u32);
+
+/* device to i2o_device and driver to i2o_driver convertion functions */
+#define to_i2o_driver(drv) container_of(drv,struct i2o_driver, driver)
+#define to_i2o_device(dev) container_of(dev, struct i2o_device, device)
+
 /*
  *	Messenger inlines
  */
 static inline u32 I2O_POST_READ32(struct i2o_controller *c)
 {
+	rmb();
 	return readl(c->post_port);
-}
+};
 
 static inline void I2O_POST_WRITE32(struct i2o_controller *c, u32 val)
 {
+	wmb();
 	writel(val, c->post_port);
-}
-
+};
 
 static inline u32 I2O_REPLY_READ32(struct i2o_controller *c)
 {
+	rmb();
 	return readl(c->reply_port);
-}
+};
 
 static inline void I2O_REPLY_WRITE32(struct i2o_controller *c, u32 val)
 {
+	wmb();
 	writel(val, c->reply_port);
-}
-
+};
 
 static inline u32 I2O_IRQ_READ32(struct i2o_controller *c)
 {
+	rmb();
 	return readl(c->irq_mask);
-}
+};
 
 static inline void I2O_IRQ_WRITE32(struct i2o_controller *c, u32 val)
 {
+	wmb();
 	writel(val, c->irq_mask);
-}
+	wmb();
+};
 
+/**
+ *	i2o_msg_get - obtain an I2O message from the IOP
+ *	@c: I2O controller
+ *	@msg: pointer to a I2O message pointer
+ *
+ *	This function tries to get a message slot. If no message slot is
+ *	available do not wait until one is availabe (see also i2o_msg_get_wait).
+ *
+ *	On a success the message is returned and the pointer to the message is
+ *	set in msg. The returned message is the physical page frame offset
+ *	address from the read port (see the i2o spec). If no message is
+ *	available returns I2O_QUEUE_EMPTY and msg is leaved untouched.
+ */
+static inline u32 i2o_msg_get(struct i2o_controller *c,
+			      struct i2o_message **msg)
+{
+	u32 m;
 
-static inline void i2o_post_message(struct i2o_controller *c, u32 m)
+	if ((m = I2O_POST_READ32(c)) != I2O_QUEUE_EMPTY)
+		*msg = c->in_queue.virt + m;
+
+	return m;
+};
+
+/**
+ *	i2o_msg_post - Post I2O message to I2O controller
+ *	@c: I2O controller to which the message should be send
+ *	@m: the message identifier
+ *
+ *	Post the message to the I2O controller.
+ */
+static inline void i2o_msg_post(struct i2o_controller *c, u32 m)
 {
-	/* The second line isnt spurious - thats forcing PCI posting */
 	I2O_POST_WRITE32(c, m);
-	(void) I2O_IRQ_READ32(c);
-}
+};
 
+/**
+ * 	i2o_msg_post_wait - Post and wait a message and wait until return
+ *	@c: controller
+ *	@m: message to post
+ *	@timeout: time in seconds to wait
+ *
+ * 	This API allows an OSM to post a message and then be told whether or
+ *	not the system received a successful reply. If the message times out
+ *	then the value '-ETIMEDOUT' is returned.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static inline int i2o_msg_post_wait(struct i2o_controller *c, u32 m,
+				    unsigned long timeout)
+{
+	return i2o_msg_post_wait_mem(c, m, timeout, NULL);
+};
+
+/**
+ *	i2o_flush_reply - Flush reply from I2O controller
+ *	@c: I2O controller
+ *	@m: the message identifier
+ *
+ *	The I2O controller must be informed that the reply message is not needed
+ *	anymore. If you forget to flush the reply, the message frame can't be
+ *	used by the controller anymore and is therefore lost.
+ *
+ *	FIXME: is there a timeout after which the controller reuse the message?
+ */
 static inline void i2o_flush_reply(struct i2o_controller *c, u32 m)
 {
 	I2O_REPLY_WRITE32(c, m);
-}
+};
 
-/*
- *	Endian handling wrapped into the macro - keeps the core code
- *	cleaner.
+/**
+ *	i2o_dma_alloc - Allocate DMA memory
+ *	@dev: struct device pointer to the PCI device of the I2O controller
+ *	@addr: i2o_dma struct which should get the DMA buffer
+ *	@len: length of the new DMA memory
+ *	@gfp_mask: GFP mask
+ *
+ *	Allocate a coherent DMA memory and write the pointers into addr.
+ *
+ *	Returns 0 on success or -ENOMEM on failure.
  */
- 
-#define i2o_raw_writel(val, mem)	__raw_writel(cpu_to_le32(val), mem)
+static inline int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr,
+				size_t len, unsigned int gfp_mask)
+{
+	addr->virt = dma_alloc_coherent(dev, len, &addr->phys, gfp_mask);
+	if (!addr->virt)
+		return -ENOMEM;
 
-extern struct i2o_controller *i2o_find_controller(int);
-extern void i2o_unlock_controller(struct i2o_controller *);
-extern struct i2o_controller *i2o_controller_chain;
-extern int i2o_num_controllers;
-extern int i2o_status_get(struct i2o_controller *);
+	memset(addr->virt, 0, len);
+	addr->len = len;
+
+	return 0;
+};
+
+/**
+ *	i2o_dma_free - Free DMA memory
+ *	@dev: struct device pointer to the PCI device of the I2O controller
+ *	@addr: i2o_dma struct which contains the DMA buffer
+ *
+ *	Free a coherent DMA memory and set virtual address of addr to NULL.
+ */
+static inline void i2o_dma_free(struct device *dev, struct i2o_dma *addr)
+{
+	if (addr->virt) {
+		if (addr->phys)
+			dma_free_coherent(dev, addr->len, addr->virt,
+					  addr->phys);
+		else
+			kfree(addr->virt);
+		addr->virt = NULL;
+	}
+};
 
-extern int i2o_install_handler(struct i2o_handler *);
-extern int i2o_remove_handler(struct i2o_handler *);
+/**
+ *	i2o_dma_map - Map the memory to DMA
+ *	@dev: struct device pointer to the PCI device of the I2O controller
+ *	@addr: i2o_dma struct which should be mapped
+ *
+ *	Map the memory in addr->virt to coherent DMA memory and write the
+ *	physical address into addr->phys.
+ *
+ *	Returns 0 on success or -ENOMEM on failure.
+ */
+static inline int i2o_dma_map(struct device *dev, struct i2o_dma *addr)
+{
+	if (!addr->virt)
+		return -EFAULT;
 
-extern int i2o_claim_device(struct i2o_device *, struct i2o_handler *);
-extern int i2o_release_device(struct i2o_device *, struct i2o_handler *);
-extern int i2o_device_notify_on(struct i2o_device *, struct i2o_handler *);
-extern int i2o_device_notify_off(struct i2o_device *,
-				 struct i2o_handler *);
+	if (!addr->phys)
+		addr->phys = dma_map_single(dev, addr->virt, addr->len,
+					    DMA_BIDIRECTIONAL);
+	if (!addr->phys)
+		return -ENOMEM;
 
-extern int i2o_post_this(struct i2o_controller *, u32 *, int);
-extern int i2o_post_wait(struct i2o_controller *, u32 *, int, int);
-extern int i2o_post_wait_mem(struct i2o_controller *, u32 *, int, int,
-			     void *, void *, dma_addr_t, dma_addr_t, int, int);
+	return 0;
+};
 
-extern int i2o_query_scalar(struct i2o_controller *, int, int, int, void *,
-			    int);
-extern int i2o_set_scalar(struct i2o_controller *, int, int, int, void *,
-			  int);
+/**
+ *	i2o_dma_unmap - Unmap the DMA memory
+ *	@dev: struct device pointer to the PCI device of the I2O controller
+ *	@addr: i2o_dma struct which should be unmapped
+ *
+ *	Unmap the memory in addr->virt from DMA memory.
+ */
+static inline void i2o_dma_unmap(struct device *dev, struct i2o_dma *addr)
+{
+	if (!addr->virt)
+		return;
+
+	if (addr->phys) {
+		dma_unmap_single(dev, addr->phys, addr->len, DMA_BIDIRECTIONAL);
+		addr->phys = 0;
+	}
+};
+
+/*
+ *	Endian handling wrapped into the macro - keeps the core code
+ *	cleaner.
+ */
+
+#define i2o_raw_writel(val, mem)	__raw_writel(cpu_to_le32(val), mem)
+
+extern int i2o_parm_field_get(struct i2o_device *, int, int, void *, int);
+extern int i2o_parm_field_set(struct i2o_device *, int, int, void *, int);
+extern int i2o_parm_table_get(struct i2o_device *, int, int, int, void *, int,
+			      void *, int);
+/* FIXME: remove
 extern int i2o_query_table(int, struct i2o_controller *, int, int, int,
 			   void *, int, void *, int);
 extern int i2o_clear_table(struct i2o_controller *, int, int);
@@ -328,51 +605,24 @@ extern int i2o_row_add_table(struct i2o_controller *, int, int, int,
 			     void *, int);
 extern int i2o_issue_params(int, struct i2o_controller *, int, void *, int,
 			    void *, int);
+*/
 
-extern int i2o_event_register(struct i2o_controller *, u32, u32, u32, u32);
-extern int i2o_event_ack(struct i2o_controller *, u32 *);
-
-extern void i2o_report_status(const char *, const char *, u32 *);
-extern void i2o_dump_message(u32 *);
-extern const char *i2o_get_class_name(int);
-
-extern int i2o_install_controller(struct i2o_controller *);
-extern int i2o_activate_controller(struct i2o_controller *);
-extern void i2o_run_queue(struct i2o_controller *);
-extern int i2o_delete_controller(struct i2o_controller *);
-
-#if BITS_PER_LONG == 64
-extern u32 i2o_context_list_add(void *, struct i2o_controller *);
-extern void *i2o_context_list_get(u32, struct i2o_controller *);
-extern u32 i2o_context_list_remove(void *, struct i2o_controller *);
-#else
-static inline u32 i2o_context_list_add(void *ptr, struct i2o_controller *c)
-{
-	return (u32)ptr;
-}
-
-static inline void *i2o_context_list_get(u32 context, struct i2o_controller *c)
-{
-	return (void *)context;
-}
-
-static inline u32 i2o_context_list_remove(void *ptr, struct i2o_controller *c)
-{
-	return (u32)ptr;
-}
-#endif
+/* debugging functions */
+extern void i2o_report_status(const char *, const char *, struct i2o_message *);
+extern void i2o_dump_message(struct i2o_message *);
+extern void i2o_dump_hrt(struct i2o_controller *c);
+extern void i2o_debug_state(struct i2o_controller *c);
 
 /*
  *	Cache strategies
  */
- 
- 
+
 /*	The NULL strategy leaves everything up to the controller. This tends to be a
  *	pessimal but functional choice.
  */
 #define CACHE_NULL		0
 /*	Prefetch data when reading. We continually attempt to load the next 32 sectors
- *	into the controller cache. 
+ *	into the controller cache.
  */
 #define CACHE_PREFETCH		1
 /*	Prefetch data when reading. We sometimes attempt to load the next 32 sectors
@@ -406,15 +656,11 @@ static inline u32 i2o_context_list_remove(void *ptr, struct i2o_controller *c)
 /*
  *	Ioctl structures
  */
- 
-
-#define 	BLKI2OGRSTRAT	_IOR('2', 1, int) 
-#define 	BLKI2OGWSTRAT	_IOR('2', 2, int) 
-#define 	BLKI2OSRSTRAT	_IOW('2', 3, int) 
-#define 	BLKI2OSWSTRAT	_IOW('2', 4, int) 
-
-
 
+#define 	BLKI2OGRSTRAT	_IOR('2', 1, int)
+#define 	BLKI2OGWSTRAT	_IOR('2', 2, int)
+#define 	BLKI2OSRSTRAT	_IOW('2', 3, int)
+#define 	BLKI2OSWSTRAT	_IOW('2', 4, int)
 
 /*
  *	I2O Function codes
@@ -652,7 +898,6 @@ static inline u32 i2o_context_list_remove(void *ptr, struct i2o_controller *c)
 #define TRL_SINGLE_VARIABLE_LENGTH	0x40
 #define TRL_MULTIPLE_FIXED_LENGTH	0x80
 
-
  /* msg header defines for MsgFlags */
 #define MSG_STATIC	0x0100
 #define MSG_64BIT_CNTXT	0x0200
@@ -673,13 +918,12 @@ static inline u32 i2o_context_list_remove(void *ptr, struct i2o_controller *c)
 #define ELEVEN_WORD_MSG_SIZE	0x000B0000
 #define I2O_MESSAGE_SIZE(x)	((x)<<16)
 
-
 /* Special TID Assignments */
 
 #define ADAPTER_TID		0
 #define HOST_TID		1
 
-#define MSG_FRAME_SIZE		64	/* i2o_scsi assumes >= 32 */
+#define MSG_FRAME_SIZE		128	/* i2o_scsi assumes >= 32 */
 #define REPLY_FRAME_SIZE	17
 #define SG_TABLESIZE		30
 #define NMBR_MSG_FRAMES		128
@@ -693,5 +937,23 @@ static inline u32 i2o_context_list_remove(void *ptr, struct i2o_controller *c)
 #define I2O_CONTEXT_LIST_USED		0x01
 #define I2O_CONTEXT_LIST_DELETED	0x02
 
-#endif /* __KERNEL__ */
-#endif /* _I2O_H */
+/* timeouts */
+#define I2O_TIMEOUT_INIT_OUTBOUND_QUEUE	15
+#define I2O_TIMEOUT_MESSAGE_GET		5
+#define I2O_TIMEOUT_RESET		30
+#define I2O_TIMEOUT_STATUS_GET		5
+#define I2O_TIMEOUT_LCT_GET		20
+#define I2O_TIMEOUT_SCSI_SCB_ABORT	240
+
+/* retries */
+#define I2O_HRT_GET_TRIES		3
+#define I2O_LCT_GET_TRIES		3
+
+/* request queue sizes */
+#define I2O_MAX_SECTORS			1024
+#define I2O_MAX_SEGMENTS		128
+
+#define I2O_REQ_MEMPOOL_SIZE		32
+
+#endif				/* __KERNEL__ */
+#endif				/* _I2O_H */
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 06542968a..f6a39379a 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -51,16 +51,6 @@
 #ifndef OK_TO_RESET_CONTROLLER		/* 1 needed for good error recovery */
 #define OK_TO_RESET_CONTROLLER	1	/* 0 for use with AH2372A/B interface */
 #endif
-#ifndef FANCY_STATUS_DUMPS		/* 1 for human-readable drive errors */
-#define FANCY_STATUS_DUMPS	1	/* 0 to reduce kernel size */
-#endif
-
-#ifdef CONFIG_BLK_DEV_CMD640
-#if 0	/* change to 1 when debugging cmd640 problems */
-void cmd640_dump_regs (void);
-#define CMD640_DUMP_REGS cmd640_dump_regs() /* for debugging cmd640 chipset */
-#endif
-#endif  /* CONFIG_BLK_DEV_CMD640 */
 
 #ifndef DISABLE_IRQ_NOSYNC
 #define DISABLE_IRQ_NOSYNC	0
@@ -756,8 +746,8 @@ typedef struct ide_drive_s {
 					 *  2=48-bit doing 28-bit
 					 *  3=64-bit
 					 */
+	unsigned scsi		: 1;	/* 0=default, 1=ide-scsi emulation */
 
-	u8	scsi;		/* 0=default, 1=skip current ide-subdriver for ide-scsi emulation */
         u8	quirk_list;	/* considered quirky, set for a specific host */
         u8	suspend_reset;	/* drive suspend mode flag, soft-reset recovers */
         u8	init_speed;	/* transfer rate set at boot */
@@ -780,6 +770,7 @@ typedef struct ide_drive_s {
 	u8	sect;		/* "real" sectors per track */
 	u8	bios_head;	/* BIOS/fdisk/LILO number of heads */
 	u8	bios_sect;	/* BIOS/fdisk/LILO sectors per track */
+	u8	doing_barrier;	/* state, 1=currently doing flush */
 
 	unsigned int	bios_cyl;	/* BIOS/fdisk/LILO number of cyls */
 	unsigned int	cyl;		/* "real" number of cyls */
@@ -798,31 +789,6 @@ typedef struct ide_drive_s {
 	struct gendisk *disk;
 } ide_drive_t;
 
-typedef struct ide_pio_ops_s {
-	void (*ata_input_data)(ide_drive_t *, void *, u32);
-	void (*ata_output_data)(ide_drive_t *, void *, u32);
-
-	void (*atapi_input_bytes)(ide_drive_t *, void *, u32);
-	void (*atapi_output_bytes)(ide_drive_t *, void *, u32);
-} ide_pio_ops_t;
-
-typedef struct ide_dma_ops_s {
-	/* insert dma operations here! */
-	int (*ide_dma_read)(ide_drive_t *drive);
-	int (*ide_dma_write)(ide_drive_t *drive);
-	int (*ide_dma_begin)(ide_drive_t *drive);
-	int (*ide_dma_end)(ide_drive_t *drive);
-	int (*ide_dma_check)(ide_drive_t *drive);
-	int (*ide_dma_on)(ide_drive_t *drive);
-	int (*ide_dma_off_quietly)(ide_drive_t *drive);
-	int (*ide_dma_test_irq)(ide_drive_t *drive);
-	int (*ide_dma_host_on)(ide_drive_t *drive);
-	int (*ide_dma_host_off)(ide_drive_t *drive);
-	int (*ide_dma_verbose)(ide_drive_t *drive);
-	int (*ide_dma_lostirq)(ide_drive_t *drive);
-	int (*ide_dma_timeout)(ide_drive_t *drive);
-} ide_dma_ops_t;
-
 /*
  * mapping stuff, prepare for highmem...
  * 
@@ -915,15 +881,11 @@ typedef struct hwif_s {
 //	u8	(*ratefilter)(ide_drive_t *, u8);
 #endif
 
-#if 0
-	ide_pio_ops_t	*pioops;
-#else
 	void (*ata_input_data)(ide_drive_t *, void *, u32);
 	void (*ata_output_data)(ide_drive_t *, void *, u32);
 
 	void (*atapi_input_bytes)(ide_drive_t *, void *, u32);
 	void (*atapi_output_bytes)(ide_drive_t *, void *, u32);
-#endif
 
 	int (*ide_dma_read)(ide_drive_t *drive);
 	int (*ide_dma_write)(ide_drive_t *drive);
@@ -960,7 +922,9 @@ typedef struct hwif_s {
 	struct scatterlist *sg_table;
 	int sg_nents;			/* Current number of entries in it */
 	int sg_dma_direction;		/* dma transfer direction */
-	int sg_dma_active;		/* is it in use */
+
+	/* data phase of the active command (currently only valid for PIO/DMA) */
+	int		data_phase;
 
 	int		mmio;		/* hosts iomio (0) or custom (2) select */
 	int		rqsize;		/* max sectors per request */
@@ -988,6 +952,7 @@ typedef struct hwif_s {
 	unsigned	autodma    : 1;	/* auto-attempt using DMA at boot */
 	unsigned	udma_four  : 1;	/* 1=ATA-66 capable, 0=default */
 	unsigned	no_lba48   : 1; /* 1 = cannot do LBA48 */
+	unsigned	no_lba48_dma : 1; /* 1 = cannot do LBA48 DMA */
 	unsigned	no_dsc     : 1;	/* 0 default, 1 dsc_overlap disabled */
 	unsigned	auto_poll  : 1; /* supports nop auto-poll */
 
@@ -1292,6 +1257,11 @@ extern ide_startstop_t ide_do_reset (ide_drive_t *);
  */
 extern void ide_init_drive_cmd (struct request *rq);
 
+/*
+ * this function returns error location sector offset in case of a write error
+ */
+extern u64 ide_get_error_location(ide_drive_t *, char *);
+
 /*
  * "action" parameter type for ide_do_drive_cmd() below.
  */
@@ -1446,11 +1416,8 @@ extern ide_startstop_t set_geometry_intr(ide_drive_t *);
 extern ide_startstop_t recal_intr(ide_drive_t *);
 extern ide_startstop_t task_no_data_intr(ide_drive_t *);
 extern ide_startstop_t task_in_intr(ide_drive_t *);
-extern ide_startstop_t task_mulin_intr(ide_drive_t *);
 extern ide_startstop_t pre_task_out_intr(ide_drive_t *, struct request *);
 extern ide_startstop_t task_out_intr(ide_drive_t *);
-extern ide_startstop_t pre_task_mulout_intr(ide_drive_t *, struct request *);
-extern ide_startstop_t task_mulout_intr(ide_drive_t *);
 
 extern int ide_raw_taskfile(ide_drive_t *, ide_task_t *, u8 *);
 
@@ -1664,4 +1631,11 @@ extern struct semaphore ide_cfg_sem;
 
 extern struct bus_type ide_bus_type;
 
+/* check if CACHE FLUSH (EXT) command is supported (bits defined in ATA-6) */
+#define ide_id_has_flush_cache(id)	((id)->cfs_enable_2 & 0x3000)
+
+/* some Maxtor disks have bit 13 defined incorrectly so check bit 10 too */
+#define ide_id_has_flush_cache_ext(id)	\
+	(((id)->cfs_enable_2 & 0x2400) == 0x2400)
+
 #endif /* _IDE_H */
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index 58d6e606d..fd1b6eb94 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -105,7 +105,7 @@ struct __fdb_entry
 #include <linux/netdevice.h>
 
 extern void brioctl_set(int (*ioctl_hook)(unsigned int, void __user *));
-extern int (*br_handle_frame_hook)(struct sk_buff *skb);
+extern int (*br_handle_frame_hook)(struct net_bridge_port *p, struct sk_buff **pskb);
 extern int (*br_should_route_hook)(struct sk_buff **pskb);
 
 #endif
diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h
index 11f31f6d2..4037aaab7 100644
--- a/include/linux/if_ether.h
+++ b/include/linux/if_ether.h
@@ -59,6 +59,8 @@
 #define ETH_P_8021Q	0x8100          /* 802.1Q VLAN Extended Header  */
 #define ETH_P_IPX	0x8137		/* IPX over DIX			*/
 #define ETH_P_IPV6	0x86DD		/* IPv6 over bluebook		*/
+#define ETH_P_WCCP	0x883E		/* Web-cache coordination protocol
+					 * defined in draft-wilson-wrec-wccp-v2-00.txt */
 #define ETH_P_PPP_DISC	0x8863		/* PPPoE discovery messages     */
 #define ETH_P_PPP_SES	0x8864		/* PPPoE session messages	*/
 #define ETH_P_MPLS_UC	0x8847		/* MPLS Unicast traffic		*/
@@ -94,11 +96,19 @@
  *	This is an Ethernet frame header.
  */
  
-struct ethhdr 
-{
+struct ethhdr {
 	unsigned char	h_dest[ETH_ALEN];	/* destination eth addr	*/
 	unsigned char	h_source[ETH_ALEN];	/* source ether addr	*/
 	unsigned short	h_proto;		/* packet type ID field	*/
 } __attribute__((packed));
 
+#ifdef __KERNEL__
+#include <linux/skbuff.h>
+
+static inline struct ethhdr *eth_hdr(const struct sk_buff *skb)
+{
+	return (struct ethhdr *)skb->mac.raw;
+}
+#endif
+
 #endif	/* _LINUX_IF_ETHER_H */
diff --git a/include/linux/if_fddi.h b/include/linux/if_fddi.h
index 221796362..a912818e6 100644
--- a/include/linux/if_fddi.h
+++ b/include/linux/if_fddi.h
@@ -5,7 +5,7 @@
  *
  *		Global definitions for the ANSI FDDI interface.
  *
- * Version:	@(#)if_fddi.h	1.0.1	09/16/96
+ * Version:	@(#)if_fddi.h	1.0.2	Sep 29 2004
  *
  * Author:	Lawrence V. Stefani, <stefani@lkg.dec.com>
  *
@@ -103,38 +103,12 @@ struct fddihdr
 	} __attribute__ ((packed));
 
 /* Define FDDI statistics structure */
-struct fddi_statistics
-	{
-	__u32	rx_packets;				/* total packets received */
-	__u32	tx_packets;				/* total packets transmitted */
-	__u32	rx_bytes;				/* total bytes received	*/
-	__u32	tx_bytes;				/* total bytes transmitted */
-	__u32	rx_errors;				/* bad packets received	*/
-	__u32	tx_errors;				/* packet transmit problems	*/
-	__u32	rx_dropped;				/* no space in linux buffers */
-	__u32	tx_dropped;				/* no space available in linux */
-	__u32	multicast;				/* multicast packets received */
-	__u32	transmit_collision;		/* always 0 for FDDI */
+struct fddi_statistics {
+
+	/* Generic statistics. */
 
-	/* detailed rx_errors */
-	__u32	rx_length_errors;
-	__u32	rx_over_errors;		/* receiver ring buff overflow	*/
-	__u32	rx_crc_errors;		/* recved pkt with crc error	*/
-	__u32	rx_frame_errors;	/* recv'd frame alignment error */
-	__u32	rx_fifo_errors;		/* recv'r fifo overrun		*/
-	__u32	rx_missed_errors;	/* receiver missed packet	*/
+	struct net_device_stats gen;
 
-	/* detailed tx_errors */
-	__u32	tx_aborted_errors;
-	__u32	tx_carrier_errors;
-	__u32	tx_fifo_errors;
-	__u32	tx_heartbeat_errors;
-	__u32	tx_window_errors;
-	
-	/* for cslip etc */
-	__u32	rx_compressed;
-	__u32	tx_compressed;
-   
 	/* Detailed FDDI statistics.  Adopted from RFC 1512 */
 
 	__u8	smt_station_id[8];
diff --git a/include/linux/if_tr.h b/include/linux/if_tr.h
index f7c97eeb9..4fd451f81 100644
--- a/include/linux/if_tr.h
+++ b/include/linux/if_tr.h
@@ -48,6 +48,15 @@ struct trh_hdr {
 	__u16 rseg[8];			/* routing registers */
 };
 
+#ifdef __KERNEL__
+#include <linux/skbuff.h>
+
+static inline struct trh_hdr *tr_hdr(const struct sk_buff *skb)
+{
+	return (struct trh_hdr *)skb->mac.raw;
+}
+#endif
+
 /* This is an Token-Ring LLC structure */
 struct trllc {
 	__u8  dsap;			/* destination SAP */
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 420767fcb..29b6e1046 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -18,7 +18,6 @@
 /* externally defined structs */
 struct vlan_group;
 struct net_device;
-struct sk_buff;
 struct packet_type;
 struct vlan_collection;
 struct vlan_dev_info;
@@ -48,6 +47,13 @@ struct vlan_ethhdr {
    unsigned short	h_vlan_encapsulated_proto; /* packet type ID field (or len) */
 };
 
+#include <linux/skbuff.h>
+
+static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb)
+{
+	return (struct vlan_ethhdr *)skb->mac.raw;
+}
+
 struct vlan_hdr {
    unsigned short       h_vlan_TCI;                /* Encapsulates priority and VLAN ID */
    unsigned short       h_vlan_encapsulated_proto; /* packet type ID field (or len) */
@@ -152,7 +158,7 @@ static inline int __vlan_hwaccel_rx(struct sk_buff *skb,
 	skb->real_dev = skb->dev;
 	skb->dev = grp->vlan_devices[vlan_tag & VLAN_VID_MASK];
 	if (skb->dev == NULL) {
-		kfree_skb(skb);
+		dev_kfree_skb_any(skb);
 
 		/* Not NET_RX_DROP, this is not being dropped
 		 * due to congestion.
@@ -180,7 +186,7 @@ static inline int __vlan_hwaccel_rx(struct sk_buff *skb,
 		 * This allows the VLAN to have a different MAC than the underlying
 		 * device, and still route correctly.
 		 */
-		if (!memcmp(skb->mac.ethernet->h_dest, skb->dev->dev_addr, ETH_ALEN))
+		if (!memcmp(eth_hdr(skb)->h_dest, skb->dev->dev_addr, ETH_ALEN))
 			skb->pkt_type = PACKET_HOST;
 		break;
 	};
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index 27a5d0a97..ec751e9fb 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -3,6 +3,8 @@
 
 #ifdef __KERNEL__
 
+#include <linux/rcupdate.h>
+
 struct ipv4_devconf
 {
 	int	accept_redirects;
@@ -31,13 +33,13 @@ extern struct ipv4_devconf ipv4_devconf;
 
 struct in_device
 {
-	struct net_device		*dev;
+	struct net_device	*dev;
 	atomic_t		refcnt;
-	rwlock_t		lock;
 	int			dead;
 	struct in_ifaddr	*ifa_list;	/* IP ifaddr chain		*/
+	rwlock_t		mc_list_lock;
 	struct ip_mc_list	*mc_list;	/* IP multicast filter chain    */
-	rwlock_t		mc_lock;	/* for mc_tomb */
+	spinlock_t		mc_tomb_lock;
 	struct ip_mc_list	*mc_tomb;
 	unsigned long		mr_v1_seen;
 	unsigned long		mr_v2_seen;
@@ -50,6 +52,7 @@ struct in_device
 
 	struct neigh_parms	*arp_parms;
 	struct ipv4_devconf	cnf;
+	struct rcu_head		rcu_head;
 };
 
 #define IN_DEV_FORWARD(in_dev)		((in_dev)->cnf.forwarding)
@@ -80,6 +83,7 @@ struct in_ifaddr
 {
 	struct in_ifaddr	*ifa_next;
 	struct in_device	*ifa_dev;
+	struct rcu_head		rcu_head;
 	u32			ifa_local;
 	u32			ifa_address;
 	u32			ifa_mask;
@@ -133,19 +137,16 @@ static __inline__ int bad_mask(u32 mask, u32 addr)
 
 #define endfor_ifa(in_dev) }
 
-extern rwlock_t inetdev_lock;
-
-
 static __inline__ struct in_device *
 in_dev_get(const struct net_device *dev)
 {
 	struct in_device *in_dev;
 
-	read_lock(&inetdev_lock);
+	rcu_read_lock();
 	in_dev = dev->ip_ptr;
 	if (in_dev)
 		atomic_inc(&in_dev->refcnt);
-	read_unlock(&inetdev_lock);
+	rcu_read_unlock();
 	return in_dev;
 }
 
@@ -157,8 +158,7 @@ __in_dev_get(const struct net_device *dev)
 
 extern void in_dev_finish_destroy(struct in_device *idev);
 
-static __inline__ void
-in_dev_put(struct in_device *idev)
+static inline void in_dev_put(struct in_device *idev)
 {
 	if (atomic_dec_and_test(&idev->refcnt))
 		in_dev_finish_destroy(idev);
diff --git a/include/linux/input.h b/include/linux/input.h
index b7a30bb64..43cb25e22 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -527,6 +527,8 @@ struct input_absinfo {
 #define MSC_SERIAL		0x00
 #define MSC_PULSELED		0x01
 #define MSC_GESTURE		0x02
+#define MSC_RAW			0x03
+#define MSC_SCAN		0x04
 #define MSC_MAX			0x07
 
 /*
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 565321b05..c7bf37959 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -8,8 +8,8 @@
 #include <linux/bitops.h>
 #include <linux/preempt.h>
 #include <linux/cpumask.h>
+#include <linux/hardirq.h>
 #include <asm/atomic.h>
-#include <asm/hardirq.h>
 #include <asm/ptrace.h>
 #include <asm/system.h>
 
diff --git a/include/linux/ioctl32.h b/include/linux/ioctl32.h
index e5bff65d3..e1a641819 100644
--- a/include/linux/ioctl32.h
+++ b/include/linux/ioctl32.h
@@ -3,6 +3,15 @@
 
 struct file;
 
+typedef int (*ioctl_trans_handler_t)(unsigned int, unsigned int,
+					unsigned long, struct file *);
+
+struct ioctl_trans {
+	unsigned long cmd;
+	ioctl_trans_handler_t handler;
+	struct ioctl_trans *next;
+};
+
 /* 
  * Register an 32bit ioctl translation handler for ioctl cmd.
  *
@@ -13,16 +22,16 @@ struct file;
  *                        struct file *file: file descriptor pointer.
  */ 
 
-extern int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *));
-
+#ifdef CONFIG_COMPAT
+extern int register_ioctl32_conversion(unsigned int cmd,
+				ioctl_trans_handler_t handler);
 extern int unregister_ioctl32_conversion(unsigned int cmd);
 
-typedef int (*ioctl_trans_handler_t)(unsigned int, unsigned int, unsigned long, struct file *);
+#else
 
-struct ioctl_trans {
-	unsigned long cmd;
-	ioctl_trans_handler_t handler;
-	struct ioctl_trans *next;
-};
+#define register_ioctl32_conversion(cmd, handler)	({ 0; })
+#define unregister_ioctl32_conversion(cmd)		({ 0; })
+
+#endif
 
 #endif
diff --git a/include/linux/ip6_tunnel.h b/include/linux/ip6_tunnel.h
index 85805a797..5c23aeb10 100644
--- a/include/linux/ip6_tunnel.h
+++ b/include/linux/ip6_tunnel.h
@@ -16,6 +16,8 @@
 #define IP6_TNL_F_USE_ORIG_FLOWLABEL 0x4
 /* being used for Mobile IPv6 */
 #define IP6_TNL_F_MIP6_DEV 0x8
+/* copy DSCP from the outer packet */
+#define IP6_TNL_F_RCV_DSCP_COPY 0x10
 
 struct ip6_tnl_parm {
 	char name[IFNAMSIZ];	/* name of tunnel device */
diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h
index 4a448922b..2b3d98e13 100644
--- a/include/linux/ipmi.h
+++ b/include/linux/ipmi.h
@@ -405,6 +405,12 @@ int ipmi_unregister_for_cmd(ipmi_user_t   user,
 			    unsigned char netfn,
 			    unsigned char cmd);
 
+/*
+ * Allow run-to-completion mode to be set for the interface of
+ * a specific user.
+ */
+void ipmi_user_set_run_to_completion(ipmi_user_t user, int val);
+
 /*
  * When the user is created, it will not receive IPMI events by
  * default.  The user must set this to TRUE to get incoming events.
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index ccc084d37..d7d167388 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -182,8 +182,7 @@ enum {
    as offsets from skb->nh.
  */
 
-struct inet6_skb_parm
-{
+struct inet6_skb_parm {
 	int			iif;
 	__u16			ra;
 	__u16			hop;
@@ -194,6 +193,14 @@ struct inet6_skb_parm
 
 #define IP6CB(skb)	((struct inet6_skb_parm*)((skb)->cb))
 
+/**
+ * struct ipv6_pinfo - ipv6 private area
+ *
+ * In the struct sock hierarchy (tcp6_sock, upd6_sock, etc)
+ * this _must_ be the last member, so that inet6_sk_generic
+ * is able to calculate its offset from the base struct sock
+ * by using the struct proto->slab_obj_size member. -acme
+ */
 struct ipv6_pinfo {
 	struct in6_addr 	saddr;
 	struct in6_addr 	rcv_saddr;
diff --git a/include/linux/isicom.h b/include/linux/isicom.h
index a5a3eea54..f9974634b 100644
--- a/include/linux/isicom.h
+++ b/include/linux/isicom.h
@@ -102,7 +102,6 @@ typedef	struct	{
 #define ClearInterrupt(base) (inw((base)+0x0a))	
 
 #define	BOARD(line)  (((line) >> 4) & 0x3)
-#define MIN(a, b) ( (a) < (b) ? (a) : (b) )
 
 	/*	isi kill queue bitmap	*/
 	
diff --git a/include/linux/iso_fs.h b/include/linux/iso_fs.h
index dd53b6cd2..099039d4b 100644
--- a/include/linux/iso_fs.h
+++ b/include/linux/iso_fs.h
@@ -192,29 +192,29 @@ static inline int isonum_712(char *p)
 }
 static inline unsigned int isonum_721(char *p)
 {
-	return le16_to_cpu(get_unaligned((u16 *)p));
+	return le16_to_cpu(get_unaligned((__le16 *)p));
 }
 static inline unsigned int isonum_722(char *p)
 {
-	return be16_to_cpu(get_unaligned((u16 *)p));
+	return be16_to_cpu(get_unaligned((__le16 *)p));
 }
 static inline unsigned int isonum_723(char *p)
 {
 	/* Ignore bigendian datum due to broken mastering programs */
-	return le16_to_cpu(get_unaligned((u16 *)p));
+	return le16_to_cpu(get_unaligned((__le16 *)p));
 }
 static inline unsigned int isonum_731(char *p)
 {
-	return le32_to_cpu(get_unaligned((u32 *)p));
+	return le32_to_cpu(get_unaligned((__le32 *)p));
 }
 static inline unsigned int isonum_732(char *p)
 {
-	return be32_to_cpu(get_unaligned((u32 *)p));
+	return be32_to_cpu(get_unaligned((__le32 *)p));
 }
 static inline unsigned int isonum_733(char *p)
 {
 	/* Ignore bigendian datum due to broken mastering programs */
-	return le32_to_cpu(get_unaligned((u32 *)p));
+	return le32_to_cpu(get_unaligned((__le32 *)p));
 }
 extern int iso_date(char *, int);
 
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index dec393a59..e65b90f19 100644
--- a/include/linux/jbd.h
+++ b/include/linux/jbd.h
@@ -137,9 +137,9 @@ typedef struct journal_s	journal_t;	/* Journal control structure */
  */
 typedef struct journal_header_s
 {
-	__u32		h_magic;
-	__u32		h_blocktype;
-	__u32		h_sequence;
+	__be32		h_magic;
+	__be32		h_blocktype;
+	__be32		h_sequence;
 } journal_header_t;
 
 
@@ -148,8 +148,8 @@ typedef struct journal_header_s
  */
 typedef struct journal_block_tag_s
 {
-	__u32		t_blocknr;	/* The on-disk block number */
-	__u32		t_flags;	/* See below */
+	__be32		t_blocknr;	/* The on-disk block number */
+	__be32		t_flags;	/* See below */
 } journal_block_tag_t;
 
 /* 
@@ -159,7 +159,7 @@ typedef struct journal_block_tag_s
 typedef struct journal_revoke_header_s
 {
 	journal_header_t r_header;
-	int		 r_count;	/* Count of bytes used in the block */
+	__be32		 r_count;	/* Count of bytes used in the block */
 } journal_revoke_header_t;
 
 
@@ -180,35 +180,35 @@ typedef struct journal_superblock_s
 
 /* 0x000C */
 	/* Static information describing the journal */
-	__u32	s_blocksize;		/* journal device blocksize */
-	__u32	s_maxlen;		/* total blocks in journal file */
-	__u32	s_first;		/* first block of log information */
+	__be32	s_blocksize;		/* journal device blocksize */
+	__be32	s_maxlen;		/* total blocks in journal file */
+	__be32	s_first;		/* first block of log information */
 
 /* 0x0018 */
 	/* Dynamic information describing the current state of the log */
-	__u32	s_sequence;		/* first commit ID expected in log */
-	__u32	s_start;		/* blocknr of start of log */
+	__be32	s_sequence;		/* first commit ID expected in log */
+	__be32	s_start;		/* blocknr of start of log */
 
 /* 0x0020 */
 	/* Error value, as set by journal_abort(). */
-	__s32	s_errno;
+	__be32	s_errno;
 
 /* 0x0024 */
 	/* Remaining fields are only valid in a version-2 superblock */
-	__u32	s_feature_compat; 	/* compatible feature set */
-	__u32	s_feature_incompat; 	/* incompatible feature set */
-	__u32	s_feature_ro_compat; 	/* readonly-compatible feature set */
+	__be32	s_feature_compat; 	/* compatible feature set */
+	__be32	s_feature_incompat; 	/* incompatible feature set */
+	__be32	s_feature_ro_compat; 	/* readonly-compatible feature set */
 /* 0x0030 */
 	__u8	s_uuid[16];		/* 128-bit uuid for journal */
 
 /* 0x0040 */
-	__u32	s_nr_users;		/* Nr of filesystems sharing log */
+	__be32	s_nr_users;		/* Nr of filesystems sharing log */
 
-	__u32	s_dynsuper;		/* Blocknr of dynamic superblock copy*/
+	__be32	s_dynsuper;		/* Blocknr of dynamic superblock copy*/
 
 /* 0x0048 */
-	__u32	s_max_transaction;	/* Limit of journal blocks per trans.*/
-	__u32	s_max_trans_data;	/* Limit of data blocks per trans. */
+	__be32	s_max_transaction;	/* Limit of journal blocks per trans.*/
+	__be32	s_max_trans_data;	/* Limit of data blocks per trans. */
 
 /* 0x0050 */
 	__u32	s_padding[44];
@@ -840,6 +840,7 @@ struct journal_s
 #define JFS_ACK_ERR	0x004	/* The errno in the sb has been acked */
 #define JFS_FLUSHED	0x008	/* The journal superblock has been flushed */
 #define JFS_LOADED	0x010	/* The journal superblock has been loaded */
+#define JFS_BARRIER	0x020	/* Use IDE barriers */
 
 /* 
  * Function declarations for the journaling transaction and buffer
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index c4c862629..40307a28b 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -12,6 +12,7 @@
 #include <linux/stddef.h>
 #include <linux/types.h>
 #include <linux/compiler.h>
+#include <linux/bitops.h>
 #include <asm/byteorder.h>
 #include <asm/bug.h>
 
@@ -97,6 +98,7 @@ extern int __kernel_text_address(unsigned long addr);
 extern int kernel_text_address(unsigned long addr);
 extern int session_of_pgrp(int pgrp);
 
+asmlinkage int vprintk(const char *fmt, va_list args);
 asmlinkage int printk(const char * fmt, ...)
 	__attribute__ ((format (printf, 1, 2)));
 
@@ -110,6 +112,10 @@ static inline int __attribute_pure__ long_log2(unsigned long x)
 	return r;
 }
 
+static inline unsigned long __attribute_const__ roundup_pow_of_two(unsigned long x)
+{
+	return (1UL << fls(x - 1));
+}
 
 extern int printk_ratelimit(void);
 extern int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst);
diff --git a/include/linux/kmod.h b/include/linux/kmod.h
index a484f5244..588f4c6eb 100644
--- a/include/linux/kmod.h
+++ b/include/linux/kmod.h
@@ -35,6 +35,7 @@ static inline int request_module(const char * name, ...) { return -ENOSYS; }
 
 #define try_then_request_module(x, mod...) ((x) ?: (request_module(mod), (x)))
 extern int call_usermodehelper(char *path, char *argv[], char *envp[], int wait);
+extern void usermodehelper_init(void);
 
 #ifdef CONFIG_HOTPLUG
 extern char hotplug_path [];
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 6360d2258..331d25b9c 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -12,13 +12,16 @@
  * destructors. 
  */
 
-#if defined(__KERNEL__) && !defined(_KOBJECT_H_)
+#ifndef _KOBJECT_H_
 #define _KOBJECT_H_
 
+#ifdef __KERNEL__
+
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/sysfs.h>
 #include <linux/rwsem.h>
+#include <linux/kref.h>
 #include <asm/atomic.h>
 
 #define KOBJ_NAME_LEN	20
@@ -26,7 +29,7 @@
 struct kobject {
 	char			* k_name;
 	char			name[KOBJ_NAME_LEN];
-	atomic_t		refcount;
+	struct kref		kref;
 	struct list_head	entry;
 	struct kobject		* parent;
 	struct kset		* kset;
@@ -58,6 +61,8 @@ extern void kobject_put(struct kobject *);
 
 extern void kobject_hotplug(const char *action, struct kobject *);
 
+extern char * kobject_get_path(struct kset *, struct kobject *, int);
+
 struct kobj_type {
 	void (*release)(struct kobject *);
 	struct sysfs_ops	* sysfs_ops;
@@ -229,5 +234,5 @@ struct subsys_attribute {
 extern int subsys_create_file(struct subsystem * , struct subsys_attribute *);
 extern void subsys_remove_file(struct subsystem * , struct subsys_attribute *);
 
-
+#endif /* __KERNEL__ */
 #endif /* _KOBJECT_H_ */
diff --git a/include/linux/kref.h b/include/linux/kref.h
index 82284b7e7..ea5948785 100644
--- a/include/linux/kref.h
+++ b/include/linux/kref.h
@@ -12,21 +12,21 @@
  *
  */
 
-#if defined(__KERNEL__) && !defined(_KREF_H_)
+#ifndef _KREF_H_
 #define _KREF_H_
 
+#ifdef __KERNEL__
+
 #include <linux/types.h>
 #include <asm/atomic.h>
 
-
 struct kref {
 	atomic_t refcount;
-	void (*release)(struct kref *kref);
 };
 
-void kref_init(struct kref *kref, void (*release)(struct kref *));
-struct kref *kref_get(struct kref *kref);
-void kref_put(struct kref *kref);
-
+void kref_init(struct kref *kref);
+void kref_get(struct kref *kref);
+void kref_put(struct kref *kref, void (*release) (struct kref *kref));
 
+#endif /* __KERNEL__ */
 #endif /* _KREF_H_ */
diff --git a/include/linux/libata.h b/include/linux/libata.h
index b646a4834..171b06794 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -32,7 +32,6 @@
 /*
  * compile-time options
  */
-#undef ATA_FORCE_PIO		/* do not configure or use DMA */
 #undef ATA_DEBUG		/* debugging output */
 #undef ATA_VERBOSE_DEBUG	/* yet more debugging output */
 #undef ATA_IRQ_TRAP		/* define to ack screaming irqs */
@@ -88,10 +87,7 @@ enum {
 	/* struct ata_device stuff */
 	ATA_DFLAG_LBA48		= (1 << 0), /* device supports LBA48 */
 	ATA_DFLAG_PIO		= (1 << 1), /* device currently in PIO mode */
-	ATA_DFLAG_MASTER	= (1 << 2), /* is device 0? */
-	ATA_DFLAG_WCACHE	= (1 << 3), /* has write cache we can
-					     * (hopefully) flush? */
-	ATA_DFLAG_LOCK_SECTORS	= (1 << 4), /* don't adjust max_sectors */
+	ATA_DFLAG_LOCK_SECTORS	= (1 << 2), /* don't adjust max_sectors */
 
 	ATA_DEV_UNKNOWN		= 0,	/* unknown device */
 	ATA_DEV_ATA		= 1,	/* ATA device */
@@ -111,7 +107,6 @@ enum {
 	ATA_FLAG_SATA_RESET	= (1 << 7), /* use COMRESET */
 
 	ATA_QCFLAG_ACTIVE	= (1 << 1), /* cmd not yet ack'd to scsi lyer */
-	ATA_QCFLAG_DMA		= (1 << 2), /* data delivered via DMA */
 	ATA_QCFLAG_SG		= (1 << 3), /* have s/g table? */
 	ATA_QCFLAG_SINGLE	= (1 << 4), /* no s/g, just a single buffer */
 	ATA_QCFLAG_DMAMAP	= ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE,
@@ -140,6 +135,13 @@ enum {
 	PORT_UNKNOWN		= 0,
 	PORT_ENABLED		= 1,
 	PORT_DISABLED		= 2,
+
+	/* encoding various smaller bitmaps into a single
+	 * unsigned long bitmap
+	 */
+	ATA_SHIFT_UDMA		= 0,
+	ATA_SHIFT_MWDMA		= 8,
+	ATA_SHIFT_PIO		= 11,
 };
 
 enum pio_task_states {
@@ -188,12 +190,13 @@ struct ata_probe_ent {
 	struct ata_ioports	port[ATA_MAX_PORTS];
 	unsigned int		n_ports;
 	unsigned int		pio_mask;
+	unsigned int		mwdma_mask;
 	unsigned int		udma_mask;
 	unsigned int		legacy_mode;
 	unsigned long		irq;
 	unsigned int		irq_flags;
 	unsigned long		host_flags;
-	void			*mmio_base;
+	void __iomem		*mmio_base;
 	void			*private_data;
 };
 
@@ -201,7 +204,7 @@ struct ata_host_set {
 	spinlock_t		lock;
 	struct pci_dev		*pdev;
 	unsigned long		irq;
-	void			*mmio_base;
+	void __iomem		*mmio_base;
 	unsigned int		n_ports;
 	void			*private_data;
 	struct ata_port_operations *ops;
@@ -215,6 +218,9 @@ struct ata_queued_cmd {
 	struct scsi_cmnd	*scsicmd;
 	void			(*scsidone)(struct scsi_cmnd *);
 
+	struct ata_taskfile	tf;
+	u8			cdb[ATAPI_CDB_LEN];
+
 	unsigned long		flags;		/* ATA_QCFLAG_xxx */
 	unsigned int		tag;
 	unsigned int		n_elem;
@@ -226,7 +232,6 @@ struct ata_queued_cmd {
 	unsigned int		cursg;
 	unsigned int		cursg_ofs;
 
-	struct ata_taskfile	tf;
 	struct scatterlist	sgent;
 	void			*buf_virt;
 
@@ -251,8 +256,10 @@ struct ata_device {
 	unsigned int		class;		/* ATA_DEV_xxx */
 	unsigned int		devno;		/* 0 or 1 */
 	u16			id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
-	unsigned int		pio_mode;
-	unsigned int		udma_mode;
+	u8			pio_mode;
+	u8			dma_mode;
+	u8			xfer_mode;
+	unsigned int		xfer_shift;	/* ATA_SHIFT_xxx */
 
 	/* cache info about current transfer mode */
 	u8			xfer_protocol;	/* taskfile xfer protocol */
@@ -277,8 +284,10 @@ struct ata_port {
 	unsigned int		bus_state;
 	unsigned int		port_state;
 	unsigned int		pio_mask;
+	unsigned int		mwdma_mask;
 	unsigned int		udma_mask;
 	unsigned int		cbl;	/* cable type; ATA_CBL_xxx */
+	unsigned int		cdb_len;
 
 	struct ata_device	device[ATA_MAX_DEVICES];
 
@@ -303,16 +312,15 @@ struct ata_port_operations {
 
 	void (*dev_config) (struct ata_port *, struct ata_device *);
 
-	void (*set_piomode) (struct ata_port *, struct ata_device *,
-			     unsigned int);
-	void (*set_udmamode) (struct ata_port *, struct ata_device *,
-			     unsigned int);
+	void (*set_piomode) (struct ata_port *, struct ata_device *);
+	void (*set_dmamode) (struct ata_port *, struct ata_device *);
 
 	void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
 	void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
 
 	void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
 	u8   (*check_status)(struct ata_port *ap);
+	void (*dev_select)(struct ata_port *ap, unsigned int device);
 
 	void (*phy_reset) (struct ata_port *ap);
 	void (*post_set_mode) (struct ata_port *ap);
@@ -342,6 +350,7 @@ struct ata_port_info {
 	Scsi_Host_Template	*sht;
 	unsigned long		host_flags;
 	unsigned long		pio_mask;
+	unsigned long		mwdma_mask;
 	unsigned long		udma_mask;
 	struct ata_port_operations	*port_ops;
 };
@@ -354,6 +363,7 @@ struct pci_bits {
 };
 
 extern void ata_port_probe(struct ata_port *);
+extern void __sata_phy_reset(struct ata_port *ap);
 extern void sata_phy_reset(struct ata_port *ap);
 extern void ata_bus_reset(struct ata_port *ap);
 extern void ata_port_disable(struct ata_port *);
@@ -363,6 +373,7 @@ extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_i
 extern void ata_pci_remove_one (struct pci_dev *pdev);
 extern int ata_device_add(struct ata_probe_ent *ent);
 extern int ata_scsi_detect(Scsi_Host_Template *sht);
+extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
 extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
 extern int ata_scsi_error(struct Scsi_Host *host);
 extern int ata_scsi_release(struct Scsi_Host *host);
@@ -370,31 +381,32 @@ extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc
 /*
  * Default driver ops implementations
  */
-extern void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf);
-extern void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
-extern void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf);
-extern void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf);
+extern void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf);
+extern void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
 extern void ata_tf_to_fis(struct ata_taskfile *tf, u8 *fis, u8 pmp);
 extern void ata_tf_from_fis(u8 *fis, struct ata_taskfile *tf);
-extern u8 ata_check_status_pio(struct ata_port *ap);
-extern u8 ata_check_status_mmio(struct ata_port *ap);
-extern void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf);
-extern void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
+extern void ata_noop_dev_select (struct ata_port *ap, unsigned int device);
+extern void ata_std_dev_select (struct ata_port *ap, unsigned int device);
+extern u8 ata_check_status(struct ata_port *ap);
+extern void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf);
 extern int ata_port_start (struct ata_port *ap);
 extern void ata_port_stop (struct ata_port *ap);
 extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
+extern struct ata_probe_ent *
+ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port);
+extern struct ata_probe_ent *
+ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port);
 extern void ata_qc_prep(struct ata_queued_cmd *qc);
 extern int ata_qc_issue_prot(struct ata_queued_cmd *qc);
 extern void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf,
 		unsigned int buflen);
 extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
 		 unsigned int n_elem);
+extern unsigned int ata_dev_classify(struct ata_taskfile *tf);
 extern void ata_dev_id_string(struct ata_device *dev, unsigned char *s,
 			      unsigned int ofs, unsigned int len);
-extern void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc);
-extern void ata_bmdma_start_mmio (struct ata_queued_cmd *qc);
-extern void ata_bmdma_setup_pio (struct ata_queued_cmd *qc);
-extern void ata_bmdma_start_pio (struct ata_queued_cmd *qc);
+extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
+extern void ata_bmdma_start (struct ata_queued_cmd *qc);
 extern void ata_bmdma_irq_clear(struct ata_port *ap);
 extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits);
 extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat);
@@ -419,7 +431,7 @@ static inline unsigned int ata_dev_present(struct ata_device *dev)
 static inline u8 ata_chk_err(struct ata_port *ap)
 {
 	if (ap->flags & ATA_FLAG_MMIO) {
-		return readb((void *) ap->ioaddr.error_addr);
+		return readb((void __iomem *) ap->ioaddr.error_addr);
 	}
 	return inb(ap->ioaddr.error_addr);
 }
@@ -432,7 +444,7 @@ static inline u8 ata_chk_status(struct ata_port *ap)
 static inline u8 ata_altstatus(struct ata_port *ap)
 {
 	if (ap->flags & ATA_FLAG_MMIO)
-		return readb(ap->ioaddr.altstatus_addr);
+		return readb((void __iomem *)ap->ioaddr.altstatus_addr);
 	return inb(ap->ioaddr.altstatus_addr);
 }
 
@@ -472,7 +484,6 @@ static inline u8 ata_wait_idle(struct ata_port *ap)
 
 static inline void ata_qc_set_polling(struct ata_queued_cmd *qc)
 {
-	qc->flags &= ~ATA_QCFLAG_DMA;
 	qc->tf.ctl |= ATA_NIEN;
 }
 
@@ -504,7 +515,7 @@ static inline u8 ata_irq_on(struct ata_port *ap)
 	ap->last_ctl = ap->ctl;
 
 	if (ap->flags & ATA_FLAG_MMIO)
-		writeb(ap->ctl, ioaddr->ctl_addr);
+		writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
 	else
 		outb(ap->ctl, ioaddr->ctl_addr);
 	tmp = ata_wait_idle(ap);
@@ -525,7 +536,7 @@ static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
 
 	/* get controller status; clear intr, err bits */
 	if (ap->flags & ATA_FLAG_MMIO) {
-		void *mmio = (void *) ap->ioaddr.bmdma_addr;
+		void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
 		host_stat = readb(mmio + ATA_DMA_STATUS);
 		writeb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
 		       mmio + ATA_DMA_STATUS);
@@ -563,7 +574,7 @@ static inline unsigned int sata_dev_present(struct ata_port *ap)
 static inline void ata_bmdma_stop(struct ata_port *ap)
 {
 	if (ap->flags & ATA_FLAG_MMIO) {
-		void *mmio = (void *) ap->ioaddr.bmdma_addr;
+		void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
 
 		/* clear start/stop bit */
 		writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
@@ -581,7 +592,7 @@ static inline void ata_bmdma_stop(struct ata_port *ap)
 static inline void ata_bmdma_ack_irq(struct ata_port *ap)
 {
 	if (ap->flags & ATA_FLAG_MMIO) {
-		void *mmio = ((void *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS;
+		void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS;
 		writeb(readb(mmio), mmio);
 	} else {
 		unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
@@ -593,11 +604,18 @@ static inline u8 ata_bmdma_status(struct ata_port *ap)
 {
 	u8 host_stat;
 	if (ap->flags & ATA_FLAG_MMIO) {
-		void *mmio = (void *) ap->ioaddr.bmdma_addr;
+		void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
 		host_stat = readb(mmio + ATA_DMA_STATUS);
 	} else
 		host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
 	return host_stat;
 }
 
+static inline int ata_try_flush_cache(struct ata_device *dev)
+{
+	return ata_id_wcache_enabled(dev) ||
+	       ata_id_has_flush(dev) ||
+	       ata_id_has_flush_ext(dev);
+}
+
 #endif /* __LINUX_LIBATA_H__ */
diff --git a/include/linux/linkage.h b/include/linux/linkage.h
index 09955c0ce..338f7795d 100644
--- a/include/linux/linkage.h
+++ b/include/linux/linkage.h
@@ -14,6 +14,10 @@
 #define asmlinkage CPP_ASMLINKAGE
 #endif
 
+#ifndef prevent_tail_call
+# define prevent_tail_call(ret) do { } while (0)
+#endif
+
 #ifndef __ALIGN
 #define __ALIGN		.align 4,0x90
 #define __ALIGN_STR	".align 4,0x90"
diff --git a/include/linux/list.h b/include/linux/list.h
index 33b863bcb..94bed0f27 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -195,6 +195,21 @@ static inline void list_del_rcu(struct list_head *entry)
 	entry->prev = LIST_POISON2;
 }
 
+/*
+ * list_replace_rcu - replace old entry by new one
+ * @old : the element to be replaced
+ * @new : the new element to insert
+ *
+ * The old entry will be replaced with the new entry atomically.
+ */
+static inline void list_replace_rcu(struct list_head *old, struct list_head *new){
+	new->next = old->next;
+	new->prev = old->prev;
+	smp_wmb();
+	new->next->prev = new;
+	new->prev->next = new;
+}
+
 /**
  * list_del_init - deletes entry from list and reinitialize it.
  * @entry: the element to delete from the list.
@@ -420,11 +435,11 @@ static inline void list_splice_init(struct list_head *list,
  */
 #define list_for_each_rcu(pos, head) \
 	for (pos = (head)->next, prefetch(pos->next); pos != (head); \
-        	pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next))
+        	pos = rcu_dereference(pos->next), prefetch(pos->next))
 
 #define __list_for_each_rcu(pos, head) \
 	for (pos = (head)->next; pos != (head); \
-        	pos = pos->next, ({ smp_read_barrier_depends(); 0;}))
+        	pos = rcu_dereference(pos->next))
 
 /**
  * list_for_each_safe_rcu	-	iterate over an rcu-protected list safe
@@ -439,7 +454,7 @@ static inline void list_splice_init(struct list_head *list,
  */
 #define list_for_each_safe_rcu(pos, n, head) \
 	for (pos = (head)->next, n = pos->next; pos != (head); \
-		pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next)
+		pos = rcu_dereference(n), n = pos->next)
 
 /**
  * list_for_each_entry_rcu	-	iterate over rcu list of given type
@@ -455,8 +470,8 @@ static inline void list_splice_init(struct list_head *list,
 	for (pos = list_entry((head)->next, typeof(*pos), member),	\
 		     prefetch(pos->member.next);			\
 	     &pos->member != (head); 					\
-	     pos = list_entry(pos->member.next, typeof(*pos), member),	\
-		     ({ smp_read_barrier_depends(); 0;}),		\
+	     pos = rcu_dereference(list_entry(pos->member.next, 	\
+					typeof(*pos), member)),		\
 		     prefetch(pos->member.next))
 
 
@@ -472,7 +487,7 @@ static inline void list_splice_init(struct list_head *list,
  */
 #define list_for_each_continue_rcu(pos, head) \
 	for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \
-        	(pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next))
+        	(pos) = rcu_dereference((pos)->next), prefetch((pos)->next))
 
 /*
  * Double linked lists with a single pointer list head.
@@ -578,12 +593,9 @@ static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
  * or hlist_del_rcu(), running on this same list.
  * However, it is perfectly legal to run concurrently with
  * the _rcu list-traversal primitives, such as
- * hlist_for_each_entry(), but only if smp_read_barrier_depends()
- * is used to prevent memory-consistency problems on Alpha CPUs.
- * Regardless of the type of CPU, the list-traversal primitive
- * must be guarded by rcu_read_lock().
- *
- * OK, so why don't we have an hlist_for_each_entry_rcu()???
+ * hlist_for_each_rcu(), used to prevent memory-consistency
+ * problems on Alpha CPUs.  Regardless of the type of CPU, the
+ * list-traversal primitive must be guarded by rcu_read_lock().
  */
 static inline void hlist_add_head_rcu(struct hlist_node *n,
 					struct hlist_head *h)
@@ -628,6 +640,10 @@ static inline void hlist_add_after(struct hlist_node *n,
 	for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
 	     pos = n)
 
+#define hlist_for_each_rcu(pos, head) \
+	for ((pos) = (head)->first; pos && ({ prefetch((pos)->next); 1; }); \
+		(pos) = rcu_dereference((pos)->next))
+
 /**
  * hlist_for_each_entry	- iterate over list of given type
  * @tpos:	the type * to use as a loop counter.
@@ -693,7 +709,7 @@ static inline void hlist_add_after(struct hlist_node *n,
 	for (pos = (head)->first;					 \
 	     pos && ({ prefetch(pos->next); 1;}) &&			 \
 		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
-	     pos = pos->next, ({ smp_read_barrier_depends(); 0; }) )
+	     pos = rcu_dereference(pos->next))
 
 #else
 #warning "don't include kernel headers in userspace"
diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h
index 2a03cf135..b054debef 100644
--- a/include/linux/lockd/bind.h
+++ b/include/linux/lockd/bind.h
@@ -20,7 +20,7 @@ struct svc_rqst;
 struct nlmsvc_binding {
 	u32			(*fopen)(struct svc_rqst *,
 						struct nfs_fh *,
-						struct file *);
+						struct file **);
 	void			(*fclose)(struct file *);
 };
 
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index e0db6e1d0..5a173a673 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -52,10 +52,25 @@ struct nlm_host {
 	wait_queue_head_t	h_gracewait;	/* wait while reclaiming */
 	u32			h_state;	/* pseudo-state counter */
 	u32			h_nsmstate;	/* true remote NSM state */
-	unsigned int		h_count;	/* reference count */
+	u32			h_pidcount;	/* Pseudopids */
+	atomic_t		h_count;	/* reference count */
 	struct semaphore	h_sema;		/* mutex for pmap binding */
 	unsigned long		h_nextrebind;	/* next portmap call */
 	unsigned long		h_expires;	/* eligible for GC */
+	struct list_head	h_lockowners;	/* Lockowners for the client */
+	spinlock_t		h_lock;
+};
+
+/*
+ * Map an fl_owner_t into a unique 32-bit "pid"
+ */
+struct nlm_lockowner {
+	struct list_head list;
+	atomic_t count;
+
+	struct nlm_host *host;
+	fl_owner_t owner;
+	uint32_t pid;
 };
 
 /*
@@ -77,7 +92,7 @@ struct nlm_rqst {
 struct nlm_file {
 	struct nlm_file *	f_next;		/* linked list */
 	struct nfs_fh		f_handle;	/* NFS file handle */
-	struct file		f_file;		/* VFS file pointer */
+	struct file *		f_file;		/* VFS file pointer */
 	struct nlm_share *	f_shares;	/* DOS shares */
 	struct nlm_block *	f_blocks;	/* blocked locks */
 	unsigned int		f_locks;	/* guesstimate # of locks */
@@ -180,7 +195,7 @@ void		  nlmsvc_invalidate_all(void);
 static __inline__ struct inode *
 nlmsvc_file_inode(struct nlm_file *file)
 {
-	return file->f_file.f_dentry->d_inode;
+	return file->f_file->f_dentry->d_inode;
 }
 
 /*
@@ -205,6 +220,8 @@ nlm_compare_locks(struct file_lock *fl1, struct file_lock *fl2)
 	     &&(fl1->fl_type  == fl2->fl_type || fl2->fl_type == F_UNLCK);
 }
 
+extern struct lock_manager_operations nlmsvc_lock_operations;
+
 #endif /* __KERNEL__ */
 
 #endif /* LINUX_LOCKD_LOCKD_H */
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index 775c41590..9835ac230 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -68,9 +68,6 @@ struct mempolicy {
 	} v;
 };
 
-/* An NULL mempolicy pointer is a synonym of &default_policy. */
-extern struct mempolicy default_policy;
-
 /*
  * Support for managing mempolicy data objects (clone, copy, destroy)
  * The default fast path of a NULL MPOL_DEFAULT policy is always inlined.
diff --git a/include/linux/mii.h b/include/linux/mii.h
index c87b17ff2..c674b2ec6 100644
--- a/include/linux/mii.h
+++ b/include/linux/mii.h
@@ -33,7 +33,8 @@
 #define MII_NCONFIG         0x1c        /* Network interface config    */
 
 /* Basic mode control register. */
-#define BMCR_RESV               0x007f  /* Unused...                   */
+#define BMCR_RESV               0x003f  /* Unused...                   */
+#define BMCR_SPEED1000		0x0040  /* MSB of Speed (1000)         */
 #define BMCR_CTST               0x0080  /* Collision test              */
 #define BMCR_FULLDPLX           0x0100  /* Full duplex                 */
 #define BMCR_ANRESTART          0x0200  /* Auto negotiation restart    */
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
index 041263ab1..209f6ffbd 100644
--- a/include/linux/miscdevice.h
+++ b/include/linux/miscdevice.h
@@ -19,6 +19,7 @@
 #define SUN_OPENPROM_MINOR 139
 #define DMAPI_MINOR		140	/* DMAPI */
 #define NVRAM_MINOR 144
+#define SGI_MMTIMER        153
 #define STORE_QUEUE_MINOR	155
 #define I2O_MINOR 166
 #define MICROCODE_MINOR		184
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 5c584cced..65ff5b5e8 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -26,6 +26,12 @@ extern void * high_memory;
 extern unsigned long vmalloc_earlyreserve;
 extern int page_cluster;
 
+#ifdef CONFIG_SYSCTL
+extern int sysctl_legacy_va_layout;
+#else
+#define sysctl_legacy_va_layout 0
+#endif
+
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -195,21 +201,21 @@ struct page {
 	page_flags_t flags;		/* Atomic flags, some possibly
 					 * updated asynchronously */
 	atomic_t _count;		/* Usage count, see below. */
-	unsigned int mapcount;		/* Count of ptes mapped in mms,
+	atomic_t _mapcount;		/* Count of ptes mapped in mms,
 					 * to show when page is mapped
-					 * & limit reverse map searches,
-					 * protected by PG_maplock.
+					 * & limit reverse map searches.
 					 */
 	unsigned long private;		/* Mapping-private opaque data:
 					 * usually used for buffer_heads
 					 * if PagePrivate set; used for
 					 * swp_entry_t if PageSwapCache
 					 */
-	struct address_space *mapping;	/* If PG_anon clear, points to
+	struct address_space *mapping;	/* If low bit clear, points to
 					 * inode address_space, or NULL.
 					 * If page mapped as anonymous
-					 * memory, PG_anon is set, and
-					 * it points to anon_vma object.
+					 * memory, low bit is set, and
+					 * it points to anon_vma object:
+					 * see PAGE_MAPPING_ANON below.
 					 */
 	pgoff_t index;			/* Our offset within mapping. */
 	struct list_head lru;		/* Pageout list, eg. active_list
@@ -433,24 +439,32 @@ void page_address_init(void);
 
 /*
  * On an anonymous page mapped into a user virtual memory area,
- * page->mapping points to its anon_vma, not to a struct address_space.
+ * page->mapping points to its anon_vma, not to a struct address_space;
+ * with the PAGE_MAPPING_ANON bit set to distinguish it.
  *
  * Please note that, confusingly, "page_mapping" refers to the inode
  * address_space which maps the page from disk; whereas "page_mapped"
  * refers to user virtual address space into which the page is mapped.
  */
+#define PAGE_MAPPING_ANON	1
+
 extern struct address_space swapper_space;
 static inline struct address_space *page_mapping(struct page *page)
 {
-	struct address_space *mapping = NULL;
+	struct address_space *mapping = page->mapping;
 
 	if (unlikely(PageSwapCache(page)))
 		mapping = &swapper_space;
-	else if (likely(!PageAnon(page)))
-		mapping = page->mapping;
+	else if (unlikely((unsigned long)mapping & PAGE_MAPPING_ANON))
+		mapping = NULL;
 	return mapping;
 }
 
+static inline int PageAnon(struct page *page)
+{
+	return ((unsigned long)page->mapping & PAGE_MAPPING_ANON) != 0;
+}
+
 /*
  * Return the pagecache index of the passed page.  Regular pagecache pages
  * use ->index whereas swapcache pages use ->private
@@ -462,12 +476,27 @@ static inline pgoff_t page_index(struct page *page)
 	return page->index;
 }
 
+/*
+ * The atomic page->_mapcount, like _count, starts from -1:
+ * so that transitions both from it and to it can be tracked,
+ * using atomic_inc_and_test and atomic_add_negative(-1).
+ */
+static inline void reset_page_mapcount(struct page *page)
+{
+	atomic_set(&(page)->_mapcount, -1);
+}
+
+static inline int page_mapcount(struct page *page)
+{
+	return atomic_read(&(page)->_mapcount) + 1;
+}
+
 /*
  * Return true if this page is mapped into pagetables.
  */
 static inline int page_mapped(struct page *page)
 {
-	return page->mapcount != 0;
+	return atomic_read(&(page)->_mapcount) >= 0;
 }
 
 /*
@@ -490,15 +519,34 @@ static inline int page_mapped(struct page *page)
 
 extern void show_free_areas(void);
 
-struct page *shmem_nopage(struct vm_area_struct * vma,
+#ifdef CONFIG_SHMEM
+struct page *shmem_nopage(struct vm_area_struct *vma,
 			unsigned long address, int *type);
 int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *new);
 struct mempolicy *shmem_get_policy(struct vm_area_struct *vma,
 					unsigned long addr);
-struct file *shmem_file_setup(char * name, loff_t size, unsigned long flags);
-void shmem_lock(struct file * file, int lock);
+int shmem_lock(struct file *file, int lock, struct user_struct *user);
+#else
+#define shmem_nopage filemap_nopage
+#define shmem_lock(a, b, c) 	({0;})	/* always in memory, no need to lock */
+#define shmem_set_policy(a, b)	(0)
+#define shmem_get_policy(a, b)	(NULL)
+#endif
+struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags);
+
 int shmem_zero_setup(struct vm_area_struct *);
 
+static inline int can_do_mlock(void)
+{
+	if (capable(CAP_IPC_LOCK))
+		return 1;
+	if (current->rlim[RLIMIT_MEMLOCK].rlim_cur != 0)
+		return 1;
+	return 0;
+}
+extern int user_shm_lock(size_t, struct user_struct *);
+extern void user_shm_unlock(size_t, struct user_struct *);
+
 /*
  * Parameter block passed down to zap_pte_range in exceptional cases.
  */
@@ -588,31 +636,32 @@ static inline pmd_t *pmd_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long a
 }
 
 extern void free_area_init(unsigned long * zones_size);
-extern void free_area_init_node(int nid, pg_data_t *pgdat, struct page *pmap,
+extern void free_area_init_node(int nid, pg_data_t *pgdat,
 	unsigned long * zones_size, unsigned long zone_start_pfn, 
 	unsigned long *zholes_size);
-extern void memmap_init_zone(struct page *, unsigned long, int,
-	unsigned long, unsigned long);
+extern void memmap_init_zone(unsigned long, int, unsigned long, unsigned long);
 extern void mem_init(void);
 extern void show_mem(void);
 extern void si_meminfo(struct sysinfo * val);
 extern void si_meminfo_node(struct sysinfo *val, int nid);
 
-static inline void vma_prio_tree_init(struct vm_area_struct *vma)
-{
-	vma->shared.vm_set.list.next = NULL;
-	vma->shared.vm_set.list.prev = NULL;
-	vma->shared.vm_set.parent = NULL;
-	vma->shared.vm_set.head = NULL;
-}
-
 /* prio_tree.c */
 void vma_prio_tree_add(struct vm_area_struct *, struct vm_area_struct *old);
 void vma_prio_tree_insert(struct vm_area_struct *, struct prio_tree_root *);
 void vma_prio_tree_remove(struct vm_area_struct *, struct prio_tree_root *);
-struct vm_area_struct *vma_prio_tree_next(
-	struct vm_area_struct *, struct prio_tree_root *,
-	struct prio_tree_iter *, pgoff_t begin, pgoff_t end);
+struct vm_area_struct *vma_prio_tree_next(struct vm_area_struct *vma,
+	struct prio_tree_iter *iter);
+
+#define vma_prio_tree_foreach(vma, iter, root, begin, end)	\
+	for (prio_tree_iter_init(iter, root, begin, end), vma = NULL;	\
+		(vma = vma_prio_tree_next(vma, iter)); )
+
+static inline void vma_nonlinear_insert(struct vm_area_struct *vma,
+					struct list_head *list)
+{
+	vma->shared.vm_set.parent = NULL;
+	list_add_tail(&vma->shared.vm_set.list, list);
+}
 
 /* mmap.c */
 extern void vma_adjust(struct vm_area_struct *vma, unsigned long start,
@@ -712,6 +761,27 @@ extern struct page * follow_page(struct mm_struct *mm, unsigned long address,
 extern int remap_page_range(struct vm_area_struct *vma, unsigned long from,
 		unsigned long to, unsigned long size, pgprot_t prot);
 
+#ifdef CONFIG_PROC_FS
+void __vm_stat_account(struct mm_struct *, unsigned long, struct file *, long);
+#else
+static inline void __vm_stat_account(struct mm_struct *mm,
+			unsigned long flags, struct file *file, long pages)
+{
+}
+#endif /* CONFIG_PROC_FS */
+
+static inline void vm_stat_account(struct vm_area_struct *vma)
+{
+	__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file,
+							vma_pages(vma));
+}
+
+static inline void vm_stat_unaccount(struct vm_area_struct *vma)
+{
+	__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file,
+							-vma_pages(vma));
+}
+
 #ifndef CONFIG_DEBUG_PAGEALLOC
 static inline void
 kernel_map_pages(struct page *page, int numpages, int enable)
diff --git a/include/linux/mman.h b/include/linux/mman.h
index 07da84fcb..18a5689ef 100644
--- a/include/linux/mman.h
+++ b/include/linux/mman.h
@@ -10,6 +10,9 @@
 #define MREMAP_MAYMOVE	1
 #define MREMAP_FIXED	2
 
+#define OVERCOMMIT_GUESS		0
+#define OVERCOMMIT_ALWAYS		1
+#define OVERCOMMIT_NEVER		2
 extern int sysctl_overcommit_memory;
 extern int sysctl_overcommit_ratio;
 extern atomic_t vm_committed_space;
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 8a23709fe..7c36a10f6 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -20,18 +20,6 @@
 #define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER
 #endif
 
-/*
- * system hash table size limits
- * - on large memory machines, we may want to allocate a bigger hash than that
- *   permitted by MAX_ORDER, so we allocate with the bootmem allocator, and are
- *   limited to this size
- */
-#if MAX_ORDER > 14
-#define MAX_SYS_HASH_TABLE_ORDER MAX_ORDER
-#else
-#define MAX_SYS_HASH_TABLE_ORDER 14
-#endif
-
 struct free_area {
 	struct list_head	free_list;
 	unsigned long		*map;
@@ -284,6 +272,8 @@ typedef struct pglist_data {
 extern int numnodes;
 extern struct pglist_data *pgdat_list;
 
+void __get_zone_counts(unsigned long *active, unsigned long *inactive,
+			unsigned long *free, struct pglist_data *pgdat);
 void get_zone_counts(unsigned long *active, unsigned long *inactive,
 			unsigned long *free);
 void build_all_zonelists(void);
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index 9e799ecc1..7a145cd86 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -73,7 +73,7 @@ struct kparam_array
 #define module_param_string(name, string, len, perm)			\
 	static struct kparam_string __param_string_##name		\
 		= { len, string };					\
-	module_param_call(name, param_set_copystring, param_get_charp,	\
+	module_param_call(name, param_set_copystring, param_get_string,	\
 		   &__param_string_##name, perm)
 
 /* Called on module insert or kernel boot */
@@ -89,6 +89,10 @@ extern int parse_args(const char *name,
 #define __param_check(name, p, type) \
 	static inline type *__check_##name(void) { return(p); }
 
+extern int param_set_byte(const char *val, struct kernel_param *kp);
+extern int param_get_byte(char *buffer, struct kernel_param *kp);
+#define param_check_byte(name, p) __param_check(name, p, unsigned char)
+
 extern int param_set_short(const char *val, struct kernel_param *kp);
 extern int param_get_short(char *buffer, struct kernel_param *kp);
 #define param_check_short(name, p) __param_check(name, p, short)
@@ -140,6 +144,7 @@ extern int param_array_set(const char *val, struct kernel_param *kp);
 extern int param_array_get(char *buffer, struct kernel_param *kp);
 
 extern int param_set_copystring(const char *val, struct kernel_param *kp);
+extern int param_get_string(char *buffer, struct kernel_param *kp);
 
 int param_array(const char *name,
 		const char *val,
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
index d8916f9bf..d35fe747b 100644
--- a/include/linux/msdos_fs.h
+++ b/include/linux/msdos_fs.h
@@ -123,34 +123,34 @@ struct fat_boot_sector {
 				   partition manager volumes */
 	__u8	sector_size[2];	/* bytes per logical sector */
 	__u8	sec_per_clus;	/* sectors/cluster */
-	__u16	reserved;	/* reserved sectors */
+	__le16	reserved;	/* reserved sectors */
 	__u8	fats;		/* number of FATs */
 	__u8	dir_entries[2];	/* root directory entries */
 	__u8	sectors[2];	/* number of sectors */
 	__u8	media;		/* media code */
-	__u16	fat_length;	/* sectors/FAT */
-	__u16	secs_track;	/* sectors per track */
-	__u16	heads;		/* number of heads */
-	__u32	hidden;		/* hidden sectors (unused) */
-	__u32	total_sect;	/* number of sectors (if sectors == 0) */
+	__le16	fat_length;	/* sectors/FAT */
+	__le16	secs_track;	/* sectors per track */
+	__le16	heads;		/* number of heads */
+	__le32	hidden;		/* hidden sectors (unused) */
+	__le32	total_sect;	/* number of sectors (if sectors == 0) */
 
 	/* The following fields are only used by FAT32 */
-	__u32	fat32_length;	/* sectors/FAT */
-	__u16	flags;		/* bit 8: fat mirroring, low 4: active fat */
+	__le32	fat32_length;	/* sectors/FAT */
+	__le16	flags;		/* bit 8: fat mirroring, low 4: active fat */
 	__u8	version[2];	/* major, minor filesystem version */
-	__u32	root_cluster;	/* first cluster in root directory */
-	__u16	info_sector;	/* filesystem info sector */
-	__u16	backup_boot;	/* backup boot sector */
-	__u16	reserved2[6];	/* Unused */
+	__le32	root_cluster;	/* first cluster in root directory */
+	__le16	info_sector;	/* filesystem info sector */
+	__le16	backup_boot;	/* backup boot sector */
+	__le16	reserved2[6];	/* Unused */
 };
 
 struct fat_boot_fsinfo {
-	__u32   signature1;	/* 0x41615252L */
-	__u32   reserved1[120];	/* Nothing as far as I can tell */
-	__u32   signature2;	/* 0x61417272L */
-	__u32   free_clusters;	/* Free cluster count.  -1 if unknown */
-	__u32   next_cluster;	/* Most recently allocated cluster */
-	__u32   reserved2[4];
+	__le32   signature1;	/* 0x41615252L */
+	__le32   reserved1[120];	/* Nothing as far as I can tell */
+	__le32   signature2;	/* 0x61417272L */
+	__le32   free_clusters;	/* Free cluster count.  -1 if unknown */
+	__le32   next_cluster;	/* Most recently allocated cluster */
+	__le32   reserved2[4];
 };
 
 struct msdos_dir_entry {
@@ -158,12 +158,12 @@ struct msdos_dir_entry {
 	__u8	attr;		/* attribute bits */
 	__u8    lcase;		/* Case for base and extension */
 	__u8	ctime_ms;	/* Creation time, milliseconds */
-	__u16	ctime;		/* Creation time */
-	__u16	cdate;		/* Creation date */
-	__u16	adate;		/* Last access date */
-	__u16   starthi;	/* High 16 bits of cluster in FAT32 */
-	__u16	time,date,start;/* time, date and first cluster */
-	__u32	size;		/* file size (in bytes) */
+	__le16	ctime;		/* Creation time */
+	__le16	cdate;		/* Creation date */
+	__le16	adate;		/* Last access date */
+	__le16   starthi;	/* High 16 bits of cluster in FAT32 */
+	__le16	time,date,start;/* time, date and first cluster */
+	__le32	size;		/* file size (in bytes) */
 };
 
 /* Up to 13 characters of the name */
@@ -174,7 +174,7 @@ struct msdos_dir_slot {
 	__u8    reserved;	/* always 0 */
 	__u8    alias_checksum;	/* checksum for 8.3 alias */
 	__u8    name5_10[12];	/* 6 more characters in name */
-	__u16   start;		/* starting cluster number, 0 in long slots */
+	__le16   start;		/* starting cluster number, 0 in long slots */
 	__u8    name11_12[4];	/* last 2 characters in name */
 };
 
@@ -233,8 +233,6 @@ extern int fat_access(struct super_block *sb, int nr, int new_value);
 extern int __fat_access(struct super_block *sb, int nr, int new_value);
 extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys);
 extern void fat_cache_init(struct super_block *sb);
-extern void fat_cache_lookup(struct inode *inode, int cluster, int *f_clu,
-			     int *d_clu);
 extern void fat_cache_add(struct inode *inode, int f_clu, int d_clu);
 extern void fat_cache_inval_inode(struct inode *inode);
 extern int fat_get_cluster(struct inode *inode, int cluster,
@@ -278,7 +276,7 @@ extern void fat_put_super(struct super_block *sb);
 int fat_fill_super(struct super_block *sb, void *data, int silent,
 		   struct inode_operations *fs_dir_inode_ops, int isvfat);
 extern int fat_statfs(struct super_block *sb, struct kstatfs *buf);
-extern void fat_write_inode(struct inode *inode, int wait);
+extern int fat_write_inode(struct inode *inode, int wait);
 extern int fat_notify_change(struct dentry * dentry, struct iattr * attr);
 
 /* fat/misc.c */
@@ -289,8 +287,7 @@ extern void fat_clusters_flush(struct super_block *sb);
 extern int fat_add_cluster(struct inode *inode);
 extern struct buffer_head *fat_extend_dir(struct inode *inode);
 extern int date_dos2unix(unsigned short time, unsigned short date);
-extern void fat_date_unix2dos(int unix_date, unsigned short *time,
-			      unsigned short *date);
+extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date);
 extern int fat__get_entry(struct inode *dir, loff_t *pos,
 			  struct buffer_head **bh,
 			  struct msdos_dir_entry **de, loff_t *i_pos);
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h
index ed41daec7..278d0f30d 100644
--- a/include/linux/mtd/map.h
+++ b/include/linux/mtd/map.h
@@ -179,7 +179,7 @@ struct map_info {
 	unsigned long phys;
 #define NO_XIP (-1UL)
 
-	unsigned long virt;
+	void __iomem *virt;
 	void *cached;
 
 	int bankwidth; /* in octets. This isn't necessarily the width
diff --git a/include/linux/ncp.h b/include/linux/ncp.h
index 92062440a..99f77876b 100644
--- a/include/linux/ncp.h
+++ b/include/linux/ncp.h
@@ -57,9 +57,9 @@ struct ncp_volume_info {
 	char volume_name[NCP_VOLNAME_LEN + 1];
 };
 
-#define AR_READ      (ntohs(0x0100))
-#define AR_WRITE     (ntohs(0x0200))
-#define AR_EXCLUSIVE (ntohs(0x2000))
+#define AR_READ      (cpu_to_le16(1))
+#define AR_WRITE     (cpu_to_le16(2))
+#define AR_EXCLUSIVE (cpu_to_le16(0x20))
 
 #define NCP_FILE_ID_LEN 6
 
@@ -71,20 +71,20 @@ struct ncp_volume_info {
 #define NW_NS_OS2     4
 
 /*  Defines for ReturnInformationMask */
-#define RIM_NAME	      (ntohl(0x01000000L))
-#define RIM_SPACE_ALLOCATED   (ntohl(0x02000000L))
-#define RIM_ATTRIBUTES	      (ntohl(0x04000000L))
-#define RIM_DATA_SIZE	      (ntohl(0x08000000L))
-#define RIM_TOTAL_SIZE	      (ntohl(0x10000000L))
-#define RIM_EXT_ATTR_INFO     (ntohl(0x20000000L))
-#define RIM_ARCHIVE	      (ntohl(0x40000000L))
-#define RIM_MODIFY	      (ntohl(0x80000000L))
-#define RIM_CREATION	      (ntohl(0x00010000L))
-#define RIM_OWNING_NAMESPACE  (ntohl(0x00020000L))
-#define RIM_DIRECTORY	      (ntohl(0x00040000L))
-#define RIM_RIGHTS	      (ntohl(0x00080000L))
-#define RIM_ALL 	      (ntohl(0xFF0F0000L))
-#define RIM_COMPRESSED_INFO   (ntohl(0x00000080L))
+#define RIM_NAME	      (cpu_to_le32(1))
+#define RIM_SPACE_ALLOCATED   (cpu_to_le32(2))
+#define RIM_ATTRIBUTES	      (cpu_to_le32(4))
+#define RIM_DATA_SIZE	      (cpu_to_le32(8))
+#define RIM_TOTAL_SIZE	      (cpu_to_le32(0x10))
+#define RIM_EXT_ATTR_INFO     (cpu_to_le32(0x20))
+#define RIM_ARCHIVE	      (cpu_to_le32(0x40))
+#define RIM_MODIFY	      (cpu_to_le32(0x80))
+#define RIM_CREATION	      (cpu_to_le32(0x100))
+#define RIM_OWNING_NAMESPACE  (cpu_to_le32(0x200))
+#define RIM_DIRECTORY	      (cpu_to_le32(0x400))
+#define RIM_RIGHTS	      (cpu_to_le32(0x800))
+#define RIM_ALL 	      (cpu_to_le32(0xFFF))
+#define RIM_COMPRESSED_INFO   (cpu_to_le32(0x80000000))
 
 /* Defines for NSInfoBitMask */
 #define NSIBM_NFS_NAME		0x0001
@@ -129,24 +129,24 @@ struct nw_nfs_info {
 
 struct nw_info_struct {
 	__u32 spaceAlloc __attribute__((packed));
-	__u32 attributes __attribute__((packed));
+	__le32 attributes __attribute__((packed));
 	__u16 flags __attribute__((packed));
-	__u32 dataStreamSize __attribute__((packed));
-	__u32 totalStreamSize __attribute__((packed));
+	__le32 dataStreamSize __attribute__((packed));
+	__le32 totalStreamSize __attribute__((packed));
 	__u16 numberOfStreams __attribute__((packed));
-	__u16 creationTime __attribute__((packed));
-	__u16 creationDate __attribute__((packed));
+	__le16 creationTime __attribute__((packed));
+	__le16 creationDate __attribute__((packed));
 	__u32 creatorID __attribute__((packed));
-	__u16 modifyTime __attribute__((packed));
-	__u16 modifyDate __attribute__((packed));
+	__le16 modifyTime __attribute__((packed));
+	__le16 modifyDate __attribute__((packed));
 	__u32 modifierID __attribute__((packed));
-	__u16 lastAccessDate __attribute__((packed));
+	__le16 lastAccessDate __attribute__((packed));
 	__u16 archiveTime __attribute__((packed));
 	__u16 archiveDate __attribute__((packed));
 	__u32 archiverID __attribute__((packed));
 	__u16 inheritedRightsMask __attribute__((packed));
-	__u32 dirEntNum __attribute__((packed));
-	__u32 DosDirNum __attribute__((packed));
+	__le32 dirEntNum __attribute__((packed));
+	__le32 DosDirNum __attribute__((packed));
 	__u32 volNumber __attribute__((packed));
 	__u32 EADataSize __attribute__((packed));
 	__u32 EAKeyCount __attribute__((packed));
@@ -161,32 +161,32 @@ struct nw_info_struct {
 };
 
 /* modify mask - use with MODIFY_DOS_INFO structure */
-#define DM_ATTRIBUTES		  (ntohl(0x02000000L))
-#define DM_CREATE_DATE		  (ntohl(0x04000000L))
-#define DM_CREATE_TIME		  (ntohl(0x08000000L))
-#define DM_CREATOR_ID		  (ntohl(0x10000000L))
-#define DM_ARCHIVE_DATE 	  (ntohl(0x20000000L))
-#define DM_ARCHIVE_TIME 	  (ntohl(0x40000000L))
-#define DM_ARCHIVER_ID		  (ntohl(0x80000000L))
-#define DM_MODIFY_DATE		  (ntohl(0x00010000L))
-#define DM_MODIFY_TIME		  (ntohl(0x00020000L))
-#define DM_MODIFIER_ID		  (ntohl(0x00040000L))
-#define DM_LAST_ACCESS_DATE	  (ntohl(0x00080000L))
-#define DM_INHERITED_RIGHTS_MASK  (ntohl(0x00100000L))
-#define DM_MAXIMUM_SPACE	  (ntohl(0x00200000L))
+#define DM_ATTRIBUTES		  (cpu_to_le32(0x02))
+#define DM_CREATE_DATE		  (cpu_to_le32(0x04))
+#define DM_CREATE_TIME		  (cpu_to_le32(0x08))
+#define DM_CREATOR_ID		  (cpu_to_le32(0x10))
+#define DM_ARCHIVE_DATE 	  (cpu_to_le32(0x20))
+#define DM_ARCHIVE_TIME 	  (cpu_to_le32(0x40))
+#define DM_ARCHIVER_ID		  (cpu_to_le32(0x80))
+#define DM_MODIFY_DATE		  (cpu_to_le32(0x0100))
+#define DM_MODIFY_TIME		  (cpu_to_le32(0x0200))
+#define DM_MODIFIER_ID		  (cpu_to_le32(0x0400))
+#define DM_LAST_ACCESS_DATE	  (cpu_to_le32(0x0800))
+#define DM_INHERITED_RIGHTS_MASK  (cpu_to_le32(0x1000))
+#define DM_MAXIMUM_SPACE	  (cpu_to_le32(0x2000))
 
 struct nw_modify_dos_info {
-	__u32 attributes __attribute__((packed));
-	__u16 creationDate __attribute__((packed));
-	__u16 creationTime __attribute__((packed));
+	__le32 attributes __attribute__((packed));
+	__le16 creationDate __attribute__((packed));
+	__le16 creationTime __attribute__((packed));
 	__u32 creatorID __attribute__((packed));
-	__u16 modifyDate __attribute__((packed));
-	__u16 modifyTime __attribute__((packed));
+	__le16 modifyDate __attribute__((packed));
+	__le16 modifyTime __attribute__((packed));
 	__u32 modifierID __attribute__((packed));
 	__u16 archiveDate __attribute__((packed));
 	__u16 archiveTime __attribute__((packed));
 	__u32 archiverID __attribute__((packed));
-	__u16 lastAccessDate __attribute__((packed));
+	__le16 lastAccessDate __attribute__((packed));
 	__u16 inheritanceGrantMask __attribute__((packed));
 	__u16 inheritanceRevokeMask __attribute__((packed));
 	__u32 maximumSpace __attribute__((packed));
diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h
index d9ab889ed..7297e4372 100644
--- a/include/linux/ncp_fs.h
+++ b/include/linux/ncp_fs.h
@@ -36,7 +36,7 @@ struct ncp_fs_info {
 				   used for read/write requests! */
 
 	int volume_number;
-	__u32 directory_id;
+	__le32 directory_id;
 };
 
 struct ncp_fs_info_v2 {
@@ -46,7 +46,7 @@ struct ncp_fs_info_v2 {
 	unsigned int buffer_size;
 
 	unsigned int volume_number;
-	__u32 directory_id;
+	__le32 directory_id;
 
 	__u32 dummy1;
 	__u32 dummy2;
@@ -78,7 +78,7 @@ struct ncp_setroot_ioctl
 {
 	int		volNumber;
 	int		namespace;
-	__u32		dirEntNum;
+	__le32		dirEntNum;
 };
 
 struct ncp_objectname_ioctl
@@ -239,8 +239,8 @@ void ncp_update_inode2(struct inode *, struct ncp_entry_info *);
 extern struct inode_operations ncp_dir_inode_operations;
 extern struct file_operations ncp_dir_operations;
 int ncp_conn_logged_in(struct super_block *);
-int ncp_date_dos2unix(__u16 time, __u16 date);
-void ncp_date_unix2dos(int unix_date, __u16 * time, __u16 * date);
+int ncp_date_dos2unix(__le16 time, __le16 date);
+void ncp_date_unix2dos(int unix_date, __le16 * time, __le16 * date);
 
 /* linux/fs/ncpfs/ioctl.c */
 int ncp_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
diff --git a/include/linux/ncp_fs_i.h b/include/linux/ncp_fs_i.h
index 009dd388c..415be1ec6 100644
--- a/include/linux/ncp_fs_i.h
+++ b/include/linux/ncp_fs_i.h
@@ -15,10 +15,10 @@
  * all the information we need to work with an inode after creation.
  */
 struct ncp_inode_info {
-	__u32	dirEntNum;
-	__u32	DosDirNum;
-	__u32	volNumber;
-	__u32	nwattr;
+	__le32	dirEntNum;
+	__le32	DosDirNum;
+	__u8	volNumber;
+	__le32	nwattr;
 	struct semaphore open_sem;
 	atomic_t	opened;
 	int	access;
diff --git a/include/linux/ncp_no.h b/include/linux/ncp_no.h
index a4523ed0e..f56a696a7 100644
--- a/include/linux/ncp_no.h
+++ b/include/linux/ncp_no.h
@@ -2,18 +2,18 @@
 #define _NCP_NO
 
 /* these define the attribute byte as seen by NCP */
-#define aRONLY			(ntohl(0x01000000))
-#define aHIDDEN			(__constant_ntohl(0x02000000))
-#define aSYSTEM			(__constant_ntohl(0x04000000))
-#define aEXECUTE		(ntohl(0x08000000))
-#define aDIR			(ntohl(0x10000000))
-#define aARCH			(ntohl(0x20000000))
-#define aSHARED			(ntohl(0x80000000))
-#define aDONTSUBALLOCATE	(ntohl(1L<<(11+8)))
-#define aTRANSACTIONAL		(ntohl(1L<<(12+8)))
-#define aPURGE			(ntohl(1L<<(16-8)))
-#define aRENAMEINHIBIT		(ntohl(1L<<(17-8)))
-#define aDELETEINHIBIT		(ntohl(1L<<(18-8)))
-#define aDONTCOMPRESS		(nothl(1L<<(27-24)))
+#define aRONLY			(__constant_cpu_to_le32(1))
+#define aHIDDEN			(__constant_cpu_to_le32(2))
+#define aSYSTEM			(__constant_cpu_to_le32(4))
+#define aEXECUTE		(__constant_cpu_to_le32(8))
+#define aDIR			(__constant_cpu_to_le32(0x10))
+#define aARCH			(__constant_cpu_to_le32(0x20))
+#define aSHARED			(__constant_cpu_to_le32(0x80))
+#define aDONTSUBALLOCATE	(__constant_cpu_to_le32(1L<<11))
+#define aTRANSACTIONAL		(__constant_cpu_to_le32(1L<<12))
+#define aPURGE			(__constant_cpu_to_le32(1L<<16))
+#define aRENAMEINHIBIT		(__constant_cpu_to_le32(1L<<17))
+#define aDELETEINHIBIT		(__constant_cpu_to_le32(1L<<18))
+#define aDONTCOMPRESS		(__constant_cpu_to_le32(1L<<27))
 
 #endif /* _NCP_NO */
diff --git a/include/linux/net.h b/include/linux/net.h
index 22daf7858..af490821b 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -21,6 +21,7 @@
 #include <linux/config.h>
 #include <linux/wait.h>
 #include <linux/stringify.h>
+#include <asm/socket.h>
 
 struct poll_table_struct;
 struct inode;
@@ -63,6 +64,34 @@ typedef enum {
 #define SOCK_PASS_CRED		16
 #define SOCK_USER_SOCKET	17
 
+#ifndef ARCH_HAS_SOCKET_TYPES
+/** sock_type - Socket types
+ * 
+ * When adding some new socket type please
+ * grep ARCH_HAS_SOCKET_TYPE include/asm-* /socket.h, at least MIPS
+ * overrides this enum for binary compat reasons.
+ * 
+ * @SOCK_STREAM - stream (connection) socket
+ * @SOCK_DGRAM - datagram (conn.less) socket
+ * @SOCK_RAW - raw socket
+ * @SOCK_RDM - reliably-delivered message
+ * @SOCK_SEQPACKET - sequential packet socket 
+ * @SOCK_PACKET - linux specific way of getting packets at the dev level.
+ *		  For writing rarp and other similar things on the user level.
+ */
+enum sock_type {
+	SOCK_STREAM	= 1,
+	SOCK_DGRAM	= 2,
+	SOCK_RAW	= 3,
+	SOCK_RDM	= 4,
+	SOCK_SEQPACKET	= 5,
+	SOCK_PACKET	= 10,
+};
+
+#define SOCK_MAX (SOCK_PACKET + 1)
+
+#endif /* ARCH_HAS_SOCKET_TYPES */
+
 /**
  *  struct socket - general BSD socket
  *  @state - socket state (%SS_CONNECTED, etc)
@@ -170,6 +199,7 @@ extern struct socket *sockfd_lookup(int fd, int *err);
 extern int	     net_ratelimit(void);
 extern unsigned long net_random(void);
 extern void	     net_srandom(unsigned long);
+extern void	     net_random_init(void);
 
 extern int   	     kernel_sendmsg(struct socket *sock, struct msghdr *msg,
 				    struct kvec *vec, size_t num, size_t len);
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 5edb93f16..8325475d6 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -73,6 +73,11 @@ struct ethtool_ops;
 
 #define MAX_ADDR_LEN	32		/* Largest hardware address length */
 
+/* Driver transmit return codes */
+#define NETDEV_TX_OK 0		/* driver took care of packet */
+#define NETDEV_TX_BUSY 1	/* driver tx path was busy*/
+#define NETDEV_TX_LOCKED -1	/* driver tx lock was already taken */
+
 /*
  *	Compute the worst case header length according to the protocols
  *	used.
@@ -462,7 +467,7 @@ struct net_device
 						     unsigned char *haddr);
 	int			(*neigh_setup)(struct net_device *dev, struct neigh_parms *);
 	int			(*accept_fastpath)(struct net_device *, struct dst_entry*);
-#ifdef CONFIG_NETPOLL_RX
+#ifdef CONFIG_NETPOLL
 	int			netpoll_rx;
 #endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -479,7 +484,6 @@ struct net_device
 
 	/* class/net/name entry */
 	struct class_device	class_dev;
-	struct net_device_stats* (*last_stats)(struct net_device *);
 	/* how much padding had been added by alloc_netdev() */
 	int padded;
 };
@@ -677,6 +681,7 @@ 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_set_mtu(struct net_device *, int);
 extern void		dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev);
 
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 83f966865..a9357be1a 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -178,7 +178,7 @@ extern inline struct ip6t_target *
 ip6t_find_target_lock(const char *name, int *error, struct semaphore *mutex);
 extern inline struct arpt_target *
 arpt_find_target_lock(const char *name, int *error, struct semaphore *mutex);
-extern void (*ip_ct_attach)(struct sk_buff *, struct nf_ct_info *);
+extern void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *);
 
 #ifdef CONFIG_NETFILTER_DEBUG
 extern void nf_dump_skb(int pf, struct sk_buff *skb);
diff --git a/include/linux/netfilter_bridge/ebt_802_3.h b/include/linux/netfilter_bridge/ebt_802_3.h
index b3d6c3219..b9f712c14 100644
--- a/include/linux/netfilter_bridge/ebt_802_3.h
+++ b/include/linux/netfilter_bridge/ebt_802_3.h
@@ -49,6 +49,15 @@ struct ebt_802_3_hdr {
 	} llc;
 };
 
+#ifdef __KERNEL__
+#include <linux/skbuff.h>
+
+static inline struct ebt_802_3_hdr *ebt_802_3_hdr(const struct sk_buff *skb)
+{
+	return (struct ebt_802_3_hdr *)skb->mac.raw;
+}
+#endif
+
 struct ebt_802_3_info 
 {
 	uint8_t  sap;
diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
index 1974f162f..989f1cf75 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h
@@ -51,10 +51,12 @@ enum ip_conntrack_status {
 
 #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
 #include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
+#include <linux/netfilter_ipv4/ip_conntrack_sctp.h>
 
 /* per conntrack: protocol private data */
 union ip_conntrack_proto {
 	/* insert conntrack proto private data here */
+	struct ip_ct_sctp sctp;
 	struct ip_ct_tcp tcp;
 	struct ip_ct_icmp icmp;
 };
@@ -156,6 +158,12 @@ struct ip_conntrack_expect
 	union ip_conntrack_expect_help help;
 };
 
+struct ip_conntrack_counter
+{
+	u_int64_t packets;
+	u_int64_t bytes;
+};
+
 struct ip_conntrack_helper;
 
 struct ip_conntrack
@@ -164,15 +172,17 @@ struct ip_conntrack
            plus 1 for any connection(s) we are `master' for */
 	struct nf_conntrack ct_general;
 
-	/* These are my tuples; original and reply */
-	struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
-
 	/* Have we seen traffic both ways yet? (bitset) */
 	unsigned long status;
 
 	/* Timer function; drops refcnt when it goes off. */
 	struct timer_list timeout;
 
+#ifdef CONFIG_IP_NF_CT_ACCT
+	/* Accounting Information (same cache line as other written members) */
+	struct ip_conntrack_counter counters[IP_CT_DIR_MAX];
+#endif
+
 	/* If we're expecting another related connection, this will be
            in expected linked list */
 	struct list_head sibling_list;
@@ -186,12 +196,7 @@ struct ip_conntrack
 	/* Helper, if any. */
 	struct ip_conntrack_helper *helper;
 
-	/* Our various nf_ct_info structs specify *what* relation this
-           packet has to the conntrack */
-	struct nf_ct_info infos[IP_CT_NUMBER];
-
 	/* Storage reserved for other modules: */
-
 	union ip_conntrack_proto proto;
 
 	union ip_conntrack_help help;
@@ -207,6 +212,9 @@ struct ip_conntrack
 	} nat;
 #endif /* CONFIG_IP_NF_NAT_NEEDED */
 
+	/* Traversed often, so hopefully in different cacheline to top */
+	/* These are my tuples; original and reply */
+	struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
 };
 
 /* get master conntrack via master expectation */
@@ -225,8 +233,12 @@ ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple,
 			 const struct ip_conntrack *ignored_conntrack);
 
 /* Return conntrack_info and tuple hash for given skb. */
-extern struct ip_conntrack *
-ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo);
+static inline struct ip_conntrack *
+ip_conntrack_get(const struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
+{
+	*ctinfo = skb->nfctinfo;
+	return (struct ip_conntrack *)skb->nfct;
+}
 
 /* decrement reference count on a conntrack */
 extern inline void ip_conntrack_put(struct ip_conntrack *ct);
@@ -245,16 +257,24 @@ extern int invert_tuplepr(struct ip_conntrack_tuple *inverse,
 			  const struct ip_conntrack_tuple *orig);
 
 /* Refresh conntrack for this many jiffies */
-extern void ip_ct_refresh(struct ip_conntrack *ct,
-			  unsigned long extra_jiffies);
+extern void ip_ct_refresh_acct(struct ip_conntrack *ct,
+			       enum ip_conntrack_info ctinfo,
+			       const struct sk_buff *skb,
+			       unsigned long extra_jiffies);
 
 /* These are for NAT.  Icky. */
+/* Update TCP window tracking data when NAT mangles the packet */
+extern int ip_conntrack_tcp_update(struct sk_buff *skb,
+				   struct ip_conntrack *conntrack,
+				   int dir);
+
 /* Call me when a conntrack is destroyed. */
 extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack);
 
 /* Fake conntrack entry for untracked connections */
 extern struct ip_conntrack ip_conntrack_untracked;
 
+extern int ip_ct_no_defrag;
 /* Returns new sk_buff, or NULL */
 struct sk_buff *
 ip_ct_gather_frags(struct sk_buff *skb);
@@ -271,6 +291,27 @@ static inline int is_confirmed(struct ip_conntrack *ct)
 }
 
 extern unsigned int ip_conntrack_htable_size;
+ 
+struct ip_conntrack_stat
+{
+	unsigned int searched;
+	unsigned int found;
+	unsigned int new;
+	unsigned int invalid;
+	unsigned int ignore;
+	unsigned int delete;
+	unsigned int delete_list;
+	unsigned int insert;
+	unsigned int insert_failed;
+	unsigned int drop;
+	unsigned int early_drop;
+	unsigned int error;
+	unsigned int expect_new;
+	unsigned int expect_create;
+	unsigned int expect_delete;
+};
+
+#define CONNTRACK_STAT_INC(count) (__get_cpu_var(ip_conntrack_stat).count++)
 
 /* eg. PROVIDES_CONNTRACK(ftp); */
 #define PROVIDES_CONNTRACK(name)                        \
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_core.h b/include/linux/netfilter_ipv4/ip_conntrack_core.h
index 4c8b5d189..bb9b11c68 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_core.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_core.h
@@ -16,34 +16,32 @@ extern int ip_conntrack_init(void);
 extern void ip_conntrack_cleanup(void);
 
 struct ip_conntrack_protocol;
-extern struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol);
-/* Like above, but you already have conntrack read lock. */
-extern struct ip_conntrack_protocol *__ip_ct_find_proto(u_int8_t protocol);
-extern struct list_head protocol_list;
-
-/* Returns conntrack if it dealt with ICMP, and filled in skb->nfct */
-extern struct ip_conntrack *icmp_error_track(struct sk_buff *skb,
-					     enum ip_conntrack_info *ctinfo,
-					     unsigned int hooknum);
-extern int get_tuple(const struct iphdr *iph,
-		     const struct sk_buff *skb,
-		     unsigned int dataoff,
-		     struct ip_conntrack_tuple *tuple,
-		     const struct ip_conntrack_protocol *protocol);
+
+extern int
+ip_ct_get_tuple(const struct iphdr *iph,
+		const struct sk_buff *skb,
+		unsigned int dataoff,
+		struct ip_conntrack_tuple *tuple,
+		const struct ip_conntrack_protocol *protocol);
+
+extern int
+ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse,
+		   const struct ip_conntrack_tuple *orig,
+		   const struct ip_conntrack_protocol *protocol);
 
 /* Find a connection corresponding to a tuple. */
 struct ip_conntrack_tuple_hash *
 ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
 		      const struct ip_conntrack *ignored_conntrack);
 
-extern int __ip_conntrack_confirm(struct nf_ct_info *nfct);
+extern int __ip_conntrack_confirm(struct sk_buff *skb);
 
 /* Confirm a connection: returns NF_DROP if packet must be dropped. */
 static inline int ip_conntrack_confirm(struct sk_buff *skb)
 {
 	if (skb->nfct
-	    && !is_confirmed((struct ip_conntrack *)skb->nfct->master))
-		return __ip_conntrack_confirm(skb->nfct);
+	    && !is_confirmed((struct ip_conntrack *)skb->nfct))
+		return __ip_conntrack_confirm(skb);
 	return NF_ACCEPT;
 }
 
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_ftp.h b/include/linux/netfilter_ipv4/ip_conntrack_ftp.h
index 677db49e2..2f85006c7 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_ftp.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_ftp.h
@@ -4,11 +4,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/netfilter_ipv4/lockhelp.h>
-
-/* Protects ftp part of conntracks */
-DECLARE_LOCK_EXTERN(ip_ftp_lock);
-
 #define FTP_PORT	21
 
 #endif /* __KERNEL__ */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_irc.h b/include/linux/netfilter_ipv4/ip_conntrack_irc.h
index 170248fa8..0cd24a02d 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_irc.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_irc.h
@@ -33,13 +33,8 @@ struct ip_ct_irc_master {
 
 #ifdef __KERNEL__
 
-#include <linux/netfilter_ipv4/lockhelp.h>
-
 #define IRC_PORT	6667
 
-/* Protects irc part of conntracks */
-DECLARE_LOCK_EXTERN(ip_irc_lock);
-
 #endif /* __KERNEL__ */
 
 #endif /* _IP_CONNTRACK_IRC_H */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_protocol.h b/include/linux/netfilter_ipv4/ip_conntrack_protocol.h
index 56e37ef25..0ff067b3f 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_protocol.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_protocol.h
@@ -3,11 +3,10 @@
 #define _IP_CONNTRACK_PROTOCOL_H
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 
+struct seq_file;
+
 struct ip_conntrack_protocol
 {
-	/* Next pointer. */
-	struct list_head list;
-
 	/* Protocol number. */
 	u_int8_t proto;
 
@@ -26,13 +25,12 @@ struct ip_conntrack_protocol
 	int (*invert_tuple)(struct ip_conntrack_tuple *inverse,
 			    const struct ip_conntrack_tuple *orig);
 
-	/* Print out the per-protocol part of the tuple. */
-	unsigned int (*print_tuple)(char *buffer,
-				    const struct ip_conntrack_tuple *);
+	/* Print out the per-protocol part of the tuple. Return like seq_* */
+	int (*print_tuple)(struct seq_file *,
+			   const struct ip_conntrack_tuple *);
 
 	/* Print out the private part of the conntrack. */
-	unsigned int (*print_conntrack)(char *buffer,
-					const struct ip_conntrack *);
+	int (*print_conntrack)(struct seq_file *, const struct ip_conntrack *);
 
 	/* Returns verdict for packet, or -1 for invalid. */
 	int (*packet)(struct ip_conntrack *conntrack,
@@ -50,17 +48,46 @@ struct ip_conntrack_protocol
 	int (*exp_matches_pkt)(struct ip_conntrack_expect *exp,
 			       const struct sk_buff *skb);
 
+	int (*error)(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
+		     unsigned int hooknum);
+
 	/* Module (if any) which this is connected to. */
 	struct module *me;
 };
 
+#define MAX_IP_CT_PROTO 256
+extern struct ip_conntrack_protocol *ip_ct_protos[MAX_IP_CT_PROTO];
+
 /* Protocol registration. */
 extern int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto);
 extern void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto);
 
+static inline struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol)
+{
+	return ip_ct_protos[protocol];
+}
+
 /* Existing built-in protocols */
 extern struct ip_conntrack_protocol ip_conntrack_protocol_tcp;
 extern struct ip_conntrack_protocol ip_conntrack_protocol_udp;
 extern struct ip_conntrack_protocol ip_conntrack_protocol_icmp;
+extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
 extern int ip_conntrack_protocol_tcp_init(void);
+
+/* Log invalid packets */
+extern unsigned int ip_ct_log_invalid;
+
+#ifdef CONFIG_SYSCTL
+#ifdef DEBUG_INVALID_PACKETS
+#define LOG_INVALID(proto) \
+	(ip_ct_log_invalid == (proto) || ip_ct_log_invalid == IPPROTO_RAW)
+#else
+#define LOG_INVALID(proto) \
+	((ip_ct_log_invalid == (proto) || ip_ct_log_invalid == IPPROTO_RAW) \
+	 && net_ratelimit())
+#endif
+#else
+#define LOG_INVALID(proto) 0
+#endif /* CONFIG_SYSCTL */
+
 #endif /*_IP_CONNTRACK_PROTOCOL_H*/
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_tcp.h b/include/linux/netfilter_ipv4/ip_conntrack_tcp.h
index d6698c911..0ab4590a0 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_tcp.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_tcp.h
@@ -4,25 +4,44 @@
 
 enum tcp_conntrack {
 	TCP_CONNTRACK_NONE,
-	TCP_CONNTRACK_ESTABLISHED,
 	TCP_CONNTRACK_SYN_SENT,
 	TCP_CONNTRACK_SYN_RECV,
+	TCP_CONNTRACK_ESTABLISHED,
 	TCP_CONNTRACK_FIN_WAIT,
-	TCP_CONNTRACK_TIME_WAIT,
-	TCP_CONNTRACK_CLOSE,
 	TCP_CONNTRACK_CLOSE_WAIT,
 	TCP_CONNTRACK_LAST_ACK,
+	TCP_CONNTRACK_TIME_WAIT,
+	TCP_CONNTRACK_CLOSE,
 	TCP_CONNTRACK_LISTEN,
-	TCP_CONNTRACK_MAX
+	TCP_CONNTRACK_MAX,
+	TCP_CONNTRACK_IGNORE
+};
+
+/* Window scaling is advertised by the sender */
+#define IP_CT_TCP_STATE_FLAG_WINDOW_SCALE	0x01
+
+/* SACK is permitted by the sender */
+#define IP_CT_TCP_FLAG_SACK_PERM		0x02
+
+struct ip_ct_tcp_state {
+	u_int32_t	td_end;		/* max of seq + len */
+	u_int32_t	td_maxend;	/* max of ack + max(win, 1) */
+	u_int32_t	td_maxwin;	/* max(win) */
+	u_int8_t	td_scale;	/* window scale factor */
+	u_int8_t	loose;		/* used when connection picked up from the middle */
+	u_int8_t	flags;		/* per direction state flags */
 };
 
 struct ip_ct_tcp
 {
-	enum tcp_conntrack state;
-
-	/* Poor man's window tracking: sequence number of valid ACK
-           handshake completion packet */
-	u_int32_t handshake_ack;
+	struct ip_ct_tcp_state seen[2];	/* connection parameters per direction */
+	u_int8_t	state;		/* state of the connection (enum tcp_conntrack) */
+	/* For detecting stale connections */
+	u_int8_t	last_dir;	/* Direction of the last packet (enum ip_conntrack_dir) */
+	u_int8_t	retrans;	/* Number of retransmitted packets */
+	u_int8_t	last_index;	/* Index of the last packet */
+	u_int32_t	last_seq;	/* Last sequence number seen in dir */
+	u_int32_t	last_end;	/* Last seq + len */
 };
 
 #endif /* _IP_CONNTRACK_TCP_H */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
index 1e7691189..3a71176e2 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
@@ -25,6 +25,9 @@ union ip_conntrack_manip_proto
 	struct {
 		u_int16_t id;
 	} icmp;
+	struct {
+		u_int16_t port;
+	} sctp;
 };
 
 /* The manipulable part of the tuple. */
@@ -55,6 +58,9 @@ struct ip_conntrack_tuple
 			struct {
 				u_int8_t type, code;
 			} icmp;
+			struct {
+				u_int16_t port;
+			} sctp;
 		} u;
 
 		/* The protocol. */
diff --git a/include/linux/netfilter_ipv4/ip_nat.h b/include/linux/netfilter_ipv4/ip_nat.h
index 1a4e46b2d..c4a362260 100644
--- a/include/linux/netfilter_ipv4/ip_nat.h
+++ b/include/linux/netfilter_ipv4/ip_nat.h
@@ -80,27 +80,18 @@ struct ip_nat_info_manip
 /* Protects NAT hash tables, and NAT-private part of conntracks. */
 DECLARE_RWLOCK_EXTERN(ip_nat_lock);
 
-/* Hashes for by-source and IP/protocol. */
-struct ip_nat_hash
-{
-	struct list_head list;
-
-	/* conntrack we're embedded in: NULL if not in hash. */
-	struct ip_conntrack *conntrack;
-};
-
 /* The structure embedded in the conntrack structure. */
 struct ip_nat_info
 {
 	/* Set to zero when conntrack created: bitmask of maniptypes */
-	int initialized;
+	u_int16_t initialized;
 
-	unsigned int num_manips;
+	u_int16_t num_manips;
 
 	/* Manipulations to be done on this conntrack. */
 	struct ip_nat_info_manip manips[IP_NAT_MAX_MANIPS];
 
-	struct ip_nat_hash bysource, byipsproto;
+	struct list_head bysource, byipsproto;
 
 	/* Helper (NULL if none). */
 	struct ip_nat_helper *helper;
diff --git a/include/linux/netfilter_ipv4/ip_nat_core.h b/include/linux/netfilter_ipv4/ip_nat_core.h
index a8bcdc987..4f01f882f 100644
--- a/include/linux/netfilter_ipv4/ip_nat_core.h
+++ b/include/linux/netfilter_ipv4/ip_nat_core.h
@@ -14,8 +14,6 @@ extern unsigned int do_bindings(struct ip_conntrack *ct,
 				unsigned int hooknum,
 				struct sk_buff **pskb);
 
-extern struct list_head protos;
-
 extern int icmp_reply_translation(struct sk_buff **pskb,
 				  struct ip_conntrack *conntrack,
 				  unsigned int hooknum,
@@ -26,8 +24,4 @@ extern void replace_in_hashes(struct ip_conntrack *conntrack,
 extern void place_in_hashes(struct ip_conntrack *conntrack,
 			    struct ip_nat_info *info);
 
-/* Built-in protocols. */
-extern struct ip_nat_protocol ip_nat_protocol_tcp;
-extern struct ip_nat_protocol ip_nat_protocol_udp;
-extern struct ip_nat_protocol ip_nat_protocol_icmp;
 #endif /* _IP_NAT_CORE_H */
diff --git a/include/linux/netfilter_ipv4/ip_nat_helper.h b/include/linux/netfilter_ipv4/ip_nat_helper.h
index 185a24a6a..b34e4ce9e 100644
--- a/include/linux/netfilter_ipv4/ip_nat_helper.h
+++ b/include/linux/netfilter_ipv4/ip_nat_helper.h
@@ -38,11 +38,15 @@ struct ip_nat_helper
 			       struct ip_nat_info *info);
 };
 
-extern struct list_head helpers;
-
 extern int ip_nat_helper_register(struct ip_nat_helper *me);
 extern void ip_nat_helper_unregister(struct ip_nat_helper *me);
 
+extern struct ip_nat_helper *
+ip_nat_find_helper(const struct ip_conntrack_tuple *tuple);
+
+extern struct ip_nat_helper *
+__ip_nat_find_helper(const struct ip_conntrack_tuple *tuple);
+
 /* These return true or false. */
 extern int ip_nat_mangle_tcp_packet(struct sk_buff **skb,
 				struct ip_conntrack *ct,
diff --git a/include/linux/netfilter_ipv4/ip_nat_protocol.h b/include/linux/netfilter_ipv4/ip_nat_protocol.h
index 998ab2bd3..e81795806 100644
--- a/include/linux/netfilter_ipv4/ip_nat_protocol.h
+++ b/include/linux/netfilter_ipv4/ip_nat_protocol.h
@@ -9,8 +9,6 @@ struct ip_nat_range;
 
 struct ip_nat_protocol
 {
-	struct list_head list;
-
 	/* Protocol name */
 	const char *name;
 
@@ -47,10 +45,24 @@ struct ip_nat_protocol
 				    const struct ip_nat_range *range);
 };
 
+#define MAX_IP_NAT_PROTO 256
+extern struct ip_nat_protocol *ip_nat_protos[MAX_IP_NAT_PROTO];
+
 /* Protocol registration. */
 extern int ip_nat_protocol_register(struct ip_nat_protocol *proto);
 extern void ip_nat_protocol_unregister(struct ip_nat_protocol *proto);
 
+static inline struct ip_nat_protocol *ip_nat_find_proto(u_int8_t protocol)
+{
+	return ip_nat_protos[protocol];
+}
+
+/* Built-in protocols. */
+extern struct ip_nat_protocol ip_nat_protocol_tcp;
+extern struct ip_nat_protocol ip_nat_protocol_udp;
+extern struct ip_nat_protocol ip_nat_protocol_icmp;
+extern struct ip_nat_protocol ip_nat_unknown_protocol;
+
 extern int init_protocols(void) __init;
 extern void cleanup_protocols(void);
 extern struct ip_nat_protocol *find_nat_proto(u_int16_t protonum);
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index b4c2b2b38..02a006f17 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -336,7 +336,6 @@ ipt_get_target(struct ipt_entry *e)
  *	Main firewall chains definitions and global var's definitions.
  */
 #ifdef __KERNEL__
-static DECLARE_MUTEX(ipt_mutex);
 
 #include <linux/init.h>
 extern void ipt_init(void) __init;
diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h
index ad7d8a4e0..bee7a5ec7 100644
--- a/include/linux/netfilter_ipv6.h
+++ b/include/linux/netfilter_ipv6.h
@@ -58,8 +58,10 @@ enum nf_ip6_hook_priorities {
 	NF_IP6_PRI_FIRST = INT_MIN,
 	NF_IP6_PRI_SELINUX_FIRST = -225,
 	NF_IP6_PRI_CONNTRACK = -200,
+	NF_IP6_PRI_BRIDGE_SABOTAGE_FORWARD = -175,
 	NF_IP6_PRI_MANGLE = -150,
 	NF_IP6_PRI_NAT_DST = -100,
+	NF_IP6_PRI_BRIDGE_SABOTAGE_LOCAL_OUT = -50,
 	NF_IP6_PRI_FILTER = 0,
 	NF_IP6_PRI_NAT_SRC = 100,
 	NF_IP6_PRI_SELINUX_LAST = 225,
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index f9983d16c..6f70cf3df 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -107,10 +107,6 @@ struct ip6t_counters
 	u_int64_t pcnt, bcnt;			/* Packet and byte counters */
 };
 
-#ifdef __KERNEL__
-static DECLARE_MUTEX(ip6t_mutex);
-#endif
-
 /* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */
 #define IP6T_F_PROTO		0x01	/* Set if rule cares about upper 
 					   protocols */
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index 670558170..01864a8fd 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -99,6 +99,7 @@ enum {
 #ifdef __KERNEL__
 
 #include <linux/capability.h>
+#include <linux/skbuff.h>
 
 struct netlink_skb_parms
 {
@@ -133,13 +134,6 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long t
 void netlink_detachskb(struct sock *sk, struct sk_buff *skb);
 int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol);
 
-/* finegrained unicast helpers: */
-struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid);
-struct sock *netlink_getsockbyfilp(struct file *filp);
-int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long timeo);
-void netlink_detachskb(struct sock *sk, struct sk_buff *skb);
-int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol);
-
 /*
  *	skb should fit one page. This choice is good for headerless malloc.
  *
diff --git a/include/linux/nfs.h b/include/linux/nfs.h
index b30265f03..ca2ffa6ae 100644
--- a/include/linux/nfs.h
+++ b/include/linux/nfs.h
@@ -8,6 +8,7 @@
 #define _LINUX_NFS_H
 
 #include <linux/sunrpc/msg_prot.h>
+#include <linux/string.h>
 
 #define NFS_PROGRAM	100003
 #define NFS_PORT	2049
@@ -138,6 +139,22 @@ struct nfs_fh {
 	unsigned char		data[NFS_MAXFHSIZE];
 };
 
+/*
+ * Returns a zero iff the size and data fields match.
+ * Checks only "size" bytes in the data field.
+ */
+static inline int nfs_compare_fh(const struct nfs_fh *a, const struct nfs_fh *b)
+{
+	return a->size != b->size || memcmp(a->data, b->data, a->size) != 0;
+}
+
+static inline void nfs_copy_fh(struct nfs_fh *target, const struct nfs_fh *source)
+{
+	target->size = source->size;
+	memcpy(target->data, source->data, source->size);
+}
+
+
 /*
  * This is really a general kernel constant, but since nothing like
  * this is defined in the kernel headers, I have to do it here.
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index 89da81cca..96974ab10 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -13,8 +13,12 @@
 #ifndef _LINUX_NFS4_H
 #define _LINUX_NFS4_H
 
+#include <linux/types.h>
+#include <linux/list.h>
+
 #define NFS4_VERIFIER_SIZE	8
 #define NFS4_FHSIZE		128
+#define NFS4_MAXPATHLEN		PATH_MAX
 #define NFS4_MAXNAMLEN		NAME_MAX
 
 #define NFS4_ACCESS_READ        0x0001
@@ -52,6 +56,60 @@
 #define ACL4_SUPPORT_AUDIT_ACL 0x04
 #define ACL4_SUPPORT_ALARM_ACL 0x08
 
+#define NFS4_ACE_FILE_INHERIT_ACE             0x00000001
+#define NFS4_ACE_DIRECTORY_INHERIT_ACE        0x00000002
+#define NFS4_ACE_NO_PROPAGATE_INHERIT_ACE     0x00000004
+#define NFS4_ACE_INHERIT_ONLY_ACE             0x00000008
+#define NFS4_ACE_SUCCESSFUL_ACCESS_ACE_FLAG   0x00000010
+#define NFS4_ACE_FAILED_ACCESS_ACE_FLAG       0x00000020
+#define NFS4_ACE_IDENTIFIER_GROUP             0x00000040
+#define NFS4_ACE_OWNER                        0x00000080
+#define NFS4_ACE_GROUP                        0x00000100
+#define NFS4_ACE_EVERYONE                     0x00000200
+
+#define NFS4_ACE_READ_DATA                    0x00000001
+#define NFS4_ACE_LIST_DIRECTORY               0x00000001
+#define NFS4_ACE_WRITE_DATA                   0x00000002
+#define NFS4_ACE_ADD_FILE                     0x00000002
+#define NFS4_ACE_APPEND_DATA                  0x00000004
+#define NFS4_ACE_ADD_SUBDIRECTORY             0x00000004
+#define NFS4_ACE_READ_NAMED_ATTRS             0x00000008
+#define NFS4_ACE_WRITE_NAMED_ATTRS            0x00000010
+#define NFS4_ACE_EXECUTE                      0x00000020
+#define NFS4_ACE_DELETE_CHILD                 0x00000040
+#define NFS4_ACE_READ_ATTRIBUTES              0x00000080
+#define NFS4_ACE_WRITE_ATTRIBUTES             0x00000100
+#define NFS4_ACE_DELETE                       0x00010000
+#define NFS4_ACE_READ_ACL                     0x00020000
+#define NFS4_ACE_WRITE_ACL                    0x00040000
+#define NFS4_ACE_WRITE_OWNER                  0x00080000
+#define NFS4_ACE_SYNCHRONIZE                  0x00100000
+#define NFS4_ACE_GENERIC_READ                 0x00120081
+#define NFS4_ACE_GENERIC_WRITE                0x00160106
+#define NFS4_ACE_GENERIC_EXECUTE              0x001200A0
+#define NFS4_ACE_MASK_ALL                     0x001F01FF
+
+enum nfs4_acl_whotype {
+	NFS4_ACL_WHO_NAMED = 0,
+	NFS4_ACL_WHO_OWNER,
+	NFS4_ACL_WHO_GROUP,
+	NFS4_ACL_WHO_EVERYONE,
+};
+
+struct nfs4_ace {
+	uint32_t	type;
+	uint32_t	flag;
+	uint32_t	access_mask;
+	int		whotype;
+	uid_t		who;
+	struct list_head l_ace;
+};
+
+struct nfs4_acl {
+	uint32_t	naces;
+	struct list_head ace_head;
+};
+
 typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
 typedef struct { char data[16]; } nfs4_stateid;
 
@@ -297,7 +355,7 @@ enum {
 	NFSPROC4_CLNT_COMMIT,
 	NFSPROC4_CLNT_OPEN,
 	NFSPROC4_CLNT_OPEN_CONFIRM,
-	NFSPROC4_CLNT_OPEN_RECLAIM,
+	NFSPROC4_CLNT_OPEN_NOATTR,
 	NFSPROC4_CLNT_OPEN_DOWNGRADE,
 	NFSPROC4_CLNT_CLOSE,
 	NFSPROC4_CLNT_SETATTR,
@@ -315,12 +373,14 @@ enum {
 	NFSPROC4_CLNT_REMOVE,
 	NFSPROC4_CLNT_RENAME,
 	NFSPROC4_CLNT_LINK,
+	NFSPROC4_CLNT_SYMLINK,
 	NFSPROC4_CLNT_CREATE,
 	NFSPROC4_CLNT_PATHCONF,
 	NFSPROC4_CLNT_STATFS,
 	NFSPROC4_CLNT_READLINK,
 	NFSPROC4_CLNT_READDIR,
 	NFSPROC4_CLNT_SERVER_CAPS,
+	NFSPROC4_CLNT_DELEGRETURN,
 };
 
 #endif
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 0fd3f8178..0ccc263aa 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -28,6 +28,7 @@
 #include <linux/nfs3.h>
 #include <linux/nfs4.h>
 #include <linux/nfs_xdr.h>
+#include <linux/rwsem.h>
 #include <linux/workqueue.h>
 
 /*
@@ -75,15 +76,33 @@
 #ifdef __KERNEL__
 
 /*
- * NFSv3 Access mode cache
+ * NFSv3/v4 Access mode cache entry
  */
-struct nfs_access_cache {
+struct nfs_access_entry {
 	unsigned long		jiffies;
 	struct rpc_cred *	cred;
 	int			mask;
-	int			err;
+};
+
+struct nfs4_state;
+struct nfs_open_context {
+	atomic_t count;
+	struct dentry *dentry;
+	struct rpc_cred *cred;
+	struct nfs4_state *state;
+	fl_owner_t lockowner;
+	int mode;
+	int error;
+
+	struct list_head list;
+	wait_queue_head_t waitq;
 };
 
+/*
+ * NFSv4 delegation
+ */
+struct nfs_delegation;
+
 /*
  * nfs fs inode data in memory
  */
@@ -137,7 +156,7 @@ struct nfs_inode {
 	 */
 	atomic_t		data_updates;
 
-	struct nfs_access_cache	cache_access;
+	struct nfs_access_entry	cache_access;
 
 	/*
 	 * This is the cookie verifier used for NFSv3 readdir
@@ -148,6 +167,7 @@ struct nfs_inode {
 	/*
 	 * 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;
@@ -156,14 +176,17 @@ struct nfs_inode {
 				ncommit,
 				npages;
 
-	/* Credentials for shared mmap */
-	struct rpc_cred		*mm_cred;
+	/* Open contexts for shared mmap writes */
+	struct list_head	open_files;
 
 	wait_queue_head_t	nfs_i_wait;
 
 #ifdef CONFIG_NFS_V4
         /* NFSv4 state */
 	struct list_head	open_states;
+	struct nfs_delegation	*delegation;
+	int			 delegation_state;
+	struct rw_semaphore	rwsem;
 #endif /* CONFIG_NFS_V4*/
 
 	struct inode		vfs_inode;
@@ -268,9 +291,12 @@ extern struct inode *nfs_fhget(struct super_block *, struct nfs_fh *,
 extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
 extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 extern int nfs_permission(struct inode *, int, struct nameidata *);
-extern void nfs_set_mmcred(struct inode *, struct rpc_cred *);
+extern int nfs_access_get_cached(struct inode *, struct rpc_cred *, struct nfs_access_entry *);
+extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *);
 extern int nfs_open(struct inode *, struct file *);
 extern int nfs_release(struct inode *, struct file *);
+extern int nfs_attribute_timeout(struct inode *inode);
+extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode);
 extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
 extern int nfs_setattr(struct dentry *, struct iattr *);
 extern void nfs_begin_attr_update(struct inode *);
@@ -278,6 +304,12 @@ extern void nfs_end_attr_update(struct inode *);
 extern void nfs_begin_data_update(struct inode *);
 extern void nfs_end_data_update(struct inode *);
 extern void nfs_end_data_update_defer(struct inode *);
+extern struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rpc_cred *cred);
+extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx);
+extern void put_nfs_open_context(struct nfs_open_context *ctx);
+extern void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx);
+extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, int mode);
+extern void nfs_file_clear_open_context(struct file *filp);
 
 /* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */
 extern u32 root_nfs_parse_addr(char *name); /*__init*/
@@ -289,16 +321,15 @@ extern struct inode_operations nfs_file_inode_operations;
 extern struct file_operations nfs_file_operations;
 extern struct address_space_operations nfs_file_aops;
 
-static __inline__ struct rpc_cred *
-nfs_file_cred(struct file *file)
+static inline struct rpc_cred *nfs_file_cred(struct file *file)
 {
-	struct rpc_cred *cred = NULL;
-	if (file)
-		cred = (struct rpc_cred *)file->private_data;
-#ifdef RPC_DEBUG
-	BUG_ON(cred && cred->cr_magic != RPCAUTH_CRED_MAGIC);
-#endif
-	return cred;
+	if (file != NULL) {
+		struct nfs_open_context *ctx;
+
+		ctx = (struct nfs_open_context*)file->private_data;
+		return ctx->cred;
+	}
+	return NULL;
 }
 
 /*
@@ -418,28 +449,6 @@ extern int  nfsroot_mount(struct sockaddr_in *, char *, struct nfs_fh *,
  * inline functions
  */
 
-static inline int nfs_attribute_timeout(struct inode *inode)
-{
-	struct nfs_inode *nfsi = NFS_I(inode);
-
-	return time_after(jiffies, nfsi->read_cache_jiffies+nfsi->attrtimeo);
-}
-
-/**
- * nfs_revalidate_inode - Revalidate the inode attributes
- * @server - pointer to nfs_server struct
- * @inode - pointer to inode struct
- *
- * Updates inode attribute information by retrieving the data from the server.
- */
-static inline int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
-{
-	if (!(NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))
-			&& !nfs_attribute_timeout(inode))
-		return NFS_STALE(inode) ? -ESTALE : 0;
-	return __nfs_revalidate_inode(server, inode);
-}
-
 static inline loff_t
 nfs_size_to_loff_t(__u64 size)
 {
@@ -507,8 +516,6 @@ struct idmap;
 
 enum nfs4_client_state {
 	NFS4CLNT_OK  = 0,
-	NFS4CLNT_NEW,
-	NFS4CLNT_SETUP_STATE,
 };
 
 /*
@@ -520,7 +527,6 @@ struct nfs4_client {
 	u64			cl_clientid;	/* constant */
 	nfs4_verifier		cl_confirm;
 	unsigned long		cl_state;
-	long			cl_generation;
 
 	u32			cl_lockowner_id;
 
@@ -530,6 +536,7 @@ struct nfs4_client {
 	 */
 	struct rw_semaphore	cl_sem;
 
+	struct list_head	cl_delegations;
 	struct list_head	cl_state_owners;
 	struct list_head	cl_unused;
 	int			cl_nunused;
@@ -573,12 +580,11 @@ struct nfs4_state_owner {
 	u32                  so_id;      /* 32-bit identifier, unique */
 	struct semaphore     so_sema;
 	u32                  so_seqid;   /* protected by so_sema */
-	unsigned int         so_flags;   /* protected by so_sema */
 	atomic_t	     so_count;
-	long		     so_generation;
 
 	struct rpc_cred	     *so_cred;	 /* Associated cred */
 	struct list_head     so_states;
+	struct list_head     so_delegations;
 };
 
 /*
@@ -596,7 +602,8 @@ struct nfs4_state_owner {
 struct nfs4_lock_state {
 	struct list_head	ls_locks;	/* Other lock stateids */
 	fl_owner_t		ls_owner;	/* POSIX lock owner */
-	struct nfs4_state *	ls_parent;	/* Parent nfs4_state */
+#define NFS_LOCK_INITIALIZED 1
+	int			ls_flags;
 	u32			ls_seqid;
 	u32			ls_id;
 	nfs4_stateid		ls_stateid;
@@ -606,6 +613,7 @@ struct nfs4_lock_state {
 /* bits for nfs4_state->flags */
 enum {
 	LK_STATE_IN_USE,
+	NFS_DELEGATED_STATE,
 };
 
 struct nfs4_state {
@@ -629,6 +637,11 @@ struct nfs4_state {
 };
 
 
+struct nfs4_exception {
+	long timeout;
+	int retry;
+};
+
 extern struct dentry_operations nfs4_dentry_operations;
 extern struct inode_operations nfs4_dir_inode_operations;
 
@@ -639,10 +652,12 @@ extern int nfs4_open_reclaim(struct nfs4_state_owner *, struct nfs4_state *);
 extern int nfs4_proc_async_renew(struct nfs4_client *);
 extern int nfs4_proc_renew(struct nfs4_client *);
 extern int nfs4_do_close(struct inode *, struct nfs4_state *);
-int nfs4_do_downgrade(struct inode *inode, struct nfs4_state *state, mode_t mode);
+extern int nfs4_do_downgrade(struct inode *inode, struct nfs4_state *state, mode_t mode);
 extern int nfs4_wait_clnt_recover(struct rpc_clnt *, struct nfs4_client *);
 extern struct inode *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
 extern int nfs4_open_revalidate(struct inode *, struct dentry *, int);
+extern int nfs4_handle_exception(struct nfs_server *, int, struct nfs4_exception *);
+extern int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request);
 
 /* nfs4renewd.c */
 extern void nfs4_schedule_state_renewal(struct nfs4_client *);
@@ -654,6 +669,8 @@ extern void init_nfsv4_state(struct nfs_server *);
 extern void destroy_nfsv4_state(struct nfs_server *);
 extern struct nfs4_client *nfs4_get_client(struct in_addr *);
 extern void nfs4_put_client(struct nfs4_client *clp);
+extern int nfs4_init_client(struct nfs4_client *clp);
+extern struct nfs4_client *nfs4_find_client(struct in_addr *);
 extern u32 nfs4_alloc_lockowner_id(struct nfs4_client *);
 
 extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
@@ -663,14 +680,13 @@ extern void nfs4_put_open_state(struct nfs4_state *);
 extern void nfs4_close_state(struct nfs4_state *, mode_t);
 extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode);
 extern void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp);
-extern int nfs4_handle_error(struct nfs_server *, int);
 extern void nfs4_schedule_state_recovery(struct nfs4_client *);
 extern struct nfs4_lock_state *nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t);
-extern struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t);
+extern struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t);
 extern void nfs4_put_lock_state(struct nfs4_lock_state *state);
 extern void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *ls);
-extern void nfs4_notify_setlk(struct inode *, struct file_lock *, struct nfs4_lock_state *);
-extern void nfs4_notify_unlck(struct inode *, struct file_lock *, struct nfs4_lock_state *);
+extern void nfs4_notify_setlk(struct nfs4_state *, struct file_lock *, struct nfs4_lock_state *);
+extern void nfs4_notify_unlck(struct nfs4_state *, struct file_lock *, struct nfs4_lock_state *);
 extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t);
 
 
@@ -681,6 +697,7 @@ struct nfs4_mount_data;
 #define destroy_nfsv4_state(server)       do { } while (0)
 #define nfs4_put_state_owner(inode, owner) do { } while (0)
 #define nfs4_put_open_state(state) do { } while (0)
+#define nfs4_close_state(a, b) do { } while (0)
 #define nfs4_renewd_prepare_shutdown(server) do { } while (0)
 #endif
 
@@ -697,6 +714,7 @@ struct nfs4_mount_data;
 #define NFSDBG_XDR		0x0020
 #define NFSDBG_FILE		0x0040
 #define NFSDBG_ROOT		0x0080
+#define NFSDBG_CALLBACK		0x0100
 #define NFSDBG_ALL		0xFFFF
 
 #ifdef __KERNEL__
diff --git a/include/linux/nfs_fs_i.h b/include/linux/nfs_fs_i.h
index 5a4fa8d54..e9a749588 100644
--- a/include/linux/nfs_fs_i.h
+++ b/include/linux/nfs_fs_i.h
@@ -5,13 +5,15 @@
 #include <linux/list.h>
 #include <linux/nfs.h>
 
+struct nlm_lockowner;
+
 /*
  * NFS lock info
  */
 struct nfs_lock_info {
 	u32		state;
 	u32		flags;
-	struct nlm_host	*host;
+	struct nlm_lockowner *owner;
 };
 
 /*
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 428355f8a..a43a38607 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -18,6 +18,7 @@ struct nfs_server {
 	unsigned int		rpages;		/* read size (in pages) */
 	unsigned int		wsize;		/* write size */
 	unsigned int		wpages;		/* write size (in pages) */
+	unsigned int		wtmult;		/* server disk block size */
 	unsigned int		dtsize;		/* readdir size */
 	unsigned int		bsize;		/* server block size */
 	unsigned int		acregmin;	/* attr cache timeouts */
diff --git a/include/linux/nfs_mount.h b/include/linux/nfs_mount.h
index 254fc0769..88e73274f 100644
--- a/include/linux/nfs_mount.h
+++ b/include/linux/nfs_mount.h
@@ -60,7 +60,7 @@ struct nfs_mount_data {
 #define NFS_MOUNT_BROKEN_SUID	0x0400	/* 4 */
 #define NFS_MOUNT_STRICTLOCK	0x1000	/* reserved for NFSv4 */
 #define NFS_MOUNT_SECFLAVOUR	0x2000	/* 5 */
-#define	NFS_MOUNT_TAGXID	0x8000	/* tagxid */
+#define NFS_MOUNT_TAGXID	0x8000	/* tagxid */
 #define NFS_MOUNT_FLAGMASK	0xFFFF
 
 #endif
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index 454587123..39e4895bc 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -29,19 +29,14 @@
 struct nfs_page {
 	struct list_head	wb_list,	/* Defines state of page: */
 				*wb_list_head;	/*      read/write/commit */
-	struct file		*wb_file;
-	fl_owner_t		wb_lockowner;
-	struct inode		*wb_inode;
-	struct rpc_cred		*wb_cred;
-	struct nfs4_state	*wb_state;
 	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 */
-	wait_queue_head_t	wb_wait;	/* wait queue */
 	unsigned long		wb_index;	/* Offset >> PAGE_CACHE_SHIFT */
 	unsigned int		wb_offset,	/* Offset & ~PAGE_CACHE_MASK */
 				wb_pgbase,	/* Start of page data */
-				wb_bytes,	/* Length of request */
-				wb_count;	/* reference count */
+				wb_bytes;	/* Length of request */
+	atomic_t		wb_count;	/* reference count */
 	unsigned long		wb_flags;
 	struct nfs_writeverf	wb_verf;	/* Commit cookie */
 };
@@ -50,9 +45,11 @@ struct nfs_page {
 #define NFS_NEED_COMMIT(req)	(test_bit(PG_NEED_COMMIT,&(req)->wb_flags))
 #define NFS_NEED_RESCHED(req)	(test_bit(PG_NEED_RESCHED,&(req)->wb_flags))
 
-extern	struct nfs_page *nfs_create_request(struct file *, struct inode *,
-					    struct page *,
-					    unsigned int, unsigned int);
+extern	struct nfs_page *nfs_create_request(struct nfs_open_context *ctx,
+					    struct inode *inode,
+					    struct page *page,
+					    unsigned int offset,
+					    unsigned int count);
 extern	void nfs_clear_request(struct nfs_page *req);
 extern	void nfs_release_request(struct nfs_page *req);
 
@@ -64,8 +61,7 @@ extern	int nfs_scan_list(struct list_head *, struct list_head *,
 extern	int nfs_coalesce_requests(struct list_head *, struct list_head *,
 				  unsigned int);
 extern  int nfs_wait_on_request(struct nfs_page *);
-
-extern	spinlock_t nfs_wreq_lock;
+extern	void nfs_unlock_request(struct nfs_page *req);
 
 /*
  * Lock the page of an asynchronous request without incrementing the wb_count
@@ -86,23 +82,10 @@ nfs_lock_request(struct nfs_page *req)
 {
 	if (test_and_set_bit(PG_BUSY, &req->wb_flags))
 		return 0;
-	req->wb_count++;
+	atomic_inc(&req->wb_count);
 	return 1;
 }
 
-static inline void
-nfs_unlock_request(struct nfs_page *req)
-{
-	if (!NFS_WBACK_BUSY(req)) {
-		printk(KERN_ERR "NFS: Invalid unlock attempted\n");
-		BUG();
-	}
-	smp_mb__before_clear_bit();
-	clear_bit(PG_BUSY, &req->wb_flags);
-	smp_mb__after_clear_bit();
-	wake_up_all(&req->wb_wait);
-	nfs_release_request(req);
-}
 
 /**
  * nfs_list_remove_request - Remove a request from its wb_list
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index f47e3c27a..f1402347c 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -99,20 +99,21 @@ struct nfs4_change_info {
  * Arguments to the open call.
  */
 struct nfs_openargs {
-	struct nfs_fh *         fh;
+	const struct nfs_fh *	fh;
 	__u32                   seqid;
-	__u32                   share_access;
+	int			open_flags;
 	__u64                   clientid;
 	__u32                   id;
-	__u32                   opentype;
-	__u32                   createmode;
 	union {
 		struct iattr *  attrs;    /* UNCHECKED, GUARDED */
 		nfs4_verifier   verifier; /* EXCLUSIVE */
+		nfs4_stateid	delegation;		/* CLAIM_DELEGATE_CUR */
+		int		delegation_type;	/* CLAIM_PREVIOUS */
 	} u;
 	const struct qstr *	name;
 	const struct nfs_server *server;	 /* Needed for ID mapping */
 	const u32 *		bitmask;
+	__u32			claim;
 };
 
 struct nfs_openres {
@@ -122,13 +123,17 @@ struct nfs_openres {
 	__u32                   rflags;
 	struct nfs_fattr *      f_attr;
 	const struct nfs_server *server;
+	int			delegation_type;
+	nfs4_stateid		delegation;
+	__u32			do_recall;
+	__u64			maxsize;
 };
 
 /*
  * Arguments to the open_confirm call.
  */
 struct nfs_open_confirmargs {
-	struct nfs_fh *         fh;
+	const struct nfs_fh *	fh;
 	nfs4_stateid            stateid;
 	__u32                   seqid;
 };
@@ -137,19 +142,6 @@ struct nfs_open_confirmres {
 	nfs4_stateid            stateid;
 };
 
-/*
- * Arguments to the open_reclaim call.
- */
-struct nfs_open_reclaimargs {
-	struct nfs_fh *		fh;
-	__u64			clientid;
-	__u32			seqid;
-	__u32			id;
-	__u32			share_access;
-	__u32			claim;
-	const __u32 *		bitmask;
-};
-
 /*
  * Arguments to the close call.
  */
@@ -157,7 +149,7 @@ struct nfs_closeargs {
 	struct nfs_fh *         fh;
 	nfs4_stateid            stateid;
 	__u32                   seqid;
-	__u32			share_access;
+	int			open_flags;
 };
 
 struct nfs_closeres {
@@ -224,6 +216,11 @@ struct nfs_lockres {
 	const struct nfs_server *	server;
 };
 
+struct nfs4_delegreturnargs {
+	const struct nfs_fh *fhandle;
+	const nfs4_stateid *stateid;
+};
+
 /*
  * Arguments to the read call.
  */
@@ -235,8 +232,7 @@ struct nfs_lockres {
 
 struct nfs_readargs {
 	struct nfs_fh *		fh;
-	fl_owner_t		lockowner;
-	struct nfs4_state *	state;
+	struct nfs_open_context *context;
 	__u64			offset;
 	__u32			count;
 	unsigned int		pgbase;
@@ -259,8 +255,7 @@ struct nfs_readres {
 
 struct nfs_writeargs {
 	struct nfs_fh *		fh;
-	fl_owner_t		lockowner;
-	struct nfs4_state *	state;
+	struct nfs_open_context *context;
 	__u64			offset;
 	__u32			count;
 	enum nfs3_stable_how	stable;
@@ -366,7 +361,8 @@ struct nfs_diropok {
 
 struct nfs_readlinkargs {
 	struct nfs_fh *		fh;
-	unsigned int		count;
+	unsigned int		pgbase;
+	unsigned int		pglen;
 	struct page **		pages;
 };
 
@@ -460,7 +456,8 @@ struct nfs3_accessres {
 
 struct nfs3_readlinkargs {
 	struct nfs_fh *		fh;
-	unsigned int		count;
+	unsigned int		pgbase;
+	unsigned int		pglen;
 	struct page **		pages;
 };
 
@@ -575,7 +572,8 @@ struct nfs4_readdir_res {
 
 struct nfs4_readlink {
 	const struct nfs_fh *		fh;
-	u32				count;   /* zero-copy data */
+	unsigned int			pgbase;
+	unsigned int			pglen;   /* zero-copy data */
 	struct page **			pages;   /* zero-copy data */
 };
 
@@ -597,13 +595,15 @@ struct nfs4_rename_res {
 };
 
 struct nfs4_setclientid {
-	nfs4_verifier			sc_verifier;      /* request */
-	char *				sc_name;	  /* request */
+	const nfs4_verifier *		sc_verifier;      /* request */
+	unsigned int			sc_name_len;
+	char				sc_name[32];	  /* request */
 	u32				sc_prog;          /* request */
+	unsigned int			sc_netid_len;
 	char				sc_netid[4];	  /* request */
+	unsigned int			sc_uaddr_len;
 	char				sc_uaddr[24];     /* request */
 	u32				sc_cb_ident;      /* request */
-	struct nfs4_client *		sc_state;	  /* response */
 };
 
 struct nfs4_statfs_arg {
@@ -657,6 +657,8 @@ struct nfs_write_data {
 	void (*complete) (struct nfs_write_data *, int);
 };
 
+struct nfs_access_entry;
+
 /*
  * RPC procedure vector for NFSv2/NFSv3 demuxing
  */
@@ -667,16 +669,18 @@ struct nfs_rpc_ops {
 
 	int	(*getroot) (struct nfs_server *, struct nfs_fh *,
 			    struct nfs_fsinfo *);
-	int	(*getattr) (struct inode *, struct nfs_fattr *);
+	int	(*getattr) (struct nfs_server *, struct nfs_fh *,
+			    struct nfs_fattr *);
 	int	(*setattr) (struct dentry *, struct nfs_fattr *,
 			    struct iattr *);
 	int	(*lookup)  (struct inode *, struct qstr *,
 			    struct nfs_fh *, struct nfs_fattr *);
-	int	(*access)  (struct inode *, struct rpc_cred *, int);
-	int	(*readlink)(struct inode *, struct page *);
-	int	(*read)    (struct nfs_read_data *, struct file *);
-	int	(*write)   (struct nfs_write_data *, struct file *);
-	int	(*commit)  (struct nfs_write_data *, struct file *);
+	int	(*access)  (struct inode *, struct nfs_access_entry *);
+	int	(*readlink)(struct inode *, struct page *, unsigned int,
+			    unsigned int);
+	int	(*read)    (struct nfs_read_data *);
+	int	(*write)   (struct nfs_write_data *);
+	int	(*commit)  (struct nfs_write_data *);
 	struct inode *	(*create)  (struct inode *, struct qstr *,
 			    struct iattr *, int);
 	int	(*remove)  (struct inode *, struct qstr *);
@@ -708,8 +712,6 @@ struct nfs_rpc_ops {
 	void	(*commit_setup) (struct nfs_write_data *, int how);
 	int	(*file_open)   (struct inode *, struct file *);
 	int	(*file_release) (struct inode *, struct file *);
-	void	(*request_init)(struct nfs_page *, struct file *);
-	int	(*request_compatible)(struct nfs_page *, struct file *, struct page *);
 	int	(*lock)(struct file *, int, struct file_lock *);
 };
 
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index 5757370b0..bf8143c8c 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -76,6 +76,11 @@ int		nfsd_lookup(struct svc_rqst *, struct svc_fh *,
 				const char *, int, struct svc_fh *);
 int		nfsd_setattr(struct svc_rqst *, struct svc_fh *,
 				struct iattr *, int, time_t);
+#ifdef CONFIG_NFSD_V4
+int             nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
+                    struct nfs4_acl *);
+int             nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
+#endif /* CONFIG_NFSD_V4 */
 int		nfsd_create(struct svc_rqst *, struct svc_fh *,
 				char *name, int len, struct iattr *attrs,
 				int type, dev_t rdev, struct svc_fh *res);
@@ -89,7 +94,7 @@ int		nfsd_commit(struct svc_rqst *, struct svc_fh *,
 				loff_t, unsigned long);
 #endif /* CONFIG_NFSD_V3 */
 int		nfsd_open(struct svc_rqst *, struct svc_fh *, int,
-				int, struct file *);
+				int, struct file **);
 void		nfsd_close(struct file *);
 int		nfsd_read(struct svc_rqst *, struct svc_fh *,
 				loff_t, struct kvec *,int, unsigned long *);
@@ -258,7 +263,6 @@ static inline int is_fsid(struct svc_fh *fh, struct knfsd_fh *reffh)
 
 /*
  * The following attributes are currently not supported by the NFSv4 server:
- *    ACL           (will be supported in a forthcoming patch)
  *    ARCHIVE       (deprecated anyway)
  *    FS_LOCATIONS  (will be supported eventually)
  *    HIDDEN        (unlikely to be supported any time soon)
@@ -278,7 +282,7 @@ static inline int is_fsid(struct svc_fh *fh, struct knfsd_fh *reffh)
  | FATTR4_WORD0_FILEHANDLE      | FATTR4_WORD0_FILEID       | FATTR4_WORD0_FILES_AVAIL      \
  | FATTR4_WORD0_FILES_FREE      | FATTR4_WORD0_FILES_TOTAL  | FATTR4_WORD0_HOMOGENEOUS      \
  | FATTR4_WORD0_MAXFILESIZE     | FATTR4_WORD0_MAXLINK      | FATTR4_WORD0_MAXNAME          \
- | FATTR4_WORD0_MAXREAD         | FATTR4_WORD0_MAXWRITE)
+ | FATTR4_WORD0_MAXREAD         | FATTR4_WORD0_MAXWRITE     | FATTR4_WORD0_ACL)
 
 #define NFSD_SUPPORTED_ATTRS_WORD1                                                          \
 (FATTR4_WORD1_MODE              | FATTR4_WORD1_NO_TRUNC     | FATTR4_WORD1_NUMLINKS         \
@@ -293,7 +297,8 @@ static inline int is_fsid(struct svc_fh *fh, struct knfsd_fh *reffh)
 (FATTR4_WORD1_TIME_ACCESS_SET   | FATTR4_WORD1_TIME_MODIFY_SET)
 
 /* These are the only attrs allowed in CREATE/OPEN/SETATTR. */
-#define NFSD_WRITEABLE_ATTRS_WORD0                            FATTR4_WORD0_SIZE
+#define NFSD_WRITEABLE_ATTRS_WORD0                                                          \
+(FATTR4_WORD0_SIZE              | FATTR4_WORD0_ACL                                         )
 #define NFSD_WRITEABLE_ATTRS_WORD1                                                          \
 (FATTR4_WORD1_MODE              | FATTR4_WORD1_OWNER         | FATTR4_WORD1_OWNER_GROUP     \
  | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_METADATA | FATTR4_WORD1_TIME_MODIFY_SET)
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index 32ffcd82d..97d84c887 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -218,7 +218,7 @@ struct nfs4_stateid {
 	struct nfs4_stateowner      * st_stateowner;
 	struct nfs4_file            * st_file;
 	stateid_t                     st_stateid;
-	struct file                   st_vfs_file;
+	struct file                 * st_vfs_file;
 	int                           st_vfs_set;
 	unsigned long                 st_access_bmap;
 	unsigned long                 st_deny_bmap;
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index ff18ed764..bf94561ca 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -39,6 +39,8 @@
 #ifndef _LINUX_NFSD_XDR4_H
 #define _LINUX_NFSD_XDR4_H
 
+#include <linux/nfs4.h>
+
 #define NFSD4_MAX_TAGLEN	128
 #define XDR_LEN(n)                     (((n) + 3) & ~3)
 
@@ -95,6 +97,7 @@ struct nfsd4_create {
 	u32		cr_bmval[2];        /* request */
 	struct iattr	cr_iattr;           /* request */
 	struct nfsd4_change_info  cr_cinfo; /* response */
+	struct nfs4_acl *cr_acl;
 };
 #define cr_linklen	u.link.namelen
 #define cr_linkname	u.link.name
@@ -216,7 +219,7 @@ struct nfsd4_open {
 	u32		op_rflags;          /* response */
 	int		op_truncate;        /* used during processing */
 	struct nfs4_stateowner *op_stateowner; /* used during processing */
-
+	struct nfs4_acl *op_acl;
 };
 #define op_iattr	u.iattr
 #define op_verf		u.verf
@@ -291,6 +294,7 @@ struct nfsd4_setattr {
 	stateid_t	sa_stateid;         /* request */
 	u32		sa_bmval[2];        /* request */
 	struct iattr	sa_iattr;           /* request */
+	struct nfs4_acl *sa_acl;
 };
 
 struct nfsd4_setclientid {
diff --git a/include/linux/nls.h b/include/linux/nls.h
index 1c657d4f0..816c04ad7 100644
--- a/include/linux/nls.h
+++ b/include/linux/nls.h
@@ -33,6 +33,31 @@ extern int utf8_mbstowcs(wchar_t *, const __u8 *, int);
 extern int utf8_wctomb(__u8 *, wchar_t, int);
 extern int utf8_wcstombs(__u8 *, const wchar_t *, int);
 
+static inline unsigned char nls_tolower(struct nls_table *t, unsigned char c)
+{
+	unsigned char nc = t->charset2lower[c];
+
+	return nc ? nc : c;
+}
+
+static inline unsigned char nls_toupper(struct nls_table *t, unsigned char c)
+{
+	unsigned char nc = t->charset2upper[c];
+
+	return nc ? nc : c;
+}
+
+static inline int nls_strnicmp(struct nls_table *t, const unsigned char *s1,
+		const unsigned char *s2, int len)
+{
+	while (len--) {
+		if (nls_tolower(t, *s1++) != nls_tolower(t, *s2++))
+			return 1;
+	}
+
+	return 0;
+}
+
 #define MODULE_ALIAS_NLS(name)	MODULE_ALIAS("nls_" __stringify(name))
 
 #endif /* _LINUX_NLS_H */
diff --git a/include/linux/node.h b/include/linux/node.h
index 6b8d64c16..6e0a697e5 100644
--- a/include/linux/node.h
+++ b/include/linux/node.h
@@ -23,7 +23,6 @@
 #include <linux/cpumask.h>
 
 struct node {
-	cpumask_t cpumap;	/* Bitmap of CPUs on the Node */
 	struct sys_device	sysdev;
 };
 
diff --git a/include/linux/notifier.h b/include/linux/notifier.h
index 5a8775b9e..900d43e88 100644
--- a/include/linux/notifier.h
+++ b/include/linux/notifier.h
@@ -29,6 +29,10 @@ extern int notifier_call_chain(struct notifier_block **n, unsigned long val, voi
 #define NOTIFY_OK		0x0001		/* Suits me */
 #define NOTIFY_STOP_MASK	0x8000		/* Don't call further */
 #define NOTIFY_BAD		(NOTIFY_STOP_MASK|0x0002)	/* Bad/Veto action	*/
+/*
+ * Clean way to return from the notifier and stop further calls.
+ */
+#define NOTIFY_STOP		(NOTIFY_OK|NOTIFY_STOP_MASK)
 
 /*
  *	Declared notifiers so far. I can imagine quite a few more chains
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index c6f5063f0..97325175d 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -69,14 +69,11 @@
 #define PG_private		12	/* Has something at ->private */
 #define PG_writeback		13	/* Page is under writeback */
 #define PG_nosave		14	/* Used for system suspend/resume */
-#define PG_maplock		15	/* Lock bit for rmap to ptes */
+#define PG_compound		15	/* Part of a compound page */
 
 #define PG_swapcache		16	/* Swap page: swp_entry_t in private */
 #define PG_mappedtodisk		17	/* Has blocks allocated on-disk */
 #define PG_reclaim		18	/* To be reclaimed asap */
-#define PG_compound		19	/* Part of a compound page */
-
-#define PG_anon			20	/* Anonymous: anon_vma in mapping */
 
 
 /*
@@ -236,6 +233,7 @@ extern unsigned long __read_page_state(unsigned offset);
 #define PageReserved(page)	test_bit(PG_reserved, &(page)->flags)
 #define SetPageReserved(page)	set_bit(PG_reserved, &(page)->flags)
 #define ClearPageReserved(page)	clear_bit(PG_reserved, &(page)->flags)
+#define __ClearPageReserved(page)	__clear_bit(PG_reserved, &(page)->flags)
 
 #define SetPagePrivate(page)	set_bit(PG_private, &(page)->flags)
 #define ClearPagePrivate(page)	clear_bit(PG_private, &(page)->flags)
@@ -292,10 +290,6 @@ extern unsigned long __read_page_state(unsigned offset);
 #define SetPageCompound(page)	set_bit(PG_compound, &(page)->flags)
 #define ClearPageCompound(page)	clear_bit(PG_compound, &(page)->flags)
 
-#define PageAnon(page)		test_bit(PG_anon, &(page)->flags)
-#define SetPageAnon(page)	set_bit(PG_anon, &(page)->flags)
-#define ClearPageAnon(page)	clear_bit(PG_anon, &(page)->flags)
-
 #ifdef CONFIG_SWAP
 #define PageSwapCache(page)	test_bit(PG_swapcache, &(page)->flags)
 #define SetPageSwapCache(page)	set_bit(PG_swapcache, &(page)->flags)
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 4da205f3c..12f8116ff 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -156,6 +156,7 @@ extern void FASTCALL(unlock_page(struct page *page));
 
 static inline void lock_page(struct page *page)
 {
+	might_sleep();
 	if (TestSetPageLocked(page))
 		__lock_page(page);
 }
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 2ce5f957c..3f76ca047 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -536,7 +536,7 @@ struct pci_dev {
 	unsigned int	is_enabled:1;	/* pci_enable_device has been called */
 	unsigned int	is_busmaster:1; /* device is busmaster */
 	
-	unsigned int 	saved_config_space[16]; /* config space saved at suspend time */
+	u32		saved_config_space[16]; /* config space saved at suspend time */
 #ifdef CONFIG_PCI_NAMES
 #define PCI_NAME_SIZE	96
 #define PCI_NAME_HALF	__stringify(43)	/* less than half to handle slop */
@@ -712,7 +712,7 @@ struct resource *pci_find_parent_resource(const struct pci_dev *dev, struct reso
 int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge);
 extern struct pci_dev *pci_dev_get(struct pci_dev *dev);
 extern void pci_dev_put(struct pci_dev *dev);
-
+extern void pci_remove_bus(struct pci_bus *b);
 extern void pci_remove_bus_device(struct pci_dev *dev);
 
 /* Generic PCI functions exported to card drivers */
@@ -1001,17 +1001,27 @@ static inline char *pci_name(struct pci_dev *pdev)
  */
 
 struct pci_fixup {
-	int pass;
 	u16 vendor, device;			/* You can use PCI_ANY_ID here of course */
 	void (*hook)(struct pci_dev *dev);
 };
 
-extern struct pci_fixup pcibios_fixups[];
+enum pci_fixup_pass {
+	pci_fixup_header,	/* Called immediately after reading configuration header */
+	pci_fixup_final,	/* Final phase of device fixups */
+};
+
+/* Anonymous variables would be nice... */
+#define DECLARE_PCI_FIXUP_HEADER(vendor, device, hook)					\
+	static struct pci_fixup __pci_fixup_##vendor##device##hook __attribute_used__	\
+	__attribute__((__section__(".pci_fixup_header"))) = {				\
+		vendor, device, hook };
 
-#define PCI_FIXUP_HEADER	1		/* Called immediately after reading configuration header */
-#define PCI_FIXUP_FINAL		2		/* Final phase of device fixups */
+#define DECLARE_PCI_FIXUP_FINAL(vendor, device, hook)				\
+	static struct pci_fixup __pci_fixup_##vendor##device##hook __attribute_used__	\
+	__attribute__((__section__(".pci_fixup_final"))) = {				\
+		vendor, device, hook };
 
-void pci_fixup_device(int pass, struct pci_dev *dev);
+void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
 
 extern int pci_pci_problems;
 #define PCIPCI_FAIL		1
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 50a747035..eed506d01 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -438,8 +438,14 @@
 #define	PCI_DEVICE_ID_IBM_405GP		0x0156
 #define PCI_DEVICE_ID_IBM_SNIPE		0x0180
 #define PCI_DEVICE_ID_IBM_SERVERAIDI960	0x01bd
+#define PCI_DEVICE_ID_IBM_CITRINE		0x028C
 #define PCI_DEVICE_ID_IBM_GEMSTONE		0xB166
 #define PCI_DEVICE_ID_IBM_MPIC_2	0xffff
+#define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_1	0x0031
+#define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2	0x0219
+#define PCI_DEVICE_ID_IBM_ICOM_V2_TWO_PORTS_RVX		0x021A
+#define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM	0x0251
+#define PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL	0x252
 
 #define PCI_VENDOR_ID_COMPEX2		0x101a // pci.ids says "AT&T GIS (NCR)"
 #define PCI_DEVICE_ID_COMPEX2_100VG	0x0005
@@ -670,6 +676,7 @@
 #define PCI_DEVICE_ID_HP_SX1000_IOC	0x127c
 #define PCI_DEVICE_ID_HP_DIVA_EVEREST	0x1282
 #define PCI_DEVICE_ID_HP_DIVA_AUX	0x1290
+#define PCI_DEVICE_ID_HP_CISS		0x3210
 
 #define PCI_VENDOR_ID_PCTECH		0x1042
 #define PCI_DEVICE_ID_PCTECH_RZ1000	0x1000
@@ -727,6 +734,7 @@
 #define PCI_DEVICE_ID_TI_1251B		0xac1f
 #define PCI_DEVICE_ID_TI_4410		0xac41
 #define PCI_DEVICE_ID_TI_4451		0xac42
+#define PCI_DEVICE_ID_TI_4520		0xac46
 #define PCI_DEVICE_ID_TI_1410		0xac50
 #define PCI_DEVICE_ID_TI_1420		0xac51
 #define PCI_DEVICE_ID_TI_1451A		0xac52
@@ -1071,6 +1079,7 @@
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2	0x0055
 #define PCI_DEVICE_ID_NVIDIA_NVENET_8		0x0056
 #define PCI_DEVICE_ID_NVIDIA_NVENET_9		0x0057
+#define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO	0x0059
 #define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE	0x0065
 #define PCI_DEVICE_ID_NVIDIA_NVENET_2		0x0066
 #define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO		0x006a
@@ -1234,6 +1243,7 @@
 #define PCI_DEVICE_ID_VIA_8233C_0	0x3109
 #define PCI_DEVICE_ID_VIA_8361		0x3112
 #define PCI_DEVICE_ID_VIA_XM266		0x3116
+#define PCI_DEVICE_ID_VIA_612X		0x3119
 #define PCI_DEVICE_ID_VIA_862X_0	0x3123
 #define PCI_DEVICE_ID_VIA_8753_0	0x3128
 #define PCI_DEVICE_ID_VIA_8233A		0x3147
@@ -1798,6 +1808,11 @@
 #define PCI_DEVICE_ID_CCD_B00C		0xb00c
 #define PCI_DEVICE_ID_CCD_B100		0xb100
 
+#define PCI_VENDOR_ID_EXAR		0x13a8
+#define PCI_DEVICE_ID_EXAR_XR17C152	0x0152
+#define PCI_DEVICE_ID_EXAR_XR17C154	0x0154
+#define PCI_DEVICE_ID_EXAR_XR17C158	0x0158
+
 #define PCI_VENDOR_ID_MICROGATE		0x13c0
 #define PCI_DEVICE_ID_MICROGATE_USC	0x0010
 #define PCI_DEVICE_ID_MICROGATE_SCC	0x0020
@@ -2228,7 +2243,9 @@
 #define PCI_DEVICE_ID_INTEL_82451NX	0x84ca
 #define PCI_DEVICE_ID_INTEL_82454NX     0x84cb
 #define PCI_DEVICE_ID_INTEL_84460GX	0x84ea
-#define	PCI_DEVICE_ID_INTEL_IXP4XX	0x8500
+#define PCI_DEVICE_ID_INTEL_IXP4XX	0x8500
+#define PCI_DEVICE_ID_INTEL_IXP2400	0x9001
+#define PCI_DEVICE_ID_INTEL_IXP2800	0x9004
 
 #define PCI_VENDOR_ID_COMPUTONE		0x8e0e
 #define PCI_DEVICE_ID_COMPUTONE_IP2EX	0x0291
@@ -2299,6 +2316,8 @@
 #define PCI_DEVICE_ID_NETMOS_9815	0x9815
 #define PCI_DEVICE_ID_NETMOS_9835	0x9835
 #define PCI_DEVICE_ID_NETMOS_9855	0x9855
+#define PCI_DEVICE_ID_NETMOS_9755	0x9755
+#define PCI_DEVICE_ID_NETMOS_9715	0x9715
 
 #define PCI_SUBVENDOR_ID_EXSYS		0xd84d
 #define PCI_SUBDEVICE_ID_EXSYS_4014	0x4014
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index 6aedd71cc..5451eb1e7 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -24,8 +24,8 @@ struct percpu_data {
 
 /* 
  * Use this to get to a cpu's version of the per-cpu object allocated using
- * alloc_percpu.  If you want to get "this cpu's version", maybe you want
- * to use get_cpu_ptr... 
+ * alloc_percpu.  Non-atomic access to the current CPU's version should
+ * probably be combined with get_cpu()/put_cpu().
  */ 
 #define per_cpu_ptr(ptr, cpu)                   \
 ({                                              \
@@ -58,26 +58,4 @@ static inline void free_percpu(const void *ptr)
 #define alloc_percpu(type) \
 	((type *)(__alloc_percpu(sizeof(type), __alignof__(type))))
 
-/* 
- * Use these with alloc_percpu. If
- * 1. You want to operate on memory allocated by alloc_percpu (dereference
- *    and read/modify/write)  AND 
- * 2. You want "this cpu's version" of the object AND 
- * 3. You want to do this safely since:
- *    a. On multiprocessors, you don't want to switch between cpus after 
- *    you've read the current processor id due to preemption -- this would 
- *    take away the implicit  advantage to not have any kind of traditional 
- *    serialization for per-cpu data
- *    b. On uniprocessors, you don't want another kernel thread messing
- *    up with the same per-cpu data due to preemption
- *    
- * So, Use get_cpu_ptr to disable preemption and get pointer to the 
- * local cpu version of the per-cpu object. Use put_cpu_ptr to enable
- * preemption.  Operations on per-cpu data between get_ and put_ is
- * then considered to be safe. And ofcourse, "Thou shalt not sleep between 
- * get_cpu_ptr and put_cpu_ptr"
- */
-#define get_cpu_ptr(ptr) per_cpu_ptr(ptr, get_cpu())
-#define put_cpu_ptr(ptr) put_cpu()
-
 #endif /* __LINUX_PERCPU_H */
diff --git a/include/linux/personality.h b/include/linux/personality.h
index 9b009b675..db31c5828 100644
--- a/include/linux/personality.h
+++ b/include/linux/personality.h
@@ -12,17 +12,6 @@ extern int		register_exec_domain(struct exec_domain *);
 extern int		unregister_exec_domain(struct exec_domain *);
 extern int		__set_personality(unsigned long);
 
-
-/*
- * Sysctl variables related to binary emulation.
- */
-extern unsigned long abi_defhandler_coff;
-extern unsigned long abi_defhandler_elf;
-extern unsigned long abi_defhandler_lcall7;
-extern unsigned long abi_defhandler_libcso;
-extern int abi_fake_utsname;
-
-
 /*
  * Flags for bug emulation.
  *
@@ -30,6 +19,7 @@ extern int abi_fake_utsname;
  */
 enum {
 	MMAP_PAGE_ZERO =	0x0100000,
+	ADDR_COMPAT_LAYOUT =	0x0200000,
 	READ_IMPLIES_EXEC =	0x0400000,
 	ADDR_LIMIT_32BIT =	0x0800000,
 	SHORT_INODE =		0x1000000,
diff --git a/include/linux/pfkeyv2.h b/include/linux/pfkeyv2.h
index a48a3ecc7..e6b519220 100644
--- a/include/linux/pfkeyv2.h
+++ b/include/linux/pfkeyv2.h
@@ -245,6 +245,7 @@ struct sadb_x_nat_t_port {
 
 /* Security Association flags */
 #define SADB_SAFLAGS_PFS	1
+#define SADB_SAFLAGS_DECAP_DSCP	0x40000000
 #define SADB_SAFLAGS_NOECN	0x80000000
 
 /* Security Association states */
diff --git a/include/linux/pid.h b/include/linux/pid.h
index 9e7213cb1..5b2fcb19d 100644
--- a/include/linux/pid.h
+++ b/include/linux/pid.h
@@ -12,34 +12,22 @@ enum pid_type
 
 struct pid
 {
+	/* Try to keep pid_chain in the same cacheline as nr for find_pid */
 	int nr;
-	atomic_t count;
-	struct task_struct *task;
-	struct list_head task_list;
-	struct list_head hash_chain;
-};
-
-struct pid_link
-{
-	struct list_head pid_chain;
-	struct pid *pidptr;
-	struct pid pid;
+	struct hlist_node pid_chain;
+	/* list of pids with the same nr, only one of them is in the hash */
+	struct list_head pid_list;
 };
 
 #define pid_task(elem, type) \
-	list_entry(elem, struct task_struct, pids[type].pid_chain)
+	list_entry(elem, struct task_struct, pids[type].pid_list)
 
 /*
- * attach_pid() and link_pid() must be called with the tasklist_lock
+ * attach_pid() and detach_pid() must be called with the tasklist_lock
  * write-held.
  */
 extern int FASTCALL(attach_pid(struct task_struct *task, enum pid_type type, int nr));
 
-extern void FASTCALL(link_pid(struct task_struct *task, struct pid_link *link, struct pid *pid));
-
-/*
- * detach_pid() must be called with the tasklist_lock write-held.
- */
 extern void FASTCALL(detach_pid(struct task_struct *task, enum pid_type));
 
 /*
@@ -52,13 +40,16 @@ extern int alloc_pidmap(void);
 extern void FASTCALL(free_pidmap(int));
 extern void switch_exec_pids(struct task_struct *leader, struct task_struct *thread);
 
-#define for_each_task_pid(who, type, task, elem, pid)		\
-	if ((pid = find_pid(type, who)))			\
-	        for (elem = pid->task_list.next,			\
-			prefetch(elem->next),				\
-			task = pid_task(elem, type);			\
-			elem != &pid->task_list;			\
-			elem = elem->next, prefetch(elem->next), 	\
-			task = pid_task(elem, type))
+#define do_each_task_pid(who, type, task)				\
+	if ((task = find_task_by_pid_type(type, who))) {		\
+		prefetch((task)->pids[type].pid_list.next);		\
+		do {
+
+#define while_each_task_pid(who, type, task)				\
+		} while (task = pid_task((task)->pids[type].pid_list.next,\
+						type),			\
+			prefetch((task)->pids[type].pid_list.next),	\
+			hlist_unhashed(&(task)->pids[type].pid_chain));	\
+	}								\
 
 #endif /* _LINUX_PID_H */
diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
index d98d8cfcd..b80dbc3b5 100644
--- a/include/linux/pkt_sched.h
+++ b/include/linux/pkt_sched.h
@@ -402,6 +402,16 @@ enum {
 #define TCA_ATM_MAX	TCA_ATM_STATE
 
 /* Network emulator */
+
+enum
+{
+	TCA_NETEM_UNSPEC,
+	TCA_NETEM_CORR,
+	TCA_NETEM_DELAY_DIST,
+};
+
+#define TCA_NETEM_MAX	TCA_NETEM_DELAY_DIST
+
 struct tc_netem_qopt
 {
 	__u32	latency;	/* added delay (us) */
@@ -411,4 +421,14 @@ struct tc_netem_qopt
 	__u32   duplicate;	/* random packet dup  (0=none ~0=100%) */
 	__u32	jitter;		/* random jitter in latency (us) */
 };
+
+struct tc_netem_corr
+{
+	__u32	delay_corr;	/* delay correlation */
+	__u32	loss_corr;	/* packet loss correlation */
+	__u32	dup_corr;	/* duplicate correlation  */
+};
+
+#define NETEM_DIST_SCALE	8192
+
 #endif
diff --git a/include/linux/pm.h b/include/linux/pm.h
index d54bc441d..7bfd2d439 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -194,11 +194,12 @@ extern void (*pm_idle)(void);
 extern void (*pm_power_off)(void);
 
 enum {
-	PM_SUSPEND_ON,
-	PM_SUSPEND_STANDBY,
-	PM_SUSPEND_MEM,
-	PM_SUSPEND_DISK,
-	PM_SUSPEND_MAX,
+	PM_SUSPEND_ON = 0,
+	PM_SUSPEND_STANDBY = 1,
+	/* NOTE: PM_SUSPEND_MEM == PCI_D3hot */
+	PM_SUSPEND_MEM = 3,
+	PM_SUSPEND_DISK = 4,
+	PM_SUSPEND_MAX = 5,
 };
 
 enum {
diff --git a/include/linux/poll.h b/include/linux/poll.h
index b4bb681fd..1bb33342c 100644
--- a/include/linux/poll.h
+++ b/include/linux/poll.h
@@ -5,6 +5,7 @@
 
 #ifdef __KERNEL__
 
+#include <linux/compiler.h>
 #include <linux/wait.h>
 #include <linux/string.h>
 #include <linux/mm.h>
@@ -81,11 +82,12 @@ int get_fd_set(unsigned long nr, void __user *ufdset, unsigned long *fdset)
 	return 0;
 }
 
-static inline
-void set_fd_set(unsigned long nr, void __user *ufdset, unsigned long *fdset)
+static inline unsigned long __must_check
+set_fd_set(unsigned long nr, void __user *ufdset, unsigned long *fdset)
 {
 	if (ufdset)
-		__copy_to_user(ufdset, fdset, FDS_BYTES(nr));
+		return __copy_to_user(ufdset, fdset, FDS_BYTES(nr));
+	return 0;
 }
 
 static inline
diff --git a/include/linux/prctl.h b/include/linux/prctl.h
index c8b69670e..54333c98e 100644
--- a/include/linux/prctl.h
+++ b/include/linux/prctl.h
@@ -50,4 +50,6 @@
                                                    process timing */
 
 
+#define PR_SET_NAME    15		/* Set process name */
+
 #endif /* _LINUX_PRCTL_H */
diff --git a/include/linux/prio_tree.h b/include/linux/prio_tree.h
index 4ac5c6269..6356a511f 100644
--- a/include/linux/prio_tree.h
+++ b/include/linux/prio_tree.h
@@ -17,8 +17,20 @@ struct prio_tree_iter {
 	unsigned long		mask;
 	unsigned long		value;
 	int			size_level;
+
+	struct prio_tree_root	*root;
+	pgoff_t			r_index;
+	pgoff_t			h_index;
 };
 
+static inline void prio_tree_iter_init(struct prio_tree_iter *iter,
+		struct prio_tree_root *root, pgoff_t r_index, pgoff_t h_index)
+{
+	iter->root = root;
+	iter->r_index = r_index;
+	iter->h_index = h_index;
+}
+
 #define INIT_PRIO_TREE_ROOT(ptr)	\
 do {					\
 	(ptr)->prio_tree_node = NULL;	\
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 3c3226075..000dd88d6 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -80,6 +80,7 @@ struct kcore_list {
 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;
@@ -87,10 +88,15 @@ extern struct proc_dir_entry *proc_root_kcore;
 extern void proc_root_init(void);
 extern void proc_misc_init(void);
 
+struct mm_struct;
+
 struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *);
 struct dentry *proc_pid_unhash(struct task_struct *p);
 void proc_pid_flush(struct dentry *proc_dentry);
 int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir);
+unsigned long task_vsize(struct mm_struct *);
+int task_statm(struct mm_struct *, int *, int *, int *, int *);
+char *task_mem(struct mm_struct *, char *);
 
 extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
 						struct proc_dir_entry *parent);
@@ -202,14 +208,13 @@ static inline struct proc_dir_entry *create_proc_entry(const char *name,
 #define remove_proc_entry(name, parent) do {} while (0)
 
 static inline struct proc_dir_entry *proc_symlink(const char *name,
-		struct proc_dir_entry *parent,char *dest) {return NULL;}
+		struct proc_dir_entry *parent,const char *dest) {return NULL;}
 static inline struct proc_dir_entry *proc_mkdir(const char *name,
 	struct proc_dir_entry *parent) {return NULL;}
 
 static inline struct proc_dir_entry *create_proc_read_entry(const char *name,
 	mode_t mode, struct proc_dir_entry *base, 
-	int (*read_proc)(char *, char **, off_t, int, int *, void *),
-	void * data) { return NULL; }
+	read_proc_t *read_proc, void * data) { return NULL; }
 static inline struct proc_dir_entry *create_proc_info_entry(const char *name,
 	mode_t mode, struct proc_dir_entry *base, get_info_t *get_info)
 	{ return NULL; }
diff --git a/include/linux/profile.h b/include/linux/profile.h
index 7593cb269..a22f4a15c 100644
--- a/include/linux/profile.h
+++ b/include/linux/profile.h
@@ -6,24 +6,28 @@
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/cpumask.h>
 #include <asm/errno.h>
 
-/* parse command line */
-int __init profile_setup(char * str);
+#define CPU_PROFILING	1
+#define SCHED_PROFILING	2
+
+struct proc_dir_entry;
+struct pt_regs;
 
 /* init basic kernel profiler */
 void __init profile_init(void);
-
-extern unsigned int * prof_buffer;
-extern unsigned long prof_len;
-extern unsigned long prof_shift;
-extern int prof_on;
-
+void profile_tick(int, struct pt_regs *);
+void profile_hit(int, void *);
+#ifdef CONFIG_PROC_FS
+void create_prof_cpu_mask(struct proc_dir_entry *);
+#else
+#define create_prof_cpu_mask(x)			do { (void)(x); } while (0)
+#endif
 
 enum profile_type {
-	EXIT_TASK,
-	EXIT_MMAP,
-	EXEC_UNMAP
+	PROFILE_TASK_EXIT,
+	PROFILE_MUNMAP
 };
 
 #ifdef CONFIG_PROFILING
@@ -33,16 +37,20 @@ struct task_struct;
 struct mm_struct;
 
 /* task is in do_exit() */
-void profile_exit_task(struct task_struct * task);
+void profile_task_exit(struct task_struct * task);
 
-/* change of vma mappings */
-void profile_exec_unmap(struct mm_struct * mm);
+/* task is dead, free task struct ? Returns 1 if
+ * the task was taken, 0 if the task should be freed.
+ */
+int profile_handoff_task(struct task_struct * task);
 
-/* exit of all vmas for a task */
-void profile_exit_mmap(struct mm_struct * mm);
+/* sys_munmap */
+void profile_munmap(unsigned long addr);
 
-int profile_event_register(enum profile_type, struct notifier_block * n);
+int task_handoff_register(struct notifier_block * n);
+int task_handoff_unregister(struct notifier_block * n);
 
+int profile_event_register(enum profile_type, struct notifier_block * n);
 int profile_event_unregister(enum profile_type, struct notifier_block * n);
 
 int register_profile_notifier(struct notifier_block * nb);
@@ -55,6 +63,16 @@ void profile_hook(struct pt_regs * regs);
 
 #else
 
+static inline int task_handoff_register(struct notifier_block * n)
+{
+	return -ENOSYS;
+}
+
+static inline int task_handoff_unregister(struct notifier_block * n)
+{
+	return -ENOSYS;
+}
+
 static inline int profile_event_register(enum profile_type t, struct notifier_block * n)
 {
 	return -ENOSYS;
@@ -65,9 +83,9 @@ static inline int profile_event_unregister(enum profile_type t, struct notifier_
 	return -ENOSYS;
 }
 
-#define profile_exit_task(a) do { } while (0)
-#define profile_exec_unmap(a) do { } while (0)
-#define profile_exit_mmap(a) do { } while (0)
+#define profile_task_exit(a) do { } while (0)
+#define profile_handoff_task(a) (0)
+#define profile_munmap(a) do { } while (0)
 
 static inline int register_profile_notifier(struct notifier_block * nb)
 {
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 7a6fdcfde..8869a4c1b 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -74,7 +74,7 @@
 
 #include <linux/compiler.h>		/* For unlikely.  */
 #include <linux/sched.h>		/* For struct task_struct.  */
-#include <linux/vs_base.h>
+#include <linux/vs_cvirt.h>
 #include <linux/vs_context.h>
 
 extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 506d52452..f4cbf4636 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -45,7 +45,6 @@
 typedef __kernel_uid32_t qid_t; /* Type in which we store ids in memory */
 typedef __u64 qsize_t;          /* Type in which we store sizes */
 
-extern spinlock_t dq_list_lock;
 extern spinlock_t dq_data_lock;
 
 /* Size of blocks in which are counted size limits */
diff --git a/include/linux/quotaio_v2.h b/include/linux/quotaio_v2.h
index f18ced911..303d7cbe3 100644
--- a/include/linux/quotaio_v2.h
+++ b/include/linux/quotaio_v2.h
@@ -27,15 +27,15 @@
  * to blocks of these structures.
  */
 struct v2_disk_dqblk {
-	__u32 dqb_id;		/* id this quota applies to */
-	__u32 dqb_ihardlimit;	/* absolute limit on allocated inodes */
-	__u32 dqb_isoftlimit;	/* preferred inode limit */
-	__u32 dqb_curinodes;	/* current # allocated inodes */
-	__u32 dqb_bhardlimit;	/* absolute limit on disk space (in QUOTABLOCK_SIZE) */
-	__u32 dqb_bsoftlimit;	/* preferred limit on disk space (in QUOTABLOCK_SIZE) */
-	__u64 dqb_curspace;	/* current space occupied (in bytes) */
-	__u64 dqb_btime;	/* time limit for excessive disk use */
-	__u64 dqb_itime;	/* time limit for excessive inode use */
+	__le32 dqb_id;		/* id this quota applies to */
+	__le32 dqb_ihardlimit;	/* absolute limit on allocated inodes */
+	__le32 dqb_isoftlimit;	/* preferred inode limit */
+	__le32 dqb_curinodes;	/* current # allocated inodes */
+	__le32 dqb_bhardlimit;	/* absolute limit on disk space (in QUOTABLOCK_SIZE) */
+	__le32 dqb_bsoftlimit;	/* preferred limit on disk space (in QUOTABLOCK_SIZE) */
+	__le64 dqb_curspace;	/* current space occupied (in bytes) */
+	__le64 dqb_btime;	/* time limit for excessive disk use */
+	__le64 dqb_itime;	/* time limit for excessive inode use */
 };
 
 /*
@@ -43,18 +43,18 @@ struct v2_disk_dqblk {
  */
 /* First generic header */
 struct v2_disk_dqheader {
-	__u32 dqh_magic;	/* Magic number identifying file */
-	__u32 dqh_version;	/* File version */
+	__le32 dqh_magic;	/* Magic number identifying file */
+	__le32 dqh_version;	/* File version */
 };
 
 /* Header with type and version specific information */
 struct v2_disk_dqinfo {
-	__u32 dqi_bgrace;	/* Time before block soft limit becomes hard limit */
-	__u32 dqi_igrace;	/* Time before inode soft limit becomes hard limit */
-	__u32 dqi_flags;	/* Flags for quotafile (DQF_*) */
-	__u32 dqi_blocks;	/* Number of blocks in file */
-	__u32 dqi_free_blk;	/* Number of first free block in the list */
-	__u32 dqi_free_entry;	/* Number of block with at least one free entry */
+	__le32 dqi_bgrace;	/* Time before block soft limit becomes hard limit */
+	__le32 dqi_igrace;	/* Time before inode soft limit becomes hard limit */
+	__le32 dqi_flags;	/* Flags for quotafile (DQF_*) */
+	__le32 dqi_blocks;	/* Number of blocks in file */
+	__le32 dqi_free_blk;	/* Number of first free block in the list */
+	__le32 dqi_free_entry;	/* Number of block with at least one free entry */
 };
 
 /*
@@ -62,11 +62,11 @@ struct v2_disk_dqinfo {
  *  there will be space for exactly 21 quota-entries in a block
  */
 struct v2_disk_dqdbheader {
-	__u32 dqdh_next_free;	/* Number of next block with free entry */
-	__u32 dqdh_prev_free;	/* Number of previous block with free entry */
-	__u16 dqdh_entries;	/* Number of valid entries in block */
-	__u16 dqdh_pad1;
-	__u32 dqdh_pad2;
+	__le32 dqdh_next_free;	/* Number of next block with free entry */
+	__le32 dqdh_prev_free;	/* Number of previous block with free entry */
+	__le16 dqdh_entries;	/* Number of valid entries in block */
+	__le16 dqdh_pad1;
+	__le32 dqdh_pad2;
 };
 
 #define V2_DQINFOOFF	sizeof(struct v2_disk_dqheader)	/* Offset of info header in file */
diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h
index 9c06e776c..fad5699f5 100644
--- a/include/linux/raid/md.h
+++ b/include/linux/raid/md.h
@@ -69,12 +69,10 @@ extern mdk_thread_t * md_register_thread (void (*run) (mddev_t *mddev),
 extern void md_unregister_thread (mdk_thread_t *thread);
 extern void md_wakeup_thread(mdk_thread_t *thread);
 extern void md_check_recovery(mddev_t *mddev);
-extern void md_interrupt_thread (mdk_thread_t *thread);
 extern void md_write_start(mddev_t *mddev);
 extern void md_write_end(mddev_t *mddev);
 extern void md_handle_safemode(mddev_t *mddev);
 extern void md_done_sync(mddev_t *mddev, int blocks, int ok);
-extern void md_sync_acct(mdk_rdev_t *rdev, unsigned long nr_sectors);
 extern void md_error (mddev_t *mddev, mdk_rdev_t *rdev);
 extern void md_unplug_mddev(mddev_t *mddev);
 
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
index faa400cf2..945346ec2 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -24,7 +24,8 @@
 #define HSM               6UL
 #define MULTIPATH         7UL
 #define RAID6		  8UL
-#define MAX_PERSONALITY   9UL
+#define	RAID10		  9UL
+#define MAX_PERSONALITY   10UL
 
 #define	LEVEL_MULTIPATH		(-4)
 #define	LEVEL_LINEAR		(-1)
@@ -43,6 +44,7 @@ static inline int pers_to_level (int pers)
 		case RAID1:		return 1;
 		case RAID5:		return 5;
 		case RAID6:		return 6;
+		case RAID10:		return 10;
 	}
 	BUG();
 	return MD_RESERVED;
@@ -60,6 +62,7 @@ static inline int level_to_pers (int level)
 		case 4:
 		case 5: return RAID5;
 		case 6: return RAID6;
+		case 10: return RAID10;
 	}
 	return MD_RESERVED;
 }
@@ -216,6 +219,7 @@ struct mddev_s
 	unsigned long			resync_mark;	/* a recent timestamp */
 	sector_t			resync_mark_cnt;/* blocks written at resync_mark */
 
+	sector_t			resync_max_sectors; /* may be set by personality */
 	/* recovery/resync flags 
 	 * NEEDED:   we might need to start a resync/recover
 	 * RUNNING:  a thread is running, or about to be started
@@ -263,6 +267,11 @@ static inline void rdev_dec_pending(mdk_rdev_t *rdev, mddev_t *mddev)
 		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 }
 
+static inline void md_sync_acct(struct block_device *bdev, unsigned long nr_sectors)
+{
+        atomic_add(nr_sectors, &bdev->bd_contains->bd_disk->sync_io);
+}
+
 struct mdk_personality_s
 {
 	char *name;
diff --git a/include/linux/random.h b/include/linux/random.h
index 9ccb52fa0..068875bf9 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -67,8 +67,6 @@ extern __u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr,
 extern __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
 					  __u16 sport, __u16 dport);
 
-extern __u32 secure_ipv6_id(__u32 *daddr);
-
 #ifndef MODULE
 extern struct file_operations random_fops, urandom_fops;
 #endif
diff --git a/include/linux/rbtree.h b/include/linux/rbtree.h
index fb2088f0b..3ae0c6e14 100644
--- a/include/linux/rbtree.h
+++ b/include/linux/rbtree.h
@@ -123,6 +123,7 @@ extern void rb_erase(struct rb_node *, struct rb_root *);
 extern struct rb_node *rb_next(struct rb_node *);
 extern struct rb_node *rb_prev(struct rb_node *);
 extern struct rb_node *rb_first(struct rb_root *);
+extern struct rb_node *rb_last(struct rb_root *);
 
 /* Fast replacement of a single node without remove/rebalance/add/rebalance */
 extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, 
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 10c4b8f24..b12bdd9d8 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -87,55 +87,157 @@ static inline int rcu_batch_after(long a, long b)
  */
 struct rcu_data {
 	/* 1) quiescent state handling : */
-        long		quiescbatch;     /* Batch # for grace period */
+	long		quiescbatch;     /* Batch # for grace period */
 	long		qsctr;		 /* User-mode/idle loop etc. */
-        long            last_qsctr;	 /* value of qsctr at beginning */
-                                         /* of rcu grace period */
+	long            last_qsctr;	 /* value of qsctr at beginning */
+					 /* of rcu grace period */
 	int		qs_pending;	 /* core waits for quiesc state */
 
 	/* 2) batch handling */
-        long  	       	batch;           /* Batch # for current RCU batch */
-        struct rcu_head *nxtlist;
+	long  	       	batch;           /* Batch # for current RCU batch */
+	struct rcu_head *nxtlist;
 	struct rcu_head **nxttail;
-        struct rcu_head *curlist;
+	struct rcu_head *curlist;
+	struct rcu_head **curtail;
+	struct rcu_head *donelist;
+	struct rcu_head **donetail;
+	int cpu;
 };
 
 DECLARE_PER_CPU(struct rcu_data, rcu_data);
+DECLARE_PER_CPU(struct rcu_data, rcu_bh_data);
 extern struct rcu_ctrlblk rcu_ctrlblk;
+extern struct rcu_ctrlblk rcu_bh_ctrlblk;
 
-#define RCU_quiescbatch(cpu)	(per_cpu(rcu_data, (cpu)).quiescbatch)
-#define RCU_qsctr(cpu) 		(per_cpu(rcu_data, (cpu)).qsctr)
-#define RCU_last_qsctr(cpu) 	(per_cpu(rcu_data, (cpu)).last_qsctr)
-#define RCU_qs_pending(cpu)	(per_cpu(rcu_data, (cpu)).qs_pending)
-#define RCU_batch(cpu) 		(per_cpu(rcu_data, (cpu)).batch)
-#define RCU_nxtlist(cpu) 	(per_cpu(rcu_data, (cpu)).nxtlist)
-#define RCU_curlist(cpu) 	(per_cpu(rcu_data, (cpu)).curlist)
-#define RCU_nxttail(cpu) 	(per_cpu(rcu_data, (cpu)).nxttail)
+/*
+ * Increment the quiscent state counter.
+ */
+static inline void rcu_qsctr_inc(int cpu)
+{
+	struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
+	rdp->qsctr++;
+}
+static inline void rcu_bh_qsctr_inc(int cpu)
+{
+	struct rcu_data *rdp = &per_cpu(rcu_bh_data, cpu);
+	rdp->qsctr++;
+}
 
-static inline int rcu_pending(int cpu) 
+static inline int __rcu_pending(struct rcu_ctrlblk *rcp,
+						struct rcu_data *rdp)
 {
 	/* This cpu has pending rcu entries and the grace period
 	 * for them has completed.
 	 */
-	if (RCU_curlist(cpu) &&
-		  !rcu_batch_before(rcu_ctrlblk.completed,RCU_batch(cpu)))
+	if (rdp->curlist && !rcu_batch_before(rcp->completed, rdp->batch))
 		return 1;
 
 	/* This cpu has no pending entries, but there are new entries */
-	if (!RCU_curlist(cpu) && RCU_nxtlist(cpu))
+	if (!rdp->curlist && rdp->nxtlist)
+		return 1;
+
+	/* This cpu has finished callbacks to invoke */
+	if (rdp->donelist)
 		return 1;
 
 	/* The rcu core waits for a quiescent state from the cpu */
-	if (RCU_quiescbatch(cpu) != rcu_ctrlblk.cur || RCU_qs_pending(cpu))
+	if (rdp->quiescbatch != rcp->cur || rdp->qs_pending)
 		return 1;
 
 	/* nothing to do */
 	return 0;
 }
 
+static inline int rcu_pending(int cpu)
+{
+	return __rcu_pending(&rcu_ctrlblk, &per_cpu(rcu_data, cpu)) ||
+		__rcu_pending(&rcu_bh_ctrlblk, &per_cpu(rcu_bh_data, cpu));
+}
+
+/**
+ * rcu_read_lock - mark the beginning of an RCU read-side critical section.
+ *
+ * When synchronize_kernel() is invoked on one CPU while other CPUs
+ * are within RCU read-side critical sections, then the
+ * synchronize_kernel() is guaranteed to block until after all the other
+ * CPUs exit their critical sections.  Similarly, if call_rcu() is invoked
+ * on one CPU while other CPUs are within RCU read-side critical
+ * sections, invocation of the corresponding RCU callback is deferred
+ * until after the all the other CPUs exit their critical sections.
+ *
+ * Note, however, that RCU callbacks are permitted to run concurrently
+ * with RCU read-side critical sections.  One way that this can happen
+ * is via the following sequence of events: (1) CPU 0 enters an RCU
+ * read-side critical section, (2) CPU 1 invokes call_rcu() to register
+ * an RCU callback, (3) CPU 0 exits the RCU read-side critical section,
+ * (4) CPU 2 enters a RCU read-side critical section, (5) the RCU
+ * callback is invoked.  This is legal, because the RCU read-side critical
+ * section that was running concurrently with the call_rcu() (and which
+ * therefore might be referencing something that the corresponding RCU
+ * callback would free up) has completed before the corresponding
+ * RCU callback is invoked.
+ *
+ * RCU read-side critical sections may be nested.  Any deferred actions
+ * will be deferred until the outermost RCU read-side critical section
+ * completes.
+ *
+ * It is illegal to block while in an RCU read-side critical section.
+ */
 #define rcu_read_lock()		preempt_disable()
+
+/**
+ * rcu_read_unlock - marks the end of an RCU read-side critical section.
+ *
+ * See rcu_read_lock() for more information.
+ */
 #define rcu_read_unlock()	preempt_enable()
 
+/*
+ * So where is rcu_write_lock()?  It does not exist, as there is no
+ * way for writers to lock out RCU readers.  This is a feature, not
+ * a bug -- this property is what provides RCU's performance benefits.
+ * Of course, writers must coordinate with each other.  The normal
+ * spinlock primitives work well for this, but any other technique may be
+ * used as well.  RCU does not care how the writers keep out of each
+ * others' way, as long as they do so.
+ */
+
+/**
+ * rcu_read_lock_bh - mark the beginning of a softirq-only RCU critical section
+ *
+ * This is equivalent of rcu_read_lock(), but to be used when updates
+ * are being done using call_rcu_bh(). Since call_rcu_bh() callbacks
+ * consider completion of a softirq handler to be a quiescent state,
+ * a process in RCU read-side critical section must be protected by
+ * disabling softirqs. Read-side critical sections in interrupt context
+ * can use just rcu_read_lock().
+ *
+ */
+#define rcu_read_lock_bh()	local_bh_disable()
+
+/*
+ * rcu_read_unlock_bh - marks the end of a softirq-only RCU critical section
+ *
+ * See rcu_read_lock_bh() for more information.
+ */
+#define rcu_read_unlock_bh()	local_bh_enable()
+
+/**
+ * rcu_dereference - fetch an RCU-protected pointer in an
+ * RCU read-side critical section.  This pointer may later
+ * be safely dereferenced.
+ *
+ * Inserts memory barriers on architectures that require them
+ * (currently only the Alpha), and, more importantly, documents
+ * exactly which pointers are protected by RCU.
+ */
+
+#define rcu_dereference(p)     ({ \
+				typeof(p) _________p1 = p; \
+				smp_read_barrier_depends(); \
+				(_________p1); \
+				})
+
 extern void rcu_init(void);
 extern void rcu_check_callbacks(int cpu, int user);
 extern void rcu_restart_cpu(int cpu);
@@ -143,6 +245,8 @@ extern void rcu_restart_cpu(int cpu);
 /* Exported interfaces */
 extern void FASTCALL(call_rcu(struct rcu_head *head, 
 				void (*func)(struct rcu_head *head)));
+extern void FASTCALL(call_rcu_bh(struct rcu_head *head,
+				void (*func)(struct rcu_head *head)));
 extern void synchronize_kernel(void);
 
 #endif /* __KERNEL__ */
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index 2a206e8e5..249ad93f3 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -892,8 +892,13 @@ struct stat_data_v1
 #define REISERFS_BARRIER_FL   (EXT2_BARRIER_FL >> 16)
 #define REISERFS_IUNLINK_FL   (EXT2_IUNLINK_FL >> 16)
 
-#define	REISERFS_FL_USER_VISIBLE	0x80FF
-#define	REISERFS_FL_USER_MODIFYABLE	0x80FF
+#ifdef CONFIG_VSERVER_LEGACY
+#define REISERFS_FL_USER_VISIBLE	(REISERFS_IUNLINK_FL|0x80FF)
+#define REISERFS_FL_USER_MODIFYABLE	(REISERFS_IUNLINK_FL|0x80FF)
+#else
+#define REISERFS_FL_USER_VISIBLE	0x80FF
+#define REISERFS_FL_USER_MODIFYABLE	0x80FF
+#endif
 
 /* persistent flags that file inherits from the parent directory */
 #define REISERFS_INHERIT_MASK ( REISERFS_IMMUTABLE_FL |	\
@@ -1741,7 +1746,7 @@ struct reiserfs_transaction_handle {
   int t_blocks_allocated ;      /* number of blocks this writer allocated */
   unsigned long t_trans_id ;    /* sanity check, equals the current trans id */
   void *t_handle_save ;		/* save existing current->journal_info */
-  int displace_new_blocks:1;	/* if new block allocation occurres, that block
+  unsigned displace_new_blocks:1; /* if new block allocation occurres, that block
 				   should be displaced from others */
 } ;
 
@@ -1784,7 +1789,8 @@ int reiserfs_end_persistent_transaction(struct reiserfs_transaction_handle *);
 int reiserfs_commit_page(struct inode *inode, struct page *page,
 		unsigned from, unsigned to);
 int reiserfs_flush_old_commits(struct super_block *);
-void reiserfs_commit_for_inode(struct inode *) ;
+int reiserfs_commit_for_inode(struct inode *) ;
+int  reiserfs_inode_needs_commit(struct inode *) ;
 void reiserfs_update_inode_transaction(struct inode *) ;
 void reiserfs_wait_on_write_block(struct super_block *s) ;
 void reiserfs_block_writes(struct reiserfs_transaction_handle *th) ;
@@ -1951,7 +1957,7 @@ void reiserfs_read_locked_inode(struct inode * inode, struct reiserfs_iget_args
 int reiserfs_find_actor(struct inode * inode, void *p) ;
 int reiserfs_init_locked_inode(struct inode * inode, void *p) ;
 void reiserfs_delete_inode (struct inode * inode);
-void reiserfs_write_inode (struct inode * inode, int) ;
+int reiserfs_write_inode (struct inode * inode, int) ;
 struct dentry *reiserfs_get_dentry(struct super_block *, void *) ;
 struct dentry *reiserfs_decode_fh(struct super_block *sb, __u32 *data,
                                      int len, int fhtype,
@@ -2160,9 +2166,9 @@ struct buffer_head * get_FEB (struct tree_balance *);
     int prealloc_size;			/* is set in determine_prealloc_size() function, used by underlayed
 					 * function that do actual allocation */
 
-    int formatted_node:1;		/* the allocator uses different polices for getting disk space for
+    unsigned formatted_node:1;		/* the allocator uses different polices for getting disk space for
 					 * formatted/unformatted blocks with/without preallocation */
-    int preallocate:1;
+    unsigned preallocate:1;
 };
 
 typedef struct __reiserfs_blocknr_hint reiserfs_blocknr_hint_t;
diff --git a/include/linux/reiserfs_fs_i.h b/include/linux/reiserfs_fs_i.h
index adc71cd0b..e08142a75 100644
--- a/include/linux/reiserfs_fs_i.h
+++ b/include/linux/reiserfs_fs_i.h
@@ -45,7 +45,7 @@ struct reiserfs_inode_info {
     struct list_head i_prealloc_list; /* per-transaction list of inodes which
                                        * have preallocated blocks */
 
-    int new_packing_locality:1;	      /* new_packig_locality is created; new blocks
+    unsigned new_packing_locality:1;  /* new_packig_locality is created; new blocks
 				       * for the contents of this directory should be
 				       * displaced */
 
diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
index 8cc1494f8..2bf165a76 100644
--- a/include/linux/reiserfs_fs_sb.h
+++ b/include/linux/reiserfs_fs_sb.h
@@ -444,6 +444,8 @@ enum reiserfs_mount_options {
     REISERFS_XATTRS,
     REISERFS_XATTRS_USER,
     REISERFS_POSIXACL,
+    REISERFS_BARRIER_NONE,
+    REISERFS_BARRIER_FLUSH,
     REISERFS_TAGXID,
 
     REISERFS_TEST1,
@@ -474,6 +476,8 @@ enum reiserfs_mount_options {
 #define reiserfs_xattrs_user(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_XATTRS_USER))
 #define reiserfs_posixacl(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_POSIXACL))
 #define reiserfs_xattrs_optional(s) (reiserfs_xattrs_user(s) || reiserfs_posixacl(s))
+#define reiserfs_barrier_none(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_BARRIER_NONE))
+#define reiserfs_barrier_flush(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_BARRIER_FLUSH))
 
 void reiserfs_file_buffer (struct buffer_head * bh, int list);
 extern struct file_system_type reiserfs_fs_type;
diff --git a/include/linux/resource.h b/include/linux/resource.h
index 94494789e..21a86cb6a 100644
--- a/include/linux/resource.h
+++ b/include/linux/resource.h
@@ -55,6 +55,12 @@ struct rlimit {
  */
 #define _STK_LIM	(8*1024*1024)
 
+/*
+ * GPG wants 32kB of mlocked memory, to make sure pass phrases
+ * and other sensitive information are never written to disk.
+ */
+#define MLOCK_LIMIT	(8 * PAGE_SIZE)
+
 /*
  * Due to binary compatibility, the actual resource numbers
  * may be different for different linux versions..
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index e3148341f..291d36c9e 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -9,11 +9,6 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 
-#define page_map_lock(page) \
-	bit_spin_lock(PG_maplock, (unsigned long *)&(page)->flags)
-#define page_map_unlock(page) \
-	bit_spin_unlock(PG_maplock, (unsigned long *)&(page)->flags)
-
 /*
  * The anon_vma heads a list of private "related" vmas, to scan if
  * an anonymous page pointing to this anon_vma needs to be unmapped:
@@ -87,24 +82,27 @@ void page_remove_rmap(struct page *);
  */
 static inline void page_dup_rmap(struct page *page)
 {
-	page_map_lock(page);
-	page->mapcount++;
-	page_map_unlock(page);
+	atomic_inc(&page->_mapcount);
 }
 
 /*
  * Called from mm/vmscan.c to handle paging out
  */
-int page_referenced(struct page *);
+int page_referenced(struct page *, int is_locked);
 int try_to_unmap(struct page *);
 
+/*
+ * Used by swapoff to help locate where page is expected in vma.
+ */
+unsigned long page_address_in_vma(struct page *, struct vm_area_struct *);
+
 #else	/* !CONFIG_MMU */
 
 #define anon_vma_init()		do {} while (0)
 #define anon_vma_prepare(vma)	(0)
 #define anon_vma_link(vma)	do {} while (0)
 
-#define page_referenced(page)	TestClearPageReferenced(page)
+#define page_referenced(page,l)	TestClearPageReferenced(page)
 #define try_to_unmap(page)	SWAP_FAIL
 
 #endif	/* CONFIG_MMU */
diff --git a/include/linux/romfs_fs.h b/include/linux/romfs_fs.h
index 8f452cbd4..e20bbf9eb 100644
--- a/include/linux/romfs_fs.h
+++ b/include/linux/romfs_fs.h
@@ -12,27 +12,27 @@
 
 #define __mkw(h,l) (((h)&0x00ff)<< 8|((l)&0x00ff))
 #define __mkl(h,l) (((h)&0xffff)<<16|((l)&0xffff))
-#define __mk4(a,b,c,d) htonl(__mkl(__mkw(a,b),__mkw(c,d)))
+#define __mk4(a,b,c,d) cpu_to_be32(__mkl(__mkw(a,b),__mkw(c,d)))
 #define ROMSB_WORD0 __mk4('-','r','o','m')
 #define ROMSB_WORD1 __mk4('1','f','s','-')
 
 /* On-disk "super block" */
 
 struct romfs_super_block {
-	__u32 word0;
-	__u32 word1;
-	__u32 size;
-	__u32 checksum;
+	__be32 word0;
+	__be32 word1;
+	__be32 size;
+	__be32 checksum;
 	char name[0];		/* volume name */
 };
 
 /* On disk inode */
 
 struct romfs_inode {
-	__u32 next;		/* low 4 bits see ROMFH_ */
-	__u32 spec;
-	__u32 size;
-	__u32 checksum;
+	__be32 next;		/* low 4 bits see ROMFH_ */
+	__be32 spec;
+	__be32 size;
+	__be32 checksum;
 	char name[0];
 };
 
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 58c6429cc..ac4528ead 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -9,53 +9,89 @@
 
 /* Types of messages */
 
-#define RTM_BASE	0x10
-
-#define	RTM_NEWLINK	(RTM_BASE+0)
-#define	RTM_DELLINK	(RTM_BASE+1)
-#define	RTM_GETLINK	(RTM_BASE+2)
-#define	RTM_SETLINK	(RTM_BASE+3)
-
-#define	RTM_NEWADDR	(RTM_BASE+4)
-#define	RTM_DELADDR	(RTM_BASE+5)
-#define	RTM_GETADDR	(RTM_BASE+6)
-
-#define	RTM_NEWROUTE	(RTM_BASE+8)
-#define	RTM_DELROUTE	(RTM_BASE+9)
-#define	RTM_GETROUTE	(RTM_BASE+10)
-
-#define	RTM_NEWNEIGH	(RTM_BASE+12)
-#define	RTM_DELNEIGH	(RTM_BASE+13)
-#define	RTM_GETNEIGH	(RTM_BASE+14)
-
-#define	RTM_NEWRULE	(RTM_BASE+16)
-#define	RTM_DELRULE	(RTM_BASE+17)
-#define	RTM_GETRULE	(RTM_BASE+18)
-
-#define	RTM_NEWQDISC	(RTM_BASE+20)
-#define	RTM_DELQDISC	(RTM_BASE+21)
-#define	RTM_GETQDISC	(RTM_BASE+22)
-
-#define	RTM_NEWTCLASS	(RTM_BASE+24)
-#define	RTM_DELTCLASS	(RTM_BASE+25)
-#define	RTM_GETTCLASS	(RTM_BASE+26)
-
-#define	RTM_NEWTFILTER	(RTM_BASE+28)
-#define	RTM_DELTFILTER	(RTM_BASE+29)
-#define	RTM_GETTFILTER	(RTM_BASE+30)
-
-#define RTM_NEWACTION   (RTM_BASE+32)
-#define RTM_DELACTION   (RTM_BASE+33)
-#define RTM_GETACTION   (RTM_BASE+34)
-
-#define RTM_NEWPREFIX	(RTM_BASE+36)
-#define RTM_GETPREFIX	(RTM_BASE+38)
-
-#define	RTM_GETMULTICAST (RTM_BASE+42)
-
-#define	RTM_GETANYCAST	(RTM_BASE+46)
-
-#define	RTM_MAX		(RTM_BASE+47)
+enum {
+	RTM_BASE	= 16,
+#define RTM_BASE	RTM_BASE
+
+	RTM_NEWLINK	= 16,
+#define RTM_NEWLINK	RTM_NEWLINK
+	RTM_DELLINK,
+#define RTM_DELLINK	RTM_DELLINK
+	RTM_GETLINK,
+#define RTM_GETLINK	RTM_GETLINK
+	RTM_SETLINK,
+#define RTM_SETLINK	RTM_SETLINK
+
+	RTM_NEWADDR	= 20,
+#define RTM_NEWADDR	RTM_NEWADDR
+	RTM_DELADDR,
+#define RTM_DELADDR	RTM_DELADDR
+	RTM_GETADDR,
+#define RTM_GETADDR	RTM_GETADDR
+
+	RTM_NEWROUTE	= 24,
+#define RTM_NEWROUTE	RTM_NEWROUTE
+	RTM_DELROUTE,
+#define RTM_DELROUTE	RTM_DELROUTE
+	RTM_GETROUTE,
+#define RTM_GETROUTE	RTM_GETROUTE
+
+	RTM_NEWNEIGH	= 28,
+#define RTM_NEWNEIGH	RTM_NEWNEIGH
+	RTM_DELNEIGH,
+#define RTM_DELNEIGH	RTM_DELNEIGH
+	RTM_GETNEIGH,
+#define RTM_GETNEIGH	RTM_GETNEIGH
+
+	RTM_NEWRULE	= 32,
+#define RTM_NEWRULE	RTM_NEWRULE
+	RTM_DELRULE,
+#define RTM_DELRULE	RTM_DELRULE
+	RTM_GETRULE,
+#define RTM_GETRULE	RTM_GETRULE
+
+	RTM_NEWQDISC	= 36,
+#define RTM_NEWQDISC	RTM_NEWQDISC
+	RTM_DELQDISC,
+#define RTM_DELQDISC	RTM_DELQDISC
+	RTM_GETQDISC,
+#define RTM_GETQDISC	RTM_GETQDISC
+
+	RTM_NEWTCLASS	= 40,
+#define RTM_NEWTCLASS	RTM_NEWTCLASS
+	RTM_DELTCLASS,
+#define RTM_DELTCLASS	RTM_DELTCLASS
+	RTM_GETTCLASS,
+#define RTM_GETTCLASS	RTM_GETTCLASS
+
+	RTM_NEWTFILTER	= 44,
+#define RTM_NEWTFILTER	RTM_NEWTFILTER
+	RTM_DELTFILTER,
+#define RTM_DELTFILTER	RTM_DELTFILTER
+	RTM_GETTFILTER,
+#define RTM_GETTFILTER	RTM_GETTFILTER
+
+	RTM_NEWACTION	= 48,
+#define RTM_NEWACTION   RTM_NEWACTION
+	RTM_DELACTION,
+#define RTM_DELACTION   RTM_DELACTION
+	RTM_GETACTION,
+#define RTM_GETACTION   RTM_GETACTION
+
+	RTM_NEWPREFIX	= 52,
+#define RTM_NEWPREFIX	RTM_NEWPREFIX
+	RTM_GETPREFIX	= 54,
+#define RTM_GETPREFIX	RTM_GETPREFIX
+
+	RTM_GETMULTICAST = 58,
+#define RTM_GETMULTICAST RTM_GETMULTICAST
+
+	RTM_GETANYCAST	= 62,
+#define RTM_GETANYCAST	RTM_GETANYCAST
+
+	RTM_MAX,
+#define RTM_MAX		RTM_MAX
+};
 
 /* 
    Generic structure for encapsulation of optional route information.
@@ -541,6 +577,17 @@ struct rtnl_link_stats
 	__u32	tx_compressed;
 };
 
+/* The struct should be in sync with struct ifmap */
+struct rtnl_link_ifmap
+{
+	__u64	mem_start;
+	__u64	mem_end;
+	__u64	base_addr;
+	__u16	irq;
+	__u8	dma;
+	__u8	port;
+};
+
 enum
 {
 	IFLA_UNSPEC,
@@ -561,6 +608,12 @@ enum
 #define IFLA_WIRELESS IFLA_WIRELESS
 	IFLA_PROTINFO,		/* Protocol specific information for a link */
 #define IFLA_PROTINFO IFLA_PROTINFO
+	IFLA_TXQLEN,
+#define IFLA_TXQLEN IFLA_TXQLEN
+	IFLA_MAP,
+#define IFLA_MAP IFLA_MAP
+	IFLA_WEIGHT,
+#define IFLA_WEIGHT IFLA_WEIGHT
 	__IFLA_MAX
 };
 
@@ -654,10 +707,6 @@ enum
 #define TCA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcmsg))
 
 
-/* SUMMARY: maximal rtattr understood by kernel */
-
-#define RTATTR_MAX		RTA_MAX
-
 /* RTnetlink multicast groups */
 
 #define RTMGRP_LINK		1
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 7fc52d7b5..a4e287fd1 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -40,7 +40,6 @@ struct exec_domain;
 #define CLONE_FS	0x00000200	/* set if fs info shared between processes */
 #define CLONE_FILES	0x00000400	/* set if open files shared between processes */
 #define CLONE_SIGHAND	0x00000800	/* set if signal handlers and blocked signals shared */
-#define CLONE_IDLETASK	0x00001000	/* set if new pid should be 0 (kernel only)*/
 #define CLONE_PTRACE	0x00002000	/* set if we want to let tracing continue on the child too */
 #define CLONE_VFORK	0x00004000	/* set if the parent wants the child to wake it up on mm_release */
 #define CLONE_PARENT	0x00008000	/* set if we want to have the same parent as the cloner */
@@ -102,15 +101,15 @@ extern unsigned long nr_iowait(void);
 #include <linux/timer.h>
 
 #include <asm/processor.h>
-#include <linux/vserver/context.h>
 
 #define TASK_RUNNING		0
 #define TASK_INTERRUPTIBLE	1
 #define TASK_UNINTERRUPTIBLE	2
 #define TASK_STOPPED		4
-#define TASK_ZOMBIE		8
-#define TASK_DEAD		16
-#define TASK_ONHOLD		32
+#define TASK_TRACED		8
+#define TASK_ZOMBIE		16
+#define TASK_DEAD		32
+#define TASK_ONHOLD		64
 
 #define __set_task_state(tsk, state_value)		\
 	do { (tsk)->state = (state_value); } while (0)
@@ -191,10 +190,26 @@ extern int sysctl_max_map_count;
 
 #include <linux/aio.h>
 
+extern unsigned long
+arch_get_unmapped_area(struct file *, unsigned long, unsigned long,
+		       unsigned long, unsigned long);
+extern unsigned long
+arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
+			  unsigned long len, unsigned long pgoff,
+			  unsigned long flags);
+extern void arch_unmap_area(struct vm_area_struct *area);
+extern void arch_unmap_area_topdown(struct vm_area_struct *area);
+
+
 struct mm_struct {
 	struct vm_area_struct * mmap;		/* list of VMAs */
 	struct rb_root mm_rb;
 	struct vm_area_struct * mmap_cache;	/* last find_vma result */
+	unsigned long (*get_unmapped_area) (struct file *filp,
+				unsigned long addr, unsigned long len,
+				unsigned long pgoff, unsigned long flags);
+	void (*unmap_area) (struct vm_area_struct *area);
+	unsigned long mmap_base;		/* base of mmap area */
 	unsigned long free_area_cache;		/* first hole */
 	pgd_t * pgd;
 	atomic_t mm_users;			/* How many users with user space? */
@@ -211,10 +226,10 @@ struct mm_struct {
 	unsigned long start_code, end_code, start_data, end_data;
 	unsigned long start_brk, brk, start_stack;
 	unsigned long arg_start, arg_end, env_start, env_end;
-	unsigned long rss, total_vm, locked_vm;
-	unsigned long def_flags;
+	unsigned long rss, total_vm, locked_vm, shared_vm;
+	unsigned long exec_vm, stack_vm, reserved_vm, def_flags;
 
-	unsigned long saved_auxv[40]; /* for /proc/PID/auxv */
+	unsigned long saved_auxv[42]; /* for /proc/PID/auxv */
 
 	unsigned dumpable:1;
 	cpumask_t cpu_vm_mask;
@@ -223,6 +238,10 @@ struct mm_struct {
 	mm_context_t context;
 	struct vx_info *mm_vx_info;
 
+	/* Token based thrashing protection. */
+	unsigned long swap_token_time;
+	char recent_pagein;
+
 	/* coredumping support */
 	int core_waiters;
 	struct completion *core_startup_done, core_done;
@@ -271,6 +290,8 @@ struct signal_struct {
 
 	/* thread group stop support, overloads group_exit_code too */
 	int			group_stop_count;
+	/* 1 if group stopped since last SIGCONT, -1 if SIGCONT since report */
+  	int			stop_state;
 
 	/* POSIX.1b Interval Timers */
 	struct list_head posix_timers;
@@ -283,6 +304,16 @@ struct signal_struct {
 	int leader;
 
 	struct tty_struct *tty; /* NULL if no tty */
+
+	/*
+	 * Cumulative resource counters for dead threads in the group,
+	 * and for reaped dead child processes forked by this group.
+	 * Live threads maintain their own counters and add to these
+	 * in __exit_signal, except for the group leader.
+	 */
+	unsigned long utime, stime, cutime, cstime;
+	unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw;
+	unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt;
 };
 
 /*
@@ -303,7 +334,7 @@ struct signal_struct {
 
 #define MAX_PRIO		(MAX_RT_PRIO + 40)
 
-#define rt_task(p)		((p)->prio < MAX_RT_PRIO)
+#define rt_task(p)		(unlikely((p)->prio < MAX_RT_PRIO))
 
 /*
  * Some day this will be a full-fledged user tracking system..
@@ -315,6 +346,7 @@ struct user_struct {
 	atomic_t sigpending;	/* How many pending signals does this user have? */
 	/* protected by mq_lock	*/
 	unsigned long mq_bytes;	/* How many bytes can be allocated to mqueue? */
+	unsigned long locked_shm; /* How many pages of mlocked shm ? */
 
 	/* Hash table maintenance information */
 	struct list_head uidhash_list;
@@ -351,6 +383,20 @@ struct k_itimer {
 	struct timespec wall_to_prev;   /* wall_to_monotonic used when set */
 };
 
+#ifdef CONFIG_SCHEDSTATS
+struct sched_info {
+	/* cumulative counters */
+	unsigned long	cpu_time,	/* time spent on the cpu */
+			run_delay,	/* time spent waiting on a runqueue */
+			pcnt;		/* # of timeslices run on this cpu */
+
+	/* timestamps */
+	unsigned long	last_arrival,	/* when we last ran on a cpu */
+			last_queued;	/* when we were last queued to run */
+};
+
+extern struct file_operations proc_schedstat_operations;
+#endif
 
 struct io_context;			/* See blkdev.h */
 void exit_io_context(void);
@@ -406,13 +452,17 @@ struct task_struct {
 
 	unsigned long sleep_avg;
 	long interactive_credit;
-	unsigned long long timestamp;
+	unsigned long long timestamp, last_ran;
 	int activated;
 
 	unsigned long policy;
 	cpumask_t cpus_allowed;
 	unsigned int time_slice, first_time_slice;
 
+#ifdef CONFIG_SCHEDSTATS
+	struct sched_info sched_info;
+#endif
+
 	struct list_head tasks;
 	/*
 	 * ptrace_list/ptrace_children forms the list of my children
@@ -429,7 +479,7 @@ struct task_struct {
 	int pdeath_signal;  /*  The signal sent when the parent dies  */
 	/* ??? */
 	unsigned long personality;
-	int did_exec:1;
+	unsigned did_exec:1;
 	pid_t pid;
 	pid_t tgid;
 	/* 
@@ -448,7 +498,7 @@ struct task_struct {
 	struct task_struct *group_leader;	/* threadgroup leader */
 
 	/* PID/PID hash table linkage. */
-	struct pid_link pids[PIDTYPE_MAX];
+	struct pid pids[PIDTYPE_MAX];
 
 	wait_queue_head_t wait_chldexit;	/* for wait4() */
 	struct completion *vfork_done;		/* for vfork() */
@@ -459,17 +509,17 @@ struct task_struct {
 	unsigned long it_real_value, it_prof_value, it_virt_value;
 	unsigned long it_real_incr, it_prof_incr, it_virt_incr;
 	struct timer_list real_timer;
-	unsigned long utime, stime, cutime, cstime;
-	unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw; /* context switch counts */
-	u64 start_time;
+	unsigned long utime, stime;
+	unsigned long nvcsw, nivcsw; /* context switch counts */
+	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, cmin_flt, cmaj_flt;
+	unsigned long min_flt, maj_flt;
 /* process credentials */
 	uid_t uid,euid,suid,fsuid;
 	gid_t gid,egid,sgid,fsgid;
 	struct group_info *group_info;
 	kernel_cap_t   cap_effective, cap_inheritable, cap_permitted;
-	int keep_capabilities:1;
+	unsigned keep_capabilities:1;
 	struct user_struct *user;
 /* limits */
 	struct rlimit rlim[RLIM_NLIMITS];
@@ -534,7 +584,13 @@ struct task_struct {
 
 	unsigned long ptrace_message;
 	siginfo_t *last_siginfo; /* For ptrace use.  */
-
+/*
+ * current io wait handle: wait queue entry to use for io waits
+ * If this thread is processing aio, this points at the waitqueue
+ * inside the currently handled kiocb. It may be NULL (i.e. default
+ * to a stack based synchronous wait) if its doing sync IO.
+ */
+	wait_queue_t *io_wait;
 #ifdef CONFIG_NUMA
   	struct mempolicy *mempolicy;
   	short il_next;		/* could be shared with used_math */
@@ -546,6 +602,7 @@ static inline pid_t process_group(struct task_struct *tsk)
 	return tsk->signal->pgrp;
 }
 
+extern void free_task(struct task_struct *tsk);
 extern void __put_task_struct(struct task_struct *tsk);
 #define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0)
 #define put_task_struct(tsk) \
@@ -577,118 +634,6 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0)
 #define PF_SYNCWRITE	0x00200000	/* I am doing a sync write */
 
 #ifdef CONFIG_SMP
-#define SCHED_LOAD_SCALE	128UL	/* increase resolution of load */
-
-#define SD_BALANCE_NEWIDLE	1	/* Balance when about to become idle */
-#define SD_BALANCE_EXEC		2	/* Balance on exec */
-#define SD_BALANCE_CLONE	4	/* Balance on clone */
-#define SD_WAKE_IDLE		8	/* Wake to idle CPU on task wakeup */
-#define SD_WAKE_AFFINE		16	/* Wake task to waking CPU */
-#define SD_WAKE_BALANCE		32	/* Perform balancing at task wakeup */
-#define SD_SHARE_CPUPOWER	64	/* Domain members share cpu power */
-
-struct sched_group {
-	struct sched_group *next;	/* Must be a circular list */
-	cpumask_t cpumask;
-
-	/*
-	 * CPU power of this group, SCHED_LOAD_SCALE being max power for a
-	 * single CPU. This should be read only (except for setup). Although
-	 * it will need to be written to at cpu hot(un)plug time, perhaps the
-	 * cpucontrol semaphore will provide enough exclusion?
-	 */
-	unsigned long cpu_power;
-};
-
-struct sched_domain {
-	/* These fields must be setup */
-	struct sched_domain *parent;	/* top domain must be null terminated */
-	struct sched_group *groups;	/* the balancing groups of the domain */
-	cpumask_t span;			/* span of all CPUs in this domain */
-	unsigned long min_interval;	/* Minimum balance interval ms */
-	unsigned long max_interval;	/* Maximum balance interval ms */
-	unsigned int busy_factor;	/* less balancing by factor if busy */
-	unsigned int imbalance_pct;	/* No balance until over watermark */
-	unsigned long long cache_hot_time; /* Task considered cache hot (ns) */
-	unsigned int cache_nice_tries;	/* Leave cache hot tasks for # tries */
-	unsigned int per_cpu_gain;	/* CPU % gained by adding domain cpus */
-	int flags;			/* See SD_* */
-
-	/* Runtime fields. */
-	unsigned long last_balance;	/* init to jiffies. units in jiffies */
-	unsigned int balance_interval;	/* initialise to 1. units in ms. */
-	unsigned int nr_balance_failed; /* initialise to 0 */
-};
-
-/* Common values for SMT siblings */
-#define SD_SIBLING_INIT (struct sched_domain) {		\
-	.span			= CPU_MASK_NONE,	\
-	.parent			= NULL,			\
-	.groups			= NULL,			\
-	.min_interval		= 1,			\
-	.max_interval		= 2,			\
-	.busy_factor		= 8,			\
-	.imbalance_pct		= 110,			\
-	.cache_hot_time		= 0,			\
-	.cache_nice_tries	= 0,			\
-	.per_cpu_gain		= 15,			\
-	.flags			= SD_BALANCE_NEWIDLE	\
-				| SD_BALANCE_EXEC	\
-				| SD_BALANCE_CLONE	\
-				| SD_WAKE_AFFINE	\
-				| SD_WAKE_IDLE		\
-				| SD_SHARE_CPUPOWER,	\
-	.last_balance		= jiffies,		\
-	.balance_interval	= 1,			\
-	.nr_balance_failed	= 0,			\
-}
-
-/* Common values for CPUs */
-#define SD_CPU_INIT (struct sched_domain) {		\
-	.span			= CPU_MASK_NONE,	\
-	.parent			= NULL,			\
-	.groups			= NULL,			\
-	.min_interval		= 1,			\
-	.max_interval		= 4,			\
-	.busy_factor		= 64,			\
-	.imbalance_pct		= 125,			\
-	.cache_hot_time		= (5*1000000/2),	\
-	.cache_nice_tries	= 1,			\
-	.per_cpu_gain		= 100,			\
-	.flags			= SD_BALANCE_NEWIDLE	\
-				| SD_BALANCE_EXEC	\
-				| SD_BALANCE_CLONE	\
-				| SD_WAKE_AFFINE	\
-				| SD_WAKE_BALANCE,	\
-	.last_balance		= jiffies,		\
-	.balance_interval	= 1,			\
-	.nr_balance_failed	= 0,			\
-}
-
-#ifdef CONFIG_NUMA
-/* Common values for NUMA nodes */
-#define SD_NODE_INIT (struct sched_domain) {		\
-	.span			= CPU_MASK_NONE,	\
-	.parent			= NULL,			\
-	.groups			= NULL,			\
-	.min_interval		= 8,			\
-	.max_interval		= 32,			\
-	.busy_factor		= 32,			\
-	.imbalance_pct		= 125,			\
-	.cache_hot_time		= (10*1000000),		\
-	.cache_nice_tries	= 1,			\
-	.per_cpu_gain		= 100,			\
-	.flags			= SD_BALANCE_EXEC	\
-				| SD_BALANCE_CLONE	\
-				| SD_WAKE_BALANCE,	\
-	.last_balance		= jiffies,		\
-	.balance_interval	= 1,			\
-	.nr_balance_failed	= 0,			\
-}
-#endif
-
-extern void cpu_attach_domain(struct sched_domain *sd, int cpu);
-
 extern int set_cpus_allowed(task_t *p, cpumask_t new_mask);
 #else
 static inline int set_cpus_allowed(task_t *p, cpumask_t new_mask)
@@ -699,10 +644,11 @@ static inline int set_cpus_allowed(task_t *p, cpumask_t new_mask)
 
 extern unsigned long long sched_clock(void);
 
+/* sched_exec is called by processes performing an exec */
 #ifdef CONFIG_SMP
-extern void sched_balance_exec(void);
+extern void sched_exec(void);
 #else
-#define sched_balance_exec()   {}
+#define sched_exec()   {}
 #endif
 
 extern void sched_idle_next(void);
@@ -739,7 +685,14 @@ extern struct task_struct init_task;
 
 extern struct   mm_struct init_mm;
 
-extern struct task_struct *find_task_by_pid(int pid);
+
+#define find_task_by_real_pid(nr) \
+	find_task_by_pid_type(PIDTYPE_PID, nr)
+#define find_task_by_pid(nr) \
+	find_task_by_pid_type(PIDTYPE_PID, \
+		vx_rmap_pid(nr))
+
+extern struct task_struct *find_task_by_pid_type(int type, int pid);
 extern void set_special_pids(pid_t session, pid_t pgrp);
 extern void __set_special_pids(pid_t session, pid_t pgrp);
 
@@ -761,16 +714,12 @@ extern void do_timer(struct pt_regs *);
 
 extern int FASTCALL(wake_up_state(struct task_struct * tsk, unsigned int state));
 extern int FASTCALL(wake_up_process(struct task_struct * tsk));
-extern void FASTCALL(wake_up_forked_process(struct task_struct * tsk));
+extern void FASTCALL(wake_up_new_task(struct task_struct * tsk,
+						unsigned long clone_flags));
 #ifdef CONFIG_SMP
  extern void kick_process(struct task_struct *tsk);
- extern void FASTCALL(wake_up_forked_thread(struct task_struct * tsk));
 #else
  static inline void kick_process(struct task_struct *tsk) { }
- static inline void wake_up_forked_thread(struct task_struct * tsk)
- {
-	wake_up_forked_process(tsk);
- }
 #endif
 extern void FASTCALL(sched_fork(task_t * p));
 extern void FASTCALL(sched_exit(task_t * p));
@@ -801,12 +750,12 @@ extern void unblock_all_signals(void);
 extern void release_task(struct task_struct * p);
 extern int send_sig_info(int, struct siginfo *, struct task_struct *);
 extern int send_group_sig_info(int, struct siginfo *, struct task_struct *);
+extern int force_sigsegv(int, struct task_struct *);
 extern int force_sig_info(int, struct siginfo *, struct task_struct *);
 extern int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp);
 extern int kill_pg_info(int, struct siginfo *, pid_t);
 extern int kill_sl_info(int, struct siginfo *, pid_t);
 extern int kill_proc_info(int, struct siginfo *, pid_t);
-extern void notify_parent(struct task_struct *, int);
 extern void do_notify_parent(struct task_struct *, int);
 extern void force_sig(int, struct task_struct *);
 extern void force_sig_specific(int, struct task_struct *);
@@ -870,8 +819,8 @@ static inline void mmdrop(struct mm_struct * mm)
 
 /* mmput gets rid of the mappings and all user-space */
 extern void mmput(struct mm_struct *);
-/* Grab a reference to the mm if its not already going away */
-extern struct mm_struct *mmgrab(struct mm_struct *);
+/* Grab a reference to a task's mm, if it is not already going away */
+extern struct mm_struct *get_task_mm(struct task_struct *task);
 /* Remove the current tasks stale references to the old mm_struct */
 extern void mm_release(struct task_struct *, struct mm_struct *);
 
@@ -897,7 +846,10 @@ extern task_t *child_reaper;
 
 extern int do_execve(char *, char __user * __user *, char __user * __user *, struct pt_regs *);
 extern long do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *);
-extern struct task_struct * copy_process(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *);
+task_t *fork_idle(int);
+
+extern void set_task_comm(struct task_struct *tsk, char *from);
+extern void get_task_comm(char *to, struct task_struct *tsk);
 
 #ifdef CONFIG_SMP
 extern void wait_task_inactive(task_t * p);
@@ -942,9 +894,7 @@ extern task_t * FASTCALL(next_thread(const task_t *p));
 
 static inline int thread_group_empty(task_t *p)
 {
-	struct pid *pid = p->pids[PIDTYPE_TGID].pidptr;
-
-	return pid->task_list.next->next == &pid->task_list;
+	return list_empty(&p->pids[PIDTYPE_TGID].pid_list);
 }
 
 #define delay_group_leader(p) \
@@ -953,8 +903,8 @@ static inline int thread_group_empty(task_t *p)
 extern void unhash_process(struct task_struct *p);
 
 /*
- * Protects ->fs, ->files, ->mm, ->ptrace, ->group_info and synchronises with
- * wait4().
+ * Protects ->fs, ->files, ->mm, ->ptrace, ->group_info, ->comm and
+ * synchronises with wait4().
  *
  * Nests both inside and outside of read_lock(&tasklist_lock).
  * It must not be nested with write_lock_irq(&tasklist_lock),
@@ -969,27 +919,7 @@ static inline void task_unlock(struct task_struct *p)
 {
 	spin_unlock(&p->alloc_lock);
 }
- 
-/**
- * get_task_mm - acquire a reference to the task's mm
- *
- * Returns %NULL if the task has no mm. User must release
- * the mm via mmput() after use.
- */
-static inline struct mm_struct * get_task_mm(struct task_struct * task)
-{
-	struct mm_struct * mm;
- 
-	task_lock(task);
-	mm = task->mm;
-	if (mm)
-		mm = mmgrab(mm);
-	task_unlock(task);
-
-	return mm;
-}
- 
- 
+
 /* set thread flags in other task's structures
  * - see asm/thread_info.h for TIF_xxxx flags available
  */
@@ -1100,6 +1030,20 @@ static inline void set_task_cpu(struct task_struct *p, unsigned int cpu)
 
 #endif /* CONFIG_SMP */
 
+#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
+extern void arch_pick_mmap_layout(struct mm_struct *mm);
+#else
+static inline void arch_pick_mmap_layout(struct mm_struct *mm)
+{
+	mm->mmap_base = TASK_UNMAPPED_BASE;
+	mm->get_unmapped_area = arch_get_unmapped_area;
+	mm->unmap_area = arch_unmap_area;
+}
+#endif
+
+extern long sched_setaffinity(pid_t pid, cpumask_t new_mask);
+extern long sched_getaffinity(pid_t pid, cpumask_t *mask);
+
 #endif /* __KERNEL__ */
 
 #endif
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index e7e8bb92a..daffe8c51 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -176,6 +176,7 @@ struct uart_port {
 #define UPIO_PORT		(0)
 #define UPIO_HUB6		(1)
 #define UPIO_MEM		(2)
+#define UPIO_MEM32		(3)
 
 	unsigned int		read_status_mask;	/* driver specific */
 	unsigned int		ignore_status_mask;	/* driver specific */
diff --git a/include/linux/serio.h b/include/linux/serio.h
index be0ccba86..f84b362a5 100644
--- a/include/linux/serio.h
+++ b/include/linux/serio.h
@@ -17,12 +17,17 @@
 #ifdef __KERNEL__
 
 #include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
 
 struct serio {
 	void *private;
-	void *driver;
-	char *name;
-	char *phys;
+	void *port_data;
+
+	char name[32];
+	char phys[32];
+
+	unsigned int manual_bind;
 
 	unsigned short idbus;
 	unsigned short idvendor;
@@ -32,31 +37,43 @@ struct serio {
 	unsigned long type;
 	unsigned long event;
 
+	spinlock_t lock;		/* protects critical sections from port's interrupt handler */
+
 	int (*write)(struct serio *, unsigned char);
 	int (*open)(struct serio *);
 	void (*close)(struct serio *);
 
-	struct serio_dev *dev;
+	struct serio *parent, *child;
+
+	struct serio_driver *drv;	/* accessed from interrupt, must be protected by serio->lock */
+
+	struct device dev;
 
 	struct list_head node;
 };
+#define to_serio_port(d)	container_of(d, struct serio, dev)
 
-struct serio_dev {
+struct serio_driver {
 	void *private;
-	char *name;
+	char *description;
+
+	unsigned int manual_bind;
 
 	void (*write_wakeup)(struct serio *);
 	irqreturn_t (*interrupt)(struct serio *, unsigned char,
 			unsigned int, struct pt_regs *);
-	void (*connect)(struct serio *, struct serio_dev *dev);
+	void (*connect)(struct serio *, struct serio_driver *drv);
 	int  (*reconnect)(struct serio *);
 	void (*disconnect)(struct serio *);
 	void (*cleanup)(struct serio *);
 
+	struct device_driver driver;
+
 	struct list_head node;
 };
+#define to_serio_driver(d)	container_of(d, struct serio_driver, driver)
 
-int serio_open(struct serio *serio, struct serio_dev *dev);
+int serio_open(struct serio *serio, struct serio_driver *drv);
 void serio_close(struct serio *serio);
 void serio_rescan(struct serio *serio);
 void serio_reconnect(struct serio *serio);
@@ -64,12 +81,11 @@ irqreturn_t serio_interrupt(struct serio *serio, unsigned char data, unsigned in
 
 void serio_register_port(struct serio *serio);
 void serio_register_port_delayed(struct serio *serio);
-void __serio_register_port(struct serio *serio);
 void serio_unregister_port(struct serio *serio);
 void serio_unregister_port_delayed(struct serio *serio);
-void __serio_unregister_port(struct serio *serio);
-void serio_register_device(struct serio_dev *dev);
-void serio_unregister_device(struct serio_dev *dev);
+
+void serio_register_driver(struct serio_driver *drv);
+void serio_unregister_driver(struct serio_driver *drv);
 
 static __inline__ int serio_write(struct serio *serio, unsigned char data)
 {
@@ -79,18 +95,34 @@ static __inline__ int serio_write(struct serio *serio, unsigned char data)
 		return -1;
 }
 
-static __inline__ void serio_dev_write_wakeup(struct serio *serio)
+static __inline__ void serio_drv_write_wakeup(struct serio *serio)
 {
-	if (serio->dev && serio->dev->write_wakeup)
-		serio->dev->write_wakeup(serio);
+	if (serio->drv && serio->drv->write_wakeup)
+		serio->drv->write_wakeup(serio);
 }
 
 static __inline__ void serio_cleanup(struct serio *serio)
 {
-	if (serio->dev && serio->dev->cleanup)
-		serio->dev->cleanup(serio);
+	if (serio->drv && serio->drv->cleanup)
+		serio->drv->cleanup(serio);
+}
+
+
+/*
+ * Use the following fucntions to protect critical sections in
+ * driver code from port's interrupt handler
+ */
+static __inline__ void serio_pause_rx(struct serio *serio)
+{
+	spin_lock_irq(&serio->lock);
 }
 
+static __inline__ void serio_continue_rx(struct serio *serio)
+{
+	spin_unlock_irq(&serio->lock);
+}
+
+
 #endif
 
 /*
diff --git a/include/linux/shm.h b/include/linux/shm.h
index 9a00f5ff6..80113a1f6 100644
--- a/include/linux/shm.h
+++ b/include/linux/shm.h
@@ -44,6 +44,7 @@ struct shmid_ds {
 #define	SHM_RDONLY	010000	/* read-only access */
 #define	SHM_RND		020000	/* round attach address to SHMLBA boundary */
 #define	SHM_REMAP	040000	/* take-over region on attach */
+#define	SHM_EXEC	0100000	/* execution access */
 
 /* super user shmctl commands */
 #define SHM_LOCK 	11
@@ -84,6 +85,7 @@ struct shmid_kernel /* private to the kernel */
 	time_t			shm_ctim;
 	pid_t			shm_cprid;
 	pid_t			shm_lprid;
+	struct user_struct	*mlock_user;
 };
 
 /* shm_mode upper byte flags */
diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
index 14a618109..e57a7ce84 100644
--- a/include/linux/shmem_fs.h
+++ b/include/linux/shmem_fs.h
@@ -13,14 +13,14 @@
 
 struct shmem_inode_info {
 	spinlock_t		lock;
-	unsigned long		next_index;
-	swp_entry_t		i_direct[SHMEM_NR_DIRECT]; /* for the first blocks */
-	struct page	       *i_indirect; /* indirect blocks */
-	unsigned long		alloced;    /* data pages allocated to file */
-	unsigned long		swapped;    /* subtotal assigned to swap */
 	unsigned long		flags;
-	struct shared_policy     policy;
-	struct list_head	list;
+	unsigned long		alloced;	/* data pages alloced to file */
+	unsigned long		swapped;	/* subtotal assigned to swap */
+	unsigned long		next_index;	/* highest alloced index + 1 */
+	struct shared_policy	policy;		/* NUMA memory alloc policy */
+	struct page		*i_indirect;	/* top indirect blocks page */
+	swp_entry_t		i_direct[SHMEM_NR_DIRECT]; /* first blocks */
+	struct list_head	swaplist;	/* chain of maybes on swap */
 	struct inode		vfs_inode;
 };
 
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 2407dd888..e5f3d83ab 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -217,7 +217,7 @@ extern int sigprocmask(int, sigset_t *, sigset_t *);
 
 #ifndef HAVE_ARCH_GET_SIGNAL_TO_DELIVER
 struct pt_regs;
-extern int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs, void *cookie);
+extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie);
 #endif
 
 #endif /* __KERNEL__ */
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 724d6841d..71fc2bdc0 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -89,16 +89,14 @@
 #define NET_CALLER(arg) __builtin_return_address(0)
 #endif
 
+struct net_device;
+
 #ifdef CONFIG_NETFILTER
 struct nf_conntrack {
 	atomic_t use;
 	void (*destroy)(struct nf_conntrack *);
 };
 
-struct nf_ct_info {
-	struct nf_conntrack *master;
-};
-
 #ifdef CONFIG_BRIDGE_NETFILTER
 struct nf_bridge_info {
 	atomic_t use;
@@ -184,6 +182,7 @@ struct skb_shared_info {
  *	@nfmark: Can be used for communication between hooks
  *	@nfcache: Cache info
  *	@nfct: Associated connection, if any
+ *	@nfctinfo: Relationship of this skb to the connection
  *	@nf_debug: Netfilter debugging
  *	@nf_bridge: Saved data about a bridged frame - see br_netfilter.c
  *      @private: Data which is private to the HIPPI implementation
@@ -220,7 +219,6 @@ struct sk_buff {
 	} nh;
 
 	union {
-	  	struct ethhdr	*ethernet;
 	  	unsigned char 	*raw;
 	} mac;
 
@@ -251,7 +249,8 @@ struct sk_buff {
 #ifdef CONFIG_NETFILTER
         unsigned long		nfmark;
 	__u32			nfcache;
-	struct nf_ct_info	*nfct;
+	__u32			nfctinfo;
+	struct nf_conntrack	*nfct;
 #ifdef CONFIG_NETFILTER_DEBUG
         unsigned int		nf_debug;
 #endif
@@ -269,7 +268,7 @@ struct sk_buff {
 #ifdef CONFIG_NET_CLS_ACT
 	__u32           tc_verd;               /* traffic control verdict */
 	__u32           tc_classid;            /* traffic control classid */
- #endif
+#endif
 
 #endif
 
@@ -1105,6 +1104,20 @@ extern void	       skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to);
 extern void	       skb_split(struct sk_buff *skb,
 				 struct sk_buff *skb1, const u32 len);
 
+static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
+				       int len, void *buffer)
+{
+	int hlen = skb_headlen(skb);
+
+	if (offset + len <= hlen)
+		return skb->data + offset;
+
+	if (skb_copy_bits(skb, offset, buffer, len) < 0)
+		return NULL;
+
+	return buffer;
+}
+
 extern void skb_init(void);
 extern void skb_add_mtu(int mtu);
 
@@ -1125,15 +1138,15 @@ extern int skb_iter_next(const struct sk_buff *skb, struct skb_iter *i);
 extern void skb_iter_abort(const struct sk_buff *skb, struct skb_iter *i);
 
 #ifdef CONFIG_NETFILTER
-static inline void nf_conntrack_put(struct nf_ct_info *nfct)
+static inline void nf_conntrack_put(struct nf_conntrack *nfct)
 {
-	if (nfct && atomic_dec_and_test(&nfct->master->use))
-		nfct->master->destroy(nfct->master);
+	if (nfct && atomic_dec_and_test(&nfct->use))
+		nfct->destroy(nfct);
 }
-static inline void nf_conntrack_get(struct nf_ct_info *nfct)
+static inline void nf_conntrack_get(struct nf_conntrack *nfct)
 {
 	if (nfct)
-		atomic_inc(&nfct->master->use);
+		atomic_inc(&nfct->use);
 }
 static inline void nf_reset(struct sk_buff *skb)
 {
@@ -1143,6 +1156,12 @@ static inline void nf_reset(struct sk_buff *skb)
 	skb->nf_debug = 0;
 #endif
 }
+static inline void nf_reset_debug(struct sk_buff *skb)
+{
+#ifdef CONFIG_NETFILTER_DEBUG
+	skb->nf_debug = 0;
+#endif
+}
 
 #ifdef CONFIG_BRIDGE_NETFILTER
 static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
diff --git a/include/linux/slab.h b/include/linux/slab.h
index e60ff6399..e51014cb2 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -4,7 +4,7 @@
  * (markhe@nextd.demon.co.uk)
  */
 
-#if	!defined(_LINUX_SLAB_H)
+#ifndef _LINUX_SLAB_H
 #define	_LINUX_SLAB_H
 
 #if	defined(__KERNEL__)
@@ -45,6 +45,7 @@ typedef struct kmem_cache_s kmem_cache_t;
 #define SLAB_RECLAIM_ACCOUNT	0x00020000UL	/* track pages allocated to indicate
 						   what is reclaimable later*/
 #define SLAB_PANIC		0x00040000UL	/* panic if kmem_cache_create() fails */
+#define SLAB_DESTROY_BY_RCU	0x00080000UL	/* defer freeing pages to RCU */
 
 /* flags passed to a constructor func */
 #define	SLAB_CTOR_CONSTRUCTOR	0x001UL		/* if not set, then deconstructor */
@@ -54,7 +55,6 @@ typedef struct kmem_cache_s kmem_cache_t;
 /* prototypes */
 extern void kmem_cache_init(void);
 
-extern kmem_cache_t *kmem_find_general_cachep(size_t, int gfpflags);
 extern kmem_cache_t *kmem_cache_create(const char *, size_t, size_t, unsigned long,
 				       void (*)(void *, kmem_cache_t *, unsigned long),
 				       void (*)(void *, kmem_cache_t *, unsigned long));
@@ -97,6 +97,7 @@ found:
 	return __kmalloc(size, flags);
 }
 
+extern void *kcalloc(size_t, size_t, int);
 extern void kfree(const void *);
 extern unsigned int ksize(const void *);
 
@@ -115,8 +116,6 @@ extern kmem_cache_t	*signal_cachep;
 extern kmem_cache_t	*sighand_cachep;
 extern kmem_cache_t	*bio_cachep;
 
-void ptrinfo(unsigned long addr);
-
 extern atomic_t slab_reclaim_pages;
 
 #endif	/* __KERNEL__ */
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 3a18d6e0a..b3aef7bf1 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -140,7 +140,6 @@ __KINLINE struct cmsghdr * cmsg_nxthdr (struct msghdr *__msg, struct cmsghdr *__
 
 #define	SCM_RIGHTS	0x01		/* rw: access rights (array of int) */
 #define SCM_CREDENTIALS 0x02		/* rw: struct ucred		*/
-#define SCM_CONNECT	0x03		/* rw: struct scm_connect	*/
 
 struct ucred {
 	__u32	pid;
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index de381ec1e..37852d55f 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -19,18 +19,18 @@
 /*
  * Must define these before including other files, inline functions need them
  */
-#define LOCK_SECTION_NAME			\
-	".text.lock." __stringify(KBUILD_BASENAME)
+#define LOCK_SECTION_NAME                       \
+        ".text.lock." __stringify(KBUILD_BASENAME)
 
-#define LOCK_SECTION_START(extra)		\
-	".subsection 1\n\t"			\
-	extra					\
-	".ifndef " LOCK_SECTION_NAME "\n\t"	\
-	LOCK_SECTION_NAME ":\n\t"		\
-	".endif\n\t"
+#define LOCK_SECTION_START(extra)               \
+        ".subsection 1\n\t"                     \
+        extra                                   \
+        ".ifndef " LOCK_SECTION_NAME "\n\t"     \
+        LOCK_SECTION_NAME ":\n\t"               \
+        ".endif\n\t"
 
-#define LOCK_SECTION_END			\
-	".previous\n\t"
+#define LOCK_SECTION_END                        \
+        ".previous\n\t"
 
 /*
  * If CONFIG_SMP is set, pull in the _raw_* definitions
@@ -38,9 +38,40 @@
 #ifdef CONFIG_SMP
 #include <asm/spinlock.h>
 
+#define __lockfunc fastcall __attribute__((section(".spinlock.text")))
+
+int __lockfunc _spin_trylock(spinlock_t *lock);
+int __lockfunc _write_trylock(rwlock_t *lock);
+void __lockfunc _spin_lock(spinlock_t *lock);
+void __lockfunc _write_lock(rwlock_t *lock);
+void __lockfunc _spin_lock(spinlock_t *lock);
+void __lockfunc _read_lock(rwlock_t *lock);
+void __lockfunc _spin_unlock(spinlock_t *lock);
+void __lockfunc _write_unlock(rwlock_t *lock);
+void __lockfunc _read_unlock(rwlock_t *lock);
+unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock);
+unsigned long __lockfunc _read_lock_irqsave(rwlock_t *lock);
+unsigned long __lockfunc _write_lock_irqsave(rwlock_t *lock);
+void __lockfunc _spin_lock_irq(spinlock_t *lock);
+void __lockfunc _spin_lock_bh(spinlock_t *lock);
+void __lockfunc _read_lock_irq(rwlock_t *lock);
+void __lockfunc _read_lock_bh(rwlock_t *lock);
+void __lockfunc _write_lock_irq(rwlock_t *lock);
+void __lockfunc _write_lock_bh(rwlock_t *lock);
+void __lockfunc _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags);
+void __lockfunc _spin_unlock_irq(spinlock_t *lock);
+void __lockfunc _spin_unlock_bh(spinlock_t *lock);
+void __lockfunc _read_unlock_irqrestore(rwlock_t *lock, unsigned long flags);
+void __lockfunc _read_unlock_irq(rwlock_t *lock);
+void __lockfunc _read_unlock_bh(rwlock_t *lock);
+void __lockfunc _write_unlock_irqrestore(rwlock_t *lock, unsigned long flags);
+void __lockfunc _write_unlock_irq(rwlock_t *lock);
+void __lockfunc _write_unlock_bh(rwlock_t *lock);
+int __lockfunc _spin_trylock_bh(spinlock_t *lock);
+int in_lock_functions(unsigned long addr);
 #else
 
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+#define in_lock_functions(ADDR) 0
 
 #if !defined(CONFIG_PREEMPT) && !defined(CONFIG_DEBUG_SPINLOCK)
 # define atomic_dec_and_lock(atomic,lock) atomic_dec_and_test(atomic)
@@ -162,9 +193,9 @@ typedef struct {
 #define spin_lock_init(lock)	do { (void)(lock); } while(0)
 #define _raw_spin_lock(lock)	do { (void)(lock); } while(0)
 #define spin_is_locked(lock)	((void)(lock), 0)
-#define _raw_spin_trylock(lock)	((void)(lock), 1)
-#define spin_unlock_wait(lock)	do { (void)(lock); } while(0)
-#define _raw_spin_unlock(lock)	do { (void)(lock); } while(0)
+#define _raw_spin_trylock(lock)	(((void)(lock), 1))
+#define spin_unlock_wait(lock)	(void)(lock);
+#define _raw_spin_unlock(lock) do { (void)(lock); } while(0)
 #endif /* CONFIG_DEBUG_SPINLOCK */
 
 /* RW spinlocks: No debug version */
@@ -184,141 +215,116 @@ typedef struct {
 #define _raw_write_unlock(lock)	do { (void)(lock); } while(0)
 #define _raw_write_trylock(lock) ({ (void)(lock); (1); })
 
-#endif /* !SMP */
-
-/*
- * Define the various spin_lock and rw_lock methods.  Note we define these
- * regardless of whether CONFIG_SMP or CONFIG_PREEMPT are set. The various
- * methods are defined as nops in the case they are not required.
- */
-#define spin_trylock(lock)	({preempt_disable(); _raw_spin_trylock(lock) ? \
+#define _spin_trylock(lock)	({preempt_disable(); _raw_spin_trylock(lock) ? \
 				1 : ({preempt_enable(); 0;});})
 
-#define write_trylock(lock)	({preempt_disable();_raw_write_trylock(lock) ? \
+#define _write_trylock(lock)	({preempt_disable(); _raw_write_trylock(lock) ? \
 				1 : ({preempt_enable(); 0;});})
 
-/* Where's read_trylock? */
-
-#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT)
-void __preempt_spin_lock(spinlock_t *lock);
-void __preempt_write_lock(rwlock_t *lock);
-
-#define spin_lock(lock) \
-do { \
-	preempt_disable(); \
-	if (unlikely(!_raw_spin_trylock(lock))) \
-		__preempt_spin_lock(lock); \
-} while (0)
-
-#define write_lock(lock) \
-do { \
-	preempt_disable(); \
-	if (unlikely(!_raw_write_trylock(lock))) \
-		__preempt_write_lock(lock); \
-} while (0)
+#define _spin_trylock_bh(lock)	({preempt_disable(); local_bh_disable(); \
+				_raw_spin_trylock(lock) ? \
+				1 : ({preempt_enable(); local_bh_enable(); 0;});})
 
-#else
-#define spin_lock(lock)	\
+#define _spin_lock(lock)	\
 do { \
 	preempt_disable(); \
 	_raw_spin_lock(lock); \
 } while(0)
 
-#define write_lock(lock) \
+#define _write_lock(lock) \
 do { \
 	preempt_disable(); \
 	_raw_write_lock(lock); \
 } while(0)
-#endif
-
-#define read_lock(lock)	\
+ 
+#define _read_lock(lock)	\
 do { \
 	preempt_disable(); \
 	_raw_read_lock(lock); \
 } while(0)
 
-#define spin_unlock(lock) \
+#define _spin_unlock(lock) \
 do { \
 	_raw_spin_unlock(lock); \
 	preempt_enable(); \
 } while (0)
 
-#define write_unlock(lock) \
+#define _write_unlock(lock) \
 do { \
 	_raw_write_unlock(lock); \
 	preempt_enable(); \
 } while(0)
 
-#define read_unlock(lock) \
+#define _read_unlock(lock) \
 do { \
 	_raw_read_unlock(lock); \
 	preempt_enable(); \
 } while(0)
 
-#define spin_lock_irqsave(lock, flags) \
-do { \
+#define _spin_lock_irqsave(lock, flags) \
+do {	\
 	local_irq_save(flags); \
 	preempt_disable(); \
-	_raw_spin_lock_flags(lock, flags); \
+	_raw_spin_lock(lock); \
 } while (0)
 
-#define spin_lock_irq(lock) \
+#define _spin_lock_irq(lock) \
 do { \
 	local_irq_disable(); \
 	preempt_disable(); \
 	_raw_spin_lock(lock); \
 } while (0)
 
-#define spin_lock_bh(lock) \
+#define _spin_lock_bh(lock) \
 do { \
 	local_bh_disable(); \
 	preempt_disable(); \
 	_raw_spin_lock(lock); \
 } while (0)
 
-#define read_lock_irqsave(lock, flags) \
-do { \
+#define _read_lock_irqsave(lock, flags) \
+do {	\
 	local_irq_save(flags); \
 	preempt_disable(); \
 	_raw_read_lock(lock); \
 } while (0)
 
-#define read_lock_irq(lock) \
+#define _read_lock_irq(lock) \
 do { \
 	local_irq_disable(); \
 	preempt_disable(); \
 	_raw_read_lock(lock); \
 } while (0)
 
-#define read_lock_bh(lock) \
+#define _read_lock_bh(lock) \
 do { \
 	local_bh_disable(); \
 	preempt_disable(); \
 	_raw_read_lock(lock); \
 } while (0)
 
-#define write_lock_irqsave(lock, flags) \
-do { \
+#define _write_lock_irqsave(lock, flags) \
+do {	\
 	local_irq_save(flags); \
 	preempt_disable(); \
 	_raw_write_lock(lock); \
 } while (0)
 
-#define write_lock_irq(lock) \
+#define _write_lock_irq(lock) \
 do { \
 	local_irq_disable(); \
 	preempt_disable(); \
 	_raw_write_lock(lock); \
 } while (0)
 
-#define write_lock_bh(lock) \
+#define _write_lock_bh(lock) \
 do { \
 	local_bh_disable(); \
 	preempt_disable(); \
 	_raw_write_lock(lock); \
 } while (0)
 
-#define spin_unlock_irqrestore(lock, flags) \
+#define _spin_unlock_irqrestore(lock, flags) \
 do { \
 	_raw_spin_unlock(lock); \
 	local_irq_restore(flags); \
@@ -331,65 +337,123 @@ do { \
 	local_irq_restore(flags); \
 } while (0)
 
-#define spin_unlock_irq(lock) \
+#define _spin_unlock_irq(lock) \
 do { \
 	_raw_spin_unlock(lock); \
 	local_irq_enable(); \
 	preempt_enable(); \
 } while (0)
 
-#define spin_unlock_bh(lock) \
+#define _spin_unlock_bh(lock) \
 do { \
 	_raw_spin_unlock(lock); \
 	preempt_enable(); \
 	local_bh_enable(); \
 } while (0)
 
-#define read_unlock_irqrestore(lock, flags) \
+#define _write_unlock_bh(lock) \
 do { \
-	_raw_read_unlock(lock); \
-	local_irq_restore(flags); \
+	_raw_write_unlock(lock); \
 	preempt_enable(); \
+	local_bh_enable(); \
 } while (0)
 
-#define read_unlock_irq(lock) \
+#define _read_unlock_irqrestore(lock, flags) \
 do { \
 	_raw_read_unlock(lock); \
-	local_irq_enable(); \
+	local_irq_restore(flags); \
 	preempt_enable(); \
 } while (0)
 
-#define read_unlock_bh(lock) \
+#define _write_unlock_irqrestore(lock, flags) \
 do { \
-	_raw_read_unlock(lock); \
+	_raw_write_unlock(lock); \
+	local_irq_restore(flags); \
 	preempt_enable(); \
-	local_bh_enable(); \
 } while (0)
 
-#define write_unlock_irqrestore(lock, flags) \
+#define _read_unlock_irq(lock)	\
 do { \
-	_raw_write_unlock(lock); \
-	local_irq_restore(flags); \
-	preempt_enable(); \
+	_raw_read_unlock(lock);	\
+	local_irq_enable();	\
+	preempt_enable();	\
 } while (0)
 
-#define write_unlock_irq(lock) \
+#define _read_unlock_bh(lock)	\
 do { \
-	_raw_write_unlock(lock); \
-	local_irq_enable(); \
-	preempt_enable(); \
+	_raw_read_unlock(lock);	\
+	local_bh_enable();	\
+	preempt_enable();	\
 } while (0)
 
-#define write_unlock_bh(lock) \
+#define _write_unlock_irq(lock)	\
 do { \
-	_raw_write_unlock(lock); \
-	preempt_enable(); \
-	local_bh_enable(); \
+	_raw_write_unlock(lock);	\
+	local_irq_enable();	\
+	preempt_enable();	\
 } while (0)
 
-#define spin_trylock_bh(lock)	({ local_bh_disable(); preempt_disable(); \
-				_raw_spin_trylock(lock) ? 1 : \
-				({preempt_enable(); local_bh_enable(); 0;});})
+#endif /* !SMP */
+
+/*
+ * Define the various spin_lock and rw_lock methods.  Note we define these
+ * regardless of whether CONFIG_SMP or CONFIG_PREEMPT are set. The various
+ * methods are defined as nops in the case they are not required.
+ */
+#define spin_trylock(lock)	_spin_trylock(lock)
+#define write_trylock(lock)	_write_trylock(lock)
+
+/* Where's read_trylock? */
+
+#define spin_lock(lock)		_spin_lock(lock)
+#define write_lock(lock)	_write_lock(lock)
+#define read_lock(lock)		_read_lock(lock)
+#define spin_unlock(lock)	_spin_unlock(lock)
+#define write_unlock(lock)	_write_unlock(lock)
+#define read_unlock(lock)	_read_unlock(lock)
+
+#ifdef CONFIG_SMP
+#define spin_lock_irqsave(lock, flags)	flags = _spin_lock_irqsave(lock)
+#define read_lock_irqsave(lock, flags)	flags = _read_lock_irqsave(lock)
+#define write_lock_irqsave(lock, flags)	flags = _write_lock_irqsave(lock)
+#else
+#define spin_lock_irqsave(lock, flags)	_spin_lock_irqsave(lock, flags)
+#define read_lock_irqsave(lock, flags)	_read_lock_irqsave(lock, flags)
+#define write_lock_irqsave(lock, flags)	_write_lock_irqsave(lock, flags)
+#endif
+
+#define spin_lock_irq(lock)		_spin_lock_irq(lock)
+#define spin_lock_bh(lock)		_spin_lock_bh(lock)
+
+#define read_lock_irq(lock)		_read_lock_irq(lock)
+#define read_lock_bh(lock)		_read_lock_bh(lock)
+
+#define write_lock_irq(lock)		_write_lock_irq(lock)
+#define write_lock_bh(lock)		_write_lock_bh(lock)
+#define spin_unlock_irqrestore(lock, flags)	_spin_unlock_irqrestore(lock, flags)
+#define spin_unlock_irq(lock)		_spin_unlock_irq(lock)
+#define spin_unlock_bh(lock)		_spin_unlock_bh(lock)
+
+#define read_unlock_irqrestore(lock, flags)	_read_unlock_irqrestore(lock, flags)
+#define read_unlock_irq(lock)			_read_unlock_irq(lock)
+#define read_unlock_bh(lock)			_read_unlock_bh(lock)
+
+#define write_unlock_irqrestore(lock, flags)	_write_unlock_irqrestore(lock, flags)
+#define write_unlock_irq(lock)			_write_unlock_irq(lock)
+#define write_unlock_bh(lock)			_write_unlock_bh(lock)
+
+#define spin_trylock_bh(lock)			_spin_trylock_bh(lock)
+
+#ifdef CONFIG_LOCKMETER
+extern void _metered_spin_lock   (spinlock_t *lock);
+extern void _metered_spin_unlock (spinlock_t *lock);
+extern int  _metered_spin_trylock(spinlock_t *lock);
+extern void _metered_read_lock    (rwlock_t *lock);
+extern void _metered_read_unlock  (rwlock_t *lock);
+extern void _metered_write_lock   (rwlock_t *lock);
+extern void _metered_write_unlock (rwlock_t *lock);
+extern int  _metered_write_trylock(rwlock_t *lock);
+#endif
 
 /* "lock on reference count zero" */
 #ifndef ATOMIC_DEC_AND_LOCK
diff --git a/include/linux/stddef.h b/include/linux/stddef.h
index dfa232215..b3a2cadf9 100644
--- a/include/linux/stddef.h
+++ b/include/linux/stddef.h
@@ -1,6 +1,8 @@
 #ifndef _LINUX_STDDEF_H
 #define _LINUX_STDDEF_H
 
+#include <linux/compiler.h>
+
 #undef NULL
 #if defined(__cplusplus)
 #define NULL 0
@@ -9,6 +11,10 @@
 #endif
 
 #undef offsetof
+#ifdef __compiler_offsetof
+#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
+#else
 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
 
 #endif
diff --git a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
index adaff41d3..5bff5a1d4 100644
--- a/include/linux/sunrpc/auth_gss.h
+++ b/include/linux/sunrpc/auth_gss.h
@@ -15,11 +15,9 @@
 #define _LINUX_SUNRPC_AUTH_GSS_H
 
 #ifdef __KERNEL__
-#ifdef __linux__
 #include <linux/sunrpc/auth.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/gss_api.h>
-#endif
 
 #define RPC_GSS_VERSION		1
 
diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
index 6c5f0060a..04ac3afcc 100644
--- a/include/linux/sunrpc/cache.h
+++ b/include/linux/sunrpc/cache.h
@@ -161,6 +161,10 @@ struct cache_deferred_req {
  * INIT copies key information from "item" to "new"
  * UPDATE copies content information from "item" to "tmp"
  * INPLACE is true if updates can happen inplace rather than allocating a new structure
+ *
+ * WARNING: any substantial changes to this must be reflected in
+ *   net/sunrpc/svcauth.c(auth_domain_lookup)
+ *  which is a similar routine that is open-coded.
  */
 #define DefineCacheLookup(RTN,MEMBER,FNAME,ARGS,SETUP,DETAIL,HASHFN,TEST,INIT,UPDATE,INPLACE)	\
 RTN *FNAME ARGS										\
@@ -233,7 +237,6 @@ RTN *FNAME ARGS										\
 	new = kmalloc(sizeof(*new), GFP_KERNEL);					\
 	if (new) {									\
 		cache_init(&new->MEMBER);						\
-		cache_get(&new->MEMBER);						\
 		goto retry;								\
 	}										\
 	return NULL;									\
diff --git a/include/linux/sunrpc/gss_asn1.h b/include/linux/sunrpc/gss_asn1.h
index 7559244d4..e0e4e1dc5 100644
--- a/include/linux/sunrpc/gss_asn1.h
+++ b/include/linux/sunrpc/gss_asn1.h
@@ -69,7 +69,6 @@ u32 g_verify_token_header(
      struct xdr_netobj *mech,
      int *body_size,
      unsigned char **buf_in,
-     int tok_type,
      int toksize);
 
 u32 g_get_mech_oid(struct xdr_netobj *mech, struct xdr_netobj * in_buf);
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index be2e6ef3b..6959ed0d6 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -113,6 +113,7 @@ typedef void			(*rpc_action)(struct rpc_task *);
 #define RPC_TASK_DYNAMIC	0x0080		/* task was kmalloc'ed */
 #define RPC_TASK_KILLED		0x0100		/* task was killed */
 #define RPC_TASK_SOFT		0x0200		/* Use soft timeouts */
+#define RPC_TASK_NOINTR		0x0400		/* uninterruptible task */
 
 #define RPC_IS_ASYNC(t)		((t)->tk_flags & RPC_TASK_ASYNC)
 #define RPC_IS_SETUID(t)	((t)->tk_flags & RPC_TASK_SETUID)
@@ -123,6 +124,7 @@ typedef void			(*rpc_action)(struct rpc_task *);
 #define RPC_IS_ACTIVATED(t)	((t)->tk_active)
 #define RPC_DO_CALLBACK(t)	((t)->tk_callback != NULL)
 #define RPC_IS_SOFT(t)		((t)->tk_flags & RPC_TASK_SOFT)
+#define RPC_TASK_UNINTERRUPTIBLE(t) ((t)->tk_flags & RPC_TASK_NOINTR)
 
 #define RPC_TASK_SLEEPING	0
 #define RPC_TASK_RUNNING	1
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 7abde582f..f464260d6 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -87,6 +87,14 @@ static inline u32 svc_getu32(struct kvec *iov)
 	iov->iov_len -= sizeof(u32);
 	return val;
 }
+
+static inline void svc_ungetu32(struct kvec *iov)
+{
+	u32 *vp = (u32 *)iov->iov_base;
+	iov->iov_base = (void *)(vp - 1);
+	iov->iov_len += sizeof(*vp);
+}
+
 static inline void svc_putu32(struct kvec *iov, u32 val)
 {
 	u32 *vp = iov->iov_base + iov->iov_len;
@@ -243,6 +251,8 @@ struct svc_program {
 	char *			pg_name;	/* service name */
 	char *			pg_class;	/* class name: services sharing authentication */
 	struct svc_stat *	pg_stats;	/* rpc statistics */
+	/* Override authentication. NULL means use default */
+	int			(*pg_authenticate)(struct svc_rqst *, u32 *);
 };
 
 /*
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index d0955f06c..932dc2ca4 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -23,16 +23,6 @@ typedef struct pbe {
 
 #define SWAP_FILENAME_MAXLENGTH	32
 
-struct suspend_header {
-	u32 version_code;
-	unsigned long num_physpages;
-	char machine[8];
-	char version[20];
-	int num_cpus;
-	int page_size;
-	suspend_pagedir_t *suspend_pagedir;
-	unsigned int num_pbes;
-};
 
 #define SUSPEND_PD_PAGES(x)     (((x)*sizeof(struct pbe))/PAGE_SIZE+1)
    
@@ -45,16 +35,12 @@ extern void drain_local_pages(void);
 /* kernel/power/swsusp.c */
 extern int software_suspend(void);
 
-extern unsigned int nr_copy_pages __nosavedata;
-extern suspend_pagedir_t *pagedir_nosave __nosavedata;
-
 #else	/* CONFIG_SOFTWARE_SUSPEND */
 static inline int software_suspend(void)
 {
 	printk("Warning: fake suspend called\n");
 	return -EPERM;
 }
-#define software_resume()		do { } while(0)
 #endif	/* CONFIG_SOFTWARE_SUSPEND */
 
 
@@ -78,12 +64,6 @@ static inline void disable_nonboot_cpus(void) {}
 static inline void enable_nonboot_cpus(void) {}
 #endif
 
-asmlinkage void do_magic(int is_resume);
-asmlinkage void do_magic_resume_1(void);
-asmlinkage void do_magic_resume_2(void);
-asmlinkage void do_magic_suspend_1(void);
-asmlinkage void do_magic_suspend_2(void);
-
 void save_processor_state(void);
 void restore_processor_state(void);
 struct saved_context;
diff --git a/include/linux/swap.h b/include/linux/swap.h
index b081066b5..371e8260c 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -204,7 +204,6 @@ extern void free_pages_and_swap_cache(struct page **, int);
 extern struct page * lookup_swap_cache(swp_entry_t);
 extern struct page * read_swap_cache_async(swp_entry_t, struct vm_area_struct *vma,
 					   unsigned long addr);
-
 /* linux/mm/swapfile.c */
 extern long total_swap_pages;
 extern unsigned int nr_swapfiles;
@@ -229,6 +228,22 @@ extern spinlock_t swaplock;
 #define swap_device_lock(p)	spin_lock(&p->sdev_lock)
 #define swap_device_unlock(p)	spin_unlock(&p->sdev_lock)
 
+/* linux/mm/thrash.c */
+extern struct mm_struct * swap_token_mm;
+extern void grab_swap_token(void);
+extern void __put_swap_token(struct mm_struct *);
+
+static inline int has_swap_token(struct mm_struct *mm)
+{
+	return (mm == swap_token_mm);
+}
+
+static inline void put_swap_token(struct mm_struct *mm)
+{
+	if (has_swap_token(mm))
+		__put_swap_token(mm);
+}
+
 #else /* CONFIG_SWAP */
 
 #define total_swap_pages			0
@@ -266,6 +281,11 @@ static inline swp_entry_t get_swap_page(void)
 	return entry;
 }
 
+/* linux/mm/thrash.c */
+#define put_swap_token(x) do { } while(0)
+#define grab_swap_token()  do { } while(0)
+#define has_swap_token(x) 0
+
 #endif /* CONFIG_SWAP */
 #endif /* __KERNEL__*/
 #endif /* _LINUX_SWAP_H */
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index fadfc6d7a..bd26cf298 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -114,6 +114,9 @@ asmlinkage long sys_getitimer(int which, struct itimerval __user *value);
 asmlinkage long sys_setitimer(int which,
 				struct itimerval __user *value,
 				struct itimerval __user *ovalue);
+asmlinkage long sys_timer_create(clockid_t which_clock,
+				 struct sigevent __user *timer_event_spec,
+				 timer_t __user * created_timer_id);
 asmlinkage long sys_timer_gettime(timer_t timer_id,
 				struct itimerspec __user *setting);
 asmlinkage long sys_timer_getoverrun(timer_t timer_id);
@@ -160,9 +163,12 @@ asmlinkage long sys_kexec_load(void *entry, unsigned long nr_segments,
 
 asmlinkage long sys_exit(int error_code);
 asmlinkage void sys_exit_group(int error_code);
-asmlinkage long sys_wait4(pid_t pid, unsigned int __user *stat_addr,
+asmlinkage long sys_wait4(pid_t pid, int __user *stat_addr,
 				int options, struct rusage __user *ru);
-asmlinkage long sys_waitpid(pid_t pid, unsigned int __user *stat_addr, int options);
+asmlinkage long sys_waitid(int which, pid_t pid,
+			   struct siginfo __user *infop,
+			   int options, struct rusage __user *ru);
+asmlinkage long sys_waitpid(pid_t pid, int __user *stat_addr, int options);
 asmlinkage long sys_set_tid_address(int __user *tidptr);
 asmlinkage long sys_futex(u32 __user *uaddr, int op, int val,
 			struct timespec __user *utime, u32 __user *uaddr2,
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index f3ce78734..c484516d3 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -133,7 +133,8 @@ enum
 	KERN_NGROUPS_MAX=63,	/* int: NGROUPS_MAX */
 	KERN_SPARC_SCONS_PWROFF=64, /* int: serial console power-off halt */
 	KERN_HZ_TIMER=65,	/* int: hz timer on or off */
-	KERN_VSHELPER=66,	/* string: path to vshelper policy agent */
+	KERN_UNKNOWN_NMI_PANIC=66, /* int: unknown nmi panic flag */
+	KERN_VSHELPER=67,	/* string: path to vshelper policy agent */
 };
 
 
@@ -166,6 +167,7 @@ enum
 	VM_BLOCK_DUMP=24,	/* block dump mode */
 	VM_HUGETLB_GROUP=25,	/* permitted hugetlb group */
 	VM_VFS_CACHE_PRESSURE=26, /* dcache/icache reclaim pressure */
+	VM_LEGACY_VA_LAYOUT=27, /* legacy/compatibility virtual address space layout */
 };
 
 
@@ -340,6 +342,7 @@ enum
 	NET_TCP_BIC_LOW_WINDOW=104,
 	NET_TCP_DEFAULT_WIN_SCALE=105,
 	NET_TCP_MODERATE_RCVBUF=106,
+	NET_TCP_TSO_WIN_DIVISOR=107,
 };
 
 enum {
@@ -411,6 +414,19 @@ enum
 	NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT=12,
 	NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT=13,
 	NET_IPV4_NF_CONNTRACK_BUCKETS=14,
+	NET_IPV4_NF_CONNTRACK_LOG_INVALID=15,
+	NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS=16,
+	NET_IPV4_NF_CONNTRACK_TCP_LOOSE=17,
+	NET_IPV4_NF_CONNTRACK_TCP_BE_LIBERAL=18,
+	NET_IPV4_NF_CONNTRACK_TCP_MAX_RETRANS=19,
+ 	NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED=20,
+ 	NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_WAIT=21,
+ 	NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_ECHOED=22,
+ 	NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_ESTABLISHED=23,
+ 	NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT=24,
+ 	NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD=25,
+ 	NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT=26,
+	NET_IPV4_NF_CONNTRACK_COUNT=27,
 };
  
 /* /proc/sys/net/ipv6 */
diff --git a/include/linux/sysv_fs.h b/include/linux/sysv_fs.h
index 4159f32c4..e0248631e 100644
--- a/include/linux/sysv_fs.h
+++ b/include/linux/sysv_fs.h
@@ -8,13 +8,18 @@
 #endif
 
 
+#ifndef __KERNEL__
+typedef u16 __fs16;
+typedef u32 __fs16;
+#endif
+
 /* inode numbers are 16 bit */
-typedef u16 sysv_ino_t;
+typedef __fs16 sysv_ino_t;
 
 /* Block numbers are 24 bit, sometimes stored in 32 bit.
    On Coherent FS, they are always stored in PDP-11 manner: the least
    significant 16 bits come last. */
-typedef u32 sysv_zone_t;
+typedef __fs32 sysv_zone_t;
 
 /* 0 is non-existent */
 #define SYSV_BADBL_INO	1	/* inode of bad blocks file */
@@ -25,29 +30,29 @@ typedef u32 sysv_zone_t;
 #define XENIX_NICINOD	100	/* number of inode cache entries */
 #define XENIX_NICFREE	100	/* number of free block list chunk entries */
 struct xenix_super_block {
-	u16		s_isize; /* index of first data zone */
-	u32		s_fsize __packed2__; /* total number of zones of this fs */
+	__fs16		s_isize; /* index of first data zone */
+	__fs32		s_fsize __packed2__; /* total number of zones of this fs */
 	/* the start of the free block list: */
-	u16		s_nfree;	/* number of free blocks in s_free, <= XENIX_NICFREE */
-	u32		s_free[XENIX_NICFREE]; /* first free block list chunk */
+	__fs16		s_nfree;	/* number of free blocks in s_free, <= XENIX_NICFREE */
+	sysv_zone_t	s_free[XENIX_NICFREE]; /* first free block list chunk */
 	/* the cache of free inodes: */
-	u16		s_ninode; /* number of free inodes in s_inode, <= XENIX_NICINOD */
+	__fs16		s_ninode; /* number of free inodes in s_inode, <= XENIX_NICINOD */
 	sysv_ino_t	s_inode[XENIX_NICINOD]; /* some free inodes */
 	/* locks, not used by Linux: */
 	char		s_flock;	/* lock during free block list manipulation */
 	char		s_ilock;	/* lock during inode cache manipulation */
 	char		s_fmod;		/* super-block modified flag */
 	char		s_ronly;	/* flag whether fs is mounted read-only */
-	u32		s_time __packed2__; /* time of last super block update */
-	u32		s_tfree __packed2__; /* total number of free zones */
-	u16		s_tinode;	/* total number of free inodes */
-	s16		s_dinfo[4];	/* device information ?? */
+	__fs32		s_time __packed2__; /* time of last super block update */
+	__fs32		s_tfree __packed2__; /* total number of free zones */
+	__fs16		s_tinode;	/* total number of free inodes */
+	__fs16		s_dinfo[4];	/* device information ?? */
 	char		s_fname[6];	/* file system volume name */
 	char		s_fpack[6];	/* file system pack name */
 	char		s_clean;	/* set to 0x46 when filesystem is properly unmounted */
 	char		s_fill[371];
 	s32		s_magic;	/* version of file system */
-	s32		s_type;		/* type of file system: 1 for 512 byte blocks
+	__fs32		s_type;		/* type of file system: 1 for 512 byte blocks
 								2 for 1024 byte blocks
 								3 for 2048 byte blocks */
 								
@@ -63,15 +68,15 @@ struct xenix_super_block {
 
 /* SystemV4 super-block data on disk */
 struct sysv4_super_block {
-	u16	s_isize;	/* index of first data zone */
+	__fs16	s_isize;	/* index of first data zone */
 	u16	s_pad0;
-	u32	s_fsize;	/* total number of zones of this fs */
+	__fs32	s_fsize;	/* total number of zones of this fs */
 	/* the start of the free block list: */
-	u16	s_nfree;	/* number of free blocks in s_free, <= SYSV_NICFREE */
+	__fs16	s_nfree;	/* number of free blocks in s_free, <= SYSV_NICFREE */
 	u16	s_pad1;
-	u32	s_free[SYSV_NICFREE]; /* first free block list chunk */
+	sysv_zone_t	s_free[SYSV_NICFREE]; /* first free block list chunk */
 	/* the cache of free inodes: */
-	u16	s_ninode;	/* number of free inodes in s_inode, <= SYSV_NICINOD */
+	__fs16	s_ninode;	/* number of free inodes in s_inode, <= SYSV_NICINOD */
 	u16	s_pad2;
 	sysv_ino_t     s_inode[SYSV_NICINOD]; /* some free inodes */
 	/* locks, not used by Linux: */
@@ -79,45 +84,45 @@ struct sysv4_super_block {
 	char	s_ilock;	/* lock during inode cache manipulation */
 	char	s_fmod;		/* super-block modified flag */
 	char	s_ronly;	/* flag whether fs is mounted read-only */
-	u32	s_time;		/* time of last super block update */
-	s16	s_dinfo[4];	/* device information ?? */
-	u32	s_tfree;	/* total number of free zones */
-	u16	s_tinode;	/* total number of free inodes */
+	__fs32	s_time;		/* time of last super block update */
+	__fs16	s_dinfo[4];	/* device information ?? */
+	__fs32	s_tfree;	/* total number of free zones */
+	__fs16	s_tinode;	/* total number of free inodes */
 	u16	s_pad3;
 	char	s_fname[6];	/* file system volume name */
 	char	s_fpack[6];	/* file system pack name */
 	s32	s_fill[12];
-	s32	s_state;	/* file system state: 0x7c269d38-s_time means clean */
+	__fs32	s_state;	/* file system state: 0x7c269d38-s_time means clean */
 	s32	s_magic;	/* version of file system */
-	s32	s_type;		/* type of file system: 1 for 512 byte blocks
+	__fs32	s_type;		/* type of file system: 1 for 512 byte blocks
 								2 for 1024 byte blocks */
 };
 
 /* SystemV2 super-block data on disk */
 struct sysv2_super_block {
-	u16	s_isize; 		/* index of first data zone */
-	u32	s_fsize __packed2__;	/* total number of zones of this fs */
+	__fs16	s_isize; 		/* index of first data zone */
+	__fs32	s_fsize __packed2__;	/* total number of zones of this fs */
 	/* the start of the free block list: */
-	u16	s_nfree;		/* number of free blocks in s_free, <= SYSV_NICFREE */
-	u32	s_free[SYSV_NICFREE];	/* first free block list chunk */
+	__fs16	s_nfree;		/* number of free blocks in s_free, <= SYSV_NICFREE */
+	sysv_zone_t s_free[SYSV_NICFREE];	/* first free block list chunk */
 	/* the cache of free inodes: */
-	u16	s_ninode;		/* number of free inodes in s_inode, <= SYSV_NICINOD */
+	__fs16	s_ninode;		/* number of free inodes in s_inode, <= SYSV_NICINOD */
 	sysv_ino_t     s_inode[SYSV_NICINOD]; /* some free inodes */
 	/* locks, not used by Linux: */
 	char	s_flock;		/* lock during free block list manipulation */
 	char	s_ilock;		/* lock during inode cache manipulation */
 	char	s_fmod;			/* super-block modified flag */
 	char	s_ronly;		/* flag whether fs is mounted read-only */
-	u32	s_time __packed2__;	/* time of last super block update */
-	s16	s_dinfo[4];		/* device information ?? */
-	u32	s_tfree __packed2__;	/* total number of free zones */
-	u16	s_tinode;		/* total number of free inodes */
+	__fs32	s_time __packed2__;	/* time of last super block update */
+	__fs16	s_dinfo[4];		/* device information ?? */
+	__fs32	s_tfree __packed2__;	/* total number of free zones */
+	__fs16	s_tinode;		/* total number of free inodes */
 	char	s_fname[6];		/* file system volume name */
 	char	s_fpack[6];		/* file system pack name */
 	s32	s_fill[14];
-	s32	s_state;		/* file system state: 0xcb096f43 means clean */
+	__fs32	s_state;		/* file system state: 0xcb096f43 means clean */
 	s32	s_magic;		/* version of file system */
-	s32	s_type;			/* type of file system: 1 for 512 byte blocks
+	__fs32	s_type;			/* type of file system: 1 for 512 byte blocks
 								2 for 1024 byte blocks */
 };
 
@@ -125,25 +130,25 @@ struct sysv2_super_block {
 #define V7_NICINOD     100     /* number of inode cache entries */
 #define V7_NICFREE     50      /* number of free block list chunk entries */
 struct v7_super_block {
-	u16    s_isize;        /* index of first data zone */
-	u32    s_fsize __packed2__; /* total number of zones of this fs */
+	__fs16 s_isize;        /* index of first data zone */
+	__fs32 s_fsize __packed2__; /* total number of zones of this fs */
 	/* the start of the free block list: */
-	u16    s_nfree;        /* number of free blocks in s_free, <= V7_NICFREE */
-	u32    s_free[V7_NICFREE]; /* first free block list chunk */
+	__fs16 s_nfree;        /* number of free blocks in s_free, <= V7_NICFREE */
+	sysv_zone_t s_free[V7_NICFREE]; /* first free block list chunk */
 	/* the cache of free inodes: */
-	u16    s_ninode;       /* number of free inodes in s_inode, <= V7_NICINOD */
+	__fs16 s_ninode;       /* number of free inodes in s_inode, <= V7_NICINOD */
 	sysv_ino_t      s_inode[V7_NICINOD]; /* some free inodes */
 	/* locks, not used by Linux or V7: */
 	char    s_flock;        /* lock during free block list manipulation */
 	char    s_ilock;        /* lock during inode cache manipulation */
 	char    s_fmod;         /* super-block modified flag */
 	char    s_ronly;        /* flag whether fs is mounted read-only */
-	u32     s_time __packed2__; /* time of last super block update */
+	__fs32  s_time __packed2__; /* time of last super block update */
 	/* the following fields are not maintained by V7: */
-	u32     s_tfree __packed2__; /* total number of free zones */
-	u16     s_tinode;       /* total number of free inodes */
-	u16     s_m;            /* interleave factor */
-	u16     s_n;            /* interleave factor */
+	__fs32  s_tfree __packed2__; /* total number of free zones */
+	__fs16  s_tinode;       /* total number of free inodes */
+	__fs16  s_m;            /* interleave factor */
+	__fs16  s_n;            /* interleave factor */
 	char    s_fname[6];     /* file system name */
 	char    s_fpack[6];     /* file system pack name */
 };
@@ -152,41 +157,41 @@ struct v7_super_block {
 #define COH_NICINOD	100	/* number of inode cache entries */
 #define COH_NICFREE	64	/* number of free block list chunk entries */
 struct coh_super_block {
-	u16		s_isize;	/* index of first data zone */
-	u32		s_fsize __packed2__; /* total number of zones of this fs */
+	__fs16		s_isize;	/* index of first data zone */
+	__fs32		s_fsize __packed2__; /* total number of zones of this fs */
 	/* the start of the free block list: */
-	u16 s_nfree;	/* number of free blocks in s_free, <= COH_NICFREE */
-	u32		s_free[COH_NICFREE] __packed2__; /* first free block list chunk */
+	__fs16 s_nfree;	/* number of free blocks in s_free, <= COH_NICFREE */
+	sysv_zone_t	s_free[COH_NICFREE] __packed2__; /* first free block list chunk */
 	/* the cache of free inodes: */
-	u16		s_ninode;	/* number of free inodes in s_inode, <= COH_NICINOD */
+	__fs16		s_ninode;	/* number of free inodes in s_inode, <= COH_NICINOD */
 	sysv_ino_t	s_inode[COH_NICINOD]; /* some free inodes */
 	/* locks, not used by Linux: */
 	char		s_flock;	/* lock during free block list manipulation */
 	char		s_ilock;	/* lock during inode cache manipulation */
 	char		s_fmod;		/* super-block modified flag */
 	char		s_ronly;	/* flag whether fs is mounted read-only */
-	u32		s_time __packed2__; /* time of last super block update */
-	u32		s_tfree __packed2__; /* total number of free zones */
-	u16		s_tinode;	/* total number of free inodes */
-	u16		s_interleave_m;	/* interleave factor */
-	u16		s_interleave_n;
+	__fs32		s_time __packed2__; /* time of last super block update */
+	__fs32		s_tfree __packed2__; /* total number of free zones */
+	__fs16		s_tinode;	/* total number of free inodes */
+	__fs16		s_interleave_m;	/* interleave factor */
+	__fs16		s_interleave_n;
 	char		s_fname[6];	/* file system volume name */
 	char		s_fpack[6];	/* file system pack name */
-	u32		s_unique;	/* zero, not used */
+	__fs32		s_unique;	/* zero, not used */
 };
 
 /* SystemV/Coherent inode data on disk */
 struct sysv_inode {
-	u16 i_mode;
-	u16 i_nlink;
-	u16 i_uid;
-	u16 i_gid;
-	u32 i_size;
+	__fs16 i_mode;
+	__fs16 i_nlink;
+	__fs16 i_uid;
+	__fs16 i_gid;
+	__fs32 i_size;
 	u8  i_data[3*(10+1+1+1)];
 	u8  i_gen;
-	u32 i_atime;	/* time of last access */
-	u32 i_mtime;	/* time of last modification */
-	u32 i_ctime;	/* time of creation */
+	__fs32 i_atime;	/* time of last access */
+	__fs32 i_mtime;	/* time of last modification */
+	__fs32 i_ctime;	/* time of creation */
 };
 
 /* SystemV/Coherent directory entry on disk */
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 9c42ac0b0..f374df7a8 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -201,6 +201,17 @@ struct tcp_sack_block {
 	__u32	end_seq;
 };
 
+typedef struct tcp_pcount {
+	__u32	val;
+} tcp_pcount_t;
+
+enum tcp_congestion_algo {
+	TCP_RENO=0,
+	TCP_VEGAS,
+	TCP_WESTWOOD,
+	TCP_BIC,
+};
+
 struct tcp_opt {
 	int	tcp_header_len;	/* Bytes of tcp header to send		*/
 
@@ -261,22 +272,22 @@ struct tcp_opt {
 	__u8	frto_counter;	/* Number of new acks after RTO */
 	__u32	frto_highmark;	/* snd_nxt when RTO occurred */
 
-	__u8	unused_pad;
+	__u8	adv_cong;	/* Using Vegas, Westwood, or BIC */
 	__u8	defer_accept;	/* User waits for some data after accept() */
 	/* one byte hole, try to pack */
 
 /* RTT measurement */
 	__u8	backoff;	/* backoff				*/
-	__u32	srtt;		/* smothed round trip time << 3		*/
+	__u32	srtt;		/* smoothed round trip time << 3	*/
 	__u32	mdev;		/* medium deviation			*/
 	__u32	mdev_max;	/* maximal mdev for the last rtt period	*/
 	__u32	rttvar;		/* smoothed mdev_max			*/
 	__u32	rtt_seq;	/* sequence number to update rttvar	*/
 	__u32	rto;		/* retransmit timeout			*/
 
-	__u32	packets_out;	/* Packets which are "in flight"	*/
-	__u32	left_out;	/* Packets which leaved network		*/
-	__u32	retrans_out;	/* Retransmitted packets out		*/
+	tcp_pcount_t packets_out; /* Packets which are "in flight"	*/
+	tcp_pcount_t left_out;	  /* Packets which leaved network	*/
+	tcp_pcount_t retrans_out; /* Retransmitted packets out		*/
 
 
 /*
@@ -337,9 +348,9 @@ struct tcp_opt {
 	__u8	syn_retries;	/* num of allowed syn retries */
 	__u8	ecn_flags;	/* ECN status bits.			*/
 	__u16	prior_ssthresh; /* ssthresh saved at recovery start	*/
-	__u32	lost_out;	/* Lost packets				*/
-	__u32	sacked_out;	/* SACK'd packets			*/
-	__u32	fackets_out;	/* FACK'd packets			*/
+	tcp_pcount_t lost_out;	/* Lost packets			*/
+	tcp_pcount_t sacked_out;/* SACK'd packets			*/
+	tcp_pcount_t fackets_out;/* FACK'd packets			*/
 	__u32	high_seq;	/* snd_nxt at onset of congestion	*/
 
 	__u32	retrans_stamp;	/* Timestamp of the last retransmit,
@@ -408,7 +419,6 @@ struct tcp_opt {
 		__u32	beg_snd_nxt;	/* right edge during last RTT */
 		__u32	beg_snd_una;	/* left edge  during last RTT */
 		__u32	beg_snd_cwnd;	/* saves the size of the cwnd */
-		__u8	do_vegas;	/* do vegas for this connection */
 		__u8	doing_vegas_now;/* if true, do vegas for this RTT */
 		__u16	cntRTT;		/* # of RTTs measured within last RTT */
 		__u32	minRTT;		/* min of RTTs measured within last RTT (in usec) */
diff --git a/include/linux/time.h b/include/linux/time.h
index d24a690cb..2111941c1 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -194,8 +194,22 @@ static inline unsigned int jiffies_to_msecs(const unsigned long j)
 	return (j * 1000) / HZ;
 #endif
 }
+
+static inline unsigned int jiffies_to_usecs(const unsigned long j)
+{
+#if HZ <= 1000 && !(1000 % HZ)
+	return (1000000 / HZ) * j;
+#elif HZ > 1000 && !(HZ % 1000)
+	return (j*1000 + (HZ - 1000))/(HZ / 1000);
+#else
+	return (j * 1000000) / HZ;
+#endif
+}
+
 static inline unsigned long msecs_to_jiffies(const unsigned int m)
 {
+	if (m > jiffies_to_msecs(MAX_JIFFY_OFFSET))
+		return MAX_JIFFY_OFFSET;
 #if HZ <= 1000 && !(1000 % HZ)
 	return (m + (1000 / HZ) - 1) / (1000 / HZ);
 #elif HZ > 1000 && !(HZ % 1000)
@@ -348,6 +362,7 @@ extern long do_utimes(char __user * filename, struct timeval * times);
 struct itimerval;
 extern int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue);
 extern int do_getitimer(int which, struct itimerval *value);
+extern void getnstimeofday (struct timespec *tv);
 
 static inline void
 set_normalized_timespec (struct timespec *ts, time_t sec, long nsec)
diff --git a/include/linux/times.h b/include/linux/times.h
index ff00f334f..0c5aa078d 100644
--- a/include/linux/times.h
+++ b/include/linux/times.h
@@ -55,6 +55,26 @@ static inline u64 jiffies_64_to_clock_t(u64 x)
 }
 #endif
 
+static inline u64 nsec_to_clock_t(u64 x)
+{
+#if (NSEC_PER_SEC % USER_HZ) == 0
+	do_div(x, (NSEC_PER_SEC / USER_HZ));
+#elif (USER_HZ % 512) == 0
+	x *= USER_HZ/512;
+	do_div(x, (NSEC_PER_SEC / 512));
+#else
+	/*
+         * max relative error 5.7e-8 (1.8s per year) for USER_HZ <= 1024,
+         * overflow after 64.99 years.
+         * exact for HZ=60, 72, 90, 120, 144, 180, 300, 600, 900, ...
+         */
+	x *= 9;
+	do_div(x, (unsigned long)((9ull * NSEC_PER_SEC + (USER_HZ/2))
+	                          / USER_HZ));
+#endif
+	return x;
+}
+
 struct tms {
 	clock_t tms_utime;
 	clock_t tms_stime;
diff --git a/include/linux/timex.h b/include/linux/timex.h
index c9e92e016..31ef4595b 100644
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -47,6 +47,8 @@
  *      kernel PLL updated to 1994-12-13 specs (rfc-1589)
  * 1997-08-30    Ulrich Windl
  *      Added new constant NTP_PHASE_LIMIT
+ * 2004-08-12    Christoph Lameter
+ *      Reworked time interpolation logic
  */
 #ifndef _LINUX_TIMEX_H
 #define _LINUX_TIMEX_H
@@ -320,101 +322,60 @@ extern long pps_stbcnt;		/* stability limit exceeded */
 
 #ifdef CONFIG_TIME_INTERPOLATION
 
-struct time_interpolator {
-	/* cache-hot stuff first: */
-	unsigned long (*get_offset) (void);
-	void (*update) (long);
-	void (*reset) (void);
+#define TIME_SOURCE_CPU 0
+#define TIME_SOURCE_MMIO64 1
+#define TIME_SOURCE_MMIO32 2
+#define TIME_SOURCE_FUNCTION 3
+
+/* For proper operations time_interpolator clocks must run slightly slower
+ * than the standard clock since the interpolator may only correct by having
+ * time jump forward during a tick. A slower clock is usually a side effect
+ * of the integer divide of the nanoseconds in a second by the frequency.
+ * The accuracy of the division can be increased by specifying a shift.
+ * However, this may cause the clock not to be slow enough.
+ * The interpolator will self-tune the clock by slowing down if no
+ * resets occur or speeding up if the time jumps per analysis cycle
+ * become too high.
+ *
+ * Setting jitter compensates for a fluctuating timesource by comparing
+ * to the last value read from the timesource to insure that an earlier value
+ * is not returned by a later call. The price to pay
+ * for the compensation is that the timer routines are not as scalable anymore.
+ */
 
-	/* cache-cold stuff follows here: */
-	struct time_interpolator *next;
+#define INTERPOLATOR_ADJUST 65536
+#define INTERPOLATOR_MAX_SKIP 10*INTERPOLATOR_ADJUST
+
+struct time_interpolator {
+	unsigned short source;		/* time source flags */
+	unsigned char shift;		/* increases accuracy of multiply by shifting. */
+			/* Note that bits may be lost if shift is set too high */
+	unsigned char jitter;		/* if set compensate for fluctuations */
+	unsigned nsec_per_cyc;		/* set by register_time_interpolator() */
+	void *addr;			/* address of counter or function */
+	unsigned long offset;		/* nsec offset at last update of interpolator */
+	unsigned long last_counter;	/* counter value in units of the counter at last update */
+	unsigned long last_cycle;	/* Last timer value if TIME_SOURCE_JITTER is set */
 	unsigned long frequency;	/* frequency in counts/second */
 	long drift;			/* drift in parts-per-million (or -1) */
+	unsigned long skips;		/* skips forward */
+	unsigned long ns_skipped;	/* nanoseconds skipped */
+	struct time_interpolator *next;
 };
 
-extern volatile unsigned long last_nsec_offset;
-#ifndef __HAVE_ARCH_CMPXCHG
-extern spin_lock_t last_nsec_offset_lock;
-#endif
-extern struct time_interpolator *time_interpolator;
-
 extern void register_time_interpolator(struct time_interpolator *);
 extern void unregister_time_interpolator(struct time_interpolator *);
-
-/* Called with xtime WRITE-lock acquired.  */
-static inline void
-time_interpolator_update(long delta_nsec)
-{
-	struct time_interpolator *ti = time_interpolator;
-
-	if (last_nsec_offset > 0) {
-#ifdef __HAVE_ARCH_CMPXCHG
-		unsigned long new, old;
-
-		do {
-			old = last_nsec_offset;
-			if (old > delta_nsec)
-				new = old - delta_nsec;
-			else
-				new = 0;
-		} while (cmpxchg(&last_nsec_offset, old, new) != old);
-#else
-		/*
-		 * This really hurts, because it serializes gettimeofday(), but without an
-		 * atomic single-word compare-and-exchange, there isn't all that much else
-		 * we can do.
-		 */
-		spin_lock(&last_nsec_offset_lock);
-		{
-			last_nsec_offset -= min(last_nsec_offset, delta_nsec);
-		}
-		spin_unlock(&last_nsec_offset_lock);
-#endif
-	}
-
-	if (ti)
-		(*ti->update)(delta_nsec);
-}
-
-/* Called with xtime WRITE-lock acquired.  */
-static inline void
-time_interpolator_reset(void)
-{
-	struct time_interpolator *ti = time_interpolator;
-
-	last_nsec_offset = 0;
-	if (ti)
-		(*ti->reset)();
-}
-
-/* Called with xtime READ-lock acquired.  */
-static inline unsigned long
-time_interpolator_get_offset(void)
-{
-	struct time_interpolator *ti = time_interpolator;
-	if (ti)
-		return (*ti->get_offset)();
-	return last_nsec_offset;
-}
+extern void time_interpolator_reset(void);
+extern unsigned long time_interpolator_resolution(void);
+extern unsigned long time_interpolator_get_offset(void);
 
 #else /* !CONFIG_TIME_INTERPOLATION */
 
-static inline void
-time_interpolator_update(long delta_nsec)
-{
-}
-
 static inline void
 time_interpolator_reset(void)
 {
 }
 
-static inline unsigned long
-time_interpolator_get_offset(void)
-{
-	return 0;
-}
-
 #endif /* !CONFIG_TIME_INTERPOLATION */
 
 #endif /* KERNEL */
diff --git a/include/linux/topology.h b/include/linux/topology.h
index a78a17713..fbaa8774a 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -55,7 +55,7 @@ static inline int __next_node_with_cpus(int node)
 	for (node = 0; node < numnodes; node = __next_node_with_cpus(node))
 
 #ifndef node_distance
-#define node_distance(from,to)	(from != to)
+#define node_distance(from,to)	((from) != (to))
 #endif
 #ifndef PENALTY_FOR_NODE_WITH_CPUS
 #define PENALTY_FOR_NODE_WITH_CPUS	(1)
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 7481d70fb..f9fd14991 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -244,6 +244,7 @@ struct tty_struct {
 	struct tty_driver *driver;
 	int index;
 	struct tty_ldisc ldisc;
+	struct semaphore termios_sem;
 	struct termios *termios, *termios_locked;
 	char name[64];
 	int pgrp;
@@ -306,26 +307,27 @@ struct tty_struct {
  * tty->write.  Thus, you must use the inline functions set_bit() and
  * clear_bit() to make things atomic.
  */
-#define TTY_THROTTLED 0
-#define TTY_IO_ERROR 1
-#define TTY_OTHER_CLOSED 2
-#define TTY_EXCLUSIVE 3
-#define TTY_DEBUG 4
-#define TTY_DO_WRITE_WAKEUP 5
-#define TTY_PUSH 6
-#define TTY_CLOSING 7
-#define TTY_DONT_FLIP 8
-#define TTY_HW_COOK_OUT 14
-#define TTY_HW_COOK_IN 15
-#define TTY_PTY_LOCK 16
-#define TTY_NO_WRITE_SPLIT 17
+#define TTY_THROTTLED 		0	/* Call unthrottle() at threshold min */
+#define TTY_IO_ERROR 		1	/* Canse an I/O error (may be no ldisc too) */
+#define TTY_OTHER_CLOSED 	2	/* Other side (if any) has closed */
+#define TTY_EXCLUSIVE 		3	/* Exclusive open mode */
+#define TTY_DEBUG 		4	/* Debugging */
+#define TTY_DO_WRITE_WAKEUP 	5	/* Call write_wakeup after queuing new */
+#define TTY_PUSH 		6	/* n_tty private */
+#define TTY_CLOSING 		7	/* ->close() in progress */
+#define TTY_DONT_FLIP 		8	/* Defer buffer flip */
+#define TTY_LDISC 		9	/* Line discipline attached */
+#define TTY_HW_COOK_OUT 	14	/* Hardware can do output cooking */
+#define TTY_HW_COOK_IN 		15	/* Hardware can do input cooking */
+#define TTY_PTY_LOCK 		16	/* pty private */
+#define TTY_NO_WRITE_SPLIT 	17	/* Preserve write boundaries to driver */
+#define TTY_HUPPED 		18	/* Post driver->hangup() */
 
 #define TTY_WRITE_FLUSH(tty) tty_write_flush((tty))
 
 extern void tty_write_flush(struct tty_struct *);
 
 extern struct termios tty_std_termios;
-extern struct tty_ldisc ldiscs[];
 extern int fg_console, last_console, want_console;
 
 extern int kmsg_redirect;
@@ -362,6 +364,16 @@ extern void tty_flip_buffer_push(struct tty_struct *tty);
 extern int tty_get_baud_rate(struct tty_struct *tty);
 extern int tty_termios_baud_rate(struct termios *termios);
 
+extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
+extern void tty_ldisc_deref(struct tty_ldisc *);
+extern struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *);
+
+extern struct tty_ldisc *tty_ldisc_get(int);
+extern void tty_ldisc_put(int);
+
+extern void tty_wakeup(struct tty_struct *tty);
+extern void tty_ldisc_flush(struct tty_struct *tty);
+
 struct semaphore;
 extern struct semaphore tty_sem;
 
diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h
index cb7ca58e4..deacf01e5 100644
--- a/include/linux/tty_ldisc.h
+++ b/include/linux/tty_ldisc.h
@@ -95,6 +95,13 @@
  * 	that line discpline should try to send more characters to the
  * 	low-level driver for transmission.  If the line discpline does
  * 	not have any more data to send, it can just return.
+ *
+ * int (*hangup)(struct tty_struct *)
+ *
+ *	Called on a hangup. Tells the discipline that it should
+ *	cease I/O to the tty driver. Can sleep. The driver should
+ *	seek to perform this action quickly but should wait until
+ *	any pending driver I/O is completed.
  */
 
 #include <linux/fs.h>
@@ -122,6 +129,7 @@ struct tty_ldisc {
 	void	(*set_termios)(struct tty_struct *tty, struct termios * old);
 	unsigned int (*poll)(struct tty_struct *, struct file *,
 			     struct poll_table_struct *);
+	int	(*hangup)(struct tty_struct *tty);
 	
 	/*
 	 * The following routines are called from below.
@@ -132,6 +140,8 @@ struct tty_ldisc {
 	void	(*write_wakeup)(struct tty_struct *);
 
 	struct  module *owner;
+	
+	int refcount;
 };
 
 #define TTY_LDISC_MAGIC	0x5403
diff --git a/include/linux/types.h b/include/linux/types.h
index 288ab653e..e678ccb20 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -142,6 +142,19 @@ typedef unsigned long sector_t;
 #define pgoff_t unsigned long
 #endif
 
+#ifdef __CHECKER__
+#define __bitwise __attribute__((bitwise))
+#else
+#define __bitwise
+#endif
+
+typedef __u16 __bitwise __le16;
+typedef __u16 __bitwise __be16;
+typedef __u32 __bitwise __le32;
+typedef __u32 __bitwise __be32;
+typedef __u64 __bitwise __le64;
+typedef __u64 __bitwise __be64;
+
 #endif /* __KERNEL_STRICT_NAMES */
 
 /*
diff --git a/include/linux/udf_fs_i.h b/include/linux/udf_fs_i.h
index 186a5a47b..62b15a421 100644
--- a/include/linux/udf_fs_i.h
+++ b/include/linux/udf_fs_i.h
@@ -45,7 +45,7 @@ struct udf_inode_info
 {
 	struct timespec		i_crtime;
 	/* Physical address of inode */
-	lb_addr			i_location;
+	kernel_lb_addr		i_location;
 	__u64			i_unique;
 	__u32			i_lenEAttr;
 	__u32			i_lenAlloc;
diff --git a/include/linux/ufs_fs.h b/include/linux/ufs_fs.h
index 6a21a49a7..7a6babeca 100644
--- a/include/linux/ufs_fs.h
+++ b/include/linux/ufs_fs.h
@@ -36,6 +36,16 @@
 #include <linux/stat.h>
 #include <linux/fs.h>
 
+#ifndef __KERNEL__
+typedef __u64 __fs64;
+typedef __u32 __fs32;
+typedef __u16 __fs16;
+#else
+typedef __u64 __bitwise __fs64;
+typedef __u32 __bitwise __fs32;
+typedef __u16 __bitwise __fs16;
+#endif
+
 #include <linux/ufs_fs_i.h>
 #include <linux/ufs_fs_sb.h>
 
@@ -297,15 +307,15 @@
 #define UFS_DIR_REC_LEN(name_len)	(((name_len) + 1 + 8 + UFS_DIR_ROUND) & ~UFS_DIR_ROUND)
 
 struct ufs_timeval {
-	__s32	tv_sec;
-	__s32	tv_usec;
+	__fs32	tv_sec;
+	__fs32	tv_usec;
 };
 
 struct ufs_dir_entry {
-	__u32  d_ino;			/* inode number of this entry */
-	__u16  d_reclen;		/* length of this entry */
+	__fs32  d_ino;			/* inode number of this entry */
+	__fs16  d_reclen;		/* length of this entry */
 	union {
-		__u16	d_namlen;		/* actual length of d_name */
+		__fs16	d_namlen;		/* actual length of d_name */
 		struct {
 			__u8	d_type;		/* file type */
 			__u8	d_namlen;	/* length of string in d_name */
@@ -315,92 +325,92 @@ struct ufs_dir_entry {
 };
 
 struct ufs_csum {
-	__u32	cs_ndir;	/* number of directories */
-	__u32	cs_nbfree;	/* number of free blocks */
-	__u32	cs_nifree;	/* number of free inodes */
-	__u32	cs_nffree;	/* number of free frags */
+	__fs32	cs_ndir;	/* number of directories */
+	__fs32	cs_nbfree;	/* number of free blocks */
+	__fs32	cs_nifree;	/* number of free inodes */
+	__fs32	cs_nffree;	/* number of free frags */
 };
 struct ufs2_csum_total {
-	__u64	cs_ndir;	/* number of directories */
-	__u64	cs_nbfree;	/* number of free blocks */
-	__u64	cs_nifree;	/* number of free inodes */
-	__u64	cs_nffree;	/* number of free frags */
-	__u64   cs_numclusters;	/* number of free clusters */
-	__u64   cs_spare[3];	/* future expansion */
+	__fs64	cs_ndir;	/* number of directories */
+	__fs64	cs_nbfree;	/* number of free blocks */
+	__fs64	cs_nifree;	/* number of free inodes */
+	__fs64	cs_nffree;	/* number of free frags */
+	__fs64   cs_numclusters;	/* number of free clusters */
+	__fs64   cs_spare[3];	/* future expansion */
 };
 
 /*
  * This is the actual superblock, as it is laid out on the disk.
  */
 struct ufs_super_block {
-	__u32	fs_link;	/* UNUSED */
-	__u32	fs_rlink;	/* UNUSED */
-	__u32	fs_sblkno;	/* addr of super-block in filesys */
-	__u32	fs_cblkno;	/* offset of cyl-block in filesys */
-	__u32	fs_iblkno;	/* offset of inode-blocks in filesys */
-	__u32	fs_dblkno;	/* offset of first data after cg */
-	__u32	fs_cgoffset;	/* cylinder group offset in cylinder */
-	__u32	fs_cgmask;	/* used to calc mod fs_ntrak */
-	__u32	fs_time;	/* last time written -- time_t */
-	__u32	fs_size;	/* number of blocks in fs */
-	__u32	fs_dsize;	/* number of data blocks in fs */
-	__u32	fs_ncg;		/* number of cylinder groups */
-	__u32	fs_bsize;	/* size of basic blocks in fs */
-	__u32	fs_fsize;	/* size of frag blocks in fs */
-	__u32	fs_frag;	/* number of frags in a block in fs */
+	__fs32	fs_link;	/* UNUSED */
+	__fs32	fs_rlink;	/* UNUSED */
+	__fs32	fs_sblkno;	/* addr of super-block in filesys */
+	__fs32	fs_cblkno;	/* offset of cyl-block in filesys */
+	__fs32	fs_iblkno;	/* offset of inode-blocks in filesys */
+	__fs32	fs_dblkno;	/* offset of first data after cg */
+	__fs32	fs_cgoffset;	/* cylinder group offset in cylinder */
+	__fs32	fs_cgmask;	/* used to calc mod fs_ntrak */
+	__fs32	fs_time;	/* last time written -- time_t */
+	__fs32	fs_size;	/* number of blocks in fs */
+	__fs32	fs_dsize;	/* number of data blocks in fs */
+	__fs32	fs_ncg;		/* number of cylinder groups */
+	__fs32	fs_bsize;	/* size of basic blocks in fs */
+	__fs32	fs_fsize;	/* size of frag blocks in fs */
+	__fs32	fs_frag;	/* number of frags in a block in fs */
 /* these are configuration parameters */
-	__u32	fs_minfree;	/* minimum percentage of free blocks */
-	__u32	fs_rotdelay;	/* num of ms for optimal next block */
-	__u32	fs_rps;		/* disk revolutions per second */
+	__fs32	fs_minfree;	/* minimum percentage of free blocks */
+	__fs32	fs_rotdelay;	/* num of ms for optimal next block */
+	__fs32	fs_rps;		/* disk revolutions per second */
 /* these fields can be computed from the others */
-	__u32	fs_bmask;	/* ``blkoff'' calc of blk offsets */
-	__u32	fs_fmask;	/* ``fragoff'' calc of frag offsets */
-	__u32	fs_bshift;	/* ``lblkno'' calc of logical blkno */
-	__u32	fs_fshift;	/* ``numfrags'' calc number of frags */
+	__fs32	fs_bmask;	/* ``blkoff'' calc of blk offsets */
+	__fs32	fs_fmask;	/* ``fragoff'' calc of frag offsets */
+	__fs32	fs_bshift;	/* ``lblkno'' calc of logical blkno */
+	__fs32	fs_fshift;	/* ``numfrags'' calc number of frags */
 /* these are configuration parameters */
-	__u32	fs_maxcontig;	/* max number of contiguous blks */
-	__u32	fs_maxbpg;	/* max number of blks per cyl group */
+	__fs32	fs_maxcontig;	/* max number of contiguous blks */
+	__fs32	fs_maxbpg;	/* max number of blks per cyl group */
 /* these fields can be computed from the others */
-	__u32	fs_fragshift;	/* block to frag shift */
-	__u32	fs_fsbtodb;	/* fsbtodb and dbtofsb shift constant */
-	__u32	fs_sbsize;	/* actual size of super block */
-	__u32	fs_csmask;	/* csum block offset */
-	__u32	fs_csshift;	/* csum block number */
-	__u32	fs_nindir;	/* value of NINDIR */
-	__u32	fs_inopb;	/* value of INOPB */
-	__u32	fs_nspf;	/* value of NSPF */
+	__fs32	fs_fragshift;	/* block to frag shift */
+	__fs32	fs_fsbtodb;	/* fsbtodb and dbtofsb shift constant */
+	__fs32	fs_sbsize;	/* actual size of super block */
+	__fs32	fs_csmask;	/* csum block offset */
+	__fs32	fs_csshift;	/* csum block number */
+	__fs32	fs_nindir;	/* value of NINDIR */
+	__fs32	fs_inopb;	/* value of INOPB */
+	__fs32	fs_nspf;	/* value of NSPF */
 /* yet another configuration parameter */
-	__u32	fs_optim;	/* optimization preference, see below */
+	__fs32	fs_optim;	/* optimization preference, see below */
 /* these fields are derived from the hardware */
 	union {
 		struct {
-			__u32	fs_npsect;	/* # sectors/track including spares */
+			__fs32	fs_npsect;	/* # sectors/track including spares */
 		} fs_sun;
 		struct {
-			__s32	fs_state;	/* file system state time stamp */
+			__fs32	fs_state;	/* file system state time stamp */
 		} fs_sunx86;
 	} fs_u1;
-	__u32	fs_interleave;	/* hardware sector interleave */
-	__u32	fs_trackskew;	/* sector 0 skew, per track */
+	__fs32	fs_interleave;	/* hardware sector interleave */
+	__fs32	fs_trackskew;	/* sector 0 skew, per track */
 /* a unique id for this filesystem (currently unused and unmaintained) */
 /* In 4.3 Tahoe this space is used by fs_headswitch and fs_trkseek */
 /* Neither of those fields is used in the Tahoe code right now but */
 /* there could be problems if they are.                            */
-	__u32	fs_id[2];	/* file system id */
+	__fs32	fs_id[2];	/* file system id */
 /* sizes determined by number of cylinder groups and their sizes */
-	__u32	fs_csaddr;	/* blk addr of cyl grp summary area */
-	__u32	fs_cssize;	/* size of cyl grp summary area */
-	__u32	fs_cgsize;	/* cylinder group size */
+	__fs32	fs_csaddr;	/* blk addr of cyl grp summary area */
+	__fs32	fs_cssize;	/* size of cyl grp summary area */
+	__fs32	fs_cgsize;	/* cylinder group size */
 /* these fields are derived from the hardware */
-	__u32	fs_ntrak;	/* tracks per cylinder */
-	__u32	fs_nsect;	/* sectors per track */
-	__u32	fs_spc;		/* sectors per cylinder */
+	__fs32	fs_ntrak;	/* tracks per cylinder */
+	__fs32	fs_nsect;	/* sectors per track */
+	__fs32	fs_spc;		/* sectors per cylinder */
 /* this comes from the disk driver partitioning */
-	__u32	fs_ncyl;	/* cylinders in file system */
+	__fs32	fs_ncyl;	/* cylinders in file system */
 /* these fields can be computed from the others */
-	__u32	fs_cpg;		/* cylinders per group */
-	__u32	fs_ipg;		/* inodes per cylinder group */
-	__u32	fs_fpg;		/* blocks per group * fs_frag */
+	__fs32	fs_cpg;		/* cylinders per group */
+	__fs32	fs_ipg;		/* inodes per cylinder group */
+	__fs32	fs_fpg;		/* blocks per group * fs_frag */
 /* this data must be re-computed after crashes */
 	struct ufs_csum fs_cstotal;	/* cylinder summary information */
 /* these fields are cleared at mount time */
@@ -411,69 +421,69 @@ struct ufs_super_block {
 	union {
 		struct {
 			__s8	fs_fsmnt[UFS_MAXMNTLEN];/* name mounted on */
-			__u32	fs_cgrotor;	/* last cg searched */
-			__u32	fs_csp[UFS_MAXCSBUFS];/*list of fs_cs info buffers */
-			__u32	fs_maxcluster;
-			__u32	fs_cpc;		/* cyl per cycle in postbl */
-			__u16	fs_opostbl[16][8]; /* old rotation block list head */
+			__fs32	fs_cgrotor;	/* last cg searched */
+			__fs32	fs_csp[UFS_MAXCSBUFS];/*list of fs_cs info buffers */
+			__fs32	fs_maxcluster;
+			__fs32	fs_cpc;		/* cyl per cycle in postbl */
+			__fs16	fs_opostbl[16][8]; /* old rotation block list head */
 		} fs_u1;
 		struct {
 			__s8  fs_fsmnt[UFS2_MAXMNTLEN];	/* name mounted on */
 			__u8   fs_volname[UFS2_MAXVOLLEN]; /* volume name */
-			__u64  fs_swuid;		/* system-wide uid */
-			__s32  fs_pad;	/* due to alignment of fs_swuid */
-			__u32   fs_cgrotor;     /* last cg searched */
-			__u32   fs_ocsp[UFS2_NOCSPTRS]; /*list of fs_cs info buffers */
-			__u32   fs_contigdirs;/*# of contiguously allocated dirs */
-			__u32   fs_csp;	/* cg summary info buffer for fs_cs */
-			__u32   fs_maxcluster;
-			__u32   fs_active;/* used by snapshots to track fs */
-			__s32   fs_old_cpc;	/* cyl per cycle in postbl */
-			__s32   fs_maxbsize;/*maximum blocking factor permitted */
-			__s64   fs_sparecon64[17];/*old rotation block list head */
-			__s64   fs_sblockloc; /* byte offset of standard superblock */
+			__fs64  fs_swuid;		/* system-wide uid */
+			__fs32  fs_pad;	/* due to alignment of fs_swuid */
+			__fs32   fs_cgrotor;     /* last cg searched */
+			__fs32   fs_ocsp[UFS2_NOCSPTRS]; /*list of fs_cs info buffers */
+			__fs32   fs_contigdirs;/*# of contiguously allocated dirs */
+			__fs32   fs_csp;	/* cg summary info buffer for fs_cs */
+			__fs32   fs_maxcluster;
+			__fs32   fs_active;/* used by snapshots to track fs */
+			__fs32   fs_old_cpc;	/* cyl per cycle in postbl */
+			__fs32   fs_maxbsize;/*maximum blocking factor permitted */
+			__fs64   fs_sparecon64[17];/*old rotation block list head */
+			__fs64   fs_sblockloc; /* byte offset of standard superblock */
 			struct  ufs2_csum_total fs_cstotal;/*cylinder summary information*/
 			struct  ufs_timeval    fs_time;		/* last time written */
-			__s64    fs_size;		/* number of blocks in fs */
-			__s64    fs_dsize;	/* number of data blocks in fs */
-			__u64    fs_csaddr;	/* blk addr of cyl grp summary area */
-			__s64    fs_pendingblocks;/* blocks in process of being freed */
-			__s32    fs_pendinginodes;/*inodes in process of being freed */
+			__fs64    fs_size;		/* number of blocks in fs */
+			__fs64    fs_dsize;	/* number of data blocks in fs */
+			__fs64   fs_csaddr;	/* blk addr of cyl grp summary area */
+			__fs64    fs_pendingblocks;/* blocks in process of being freed */
+			__fs32    fs_pendinginodes;/*inodes in process of being freed */
 		} fs_u2;
 	}  fs_u11;
 	union {
 		struct {
-			__s32	fs_sparecon[53];/* reserved for future constants */
-			__s32	fs_reclaim;
-			__s32	fs_sparecon2[1];
-			__s32	fs_state;	/* file system state time stamp */
-			__u32	fs_qbmask[2];	/* ~usb_bmask */
-			__u32	fs_qfmask[2];	/* ~usb_fmask */
+			__fs32	fs_sparecon[53];/* reserved for future constants */
+			__fs32	fs_reclaim;
+			__fs32	fs_sparecon2[1];
+			__fs32	fs_state;	/* file system state time stamp */
+			__fs32	fs_qbmask[2];	/* ~usb_bmask */
+			__fs32	fs_qfmask[2];	/* ~usb_fmask */
 		} fs_sun;
 		struct {
-			__s32	fs_sparecon[53];/* reserved for future constants */
-			__s32	fs_reclaim;
-			__s32	fs_sparecon2[1];
-			__u32	fs_npsect;	/* # sectors/track including spares */
-			__u32	fs_qbmask[2];	/* ~usb_bmask */
-			__u32	fs_qfmask[2];	/* ~usb_fmask */
+			__fs32	fs_sparecon[53];/* reserved for future constants */
+			__fs32	fs_reclaim;
+			__fs32	fs_sparecon2[1];
+			__fs32	fs_npsect;	/* # sectors/track including spares */
+			__fs32	fs_qbmask[2];	/* ~usb_bmask */
+			__fs32	fs_qfmask[2];	/* ~usb_fmask */
 		} fs_sunx86;
 		struct {
-			__s32	fs_sparecon[50];/* reserved for future constants */
-			__s32	fs_contigsumsize;/* size of cluster summary array */
-			__s32	fs_maxsymlinklen;/* max length of an internal symlink */
-			__s32	fs_inodefmt;	/* format of on-disk inodes */
-			__u32	fs_maxfilesize[2];	/* max representable file size */
-			__u32	fs_qbmask[2];	/* ~usb_bmask */
-			__u32	fs_qfmask[2];	/* ~usb_fmask */
-			__s32	fs_state;	/* file system state time stamp */
+			__fs32	fs_sparecon[50];/* reserved for future constants */
+			__fs32	fs_contigsumsize;/* size of cluster summary array */
+			__fs32	fs_maxsymlinklen;/* max length of an internal symlink */
+			__fs32	fs_inodefmt;	/* format of on-disk inodes */
+			__fs32	fs_maxfilesize[2];	/* max representable file size */
+			__fs32	fs_qbmask[2];	/* ~usb_bmask */
+			__fs32	fs_qfmask[2];	/* ~usb_fmask */
+			__fs32	fs_state;	/* file system state time stamp */
 		} fs_44;
 	} fs_u2;
-	__s32	fs_postblformat;	/* format of positional layout tables */
-	__s32	fs_nrpos;		/* number of rotational positions */
-	__s32	fs_postbloff;		/* (__s16) rotation block list head */
-	__s32	fs_rotbloff;		/* (__u8) blocks for each rotation */
-	__s32	fs_magic;		/* magic number */
+	__fs32	fs_postblformat;	/* format of positional layout tables */
+	__fs32	fs_nrpos;		/* number of rotational positions */
+	__fs32	fs_postbloff;		/* (__s16) rotation block list head */
+	__fs32	fs_rotbloff;		/* (__u8) blocks for each rotation */
+	__fs32	fs_magic;		/* magic number */
 	__u8	fs_space[1];		/* list of blocks for each rotation */
 };
 
@@ -509,41 +519,41 @@ struct ufs_super_block {
  * size of this structure is 172 B
  */
 struct	ufs_cylinder_group {
-	__u32	cg_link;		/* linked list of cyl groups */
-	__u32	cg_magic;		/* magic number */
-	__u32	cg_time;		/* time last written */
-	__u32	cg_cgx;			/* we are the cgx'th cylinder group */
-	__u16	cg_ncyl;		/* number of cyl's this cg */
-	__u16	cg_niblk;		/* number of inode blocks this cg */
-	__u32	cg_ndblk;		/* number of data blocks this cg */
+	__fs32	cg_link;		/* linked list of cyl groups */
+	__fs32	cg_magic;		/* magic number */
+	__fs32	cg_time;		/* time last written */
+	__fs32	cg_cgx;			/* we are the cgx'th cylinder group */
+	__fs16	cg_ncyl;		/* number of cyl's this cg */
+	__fs16	cg_niblk;		/* number of inode blocks this cg */
+	__fs32	cg_ndblk;		/* number of data blocks this cg */
 	struct	ufs_csum cg_cs;		/* cylinder summary information */
-	__u32	cg_rotor;		/* position of last used block */
-	__u32	cg_frotor;		/* position of last used frag */
-	__u32	cg_irotor;		/* position of last used inode */
-	__u32	cg_frsum[UFS_MAXFRAG];	/* counts of available frags */
-	__u32	cg_btotoff;		/* (__u32) block totals per cylinder */
-	__u32	cg_boff;		/* (short) free block positions */
-	__u32	cg_iusedoff;		/* (char) used inode map */
-	__u32	cg_freeoff;		/* (u_char) free block map */
-	__u32	cg_nextfreeoff;		/* (u_char) next available space */
+	__fs32	cg_rotor;		/* position of last used block */
+	__fs32	cg_frotor;		/* position of last used frag */
+	__fs32	cg_irotor;		/* position of last used inode */
+	__fs32	cg_frsum[UFS_MAXFRAG];	/* counts of available frags */
+	__fs32	cg_btotoff;		/* (__u32) block totals per cylinder */
+	__fs32	cg_boff;		/* (short) free block positions */
+	__fs32	cg_iusedoff;		/* (char) used inode map */
+	__fs32	cg_freeoff;		/* (u_char) free block map */
+	__fs32	cg_nextfreeoff;		/* (u_char) next available space */
 	union {
 		struct {
-			__u32	cg_clustersumoff;	/* (u_int32) counts of avail clusters */
-			__u32	cg_clusteroff;		/* (u_int8) free cluster map */
-			__u32	cg_nclusterblks;	/* number of clusters this cg */
-			__u32	cg_sparecon[13];	/* reserved for future use */
+			__fs32	cg_clustersumoff;	/* (u_int32) counts of avail clusters */
+			__fs32	cg_clusteroff;		/* (u_int8) free cluster map */
+			__fs32	cg_nclusterblks;	/* number of clusters this cg */
+			__fs32	cg_sparecon[13];	/* reserved for future use */
 		} cg_44;
 		struct {
-			__u32	cg_clustersumoff;/* (u_int32) counts of avail clusters */
-			__u32	cg_clusteroff;	/* (u_int8) free cluster map */
-			__u32	cg_nclusterblks;/* number of clusters this cg */
-			__u32   cg_niblk; /* number of inode blocks this cg */
-			__u32   cg_initediblk;	/* last initialized inode */
-			__u32   cg_sparecon32[3];/* reserved for future use */
-			__u64   cg_time;	/* time last written */
-			__u64	cg_sparecon[3];	/* reserved for future use */
+			__fs32	cg_clustersumoff;/* (u_int32) counts of avail clusters */
+			__fs32	cg_clusteroff;	/* (u_int8) free cluster map */
+			__fs32	cg_nclusterblks;/* number of clusters this cg */
+			__fs32   cg_niblk; /* number of inode blocks this cg */
+			__fs32   cg_initediblk;	/* last initialized inode */
+			__fs32   cg_sparecon32[3];/* reserved for future use */
+			__fs64   cg_time;	/* time last written */
+			__fs64	cg_sparecon[3];	/* reserved for future use */
 		} cg_u2;
-		__u32	cg_sparecon[16];	/* reserved for future use */
+		__fs32	cg_sparecon[16];	/* reserved for future use */
 	} cg_u;
 	__u8	cg_space[1];		/* space for cylinder group maps */
 /* actually longer */
@@ -553,82 +563,82 @@ struct	ufs_cylinder_group {
  * structure of an on-disk inode
  */
 struct ufs_inode {
-	__u16	ui_mode;		/*  0x0 */
-	__u16	ui_nlink;		/*  0x2 */
+	__fs16	ui_mode;		/*  0x0 */
+	__fs16	ui_nlink;		/*  0x2 */
 	union {
 		struct {
-			__u16	ui_suid;	/*  0x4 */
-			__u16	ui_sgid;	/*  0x6 */
+			__fs16	ui_suid;	/*  0x4 */
+			__fs16	ui_sgid;	/*  0x6 */
 		} oldids;
-		__u32	ui_inumber;		/*  0x4 lsf: inode number */
-		__u32	ui_author;		/*  0x4 GNU HURD: author */
+		__fs32	ui_inumber;		/*  0x4 lsf: inode number */
+		__fs32	ui_author;		/*  0x4 GNU HURD: author */
 	} ui_u1;
-	__u64	ui_size;		/*  0x8 */
+	__fs64	ui_size;		/*  0x8 */
 	struct ufs_timeval ui_atime;	/* 0x10 access */
 	struct ufs_timeval ui_mtime;	/* 0x18 modification */
 	struct ufs_timeval ui_ctime;	/* 0x20 creation */
 	union {
 		struct {
-			__u32	ui_db[UFS_NDADDR];/* 0x28 data blocks */
-			__u32	ui_ib[UFS_NINDIR];/* 0x58 indirect blocks */
+			__fs32	ui_db[UFS_NDADDR];/* 0x28 data blocks */
+			__fs32	ui_ib[UFS_NINDIR];/* 0x58 indirect blocks */
 		} ui_addr;
 		__u8	ui_symlink[4*(UFS_NDADDR+UFS_NINDIR)];/* 0x28 fast symlink */
 	} ui_u2;
-	__u32	ui_flags;		/* 0x64 immutable, append-only... */
-	__u32	ui_blocks;		/* 0x68 blocks in use */
-	__u32	ui_gen;			/* 0x6c like ext2 i_version, for NFS support */
+	__fs32	ui_flags;		/* 0x64 immutable, append-only... */
+	__fs32	ui_blocks;		/* 0x68 blocks in use */
+	__fs32	ui_gen;			/* 0x6c like ext2 i_version, for NFS support */
 	union {
 		struct {
-			__u32	ui_shadow;	/* 0x70 shadow inode with security data */
-			__u32	ui_uid;		/* 0x74 long EFT version of uid */
-			__u32	ui_gid;		/* 0x78 long EFT version of gid */
-			__u32	ui_oeftflag;	/* 0x7c reserved */
+			__fs32	ui_shadow;	/* 0x70 shadow inode with security data */
+			__fs32	ui_uid;		/* 0x74 long EFT version of uid */
+			__fs32	ui_gid;		/* 0x78 long EFT version of gid */
+			__fs32	ui_oeftflag;	/* 0x7c reserved */
 		} ui_sun;
 		struct {
-			__u32	ui_uid;		/* 0x70 File owner */
-			__u32	ui_gid;		/* 0x74 File group */
-			__s32	ui_spare[2];	/* 0x78 reserved */
+			__fs32	ui_uid;		/* 0x70 File owner */
+			__fs32	ui_gid;		/* 0x74 File group */
+			__fs32	ui_spare[2];	/* 0x78 reserved */
 		} ui_44;
 		struct {
-			__u32	ui_uid;		/* 0x70 */
-			__u32	ui_gid;		/* 0x74 */
-			__u16	ui_modeh;	/* 0x78 mode high bits */
-			__u16	ui_spare;	/* 0x7A unused */
-			__u32	ui_trans;	/* 0x7c filesystem translator */
+			__fs32	ui_uid;		/* 0x70 */
+			__fs32	ui_gid;		/* 0x74 */
+			__fs16	ui_modeh;	/* 0x78 mode high bits */
+			__fs16	ui_spare;	/* 0x7A unused */
+			__fs32	ui_trans;	/* 0x7c filesystem translator */
 		} ui_hurd;
 	} ui_u3;
 };
 
 #define UFS_NXADDR  2            /* External addresses in inode. */
 struct ufs2_inode {
-	__u16     ui_mode;        /*   0: IFMT, permissions; see below. */
-	__s16     ui_nlink;       /*   2: File link count. */
-	__u32     ui_uid;         /*   4: File owner. */
-	__u32     ui_gid;         /*   8: File group. */
-	__u32     ui_blksize;     /*  12: Inode blocksize. */
-	__u64     ui_size;        /*  16: File byte count. */
-	__u64     ui_blocks;      /*  24: Bytes actually held. */
+	__fs16     ui_mode;        /*   0: IFMT, permissions; see below. */
+	__fs16     ui_nlink;       /*   2: File link count. */
+	__fs32     ui_uid;         /*   4: File owner. */
+	__fs32     ui_gid;         /*   8: File group. */
+	__fs32     ui_blksize;     /*  12: Inode blocksize. */
+	__fs64     ui_size;        /*  16: File byte count. */
+	__fs64     ui_blocks;      /*  24: Bytes actually held. */
 	struct ufs_timeval   ui_atime;       /*  32: Last access time. */
 	struct ufs_timeval   ui_mtime;       /*  40: Last modified time. */
 	struct ufs_timeval   ui_ctime;       /*  48: Last inode change time. */
 	struct ufs_timeval   ui_birthtime;   /*  56: Inode creation time. */
-	__s32     ui_mtimensec;   /*  64: Last modified time. */
-	__s32     ui_atimensec;   /*  68: Last access time. */
-	__s32     ui_ctimensec;   /*  72: Last inode change time. */
-	__s32     ui_birthnsec;   /*  76: Inode creation time. */
-	__s32     ui_gen;         /*  80: Generation number. */
-	__u32     ui_kernflags;   /*  84: Kernel flags. */
-	__u32     ui_flags;       /*  88: Status flags (chflags). */
-	__s32     ui_extsize;     /*  92: External attributes block. */
-	__s64     ui_extb[UFS_NXADDR];/*  96: External attributes block. */
+	__fs32     ui_mtimensec;   /*  64: Last modified time. */
+	__fs32     ui_atimensec;   /*  68: Last access time. */
+	__fs32     ui_ctimensec;   /*  72: Last inode change time. */
+	__fs32     ui_birthnsec;   /*  76: Inode creation time. */
+	__fs32     ui_gen;         /*  80: Generation number. */
+	__fs32     ui_kernflags;   /*  84: Kernel flags. */
+	__fs32     ui_flags;       /*  88: Status flags (chflags). */
+	__fs32     ui_extsize;     /*  92: External attributes block. */
+	__fs64     ui_extb[UFS_NXADDR];/*  96: External attributes block. */
 	union {
 		struct {
-			__s64     ui_db[UFS_NDADDR]; /* 112: Direct disk blocks. */
-			__s64     ui_ib[UFS_NINDIR];/* 208: Indirect disk blocks.*/
+			__fs64     ui_db[UFS_NDADDR]; /* 112: Direct disk blocks. */
+			__fs64     ui_ib[UFS_NINDIR];/* 208: Indirect disk blocks.*/
 		} ui_addr;
 	__u8	ui_symlink[2*4*(UFS_NDADDR+UFS_NINDIR)];/* 0x28 fast symlink */
 	} ui_u2;
-	__s64     ui_spare[3];    /* 232: Reserved; currently unused */
+	__fs64     ui_spare[3];    /* 232: Reserved; currently unused */
 };
 
 
@@ -752,60 +762,60 @@ struct ufs_sb_private_info {
  *	ufs_super_block_third	356
  */
 struct ufs_super_block_first {
-	__u32	fs_link;
-	__u32	fs_rlink;
-	__u32	fs_sblkno;
-	__u32	fs_cblkno;
-	__u32	fs_iblkno;
-	__u32	fs_dblkno;
-	__u32	fs_cgoffset;
-	__u32	fs_cgmask;
-	__u32	fs_time;
-	__u32	fs_size;
-	__u32	fs_dsize;
-	__u32	fs_ncg;
-	__u32	fs_bsize;
-	__u32	fs_fsize;
-	__u32	fs_frag;
-	__u32	fs_minfree;
-	__u32	fs_rotdelay;
-	__u32	fs_rps;
-	__u32	fs_bmask;
-	__u32	fs_fmask;
-	__u32	fs_bshift;
-	__u32	fs_fshift;
-	__u32	fs_maxcontig;
-	__u32	fs_maxbpg;
-	__u32	fs_fragshift;
-	__u32	fs_fsbtodb;
-	__u32	fs_sbsize;
-	__u32	fs_csmask;
-	__u32	fs_csshift;
-	__u32	fs_nindir;
-	__u32	fs_inopb;
-	__u32	fs_nspf;
-	__u32	fs_optim;
+	__fs32	fs_link;
+	__fs32	fs_rlink;
+	__fs32	fs_sblkno;
+	__fs32	fs_cblkno;
+	__fs32	fs_iblkno;
+	__fs32	fs_dblkno;
+	__fs32	fs_cgoffset;
+	__fs32	fs_cgmask;
+	__fs32	fs_time;
+	__fs32	fs_size;
+	__fs32	fs_dsize;
+	__fs32	fs_ncg;
+	__fs32	fs_bsize;
+	__fs32	fs_fsize;
+	__fs32	fs_frag;
+	__fs32	fs_minfree;
+	__fs32	fs_rotdelay;
+	__fs32	fs_rps;
+	__fs32	fs_bmask;
+	__fs32	fs_fmask;
+	__fs32	fs_bshift;
+	__fs32	fs_fshift;
+	__fs32	fs_maxcontig;
+	__fs32	fs_maxbpg;
+	__fs32	fs_fragshift;
+	__fs32	fs_fsbtodb;
+	__fs32	fs_sbsize;
+	__fs32	fs_csmask;
+	__fs32	fs_csshift;
+	__fs32	fs_nindir;
+	__fs32	fs_inopb;
+	__fs32	fs_nspf;
+	__fs32	fs_optim;
 	union {
 		struct {
-			__u32	fs_npsect;
+			__fs32	fs_npsect;
 		} fs_sun;
 		struct {
-			__s32	fs_state;
+			__fs32	fs_state;
 		} fs_sunx86;
 	} fs_u1;
-	__u32	fs_interleave;
-	__u32	fs_trackskew;
-	__u32	fs_id[2];
-	__u32	fs_csaddr;
-	__u32	fs_cssize;
-	__u32	fs_cgsize;
-	__u32	fs_ntrak;
-	__u32	fs_nsect;
-	__u32	fs_spc;
-	__u32	fs_ncyl;
-	__u32	fs_cpg;
-	__u32	fs_ipg;
-	__u32	fs_fpg;
+	__fs32	fs_interleave;
+	__fs32	fs_trackskew;
+	__fs32	fs_id[2];
+	__fs32	fs_csaddr;
+	__fs32	fs_cssize;
+	__fs32	fs_cgsize;
+	__fs32	fs_ntrak;
+	__fs32	fs_nsect;
+	__fs32	fs_spc;
+	__fs32	fs_ncyl;
+	__fs32	fs_cpg;
+	__fs32	fs_ipg;
+	__fs32	fs_fpg;
 	struct ufs_csum fs_cstotal;
 	__s8	fs_fmod;
 	__s8	fs_clean;
@@ -817,48 +827,48 @@ struct ufs_super_block_first {
 
 struct ufs_super_block_second {
 	__s8	fs_fsmnt[212];
-	__u32	fs_cgrotor;
-	__u32	fs_csp[UFS_MAXCSBUFS];
-	__u32	fs_maxcluster;
-	__u32	fs_cpc;
-	__u16	fs_opostbl[82];
+	__fs32	fs_cgrotor;
+	__fs32	fs_csp[UFS_MAXCSBUFS];
+	__fs32	fs_maxcluster;
+	__fs32	fs_cpc;
+	__fs16	fs_opostbl[82];
 };	
 
 struct ufs_super_block_third {
-	__u16	fs_opostbl[46];
+	__fs16	fs_opostbl[46];
 	union {
 		struct {
-			__s32	fs_sparecon[53];/* reserved for future constants */
-			__s32	fs_reclaim;
-			__s32	fs_sparecon2[1];
-			__s32	fs_state;	/* file system state time stamp */
-			__u32	fs_qbmask[2];	/* ~usb_bmask */
-			__u32	fs_qfmask[2];	/* ~usb_fmask */
+			__fs32	fs_sparecon[53];/* reserved for future constants */
+			__fs32	fs_reclaim;
+			__fs32	fs_sparecon2[1];
+			__fs32	fs_state;	/* file system state time stamp */
+			__fs32	fs_qbmask[2];	/* ~usb_bmask */
+			__fs32	fs_qfmask[2];	/* ~usb_fmask */
 		} fs_sun;
 		struct {
-			__s32	fs_sparecon[53];/* reserved for future constants */
-			__s32	fs_reclaim;
-			__s32	fs_sparecon2[1];
-			__u32	fs_npsect;	/* # sectors/track including spares */
-			__u32	fs_qbmask[2];	/* ~usb_bmask */
-			__u32	fs_qfmask[2];	/* ~usb_fmask */
+			__fs32	fs_sparecon[53];/* reserved for future constants */
+			__fs32	fs_reclaim;
+			__fs32	fs_sparecon2[1];
+			__fs32	fs_npsect;	/* # sectors/track including spares */
+			__fs32	fs_qbmask[2];	/* ~usb_bmask */
+			__fs32	fs_qfmask[2];	/* ~usb_fmask */
 		} fs_sunx86;
 		struct {
-			__s32	fs_sparecon[50];/* reserved for future constants */
-			__s32	fs_contigsumsize;/* size of cluster summary array */
-			__s32	fs_maxsymlinklen;/* max length of an internal symlink */
-			__s32	fs_inodefmt;	/* format of on-disk inodes */
-			__u32	fs_maxfilesize[2];	/* max representable file size */
-			__u32	fs_qbmask[2];	/* ~usb_bmask */
-			__u32	fs_qfmask[2];	/* ~usb_fmask */
-			__s32	fs_state;	/* file system state time stamp */
+			__fs32	fs_sparecon[50];/* reserved for future constants */
+			__fs32	fs_contigsumsize;/* size of cluster summary array */
+			__fs32	fs_maxsymlinklen;/* max length of an internal symlink */
+			__fs32	fs_inodefmt;	/* format of on-disk inodes */
+			__fs32	fs_maxfilesize[2];	/* max representable file size */
+			__fs32	fs_qbmask[2];	/* ~usb_bmask */
+			__fs32	fs_qfmask[2];	/* ~usb_fmask */
+			__fs32	fs_state;	/* file system state time stamp */
 		} fs_44;
 	} fs_u2;
-	__s32	fs_postblformat;
-	__s32	fs_nrpos;
-	__s32	fs_postbloff;
-	__s32	fs_rotbloff;
-	__s32	fs_magic;
+	__fs32	fs_postblformat;
+	__fs32	fs_nrpos;
+	__fs32	fs_postbloff;
+	__fs32	fs_rotbloff;
+	__fs32	fs_magic;
 	__u8	fs_space[1];
 };
 
@@ -867,7 +877,7 @@ struct ufs_super_block_third {
 /* balloc.c */
 extern void ufs_free_fragments (struct inode *, unsigned, unsigned);
 extern void ufs_free_blocks (struct inode *, unsigned, unsigned);
-extern unsigned ufs_new_fragments (struct inode *, u32 *, unsigned, unsigned, unsigned, int *);
+extern unsigned ufs_new_fragments (struct inode *, __fs32 *, unsigned, unsigned, unsigned, int *);
 
 /* cylinder.c */
 extern struct ufs_cg_private_info * ufs_load_cylinder (struct super_block *, unsigned);
@@ -875,7 +885,6 @@ extern void ufs_put_cylinder (struct super_block *, unsigned);
 
 /* dir.c */
 extern struct inode_operations ufs_dir_inode_operations;
-extern int ufs_check_dir_entry (const char *, struct inode *, struct ufs_dir_entry *, struct buffer_head *, unsigned long);
 extern int ufs_add_link (struct dentry *, struct inode *);
 extern ino_t ufs_inode_by_name(struct inode *, struct dentry *);
 extern int ufs_make_empty(struct inode *, struct inode *);
@@ -899,7 +908,7 @@ extern struct inode * ufs_new_inode (struct inode *, int);
 extern u64  ufs_frag_map (struct inode *, sector_t);
 extern void ufs_read_inode (struct inode *);
 extern void ufs_put_inode (struct inode *);
-extern void ufs_write_inode (struct inode *, int);
+extern int ufs_write_inode (struct inode *, int);
 extern int ufs_sync_inode (struct inode *);
 extern void ufs_delete_inode (struct inode *);
 extern struct buffer_head * ufs_getfrag (struct inode *, unsigned, int, int *);
@@ -909,11 +918,9 @@ extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *);
 extern struct file_operations ufs_dir_operations;
         
 /* super.c */
-extern struct file_system_type ufs_fs_type;
 extern void ufs_warning (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
 extern void ufs_error (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
 extern void ufs_panic (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4)));
-extern void ufs_write_super (struct super_block *);
 
 /* symlink.c */
 extern struct inode_operations ufs_fast_symlink_inode_operations;
diff --git a/include/linux/ufs_fs_i.h b/include/linux/ufs_fs_i.h
index c4ef0dfa9..21665a953 100644
--- a/include/linux/ufs_fs_i.h
+++ b/include/linux/ufs_fs_i.h
@@ -15,9 +15,9 @@
 
 struct ufs_inode_info {
 	union {
-		__u32	i_data[15];
+		__fs32	i_data[15];
 		__u8	i_symlink[4*15];
-		__u64	u2_i_data[15];
+		__fs64	u2_i_data[15];
 	} i_u1;
 	__u32	i_flags;
 	__u32	i_gen;
diff --git a/include/linux/umem.h b/include/linux/umem.h
index 2eb1f5564..f36ebfc32 100644
--- a/include/linux/umem.h
+++ b/include/linux/umem.h
@@ -110,19 +110,19 @@ DMA READ OPERATIONS.
 #define DMA_WRITE_TO_HOST 1
 
 struct mm_dma_desc {
-	u64	pci_addr;
-	u64	local_addr;
-	u32	transfer_size;
+	__le64	pci_addr;
+	__le64	local_addr;
+	__le32	transfer_size;
 	u32	zero1;
-	u64	next_desc_addr;
-	u64	sem_addr;
-	u32	control_bits;
+	__le64	next_desc_addr;
+	__le64	sem_addr;
+	__le32	control_bits;
 	u32	zero2;
 
 	dma_addr_t data_dma_handle;
 
 	/* Copy of the bits */
-	u64	sem_control_bits;
+	__le64	sem_control_bits;
 } __attribute__((aligned(8)));
 
 #define PCI_VENDOR_ID_MICRO_MEMORY		0x1332
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 632e19947..a43c95a01 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -294,8 +294,6 @@ struct usb_device {
 	struct semaphore serialize;
 
 	unsigned int toggle[2];		/* one bit for each endpoint ([0] = IN, [1] = OUT) */
-	unsigned int halted[2];		/* endpoint halts; one bit per endpoint # & direction; */
-					/* [0] = IN, [1] = OUT */
 	int epmaxpacketin[16];		/* INput endpoint specific maximums */
 	int epmaxpacketout[16];		/* OUTput endpoint specific maximums */
 
@@ -653,8 +651,6 @@ typedef void (*usb_complete_t)(struct urb *, struct pt_regs *);
  *	it likes with the URB, including resubmitting or freeing it.
  * @iso_frame_desc: Used to provide arrays of ISO transfer buffers and to 
  *	collect the transfer status for each buffer.
- * @timeout: If set to zero, the urb will never timeout.  Otherwise this is
- *	the time in jiffies that this urb will timeout in.
  *
  * This structure identifies USB transfer requests.  URBs must be allocated by
  * calling usb_alloc_urb() and freed with a call to usb_free_urb().
@@ -684,8 +680,8 @@ typedef void (*usb_complete_t)(struct urb *, struct pt_regs *);
  *
  * Initialization:
  *
- * All URBs submitted must initialize dev, pipe,
- * transfer_flags (may be zero), complete, timeout (may be zero).
+ * All URBs submitted must initialize the dev, pipe, transfer_flags (may be
+ * zero), and complete fields.
  * The URB_ASYNC_UNLINK transfer flag affects later invocations of
  * the usb_unlink_urb() routine.  Note: Failure to set URB_ASYNC_UNLINK
  * with usb_unlink_urb() is deprecated.  For synchronous unlinks use
@@ -785,7 +781,6 @@ struct urb
 	int number_of_packets;		/* (in) number of ISO packets */
 	int interval;			/* (modify) transfer interval (INT/ISO) */
 	int error_count;		/* (return) number of ISO errors */
-	int timeout;			/* (in) timeout, in jiffies */
 	void *context;			/* (in) context for completion */
 	usb_complete_t complete;	/* (in) completion routine */
 	struct usb_iso_packet_descriptor iso_frame_desc[0];	/* (in) ISO ONLY */
@@ -1084,10 +1079,6 @@ void usb_sg_wait (struct usb_sg_request *io);
 #define	usb_dotoggle(dev, ep, out)  ((dev)->toggle[out] ^= (1 << (ep)))
 #define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | ((bit) << (ep)))
 
-/* Endpoint halt control/status ... likewise USE WITH CAUTION */
-#define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep)))
-#define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep)))
-
 
 static inline unsigned int __create_pipe(struct usb_device *dev, unsigned int endpoint)
 {
diff --git a/include/linux/usb_ch9.h b/include/linux/usb_ch9.h
index 2a9e19b10..c1aa8d8f6 100644
--- a/include/linux/usb_ch9.h
+++ b/include/linux/usb_ch9.h
@@ -103,9 +103,9 @@
 struct usb_ctrlrequest {
 	__u8 bRequestType;
 	__u8 bRequest;
-	__u16 wValue;
-	__u16 wIndex;
-	__u16 wLength;
+	__le16 wValue;
+	__le16 wIndex;
+	__le16 wLength;
 } __attribute__ ((packed));
 
 /*-------------------------------------------------------------------------*/
@@ -230,7 +230,7 @@ struct usb_string_descriptor {
 	__u8  bLength;
 	__u8  bDescriptorType;
 
-	__u16 wData[1];		/* UTF-16LE encoded */
+	__le16 wData[1];		/* UTF-16LE encoded */
 } __attribute__ ((packed));
 
 /* note that "string" zero is special, it holds language codes that
diff --git a/include/linux/usb_gadget.h b/include/linux/usb_gadget.h
index 3f0831107..9bba99979 100644
--- a/include/linux/usb_gadget.h
+++ b/include/linux/usb_gadget.h
@@ -767,12 +767,6 @@ usb_gadget_disconnect (struct usb_gadget *gadget)
  * the (remote) host can't do that any longer; or an error state might
  * be cleared, to make the device behave identically whether or not
  * power is maintained.
- *
- * If the OTG b_hnp_enabled flag is set during a suspend() call, the
- * device may use HNP to switch from "B-Peripheral" to "B-Host" mode
- * (or back from "A-Peripheral" mode to the original "A-Host") if
- * the gadget driver calls usb_gadget_disconnect() before the device
- * is resumed.
  */
 struct usb_gadget_driver {
 	char			*function;
diff --git a/include/linux/videodev.h b/include/linux/videodev.h
index f82a7451f..a15ab1ade 100644
--- a/include/linux/videodev.h
+++ b/include/linux/videodev.h
@@ -1,6 +1,7 @@
 #ifndef __LINUX_VIDEODEV_H
 #define __LINUX_VIDEODEV_H
 
+#include <linux/compiler.h>
 #include <linux/types.h>
 #include <linux/version.h>
 
diff --git a/include/linux/vs_base.h b/include/linux/vs_base.h
index 52096ed2b..ed23add3a 100644
--- a/include/linux/vs_base.h
+++ b/include/linux/vs_base.h
@@ -38,32 +38,54 @@ static __inline__ int __vx_check(xid_t cid, xid_t id, unsigned int mode)
 }
 
 
-#define __vx_flags(v,m,f)	(((v) & (m)) ^ (f))
+#define __vx_state(v)	((v) ? ((v)->vx_state) : 0)
 
-#define	__vx_task_flags(t,m,f) \
-	(((t) && ((t)->vx_info)) ? \
-		__vx_flags((t)->vx_info->vx_flags,(m),(f)) : 0)
+#define vx_info_state(v,m)	(__vx_state(v) & (m))
 
-#define vx_current_flags() \
-	((current->vx_info) ? current->vx_info->vx_flags : 0)
 
-#define vx_flags(m,f)	__vx_flags(vx_current_flags(),(m),(f))
+/* generic flag merging */
+
+#define vx_check_flags(v,m,f)	(((v) & (m)) ^ (f))
+
+#define vx_mask_flags(v,f,m)	(((v) & ~(m)) | ((f) & (m)))
+
+#define vx_mask_mask(v,f,m)	(((v) & ~(m)) | ((v) & (f) & (m)))
+
+
+/* context flags */
+
+#define __vx_flags(v)	((v) ? (v)->vx_flags : 0)
+
+#define vx_current_flags()	__vx_flags(current->vx_info)
+
+#define vx_info_flags(v,m,f) \
+	vx_check_flags(__vx_flags(v),(m),(f))
 
+#define task_vx_flags(t,m,f) \
+	((t) && vx_info_flags((t)->vx_info, (m), (f)))
 
-#define vx_current_ccaps() \
-	((current->vx_info) ? current->vx_info->vx_ccaps : 0)
+#define vx_flags(m,f)	vx_info_flags(current->vx_info,(m),(f))
+
+
+/* context caps */
+
+#define __vx_ccaps(v)	((v) ? (v)->vx_ccaps : 0)
+
+#define vx_current_ccaps()	__vx_ccaps(current->vx_info)
+
+#define vx_info_ccaps(v,c)	(__vx_ccaps(v) & (c))
+
+#define vx_ccaps(c)	vx_info_ccaps(current->vx_info,(c))
 
-#define vx_ccaps(c)	(vx_current_ccaps() & (c))
 
 #define vx_current_bcaps() \
 	(((current->vx_info) && !vx_flags(VXF_STATE_SETUP, 0)) ? \
 	current->vx_info->vx_bcaps : cap_bset)
 
 
-/* generic flag merging */
-
-#define	vx_mask_flags(v,f,m)	(((v) & ~(m)) | ((f) & (m)))
+#define vx_current_initpid(n) \
+	(current->vx_info && \
+	(current->vx_info->vx_initpid == (n)))
 
-#define	vx_mask_mask(v,f,m)	(((v) & ~(m)) | ((v) & (f) & (m)))
 
 #endif
diff --git a/include/linux/vs_context.h b/include/linux/vs_context.h
index 541935bcb..9d119cdc2 100644
--- a/include/linux/vs_context.h
+++ b/include/linux/vs_context.h
@@ -28,8 +28,7 @@ static inline struct vx_info *__get_vx_info(struct vx_info *vxi,
 }
 
 
-#define	free_vx_info(i)	\
-	call_rcu(&i->vx_rcu, rcu_free_vx_info);
+extern void free_vx_info(struct vx_info *);
 
 #define put_vx_info(i)	__put_vx_info(i,__FILE__,__LINE__)
 
@@ -49,35 +48,40 @@ static inline void __put_vx_info(struct vx_info *vxi, const char *_file, int _li
 static inline void __set_vx_info(struct vx_info **vxp, struct vx_info *vxi,
 	const char *_file, int _line)
 {
-	BUG_ON(*vxp);
+	struct vx_info *vxo;
+
 	if (!vxi)
 		return;
+
 	vxlprintk(VXD_CBIT(xid, 3), "set_vx_info(%p[#%d.%d.%d])",
 		vxi, vxi?vxi->vx_id:0,
 		vxi?atomic_read(&vxi->vx_usecnt):0,
 		vxi?atomic_read(&vxi->vx_refcnt):0,
 		_file, _line);
+
 	atomic_inc(&vxi->vx_refcnt);
-	*vxp = __get_vx_info(vxi, _file, _line);
+	vxo = xchg(vxp, __get_vx_info(vxi, _file, _line));
+	BUG_ON(vxo);
 }
 
-#define	clr_vx_info(p)	__clr_vx_info(p,__FILE__,__LINE__)
+#define clr_vx_info(p)	__clr_vx_info(p,__FILE__,__LINE__)
 
 static inline void __clr_vx_info(struct vx_info **vxp,
 	const char *_file, int _line)
 {
-	struct vx_info *vxo = *vxp;
+	struct vx_info *vxo;
 
+	vxo = xchg(vxp, NULL);
 	if (!vxo)
 		return;
+
 	vxlprintk(VXD_CBIT(xid, 3), "clr_vx_info(%p[#%d.%d.%d])",
 		vxo, vxo?vxo->vx_id:0,
 		vxo?atomic_read(&vxo->vx_usecnt):0,
 		vxo?atomic_read(&vxo->vx_refcnt):0,
 		_file, _line);
-	*vxp = NULL;
-	wmb();
-	if (vxo && atomic_dec_and_test(&vxo->vx_refcnt))
+
+	if (atomic_dec_and_test(&vxo->vx_refcnt))
 		unhash_vx_info(vxo);
 	__put_vx_info(vxo, _file, _line);
 }
@@ -89,7 +93,7 @@ static __inline__ struct vx_info *__task_get_vx_info(struct task_struct *p,
 	const char *_file, int _line)
 {
 	struct vx_info *vxi;
-	
+
 	task_lock(p);
 	vxlprintk(VXD_CBIT(xid, 5), "task_get_vx_info(%p)",
 		p, _file, _line);
diff --git a/include/linux/vs_cvirt.h b/include/linux/vs_cvirt.h
index 07c3e8620..616706e8b 100644
--- a/include/linux/vs_cvirt.h
+++ b/include/linux/vs_cvirt.h
@@ -21,43 +21,76 @@ static inline struct new_utsname *vx_new_utsname(void)
 /* pid faking stuff */
 
 
-#define vx_map_tgid(v,p) \
-	__vx_map_tgid((v), (p), __FILE__, __LINE__)
+#define vx_info_map_pid(v,p) \
+	__vx_info_map_pid((v), (p), __FUNC__, __FILE__, __LINE__)
+#define vx_map_pid(p)	vx_info_map_pid(current->vx_info, p)
+#define vx_map_tgid(p) vx_map_pid(p)
 
-static inline int __vx_map_tgid(struct vx_info *vxi, int pid,
-	char *file, int line)
+static inline int __vx_info_map_pid(struct vx_info *vxi, int pid,
+	const char *func, const char *file, int line)
 {
-	if (vxi && __vx_flags(vxi->vx_flags, VXF_INFO_INIT, 0)) {
-		vxlprintk(VXD_CBIT(cvirt, 2),
+	if (vx_info_flags(vxi, VXF_INFO_INIT, 0)) {
+		vxfprintk(VXD_CBIT(cvirt, 2),
 			"vx_map_tgid: %p/%llx: %d -> %d",
-			vxi, vxi->vx_flags, pid,
-			(pid == vxi->vx_initpid)?1:pid,
-			file, line);
+			vxi, (long long)vxi->vx_flags, pid,
+			(pid && pid == vxi->vx_initpid)?1:pid,
+			func, file, line);
+		if (pid == 0)
+			return 0;
 		if (pid == vxi->vx_initpid)
 			return 1;
 	}
 	return pid;
 }
 
-#define vx_rmap_tgid(v,p) \
-	__vx_rmap_tgid((v), (p), __FILE__, __LINE__)
+#define vx_info_rmap_pid(v,p) \
+	__vx_info_rmap_pid((v), (p), __FUNC__, __FILE__, __LINE__)
+#define vx_rmap_pid(p)	vx_info_rmap_pid(current->vx_info, p)
+#define vx_rmap_tgid(p) vx_rmap_pid(p)
 
-static inline int __vx_rmap_tgid(struct vx_info *vxi, int pid,
-	char *file, int line)
+static inline int __vx_info_rmap_pid(struct vx_info *vxi, int pid,
+	const char *func, const char *file, int line)
 {
-	if (vxi && __vx_flags(vxi->vx_flags, VXF_INFO_INIT, 0)) {
-		vxlprintk(VXD_CBIT(cvirt, 2),
+	if (vx_info_flags(vxi, VXF_INFO_INIT, 0)) {
+		vxfprintk(VXD_CBIT(cvirt, 2),
 			"vx_rmap_tgid: %p/%llx: %d -> %d",
-			vxi, vxi->vx_flags, pid,
+			vxi, (long long)vxi->vx_flags, pid,
 			(pid == 1)?vxi->vx_initpid:pid,
-			file, line);
+			func, file, line);
 		if ((pid == 1) && vxi->vx_initpid)
 			return vxi->vx_initpid;
+		if (pid == vxi->vx_initpid)
+			return ~0U;
 	}
 	return pid;
 }
 
 
+static inline void vx_activate_task(struct task_struct *p)
+{
+	struct vx_info *vxi;
+
+	// if ((vxi = task_get_vx_info(p))) {
+	if ((vxi = p->vx_info)) {
+		vx_update_load(vxi);
+		atomic_inc(&vxi->cvirt.nr_running);
+		// put_vx_info(vxi);
+	}
+}
+
+static inline void vx_deactivate_task(struct task_struct *p)
+{
+	struct vx_info *vxi;
+
+	// if ((vxi = task_get_vx_info(p))) {
+	if ((vxi = p->vx_info)) {
+		vx_update_load(vxi);
+		atomic_dec(&vxi->cvirt.nr_running);
+		// put_vx_info(vxi);
+	}
+}
+
+
 #else
 #warning duplicate inclusion
 #endif
diff --git a/include/linux/vs_dlimit.h b/include/linux/vs_dlimit.h
index 53400ab98..805c25748 100644
--- a/include/linux/vs_dlimit.h
+++ b/include/linux/vs_dlimit.h
@@ -25,7 +25,7 @@ static inline struct dl_info *__get_dl_info(struct dl_info *dli,
 }
 
 
-#define	free_dl_info(i)	\
+#define free_dl_info(i) \
 	call_rcu(&i->dl_rcu, rcu_free_dl_info);
 
 #define put_dl_info(i)	__put_dl_info(i,__FILE__,__LINE__)
@@ -43,7 +43,7 @@ static inline void __put_dl_info(struct dl_info *dli,
 }
 
 
-#define	__dlimit_char(d)	((d)?'*':' ')
+#define __dlimit_char(d)	((d)?'*':' ')
 
 static inline int __dl_alloc_space(struct super_block *sb,
 	xid_t xid, dlsize_t nr, const char *file, int line)
@@ -66,7 +66,8 @@ static inline int __dl_alloc_space(struct super_block *sb,
 out:
 	vxlprintk(VXD_CBIT(dlim, 1),
 		"ALLOC (%p,#%d)%c %lld bytes (%d)",
-		sb, xid, __dlimit_char(dli), nr, ret, file, line);
+		sb, xid, __dlimit_char(dli), (long long)nr,
+		ret, file, line);
 	return ret;
 }
 
@@ -91,7 +92,8 @@ static inline void __dl_free_space(struct super_block *sb,
 out:
 	vxlprintk(VXD_CBIT(dlim, 1),
 		"FREE  (%p,#%d)%c %lld bytes",
-		sb, xid, __dlimit_char(dli), nr, _file, _line);
+		sb, xid, __dlimit_char(dli), (long long)nr,
+		_file, _line);
 }
 
 static inline int __dl_alloc_inode(struct super_block *sb,
@@ -167,8 +169,9 @@ static inline void __dl_adjust_block(struct super_block *sb, xid_t xid,
 
 	vxlprintk(VXD_CBIT(dlim, 2),
 		"ADJUST: %lld,%lld on %d,%d [mult=%d]",
-		bfree, broot, *free_blocks, *root_blocks,
-		dli->dl_nrlmult, _file, _line);
+		(long long)bfree, (long long)broot,
+		*free_blocks, *root_blocks, dli->dl_nrlmult,
+		_file, _line);
 	if (free_blocks) {
 		if (*free_blocks > bfree)
 			*free_blocks = bfree;
@@ -198,7 +201,7 @@ static inline void __dl_adjust_block(struct super_block *sb, xid_t xid,
 	__dl_free_inode(sb, xid, __FILE__, __LINE__ )
 
 
-#define	DLIMIT_ADJUST_BLOCK(sb, xid, fb, rb) \
+#define DLIMIT_ADJUST_BLOCK(sb, xid, fb, rb) \
 	__dl_adjust_block(sb, xid, fb, rb, __FILE__, __LINE__ )
 
 
diff --git a/include/linux/vs_limit.h b/include/linux/vs_limit.h
index ce0819404..30987973d 100644
--- a/include/linux/vs_limit.h
+++ b/include/linux/vs_limit.h
@@ -23,46 +23,39 @@ static inline void __vx_acc_cres(struct vx_info *vxi,
 			(vxi?vxi->vx_id:-1), vlimit_name[res], res,
 			(vxi?atomic_read(&vxi->limit.rcur[res]):0),
 			(dir>0)?"++":"--", _data, _file, _line);
-        if (vxi) {
-                if (dir > 0)
-                        atomic_inc(&vxi->limit.rcur[res]);
-                else
-                        atomic_dec(&vxi->limit.rcur[res]);
-        }
+	if (vxi) {
+		if (dir > 0)
+			atomic_inc(&vxi->limit.rcur[res]);
+		else
+			atomic_dec(&vxi->limit.rcur[res]);
+	}
 }
 
 #define vx_acc_cres(v,d,p,r) \
 	__vx_acc_cres((v), (r), (d), (p), __FILE__, __LINE__)
 
-#define vx_nproc_inc(p)	\
-	vx_acc_cres(current->vx_info, 1, (p), RLIMIT_NPROC)
-#define vx_nproc_dec(p)	\
-	vx_acc_cres(current->vx_info,-1, (p), RLIMIT_NPROC)
-
-#define vx_files_inc(f)	\
-	vx_acc_cres(current->vx_info, 1, (f), RLIMIT_NOFILE)
-#define vx_files_dec(f)	\
-	vx_acc_cres(current->vx_info,-1, (f), RLIMIT_NOFILE)
-
-/*
-#define vx_openfd_inc(f) do {					\
-	vx_acc_cres(current->vx_info, 1, RLIMIT_OPENFD);	\
-	printk("vx_openfd_inc: %d[#%d] in %s:%d\n",		\
-		f, current->xid, __FILE__, __LINE__);		\
-	} while (0)
-
-#define vx_openfd_dec(f) do {					\
-	vx_acc_cres(current->vx_info,-1, RLIMIT_OPENFD);	\
-	printk("vx_openfd_dec: %d[#%d] in %s:%d\n",		\
-		f, current->xid, __FILE__, __LINE__);		\
-	} while (0)
-*/
+#define vx_acc_cres_cond(x,d,p,r) \
+	__vx_acc_cres(((x) == current->xid) ? current->vx_info : 0,\
+	(r), (d), (p), __FILE__, __LINE__)
+
+#define vx_nproc_inc(p) \
+	vx_acc_cres((p)->vx_info, 1, (p), RLIMIT_NPROC)
+
+#define vx_nproc_dec(p) \
+	vx_acc_cres((p)->vx_info,-1, (p), RLIMIT_NPROC)
+
+#define vx_files_inc(f) \
+	vx_acc_cres_cond((f)->f_xid, 1, (f), RLIMIT_NOFILE)
+
+#define vx_files_dec(f) \
+	vx_acc_cres_cond((f)->f_xid,-1, (f), RLIMIT_NOFILE)
+
 
 #define vx_cres_avail(v,n,r) \
-        __vx_cres_avail((v), (r), (n), __FILE__, __LINE__)
+	__vx_cres_avail((v), (r), (n), __FILE__, __LINE__)
 
 static inline int __vx_cres_avail(struct vx_info *vxi,
-                int res, int num, char *_file, int _line)
+		int res, int num, char *_file, int _line)
 {
 	unsigned long value;
 
@@ -70,21 +63,21 @@ static inline int __vx_cres_avail(struct vx_info *vxi,
 		VXD_RLIMIT(res, RLIMIT_NPROC) ||
 		VXD_RLIMIT(res, VLIMIT_NSOCK))
 		vxlprintk(1, "vx_cres_avail[%5d,%s,%2d]: %5ld > %5d + %5d",
-                        (vxi?vxi->vx_id:-1), vlimit_name[res], res,
+			(vxi?vxi->vx_id:-1), vlimit_name[res], res,
 			(vxi?vxi->limit.rlim[res]:1),
-                        (vxi?atomic_read(&vxi->limit.rcur[res]):0),
+			(vxi?atomic_read(&vxi->limit.rcur[res]):0),
 			num, _file, _line);
-        if (!vxi)
-                return 1;
-	value = atomic_read(&vxi->limit.rcur[res]);	
+	if (!vxi)
+		return 1;
+	value = atomic_read(&vxi->limit.rcur[res]);
 	if (value > vxi->limit.rmax[res])
 		vxi->limit.rmax[res] = value;
-        if (vxi->limit.rlim[res] == RLIM_INFINITY)
-                return 1;
-        if (value + num <= vxi->limit.rlim[res])
-                return 1;
+	if (vxi->limit.rlim[res] == RLIM_INFINITY)
+		return 1;
+	if (value + num <= vxi->limit.rlim[res])
+		return 1;
 	atomic_inc(&vxi->limit.lhit[res]);
-        return 0;
+	return 0;
 }
 
 #define vx_nproc_avail(n) \
diff --git a/include/linux/vs_memory.h b/include/linux/vs_memory.h
index 3bcfefd49..43cde1aef 100644
--- a/include/linux/vs_memory.h
+++ b/include/linux/vs_memory.h
@@ -14,7 +14,7 @@
 	__vx_acc_page(&(m->v), m->mm_vx_info, r, d, __FILE__, __LINE__)
 
 static inline void __vx_acc_page(unsigned long *v, struct vx_info *vxi,
-                int res, int dir, char *file, int line)
+		int res, int dir, char *file, int line)
 {
 	if (VXD_RLIMIT(res, RLIMIT_RSS) ||
 		VXD_RLIMIT(res, RLIMIT_AS) ||
@@ -23,18 +23,18 @@ static inline void __vx_acc_page(unsigned long *v, struct vx_info *vxi,
 			(vxi?vxi->vx_id:-1), vlimit_name[res], res,
 			(vxi?atomic_read(&vxi->limit.rcur[res]):0),
 			(dir?"++":"--"), file, line);
-        if (v) {
-                if (dir > 0)
-                        ++(*v);
-                else
-                        --(*v);
-        }
-        if (vxi) {
-                if (dir > 0)
-                        atomic_inc(&vxi->limit.rcur[res]);
-                else
-                        atomic_dec(&vxi->limit.rcur[res]);
-        }
+	if (v) {
+		if (dir > 0)
+			++(*v);
+		else
+			--(*v);
+	}
+	if (vxi) {
+		if (dir > 0)
+			atomic_inc(&vxi->limit.rcur[res]);
+		else
+			atomic_dec(&vxi->limit.rcur[res]);
+	}
 }
 
 
@@ -42,7 +42,7 @@ static inline void __vx_acc_page(unsigned long *v, struct vx_info *vxi,
 	__vx_acc_pages(&(m->v), m->mm_vx_info, r, p, __FILE__, __LINE__)
 
 static inline void __vx_acc_pages(unsigned long *v, struct vx_info *vxi,
-                int res, int pages, char *_file, int _line)
+		int res, int pages, char *_file, int _line)
 {
 	if (VXD_RLIMIT(res, RLIMIT_RSS) ||
 		VXD_RLIMIT(res, RLIMIT_AS) ||
@@ -51,49 +51,49 @@ static inline void __vx_acc_pages(unsigned long *v, struct vx_info *vxi,
 			(vxi?vxi->vx_id:-1), vlimit_name[res], res,
 			(vxi?atomic_read(&vxi->limit.rcur[res]):0),
 			pages, _file, _line);
-        if (pages == 0)
-                return;
-        if (v)
-                *v += pages;
-        if (vxi)
-                atomic_add(pages, &vxi->limit.rcur[res]);
+	if (pages == 0)
+		return;
+	if (v)
+		*v += pages;
+	if (vxi)
+		atomic_add(pages, &vxi->limit.rcur[res]);
 }
 
 
 
-#define vx_acc_vmpage(m,d)     vx_acc_page(m, d, total_vm,  RLIMIT_AS)
-#define vx_acc_vmlpage(m,d)    vx_acc_page(m, d, locked_vm, RLIMIT_MEMLOCK)
-#define vx_acc_rsspage(m,d)    vx_acc_page(m, d, rss,	    RLIMIT_RSS)
+#define vx_acc_vmpage(m,d)	vx_acc_page(m, d, total_vm,  RLIMIT_AS)
+#define vx_acc_vmlpage(m,d)	vx_acc_page(m, d, locked_vm, RLIMIT_MEMLOCK)
+#define vx_acc_rsspage(m,d)	vx_acc_page(m, d, rss,	     RLIMIT_RSS)
 
-#define vx_acc_vmpages(m,p)    vx_acc_pages(m, p, total_vm,  RLIMIT_AS)
-#define vx_acc_vmlpages(m,p)   vx_acc_pages(m, p, locked_vm, RLIMIT_MEMLOCK)
-#define vx_acc_rsspages(m,p)   vx_acc_pages(m, p, rss,       RLIMIT_RSS)
+#define vx_acc_vmpages(m,p)	vx_acc_pages(m, p, total_vm,  RLIMIT_AS)
+#define vx_acc_vmlpages(m,p)	vx_acc_pages(m, p, locked_vm, RLIMIT_MEMLOCK)
+#define vx_acc_rsspages(m,p)	vx_acc_pages(m, p, rss,       RLIMIT_RSS)
 
-#define vx_pages_add(s,r,p)    __vx_acc_pages(0, s, r, p, __FILE__, __LINE__)
-#define vx_pages_sub(s,r,p)    vx_pages_add(s, r, -(p))
+#define vx_pages_add(s,r,p)	__vx_acc_pages(0, s, r, p, __FILE__, __LINE__)
+#define vx_pages_sub(s,r,p)	vx_pages_add(s, r, -(p))
 
-#define vx_vmpages_inc(m)      vx_acc_vmpage(m, 1)
-#define vx_vmpages_dec(m)      vx_acc_vmpage(m,-1)
-#define vx_vmpages_add(m,p)    vx_acc_vmpages(m, p)
-#define vx_vmpages_sub(m,p)    vx_acc_vmpages(m,-(p))
+#define vx_vmpages_inc(m)	vx_acc_vmpage(m, 1)
+#define vx_vmpages_dec(m)	vx_acc_vmpage(m,-1)
+#define vx_vmpages_add(m,p)	vx_acc_vmpages(m, p)
+#define vx_vmpages_sub(m,p)	vx_acc_vmpages(m,-(p))
 
-#define vx_vmlocked_inc(m)     vx_acc_vmlpage(m, 1)
-#define vx_vmlocked_dec(m)     vx_acc_vmlpage(m,-1)
-#define vx_vmlocked_add(m,p)   vx_acc_vmlpages(m, p)
-#define vx_vmlocked_sub(m,p)   vx_acc_vmlpages(m,-(p))
+#define vx_vmlocked_inc(m)	vx_acc_vmlpage(m, 1)
+#define vx_vmlocked_dec(m)	vx_acc_vmlpage(m,-1)
+#define vx_vmlocked_add(m,p)	vx_acc_vmlpages(m, p)
+#define vx_vmlocked_sub(m,p)	vx_acc_vmlpages(m,-(p))
 
-#define vx_rsspages_inc(m)     vx_acc_rsspage(m, 1)
-#define vx_rsspages_dec(m)     vx_acc_rsspage(m,-1)
-#define vx_rsspages_add(m,p)   vx_acc_rsspages(m, p)
-#define vx_rsspages_sub(m,p)   vx_acc_rsspages(m,-(p))
+#define vx_rsspages_inc(m)	vx_acc_rsspage(m, 1)
+#define vx_rsspages_dec(m)	vx_acc_rsspage(m,-1)
+#define vx_rsspages_add(m,p)	vx_acc_rsspages(m, p)
+#define vx_rsspages_sub(m,p)	vx_acc_rsspages(m,-(p))
 
 
 
 #define vx_pages_avail(m, p, r) \
-        __vx_pages_avail((m)->mm_vx_info, (r), (p), __FILE__, __LINE__)
+	__vx_pages_avail((m)->mm_vx_info, (r), (p), __FILE__, __LINE__)
 
 static inline int __vx_pages_avail(struct vx_info *vxi,
-                int res, int pages, char *_file, int _line)
+		int res, int pages, char *_file, int _line)
 {
 	unsigned long value;
 
@@ -101,26 +101,26 @@ static inline int __vx_pages_avail(struct vx_info *vxi,
 		VXD_RLIMIT(res, RLIMIT_AS) ||
 		VXD_RLIMIT(res, RLIMIT_MEMLOCK))
 		vxlprintk(1, "vx_pages_avail[%5d,%s,%2d]: %5ld > %5d + %5d",
-                        (vxi?vxi->vx_id:-1), vlimit_name[res], res,
+			(vxi?vxi->vx_id:-1), vlimit_name[res], res,
 			(vxi?vxi->limit.rlim[res]:1),
-                        (vxi?atomic_read(&vxi->limit.rcur[res]):0),
+			(vxi?atomic_read(&vxi->limit.rcur[res]):0),
 			pages, _file, _line);
-        if (!vxi)
-                return 1;
-	value = atomic_read(&vxi->limit.rcur[res]);	
+	if (!vxi)
+		return 1;
+	value = atomic_read(&vxi->limit.rcur[res]);
 	if (value > vxi->limit.rmax[res])
 		vxi->limit.rmax[res] = value;
-        if (vxi->limit.rlim[res] == RLIM_INFINITY)
-                return 1;
-        if (value + pages <= vxi->limit.rlim[res])
-                return 1;
+	if (vxi->limit.rlim[res] == RLIM_INFINITY)
+		return 1;
+	if (value + pages <= vxi->limit.rlim[res])
+		return 1;
 	atomic_inc(&vxi->limit.lhit[res]);
-        return 0;
+	return 0;
 }
 
-#define vx_vmpages_avail(m,p)  vx_pages_avail(m, p, RLIMIT_AS)
-#define vx_vmlocked_avail(m,p) vx_pages_avail(m, p, RLIMIT_MEMLOCK)
-#define vx_rsspages_avail(m,p) vx_pages_avail(m, p, RLIMIT_RSS)
+#define vx_vmpages_avail(m,p)	vx_pages_avail(m, p, RLIMIT_AS)
+#define vx_vmlocked_avail(m,p)	vx_pages_avail(m, p, RLIMIT_MEMLOCK)
+#define vx_rsspages_avail(m,p)	vx_pages_avail(m, p, RLIMIT_RSS)
 
 #else
 #warning duplicate inclusion
diff --git a/include/linux/vs_network.h b/include/linux/vs_network.h
index 915ad174f..4bbf92368 100644
--- a/include/linux/vs_network.h
+++ b/include/linux/vs_network.h
@@ -27,7 +27,7 @@ static inline struct nx_info *__get_nx_info(struct nx_info *nxi,
 }
 
 
-#define	free_nx_info(i)	\
+#define free_nx_info(i) \
 	call_rcu(&i->nx_rcu, rcu_free_nx_info);
 
 #define put_nx_info(i)	__put_nx_info(i,__FILE__,__LINE__)
@@ -43,41 +43,45 @@ static inline void __put_nx_info(struct nx_info *nxi, const char *_file, int _li
 		free_nx_info(nxi);
 }
 
-
 #define set_nx_info(p,i) __set_nx_info(p,i,__FILE__,__LINE__)
 
 static inline void __set_nx_info(struct nx_info **nxp, struct nx_info *nxi,
 	const char *_file, int _line)
 {
-	BUG_ON(*nxp);
+	struct nx_info *nxo;
+
 	if (!nxi)
 		return;
+
 	vxlprintk(VXD_CBIT(nid, 3), "set_nx_info(%p[#%d.%d.%d])",
 		nxi, nxi?nxi->nx_id:0,
 		nxi?atomic_read(&nxi->nx_usecnt):0,
 		nxi?atomic_read(&nxi->nx_refcnt):0,
 		_file, _line);
+
 	atomic_inc(&nxi->nx_refcnt);
-	*nxp = __get_nx_info(nxi, _file, _line);
+	nxo = xchg(nxp, __get_nx_info(nxi, _file, _line));
+	BUG_ON(nxo);
 }
 
-#define	clr_nx_info(p)	__clr_nx_info(p,__FILE__,__LINE__)
+#define clr_nx_info(p)	__clr_nx_info(p,__FILE__,__LINE__)
 
 static inline void __clr_nx_info(struct nx_info **nxp,
 	const char *_file, int _line)
 {
-	struct nx_info *nxo = *nxp;
+	struct nx_info *nxo;
 
+	nxo = xchg(nxp, NULL);
 	if (!nxo)
 		return;
+
 	vxlprintk(VXD_CBIT(nid, 3), "clr_nx_info(%p[#%d.%d.%d])",
 		nxo, nxo?nxo->nx_id:0,
 		nxo?atomic_read(&nxo->nx_usecnt):0,
 		nxo?atomic_read(&nxo->nx_refcnt):0,
 		_file, _line);
-	*nxp = NULL;
-	wmb();
-	if (nxo && atomic_dec_and_test(&nxo->nx_refcnt))
+
+	if (atomic_dec_and_test(&nxo->nx_refcnt))
 		unhash_nx_info(nxo);
 	__put_nx_info(nxo, _file, _line);
 }
@@ -89,7 +93,7 @@ static __inline__ struct nx_info *__task_get_nx_info(struct task_struct *p,
 	const char *_file, int _line)
 {
 	struct nx_info *nxi;
-	
+
 	task_lock(p);
 	nxi = __get_nx_info(p->nx_info, _file, _line);
 	vxlprintk(VXD_CBIT(nid, 5), "task_get_nx_info(%p)",
@@ -123,7 +127,7 @@ static __inline__ void __nx_verify_info(
 
 #define __nx_flags(v,m,f)	(((v) & (m)) ^ (f))
 
-#define	__nx_task_flags(t,m,f) \
+#define __nx_task_flags(t,m,f) \
 	(((t) && ((t)->nx_info)) ? \
 		__nx_flags((t)->nx_info->nx_flags,(m),(f)) : 0)
 
@@ -139,6 +143,21 @@ static __inline__ void __nx_verify_info(
 #define nx_ncaps(c)	(nx_current_ncaps() & (c))
 
 
+static inline int addr_in_nx_info(struct nx_info *nxi, uint32_t addr)
+{
+	int n,i;
+
+	if (!nxi)
+		return 1;
+
+	n = nxi->nbipv4;
+	for (i=0; i<n; i++) {
+		if (nxi->ipv4[i] == addr)
+			return 1;
+	}
+	return 0;
+}
+
 
 #else
 #warning duplicate inclusion
diff --git a/include/linux/vs_socket.h b/include/linux/vs_socket.h
index 560f2eb9b..ed3451a45 100644
--- a/include/linux/vs_socket.h
+++ b/include/linux/vs_socket.h
@@ -34,12 +34,12 @@ static inline int vx_sock_type(int family)
 static inline void __vx_acc_sock(struct vx_info *vxi,
 	int family, int pos, int size, char *file, int line)
 {
-        if (vxi) {
+	if (vxi) {
 		int type = vx_sock_type(family);
 
 		atomic_inc(&vxi->cacct.sock[type][pos].count);
 		atomic_add(size, &vxi->cacct.sock[type][pos].total);
-        }
+	}
 }
 
 #define vx_sock_recv(sk,s) \
@@ -50,12 +50,12 @@ static inline void __vx_acc_sock(struct vx_info *vxi,
 	vx_acc_sock((sk)->sk_vx_info, (sk)->sk_family, 2, (s))
 
 
-#define	sock_vx_init(s)	 do {		\
+#define sock_vx_init(s) do {		\
 	(s)->sk_xid = 0;		\
 	(s)->sk_vx_info = NULL;		\
 	} while (0)
 
-#define	sock_nx_init(s)	 do {		\
+#define sock_nx_init(s) do {		\
 	(s)->sk_nid = 0;		\
 	(s)->sk_nx_info = NULL;		\
 	} while (0)
diff --git a/include/linux/vserver.h b/include/linux/vserver.h
index db88b5e06..6c31e76b9 100644
--- a/include/linux/vserver.h
+++ b/include/linux/vserver.h
@@ -6,8 +6,4 @@
 
 extern long vs_reboot(unsigned int, void *);
 
-#define hlist_for_each_rcu(pos, head) \
-	for (pos = (head)->first; pos && ({ prefetch(pos->next); 1;}); \
-		pos = pos->next, ({ smp_read_barrier_depends(); 0;}))
-
 #endif
diff --git a/include/linux/vserver/context.h b/include/linux/vserver/context.h
index 434bfbaa2..4061e7b45 100644
--- a/include/linux/vserver/context.h
+++ b/include/linux/vserver/context.h
@@ -27,15 +27,19 @@ struct vx_info {
 	atomic_t vx_usecnt;			/* usage count */
 	atomic_t vx_refcnt;			/* reference count */
 	struct vx_info *vx_parent;		/* parent context */
+	int vx_state;				/* context state */
 
 	struct namespace *vx_namespace;		/* private namespace */
 	struct fs_struct *vx_fs;		/* private namespace fs */
-	uint64_t vx_flags;			/* VX_INFO_xxx */
+	uint64_t vx_flags;			/* context flags */
 	uint64_t vx_bcaps;			/* bounding caps (system) */
 	uint64_t vx_ccaps;			/* context caps (vserver) */
 
 	pid_t vx_initpid;			/* PID of fake init process */
 
+	spinlock_t vx_lock;
+	wait_queue_head_t vx_exit;		/* context exit waitqueue */
+
 	struct _vx_limit limit;			/* vserver limits */
 	struct _vx_sched sched;			/* vserver scheduler */
 	struct _vx_cvirt cvirt;			/* virtual/bias stuff */
@@ -44,6 +48,16 @@ struct vx_info {
 	char vx_name[65];			/* vserver name */
 };
 
+/* status flags */
+
+#define VXS_HASHED	0x0001
+#define VXS_PAUSED	0x0010
+#define VXS_ONHOLD	0x0020
+#define VXS_SHUTDOWN	0x0100
+#define VXS_DEFUNCT	0x1000
+#define VXS_RELEASED	0x8000
+
+/* check conditions */
 
 #define VX_ADMIN	0x0001
 #define VX_WATCH	0x0002
@@ -64,7 +78,7 @@ struct vx_info {
 
 struct rcu_head;
 
-extern void rcu_free_vx_info(struct rcu_head *);
+// extern void rcu_free_vx_info(struct rcu_head *);
 extern void unhash_vx_info(struct vx_info *);
 
 extern struct vx_info *locate_vx_info(int);
@@ -92,10 +106,10 @@ extern int vc_task_xid(uint32_t, void __user *);
 #define VCMD_vx_info		VC_CMD(VINFO, 5, 0)
 #define VCMD_nx_info		VC_CMD(VINFO, 6, 0)
 
-struct  vcmd_vx_info_v0 {
+struct	vcmd_vx_info_v0 {
 	uint32_t xid;
 	uint32_t initpid;
-	/* more to come */	
+	/* more to come */
 };
 
 #ifdef	__KERNEL__
@@ -115,7 +129,7 @@ extern int vc_ctx_migrate(uint32_t, void __user *);
 #define VCMD_get_cflags		VC_CMD(FLAGS, 1, 0)
 #define VCMD_set_cflags		VC_CMD(FLAGS, 2, 0)
 
-struct  vcmd_ctx_flags_v0 {
+struct	vcmd_ctx_flags_v0 {
 	uint64_t flagword;
 	uint64_t mask;
 };
@@ -143,6 +157,7 @@ extern int vc_set_cflags(uint32_t, void __user *);
 #define VXF_VIRT_MEM		0x00010000
 #define VXF_VIRT_UPTIME		0x00020000
 #define VXF_VIRT_CPU		0x00040000
+#define VXF_VIRT_LOAD		0x00080000
 
 #define VXF_HIDE_MOUNT		0x01000000
 #define VXF_HIDE_NETIF		0x02000000
@@ -150,15 +165,17 @@ extern int vc_set_cflags(uint32_t, void __user *);
 #define VXF_STATE_SETUP		(1ULL<<32)
 #define VXF_STATE_INIT		(1ULL<<33)
 
-#define	VXF_FORK_RSS		(1ULL<<48)
-#define	VXF_PROLIFIC		(1ULL<<49)
+#define VXF_FORK_RSS		(1ULL<<48)
+#define VXF_PROLIFIC		(1ULL<<49)
+
+#define VXF_IGNEG_NICE		(1ULL<<52)
 
 #define VXF_ONE_TIME		(0x0003ULL<<32)
 
 #define VCMD_get_ccaps		VC_CMD(FLAGS, 3, 0)
 #define VCMD_set_ccaps		VC_CMD(FLAGS, 4, 0)
 
-struct  vcmd_ctx_caps_v0 {
+struct	vcmd_ctx_caps_v0 {
 	uint64_t bcaps;
 	uint64_t ccaps;
 	uint64_t cmask;
@@ -176,6 +193,7 @@ extern int vc_set_ccaps(uint32_t, void __user *);
 #define VXC_RAW_ICMP		0x00000100
 
 #define VXC_SECURE_MOUNT	0x00010000
+#define VXC_SECURE_REMOUNT	0x00020000
 
 
 #endif	/* _VX_CONTEXT_H */
diff --git a/include/linux/vserver/cvirt.h b/include/linux/vserver/cvirt.h
index 7beeaaa7b..4a4bd17d8 100644
--- a/include/linux/vserver/cvirt.h
+++ b/include/linux/vserver/cvirt.h
@@ -6,17 +6,30 @@
 #include <linux/rwsem.h>
 #include <linux/jiffies.h>
 #include <linux/time.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
 #include <asm/atomic.h>
 
 /* context sub struct */
 
 struct _vx_cvirt {
-	int max_threads;
+	int max_threads;		/* maximum allowed threads */
+	atomic_t nr_threads;		/* number of current threads */
+	atomic_t nr_running;		/* number of running threads */
+
+	atomic_t nr_onhold;		/* processes on hold */
+	uint32_t onhold_last;		/* jiffies when put on hold */
 
 	struct timespec bias_idle;
-	uint64_t bias_jiffies;
+	struct timespec bias_uptime;	/* context creation point */
 
 	struct new_utsname utsname;
+
+	spinlock_t load_lock;		/* lock for the load averages */
+	uint32_t load_last;		/* last time load was cacled */
+	uint32_t load[3];		/* load averages 1,5,15 */
+
+	struct cpu_usage_stat cpustat[NR_CPUS];
 };
 
 struct sock_acc {
@@ -25,9 +38,6 @@ struct sock_acc {
 };
 
 struct _vx_cacct {
-	atomic_t nr_threads;
-	int nr_running;
-
 	unsigned long total_forks;
 
 	struct sock_acc sock[5][3];
@@ -52,16 +62,35 @@ static inline void vx_info_init_cvirt(struct _vx_cvirt *cvirt)
 {
 	uint64_t idle_jiffies = vx_idle_jiffies();
 
-	cvirt->bias_jiffies = get_jiffies_64();
+	do_posix_clock_monotonic_gettime(&cvirt->bias_uptime);
 	jiffies_to_timespec(idle_jiffies, &cvirt->bias_idle);
+	atomic_set(&cvirt->nr_threads, 0);
+	atomic_set(&cvirt->nr_running, 0);
+	atomic_set(&cvirt->nr_onhold, 0);
 
 	down_read(&uts_sem);
 	cvirt->utsname = system_utsname;
 	up_read(&uts_sem);
+
+	spin_lock_init(&cvirt->load_lock);
+	cvirt->load_last = jiffies;
+	cvirt->load[0] = 0;
+	cvirt->load[1] = 0;
+	cvirt->load[2] = 0;
 }
 
 static inline void vx_info_exit_cvirt(struct _vx_cvirt *cvirt)
 {
+#ifdef	CONFIG_VSERVER_DEBUG
+	int value;
+
+	if ((value = atomic_read(&cvirt->nr_threads)))
+		printk("!!! cvirt: %p[nr_threads] = %d on exit.\n",
+			cvirt, value);
+	if ((value = atomic_read(&cvirt->nr_running)))
+		printk("!!! cvirt: %p[nr_running] = %d on exit.\n",
+			cvirt, value);
+#endif
 	return;
 }
 
@@ -69,7 +98,6 @@ static inline void vx_info_init_cacct(struct _vx_cacct *cacct)
 {
 	int i,j;
 
-	atomic_set(&cacct->nr_threads, 1);
 	for (i=0; i<5; i++) {
 		for (j=0; j<3; j++) {
 			atomic_set(&cacct->sock[i][j].count, 0);
@@ -83,11 +111,19 @@ static inline void vx_info_exit_cacct(struct _vx_cacct *cacct)
 	return;
 }
 
+#define LOAD_INT(x) ((x) >> FSHIFT)
+#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
+
+
 static inline int vx_info_proc_cvirt(struct _vx_cvirt *cvirt, char *buffer)
 {
 	int length = 0;
+	int a, b, c;
+
 	length += sprintf(buffer + length,
-		"BiasJiffies:\t%lld\n", (long long int)cvirt->bias_jiffies);
+		"BiasUptime:\t%lu.%02lu\n",
+			(unsigned long)cvirt->bias_uptime.tv_sec,
+			(cvirt->bias_uptime.tv_nsec / (NSEC_PER_SEC / 100)));
 	length += sprintf(buffer + length,
 		"SysName:\t%.*s\n"
 		"NodeName:\t%.*s\n"
@@ -102,6 +138,22 @@ static inline int vx_info_proc_cvirt(struct _vx_cvirt *cvirt, char *buffer)
 		,__NEW_UTS_LEN, cvirt->utsname.machine
 		,__NEW_UTS_LEN, cvirt->utsname.domainname
 		);
+
+	a = cvirt->load[0] + (FIXED_1/200);
+	b = cvirt->load[1] + (FIXED_1/200);
+	c = cvirt->load[2] + (FIXED_1/200);
+	length += sprintf(buffer + length,
+		"nr_threads:\t%d\n"
+		"nr_running:\t%d\n"
+		"nr_onhold:\t%d\n"
+		"loadavg:\t%d.%02d %d.%02d %d.%02d\n"
+		,atomic_read(&cvirt->nr_threads)
+		,atomic_read(&cvirt->nr_running)
+		,atomic_read(&cvirt->nr_onhold)
+		,LOAD_INT(a), LOAD_FRAC(a)
+		,LOAD_INT(b), LOAD_FRAC(b)
+		,LOAD_INT(c), LOAD_FRAC(c)
+		);
 	return length;
 }
 
@@ -119,9 +171,11 @@ static inline int vx_info_proc_cacct(struct _vx_cacct *cacct, char *buffer)
 				,vx_sock_count(cacct, i, j)
 				,vx_sock_total(cacct, i, j)
 				);
-		}	
+		}
 		buffer[length++] = '\n';
 	}
+	length += sprintf(buffer + length,
+		"forks:\t%lu\n", cacct->total_forks);
 	return length;
 }
 
@@ -138,7 +192,12 @@ static inline int vx_info_proc_cacct(struct _vx_cacct *cacct, char *buffer)
 
 struct timespec;
 
-void vx_vsi_uptime(struct timespec *uptime, struct timespec *idle);
+void vx_vsi_uptime(struct timespec *, struct timespec *);
+
+struct vx_info;
+
+void vx_update_load(struct vx_info *);
+
 
 #endif	/* __KERNEL__ */
 
diff --git a/include/linux/vserver/debug.h b/include/linux/vserver/debug.h
index 15b52c930..9529c3c82 100644
--- a/include/linux/vserver/debug.h
+++ b/include/linux/vserver/debug.h
@@ -2,6 +2,21 @@
 #define _VX_DEBUG_H
 
 
+#define VXD_CBIT(n,m)	(vx_debug_ ## n & (1 << (m)))
+#define VXD_CMIN(n,m)	(vx_debug_ ## n > (m))
+#define VXD_MASK(n,m)	(vx_debug_ ## n & (m))
+
+#define VXD_QPOS(v,p)	(((uint32_t)(v) >> ((p)*8)) & 0xFF)
+#define VXD_QUAD(v)	VXD_QPOS(v,0), VXD_QPOS(v,1),		\
+			VXD_QPOS(v,2), VXD_QPOS(v,3)
+
+// #define	VXD_HERE	__FILE__, __LINE__
+
+#define __FUNC__	__func__
+
+
+#ifdef	CONFIG_VSERVER_DEBUG
+
 extern unsigned int vx_debug_switch;
 extern unsigned int vx_debug_xid;
 extern unsigned int vx_debug_nid;
@@ -11,33 +26,39 @@ extern unsigned int vx_debug_dlim;
 extern unsigned int vx_debug_cvirt;
 
 
-#define	VXD_CBIT(n,m)	(vx_debug_ ## n & (1 << (m)))
-#define	VXD_CMIN(n,m)	(vx_debug_ ## n > (m))
-#define	VXD_MASK(n,m)	(vx_debug_ ## n & (m))
-
-// #define	VXD_HERE	__FILE__, __LINE__
-
-
-#ifdef	CONFIG_VSERVER_DEBUG
-
-#define	VX_LOGLEVEL	"vxD: "
+#define VX_LOGLEVEL	"vxD: "
 
 #define vxdprintk(c,f,x...)					\
 	do {							\
 		if (c)						\
 			printk(VX_LOGLEVEL f "\n", x);		\
-	} while (0)	
+	} while (0)
 
 #define vxlprintk(c,f,x...)					\
 	do {							\
 		if (c)						\
 			printk(VX_LOGLEVEL f " @%s:%d\n", x);	\
-	} while (0)	
+	} while (0)
+
+#define vxfprintk(c,f,x...)					\
+	do {							\
+		if (c)						\
+			printk(VX_LOGLEVEL f " %s@%s:%d\n", x); \
+	} while (0)
 
 #else
 
-#define vxdprintk(x...)	do { } while (0)
-#define vxlprintk(x...)	do { } while (0)
+#define vx_debug_switch 0
+#define vx_debug_xid	0
+#define vx_debug_nid	0
+#define vx_debug_net	0
+#define vx_debug_limit	0
+#define vx_debug_dlim	0
+#define vx_debug_cvirt	0
+
+#define vxdprintk(x...) do { } while (0)
+#define vxlprintk(x...) do { } while (0)
+#define vxfprintk(x...) do { } while (0)
 
 #endif
 
diff --git a/include/linux/vserver/dlimit.h b/include/linux/vserver/dlimit.h
index c0cfafcd9..14a68fd04 100644
--- a/include/linux/vserver/dlimit.h
+++ b/include/linux/vserver/dlimit.h
@@ -13,12 +13,12 @@
 #define VCMD_get_dlimit		VC_CMD(DLIMIT, 6, 0)
 
 
-struct  vcmd_ctx_dlimit_base_v0 {
+struct	vcmd_ctx_dlimit_base_v0 {
 	const char __user *name;
 	uint32_t flags;
 };
 
-struct  vcmd_ctx_dlimit_v0 {
+struct	vcmd_ctx_dlimit_v0 {
 	const char __user *name;
 	uint32_t space_used;			/* used space in kbytes */
 	uint32_t space_total;			/* maximum space in kbytes */
@@ -28,9 +28,9 @@ struct  vcmd_ctx_dlimit_v0 {
 	uint32_t flags;
 };
 
-#define CDLIM_UNSET             (0ULL)
-#define CDLIM_INFINITY          (~0ULL)
-#define CDLIM_KEEP              (~1ULL)
+#define CDLIM_UNSET		(0ULL)
+#define CDLIM_INFINITY		(~0ULL)
+#define CDLIM_KEEP		(~1ULL)
 
 
 #ifdef	__KERNEL__
@@ -77,7 +77,7 @@ extern int vc_set_dlimit(uint32_t, void __user *);
 extern int vc_get_dlimit(uint32_t, void __user *);
 
 
-typedef	uint64_t dlsize_t;
+typedef uint64_t dlsize_t;
 
 
 #endif	/* __KERNEL__ */
diff --git a/include/linux/vserver/inode.h b/include/linux/vserver/inode.h
index fc49aba6d..b8a5e7885 100644
--- a/include/linux/vserver/inode.h
+++ b/include/linux/vserver/inode.h
@@ -11,7 +11,7 @@
 #define VCMD_get_iattr		VC_CMD(INODE, 1, 1)
 #define VCMD_set_iattr		VC_CMD(INODE, 2, 1)
 
-struct  vcmd_ctx_iattr_v0 {
+struct	vcmd_ctx_iattr_v0 {
 	/* device handle in id */
 	uint64_t ino;
 	uint32_t xid;
@@ -19,7 +19,7 @@ struct  vcmd_ctx_iattr_v0 {
 	uint32_t mask;
 };
 
-struct  vcmd_ctx_iattr_v1 {
+struct	vcmd_ctx_iattr_v1 {
 	const char __user *name;
 	uint32_t xid;
 	uint32_t flags;
@@ -36,7 +36,7 @@ struct  vcmd_ctx_iattr_v1 {
 
 #define IATTR_BARRIER	0x00010000
 #define IATTR_IUNLINK	0x00020000
-#define IATTR_IMMUTABLE	0x00040000
+#define IATTR_IMMUTABLE 0x00040000
 
 
 #ifdef	CONFIG_VSERVER_PROC_SECURE
@@ -49,7 +49,7 @@ struct  vcmd_ctx_iattr_v1 {
 
 #ifdef	__KERNEL__
 
-#define vx_hide_check(c,m)      (((m) & IATTR_HIDE) ? vx_check(c,m) : 1)
+#define vx_hide_check(c,m)	(((m) & IATTR_HIDE) ? vx_check(c,m) : 1)
 
 extern int vc_get_iattr_v0(uint32_t, void __user *);
 extern int vc_set_iattr_v0(uint32_t, void __user *);
diff --git a/include/linux/vserver/legacy.h b/include/linux/vserver/legacy.h
index 1372c0fa6..877bfb8ad 100644
--- a/include/linux/vserver/legacy.h
+++ b/include/linux/vserver/legacy.h
@@ -13,12 +13,12 @@
 
 /*  compatibiliy vserver arguments */
 
-struct  vcmd_new_s_context_v1 {
+struct	vcmd_new_s_context_v1 {
 	uint32_t remove_cap;
 	uint32_t flags;
 };
 
-struct  vcmd_set_ipv4root_v3 {
+struct	vcmd_set_ipv4root_v3 {
 	/* number of pairs in id */
 	uint32_t broadcast;
 	struct {
@@ -40,7 +40,7 @@ struct  vcmd_set_ipv4root_v3 {
 					/* of the context */
 #define VX_INFO_NAMESPACE	128	/* save private namespace */
 
-	
+
 #define NB_S_CONTEXT	16
 
 #define NB_IPV4ROOT	16
diff --git a/include/linux/vserver/limit.h b/include/linux/vserver/limit.h
index ef9c9fc2d..d9e1eea01 100644
--- a/include/linux/vserver/limit.h
+++ b/include/linux/vserver/limit.h
@@ -11,6 +11,7 @@
 
 #define VLIMIT_NSOCK	16
 
+
 extern const char *vlimit_name[NUM_LIMITS];
 
 struct _vx_limit {
@@ -53,19 +54,19 @@ static inline void vx_limit_fixup(struct _vx_limit *limit)
 {
 	unsigned long value;
 	unsigned int lim;
-	
-        for (lim=0; lim<NUM_LIMITS; lim++) {
-                value = atomic_read(&limit->rcur[lim]);
-                if (value > limit->rmax[lim])
+
+	for (lim=0; lim<NUM_LIMITS; lim++) {
+		value = atomic_read(&limit->rcur[lim]);
+		if (value > limit->rmax[lim])
 			limit->rmax[lim] = value;
 		if (limit->rmax[lim] > limit->rlim[lim])
 			limit->rmax[lim] = limit->rlim[lim];
-        }
+	}
 }
 
-#define	VX_LIMIT_FMT	":\t%10d\t%10ld\t%10ld\t%6d\n"
+#define VX_LIMIT_FMT	":\t%10d\t%10ld\t%10ld\t%6d\n"
 
-#define	VX_LIMIT_ARG(r)				\
+#define VX_LIMIT_ARG(r)				\
 		,atomic_read(&limit->rcur[r])	\
 		,limit->rmax[r]			\
 		,limit->rlim[r]			\
@@ -79,7 +80,7 @@ static inline int vx_info_proc_limit(struct _vx_limit *limit, char *buffer)
 		"VM"	VX_LIMIT_FMT
 		"VML"	VX_LIMIT_FMT
 		"RSS"	VX_LIMIT_FMT
-		"FILES"	VX_LIMIT_FMT
+		"FILES" VX_LIMIT_FMT
 		"SOCK"	VX_LIMIT_FMT
 		VX_LIMIT_ARG(RLIMIT_NPROC)
 		VX_LIMIT_ARG(RLIMIT_AS)
@@ -96,7 +97,7 @@ static inline int vx_info_proc_limit(struct _vx_limit *limit, char *buffer)
 
 #include "switch.h"
 
-#define	VXD_RLIMIT(r,l)		(VXD_CBIT(limit, (l)) && ((r) == (l)))
+#define VXD_RLIMIT(r,l)		(VXD_CBIT(limit, (l)) && ((r) == (l)))
 
 /*  rlimit vserver commands */
 
@@ -104,14 +105,14 @@ static inline int vx_info_proc_limit(struct _vx_limit *limit, char *buffer)
 #define VCMD_set_rlimit		VC_CMD(RLIMIT, 2, 0)
 #define VCMD_get_rlimit_mask	VC_CMD(RLIMIT, 3, 0)
 
-struct  vcmd_ctx_rlimit_v0 {
+struct	vcmd_ctx_rlimit_v0 {
 	uint32_t id;
 	uint64_t minimum;
 	uint64_t softlimit;
 	uint64_t maximum;
 };
 
-struct  vcmd_ctx_rlimit_mask_v0 {
+struct	vcmd_ctx_rlimit_mask_v0 {
 	uint32_t minimum;
 	uint32_t softlimit;
 	uint32_t maximum;
diff --git a/include/linux/vserver/namespace.h b/include/linux/vserver/namespace.h
index 140fc79f2..08167a110 100644
--- a/include/linux/vserver/namespace.h
+++ b/include/linux/vserver/namespace.h
@@ -3,13 +3,13 @@
 
 #include <linux/types.h>
 
-	
+
 /* virtual host info names */
 
 #define VCMD_vx_set_vhi_name	VC_CMD(VHOST, 1, 0)
 #define VCMD_vx_get_vhi_name	VC_CMD(VHOST, 2, 0)
 
-struct  vcmd_vx_vhi_name_v0 {
+struct	vcmd_vx_vhi_name_v0 {
 	uint32_t field;
 	char name[65];
 };
@@ -44,6 +44,9 @@ extern int vc_get_vhi_name(uint32_t, void __user *);
 struct vx_info;
 struct namespace;
 struct fs_struct;
+struct vfsmount;
+
+extern int vx_check_vfsmount(struct vx_info *, struct vfsmount *);
 
 extern int vx_set_namespace(struct vx_info *, struct namespace *, struct fs_struct *);
 
diff --git a/include/linux/vserver/network.h b/include/linux/vserver/network.h
index a89265d3d..e77866b5f 100644
--- a/include/linux/vserver/network.h
+++ b/include/linux/vserver/network.h
@@ -60,6 +60,10 @@ struct net_device;
 int ifa_in_nx_info(struct in_ifaddr *, struct nx_info *);
 int dev_in_nx_info(struct net_device *, struct nx_info *);
 
+struct sock;
+
+int nx_addr_conflict(struct nx_info *, uint32_t, struct sock *);
+
 
 #endif	/* __KERNEL__ */
 
@@ -76,9 +80,9 @@ extern int vc_task_nid(uint32_t, void __user *);
 
 #define VCMD_nx_info		VC_CMD(VINFO, 6, 0)
 
-struct  vcmd_nx_info_v0 {
+struct	vcmd_nx_info_v0 {
 	uint32_t nid;
-	/* more to come */	
+	/* more to come */
 };
 
 #ifdef	__KERNEL__
@@ -92,15 +96,15 @@ extern int vc_nx_info(uint32_t, void __user *);
 #define VCMD_net_add		VC_CMD(NETALT, 1, 0)
 #define VCMD_net_remove		VC_CMD(NETALT, 2, 0)
 
-struct  vcmd_net_nx_v0 {
+struct	vcmd_net_nx_v0 {
 	uint16_t type;
 	uint16_t count;
 	uint32_t ip[4];
 	uint32_t mask[4];
-	/* more to come */	
+	/* more to come */
 };
 
-//	IPN_TYPE_IPV4	
+//	IPN_TYPE_IPV4
 
 
 #ifdef	__KERNEL__
@@ -112,7 +116,7 @@ extern int vc_net_migrate(uint32_t, void __user *);
 #define VCMD_get_nflags		VC_CMD(FLAGS, 5, 0)
 #define VCMD_set_nflags		VC_CMD(FLAGS, 6, 0)
 
-struct  vcmd_net_flags_v0 {
+struct	vcmd_net_flags_v0 {
 	uint64_t flagword;
 	uint64_t mask;
 };
@@ -131,7 +135,7 @@ extern int vc_set_nflags(uint32_t, void __user *);
 #define VCMD_get_ncaps		VC_CMD(FLAGS, 7, 0)
 #define VCMD_set_ncaps		VC_CMD(FLAGS, 8, 0)
 
-struct  vcmd_net_caps_v0 {
+struct	vcmd_net_caps_v0 {
 	uint64_t ncaps;
 	uint64_t cmask;
 };
diff --git a/include/linux/vserver/sched.h b/include/linux/vserver/sched.h
index fd6bc2af3..f5982bb4e 100644
--- a/include/linux/vserver/sched.h
+++ b/include/linux/vserver/sched.h
@@ -8,24 +8,35 @@
 #include <asm/atomic.h>
 #include <asm/param.h>
 
+struct _vx_ticks {
+	uint64_t user_ticks;		/* token tick events */
+	uint64_t sys_ticks;		/* token tick events */
+	uint64_t hold_ticks;		/* token ticks paused */
+	uint64_t unused[5];		/* cacheline ? */
+};
+
 /* context sub struct */
 
 struct _vx_sched {
-	spinlock_t tokens_lock; /* lock for this structure */
+	atomic_t tokens;		/* number of CPU tokens */
+	spinlock_t tokens_lock;		/* lock for token bucket */
+
+	int fill_rate;			/* Fill rate: add X tokens... */
+	int interval;			/* Divisor:   per Y jiffies   */
+	int tokens_min;			/* Limit:     minimum for unhold */
+	int tokens_max;			/* Limit:     no more than N tokens */
+	uint32_t jiffies;		/* last time accounted */
 
-	int fill_rate;		/* Fill rate: add X tokens... */
-	int interval;		/* Divisor:   per Y jiffies   */
-	atomic_t tokens;	/* number of CPU tokens in this context */
-	int tokens_min;		/* Limit:     minimum for unhold */
-	int tokens_max;		/* Limit:     no more than N tokens */
-	uint32_t jiffies;	/* add an integral multiple of Y to this */
+	int priority_bias;		/* bias offset for priority */
+	cpumask_t cpus_allowed;		/* cpu mask for context */
 
-	uint64_t ticks;		/* token tick events */
-	cpumask_t cpus_allowed;	/* cpu mask for context */
+	struct _vx_ticks cpu[NR_CPUS];
 };
 
 static inline void vx_info_init_sched(struct _vx_sched *sched)
 {
+	int i;
+
 	/* scheduling; hard code starting values as constants */
 	sched->fill_rate	= 1;
 	sched->interval		= 4;
@@ -36,6 +47,13 @@ static inline void vx_info_init_sched(struct _vx_sched *sched)
 
 	atomic_set(&sched->tokens, HZ >> 2);
 	sched->cpus_allowed	= CPU_MASK_ALL;
+	sched->priority_bias	= 0;
+
+	for_each_cpu(i) {
+		sched->cpu[i].user_ticks	= 0;
+		sched->cpu[i].sys_ticks		= 0;
+		sched->cpu[i].hold_ticks	= 0;
+	}
 }
 
 static inline void vx_info_exit_sched(struct _vx_sched *sched)
@@ -45,20 +63,35 @@ static inline void vx_info_exit_sched(struct _vx_sched *sched)
 
 static inline int vx_info_proc_sched(struct _vx_sched *sched, char *buffer)
 {
-	return sprintf(buffer,
-		"Ticks:\t%16lld\n"
+	int length = 0;
+	int i;
+
+	length += sprintf(buffer,
 		"Token:\t\t%8d\n"
 		"FillRate:\t%8d\n"
-		"Interval:\t%8d\n"		
+		"Interval:\t%8d\n"
 		"TokensMin:\t%8d\n"
 		"TokensMax:\t%8d\n"
-		,(unsigned long long)sched->ticks
+		"PrioBias:\t%8d\n"
 		,atomic_read(&sched->tokens)
 		,sched->fill_rate
 		,sched->interval
 		,sched->tokens_min
 		,sched->tokens_max
+		,sched->priority_bias
 		);
+
+	for_each_online_cpu(i) {
+		length += sprintf(buffer + length,
+			"cpu %d: %lld %lld %lld\n"
+			,i
+			,(long long)sched->cpu[i].user_ticks
+			,(long long)sched->cpu[i].sys_ticks
+			,(long long)sched->cpu[i].hold_ticks
+			);
+	}
+
+	return length;
 }
 
 
@@ -70,9 +103,10 @@ static inline int vx_info_proc_sched(struct _vx_sched *sched, char *buffer)
 
 /*  sched vserver commands */
 
-#define VCMD_set_sched		VC_CMD(SCHED, 1, 2)
+#define VCMD_set_sched_v2	VC_CMD(SCHED, 1, 2)
+#define VCMD_set_sched		VC_CMD(SCHED, 1, 3)
 
-struct  vcmd_set_sched_v2 {
+struct	vcmd_set_sched_v2 {
 	int32_t fill_rate;
 	int32_t interval;
 	int32_t tokens;
@@ -81,16 +115,38 @@ struct  vcmd_set_sched_v2 {
 	uint64_t cpu_mask;
 };
 
+struct	vcmd_set_sched_v3 {
+	uint32_t set_mask;
+	int32_t fill_rate;
+	int32_t interval;
+	int32_t tokens;
+	int32_t tokens_min;
+	int32_t tokens_max;
+	int32_t priority_bias;
+};
+
+
+#define VXSM_FILL_RATE		0x0001
+#define VXSM_INTERVAL		0x0002
+#define VXSM_TOKENS		0x0010
+#define VXSM_TOKENS_MIN		0x0020
+#define VXSM_TOKENS_MAX		0x0040
+#define VXSM_PRIO_BIAS		0x0100
+
 #define SCHED_KEEP		(-2)
 
 #ifdef	__KERNEL__
 
 extern int vc_set_sched_v1(uint32_t, void __user *);
+extern int vc_set_sched_v2(uint32_t, void __user *);
 extern int vc_set_sched(uint32_t, void __user *);
 
 
 #define VAVAVOOM_RATIO		50
 
+#define MAX_PRIO_BIAS		20
+#define MIN_PRIO_BIAS		-20
+
 #include "context.h"
 
 
@@ -116,24 +172,48 @@ static inline int vx_need_resched(struct task_struct *p)
 {
 #ifdef	CONFIG_VSERVER_HARDCPU
 	struct vx_info *vxi = p->vx_info;
+#endif
+	int slice = --p->time_slice;
 
+#ifdef	CONFIG_VSERVER_HARDCPU
 	if (vxi) {
 		int tokens;
 
-		p->time_slice--;
-		if (atomic_read(&vxi->vx_usecnt) < 1)
-			printk("need_resched: p=%p, s=%ld, ref=%d, id=%d/%d\n",
-				p, p->state, atomic_read(&vxi->vx_usecnt),
-				vxi->vx_id, p->xid);
 		if ((tokens = vx_tokens_avail(vxi)) > 0)
 			vx_consume_token(vxi);
-		return ((p->time_slice == 0) || (tokens < 1));
+		/* for tokens > 0, one token was consumed */
+		if (tokens < 2)
+			return 1;
 	}
 #endif
-	p->time_slice--;
-	return (p->time_slice == 0);
+	return (slice == 0);
+}
+
+
+static inline void vx_onhold_inc(struct vx_info *vxi)
+{
+	int onhold = atomic_read(&vxi->cvirt.nr_onhold);
+
+	atomic_inc(&vxi->cvirt.nr_onhold);
+	if (!onhold)
+		vxi->cvirt.onhold_last = jiffies;
+}
+
+static inline void __vx_onhold_update(struct vx_info *vxi)
+{
+	int cpu = smp_processor_id();
+	uint32_t now = jiffies;
+	uint32_t delta = now - vxi->cvirt.onhold_last;
+
+	vxi->cvirt.onhold_last = now;
+	vxi->sched.cpu[cpu].hold_ticks += delta;
 }
 
+static inline void vx_onhold_dec(struct vx_info *vxi)
+{
+	if (atomic_dec_and_test(&vxi->cvirt.nr_onhold))
+		__vx_onhold_update(vxi);
+}
 
 #endif	/* __KERNEL__ */
 
diff --git a/include/linux/vserver/signal.h b/include/linux/vserver/signal.h
index 391112768..7d0d4303b 100644
--- a/include/linux/vserver/signal.h
+++ b/include/linux/vserver/signal.h
@@ -6,14 +6,22 @@
 /*  context signalling */
 
 #define VCMD_ctx_kill		VC_CMD(PROCTRL, 1, 0)
+#define VCMD_wait_exit		VC_CMD(EVENT, 99, 0)
 
-struct  vcmd_ctx_kill_v0 {
+struct	vcmd_ctx_kill_v0 {
 	int32_t pid;
 	int32_t sig;
 };
 
+struct	vcmd_wait_exit_v0 {
+	int32_t a;
+	int32_t b;
+};
+
 #ifdef	__KERNEL__
+
 extern int vc_ctx_kill(uint32_t, void __user *);
+extern int vc_wait_exit(uint32_t, void __user *);
 
 #endif	/* __KERNEL__ */
 #endif	/* _VX_SIGNAL_H */
diff --git a/include/linux/vserver/switch.h b/include/linux/vserver/switch.h
index 2aecbafd3..5855b05d4 100644
--- a/include/linux/vserver/switch.h
+++ b/include/linux/vserver/switch.h
@@ -12,11 +12,11 @@
 
 /*
 
-  Syscall Matrix V2.7
+  Syscall Matrix V2.8
 
-         |VERSION|CREATE |MODIFY |MIGRATE|CONTROL|EXPERIM| |SPECIAL|SPECIAL|
-         |STATS  |DESTROY|ALTER  |CHANGE |LIMIT  |TEST   | |       |       |
-         |INFO   |SETUP  |       |MOVE   |       |       | |       |       |
+	 |VERSION|CREATE |MODIFY |MIGRATE|CONTROL|EXPERIM| |SPECIAL|SPECIAL|
+	 |STATS  |DESTROY|ALTER  |CHANGE |LIMIT  |TEST   | |       |       |
+	 |INFO   |SETUP  |       |MOVE   |       |       | |       |       |
   -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
   SYSTEM |VERSION|VSETUP |VHOST  |       |       |       | |DEVICES|       |
   HOST   |     00|     01|     02|     03|     04|     05| |     06|     07|
@@ -25,22 +25,22 @@
   PROCESS|     08|     09|     10|     11|     12|     13| |     14|     15|
   -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
   MEMORY |       |       |       |       |       |       | |SWAP   |       |
-         |     16|     17|     18|     19|     20|     21| |     22|     23|
+	 |     16|     17|     18|     19|     20|     21| |     22|     23|
   -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
   NETWORK|       |VNET   |NETALT |NETMIG |NETCTL |       | |SERIAL |       |
-         |     24|     25|     26|     27|     28|     29| |     30|     31|
+	 |     24|     25|     26|     27|     28|     29| |     30|     31|
   -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
   DISK   |       |       |       |       |DLIMIT |       | |INODE  |       |
   VFS    |     32|     33|     34|     35|     36|     37| |     38|     39|
   -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
   OTHER  |       |       |       |       |       |       | |VINFO  |       |
-         |     40|     41|     42|     43|     44|     45| |     46|     47|
+	 |     40|     41|     42|     43|     44|     45| |     46|     47|
   =======+=======+=======+=======+=======+=======+=======+ +=======+=======+
-  SPECIAL|       |       |       |       |FLAGS  |       | |       |       |
-         |     48|     49|     50|     51|     52|     53| |     54|     55|
+  SPECIAL|EVENT  |       |       |       |FLAGS  |       | |       |       |
+	 |     48|     49|     50|     51|     52|     53| |     54|     55|
   -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
   SPECIAL|       |       |       |       |RLIMIT |SYSCALL| |       |COMPAT |
-         |     56|     57|     58|     59|     60|TEST 61| |     62|     63|
+	 |     56|     57|     58|     59|     60|TEST 61| |     62|     63|
   -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
 
 */
@@ -49,7 +49,7 @@
 
 #define VC_CAT_VSETUP		1
 #define VC_CAT_VHOST		2
-	
+
 #define VC_CAT_VPROC		9
 #define VC_CAT_PROCALT		10
 #define VC_CAT_PROCMIG		11
@@ -66,16 +66,17 @@
 #define VC_CAT_INODE		38
 
 #define VC_CAT_VINFO		46
+#define VC_CAT_EVENT		48
 
 #define VC_CAT_FLAGS		52
 #define VC_CAT_RLIMIT		60
 
 #define VC_CAT_SYSTEST		61
 #define VC_CAT_COMPAT		63
-	
+
 /*  interface version */
 
-#define VCI_VERSION		0x00010020
+#define VCI_VERSION		0x00010022
 
 
 /*  query version */
@@ -87,7 +88,6 @@
 
 #include <linux/errno.h>
 
-#define ENOTSUP		-EOPNOTSUPP
 
 #else	/* __KERNEL__ */
 #define __user
diff --git a/include/linux/vserver/xid.h b/include/linux/vserver/xid.h
index 3472defa5..23908fd4c 100644
--- a/include/linux/vserver/xid.h
+++ b/include/linux/vserver/xid.h
@@ -2,7 +2,7 @@
 #define _VX_XID_H
 
 
-#define	XID_TAG(in)	(!(in) || \
+#define XID_TAG(in)	(!(in) || \
 	(((struct inode *)in)->i_sb && \
 	(((struct inode *)in)->i_sb->s_flags & MS_TAGXID)))
 
@@ -114,7 +114,7 @@ static inline gid_t vx_map_gid(gid_t gid)
 }
 
 
-#ifdef	CONFIG_VSERVER_LEGACY		
+#ifdef	CONFIG_VSERVER_LEGACY
 #define FIOC_GETXID	_IOR('x', 1, long)
 #define FIOC_SETXID	_IOW('x', 2, long)
 #define FIOC_SETXIDJ	_IOW('x', 3, long)
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index 383a93cbb..6dbef2f84 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -93,8 +93,8 @@ void reset_vc(unsigned int new_console);
  * vc_screen.c shares this temporary buffer with the console write code so that
  * we can easily avoid touching user space while holding the console spinlock.
  */
-extern char con_buf[PAGE_SIZE];
 #define CON_BUF_SIZE	PAGE_SIZE
+extern char con_buf[CON_BUF_SIZE];
 extern struct semaphore con_buf_sem;
 
 #endif /* _VT_KERN_H */
diff --git a/include/linux/wait.h b/include/linux/wait.h
index e0f2b2ffc..21cd4df67 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -3,11 +3,20 @@
 
 #define WNOHANG		0x00000001
 #define WUNTRACED	0x00000002
+#define WSTOPPED	WUNTRACED
+#define WEXITED		0x00000004
+#define WCONTINUED	0x00000008
+#define WNOWAIT		0x01000000	/* Don't reap, just poll status.  */
 
 #define __WNOTHREAD	0x20000000	/* Don't wait on children of other threads in this group */
 #define __WALL		0x40000000	/* Wait on all children, regardless of type */
 #define __WCLONE	0x80000000	/* Wait only on non-SIGCHLD children */
 
+/* First argument to waitid: */
+#define P_ALL		0
+#define P_PID		1
+#define P_PGID		2
+
 #ifdef __KERNEL__
 
 #include <linux/config.h>
@@ -80,6 +89,15 @@ static inline int waitqueue_active(wait_queue_head_t *q)
 	return !list_empty(&q->task_list);
 }
 
+/*
+ * Used to distinguish between sync and async io wait context:
+ * sync i/o typically specifies a NULL wait queue entry or a wait
+ * queue entry bound to a task (current task) to wake up.
+ * aio specifies a wait queue entry with an async notification
+ * callback routine, not associated with any task.
+ */
+#define is_sync_wait(wait)	(!(wait) || ((wait)->task))
+
 extern void FASTCALL(add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait));
 extern void FASTCALL(add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t * wait));
 extern void FASTCALL(remove_wait_queue(wait_queue_head_t *q, wait_queue_t * wait));
@@ -138,6 +156,29 @@ do {									\
 	__wait_event(wq, condition);					\
 } while (0)
 
+#define __wait_event_timeout(wq, condition, ret)			\
+do {									\
+	DEFINE_WAIT(__wait);						\
+									\
+	for (;;) {							\
+		prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE);	\
+		if (condition)						\
+			break;						\
+		ret = schedule_timeout(ret);				\
+		if (!ret)						\
+			break;						\
+	}								\
+	finish_wait(&wq, &__wait);					\
+} while (0)
+
+#define wait_event_timeout(wq, condition, timeout)			\
+({									\
+	long __ret = timeout;						\
+	if (!(condition)) 						\
+		__wait_event_timeout(wq, condition, __ret);		\
+	__ret;								\
+})
+
 #define __wait_event_interruptible(wq, condition, ret)			\
 do {									\
 	DEFINE_WAIT(__wait);						\
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index 50633a827..d37b66436 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -63,6 +63,8 @@ extern void FASTCALL(flush_workqueue(struct workqueue_struct *wq));
 
 extern int FASTCALL(schedule_work(struct work_struct *work));
 extern int FASTCALL(schedule_delayed_work(struct work_struct *work, unsigned long delay));
+
+extern int schedule_delayed_work_on(int cpu, struct work_struct *work, unsigned long delay);
 extern void flush_scheduled_work(void);
 extern int current_is_keventd(void);
 extern int keventd_up(void);
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index e4450070a..7c165c334 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -29,7 +29,9 @@ enum writeback_sync_modes {
 };
 
 /*
- * A control structure which tells the writeback code what to do
+ * A control structure which tells the writeback code what to do.  These are
+ * always on the stack, and hence need no locking.  They are always initialised
+ * in a manner such that unspecified fields are set to zero.
  */
 struct writeback_control {
 	struct backing_dev_info *bdi;	/* If !NULL, only write back this
@@ -40,10 +42,19 @@ struct writeback_control {
 	long nr_to_write;		/* Write this many pages, and decrement
 					   this for each page written */
 	long pages_skipped;		/* Pages which were not written */
-	int nonblocking;		/* Don't get stuck on request queues */
-	int encountered_congestion;	/* An output: a queue is full */
-	int for_kupdate;		/* A kupdate writeback */
-	int for_reclaim;		/* Invoked from the page allocator */
+
+	/*
+	 * For a_ops->writepages(): is start or end are non-zero then this is
+	 * a hint that the filesystem need only write out the pages inside that
+	 * byterange.  The byte at `end' is included in the writeout request.
+	 */
+	loff_t start;
+	loff_t end;
+
+	unsigned nonblocking:1;			/* Don't get stuck on request queues */
+	unsigned encountered_congestion:1;	/* An output: a queue is full */
+	unsigned for_kupdate:1;			/* A kupdate writeback */
+	unsigned for_reclaim:1;			/* Invoked from the page allocator */
 };
 
 /*
@@ -64,6 +75,7 @@ void sync_inodes(int wait);
 /* writeback.h requires fs.h; it, too, is not included from here. */
 static inline void wait_on_inode(struct inode *inode)
 {
+	might_sleep();
 	if (inode->i_state & I_LOCK)
 		__wait_on_inode(inode);
 }
@@ -92,6 +104,8 @@ void page_writeback_init(void);
 void balance_dirty_pages_ratelimited(struct address_space *mapping);
 int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0);
 int do_writepages(struct address_space *mapping, struct writeback_control *wbc);
+int sync_page_range(struct inode *inode, struct address_space *mapping,
+			loff_t pos, size_t count);
 
 /* pdflush.c */
 extern int nr_pdflush_threads;	/* Global so it can be exported to sysctl
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index 2e22a996f..f0df02ae6 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -190,6 +190,7 @@ struct xfrm_usersa_info {
 	__u8				replay_window;
 	__u8				flags;
 #define XFRM_STATE_NOECN	1
+#define XFRM_STATE_DECAP_DSCP	2
 };
 
 struct xfrm_usersa_id {
diff --git a/include/math-emu/op-common.h b/include/math-emu/op-common.h
index 8c54bf6b9..93780abd0 100644
--- a/include/math-emu/op-common.h
+++ b/include/math-emu/op-common.h
@@ -769,9 +769,9 @@ do {									\
 	X##_c = FP_CLS_NORMAL;						\
 									\
 	if ((X##_s = (r < 0)))						\
-	  r = -r;							\
-									\
-	ur_ = (unsigned rtype) r;					\
+	  ur_ = (unsigned rtype) -r;					\
+	else								\
+	  ur_ = (unsigned rtype) r;					\
 	if (rsize <= _FP_W_TYPE_SIZE)					\
 	  __FP_CLZ(X##_e, ur_);						\
 	else								\
diff --git a/include/media/id.h b/include/media/id.h
index dca5dcfc0..1b0320dc8 100644
--- a/include/media/id.h
+++ b/include/media/id.h
@@ -35,4 +35,3 @@
 #ifndef I2C_ALGO_SAA7134
 # define I2C_ALGO_SAA7134 0x090000
 #endif
-
diff --git a/include/media/tuner.h b/include/media/tuner.h
index fb571d596..9597ffeb0 100644
--- a/include/media/tuner.h
+++ b/include/media/tuner.h
@@ -70,6 +70,8 @@
 #define TUNER_PHILIPS_FM1236_MK3 43
 #define TUNER_PHILIPS_4IN1       44	/* ATI TV Wonder Pro - Conexant */
 #define TUNER_MICROTUNE_4049FM5  45
+#define TUNER_LG_NTSC_TAPE       47
+#define TUNER_TNF_8831BGFF       48
 
 #define NOTUNER 0
 #define PAL     1	/* PAL_BG */
@@ -88,6 +90,7 @@
 #define Samsung 7
 #define Microtune 8
 #define HITACHI 9
+#define Panasonic 10
 
 #define TUNER_SET_TYPE               _IOW('t',1,int)    /* set tuner type */
 #define TUNER_SET_TVFREQ             _IOW('t',2,int)    /* set tv freq */
@@ -96,4 +99,18 @@
 # define TUNER_SET_MODE              _IOW('t',4,int)    /* set tuner mode */
 #endif
 
+#define  TDA9887_SET_CONFIG          _IOW('t',5,int)
+/* tv card specific */
+# define TDA9887_PRESENT             (1<<0)
+# define TDA9887_PORT1               (1<<1)
+# define TDA9887_PORT2               (1<<2)
+# define TDA9887_QSS                 (1<<3)
+# define TDA9887_INTERCARRIER        (1<<4)
+/* config options */
+# define TDA9887_DEEMPHASIS_MASK     (3<<16)
+# define TDA9887_DEEMPHASIS_NONE     (1<<16)
+# define TDA9887_DEEMPHASIS_50       (2<<16)
+# define TDA9887_DEEMPHASIS_75       (3<<16)
+# define TDA9887_AUTOMUTE            (1<<18)
+
 #endif
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index fc2b279cd..50f4c2c4d 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -74,7 +74,7 @@ extern int			ipv6_rcv_saddr_equal(const struct sock *sk,
 						      const struct sock *sk2);
 extern void			addrconf_join_solict(struct net_device *dev,
 					struct in6_addr *addr);
-extern void			addrconf_leave_solict(struct net_device *dev,
+extern void			addrconf_leave_solict(struct inet6_dev *idev,
 					struct in6_addr *addr);
 
 /*
@@ -89,6 +89,7 @@ extern int inet6_mc_check(struct sock *sk, struct in6_addr *mc_addr,
 		struct in6_addr *src_addr);
 
 extern int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr);
+extern int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr);
 extern int ipv6_dev_mc_dec(struct net_device *dev, struct in6_addr *addr);
 extern void ipv6_mc_up(struct inet6_dev *idev);
 extern void ipv6_mc_down(struct inet6_dev *idev);
@@ -111,6 +112,7 @@ extern void ipv6_sock_ac_close(struct sock *sk);
 extern int inet6_ac_check(struct sock *sk, struct in6_addr *addr, int ifindex);
 
 extern int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr);
+extern int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr);
 extern int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr);
 extern int ipv6_chk_acast_addr(struct net_device *dev, struct in6_addr *addr);
 
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index 79314ff55..621c64fea 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -43,16 +43,14 @@ static inline struct sock *first_unix_socket(int *i)
 #define forall_unix_sockets(i, s) \
 	for (s = first_unix_socket(&(i)); s; s = next_unix_socket(&(i),(s)))
 
-struct unix_address
-{
+struct unix_address {
 	atomic_t	refcnt;
 	int		len;
 	unsigned	hash;
 	struct sockaddr_un name[0];
 };
 
-struct unix_skb_parms
-{
+struct unix_skb_parms {
 	struct ucred		creds;		/* Skb credentials	*/
 	struct scm_fp_list	*fp;		/* Passed files		*/
 };
@@ -74,6 +72,7 @@ struct unix_sock {
         struct dentry		*dentry;
         struct vfsmount		*mnt;
         struct semaphore        readsem;
+        struct sock		*peer;
         struct sock		*other;
         struct sock		*gc_tree;
         atomic_t                inflight;
diff --git a/include/net/dn_neigh.h b/include/net/dn_neigh.h
index b0c2802a5..4b1eb038d 100644
--- a/include/net/dn_neigh.h
+++ b/include/net/dn_neigh.h
@@ -18,7 +18,6 @@ struct dn_neigh {
 
 extern void dn_neigh_init(void);
 extern void dn_neigh_cleanup(void);
-extern struct neighbour *dn_neigh_lookup(struct neigh_table *tbl, const void *ptr);
 extern int dn_neigh_router_hello(struct sk_buff *skb);
 extern int dn_neigh_endnode_hello(struct sk_buff *skb);
 extern void dn_neigh_pointopoint_hello(struct sk_buff *skb);
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index 48280b138..76ce5f8b6 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -51,6 +51,7 @@ struct inet6_ifaddr
 	struct timer_list	timer;
 
 	struct inet6_dev	*idev;
+	struct rt6_info		*rt;
 
 	struct inet6_ifaddr	*lst_next;      /* next addr in addr_lst */
 	struct inet6_ifaddr	*if_next;       /* next addr in inet6_dev */
@@ -133,6 +134,7 @@ struct ifacaddr6
 {
 	struct in6_addr		aca_addr;
 	struct inet6_dev	*aca_idev;
+	struct rt6_info		*aca_rt;
 	struct ifacaddr6	*aca_next;
 	int			aca_users;
 	atomic_t		aca_refcnt;
diff --git a/include/net/inet_ecn.h b/include/net/inet_ecn.h
index 4b9c75562..f87845e2e 100644
--- a/include/net/inet_ecn.h
+++ b/include/net/inet_ecn.h
@@ -2,6 +2,7 @@
 #define _INET_ECN_H_
 
 #include <linux/ip.h>
+#include <net/dsfield.h>
 
 enum {
 	INET_ECN_NOT_ECT = 0,
@@ -16,9 +17,9 @@ static inline int INET_ECN_is_ce(__u8 dsfield)
 	return (dsfield & INET_ECN_MASK) == INET_ECN_CE;
 }
 
-static inline int INET_ECN_is_not_ce(__u8 dsfield)
+static inline int INET_ECN_is_not_ect(__u8 dsfield)
 {
-	return (dsfield & INET_ECN_MASK) == INET_ECN_ECT_0;
+	return (dsfield & INET_ECN_MASK) == INET_ECN_NOT_ECT;
 }
 
 static inline int INET_ECN_is_capable(__u8 dsfield)
@@ -29,8 +30,8 @@ static inline int INET_ECN_is_capable(__u8 dsfield)
 static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner)
 {
 	outer &= ~INET_ECN_MASK;
-	if (INET_ECN_is_capable(inner))
-		outer |= (inner & INET_ECN_MASK);
+	outer |= !INET_ECN_is_ce(inner) ? (inner & INET_ECN_MASK) :
+					  INET_ECN_ECT_0;
 	return outer;
 }
 
@@ -50,7 +51,25 @@ static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner)
 static inline void IP_ECN_set_ce(struct iphdr *iph)
 {
 	u32 check = iph->check;
-	check += __constant_htons(0xFFFE);
+	u32 ecn = (iph->tos + 1) & INET_ECN_MASK;
+
+	/*
+	 * After the last operation we have (in binary):
+	 * INET_ECN_NOT_ECT => 01
+	 * INET_ECN_ECT_1   => 10
+	 * INET_ECN_ECT_0   => 11
+	 * INET_ECN_CE      => 00
+	 */
+	if (!(ecn & 2))
+		return;
+
+	/*
+	 * The following gives us:
+	 * INET_ECN_ECT_1 => check += htons(0xFFFD)
+	 * INET_ECN_ECT_0 => check += htons(0xFFFE)
+	 */
+	check += htons(0xFFFB) + htons(ecn);
+
 	iph->check = check + (check>=0xFFFF);
 	iph->tos |= INET_ECN_CE;
 }
@@ -60,10 +79,18 @@ static inline void IP_ECN_clear(struct iphdr *iph)
 	iph->tos &= ~INET_ECN_MASK;
 }
 
+static inline void ipv4_copy_dscp(struct iphdr *outer, struct iphdr *inner)
+{
+	u32 dscp = ipv4_get_dsfield(outer) & ~INET_ECN_MASK;
+	ipv4_change_dsfield(inner, INET_ECN_MASK, dscp);
+}
+
 struct ipv6hdr;
 
 static inline void IP6_ECN_set_ce(struct ipv6hdr *iph)
 {
+	if (INET_ECN_is_not_ect(ipv6_get_dsfield(iph)))
+		return;
 	*(u32*)iph |= htonl(INET_ECN_CE << 20);
 }
 
@@ -72,6 +99,10 @@ static inline void IP6_ECN_clear(struct ipv6hdr *iph)
 	*(u32*)iph &= ~htonl(INET_ECN_MASK << 20);
 }
 
-#define ip6_get_dsfield(iph) ((ntohs(*(u16*)(iph)) >> 4) & 0xFF)
+static inline void ipv6_copy_dscp(struct ipv6hdr *outer, struct ipv6hdr *inner)
+{
+	u32 dscp = ipv6_get_dsfield(outer) & ~INET_ECN_MASK;
+	ipv6_change_dsfield(inner, INET_ECN_MASK, dscp);
+}
 
 #endif
diff --git a/include/net/ip.h b/include/net/ip.h
index bacccde1c..0f633ff0b 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -255,6 +255,7 @@ extern int	ip_call_ra_chain(struct sk_buff *skb);
  */
  
 struct sk_buff *ip_defrag(struct sk_buff *skb);
+extern void ipfrag_flush(void);
 extern int ip_frag_nqueues;
 extern atomic_t ip_frag_mem;
 
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 14d41c4ba..319904518 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -20,6 +20,7 @@
 #include <net/dst.h>
 #include <net/flow.h>
 #include <linux/rtnetlink.h>
+#include <linux/spinlock.h>
 
 struct rt6_info;
 
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 75d503dc1..d859c4160 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -11,8 +11,10 @@
 
 #include <net/flow.h>
 #include <net/ip6_fib.h>
+#include <net/sock.h>
 #include <linux/tcp.h>
 #include <linux/ip.h>
+#include <linux/ipv6.h>
 
 struct pol_chain {
 	int			type;
@@ -40,6 +42,9 @@ extern int			ipv6_route_ioctl(unsigned int cmd, void __user *arg);
 extern int			ip6_route_add(struct in6_rtmsg *rtmsg,
 					      struct nlmsghdr *,
 					      void *rtattr);
+extern int			ip6_ins_rt(struct rt6_info *,
+					   struct nlmsghdr *,
+					   void *rtattr);
 extern int			ip6_del_rt(struct rt6_info *,
 					   struct nlmsghdr *,
 					   void *rtattr);
@@ -69,6 +74,10 @@ extern struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
 extern int ndisc_dst_gc(int *more);
 extern void fib6_force_start_gc(void);
 
+extern struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
+					   const struct in6_addr *addr,
+					   int anycast);
+
 /*
  *	support functions for ND
  *
@@ -80,9 +89,12 @@ extern struct rt6_info *	rt6_add_dflt_router(struct in6_addr *gwaddr,
 
 extern void			rt6_purge_dflt_routers(int lst_resort);
 
+extern void			rt6_reset_dflt_pointer(struct rt6_info *rt);
+
 extern void			rt6_redirect(struct in6_addr *dest,
 					     struct in6_addr *saddr,
 					     struct neighbour *neigh,
+					     u8 *lladdr,
 					     int on_link);
 
 extern void			rt6_pmtu_discovery(struct in6_addr *daddr,
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index f14edafea..48a6ea4c2 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -23,8 +23,7 @@
 /* WARNING: The ordering of these elements must match ordering
  *          of RTA_* rtnetlink attribute numbers.
  */
-struct kern_rta
-{
+struct kern_rta {
 	void		*rta_dst;
 	void		*rta_src;
 	int		*rta_iif;
@@ -40,9 +39,12 @@ struct kern_rta
 	struct rta_session *rta_sess;
 };
 
-struct fib_nh
-{
-	struct net_device		*nh_dev;
+struct fib_info;
+
+struct fib_nh {
+	struct net_device	*nh_dev;
+	struct hlist_node	nh_hash;
+	struct fib_info		*nh_parent;
 	unsigned		nh_flags;
 	unsigned char		nh_scope;
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
@@ -60,10 +62,9 @@ struct fib_nh
  * This structure contains data shared by many of routes.
  */
 
-struct fib_info
-{
-	struct fib_info		*fib_next;
-	struct fib_info		*fib_prev;
+struct fib_info {
+	struct hlist_node	fib_hash;
+	struct hlist_node	fib_lhash;
 	int			fib_treeref;
 	atomic_t		fib_clntref;
 	int			fib_dead;
@@ -89,8 +90,7 @@ struct fib_info
 struct fib_rule;
 #endif
 
-struct fib_result
-{
+struct fib_result {
 	unsigned char	prefixlen;
 	unsigned char	nh_sel;
 	unsigned char	type;
@@ -119,8 +119,7 @@ struct fib_result
 #define FIB_RES_DEV(res)		(FIB_RES_NH(res).nh_dev)
 #define FIB_RES_OIF(res)		(FIB_RES_NH(res).nh_oif)
 
-struct fib_table
-{
+struct fib_table {
 	unsigned char	tb_id;
 	unsigned	tb_stamp;
 	int		(*tb_lookup)(struct fib_table *tb, const struct flowi *flp, struct fib_result *res);
@@ -211,22 +210,11 @@ extern int fib_validate_source(u32 src, u32 dst, u8 tos, int oif,
 extern void fib_select_multipath(const struct flowi *flp, struct fib_result *res);
 
 /* Exported by fib_semantics.c */
-extern int 		ip_fib_check_default(u32 gw, struct net_device *dev);
-extern void		fib_release_info(struct fib_info *);
-extern int		fib_semantic_match(int type, struct fib_info *,
-					   const struct flowi *, struct fib_result*);
-extern struct fib_info	*fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
-					 const struct nlmsghdr *, int *err);
-extern int fib_nh_match(struct rtmsg *r, struct nlmsghdr *, struct kern_rta *rta, struct fib_info *fi);
-extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
-			 u8 tb_id, u8 type, u8 scope, void *dst, int dst_len, u8 tos,
-			 struct fib_info *fi);
+extern int ip_fib_check_default(u32 gw, struct net_device *dev);
 extern int fib_sync_down(u32 local, struct net_device *dev, int force);
 extern int fib_sync_up(struct net_device *dev);
 extern int fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm,
 			       struct kern_rta *rta, struct rtentry *r);
-extern void fib_node_seq_show(struct seq_file *seq, int type, int dead,
-			      struct fib_info *fi, u32 prefix, u32 mask);
 extern u32  __fib_res_prefsrc(struct fib_result *res);
 
 /* Exported by fib_hash.c */
@@ -242,7 +230,6 @@ extern u32 fib_rules_map_destination(u32 daddr, struct fib_result *res);
 #ifdef CONFIG_NET_CLS_ROUTE
 extern u32 fib_rules_tclass(struct fib_result *res);
 #endif
-extern u32 fib_rules_policy(u32 saddr, struct fib_result *res, unsigned *flags);
 extern void fib_rules_init(void);
 #endif
 
diff --git a/include/net/ipcomp.h b/include/net/ipcomp.h
index e94a6488a..e651a57ec 100644
--- a/include/net/ipcomp.h
+++ b/include/net/ipcomp.h
@@ -5,8 +5,7 @@
 
 struct ipcomp_data {
 	u16 threshold;
-	u8 *scratch;
-	struct crypto_tfm *tfm;
+	struct crypto_tfm **tfms;
 };
 
 #endif
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 034cf3084..a3f44754a 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -16,7 +16,7 @@
 #define _NET_IPV6_H
 
 #include <linux/ipv6.h>
-#include <asm/hardirq.h>
+#include <linux/hardirq.h>
 #include <net/ndisc.h>
 #include <net/flow.h>
 #include <net/snmp.h>
diff --git a/include/net/llc_pdu.h b/include/net/llc_pdu.h
index 644f9edc2..cbbfc3734 100644
--- a/include/net/llc_pdu.h
+++ b/include/net/llc_pdu.h
@@ -253,9 +253,9 @@ static inline void llc_pdu_header_init(struct sk_buff *skb, u8 type,
 static inline void llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa)
 {
 	if (skb->protocol == ntohs(ETH_P_802_2))
-		memcpy(sa, ((struct ethhdr *)skb->mac.raw)->h_source, ETH_ALEN);
+		memcpy(sa, eth_hdr(skb)->h_source, ETH_ALEN);
 	else if (skb->protocol == ntohs(ETH_P_TR_802_2))
-		memcpy(sa, ((struct trh_hdr *)skb->mac.raw)->saddr, ETH_ALEN);
+		memcpy(sa, tr_hdr(skb)->saddr, ETH_ALEN);
 }
 
 /**
@@ -268,9 +268,9 @@ static inline void llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa)
 static inline void llc_pdu_decode_da(struct sk_buff *skb, u8 *da)
 {
 	if (skb->protocol == ntohs(ETH_P_802_2))
-		memcpy(da, ((struct ethhdr *)skb->mac.raw)->h_dest, ETH_ALEN);
+		memcpy(da, eth_hdr(skb)->h_dest, ETH_ALEN);
 	else if (skb->protocol == ntohs(ETH_P_TR_802_2))
-		memcpy(da, ((struct trh_hdr *)skb->mac.raw)->daddr, ETH_ALEN);
+		memcpy(da, tr_hdr(skb)->daddr, ETH_ALEN);
 }
 
 /**
@@ -347,7 +347,7 @@ static inline void llc_pdu_init_as_test_rsp(struct sk_buff *skb,
 		struct llc_pdu_un *ev_pdu = llc_pdu_un_hdr(ev_skb);
 		int dsize;
 
-		dsize = ntohs(((struct ethhdr *)ev_skb->mac.raw)->h_proto) - 3;
+		dsize = ntohs(eth_hdr(ev_skb)->h_proto) - 3;
 		memcpy(((u8 *)pdu) + 3, ((u8 *)ev_pdu) + 3, dsize);
 		skb_put(skb, dsize);
 	}
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 464203b2a..40073cf19 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -7,6 +7,11 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>
  *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru>
+ *
+ * 	Changes:
+ *
+ *	Harald Welte:		<laforge@gnumonks.org>
+ *		- Add neighbour cache statistics like rtstat
  */
 
 /* The following flags & states are exported to user space,
@@ -45,14 +50,19 @@
 
 #include <asm/atomic.h>
 #include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/rcupdate.h>
+#include <linux/seq_file.h>
 
 #include <linux/err.h>
 #include <linux/sysctl.h>
 
-#define NUD_IN_TIMER	(NUD_INCOMPLETE|NUD_DELAY|NUD_PROBE)
+#define NUD_IN_TIMER	(NUD_INCOMPLETE|NUD_REACHABLE|NUD_DELAY|NUD_PROBE)
 #define NUD_VALID	(NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE|NUD_PROBE|NUD_STALE|NUD_DELAY)
 #define NUD_CONNECTED	(NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE)
 
+struct neighbour;
+
 struct neigh_parms
 {
 	struct neigh_parms *next;
@@ -63,6 +73,10 @@ struct neigh_parms
 
 	void	*sysctl_table;
 
+	int dead;
+	atomic_t refcnt;
+	struct rcu_head rcu_head;
+
 	int	base_reachable_time;
 	int	retrans_time;
 	int	gc_staletime;
@@ -81,12 +95,25 @@ struct neigh_parms
 
 struct neigh_statistics
 {
-	unsigned long allocs;
-	unsigned long res_failed;
-	unsigned long rcv_probes_mcast;
-	unsigned long rcv_probes_ucast;
+	unsigned long allocs;		/* number of allocated neighs */
+	unsigned long destroys;		/* number of destroyed neighs */
+	unsigned long hash_grows;	/* number of hash resizes */
+
+	unsigned long res_failed;	/* nomber of failed resolutions */
+
+	unsigned long lookups;		/* number of lookups */
+	unsigned long hits;		/* number of hits (among lookups) */
+
+	unsigned long rcv_probes_mcast;	/* number of received mcast ipv6 */
+	unsigned long rcv_probes_ucast; /* number of received ucast ipv6 */
+
+	unsigned long periodic_gc_runs;	/* number of periodic GC runs */
+	unsigned long forced_gc_runs;	/* number of forced GC runs */
 };
 
+#define NEIGH_CACHE_STAT_INC(tbl, field)				\
+		(per_cpu_ptr((tbl)->stats, smp_processor_id())->field++)
+
 struct neighbour
 {
 	struct neighbour	*next;
@@ -131,9 +158,6 @@ struct pneigh_entry
 	u8			key[0];
 };
 
-#define NEIGH_HASHMASK		0x1F
-#define PNEIGH_HASHMASK		0xF
-
 /*
  *	neighbour table manipulation
  */
@@ -166,22 +190,38 @@ struct neigh_table
 	unsigned long		last_rand;
 	struct neigh_parms	*parms_list;
 	kmem_cache_t		*kmem_cachep;
-	struct neigh_statistics	stats;
-	struct neighbour	*hash_buckets[NEIGH_HASHMASK+1];
-	struct pneigh_entry	*phash_buckets[PNEIGH_HASHMASK+1];
+	struct neigh_statistics	*stats;
+	struct neighbour	**hash_buckets;
+	unsigned int		hash_mask;
+	__u32			hash_rnd;
+	unsigned int		hash_chain_gc;
+	struct pneigh_entry	**phash_buckets;
+#ifdef CONFIG_PROC_FS
+	struct proc_dir_entry	*pde;
+#endif
 };
 
+/* flags for neigh_update() */
+#define NEIGH_UPDATE_F_OVERRIDE			0x00000001
+#define NEIGH_UPDATE_F_WEAK_OVERRIDE		0x00000002
+#define NEIGH_UPDATE_F_OVERRIDE_ISROUTER	0x00000004
+#define NEIGH_UPDATE_F_ISROUTER			0x40000000
+#define NEIGH_UPDATE_F_ADMIN			0x80000000
+
 extern void			neigh_table_init(struct neigh_table *tbl);
 extern int			neigh_table_clear(struct neigh_table *tbl);
 extern struct neighbour *	neigh_lookup(struct neigh_table *tbl,
 					     const void *pkey,
 					     struct net_device *dev);
+extern struct neighbour *	neigh_lookup_nodev(struct neigh_table *tbl,
+						   const void *pkey);
 extern struct neighbour *	neigh_create(struct neigh_table *tbl,
 					     const void *pkey,
 					     struct net_device *dev);
 extern void			neigh_destroy(struct neighbour *neigh);
 extern int			__neigh_event_send(struct neighbour *neigh, struct sk_buff *skb);
-extern int			neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, int override, int arp);
+extern int			neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, 
+					     u32 flags);
 extern void			neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev);
 extern int			neigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
 extern int			neigh_resolve_output(struct sk_buff *skb);
@@ -193,6 +233,7 @@ extern struct neighbour 	*neigh_event_ns(struct neigh_table *tbl,
 
 extern struct neigh_parms	*neigh_parms_alloc(struct net_device *dev, struct neigh_table *tbl);
 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,
@@ -207,6 +248,24 @@ extern int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
 extern int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
 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_table *tbl;
+	void *(*neigh_sub_iter)(struct neigh_seq_state *state,
+				struct neighbour *n, loff_t *pos);
+	unsigned int bucket;
+	unsigned int flags;
+#define NEIGH_SEQ_NEIGH_ONLY	0x00000001
+#define NEIGH_SEQ_IS_PNEIGH	0x00000002
+#define NEIGH_SEQ_SKIP_NOARP	0x00000004
+};
+extern void *neigh_seq_start(struct seq_file *, loff_t *, struct neigh_table *, unsigned int);
+extern void *neigh_seq_next(struct seq_file *, void *, loff_t *);
+extern void neigh_seq_stop(struct seq_file *, void *);
+
 extern int			neigh_sysctl_register(struct net_device *dev, 
 						      struct neigh_parms *p,
 						      int p_id, int pdev_id,
@@ -214,6 +273,23 @@ extern int			neigh_sysctl_register(struct net_device *dev,
 						      proc_handler *proc_handler);
 extern void			neigh_sysctl_unregister(struct neigh_parms *p);
 
+static inline void __neigh_parms_put(struct neigh_parms *parms)
+{
+	atomic_dec(&parms->refcnt);
+}
+
+static inline void neigh_parms_put(struct neigh_parms *parms)
+{
+	if (atomic_dec_and_test(&parms->refcnt))
+		neigh_parms_destroy(parms);
+}
+
+static inline struct neigh_parms *neigh_parms_clone(struct neigh_parms *parms)
+{
+	atomic_inc(&parms->refcnt);
+	return parms;
+}
+
 /*
  *	Neighbour references
  */
diff --git a/include/net/pkt_act.h b/include/net/pkt_act.h
index 09b899d87..e7e7da355 100644
--- a/include/net/pkt_act.h
+++ b/include/net/pkt_act.h
@@ -212,9 +212,8 @@ tcf_hash_search(struct tc_action *a, u32 index)
 	if (p != NULL) {
 		a->priv = p;
 		return 1;
-	} else {
-		return 0;
 	}
+	return 0;
 }
 
 #ifdef CONFIG_NET_ACT_INIT
@@ -274,11 +273,11 @@ tcf_hash_create(struct tc_st *parm, struct rtattr *est, struct tc_action *a, int
 static inline struct tcf_st *
 tcf_hash_init(struct tc_st *parm, struct rtattr *est, struct tc_action *a, int size, int ovr, int bind)
 {
-	struct tcf_st *p;
-	p = tcf_hash_check (parm,a,ovr,bind);
-	if (NULL == p) {
-		return tcf_hash_create(parm, est, a, size, ovr, bind);
-	}
+	struct tcf_st *p = tcf_hash_check (parm,a,ovr,bind);
+
+	if (!p)
+		p = tcf_hash_create(parm, est, a, size, ovr, bind);
+	return p;
 }
 
 #endif
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
index bce3aaf91..dab127cc2 100644
--- a/include/net/pkt_sched.h
+++ b/include/net/pkt_sched.h
@@ -80,6 +80,7 @@ struct Qdisc
 	int			padded;
 	struct Qdisc_ops	*ops;
 	u32			handle;
+	u32			parent;
 	atomic_t		refcnt;
 	struct sk_buff_head	q;
 	struct net_device	*dev;
@@ -375,7 +376,7 @@ struct tc_action_ops
 extern int tcf_register_action(struct tc_action_ops *a);
 extern int tcf_unregister_action(struct tc_action_ops *a);
 extern void tcf_action_destroy(struct tc_action *a, int bind);
-extern int tcf_action_exec(struct sk_buff *skb, struct tc_action *a);
+extern int tcf_action_exec(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res);
 extern int tcf_action_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a,char *n, int ovr, int bind);
 extern int tcf_action_init_1(struct rtattr *rta, struct rtattr *est, struct tc_action *a,char *n, int ovr, int bind);
 extern int tcf_action_dump(struct sk_buff *skb, struct tc_action *a, int, int);
diff --git a/include/net/route.h b/include/net/route.h
index 7252ea43e..7831bd9a2 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -76,11 +76,6 @@ struct rtable
 	/* Miscellaneous cached information */
 	__u32			rt_spec_dst; /* RFC1122 specific destination */
 	struct inet_peer	*peer; /* long-living peer info */
-
-#ifdef CONFIG_IP_ROUTE_NAT
-	__u32			rt_src_map;
-	__u32			rt_dst_map;
-#endif
 };
 
 struct ip_rt_acct
@@ -233,7 +228,7 @@ static inline int ip_route_connect(struct rtable **rp, u32 dst,
 			return err;
 		if (fl.fl4_dst == IPI_LOOPBACK && !vx_check(0, VX_ADMIN))
 			fl.fl4_dst = nx_info->ipv4[0];
-	}	
+	}
 	if (!fl.fl4_dst || !fl.fl4_src) {
 		err = __ip_route_output_key(rp, &fl);
 		if (err)
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 17d0f9adc..053a0ac27 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -505,6 +505,7 @@ for (pos = chunk->subh.fwdtsn_hdr->skip;\
 /* External references. */
 
 extern struct proto sctp_prot;
+extern struct proto sctpv6_prot;
 extern struct proc_dir_entry *proc_net_sctp;
 void sctp_put_port(struct sock *sk);
 
diff --git a/include/net/sock.h b/include/net/sock.h
index fb4df58ec..62cb86257 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -146,7 +146,6 @@ struct sock_common {
   *	@sk_route_caps - route capabilities (e.g. %NETIF_F_TSO)
   *	@sk_lingertime - %SO_LINGER l_linger setting
   *	@sk_hashent - hash entry in several tables (e.g. tcp_ehash)
-  *	@sk_pair - socket pair (e.g. AF_UNIX/unix_peer)
   *	@sk_backlog - always used with the per-socket spinlock held
   *	@sk_callback_lock - used with the callbacks in the end of this struct
   *	@sk_error_queue - rarely used
@@ -227,7 +226,6 @@ struct sock {
 	int			sk_route_caps;
 	unsigned long	        sk_lingertime;
 	int			sk_hashent;
-	struct sock		*sk_pair;
 	/*
 	 * The backlog queue is special, it is always used with
 	 * the per-socket spinlock held and requires low latency
@@ -563,6 +561,9 @@ struct proto {
 	int			*sysctl_rmem;
 	int			max_header;
 
+	kmem_cache_t		*slab;
+	int			slab_obj_size;
+
 	char			name[32];
 
 	struct {
@@ -571,6 +572,14 @@ struct proto {
 	} stats[NR_CPUS];
 };
 
+extern int sk_alloc_slab(struct proto *prot, char *name);
+extern void sk_free_slab(struct proto *prot);
+
+static inline void sk_alloc_slab_error(struct proto *proto)
+{
+	printk(KERN_CRIT "%s: Can't create sock SLAB cache!\n", proto->name);
+}
+
 static __inline__ void sk_set_owner(struct sock *sk, struct module *owner)
 {
 	/*
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 75740eaa4..08c5cdbe7 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -153,9 +153,6 @@ extern struct tcp_hashinfo {
 #define tcp_lhash_wait	(tcp_hashinfo.__tcp_lhash_wait)
 #define tcp_portalloc_lock (tcp_hashinfo.__tcp_portalloc_lock)
 
-/* SLAB cache for TCP socks */
-extern kmem_cache_t *tcp_sk_cachep;
-
 extern kmem_cache_t *tcp_bucket_cachep;
 extern struct tcp_bind_bucket *tcp_bucket_create(struct tcp_bind_hashbucket *head,
 						 unsigned short snum);
@@ -615,8 +612,8 @@ extern int sysctl_tcp_nometrics_save;
 extern int sysctl_tcp_bic;
 extern int sysctl_tcp_bic_fast_convergence;
 extern int sysctl_tcp_bic_low_window;
-extern int sysctl_tcp_default_win_scale;
 extern int sysctl_tcp_moderate_rcvbuf;
+extern int sysctl_tcp_tso_win_divisor;
 
 extern atomic_t tcp_memory_allocated;
 extern atomic_t tcp_sockets_allocated;
@@ -952,6 +949,7 @@ extern int tcp_write_xmit(struct sock *, int nonagle);
 extern int tcp_retransmit_skb(struct sock *, struct sk_buff *);
 extern void tcp_xmit_retransmit_queue(struct sock *);
 extern void tcp_simple_retransmit(struct sock *);
+extern int tcp_trim_head(struct sock *, struct sk_buff *, u32);
 
 extern void tcp_send_probe0(struct sock *);
 extern void tcp_send_partial(struct sock *);
@@ -959,7 +957,6 @@ extern int  tcp_write_wakeup(struct sock *);
 extern void tcp_send_fin(struct sock *sk);
 extern void tcp_send_active_reset(struct sock *sk, int priority);
 extern int  tcp_send_synack(struct sock *);
-extern int  tcp_transmit_skb(struct sock *, struct sk_buff *);
 extern void tcp_push_one(struct sock *, unsigned mss_now);
 extern void tcp_send_ack(struct sock *sk);
 extern void tcp_send_delayed_ack(struct sock *sk);
@@ -970,7 +967,8 @@ extern void tcp_clear_xmit_timers(struct sock *);
 
 extern void tcp_delete_keepalive_timer (struct sock *);
 extern void tcp_reset_keepalive_timer (struct sock *, unsigned long);
-extern int tcp_sync_mss(struct sock *sk, u32 pmtu);
+extern unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu);
+extern unsigned int tcp_current_mss(struct sock *sk, int large);
 
 extern const char timer_bug_msg[];
 
@@ -1044,34 +1042,6 @@ static inline void tcp_reset_xmit_timer(struct sock *sk, int what, unsigned long
 	};
 }
 
-/* Compute the current effective MSS, taking SACKs and IP options,
- * and even PMTU discovery events into account.
- *
- * LARGESEND note: !urg_mode is overkill, only frames up to snd_up
- * cannot be large. However, taking into account rare use of URG, this
- * is not a big flaw.
- */
-
-static __inline__ unsigned int tcp_current_mss(struct sock *sk, int large)
-{
-	struct tcp_opt *tp = tcp_sk(sk);
-	struct dst_entry *dst = __sk_dst_get(sk);
-	int mss_now = large && (sk->sk_route_caps & NETIF_F_TSO) &&
-		      !tp->urg_mode ?
-		tp->mss_cache : tp->mss_cache_std;
-
-	if (dst) {
-		u32 mtu = dst_pmtu(dst);
-		if (mtu != tp->pmtu_cookie ||
-		    tp->ext2_header_len != dst->header_len)
-			mss_now = tcp_sync_mss(sk, mtu);
-	}
-	if (tp->eff_sacks)
-		mss_now -= (TCPOLEN_SACK_BASE_ALIGNED +
-			    (tp->eff_sacks * TCPOLEN_SACK_PERBLOCK));
-	return mss_now;
-}
-
 /* Initialize RCV_MSS value.
  * RCV_MSS is an our guess about MSS used by the peer.
  * We haven't any direct information about the MSS.
@@ -1192,6 +1162,75 @@ struct tcp_skb_cb {
 
 #include <net/tcp_ecn.h>
 
+/* Due to TSO, an SKB can be composed of multiple actual
+ * packets.  To keep these tracked properly, we use this.
+ */
+static inline int tcp_skb_pcount(struct sk_buff *skb)
+{
+	return skb_shinfo(skb)->tso_segs;
+}
+
+/* This is valid iff tcp_skb_pcount() > 1. */
+static inline int tcp_skb_mss(struct sk_buff *skb)
+{
+	return skb_shinfo(skb)->tso_size;
+}
+
+static inline void tcp_inc_pcount(tcp_pcount_t *count, struct sk_buff *skb)
+{
+	count->val += tcp_skb_pcount(skb);
+}
+
+static inline void tcp_inc_pcount_explicit(tcp_pcount_t *count, int amt)
+{
+	count->val += amt;
+}
+
+static inline void tcp_dec_pcount_explicit(tcp_pcount_t *count, int amt)
+{
+	count->val -= amt;
+}
+
+static inline void tcp_dec_pcount(tcp_pcount_t *count, struct sk_buff *skb)
+{
+	count->val -= tcp_skb_pcount(skb);
+}
+
+static inline void tcp_dec_pcount_approx(tcp_pcount_t *count,
+					 struct sk_buff *skb)
+{
+	if (count->val) {
+		count->val -= tcp_skb_pcount(skb);
+		if ((int)count->val < 0)
+			count->val = 0;
+	}
+}
+
+static inline __u32 tcp_get_pcount(tcp_pcount_t *count)
+{
+	return count->val;
+}
+
+static inline void tcp_set_pcount(tcp_pcount_t *count, __u32 val)
+{
+	count->val = val;
+}
+
+static inline void tcp_packets_out_inc(struct sock *sk, struct tcp_opt *tp,
+				       struct sk_buff *skb)
+{
+	int orig = tcp_get_pcount(&tp->packets_out);
+
+	tcp_inc_pcount(&tp->packets_out, skb);
+	if (!orig)
+		tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+}
+
+static inline void tcp_packets_out_dec(struct tcp_opt *tp, struct sk_buff *skb)
+{
+	tcp_dec_pcount(&tp->packets_out, skb);
+}
+
 /* This determines how many packets are "in the network" to the best
  * of our knowledge.  In many cases it is conservative, but where
  * detailed information is available from the receiver (via SACK
@@ -1208,9 +1247,18 @@ struct tcp_skb_cb {
  */
 static __inline__ unsigned int tcp_packets_in_flight(struct tcp_opt *tp)
 {
-	return tp->packets_out - tp->left_out + tp->retrans_out;
+	return (tcp_get_pcount(&tp->packets_out) -
+		tcp_get_pcount(&tp->left_out) +
+		tcp_get_pcount(&tp->retrans_out));
 }
 
+/*
+ * Which congestion algorithim is in use on the connection.
+ */
+#define tcp_is_vegas(__tp)	((__tp)->adv_cong == TCP_VEGAS)
+#define tcp_is_westwood(__tp)	((__tp)->adv_cong == TCP_WESTWOOD)
+#define tcp_is_bic(__tp)	((__tp)->adv_cong == TCP_BIC)
+
 /* Recalculate snd_ssthresh, we want to set it to:
  *
  * Reno:
@@ -1223,7 +1271,7 @@ static __inline__ unsigned int tcp_packets_in_flight(struct tcp_opt *tp)
  */
 static inline __u32 tcp_recalc_ssthresh(struct tcp_opt *tp)
 {
-	if (sysctl_tcp_bic) {
+	if (tcp_is_bic(tp)) {
 		if (sysctl_tcp_bic_fast_convergence &&
 		    tp->snd_cwnd < tp->bictcp.last_max_cwnd)
 			tp->bictcp.last_max_cwnd
@@ -1242,11 +1290,6 @@ static inline __u32 tcp_recalc_ssthresh(struct tcp_opt *tp)
 
 /* Stop taking Vegas samples for now. */
 #define tcp_vegas_disable(__tp)	((__tp)->vegas.doing_vegas_now = 0)
-
-/* Is this TCP connection using Vegas (regardless of whether it is taking
- * Vegas measurements at the current time)?
- */
-#define tcp_is_vegas(__tp)	((__tp)->vegas.do_vegas)
     
 static inline void tcp_vegas_enable(struct tcp_opt *tp)
 {
@@ -1280,7 +1323,7 @@ static inline void tcp_vegas_enable(struct tcp_opt *tp)
 /* Should we be taking Vegas samples right now? */
 #define tcp_vegas_enabled(__tp)	((__tp)->vegas.doing_vegas_now)
 
-extern void tcp_vegas_init(struct tcp_opt *tp);
+extern void tcp_ca_init(struct tcp_opt *tp);
 
 static inline void tcp_set_ca_state(struct tcp_opt *tp, u8 ca_state)
 {
@@ -1309,9 +1352,15 @@ static inline __u32 tcp_current_ssthresh(struct tcp_opt *tp)
 
 static inline void tcp_sync_left_out(struct tcp_opt *tp)
 {
-	if (tp->sack_ok && tp->sacked_out >= tp->packets_out - tp->lost_out)
-		tp->sacked_out = tp->packets_out - tp->lost_out;
-	tp->left_out = tp->sacked_out + tp->lost_out;
+	if (tp->sack_ok &&
+	    (tcp_get_pcount(&tp->sacked_out) >=
+	     tcp_get_pcount(&tp->packets_out) - tcp_get_pcount(&tp->lost_out)))
+		tcp_set_pcount(&tp->sacked_out,
+			       (tcp_get_pcount(&tp->packets_out) -
+				tcp_get_pcount(&tp->lost_out)));
+	tcp_set_pcount(&tp->left_out,
+		       (tcp_get_pcount(&tp->sacked_out) +
+			tcp_get_pcount(&tp->lost_out)));
 }
 
 extern void tcp_cwnd_application_limited(struct sock *sk);
@@ -1320,14 +1369,16 @@ extern void tcp_cwnd_application_limited(struct sock *sk);
 
 static inline void tcp_cwnd_validate(struct sock *sk, struct tcp_opt *tp)
 {
-	if (tp->packets_out >= tp->snd_cwnd) {
+	__u32 packets_out = tcp_get_pcount(&tp->packets_out);
+
+	if (packets_out >= tp->snd_cwnd) {
 		/* Network is feed fully. */
 		tp->snd_cwnd_used = 0;
 		tp->snd_cwnd_stamp = tcp_time_stamp;
 	} else {
 		/* Network starves. */
-		if (tp->packets_out > tp->snd_cwnd_used)
-			tp->snd_cwnd_used = tp->packets_out;
+		if (tcp_get_pcount(&tp->packets_out) > tp->snd_cwnd_used)
+			tp->snd_cwnd_used = tcp_get_pcount(&tp->packets_out);
 
 		if ((s32)(tcp_time_stamp - tp->snd_cwnd_stamp) >= tp->rto)
 			tcp_cwnd_application_limited(sk);
@@ -1393,16 +1444,25 @@ tcp_nagle_check(struct tcp_opt *tp, struct sk_buff *skb, unsigned mss_now, int n
 		!(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) &&
 		((nonagle&TCP_NAGLE_CORK) ||
 		 (!nonagle &&
-		  tp->packets_out &&
+		  tcp_get_pcount(&tp->packets_out) &&
 		  tcp_minshall_check(tp))));
 }
 
+extern void tcp_set_skb_tso_segs(struct sk_buff *, unsigned int);
+
 /* This checks if the data bearing packet SKB (usually sk->sk_send_head)
  * should be put on the wire right now.
  */
 static __inline__ int tcp_snd_test(struct tcp_opt *tp, struct sk_buff *skb,
 				   unsigned cur_mss, int nonagle)
 {
+	int pkts = tcp_skb_pcount(skb);
+
+	if (!pkts) {
+		tcp_set_skb_tso_segs(skb, tp->mss_cache_std);
+		pkts = tcp_skb_pcount(skb);
+	}
+
 	/*	RFC 1122 - section 4.2.3.4
 	 *
 	 *	We must queue if
@@ -1429,14 +1489,14 @@ static __inline__ int tcp_snd_test(struct tcp_opt *tp, struct sk_buff *skb,
 	 */
 	return (((nonagle&TCP_NAGLE_PUSH) || tp->urg_mode
 		 || !tcp_nagle_check(tp, skb, cur_mss, nonagle)) &&
-		((tcp_packets_in_flight(tp) < tp->snd_cwnd) ||
+		(((tcp_packets_in_flight(tp) + (pkts-1)) < tp->snd_cwnd) ||
 		 (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)) &&
 		!after(TCP_SKB_CB(skb)->end_seq, tp->snd_una + tp->snd_wnd));
 }
 
 static __inline__ void tcp_check_probe_timer(struct sock *sk, struct tcp_opt *tp)
 {
-	if (!tp->packets_out && !tp->pending)
+	if (!tcp_get_pcount(&tp->packets_out) && !tp->pending)
 		tcp_reset_xmit_timer(sk, TCP_TIME_PROBE0, tp->rto);
 }
 
@@ -1694,68 +1754,10 @@ static inline void tcp_syn_build_options(__u32 *ptr, int mss, int ts, int sack,
 		*ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_WINDOW << 16) | (TCPOLEN_WINDOW << 8) | (wscale));
 }
 
-/* Determine a window scaling and initial window to offer.
- * Based on the assumption that the given amount of space
- * will be offered. Store the results in the tp structure.
- * NOTE: for smooth operation initial space offering should
- * be a multiple of mss if possible. We assume here that mss >= 1.
- * This MUST be enforced by all callers.
- */
-static inline void tcp_select_initial_window(int __space, __u32 mss,
-	__u32 *rcv_wnd,
-	__u32 *window_clamp,
-	int wscale_ok,
-	__u8 *rcv_wscale)
-{
-	unsigned int space = (__space < 0 ? 0 : __space);
-
-	/* If no clamp set the clamp to the max possible scaled window */
-	if (*window_clamp == 0)
-		(*window_clamp) = (65535 << 14);
-	space = min(*window_clamp, space);
-
-	/* Quantize space offering to a multiple of mss if possible. */
-	if (space > mss)
-		space = (space / mss) * mss;
-
-	/* NOTE: offering an initial window larger than 32767
-	 * will break some buggy TCP stacks. We try to be nice.
-	 * If we are not window scaling, then this truncates
-	 * our initial window offering to 32k. There should also
-	 * be a sysctl option to stop being nice.
-	 */
-	(*rcv_wnd) = min(space, MAX_TCP_WINDOW);
-	(*rcv_wscale) = 0;
-	if (wscale_ok) {
-		/* See RFC1323 for an explanation of the limit to 14 */
-		while (space > 65535 && (*rcv_wscale) < 14) {
-			space >>= 1;
-			(*rcv_wscale)++;
-		}
-		if (*rcv_wscale && sysctl_tcp_app_win && space>=mss &&
-		    space - max((space>>sysctl_tcp_app_win), mss>>*rcv_wscale) < 65536/2)
-			(*rcv_wscale)--;
-
-		*rcv_wscale = max((__u8)sysctl_tcp_default_win_scale,
-				  *rcv_wscale);
-	}
-
-	/* Set initial window to value enough for senders,
-	 * following RFC1414. Senders, not following this RFC,
-	 * will be satisfied with 2.
-	 */
-	if (mss > (1<<*rcv_wscale)) {
-		int init_cwnd = 4;
-		if (mss > 1460*3)
-			init_cwnd = 2;
-		else if (mss > 1460)
-			init_cwnd = 3;
-		if (*rcv_wnd > init_cwnd*mss)
-			*rcv_wnd = init_cwnd*mss;
-	}
-	/* Set the clamp no higher than max representable value */
-	(*window_clamp) = min(65535U << (*rcv_wscale), *window_clamp);
-}
+/* Determine a window scaling and initial window to offer. */
+extern void tcp_select_initial_window(int __space, __u32 mss,
+				      __u32 *rcv_wnd, __u32 *window_clamp,
+				      int wscale_ok, __u8 *rcv_wscale);
 
 static inline int tcp_win_from_space(int space)
 {
@@ -1765,13 +1767,13 @@ static inline int tcp_win_from_space(int space)
 }
 
 /* Note: caller must be prepared to deal with negative returns */ 
-static inline int tcp_space(struct sock *sk)
+static inline int tcp_space(const struct sock *sk)
 {
 	return tcp_win_from_space(sk->sk_rcvbuf -
 				  atomic_read(&sk->sk_rmem_alloc));
 } 
 
-static inline int tcp_full_space( struct sock *sk)
+static inline int tcp_full_space(const struct sock *sk)
 {
 	return tcp_win_from_space(sk->sk_rcvbuf); 
 }
@@ -2005,7 +2007,7 @@ extern void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo);
 
 static inline void tcp_westwood_update_rtt(struct tcp_opt *tp, __u32 rtt_seq)
 {
-        if (sysctl_tcp_westwood)
+        if (tcp_is_westwood(tp))
                 tp->westwood.rtt = rtt_seq;
 }
 
@@ -2014,33 +2016,33 @@ void __tcp_westwood_slow_bw(struct sock *, struct sk_buff *);
 
 static inline void tcp_westwood_fast_bw(struct sock *sk, struct sk_buff *skb)
 {
-        if (sysctl_tcp_westwood)
+        if (tcp_is_westwood(tcp_sk(sk)))
                 __tcp_westwood_fast_bw(sk, skb);
 }
 
 static inline void tcp_westwood_slow_bw(struct sock *sk, struct sk_buff *skb)
 {
-        if (sysctl_tcp_westwood)
+        if (tcp_is_westwood(tcp_sk(sk)))
                 __tcp_westwood_slow_bw(sk, skb);
 }
 
 static inline __u32 __tcp_westwood_bw_rttmin(const struct tcp_opt *tp)
 {
         return max((tp->westwood.bw_est) * (tp->westwood.rtt_min) /
-		   (__u32) (tp->mss_cache),
+		   (__u32) (tp->mss_cache_std),
 		   2U);
 }
 
 static inline __u32 tcp_westwood_bw_rttmin(const struct tcp_opt *tp)
 {
-	return sysctl_tcp_westwood ? __tcp_westwood_bw_rttmin(tp) : 0;
+	return tcp_is_westwood(tp) ? __tcp_westwood_bw_rttmin(tp) : 0;
 }
 
 static inline int tcp_westwood_ssthresh(struct tcp_opt *tp)
 {
 	__u32 ssthresh = 0;
 
-	if (sysctl_tcp_westwood) {
+	if (tcp_is_westwood(tp)) {
 		ssthresh = __tcp_westwood_bw_rttmin(tp);
 		if (ssthresh)
 			tp->snd_ssthresh = ssthresh;  
@@ -2053,7 +2055,7 @@ static inline int tcp_westwood_cwnd(struct tcp_opt *tp)
 {
 	__u32 cwnd = 0;
 
-	if (sysctl_tcp_westwood) {
+	if (tcp_is_westwood(tp)) {
 		cwnd = __tcp_westwood_bw_rttmin(tp);
 		if (cwnd)
 			tp->snd_cwnd = cwnd;
diff --git a/include/net/tcp_ecn.h b/include/net/tcp_ecn.h
index 061057572..38e0feddc 100644
--- a/include/net/tcp_ecn.h
+++ b/include/net/tcp_ecn.h
@@ -90,7 +90,7 @@ TCP_ECN_check_ce(struct tcp_opt *tp, struct sk_buff *skb)
 		/* Funny extension: if ECT is not set on a segment,
 		 * it is surely retransmit. It is not in ECN RFC,
 		 * but Linux follows this rule. */
-		else if (!INET_ECN_is_capable((TCP_SKB_CB(skb)->flags)))
+		else if (INET_ECN_is_not_ect((TCP_SKB_CB(skb)->flags)))
 			tcp_enter_quickack_mode(tp);
 	}
 }
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index aaf74999a..b5c9b1028 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -216,7 +216,7 @@ struct xfrm_type
 	void			(*destructor)(struct xfrm_state *);
 	int			(*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
 	int			(*post_input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
-	int			(*output)(struct sk_buff **pskb);
+	int			(*output)(struct sk_buff *pskb);
 	/* Estimate maximal size of result of transformation of a dgram */
 	u32			(*get_max_size)(struct xfrm_state *, int size);
 };
@@ -304,47 +304,6 @@ extern int xfrm_register_km(struct xfrm_mgr *km);
 extern int xfrm_unregister_km(struct xfrm_mgr *km);
 
 
-#define XFRM_FLOWCACHE_HASH_SIZE	1024
-
-static inline u32 __flow_hash4(struct flowi *fl)
-{
-	u32 hash = fl->fl4_src ^ fl->fl_ip_sport;
-
-	hash = ((hash & 0xF0F0F0F0) >> 4) | ((hash & 0x0F0F0F0F) << 4);
-
-	hash ^= fl->fl4_dst ^ fl->fl_ip_dport;
-	hash ^= (hash >> 10);
-	hash ^= (hash >> 20);
-	return hash & (XFRM_FLOWCACHE_HASH_SIZE-1);
-}
-
-static inline u32 __flow_hash6(struct flowi *fl)
-{
-	u32 hash = fl->fl6_src.s6_addr32[2] ^
-		   fl->fl6_src.s6_addr32[3] ^ 
-		   fl->fl_ip_sport;
-
-	hash = ((hash & 0xF0F0F0F0) >> 4) | ((hash & 0x0F0F0F0F) << 4);
-
-	hash ^= fl->fl6_dst.s6_addr32[2] ^
-		fl->fl6_dst.s6_addr32[3] ^ 
-		fl->fl_ip_dport;
-	hash ^= (hash >> 10);
-	hash ^= (hash >> 20);
-	return hash & (XFRM_FLOWCACHE_HASH_SIZE-1);
-}
-
-static inline u32 flow_hash(struct flowi *fl, unsigned short family)
-{
-	switch (family) {
-	case AF_INET:
-		return __flow_hash4(fl);
-	case AF_INET6:
-		return __flow_hash6(fl);
-	}
-	return 0;	/*XXX*/
-}
-
 extern struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2];
 
 static inline void xfrm_pol_hold(struct xfrm_policy *policy)
@@ -462,13 +421,53 @@ static __inline__ int addr_match(void *token1, void *token2, int prefixlen)
 	return 1;
 }
 
+static __inline__
+u16 xfrm_flowi_sport(struct flowi *fl)
+{
+	u16 port;
+	switch(fl->proto) {
+	case IPPROTO_TCP:
+	case IPPROTO_UDP:
+	case IPPROTO_SCTP:
+		port = fl->fl_ip_sport;
+		break;
+	case IPPROTO_ICMP:
+	case IPPROTO_ICMPV6:
+		port = htons(fl->fl_icmp_type);
+		break;
+	default:
+		port = 0;	/*XXX*/
+	}
+	return port;
+}
+
+static __inline__
+u16 xfrm_flowi_dport(struct flowi *fl)
+{
+	u16 port;
+	switch(fl->proto) {
+	case IPPROTO_TCP:
+	case IPPROTO_UDP:
+	case IPPROTO_SCTP:
+		port = fl->fl_ip_dport;
+		break;
+	case IPPROTO_ICMP:
+	case IPPROTO_ICMPV6:
+		port = htons(fl->fl_icmp_code);
+		break;
+	default:
+		port = 0;	/*XXX*/
+	}
+	return port;
+}
+
 static inline int
 __xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl)
 {
 	return  addr_match(&fl->fl4_dst, &sel->daddr, sel->prefixlen_d) &&
 		addr_match(&fl->fl4_src, &sel->saddr, sel->prefixlen_s) &&
-		!((fl->fl_ip_dport^sel->dport)&sel->dport_mask) &&
-		!((fl->fl_ip_sport^sel->sport)&sel->sport_mask) &&
+		!((xfrm_flowi_dport(fl) ^ sel->dport) & sel->dport_mask) &&
+		!((xfrm_flowi_sport(fl) ^ sel->sport) & sel->sport_mask) &&
 		(fl->proto == sel->proto || !sel->proto) &&
 		(fl->oif == sel->ifindex || !sel->ifindex);
 }
@@ -478,8 +477,8 @@ __xfrm6_selector_match(struct xfrm_selector *sel, struct flowi *fl)
 {
 	return  addr_match(&fl->fl6_dst, &sel->daddr, sel->prefixlen_d) &&
 		addr_match(&fl->fl6_src, &sel->saddr, sel->prefixlen_s) &&
-		!((fl->fl_ip_dport^sel->dport)&sel->dport_mask) &&
-		!((fl->fl_ip_sport^sel->sport)&sel->sport_mask) &&
+		!((xfrm_flowi_dport(fl) ^ sel->dport) & sel->dport_mask) &&
+		!((xfrm_flowi_sport(fl) ^ sel->sport) & sel->sport_mask) &&
 		(fl->proto == sel->proto || !sel->proto) &&
 		(fl->oif == sel->ifindex || !sel->ifindex);
 }
@@ -795,8 +794,6 @@ extern void xfrm4_state_init(void);
 extern void xfrm4_state_fini(void);
 extern void xfrm6_state_init(void);
 extern void xfrm6_state_fini(void);
-extern void xfrm6_tunnel_init(void);
-extern void xfrm6_tunnel_fini(void);
 
 extern int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), void *);
 extern struct xfrm_state *xfrm_state_alloc(void);
@@ -821,6 +818,7 @@ extern int xfrm4_rcv(struct sk_buff *skb);
 extern int xfrm4_output(struct sk_buff **pskb);
 extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
 extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
+extern int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi);
 extern int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp);
 extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler);
 extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler);
@@ -852,8 +850,6 @@ static inline int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsig
 #endif
 
 void xfrm_policy_init(void);
-void xfrm4_policy_init(void);
-void xfrm6_policy_init(void);
 struct xfrm_policy *xfrm_policy_alloc(int gfp);
 extern int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), void *);
 int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
@@ -900,4 +896,17 @@ typedef void (icv_update_fn_t)(struct crypto_tfm *, struct scatterlist *, unsign
 extern void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
 			 int offset, int len, icv_update_fn_t icv_update);
 
+static inline int xfrm_addr_cmp(xfrm_address_t *a, xfrm_address_t *b,
+				int family)
+{
+	switch (family) {
+	default:
+	case AF_INET:
+		return a->a4 - b->a4;
+	case AF_INET6:
+		return ipv6_addr_cmp((struct in6_addr *)a,
+				     (struct in6_addr *)b);
+	}
+}
+
 #endif	/* _NET_XFRM_H */
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
index 4df622f6d..7883d79b9 100644
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -103,7 +103,7 @@ typedef struct pccard_mem_map {
     u_char	map;
     u_char	flags;
     u_short	speed;
-    u_long	sys_start, sys_stop;
+    u_long	static_start;
     u_int	card_start;
     struct resource *res;
 } pccard_mem_map;
@@ -176,7 +176,7 @@ struct pcmcia_socket {
 	u_short				lock_count;
 	client_handle_t			clients;
 	pccard_mem_map			cis_mem;
-	u_char				*cis_virt;
+	void __iomem 			*cis_virt;
 	struct config_t			*config;
 	struct {
 		u_int			AssignedIRQ;
@@ -227,7 +227,7 @@ struct pcmcia_socket {
 	/* cardbus (32-bit) */
 #ifdef CONFIG_CARDBUS
 	struct resource *		cb_cis_res;
-	u_char				*cb_cis_virt;
+	void __iomem			*cb_cis_virt;
 #endif
 
 	/* socket device */
diff --git a/include/rxrpc/call.h b/include/rxrpc/call.h
index 2620d1921..f9b0a7cbd 100644
--- a/include/rxrpc/call.h
+++ b/include/rxrpc/call.h
@@ -67,8 +67,8 @@ struct rxrpc_call
 	wait_queue_head_t	waitq;		/* wait queue for events to happen */
 	struct list_head	link;		/* general internal list link */
 	struct list_head	call_link;	/* master call list link */
-	uint32_t		chan_ix;	/* connection channel index (net order) */
-	uint32_t		call_id;	/* call ID on connection (net order) */
+	__be32			chan_ix;	/* connection channel index  */
+	__be32			call_id;	/* call ID on connection  */
 	unsigned long		cjif;		/* jiffies at call creation */
 	unsigned long		flags;		/* control flags */
 #define RXRPC_CALL_ACKS_TIMO	0x00000001	/* ACKS timeout reached */
@@ -97,7 +97,7 @@ struct rxrpc_call
 	rxrpc_seq_t		ackr_win_bot;	/* bottom of ACK window */
 	rxrpc_seq_t		ackr_win_top;	/* top of ACK window */
 	rxrpc_seq_t		ackr_high_seq;	/* highest seqno yet received */
-	rxrpc_seq_t		ackr_prev_seq;	/* previous seqno received */
+	rxrpc_seq_net_t		ackr_prev_seq;	/* previous seqno received */
 	unsigned		ackr_pend_cnt;	/* number of pending ACKs */
 	struct timer_list	ackr_dfr_timo;	/* timeout on deferred ACK */
 	char			ackr_dfr_perm;	/* request for deferred ACKs permitted */
diff --git a/include/rxrpc/connection.h b/include/rxrpc/connection.h
index f22e71097..41e6781ad 100644
--- a/include/rxrpc/connection.h
+++ b/include/rxrpc/connection.h
@@ -45,18 +45,18 @@ struct rxrpc_connection
 	rxrpc_serial_t		serial_counter;	/* packet serial number counter */
 
 	/* the following should all be in net order */
-	uint32_t		in_epoch;	/* peer's epoch */
-	uint32_t		out_epoch;	/* my epoch */
-	uint32_t		conn_id;	/* connection ID, appropriately shifted */
-	uint16_t		service_id;	/* service ID */
+	__be32			in_epoch;	/* peer's epoch */
+	__be32			out_epoch;	/* my epoch */
+	__be32			conn_id;	/* connection ID, appropriately shifted */
+	__be16			service_id;	/* service ID */
 	uint8_t			security_ix;	/* security ID */
 	uint8_t			in_clientflag;	/* RXRPC_CLIENT_INITIATED if we are server */
 	uint8_t			out_clientflag;	/* RXRPC_CLIENT_INITIATED if we are client */
 };
 
 extern int rxrpc_create_connection(struct rxrpc_transport *trans,
-				   uint16_t port,
-				   uint32_t addr,
+				   __be16 port,
+				   __be32 addr,
 				   uint16_t service_id,
 				   void *security,
 				   struct rxrpc_connection **_conn);
diff --git a/include/rxrpc/packet.h b/include/rxrpc/packet.h
index 068813d65..f9224d363 100644
--- a/include/rxrpc/packet.h
+++ b/include/rxrpc/packet.h
@@ -27,19 +27,19 @@ extern size_t RXRPC_MAX_PACKET_SIZE;
  */
 struct rxrpc_header
 {
-	uint32_t	epoch;		/* client boot timestamp */
+	__be32		epoch;		/* client boot timestamp */
 
-	uint32_t	cid;		/* connection and channel ID */
+	__be32		cid;		/* connection and channel ID */
 #define RXRPC_MAXCALLS		4			/* max active calls per conn */
 #define RXRPC_CHANNELMASK	(RXRPC_MAXCALLS-1)	/* mask for channel ID */
 #define RXRPC_CIDMASK		(~RXRPC_CHANNELMASK)	/* mask for connection ID */
 #define RXRPC_CIDSHIFT		2			/* shift for connection ID */
 
-	uint32_t	callNumber;	/* call ID (0 for connection-level packets) */
+	__be32		callNumber;	/* call ID (0 for connection-level packets) */
 #define RXRPC_PROCESS_MAXCALLS	(1<<2)	/* maximum number of active calls per conn (power of 2) */
 
-	uint32_t	seq;		/* sequence number of pkt in call stream */
-	uint32_t	serial;		/* serial number of pkt sent to network */
+	__be32		seq;		/* sequence number of pkt in call stream */
+	__be32		serial;		/* serial number of pkt sent to network */
 
 	uint8_t		type;		/* packet type */
 #define RXRPC_PACKET_TYPE_DATA		1	/* data */
@@ -62,8 +62,8 @@ struct rxrpc_header
 
 	uint8_t		userStatus;	/* app-layer defined status */
 	uint8_t		securityIndex;	/* security protocol ID */
-	uint16_t	_rsvd;		/* reserved (used by kerberos security as cksum) */
-	uint16_t	serviceId;	/* service ID */
+	__be16		_rsvd;		/* reserved (used by kerberos security as cksum) */
+	__be16		serviceId;	/* service ID */
 
 } __attribute__((packed));
 
@@ -85,7 +85,7 @@ struct rxrpc_jumbo_header
 {
 	uint8_t		flags;		/* packet flags (as per rxrpc_header) */
 	uint8_t		pad;
-	uint16_t	_rsvd;		/* reserved (used by kerberos security as cksum) */
+	__be16		_rsvd;		/* reserved (used by kerberos security as cksum) */
 };
 
 #define RXRPC_JUMBO_DATALEN	1412	/* non-terminal jumbo packet data length */
@@ -97,12 +97,12 @@ struct rxrpc_jumbo_header
  */
 struct rxrpc_ackpacket
 {
-	uint16_t	bufferSpace;	/* number of packet buffers available */
-	uint16_t	maxSkew;	/* diff between serno being ACK'd and highest serial no
+	__be16		bufferSpace;	/* number of packet buffers available */
+	__be16		maxSkew;	/* diff between serno being ACK'd and highest serial no
 					 * received */
-	uint32_t	firstPacket;	/* sequence no of first ACK'd packet in attached list */
-	uint32_t	previousPacket;	/* sequence no of previous packet received */
-	uint32_t	serial;		/* serial no of packet that prompted this ACK */
+	__be32		firstPacket;	/* sequence no of first ACK'd packet in attached list */
+	__be32		previousPacket;	/* sequence no of previous packet received */
+	__be32		serial;		/* serial no of packet that prompted this ACK */
 
 	uint8_t		reason;		/* reason for ACK */
 #define RXRPC_ACK_REQUESTED		1	/* ACK was requested on packet */
diff --git a/include/rxrpc/peer.h b/include/rxrpc/peer.h
index da4832fcc..8b8fe97cb 100644
--- a/include/rxrpc/peer.h
+++ b/include/rxrpc/peer.h
@@ -67,7 +67,7 @@ struct rxrpc_peer
 
 
 extern int rxrpc_peer_lookup(struct rxrpc_transport *trans,
-			     u32 addr,
+			     __be32 addr,
 			     struct rxrpc_peer **_peer);
 
 static inline void rxrpc_get_peer(struct rxrpc_peer *peer)
diff --git a/include/rxrpc/rxrpc.h b/include/rxrpc/rxrpc.h
index df6595c32..8d9874cef 100644
--- a/include/rxrpc/rxrpc.h
+++ b/include/rxrpc/rxrpc.h
@@ -14,12 +14,19 @@
 
 #ifdef __KERNEL__
 
-extern uint32_t rxrpc_epoch;
+extern __be32 rxrpc_epoch;
 
+#ifdef CONFIG_SYSCTL
 extern int rxrpc_ktrace;
 extern int rxrpc_kdebug;
 extern int rxrpc_kproto;
 extern int rxrpc_knet;
+#else
+#define rxrpc_ktrace	0
+#define rxrpc_kdebug	0
+#define rxrpc_kproto	0
+#define rxrpc_knet	0
+#endif
 
 extern int rxrpc_sysctl_init(void);
 extern void rxrpc_sysctl_cleanup(void);
diff --git a/include/rxrpc/transport.h b/include/rxrpc/transport.h
index 6aa886911..486371459 100644
--- a/include/rxrpc/transport.h
+++ b/include/rxrpc/transport.h
@@ -78,8 +78,6 @@ struct rxrpc_transport
 	volatile char		error_rcvd;	/* T if received ICMP error outstanding */
 };
 
-extern struct list_head rxrpc_transports;
-
 extern int rxrpc_create_transport(unsigned short port,
 				  struct rxrpc_transport **_trans);
 
diff --git a/include/rxrpc/types.h b/include/rxrpc/types.h
index 2f37ad8bb..327a5fc47 100644
--- a/include/rxrpc/types.h
+++ b/include/rxrpc/types.h
@@ -21,6 +21,8 @@
 
 typedef uint32_t	rxrpc_seq_t;	/* Rx message sequence number */
 typedef uint32_t	rxrpc_serial_t;	/* Rx message serial number */
+typedef __be32	rxrpc_seq_net_t; /* on-the-wire Rx message sequence number */
+typedef __be32	rxrpc_serial_net_t; /* on-the-wire Rx message serial number */
 
 struct rxrpc_call;
 struct rxrpc_connection;
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 1c6d29384..916511a59 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -108,6 +108,7 @@ extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
 #define WRITE_LONG_2          0xea
 #define READ_16               0x88
 #define WRITE_16              0x8a
+#define VERIFY_16	      0x8f
 #define SERVICE_ACTION_IN     0x9e
 /* values for service action in */
 #define	SAI_READ_CAPACITY_16  0x10
@@ -353,14 +354,19 @@ struct scsi_lun {
 		     ((lun) & 0x07))
 
 /*
- *  SCSI command sets
+ *  struct scsi_device::scsi_level values. For SCSI devices other than those
+ *  prior to SCSI-2 (i.e. over 12 years old) this value is (resp[2] + 1)
+ *  where "resp" is a byte array of the response to an INQUIRY. The scsi_level
+ *  variable is visible to the user via sysfs.
  */
 
 #define SCSI_UNKNOWN    0
 #define SCSI_1          1
 #define SCSI_1_CCS      2
 #define SCSI_2          3
-#define SCSI_3          4
+#define SCSI_3          4        /* SPC */
+#define SCSI_SPC_2      5
+#define SCSI_SPC_3      6
 
 /*
  * INQ PERIPHERAL QUALIFIERS
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 75a1909c2..e76510c34 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -129,8 +129,10 @@ struct scsi_device {
 #define transport_class_to_sdev(class_dev) \
 	container_of(class_dev, struct scsi_device, transport_classdev)
 
-extern struct scsi_device *scsi_add_device(struct Scsi_Host *,
-		uint, uint, uint);
+extern struct scsi_device *__scsi_add_device(struct Scsi_Host *,
+		uint, uint, uint, void *hostdata);
+#define scsi_add_device(host, channel, target, lun) \
+	__scsi_add_device(host, channel, target, lun, NULL)
 extern void scsi_remove_device(struct scsi_device *);
 extern int scsi_device_cancel(struct scsi_device *, int);
 
@@ -183,13 +185,47 @@ extern int scsi_set_medium_removal(struct scsi_device *, char);
 extern int scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
 			   unsigned char *buffer, int len, int timeout,
 			   int retries, struct scsi_mode_data *data);
+extern int scsi_test_unit_ready(struct scsi_device *sdev, int timeout,
+				int retries);
 extern int scsi_device_set_state(struct scsi_device *sdev,
 				 enum scsi_device_state state);
 extern int scsi_device_quiesce(struct scsi_device *sdev);
 extern void scsi_device_resume(struct scsi_device *sdev);
 extern const char *scsi_device_state_name(enum scsi_device_state);
-static int inline scsi_device_online(struct scsi_device *sdev)
+static inline int scsi_device_online(struct scsi_device *sdev)
 {
 	return sdev->sdev_state != SDEV_OFFLINE;
 }
+
+/* accessor functions for the SCSI parameters */
+static inline int scsi_device_sync(struct scsi_device *sdev)
+{
+	return sdev->sdtr;
+}
+static inline int scsi_device_wide(struct scsi_device *sdev)
+{
+	return sdev->wdtr;
+}
+static inline int scsi_device_dt(struct scsi_device *sdev)
+{
+	return sdev->ppr;
+}
+static inline int scsi_device_dt_only(struct scsi_device *sdev)
+{
+	if (sdev->inquiry_len < 57)
+		return 0;
+	return (sdev->inquiry[56] & 0x0c) == 0x04;
+}
+static inline int scsi_device_ius(struct scsi_device *sdev)
+{
+	if (sdev->inquiry_len < 57)
+		return 0;
+	return sdev->inquiry[56] & 0x01;
+}
+static inline int scsi_device_qas(struct scsi_device *sdev)
+{
+	if (sdev->inquiry_len < 57)
+		return 0;
+	return sdev->inquiry[56] & 0x02;
+}
 #endif /* _SCSI_SCSI_DEVICE_H */
diff --git a/include/scsi/scsi_driver.h b/include/scsi/scsi_driver.h
index 3465f31a2..98c2e33f6 100644
--- a/include/scsi/scsi_driver.h
+++ b/include/scsi/scsi_driver.h
@@ -13,6 +13,7 @@ struct scsi_driver {
 
 	int (*init_command)(struct scsi_cmnd *);
 	void (*rescan)(struct device *);
+	int (*issue_flush)(struct device *, sector_t *);
 };
 #define to_scsi_driver(drv) \
 	container_of((drv), struct scsi_driver, gendrv)
diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
index 887601dc6..ae261ea5f 100644
--- a/include/scsi/scsi_eh.h
+++ b/include/scsi/scsi_eh.h
@@ -11,7 +11,6 @@ extern int scsi_delete_timer(struct scsi_cmnd *);
 extern void scsi_report_bus_reset(struct Scsi_Host *, int);
 extern void scsi_report_device_reset(struct Scsi_Host *, int, int);
 extern int scsi_block_when_processing_errors(struct scsi_device *);
-extern void scsi_sleep(int);
 
 /*
  * Reset request from external source
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
index 3629059ad..bcdda71ac 100644
--- a/include/sound/ac97_codec.h
+++ b/include/sound/ac97_codec.h
@@ -364,11 +364,21 @@
 #define AC97_RATES_MIC_ADC	4
 #define AC97_RATES_SPDIF	5
 
+/* shared controllers */
+enum {
+	AC97_SHARED_TYPE_NONE,
+	AC97_SHARED_TYPE_ICH,
+	AC97_SHARED_TYPE_ATIIXP,
+	AC97_SHARED_TYPES
+};
+
 /*
  *
  */
 
 typedef struct _snd_ac97_bus ac97_bus_t;
+typedef struct _snd_ac97_bus_ops ac97_bus_ops_t;
+typedef struct _snd_ac97_template ac97_template_t;
 typedef struct _snd_ac97 ac97_t;
 
 enum ac97_pcm_cfg {
@@ -405,29 +415,45 @@ struct snd_ac97_build_ops {
 	int (*build_post_spdif) (ac97_t *ac97);
 };
 
-struct _snd_ac97_bus {
-	/* -- lowlevel (hardware) driver specific -- */
+struct _snd_ac97_bus_ops {
 	void (*reset) (ac97_t *ac97);
 	void (*write) (ac97_t *ac97, unsigned short reg, unsigned short val);
 	unsigned short (*read) (ac97_t *ac97, unsigned short reg);
 	void (*wait) (ac97_t *ac97);
 	void (*init) (ac97_t *ac97);
+};
+
+struct _snd_ac97_bus {
+	/* -- lowlevel (hardware) driver specific -- */
+	ac97_bus_ops_t *ops;
 	void *private_data;
 	void (*private_free) (ac97_bus_t *bus);
 	/* --- */
 	snd_card_t *card;
 	unsigned short num;	/* bus number */
-	unsigned short vra: 1,	/* bridge supports VRA */
+	unsigned short no_vra: 1, /* bridge doesn't support VRA */
 		       isdin: 1;/* independent SDIN */
 	unsigned int clock;	/* AC'97 base clock (usually 48000Hz) */
 	spinlock_t bus_lock;	/* used mainly for slot allocation */
 	unsigned short used_slots[2][4]; /* actually used PCM slots */
 	unsigned short pcms_count; /* count of PCMs */
 	struct ac97_pcm *pcms;
+	unsigned int shared_type;	/* type of shared controller betwen audio and modem */
 	ac97_t *codec[4];
 	snd_info_entry_t *proc;
 };
 
+struct _snd_ac97_template {
+	void *private_data;
+	void (*private_free) (ac97_t *ac97);
+	struct pci_dev *pci;	/* assigned PCI device - used for quirks */
+	unsigned short num;	/* number of codec: 0 = primary, 1 = secondary */
+	unsigned short addr;	/* physical address of codec [0-3] */
+	unsigned int scaps;	/* driver capabilities */
+	unsigned int limited_regs; /* allow limited registers only */
+	DECLARE_BITMAP(reg_accessed, 0x80); /* bit flags */
+};
+
 struct _snd_ac97 {
 	/* -- lowlevel (hardware) driver specific -- */
 	struct snd_ac97_build_ops * build_ops;
@@ -441,6 +467,7 @@ struct _snd_ac97 {
 	unsigned short subsystem_vendor;
 	unsigned short subsystem_device;
 	spinlock_t reg_lock;
+	struct semaphore mutex;	/* mutex for AD18xx multi-codecs and paging (2.3) */
 	unsigned short num;	/* number of codec: 0 = primary, 1 = secondary */
 	unsigned short addr;	/* physical address of codec [0-3] */
 	unsigned int id;	/* identification of codec */
@@ -461,7 +488,6 @@ struct _snd_ac97 {
 			unsigned short id[3];		// codec IDs (lower 16-bit word)
 			unsigned short pcmreg[3];	// PCM registers
 			unsigned short codec_cfg[3];	// CODEC_CFG bits
-			struct semaphore mutex;
 		} ad18xx;
 		unsigned int dev_flags;		/* device specific */
 	} spec;
@@ -484,10 +510,14 @@ static inline int ac97_can_amap(ac97_t * ac97)
 {
 	return (ac97->ext_id & AC97_EI_AMAP) != 0;
 }
+static inline int ac97_can_spdif(ac97_t * ac97)
+{
+	return (ac97->ext_id & AC97_EI_SPDIF) != 0;
+}
 
 /* functions */
-int snd_ac97_bus(snd_card_t * card, ac97_bus_t * _bus, ac97_bus_t ** rbus); /* create new AC97 bus */
-int snd_ac97_mixer(ac97_bus_t * bus, ac97_t * _ac97, ac97_t ** rac97);	/* create mixer controls */
+int snd_ac97_bus(snd_card_t *card, int num, ac97_bus_ops_t *ops, void *private_data, ac97_bus_t **rbus); /* create new AC97 bus */
+int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97);	/* create mixer controls */
 
 void snd_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short value);
 unsigned short snd_ac97_read(ac97_t *ac97, unsigned short reg);
diff --git a/include/sound/asequencer.h b/include/sound/asequencer.h
index 4ba33e7bc..728efd504 100644
--- a/include/sound/asequencer.h
+++ b/include/sound/asequencer.h
@@ -177,7 +177,7 @@
 
 /* 150-151: kernel events with quote - DO NOT use in user clients */
 #define SNDRV_SEQ_EVENT_KERNEL_ERROR	150
-#define SNDRV_SEQ_EVENT_KERNEL_QUOTE	151
+#define SNDRV_SEQ_EVENT_KERNEL_QUOTE	151	/* obsolete */
 
 /* 152-191: reserved */
 
@@ -640,7 +640,7 @@ struct sndrv_seq_queue_info {
 	 *  etc. if the queue is locked for other clients
 	 */
 	int owner;		/* client id for owner of the queue */
-	int locked:1;		/* timing queue locked for other queues */
+	unsigned locked:1;	/* timing queue locked for other queues */
 	char name[64];		/* name of this queue */
 	unsigned int flags;	/* flags */
 	char reserved[60];	/* for future use */
diff --git a/include/sound/asound.h b/include/sound/asound.h
index 23b27b73a..56d63b91b 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -275,7 +275,6 @@ enum sndrv_pcm_subformat {
 #define SNDRV_PCM_INFO_HALF_DUPLEX	0x00100000	/* only half duplex */
 #define SNDRV_PCM_INFO_JOINT_DUPLEX	0x00200000	/* playback and capture stream are somewhat correlated */
 #define SNDRV_PCM_INFO_SYNC_START	0x00400000	/* pcm support some kind of sync go */
-#define SNDRV_PCM_INFO_NONATOMIC_OPS	0x00800000	/* non-atomic prepare callback */
 
 enum sndrv_pcm_state {
 	SNDRV_PCM_STATE_OPEN = 0,	/* stream is open */
diff --git a/include/sound/control.h b/include/sound/control.h
index 9224ffe0a..ed809e546 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -35,8 +35,7 @@ typedef struct sndrv_ctl_elem_value snd_ctl_elem_value_t;
 typedef enum sndrv_ctl_event_type snd_ctl_event_type_t;
 typedef struct sndrv_ctl_event snd_ctl_event_t;
 
-#define _snd_kcontrol_chip(kcontrol) ((kcontrol)->private_data)
-#define snd_kcontrol_chip(kcontrol) snd_magic_cast1(chip_t, _snd_kcontrol_chip(kcontrol), return -ENXIO)
+#define snd_kcontrol_chip(kcontrol) ((kcontrol)->private_data)
 
 typedef int (snd_kcontrol_info_t) (snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo);
 typedef int (snd_kcontrol_get_t) (snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
diff --git a/include/sound/core.h b/include/sound/core.h
index caf1b3c85..846852299 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -211,23 +211,27 @@ int snd_card_set_dev_pm_callback(snd_card_t *card, int type,
 				 void *private_data);
 #define snd_card_set_isa_pm_callback(card,suspend,resume,data) \
 	snd_card_set_dev_pm_callback(card, PM_ISA_DEV, suspend, resume, data)
+#ifdef CONFIG_PCI
 #ifndef SND_PCI_PM_CALLBACKS
 int snd_card_pci_suspend(struct pci_dev *dev, u32 state);
 int snd_card_pci_resume(struct pci_dev *dev);
 #define SND_PCI_PM_CALLBACKS \
 	.suspend = snd_card_pci_suspend,  .resume = snd_card_pci_resume
 #endif
+#endif
 #else
 #define snd_power_lock(card)		do { (void)(card); } while (0)
 #define snd_power_unlock(card)		do { (void)(card); } while (0)
 static inline int snd_power_wait(snd_card_t *card, unsigned int state, struct file *file) { return 0; }
 #define snd_power_get_state(card)	SNDRV_CTL_POWER_D0
 #define snd_power_change_state(card, state)	do { (void)(card); } while (0)
-#define snd_card_set_pm_callback(card,suspend,resume,data) -EINVAL
-#define snd_card_set_dev_pm_callback(card,suspend,resume,data) -EINVAL
-#define snd_card_set_isa_pm_callback(card,suspend,resume,data) -EINVAL
+#define snd_card_set_pm_callback(card,suspend,resume,data)
+#define snd_card_set_dev_pm_callback(card,suspend,resume,data)
+#define snd_card_set_isa_pm_callback(card,suspend,resume,data)
+#ifdef CONFIG_PCI
 #define SND_PCI_PM_CALLBACKS
 #endif
+#endif
 
 /* device.c */
 
@@ -268,7 +272,7 @@ int snd_oss_init_module(void);
 #else
 #define snd_minor_info_oss_init() /*NOP*/
 #define snd_minor_info_oss_done() /*NOP*/
-#define snd_oss_init_module() /*NOP*/
+#define snd_oss_init_module() 0
 #endif
 
 /* memory.c */
@@ -279,10 +283,12 @@ void snd_memory_done(void);
 int snd_memory_info_init(void);
 int snd_memory_info_done(void);
 void *snd_hidden_kmalloc(size_t size, int flags);
+void *snd_hidden_kcalloc(size_t n, size_t size, int flags);
 void snd_hidden_kfree(const void *obj);
 void *snd_hidden_vmalloc(unsigned long size);
 void snd_hidden_vfree(void *obj);
 #define kmalloc(size, flags) snd_hidden_kmalloc(size, flags)
+#define kcalloc(n, size, flags) snd_hidden_kcalloc(n, size, flags)
 #define kfree(obj) snd_hidden_kfree(obj)
 #define vmalloc(size) snd_hidden_vmalloc(size)
 #define vfree(obj) snd_hidden_vfree(obj)
@@ -300,7 +306,6 @@ void snd_hidden_vfree(void *obj);
 #define kfree_nocheck(obj) kfree(obj)
 #define vfree_nocheck(obj) vfree(obj)
 #endif
-void *snd_kcalloc(size_t size, int flags);
 char *snd_kmalloc_strdup(const char *string, int flags);
 int copy_to_user_fromio(void __user *dst, unsigned long src, size_t count);
 int copy_from_user_toio(unsigned long dst, const void __user *src, size_t count);
@@ -411,7 +416,7 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
  * not checked.
  */
 #define snd_assert(expr, args...) do {\
-	if (!(expr)) {\
+	if (unlikely(!(expr))) {				\
 		snd_printk("BUG? (%s) (called from %p)\n", __ASTRING__(expr), __builtin_return_address(0));\
 		args;\
 	}\
@@ -427,7 +432,7 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
  * CONFIG_SND_DEBUG is not set but without any error messages.
  */
 #define snd_runtime_check(expr, args...) do {\
-	if (!(expr)) {\
+	if (unlikely(!(expr))) {				\
 		snd_printk("ERROR (%s) (called from %p)\n", __ASTRING__(expr), __builtin_return_address(0));\
 		args;\
 	}\
diff --git a/include/sound/cs46xx.h b/include/sound/cs46xx.h
index 6f74f6d93..196592f10 100644
--- a/include/sound/cs46xx.h
+++ b/include/sound/cs46xx.h
@@ -24,6 +24,7 @@
  */
 
 #include "pcm.h"
+#include "pcm-indirect.h"
 #include "rawmidi.h"
 #include "ac97_codec.h"
 #include "cs46xx_dsp_spos.h"
@@ -1650,14 +1651,7 @@ typedef struct _snd_cs46xx_pcm_t {
   
 	unsigned int ctl;
 	unsigned int shift;	/* Shift count to trasform frames in bytes */
-	unsigned int sw_bufsize;
-	unsigned int sw_data;	/* Offset to next dst (or src) in sw ring buffer */
-	unsigned int sw_io;
-	int sw_ready;		/* Bytes ready to be transferred to/from hw */
-	unsigned int hw_data;	/* Offset to next dst (or src) in hw ring buffer */
-	unsigned int hw_io;	/* Ring buffer hw pointer */
-	int hw_ready;		/* Bytes ready for play (or captured) in hw ring buffer */
-	size_t appl_ptr;	/* Last seen appl_ptr */
+	snd_pcm_indirect_t pcm_rec;
 	snd_pcm_substream_t *substream;
 
 	pcm_channel_descriptor_t * pcm_channel;
@@ -1695,14 +1689,7 @@ struct _snd_cs46xx {
 
 		unsigned int ctl;
 		unsigned int shift;	/* Shift count to trasform frames in bytes */
-		unsigned int sw_bufsize;
-		unsigned int sw_data;	/* Offset to next dst (or src) in sw ring buffer */
-		unsigned int sw_io;
-		int sw_ready;		/* Bytes ready to be transferred to/from hw */
-		unsigned int hw_data;	/* Offset to next dst (or src) in hw ring buffer */
-		unsigned int hw_io;	/* Ring buffer hw pointer */
-		int hw_ready;		/* Bytes ready for play (or captured) in hw ring buffer */
-		size_t appl_ptr;	/* Last seen appl_ptr */
+		snd_pcm_indirect_t pcm_rec;
 		snd_pcm_substream_t *substream;
 	} capt;
 
@@ -1723,8 +1710,6 @@ struct _snd_cs46xx {
 	unsigned int midcr;
 	unsigned int uartm;
 
-	struct snd_dma_device dma_dev;
-
 	int amplifier;
 	void (*amplifier_ctrl)(cs46xx_t *, int);
 	void (*active_ctrl)(cs46xx_t *, int);
diff --git a/include/sound/driver.h b/include/sound/driver.h
index adef8f96f..948e9a1ae 100644
--- a/include/sound/driver.h
+++ b/include/sound/driver.h
@@ -61,6 +61,4 @@ void snd_wrapper_vfree(void *);
 #undef vfree
 #endif
 
-#include "sndmagic.h"
-
 #endif /* __SOUND_DRIVER_H */
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index 6182b7764..31b0df1fc 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -30,6 +30,7 @@
 #include <sound/hwdep.h>
 #include <sound/ac97_codec.h>
 #include <sound/util_mem.h>
+#include <sound/pcm-indirect.h>
 #include <linux/interrupt.h>
 #include <asm/io.h>
 
@@ -887,10 +888,7 @@ typedef struct {
 	unsigned char gpr_trigger;	/* GPR containing trigger (activate) information (host) */
 	unsigned char gpr_running;	/* GPR containing info if PCM is running (FX8010) */
 	unsigned char etram[32];	/* external TRAM address & data */
-	unsigned int sw_data, hw_data;
-	unsigned int sw_io, hw_io;
-	unsigned int sw_ready, hw_ready;
-	unsigned int appl_ptr;
+	snd_pcm_indirect_t pcm_rec;
 	unsigned int tram_pos;
 	unsigned int tram_shift;
 	snd_emu10k1_fx8010_irq_t *irq;
@@ -935,11 +933,11 @@ struct _snd_emu10k1 {
 	int irq;
 
 	unsigned long port;			/* I/O port number */
-	struct resource *res_port;
 	int APS: 1,				/* APS flag */
 	    no_ac97: 1,				/* no AC'97 */
 	    tos_link: 1,			/* tos link detected */
-	    rear_ac97: 1;			/* rear channels are on AC'97 */
+	    rear_ac97: 1,			/* rear channels are on AC'97 */
+	    spk71:1;				/* 7.1 configuration (Audigy 2 ZS) */
 	unsigned int audigy;			/* is Audigy? */
 	unsigned int revision;			/* chip revision */
 	unsigned int serial;			/* serial number */
@@ -947,7 +945,6 @@ struct _snd_emu10k1 {
 	unsigned int card_type;			/* EMU10K1_CARD_* */
 	unsigned int ecard_ctrl;		/* ecard control bits */
 	unsigned long dma_mask;			/* PCI DMA mask */
-	struct snd_dma_device dma_dev;		/* DMA device description */
 	int max_cache_pages;			/* max memory size / PAGE_SIZE */
 	struct snd_dma_buffer silent_page;	/* silent page */
 	struct snd_dma_buffer ptb_pages;	/* page table pages */
@@ -972,7 +969,6 @@ struct _snd_emu10k1 {
 	snd_pcm_t *pcm;
 	snd_pcm_t *pcm_mic;
 	snd_pcm_t *pcm_efx;
-	snd_pcm_t *pcm_fx8010;
 
 	spinlock_t synth_lock;
 	void *synth;
@@ -1069,6 +1065,15 @@ int snd_emu10k1_audigy_midi(emu10k1_t * emu);
 /* proc interface */
 int snd_emu10k1_proc_init(emu10k1_t * emu);
 
+/* fx8010 irq handler */
+int snd_emu10k1_fx8010_register_irq_handler(emu10k1_t *emu,
+					    snd_fx8010_irq_handler_t *handler,
+					    unsigned char gpr_running,
+					    void *private_data,
+					    snd_emu10k1_fx8010_irq_t **r_irq);
+int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
+					      snd_emu10k1_fx8010_irq_t *irq);
+
 #endif /* __KERNEL__ */
 
 /*
@@ -1162,6 +1167,8 @@ int snd_emu10k1_proc_init(emu10k1_t * emu);
 #define FXBUS_PCM_RIGHT_FRONT	0x09
 #define FXBUS_MIDI_REVERB	0x0c
 #define FXBUS_MIDI_CHORUS	0x0d
+#define FXBUS_PCM_LEFT_SIDE	0x0e
+#define FXBUS_PCM_RIGHT_SIDE	0x0f
 #define FXBUS_PT_LEFT		0x14
 #define FXBUS_PT_RIGHT		0x15
 
@@ -1227,8 +1234,8 @@ int snd_emu10k1_proc_init(emu10k1_t * emu);
 #define A_EXTOUT_AFRONT_R	0x09	/*              right */
 #define A_EXTOUT_ACENTER	0x0a	/* analog center */
 #define A_EXTOUT_ALFE		0x0b	/* analog LFE */
-/* 0x0c ?? */
-/* 0x0d ?? */
+#define A_EXTOUT_ASIDE_L	0x0c	/* analog side left  - Audigy 2 ZS */
+#define A_EXTOUT_ASIDE_R	0x0d	/*             right - Audigy 2 ZS */
 #define A_EXTOUT_AREAR_L	0x0e	/* analog rear left */
 #define A_EXTOUT_AREAR_R	0x0f	/*             right */
 #define A_EXTOUT_AC97_L		0x10	/* AC97 left (front) */
diff --git a/include/sound/es1688.h b/include/sound/es1688.h
index d390c6476..104bb9b02 100644
--- a/include/sound/es1688.h
+++ b/include/sound/es1688.h
@@ -55,8 +55,6 @@ struct _snd_es1688 {
 
 typedef struct _snd_es1688 es1688_t;
 
-#define chip_t es1688_t
-
 /* I/O ports */
 
 #define ES1688P(codec, x) ((codec)->port + e_s_s_ESS1688##x)
diff --git a/include/sound/info.h b/include/sound/info.h
index 29a6b83d1..e9efd4e4e 100644
--- a/include/sound/info.h
+++ b/include/sound/info.h
@@ -91,9 +91,12 @@ struct snd_info_entry {
 
 extern int snd_info_check_reserved_words(const char *str);
 
-#ifdef CONFIG_SND_OSSEMUL
+#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS)
 extern int snd_info_minor_register(void);
 extern int snd_info_minor_unregister(void);
+#else
+#define snd_info_minor_register() /* NOP */
+#define snd_info_minor_unregister() /* NOP */
 #endif
 
 
diff --git a/include/sound/initval.h b/include/sound/initval.h
index acb0a7f95..2bf150882 100644
--- a/include/sound/initval.h
+++ b/include/sound/initval.h
@@ -21,20 +21,6 @@
  *
  */
 
-#ifndef MODULE_GENERIC_STRING
-#ifdef MODULE
-#define MODULE_GENERIC_STRING(name, string) \
-static const char __module_generic_string_##name [] \
-  __attribute__ ((unused, __section__(".modstring"))) = #name "=" string;
-#else
-#define MODULE_GENERIC_STRING(name, string)
-#endif
-#endif
-
-#define MODULE_CLASSES(val) MODULE_GENERIC_STRING(info_classes, val)
-#define MODULE_DEVICES(val) MODULE_GENERIC_STRING(info_devices, val)
-#define MODULE_PARM_SYNTAX(id, val) MODULE_GENERIC_STRING(info_parm_##id, val)
-
 #define SNDRV_AUTO_PORT		1
 #define SNDRV_AUTO_IRQ		0xffff
 #define SNDRV_AUTO_DMA		0xffff
@@ -64,25 +50,6 @@ static const char __module_generic_string_##name [] \
 #define SNDRV_DEFAULT_DMA_SIZE	{ [0 ... (SNDRV_CARDS-1)] = SNDRV_AUTO_DMA_SIZE }
 #define SNDRV_DEFAULT_PTR	SNDRV_DEFAULT_STR
 
-#define SNDRV_BOOLEAN_TRUE_DESC	"allows:{{0,Disabled},{1,Enabled}},default:1,dialog:check"
-#define SNDRV_BOOLEAN_FALSE_DESC "allows:{{0,Disabled},{1,Enabled}},default:0,dialog:check"
-
-#define SNDRV_ENABLED		"enable:(enable)"
-
-#define SNDRV_INDEX_DESC	SNDRV_ENABLED ",allows:{{0,7}},unique,skill:required,dialog:list"
-#define SNDRV_ID_DESC		SNDRV_ENABLED ",unique"
-#define SNDRV_ENABLE_DESC	SNDRV_BOOLEAN_FALSE_DESC
-#define SNDRV_ISAPNP_DESC	SNDRV_ENABLED "," SNDRV_BOOLEAN_TRUE_DESC
-#define SNDRV_DMA8_DESC		SNDRV_ENABLED ",allows:{{0,1},{3}},dialog:list"
-#define SNDRV_DMA16_DESC	SNDRV_ENABLED ",allows:{{5,7}},dialog:list"
-#define SNDRV_DMA_DESC		SNDRV_ENABLED ",allows:{{0,1},{3},{5,7}},dialog:list"
-#define SNDRV_IRQ_DESC		SNDRV_ENABLED ",allows:{{5},{7},{9},{10,12},{14,15}},dialog:list"
-#define SNDRV_DMA_SIZE_DESC	SNDRV_ENABLED ",allows:{{4,128}},default:64,skill:advanced"
-#define SNDRV_DMA8_SIZE_DESC	SNDRV_ENABLED ",allows:{{4, 64}},default:64,skill:advanced"
-#define SNDRV_DMA16_SIZE_DESC	SNDRV_ENABLED ",allows:{{4,128}},default:64,skill:advanced"
-#define SNDRV_PORT12_DESC	SNDRV_ENABLED ",allows:{{0,0x3fff}},base:16"
-#define SNDRV_PORT_DESC		SNDRV_ENABLED ",allows:{{0,0xffff}},base:16"
-
 #ifdef SNDRV_LEGACY_AUTO_PROBE
 static int snd_legacy_auto_probe(unsigned long *ports, int (*probe)(unsigned long port))
 {
diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h
index eb0fd487d..3a2fd2cc9 100644
--- a/include/sound/memalloc.h
+++ b/include/sound/memalloc.h
@@ -30,9 +30,8 @@ struct device;
  * buffer device info
  */
 struct snd_dma_device {
-	int type;			/* SNDRV_MEM_TYPE_XXX */
+	int type;			/* SNDRV_DMA_TYPE_XXX */
 	struct device *dev;		/* generic device */
-	unsigned int id;		/* a unique ID */
 };
 
 #ifndef snd_dma_pci_data
@@ -56,6 +55,7 @@ struct snd_dma_device {
  * info for buffer allocation
  */
 struct snd_dma_buffer {
+	struct snd_dma_device dev;	/* device type */
 	unsigned char *area;	/* virtual pointer */
 	dma_addr_t addr;	/* physical address */
 	size_t bytes;		/* buffer size in bytes */
@@ -76,7 +76,7 @@ struct snd_sg_buf {
 	int tblsize;	/* allocated table size */
 	struct snd_sg_page *table;	/* address table */
 	struct page **page_table;	/* page table (for vmap/vunmap) */
-	struct snd_dma_device dev;
+	struct device *dev;
 };
 
 /*
@@ -97,20 +97,21 @@ static inline dma_addr_t snd_sgbuf_get_addr(struct snd_sg_buf *sgbuf, size_t off
 
 
 /* allocate/release a buffer */
-int snd_dma_alloc_pages(const struct snd_dma_device *dev, size_t size,
+int snd_dma_alloc_pages(int type, struct device *dev, size_t size,
 			struct snd_dma_buffer *dmab);
-int snd_dma_alloc_pages_fallback(const struct snd_dma_device *dev, size_t size,
+int snd_dma_alloc_pages_fallback(int type, struct device *dev, size_t size,
                                  struct snd_dma_buffer *dmab);
-void snd_dma_free_pages(const struct snd_dma_device *dev, struct snd_dma_buffer *dmab);
+void snd_dma_free_pages(struct snd_dma_buffer *dmab);
 
 /* buffer-preservation managements */
-size_t snd_dma_get_reserved(const struct snd_dma_device *dev, struct snd_dma_buffer *dmab);
-int snd_dma_free_reserved(const struct snd_dma_device *dev);
-int snd_dma_set_reserved(const struct snd_dma_device *dev, struct snd_dma_buffer *dmab);
+
+#define snd_dma_pci_buf_id(pci)	(((unsigned int)(pci)->vendor << 16) | (pci)->device)
+
+size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id);
+int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id);
 
 /* basic memory allocation functions */
 void *snd_malloc_pages(size_t size, unsigned int gfp_flags);
-void *snd_malloc_pages_fallback(size_t size, unsigned int gfp_flags, size_t *res_size);
 void snd_free_pages(void *ptr, size_t size);
 
 #endif /* __SOUND_MEMALLOC_H */
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 42293603d..c780e1013 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -52,10 +52,8 @@ typedef struct sndrv_pcm_mmap_control snd_pcm_mmap_control_t;
 typedef struct sndrv_mask snd_mask_t;
 typedef struct snd_sg_buf snd_pcm_sgbuf_t;
 
-#define _snd_pcm_substream_chip(substream) ((substream)->private_data)
-#define snd_pcm_substream_chip(substream) snd_magic_cast1(chip_t, _snd_pcm_substream_chip(substream), return -ENXIO)
-#define _snd_pcm_chip(pcm) ((pcm)->private_data)
-#define snd_pcm_chip(pcm) snd_magic_cast1(chip_t, _snd_pcm_chip(pcm), return -ENXIO)
+#define snd_pcm_substream_chip(substream) ((substream)->private_data)
+#define snd_pcm_chip(pcm) ((pcm)->private_data)
 
 typedef struct _snd_pcm_file snd_pcm_file_t;
 typedef struct _snd_pcm_runtime snd_pcm_runtime_t;
@@ -99,6 +97,7 @@ typedef struct _snd_pcm_ops {
 	int (*silence)(snd_pcm_substream_t *substream, int channel, 
 		       snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
 	struct page *(*page)(snd_pcm_substream_t *substream, unsigned long offset);
+	int (*mmap)(snd_pcm_substream_t *substream, struct vm_area_struct *vma);
 	int (*ack)(snd_pcm_substream_t *substream);
 } snd_pcm_ops_t;
 
@@ -123,6 +122,8 @@ typedef struct _snd_pcm_ops {
 #define SNDRV_PCM_TRIGGER_SUSPEND	5
 #define SNDRV_PCM_TRIGGER_RESUME	6
 
+#define SNDRV_PCM_POS_XRUN		((snd_pcm_uframes_t)-1)
+
 /* If you change this don't forget to change rates[] table in pcm_native.c */
 #define SNDRV_PCM_RATE_5512		(1<<0)		/* 5512Hz */
 #define SNDRV_PCM_RATE_8000		(1<<1)		/* 8000Hz */
@@ -351,7 +352,8 @@ struct _snd_pcm_runtime {
 	unsigned char *dma_area;	/* DMA area */
 	dma_addr_t dma_addr;		/* physical bus address (not accessible from main CPU) */
 	size_t dma_bytes;		/* size of DMA area */
-	void *dma_private;		/* private DMA data for the memory allocator */
+
+	struct snd_dma_buffer *dma_buffer_p;	/* allocated buffer */
 
 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
 	/* -- OSS things -- */
@@ -372,8 +374,8 @@ struct _snd_pcm_substream {
 	char name[32];			/* substream name */
 	int stream;			/* stream (direction) */
 	size_t buffer_bytes_max;	/* limit ring buffer size */
-	struct snd_dma_device dma_device;
 	struct snd_dma_buffer dma_buffer;
+	unsigned int dma_buf_id;
 	size_t dma_max;
 	/* -- hardware operations -- */
 	unsigned int open_flag: 1;	/* lowlevel device has been opened */
@@ -382,7 +384,7 @@ struct _snd_pcm_substream {
 	snd_pcm_runtime_t *runtime;
         /* -- timer section -- */
 	snd_timer_t *timer;		/* timer */
-	int timer_running: 1;		/* time is running */
+	unsigned timer_running: 1;	/* time is running */
 	spinlock_t timer_lock;
 	/* -- next substream -- */
 	snd_pcm_substream_t *next;
@@ -851,7 +853,7 @@ int snd_pcm_format_little_endian(snd_pcm_format_t format);
 int snd_pcm_format_big_endian(snd_pcm_format_t format);
 int snd_pcm_format_width(snd_pcm_format_t format);			/* in bits */
 int snd_pcm_format_physical_width(snd_pcm_format_t format);		/* in bits */
-u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format);
+const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format);
 int snd_pcm_format_set_silence(snd_pcm_format_t format, void *buf, unsigned int frames);
 snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian);
 ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples);
@@ -892,6 +894,22 @@ snd_pcm_sframes_t snd_pcm_lib_readv(snd_pcm_substream_t *substream,
 
 int snd_pcm_limit_hw_rates(snd_pcm_runtime_t *runtime);
 
+static inline void snd_pcm_set_runtime_buffer(snd_pcm_substream_t *substream,
+					      struct snd_dma_buffer *bufp)
+{
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	if (bufp) {
+		runtime->dma_buffer_p = bufp;
+		runtime->dma_area = bufp->area;
+		runtime->dma_addr = bufp->addr;
+		runtime->dma_bytes = bufp->bytes;
+	} else {
+		runtime->dma_buffer_p = NULL;
+		runtime->dma_area = NULL;
+		runtime->dma_addr = 0;
+		runtime->dma_bytes = 0;
+	}
+}
 
 /*
  *  Timer interface
@@ -916,11 +934,33 @@ int snd_pcm_lib_preallocate_pages_for_all(snd_pcm_t *pcm,
 int snd_pcm_lib_malloc_pages(snd_pcm_substream_t *substream, size_t size);
 int snd_pcm_lib_free_pages(snd_pcm_substream_t *substream);
 
-#define snd_pcm_substream_sgbuf(substream) ((substream)->runtime->dma_private)
+#define snd_pcm_substream_sgbuf(substream) ((substream)->runtime->dma_buffer_p->private_data)
 #define snd_pcm_sgbuf_pages(size) snd_sgbuf_aligned_pages(size)
 #define snd_pcm_sgbuf_get_addr(sgbuf,ofs) snd_sgbuf_get_addr(sgbuf,ofs)
 struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset);
 
+/* handle mmap counter - PCM mmap callback should handle this counter properly */
+static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area)
+{
+	snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
+	atomic_inc(&substream->runtime->mmap_count);
+}
+
+static inline void snd_pcm_mmap_data_close(struct vm_area_struct *area)
+{
+	snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
+	atomic_dec(&substream->runtime->mmap_count);
+}
+
+/* mmap for io-memory area */
+#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_ALPHA)
+#define SNDRV_PCM_INFO_MMAP_IOMEM	SNDRV_PCM_INFO_MMAP
+int snd_pcm_lib_mmap_iomem(snd_pcm_substream_t *substream, struct vm_area_struct *area);
+#else
+#define SNDRV_PCM_INFO_MMAP_IOMEM	0
+#define snd_pcm_lib_mmap_iomem	NULL
+#endif
+
 static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max)
 {
 	*max = dma < 4 ? 64 * 1024 : 128 * 1024;
diff --git a/include/sound/pcm_oss.h b/include/sound/pcm_oss.h
index 096d975de..518728536 100644
--- a/include/sound/pcm_oss.h
+++ b/include/sound/pcm_oss.h
@@ -39,10 +39,10 @@ struct _snd_pcm_oss_setup {
 };
 
 typedef struct _snd_pcm_oss_runtime {
-	int params: 1,				/* format/parameter change */
-            prepare: 1,				/* need to prepare the operation */
-            trigger: 1,				/* trigger flag */
-            sync_trigger: 1;			/* sync trigger flag */
+	unsigned params: 1,			/* format/parameter change */
+		 prepare: 1,			/* need to prepare the operation */
+		 trigger: 1,			/* trigger flag */
+		 sync_trigger: 1;		/* sync trigger flag */
 	int rate;				/* requested rate */
 	int format;				/* requested OSS format */
 	unsigned int channels;			/* requested channels */
@@ -68,7 +68,7 @@ typedef struct _snd_pcm_oss_file {
 } snd_pcm_oss_file_t;
 
 typedef struct _snd_pcm_oss_substream {
-	int oss: 1;				/* oss mode */
+	unsigned oss: 1;			/* oss mode */
 	snd_pcm_oss_setup_t *setup;		/* active setup */
 	snd_pcm_oss_file_t *file;
 } snd_pcm_oss_substream_t;
diff --git a/include/sound/seq_kernel.h b/include/sound/seq_kernel.h
index d0b69fbef..a64fb3f94 100644
--- a/include/sound/seq_kernel.h
+++ b/include/sound/seq_kernel.h
@@ -129,8 +129,8 @@ typedef struct _snd_seq_queue queue_t;
 
 typedef struct {
 	void *private_data;
-	int allow_input: 1,
-	    allow_output: 1;
+	unsigned allow_input: 1,
+		 allow_output: 1;
 	/*...*/
 } snd_seq_client_callback_t;
 
@@ -168,6 +168,9 @@ typedef int (*snd_seq_dump_func_t)(void *ptr, void *buf, int count);
 int snd_seq_expand_var_event(const snd_seq_event_t *event, int count, char *buf, int in_kernel, int size_aligned);
 int snd_seq_dump_var_event(const snd_seq_event_t *event, snd_seq_dump_func_t func, void *private_data);
 
+/* interface for OSS emulation */
+int snd_seq_set_queue_tempo(int client, snd_seq_queue_tempo_t *tempo);
+
 /* port callback routines */
 void snd_port_init_callback(snd_seq_port_callback_t *p);
 snd_seq_port_callback_t *snd_port_alloc_callback(void);
diff --git a/include/sound/soundfont.h b/include/sound/soundfont.h
index 907465a2c..eb1d612f3 100644
--- a/include/sound/soundfont.h
+++ b/include/sound/soundfont.h
@@ -95,6 +95,7 @@ typedef struct snd_sf_list {
 	int zone_locked;	/* locked time for zone */
 	int sample_locked;	/* locked time for sample */
 	snd_sf_callback_t callback;	/* callback functions */
+	int presets_locked;
 	struct semaphore presets_mutex;
 	spinlock_t lock;
 	snd_util_memhdr_t *memhdr;
diff --git a/include/sound/timer.h b/include/sound/timer.h
index fd33b802e..57fde9906 100644
--- a/include/sound/timer.h
+++ b/include/sound/timer.h
@@ -40,8 +40,7 @@ typedef struct sndrv_timer_status snd_timer_status_t;
 typedef struct sndrv_timer_read snd_timer_read_t;
 typedef struct sndrv_timer_tread snd_timer_tread_t;
 
-#define _snd_timer_chip(timer) ((timer)->private_data)
-#define snd_timer_chip(timer) snd_magic_cast1(chip_t, _snd_timer_chip(timer), return -ENXIO)
+#define snd_timer_chip(timer) ((timer)->private_data)
 
 #define SNDRV_TIMER_DEVICES	16
 
diff --git a/include/sound/trident.h b/include/sound/trident.h
index 255a5cbe6..7538ba6b3 100644
--- a/include/sound/trident.h
+++ b/include/sound/trident.h
@@ -398,7 +398,6 @@ struct _snd_trident {
         unsigned char  bDMAStart;
 
 	unsigned long port;
-	struct resource *res_port;
 	unsigned long midi_port;
 
 	unsigned int spurious_irq_count;
diff --git a/include/sound/version.h b/include/sound/version.h
index 9f7d0e930..ce09f8071 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
 /* include/version.h.  Generated by configure.  */
-#define CONFIG_SND_VERSION "1.0.4"
-#define CONFIG_SND_DATE " (Mon May 17 14:31:44 2004 UTC)"
+#define CONFIG_SND_VERSION "1.0.6"
+#define CONFIG_SND_DATE " (Sun Aug 15 07:17:53 2004 UTC)"
diff --git a/include/sound/vx_core.h b/include/sound/vx_core.h
index 5609f5420..d3d90e1f2 100644
--- a/include/sound/vx_core.h
+++ b/include/sound/vx_core.h
@@ -182,6 +182,7 @@ struct snd_vx_core {
 	/* clock and audio sources */
 	unsigned int audio_source;	/* current audio input source */
 	unsigned int audio_source_target;
+	unsigned int clock_mode;	/* clock mode (VX_CLOCK_MODE_XXX) */
 	unsigned int clock_source;	/* current clock source (INTERNAL_QUARTZ or UER_SYNC) */
 	unsigned int freq;		/* current frequency */
 	unsigned int freq_detected;	/* detected frequency from digital in */
@@ -364,6 +365,13 @@ enum {
 	UER_SYNC
 };
 
+/* clock mode */
+enum {
+	VX_CLOCK_MODE_AUTO,	/* depending on the current audio source */
+	VX_CLOCK_MODE_INTERNAL,	/* fixed to internal quartz */
+	VX_CLOCK_MODE_EXTERNAL	/* fixed to UER sync */
+};
+
 /* SPDIF/UER type */
 enum {
 	VX_UER_MODE_CONSUMER,
diff --git a/include/sound/ymfpci.h b/include/sound/ymfpci.h
index cf2cd5ad6..1f4db1df1 100644
--- a/include/sound/ymfpci.h
+++ b/include/sound/ymfpci.h
@@ -316,7 +316,6 @@ struct _snd_ymfpci {
 	struct gameport gameport;
 #endif
 
-	struct snd_dma_device dma_dev;
 	struct snd_dma_buffer work_ptr;
 
 	unsigned int bank_size_playback;
diff --git a/include/video/neomagic.h b/include/video/neomagic.h
index 21953f8bd..ab69ed7b9 100644
--- a/include/video/neomagic.h
+++ b/include/video/neomagic.h
@@ -69,6 +69,9 @@
 #define NEO_ICON128_ENABLE	0x0000000C
 #define NEO_ICON_BLANK		0x00000010
 
+#define NEO_GR01_SUPPRESS_VSYNC 0x10
+#define NEO_GR01_SUPPRESS_HSYNC 0x20
+
 #ifdef __KERNEL__
 
 #ifdef NEOFB_DEBUG
diff --git a/include/video/tdfx.h b/include/video/tdfx.h
index 3120bfbea..96eb4a761 100644
--- a/include/video/tdfx.h
+++ b/include/video/tdfx.h
@@ -114,6 +114,7 @@
 #define VGAINIT1_MASK                   0x1fffff
 #define VIDCFG_VIDPROC_ENABLE           BIT(0)
 #define VIDCFG_CURS_X11                 BIT(1)
+#define VIDCFG_INTERLACE                BIT(3)
 #define VIDCFG_HALF_MODE                BIT(4)
 #define VIDCFG_DESK_ENABLE              BIT(7)
 #define VIDCFG_CLUT_BYPASS              BIT(10)
diff --git a/include/video/vga.h b/include/video/vga.h
index e44593d3c..700d6c8eb 100644
--- a/include/video/vga.h
+++ b/include/video/vga.h
@@ -203,7 +203,7 @@
 #define VGA_SAVE_CMAP  16 /* save/restore color map/DAC   */
 
 struct vgastate {
-	caddr_t vgabase;	/* mmio base, if supported 		   */
+	void __iomem *vgabase;	/* mmio base, if supported 		   */
 	unsigned long membase;	/* VGA window base, 0 for default - 0xA000 */
 	__u32 memsize;		/* VGA window size, 0 for default 64K	   */
 	__u32 flags;		/* what state[s] to save (see VGA_SAVE_*)  */
@@ -238,23 +238,23 @@ static inline void vga_io_w_fast (unsigned short port, unsigned char reg,
 	outw(VGA_OUT16VAL (val, reg), port);
 }
 
-static inline unsigned char vga_mm_r (caddr_t regbase, unsigned short port)
+static inline unsigned char vga_mm_r (void __iomem *regbase, unsigned short port)
 {
 	return readb (regbase + port);
 }
 
-static inline void vga_mm_w (caddr_t regbase, unsigned short port, unsigned char val)
+static inline void vga_mm_w (void __iomem *regbase, unsigned short port, unsigned char val)
 {
 	writeb (val, regbase + port);
 }
 
-static inline void vga_mm_w_fast (caddr_t regbase, unsigned short port,
+static inline void vga_mm_w_fast (void __iomem *regbase, unsigned short port,
 				  unsigned char reg, unsigned char val)
 {
 	writew (VGA_OUT16VAL (val, reg), regbase + port);
 }
 
-static inline unsigned char vga_r (caddr_t regbase, unsigned short port)
+static inline unsigned char vga_r (void __iomem *regbase, unsigned short port)
 {
 	if (regbase)
 		return vga_mm_r (regbase, port);
@@ -262,7 +262,7 @@ static inline unsigned char vga_r (caddr_t regbase, unsigned short port)
 		return vga_io_r (port);
 }
 
-static inline void vga_w (caddr_t regbase, unsigned short port, unsigned char val)
+static inline void vga_w (void __iomem *regbase, unsigned short port, unsigned char val)
 {
 	if (regbase)
 		vga_mm_w (regbase, port, val);
@@ -271,7 +271,7 @@ static inline void vga_w (caddr_t regbase, unsigned short port, unsigned char va
 }
 
 
-static inline void vga_w_fast (caddr_t regbase, unsigned short port,
+static inline void vga_w_fast (void __iomem *regbase, unsigned short port,
 			       unsigned char reg, unsigned char val)
 {
 	if (regbase)
@@ -285,13 +285,13 @@ static inline void vga_w_fast (caddr_t regbase, unsigned short port,
  * VGA CRTC register read/write
  */
  
-static inline unsigned char vga_rcrt (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_rcrt (void __iomem *regbase, unsigned char reg)
 {
         vga_w (regbase, VGA_CRT_IC, reg);
         return vga_r (regbase, VGA_CRT_DC);
 }
 
-static inline void vga_wcrt (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_wcrt (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
 #ifdef VGA_OUTW_WRITE
 	vga_w_fast (regbase, VGA_CRT_IC, reg, val);
@@ -317,13 +317,13 @@ static inline void vga_io_wcrt (unsigned char reg, unsigned char val)
 #endif /* VGA_OUTW_WRITE */
 }
 
-static inline unsigned char vga_mm_rcrt (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_mm_rcrt (void __iomem *regbase, unsigned char reg)
 {
         vga_mm_w (regbase, VGA_CRT_IC, reg);
         return vga_mm_r (regbase, VGA_CRT_DC);
 }
 
-static inline void vga_mm_wcrt (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_mm_wcrt (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
 #ifdef VGA_OUTW_WRITE
 	vga_mm_w_fast (regbase, VGA_CRT_IC, reg, val);
@@ -338,13 +338,13 @@ static inline void vga_mm_wcrt (caddr_t regbase, unsigned char reg, unsigned cha
  * VGA sequencer register read/write
  */
  
-static inline unsigned char vga_rseq (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_rseq (void __iomem *regbase, unsigned char reg)
 {
         vga_w (regbase, VGA_SEQ_I, reg);
         return vga_r (regbase, VGA_SEQ_D);
 }
 
-static inline void vga_wseq (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_wseq (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
 #ifdef VGA_OUTW_WRITE
 	vga_w_fast (regbase, VGA_SEQ_I, reg, val);
@@ -370,13 +370,13 @@ static inline void vga_io_wseq (unsigned char reg, unsigned char val)
 #endif /* VGA_OUTW_WRITE */
 }
 
-static inline unsigned char vga_mm_rseq (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_mm_rseq (void __iomem *regbase, unsigned char reg)
 {
         vga_mm_w (regbase, VGA_SEQ_I, reg);
         return vga_mm_r (regbase, VGA_SEQ_D);
 }
 
-static inline void vga_mm_wseq (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_mm_wseq (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
 #ifdef VGA_OUTW_WRITE
 	vga_mm_w_fast (regbase, VGA_SEQ_I, reg, val);
@@ -390,13 +390,13 @@ static inline void vga_mm_wseq (caddr_t regbase, unsigned char reg, unsigned cha
  * VGA graphics controller register read/write
  */
  
-static inline unsigned char vga_rgfx (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_rgfx (void __iomem *regbase, unsigned char reg)
 {
         vga_w (regbase, VGA_GFX_I, reg);
         return vga_r (regbase, VGA_GFX_D);
 }
 
-static inline void vga_wgfx (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_wgfx (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
 #ifdef VGA_OUTW_WRITE
 	vga_w_fast (regbase, VGA_GFX_I, reg, val);
@@ -422,13 +422,13 @@ static inline void vga_io_wgfx (unsigned char reg, unsigned char val)
 #endif /* VGA_OUTW_WRITE */
 }
 
-static inline unsigned char vga_mm_rgfx (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_mm_rgfx (void __iomem *regbase, unsigned char reg)
 {
         vga_mm_w (regbase, VGA_GFX_I, reg);
         return vga_mm_r (regbase, VGA_GFX_D);
 }
 
-static inline void vga_mm_wgfx (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_mm_wgfx (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
 #ifdef VGA_OUTW_WRITE
 	vga_mm_w_fast (regbase, VGA_GFX_I, reg, val);
@@ -443,13 +443,13 @@ static inline void vga_mm_wgfx (caddr_t regbase, unsigned char reg, unsigned cha
  * VGA attribute controller register read/write
  */
  
-static inline unsigned char vga_rattr (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_rattr (void __iomem *regbase, unsigned char reg)
 {
         vga_w (regbase, VGA_ATT_IW, reg);
         return vga_r (regbase, VGA_ATT_R);
 }
 
-static inline void vga_wattr (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_wattr (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
         vga_w (regbase, VGA_ATT_IW, reg);
         vga_w (regbase, VGA_ATT_W, val);
@@ -467,13 +467,13 @@ static inline void vga_io_wattr (unsigned char reg, unsigned char val)
         vga_io_w (VGA_ATT_W, val);
 }
 
-static inline unsigned char vga_mm_rattr (caddr_t regbase, unsigned char reg)
+static inline unsigned char vga_mm_rattr (void __iomem *regbase, unsigned char reg)
 {
         vga_mm_w (regbase, VGA_ATT_IW, reg);
         return vga_mm_r (regbase, VGA_ATT_R);
 }
 
-static inline void vga_mm_wattr (caddr_t regbase, unsigned char reg, unsigned char val)
+static inline void vga_mm_wattr (void __iomem *regbase, unsigned char reg, unsigned char val)
 {
         vga_mm_w (regbase, VGA_ATT_IW, reg);
         vga_mm_w (regbase, VGA_ATT_W, val);
diff --git a/init/Kconfig b/init/Kconfig
index 113a656f5..3f83eb242 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1,4 +1,3 @@
-
 menu "Code maturity level options"
 
 config EXPERIMENTAL
@@ -53,9 +52,18 @@ config BROKEN_ON_SMP
 
 endmenu
 
-
 menu "General setup"
 
+config LOCALVERSION
+	string "Local version - append to kernel release"
+	help
+	  Append an extra string to the end of your kernel version.
+	  This will show up when you type uname, for example.
+	  The string you set here will be appended after the contents of
+	  any files with a filename matching localversion* in your
+	  object and source tree, in that order.  Your total string can
+	  be a maximum of 64 characters.
+
 config SWAP
 	bool "Support for paging of anonymous memory (swap)"
 	depends on MMU
@@ -123,7 +131,7 @@ config BSD_PROCESS_ACCT_V3
 	  process and it's parent. Note that this file format is incompatible
 	  with previous v0/v1/v2 file formats, so you will need updated tools
 	  for processing it. A preliminary version of these tools is available
-	  at <http://http://www.de.kernel.org/pub/linux/utils/acct/>.
+	  at <http://www.physik3.uni-rostock.de/tim/kernel/utils/acct/>.
 
 config SYSCTL
 	bool "Sysctl support"
@@ -285,8 +293,21 @@ config CC_OPTIMIZE_FOR_SIZE
 
 	  If unsure, say N.
 
+config SHMEM
+	default y
+	bool "Use full shmem filesystem" if EMBEDDED && MMU
+	help
+	  The shmem is an internal filesystem used to manage shared memory.
+	  It is backed by swap and manages resource limits. It is also exported
+	  to userspace as tmpfs if TMPFS is enabled. Disabling this
+	  option replaces shmem and tmpfs with the much simpler ramfs code,
+	  which may be appropriate on small systems without swap.
+
 endmenu		# General setup
 
+config TINY_SHMEM
+	default !SHMEM
+	bool
 
 menu "Loadable module support"
 
diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c
index 6f8900ee1..4abfc1c01 100644
--- a/init/do_mounts_rd.c
+++ b/init/do_mounts_rd.c
@@ -122,7 +122,8 @@ identify_ramdisk_image(int fd, int start_block)
 		printk(KERN_NOTICE
 		       "RAMDISK: ext2 filesystem found at block %d\n",
 		       start_block);
-		nblocks = le32_to_cpu(ext2sb->s_blocks_count);
+		nblocks = le32_to_cpu(ext2sb->s_blocks_count) <<
+			le32_to_cpu(ext2sb->s_log_block_size);
 		goto done;
 	}
 
@@ -173,10 +174,15 @@ int __init rd_load_image(char *from)
 	}
 
 	/*
-	 * NOTE NOTE: nblocks suppose that the blocksize is BLOCK_SIZE, so
-	 * rd_load_image will work only with filesystem BLOCK_SIZE wide!
-	 * So make sure to use 1k blocksize while generating ext2fs
-	 * ramdisk-images.
+	 * NOTE NOTE: nblocks is not actually blocks but
+	 * the number of kibibytes of data to load into a ramdisk.
+	 * So any ramdisk block size that is a multiple of 1KiB should
+	 * work when the appropriate ramdisk_blocksize is specified
+	 * on the command line.
+	 *
+	 * The default ramdisk_blocksize is 1KiB and it is generally
+	 * silly to use anything else, so make sure to use 1KiB
+	 * blocksize while generating ext2fs ramdisk-images.
 	 */
 	if (sys_ioctl(out_fd, BLKGETSIZE, (unsigned long)&rd_blocks) < 0)
 		rd_blocks = 0;
@@ -184,7 +190,7 @@ int __init rd_load_image(char *from)
 		rd_blocks >>= 1;
 
 	if (nblocks > rd_blocks) {
-		printk("RAMDISK: image too big! (%d/%ld blocks)\n",
+		printk("RAMDISK: image too big! (%dKiB/%ldKiB)\n",
 		       nblocks, rd_blocks);
 		goto done;
 	}
@@ -211,7 +217,7 @@ int __init rd_load_image(char *from)
 		goto done;
 	}
 
-	printk(KERN_NOTICE "RAMDISK: Loading %d blocks [%ld disk%s] into ram disk... ", 
+	printk(KERN_NOTICE "RAMDISK: Loading %dKiB [%ld disk%s] into ram disk... ",
 		nblocks, ((nblocks-1)/devblocks)+1, nblocks>devblocks ? "s" : "");
 	for (i = 0, disk = 1; i < nblocks; i++) {
 		if (i && (i % devblocks == 0)) {
diff --git a/init/main.c b/init/main.c
index cafeaeb4e..0c0135ad0 100644
--- a/init/main.c
+++ b/init/main.c
@@ -31,6 +31,7 @@
 #include <linux/tty.h>
 #include <linux/gfp.h>
 #include <linux/percpu.h>
+#include <linux/kmod.h>
 #include <linux/kernel_stat.h>
 #include <linux/security.h>
 #include <linux/workqueue.h>
@@ -93,6 +94,11 @@ extern void free_initmem(void);
 extern void populate_rootfs(void);
 extern void driver_init(void);
 extern void prepare_namespace(void);
+#ifdef	CONFIG_ACPI
+extern void acpi_early_init(void);
+#else
+static inline void acpi_early_init(void) { }
+#endif
 
 #ifdef CONFIG_TC
 extern void tc_init(void);
@@ -104,8 +110,8 @@ EXPORT_SYMBOL(system_state);
 /*
  * Boot command-line arguments
  */
-#define MAX_INIT_ARGS 8
-#define MAX_INIT_ENVS 8
+#define MAX_INIT_ARGS 32
+#define MAX_INIT_ENVS 32
 
 extern void time_init(void);
 /* Default late time init is NULL. archs can override this later. */
@@ -150,8 +156,6 @@ static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
 char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
 static const char *panic_later, *panic_param;
 
-__setup("profile=", profile_setup);
-
 static int __init obsolete_checksetup(char *line)
 {
 	struct obs_kernel_param *p;
@@ -178,15 +182,28 @@ static int __init obsolete_checksetup(char *line)
 	return 0;
 }
 
-/* this should be approx 2 Bo*oMips to start (note initial shift), and will
-   still work even if initially too large, it will just take slightly longer */
+static unsigned long preset_lpj;
+static int __init lpj_setup(char *str)
+{
+	preset_lpj = simple_strtoul(str,NULL,0);
+	return 1;
+}
+
+__setup("lpj=", lpj_setup);
+
+/*
+ * This should be approx 2 Bo*oMips to start (note initial shift), and will
+ * still work even if initially too large, it will just take slightly longer
+ */
 unsigned long loops_per_jiffy = (1<<12);
 
 EXPORT_SYMBOL(loops_per_jiffy);
 
-/* This is the number of bits of precision for the loops_per_jiffy.  Each
-   bit takes on average 1.5/HZ seconds.  This (like the original) is a little
-   better than 1% */
+/*
+ * This is the number of bits of precision for the loops_per_jiffy.  Each
+ * bit takes on average 1.5/HZ seconds.  This (like the original) is a little
+ * better than 1%
+ */
 #define LPS_PREC 8
 
 void __devinit calibrate_delay(void)
@@ -194,40 +211,53 @@ void __devinit calibrate_delay(void)
 	unsigned long ticks, loopbit;
 	int lps_precision = LPS_PREC;
 
-	loops_per_jiffy = (1<<12);
-
-	printk("Calibrating delay loop... ");
-	while ((loops_per_jiffy <<= 1) != 0) {
-		/* wait for "start of" clock tick */
-		ticks = jiffies;
-		while (ticks == jiffies)
-			/* nothing */;
-		/* Go .. */
-		ticks = jiffies;
-		__delay(loops_per_jiffy);
-		ticks = jiffies - ticks;
-		if (ticks)
-			break;
-	}
+	if (preset_lpj) {
+		loops_per_jiffy = preset_lpj;
+		printk("Calibrating delay loop (skipped)... "
+			"%lu.%02lu BogoMIPS preset\n",
+			loops_per_jiffy/(500000/HZ),
+			(loops_per_jiffy/(5000/HZ)) % 100);
+	} else {
+		loops_per_jiffy = (1<<12);
+
+		printk(KERN_DEBUG "Calibrating delay loop... ");
+		while ((loops_per_jiffy <<= 1) != 0) {
+			/* wait for "start of" clock tick */
+			ticks = jiffies;
+			while (ticks == jiffies)
+				/* nothing */;
+			/* Go .. */
+			ticks = jiffies;
+			__delay(loops_per_jiffy);
+			ticks = jiffies - ticks;
+			if (ticks)
+				break;
+		}
+
+		/*
+		 * Do a binary approximation to get loops_per_jiffy set to
+		 * equal one clock (up to lps_precision bits)
+		 */
+		loops_per_jiffy >>= 1;
+		loopbit = loops_per_jiffy;
+		while (lps_precision-- && (loopbit >>= 1)) {
+			loops_per_jiffy |= loopbit;
+			ticks = jiffies;
+			while (ticks == jiffies)
+				/* nothing */;
+			ticks = jiffies;
+			__delay(loops_per_jiffy);
+			if (jiffies != ticks)	/* longer than 1 tick */
+				loops_per_jiffy &= ~loopbit;
+		}
 
-/* Do a binary approximation to get loops_per_jiffy set to equal one clock
-   (up to lps_precision bits) */
-	loops_per_jiffy >>= 1;
-	loopbit = loops_per_jiffy;
-	while ( lps_precision-- && (loopbit >>= 1) ) {
-		loops_per_jiffy |= loopbit;
-		ticks = jiffies;
-		while (ticks == jiffies);
-		ticks = jiffies;
-		__delay(loops_per_jiffy);
-		if (jiffies != ticks)	/* longer than 1 tick */
-			loops_per_jiffy &= ~loopbit;
+		/* Round the value and print it */
+		printk("%lu.%02lu BogoMIPS (lpj=%lu)\n",
+			loops_per_jiffy/(500000/HZ),
+			(loops_per_jiffy/(5000/HZ)) % 100,
+			loops_per_jiffy);
 	}
 
-/* Round the value and print it */	
-	printk("%lu.%02lu BogoMIPS\n",
-		loops_per_jiffy/(500000/HZ),
-		(loops_per_jiffy/(5000/HZ)) % 100);
 }
 
 static int __init debug_kernel(char *str)
@@ -249,20 +279,26 @@ static int __init quiet_kernel(char *str)
 __setup("debug", debug_kernel);
 __setup("quiet", quiet_kernel);
 
-/* Unknown boot options get handed to init, unless they look like
-   failed parameters */
+/*
+ * Unknown boot options get handed to init, unless they look like
+ * failed parameters
+ */
 static int __init unknown_bootoption(char *param, char *val)
 {
 	/* Change NUL term back to "=", to make "param" the whole string. */
-	if (val)
-		val[-1] = '=';
+	if (val) {
+		if (val[-1] == '"') val[-2] = '=';
+		else val[-1] = '=';
+	}
 
 	/* Handle obsolete-style parameters */
 	if (obsolete_checksetup(param))
 		return 0;
 
-	/* Preemptive maintenance for "why didn't my mispelled command
-           line work?" */
+	/*
+	 * Preemptive maintenance for "why didn't my mispelled command
+	 * line work?"
+	 */
 	if (strchr(param, '.') && (!val || strchr(param, '.') < val)) {
 		printk(KERN_ERR "Unknown boot option `%s': ignoring\n", param);
 		return 0;
@@ -302,7 +338,8 @@ static int __init init_setup(char *str)
 	unsigned int i;
 
 	execute_command = str;
-	/* In case LILO is going to boot us with default command line,
+	/*
+	 * In case LILO is going to boot us with default command line,
 	 * it prepends "auto" before the whole cmdline which makes
 	 * the shell think it should execute a script with such name.
 	 * So we ignore all arguments entered _before_ init=... [MJ]
@@ -465,7 +502,6 @@ asmlinkage void __init start_kernel(void)
 	 * time - but meanwhile we still have a functioning scheduler.
 	 */
 	sched_init();
-
 	build_all_zonelists();
 	page_alloc_init();
 	printk("Kernel command line: %s\n", saved_command_line);
@@ -530,12 +566,7 @@ asmlinkage void __init start_kernel(void)
 #endif
 	check_bugs();
 
-	/* 
-	 *	We count on the initial thread going ok 
-	 *	Like idlers init is an unlocked kernel thread, which will
-	 *	make syscalls (and thus be locked).
-	 */
-	init_idle(current, smp_processor_id());
+	acpi_early_init(); /* before LAPIC and SMP init */
 
 	/* Do the rest non-__init'ed, we're now alive */
 	rest_init();
@@ -598,6 +629,10 @@ static void __init do_initcalls(void)
  */
 static void __init do_basic_setup(void)
 {
+	/* drivers will send hotplug events */
+	init_workqueues();
+	usermodehelper_init();
+
 	driver_init();
 
 #ifdef CONFIG_SYSCTL
@@ -607,7 +642,6 @@ static void __init do_basic_setup(void)
 	/* Networking initialization needs a process context */ 
 	sock_init();
 
-	init_workqueues();
 	do_initcalls();
 }
 
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index c9ea777b1..aee2696c3 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -828,7 +828,7 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
 	/* First try to allocate memory, before doing anything with
 	 * existing queues. */
 	msg_ptr = load_msg(u_msg_ptr, msg_len);
-	if (unlikely(IS_ERR(msg_ptr))) {
+	if (IS_ERR(msg_ptr)) {
 		ret = PTR_ERR(msg_ptr);
 		goto out_fput;
 	}
diff --git a/ipc/msg.c b/ipc/msg.c
index c4d3b2a7a..095f2b747 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -103,14 +103,14 @@ static int newque (key_t key, int msgflg)
 	msq->q_perm.security = NULL;
 	retval = security_msg_queue_alloc(msq);
 	if (retval) {
-		ipc_rcu_free(msq, sizeof(*msq));
+		ipc_rcu_putref(msq);
 		return retval;
 	}
 
 	id = ipc_addid(&msg_ids, &msq->q_perm, msg_ctlmni);
 	if(id == -1) {
 		security_msg_queue_free(msq);
-		ipc_rcu_free(msq, sizeof(*msq));
+		ipc_rcu_putref(msq);
 		return -ENOSPC;
 	}
 
@@ -166,8 +166,10 @@ static void expunge_all(struct msg_queue* msq, int res)
 		
 		msr = list_entry(tmp,struct msg_receiver,r_list);
 		tmp = tmp->next;
-		msr->r_msg = ERR_PTR(res);
+		msr->r_msg = NULL;
 		wake_up_process(msr->r_tsk);
+		smp_mb();
+		msr->r_msg = ERR_PTR(res);
 	}
 }
 /* 
@@ -196,7 +198,7 @@ static void freeque (struct msg_queue *msq, int id)
 	}
 	atomic_sub(msq->q_cbytes, &msg_bytes);
 	security_msg_queue_free(msq);
-	ipc_rcu_free(msq, sizeof(struct msg_queue));
+	ipc_rcu_putref(msq);
 }
 
 asmlinkage long sys_msgget (key_t key, int msgflg)
@@ -528,13 +530,17 @@ static inline int pipelined_send(struct msg_queue* msq, struct msg_msg* msg)
 		   !security_msg_queue_msgrcv(msq, msg, msr->r_tsk, msr->r_msgtype, msr->r_mode)) {
 			list_del(&msr->r_list);
 			if(msr->r_maxsize < msg->m_ts) {
-				msr->r_msg = ERR_PTR(-E2BIG);
+				msr->r_msg = NULL;
 				wake_up_process(msr->r_tsk);
+				smp_mb();
+				msr->r_msg = ERR_PTR(-E2BIG);
 			} else {
-				msr->r_msg = msg;
+				msr->r_msg = NULL;
 				msq->q_lrpid = msr->r_tsk->pid;
 				msq->q_rtime = get_seconds();
 				wake_up_process(msr->r_tsk);
+				smp_mb();
+				msr->r_msg = msg;
 				return 1;
 			}
 		}
@@ -567,43 +573,49 @@ asmlinkage long sys_msgsnd (int msqid, struct msgbuf __user *msgp, size_t msgsz,
 	err=-EINVAL;
 	if(msq==NULL)
 		goto out_free;
-retry:
+
 	err= -EIDRM;
 	if (msg_checkid(msq,msqid))
 		goto out_unlock_free;
 
-	err=-EACCES;
-	if (ipcperms(&msq->q_perm, S_IWUGO)) 
-		goto out_unlock_free;
+	for (;;) {
+		struct msg_sender s;
 
-	err = security_msg_queue_msgsnd(msq, msg, msgflg);
-	if (err)
-		goto out_unlock_free;
+		err=-EACCES;
+		if (ipcperms(&msq->q_perm, S_IWUGO))
+			goto out_unlock_free;
 
-	if(msgsz + msq->q_cbytes > msq->q_qbytes ||
-		1 + msq->q_qnum > msq->q_qbytes) {
-		struct msg_sender s;
+		err = security_msg_queue_msgsnd(msq, msg, msgflg);
+		if (err)
+			goto out_unlock_free;
 
+		if(msgsz + msq->q_cbytes <= msq->q_qbytes &&
+				1 + msq->q_qnum <= msq->q_qbytes) {
+			break;
+		}
+
+		/* queue full, wait: */
 		if(msgflg&IPC_NOWAIT) {
 			err=-EAGAIN;
 			goto out_unlock_free;
 		}
 		ss_add(msq, &s);
+		ipc_rcu_getref(msq);
 		msg_unlock(msq);
 		schedule();
-		current->state= TASK_RUNNING;
 
-		msq = msg_lock(msqid);
-		err = -EIDRM;
-		if(msq==NULL)
-			goto out_free;
+		ipc_lock_by_ptr(&msq->q_perm);
+		ipc_rcu_putref(msq);
+		if (msq->q_perm.deleted) {
+			err = -EIDRM;
+			goto out_unlock_free;
+		}
 		ss_del(&s);
 		
 		if (signal_pending(current)) {
-			err=-EINTR;
+			err=-ERESTARTNOHAND;
 			goto out_unlock_free;
 		}
-		goto retry;
 	}
 
 	msq->q_lspid = current->tgid;
@@ -652,10 +664,7 @@ asmlinkage long sys_msgrcv (int msqid, struct msgbuf __user *msgp, size_t msgsz,
 			    long msgtyp, int msgflg)
 {
 	struct msg_queue *msq;
-	struct msg_receiver msr_d;
-	struct list_head* tmp;
-	struct msg_msg* msg, *found_msg;
-	int err;
+	struct msg_msg *msg;
 	int mode;
 
 	if (msqid < 0 || (long) msgsz < 0)
@@ -665,62 +674,57 @@ asmlinkage long sys_msgrcv (int msqid, struct msgbuf __user *msgp, size_t msgsz,
 	msq = msg_lock(msqid);
 	if(msq==NULL)
 		return -EINVAL;
-retry:
-	err = -EIDRM;
+
+	msg = ERR_PTR(-EIDRM);
 	if (msg_checkid(msq,msqid))
 		goto out_unlock;
 
-	err=-EACCES;
-	if (ipcperms (&msq->q_perm, S_IRUGO))
-		goto out_unlock;
+	for (;;) {
+		struct msg_receiver msr_d;
+		struct list_head* tmp;
 
-	tmp = msq->q_messages.next;
-	found_msg=NULL;
-	while (tmp != &msq->q_messages) {
-		msg = list_entry(tmp,struct msg_msg,m_list);
-		if(testmsg(msg,msgtyp,mode) &&
-		   !security_msg_queue_msgrcv(msq, msg, current, msgtyp, mode)) {
-			found_msg = msg;
-			if(mode == SEARCH_LESSEQUAL && msg->m_type != 1) {
-				found_msg=msg;
-				msgtyp=msg->m_type-1;
-			} else {
-				found_msg=msg;
-				break;
-			}
-		}
-		tmp = tmp->next;
-	}
-	if(found_msg) {
-		msg=found_msg;
-		if ((msgsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) {
-			err=-E2BIG;
+		msg = ERR_PTR(-EACCES);
+		if (ipcperms (&msq->q_perm, S_IRUGO))
 			goto out_unlock;
+
+		msg = ERR_PTR(-EAGAIN);
+		tmp = msq->q_messages.next;
+		while (tmp != &msq->q_messages) {
+			struct msg_msg *walk_msg;
+			walk_msg = list_entry(tmp,struct msg_msg,m_list);
+			if(testmsg(walk_msg,msgtyp,mode) &&
+			   !security_msg_queue_msgrcv(msq, walk_msg, current, msgtyp, mode)) {
+				msg = walk_msg;
+				if(mode == SEARCH_LESSEQUAL && walk_msg->m_type != 1) {
+					msg=walk_msg;
+					msgtyp=walk_msg->m_type-1;
+				} else {
+					msg=walk_msg;
+					break;
+				}
+			}
+			tmp = tmp->next;
 		}
-		list_del(&msg->m_list);
-		msq->q_qnum--;
-		msq->q_rtime = get_seconds();
-		msq->q_lrpid = current->tgid;
-		msq->q_cbytes -= msg->m_ts;
-		atomic_sub(msg->m_ts,&msg_bytes);
-		atomic_dec(&msg_hdrs);
-		ss_wakeup(&msq->q_senders,0);
-		msg_unlock(msq);
-out_success:
-		msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz;
-		if (put_user (msg->m_type, &msgp->mtype) ||
-		    store_msg(msgp->mtext, msg, msgsz)) {
-			    msgsz = -EFAULT;
+		if(!IS_ERR(msg)) {
+			/* Found a suitable message. Unlink it from the queue. */
+			if ((msgsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) {
+				msg = ERR_PTR(-E2BIG);
+				goto out_unlock;
+			}
+			list_del(&msg->m_list);
+			msq->q_qnum--;
+			msq->q_rtime = get_seconds();
+			msq->q_lrpid = current->tgid;
+			msq->q_cbytes -= msg->m_ts;
+			atomic_sub(msg->m_ts,&msg_bytes);
+			atomic_dec(&msg_hdrs);
+			ss_wakeup(&msq->q_senders,0);
+			msg_unlock(msq);
+			break;
 		}
-		free_msg(msg);
-		return msgsz;
-	} else
-	{
-		/* no message waiting. Prepare for pipelined
-		 * receive.
-		 */
+		/* No message waiting. Wait for a message */
 		if (msgflg & IPC_NOWAIT) {
-			err=-ENOMSG;
+			msg = ERR_PTR(-ENOMSG);
 			goto out_unlock;
 		}
 		list_add_tail(&msr_d.r_list,&msq->q_receivers);
@@ -730,52 +734,76 @@ out_success:
 		if(msgflg & MSG_NOERROR)
 			msr_d.r_maxsize = INT_MAX;
 		 else
-		 	msr_d.r_maxsize = msgsz;
+			msr_d.r_maxsize = msgsz;
 		msr_d.r_msg = ERR_PTR(-EAGAIN);
 		current->state = TASK_INTERRUPTIBLE;
 		msg_unlock(msq);
 
 		schedule();
 
-		/*
-		 * The below optimisation is buggy.  A sleeping thread that is
-		 * woken up checks if it got a message and if so, copies it to
-		 * userspace and just returns without taking any locks.
-		 * But this return to user space can be faster than the message
-		 * send, and if the receiver immediately exits the
-		 * wake_up_process performed by the sender will oops.
+		/* Lockless receive, part 1:
+		 * Disable preemption.  We don't hold a reference to the queue
+		 * and getting a reference would defeat the idea of a lockless
+		 * operation, thus the code relies on rcu to guarantee the
+		 * existance of msq:
+		 * Prior to destruction, expunge_all(-EIRDM) changes r_msg.
+		 * Thus if r_msg is -EAGAIN, then the queue not yet destroyed.
+		 * rcu_read_lock() prevents preemption between reading r_msg
+		 * and the spin_lock() inside ipc_lock_by_ptr().
+		 */
+		rcu_read_lock();
+
+		/* Lockless receive, part 2:
+		 * Wait until pipelined_send or expunge_all are outside of
+		 * wake_up_process(). There is a race with exit(), see
+		 * ipc/mqueue.c for the details.
 		 */
-#if 0
 		msg = (struct msg_msg*) msr_d.r_msg;
-		if(!IS_ERR(msg)) 
-			goto out_success;
-#endif
+		while (msg == NULL) {
+			cpu_relax();
+			msg = (struct msg_msg*) msr_d.r_msg;
+		}
 
-		msq = msg_lock(msqid);
-		msg = (struct msg_msg*)msr_d.r_msg;
-		if(!IS_ERR(msg)) {
-			/* our message arived while we waited for
-			 * the spinlock. Process it.
-			 */
-			if(msq)
-				msg_unlock(msq);
-			goto out_success;
+		/* Lockless receive, part 3:
+		 * If there is a message or an error then accept it without
+		 * locking.
+		 */
+		if(msg != ERR_PTR(-EAGAIN)) {
+			rcu_read_unlock();
+			break;
 		}
-		err = PTR_ERR(msg);
-		if(err == -EAGAIN) {
-			if(!msq)
-				BUG();
-			list_del(&msr_d.r_list);
-			if (signal_pending(current))
-				err=-EINTR;
-			 else
-				goto retry;
+
+		/* Lockless receive, part 3:
+		 * Acquire the queue spinlock.
+		 */
+		ipc_lock_by_ptr(&msq->q_perm);
+		rcu_read_unlock();
+
+		/* Lockless receive, part 4:
+		 * Repeat test after acquiring the spinlock.
+		 */
+		msg = (struct msg_msg*)msr_d.r_msg;
+		if(msg != ERR_PTR(-EAGAIN))
+			goto out_unlock;
+
+		list_del(&msr_d.r_list);
+		if (signal_pending(current)) {
+			msg = ERR_PTR(-ERESTARTNOHAND);
+out_unlock:
+			msg_unlock(msq);
+			break;
 		}
 	}
-out_unlock:
-	if(msq)
-		msg_unlock(msq);
-	return err;
+	if (IS_ERR(msg))
+       		return PTR_ERR(msg);
+
+	msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz;
+	if (put_user (msg->m_type, &msgp->mtype) ||
+	    store_msg(msgp->mtext, msg, msgsz)) {
+		    msgsz = -EFAULT;
+	}
+	free_msg(msg);
+	return msgsz;
 }
 
 #ifdef CONFIG_PROC_FS
@@ -794,7 +822,7 @@ static int sysvipc_msg_read_proc(char *buffer, char **start, off_t offset, int l
 		if (msq) {
 			if (!vx_check(msq->q_perm.xid, VX_IDENT)) {
 				msg_unlock(msq);
-				continue;	
+				continue;
 			}
 			len += sprintf(buffer + len, "%10d %10d  %4o  %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n",
 				msq->q_perm.key,
diff --git a/ipc/sem.c b/ipc/sem.c
index 71936c913..b1bd0af67 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -182,14 +182,14 @@ static int newary (key_t key, int nsems, int semflg)
 	sma->sem_perm.security = NULL;
 	retval = security_sem_alloc(sma);
 	if (retval) {
-		ipc_rcu_free(sma, size);
+		ipc_rcu_putref(sma);
 		return retval;
 	}
 
 	id = ipc_addid(&sem_ids, &sma->sem_perm, sc_semmni);
 	if(id == -1) {
 		security_sem_free(sma);
-		ipc_rcu_free(sma, size);
+		ipc_rcu_putref(sma);
 		return -ENOSPC;
 	}
 	used_sems += nsems;
@@ -244,25 +244,6 @@ asmlinkage long sys_semget (key_t key, int nsems, int semflg)
 	return err;
 }
 
-/* doesn't acquire the sem_lock on error! */
-static int sem_revalidate(int semid, struct sem_array* sma, int nsems, short flg)
-{
-	struct sem_array* smanew;
-
-	smanew = sem_lock(semid);
-	if(smanew==NULL)
-		return -EIDRM;
-	if(smanew != sma || sem_checkid(sma,semid) || sma->sem_nsems != nsems) {
-		sem_unlock(smanew);
-		return -EIDRM;
-	}
-
-	if (flg && ipcperms(&sma->sem_perm, flg)) {
-		sem_unlock(smanew);
-		return -EACCES;
-	}
-	return 0;
-}
 /* Manage the doubly linked list sma->sem_pending as a FIFO:
  * insert new queue elements at the tail sma->sem_pending_last.
  */
@@ -476,7 +457,7 @@ static void freeary (struct sem_array *sma, int id)
 	used_sems -= sma->sem_nsems;
 	size = sizeof (*sma) + sma->sem_nsems * sizeof (struct sem);
 	security_sem_free(sma);
-	ipc_rcu_free(sma, size);
+	ipc_rcu_putref(sma);
 }
 
 static unsigned long copy_semid_to_user(void __user *buf, struct semid64_ds *in, int version)
@@ -617,13 +598,24 @@ static int semctl_main(int semid, int semnum, int cmd, int version, union semun
 		int i;
 
 		if(nsems > SEMMSL_FAST) {
+			ipc_rcu_getref(sma);
 			sem_unlock(sma);			
+
 			sem_io = ipc_alloc(sizeof(ushort)*nsems);
-			if(sem_io == NULL)
+			if(sem_io == NULL) {
+				ipc_lock_by_ptr(&sma->sem_perm);
+				ipc_rcu_putref(sma);
+				sem_unlock(sma);
 				return -ENOMEM;
-			err = sem_revalidate(semid, sma, nsems, S_IRUGO);
-			if(err)
+			}
+
+			ipc_lock_by_ptr(&sma->sem_perm);
+			ipc_rcu_putref(sma);
+			if (sma->sem_perm.deleted) {
+				sem_unlock(sma);
+				err = -EIDRM;
 				goto out_free;
+			}
 		}
 
 		for (i = 0; i < sma->sem_nsems; i++)
@@ -639,28 +631,43 @@ static int semctl_main(int semid, int semnum, int cmd, int version, union semun
 		int i;
 		struct sem_undo *un;
 
+		ipc_rcu_getref(sma);
 		sem_unlock(sma);
 
 		if(nsems > SEMMSL_FAST) {
 			sem_io = ipc_alloc(sizeof(ushort)*nsems);
-			if(sem_io == NULL)
+			if(sem_io == NULL) {
+				ipc_lock_by_ptr(&sma->sem_perm);
+				ipc_rcu_putref(sma);
+				sem_unlock(sma);
 				return -ENOMEM;
+			}
 		}
 
 		if (copy_from_user (sem_io, arg.array, nsems*sizeof(ushort))) {
+			ipc_lock_by_ptr(&sma->sem_perm);
+			ipc_rcu_putref(sma);
+			sem_unlock(sma);
 			err = -EFAULT;
 			goto out_free;
 		}
 
 		for (i = 0; i < nsems; i++) {
 			if (sem_io[i] > SEMVMX) {
+				ipc_lock_by_ptr(&sma->sem_perm);
+				ipc_rcu_putref(sma);
+				sem_unlock(sma);
 				err = -ERANGE;
 				goto out_free;
 			}
 		}
-		err = sem_revalidate(semid, sma, nsems, S_IWUGO);
-		if(err)
+		ipc_lock_by_ptr(&sma->sem_perm);
+		ipc_rcu_putref(sma);
+		if (sma->sem_perm.deleted) {
+			sem_unlock(sma);
+			err = -EIDRM;
 			goto out_free;
+		}
 
 		for (i = 0; i < nsems; i++)
 			sma->sem_base[i].semval = sem_io[i];
@@ -980,11 +987,16 @@ static struct sem_undo *find_undo(int semid)
 		goto out;
 	}
 	nsems = sma->sem_nsems;
+	ipc_rcu_getref(sma);
 	sem_unlock(sma);
 
 	new = (struct sem_undo *) kmalloc(sizeof(struct sem_undo) + sizeof(short)*nsems, GFP_KERNEL);
-	if (!new)
+	if (!new) {
+		ipc_lock_by_ptr(&sma->sem_perm);
+		ipc_rcu_putref(sma);
+		sem_unlock(sma);
 		return ERR_PTR(-ENOMEM);
+	}
 	memset(new, 0, sizeof(struct sem_undo) + sizeof(short)*nsems);
 	new->semadj = (short *) &new[1];
 	new->semid = semid;
@@ -994,13 +1006,18 @@ static struct sem_undo *find_undo(int semid)
 	if (un) {
 		unlock_semundo();
 		kfree(new);
+		ipc_lock_by_ptr(&sma->sem_perm);
+		ipc_rcu_putref(sma);
+		sem_unlock(sma);
 		goto out;
 	}
-	error = sem_revalidate(semid, sma, nsems, 0);
-	if (error) {
+	ipc_lock_by_ptr(&sma->sem_perm);
+	ipc_rcu_putref(sma);
+	if (sma->sem_perm.deleted) {
+		sem_unlock(sma);
 		unlock_semundo();
 		kfree(new);
-		un = ERR_PTR(error);
+		un = ERR_PTR(-EIDRM);
 		goto out;
 	}
 	new->proc_next = ulp->proc_list;
@@ -1272,8 +1289,23 @@ found:
 			struct sem * sem = &sma->sem_base[i];
 			if (u->semadj[i]) {
 				sem->semval += u->semadj[i];
+				/*
+				 * Range checks of the new semaphore value,
+				 * not defined by sus:
+				 * - Some unices ignore the undo entirely
+				 *   (e.g. HP UX 11i 11.22, Tru64 V5.1)
+				 * - some cap the value (e.g. FreeBSD caps
+				 *   at 0, but doesn't enforce SEMVMX)
+				 *
+				 * Linux caps the semaphore value, both at 0
+				 * and at SEMVMX.
+				 *
+				 * 	Manfred <manfred@colorfullife.com>
+				 */
 				if (sem->semval < 0)
-					sem->semval = 0; /* shouldn't happen */
+					sem->semval = 0;
+				if (sem->semval > SEMVMX)
+					sem->semval = SEMVMX;
 				sem->sempid = current->tgid;
 			}
 		}
diff --git a/ipc/shm.c b/ipc/shm.c
index 62c5393bb..54a50c29d 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -80,7 +80,7 @@ static inline struct shmid_kernel *shm_rmid(int id)
 
 static inline int shm_addid(struct shmid_kernel *shp)
 {
-	return ipc_addid(&shm_ids, &shp->shm_perm, shm_ctlmni+1);
+	return ipc_addid(&shm_ids, &shp->shm_perm, shm_ctlmni);
 }
 
 
@@ -116,10 +116,13 @@ static void shm_destroy (struct shmid_kernel *shp)
 	shm_rmid (shp->id);
 	shm_unlock(shp);
 	if (!is_file_hugepages(shp->shm_file))
-		shmem_lock(shp->shm_file, 0);
+		shmem_lock(shp->shm_file, 0, shp->mlock_user);
+	else
+		user_shm_unlock(shp->shm_file->f_dentry->d_inode->i_size,
+						shp->mlock_user);
 	fput (shp->shm_file);
 	security_shm_free(shp);
-	ipc_rcu_free(shp, sizeof(struct shmid_kernel));
+	ipc_rcu_putref(shp);
 }
 
 /*
@@ -193,17 +196,20 @@ static int newseg (key_t key, int shmflg, size_t size)
 	shp->shm_perm.key = key;
 	shp->shm_perm.xid = current->xid;
 	shp->shm_flags = (shmflg & S_IRWXUGO);
+	shp->mlock_user = NULL;
 
 	shp->shm_perm.security = NULL;
 	error = security_shm_alloc(shp);
 	if (error) {
-		ipc_rcu_free(shp, sizeof(*shp));
+		ipc_rcu_putref(shp);
 		return error;
 	}
 
-	if (shmflg & SHM_HUGETLB)
+	if (shmflg & SHM_HUGETLB) {
+		/* hugetlb_zero_setup takes care of mlock user accounting */
 		file = hugetlb_zero_setup(size);
-	else {
+		shp->mlock_user = current->user;
+	} else {
 		sprintf (name, "SYSV%08x", key);
 		file = shmem_file_setup(name, size, VM_ACCOUNT);
 	}
@@ -237,7 +243,7 @@ no_id:
 	fput(file);
 no_file:
 	security_shm_free(shp);
-	ipc_rcu_free(shp, sizeof(*shp));
+	ipc_rcu_putref(shp);
 	return error;
 }
 
@@ -507,14 +513,11 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
 	case SHM_LOCK:
 	case SHM_UNLOCK:
 	{
-/* Allow superuser to lock segment in memory */
-/* Should the pages be faulted in here or leave it to user? */
-/* need to determine interaction with current->swappable */
-		if (!capable(CAP_IPC_LOCK)) {
+		/* Allow superuser to lock segment in memory */
+		if (!can_do_mlock() && cmd == SHM_LOCK) {
 			err = -EPERM;
 			goto out;
 		}
-
 		shp = shm_lock(shmid);
 		if(shp==NULL) {
 			err = -EINVAL;
@@ -529,13 +532,18 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
 			goto out_unlock;
 		
 		if(cmd==SHM_LOCK) {
-			if (!is_file_hugepages(shp->shm_file))
-				shmem_lock(shp->shm_file, 1);
-			shp->shm_flags |= SHM_LOCKED;
-		} else {
-			if (!is_file_hugepages(shp->shm_file))
-				shmem_lock(shp->shm_file, 0);
+			struct user_struct * user = current->user;
+			if (!is_file_hugepages(shp->shm_file)) {
+				err = shmem_lock(shp->shm_file, 1, user);
+				if (!err) {
+					shp->shm_flags |= SHM_LOCKED;
+					shp->mlock_user = user;
+				}
+			}
+		} else if (!is_file_hugepages(shp->shm_file)) {
+			shmem_lock(shp->shm_file, 0, shp->mlock_user);
 			shp->shm_flags &= ~SHM_LOCKED;
+			shp->mlock_user = NULL;
 		}
 		shm_unlock(shp);
 		goto out;
@@ -683,6 +691,10 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
 		o_flags = O_RDWR;
 		acc_mode = S_IRUGO | S_IWUGO;
 	}
+	if (shmflg & SHM_EXEC) {
+		prot |= PROT_EXEC;
+		acc_mode |= S_IXUGO;
+	}
 
 	/*
 	 * We cannot rely on the fs check since SYSV IPC does have an
@@ -857,7 +869,7 @@ static int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int l
 
 			if (!vx_check(shp->shm_perm.xid, VX_IDENT)) {
 				shm_unlock(shp);
-				continue;	
+				continue;
 			}
 			if (sizeof(size_t) <= sizeof(int))
 				format = SMALL_STRING;
diff --git a/ipc/util.c b/ipc/util.c
index d84ac5198..b9f02e961 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -101,7 +101,7 @@ int ipc_findkey(struct ipc_ids* ids, key_t key)
 	int max_id = ids->max_id;
 
 	/*
-	 * read_barrier_depends is not needed here
+	 * rcu_dereference() is not needed here
 	 * since ipc_ids.sem is held
 	 */
 	for (id = 0; id <= max_id; id++) {
@@ -109,7 +109,7 @@ int ipc_findkey(struct ipc_ids* ids, key_t key)
 		if (p==NULL)
 			continue;
 		if (!vx_check(p->xid, VX_IDENT))
-			continue;	
+			continue;
 		if (key == p->key)
 			return id;
 	}
@@ -138,7 +138,6 @@ static int grow_ary(struct ipc_ids* ids, int newsize)
 		new[i].p = NULL;
 	}
 	old = ids->entries;
-	i = ids->size;
 
 	/*
 	 * before setting the ids->entries to the new array, there must be a
@@ -150,7 +149,7 @@ static int grow_ary(struct ipc_ids* ids, int newsize)
 	smp_wmb();	/* prevent indexing into old array based on new size. */
 	ids->size = newsize;
 
-	ipc_rcu_free(old, sizeof(struct ipc_id)*i);
+	ipc_rcu_putref(old);
 	return ids->size;
 }
 
@@ -175,7 +174,7 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
 	size = grow_ary(ids,size);
 
 	/*
-	 * read_barrier_depends() is not needed here since
+	 * rcu_dereference()() is not needed here since
 	 * ipc_ids.sem is held
 	 */
 	for (id = 0; id < size; id++) {
@@ -224,7 +223,7 @@ struct kern_ipc_perm* ipc_rmid(struct ipc_ids* ids, int id)
 		BUG();
 
 	/* 
-	 * do not need a read_barrier_depends() here to force ordering
+	 * do not need a rcu_dereference()() here to force ordering
 	 * on Alpha, since the ipc_ids.sem is held.
 	 */	
 	p = ids->entries[lid].p;
@@ -280,25 +279,47 @@ void ipc_free(void* ptr, int size)
 		kfree(ptr);
 }
 
-struct ipc_rcu_kmalloc
+/*
+ * rcu allocations:
+ * There are three headers that are prepended to the actual allocation:
+ * - during use: ipc_rcu_hdr.
+ * - during the rcu grace period: ipc_rcu_grace.
+ * - [only if vmalloc]: ipc_rcu_sched.
+ * Their lifetime doesn't overlap, thus the headers share the same memory.
+ * Unlike a normal union, they are right-aligned, thus some container_of
+ * forward/backward casting is necessary:
+ */
+struct ipc_rcu_hdr
+{
+	int refcount;
+	int is_vmalloc;
+	void *data[0];
+};
+
+
+struct ipc_rcu_grace
 {
 	struct rcu_head rcu;
 	/* "void *" makes sure alignment of following data is sane. */
 	void *data[0];
 };
 
-struct ipc_rcu_vmalloc
+struct ipc_rcu_sched
 {
-	struct rcu_head rcu;
 	struct work_struct work;
 	/* "void *" makes sure alignment of following data is sane. */
 	void *data[0];
 };
 
+#define HDRLEN_KMALLOC		(sizeof(struct ipc_rcu_grace) > sizeof(struct ipc_rcu_hdr) ? \
+					sizeof(struct ipc_rcu_grace) : sizeof(struct ipc_rcu_hdr))
+#define HDRLEN_VMALLOC		(sizeof(struct ipc_rcu_sched) > HDRLEN_KMALLOC ? \
+					sizeof(struct ipc_rcu_sched) : HDRLEN_KMALLOC)
+
 static inline int rcu_use_vmalloc(int size)
 {
 	/* Too big for a single page? */
-	if (sizeof(struct ipc_rcu_kmalloc) + size > PAGE_SIZE)
+	if (HDRLEN_KMALLOC + size > PAGE_SIZE)
 		return 1;
 	return 0;
 }
@@ -320,16 +341,29 @@ void* ipc_rcu_alloc(int size)
 	 * workqueue if necessary (for vmalloc). 
 	 */
 	if (rcu_use_vmalloc(size)) {
-		out = vmalloc(sizeof(struct ipc_rcu_vmalloc) + size);
-		if (out) out += sizeof(struct ipc_rcu_vmalloc);
+		out = vmalloc(HDRLEN_VMALLOC + size);
+		if (out) {
+			out += HDRLEN_VMALLOC;
+			container_of(out, struct ipc_rcu_hdr, data)->is_vmalloc = 1;
+			container_of(out, struct ipc_rcu_hdr, data)->refcount = 1;
+		}
 	} else {
-		out = kmalloc(sizeof(struct ipc_rcu_kmalloc)+size, GFP_KERNEL);
-		if (out) out += sizeof(struct ipc_rcu_kmalloc);
+		out = kmalloc(HDRLEN_KMALLOC + size, GFP_KERNEL);
+		if (out) {
+			out += HDRLEN_KMALLOC;
+			container_of(out, struct ipc_rcu_hdr, data)->is_vmalloc = 0;
+			container_of(out, struct ipc_rcu_hdr, data)->refcount = 1;
+		}
 	}
 
 	return out;
 }
 
+void ipc_rcu_getref(void *ptr)
+{
+	container_of(ptr, struct ipc_rcu_hdr, data)->refcount++;
+}
+
 /**
  *	ipc_schedule_free	- free ipc + rcu space
  * 
@@ -338,11 +372,13 @@ void* ipc_rcu_alloc(int size)
  */
 static void ipc_schedule_free(struct rcu_head *head)
 {
-	struct ipc_rcu_vmalloc *free =
-		container_of(head, struct ipc_rcu_vmalloc, rcu);
+	struct ipc_rcu_grace *grace =
+		container_of(head, struct ipc_rcu_grace, rcu);
+	struct ipc_rcu_sched *sched =
+			container_of(&(grace->data[0]), struct ipc_rcu_sched, data[0]);
 
-	INIT_WORK(&free->work, vfree, free);
-	schedule_work(&free->work);
+	INIT_WORK(&sched->work, vfree, sched);
+	schedule_work(&sched->work);
 }
 
 /**
@@ -353,25 +389,23 @@ static void ipc_schedule_free(struct rcu_head *head)
  */
 static void ipc_immediate_free(struct rcu_head *head)
 {
-	struct ipc_rcu_kmalloc *free =
-		container_of(head, struct ipc_rcu_kmalloc, rcu);
+	struct ipc_rcu_grace *free =
+		container_of(head, struct ipc_rcu_grace, rcu);
 	kfree(free);
 }
 
-
-
-void ipc_rcu_free(void* ptr, int size)
+void ipc_rcu_putref(void *ptr)
 {
-	if (rcu_use_vmalloc(size)) {
-		struct ipc_rcu_vmalloc *free;
-		free = ptr - sizeof(*free);
-		call_rcu(&free->rcu, ipc_schedule_free);
+	if (--container_of(ptr, struct ipc_rcu_hdr, data)->refcount > 0)
+		return;
+
+	if (container_of(ptr, struct ipc_rcu_hdr, data)->is_vmalloc) {
+		call_rcu(&container_of(ptr, struct ipc_rcu_grace, data)->rcu,
+				ipc_schedule_free);
 	} else {
-		struct ipc_rcu_kmalloc *free;
-		free = ptr - sizeof(*free);
-		call_rcu(&free->rcu, ipc_immediate_free);
+		call_rcu(&container_of(ptr, struct ipc_rcu_grace, data)->rcu,
+				ipc_immediate_free);
 	}
-
 }
 
 /**
@@ -486,13 +520,12 @@ struct kern_ipc_perm* ipc_lock(struct ipc_ids* ids, int id)
 	 * Note: The following two read barriers are corresponding
 	 * to the two write barriers in grow_ary(). They guarantee 
 	 * the writes are seen in the same order on the read side. 
-	 * smp_rmb() has effect on all CPUs.  read_barrier_depends() 
+	 * smp_rmb() has effect on all CPUs.  rcu_dereference()
 	 * is used if there are data dependency between two reads, and 
 	 * has effect only on Alpha.
 	 */
 	smp_rmb(); /* prevent indexing old array with new size */
-	entries = ids->entries;
-	read_barrier_depends(); /*prevent seeing new array unitialized */
+	entries = rcu_dereference(ids->entries);
 	out = entries[lid].p;
 	if(out == NULL) {
 		rcu_read_unlock();
@@ -511,6 +544,12 @@ struct kern_ipc_perm* ipc_lock(struct ipc_ids* ids, int id)
 	return out;
 }
 
+void ipc_lock_by_ptr(struct kern_ipc_perm *perm)
+{
+	rcu_read_lock();
+	spin_lock(&perm->lock);
+}
+
 void ipc_unlock(struct kern_ipc_perm* perm)
 {
 	spin_unlock(&perm->lock);
diff --git a/ipc/util.h b/ipc/util.h
index 8697df67b..3b3adb2d5 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -45,14 +45,20 @@ int ipcperms (struct kern_ipc_perm *ipcp, short flg);
  */
 void* ipc_alloc(int size);
 void ipc_free(void* ptr, int size);
-/* for allocation that need to be freed by RCU
- * both function can sleep
+
+/*
+ * For allocation that need to be freed by RCU.
+ * Objects are reference counted, they start with reference count 1.
+ * getref increases the refcount, the putref call that reduces the recount
+ * to 0 schedules the rcu destruction. Caller must guarantee locking.
  */
 void* ipc_rcu_alloc(int size);
-void ipc_rcu_free(void* arg, int size);
+void ipc_rcu_getref(void *ptr);
+void ipc_rcu_putref(void *ptr);
 
 struct kern_ipc_perm* ipc_get(struct ipc_ids* ids, int id);
 struct kern_ipc_perm* ipc_lock(struct ipc_ids* ids, int id);
+void ipc_lock_by_ptr(struct kern_ipc_perm *ipcp);
 void ipc_unlock(struct kern_ipc_perm* perm);
 int ipc_buildid(struct ipc_ids* ids, int id, int seq);
 int ipc_checkid(struct ipc_ids* ids, struct kern_ipc_perm* ipcp, int uid);
diff --git a/kernel/Makefile b/kernel/Makefile
index e56906d36..c978df7c5 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -16,7 +16,7 @@ obj-y	  += vserver/vserver.o
 
 obj-$(CONFIG_FUTEX) += futex.o
 obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
-obj-$(CONFIG_SMP) += cpu.o
+obj-$(CONFIG_SMP) += cpu.o spinlock.o
 obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_MODULES) += module.o
 obj-$(CONFIG_KALLSYMS) += kallsyms.o
@@ -28,6 +28,7 @@ obj-$(CONFIG_IKCONFIG_PROC) += configs.o
 obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
 obj-$(CONFIG_AUDIT) += audit.o
 obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
+obj-$(CONFIG_KPROBES) += kprobes.o
 
 ifneq ($(CONFIG_IA64),y)
 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
diff --git a/kernel/acct.c b/kernel/acct.c
index daf23c4ef..fb6989a34 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -384,6 +384,8 @@ static void do_acct_process(long exitcode, struct file *file)
 	unsigned long vsize;
 	unsigned long flim;
 	u64 elapsed;
+	u64 run_time;
+	struct timespec uptime;
 
 	/*
 	 * First check to see if there is enough free_space to continue
@@ -401,7 +403,13 @@ static void do_acct_process(long exitcode, struct file *file)
 	ac.ac_version = ACCT_VERSION | ACCT_BYTEORDER;
 	strlcpy(ac.ac_comm, current->comm, sizeof(ac.ac_comm));
 
-	elapsed = jiffies_64_to_AHZ(get_jiffies_64() - current->start_time);
+	/* calculate run_time in nsec*/
+	do_posix_clock_monotonic_gettime(&uptime);
+	run_time = (u64)uptime.tv_sec*NSEC_PER_SEC + uptime.tv_nsec;
+	run_time -= (u64)current->start_time.tv_sec*NSEC_PER_SEC
+					+ current->start_time.tv_nsec;
+	/* convert nsec -> AHZ */
+	elapsed = nsec_to_AHZ(run_time);
 #if ACCT_VERSION==3
 	ac.ac_etime = encode_float(elapsed);
 #else
diff --git a/kernel/audit.c b/kernel/audit.c
index 765822b03..d813b7aa4 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -708,7 +708,7 @@ void audit_log_d_path(struct audit_buffer *ab, const char *prefix,
 		audit_log_move(ab);
 	avail = sizeof(ab->tmp) - ab->len;
 	p = d_path(dentry, vfsmnt, ab->tmp + ab->len, avail);
-	if (p == ERR_PTR(-ENAMETOOLONG)) {
+	if (IS_ERR(p)) {
 		/* FIXME: can we save some information here? */
 		audit_log_format(ab, "<toolong>");
 	} else {
@@ -810,16 +810,3 @@ void audit_log(struct audit_context *ctx, const char *fmt, ...)
 		audit_log_end(ab);
 	}
 }
-
-EXPORT_SYMBOL_GPL(audit_set_rate_limit);
-EXPORT_SYMBOL_GPL(audit_set_backlog_limit);
-EXPORT_SYMBOL_GPL(audit_set_enabled);
-EXPORT_SYMBOL_GPL(audit_set_failure);
-
-EXPORT_SYMBOL_GPL(audit_log_start);
-EXPORT_SYMBOL_GPL(audit_log_format);
-EXPORT_SYMBOL_GPL(audit_log_end_irq);
-EXPORT_SYMBOL_GPL(audit_log_end_fast);
-EXPORT_SYMBOL_GPL(audit_log_end);
-EXPORT_SYMBOL_GPL(audit_log);
-EXPORT_SYMBOL_GPL(audit_log_d_path);
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index e688c73f6..0962944e8 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -857,6 +857,7 @@ void audit_putname(const char *name)
 	}
 #endif
 }
+EXPORT_SYMBOL(audit_putname);
 
 /* Store the inode and device from a lookup.  Called from
  * fs/namei.c:path_lookup(). */
@@ -913,11 +914,3 @@ int audit_set_loginuid(struct audit_context *ctx, uid_t loginuid)
 	}
 	return 0;
 }
-
-EXPORT_SYMBOL_GPL(audit_alloc);
-EXPORT_SYMBOL_GPL(audit_free);
-EXPORT_SYMBOL_GPL(audit_syscall_entry);
-EXPORT_SYMBOL_GPL(audit_syscall_exit);
-EXPORT_SYMBOL_GPL(audit_getname);
-EXPORT_SYMBOL_GPL(audit_putname);
-EXPORT_SYMBOL_GPL(audit_inode);
diff --git a/kernel/capability.c b/kernel/capability.c
index 1c5c35718..7d419fd58 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -10,6 +10,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/security.h>
+#include <linux/vs_cvirt.h>
 #include <asm/uaccess.h>
 
 unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */
@@ -89,14 +90,12 @@ static inline void cap_set_pg(int pgrp, kernel_cap_t *effective,
 			      kernel_cap_t *permitted)
 {
 	task_t *g, *target;
-	struct list_head *l;
-	struct pid *pid;
 
-	for_each_task_pid(pgrp, PIDTYPE_PGID, g, l, pid) {
+	do_each_task_pid(pgrp, PIDTYPE_PGID, g) {
 		target = g;
 		while_each_thread(g, target)
 			security_capset_set(target, effective, inheritable, permitted);
-	}
+	} while_each_task_pid(pgrp, PIDTYPE_PGID, g);
 }
 
 /*
diff --git a/kernel/compat.c b/kernel/compat.c
index 481ac0d4b..33880d224 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -160,10 +160,39 @@ asmlinkage long compat_sys_times(struct compat_tms __user *tbuf)
 	 */
 	if (tbuf) {
 		struct compat_tms tmp;
-		tmp.tms_utime = compat_jiffies_to_clock_t(current->utime);
-		tmp.tms_stime = compat_jiffies_to_clock_t(current->stime);
-		tmp.tms_cutime = compat_jiffies_to_clock_t(current->cutime);
-		tmp.tms_cstime = compat_jiffies_to_clock_t(current->cstime);
+		struct task_struct *tsk = current;
+		struct task_struct *t;
+		unsigned long utime, stime, cutime, cstime;
+
+		read_lock(&tasklist_lock);
+		utime = tsk->signal->utime;
+		stime = tsk->signal->stime;
+		t = tsk;
+		do {
+			utime += t->utime;
+			stime += t->stime;
+			t = next_thread(t);
+		} while (t != tsk);
+
+		/*
+		 * While we have tasklist_lock read-locked, no dying thread
+		 * can be updating current->signal->[us]time.  Instead,
+		 * we got their counts included in the live thread loop.
+		 * However, another thread can come in right now and
+		 * do a wait call that updates current->signal->c[us]time.
+		 * To make sure we always see that pair updated atomically,
+		 * we take the siglock around fetching them.
+		 */
+		spin_lock_irq(&tsk->sighand->siglock);
+		cutime = tsk->signal->cutime;
+		cstime = tsk->signal->cstime;
+		spin_unlock_irq(&tsk->sighand->siglock);
+		read_unlock(&tasklist_lock);
+
+		tmp.tms_utime = compat_jiffies_to_clock_t(utime);
+		tmp.tms_stime = compat_jiffies_to_clock_t(stime);
+		tmp.tms_cutime = compat_jiffies_to_clock_t(cutime);
+		tmp.tms_cstime = compat_jiffies_to_clock_t(cstime);
 		if (copy_to_user(tbuf, &tmp, sizeof(tmp)))
 			return -EFAULT;
 	}
@@ -310,7 +339,7 @@ asmlinkage long compat_sys_getrlimit (unsigned int resource,
 	return ret;
 }
 
-static long put_compat_rusage(struct compat_rusage __user *ru, struct rusage *r)
+int put_compat_rusage(const struct rusage *r, struct compat_rusage __user *ru)
 {
 	if (!access_ok(VERIFY_WRITE, ru, sizeof(*ru)) ||
 	    __put_user(r->ru_utime.tv_sec, &ru->ru_utime.tv_sec) ||
@@ -348,7 +377,7 @@ asmlinkage long compat_sys_getrusage(int who, struct compat_rusage __user *ru)
 	if (ret)
 		return ret;
 
-	if (put_compat_rusage(ru, &r))
+	if (put_compat_rusage(&r, ru))
 		return -EFAULT;
 
 	return 0;
@@ -374,7 +403,7 @@ compat_sys_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options,
 		set_fs (old_fs);
 
 		if (ret > 0) {
-			if (put_compat_rusage(ru, &r)) 
+			if (put_compat_rusage(&r, ru))
 				return -EFAULT;
 			if (stat_addr && put_user(status, stat_addr))
 				return -EFAULT;
@@ -383,48 +412,58 @@ compat_sys_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options,
 	}
 }
 
-asmlinkage long compat_sys_sched_setaffinity(compat_pid_t pid, 
+static int compat_get_user_cpu_mask(compat_ulong_t __user *user_mask_ptr,
+				    unsigned len, cpumask_t *new_mask)
+{
+	unsigned long *k;
+
+	if (len < sizeof(cpumask_t))
+		memset(new_mask, 0, sizeof(cpumask_t));
+	else if (len > sizeof(cpumask_t))
+		len = sizeof(cpumask_t);
+
+	k = cpus_addr(*new_mask);
+	return compat_get_bitmap(k, user_mask_ptr, len * 8);
+}
+
+asmlinkage long compat_sys_sched_setaffinity(compat_pid_t pid,
 					     unsigned int len,
 					     compat_ulong_t __user *user_mask_ptr)
 {
-	unsigned long kern_mask;
-	mm_segment_t old_fs;
-	int ret;
+	cpumask_t new_mask;
+	int retval;
 
-	if (get_user(kern_mask, user_mask_ptr))
-		return -EFAULT;
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_sched_setaffinity(pid,
-				    sizeof(kern_mask),
-				    (unsigned long __user *) &kern_mask);
-	set_fs(old_fs);
+	retval = compat_get_user_cpu_mask(user_mask_ptr, len, &new_mask);
+	if (retval)
+		return retval;
 
-	return ret;
+	return sched_setaffinity(pid, new_mask);
 }
 
 asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len,
 					     compat_ulong_t __user *user_mask_ptr)
 {
-	unsigned long kern_mask;
-	mm_segment_t old_fs;
 	int ret;
+	cpumask_t mask;
+	unsigned long *k;
+	unsigned int min_length = sizeof(cpumask_t);
 
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = sys_sched_getaffinity(pid,
-				    sizeof(kern_mask),
-				    (unsigned long __user *) &kern_mask);
-	set_fs(old_fs);
+	if (NR_CPUS <= BITS_PER_COMPAT_LONG)
+		min_length = sizeof(compat_ulong_t);
 
-	if (ret > 0) {
-		ret = sizeof(compat_ulong_t);
-		if (put_user(kern_mask, user_mask_ptr))
-			return -EFAULT;
-	}
+	if (len < min_length)
+		return -EINVAL;
 
-	return ret;
+	ret = sched_getaffinity(pid, &mask);
+	if (ret < 0)
+		return ret;
+
+	k = cpus_addr(mask);
+	ret = compat_put_bitmap(user_mask_ptr, k, min_length * 8);
+	if (ret)
+		return ret;
+
+	return min_length;
 }
 
 static int get_compat_itimerspec(struct itimerspec *dst, 
@@ -561,3 +600,83 @@ long compat_clock_nanosleep(clockid_t which_clock, int flags,
 
 /* timer_create is architecture specific because it needs sigevent conversion */
 
+long compat_get_bitmap(unsigned long *mask, compat_ulong_t __user *umask,
+		       unsigned long bitmap_size)
+{
+	int i, j;
+	unsigned long m;
+	compat_ulong_t um;
+	unsigned long nr_compat_longs;
+
+	/* align bitmap up to nearest compat_long_t boundary */
+	bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);
+
+	if (verify_area(VERIFY_READ, umask, bitmap_size / 8))
+		return -EFAULT;
+
+	nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
+
+	for (i = 0; i < BITS_TO_LONGS(bitmap_size); i++) {
+		m = 0;
+
+		for (j = 0; j < sizeof(m)/sizeof(um); j++) {
+			/*
+			 * We dont want to read past the end of the userspace
+			 * bitmap. We must however ensure the end of the
+			 * kernel bitmap is zeroed.
+			 */
+			if (nr_compat_longs-- > 0) {
+				if (__get_user(um, umask))
+					return -EFAULT;
+			} else {
+				um = 0;
+			}
+
+			umask++;
+			m |= (long)um << (j * BITS_PER_COMPAT_LONG);
+		}
+		*mask++ = m;
+	}
+
+	return 0;
+}
+
+long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
+		       unsigned long bitmap_size)
+{
+	int i, j;
+	unsigned long m;
+	compat_ulong_t um;
+	unsigned long nr_compat_longs;
+
+	/* align bitmap up to nearest compat_long_t boundary */
+	bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);
+
+	if (verify_area(VERIFY_WRITE, umask, bitmap_size / 8))
+		return -EFAULT;
+
+	nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
+
+	for (i = 0; i < BITS_TO_LONGS(bitmap_size); i++) {
+		m = *mask++;
+
+		for (j = 0; j < sizeof(m)/sizeof(um); j++) {
+			um = m;
+
+			/*
+			 * We dont want to write past the end of the userspace
+			 * bitmap.
+			 */
+			if (nr_compat_longs-- > 0) {
+				if (__put_user(um, umask))
+					return -EFAULT;
+			}
+
+			umask++;
+			m >>= 4*sizeof(um);
+			m >>= 4*sizeof(um);
+		}
+	}
+
+	return 0;
+}
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 083521327..64b8ed3cc 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -61,13 +61,13 @@ static inline void check_for_tasks(int cpu)
  * cpu' with certain environment variables set.  */
 static int cpu_run_sbin_hotplug(unsigned int cpu, const char *action)
 {
-	char *argv[3], *envp[5], cpu_str[12], action_str[32];
+	char *argv[3], *envp[6], cpu_str[12], action_str[32], devpath_str[40];
 	int i;
 
 	sprintf(cpu_str, "CPU=%d", cpu);
 	sprintf(action_str, "ACTION=%s", action);
-	/* FIXME: Add DEVPATH. --RR */
-
+	sprintf(devpath_str, "DEVPATH=devices/system/cpu/cpu%d", cpu);
+	
 	i = 0;
 	argv[i++] = hotplug_path;
 	argv[i++] = "cpu";
@@ -79,6 +79,7 @@ static int cpu_run_sbin_hotplug(unsigned int cpu, const char *action)
 	envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
 	envp[i++] = cpu_str;
 	envp[i++] = action_str;
+	envp[i++] = devpath_str;
 	envp[i] = NULL;
 
 	return call_usermodehelper(argv[0], argv, envp, 0);
diff --git a/kernel/exec_domain.c b/kernel/exec_domain.c
index a5686ae5d..5fba35304 100644
--- a/kernel/exec_domain.c
+++ b/kernel/exec_domain.c
@@ -44,29 +44,7 @@ struct exec_domain default_exec_domain = {
 static void
 default_handler(int segment, struct pt_regs *regp)
 {
-	u_long			pers = 0;
-
-	/*
-	 * This may have been a static linked SVr4 binary, so we would
-	 * have the personality set incorrectly. Or it might have been
-	 * a Solaris/x86 binary. We can tell which because the former
-	 * uses lcall7, while the latter used lcall 0x27.
-	 * Try to find or load the appropriate personality, and fall back
-	 * to just forcing a SEGV.
-	 *
-	 * XXX: this is IA32-specific and should be moved to the MD-tree.
-	 */
-	switch (segment) {
-#ifdef __i386__
-	case 0x07:
-		pers = abi_defhandler_lcall7;
-		break;
-	case 0x27:
-		pers = PER_SOLARIS;
-		break;
-#endif
-	}
-	set_personality(pers);
+	set_personality(0);
 
 	if (current_thread_info()->exec_domain->handler != default_handler)
 		current_thread_info()->exec_domain->handler(segment, regp);
@@ -228,100 +206,3 @@ sys_personality(u_long personality)
 EXPORT_SYMBOL(register_exec_domain);
 EXPORT_SYMBOL(unregister_exec_domain);
 EXPORT_SYMBOL(__set_personality);
-
-/*
- * We have to have all sysctl handling for the Linux-ABI
- * in one place as the dynamic registration of sysctls is
- * horribly crufty in Linux <= 2.4.
- *
- * I hope the new sysctl schemes discussed for future versions
- * will obsolete this.
- *
- * 				--hch
- */
-
-u_long abi_defhandler_coff = PER_SCOSVR3;
-u_long abi_defhandler_elf = PER_LINUX;
-u_long abi_defhandler_lcall7 = PER_SVR4;
-u_long abi_defhandler_libcso = PER_SVR4;
-u_int abi_traceflg;
-int abi_fake_utsname;
-
-static struct ctl_table abi_table[] = {
-	{
-		.ctl_name	= ABI_DEFHANDLER_COFF,
-		.procname	= "defhandler_coff",
-		.data		= &abi_defhandler_coff,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_doulongvec_minmax,
-	},
-	{
-		.ctl_name	= ABI_DEFHANDLER_ELF,
-		.procname	= "defhandler_elf",
-		.data		= &abi_defhandler_elf,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_doulongvec_minmax,
-	},
-	{
-		.ctl_name	= ABI_DEFHANDLER_LCALL7,
-		.procname	= "defhandler_lcall7",
-		.data		= &abi_defhandler_lcall7,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_doulongvec_minmax,
-	},
-	{
-		.ctl_name	= ABI_DEFHANDLER_LIBCSO,
-		.procname	= "defhandler_libcso",
-		.data		= &abi_defhandler_libcso,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_doulongvec_minmax,
-	},
-	{
-		.ctl_name	= ABI_TRACE,
-		.procname	= "trace",
-		.data		= &abi_traceflg,
-		.maxlen		= sizeof(u_int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-	},
-	{
-		.ctl_name	= ABI_FAKE_UTSNAME,
-		.procname	= "fake_utsname",
-		.data		= &abi_fake_utsname,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-	},
-	{ .ctl_name = 0 }
-};
-
-static struct ctl_table abi_root_table[] = {
-	{
-		.ctl_name	= CTL_ABI,
-		.procname	= "abi",
-		.mode		= 0555,
-		.child		= abi_table,
-	},
-	{ .ctl_name = 0 }
-};
-
-static int __init
-abi_register_sysctl(void)
-{
-	register_sysctl_table(abi_root_table, 1);
-	return 0;
-}
-
-__initcall(abi_register_sysctl);
-
-
-EXPORT_SYMBOL(abi_defhandler_coff);
-EXPORT_SYMBOL(abi_defhandler_elf);
-EXPORT_SYMBOL(abi_defhandler_lcall7);
-EXPORT_SYMBOL(abi_defhandler_libcso);
-EXPORT_SYMBOL(abi_traceflg);
-EXPORT_SYMBOL(abi_fake_utsname);
diff --git a/kernel/exit.c b/kernel/exit.c
index 8c5742ebb..45384fd56 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -15,6 +15,7 @@
 #include <linux/tty.h>
 #include <linux/namespace.h>
 #include <linux/security.h>
+#include <linux/cpu.h>
 #include <linux/acct.h>
 #include <linux/file.h>
 #include <linux/binfmts.h>
@@ -40,8 +41,8 @@ static void __unhash_process(struct task_struct *p)
 	nr_threads--;
 	/* tasklist_lock is held, is this sufficient? */
 	if (p->vx_info) {
-		atomic_dec(&p->vx_info->cacct.nr_threads);
-		atomic_dec(&p->vx_info->limit.rcur[RLIMIT_NPROC]);
+		atomic_dec(&p->vx_info->cvirt.nr_threads);
+		vx_nproc_dec(p);
 	}
 	detach_pid(p, PIDTYPE_PID);
 	detach_pid(p, PIDTYPE_TGID);
@@ -62,8 +63,6 @@ void release_task(struct task_struct * p)
 	struct dentry *proc_dentry;
 
 repeat: 
-	BUG_ON(p->state < TASK_ZOMBIE);
- 
 	atomic_dec(&p->user->processes);
 	spin_lock(&p->proc_lock);
 	proc_dentry = proc_pid_unhash(p);
@@ -96,12 +95,6 @@ repeat:
 		zap_leader = (leader->exit_signal == -1);
 	}
 
-	p->parent->cutime += p->utime + p->cutime;
-	p->parent->cstime += p->stime + p->cstime;
-	p->parent->cmin_flt += p->min_flt + p->cmin_flt;
-	p->parent->cmaj_flt += p->maj_flt + p->cmaj_flt;
-	p->parent->cnvcsw += p->nvcsw + p->cnvcsw;
-	p->parent->cnivcsw += p->nivcsw + p->cnivcsw;
 	sched_exit(p);
 	write_unlock_irq(&tasklist_lock);
 	spin_unlock(&p->proc_lock);
@@ -137,16 +130,15 @@ void unhash_process(struct task_struct *p)
 int session_of_pgrp(int pgrp)
 {
 	struct task_struct *p;
-	struct list_head *l;
-	struct pid *pid;
 	int sid = -1;
 
 	read_lock(&tasklist_lock);
-	for_each_task_pid(pgrp, PIDTYPE_PGID, p, l, pid)
+	do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
 		if (p->signal->session > 0) {
 			sid = p->signal->session;
 			goto out;
 		}
+	} while_each_task_pid(pgrp, PIDTYPE_PGID, p);
 	p = find_task_by_pid(pgrp);
 	if (p)
 		sid = p->signal->session;
@@ -167,11 +159,9 @@ out:
 static int will_become_orphaned_pgrp(int pgrp, task_t *ignored_task)
 {
 	struct task_struct *p;
-	struct list_head *l;
-	struct pid *pid;
 	int ret = 1;
 
-	for_each_task_pid(pgrp, PIDTYPE_PGID, p, l, pid) {
+	do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
 		if (p == ignored_task
 				|| p->state >= TASK_ZOMBIE 
 				|| p->real_parent->pid == 1)
@@ -181,7 +171,7 @@ static int will_become_orphaned_pgrp(int pgrp, task_t *ignored_task)
 			ret = 0;
 			break;
 		}
-	}
+	} while_each_task_pid(pgrp, PIDTYPE_PGID, p);
 	return ret;	/* (sighing) "Often!" */
 }
 
@@ -200,10 +190,8 @@ static inline int has_stopped_jobs(int pgrp)
 {
 	int retval = 0;
 	struct task_struct *p;
-	struct list_head *l;
-	struct pid *pid;
 
-	for_each_task_pid(pgrp, PIDTYPE_PGID, p, l, pid) {
+	do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
 		if (p->state != TASK_STOPPED)
 			continue;
 
@@ -219,7 +207,7 @@ static inline int has_stopped_jobs(int pgrp)
 
 		retval = 1;
 		break;
-	}
+	} while_each_task_pid(pgrp, PIDTYPE_PGID, p);
 	return retval;
 }
 
@@ -537,10 +525,8 @@ static inline void choose_new_parent(task_t *p, task_t *reaper, task_t *child_re
 	 * Make sure we're not reparenting to ourselves and that
 	 * the parent is not a zombie.
 	 */
-	if (p == reaper || reaper->state >= TASK_ZOMBIE)
-		p->real_parent = child_reaper;
-	else
-		p->real_parent = reaper;
+	BUG_ON(p == reaper || reaper->state >= TASK_ZOMBIE);
+	p->real_parent = reaper;
 	if (p->parent == p->real_parent)
 		BUG();
 }
@@ -577,6 +563,14 @@ static inline void reparent_thread(task_t *p, task_t *father, int traced)
 		if (p->state == TASK_ZOMBIE && p->exit_signal != -1 &&
 		    thread_group_empty(p))
 			do_notify_parent(p, p->exit_signal);
+		else if (p->state == TASK_TRACED) {
+			/*
+			 * If it was at a trace stop, turn it into
+			 * a normal stop since it's no longer being
+			 * traced.
+			 */
+			p->state = TASK_STOPPED;
+		}
 	}
 
 	/*
@@ -609,9 +603,13 @@ static inline void forget_original_parent(struct task_struct * father,
 	struct list_head *_p, *_n;
 
 	/* FIXME handle vchild_reaper/initpid */
-	reaper = father->group_leader;
-	if (reaper == father)
-		reaper = child_reaper;
+	do {
+		reaper = next_thread(reaper);
+		if (reaper == father) {
+			reaper = child_reaper;
+			break;
+		}
+	} while (reaper->state >= TASK_ZOMBIE);
 
 	/*
 	 * There are only two places where our children can be:
@@ -765,7 +763,6 @@ static void exit_notify(struct task_struct *tsk)
 	if (tsk->exit_signal == -1 && tsk->ptrace == 0)
 		state = TASK_DEAD;
 	tsk->state = state;
-	tsk->flags |= PF_DEAD;
 
 	/*
 	 * Clear these here so that update_process_times() won't try to deliver
@@ -775,20 +772,7 @@ static void exit_notify(struct task_struct *tsk)
 	tsk->it_prof_value = 0;
 	tsk->rlim[RLIMIT_CPU].rlim_cur = RLIM_INFINITY;
 
-	/*
-	 * In the preemption case it must be impossible for the task
-	 * to get runnable again, so use "_raw_" unlock to keep
-	 * preempt_count elevated until we schedule().
-	 *
-	 * To avoid deadlock on SMP, interrupts must be unmasked.  If we
-	 * don't, subsequently called functions (e.g, wait_task_inactive()
-	 * via release_task()) will spin, with interrupt flags
-	 * unwittingly blocked, until the other task sleeps.  That task
-	 * may itself be waiting for smp_call_function() to answer and
-	 * complete, and with interrupts blocked that will never happen.
-	 */
-	_raw_write_unlock(&tasklist_lock);
-	local_irq_enable();
+	write_unlock_irq(&tasklist_lock);
 
 	list_for_each_safe(_p, _n, &ptrace_dead) {
 		list_del_init(_p);
@@ -800,12 +784,17 @@ static void exit_notify(struct task_struct *tsk)
 	if (state == TASK_DEAD)
 		release_task(tsk);
 
+	/* PF_DEAD causes final put_task_struct after we schedule. */
+	preempt_disable();
+	tsk->flags |= PF_DEAD;
 }
 
 asmlinkage NORET_TYPE void do_exit(long code)
 {
 	struct task_struct *tsk = current;
 
+	profile_task_exit(tsk);
+
 	if (unlikely(in_interrupt()))
 		panic("Aiee, killing interrupt handler!");
 	if (unlikely(!tsk->pid))
@@ -822,8 +811,6 @@ asmlinkage NORET_TYPE void do_exit(long code)
 				current->comm, current->pid,
 				preempt_count());
 
-	profile_exit_task(tsk);
- 
 	if (unlikely(current->ptrace & PT_TRACE_EXIT)) {
 		current->ptrace_message = code;
 		ptrace_notify((PTRACE_EVENT_EXIT << 8) | SIGTRAP);
@@ -874,9 +861,6 @@ asmlinkage long sys_exit(int error_code)
 
 task_t fastcall *next_thread(const task_t *p)
 {
-	const struct pid_link *link = p->pids + PIDTYPE_TGID;
-	const struct list_head *tmp, *head = &link->pidptr->task_list;
-
 #ifdef CONFIG_SMP
 	if (!p->sighand)
 		BUG();
@@ -884,11 +868,7 @@ task_t fastcall *next_thread(const task_t *p)
 				!rwlock_is_locked(&tasklist_lock))
 		BUG();
 #endif
-	tmp = link->pid_chain.next;
-	if (tmp == head)
-		tmp = head->next;
-
-	return pid_task(tmp, PIDTYPE_TGID);
+	return pid_task(p->pids[PIDTYPE_TGID].pid_list.next, PIDTYPE_TGID);
 }
 
 EXPORT_SYMBOL(next_thread);
@@ -976,16 +956,66 @@ static int eligible_child(pid_t pid, int options, task_t *p)
 	return 1;
 }
 
+static int wait_noreap_copyout(task_t *p, pid_t pid, uid_t uid,
+			       int why, int status,
+			       struct siginfo __user *infop,
+			       struct rusage __user *rusagep)
+{
+	int retval = rusagep ? getrusage(p, RUSAGE_BOTH, rusagep) : 0;
+	put_task_struct(p);
+	if (!retval)
+		retval = put_user(SIGCHLD, &infop->si_signo);
+	if (!retval)
+		retval = put_user(0, &infop->si_errno);
+	if (!retval)
+		retval = put_user((short)why, &infop->si_code);
+	if (!retval)
+		retval = put_user(pid, &infop->si_pid);
+	if (!retval)
+		retval = put_user(uid, &infop->si_uid);
+	if (!retval)
+		retval = put_user(status, &infop->si_status);
+	if (!retval)
+		retval = pid;
+	return retval;
+}
+
 /*
  * Handle sys_wait4 work for one task in state TASK_ZOMBIE.  We hold
  * read_lock(&tasklist_lock) on entry.  If we return zero, we still hold
  * the lock and this task is uninteresting.  If we return nonzero, we have
  * released the lock and the system call should return.
  */
-static int wait_task_zombie(task_t *p, unsigned int __user *stat_addr, struct rusage __user *ru)
+static int wait_task_zombie(task_t *p, int noreap,
+			    struct siginfo __user *infop,
+			    int __user *stat_addr, struct rusage __user *ru)
 {
 	unsigned long state;
 	int retval;
+	int status;
+
+	if (unlikely(noreap)) {
+		pid_t pid = p->pid;
+		uid_t uid = p->uid;
+		int exit_code = p->exit_code;
+		int why, status;
+
+		if (unlikely(p->state != TASK_ZOMBIE))
+			return 0;
+		if (unlikely(p->exit_signal == -1 && p->ptrace == 0))
+			return 0;
+		get_task_struct(p);
+		read_unlock(&tasklist_lock);
+		if ((exit_code & 0x7f) == 0) {
+			why = CLD_EXITED;
+			status = exit_code >> 8;
+		} else {
+			why = (exit_code & 0x80) ? CLD_DUMPED : CLD_KILLED;
+			status = exit_code & 0x7f;
+		}
+		return wait_noreap_copyout(p, pid, uid, why,
+					   status, infop, ru);
+	}
 
 	/*
 	 * Try to move the task's state to DEAD
@@ -996,12 +1026,45 @@ static int wait_task_zombie(task_t *p, unsigned int __user *stat_addr, struct ru
 		BUG_ON(state != TASK_DEAD);
 		return 0;
 	}
-	if (unlikely(p->exit_signal == -1 && p->ptrace == 0))
+	if (unlikely(p->exit_signal == -1 && p->ptrace == 0)) {
 		/*
 		 * This can only happen in a race with a ptraced thread
 		 * dying on another processor.
 		 */
 		return 0;
+	}
+
+	if (likely(p->real_parent == p->parent) && likely(p->signal)) {
+		/*
+		 * The resource counters for the group leader are in its
+		 * own task_struct.  Those for dead threads in the group
+		 * are in its signal_struct, as are those for the child
+		 * processes it has previously reaped.  All these
+		 * accumulate in the parent's signal_struct c* fields.
+		 *
+		 * We don't bother to take a lock here to protect these
+		 * p->signal fields, because they are only touched by
+		 * __exit_signal, which runs with tasklist_lock
+		 * write-locked anyway, and so is excluded here.  We do
+		 * need to protect the access to p->parent->signal fields,
+		 * as other threads in the parent group can be right
+		 * here reaping other children at the same time.
+		 */
+		spin_lock_irq(&p->parent->sighand->siglock);
+		p->parent->signal->cutime +=
+			p->utime + p->signal->utime + p->signal->cutime;
+		p->parent->signal->cstime +=
+			p->stime + p->signal->stime + p->signal->cstime;
+		p->parent->signal->cmin_flt +=
+			p->min_flt + p->signal->min_flt + p->signal->cmin_flt;
+		p->parent->signal->cmaj_flt +=
+			p->maj_flt + p->signal->maj_flt + p->signal->cmaj_flt;
+		p->parent->signal->cnvcsw +=
+			p->nvcsw + p->signal->nvcsw + p->signal->cnvcsw;
+		p->parent->signal->cnivcsw +=
+			p->nivcsw + p->signal->nivcsw + p->signal->cnivcsw;
+		spin_unlock_irq(&p->parent->sighand->siglock);
+	}
 
 	/*
 	 * Now we are sure this task is interesting, and no other
@@ -1010,12 +1073,32 @@ static int wait_task_zombie(task_t *p, unsigned int __user *stat_addr, struct ru
 	read_unlock(&tasklist_lock);
 
 	retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;
-	if (!retval && stat_addr) {
-		if (p->signal->group_exit)
-			retval = put_user(p->signal->group_exit_code, stat_addr);
-		else
-			retval = put_user(p->exit_code, stat_addr);
+	status = p->signal->group_exit
+		? p->signal->group_exit_code : p->exit_code;
+	if (!retval && stat_addr)
+		retval = put_user(status, stat_addr);
+	if (!retval && infop)
+		retval = put_user(SIGCHLD, &infop->si_signo);
+	if (!retval && infop)
+		retval = put_user(0, &infop->si_errno);
+	if (!retval && infop) {
+		int why;
+
+		if ((status & 0x7f) == 0) {
+			why = CLD_EXITED;
+			status >>= 8;
+		} else {
+			why = (status & 0x80) ? CLD_DUMPED : CLD_KILLED;
+			status &= 0x7f;
+		}
+		retval = put_user((short)why, &infop->si_code);
+		if (!retval)
+			retval = put_user(status, &infop->si_status);
 	}
+	if (!retval && infop)
+		retval = put_user(p->pid, &infop->si_pid);
+	if (!retval && infop)
+		retval = put_user(p->uid, &infop->si_uid);
 	if (retval) {
 		p->state = TASK_ZOMBIE;
 		return retval;
@@ -1028,8 +1111,9 @@ static int wait_task_zombie(task_t *p, unsigned int __user *stat_addr, struct ru
 			__ptrace_unlink(p);
 			p->state = TASK_ZOMBIE;
 			/*
-			 * If this is not a detached task, notify the parent.  If it's
-			 * still not detached after that, don't release it now.
+			 * If this is not a detached task, notify the parent.
+			 * If it's still not detached after that, don't release
+			 * it now.
 			 */
 			if (p->exit_signal != -1) {
 				do_notify_parent(p, p->exit_signal);
@@ -1051,9 +1135,9 @@ static int wait_task_zombie(task_t *p, unsigned int __user *stat_addr, struct ru
  * the lock and this task is uninteresting.  If we return nonzero, we have
  * released the lock and the system call should return.
  */
-static int wait_task_stopped(task_t *p, int delayed_group_leader,
-			     unsigned int __user *stat_addr,
-			     struct rusage __user *ru)
+static int wait_task_stopped(task_t *p, int delayed_group_leader, int noreap,
+			     struct siginfo __user *infop,
+			     int __user *stat_addr, struct rusage __user *ru)
 {
 	int retval, exit_code;
 
@@ -1076,6 +1160,21 @@ static int wait_task_stopped(task_t *p, int delayed_group_leader,
 	 */
 	get_task_struct(p);
 	read_unlock(&tasklist_lock);
+
+	if (unlikely(noreap)) {
+		pid_t pid = p->pid;
+		uid_t uid = p->uid;
+		int why = (p->ptrace & PT_PTRACED) ? CLD_TRAPPED : CLD_STOPPED;
+
+		exit_code = p->exit_code;
+		if (unlikely(!exit_code) ||
+		    unlikely(p->state > TASK_STOPPED))
+			goto bail_ref;
+		return wait_noreap_copyout(p, pid, uid,
+					   why, (exit_code << 8) | 0x7f,
+					   infop, ru);
+	}
+
 	write_lock_irq(&tasklist_lock);
 
 	/*
@@ -1084,7 +1183,7 @@ static int wait_task_stopped(task_t *p, int delayed_group_leader,
 	 * race with the TASK_ZOMBIE case.
 	 */
 	exit_code = xchg(&p->exit_code, 0);
-	if (unlikely(p->state > TASK_STOPPED)) {
+	if (unlikely(p->state >= TASK_ZOMBIE)) {
 		/*
 		 * The task resumed and then died.  Let the next iteration
 		 * catch it in TASK_ZOMBIE.  Note that exit_code might
@@ -1101,6 +1200,7 @@ static int wait_task_stopped(task_t *p, int delayed_group_leader,
 		 * resumed, or it resumed and then died.
 		 */
 		write_unlock_irq(&tasklist_lock);
+bail_ref:
 		put_task_struct(p);
 		read_lock(&tasklist_lock);
 		return 0;
@@ -1115,6 +1215,20 @@ static int wait_task_stopped(task_t *p, int delayed_group_leader,
 	retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;
 	if (!retval && stat_addr)
 		retval = put_user((exit_code << 8) | 0x7f, stat_addr);
+	if (!retval && infop)
+		retval = put_user(SIGCHLD, &infop->si_signo);
+	if (!retval && infop)
+		retval = put_user(0, &infop->si_errno);
+	if (!retval && infop)
+		retval = put_user((short)((p->ptrace & PT_PTRACED)
+					  ? CLD_TRAPPED : CLD_STOPPED),
+				  &infop->si_code);
+	if (!retval && infop)
+		retval = put_user(exit_code, &infop->si_status);
+	if (!retval && infop)
+		retval = put_user(p->pid, &infop->si_pid);
+	if (!retval && infop)
+		retval = put_user(p->uid, &infop->si_uid);
 	if (!retval)
 		retval = p->pid;
 	put_task_struct(p);
@@ -1123,15 +1237,13 @@ static int wait_task_stopped(task_t *p, int delayed_group_leader,
 	return retval;
 }
 
-asmlinkage long sys_wait4(pid_t pid,unsigned int __user *stat_addr, int options, struct rusage __user *ru)
+static long do_wait(pid_t pid, int options, struct siginfo __user *infop,
+		    int __user *stat_addr, struct rusage __user *ru)
 {
 	DECLARE_WAITQUEUE(wait, current);
 	struct task_struct *tsk;
 	int flag, retval;
 
-	if (options & ~(WNOHANG|WUNTRACED|__WNOTHREAD|__WCLONE|__WALL))
-		return -EINVAL;
-
 	add_wait_queue(&current->wait_chldexit,&wait);
 repeat:
 	flag = 0;
@@ -1152,30 +1264,69 @@ repeat:
 			flag = 1;
 
 			switch (p->state) {
+			case TASK_TRACED:
+				if (!(p->ptrace & PT_PTRACED))
+					continue;
+				/*FALLTHROUGH*/
 			case TASK_STOPPED:
 				if (!(options & WUNTRACED) &&
 				    !(p->ptrace & PT_PTRACED))
 					continue;
 				retval = wait_task_stopped(p, ret == 2,
+							   (options & WNOWAIT),
+							   infop,
 							   stat_addr, ru);
 				if (retval != 0) /* He released the lock.  */
-					goto end_wait4;
+					goto end;
 				break;
 			case TASK_ZOMBIE:
 				/*
 				 * Eligible but we cannot release it yet:
 				 */
 				if (ret == 2)
+					goto check_continued;
+				if (!likely(options & WEXITED))
 					continue;
-				retval = wait_task_zombie(p, stat_addr, ru);
+				retval = wait_task_zombie(
+					p, (options & WNOWAIT),
+					infop, stat_addr, ru);
 				if (retval != 0) /* He released the lock.  */
-					goto end_wait4;
+					goto end;
+				break;
+			case TASK_DEAD:
+				continue;
+			default:
+check_continued:
+				if (!unlikely(options & WCONTINUED))
+					continue;
+				if (unlikely(!p->signal))
+					continue;
+				spin_lock_irq(&p->sighand->siglock);
+				if (p->signal->stop_state < 0) {
+					pid_t pid;
+					uid_t uid;
+
+					if (!(options & WNOWAIT))
+						p->signal->stop_state = 0;
+					spin_unlock_irq(&p->sighand->siglock);
+					pid = p->pid;
+					uid = p->uid;
+					get_task_struct(p);
+					read_unlock(&tasklist_lock);
+					retval = wait_noreap_copyout(p, pid,
+							uid, CLD_CONTINUED,
+							SIGCONT, infop, ru);
+					BUG_ON(retval == 0);
+					goto end;
+				}
+				spin_unlock_irq(&p->sighand->siglock);
 				break;
 			}
 		}
 		if (!flag) {
-			list_for_each (_p,&tsk->ptrace_children) {
-				p = list_entry(_p,struct task_struct,ptrace_list);
+			list_for_each(_p, &tsk->ptrace_children) {
+				p = list_entry(_p, struct task_struct,
+						ptrace_list);
 				if (!eligible_child(pid, options, p))
 					continue;
 				flag = 1;
@@ -1188,31 +1339,104 @@ repeat:
 		if (tsk->signal != current->signal)
 			BUG();
 	} while (tsk != current);
+
 	read_unlock(&tasklist_lock);
 	if (flag) {
 		retval = 0;
 		if (options & WNOHANG)
-			goto end_wait4;
+			goto end;
 		retval = -ERESTARTSYS;
 		if (signal_pending(current))
-			goto end_wait4;
+			goto end;
 		schedule();
 		goto repeat;
 	}
 	retval = -ECHILD;
-end_wait4:
+end:
 	current->state = TASK_RUNNING;
 	remove_wait_queue(&current->wait_chldexit,&wait);
+	if (infop) {
+		if (retval > 0)
+		retval = 0;
+		else {
+			/*
+			 * For a WNOHANG return, clear out all the fields
+			 * we would set so the user can easily tell the
+			 * difference.
+			 */
+			if (!retval)
+				retval = put_user(0, &infop->si_signo);
+			if (!retval)
+				retval = put_user(0, &infop->si_errno);
+			if (!retval)
+				retval = put_user(0, &infop->si_code);
+			if (!retval)
+				retval = put_user(0, &infop->si_pid);
+			if (!retval)
+				retval = put_user(0, &infop->si_uid);
+			if (!retval)
+				retval = put_user(0, &infop->si_status);
+		}
+	}
 	return retval;
 }
 
+asmlinkage long sys_waitid(int which, pid_t pid,
+			   struct siginfo __user *infop, int options,
+			   struct rusage __user *ru)
+{
+	long ret;
+
+	if (options & ~(WNOHANG|WNOWAIT|WEXITED|WSTOPPED|WCONTINUED))
+		return -EINVAL;
+	if (!(options & (WEXITED|WSTOPPED|WCONTINUED)))
+		return -EINVAL;
+
+	switch (which) {
+	case P_ALL:
+		pid = -1;
+		break;
+	case P_PID:
+		if (pid <= 0)
+			return -EINVAL;
+		break;
+	case P_PGID:
+		if (pid <= 0)
+			return -EINVAL;
+		pid = -pid;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = do_wait(pid, options, infop, NULL, ru);
+
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
+}
+
+asmlinkage long sys_wait4(pid_t pid, int __user *stat_addr,
+			  int options, struct rusage __user *ru)
+{
+	long ret;
+
+	if (options & ~(WNOHANG|WUNTRACED|__WNOTHREAD|__WCLONE|__WALL))
+		return -EINVAL;
+	ret = do_wait(pid, options | WEXITED, NULL, stat_addr, ru);
+
+	/* avoid REGPARM breakage on x86: */
+	prevent_tail_call(ret);
+	return ret;
+}
+
 #ifdef __ARCH_WANT_SYS_WAITPID
 
 /*
  * sys_waitpid() remains for compatibility. waitpid() should be
  * implemented by calling sys_wait4() from libc.a.
  */
-asmlinkage long sys_waitpid(pid_t pid, unsigned __user *stat_addr, int options)
+asmlinkage long sys_waitpid(pid_t pid, int __user *stat_addr, int options)
 {
 	return sys_wait4(pid, stat_addr, options, NULL);
 }
diff --git a/kernel/fork.c b/kernel/fork.c
index be07582f0..4ab37a13f 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -29,12 +29,14 @@
 #include <linux/fs.h>
 #include <linux/cpu.h>
 #include <linux/security.h>
+#include <linux/swap.h>
 #include <linux/syscalls.h>
 #include <linux/jiffies.h>
 #include <linux/futex.h>
 #include <linux/ptrace.h>
 #include <linux/mount.h>
 #include <linux/audit.h>
+#include <linux/profile.h>
 #include <linux/rmap.h>
 #include <linux/vs_network.h>
 #include <linux/vs_limit.h>
@@ -78,13 +80,14 @@ int nr_processes(void)
 static kmem_cache_t *task_struct_cachep;
 #endif
 
-static void free_task(struct task_struct *tsk)
+void free_task(struct task_struct *tsk)
 {
 	free_thread_info(tsk->thread_info);
 	clr_vx_info(&tsk->vx_info);
 	clr_nx_info(&tsk->nx_info);
 	free_task_struct(tsk);
 }
+EXPORT_SYMBOL(free_task);
 
 void __put_task_struct(struct task_struct *tsk)
 {
@@ -97,7 +100,9 @@ void __put_task_struct(struct task_struct *tsk)
 	security_task_free(tsk);
 	free_uid(tsk->user);
 	put_group_info(tsk->group_info);
-	free_task(tsk);
+
+	if (!profile_handoff_task(tsk))
+		free_task(tsk);
 }
 
 void fastcall add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait)
@@ -156,7 +161,12 @@ void fastcall prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int stat
 	spin_lock_irqsave(&q->lock, flags);
 	if (list_empty(&wait->task_list))
 		__add_wait_queue(q, wait);
-	set_current_state(state);
+	/*
+	 * don't alter the task state if this is just going to
+	 * queue an async wait queue callback
+	 */
+	if (is_sync_wait(wait))
+		set_current_state(state);
 	spin_unlock_irqrestore(&q->lock, flags);
 }
 
@@ -171,7 +181,12 @@ prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state)
 	spin_lock_irqsave(&q->lock, flags);
 	if (list_empty(&wait->task_list))
 		__add_wait_queue_tail(q, wait);
-	set_current_state(state);
+	/*
+	 * don't alter the task state if this is just going to
+ 	 * queue an async wait queue callback
+	 */
+	if (is_sync_wait(wait))
+		set_current_state(state);
 	spin_unlock_irqrestore(&q->lock, flags);
 }
 
@@ -284,7 +299,7 @@ static inline int dup_mmap(struct mm_struct * mm, struct mm_struct * oldmm)
 	mm->locked_vm = 0;
 	mm->mmap = NULL;
 	mm->mmap_cache = NULL;
-	mm->free_area_cache = TASK_UNMAPPED_BASE;
+	mm->free_area_cache = oldmm->mmap_base;
 	mm->map_count = 0;
 	mm->rss = 0;
 	cpus_clear(mm->cpu_vm_mask);
@@ -307,8 +322,11 @@ static inline int dup_mmap(struct mm_struct * mm, struct mm_struct * oldmm)
 	for (mpnt = current->mm->mmap ; mpnt ; mpnt = mpnt->vm_next) {
 		struct file *file;
 
-		if(mpnt->vm_flags & VM_DONTCOPY)
+		if (mpnt->vm_flags & VM_DONTCOPY) {
+			__vm_stat_account(mm, mpnt->vm_flags, mpnt->vm_file,
+							-vma_pages(mpnt));
 			continue;
+		}
 		charge = 0;
 		if (mpnt->vm_flags & VM_ACCOUNT) {
 			unsigned int len = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
@@ -329,7 +347,6 @@ static inline int dup_mmap(struct mm_struct * mm, struct mm_struct * oldmm)
 		tmp->vm_mm = mm;
 		tmp->vm_next = NULL;
 		anon_vma_link(tmp);
-		vma_prio_tree_init(tmp);
 		file = tmp->vm_file;
 		if (file) {
 			struct inode *inode = file->f_dentry->d_inode;
@@ -469,26 +486,43 @@ void mmput(struct mm_struct *mm)
 		spin_unlock(&mmlist_lock);
 		exit_aio(mm);
 		exit_mmap(mm);
+		put_swap_token(mm);
 		mmdrop(mm);
 	}
 }
+EXPORT_SYMBOL_GPL(mmput);
 
-/*
- * Checks if the use count of an mm is non-zero and if so
- * returns a reference to it after bumping up the use count.
- * If the use count is zero, it means this mm is going away,
- * so return NULL.
+/**
+ * get_task_mm - acquire a reference to the task's mm
+ *
+ * Returns %NULL if the task has no mm.  Checks if the use count
+ * of the mm is non-zero and if so returns a reference to it, after
+ * bumping up the use count.  User must release the mm via mmput()
+ * after use.  Typically used by /proc and ptrace.
+ *
+ * If the use count is zero, it means that this mm is going away,
+ * so return %NULL.  This only happens in the case of an AIO daemon
+ * which has temporarily adopted an mm (see use_mm), in the course
+ * of its final mmput, before exit_aio has completed.
  */
-struct mm_struct *mmgrab(struct mm_struct *mm)
+struct mm_struct *get_task_mm(struct task_struct *task)
 {
-	spin_lock(&mmlist_lock);
-	if (!atomic_read(&mm->mm_users))
-		mm = NULL;
-	else
-		atomic_inc(&mm->mm_users);
-	spin_unlock(&mmlist_lock);
+	struct mm_struct *mm;
+
+	task_lock(task);
+	mm = task->mm;
+	if (mm) {
+		spin_lock(&mmlist_lock);
+		if (!atomic_read(&mm->mm_users))
+			mm = NULL;
+		else
+			atomic_inc(&mm->mm_users);
+		spin_unlock(&mmlist_lock);
+	}
+	task_unlock(task);
 	return mm;
 }
+EXPORT_SYMBOL_GPL(get_task_mm);
 
 /* Please note the differences between mmput and mm_release.
  * mmput is called whenever we stop holding onto a mm_struct,
@@ -534,8 +568,7 @@ static int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
 	int retval;
 
 	tsk->min_flt = tsk->maj_flt = 0;
-	tsk->cmin_flt = tsk->cmaj_flt = 0;
-	tsk->nvcsw = tsk->nivcsw = tsk->cnvcsw = tsk->cnivcsw = 0;
+	tsk->nvcsw = tsk->nivcsw = 0;
 
 	tsk->mm = NULL;
 	tsk->active_mm = NULL;
@@ -843,6 +876,10 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
 	sig->leader = 0;	/* session leadership doesn't inherit */
 	sig->tty_old_pgrp = 0;
 
+	sig->utime = sig->stime = sig->cutime = sig->cstime = 0;
+	sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0;
+	sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0;
+
 	return 0;
 }
 
@@ -872,12 +909,13 @@ asmlinkage long sys_set_tid_address(int __user *tidptr)
  * parts of the process environment (as per the clone
  * flags). The actual kick-off is left to the caller.
  */
-struct task_struct *copy_process(unsigned long clone_flags,
+static task_t *copy_process(unsigned long clone_flags,
 				 unsigned long stack_start,
 				 struct pt_regs *regs,
 				 unsigned long stack_size,
 				 int __user *parent_tidptr,
-				 int __user *child_tidptr)
+				 int __user *child_tidptr,
+				 int pid)
 {
 	int retval;
 	struct task_struct *p = NULL;
@@ -928,8 +966,8 @@ struct task_struct *copy_process(unsigned long clone_flags,
 	}
 
 	retval = -EAGAIN;
-        if (!vx_nproc_avail(1))
-                goto bad_fork_cleanup_vm;
+	if (!vx_nproc_avail(1))
+		goto bad_fork_cleanup_vm;
 
 	if (atomic_read(&p->user->processes) >=
 			p->rlim[RLIMIT_NPROC].rlim_cur) {
@@ -958,13 +996,7 @@ struct task_struct *copy_process(unsigned long clone_flags,
 
 	p->did_exec = 0;
 	copy_flags(clone_flags, p);
-	if (clone_flags & CLONE_IDLETASK)
-		p->pid = 0;
-	else {
-		p->pid = alloc_pidmap();
-		if (p->pid == -1)
-			goto bad_fork_cleanup;
-	}
+	p->pid = pid;
 	retval = -EFAULT;
 	if (clone_flags & CLONE_PARENT_SETTID)
 		if (put_user(p->pid, parent_tidptr))
@@ -988,11 +1020,11 @@ struct task_struct *copy_process(unsigned long clone_flags,
 	p->real_timer.data = (unsigned long) p;
 
 	p->utime = p->stime = 0;
-	p->cutime = p->cstime = 0;
 	p->lock_depth = -1;		/* -1 = no lock */
-	p->start_time = get_jiffies_64();
+	do_posix_clock_monotonic_gettime(&p->start_time);
 	p->security = NULL;
 	p->io_context = NULL;
+	p->io_wait = NULL;
 	p->audit_context = NULL;
 #ifdef CONFIG_NUMA
  	p->mempolicy = mpol_copy(p->mempolicy);
@@ -1061,6 +1093,17 @@ struct task_struct *copy_process(unsigned long clone_flags,
 
 	/* Need tasklist lock for parent etc handling! */
 	write_lock_irq(&tasklist_lock);
+
+	/*
+	 * The task hasn't been attached yet, so cpus_allowed mask cannot
+	 * have changed. The cpus_allowed mask of the parent may have
+	 * changed after it was copied first time, and it may then move to
+	 * another CPU - so we re-copy it here and set the child's CPU to
+	 * the parent's CPU. This avoids alot of nasty races.
+	 */
+	p->cpus_allowed = current->cpus_allowed;
+	set_task_cpu(p, smp_processor_id());
+
 	/*
 	 * Check for pending SIGKILL! The new thread should not be allowed
 	 * to slip out of an OOM kill. (or normal SIGKILL.)
@@ -1072,7 +1115,7 @@ struct task_struct *copy_process(unsigned long clone_flags,
 	}
 
 	/* CLONE_PARENT re-uses the old parent */
-	if (clone_flags & CLONE_PARENT)
+	if (clone_flags & (CLONE_PARENT|CLONE_THREAD))
 		p->real_parent = current->real_parent;
 	else
 		p->real_parent = current;
@@ -1108,25 +1151,24 @@ struct task_struct *copy_process(unsigned long clone_flags,
 	}
 
 	SET_LINKS(p);
-	if (p->ptrace & PT_PTRACED)
+	if (unlikely(p->ptrace & PT_PTRACED))
 		__ptrace_link(p, current->parent);
 
 	attach_pid(p, PIDTYPE_PID, p->pid);
+	attach_pid(p, PIDTYPE_TGID, p->tgid);
 	if (thread_group_leader(p)) {
-		attach_pid(p, PIDTYPE_TGID, p->tgid);
 		attach_pid(p, PIDTYPE_PGID, process_group(p));
 		attach_pid(p, PIDTYPE_SID, p->signal->session);
 		if (p->pid)
 			__get_cpu_var(process_counts)++;
-	} else
-		link_pid(p, p->pids + PIDTYPE_TGID, &p->group_leader->pids[PIDTYPE_TGID].pid);
+	}
 
 	nr_threads++;
 	/* p is copy of current */
 	vxi = p->vx_info;
 	if (vxi) {
-		atomic_inc(&vxi->cacct.nr_threads);
-		atomic_inc(&vxi->limit.rcur[RLIMIT_NPROC]);
+		atomic_inc(&vxi->cvirt.nr_threads);
+		vx_nproc_inc(p);
 	}
 	write_unlock_irq(&tasklist_lock);
 	retval = 0;
@@ -1139,9 +1181,8 @@ fork_out:
 bad_fork_cleanup_namespace:
 	exit_namespace(p);
 bad_fork_cleanup_mm:
-	exit_mm(p);
-	if (p->active_mm)
-		mmdrop(p->active_mm);
+	if (p->mm)
+		mmput(p->mm);
 bad_fork_cleanup_signal:
 	exit_signal(p);
 bad_fork_cleanup_sighand:
@@ -1161,8 +1202,6 @@ bad_fork_cleanup_policy:
 	mpol_free(p->mempolicy);
 #endif
 bad_fork_cleanup:
-	if (p->pid > 0)
-		free_pidmap(p->pid);
 	if (p->binfmt)
 		module_put(p->binfmt->module);
 bad_fork_cleanup_put_domain:
@@ -1179,9 +1218,28 @@ bad_fork_free:
 	goto fork_out;
 }
 
+struct pt_regs * __devinit __attribute__((weak)) idle_regs(struct pt_regs *regs)
+{
+	memset(regs, 0, sizeof(struct pt_regs));
+	return regs;
+}
+
+task_t * __devinit fork_idle(int cpu)
+{
+	task_t *task;
+	struct pt_regs regs;
+
+	task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL, NULL, 0);
+	if (!task)
+		return ERR_PTR(-ENOMEM);
+	init_idle(task, cpu);
+	unhash_process(task);
+	return task;
+}
+
 static inline int fork_traceflag (unsigned clone_flags)
 {
-	if (clone_flags & (CLONE_UNTRACED | CLONE_IDLETASK))
+	if (clone_flags & CLONE_UNTRACED)
 		return 0;
 	else if (clone_flags & CLONE_VFORK) {
 		if (current->ptrace & PT_TRACE_VFORK)
@@ -1210,21 +1268,21 @@ long do_fork(unsigned long clone_flags,
 {
 	struct task_struct *p;
 	int trace = 0;
-	long pid;
+	long pid = alloc_pidmap();
 
+	if (pid < 0)
+		return -EAGAIN;
 	if (unlikely(current->ptrace)) {
 		trace = fork_traceflag (clone_flags);
 		if (trace)
 			clone_flags |= CLONE_PTRACE;
 	}
 
-	p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr);
+	p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, pid);
 	/*
 	 * Do this prior waking up the new thread - the thread pointer
 	 * might get invalid after that point, if the thread exits quickly.
 	 */
-	pid = IS_ERR(p) ? PTR_ERR(p) : p->pid;
-
 	if (!IS_ERR(p)) {
 		struct completion vfork;
 
@@ -1241,31 +1299,10 @@ long do_fork(unsigned long clone_flags,
 			set_tsk_thread_flag(p, TIF_SIGPENDING);
 		}
 
-		if (!(clone_flags & CLONE_STOPPED)) {
-			/*
-			 * Do the wakeup last. On SMP we treat fork() and
-			 * CLONE_VM separately, because fork() has already
-			 * created cache footprint on this CPU (due to
-			 * copying the pagetables), hence migration would
-			 * probably be costy. Threads on the other hand
-			 * have less traction to the current CPU, and if
-			 * there's an imbalance then the scheduler can
-			 * migrate this fresh thread now, before it
-			 * accumulates a larger cache footprint:
-			 */
-			if (clone_flags & CLONE_VM)
-				wake_up_forked_thread(p);
-			else
-				wake_up_forked_process(p);
-		} else {
-			int cpu = get_cpu();
-
+		if (!(clone_flags & CLONE_STOPPED))
+			wake_up_new_task(p, clone_flags);
+		else
 			p->state = TASK_STOPPED;
-			if (cpu_is_offline(task_cpu(p)))
-				set_task_cpu(p, cpu);
-
-			put_cpu();
-		}
 		++total_forks;
 
 		if (unlikely (trace)) {
@@ -1277,12 +1314,10 @@ long do_fork(unsigned long clone_flags,
 			wait_for_completion(&vfork);
 			if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE))
 				ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP);
-		} else
-			/*
-			 * Let the child process run first, to avoid most of the
-			 * COW overhead when the child exec()s afterwards.
-			 */
-			set_need_resched();
+		}
+	} else {
+		free_pidmap(pid);
+		pid = PTR_ERR(p);
 	}
 	return pid;
 }
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 579269c38..5e7c44a0c 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -272,10 +272,8 @@ int call_usermodehelper(char *path, char **argv, char **envp, int wait)
 }
 EXPORT_SYMBOL(call_usermodehelper);
 
-static __init int usermodehelper_init(void)
+void __init usermodehelper_init(void)
 {
 	khelper_wq = create_singlethread_workqueue("khelper");
 	BUG_ON(!khelper_wq);
-	return 0;
 }
-core_initcall(usermodehelper_init);
diff --git a/kernel/kthread.c b/kernel/kthread.c
index 5689ebb1a..fc0767d84 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -108,7 +108,7 @@ static void keventd_create_kthread(void *_create)
 		create->result = ERR_PTR(pid);
 	} else {
 		wait_for_completion(&create->started);
-		create->result = find_task_by_pid(pid);
+		create->result = find_task_by_real_pid(pid);
 	}
 	complete(&create->done);
 }
diff --git a/kernel/module.c b/kernel/module.c
index dfe295ecf..8b3726655 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -89,13 +89,6 @@ static inline int strong_try_module_get(struct module *mod)
 	return try_module_get(mod);
 }
 
-/* Stub function for modules which don't have an initfn */
-int init_module(void)
-{
-	return 0;
-}
-EXPORT_SYMBOL(init_module);
-
 /* A thread that wants to hold a reference to a module only while it
  * is running can call ths to safely exit.
  * nfsd and lockd use this.
@@ -529,12 +522,6 @@ EXPORT_SYMBOL(module_refcount);
 /* This exists whether we can unload or not */
 static void free_module(struct module *mod);
 
-/* Stub function for modules which don't have an exitfn */
-void cleanup_module(void)
-{
-}
-EXPORT_SYMBOL(cleanup_module);
-
 static void wait_for_zero_refcount(struct module *mod)
 {
 	/* Since we might sleep for some time, drop the semaphore first */
@@ -589,7 +576,7 @@ sys_delete_module(const char __user *name_user, unsigned int flags)
 	}
 
 	/* If it has an init func, it must have an exit func to unload */
-	if ((mod->init != init_module && mod->exit == cleanup_module)
+	if ((mod->init != NULL && mod->exit == NULL)
 	    || mod->unsafe) {
 		forced = try_force(flags);
 		if (!forced) {
@@ -610,9 +597,11 @@ sys_delete_module(const char __user *name_user, unsigned int flags)
 		wait_for_zero_refcount(mod);
 
 	/* Final destruction now noone is using it. */
-	up(&module_mutex);
-	mod->exit();
-	down(&module_mutex);
+	if (mod->exit != NULL) {
+		up(&module_mutex);
+		mod->exit();
+		down(&module_mutex);
+	}
 	free_module(mod);
 
  out:
@@ -639,7 +628,7 @@ static void print_unload_info(struct seq_file *m, struct module *mod)
 		seq_printf(m, "[unsafe],");
 	}
 
-	if (mod->init != init_module && mod->exit == cleanup_module) {
+	if (mod->init != NULL && mod->exit == NULL) {
 		printed_something = 1;
 		seq_printf(m, "[permanent],");
 	}
@@ -725,19 +714,6 @@ static inline int sysfs_unload_setup(struct module *mod)
 #endif /* CONFIG_MODULE_UNLOAD */
 
 #ifdef CONFIG_OBSOLETE_MODPARM
-static int param_set_byte(const char *val, struct kernel_param *kp)  
-{
-	char *endp;
-	long l;
-
-	if (!val) return -EINVAL;
-	l = simple_strtol(val, &endp, 0);
-	if (endp == val || *endp || ((char)l != l))
-		return -EINVAL;
-	*((char *)kp->arg) = l;
-	return 0;
-}
-
 /* Bounds checking done below */
 static int obsparm_copy_string(const char *val, struct kernel_param *kp)
 {
@@ -1551,9 +1527,6 @@ static struct module *load_module(void __user *umod,
 	secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
 	sechdrs[0].sh_addr = 0;
 
-	/* And these should exist, but gcc whinges if we don't init them */
-	symindex = strindex = 0;
-
 	for (i = 1; i < hdr->e_shnum; i++) {
 		if (sechdrs[i].sh_type != SHT_NOBITS
 		    && len < sechdrs[i].sh_offset + sechdrs[i].sh_size)
@@ -1585,6 +1558,13 @@ static struct module *load_module(void __user *umod,
 	}
 	mod = (void *)sechdrs[modindex].sh_addr;
 
+	if (symindex == 0) {
+		printk(KERN_WARNING "%s: module has no symbols (stripped?)\n",
+		       mod->name);
+		err = -ENOEXEC;
+		goto free_hdr;
+	}
+
 	/* Optional sections */
 	exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab");
 	gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl");
@@ -1845,7 +1825,7 @@ sys_init_module(void __user *umod,
 		const char __user *uargs)
 {
 	struct module *mod;
-	int ret;
+	int ret = 0;
 
 	/* Must have permission */
 	if (!capable(CAP_SYS_MODULE))
@@ -1884,7 +1864,8 @@ sys_init_module(void __user *umod,
 	up(&notify_mutex);
 
 	/* Start the module */
-	ret = mod->init();
+	if (mod->init != NULL)
+		ret = mod->init();
 	if (ret < 0) {
 		/* Init routine failed: abort.  Try to protect us from
                    buggy refcounters. */
diff --git a/kernel/panic.c b/kernel/panic.c
index 3c1581eb6..b3abe97f8 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -59,13 +59,7 @@ NORET_TYPE void panic(const char * fmt, ...)
 	va_start(args, fmt);
 	vsnprintf(buf, sizeof(buf), fmt, args);
 	va_end(args);
-	printk(KERN_EMERG "Kernel panic: %s\n",buf);
-	if (in_interrupt())
-		printk(KERN_EMERG "In interrupt handler - not syncing\n");
-	else if (!current->pid)
-		printk(KERN_EMERG "In idle task - not syncing\n");
-	else
-		sys_sync();
+	printk(KERN_EMERG "Kernel panic - not syncing: %s\n",buf);
 	bust_spinlocks(0);
 
 #ifdef CONFIG_SMP
diff --git a/kernel/params.c b/kernel/params.c
index 5f38ee74a..cfd8a8413 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -171,6 +171,7 @@ int parse_args(const char *name,
 		return sprintf(buffer, format, *((type *)kp->arg));	\
 	}
 
+STANDARD_PARAM_DEF(byte, unsigned char, "%c", unsigned long, simple_strtoul);
 STANDARD_PARAM_DEF(short, short, "%hi", long, simple_strtol);
 STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", unsigned long, simple_strtoul);
 STANDARD_PARAM_DEF(int, int, "%i", long, simple_strtol);
@@ -339,6 +340,14 @@ int param_set_copystring(const char *val, struct kernel_param *kp)
 	return 0;
 }
 
+int param_get_string(char *buffer, struct kernel_param *kp)
+{
+	struct kparam_string *kps = kp->arg;
+	return strlcpy(buffer, kps->string, kps->maxlen);
+}
+
+EXPORT_SYMBOL(param_set_byte);
+EXPORT_SYMBOL(param_get_byte);
 EXPORT_SYMBOL(param_set_short);
 EXPORT_SYMBOL(param_get_short);
 EXPORT_SYMBOL(param_set_ushort);
@@ -360,3 +369,4 @@ EXPORT_SYMBOL(param_get_invbool);
 EXPORT_SYMBOL(param_array_set);
 EXPORT_SYMBOL(param_array_get);
 EXPORT_SYMBOL(param_set_copystring);
+EXPORT_SYMBOL(param_get_string);
diff --git a/kernel/pid.c b/kernel/pid.c
index 23706b226..83008f812 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -25,10 +25,9 @@
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/hash.h>
-#include <linux/vs_cvirt.h>
 
 #define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift)
-static struct list_head *pid_hash[PIDTYPE_MAX];
+static struct hlist_head *pid_hash[PIDTYPE_MAX];
 static int pidhash_shift;
 
 int pid_max = PID_MAX_DEFAULT;
@@ -147,73 +146,66 @@ failure:
 	return -1;
 }
 
-fastcall struct pid *find_pid(enum pid_type type, int nr)
+struct pid * fastcall find_pid(enum pid_type type, int nr)
 {
-	struct list_head *elem, *bucket = &pid_hash[type][pid_hashfn(nr)];
+	struct hlist_node *elem;
 	struct pid *pid;
 
-	__list_for_each(elem, bucket) {
-		pid = list_entry(elem, struct pid, hash_chain);
+	hlist_for_each_entry(pid, elem,
+			&pid_hash[type][pid_hashfn(nr)], pid_chain) {
 		if (pid->nr == nr)
 			return pid;
 	}
 	return NULL;
 }
 
-void fastcall link_pid(task_t *task, struct pid_link *link, struct pid *pid)
-{
-	atomic_inc(&pid->count);
-	list_add_tail(&link->pid_chain, &pid->task_list);
-	link->pidptr = pid;
-}
-
 int fastcall attach_pid(task_t *task, enum pid_type type, int nr)
 {
-	struct pid *pid = find_pid(type, nr);
-
-	if (pid)
-		atomic_inc(&pid->count);
-	else {
-		pid = &task->pids[type].pid;
-		pid->nr = nr;
-		atomic_set(&pid->count, 1);
-		INIT_LIST_HEAD(&pid->task_list);
-		pid->task = task;
-		get_task_struct(task);
-		list_add(&pid->hash_chain, &pid_hash[type][pid_hashfn(nr)]);
+	struct pid *pid, *task_pid;
+
+	task_pid = &task->pids[type];
+	pid = find_pid(type, nr);
+	if (pid == NULL) {
+		hlist_add_head(&task_pid->pid_chain,
+				&pid_hash[type][pid_hashfn(nr)]);
+		INIT_LIST_HEAD(&task_pid->pid_list);
+	} else {
+		INIT_HLIST_NODE(&task_pid->pid_chain);
+		list_add_tail(&task_pid->pid_list, &pid->pid_list);
 	}
-	list_add_tail(&task->pids[type].pid_chain, &pid->task_list);
-	task->pids[type].pidptr = pid;
+	task_pid->nr = nr;
 
 	return 0;
 }
 
 static inline int __detach_pid(task_t *task, enum pid_type type)
 {
-	struct pid_link *link = task->pids + type;
-	struct pid *pid = link->pidptr;
+	struct pid *pid, *pid_next;
 	int nr;
 
-	list_del(&link->pid_chain);
-	if (!atomic_dec_and_test(&pid->count))
-		return 0;
-
+	pid = &task->pids[type];
+	if (!hlist_unhashed(&pid->pid_chain)) {
+		hlist_del(&pid->pid_chain);
+		if (!list_empty(&pid->pid_list)) {
+			pid_next = list_entry(pid->pid_list.next,
+						struct pid, pid_list);
+			/* insert next pid from pid_list to hash */
+			hlist_add_head(&pid_next->pid_chain,
+				&pid_hash[type][pid_hashfn(pid_next->nr)]);
+		}
+	}
+	list_del(&pid->pid_list);
 	nr = pid->nr;
-	list_del(&pid->hash_chain);
-	put_task_struct(pid->task);
+	pid->nr = 0;
 
 	return nr;
 }
 
-static void _detach_pid(task_t *task, enum pid_type type)
-{
-	__detach_pid(task, type);
-}
-
 void fastcall detach_pid(task_t *task, enum pid_type type)
 {
-	int nr = __detach_pid(task, type);
+	int nr;
 
+	nr = __detach_pid(task, type);
 	if (!nr)
 		return;
 
@@ -223,17 +215,18 @@ void fastcall detach_pid(task_t *task, enum pid_type type)
 	free_pidmap(nr);
 }
 
-task_t *find_task_by_pid(int nr)
+task_t *find_task_by_pid_type(int type, int nr)
 {
-	struct pid *pid = find_pid(PIDTYPE_PID,
-		vx_rmap_tgid(current->vx_info, nr));
+	struct pid *pid;
 
+	pid = find_pid(type, nr);
 	if (!pid)
 		return NULL;
-	return pid_task(pid->task_list.next, PIDTYPE_PID);
+
+	return pid_task(&pid->pid_list, type);
 }
 
-EXPORT_SYMBOL(find_task_by_pid);
+EXPORT_SYMBOL(find_task_by_pid_type);
 
 /*
  * This function switches the PIDs if a non-leader thread calls
@@ -242,13 +235,13 @@ EXPORT_SYMBOL(find_task_by_pid);
  */
 void switch_exec_pids(task_t *leader, task_t *thread)
 {
-	_detach_pid(leader, PIDTYPE_PID);
-	_detach_pid(leader, PIDTYPE_TGID);
-	_detach_pid(leader, PIDTYPE_PGID);
-	_detach_pid(leader, PIDTYPE_SID);
+	__detach_pid(leader, PIDTYPE_PID);
+	__detach_pid(leader, PIDTYPE_TGID);
+	__detach_pid(leader, PIDTYPE_PGID);
+	__detach_pid(leader, PIDTYPE_SID);
 
-	_detach_pid(thread, PIDTYPE_PID);
-	_detach_pid(thread, PIDTYPE_TGID);
+	__detach_pid(thread, PIDTYPE_PID);
+	__detach_pid(thread, PIDTYPE_TGID);
 
 	leader->pid = leader->tgid = thread->pid;
 	thread->pid = thread->tgid;
@@ -273,23 +266,23 @@ void switch_exec_pids(task_t *leader, task_t *thread)
 void __init pidhash_init(void)
 {
 	int i, j, pidhash_size;
-	unsigned long megabytes = max_pfn >> (20 - PAGE_SHIFT);
+	unsigned long megabytes = nr_kernel_pages >> (20 - PAGE_SHIFT);
 
 	pidhash_shift = max(4, fls(megabytes * 4));
 	pidhash_shift = min(12, pidhash_shift);
 	pidhash_size = 1 << pidhash_shift;
 
-	printk("PID hash table entries: %d (order %d: %Zd bytes)\n",
+	printk("PID hash table entries: %d (order: %d, %Zd bytes)\n",
 		pidhash_size, pidhash_shift,
-		pidhash_size * sizeof(struct list_head));
+		PIDTYPE_MAX * pidhash_size * sizeof(struct hlist_head));
 
 	for (i = 0; i < PIDTYPE_MAX; i++) {
 		pid_hash[i] = alloc_bootmem(pidhash_size *
-					sizeof(struct list_head));
+					sizeof(*(pid_hash[i])));
 		if (!pid_hash[i])
 			panic("Could not alloc pidhash!\n");
 		for (j = 0; j < pidhash_size; j++)
-			INIT_LIST_HEAD(&pid_hash[i][j]);
+			INIT_HLIST_HEAD(&pid_hash[i][j]);
 	}
 }
 
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index 42c248688..72530f71e 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -499,7 +499,7 @@ static inline struct task_struct * good_sigevent(sigevent_t * event)
 	struct task_struct *rtn = current->group_leader;
 
 	if ((event->sigev_notify & SIGEV_THREAD_ID ) &&
-		(!(rtn = find_task_by_pid(event->sigev_notify_thread_id)) ||
+		(!(rtn = find_task_by_real_pid(event->sigev_notify_thread_id)) ||
 		 rtn->tgid != current->tgid ||
 		 (event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_SIGNAL))
 		return NULL;
@@ -650,7 +650,8 @@ sys_timer_create(clockid_t which_clock,
 				list_add(&new_timer->list,
 					 &process->signal->posix_timers);
 				spin_unlock_irqrestore(&process->sighand->siglock, flags);
-				get_task_struct(process);
+				if (new_timer->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID))
+					get_task_struct(process);
 			} else {
 				spin_unlock_irqrestore(&process->sighand->siglock, flags);
 				process = NULL;
@@ -1102,7 +1103,7 @@ retry_delete:
 	if (timer->it_process) {
 		if (timer->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID))
 			put_task_struct(timer->it_process);
-	timer->it_process = NULL;
+		timer->it_process = NULL;
 	}
 	unlock_timer(timer, flags);
 	release_posix_timer(timer, IT_ID_SET);
@@ -1168,15 +1169,10 @@ void exit_itimers(struct signal_struct *sig)
  */
 static int do_posix_gettime(struct k_clock *clock, struct timespec *tp)
 {
-	struct timeval tv;
-
 	if (clock->clock_get)
 		return clock->clock_get(tp);
 
-	do_gettimeofday(&tv);
-	tp->tv_sec = tv.tv_sec;
-	tp->tv_nsec = tv.tv_usec * NSEC_PER_USEC;
-
+	getnstimeofday(tp);
 	return 0;
 }
 
@@ -1192,24 +1188,16 @@ static u64 do_posix_clock_monotonic_gettime_parts(
 	struct timespec *tp, struct timespec *mo)
 {
 	u64 jiff;
-	struct timeval tpv;
 	unsigned int seq;
 
 	do {
 		seq = read_seqbegin(&xtime_lock);
-		do_gettimeofday(&tpv);
+		getnstimeofday(tp);
 		*mo = wall_to_monotonic;
 		jiff = jiffies_64;
 
 	} while(read_seqretry(&xtime_lock, seq));
 
-	/*
-	 * Love to get this before it is converted to usec.
-	 * It would save a div AND a mpy.
-	 */
-	tp->tv_sec = tpv.tv_sec;
-	tp->tv_nsec = tpv.tv_usec * NSEC_PER_USEC;
-
 	return jiff;
 }
 
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 6bb62269f..67f955286 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -18,6 +18,13 @@ config PM
 	  will issue the hlt instruction if nothing is to be done, thereby
 	  sending the processor to sleep and saving power.
 
+config PM_DEBUG
+	bool "Power Management Debug Support"
+	---help---
+	This option enables verbose debugging support in the Power Management
+	code. This is helpful when debugging and reporting various PM bugs, 
+	like suspend support.
+
 config SOFTWARE_SUSPEND
 	bool "Software Suspend (EXPERIMENTAL)"
 	depends on EXPERIMENTAL && PM && SWAP
@@ -42,33 +49,12 @@ config SOFTWARE_SUSPEND
 
 	  For more information take a look at Documentation/power/swsusp.txt.
 
-config PM_DISK
-	bool "Suspend-to-Disk Support"
-	depends on PM && SWAP && X86 && !X86_64
-	---help---
-	  Suspend-to-disk is a power management state in which the contents
-	  of memory are stored on disk and the entire system is shut down or
-	  put into a low-power state (e.g. ACPI S4). When the computer is 
-	  turned back on, the stored image is loaded from disk and execution
-	  resumes from where it left off before suspending. 
-
-	  This config option enables the core infrastructure necessary to 
-	  perform the suspend and resume transition. 
-
-	  Currently, this suspend-to-disk implementation is based on a forked
-	  version of the swsusp code base. As such, it's still experimental,
-	  and still relies on CONFIG_SWAP. 
-
-	  More information can be found in Documentation/power/.
-
-	  If unsure, Say N.
-
-config PM_DISK_PARTITION
+config PM_STD_PARTITION
 	string "Default resume partition"
-	depends on PM_DISK
+	depends on SOFTWARE_SUSPEND
 	default ""
 	---help---
-	  The default resume partition is the partition that the pmdisk suspend-
+	  The default resume partition is the partition that the suspend-
 	  to-disk implementation will look for a suspended disk image. 
 
 	  The partition specified here will be different for almost every user. 
@@ -77,16 +63,10 @@ config PM_DISK_PARTITION
 
 	  The partition specified can be overridden by specifying:
 
-		pmdisk=/dev/<other device> 
+		resume=/dev/<other device> 
 
 	  which will set the resume partition to the device specified. 
 
-	  One may also do: 
-
-		pmdisk=off
-
-	  to inform the kernel not to perform a resume transition. 
-
 	  Note there is currently not a way to specify which device to save the
 	  suspended image to. It will simply pick the first available swap 
 	  device.
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index 2509213f5..fbdc63413 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -1,8 +1,11 @@
 
+ifeq ($(CONFIG_PM_DEBUG),y)
+EXTRA_CFLAGS	+=	-DDEBUG
+endif
+
 swsusp-smp-$(CONFIG_SMP)	+= smp.o
 
 obj-y				:= main.o process.o console.o pm.o
-obj-$(CONFIG_SOFTWARE_SUSPEND)	+= swsusp.o $(swsusp-smp-y)
-obj-$(CONFIG_PM_DISK)		+= disk.o pmdisk.o
+obj-$(CONFIG_SOFTWARE_SUSPEND)	+= swsusp.o $(swsusp-smp-y) disk.o
 
 obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
diff --git a/kernel/power/console.c b/kernel/power/console.c
index 00b390d7a..7ff375e7c 100644
--- a/kernel/power/console.c
+++ b/kernel/power/console.c
@@ -11,7 +11,9 @@
 
 static int new_loglevel = 10;
 static int orig_loglevel;
+#ifdef SUSPEND_CONSOLE
 static int orig_fgconsole, orig_kmsg;
+#endif
 
 int pm_prepare_console(void)
 {
@@ -50,6 +52,7 @@ void pm_restore_console(void)
 	acquire_console_sem();
 	set_console(orig_fgconsole);
 	release_console_sem();
+	kmsg_redirect = orig_kmsg;
 #endif
 	return;
 }
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index 6abcf99b7..312aa169c 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -8,13 +8,11 @@
  *
  */
 
-#define DEBUG
-
-
 #include <linux/suspend.h>
 #include <linux/syscalls.h>
 #include <linux/reboot.h>
 #include <linux/string.h>
+#include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/fs.h>
 #include "power.h"
@@ -23,13 +21,16 @@
 extern u32 pm_disk_mode;
 extern struct pm_ops * pm_ops;
 
-extern int pmdisk_save(void);
-extern int pmdisk_write(void);
-extern int pmdisk_read(void);
-extern int pmdisk_restore(void);
-extern int pmdisk_free(void);
+extern int swsusp_suspend(void);
+extern int swsusp_write(void);
+extern int swsusp_read(void);
+extern int swsusp_resume(void);
+extern int swsusp_free(void);
 
 
+static int noresume = 0;
+char resume_file[256] = CONFIG_PM_STD_PARTITION;
+
 /**
  *	power_down - Shut machine down for hibernate.
  *	@mode:		Suspend-to-disk mode
@@ -46,22 +47,26 @@ static int power_down(u32 mode)
 	int error = 0;
 
 	local_irq_save(flags);
-	device_power_down(PM_SUSPEND_DISK);
 	switch(mode) {
 	case PM_DISK_PLATFORM:
+		device_power_down(PM_SUSPEND_DISK);
 		error = pm_ops->enter(PM_SUSPEND_DISK);
 		break;
 	case PM_DISK_SHUTDOWN:
 		printk("Powering off system\n");
+		device_shutdown();
 		machine_power_off();
 		break;
 	case PM_DISK_REBOOT:
+		device_shutdown();
 		machine_restart(NULL);
 		break;
 	}
 	machine_halt();
-	device_power_up();
-	local_irq_restore(flags);
+	/* Valid image is on the disk, if we continue we risk serious data corruption
+	   after resume. */
+	printk(KERN_CRIT "Please power me down manually\n");
+	while(1);
 	return 0;
 }
 
@@ -99,6 +104,7 @@ static void finish(void)
 {
 	device_resume();
 	platform_finish();
+	enable_nonboot_cpus();
 	thaw_processes();
 	pm_restore_console();
 }
@@ -126,6 +132,7 @@ static int prepare(void)
 	/* Free memory before shutting down devices. */
 	free_some_memory();
 
+	disable_nonboot_cpus();
 	if ((error = device_suspend(PM_SUSPEND_DISK)))
 		goto Finish;
 
@@ -133,6 +140,7 @@ static int prepare(void)
  Finish:
 	platform_finish();
  Thaw:
+	enable_nonboot_cpus();
 	thaw_processes();
 	pm_restore_console();
 	return error;
@@ -161,7 +169,7 @@ int pm_suspend_disk(void)
 
 	pr_debug("PM: snapshotting memory.\n");
 	in_suspend = 1;
-	if ((error = pmdisk_save()))
+	if ((error = swsusp_suspend()))
 		goto Done;
 
 	if (in_suspend) {
@@ -173,14 +181,14 @@ int pm_suspend_disk(void)
 		mb();
 		barrier();
 
-		error = pmdisk_write();
+		error = swsusp_write();
 		if (!error) {
 			error = power_down(pm_disk_mode);
 			pr_debug("PM: Power down failed.\n");
 		}
 	} else
 		pr_debug("PM: Image restored successfully.\n");
-	pmdisk_free();
+	swsusp_free();
  Done:
 	finish();
 	return error;
@@ -188,7 +196,7 @@ int pm_suspend_disk(void)
 
 
 /**
- *	pm_resume - Resume from a saved image.
+ *	software_resume - Resume from a saved image.
  *
  *	Called as a late_initcall (so all devices are discovered and
  *	initialized), we call pmdisk to see if we have a saved image or not.
@@ -199,13 +207,21 @@ int pm_suspend_disk(void)
  *
  */
 
-static int pm_resume(void)
+static int software_resume(void)
 {
 	int error;
 
+	if (noresume) {
+		/**
+		 * FIXME: If noresume is specified, we need to find the partition
+		 * and reset it back to normal swap space.
+		 */
+		return 0;
+	}
+
 	pr_debug("PM: Reading pmdisk image.\n");
 
-	if ((error = pmdisk_read()))
+	if ((error = swsusp_read()))
 		goto Done;
 
 	pr_debug("PM: Preparing system for restore.\n");
@@ -216,28 +232,18 @@ static int pm_resume(void)
 	barrier();
 	mb();
 
-	/* FIXME: The following (comment and mdelay()) are from swsusp.
-	 * Are they really necessary?
-	 *
-	 * We do not want some readahead with DMA to corrupt our memory, right?
-	 * Do it with disabled interrupts for best effect. That way, if some
-	 * driver scheduled DMA, we have good chance for DMA to finish ;-).
-	 */
-	pr_debug("PM: Waiting for DMAs to settle down.\n");
-	mdelay(1000);
-
 	pr_debug("PM: Restoring saved image.\n");
-	pmdisk_restore();
+	swsusp_resume();
 	pr_debug("PM: Restore failed, recovering.n");
 	finish();
  Free:
-	pmdisk_free();
+	swsusp_free();
  Done:
 	pr_debug("PM: Resume from disk failed.\n");
 	return 0;
 }
 
-late_initcall(pm_resume);
+late_initcall(software_resume);
 
 
 static char * pm_disk_modes[] = {
@@ -336,3 +342,22 @@ static int __init pm_disk_init(void)
 }
 
 core_initcall(pm_disk_init);
+
+
+static int __init resume_setup(char *str)
+{
+	if (noresume)
+		return 1;
+
+	strncpy( resume_file, str, 255 );
+	return 1;
+}
+
+static int __init noresume_setup(char *str)
+{
+	noresume = 1;
+	return 1;
+}
+
+__setup("noresume", noresume_setup);
+__setup("resume=", resume_setup);
diff --git a/kernel/power/main.c b/kernel/power/main.c
index d582906fe..2f08a432f 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -8,8 +8,6 @@
  *
  */
 
-#define DEBUG
-
 #include <linux/suspend.h>
 #include <linux/kobject.h>
 #include <linux/string.h>
@@ -35,8 +33,6 @@ void pm_set_ops(struct pm_ops * ops)
 {
 	down(&pm_sem);
 	pm_ops = ops;
-	if (ops->pm_disk_mode && ops->pm_disk_mode < PM_DISK_MAX)
-		pm_disk_mode = ops->pm_disk_mode;
 	up(&pm_sem);
 }
 
@@ -169,6 +165,15 @@ static int enter_state(u32 state)
 	return error;
 }
 
+/*
+ * This is main interface to the outside world. It needs to be
+ * called from process context.
+ */
+int software_suspend(void)
+{
+	return enter_state(PM_SUSPEND_DISK);
+}
+
 
 /**
  *	pm_suspend - Externally visible function for suspending system.
@@ -225,8 +230,8 @@ static ssize_t state_store(struct subsystem * subsys, const char * buf, size_t n
 	p = memchr(buf, '\n', n);
 	len = p ? p - buf : n;
 
-	for (s = &pm_states[state]; *s; s++, state++) {
-		if (!strncmp(buf, *s, len))
+	for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {
+		if (*s && !strncmp(buf, *s, len))
 			break;
 	}
 	if (*s)
diff --git a/kernel/power/power.h b/kernel/power/power.h
index d180b0a19..cd6a3493c 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -1,4 +1,5 @@
-
+#include <linux/suspend.h>
+#include <linux/utsname.h>
 
 /* With SUSPEND_CONSOLE defined, it suspend looks *really* cool, but
    we probably do not take enough locks for switching consoles, etc,
@@ -9,7 +10,20 @@
 #endif
 
 
-#ifdef CONFIG_PM_DISK
+struct swsusp_info {
+	struct new_utsname	uts;
+	u32			version_code;
+	unsigned long		num_physpages;
+	int			cpus;
+	unsigned long		image_pages;
+	unsigned long		pagedir_pages;
+	suspend_pagedir_t	* suspend_pagedir;
+	swp_entry_t		pagedir[768];
+} __attribute__((aligned(PAGE_SIZE)));
+
+
+
+#ifdef CONFIG_SOFTWARE_SUSPEND
 extern int pm_suspend_disk(void);
 
 #else
@@ -18,7 +32,6 @@ static inline int pm_suspend_disk(void)
 	return -EPERM;
 }
 #endif
-
 extern struct semaphore pm_sem;
 #define power_attr(_name) \
 static struct subsys_attribute _name##_attr = {	\
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 0d1f63ec7..bda013de5 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -25,7 +25,8 @@ static inline int freezeable(struct task_struct * p)
 	    (p->flags & PF_NOFREEZE) ||
 	    (p->state == TASK_ZOMBIE) ||
 	    (p->state == TASK_DEAD) ||
-	    (p->state == TASK_STOPPED))
+	    (p->state == TASK_STOPPED) ||
+	    (p->state == TASK_TRACED))
 		return 0;
 	return 1;
 }
@@ -70,6 +71,7 @@ int freeze_processes(void)
 			if (!freezeable(p))
 				continue;
 			if ((p->flags & PF_FROZEN) ||
+			    (p->state == TASK_TRACED) ||
 			    (p->state == TASK_STOPPED))
 				continue;
 
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index 081b65103..1c49df18d 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -62,6 +62,7 @@
 #include <linux/syscalls.h>
 #include <linux/console.h>
 #include <linux/highmem.h>
+#include <linux/bio.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -70,25 +71,16 @@
 
 #include "power.h"
 
-unsigned char software_suspend_enabled = 0;
-
-#define NORESUME		1
-#define RESUME_SPECIFIED	2
-
 /* References to section boundaries */
 extern char __nosave_begin, __nosave_end;
 
 extern int is_head_of_free_region(struct page *);
 
-/* Locks */
-spinlock_t suspend_pagedir_lock __nosavedata = SPIN_LOCK_UNLOCKED;
-
 /* Variables to be preserved over suspend */
-static int pagedir_order_check;
-static int nr_copy_pages_check;
+int pagedir_order_check;
+int nr_copy_pages_check;
 
-static int resume_status;
-static char resume_file[256] = "";			/* For resume= kernel option */
+extern char resume_file[];
 static dev_t resume_device;
 /* Local variables that should not be affected by save */
 unsigned int nr_copy_pages __nosavedata = 0;
@@ -110,16 +102,16 @@ suspend_pagedir_t *pagedir_nosave __nosavedata = NULL;
 static suspend_pagedir_t *pagedir_save;
 static int pagedir_order __nosavedata = 0;
 
-struct link {
-	char dummy[PAGE_SIZE - sizeof(swp_entry_t)];
-	swp_entry_t next;
-};
+#define SWSUSP_SIG	"S1SUSPEND"
 
-union diskpage {
-	union swap_header swh;
-	struct link link;
-	struct suspend_header sh;
-};
+struct swsusp_header {
+	char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)];
+	swp_entry_t swsusp_info;
+	char	orig_sig[10];
+	char	sig[10];
+} __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header;
+
+struct swsusp_info swsusp_info;
 
 /*
  * XXX: We try to keep some more pages free so that I/O operations succeed
@@ -127,54 +119,10 @@ union diskpage {
  */
 #define PAGES_FOR_IO	512
 
-static const char name_suspend[] = "Suspend Machine: ";
-static const char name_resume[] = "Resume Machine: ";
-
-/*
- * Debug
- */
-#define	DEBUG_DEFAULT
-#undef	DEBUG_PROCESS
-#undef	DEBUG_SLOW
-#define TEST_SWSUSP 0		/* Set to 1 to reboot instead of halt machine after suspension */
-
-#ifdef DEBUG_DEFAULT
-# define PRINTK(f, a...)	printk(f, ## a)
-#else
-# define PRINTK(f, a...)       	do { } while(0)
-#endif
-
-#ifdef DEBUG_SLOW
-#define MDELAY(a) mdelay(a)
-#else
-#define MDELAY(a) do { } while(0)
-#endif
-
 /*
  * Saving part...
  */
 
-static __inline__ int fill_suspend_header(struct suspend_header *sh)
-{
-	memset((char *)sh, 0, sizeof(*sh));
-
-	sh->version_code = LINUX_VERSION_CODE;
-	sh->num_physpages = num_physpages;
-	strncpy(sh->machine, system_utsname.machine, 8);
-	strncpy(sh->version, system_utsname.version, 20);
-	/* FIXME: Is this bogus? --RR */
-	sh->num_cpus = num_online_cpus();
-	sh->page_size = PAGE_SIZE;
-	sh->suspend_pagedir = pagedir_nosave;
-	BUG_ON (pagedir_save != pagedir_nosave);
-	sh->num_pbes = nr_copy_pages;
-	/* TODO: needed? mounted fs' last mounted date comparison
-	 * [so they haven't been mounted since last suspend.
-	 * Maybe it isn't.] [we'd need to do this for _all_ fs-es]
-	 */
-	return 0;
-}
-
 /* We memorize in swapfile_used what swap devices are used for suspension */
 #define SWAPFILE_UNUSED    0
 #define SWAPFILE_SUSPEND   1	/* This is the suspending device */
@@ -182,47 +130,30 @@ static __inline__ int fill_suspend_header(struct suspend_header *sh)
 
 static unsigned short swapfile_used[MAX_SWAPFILES];
 static unsigned short root_swap;
-#define MARK_SWAP_SUSPEND 0
-#define MARK_SWAP_RESUME 2
 
-static void mark_swapfiles(swp_entry_t prev, int mode)
+static int mark_swapfiles(swp_entry_t prev)
 {
-	swp_entry_t entry;
-	union diskpage *cur;
-	struct page *page;
+	int error;
 
-	if (root_swap == 0xFFFF)  /* ignored */
-		return;
-
-	page = alloc_page(GFP_ATOMIC);
-	if (!page)
-		panic("Out of memory in mark_swapfiles");
-	cur = page_address(page);
-	/* XXX: this is dirty hack to get first page of swap file */
-	entry = swp_entry(root_swap, 0);
-	rw_swap_page_sync(READ, entry, page);
-
-	if (mode == MARK_SWAP_RESUME) {
-	  	if (!memcmp("S1",cur->swh.magic.magic,2))
-		  	memcpy(cur->swh.magic.magic,"SWAP-SPACE",10);
-		else if (!memcmp("S2",cur->swh.magic.magic,2))
-			memcpy(cur->swh.magic.magic,"SWAPSPACE2",10);
-		else printk("%sUnable to find suspended-data signature (%.10s - misspelled?\n", 
-		      	name_resume, cur->swh.magic.magic);
+	rw_swap_page_sync(READ, 
+			  swp_entry(root_swap, 0),
+			  virt_to_page((unsigned long)&swsusp_header));
+	if (!memcmp("SWAP-SPACE",swsusp_header.sig, 10) ||
+	    !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) {
+		memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10);
+		memcpy(swsusp_header.sig,SWSUSP_SIG, 10);
+		swsusp_header.swsusp_info = prev;
+		error = rw_swap_page_sync(WRITE, 
+					  swp_entry(root_swap, 0),
+					  virt_to_page((unsigned long)
+						       &swsusp_header));
 	} else {
-	  	if ((!memcmp("SWAP-SPACE",cur->swh.magic.magic,10)))
-		  	memcpy(cur->swh.magic.magic,"S1SUSP....",10);
-		else if ((!memcmp("SWAPSPACE2",cur->swh.magic.magic,10)))
-			memcpy(cur->swh.magic.magic,"S2SUSP....",10);
-		else panic("\nSwapspace is not swapspace (%.10s)\n", cur->swh.magic.magic);
-		cur->link.next = prev; /* prev is the first/last swap page of the resume area */
-		/* link.next lies *no more* in last 4/8 bytes of magic */
+		pr_debug("swsusp: Partition is not swap space.\n");
+		error = -ENODEV;
 	}
-	rw_swap_page_sync(WRITE, entry, page);
-	__free_page(page);
+	return error;
 }
 
-
 /*
  * Check whether the swap device is the specified resume
  * device, irrespective of whether they are specified by
@@ -243,7 +174,7 @@ static int is_resume_device(const struct swap_info_struct *swap_info)
 		resume_device == MKDEV(imajor(inode), iminor(inode));
 }
 
-static void read_swapfiles(void) /* This is called before saving image */
+int swsusp_swap_check(void) /* This is called before saving image */
 {
 	int i, len;
 	
@@ -274,114 +205,211 @@ static void read_swapfiles(void) /* This is called before saving image */
 		}
 	}
 	swap_list_unlock();
+	return (root_swap != 0xffff) ? 0 : -ENODEV;
 }
 
-static void lock_swapdevices(void) /* This is called after saving image so modification
-				      will be lost after resume... and that's what we want. */
+/**
+ * This is called after saving image so modification
+ * will be lost after resume... and that's what we want.
+ * we make the device unusable. A new call to
+ * lock_swapdevices can unlock the devices. 
+ */
+static void lock_swapdevices(void)
 {
 	int i;
 
 	swap_list_lock();
 	for(i = 0; i< MAX_SWAPFILES; i++)
 		if(swapfile_used[i] == SWAPFILE_IGNORED) {
-			swap_info[i].flags ^= 0xFF; /* we make the device unusable. A new call to
-						       lock_swapdevices can unlock the devices. */
+			swap_info[i].flags ^= 0xFF;
 		}
 	swap_list_unlock();
 }
 
+
+
 /**
- *    write_suspend_image - Write entire image to disk.
+ *	write_swap_page - Write one page to a fresh swap location.
+ *	@addr:	Address we're writing.
+ *	@loc:	Place to store the entry we used.
  *
- *    After writing suspend signature to the disk, suspend may no
- *    longer fail: we have ready-to-run image in swap, and rollback
- *    would happen on next reboot -- corrupting data.
+ *	Allocate a new swap entry and 'sync' it. Note we discard -EIO
+ *	errors. That is an artifact left over from swsusp. It did not 
+ *	check the return of rw_swap_page_sync() at all, since most pages
+ *	written back to swap would return -EIO.
+ *	This is a partial improvement, since we will at least return other
+ *	errors, though we need to eventually fix the damn code.
+ */
+
+static int write_page(unsigned long addr, swp_entry_t * loc)
+{
+	swp_entry_t entry;
+	int error = 0;
+
+	entry = get_swap_page();
+	if (swp_offset(entry) && 
+	    swapfile_used[swp_type(entry)] == SWAPFILE_SUSPEND) {
+		error = rw_swap_page_sync(WRITE, entry,
+					  virt_to_page(addr));
+		if (error == -EIO)
+			error = 0;
+		if (!error)
+			*loc = entry;
+	} else
+		error = -ENOSPC;
+	return error;
+}
+
+
+/**
+ *	data_free - Free the swap entries used by the saved image.
  *
- *    Note: The buffer we allocate to use to write the suspend header is
- *    not freed; its not needed since the system is going down anyway
- *    (plus it causes an oops and I'm lazy^H^H^H^Htoo busy).
+ *	Walk the list of used swap entries and free each one. 
+ *	This is only used for cleanup when suspend fails.
  */
-static int write_suspend_image(void)
+
+static void data_free(void)
 {
+	swp_entry_t entry;
 	int i;
-	swp_entry_t entry, prev = { 0 };
-	int nr_pgdir_pages = SUSPEND_PD_PAGES(nr_copy_pages);
-	union diskpage *cur,  *buffer = (union diskpage *)get_zeroed_page(GFP_ATOMIC);
-	unsigned long address;
-	struct page *page;
 
-	if (!buffer)
-		return -ENOMEM;
+	for (i = 0; i < nr_copy_pages; i++) {
+		entry = (pagedir_nosave + i)->swap_address;
+		if (entry.val)
+			swap_free(entry);
+		else
+			break;
+		(pagedir_nosave + i)->swap_address = (swp_entry_t){0};
+	}
+}
+
+
+/**
+ *	data_write - Write saved image to swap.
+ *
+ *	Walk the list of pages in the image and sync each one to swap.
+ */
+
+static int data_write(void)
+{
+	int error = 0;
+	int i;
 
 	printk( "Writing data to swap (%d pages): ", nr_copy_pages );
-	for (i=0; i<nr_copy_pages; i++) {
+	for (i = 0; i < nr_copy_pages && !error; i++) {
 		if (!(i%100))
 			printk( "." );
-		entry = get_swap_page();
-		if (!entry.val)
-			panic("\nNot enough swapspace when writing data" );
-		
-		if (swapfile_used[swp_type(entry)] != SWAPFILE_SUSPEND)
-			panic("\nPage %d: not enough swapspace on suspend device", i );
-	    
-		address = (pagedir_nosave+i)->address;
-		page = virt_to_page(address);
-		rw_swap_page_sync(WRITE, entry, page);
-		(pagedir_nosave+i)->swap_address = entry;
+		error = write_page((pagedir_nosave+i)->address,
+					  &((pagedir_nosave+i)->swap_address));
 	}
-	printk( "|\n" );
-	printk( "Writing pagedir (%d pages): ", nr_pgdir_pages);
-	for (i=0; i<nr_pgdir_pages; i++) {
-		cur = (union diskpage *)((char *) pagedir_nosave)+i;
-		BUG_ON ((char *) cur != (((char *) pagedir_nosave) + i*PAGE_SIZE));
-		printk( "." );
-		entry = get_swap_page();
-		if (!entry.val) {
-			printk(KERN_CRIT "Not enough swapspace when writing pgdir\n" );
-			panic("Don't know how to recover");
-			free_page((unsigned long) buffer);
-			return -ENOSPC;
-		}
+	printk(" %d Pages done.\n",i);
+	return error;
+}
 
-		if(swapfile_used[swp_type(entry)] != SWAPFILE_SUSPEND)
-			panic("\nNot enough swapspace for pagedir on suspend device" );
+static void dump_info(void)
+{
+	pr_debug(" swsusp: Version: %u\n",swsusp_info.version_code);
+	pr_debug(" swsusp: Num Pages: %ld\n",swsusp_info.num_physpages);
+	pr_debug(" swsusp: UTS Sys: %s\n",swsusp_info.uts.sysname);
+	pr_debug(" swsusp: UTS Node: %s\n",swsusp_info.uts.nodename);
+	pr_debug(" swsusp: UTS Release: %s\n",swsusp_info.uts.release);
+	pr_debug(" swsusp: UTS Version: %s\n",swsusp_info.uts.version);
+	pr_debug(" swsusp: UTS Machine: %s\n",swsusp_info.uts.machine);
+	pr_debug(" swsusp: UTS Domain: %s\n",swsusp_info.uts.domainname);
+	pr_debug(" swsusp: CPUs: %d\n",swsusp_info.cpus);
+	pr_debug(" swsusp: Image: %ld Pages\n",swsusp_info.image_pages);
+	pr_debug(" swsusp: Pagedir: %ld Pages\n",swsusp_info.pagedir_pages);
+}
 
-		BUG_ON (sizeof(swp_entry_t) != sizeof(long));
-		BUG_ON (PAGE_SIZE % sizeof(struct pbe));
+static void init_header(void)
+{
+	memset(&swsusp_info,0,sizeof(swsusp_info));
+	swsusp_info.version_code = LINUX_VERSION_CODE;
+	swsusp_info.num_physpages = num_physpages;
+	memcpy(&swsusp_info.uts,&system_utsname,sizeof(system_utsname));
+
+	swsusp_info.suspend_pagedir = pagedir_nosave;
+	swsusp_info.cpus = num_online_cpus();
+	swsusp_info.image_pages = nr_copy_pages;
+	dump_info();
+}
 
-		cur->link.next = prev;				
-		page = virt_to_page((unsigned long)cur);
-		rw_swap_page_sync(WRITE, entry, page);
-		prev = entry;
+static int close_swap(void)
+{
+	swp_entry_t entry;
+	int error;
+
+	error = write_page((unsigned long)&swsusp_info,&entry);
+	if (!error) { 
+		printk( "S" );
+		error = mark_swapfiles(entry);
+		printk( "|\n" );
 	}
-	printk("H");
-	BUG_ON (sizeof(struct suspend_header) > PAGE_SIZE-sizeof(swp_entry_t));
-	BUG_ON (sizeof(union diskpage) != PAGE_SIZE);
-	BUG_ON (sizeof(struct link) != PAGE_SIZE);
-	entry = get_swap_page();
-	if (!entry.val)
-		panic( "\nNot enough swapspace when writing header" );
-	if (swapfile_used[swp_type(entry)] != SWAPFILE_SUSPEND)
-		panic("\nNot enough swapspace for header on suspend device" );
-
-	cur = (void *) buffer;
-	if (fill_suspend_header(&cur->sh))
-		BUG();		/* Not a BUG_ON(): we want fill_suspend_header to be called, always */
-		
-	cur->link.next = prev;
-
-	page = virt_to_page((unsigned long)cur);
-	rw_swap_page_sync(WRITE, entry, page);
-	prev = entry;
-
-	printk( "S" );
-	mark_swapfiles(prev, MARK_SWAP_SUSPEND);
-	printk( "|\n" );
-
-	MDELAY(1000);
-	return 0;
+	return error;
 }
 
+/**
+ *	free_pagedir_entries - Free pages used by the page directory.
+ *
+ *	This is used during suspend for error recovery.
+ */
+
+static void free_pagedir_entries(void)
+{
+	int i;
+
+	for (i = 0; i < swsusp_info.pagedir_pages; i++)
+		swap_free(swsusp_info.pagedir[i]);
+}
+
+
+/**
+ *	write_pagedir - Write the array of pages holding the page directory.
+ *	@last:	Last swap entry we write (needed for header).
+ */
+
+static int write_pagedir(void)
+{
+	unsigned long addr = (unsigned long)pagedir_nosave;
+	int error = 0;
+	int n = SUSPEND_PD_PAGES(nr_copy_pages);
+	int i;
+
+	swsusp_info.pagedir_pages = n;
+	printk( "Writing pagedir (%d pages)\n", n);
+	for (i = 0; i < n && !error; i++, addr += PAGE_SIZE)
+		error = write_page(addr, &swsusp_info.pagedir[i]);
+	return error;
+}
+
+/**
+ *	write_suspend_image - Write entire image and metadata.
+ *
+ */
+
+static int write_suspend_image(void)
+{
+	int error;
+
+	init_header();
+	if ((error = data_write()))
+		goto FreeData;
+
+	if ((error = write_pagedir()))
+		goto FreePagedir;
+
+	if ((error = close_swap()))
+		goto FreePagedir;
+ Done:
+	return error;
+ FreePagedir:
+	free_pagedir_entries();
+ FreeData:
+	data_free();
+	goto Done;
+}
+
+
 #ifdef CONFIG_HIGHMEM
 struct highmem_page {
 	char *data;
@@ -438,22 +466,30 @@ static int save_highmem_zone(struct zone *zone)
 	}
 	return 0;
 }
+#endif /* CONFIG_HIGHMEM */
+
 
 static int save_highmem(void)
 {
+#ifdef CONFIG_HIGHMEM
 	struct zone *zone;
 	int res = 0;
+
+	pr_debug("swsusp: Saving Highmem\n");
 	for_each_zone(zone) {
 		if (is_highmem(zone))
 			res = save_highmem_zone(zone);
 		if (res)
 			return res;
 	}
+#endif
 	return 0;
 }
 
 static int restore_highmem(void)
 {
+#ifdef CONFIG_HIGHMEM
+	printk("swsusp: Restoring Highmem\n");
 	while (highmem_copy) {
 		struct highmem_page *save = highmem_copy;
 		void *kaddr;
@@ -465,9 +501,10 @@ static int restore_highmem(void)
 		free_page((long) save->data);
 		kfree(save);
 	}
+#endif
 	return 0;
 }
-#endif
+
 
 static int pfn_is_nosave(unsigned long pfn)
 {
@@ -476,57 +513,82 @@ static int pfn_is_nosave(unsigned long pfn)
 	return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
 }
 
-/* if *pagedir_p != NULL it also copies the counted pages */
-static int count_and_copy_zone(struct zone *zone, struct pbe **pagedir_p)
+/**
+ *	saveable - Determine whether a page should be cloned or not.
+ *	@pfn:	The page
+ *
+ *	We save a page if it's Reserved, and not in the range of pages
+ *	statically defined as 'unsaveable', or if it isn't reserved, and
+ *	isn't part of a free chunk of pages.
+ *	If it is part of a free chunk, we update @pfn to point to the last 
+ *	page of the chunk.
+ */
+
+static int saveable(struct zone * zone, unsigned long * zone_pfn)
 {
-	unsigned long zone_pfn, chunk_size, nr_copy_pages = 0;
-	struct pbe *pbe = *pagedir_p;
-	for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) {
-		struct page *page;
-		unsigned long pfn = zone_pfn + zone->zone_start_pfn;
+	unsigned long pfn = *zone_pfn + zone->zone_start_pfn;
+	unsigned long chunk_size;
+	struct page * page;
 
-		if (!(pfn%1000))
-			printk(".");
-		if (!pfn_valid(pfn))
-			continue;
-		page = pfn_to_page(pfn);
-		BUG_ON(PageReserved(page) && PageNosave(page));
-		if (PageNosave(page))
-			continue;
-		if (PageReserved(page) && pfn_is_nosave(pfn)) {
-			PRINTK("[nosave pfn 0x%lx]", pfn);
-			continue;
-		}
-		if ((chunk_size = is_head_of_free_region(page))) {
-			pfn += chunk_size - 1;
-			zone_pfn += chunk_size - 1;
-			continue;
+	if (!pfn_valid(pfn))
+		return 0;
+
+	if (!(pfn%1000))
+		printk(".");
+	page = pfn_to_page(pfn);
+	BUG_ON(PageReserved(page) && PageNosave(page));
+	if (PageNosave(page))
+		return 0;
+	if (PageReserved(page) && pfn_is_nosave(pfn)) {
+		pr_debug("[nosave pfn 0x%lx]", pfn);
+		return 0;
+	}
+	if ((chunk_size = is_head_of_free_region(page))) {
+		*zone_pfn += chunk_size - 1;
+		return 0;
+	}
+
+	return 1;
+}
+
+static void count_data_pages(void)
+{
+	struct zone *zone;
+	unsigned long zone_pfn;
+
+	nr_copy_pages = 0;
+
+	for_each_zone(zone) {
+		if (!is_highmem(zone)) {
+			for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn)
+				nr_copy_pages += saveable(zone, &zone_pfn);
 		}
-		nr_copy_pages++;
-		if (!pbe)
-			continue;
-		pbe->orig_address = (long) page_address(page);
-		/* Copy page is dangerous: it likes to mess with
-		   preempt count on specific cpus. Wrong preempt count is then copied,
-		   oops. */
-		copy_page((void *)pbe->address, (void *)pbe->orig_address);
-		pbe++;
 	}
-	*pagedir_p = pbe;
-	return nr_copy_pages;
 }
 
-static int count_and_copy_data_pages(struct pbe *pagedir_p)
+
+static void copy_data_pages(void)
 {
-	int nr_copy_pages = 0;
 	struct zone *zone;
+	unsigned long zone_pfn;
+	struct pbe * pbe = pagedir_nosave;
+	
 	for_each_zone(zone) {
 		if (!is_highmem(zone))
-			nr_copy_pages += count_and_copy_zone(zone, &pagedir_p);
+			for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) {
+				if (saveable(zone, &zone_pfn)) {
+					struct page * page;
+					page = pfn_to_page(zone_pfn + zone->zone_start_pfn);
+					pbe->orig_address = (long) page_address(page);
+					/* copy_page is no usable for copying task structs. */
+					memcpy((void *)pbe->address, (void *)pbe->orig_address, PAGE_SIZE);
+					pbe++;
+				}
+			}
 	}
-	return nr_copy_pages;
 }
 
+
 static void free_suspend_pagedir_zone(struct zone *zone, unsigned long pagedir)
 {
 	unsigned long zone_pfn, pagedir_end, pagedir_pfn, pagedir_end_pfn;
@@ -547,119 +609,202 @@ static void free_suspend_pagedir_zone(struct zone *zone, unsigned long pagedir)
 	}
 }
 
-static void free_suspend_pagedir(unsigned long this_pagedir)
+void swsusp_free(void)
 {
+	unsigned long p = (unsigned long)pagedir_save;
 	struct zone *zone;
 	for_each_zone(zone) {
 		if (!is_highmem(zone))
-			free_suspend_pagedir_zone(zone, this_pagedir);
+			free_suspend_pagedir_zone(zone, p);
 	}
-	free_pages(this_pagedir, pagedir_order);
+	free_pages(p, pagedir_order);
 }
 
-static suspend_pagedir_t *create_suspend_pagedir(int nr_copy_pages)
+
+/**
+ *	calc_order - Determine the order of allocation needed for pagedir_save.
+ *
+ *	This looks tricky, but is just subtle. Please fix it some time.
+ *	Since there are %nr_copy_pages worth of pages in the snapshot, we need
+ *	to allocate enough contiguous space to hold 
+ *		(%nr_copy_pages * sizeof(struct pbe)), 
+ *	which has the saved/orig locations of the page.. 
+ *
+ *	SUSPEND_PD_PAGES() tells us how many pages we need to hold those 
+ *	structures, then we call get_bitmask_order(), which will tell us the
+ *	last bit set in the number, starting with 1. (If we need 30 pages, that
+ *	is 0x0000001e in hex. The last bit is the 5th, which is the order we 
+ *	would use to allocate 32 contiguous pages).
+ *
+ *	Since we also need to save those pages, we add the number of pages that
+ *	we need to nr_copy_pages, and in case of an overflow, do the 
+ *	calculation again to update the number of pages needed. 
+ *
+ *	With this model, we will tend to waste a lot of memory if we just cross
+ *	an order boundary. Plus, the higher the order of allocation that we try
+ *	to do, the more likely we are to fail in a low-memory situtation 
+ *	(though	we're unlikely to get this far in such a case, since swsusp 
+ *	requires half of memory to be free anyway).
+ */
+
+
+static void calc_order(void)
 {
-	int i;
-	suspend_pagedir_t *pagedir;
-	struct pbe *p;
-	struct page *page;
+	int diff = 0;
+	int order = 0;
+
+	do {
+		diff = get_bitmask_order(SUSPEND_PD_PAGES(nr_copy_pages)) - order;
+		if (diff) {
+			order += diff;
+			nr_copy_pages += 1 << diff;
+		}
+	} while(diff);
+	pagedir_order = order;
+}
 
-	pagedir_order = get_bitmask_order(SUSPEND_PD_PAGES(nr_copy_pages));
 
-	p = pagedir = (suspend_pagedir_t *)__get_free_pages(GFP_ATOMIC | __GFP_COLD, pagedir_order);
-	if (!pagedir)
-		return NULL;
+/**
+ *	alloc_pagedir - Allocate the page directory.
+ *
+ *	First, determine exactly how many contiguous pages we need and
+ *	allocate them.
+ */
 
-	page = virt_to_page(pagedir);
-	for(i=0; i < 1<<pagedir_order; i++)
-		SetPageNosave(page++);
-		
-	while(nr_copy_pages--) {
+static int alloc_pagedir(void)
+{
+	calc_order();
+	pagedir_save = (suspend_pagedir_t *)__get_free_pages(GFP_ATOMIC | __GFP_COLD,
+							     pagedir_order);
+	if (!pagedir_save)
+		return -ENOMEM;
+	memset(pagedir_save, 0, (1 << pagedir_order) * PAGE_SIZE);
+	pagedir_nosave = pagedir_save;
+	return 0;
+}
+
+
+/**
+ *	alloc_image_pages - Allocate pages for the snapshot.
+ *
+ */
+
+static int alloc_image_pages(void)
+{
+	struct pbe * p;
+	int i;
+
+	for (i = 0, p = pagedir_save; i < nr_copy_pages; i++, p++) {
 		p->address = get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
-		if (!p->address) {
-			free_suspend_pagedir((unsigned long) pagedir);
-			return NULL;
-		}
+		if(!p->address)
+			goto Error;
 		SetPageNosave(virt_to_page(p->address));
-		p->orig_address = 0;
-		p++;
 	}
-	return pagedir;
+	return 0;
+ Error:
+	do { 
+		if (p->address)
+			free_page(p->address);
+		p->address = 0;
+	} while (p-- > pagedir_save);
+	return -ENOMEM;
 }
 
-static int prepare_suspend_processes(void)
+
+/**
+ *	enough_free_mem - Make sure we enough free memory to snapshot.
+ *
+ *	Returns TRUE or FALSE after checking the number of available 
+ *	free pages.
+ */
+
+static int enough_free_mem(void)
 {
-	sys_sync();	/* Syncing needs pdflushd, so do it before stopping processes */
-	if (freeze_processes()) {
-		printk( KERN_ERR "Suspend failed: Not all processes stopped!\n" );
-		thaw_processes();
-		return 1;
+	if (nr_free_pages() < (nr_copy_pages + PAGES_FOR_IO)) {
+		pr_debug("swsusp: Not enough free pages: Have %d\n",
+			 nr_free_pages());
+		return 0;
 	}
-	return 0;
+	return 1;
 }
 
-/*
- * Try to free as much memory as possible, but do not OOM-kill anyone
+
+/**
+ *	enough_swap - Make sure we have enough swap to save the image.
+ *
+ *	Returns TRUE or FALSE after checking the total amount of swap 
+ *	space avaiable.
  *
- * Notice: all userland should be stopped at this point, or livelock is possible.
+ *	FIXME: si_swapinfo(&i) returns all swap devices information.
+ *	We should only consider resume_device. 
  */
-static void free_some_memory(void)
+
+static int enough_swap(void)
 {
-	printk("Freeing memory: ");
-	while (shrink_all_memory(10000))
-		printk(".");
-	printk("|\n");
+	struct sysinfo i;
+
+	si_swapinfo(&i);
+	if (i.freeswap < (nr_copy_pages + PAGES_FOR_IO))  {
+		pr_debug("swsusp: Not enough swap. Need %ld\n",i.freeswap);
+		return 0;
+	}
+	return 1;
 }
 
-static int suspend_prepare_image(void)
+static int swsusp_alloc(void)
 {
-	struct sysinfo i;
-	unsigned int nr_needed_pages = 0;
+	int error;
+
+	pr_debug("suspend: (pages needed: %d + %d free: %d)\n",
+		 nr_copy_pages, PAGES_FOR_IO, nr_free_pages());
 
 	pagedir_nosave = NULL;
-	printk( "/critical section: ");
-#ifdef CONFIG_HIGHMEM
-	printk( "handling highmem" );
-	if (save_highmem()) {
-		printk(KERN_CRIT "%sNot enough free pages for highmem\n", name_suspend);
+	if (!enough_free_mem())
 		return -ENOMEM;
-	}
-	printk(", ");
-#endif
 
-	printk("counting pages to copy" );
-	drain_local_pages();
-	nr_copy_pages = count_and_copy_data_pages(NULL);
-	nr_needed_pages = nr_copy_pages + PAGES_FOR_IO;
-	
-	printk(" (pages needed: %d+%d=%d free: %d)\n",nr_copy_pages,PAGES_FOR_IO,nr_needed_pages,nr_free_pages());
-	if(nr_free_pages() < nr_needed_pages) {
-		printk(KERN_CRIT "%sCouldn't get enough free pages, on %d pages short\n",
-		       name_suspend, nr_needed_pages-nr_free_pages());
-		root_swap = 0xFFFF;
-		return -ENOMEM;
-	}
-	si_swapinfo(&i);	/* FIXME: si_swapinfo(&i) returns all swap devices information.
-				   We should only consider resume_device. */
-	if (i.freeswap < nr_needed_pages)  {
-		printk(KERN_CRIT "%sThere's not enough swap space available, on %ld pages short\n",
-		       name_suspend, nr_needed_pages-i.freeswap);
+	if (!enough_swap())
 		return -ENOSPC;
-	}
 
-	PRINTK( "Alloc pagedir\n" ); 
-	pagedir_save = pagedir_nosave = create_suspend_pagedir(nr_copy_pages);
-	if (!pagedir_nosave) {
-		/* Pagedir is big, one-chunk allocation. It is easily possible for this allocation to fail */
-		printk(KERN_CRIT "%sCouldn't allocate continuous pagedir\n", name_suspend);
-		return -ENOMEM;
+	if ((error = alloc_pagedir())) {
+		pr_debug("suspend: Allocating pagedir failed.\n");
+		return error;
+	}
+	if ((error = alloc_image_pages())) {
+		pr_debug("suspend: Allocating image pages failed.\n");
+		swsusp_free();
+		return error;
 	}
+
 	nr_copy_pages_check = nr_copy_pages;
 	pagedir_order_check = pagedir_order;
+	return 0;
+}
+
+int suspend_prepare_image(void)
+{
+	unsigned int nr_needed_pages = 0;
+	int error;
+
+	pr_debug("swsusp: critical section: \n");
+	if (save_highmem()) {
+		printk(KERN_CRIT "Suspend machine: Not enough free pages for highmem\n");
+		return -ENOMEM;
+	}
+
+	drain_local_pages();
+	count_data_pages();
+	printk("swsusp: Need to copy %u pages\n",nr_copy_pages);
+	nr_needed_pages = nr_copy_pages + PAGES_FOR_IO;
 
-	drain_local_pages();	/* During allocating of suspend pagedir, new cold pages may appear. Kill them */
-	if (nr_copy_pages != count_and_copy_data_pages(pagedir_nosave))	/* copy */
-		BUG();
+	error = swsusp_alloc();
+	if (error)
+		return error;
+	
+	/* During allocating of suspend pagedir, new cold pages may appear. 
+	 * Kill them.
+	 */
+	drain_local_pages();
+	copy_data_pages();
 
 	/*
 	 * End of critical section. From now on, we can write to memory,
@@ -667,205 +812,86 @@ static int suspend_prepare_image(void)
 	 * touch swap space! Except we must write out our image of course.
 	 */
 
-	printk( "critical section/: done (%d pages copied)\n", nr_copy_pages );
+	printk("swsusp: critical section/: done (%d pages copied)\n", nr_copy_pages );
 	return 0;
 }
 
-static void suspend_save_image(void)
+
+/* It is important _NOT_ to umount filesystems at this point. We want
+ * them synced (in case something goes wrong) but we DO not want to mark
+ * filesystem clean: it is not. (And it does not matter, if we resume
+ * correctly, we'll mark system clean, anyway.)
+ */
+int swsusp_write(void)
 {
+	int error;
 	device_resume();
-
 	lock_swapdevices();
-	write_suspend_image();
-	lock_swapdevices();	/* This will unlock ignored swap devices since writing is finished */
+	error = write_suspend_image();
+	/* This will unlock ignored swap devices since writing is finished */
+	lock_swapdevices();
+	return error;
 
-	/* It is important _NOT_ to umount filesystems at this point. We want
-	 * them synced (in case something goes wrong) but we DO not want to mark
-	 * filesystem clean: it is not. (And it does not matter, if we resume
-	 * correctly, we'll mark system clean, anyway.)
-	 */
 }
 
-static void suspend_power_down(void)
-{
-	extern int C_A_D;
-	C_A_D = 0;
-	printk(KERN_EMERG "%s%s Trying to power down.\n", name_suspend, TEST_SWSUSP ? "Disable TEST_SWSUSP. NOT ": "");
-#ifdef CONFIG_VT
-	PRINTK(KERN_EMERG "shift_state: %04x\n", shift_state);
-	mdelay(1000);
-	if (TEST_SWSUSP ^ (!!(shift_state & (1 << KG_CTRL))))
-		machine_restart(NULL);
-	else
-#endif
-	{
-		device_suspend(3);
-		device_shutdown();
-		machine_power_off();
-	}
 
-	printk(KERN_EMERG "%sProbably not capable for powerdown. System halted.\n", name_suspend);
-	machine_halt();
-	while (1);
-	/* NOTREACHED */
-}
+extern asmlinkage int swsusp_arch_suspend(void);
+extern asmlinkage int swsusp_arch_resume(void);
 
-/*
- * Magic happens here
- */
 
-asmlinkage void do_magic_resume_1(void)
+asmlinkage int swsusp_save(void)
 {
-	barrier();
-	mb();
-	spin_lock_irq(&suspend_pagedir_lock);	/* Done to disable interrupts */ 
-
-	device_power_down(3);
-	PRINTK( "Waiting for DMAs to settle down...\n");
-	mdelay(1000);	/* We do not want some readahead with DMA to corrupt our memory, right?
-			   Do it with disabled interrupts for best effect. That way, if some
-			   driver scheduled DMA, we have good chance for DMA to finish ;-). */
+	int error = 0;
+
+	if ((error = swsusp_swap_check()))
+		return error;
+	return suspend_prepare_image();
 }
 
-asmlinkage void do_magic_resume_2(void)
+int swsusp_suspend(void)
 {
-	BUG_ON (nr_copy_pages_check != nr_copy_pages);
-	BUG_ON (pagedir_order_check != pagedir_order);
-
-	__flush_tlb_global();		/* Even mappings of "global" things (vmalloc) need to be fixed */
-
-	PRINTK( "Freeing prev allocated pagedir\n" );
-	free_suspend_pagedir((unsigned long) pagedir_save);
-
-#ifdef CONFIG_HIGHMEM
-	printk( "Restoring highmem\n" );
+	int error;
+	if ((error = arch_prepare_suspend()))
+		return error;
+	local_irq_disable();
+	save_processor_state();
+	error = swsusp_arch_suspend();
+	/* Restore control flow magically appears here */
+	restore_processor_state();
 	restore_highmem();
-#endif
-	printk("done, devices\n");
-
-	device_power_up();
-	spin_unlock_irq(&suspend_pagedir_lock);
-	device_resume();
-
-	/* Fixme: this is too late; we should do this ASAP to avoid "infinite reboots" problem */
-	PRINTK( "Fixing swap signatures... " );
-	mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME);
-	PRINTK( "ok\n" );
-
-#ifdef SUSPEND_CONSOLE
-	acquire_console_sem();
-	update_screen(fg_console);
-	release_console_sem();
-#endif
+	local_irq_enable();
+	return error;
 }
 
-/* do_magic() is implemented in arch/?/kernel/suspend_asm.S, and basically does:
-
-	if (!resume) {
-		do_magic_suspend_1();
-		save_processor_state();
-		SAVE_REGISTERS
-		do_magic_suspend_2();
-		return;
-	}
-	GO_TO_SWAPPER_PAGE_TABLES
-	do_magic_resume_1();
-	COPY_PAGES_BACK
-	RESTORE_REGISTERS
-	restore_processor_state();
-	do_magic_resume_2();
 
- */
-
-asmlinkage void do_magic_suspend_1(void)
+asmlinkage int swsusp_restore(void)
 {
-	mb();
-	barrier();
-	BUG_ON(in_atomic());
-	spin_lock_irq(&suspend_pagedir_lock);
+	BUG_ON (nr_copy_pages_check != nr_copy_pages);
+	BUG_ON (pagedir_order_check != pagedir_order);
+	
+	/* Even mappings of "global" things (vmalloc) need to be fixed */
+	__flush_tlb_global();
+	return 0;
 }
 
-asmlinkage void do_magic_suspend_2(void)
+int swsusp_resume(void)
 {
-	int is_problem;
-	read_swapfiles();
-	device_power_down(3);
-	is_problem = suspend_prepare_image();
-	device_power_up();
-	spin_unlock_irq(&suspend_pagedir_lock);
-	if (!is_problem) {
-		kernel_fpu_end();	/* save_processor_state() does kernel_fpu_begin, and we need to revert it in order to pass in_atomic() checks */
-		BUG_ON(in_atomic());
-		suspend_save_image();
-		suspend_power_down();	/* FIXME: if suspend_power_down is commented out, console is lost after few suspends ?! */
-	}
-
-	printk(KERN_EMERG "%sSuspend failed, trying to recover...\n", name_suspend);
-	MDELAY(1000); /* So user can wait and report us messages if armageddon comes :-) */
-
-	barrier();
-	mb();
-	spin_lock_irq(&suspend_pagedir_lock);	/* Done to disable interrupts */ 
-
-	free_pages((unsigned long) pagedir_nosave, pagedir_order);
-	spin_unlock_irq(&suspend_pagedir_lock);
-
-	device_resume();
-	PRINTK( "Fixing swap signatures... " );
-	mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME);
-	PRINTK( "ok\n" );
+	int error;
+	local_irq_disable();
+	/* We'll ignore saved state, but this gets preempt count (etc) right */
+	save_processor_state();
+	error = swsusp_arch_resume();
+	/* Code below is only ever reached in case of failure. Otherwise
+	 * execution continues at place where swsusp_arch_suspend was called
+         */
+	BUG_ON(!error);
+	restore_processor_state();
+	restore_highmem();
+	local_irq_enable();
+	return error;
 }
 
-/*
- * This is main interface to the outside world. It needs to be
- * called from process context.
- */
-int software_suspend(void)
-{
-	int res;
-	if (!software_suspend_enabled)
-		return -EAGAIN;
-
-	software_suspend_enabled = 0;
-	might_sleep();
 
-	if (arch_prepare_suspend()) {
-		printk("%sArchitecture failed to prepare\n", name_suspend);
-		return -EPERM;
-	}		
-	if (pm_prepare_console())
-		printk( "%sCan't allocate a console... proceeding\n", name_suspend);
-	if (!prepare_suspend_processes()) {
-
-		/* At this point, all user processes and "dangerous"
-                   kernel threads are stopped. Free some memory, as we
-                   need half of memory free. */
-
-		free_some_memory();
-		disable_nonboot_cpus();
-		/* Save state of all device drivers, and stop them. */
-		printk("Suspending devices... ");
-		if ((res = device_suspend(3))==0) {
-			/* If stopping device drivers worked, we proceed basically into
-			 * suspend_save_image.
-			 *
-			 * do_magic(0) returns after system is resumed.
-			 *
-			 * do_magic() copies all "used" memory to "free" memory, then
-			 * unsuspends all device drivers, and writes memory to disk
-			 * using normal kernel mechanism.
-			 */
-			do_magic(0);
-		}
-		thaw_processes();
-		enable_nonboot_cpus();
-	} else
-		res = -EBUSY;
-	software_suspend_enabled = 1;
-	MDELAY(1000);
-	pm_restore_console();
-	return res;
-}
 
 /* More restore stuff */
 
@@ -874,14 +900,14 @@ int software_suspend(void)
 /*
  * Returns true if given address/order collides with any orig_address 
  */
-static int does_collide_order(suspend_pagedir_t *pagedir, unsigned long addr,
+static int __init does_collide_order(suspend_pagedir_t *pagedir, unsigned long addr,
 		int order)
 {
 	int i;
 	unsigned long addre = addr + (PAGE_SIZE<<order);
 	
-	for(i=0; i < nr_copy_pages; i++)
-		if((pagedir+i)->orig_address >= addr &&
+	for (i=0; i < nr_copy_pages; i++)
+		if ((pagedir+i)->orig_address >= addr &&
 			(pagedir+i)->orig_address < addre)
 			return 1;
 
@@ -892,7 +918,7 @@ static int does_collide_order(suspend_pagedir_t *pagedir, unsigned long addr,
  * We check here that pagedir & pages it points to won't collide with pages
  * where we're going to restore from the loaded pages later
  */
-static int check_pagedir(void)
+static int __init check_pagedir(void)
 {
 	int i;
 
@@ -910,7 +936,7 @@ static int check_pagedir(void)
 	return 0;
 }
 
-static int relocate_pagedir(void)
+static int __init swsusp_pagedir_relocate(void)
 {
 	/*
 	 * We have to avoid recursion (not to overflow kernel stack),
@@ -923,9 +949,9 @@ static int relocate_pagedir(void)
 
 	printk("Relocating pagedir ");
 
-	if(!does_collide_order(old_pagedir, (unsigned long)old_pagedir, pagedir_order)) {
+	if (!does_collide_order(old_pagedir, (unsigned long)old_pagedir, pagedir_order)) {
 		printk("not necessary\n");
-		return 0;
+		return check_pagedir();
 	}
 
 	while ((m = (void *) __get_free_pages(GFP_ATOMIC, pagedir_order)) != NULL) {
@@ -953,283 +979,253 @@ static int relocate_pagedir(void)
 		free_pages((unsigned long)f, pagedir_order);
 	}
 	printk("|\n");
-	return ret;
+	return check_pagedir();
 }
 
-/*
- * Sanity check if this image makes sense with this kernel/swap context
- * I really don't think that it's foolproof but more than nothing..
+/**
+ *	Using bio to read from swap.
+ *	This code requires a bit more work than just using buffer heads
+ *	but, it is the recommended way for 2.5/2.6.
+ *	The following are to signal the beginning and end of I/O. Bios
+ *	finish asynchronously, while we want them to happen synchronously.
+ *	A simple atomic_t, and a wait loop take care of this problem.
  */
 
-static int sanity_check_failed(char *reason)
-{
-	printk(KERN_ERR "%s%s\n", name_resume, reason);
-	return -EPERM;
-}
+static atomic_t io_done = ATOMIC_INIT(0);
 
-static int sanity_check(struct suspend_header *sh)
+static void start_io(void)
 {
-	if (sh->version_code != LINUX_VERSION_CODE)
-		return sanity_check_failed("Incorrect kernel version");
-	if (sh->num_physpages != num_physpages)
-		return sanity_check_failed("Incorrect memory size");
-	if (strncmp(sh->machine, system_utsname.machine, 8))
-		return sanity_check_failed("Incorrect machine type");
-	if (strncmp(sh->version, system_utsname.version, 20))
-		return sanity_check_failed("Incorrect version");
-	if (sh->num_cpus != num_online_cpus())
-		return sanity_check_failed("Incorrect number of cpus");
-	if (sh->page_size != PAGE_SIZE)
-		return sanity_check_failed("Incorrect PAGE_SIZE");
-	return 0;
+	atomic_set(&io_done,1);
 }
 
-static int bdev_read_page(struct block_device *bdev, long pos, void *buf)
+static int end_io(struct bio * bio, unsigned int num, int err)
 {
-	struct buffer_head *bh;
-	BUG_ON (pos%PAGE_SIZE);
-	bh = __bread(bdev, pos/PAGE_SIZE, PAGE_SIZE);
-	if (!bh || (!bh->b_data)) {
-		return -1;
-	}
-	memcpy(buf, bh->b_data, PAGE_SIZE);	/* FIXME: may need kmap() */
-	BUG_ON(!buffer_uptodate(bh));
-	brelse(bh);
+	atomic_set(&io_done,0);
 	return 0;
-} 
+}
 
-static int bdev_write_page(struct block_device *bdev, long pos, void *buf)
+static void wait_io(void)
 {
-#if 0
-	struct buffer_head *bh;
-	BUG_ON (pos%PAGE_SIZE);
-	bh = __bread(bdev, pos/PAGE_SIZE, PAGE_SIZE);
-	if (!bh || (!bh->b_data)) {
-		return -1;
-	}
-	memcpy(bh->b_data, buf, PAGE_SIZE);	/* FIXME: may need kmap() */
-	BUG_ON(!buffer_uptodate(bh));
-	generic_make_request(WRITE, bh);
-	if (!buffer_uptodate(bh))
-		printk(KERN_CRIT "%sWarning %s: Fixing swap signatures unsuccessful...\n", name_resume, resume_file);
-	wait_on_buffer(bh);
-	brelse(bh);
-	return 0;
-#endif
-	printk(KERN_CRIT "%sWarning %s: Fixing swap signatures unimplemented...\n", name_resume, resume_file);
-	return 0;
+	while(atomic_read(&io_done))
+		io_schedule();
 }
 
-extern dev_t __init name_to_dev_t(const char *line);
 
-static int __init __read_suspend_image(struct block_device *bdev, union diskpage *cur, int noresume)
-{
-	swp_entry_t next;
-	int i, nr_pgdir_pages;
+static struct block_device * resume_bdev;
 
-#define PREPARENEXT \
-	{	next = cur->link.next; \
-		next.val = swp_offset(next) * PAGE_SIZE; \
-        }
+/**
+ *	submit - submit BIO request.
+ *	@rw:	READ or WRITE.
+ *	@off	physical offset of page.
+ *	@page:	page we're reading or writing.
+ *
+ *	Straight from the textbook - allocate and initialize the bio.
+ *	If we're writing, make sure the page is marked as dirty.
+ *	Then submit it and wait.
+ */
 
-	if (bdev_read_page(bdev, 0, cur)) return -EIO;
+static int submit(int rw, pgoff_t page_off, void * page)
+{
+	int error = 0;
+	struct bio * bio;
 
-	if ((!memcmp("SWAP-SPACE",cur->swh.magic.magic,10)) ||
-	    (!memcmp("SWAPSPACE2",cur->swh.magic.magic,10))) {
-		printk(KERN_ERR "%sThis is normal swap space\n", name_resume );
-		return -EINVAL;
+	bio = bio_alloc(GFP_ATOMIC, 1);
+	if (!bio)
+		return -ENOMEM;
+	bio->bi_sector = page_off * (PAGE_SIZE >> 9);
+	bio_get(bio);
+	bio->bi_bdev = resume_bdev;
+	bio->bi_end_io = end_io;
+
+	if (bio_add_page(bio, virt_to_page(page), PAGE_SIZE, 0) < PAGE_SIZE) {
+		printk("swsusp: ERROR: adding page to bio at %ld\n",page_off);
+		error = -EFAULT;
+		goto Done;
 	}
 
-	PREPARENEXT; /* We have to read next position before we overwrite it */
-
-	if (!memcmp("S1",cur->swh.magic.magic,2))
-		memcpy(cur->swh.magic.magic,"SWAP-SPACE",10);
-	else if (!memcmp("S2",cur->swh.magic.magic,2))
-		memcpy(cur->swh.magic.magic,"SWAPSPACE2",10);
-	else {
-		if (noresume)
-			return -EINVAL;
-		panic("%sUnable to find suspended-data signature (%.10s - misspelled?\n", 
-			name_resume, cur->swh.magic.magic);
-	}
-	if (noresume) {
-		/* We don't do a sanity check here: we want to restore the swap
-		   whatever version of kernel made the suspend image;
-		   We need to write swap, but swap is *not* enabled so
-		   we must write the device directly */
-		printk("%s: Fixing swap signatures %s...\n", name_resume, resume_file);
-		bdev_write_page(bdev, 0, cur);
-	}
+	if (rw == WRITE)
+		bio_set_pages_dirty(bio);
+	start_io();
+	submit_bio(rw | (1 << BIO_RW_SYNC), bio);
+	wait_io();
+ Done:
+	bio_put(bio);
+	return error;
+}
 
-	printk( "%sSignature found, resuming\n", name_resume );
-	MDELAY(1000);
+int bio_read_page(pgoff_t page_off, void * page)
+{
+	return submit(READ, page_off, page);
+}
 
-	if (bdev_read_page(bdev, next.val, cur)) return -EIO;
-	if (sanity_check(&cur->sh)) 	/* Is this same machine? */	
-		return -EPERM;
-	PREPARENEXT;
+int bio_write_page(pgoff_t page_off, void * page)
+{
+	return submit(WRITE, page_off, page);
+}
 
-	pagedir_save = cur->sh.suspend_pagedir;
-	nr_copy_pages = cur->sh.num_pbes;
-	nr_pgdir_pages = SUSPEND_PD_PAGES(nr_copy_pages);
-	pagedir_order = get_bitmask_order(nr_pgdir_pages);
+/*
+ * Sanity check if this image makes sense with this kernel/swap context
+ * I really don't think that it's foolproof but more than nothing..
+ */
 
-	pagedir_nosave = (suspend_pagedir_t *)__get_free_pages(GFP_ATOMIC, pagedir_order);
-	if (!pagedir_nosave)
-		return -ENOMEM;
+static const char * __init sanity_check(void)
+{
+	dump_info();
+	if(swsusp_info.version_code != LINUX_VERSION_CODE)
+		return "kernel version";
+	if(swsusp_info.num_physpages != num_physpages)
+		return "memory size";
+	if (strcmp(swsusp_info.uts.sysname,system_utsname.sysname))
+		return "system type";
+	if (strcmp(swsusp_info.uts.release,system_utsname.release))
+		return "kernel release";
+	if (strcmp(swsusp_info.uts.version,system_utsname.version))
+		return "version";
+	if (strcmp(swsusp_info.uts.machine,system_utsname.machine))
+		return "machine";
+	if(swsusp_info.cpus != num_online_cpus())
+		return "number of cpus";
+	return NULL;
+}
 
-	PRINTK( "%sReading pagedir, ", name_resume );
 
-	/* We get pages in reverse order of saving! */
-	for (i=nr_pgdir_pages-1; i>=0; i--) {
-		BUG_ON (!next.val);
-		cur = (union diskpage *)((char *) pagedir_nosave)+i;
-		if (bdev_read_page(bdev, next.val, cur)) return -EIO;
-		PREPARENEXT;
-	}
-	BUG_ON (next.val);
+static int __init check_header(void)
+{
+	const char * reason = NULL;
+	int error;
 
-	if (relocate_pagedir())
-		return -ENOMEM;
-	if (check_pagedir())
-		return -ENOMEM;
+	if ((error = bio_read_page(swp_offset(swsusp_header.swsusp_info), &swsusp_info)))
+		return error;
 
-	printk( "Reading image data (%d pages): ", nr_copy_pages );
-	for(i=0; i < nr_copy_pages; i++) {
-		swp_entry_t swap_address = (pagedir_nosave+i)->swap_address;
-		if (!(i%100))
-			printk( "." );
-		/* You do not need to check for overlaps...
-		   ... check_pagedir already did this work */
-		if (bdev_read_page(bdev, swp_offset(swap_address) * PAGE_SIZE, (char *)((pagedir_nosave+i)->address)))
-			return -EIO;
+ 	/* Is this same machine? */
+	if ((reason = sanity_check())) {
+		printk(KERN_ERR "swsusp: Resume mismatch: %s\n",reason);
+		return -EPERM;
 	}
-	printk( "|\n" );
-	return 0;
+	nr_copy_pages = swsusp_info.image_pages;
+	return error;
 }
 
-static int __init read_suspend_image(const char * specialfile, int noresume)
+static int __init check_sig(void)
 {
-	union diskpage *cur;
-	unsigned long scratch_page = 0;
 	int error;
-	char b[BDEVNAME_SIZE];
-
-	resume_device = name_to_dev_t(specialfile);
-	scratch_page = get_zeroed_page(GFP_ATOMIC);
-	cur = (void *) scratch_page;
-	if (cur) {
-		struct block_device *bdev;
-		printk("Resuming from device %s\n",
-				__bdevname(resume_device, b));
-		bdev = open_by_devnum(resume_device, FMODE_READ);
-		if (IS_ERR(bdev)) {
-			error = PTR_ERR(bdev);
-		} else {
-			set_blocksize(bdev, PAGE_SIZE);
-			error = __read_suspend_image(bdev, cur, noresume);
-			blkdev_put(bdev);
-		}
-	} else error = -ENOMEM;
 
-	if (scratch_page)
-		free_page(scratch_page);
-	switch (error) {
-		case 0:
-			PRINTK("Reading resume file was successful\n");
-			break;
-		case -EINVAL:
-			break;
-		case -EIO:
-			printk( "%sI/O error\n", name_resume);
-			break;
-		case -ENOENT:
-			printk( "%s%s: No such file or directory\n", name_resume, specialfile);
-			break;
-		case -ENOMEM:
-			printk( "%sNot enough memory\n", name_resume);
-			break;
-		default:
-			printk( "%sError %d resuming\n", name_resume, error );
+	memset(&swsusp_header, 0, sizeof(swsusp_header));
+	if ((error = bio_read_page(0, &swsusp_header)))
+		return error;
+	if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) {
+		memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10);
+
+		/*
+		 * Reset swap signature now.
+		 */
+		error = bio_write_page(0, &swsusp_header);
+	} else { 
+		pr_debug(KERN_ERR "swsusp: Invalid partition type.\n");
+		return -EINVAL;
 	}
-	MDELAY(1000);
+	if (!error)
+		pr_debug("swsusp: Signature found, resuming\n");
 	return error;
 }
 
 /**
- *	software_resume - Resume from a saved image.
- *
- *	Called as a late_initcall (so all devices are discovered and 
- *	initialized), we call swsusp to see if we have a saved image or not.
- *	If so, we quiesce devices, then restore the saved image. We will 
- *	return above (in pm_suspend_disk() ) if everything goes well. 
- *	Otherwise, we fail gracefully and return to the normally 
- *	scheduled program.
+ *	swsusp_read_data - Read image pages from swap.
  *
+ *	You do not need to check for overlaps, check_pagedir()
+ *	already did that.
  */
-static int __init software_resume(void)
-{
-	if (num_online_cpus() > 1) {
-		printk(KERN_WARNING "Software Suspend has malfunctioning SMP support. Disabled :(\n");	
-		return -EINVAL;
-	}
-	/* We enable the possibility of machine suspend */
-	software_suspend_enabled = 1;
-	if (!resume_status)
-		return 0;
 
-	printk( "%s", name_resume );
-	if (resume_status == NORESUME) {
-		if(resume_file[0])
-			read_suspend_image(resume_file, 1);
-		printk( "disabled\n" );
-		return 0;
-	}
-	MDELAY(1000);
+static int __init data_read(void)
+{
+	struct pbe * p;
+	int error;
+	int i;
 
-	if (pm_prepare_console())
-		printk("swsusp: Can't allocate a console... proceeding\n");
+	if ((error = swsusp_pagedir_relocate()))
+		return error;
 
-	if (!resume_file[0] && resume_status == RESUME_SPECIFIED) {
-		printk( "suspension device unspecified\n" );
-		return -EINVAL;
+	printk( "Reading image data (%d pages): ", nr_copy_pages );
+	for(i = 0, p = pagedir_nosave; i < nr_copy_pages && !error; i++, p++) {
+		if (!(i%100))
+			printk( "." );
+		error = bio_read_page(swp_offset(p->swap_address),
+				  (void *)p->address);
 	}
+	printk(" %d done.\n",i);
+	return error;
 
-	printk( "resuming from %s\n", resume_file);
-	if (read_suspend_image(resume_file, 0))
-		goto read_failure;
-	/* FIXME: Should we stop processes here, just to be safer? */
-	disable_nonboot_cpus();
-	device_suspend(3);
-	do_magic(1);
-	panic("This never returns");
-
-read_failure:
-	pm_restore_console();
-	return 0;
 }
 
-late_initcall(software_resume);
+extern dev_t __init name_to_dev_t(const char *line);
 
-static int __init resume_setup(char *str)
+static int __init read_pagedir(void)
 {
-	if (resume_status == NORESUME)
-		return 1;
+	unsigned long addr;
+	int i, n = swsusp_info.pagedir_pages;
+	int error = 0;
 
-	strncpy( resume_file, str, 255 );
-	resume_status = RESUME_SPECIFIED;
+	pagedir_order = get_bitmask_order(n);
 
-	return 1;
+	addr =__get_free_pages(GFP_ATOMIC, pagedir_order);
+	if (!addr)
+		return -ENOMEM;
+	pagedir_nosave = (struct pbe *)addr;
+
+	pr_debug("pmdisk: Reading pagedir (%d Pages)\n",n);
+
+	for (i = 0; i < n && !error; i++, addr += PAGE_SIZE) {
+		unsigned long offset = swp_offset(swsusp_info.pagedir[i]);
+		if (offset)
+			error = bio_read_page(offset, (void *)addr);
+		else
+			error = -EFAULT;
+	}
+	if (error)
+		free_pages((unsigned long)pagedir_nosave, pagedir_order);
+	return error;
 }
 
-static int __init noresume_setup(char *str)
+static int __init read_suspend_image(void)
 {
-	resume_status = NORESUME;
-	return 1;
+	int error = 0;
+
+	if ((error = check_sig()))
+		return error;
+	if ((error = check_header()))
+		return error;
+	if ((error = read_pagedir()))
+		return error;
+	if ((error = data_read()))
+		free_pages((unsigned long)pagedir_nosave, pagedir_order);
+	return error;
 }
 
-__setup("noresume", noresume_setup);
-__setup("resume=", resume_setup);
+/**
+ *	pmdisk_read - Read saved image from swap.
+ */
+
+int __init swsusp_read(void)
+{
+	int error;
+
+	if (!strlen(resume_file))
+		return -ENOENT;
 
-EXPORT_SYMBOL(software_suspend);
-EXPORT_SYMBOL(software_suspend_enabled);
+	resume_device = name_to_dev_t(resume_file);
+	pr_debug("swsusp: Resume From Partition: %s\n", resume_file);
+
+	resume_bdev = open_by_devnum(resume_device, FMODE_READ);
+	if (!IS_ERR(resume_bdev)) {
+		set_blocksize(resume_bdev, PAGE_SIZE);
+		error = read_suspend_image();
+		blkdev_put(resume_bdev);
+	} else
+		error = PTR_ERR(resume_bdev);
+
+	if (!error)
+		pr_debug("Reading resume file was successful\n");
+	else
+		pr_debug("pmdisk: Error %d resuming\n", error);
+	return error;
+}
diff --git a/kernel/printk.c b/kernel/printk.c
index 9b1f825bc..11c6681ad 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -193,6 +193,8 @@ static int __init log_buf_len_setup(char *str)
 	unsigned long size = memparse(str, &str);
 	unsigned long flags;
 
+	if (size)
+		size = roundup_pow_of_two(size);
 	if (size > log_buf_len) {
 		unsigned long start, dest_idx, offset;
 		char * new_log_buf;
@@ -512,22 +514,34 @@ static void zap_locks(void)
 asmlinkage int printk(const char *fmt, ...)
 {
 	va_list args;
+	int r;
+
+	va_start(args, fmt);
+	r = vprintk(fmt, args);
+	va_end(args);
+
+	return r;
+}
+
+static volatile int printk_cpu = -1;
+
+asmlinkage int vprintk(const char *fmt, va_list args)
+{
 	unsigned long flags;
 	int printed_len;
 	char *p;
 	static char printk_buf[1024];
 	static int log_level_unknown = 1;
 
-	if (unlikely(oops_in_progress))
+	if (unlikely(oops_in_progress && printk_cpu == smp_processor_id()))
 		zap_locks();
 
 	/* This stops the holder of console_sem just where we want him */
 	spin_lock_irqsave(&logbuf_lock, flags);
+	printk_cpu = smp_processor_id();
 
 	/* Emit the output into the temporary buffer */
-	va_start(args, fmt);
 	printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);
-	va_end(args);
 
 	/*
 	 * Copy the output into log_buf.  If the caller didn't provide
@@ -579,6 +593,7 @@ out:
 	return printed_len;
 }
 EXPORT_SYMBOL(printk);
+EXPORT_SYMBOL(vprintk);
 
 /**
  * acquire_console_sem - lock the console system for exclusive use.
diff --git a/kernel/profile.c b/kernel/profile.c
index 5c02ac0fb..cab14764c 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -8,38 +8,44 @@
 #include <linux/bootmem.h>
 #include <linux/notifier.h>
 #include <linux/mm.h>
+#include <linux/cpumask.h>
+#include <linux/profile.h>
 #include <asm/sections.h>
 
-unsigned int * prof_buffer;
-unsigned long prof_len;
-unsigned long prof_shift;
-int prof_on;
+static atomic_t *prof_buffer;
+static unsigned long prof_len, prof_shift;
+static int prof_on;
+static cpumask_t prof_cpu_mask = CPU_MASK_ALL;
 
-int __init profile_setup(char * str)
+static int __init profile_setup(char * str)
 {
 	int par;
+
+	if (!strncmp(str, "schedule", 8)) {
+		prof_on = 2;
+		printk(KERN_INFO "kernel schedule profiling enabled\n");
+		if (str[7] == ',')
+			str += 8;
+	}
 	if (get_option(&str,&par)) {
 		prof_shift = par;
 		prof_on = 1;
-		printk(KERN_INFO "kernel profiling enabled\n");
+		printk(KERN_INFO "kernel profiling enabled (shift: %ld)\n",
+			prof_shift);
 	}
 	return 1;
 }
+__setup("profile=", profile_setup);
 
 
 void __init profile_init(void)
 {
-	unsigned int size;
- 
 	if (!prof_on) 
 		return;
  
 	/* only text is profiled */
-	prof_len = _etext - _stext;
-	prof_len >>= prof_shift;
-		
-	size = prof_len * sizeof(unsigned int) + PAGE_SIZE - 1;
-	prof_buffer = (unsigned int *) alloc_bootmem(size);
+	prof_len = (_etext - _stext) >> prof_shift;
+	prof_buffer = alloc_bootmem(prof_len*sizeof(atomic_t));
 }
 
 /* Profile event notifications */
@@ -47,31 +53,54 @@ void __init profile_init(void)
 #ifdef CONFIG_PROFILING
  
 static DECLARE_RWSEM(profile_rwsem);
-static struct notifier_block * exit_task_notifier;
-static struct notifier_block * exit_mmap_notifier;
-static struct notifier_block * exec_unmap_notifier;
+static rwlock_t handoff_lock = RW_LOCK_UNLOCKED;
+static struct notifier_block * task_exit_notifier;
+static struct notifier_block * task_free_notifier;
+static struct notifier_block * munmap_notifier;
  
-void profile_exit_task(struct task_struct * task)
+void profile_task_exit(struct task_struct * task)
 {
 	down_read(&profile_rwsem);
-	notifier_call_chain(&exit_task_notifier, 0, task);
+	notifier_call_chain(&task_exit_notifier, 0, task);
 	up_read(&profile_rwsem);
 }
  
-void profile_exit_mmap(struct mm_struct * mm)
+int profile_handoff_task(struct task_struct * task)
 {
-	down_read(&profile_rwsem);
-	notifier_call_chain(&exit_mmap_notifier, 0, mm);
-	up_read(&profile_rwsem);
+	int ret;
+	read_lock(&handoff_lock);
+	ret = notifier_call_chain(&task_free_notifier, 0, task);
+	read_unlock(&handoff_lock);
+	return (ret == NOTIFY_OK) ? 1 : 0;
 }
 
-void profile_exec_unmap(struct mm_struct * mm)
+void profile_munmap(unsigned long addr)
 {
 	down_read(&profile_rwsem);
-	notifier_call_chain(&exec_unmap_notifier, 0, mm);
+	notifier_call_chain(&munmap_notifier, 0, (void *)addr);
 	up_read(&profile_rwsem);
 }
 
+int task_handoff_register(struct notifier_block * n)
+{
+	int err = -EINVAL;
+
+	write_lock(&handoff_lock);
+	err = notifier_chain_register(&task_free_notifier, n);
+	write_unlock(&handoff_lock);
+	return err;
+}
+
+int task_handoff_unregister(struct notifier_block * n)
+{
+	int err = -EINVAL;
+
+	write_lock(&handoff_lock);
+	err = notifier_chain_unregister(&task_free_notifier, n);
+	write_unlock(&handoff_lock);
+	return err;
+}
+
 int profile_event_register(enum profile_type type, struct notifier_block * n)
 {
 	int err = -EINVAL;
@@ -79,14 +108,11 @@ int profile_event_register(enum profile_type type, struct notifier_block * n)
 	down_write(&profile_rwsem);
  
 	switch (type) {
-		case EXIT_TASK:
-			err = notifier_chain_register(&exit_task_notifier, n);
-			break;
-		case EXIT_MMAP:
-			err = notifier_chain_register(&exit_mmap_notifier, n);
+		case PROFILE_TASK_EXIT:
+			err = notifier_chain_register(&task_exit_notifier, n);
 			break;
-		case EXEC_UNMAP:
-			err = notifier_chain_register(&exec_unmap_notifier, n);
+		case PROFILE_MUNMAP:
+			err = notifier_chain_register(&munmap_notifier, n);
 			break;
 	}
  
@@ -103,14 +129,11 @@ int profile_event_unregister(enum profile_type type, struct notifier_block * n)
 	down_write(&profile_rwsem);
  
 	switch (type) {
-		case EXIT_TASK:
-			err = notifier_chain_unregister(&exit_task_notifier, n);
+		case PROFILE_TASK_EXIT:
+			err = notifier_chain_unregister(&task_exit_notifier, n);
 			break;
-		case EXIT_MMAP:
-			err = notifier_chain_unregister(&exit_mmap_notifier, n);
-			break;
-		case EXEC_UNMAP:
-			err = notifier_chain_unregister(&exec_unmap_notifier, n);
+		case PROFILE_MUNMAP:
+			err = notifier_chain_unregister(&munmap_notifier, n);
 			break;
 	}
 
@@ -150,8 +173,150 @@ void profile_hook(struct pt_regs * regs)
 
 EXPORT_SYMBOL_GPL(register_profile_notifier);
 EXPORT_SYMBOL_GPL(unregister_profile_notifier);
+EXPORT_SYMBOL_GPL(task_handoff_register);
+EXPORT_SYMBOL_GPL(task_handoff_unregister);
 
 #endif /* CONFIG_PROFILING */
 
 EXPORT_SYMBOL_GPL(profile_event_register);
 EXPORT_SYMBOL_GPL(profile_event_unregister);
+
+void profile_hit(int type, void *__pc)
+{
+	unsigned long pc;
+
+	if (prof_on != type || !prof_buffer)
+		return;
+	pc = ((unsigned long)__pc - (unsigned long)_stext) >> prof_shift;
+	atomic_inc(&prof_buffer[min(pc, prof_len - 1)]);
+}
+
+void profile_tick(int type, struct pt_regs *regs)
+{
+	if (type == CPU_PROFILING)
+		profile_hook(regs);
+	if (!user_mode(regs) && cpu_isset(smp_processor_id(), prof_cpu_mask))
+		profile_hit(type, (void *)profile_pc(regs));
+}
+
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include <asm/ptrace.h>
+
+static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
+			int count, int *eof, void *data)
+{
+	int len = cpumask_scnprintf(page, count, *(cpumask_t *)data);
+	if (count - len < 2)
+		return -EINVAL;
+	len += sprintf(page + len, "\n");
+	return len;
+}
+
+static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer,
+					unsigned long count, void *data)
+{
+	cpumask_t *mask = (cpumask_t *)data;
+	unsigned long full_count = count, err;
+	cpumask_t new_value;
+
+	err = cpumask_parse(buffer, count, new_value);
+	if (err)
+		return err;
+
+	*mask = new_value;
+	return full_count;
+}
+
+void create_prof_cpu_mask(struct proc_dir_entry *root_irq_dir)
+{
+	struct proc_dir_entry *entry;
+
+	/* create /proc/irq/prof_cpu_mask */
+	if (!(entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir)))
+		return;
+	entry->nlink = 1;
+	entry->data = (void *)&prof_cpu_mask;
+	entry->read_proc = prof_cpu_mask_read_proc;
+	entry->write_proc = prof_cpu_mask_write_proc;
+}
+
+/*
+ * This function accesses profiling information. The returned data is
+ * binary: the sampling step and the actual contents of the profile
+ * buffer. Use of the program readprofile is recommended in order to
+ * get meaningful info out of these data.
+ */
+static ssize_t
+read_profile(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+	unsigned long p = *ppos;
+	ssize_t read;
+	char * pnt;
+	unsigned int sample_step = 1 << prof_shift;
+
+	if (p >= (prof_len+1)*sizeof(unsigned int))
+		return 0;
+	if (count > (prof_len+1)*sizeof(unsigned int) - p)
+		count = (prof_len+1)*sizeof(unsigned int) - p;
+	read = 0;
+
+	while (p < sizeof(unsigned int) && count > 0) {
+		put_user(*((char *)(&sample_step)+p),buf);
+		buf++; p++; count--; read++;
+	}
+	pnt = (char *)prof_buffer + p - sizeof(atomic_t);
+	if (copy_to_user(buf,(void *)pnt,count))
+		return -EFAULT;
+	read += count;
+	*ppos += read;
+	return read;
+}
+
+/*
+ * Writing to /proc/profile resets the counters
+ *
+ * Writing a 'profiling multiplier' value into it also re-sets the profiling
+ * interrupt frequency, on architectures that support this.
+ */
+static ssize_t write_profile(struct file *file, const char __user *buf,
+			     size_t count, loff_t *ppos)
+{
+#ifdef CONFIG_SMP
+	extern int setup_profiling_timer (unsigned int multiplier);
+
+	if (count == sizeof(int)) {
+		unsigned int multiplier;
+
+		if (copy_from_user(&multiplier, buf, sizeof(int)))
+			return -EFAULT;
+
+		if (setup_profiling_timer(multiplier))
+			return -EINVAL;
+	}
+#endif
+
+	memset(prof_buffer, 0, prof_len * sizeof(atomic_t));
+	return count;
+}
+
+static struct file_operations proc_profile_operations = {
+	.read		= read_profile,
+	.write		= write_profile,
+};
+
+static int __init create_proc_profile(void)
+{
+	struct proc_dir_entry *entry;
+
+	if (!prof_on)
+		return 0;
+	if (!(entry = create_proc_entry("profile", S_IWUSR | S_IRUGO, NULL)))
+		return 0;
+	entry->proc_fops = &proc_profile_operations;
+	entry->size = (1+prof_len) * sizeof(atomic_t);
+	return 0;
+}
+module_init(create_proc_profile);
+#endif /* CONFIG_PROC_FS */
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 8b2856aaf..b14b4a467 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -55,6 +55,15 @@ void __ptrace_unlink(task_t *child)
 	REMOVE_LINKS(child);
 	child->parent = child->real_parent;
 	SET_LINKS(child);
+
+	if (child->state == TASK_TRACED) {
+		/*
+		 * Turn a tracing stop into a normal stop now,
+		 * since with no tracer there would be no way
+		 * to wake it up with SIGCONT or SIGKILL.
+		 */
+		child->state = TASK_STOPPED;
+	}
 }
 
 /*
@@ -62,20 +71,35 @@ void __ptrace_unlink(task_t *child)
  */
 int ptrace_check_attach(struct task_struct *child, int kill)
 {
-	if (!(child->ptrace & PT_PTRACED))
-		return -ESRCH;
+	int ret = -ESRCH;
 
-	if (child->parent != current)
-		return -ESRCH;
+	/*
+	 * We take the read lock around doing both checks to close a
+	 * possible race where someone else was tracing our child and
+	 * detached between these two checks.  After this locked check,
+	 * we are sure that this is our traced child and that can only
+	 * be changed by us so it's not changing right after this.
+	 */
+	read_lock(&tasklist_lock);
+	if ((child->ptrace & PT_PTRACED) && child->parent == current &&
+	    child->signal != NULL) {
+		ret = 0;
+		spin_lock_irq(&child->sighand->siglock);
+		if (child->state == TASK_STOPPED) {
+			child->state = TASK_TRACED;
+		} else if (child->state != TASK_TRACED && !kill) {
+			ret = -ESRCH;
+		}
+		spin_unlock_irq(&child->sighand->siglock);
+	}
+	read_unlock(&tasklist_lock);
 
-	if (!kill) {
-		if (child->state != TASK_STOPPED)
-			return -ESRCH;
+	if (!ret && !kill) {
 		wait_task_inactive(child);
 	}
 
 	/* All systems go.. */
-	return 0;
+	return ret;
 }
 
 int ptrace_attach(struct task_struct *task)
@@ -178,8 +202,6 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
 		if (bytes > PAGE_SIZE-offset)
 			bytes = PAGE_SIZE-offset;
 
-		flush_cache_page(vma, addr);
-
 		maddr = kmap(page);
 		if (write) {
 			copy_to_user_page(vma, page, addr,
@@ -322,24 +344,3 @@ int ptrace_request(struct task_struct *child, long request,
 
 	return ret;
 }
-
-void ptrace_notify(int exit_code)
-{
-	BUG_ON (!(current->ptrace & PT_PTRACED));
-
-	/* Let the debugger run.  */
-	current->exit_code = exit_code;
-	set_current_state(TASK_STOPPED);
-	notify_parent(current, SIGCHLD);
-	schedule();
-
-	/*
-	 * Signals sent while we were stopped might set TIF_SIGPENDING.
-	 */
-
-	spin_lock_irq(&current->sighand->siglock);
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-}
-
-EXPORT_SYMBOL(ptrace_notify);
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index b331fe3f6..1b16bfc7d 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -17,9 +17,10 @@
  *
  * Copyright (C) IBM Corporation, 2001
  *
- * Author: Dipankar Sarma <dipankar@in.ibm.com>
+ * Authors: Dipankar Sarma <dipankar@in.ibm.com>
+ *	    Manfred Spraul <manfred@colorfullife.com>
  * 
- * Based on the original work by Paul McKenney <paul.mckenney@us.ibm.com>
+ * Based on the original work by Paul McKenney <paulmck@us.ibm.com>
  * and inputs from Rusty Russell, Andrea Arcangeli and Andi Kleen.
  * Papers:
  * http://www.rdrop.com/users/paulmck/paper/rclockpdcsproof.pdf
@@ -40,6 +41,7 @@
 #include <asm/bitops.h>
 #include <linux/module.h>
 #include <linux/completion.h>
+#include <linux/moduleparam.h>
 #include <linux/percpu.h>
 #include <linux/notifier.h>
 #include <linux/rcupdate.h>
@@ -48,44 +50,82 @@
 /* Definition for rcupdate control block. */
 struct rcu_ctrlblk rcu_ctrlblk = 
 	{ .cur = -300, .completed = -300 , .lock = SEQCNT_ZERO };
+struct rcu_ctrlblk rcu_bh_ctrlblk =
+	{ .cur = -300, .completed = -300 , .lock = SEQCNT_ZERO };
 
 /* Bookkeeping of the progress of the grace period */
-struct {
-	spinlock_t	mutex; /* Guard this struct and writes to rcu_ctrlblk */
-	cpumask_t	rcu_cpu_mask; /* CPUs that need to switch in order    */
+struct rcu_state {
+	spinlock_t	lock; /* Guard this struct and writes to rcu_ctrlblk */
+	cpumask_t	cpumask; /* CPUs that need to switch in order    */
 	                              /* for current batch to proceed.        */
-} rcu_state ____cacheline_maxaligned_in_smp =
-	  {.mutex = SPIN_LOCK_UNLOCKED, .rcu_cpu_mask = CPU_MASK_NONE };
+};
 
+struct rcu_state rcu_state ____cacheline_maxaligned_in_smp =
+	  {.lock = SPIN_LOCK_UNLOCKED, .cpumask = CPU_MASK_NONE };
+struct rcu_state rcu_bh_state ____cacheline_maxaligned_in_smp =
+	  {.lock = SPIN_LOCK_UNLOCKED, .cpumask = CPU_MASK_NONE };
 
 DEFINE_PER_CPU(struct rcu_data, rcu_data) = { 0L };
+DEFINE_PER_CPU(struct rcu_data, rcu_bh_data) = { 0L };
 
 /* Fake initialization required by compiler */
 static DEFINE_PER_CPU(struct tasklet_struct, rcu_tasklet) = {NULL};
-#define RCU_tasklet(cpu) (per_cpu(rcu_tasklet, cpu))
+static int maxbatch = 10;
 
 /**
- * call_rcu - Queue an RCU update request.
+ * call_rcu - Queue an RCU callback for invocation after a grace period.
  * @head: structure to be used for queueing the RCU updates.
  * @func: actual update function to be invoked after the grace period
  *
- * The update function will be invoked as soon as all CPUs have performed 
- * a context switch or been seen in the idle loop or in a user process. 
- * The read-side of critical section that use call_rcu() for updation must 
- * be protected by rcu_read_lock()/rcu_read_unlock().
+ * The update function will be invoked some time after a full grace
+ * period elapses, in other words after all currently executing RCU
+ * read-side critical sections have completed.  RCU read-side critical
+ * sections are delimited by rcu_read_lock() and rcu_read_unlock(),
+ * and may be nested.
  */
 void fastcall call_rcu(struct rcu_head *head,
 				void (*func)(struct rcu_head *rcu))
 {
-	int cpu;
 	unsigned long flags;
+	struct rcu_data *rdp;
 
 	head->func = func;
 	head->next = NULL;
 	local_irq_save(flags);
-	cpu = smp_processor_id();
-	*RCU_nxttail(cpu) = head;
-	RCU_nxttail(cpu) = &head->next;
+	rdp = &__get_cpu_var(rcu_data);
+	*rdp->nxttail = head;
+	rdp->nxttail = &head->next;
+	local_irq_restore(flags);
+}
+
+/**
+ * call_rcu_bh - Queue an RCU for invocation after a quicker grace period.
+ * @head: structure to be used for queueing the RCU updates.
+ * @func: actual update function to be invoked after the grace period
+ *
+ * The update function will be invoked some time after a full grace
+ * period elapses, in other words after all currently executing RCU
+ * read-side critical sections have completed. call_rcu_bh() assumes
+ * that the read-side critical sections end on completion of a softirq
+ * handler. This means that read-side critical sections in process
+ * context must not be interrupted by softirqs. This interface is to be
+ * used when most of the read-side critical sections are in softirq context.
+ * RCU read-side critical sections are delimited by rcu_read_lock() and
+ * rcu_read_unlock(), * if in interrupt context or rcu_read_lock_bh()
+ * and rcu_read_unlock_bh(), if in process context. These may be nested.
+ */
+void fastcall call_rcu_bh(struct rcu_head *head,
+				void (*func)(struct rcu_head *rcu))
+{
+	unsigned long flags;
+	struct rcu_data *rdp;
+
+	head->func = func;
+	head->next = NULL;
+	local_irq_save(flags);
+	rdp = &__get_cpu_var(rcu_bh_data);
+	*rdp->nxttail = head;
+	rdp->nxttail = &head->next;
 	local_irq_restore(flags);
 }
 
@@ -93,15 +133,23 @@ void fastcall call_rcu(struct rcu_head *head,
  * Invoke the completed RCU callbacks. They are expected to be in
  * a per-cpu list.
  */
-static void rcu_do_batch(struct rcu_head *list)
+static void rcu_do_batch(struct rcu_data *rdp)
 {
-	struct rcu_head *next;
+	struct rcu_head *next, *list;
+	int count = 0;
 
+	list = rdp->donelist;
 	while (list) {
-		next = list->next;
+		next = rdp->donelist = list->next;
 		list->func(list);
 		list = next;
+		if (++count >= maxbatch)
+			break;
 	}
+	if (!rdp->donelist)
+		rdp->donetail = &rdp->donelist;
+	else
+		tasklet_schedule(&per_cpu(rcu_tasklet, rdp->cpu));
 }
 
 /*
@@ -109,15 +157,15 @@ static void rcu_do_batch(struct rcu_head *list)
  * The grace period handling consists out of two steps:
  * - A new grace period is started.
  *   This is done by rcu_start_batch. The start is not broadcasted to
- *   all cpus, they must pick this up by comparing rcu_ctrlblk.cur with
- *   RCU_quiescbatch(cpu). All cpus are recorded  in the
- *   rcu_state.rcu_cpu_mask bitmap.
+ *   all cpus, they must pick this up by comparing rcp->cur with
+ *   rdp->quiescbatch. All cpus are recorded  in the
+ *   rcu_state.cpumask bitmap.
  * - All cpus must go through a quiescent state.
  *   Since the start of the grace period is not broadcasted, at least two
  *   calls to rcu_check_quiescent_state are required:
  *   The first call just notices that a new grace period is running. The
  *   following calls check if there was a quiescent state since the beginning
- *   of the grace period. If so, it updates rcu_state.rcu_cpu_mask. If
+ *   of the grace period. If so, it updates rcu_state.cpumask. If
  *   the bitmap is empty, then the grace period is completed.
  *   rcu_check_quiescent_state calls rcu_start_batch(0) to start the next grace
  *   period (if necessary).
@@ -125,22 +173,22 @@ static void rcu_do_batch(struct rcu_head *list)
 /*
  * Register a new batch of callbacks, and start it up if there is currently no
  * active batch and the batch to be registered has not already occurred.
- * Caller must hold rcu_state.mutex.
+ * Caller must hold rcu_state.lock.
  */
-static void rcu_start_batch(int next_pending)
+static void rcu_start_batch(struct rcu_ctrlblk *rcp, struct rcu_state *rsp,
+				int next_pending)
 {
 	if (next_pending)
-		rcu_ctrlblk.next_pending = 1;
+		rcp->next_pending = 1;
 
-	if (rcu_ctrlblk.next_pending &&
-			rcu_ctrlblk.completed == rcu_ctrlblk.cur) {
+	if (rcp->next_pending &&
+			rcp->completed == rcp->cur) {
 		/* Can't change, since spin lock held. */
-		cpus_andnot(rcu_state.rcu_cpu_mask, cpu_online_map,
-							nohz_cpu_mask);
-		write_seqcount_begin(&rcu_ctrlblk.lock);
-		rcu_ctrlblk.next_pending = 0;
-		rcu_ctrlblk.cur++;
-		write_seqcount_end(&rcu_ctrlblk.lock);
+		cpus_andnot(rsp->cpumask, cpu_online_map, nohz_cpu_mask);
+		write_seqcount_begin(&rcp->lock);
+		rcp->next_pending = 0;
+		rcp->cur++;
+		write_seqcount_end(&rcp->lock);
 	}
 }
 
@@ -149,13 +197,13 @@ static void rcu_start_batch(int next_pending)
  * Clear it from the cpu mask and complete the grace period if it was the last
  * cpu. Start another grace period if someone has further entries pending
  */
-static void cpu_quiet(int cpu)
+static void cpu_quiet(int cpu, struct rcu_ctrlblk *rcp, struct rcu_state *rsp)
 {
-	cpu_clear(cpu, rcu_state.rcu_cpu_mask);
-	if (cpus_empty(rcu_state.rcu_cpu_mask)) {
+	cpu_clear(cpu, rsp->cpumask);
+	if (cpus_empty(rsp->cpumask)) {
 		/* batch completed ! */
-		rcu_ctrlblk.completed = rcu_ctrlblk.cur;
-		rcu_start_batch(0);
+		rcp->completed = rcp->cur;
+		rcu_start_batch(rcp, rsp, 0);
 	}
 }
 
@@ -164,15 +212,14 @@ static void cpu_quiet(int cpu)
  * switch). If so and if it already hasn't done so in this RCU
  * quiescent cycle, then indicate that it has done so.
  */
-static void rcu_check_quiescent_state(void)
+static void rcu_check_quiescent_state(struct rcu_ctrlblk *rcp,
+			struct rcu_state *rsp, struct rcu_data *rdp)
 {
-	int cpu = smp_processor_id();
-
-	if (RCU_quiescbatch(cpu) != rcu_ctrlblk.cur) {
+	if (rdp->quiescbatch != rcp->cur) {
 		/* new grace period: record qsctr value. */
-		RCU_qs_pending(cpu) = 1;
-		RCU_last_qsctr(cpu) = RCU_qsctr(cpu);
-		RCU_quiescbatch(cpu) = rcu_ctrlblk.cur;
+		rdp->qs_pending = 1;
+		rdp->last_qsctr = rdp->qsctr;
+		rdp->quiescbatch = rcp->cur;
 		return;
 	}
 
@@ -180,7 +227,7 @@ static void rcu_check_quiescent_state(void)
 	 * qs_pending is checked instead of the actual bitmap to avoid
 	 * cacheline trashing.
 	 */
-	if (!RCU_qs_pending(cpu))
+	if (!rdp->qs_pending)
 		return;
 
 	/* 
@@ -188,19 +235,19 @@ static void rcu_check_quiescent_state(void)
 	 * we may miss one quiescent state of that CPU. That is
 	 * tolerable. So no need to disable interrupts.
 	 */
-	if (RCU_qsctr(cpu) == RCU_last_qsctr(cpu))
+	if (rdp->qsctr == rdp->last_qsctr)
 		return;
-	RCU_qs_pending(cpu) = 0;
+	rdp->qs_pending = 0;
 
-	spin_lock(&rcu_state.mutex);
+	spin_lock(&rsp->lock);
 	/*
-	 * RCU_quiescbatch/batch.cur and the cpu bitmap can come out of sync
+	 * rdp->quiescbatch/rcp->cur and the cpu bitmap can come out of sync
 	 * during cpu startup. Ignore the quiescent state.
 	 */
-	if (likely(RCU_quiescbatch(cpu) == rcu_ctrlblk.cur))
-		cpu_quiet(cpu);
+	if (likely(rdp->quiescbatch == rcp->cur))
+		cpu_quiet(rdp->cpu, rcp, rsp);
 
-	spin_unlock(&rcu_state.mutex);
+	spin_unlock(&rsp->lock);
 }
 
 
@@ -210,112 +257,140 @@ static void rcu_check_quiescent_state(void)
  * locking requirements, the list it's pulling from has to belong to a cpu
  * which is dead and hence not processing interrupts.
  */
-static void rcu_move_batch(struct rcu_head *list)
+static void rcu_move_batch(struct rcu_data *this_rdp, struct rcu_head *list,
+				struct rcu_head **tail)
 {
-	int cpu;
-
 	local_irq_disable();
-
-	cpu = smp_processor_id();
-
-	while (list != NULL) {
-		*RCU_nxttail(cpu) = list;
-		RCU_nxttail(cpu) = &list->next;
-		list = list->next;
-	}
+	*this_rdp->nxttail = list;
+	if (list)
+		this_rdp->nxttail = tail;
 	local_irq_enable();
 }
 
-static void rcu_offline_cpu(int cpu)
+static void __rcu_offline_cpu(struct rcu_data *this_rdp,
+	struct rcu_ctrlblk *rcp, struct rcu_state *rsp, struct rcu_data *rdp)
 {
 	/* if the cpu going offline owns the grace period
 	 * we can block indefinitely waiting for it, so flush
 	 * it here
 	 */
-	spin_lock_bh(&rcu_state.mutex);
-	if (rcu_ctrlblk.cur != rcu_ctrlblk.completed)
-		cpu_quiet(cpu);
-	spin_unlock_bh(&rcu_state.mutex);
+	spin_lock_bh(&rsp->lock);
+	if (rcp->cur != rcp->completed)
+		cpu_quiet(rdp->cpu, rcp, rsp);
+	spin_unlock_bh(&rsp->lock);
+	rcu_move_batch(this_rdp, rdp->curlist, rdp->curtail);
+	rcu_move_batch(this_rdp, rdp->nxtlist, rdp->nxttail);
 
-	rcu_move_batch(RCU_curlist(cpu));
-	rcu_move_batch(RCU_nxtlist(cpu));
-
-	tasklet_kill_immediate(&RCU_tasklet(cpu), cpu);
+}
+static void rcu_offline_cpu(int cpu)
+{
+	struct rcu_data *this_rdp = &get_cpu_var(rcu_data);
+	struct rcu_data *this_bh_rdp = &get_cpu_var(rcu_bh_data);
+
+	__rcu_offline_cpu(this_rdp, &rcu_ctrlblk, &rcu_state,
+					&per_cpu(rcu_data, cpu));
+	__rcu_offline_cpu(this_bh_rdp, &rcu_bh_ctrlblk, &rcu_bh_state,
+					&per_cpu(rcu_bh_data, cpu));
+	put_cpu_var(rcu_data);
+	put_cpu_var(rcu_bh_data);
+	tasklet_kill_immediate(&per_cpu(rcu_tasklet, cpu), cpu);
 }
 
-#endif
+#else
 
-void rcu_restart_cpu(int cpu)
+static void rcu_offline_cpu(int cpu)
 {
-	spin_lock_bh(&rcu_state.mutex);
-	RCU_quiescbatch(cpu) = rcu_ctrlblk.completed;
-	RCU_qs_pending(cpu) = 0;
-	spin_unlock_bh(&rcu_state.mutex);
 }
 
+#endif
+
 /*
  * This does the RCU processing work from tasklet context. 
  */
-static void rcu_process_callbacks(unsigned long unused)
+static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp,
+			struct rcu_state *rsp, struct rcu_data *rdp)
 {
-	int cpu = smp_processor_id();
-	struct rcu_head *rcu_list = NULL;
-
-	if (RCU_curlist(cpu) &&
-	    !rcu_batch_before(rcu_ctrlblk.completed, RCU_batch(cpu))) {
-		rcu_list = RCU_curlist(cpu);
-		RCU_curlist(cpu) = NULL;
+	if (rdp->curlist && !rcu_batch_before(rcp->completed, rdp->batch)) {
+		*rdp->donetail = rdp->curlist;
+		rdp->donetail = rdp->curtail;
+		rdp->curlist = NULL;
+		rdp->curtail = &rdp->curlist;
 	}
 
 	local_irq_disable();
-	if (RCU_nxtlist(cpu) && !RCU_curlist(cpu)) {
+	if (rdp->nxtlist && !rdp->curlist) {
 		int next_pending, seq;
 
-		RCU_curlist(cpu) = RCU_nxtlist(cpu);
-		RCU_nxtlist(cpu) = NULL;
-		RCU_nxttail(cpu) = &RCU_nxtlist(cpu);
+		rdp->curlist = rdp->nxtlist;
+		rdp->curtail = rdp->nxttail;
+		rdp->nxtlist = NULL;
+		rdp->nxttail = &rdp->nxtlist;
 		local_irq_enable();
 
 		/*
 		 * start the next batch of callbacks
 		 */
 		do {
-			seq = read_seqcount_begin(&rcu_ctrlblk.lock);
+			seq = read_seqcount_begin(&rcp->lock);
 			/* determine batch number */
-			RCU_batch(cpu) = rcu_ctrlblk.cur + 1;
-			next_pending = rcu_ctrlblk.next_pending;
-		} while (read_seqcount_retry(&rcu_ctrlblk.lock, seq));
+			rdp->batch = rcp->cur + 1;
+			next_pending = rcp->next_pending;
+		} while (read_seqcount_retry(&rcp->lock, seq));
 
 		if (!next_pending) {
 			/* and start it/schedule start if it's a new batch */
-			spin_lock(&rcu_state.mutex);
-			rcu_start_batch(1);
-			spin_unlock(&rcu_state.mutex);
+			spin_lock(&rsp->lock);
+			rcu_start_batch(rcp, rsp, 1);
+			spin_unlock(&rsp->lock);
 		}
 	} else {
 		local_irq_enable();
 	}
-	rcu_check_quiescent_state();
-	if (rcu_list)
-		rcu_do_batch(rcu_list);
+	rcu_check_quiescent_state(rcp, rsp, rdp);
+	if (rdp->donelist)
+		rcu_do_batch(rdp);
+}
+
+static void rcu_process_callbacks(unsigned long unused)
+{
+	__rcu_process_callbacks(&rcu_ctrlblk, &rcu_state,
+				&__get_cpu_var(rcu_data));
+	__rcu_process_callbacks(&rcu_bh_ctrlblk, &rcu_bh_state,
+				&__get_cpu_var(rcu_bh_data));
 }
 
 void rcu_check_callbacks(int cpu, int user)
 {
 	if (user || 
 	    (idle_cpu(cpu) && !in_softirq() && 
-				hardirq_count() <= (1 << HARDIRQ_SHIFT)))
-		RCU_qsctr(cpu)++;
-	tasklet_schedule(&RCU_tasklet(cpu));
+				hardirq_count() <= (1 << HARDIRQ_SHIFT))) {
+		rcu_qsctr_inc(cpu);
+		rcu_bh_qsctr_inc(cpu);
+	} else if (!in_softirq())
+		rcu_bh_qsctr_inc(cpu);
+	tasklet_schedule(&per_cpu(rcu_tasklet, cpu));
+}
+
+static void rcu_init_percpu_data(int cpu, struct rcu_ctrlblk *rcp,
+						struct rcu_data *rdp)
+{
+	memset(rdp, 0, sizeof(*rdp));
+	rdp->curtail = &rdp->curlist;
+	rdp->nxttail = &rdp->nxtlist;
+	rdp->donetail = &rdp->donelist;
+	rdp->quiescbatch = rcp->completed;
+	rdp->qs_pending = 0;
+	rdp->cpu = cpu;
 }
 
 static void __devinit rcu_online_cpu(int cpu)
 {
-	memset(&per_cpu(rcu_data, cpu), 0, sizeof(struct rcu_data));
-	tasklet_init(&RCU_tasklet(cpu), rcu_process_callbacks, 0UL);
-	RCU_nxttail(cpu) = &RCU_nxtlist(cpu);
-	RCU_quiescbatch(cpu) = rcu_ctrlblk.completed;
-	RCU_qs_pending(cpu) = 0;
+	struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
+	struct rcu_data *bh_rdp = &per_cpu(rcu_bh_data, cpu);
+
+	rcu_init_percpu_data(cpu, &rcu_ctrlblk, rdp);
+	rcu_init_percpu_data(cpu, &rcu_bh_ctrlblk, bh_rdp);
+	tasklet_init(&per_cpu(rcu_tasklet, cpu), rcu_process_callbacks, 0UL);
 }
 
 static int __devinit rcu_cpu_notify(struct notifier_block *self, 
@@ -326,11 +401,9 @@ static int __devinit rcu_cpu_notify(struct notifier_block *self,
 	case CPU_UP_PREPARE:
 		rcu_online_cpu(cpu);
 		break;
-#ifdef CONFIG_HOTPLUG_CPU
 	case CPU_DEAD:
 		rcu_offline_cpu(cpu);
 		break;
-#endif
 	default:
 		break;
 	}
@@ -370,8 +443,13 @@ static void wakeme_after_rcu(struct rcu_head  *head)
 }
 
 /**
- * synchronize-kernel - wait until all the CPUs have gone
- * through a "quiescent" state. It may sleep.
+ * synchronize_kernel - wait until a grace period has elapsed.
+ *
+ * Control will return to the caller some time after a full grace
+ * period has elapsed, in other words after all currently executing RCU
+ * read-side critical sections have completed.  RCU read-side critical
+ * sections are delimited by rcu_read_lock() and rcu_read_unlock(),
+ * and may be nested.
  */
 void synchronize_kernel(void)
 {
@@ -385,6 +463,7 @@ void synchronize_kernel(void)
 	wait_for_completion(&rcu.completion);
 }
 
-
+module_param(maxbatch, int, 0);
 EXPORT_SYMBOL(call_rcu);
+EXPORT_SYMBOL(call_rcu_bh);
 EXPORT_SYMBOL(synchronize_kernel);
diff --git a/kernel/resource.c b/kernel/resource.c
index da0ffd601..4a3f5c2d1 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -315,11 +315,12 @@ EXPORT_SYMBOL(allocate_resource);
  */
 int insert_resource(struct resource *parent, struct resource *new)
 {
-	int result = 0;
+	int result;
 	struct resource *first, *next;
 
 	write_lock(&resource_lock);
  begin:
+ 	result = 0;
 	first = __request_resource(parent, new);
 	if (!first)
 		goto out;
@@ -328,15 +329,20 @@ int insert_resource(struct resource *parent, struct resource *new)
 	if (first == parent)
 		goto out;
 
-	for (next = first; next->sibling; next = next->sibling)
+	/* Resource fully contained by the clashing resource? Recurse into it */
+	if (first->start <= new->start && first->end >= new->end) {
+		parent = first;
+		goto begin;
+	}
+
+	for (next = first; ; next = next->sibling) {
+		/* Partial overlap? Bad, and unfixable */
+		if (next->start < new->start || next->end > new->end)
+			goto out;
+		if (!next->sibling)
+			break;
 		if (next->sibling->start > new->end)
 			break;
-
-	/* existing resource includes new resource */
-	if (next->end >= new->end) {
-		parent = next;
-		result = 0;
-		goto begin;
 	}
 
 	result = 0;
diff --git a/kernel/sched.c b/kernel/sched.c
index 305f94852..f1780c905 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -31,6 +31,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/security.h>
 #include <linux/notifier.h>
+#include <linux/profile.h>
 #include <linux/suspend.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
@@ -40,8 +41,12 @@
 #include <linux/cpu.h>
 #include <linux/percpu.h>
 #include <linux/kthread.h>
+#include <linux/seq_file.h>
+#include <linux/times.h>
 #include <linux/vserver/sched.h>
 #include <linux/vs_base.h>
+#include <linux/vs_context.h>
+#include <linux/vs_cvirt.h>
 #include <asm/tlb.h>
 
 #include <asm/unistd.h>
@@ -69,8 +74,6 @@
 #define USER_PRIO(p)		((p)-MAX_RT_PRIO)
 #define TASK_USER_PRIO(p)	USER_PRIO((p)->static_prio)
 #define MAX_USER_PRIO		(USER_PRIO(MAX_PRIO))
-#define AVG_TIMESLICE	(MIN_TIMESLICE + ((MAX_TIMESLICE - MIN_TIMESLICE) *\
-			(MAX_PRIO-1-NICE_TO_PRIO(0))/(MAX_USER_PRIO - 1)))
 
 /*
  * Some helpers for converting nanosecond timing to jiffy resolution
@@ -81,12 +84,12 @@
 /*
  * These are the 'tuning knobs' of the scheduler:
  *
- * Minimum timeslice is 10 msecs, default timeslice is 100 msecs,
- * maximum timeslice is 200 msecs. Timeslices get refilled after
- * they expire.
+ * Minimum timeslice is 5 msecs (or 1 jiffy, whichever is larger),
+ * default timeslice is 100 msecs, maximum timeslice is 800 msecs.
+ * Timeslices get refilled after they expire.
  */
-#define MIN_TIMESLICE		( 10 * HZ / 1000)
-#define MAX_TIMESLICE		(200 * HZ / 1000)
+#define MIN_TIMESLICE		max(5 * HZ / 1000, 1)
+#define DEF_TIMESLICE		(100 * HZ / 1000)
 #define ON_RUNQUEUE_WEIGHT	 30
 #define CHILD_PENALTY		 95
 #define PARENT_PENALTY		100
@@ -94,7 +97,7 @@
 #define PRIO_BONUS_RATIO	 25
 #define MAX_BONUS		(MAX_USER_PRIO * PRIO_BONUS_RATIO / 100)
 #define INTERACTIVE_DELTA	  2
-#define MAX_SLEEP_AVG		(AVG_TIMESLICE * MAX_BONUS)
+#define MAX_SLEEP_AVG		(DEF_TIMESLICE * MAX_BONUS)
 #define STARVATION_LIMIT	(MAX_SLEEP_AVG)
 #define NS_MAX_SLEEP_AVG	(JIFFIES_TO_NS(MAX_SLEEP_AVG))
 #define CREDIT_LIMIT		100
@@ -163,26 +166,36 @@
 	((p)->prio < (rq)->curr->prio)
 
 /*
- * BASE_TIMESLICE scales user-nice values [ -20 ... 19 ]
- * to time slice values.
+ * task_timeslice() scales user-nice values [ -20 ... 0 ... 19 ]
+ * to time slice values: [800ms ... 100ms ... 5ms]
  *
  * The higher a thread's priority, the bigger timeslices
  * it gets during one round of execution. But even the lowest
  * priority thread gets MIN_TIMESLICE worth of execution time.
- *
- * task_timeslice() is the interface that is used by the scheduler.
  */
 
-#define BASE_TIMESLICE(p) (MIN_TIMESLICE + \
-		((MAX_TIMESLICE - MIN_TIMESLICE) * \
-			(MAX_PRIO-1 - (p)->static_prio) / (MAX_USER_PRIO-1)))
+#define SCALE_PRIO(x, prio) \
+	max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO/2), MIN_TIMESLICE)
 
 static unsigned int task_timeslice(task_t *p)
 {
-	return BASE_TIMESLICE(p);
+	if (p->static_prio < NICE_TO_PRIO(0))
+		return SCALE_PRIO(DEF_TIMESLICE*4, p->static_prio);
+	else
+		return SCALE_PRIO(DEF_TIMESLICE, p->static_prio);
 }
+#define task_hot(p, now, sd) ((long long) ((now) - (p)->last_ran)	\
+				< (long long) (sd)->cache_hot_time)
+
+enum idle_type
+{
+	IDLE,
+	NOT_IDLE,
+	NEWLY_IDLE,
+	MAX_IDLE_TYPES
+};
 
-#define task_hot(p, now, sd) ((now) - (p)->timestamp < (sd)->cache_hot_time)
+struct sched_domain;
 
 /*
  * These are the runqueue data structures:
@@ -235,12 +248,190 @@ struct runqueue {
 	task_t *migration_thread;
 	struct list_head migration_queue;
 #endif
+#ifdef CONFIG_VSERVER_HARDCPU
 	struct list_head hold_queue;
 	int idle_tokens;
+#endif
+
+#ifdef CONFIG_SCHEDSTATS
+	/* latency stats */
+	struct sched_info rq_sched_info;
+
+	/* sys_sched_yield() stats */
+	unsigned long yld_exp_empty;
+	unsigned long yld_act_empty;
+	unsigned long yld_both_empty;
+	unsigned long yld_cnt;
+
+	/* schedule() stats */
+	unsigned long sched_noswitch;
+	unsigned long sched_switch;
+	unsigned long sched_cnt;
+	unsigned long sched_goidle;
+
+	/* pull_task() stats */
+	unsigned long pt_gained[MAX_IDLE_TYPES];
+	unsigned long pt_lost[MAX_IDLE_TYPES];
+
+	/* active_load_balance() stats */
+	unsigned long alb_cnt;
+	unsigned long alb_lost;
+	unsigned long alb_gained;
+	unsigned long alb_failed;
+
+	/* try_to_wake_up() stats */
+	unsigned long ttwu_cnt;
+	unsigned long ttwu_attempts;
+	unsigned long ttwu_moved;
+
+	/* wake_up_new_task() stats */
+	unsigned long wunt_cnt;
+	unsigned long wunt_moved;
+
+	/* sched_migrate_task() stats */
+	unsigned long smt_cnt;
+
+	/* sched_balance_exec() stats */
+	unsigned long sbe_cnt;
+#endif
 };
 
 static DEFINE_PER_CPU(struct runqueue, runqueues);
 
+/*
+ * sched-domains (multiprocessor balancing) declarations:
+ */
+#ifdef CONFIG_SMP
+#define SCHED_LOAD_SCALE	128UL	/* increase resolution of load */
+
+#define SD_BALANCE_NEWIDLE	1	/* Balance when about to become idle */
+#define SD_BALANCE_EXEC		2	/* Balance on exec */
+#define SD_WAKE_IDLE		4	/* Wake to idle CPU on task wakeup */
+#define SD_WAKE_AFFINE		8	/* Wake task to waking CPU */
+#define SD_WAKE_BALANCE		16	/* Perform balancing at task wakeup */
+#define SD_SHARE_CPUPOWER	32	/* Domain members share cpu power */
+
+struct sched_group {
+	struct sched_group *next;	/* Must be a circular list */
+	cpumask_t cpumask;
+
+	/*
+	 * CPU power of this group, SCHED_LOAD_SCALE being max power for a
+	 * single CPU. This should be read only (except for setup). Although
+	 * it will need to be written to at cpu hot(un)plug time, perhaps the
+	 * cpucontrol semaphore will provide enough exclusion?
+	 */
+	unsigned long cpu_power;
+};
+
+struct sched_domain {
+	/* These fields must be setup */
+	struct sched_domain *parent;	/* top domain must be null terminated */
+	struct sched_group *groups;	/* the balancing groups of the domain */
+	cpumask_t span;			/* span of all CPUs in this domain */
+	unsigned long min_interval;	/* Minimum balance interval ms */
+	unsigned long max_interval;	/* Maximum balance interval ms */
+	unsigned int busy_factor;	/* less balancing by factor if busy */
+	unsigned int imbalance_pct;	/* No balance until over watermark */
+	unsigned long long cache_hot_time; /* Task considered cache hot (ns) */
+	unsigned int cache_nice_tries;	/* Leave cache hot tasks for # tries */
+	unsigned int per_cpu_gain;	/* CPU % gained by adding domain cpus */
+	int flags;			/* See SD_* */
+
+	/* Runtime fields. */
+	unsigned long last_balance;	/* init to jiffies. units in jiffies */
+	unsigned int balance_interval;	/* initialise to 1. units in ms. */
+	unsigned int nr_balance_failed; /* initialise to 0 */
+
+#ifdef CONFIG_SCHEDSTATS
+	/* load_balance() stats */
+	unsigned long lb_cnt[MAX_IDLE_TYPES];
+	unsigned long lb_failed[MAX_IDLE_TYPES];
+	unsigned long lb_imbalance[MAX_IDLE_TYPES];
+	unsigned long lb_nobusyg[MAX_IDLE_TYPES];
+	unsigned long lb_nobusyq[MAX_IDLE_TYPES];
+
+	/* sched_balance_exec() stats */
+	unsigned long sbe_attempts;
+	unsigned long sbe_pushed;
+
+	/* try_to_wake_up() stats */
+	unsigned long ttwu_wake_affine;
+	unsigned long ttwu_wake_balance;
+#endif
+};
+
+#ifndef ARCH_HAS_SCHED_TUNE
+#ifdef CONFIG_SCHED_SMT
+#define ARCH_HAS_SCHED_WAKE_IDLE
+/* Common values for SMT siblings */
+#define SD_SIBLING_INIT (struct sched_domain) {		\
+	.span			= CPU_MASK_NONE,	\
+	.parent			= NULL,			\
+	.groups			= NULL,			\
+	.min_interval		= 1,			\
+	.max_interval		= 2,			\
+	.busy_factor		= 8,			\
+	.imbalance_pct		= 110,			\
+	.cache_hot_time		= 0,			\
+	.cache_nice_tries	= 0,			\
+	.per_cpu_gain		= 25,			\
+	.flags			= SD_BALANCE_NEWIDLE	\
+				| SD_BALANCE_EXEC	\
+				| SD_WAKE_AFFINE	\
+				| SD_WAKE_IDLE		\
+				| SD_SHARE_CPUPOWER,	\
+	.last_balance		= jiffies,		\
+	.balance_interval	= 1,			\
+	.nr_balance_failed	= 0,			\
+}
+#endif
+
+/* Common values for CPUs */
+#define SD_CPU_INIT (struct sched_domain) {		\
+	.span			= CPU_MASK_NONE,	\
+	.parent			= NULL,			\
+	.groups			= NULL,			\
+	.min_interval		= 1,			\
+	.max_interval		= 4,			\
+	.busy_factor		= 64,			\
+	.imbalance_pct		= 125,			\
+	.cache_hot_time		= cache_decay_ticks*1000000 ? : (5*1000000/2),\
+	.cache_nice_tries	= 1,			\
+	.per_cpu_gain		= 100,			\
+	.flags			= SD_BALANCE_NEWIDLE	\
+				| SD_BALANCE_EXEC	\
+				| SD_WAKE_AFFINE	\
+				| SD_WAKE_BALANCE,	\
+	.last_balance		= jiffies,		\
+	.balance_interval	= 1,			\
+	.nr_balance_failed	= 0,			\
+}
+
+/* Arch can override this macro in processor.h */
+#if defined(CONFIG_NUMA) && !defined(SD_NODE_INIT)
+#define SD_NODE_INIT (struct sched_domain) {		\
+	.span			= CPU_MASK_NONE,	\
+	.parent			= NULL,			\
+	.groups			= NULL,			\
+	.min_interval		= 8,			\
+	.max_interval		= 32,			\
+	.busy_factor		= 32,			\
+	.imbalance_pct		= 125,			\
+	.cache_hot_time		= (10*1000000),		\
+	.cache_nice_tries	= 1,			\
+	.per_cpu_gain		= 100,			\
+	.flags			= SD_BALANCE_EXEC	\
+				| SD_WAKE_BALANCE,	\
+	.last_balance		= jiffies,		\
+	.balance_interval	= 1,			\
+	.nr_balance_failed	= 0,			\
+}
+#endif
+#endif /* ARCH_HAS_SCHED_TUNE */
+#endif
+
+
 #define for_each_domain(cpu, domain) \
 	for (domain = cpu_rq(cpu)->sd; domain; domain = domain->parent)
 
@@ -283,6 +474,104 @@ static inline void task_rq_unlock(runqueue_t *rq, unsigned long *flags)
 	spin_unlock_irqrestore(&rq->lock, *flags);
 }
 
+#ifdef CONFIG_SCHEDSTATS
+/*
+ * bump this up when changing the output format or the meaning of an existing
+ * format, so that tools can adapt (or abort)
+ */
+#define SCHEDSTAT_VERSION 10
+
+static int show_schedstat(struct seq_file *seq, void *v)
+{
+	int cpu;
+	enum idle_type itype;
+
+	seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION);
+	seq_printf(seq, "timestamp %lu\n", jiffies);
+	for_each_online_cpu(cpu) {
+		runqueue_t *rq = cpu_rq(cpu);
+#ifdef CONFIG_SMP
+		struct sched_domain *sd;
+		int dcnt = 0;
+#endif
+
+		/* runqueue-specific stats */
+		seq_printf(seq,
+		    "cpu%d %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu "
+		    "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
+		    cpu, rq->yld_both_empty,
+		    rq->yld_act_empty, rq->yld_exp_empty,
+		    rq->yld_cnt, rq->sched_noswitch,
+		    rq->sched_switch, rq->sched_cnt, rq->sched_goidle,
+		    rq->alb_cnt, rq->alb_gained, rq->alb_lost,
+		    rq->alb_failed,
+		    rq->ttwu_cnt, rq->ttwu_moved, rq->ttwu_attempts,
+		    rq->wunt_cnt, rq->wunt_moved,
+		    rq->smt_cnt, rq->sbe_cnt, rq->rq_sched_info.cpu_time,
+		    rq->rq_sched_info.run_delay, rq->rq_sched_info.pcnt);
+
+		for (itype = IDLE; itype < MAX_IDLE_TYPES; itype++)
+			seq_printf(seq, " %lu %lu", rq->pt_gained[itype],
+						    rq->pt_lost[itype]);
+		seq_printf(seq, "\n");
+
+#ifdef CONFIG_SMP
+		/* domain-specific stats */
+		for_each_domain(cpu, sd) {
+			char mask_str[NR_CPUS];
+
+			cpumask_scnprintf(mask_str, NR_CPUS, sd->span);
+			seq_printf(seq, "domain%d %s", dcnt++, mask_str);
+			for (itype = IDLE; itype < MAX_IDLE_TYPES; itype++) {
+				seq_printf(seq, " %lu %lu %lu %lu %lu",
+				    sd->lb_cnt[itype],
+				    sd->lb_failed[itype],
+				    sd->lb_imbalance[itype],
+				    sd->lb_nobusyq[itype],
+				    sd->lb_nobusyg[itype]);
+			}
+			seq_printf(seq, " %lu %lu %lu %lu\n",
+			    sd->sbe_pushed, sd->sbe_attempts,
+			    sd->ttwu_wake_affine, sd->ttwu_wake_balance);
+		}
+#endif
+	}
+	return 0;
+}
+
+static int schedstat_open(struct inode *inode, struct file *file)
+{
+	unsigned int size = PAGE_SIZE * (1 + num_online_cpus() / 32);
+	char *buf = kmalloc(size, GFP_KERNEL);
+	struct seq_file *m;
+	int res;
+
+	if (!buf)
+		return -ENOMEM;
+	res = single_open(file, show_schedstat, NULL);
+	if (!res) {
+		m = file->private_data;
+		m->buf = buf;
+		m->size = size;
+	} else
+		kfree(buf);
+	return res;
+}
+
+struct file_operations proc_schedstat_operations = {
+	.open    = schedstat_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = single_release,
+};
+
+# define schedstat_inc(rq, field)	rq->field++;
+# define schedstat_add(rq, field, amt)	rq->field += amt;
+#else /* !CONFIG_SCHEDSTATS */
+# define schedstat_inc(rq, field)	do { } while (0);
+# define schedstat_add(rq, field, amt)	do { } while (0);
+#endif
+
 /*
  * rq_lock - lock a given runqueue and disable interrupts.
  */
@@ -302,6 +591,112 @@ static inline void rq_unlock(runqueue_t *rq)
 	spin_unlock_irq(&rq->lock);
 }
 
+#ifdef CONFIG_SCHEDSTATS
+/*
+ * Called when a process is dequeued from the active array and given
+ * the cpu.  We should note that with the exception of interactive
+ * tasks, the expired queue will become the active queue after the active
+ * queue is empty, without explicitly dequeuing and requeuing tasks in the
+ * expired queue.  (Interactive tasks may be requeued directly to the
+ * active queue, thus delaying tasks in the expired queue from running;
+ * see scheduler_tick()).
+ *
+ * This function is only called from sched_info_arrive(), rather than
+ * dequeue_task(). Even though a task may be queued and dequeued multiple
+ * times as it is shuffled about, we're really interested in knowing how
+ * long it was from the *first* time it was queued to the time that it
+ * finally hit a cpu.
+ */
+static inline void sched_info_dequeued(task_t *t)
+{
+	t->sched_info.last_queued = 0;
+}
+
+/*
+ * Called when a task finally hits the cpu.  We can now calculate how
+ * long it was waiting to run.  We also note when it began so that we
+ * can keep stats on how long its timeslice is.
+ */
+static inline void sched_info_arrive(task_t *t)
+{
+	unsigned long now = jiffies, diff = 0;
+	struct runqueue *rq = task_rq(t);
+
+	if (t->sched_info.last_queued)
+		diff = now - t->sched_info.last_queued;
+	sched_info_dequeued(t);
+	t->sched_info.run_delay += diff;
+	t->sched_info.last_arrival = now;
+	t->sched_info.pcnt++;
+
+	if (!rq)
+		return;
+
+	rq->rq_sched_info.run_delay += diff;
+	rq->rq_sched_info.pcnt++;
+}
+
+/*
+ * Called when a process is queued into either the active or expired
+ * array.  The time is noted and later used to determine how long we
+ * had to wait for us to reach the cpu.  Since the expired queue will
+ * become the active queue after active queue is empty, without dequeuing
+ * and requeuing any tasks, we are interested in queuing to either. It
+ * is unusual but not impossible for tasks to be dequeued and immediately
+ * requeued in the same or another array: this can happen in sched_yield(),
+ * set_user_nice(), and even load_balance() as it moves tasks from runqueue
+ * to runqueue.
+ *
+ * This function is only called from enqueue_task(), but also only updates
+ * the timestamp if it is already not set.  It's assumed that
+ * sched_info_dequeued() will clear that stamp when appropriate.
+ */
+static inline void sched_info_queued(task_t *t)
+{
+	if (!t->sched_info.last_queued)
+		t->sched_info.last_queued = jiffies;
+}
+
+/*
+ * Called when a process ceases being the active-running process, either
+ * voluntarily or involuntarily.  Now we can calculate how long we ran.
+ */
+static inline void sched_info_depart(task_t *t)
+{
+	struct runqueue *rq = task_rq(t);
+	unsigned long diff = jiffies - t->sched_info.last_arrival;
+
+	t->sched_info.cpu_time += diff;
+
+	if (rq)
+		rq->rq_sched_info.cpu_time += diff;
+}
+
+/*
+ * Called when tasks are switched involuntarily due, typically, to expiring
+ * their time slice.  (This may also be called when switching to or from
+ * the idle task.)  We are only called when prev != next.
+ */
+static inline void sched_info_switch(task_t *prev, task_t *next)
+{
+	struct runqueue *rq = task_rq(prev);
+
+	/*
+	 * prev now departs the cpu.  It's not interesting to record
+	 * stats about how efficient we were at scheduling the idle
+	 * process, however.
+	 */
+	if (prev != rq->idle)
+		sched_info_depart(prev);
+
+	if (next != rq->idle)
+		sched_info_arrive(next);
+}
+#else
+#define sched_info_queued(t)		do { } while (0)
+#define sched_info_switch(t, next)	do { } while (0)
+#endif /* CONFIG_SCHEDSTATS */
+
 /*
  * Adding/removing a task to/from a priority array:
  */
@@ -315,6 +710,7 @@ static void dequeue_task(struct task_struct *p, prio_array_t *array)
 
 static void enqueue_task(struct task_struct *p, prio_array_t *array)
 {
+	sched_info_queued(p);
 	list_add_tail(&p->run_list, array->queue + p->prio);
 	__set_bit(p->prio, array->bitmap);
 	array->nr_active++;
@@ -358,7 +754,7 @@ static int effective_prio(task_t *p)
 	bonus = CURRENT_BONUS(p) - MAX_BONUS / 2;
 
 	prio = p->static_prio - bonus;
-	if (__vx_task_flags(p, VXF_SCHED_PRIO, 0))
+	if (task_vx_flags(p, VXF_SCHED_PRIO, 0))
 		prio += effective_vavavoom(p, MAX_USER_PRIO);
 
 	if (prio < MAX_RT_PRIO)
@@ -406,7 +802,7 @@ static void recalc_task_prio(task_t *p, unsigned long long now)
 		if (p->mm && p->activated != -1 &&
 			sleep_time > INTERACTIVE_SLEEP(p)) {
 				p->sleep_avg = JIFFIES_TO_NS(MAX_SLEEP_AVG -
-						AVG_TIMESLICE);
+						DEF_TIMESLICE);
 				if (!HIGH_CREDIT(p))
 					p->interactive_credit++;
 		} else {
@@ -506,21 +902,29 @@ static void activate_task(task_t *p, runqueue_t *rq, int local)
 	}
 	p->timestamp = now;
 
+	vx_activate_task(p);
 	__activate_task(p, rq);
 }
 
 /*
  * deactivate_task - remove a task from the runqueue.
  */
-static void deactivate_task(struct task_struct *p, runqueue_t *rq)
+static void __deactivate_task(struct task_struct *p, runqueue_t *rq)
 {
 	rq->nr_running--;
 	if (p->state == TASK_UNINTERRUPTIBLE)
 		rq->nr_uninterruptible++;
 	dequeue_task(p, p->array);
+
 	p->array = NULL;
 }
 
+static void deactivate_task(struct task_struct *p, runqueue_t *rq)
+{
+	__deactivate_task(p, rq);
+	vx_deactivate_task(p);
+}
+
 /*
  * resched_task - mark a task 'to be rescheduled now'.
  *
@@ -533,7 +937,8 @@ static void resched_task(task_t *p)
 {
 	int need_resched, nrpolling;
 
-	preempt_disable();
+	BUG_ON(!spin_is_locked(&task_rq(p)->lock));
+
 	/* minimise the chance of sending an interrupt to poll_idle() */
 	nrpolling = test_tsk_thread_flag(p,TIF_POLLING_NRFLAG);
 	need_resched = test_and_set_tsk_thread_flag(p,TIF_NEED_RESCHED);
@@ -541,7 +946,6 @@ static void resched_task(task_t *p)
 
 	if (!need_resched && !nrpolling && (task_cpu(p) != smp_processor_id()))
 		smp_send_reschedule(task_cpu(p));
-	preempt_enable();
 }
 #else
 static inline void resched_task(task_t *p)
@@ -747,6 +1151,7 @@ static int try_to_wake_up(task_t * p, unsigned int state, int sync)
 #endif
 
 	rq = task_rq_lock(p, &flags);
+	schedstat_inc(rq, ttwu_cnt);
 	old_state = p->state;
 	if (!(old_state & state))
 		goto out;
@@ -794,23 +1199,35 @@ static int try_to_wake_up(task_t * p, unsigned int state, int sync)
 		 */
 		imbalance = sd->imbalance_pct + (sd->imbalance_pct - 100) / 2;
 
-		if ( ((sd->flags & SD_WAKE_AFFINE) &&
-				!task_hot(p, rq->timestamp_last_tick, sd))
-			|| ((sd->flags & SD_WAKE_BALANCE) &&
-				imbalance*this_load <= 100*load) ) {
+		if ((sd->flags & SD_WAKE_AFFINE) &&
+				!task_hot(p, rq->timestamp_last_tick, sd)) {
+			/*
+			 * This domain has SD_WAKE_AFFINE and p is cache cold
+			 * in this domain.
+			 */
+			if (cpu_isset(cpu, sd->span)) {
+				schedstat_inc(sd, ttwu_wake_affine);
+				goto out_set_cpu;
+			}
+		} else if ((sd->flags & SD_WAKE_BALANCE) &&
+				imbalance*this_load <= 100*load) {
 			/*
-			 * Now sd has SD_WAKE_AFFINE and p is cache cold in sd
-			 * or sd has SD_WAKE_BALANCE and there is an imbalance
+			 * This domain has SD_WAKE_BALANCE and there is
+			 * an imbalance.
 			 */
-			if (cpu_isset(cpu, sd->span))
+			if (cpu_isset(cpu, sd->span)) {
+				schedstat_inc(sd, ttwu_wake_balance);
 				goto out_set_cpu;
+			}
 		}
 	}
 
 	new_cpu = cpu; /* Could not wake to this_cpu. Wake to cpu instead */
 out_set_cpu:
+	schedstat_inc(rq, ttwu_attempts);
 	new_cpu = wake_idle(new_cpu, p);
 	if (new_cpu != cpu && cpu_isset(new_cpu, p->cpus_allowed)) {
+		schedstat_inc(rq, ttwu_moved);
 		set_task_cpu(p, new_cpu);
 		task_rq_unlock(rq, &flags);
 		/* might preempt at this point */
@@ -861,7 +1278,7 @@ out:
 
 int fastcall wake_up_process(task_t * p)
 {
-	return try_to_wake_up(p, TASK_STOPPED |
+	return try_to_wake_up(p, TASK_STOPPED | TASK_TRACED |
 		       		 TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE, 0);
 }
 
@@ -872,6 +1289,11 @@ int fastcall wake_up_state(task_t *p, unsigned int state)
 	return try_to_wake_up(p, state, 0);
 }
 
+#ifdef CONFIG_SMP
+static int find_idlest_cpu(struct task_struct *p, int this_cpu,
+			   struct sched_domain *sd);
+#endif
+
 /*
  * Perform scheduler related setup for a newly forked process p.
  * p is forked by current.
@@ -888,6 +1310,9 @@ void fastcall sched_fork(task_t *p)
 	INIT_LIST_HEAD(&p->run_list);
 	p->array = NULL;
 	spin_lock_init(&p->switch_lock);
+#ifdef CONFIG_SCHEDSTATS
+	memset(&p->sched_info, 0, sizeof(p->sched_info));
+#endif
 #ifdef CONFIG_PREEMPT
 	/*
 	 * During context-switch we hold precisely one spinlock, which
@@ -911,7 +1336,7 @@ void fastcall sched_fork(task_t *p)
 	p->first_time_slice = 1;
 	current->time_slice >>= 1;
 	p->timestamp = sched_clock();
-	if (!current->time_slice) {
+	if (unlikely(!current->time_slice)) {
 		/*
 		 * This case is rare, it happens when the parent has only
 		 * a single jiffy left from its timeslice. Taking the
@@ -927,44 +1352,90 @@ void fastcall sched_fork(task_t *p)
 }
 
 /*
- * wake_up_forked_process - wake up a freshly forked process.
+ * wake_up_new_task - wake up a newly created task for the first time.
  *
  * This function will do some initial scheduler statistics housekeeping
- * that must be done for every newly created process.
+ * that must be done for every newly created context, then puts the task
+ * on the runqueue and wakes it.
  */
-void fastcall wake_up_forked_process(task_t * p)
+void fastcall wake_up_new_task(task_t * p, unsigned long clone_flags)
 {
 	unsigned long flags;
-	runqueue_t *rq = task_rq_lock(current, &flags);
+	int this_cpu, cpu;
+	runqueue_t *rq, *this_rq;
+
+	rq = task_rq_lock(p, &flags);
+	cpu = task_cpu(p);
+	this_cpu = smp_processor_id();
 
 	BUG_ON(p->state != TASK_RUNNING);
 
+	schedstat_inc(rq, wunt_cnt);
 	/*
 	 * We decrease the sleep average of forking parents
 	 * and children as well, to keep max-interactive tasks
-	 * from forking tasks that are max-interactive.
+	 * from forking tasks that are max-interactive. The parent
+	 * (current) is done further down, under its lock.
 	 */
-	current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) *
-		PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
-
 	p->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(p) *
 		CHILD_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
 
 	p->interactive_credit = 0;
 
 	p->prio = effective_prio(p);
-	set_task_cpu(p, smp_processor_id());
 
-	if (unlikely(!current->array))
+	vx_activate_task(p);
+	if (likely(cpu == this_cpu)) {
+		if (!(clone_flags & CLONE_VM)) {
+			/*
+			 * The VM isn't cloned, so we're in a good position to
+			 * do child-runs-first in anticipation of an exec. This
+			 * usually avoids a lot of COW overhead.
+			 */
+			if (unlikely(!current->array))
+				__activate_task(p, rq);
+			else {
+				p->prio = current->prio;
+				list_add_tail(&p->run_list, &current->run_list);
+				p->array = current->array;
+				p->array->nr_active++;
+				rq->nr_running++;
+			}
+			set_need_resched();
+		} else
+			/* Run child last */
+			__activate_task(p, rq);
+		/*
+		 * We skip the following code due to cpu == this_cpu
+	 	 *
+		 *   task_rq_unlock(rq, &flags);
+		 *   this_rq = task_rq_lock(current, &flags);
+		 */
+		this_rq = rq;
+	} else {
+		this_rq = cpu_rq(this_cpu);
+
+		/*
+		 * Not the local CPU - must adjust timestamp. This should
+		 * get optimised away in the !CONFIG_SMP case.
+		 */
+		p->timestamp = (p->timestamp - this_rq->timestamp_last_tick)
+					+ rq->timestamp_last_tick;
 		__activate_task(p, rq);
-	else {
-		p->prio = current->prio;
-		list_add_tail(&p->run_list, &current->run_list);
-		p->array = current->array;
-		p->array->nr_active++;
-		rq->nr_running++;
+		if (TASK_PREEMPTS_CURR(p, rq))
+			resched_task(rq->curr);
+
+		schedstat_inc(rq, wunt_moved);
+		/*
+		 * Parent and child are on different CPUs, now get the
+		 * parent runqueue to update the parent's ->sleep_avg:
+		 */
+		task_rq_unlock(rq, &flags);
+		this_rq = task_rq_lock(current, &flags);
 	}
-	task_rq_unlock(rq, &flags);
+	current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) *
+		PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
+	task_rq_unlock(this_rq, &flags);
 }
 
 /*
@@ -981,18 +1452,16 @@ void fastcall sched_exit(task_t * p)
 	unsigned long flags;
 	runqueue_t *rq;
 
-	local_irq_save(flags);
-	if (p->first_time_slice) {
-		p->parent->time_slice += p->time_slice;
-		if (unlikely(p->parent->time_slice > MAX_TIMESLICE))
-			p->parent->time_slice = MAX_TIMESLICE;
-	}
-	local_irq_restore(flags);
 	/*
 	 * If the child was a (relative-) CPU hog then decrease
 	 * the sleep_avg of the parent as well.
 	 */
 	rq = task_rq_lock(p->parent, &flags);
+	if (p->first_time_slice) {
+		p->parent->time_slice += p->time_slice;
+		if (unlikely(p->parent->time_slice > task_timeslice(p)))
+			p->parent->time_slice = task_timeslice(p);
+	}
 	if (p->sleep_avg < p->parent->sleep_avg)
 		p->parent->sleep_avg = p->parent->sleep_avg /
 		(EXIT_WEIGHT + 1) * EXIT_WEIGHT + p->sleep_avg /
@@ -1092,7 +1561,7 @@ unsigned long nr_running(void)
 {
 	unsigned long i, sum = 0;
 
-	for_each_cpu(i)
+	for_each_online_cpu(i)
 		sum += cpu_rq(i)->nr_running;
 
 	return sum;
@@ -1128,6 +1597,8 @@ unsigned long nr_iowait(void)
 	return sum;
 }
 
+#ifdef CONFIG_SMP
+
 /*
  * double_rq_lock - safely lock two runqueues
  *
@@ -1162,14 +1633,20 @@ static void double_rq_unlock(runqueue_t *rq1, runqueue_t *rq2)
 		spin_unlock(&rq2->lock);
 }
 
-enum idle_type
+/*
+ * double_lock_balance - lock the busiest runqueue, this_rq is locked already.
+ */
+static void double_lock_balance(runqueue_t *this_rq, runqueue_t *busiest)
 {
-	IDLE,
-	NOT_IDLE,
-	NEWLY_IDLE,
-};
-
-#ifdef CONFIG_SMP
+	if (unlikely(!spin_trylock(&busiest->lock))) {
+		if (busiest < this_rq) {
+			spin_unlock(&this_rq->lock);
+			spin_lock(&busiest->lock);
+			spin_lock(&this_rq->lock);
+		} else
+			spin_lock(&busiest->lock);
+	}
+}
 
 /*
  * find_idlest_cpu - find the least busy runqueue.
@@ -1217,89 +1694,6 @@ static int find_idlest_cpu(struct task_struct *p, int this_cpu,
 	return this_cpu;
 }
 
-/*
- * wake_up_forked_thread - wake up a freshly forked thread.
- *
- * This function will do some initial scheduler statistics housekeeping
- * that must be done for every newly created context, and it also does
- * runqueue balancing.
- */
-void fastcall wake_up_forked_thread(task_t * p)
-{
-	unsigned long flags;
-	int this_cpu = get_cpu(), cpu;
-	struct sched_domain *tmp, *sd = NULL;
-	runqueue_t *this_rq = cpu_rq(this_cpu), *rq;
-
-	/*
-	 * Find the largest domain that this CPU is part of that
-	 * is willing to balance on clone:
-	 */
-	for_each_domain(this_cpu, tmp)
-		if (tmp->flags & SD_BALANCE_CLONE)
-			sd = tmp;
-	if (sd)
-		cpu = find_idlest_cpu(p, this_cpu, sd);
-	else
-		cpu = this_cpu;
-
-	local_irq_save(flags);
-lock_again:
-	rq = cpu_rq(cpu);
-	double_rq_lock(this_rq, rq);
-
-	BUG_ON(p->state != TASK_RUNNING);
-
-	/*
-	 * We did find_idlest_cpu() unlocked, so in theory
-	 * the mask could have changed - just dont migrate
-	 * in this case:
-	 */
-	if (unlikely(!cpu_isset(cpu, p->cpus_allowed))) {
-		cpu = this_cpu;
-		double_rq_unlock(this_rq, rq);
-		goto lock_again;
-	}
-	/*
-	 * We decrease the sleep average of forking parents
-	 * and children as well, to keep max-interactive tasks
-	 * from forking tasks that are max-interactive.
-	 */
-	current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) *
-		PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
-
-	p->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(p) *
-		CHILD_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
-
-	p->interactive_credit = 0;
-
-	p->prio = effective_prio(p);
-	set_task_cpu(p, cpu);
-
-	if (cpu == this_cpu) {
-		if (unlikely(!current->array))
-			__activate_task(p, rq);
-		else {
-			p->prio = current->prio;
-			list_add_tail(&p->run_list, &current->run_list);
-			p->array = current->array;
-			p->array->nr_active++;
-			rq->nr_running++;
-		}
-	} else {
-		/* Not the local CPU - must adjust timestamp */
-		p->timestamp = (p->timestamp - this_rq->timestamp_last_tick)
-					+ rq->timestamp_last_tick;
-		__activate_task(p, rq);
-		if (TASK_PREEMPTS_CURR(p, rq))
-			resched_task(rq->curr);
-	}
-
-	double_rq_unlock(this_rq, rq);
-	local_irq_restore(flags);
-	put_cpu();
-}
-
 /*
  * If dest_cpu is allowed for this process, migrate the task to it.
  * This is accomplished by forcing the cpu_allowed mask to only
@@ -1317,6 +1711,7 @@ static void sched_migrate_task(task_t *p, int dest_cpu)
 	    || unlikely(cpu_is_offline(dest_cpu)))
 		goto out;
 
+	schedstat_inc(rq, smt_cnt);
 	/* force the process onto the specified CPU */
 	if (migrate_task(p, dest_cpu, &req)) {
 		/* Need to wait for migration thread (might exit: take ref). */
@@ -1333,17 +1728,18 @@ out:
 }
 
 /*
- * sched_balance_exec(): find the highest-level, exec-balance-capable
+ * sched_exec(): find the highest-level, exec-balance-capable
  * domain and try to migrate the task to the least loaded CPU.
  *
  * execve() is a valuable balancing opportunity, because at this point
  * the task has the smallest effective memory and cache footprint.
  */
-void sched_balance_exec(void)
+void sched_exec(void)
 {
 	struct sched_domain *tmp, *sd = NULL;
 	int new_cpu, this_cpu = get_cpu();
 
+	schedstat_inc(this_rq(), sbe_cnt);
 	/* Prefer the current CPU if there's only this task running */
 	if (this_rq()->nr_running <= 1)
 		goto out;
@@ -1353,8 +1749,10 @@ void sched_balance_exec(void)
 			sd = tmp;
 
 	if (sd) {
+		schedstat_inc(sd, sbe_attempts);
 		new_cpu = find_idlest_cpu(current, this_cpu, sd);
 		if (new_cpu != this_cpu) {
+			schedstat_inc(sd, sbe_pushed);
 			put_cpu();
 			sched_migrate_task(current, new_cpu);
 			return;
@@ -1364,21 +1762,6 @@ out:
 	put_cpu();
 }
 
-/*
- * double_lock_balance - lock the busiest runqueue, this_rq is locked already.
- */
-static void double_lock_balance(runqueue_t *this_rq, runqueue_t *busiest)
-{
-	if (unlikely(!spin_trylock(&busiest->lock))) {
-		if (busiest < this_rq) {
-			spin_unlock(&this_rq->lock);
-			spin_lock(&busiest->lock);
-			spin_lock(&this_rq->lock);
-		} else
-			spin_lock(&busiest->lock);
-	}
-}
-
 /*
  * pull_task - move a task from a remote runqueue to the local runqueue.
  * Both runqueues must be locked.
@@ -1493,6 +1876,15 @@ skip_queue:
 		idx++;
 		goto skip_bitmap;
 	}
+
+	/*
+	 * Right now, this is the only place pull_task() is called,
+	 * so we can safely collect pull_task() stats here rather than
+	 * inside pull_task().
+	 */
+	schedstat_inc(this_rq, pt_gained[idle]);
+	schedstat_inc(busiest, pt_lost[idle]);
+
 	pull_task(busiest, array, tmp, this_rq, dst_array, this_cpu);
 	pulled++;
 
@@ -1687,14 +2079,20 @@ static int load_balance(int this_cpu, runqueue_t *this_rq,
 	int nr_moved;
 
 	spin_lock(&this_rq->lock);
+	schedstat_inc(sd, lb_cnt[idle]);
 
 	group = find_busiest_group(sd, this_cpu, &imbalance, idle);
-	if (!group)
+	if (!group) {
+		schedstat_inc(sd, lb_nobusyg[idle]);
 		goto out_balanced;
+	}
 
 	busiest = find_busiest_queue(group);
-	if (!busiest)
+	if (!busiest) {
+		schedstat_inc(sd, lb_nobusyq[idle]);
 		goto out_balanced;
+	}
+
 	/*
 	 * This should be "impossible", but since load
 	 * balancing is inherently racy and statistical,
@@ -1705,6 +2103,8 @@ static int load_balance(int this_cpu, runqueue_t *this_rq,
 		goto out_balanced;
 	}
 
+	schedstat_add(sd, lb_imbalance[idle], imbalance);
+
 	nr_moved = 0;
 	if (busiest->nr_running > 1) {
 		/*
@@ -1721,6 +2121,7 @@ static int load_balance(int this_cpu, runqueue_t *this_rq,
 	spin_unlock(&this_rq->lock);
 
 	if (!nr_moved) {
+		schedstat_inc(sd, lb_failed[idle]);
 		sd->nr_balance_failed++;
 
 		if (unlikely(sd->nr_balance_failed > sd->cache_nice_tries+2)) {
@@ -1775,19 +2176,27 @@ static int load_balance_newidle(int this_cpu, runqueue_t *this_rq,
 	unsigned long imbalance;
 	int nr_moved = 0;
 
+	schedstat_inc(sd, lb_cnt[NEWLY_IDLE]);
 	group = find_busiest_group(sd, this_cpu, &imbalance, NEWLY_IDLE);
-	if (!group)
+	if (!group) {
+		schedstat_inc(sd, lb_nobusyg[NEWLY_IDLE]);
 		goto out;
+	}
 
 	busiest = find_busiest_queue(group);
-	if (!busiest || busiest == this_rq)
+	if (!busiest || busiest == this_rq) {
+		schedstat_inc(sd, lb_nobusyq[NEWLY_IDLE]);
 		goto out;
+	}
 
 	/* Attempt to move tasks */
 	double_lock_balance(this_rq, busiest);
 
+	schedstat_add(sd, lb_imbalance[NEWLY_IDLE], imbalance);
 	nr_moved = move_tasks(this_rq, this_cpu, busiest,
 					imbalance, sd, NEWLY_IDLE);
+	if (!nr_moved)
+		schedstat_inc(sd, lb_failed[NEWLY_IDLE]);
 
 	spin_unlock(&busiest->lock);
 
@@ -1827,40 +2236,39 @@ static void active_load_balance(runqueue_t *busiest, int busiest_cpu)
 	struct sched_group *group, *busy_group;
 	int i;
 
+	schedstat_inc(busiest, alb_cnt);
 	if (busiest->nr_running <= 1)
 		return;
 
 	for_each_domain(busiest_cpu, sd)
 		if (cpu_isset(busiest->push_cpu, sd->span))
 			break;
-	if (!sd) {
-		WARN_ON(1);
+	if (!sd)
 		return;
-	}
 
- 	group = sd->groups;
+	group = sd->groups;
 	while (!cpu_isset(busiest_cpu, group->cpumask))
- 		group = group->next;
- 	busy_group = group;
+		group = group->next;
+	busy_group = group;
 
- 	group = sd->groups;
- 	do {
+	group = sd->groups;
+	do {
 		cpumask_t tmp;
 		runqueue_t *rq;
 		int push_cpu = 0;
 
- 		if (group == busy_group)
- 			goto next_group;
+		if (group == busy_group)
+			goto next_group;
 
 		cpus_and(tmp, group->cpumask, cpu_online_map);
 		if (!cpus_weight(tmp))
 			goto next_group;
 
- 		for_each_cpu_mask(i, tmp) {
+		for_each_cpu_mask(i, tmp) {
 			if (!idle_cpu(i))
 				goto next_group;
- 			push_cpu = i;
- 		}
+			push_cpu = i;
+		}
 
 		rq = cpu_rq(push_cpu);
 
@@ -1873,7 +2281,12 @@ static void active_load_balance(runqueue_t *busiest, int busiest_cpu)
 		if (unlikely(busiest == rq))
 			goto next_group;
 		double_lock_balance(busiest, rq);
-		move_tasks(rq, push_cpu, busiest, 1, sd, IDLE);
+		if (move_tasks(rq, push_cpu, busiest, 1, sd, IDLE)) {
+			schedstat_inc(busiest, alb_lost);
+			schedstat_inc(rq, alb_gained);
+		} else {
+			schedstat_inc(busiest, alb_failed);
+		}
 		spin_unlock(&rq->lock);
 next_group:
 		group = group->next;
@@ -1945,17 +2358,20 @@ static inline void idle_balance(int cpu, runqueue_t *rq)
 
 static inline int wake_priority_sleeper(runqueue_t *rq)
 {
+	int ret = 0;
 #ifdef CONFIG_SCHED_SMT
+	spin_lock(&rq->lock);
 	/*
 	 * If an SMT sibling task has been put to sleep for priority
 	 * reasons reschedule the idle task to see if it can now run.
 	 */
 	if (rq->nr_running) {
 		resched_task(rq->idle);
-		return 1;
+		ret = 1;
 	}
+	spin_unlock(&rq->lock);
 #endif
-	return 0;
+	return ret;
 }
 
 DEFINE_PER_CPU(struct kernel_stat, kstat);
@@ -1991,12 +2407,18 @@ void scheduler_tick(int user_ticks, int sys_ticks)
 	struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
 	runqueue_t *rq = this_rq();
 	task_t *p = current;
+	struct vx_info *vxi = p->vx_info;
 
 	rq->timestamp_last_tick = sched_clock();
 
 	if (rcu_pending(cpu))
 		rcu_check_callbacks(cpu, user_ticks);
 
+	if (vxi) {
+		vxi->sched.cpu[cpu].user_ticks += user_ticks;
+		vxi->sched.cpu[cpu].sys_ticks += sys_ticks;
+	}
+
 	/* note: this timer irq context must be accounted for as well */
 	if (hardirq_count() - HARDIRQ_OFFSET) {
 		cpustat->irq += sys_ticks;
@@ -2007,15 +2429,20 @@ void scheduler_tick(int user_ticks, int sys_ticks)
 	}
 
 	if (p == rq->idle) {
-		if (!--rq->idle_tokens && !list_empty(&rq->hold_queue))
-			set_need_resched();	
-
 		if (atomic_read(&rq->nr_iowait) > 0)
 			cpustat->iowait += sys_ticks;
+			// vx_cpustat_acc(vxi, iowait, cpu, cpustat, sys_ticks);
 		else
 			cpustat->idle += sys_ticks;
+			// vx_cpustat_acc(vxi, idle, cpu, cpustat, sys_ticks);
+
 		if (wake_priority_sleeper(rq))
 			goto out;
+
+#ifdef CONFIG_VSERVER_HARDCPU_IDLE
+		if (!--rq->idle_tokens && !list_empty(&rq->hold_queue))
+			set_need_resched();
+#endif
 		rebalance_tick(cpu, rq, IDLE);
 		return;
 	}
@@ -2038,7 +2465,7 @@ void scheduler_tick(int user_ticks, int sys_ticks)
 	 * timeslice. This makes it possible for interactive tasks
 	 * to use up their timeslices at their highest priority levels.
 	 */
-	if (unlikely(rt_task(p))) {
+	if (rt_task(p)) {
 		/*
 		 * RR tasks need a special form of timeslice management.
 		 * FIFO tasks have no timeslices.
@@ -2104,23 +2531,34 @@ out:
 }
 
 #ifdef CONFIG_SCHED_SMT
-static inline void wake_sleeping_dependent(int cpu, runqueue_t *rq)
+static inline void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq)
 {
-	int i;
-	struct sched_domain *sd = rq->sd;
+	struct sched_domain *sd = this_rq->sd;
 	cpumask_t sibling_map;
+	int i;
 
 	if (!(sd->flags & SD_SHARE_CPUPOWER))
 		return;
 
+	/*
+	 * Unlock the current runqueue because we have to lock in
+	 * CPU order to avoid deadlocks. Caller knows that we might
+	 * unlock. We keep IRQs disabled.
+	 */
+	spin_unlock(&this_rq->lock);
+
 	cpus_and(sibling_map, sd->span, cpu_online_map);
-	for_each_cpu_mask(i, sibling_map) {
-		runqueue_t *smt_rq;
 
-		if (i == cpu)
-			continue;
+	for_each_cpu_mask(i, sibling_map)
+		spin_lock(&cpu_rq(i)->lock);
+	/*
+	 * We clear this CPU from the mask. This both simplifies the
+	 * inner loop and keps this_rq locked when we exit:
+	 */
+	cpu_clear(this_cpu, sibling_map);
 
-		smt_rq = cpu_rq(i);
+	for_each_cpu_mask(i, sibling_map) {
+		runqueue_t *smt_rq = cpu_rq(i);
 
 		/*
 		 * If an SMT sibling task is sleeping due to priority
@@ -2129,27 +2567,53 @@ static inline void wake_sleeping_dependent(int cpu, runqueue_t *rq)
 		if (smt_rq->curr == smt_rq->idle && smt_rq->nr_running)
 			resched_task(smt_rq->idle);
 	}
+
+	for_each_cpu_mask(i, sibling_map)
+		spin_unlock(&cpu_rq(i)->lock);
+	/*
+	 * We exit with this_cpu's rq still held and IRQs
+	 * still disabled:
+	 */
 }
 
-static inline int dependent_sleeper(int cpu, runqueue_t *rq, task_t *p)
+static inline int dependent_sleeper(int this_cpu, runqueue_t *this_rq)
 {
-	struct sched_domain *sd = rq->sd;
+	struct sched_domain *sd = this_rq->sd;
 	cpumask_t sibling_map;
+	prio_array_t *array;
 	int ret = 0, i;
+	task_t *p;
 
 	if (!(sd->flags & SD_SHARE_CPUPOWER))
 		return 0;
 
+	/*
+	 * The same locking rules and details apply as for
+	 * wake_sleeping_dependent():
+	 */
+	spin_unlock(&this_rq->lock);
 	cpus_and(sibling_map, sd->span, cpu_online_map);
-	for_each_cpu_mask(i, sibling_map) {
-		runqueue_t *smt_rq;
-		task_t *smt_curr;
+	for_each_cpu_mask(i, sibling_map)
+		spin_lock(&cpu_rq(i)->lock);
+	cpu_clear(this_cpu, sibling_map);
 
-		if (i == cpu)
-			continue;
+	/*
+	 * Establish next task to be run - it might have gone away because
+	 * we released the runqueue lock above:
+	 */
+	if (!this_rq->nr_running)
+		goto out_unlock;
+	array = this_rq->active;
+	if (!array->nr_active)
+		array = this_rq->expired;
+	BUG_ON(!array->nr_active);
+
+	p = list_entry(array->queue[sched_find_first_bit(array->bitmap)].next,
+		task_t, run_list);
 
-		smt_rq = cpu_rq(i);
-		smt_curr = smt_rq->curr;
+	for_each_cpu_mask(i, sibling_map) {
+		runqueue_t *smt_rq = cpu_rq(i);
+		task_t *smt_curr = smt_rq->curr;
 
 		/*
 		 * If a user task with lower static priority than the
@@ -2175,14 +2639,17 @@ static inline int dependent_sleeper(int cpu, runqueue_t *rq, task_t *p)
 			(smt_curr == smt_rq->idle && smt_rq->nr_running))
 				resched_task(smt_curr);
 	}
+out_unlock:
+	for_each_cpu_mask(i, sibling_map)
+		spin_unlock(&cpu_rq(i)->lock);
 	return ret;
 }
 #else
-static inline void wake_sleeping_dependent(int cpu, runqueue_t *rq)
+static inline void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq)
 {
 }
 
-static inline int dependent_sleeper(int cpu, runqueue_t *rq, task_t *p)
+static inline int dependent_sleeper(int this_cpu, runqueue_t *this_rq)
 {
 	return 0;
 }
@@ -2200,7 +2667,7 @@ asmlinkage void __sched schedule(void)
 	struct list_head *queue;
 	unsigned long long now;
 	unsigned long run_time;
-#ifdef	CONFIG_VSERVER_HARDCPU		
+#ifdef	CONFIG_VSERVER_HARDCPU
 	struct vx_info *vxi;
 	int maxidle = -HZ;
 #endif
@@ -2223,7 +2690,17 @@ need_resched:
 	prev = current;
 	rq = this_rq();
 
+	/*
+	 * The idle thread is not allowed to schedule!
+	 * Remove this check after it has been exercised a bit.
+	 */
+	if (unlikely(current == rq->idle) && current->state != TASK_RUNNING) {
+		printk(KERN_ERR "bad: scheduling from the idle thread!\n");
+		dump_stack();
+	}
+
 	release_kernel_lock(prev);
+	schedstat_inc(rq, sched_cnt);
 	now = sched_clock();
 	if (likely(now - prev->timestamp < NS_MAX_SLEEP_AVG))
 		run_time = now - prev->timestamp;
@@ -2254,7 +2731,7 @@ need_resched:
 			deactivate_task(prev, rq);
 	}
 
-#ifdef	CONFIG_VSERVER_HARDCPU		
+#ifdef CONFIG_VSERVER_HARDCPU
 	if (!list_empty(&rq->hold_queue)) {
 		struct list_head *l, *n;
 		int ret;
@@ -2272,28 +2749,56 @@ need_resched:
 			if (ret > 0) {
 				list_del(&next->run_list);
 				next->state &= ~TASK_ONHOLD;
-				recalc_task_prio(next, now);
-				__activate_task(next, rq);
-				// printk("··· unhold %p\n", next);
+				// one less waiting
+				vx_onhold_dec(vxi);
+				array = rq->expired;
+				next->prio = MAX_PRIO-1;
+				enqueue_task(next, array);
+				rq->nr_running++;
+				if (next->static_prio < rq->best_expired_prio)
+					rq->best_expired_prio = next->static_prio;
+
+				// printk("··· %8lu unhold %p [%d]\n", jiffies, next, next->prio);
 				break;
 			}
 			if ((ret < 0) && (maxidle < ret))
 				maxidle = ret;
-		}	
+		}
 	}
 	rq->idle_tokens = -maxidle;
 
 pick_next:
 #endif
+
 	cpu = smp_processor_id();
 	if (unlikely(!rq->nr_running)) {
+go_idle:
 		idle_balance(cpu, rq);
 		if (!rq->nr_running) {
 			next = rq->idle;
 			rq->expired_timestamp = 0;
 			wake_sleeping_dependent(cpu, rq);
+			/*
+			 * wake_sleeping_dependent() might have released
+			 * the runqueue, so break out if we got new
+			 * tasks meanwhile:
+			 */
+			if (!rq->nr_running)
+				goto switch_tasks;
+		}
+	} else {
+		if (dependent_sleeper(cpu, rq)) {
+			schedstat_inc(rq, sched_goidle);
+			next = rq->idle;
 			goto switch_tasks;
 		}
+		/*
+		 * dependent_sleeper() releases and reacquires the runqueue
+		 * lock, hence go into the idle loop if the rq went
+		 * empty meanwhile:
+		 */
+		if (unlikely(!rq->nr_running))
+			goto go_idle;
 	}
 
 	array = rq->active;
@@ -2301,34 +2806,34 @@ pick_next:
 		/*
 		 * Switch the active and expired arrays.
 		 */
+		schedstat_inc(rq, sched_switch);
 		rq->active = rq->expired;
 		rq->expired = array;
 		array = rq->active;
 		rq->expired_timestamp = 0;
 		rq->best_expired_prio = MAX_PRIO;
-	}
+	} else
+		schedstat_inc(rq, sched_noswitch);
 
 	idx = sched_find_first_bit(array->bitmap);
 	queue = array->queue + idx;
 	next = list_entry(queue->next, task_t, run_list);
 
-	if (dependent_sleeper(cpu, rq, next)) {
-		next = rq->idle;
-		goto switch_tasks;
-	}
-
-#ifdef	CONFIG_VSERVER_HARDCPU		
+#ifdef	CONFIG_VSERVER_HARDCPU
 	vxi = next->vx_info;
-	if (vxi && __vx_flags(vxi->vx_flags,
-		VXF_SCHED_PAUSE|VXF_SCHED_HARD, 0)) {
+	if (vx_info_flags(vxi, VXF_SCHED_PAUSE|VXF_SCHED_HARD, 0)) {
 		int ret = vx_tokens_recalc(vxi);
 
 		if (unlikely(ret <= 0)) {
 			if (ret && (rq->idle_tokens > -ret))
 				rq->idle_tokens = -ret;
-			deactivate_task(next, rq);
+			__deactivate_task(next, rq);
+			recalc_task_prio(next, now);
+			// a new one on hold
+			vx_onhold_inc(vxi);
+			next->state |= TASK_ONHOLD;
 			list_add_tail(&next->run_list, &rq->hold_queue);
-			next->state |= TASK_ONHOLD;			
+			//printk("··· %8lu hold   %p [%d]\n", jiffies, next, next->prio);
 			goto pick_next;
 		}
 	}
@@ -2349,7 +2854,7 @@ pick_next:
 switch_tasks:
 	prefetch(next);
 	clear_tsk_need_resched(prev);
-	RCU_qsctr(task_cpu(prev))++;
+	rcu_qsctr_inc(task_cpu(prev));
 
 	prev->sleep_avg -= run_time;
 	if ((long)prev->sleep_avg <= 0) {
@@ -2357,8 +2862,9 @@ switch_tasks:
 		if (!(HIGH_CREDIT(prev) || LOW_CREDIT(prev)))
 			prev->interactive_credit--;
 	}
-	prev->timestamp = now;
+	prev->timestamp = prev->last_ran = now;
 
+	sched_info_switch(prev, next);
 	if (likely(prev != next)) {
 		next->timestamp = now;
 		rq->nr_switches++;
@@ -2375,7 +2881,7 @@ switch_tasks:
 
 	reacquire_kernel_lock(current);
 	preempt_enable_no_resched();
-	if (test_thread_flag(TIF_NEED_RESCHED))
+	if (unlikely(test_thread_flag(TIF_NEED_RESCHED)))
 		goto need_resched;
 }
 
@@ -2688,6 +3194,8 @@ asmlinkage long sys_nice(int increment)
 	 * and we have a single winner.
 	 */
 	if (increment < 0) {
+		if (vx_flags(VXF_IGNEG_NICE, 0))
+			return 0;
 		if (!capable(CAP_SYS_NICE))
 			return -EPERM;
 		if (increment < -40)
@@ -2813,6 +3321,7 @@ static int setscheduler(pid_t pid, int policy, struct sched_param __user *param)
 				policy != SCHED_NORMAL)
 			goto out_unlock;
 	}
+	profile_hit(SCHED_PROFILING, __builtin_return_address(0));
 
 	/*
 	 * Valid priorities for SCHED_FIFO and SCHED_RR are
@@ -2843,6 +3352,7 @@ static int setscheduler(pid_t pid, int policy, struct sched_param __user *param)
 	oldprio = p->prio;
 	__setscheduler(p, policy, lp.sched_priority);
 	if (array) {
+		vx_activate_task(p);
 		__activate_task(p, task_rq(p));
 		/*
 		 * Reschedule if we are currently running on this runqueue and
@@ -2953,24 +3463,10 @@ out_unlock:
 	return retval;
 }
 
-/**
- * sys_sched_setaffinity - set the cpu affinity of a process
- * @pid: pid of the process
- * @len: length in bytes of the bitmask pointed to by user_mask_ptr
- * @user_mask_ptr: user-space pointer to the new cpu mask
- */
-asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len,
-				      unsigned long __user *user_mask_ptr)
+long sched_setaffinity(pid_t pid, cpumask_t new_mask)
 {
-	cpumask_t new_mask;
-	int retval;
 	task_t *p;
-
-	if (len < sizeof(new_mask))
-		return -EINVAL;
-
-	if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask)))
-		return -EFAULT;
+	int retval;
 
 	lock_cpu_hotplug();
 	read_lock(&tasklist_lock);
@@ -3003,6 +3499,36 @@ out_unlock:
 	return retval;
 }
 
+static int get_user_cpu_mask(unsigned long __user *user_mask_ptr, unsigned len,
+			     cpumask_t *new_mask)
+{
+	if (len < sizeof(cpumask_t)) {
+		memset(new_mask, 0, sizeof(cpumask_t));
+	} else if (len > sizeof(cpumask_t)) {
+		len = sizeof(cpumask_t);
+	}
+	return copy_from_user(new_mask, user_mask_ptr, len) ? -EFAULT : 0;
+}
+
+/**
+ * sys_sched_setaffinity - set the cpu affinity of a process
+ * @pid: pid of the process
+ * @len: length in bytes of the bitmask pointed to by user_mask_ptr
+ * @user_mask_ptr: user-space pointer to the new cpu mask
+ */
+asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len,
+				      unsigned long __user *user_mask_ptr)
+{
+	cpumask_t new_mask;
+	int retval;
+
+	retval = get_user_cpu_mask(user_mask_ptr, len, &new_mask);
+	if (retval)
+		return retval;
+
+	return sched_setaffinity(pid, new_mask);
+}
+
 /*
  * Represents all cpu's present in the system
  * In systems capable of hotplug, this map could dynamically grow
@@ -3018,24 +3544,11 @@ cpumask_t cpu_online_map = CPU_MASK_ALL;
 cpumask_t cpu_possible_map = CPU_MASK_ALL;
 #endif
 
-/**
- * sys_sched_getaffinity - get the cpu affinity of a process
- * @pid: pid of the process
- * @len: length in bytes of the bitmask pointed to by user_mask_ptr
- * @user_mask_ptr: user-space pointer to hold the current cpu mask
- */
-asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len,
-				      unsigned long __user *user_mask_ptr)
+long sched_getaffinity(pid_t pid, cpumask_t *mask)
 {
-	unsigned int real_len;
-	cpumask_t mask;
 	int retval;
 	task_t *p;
 
-	real_len = sizeof(mask);
-	if (len < real_len)
-		return -EINVAL;
-
 	lock_cpu_hotplug();
 	read_lock(&tasklist_lock);
 
@@ -3045,16 +3558,40 @@ asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len,
 		goto out_unlock;
 
 	retval = 0;
-	cpus_and(mask, p->cpus_allowed, cpu_possible_map);
+	cpus_and(*mask, p->cpus_allowed, cpu_possible_map);
 
 out_unlock:
 	read_unlock(&tasklist_lock);
 	unlock_cpu_hotplug();
 	if (retval)
 		return retval;
-	if (copy_to_user(user_mask_ptr, &mask, real_len))
+
+	return 0;
+}
+
+/**
+ * sys_sched_getaffinity - get the cpu affinity of a process
+ * @pid: pid of the process
+ * @len: length in bytes of the bitmask pointed to by user_mask_ptr
+ * @user_mask_ptr: user-space pointer to hold the current cpu mask
+ */
+asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len,
+				      unsigned long __user *user_mask_ptr)
+{
+	int ret;
+	cpumask_t mask;
+
+	if (len < sizeof(cpumask_t))
+		return -EINVAL;
+
+	ret = sched_getaffinity(pid, &mask);
+	if (ret < 0)
+		return ret;
+
+	if (copy_to_user(user_mask_ptr, &mask, sizeof(cpumask_t)))
 		return -EFAULT;
-	return real_len;
+
+	return sizeof(cpumask_t);
 }
 
 /**
@@ -3070,6 +3607,7 @@ asmlinkage long sys_sched_yield(void)
 	prio_array_t *array = current->array;
 	prio_array_t *target = rq->expired;
 
+	schedstat_inc(rq, yld_cnt);
 	/*
 	 * We implement yielding by moving the task into the expired
 	 * queue.
@@ -3077,9 +3615,16 @@ asmlinkage long sys_sched_yield(void)
 	 * (special rule: RT tasks will just roundrobin in the active
 	 *  array.)
 	 */
-	if (unlikely(rt_task(current)))
+	if (rt_task(current))
 		target = rq->active;
 
+	if (current->array->nr_active == 1) {
+		schedstat_inc(rq, yld_act_empty);
+		if (!rq->expired->nr_active)
+			schedstat_inc(rq, yld_both_empty);
+	} else if (!rq->expired->nr_active)
+		schedstat_inc(rq, yld_exp_empty);
+
 	dequeue_task(current, array);
 	enqueue_task(current, target);
 
@@ -3253,7 +3798,7 @@ static void show_task(task_t * p)
 	task_t *relative;
 	unsigned state;
 	unsigned long free = 0;
-	static const char *stat_nam[] = { "R", "S", "D", "T", "Z", "W" };
+	static const char *stat_nam[] = { "R", "S", "D", "T", "t", "Z", "X" };
 
 	printk("%-13.13s ", p->comm);
 	state = p->state ? __ffs(p->state) + 1 : 0;
@@ -3330,21 +3875,20 @@ void show_state(void)
 
 void __devinit init_idle(task_t *idle, int cpu)
 {
-	runqueue_t *idle_rq = cpu_rq(cpu), *rq = cpu_rq(task_cpu(idle));
+	runqueue_t *rq = cpu_rq(cpu);
 	unsigned long flags;
 
-	local_irq_save(flags);
-	double_rq_lock(idle_rq, rq);
-
-	idle_rq->curr = idle_rq->idle = idle;
-	deactivate_task(idle, rq);
+	idle->sleep_avg = 0;
+	idle->interactive_credit = 0;
 	idle->array = NULL;
 	idle->prio = MAX_PRIO;
 	idle->state = TASK_RUNNING;
 	set_task_cpu(idle, cpu);
-	double_rq_unlock(idle_rq, rq);
+
+	spin_lock_irqsave(&rq->lock, flags);
+	rq->curr = rq->idle = idle;
 	set_tsk_need_resched(idle);
-	local_irq_restore(flags);
+	spin_unlock_irqrestore(&rq->lock, flags);
 
 	/* Set the preempt count _outside_ the spinlocks! */
 #ifdef CONFIG_PREEMPT
@@ -3426,7 +3970,7 @@ EXPORT_SYMBOL_GPL(set_cpus_allowed);
  * Move (not current) task off this cpu, onto dest cpu.  We're doing
  * this because either it can't run here any more (set_cpus_allowed()
  * away from this CPU, or CPU going down), or because we're
- * attempting to rebalance this task on exec (sched_balance_exec).
+ * attempting to rebalance this task on exec (sched_exec).
  *
  * So we race with normal scheduler movements, but that's OK, as long
  * as the task is no longer on this CPU.
@@ -3438,7 +3982,7 @@ static void __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
 	if (unlikely(cpu_is_offline(dest_cpu)))
 		return;
 
-	rq_src  = cpu_rq(src_cpu);
+	rq_src = cpu_rq(src_cpu);
 	rq_dest = cpu_rq(dest_cpu);
 
 	double_rq_lock(rq_src, rq_dest);
@@ -3543,49 +4087,52 @@ wait_to_die:
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-/* migrate_all_tasks - function to migrate all tasks from the dead cpu.  */
-static void migrate_all_tasks(int src_cpu)
+/* Figure out where task on dead CPU should go, use force if neccessary. */
+static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *tsk)
 {
-	struct task_struct *tsk, *t;
 	int dest_cpu;
-	unsigned int node;
+	cpumask_t mask;
 
-	write_lock_irq(&tasklist_lock);
+	/* On same node? */
+	mask = node_to_cpumask(cpu_to_node(dead_cpu));
+	cpus_and(mask, mask, tsk->cpus_allowed);
+	dest_cpu = any_online_cpu(mask);
 
-	/* watch out for per node tasks, let's stay on this node */
-	node = cpu_to_node(src_cpu);
+	/* On any allowed CPU? */
+	if (dest_cpu == NR_CPUS)
+		dest_cpu = any_online_cpu(tsk->cpus_allowed);
+
+	/* No more Mr. Nice Guy. */
+	if (dest_cpu == NR_CPUS) {
+		cpus_setall(tsk->cpus_allowed);
+		dest_cpu = any_online_cpu(tsk->cpus_allowed);
+
+		/*
+		 * Don't tell them about moving exiting tasks or
+		 * kernel threads (both mm NULL), since they never
+		 * leave kernel.
+		 */
+		if (tsk->mm && printk_ratelimit())
+			printk(KERN_INFO "process %d (%s) no "
+			       "longer affine to cpu%d\n",
+			       tsk->pid, tsk->comm, dead_cpu);
+	}
+	__migrate_task(tsk, dead_cpu, dest_cpu);
+}
+
+/* Run through task list and migrate tasks from the dead cpu. */
+static void migrate_live_tasks(int src_cpu)
+{
+	struct task_struct *tsk, *t;
+
+	write_lock_irq(&tasklist_lock);
 
 	do_each_thread(t, tsk) {
-		cpumask_t mask;
 		if (tsk == current)
 			continue;
 
-		if (task_cpu(tsk) != src_cpu)
-			continue;
-
-		/* Figure out where this task should go (attempting to
-		 * keep it on-node), and check if it can be migrated
-		 * as-is.  NOTE that kernel threads bound to more than
-		 * one online cpu will be migrated. */
-		mask = node_to_cpumask(node);
-		cpus_and(mask, mask, tsk->cpus_allowed);
-		dest_cpu = any_online_cpu(mask);
-		if (dest_cpu == NR_CPUS)
-			dest_cpu = any_online_cpu(tsk->cpus_allowed);
-		if (dest_cpu == NR_CPUS) {
-			cpus_setall(tsk->cpus_allowed);
-			dest_cpu = any_online_cpu(tsk->cpus_allowed);
-
-			/* Don't tell them about moving exiting tasks
-			   or kernel threads (both mm NULL), since
-			   they never leave kernel. */
-			if (tsk->mm && printk_ratelimit())
-				printk(KERN_INFO "process %d (%s) no "
-				       "longer affine to cpu%d\n",
-				       tsk->pid, tsk->comm, src_cpu);
-		}
-
-		__migrate_task(tsk, src_cpu, dest_cpu);
+		if (task_cpu(tsk) == src_cpu)
+			move_task_off_dead_cpu(src_cpu, tsk);
 	} while_each_thread(t, tsk);
 
 	write_unlock_irq(&tasklist_lock);
@@ -3616,6 +4163,47 @@ void sched_idle_next(void)
 
 	spin_unlock_irqrestore(&rq->lock, flags);
 }
+
+static void migrate_dead(unsigned int dead_cpu, task_t *tsk)
+{
+	struct runqueue *rq = cpu_rq(dead_cpu);
+
+	/* Must be exiting, otherwise would be on tasklist. */
+	BUG_ON(tsk->state != TASK_ZOMBIE && tsk->state != TASK_DEAD);
+
+	/* Cannot have done final schedule yet: would have vanished. */
+	BUG_ON(tsk->flags & PF_DEAD);
+
+	get_task_struct(tsk);
+
+	/*
+	 * Drop lock around migration; if someone else moves it,
+	 * that's OK.  No task can be added to this CPU, so iteration is
+	 * fine.
+	 */
+	spin_unlock_irq(&rq->lock);
+	move_task_off_dead_cpu(dead_cpu, tsk);
+	spin_lock_irq(&rq->lock);
+
+	put_task_struct(tsk);
+}
+
+/* release_task() removes task from tasklist, so we won't find dead tasks. */
+static void migrate_dead_tasks(unsigned int dead_cpu)
+{
+	unsigned arr, i;
+	struct runqueue *rq = cpu_rq(dead_cpu);
+
+	for (arr = 0; arr < 2; arr++) {
+		for (i = 0; i < MAX_PRIO; i++) {
+			struct list_head *list = &rq->arrays[arr].queue[i];
+			while (!list_empty(list))
+				migrate_dead(dead_cpu,
+					     list_entry(list->next, task_t,
+							run_list));
+		}
+	}
+}
 #endif /* CONFIG_HOTPLUG_CPU */
 
 /*
@@ -3655,7 +4243,7 @@ static int migration_call(struct notifier_block *nfb, unsigned long action,
 		cpu_rq(cpu)->migration_thread = NULL;
 		break;
 	case CPU_DEAD:
-		migrate_all_tasks(cpu);
+		migrate_live_tasks(cpu);
 		rq = cpu_rq(cpu);
 		kthread_stop(rq->migration_thread);
 		rq->migration_thread = NULL;
@@ -3664,8 +4252,9 @@ static int migration_call(struct notifier_block *nfb, unsigned long action,
 		deactivate_task(rq->idle, rq);
 		rq->idle->static_prio = MAX_PRIO;
 		__setscheduler(rq->idle, SCHED_NORMAL, 0);
+		migrate_dead_tasks(cpu);
 		task_rq_unlock(rq, &flags);
- 		BUG_ON(rq->nr_running != 0);
+		BUG_ON(rq->nr_running != 0);
 
 		/* No need to migrate the tasks: it was best-effort if
 		 * they didn't do lock_cpu_hotplug().  Just wake up
@@ -3680,7 +4269,7 @@ static int migration_call(struct notifier_block *nfb, unsigned long action,
 			complete(&req->done);
 		}
 		spin_unlock_irq(&rq->lock);
- 		break;
+		break;
 #endif
 	}
 	return NOTIFY_OK;
@@ -3722,7 +4311,7 @@ EXPORT_SYMBOL(kernel_flag);
 
 #ifdef CONFIG_SMP
 /* Attach the domain 'sd' to 'cpu' as its base domain */
-void cpu_attach_domain(struct sched_domain *sd, int cpu)
+static void cpu_attach_domain(struct sched_domain *sd, int cpu)
 {
 	migration_req_t req;
 	unsigned long flags;
@@ -3753,124 +4342,343 @@ void cpu_attach_domain(struct sched_domain *sd, int cpu)
 	unlock_cpu_hotplug();
 }
 
-#ifdef ARCH_HAS_SCHED_DOMAIN
-extern void __init arch_init_sched_domains(void);
-#else
-static struct sched_group sched_group_cpus[NR_CPUS];
+/*
+ * To enable disjoint top-level NUMA domains, define SD_NODES_PER_DOMAIN
+ * in arch code. That defines the number of nearby nodes in a node's top
+ * level scheduling domain.
+ */
+#if defined(CONFIG_NUMA) && defined(SD_NODES_PER_DOMAIN)
+/**
+ * find_next_best_node - find the next node to include in a sched_domain
+ * @node: node whose sched_domain we're building
+ * @used_nodes: nodes already in the sched_domain
+ *
+ * Find the next node to include in a given scheduling domain.  Simply
+ * finds the closest node not already in the @used_nodes map.
+ *
+ * Should use nodemask_t.
+ */
+static int __init find_next_best_node(int node, unsigned long *used_nodes)
+{
+	int i, n, val, min_val, best_node = 0;
+
+	min_val = INT_MAX;
+
+	for (i = 0; i < numnodes; i++) {
+		/* Start at @node */
+		n = (node + i) % numnodes;
+
+		/* Skip already used nodes */
+		if (test_bit(n, used_nodes))
+			continue;
+
+		/* Simple min distance search */
+		val = node_distance(node, i);
+
+		if (val < min_val) {
+			min_val = val;
+			best_node = n;
+		}
+	}
+
+	set_bit(best_node, used_nodes);
+	return best_node;
+}
+
+/**
+ * sched_domain_node_span - get a cpumask for a node's sched_domain
+ * @node: node whose cpumask we're constructing
+ * @size: number of nodes to include in this span
+ *
+ * Given a node, construct a good cpumask for its sched_domain to span.  It
+ * should be one that prevents unnecessary balancing, but also spreads tasks
+ * out optimally.
+ */
+cpumask_t __init sched_domain_node_span(int node)
+{
+	int i;
+	cpumask_t span;
+	DECLARE_BITMAP(used_nodes, MAX_NUMNODES);
+
+	cpus_clear(span);
+	bitmap_zero(used_nodes, MAX_NUMNODES);
+
+	for (i = 0; i < SD_NODES_PER_DOMAIN; i++) {
+		int next_node = find_next_best_node(node, used_nodes);
+		cpumask_t  nodemask;
+
+		nodemask = node_to_cpumask(next_node);
+		cpus_or(span, span, nodemask);
+	}
+
+	return span;
+}
+#else /* CONFIG_NUMA && SD_NODES_PER_DOMAIN */
+cpumask_t __init sched_domain_node_span(int node)
+{
+	return cpu_possible_map;
+}
+#endif /* CONFIG_NUMA && SD_NODES_PER_DOMAIN */
+
+#ifdef CONFIG_SCHED_SMT
 static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
+static struct sched_group sched_group_cpus[NR_CPUS];
+__init static int cpu_to_cpu_group(int cpu)
+{
+	return cpu;
+}
+#endif
+
+static DEFINE_PER_CPU(struct sched_domain, phys_domains);
+static struct sched_group sched_group_phys[NR_CPUS];
+__init static int cpu_to_phys_group(int cpu)
+{
+#ifdef CONFIG_SCHED_SMT
+	return first_cpu(cpu_sibling_map[cpu]);
+#else
+	return cpu;
+#endif
+}
+
 #ifdef CONFIG_NUMA
-static struct sched_group sched_group_nodes[MAX_NUMNODES];
+
 static DEFINE_PER_CPU(struct sched_domain, node_domains);
-static void __init arch_init_sched_domains(void)
+static struct sched_group sched_group_nodes[MAX_NUMNODES];
+__init static int cpu_to_node_group(int cpu)
 {
-	int i;
-	struct sched_group *first_node = NULL, *last_node = NULL;
+	return cpu_to_node(cpu);
+}
+#endif
 
-	/* Set up domains */
-	for_each_cpu(i) {
-		int node = cpu_to_node(i);
-		cpumask_t nodemask = node_to_cpumask(node);
-		struct sched_domain *node_sd = &per_cpu(node_domains, i);
-		struct sched_domain *cpu_sd = &per_cpu(cpu_domains, i);
-
-		*node_sd = SD_NODE_INIT;
-		node_sd->span = cpu_possible_map;
-		node_sd->groups = &sched_group_nodes[cpu_to_node(i)];
-
-		*cpu_sd = SD_CPU_INIT;
-		cpus_and(cpu_sd->span, nodemask, cpu_possible_map);
-		cpu_sd->groups = &sched_group_cpus[i];
-		cpu_sd->parent = node_sd;
-	}
+/* Groups for isolated scheduling domains */
+static struct sched_group sched_group_isolated[NR_CPUS];
 
-	/* Set up groups */
-	for (i = 0; i < MAX_NUMNODES; i++) {
-		cpumask_t tmp = node_to_cpumask(i);
-		cpumask_t nodemask;
-		struct sched_group *first_cpu = NULL, *last_cpu = NULL;
-		struct sched_group *node = &sched_group_nodes[i];
-		int j;
+/* cpus with isolated domains */
+cpumask_t __initdata cpu_isolated_map = CPU_MASK_NONE;
 
-		cpus_and(nodemask, tmp, cpu_possible_map);
+__init static int cpu_to_isolated_group(int cpu)
+{
+	return cpu;
+}
 
-		if (cpus_empty(nodemask))
-			continue;
+/* Setup the mask of cpus configured for isolated domains */
+static int __init isolated_cpu_setup(char *str)
+{
+	int ints[NR_CPUS], i;
 
-		node->cpumask = nodemask;
-		node->cpu_power = SCHED_LOAD_SCALE * cpus_weight(node->cpumask);
+	str = get_options(str, ARRAY_SIZE(ints), ints);
+	cpus_clear(cpu_isolated_map);
+	for (i = 1; i <= ints[0]; i++)
+		cpu_set(ints[i], cpu_isolated_map);
+	return 1;
+}
 
-		for_each_cpu_mask(j, node->cpumask) {
-			struct sched_group *cpu = &sched_group_cpus[j];
+__setup ("isolcpus=", isolated_cpu_setup);
 
-			cpus_clear(cpu->cpumask);
-			cpu_set(j, cpu->cpumask);
-			cpu->cpu_power = SCHED_LOAD_SCALE;
+/*
+ * init_sched_build_groups takes an array of groups, the cpumask we wish
+ * to span, and a pointer to a function which identifies what group a CPU
+ * belongs to. The return value of group_fn must be a valid index into the
+ * groups[] array, and must be >= 0 and < NR_CPUS (due to the fact that we
+ * keep track of groups covered with a cpumask_t).
+ *
+ * init_sched_build_groups will build a circular linked list of the groups
+ * covered by the given span, and will set each group's ->cpumask correctly,
+ * and ->cpu_power to 0.
+ */
+__init static void init_sched_build_groups(struct sched_group groups[],
+			cpumask_t span, int (*group_fn)(int cpu))
+{
+	struct sched_group *first = NULL, *last = NULL;
+	cpumask_t covered = CPU_MASK_NONE;
+	int i;
 
-			if (!first_cpu)
-				first_cpu = cpu;
-			if (last_cpu)
-				last_cpu->next = cpu;
-			last_cpu = cpu;
-		}
-		last_cpu->next = first_cpu;
+	for_each_cpu_mask(i, span) {
+		int group = group_fn(i);
+		struct sched_group *sg = &groups[group];
+		int j;
 
-		if (!first_node)
-			first_node = node;
-		if (last_node)
-			last_node->next = node;
-		last_node = node;
-	}
-	last_node->next = first_node;
+		if (cpu_isset(i, covered))
+			continue;
 
-	mb();
-	for_each_cpu(i) {
-		struct sched_domain *cpu_sd = &per_cpu(cpu_domains, i);
-		cpu_attach_domain(cpu_sd, i);
+		sg->cpumask = CPU_MASK_NONE;
+		sg->cpu_power = 0;
+
+		for_each_cpu_mask(j, span) {
+			if (group_fn(j) != group)
+				continue;
+
+			cpu_set(j, covered);
+			cpu_set(j, sg->cpumask);
+		}
+		if (!first)
+			first = sg;
+		if (last)
+			last->next = sg;
+		last = sg;
 	}
+	last->next = first;
 }
 
-#else /* !CONFIG_NUMA */
-static void __init arch_init_sched_domains(void)
+__init static void arch_init_sched_domains(void)
 {
 	int i;
-	struct sched_group *first_cpu = NULL, *last_cpu = NULL;
+	cpumask_t cpu_default_map;
+
+	/*
+	 * Setup mask for cpus without special case scheduling requirements.
+	 * For now this just excludes isolated cpus, but could be used to
+	 * exclude other special cases in the future.
+	 */
+	cpus_complement(cpu_default_map, cpu_isolated_map);
+	cpus_and(cpu_default_map, cpu_default_map, cpu_possible_map);
 
 	/* Set up domains */
 	for_each_cpu(i) {
-		struct sched_domain *cpu_sd = &per_cpu(cpu_domains, i);
+		int group;
+		struct sched_domain *sd = NULL, *p;
+		cpumask_t nodemask = node_to_cpumask(cpu_to_node(i));
+
+		cpus_and(nodemask, nodemask, cpu_default_map);
+
+		/*
+		 * Set up isolated domains.
+		 * Unlike those of other cpus, the domains and groups are
+		 * single level, and span a single cpu.
+		 */
+		if (cpu_isset(i, cpu_isolated_map)) {
+#ifdef CONFIG_SCHED_SMT
+			sd = &per_cpu(cpu_domains, i);
+#else
+			sd = &per_cpu(phys_domains, i);
+#endif
+			group = cpu_to_isolated_group(i);
+			*sd = SD_CPU_INIT;
+			cpu_set(i, sd->span);
+			sd->balance_interval = INT_MAX;	/* Don't balance */
+			sd->flags = 0;			/* Avoid WAKE_ */
+			sd->groups = &sched_group_isolated[group];
+			printk(KERN_INFO "Setting up cpu %d isolated.\n", i);
+			/* Single level, so continue with next cpu */
+			continue;
+		}
+
+#ifdef CONFIG_NUMA
+		sd = &per_cpu(node_domains, i);
+		group = cpu_to_node_group(i);
+		*sd = SD_NODE_INIT;
+		/* FIXME: should be multilevel, in arch code */
+		sd->span = sched_domain_node_span(i);
+		cpus_and(sd->span, sd->span, cpu_default_map);
+		sd->groups = &sched_group_nodes[group];
+#endif
 
-		*cpu_sd = SD_CPU_INIT;
-		cpu_sd->span = cpu_possible_map;
-		cpu_sd->groups = &sched_group_cpus[i];
+		p = sd;
+		sd = &per_cpu(phys_domains, i);
+		group = cpu_to_phys_group(i);
+		*sd = SD_CPU_INIT;
+#ifdef CONFIG_NUMA
+		sd->span = nodemask;
+#else
+		sd->span = cpu_possible_map;
+#endif
+		sd->parent = p;
+		sd->groups = &sched_group_phys[group];
+
+#ifdef CONFIG_SCHED_SMT
+		p = sd;
+		sd = &per_cpu(cpu_domains, i);
+		group = cpu_to_cpu_group(i);
+		*sd = SD_SIBLING_INIT;
+		sd->span = cpu_sibling_map[i];
+		cpus_and(sd->span, sd->span, cpu_default_map);
+		sd->parent = p;
+		sd->groups = &sched_group_cpus[group];
+#endif
 	}
 
-	/* Set up CPU groups */
-	for_each_cpu_mask(i, cpu_possible_map) {
-		struct sched_group *cpu = &sched_group_cpus[i];
+#ifdef CONFIG_SCHED_SMT
+	/* Set up CPU (sibling) groups */
+	for_each_cpu(i) {
+		cpumask_t this_sibling_map = cpu_sibling_map[i];
+		cpus_and(this_sibling_map, this_sibling_map, cpu_default_map);
+		if (i != first_cpu(this_sibling_map))
+			continue;
+
+		init_sched_build_groups(sched_group_cpus, this_sibling_map,
+						&cpu_to_cpu_group);
+	}
+#endif
+
+	/* Set up isolated groups */
+	for_each_cpu_mask(i, cpu_isolated_map) {
+		cpumask_t mask;
+		cpus_clear(mask);
+		cpu_set(i, mask);
+		init_sched_build_groups(sched_group_isolated, mask,
+						&cpu_to_isolated_group);
+	}
+
+#ifdef CONFIG_NUMA
+	/* Set up physical groups */
+	for (i = 0; i < MAX_NUMNODES; i++) {
+		cpumask_t nodemask = node_to_cpumask(i);
+
+		cpus_and(nodemask, nodemask, cpu_default_map);
+		if (cpus_empty(nodemask))
+			continue;
+
+		init_sched_build_groups(sched_group_phys, nodemask,
+						&cpu_to_phys_group);
+	}
+#else
+	init_sched_build_groups(sched_group_phys, cpu_possible_map,
+							&cpu_to_phys_group);
+#endif
+
+#ifdef CONFIG_NUMA
+	/* Set up node groups */
+	init_sched_build_groups(sched_group_nodes, cpu_default_map,
+					&cpu_to_node_group);
+#endif
+
+	/* Calculate CPU power for physical packages and nodes */
+	for_each_cpu_mask(i, cpu_default_map) {
+		int power;
+		struct sched_domain *sd;
+#ifdef CONFIG_SCHED_SMT
+		sd = &per_cpu(cpu_domains, i);
+		power = SCHED_LOAD_SCALE;
+		sd->groups->cpu_power = power;
+#endif
 
-		cpus_clear(cpu->cpumask);
-		cpu_set(i, cpu->cpumask);
-		cpu->cpu_power = SCHED_LOAD_SCALE;
+		sd = &per_cpu(phys_domains, i);
+		power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE *
+				(cpus_weight(sd->groups->cpumask)-1) / 10;
+		sd->groups->cpu_power = power;
 
-		if (!first_cpu)
-			first_cpu = cpu;
-		if (last_cpu)
-			last_cpu->next = cpu;
-		last_cpu = cpu;
+#ifdef CONFIG_NUMA
+		if (i == first_cpu(sd->groups->cpumask)) {
+			/* Only add "power" once for each physical package. */
+			sd = &per_cpu(node_domains, i);
+			sd->groups->cpu_power += power;
+		}
+#endif
 	}
-	last_cpu->next = first_cpu;
 
-	mb(); /* domains were modified outside the lock */
+	/* Attach the domains */
 	for_each_cpu(i) {
-		struct sched_domain *cpu_sd = &per_cpu(cpu_domains, i);
-		cpu_attach_domain(cpu_sd, i);
+		struct sched_domain *sd;
+#ifdef CONFIG_SCHED_SMT
+		sd = &per_cpu(cpu_domains, i);
+#else
+		sd = &per_cpu(phys_domains, i);
+#endif
+		cpu_attach_domain(sd, i);
 	}
 }
 
-#endif /* CONFIG_NUMA */
-#endif /* ARCH_HAS_SCHED_DOMAIN */
-
-#define SCHED_DOMAIN_DEBUG
+#undef SCHED_DOMAIN_DEBUG
 #ifdef SCHED_DOMAIN_DEBUG
 void sched_domain_debug(void)
 {
@@ -3965,8 +4773,9 @@ int in_sched_functions(unsigned long addr)
 {
 	/* Linker adds these: start and end of __sched functions */
 	extern char __sched_text_start[], __sched_text_end[];
-	return addr >= (unsigned long)__sched_text_start
-		&& addr < (unsigned long)__sched_text_end;
+	return in_lock_functions(addr) ||
+		(addr >= (unsigned long)__sched_text_start
+		&& addr < (unsigned long)__sched_text_end);
 }
 
 void __init sched_init(void)
@@ -4009,7 +4818,9 @@ void __init sched_init(void)
 		rq->migration_thread = NULL;
 		INIT_LIST_HEAD(&rq->migration_queue);
 #endif
+#ifdef CONFIG_VSERVER_HARDCPU
 		INIT_LIST_HEAD(&rq->hold_queue);
+#endif
 		atomic_set(&rq->nr_iowait, 0);
 
 		for (j = 0; j < 2; j++) {
@@ -4022,21 +4833,20 @@ void __init sched_init(void)
 			__set_bit(MAX_PRIO, array->bitmap);
 		}
 	}
-	/*
-	 * We have to do a little magic to get the first
-	 * thread right in SMP mode.
-	 */
-	rq = this_rq();
-	rq->curr = current;
-	rq->idle = current;
-	set_task_cpu(current, smp_processor_id());
-	wake_up_forked_process(current);
 
 	/*
 	 * The boot idle thread does lazy MMU switching as well:
 	 */
 	atomic_inc(&init_mm.mm_count);
 	enter_lazy_tlb(&init_mm, current);
+
+	/*
+	 * Make us the idle thread. Technically, schedule() should not be
+	 * called from this thread, however somewhere below it might be,
+	 * but because we are the idle thread, we just pick up running again
+	 * when this runqueue becomes "idle".
+	 */
+	init_idle(current, smp_processor_id());
 }
 
 #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
@@ -4060,49 +4870,3 @@ void __might_sleep(char *file, int line)
 }
 EXPORT_SYMBOL(__might_sleep);
 #endif
-
-
-#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT)
-/*
- * This could be a long-held lock.  If another CPU holds it for a long time,
- * and that CPU is not asked to reschedule then *this* CPU will spin on the
- * lock for a long time, even if *this* CPU is asked to reschedule.
- *
- * So what we do here, in the slow (contended) path is to spin on the lock by
- * hand while permitting preemption.
- *
- * Called inside preempt_disable().
- */
-void __sched __preempt_spin_lock(spinlock_t *lock)
-{
-	if (preempt_count() > 1) {
-		_raw_spin_lock(lock);
-		return;
-	}
-	do {
-		preempt_enable();
-		while (spin_is_locked(lock))
-			cpu_relax();
-		preempt_disable();
-	} while (!_raw_spin_trylock(lock));
-}
-
-EXPORT_SYMBOL(__preempt_spin_lock);
-
-void __sched __preempt_write_lock(rwlock_t *lock)
-{
-	if (preempt_count() > 1) {
-		_raw_write_lock(lock);
-		return;
-	}
-
-	do {
-		preempt_enable();
-		while (rwlock_is_locked(lock))
-			cpu_relax();
-		preempt_disable();
-	} while (!_raw_write_trylock(lock));
-}
-
-EXPORT_SYMBOL(__preempt_write_lock);
-#endif /* defined(CONFIG_SMP) && defined(CONFIG_PREEMPT) */
diff --git a/kernel/signal.c b/kernel/signal.c
index 74d1d9eec..4d39765b4 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -26,6 +26,8 @@
 #include <asm/unistd.h>
 #include <asm/siginfo.h>
 
+extern void k_getrusage(struct task_struct *, int, struct rusage *);
+
 /*
  * SLAB caches for signal bits.
  */
@@ -367,6 +369,22 @@ void __exit_signal(struct task_struct *tsk)
 		if (tsk == sig->curr_target)
 			sig->curr_target = next_thread(tsk);
 		tsk->signal = NULL;
+		/*
+		 * Accumulate here the counters for all threads but the
+		 * group leader as they die, so they can be added into
+		 * the process-wide totals when those are taken.
+		 * The group leader stays around as a zombie as long
+		 * as there are other threads.  When it gets reaped,
+		 * the exit.c code will add its counts into these totals.
+		 * We won't ever get here for the group leader, since it
+		 * will have been the last reference on the signal_struct.
+		 */
+		sig->utime += tsk->utime;
+		sig->stime += tsk->stime;
+		sig->min_flt += tsk->min_flt;
+		sig->maj_flt += tsk->maj_flt;
+		sig->nvcsw += tsk->nvcsw;
+		sig->nivcsw += tsk->nivcsw;
 		spin_unlock(&sighand->siglock);
 		sig = NULL;	/* Marker for below.  */
 	}
@@ -602,23 +620,33 @@ static int check_kill_permission(int sig, struct siginfo *info,
 				 struct task_struct *t)
 {
 	int error = -EINVAL;
+	int user;
+
 	if (sig < 0 || sig > _NSIG)
 		return error;
+
+	user = (!info || ((unsigned long)info != 1 &&
+		(unsigned long)info != 2 && SI_FROMUSER(info)));
+
 	error = -EPERM;
-	if ((!info || ((unsigned long)info != 1 &&
-			(unsigned long)info != 2 && SI_FROMUSER(info)))
-	    && ((sig != SIGCONT) ||
+	if (user && ((sig != SIGCONT) ||
 		(current->signal->session != t->signal->session))
 	    && (current->euid ^ t->suid) && (current->euid ^ t->uid)
 	    && (current->uid ^ t->suid) && (current->uid ^ t->uid)
 	    && !capable(CAP_KILL))
 		return error;
+
+	error = -ESRCH;
+	if (user && !vx_check(vx_task_xid(t), VX_ADMIN|VX_IDENT))
+		return error;
+
 	return security_task_kill(t, info, sig);
 }
 
 /* forward decl */
 static void do_notify_parent_cldstop(struct task_struct *tsk,
-				     struct task_struct *parent);
+				     struct task_struct *parent,
+				     int why);
 
 /*
  * Handle magic process-wide effects of stop/continue signals.
@@ -660,12 +688,17 @@ static void handle_stop_signal(int sig, struct task_struct *p)
 			 * the SIGCHLD was pending on entry to this kill.
 			 */
 			p->signal->group_stop_count = 0;
+			p->signal->stop_state = 1;
+			spin_unlock(&p->sighand->siglock);
 			if (p->ptrace & PT_PTRACED)
-				do_notify_parent_cldstop(p, p->parent);
+				do_notify_parent_cldstop(p, p->parent,
+							 CLD_STOPPED);
 			else
 				do_notify_parent_cldstop(
 					p->group_leader,
-					p->group_leader->real_parent);
+					p->group_leader->real_parent,
+							 CLD_STOPPED);
+			spin_lock(&p->sighand->siglock);
 		}
 		rm_from_queue(SIG_KERNEL_STOP_MASK, &p->signal->shared_pending);
 		t = p;
@@ -696,6 +729,25 @@ static void handle_stop_signal(int sig, struct task_struct *p)
 
 			t = next_thread(t);
 		} while (t != p);
+
+		if (p->signal->stop_state > 0) {
+			/*
+			 * We were in fact stopped, and are now continued.
+			 * Notify the parent with CLD_CONTINUED.
+			 */
+			p->signal->stop_state = -1;
+			p->signal->group_exit_code = 0;
+			spin_unlock(&p->sighand->siglock);
+			if (p->ptrace & PT_PTRACED)
+				do_notify_parent_cldstop(p, p->parent,
+							 CLD_CONTINUED);
+			else
+				do_notify_parent_cldstop(
+					p->group_leader,
+					p->group_leader->real_parent,
+							 CLD_CONTINUED);
+			spin_lock(&p->sighand->siglock);
+		}
 	}
 }
 
@@ -861,10 +913,19 @@ force_sig_specific(int sig, struct task_struct *t)
 
 
 static void
-__group_complete_signal(int sig, struct task_struct *p, unsigned int mask)
+__group_complete_signal(int sig, struct task_struct *p)
 {
+	unsigned int mask;
 	struct task_struct *t;
 
+	/*
+	 * Don't bother zombies and stopped tasks (but
+	 * SIGKILL will punch through stopped state)
+	 */
+	mask = TASK_DEAD | TASK_ZOMBIE | TASK_TRACED;
+	if (sig != SIGKILL)
+		mask |= TASK_STOPPED;
+
 	/*
 	 * Now find a thread we can wake up to take the signal off the queue.
 	 *
@@ -966,7 +1027,6 @@ __group_complete_signal(int sig, struct task_struct *p, unsigned int mask)
 static int
 __group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
 {
-	unsigned int mask;
 	int ret = 0;
 
 #ifdef CONFIG_SMP
@@ -989,14 +1049,6 @@ __group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
 		/* This is a non-RT signal and we already have one queued.  */
 		return ret;
 
-	/*
-	 * Don't bother zombies and stopped tasks (but
-	 * SIGKILL will punch through stopped state)
-	 */
-	mask = TASK_DEAD | TASK_ZOMBIE;
-	if (sig != SIGKILL)
-		mask |= TASK_STOPPED;
-
 	/*
 	 * Put this signal on the shared-pending queue, or fail with EAGAIN.
 	 * We always use the shared queue for process-wide signals,
@@ -1006,7 +1058,7 @@ __group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
 	if (unlikely(ret))
 		return ret;
 
-	__group_complete_signal(sig, p, mask);
+	__group_complete_signal(sig, p);
 	return 0;
 }
 
@@ -1054,9 +1106,6 @@ int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
 	unsigned long flags;
 	int ret;
 
-	if (!vx_check(vx_task_xid(p), VX_ADMIN|VX_WATCH|VX_IDENT))
-		return -ESRCH;
-
 	ret = check_kill_permission(sig, info, p);
 	if (!ret && sig && p->sighand) {
 		spin_lock_irqsave(&p->sighand->siglock, flags);
@@ -1075,8 +1124,6 @@ int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
 int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp)
 {
 	struct task_struct *p;
-	struct list_head *l;
-	struct pid *pid;
 	int retval, success;
 
 	if (pgrp <= 0)
@@ -1084,11 +1131,11 @@ int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp)
 
 	success = 0;
 	retval = -ESRCH;
-	for_each_task_pid(pgrp, PIDTYPE_PGID, p, l, pid) {
+	do_each_task_pid(pgrp, PIDTYPE_PGID, p) {
 		int err = group_send_sig_info(sig, info, p);
 		success |= !err;
 		retval = err;
-	}
+	} while_each_task_pid(pgrp, PIDTYPE_PGID, p);
 	return success ? 0 : retval;
 }
 
@@ -1115,8 +1162,6 @@ int
 kill_sl_info(int sig, struct siginfo *info, pid_t sid)
 {
 	int err, retval = -EINVAL;
-	struct pid *pid;
-	struct list_head *l;
 	struct task_struct *p;
 
 	if (sid <= 0)
@@ -1124,13 +1169,13 @@ kill_sl_info(int sig, struct siginfo *info, pid_t sid)
 
 	retval = -ESRCH;
 	read_lock(&tasklist_lock);
-	for_each_task_pid(sid, PIDTYPE_SID, p, l, pid) {
+	do_each_task_pid(sid, PIDTYPE_SID, p) {
 		if (!p->signal->leader)
 			continue;
 		err = group_send_sig_info(sig, info, p);
 		if (retval)
 			retval = err;
-	}
+	} while_each_task_pid(sid, PIDTYPE_SID, p);
 	read_unlock(&tasklist_lock);
 out:
 	return retval;
@@ -1246,6 +1291,25 @@ force_sig(int sig, struct task_struct *p)
 	force_sig_info(sig, (void*)1L, p);
 }
 
+/*
+ * When things go south during signal handling, we
+ * will force a SIGSEGV. And if the signal that caused
+ * the problem was already a SIGSEGV, we'll want to
+ * make sure we don't even try to deliver the signal..
+ */
+int
+force_sigsegv(int sig, struct task_struct *p)
+{
+	if (sig == SIGSEGV) {
+		unsigned long flags;
+		spin_lock_irqsave(&p->sighand->siglock, flags);
+		p->sighand->action[sig - 1].sa.sa_handler = SIG_DFL;
+		spin_unlock_irqrestore(&p->sighand->siglock, flags);
+	}
+	force_sig(SIGSEGV, p);
+	return 0;
+}
+
 int
 kill_pg(pid_t pgrp, int sig, int priv)
 {
@@ -1351,7 +1415,6 @@ int
 send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
 {
 	unsigned long flags;
-	unsigned int mask;
 	int ret = 0;
 
 	BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
@@ -1376,13 +1439,6 @@ send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
 		q->info.si_overrun++;
 		goto out;
 	} 
-	/*
-	 * Don't bother zombies and stopped tasks (but
-	 * SIGKILL will punch through stopped state)
-	 */
-	mask = TASK_DEAD | TASK_ZOMBIE;
-	if (sig != SIGKILL)
-		mask |= TASK_STOPPED;
 
 	/*
 	 * Put this signal on the shared-pending queue.
@@ -1393,7 +1449,7 @@ send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p)
 	list_add_tail(&q->list, &p->signal->shared_pending.list);
 	sigaddset(&p->signal->shared_pending.signal, sig);
 
-	__group_complete_signal(sig, p, mask);
+	__group_complete_signal(sig, p);
 out:
 	spin_unlock_irqrestore(&p->sighand->siglock, flags);
 	read_unlock(&tasklist_lock);
@@ -1426,21 +1482,24 @@ static void __wake_up_parent(struct task_struct *p,
 }
 
 /*
- * Let a parent know about a status change of a child.
+ * Let a parent know about the death of a child.
+ * For a stopped/continued status change, use do_notify_parent_cldstop instead.
  */
 
 void do_notify_parent(struct task_struct *tsk, int sig)
 {
 	struct siginfo info;
 	unsigned long flags;
-	int why, status;
 	struct sighand_struct *psig;
 
 	if (sig == -1)
 		BUG();
 
-	BUG_ON(tsk->group_leader != tsk && tsk->group_leader->state != TASK_ZOMBIE && !tsk->ptrace);
-	BUG_ON(tsk->group_leader == tsk && !thread_group_empty(tsk) && !tsk->ptrace);
+ 	/* do_notify_parent_cldstop should have been called instead.  */
+ 	BUG_ON(tsk->state & (TASK_STOPPED|TASK_TRACED));
+
+	BUG_ON(!tsk->ptrace &&
+	       (tsk->group_leader != tsk || !thread_group_empty(tsk)));
 
 	info.si_signo = sig;
 	info.si_errno = 0;
@@ -1448,37 +1507,22 @@ void do_notify_parent(struct task_struct *tsk, int sig)
 	info.si_uid = tsk->uid;
 
 	/* FIXME: find out whether or not this is supposed to be c*time. */
-	info.si_utime = tsk->utime;
-	info.si_stime = tsk->stime;
-
-	status = tsk->exit_code & 0x7f;
-	why = SI_KERNEL;	/* shouldn't happen */
-	switch (tsk->state) {
-	case TASK_STOPPED:
-		/* FIXME -- can we deduce CLD_TRAPPED or CLD_CONTINUED? */
-		if (tsk->ptrace & PT_PTRACED)
-			why = CLD_TRAPPED;
-		else
-			why = CLD_STOPPED;
-		break;
+	info.si_utime = tsk->utime + tsk->signal->utime;
+	info.si_stime = tsk->stime + tsk->signal->stime;
 
-	default:
-		if (tsk->exit_code & 0x80)
-			why = CLD_DUMPED;
-		else if (tsk->exit_code & 0x7f)
-			why = CLD_KILLED;
-		else {
-			why = CLD_EXITED;
-			status = tsk->exit_code >> 8;
-		}
-		break;
+	info.si_status = tsk->exit_code & 0x7f;
+	if (tsk->exit_code & 0x80)
+		info.si_code = CLD_DUMPED;
+	else if (tsk->exit_code & 0x7f)
+		info.si_code = CLD_KILLED;
+	else {
+		info.si_code = CLD_EXITED;
+		info.si_status = tsk->exit_code >> 8;
 	}
-	info.si_code = why;
-	info.si_status = status;
 
 	psig = tsk->parent->sighand;
 	spin_lock_irqsave(&psig->siglock, flags);
-	if (sig == SIGCHLD && tsk->state != TASK_STOPPED &&
+	if (sig == SIGCHLD &&
 	    (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN ||
 	     (psig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT))) {
 		/*
@@ -1506,26 +1550,9 @@ void do_notify_parent(struct task_struct *tsk, int sig)
 	spin_unlock_irqrestore(&psig->siglock, flags);
 }
 
-
-/*
- * We need the tasklist lock because it's the only
- * thing that protects out "parent" pointer.
- *
- * exit.c calls "do_notify_parent()" directly, because
- * it already has the tasklist lock.
- */
-void
-notify_parent(struct task_struct *tsk, int sig)
-{
-	if (sig != -1) {
-		read_lock(&tasklist_lock);
-		do_notify_parent(tsk, sig);
-		read_unlock(&tasklist_lock);
-	}
-}
-
 static void
-do_notify_parent_cldstop(struct task_struct *tsk, struct task_struct *parent)
+do_notify_parent_cldstop(struct task_struct *tsk, struct task_struct *parent,
+			 int why)
 {
 	struct siginfo info;
 	unsigned long flags;
@@ -1540,8 +1567,20 @@ do_notify_parent_cldstop(struct task_struct *tsk, struct task_struct *parent)
 	info.si_utime = tsk->utime;
 	info.si_stime = tsk->stime;
 
-	info.si_status = tsk->exit_code & 0x7f;
-	info.si_code = CLD_STOPPED;
+ 	info.si_code = why;
+ 	switch (why) {
+ 	case CLD_CONTINUED:
+ 		info.si_status = SIGCONT;
+ 		break;
+ 	case CLD_STOPPED:
+ 		info.si_status = tsk->signal->group_exit_code & 0x7f;
+ 		break;
+ 	case CLD_TRAPPED:
+ 		info.si_status = tsk->exit_code & 0x7f;
+ 		break;
+ 	default:
+ 		BUG();
+ 	}
 
 	sighand = parent->sighand;
 	spin_lock_irqsave(&sighand->siglock, flags);
@@ -1555,6 +1594,68 @@ do_notify_parent_cldstop(struct task_struct *tsk, struct task_struct *parent)
 	spin_unlock_irqrestore(&sighand->siglock, flags);
 }
 
+/*
+ * This must be called with current->sighand->siglock held.
+ *
+ * This should be the path for all ptrace stops.
+ * We always set current->last_siginfo while stopped here.
+ * That makes it a way to test a stopped process for
+ * being ptrace-stopped vs being job-control-stopped.
+ */
+static void ptrace_stop(int exit_code, siginfo_t *info)
+{
+	BUG_ON(!(current->ptrace & PT_PTRACED));
+
+	/*
+	 * If there is a group stop in progress,
+	 * we must participate in the bookkeeping.
+	 */
+	if (current->signal->group_stop_count > 0)
+		--current->signal->group_stop_count;
+
+	current->last_siginfo = info;
+	current->exit_code = exit_code;
+
+	/* Let the debugger run.  */
+	set_current_state(TASK_TRACED);
+	spin_unlock_irq(&current->sighand->siglock);
+	read_lock(&tasklist_lock);
+	do_notify_parent_cldstop(current, current->parent, CLD_TRAPPED);
+	read_unlock(&tasklist_lock);
+	schedule();
+
+	/*
+	 * We are back.  Now reacquire the siglock before touching
+	 * last_siginfo, so that we are sure to have synchronized with
+	 * any signal-sending on another CPU that wants to examine it.
+	 */
+	spin_lock_irq(&current->sighand->siglock);
+	current->last_siginfo = NULL;
+
+	/*
+	 * Queued signals ignored us while we were stopped for tracing.
+	 * So check for any that we should take before resuming user mode.
+	 */
+	recalc_sigpending();
+}
+
+void ptrace_notify(int exit_code)
+{
+	siginfo_t info;
+
+	BUG_ON((exit_code & (0x7f | ~0xffff)) != SIGTRAP);
+
+	memset(&info, 0, sizeof info);
+	info.si_signo = SIGTRAP;
+	info.si_code = exit_code;
+	info.si_pid = current->pid;
+	info.si_uid = current->uid;
+
+	/* Let the debugger run.  */
+	spin_lock_irq(&current->sighand->siglock);
+	ptrace_stop(exit_code, &info);
+	spin_unlock_irq(&current->sighand->siglock);
+}
 
 #ifndef HAVE_ARCH_GET_SIGNAL_TO_DELIVER
 
@@ -1568,13 +1669,15 @@ finish_stop(int stop_count)
 	 */
 	if (stop_count < 0 || (current->ptrace & PT_PTRACED)) {
 		read_lock(&tasklist_lock);
-		do_notify_parent_cldstop(current, current->parent);
+		do_notify_parent_cldstop(current, current->parent,
+					 CLD_STOPPED);
 		read_unlock(&tasklist_lock);
 	}
 	else if (stop_count == 0) {
 		read_lock(&tasklist_lock);
 		do_notify_parent_cldstop(current->group_leader,
-					 current->group_leader->real_parent);
+					 current->group_leader->real_parent,
+					 CLD_STOPPED);
 		read_unlock(&tasklist_lock);
 	}
 
@@ -1607,14 +1710,17 @@ do_signal_stop(int signr)
 		stop_count = --sig->group_stop_count;
 		current->exit_code = signr;
 		set_current_state(TASK_STOPPED);
+		if (stop_count == 0)
+			sig->stop_state = 1;
 		spin_unlock_irq(&sighand->siglock);
 	}
 	else if (thread_group_empty(current)) {
 		/*
 		 * Lock must be held through transition to stopped state.
 		 */
-		current->exit_code = signr;
+		current->exit_code = current->signal->group_exit_code = signr;
 		set_current_state(TASK_STOPPED);
+		sig->stop_state = 1;
 		spin_unlock_irq(&sighand->siglock);
 	}
 	else {
@@ -1680,6 +1786,8 @@ do_signal_stop(int signr)
 
 		current->exit_code = signr;
 		set_current_state(TASK_STOPPED);
+		if (stop_count == 0)
+			sig->stop_state = 1;
 
 		spin_unlock_irq(&sighand->siglock);
 		read_unlock(&tasklist_lock);
@@ -1720,6 +1828,8 @@ static inline int handle_group_stop(void)
 	 * without any associated signal being in our queue.
 	 */
 	stop_count = --current->signal->group_stop_count;
+	if (stop_count == 0)
+		current->signal->stop_state = 1;
 	current->exit_code = current->signal->group_exit_code;
 	set_current_state(TASK_STOPPED);
 	spin_unlock_irq(&current->sighand->siglock);
@@ -1727,7 +1837,8 @@ static inline int handle_group_stop(void)
 	return 1;
 }
 
-int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs, void *cookie)
+int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
+			  struct pt_regs *regs, void *cookie)
 {
 	sigset_t *mask = &current->blocked;
 	int signr = 0;
@@ -1749,25 +1860,10 @@ relock:
 		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
 			ptrace_signal_deliver(regs, cookie);
 
-			/*
-			 * If there is a group stop in progress,
-			 * we must participate in the bookkeeping.
-			 */
-			if (current->signal->group_stop_count > 0)
-				--current->signal->group_stop_count;
-
 			/* Let the debugger run.  */
-			current->exit_code = signr;
-			current->last_siginfo = info;
-			set_current_state(TASK_STOPPED);
-			spin_unlock_irq(&current->sighand->siglock);
-			notify_parent(current, SIGCHLD);
-			schedule();
-
-			current->last_siginfo = NULL;
+			ptrace_stop(signr, info);
 
 			/* We're back.  Did the debugger cancel the sig?  */
-			spin_lock_irq(&current->sighand->siglock);
 			signr = current->exit_code;
 			if (signr == 0)
 				continue;
@@ -1796,8 +1892,15 @@ relock:
 		ka = &current->sighand->action[signr-1];
 		if (ka->sa.sa_handler == SIG_IGN) /* Do nothing.  */
 			continue;
-		if (ka->sa.sa_handler != SIG_DFL) /* Run the handler.  */
+		if (ka->sa.sa_handler != SIG_DFL) {
+			/* Run the handler.  */
+			*return_ka = *ka;
+
+			if (ka->sa.sa_flags & SA_ONESHOT)
+				ka->sa.sa_handler = SIG_DFL;
+
 			break; /* will return non-zero "signr" value */
+		}
 
 		/*
 		 * Now we are doing the default action for this signal.
@@ -1891,7 +1994,7 @@ EXPORT_SYMBOL(kill_proc);
 EXPORT_SYMBOL(kill_proc_info);
 EXPORT_SYMBOL(kill_sl);
 EXPORT_SYMBOL(kill_sl_info);
-EXPORT_SYMBOL(notify_parent);
+EXPORT_SYMBOL(ptrace_notify);
 EXPORT_SYMBOL(send_sig);
 EXPORT_SYMBOL(send_sig_info);
 EXPORT_SYMBOL(send_group_sig_info);
diff --git a/kernel/softirq.c b/kernel/softirq.c
index c336ae21b..4a3da9be9 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -15,6 +15,7 @@
 #include <linux/percpu.h>
 #include <linux/cpu.h>
 #include <linux/kthread.h>
+#include <linux/rcupdate.h>
 
 #include <asm/irq.h>
 /*
@@ -75,10 +76,12 @@ asmlinkage void __do_softirq(void)
 	struct softirq_action *h;
 	__u32 pending;
 	int max_restart = MAX_SOFTIRQ_RESTART;
+	int cpu;
 
 	pending = local_softirq_pending();
 
 	local_bh_disable();
+	cpu = smp_processor_id();
 restart:
 	/* Reset the pending bitmask before enabling irqs */
 	local_softirq_pending() = 0;
@@ -88,8 +91,10 @@ restart:
 	h = softirq_vec;
 
 	do {
-		if (pending & 1)
+		if (pending & 1) {
 			h->action(h);
+			rcu_bh_qsctr_inc(cpu);
+		}
 		h++;
 		pending >>= 1;
 	} while (pending);
diff --git a/kernel/sys.c b/kernel/sys.c
index e7a076dce..1ba0e4c99 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -277,7 +277,9 @@ cond_syscall(compat_sys_mq_getsetattr)
 cond_syscall(sys_mbind)
 cond_syscall(sys_get_mempolicy)
 cond_syscall(sys_set_mempolicy)
+cond_syscall(compat_mbind)
 cond_syscall(compat_get_mempolicy)
+cond_syscall(compat_set_mempolicy)
 
 /* arch-specific weak syscall entries */
 cond_syscall(sys_pciconfig_read)
@@ -294,7 +296,10 @@ static int set_one_prio(struct task_struct *p, int niceval, int error)
 		goto out;
 	}
 	if (niceval < task_nice(p) && !capable(CAP_SYS_NICE)) {
-		error = -EACCES;
+		if (vx_flags(VXF_IGNEG_NICE, 0))
+			error = 0;
+		else
+			error = -EACCES;
 		goto out;
 	}
 	no_nice = security_task_setnice(p, niceval);
@@ -313,8 +318,6 @@ asmlinkage long sys_setpriority(int which, int who, int niceval)
 {
 	struct task_struct *g, *p;
 	struct user_struct *user;
-	struct pid *pid;
-	struct list_head *l;
 	int error = -EINVAL;
 
 	if (which > 2 || which < 0)
@@ -339,8 +342,9 @@ asmlinkage long sys_setpriority(int which, int who, int niceval)
 		case PRIO_PGRP:
 			if (!who)
 				who = process_group(current);
-			for_each_task_pid(who, PIDTYPE_PGID, p, l, pid)
+			do_each_task_pid(who, PIDTYPE_PGID, p) {
 				error = set_one_prio(p, niceval, error);
+			} while_each_task_pid(who, PIDTYPE_PGID, p);
 			break;
 		case PRIO_USER:
 			if (!who)
@@ -374,8 +378,6 @@ out:
 asmlinkage long sys_getpriority(int which, int who)
 {
 	struct task_struct *g, *p;
-	struct list_head *l;
-	struct pid *pid;
 	struct user_struct *user;
 	long niceval, retval = -ESRCH;
 
@@ -397,11 +399,11 @@ asmlinkage long sys_getpriority(int which, int who)
 		case PRIO_PGRP:
 			if (!who)
 				who = process_group(current);
-			for_each_task_pid(who, PIDTYPE_PGID, p, l, pid) {
+			do_each_task_pid(who, PIDTYPE_PGID, p) {
 				niceval = 20 - task_nice(p);
 				if (niceval > retval)
 					retval = niceval;
-			}
+			} while_each_task_pid(who, PIDTYPE_PGID, p);
 			break;
 		case PRIO_USER:
 			if (!who)
@@ -954,10 +956,39 @@ asmlinkage long sys_times(struct tms __user * tbuf)
 	 */
 	if (tbuf) {
 		struct tms tmp;
-		tmp.tms_utime = jiffies_to_clock_t(current->utime);
-		tmp.tms_stime = jiffies_to_clock_t(current->stime);
-		tmp.tms_cutime = jiffies_to_clock_t(current->cutime);
-		tmp.tms_cstime = jiffies_to_clock_t(current->cstime);
+		struct task_struct *tsk = current;
+		struct task_struct *t;
+		unsigned long utime, stime, cutime, cstime;
+
+		read_lock(&tasklist_lock);
+		utime = tsk->signal->utime;
+		stime = tsk->signal->stime;
+		t = tsk;
+		do {
+			utime += t->utime;
+			stime += t->stime;
+			t = next_thread(t);
+		} while (t != tsk);
+
+		/*
+		 * While we have tasklist_lock read-locked, no dying thread
+		 * can be updating current->signal->[us]time.  Instead,
+		 * we got their counts included in the live thread loop.
+		 * However, another thread can come in right now and
+		 * do a wait call that updates current->signal->c[us]time.
+		 * To make sure we always see that pair updated atomically,
+		 * we take the siglock around fetching them.
+		 */
+		spin_lock_irq(&tsk->sighand->siglock);
+		cutime = tsk->signal->cutime;
+		cstime = tsk->signal->cstime;
+		spin_unlock_irq(&tsk->sighand->siglock);
+		read_unlock(&tasklist_lock);
+
+		tmp.tms_utime = jiffies_to_clock_t(utime);
+		tmp.tms_stime = jiffies_to_clock_t(stime);
+		tmp.tms_cutime = jiffies_to_clock_t(cutime);
+		tmp.tms_cstime = jiffies_to_clock_t(cstime);
 		if (copy_to_user(tbuf, &tmp, sizeof(struct tms)))
 			return -EFAULT;
 	}
@@ -981,14 +1012,17 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
 {
 	struct task_struct *p;
 	int err = -EINVAL;
+	pid_t rpgid;
 
 	if (!pid)
-		pid = current->pid;
+		pid = vx_map_pid(current->pid);
 	if (!pgid)
 		pgid = pid;
 	if (pgid < 0)
 		return -EINVAL;
 
+	rpgid = vx_rmap_pid(pgid);
+
 	/* From this point forward we keep holding onto the tasklist lock
 	 * so that our parent does not change from under us. -DaveM
 	 */
@@ -1022,24 +1056,23 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
 
 	if (pgid != pid) {
 		struct task_struct *p;
-		struct pid *pid;
-		struct list_head *l;
 
-		for_each_task_pid(pgid, PIDTYPE_PGID, p, l, pid)
+		do_each_task_pid(rpgid, PIDTYPE_PGID, p) {
 			if (p->signal->session == current->signal->session)
 				goto ok_pgid;
+		} while_each_task_pid(rpgid, PIDTYPE_PGID, p);
 		goto out;
 	}
 
 ok_pgid:
-	err = security_task_setpgid(p, pgid);
+	err = security_task_setpgid(p, rpgid);
 	if (err)
 		goto out;
 
-	if (process_group(p) != pgid) {
+	if (process_group(p) != rpgid) {
 		detach_pid(p, PIDTYPE_PGID);
-		p->signal->pgrp = pgid;
-		attach_pid(p, PIDTYPE_PGID, pgid);
+		p->signal->pgrp = rpgid;
+		attach_pid(p, PIDTYPE_PGID, rpgid);
 	}
 
 	err = 0;
@@ -1052,7 +1085,7 @@ out:
 asmlinkage long sys_getpgid(pid_t pid)
 {
 	if (!pid) {
-		return process_group(current);
+		return vx_rmap_pid(process_group(current));
 	} else {
 		int retval;
 		struct task_struct *p;
@@ -1064,7 +1097,7 @@ asmlinkage long sys_getpgid(pid_t pid)
 		if (p) {
 			retval = security_task_getpgid(p);
 			if (!retval)
-				retval = process_group(p);
+				retval = vx_rmap_pid(process_group(p));
 		}
 		read_unlock(&tasklist_lock);
 		return retval;
@@ -1546,44 +1579,86 @@ asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit __user *rlim)
  * a lot simpler!  (Which we're not doing right now because we're not
  * measuring them yet).
  *
- * This is SMP safe.  Either we are called from sys_getrusage on ourselves
- * below (we know we aren't going to exit/disappear and only we change our
- * rusage counters), or we are called from wait4() on a process which is
- * either stopped or zombied.  In the zombied case the task won't get
- * reaped till shortly after the call to getrusage(), in both cases the
- * task being examined is in a frozen state so the counters won't change.
+ * This expects to be called with tasklist_lock read-locked or better,
+ * and the siglock not locked.  It may momentarily take the siglock.
+ *
+ * When sampling multiple threads for RUSAGE_SELF, under SMP we might have
+ * races with threads incrementing their own counters.  But since word
+ * reads are atomic, we either get new values or old values and we don't
+ * care which for the sums.  We always take the siglock to protect reading
+ * the c* fields from p->signal from races with exit.c updating those
+ * fields when reaping, so a sample either gets all the additions of a
+ * given child after it's reaped, or none so this sample is before reaping.
  */
-int getrusage(struct task_struct *p, int who, struct rusage __user *ru)
+
+void k_getrusage(struct task_struct *p, int who, struct rusage *r)
 {
-	struct rusage r;
+	struct task_struct *t;
+	unsigned long flags;
+	unsigned long utime, stime;
+
+	memset((char *) r, 0, sizeof *r);
+
+	if (unlikely(!p->signal))
+		return;
 
-	memset((char *) &r, 0, sizeof(r));
 	switch (who) {
-		case RUSAGE_SELF:
-			jiffies_to_timeval(p->utime, &r.ru_utime);
-			jiffies_to_timeval(p->stime, &r.ru_stime);
-			r.ru_nvcsw = p->nvcsw;
-			r.ru_nivcsw = p->nivcsw;
-			r.ru_minflt = p->min_flt;
-			r.ru_majflt = p->maj_flt;
-			break;
 		case RUSAGE_CHILDREN:
-			jiffies_to_timeval(p->cutime, &r.ru_utime);
-			jiffies_to_timeval(p->cstime, &r.ru_stime);
-			r.ru_nvcsw = p->cnvcsw;
-			r.ru_nivcsw = p->cnivcsw;
-			r.ru_minflt = p->cmin_flt;
-			r.ru_majflt = p->cmaj_flt;
+			spin_lock_irqsave(&p->sighand->siglock, flags);
+			utime = p->signal->cutime;
+			stime = p->signal->cstime;
+			r->ru_nvcsw = p->signal->cnvcsw;
+			r->ru_nivcsw = p->signal->cnivcsw;
+			r->ru_minflt = p->signal->cmin_flt;
+			r->ru_majflt = p->signal->cmaj_flt;
+			spin_unlock_irqrestore(&p->sighand->siglock, flags);
+			jiffies_to_timeval(utime, &r->ru_utime);
+			jiffies_to_timeval(stime, &r->ru_stime);
 			break;
-		default:
-			jiffies_to_timeval(p->utime + p->cutime, &r.ru_utime);
-			jiffies_to_timeval(p->stime + p->cstime, &r.ru_stime);
-			r.ru_nvcsw = p->nvcsw + p->cnvcsw;
-			r.ru_nivcsw = p->nivcsw + p->cnivcsw;
-			r.ru_minflt = p->min_flt + p->cmin_flt;
-			r.ru_majflt = p->maj_flt + p->cmaj_flt;
+		case RUSAGE_SELF:
+			spin_lock_irqsave(&p->sighand->siglock, flags);
+			utime = stime = 0;
+			goto sum_group;
+		case RUSAGE_BOTH:
+			spin_lock_irqsave(&p->sighand->siglock, flags);
+			utime = p->signal->cutime;
+			stime = p->signal->cstime;
+			r->ru_nvcsw = p->signal->cnvcsw;
+			r->ru_nivcsw = p->signal->cnivcsw;
+			r->ru_minflt = p->signal->cmin_flt;
+			r->ru_majflt = p->signal->cmaj_flt;
+		sum_group:
+			utime += p->signal->utime;
+			stime += p->signal->stime;
+			r->ru_nvcsw += p->signal->nvcsw;
+			r->ru_nivcsw += p->signal->nivcsw;
+			r->ru_minflt += p->signal->min_flt;
+			r->ru_majflt += p->signal->maj_flt;
+			t = p;
+			do {
+				utime += t->utime;
+				stime += t->stime;
+				r->ru_nvcsw += t->nvcsw;
+				r->ru_nivcsw += t->nivcsw;
+				r->ru_minflt += t->min_flt;
+				r->ru_majflt += t->maj_flt;
+				t = next_thread(t);
+			} while (t != p);
+			spin_unlock_irqrestore(&p->sighand->siglock, flags);
+			jiffies_to_timeval(utime, &r->ru_utime);
+			jiffies_to_timeval(stime, &r->ru_stime);
 			break;
+		default:
+			BUG();
 	}
+}
+
+int getrusage(struct task_struct *p, int who, struct rusage __user *ru)
+{
+	struct rusage r;
+	read_lock(&tasklist_lock);
+	k_getrusage(p, who, &r);
+	read_unlock(&tasklist_lock);
 	return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
 }
 
@@ -1673,6 +1748,17 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
 			}
 			current->keep_capabilities = arg2;
 			break;
+		case PR_SET_NAME: {
+			struct task_struct *me = current;
+			unsigned char ncomm[sizeof(me->comm)];
+
+			ncomm[sizeof(me->comm)-1] = 0;
+			if (strncpy_from_user(ncomm, (char __user *)arg2,
+						sizeof(me->comm)-1) < 0)
+				return -EFAULT;
+			set_task_comm(me, ncomm);
+			return 0;
+		}
 		default:
 			error = -EINVAL;
 			break;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 608fbac3e..7c25a032b 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -42,6 +42,7 @@
 #include <linux/dcache.h>
 
 #include <asm/uaccess.h>
+#include <asm/processor.h>
 
 #ifdef CONFIG_ROOT_NFS
 #include <linux/nfs_fs.h>
@@ -65,6 +66,12 @@ extern int min_free_kbytes;
 extern int printk_ratelimit_jiffies;
 extern int printk_ratelimit_burst;
 
+#if defined(CONFIG_X86_LOCAL_APIC) && defined(__i386__)
+int unknown_nmi_panic;
+extern int proc_unknown_nmi_panic(ctl_table *, int, struct file *,
+				  void __user *, size_t *, loff_t *);
+#endif
+
 /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
 static int maxolduid = 65535;
 static int minolduid;
@@ -111,12 +118,6 @@ extern int sysctl_userprocess_debug;
 
 extern int sysctl_hz_timer;
 
-#if defined(CONFIG_PPC32) && defined(CONFIG_6xx)
-extern unsigned long powersave_nap;
-int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
-		  void __user *buffer, size_t *lenp, loff_t *ppos);
-#endif
-
 #ifdef CONFIG_BSD_PROCESS_ACCT
 extern int acct_parm[];
 #endif
@@ -144,6 +145,10 @@ extern ctl_table random_table[];
 extern ctl_table pty_table[];
 #endif
 
+#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
+int sysctl_legacy_va_layout;
+#endif
+
 /* /proc declarations: */
 
 #ifdef CONFIG_PROC_FS
@@ -290,7 +295,7 @@ static ctl_table kern_table[] = {
 		.procname	= "tainted",
 		.data		= &tainted,
 		.maxlen		= sizeof(int),
-		.mode		= 0644,
+		.mode		= 0444,
 		.proc_handler	= &proc_dointvec,
 	},
 	{
@@ -355,22 +360,6 @@ static ctl_table kern_table[] = {
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
 	},
-#endif
-#if defined(CONFIG_PPC32) && defined(CONFIG_6xx)
-	{
-		.ctl_name	= KERN_PPC_POWERSAVE_NAP,
-		.procname	= "powersave-nap",
-		.data		= &powersave_nap,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-	},
-	{
-		.ctl_name	= KERN_PPC_L2CR,
-		.procname	= "l2cr",
-		.mode		= 0644,
-		.proc_handler	= &proc_dol2crvec,
-	},
 #endif
 	{
 		.ctl_name	= KERN_CTLALTDEL,
@@ -630,6 +619,16 @@ static ctl_table kern_table[] = {
 		.mode		= 0444,
 		.proc_handler	= &proc_dointvec,
 	},
+#if defined(CONFIG_X86_LOCAL_APIC) && defined(__i386__)
+	{
+		.ctl_name       = KERN_UNKNOWN_NMI_PANIC,
+		.procname       = "unknown_nmi_panic",
+		.data           = &unknown_nmi_panic,
+		.maxlen         = sizeof (int),
+		.mode           = 0644,
+		.proc_handler   = &proc_unknown_nmi_panic,
+	},
+#endif
 	{ .ctl_name = 0 }
 };
 
@@ -799,6 +798,18 @@ static ctl_table vm_table[] = {
 		.strategy	= &sysctl_intvec,
 		.extra1		= &zero,
 	},
+#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
+	{
+		.ctl_name	= VM_LEGACY_VA_LAYOUT,
+		.procname	= "legacy_va_layout",
+		.data		= &sysctl_legacy_va_layout,
+		.maxlen		= sizeof(sysctl_legacy_va_layout),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &zero,
+	},
+#endif
 	{ .ctl_name = 0 }
 };
 
diff --git a/kernel/time.c b/kernel/time.c
index 68c22f2bf..167a72a07 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -22,6 +22,9 @@
  *	"A Kernel Model for Precision Timekeeping" by Dave Mills
  *	Allow time_constant larger than MAXTC(6) for NTP v4 (MAXTC == 10)
  *	(Even though the technical memorandum forbids it)
+ * 2004-07-14	 Christoph Lameter
+ *	Added getnstimeofday to allow the posix timer functions to return
+ *	with nanosecond accuracy
  */
 
 #include <linux/module.h>
@@ -123,7 +126,7 @@ inline static void warp_clock(void)
 	write_seqlock_irq(&xtime_lock);
 	wall_to_monotonic.tv_sec -= sys_tz.tz_minuteswest * 60;
 	xtime.tv_sec += sys_tz.tz_minuteswest * 60;
-	time_interpolator_update(sys_tz.tz_minuteswest * 60 * NSEC_PER_SEC);
+	time_interpolator_reset();
 	write_sequnlock_irq(&xtime_lock);
 	clock_was_set();
 }
@@ -421,6 +424,103 @@ struct timespec current_kernel_time(void)
 
 EXPORT_SYMBOL(current_kernel_time);
 
+#ifdef CONFIG_TIME_INTERPOLATION
+void getnstimeofday (struct timespec *tv)
+{
+	unsigned long seq,sec,nsec;
+
+	do {
+		seq = read_seqbegin(&xtime_lock);
+		sec = xtime.tv_sec;
+		nsec = xtime.tv_nsec+time_interpolator_get_offset();
+	} while (unlikely(read_seqretry(&xtime_lock, seq)));
+
+	while (unlikely(nsec >= NSEC_PER_SEC)) {
+		nsec -= NSEC_PER_SEC;
+		++sec;
+	}
+	tv->tv_sec = sec;
+	tv->tv_nsec = nsec;
+}
+
+int do_settimeofday (struct timespec *tv)
+{
+	time_t wtm_sec, sec = tv->tv_sec;
+	long wtm_nsec, nsec = tv->tv_nsec;
+
+	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+		return -EINVAL;
+
+	write_seqlock_irq(&xtime_lock);
+	{
+		/*
+		 * This is revolting. We need to set "xtime" correctly. However, the value
+		 * in this location is the value at the most recent update of wall time.
+		 * Discover what correction gettimeofday would have done, and then undo
+		 * it!
+		 */
+		nsec -= time_interpolator_get_offset();
+
+		wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+		wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+		set_normalized_timespec(&xtime, sec, nsec);
+		set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+
+		time_adjust = 0;		/* stop active adjtime() */
+		time_status |= STA_UNSYNC;
+		time_maxerror = NTP_PHASE_LIMIT;
+		time_esterror = NTP_PHASE_LIMIT;
+		time_interpolator_reset();
+	}
+	write_sequnlock_irq(&xtime_lock);
+	clock_was_set();
+	return 0;
+}
+
+EXPORT_SYMBOL(do_settimeofday);
+
+void do_gettimeofday (struct timeval *tv)
+{
+	unsigned long seq, nsec, usec, sec, offset;
+	do {
+		seq = read_seqbegin(&xtime_lock);
+		offset = time_interpolator_get_offset();
+		sec = xtime.tv_sec;
+		nsec = xtime.tv_nsec;
+	} while (unlikely(read_seqretry(&xtime_lock, seq)));
+
+	usec = (nsec + offset) / 1000;
+
+	while (unlikely(usec >= USEC_PER_SEC)) {
+		usec -= USEC_PER_SEC;
+		++sec;
+	}
+
+	tv->tv_sec = sec;
+	tv->tv_usec = usec;
+}
+
+EXPORT_SYMBOL(do_gettimeofday);
+
+
+#else
+/*
+ * Simulate gettimeofday using do_gettimeofday which only allows a timeval
+ * and therefore only yields usec accuracy
+ */
+void getnstimeofday(struct timespec *tv)
+{
+	struct timeval x;
+
+	do_gettimeofday(&x);
+	tv->tv_sec = x.tv_sec;
+	tv->tv_nsec = x.tv_usec * NSEC_PER_USEC;
+}
+#endif
+
+EXPORT_SYMBOL(getnstimeofday);
+
 #if (BITS_PER_LONG < 64)
 u64 get_jiffies_64(void)
 {
diff --git a/kernel/timer.c b/kernel/timer.c
index f7d42e8ec..69719eecb 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -31,7 +31,6 @@
 #include <linux/time.h>
 #include <linux/jiffies.h>
 #include <linux/cpu.h>
-#include <linux/vs_base.h>
 #include <linux/vs_cvirt.h>
 #include <linux/vserver/sched.h>
 
@@ -39,6 +38,13 @@
 #include <asm/unistd.h>
 #include <asm/div64.h>
 #include <asm/timex.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_TIME_INTERPOLATION
+static void time_interpolator_update(long delta_nsec);
+#else
+#define time_interpolator_update(x)
+#endif
 
 /*
  * per-CPU timer vector definitions:
@@ -236,6 +242,8 @@ void add_timer_on(struct timer_list *timer, int cpu)
 	spin_unlock_irqrestore(&base->lock, flags);
 }
 
+EXPORT_SYMBOL(add_timer_on);
+
 /***
  * mod_timer - modify a timer's timeout
  * @timer: the timer to be modified
@@ -622,6 +630,9 @@ static void second_overflow(void)
 	if (xtime.tv_sec % 86400 == 0) {
 	    xtime.tv_sec--;
 	    wall_to_monotonic.tv_sec++;
+	    /* The timer interpolator will make time change gradually instead
+	     * of an immediate jump by one second.
+	     */
 	    time_interpolator_update(-NSEC_PER_SEC);
 	    time_state = TIME_OOP;
 	    clock_was_set();
@@ -633,6 +644,7 @@ static void second_overflow(void)
 	if ((xtime.tv_sec + 1) % 86400 == 0) {
 	    xtime.tv_sec++;
 	    wall_to_monotonic.tv_sec--;
+	    /* Use of time interpolator for a gradual change of time */
 	    time_interpolator_update(NSEC_PER_SEC);
 	    time_state = TIME_WAIT;
 	    clock_was_set();
@@ -999,7 +1011,7 @@ asmlinkage unsigned long sys_alarm(unsigned int seconds)
  */
 asmlinkage long sys_getpid(void)
 {
-	return vx_map_tgid(current->vx_info, current->tgid);
+	return vx_map_tgid(current->tgid);
 }
 
 /*
@@ -1043,7 +1055,7 @@ asmlinkage long sys_getppid(void)
 #endif
 		break;
 	}
-	return vx_map_tgid(current->vx_info, pid);
+	return vx_map_pid(pid);
 }
 
 asmlinkage long sys_getuid(void)
@@ -1244,8 +1256,7 @@ asmlinkage long sys_sysinfo(struct sysinfo __user *info)
 		 * too.
 		 */
 
-		do_gettimeofday((struct timeval *)&tp);
-		tp.tv_nsec *= NSEC_PER_USEC;
+		getnstimeofday(&tp);
 		tp.tv_sec += wall_to_monotonic.tv_sec;
 		tp.tv_nsec += wall_to_monotonic.tv_nsec;
 		if (tp.tv_nsec - NSEC_PER_SEC >= 0) {
@@ -1434,15 +1445,112 @@ void __init init_timers(void)
 }
 
 #ifdef CONFIG_TIME_INTERPOLATION
-volatile unsigned long last_nsec_offset;
-#ifndef __HAVE_ARCH_CMPXCHG
-spinlock_t last_nsec_offset_lock = SPIN_LOCK_UNLOCKED;
-#endif
 
 struct time_interpolator *time_interpolator;
 static struct time_interpolator *time_interpolator_list;
 static spinlock_t time_interpolator_lock = SPIN_LOCK_UNLOCKED;
 
+static inline unsigned long time_interpolator_get_cycles(unsigned int src)
+{
+	unsigned long (*x)(void);
+
+	switch (src)
+	{
+		case TIME_SOURCE_FUNCTION:
+			x = time_interpolator->addr;
+			return x();
+
+		case TIME_SOURCE_MMIO64	:
+			return readq(time_interpolator->addr);
+
+		case TIME_SOURCE_MMIO32	:
+			return readl(time_interpolator->addr);
+		default: return get_cycles();
+	}
+}
+
+static inline unsigned long time_interpolator_get_counter(void)
+{
+	unsigned int src = time_interpolator->source;
+
+	if (time_interpolator->jitter)
+	{
+		unsigned long lcycle;
+		unsigned long now;
+
+		do {
+			lcycle = time_interpolator->last_cycle;
+			now = time_interpolator_get_cycles(src);
+			if (lcycle && time_after(lcycle, now)) return lcycle;
+			/* Keep track of the last timer value returned. The use of cmpxchg here
+			 * will cause contention in an SMP environment.
+			 */
+		} while (unlikely(cmpxchg(&time_interpolator->last_cycle, lcycle, now) != lcycle));
+		return now;
+	}
+	else
+		return time_interpolator_get_cycles(src);
+}
+
+void time_interpolator_reset(void)
+{
+	time_interpolator->offset = 0;
+	time_interpolator->last_counter = time_interpolator_get_counter();
+}
+
+unsigned long time_interpolator_resolution(void)
+{
+	if (time_interpolator->frequency < NSEC_PER_SEC)
+		return NSEC_PER_SEC / time_interpolator->frequency;
+	else
+		return 1;
+}
+
+#define GET_TI_NSECS(count,i) ((((count) - i->last_counter) * i->nsec_per_cyc) >> i->shift)
+
+unsigned long time_interpolator_get_offset(void)
+{
+	return time_interpolator->offset +
+		GET_TI_NSECS(time_interpolator_get_counter(), time_interpolator);
+}
+
+static void time_interpolator_update(long delta_nsec)
+{
+	unsigned long counter = time_interpolator_get_counter();
+	unsigned long offset = time_interpolator->offset + GET_TI_NSECS(counter, time_interpolator);
+
+	/* The interpolator compensates for late ticks by accumulating
+         * the late time in time_interpolator->offset. A tick earlier than
+	 * expected will lead to a reset of the offset and a corresponding
+	 * jump of the clock forward. Again this only works if the
+	 * interpolator clock is running slightly slower than the regular clock
+	 * and the tuning logic insures that.
+         */
+
+	if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)
+		time_interpolator->offset = offset - delta_nsec;
+	else {
+		time_interpolator->skips++;
+		time_interpolator->ns_skipped += delta_nsec - offset;
+		time_interpolator->offset = 0;
+	}
+	time_interpolator->last_counter = counter;
+
+	/* Tuning logic for time interpolator invoked every minute or so.
+	 * Decrease interpolator clock speed if no skips occurred and an offset is carried.
+	 * Increase interpolator clock speed if we skip too much time.
+	 */
+	if (jiffies % INTERPOLATOR_ADJUST == 0)
+	{
+		if (time_interpolator->skips == 0 && time_interpolator->offset > TICK_NSEC)
+			time_interpolator->nsec_per_cyc--;
+		if (time_interpolator->ns_skipped > INTERPOLATOR_MAX_SKIP && time_interpolator->offset == 0)
+			time_interpolator->nsec_per_cyc++;
+		time_interpolator->skips = 0;
+		time_interpolator->ns_skipped = 0;
+	}
+}
+
 static inline int
 is_better_time_interpolator(struct time_interpolator *new)
 {
@@ -1455,11 +1563,16 @@ is_better_time_interpolator(struct time_interpolator *new)
 void
 register_time_interpolator(struct time_interpolator *ti)
 {
+	unsigned long flags;
+
+	ti->nsec_per_cyc = (NSEC_PER_SEC << ti->shift) / ti->frequency;
 	spin_lock(&time_interpolator_lock);
-	write_seqlock_irq(&xtime_lock);
-	if (is_better_time_interpolator(ti))
+	write_seqlock_irqsave(&xtime_lock, flags);
+	if (is_better_time_interpolator(ti)) {
 		time_interpolator = ti;
-	write_sequnlock_irq(&xtime_lock);
+		time_interpolator_reset();
+	}
+	write_sequnlock_irqrestore(&xtime_lock, flags);
 
 	ti->next = time_interpolator_list;
 	time_interpolator_list = ti;
@@ -1470,6 +1583,7 @@ void
 unregister_time_interpolator(struct time_interpolator *ti)
 {
 	struct time_interpolator *curr, **prev;
+	unsigned long flags;
 
 	spin_lock(&time_interpolator_lock);
 	prev = &time_interpolator_list;
@@ -1481,7 +1595,7 @@ unregister_time_interpolator(struct time_interpolator *ti)
 		prev = &curr->next;
 	}
 
-	write_seqlock_irq(&xtime_lock);
+	write_seqlock_irqsave(&xtime_lock, flags);
 	if (ti == time_interpolator) {
 		/* we lost the best time-interpolator: */
 		time_interpolator = NULL;
@@ -1489,8 +1603,9 @@ unregister_time_interpolator(struct time_interpolator *ti)
 		for (curr = time_interpolator_list; curr; curr = curr->next)
 			if (is_better_time_interpolator(curr))
 				time_interpolator = curr;
+		time_interpolator_reset();
 	}
-	write_sequnlock_irq(&xtime_lock);
+	write_sequnlock_irqrestore(&xtime_lock, flags);
 	spin_unlock(&time_interpolator_lock);
 }
 #endif /* CONFIG_TIME_INTERPOLATION */
@@ -1511,3 +1626,19 @@ void msleep(unsigned int msecs)
 
 EXPORT_SYMBOL(msleep);
 
+/**
+ * msleep_interruptible - sleep waiting for waitqueue interruptions
+ * @msecs: Time in milliseconds to sleep for
+ */
+unsigned long msleep_interruptible(unsigned int msecs)
+{
+	unsigned long timeout = msecs_to_jiffies(msecs);
+
+	while (timeout && !signal_pending(current)) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		timeout = schedule_timeout(timeout);
+	}
+	return jiffies_to_msecs(timeout);
+}
+
+EXPORT_SYMBOL(msleep_interruptible);
diff --git a/kernel/user.c b/kernel/user.c
index 850b0aeed..5e6a22172 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -32,7 +32,8 @@ struct user_struct root_user = {
 	.processes	= ATOMIC_INIT(1),
 	.files		= ATOMIC_INIT(0),
 	.sigpending	= ATOMIC_INIT(0),
-	.mq_bytes	= 0
+	.mq_bytes	= 0,
+	.locked_shm     = 0,
 };
 
 /*
@@ -114,6 +115,7 @@ struct user_struct * alloc_uid(xid_t xid, uid_t uid)
 		atomic_set(&new->sigpending, 0);
 
 		new->mq_bytes = 0;
+		new->locked_shm = 0;
 
 		/*
 		 * Before adding this, check whether we raced
diff --git a/kernel/vserver/Kconfig b/kernel/vserver/Kconfig
index 5160a0135..aea29b20a 100644
--- a/kernel/vserver/Kconfig
+++ b/kernel/vserver/Kconfig
@@ -25,6 +25,16 @@ config	VSERVER_HARDCPU
 	help
 	  Activate the Hard CPU Limits
 
+config	VSERVER_HARDCPU_IDLE
+	bool	"Limit the IDLE task"
+	depends on VSERVER_HARDCPU
+	default n
+	help
+	  Limit the idle slices, so the the next context
+	  will be scheduled as soon as possible.
+	  might improve interactivity/latency but
+	  increases scheduling overhead.
+
 choice
 	prompt	"Persistent Inode Context Tagging"
 	default	INOXID_UGID24
diff --git a/kernel/vserver/context.c b/kernel/vserver/context.c
index 120ac1abc..c897a8697 100644
--- a/kernel/vserver/context.c
+++ b/kernel/vserver/context.c
@@ -37,7 +37,7 @@
 static struct vx_info *__alloc_vx_info(xid_t xid)
 {
 	struct vx_info *new = NULL;
-	
+
 	vxdprintk(VXD_CBIT(xid, 0), "alloc_vx_info(%d)*", xid);
 
 	/* would this benefit from a slab cache? */
@@ -51,6 +51,10 @@ static struct vx_info *__alloc_vx_info(xid_t xid)
 	INIT_HLIST_NODE(&new->vx_hlist);
 	atomic_set(&new->vx_refcnt, 0);
 	atomic_set(&new->vx_usecnt, 0);
+	new->vx_parent = NULL;
+	new->vx_state = 0;
+	new->vx_lock = SPIN_LOCK_UNLOCKED;
+	init_waitqueue_head(&new->vx_exit);
 
 	/* rest of init goes here */
 	vx_info_init_limit(&new->limit);
@@ -58,6 +62,7 @@ static struct vx_info *__alloc_vx_info(xid_t xid)
 	vx_info_init_cvirt(&new->cvirt);
 	vx_info_init_cacct(&new->cacct);
 
+
 	new->vx_flags = VXF_STATE_SETUP|VXF_STATE_INIT;
 	new->vx_bcaps = CAP_INIT_EFF_SET;
 	new->vx_ccaps = 0;
@@ -79,26 +84,79 @@ static void __dealloc_vx_info(struct vx_info *vxi)
 	vxi->vx_hlist.next = LIST_POISON1;
 	vxi->vx_id = -1;
 
-	if (vxi->vx_namespace)
-		put_namespace(vxi->vx_namespace);
-	if (vxi->vx_fs)
-		put_fs_struct(vxi->vx_fs);
-	
 	vx_info_exit_limit(&vxi->limit);
 	vx_info_exit_sched(&vxi->sched);
 	vx_info_exit_cvirt(&vxi->cvirt);
 	vx_info_exit_cacct(&vxi->cacct);
-	
+
+
 	BUG_ON(atomic_read(&vxi->vx_usecnt));
 	BUG_ON(atomic_read(&vxi->vx_refcnt));
 
+	BUG_ON(vx_info_state(vxi, VXS_HASHED));
+	// BUG_ON(!vx_state(vxi, VXS_DEFUNCT));
+
+	vxi->vx_state |= VXS_RELEASED;
 	kfree(vxi);
 }
 
+static inline int __free_vx_info(struct vx_info *vxi)
+{
+	int usecnt, refcnt;
+
+	BUG_ON(!vxi);
+
+	usecnt = atomic_read(&vxi->vx_usecnt);
+	BUG_ON(usecnt < 0);
+
+	refcnt = atomic_read(&vxi->vx_refcnt);
+	BUG_ON(refcnt < 0);
+
+	if (!usecnt)
+		__dealloc_vx_info(vxi);
+	return usecnt;
+}
+
+#if 0
+
+static void __rcu_free_vx_info(struct rcu_head *head)
+{
+	struct vx_info *vxi = container_of(head, struct vx_info, vx_rcu);
+
+	BUG_ON(!head);
+	vxdprintk(VXD_CBIT(xid, 3),
+		"rcu_free_vx_info(%p): uc=%d", vxi,
+		atomic_read(&vxi->vx_usecnt));
+
+	__free_vx_info(vxi);
+}
+
+#endif
+
+void free_vx_info(struct vx_info *vxi)
+{
+	struct namespace *namespace;
+	struct fs_struct *fs;
+
+	/* context shutdown is mandatory */
+	// BUG_ON(vxi->vx_state != VXS_SHUTDOWN);
+
+	namespace = xchg(&vxi->vx_namespace, NULL);
+	fs = xchg(&vxi->vx_fs, NULL);
+
+	if (namespace)
+		put_namespace(namespace);
+	if (fs)
+		put_fs_struct(fs);
+
+	BUG_ON(__free_vx_info(vxi));
+	// call_rcu(&i->vx_rcu, __rcu_free_vx_info);
+}
+
 
 /*	hash table for vx_info hash */
 
-#define	VX_HASH_SIZE	13
+#define VX_HASH_SIZE	13
 
 struct hlist_head vx_info_hash[VX_HASH_SIZE];
 
@@ -120,10 +178,11 @@ static inline unsigned int __hashval(xid_t xid)
 static inline void __hash_vx_info(struct vx_info *vxi)
 {
 	struct hlist_head *head;
-	
+
 	vxdprintk(VXD_CBIT(xid, 4),
 		"__hash_vx_info: %p[#%d]", vxi, vxi->vx_id);
 	get_vx_info(vxi);
+	vxi->vx_state |= VXS_HASHED;
 	head = &vx_info_hash[__hashval(vxi->vx_id)];
 	hlist_add_head_rcu(&vxi->vx_hlist, head);
 }
@@ -137,6 +196,7 @@ static inline void __unhash_vx_info(struct vx_info *vxi)
 {
 	vxdprintk(VXD_CBIT(xid, 4),
 		"__unhash_vx_info: %p[#%d]", vxi, vxi->vx_id);
+	vxi->vx_state &= ~VXS_HASHED;
 	hlist_del_rcu(&vxi->vx_hlist);
 	put_vx_info(vxi);
 }
@@ -156,9 +216,9 @@ static inline struct vx_info *__lookup_vx_info(xid_t xid)
 		struct vx_info *vxi =
 			hlist_entry(pos, struct vx_info, vx_hlist);
 
-		if (vxi->vx_id == xid) {
+		if ((vxi->vx_id == xid) &&
+			vx_info_state(vxi, VXS_HASHED))
 			return vxi;
-		}
 	}
 	return NULL;
 }
@@ -173,7 +233,7 @@ static inline xid_t __vx_dynamic_id(void)
 {
 	static xid_t seq = MAX_S_CONTEXT;
 	xid_t barrier = seq;
-	
+
 	do {
 		if (++seq > MAX_S_CONTEXT)
 			seq = MIN_D_CONTEXT;
@@ -194,7 +254,7 @@ static inline xid_t __vx_dynamic_id(void)
 static struct vx_info * __loc_vx_info(int id, int *err)
 {
 	struct vx_info *new, *vxi = NULL;
-	
+
 	vxdprintk(VXD_CBIT(xid, 1), "loc_vx_info(%d)*", id);
 
 	if (!(new = __alloc_vx_info(id))) {
@@ -249,28 +309,6 @@ out_unlock:
 /*	exported stuff						*/
 
 
-
-void rcu_free_vx_info(struct rcu_head *head)
-{
-	struct vx_info *vxi = container_of(head, struct vx_info, vx_rcu);
-	int usecnt, refcnt;
-
-	BUG_ON(!vxi || !head);
-
-	usecnt = atomic_read(&vxi->vx_usecnt);
-	BUG_ON(usecnt < 0);
-
-	refcnt = atomic_read(&vxi->vx_refcnt);
-	BUG_ON(refcnt < 0);
-
-	vxdprintk(VXD_CBIT(xid, 3),
-		"rcu_free_vx_info(%p): uc=%d", vxi, usecnt);
-	if (!usecnt)
-		__dealloc_vx_info(vxi);
-	else
-		printk("!!! rcu didn't free\n");
-}
-
 void unhash_vx_info(struct vx_info *vxi)
 {
 	spin_lock(&vx_info_hash_lock);
@@ -280,13 +318,13 @@ void unhash_vx_info(struct vx_info *vxi)
 
 /*	locate_vx_info()
 
-	* search for a vx_info and get() it			
+	* search for a vx_info and get() it
 	* negative id means current				*/
 
 struct vx_info *locate_vx_info(int id)
 {
 	struct vx_info *vxi;
-	
+
 	if (id < 0) {
 		vxi = get_vx_info(current->vx_info);
 	} else {
@@ -331,10 +369,6 @@ struct vx_info *locate_or_create_vx_info(int id)
 
 #ifdef	CONFIG_PROC_FS
 
-#define hlist_for_each_rcu(pos, head) \
-        for (pos = (head)->first; pos && ({ prefetch(pos->next); 1;}); \
-		pos = pos->next, ({ smp_read_barrier_depends(); 0;}))
-
 int get_xid_list(int index, unsigned int *xids, int size)
 {
 	int hindex, nr_xids = 0;
@@ -351,7 +385,7 @@ int get_xid_list(int index, unsigned int *xids, int size)
 				continue;
 
 			vxi = hlist_entry(pos, struct vx_info, vx_hlist);
-			xids[nr_xids] = vxi->vx_id;			
+			xids[nr_xids] = vxi->vx_id;
 			if (++nr_xids >= size)
 				goto out;
 		}
@@ -365,7 +399,7 @@ out:
 int vx_migrate_user(struct task_struct *p, struct vx_info *vxi)
 {
 	struct user_struct *new_user, *old_user;
-	
+
 	if (!p || !vxi)
 		BUG();
 	new_user = alloc_uid(vxi->vx_id, p->uid);
@@ -397,7 +431,7 @@ void vx_mask_bcaps(struct task_struct *p)
 static inline int vx_nofiles_task(struct task_struct *tsk)
 {
 	struct files_struct *files = tsk->files;
-	const unsigned long *obptr;
+	unsigned long *obptr;
 	int count, total;
 
 	spin_lock(&files->file_lock);
@@ -443,7 +477,7 @@ int vx_migrate_task(struct task_struct *p, struct vx_info *vxi)
 {
 	struct vx_info *old_vxi;
 	int ret = 0;
-	
+
 	if (!p || !vxi)
 		BUG();
 
@@ -463,14 +497,18 @@ int vx_migrate_task(struct task_struct *p, struct vx_info *vxi)
 		nofiles = vx_nofiles_task(p);
 
 		if (old_vxi) {
-			atomic_dec(&old_vxi->cacct.nr_threads);
+			atomic_dec(&old_vxi->cvirt.nr_threads);
+			atomic_dec(&old_vxi->cvirt.nr_running);
 			atomic_dec(&old_vxi->limit.rcur[RLIMIT_NPROC]);
-			atomic_sub(nofiles, &old_vxi->limit.rcur[RLIMIT_NOFILE]);
+			/* FIXME: what about the struct files here? */
+			// atomic_sub(nofiles, &old_vxi->limit.rcur[RLIMIT_NOFILE]);
 			// atomic_sub(openfd, &old_vxi->limit.rcur[RLIMIT_OPENFD]);
-		}		
-		atomic_inc(&vxi->cacct.nr_threads);
+		}
+		atomic_inc(&vxi->cvirt.nr_threads);
+		atomic_inc(&vxi->cvirt.nr_running);
 		atomic_inc(&vxi->limit.rcur[RLIMIT_NPROC]);
-		atomic_add(nofiles, &vxi->limit.rcur[RLIMIT_NOFILE]);
+		/* FIXME: what about the struct files here? */
+		// atomic_add(nofiles, &vxi->limit.rcur[RLIMIT_NOFILE]);
 		// atomic_add(openfd, &vxi->limit.rcur[RLIMIT_OPENFD]);
 
 		vxdprintk(VXD_CBIT(xid, 5),
@@ -497,10 +535,14 @@ int vx_set_init(struct vx_info *vxi, struct task_struct *p)
 {
 	if (!vxi)
 		return -EINVAL;
-        if (vxi->vx_initpid)
-                return -EPERM;
+	if (vxi->vx_initpid)
+		return -EPERM;
+
+	vxdprintk(VXD_CBIT(xid, 6),
+		"vx_set_init(%p[#%d],%p[#%d,%d,%d])",
+		vxi, vxi->vx_id, p, p->xid, p->pid, p->tgid);
 
-        vxi->vx_initpid = p->tgid;
+	vxi->vx_initpid = p->tgid;
 	return 0;
 }
 
@@ -514,22 +556,22 @@ int vx_set_init(struct vx_info *vxi, struct task_struct *p)
 
 int vc_task_xid(uint32_t id, void __user *data)
 {
-        xid_t xid;
-
-        if (id) {
-                struct task_struct *tsk;
-
-                if (!vx_check(0, VX_ADMIN|VX_WATCH))
-                        return -EPERM;
-
-                read_lock(&tasklist_lock);
-                tsk = find_task_by_pid(id);
-                xid = (tsk) ? tsk->xid : -ESRCH;
-                read_unlock(&tasklist_lock);
-        }
-        else
-                xid = current->xid;
-        return xid;
+	xid_t xid;
+
+	if (id) {
+		struct task_struct *tsk;
+
+		if (!vx_check(0, VX_ADMIN|VX_WATCH))
+			return -EPERM;
+
+		read_lock(&tasklist_lock);
+		tsk = find_task_by_real_pid(id);
+		xid = (tsk) ? tsk->xid : -ESRCH;
+		read_unlock(&tasklist_lock);
+	}
+	else
+		xid = current->xid;
+	return xid;
 }
 
 
@@ -593,7 +635,7 @@ out_put:
 int vc_ctx_migrate(uint32_t id, void __user *data)
 {
 	struct vx_info *vxi;
-	
+
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
@@ -712,7 +754,8 @@ int vc_set_ccaps(uint32_t id, void __user *data)
 
 #include <linux/module.h>
 
-EXPORT_SYMBOL_GPL(rcu_free_vx_info);
+// EXPORT_SYMBOL_GPL(rcu_free_vx_info);
+EXPORT_SYMBOL_GPL(free_vx_info);
 EXPORT_SYMBOL_GPL(vx_info_hash_lock);
 EXPORT_SYMBOL_GPL(unhash_vx_info);
 
diff --git a/kernel/vserver/cvirt.c b/kernel/vserver/cvirt.c
index a5192211f..6b5f10082 100644
--- a/kernel/vserver/cvirt.c
+++ b/kernel/vserver/cvirt.c
@@ -24,13 +24,10 @@
 void vx_vsi_uptime(struct timespec *uptime, struct timespec *idle)
 {
 	struct vx_info *vxi = current->vx_info;
-	struct timeval bias;
-
-	jiffies_to_timeval(vxi->cvirt.bias_jiffies - INITIAL_JIFFIES, &bias);
 
 	set_normalized_timespec(uptime,
-		uptime->tv_sec - bias.tv_sec,
-		uptime->tv_nsec - bias.tv_usec*1000);
+		uptime->tv_sec - vxi->cvirt.bias_uptime.tv_sec,
+		uptime->tv_nsec - vxi->cvirt.bias_uptime.tv_nsec);
 	if (!idle)
 		return;
 	set_normalized_timespec(idle,
@@ -44,3 +41,44 @@ uint64_t vx_idle_jiffies()
 	return init_task.utime + init_task.stime;
 }
 
+
+
+static inline uint32_t __update_loadavg(uint32_t load,
+	int wsize, int delta, int n)
+{
+	unsigned long long calc;
+
+	/* just set it to n */
+	if (unlikely(delta >= wsize))
+		return (n << FSHIFT);
+
+	calc = (delta * n) << FSHIFT;
+	calc += (wsize - delta) * load;
+	do_div(calc, wsize);
+	return calc;
+}
+
+
+void vx_update_load(struct vx_info *vxi)
+{
+	uint32_t now, last, delta;
+
+	spin_lock(&vxi->cvirt.load_lock);
+
+	now = jiffies;
+	last = vxi->cvirt.load_last;
+	delta = now - last;
+
+	vxi->cvirt.load[0] = __update_loadavg(vxi->cvirt.load[0],
+		60*HZ, delta, atomic_read(&vxi->cvirt.nr_running));
+	vxi->cvirt.load[1] = __update_loadavg(vxi->cvirt.load[1],
+		5*60*HZ, delta, atomic_read(&vxi->cvirt.nr_running));
+	vxi->cvirt.load[2] = __update_loadavg(vxi->cvirt.load[2],
+		15*60*HZ, delta, atomic_read(&vxi->cvirt.nr_running));
+
+	vxi->cvirt.load_last = now;
+	spin_unlock(&vxi->cvirt.load_lock);
+}
+
+
+
diff --git a/kernel/vserver/dlimit.c b/kernel/vserver/dlimit.c
index d9478ddd8..11da06d49 100644
--- a/kernel/vserver/dlimit.c
+++ b/kernel/vserver/dlimit.c
@@ -30,7 +30,7 @@
 static struct dl_info *__alloc_dl_info(struct super_block *sb, xid_t xid)
 {
 	struct dl_info *new = NULL;
-	
+
 	vxdprintk(VXD_CBIT(dlim, 5),
 		"alloc_dl_info(%p,%d)*", sb, xid);
 
@@ -77,7 +77,7 @@ static void __dealloc_dl_info(struct dl_info *dli)
 
 /*	hash table for dl_info hash */
 
-#define	DL_HASH_SIZE	13
+#define DL_HASH_SIZE	13
 
 struct hlist_head dl_info_hash[DL_HASH_SIZE];
 
@@ -99,7 +99,7 @@ static inline unsigned int __hashval(struct super_block *sb, xid_t xid)
 static inline void __hash_dl_info(struct dl_info *dli)
 {
 	struct hlist_head *head;
-	
+
 	vxdprintk(VXD_CBIT(dlim, 6),
 		"__hash_dl_info: %p[#%d]", dli, dli->dl_xid);
 	get_dl_info(dli);
@@ -121,11 +121,6 @@ static inline void __unhash_dl_info(struct dl_info *dli)
 }
 
 
-#define hlist_for_each_rcu(pos, head) \
-	for (pos = (head)->first; pos && ({ prefetch(pos->next); 1;}); \
-		pos = pos->next, ({ smp_read_barrier_depends(); 0;}))
-
-
 /*	__lookup_dl_info()
 
 	* requires the rcu_read_lock()
@@ -150,14 +145,14 @@ static inline struct dl_info *__lookup_dl_info(struct super_block *sb, xid_t xid
 
 struct dl_info *locate_dl_info(struct super_block *sb, xid_t xid)
 {
-        struct dl_info *dli;
+	struct dl_info *dli;
 
 	rcu_read_lock();
 	dli = get_dl_info(__lookup_dl_info(sb, xid));
 	vxdprintk(VXD_CBIT(dlim, 7),
 		"locate_dl_info(%p,#%d) = %p", sb, xid, dli);
 	rcu_read_unlock();
-        return dli;
+	return dli;
 }
 
 void rcu_free_dl_info(struct rcu_head *head)
@@ -204,20 +199,20 @@ int vc_add_dlimit(uint32_t id, void __user *data)
 		if (!nd.dentry->d_inode)
 			goto out_release;
 		if (!(sb = nd.dentry->d_inode->i_sb))
-			goto out_release;	
-		
+			goto out_release;
+
 		dli = __alloc_dl_info(sb, id);
-		spin_lock(&dl_info_hash_lock);		
+		spin_lock(&dl_info_hash_lock);
 
 		ret = -EEXIST;
 		if (__lookup_dl_info(sb, id))
-			goto out_unlock;	
+			goto out_unlock;
 		__hash_dl_info(dli);
 		dli = NULL;
 		ret = 0;
 
 	out_unlock:
-		spin_unlock(&dl_info_hash_lock);		
+		spin_unlock(&dl_info_hash_lock);
 		if (dli)
 			__dealloc_dl_info(dli);
 	out_release:
@@ -247,20 +242,20 @@ int vc_rem_dlimit(uint32_t id, void __user *data)
 		if (!nd.dentry->d_inode)
 			goto out_release;
 		if (!(sb = nd.dentry->d_inode->i_sb))
-			goto out_release;	
-		
-		spin_lock(&dl_info_hash_lock);		
+			goto out_release;
+
+		spin_lock(&dl_info_hash_lock);
 		dli = __lookup_dl_info(sb, id);
 
 		ret = -ESRCH;
 		if (!dli)
 			goto out_unlock;
-		
+
 		__unhash_dl_info(dli);
 		ret = 0;
 
 	out_unlock:
-		spin_unlock(&dl_info_hash_lock);		
+		spin_unlock(&dl_info_hash_lock);
 	out_release:
 		path_release(&nd);
 	}
@@ -288,10 +283,13 @@ int vc_set_dlimit(uint32_t id, void __user *data)
 		if (!nd.dentry->d_inode)
 			goto out_release;
 		if (!(sb = nd.dentry->d_inode->i_sb))
-			goto out_release;	
-		if (vc_data.reserved > 100 ||
-			vc_data.inodes_used > vc_data.inodes_total ||
-			vc_data.space_used > vc_data.space_total)
+			goto out_release;
+		if ((vc_data.reserved != (uint32_t)CDLIM_KEEP &&
+			vc_data.reserved > 100) ||
+			(vc_data.inodes_used != (uint32_t)CDLIM_KEEP &&
+			vc_data.inodes_used > vc_data.inodes_total) ||
+			(vc_data.space_used != (uint32_t)CDLIM_KEEP &&
+			vc_data.space_used > vc_data.space_total))
 			goto out_release;
 
 		ret = -ESRCH;
@@ -299,7 +297,7 @@ int vc_set_dlimit(uint32_t id, void __user *data)
 		if (!dli)
 			goto out_release;
 
-		spin_lock(&dli->dl_lock);		
+		spin_lock(&dli->dl_lock);
 
 		if (vc_data.inodes_used != (uint32_t)CDLIM_KEEP)
 			dli->dl_inodes_used = vc_data.inodes_used;
@@ -318,8 +316,8 @@ int vc_set_dlimit(uint32_t id, void __user *data)
 		if (vc_data.reserved != (uint32_t)CDLIM_KEEP)
 			dli->dl_nrlmult = (1 << 10) * (100 - vc_data.reserved) / 100;
 
-		spin_unlock(&dli->dl_lock);		
-		
+		spin_unlock(&dli->dl_lock);
+
 		put_dl_info(dli);
 		ret = 0;
 
@@ -349,7 +347,7 @@ int vc_get_dlimit(uint32_t id, void __user *data)
 		if (!nd.dentry->d_inode)
 			goto out_release;
 		if (!(sb = nd.dentry->d_inode->i_sb))
-			goto out_release;	
+			goto out_release;
 		if (vc_data.reserved > 100 ||
 			vc_data.inodes_used > vc_data.inodes_total ||
 			vc_data.space_used > vc_data.space_total)
@@ -360,7 +358,7 @@ int vc_get_dlimit(uint32_t id, void __user *data)
 		if (!dli)
 			goto out_release;
 
-		spin_lock(&dli->dl_lock);		
+		spin_lock(&dli->dl_lock);
 		vc_data.inodes_used = dli->dl_inodes_used;
 		vc_data.inodes_total = dli->dl_inodes_total;
 		vc_data.space_used = dli->dl_space_used >> 10;
@@ -370,8 +368,8 @@ int vc_get_dlimit(uint32_t id, void __user *data)
 			vc_data.space_total = dli->dl_space_total >> 10;
 
 		vc_data.reserved = 100 - ((dli->dl_nrlmult * 100 + 512) >> 10);
-		spin_unlock(&dli->dl_lock);		
-		
+		spin_unlock(&dli->dl_lock);
+
 		put_dl_info(dli);
 		ret = -EFAULT;
 		if (copy_to_user(data, &vc_data, sizeof(vc_data)))
@@ -388,9 +386,9 @@ int vc_get_dlimit(uint32_t id, void __user *data)
 void vx_vsi_statfs(struct super_block *sb, struct kstatfs *buf)
 {
 	struct dl_info *dli;
-        __u64 blimit, bfree, bavail;
-        __u32 ifree;
-		
+	__u64 blimit, bfree, bavail;
+	__u32 ifree;
+
 	dli = locate_dl_info(sb, current->xid);
 	if (!dli)
 		return;
@@ -442,14 +440,12 @@ no_ilim:
 no_blim:
 	spin_unlock(&dli->dl_lock);
 	put_dl_info(dli);
-	
-	return;	
+
+	return;
 }
 
 #include <linux/module.h>
 
 EXPORT_SYMBOL_GPL(locate_dl_info);
 EXPORT_SYMBOL_GPL(rcu_free_dl_info);
-// EXPORT_SYMBOL_GPL(dl_info_hash_lock);
-// EXPORT_SYMBOL_GPL(unhash_dl_info);
 
diff --git a/kernel/vserver/helper.c b/kernel/vserver/helper.c
index 880b84335..023bbee64 100644
--- a/kernel/vserver/helper.c
+++ b/kernel/vserver/helper.c
@@ -57,19 +57,19 @@ long vs_reboot(unsigned int cmd, void * arg)
 	switch (cmd) {
 	case LINUX_REBOOT_CMD_RESTART:
 		argv[1] = "restart";
-		break;	
+		break;
 
 	case LINUX_REBOOT_CMD_HALT:
 		argv[1] = "halt";
-		break;	
+		break;
 
 	case LINUX_REBOOT_CMD_POWER_OFF:
 		argv[1] = "poweroff";
-		break;	
+		break;
 
 	case LINUX_REBOOT_CMD_SW_SUSPEND:
 		argv[1] = "swsusp";
-		break;	
+		break;
 
 	case LINUX_REBOOT_CMD_RESTART2:
 		if (strncpy_from_user(&buffer[0], (char *)arg, sizeof(buffer) - 1) < 0)
@@ -77,7 +77,7 @@ long vs_reboot(unsigned int cmd, void * arg)
 		argv[3] = buffer;
 	default:
 		argv[1] = "restart2";
-		break;	
+		break;
 	}
 
 	/* maybe we should wait ? */
diff --git a/kernel/vserver/inode.c b/kernel/vserver/inode.c
index dda881895..8be58829e 100644
--- a/kernel/vserver/inode.c
+++ b/kernel/vserver/inode.c
@@ -29,7 +29,7 @@ static int __vc_get_iattr(struct inode *in, uint32_t *xid, uint32_t *flags, uint
 	*flags = IATTR_XID
 		| (IS_BARRIER(in) ? IATTR_BARRIER : 0)
 		| (IS_IUNLINK(in) ? IATTR_IUNLINK : 0)
-		| (IS_IMMUTABLE(in) ? IATTR_IMMUTABLE : 0);	
+		| (IS_IMMUTABLE(in) ? IATTR_IMMUTABLE : 0);
 	*mask = IATTR_IUNLINK | IATTR_IMMUTABLE;
 
 	if (S_ISDIR(in->i_mode))
@@ -42,12 +42,12 @@ static int __vc_get_iattr(struct inode *in, uint32_t *xid, uint32_t *flags, uint
 
 	if (in->i_sb->s_magic == PROC_SUPER_MAGIC) {
 		struct proc_dir_entry *entry = PROC_I(in)->pde;
-		
+
 		// check for specific inodes ?
 		if (entry)
 			*mask |= IATTR_FLAGS;
 		if (entry)
-			*flags |= (entry->vx_flags & IATTR_FLAGS);	
+			*flags |= (entry->vx_flags & IATTR_FLAGS);
 		else
 			*flags |= (PROC_I(in)->vx_flags & IATTR_FLAGS);
 	}
@@ -105,7 +105,7 @@ static int __vc_set_iattr(struct dentry *de, uint32_t *xid, uint32_t *flags, uin
 		if (entry)
 			entry->vx_flags = iflags;
 	}
-	
+
 	if (*mask & (IATTR_BARRIER | IATTR_IUNLINK | IATTR_IMMUTABLE)) {
 		struct iattr attr;
 
@@ -141,7 +141,7 @@ static int __vc_set_iattr(struct dentry *de, uint32_t *xid, uint32_t *flags, uin
 				error = inode_setattr(in, &attr);
 		}
 	}
-		
+
 	mark_inode_dirty(in);
 	up(&in->i_sem);
 	return 0;
@@ -171,7 +171,7 @@ int vc_set_iattr(uint32_t id, void __user *data)
 }
 
 
-#ifdef	CONFIG_VSERVER_LEGACY		
+#ifdef	CONFIG_VSERVER_LEGACY
 #include <linux/proc_fs.h>
 
 #define PROC_DYNAMIC_FIRST 0xF0000000UL
@@ -187,6 +187,8 @@ int vx_proc_ioctl(struct inode * inode, struct file * filp,
 		return -ENOTTY;
 
 	entry = PROC_I(inode)->pde;
+	if (!entry)
+		return -ENOTTY;
 
 	switch(cmd) {
 	case FIOC_GETXFLG: {
diff --git a/kernel/vserver/legacy.c b/kernel/vserver/legacy.c
index 0e78e5eac..482ea8f24 100644
--- a/kernel/vserver/legacy.c
+++ b/kernel/vserver/legacy.c
@@ -60,9 +60,9 @@ int vc_new_s_context(uint32_t ctx, void __user *data)
 		}
 		return ret;
 	}
-	
+
 	if (!vx_check(0, VX_ADMIN) ||
-		!capable(CAP_SYS_ADMIN) || vx_flags(VX_INFO_LOCK, 0))
+		!capable(CAP_SYS_ADMIN) || vx_flags(VX_INFO_PRIVATE, 0))
 		return -EPERM;
 
 	/* ugly hack for Spectator */
@@ -74,7 +74,7 @@ int vc_new_s_context(uint32_t ctx, void __user *data)
 	if (((ctx > MAX_S_CONTEXT) && (ctx != VX_DYNAMIC_ID)) ||
 		(ctx == 0))
 		return -EINVAL;
-		
+
 	if ((ctx == VX_DYNAMIC_ID) || (ctx < MIN_D_CONTEXT))
 		new_vxi = locate_or_create_vx_info(ctx);
 	else
@@ -83,7 +83,7 @@ int vc_new_s_context(uint32_t ctx, void __user *data)
 	if (!new_vxi)
 		return -EINVAL;
 	new_vxi->vx_flags &= ~(VXF_STATE_SETUP|VXF_STATE_INIT);
-	
+
 	ret = vx_migrate_task(current, new_vxi);
 	if (ret == 0) {
 		current->vx_info->vx_bcaps &= (~vc_data.remove_cap);
@@ -124,7 +124,7 @@ int vc_set_ipv4root(uint32_t nbip, void __user *data)
 		err = 0;
 	else if (nxi) {
 		int found = 0;
-		
+
 		// We are allowed to select a subset of the currently
 		// installed IP numbers. No new one allowed
 		// We can't change the broadcast address though
diff --git a/kernel/vserver/limit.c b/kernel/vserver/limit.c
index 99590bbc0..4af1ee567 100644
--- a/kernel/vserver/limit.c
+++ b/kernel/vserver/limit.c
@@ -10,6 +10,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/vserver/limit.h>
 #include <linux/vserver/context.h>
 #include <linux/vserver/switch.h>
@@ -33,6 +34,8 @@ const char *vlimit_name[NUM_LIMITS] = {
 	[VLIMIT_NSOCK]		= "NSOCK",
 };
 
+EXPORT_SYMBOL_GPL(vlimit_name);
+
 
 static int is_valid_rlimit(int id)
 {
@@ -57,7 +60,7 @@ static inline uint64_t vc_get_rlim(struct vx_info *vxi, int id)
 	limit = vxi->limit.rlim[id];
 	if (limit == RLIM_INFINITY)
 		return CRLIM_INFINITY;
-	return limit;	
+	return limit;
 }
 
 int vc_get_rlimit(uint32_t id, void __user *data)
@@ -69,7 +72,7 @@ int vc_get_rlimit(uint32_t id, void __user *data)
 		return -EFAULT;
 	if (!is_valid_rlimit(vc_data.id))
 		return -ENOTSUPP;
-		
+
 	vxi = locate_vx_info(id);
 	if (!vxi)
 		return -ESRCH;
@@ -102,7 +105,6 @@ int vc_set_rlimit(uint32_t id, void __user *data)
 
 	if (vc_data.maximum != CRLIM_KEEP)
 		vxi->limit.rlim[vc_data.id] = vc_data.maximum;
-	printk("setting [%d] = %d\n", vc_data.id, (int)vc_data.maximum);
 	put_vx_info(vxi);
 
 	return 0;
@@ -126,7 +128,7 @@ int vc_get_rlimit_mask(uint32_t id, void __user *data)
 	if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RESOURCE))
 		return -EPERM;
 	if (copy_to_user(data, &mask, sizeof(mask)))
-                return -EFAULT;
+		return -EFAULT;
 	return 0;
 }
 
@@ -142,15 +144,15 @@ void vx_vsi_meminfo(struct sysinfo *val)
 	v = atomic_read(&vxi->limit.rcur[RLIMIT_RSS]);
 	val->freeram = (v < val->totalram) ? val->totalram - v : 0;
 	val->bufferram = 0;
-        val->totalhigh = 0;
-        val->freehigh = 0;
+	val->totalhigh = 0;
+	val->freehigh = 0;
 	return;
 }
 
 void vx_vsi_swapinfo(struct sysinfo *val)
 {
 	struct vx_info *vxi = current->vx_info;
-	unsigned long w,v;
+	unsigned long v, w;
 
 	v = vxi->limit.rlim[RLIMIT_RSS];
 	w = vxi->limit.rlim[RLIMIT_AS];
diff --git a/kernel/vserver/namespace.c b/kernel/vserver/namespace.c
index 3dc0f351c..ee60d4b53 100644
--- a/kernel/vserver/namespace.c
+++ b/kernel/vserver/namespace.c
@@ -17,11 +17,57 @@
 #include <linux/vs_context.h>
 #include <linux/namespace.h>
 #include <linux/dcache.h>
+#include <linux/fs.h>
 
 #include <asm/errno.h>
 #include <asm/uaccess.h>
 
 
+int vx_check_vfsmount(struct vx_info *vxi, struct vfsmount *mnt)
+{
+	struct vfsmount *root_mnt, *altroot_mnt;
+	struct dentry *root, *altroot, *point;
+	int r1, r2, s1, s2, ret = 0;
+
+	if (!vxi || !mnt)
+		return 1;
+
+	spin_lock(&dcache_lock);
+	altroot_mnt = current->fs->rootmnt;
+	altroot = current->fs->root;
+	point = altroot;
+
+	if (vxi->vx_fs) {
+		root_mnt = vxi->vx_fs->rootmnt;
+		root = vxi->vx_fs->root;
+	} else {
+		root_mnt = altroot_mnt;
+		root = altroot;
+	}
+	/* printk("··· %p:%p/%p:%p ",
+		root_mnt, root, altroot_mnt, altroot);	*/
+
+	while ((mnt != mnt->mnt_parent) &&
+		(mnt != root_mnt) && (mnt != altroot_mnt)) {
+		point = mnt->mnt_mountpoint;
+		mnt = mnt->mnt_parent;
+	}
+
+	r1 = (mnt == root_mnt);
+	s1 = is_subdir(point, root);
+	r2 = (mnt == altroot_mnt);
+	s2 = is_subdir(point, altroot);
+
+	ret = (((mnt == root_mnt) && is_subdir(point, root)) ||
+		((mnt == altroot_mnt) && is_subdir(point, altroot)));
+	/* printk("··· for %p:%p -> %d:%d/%d:%d = %d\n",
+		mnt, point, r1, s1, r2, s2, ret);	*/
+	spin_unlock(&dcache_lock);
+
+	return (r2 && s2);
+}
+
+
 /* virtual host info names */
 
 static char * vx_vhi_name(struct vx_info *vxi, int id)
@@ -57,11 +103,11 @@ int vc_set_vhi_name(uint32_t id, void __user *data)
 		return -EPERM;
 	if (copy_from_user (&vc_data, data, sizeof(vc_data)))
 		return -EFAULT;
-	
+
 	vxi = locate_vx_info(id);
 	if (!vxi)
 		return -ESRCH;
-	
+
 	name = vx_vhi_name(vxi, vc_data.field);
 	if (name)
 		memcpy(name, vc_data.name, 65);
@@ -85,7 +131,7 @@ int vc_get_vhi_name(uint32_t id, void __user *data)
 	name = vx_vhi_name(vxi, vc_data.field);
 	if (!name)
 		goto out_put;
-			
+
 	memcpy(vc_data.name, name, 65);
 	if (copy_to_user (data, &vc_data, sizeof(vc_data)))
 		return -EFAULT;
@@ -145,7 +191,7 @@ int vc_enter_namespace(uint32_t id, void *data)
 	old_ns = current->namespace;
 	old_fs = current->fs;
 	get_namespace(vxi->vx_namespace);
-	current->namespace = vxi->vx_namespace;	
+	current->namespace = vxi->vx_namespace;
 	current->fs = fs;
 	task_unlock(current);
 
diff --git a/kernel/vserver/network.c b/kernel/vserver/network.c
index a62d1c435..e87c8b617 100644
--- a/kernel/vserver/network.c
+++ b/kernel/vserver/network.c
@@ -16,8 +16,8 @@
 #include <linux/slab.h>
 #include <linux/vserver.h>
 #include <linux/vs_base.h>
-#include <linux/vs_network.h>
 #include <linux/rcupdate.h>
+#include <net/tcp.h>
 
 #include <asm/errno.h>
 
@@ -30,14 +30,14 @@
 static struct nx_info *__alloc_nx_info(nid_t nid)
 {
 	struct nx_info *new = NULL;
-	
+
 	vxdprintk(VXD_CBIT(nid, 1), "alloc_nx_info(%d)*", nid);
 
 	/* would this benefit from a slab cache? */
 	new = kmalloc(sizeof(struct nx_info), GFP_KERNEL);
 	if (!new)
 		return 0;
-	
+
 	memset (new, 0, sizeof(struct nx_info));
 	new->nx_id = nid;
 	INIT_RCU_HEAD(&new->nx_rcu);
@@ -46,7 +46,7 @@ static struct nx_info *__alloc_nx_info(nid_t nid)
 	atomic_set(&new->nx_usecnt, 0);
 
 	/* rest of init goes here */
-	
+
 	vxdprintk(VXD_CBIT(nid, 0),
 		"alloc_nx_info() = %p", new);
 	return new;
@@ -63,7 +63,7 @@ static void __dealloc_nx_info(struct nx_info *nxi)
 
 	nxi->nx_hlist.next = LIST_POISON1;
 	nxi->nx_id = -1;
-	
+
 	BUG_ON(atomic_read(&nxi->nx_usecnt));
 	BUG_ON(atomic_read(&nxi->nx_refcnt));
 
@@ -73,7 +73,7 @@ static void __dealloc_nx_info(struct nx_info *nxi)
 
 /*	hash table for nx_info hash */
 
-#define	NX_HASH_SIZE	13
+#define NX_HASH_SIZE	13
 
 struct hlist_head nx_info_hash[NX_HASH_SIZE];
 
@@ -95,7 +95,7 @@ static inline unsigned int __hashval(nid_t nid)
 static inline void __hash_nx_info(struct nx_info *nxi)
 {
 	struct hlist_head *head;
-	
+
 	vxdprintk(VXD_CBIT(nid, 4),
 		"__hash_nx_info: %p[#%d]", nxi, nxi->nx_id);
 	get_nx_info(nxi);
@@ -148,7 +148,7 @@ static inline nid_t __nx_dynamic_id(void)
 {
 	static nid_t seq = MAX_N_CONTEXT;
 	nid_t barrier = seq;
-	
+
 	do {
 		if (++seq > MAX_N_CONTEXT)
 			seq = MIN_D_CONTEXT;
@@ -169,7 +169,7 @@ static inline nid_t __nx_dynamic_id(void)
 static struct nx_info * __loc_nx_info(int id, int *err)
 {
 	struct nx_info *new, *nxi = NULL;
-	
+
 	vxdprintk(VXD_CBIT(nid, 1), "loc_nx_info(%d)*", id);
 
 	if (!(new = __alloc_nx_info(id))) {
@@ -256,13 +256,13 @@ void unhash_nx_info(struct nx_info *nxi)
 
 /*	locate_nx_info()
 
-	* search for a nx_info and get() it			
+	* search for a nx_info and get() it
 	* negative id means current				*/
 
 struct nx_info *locate_nx_info(int id)
 {
 	struct nx_info *nxi;
-	
+
 	if (id < 0) {
 		nxi = get_nx_info(current->nx_info);
 	} else {
@@ -300,7 +300,7 @@ struct nx_info *create_nx_info(void)
 {
 	struct nx_info *new;
 	int err;
-	
+
 	vxdprintk(VXD_CBIT(nid, 5), "create_nx_info(%s)", "void");
 	if (!(new = __loc_nx_info(NX_DYNAMIC_ID, &err)))
 		return NULL;
@@ -312,10 +312,6 @@ struct nx_info *create_nx_info(void)
 
 #ifdef	CONFIG_PROC_FS
 
-#define hlist_for_each_rcu(pos, head) \
-        for (pos = (head)->first; pos && ({ prefetch(pos->next); 1;}); \
-		pos = pos->next, ({ smp_read_barrier_depends(); 0;}))
-
 int get_nid_list(int index, unsigned int *nids, int size)
 {
 	int hindex, nr_nids = 0;
@@ -332,7 +328,7 @@ int get_nid_list(int index, unsigned int *nids, int size)
 				continue;
 
 			nxi = hlist_entry(pos, struct nx_info, nx_hlist);
-			nids[nr_nids] = nxi->nx_id;			
+			nids[nr_nids] = nxi->nx_id;
 			if (++nr_nids >= size)
 				goto out;
 		}
@@ -352,7 +348,7 @@ int nx_migrate_task(struct task_struct *p, struct nx_info *nxi)
 {
 	struct nx_info *old_nxi;
 	int ret = 0;
-	
+
 	if (!p || !nxi)
 		BUG();
 
@@ -385,22 +381,14 @@ out:
 #include <linux/netdevice.h>
 #include <linux/inetdevice.h>
 
-static inline int __addr_in_nx_info(u32 addr, struct nx_info *nxi)
-{
-	int i, nbip;
-
-	nbip = nxi->nbipv4;
-	for (i=0; i<nbip; i++)
-		if (nxi->ipv4[i] == addr)
-			return 1;
-	return 0;
-}
 
 int ifa_in_nx_info(struct in_ifaddr *ifa, struct nx_info *nxi)
 {
-	if (nxi && ifa)
-		return __addr_in_nx_info(ifa->ifa_address, nxi);
-	return 1;
+	if (!nxi)
+		return 1;
+	if (!ifa)
+		return 0;
+	return addr_in_nx_info(nxi, ifa->ifa_address);
 }
 
 int dev_in_nx_info(struct net_device *dev, struct nx_info *nxi)
@@ -416,13 +404,63 @@ int dev_in_nx_info(struct net_device *dev, struct nx_info *nxi)
 
 	for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
 		ifap = &ifa->ifa_next) {
-		if (__addr_in_nx_info(ifa->ifa_address, nxi))
+		if (addr_in_nx_info(nxi, ifa->ifa_address))
 			return 1;
 	}
 	return 0;
 }
 
+/*
+ *	check if address is covered by socket
+ *
+ *	sk:	the socket to check against
+ *	addr:	the address in question (must be != 0)
+ */
+static inline int __addr_in_socket(struct sock *sk, uint32_t addr)
+{
+	struct nx_info *nxi = sk->sk_nx_info;
+	uint32_t saddr = tcp_v4_rcv_saddr(sk);
+
+	vxdprintk(VXD_CBIT(net, 5),
+		"__addr_in_socket(%p,%d.%d.%d.%d) %p:%d.%d.%d.%d %p;%lx",
+		sk, VXD_QUAD(addr), nxi, VXD_QUAD(saddr), sk->sk_socket,
+		(sk->sk_socket?sk->sk_socket->flags:0));
+
+	if (saddr) {
+		/* direct address match */
+		return (saddr == addr);
+	} else if (nxi) {
+		/* match against nx_info */
+		return addr_in_nx_info(nxi, addr);
+	} else {
+		/* unrestricted any socket */
+		return 1;
+	}
+}
+
 
+int nx_addr_conflict(struct nx_info *nxi, uint32_t addr, struct sock *sk)
+{
+	vxdprintk(VXD_CBIT(net, 2),
+		"nx_addr_conflict(%p,%p) %d.%d,%d.%d",
+		nxi, sk, VXD_QUAD(addr));
+
+	if (addr) {
+		/* check real address */
+		return __addr_in_socket(sk, addr);
+	} else if (nxi) {
+		/* check against nx_info */
+		int i, n = nxi->nbipv4;
+
+		for (i=0; i<n; i++)
+			if (__addr_in_socket(sk, nxi->ipv4[i]))
+				return 1;
+		return 0;
+	} else {
+		/* check against any */
+		return 1;
+	}
+}
 
 
 /* vserver syscall commands below here */
@@ -434,22 +472,22 @@ int dev_in_nx_info(struct net_device *dev, struct nx_info *nxi)
 
 int vc_task_nid(uint32_t id, void __user *data)
 {
-        nid_t nid;
-
-        if (id) {
-                struct task_struct *tsk;
-
-                if (!vx_check(0, VX_ADMIN|VX_WATCH))
-                        return -EPERM;
-
-                read_lock(&tasklist_lock);
-                tsk = find_task_by_pid(id);
-                nid = (tsk) ? tsk->nid : -ESRCH;
-                read_unlock(&tasklist_lock);
-        }
-        else
-                nid = current->nid;
-        return nid;
+	nid_t nid;
+
+	if (id) {
+		struct task_struct *tsk;
+
+		if (!vx_check(0, VX_ADMIN|VX_WATCH))
+			return -EPERM;
+
+		read_lock(&tasklist_lock);
+		tsk = find_task_by_real_pid(id);
+		nid = (tsk) ? tsk->nid : -ESRCH;
+		read_unlock(&tasklist_lock);
+	}
+	else
+		nid = current->nid;
+	return nid;
 }
 
 
@@ -480,7 +518,7 @@ int vc_nx_info(uint32_t id, void __user *data)
 
 int vc_net_create(uint32_t nid, void __user *data)
 {
-        // int ret = -ENOMEM;
+	// int ret = -ENOMEM;
 	struct nx_info *new_nxi;
 	int ret;
 
@@ -512,7 +550,7 @@ out_put:
 int vc_net_migrate(uint32_t id, void __user *data)
 {
 	struct nx_info *nxi;
-	
+
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
diff --git a/kernel/vserver/proc.c b/kernel/vserver/proc.c
index e957fd43b..4408810b7 100644
--- a/kernel/vserver/proc.c
+++ b/kernel/vserver/proc.c
@@ -22,6 +22,7 @@
 #include <linux/vs_base.h>
 #include <linux/vs_context.h>
 #include <linux/vs_network.h>
+#include <linux/vs_cvirt.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -46,7 +47,7 @@ enum vid_directory_inos {
 	PROC_NID_STATUS,
 };
 
-#define	PROC_VID_MASK	0x60
+#define PROC_VID_MASK	0x60
 
 
 /* first the actual feeds */
@@ -93,12 +94,12 @@ int proc_xid_status (int vid, char *buffer)
 	if (!vxi)
 		return 0;
 	length = sprintf(buffer,
-		"UseCnt:\t%d\n"		
-		"RefCnt:\t%d\n"		
+		"UseCnt:\t%d\n"
+		"RefCnt:\t%d\n"
 		"Flags:\t%016llx\n"
 		"BCaps:\t%016llx\n"
 		"CCaps:\t%016llx\n"
-		"Ticks:\t%d\n"		
+		"Ticks:\t%d\n"
 		,atomic_read(&vxi->vx_usecnt)
 		,atomic_read(&vxi->vx_refcnt)
 		,(unsigned long long)vxi->vx_flags
@@ -144,6 +145,7 @@ int proc_xid_cvirt (int vid, char *buffer)
 	vxi = locate_vx_info(vid);
 	if (!vxi)
 		return 0;
+	vx_update_load(vxi);
 	length = vx_info_proc_cvirt(&vxi->cvirt, buffer);
 	put_vx_info(vxi);
 	return length;
@@ -174,7 +176,7 @@ static int proc_vnet_info(int vid, char *buffer)
 		);
 }
 
-#define	atoquad(a) \
+#define atoquad(a) \
 	(((a)>>0) & 0xff), (((a)>>8) & 0xff), \
 	(((a)>>16) & 0xff), (((a)>>24) & 0xff)
 
@@ -211,8 +213,8 @@ int proc_nid_status (int vid, char *buffer)
 	if (!nxi)
 		return 0;
 	length = sprintf(buffer,
-		"UseCnt:\t%d\n"		
-		"RefCnt:\t%d\n"		
+		"UseCnt:\t%d\n"
+		"RefCnt:\t%d\n"
 		,atomic_read(&nxi->nx_usecnt)
 		,atomic_read(&nxi->nx_refcnt)
 		);
@@ -223,11 +225,11 @@ int proc_nid_status (int vid, char *buffer)
 /* here the inode helpers */
 
 
+#define fake_ino(id,nr) (((nr) & 0xFFFF) | \
+			(((id) & 0xFFFF) << 16))
 
-#define fake_ino(id,ino) (((id)<<16)|(ino))
-
-#define	inode_vid(i)	((i)->i_ino >> 16)
-#define	inode_type(i)	((i)->i_ino & 0xFFFF)
+#define inode_vid(i)	(((i)->i_ino >> 16) & 0xFFFF)
+#define inode_type(i)	((i)->i_ino & 0xFFFF)
 
 #define MAX_MULBY10	((~0U-9)/10)
 
@@ -264,7 +266,7 @@ static int proc_vid_revalidate(struct dentry * dentry, struct nameidata *nd)
 		case PROC_NID_INO:
 			hashed = nx_info_is_hashed(vid);
 			break;
-	}	
+	}
 	if (hashed)
 		return 1;
 	d_drop(dentry);
@@ -274,7 +276,7 @@ static int proc_vid_revalidate(struct dentry * dentry, struct nameidata *nd)
 /*
 static int proc_vid_delete_dentry(struct dentry * dentry)
 {
-        return 1;
+	return 1;
 }
 */
 
@@ -327,7 +329,7 @@ static struct file_operations proc_vid_info_file_operations = {
 };
 
 static struct dentry_operations proc_vid_dentry_operations = {
-	d_revalidate:   proc_vid_revalidate,
+	d_revalidate:	proc_vid_revalidate,
 //	d_delete:       proc_vid_delete_dentry,
 };
 
@@ -371,10 +373,10 @@ static struct dentry *proc_vid_lookup(struct inode *dir,
 
 	switch (inode_type(dir)) {
 		case PROC_XID_INO:
-			p = vx_base_stuff;	
+			p = vx_base_stuff;
 			break;
 		case PROC_NID_INO:
-			p = vn_base_stuff;	
+			p = vn_base_stuff;
 			break;
 		default:
 			goto out;
@@ -420,7 +422,7 @@ static struct dentry *proc_vid_lookup(struct inode *dir,
 		case PROC_NID_STATUS:
 			PROC_I(inode)->op.proc_vid_read = proc_nid_status;
 			break;
-		
+
 		default:
 			printk("procfs: impossible type (%d)",p->type);
 			iput(inode);
@@ -431,7 +433,7 @@ static struct dentry *proc_vid_lookup(struct inode *dir,
 	inode->i_fop = &proc_vid_info_file_operations;
 	inode->i_nlink = 1;
 	inode->i_flags|=S_IMMUTABLE;
-	
+
 	dentry->d_op = &proc_vid_dentry_operations;
 	d_add(dentry, inode);
 	error = 0;
@@ -446,7 +448,7 @@ static int proc_vid_readdir(struct file * filp,
 	int i, size;
 	struct inode *inode = filp->f_dentry->d_inode;
 	struct vid_entry *p;
-	
+
 	i = filp->f_pos;
 	switch (i) {
 		case 0:
@@ -468,11 +470,11 @@ static int proc_vid_readdir(struct file * filp,
 			switch (inode_type(inode)) {
 				case PROC_XID_INO:
 					size = sizeof(vx_base_stuff);
-					p = vx_base_stuff + i;	
+					p = vx_base_stuff + i;
 					break;
 				case PROC_NID_INO:
 					size = sizeof(vn_base_stuff);
-					p = vn_base_stuff + i;	
+					p = vn_base_stuff + i;
 					break;
 				default:
 					return 1;
@@ -591,7 +593,7 @@ struct dentry *proc_virtual_lookup(struct inode *dir,
 	dentry->d_op = &proc_vid_dentry_operations;
 	d_add(dentry, inode);
 	ret = 0;
-	
+
 out_release:
 	put_vx_info(vxi);
 out:
@@ -661,7 +663,7 @@ struct dentry *proc_vnet_lookup(struct inode *dir,
 	dentry->d_op = &proc_vid_dentry_operations;
 	d_add(dentry, inode);
 	ret = 0;
-	
+
 out_release:
 	put_nx_info(nxi);
 out:
@@ -838,9 +840,22 @@ void proc_vx_init(void)
 
 char *task_vx_info(struct task_struct *p, char *buffer)
 {
-	return buffer + sprintf(buffer,
-		"XID:\t%d\n"
-		,p->xid);
+	struct vx_info *vxi;
+
+	buffer += sprintf (buffer,"XID:\t%d\n", vx_task_xid(p));
+	vxi = task_get_vx_info(p);
+	if (vxi && !vx_flags(VXF_INFO_HIDE, 0)) {
+		buffer += sprintf (buffer,"BCaps:\t%016llx\n"
+			,(unsigned long long)vxi->vx_bcaps);
+		buffer += sprintf (buffer,"CCaps:\t%016llx\n"
+			,(unsigned long long)vxi->vx_ccaps);
+		buffer += sprintf (buffer,"CFlags:\t%016llx\n"
+			,(unsigned long long)vxi->vx_flags);
+		buffer += sprintf (buffer,"CIPid:\t%d\n"
+			,vxi->vx_initpid);
+	}
+	put_vx_info(vxi);
+	return buffer;
 }
 
 int proc_pid_vx_info(struct task_struct *p, char *buffer)
@@ -853,9 +868,25 @@ int proc_pid_vx_info(struct task_struct *p, char *buffer)
 
 char *task_nx_info(struct task_struct *p, char *buffer)
 {
-	return buffer + sprintf(buffer,
-		"NID:\t%d\n"
-		,p->nid);
+	struct nx_info *nxi;
+
+	buffer += sprintf (buffer,"NID:\t%d\n", nx_task_nid(p));
+	nxi = task_get_nx_info(p);
+	if (nxi && !vx_flags(VXF_INFO_HIDE, 0)) {
+		int i;
+
+		for (i=0; i<nxi->nbipv4; i++){
+			buffer += sprintf (buffer,
+				"V4Root[%d]:\t%d.%d.%d.%d/%d.%d.%d.%d\n", i
+				,NIPQUAD(nxi->ipv4[i])
+				,NIPQUAD(nxi->mask[i]));
+		}
+		buffer += sprintf (buffer,
+			"V4Root[bcast]:\t%d.%d.%d.%d\n"
+			,NIPQUAD(nxi->v4_bcast));
+	}
+	put_nx_info(nxi);
+	return buffer;
 }
 
 int proc_pid_nx_info(struct task_struct *p, char *buffer)
diff --git a/kernel/vserver/sched.c b/kernel/vserver/sched.c
index b2d45c23f..fab4514e6 100644
--- a/kernel/vserver/sched.c
+++ b/kernel/vserver/sched.c
@@ -33,7 +33,7 @@ int vx_tokens_recalc(struct vx_info *vxi)
 {
 	long delta, tokens = 0;
 
-	if (__vx_flags(vxi->vx_flags, VXF_SCHED_PAUSE, 0))
+	if (vx_info_flags(vxi, VXF_SCHED_PAUSE, 0))
 		/* we are paused */
 		return 0;
 
@@ -52,7 +52,7 @@ int vx_tokens_recalc(struct vx_info *vxi)
 		atomic_add(tokens, &vxi->sched.tokens);
 		vxi->sched.jiffies += delta;
 		tokens = atomic_read(&vxi->sched.tokens);
-	
+
 		if (tokens > vxi->sched.tokens_max) {
 			tokens = vxi->sched.tokens_max;
 			atomic_set(&vxi->sched.tokens, tokens);
@@ -60,7 +60,10 @@ int vx_tokens_recalc(struct vx_info *vxi)
 		spin_unlock(&vxi->sched.tokens_lock);
 	} else {
 		/* no new tokens */
-		if ((tokens = vx_tokens_avail(vxi)) < vxi->sched.tokens_min) {
+		tokens = vx_tokens_avail(vxi);
+		if (tokens <= 0)
+			vxi->vx_state |= VXS_ONHOLD;
+		if (tokens < vxi->sched.tokens_min) {
 			/* enough tokens will be available in */
 			if (vxi->sched.tokens_min == 0)
 				return delta - vxi->sched.interval;
@@ -68,7 +71,14 @@ int vx_tokens_recalc(struct vx_info *vxi)
 				vxi->sched.tokens_min / vxi->sched.fill_rate;
 		}
 	}
+
 	/* we have some tokens left */
+	if (vx_info_state(vxi, VXS_ONHOLD) &&
+		(tokens >= vxi->sched.tokens_min))
+		vxi->vx_state &= ~VXS_ONHOLD;
+	if (vx_info_state(vxi, VXS_ONHOLD))
+		tokens -= vxi->sched.tokens_min;
+
 	return tokens;
 }
 
@@ -119,14 +129,14 @@ int effective_vavavoom(task_t *p, int max_prio)
 }
 
 
-int vc_set_sched(uint32_t xid, void __user *data)
+int vc_set_sched_v2(uint32_t xid, void __user *data)
 {
 	struct vcmd_set_sched_v2 vc_data;
 	struct vx_info *vxi;
 
 	if (copy_from_user (&vc_data, data, sizeof(vc_data)))
 		return -EFAULT;
-	
+
 	vxi = locate_vx_info(xid);
 	if (!vxi)
 		return -EINVAL;
@@ -161,3 +171,55 @@ int vc_set_sched(uint32_t xid, void __user *data)
 	return 0;
 }
 
+
+int vc_set_sched(uint32_t xid, void __user *data)
+{
+	struct vcmd_set_sched_v3 vc_data;
+	struct vx_info *vxi;
+	unsigned int set_mask;
+
+	if (copy_from_user (&vc_data, data, sizeof(vc_data)))
+		return -EFAULT;
+
+	vxi = locate_vx_info(xid);
+	if (!vxi)
+		return -EINVAL;
+
+	set_mask = vc_data.set_mask;
+
+	spin_lock(&vxi->sched.tokens_lock);
+
+	if (set_mask & VXSM_FILL_RATE)
+		vxi->sched.fill_rate = vc_data.fill_rate;
+	if (set_mask & VXSM_INTERVAL)
+		vxi->sched.interval = vc_data.interval;
+	if (set_mask & VXSM_TOKENS)
+		atomic_set(&vxi->sched.tokens, vc_data.tokens);
+	if (set_mask & VXSM_TOKENS_MIN)
+		vxi->sched.tokens_min = vc_data.tokens_min;
+	if (set_mask & VXSM_TOKENS_MAX)
+		vxi->sched.tokens_max = vc_data.tokens_max;
+	if (set_mask & VXSM_PRIO_BIAS)
+		vxi->sched.priority_bias = vc_data.priority_bias;
+
+	/* Sanity check the resultant values */
+	if (vxi->sched.fill_rate <= 0)
+		vxi->sched.fill_rate = 1;
+	if (vxi->sched.interval <= 0)
+		vxi->sched.interval = HZ;
+	if (vxi->sched.tokens_max == 0)
+		vxi->sched.tokens_max = 1;
+	if (atomic_read(&vxi->sched.tokens) > vxi->sched.tokens_max)
+		atomic_set(&vxi->sched.tokens, vxi->sched.tokens_max);
+	if (vxi->sched.tokens_min > vxi->sched.tokens_max)
+		vxi->sched.tokens_min = vxi->sched.tokens_max;
+	if (vxi->sched.priority_bias > MAX_PRIO_BIAS)
+		vxi->sched.priority_bias = MAX_PRIO_BIAS;
+	if (vxi->sched.priority_bias < MIN_PRIO_BIAS)
+		vxi->sched.priority_bias = MIN_PRIO_BIAS;
+
+	spin_unlock(&vxi->sched.tokens_lock);
+	put_vx_info(vxi);
+	return 0;
+}
+
diff --git a/kernel/vserver/signal.c b/kernel/vserver/signal.c
index 91d8a3da2..0499c9ec7 100644
--- a/kernel/vserver/signal.c
+++ b/kernel/vserver/signal.c
@@ -32,7 +32,7 @@ int vc_ctx_kill(uint32_t id, void __user *data)
 		return -ENOSYS;
 	if (copy_from_user (&vc_data, data, sizeof(vc_data)))
 		return -EFAULT;
-	
+
 	info.si_signo = vc_data.sig;
 	info.si_errno = 0;
 	info.si_code = SI_USER;
@@ -62,14 +62,14 @@ int vc_ctx_kill(uint32_t id, void __user *data)
 				retval = err;
 		}
 		break;
-		
+
 	default:
-	p = find_task_by_pid(vc_data.pid);
+	p = find_task_by_real_pid(vc_data.pid);
 		if (p) {
 			if (!thread_group_leader(p)) {
 				struct task_struct *tg;
-			
-				tg = find_task_by_pid(p->tgid);
+
+				tg = find_task_by_real_pid(p->tgid);
 				if (tg)
 					p = tg;
 			}
@@ -84,3 +84,44 @@ int vc_ctx_kill(uint32_t id, void __user *data)
 }
 
 
+static int __wait_exit(struct vx_info *vxi)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	int ret = 0;
+
+	add_wait_queue(&vxi->vx_exit, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+
+wait:
+	if (vx_info_state(vxi, VXS_DEFUNCT))
+		goto out;
+	if (signal_pending(current)) {
+		ret = -ERESTARTSYS;
+		goto out;
+	}
+	schedule();
+	goto wait;
+
+out:
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&vxi->vx_exit, &wait);
+	return ret;
+}
+
+
+
+int vc_wait_exit(uint32_t id, void __user *data)
+{
+//	struct vcmd_wait_exit_v0 vc_data;
+	struct vx_info *vxi;
+	int ret;
+
+	vxi = locate_vx_info(id);
+	if (!vxi)
+		return -ESRCH;
+
+	ret = __wait_exit(vxi);
+	put_vx_info(vxi);
+	return ret;
+}
+
diff --git a/kernel/vserver/switch.c b/kernel/vserver/switch.c
index f13ee97a9..f72cb7ead 100644
--- a/kernel/vserver/switch.c
+++ b/kernel/vserver/switch.c
@@ -42,6 +42,8 @@ vc_get_version(uint32_t id)
 extern asmlinkage long
 sys_vserver(uint32_t cmd, uint32_t id, void __user *data)
 {
+	if (!capable(CAP_CONTEXT))
+		return -EPERM;
 
 	vxdprintk(VXD_CBIT(switch, 0),
 		"vc: VCMD_%02d_%d[%d], %d",
@@ -52,7 +54,7 @@ sys_vserver(uint32_t cmd, uint32_t id, void __user *data)
 	case VCMD_get_version:
 		return vc_get_version(id);
 
-#ifdef	CONFIG_VSERVER_LEGACY		
+#ifdef	CONFIG_VSERVER_LEGACY
 	case VCMD_new_s_context:
 		return vc_new_s_context(id, data);
 	case VCMD_set_ipv4root:
@@ -96,7 +98,7 @@ sys_vserver(uint32_t cmd, uint32_t id, void __user *data)
 		return vc_set_rlimit(id, data);
 	case VCMD_get_rlimit_mask:
 		return vc_get_rlimit_mask(id, data);
-		
+
 	case VCMD_vx_get_vhi_name:
 		return vc_get_vhi_name(id, data);
 	case VCMD_vx_set_vhi_name:
@@ -122,6 +124,9 @@ sys_vserver(uint32_t cmd, uint32_t id, void __user *data)
 	case VCMD_get_ncaps:
 		return vc_get_ncaps(id, data);
 
+	case VCMD_set_sched_v2:
+		return vc_set_sched_v2(id, data);
+	/* this is version 3 */
 	case VCMD_set_sched:
 		return vc_set_sched(id, data);
 
@@ -143,7 +148,10 @@ sys_vserver(uint32_t cmd, uint32_t id, void __user *data)
 	case VCMD_ctx_kill:
 		return vc_ctx_kill(id, data);
 
-#ifdef	CONFIG_VSERVER_LEGACY		
+	case VCMD_wait_exit:
+		return vc_wait_exit(id, data);
+
+#ifdef	CONFIG_VSERVER_LEGACY
 	case VCMD_create_context:
 		return vc_ctx_create(id, data);
 #endif
@@ -157,7 +165,7 @@ sys_vserver(uint32_t cmd, uint32_t id, void __user *data)
 		return vc_enter_namespace(id, data);
 
 	case VCMD_ctx_create:
-#ifdef	CONFIG_VSERVER_LEGACY		
+#ifdef	CONFIG_VSERVER_LEGACY
 		if (id == 1) {
 			current->xid = 1;
 			return 1;
diff --git a/kernel/vserver/sysctl.c b/kernel/vserver/sysctl.c
index 298c62f18..fffc0dd46 100644
--- a/kernel/vserver/sysctl.c
+++ b/kernel/vserver/sysctl.c
@@ -25,13 +25,13 @@
 #define CTL_VSERVER	4242    /* unused? */
 
 enum {
-        CTL_DEBUG_SWITCH = 1,
-        CTL_DEBUG_XID,
-        CTL_DEBUG_NID,
-        CTL_DEBUG_NET,
-        CTL_DEBUG_LIMIT,
-        CTL_DEBUG_DLIM,
-        CTL_DEBUG_CVIRT,
+	CTL_DEBUG_SWITCH = 1,
+	CTL_DEBUG_XID,
+	CTL_DEBUG_NID,
+	CTL_DEBUG_NET,
+	CTL_DEBUG_LIMIT,
+	CTL_DEBUG_DLIM,
+	CTL_DEBUG_CVIRT,
 };
 
 
@@ -57,7 +57,7 @@ void vserver_register_sysctl(void)
 //			vserver_table[0].de->owner = THIS_MODULE;
 #endif
 	}
-			
+
 }
 
 void vserver_unregister_sysctl(void)
@@ -125,79 +125,85 @@ done:
 	*ppos += *lenp;
 	return 0;
 }
-	
+
 
 
 static ctl_table debug_table[] = {
-        {
-                .ctl_name       = CTL_DEBUG_SWITCH,
-                .procname       = "debug_switch",
-                .data           = &vx_debug_switch,
-                .maxlen         = sizeof(int),
-                .mode           = 0644,
-                .proc_handler   = &proc_dodebug
-        },
-        {
-                .ctl_name       = CTL_DEBUG_XID,
-                .procname       = "debug_xid",
-                .data           = &vx_debug_xid,
-                .maxlen         = sizeof(int),
-                .mode           = 0644,
-                .proc_handler   = &proc_dodebug
-        },
-        {
-                .ctl_name       = CTL_DEBUG_NID,
-                .procname       = "debug_nid",
-                .data           = &vx_debug_nid,
-                .maxlen         = sizeof(int),
-                .mode           = 0644,
-                .proc_handler   = &proc_dodebug
-        },
-        {
-                .ctl_name       = CTL_DEBUG_NET,
-                .procname       = "debug_net",
-                .data           = &vx_debug_net,
-                .maxlen         = sizeof(int),
-                .mode           = 0644,
-                .proc_handler   = &proc_dodebug
-        },
-        {
-                .ctl_name       = CTL_DEBUG_LIMIT,
-                .procname       = "debug_limit",
-                .data           = &vx_debug_limit,
-                .maxlen         = sizeof(int),
-                .mode           = 0644,
-                .proc_handler   = &proc_dodebug
-        },
-        {
-                .ctl_name       = CTL_DEBUG_DLIM,
-                .procname       = "debug_dlim",
-                .data           = &vx_debug_dlim,
-                .maxlen         = sizeof(int),
-                .mode           = 0644,
-                .proc_handler   = &proc_dodebug
-        },
-        {
-                .ctl_name       = CTL_DEBUG_CVIRT,
-                .procname       = "debug_cvirt",
-                .data           = &vx_debug_cvirt,
-                .maxlen         = sizeof(int),
-                .mode           = 0644,
-                .proc_handler   = &proc_dodebug
-        },
-        { .ctl_name = 0 }
+	{
+		.ctl_name	= CTL_DEBUG_SWITCH,
+		.procname	= "debug_switch",
+		.data		= &vx_debug_switch,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dodebug
+	},
+	{
+		.ctl_name	= CTL_DEBUG_XID,
+		.procname	= "debug_xid",
+		.data		= &vx_debug_xid,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dodebug
+	},
+	{
+		.ctl_name	= CTL_DEBUG_NID,
+		.procname	= "debug_nid",
+		.data		= &vx_debug_nid,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dodebug
+	},
+	{
+		.ctl_name	= CTL_DEBUG_NET,
+		.procname	= "debug_net",
+		.data		= &vx_debug_net,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dodebug
+	},
+	{
+		.ctl_name	= CTL_DEBUG_LIMIT,
+		.procname	= "debug_limit",
+		.data		= &vx_debug_limit,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dodebug
+	},
+	{
+		.ctl_name	= CTL_DEBUG_DLIM,
+		.procname	= "debug_dlim",
+		.data		= &vx_debug_dlim,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dodebug
+	},
+	{
+		.ctl_name	= CTL_DEBUG_CVIRT,
+		.procname	= "debug_cvirt",
+		.data		= &vx_debug_cvirt,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dodebug
+	},
+	{ .ctl_name = 0 }
 };
 
 static ctl_table vserver_table[] = {
-        {
-                .ctl_name       = CTL_VSERVER,
-                .procname       = "vserver",
-                .mode           = 0555,
-                .child          = debug_table
-        },
-        { .ctl_name = 0 }
+	{
+		.ctl_name	= CTL_VSERVER,
+		.procname	= "vserver",
+		.mode		= 0555,
+		.child		= debug_table
+	},
+	{ .ctl_name = 0 }
 };
 
 
+EXPORT_SYMBOL_GPL(vx_debug_switch);
+EXPORT_SYMBOL_GPL(vx_debug_xid);
+EXPORT_SYMBOL_GPL(vx_debug_nid);
+EXPORT_SYMBOL_GPL(vx_debug_net);
+EXPORT_SYMBOL_GPL(vx_debug_limit);
 EXPORT_SYMBOL_GPL(vx_debug_dlim);
+EXPORT_SYMBOL_GPL(vx_debug_cvirt);
 
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 987fbc298..ee77ccd01 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -398,6 +398,26 @@ int fastcall schedule_delayed_work(struct work_struct *work, unsigned long delay
 	return queue_delayed_work(keventd_wq, work, delay);
 }
 
+int schedule_delayed_work_on(int cpu,
+			struct work_struct *work, unsigned long delay)
+{
+	int ret = 0;
+	struct timer_list *timer = &work->timer;
+
+	if (!test_and_set_bit(0, &work->pending)) {
+		BUG_ON(timer_pending(timer));
+		BUG_ON(!list_empty(&work->entry));
+		/* This stores keventd_wq for the moment, for the timer_fn */
+		work->wq_data = keventd_wq;
+		timer->expires = jiffies + delay;
+		timer->data = (unsigned long)work;
+		timer->function = delayed_work_timer_fn;
+		add_timer_on(timer, cpu);
+		ret = 1;
+	}
+	return ret;
+}
+
 void flush_scheduled_work(void)
 {
 	flush_workqueue(keventd_wq);
@@ -505,5 +525,5 @@ EXPORT_SYMBOL_GPL(destroy_workqueue);
 
 EXPORT_SYMBOL(schedule_work);
 EXPORT_SYMBOL(schedule_delayed_work);
+EXPORT_SYMBOL(schedule_delayed_work_on);
 EXPORT_SYMBOL(flush_scheduled_work);
-
diff --git a/lib/Makefile b/lib/Makefile
index 295e70bcd..da5dca19c 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -5,12 +5,9 @@
 
 lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
 	 bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
-	 kobject.o idr.o div64.o parser.o int_sqrt.o \
+	 kobject.o kref.o idr.o div64.o parser.o int_sqrt.o \
 	 bitmap.o extable.o
 
-# hack for now till some static code uses krefs, then it can move up above...
-obj-y += kref.o
-
 lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
 lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
 
@@ -21,11 +18,12 @@ endif
 obj-$(CONFIG_CRC_CCITT)	+= crc-ccitt.o
 obj-$(CONFIG_CRC32)	+= crc32.o
 obj-$(CONFIG_LIBCRC32C)	+= libcrc32c.o
+obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
 
 obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
 obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/
 
-host-progs	:= gen_crc32table
+hostprogs-y	:= gen_crc32table
 clean-files	:= crc32table.h
 
 $(obj)/crc32.o: $(obj)/crc32table.h
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 7eb16be30..8ffd202dc 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -408,3 +408,85 @@ int bitmap_parse(const char __user *ubuf, unsigned int ubuflen,
 	return 0;
 }
 EXPORT_SYMBOL(bitmap_parse);
+
+/**
+ *	bitmap_find_free_region - find a contiguous aligned mem region
+ *	@bitmap: an array of unsigned longs corresponding to the bitmap
+ *	@bits: number of bits in the bitmap
+ *	@order: region size to find (size is actually 1<<order)
+ *
+ * This is used to allocate a memory region from a bitmap.  The idea is
+ * that the region has to be 1<<order sized and 1<<order aligned (this
+ * makes the search algorithm much faster).
+ *
+ * The region is marked as set bits in the bitmap if a free one is
+ * found.
+ *
+ * Returns either beginning of region or negative error
+ */
+int bitmap_find_free_region(unsigned long *bitmap, int bits, int order)
+{
+	unsigned long mask;
+	int pages = 1 << order;
+	int i;
+
+	if(pages > BITS_PER_LONG)
+		return -EINVAL;
+
+	/* make a mask of the order */
+	mask = (1ul << (pages - 1));
+	mask += mask - 1;
+
+	/* run up the bitmap pages bits at a time */
+	for (i = 0; i < bits; i += pages) {
+		int index = i/BITS_PER_LONG;
+		int offset = i - (index * BITS_PER_LONG);
+		if((bitmap[index] & (mask << offset)) == 0) {
+			/* set region in bimap */
+			bitmap[index] |= (mask << offset);
+			return i;
+		}
+	}
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(bitmap_find_free_region);
+
+/**
+ *	bitmap_release_region - release allocated bitmap region
+ *	@bitmap: a pointer to the bitmap
+ *	@pos: the beginning of the region
+ *	@order: the order of the bits to release (number is 1<<order)
+ *
+ * This is the complement to __bitmap_find_free_region and releases
+ * the found region (by clearing it in the bitmap).
+ */
+void bitmap_release_region(unsigned long *bitmap, int pos, int order)
+{
+	int pages = 1 << order;
+	unsigned long mask = (1ul << (pages - 1));
+	int index = pos/BITS_PER_LONG;
+	int offset = pos - (index * BITS_PER_LONG);
+	mask += mask - 1;
+	bitmap[index] &= ~(mask << offset);
+}
+EXPORT_SYMBOL(bitmap_release_region);
+
+int bitmap_allocate_region(unsigned long *bitmap, int pos, int order)
+{
+	int pages = 1 << order;
+	unsigned long mask = (1ul << (pages - 1));
+	int index = pos/BITS_PER_LONG;
+	int offset = pos - (index * BITS_PER_LONG);
+
+	/* We don't do regions of pages > BITS_PER_LONG.  The
+	 * algorithm would be a simple look for multiple zeros in the
+	 * array, but there's no driver today that needs this.  If you
+	 * trip this BUG(), you get to code it... */
+	BUG_ON(pages > BITS_PER_LONG);
+	mask += mask - 1;
+	if (bitmap[index] & (mask << offset))
+		return -EBUSY;
+	bitmap[index] |= (mask << offset);
+	return 0;
+}
+EXPORT_SYMBOL(bitmap_allocate_region);
diff --git a/lib/idr.c b/lib/idr.c
index 6d1df639d..972eefcce 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -1,21 +1,17 @@
 /*
- * linux/kernel/id.c
- *
  * 2002-10-18  written by Jim Houston jim.houston@ccur.com
  *	Copyright (C) 2002 by Concurrent Computer Corporation
  *	Distributed under the GNU GPL license version 2.
  *
+ * Modified by George Anzinger to reuse immediately and to use
+ * find bit instructions.  Also removed _irq on spinlocks.
+ *
  * Small id to pointer translation service.  
  *
  * It uses a radix tree like structure as a sparse array indexed 
  * by the id to obtain the pointer.  The bitmap makes allocating
  * a new id quick.  
-
- * Modified by George Anzinger to reuse immediately and to use
- * find bit instructions.  Also removed _irq on spinlocks.
-
- * So here is what this bit of code does:
-
+ *
  * You call it to allocate an id (an int) an associate with that id a
  * pointer or what ever, we treat it as a (void *).  You can pass this
  * id to a user for him to pass back at a later time.  You then pass
@@ -26,78 +22,8 @@
  * don't need to go to the memory "store" during an id allocate, just 
  * so you don't need to be too concerned about locking and conflicts
  * with the slab allocator.
-
- * What you need to do is, since we don't keep the counter as part of
- * id / ptr pair, to keep a copy of it in the pointed to structure
- * (or else where) so that when you ask for a ptr you can varify that
- * the returned ptr is correct by comparing the id it contains with the one
- * you asked for.  In other words, we only did half the reuse protection.
- * Since the code depends on your code doing this check, we ignore high
- * order bits in the id, not just the count, but bits that would, if used,
- * index outside of the allocated ids.  In other words, if the largest id
- * currently allocated is 32 a look up will only look at the low 5 bits of
- * the id.  Since you will want to keep this id in the structure anyway
- * (if for no other reason than to be able to eliminate the id when the
- * structure is found in some other way) this seems reasonable.  If you
- * really think otherwise, the code to check these bits here, it is just
- * disabled with a #if 0.
-
-
- * So here are the complete details:
-
- *  include <linux/idr.h>
-
- * void idr_init(struct idr *idp)
-
- *   This function is use to set up the handle (idp) that you will pass
- *   to the rest of the functions.  The structure is defined in the
- *   header.
-
- * int idr_pre_get(struct idr *idp, unsigned gfp_mask)
-
- *   This function should be called prior to locking and calling the
- *   following function.  It pre allocates enough memory to satisfy the
- *   worst possible allocation.  Unless gfp_mask is GFP_ATOMIC, it can
- *   sleep, so must not be called with any spinlocks held.  If the system is
- *   REALLY out of memory this function returns 0, other wise 1.
-
- * int idr_get_new(struct idr *idp, void *ptr, int *id);
- 
- *   This is the allocate id function.  It should be called with any
- *   required locks.  In fact, in the SMP case, you MUST lock prior to
- *   calling this function to avoid possible out of memory problems.
- *   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 a -ENOSPC.  ptr is the pointer you want associated
- *   with the id.  The value is returned in the "id" field.  idr_get_new()
- *   returns a value in the range 0 ... 0x7fffffff
-
- * int idr_get_new_above(struct idr *idp, void *ptr, int start_id, int *id);
-
- *   Like idr_get_new(), but the returned id is guaranteed to be at or
- *   above start_id.
-
- * void *idr_find(struct idr *idp, int id);
- 
- *   returns the "ptr", given the id.  A NULL return indicates that the
- *   id is not valid (or you passed NULL in the idr_get_new(), shame on
- *   you).  This function must be called with a spinlock that prevents
- *   calling either idr_get_new() or idr_remove() or idr_find() while it
- *   is working.
-
- * void idr_remove(struct idr *idp, int id);
-
- *   removes the given id, freeing that slot and any memory that may
- *   now be unused.  See idr_find() for locking restrictions.
-
- * int idr_full(struct idr *idp);
-
- *   Returns true if the idr is full and false if not.
-
  */
 
-
-
 #ifndef TEST                        // to test in user space...
 #include <linux/slab.h>
 #include <linux/init.h>
@@ -106,18 +32,17 @@
 #include <linux/string.h>
 #include <linux/idr.h>
 
-
 static kmem_cache_t *idr_layer_cache;
 
-
-
 static struct idr_layer *alloc_layer(struct idr *idp)
 {
 	struct idr_layer *p;
 
 	spin_lock(&idp->lock);
-	if (!(p = idp->id_free))
+	if (!(p = idp->id_free)) {
+		spin_unlock(&idp->lock);
 		return NULL;
+	}
 	idp->id_free = p->ary[0];
 	idp->id_free_cnt--;
 	p->ary[0] = NULL;
@@ -137,6 +62,18 @@ static void free_layer(struct idr *idp, struct idr_layer *p)
 	spin_unlock(&idp->lock);
 }
 
+/**
+ * idr_pre_get - reserver resources for idr allocation
+ * @idp:	idr handle
+ * @gfp_mask:	memory allocation flags
+ *
+ * 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 idr_pre_get(struct idr *idp, unsigned gfp_mask)
 {
 	while (idp->id_free_cnt < IDR_FREE_MAX) {
@@ -271,6 +208,22 @@ build_up:
 	return(v);
 }
 
+/**
+ * idr_get_new_above - allocate new idr entry above a start id
+ * @idp: idr handle
+ * @ptr: pointer you want associated with the ide
+ * @start_id: id to start search at
+ * @id: pointer to the allocated handle
+ *
+ * This is the allocate id function.  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 idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id)
 {
 	int rv;
@@ -290,6 +243,21 @@ int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id)
 }
 EXPORT_SYMBOL(idr_get_new_above);
 
+/**
+ * idr_get_new - allocate new idr entry
+ * @idp: idr handle
+ * @ptr: pointer you want associated with the ide
+ * @id: pointer to the allocated handle
+ *
+ * This is the allocate id function.  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 idr_get_new(struct idr *idp, void *ptr, int *id)
 {
 	int rv;
@@ -338,6 +306,11 @@ static void sub_remove(struct idr *idp, int shift, int id)
 	}
 }
 
+/**
+ * idr_remove - remove the given id and free it's slot
+ * idp: idr handle
+ * id: uniqueue key
+ */
 void idr_remove(struct idr *idp, int id)
 {
 	struct idr_layer *p;
@@ -365,6 +338,17 @@ void idr_remove(struct idr *idp, int id)
 }
 EXPORT_SYMBOL(idr_remove);
 
+/**
+ * idr_find - return pointer for given id
+ * @idp: idr handle
+ * @id: lookup key
+ *
+ * Return the pointer given the id it has been registered with.  A %NULL
+ * return indicates that @id is not valid or you passed %NULL in
+ * idr_get_new().
+ *
+ * The caller must serialize idr_find() vs idr_get_new() and idr_remove().
+ */
 void *idr_find(struct idr *idp, int id)
 {
 	int n;
@@ -372,17 +356,13 @@ void *idr_find(struct idr *idp, int id)
 
 	n = idp->layers * IDR_BITS;
 	p = idp->top;
-#if 0
-	/*
-	 * This tests to see if bits outside the current tree are
-	 * present.  If so, tain't one of ours!
-	 */
-	if ( unlikely( (id & ~(~0 << MAX_ID_SHIFT)) >> (n + IDR_BITS)))
-	     return NULL;
-#endif
+
 	/* Mask off upper bits we don't use for the search. */
 	id &= MAX_ID_MASK;
 
+	if (id >= (1 << n))
+		return NULL;
+
 	while (n > 0 && p) {
 		n -= IDR_BITS;
 		p = p->ary[(id >> n) & IDR_MASK];
@@ -405,6 +385,13 @@ static  int init_id_cache(void)
 	return 0;
 }
 
+/**
+ * idr_init - initialize idr handle
+ * @idp:	idr handle
+ *
+ * This function is use to set up the handle (@idp) that you will pass
+ * to the rest of the functions.
+ */
 void idr_init(struct idr *idp)
 {
 	init_id_cache();
@@ -412,4 +399,3 @@ void idr_init(struct idr *idp)
 	spin_lock_init(&idp->lock);
 }
 EXPORT_SYMBOL(idr_init);
-
diff --git a/lib/kobject.c b/lib/kobject.c
index 781f3e896..a971b8e55 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -58,14 +58,11 @@ static int create_dir(struct kobject * kobj)
 	return error;
 }
 
-
 static inline struct kobject * to_kobj(struct list_head * entry)
 {
 	return container_of(entry,struct kobject,entry);
 }
 
-
-#ifdef CONFIG_HOTPLUG
 static int get_kobj_path_length(struct kset *kset, struct kobject *kobj)
 {
 	int length = 1;
@@ -98,6 +95,31 @@ static void fill_kobj_path(struct kset *kset, struct kobject *kobj, char *path,
 	pr_debug("%s: path = '%s'\n",__FUNCTION__,path);
 }
 
+/**
+ * kobject_get_path - generate and return the path associated with a given kobj
+ * and kset pair.  The result must be freed by the caller with kfree().
+ *
+ * @kset:	kset in question, with which to build the path
+ * @kobj:	kobject in question, with which to build the path
+ * @gfp_mask:	the allocation type used to allocate the path
+ */
+char * kobject_get_path(struct kset *kset, struct kobject *kobj, int gfp_mask)
+{
+	char *path;
+	int len;
+
+	len = get_kobj_path_length(kset, kobj);
+	path = kmalloc(len, gfp_mask);
+	if (!path)
+		return NULL;
+	memset(path, 0x00, len);
+	fill_kobj_path(kset, kobj, path, len);
+
+	return path;
+}
+
+#ifdef CONFIG_HOTPLUG
+
 #define BUFFER_SIZE	1024	/* should be enough memory for the env */
 #define NUM_ENVP	32	/* number of env pointers */
 static unsigned long sequence_num;
@@ -112,7 +134,6 @@ static void kset_hotplug(const char *action, struct kset *kset,
 	char *scratch;
 	int i = 0;
 	int retval;
-	int kobj_path_length;
 	char *kobj_path = NULL;
 	char *name = NULL;
 	unsigned long seq;
@@ -163,12 +184,9 @@ static void kset_hotplug(const char *action, struct kset *kset,
 	envp [i++] = scratch;
 	scratch += sprintf(scratch, "SEQNUM=%ld", seq) + 1;
 
-	kobj_path_length = get_kobj_path_length (kset, kobj);
-	kobj_path = kmalloc (kobj_path_length, GFP_KERNEL);
+	kobj_path = kobject_get_path(kset, kobj, GFP_KERNEL);
 	if (!kobj_path)
 		goto exit;
-	memset (kobj_path, 0x00, kobj_path_length);
-	fill_kobj_path (kset, kobj, kobj_path, kobj_path_length);
 
 	envp [i++] = scratch;
 	scratch += sprintf (scratch, "DEVPATH=%s", kobj_path) + 1;
@@ -225,10 +243,9 @@ void kobject_hotplug(const char *action, struct kobject *kobj)
  *	kobject_init - initialize object.
  *	@kobj:	object in question.
  */
-
 void kobject_init(struct kobject * kobj)
 {
-	atomic_set(&kobj->refcount,1);
+ 	kref_init(&kobj->kref);
 	INIT_LIST_HEAD(&kobj->entry);
 	kobj->kset = kset_get(kobj->kset);
 }
@@ -325,7 +342,7 @@ int kobject_register(struct kobject * kobj)
  *	@kobj:	object.
  *	@name:	name. 
  *
- *	If strlen(name) < KOBJ_NAME_LEN, then use a dynamically allocated
+ *	If strlen(name) >= KOBJ_NAME_LEN, then use a dynamically allocated
  *	string that @kobj->k_name points to. Otherwise, use the static 
  *	@kobj->name array.
  */
@@ -429,10 +446,8 @@ void kobject_unregister(struct kobject * kobj)
 
 struct kobject * kobject_get(struct kobject * kobj)
 {
-	if (kobj) {
-		WARN_ON(!atomic_read(&kobj->refcount));
-		atomic_inc(&kobj->refcount);
-	}
+	if (kobj)
+		kref_get(&kobj->kref);
 	return kobj;
 }
 
@@ -459,17 +474,21 @@ void kobject_cleanup(struct kobject * kobj)
 		kobject_put(parent);
 }
 
+static void kobject_release(struct kref *kref)
+{
+	kobject_cleanup(container_of(kref, struct kobject, kref));
+}
+
 /**
  *	kobject_put - decrement refcount for object.
  *	@kobj:	object.
  *
  *	Decrement the refcount, and if 0, call kobject_cleanup().
  */
-
 void kobject_put(struct kobject * kobj)
 {
-	if (atomic_dec_and_test(&kobj->refcount))
-		kobject_cleanup(kobj);
+	if (kobj)
+		kref_put(&kobj->kref, kobject_release);
 }
 
 
@@ -626,7 +645,7 @@ void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a)
 	}
 }
 
-
+EXPORT_SYMBOL(kobject_get_path);
 EXPORT_SYMBOL(kobject_init);
 EXPORT_SYMBOL(kobject_register);
 EXPORT_SYMBOL(kobject_unregister);
diff --git a/lib/kref.c b/lib/kref.c
index ee141adbf..2218b7ae7 100644
--- a/lib/kref.c
+++ b/lib/kref.c
@@ -11,48 +11,45 @@
  *
  */
 
-/* #define DEBUG */
-
 #include <linux/kref.h>
 #include <linux/module.h>
 
 /**
  * kref_init - initialize object.
  * @kref: object in question.
- * @release: pointer to a function that will clean up the object
- *	     when the last reference to the object is released.
- *	     This pointer is required.
  */
-void kref_init(struct kref *kref, void (*release)(struct kref *kref))
+void kref_init(struct kref *kref)
 {
-	WARN_ON(release == NULL);
 	atomic_set(&kref->refcount,1);
-	kref->release = release;
 }
 
 /**
  * kref_get - increment refcount for object.
  * @kref: object.
  */
-struct kref *kref_get(struct kref *kref)
+void kref_get(struct kref *kref)
 {
 	WARN_ON(!atomic_read(&kref->refcount));
 	atomic_inc(&kref->refcount);
-	return kref;
 }
 
 /**
  * kref_put - decrement refcount for object.
  * @kref: object.
+ * @release: pointer to the function that will clean up the object when the
+ *	     last reference to the object is released.
+ *	     This pointer is required, and it is not acceptable to pass kfree
+ *	     in as this function.
  *
- * Decrement the refcount, and if 0, call kref->release().
+ * Decrement the refcount, and if 0, call release().
  */
-void kref_put(struct kref *kref)
+void kref_put(struct kref *kref, void (*release) (struct kref *kref))
 {
-	if (atomic_dec_and_test(&kref->refcount)) {
-		pr_debug("kref cleaning up\n");
-		kref->release(kref);
-	}
+	WARN_ON(release == NULL);
+	WARN_ON(release == (void (*)(struct kref *))kfree);
+
+	if (atomic_dec_and_test(&kref->refcount))
+		release(kref);
 }
 
 EXPORT_SYMBOL(kref_init);
diff --git a/lib/rbtree.c b/lib/rbtree.c
index 621552c34..14b791ac5 100644
--- a/lib/rbtree.c
+++ b/lib/rbtree.c
@@ -312,6 +312,19 @@ struct rb_node *rb_first(struct rb_root *root)
 }
 EXPORT_SYMBOL(rb_first);
 
+struct rb_node *rb_last(struct rb_root *root)
+{
+	struct rb_node	*n;
+
+	n = root->rb_node;
+	if (!n)
+		return NULL;
+	while (n->rb_right)
+		n = n->rb_right;
+	return n;
+}
+EXPORT_SYMBOL(rb_last);
+
 struct rb_node *rb_next(struct rb_node *node)
 {
 	/* If we have a right-hand child, go down and then left as far
diff --git a/lib/rwsem.c b/lib/rwsem.c
index 465ec7256..924c14e0b 100644
--- a/lib/rwsem.c
+++ b/lib/rwsem.c
@@ -255,10 +255,10 @@ struct rw_semaphore fastcall *rwsem_downgrade_wake(struct rw_semaphore *sem)
 	return sem;
 }
 
-EXPORT_SYMBOL_NOVERS(rwsem_down_read_failed);
-EXPORT_SYMBOL_NOVERS(rwsem_down_write_failed);
-EXPORT_SYMBOL_NOVERS(rwsem_wake);
-EXPORT_SYMBOL_NOVERS(rwsem_downgrade_wake);
+EXPORT_SYMBOL(rwsem_down_read_failed);
+EXPORT_SYMBOL(rwsem_down_write_failed);
+EXPORT_SYMBOL(rwsem_wake);
+EXPORT_SYMBOL(rwsem_downgrade_wake);
 #if RWSEM_DEBUG
 EXPORT_SYMBOL(rwsemtrace);
 #endif
diff --git a/lib/zlib_inflate/Makefile b/lib/zlib_inflate/Makefile
index 0408851f6..221c139e0 100644
--- a/lib/zlib_inflate/Makefile
+++ b/lib/zlib_inflate/Makefile
@@ -16,4 +16,4 @@
 obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate.o
 
 zlib_inflate-objs := infblock.o infcodes.o inffast.o inflate.o \
-		     inftrees.o infutil.o inflate_syms.o
+		     inflate_sync.o inftrees.o infutil.o inflate_syms.o
diff --git a/lib/zlib_inflate/infblock.c b/lib/zlib_inflate/infblock.c
index 7bb7db5cd..50f21ca4e 100644
--- a/lib/zlib_inflate/infblock.c
+++ b/lib/zlib_inflate/infblock.c
@@ -139,7 +139,7 @@ int zlib_inflate_blocks(
             uInt bl, bd;
             inflate_huft *tl, *td;
 
-            zlib_inflate_trees_fixed(&bl, &bd, &tl, &td, z);
+            zlib_inflate_trees_fixed(&bl, &bd, &tl, &td, s->hufts, z);
             s->sub.decode.codes = zlib_inflate_codes_new(bl, bd, tl, td, z);
             if (s->sub.decode.codes == NULL)
             {
diff --git a/lib/zlib_inflate/inflate.c b/lib/zlib_inflate/inflate.c
index 974a0fe85..3d94cb90c 100644
--- a/lib/zlib_inflate/inflate.c
+++ b/lib/zlib_inflate/inflate.c
@@ -53,8 +53,6 @@ int zlib_inflateInit2_(
       return Z_VERSION_ERROR;
 
   /* initialize state */
-  if (z == NULL)
-    return Z_STREAM_ERROR;
   z->msg = NULL;
   z->state = &WS(z)->internal_state;
   z->state->blocks = NULL;
@@ -248,144 +246,3 @@ int zlib_inflate(
   z->state->sub.marker = 0;       /* can try inflateSync */
   return Z_DATA_ERROR;
 }
-
-
-int zlib_inflateSync(
-	z_streamp z
-)
-{
-  uInt n;       /* number of bytes to look at */
-  Byte *p;      /* pointer to bytes */
-  uInt m;       /* number of marker bytes found in a row */
-  uLong r, w;   /* temporaries to save total_in and total_out */
-
-  /* set up */
-  if (z == NULL || z->state == NULL)
-    return Z_STREAM_ERROR;
-  if (z->state->mode != I_BAD)
-  {
-    z->state->mode = I_BAD;
-    z->state->sub.marker = 0;
-  }
-  if ((n = z->avail_in) == 0)
-    return Z_BUF_ERROR;
-  p = z->next_in;
-  m = z->state->sub.marker;
-
-  /* search */
-  while (n && m < 4)
-  {
-    static const Byte mark[4] = {0, 0, 0xff, 0xff};
-    if (*p == mark[m])
-      m++;
-    else if (*p)
-      m = 0;
-    else
-      m = 4 - m;
-    p++, n--;
-  }
-
-  /* restore */
-  z->total_in += p - z->next_in;
-  z->next_in = p;
-  z->avail_in = n;
-  z->state->sub.marker = m;
-
-  /* return no joy or set up to restart on a new block */
-  if (m != 4)
-    return Z_DATA_ERROR;
-  r = z->total_in;  w = z->total_out;
-  zlib_inflateReset(z);
-  z->total_in = r;  z->total_out = w;
-  z->state->mode = BLOCKS;
-  return Z_OK;
-}
-
-
-/* Returns true if inflate is currently at the end of a block generated
- * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
- * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
- * but removes the length bytes of the resulting empty stored block. When
- * decompressing, PPP checks that at the end of input packet, inflate is
- * waiting for these length bytes.
- */
-int zlib_inflateSyncPoint(
-	z_streamp z
-)
-{
-  if (z == NULL || z->state == NULL || z->state->blocks == NULL)
-    return Z_STREAM_ERROR;
-  return zlib_inflate_blocks_sync_point(z->state->blocks);
-}
-
-/*
- * This subroutine adds the data at next_in/avail_in to the output history
- * without performing any output.  The output buffer must be "caught up";
- * i.e. no pending output (hence s->read equals s->write), and the state must
- * be BLOCKS (i.e. we should be willing to see the start of a series of
- * BLOCKS).  On exit, the output will also be caught up, and the checksum
- * will have been updated if need be.
- */
-static int zlib_inflate_addhistory(inflate_blocks_statef *s,
-				      z_stream              *z)
-{
-    uLong b;              /* bit buffer */  /* NOT USED HERE */
-    uInt k;               /* bits in bit buffer */ /* NOT USED HERE */
-    uInt t;               /* temporary storage */
-    Byte *p;              /* input data pointer */
-    uInt n;               /* bytes available there */
-    Byte *q;              /* output window write pointer */
-    uInt m;               /* bytes to end of window or read pointer */
-
-    if (s->read != s->write)
-	return Z_STREAM_ERROR;
-    if (s->mode != TYPE)
-	return Z_DATA_ERROR;
-
-    /* we're ready to rock */
-    LOAD
-    /* while there is input ready, copy to output buffer, moving
-     * pointers as needed.
-     */
-    while (n) {
-	t = n;  /* how many to do */
-	/* is there room until end of buffer? */
-	if (t > m) t = m;
-	/* update check information */
-	if (s->checkfn != NULL)
-	    s->check = (*s->checkfn)(s->check, q, t);
-	memcpy(q, p, t);
-	q += t;
-	p += t;
-	n -= t;
-	z->total_out += t;
-	s->read = q;    /* drag read pointer forward */
-/*      WWRAP  */ 	/* expand WWRAP macro by hand to handle s->read */
-	if (q == s->end) {
-	    s->read = q = s->window;
-	    m = WAVAIL;
-	}
-    }
-    UPDATE
-    return Z_OK;
-}
-
-
-/*
- * This subroutine adds the data at next_in/avail_in to the output history
- * without performing any output.  The output buffer must be "caught up";
- * i.e. no pending output (hence s->read equals s->write), and the state must
- * be BLOCKS (i.e. we should be willing to see the start of a series of
- * BLOCKS).  On exit, the output will also be caught up, and the checksum
- * will have been updated if need be.
- */
-
-int zlib_inflateIncomp(
-	z_stream *z
-	
-)
-{
-    if (z->state->mode != BLOCKS)
-	return Z_DATA_ERROR;
-    return zlib_inflate_addhistory(z->state->blocks, z);
-}
diff --git a/lib/zlib_inflate/inftrees.c b/lib/zlib_inflate/inftrees.c
index b0b58b67e..874950ec4 100644
--- a/lib/zlib_inflate/inftrees.c
+++ b/lib/zlib_inflate/inftrees.c
@@ -374,21 +374,39 @@ int zlib_inflate_trees_dynamic(
 }
 
 
-/* build fixed tables only once--keep them here */
-#include "inffixed.h"
-
-
 int zlib_inflate_trees_fixed(
 	uInt *bl,                /* literal desired/actual bit depth */
 	uInt *bd,                /* distance desired/actual bit depth */
 	inflate_huft **tl,       /* literal/length tree result */
 	inflate_huft **td,       /* distance tree result */
+	inflate_huft *hp,       /* space for trees */
 	z_streamp z              /* for memory allocation */
 )
 {
-  *bl = fixed_bl;
-  *bd = fixed_bd;
-  *tl = fixed_tl;
-  *td = fixed_td;
+  int i;                /* temporary variable */
+  unsigned l[288];      /* length list for huft_build */
+  uInt *v;              /* work area for huft_build */
+
+  /* set up literal table */
+  for (i = 0; i < 144; i++)
+    l[i] = 8;
+  for (; i < 256; i++)
+    l[i] = 9;
+  for (; i < 280; i++)
+    l[i] = 7;
+  for (; i < 288; i++)          /* make a complete, but wrong code set */
+    l[i] = 8;
+  *bl = 9;
+  v = WS(z)->tree_work_area_1;
+  if ((i = huft_build(l, 288, 257, cplens, cplext, tl, bl, hp,  &i, v)) != 0)
+    return i;
+
+  /* set up distance table */
+  for (i = 0; i < 30; i++)      /* make an incomplete code set */
+    l[i] = 5;
+  *bd = 5;
+  if ((i = huft_build(l, 30, 0, cpdist, cpdext, td, bd, hp, &i, v)) > 1)
+    return i;
+
   return Z_OK;
 }
diff --git a/lib/zlib_inflate/inftrees.h b/lib/zlib_inflate/inftrees.h
index efb3d8a4f..e37705adc 100644
--- a/lib/zlib_inflate/inftrees.h
+++ b/lib/zlib_inflate/inftrees.h
@@ -58,6 +58,7 @@ extern int zlib_inflate_trees_fixed (
     uInt *,                     /* distance desired/actual bit depth */
     inflate_huft **,            /* literal/length tree result */
     inflate_huft **,            /* distance tree result */
+    inflate_huft *,             /* space for trees */
     z_streamp);                 /* for memory allocation */
 
 #endif /* _INFTREES_H */
diff --git a/mm/Makefile b/mm/Makefile
index d22feb38a..7cea59b58 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -5,13 +5,16 @@
 mmu-y			:= nommu.o
 mmu-$(CONFIG_MMU)	:= fremap.o highmem.o madvise.o memory.o mincore.o \
 			   mlock.o mmap.o mprotect.o mremap.o msync.o rmap.o \
-			   shmem.o vmalloc.o
+			   vmalloc.o
 
 obj-y			:= bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
 			   page_alloc.o page-writeback.o pdflush.o prio_tree.o \
 			   readahead.o slab.o swap.o truncate.o vmscan.o \
 			   $(mmu-y)
 
-obj-$(CONFIG_SWAP)	+= page_io.o swap_state.o swapfile.o
+obj-$(CONFIG_SWAP)	+= page_io.o swap_state.o swapfile.o thrash.o
 obj-$(CONFIG_HUGETLBFS)	+= hugetlb.o
 obj-$(CONFIG_NUMA) 	+= mempolicy.o
+obj-$(CONFIG_SHMEM) += shmem.o
+obj-$(CONFIG_TINY_SHMEM) += tiny-shmem.o
+
diff --git a/mm/bootmem.c b/mm/bootmem.c
index 966135b90..092d85176 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -259,6 +259,7 @@ static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat)
 	unsigned long i, count, total = 0;
 	unsigned long idx;
 	unsigned long *map; 
+	int gofast = 0;
 
 	BUG_ON(!bdata->node_bootmem_map);
 
@@ -267,14 +268,32 @@ static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat)
 	page = virt_to_page(phys_to_virt(bdata->node_boot_start));
 	idx = bdata->node_low_pfn - (bdata->node_boot_start >> PAGE_SHIFT);
 	map = bdata->node_bootmem_map;
+	/* Check physaddr is O(LOG2(BITS_PER_LONG)) page aligned */
+	if (bdata->node_boot_start == 0 ||
+	    ffs(bdata->node_boot_start) - PAGE_SHIFT > ffs(BITS_PER_LONG))
+		gofast = 1;
 	for (i = 0; i < idx; ) {
 		unsigned long v = ~map[i / BITS_PER_LONG];
-		if (v) {
+		if (gofast && v == ~0UL) {
+			int j;
+
+			count += BITS_PER_LONG;
+			__ClearPageReserved(page);
+			set_page_count(page, 1);
+			for (j = 1; j < BITS_PER_LONG; j++) {
+				if (j + 16 < BITS_PER_LONG)
+					prefetchw(page + j + 16);
+				__ClearPageReserved(page + j);
+			}
+			__free_pages(page, ffs(BITS_PER_LONG)-1);
+			i += BITS_PER_LONG;
+			page += BITS_PER_LONG;
+		} else if (v) {
 			unsigned long m;
 			for (m = 1; m && i < idx; m<<=1, page++, i++) {
 				if (v & m) {
 					count++;
-					ClearPageReserved(page);
+					__ClearPageReserved(page);
 					set_page_count(page, 1);
 					__free_page(page);
 				}
@@ -294,7 +313,7 @@ static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat)
 	count = 0;
 	for (i = 0; i < ((bdata->node_low_pfn-(bdata->node_boot_start >> PAGE_SHIFT))/8 + PAGE_SIZE-1)/PAGE_SIZE; i++,page++) {
 		count++;
-		ClearPageReserved(page);
+		__ClearPageReserved(page);
 		set_page_count(page, 1);
 		__free_page(page);
 	}
diff --git a/mm/filemap.c b/mm/filemap.c
index ab85dcb49..272c3e0a6 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -60,7 +60,6 @@
  *      ->swap_list_lock
  *        ->swap_device_lock	(exclusive_swap_page, others)
  *          ->mapping->tree_lock
- *    ->page_map_lock()		(try_to_unmap_file)
  *
  *  ->i_sem
  *    ->i_mmap_lock		(truncate->unmap_mapping_range)
@@ -83,16 +82,20 @@
  *    ->sb_lock			(fs/fs-writeback.c)
  *    ->mapping->tree_lock	(__sync_single_inode)
  *
+ *  ->i_mmap_lock
+ *    ->anon_vma.lock		(vma_adjust)
+ *
+ *  ->anon_vma.lock
+ *    ->page_table_lock		(anon_vma_prepare and various)
+ *
  *  ->page_table_lock
  *    ->swap_device_lock	(try_to_unmap_one)
  *    ->private_lock		(try_to_unmap_one)
  *    ->tree_lock		(try_to_unmap_one)
  *    ->zone.lru_lock		(follow_page->mark_page_accessed)
- *    ->page_map_lock()		(page_add_anon_rmap)
- *      ->tree_lock		(page_remove_rmap->set_page_dirty)
- *      ->private_lock		(page_remove_rmap->set_page_dirty)
- *      ->inode_lock		(page_remove_rmap->set_page_dirty)
- *    ->anon_vma.lock		(anon_vma_prepare)
+ *    ->private_lock		(page_remove_rmap->set_page_dirty)
+ *    ->tree_lock		(page_remove_rmap->set_page_dirty)
+ *    ->inode_lock		(page_remove_rmap->set_page_dirty)
  *    ->inode_lock		(zap_pte_range->set_page_dirty)
  *    ->private_lock		(zap_pte_range->__set_page_dirty_buffers)
  *
@@ -142,20 +145,26 @@ static inline int sync_page(struct page *page)
 }
 
 /**
- * filemap_fdatawrite - start writeback against all of a mapping's dirty pages
+ * filemap_fdatawrite_range - start writeback against all of a mapping's
+ * dirty pages that lie within the byte offsets <start, end>
  * @mapping: address space structure to write
+ * @start: offset in bytes where the range starts
+ * @end : offset in bytes where the range ends
  *
  * If sync_mode is WB_SYNC_ALL then this is a "data integrity" operation, as
  * opposed to a regular memory * cleansing writeback.  The difference between
  * these two operations is that if a dirty page/buffer is encountered, it must
  * be waited upon, and not just skipped over.
  */
-static int __filemap_fdatawrite(struct address_space *mapping, int sync_mode)
+static int __filemap_fdatawrite_range(struct address_space *mapping,
+	loff_t start, loff_t end, int sync_mode)
 {
 	int ret;
 	struct writeback_control wbc = {
 		.sync_mode = sync_mode,
 		.nr_to_write = mapping->nrpages * 2,
+		.start = start,
+		.end = end,
 	};
 
 	if (mapping->backing_dev_info->memory_backed)
@@ -165,12 +174,25 @@ static int __filemap_fdatawrite(struct address_space *mapping, int sync_mode)
 	return ret;
 }
 
+static inline int __filemap_fdatawrite(struct address_space *mapping,
+	int sync_mode)
+{
+	return __filemap_fdatawrite_range(mapping, 0, 0, sync_mode);
+}
+
 int filemap_fdatawrite(struct address_space *mapping)
 {
 	return __filemap_fdatawrite(mapping, WB_SYNC_ALL);
 }
 EXPORT_SYMBOL(filemap_fdatawrite);
 
+int filemap_fdatawrite_range(struct address_space *mapping,
+	loff_t start, loff_t end)
+{
+	return __filemap_fdatawrite_range(mapping, start, end, WB_SYNC_ALL);
+}
+EXPORT_SYMBOL(filemap_fdatawrite_range);
+
 /*
  * This is a mostly non-blocking flush.  Not suitable for data-integrity
  * purposes - I/O may not be started against all dirty pages.
@@ -198,7 +220,8 @@ static int wait_on_page_writeback_range(struct address_space *mapping,
 
 	pagevec_init(&pvec, 0);
 	index = start;
-	while ((nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
+	while ((index <= end) &&
+			(nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
 			PAGECACHE_TAG_WRITEBACK,
 			min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1)) != 0) {
 		unsigned i;
@@ -206,6 +229,10 @@ static int wait_on_page_writeback_range(struct address_space *mapping,
 		for (i = 0; i < nr_pages; i++) {
 			struct page *page = pvec.pages[i];
 
+			/* until radix tree lookup accepts end_index */
+			if (page->index > end)
+				continue;
+
 			wait_on_page_writeback(page);
 			if (PageError(page))
 				ret = -EIO;
@@ -223,6 +250,35 @@ static int wait_on_page_writeback_range(struct address_space *mapping,
 	return ret;
 }
 
+/*
+ * Write and wait upon all the pages in the passed range.  This is a "data
+ * integrity" operation.  It waits upon in-flight writeout before starting and
+ * waiting upon new writeout.  If there was an IO error, return it.
+ *
+ * We need to re-take i_sem during the generic_osync_inode list walk because
+ * it is otherwise livelockable.
+ */
+int sync_page_range(struct inode *inode, struct address_space *mapping,
+			loff_t pos, size_t count)
+{
+	pgoff_t start = pos >> PAGE_CACHE_SHIFT;
+	pgoff_t end = (pos + count - 1) >> PAGE_CACHE_SHIFT;
+	int ret;
+
+	if (mapping->backing_dev_info->memory_backed || !count)
+		return 0;
+	ret = filemap_fdatawrite_range(mapping, pos, pos + count - 1);
+	if (ret == 0) {
+		down(&inode->i_sem);
+		ret = generic_osync_inode(inode, mapping, OSYNC_METADATA);
+		up(&inode->i_sem);
+	}
+	if (ret == 0)
+		ret = wait_on_page_writeback_range(mapping, start, end);
+	return ret;
+}
+EXPORT_SYMBOL(sync_page_range);
+
 /**
  * filemap_fdatawait - walk the list of under-writeback pages of the given
  *     address space and wait for all of them.
@@ -231,9 +287,14 @@ static int wait_on_page_writeback_range(struct address_space *mapping,
  */
 int filemap_fdatawait(struct address_space *mapping)
 {
-	return wait_on_page_writeback_range(mapping, 0, -1);
-}
+	loff_t i_size = i_size_read(mapping->host);
+
+	if (i_size == 0)
+		return 0;
 
+	return wait_on_page_writeback_range(mapping, 0,
+				(i_size - 1) >> PAGE_CACHE_SHIFT);
+}
 EXPORT_SYMBOL(filemap_fdatawait);
 
 int filemap_write_and_wait(struct address_space *mapping)
@@ -644,13 +705,15 @@ EXPORT_SYMBOL(grab_cache_page_nowait);
  *
  * This is really ugly. But the goto's actually try to clarify some
  * of the logic when it comes to error handling etc.
- * - note the struct file * is only passed for the use of readpage
+ *
+ * Note the struct file* is only passed for the use of readpage.  It may be
+ * NULL.
  */
 void do_generic_mapping_read(struct address_space *mapping,
 			     struct file_ra_state *_ra,
-			     struct file * filp,
+			     struct file *filp,
 			     loff_t *ppos,
-			     read_descriptor_t * desc,
+			     read_descriptor_t *desc,
 			     read_actor_t actor)
 {
 	struct inode *inode = mapping->host;
@@ -665,14 +728,26 @@ void do_generic_mapping_read(struct address_space *mapping,
 	offset = *ppos & ~PAGE_CACHE_MASK;
 
 	isize = i_size_read(inode);
-	end_index = isize >> PAGE_CACHE_SHIFT;
-	if (index > end_index)
+	if (!isize)
 		goto out;
 
+	end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
 	for (;;) {
 		struct page *page;
 		unsigned long nr, ret;
 
+		/* nr is the maximum number of bytes to copy from this page */
+		nr = PAGE_CACHE_SIZE;
+		if (index >= end_index) {
+			if (index > end_index)
+				goto out;
+			nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
+			if (nr <= offset) {
+				goto out;
+			}
+		}
+		nr = nr - offset;
+
 		cond_resched();
 		page_cache_readahead(mapping, &ra, filp, index);
 
@@ -685,16 +760,6 @@ find_page:
 		if (!PageUptodate(page))
 			goto page_not_up_to_date;
 page_ok:
-		/* nr is the maximum number of bytes to copy from this page */
-		nr = PAGE_CACHE_SIZE;
-		if (index == end_index) {
-			nr = isize & ~PAGE_CACHE_MASK;
-			if (nr <= offset) {
-				page_cache_release(page);
-				goto out;
-			}
-		}
-		nr = nr - offset;
 
 		/* If users can be writing to this page using arbitrary
 		 * virtual addresses, take care about potential aliasing
@@ -770,11 +835,22 @@ readpage:
 		 * another truncate extends the file - this is desired though).
 		 */
 		isize = i_size_read(inode);
-		end_index = isize >> PAGE_CACHE_SHIFT;
-		if (index > end_index) {
+		end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
+		if (unlikely(!isize || index > end_index)) {
 			page_cache_release(page);
 			goto out;
 		}
+
+		/* nr is the maximum number of bytes to copy from this page */
+		nr = PAGE_CACHE_SIZE;
+		if (index == end_index) {
+			nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
+			if (nr <= offset) {
+				page_cache_release(page);
+				goto out;
+			}
+		}
+		nr = nr - offset;
 		goto page_ok;
 
 readpage_error:
@@ -814,7 +890,8 @@ out:
 	*ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
 	if (cached_page)
 		page_cache_release(cached_page);
-	file_accessed(filp);
+	if (filp)
+		file_accessed(filp);
 }
 
 EXPORT_SYMBOL(do_generic_mapping_read);
@@ -834,7 +911,8 @@ int file_read_actor(read_descriptor_t *desc, struct page *page,
 	 */
 	if (!fault_in_pages_writeable(desc->arg.buf, size)) {
 		kaddr = kmap_atomic(page, KM_USER0);
-		left = __copy_to_user(desc->arg.buf, kaddr + offset, size);
+		left = __copy_to_user_inatomic(desc->arg.buf,
+						kaddr + offset, size);
 		kunmap_atomic(kaddr, KM_USER0);
 		if (left == 0)
 			goto success;
@@ -1195,6 +1273,7 @@ no_cached_page:
 	 * effect.
 	 */
 	error = page_cache_read(file, pgoff);
+	grab_swap_token();
 
 	/*
 	 * The page we want has now been added to the page cache.
@@ -1431,7 +1510,7 @@ repeat:
 	return 0;
 }
 
-static struct vm_operations_struct generic_file_vm_ops = {
+struct vm_operations_struct generic_file_vm_ops = {
 	.nopage		= filemap_nopage,
 	.populate	= filemap_populate,
 };
@@ -1630,7 +1709,7 @@ filemap_copy_from_user(struct page *page, unsigned long offset,
 	int left;
 
 	kaddr = kmap_atomic(page, KM_USER0);
-	left = __copy_from_user(kaddr + offset, buf, bytes);
+	left = __copy_from_user_inatomic(kaddr + offset, buf, bytes);
 	kunmap_atomic(kaddr, KM_USER0);
 
 	if (left != 0) {
@@ -1653,7 +1732,7 @@ __filemap_copy_from_user_iovec(char *vaddr,
 		int copy = min(bytes, iov->iov_len - base);
 
 		base = 0;
-		left = __copy_from_user(vaddr, buf, copy);
+		left = __copy_from_user_inatomic(vaddr, buf, copy);
 		copied += copy;
 		bytes -= copy;
 		vaddr += copy;
@@ -1802,116 +1881,64 @@ inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count, i
 
 EXPORT_SYMBOL(generic_write_checks);
 
-/*
- * Write to a file through the page cache. 
- * Called under i_sem for S_ISREG files.
- *
- * We put everything into the page cache prior to writing it. This is not a
- * problem when writing full pages. With partial pages, however, we first have
- * to read the data into the cache, then dirty the page, and finally schedule
- * it for writing by marking it dirty.
- *							okir@monad.swb.de
- */
 ssize_t
-generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
-				unsigned long nr_segs, loff_t *ppos)
+generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
+		unsigned long *nr_segs, loff_t pos, loff_t *ppos,
+		size_t count, size_t ocount)
+{
+	struct file	*file = iocb->ki_filp;
+	struct address_space *mapping = file->f_mapping;
+	struct inode	*inode = mapping->host;
+	ssize_t		written;
+
+	if (count != ocount)
+		*nr_segs = iov_shorten((struct iovec *)iov, *nr_segs, count);
+
+	written = generic_file_direct_IO(WRITE, iocb, iov, pos, *nr_segs);
+	if (written > 0) {
+		loff_t end = pos + written;
+		if (end > i_size_read(inode) && !S_ISBLK(inode->i_mode)) {
+			i_size_write(inode,  end);
+			mark_inode_dirty(inode);
+		}
+		*ppos = end;
+	}
+
+	/*
+	 * Sync the fs metadata but not the minor inode changes and
+	 * of course not the data as we did direct DMA for the IO.
+	 * i_sem is held, which protects generic_osync_inode() from
+	 * livelocking.
+	 */
+	if (written >= 0 && file->f_flags & O_SYNC)
+		generic_osync_inode(inode, mapping, OSYNC_METADATA);
+	if (written == count && !is_sync_kiocb(iocb))
+		written = -EIOCBQUEUED;
+	return written;
+}
+
+EXPORT_SYMBOL(generic_file_direct_write);
+
+ssize_t
+generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
+		unsigned long nr_segs, loff_t pos, loff_t *ppos,
+		size_t count, ssize_t written)
 {
 	struct file *file = iocb->ki_filp;
 	struct address_space * mapping = file->f_mapping;
 	struct address_space_operations *a_ops = mapping->a_ops;
-	size_t ocount;		/* original count */
-	size_t count;		/* after file limit checks */
 	struct inode 	*inode = mapping->host;
 	long		status = 0;
-	loff_t		pos;
 	struct page	*page;
 	struct page	*cached_page = NULL;
-	const int	isblk = S_ISBLK(inode->i_mode);
-	ssize_t		written;
-	ssize_t		err;
 	size_t		bytes;
 	struct pagevec	lru_pvec;
 	const struct iovec *cur_iov = iov; /* current iovec */
 	size_t		iov_base = 0;	   /* offset in the current iovec */
-	unsigned long	seg;
 	char __user	*buf;
 
-	ocount = 0;
-	for (seg = 0; seg < nr_segs; seg++) {
-		const struct iovec *iv = &iov[seg];
-
-		/*
-		 * If any segment has a negative length, or the cumulative
-		 * length ever wraps negative then return -EINVAL.
-		 */
-		ocount += iv->iov_len;
-		if (unlikely((ssize_t)(ocount|iv->iov_len) < 0))
-			return -EINVAL;
-		if (access_ok(VERIFY_READ, iv->iov_base, iv->iov_len))
-			continue;
-		if (seg == 0)
-			return -EFAULT;
-		nr_segs = seg;
-		ocount -= iv->iov_len;	/* This segment is no good */
-		break;
-	}
-
-	count = ocount;
-	pos = *ppos;
 	pagevec_init(&lru_pvec, 0);
 
-	/* We can write back this queue in page reclaim */
-	current->backing_dev_info = mapping->backing_dev_info;
-	written = 0;
-
-	err = generic_write_checks(file, &pos, &count, isblk);
-	if (err)
-		goto out;
-
-	if (count == 0)
-		goto out;
-
-	err = remove_suid(file->f_dentry);
-	if (err)
-		goto out;
-
-	inode_update_time(inode, 1);
-
-	/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
-	if (unlikely(file->f_flags & O_DIRECT)) {
-		if (count != ocount)
-			nr_segs = iov_shorten((struct iovec *)iov,
-						nr_segs, count);
-		written = generic_file_direct_IO(WRITE, iocb,
-					iov, pos, nr_segs);
-		if (written > 0) {
-			loff_t end = pos + written;
-			if (end > i_size_read(inode) && !isblk) {
-				i_size_write(inode,  end);
-				mark_inode_dirty(inode);
-			}
-			*ppos = end;
-		}
-		/*
-		 * Sync the fs metadata but not the minor inode changes and
-		 * of course not the data as we did direct DMA for the IO.
-		 * i_sem is held, which protects generic_osync_inode() from
-		 * livelocking.
-		 */
-		if (written >= 0 && file->f_flags & O_SYNC)
-			status = generic_osync_inode(inode, mapping, OSYNC_METADATA);
-		if (written == count && !is_sync_kiocb(iocb))
-			written = -EIOCBQUEUED;
-		if (written < 0 || written == count)
-			goto out_status;
-		/*
-		 * direct-io write to a hole: fall through to buffered I/O
-		 * for completing the rest of the request.
-		 */
-		pos += written;
-		count -= written;
-	}
-
 	buf = iov->iov_base + written;	/* handle partial DIO write */
 	do {
 		unsigned long index;
@@ -1992,11 +2019,13 @@ generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
 	/*
 	 * For now, when the user asks for O_SYNC, we'll actually give O_DSYNC
 	 */
-	if (status >= 0) {
-		if ((file->f_flags & O_SYNC) || IS_SYNC(inode))
-			status = generic_osync_inode(inode, mapping,
-					OSYNC_METADATA|OSYNC_DATA);
-	}
+	if (likely(status >= 0)) {
+		if (unlikely((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
+			if (!a_ops->writepage || !is_sync_kiocb(iocb))
+				status = generic_osync_inode(inode, mapping,
+						OSYNC_METADATA|OSYNC_DATA);
+		}
+  	}
 	
 	/*
 	 * If we get here for O_DIRECT writes then we must have fallen through
@@ -2006,12 +2035,85 @@ generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
 	if (unlikely(file->f_flags & O_DIRECT) && written)
 		status = filemap_write_and_wait(mapping);
 
-out_status:	
-	err = written ? written : status;
-out:
 	pagevec_lru_add(&lru_pvec);
+	return written ? written : status;
+}
+
+EXPORT_SYMBOL(generic_file_buffered_write);
+
+ssize_t
+generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov,
+				unsigned long nr_segs, loff_t *ppos)
+{
+	struct file *file = iocb->ki_filp;
+	struct address_space * mapping = file->f_mapping;
+	size_t ocount;		/* original count */
+	size_t count;		/* after file limit checks */
+	struct inode 	*inode = mapping->host;
+	unsigned long	seg;
+	loff_t		pos;
+	ssize_t		written;
+	ssize_t		err;
+
+	ocount = 0;
+	for (seg = 0; seg < nr_segs; seg++) {
+		const struct iovec *iv = &iov[seg];
+
+		/*
+		 * If any segment has a negative length, or the cumulative
+		 * length ever wraps negative then return -EINVAL.
+		 */
+		ocount += iv->iov_len;
+		if (unlikely((ssize_t)(ocount|iv->iov_len) < 0))
+			return -EINVAL;
+		if (access_ok(VERIFY_READ, iv->iov_base, iv->iov_len))
+			continue;
+		if (seg == 0)
+			return -EFAULT;
+		nr_segs = seg;
+		ocount -= iv->iov_len;	/* This segment is no good */
+		break;
+	}
+
+	count = ocount;
+	pos = *ppos;
+
+	/* We can write back this queue in page reclaim */
+	current->backing_dev_info = mapping->backing_dev_info;
+	written = 0;
+
+	err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
+	if (err)
+		goto out;
+
+	if (count == 0)
+		goto out;
+
+	err = remove_suid(file->f_dentry);
+	if (err)
+		goto out;
+
+	inode_update_time(inode, 1);
+
+	/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
+	if (unlikely(file->f_flags & O_DIRECT)) {
+		written = generic_file_direct_write(iocb, iov,
+				&nr_segs, pos, ppos, count, ocount);
+		if (written < 0 || written == count)
+			goto out;
+		/*
+		 * direct-io write to a hole: fall through to buffered I/O
+		 * for completing the rest of the request.
+		 */
+		pos += written;
+		count -= written;
+	}
+
+	written = generic_file_buffered_write(iocb, iov, nr_segs,
+			pos, ppos, count, written);
+out:
 	current->backing_dev_info = NULL;
-	return err;
+	return written ? written : err;
 }
 
 EXPORT_SYMBOL(generic_file_aio_write_nolock);
@@ -2036,36 +2138,52 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const char __user *buf,
 			       size_t count, loff_t pos)
 {
 	struct file *file = iocb->ki_filp;
-	struct inode *inode = file->f_mapping->host;
-	ssize_t err;
-	struct iovec local_iov = { .iov_base = (void __user *)buf, .iov_len = count };
+	struct address_space *mapping = file->f_mapping;
+	struct inode *inode = mapping->host;
+	ssize_t ret;
+	struct iovec local_iov = { .iov_base = (void __user *)buf,
+					.iov_len = count };
 
 	BUG_ON(iocb->ki_pos != pos);
 
 	down(&inode->i_sem);
-	err = generic_file_aio_write_nolock(iocb, &local_iov, 1, 
+	ret = generic_file_aio_write_nolock(iocb, &local_iov, 1,
 						&iocb->ki_pos);
 	up(&inode->i_sem);
 
-	return err;
-}
+	if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
+		ssize_t err;
 
+		err = sync_page_range(inode, mapping, pos, ret);
+		if (err < 0)
+			ret = err;
+	}
+	return ret;
+}
 EXPORT_SYMBOL(generic_file_aio_write);
 
 ssize_t generic_file_write(struct file *file, const char __user *buf,
 			   size_t count, loff_t *ppos)
 {
-	struct inode	*inode = file->f_mapping->host;
-	ssize_t		err;
-	struct iovec local_iov = { .iov_base = (void __user *)buf, .iov_len = count };
+	struct address_space *mapping = file->f_mapping;
+	struct inode *inode = mapping->host;
+	ssize_t	ret;
+	struct iovec local_iov = { .iov_base = (void __user *)buf,
+					.iov_len = count };
 
 	down(&inode->i_sem);
-	err = generic_file_write_nolock(file, &local_iov, 1, ppos);
+	ret = generic_file_write_nolock(file, &local_iov, 1, ppos);
 	up(&inode->i_sem);
 
-	return err;
-}
+	if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
+		ssize_t err;
 
+		err = sync_page_range(inode, mapping, *ppos - ret, ret);
+		if (err < 0)
+			ret = err;
+	}
+	return ret;
+}
 EXPORT_SYMBOL(generic_file_write);
 
 ssize_t generic_file_readv(struct file *filp, const struct iovec *iov,
@@ -2084,14 +2202,23 @@ ssize_t generic_file_readv(struct file *filp, const struct iovec *iov,
 EXPORT_SYMBOL(generic_file_readv);
 
 ssize_t generic_file_writev(struct file *file, const struct iovec *iov,
-			unsigned long nr_segs, loff_t * ppos) 
+			unsigned long nr_segs, loff_t *ppos)
 {
-	struct inode *inode = file->f_mapping->host;
+	struct address_space *mapping = file->f_mapping;
+	struct inode *inode = mapping->host;
 	ssize_t ret;
 
 	down(&inode->i_sem);
 	ret = generic_file_write_nolock(file, iov, nr_segs, ppos);
 	up(&inode->i_sem);
+
+	if (ret > 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
+		int err;
+
+		err = sync_page_range(inode, mapping, *ppos - ret, ret);
+		if (err < 0)
+			ret = err;
+	}
 	return ret;
 }
 
diff --git a/mm/fremap.c b/mm/fremap.c
index 2f211f502..eaa833350 100644
--- a/mm/fremap.c
+++ b/mm/fremap.c
@@ -226,9 +226,7 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size,
 			flush_dcache_mmap_lock(mapping);
 			vma->vm_flags |= VM_NONLINEAR;
 			vma_prio_tree_remove(vma, &mapping->i_mmap);
-			vma_prio_tree_init(vma);
-			list_add_tail(&vma->shared.vm_set.list,
-					&mapping->i_mmap_nonlinear);
+			vma_nonlinear_insert(vma, &mapping->i_mmap_nonlinear);
 			flush_dcache_mmap_unlock(mapping);
 			spin_unlock(&mapping->i_mmap_lock);
 		}
diff --git a/mm/highmem.c b/mm/highmem.c
index 432da5b68..c190cf80a 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -284,7 +284,7 @@ static void copy_to_high_bio_irq(struct bio *to, struct bio *from)
 	struct bio_vec *tovec, *fromvec;
 	int i;
 
-	bio_for_each_segment(tovec, to, i) {
+	__bio_for_each_segment(tovec, to, i, 0) {
 		fromvec = from->bi_io_vec + i;
 
 		/*
@@ -300,6 +300,7 @@ static void copy_to_high_bio_irq(struct bio *to, struct bio *from)
 		 */
 		vfrom = page_address(fromvec->bv_page) + tovec->bv_offset;
 
+		flush_dcache_page(tovec->bv_page);
 		bounce_copy_vec(tovec, vfrom);
 	}
 }
@@ -316,7 +317,7 @@ static void bounce_end_io(struct bio *bio, mempool_t *pool)
 	/*
 	 * free up bounce indirect pages used
 	 */
-	bio_for_each_segment(bvec, bio, i) {
+	__bio_for_each_segment(bvec, bio, i, 0) {
 		org_vec = bio_orig->bi_io_vec + i;
 		if (bvec->bv_page == org_vec->bv_page)
 			continue;
@@ -406,6 +407,7 @@ static void __blk_queue_bounce(request_queue_t *q, struct bio **bio_orig,
 		if (rw == WRITE) {
 			char *vto, *vfrom;
 
+			flush_dcache_page(from->bv_page);
 			vto = page_address(to->bv_page) + to->bv_offset;
 			vfrom = kmap(from->bv_page) + from->bv_offset;
 			memcpy(vto, vfrom, to->bv_len);
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 6c522e127..3e17acfb3 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -21,7 +21,7 @@ static spinlock_t hugetlb_lock = SPIN_LOCK_UNLOCKED;
 
 static void enqueue_huge_page(struct page *page)
 {
-	int nid = page_zone(page)->zone_pgdat->node_id;
+	int nid = page_to_nid(page);
 	list_add(&page->lru, &hugepage_freelists[nid]);
 	free_huge_pages++;
 	free_huge_pages_node[nid]++;
@@ -52,7 +52,7 @@ static struct page *alloc_fresh_huge_page(void)
 {
 	static int nid = 0;
 	struct page *page;
-	page = alloc_pages_node(nid, GFP_HIGHUSER|__GFP_COMP,
+	page = alloc_pages_node(nid, GFP_HIGHUSER|__GFP_COMP|__GFP_NOWARN,
 					HUGETLB_PAGE_ORDER);
 	nid = (nid + 1) % numnodes;
 	if (page) {
@@ -123,6 +123,7 @@ static int __init hugetlb_setup(char *s)
 }
 __setup("hugepages=", hugetlb_setup);
 
+#ifdef CONFIG_SYSCTL
 static void update_and_free_page(struct page *page)
 {
 	int i;
@@ -188,7 +189,6 @@ static unsigned long set_max_huge_pages(unsigned long count)
 	return nr_huge_pages;
 }
 
-#ifdef CONFIG_SYSCTL
 int hugetlb_sysctl_handler(struct ctl_table *table, int write,
 			   struct file *file, void __user *buffer,
 			   size_t *length, loff_t *ppos)
diff --git a/mm/memory.c b/mm/memory.c
index adaca7c22..ea40537ba 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1129,12 +1129,12 @@ no_new_page:
 static inline void unmap_mapping_range_list(struct prio_tree_root *root,
 					    struct zap_details *details)
 {
-	struct vm_area_struct *vma = NULL;
+	struct vm_area_struct *vma;
 	struct prio_tree_iter iter;
 	pgoff_t vba, vea, zba, zea;
 
-	while ((vma = vma_prio_tree_next(vma, root, &iter,
-			details->first_index, details->last_index)) != NULL) {
+	vma_prio_tree_foreach(vma, &iter, root,
+			details->first_index, details->last_index) {
 		vba = vma->vm_pgoff;
 		vea = vba + ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) - 1;
 		/* Assume for now that PAGE_CACHE_SHIFT == PAGE_SHIFT */
@@ -1357,6 +1357,7 @@ static int do_swap_page(struct mm_struct * mm,
 		/* Had to read the page from swap area: Major fault */
 		ret = VM_FAULT_MAJOR;
 		inc_page_state(pgmajfault);
+		grab_swap_token();
 	}
 
 	if (!vx_rsspages_avail(mm, 1)) {
@@ -1761,6 +1762,8 @@ int make_pages_present(unsigned long addr, unsigned long end)
 	struct vm_area_struct * vma;
 
 	vma = find_vma(current->mm, addr);
+	if (!vma)
+		return -1;
 	write = (vma->vm_flags & VM_WRITE) != 0;
 	if (addr >= end)
 		BUG();
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index d06eabbf7..8fe9c7ee9 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -146,6 +146,8 @@ static int get_nodes(unsigned long *nodes, unsigned long __user *nmask,
 	/* When the user specified more nodes than supported just check
 	   if the non supported part is all zero. */
 	if (nlongs > BITS_TO_LONGS(MAX_NUMNODES)) {
+		if (nlongs > PAGE_SIZE/sizeof(long))
+			return -EINVAL;
 		for (k = BITS_TO_LONGS(MAX_NUMNODES); k < nlongs; k++) {
 			unsigned long t;
 			if (get_user(t,  nmask + k))
@@ -438,7 +440,7 @@ static int lookup_node(struct mm_struct *mm, unsigned long addr)
 
 	err = get_user_pages(current, mm, addr & PAGE_MASK, 1, 0, 0, &p, NULL);
 	if (err >= 0) {
-		err = page_zone(p)->zone_pgdat->node_id;
+		err = page_to_nid(p);
 		put_page(p);
 	}
 	return err;
@@ -526,20 +528,82 @@ asmlinkage long sys_get_mempolicy(int __user *policy,
 }
 
 #ifdef CONFIG_COMPAT
-/* The other functions are compatible */
+
 asmlinkage long compat_get_mempolicy(int __user *policy,
-				  unsigned __user *nmask, unsigned  maxnode,
-				  unsigned addr, unsigned  flags)
+				     compat_ulong_t __user *nmask,
+				     compat_ulong_t maxnode,
+				     compat_ulong_t addr, compat_ulong_t flags)
 {
 	long err;
 	unsigned long __user *nm = NULL;
+	unsigned long nr_bits, alloc_size;
+	DECLARE_BITMAP(bm, MAX_NUMNODES);
+
+	nr_bits = min_t(unsigned long, maxnode-1, MAX_NUMNODES);
+	alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
+
 	if (nmask)
-		nm = compat_alloc_user_space(ALIGN(maxnode-1, 64) / 8);
-	err = sys_get_mempolicy(policy, nm, maxnode, addr, flags);
-	if (!err && copy_in_user(nmask, nm, ALIGN(maxnode-1, 32)/8))
-		err = -EFAULT;
+		nm = compat_alloc_user_space(alloc_size);
+
+	err = sys_get_mempolicy(policy, nm, nr_bits+1, addr, flags);
+
+	if (!err && nmask) {
+		err = copy_from_user(bm, nm, alloc_size);
+		/* ensure entire bitmap is zeroed */
+		err |= clear_user(nmask, ALIGN(maxnode-1, 8) / 8);
+		err |= compat_put_bitmap(nmask, bm, nr_bits);
+	}
+
 	return err;
 }
+
+asmlinkage long compat_set_mempolicy(int mode, compat_ulong_t __user *nmask,
+				     compat_ulong_t maxnode)
+{
+	long err = 0;
+	unsigned long __user *nm = NULL;
+	unsigned long nr_bits, alloc_size;
+	DECLARE_BITMAP(bm, MAX_NUMNODES);
+
+	nr_bits = min_t(unsigned long, maxnode-1, MAX_NUMNODES);
+	alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
+
+	if (nmask) {
+		err = compat_get_bitmap(bm, nmask, nr_bits);
+		nm = compat_alloc_user_space(alloc_size);
+		err |= copy_to_user(nm, bm, alloc_size);
+	}
+
+	if (err)
+		return -EFAULT;
+
+	return sys_set_mempolicy(mode, nm, nr_bits+1);
+}
+
+asmlinkage long compat_mbind(compat_ulong_t start, compat_ulong_t len,
+			     compat_ulong_t mode, compat_ulong_t __user *nmask,
+			     compat_ulong_t maxnode, compat_ulong_t flags)
+{
+	long err = 0;
+	unsigned long __user *nm = NULL;
+	unsigned long nr_bits, alloc_size;
+	DECLARE_BITMAP(bm, MAX_NUMNODES);
+
+	nr_bits = min_t(unsigned long, maxnode-1, MAX_NUMNODES);
+	alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
+
+	if (nmask) {
+		err = compat_get_bitmap(bm, nmask, nr_bits);
+		nm = compat_alloc_user_space(alloc_size);
+		err |= copy_to_user(nm, bm, alloc_size);
+	}
+
+	if (err)
+		return -EFAULT;
+
+	return sys_mbind(start, len, mode, nm, nr_bits+1, flags);
+}
+
 #endif
 
 /* Return effective policy for a VMA */
diff --git a/mm/mempool.c b/mm/mempool.c
index a6c1537ee..8dec8779e 100644
--- a/mm/mempool.c
+++ b/mm/mempool.c
@@ -194,6 +194,7 @@ void * mempool_alloc(mempool_t *pool, int gfp_mask)
 	DEFINE_WAIT(wait);
 	int gfp_nowait = gfp_mask & ~(__GFP_WAIT | __GFP_IO);
 
+	might_sleep_if(gfp_mask & __GFP_WAIT);
 repeat_alloc:
 	element = pool->alloc(gfp_nowait|__GFP_NOWARN, pool->pool_data);
 	if (likely(element != NULL))
diff --git a/mm/mlock.c b/mm/mlock.c
index 861c7a3b0..16b3bf844 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -62,8 +62,6 @@ static int do_mlock(unsigned long start, size_t len, int on)
 	struct vm_area_struct * vma, * next;
 	int error;
 
-	if (on && !capable(CAP_IPC_LOCK))
-		return -EPERM;
 	len = PAGE_ALIGN(len);
 	end = start + len;
 	if (end < start)
@@ -109,6 +107,9 @@ asmlinkage long sys_mlock(unsigned long start, size_t len)
 	unsigned long lock_limit;
 	int error = -ENOMEM;
 
+	if (!can_do_mlock())
+		return -EPERM;
+
 	down_write(&current->mm->mmap_sem);
 	len = PAGE_ALIGN(len + (start & ~PAGE_MASK));
 	start &= PAGE_MASK;
@@ -122,7 +123,7 @@ asmlinkage long sys_mlock(unsigned long start, size_t len)
 	lock_limit >>= PAGE_SHIFT;
 
 	/* check against resource limits */
-	if (locked <= lock_limit)
+	if ((locked <= lock_limit) || capable(CAP_IPC_LOCK))
 		error = do_mlock(start, len, 1);
 out:
 	up_write(&current->mm->mmap_sem);
@@ -143,19 +144,15 @@ asmlinkage long sys_munlock(unsigned long start, size_t len)
 
 static int do_mlockall(int flags)
 {
-	int error;
-	unsigned int def_flags;
 	struct vm_area_struct * vma;
+	unsigned int def_flags = 0;
 
-	if (!capable(CAP_IPC_LOCK))
-		return -EPERM;
-
-	def_flags = 0;
 	if (flags & MCL_FUTURE)
 		def_flags = VM_LOCKED;
 	current->mm->def_flags = def_flags;
+	if (flags == MCL_FUTURE)
+		goto out;
 
-	error = 0;
 	for (vma = current->mm->mmap; vma ; vma = vma->vm_next) {
 		unsigned int newflags;
 
@@ -166,7 +163,8 @@ static int do_mlockall(int flags)
 		/* Ignore errors */
 		mlock_fixup(vma, vma->vm_start, vma->vm_end, newflags);
 	}
-	return error;
+out:
+	return 0;
 }
 
 asmlinkage long sys_mlockall(int flags)
@@ -174,20 +172,26 @@ asmlinkage long sys_mlockall(int flags)
 	unsigned long lock_limit;
 	int ret = -EINVAL;
 
-	down_write(&current->mm->mmap_sem);
 	if (!flags || (flags & ~(MCL_CURRENT | MCL_FUTURE)))
 		goto out;
 
+	ret = -EPERM;
+	if (!can_do_mlock())
+		goto out;
+
+	down_write(&current->mm->mmap_sem);
+
 	lock_limit = current->rlim[RLIMIT_MEMLOCK].rlim_cur;
 	lock_limit >>= PAGE_SHIFT;
 
 	ret = -ENOMEM;
 	if (!vx_vmlocked_avail(current->mm, current->mm->total_vm))
 		goto out;
-	if (current->mm->total_vm <= lock_limit)
+	if (!(flags & MCL_CURRENT) || (current->mm->total_vm <= lock_limit) ||
+	    capable(CAP_IPC_LOCK))
 		ret = do_mlockall(flags);
-out:
 	up_write(&current->mm->mmap_sem);
+out:
 	return ret;
 }
 
@@ -200,3 +204,36 @@ asmlinkage long sys_munlockall(void)
 	up_write(&current->mm->mmap_sem);
 	return ret;
 }
+
+/*
+ * Objects with different lifetime than processes (SHM_LOCK and SHM_HUGETLB
+ * shm segments) get accounted against the user_struct instead.
+ */
+static spinlock_t shmlock_user_lock = SPIN_LOCK_UNLOCKED;
+
+int user_shm_lock(size_t size, struct user_struct *user)
+{
+	unsigned long lock_limit, locked;
+	int allowed = 0;
+
+	spin_lock(&shmlock_user_lock);
+	locked = size >> PAGE_SHIFT;
+	lock_limit = current->rlim[RLIMIT_MEMLOCK].rlim_cur;
+	lock_limit >>= PAGE_SHIFT;
+	if (locked + user->locked_shm > lock_limit && !capable(CAP_IPC_LOCK))
+		goto out;
+	get_uid(user);
+	user->locked_shm += locked;
+	allowed = 1;
+out:
+	spin_unlock(&shmlock_user_lock);
+	return allowed;
+}
+
+void user_shm_unlock(size_t size, struct user_struct *user)
+{
+	spin_lock(&shmlock_user_lock);
+	user->locked_shm -= (size >> PAGE_SHIFT);
+	spin_unlock(&shmlock_user_lock);
+	free_uid(user);
+}
diff --git a/mm/mmap.c b/mm/mmap.c
index 0a89be9fb..e2364f60e 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -54,7 +54,7 @@ pgprot_t protection_map[16] = {
 	__S000, __S001, __S010, __S011, __S100, __S101, __S110, __S111
 };
 
-int sysctl_overcommit_memory = 0;	/* default is heuristic overcommit */
+int sysctl_overcommit_memory = OVERCOMMIT_GUESS;  /* heuristic overcommit */
 int sysctl_overcommit_ratio = 50;	/* default is 50% */
 int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT;
 atomic_t vm_committed_space = ATOMIC_INIT(0);
@@ -90,6 +90,7 @@ static void remove_vm_struct(struct vm_area_struct *vma)
 {
 	struct file *file = vma->vm_file;
 
+	might_sleep();
 	if (file) {
 		struct address_space *mapping = file->f_mapping;
 		spin_lock(&mapping->i_mmap_lock);
@@ -279,8 +280,7 @@ static inline void __vma_link_file(struct vm_area_struct *vma)
 
 		flush_dcache_mmap_lock(mapping);
 		if (unlikely(vma->vm_flags & VM_NONLINEAR))
-			list_add_tail(&vma->shared.vm_set.list,
-					&mapping->i_mmap_nonlinear);
+			vma_nonlinear_insert(vma, &mapping->i_mmap_nonlinear);
 		else
 			vma_prio_tree_insert(vma, &mapping->i_mmap);
 		flush_dcache_mmap_unlock(mapping);
@@ -449,11 +449,8 @@ again:			remove_next = 1 + (end > next->vm_end);
 	}
 
 	if (root) {
-		if (adjust_next) {
-			vma_prio_tree_init(next);
+		if (adjust_next)
 			vma_prio_tree_insert(next, root);
-		}
-		vma_prio_tree_init(vma);
 		vma_prio_tree_insert(vma, root);
 		flush_dcache_mmap_unlock(mapping);
 	}
@@ -732,6 +729,32 @@ none:
 	return NULL;
 }
 
+#ifdef CONFIG_PROC_FS
+void __vm_stat_account(struct mm_struct *mm, unsigned long flags,
+						struct file *file, long pages)
+{
+	const unsigned long stack_flags
+		= VM_STACK_FLAGS & (VM_GROWSUP|VM_GROWSDOWN);
+
+#ifdef CONFIG_HUGETLB
+	if (flags & VM_HUGETLB) {
+		if (!(flags & VM_DONTCOPY))
+			mm->shared_vm += pages;
+		return;
+	}
+#endif /* CONFIG_HUGETLB */
+
+	if (file)
+		mm->shared_vm += pages;
+	else if (flags & stack_flags)
+		mm->stack_vm += pages;
+	if (flags & VM_EXEC)
+		mm->exec_vm += pages;
+	if (flags & (VM_RESERVED|VM_IO))
+		mm->reserved_vm += pages;
+}
+#endif /* CONFIG_PROC_FS */
+
 /*
  * The caller must hold down_write(current->mm->mmap_sem).
  */
@@ -750,13 +773,6 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
 	int accountable = 1;
 	unsigned long charged = 0;
 
-	/*
-	 * Does the application expect PROT_READ to imply PROT_EXEC:
-	 */
-	if (unlikely((prot & PROT_READ) &&
-			(current->personality & READ_IMPLIES_EXEC)))
-		prot |= PROT_EXEC;
-
 	if (file) {
 		if (is_file_hugepages(file))
 			accountable = 0;
@@ -768,6 +784,15 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
 		    (file->f_vfsmnt->mnt_flags & MNT_NOEXEC))
 			return -EPERM;
 	}
+	/*
+	 * Does the application expect PROT_READ to imply PROT_EXEC?
+	 *
+	 * (the exception is when the underlying filesystem is noexec
+	 *  mounted, in which case we dont add PROT_EXEC.)
+	 */
+	if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
+		if (!(file && (file->f_vfsmnt->mnt_flags & MNT_NOEXEC)))
+			prot |= PROT_EXEC;
 
 	if (!len)
 		return addr;
@@ -800,15 +825,17 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
 			mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
 
 	if (flags & MAP_LOCKED) {
-		if (!capable(CAP_IPC_LOCK))
+		if (!can_do_mlock())
 			return -EPERM;
 		vm_flags |= VM_LOCKED;
 	}
 	/* mlock MCL_FUTURE? */
 	if (vm_flags & VM_LOCKED) {
-		unsigned long locked = mm->locked_vm << PAGE_SHIFT;
+		unsigned long locked, lock_limit;
+		locked = mm->locked_vm << PAGE_SHIFT;
+		lock_limit = current->rlim[RLIMIT_MEMLOCK].rlim_cur;
 		locked += len;
-		if (locked > current->rlim[RLIMIT_MEMLOCK].rlim_cur)
+		if (locked > lock_limit && !capable(CAP_IPC_LOCK))
 			return -EAGAIN;
 	}
 
@@ -886,7 +913,7 @@ munmap_back:
 		return -ENOMEM;
 
 	if (accountable && (!(flags & MAP_NORESERVE) ||
-			sysctl_overcommit_memory > 1)) {
+			    sysctl_overcommit_memory == OVERCOMMIT_NEVER)) {
 		if (vm_flags & VM_SHARED) {
 			/* Check memory availability in shmem_file_setup? */
 			vm_flags |= VM_ACCOUNT;
@@ -994,6 +1021,7 @@ out:
 					pgoff, flags & MAP_NONBLOCK);
 		down_write(&mm->mmap_sem);
 	}
+	__vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT);
 	return addr;
 
 unmap_and_free_vma:
@@ -1026,7 +1054,7 @@ EXPORT_SYMBOL(do_mmap_pgoff);
  * This function "knows" that -ENOMEM has the bits set.
  */
 #ifndef HAVE_ARCH_UNMAPPED_AREA
-static inline unsigned long
+unsigned long
 arch_get_unmapped_area(struct file *filp, unsigned long addr,
 		unsigned long len, unsigned long pgoff, unsigned long flags)
 {
@@ -1070,12 +1098,118 @@ full_search:
 		addr = vma->vm_end;
 	}
 }
-#else
-extern unsigned long
-arch_get_unmapped_area(struct file *, unsigned long, unsigned long,
-			unsigned long, unsigned long);
 #endif	
 
+void arch_unmap_area(struct vm_area_struct *area)
+{
+	/*
+	 * Is this a new hole at the lowest possible address?
+	 */
+	if (area->vm_start >= TASK_UNMAPPED_BASE &&
+			area->vm_start < area->vm_mm->free_area_cache)
+		area->vm_mm->free_area_cache = area->vm_start;
+}
+
+/*
+ * This mmap-allocator allocates new areas top-down from below the
+ * stack's low limit (the base):
+ */
+#ifndef HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
+unsigned long
+arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
+			  const unsigned long len, const unsigned long pgoff,
+			  const unsigned long flags)
+{
+	struct vm_area_struct *vma, *prev_vma;
+	struct mm_struct *mm = current->mm;
+	unsigned long base = mm->mmap_base, addr = addr0;
+	int first_time = 1;
+
+	/* requested length too big for entire address space */
+	if (len > TASK_SIZE)
+		return -ENOMEM;
+
+	/* dont allow allocations above current base */
+	if (mm->free_area_cache > base)
+		mm->free_area_cache = base;
+
+	/* requesting a specific address */
+	if (addr) {
+		addr = PAGE_ALIGN(addr);
+		vma = find_vma(mm, addr);
+		if (TASK_SIZE - len >= addr &&
+				(!vma || addr + len <= vma->vm_start))
+			return addr;
+	}
+
+try_again:
+	/* make sure it can fit in the remaining address space */
+	if (mm->free_area_cache < len)
+		goto fail;
+
+	/* either no address requested or cant fit in requested address hole */
+	addr = (mm->free_area_cache - len) & PAGE_MASK;
+	do {
+		/*
+		 * Lookup failure means no vma is above this address,
+		 * i.e. return with success:
+		 */
+ 	 	if (!(vma = find_vma_prev(mm, addr, &prev_vma)))
+			return addr;
+
+		/*
+		 * new region fits between prev_vma->vm_end and
+		 * vma->vm_start, use it:
+		 */
+		if (addr+len <= vma->vm_start &&
+				(!prev_vma || (addr >= prev_vma->vm_end)))
+			/* remember the address as a hint for next time */
+			return (mm->free_area_cache = addr);
+		else
+			/* pull free_area_cache down to the first hole */
+			if (mm->free_area_cache == vma->vm_end)
+				mm->free_area_cache = vma->vm_start;
+
+		/* try just below the current vma->vm_start */
+		addr = vma->vm_start-len;
+	} while (len <= vma->vm_start);
+
+fail:
+	/*
+	 * if hint left us with no space for the requested
+	 * mapping then try again:
+	 */
+	if (first_time) {
+		mm->free_area_cache = base;
+		first_time = 0;
+		goto try_again;
+	}
+	/*
+	 * A failed mmap() very likely causes application failure,
+	 * so fall back to the bottom-up function here. This scenario
+	 * can happen with large stack limits and large mmap()
+	 * allocations.
+	 */
+	mm->free_area_cache = TASK_UNMAPPED_BASE;
+	addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
+	/*
+	 * Restore the topdown base:
+	 */
+	mm->free_area_cache = base;
+
+	return addr;
+}
+#endif
+
+void arch_unmap_area_topdown(struct vm_area_struct *area)
+{
+	/*
+	 * Is this a new hole at the highest possible address?
+	 */
+	if (area->vm_end > area->vm_mm->free_area_cache)
+		area->vm_mm->free_area_cache = area->vm_end;
+}
+
 unsigned long
 get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
 		unsigned long pgoff, unsigned long flags)
@@ -1110,7 +1244,7 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
 		return file->f_op->get_unmapped_area(file, addr, len,
 						pgoff, flags);
 
-	return arch_get_unmapped_area(file, addr, len, pgoff, flags);
+	return current->mm->get_unmapped_area(file, addr, len, pgoff, flags);
 }
 
 EXPORT_SYMBOL(get_unmapped_area);
@@ -1236,6 +1370,7 @@ int expand_stack(struct vm_area_struct * vma, unsigned long address)
 	if (vma->vm_flags & VM_LOCKED)
 		// vma->vm_mm->locked_vm += grow;
 		vx_vmlocked_add(vma->vm_mm, grow);
+	__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow);
 	anon_vma_unlock(vma);
 	return 0;
 }
@@ -1301,6 +1436,7 @@ int expand_stack(struct vm_area_struct *vma, unsigned long address)
 	if (vma->vm_flags & VM_LOCKED)
 		// vma->vm_mm->locked_vm += grow;
 		vx_vmlocked_add(vma->vm_mm, grow);
+	__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow);
 	anon_vma_unlock(vma);
 	return 0;
 }
@@ -1405,17 +1541,12 @@ static void unmap_vma(struct mm_struct *mm, struct vm_area_struct *area)
 
 	// area->vm_mm->total_vm -= len >> PAGE_SHIFT;
 	vx_vmpages_sub(area->vm_mm, len >> PAGE_SHIFT);
-	
+
 	if (area->vm_flags & VM_LOCKED)
 		// area->vm_mm->locked_vm -= len >> PAGE_SHIFT;
 		vx_vmlocked_sub(area->vm_mm, len >> PAGE_SHIFT);
-	/*
-	 * Is this a new hole at the lowest possible address?
-	 */
-	if (area->vm_start >= TASK_UNMAPPED_BASE &&
-				area->vm_start < area->vm_mm->free_area_cache)
-	      area->vm_mm->free_area_cache = area->vm_start;
-
+	vm_stat_unaccount(area);
+	area->vm_mm->unmap_area(area);
 	remove_vm_struct(area);
 }
 
@@ -1504,7 +1635,6 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
 
 	/* most fields are the same, copy all, and then fixup */
 	*new = *vma;
-	vma_prio_tree_init(new);
 
 	if (new_below)
 		new->vm_end = addr;
@@ -1569,10 +1699,6 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
 	if (mpnt->vm_start >= end)
 		return 0;
 
-	/* Something will probably happen, so notify. */
-	if (mpnt->vm_file && (mpnt->vm_flags & VM_EXEC))
-		profile_exec_unmap(mm);
- 
 	/*
 	 * If we need to split any vma, do it now to save pain later.
 	 *
@@ -1615,6 +1741,8 @@ asmlinkage long sys_munmap(unsigned long addr, size_t len)
 	int ret;
 	struct mm_struct *mm = current->mm;
 
+	profile_munmap(addr);
+
 	down_write(&mm->mmap_sem);
 	ret = do_munmap(mm, addr, len);
 	up_write(&mm->mmap_sem);
@@ -1645,9 +1773,11 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
 	 * mlock MCL_FUTURE?
 	 */
 	if (mm->def_flags & VM_LOCKED) {
-		unsigned long locked = mm->locked_vm << PAGE_SHIFT;
+		unsigned long locked, lock_limit;
+		locked = mm->locked_vm << PAGE_SHIFT;
+		lock_limit = current->rlim[RLIMIT_MEMLOCK].rlim_cur;
 		locked += len;
-		if (locked > current->rlim[RLIMIT_MEMLOCK].rlim_cur)
+		if (locked > lock_limit && !capable(CAP_IPC_LOCK))
 			return -EAGAIN;
 		if (!vx_vmlocked_avail(mm, len >> PAGE_SHIFT))
 			return -ENOMEM;
@@ -1720,8 +1850,6 @@ void exit_mmap(struct mm_struct *mm)
 	struct vm_area_struct *vma;
 	unsigned long nr_accounted = 0;
 
-	profile_exit_mmap(mm);
- 
 	lru_add_drain();
 
 	spin_lock(&mm->page_table_lock);
@@ -1825,7 +1953,6 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
 		new_vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
 		if (new_vma) {
 			*new_vma = *vma;
-			vma_prio_tree_init(new_vma);
 			pol = mpol_copy(vma_policy(vma));
 			if (IS_ERR(pol)) {
 				kmem_cache_free(vm_area_cachep, new_vma);
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 88041d46a..67d02dc0e 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -175,9 +175,11 @@ success:
 	 * vm_flags and vm_page_prot are protected by the mmap_sem
 	 * held in write mode.
 	 */
+	vm_stat_unaccount(vma);
 	vma->vm_flags = newflags;
 	vma->vm_page_prot = newprot;
 	change_protection(vma, start, end, newprot);
+	vm_stat_account(vma);
 	return 0;
 
 fail:
diff --git a/mm/mremap.c b/mm/mremap.c
index 330a32a4a..92142f58b 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -226,6 +226,7 @@ static unsigned long move_vma(struct vm_area_struct *vma,
 
 	// mm->total_vm += new_len >> PAGE_SHIFT;
 	vx_vmpages_add(mm, new_len >> PAGE_SHIFT);
+	__vm_stat_account(mm, vma->vm_flags, vma->vm_file, new_len>>PAGE_SHIFT);
 	if (vm_flags & VM_LOCKED) {
 		// mm->locked_vm += new_len >> PAGE_SHIFT;
 		vx_vmlocked_add(mm, new_len >> PAGE_SHIFT);
@@ -327,10 +328,12 @@ unsigned long do_mremap(unsigned long addr,
 			goto out;
 	}
 	if (vma->vm_flags & VM_LOCKED) {
-		unsigned long locked = current->mm->locked_vm << PAGE_SHIFT;
+		unsigned long locked, lock_limit;
+		locked = current->mm->locked_vm << PAGE_SHIFT;
+		lock_limit = current->rlim[RLIMIT_MEMLOCK].rlim_cur;
 		locked += new_len - old_len;
 		ret = -EAGAIN;
-		if (locked > current->rlim[RLIMIT_MEMLOCK].rlim_cur)
+		if (locked > lock_limit && !capable(CAP_IPC_LOCK))
 			goto out;
 		ret = -ENOMEM;
 		if (!vx_vmlocked_avail(current->mm,
@@ -369,6 +372,8 @@ unsigned long do_mremap(unsigned long addr,
 
 			// current->mm->total_vm += pages;
 			vx_vmpages_add(current->mm, pages);
+			__vm_stat_account(vma->vm_mm, vma->vm_flags,
+							vma->vm_file, pages);
 			if (vma->vm_flags & VM_LOCKED) {
 				// current->mm->locked_vm += pages;
 				vx_vmlocked_add(vma->vm_mm, pages);
diff --git a/mm/nommu.c b/mm/nommu.c
index 114c0ccb4..dd4b66b8c 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -30,7 +30,7 @@ unsigned long max_mapnr;
 unsigned long num_physpages;
 unsigned long askedalloc, realalloc;
 atomic_t vm_committed_space = ATOMIC_INIT(0);
-int sysctl_overcommit_memory; /* default is heuristic overcommit */
+int sysctl_overcommit_memory = OVERCOMMIT_GUESS; /* heuristic overcommit */
 int sysctl_overcommit_ratio = 50; /* default is 50% */
 
 int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT;
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 3de04b617..2d30febea 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -26,6 +26,7 @@
 /**
  * oom_badness - calculate a numeric value for how bad this task has been
  * @p: task struct of which task we should calculate
+ * @p: current uptime in seconds
  *
  * The formula used is relatively simple and documented inline in the
  * function. The main rationale is that we want to select a good task
@@ -41,9 +42,9 @@
  *    of least surprise ... (be careful when you change it)
  */
 
-static int badness(struct task_struct *p)
+static unsigned long badness(struct task_struct *p, unsigned long uptime)
 {
-	int points, cpu_time, run_time, s;
+	unsigned long points, cpu_time, run_time, s;
 
 	if (!p->mm)
 		return 0;
@@ -57,12 +58,16 @@ static int badness(struct task_struct *p)
 	/* add vserver badness ;) */
 
 	/*
-	 * CPU time is in seconds and run time is in minutes. There is no
-	 * particular reason for this other than that it turned out to work
-	 * very well in practice.
+	 * CPU time is in tens of seconds and run time is in thousands
+         * of seconds. There is no particular reason for this other than
+         * that it turned out to work very well in practice.
 	 */
 	cpu_time = (p->utime + p->stime) >> (SHIFT_HZ + 3);
-	run_time = (get_jiffies_64() - p->start_time) >> (SHIFT_HZ + 10);
+
+	if (uptime >= p->start_time.tv_sec)
+		run_time = (uptime - p->start_time.tv_sec) >> 10;
+	else
+		run_time = 0;
 
 	s = int_sqrt(cpu_time);
 	if (s)
@@ -109,13 +114,15 @@ static int badness(struct task_struct *p)
  */
 static struct task_struct * select_bad_process(void)
 {
-	int maxpoints = 0;
+	unsigned long maxpoints = 0;
 	struct task_struct *g, *p;
 	struct task_struct *chosen = NULL;
+	struct timespec uptime;
 
+	do_posix_clock_monotonic_gettime(&uptime);
 	do_each_thread(g, p)
 		if (p->pid) {
-			int points = badness(p);
+			unsigned long points = badness(p, uptime.tv_sec);
 			if (points > maxpoints) {
 				chosen = p;
 				maxpoints = points;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 3fe5eb3ad..8bcef6812 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -57,8 +57,8 @@ EXPORT_SYMBOL(zone_table);
 static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" };
 int min_free_kbytes = 1024;
 
-static unsigned long __initdata nr_kernel_pages;
-static unsigned long __initdata nr_all_pages;
+unsigned long __initdata nr_kernel_pages;
+unsigned long __initdata nr_all_pages;
 
 /*
  * Temporary debugging check for pages not lying within a given zone.
@@ -78,9 +78,9 @@ static void bad_page(const char *function, struct page *page)
 {
 	printk(KERN_EMERG "Bad page state at %s (in process '%s', page %p)\n",
 		function, current->comm, page);
-	printk(KERN_EMERG "flags:0x%08lx mapping:%p mapcount:%d count:%d\n",
-		(unsigned long)page->flags, page->mapping,
-		(int)page->mapcount, page_count(page));
+	printk(KERN_EMERG "flags:0x%0*lx mapping:%p mapcount:%d count:%d\n",
+		(int)(2*sizeof(page_flags_t)), (unsigned long)page->flags,
+		page->mapping, page_mapcount(page), page_count(page));
 	printk(KERN_EMERG "Backtrace:\n");
 	dump_stack();
 	printk(KERN_EMERG "Trying to fix it up, but a reboot is needed\n");
@@ -89,13 +89,11 @@ static void bad_page(const char *function, struct page *page)
 			1 << PG_lru	|
 			1 << PG_active	|
 			1 << PG_dirty	|
-			1 << PG_maplock |
-			1 << PG_anon    |
 			1 << PG_swapcache |
 			1 << PG_writeback);
 	set_page_count(page, 0);
+	reset_page_mapcount(page);
 	page->mapping = NULL;
-	page->mapcount = 0;
 }
 
 #ifndef CONFIG_HUGETLB_PAGE
@@ -231,8 +229,6 @@ static inline void free_pages_check(const char *function, struct page *page)
 			1 << PG_active	|
 			1 << PG_reclaim	|
 			1 << PG_slab	|
-			1 << PG_maplock |
-			1 << PG_anon    |
 			1 << PG_swapcache |
 			1 << PG_writeback )))
 		bad_page(function, page);
@@ -281,6 +277,8 @@ void __free_pages_ok(struct page *page, unsigned int order)
 	LIST_HEAD(list);
 	int i;
 
+	arch_free_page(page, order);
+
 	mod_page_state(pgfree, 1 << order);
 	for (i = 0 ; i < (1 << order) ; ++i)
 		free_pages_check(__FUNCTION__, page + i);
@@ -352,8 +350,6 @@ static void prep_new_page(struct page *page, int order)
 			1 << PG_active	|
 			1 << PG_dirty	|
 			1 << PG_reclaim	|
-			1 << PG_maplock |
-			1 << PG_anon    |
 			1 << PG_swapcache |
 			1 << PG_writeback )))
 		bad_page(__FUNCTION__, page);
@@ -511,8 +507,12 @@ static void fastcall free_hot_cold_page(struct page *page, int cold)
 	struct per_cpu_pages *pcp;
 	unsigned long flags;
 
+	arch_free_page(page, 0);
+
 	kernel_map_pages(page, 1, 0);
 	inc_page_state(pgfree);
+	if (PageAnon(page))
+		page->mapping = NULL;
 	free_pages_check(__FUNCTION__, page);
 	pcp = &zone->pageset[get_cpu()].pcp[cold];
 	local_irq_save(flags);
@@ -602,83 +602,75 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order,
 {
 	const int wait = gfp_mask & __GFP_WAIT;
 	unsigned long min;
-	struct zone **zones;
+	struct zone **zones, *z;
 	struct page *page;
 	struct reclaim_state reclaim_state;
 	struct task_struct *p = current;
 	int i;
 	int alloc_type;
 	int do_retry;
+	int can_try_harder;
 
 	might_sleep_if(wait);
 
+	/*
+	 * The caller may dip into page reserves a bit more if the caller
+	 * cannot run direct reclaim, or is the caller has realtime scheduling
+	 * policy
+	 */
+	can_try_harder = (unlikely(rt_task(p)) && !in_interrupt()) || !wait;
+
 	zones = zonelist->zones;  /* the list of zones suitable for gfp_mask */
-	if (zones[0] == NULL)     /* no zones in the zonelist */
+
+	if (unlikely(zones[0] == NULL)) {
+		/* Should this ever happen?? */
 		return NULL;
+	}
 
 	alloc_type = zone_idx(zones[0]);
 
 	/* Go through the zonelist once, looking for a zone with enough free */
-	for (i = 0; zones[i] != NULL; i++) {
-		struct zone *z = zones[i];
-
-		min = (1<<order) + z->protection[alloc_type];
+	for (i = 0; (z = zones[i]) != NULL; i++) {
+		min = z->pages_low + (1<<order) + z->protection[alloc_type];
 
-		/*
-		 * We let real-time tasks dip their real-time paws a little
-		 * deeper into reserves.
-		 */
-		if (rt_task(p))
-			min -= z->pages_low >> 1;
+		if (z->free_pages < min)
+			continue;
 
-		if (z->free_pages >= min ||
-				(!wait && z->free_pages >= z->pages_high)) {
-			page = buffered_rmqueue(z, order, gfp_mask);
-			if (page) {
-				zone_statistics(zonelist, z);
-				goto got_pg;
-			}
-		}
+		page = buffered_rmqueue(z, order, gfp_mask);
+		if (page)
+			goto got_pg;
 	}
 
-	/* we're somewhat low on memory, failed to find what we needed */
-	for (i = 0; zones[i] != NULL; i++)
-		wakeup_kswapd(zones[i]);
-
-	/* Go through the zonelist again, taking __GFP_HIGH into account */
-	for (i = 0; zones[i] != NULL; i++) {
-		struct zone *z = zones[i];
-
-		min = (1<<order) + z->protection[alloc_type];
+	for (i = 0; (z = zones[i]) != NULL; i++)
+		wakeup_kswapd(z);
 
+	/*
+	 * Go through the zonelist again. Let __GFP_HIGH and allocations
+	 * coming from realtime tasks to go deeper into reserves
+	 */
+	for (i = 0; (z = zones[i]) != NULL; i++) {
+		min = z->pages_min;
 		if (gfp_mask & __GFP_HIGH)
-			min -= z->pages_low >> 2;
-		if (rt_task(p))
-			min -= z->pages_low >> 1;
+			min /= 2;
+		if (can_try_harder)
+			min -= min / 4;
+		min += (1<<order) + z->protection[alloc_type];
 
-		if (z->free_pages >= min ||
-				(!wait && z->free_pages >= z->pages_high)) {
-			page = buffered_rmqueue(z, order, gfp_mask);
-			if (page) {
-				zone_statistics(zonelist, z);
-				goto got_pg;
-			}
-		}
-	}
+		if (z->free_pages < min)
+			continue;
 
-	/* here we're in the low on memory slow path */
+		page = buffered_rmqueue(z, order, gfp_mask);
+		if (page)
+			goto got_pg;
+	}
 
-rebalance:
+	/* This allocation should allow future memory freeing. */
 	if ((p->flags & (PF_MEMALLOC | PF_MEMDIE)) && !in_interrupt()) {
 		/* go through the zonelist yet again, ignoring mins */
-		for (i = 0; zones[i] != NULL; i++) {
-			struct zone *z = zones[i];
-
+		for (i = 0; (z = zones[i]) != NULL; i++) {
 			page = buffered_rmqueue(z, order, gfp_mask);
-			if (page) {
-				zone_statistics(zonelist, z);
+			if (page)
 				goto got_pg;
-			}
 		}
 		goto nopage;
 	}
@@ -687,6 +679,8 @@ rebalance:
 	if (!wait)
 		goto nopage;
 
+rebalance:
+	/* We now go into synchronous reclaim */
 	p->flags |= PF_MEMALLOC;
 	reclaim_state.reclaimed_slab = 0;
 	p->reclaim_state = &reclaim_state;
@@ -697,27 +691,28 @@ rebalance:
 	p->flags &= ~PF_MEMALLOC;
 
 	/* go through the zonelist yet one more time */
-	for (i = 0; zones[i] != NULL; i++) {
-		struct zone *z = zones[i];
+	for (i = 0; (z = zones[i]) != NULL; i++) {
+		min = z->pages_min;
+		if (gfp_mask & __GFP_HIGH)
+			min /= 2;
+		if (can_try_harder)
+			min -= min / 4;
+		min += (1<<order) + z->protection[alloc_type];
 
-		min = (1UL << order) + z->protection[alloc_type];
+		if (z->free_pages < min)
+			continue;
 
-		if (z->free_pages >= min ||
-				(!wait && z->free_pages >= z->pages_high)) {
-			page = buffered_rmqueue(z, order, gfp_mask);
-			if (page) {
- 				zone_statistics(zonelist, z);
-				goto got_pg;
-			}
-		}
+		page = buffered_rmqueue(z, order, gfp_mask);
+		if (page)
+			goto got_pg;
 	}
 
 	/*
 	 * Don't let big-order allocations loop unless the caller explicitly
 	 * requests that.  Wait for some write requests to complete then retry.
 	 *
-	 * In this implementation, __GFP_REPEAT means __GFP_NOFAIL, but that
-	 * may not be true in other implementations.
+	 * In this implementation, __GFP_REPEAT means __GFP_NOFAIL for order
+	 * <= 3, but that may not be true in other implementations.
 	 */
 	do_retry = 0;
 	if (!(gfp_mask & __GFP_NORETRY)) {
@@ -740,6 +735,7 @@ nopage:
 	}
 	return NULL;
 got_pg:
+	zone_statistics(zonelist, z);
 	kernel_map_pages(page, 1 << order, 1);
 	return page;
 }
@@ -804,8 +800,8 @@ EXPORT_SYMBOL(__free_pages);
 fastcall void free_pages(unsigned long addr, unsigned int order)
 {
 	if (addr != 0) {
-		BUG_ON(!virt_addr_valid(addr));
-		__free_pages(virt_to_page(addr), order);
+		BUG_ON(!virt_addr_valid((void *)addr));
+		__free_pages(virt_to_page((void *)addr), order);
 	}
 }
 
@@ -967,18 +963,36 @@ unsigned long __read_page_state(unsigned offset)
 	return ret;
 }
 
+void __get_zone_counts(unsigned long *active, unsigned long *inactive,
+			unsigned long *free, struct pglist_data *pgdat)
+{
+	struct zone *zones = pgdat->node_zones;
+	int i;
+
+	*active = 0;
+	*inactive = 0;
+	*free = 0;
+	for (i = 0; i < MAX_NR_ZONES; i++) {
+		*active += zones[i].nr_active;
+		*inactive += zones[i].nr_inactive;
+		*free += zones[i].free_pages;
+	}
+}
+
 void get_zone_counts(unsigned long *active,
 		unsigned long *inactive, unsigned long *free)
 {
-	struct zone *zone;
+	struct pglist_data *pgdat;
 
 	*active = 0;
 	*inactive = 0;
 	*free = 0;
-	for_each_zone(zone) {
-		*active += zone->nr_active;
-		*inactive += zone->nr_inactive;
-		*free += zone->free_pages;
+	for_each_pgdat(pgdat) {
+		unsigned long l, m, n;
+		__get_zone_counts(&l, &m, &n, pgdat);
+		*active += l;
+		*inactive += m;
+		*free += n;
 	}
 }
 
@@ -1383,14 +1397,16 @@ static void __init calculate_zone_totalpages(struct pglist_data *pgdat,
  * up by free_all_bootmem() once the early boot process is
  * done. Non-atomic initialization, single-pass.
  */
-void __init memmap_init_zone(struct page *start, unsigned long size, int nid,
-		unsigned long zone, unsigned long start_pfn)
+void __init memmap_init_zone(unsigned long size, int nid, unsigned long zone,
+		unsigned long start_pfn)
 {
+	struct page *start = pfn_to_page(start_pfn);
 	struct page *page;
 
 	for (page = start; page < (start + size); page++) {
 		set_page_zone(page, NODEZONE(nid, zone));
 		set_page_count(page, 0);
+		reset_page_mapcount(page);
 		SetPageReserved(page);
 		INIT_LIST_HEAD(&page->lru);
 #ifdef WANT_PAGE_VIRTUAL
@@ -1402,9 +1418,55 @@ void __init memmap_init_zone(struct page *start, unsigned long size, int nid,
 	}
 }
 
+/*
+ * Page buddy system uses "index >> (i+1)", where "index" is
+ * at most "size-1".
+ *
+ * The extra "+3" is to round down to byte size (8 bits per byte
+ * assumption). Thus we get "(size-1) >> (i+4)" as the last byte
+ * we can access.
+ *
+ * The "+1" is because we want to round the byte allocation up
+ * rather than down. So we should have had a "+7" before we shifted
+ * down by three. Also, we have to add one as we actually _use_ the
+ * last bit (it's [0,n] inclusive, not [0,n[).
+ *
+ * So we actually had +7+1 before we shift down by 3. But
+ * (n+8) >> 3 == (n >> 3) + 1 (modulo overflows, which we do not have).
+ *
+ * Finally, we LONG_ALIGN because all bitmap operations are on longs.
+ */
+unsigned long pages_to_bitmap_size(unsigned long order, unsigned long nr_pages)
+{
+	unsigned long bitmap_size;
+
+	bitmap_size = (nr_pages-1) >> (order+4);
+	bitmap_size = LONG_ALIGN(bitmap_size+1);
+
+	return bitmap_size;
+}
+
+void zone_init_free_lists(struct pglist_data *pgdat, struct zone *zone, unsigned long size)
+{
+	int order;
+	for (order = 0; ; order++) {
+		unsigned long bitmap_size;
+
+		INIT_LIST_HEAD(&zone->free_area[order].free_list);
+		if (order == MAX_ORDER-1) {
+			zone->free_area[order].map = NULL;
+			break;
+		}
+
+		bitmap_size = pages_to_bitmap_size(order, size);
+		zone->free_area[order].map =
+		  (unsigned long *) alloc_bootmem_node(pgdat, bitmap_size);
+	}
+}
+
 #ifndef __HAVE_ARCH_MEMMAP_INIT
-#define memmap_init(start, size, nid, zone, start_pfn) \
-	memmap_init_zone((start), (size), (nid), (zone), (start_pfn))
+#define memmap_init(size, nid, zone, start_pfn) \
+	memmap_init_zone((size), (nid), (zone), (start_pfn))
 #endif
 
 /*
@@ -1419,7 +1481,6 @@ static void __init free_area_init_core(struct pglist_data *pgdat,
 	unsigned long i, j;
 	const unsigned long zone_required_alignment = 1UL << (MAX_ORDER-1);
 	int cpu, nid = pgdat->node_id;
-	struct page *lmem_map = pgdat->node_mem_map;
 	unsigned long zone_start_pfn = pgdat->node_start_pfn;
 
 	pgdat->nr_zones = 0;
@@ -1507,71 +1568,41 @@ static void __init free_area_init_core(struct pglist_data *pgdat,
 
 		pgdat->nr_zones = j+1;
 
-		zone->zone_mem_map = lmem_map;
+		zone->zone_mem_map = pfn_to_page(zone_start_pfn);
 		zone->zone_start_pfn = zone_start_pfn;
 
 		if ((zone_start_pfn) & (zone_required_alignment-1))
 			printk("BUG: wrong zone alignment, it will crash\n");
 
-		memmap_init(lmem_map, size, nid, j, zone_start_pfn);
+		memmap_init(size, nid, j, zone_start_pfn);
 
 		zone_start_pfn += size;
-		lmem_map += size;
-
-		for (i = 0; ; i++) {
-			unsigned long bitmap_size;
-
-			INIT_LIST_HEAD(&zone->free_area[i].free_list);
-			if (i == MAX_ORDER-1) {
-				zone->free_area[i].map = NULL;
-				break;
-			}
 
-			/*
-			 * Page buddy system uses "index >> (i+1)",
-			 * where "index" is at most "size-1".
-			 *
-			 * The extra "+3" is to round down to byte
-			 * size (8 bits per byte assumption). Thus
-			 * we get "(size-1) >> (i+4)" as the last byte
-			 * we can access.
-			 *
-			 * The "+1" is because we want to round the
-			 * byte allocation up rather than down. So
-			 * we should have had a "+7" before we shifted
-			 * down by three. Also, we have to add one as
-			 * we actually _use_ the last bit (it's [0,n]
-			 * inclusive, not [0,n[).
-			 *
-			 * So we actually had +7+1 before we shift
-			 * down by 3. But (n+8) >> 3 == (n >> 3) + 1
-			 * (modulo overflows, which we do not have).
-			 *
-			 * Finally, we LONG_ALIGN because all bitmap
-			 * operations are on longs.
-			 */
-			bitmap_size = (size-1) >> (i+4);
-			bitmap_size = LONG_ALIGN(bitmap_size+1);
-			zone->free_area[i].map = 
-			  (unsigned long *) alloc_bootmem_node(pgdat, bitmap_size);
-		}
+		zone_init_free_lists(pgdat, zone, zone->spanned_pages);
 	}
 }
 
-void __init free_area_init_node(int nid, struct pglist_data *pgdat,
-		struct page *node_mem_map, unsigned long *zones_size,
-		unsigned long node_start_pfn, unsigned long *zholes_size)
+void __init node_alloc_mem_map(struct pglist_data *pgdat)
 {
 	unsigned long size;
 
+	size = (pgdat->node_spanned_pages + 1) * sizeof(struct page);
+	pgdat->node_mem_map = alloc_bootmem_node(pgdat, size);
+#ifndef CONFIG_DISCONTIGMEM
+	mem_map = contig_page_data.node_mem_map;
+#endif
+}
+
+void __init free_area_init_node(int nid, struct pglist_data *pgdat,
+		unsigned long *zones_size, unsigned long node_start_pfn,
+		unsigned long *zholes_size)
+{
 	pgdat->node_id = nid;
 	pgdat->node_start_pfn = node_start_pfn;
 	calculate_zone_totalpages(pgdat, zones_size, zholes_size);
-	if (!node_mem_map) {
-		size = (pgdat->node_spanned_pages + 1) * sizeof(struct page);
-		node_mem_map = alloc_bootmem_node(pgdat, size);
-	}
-	pgdat->node_mem_map = node_mem_map;
+
+	if (!pfn_to_page(node_start_pfn))
+		node_alloc_mem_map(pgdat);
 
 	free_area_init_core(pgdat, zones_size, zholes_size);
 }
@@ -1584,9 +1615,8 @@ EXPORT_SYMBOL(contig_page_data);
 
 void __init free_area_init(unsigned long *zones_size)
 {
-	free_area_init_node(0, &contig_page_data, NULL, zones_size,
+	free_area_init_node(0, &contig_page_data, zones_size,
 			__pa(PAGE_OFFSET) >> PAGE_SHIFT, NULL);
-	mem_map = contig_page_data.node_mem_map;
 }
 #endif
 
@@ -1845,11 +1875,11 @@ static void setup_per_zone_protection(void)
 				 * We never protect zones that don't have memory
 				 * in them (j>max_zone) or zones that aren't in
 				 * the zonelists for a certain type of
-				 * allocation (j>i).  We have to assign these to
-				 * zero because the lower zones take
+				 * allocation (j>=i).  We have to assign these
+				 * to zero because the lower zones take
 				 * contributions from the higher zones.
 				 */
-				if (j > max_zone || j > i) {
+				if (j > max_zone || j >= i) {
 					zone->protection[i] = 0;
 					continue;
 				}
@@ -1858,7 +1888,6 @@ static void setup_per_zone_protection(void)
 				 */
 				zone->protection[i] = higherzone_val(zone,
 								max_zone, i);
-				zone->protection[i] += zone->pages_low;
 			}
 		}
 	}
@@ -1993,41 +2022,40 @@ void *__init alloc_large_system_hash(const char *tablename,
 				     unsigned int *_hash_shift,
 				     unsigned int *_hash_mask)
 {
-	unsigned long mem, max, log2qty, size;
+	unsigned long long max;
+	unsigned long log2qty, size;
 	void *table;
 
-	/* round applicable memory size up to nearest megabyte */
-	mem = consider_highmem ? nr_all_pages : nr_kernel_pages;
-	mem += (1UL << (20 - PAGE_SHIFT)) - 1;
-	mem >>= 20 - PAGE_SHIFT;
-	mem <<= 20 - PAGE_SHIFT;
-
-	/* limit to 1 bucket per 2^scale bytes of low memory (rounded up to
-	 * nearest power of 2 in size) */
-	if (scale > PAGE_SHIFT)
-		mem >>= (scale - PAGE_SHIFT);
-	else
-		mem <<= (PAGE_SHIFT - scale);
-
-	mem = 1UL << (long_log2(mem) + 1);
+	/* allow the kernel cmdline to have a say */
+	if (!numentries) {
+		/* round applicable memory size up to nearest megabyte */
+		numentries = consider_highmem ? nr_all_pages : nr_kernel_pages;
+		numentries += (1UL << (20 - PAGE_SHIFT)) - 1;
+		numentries >>= 20 - PAGE_SHIFT;
+		numentries <<= 20 - PAGE_SHIFT;
+
+		/* limit to 1 bucket per 2^scale bytes of low memory */
+		if (scale > PAGE_SHIFT)
+			numentries >>= (scale - PAGE_SHIFT);
+		else
+			numentries <<= (PAGE_SHIFT - scale);
+	}
+	/* rounded up to nearest power of 2 in size */
+	numentries = 1UL << (long_log2(numentries) + 1);
 
-	/* limit allocation size */
-	max = (1UL << (PAGE_SHIFT + MAX_SYS_HASH_TABLE_ORDER)) / bucketsize;
-	if (max > mem)
-		max = mem;
+	/* limit allocation size to 1/16 total memory */
+	max = ((unsigned long long)nr_all_pages << PAGE_SHIFT) >> 4;
+	do_div(max, bucketsize);
 
-	/* allow the kernel cmdline to have a say */
-	if (!numentries || numentries > max)
+	if (numentries > max)
 		numentries = max;
 
 	log2qty = long_log2(numentries);
 
 	do {
 		size = bucketsize << log2qty;
-
-		table = (void *) alloc_bootmem(size);
-
-	} while (!table && size > PAGE_SIZE);
+		table = alloc_bootmem(size);
+	} while (!table && size > PAGE_SIZE && --log2qty);
 
 	if (!table)
 		panic("Failed to allocate %s hash table\n", tablename);
diff --git a/mm/prio_tree.c b/mm/prio_tree.c
index 6cd41a831..2a1d02f93 100644
--- a/mm/prio_tree.c
+++ b/mm/prio_tree.c
@@ -81,6 +81,8 @@ static inline unsigned long prio_tree_maxindex(unsigned int bits)
 	return index_bits_to_maxindex[bits - 1];
 }
 
+static void prio_tree_remove(struct prio_tree_root *, struct prio_tree_node *);
+
 /*
  * Extend a priority search tree so that it can store a node with heap_index
  * max_heap_index. In the worst case, this algorithm takes O((log n)^2).
@@ -90,8 +92,6 @@ static inline unsigned long prio_tree_maxindex(unsigned int bits)
 static struct prio_tree_node *prio_tree_expand(struct prio_tree_root *root,
 		struct prio_tree_node *node, unsigned long max_heap_index)
 {
-	static void prio_tree_remove(struct prio_tree_root *,
-					struct prio_tree_node *);
 	struct prio_tree_node *first = NULL, *prev, *last = NULL;
 
 	if (max_heap_index > prio_tree_maxindex(root->index_bits))
@@ -312,9 +312,7 @@ static void prio_tree_remove(struct prio_tree_root *root,
  * 'm' is the number of prio_tree_nodes that overlap the interval X.
  */
 
-static struct prio_tree_node *prio_tree_left(
-		struct prio_tree_root *root, struct prio_tree_iter *iter,
-		unsigned long radix_index, unsigned long heap_index,
+static struct prio_tree_node *prio_tree_left(struct prio_tree_iter *iter,
 		unsigned long *r_index, unsigned long *h_index)
 {
 	if (prio_tree_left_empty(iter->cur))
@@ -322,7 +320,7 @@ static struct prio_tree_node *prio_tree_left(
 
 	GET_INDEX(iter->cur->left, *r_index, *h_index);
 
-	if (radix_index <= *h_index) {
+	if (iter->r_index <= *h_index) {
 		iter->cur = iter->cur->left;
 		iter->mask >>= 1;
 		if (iter->mask) {
@@ -336,7 +334,7 @@ static struct prio_tree_node *prio_tree_left(
 				iter->mask = ULONG_MAX;
 			} else {
 				iter->size_level = 1;
-				iter->mask = 1UL << (root->index_bits - 1);
+				iter->mask = 1UL << (iter->root->index_bits - 1);
 			}
 		}
 		return iter->cur;
@@ -345,9 +343,7 @@ static struct prio_tree_node *prio_tree_left(
 	return NULL;
 }
 
-static struct prio_tree_node *prio_tree_right(
-		struct prio_tree_root *root, struct prio_tree_iter *iter,
-		unsigned long radix_index, unsigned long heap_index,
+static struct prio_tree_node *prio_tree_right(struct prio_tree_iter *iter,
 		unsigned long *r_index, unsigned long *h_index)
 {
 	unsigned long value;
@@ -360,12 +356,12 @@ static struct prio_tree_node *prio_tree_right(
 	else
 		value = iter->value | iter->mask;
 
-	if (heap_index < value)
+	if (iter->h_index < value)
 		return NULL;
 
 	GET_INDEX(iter->cur->right, *r_index, *h_index);
 
-	if (radix_index <= *h_index) {
+	if (iter->r_index <= *h_index) {
 		iter->cur = iter->cur->right;
 		iter->mask >>= 1;
 		iter->value = value;
@@ -380,7 +376,7 @@ static struct prio_tree_node *prio_tree_right(
 				iter->mask = ULONG_MAX;
 			} else {
 				iter->size_level = 1;
-				iter->mask = 1UL << (root->index_bits - 1);
+				iter->mask = 1UL << (iter->root->index_bits - 1);
 			}
 		}
 		return iter->cur;
@@ -405,10 +401,10 @@ static struct prio_tree_node *prio_tree_parent(struct prio_tree_iter *iter)
 	return iter->cur;
 }
 
-static inline int overlap(unsigned long radix_index, unsigned long heap_index,
+static inline int overlap(struct prio_tree_iter *iter,
 		unsigned long r_index, unsigned long h_index)
 {
-	return heap_index >= r_index && radix_index <= h_index;
+	return iter->h_index >= r_index && iter->r_index <= h_index;
 }
 
 /*
@@ -418,35 +414,33 @@ static inline int overlap(unsigned long radix_index, unsigned long heap_index,
  * heap_index]. Note that always radix_index <= heap_index. We do a pre-order
  * traversal of the tree.
  */
-static struct prio_tree_node *prio_tree_first(struct prio_tree_root *root,
-		struct prio_tree_iter *iter, unsigned long radix_index,
-		unsigned long heap_index)
+static struct prio_tree_node *prio_tree_first(struct prio_tree_iter *iter)
 {
+	struct prio_tree_root *root;
 	unsigned long r_index, h_index;
 
 	INIT_PRIO_TREE_ITER(iter);
 
+	root = iter->root;
 	if (prio_tree_empty(root))
 		return NULL;
 
 	GET_INDEX(root->prio_tree_node, r_index, h_index);
 
-	if (radix_index > h_index)
+	if (iter->r_index > h_index)
 		return NULL;
 
 	iter->mask = 1UL << (root->index_bits - 1);
 	iter->cur = root->prio_tree_node;
 
 	while (1) {
-		if (overlap(radix_index, heap_index, r_index, h_index))
+		if (overlap(iter, r_index, h_index))
 			return iter->cur;
 
-		if (prio_tree_left(root, iter, radix_index, heap_index,
-					&r_index, &h_index))
+		if (prio_tree_left(iter, &r_index, &h_index))
 			continue;
 
-		if (prio_tree_right(root, iter, radix_index, heap_index,
-					&r_index, &h_index))
+		if (prio_tree_right(iter, &r_index, &h_index))
 			continue;
 
 		break;
@@ -459,21 +453,16 @@ static struct prio_tree_node *prio_tree_first(struct prio_tree_root *root,
  *
  * Get the next prio_tree_node that overlaps with the input interval in iter
  */
-static struct prio_tree_node *prio_tree_next(struct prio_tree_root *root,
-		struct prio_tree_iter *iter, unsigned long radix_index,
-		unsigned long heap_index)
+static struct prio_tree_node *prio_tree_next(struct prio_tree_iter *iter)
 {
 	unsigned long r_index, h_index;
 
 repeat:
-	while (prio_tree_left(root, iter, radix_index,
-				heap_index, &r_index, &h_index)) {
-		if (overlap(radix_index, heap_index, r_index, h_index))
+	while (prio_tree_left(iter, &r_index, &h_index))
+		if (overlap(iter, r_index, h_index))
 			return iter->cur;
-	}
 
-	while (!prio_tree_right(root, iter, radix_index,
-				heap_index, &r_index, &h_index)) {
+	while (!prio_tree_right(iter, &r_index, &h_index)) {
 	    	while (!prio_tree_root(iter->cur) &&
 				iter->cur->parent->right == iter->cur)
 			prio_tree_parent(iter);
@@ -484,7 +473,7 @@ repeat:
 		prio_tree_parent(iter);
 	}
 
-	if (overlap(radix_index, heap_index, r_index, h_index))
+	if (overlap(iter, r_index, h_index))
 		return iter->cur;
 
 	goto repeat;
@@ -538,6 +527,9 @@ void vma_prio_tree_add(struct vm_area_struct *vma, struct vm_area_struct *old)
 	BUG_ON(RADIX_INDEX(vma) != RADIX_INDEX(old));
 	BUG_ON(HEAP_INDEX(vma) != HEAP_INDEX(old));
 
+	vma->shared.vm_set.head = NULL;
+	vma->shared.vm_set.parent = NULL;
+
 	if (!old->shared.vm_set.parent)
 		list_add(&vma->shared.vm_set.list,
 				&old->shared.vm_set.list);
@@ -557,6 +549,8 @@ void vma_prio_tree_insert(struct vm_area_struct *vma,
 	struct prio_tree_node *ptr;
 	struct vm_area_struct *old;
 
+	vma->shared.vm_set.head = NULL;
+
 	ptr = prio_tree_insert(root, &vma->shared.prio_tree_node);
 	if (ptr != &vma->shared.prio_tree_node) {
 		old = prio_tree_entry(ptr, struct vm_area_struct,
@@ -617,8 +611,7 @@ void vma_prio_tree_remove(struct vm_area_struct *vma,
  * page in the given range of contiguous file pages.
  */
 struct vm_area_struct *vma_prio_tree_next(struct vm_area_struct *vma,
-		struct prio_tree_root *root, struct prio_tree_iter *iter,
-		pgoff_t begin, pgoff_t end)
+					struct prio_tree_iter *iter)
 {
 	struct prio_tree_node *ptr;
 	struct vm_area_struct *next;
@@ -627,7 +620,7 @@ struct vm_area_struct *vma_prio_tree_next(struct vm_area_struct *vma,
 		/*
 		 * First call is with NULL vma
 		 */
-		ptr = prio_tree_first(root, iter, begin, end);
+		ptr = prio_tree_first(iter);
 		if (ptr) {
 			next = prio_tree_entry(ptr, struct vm_area_struct,
 						shared.prio_tree_node);
@@ -652,7 +645,7 @@ struct vm_area_struct *vma_prio_tree_next(struct vm_area_struct *vma,
 		}
 	}
 
-	ptr = prio_tree_next(root, iter, begin, end);
+	ptr = prio_tree_next(iter);
 	if (ptr) {
 		next = prio_tree_entry(ptr, struct vm_area_struct,
 					shared.prio_tree_node);
diff --git a/mm/readahead.c b/mm/readahead.c
index 7073392b3..a5e6906a0 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -28,16 +28,15 @@ struct backing_dev_info default_backing_dev_info = {
 EXPORT_SYMBOL_GPL(default_backing_dev_info);
 
 /*
- * Initialise a struct file's readahead state
+ * Initialise a struct file's readahead state.  Assumes that the caller has
+ * memset *ra to zero.
  */
 void
 file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping)
 {
-	memset(ra, 0, sizeof(*ra));
 	ra->ra_pages = mapping->backing_dev_info->ra_pages;
 	ra->average = ra->ra_pages / 2;
 }
-EXPORT_SYMBOL(file_ra_state_init);
 
 /*
  * Return max readahead size for this inode in number-of-pages.
@@ -384,25 +383,10 @@ page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra,
 		first_access=1;
 		ra->next_size = max / 2;
 		ra->prev_page = offset;
-		ra->serial_cnt++;
+		ra->currnt_wnd_hit++;
 		goto do_io;
 	}
 
-	if (offset == ra->prev_page + 1) {
-		if (ra->serial_cnt <= (max * 2))
-			ra->serial_cnt++;
-	} else {
-		/*
-		 * to avoid rounding errors, ensure that 'average'
-		 * tends towards the value of ra->serial_cnt.
-		 */
-		average = ra->average;
-		if (average < ra->serial_cnt) {
-			average++;
-		}
-		ra->average = (average + ra->serial_cnt) / 2;
-		ra->serial_cnt = 1;
-	}
 	ra->prev_page = offset;
 
 	if (offset >= ra->start && offset <= (ra->start + ra->size)) {
@@ -411,12 +395,22 @@ page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra,
 		 * page beyond the end.  Expand the next readahead size.
 		 */
 		ra->next_size += 2;
+
+		if (ra->currnt_wnd_hit <= (max * 2))
+			ra->currnt_wnd_hit++;
 	} else {
 		/*
 		 * A miss - lseek, pagefault, pread, etc.  Shrink the readahead
 		 * window.
 		 */
 		ra->next_size -= 2;
+
+		average = ra->average;
+		if (average < ra->currnt_wnd_hit) {
+			average++;
+		}
+		ra->average = (average + ra->currnt_wnd_hit) / 2;
+		ra->currnt_wnd_hit = 1;
 	}
 
 	if ((long)ra->next_size > (long)max)
@@ -469,8 +463,8 @@ do_io:
 			  * current window.
 			  */
 			average = ra->average;
-			if (ra->serial_cnt > average)
-				average = (ra->serial_cnt + ra->average + 1) / 2;
+			if (ra->currnt_wnd_hit > average)
+				average = (ra->currnt_wnd_hit + ra->average + 1) / 2;
 
 			ra->next_size = min(average , (unsigned long)max);
 		}
@@ -505,8 +499,8 @@ do_io:
 			 * random. Hence don't bother to readahead.
 			 */
 			average = ra->average;
-			if (ra->serial_cnt > average)
-				average = (ra->serial_cnt + ra->average + 1) / 2;
+			if (ra->currnt_wnd_hit > average)
+				average = (ra->currnt_wnd_hit + ra->average + 1) / 2;
 
 			if (average > max) {
 				ra->ahead_start = ra->start + ra->size;
@@ -577,6 +571,6 @@ unsigned long max_sane_readahead(unsigned long nr)
 	unsigned long inactive;
 	unsigned long free;
 
-	get_zone_counts(&active, &inactive, &free);
+	__get_zone_counts(&active, &inactive, &free, NODE_DATA(numa_node_id()));
 	return min(nr, (inactive + free) / 2);
 }
diff --git a/mm/rmap.c b/mm/rmap.c
index c8e236e58..c5363bf41 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -18,9 +18,30 @@
  */
 
 /*
- * Locking: see "Lock ordering" summary in filemap.c.
- * In swapout, page_map_lock is held on entry to page_referenced and
- * try_to_unmap, so they trylock for i_mmap_lock and page_table_lock.
+ * Lock ordering in mm:
+ *
+ * inode->i_sem	(while writing or truncating, not reading or faulting)
+ *   inode->i_alloc_sem
+ *
+ * When a page fault occurs in writing from user to file, down_read
+ * of mmap_sem nests within i_sem; in sys_msync, i_sem nests within
+ * down_read of mmap_sem; i_sem and down_write of mmap_sem are never
+ * taken together; in truncation, i_sem is taken outermost.
+ *
+ * mm->mmap_sem
+ *   page->flags PG_locked (lock_page)
+ *     mapping->i_mmap_lock
+ *       anon_vma->lock
+ *         mm->page_table_lock
+ *           zone->lru_lock (in mark_page_accessed)
+ *           swap_list_lock (in swap_free etc's swap_info_get)
+ *             swap_device_lock (in swap_duplicate, swap_info_get)
+ *             mapping->private_lock (in __set_page_dirty_buffers)
+ *             inode_lock (in set_page_dirty's __mark_inode_dirty)
+ *               sb_lock (within inode_lock in fs/fs-writeback.c)
+ *               mapping->tree_lock (widely used, in set_page_dirty,
+ *                         in arch-dependent flush_dcache_mmap_lock,
+ *                         within inode_lock in __sync_single_inode)
  */
 
 #include <linux/mm.h>
@@ -30,6 +51,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/rmap.h>
+#include <linux/rcupdate.h>
 #include <linux/vs_memory.h>
 
 #include <asm/tlbflush.h>
@@ -64,28 +86,32 @@ int anon_vma_prepare(struct vm_area_struct *vma)
 	might_sleep();
 	if (unlikely(!anon_vma)) {
 		struct mm_struct *mm = vma->vm_mm;
-		struct anon_vma *allocated = NULL;
+		struct anon_vma *allocated, *locked;
 
 		anon_vma = find_mergeable_anon_vma(vma);
-		if (!anon_vma) {
+		if (anon_vma) {
+			allocated = NULL;
+			locked = anon_vma;
+			spin_lock(&locked->lock);
+		} else {
 			anon_vma = anon_vma_alloc();
 			if (unlikely(!anon_vma))
 				return -ENOMEM;
 			allocated = anon_vma;
+			locked = NULL;
 		}
 
 		/* page_table_lock to protect against threads */
 		spin_lock(&mm->page_table_lock);
 		if (likely(!vma->anon_vma)) {
-			if (!allocated)
-				spin_lock(&anon_vma->lock);
 			vma->anon_vma = anon_vma;
 			list_add(&vma->anon_vma_node, &anon_vma->head);
-			if (!allocated)
-				spin_unlock(&anon_vma->lock);
 			allocated = NULL;
 		}
 		spin_unlock(&mm->page_table_lock);
+
+		if (locked)
+			spin_unlock(&locked->lock);
 		if (unlikely(allocated))
 			anon_vma_free(allocated);
 	}
@@ -160,16 +186,31 @@ static void anon_vma_ctor(void *data, kmem_cache_t *cachep, unsigned long flags)
 
 void __init anon_vma_init(void)
 {
-	anon_vma_cachep = kmem_cache_create("anon_vma",
-		sizeof(struct anon_vma), 0, SLAB_PANIC, anon_vma_ctor, NULL);
+	anon_vma_cachep = kmem_cache_create("anon_vma", sizeof(struct anon_vma),
+			0, SLAB_DESTROY_BY_RCU|SLAB_PANIC, anon_vma_ctor, NULL);
 }
 
-/* this needs the page->flags PG_maplock held */
-static inline void clear_page_anon(struct page *page)
+/*
+ * Getting a lock on a stable anon_vma from a page off the LRU is
+ * tricky: page_lock_anon_vma rely on RCU to guard against the races.
+ */
+static struct anon_vma *page_lock_anon_vma(struct page *page)
 {
-	BUG_ON(!page->mapping);
-	page->mapping = NULL;
-	ClearPageAnon(page);
+	struct anon_vma *anon_vma = NULL;
+	unsigned long anon_mapping;
+
+	rcu_read_lock();
+	anon_mapping = (unsigned long) page->mapping;
+	if (!(anon_mapping & PAGE_MAPPING_ANON))
+		goto out;
+	if (!page_mapped(page))
+		goto out;
+
+	anon_vma = (struct anon_vma *) (anon_mapping - PAGE_MAPPING_ANON);
+	spin_lock(&anon_vma->lock);
+out:
+	rcu_read_unlock();
+	return anon_vma;
 }
 
 /*
@@ -190,6 +231,24 @@ vma_address(struct page *page, struct vm_area_struct *vma)
 	return address;
 }
 
+/*
+ * At what user virtual address is page expected in vma? checking that the
+ * page matches the vma: currently only used by unuse_process, on anon pages.
+ */
+unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma)
+{
+	if (PageAnon(page)) {
+		if ((void *)vma->anon_vma !=
+		    (void *)page->mapping - PAGE_MAPPING_ANON)
+			return -EFAULT;
+	} else if (page->mapping && !(vma->vm_flags & VM_NONLINEAR)) {
+		if (vma->vm_file->f_mapping != page->mapping)
+			return -EFAULT;
+	} else
+		return -EFAULT;
+	return vma_address(page, vma);
+}
+
 /*
  * Subfunctions of page_referenced: page_referenced_one called
  * repeatedly from either page_referenced_anon or page_referenced_file.
@@ -210,8 +269,7 @@ static int page_referenced_one(struct page *page,
 	if (address == -EFAULT)
 		goto out;
 
-	if (!spin_trylock(&mm->page_table_lock))
-		goto out;
+	spin_lock(&mm->page_table_lock);
 
 	pgd = pgd_offset(mm, address);
 	if (!pgd_present(*pgd))
@@ -231,6 +289,9 @@ static int page_referenced_one(struct page *page,
 	if (ptep_clear_flush_young(vma, address, pte))
 		referenced++;
 
+	if (mm != current->mm && has_swap_token(mm))
+		referenced++;
+
 	(*mapcount)--;
 
 out_unmap:
@@ -241,15 +302,18 @@ out:
 	return referenced;
 }
 
-static inline int page_referenced_anon(struct page *page)
+static int page_referenced_anon(struct page *page)
 {
-	unsigned int mapcount = page->mapcount;
-	struct anon_vma *anon_vma = (struct anon_vma *) page->mapping;
+	unsigned int mapcount;
+	struct anon_vma *anon_vma;
 	struct vm_area_struct *vma;
 	int referenced = 0;
 
-	spin_lock(&anon_vma->lock);
-	BUG_ON(list_empty(&anon_vma->head));
+	anon_vma = page_lock_anon_vma(page);
+	if (!anon_vma)
+		return referenced;
+
+	mapcount = page_mapcount(page);
 	list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
 		referenced += page_referenced_one(page, vma, &mapcount);
 		if (!mapcount)
@@ -269,24 +333,40 @@ static inline int page_referenced_anon(struct page *page)
  * of references it found.
  *
  * This function is only called from page_referenced for object-based pages.
- *
- * The spinlock address_space->i_mmap_lock is tried.  If it can't be gotten,
- * assume a reference count of 0, so try_to_unmap will then have a go.
  */
-static inline int page_referenced_file(struct page *page)
+static int page_referenced_file(struct page *page)
 {
-	unsigned int mapcount = page->mapcount;
+	unsigned int mapcount;
 	struct address_space *mapping = page->mapping;
 	pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
-	struct vm_area_struct *vma = NULL;
+	struct vm_area_struct *vma;
 	struct prio_tree_iter iter;
 	int referenced = 0;
 
-	if (!spin_trylock(&mapping->i_mmap_lock))
-		return 0;
+	/*
+	 * The caller's checks on page->mapping and !PageAnon have made
+	 * sure that this is a file page: the check for page->mapping
+	 * excludes the case just before it gets set on an anon page.
+	 */
+	BUG_ON(PageAnon(page));
+
+	/*
+	 * The page lock not only makes sure that page->mapping cannot
+	 * suddenly be NULLified by truncation, it makes sure that the
+	 * structure at mapping cannot be freed and reused yet,
+	 * so we can safely take mapping->i_mmap_lock.
+	 */
+	BUG_ON(!PageLocked(page));
 
-	while ((vma = vma_prio_tree_next(vma, &mapping->i_mmap,
-					&iter, pgoff, pgoff)) != NULL) {
+	spin_lock(&mapping->i_mmap_lock);
+
+	/*
+	 * i_mmap_lock does not stabilize mapcount at all, but mapcount
+	 * is more likely to be accurate if we note it after spinning.
+	 */
+	mapcount = page_mapcount(page);
+
+	vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) {
 		if ((vma->vm_flags & (VM_LOCKED|VM_MAYSHARE))
 				  == (VM_LOCKED|VM_MAYSHARE)) {
 			referenced++;
@@ -304,12 +384,12 @@ static inline int page_referenced_file(struct page *page)
 /**
  * page_referenced - test if the page was referenced
  * @page: the page to test
+ * @is_locked: caller holds lock on the page
  *
  * Quick test_and_clear_referenced for all mappings to a page,
  * returns the number of ptes which referenced the page.
- * Caller needs to hold the rmap lock.
  */
-int page_referenced(struct page *page)
+int page_referenced(struct page *page, int is_locked)
 {
 	int referenced = 0;
 
@@ -319,11 +399,18 @@ int page_referenced(struct page *page)
 	if (TestClearPageReferenced(page))
 		referenced++;
 
-	if (page->mapcount && page->mapping) {
+	if (page_mapped(page) && page->mapping) {
 		if (PageAnon(page))
 			referenced += page_referenced_anon(page);
-		else
+		else if (is_locked)
 			referenced += page_referenced_file(page);
+		else if (TestSetPageLocked(page))
+			referenced++;
+		else {
+			if (page->mapping)
+				referenced += page_referenced_file(page);
+			unlock_page(page);
+		}
 	}
 	return referenced;
 }
@@ -345,36 +432,17 @@ void page_add_anon_rmap(struct page *page,
 	BUG_ON(PageReserved(page));
 	BUG_ON(!anon_vma);
 
+	anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON;
 	index = (address - vma->vm_start) >> PAGE_SHIFT;
 	index += vma->vm_pgoff;
 	index >>= PAGE_CACHE_SHIFT - PAGE_SHIFT;
 
-	/*
-	 * Setting and clearing PG_anon must always happen inside
-	 * page_map_lock to avoid races between mapping and
-	 * unmapping on different processes of the same
-	 * shared cow swapcache page. And while we take the
-	 * page_map_lock PG_anon cannot change from under us.
-	 * Actually PG_anon cannot change under fork either
-	 * since fork holds a reference on the page so it cannot
-	 * be unmapped under fork and in turn copy_page_range is
-	 * allowed to read PG_anon outside the page_map_lock.
-	 */
-	page_map_lock(page);
-	if (!page->mapcount) {
-		BUG_ON(PageAnon(page));
-		BUG_ON(page->mapping);
-		SetPageAnon(page);
+	if (atomic_inc_and_test(&page->_mapcount)) {
 		page->index = index;
 		page->mapping = (struct address_space *) anon_vma;
 		inc_page_state(nr_mapped);
-	} else {
-		BUG_ON(!PageAnon(page));
-		BUG_ON(page->index != index);
-		BUG_ON(page->mapping != (struct address_space *) anon_vma);
 	}
-	page->mapcount++;
-	page_map_unlock(page);
+	/* else checking page index and mapping is racy */
 }
 
 /**
@@ -389,11 +457,8 @@ void page_add_file_rmap(struct page *page)
 	if (!pfn_valid(page_to_pfn(page)) || PageReserved(page))
 		return;
 
-	page_map_lock(page);
-	if (!page->mapcount)
+	if (atomic_inc_and_test(&page->_mapcount))
 		inc_page_state(nr_mapped);
-	page->mapcount++;
-	page_map_unlock(page);
 }
 
 /**
@@ -405,18 +470,22 @@ void page_add_file_rmap(struct page *page)
 void page_remove_rmap(struct page *page)
 {
 	BUG_ON(PageReserved(page));
-	BUG_ON(!page->mapcount);
 
-	page_map_lock(page);
-	page->mapcount--;
-	if (!page->mapcount) {
+	if (atomic_add_negative(-1, &page->_mapcount)) {
+		BUG_ON(page_mapcount(page) < 0);
+		/*
+		 * It would be tidy to reset the PageAnon mapping here,
+		 * but that might overwrite a racing page_add_anon_rmap
+		 * which increments mapcount after us but sets mapping
+		 * before us: so leave the reset to free_hot_cold_page,
+		 * and remember that it's only reliable while mapped.
+		 * Leaving it set also helps swapoff to reinstate ptes
+		 * faster for those pages still in swapcache.
+		 */
 		if (page_test_and_clear_dirty(page))
 			set_page_dirty(page);
-		if (PageAnon(page))
-			clear_page_anon(page);
 		dec_page_state(nr_mapped);
 	}
-	page_map_unlock(page);
 }
 
 /*
@@ -443,8 +512,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma)
 	 * We need the page_table_lock to protect us from page faults,
 	 * munmap, fork, etc...
 	 */
-	if (!spin_trylock(&mm->page_table_lock))
-		goto out;
+	spin_lock(&mm->page_table_lock);
 
 	pgd = pgd_offset(mm, address);
 	if (!pgd_present(*pgd))
@@ -488,7 +556,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma)
 	 * ptes from being unmapped, so swapoff can make progress.
 	 */
 	if (PageSwapCache(page) &&
-	    page_count(page) != page->mapcount + 2) {
+	    page_count(page) != page_mapcount(page) + 2) {
 		ret = SWAP_FAIL;
 		goto out_unmap;
 	}
@@ -515,8 +583,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma)
 
 	// mm->rss--;
 	vx_rsspages_dec(mm);
-	BUG_ON(!page->mapcount);
-	page->mapcount--;
+	page_remove_rmap(page);
 	page_cache_release(page);
 
 out_unmap:
@@ -549,7 +616,7 @@ out:
 #define CLUSTER_SIZE	min(32*PAGE_SIZE, PMD_SIZE)
 #define CLUSTER_MASK	(~(CLUSTER_SIZE - 1))
 
-static int try_to_unmap_cluster(unsigned long cursor,
+static void try_to_unmap_cluster(unsigned long cursor,
 	unsigned int *mapcount, struct vm_area_struct *vma)
 {
 	struct mm_struct *mm = vma->vm_mm;
@@ -566,8 +633,7 @@ static int try_to_unmap_cluster(unsigned long cursor,
 	 * We need the page_table_lock to protect us from page faults,
 	 * munmap, fork, etc...
 	 */
-	if (!spin_trylock(&mm->page_table_lock))
-		return SWAP_FAIL;
+	spin_lock(&mm->page_table_lock);
 
 	address = (vma->vm_start + cursor) & CLUSTER_MASK;
 	end = address + CLUSTER_SIZE;
@@ -625,20 +691,21 @@ static int try_to_unmap_cluster(unsigned long cursor,
 
 out_unlock:
 	spin_unlock(&mm->page_table_lock);
-	return SWAP_AGAIN;
 }
 
-static inline int try_to_unmap_anon(struct page *page)
+static int try_to_unmap_anon(struct page *page)
 {
-	struct anon_vma *anon_vma = (struct anon_vma *) page->mapping;
+	struct anon_vma *anon_vma;
 	struct vm_area_struct *vma;
 	int ret = SWAP_AGAIN;
 
-	spin_lock(&anon_vma->lock);
-	BUG_ON(list_empty(&anon_vma->head));
+	anon_vma = page_lock_anon_vma(page);
+	if (!anon_vma)
+		return ret;
+
 	list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
 		ret = try_to_unmap_one(page, vma);
-		if (ret == SWAP_FAIL || !page->mapcount)
+		if (ret == SWAP_FAIL || !page_mapped(page))
 			break;
 	}
 	spin_unlock(&anon_vma->lock);
@@ -653,15 +720,12 @@ static inline int try_to_unmap_anon(struct page *page)
  * contained in the address_space struct it points to.
  *
  * This function is only called from try_to_unmap for object-based pages.
- *
- * The spinlock address_space->i_mmap_lock is tried.  If it can't be gotten,
- * return a temporary error.
  */
-static inline int try_to_unmap_file(struct page *page)
+static int try_to_unmap_file(struct page *page)
 {
 	struct address_space *mapping = page->mapping;
 	pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
-	struct vm_area_struct *vma = NULL;
+	struct vm_area_struct *vma;
 	struct prio_tree_iter iter;
 	int ret = SWAP_AGAIN;
 	unsigned long cursor;
@@ -669,13 +733,10 @@ static inline int try_to_unmap_file(struct page *page)
 	unsigned long max_nl_size = 0;
 	unsigned int mapcount;
 
-	if (!spin_trylock(&mapping->i_mmap_lock))
-		return ret;
-
-	while ((vma = vma_prio_tree_next(vma, &mapping->i_mmap,
-					&iter, pgoff, pgoff)) != NULL) {
+	spin_lock(&mapping->i_mmap_lock);
+	vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) {
 		ret = try_to_unmap_one(page, vma);
-		if (ret == SWAP_FAIL || !page->mapcount)
+		if (ret == SWAP_FAIL || !page_mapped(page))
 			goto out;
 	}
 
@@ -694,8 +755,10 @@ static inline int try_to_unmap_file(struct page *page)
 			max_nl_size = cursor;
 	}
 
-	if (max_nl_size == 0)	/* any nonlinears locked or reserved */
+	if (max_nl_size == 0) {	/* any nonlinears locked or reserved */
+		ret = SWAP_FAIL;
 		goto out;
+	}
 
 	/*
 	 * We don't try to search for this page in the nonlinear vmas,
@@ -704,8 +767,9 @@ static inline int try_to_unmap_file(struct page *page)
 	 * The mapcount of the page we came in with is irrelevant,
 	 * but even so use it as a guide to how hard we should try?
 	 */
-	mapcount = page->mapcount;
-	page_map_unlock(page);
+	mapcount = page_mapcount(page);
+	if (!mapcount)
+		goto out;
 	cond_resched_lock(&mapping->i_mmap_lock);
 
 	max_nl_size = (max_nl_size + CLUSTER_SIZE - 1) & CLUSTER_MASK;
@@ -721,19 +785,13 @@ static inline int try_to_unmap_file(struct page *page)
 			while (vma->vm_mm->rss &&
 				cursor < max_nl_cursor &&
 				cursor < vma->vm_end - vma->vm_start) {
-				ret = try_to_unmap_cluster(
-						cursor, &mapcount, vma);
-				if (ret == SWAP_FAIL)
-					break;
+				try_to_unmap_cluster(cursor, &mapcount, vma);
 				cursor += CLUSTER_SIZE;
 				vma->vm_private_data = (void *) cursor;
 				if ((int)mapcount <= 0)
-					goto relock;
+					goto out;
 			}
-			if (ret != SWAP_FAIL)
-				vma->vm_private_data =
-					(void *) max_nl_cursor;
-			ret = SWAP_AGAIN;
+			vma->vm_private_data = (void *) max_nl_cursor;
 		}
 		cond_resched_lock(&mapping->i_mmap_lock);
 		max_nl_cursor += CLUSTER_SIZE;
@@ -749,8 +807,6 @@ static inline int try_to_unmap_file(struct page *page)
 		if (!(vma->vm_flags & VM_RESERVED))
 			vma->vm_private_data = NULL;
 	}
-relock:
-	page_map_lock(page);
 out:
 	spin_unlock(&mapping->i_mmap_lock);
 	return ret;
@@ -761,11 +817,11 @@ out:
  * @page: the page to get unmapped
  *
  * Tries to remove all the page table entries which are mapping this
- * page, used in the pageout path.  Caller must hold the page lock
- * and its rmap lock.  Return values are:
+ * page, used in the pageout path.  Caller must hold the page lock.
+ * Return values are:
  *
  * SWAP_SUCCESS	- we succeeded in removing all mappings
- * SWAP_AGAIN	- we missed a trylock, try again later
+ * SWAP_AGAIN	- we missed a mapping, try again later
  * SWAP_FAIL	- the page is unswappable
  */
 int try_to_unmap(struct page *page)
@@ -774,20 +830,13 @@ int try_to_unmap(struct page *page)
 
 	BUG_ON(PageReserved(page));
 	BUG_ON(!PageLocked(page));
-	BUG_ON(!page->mapcount);
 
 	if (PageAnon(page))
 		ret = try_to_unmap_anon(page);
 	else
 		ret = try_to_unmap_file(page);
 
-	if (!page->mapcount) {
-		if (page_test_and_clear_dirty(page))
-			set_page_dirty(page);
-		if (PageAnon(page))
-			clear_page_anon(page);
-		dec_page_state(nr_mapped);
+	if (!page_mapped(page))
 		ret = SWAP_SUCCESS;
-	}
 	return ret;
 }
diff --git a/mm/shmem.c b/mm/shmem.c
index 57f861722..8951a2a50 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -6,8 +6,8 @@
  *		 2000-2001 Christoph Rohland
  *		 2000-2001 SAP AG
  *		 2002 Red Hat Inc.
- * Copyright (C) 2002-2003 Hugh Dickins.
- * Copyright (C) 2002-2003 VERITAS Software Corporation.
+ * Copyright (C) 2002-2004 Hugh Dickins.
+ * Copyright (C) 2002-2004 VERITAS Software Corporation.
  * Copyright (C) 2004 Andi Kleen, SuSE Labs
  *
  * This file is released under the GPL.
@@ -178,16 +178,18 @@ static struct backing_dev_info shmem_backing_dev_info = {
 	.unplug_io_fn = default_unplug_io_fn,
 };
 
-LIST_HEAD(shmem_inodes);
-static spinlock_t shmem_ilock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(shmem_swaplist);
+static spinlock_t shmem_swaplist_lock = SPIN_LOCK_UNLOCKED;
 
 static void shmem_free_block(struct inode *inode)
 {
 	struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
-	spin_lock(&sbinfo->stat_lock);
-	sbinfo->free_blocks++;
-	inode->i_blocks -= BLOCKS_PER_PAGE;
-	spin_unlock(&sbinfo->stat_lock);
+	if (sbinfo) {
+		spin_lock(&sbinfo->stat_lock);
+		sbinfo->free_blocks++;
+		inode->i_blocks -= BLOCKS_PER_PAGE;
+		spin_unlock(&sbinfo->stat_lock);
+	}
 }
 
 /*
@@ -212,11 +214,13 @@ static void shmem_recalc_inode(struct inode *inode)
 	if (freed > 0) {
 		struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
 		info->alloced -= freed;
-		spin_lock(&sbinfo->stat_lock);
-		sbinfo->free_blocks += freed;
-		inode->i_blocks -= freed*BLOCKS_PER_PAGE;
-		spin_unlock(&sbinfo->stat_lock);
 		shmem_unacct_blocks(info->flags, freed);
+		if (sbinfo) {
+			spin_lock(&sbinfo->stat_lock);
+			sbinfo->free_blocks += freed;
+			inode->i_blocks -= freed*BLOCKS_PER_PAGE;
+			spin_unlock(&sbinfo->stat_lock);
+		}
 	}
 }
 
@@ -349,14 +353,16 @@ static swp_entry_t *shmem_swp_alloc(struct shmem_inode_info *info, unsigned long
 		 * page (and perhaps indirect index pages) yet to allocate:
 		 * a waste to allocate index if we cannot allocate data.
 		 */
-		spin_lock(&sbinfo->stat_lock);
-		if (sbinfo->free_blocks <= 1) {
+		if (sbinfo) {
+			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);
-			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));
@@ -597,17 +603,21 @@ static void shmem_delete_inode(struct inode *inode)
 	struct shmem_inode_info *info = SHMEM_I(inode);
 
 	if (inode->i_op->truncate == shmem_truncate) {
-		spin_lock(&shmem_ilock);
-		list_del(&info->list);
-		spin_unlock(&shmem_ilock);
 		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);
+		}
+	}
+	if (sbinfo) {
+		BUG_ON(inode->i_blocks);
+		spin_lock(&sbinfo->stat_lock);
+		sbinfo->free_inodes++;
+		spin_unlock(&sbinfo->stat_lock);
 	}
-	BUG_ON(inode->i_blocks);
-	spin_lock(&sbinfo->stat_lock);
-	sbinfo->free_inodes++;
-	spin_unlock(&sbinfo->stat_lock);
 	clear_inode(inode);
 }
 
@@ -712,22 +722,23 @@ found:
  */
 int shmem_unuse(swp_entry_t entry, struct page *page)
 {
-	struct list_head *p;
+	struct list_head *p, *next;
 	struct shmem_inode_info *info;
 	int found = 0;
 
-	spin_lock(&shmem_ilock);
-	list_for_each(p, &shmem_inodes) {
-		info = list_entry(p, struct shmem_inode_info, list);
-
-		if (info->swapped && shmem_unuse_inode(info, entry, page)) {
+	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_inodes, &info->list);
+			list_move_tail(&shmem_swaplist, &info->swaplist);
 			found = 1;
 			break;
 		}
 	}
-	spin_unlock(&shmem_ilock);
+	spin_unlock(&shmem_swaplist_lock);
 	return found;
 }
 
@@ -769,6 +780,12 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
 		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;
 	}
@@ -867,7 +884,7 @@ static int shmem_getpage(struct inode *inode, unsigned long idx,
 	struct page *swappage;
 	swp_entry_t *entry;
 	swp_entry_t swap;
-	int error, majmin = VM_FAULT_MINOR;
+	int error;
 
 	if (idx >= SHMEM_MAX_INDEX)
 		return -EFBIG;
@@ -905,9 +922,10 @@ repeat:
 			shmem_swp_unmap(entry);
 			spin_unlock(&info->lock);
 			/* here we actually do the io */
-			if (majmin == VM_FAULT_MINOR && type)
+			if (type && *type == VM_FAULT_MINOR) {
 				inc_page_state(pgmajfault);
-			majmin = VM_FAULT_MAJOR;
+				*type = VM_FAULT_MAJOR;
+			}
 			swappage = shmem_swapin(info, swap, idx);
 			if (!swappage) {
 				spin_lock(&info->lock);
@@ -1000,16 +1018,23 @@ repeat:
 	} else {
 		shmem_swp_unmap(entry);
 		sbinfo = SHMEM_SB(inode->i_sb);
-		spin_lock(&sbinfo->stat_lock);
-		if (sbinfo->free_blocks == 0 || shmem_acct_block(info->flags)) {
+		if (sbinfo) {
+			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;
 		}
-		sbinfo->free_blocks--;
-		inode->i_blocks += BLOCKS_PER_PAGE;
-		spin_unlock(&sbinfo->stat_lock);
 
 		if (!filepage) {
 			spin_unlock(&info->lock);
@@ -1052,15 +1077,10 @@ repeat:
 		SetPageUptodate(filepage);
 	}
 done:
-	if (!*pagep) {
-		if (filepage) {
-			unlock_page(filepage);
-			*pagep = filepage;
-		} else
-			*pagep = ZERO_PAGE(0);
+	if (*pagep != filepage) {
+		unlock_page(filepage);
+		*pagep = filepage;
 	}
-	if (type)
-		*type = majmin;
 	return 0;
 
 failed:
@@ -1150,17 +1170,26 @@ shmem_get_policy(struct vm_area_struct *vma, unsigned long addr)
 }
 #endif
 
-void shmem_lock(struct file *file, int lock)
+int shmem_lock(struct file *file, int lock, struct user_struct *user)
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	struct shmem_inode_info *info = SHMEM_I(inode);
+	int retval = -ENOMEM;
 
 	spin_lock(&info->lock);
-	if (lock)
+	if (lock && !(info->flags & VM_LOCKED)) {
+		if (!user_shm_lock(inode->i_size, user))
+			goto out_nomem;
 		info->flags |= VM_LOCKED;
-	else
+	}
+	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)
@@ -1177,13 +1206,15 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
 	struct shmem_inode_info *info;
 	struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
 
-	spin_lock(&sbinfo->stat_lock);
-	if (!sbinfo->free_inodes) {
+	if (sbinfo) {
+		spin_lock(&sbinfo->stat_lock);
+		if (!sbinfo->free_inodes) {
+			spin_unlock(&sbinfo->stat_lock);
+			return NULL;
+		}
+		sbinfo->free_inodes--;
 		spin_unlock(&sbinfo->stat_lock);
-		return NULL;
 	}
-	sbinfo->free_inodes--;
-	spin_unlock(&sbinfo->stat_lock);
 
 	inode = new_inode(sb);
 	if (inode) {
@@ -1199,6 +1230,8 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
 		memset(info, 0, (char *)inode - (char *)info);
 		spin_lock_init(&info->lock);
  		mpol_shared_policy_init(&info->policy);
+		INIT_LIST_HEAD(&info->swaplist);
+
 		switch (mode & S_IFMT) {
 		default:
 			init_special_inode(inode, mode, dev);
@@ -1206,9 +1239,6 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
 		case S_IFREG:
 			inode->i_op = &shmem_inode_operations;
 			inode->i_fop = &shmem_file_operations;
-			spin_lock(&shmem_ilock);
-			list_add_tail(&info->list, &shmem_inodes);
-			spin_unlock(&shmem_ilock);
 			break;
 		case S_IFDIR:
 			inode->i_nlink++;
@@ -1224,32 +1254,32 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
 	return inode;
 }
 
-static int shmem_set_size(struct shmem_sb_info *info,
+#ifdef CONFIG_TMPFS
+
+static int shmem_set_size(struct shmem_sb_info *sbinfo,
 			  unsigned long max_blocks, unsigned long max_inodes)
 {
 	int error;
 	unsigned long blocks, inodes;
 
-	spin_lock(&info->stat_lock);
-	blocks = info->max_blocks - info->free_blocks;
-	inodes = info->max_inodes - info->free_inodes;
+	spin_lock(&sbinfo->stat_lock);
+	blocks = sbinfo->max_blocks - sbinfo->free_blocks;
+	inodes = sbinfo->max_inodes - sbinfo->free_inodes;
 	error = -EINVAL;
 	if (max_blocks < blocks)
 		goto out;
 	if (max_inodes < inodes)
 		goto out;
 	error = 0;
-	info->max_blocks  = max_blocks;
-	info->free_blocks = max_blocks - blocks;
-	info->max_inodes  = max_inodes;
-	info->free_inodes = max_inodes - inodes;
+	sbinfo->max_blocks  = max_blocks;
+	sbinfo->free_blocks = max_blocks - blocks;
+	sbinfo->max_inodes  = max_inodes;
+	sbinfo->free_inodes = max_inodes - inodes;
 out:
-	spin_unlock(&info->stat_lock);
+	spin_unlock(&sbinfo->stat_lock);
 	return error;
 }
 
-#ifdef CONFIG_TMPFS
-
 static struct inode_operations shmem_symlink_inode_operations;
 static struct inode_operations shmem_symlink_inline_operations;
 
@@ -1270,7 +1300,7 @@ shmem_file_write(struct file *file, const char __user *buf, size_t count, loff_t
 	struct inode	*inode = file->f_dentry->d_inode;
 	loff_t		pos;
 	unsigned long	written;
-	int		err;
+	ssize_t		err;
 
 	if ((ssize_t) count < 0)
 		return -EINVAL;
@@ -1322,7 +1352,8 @@ shmem_file_write(struct file *file, const char __user *buf, size_t count, loff_t
 			__get_user(dummy, buf + bytes - 1);
 
 			kaddr = kmap_atomic(page, KM_USER0);
-			left = __copy_from_user(kaddr + offset, buf, bytes);
+			left = __copy_from_user_inatomic(kaddr + offset,
+							buf, bytes);
 			kunmap_atomic(kaddr, KM_USER0);
 		}
 		if (left) {
@@ -1406,13 +1437,14 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_
 		if (index == end_index) {
 			nr = i_size & ~PAGE_CACHE_MASK;
 			if (nr <= offset) {
-				page_cache_release(page);
+				if (page)
+					page_cache_release(page);
 				break;
 			}
 		}
 		nr -= offset;
 
-		if (page != ZERO_PAGE(0)) {
+		if (page) {
 			/*
 			 * If users can be writing to this page using arbitrary
 			 * virtual addresses, take care about potential aliasing
@@ -1425,7 +1457,8 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_
 			 */
 			if (!offset)
 				mark_page_accessed(page);
-		}
+		} else
+			page = ZERO_PAGE(0);
 
 		/*
 		 * Ok, we have the page, and it's up-to-date, so
@@ -1500,13 +1533,16 @@ static int shmem_statfs(struct super_block *sb, struct kstatfs *buf)
 
 	buf->f_type = TMPFS_SUPER_MAGIC;
 	buf->f_bsize = PAGE_CACHE_SIZE;
-	spin_lock(&sbinfo->stat_lock);
-	buf->f_blocks = sbinfo->max_blocks;
-	buf->f_bavail = buf->f_bfree = sbinfo->free_blocks;
-	buf->f_files = sbinfo->max_inodes;
-	buf->f_ffree = sbinfo->free_inodes;
-	spin_unlock(&sbinfo->stat_lock);
 	buf->f_namelen = NAME_MAX;
+	if (sbinfo) {
+		spin_lock(&sbinfo->stat_lock);
+		buf->f_blocks = sbinfo->max_blocks;
+		buf->f_bavail = buf->f_bfree = sbinfo->free_blocks;
+		buf->f_files = sbinfo->max_inodes;
+		buf->f_ffree = sbinfo->free_inodes;
+		spin_unlock(&sbinfo->stat_lock);
+	}
+	/* else leave those fields 0 like simple_statfs */
 	return 0;
 }
 
@@ -1556,6 +1592,22 @@ static int shmem_create(struct inode *dir, struct dentry *dentry, int mode,
 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) {
+		spin_lock(&sbinfo->stat_lock);
+		if (!sbinfo->free_inodes) {
+			spin_unlock(&sbinfo->stat_lock);
+			return -ENOSPC;
+		}
+		sbinfo->free_inodes--;
+		spin_unlock(&sbinfo->stat_lock);
+	}
 
 	dir->i_size += BOGO_DIRENT_SIZE;
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
@@ -1570,6 +1622,15 @@ static int shmem_unlink(struct inode *dir, struct dentry *dentry)
 {
 	struct inode *inode = dentry->d_inode;
 
+	if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode)) {
+		struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
+		if (sbinfo) {
+			spin_lock(&sbinfo->stat_lock);
+			sbinfo->free_inodes++;
+			spin_unlock(&sbinfo->stat_lock);
+		}
+	}
+
 	dir->i_size -= BOGO_DIRENT_SIZE;
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 	inode->i_nlink--;
@@ -1647,9 +1708,6 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
 			return error;
 		}
 		inode->i_op = &shmem_symlink_inode_operations;
-		spin_lock(&shmem_ilock);
-		list_add_tail(&info->list, &shmem_inodes);
-		spin_unlock(&shmem_ilock);
 		kaddr = kmap_atomic(page, KM_USER0);
 		memcpy(kaddr, symname, len);
 		kunmap_atomic(kaddr, KM_USER0);
@@ -1778,53 +1836,75 @@ bad_val:
 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;
+	unsigned long max_blocks = 0;
+	unsigned long max_inodes = 0;
 
+	if (sbinfo) {
+		max_blocks = sbinfo->max_blocks;
+		max_inodes = sbinfo->max_inodes;
+	}
 	if (shmem_parse_options(data, NULL, NULL, NULL, &max_blocks, &max_inodes))
 		return -EINVAL;
+	/* Keep it simple: disallow limited <-> unlimited remount */
+	if ((max_blocks || max_inodes) == !sbinfo)
+		return -EINVAL;
+	/* But allow the pointless unlimited -> unlimited remount */
+	if (!sbinfo)
+		return 0;
 	return shmem_set_size(sbinfo, max_blocks, max_inodes);
 }
 #endif
 
+static void shmem_put_super(struct super_block *sb)
+{
+	kfree(sb->s_fs_info);
+	sb->s_fs_info = NULL;
+}
+
 static int shmem_fill_super(struct super_block *sb,
 			    void *data, int silent)
 {
 	struct inode *inode;
 	struct dentry *root;
-	unsigned long blocks, inodes;
 	int mode   = S_IRWXUGO | S_ISVTX;
 	uid_t uid = current->fsuid;
 	gid_t gid = current->fsgid;
-	struct shmem_sb_info *sbinfo;
 	int err = -ENOMEM;
 
-	sbinfo = kmalloc(sizeof(struct shmem_sb_info), GFP_KERNEL);
-	if (!sbinfo)
-		return -ENOMEM;
-	sb->s_fs_info = sbinfo;
-	memset(sbinfo, 0, sizeof(struct shmem_sb_info));
+#ifdef CONFIG_TMPFS
+	unsigned long blocks = 0;
+	unsigned long inodes = 0;
 
 	/*
 	 * Per default we only allow half of the physical ram per
-	 * tmpfs instance
+	 * tmpfs instance, limiting inodes to one per page of lowmem;
+	 * but the internal instance is left unlimited.
 	 */
-	blocks = inodes = totalram_pages / 2;
+	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))
+			return -EINVAL;
+	}
 
-#ifdef CONFIG_TMPFS
-	if (shmem_parse_options(data, &mode, &uid, &gid, &blocks, &inodes)) {
-		err = -EINVAL;
-		goto failed;
+	if (blocks || inodes) {
+		struct shmem_sb_info *sbinfo;
+		sbinfo = kmalloc(sizeof(struct shmem_sb_info), GFP_KERNEL);
+		if (!sbinfo)
+			return -ENOMEM;
+		sb->s_fs_info = sbinfo;
+		spin_lock_init(&sbinfo->stat_lock);
+		sbinfo->max_blocks = blocks;
+		sbinfo->free_blocks = blocks;
+		sbinfo->max_inodes = inodes;
+		sbinfo->free_inodes = inodes;
 	}
-#else
-	sb->s_flags |= MS_NOUSER;
 #endif
 
-	spin_lock_init(&sbinfo->stat_lock);
-	sbinfo->max_blocks = blocks;
-	sbinfo->free_blocks = blocks;
-	sbinfo->max_inodes = inodes;
-	sbinfo->free_inodes = inodes;
 	sb->s_maxbytes = SHMEM_MAX_BYTES;
 	sb->s_blocksize = PAGE_CACHE_SIZE;
 	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
@@ -1844,17 +1924,10 @@ static int shmem_fill_super(struct super_block *sb,
 failed_iput:
 	iput(inode);
 failed:
-	kfree(sbinfo);
-	sb->s_fs_info = NULL;
+	shmem_put_super(sb);
 	return err;
 }
 
-static void shmem_put_super(struct super_block *sb)
-{
-	kfree(sb->s_fs_info);
-	sb->s_fs_info = NULL;
-}
-
 static kmem_cache_t *shmem_inode_cachep;
 
 static struct inode *shmem_alloc_inode(struct super_block *sb)
@@ -1886,8 +1959,7 @@ static int init_inodecache(void)
 {
 	shmem_inode_cachep = kmem_cache_create("shmem_inode_cache",
 				sizeof(struct shmem_inode_info),
-				0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
-				init_once, NULL);
+				0, 0, init_once, NULL);
 	if (shmem_inode_cachep == NULL)
 		return -ENOMEM;
 	return 0;
@@ -1989,15 +2061,13 @@ static int __init init_tmpfs(void)
 #ifdef CONFIG_TMPFS
 	devfs_mk_dir("shm");
 #endif
-	shm_mnt = kern_mount(&tmpfs_fs_type);
+	shm_mnt = do_kern_mount(tmpfs_fs_type.name, 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;
 	}
-
-	/* The internal instance should not do size checking */
-	shmem_set_size(SHMEM_SB(shm_mnt->mnt_sb), ULONG_MAX, ULONG_MAX);
 	return 0;
 
 out1:
@@ -2028,7 +2098,7 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
 	if (IS_ERR(shm_mnt))
 		return (void *)shm_mnt;
 
-	if (size > SHMEM_MAX_BYTES)
+	if (size < 0 || size > SHMEM_MAX_BYTES)
 		return ERR_PTR(-EINVAL);
 
 	if (shmem_acct_size(flags, size))
@@ -2062,7 +2132,7 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
 	file->f_mapping = inode->i_mapping;
 	file->f_op = &shmem_file_operations;
 	file->f_mode = FMODE_WRITE | FMODE_READ;
-	return(file);
+	return file;
 
 close_file:
 	put_filp(file);
diff --git a/mm/slab.c b/mm/slab.c
index 34d9e5b5e..3b00d4499 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -91,10 +91,12 @@
 #include	<linux/cpu.h>
 #include	<linux/sysctl.h>
 #include	<linux/module.h>
+#include	<linux/rcupdate.h>
 
 #include	<asm/uaccess.h>
 #include	<asm/cacheflush.h>
 #include	<asm/tlbflush.h>
+#include	<asm/page.h>
 
 /*
  * DEBUG	- 1 for kmem_cache_create() to honour; SLAB_DEBUG_INITIAL,
@@ -139,11 +141,13 @@
 			 SLAB_POISON | SLAB_HWCACHE_ALIGN | \
 			 SLAB_NO_REAP | SLAB_CACHE_DMA | \
 			 SLAB_MUST_HWCACHE_ALIGN | SLAB_STORE_USER | \
-			 SLAB_RECLAIM_ACCOUNT | SLAB_PANIC)
+			 SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \
+			 SLAB_DESTROY_BY_RCU)
 #else
 # define CREATE_MASK	(SLAB_HWCACHE_ALIGN | SLAB_NO_REAP | \
 			 SLAB_CACHE_DMA | SLAB_MUST_HWCACHE_ALIGN | \
-			 SLAB_RECLAIM_ACCOUNT | SLAB_PANIC)
+			 SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \
+			 SLAB_DESTROY_BY_RCU)
 #endif
 
 /*
@@ -189,6 +193,28 @@ struct slab {
 	kmem_bufctl_t		free;
 };
 
+/*
+ * struct slab_rcu
+ *
+ * slab_destroy on a SLAB_DESTROY_BY_RCU cache uses this structure to
+ * arrange for kmem_freepages to be called via RCU.  This is useful if
+ * we need to approach a kernel structure obliquely, from its address
+ * obtained without the usual locking.  We can lock the structure to
+ * stabilize it and check it's still at the given address, only if we
+ * can be sure that the memory has not been meanwhile reused for some
+ * other kind of object (which our subsystem's lock might corrupt).
+ *
+ * rcu_read_lock before reading the address, then rcu_read_unlock after
+ * taking the spinlock within the structure expected at that address.
+ *
+ * We assume struct slab_rcu can overlay struct slab when destroying.
+ */
+struct slab_rcu {
+	struct rcu_head		head;
+	kmem_cache_t		*cachep;
+	void			*addr;
+};
+
 /*
  * struct array_cache
  *
@@ -478,8 +504,10 @@ static struct cache_names __initdata cache_names[] = {
 #undef CACHE
 };
 
-struct arraycache_init initarray_cache __initdata = { { 0, BOOT_CPUCACHE_ENTRIES, 1, 0} };
-struct arraycache_init initarray_generic __initdata = { { 0, BOOT_CPUCACHE_ENTRIES, 1, 0} };
+static struct arraycache_init initarray_cache __initdata =
+	{ { 0, BOOT_CPUCACHE_ENTRIES, 1, 0} };
+static struct arraycache_init initarray_generic __initdata =
+	{ { 0, BOOT_CPUCACHE_ENTRIES, 1, 0} };
 
 /* internal cache of cache description objs */
 static kmem_cache_t cache_cache = {
@@ -497,8 +525,7 @@ static kmem_cache_t cache_cache = {
 
 /* Guard access to the cache-chain. */
 static struct semaphore	cache_chain_sem;
-
-struct list_head cache_chain;
+static struct list_head cache_chain;
 
 /*
  * vm_enough_memory() looks at this to determine how many
@@ -513,17 +540,17 @@ EXPORT_SYMBOL(slab_reclaim_pages);
  * chicken and egg problem: delay the per-cpu array allocation
  * until the general caches are up.
  */
-enum {
+static enum {
 	NONE,
 	PARTIAL,
 	FULL
 } g_cpucache_up;
 
-static DEFINE_PER_CPU(struct timer_list, reap_timers);
+static DEFINE_PER_CPU(struct work_struct, reap_work);
 
-static void reap_timer_fnc(unsigned long data);
 static void free_block(kmem_cache_t* cachep, void** objpp, int len);
 static void enable_cpucache (kmem_cache_t *cachep);
+static void cache_reap (void *unused);
 
 static inline void ** ac_entry(struct array_cache *ac)
 {
@@ -535,6 +562,22 @@ static inline struct array_cache *ac_data(kmem_cache_t *cachep)
 	return cachep->array[smp_processor_id()];
 }
 
+static kmem_cache_t * kmem_find_general_cachep (size_t size, int gfpflags)
+{
+	struct cache_sizes *csizep = malloc_sizes;
+
+	/* This function could be moved to the header file, and
+	 * made inline so consumers can quickly determine what
+	 * cache pointer they require.
+	 */
+	for ( ; csizep->cs_size; csizep++) {
+		if (size > csizep->cs_size)
+			continue;
+		break;
+	}
+	return (gfpflags & GFP_DMA) ? csizep->cs_dmacachep : csizep->cs_cachep;
+}
+
 /* Cal the num objs, wastage, and bytes left over for a given slab size. */
 static void cache_estimate (unsigned long gfporder, size_t size, size_t align,
 		 int flags, size_t *left_over, unsigned int *num)
@@ -573,35 +616,26 @@ static void __slab_error(const char *function, kmem_cache_t *cachep, char *msg)
 }
 
 /*
- * Start the reap timer running on the target CPU.  We run at around 1 to 2Hz.
- * Add the CPU number into the expiry time to minimize the possibility of the
- * CPUs getting into lockstep and contending for the global cache chain lock.
+ * Initiate the reap timer running on the target CPU.  We run at around 1 to 2Hz
+ * via the workqueue/eventd.
+ * Add the CPU number into the expiration time to minimize the possibility of
+ * the CPUs getting into lockstep and contending for the global cache chain
+ * lock.
  */
 static void __devinit start_cpu_timer(int cpu)
 {
-	struct timer_list *rt = &per_cpu(reap_timers, cpu);
-
-	if (rt->function == NULL) {
-		init_timer(rt);
-		rt->expires = jiffies + HZ + 3*cpu;
-		rt->data = cpu;
-		rt->function = reap_timer_fnc;
-		add_timer_on(rt, cpu);
-	}
-}
+	struct work_struct *reap_work = &per_cpu(reap_work, cpu);
 
-#ifdef CONFIG_HOTPLUG_CPU
-static void stop_cpu_timer(int cpu)
-{
-	struct timer_list *rt = &per_cpu(reap_timers, cpu);
-
-	if (rt->function) {
-		del_timer_sync(rt);
-		WARN_ON(timer_pending(rt));
-		rt->function = NULL;
+	/*
+	 * When this gets called from do_initcalls via cpucache_init(),
+	 * init_workqueues() has already run, so keventd will be setup
+	 * at that time.
+	 */
+	if (keventd_up() && reap_work->func == NULL) {
+		INIT_WORK(reap_work, cache_reap, NULL);
+		schedule_delayed_work_on(cpu, reap_work, HZ + 3 * cpu);
 	}
 }
-#endif
 
 static struct array_cache *alloc_arraycache(int cpu, int entries, int batchcount)
 {
@@ -654,7 +688,6 @@ static int __devinit cpuup_callback(struct notifier_block *nfb,
 		break;
 #ifdef CONFIG_HOTPLUG_CPU
 	case CPU_DEAD:
-		stop_cpu_timer(cpu);
 		/* fall thru */
 	case CPU_UP_CANCELED:
 		down(&cache_chain_sem);
@@ -806,7 +839,7 @@ void __init kmem_cache_init(void)
 	 */
 }
 
-int __init cpucache_init(void)
+static int __init cpucache_init(void)
 {
 	int cpu;
 
@@ -883,6 +916,16 @@ static void kmem_freepages(kmem_cache_t *cachep, void *addr)
 		atomic_sub(1<<cachep->gfporder, &slab_reclaim_pages);
 }
 
+static void kmem_rcu_free(struct rcu_head *head)
+{
+	struct slab_rcu *slab_rcu = (struct slab_rcu *) head;
+	kmem_cache_t *cachep = slab_rcu->cachep;
+
+	kmem_freepages(cachep, slab_rcu->addr);
+	if (OFF_SLAB(cachep))
+		kmem_cache_free(cachep->slabp_cache, slab_rcu);
+}
+
 #if DEBUG
 
 #ifdef CONFIG_DEBUG_PAGEALLOC
@@ -938,9 +981,10 @@ static void dump_line(char *data, int offset, int limit)
 }
 #endif
 
+#if DEBUG
+
 static void print_objinfo(kmem_cache_t *cachep, void *objp, int lines)
 {
-#if DEBUG
 	int i, size;
 	char *realobj;
 
@@ -951,8 +995,10 @@ static void print_objinfo(kmem_cache_t *cachep, void *objp, int lines)
 	}
 
 	if (cachep->flags & SLAB_STORE_USER) {
-		printk(KERN_ERR "Last user: [<%p>]", *dbg_userword(cachep, objp));
-		print_symbol("(%s)", (unsigned long)*dbg_userword(cachep, objp));
+		printk(KERN_ERR "Last user: [<%p>]",
+				*dbg_userword(cachep, objp));
+		print_symbol("(%s)",
+				(unsigned long)*dbg_userword(cachep, objp));
 		printk("\n");
 	}
 	realobj = (char*)objp+obj_dbghead(cachep);
@@ -964,11 +1010,8 @@ static void print_objinfo(kmem_cache_t *cachep, void *objp, int lines)
 			limit = size-i;
 		dump_line(realobj, i, limit);
 	}
-#endif
 }
 
-#if DEBUG
-
 static void check_poison_obj(kmem_cache_t *cachep, void *objp)
 {
 	char *realobj;
@@ -1036,6 +1079,8 @@ static void check_poison_obj(kmem_cache_t *cachep, void *objp)
  */
 static void slab_destroy (kmem_cache_t *cachep, struct slab *slabp)
 {
+	void *addr = slabp->s_mem - slabp->colouroff;
+
 #if DEBUG
 	int i;
 	for (i = 0; i < cachep->num; i++) {
@@ -1071,10 +1116,19 @@ static void slab_destroy (kmem_cache_t *cachep, struct slab *slabp)
 		}
 	}
 #endif
-	
-	kmem_freepages(cachep, slabp->s_mem-slabp->colouroff);
-	if (OFF_SLAB(cachep))
-		kmem_cache_free(cachep->slabp_cache, slabp);
+
+	if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU)) {
+		struct slab_rcu *slab_rcu;
+
+		slab_rcu = (struct slab_rcu *) slabp;
+		slab_rcu->cachep = cachep;
+		slab_rcu->addr = addr;
+		call_rcu(&slab_rcu->head, kmem_rcu_free);
+	} else {
+		kmem_freepages(cachep, addr);
+		if (OFF_SLAB(cachep))
+			kmem_cache_free(cachep->slabp_cache, slabp);
+	}
 }
 
 /**
@@ -1149,9 +1203,15 @@ kmem_cache_create (const char *name, size_t size, size_t align,
 	 */
 	if ((size < 4096 || fls(size-1) == fls(size-1+3*BYTES_PER_WORD)))
 		flags |= SLAB_RED_ZONE|SLAB_STORE_USER;
-	flags |= SLAB_POISON;
+	if (!(flags & SLAB_DESTROY_BY_RCU))
+		flags |= SLAB_POISON;
 #endif
+	if (flags & SLAB_DESTROY_BY_RCU)
+		BUG_ON(flags & SLAB_POISON);
 #endif
+	if (flags & SLAB_DESTROY_BY_RCU)
+		BUG_ON(dtor);
+
 	/*
 	 * Always checks flags, a caller might be expecting debug
 	 * support which isn't available.
@@ -1563,6 +1623,9 @@ int kmem_cache_destroy (kmem_cache_t * cachep)
 		return 1;
 	}
 
+	if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU))
+		synchronize_kernel();
+
 	/* no cpu_online check required here since we clear the percpu
 	 * array on cpu offline and set this to NULL.
 	 */
@@ -2372,8 +2435,7 @@ EXPORT_SYMBOL(__kmalloc);
 /**
  * __alloc_percpu - allocate one copy of the object for every present
  * cpu in the system, zeroing them.
- * Objects should be dereferenced using per_cpu_ptr/get_cpu_ptr
- * macros only.
+ * Objects should be dereferenced using the per_cpu_ptr macro only.
  *
  * @size: how many bytes of memory are required.
  * @align: the alignment, which can't be greater than SMP_CACHE_BYTES.
@@ -2433,6 +2495,27 @@ void kmem_cache_free (kmem_cache_t *cachep, void *objp)
 
 EXPORT_SYMBOL(kmem_cache_free);
 
+/**
+ * kcalloc - allocate memory for an array. The memory is set to zero.
+ * @n: number of elements.
+ * @size: element size.
+ * @flags: the type of memory to allocate.
+ */
+void *kcalloc(size_t n, size_t size, int flags)
+{
+	void *ret = NULL;
+
+	if (n != 0 && size > INT_MAX / n)
+		return ret;
+
+	ret = kmalloc(n * size, flags);
+	if (ret)
+		memset(ret, 0, n * size);
+	return ret;
+}
+
+EXPORT_SYMBOL(kcalloc);
+
 /**
  * kfree - free previously allocated memory
  * @objp: pointer returned by kmalloc.
@@ -2487,24 +2570,6 @@ unsigned int kmem_cache_size(kmem_cache_t *cachep)
 
 EXPORT_SYMBOL(kmem_cache_size);
 
-kmem_cache_t * kmem_find_general_cachep (size_t size, int gfpflags)
-{
-	struct cache_sizes *csizep = malloc_sizes;
-
-	/* This function could be moved to the header file, and
-	 * made inline so consumers can quickly determine what
-	 * cache pointer they require.
-	 */
-	for ( ; csizep->cs_size; csizep++) {
-		if (size > csizep->cs_size)
-			continue;
-		break;
-	}
-	return (gfpflags & GFP_DMA) ? csizep->cs_dmacachep : csizep->cs_cachep;
-}
-
-EXPORT_SYMBOL(kmem_find_general_cachep);
-
 struct ccupdate_struct {
 	kmem_cache_t *cachep;
 	struct array_cache *new[NR_CPUS];
@@ -2630,27 +2695,6 @@ static void enable_cpucache (kmem_cache_t *cachep)
 					cachep->name, -err);
 }
 
-static void drain_array(kmem_cache_t *cachep, struct array_cache *ac)
-{
-	int tofree;
-
-	check_irq_off();
-	if (ac->touched) {
-		ac->touched = 0;
-	} else if (ac->avail) {
-		tofree = (ac->limit+4)/5;
-		if (tofree > ac->avail) {
-			tofree = (ac->avail+1)/2;
-		}
-		spin_lock(&cachep->spinlock);
-		free_block(cachep, ac_entry(ac), tofree);
-		spin_unlock(&cachep->spinlock);
-		ac->avail -= tofree;
-		memmove(&ac_entry(ac)[0], &ac_entry(ac)[tofree],
-					sizeof(void*)*ac->avail);
-	}
-}
-
 static void drain_array_locked(kmem_cache_t *cachep,
 				struct array_cache *ac, int force)
 {
@@ -2674,24 +2718,23 @@ static void drain_array_locked(kmem_cache_t *cachep,
 /**
  * cache_reap - Reclaim memory from caches.
  *
- * Called from a timer, every few seconds
+ * Called from workqueue/eventd every few seconds.
  * Purpose:
  * - clear the per-cpu caches for this CPU.
  * - return freeable pages to the main free memory pool.
  *
  * If we cannot acquire the cache chain semaphore then just give up - we'll
- * try again next timer interrupt.
+ * try again on the next iteration.
  */
-static void cache_reap (void)
+static void cache_reap(void *unused)
 {
 	struct list_head *walk;
 
-#if DEBUG
-	BUG_ON(!in_interrupt());
-	BUG_ON(in_irq());
-#endif
-	if (down_trylock(&cache_chain_sem))
+	if (down_trylock(&cache_chain_sem)) {
+		/* Give up. Setup the next iteration. */
+		schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC + smp_processor_id());
 		return;
+	}
 
 	list_for_each(walk, &cache_chain) {
 		kmem_cache_t *searchp;
@@ -2705,16 +2748,14 @@ static void cache_reap (void)
 			goto next;
 
 		check_irq_on();
-		local_irq_disable();
-		drain_array(searchp, ac_data(searchp));
 
-		if(time_after(searchp->lists.next_reap, jiffies))
-			goto next_irqon;
+		spin_lock_irq(&searchp->spinlock);
 
-		spin_lock(&searchp->spinlock);
-		if(time_after(searchp->lists.next_reap, jiffies)) {
+		drain_array_locked(searchp, ac_data(searchp), 0);
+
+		if(time_after(searchp->lists.next_reap, jiffies))
 			goto next_unlock;
-		}
+
 		searchp->lists.next_reap = jiffies + REAPTIMEOUT_LIST3;
 
 		if (searchp->lists.shared)
@@ -2747,30 +2788,14 @@ static void cache_reap (void)
 			spin_lock_irq(&searchp->spinlock);
 		} while(--tofree > 0);
 next_unlock:
-		spin_unlock(&searchp->spinlock);
-next_irqon:
-		local_irq_enable();
+		spin_unlock_irq(&searchp->spinlock);
 next:
 		;
 	}
 	check_irq_on();
 	up(&cache_chain_sem);
-}
-
-/*
- * This is a timer handler.  There is one per CPU.  It is called periodially
- * to shrink this CPU's caches.  Otherwise there could be memory tied up
- * for long periods (or for ever) due to load changes.
- */
-static void reap_timer_fnc(unsigned long cpu)
-{
-	struct timer_list *rt = &__get_cpu_var(reap_timers);
-
-	/* CPU hotplug can drag us off cpu: don't run on wrong CPU */
-	if (!cpu_is_offline(cpu)) {
-		cache_reap();
-		mod_timer(rt, jiffies + REAPTIMEOUT_CPUC + cpu);
-	}
+	/* Setup the next iteration */
+	schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC + smp_processor_id());
 }
 
 #ifdef CONFIG_PROC_FS
@@ -2997,72 +3022,3 @@ unsigned int ksize(const void *objp)
 
 	return size;
 }
-
-void ptrinfo(unsigned long addr)
-{
-	struct page *page;
-
-	printk("Dumping data about address %p.\n", (void*)addr);
-	if (!virt_addr_valid((void*)addr)) {
-		printk("virt addr invalid.\n");
-		return;
-	}
-#ifdef CONFIG_MMU
-	do {
-		pgd_t *pgd = pgd_offset_k(addr);
-		pmd_t *pmd;
-		if (pgd_none(*pgd)) {
-			printk("No pgd.\n");
-			break;
-		}
-		pmd = pmd_offset(pgd, addr);
-		if (pmd_none(*pmd)) {
-			printk("No pmd.\n");
-			break;
-		}
-#ifdef CONFIG_X86
-		if (pmd_large(*pmd)) {
-			printk("Large page.\n");
-			break;
-		}
-#endif
-		printk("normal page, pte_val 0x%llx\n",
-		  (unsigned long long)pte_val(*pte_offset_kernel(pmd, addr)));
-	} while(0);
-#endif
-
-	page = virt_to_page((void*)addr);
-	printk("struct page at %p, flags %08lx\n",
-			page, (unsigned long)page->flags);
-	if (PageSlab(page)) {
-		kmem_cache_t *c;
-		struct slab *s;
-		unsigned long flags;
-		int objnr;
-		void *objp;
-
-		c = GET_PAGE_CACHE(page);
-		printk("belongs to cache %s.\n",c->name);
-
-		spin_lock_irqsave(&c->spinlock, flags);
-		s = GET_PAGE_SLAB(page);
-		printk("slabp %p with %d inuse objects (from %d).\n",
-			s, s->inuse, c->num);
-		check_slabp(c,s);
-
-		objnr = (addr-(unsigned long)s->s_mem)/c->objsize;
-		objp = s->s_mem+c->objsize*objnr;
-		printk("points into object no %d, starting at %p, len %d.\n",
-			objnr, objp, c->objsize);
-		if (objnr >= c->num) {
-			printk("Bad obj number.\n");
-		} else {
-			kernel_map_pages(virt_to_page(objp),
-					c->objsize/PAGE_SIZE, 1);
-
-			print_objinfo(c, objp, 2);
-		}
-		spin_unlock_irqrestore(&c->spinlock, flags);
-
-	}
-}
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 571713576..6e81f2d52 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -171,7 +171,7 @@ int add_to_swap(struct page * page)
 		/*
 		 * Add it to the swap cache and mark it dirty
 		 */
-		err = __add_to_swap_cache(page, entry, GFP_ATOMIC);
+		err = __add_to_swap_cache(page, entry, GFP_ATOMIC|__GFP_NOWARN);
 
 		if (pf_flags & PF_MEMALLOC)
 			current->flags |= PF_MEMALLOC;
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 89bc19ef3..50c3a777c 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -523,14 +523,24 @@ static unsigned long unuse_pgd(struct vm_area_struct * vma, pgd_t *dir,
 }
 
 /* vma->vm_mm->page_table_lock is held */
-static unsigned long unuse_vma(struct vm_area_struct * vma, pgd_t *pgdir,
+static unsigned long unuse_vma(struct vm_area_struct * vma,
 	swp_entry_t entry, struct page *page)
 {
-	unsigned long start = vma->vm_start, end = vma->vm_end;
+	pgd_t *pgdir;
+	unsigned long start, end;
 	unsigned long foundaddr;
 
-	if (start >= end)
-		BUG();
+	if (page->mapping) {
+		start = page_address_in_vma(page, vma);
+		if (start == -EFAULT)
+			return 0;
+		else
+			end = start + PAGE_SIZE;
+	} else {
+		start = vma->vm_start;
+		end = vma->vm_end;
+	}
+	pgdir = pgd_offset(vma->vm_mm, start);
 	do {
 		foundaddr = unuse_pgd(vma, pgdir, start, end - start,
 						entry, page);
@@ -562,9 +572,8 @@ static int unuse_process(struct mm_struct * mm,
 	}
 	spin_lock(&mm->page_table_lock);
 	for (vma = mm->mmap; vma; vma = vma->vm_next) {
-		if (!is_vm_hugetlb_page(vma)) {
-			pgd_t * pgd = pgd_offset(mm, vma->vm_start);
-			foundaddr = unuse_vma(vma, pgd, entry, page);
+		if (vma->anon_vma) {
+			foundaddr = unuse_vma(vma, entry, page);
 			if (foundaddr)
 				break;
 		}
@@ -1602,8 +1611,8 @@ void si_swapinfo(struct sysinfo *val)
 	val->freeswap = nr_swap_pages + nr_to_be_unused;
 	val->totalswap = total_swap_pages + nr_to_be_unused;
 	swap_list_unlock();
-        if (vx_flags(VXF_VIRT_MEM, 0))
-                vx_vsi_swapinfo(val);
+	if (vx_flags(VXF_VIRT_MEM, 0))
+		vx_vsi_swapinfo(val);
 }
 
 /*
diff --git a/mm/truncate.c b/mm/truncate.c
index c9a30ae62..0ab3a157e 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -155,6 +155,7 @@ void truncate_inode_pages(struct address_space *mapping, loff_t lstart)
 
 	next = start;
 	for ( ; ; ) {
+		cond_resched();
 		if (!pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
 			if (next == start)
 				break;
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index a4c7c0a17..4093deae3 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -179,11 +179,26 @@ int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages)
 	return err;
 }
 
+#define IOREMAP_MAX_ORDER	(7 + PAGE_SHIFT)	/* 128 pages */
+
 struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
 				unsigned long start, unsigned long end)
 {
 	struct vm_struct **p, *tmp, *area;
-	unsigned long addr = start;
+	unsigned long align = 1;
+	unsigned long addr;
+
+	if (flags & VM_IOREMAP) {
+		int bit = fls(size);
+
+		if (bit > IOREMAP_MAX_ORDER)
+			bit = IOREMAP_MAX_ORDER;
+		else if (bit < PAGE_SHIFT)
+			bit = PAGE_SHIFT;
+
+		align = 1ul << bit;
+	}
+	addr = ALIGN(start, align);
 
 	area = kmalloc(sizeof(*area), GFP_KERNEL);
 	if (unlikely(!area))
@@ -200,13 +215,17 @@ struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
 
 	write_lock(&vmlist_lock);
 	for (p = &vmlist; (tmp = *p) != NULL ;p = &tmp->next) {
-		if ((unsigned long)tmp->addr < addr)
+		if ((unsigned long)tmp->addr < addr) {
+			if((unsigned long)tmp->addr + tmp->size >= addr)
+				addr = ALIGN(tmp->size + 
+					     (unsigned long)tmp->addr, align);
 			continue;
+		}
 		if ((size + addr) < addr)
 			goto out;
 		if (size + addr <= (unsigned long)tmp->addr)
 			goto found;
-		addr = tmp->size + (unsigned long)tmp->addr;
+		addr = ALIGN(tmp->size + (unsigned long)tmp->addr, align);
 		if (addr > end - size)
 			goto out;
 	}
@@ -228,6 +247,8 @@ found:
 out:
 	write_unlock(&vmlist_lock);
 	kfree(area);
+	if (printk_ratelimit())
+		printk(KERN_WARNING "allocation failed: out of vmalloc space - use vmalloc=<size> to increase size.\n");
 	return NULL;
 }
 
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 8e3b69342..156d701e6 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -32,6 +32,7 @@
 #include <linux/topology.h>
 #include <linux/cpu.h>
 #include <linux/notifier.h>
+#include <linux/rwsem.h>
 
 #include <asm/tlbflush.h>
 #include <asm/div64.h>
@@ -122,7 +123,7 @@ int vm_swappiness = 60;
 static long total_memory;
 
 static LIST_HEAD(shrinker_list);
-static DECLARE_MUTEX(shrinker_sem);
+static DECLARE_RWSEM(shrinker_rwsem);
 
 /*
  * Add a shrinker callback to be called from the vm
@@ -136,9 +137,9 @@ struct shrinker *set_shrinker(int seeks, shrinker_t theshrinker)
 	        shrinker->shrinker = theshrinker;
 	        shrinker->seeks = seeks;
 	        shrinker->nr = 0;
-	        down(&shrinker_sem);
+	        down_write(&shrinker_rwsem);
 	        list_add(&shrinker->list, &shrinker_list);
-	        up(&shrinker_sem);
+	        up_write(&shrinker_rwsem);
 	}
 	return shrinker;
 }
@@ -149,13 +150,13 @@ EXPORT_SYMBOL(set_shrinker);
  */
 void remove_shrinker(struct shrinker *shrinker)
 {
-	down(&shrinker_sem);
+	down_write(&shrinker_rwsem);
 	list_del(&shrinker->list);
-	up(&shrinker_sem);
+	up_write(&shrinker_rwsem);
 	kfree(shrinker);
 }
 EXPORT_SYMBOL(remove_shrinker);
- 
+
 #define SHRINK_BATCH 128
 /*
  * Call the shrink functions to age shrinkable caches
@@ -179,11 +180,15 @@ static int shrink_slab(unsigned long scanned, unsigned int gfp_mask,
 {
 	struct shrinker *shrinker;
 
-	if (down_trylock(&shrinker_sem))
+	if (scanned == 0)
+		scanned = SWAP_CLUSTER_MAX;
+
+	if (!down_read_trylock(&shrinker_rwsem))
 		return 0;
 
 	list_for_each_entry(shrinker, &shrinker_list, list) {
 		unsigned long long delta;
+		unsigned long total_scan;
 
 		delta = (4 * scanned) / shrinker->seeks;
 		delta *= (*shrinker->shrinker)(0, gfp_mask);
@@ -192,27 +197,29 @@ static int shrink_slab(unsigned long scanned, unsigned int gfp_mask,
 		if (shrinker->nr < 0)
 			shrinker->nr = LONG_MAX;	/* It wrapped! */
 
-		if (shrinker->nr <= SHRINK_BATCH)
-			continue;
-		while (shrinker->nr) {
-			long this_scan = shrinker->nr;
+		total_scan = shrinker->nr;
+		shrinker->nr = 0;
+
+		while (total_scan >= SHRINK_BATCH) {
+			long this_scan = SHRINK_BATCH;
 			int shrink_ret;
 
-			if (this_scan > 128)
-				this_scan = 128;
 			shrink_ret = (*shrinker->shrinker)(this_scan, gfp_mask);
-			mod_page_state(slabs_scanned, this_scan);
-			shrinker->nr -= this_scan;
 			if (shrink_ret == -1)
 				break;
+			mod_page_state(slabs_scanned, this_scan);
+			total_scan -= this_scan;
+
 			cond_resched();
 		}
+
+		shrinker->nr += total_scan;
 	}
-	up(&shrinker_sem);
+	up_read(&shrinker_rwsem);
 	return 0;
 }
 
-/* Must be called with page's rmap lock held. */
+/* Called without lock on whether page is mapped, so answer is unstable */
 static inline int page_mapping_inuse(struct page *page)
 {
 	struct address_space *mapping;
@@ -370,26 +377,19 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc)
 		if (page_mapped(page) || PageSwapCache(page))
 			sc->nr_scanned++;
 
-		page_map_lock(page);
-		referenced = page_referenced(page);
-		if (referenced && page_mapping_inuse(page)) {
-			/* In active use or really unfreeable.  Activate it. */
-			page_map_unlock(page);
+		referenced = page_referenced(page, 1);
+		/* In active use or really unfreeable?  Activate it. */
+		if (referenced && page_mapping_inuse(page))
 			goto activate_locked;
-		}
 
 #ifdef CONFIG_SWAP
 		/*
 		 * Anonymous process memory has backing store?
 		 * Try to allocate it some swap space here.
-		 *
-		 * XXX: implement swap clustering ?
 		 */
 		if (PageAnon(page) && !PageSwapCache(page)) {
-			page_map_unlock(page);
 			if (!add_to_swap(page))
 				goto activate_locked;
-			page_map_lock(page);
 		}
 #endif /* CONFIG_SWAP */
 
@@ -404,16 +404,13 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc)
 		if (page_mapped(page) && mapping) {
 			switch (try_to_unmap(page)) {
 			case SWAP_FAIL:
-				page_map_unlock(page);
 				goto activate_locked;
 			case SWAP_AGAIN:
-				page_map_unlock(page);
 				goto keep_locked;
 			case SWAP_SUCCESS:
 				; /* try to free the page below */
 			}
 		}
-		page_map_unlock(page);
 
 		if (PageDirty(page)) {
 			if (referenced)
@@ -716,25 +713,12 @@ refill_inactive_zone(struct zone *zone, struct scan_control *sc)
 		page = lru_to_page(&l_hold);
 		list_del(&page->lru);
 		if (page_mapped(page)) {
-			if (!reclaim_mapped) {
-				list_add(&page->lru, &l_active);
-				continue;
-			}
-			page_map_lock(page);
-			if (page_referenced(page)) {
-				page_map_unlock(page);
+			if (!reclaim_mapped ||
+			    (total_swap_pages == 0 && PageAnon(page)) ||
+			    page_referenced(page, 0)) {
 				list_add(&page->lru, &l_active);
 				continue;
 			}
-			page_map_unlock(page);
-		}
-		/*
-		 * FIXME: need to consider page_count(page) here if/when we
-		 * reap orphaned pages via the LRU (Daniel's locking stuff)
-		 */
-		if (total_swap_pages == 0 && PageAnon(page)) {
-			list_add(&page->lru, &l_active);
-			continue;
 		}
 		list_add(&page->lru, &l_inactive);
 	}
@@ -867,6 +851,9 @@ shrink_caches(struct zone **zones, struct scan_control *sc)
 	for (i = 0; zones[i] != NULL; i++) {
 		struct zone *zone = zones[i];
 
+		if (zone->present_pages == 0)
+			continue;
+
 		zone->temp_priority = sc->priority;
 		if (zone->prev_priority > sc->priority)
 			zone->prev_priority = sc->priority;
@@ -984,12 +971,16 @@ out:
 static int balance_pgdat(pg_data_t *pgdat, int nr_pages)
 {
 	int to_free = nr_pages;
+	int all_zones_ok;
 	int priority;
 	int i;
-	int total_scanned = 0, total_reclaimed = 0;
+	int total_scanned, total_reclaimed;
 	struct reclaim_state *reclaim_state = current->reclaim_state;
 	struct scan_control sc;
 
+loop_again:
+	total_scanned = 0;
+	total_reclaimed = 0;
 	sc.gfp_mask = GFP_KERNEL;
 	sc.may_writepage = 0;
 	sc.nr_mapped = read_page_state(nr_mapped);
@@ -1003,10 +994,11 @@ static int balance_pgdat(pg_data_t *pgdat, int nr_pages)
 	}
 
 	for (priority = DEF_PRIORITY; priority >= 0; priority--) {
-		int all_zones_ok = 1;
 		int end_zone = 0;	/* Inclusive.  0 = ZONE_DMA */
 		unsigned long lru_pages = 0;
 
+		all_zones_ok = 1;
+
 		if (nr_pages == 0) {
 			/*
 			 * Scan in the highmem->dma direction for the highest
@@ -1015,6 +1007,9 @@ static int balance_pgdat(pg_data_t *pgdat, int nr_pages)
 			for (i = pgdat->nr_zones - 1; i >= 0; i--) {
 				struct zone *zone = pgdat->node_zones + i;
 
+				if (zone->present_pages == 0)
+					continue;
+
 				if (zone->all_unreclaimable &&
 						priority != DEF_PRIORITY)
 					continue;
@@ -1047,6 +1042,9 @@ scan:
 		for (i = 0; i <= end_zone; i++) {
 			struct zone *zone = pgdat->node_zones + i;
 
+			if (zone->present_pages == 0)
+				continue;
+
 			if (zone->all_unreclaimable && priority != DEF_PRIORITY)
 				continue;
 
@@ -1067,7 +1065,8 @@ scan:
 			total_reclaimed += sc.nr_reclaimed;
 			if (zone->all_unreclaimable)
 				continue;
-			if (zone->pages_scanned > zone->present_pages * 2)
+			if (zone->pages_scanned >= (zone->nr_active +
+							zone->nr_inactive) * 4)
 				zone->all_unreclaimable = 1;
 			/*
 			 * If we've done a decent amount of scanning and
@@ -1088,6 +1087,15 @@ scan:
 		 */
 		if (total_scanned && priority < DEF_PRIORITY - 2)
 			blk_congestion_wait(WRITE, HZ/10);
+
+		/*
+		 * We do this so kswapd doesn't build up large priorities for
+		 * example when it is freeing in parallel with allocators. It
+		 * matches the direct reclaim path behaviour in terms of impact
+		 * on zone->*_priority.
+		 */
+		if (total_reclaimed >= SWAP_CLUSTER_MAX)
+			break;
 	}
 out:
 	for (i = 0; i < pgdat->nr_zones; i++) {
@@ -1095,6 +1103,11 @@ out:
 
 		zone->prev_priority = zone->temp_priority;
 	}
+	if (!all_zones_ok) {
+		cond_resched();
+		goto loop_again;
+	}
+
 	return total_reclaimed;
 }
 
@@ -1158,6 +1171,8 @@ static int kswapd(void *p)
  */
 void wakeup_kswapd(struct zone *zone)
 {
+	if (zone->present_pages == 0)
+		return;
 	if (zone->free_pages > zone->pages_low)
 		return;
 	if (!waitqueue_active(&zone->zone_pgdat->kswapd_wait))
@@ -1223,7 +1238,7 @@ static int __init kswapd_init(void)
 	swap_setup();
 	for_each_pgdat(pgdat)
 		pgdat->kswapd
-		= find_task_by_pid(kernel_thread(kswapd, pgdat, CLONE_KERNEL));
+		= find_task_by_real_pid(kernel_thread(kswapd, pgdat, CLONE_KERNEL));
 	total_memory = nr_free_pagecache_pages();
 	hotcpu_notifier(cpu_callback, 0);
 	return 0;
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index df9970410..3ee1dcd35 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -537,7 +537,7 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
 
 out_free_unregister:
 	unregister_netdev(new_dev);
-	goto out_put_dev;
+	goto out_unlock;
 
 out_free_newdev:
 	free_netdev(new_dev);
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 460aabc09..79b0262de 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -211,7 +211,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
 		 * This allows the VLAN to have a different MAC than the underlying
 		 * device, and still route correctly.
 		 */
-		if (memcmp(skb->mac.ethernet->h_dest, skb->dev->dev_addr, ETH_ALEN) == 0) {
+		if (memcmp(eth_hdr(skb)->h_dest, skb->dev->dev_addr, ETH_ALEN) == 0) {
 			/* It is for our (changed) MAC-address! */
 			skb->pkt_type = PACKET_HOST;
 		}
@@ -244,7 +244,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
 			/* TODO:  Add a more specific counter here. */
 			stats->rx_errors++;
 		}
-		rcu_read_lock();
+		rcu_read_unlock();
 		return 0;
 	}
 
@@ -772,7 +772,7 @@ int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	case SIOCGMIIREG:
 	case SIOCSMIIREG:
 		if (real_dev->do_ioctl && netif_device_present(real_dev)) 
-			err = real_dev->do_ioctl(dev, &ifrr, cmd);
+			err = real_dev->do_ioctl(real_dev, &ifrr, cmd);
 		break;
 
 	case SIOCETHTOOL:
diff --git a/net/Kconfig b/net/Kconfig
index 37ee31e7d..cae135013 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -324,6 +324,19 @@ config BRIDGE
 
 config VLAN_8021Q
 	tristate "802.1Q VLAN Support"
+	---help---
+	  Select this and you will be able to create 802.1Q VLAN interfaces
+	  on your ethernet interfaces.  802.1Q VLAN supports almost
+	  everything a regular ethernet interface does, including
+	  firewalling, bridging, and of course IP traffic.  You will need
+	  the 'vconfig' tool from the VLAN project in order to effectively
+	  use VLANs.  See the VLAN web page for more information:
+	  <http://www.candelatech.com/~greear/vlan.html>
+
+	  To compile this code as a module, choose M here: the module
+	  will be called 8021q.
+
+	  If unsure, say N.
 
 config DECNET
 	tristate "DECnet Support"
diff --git a/net/Makefile b/net/Makefile
index 61740b47a..a46436e0f 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -9,7 +9,8 @@ obj-y	:= nonet.o
 
 obj-$(CONFIG_NET)		:= socket.o core/
 
-obj-$(CONFIG_COMPAT)		+= compat.o
+tmp-$(CONFIG_COMPAT) 		:= compat.o
+obj-$(CONFIG_NET)		+= $(tmp-y)
 
 # LLC has to be linked before the files in net/802/
 obj-$(CONFIG_LLC)		+= llc/
diff --git a/net/appletalk/Makefile b/net/appletalk/Makefile
index cbe8a6a0b..d179728ad 100644
--- a/net/appletalk/Makefile
+++ b/net/appletalk/Makefile
@@ -4,5 +4,6 @@
 
 obj-$(CONFIG_ATALK) += appletalk.o
 
-appletalk-y			:= aarp.o ddp.o atalk_proc.o
+appletalk-y			:= aarp.o ddp.o
+appletalk-$(CONFIG_PROC_FS)	+= atalk_proc.o
 appletalk-$(CONFIG_SYSCTL)	+= sysctl_net_atalk.o
diff --git a/net/appletalk/atalk_proc.c b/net/appletalk/atalk_proc.c
index 1e00a5822..4d20501fa 100644
--- a/net/appletalk/atalk_proc.c
+++ b/net/appletalk/atalk_proc.c
@@ -15,8 +15,6 @@
 #include <net/sock.h>
 #include <linux/atalk.h>
 
-#ifdef CONFIG_PROC_FS
-extern struct file_operations atalk_seq_arp_fops;
 
 static __inline__ struct atalk_iface *atalk_get_interface_idx(loff_t pos)
 {
@@ -321,14 +319,3 @@ void __exit atalk_proc_exit(void)
 	remove_proc_entry("arp", atalk_proc_dir);
 	remove_proc_entry("atalk", proc_net);
 }
-
-#else /* CONFIG_PROC_FS */
-int __init atalk_proc_init(void)
-{
-	return 0;
-}
-
-void __exit atalk_proc_exit(void)
-{
-}
-#endif /* CONFIG_PROC_FS */
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 4185d7b8e..588cbe1ec 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -61,16 +61,6 @@
 #include <net/route.h>
 #include <linux/atalk.h>
 
-extern void aarp_cleanup_module(void);
-
-extern void aarp_probe_network(struct atalk_iface *atif);
-extern int  aarp_proxy_probe_network(struct atalk_iface *atif,
-				     struct atalk_addr *sa);
-extern void aarp_proxy_remove(struct net_device *dev, struct atalk_addr *sa);
-
-extern void atalk_register_sysctl(void);
-extern void atalk_unregister_sysctl(void);
-
 struct datalink_proto *ddp_dl, *aarp_dl;
 static struct proto_ops atalk_dgram_ops;
 
diff --git a/net/appletalk/sysctl_net_atalk.c b/net/appletalk/sysctl_net_atalk.c
index 25b33f670..af7f06043 100644
--- a/net/appletalk/sysctl_net_atalk.c
+++ b/net/appletalk/sysctl_net_atalk.c
@@ -7,13 +7,9 @@
  */
 
 #include <linux/config.h>
-
-#ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
-extern int sysctl_aarp_expiry_time;
-extern int sysctl_aarp_tick_time;
-extern int sysctl_aarp_retransmit_limit;
-extern int sysctl_aarp_resolve_time;
+#include <net/sock.h>
+#include <linux/atalk.h>
 
 static struct ctl_table atalk_table[] = {
 	{
@@ -85,13 +81,3 @@ void atalk_unregister_sysctl(void)
 {
 	unregister_sysctl_table(atalk_table_header);
 }
-
-#else /* CONFIG_PROC_FS */
-void atalk_register_sysctl(void)
-{
-}
-
-void atalk_unregister_sysctl(void)
-{
-}
-#endif /* CONFIG_PROC_FS */ 
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index 66778f43a..f7955e643 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -294,7 +294,7 @@ static inline unsigned short br_type_trans(struct sk_buff *skb,
 {
 	struct ethhdr *eth;
 	unsigned char *rawp;
-	eth = skb->mac.ethernet;
+	eth = eth_hdr(skb);
 
 	if (*eth->h_dest & 1) {
 		if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 4417df3fa..8db42d467 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -26,6 +26,8 @@
 #include <linux/bitops.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/rcupdate.h>
+#include <linux/jhash.h>
 #include <net/route.h> /* for struct rtable and routing */
 #include <net/icmp.h> /* icmp_send */
 #include <asm/param.h> /* for HZ */
@@ -47,8 +49,8 @@
 #endif
 
 
-struct net_device *clip_devs = NULL;
-struct atm_vcc *atmarpd = NULL;
+static struct net_device *clip_devs;
+static struct atm_vcc *atmarpd;
 static struct neigh_table clip_tbl;
 static struct timer_list idle_timer;
 static int start_timer = 1;
@@ -109,7 +111,8 @@ static void unlink_clip_vcc(struct clip_vcc *clip_vcc)
 				goto out;
 			entry->expires = jiffies-1;
 				/* force resolution or expiration */
-			error = neigh_update(entry->neigh,NULL,NUD_NONE,0,0);
+			error = neigh_update(entry->neigh, NULL, NUD_NONE,
+					     NEIGH_UPDATE_F_ADMIN);
 			if (error)
 				printk(KERN_CRIT "unlink_clip_vcc: "
 				    "neigh_update failed with %d\n",error);
@@ -121,64 +124,49 @@ out:
 	spin_unlock_bh(&entry->neigh->dev->xmit_lock);
 }
 
-
-static void idle_timer_check(unsigned long dummy)
+/* The neighbour entry n->lock is held. */
+static int neigh_check_cb(struct neighbour *n)
 {
-	int i;
+	struct atmarp_entry *entry = NEIGH2ENTRY(n);
+	struct clip_vcc *cv;
 
-	/*DPRINTK("idle_timer_check\n");*/
-	write_lock(&clip_tbl.lock);
-	for (i = 0; i <= NEIGH_HASHMASK; i++) {
-		struct neighbour **np;
-
-		for (np = &clip_tbl.hash_buckets[i]; *np;) {
-			struct neighbour *n = *np;
-			struct atmarp_entry *entry = NEIGH2ENTRY(n);
-			struct clip_vcc *clip_vcc;
-
-			write_lock(&n->lock);
-
-			for (clip_vcc = entry->vccs; clip_vcc;
-			    clip_vcc = clip_vcc->next)
-				if (clip_vcc->idle_timeout &&
-				    time_after(jiffies, clip_vcc->last_use+
-				    clip_vcc->idle_timeout)) {
-					DPRINTK("releasing vcc %p->%p of "
-					    "entry %p\n",clip_vcc,clip_vcc->vcc,
-					    entry);
-					vcc_release_async(clip_vcc->vcc,
-							  -ETIMEDOUT);
-				}
-			if (entry->vccs ||
-			    time_before(jiffies, entry->expires)) {
-				np = &n->next;
-				write_unlock(&n->lock);
-				continue;
-			}
-			if (atomic_read(&n->refcnt) > 1) {
-				struct sk_buff *skb;
-
-				DPRINTK("destruction postponed with ref %d\n",
-				    atomic_read(&n->refcnt));
-				while ((skb = skb_dequeue(&n->arp_queue)) !=
-				     NULL) 
-					dev_kfree_skb(skb);
-				np = &n->next;
-				write_unlock(&n->lock);
-				continue;
-			}
-			*np = n->next;
-			DPRINTK("expired neigh %p\n",n);
-			n->dead = 1;
-			write_unlock(&n->lock);
-			neigh_release(n);
+	for (cv = entry->vccs; cv; cv = cv->next) {
+		unsigned long exp = cv->last_use + cv->idle_timeout;
+
+		if (cv->idle_timeout && time_after(jiffies, exp)) {
+			DPRINTK("releasing vcc %p->%p of entry %p\n",
+				cv, cv->vcc, entry);
+			vcc_release_async(cv->vcc, -ETIMEDOUT);
 		}
 	}
+
+	if (entry->vccs || time_before(jiffies, entry->expires))
+		return 0;
+
+	if (atomic_read(&n->refcnt) > 1) {
+		struct sk_buff *skb;
+
+		DPRINTK("destruction postponed with ref %d\n",
+			atomic_read(&n->refcnt));
+
+		while ((skb = skb_dequeue(&n->arp_queue)) != NULL) 
+			dev_kfree_skb(skb);
+
+		return 0;
+	}
+
+	DPRINTK("expired neigh %p\n",n);
+	return 1;
+}
+
+static void idle_timer_check(unsigned long dummy)
+{
+	write_lock(&clip_tbl.lock);
+	__neigh_for_each_release(&clip_tbl, neigh_check_cb);
 	mod_timer(&idle_timer, jiffies+CLIP_CHECK_INTERVAL*HZ);
 	write_unlock(&clip_tbl.lock);
 }
 
-
 static int clip_arp_rcv(struct sk_buff *skb)
 {
 	struct atm_vcc *vcc;
@@ -311,13 +299,25 @@ static int clip_constructor(struct neighbour *neigh)
 {
 	struct atmarp_entry *entry = NEIGH2ENTRY(neigh);
 	struct net_device *dev = neigh->dev;
-	struct in_device *in_dev = dev->ip_ptr;
+	struct in_device *in_dev;
+	struct neigh_parms *parms;
 
 	DPRINTK("clip_constructor (neigh %p, entry %p)\n",neigh,entry);
-	if (!in_dev) return -EINVAL;
 	neigh->type = inet_addr_type(entry->ip);
 	if (neigh->type != RTN_UNICAST) return -EINVAL;
-	if (in_dev->arp_parms) neigh->parms = in_dev->arp_parms;
+
+	rcu_read_lock();
+	in_dev = rcu_dereference(__in_dev_get(dev));
+	if (!in_dev) {
+		rcu_read_unlock();
+		return -EINVAL;
+	}
+
+	parms = in_dev->arp_parms;
+	__neigh_parms_put(neigh->parms);
+	neigh->parms = neigh_parms_clone(parms);
+	rcu_read_unlock();
+
 	neigh->ops = &clip_neigh_ops;
 	neigh->output = neigh->nud_state & NUD_VALID ?
 	    neigh->ops->connected_output : neigh->ops->output;
@@ -329,15 +329,7 @@ static int clip_constructor(struct neighbour *neigh)
 
 static u32 clip_hash(const void *pkey, const struct net_device *dev)
 {
-	u32 hash_val;
-
-	hash_val = *(u32*)pkey;
-	hash_val ^= (hash_val>>16);
-	hash_val ^= hash_val>>8;
-	hash_val ^= hash_val>>3;
-	hash_val = (hash_val^dev->ifindex)&NEIGH_HASHMASK;
-
-	return hash_val;
+	return jhash_2words(*(u32 *)pkey, dev->ifindex, clip_tbl.hash_rnd);
 }
 
 static struct neigh_table clip_tbl = {
@@ -557,7 +549,8 @@ static int clip_setentry(struct atm_vcc *vcc,u32 ip)
 		}
 		link_vcc(clip_vcc,entry);
 	}
-	error = neigh_update(neigh,llc_oui,NUD_PERMANENT,1,0);
+	error = neigh_update(neigh, llc_oui, NUD_PERMANENT, 
+			     NEIGH_UPDATE_F_OVERRIDE|NEIGH_UPDATE_F_ADMIN);
 	neigh_release(neigh);
 	return error;
 }
@@ -818,120 +811,126 @@ static void svc_addr(struct seq_file *seq, struct sockaddr_atmsvc *addr)
 	}
 }
 
+/* This means the neighbour entry has no attached VCC objects. */
+#define SEQ_NO_VCC_TOKEN	((void *) 2)
+
 static void atmarp_info(struct seq_file *seq, struct net_device *dev,
 			struct atmarp_entry *entry, struct clip_vcc *clip_vcc)
 {
+	unsigned long exp;
 	char buf[17];
-	int svc, off;
+	int svc, llc, off;
+
+	svc = ((clip_vcc == SEQ_NO_VCC_TOKEN) ||
+	       (clip_vcc->vcc->sk->sk_family == AF_ATMSVC));
+
+	llc = ((clip_vcc == SEQ_NO_VCC_TOKEN) ||
+	       clip_vcc->encap);
+
+	if (clip_vcc == SEQ_NO_VCC_TOKEN)
+		exp = entry->neigh->used;
+	else
+		exp = clip_vcc->last_use;
 
-	svc = !clip_vcc || clip_vcc->vcc->sk->sk_family == AF_ATMSVC;
-	seq_printf(seq, "%-6s%-4s%-4s%5ld ", dev->name, svc ? "SVC" : "PVC",
-	    !clip_vcc || clip_vcc->encap ? "LLC" : "NULL",
-	    (jiffies-(clip_vcc ? clip_vcc->last_use : entry->neigh->used))/HZ);
+	exp = (jiffies - exp) / HZ;
 
-	off = scnprintf(buf, sizeof(buf) - 1, "%d.%d.%d.%d", NIPQUAD(entry->ip));
+	seq_printf(seq, "%-6s%-4s%-4s%5ld ",
+		   dev->name,
+		   svc ? "SVC" : "PVC",
+		   llc ? "LLC" : "NULL",
+		   exp);
+
+	off = scnprintf(buf, sizeof(buf) - 1, "%d.%d.%d.%d",
+			NIPQUAD(entry->ip));
 	while (off < 16)
 		buf[off++] = ' ';
 	buf[off] = '\0';
 	seq_printf(seq, "%s", buf);
 
-	if (!clip_vcc) {
+	if (clip_vcc == SEQ_NO_VCC_TOKEN) {
 		if (time_before(jiffies, entry->expires))
 			seq_printf(seq, "(resolving)\n");
 		else
 			seq_printf(seq, "(expired, ref %d)\n",
 				   atomic_read(&entry->neigh->refcnt));
 	} else if (!svc) {
-		seq_printf(seq, "%d.%d.%d\n", clip_vcc->vcc->dev->number,
-			   clip_vcc->vcc->vpi, clip_vcc->vcc->vci);
+		seq_printf(seq, "%d.%d.%d\n",
+			   clip_vcc->vcc->dev->number,
+			   clip_vcc->vcc->vpi,
+			   clip_vcc->vcc->vci);
 	} else {
 		svc_addr(seq, &clip_vcc->vcc->remote);
 		seq_putc(seq, '\n');
 	}
 }
 
-struct arp_state {
-	int bucket;
-  	struct neighbour *n;
+struct clip_seq_state {
+	/* This member must be first. */
+	struct neigh_seq_state ns;
+
+	/* Local to clip specific iteration. */
 	struct clip_vcc *vcc;
 };
-  
-static void *arp_vcc_walk(struct arp_state *state,
-			  struct atmarp_entry *e, loff_t *l)
-{
-	struct clip_vcc *vcc = state->vcc;
 
-	if (!vcc)
-		vcc = e->vccs;
-	if (vcc == (void *)1) {
-		vcc = e->vccs;
-		--*l;
-  	}
-	for (; vcc; vcc = vcc->next) {
-		if (--*l < 0)
-			break;
-	}
-	state->vcc = vcc;
-	return (*l < 0) ? state : NULL;
-}
-  
-static void *arp_get_idx(struct arp_state *state, loff_t l)
+static struct clip_vcc *clip_seq_next_vcc(struct atmarp_entry *e,
+					  struct clip_vcc *curr)
 {
-	void *v = NULL;
-
-	for (; state->bucket <= NEIGH_HASHMASK; state->bucket++) {
-		for (; state->n; state->n = state->n->next) {
-			v = arp_vcc_walk(state, NEIGH2ENTRY(state->n), &l);
-			if (v)
-				goto done;
-  		}
-		state->n = clip_tbl.hash_buckets[state->bucket + 1];
+	if (!curr) {
+		curr = e->vccs;
+		if (!curr)
+			return SEQ_NO_VCC_TOKEN;
+		return curr;
 	}
-done:
-	return v;
+	if (curr == SEQ_NO_VCC_TOKEN)
+		return NULL;
+
+	curr = curr->next;
+
+	return curr;
 }
 
-static void *arp_seq_start(struct seq_file *seq, loff_t *pos)
+static void *clip_seq_vcc_walk(struct clip_seq_state *state,
+			       struct atmarp_entry *e, loff_t *pos)
 {
-	struct arp_state *state = seq->private;
-	void *ret = (void *)1;
-
-	read_lock_bh(&clip_tbl.lock);
-	state->bucket = 0;
-	state->n = clip_tbl.hash_buckets[0];
-	state->vcc = (void *)1;
-	if (*pos)
-		ret = arp_get_idx(state, *pos);
-	return ret;
-}
+	struct clip_vcc *vcc = state->vcc;
 
-static void arp_seq_stop(struct seq_file *seq, void *v)
+	vcc = clip_seq_next_vcc(e, vcc);
+	if (vcc && pos != NULL) {
+		while (*pos) {
+			vcc = clip_seq_next_vcc(e, vcc);
+			if (!vcc)
+				break;
+			--(*pos);
+		}
+	}
+	state->vcc = vcc;
+
+	return vcc;
+}
+  
+static void *clip_seq_sub_iter(struct neigh_seq_state *_state,
+			       struct neighbour *n, loff_t *pos)
 {
-	struct arp_state *state = seq->private;
+	struct clip_seq_state *state = (struct clip_seq_state *) _state;
 
-	if (state->bucket != -1)
-		read_unlock_bh(&clip_tbl.lock);
+	return clip_seq_vcc_walk(state, NEIGH2ENTRY(n), pos);
 }
 
-static void *arp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+static void *clip_seq_start(struct seq_file *seq, loff_t *pos)
 {
-	struct arp_state *state = seq->private;
-
-	v = arp_get_idx(state, 1);
-	*pos += !!PTR_ERR(v);
-	return v;
+	return neigh_seq_start(seq, pos, &clip_tbl, NEIGH_SEQ_NEIGH_ONLY);
 }
 
-static int arp_seq_show(struct seq_file *seq, void *v)
+static int clip_seq_show(struct seq_file *seq, void *v)
 {
 	static char atm_arp_banner[] = 
 		"IPitf TypeEncp Idle IP address      ATM address\n";
 
-	if (v == (void *)1)
+	if (v == SEQ_START_TOKEN) {
 		seq_puts(seq, atm_arp_banner);
-	else {
-		struct arp_state *state = seq->private;
-		struct neighbour *n = state->n;	
+	} else {
+		struct clip_seq_state *state = seq->private;
+		struct neighbour *n = v;
 		struct clip_vcc *vcc = state->vcc;
 
 		atmarp_info(seq, n->dev, NEIGH2ENTRY(n), vcc);
@@ -940,15 +939,15 @@ static int arp_seq_show(struct seq_file *seq, void *v)
 }
 
 static struct seq_operations arp_seq_ops = {
-	.start	= arp_seq_start,
-	.next	= arp_seq_next,
-	.stop	= arp_seq_stop,
-	.show	= arp_seq_show,
+	.start	= clip_seq_start,
+	.next	= neigh_seq_next,
+	.stop	= neigh_seq_stop,
+	.show	= clip_seq_show,
 };
 
 static int arp_seq_open(struct inode *inode, struct file *file)
 {
-	struct arp_state *state;
+	struct clip_seq_state *state;
 	struct seq_file *seq;
 	int rc = -EAGAIN;
 
@@ -957,6 +956,8 @@ static int arp_seq_open(struct inode *inode, struct file *file)
 		rc = -ENOMEM;
 		goto out_kfree;
 	}
+	memset(state, 0, sizeof(*state));
+	state->ns.neigh_sub_iter = clip_seq_sub_iter;
 
 	rc = seq_open(file, &arp_seq_ops);
 	if (rc)
@@ -972,35 +973,18 @@ out_kfree:
 	goto out;
 }
 
-static int arp_seq_release(struct inode *inode, struct file *file)
-{
-	return seq_release_private(inode, file);
-}
-
 static 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
 
 static int __init atm_clip_init(void)
 {
-	/* we should use neigh_table_init() */
-	clip_tbl.lock = RW_LOCK_UNLOCKED;
-	clip_tbl.kmem_cachep = kmem_cache_create(clip_tbl.id,
-	    clip_tbl.entry_size, 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
-
-	if (!clip_tbl.kmem_cachep)
-		return -ENOMEM;
-
-	/* so neigh_ifdown() doesn't complain */
-	clip_tbl.proxy_timer.data = 0;
-	clip_tbl.proxy_timer.function = NULL;
-	init_timer(&clip_tbl.proxy_timer);
-	skb_queue_head_init(&clip_tbl.proxy_queue);
+	neigh_table_init(&clip_tbl);
 
 	clip_tbl_hook = &clip_tbl;
 	register_atm_ioctl(&clip_ioctl_ops);
@@ -1026,7 +1010,18 @@ static void __exit atm_clip_exit(void)
 
 	deregister_atm_ioctl(&clip_ioctl_ops);
 
+	/* First, stop the idle timer, so it stops banging
+	 * on the table.
+	 */
+	if (start_timer == 0)
+		del_timer(&idle_timer);
+
+	/* Next, purge the table, so that the device
+	 * unregister loop below does not hang due to
+	 * device references remaining in the table.
+	 */
 	neigh_ifdown(&clip_tbl, NULL);
+
 	dev = clip_devs;
 	while (dev) {
 		next = PRIV(dev)->next;
@@ -1034,9 +1029,9 @@ static void __exit atm_clip_exit(void)
 		free_netdev(dev);
 		dev = next;
 	}
-	if (start_timer == 0) del_timer(&idle_timer);
 
-	kmem_cache_destroy(clip_tbl.kmem_cachep);
+	/* Now it is safe to fully shutdown whole table. */
+	neigh_table_clear(&clip_tbl);
 
 	clip_tbl_hook = NULL;
 }
diff --git a/net/atm/common.h b/net/atm/common.h
index d4cb95c57..e49ed41c0 100644
--- a/net/atm/common.h
+++ b/net/atm/common.h
@@ -24,11 +24,6 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
 int vcc_getsockopt(struct socket *sock, int level, int optname,
 		   char __user *optval, int __user *optlen);
 
-void atm_shutdown_dev(struct atm_dev *dev);
-
-void pppoatm_ioctl_set(int (*hook)(struct atm_vcc *, unsigned int, unsigned long));
-void br2684_ioctl_set(int (*hook)(struct atm_vcc *, unsigned int, unsigned long));
-
 int atmpvc_init(void);
 void atmpvc_exit(void);
 int atmsvc_init(void);
@@ -50,12 +45,6 @@ static inline void atm_proc_exit(void)
 #endif /* CONFIG_PROC_FS */
 
 /* SVC */
-
-void svc_callback(struct atm_vcc *vcc);
 int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos);
 
-/* p2mp */
-
-int create_leaf(struct socket *leaf,struct socket *session);
-
 #endif
diff --git a/net/atm/ipcommon.h b/net/atm/ipcommon.h
index bc1675eca..d72165f60 100644
--- a/net/atm/ipcommon.h
+++ b/net/atm/ipcommon.h
@@ -12,9 +12,6 @@
 #include <linux/netdevice.h>
 #include <linux/atmdev.h>
 
-
-extern struct net_device *clip_devs;
-
 /*
  * Appends all skbs from "from" to "to". The operation is atomic with respect
  * to all other skb operations on "from" or "to".
diff --git a/net/atm/lec.h b/net/atm/lec.h
index c544f926e..9c1902109 100644
--- a/net/atm/lec.h
+++ b/net/atm/lec.h
@@ -151,7 +151,6 @@ int lecd_attach(struct atm_vcc *vcc, int arg);
 int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg);
 int lec_mcast_attach(struct atm_vcc *vcc, int arg);
 struct net_device *get_dev_lec(int itf);
-int make_lec(struct atm_vcc *vcc);
 int send_to_lecd(struct lec_priv *priv,
                  atmlec_msg_type type, unsigned char *mac_addr,
                  unsigned char *atm_addr, struct sk_buff *data);
diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c
index 4f1849f9a..60834b5a1 100644
--- a/net/atm/mpoa_proc.c
+++ b/net/atm/mpoa_proc.c
@@ -121,7 +121,7 @@ static void mpc_stop(struct seq_file *m, void *v)
 /*
  * READING function - called when the /proc/atm/mpoa file is read from.
  */
-static ssize_t mpc_show(struct seq_file *m, void *v)
+static int mpc_show(struct seq_file *m, void *v)
 {
 	struct mpoa_client *mpc = v;
 	unsigned char *temp;
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 47fbd98e0..2ff9b6f5c 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -1176,13 +1176,16 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr,
 		/* check if we can remove this feature. It is broken. */
 		printk(KERN_WARNING "ax25_connect(): %s uses autobind, please contact jreuter@yaina.de\n",
 			current->comm);
-		if ((err = ax25_rt_autobind(ax25, &fsa->fsa_ax25.sax25_call)) < 0)
+		if ((err = ax25_rt_autobind(ax25, &fsa->fsa_ax25.sax25_call)) < 0) {
+			kfree(digi);
 			goto out;
+		}
 
 		ax25_fillin_cb(ax25, ax25->ax25_dev);
 		ax25_cb_add(ax25);
 	} else {
 		if (ax25->ax25_dev == NULL) {
+			kfree(digi);
 			err = -EHOSTUNREACH;
 			goto out;
 		}
@@ -1191,8 +1194,7 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr,
 	if (sk->sk_type == SOCK_SEQPACKET &&
 	    (ax25t=ax25_find_cb(&ax25->source_addr, &fsa->fsa_ax25.sax25_call, digi,
 		    	 ax25->ax25_dev->dev))) {
-		if (digi != NULL)
-			kfree(digi);
+		kfree(digi);
 		err = -EADDRINUSE;		/* Already such a connection */
 		ax25_cb_put(ax25t);
 		goto out;
@@ -1336,7 +1338,6 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags)
 	remove_wait_queue(sk->sk_sleep, &wait);
 
 	newsk		 = skb->sk;
-	newsk->sk_pair	 = NULL;
 	newsk->sk_socket = newsock;
 	newsk->sk_sleep	 = &newsock->wait;
 
diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c
index e7f9e6793..01a2c865a 100644
--- a/net/ax25/ax25_in.c
+++ b/net/ax25/ax25_in.c
@@ -372,7 +372,6 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
 		skb_queue_head(&sk->sk_receive_queue, skb);
 
 		make->sk_state = TCP_ESTABLISHED;
-		make->sk_pair  = sk;
 
 		sk->sk_ack_backlog++;
 		bh_unlock_sock(sk);
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index a87cc64e9..682bf20af 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -384,7 +384,7 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
 	
 	s->stats.rx_packets++;
 	nskb->dev       = dev;
-	nskb->ip_summed = CHECKSUM_UNNECESSARY;
+	nskb->ip_summed = CHECKSUM_NONE;
 	nskb->protocol  = eth_type_trans(nskb, dev);
 	netif_rx_ni(nskb);
 	return 0;
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index cc323a7f0..1da6a95e2 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -57,7 +57,7 @@
 #define BT_DBG(D...)
 #endif
 
-#define VERSION "2.3"
+#define VERSION "2.4"
 
 static struct proto_ops l2cap_sock_ops;
 
@@ -1453,7 +1453,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
 	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
 
 	if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, scid)))
-		return -ENOENT;
+		return 0;
 
 	switch (result) {
 	case L2CAP_CR_SUCCESS:
@@ -1527,7 +1527,6 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
 	u16 scid, flags, result;
 	struct sock *sk;
-	int err = 0;
 
 	scid   = __le16_to_cpu(rsp->scid);
 	flags  = __le16_to_cpu(rsp->flags);
@@ -1536,7 +1535,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x", scid, flags, result);
 
 	if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, scid)))
-		return -ENOENT;
+		return 0;
 
 	switch (result) {
 	case L2CAP_CONF_SUCCESS:
@@ -1581,7 +1580,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 
 done:
 	bh_unlock_sock(sk);
-	return err;
+	return 0;
 }
 
 static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
@@ -1625,6 +1624,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
 
 	if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, scid)))
 		return 0;
+
 	l2cap_chan_del(sk, 0);
 	bh_unlock_sock(sk);
 
@@ -1632,7 +1632,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
 	return 0;
 }
 
-static inline int l2cap_info_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
 {
 	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
 	struct l2cap_info_rsp rsp;
@@ -1645,10 +1645,11 @@ static inline int l2cap_info_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *
 	rsp.type   = __cpu_to_le16(type);
 	rsp.result = __cpu_to_le16(L2CAP_IR_NOTSUPP);
 	l2cap_send_rsp(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp), &rsp);
+
 	return 0;
 }
 
-static inline int l2cap_info_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
 {
 	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
 	u16 type, result;
@@ -1721,11 +1722,11 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *sk
 			break;
 
 		case L2CAP_INFO_REQ:
-			err = l2cap_info_req(conn, &cmd, data);
+			err = l2cap_information_req(conn, &cmd, data);
 			break;
 
 		case L2CAP_INFO_RSP:
-			err = l2cap_info_rsp(conn, &cmd, data);
+			err = l2cap_information_rsp(conn, &cmd, data);
 			break;
 
 		default:
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index fdf8f9eb6..943d5ddc5 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -45,27 +45,15 @@ static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
 			br_pass_frame_up_finish);
 }
 
+/* note: already called with rcu_read_lock (preempt_disabled) */
 int br_handle_frame_finish(struct sk_buff *skb)
 {
-	struct net_bridge *br;
-	unsigned char *dest;
+	const unsigned char *dest = eth_hdr(skb)->h_dest;
+	struct net_bridge_port *p = skb->dev->br_port;
+	struct net_bridge *br = p->br;
 	struct net_bridge_fdb_entry *dst;
-	struct net_bridge_port *p;
-	int passedup;
+	int passedup = 0;
 
-	dest = skb->mac.ethernet->h_dest;
-
-	rcu_read_lock();
-	p = skb->dev->br_port;
-	smp_read_barrier_depends();
-
-	if (p == NULL || p->state == BR_STATE_DISABLED) {
-		kfree_skb(skb);
-		goto out;
-	}
-
-	br = p->br;
-	passedup = 0;
 	if (br->dev->flags & IFF_PROMISC) {
 		struct sk_buff *skb2;
 
@@ -100,28 +88,29 @@ int br_handle_frame_finish(struct sk_buff *skb)
 	br_flood_forward(br, skb, 0);
 
 out:
-	rcu_read_unlock();
 	return 0;
 }
 
-int br_handle_frame(struct sk_buff *skb)
+/*
+ * Called via br_handle_frame_hook.
+ * Return 0 if *pskb should be processed furthur
+ *	  1 if *pskb is handled
+ * note: already called with rcu_read_lock (preempt_disabled) 
+ */
+int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb)
 {
-	unsigned char *dest;
-	struct net_bridge_port *p;
+	struct sk_buff *skb = *pskb;
+	const unsigned char *dest = eth_hdr(skb)->h_dest;
 
-	dest = skb->mac.ethernet->h_dest;
-
-	rcu_read_lock();
-	p = skb->dev->br_port;
-	if (p == NULL || p->state == BR_STATE_DISABLED)
+	if (p->state == BR_STATE_DISABLED)
 		goto err;
 
-	if (skb->mac.ethernet->h_source[0] & 1)
+	if (eth_hdr(skb)->h_source[0] & 1)
 		goto err;
 
 	if (p->state == BR_STATE_LEARNING ||
 	    p->state == BR_STATE_FORWARDING)
-		br_fdb_insert(p->br, p, skb->mac.ethernet->h_source, 0);
+		br_fdb_insert(p->br, p, eth_hdr(skb)->h_source, 0);
 
 	if (p->br->stp_enabled &&
 	    !memcmp(dest, bridge_ula, 5) &&
@@ -129,15 +118,16 @@ int br_handle_frame(struct sk_buff *skb)
 		if (!dest[5]) {
 			NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, 
 				NULL, br_stp_handle_bpdu);
-			rcu_read_unlock();
-			return 0;
+			return 1;
 		}
 	}
 
 	else if (p->state == BR_STATE_FORWARDING) {
-		if (br_should_route_hook && br_should_route_hook(&skb)) {
-			rcu_read_unlock();
-			return -1;
+		if (br_should_route_hook) {
+			if (br_should_route_hook(pskb)) 
+				return 0;
+			skb = *pskb;
+			dest = eth_hdr(skb)->h_dest;
 		}
 
 		if (!memcmp(p->br->dev->dev_addr, dest, ETH_ALEN))
@@ -145,12 +135,10 @@ int br_handle_frame(struct sk_buff *skb)
 
 		NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
 			br_handle_frame_finish);
-		rcu_read_unlock();
-		return 0;
+		return 1;
 	}
 
 err:
-	rcu_read_unlock();
 	kfree_skb(skb);
-	return 0;
+	return 1;
 }
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 404dda32b..50e4df355 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -11,6 +11,7 @@
  *	Jun 19 2003: let arptables see bridged ARP traffic (bdschuym)
  *	Oct 06 2003: filter encapsulated IP/ARP VLAN traffic on untagged bridge
  *	             (bdschuym)
+ *	Sep 01 2004: add IPv6 filtering (bdschuym)
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -29,9 +30,11 @@
 #include <linux/if_vlan.h>
 #include <linux/netfilter_bridge.h>
 #include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv6.h>
 #include <linux/netfilter_arp.h>
 #include <linux/in_route.h>
 #include <net/ip.h>
+#include <net/ipv6.h>
 #include <asm/uaccess.h>
 #include <asm/checksum.h>
 #include "br_private.h"
@@ -39,7 +42,6 @@
 #include <linux/sysctl.h>
 #endif
 
-
 #define skb_origaddr(skb)	 (((struct bridge_skb_cb *) \
 				 (skb->nf_bridge->data))->daddr.ipv4)
 #define store_orig_dstaddr(skb)	 (skb_origaddr(skb) = (skb)->nh.iph->daddr)
@@ -51,6 +53,7 @@
 #ifdef CONFIG_SYSCTL
 static struct ctl_table_header *brnf_sysctl_header;
 static int brnf_call_iptables = 1;
+static int brnf_call_ip6tables = 1;
 static int brnf_call_arptables = 1;
 static int brnf_filter_vlan_tagged = 1;
 #else
@@ -60,6 +63,9 @@ static int brnf_filter_vlan_tagged = 1;
 #define IS_VLAN_IP (skb->protocol == __constant_htons(ETH_P_8021Q) &&    \
 	hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_IP) &&  \
 	brnf_filter_vlan_tagged)
+#define IS_VLAN_IPV6 (skb->protocol == __constant_htons(ETH_P_8021Q) &&    \
+	hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_IPV6) &&  \
+	brnf_filter_vlan_tagged)
 #define IS_VLAN_ARP (skb->protocol == __constant_htons(ETH_P_8021Q) &&   \
 	hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_ARP) && \
 	brnf_filter_vlan_tagged)
@@ -71,8 +77,7 @@ static int brnf_filter_vlan_tagged = 1;
  * Currently, we fill in the PMTU entry because netfilter
  * refragmentation needs it, and the rt_flags entry because
  * ipt_REJECT needs it.  Future netfilter modules might
- * require us to fill additional fields.
- */
+ * require us to fill additional fields. */
 static struct net_device __fake_net_device = {
 	.hard_header_len	= ETH_HLEN
 };
@@ -91,6 +96,36 @@ static struct rtable __fake_rtable = {
 
 
 /* PF_BRIDGE/PRE_ROUTING *********************************************/
+/* Undo the changes made for ip6tables PREROUTING and continue the
+ * bridge PRE_ROUTING hook. */
+static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb)
+{
+	struct nf_bridge_info *nf_bridge = skb->nf_bridge;
+
+#ifdef CONFIG_NETFILTER_DEBUG
+	skb->nf_debug ^= (1 << NF_BR_PRE_ROUTING);
+#endif
+
+	if (nf_bridge->mask & BRNF_PKT_TYPE) {
+		skb->pkt_type = PACKET_OTHERHOST;
+		nf_bridge->mask ^= BRNF_PKT_TYPE;
+	}
+	nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;
+
+	skb->dst = (struct dst_entry *)&__fake_rtable;
+	dst_hold(skb->dst);
+
+	skb->dev = nf_bridge->physindev;
+	if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
+		skb_push(skb, VLAN_HLEN);
+		skb->nh.raw -= VLAN_HLEN;
+	}
+	NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
+		       br_handle_frame_finish, 1);
+
+	return 0;
+}
+
 static void __br_dnat_complain(void)
 {
 	static unsigned long last_complaint;
@@ -102,7 +137,6 @@ static void __br_dnat_complain(void)
 	}
 }
 
-
 /* This requires some explaining. If DNAT has taken place,
  * we will need to fix up the destination Ethernet address,
  * and this is a tricky process.
@@ -145,9 +179,7 @@ static void __br_dnat_complain(void)
  *
  * --Lennert, 20020411
  * --Bart, 20020416 (updated)
- * --Bart, 20021007 (updated)
- */
-
+ * --Bart, 20021007 (updated) */
 static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
 {
 #ifdef CONFIG_NETFILTER_DEBUG
@@ -195,8 +227,7 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
 
 			if (!ip_route_output_key(&rt, &fl)) {
 				/* Bridged-and-DNAT'ed traffic doesn't
-				 * require ip_forwarding.
-				 */
+				 * require ip_forwarding. */
 				if (((struct dst_entry *)rt)->dev == dev) {
 					skb->dst = (struct dst_entry *)rt;
 					goto bridged_dnat;
@@ -210,8 +241,7 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
 			if (skb->dst->dev == dev) {
 bridged_dnat:
 				/* Tell br_nf_local_out this is a
-				 * bridged frame
-				 */
+				 * bridged frame */
 				nf_bridge->mask |= BRNF_BRIDGED_DNAT;
 				skb->dev = nf_bridge->physindev;
 				if (skb->protocol ==
@@ -225,7 +255,7 @@ bridged_dnat:
 					       1);
 				return 0;
 			}
-			memcpy(skb->mac.ethernet->h_dest, dev->dev_addr,
+			memcpy(eth_hdr(skb)->h_dest, dev->dev_addr,
 			       ETH_ALEN);
 			skb->pkt_type = PACKET_HOST;
 		}
@@ -245,12 +275,135 @@ bridged_dnat:
 	return 0;
 }
 
-/* Replicate the checks that IPv4 does on packet reception.
+/* Some common code for IPv4/IPv6 */
+static void setup_pre_routing(struct sk_buff *skb)
+{
+	struct nf_bridge_info *nf_bridge = skb->nf_bridge;
+
+	if (skb->pkt_type == PACKET_OTHERHOST) {
+		skb->pkt_type = PACKET_HOST;
+		nf_bridge->mask |= BRNF_PKT_TYPE;
+	}
+
+	nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING;
+	nf_bridge->physindev = skb->dev;
+	skb->dev = bridge_parent(skb->dev);
+}
+
+/* We only check the length. A bridge shouldn't do any hop-by-hop stuff anyway */
+static int check_hbh_len(struct sk_buff *skb)
+{
+	unsigned char *raw = (u8*)(skb->nh.ipv6h+1);
+	u32 pkt_len;
+	int off = raw - skb->nh.raw;
+	int len = (raw[1]+1)<<3;
+
+	if ((raw + len) - skb->data > skb_headlen(skb))
+		goto bad;
+
+	off += 2;
+	len -= 2;
+
+	while (len > 0) {
+		int optlen = raw[off+1]+2;
+
+		switch (skb->nh.raw[off]) {
+		case IPV6_TLV_PAD0:
+			optlen = 1;
+			break;
+
+		case IPV6_TLV_PADN:
+			break;
+
+		case IPV6_TLV_JUMBO:
+			if (skb->nh.raw[off+1] != 4 || (off&3) != 2)
+				goto bad;
+
+			pkt_len = ntohl(*(u32*)(skb->nh.raw+off+2));
+
+			if (pkt_len > skb->len - sizeof(struct ipv6hdr))
+				goto bad;
+			if (pkt_len + sizeof(struct ipv6hdr) < skb->len) {
+				if (__pskb_trim(skb,
+				    pkt_len + sizeof(struct ipv6hdr)))
+					goto bad;
+				if (skb->ip_summed == CHECKSUM_HW)
+					skb->ip_summed = CHECKSUM_NONE;
+			}
+			break;
+		default:
+			if (optlen > len)
+				goto bad;
+			break;
+		}
+		off += optlen;
+		len -= optlen;
+	}
+	if (len == 0)
+		return 0;
+bad:
+	return -1;
+
+}
+
+/* Replicate the checks that IPv6 does on packet reception and pass the packet
+ * to ip6tables, which doesn't support NAT, so things are fairly simple. */
+static unsigned int br_nf_pre_routing_ipv6(unsigned int hook,
+   struct sk_buff *skb, const struct net_device *in,
+   const struct net_device *out, int (*okfn)(struct sk_buff *))
+{
+	struct ipv6hdr *hdr;
+	u32 pkt_len;
+	struct nf_bridge_info *nf_bridge;
+
+	if (skb->len < sizeof(struct ipv6hdr))
+		goto inhdr_error;
+
+	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+		goto inhdr_error;
+
+	hdr = skb->nh.ipv6h;
+
+	if (hdr->version != 6)
+		goto inhdr_error;
+
+	pkt_len = ntohs(hdr->payload_len);
+
+	if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) {
+		if (pkt_len + sizeof(struct ipv6hdr) > skb->len)
+			goto inhdr_error;
+		if (pkt_len + sizeof(struct ipv6hdr) < skb->len) {
+			if (__pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr)))
+				goto inhdr_error;
+			if (skb->ip_summed == CHECKSUM_HW)
+				skb->ip_summed = CHECKSUM_NONE;
+		}
+	}
+	if (hdr->nexthdr == NEXTHDR_HOP && check_hbh_len(skb))
+			goto inhdr_error;
+
+#ifdef CONFIG_NETFILTER_DEBUG
+	skb->nf_debug ^= (1 << NF_IP6_PRE_ROUTING);
+#endif
+	if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
+		return NF_DROP;
+	setup_pre_routing(skb);
+
+	NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL,
+		br_nf_pre_routing_finish_ipv6);
+
+	return NF_STOLEN;
+
+inhdr_error:
+	return NF_DROP;
+}
+
+/* Direct IPv6 traffic to br_nf_pre_routing_ipv6.
+ * Replicate the checks that IPv4 does on packet reception.
  * Set skb->dev to the bridge device (i.e. parent of the
  * receiving device) to make netfilter happy, the REDIRECT
  * target in particular.  Save the original destination IP
- * address to be able to detect DNAT afterwards.
- */
+ * address to be able to detect DNAT afterwards. */
 static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
    const struct net_device *in, const struct net_device *out,
    int (*okfn)(struct sk_buff *))
@@ -259,25 +412,38 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
 	__u32 len;
 	struct sk_buff *skb = *pskb;
 	struct nf_bridge_info *nf_bridge;
+	struct vlan_ethhdr *hdr = vlan_eth_hdr(*pskb);
 
+	if (skb->protocol == __constant_htons(ETH_P_IPV6) || IS_VLAN_IPV6) {
+#ifdef CONFIG_SYSCTL
+		if (!brnf_call_ip6tables)
+			return NF_ACCEPT;
+#endif
+		if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
+			goto out;
+
+		if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
+			skb_pull(skb, VLAN_HLEN);
+			(skb)->nh.raw += VLAN_HLEN;
+		}
+		return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn);
+	}
 #ifdef CONFIG_SYSCTL
 	if (!brnf_call_iptables)
 		return NF_ACCEPT;
 #endif
 
-	if (skb->protocol != __constant_htons(ETH_P_IP)) {
-		struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)
-					  ((*pskb)->mac.ethernet);
+	if (skb->protocol != __constant_htons(ETH_P_IP) && !IS_VLAN_IP)
+		return NF_ACCEPT;
 
-		if (!IS_VLAN_IP)
-			return NF_ACCEPT;
-		if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
-			goto out;
-		skb_pull(*pskb, VLAN_HLEN);
-		(*pskb)->nh.raw += VLAN_HLEN;
-	} else if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
+	if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
 		goto out;
 
+	if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
+		skb_pull(skb, VLAN_HLEN);
+		(skb)->nh.raw += VLAN_HLEN;
+	}
+
 	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
 		goto inhdr_error;
 
@@ -305,17 +471,9 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
 #ifdef CONFIG_NETFILTER_DEBUG
 	skb->nf_debug ^= (1 << NF_IP_PRE_ROUTING);
 #endif
- 	if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
+	if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
 		return NF_DROP;
-
-	if (skb->pkt_type == PACKET_OTHERHOST) {
-		skb->pkt_type = PACKET_HOST;
-		nf_bridge->mask |= BRNF_PKT_TYPE;
-	}
-
-	nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING;
-	nf_bridge->physindev = skb->dev;
-	skb->dev = bridge_parent(skb->dev);
+	setup_pre_routing(skb);
 	store_orig_dstaddr(skb);
 
 	NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL,
@@ -336,8 +494,7 @@ out:
  * packet would pass through PRE_ROUTING again (which already
  * took place when the packet entered the bridge), but we
  * register an IPv4 PRE_ROUTING 'sabotage' hook that will
- * prevent this from happening.
- */
+ * prevent this from happening. */
 static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff **pskb,
    const struct net_device *in, const struct net_device *out,
    int (*okfn)(struct sk_buff *))
@@ -358,13 +515,13 @@ static int br_nf_forward_finish(struct sk_buff *skb)
 {
 	struct nf_bridge_info *nf_bridge = skb->nf_bridge;
 	struct net_device *in;
-	struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
+	struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
 
 #ifdef CONFIG_NETFILTER_DEBUG
 	skb->nf_debug ^= (1 << NF_BR_FORWARD);
 #endif
 
-	if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) {
+	if (skb->protocol != __constant_htons(ETH_P_ARP) && !IS_VLAN_ARP) {
 		in = nf_bridge->physindev;
 		if (nf_bridge->mask & BRNF_PKT_TYPE) {
 			skb->pkt_type = PACKET_OTHERHOST;
@@ -385,25 +542,26 @@ static int br_nf_forward_finish(struct sk_buff *skb)
 /* This is the 'purely bridged' case.  For IP, we pass the packet to
  * netfilter with indev and outdev set to the bridge device,
  * but we are still able to filter on the 'real' indev/outdev
- * because of the ipt_physdev.c module. For ARP, indev and outdev are the
- * bridge ports.
- */
+ * because of the physdev module. For ARP, indev and outdev are the
+ * bridge ports. */
 static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
    const struct net_device *in, const struct net_device *out,
    int (*okfn)(struct sk_buff *))
 {
 	struct sk_buff *skb = *pskb;
 	struct nf_bridge_info *nf_bridge;
-	struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
+	struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
+	int pf;
 
-#ifdef CONFIG_SYSCTL
 	if (!skb->nf_bridge)
 		return NF_ACCEPT;
-#endif
 
-	if (skb->protocol != __constant_htons(ETH_P_IP)) {
-		if (!IS_VLAN_IP)
-			return NF_ACCEPT;
+	if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP)
+		pf = PF_INET;
+	else
+		pf = PF_INET6;
+
+	if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
 		skb_pull(*pskb, VLAN_HLEN);
 		(*pskb)->nh.raw += VLAN_HLEN;
 	}
@@ -421,7 +579,7 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
 	nf_bridge->mask |= BRNF_BRIDGED;
 	nf_bridge->physoutdev = skb->dev;
 
-	NF_HOOK(PF_INET, NF_IP_FORWARD, skb, bridge_parent(in),
+	NF_HOOK(pf, NF_IP_FORWARD, skb, bridge_parent(in),
 		bridge_parent(out), br_nf_forward_finish);
 
 	return NF_STOLEN;
@@ -432,7 +590,7 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb,
    int (*okfn)(struct sk_buff *))
 {
 	struct sk_buff *skb = *pskb;
-	struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
+	struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
 	struct net_device **d = (struct net_device **)(skb->cb);
 
 #ifdef CONFIG_SYSCTL
@@ -483,11 +641,10 @@ static int br_nf_local_out_finish(struct sk_buff *skb)
 	return 0;
 }
 
-
 /* This function sees both locally originated IP packets and forwarded
  * IP packets (in both cases the destination device is a bridge
  * device). It also sees bridged-and-DNAT'ed packets.
- * To be able to filter on the physical bridge devices (with the ipt_physdev.c
+ * To be able to filter on the physical bridge devices (with the physdev
  * module), we steal packets destined to a bridge device away from the
  * PF_INET/FORWARD and PF_INET/OUTPUT hook functions, and give them back later,
  * when we have determined the real output device. This is done in here.
@@ -501,45 +658,44 @@ static int br_nf_local_out_finish(struct sk_buff *skb)
  * this packet before, and so the packet was locally originated. We fake
  * the PF_INET/LOCAL_OUT hook.
  * Finally, if nf_bridge->physindev isn't NULL, then the packet was IP routed,
- * so we fake the PF_INET/FORWARD hook. ipv4_sabotage_out() makes sure
+ * so we fake the PF_INET/FORWARD hook. ip_sabotage_out() makes sure
  * even routed packets that didn't arrive on a bridge interface have their
- * nf_bridge->physindev set.
- */
-
+ * nf_bridge->physindev set. */
 static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
    const struct net_device *in, const struct net_device *out,
-   int (*_okfn)(struct sk_buff *))
+   int (*okfn)(struct sk_buff *))
 {
-	int (*okfn)(struct sk_buff *skb);
-	struct net_device *realindev;
+	struct net_device *realindev, *realoutdev;
 	struct sk_buff *skb = *pskb;
 	struct nf_bridge_info *nf_bridge;
-	struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
+	struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
+	int pf;
 
-#ifdef CONFIG_SYSCTL
 	if (!skb->nf_bridge)
 		return NF_ACCEPT;
-#endif
 
-	if (skb->protocol != __constant_htons(ETH_P_IP) && !IS_VLAN_IP)
-		return NF_ACCEPT;
+	if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP)
+		pf = PF_INET;
+	else
+		pf = PF_INET6;
 
+#ifdef CONFIG_NETFILTER_DEBUG
 	/* Sometimes we get packets with NULL ->dst here (for example,
-	 * running a dhcp client daemon triggers this).
-	 */
-	if (skb->dst == NULL)
+	 * running a dhcp client daemon triggers this). This should now
+	 * be fixed, but let's keep the check around. */
+	if (skb->dst == NULL) {
+		printk(KERN_CRIT "br_netfilter: skb->dst == NULL.");
 		return NF_ACCEPT;
+	}
+#endif
 
 	nf_bridge = skb->nf_bridge;
 	nf_bridge->physoutdev = skb->dev;
 	realindev = nf_bridge->physindev;
 
 	/* Bridged, take PF_BRIDGE/FORWARD.
-	 * (see big note in front of br_nf_pre_routing_finish)
-	 */
+	 * (see big note in front of br_nf_pre_routing_finish) */
 	if (nf_bridge->mask & BRNF_BRIDGED_DNAT) {
-		okfn = br_forward_finish;
-
 		if (nf_bridge->mask & BRNF_PKT_TYPE) {
 			skb->pkt_type = PACKET_OTHERHOST;
 			nf_bridge->mask ^= BRNF_PKT_TYPE;
@@ -550,41 +706,41 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
 		}
 
 		NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, realindev,
-			skb->dev, okfn);
-	} else {
-		struct net_device *realoutdev = bridge_parent(skb->dev);
+			skb->dev, br_forward_finish);
+		goto out;
+	}
+	realoutdev = bridge_parent(skb->dev);
 
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-		/* iptables should match -o br0.x */
-		if (nf_bridge->netoutdev)
-			realoutdev = nf_bridge->netoutdev;
+	/* iptables should match -o br0.x */
+	if (nf_bridge->netoutdev)
+		realoutdev = nf_bridge->netoutdev;
 #endif
-		okfn = br_nf_local_out_finish;
-		if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
-			skb_pull(skb, VLAN_HLEN);
-			(*pskb)->nh.raw += VLAN_HLEN;
-		}
-		/* IP forwarded traffic has a physindev, locally
-		 * generated traffic hasn't.
-		 */
-		if (realindev != NULL) {
-			if (((nf_bridge->mask & BRNF_DONT_TAKE_PARENT) == 0) &&
-			    has_bridge_parent(realindev))
-				realindev = bridge_parent(realindev);
-			NF_HOOK_THRESH(PF_INET, NF_IP_FORWARD, skb, realindev,
-				       realoutdev, okfn,
-				       NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD + 1);
-		} else {
+	if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
+		skb_pull(skb, VLAN_HLEN);
+		(*pskb)->nh.raw += VLAN_HLEN;
+	}
+	/* IP forwarded traffic has a physindev, locally
+	 * generated traffic hasn't. */
+	if (realindev != NULL) {
+		if (!(nf_bridge->mask & BRNF_DONT_TAKE_PARENT) &&
+		    has_bridge_parent(realindev))
+			realindev = bridge_parent(realindev);
+
+		NF_HOOK_THRESH(pf, NF_IP_FORWARD, skb, realindev,
+			       realoutdev, br_nf_local_out_finish,
+			       NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD + 1);
+	} else {
 #ifdef CONFIG_NETFILTER_DEBUG
-			skb->nf_debug ^= (1 << NF_IP_LOCAL_OUT);
+		skb->nf_debug ^= (1 << NF_IP_LOCAL_OUT);
 #endif
 
-			NF_HOOK_THRESH(PF_INET, NF_IP_LOCAL_OUT, skb, realindev,
-				       realoutdev, okfn,
-				       NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT + 1);
-		}
+		NF_HOOK_THRESH(pf, NF_IP_LOCAL_OUT, skb, realindev,
+			       realoutdev, br_nf_local_out_finish,
+			       NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT + 1);
 	}
 
+out:
 	return NF_STOLEN;
 }
 
@@ -596,8 +752,9 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
 {
 	struct sk_buff *skb = *pskb;
 	struct nf_bridge_info *nf_bridge = (*pskb)->nf_bridge;
-	struct vlan_ethhdr *hdr = (struct vlan_ethhdr *)(skb->mac.ethernet);
+	struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
 	struct net_device *realoutdev = bridge_parent(skb->dev);
+	int pf;
 
 #ifdef CONFIG_NETFILTER_DEBUG
 	/* Be very paranoid. This probably won't happen anymore, but let's
@@ -609,19 +766,15 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
 	}
 #endif
 
-#ifdef CONFIG_SYSCTL
 	if (!nf_bridge)
 		return NF_ACCEPT;
-#endif
 
-	if (skb->protocol != __constant_htons(ETH_P_IP) && !IS_VLAN_IP)
-		return NF_ACCEPT;
+	if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP)
+		pf = PF_INET;
+	else
+		pf = PF_INET6;
 
 #ifdef CONFIG_NETFILTER_DEBUG
-	/* Sometimes we get packets with NULL ->dst here (for example,
-	 * running a dhcp client daemon triggers this). This should now
-	 * be fixed, but let's keep the check around.
-	 */
 	if (skb->dst == NULL) {
 		printk(KERN_CRIT "br_netfilter: skb->dst == NULL.");
 		goto print_error;
@@ -631,8 +784,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
 #endif
 
 	/* We assume any code from br_dev_queue_push_xmit onwards doesn't care
-	 * about the value of skb->pkt_type.
-	 */
+	 * about the value of skb->pkt_type. */
 	if (skb->pkt_type == PACKET_OTHERHOST) {
 		skb->pkt_type = PACKET_HOST;
 		nf_bridge->mask |= BRNF_PKT_TYPE;
@@ -649,8 +801,8 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
 	if (nf_bridge->netoutdev)
 		realoutdev = nf_bridge->netoutdev;
 #endif
-	NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
-		realoutdev, br_dev_queue_push_xmit);
+	NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev,
+	        br_dev_queue_push_xmit);
 
 	return NF_STOLEN;
 
@@ -668,12 +820,10 @@ print_error:
 }
 
 
-/* IPv4/SABOTAGE *****************************************************/
-
-/* Don't hand locally destined packets to PF_INET/PRE_ROUTING
- * for the second time.
- */
-static unsigned int ipv4_sabotage_in(unsigned int hook, struct sk_buff **pskb,
+/* IP/SABOTAGE *****************************************************/
+/* Don't hand locally destined packets to PF_INET(6)/PRE_ROUTING
+ * for the second time. */
+static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff **pskb,
    const struct net_device *in, const struct net_device *out,
    int (*okfn)(struct sk_buff *))
 {
@@ -686,19 +836,26 @@ static unsigned int ipv4_sabotage_in(unsigned int hook, struct sk_buff **pskb,
 	return NF_ACCEPT;
 }
 
-/* Postpone execution of PF_INET/FORWARD, PF_INET/LOCAL_OUT
- * and PF_INET/POST_ROUTING until we have done the forwarding
- * decision in the bridge code and have determined skb->physoutdev.
- */
-static unsigned int ipv4_sabotage_out(unsigned int hook, struct sk_buff **pskb,
+/* Postpone execution of PF_INET(6)/FORWARD, PF_INET(6)/LOCAL_OUT
+ * and PF_INET(6)/POST_ROUTING until we have done the forwarding
+ * decision in the bridge code and have determined nf_bridge->physoutdev. */
+static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb,
    const struct net_device *in, const struct net_device *out,
    int (*okfn)(struct sk_buff *))
 {
 	struct sk_buff *skb = *pskb;
 
 #ifdef CONFIG_SYSCTL
-	if (!brnf_call_iptables && !skb->nf_bridge)
-		return NF_ACCEPT;
+	if (!skb->nf_bridge) {
+		struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
+
+		if (skb->protocol == __constant_htons(ETH_P_IP) ||
+		    IS_VLAN_IP) {
+			if (!brnf_call_iptables)
+				return NF_ACCEPT;
+		} else if (!brnf_call_ip6tables)
+			return NF_ACCEPT;
+	}
 #endif
 
 	if ((out->hard_start_xmit == br_dev_xmit &&
@@ -721,8 +878,7 @@ static unsigned int ipv4_sabotage_out(unsigned int hook, struct sk_buff **pskb,
 		 * will need the indev then. For a brouter, the real indev
 		 * can be a bridge port, so we make sure br_nf_local_out()
 		 * doesn't use the bridge parent of the indev by using
-		 * the BRNF_DONT_TAKE_PARENT mask.
-		 */
+		 * the BRNF_DONT_TAKE_PARENT mask. */
 		if (hook == NF_IP_FORWARD && nf_bridge->physindev == NULL) {
 			nf_bridge->mask &= BRNF_DONT_TAKE_PARENT;
 			nf_bridge->physindev = (struct net_device *)in;
@@ -742,8 +898,7 @@ static unsigned int ipv4_sabotage_out(unsigned int hook, struct sk_buff **pskb,
 /* For br_nf_local_out we need (prio = NF_BR_PRI_FIRST), to insure that innocent
  * PF_BRIDGE/NF_BR_LOCAL_OUT functions don't get bridged traffic as input.
  * For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because
- * ip_refrag() can return NF_STOLEN.
- */
+ * ip_refrag() can return NF_STOLEN. */
 static struct nf_hook_ops br_nf_ops[] = {
 	{ .hook = br_nf_pre_routing, 
 	  .owner = THIS_MODULE, 
@@ -775,26 +930,46 @@ static struct nf_hook_ops br_nf_ops[] = {
 	  .pf = PF_BRIDGE,
 	  .hooknum = NF_BR_POST_ROUTING,
 	  .priority = NF_BR_PRI_LAST, },
-	{ .hook = ipv4_sabotage_in,
+	{ .hook = ip_sabotage_in,
 	  .owner = THIS_MODULE,
 	  .pf = PF_INET,
 	  .hooknum = NF_IP_PRE_ROUTING,
 	  .priority = NF_IP_PRI_FIRST, },
-	{ .hook = ipv4_sabotage_out,
+	{ .hook = ip_sabotage_in,
+	  .owner = THIS_MODULE,
+	  .pf = PF_INET6,
+	  .hooknum = NF_IP6_PRE_ROUTING,
+	  .priority = NF_IP6_PRI_FIRST, },
+	{ .hook = ip_sabotage_out,
 	  .owner = THIS_MODULE,
 	  .pf = PF_INET,
 	  .hooknum = NF_IP_FORWARD,
 	  .priority = NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD, },
-	{ .hook = ipv4_sabotage_out,
+	{ .hook = ip_sabotage_out,
+	  .owner = THIS_MODULE,
+	  .pf = PF_INET6,
+	  .hooknum = NF_IP6_FORWARD,
+	  .priority = NF_IP6_PRI_BRIDGE_SABOTAGE_FORWARD, },
+	{ .hook = ip_sabotage_out,
 	  .owner = THIS_MODULE,
 	  .pf = PF_INET,
 	  .hooknum = NF_IP_LOCAL_OUT,
 	  .priority = NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT, },
-	{ .hook = ipv4_sabotage_out,
+	{ .hook = ip_sabotage_out,
+	  .owner = THIS_MODULE,
+	  .pf = PF_INET6,
+	  .hooknum = NF_IP6_LOCAL_OUT,
+	  .priority = NF_IP6_PRI_BRIDGE_SABOTAGE_LOCAL_OUT, },
+	{ .hook = ip_sabotage_out,
 	  .owner = THIS_MODULE,
 	  .pf = PF_INET,
 	  .hooknum = NF_IP_POST_ROUTING,
 	  .priority = NF_IP_PRI_FIRST, },
+	{ .hook = ip_sabotage_out,
+	  .owner = THIS_MODULE,
+	  .pf = PF_INET6,
+	  .hooknum = NF_IP6_POST_ROUTING,
+	  .priority = NF_IP6_PRI_FIRST, },
 };
 
 #ifdef CONFIG_SYSCTL
@@ -828,6 +1003,14 @@ static ctl_table brnf_table[] = {
 		.mode		= 0644,
 		.proc_handler	= &brnf_sysctl_call_tables,
 	},
+	{
+		.ctl_name	= NET_BRIDGE_NF_CALL_IP6TABLES,
+		.procname	= "bridge-nf-call-ip6tables",
+		.data		= &brnf_call_ip6tables,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &brnf_sysctl_call_tables,
+	},
 	{
 		.ctl_name	= NET_BRIDGE_NF_FILTER_VLAN_TAGGED,
 		.procname	= "bridge-nf-filter-vlan-tagged",
diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c
index d0702fbcb..f8fb49e34 100644
--- a/net/bridge/br_notify.c
+++ b/net/bridge/br_notify.c
@@ -76,10 +76,12 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
 		break;
 
 	case NETDEV_UNREGISTER:
+		spin_unlock_bh(&br->lock);
 		br_del_if(br, dev);
-		break;
+		goto done;
 	} 
 	spin_unlock_bh(&br->lock);
 
+ done:
 	return NOTIFY_DONE;
 }
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index d2b2fb27f..cecdba777 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -177,7 +177,7 @@ extern int br_min_mtu(const struct net_bridge *br);
 
 /* br_input.c */
 extern int br_handle_frame_finish(struct sk_buff *skb);
-extern int br_handle_frame(struct sk_buff *skb);
+extern int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb);
 
 /* br_ioctl.c */
 extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
diff --git a/net/bridge/netfilter/ebt_802_3.c b/net/bridge/netfilter/ebt_802_3.c
index 1db4434f9..468ebdf4b 100644
--- a/net/bridge/netfilter/ebt_802_3.c
+++ b/net/bridge/netfilter/ebt_802_3.c
@@ -16,7 +16,7 @@ static int ebt_filter_802_3(const struct sk_buff *skb, const struct net_device *
    const struct net_device *out, const void *data, unsigned int datalen)
 {
 	struct ebt_802_3_info *info = (struct ebt_802_3_info *)data;
-	struct ebt_802_3_hdr *hdr = (struct ebt_802_3_hdr *)skb->mac.ethernet;
+	struct ebt_802_3_hdr *hdr = ebt_802_3_hdr(skb);
 	uint16_t type = hdr->llc.ui.ctrl & IS_UI ? hdr->llc.ui.type : hdr->llc.ni.type;
 
 	if (info->bitmask & EBT_802_3_SAP) {
diff --git a/net/bridge/netfilter/ebt_among.c b/net/bridge/netfilter/ebt_among.c
index 727311dfd..5a1f5e3bf 100644
--- a/net/bridge/netfilter/ebt_among.c
+++ b/net/bridge/netfilter/ebt_among.c
@@ -72,42 +72,55 @@ static int ebt_mac_wormhash_check_integrity(const struct ebt_mac_wormhash
 
 static int get_ip_dst(const struct sk_buff *skb, uint32_t *addr)
 {
-	if (skb->mac.ethernet->h_proto == __constant_htons(ETH_P_IP)) {
-		struct iphdr iph;
+	if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) {
+		struct iphdr _iph, *ih;
 
-		if (skb_copy_bits(skb, 0, &iph, sizeof(iph)))
+		ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
+		if (ih == NULL)
 			return -1;
-		*addr = iph.daddr;
-	} else if (skb->mac.ethernet->h_proto == __constant_htons(ETH_P_ARP)) {
-		struct arphdr arph;
-
-		if (skb_copy_bits(skb, 0, &arph, sizeof(arph)) ||
-		    arph.ar_pln != sizeof(uint32_t) || arph.ar_hln != ETH_ALEN)
+		*addr = ih->daddr;
+	} else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) {
+		struct arphdr _arph, *ah;
+		uint32_t buf, *bp;
+
+		ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
+		if (ah == NULL ||
+		    ah->ar_pln != sizeof(uint32_t) ||
+		    ah->ar_hln != ETH_ALEN)
 			return -1;
-		if (skb_copy_bits(skb, sizeof(struct arphdr) +
-		    2 * ETH_ALEN + sizeof(uint32_t), addr, sizeof(uint32_t)))
+		bp = skb_header_pointer(skb, sizeof(struct arphdr) +
+					2 * ETH_ALEN + sizeof(uint32_t),
+					sizeof(uint32_t), &buf);
+		if (bp == NULL)
 			return -1;
+		*addr = *bp;
 	}
 	return 0;
 }
 
 static int get_ip_src(const struct sk_buff *skb, uint32_t *addr)
 {
-	if (skb->mac.ethernet->h_proto == __constant_htons(ETH_P_IP)) {
-		struct iphdr iph;
+	if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) {
+		struct iphdr _iph, *ih;
 
-		if (skb_copy_bits(skb, 0, &iph, sizeof(iph)))
+		ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
+		if (ih == NULL)
 			return -1;
-		*addr = iph.saddr;
-	} else if (skb->mac.ethernet->h_proto == __constant_htons(ETH_P_ARP)) {
-		struct arphdr arph;
-
-		if (skb_copy_bits(skb, 0, &arph, sizeof(arph)) ||
-		    arph.ar_pln != sizeof(uint32_t) || arph.ar_hln != ETH_ALEN)
+		*addr = ih->saddr;
+	} else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) {
+		struct arphdr _arph, *ah;
+		uint32_t buf, *bp;
+
+		ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
+		if (ah == NULL ||
+		    ah->ar_pln != sizeof(uint32_t) ||
+		    ah->ar_hln != ETH_ALEN)
 			return -1;
-		if (skb_copy_bits(skb, sizeof(struct arphdr) +
-		    ETH_ALEN, addr, sizeof(uint32_t)))
+		bp = skb_header_pointer(skb, sizeof(struct arphdr) +
+					ETH_ALEN, sizeof(uint32_t), &buf);
+		if (bp == NULL)
 			return -1;
+		*addr = *bp;
 	}
 	return 0;
 }
@@ -126,7 +139,7 @@ static int ebt_filter_among(const struct sk_buff *skb,
 	wh_src = ebt_among_wh_src(info);
 
 	if (wh_src) {
-		smac = skb->mac.ethernet->h_source;
+		smac = eth_hdr(skb)->h_source;
 		if (get_ip_src(skb, &sip))
 			return EBT_NOMATCH;
 		if (!(info->bitmask & EBT_AMONG_SRC_NEG)) {
@@ -141,7 +154,7 @@ static int ebt_filter_among(const struct sk_buff *skb,
 	}
 
 	if (wh_dst) {
-		dmac = skb->mac.ethernet->h_dest;
+		dmac = eth_hdr(skb)->h_dest;
 		if (get_ip_dst(skb, &dip))
 			return EBT_NOMATCH;
 		if (!(info->bitmask & EBT_AMONG_DST_NEG)) {
diff --git a/net/bridge/netfilter/ebt_arp.c b/net/bridge/netfilter/ebt_arp.c
index eb675848f..b94c48cb6 100644
--- a/net/bridge/netfilter/ebt_arp.c
+++ b/net/bridge/netfilter/ebt_arp.c
@@ -19,72 +19,79 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in
    const struct net_device *out, const void *data, unsigned int datalen)
 {
 	struct ebt_arp_info *info = (struct ebt_arp_info *)data;
-	struct arphdr arph;
+	struct arphdr _arph, *ah;
 
-	if (skb_copy_bits(skb, 0, &arph, sizeof(arph)))
+	ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
+	if (ah == NULL)
 		return EBT_NOMATCH;
 	if (info->bitmask & EBT_ARP_OPCODE && FWINV(info->opcode !=
-	   arph.ar_op, EBT_ARP_OPCODE))
+	   ah->ar_op, EBT_ARP_OPCODE))
 		return EBT_NOMATCH;
 	if (info->bitmask & EBT_ARP_HTYPE && FWINV(info->htype !=
-	   arph.ar_hrd, EBT_ARP_HTYPE))
+	   ah->ar_hrd, EBT_ARP_HTYPE))
 		return EBT_NOMATCH;
 	if (info->bitmask & EBT_ARP_PTYPE && FWINV(info->ptype !=
-	   arph.ar_pro, EBT_ARP_PTYPE))
+	   ah->ar_pro, EBT_ARP_PTYPE))
 		return EBT_NOMATCH;
 
 	if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP)) {
-		uint32_t addr;
+		uint32_t _addr, *ap;
 
 		/* IPv4 addresses are always 4 bytes */
-		if (arph.ar_pln != sizeof(uint32_t))
+		if (ah->ar_pln != sizeof(uint32_t))
 			return EBT_NOMATCH;
 		if (info->bitmask & EBT_ARP_SRC_IP) {
-			if (skb_copy_bits(skb, sizeof(struct arphdr) +
-			    arph.ar_hln, &addr, sizeof(addr)))
+			ap = skb_header_pointer(skb, sizeof(struct arphdr) +
+						ah->ar_hln, sizeof(_addr),
+						&_addr);
+			if (ap == NULL)
 				return EBT_NOMATCH;
-			if (FWINV(info->saddr != (addr & info->smsk),
+			if (FWINV(info->saddr != (*ap & info->smsk),
 			   EBT_ARP_SRC_IP))
 				return EBT_NOMATCH;
 		}
 
 		if (info->bitmask & EBT_ARP_DST_IP) {
-			if (skb_copy_bits(skb, sizeof(struct arphdr) +
-			    2*arph.ar_hln + sizeof(uint32_t), &addr,
-			    sizeof(addr)))
+			ap = skb_header_pointer(skb, sizeof(struct arphdr) +
+						2*ah->ar_hln+sizeof(uint32_t),
+						sizeof(_addr), &_addr);
+			if (ap == NULL)
 				return EBT_NOMATCH;
-			if (FWINV(info->daddr != (addr & info->dmsk),
+			if (FWINV(info->daddr != (*ap & info->dmsk),
 			   EBT_ARP_DST_IP))
 				return EBT_NOMATCH;
 		}
 	}
 
 	if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)) {
-		unsigned char mac[ETH_ALEN];
+		unsigned char _mac[ETH_ALEN], *mp;
 		uint8_t verdict, i;
 
 		/* MAC addresses are 6 bytes */
-		if (arph.ar_hln != ETH_ALEN)
+		if (ah->ar_hln != ETH_ALEN)
 			return EBT_NOMATCH;
 		if (info->bitmask & EBT_ARP_SRC_MAC) {
-			if (skb_copy_bits(skb, sizeof(struct arphdr), &mac,
-			    ETH_ALEN))
+			mp = skb_header_pointer(skb, sizeof(struct arphdr),
+						sizeof(_mac), &_mac);
+			if (mp == NULL)
 				return EBT_NOMATCH;
 			verdict = 0;
 			for (i = 0; i < 6; i++)
-				verdict |= (mac[i] ^ info->smaddr[i]) &
+				verdict |= (mp[i] ^ info->smaddr[i]) &
 				       info->smmsk[i];
 			if (FWINV(verdict != 0, EBT_ARP_SRC_MAC))
 				return EBT_NOMATCH;
 		}
 
 		if (info->bitmask & EBT_ARP_DST_MAC) {
-			if (skb_copy_bits(skb, sizeof(struct arphdr) +
-			    arph.ar_hln + arph.ar_pln, &mac, ETH_ALEN))
+			mp = skb_header_pointer(skb, sizeof(struct arphdr) +
+						ah->ar_hln + ah->ar_pln,
+						sizeof(_mac), &_mac);
+			if (mp == NULL)
 				return EBT_NOMATCH;
 			verdict = 0;
 			for (i = 0; i < 6; i++)
-				verdict |= (mac[i] ^ info->dmaddr[i]) &
+				verdict |= (mp[i] ^ info->dmaddr[i]) &
 					info->dmmsk[i];
 			if (FWINV(verdict != 0, EBT_ARP_DST_MAC))
 				return EBT_NOMATCH;
@@ -101,8 +108,8 @@ static int ebt_arp_check(const char *tablename, unsigned int hookmask,
 
 	if (datalen != EBT_ALIGN(sizeof(struct ebt_arp_info)))
 		return -EINVAL;
-	if ((e->ethproto != __constant_htons(ETH_P_ARP) &&
-	   e->ethproto != __constant_htons(ETH_P_RARP)) ||
+	if ((e->ethproto != htons(ETH_P_ARP) &&
+	   e->ethproto != htons(ETH_P_RARP)) ||
 	   e->invflags & EBT_IPROTO)
 		return -EINVAL;
 	if (info->bitmask & ~EBT_ARP_MASK || info->invflags & ~EBT_ARP_MASK)
diff --git a/net/bridge/netfilter/ebt_arpreply.c b/net/bridge/netfilter/ebt_arpreply.c
index 87ba30dd0..b934de90f 100644
--- a/net/bridge/netfilter/ebt_arpreply.c
+++ b/net/bridge/netfilter/ebt_arpreply.c
@@ -20,30 +20,38 @@ static int ebt_target_reply(struct sk_buff **pskb, unsigned int hooknr,
    const void *data, unsigned int datalen)
 {
 	struct ebt_arpreply_info *info = (struct ebt_arpreply_info *)data;
-	u32 sip, dip;
-	struct arphdr ah;
-	unsigned char sha[ETH_ALEN];
+	u32 _sip, *siptr, _dip, *diptr;
+	struct arphdr _ah, *ap;
+	unsigned char _sha[ETH_ALEN], *shp;
 	struct sk_buff *skb = *pskb;
 
-	if (skb_copy_bits(skb, 0, &ah, sizeof(ah)))
+	ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah);
+	if (ap == NULL)
 		return EBT_DROP;
 
-	if (ah.ar_op != __constant_htons(ARPOP_REQUEST) || ah.ar_hln != ETH_ALEN
-	    || ah.ar_pro != __constant_htons(ETH_P_IP) || ah.ar_pln != 4)
+	if (ap->ar_op != htons(ARPOP_REQUEST) ||
+	    ap->ar_hln != ETH_ALEN ||
+	    ap->ar_pro != htons(ETH_P_IP) ||
+	    ap->ar_pln != 4)
 		return EBT_CONTINUE;
 
-	if (skb_copy_bits(skb, sizeof(ah), &sha, ETH_ALEN))
+	shp = skb_header_pointer(skb, sizeof(_ah), ETH_ALEN, &_sha);
+	if (shp == NULL)
 		return EBT_DROP;
 
-	if (skb_copy_bits(skb, sizeof(ah) + ETH_ALEN, &sip, sizeof(sip)))
+	siptr = skb_header_pointer(skb, sizeof(_ah) + ETH_ALEN,
+				   sizeof(_sip), &_sip);
+	if (siptr == NULL)
 		return EBT_DROP;
 
-	if (skb_copy_bits(skb, sizeof(ah) + 2 * ETH_ALEN + sizeof(sip),
-	    &dip, sizeof(dip)))
+	diptr = skb_header_pointer(skb,
+				   sizeof(_ah) + 2 * ETH_ALEN + sizeof(_sip),
+				   sizeof(_dip), &_dip);
+	if (diptr == NULL)
 		return EBT_DROP;
 
-	arp_send(ARPOP_REPLY, ETH_P_ARP, sip, (struct net_device *)in,
-	         dip, sha, info->mac, sha);
+	arp_send(ARPOP_REPLY, ETH_P_ARP, *siptr, (struct net_device *)in,
+	         *diptr, shp, info->mac, shp);
 
 	return info->target;
 }
@@ -57,7 +65,7 @@ static int ebt_target_reply_check(const char *tablename, unsigned int hookmask,
 		return -EINVAL;
 	if (BASE_CHAIN && info->target == EBT_RETURN)
 		return -EINVAL;
-	if (e->ethproto != __constant_htons(ETH_P_ARP) ||
+	if (e->ethproto != htons(ETH_P_ARP) ||
 	    e->invflags & EBT_IPROTO)
 		return -EINVAL;
 	CLEAR_BASE_CHAIN_BIT;
diff --git a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c
index f9552dfb1..f5463086c 100644
--- a/net/bridge/netfilter/ebt_dnat.c
+++ b/net/bridge/netfilter/ebt_dnat.c
@@ -30,8 +30,7 @@ static int ebt_target_dnat(struct sk_buff **pskb, unsigned int hooknr,
 		kfree_skb(*pskb);
 		*pskb = nskb;
 	}
-	memcpy(((**pskb).mac.ethernet)->h_dest, info->mac,
-	   ETH_ALEN * sizeof(unsigned char));
+	memcpy(eth_hdr(*pskb)->h_dest, info->mac, ETH_ALEN);
 	return info->target;
 }
 
diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c
index 7bab7d065..7323805b9 100644
--- a/net/bridge/netfilter/ebt_ip.c
+++ b/net/bridge/netfilter/ebt_ip.c
@@ -28,41 +28,44 @@ static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in,
    unsigned int datalen)
 {
 	struct ebt_ip_info *info = (struct ebt_ip_info *)data;
-	union {struct iphdr iph; struct tcpudphdr ports;} u;
+	struct iphdr _iph, *ih;
+	struct tcpudphdr _ports, *pptr;
 
-	if (skb_copy_bits(skb, 0, &u.iph, sizeof(u.iph)))
+	ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
+	if (ih == NULL)
 		return EBT_NOMATCH;
 	if (info->bitmask & EBT_IP_TOS &&
-	   FWINV(info->tos != u.iph.tos, EBT_IP_TOS))
+	   FWINV(info->tos != ih->tos, EBT_IP_TOS))
 		return EBT_NOMATCH;
 	if (info->bitmask & EBT_IP_SOURCE &&
-	   FWINV((u.iph.saddr & info->smsk) !=
+	   FWINV((ih->saddr & info->smsk) !=
 	   info->saddr, EBT_IP_SOURCE))
 		return EBT_NOMATCH;
 	if ((info->bitmask & EBT_IP_DEST) &&
-	   FWINV((u.iph.daddr & info->dmsk) !=
+	   FWINV((ih->daddr & info->dmsk) !=
 	   info->daddr, EBT_IP_DEST))
 		return EBT_NOMATCH;
 	if (info->bitmask & EBT_IP_PROTO) {
-		if (FWINV(info->protocol != u.iph.protocol, EBT_IP_PROTO))
+		if (FWINV(info->protocol != ih->protocol, EBT_IP_PROTO))
 			return EBT_NOMATCH;
 		if (!(info->bitmask & EBT_IP_DPORT) &&
 		    !(info->bitmask & EBT_IP_SPORT))
 			return EBT_MATCH;
-		if (skb_copy_bits(skb, u.iph.ihl*4, &u.ports,
-		    sizeof(u.ports)))
+		pptr = skb_header_pointer(skb, ih->ihl*4,
+					  sizeof(_ports), &_ports);
+		if (pptr == NULL)
 			return EBT_NOMATCH;
 		if (info->bitmask & EBT_IP_DPORT) {
-			u.ports.dst = ntohs(u.ports.dst);
-			if (FWINV(u.ports.dst < info->dport[0] ||
-			          u.ports.dst > info->dport[1],
+			u32 dst = ntohs(pptr->dst);
+			if (FWINV(dst < info->dport[0] ||
+			          dst > info->dport[1],
 			          EBT_IP_DPORT))
 			return EBT_NOMATCH;
 		}
 		if (info->bitmask & EBT_IP_SPORT) {
-			u.ports.src = ntohs(u.ports.src);
-			if (FWINV(u.ports.src < info->sport[0] ||
-			          u.ports.src > info->sport[1],
+			u32 src = ntohs(pptr->src);
+			if (FWINV(src < info->sport[0] ||
+			          src > info->sport[1],
 			          EBT_IP_SPORT))
 			return EBT_NOMATCH;
 		}
@@ -77,7 +80,7 @@ static int ebt_ip_check(const char *tablename, unsigned int hookmask,
 
 	if (datalen != EBT_ALIGN(sizeof(struct ebt_ip_info)))
 		return -EINVAL;
-	if (e->ethproto != __constant_htons(ETH_P_IP) ||
+	if (e->ethproto != htons(ETH_P_IP) ||
 	   e->invflags & EBT_IPROTO)
 		return -EINVAL;
 	if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK)
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 2da7c6827..6c022efaa 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -70,64 +70,76 @@ static void ebt_log(const struct sk_buff *skb, const struct net_device *in,
 	   out ? out->name : "");
 
 	printk("MAC source = ");
-	print_MAC((skb->mac.ethernet)->h_source);
+	print_MAC(eth_hdr(skb)->h_source);
 	printk("MAC dest = ");
-	print_MAC((skb->mac.ethernet)->h_dest);
+	print_MAC(eth_hdr(skb)->h_dest);
 
-	printk("proto = 0x%04x", ntohs(((*skb).mac.ethernet)->h_proto));
+	printk("proto = 0x%04x", ntohs(eth_hdr(skb)->h_proto));
 
-	if ((info->bitmask & EBT_LOG_IP) && skb->mac.ethernet->h_proto ==
+	if ((info->bitmask & EBT_LOG_IP) && eth_hdr(skb)->h_proto ==
 	   htons(ETH_P_IP)){
-		if (skb_copy_bits(skb, 0, &u.iph, sizeof(u.iph))) {
+		struct iphdr _iph, *ih;
+
+		ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
+		if (ih == NULL) {
 			printk(" INCOMPLETE IP header");
 			goto out;
 		}
 		printk(" IP SRC=%u.%u.%u.%u IP DST=%u.%u.%u.%u,",
-		   NIPQUAD(u.iph.saddr), NIPQUAD(u.iph.daddr));
+		   NIPQUAD(ih->saddr), NIPQUAD(ih->daddr));
 		printk(" IP tos=0x%02X, IP proto=%d", u.iph.tos,
-		       u.iph.protocol);
-		if (u.iph.protocol == IPPROTO_TCP ||
-		    u.iph.protocol == IPPROTO_UDP) {
-			if (skb_copy_bits(skb, u.iph.ihl*4, &u.ports,
-			    sizeof(u.ports))) {
+		       ih->protocol);
+		if (ih->protocol == IPPROTO_TCP ||
+		    ih->protocol == IPPROTO_UDP) {
+			struct tcpudphdr _ports, *pptr;
+
+			pptr = skb_header_pointer(skb, ih->ihl*4,
+						  sizeof(_ports), &_ports);
+			if (pptr == NULL) {
 				printk(" INCOMPLETE TCP/UDP header");
 				goto out;
 			}
-			printk(" SPT=%u DPT=%u", ntohs(u.ports.src),
-			   ntohs(u.ports.dst));
+			printk(" SPT=%u DPT=%u", ntohs(pptr->src),
+			   ntohs(pptr->dst));
 		}
 		goto out;
 	}
 
 	if ((info->bitmask & EBT_LOG_ARP) &&
-	    ((skb->mac.ethernet->h_proto == __constant_htons(ETH_P_ARP)) ||
-	    (skb->mac.ethernet->h_proto == __constant_htons(ETH_P_RARP)))) {
-		if (skb_copy_bits(skb, 0, &u.arph, sizeof(u.arph))) {
+	    ((eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) ||
+	     (eth_hdr(skb)->h_proto == htons(ETH_P_RARP)))) {
+		struct arphdr _arph, *ah;
+
+		ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
+		if (ah == NULL) {
 			printk(" INCOMPLETE ARP header");
 			goto out;
 		}
 		printk(" ARP HTYPE=%d, PTYPE=0x%04x, OPCODE=%d",
-		       ntohs(u.arph.ar_hrd), ntohs(u.arph.ar_pro),
-		       ntohs(u.arph.ar_op));
+		       ntohs(ah->ar_hrd), ntohs(ah->ar_pro),
+		       ntohs(ah->ar_op));
 
 		/* If it's for Ethernet and the lengths are OK,
 		 * then log the ARP payload */
-		if (u.arph.ar_hrd == __constant_htons(1) &&
-		    u.arph.ar_hln == ETH_ALEN &&
-		    u.arph.ar_pln == sizeof(uint32_t)) {
-			if (skb_copy_bits(skb, sizeof(u.arph), &u.arpp,
-			    sizeof(u.arpp))) {
+		if (ah->ar_hrd == htons(1) &&
+		    ah->ar_hln == ETH_ALEN &&
+		    ah->ar_pln == sizeof(uint32_t)) {
+			struct arppayload _arpp, *ap;
+
+			ap = skb_header_pointer(skb, sizeof(u.arph),
+						sizeof(_arpp), &_arpp);
+			if (ap == NULL) {
 				printk(" INCOMPLETE ARP payload");
 				goto out;
 			}
 			printk(" ARP MAC SRC=");
-			print_MAC(u.arpp.mac_src);
+			print_MAC(ap->mac_src);
 			printk(" ARP IP SRC=%u.%u.%u.%u",
-			       myNIPQUAD(u.arpp.ip_src));
+			       myNIPQUAD(ap->ip_src));
 			printk(" ARP MAC DST=");
-			print_MAC(u.arpp.mac_dst);
+			print_MAC(ap->mac_dst);
 			printk(" ARP IP DST=%u.%u.%u.%u",
-			       myNIPQUAD(u.arpp.ip_dst));
+			       myNIPQUAD(ap->ip_dst));
 		}
 	}
 out:
diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c
index befbfa1e0..1538b4386 100644
--- a/net/bridge/netfilter/ebt_redirect.c
+++ b/net/bridge/netfilter/ebt_redirect.c
@@ -32,11 +32,10 @@ static int ebt_target_redirect(struct sk_buff **pskb, unsigned int hooknr,
 		*pskb = nskb;
 	}
 	if (hooknr != NF_BR_BROUTING)
-		memcpy((**pskb).mac.ethernet->h_dest,
-		   in->br_port->br->dev->dev_addr, ETH_ALEN);
+		memcpy(eth_hdr(*pskb)->h_dest,
+		       in->br_port->br->dev->dev_addr, ETH_ALEN);
 	else
-		memcpy((**pskb).mac.ethernet->h_dest,
-		   in->dev_addr, ETH_ALEN);
+		memcpy(eth_hdr(*pskb)->h_dest, in->dev_addr, ETH_ALEN);
 	(*pskb)->pkt_type = PACKET_HOST;
 	return info->target;
 }
diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
index ae0f0539c..1529bdcb9 100644
--- a/net/bridge/netfilter/ebt_snat.c
+++ b/net/bridge/netfilter/ebt_snat.c
@@ -30,8 +30,7 @@ static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr,
 		kfree_skb(*pskb);
 		*pskb = nskb;
 	}
-	memcpy(((**pskb).mac.ethernet)->h_source, info->mac,
-	   ETH_ALEN * sizeof(unsigned char));
+	memcpy(eth_hdr(*pskb)->h_source, info->mac, ETH_ALEN);
 	return info->target;
 }
 
diff --git a/net/bridge/netfilter/ebt_stp.c b/net/bridge/netfilter/ebt_stp.c
index d0299efa1..f8a8cdec1 100644
--- a/net/bridge/netfilter/ebt_stp.c
+++ b/net/bridge/netfilter/ebt_stp.c
@@ -122,26 +122,30 @@ static int ebt_filter_stp(const struct sk_buff *skb, const struct net_device *in
    const struct net_device *out, const void *data, unsigned int datalen)
 {
 	struct ebt_stp_info *info = (struct ebt_stp_info *)data;
-	struct stp_header stph;
+	struct stp_header _stph, *sp;
 	uint8_t header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00};
-	if (skb_copy_bits(skb, 0, &stph, sizeof(stph)))
+
+	sp = skb_header_pointer(skb, 0, sizeof(_stph), &_stph);
+	if (sp == NULL)
 		return EBT_NOMATCH;
 
 	/* The stp code only considers these */
-	if (memcmp(&stph, header, sizeof(header)))
+	if (memcmp(sp, header, sizeof(header)))
 		return EBT_NOMATCH;
 
 	if (info->bitmask & EBT_STP_TYPE
-	    && FWINV(info->type != stph.type, EBT_STP_TYPE))
+	    && FWINV(info->type != sp->type, EBT_STP_TYPE))
 		return EBT_NOMATCH;
 
-	if (stph.type == BPDU_TYPE_CONFIG &&
+	if (sp->type == BPDU_TYPE_CONFIG &&
 	    info->bitmask & EBT_STP_CONFIG_MASK) {
-		struct stp_config_pdu stpc;
+		struct stp_config_pdu _stpc, *st;
 
-		if (skb_copy_bits(skb, sizeof(stph), &stpc, sizeof(stpc)))
-		    return EBT_NOMATCH;
-		return ebt_filter_config(info, &stpc);
+		st = skb_header_pointer(skb, sizeof(_stph),
+					sizeof(_stpc), &_stpc);
+		if (st == NULL)
+			return EBT_NOMATCH;
+		return ebt_filter_config(info, st);
 	}
 	return EBT_MATCH;
 }
diff --git a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c
index ec111772b..db60d7349 100644
--- a/net/bridge/netfilter/ebt_vlan.c
+++ b/net/bridge/netfilter/ebt_vlan.c
@@ -21,13 +21,14 @@
 #include <linux/if_ether.h>
 #include <linux/if_vlan.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/netfilter_bridge/ebtables.h>
 #include <linux/netfilter_bridge/ebt_vlan.h>
 
-static unsigned char debug;
+static int debug;
 #define MODULE_VERS "0.6"
 
-MODULE_PARM(debug, "0-1b");
+module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "debug=1 is turn on debug messages");
 MODULE_AUTHOR("Nick Fedchik <nick@fedchik.org.ua>");
 MODULE_DESCRIPTION("802.1Q match module (ebtables extension), v"
@@ -48,7 +49,7 @@ ebt_filter_vlan(const struct sk_buff *skb,
 		const void *data, unsigned int datalen)
 {
 	struct ebt_vlan_info *info = (struct ebt_vlan_info *) data;
-	struct vlan_hdr frame;
+	struct vlan_hdr _frame, *fp;
 
 	unsigned short TCI;	/* Whole TCI, given from parsed frame */
 	unsigned short id;	/* VLAN ID, given from frame TCI */
@@ -56,7 +57,8 @@ ebt_filter_vlan(const struct sk_buff *skb,
 	/* VLAN encapsulated Type/Length field, given from orig frame */
 	unsigned short encap;
 
-	if (skb_copy_bits(skb, 0, &frame, sizeof(frame)))
+	fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame);
+	if (fp == NULL)
 		return EBT_NOMATCH;
 
 	/* Tag Control Information (TCI) consists of the following elements:
@@ -66,10 +68,10 @@ ebt_filter_vlan(const struct sk_buff *skb,
 	 * (CFI) is a single bit flag value. Currently ignored.
 	 * - VLAN Identifier (VID). The VID is encoded as
 	 * an unsigned binary number. */
-	TCI = ntohs(frame.h_vlan_TCI);
+	TCI = ntohs(fp->h_vlan_TCI);
 	id = TCI & VLAN_VID_MASK;
 	prio = (TCI >> 13) & 0x7;
-	encap = frame.h_vlan_encapsulated_proto;
+	encap = fp->h_vlan_encapsulated_proto;
 
 	/* Checking VLAN Identifier (VID) */
 	if (GET_BITMASK(EBT_VLAN_ID))
@@ -102,7 +104,7 @@ ebt_check_vlan(const char *tablename,
 	}
 
 	/* Is it 802.1Q frame checked? */
-	if (e->ethproto != __constant_htons(ETH_P_8021Q)) {
+	if (e->ethproto != htons(ETH_P_8021Q)) {
 		DEBUG_MSG
 		    ("passed entry proto %2.4X is not 802.1Q (8100)\n",
 		     (unsigned short) ntohs(e->ethproto));
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 65184c5e6..8352eec5b 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -190,7 +190,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
 	base = private->entries;
 	i = 0;
 	while (i < nentries) {
-		if (ebt_basic_match(point, (**pskb).mac.ethernet, in, out))
+		if (ebt_basic_match(point, eth_hdr(*pskb), in, out))
 			goto letscontinue;
 
 		if (EBT_MATCH_ITERATE(point, ebt_do_match, *pskb, in, out) != 0)
diff --git a/net/compat.c b/net/compat.c
index 998b21b65..6080b6439 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -455,13 +455,15 @@ static int do_set_sock_timeout(int fd, int level, int optname, char __user *optv
 asmlinkage long compat_sys_setsockopt(int fd, int level, int optname,
 				char __user *optval, int optlen)
 {
+	/* SO_SET_REPLACE seems to be the same in all levels */
 	if (optname == IPT_SO_SET_REPLACE)
 		return do_netfilter_replace(fd, level, optname,
 					    optval, optlen);
-	if (optname == SO_ATTACH_FILTER)
+	if (level == SOL_SOCKET && optname == SO_ATTACH_FILTER)
 		return do_set_attach_filter(fd, level, optname,
 					    optval, optlen);
-	if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
+	if (level == SOL_SOCKET &&
+	    (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO))
 		return do_set_sock_timeout(fd, level, optname, optval, optlen);
 
 	return sys_setsockopt(fd, level, optname, optval, optlen);
diff --git a/net/core/Makefile b/net/core/Makefile
index e9b21b941..81f03243f 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the Linux networking core.
 #
 
-obj-y := sock.o skbuff.o iovec.o datagram.o stream.o scm.o
+obj-y := sock.o skbuff.o iovec.o datagram.o stream.o scm.o gen_stats.o gen_estimator.o
 
 obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
 
diff --git a/net/core/dev.c b/net/core/dev.c
index 0301ffcdc..65b3541fc 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -113,6 +113,7 @@
 #include <net/iw_handler.h>
 #endif	/* CONFIG_NET_RADIO */
 #include <asm/current.h>
+#include <linux/vs_base.h>
 #include <linux/vs_network.h>
 
 /* This define, if set, will randomly drop a packet when congestion
@@ -862,18 +863,6 @@ static int default_rebuild_header(struct sk_buff *skb)
 }
 
 
-/*
- * Some old buggy device drivers change get_stats after registering
- * the device.  Try and trap them here.
- * This can be elimnated when all devices are known fixed.
- */
-static inline int get_stats_changed(struct net_device *dev)
-{
-	int changed = dev->last_stats != dev->get_stats;
-	dev->last_stats = dev->get_stats;
-	return changed;
-}
-
 /**
  *	dev_open	- prepare an interface for use.
  *	@dev:	device to open
@@ -897,14 +886,6 @@ int dev_open(struct net_device *dev)
 	if (dev->flags & IFF_UP)
 		return 0;
 
-	/*
-	 *	 Check for broken device drivers.
-	 */
-	if (get_stats_changed(dev) && net_ratelimit()) {
-		printk(KERN_ERR "%s: driver changed get_stats after register\n",
-		       dev->name);
-	}
-
 	/*
 	 *	Is it even present?
 	 */
@@ -921,14 +902,6 @@ int dev_open(struct net_device *dev)
 			clear_bit(__LINK_STATE_START, &dev->state);
 	}
 
-	/*
-	 * 	Check for more broken device drivers.
-	 */
-	if (get_stats_changed(dev) && net_ratelimit()) {
-		printk(KERN_ERR "%s: driver changed get_stats in open\n",
-		       dev->name);
-	}
-
  	/*
 	 *	If it went open OK then:
 	 */
@@ -1145,16 +1118,10 @@ int skb_checksum_help(struct sk_buff **pskb, int inward)
 		goto out;
 	}
 
-	if (skb_shared(*pskb)  || skb_cloned(*pskb)) {
-		struct sk_buff *newskb = skb_copy(*pskb, GFP_ATOMIC);
-		if (!newskb) {
-			ret = -ENOMEM;
+	if (skb_cloned(*pskb)) {
+		ret = pskb_expand_head(*pskb, 0, 0, GFP_ATOMIC);
+		if (ret)
 			goto out;
-		}
-		if ((*pskb)->sk)
-			skb_set_owner_w(newskb, (*pskb)->sk);
-		kfree_skb(*pskb);
-		*pskb = newskb;
 	}
 
 	if (offset > (int)(*pskb)->len)
@@ -1256,17 +1223,17 @@ int __skb_linearize(struct sk_buff *skb, int gfp_mask)
 	return 0;
 }
 
-#define HARD_TX_LOCK_BH(dev, cpu) {			\
+#define HARD_TX_LOCK(dev, cpu) {			\
 	if ((dev->features & NETIF_F_LLTX) == 0) {	\
-		spin_lock_bh(&dev->xmit_lock);		\
+		spin_lock(&dev->xmit_lock);		\
 		dev->xmit_lock_owner = cpu;		\
 	}						\
 }
 
-#define HARD_TX_UNLOCK_BH(dev) {			\
+#define HARD_TX_UNLOCK(dev) {				\
 	if ((dev->features & NETIF_F_LLTX) == 0) {	\
 		dev->xmit_lock_owner = -1;		\
-		spin_unlock_bh(&dev->xmit_lock);	\
+		spin_unlock(&dev->xmit_lock);		\
 	}						\
 }
 
@@ -1320,7 +1287,12 @@ int dev_queue_xmit(struct sk_buff *skb)
 	      	if (skb_checksum_help(&skb, 0))
 	      		goto out_kfree_skb;
 
-	rcu_read_lock();
+
+	/* Disable soft irqs for various locks below. Also 
+	 * stops preemption for RCU. 
+	 */
+	local_bh_disable(); 
+
 	/* Updates of qdisc are serialized by queue_lock. 
 	 * The struct Qdisc which is pointed to by qdisc is now a 
 	 * rcu structure - it may be accessed without acquiring 
@@ -1333,25 +1305,22 @@ int dev_queue_xmit(struct sk_buff *skb)
 	 * also serializes access to the device queue.
 	 */
 
-	q = dev->qdisc;
-	smp_read_barrier_depends();
+	q = rcu_dereference(dev->qdisc);
 #ifdef CONFIG_NET_CLS_ACT
 	skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_EGRESS);
 #endif
 	if (q->enqueue) {
 		/* Grab device queue */
-		spin_lock_bh(&dev->queue_lock);
+		spin_lock(&dev->queue_lock);
 
 		rc = q->enqueue(skb, q);
 
 		qdisc_run(dev);
 
-		spin_unlock_bh(&dev->queue_lock);
-		rcu_read_unlock();
+		spin_unlock(&dev->queue_lock);
 		rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc;
 		goto out;
 	}
-	rcu_read_unlock();
 
 	/* The device has no queue. Common case for software devices:
 	   loopback, all the sorts of tunnels...
@@ -1366,12 +1335,11 @@ int dev_queue_xmit(struct sk_buff *skb)
 	   Either shot noqueue qdisc, it is even simpler 8)
 	 */
 	if (dev->flags & IFF_UP) {
-		int cpu = get_cpu();
+		int cpu = smp_processor_id(); /* ok because BHs are off */
 
 		if (dev->xmit_lock_owner != cpu) {
 
-			HARD_TX_LOCK_BH(dev, cpu);
-			put_cpu();
+			HARD_TX_LOCK(dev, cpu);
 
 			if (!netif_queue_stopped(dev)) {
 				if (netdev_nit)
@@ -1379,17 +1347,16 @@ int dev_queue_xmit(struct sk_buff *skb)
 
 				rc = 0;
 				if (!dev->hard_start_xmit(skb, dev)) {
-					HARD_TX_UNLOCK_BH(dev);
+					HARD_TX_UNLOCK(dev);
 					goto out;
 				}
 			}
-			HARD_TX_UNLOCK_BH(dev);
+			HARD_TX_UNLOCK(dev);
 			if (net_ratelimit())
 				printk(KERN_CRIT "Virtual device %s asks to "
 				       "queue packet!\n", dev->name);
 			goto out_enetdown;
 		} else {
-			put_cpu();
 			/* Recursion is detected! It is possible,
 			 * unfortunately */
 			if (net_ratelimit())
@@ -1402,6 +1369,7 @@ out_enetdown:
 out_kfree_skb:
 	kfree_skb(skb);
 out:
+	local_bh_enable();
 	return rc;
 }
 
@@ -1559,7 +1527,7 @@ int netif_rx(struct sk_buff *skb)
 	struct softnet_data *queue;
 	unsigned long flags;
 
-#ifdef CONFIG_NETPOLL_RX
+#ifdef CONFIG_NETPOLL
 	if (skb->dev->netpoll_rx && netpoll_rx(skb)) {
 		kfree_skb(skb);
 		return NET_RX_DROP;
@@ -1678,43 +1646,34 @@ static void net_tx_action(struct softirq_action *h)
 }
 
 static __inline__ int deliver_skb(struct sk_buff *skb,
-				  struct packet_type *pt_prev, int last)
+				  struct packet_type *pt_prev)
 {
 	atomic_inc(&skb->users);
 	return pt_prev->func(skb, skb->dev, pt_prev);
 }
 
-
 #if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE)
-int (*br_handle_frame_hook)(struct sk_buff *skb);
+int (*br_handle_frame_hook)(struct net_bridge_port *p, struct sk_buff **pskb);
 
-static __inline__ int handle_bridge(struct sk_buff *skb,
-				     struct packet_type *pt_prev)
+static __inline__ int handle_bridge(struct sk_buff **pskb,
+				    struct packet_type **pt_prev, int *ret)
 {
-	int ret = NET_RX_DROP;
-	if (pt_prev)
-		ret = deliver_skb(skb, pt_prev, 0);
+	struct net_bridge_port *port;
 
-	return ret;
-}
-
-#endif
-
-static inline int __handle_bridge(struct sk_buff *skb,
-			struct packet_type **pt_prev, int *ret)
-{
-#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
-	if (skb->dev->br_port && skb->pkt_type != PACKET_LOOPBACK) {
-		*ret = handle_bridge(skb, *pt_prev);
-		if (br_handle_frame_hook(skb) == 0)
-			return 1;
+	if ((*pskb)->pkt_type == PACKET_LOOPBACK ||
+	    (port = rcu_dereference((*pskb)->dev->br_port)) == NULL)
+		return 0;
 
+	if (*pt_prev) {
+		*ret = deliver_skb(*pskb, *pt_prev);
 		*pt_prev = NULL;
-	}
-#endif
-	return 0;
+	} 
+	
+	return br_handle_frame_hook(port, pskb);
 }
-
+#else
+#define handle_bridge(skb, pt_prev, ret)	(0)
+#endif
 
 #ifdef CONFIG_NET_CLS_ACT
 /* TODO: Maybe we should just force sch_ingress to be compiled in
@@ -1763,7 +1722,7 @@ int netif_receive_skb(struct sk_buff *skb)
 	int ret = NET_RX_DROP;
 	unsigned short type;
 
-#ifdef CONFIG_NETPOLL_RX
+#ifdef CONFIG_NETPOLL
 	if (skb->dev->netpoll_rx && skb->dev->poll && netpoll_rx(skb)) {
 		kfree_skb(skb);
 		return NET_RX_DROP;
@@ -1781,27 +1740,27 @@ int netif_receive_skb(struct sk_buff *skb)
 	skb->mac_len = skb->nh.raw - skb->mac.raw;
 
 	pt_prev = NULL;
+
+	rcu_read_lock();
+
 #ifdef CONFIG_NET_CLS_ACT
 	if (skb->tc_verd & TC_NCLS) {
 		skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
-		rcu_read_lock();
 		goto ncls;
 	}
- #endif
+#endif
 
-	rcu_read_lock();
 	list_for_each_entry_rcu(ptype, &ptype_all, list) {
 		if (!ptype->dev || ptype->dev == skb->dev) {
 			if (pt_prev) 
-				ret = deliver_skb(skb, pt_prev, 0);
+				ret = deliver_skb(skb, pt_prev);
 			pt_prev = ptype;
 		}
 	}
 
 #ifdef CONFIG_NET_CLS_ACT
 	if (pt_prev) {
-		atomic_inc(&skb->users);
-		ret = pt_prev->func(skb, skb->dev, pt_prev);
+		ret = deliver_skb(skb, pt_prev);
 		pt_prev = NULL; /* noone else should process this after*/
 	} else {
 		skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
@@ -1820,7 +1779,7 @@ ncls:
 
 	handle_diverter(skb);
 
-	if (__handle_bridge(skb, &pt_prev, &ret))
+	if (handle_bridge(&skb, &pt_prev, &ret))
 		goto out;
 
 	type = skb->protocol;
@@ -1828,7 +1787,7 @@ ncls:
 		if (ptype->type == type &&
 		    (!ptype->dev || ptype->dev == skb->dev)) {
 			if (pt_prev) 
-				ret = deliver_skb(skb, pt_prev, 0);
+				ret = deliver_skb(skb, pt_prev);
 			pt_prev = ptype;
 		}
 	}
@@ -2043,7 +2002,8 @@ static int dev_ifconf(char __user *arg)
 
 	total = 0;
 	for (dev = dev_base; dev; dev = dev->next) {
-		if (!dev_in_nx_info(dev, current->nx_info))
+		if (vx_flags(VXF_HIDE_NETIF, 0) &&
+			!dev_in_nx_info(dev, current->nx_info))
 			continue;
 		for (i = 0; i < NPROTO; i++) {
 			if (gifconf_list[i]) {
@@ -2107,7 +2067,7 @@ static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev)
 {
 	struct nx_info *nxi = current->nx_info;
 
-	if (!dev_in_nx_info(dev, nxi))
+	if (vx_flags(VXF_HIDE_NETIF, 0) && !dev_in_nx_info(dev, nxi))
 		return;
 	if (dev->get_stats) {
 		struct net_device_stats *stats = dev->get_stats(dev);
@@ -3287,6 +3247,8 @@ static int __init net_dev_init(void)
 
 	BUG_ON(!dev_boot_phase);
 
+	net_random_init();
+
 	if (dev_proc_init())
 		goto out;
 
@@ -3366,6 +3328,7 @@ EXPORT_SYMBOL(dev_remove_pack);
 EXPORT_SYMBOL(dev_set_allmulti);
 EXPORT_SYMBOL(dev_set_promiscuity);
 EXPORT_SYMBOL(dev_change_flags);
+EXPORT_SYMBOL(dev_change_name);
 EXPORT_SYMBOL(dev_set_mtu);
 EXPORT_SYMBOL(free_netdev);
 EXPORT_SYMBOL(netdev_boot_setup_check);
diff --git a/net/core/dv.c b/net/core/dv.c
index c1340cc53..05c76cb9c 100644
--- a/net/core/dv.c
+++ b/net/core/dv.c
@@ -450,12 +450,12 @@ int divert_ioctl(unsigned int cmd, struct divert_cf __user *arg)
  */
 
 #define	ETH_DIVERT_FRAME(skb) \
-	memcpy(skb->mac.ethernet, skb->dev->dev_addr, ETH_ALEN); \
+	memcpy(eth_hdr(skb), skb->dev->dev_addr, ETH_ALEN); \
 	skb->pkt_type=PACKET_HOST
 		
 void divert_frame(struct sk_buff *skb)
 {
-	struct ethhdr			*eth = skb->mac.ethernet;
+	struct ethhdr			*eth = eth_hdr(skb);
 	struct iphdr			*iph;
 	struct tcphdr			*tcph;
 	struct udphdr			*udph;
@@ -553,6 +553,3 @@ void divert_frame(struct sk_buff *skb)
 		break;
 	}
 }
-
-EXPORT_SYMBOL(alloc_divert_blk);
-EXPORT_SYMBOL(free_divert_blk);
diff --git a/net/core/filter.c b/net/core/filter.c
index 9c2a95080..f3b88205a 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -183,9 +183,10 @@ int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen)
 					continue;
 				}
 			} else {
-				u32 tmp;
-				if (!skb_copy_bits(skb, k, &tmp, 4)) {
-					A = ntohl(tmp);
+				u32 _tmp, *p;
+				p = skb_header_pointer(skb, k, 4, &_tmp);
+				if (p != NULL) {
+					A = ntohl(*p);
 					continue;
 				}
 			}
@@ -208,9 +209,10 @@ int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen)
 					continue;
 				}
 			} else {
-				u16 tmp;
-				if (!skb_copy_bits(skb, k, &tmp, 2)) {
-					A = ntohs(tmp);
+				u16 _tmp, *p;
+				p = skb_header_pointer(skb, k, 2, &_tmp);
+				if (p != NULL) {
+					A = ntohs(*p);
 					continue;
 				}
 			}
@@ -233,9 +235,10 @@ load_b:
 					continue;
 				}
 			} else {
-				u8 tmp;
-				if (!skb_copy_bits(skb, k, &tmp, 1)) {
-					A = tmp;
+				u8 _tmp, *p;
+				p = skb_header_pointer(skb, k, 1, &_tmp);
+				if (p != NULL) {
+					A = *p;
 					continue;
 				}
 			}
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index ee410cb7d..c9bd1b74f 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -12,6 +12,7 @@
  *
  *	Fixes:
  *	Vitaly E. Lavrov	releasing NULL neighbor in neigh_add.
+ *	Harald Welte		Add neighbour cache statistics like rtstat
  */
 
 #include <linux/config.h>
@@ -21,6 +22,7 @@
 #include <linux/socket.h>
 #include <linux/sched.h>
 #include <linux/netdevice.h>
+#include <linux/proc_fs.h>
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
 #endif
@@ -29,6 +31,7 @@
 #include <net/dst.h>
 #include <net/sock.h>
 #include <linux/rtnetlink.h>
+#include <linux/random.h>
 
 #define NEIGH_DEBUG 1
 
@@ -47,6 +50,8 @@
 #define NEIGH_PRINTK2 NEIGH_PRINTK
 #endif
 
+#define PNEIGH_HASHMASK		0xF
+
 static void neigh_timer_handler(unsigned long arg);
 #ifdef CONFIG_ARPD
 static void neigh_app_notify(struct neighbour *n);
@@ -56,6 +61,7 @@ void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev);
 
 static int neigh_glbl_allocs;
 static struct neigh_table *neigh_tables;
+static struct file_operations neigh_stat_seq_fops;
 
 /*
    Neighbour hash table buckets are protected with rwlock tbl->lock.
@@ -113,27 +119,21 @@ static int neigh_forced_gc(struct neigh_table *tbl)
 	int shrunk = 0;
 	int i;
 
-	for (i = 0; i <= NEIGH_HASHMASK; i++) {
+	NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
+
+	write_lock_bh(&tbl->lock);
+	for (i = 0; i <= tbl->hash_mask; i++) {
 		struct neighbour *n, **np;
 
 		np = &tbl->hash_buckets[i];
-		write_lock_bh(&tbl->lock);
 		while ((n = *np) != NULL) {
 			/* Neighbour record may be discarded if:
-			   - nobody refers to it.
-			   - it is not permanent
-			   - (NEW and probably wrong)
-			     INCOMPLETE entries are kept at least for
-			     n->parms->retrans_time, otherwise we could
-			     flood network with resolution requests.
-			     It is not clear, what is better table overflow
-			     or flooding.
+			 * - nobody refers to it.
+			 * - it is not permanent
 			 */
 			write_lock(&n->lock);
 			if (atomic_read(&n->refcnt) == 1 &&
-			    !(n->nud_state & NUD_PERMANENT) &&
-			    (n->nud_state != NUD_INCOMPLETE ||
-			     jiffies - n->used > n->parms->retrans_time)) {
+			    !(n->nud_state & NUD_PERMANENT)) {
 				*np	= n->next;
 				n->dead = 1;
 				shrunk	= 1;
@@ -144,10 +144,12 @@ static int neigh_forced_gc(struct neigh_table *tbl)
 			write_unlock(&n->lock);
 			np = &n->next;
 		}
-		write_unlock_bh(&tbl->lock);
 	}
 
 	tbl->last_flush = jiffies;
+
+	write_unlock_bh(&tbl->lock);
+
 	return shrunk;
 }
 
@@ -177,7 +179,7 @@ void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
 
 	write_lock_bh(&tbl->lock);
 
-	for (i=0; i <= NEIGH_HASHMASK; i++) {
+	for (i=0; i <= tbl->hash_mask; i++) {
 		struct neighbour *n, **np;
 
 		np = &tbl->hash_buckets[i];
@@ -204,7 +206,7 @@ int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
 
 	write_lock_bh(&tbl->lock);
 
-	for (i = 0; i <= NEIGH_HASHMASK; i++) {
+	for (i = 0; i <= tbl->hash_mask; i++) {
 		struct neighbour *n, **np = &tbl->hash_buckets[i];
 
 		while ((n = *np) != NULL) {
@@ -227,7 +229,6 @@ int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
 				   we must kill timers etc. and move
 				   it to safe state.
 				 */
-				n->parms = &tbl->parms;
 				skb_queue_purge(&n->arp_queue);
 				n->output = neigh_blackhole;
 				if (n->nud_state & NUD_VALID)
@@ -256,7 +257,7 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl)
 
 	if (tbl->entries > tbl->gc_thresh3 ||
 	    (tbl->entries > tbl->gc_thresh2 &&
-	     now - tbl->last_flush > 5 * HZ)) {
+	     time_after(now, tbl->last_flush + 5 * HZ))) {
 		if (!neigh_forced_gc(tbl) &&
 		    tbl->entries > tbl->gc_thresh3)
 			goto out;
@@ -273,11 +274,12 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl)
 	n->updated	  = n->used = now;
 	n->nud_state	  = NUD_NONE;
 	n->output	  = neigh_blackhole;
-	n->parms	  = &tbl->parms;
+	n->parms	  = neigh_parms_clone(&tbl->parms);
 	init_timer(&n->timer);
 	n->timer.function = neigh_timer_handler;
 	n->timer.data	  = (unsigned long)n;
-	tbl->stats.allocs++;
+
+	NEIGH_CACHE_STAT_INC(tbl, allocs);
 	neigh_glbl_allocs++;
 	tbl->entries++;
 	n->tbl		  = tbl;
@@ -287,17 +289,103 @@ out:
 	return n;
 }
 
+static struct neighbour **neigh_hash_alloc(unsigned int entries)
+{
+	unsigned long size = entries * sizeof(struct neighbour *);
+	struct neighbour **ret;
+
+	if (size <= PAGE_SIZE) {
+		ret = kmalloc(size, GFP_ATOMIC);
+	} else {
+		ret = (struct neighbour **)
+			__get_free_pages(GFP_ATOMIC, get_order(size));
+	}
+	if (ret)
+		memset(ret, 0, size);
+
+	return ret;
+}
+
+static void neigh_hash_free(struct neighbour **hash, unsigned int entries)
+{
+	unsigned long size = entries * sizeof(struct neighbour *);
+
+	if (size <= PAGE_SIZE)
+		kfree(hash);
+	else
+		free_pages((unsigned long)hash, get_order(size));
+}
+
+static void neigh_hash_grow(struct neigh_table *tbl, unsigned long new_entries)
+{
+	struct neighbour **new_hash, **old_hash;
+	unsigned int i, new_hash_mask, old_entries;
+
+	NEIGH_CACHE_STAT_INC(tbl, hash_grows);
+
+	BUG_ON(new_entries & (new_entries - 1));
+	new_hash = neigh_hash_alloc(new_entries);
+	if (!new_hash)
+		return;
+
+	old_entries = tbl->hash_mask + 1;
+	new_hash_mask = new_entries - 1;
+	old_hash = tbl->hash_buckets;
+
+	get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd));
+	for (i = 0; i < old_entries; i++) {
+		struct neighbour *n, *next;
+
+		for (n = old_hash[i]; n; n = next) {
+			unsigned int hash_val = tbl->hash(n->primary_key, n->dev);
+
+			hash_val &= new_hash_mask;
+			next = n->next;
+
+			n->next = new_hash[hash_val];
+			new_hash[hash_val] = n;
+		}
+	}
+	tbl->hash_buckets = new_hash;
+	tbl->hash_mask = new_hash_mask;
+
+	neigh_hash_free(old_hash, old_entries);
+}
+
 struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
 			       struct net_device *dev)
 {
 	struct neighbour *n;
 	int key_len = tbl->key_len;
-	u32 hash_val = tbl->hash(pkey, dev);
+	u32 hash_val = tbl->hash(pkey, dev) & tbl->hash_mask;
+	
+	NEIGH_CACHE_STAT_INC(tbl, lookups);
 
 	read_lock_bh(&tbl->lock);
 	for (n = tbl->hash_buckets[hash_val]; n; n = n->next) {
 		if (dev == n->dev && !memcmp(n->primary_key, pkey, key_len)) {
 			neigh_hold(n);
+			NEIGH_CACHE_STAT_INC(tbl, hits);
+			break;
+		}
+	}
+	read_unlock_bh(&tbl->lock);
+	return n;
+}
+
+struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, const void *pkey)
+{
+	struct neighbour *n;
+	int key_len = tbl->key_len;
+	u32 hash_val = tbl->hash(pkey, NULL) & tbl->hash_mask;
+
+	NEIGH_CACHE_STAT_INC(tbl, lookups);
+
+	read_lock_bh(&tbl->lock);
+	for (n = tbl->hash_buckets[hash_val]; n; n = n->next) {
+		if (!memcmp(n->primary_key, pkey, key_len)) {
+			neigh_hold(n);
+			NEIGH_CACHE_STAT_INC(tbl, hits);
 			break;
 		}
 	}
@@ -337,15 +425,23 @@ struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey,
 
 	n->confirmed = jiffies - (n->parms->base_reachable_time << 1);
 
-	hash_val = tbl->hash(pkey, dev);
-
 	write_lock_bh(&tbl->lock);
+
+	if (tbl->entries > (tbl->hash_mask + 1))
+		neigh_hash_grow(tbl, (tbl->hash_mask + 1) << 1);
+
+	hash_val = tbl->hash(pkey, dev) & tbl->hash_mask;
+
+	if (n->parms->dead) {
+		rc = ERR_PTR(-EINVAL);
+		goto out_tbl_unlock;
+	}
+
 	for (n1 = tbl->hash_buckets[hash_val]; n1; n1 = n1->next) {
 		if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) {
 			neigh_hold(n1);
-			write_unlock_bh(&tbl->lock);
 			rc = n1;
-			goto out_neigh_release;
+			goto out_tbl_unlock;
 		}
 	}
 
@@ -358,6 +454,8 @@ struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey,
 	rc = n;
 out:
 	return rc;
+out_tbl_unlock:
+	write_unlock_bh(&tbl->lock);
 out_neigh_release:
 	neigh_release(n);
 	goto out;
@@ -395,8 +493,12 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, const void *pkey,
 
 	memcpy(n->key, pkey, key_len);
 	n->dev = dev;
+	if (dev)
+		dev_hold(dev);
 
 	if (tbl->pconstructor && tbl->pconstructor(n)) {
+		if (dev)
+			dev_put(dev);
 		kfree(n);
 		n = NULL;
 		goto out;
@@ -423,18 +525,21 @@ int pneigh_delete(struct neigh_table *tbl, const void *pkey,
 	hash_val ^= hash_val >> 4;
 	hash_val &= PNEIGH_HASHMASK;
 
+	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) {
-			write_lock_bh(&tbl->lock);
 			*np = n->next;
 			write_unlock_bh(&tbl->lock);
 			if (tbl->pdestructor)
 				tbl->pdestructor(n);
+			if (n->dev)
+				dev_put(n->dev);
 			kfree(n);
 			return 0;
 		}
 	}
+	write_unlock_bh(&tbl->lock);
 	return -ENOENT;
 }
 
@@ -450,6 +555,8 @@ static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
 				*np = n->next;
 				if (tbl->pdestructor)
 					tbl->pdestructor(n);
+				if (n->dev)
+					dev_put(n->dev);
 				kfree(n);
 				continue;
 			}
@@ -468,6 +575,8 @@ void neigh_destroy(struct neighbour *neigh)
 {
 	struct hh_cache *hh;
 
+	NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
+
 	if (!neigh->dead) {
 		printk(KERN_WARNING
 		       "Destroying alive neighbour %p\n", neigh);
@@ -494,6 +603,7 @@ void neigh_destroy(struct neighbour *neigh)
 	skb_queue_purge(&neigh->arp_queue);
 
 	dev_put(neigh->dev);
+	neigh_parms_put(neigh->parms);
 
 	NEIGH_PRINTK2("neigh %p is destroyed.\n", neigh);
 
@@ -536,46 +646,13 @@ static void neigh_connect(struct neighbour *neigh)
 		hh->hh_output = neigh->ops->hh_output;
 }
 
-/*
-   Transitions NUD_STALE <-> NUD_REACHABLE do not occur
-   when fast path is built: we have no timers associated with
-   these states, we do not have time to check state when sending.
-   neigh_periodic_timer check periodically neigh->confirmed
-   time and moves NUD_REACHABLE -> NUD_STALE.
-
-   If a routine wants to know TRUE entry state, it calls
-   neigh_sync before checking state.
-
-   Called with write_locked neigh.
- */
-
-static void neigh_sync(struct neighbour *n)
-{
-	unsigned long now = jiffies;
-	u8 state = n->nud_state;
-
-	if (state & (NUD_NOARP | NUD_PERMANENT))
-		return;
-	if (state & NUD_REACHABLE) {
-		if (now - n->confirmed > n->parms->reachable_time) {
-			n->nud_state = NUD_STALE;
-			neigh_suspect(n);
-		}
-	} else if (state & NUD_VALID) {
-		if (now - n->confirmed < n->parms->reachable_time) {
-			neigh_del_timer(n);
-			n->nud_state = NUD_REACHABLE;
-			neigh_connect(n);
-		}
-	}
-}
-
 static void neigh_periodic_timer(unsigned long arg)
 {
 	struct neigh_table *tbl = (struct neigh_table *)arg;
-	unsigned long now = jiffies;
-	int i;
+	struct neighbour *n, **np;
+	unsigned long expire, now = jiffies;
 
+	NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
 
 	write_lock(&tbl->lock);
 
@@ -583,7 +660,7 @@ static void neigh_periodic_timer(unsigned long arg)
 	 *	periodically recompute ReachableTime from random function
 	 */
 
-	if (now - tbl->last_rand > 300 * HZ) {
+	if (time_after(now, tbl->last_rand + 300 * HZ)) {
 		struct neigh_parms *p;
 		tbl->last_rand = now;
 		for (p = &tbl->parms; p; p = p->next)
@@ -591,47 +668,49 @@ static void neigh_periodic_timer(unsigned long arg)
 				neigh_rand_reach_time(p->base_reachable_time);
 	}
 
-	for (i = 0; i <= NEIGH_HASHMASK; i++) {
-		struct neighbour *n, **np;
-
-		np = &tbl->hash_buckets[i];
-		while ((n = *np) != NULL) {
-			unsigned state;
+	np = &tbl->hash_buckets[tbl->hash_chain_gc];
+	tbl->hash_chain_gc = ((tbl->hash_chain_gc + 1) & tbl->hash_mask);
 
-			write_lock(&n->lock);
+	while ((n = *np) != NULL) {
+		unsigned int state;
 
-			state = n->nud_state;
-			if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
-				write_unlock(&n->lock);
-				goto next_elt;
-			}
+		write_lock(&n->lock);
 
-			if ((long)(n->used - n->confirmed) < 0)
-				n->used = n->confirmed;
+		state = n->nud_state;
+		if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
+			write_unlock(&n->lock);
+			goto next_elt;
+		}
 
-			if (atomic_read(&n->refcnt) == 1 &&
-			    (state == NUD_FAILED ||
-			     now - n->used > n->parms->gc_staletime)) {
-				*np = n->next;
-				n->dead = 1;
-				write_unlock(&n->lock);
-				neigh_release(n);
-				continue;
-			}
+		if (time_before(n->used, n->confirmed))
+			n->used = n->confirmed;
 
-			if (n->nud_state & NUD_REACHABLE &&
-			    now - n->confirmed > n->parms->reachable_time) {
-				n->nud_state = NUD_STALE;
-				neigh_suspect(n);
-			}
+		if (atomic_read(&n->refcnt) == 1 &&
+		    (state == NUD_FAILED ||
+		     time_after(now, n->used + n->parms->gc_staletime))) {
+			*np = n->next;
+			n->dead = 1;
 			write_unlock(&n->lock);
+			neigh_release(n);
+			continue;
+		}
+		write_unlock(&n->lock);
 
 next_elt:
-			np = &n->next;
-		}
+		np = &n->next;
 	}
 
-	mod_timer(&tbl->gc_timer, now + tbl->gc_interval);
+ 	/* Cycle through all hash buckets every base_reachable_time/2 ticks.
+ 	 * ARP entry timeouts range from 1/2 base_reachable_time to 3/2
+ 	 * base_reachable_time.
+	 */
+	expire = tbl->parms.base_reachable_time >> 1;
+	expire /= (tbl->hash_mask + 1);
+	if (!expire)
+		expire = 1;
+
+ 	mod_timer(&tbl->gc_timer, now + expire);
+
 	write_unlock(&tbl->lock);
 }
 
@@ -648,7 +727,7 @@ static __inline__ int neigh_max_probes(struct neighbour *n)
 
 static void neigh_timer_handler(unsigned long arg)
 {
-	unsigned long now = jiffies;
+	unsigned long now, next;
 	struct neighbour *neigh = (struct neighbour *)arg;
 	unsigned state;
 	int notify = 0;
@@ -656,6 +735,8 @@ static void neigh_timer_handler(unsigned long arg)
 	write_lock(&neigh->lock);
 
 	state = neigh->nud_state;
+	now = jiffies;
+	next = now + HZ;
 
 	if (!(state & NUD_IN_TIMER)) {
 #ifndef CONFIG_SMP
@@ -664,25 +745,47 @@ static void neigh_timer_handler(unsigned long arg)
 		goto out;
 	}
 
-	if ((state & NUD_VALID) &&
-	    now - neigh->confirmed < neigh->parms->reachable_time) {
-		neigh->nud_state = NUD_REACHABLE;
-		NEIGH_PRINTK2("neigh %p is still alive.\n", neigh);
-		neigh_connect(neigh);
-		goto out;
-	}
-	if (state == NUD_DELAY) {
-		NEIGH_PRINTK2("neigh %p is probed.\n", neigh);
-		neigh->nud_state = NUD_PROBE;
-		atomic_set(&neigh->probes, 0);
+	if (state & NUD_REACHABLE) {
+		if (time_before_eq(now, 
+				   neigh->confirmed + neigh->parms->reachable_time)) {
+			NEIGH_PRINTK2("neigh %p is still alive.\n", neigh);
+			next = neigh->confirmed + neigh->parms->reachable_time;
+		} else if (time_before_eq(now,
+					  neigh->used + neigh->parms->delay_probe_time)) {
+			NEIGH_PRINTK2("neigh %p is delayed.\n", neigh);
+			neigh->nud_state = NUD_DELAY;
+			neigh_suspect(neigh);
+			next = now + neigh->parms->delay_probe_time;
+		} else {
+			NEIGH_PRINTK2("neigh %p is suspected.\n", neigh);
+			neigh->nud_state = NUD_STALE;
+			neigh_suspect(neigh);
+		}
+	} else if (state & NUD_DELAY) {
+		if (time_before_eq(now, 
+				   neigh->confirmed + neigh->parms->delay_probe_time)) {
+			NEIGH_PRINTK2("neigh %p is now reachable.\n", neigh);
+			neigh->nud_state = NUD_REACHABLE;
+			neigh_connect(neigh);
+			next = neigh->confirmed + neigh->parms->reachable_time;
+		} else {
+			NEIGH_PRINTK2("neigh %p is probed.\n", neigh);
+			neigh->nud_state = NUD_PROBE;
+			atomic_set(&neigh->probes, 0);
+			next = now + neigh->parms->retrans_time;
+		}
+	} else {
+		/* NUD_PROBE|NUD_INCOMPLETE */
+		next = now + neigh->parms->retrans_time;
 	}
 
-	if (atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
+	if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
+	    atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
 		struct sk_buff *skb;
 
 		neigh->nud_state = NUD_FAILED;
 		notify = 1;
-		neigh->tbl->stats.res_failed++;
+		NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
 		NEIGH_PRINTK2("neigh %p is failed.\n", neigh);
 
 		/* It is very thin place. report_unreachable is very complicated
@@ -697,19 +800,30 @@ static void neigh_timer_handler(unsigned long arg)
 			write_lock(&neigh->lock);
 		}
 		skb_queue_purge(&neigh->arp_queue);
-		goto out;
 	}
 
-	neigh->timer.expires = now + neigh->parms->retrans_time;
-	add_timer(&neigh->timer);
-	write_unlock(&neigh->lock);
-
-	neigh->ops->solicit(neigh, skb_peek(&neigh->arp_queue));
-	atomic_inc(&neigh->probes);
-	return;
-
+	if (neigh->nud_state & NUD_IN_TIMER) {
+		neigh_hold(neigh);
+		if (time_before(next, jiffies + HZ/2))
+			next = jiffies + HZ/2;
+		neigh->timer.expires = next;
+		add_timer(&neigh->timer);
+	}
+	if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
+		struct sk_buff *skb = skb_peek(&neigh->arp_queue);
+		/* keep skb alive even if arp_queue overflows */
+		if (skb)
+			skb_get(skb);
+		write_unlock(&neigh->lock);
+		neigh->ops->solicit(neigh, skb);
+		atomic_inc(&neigh->probes);
+		if (skb)
+			kfree_skb(skb);
+	} else {
 out:
-	write_unlock(&neigh->lock);
+		write_unlock(&neigh->lock);
+	}
+
 #ifdef CONFIG_ARPD
 	if (notify && neigh->parms->app_probes)
 		neigh_app_notify(neigh);
@@ -720,6 +834,7 @@ out:
 int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
 {
 	int rc;
+	unsigned long now;
 
 	write_lock_bh(&neigh->lock);
 
@@ -727,18 +842,15 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
 	if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
 		goto out_unlock_bh;
 
+	now = jiffies;
+	
 	if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
 		if (neigh->parms->mcast_probes + neigh->parms->app_probes) {
 			atomic_set(&neigh->probes, neigh->parms->ucast_probes);
 			neigh->nud_state     = NUD_INCOMPLETE;
 			neigh_hold(neigh);
-			neigh->timer.expires = jiffies +
-					       neigh->parms->retrans_time;
+			neigh->timer.expires = now + 1;
 			add_timer(&neigh->timer);
-			write_unlock_bh(&neigh->lock);
-			neigh->ops->solicit(neigh, skb);
-			atomic_inc(&neigh->probes);
-			write_lock_bh(&neigh->lock);
 		} else {
 			neigh->nud_state = NUD_FAILED;
 			write_unlock_bh(&neigh->lock);
@@ -747,6 +859,12 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
 				kfree_skb(skb);
 			return 1;
 		}
+	} else if (neigh->nud_state & NUD_STALE) {
+		NEIGH_PRINTK2("neigh %p is delayed.\n", neigh);
+		neigh_hold(neigh);
+		neigh->nud_state = NUD_DELAY;
+		neigh->timer.expires = jiffies + neigh->parms->delay_probe_time;
+		add_timer(&neigh->timer);
 	}
 
 	if (neigh->nud_state == NUD_INCOMPLETE) {
@@ -761,13 +879,6 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
 			__skb_queue_tail(&neigh->arp_queue, skb);
 		}
 		rc = 1;
-	} else if (neigh->nud_state == NUD_STALE) {
-		NEIGH_PRINTK2("neigh %p is delayed.\n", neigh);
-		neigh_hold(neigh);
-		neigh->nud_state = NUD_DELAY;
-		neigh->timer.expires = jiffies + neigh->parms->delay_probe_time;
-		add_timer(&neigh->timer);
-		rc = 0;
 	}
 out_unlock_bh:
 	write_unlock_bh(&neigh->lock);
@@ -794,14 +905,26 @@ static __inline__ void neigh_update_hhs(struct neighbour *neigh)
 /* Generic update routine.
    -- lladdr is new lladdr or NULL, if it is not supplied.
    -- new    is new state.
-   -- override == 1 allows to override existing lladdr, if it is different.
-   -- arp == 0 means that the change is administrative.
+   -- flags
+	NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
+				if it is different.
+	NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
+				lladdr instead of overriding it 
+				if it is different.
+				It also allows to retain current state
+				if lladdr is unchanged.
+	NEIGH_UPDATE_F_ADMIN	means that the change is administrative.
+
+	NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing 
+				NTF_ROUTER flag.
+	NEIGH_UPDATE_F_ISROUTER	indicates if the neighbour is known as
+				a router.
 
    Caller MUST hold reference count on the entry.
  */
 
 int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
-		 int override, int arp)
+		 u32 flags)
 {
 	u8 old;
 	int err;
@@ -809,6 +932,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
 	int notify = 0;
 #endif
 	struct net_device *dev;
+	int update_isrouter = 0;
 
 	write_lock_bh(&neigh->lock);
 
@@ -816,7 +940,8 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
 	old    = neigh->nud_state;
 	err    = -EPERM;
 
-	if (arp && (old & (NUD_NOARP | NUD_PERMANENT)))
+	if (!(flags & NEIGH_UPDATE_F_ADMIN) && 
+	    (old & (NUD_NOARP | NUD_PERMANENT)))
 		goto out;
 
 	if (!(new & NUD_VALID)) {
@@ -841,12 +966,9 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
 		   - compare new & old
 		   - if they are different, check override flag
 		 */
-		if (old & NUD_VALID) {
-			if (!memcmp(lladdr, neigh->ha, dev->addr_len))
-				lladdr = neigh->ha;
-			else if (!override)
-				goto out;
-		}
+		if ((old & NUD_VALID) && 
+		    !memcmp(lladdr, neigh->ha, dev->addr_len))
+			lladdr = neigh->ha;
 	} else {
 		/* No address is supplied; if we know something,
 		   use it, otherwise discard the request.
@@ -857,8 +979,6 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
 		lladdr = neigh->ha;
 	}
 
-	neigh_sync(neigh);
-	old = neigh->nud_state;
 	if (new & NUD_CONNECTED)
 		neigh->confirmed = jiffies;
 	neigh->updated = jiffies;
@@ -867,12 +987,37 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
 	   do not change entry state, if new one is STALE.
 	 */
 	err = 0;
-	if ((old & NUD_VALID) && lladdr == neigh->ha &&
-	    (new == old || (new == NUD_STALE && (old & NUD_CONNECTED))))
-		goto out;
+	update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
+	if (old & NUD_VALID) {
+		if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
+			update_isrouter = 0;
+			if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
+			    (old & NUD_CONNECTED)) {
+				lladdr = neigh->ha;
+				new = NUD_STALE;
+			} else
+				goto out;
+		} else {
+			if (lladdr == neigh->ha && new == NUD_STALE &&
+			    ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) ||
+			     (old & NUD_CONNECTED))
+			    )
+				new = old;
+		}
+	}
+
+	if (new != old) {
+		neigh_del_timer(neigh);
+		if (new & NUD_IN_TIMER) {
+			neigh_hold(neigh);
+			neigh->timer.expires = jiffies + 
+						((new & NUD_REACHABLE) ? 
+						 neigh->parms->reachable_time : 0);
+			add_timer(&neigh->timer);
+		}
+		neigh->nud_state = new;
+	}
 
-	neigh_del_timer(neigh);
-	neigh->nud_state = new;
 	if (lladdr != neigh->ha) {
 		memcpy(&neigh->ha, lladdr, dev->addr_len);
 		neigh_update_hhs(neigh);
@@ -907,6 +1052,11 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
 		skb_queue_purge(&neigh->arp_queue);
 	}
 out:
+	if (update_isrouter) {
+		neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
+			(neigh->flags | NTF_ROUTER) :
+			(neigh->flags & ~NTF_ROUTER);
+	}
 	write_unlock_bh(&neigh->lock);
 #ifdef CONFIG_ARPD
 	if (notify && neigh->parms->app_probes)
@@ -922,7 +1072,8 @@ struct neighbour *neigh_event_ns(struct neigh_table *tbl,
 	struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
 						 lladdr || !dev->addr_len);
 	if (neigh)
-		neigh_update(neigh, lladdr, NUD_STALE, 1, 1);
+		neigh_update(neigh, lladdr, NUD_STALE, 
+			     NEIGH_UPDATE_F_OVERRIDE);
 	return neigh;
 }
 
@@ -1088,26 +1239,25 @@ void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
 		    struct sk_buff *skb)
 {
 	unsigned long now = jiffies;
-	long sched_next = net_random() % p->proxy_delay;
+	unsigned long sched_next = now + (net_random() % p->proxy_delay);
 
 	if (tbl->proxy_queue.qlen > p->proxy_qlen) {
 		kfree_skb(skb);
 		return;
 	}
 	skb->stamp.tv_sec  = LOCALLY_ENQUEUED;
-	skb->stamp.tv_usec = now + sched_next;
+	skb->stamp.tv_usec = sched_next;
 
 	spin_lock(&tbl->proxy_queue.lock);
 	if (del_timer(&tbl->proxy_timer)) {
-		long tval = tbl->proxy_timer.expires - now;
-		if (tval < sched_next)
-			sched_next = tval;
+		if (time_before(tbl->proxy_timer.expires, sched_next))
+			sched_next = tbl->proxy_timer.expires;
 	}
 	dst_release(skb->dst);
 	skb->dst = NULL;
 	dev_hold(skb->dev);
 	__skb_queue_tail(&tbl->proxy_queue, skb);
-	mod_timer(&tbl->proxy_timer, now + sched_next);
+	mod_timer(&tbl->proxy_timer, sched_next);
 	spin_unlock(&tbl->proxy_queue.lock);
 }
 
@@ -1120,6 +1270,8 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
 	if (p) {
 		memcpy(p, &tbl->parms, sizeof(*p));
 		p->tbl		  = tbl;
+		atomic_set(&p->refcnt, 1);
+		INIT_RCU_HEAD(&p->rcu_head);
 		p->reachable_time =
 				neigh_rand_reach_time(p->base_reachable_time);
 		if (dev && dev->neigh_setup && dev->neigh_setup(dev, p)) {
@@ -1135,6 +1287,14 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
 	return p;
 }
 
+static void neigh_rcu_free_parms(struct rcu_head *head)
+{
+	struct neigh_parms *parms =
+		container_of(head, struct neigh_parms, rcu_head);
+
+	neigh_parms_put(parms);
+}
+
 void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
 {
 	struct neigh_parms **p;
@@ -1145,8 +1305,9 @@ void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
 	for (p = &tbl->parms.next; *p; p = &(*p)->next) {
 		if (*p == parms) {
 			*p = parms->next;
+			parms->dead = 1;
 			write_unlock_bh(&tbl->lock);
-			kfree(parms);
+			call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
 			return;
 		}
 	}
@@ -1154,11 +1315,19 @@ void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
 	NEIGH_PRINTK1("neigh_parms_release: not found\n");
 }
 
+void neigh_parms_destroy(struct neigh_parms *parms)
+{
+	kfree(parms);
+}
+
 
 void neigh_table_init(struct neigh_table *tbl)
 {
 	unsigned long now = jiffies;
+	unsigned long phsize;
 
+	atomic_set(&tbl->parms.refcnt, 1);
+	INIT_RCU_HEAD(&tbl->parms.rcu_head);
 	tbl->parms.reachable_time =
 			  neigh_rand_reach_time(tbl->parms.base_reachable_time);
 
@@ -1171,12 +1340,36 @@ void neigh_table_init(struct neigh_table *tbl)
 	if (!tbl->kmem_cachep)
 		panic("cannot create neighbour cache");
 
+	tbl->stats = alloc_percpu(struct neigh_statistics);
+	if (!tbl->stats)
+		panic("cannot create neighbour cache statistics");
+	
+#ifdef CONFIG_PROC_FS
+	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;
+	tbl->pde->data = tbl;
+#endif
+
+	tbl->hash_mask = 1;
+	tbl->hash_buckets = neigh_hash_alloc(tbl->hash_mask + 1);
+
+	phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
+	tbl->phash_buckets = kmalloc(phsize, GFP_KERNEL);
+
+	if (!tbl->hash_buckets || !tbl->phash_buckets)
+		panic("cannot allocate neighbour cache hashes");
+
+	memset(tbl->phash_buckets, 0, phsize);
+
+	get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd));
+
 	tbl->lock	       = RW_LOCK_UNLOCKED;
 	init_timer(&tbl->gc_timer);
 	tbl->gc_timer.data     = (unsigned long)tbl;
 	tbl->gc_timer.function = neigh_periodic_timer;
-	tbl->gc_timer.expires  = now + tbl->gc_interval +
-				 tbl->parms.reachable_time;
+	tbl->gc_timer.expires  = now + 1;
 	add_timer(&tbl->gc_timer);
 
 	init_timer(&tbl->proxy_timer);
@@ -1211,6 +1404,13 @@ int neigh_table_clear(struct neigh_table *tbl)
 		}
 	}
 	write_unlock(&neigh_tbl_lock);
+
+	neigh_hash_free(tbl->hash_buckets, tbl->hash_mask + 1);
+	tbl->hash_buckets = NULL;
+
+	kfree(tbl->phash_buckets);
+	tbl->phash_buckets = NULL;
+
 	return 0;
 }
 
@@ -1250,7 +1450,9 @@ int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 
 		n = neigh_lookup(tbl, RTA_DATA(nda[NDA_DST - 1]), dev);
 		if (n) {
-			err = neigh_update(n, NULL, NUD_FAILED, 1, 0);
+			err = neigh_update(n, NULL, NUD_FAILED, 
+					   NEIGH_UPDATE_F_OVERRIDE|
+					   NEIGH_UPDATE_F_ADMIN);
 			neigh_release(n);
 		}
 		goto out_dev_put;
@@ -1323,7 +1525,8 @@ int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 						RTA_DATA(nda[NDA_LLADDR - 1]) :
 						NULL,
 					   ndm->ndm_state,
-					   override, 0);
+					   (override ? NEIGH_UPDATE_F_OVERRIDE : 0) |
+					   NEIGH_UPDATE_F_ADMIN);
 		}
 		if (n)
 			neigh_release(n);
@@ -1387,7 +1590,7 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
 	int rc, h, s_h = cb->args[1];
 	int idx, s_idx = idx = cb->args[2];
 
-	for (h = 0; h <= NEIGH_HASHMASK; h++) {
+	for (h = 0; h <= tbl->hash_mask; h++) {
 		if (h < s_h)
 			continue;
 		if (h > s_h)
@@ -1437,6 +1640,366 @@ int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
 	return skb->len;
 }
 
+void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
+{
+	int chain;
+
+	read_lock_bh(&tbl->lock);
+	for (chain = 0; chain <= tbl->hash_mask; chain++) {
+		struct neighbour *n;
+
+		for (n = tbl->hash_buckets[chain]; n; n = n->next)
+			cb(n, cookie);
+	}
+	read_unlock_bh(&tbl->lock);
+}
+EXPORT_SYMBOL(neigh_for_each);
+
+/* The tbl->lock must be held as a writer and BH disabled. */
+void __neigh_for_each_release(struct neigh_table *tbl,
+			      int (*cb)(struct neighbour *))
+{
+	int chain;
+
+	for (chain = 0; chain <= tbl->hash_mask; chain++) {
+		struct neighbour *n, **np;
+
+		np = &tbl->hash_buckets[chain];
+		while ((n = *np) != NULL) {
+			int release;
+
+			write_lock(&n->lock);
+			release = cb(n);
+			if (release) {
+				*np = n->next;
+				n->dead = 1;
+			} else
+				np = &n->next;
+			write_unlock(&n->lock);
+			if (release)
+				neigh_release(n);
+		}
+	}
+}
+EXPORT_SYMBOL(__neigh_for_each_release);
+
+#ifdef CONFIG_PROC_FS
+
+static struct neighbour *neigh_get_first(struct seq_file *seq)
+{
+	struct neigh_seq_state *state = seq->private;
+	struct neigh_table *tbl = state->tbl;
+	struct neighbour *n = NULL;
+	int bucket = state->bucket;
+
+	state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
+	for (bucket = 0; bucket <= tbl->hash_mask; bucket++) {
+		n = tbl->hash_buckets[bucket];
+
+		while (n) {
+			if (state->neigh_sub_iter) {
+				loff_t fakep = 0;
+				void *v;
+
+				v = state->neigh_sub_iter(state, n, &fakep);
+				if (!v)
+					goto next;
+			}
+			if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
+				break;
+			if (n->nud_state & ~NUD_NOARP)
+				break;
+		next:
+			n = n->next;
+		}
+
+		if (n)
+			break;
+	}
+	state->bucket = bucket;
+
+	return n;
+}
+
+static struct neighbour *neigh_get_next(struct seq_file *seq,
+					struct neighbour *n,
+					loff_t *pos)
+{
+	struct neigh_seq_state *state = seq->private;
+	struct neigh_table *tbl = state->tbl;
+
+	if (state->neigh_sub_iter) {
+		void *v = state->neigh_sub_iter(state, n, pos);
+		if (v)
+			return n;
+	}
+	n = n->next;
+
+	while (1) {
+		while (n) {
+			if (state->neigh_sub_iter) {
+				void *v = state->neigh_sub_iter(state, n, pos);
+				if (v)
+					return n;
+				goto next;
+			}
+			if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
+				break;
+
+			if (n->nud_state & ~NUD_NOARP)
+				break;
+		next:
+			n = n->next;
+		}
+
+		if (n)
+			break;
+
+		if (++state->bucket > tbl->hash_mask)
+			break;
+
+		n = tbl->hash_buckets[state->bucket];
+	}
+
+	if (n && pos)
+		--(*pos);
+	return n;
+}
+
+static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
+{
+	struct neighbour *n = neigh_get_first(seq);
+
+	if (n) {
+		while (*pos) {
+			n = neigh_get_next(seq, n, pos);
+			if (!n)
+				break;
+		}
+	}
+	return *pos ? NULL : n;
+}
+
+static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
+{
+	struct neigh_seq_state *state = seq->private;
+	struct neigh_table *tbl = state->tbl;
+	struct pneigh_entry *pn = NULL;
+	int bucket = state->bucket;
+
+	state->flags |= NEIGH_SEQ_IS_PNEIGH;
+	for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
+		pn = tbl->phash_buckets[bucket];
+		if (pn)
+			break;
+	}
+	state->bucket = bucket;
+
+	return pn;
+}
+
+static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
+					    struct pneigh_entry *pn,
+					    loff_t *pos)
+{
+	struct neigh_seq_state *state = seq->private;
+	struct neigh_table *tbl = state->tbl;
+
+	pn = pn->next;
+	while (!pn) {
+		if (++state->bucket > PNEIGH_HASHMASK)
+			break;
+		pn = tbl->phash_buckets[state->bucket];
+		if (pn)
+			break;
+	}
+
+	if (pn && pos)
+		--(*pos);
+
+	return pn;
+}
+
+static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
+{
+	struct pneigh_entry *pn = pneigh_get_first(seq);
+
+	if (pn) {
+		while (*pos) {
+			pn = pneigh_get_next(seq, pn, pos);
+			if (!pn)
+				break;
+		}
+	}
+	return *pos ? NULL : pn;
+}
+
+static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
+{
+	struct neigh_seq_state *state = seq->private;
+	void *rc;
+
+	rc = neigh_get_idx(seq, pos);
+	if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
+		rc = pneigh_get_idx(seq, pos);
+
+	return rc;
+}
+
+void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl, unsigned int neigh_seq_flags)
+{
+	struct neigh_seq_state *state = seq->private;
+	loff_t pos_minus_one;
+
+	state->tbl = tbl;
+	state->bucket = 0;
+	state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
+
+	read_lock_bh(&tbl->lock);
+
+	pos_minus_one = *pos - 1;
+	return *pos ? neigh_get_idx_any(seq, &pos_minus_one) : SEQ_START_TOKEN;
+}
+EXPORT_SYMBOL(neigh_seq_start);
+
+void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct neigh_seq_state *state;
+	void *rc;
+
+	if (v == SEQ_START_TOKEN) {
+		rc = neigh_get_idx(seq, pos);
+		goto out;
+	}
+
+	state = seq->private;
+	if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
+		rc = neigh_get_next(seq, v, NULL);
+		if (rc)
+			goto out;
+		if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
+			rc = pneigh_get_first(seq);
+	} else {
+		BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
+		rc = pneigh_get_next(seq, v, NULL);
+	}
+out:
+	++(*pos);
+	return rc;
+}
+EXPORT_SYMBOL(neigh_seq_next);
+
+void neigh_seq_stop(struct seq_file *seq, void *v)
+{
+	struct neigh_seq_state *state = seq->private;
+	struct neigh_table *tbl = state->tbl;
+
+	read_unlock_bh(&tbl->lock);
+}
+EXPORT_SYMBOL(neigh_seq_stop);
+
+/* statistics via seq_file */
+
+static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	struct proc_dir_entry *pde = seq->private;
+	struct neigh_table *tbl = pde->data;
+	int cpu;
+
+	if (*pos == 0)
+		return SEQ_START_TOKEN;
+	
+	for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) {
+		if (!cpu_possible(cpu))
+			continue;
+		*pos = cpu+1;
+		return per_cpu_ptr(tbl->stats, cpu);
+	}
+	return NULL;
+}
+
+static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct proc_dir_entry *pde = seq->private;
+	struct neigh_table *tbl = pde->data;
+	int cpu;
+
+	for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
+		if (!cpu_possible(cpu))
+			continue;
+		*pos = cpu+1;
+		return per_cpu_ptr(tbl->stats, cpu);
+	}
+	return NULL;
+}
+
+static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
+{
+
+}
+
+static int neigh_stat_seq_show(struct seq_file *seq, void *v)
+{
+	struct proc_dir_entry *pde = seq->private;
+	struct neigh_table *tbl = pde->data;
+	struct neigh_statistics *st = v;
+
+	if (v == SEQ_START_TOKEN) {
+		seq_printf(seq, "entries  allocs destroys hash_grows  lookups hits  res_failed  rcv_probes_mcast rcv_probes_ucast  periodic_gc_runs forced_gc_runs forced_gc_goal_miss\n");
+		return 0;
+	}
+
+	seq_printf(seq, "%08x  %08lx %08lx %08lx  %08lx %08lx  %08lx  "
+			"%08lx %08lx  %08lx %08lx\n",
+		   tbl->entries,
+
+		   st->allocs,
+		   st->destroys,
+		   st->hash_grows,
+
+		   st->lookups,
+		   st->hits,
+
+		   st->res_failed,
+
+		   st->rcv_probes_mcast,
+		   st->rcv_probes_ucast,
+
+		   st->periodic_gc_runs,
+		   st->forced_gc_runs
+		   );
+
+	return 0;
+}
+
+static struct seq_operations neigh_stat_seq_ops = {
+	.start	= neigh_stat_seq_start,
+	.next	= neigh_stat_seq_next,
+	.stop	= neigh_stat_seq_stop,
+	.show	= neigh_stat_seq_show,
+};
+
+static int neigh_stat_seq_open(struct inode *inode, struct file *file)
+{
+	int ret = seq_open(file, &neigh_stat_seq_ops);
+
+	if (!ret) {
+		struct seq_file *sf = file->private_data;
+		sf->private = PDE(inode);
+	}
+	return ret;
+};
+
+static struct file_operations neigh_stat_seq_fops = {
+	.owner	 = THIS_MODULE,
+	.open 	 = neigh_stat_seq_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = seq_release,
+};
+
+#endif /* CONFIG_PROC_FS */
+
 #ifdef CONFIG_ARPD
 void neigh_app_ns(struct neighbour *n)
 {
@@ -1733,6 +2296,7 @@ EXPORT_SYMBOL(neigh_dump_info);
 EXPORT_SYMBOL(neigh_event_ns);
 EXPORT_SYMBOL(neigh_ifdown);
 EXPORT_SYMBOL(neigh_lookup);
+EXPORT_SYMBOL(neigh_lookup_nodev);
 EXPORT_SYMBOL(neigh_parms_alloc);
 EXPORT_SYMBOL(neigh_parms_release);
 EXPORT_SYMBOL(neigh_rand_reach_time);
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 46d26fc92..6cf0afc7b 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -408,7 +408,6 @@ int netdev_register_sysfs(struct net_device *net)
 
 	class_dev->class = &net_class;
 	class_dev->class_data = net;
-	net->last_stats = net->get_stats;
 
 	strlcpy(class_dev->class_id, net->name, BUS_ID_SIZE);
 	if ((ret = class_device_register(class_dev)))
diff --git a/net/core/netfilter.c b/net/core/netfilter.c
index 58632d189..91b3bb238 100644
--- a/net/core/netfilter.c
+++ b/net/core/netfilter.c
@@ -695,11 +695,12 @@ int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
 	/* DaveM says protocol headers are also modifiable. */
 	switch ((*pskb)->nh.iph->protocol) {
 	case IPPROTO_TCP: {
-		struct tcphdr hdr;
-		if (skb_copy_bits(*pskb, (*pskb)->nh.iph->ihl*4,
-				  &hdr, sizeof(hdr)) != 0)
+		struct tcphdr _hdr, *hp;
+		hp = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl*4,
+					sizeof(_hdr), &_hdr);
+		if (hp == NULL)
 			goto copy_skb;
-		if (writable_len <= (*pskb)->nh.iph->ihl*4 + hdr.doff*4)
+		if (writable_len <= (*pskb)->nh.iph->ihl*4 + hp->doff*4)
 			goto pull_skb;
 		goto copy_skb;
 	}
@@ -783,13 +784,12 @@ void nf_log_packet(int pf,
 	nf_logfn *logfn;
 	
 	rcu_read_lock();
-	logfn = nf_logging[pf];
+	logfn = rcu_dereference(nf_logging[pf]);
 	if (logfn) {
 		va_start(args, fmt);
 		vsnprintf(prefix, sizeof(prefix), fmt, args);
 		va_end(args);
 		/* We must read logging before nf_logfn[pf] */
-		smp_read_barrier_depends();
 		logfn(hooknum, skb, in, out, prefix);
 	} else if (!reported) {
 		printk(KERN_WARNING "nf_log_packet: can\'t log yet, "
@@ -806,7 +806,7 @@ EXPORT_SYMBOL(nf_log_packet);
    tracking in use: without this, connection may not be in hash table,
    and hence manufactured ICMP or RST packets will not be associated
    with it. */
-void (*ip_ct_attach)(struct sk_buff *, struct nf_ct_info *);
+void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *);
 
 void __init netfilter_init(void)
 {
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index daac16887..cb3a03fb1 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -18,8 +18,10 @@
 #include <linux/interrupt.h>
 #include <linux/netpoll.h>
 #include <linux/sched.h>
+#include <linux/rcupdate.h>
 #include <net/tcp.h>
 #include <net/udp.h>
+#include <asm/unaligned.h>
 
 /*
  * We maintain a small pool of fully-sized skbs, to make sure the
@@ -36,7 +38,11 @@ static struct sk_buff *skbs;
 static spinlock_t rx_list_lock = SPIN_LOCK_UNLOCKED;
 static LIST_HEAD(rx_list);
 
-static int trapped;
+static atomic_t trapped;
+spinlock_t netpoll_poll_lock = SPIN_LOCK_UNLOCKED;
+
+#define NETPOLL_RX_ENABLED  1
+#define NETPOLL_RX_DROP     2
 
 #define MAX_SKB_SIZE \
 		(MAX_UDP_CHUNK + sizeof(struct udphdr) + \
@@ -61,7 +67,14 @@ static int checksum_udp(struct sk_buff *skb, struct udphdr *uh,
 
 void netpoll_poll(struct netpoll *np)
 {
-	int budget = 1;
+	/*
+	 * In cases where there is bi-directional communications, reading
+	 * only one message at a time can lead to packets being dropped by
+	 * the network adapter, forcing superfluous retries and possibly
+	 * timeouts.  Thus, we set our budget to a more reasonable value.
+	 */
+	int budget = 16;
+	unsigned long flags;
 
 	if(!np->dev || !netif_running(np->dev) || !np->dev->poll_controller)
 		return;
@@ -70,9 +83,19 @@ void netpoll_poll(struct netpoll *np)
 	np->dev->poll_controller(np->dev);
 
 	/* If scheduling is stopped, tickle NAPI bits */
-	if(trapped && np->dev->poll &&
-	   test_bit(__LINK_STATE_RX_SCHED, &np->dev->state))
+	spin_lock_irqsave(&netpoll_poll_lock, flags);
+	if (np->dev->poll &&
+	    test_bit(__LINK_STATE_RX_SCHED, &np->dev->state)) {
+		np->dev->netpoll_rx |= NETPOLL_RX_DROP;
+		atomic_inc(&trapped);
+
 		np->dev->poll(np->dev, &budget);
+
+		atomic_dec(&trapped);
+		np->dev->netpoll_rx &= ~NETPOLL_RX_DROP;
+	}
+	spin_unlock_irqrestore(&netpoll_poll_lock, flags);
+
 	zap_completion_queue();
 }
 
@@ -168,6 +191,18 @@ repeat:
 	spin_lock(&np->dev->xmit_lock);
 	np->dev->xmit_lock_owner = smp_processor_id();
 
+	/*
+	 * network drivers do not expect to be called if the queue is
+	 * stopped.
+	 */
+	if (netif_queue_stopped(np->dev)) {
+		np->dev->xmit_lock_owner = -1;
+		spin_unlock(&np->dev->xmit_lock);
+
+		netpoll_poll(np);
+		goto repeat;
+	}
+
 	status = np->dev->hard_start_xmit(skb, np->dev);
 	np->dev->xmit_lock_owner = -1;
 	spin_unlock(&np->dev->xmit_lock);
@@ -206,17 +241,17 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
 
 	iph = (struct iphdr *)skb_push(skb, sizeof(*iph));
 
-	iph->version  = 4;
-	iph->ihl      = 5;
+	/* iph->version = 4; iph->ihl = 5; */
+	put_unaligned(0x45, (unsigned char *)iph);
 	iph->tos      = 0;
-	iph->tot_len  = htons(ip_len);
+	put_unaligned(htons(ip_len), &(iph->tot_len));
 	iph->id       = 0;
 	iph->frag_off = 0;
 	iph->ttl      = 64;
 	iph->protocol = IPPROTO_UDP;
 	iph->check    = 0;
-	iph->saddr    = htonl(np->local_ip);
-	iph->daddr    = htonl(np->remote_ip);
+	put_unaligned(htonl(np->local_ip), &(iph->saddr));
+	put_unaligned(htonl(np->remote_ip), &(iph->daddr));
 	iph->check    = ip_fast_csum((unsigned char *)iph, iph->ihl);
 
 	eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
@@ -337,12 +372,13 @@ int netpoll_rx(struct sk_buff *skb)
 		goto out;
 
 	/* check if netpoll clients need ARP */
-	if (skb->protocol == __constant_htons(ETH_P_ARP) && trapped) {
+	if (skb->protocol == __constant_htons(ETH_P_ARP) &&
+	    atomic_read(&trapped)) {
 		arp_reply(skb);
 		return 1;
 	}
 
-	proto = ntohs(skb->mac.ethernet->h_proto);
+	proto = ntohs(eth_hdr(skb)->h_proto);
 	if (proto != ETH_P_IP)
 		goto out;
 	if (skb->pkt_type == PACKET_OTHERHOST)
@@ -400,7 +436,7 @@ int netpoll_rx(struct sk_buff *skb)
 	spin_unlock_irqrestore(&rx_list_lock, flags);
 
 out:
-	return trapped;
+	return atomic_read(&trapped);
 }
 
 int netpoll_parse_options(struct netpoll *np, char *opt)
@@ -572,16 +608,18 @@ int netpoll_setup(struct netpoll *np)
 		memcpy(np->local_mac, ndev->dev_addr, 6);
 
 	if (!np->local_ip) {
-		in_dev = in_dev_get(ndev);
+		rcu_read_lock();
+		in_dev = __in_dev_get(ndev);
 
 		if (!in_dev) {
+			rcu_read_unlock();
 			printk(KERN_ERR "%s: no IP address for %s, aborting\n",
 			       np->name, np->dev_name);
 			goto release;
 		}
 
 		np->local_ip = ntohl(in_dev->ifa_list->ifa_local);
-		in_dev_put(in_dev);
+		rcu_read_unlock();
 		printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n",
 		       np->name, HIPQUAD(np->local_ip));
 	}
@@ -591,9 +629,7 @@ int netpoll_setup(struct netpoll *np)
 	if(np->rx_hook) {
 		unsigned long flags;
 
-#ifdef CONFIG_NETPOLL_RX
-		np->dev->netpoll_rx = 1;
-#endif
+		np->dev->netpoll_rx = NETPOLL_RX_ENABLED;
 
 		spin_lock_irqsave(&rx_list_lock, flags);
 		list_add(&np->rx_list, &rx_list);
@@ -608,29 +644,31 @@ int netpoll_setup(struct netpoll *np)
 
 void netpoll_cleanup(struct netpoll *np)
 {
-	if(np->rx_hook) {
+	if (np->rx_hook) {
 		unsigned long flags;
 
 		spin_lock_irqsave(&rx_list_lock, flags);
 		list_del(&np->rx_list);
-#ifdef CONFIG_NETPOLL_RX
-		np->dev->netpoll_rx = 0;
-#endif
 		spin_unlock_irqrestore(&rx_list_lock, flags);
 	}
 
+	if (np->dev)
+		np->dev->netpoll_rx = 0;
 	dev_put(np->dev);
 	np->dev = NULL;
 }
 
 int netpoll_trap(void)
 {
-	return trapped;
+	return atomic_read(&trapped);
 }
 
 void netpoll_set_trap(int trap)
 {
-	trapped = trap;
+	if (trap)
+		atomic_inc(&trapped);
+	else
+		atomic_dec(&trapped);
 }
 
 EXPORT_SYMBOL(netpoll_set_trap);
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index d1a62cddb..1d1c5451f 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -52,6 +52,9 @@
  *
  * Fixed unaligned access on IA-64 Grant Grundler <grundler@parisc-linux.org>
  *
+ * New xmit() return, do_div and misc clean up by Stephen Hemminger 
+ * <shemminger@osdl.org> 040923
+ *
  * See Documentation/networking/pktgen.txt for how to use this.
  */
 
@@ -70,6 +73,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/inet.h>
+#include <linux/rcupdate.h>
 #include <asm/byteorder.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -93,7 +97,7 @@
 
 #define VERSION "pktgen version 1.32"
 static char version[] __initdata = 
-  "pktgen.c: v1.3: Packet Generator for packet performance testing.\n";
+  "pktgen.c: v1.4: Packet Generator for packet performance testing.\n";
 
 /* Used to help with determining the pkts on receive */
 
@@ -263,14 +267,17 @@ static struct net_device *setup_inject(struct pktgen_info* info)
 	info->saddr_min = 0;
 	info->saddr_max = 0;
 	if (strlen(info->src_min) == 0) {
-		struct in_device *in_dev = in_dev_get(odev);
+		struct in_device *in_dev;
+
+		rcu_read_lock();
+		in_dev = __in_dev_get(odev);
 		if (in_dev) {
 			if (in_dev->ifa_list) {
 				info->saddr_min = in_dev->ifa_list->ifa_address;
 				info->saddr_max = info->saddr_min;
 			}
-			in_dev_put(in_dev);
 		}
+		rcu_read_unlock();
 	}
 	else {
 		info->saddr_min = in_aton(info->src_min);
@@ -580,15 +587,48 @@ static struct sk_buff *fill_packet(struct net_device *odev, struct pktgen_info*
 	return skb;
 }
 
+static void show_results(struct pktgen_info* info, int nr_frags)
+{
+	__u64 total, bps, mbps, pps;
+	unsigned long idle;
+	int size = info->pkt_size + 4; /* incl 32bit ethernet CRC */
+	char *p = info->result;
+
+	total = (info->stopped_at.tv_sec - info->started_at.tv_sec) * 1000000ull
+		+ info->stopped_at.tv_usec - info->started_at.tv_usec;
+
+	BUG_ON(cpu_speed == 0);
+
+	idle = info->idle_acc;
+	do_div(idle, cpu_speed);
+
+	p += sprintf(p, "OK: %llu(c%llu+d%lu) usec, %llu (%dbyte,%dfrags)\n",
+		     total, total - idle, idle,
+		     info->sofar, size, nr_frags);
+
+	pps = info->sofar * USEC_PER_SEC;
+	
+	while ((total >> 32) != 0) {
+		pps >>= 1;
+		total >>= 1;
+	}
+
+	do_div(pps, total);
+	
+	bps = pps * 8 * size;
+
+	mbps = bps;
+	do_div(mbps, 1000000);
+	p += sprintf(p, "  %llupps %lluMb/sec (%llubps) errors: %llu",
+		     pps, mbps, bps, info->errors);
+}
 
 static void inject(struct pktgen_info* info)
 {
-	struct net_device *odev = NULL;
+	struct net_device *odev;
 	struct sk_buff *skb = NULL;
-	__u64 total = 0;
-	__u64 idle = 0;
 	__u64 lcount = 0;
-	int nr_frags = 0;
+	int ret;
 	int last_ok = 1;	   /* Was last skb sent? 
 				    * Or a failed transmit of some sort?  This will keep
 				    * sequence numbers in order, for example.
@@ -628,35 +668,38 @@ static void inject(struct pktgen_info* info)
 			}
 		}
 
-		nr_frags = skb_shinfo(skb)->nr_frags;
-		   
-		spin_lock_bh(&odev->xmit_lock);
+		if (!(odev->features & NETIF_F_LLTX))
+			spin_lock_bh(&odev->xmit_lock);
 		if (!netif_queue_stopped(odev)) {
 
 			atomic_inc(&skb->users);
 
-			if (odev->hard_start_xmit(skb, odev)) {
-
+		retry:
+			ret = odev->hard_start_xmit(skb, odev);
+			if (likely(ret == NETDEV_TX_OK)) {
+				last_ok = 1;	
+				info->sofar++;
+				info->seq_num++;
+			} else if (ret == NETDEV_TX_LOCKED 
+				   && (odev->features & NETIF_F_LLTX)) {
+				cpu_relax();
+				goto retry;
+			} else {
 				atomic_dec(&skb->users);
-				if (net_ratelimit()) {
+				if (debug && net_ratelimit()) {
 				   printk(KERN_INFO "Hard xmit error\n");
 				}
 				info->errors++;
 				last_ok = 0;
 			}
-			else {
-			   last_ok = 1;	
-			   info->sofar++;
-			   info->seq_num++;
-			}
 		}
 		else {
 			/* Re-try it next time */
 			last_ok = 0;
 		}
 		
-
-		spin_unlock_bh(&odev->xmit_lock);
+		if (!(odev->features & NETIF_F_LLTX))
+			spin_unlock_bh(&odev->xmit_lock);
 
 		if (info->ipg) {
 			/* Try not to busy-spin if we have larger sleep times.
@@ -720,38 +763,7 @@ static void inject(struct pktgen_info* info)
 
 	do_gettimeofday(&(info->stopped_at));
 
-	total = (info->stopped_at.tv_sec - info->started_at.tv_sec) * 1000000 +
-		info->stopped_at.tv_usec - info->started_at.tv_usec;
-
-	idle = (__u32)(info->idle_acc)/(__u32)(cpu_speed);
-
-	{
-		char *p = info->result;
-		__u64 bps, pps = 0;
-
-		if (total > 1000)
-			pps = (__u32)(info->sofar * 1000) / ((__u32)(total) / 1000);
-		else if(total > 100)
-			pps = (__u32)(info->sofar * 10000) / ((__u32)(total) / 100);
-		else if(total > 10)
-			pps = (__u32)(info->sofar * 100000) / ((__u32)(total) / 10);
-		else if(total > 1)
-			pps = (__u32)(info->sofar * 1000000) / (__u32)total;
-
-		bps = pps * 8 * (info->pkt_size + 4); /* take 32bit ethernet CRC into account */
-		p += sprintf(p, "OK: %llu(c%llu+d%llu) usec, %llu (%dbyte,%dfrags) %llupps %lluMb/sec (%llubps)  errors: %llu",
-			     (unsigned long long) total,
-			     (unsigned long long) (total - idle),
-			     (unsigned long long) idle,
-			     (unsigned long long) info->sofar,
-			     skb->len + 4, /* Add 4 to account for the ethernet checksum */
-			     nr_frags,
-			     (unsigned long long) pps,
-			     (unsigned long long) (bps / (u64) 1024 / (u64) 1024),
-			     (unsigned long long) bps,
-			     (unsigned long long) info->errors
-			     );
-	}
+	show_results(info, skb_shinfo(skb)->nr_frags);
 
 	kfree_skb(skb);
 
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 9afe9d13d..2a8e28941 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -166,31 +166,58 @@ static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
 	r->ifi_family = AF_UNSPEC;
 	r->ifi_type = dev->type;
 	r->ifi_index = dev->ifindex;
-	r->ifi_flags = dev->flags;
+	r->ifi_flags = dev_get_flags(dev);
 	r->ifi_change = change;
 
-	if (!netif_running(dev) || !netif_carrier_ok(dev))
-		r->ifi_flags &= ~IFF_RUNNING;
-	else
-		r->ifi_flags |= IFF_RUNNING;
-
 	RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name);
+
+	if (1) {
+		u32 txqlen = dev->tx_queue_len;
+		RTA_PUT(skb, IFLA_TXQLEN, sizeof(txqlen), &txqlen);
+	}
+
+	if (1) {
+		u32 weight = dev->weight;
+		RTA_PUT(skb, IFLA_WEIGHT, sizeof(weight), &weight);
+	}
+
+	if (1) {
+		struct rtnl_link_ifmap map = {
+			.mem_start   = dev->mem_start,
+			.mem_end     = dev->mem_end,
+			.base_addr   = dev->base_addr,
+			.irq         = dev->irq,
+			.dma         = dev->dma,
+			.port        = dev->if_port,
+		};
+		RTA_PUT(skb, IFLA_MAP, sizeof(map), &map);
+	}
+
 	if (dev->addr_len) {
 		RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
 		RTA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast);
 	}
+
 	if (1) {
-		unsigned mtu = dev->mtu;
+		u32 mtu = dev->mtu;
 		RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu);
 	}
-	if (dev->ifindex != dev->iflink)
-		RTA_PUT(skb, IFLA_LINK, sizeof(int), &dev->iflink);
+
+	if (dev->ifindex != dev->iflink) {
+		u32 iflink = dev->iflink;
+		RTA_PUT(skb, IFLA_LINK, sizeof(iflink), &iflink);
+	}
+
 	if (dev->qdisc_sleeping)
 		RTA_PUT(skb, IFLA_QDISC,
 			strlen(dev->qdisc_sleeping->ops->id) + 1,
 			dev->qdisc_sleeping->ops->id);
-	if (dev->master)
-		RTA_PUT(skb, IFLA_MASTER, sizeof(int), &dev->master->ifindex);
+	
+	if (dev->master) {
+		u32 master = dev->master->ifindex;
+		RTA_PUT(skb, IFLA_MASTER, sizeof(master), &master);
+	}
+
 	if (dev->get_stats) {
 		unsigned long *stats = (unsigned long*)dev->get_stats(dev);
 		if (stats) {
@@ -224,7 +251,8 @@ int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
 	for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
 		if (idx < s_idx)
 			continue;
-		if (!dev_in_nx_info(dev, current->nx_info))
+		if (vx_info_flags(skb->sk->sk_vx_info, VXF_HIDE_NETIF, 0) &&
+			!dev_in_nx_info(dev, skb->sk->sk_nx_info))
 			continue;
 		if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, 0) <= 0)
 			break;
@@ -240,7 +268,7 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 	struct ifinfomsg  *ifm = NLMSG_DATA(nlh);
 	struct rtattr    **ida = arg;
 	struct net_device *dev;
-	int err;
+	int err, send_addr_notify = 0;
 
 	dev = dev_get_by_index(ifm->ifi_index);
 	if (!dev)
@@ -248,6 +276,41 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 
 	err = -EINVAL;
 
+	if (ifm->ifi_flags)
+		dev_change_flags(dev, ifm->ifi_flags);
+
+	if (ida[IFLA_MAP - 1]) {
+		struct rtnl_link_ifmap *u_map;
+		struct ifmap k_map;
+
+		if (!dev->set_config) {
+			err = -EOPNOTSUPP;
+			goto out;
+		}
+
+		if (!netif_device_present(dev)) {
+			err = -ENODEV;
+			goto out;
+		}
+		
+		if (ida[IFLA_MAP - 1]->rta_len != RTA_LENGTH(sizeof(*u_map)))
+			goto out;
+
+		u_map = RTA_DATA(ida[IFLA_MAP - 1]);
+
+		k_map.mem_start = (unsigned long) u_map->mem_start;
+		k_map.mem_end = (unsigned long) u_map->mem_end;
+		k_map.base_addr = (unsigned short) u_map->base_addr;
+		k_map.irq = (unsigned char) u_map->irq;
+		k_map.dma = (unsigned char) u_map->dma;
+		k_map.port = (unsigned char) u_map->port;
+
+		err = dev->set_config(dev, &k_map);
+
+		if (err)
+			goto out;
+	}
+
 	if (ida[IFLA_ADDRESS - 1]) {
 		if (!dev->set_mac_address) {
 			err = -EOPNOTSUPP;
@@ -263,6 +326,7 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 		err = dev->set_mac_address(dev, RTA_DATA(ida[IFLA_ADDRESS - 1]));
 		if (err)
 			goto out;
+		send_addr_notify = 1;
 	}
 
 	if (ida[IFLA_BROADCAST - 1]) {
@@ -270,12 +334,54 @@ static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 			goto out;
 		memcpy(dev->broadcast, RTA_DATA(ida[IFLA_BROADCAST - 1]),
 		       dev->addr_len);
+		send_addr_notify = 1;
+	}
+
+	if (ida[IFLA_MTU - 1]) {
+		if (ida[IFLA_MTU - 1]->rta_len != RTA_LENGTH(sizeof(u32)))
+			goto out;
+		err = dev_set_mtu(dev, *((u32 *) RTA_DATA(ida[IFLA_MTU - 1])));
+
+		if (err)
+			goto out;
+
+	}
+
+	if (ida[IFLA_TXQLEN - 1]) {
+		if (ida[IFLA_TXQLEN - 1]->rta_len != RTA_LENGTH(sizeof(u32)))
+			goto out;
+
+		dev->tx_queue_len = *((u32 *) RTA_DATA(ida[IFLA_TXQLEN - 1]));
+	}
+
+	if (ida[IFLA_WEIGHT - 1]) {
+		if (ida[IFLA_WEIGHT - 1]->rta_len != RTA_LENGTH(sizeof(u32)))
+			goto out;
+
+		dev->weight = *((u32 *) RTA_DATA(ida[IFLA_WEIGHT - 1]));
+	}
+
+	if (ida[IFLA_IFNAME - 1]) {
+		char ifname[IFNAMSIZ];
+
+		if (ida[IFLA_IFNAME - 1]->rta_len > RTA_LENGTH(sizeof(ifname)))
+			goto out;
+
+		memset(ifname, 0, sizeof(ifname));
+		memcpy(ifname, RTA_DATA(ida[IFLA_IFNAME - 1]),
+			RTA_PAYLOAD(ida[IFLA_IFNAME - 1]));
+		ifname[IFNAMSIZ - 1] = '\0';
+
+		err = dev_change_name(dev, ifname);
+
+		if (err)
+			goto out;
 	}
 
 	err = 0;
 
 out:
-	if (!err)
+	if (send_addr_notify)
 		call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
 
 	dev_put(dev);
@@ -309,9 +415,12 @@ static int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
 void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
 {
 	struct sk_buff *skb;
-	int size = NLMSG_GOODSIZE;
+	int size = NLMSG_SPACE(sizeof(struct ifinfomsg) +
+			       sizeof(struct rtnl_link_ifmap) +
+			       sizeof(struct rtnl_link_stats) + 128);
 
-	if (!dev_in_nx_info(dev, current->nx_info))
+	if (vx_flags(VXF_HIDE_NETIF, 0) &&
+		!dev_in_nx_info(dev, current->nx_info))
 		return;
 	skb = alloc_skb(size, GFP_KERNEL);
 	if (!skb)
@@ -330,6 +439,10 @@ static int rtnetlink_done(struct netlink_callback *cb)
 	return 0;
 }
 
+/* Protected by RTNL sempahore.  */
+static struct rtattr **rta_buf;
+static int rtattr_max;
+
 /* Process one rtnetlink message. */
 
 static __inline__ int
@@ -337,8 +450,6 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp)
 {
 	struct rtnetlink_link *link;
 	struct rtnetlink_link *link_tab;
-	struct rtattr	*rta[RTATTR_MAX];
-
 	int sz_idx, kind;
 	int min_len;
 	int family;
@@ -405,7 +516,7 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp)
 		return -1;
 	}
 
-	memset(&rta, 0, sizeof(rta));
+	memset(rta_buf, 0, (rtattr_max * sizeof(struct rtattr *)));
 
 	min_len = rtm_min[sz_idx];
 	if (nlh->nlmsg_len < min_len)
@@ -420,7 +531,7 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp)
 			if (flavor) {
 				if (flavor > rta_max[sz_idx])
 					goto err_inval;
-				rta[flavor-1] = attr;
+				rta_buf[flavor-1] = attr;
 			}
 			attr = RTA_NEXT(attr, attrlen);
 		}
@@ -430,7 +541,7 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp)
 		link = &(rtnetlink_links[PF_UNSPEC][type]);
 	if (link->doit == NULL)
 		goto err_inval;
-	err = link->doit(skb, nlh, (void *)&rta);
+	err = link->doit(skb, nlh, (void *)&rta_buf[0]);
 
 	*errp = err;
 	return err;
@@ -550,6 +661,16 @@ static struct notifier_block rtnetlink_dev_notifier = {
 
 void __init rtnetlink_init(void)
 {
+	int i;
+
+	rtattr_max = 0;
+	for (i = 0; i < ARRAY_SIZE(rta_max); i++)
+		if (rta_max[i] > rtattr_max)
+			rtattr_max = rta_max[i];
+	rta_buf = kmalloc(rtattr_max * sizeof(struct rtattr *), GFP_KERNEL);
+	if (!rta_buf)
+		panic("rtnetlink_init: cannot allocate rta_buf\n");
+
 	rtnl = netlink_kernel_create(NETLINK_ROUTE, rtnetlink_rcv);
 	if (rtnl == NULL)
 		panic("rtnetlink_init: cannot initialize rtnetlink\n");
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index c34a3a9db..f7749294a 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -311,6 +311,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, int gfp_mask)
 	C(nfcache);
 	C(nfct);
 	nf_conntrack_get(skb->nfct);
+	C(nfctinfo);
 #ifdef CONFIG_NETFILTER_DEBUG
 	C(nf_debug);
 #endif
@@ -377,6 +378,7 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
 	new->nfcache	= old->nfcache;
 	new->nfct	= old->nfct;
 	nf_conntrack_get(old->nfct);
+	new->nfctinfo	= old->nfctinfo;
 #ifdef CONFIG_NETFILTER_DEBUG
 	new->nf_debug	= old->nf_debug;
 #endif
diff --git a/net/core/sock.c b/net/core/sock.c
index d5b2d9105..3e23eed56 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1356,6 +1356,27 @@ void sk_common_release(struct sock *sk)
 
 EXPORT_SYMBOL(sk_common_release);
 
+int sk_alloc_slab(struct proto *prot, char *name)
+{
+	prot->slab = kmem_cache_create(name,
+				       prot->slab_obj_size, 0,
+				       SLAB_HWCACHE_ALIGN, NULL, NULL);
+
+	return prot->slab != NULL ? 0 : -ENOBUFS;
+}
+
+EXPORT_SYMBOL(sk_alloc_slab);
+
+void sk_free_slab(struct proto *prot)
+{
+	if (prot->slab != NULL) {
+		kmem_cache_destroy(prot->slab);
+		prot->slab = NULL;
+	}
+}
+
+EXPORT_SYMBOL(sk_free_slab);
+
 EXPORT_SYMBOL(__lock_sock);
 EXPORT_SYMBOL(__release_sock);
 EXPORT_SYMBOL(sk_alloc);
diff --git a/net/core/utils.c b/net/core/utils.c
index 8058d9c5e..e11a8654f 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -19,23 +19,125 @@
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/types.h>
+#include <linux/random.h>
+#include <linux/percpu.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
-static unsigned long net_rand_seed = 152L;
+
+/*
+  This is a maximally equidistributed combined Tausworthe generator
+  based on code from GNU Scientific Library 1.5 (30 Jun 2004)
+
+   x_n = (s1_n ^ s2_n ^ s3_n) 
+
+   s1_{n+1} = (((s1_n & 4294967294) <<12) ^ (((s1_n <<13) ^ s1_n) >>19))
+   s2_{n+1} = (((s2_n & 4294967288) << 4) ^ (((s2_n << 2) ^ s2_n) >>25))
+   s3_{n+1} = (((s3_n & 4294967280) <<17) ^ (((s3_n << 3) ^ s3_n) >>11))
+
+   The period of this generator is about 2^88.
+
+   From: P. L'Ecuyer, "Maximally Equidistributed Combined Tausworthe
+   Generators", Mathematics of Computation, 65, 213 (1996), 203--213.
+
+   This is available on the net from L'Ecuyer's home page,
+
+   http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps
+   ftp://ftp.iro.umontreal.ca/pub/simulation/lecuyer/papers/tausme.ps 
+
+   There is an erratum in the paper "Tables of Maximally
+   Equidistributed Combined LFSR Generators", Mathematics of
+   Computation, 68, 225 (1999), 261--269:
+   http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps
+
+        ... the k_j most significant bits of z_j must be non-
+        zero, for each j. (Note: this restriction also applies to the 
+        computer code given in [4], but was mistakenly not mentioned in
+        that paper.)
+   
+   This affects the seeding procedure by imposing the requirement
+   s1 > 1, s2 > 7, s3 > 15.
+
+*/
+struct nrnd_state {
+	u32 s1, s2, s3;
+};
+
+static DEFINE_PER_CPU(struct nrnd_state, net_rand_state);
+
+static u32 __net_random(struct nrnd_state *state)
+{
+#define TAUSWORTHE(s,a,b,c,d) ((s&c)<<d) ^ (((s <<a) ^ s)>>b)
+
+	state->s1 = TAUSWORTHE(state->s1, 13, 19, 4294967294UL, 12);
+	state->s2 = TAUSWORTHE(state->s2, 2, 25, 4294967288UL, 4);
+	state->s3 = TAUSWORTHE(state->s3, 3, 11, 4294967280UL, 17);
+
+	return (state->s1 ^ state->s2 ^ state->s3);
+}
+
+static void __net_srandom(struct nrnd_state *state, unsigned long s)
+{
+	if (s == 0)
+		s = 1;      /* default seed is 1 */
+
+#define LCG(n) (69069 * n)
+	state->s1 = LCG(s);
+	state->s2 = LCG(state->s1);
+	state->s3 = LCG(state->s2);
+
+	/* "warm it up" */
+	__net_random(state);
+	__net_random(state);
+	__net_random(state);
+	__net_random(state);
+	__net_random(state);
+	__net_random(state);
+}
+
 
 unsigned long net_random(void)
 {
-	net_rand_seed=net_rand_seed*69069L+1;
-        return net_rand_seed^jiffies;
+	unsigned long r;
+	struct nrnd_state *state = &get_cpu_var(net_rand_state);
+	r = __net_random(state);
+	put_cpu_var(state);
+	return r;
 }
 
+
 void net_srandom(unsigned long entropy)
 {
-	net_rand_seed ^= entropy;
-	net_random();
+	struct nrnd_state *state = &get_cpu_var(net_rand_state);
+	__net_srandom(state, state->s1^entropy);
+	put_cpu_var(state);
+}
+
+void __init net_random_init(void)
+{
+	int i;
+
+	for (i = 0; i < NR_CPUS; i++) {
+		struct nrnd_state *state = &per_cpu(net_rand_state,i);
+		__net_srandom(state, i+jiffies);
+	}
+}
+
+static int net_random_reseed(void)
+{
+	int i;
+	unsigned long seed[NR_CPUS];
+
+	get_random_bytes(seed, sizeof(seed));
+	for (i = 0; i < NR_CPUS; i++) {
+		struct nrnd_state *state = &per_cpu(net_rand_state,i);
+		__net_srandom(state, seed[i]);
+	}
+	return 0;
 }
+late_initcall(net_random_reseed);
 
 int net_msg_cost = 5*HZ;
 int net_msg_burst = 10;
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index 11b0f0c6d..a21a32680 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -41,6 +41,7 @@
 #include <linux/sysctl.h>
 #include <linux/notifier.h>
 #include <asm/uaccess.h>
+#include <asm/system.h>
 #include <net/neighbour.h>
 #include <net/dst.h>
 #include <net/flow.h>
@@ -247,21 +248,6 @@ static struct dn_dev_sysctl_table {
 	}, {0}}
 };
 
-static inline __u16 mtu2blksize(struct net_device *dev)
-{
-	u32 blksize = dev->mtu;
-	if (blksize > 0xffff)
-		blksize = 0xffff;
-
-	if (dev->type == ARPHRD_ETHER ||
-	    dev->type == ARPHRD_PPP ||
-	    dev->type == ARPHRD_IPGRE ||
-	    dev->type == ARPHRD_LOOPBACK)
-		blksize -= 2;
-
-	return (__u16)blksize;
-}
-
 static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *parms)
 {
 	struct dn_dev_sysctl_table *t;
@@ -314,52 +300,6 @@ static void dn_dev_sysctl_unregister(struct dn_dev_parms *parms)
 	}
 }
 
-struct net_device *dn_dev_get_default(void)
-{
-	struct net_device *dev;
-	read_lock(&dndev_lock);
-	dev = decnet_default_device;
-	if (dev) {
-		if (dev->dn_ptr)
-			dev_hold(dev);
-		else
-			dev = NULL;
-	}
-	read_unlock(&dndev_lock);
-	return dev;
-}
-
-int dn_dev_set_default(struct net_device *dev, int force)
-{
-	struct net_device *old = NULL;
-	int rv = -EBUSY;
-	if (!dev->dn_ptr)
-		return -ENODEV;
-	write_lock(&dndev_lock);
-	if (force || decnet_default_device == NULL) {
-		old = decnet_default_device;
-		decnet_default_device = dev;
-		rv = 0;
-	}
-	write_unlock(&dndev_lock);
-	if (old)
-		dev_put(dev);
-	return rv;
-}
-
-static void dn_dev_check_default(struct net_device *dev)
-{
-	write_lock(&dndev_lock);
-	if (dev == decnet_default_device) {
-		decnet_default_device = NULL;
-	} else {
-		dev = NULL;
-	}
-	write_unlock(&dndev_lock);
-	if (dev)
-		dev_put(dev);
-}
-
 static int dn_forwarding_proc(ctl_table *table, int write, 
 				struct file *filep,
 				void __user *buffer,
@@ -454,6 +394,21 @@ static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *
 
 #endif /* CONFIG_SYSCTL */
 
+static inline __u16 mtu2blksize(struct net_device *dev)
+{
+	u32 blksize = dev->mtu;
+	if (blksize > 0xffff)
+		blksize = 0xffff;
+
+	if (dev->type == ARPHRD_ETHER ||
+	    dev->type == ARPHRD_PPP ||
+	    dev->type == ARPHRD_IPGRE ||
+	    dev->type == ARPHRD_LOOPBACK)
+		blksize -= 2;
+
+	return (__u16)blksize;
+}
+
 static struct dn_ifaddr *dn_dev_alloc_ifa(void)
 {
 	struct dn_ifaddr *ifa;
@@ -635,6 +590,52 @@ rarok:
 	goto done;
 }
 
+struct net_device *dn_dev_get_default(void)
+{
+	struct net_device *dev;
+	read_lock(&dndev_lock);
+	dev = decnet_default_device;
+	if (dev) {
+		if (dev->dn_ptr)
+			dev_hold(dev);
+		else
+			dev = NULL;
+	}
+	read_unlock(&dndev_lock);
+	return dev;
+}
+
+int dn_dev_set_default(struct net_device *dev, int force)
+{
+	struct net_device *old = NULL;
+	int rv = -EBUSY;
+	if (!dev->dn_ptr)
+		return -ENODEV;
+	write_lock(&dndev_lock);
+	if (force || decnet_default_device == NULL) {
+		old = decnet_default_device;
+		decnet_default_device = dev;
+		rv = 0;
+	}
+	write_unlock(&dndev_lock);
+	if (old)
+		dev_put(dev);
+	return rv;
+}
+
+static void dn_dev_check_default(struct net_device *dev)
+{
+	write_lock(&dndev_lock);
+	if (dev == decnet_default_device) {
+		decnet_default_device = NULL;
+	} else {
+		dev = NULL;
+	}
+	write_unlock(&dndev_lock);
+	if (dev)
+		dev_put(dev);
+}
+
 static struct dn_dev *dn_dev_by_index(int ifindex)
 {
 	struct net_device *dev;
@@ -1108,6 +1109,7 @@ struct dn_dev *dn_dev_create(struct net_device *dev, int *err)
 
 	memset(dn_db, 0, sizeof(struct dn_dev));
 	memcpy(&dn_db->parms, p, sizeof(struct dn_dev_parms));
+	smp_wmb();
 	dev->dn_ptr = dn_db;
 	dn_db->dev = dev;
 	init_timer(&dn_db->timer);
@@ -1215,6 +1217,7 @@ static void dn_dev_delete(struct net_device *dev)
 	dev->dn_ptr = NULL;
 
 	neigh_parms_release(&dn_neigh_table, dn_db->neigh_parms);
+	neigh_ifdown(&dn_neigh_table, dev);
 
 	if (dn_db->router)
 		neigh_release(dn_db->router);
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index ab64b850c..dc48de88b 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -35,6 +35,8 @@
 #include <linux/netfilter_decnet.h>
 #include <linux/spinlock.h>
 #include <linux/seq_file.h>
+#include <linux/rcupdate.h>
+#include <linux/jhash.h>
 #include <asm/atomic.h>
 #include <net/neighbour.h>
 #include <net/dst.h>
@@ -121,26 +123,32 @@ struct neigh_table dn_neigh_table = {
 
 static u32 dn_neigh_hash(const void *pkey, const struct net_device *dev)
 {
-	u32 hash_val;
-
-	hash_val = *(dn_address *)pkey;
-	hash_val ^= (hash_val >> 10);
-	hash_val ^= (hash_val >> 3);
-
-	return hash_val & NEIGH_HASHMASK;
+	return jhash_2words(*(dn_address *)pkey, 0, dn_neigh_table.hash_rnd);
 }
 
 static int dn_neigh_construct(struct neighbour *neigh)
 {
 	struct net_device *dev = neigh->dev;
 	struct dn_neigh *dn = (struct dn_neigh *)neigh;
-	struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
+	struct dn_dev *dn_db;
+	struct neigh_parms *parms;
 
-	if (dn_db == NULL)
+	rcu_read_lock();
+	dn_db = rcu_dereference(dev->dn_ptr);
+	if (dn_db == NULL) {
+		rcu_read_unlock();
 		return -EINVAL;
+	}
 
-	if (dn_db->neigh_parms)
-		neigh->parms = dn_db->neigh_parms;
+	parms = dn_db->neigh_parms;
+	if (!parms) {
+		rcu_read_unlock();
+		return -EINVAL;
+	}
+
+	__neigh_parms_put(neigh->parms);
+	neigh->parms = neigh_parms_clone(parms);
+	rcu_read_unlock();
 
 	if (dn_db->use_long)
 		neigh->ops = &dn_long_ops;
@@ -346,27 +354,6 @@ static int dn_phase3_output(struct sk_buff *skb)
  * basically does a neigh_lookup(), but without comparing the device
  * field. This is required for the On-Ethernet cache
  */
-struct neighbour *dn_neigh_lookup(struct neigh_table *tbl, const void *ptr)
-{
-	struct neighbour *neigh;
-	u32 hash_val;
-
-	hash_val = tbl->hash(ptr, NULL);
-
-	read_lock_bh(&tbl->lock);
-	for(neigh = tbl->hash_buckets[hash_val]; neigh != NULL; neigh = neigh->next) {
-		if (memcmp(neigh->primary_key, ptr, tbl->key_len) == 0) {
-			atomic_inc(&neigh->refcnt);
-			read_unlock_bh(&tbl->lock);
-			return neigh;
-		}
-	}
-	read_unlock_bh(&tbl->lock);
-
-	return NULL;
-}
-
-
 /*
  * Any traffic on a pointopoint link causes the timer to be reset
  * for the entry in the neighbour table.
@@ -412,7 +399,7 @@ int dn_neigh_router_hello(struct sk_buff *skb)
 			neigh->updated = jiffies;
 
 			if (neigh->dev->type == ARPHRD_ETHER)
-				memcpy(neigh->ha, &skb->mac.ethernet->h_source, ETH_ALEN);
+				memcpy(neigh->ha, &eth_hdr(skb)->h_source, ETH_ALEN);
 
 			dn->blksize  = dn_ntohs(msg->blksize);
 			dn->priority = msg->priority;
@@ -468,7 +455,7 @@ int dn_neigh_endnode_hello(struct sk_buff *skb)
 			neigh->updated = jiffies;
 
 			if (neigh->dev->type == ARPHRD_ETHER)
-				memcpy(neigh->ha, &skb->mac.ethernet->h_source, ETH_ALEN);
+				memcpy(neigh->ha, &eth_hdr(skb)->h_source, ETH_ALEN);
 			dn->flags   &= ~(DN_NDFLAG_R1 | DN_NDFLAG_R2);
 			dn->blksize  = dn_ntohs(msg->blksize);
 			dn->priority = 0;
@@ -501,141 +488,66 @@ static char *dn_find_slot(char *base, int max, int priority)
 	return (*min < priority) ? (min - 6) : NULL;
 }
 
-int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n)
-{
-	int t = 0;
-	int i;
-	struct neighbour *neigh;
-	struct dn_neigh *dn;
-	struct neigh_table *tbl = &dn_neigh_table;
-	unsigned char *rs = ptr;
-	struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
-
-	read_lock_bh(&tbl->lock);
-
-	for(i = 0; i < NEIGH_HASHMASK; i++) {
-		for(neigh = tbl->hash_buckets[i]; neigh != NULL; neigh = neigh->next) {
-			if (neigh->dev != dev)
-				continue;
-			dn = (struct dn_neigh *)neigh;
-			if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2)))
-				continue;
-			if (dn_db->parms.forwarding == 1 && (dn->flags & DN_NDFLAG_R2))
-				continue;
-			if (t == n)
-				rs = dn_find_slot(ptr, n, dn->priority);
-			else
-				t++;
-			if (rs == NULL)
-				continue;
-			dn_dn2eth(rs, dn->addr);
-			rs += 6;
-			*rs = neigh->nud_state & NUD_CONNECTED ? 0x80 : 0x0;
-			*rs |= dn->priority;
-			rs++;
-		}
-	}
-
-	read_unlock_bh(&tbl->lock);
-
-	return t;
-}
-
-
-#ifdef CONFIG_PROC_FS
-
-struct dn_neigh_iter_state {
-	int bucket;
+struct elist_cb_state {
+	struct net_device *dev;
+	unsigned char *ptr;
+	unsigned char *rs;
+	int t, n;
 };
 
-static struct neighbour *neigh_get_first(struct seq_file *seq)
+static void neigh_elist_cb(struct neighbour *neigh, void *_info)
 {
-	struct dn_neigh_iter_state *state = seq->private;
-	struct neighbour *n = NULL;
-
-	for(state->bucket = 0;
-	    state->bucket <= NEIGH_HASHMASK;
-	    ++state->bucket) {
-		n = dn_neigh_table.hash_buckets[state->bucket];
-		if (n)
-			break;
-	}
-
-	return n;
-}
-
-static struct neighbour *neigh_get_next(struct seq_file *seq,
-					struct neighbour *n)
-{
-	struct dn_neigh_iter_state *state = seq->private;
+	struct elist_cb_state *s = _info;
+	struct dn_dev *dn_db;
+	struct dn_neigh *dn;
 
-	n = n->next;
-try_again:
-	if (n)
-		goto out;
-	if (++state->bucket > NEIGH_HASHMASK)
-		goto out;
-	n = dn_neigh_table.hash_buckets[state->bucket];
-	goto try_again;
-out:
-	return n;
-}
+	if (neigh->dev != s->dev)
+		return;
 
-static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
-{
-	struct neighbour *n = neigh_get_first(seq);
+	dn = (struct dn_neigh *) neigh;
+	if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2)))
+		return;
 
-	if (n)
-		while(*pos && (n = neigh_get_next(seq, n)))
-			--*pos;
-	return *pos ? NULL : n;
-}
+	dn_db = (struct dn_dev *) s->dev->dn_ptr;
+	if (dn_db->parms.forwarding == 1 && (dn->flags & DN_NDFLAG_R2))
+		return;
 
-static void *dn_neigh_get_idx(struct seq_file *seq, loff_t pos)
-{
-	void *rc;
-	read_lock_bh(&dn_neigh_table.lock);
-	rc = neigh_get_idx(seq, &pos);
-	if (!rc) {
-		read_unlock_bh(&dn_neigh_table.lock);
-	}
-	return rc;
-}
-
-static void *dn_neigh_seq_start(struct seq_file *seq, loff_t *pos)
-{
-	return *pos ? dn_neigh_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
+	if (s->t == s->n)
+		s->rs = dn_find_slot(s->ptr, s->n, dn->priority);
+	else
+		s->t++;
+	if (s->rs == NULL)
+		return;
+
+	dn_dn2eth(s->rs, dn->addr);
+	s->rs += 6;
+	*(s->rs) = neigh->nud_state & NUD_CONNECTED ? 0x80 : 0x0;
+	*(s->rs) |= dn->priority;
+	s->rs++;
 }
 
-static void *dn_neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n)
 {
-	void *rc;
+	struct elist_cb_state state;
 
+	state.dev = dev;
+	state.t = 0;
+	state.n = n;
+	state.ptr = ptr;
+	state.rs = ptr;
 
-	if (v == SEQ_START_TOKEN) {
-		rc = dn_neigh_get_idx(seq, 0);
-		goto out;
-	}
+	neigh_for_each(&dn_neigh_table, neigh_elist_cb, &state);
 
-	rc = neigh_get_next(seq, v);
-	if (rc)
-		goto out;
-	read_unlock_bh(&dn_neigh_table.lock);
-out:
-	++*pos;
-	return rc;
+	return state.t;
 }
 
-static void dn_neigh_seq_stop(struct seq_file *seq, void *v)
-{
-	if (v && v != SEQ_START_TOKEN)
-		read_unlock_bh(&dn_neigh_table.lock);
-}
+
+#ifdef CONFIG_PROC_FS
 
 static inline void dn_neigh_format_entry(struct seq_file *seq,
 					 struct neighbour *n)
 {
-	struct dn_neigh *dn = (struct dn_neigh *)n;
+	struct dn_neigh *dn = (struct dn_neigh *) n;
 	char buf[DN_ASCBUF_LEN];
 
 	read_lock(&n->lock);
@@ -662,10 +574,16 @@ static int dn_neigh_seq_show(struct seq_file *seq, void *v)
 	return 0;
 }
 
+static void *dn_neigh_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	return neigh_seq_start(seq, pos, &dn_neigh_table,
+			       NEIGH_SEQ_NEIGH_ONLY);
+}
+
 static struct seq_operations dn_neigh_seq_ops = {
 	.start = dn_neigh_seq_start,
-	.next  = dn_neigh_seq_next,
-	.stop  = dn_neigh_seq_stop,
+	.next  = neigh_seq_next,
+	.stop  = neigh_seq_stop,
 	.show  = dn_neigh_seq_show,
 };
 
@@ -673,11 +591,12 @@ static int dn_neigh_seq_open(struct inode *inode, struct file *file)
 {
 	struct seq_file *seq;
 	int rc = -ENOMEM;
-	struct dn_neigh_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+	struct neigh_seq_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
 
 	if (!s)
 		goto out;
 
+	memset(s, 0, sizeof(*s));
 	rc = seq_open(file, &dn_neigh_seq_ops);
 	if (rc)
 		goto out_kfree;
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index c181467dd..64bdf10b7 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -1,4 +1,3 @@
-
 /*
  * DECnet       An implementation of the DECnet protocol suite for the LINUX
  *              operating system.  DECnet is implemented using the  BSD Socket
@@ -146,14 +145,14 @@ static __inline__ unsigned dn_hash(unsigned short src, unsigned short dst)
 
 static inline void dnrt_free(struct dn_route *rt)
 {
-	call_rcu(&rt->u.dst.rcu_head, dst_rcu_free);
+	call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
 }
 
 static inline void dnrt_drop(struct dn_route *rt)
 {
 	if (rt)
 		dst_release(&rt->u.dst);
-	call_rcu(&rt->u.dst.rcu_head, dst_rcu_free);
+	call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
 }
 
 static void dn_dst_check_expire(unsigned long dummy)
@@ -997,7 +996,7 @@ source_ok:
 		 * here
 		 */
 		if (!try_hard) {
-			neigh = dn_neigh_lookup(&dn_neigh_table, &fl.fld_dst);
+			neigh = neigh_lookup_nodev(&dn_neigh_table, &fl.fld_dst);
 			if (neigh) {
 				if ((oldflp->oif && 
 				    (neigh->dev->ifindex != oldflp->oif)) ||
@@ -1174,9 +1173,9 @@ static int __dn_route_output_key(struct dst_entry **pprt, const struct flowi *fl
 	struct dn_route *rt = NULL;
 
 	if (!(flags & MSG_TRYHARD)) {
-		rcu_read_lock();
-		for(rt = dn_rt_hash_table[hash].chain; rt; rt = rt->u.rt_next) {
-			read_barrier_depends();
+		rcu_read_lock_bh();
+		for(rt = rcu_dereference(dn_rt_hash_table[hash].chain); rt;
+			rt = rcu_dereference(rt->u.rt_next)) {
 			if ((flp->fld_dst == rt->fl.fld_dst) &&
 			    (flp->fld_src == rt->fl.fld_src) &&
 #ifdef CONFIG_DECNET_ROUTE_FWMARK
@@ -1187,12 +1186,12 @@ static int __dn_route_output_key(struct dst_entry **pprt, const struct flowi *fl
 				rt->u.dst.lastuse = jiffies;
 				dst_hold(&rt->u.dst);
 				rt->u.dst.__use++;
-				rcu_read_unlock();
+				rcu_read_unlock_bh();
 				*pprt = &rt->u.dst;
 				return 0;
 			}
 		}
-		rcu_read_unlock();
+		rcu_read_unlock_bh();
 	}
 
 	return dn_route_output_slow(pprt, flp, flags);
@@ -1454,8 +1453,8 @@ int dn_route_input(struct sk_buff *skb)
 		return 0;
 
 	rcu_read_lock();
-	for(rt = dn_rt_hash_table[hash].chain; rt != NULL; rt = rt->u.rt_next) {
-		read_barrier_depends();
+	for(rt = rcu_dereference(dn_rt_hash_table[hash].chain); rt != NULL;
+	    rt = rcu_dereference(rt->u.rt_next)) {
 		if ((rt->fl.fld_src == cb->src) &&
 	 	    (rt->fl.fld_dst == cb->dst) &&
 		    (rt->fl.oif == 0) &&
@@ -1647,21 +1646,22 @@ int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb)
 			continue;
 		if (h > s_h)
 			s_idx = 0;
-		rcu_read_lock();
-		for(rt = dn_rt_hash_table[h].chain, idx = 0; rt; rt = rt->u.rt_next, idx++) {
-			read_barrier_depends();
+		rcu_read_lock_bh();
+		for(rt = rcu_dereference(dn_rt_hash_table[h].chain), idx = 0;
+			rt;
+			rt = rcu_dereference(rt->u.rt_next), idx++) {
 			if (idx < s_idx)
 				continue;
 			skb->dst = dst_clone(&rt->u.dst);
 			if (dn_rt_fill_info(skb, NETLINK_CB(cb->skb).pid,
 					cb->nlh->nlmsg_seq, RTM_NEWROUTE, 1) <= 0) {
 				dst_release(xchg(&skb->dst, NULL));
-				rcu_read_unlock();
+				rcu_read_unlock_bh();
 				goto done;
 			}
 			dst_release(xchg(&skb->dst, NULL));
 		}
-		rcu_read_unlock();
+		rcu_read_unlock_bh();
 	}
 
 done:
@@ -1681,7 +1681,7 @@ static struct dn_route *dn_rt_cache_get_first(struct seq_file *seq)
 	struct dn_rt_cache_iter_state *s = seq->private;
 
 	for(s->bucket = dn_rt_hash_mask; s->bucket >= 0; --s->bucket) {
-		rcu_read_lock();
+		rcu_read_lock_bh();
 		rt = dn_rt_hash_table[s->bucket].chain;
 		if (rt)
 			break;
@@ -1692,15 +1692,14 @@ static struct dn_route *dn_rt_cache_get_first(struct seq_file *seq)
 
 static struct dn_route *dn_rt_cache_get_next(struct seq_file *seq, struct dn_route *rt)
 {
-	struct dn_rt_cache_iter_state *s = seq->private;
+	struct dn_rt_cache_iter_state *s = rcu_dereference(seq->private);
 
-	smp_read_barrier_depends();
 	rt = rt->u.rt_next;
 	while(!rt) {
-		rcu_read_unlock();
+		rcu_read_unlock_bh();
 		if (--s->bucket < 0)
 			break;
-		rcu_read_lock();
+		rcu_read_lock_bh();
 		rt = dn_rt_hash_table[s->bucket].chain;
 	}
 	return rt;
@@ -1727,7 +1726,7 @@ static void *dn_rt_cache_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 static void dn_rt_cache_seq_stop(struct seq_file *seq, void *v)
 {
 	if (v)
-		rcu_read_unlock();
+		rcu_read_unlock_bh();
 }
 
 static int dn_rt_cache_seq_show(struct seq_file *seq, void *v)
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index 07b4cff2f..fc31ae120 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -39,6 +39,7 @@
 #include <net/udp.h>
 #include <net/ip.h>
 #include <linux/spinlock.h>
+#include <linux/rcupdate.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -401,16 +402,17 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
 	   y.x maps to IP a.b.c.x.  This should be replaced with something
 	   more flexible and more aware of subnet masks.  */
 	{
-		struct in_device *idev = in_dev_get(dev);
+		struct in_device *idev;
 		unsigned long network = 0;
+
+		rcu_read_lock();
+		idev = __in_dev_get(dev);
 		if (idev) {
-			read_lock(&idev->lock);
 			if (idev->ifa_list)
 				network = ntohl(idev->ifa_list->ifa_address) & 
 					0xffffff00;		/* !!! */
-			read_unlock(&idev->lock);
-			in_dev_put(idev);
 		}
+		rcu_read_unlock();
 		udpdest.sin_addr.s_addr = htonl(network | addr.station);
 	}
 
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index 9569f3a80..a238f92ec 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -163,10 +163,8 @@ unsigned short eth_type_trans(struct sk_buff *skb, struct net_device *dev)
 	
 	skb->mac.raw=skb->data;
 	skb_pull(skb,ETH_HLEN);
-	eth= skb->mac.ethernet;
-#ifdef CONFIG_NET_CLS_ACT
+	eth = eth_hdr(skb);
 	skb->input_dev = dev;
-#endif
 	
 	if(*eth->h_dest&1)
 	{
@@ -212,7 +210,7 @@ unsigned short eth_type_trans(struct sk_buff *skb, struct net_device *dev)
 
 int eth_header_parse(struct sk_buff *skb, unsigned char *haddr)
 {
-	struct ethhdr *eth = skb->mac.ethernet;
+	struct ethhdr *eth = eth_hdr(skb);
 	memcpy(haddr, eth->h_source, ETH_ALEN);
 	return ETH_ALEN;
 }
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index de00c668c..ab116cb70 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -60,12 +60,8 @@ config IP_MULTIPLE_TABLES
 	  Normally, a router decides what to do with a received packet based
 	  solely on the packet's final destination address. If you say Y here,
 	  the Linux router will also be able to take the packet's source
-	  address into account. Furthermore, if you also say Y to "Use TOS
-	  value as routing key" below, the TOS (Type-Of-Service) field of the
-	  packet can be used for routing decisions as well. In addition, if
-	  you say Y here and to "Fast network address translation" below,
-	  the router will also be able to modify source and destination
-	  addresses of forwarded packets.
+	  address into account. Furthermore, the TOS (Type-Of-Service) field
+	  of the packet can be used for routing decisions as well.
 
 	  If you are interested in this, please see the preliminary
 	  documentation at <http://www.compendium.com.ar/policy-routing.txt>
@@ -82,16 +78,6 @@ config IP_ROUTE_FWMARK
 	  If you say Y here, you will be able to specify different routes for
 	  packets with different mark values (see iptables(8), MARK target).
 
-config IP_ROUTE_NAT
-	bool "IP: fast network address translation"
-	depends on IP_MULTIPLE_TABLES
-	help
-	  If you say Y here, your router will be able to modify source and
-	  destination addresses of packets that pass through it, in a manner
-	  you specify.  General information about Network Address Translation
-	  can be gotten from the document
-	  <http://www.hasenstein.com/linux-ip-nat/diplom/nat.html>.
-
 config IP_ROUTE_MULTIPATH
 	bool "IP: equal cost multipath"
 	depends on IP_ADVANCED_ROUTER
@@ -104,16 +90,6 @@ config IP_ROUTE_MULTIPATH
 	  equal "cost" and chooses one of them in a non-deterministic fashion
 	  if a matching packet arrives.
 
-config IP_ROUTE_TOS
-	bool "IP: use TOS value as routing key"
-	depends on IP_ADVANCED_ROUTER
-	help
-	  The header of every IP packet carries a TOS (Type Of Service) value
-	  with which the packet requests a certain treatment, e.g. low
-	  latency (for interactive traffic), high throughput, or high
-	  reliability.  If you say Y here, you will be able to specify
-	  different routes for packets with different TOS values.
-
 config IP_ROUTE_VERBOSE
 	bool "IP: verbose route monitoring"
 	depends on IP_ADVANCED_ROUTER
@@ -187,7 +163,7 @@ config IP_PNP_RARP
 config NET_IPIP
 	tristate "IP: tunneling"
 	depends on INET
-	select XFRM
+	select INET_TUNNEL
 	---help---
 	  Tunneling means encapsulating data of one protocol type within
 	  another protocol and sending it over a channel that understands the
@@ -351,6 +327,7 @@ config INET_ESP
 config INET_IPCOMP
 	tristate "IP: IPComp transformation"
 	select XFRM
+	select INET_TUNNEL
 	select CRYPTO
 	select CRYPTO_DEFLATE
 	---help---
@@ -359,5 +336,14 @@ config INET_IPCOMP
 	  
 	  If unsure, say Y.
 
+config INET_TUNNEL
+	tristate "IP: tunnel transformation"
+	select XFRM
+	---help---
+	  Support for generic IP tunnel transformation, which is required by
+	  the IP tunneling module as well as tunnel mode IPComp.
+	  
+	  If unsure, say Y.
+
 source "net/ipv4/ipvs/Kconfig"
 
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 0fe409afa..38f750996 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -11,7 +11,6 @@ obj-y     := utils.o route.o inetpeer.o protocol.o \
 
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o
-obj-$(CONFIG_IP_ROUTE_NAT) += ip_nat_dumb.o
 obj-$(CONFIG_IP_MROUTE) += ipmr.o
 obj-$(CONFIG_NET_IPIP) += ipip.o
 obj-$(CONFIG_NET_IPGRE) += ip_gre.o
@@ -19,9 +18,10 @@ obj-$(CONFIG_SYN_COOKIES) += syncookies.o
 obj-$(CONFIG_INET_AH) += ah4.o
 obj-$(CONFIG_INET_ESP) += esp4.o
 obj-$(CONFIG_INET_IPCOMP) += ipcomp.o
+obj-$(CONFIG_INET_TUNNEL) += xfrm4_tunnel.o 
 obj-$(CONFIG_IP_PNP) += ipconfig.o
 obj-$(CONFIG_NETFILTER)	+= netfilter/
 obj-$(CONFIG_IP_VS) += ipvs/
 
 obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
-		      xfrm4_tunnel.o xfrm4_output.o
+		      xfrm4_output.o
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index c4a967b81..760516a56 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -122,11 +122,6 @@ atomic_t inet_sock_nr;
 
 extern void ip_mc_drop_socket(struct sock *sk);
 
-/* Per protocol sock slabcache */
-kmem_cache_t *tcp_sk_cachep;
-static kmem_cache_t *udp_sk_cachep;
-static kmem_cache_t *raw4_sk_cachep;
-
 /* The inetsw table contains everything that inet_create needs to
  * build a new socket.
  */
@@ -159,7 +154,7 @@ void inet_sock_destruct(struct sock *sk)
 
 	if (inet->opt)
 		kfree(inet->opt);
-	
+
 	vx_sock_dec(sk);
 	clr_vx_info(&sk->sk_vx_info);
 	sk->sk_xid = -1;
@@ -236,28 +231,6 @@ out:
 	return err;
 }
 
-static __inline__ kmem_cache_t *inet_sk_slab(int protocol)
-{
-	kmem_cache_t* rc = tcp_sk_cachep;
-
-	if (protocol == IPPROTO_UDP)
-		rc = udp_sk_cachep;
-	else if (protocol == IPPROTO_RAW)
-		rc = raw4_sk_cachep;
-	return rc;
-}
-
-static __inline__ int inet_sk_size(int protocol)
-{
-	int rc = sizeof(struct tcp_sock);
-
-	if (protocol == IPPROTO_UDP)
-		rc = sizeof(struct udp_sock);
-	else if (protocol == IPPROTO_RAW)
-		rc = sizeof(struct raw_sock);
-	return rc;
-}
-
 /*
  *	Create an inet socket.
  */
@@ -268,13 +241,12 @@ static int inet_create(struct socket *sock, int protocol)
 	struct list_head *p;
 	struct inet_protosw *answer;
 	struct inet_opt *inet;
-	int err = -ENOBUFS;
+	struct proto *answer_prot;
+	unsigned char answer_flags;
+	char answer_no_check;
+	int err;
 
 	sock->state = SS_UNCONNECTED;
-	sk = sk_alloc(PF_INET, GFP_KERNEL, inet_sk_size(protocol),
-		      inet_sk_slab(protocol));
-	if (!sk)
-		goto out;
 
 	/* Look for the requested type/protocol pair. */
 	answer = NULL;
@@ -300,24 +272,38 @@ static int inet_create(struct socket *sock, int protocol)
 
 	err = -ESOCKTNOSUPPORT;
 	if (!answer)
-		goto out_sk_free;
+		goto out_rcu_unlock;
 	err = -EPERM;
 	if ((protocol == IPPROTO_ICMP) && vx_ccaps(VXC_RAW_ICMP))
 		goto override;
 	if (answer->capability > 0 && !capable(answer->capability))
-		goto out_sk_free;
+		goto out_rcu_unlock;
 override:
 	err = -EPROTONOSUPPORT;
 	if (!protocol)
-		goto out_sk_free;
-	err = 0;
+		goto out_rcu_unlock;
+
 	sock->ops = answer->ops;
-	sk->sk_prot = answer->prot;
-	sk->sk_no_check = answer->no_check;
-	if (INET_PROTOSW_REUSE & answer->flags)
-		sk->sk_reuse = 1;
+	answer_prot = answer->prot;
+	answer_no_check = answer->no_check;
+	answer_flags = answer->flags;
 	rcu_read_unlock();
 
+	BUG_TRAP(answer_prot->slab != NULL);
+
+	err = -ENOBUFS;
+	sk = sk_alloc(PF_INET, GFP_KERNEL,
+		      answer_prot->slab_obj_size,
+		      answer_prot->slab);
+	if (sk == NULL)
+		goto out;
+
+	err = 0;
+	sk->sk_prot = answer_prot;
+	sk->sk_no_check = answer_no_check;
+	if (INET_PROTOSW_REUSE & answer_flags)
+		sk->sk_reuse = 1;
+
 	inet = inet_sk(sk);
 
 	if (SOCK_RAW == sock->type) {
@@ -337,11 +323,10 @@ override:
 	sk_set_owner(sk, THIS_MODULE);
 
 	sk->sk_destruct	   = inet_sock_destruct;
-	sk->sk_zapped	   = 0;
 	sk->sk_family	   = PF_INET;
 	sk->sk_protocol	   = protocol;
 	sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
-	
+
 	set_vx_info(&sk->sk_vx_info, current->vx_info);
 	sk->sk_xid = vx_current_xid();
 	vx_sock_inc(sk);
@@ -376,9 +361,8 @@ override:
 	}
 out:
 	return err;
-out_sk_free:
+out_rcu_unlock:
 	rcu_read_unlock();
-	sk_free(sk);
 	goto out;
 }
 
@@ -432,8 +416,8 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 	int chk_addr_ret;
 	int err;
 	__u32 s_addr;	/* Address used for validation */
-	__u32 s_addr1;
-	__u32 s_addr2 = 0xffffffffl;	/* Optional address of the socket */
+	__u32 s_addr1;	/* Address used for socket */
+	__u32 s_addr2;	/* Broadcast address for the socket */
 	struct nx_info *nxi = sk->sk_nx_info;
 
 	/* If the socket has its own bind function then use it. (RAW) */
@@ -445,38 +429,41 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 	if (addr_len < sizeof(struct sockaddr_in))
 		goto out;
 
-	s_addr = s_addr1 = addr->sin_addr.s_addr;
+	s_addr = addr->sin_addr.s_addr;
+	s_addr1 = s_addr;
+	s_addr2 = 0xffffffffl;
+
 	vxdprintk(VXD_CBIT(net, 3),
-		"inet_bind(%p) %p,%p;%lx",
+		"inet_bind(%p)* %p,%p;%lx %d.%d.%d.%d",
 		sk, sk->sk_nx_info, sk->sk_socket,
-		(sk->sk_socket?sk->sk_socket->flags:0));
+		(sk->sk_socket?sk->sk_socket->flags:0),
+		VXD_QUAD(s_addr));
 	if (nxi) {
 		__u32 v4_bcast = nxi->v4_bcast;
 		__u32 ipv4root = nxi->ipv4[0];
 		int nbipv4 = nxi->nbipv4;
+
 		if (s_addr == 0) {
+			/* bind to any for 1-n */
 			s_addr = ipv4root;
-			if (nbipv4 > 1)
-				s_addr1 = 0;
-			else {
-				s_addr1 = ipv4root;
-			}
+			s_addr1 = (nbipv4 > 1) ? 0 : s_addr;
 			s_addr2 = v4_bcast;
 		} else if (s_addr == 0x0100007f) {
-			s_addr = s_addr1 = ipv4root;
+			/* rewrite localhost to ipv4root */
+			s_addr = ipv4root;
+			s_addr1 = ipv4root;
 		} else if (s_addr != v4_bcast) {
-			int i;
-			for (i=0; i<nbipv4; i++) {
-				if (s_addr == nxi->ipv4[i])
-					break;
-			}
-			if (i == nbipv4) {
+			/* normal address bind */
+			if (!addr_in_nx_info(nxi, s_addr))
 				return -EADDRNOTAVAIL;
-			}
 		}
 	}
 	chk_addr_ret = inet_addr_type(s_addr);
 
+	vxdprintk(VXD_CBIT(net, 3),
+		"inet_bind(%p) %d.%d.%d.%d, %d.%d.%d.%d, %d.%d.%d.%d",
+		sk, VXD_QUAD(s_addr), VXD_QUAD(s_addr1), VXD_QUAD(s_addr2));
+
 	/* Not specified by any standard per-se, however it breaks too
 	 * many applications when removed.  It is unfortunate since
 	 * allowing applications to make a non-local bind solves
@@ -894,7 +881,7 @@ struct proto_ops inet_dgram_ops = {
 	.sendpage =	inet_sendpage,
 };
 
-struct net_proto_family inet_family_ops = {
+static struct net_proto_family inet_family_ops = {
 	.family = PF_INET,
 	.create = inet_create,
 	.owner	= THIS_MODULE,
@@ -1067,24 +1054,29 @@ static int __init inet_init(void)
 	struct sk_buff *dummy_skb;
 	struct inet_protosw *q;
 	struct list_head *r;
+	int rc = -EINVAL;
 
 	if (sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)) {
 		printk(KERN_CRIT "%s: panic\n", __FUNCTION__);
-		return -EINVAL;
+		goto out;
+	}
+
+	rc = sk_alloc_slab(&tcp_prot, "tcp_sock");
+	if (rc) {
+		sk_alloc_slab_error(&tcp_prot);
+		goto out;
+	}
+	rc = sk_alloc_slab(&udp_prot, "udp_sock");
+	if (rc) {
+		sk_alloc_slab_error(&udp_prot);
+		goto out_tcp_free_slab;
+	}
+	rc = sk_alloc_slab(&raw_prot, "raw_sock");
+	if (rc) {
+		sk_alloc_slab_error(&raw_prot);
+		goto out_udp_free_slab;
 	}
 
-	tcp_sk_cachep = kmem_cache_create("tcp_sock",
-					  sizeof(struct tcp_sock), 0,
-					  SLAB_HWCACHE_ALIGN, NULL, NULL);
-	udp_sk_cachep = kmem_cache_create("udp_sock",
-					  sizeof(struct udp_sock), 0,
-					  SLAB_HWCACHE_ALIGN, NULL, NULL);
-	raw4_sk_cachep = kmem_cache_create("raw4_sock",
-					   sizeof(struct raw_sock), 0,
-					   SLAB_HWCACHE_ALIGN, NULL, NULL);
-	if (!tcp_sk_cachep || !udp_sk_cachep || !raw4_sk_cachep)
-		printk(KERN_CRIT
-		       "inet_init: Can't create protocol sock SLAB caches!\n");
 	/*
 	 *	Tell SOCKET that we are alive... 
 	 */
@@ -1154,7 +1146,14 @@ static int __init inet_init(void)
 
 	ipfrag_init();
 
-	return 0;
+	rc = 0;
+out:
+	return rc;
+out_tcp_free_slab:
+	sk_free_slab(&tcp_prot);
+out_udp_free_slab:
+	sk_free_slab(&udp_prot);
+	goto out;
 }
 
 module_init(inet_init);
@@ -1214,7 +1213,6 @@ EXPORT_SYMBOL(inet_accept);
 EXPORT_SYMBOL(inet_bind);
 EXPORT_SYMBOL(inet_dgram_connect);
 EXPORT_SYMBOL(inet_dgram_ops);
-EXPORT_SYMBOL(inet_family_ops);
 EXPORT_SYMBOL(inet_getname);
 EXPORT_SYMBOL(inet_ioctl);
 EXPORT_SYMBOL(inet_listen);
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 9784f0376..970fe58b4 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -53,10 +53,10 @@ static int ip_clear_mutable_options(struct iphdr *iph, u32 *daddr)
 	return 0;
 }
 
-static int ah_output(struct sk_buff **pskb)
+static int ah_output(struct sk_buff *skb)
 {
 	int err;
-	struct dst_entry *dst = (*pskb)->dst;
+	struct dst_entry *dst = skb->dst;
 	struct xfrm_state *x  = dst->xfrm;
 	struct iphdr *iph, *top_iph;
 	struct ip_auth_hdr *ah;
@@ -66,7 +66,7 @@ static int ah_output(struct sk_buff **pskb)
 		char 		buf[60];
 	} tmp_iph;
 
-	top_iph = (*pskb)->nh.iph;
+	top_iph = skb->nh.iph;
 	iph = &tmp_iph.iph;
 
 	iph->tos = top_iph->tos;
@@ -85,7 +85,7 @@ static int ah_output(struct sk_buff **pskb)
 	ah->nexthdr = top_iph->protocol;
 
 	top_iph->tos = 0;
-	top_iph->tot_len = htons((*pskb)->len);
+	top_iph->tot_len = htons(skb->len);
 	top_iph->frag_off = 0;
 	top_iph->ttl = 0;
 	top_iph->protocol = IPPROTO_AH;
@@ -98,7 +98,7 @@ static int ah_output(struct sk_buff **pskb)
 	ah->reserved = 0;
 	ah->spi = x->id.spi;
 	ah->seq_no = htonl(++x->replay.oseq);
-	ahp->icv(ahp, *pskb, ah->auth_data);
+	ahp->icv(ahp, skb, ah->auth_data);
 
 	top_iph->tos = iph->tos;
 	top_iph->ttl = iph->ttl;
@@ -116,7 +116,7 @@ error:
 	return err;
 }
 
-int ah_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ah_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
 {
 	int ah_hlen;
 	struct iphdr *iph;
@@ -184,7 +184,7 @@ out:
 	return -EINVAL;
 }
 
-void ah4_err(struct sk_buff *skb, u32 info)
+static void ah4_err(struct sk_buff *skb, u32 info)
 {
 	struct iphdr *iph = (struct iphdr*)skb->data;
 	struct ip_auth_hdr *ah = (struct ip_auth_hdr*)(skb->data+(iph->ihl<<2));
@@ -214,6 +214,9 @@ static int ah_init_state(struct xfrm_state *x, void *args)
 	if (x->aalg->alg_key_len > 512)
 		goto error;
 
+	if (x->encap)
+		goto error;
+
 	ahp = kmalloc(sizeof(*ahp), GFP_KERNEL);
 	if (ahp == NULL)
 		return -ENOMEM;
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index c472a6653..9b5d1e813 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -71,6 +71,7 @@
  *					arp_xmit so intermediate drivers like
  *					bonding can change the skb before
  *					sending (e.g. insert 8021q tag).
+ *		Harald Welte	:	convert to make use of jenkins hash
  */
 
 #include <linux/module.h>
@@ -96,6 +97,8 @@
 #include <linux/stat.h>
 #include <linux/init.h>
 #include <linux/net.h>
+#include <linux/rcupdate.h>
+#include <linux/jhash.h>
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
 #endif
@@ -222,31 +225,29 @@ int arp_mc_map(u32 addr, u8 *haddr, struct net_device *dev, int dir)
 
 static u32 arp_hash(const void *pkey, const struct net_device *dev)
 {
-	u32 hash_val;
-
-	hash_val = *(u32*)pkey;
-	hash_val ^= (hash_val>>16);
-	hash_val ^= hash_val>>8;
-	hash_val ^= hash_val>>3;
-	hash_val = (hash_val^dev->ifindex)&NEIGH_HASHMASK;
-
-	return hash_val;
+	return jhash_2words(*(u32 *)pkey, dev->ifindex, arp_tbl.hash_rnd);
 }
 
 static int arp_constructor(struct neighbour *neigh)
 {
 	u32 addr = *(u32*)neigh->primary_key;
 	struct net_device *dev = neigh->dev;
-	struct in_device *in_dev = in_dev_get(dev);
-
-	if (in_dev == NULL)
-		return -EINVAL;
+	struct in_device *in_dev;
+	struct neigh_parms *parms;
 
 	neigh->type = inet_addr_type(addr);
-	if (in_dev->arp_parms)
-		neigh->parms = in_dev->arp_parms;
 
-	in_dev_put(in_dev);
+	rcu_read_lock();
+	in_dev = rcu_dereference(__in_dev_get(dev));
+	if (in_dev == NULL) {
+		rcu_read_unlock();
+		return -EINVAL;
+	}
+
+	parms = in_dev->arp_parms;
+	__neigh_parms_put(neigh->parms);
+	neigh->parms = neigh_parms_clone(parms);
+	rcu_read_unlock();
 
 	if (dev->hard_header == NULL) {
 		neigh->nud_state = NUD_NOARP;
@@ -695,6 +696,7 @@ void arp_send(int type, int ptype, u32 dest_ip,
 
 static void parp_redo(struct sk_buff *skb)
 {
+	nf_reset(skb);
 	arp_rcv(skb, skb->dev, NULL);
 }
 
@@ -906,7 +908,7 @@ int arp_process(struct sk_buff *skb)
 		if (arp->ar_op != htons(ARPOP_REPLY) ||
 		    skb->pkt_type != PACKET_HOST)
 			state = NUD_STALE;
-		neigh_update(n, sha, state, override, 1);
+		neigh_update(n, sha, state, override ? NEIGH_UPDATE_F_OVERRIDE : 0);
 		neigh_release(n);
 	}
 
@@ -1003,8 +1005,26 @@ int arp_req_set(struct arpreq *r, struct net_device * dev)
 		if (!dev)
 			return -EINVAL;
 	}
-	if (r->arp_ha.sa_family != dev->type)	
-		return -EINVAL;
+	switch (dev->type) {
+#ifdef CONFIG_FDDI
+	case ARPHRD_FDDI:
+		/*
+		 * According to RFC 1390, FDDI devices should accept ARP
+		 * hardware types of 1 (Ethernet).  However, to be more
+		 * robust, we'll accept hardware types of either 1 (Ethernet)
+		 * or 6 (IEEE 802.2).
+		 */
+		if (r->arp_ha.sa_family != ARPHRD_FDDI &&
+		    r->arp_ha.sa_family != ARPHRD_ETHER &&
+		    r->arp_ha.sa_family != ARPHRD_IEEE802)
+			return -EINVAL;
+		break;
+#endif
+	default:
+		if (r->arp_ha.sa_family != dev->type)
+			return -EINVAL;
+		break;
+	}
 
 	neigh = __neigh_lookup_errno(&arp_tbl, &ip, dev);
 	err = PTR_ERR(neigh);
@@ -1013,7 +1033,9 @@ int arp_req_set(struct arpreq *r, struct net_device * dev)
 		if (r->arp_flags & ATF_PERM)
 			state = NUD_PERMANENT;
 		err = neigh_update(neigh, (r->arp_flags&ATF_COM) ?
-				   r->arp_ha.sa_data : NULL, state, 1, 0);
+				   r->arp_ha.sa_data : NULL, state, 
+				   NEIGH_UPDATE_F_OVERRIDE|
+				   NEIGH_UPDATE_F_ADMIN);
 		neigh_release(neigh);
 	}
 	return err;
@@ -1093,7 +1115,9 @@ int arp_req_delete(struct arpreq *r, struct net_device * dev)
 	neigh = neigh_lookup(&arp_tbl, &ip, dev);
 	if (neigh) {
 		if (neigh->nud_state&~NUD_NOARP)
-			err = neigh_update(neigh, NULL, NUD_FAILED, 1, 0);
+			err = neigh_update(neigh, NULL, NUD_FAILED, 
+					   NEIGH_UPDATE_F_OVERRIDE|
+					   NEIGH_UPDATE_F_ADMIN);
 		neigh_release(neigh);
 	}
 	return err;
@@ -1257,162 +1281,10 @@ static char *ax2asc2(ax25_address *a, char *buf)
 }
 #endif /* CONFIG_AX25 */
 
-struct arp_iter_state {
-	int is_pneigh, bucket;
-};
-
-static struct neighbour *neigh_get_first(struct seq_file *seq)
-{
-	struct arp_iter_state* state = seq->private;
-	struct neighbour *n = NULL;
-
-	state->is_pneigh = 0;
-
-	for (state->bucket = 0;
-	     state->bucket <= NEIGH_HASHMASK;
-	     ++state->bucket) {
-		n = arp_tbl.hash_buckets[state->bucket];
-		while (n && !(n->nud_state & ~NUD_NOARP))
-			n = n->next;
-		if (n)
-			break;
-	}
-
-	return n;
-}
-
-static struct neighbour *neigh_get_next(struct seq_file *seq,
-					struct neighbour *n)
-{
-	struct arp_iter_state* state = seq->private;
-
-	do {
-		n = n->next;
-		/* Don't confuse "arp -a" w/ magic entries */
-try_again:
-		;
-	} while (n && !(n->nud_state & ~NUD_NOARP));
-
-	if (n)
-		goto out;
-	if (++state->bucket > NEIGH_HASHMASK)
-		goto out;
-	n = arp_tbl.hash_buckets[state->bucket];
-	goto try_again;
-out:
-	return n;
-}
-
-static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
-{
-	struct neighbour *n = neigh_get_first(seq);
-
-	if (n)
-		while (*pos && (n = neigh_get_next(seq, n)))
-			--*pos;
-	return *pos ? NULL : n;
-}
-
-static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
-{
-	struct arp_iter_state* state = seq->private;
-	struct pneigh_entry *pn;
-
-	state->is_pneigh = 1;
-
-	for (state->bucket = 0;
-	     state->bucket <= PNEIGH_HASHMASK;
-	     ++state->bucket) {
-		pn = arp_tbl.phash_buckets[state->bucket];
-		if (pn)
-			break;
-	}
-	return pn;
-}
-
-static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
-					    struct pneigh_entry *pn)
-{
-	struct arp_iter_state* state = seq->private;
-
-	pn = pn->next;
-	while (!pn) {
-		if (++state->bucket > PNEIGH_HASHMASK)
-			break;
-		pn = arp_tbl.phash_buckets[state->bucket];
-	}
-	return pn;
-}
-
-static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t pos)
-{
-	struct pneigh_entry *pn = pneigh_get_first(seq);
-
-	if (pn)
-		while (pos && (pn = pneigh_get_next(seq, pn)))
-			--pos;
-	return pos ? NULL : pn;
-}
-
-static void *arp_get_idx(struct seq_file *seq, loff_t pos)
-{
-	void *rc;
-
-	read_lock_bh(&arp_tbl.lock);
-	rc = neigh_get_idx(seq, &pos);
-
-	if (!rc) {
-		read_unlock_bh(&arp_tbl.lock);
-		rc = pneigh_get_idx(seq, pos);
-	}
-	return rc;
-}
-
-static void *arp_seq_start(struct seq_file *seq, loff_t *pos)
-{
-	struct arp_iter_state* state = seq->private;
-
-	state->is_pneigh = 0;
-	state->bucket = 0;
-	return *pos ? arp_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
-}
-
-static void *arp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-	void *rc;
-	struct arp_iter_state* state;
-
-	if (v == SEQ_START_TOKEN) {
-		rc = arp_get_idx(seq, 0);
-		goto out;
-	}
-
-	state = seq->private;
-	if (!state->is_pneigh) {
-		rc = neigh_get_next(seq, v);
-		if (rc)
-			goto out;
-		read_unlock_bh(&arp_tbl.lock);
-		rc = pneigh_get_first(seq);
-	} else
-		rc = pneigh_get_next(seq, v);
-out:
-	++*pos;
-	return rc;
-}
-
-static void arp_seq_stop(struct seq_file *seq, void *v)
-{
-	struct arp_iter_state* state = seq->private;
-
-	if (!state->is_pneigh && v != SEQ_START_TOKEN)
-		read_unlock_bh(&arp_tbl.lock);
-}
-
 #define HBUFFERLEN 30
 
-static __inline__ void arp_format_neigh_entry(struct seq_file *seq,
-					      struct neighbour *n)
+static void arp_format_neigh_entry(struct seq_file *seq,
+				   struct neighbour *n)
 {
 	char hbuffer[HBUFFERLEN];
 	const char hexbuf[] = "0123456789ABCDEF";
@@ -1443,8 +1315,8 @@ static __inline__ void arp_format_neigh_entry(struct seq_file *seq,
 	read_unlock(&n->lock);
 }
 
-static __inline__ void arp_format_pneigh_entry(struct seq_file *seq,
-					       struct pneigh_entry *n)
+static void arp_format_pneigh_entry(struct seq_file *seq,
+				    struct pneigh_entry *n)
 {
 	struct net_device *dev = n->dev;
 	int hatype = dev ? dev->type : 0;
@@ -1458,13 +1330,13 @@ static __inline__ void arp_format_pneigh_entry(struct seq_file *seq,
 
 static int arp_seq_show(struct seq_file *seq, void *v)
 {
-	if (v == SEQ_START_TOKEN)
+	if (v == SEQ_START_TOKEN) {
 		seq_puts(seq, "IP address       HW type     Flags       "
 			      "HW address            Mask     Device\n");
-	else {
-		struct arp_iter_state* state = seq->private;
+	} else {
+		struct neigh_seq_state *state = seq->private;
 
-		if (state->is_pneigh)
+		if (state->flags & NEIGH_SEQ_IS_PNEIGH)
 			arp_format_pneigh_entry(seq, v);
 		else
 			arp_format_neigh_entry(seq, v);
@@ -1473,12 +1345,20 @@ static int arp_seq_show(struct seq_file *seq, void *v)
 	return 0;
 }
 
+static void *arp_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	/* Don't want to confuse "arp -a" w/ magic entries,
+	 * so we tell the generic iterator to skip NUD_NOARP.
+	 */
+	return neigh_seq_start(seq, pos, &arp_tbl, NEIGH_SEQ_SKIP_NOARP);
+}
+
 /* ------------------------------------------------------------------------ */
 
 static struct seq_operations arp_seq_ops = {
 	.start  = arp_seq_start,
-	.next   = arp_seq_next,
-	.stop   = arp_seq_stop,
+	.next   = neigh_seq_next,
+	.stop   = neigh_seq_stop,
 	.show   = arp_seq_show,
 };
 
@@ -1486,11 +1366,12 @@ static int arp_seq_open(struct inode *inode, struct file *file)
 {
 	struct seq_file *seq;
 	int rc = -ENOMEM;
-	struct arp_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+	struct neigh_seq_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
        
 	if (!s)
 		goto out;
 
+	memset(s, 0, sizeof(*s));
 	rc = seq_open(file, &arp_seq_ops);
 	if (rc)
 		goto out_kfree;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index a85a45964..cc5dd5637 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -88,31 +88,31 @@ static void devinet_sysctl_register(struct in_device *in_dev,
 static void devinet_sysctl_unregister(struct ipv4_devconf *p);
 #endif
 
-int inet_ifa_count;
-int inet_dev_count;
-
 /* Locks all the inet devices. */
 
-rwlock_t inetdev_lock = RW_LOCK_UNLOCKED;
-
 static struct in_ifaddr *inet_alloc_ifa(void)
 {
 	struct in_ifaddr *ifa = kmalloc(sizeof(*ifa), GFP_KERNEL);
 
 	if (ifa) {
 		memset(ifa, 0, sizeof(*ifa));
-		inet_ifa_count++;
+		INIT_RCU_HEAD(&ifa->rcu_head);
 	}
 
 	return ifa;
 }
 
-static __inline__ void inet_free_ifa(struct in_ifaddr *ifa)
+static void inet_rcu_free_ifa(struct rcu_head *head)
 {
+	struct in_ifaddr *ifa = container_of(head, struct in_ifaddr, rcu_head);
 	if (ifa->ifa_dev)
-		__in_dev_put(ifa->ifa_dev);
+		in_dev_put(ifa->ifa_dev);
 	kfree(ifa);
-	inet_ifa_count--;
+}
+
+static inline void inet_free_ifa(struct in_ifaddr *ifa)
+{
+	call_rcu(&ifa->rcu_head, inet_rcu_free_ifa);
 }
 
 void in_dev_finish_destroy(struct in_device *idev)
@@ -129,7 +129,6 @@ void in_dev_finish_destroy(struct in_device *idev)
 	if (!idev->dead)
 		printk("Freeing alive in_device %p\n", idev);
 	else {
-		inet_dev_count--;
 		kfree(idev);
 	}
 }
@@ -144,24 +143,24 @@ struct in_device *inetdev_init(struct net_device *dev)
 	if (!in_dev)
 		goto out;
 	memset(in_dev, 0, sizeof(*in_dev));
-	in_dev->lock = RW_LOCK_UNLOCKED;
+	INIT_RCU_HEAD(&in_dev->rcu_head);
 	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)
 		goto out_kfree;
-	inet_dev_count++;
 	/* Reference in_dev->dev */
 	dev_hold(dev);
 #ifdef CONFIG_SYSCTL
 	neigh_sysctl_register(dev, in_dev->arp_parms, NET_IPV4,
 			      NET_IPV4_NEIGH, "ipv4", NULL);
 #endif
-	write_lock_bh(&inetdev_lock);
-	dev->ip_ptr = in_dev;
+
 	/* Account for reference dev->ip_ptr */
 	in_dev_hold(in_dev);
-	write_unlock_bh(&inetdev_lock);
+	smp_wmb();
+	dev->ip_ptr = in_dev;
+
 #ifdef CONFIG_SYSCTL
 	devinet_sysctl_register(in_dev, &in_dev->cnf);
 #endif
@@ -176,9 +175,16 @@ out_kfree:
 	goto out;
 }
 
+static void in_dev_rcu_put(struct rcu_head *head)
+{
+	struct in_device *idev = container_of(head, struct in_device, rcu_head);
+	in_dev_put(idev);
+}
+
 static void inetdev_destroy(struct in_device *in_dev)
 {
 	struct in_ifaddr *ifa;
+	struct net_device *dev;
 
 	ASSERT_RTNL();
 
@@ -194,30 +200,31 @@ static void inetdev_destroy(struct in_device *in_dev)
 #ifdef CONFIG_SYSCTL
 	devinet_sysctl_unregister(&in_dev->cnf);
 #endif
-	write_lock_bh(&inetdev_lock);
-	in_dev->dev->ip_ptr = NULL;
-	/* in_dev_put following below will kill the in_device */
-	write_unlock_bh(&inetdev_lock);
+
+	dev = in_dev->dev;
+	dev->ip_ptr = NULL;
 
 #ifdef CONFIG_SYSCTL
 	neigh_sysctl_unregister(in_dev->arp_parms);
 #endif
 	neigh_parms_release(&arp_tbl, in_dev->arp_parms);
-	in_dev_put(in_dev);
+	arp_ifdown(dev);
+
+	call_rcu(&in_dev->rcu_head, in_dev_rcu_put);
 }
 
 int inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b)
 {
-	read_lock(&in_dev->lock);
+	rcu_read_lock();
 	for_primary_ifa(in_dev) {
 		if (inet_ifa_match(a, ifa)) {
 			if (!b || inet_ifa_match(b, ifa)) {
-				read_unlock(&in_dev->lock);
+				rcu_read_unlock();
 				return 1;
 			}
 		}
 	} endfor_ifa(in_dev);
-	read_unlock(&in_dev->lock);
+	rcu_read_unlock();
 	return 0;
 }
 
@@ -241,9 +248,8 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
 				ifap1 = &ifa->ifa_next;
 				continue;
 			}
-			write_lock_bh(&in_dev->lock);
+
 			*ifap1 = ifa->ifa_next;
-			write_unlock_bh(&in_dev->lock);
 
 			rtmsg_ifa(RTM_DELADDR, ifa);
 			notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa);
@@ -253,9 +259,7 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
 
 	/* 2. Unlink it */
 
-	write_lock_bh(&in_dev->lock);
 	*ifap = ifa1->ifa_next;
-	write_unlock_bh(&in_dev->lock);
 
 	/* 3. Announce address deletion */
 
@@ -317,9 +321,7 @@ static int inet_insert_ifa(struct in_ifaddr *ifa)
 	}
 
 	ifa->ifa_next = *ifap;
-	write_lock_bh(&in_dev->lock);
 	*ifap = ifa;
-	write_unlock_bh(&in_dev->lock);
 
 	/* Send message first, then call notifier.
 	   Notifier will trigger FIB update, so that
@@ -622,7 +624,8 @@ int devinet_ioctl(unsigned int cmd, void __user *arg)
 	ret = -EADDRNOTAVAIL;
 	if (!ifa && cmd != SIOCSIFADDR && cmd != SIOCSIFFLAGS)
 		goto done;
-	if (!ifa_in_nx_info(ifa, current->nx_info))
+	if (vx_flags(VXF_HIDE_NETIF, 0) &&
+		!ifa_in_nx_info(ifa, current->nx_info))
 		goto done;
 
 	switch(cmd) {
@@ -767,7 +770,8 @@ static int inet_gifconf(struct net_device *dev, char __user *buf, int len)
 		goto out;
 
 	for (; ifa; ifa = ifa->ifa_next) {
-		if (!ifa_in_nx_info(ifa, current->nx_info))
+		if (vx_flags(VXF_HIDE_NETIF, 0) &&
+			!ifa_in_nx_info(ifa, current->nx_info))
 			continue;
 		if (!buf) {
 			done += sizeof(ifr);
@@ -802,12 +806,11 @@ u32 inet_select_addr(const struct net_device *dev, u32 dst, int scope)
 	u32 addr = 0;
 	struct in_device *in_dev;
 
-	read_lock(&inetdev_lock);
+	rcu_read_lock();
 	in_dev = __in_dev_get(dev);
 	if (!in_dev)
-		goto out_unlock_inetdev;
+		goto no_in_dev;
 
-	read_lock(&in_dev->lock);
 	for_primary_ifa(in_dev) {
 		if (ifa->ifa_scope > scope)
 			continue;
@@ -818,8 +821,8 @@ u32 inet_select_addr(const struct net_device *dev, u32 dst, int scope)
 		if (!addr)
 			addr = ifa->ifa_local;
 	} endfor_ifa(in_dev);
-	read_unlock(&in_dev->lock);
-	read_unlock(&inetdev_lock);
+no_in_dev:
+	rcu_read_unlock();
 
 	if (addr)
 		goto out;
@@ -829,30 +832,24 @@ u32 inet_select_addr(const struct net_device *dev, u32 dst, int scope)
 	   in dev_base list.
 	 */
 	read_lock(&dev_base_lock);
-	read_lock(&inetdev_lock);
+	rcu_read_lock();
 	for (dev = dev_base; dev; dev = dev->next) {
 		if ((in_dev = __in_dev_get(dev)) == NULL)
 			continue;
 
-		read_lock(&in_dev->lock);
 		for_primary_ifa(in_dev) {
 			if (ifa->ifa_scope != RT_SCOPE_LINK &&
 			    ifa->ifa_scope <= scope) {
-				read_unlock(&in_dev->lock);
 				addr = ifa->ifa_local;
 				goto out_unlock_both;
 			}
 		} endfor_ifa(in_dev);
-		read_unlock(&in_dev->lock);
 	}
 out_unlock_both:
-	read_unlock(&inetdev_lock);
 	read_unlock(&dev_base_lock);
+	rcu_read_unlock();
 out:
 	return addr;
-out_unlock_inetdev:
-	read_unlock(&inetdev_lock);
-	goto out;
 }
 
 static u32 confirm_addr_indev(struct in_device *in_dev, u32 dst,
@@ -905,29 +902,24 @@ u32 inet_confirm_addr(const struct net_device *dev, u32 dst, u32 local, int scop
 	struct in_device *in_dev;
 
 	if (dev) {
-		read_lock(&inetdev_lock);
-		if ((in_dev = __in_dev_get(dev))) {
-			read_lock(&in_dev->lock);
+		rcu_read_lock();
+		if ((in_dev = __in_dev_get(dev)))
 			addr = confirm_addr_indev(in_dev, dst, local, scope);
-			read_unlock(&in_dev->lock);
-		}
-		read_unlock(&inetdev_lock);
+		rcu_read_unlock();
 
 		return addr;
 	}
 
 	read_lock(&dev_base_lock);
-	read_lock(&inetdev_lock);
+	rcu_read_lock();
 	for (dev = dev_base; dev; dev = dev->next) {
 		if ((in_dev = __in_dev_get(dev))) {
-			read_lock(&in_dev->lock);
 			addr = confirm_addr_indev(in_dev, dst, local, scope);
-			read_unlock(&in_dev->lock);
 			if (addr)
 				break;
 		}
 	}
-	read_unlock(&inetdev_lock);
+	rcu_read_unlock();
 	read_unlock(&dev_base_lock);
 
 	return addr;
@@ -1087,6 +1079,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
 	struct net_device *dev;
 	struct in_device *in_dev;
 	struct in_ifaddr *ifa;
+	struct sock *sk = skb->sk;
 	int s_ip_idx, s_idx = cb->args[0];
 
 	s_ip_idx = ip_idx = cb->args[1];
@@ -1096,28 +1089,27 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
 			continue;
 		if (idx > s_idx)
 			s_ip_idx = 0;
-		read_lock(&inetdev_lock);
+		rcu_read_lock();
 		if ((in_dev = __in_dev_get(dev)) == NULL) {
-			read_unlock(&inetdev_lock);
+			rcu_read_unlock();
 			continue;
 		}
-		read_lock(&in_dev->lock);
+
 		for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
 		     ifa = ifa->ifa_next, ip_idx++) {
-			if (!ifa_in_nx_info(ifa, current->nx_info))
+			if (sk && vx_info_flags(sk->sk_vx_info, VXF_HIDE_NETIF, 0) &&
+				!ifa_in_nx_info(ifa, sk->sk_nx_info))
 				continue;
 			if (ip_idx < s_ip_idx)
 				continue;
 			if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
 					     cb->nlh->nlmsg_seq,
 					     RTM_NEWADDR) <= 0) {
-				read_unlock(&in_dev->lock);
-				read_unlock(&inetdev_lock);
+				rcu_read_unlock();
 				goto done;
 			}
 		}
-		read_unlock(&in_dev->lock);
-		read_unlock(&inetdev_lock);
+		rcu_read_unlock();
 	}
 
 done:
@@ -1171,11 +1163,11 @@ void inet_forward_change(void)
 	read_lock(&dev_base_lock);
 	for (dev = dev_base; dev; dev = dev->next) {
 		struct in_device *in_dev;
-		read_lock(&inetdev_lock);
+		rcu_read_lock();
 		in_dev = __in_dev_get(dev);
 		if (in_dev)
 			in_dev->cnf.forwarding = on;
-		read_unlock(&inetdev_lock);
+		rcu_read_unlock();
 	}
 	read_unlock(&dev_base_lock);
 
@@ -1541,6 +1533,5 @@ EXPORT_SYMBOL(devinet_ioctl);
 EXPORT_SYMBOL(in_dev_finish_destroy);
 EXPORT_SYMBOL(inet_select_addr);
 EXPORT_SYMBOL(inetdev_by_index);
-EXPORT_SYMBOL(inetdev_lock);
 EXPORT_SYMBOL(register_inetaddr_notifier);
 EXPORT_SYMBOL(unregister_inetaddr_notifier);
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 07a594b83..27d8f808b 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -17,10 +17,10 @@ struct esp_decap_data {
 	__u8		proto;
 };
 
-int esp_output(struct sk_buff **pskb)
+static int esp_output(struct sk_buff *skb)
 {
 	int err;
-	struct dst_entry *dst = (*pskb)->dst;
+	struct dst_entry *dst = skb->dst;
 	struct xfrm_state *x  = dst->xfrm;
 	struct iphdr *top_iph;
 	struct ip_esp_hdr *esph;
@@ -33,13 +33,13 @@ int esp_output(struct sk_buff **pskb)
 	int nfrags;
 
 	/* Strip IP+ESP header. */
-	__skb_pull(*pskb, (*pskb)->h.raw - (*pskb)->data);
+	__skb_pull(skb, skb->h.raw - skb->data);
 	/* Now skb is pure payload to encrypt */
 
 	err = -ENOMEM;
 
 	/* Round to block size */
-	clen = (*pskb)->len;
+	clen = skb->len;
 
 	esp = x->data;
 	alen = esp->auth.icv_trunc_len;
@@ -49,22 +49,22 @@ int esp_output(struct sk_buff **pskb)
 	if (esp->conf.padlen)
 		clen = (clen + esp->conf.padlen-1)&~(esp->conf.padlen-1);
 
-	if ((nfrags = skb_cow_data(*pskb, clen-(*pskb)->len+alen, &trailer)) < 0)
+	if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0)
 		goto error;
 
 	/* Fill padding... */
 	do {
 		int i;
-		for (i=0; i<clen-(*pskb)->len - 2; i++)
+		for (i=0; i<clen-skb->len - 2; i++)
 			*(u8*)(trailer->tail + i) = i+1;
 	} while (0);
-	*(u8*)(trailer->tail + clen-(*pskb)->len - 2) = (clen - (*pskb)->len)-2;
-	pskb_put(*pskb, trailer, clen - (*pskb)->len);
+	*(u8*)(trailer->tail + clen-skb->len - 2) = (clen - skb->len)-2;
+	pskb_put(skb, trailer, clen - skb->len);
 
-	__skb_push(*pskb, (*pskb)->data - (*pskb)->nh.raw);
-	top_iph = (*pskb)->nh.iph;
-	esph = (struct ip_esp_hdr *)((*pskb)->nh.raw + top_iph->ihl*4);
-	top_iph->tot_len = htons((*pskb)->len + alen);
+	__skb_push(skb, skb->data - skb->nh.raw);
+	top_iph = skb->nh.iph;
+	esph = (struct ip_esp_hdr *)(skb->nh.raw + top_iph->ihl*4);
+	top_iph->tot_len = htons(skb->len + alen);
 	*(u8*)(trailer->tail - 1) = top_iph->protocol;
 
 	/* this is non-NULL only with UDP Encapsulation */
@@ -76,7 +76,7 @@ int esp_output(struct sk_buff **pskb)
 		uh = (struct udphdr *)esph;
 		uh->source = encap->encap_sport;
 		uh->dest = encap->encap_dport;
-		uh->len = htons((*pskb)->len + alen - top_iph->ihl*4);
+		uh->len = htons(skb->len + alen - top_iph->ihl*4);
 		uh->check = 0;
 
 		switch (encap->encap_type) {
@@ -109,7 +109,7 @@ int esp_output(struct sk_buff **pskb)
 			if (!sg)
 				goto error;
 		}
-		skb_to_sgvec(*pskb, sg, esph->enc_data+esp->conf.ivlen-(*pskb)->data, clen);
+		skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen);
 		crypto_cipher_encrypt(tfm, sg, sg, clen);
 		if (unlikely(sg != &esp->sgbuf[0]))
 			kfree(sg);
@@ -121,9 +121,9 @@ int esp_output(struct sk_buff **pskb)
 	}
 
 	if (esp->auth.icv_full_len) {
-		esp->auth.icv(esp, *pskb, (u8*)esph-(*pskb)->data,
+		esp->auth.icv(esp, skb, (u8*)esph-skb->data,
 		              sizeof(struct ip_esp_hdr) + esp->conf.ivlen+clen, trailer->tail);
-		pskb_put(*pskb, trailer, alen);
+		pskb_put(skb, trailer, alen);
 	}
 
 	ip_send_check(top_iph);
@@ -139,7 +139,7 @@ error:
  * expensive, so we only support truncated data, which is the recommended
  * and common case.
  */
-int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
 {
 	struct iphdr *iph;
 	struct ip_esp_hdr *esph;
@@ -246,7 +246,7 @@ out:
 	return -EINVAL;
 }
 
-int esp_post_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int esp_post_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
 {
   
 	if (x->encap) {
@@ -320,7 +320,7 @@ static u32 esp4_get_max_size(struct xfrm_state *x, int mtu)
 	return mtu + x->props.header_len + esp->auth.icv_trunc_len;
 }
 
-void esp4_err(struct sk_buff *skb, u32 info)
+static void esp4_err(struct sk_buff *skb, u32 info)
 {
 	struct iphdr *iph = (struct iphdr*)skb->data;
 	struct ip_esp_hdr *esph = (struct ip_esp_hdr*)(skb->data+(iph->ihl<<2));
@@ -338,7 +338,7 @@ void esp4_err(struct sk_buff *skb, u32 info)
 	xfrm_state_put(x);
 }
 
-void esp_destroy(struct xfrm_state *x)
+static void esp_destroy(struct xfrm_state *x)
 {
 	struct esp_data *esp = x->data;
 
@@ -364,7 +364,7 @@ void esp_destroy(struct xfrm_state *x)
 	kfree(esp);
 }
 
-int esp_init_state(struct xfrm_state *x, void *args)
+static int esp_init_state(struct xfrm_state *x, void *args)
 {
 	struct esp_data *esp = NULL;
 
@@ -436,6 +436,7 @@ int esp_init_state(struct xfrm_state *x, void *args)
 
 		switch (encap->encap_type) {
 		default:
+			goto error;
 		case UDP_ENCAP_ESPINUDP:
 			x->props.header_len += sizeof(struct udphdr);
 			break;
@@ -449,15 +450,9 @@ int esp_init_state(struct xfrm_state *x, void *args)
 	return 0;
 
 error:
-	if (esp) {
-		if (esp->auth.tfm)
-			crypto_free_tfm(esp->auth.tfm);
-		if (esp->auth.work_icv)
-			kfree(esp->auth.work_icv);
-		if (esp->conf.tfm)
-			crypto_free_tfm(esp->conf.tfm);
-		kfree(esp);
-	}
+	x->data = esp;
+	esp_destroy(x);
+	x->data = NULL;
 	return -EINVAL;
 }
 
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index f5b008a9d..f13e797c3 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -172,13 +172,13 @@ int fib_validate_source(u32 src, u32 dst, u8 tos, int oif,
 	int ret;
 
 	no_addr = rpf = 0;
-	read_lock(&inetdev_lock);
+	rcu_read_lock();
 	in_dev = __in_dev_get(dev);
 	if (in_dev) {
 		no_addr = in_dev->ifa_list == NULL;
 		rpf = IN_DEV_RPFILTER(in_dev);
 	}
-	read_unlock(&inetdev_lock);
+	rcu_read_unlock();
 
 	if (in_dev == NULL)
 		goto e_inval;
diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
index 3b4f8e35e..25535ff4f 100644
--- a/net/ipv4/fib_hash.c
+++ b/net/ipv4/fib_hash.c
@@ -43,159 +43,106 @@
 #include <net/sock.h>
 #include <net/ip_fib.h>
 
-#define FTprint(a...)
-/*
-   printk(KERN_DEBUG a)
- */
-
-static kmem_cache_t * fn_hash_kmem;
-
-/*
-   These bizarre types are just to force strict type checking.
-   When I reversed order of bytes and changed to natural mask lengths,
-   I forgot to make fixes in several places. Now I am lazy to return
-   it back.
- */
+#include "fib_lookup.h"
 
-typedef struct {
-	u32	datum;
-} fn_key_t;
+static kmem_cache_t *fn_hash_kmem;
+static kmem_cache_t *fn_alias_kmem;
 
-typedef struct {
-	u32	datum;
-} fn_hash_idx_t;
-
-struct fib_node
-{
-	struct fib_node		*fn_next;
-	struct fib_info		*fn_info;
-#define FIB_INFO(f)	((f)->fn_info)
-	fn_key_t		fn_key;
-	u8			fn_tos;
-	u8			fn_type;
-	u8			fn_scope;
-	u8			fn_state;
+struct fib_node {
+	struct hlist_node	fn_hash;
+	struct list_head	fn_alias;
+	u32			fn_key;
 };
 
-#define FN_S_ZOMBIE	1
-#define FN_S_ACCESSED	2
-
-static int fib_hash_zombies;
-
-struct fn_zone
-{
-	struct fn_zone	*fz_next;	/* Next not empty zone	*/
-	struct fib_node	**fz_hash;	/* Hash table pointer	*/
-	int		fz_nent;	/* Number of entries	*/
+struct fn_zone {
+	struct fn_zone		*fz_next;	/* Next not empty zone	*/
+	struct hlist_head	*fz_hash;	/* Hash table pointer	*/
+	int			fz_nent;	/* Number of entries	*/
 
-	int		fz_divisor;	/* Hash divisor		*/
-	u32		fz_hashmask;	/* (fz_divisor - 1)	*/
-#define FZ_HASHMASK(fz)	((fz)->fz_hashmask)
+	int			fz_divisor;	/* Hash divisor		*/
+	u32			fz_hashmask;	/* (fz_divisor - 1)	*/
+#define FZ_HASHMASK(fz)		((fz)->fz_hashmask)
 
-	int		fz_order;	/* Zone order		*/
-	u32		fz_mask;
-#define FZ_MASK(fz)	((fz)->fz_mask)
+	int			fz_order;	/* Zone order		*/
+	u32			fz_mask;
+#define FZ_MASK(fz)		((fz)->fz_mask)
 };
 
 /* NOTE. On fast computers evaluation of fz_hashmask and fz_mask
-   can be cheaper than memory lookup, so that FZ_* macros are used.
+ * can be cheaper than memory lookup, so that FZ_* macros are used.
  */
 
-struct fn_hash
-{
+struct fn_hash {
 	struct fn_zone	*fn_zones[33];
 	struct fn_zone	*fn_zone_list;
 };
 
-static __inline__ fn_hash_idx_t fn_hash(fn_key_t key, struct fn_zone *fz)
+static inline u32 fn_hash(u32 key, struct fn_zone *fz)
 {
-	u32 h = ntohl(key.datum)>>(32 - fz->fz_order);
+	u32 h = ntohl(key)>>(32 - fz->fz_order);
 	h ^= (h>>20);
 	h ^= (h>>10);
 	h ^= (h>>5);
 	h &= FZ_HASHMASK(fz);
-	return *(fn_hash_idx_t*)&h;
-}
-
-#define fz_key_0(key)		((key).datum = 0)
-#define fz_prefix(key,fz)	((key).datum)
-
-static __inline__ fn_key_t fz_key(u32 dst, struct fn_zone *fz)
-{
-	fn_key_t k;
-	k.datum = dst & FZ_MASK(fz);
-	return k;
-}
-
-static __inline__ struct fib_node ** fz_chain_p(fn_key_t key, struct fn_zone *fz)
-{
-	return &fz->fz_hash[fn_hash(key, fz).datum];
-}
-
-static __inline__ struct fib_node * fz_chain(fn_key_t key, struct fn_zone *fz)
-{
-	return fz->fz_hash[fn_hash(key, fz).datum];
+	return h;
 }
 
-static __inline__ int fn_key_eq(fn_key_t a, fn_key_t b)
+static inline u32 fz_key(u32 dst, struct fn_zone *fz)
 {
-	return a.datum == b.datum;
-}
-
-static __inline__ int fn_key_leq(fn_key_t a, fn_key_t b)
-{
-	return a.datum <= b.datum;
+	return dst & FZ_MASK(fz);
 }
 
 static rwlock_t fib_hash_lock = RW_LOCK_UNLOCKED;
 
-#define FZ_MAX_DIVISOR ((PAGE_SIZE<<MAX_ORDER) / sizeof(struct fib_node *))
+#define FZ_MAX_DIVISOR ((PAGE_SIZE<<MAX_ORDER) / sizeof(struct hlist_head))
 
-static struct fib_node **fz_hash_alloc(int divisor)
+static struct hlist_head *fz_hash_alloc(int divisor)
 {
-	unsigned long size = divisor * sizeof(struct fib_node *);
+	unsigned long size = divisor * sizeof(struct hlist_head);
 
-	if (divisor <= 1024) {
+	if (size <= PAGE_SIZE) {
 		return kmalloc(size, GFP_KERNEL);
 	} else {
-		return (struct fib_node **)
+		return (struct hlist_head *)
 			__get_free_pages(GFP_KERNEL, get_order(size));
 	}
 }
 
 /* The fib hash lock must be held when this is called. */
-static __inline__ void fn_rebuild_zone(struct fn_zone *fz,
-				       struct fib_node **old_ht,
-				       int old_divisor)
+static inline void fn_rebuild_zone(struct fn_zone *fz,
+				   struct hlist_head *old_ht,
+				   int old_divisor)
 {
 	int i;
-	struct fib_node *f, **fp, *next;
-
-	for (i=0; i<old_divisor; i++) {
-		for (f=old_ht[i]; f; f=next) {
-			next = f->fn_next;
-			for (fp = fz_chain_p(f->fn_key, fz);
-			     *fp && fn_key_leq((*fp)->fn_key, f->fn_key);
-			     fp = &(*fp)->fn_next)
-				/* NONE */;
-			f->fn_next = *fp;
-			*fp = f;
+
+	for (i = 0; i < old_divisor; i++) {
+		struct hlist_node *node, *n;
+		struct fib_node *f;
+
+		hlist_for_each_entry_safe(f, node, n, &old_ht[i], fn_hash) {
+			struct hlist_head *new_head;
+
+			hlist_del(&f->fn_hash);
+
+			new_head = &fz->fz_hash[fn_hash(f->fn_key, fz)];
+			hlist_add_head(&f->fn_hash, new_head);
 		}
 	}
 }
 
-static void fz_hash_free(struct fib_node **hash, int divisor)
+static void fz_hash_free(struct hlist_head *hash, int divisor)
 {
-	if (divisor <= 1024)
+	unsigned long size = divisor * sizeof(struct hlist_head);
+
+	if (size <= PAGE_SIZE)
 		kfree(hash);
 	else
-		free_pages((unsigned long) hash,
-			   get_order(divisor * sizeof(struct fib_node *)));
+		free_pages((unsigned long)hash, get_order(size));
 }
 
 static void fn_rehash_zone(struct fn_zone *fz)
 {
-	struct fib_node **ht, **old_ht;
+	struct hlist_head *ht, *old_ht;
 	int old_divisor, new_divisor;
 	u32 new_hashmask;
 		
@@ -226,7 +173,7 @@ static void fn_rehash_zone(struct fn_zone *fz)
 	ht = fz_hash_alloc(new_divisor);
 
 	if (ht)	{
-		memset(ht, 0, new_divisor*sizeof(struct fib_node*));
+		memset(ht, 0, new_divisor * sizeof(struct hlist_head));
 
 		write_lock_bh(&fib_hash_lock);
 		old_ht = fz->fz_hash;
@@ -240,12 +187,16 @@ static void fn_rehash_zone(struct fn_zone *fz)
 	}
 }
 
-static void fn_free_node(struct fib_node * f)
+static inline void fn_free_node(struct fib_node * f)
 {
-	fib_release_info(FIB_INFO(f));
 	kmem_cache_free(fn_hash_kmem, f);
 }
 
+static inline void fn_free_alias(struct fib_alias *fa)
+{
+	fib_release_info(fa->fa_info);
+	kmem_cache_free(fn_alias_kmem, fa);
+}
 
 static struct fn_zone *
 fn_new_zone(struct fn_hash *table, int z)
@@ -267,7 +218,7 @@ fn_new_zone(struct fn_hash *table, int z)
 		kfree(fz);
 		return NULL;
 	}
-	memset(fz->fz_hash, 0, fz->fz_divisor*sizeof(struct fib_node*));
+	memset(fz->fz_hash, 0, fz->fz_divisor * sizeof(struct hlist_head *));
 	fz->fz_order = z;
 	fz->fz_mask = inet_make_mask(z);
 
@@ -298,35 +249,20 @@ fn_hash_lookup(struct fib_table *tb, const struct flowi *flp, struct fib_result
 
 	read_lock(&fib_hash_lock);
 	for (fz = t->fn_zone_list; fz; fz = fz->fz_next) {
+		struct hlist_head *head;
+		struct hlist_node *node;
 		struct fib_node *f;
-		fn_key_t k = fz_key(flp->fl4_dst, fz);
+		u32 k = fz_key(flp->fl4_dst, fz);
 
-		for (f = fz_chain(k, fz); f; f = f->fn_next) {
-			if (!fn_key_eq(k, f->fn_key)) {
-				if (fn_key_leq(k, f->fn_key))
-					break;
-				else
-					continue;
-			}
-#ifdef CONFIG_IP_ROUTE_TOS
-			if (f->fn_tos && f->fn_tos != flp->fl4_tos)
-				continue;
-#endif
-			f->fn_state |= FN_S_ACCESSED;
-
-			if (f->fn_state&FN_S_ZOMBIE)
-				continue;
-			if (f->fn_scope < flp->fl4_scope)
+		head = &fz->fz_hash[fn_hash(k, fz)];
+		hlist_for_each_entry(f, node, head, fn_hash) {
+			if (f->fn_key != k)
 				continue;
 
-			err = fib_semantic_match(f->fn_type, FIB_INFO(f), flp, res);
-			if (err == 0) {
-				res->type = f->fn_type;
-				res->scope = f->fn_scope;
-				res->prefixlen = fz->fz_order;
-				goto out;
-			}
-			if (err < 0)
+			err = fib_semantic_match(&f->fn_alias,
+						 flp, res,
+						 fz->fz_order);
+			if (err <= 0)
 				goto out;
 		}
 	}
@@ -365,6 +301,7 @@ static void
 fn_hash_select_default(struct fib_table *tb, const struct flowi *flp, struct fib_result *res)
 {
 	int order, last_idx;
+	struct hlist_node *node;
 	struct fib_node *f;
 	struct fib_info *fi = NULL;
 	struct fib_info *last_resort;
@@ -379,36 +316,41 @@ fn_hash_select_default(struct fib_table *tb, const struct flowi *flp, struct fib
 	order = -1;
 
 	read_lock(&fib_hash_lock);
-	for (f = fz->fz_hash[0]; f; f = f->fn_next) {
-		struct fib_info *next_fi = FIB_INFO(f);
+	hlist_for_each_entry(f, node, &fz->fz_hash[0], fn_hash) {
+		struct fib_alias *fa;
 
-		if ((f->fn_state&FN_S_ZOMBIE) ||
-		    f->fn_scope != res->scope ||
-		    f->fn_type != RTN_UNICAST)
-			continue;
+		list_for_each_entry(fa, &f->fn_alias, fa_list) {
+			struct fib_info *next_fi = fa->fa_info;
 
-		if (next_fi->fib_priority > res->fi->fib_priority)
-			break;
-		if (!next_fi->fib_nh[0].nh_gw || next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
-			continue;
-		f->fn_state |= FN_S_ACCESSED;
+			if (fa->fa_scope != res->scope ||
+			    fa->fa_type != RTN_UNICAST)
+				continue;
 
-		if (fi == NULL) {
-			if (next_fi != res->fi)
+			if (next_fi->fib_priority > res->fi->fib_priority)
 				break;
-		} else if (!fib_detect_death(fi, order, &last_resort, &last_idx)) {
-			if (res->fi)
-				fib_info_put(res->fi);
-			res->fi = fi;
-			atomic_inc(&fi->fib_clntref);
-			fn_hash_last_dflt = order;
-			goto out;
+			if (!next_fi->fib_nh[0].nh_gw ||
+			    next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
+				continue;
+			fa->fa_state |= FA_S_ACCESSED;
+
+			if (fi == NULL) {
+				if (next_fi != res->fi)
+					break;
+			} else if (!fib_detect_death(fi, order, &last_resort,
+						     &last_idx)) {
+				if (res->fi)
+					fib_info_put(res->fi);
+				res->fi = fi;
+				atomic_inc(&fi->fib_clntref);
+				fn_hash_last_dflt = order;
+				goto out;
+			}
+			fi = next_fi;
+			order++;
 		}
-		fi = next_fi;
-		order++;
 	}
 
-	if (order<=0 || fi==NULL) {
+	if (order <= 0 || fi == NULL) {
 		fn_hash_last_dflt = -1;
 		goto out;
 	}
@@ -434,52 +376,76 @@ out:
 	read_unlock(&fib_hash_lock);
 }
 
-#define FIB_SCAN(f, fp) \
-for ( ; ((f) = *(fp)) != NULL; (fp) = &(f)->fn_next)
+static void rtmsg_fib(int, struct fib_node *, struct fib_alias *,
+		      int, int,
+		      struct nlmsghdr *n,
+		      struct netlink_skb_parms *);
 
-#define FIB_SCAN_KEY(f, fp, key) \
-for ( ; ((f) = *(fp)) != NULL && fn_key_eq((f)->fn_key, (key)); (fp) = &(f)->fn_next)
+/* Insert node F to FZ. */
+static inline void fib_insert_node(struct fn_zone *fz, struct fib_node *f)
+{
+	struct hlist_head *head = &fz->fz_hash[fn_hash(f->fn_key, fz)];
 
-#ifndef CONFIG_IP_ROUTE_TOS
-#define FIB_SCAN_TOS(f, fp, key, tos) FIB_SCAN_KEY(f, fp, key)
-#else
-#define FIB_SCAN_TOS(f, fp, key, tos) \
-for ( ; ((f) = *(fp)) != NULL && fn_key_eq((f)->fn_key, (key)) && \
-     (f)->fn_tos == (tos) ; (fp) = &(f)->fn_next)
-#endif
+	hlist_add_head(&f->fn_hash, head);
+}
 
+/* Return the node in FZ matching KEY. */
+static struct fib_node *fib_find_node(struct fn_zone *fz, u32 key)
+{
+	struct hlist_head *head = &fz->fz_hash[fn_hash(key, fz)];
+	struct hlist_node *node;
+	struct fib_node *f;
 
-static void rtmsg_fib(int, struct fib_node*, int, int,
-		      struct nlmsghdr *n,
-		      struct netlink_skb_parms *);
+	hlist_for_each_entry(f, node, head, fn_hash) {
+		if (f->fn_key == key)
+			return f;
+	}
+
+	return NULL;
+}
+
+/* Return the first fib alias matching TOS with
+ * priority less than or equal to PRIO.
+ */
+static struct fib_alias *fib_find_alias(struct fib_node *fn, u8 tos, u32 prio)
+{
+	if (fn) {
+		struct list_head *head = &fn->fn_alias;
+		struct fib_alias *fa;
+
+		list_for_each_entry(fa, head, fa_list) {
+			if (fa->fa_tos > tos)
+				continue;
+			if (fa->fa_info->fib_priority >= prio ||
+			    fa->fa_tos < tos)
+				return fa;
+		}
+	}
+	return NULL;
+}
 
 static int
 fn_hash_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
-		struct nlmsghdr *n, struct netlink_skb_parms *req)
+	       struct nlmsghdr *n, struct netlink_skb_parms *req)
 {
-	struct fn_hash *table = (struct fn_hash*)tb->tb_data;
-	struct fib_node *new_f, *f, **fp, **del_fp;
+	struct fn_hash *table = (struct fn_hash *) tb->tb_data;
+	struct fib_node *new_f, *f;
+	struct fib_alias *fa, *new_fa;
 	struct fn_zone *fz;
 	struct fib_info *fi;
-
 	int z = r->rtm_dst_len;
 	int type = r->rtm_type;
-#ifdef CONFIG_IP_ROUTE_TOS
 	u8 tos = r->rtm_tos;
-#endif
-	fn_key_t key;
+	u32 key;
 	int err;
 
-FTprint("tb(%d)_insert: %d %08x/%d %d %08x\n", tb->tb_id, r->rtm_type, rta->rta_dst ?
-*(u32*)rta->rta_dst : 0, z, rta->rta_oif ? *rta->rta_oif : -1,
-rta->rta_prefsrc ? *(u32*)rta->rta_prefsrc : 0);
 	if (z > 32)
 		return -EINVAL;
 	fz = table->fn_zones[z];
 	if (!fz && !(fz = fn_new_zone(table, z)))
 		return -ENOBUFS;
 
-	fz_key_0(key);
+	key = 0;
 	if (rta->rta_dst) {
 		u32 dst;
 		memcpy(&dst, rta->rta_dst, 4);
@@ -496,136 +462,114 @@ rta->rta_prefsrc ? *(u32*)rta->rta_prefsrc : 0);
 	    (z==32 || (1<<z) > fz->fz_divisor))
 		fn_rehash_zone(fz);
 
-	fp = fz_chain_p(key, fz);
-
-
-	/*
-	 * Scan list to find the first route with the same destination
+	f = fib_find_node(fz, key);
+	fa = fib_find_alias(f, tos, fi->fib_priority);
+
+	/* Now fa, if non-NULL, points to the first fib alias
+	 * with the same keys [prefix,tos,priority], if such key already
+	 * exists or to the node before which we will insert new one.
+	 *
+	 * If fa is NULL, we will need to allocate a new one and
+	 * insert to the head of f.
+	 *
+	 * If f is NULL, no fib node matched the destination key
+	 * and we need to allocate a new one of those as well.
 	 */
-	FIB_SCAN(f, fp) {
-		if (fn_key_leq(key,f->fn_key))
-			break;
-	}
 
-#ifdef CONFIG_IP_ROUTE_TOS
-	/*
-	 * Find route with the same destination and tos.
-	 */
-	FIB_SCAN_KEY(f, fp, key) {
-		if (f->fn_tos <= tos)
-			break;
-	}
-#endif
-
-	del_fp = NULL;
-
-	if (f && (f->fn_state&FN_S_ZOMBIE) &&
-#ifdef CONFIG_IP_ROUTE_TOS
-	    f->fn_tos == tos &&
-#endif
-	    fn_key_eq(f->fn_key, key)) {
-		del_fp = fp;
-		fp = &f->fn_next;
-		f = *fp;
-		goto create;
-	}
-
-	FIB_SCAN_TOS(f, fp, key, tos) {
-		if (fi->fib_priority <= FIB_INFO(f)->fib_priority)
-			break;
-	}
-
-	/* Now f==*fp points to the first node with the same
-	   keys [prefix,tos,priority], if such key already
-	   exists or to the node, before which we will insert new one.
-	 */
-
-	if (f && 
-#ifdef CONFIG_IP_ROUTE_TOS
-	    f->fn_tos == tos &&
-#endif
-	    fn_key_eq(f->fn_key, key) &&
-	    fi->fib_priority == FIB_INFO(f)->fib_priority) {
-		struct fib_node **ins_fp;
+	if (fa && fa->fa_tos == tos &&
+	    fa->fa_info->fib_priority == fi->fib_priority) {
+		struct fib_alias *fa_orig;
 
 		err = -EEXIST;
-		if (n->nlmsg_flags&NLM_F_EXCL)
+		if (n->nlmsg_flags & NLM_F_EXCL)
 			goto out;
 
-		if (n->nlmsg_flags&NLM_F_REPLACE) {
-			del_fp = fp;
-			fp = &f->fn_next;
-			f = *fp;
-			goto replace;
-		}
+		if (n->nlmsg_flags & NLM_F_REPLACE) {
+			struct fib_info *fi_drop;
+			u8 state;
 
-		ins_fp = fp;
-		err = -EEXIST;
+			write_lock_bh(&fib_hash_lock);
+			fi_drop = fa->fa_info;
+			fa->fa_info = fi;
+			fa->fa_type = type;
+			fa->fa_scope = r->rtm_scope;
+			state = fa->fa_state;
+			fa->fa_state &= ~FA_S_ACCESSED;
+			write_unlock_bh(&fib_hash_lock);
 
-		FIB_SCAN_TOS(f, fp, key, tos) {
-			if (fi->fib_priority != FIB_INFO(f)->fib_priority)
-				break;
-			if (f->fn_type == type && f->fn_scope == r->rtm_scope
-			    && FIB_INFO(f) == fi)
-				goto out;
+			fib_release_info(fi_drop);
+			if (state & FA_S_ACCESSED)
+				rt_cache_flush(-1);
+			return 0;
 		}
 
-		if (!(n->nlmsg_flags&NLM_F_APPEND)) {
-			fp = ins_fp;
-			f = *fp;
+		/* Error if we find a perfect match which
+		 * uses the same scope, type, and nexthop
+		 * information.
+		 */
+		fa_orig = fa;
+		fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
+		list_for_each_entry_continue(fa, &f->fn_alias, fa_list) {
+			if (fa->fa_tos != tos)
+				break;
+			if (fa->fa_info->fib_priority != fi->fib_priority)
+				break;
+			if (fa->fa_type == type &&
+			    fa->fa_scope == r->rtm_scope &&
+			    fa->fa_info == fi)
+				goto out;
 		}
+		if (!(n->nlmsg_flags & NLM_F_APPEND))
+			fa = fa_orig;
 	}
 
-create:
 	err = -ENOENT;
 	if (!(n->nlmsg_flags&NLM_F_CREATE))
 		goto out;
 
-replace:
 	err = -ENOBUFS;
-	new_f = kmem_cache_alloc(fn_hash_kmem, SLAB_KERNEL);
-	if (new_f == NULL)
+	new_fa = kmem_cache_alloc(fn_alias_kmem, SLAB_KERNEL);
+	if (new_fa == NULL)
 		goto out;
 
-	memset(new_f, 0, sizeof(struct fib_node));
+	new_f = NULL;
+	if (!f) {
+		new_f = kmem_cache_alloc(fn_hash_kmem, SLAB_KERNEL);
+		if (new_f == NULL)
+			goto out_free_new_fa;
 
-	new_f->fn_key = key;
-#ifdef CONFIG_IP_ROUTE_TOS
-	new_f->fn_tos = tos;
-#endif
-	new_f->fn_type = type;
-	new_f->fn_scope = r->rtm_scope;
-	FIB_INFO(new_f) = fi;
+		INIT_HLIST_NODE(&new_f->fn_hash);
+		INIT_LIST_HEAD(&new_f->fn_alias);
+		new_f->fn_key = key;
+		f = new_f;
+	}
+
+	new_fa->fa_info = fi;
+	new_fa->fa_tos = tos;
+	new_fa->fa_type = type;
+	new_fa->fa_scope = r->rtm_scope;
+	new_fa->fa_state = 0;
 
 	/*
 	 * Insert new entry to the list.
 	 */
 
-	new_f->fn_next = f;
 	write_lock_bh(&fib_hash_lock);
-	*fp = new_f;
+	if (new_f)
+		fib_insert_node(fz, new_f);
+	list_add_tail(&new_fa->fa_list,
+		 (fa ? &fa->fa_list : &f->fn_alias));
 	write_unlock_bh(&fib_hash_lock);
-	fz->fz_nent++;
 
-	if (del_fp) {
-		f = *del_fp;
-		/* Unlink replaced node */
-		write_lock_bh(&fib_hash_lock);
-		*del_fp = f->fn_next;
-		write_unlock_bh(&fib_hash_lock);
+	if (new_f)
+		fz->fz_nent++;
+	rt_cache_flush(-1);
 
-		if (!(f->fn_state&FN_S_ZOMBIE))
-			rtmsg_fib(RTM_DELROUTE, f, z, tb->tb_id, n, req);
-		if (f->fn_state&FN_S_ACCESSED)
-			rt_cache_flush(-1);
-		fn_free_node(f);
-		fz->fz_nent--;
-	} else {
-		rt_cache_flush(-1);
-	}
-	rtmsg_fib(RTM_NEWROUTE, new_f, z, tb->tb_id, n, req);
+	rtmsg_fib(RTM_NEWROUTE, f, new_fa, z, tb->tb_id, n, req);
 	return 0;
 
+out_free_new_fa:
+	kmem_cache_free(fn_alias_kmem, new_fa);
 out:
 	fib_release_info(fi);
 	return err;
@@ -634,26 +578,22 @@ out:
 
 static int
 fn_hash_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
-		struct nlmsghdr *n, struct netlink_skb_parms *req)
+	       struct nlmsghdr *n, struct netlink_skb_parms *req)
 {
 	struct fn_hash *table = (struct fn_hash*)tb->tb_data;
-	struct fib_node **fp, **del_fp, *f;
+	struct fib_node *f;
+	struct fib_alias *fa, *fa_to_delete;
 	int z = r->rtm_dst_len;
 	struct fn_zone *fz;
-	fn_key_t key;
-	int matched;
-#ifdef CONFIG_IP_ROUTE_TOS
+	u32 key;
 	u8 tos = r->rtm_tos;
-#endif
 
-FTprint("tb(%d)_delete: %d %08x/%d %d\n", tb->tb_id, r->rtm_type, rta->rta_dst ?
-       *(u32*)rta->rta_dst : 0, z, rta->rta_oif ? *rta->rta_oif : -1);
 	if (z > 32)
 		return -EINVAL;
 	if ((fz  = table->fn_zones[z]) == NULL)
 		return -ESRCH;
 
-	fz_key_0(key);
+	key = 0;
 	if (rta->rta_dst) {
 		u32 dst;
 		memcpy(&dst, rta->rta_dst, 4);
@@ -662,62 +602,52 @@ FTprint("tb(%d)_delete: %d %08x/%d %d\n", tb->tb_id, r->rtm_type, rta->rta_dst ?
 		key = fz_key(dst, fz);
 	}
 
-	fp = fz_chain_p(key, fz);
+	f = fib_find_node(fz, key);
+	fa = fib_find_alias(f, tos, 0);
+	if (!fa)
+		return -ESRCH;
 
+	fa_to_delete = NULL;
+	fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
+	list_for_each_entry_continue(fa, &f->fn_alias, fa_list) {
+		struct fib_info *fi = fa->fa_info;
 
-	FIB_SCAN(f, fp) {
-		if (fn_key_eq(f->fn_key, key))
+		if (fa->fa_tos != tos)
 			break;
-		if (fn_key_leq(key, f->fn_key)) {
-			return -ESRCH;
-		}
-	}
-#ifdef CONFIG_IP_ROUTE_TOS
-	FIB_SCAN_KEY(f, fp, key) {
-		if (f->fn_tos == tos)
-			break;
-	}
-#endif
-
-	matched = 0;
-	del_fp = NULL;
-	FIB_SCAN_TOS(f, fp, key, tos) {
-		struct fib_info * fi = FIB_INFO(f);
 
-		if (f->fn_state&FN_S_ZOMBIE) {
-			return -ESRCH;
+		if ((!r->rtm_type ||
+		     fa->fa_type == r->rtm_type) &&
+		    (r->rtm_scope == RT_SCOPE_NOWHERE ||
+		     fa->fa_scope == r->rtm_scope) &&
+		    (!r->rtm_protocol ||
+		     fi->fib_protocol == r->rtm_protocol) &&
+		    fib_nh_match(r, n, rta, fi) == 0) {
+			fa_to_delete = fa;
+			break;
 		}
-		matched++;
-
-		if (del_fp == NULL &&
-		    (!r->rtm_type || f->fn_type == r->rtm_type) &&
-		    (r->rtm_scope == RT_SCOPE_NOWHERE || f->fn_scope == r->rtm_scope) &&
-		    (!r->rtm_protocol || fi->fib_protocol == r->rtm_protocol) &&
-		    fib_nh_match(r, n, rta, fi) == 0)
-			del_fp = fp;
 	}
 
-	if (del_fp) {
-		f = *del_fp;
-		rtmsg_fib(RTM_DELROUTE, f, z, tb->tb_id, n, req);
+	if (fa_to_delete) {
+		int kill_fn;
 
-		if (matched != 1) {
-			write_lock_bh(&fib_hash_lock);
-			*del_fp = f->fn_next;
-			write_unlock_bh(&fib_hash_lock);
+		fa = fa_to_delete;
+		rtmsg_fib(RTM_DELROUTE, f, fa, z, tb->tb_id, n, req);
 
-			if (f->fn_state&FN_S_ACCESSED)
-				rt_cache_flush(-1);
+		kill_fn = 0;
+		write_lock_bh(&fib_hash_lock);
+		list_del(&fa->fa_list);
+		if (list_empty(&f->fn_alias)) {
+			hlist_del(&f->fn_hash);
+			kill_fn = 1;
+		}
+		write_unlock_bh(&fib_hash_lock);
+
+		if (fa->fa_state & FA_S_ACCESSED)
+			rt_cache_flush(-1);
+		fn_free_alias(fa);
+		if (kill_fn) {
 			fn_free_node(f);
 			fz->fz_nent--;
-		} else {
-			f->fn_state |= FN_S_ZOMBIE;
-			if (f->fn_state&FN_S_ACCESSED) {
-				f->fn_state &= ~FN_S_ACCESSED;
-				rt_cache_flush(-1);
-			}
-			if (++fib_hash_zombies > 128)
-				fib_flush();
 		}
 
 		return 0;
@@ -725,74 +655,99 @@ FTprint("tb(%d)_delete: %d %08x/%d %d\n", tb->tb_id, r->rtm_type, rta->rta_dst ?
 	return -ESRCH;
 }
 
-static __inline__ int
-fn_flush_list(struct fib_node ** fp, int z, struct fn_hash *table)
+static int fn_flush_list(struct fn_zone *fz, int idx)
 {
-	int found = 0;
+	struct hlist_head *head = &fz->fz_hash[idx];
+	struct hlist_node *node, *n;
 	struct fib_node *f;
+	int found = 0;
 
-	while ((f = *fp) != NULL) {
-		struct fib_info *fi = FIB_INFO(f);
-
-		if (fi && ((f->fn_state&FN_S_ZOMBIE) || (fi->fib_flags&RTNH_F_DEAD))) {
-			write_lock_bh(&fib_hash_lock);
-			*fp = f->fn_next;
-			write_unlock_bh(&fib_hash_lock);
-
+	hlist_for_each_entry_safe(f, node, n, head, fn_hash) {
+		struct fib_alias *fa, *fa_node;
+		int kill_f;
+
+		kill_f = 0;
+		list_for_each_entry_safe(fa, fa_node, &f->fn_alias, fa_list) {
+			struct fib_info *fi = fa->fa_info;
+
+			if (fi && (fi->fib_flags&RTNH_F_DEAD)) {
+				write_lock_bh(&fib_hash_lock);
+				list_del(&fa->fa_list);
+				if (list_empty(&f->fn_alias)) {
+					hlist_del(&f->fn_hash);
+					kill_f = 1;
+				}
+				write_unlock_bh(&fib_hash_lock);
+
+				fn_free_alias(fa);
+				found++;
+			}
+		}
+		if (kill_f) {
 			fn_free_node(f);
-			found++;
-			continue;
+			fz->fz_nent--;
 		}
-		fp = &f->fn_next;
 	}
 	return found;
 }
 
 static int fn_hash_flush(struct fib_table *tb)
 {
-	struct fn_hash *table = (struct fn_hash*)tb->tb_data;
+	struct fn_hash *table = (struct fn_hash *) tb->tb_data;
 	struct fn_zone *fz;
 	int found = 0;
 
-	fib_hash_zombies = 0;
 	for (fz = table->fn_zone_list; fz; fz = fz->fz_next) {
 		int i;
-		int tmp = 0;
-		for (i=fz->fz_divisor-1; i>=0; i--)
-			tmp += fn_flush_list(&fz->fz_hash[i], fz->fz_order, table);
-		fz->fz_nent -= tmp;
-		found += tmp;
+
+		for (i = fz->fz_divisor - 1; i >= 0; i--)
+			found += fn_flush_list(fz, i);
 	}
 	return found;
 }
 
 
-static __inline__ int
+static inline int
 fn_hash_dump_bucket(struct sk_buff *skb, struct netlink_callback *cb,
 		     struct fib_table *tb,
 		     struct fn_zone *fz,
-		     struct fib_node *f)
+		     struct hlist_head *head)
 {
+	struct hlist_node *node;
+	struct fib_node *f;
 	int i, s_i;
 
 	s_i = cb->args[3];
-	for (i=0; f; i++, f=f->fn_next) {
-		if (i < s_i) continue;
-		if (f->fn_state&FN_S_ZOMBIE) continue;
-		if (fib_dump_info(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq,
-				  RTM_NEWROUTE,
-				  tb->tb_id, (f->fn_state&FN_S_ZOMBIE) ? 0 : f->fn_type, f->fn_scope,
-				  &f->fn_key, fz->fz_order, f->fn_tos,
-				  f->fn_info) < 0) {
-			cb->args[3] = i;
-			return -1;
+	i = 0;
+	hlist_for_each_entry(f, node, head, fn_hash) {
+		struct fib_alias *fa;
+
+		list_for_each_entry(fa, &f->fn_alias, fa_list) {
+			if (i < s_i)
+				continue;
+
+			if (fib_dump_info(skb, NETLINK_CB(cb->skb).pid,
+					  cb->nlh->nlmsg_seq,
+					  RTM_NEWROUTE,
+					  tb->tb_id,
+					  fa->fa_type,
+					  fa->fa_scope,
+					  &f->fn_key,
+					  fz->fz_order,
+					  fa->fa_tos,
+					  fa->fa_info) < 0) {
+				cb->args[3] = i;
+				return -1;
+			}
+
+			i++;
 		}
 	}
 	cb->args[3] = i;
 	return skb->len;
 }
 
-static __inline__ int
+static inline int
 fn_hash_dump_zone(struct sk_buff *skb, struct netlink_callback *cb,
 		   struct fib_table *tb,
 		   struct fn_zone *fz)
@@ -803,10 +758,12 @@ fn_hash_dump_zone(struct sk_buff *skb, struct netlink_callback *cb,
 	for (h=0; h < fz->fz_divisor; h++) {
 		if (h < s_h) continue;
 		if (h > s_h)
-			memset(&cb->args[3], 0, sizeof(cb->args) - 3*sizeof(cb->args[0]));
-		if (fz->fz_hash == NULL || fz->fz_hash[h] == NULL)
+			memset(&cb->args[3], 0,
+			       sizeof(cb->args) - 3*sizeof(cb->args[0]));
+		if (fz->fz_hash == NULL ||
+		    hlist_empty(&fz->fz_hash[h]))
 			continue;
-		if (fn_hash_dump_bucket(skb, cb, tb, fz, fz->fz_hash[h]) < 0) {
+		if (fn_hash_dump_bucket(skb, cb, tb, fz, &fz->fz_hash[h])<0) {
 			cb->args[2] = h;
 			return -1;
 		}
@@ -826,7 +783,8 @@ static int fn_hash_dump(struct fib_table *tb, struct sk_buff *skb, struct netlin
 	for (fz = table->fn_zone_list, m=0; fz; fz = fz->fz_next, m++) {
 		if (m < s_m) continue;
 		if (m > s_m)
-			memset(&cb->args[2], 0, sizeof(cb->args) - 2*sizeof(cb->args[0]));
+			memset(&cb->args[2], 0,
+			       sizeof(cb->args) - 2*sizeof(cb->args[0]));
 		if (fn_hash_dump_zone(skb, cb, tb, fz) < 0) {
 			cb->args[1] = m;
 			read_unlock(&fib_hash_lock);
@@ -838,7 +796,8 @@ static int fn_hash_dump(struct fib_table *tb, struct sk_buff *skb, struct netlin
 	return skb->len;
 }
 
-static void rtmsg_fib(int event, struct fib_node* f, int z, int tb_id,
+static void rtmsg_fib(int event, struct fib_node *f, struct fib_alias *fa,
+		      int z, int tb_id,
 		      struct nlmsghdr *n, struct netlink_skb_parms *req)
 {
 	struct sk_buff *skb;
@@ -850,8 +809,9 @@ static void rtmsg_fib(int event, struct fib_node* f, int z, int tb_id,
 		return;
 
 	if (fib_dump_info(skb, pid, n->nlmsg_seq, event, tb_id,
-			  f->fn_type, f->fn_scope, &f->fn_key, z, f->fn_tos,
-			  FIB_INFO(f)) < 0) {
+			  fa->fa_type, fa->fa_scope, &f->fn_key, z,
+			  fa->fa_tos,
+			  fa->fa_info) < 0) {
 		kfree_skb(skb);
 		return;
 	}
@@ -877,7 +837,14 @@ struct fib_table * __init fib_hash_init(int id)
 						 0, SLAB_HWCACHE_ALIGN,
 						 NULL, NULL);
 
-	tb = kmalloc(sizeof(struct fib_table) + sizeof(struct fn_hash), GFP_KERNEL);
+	if (fn_alias_kmem == NULL)
+		fn_alias_kmem = kmem_cache_create("ip_fib_alias",
+						  sizeof(struct fib_alias),
+						  0, SLAB_HWCACHE_ALIGN,
+						  NULL, NULL);
+
+	tb = kmalloc(sizeof(struct fib_table) + sizeof(struct fn_hash),
+		     GFP_KERNEL);
 	if (tb == NULL)
 		return NULL;
 
@@ -898,64 +865,105 @@ struct fib_table * __init fib_hash_init(int id)
 struct fib_iter_state {
 	struct fn_zone	*zone;
 	int		bucket;
-	struct fib_node **hash;
-	struct fib_node *node;
+	struct hlist_head *hash_head;
+	struct fib_node *fn;
+	struct fib_alias *fa;
 };
 
-static __inline__ struct fib_node *fib_get_first(struct seq_file *seq)
+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_iter_state *iter = seq->private;
+	struct fn_hash *table = (struct fn_hash *) ip_fib_main_table->tb_data;
 
-	iter->bucket = 0;
-	iter->hash   = NULL;
-	iter->node   = NULL;
+	iter->bucket    = 0;
+	iter->hash_head = NULL;
+	iter->fn        = NULL;
+	iter->fa        = NULL;
 
 	for (iter->zone = table->fn_zone_list; iter->zone;
 	     iter->zone = iter->zone->fz_next) {
 		int maxslot;
 
-		if (!iter->zone->fz_next)
+		if (!iter->zone->fz_nent)
 			continue;
 
-		iter->hash = iter->zone->fz_hash;
+		iter->hash_head = iter->zone->fz_hash;
 		maxslot = iter->zone->fz_divisor;
 
 		for (iter->bucket = 0; iter->bucket < maxslot;
-		     ++iter->bucket, ++iter->hash) {
-			iter->node = *iter->hash;
-
-			if (iter->node)
-				goto out;
+		     ++iter->bucket, ++iter->hash_head) {
+			struct hlist_node *node;
+			struct fib_node *fn;
+
+			hlist_for_each_entry(fn,node,iter->hash_head,fn_hash) {
+				struct fib_alias *fa;
+
+				list_for_each_entry(fa,&fn->fn_alias,fa_list) {
+					iter->fn = fn;
+					iter->fa = fa;
+					goto out;
+				}
+			}
 		}
 	}
 out:
-	return iter->node;
+	return iter->fa;
 }
 
-static __inline__ struct fib_node *fib_get_next(struct seq_file *seq)
+static struct fib_alias *fib_get_next(struct seq_file *seq)
 {
-	struct fib_iter_state* iter = seq->private;
+	struct fib_iter_state *iter = seq->private;
+	struct fib_node *fn;
+	struct fib_alias *fa;
+
+	/* Advance FA, if any. */
+	fn = iter->fn;
+	fa = iter->fa;
+	if (fa) {
+		BUG_ON(!fn);
+		list_for_each_entry_continue(fa, &fn->fn_alias, fa_list) {
+			iter->fa = fa;
+			goto out;
+		}
+	}
 
-	if (iter->node)
-		iter->node = iter->node->fn_next;
+	fa = iter->fa = NULL;
 
-	if (iter->node)
-		goto out;
+	/* Advance FN. */
+	if (fn) {
+		struct hlist_node *node = &fn->fn_hash;
+		hlist_for_each_entry_continue(fn, node, fn_hash) {
+			iter->fn = fn;
 
+			list_for_each_entry(fa, &fn->fn_alias, fa_list) {
+				iter->fa = fa;
+				goto out;
+			}
+		}
+	}
+
+	fn = iter->fn = NULL;
+
+	/* Advance hash chain. */
 	if (!iter->zone)
 		goto out;
 
 	for (;;) {
+		struct hlist_node *node;
 		int maxslot;
 
 		maxslot = iter->zone->fz_divisor;
 
 		while (++iter->bucket < maxslot) {
-			iter->node = *++iter->hash;
-
-			if (iter->node)
-				goto out;
+			iter->hash_head++;
+
+			hlist_for_each_entry(fn, node, iter->hash_head, fn_hash) {
+				list_for_each_entry(fa, &fn->fn_alias, fa_list) {
+					iter->fn = fn;
+					iter->fa = fa;
+					goto out;
+				}
+			}
 		}
 
 		iter->zone = iter->zone->fz_next;
@@ -963,14 +971,19 @@ static __inline__ struct fib_node *fib_get_next(struct seq_file *seq)
 		if (!iter->zone)
 			goto out;
 		
-		iter->hash = iter->zone->fz_hash;
 		iter->bucket = 0;
-		iter->node = *iter->hash;
-		if (iter->node)
-			break;
+		iter->hash_head = iter->zone->fz_hash;
+
+		hlist_for_each_entry(fn, node, iter->hash_head, fn_hash) {
+			list_for_each_entry(fa, &fn->fn_alias, fa_list) {
+				iter->fn = fn;
+				iter->fa = fa;
+				goto out;
+			}
+		}
 	}
 out:
-	return iter->node;
+	return fa;
 }
 
 static void *fib_seq_start(struct seq_file *seq, loff_t *pos)
@@ -994,7 +1007,7 @@ static void fib_seq_stop(struct seq_file *seq, void *v)
 	read_unlock(&fib_hash_lock);
 }
 
-static unsigned fib_flag_trans(int type, int dead, u32 mask, struct fib_info *fi)
+static unsigned fib_flag_trans(int type, u32 mask, struct fib_info *fi)
 {
 	static unsigned type2flags[RTN_MAX + 1] = {
 		[7] = RTF_REJECT, [8] = RTF_REJECT,
@@ -1005,8 +1018,7 @@ static unsigned fib_flag_trans(int type, int dead, u32 mask, struct fib_info *fi
 		flags |= RTF_GATEWAY;
 	if (mask == 0xFFFFFFFF)
 		flags |= RTF_HOST;
-	if (!dead)
-		flags |= RTF_UP;
+	flags |= RTF_UP;
 	return flags;
 }
 
@@ -1020,11 +1032,12 @@ extern int dev_in_nx_info(struct net_device *, struct nx_info *);
  */
 static int fib_seq_show(struct seq_file *seq, void *v)
 {
-	struct fib_iter_state* iter;
+	struct fib_iter_state *iter;
 	char bf[128];
 	u32 prefix, mask;
 	unsigned flags;
 	struct fib_node *f;
+	struct fib_alias *fa;
 	struct fib_info *fi;
 
 	if (v == SEQ_START_TOKEN) {
@@ -1034,14 +1047,15 @@ static int fib_seq_show(struct seq_file *seq, void *v)
 		goto out;
 	}
 
-	f	= v;
-	fi	= FIB_INFO(f);
 	iter	= seq->private;
-	prefix	= fz_prefix(f->fn_key, iter->zone);
+	f	= iter->fn;
+	fa	= iter->fa;
+	fi	= fa->fa_info;
+	prefix	= f->fn_key;
 	mask	= FZ_MASK(iter->zone);
-	flags	= fib_flag_trans(f->fn_type, f->fn_state & FN_S_ZOMBIE,
-				 mask, fi);
-	if (fi && dev_in_nx_info(fi->fib_dev, current->nx_info))
+	flags	= fib_flag_trans(fa->fa_type, mask, fi);
+	if (fi && (!vx_flags(VXF_HIDE_NETIF, 0) ||
+		dev_in_nx_info(fi->fib_dev, current->nx_info)))
 		snprintf(bf, sizeof(bf),
 			 "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
 			 fi->fib_dev ? fi->fib_dev->name : "*", prefix,
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 66e78bb4e..ee19a7e7a 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -176,7 +176,7 @@ int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 	table_id = rtm->rtm_table;
 	if (table_id == RT_TABLE_UNSPEC) {
 		struct fib_table *table;
-		if (rtm->rtm_type == RTN_UNICAST || rtm->rtm_type == RTN_NAT) {
+		if (rtm->rtm_type == RTN_UNICAST) {
 			if ((table = fib_empty_table()) == NULL)
 				return -ENOBUFS;
 			table_id = table->tb_id;
@@ -251,26 +251,6 @@ u32 fib_rules_map_destination(u32 daddr, struct fib_result *res)
 	return (daddr&~mask)|res->fi->fib_nh->nh_gw;
 }
 
-u32 fib_rules_policy(u32 saddr, struct fib_result *res, unsigned *flags)
-{
-	struct fib_rule *r = res->r;
-
-	if (r->r_action == RTN_NAT) {
-		int addrtype = inet_addr_type(r->r_srcmap);
-
-		if (addrtype == RTN_NAT) {
-			/* Packet is from  translated source; remember it */
-			saddr = (saddr&~r->r_srcmask)|r->r_srcmap;
-			*flags |= RTCF_SNAT;
-		} else if (addrtype == RTN_LOCAL || r->r_srcmap == 0) {
-			/* Packet is from masqueraded source; remember it */
-			saddr = r->r_srcmap;
-			*flags |= RTCF_MASQ;
-		}
-	}
-	return saddr;
-}
-
 #ifdef CONFIG_NET_CLS_ROUTE
 u32 fib_rules_tclass(struct fib_result *res)
 {
@@ -322,9 +302,7 @@ FRprintk("Lookup: %u.%u.%u.%u <- %u.%u.%u.%u ",
 	for (r = fib_rules; r; r=r->r_next) {
 		if (((saddr^r->r_src) & r->r_srcmask) ||
 		    ((daddr^r->r_dst) & r->r_dstmask) ||
-#ifdef CONFIG_IP_ROUTE_TOS
 		    (r->r_tos && r->r_tos != flp->fl4_tos) ||
-#endif
 #ifdef CONFIG_IP_ROUTE_FWMARK
 		    (r->r_fwmark && r->r_fwmark != flp->fl4_fwmark) ||
 #endif
@@ -334,7 +312,6 @@ FRprintk("Lookup: %u.%u.%u.%u <- %u.%u.%u.%u ",
 FRprintk("tb %d r %d ", r->r_table, r->r_action);
 		switch (r->r_action) {
 		case RTN_UNICAST:
-		case RTN_NAT:
 			policy = r;
 			break;
 		case RTN_UNREACHABLE:
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index c1b6060df..e2a772d3b 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -43,16 +43,19 @@
 #include <net/sock.h>
 #include <net/ip_fib.h>
 
+#include "fib_lookup.h"
+
 #define FSprintk(a...)
 
-static struct fib_info 	*fib_info_list;
 static rwlock_t fib_info_lock = RW_LOCK_UNLOCKED;
-int fib_info_cnt;
-
-#define for_fib_info() { struct fib_info *fi; \
-	for (fi = fib_info_list; fi; fi = fi->fib_next)
+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 endfor_fib_info() }
+#define DEVINDEX_HASHBITS 8
+#define DEVINDEX_HASHSIZE (1U << DEVINDEX_HASHBITS)
+static struct hlist_head fib_info_devhash[DEVINDEX_HASHSIZE];
 
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 
@@ -124,17 +127,10 @@ static struct
 		.error	= -EAGAIN,
 		.scope	= RT_SCOPE_UNIVERSE,
 	},	/* RTN_THROW */
-#ifdef CONFIG_IP_ROUTE_NAT
-	{
-		.error	= 0,
-		.scope	= RT_SCOPE_HOST,
-	},	/* RTN_NAT */
-#else
 	{
 		.error	= -EINVAL,
 		.scope	= RT_SCOPE_NOWHERE,
 	},	/* RTN_NAT */
-#endif
 	{
 		.error	= -EINVAL,
 		.scope	= RT_SCOPE_NOWHERE,
@@ -163,12 +159,12 @@ void fib_release_info(struct fib_info *fi)
 {
 	write_lock(&fib_info_lock);
 	if (fi && --fi->fib_treeref == 0) {
-		if (fi->fib_next)
-			fi->fib_next->fib_prev = fi->fib_prev;
-		if (fi->fib_prev)
-			fi->fib_prev->fib_next = fi->fib_next;
-		if (fi == fib_info_list)
-			fib_info_list = fi->fib_next;
+		hlist_del(&fi->fib_hash);
+		if (fi->fib_prefsrc)
+			hlist_del(&fi->fib_lhash);
+		change_nexthops(fi) {
+			hlist_del(&nh->nh_hash);
+		} endfor_nexthops(fi)
 		fi->fib_dead = 1;
 		fib_info_put(fi);
 	}
@@ -196,42 +192,79 @@ static __inline__ int nh_comp(const struct fib_info *fi, const struct fib_info *
 	return 0;
 }
 
-static __inline__ struct fib_info * fib_find_info(const struct fib_info *nfi)
+static inline unsigned int fib_info_hashfn(const struct fib_info *fi)
+{
+	unsigned int mask = (fib_hash_size - 1);
+	unsigned int val = fi->fib_nhs;
+
+	val ^= fi->fib_protocol;
+	val ^= fi->fib_prefsrc;
+	val ^= fi->fib_priority;
+
+	return (val ^ (val >> 7) ^ (val >> 12)) & mask;
+}
+
+static struct fib_info *fib_find_info(const struct fib_info *nfi)
 {
-	for_fib_info() {
+	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];
+
+	hlist_for_each_entry(fi, node, head, fib_hash) {
 		if (fi->fib_nhs != nfi->fib_nhs)
 			continue;
 		if (nfi->fib_protocol == fi->fib_protocol &&
 		    nfi->fib_prefsrc == fi->fib_prefsrc &&
 		    nfi->fib_priority == fi->fib_priority &&
-		    memcmp(nfi->fib_metrics, fi->fib_metrics, sizeof(fi->fib_metrics)) == 0 &&
+		    memcmp(nfi->fib_metrics, fi->fib_metrics,
+			   sizeof(fi->fib_metrics)) == 0 &&
 		    ((nfi->fib_flags^fi->fib_flags)&~RTNH_F_DEAD) == 0 &&
 		    (nfi->fib_nhs == 0 || nh_comp(fi, nfi) == 0))
 			return fi;
-	} endfor_fib_info();
+	}
+
 	return NULL;
 }
 
+static inline unsigned int fib_devindex_hashfn(unsigned int val)
+{
+	unsigned int mask = DEVINDEX_HASHSIZE - 1;
+
+	return (val ^
+		(val >> DEVINDEX_HASHBITS) ^
+		(val >> (DEVINDEX_HASHBITS * 2))) & mask;
+}
+
 /* Check, that the gateway is already configured.
    Used only by redirect accept routine.
  */
 
 int ip_fib_check_default(u32 gw, struct net_device *dev)
 {
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct fib_nh *nh;
+	unsigned int hash;
+
 	read_lock(&fib_info_lock);
-	for_fib_info() {
-		if (fi->fib_flags & RTNH_F_DEAD)
-			continue;
-		for_nexthops(fi) {
-			if (nh->nh_dev == dev && nh->nh_gw == gw &&
-			    nh->nh_scope == RT_SCOPE_LINK &&
-			    !(nh->nh_flags&RTNH_F_DEAD)) {
-				read_unlock(&fib_info_lock);
-				return 0;
-			}
-		} endfor_nexthops(fi);
-	} endfor_fib_info();
+
+	hash = fib_devindex_hashfn(dev->ifindex);
+	head = &fib_info_devhash[hash];
+	hlist_for_each_entry(nh, node, head, nh_hash) {
+		if (nh->nh_dev == dev &&
+		    nh->nh_gw == gw &&
+		    !(nh->nh_flags&RTNH_F_DEAD)) {
+			read_unlock(&fib_info_lock);
+			return 0;
+		}
+	}
+
 	read_unlock(&fib_info_lock);
+
 	return -1;
 }
 
@@ -458,6 +491,82 @@ out:
 	return 0;
 }
 
+static inline unsigned int fib_laddr_hashfn(u32 val)
+{
+	unsigned int mask = (fib_hash_size - 1);
+
+	return (val ^ (val >> 7) ^ (val >> 14)) & mask;
+}
+
+static struct hlist_head *fib_hash_alloc(int bytes)
+{
+	if (bytes <= PAGE_SIZE)
+		return kmalloc(bytes, GFP_KERNEL);
+	else
+		return (struct hlist_head *)
+			__get_free_pages(GFP_KERNEL, get_order(bytes));
+}
+
+static void fib_hash_free(struct hlist_head *hash, int bytes)
+{
+	if (!hash)
+		return;
+
+	if (bytes <= PAGE_SIZE)
+		kfree(hash);
+	else
+		free_pages((unsigned long) hash, get_order(bytes));
+}
+
+static void fib_hash_move(struct hlist_head *new_info_hash,
+			  struct hlist_head *new_laddrhash,
+			  unsigned int new_size)
+{
+	unsigned int old_size = fib_hash_size;
+	unsigned int i;
+
+	write_lock(&fib_info_lock);
+	fib_hash_size = new_size;
+
+	for (i = 0; i < old_size; i++) {
+		struct hlist_head *head = &fib_info_hash[i];
+		struct hlist_node *node, *n;
+		struct fib_info *fi;
+
+		hlist_for_each_entry_safe(fi, node, n, head, fib_hash) {
+			struct hlist_head *dest;
+			unsigned int new_hash;
+
+			hlist_del(&fi->fib_hash);
+
+			new_hash = fib_info_hashfn(fi);
+			dest = &new_info_hash[new_hash];
+			hlist_add_head(&fi->fib_hash, dest);
+		}
+	}
+	fib_info_hash = new_info_hash;
+
+	for (i = 0; i < old_size; i++) {
+		struct hlist_head *lhead = &fib_info_laddrhash[i];
+		struct hlist_node *node, *n;
+		struct fib_info *fi;
+
+		hlist_for_each_entry_safe(fi, node, n, lhead, fib_lhash) {
+			struct hlist_head *ldest;
+			unsigned int new_hash;
+
+			hlist_del(&fi->fib_lhash);
+
+			new_hash = fib_laddr_hashfn(fi->fib_prefsrc);
+			ldest = &new_laddrhash[new_hash];
+			hlist_add_head(&fi->fib_lhash, ldest);
+		}
+	}
+	fib_info_laddrhash = new_laddrhash;
+
+	write_unlock(&fib_info_lock);
+}
+
 struct fib_info *
 fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
 		const struct nlmsghdr *nlh, int *errp)
@@ -483,15 +592,45 @@ fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
 	}
 #endif
 
-	fi = kmalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL);
 	err = -ENOBUFS;
+	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;
+
+		if (!new_size)
+			new_size = 1;
+		bytes = new_size * sizeof(struct hlist_head *);
+		new_info_hash = fib_hash_alloc(bytes);
+		new_laddrhash = fib_hash_alloc(bytes);
+		if (!new_info_hash || !new_laddrhash) {
+			fib_hash_free(new_info_hash, bytes);
+			fib_hash_free(new_laddrhash, bytes);
+		} else {
+			memset(new_info_hash, 0, bytes);
+			memset(new_laddrhash, 0, bytes);
+
+			fib_hash_move(new_info_hash, new_laddrhash, new_size);
+		}
+
+		if (!fib_hash_size)
+			goto failure;
+	}
+
+	fi = kmalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL);
 	if (fi == NULL)
 		goto failure;
 	fib_info_cnt++;
 	memset(fi, 0, sizeof(*fi)+nhs*sizeof(struct fib_nh));
 
 	fi->fib_protocol = r->rtm_protocol;
+
 	fi->fib_nhs = nhs;
+	change_nexthops(fi) {
+		nh->nh_parent = fi;
+	} endfor_nexthops(fi)
+
 	fi->fib_flags = r->rtm_flags;
 	if (rta->rta_priority)
 		fi->fib_priority = *rta->rta_priority;
@@ -543,15 +682,6 @@ fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
 #endif
 	}
 
-#ifdef CONFIG_IP_ROUTE_NAT
-	if (r->rtm_type == RTN_NAT) {
-		if (rta->rta_gw == NULL || nhs != 1 || rta->rta_oif)
-			goto err_inval;
-		memcpy(&fi->fib_nh->nh_gw, rta->rta_gw, 4);
-		goto link_it;
-	}
-#endif
-
 	if (fib_props[r->rtm_type].error) {
 		if (rta->rta_gw || rta->rta_oif || rta->rta_mp)
 			goto err_inval;
@@ -597,11 +727,24 @@ link_it:
 	fi->fib_treeref++;
 	atomic_inc(&fi->fib_clntref);
 	write_lock(&fib_info_lock);
-	fi->fib_next = fib_info_list;
-	fi->fib_prev = NULL;
-	if (fib_info_list)
-		fib_info_list->fib_prev = fi;
-	fib_info_list = fi;
+	hlist_add_head(&fi->fib_hash,
+		       &fib_info_hash[fib_info_hashfn(fi)]);
+	if (fi->fib_prefsrc) {
+		struct hlist_head *head;
+
+		head = &fib_info_laddrhash[fib_laddr_hashfn(fi->fib_prefsrc)];
+		hlist_add_head(&fi->fib_lhash, head);
+	}
+	change_nexthops(fi) {
+		struct hlist_head *head;
+		unsigned int hash;
+
+		if (!nh->nh_dev)
+			continue;
+		hash = fib_devindex_hashfn(nh->nh_dev->ifindex);
+		head = &fib_info_devhash[hash];
+		hlist_add_head(&nh->nh_hash, head);
+	} endfor_nexthops(fi)
 	write_unlock(&fib_info_lock);
 	return fi;
 
@@ -617,57 +760,73 @@ failure:
 	return NULL;
 }
 
-int 
-fib_semantic_match(int type, struct fib_info *fi, const struct flowi *flp, struct fib_result *res)
+int fib_semantic_match(struct list_head *head, const struct flowi *flp,
+		       struct fib_result *res, int prefixlen)
 {
-	int err = fib_props[type].error;
+	struct fib_alias *fa;
+	int nh_sel = 0;
 
-	if (err == 0) {
-		if (fi->fib_flags&RTNH_F_DEAD)
-			return 1;
+	list_for_each_entry(fa, head, fa_list) {
+		int err;
 
-		res->fi = fi;
+		if (fa->fa_tos &&
+		    fa->fa_tos != flp->fl4_tos)
+			continue;
 
-		switch (type) {
-#ifdef CONFIG_IP_ROUTE_NAT
-		case RTN_NAT:
-			FIB_RES_RESET(*res);
-			atomic_inc(&fi->fib_clntref);
-			return 0;
-#endif
-		case RTN_UNICAST:
-		case RTN_LOCAL:
-		case RTN_BROADCAST:
-		case RTN_ANYCAST:
-		case RTN_MULTICAST:
-			for_nexthops(fi) {
-				if (nh->nh_flags&RTNH_F_DEAD)
-					continue;
-				if (!flp->oif || flp->oif == nh->nh_oif)
-					break;
-			}
+		if (fa->fa_scope < flp->fl4_scope)
+			continue;
+
+		fa->fa_state |= FA_S_ACCESSED;
+
+		err = fib_props[fa->fa_type].error;
+		if (err == 0) {
+			struct fib_info *fi = fa->fa_info;
+
+			if (fi->fib_flags & RTNH_F_DEAD)
+				continue;
+
+			switch (fa->fa_type) {
+			case RTN_UNICAST:
+			case RTN_LOCAL:
+			case RTN_BROADCAST:
+			case RTN_ANYCAST:
+			case RTN_MULTICAST:
+				for_nexthops(fi) {
+					if (nh->nh_flags&RTNH_F_DEAD)
+						continue;
+					if (!flp->oif || flp->oif == nh->nh_oif)
+						break;
+				}
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
-			if (nhsel < fi->fib_nhs) {
-				res->nh_sel = nhsel;
-				atomic_inc(&fi->fib_clntref);
-				return 0;
-			}
+				if (nhsel < fi->fib_nhs) {
+					nh_sel = nhsel;
+					goto out_fill_res;
+				}
 #else
-			if (nhsel < 1) {
-				atomic_inc(&fi->fib_clntref);
-				return 0;
-			}
+				if (nhsel < 1) {
+					goto out_fill_res;
+				}
 #endif
-			endfor_nexthops(fi);
-			res->fi = NULL;
-			return 1;
-		default:
-			res->fi = NULL;
-			printk(KERN_DEBUG "impossible 102\n");
-			return -EINVAL;
+				endfor_nexthops(fi);
+				continue;
+
+			default:
+				printk(KERN_DEBUG "impossible 102\n");
+				return -EINVAL;
+			};
 		}
+		return err;
 	}
-	return err;
+	return 1;
+
+out_fill_res:
+	res->prefixlen = prefixlen;
+	res->nh_sel = nh_sel;
+	res->type = fa->fa_type;
+	res->scope = fa->fa_scope;
+	res->fi = fa->fa_info;
+	atomic_inc(&res->fi->fib_clntref);
+	return 0;
 }
 
 /* Find appropriate source address to this destination */
@@ -906,13 +1065,36 @@ int fib_sync_down(u32 local, struct net_device *dev, int force)
 	if (force)
 		scope = -1;
 
-	for_fib_info() {
-		if (local && fi->fib_prefsrc == local) {
-			fi->fib_flags |= RTNH_F_DEAD;
-			ret++;
-		} else if (dev && fi->fib_nhs) {
-			int dead = 0;
+	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;
+
+		hlist_for_each_entry(fi, node, head, fib_lhash) {
+			if (fi->fib_prefsrc == local) {
+				fi->fib_flags |= RTNH_F_DEAD;
+				ret++;
+			}
+		}
+	}
+
+	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_node *node;
+		struct fib_nh *nh;
 
+		hlist_for_each_entry(nh, node, head, nh_hash) {
+			struct fib_info *fi = nh->nh_parent;
+			int dead;
+
+			BUG_ON(!fi->fib_nhs);
+			if (nh->nh_dev != dev || fi == prev_fi)
+				continue;
+			prev_fi = fi;
+			dead = 0;
 			change_nexthops(fi) {
 				if (nh->nh_flags&RTNH_F_DEAD)
 					dead++;
@@ -939,7 +1121,8 @@ int fib_sync_down(u32 local, struct net_device *dev, int force)
 				ret++;
 			}
 		}
-	} endfor_fib_info();
+	}
+
 	return ret;
 }
 
@@ -952,14 +1135,31 @@ int fib_sync_down(u32 local, struct net_device *dev, int force)
 
 int fib_sync_up(struct net_device *dev)
 {
-	int ret = 0;
+	struct fib_info *prev_fi;
+	unsigned int hash;
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct fib_nh *nh;
+	int ret;
 
 	if (!(dev->flags&IFF_UP))
 		return 0;
 
-	for_fib_info() {
-		int alive = 0;
+	prev_fi = NULL;
+	hash = fib_devindex_hashfn(dev->ifindex);
+	head = &fib_info_devhash[hash];
+	ret = 0;
+
+	hlist_for_each_entry(nh, node, head, nh_hash) {
+		struct fib_info *fi = nh->nh_parent;
+		int alive;
 
+		BUG_ON(!fi->fib_nhs);
+		if (nh->nh_dev != dev || fi == prev_fi)
+			continue;
+
+		prev_fi = fi;
+		alive = 0;
 		change_nexthops(fi) {
 			if (!(nh->nh_flags&RTNH_F_DEAD)) {
 				alive++;
@@ -980,7 +1180,8 @@ int fib_sync_up(struct net_device *dev)
 			fi->fib_flags &= ~RTNH_F_DEAD;
 			ret++;
 		}
-	} endfor_fib_info();
+	}
+
 	return ret;
 }
 
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 69261324d..062589289 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -478,20 +478,25 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info)
 		 *	ICMP error
 		 */
 		if (iph->protocol == IPPROTO_ICMP) {
-			u8 inner_type;
-
-			if (skb_copy_bits(skb_in,
-					  skb_in->nh.raw + (iph->ihl << 2) +
-					  offsetof(struct icmphdr, type) -
-					  skb_in->data, &inner_type, 1))
+			u8 _inner_type, *itp;
+
+			itp = skb_header_pointer(skb_in,
+						 skb_in->nh.raw +
+						 (iph->ihl << 2) +
+						 offsetof(struct icmphdr,
+							  type) -
+						 skb_in->data,
+						 sizeof(_inner_type),
+						 &_inner_type);
+			if (itp == NULL)
 				goto out;
 
 			/*
 			 *	Assume any unknown ICMP type is an error. This
 			 *	isn't specified by the RFC, but think about it..
 			 */
-			if (inner_type > NR_ICMP_TYPES ||
-			    icmp_pointers[inner_type].error)
+			if (*itp > NR_ICMP_TYPES ||
+			    icmp_pointers[*itp].error)
 				goto out;
 		}
 	}
@@ -503,16 +508,6 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info)
 	 *	Construct source address and options.
 	 */
 
-#ifdef CONFIG_IP_ROUTE_NAT
-	/*
-	 *	Restore original addresses if packet has been translated.
-	 */
-	if (rt->rt_flags & RTCF_NAT && IPCB(skb_in)->flags & IPSKB_TRANSLATED) {
-		iph->daddr = rt->fl.fl4_dst;
-		iph->saddr = rt->fl.fl4_src;
-	}
-#endif
-
 	saddr = iph->daddr;
 	if (!(rt->rt_flags & RTCF_LOCAL))
 		saddr = 0;
@@ -705,8 +700,7 @@ static void icmp_unreach(struct sk_buff *skb)
 	read_unlock(&raw_v4_lock);
 
 	rcu_read_lock();
-	ipprot = inet_protos[hash];
-	smp_read_barrier_depends();
+	ipprot = rcu_dereference(inet_protos[hash]);
 	if (ipprot && ipprot->err_handler)
 		ipprot->err_handler(skb, info);
 	rcu_read_unlock();
@@ -880,7 +874,6 @@ static void icmp_address_reply(struct sk_buff *skb)
 	struct net_device *dev = skb->dev;
 	struct in_device *in_dev;
 	struct in_ifaddr *ifa;
-	u32 mask;
 
 	if (skb->len < 4 || !(rt->rt_flags&RTCF_DIRECTSRC))
 		goto out;
@@ -888,24 +881,27 @@ static void icmp_address_reply(struct sk_buff *skb)
 	in_dev = in_dev_get(dev);
 	if (!in_dev)
 		goto out;
-	read_lock(&in_dev->lock);
+	rcu_read_lock();
 	if (in_dev->ifa_list &&
 	    IN_DEV_LOG_MARTIANS(in_dev) &&
 	    IN_DEV_FORWARD(in_dev)) {
-		if (skb_copy_bits(skb, 0, &mask, 4))
+		u32 _mask, *mp;
+
+		mp = skb_header_pointer(skb, 0, sizeof(_mask), &_mask);
+		if (mp == NULL)
 			BUG();
 		for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
-			if (mask == ifa->ifa_mask &&
+			if (*mp == ifa->ifa_mask &&
 			    inet_ifa_match(rt->rt_src, ifa))
 				break;
 		}
 		if (!ifa && net_ratelimit()) {
 			printk(KERN_INFO "Wrong address mask %u.%u.%u.%u from "
 					 "%s/%u.%u.%u.%u\n",
-			       NIPQUAD(mask), dev->name, NIPQUAD(rt->rt_src));
+			       NIPQUAD(*mp), dev->name, NIPQUAD(rt->rt_src));
 		}
 	}
-	read_unlock(&in_dev->lock);
+	rcu_read_unlock();
 	in_dev_put(in_dev);
 out:;
 }
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 01db76123..d1815d3ef 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -487,7 +487,7 @@ static int igmpv3_send_report(struct in_device *in_dev, struct ip_mc_list *pmc)
 	int type;
 
 	if (!pmc) {
-		read_lock(&in_dev->lock);
+		read_lock(&in_dev->mc_list_lock);
 		for (pmc=in_dev->mc_list; pmc; pmc=pmc->next) {
 			if (pmc->multiaddr == IGMP_ALL_HOSTS)
 				continue;
@@ -499,7 +499,7 @@ static int igmpv3_send_report(struct in_device *in_dev, struct ip_mc_list *pmc)
 			skb = add_grec(skb, pmc, type, 0, 0);
 			spin_unlock_bh(&pmc->lock);
 		}
-		read_unlock(&in_dev->lock);
+		read_unlock(&in_dev->mc_list_lock);
 	} else {
 		spin_lock_bh(&pmc->lock);
 		if (pmc->sfcount[MCAST_EXCLUDE])
@@ -541,8 +541,8 @@ static void igmpv3_send_cr(struct in_device *in_dev)
 	struct sk_buff *skb = NULL;
 	int type, dtype;
 
-	read_lock(&in_dev->lock);
-	write_lock_bh(&in_dev->mc_lock);
+	read_lock(&in_dev->mc_list_lock);
+	spin_lock_bh(&in_dev->mc_tomb_lock);
 
 	/* deleted MCA's */
 	pmc_prev = NULL;
@@ -575,7 +575,7 @@ static void igmpv3_send_cr(struct in_device *in_dev)
 		} else
 			pmc_prev = pmc;
 	}
-	write_unlock_bh(&in_dev->mc_lock);
+	spin_unlock_bh(&in_dev->mc_tomb_lock);
 
 	/* change recs */
 	for (pmc=in_dev->mc_list; pmc; pmc=pmc->next) {
@@ -601,7 +601,8 @@ static void igmpv3_send_cr(struct in_device *in_dev)
 		}
 		spin_unlock_bh(&pmc->lock);
 	}
-	read_unlock(&in_dev->lock);
+	read_unlock(&in_dev->mc_list_lock);
+
 	if (!skb)
 		return;
 	(void) igmpv3_sendpack(skb);
@@ -759,14 +760,14 @@ static void igmp_heard_report(struct in_device *in_dev, u32 group)
 	if (group == IGMP_ALL_HOSTS)
 		return;
 
-	read_lock(&in_dev->lock);
+	read_lock(&in_dev->mc_list_lock);
 	for (im=in_dev->mc_list; im!=NULL; im=im->next) {
 		if (im->multiaddr == group) {
 			igmp_stop_timer(im);
 			break;
 		}
 	}
-	read_unlock(&in_dev->lock);
+	read_unlock(&in_dev->mc_list_lock);
 }
 
 static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
@@ -840,7 +841,7 @@ static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
 	 * - Use the igmp->igmp_code field as the maximum
 	 *   delay possible
 	 */
-	read_lock(&in_dev->lock);
+	read_lock(&in_dev->mc_list_lock);
 	for (im=in_dev->mc_list; im!=NULL; im=im->next) {
 		if (group && group != im->multiaddr)
 			continue;
@@ -856,7 +857,7 @@ static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
 		spin_unlock_bh(&im->lock);
 		igmp_mod_timer(im, max_delay);
 	}
-	read_unlock(&in_dev->lock);
+	read_unlock(&in_dev->mc_list_lock);
 }
 
 int igmp_rcv(struct sk_buff *skb)
@@ -982,10 +983,10 @@ static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im)
 	}
 	spin_unlock_bh(&im->lock);
 
-	write_lock_bh(&in_dev->mc_lock);
+	spin_lock_bh(&in_dev->mc_tomb_lock);
 	pmc->next = in_dev->mc_tomb;
 	in_dev->mc_tomb = pmc;
-	write_unlock_bh(&in_dev->mc_lock);
+	spin_unlock_bh(&in_dev->mc_tomb_lock);
 }
 
 static void igmpv3_del_delrec(struct in_device *in_dev, __u32 multiaddr)
@@ -993,7 +994,7 @@ static void igmpv3_del_delrec(struct in_device *in_dev, __u32 multiaddr)
 	struct ip_mc_list *pmc, *pmc_prev;
 	struct ip_sf_list *psf, *psf_next;
 
-	write_lock_bh(&in_dev->mc_lock);
+	spin_lock_bh(&in_dev->mc_tomb_lock);
 	pmc_prev = NULL;
 	for (pmc=in_dev->mc_tomb; pmc; pmc=pmc->next) {
 		if (pmc->multiaddr == multiaddr)
@@ -1006,7 +1007,7 @@ static void igmpv3_del_delrec(struct in_device *in_dev, __u32 multiaddr)
 		else
 			in_dev->mc_tomb = pmc->next;
 	}
-	write_unlock_bh(&in_dev->mc_lock);
+	spin_unlock_bh(&in_dev->mc_tomb_lock);
 	if (pmc) {
 		for (psf=pmc->tomb; psf; psf=psf_next) {
 			psf_next = psf->sf_next;
@@ -1021,10 +1022,10 @@ static void igmpv3_clear_delrec(struct in_device *in_dev)
 {
 	struct ip_mc_list *pmc, *nextpmc;
 
-	write_lock_bh(&in_dev->mc_lock);
+	spin_lock_bh(&in_dev->mc_tomb_lock);
 	pmc = in_dev->mc_tomb;
 	in_dev->mc_tomb = NULL;
-	write_unlock_bh(&in_dev->mc_lock);
+	spin_unlock_bh(&in_dev->mc_tomb_lock);
 
 	for (; pmc; pmc = nextpmc) {
 		nextpmc = pmc->next;
@@ -1033,7 +1034,7 @@ static void igmpv3_clear_delrec(struct in_device *in_dev)
 		kfree(pmc);
 	}
 	/* clear dead sources, too */
-	read_lock(&in_dev->lock);
+	read_lock(&in_dev->mc_list_lock);
 	for (pmc=in_dev->mc_list; pmc; pmc=pmc->next) {
 		struct ip_sf_list *psf, *psf_next;
 
@@ -1046,7 +1047,7 @@ static void igmpv3_clear_delrec(struct in_device *in_dev)
 			kfree(psf);
 		}
 	}
-	read_unlock(&in_dev->lock);
+	read_unlock(&in_dev->mc_list_lock);
 }
 #endif
 
@@ -1167,10 +1168,10 @@ void ip_mc_inc_group(struct in_device *in_dev, u32 addr)
 	im->gsquery = 0;
 #endif
 	im->loaded = 0;
-	write_lock_bh(&in_dev->lock);
+	write_lock_bh(&in_dev->mc_list_lock);
 	im->next=in_dev->mc_list;
 	in_dev->mc_list=im;
-	write_unlock_bh(&in_dev->lock);
+	write_unlock_bh(&in_dev->mc_list_lock);
 #ifdef CONFIG_IP_MULTICAST
 	igmpv3_del_delrec(in_dev, im->multiaddr);
 #endif
@@ -1194,9 +1195,9 @@ void ip_mc_dec_group(struct in_device *in_dev, u32 addr)
 	for (ip=&in_dev->mc_list; (i=*ip)!=NULL; ip=&i->next) {
 		if (i->multiaddr==addr) {
 			if (--i->users == 0) {
-				write_lock_bh(&in_dev->lock);
+				write_lock_bh(&in_dev->mc_list_lock);
 				*ip = i->next;
-				write_unlock_bh(&in_dev->lock);
+				write_unlock_bh(&in_dev->mc_list_lock);
 				igmp_group_dropped(i);
 
 				if (!in_dev->dead)
@@ -1251,7 +1252,8 @@ void ip_mc_init_dev(struct in_device *in_dev)
 	in_dev->mr_qrv = IGMP_Unsolicited_Report_Count;
 #endif
 
-	in_dev->mc_lock = RW_LOCK_UNLOCKED;
+	in_dev->mc_list_lock = RW_LOCK_UNLOCKED;
+	in_dev->mc_tomb_lock = SPIN_LOCK_UNLOCKED;
 }
 
 /* Device going up */
@@ -1281,17 +1283,17 @@ void ip_mc_destroy_dev(struct in_device *in_dev)
 	/* Deactivate timers */
 	ip_mc_down(in_dev);
 
-	write_lock_bh(&in_dev->lock);
+	write_lock_bh(&in_dev->mc_list_lock);
 	while ((i = in_dev->mc_list) != NULL) {
 		in_dev->mc_list = i->next;
-		write_unlock_bh(&in_dev->lock);
+		write_unlock_bh(&in_dev->mc_list_lock);
 
 		igmp_group_dropped(i);
 		ip_ma_put(i);
 
-		write_lock_bh(&in_dev->lock);
+		write_lock_bh(&in_dev->mc_list_lock);
 	}
-	write_unlock_bh(&in_dev->lock);
+	write_unlock_bh(&in_dev->mc_list_lock);
 }
 
 static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr)
@@ -1391,18 +1393,18 @@ int ip_mc_del_src(struct in_device *in_dev, __u32 *pmca, int sfmode,
 
 	if (!in_dev)
 		return -ENODEV;
-	read_lock(&in_dev->lock);
+	read_lock(&in_dev->mc_list_lock);
 	for (pmc=in_dev->mc_list; pmc; pmc=pmc->next) {
 		if (*pmca == pmc->multiaddr)
 			break;
 	}
 	if (!pmc) {
 		/* MCA not found?? bug */
-		read_unlock(&in_dev->lock);
+		read_unlock(&in_dev->mc_list_lock);
 		return -ESRCH;
 	}
 	spin_lock_bh(&pmc->lock);
-	read_unlock(&in_dev->lock);
+	read_unlock(&in_dev->mc_list_lock);
 #ifdef CONFIG_IP_MULTICAST
 	sf_markstate(pmc);
 #endif
@@ -1527,18 +1529,18 @@ int ip_mc_add_src(struct in_device *in_dev, __u32 *pmca, int sfmode,
 
 	if (!in_dev)
 		return -ENODEV;
-	read_lock(&in_dev->lock);
+	read_lock(&in_dev->mc_list_lock);
 	for (pmc=in_dev->mc_list; pmc; pmc=pmc->next) {
 		if (*pmca == pmc->multiaddr)
 			break;
 	}
 	if (!pmc) {
 		/* MCA not found?? bug */
-		read_unlock(&in_dev->lock);
+		read_unlock(&in_dev->mc_list_lock);
 		return -ESRCH;
 	}
 	spin_lock_bh(&pmc->lock);
-	read_unlock(&in_dev->lock);
+	read_unlock(&in_dev->mc_list_lock);
 
 #ifdef CONFIG_IP_MULTICAST
 	sf_markstate(pmc);
@@ -2095,7 +2097,7 @@ int ip_check_mc(struct in_device *in_dev, u32 mc_addr, u32 src_addr, u16 proto)
 	struct ip_sf_list *psf;
 	int rv = 0;
 
-	read_lock(&in_dev->lock);
+	read_lock(&in_dev->mc_list_lock);
 	for (im=in_dev->mc_list; im; im=im->next) {
 		if (im->multiaddr == mc_addr)
 			break;
@@ -2117,7 +2119,7 @@ int ip_check_mc(struct in_device *in_dev, u32 mc_addr, u32 src_addr, u16 proto)
 		} else
 			rv = 1; /* unspecified source; tentatively allow */
 	}
-	read_unlock(&in_dev->lock);
+	read_unlock(&in_dev->mc_list_lock);
 	return rv;
 }
 
@@ -2141,13 +2143,13 @@ static inline struct ip_mc_list *igmp_mc_get_first(struct seq_file *seq)
 		in_dev = in_dev_get(state->dev);
 		if (!in_dev)
 			continue;
-		read_lock(&in_dev->lock);
+		read_lock(&in_dev->mc_list_lock);
 		im = in_dev->mc_list;
 		if (im) {
 			state->in_dev = in_dev;
 			break;
 		}
-		read_unlock(&in_dev->lock);
+		read_unlock(&in_dev->mc_list_lock);
 		in_dev_put(in_dev);
 	}
 	return im;
@@ -2159,7 +2161,7 @@ static struct ip_mc_list *igmp_mc_get_next(struct seq_file *seq, struct ip_mc_li
 	im = im->next;
 	while (!im) {
 		if (likely(state->in_dev != NULL)) {
-			read_unlock(&state->in_dev->lock);
+			read_unlock(&state->in_dev->mc_list_lock);
 			in_dev_put(state->in_dev);
 		}
 		state->dev = state->dev->next;
@@ -2170,7 +2172,7 @@ static struct ip_mc_list *igmp_mc_get_next(struct seq_file *seq, struct ip_mc_li
 		state->in_dev = in_dev_get(state->dev);
 		if (!state->in_dev)
 			continue;
-		read_lock(&state->in_dev->lock);
+		read_lock(&state->in_dev->mc_list_lock);
 		im = state->in_dev->mc_list;
 	}
 	return im;
@@ -2206,7 +2208,7 @@ static void igmp_mc_seq_stop(struct seq_file *seq, void *v)
 {
 	struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);
 	if (likely(state->in_dev != NULL)) {
-		read_unlock(&state->in_dev->lock);
+		read_unlock(&state->in_dev->mc_list_lock);
 		in_dev_put(state->in_dev);
 		state->in_dev = NULL;
 	}
@@ -2304,7 +2306,7 @@ static inline struct ip_sf_list *igmp_mcf_get_first(struct seq_file *seq)
 		idev = in_dev_get(state->dev);
 		if (unlikely(idev == NULL))
 			continue;
-		read_lock_bh(&idev->lock);
+		read_lock(&idev->mc_list_lock);
 		im = idev->mc_list;
 		if (likely(im != NULL)) {
 			spin_lock_bh(&im->lock);
@@ -2316,7 +2318,7 @@ static inline struct ip_sf_list *igmp_mcf_get_first(struct seq_file *seq)
 			}
 			spin_unlock_bh(&im->lock);
 		}
-		read_unlock_bh(&idev->lock);
+		read_unlock(&idev->mc_list_lock);
 		in_dev_put(idev);
 	}
 	return psf;
@@ -2332,7 +2334,7 @@ static struct ip_sf_list *igmp_mcf_get_next(struct seq_file *seq, struct ip_sf_l
 		state->im = state->im->next;
 		while (!state->im) {
 			if (likely(state->idev != NULL)) {
-				read_unlock_bh(&state->idev->lock);
+				read_unlock(&state->idev->mc_list_lock);
 				in_dev_put(state->idev);
 			}
 			state->dev = state->dev->next;
@@ -2343,7 +2345,7 @@ static struct ip_sf_list *igmp_mcf_get_next(struct seq_file *seq, struct ip_sf_l
 			state->idev = in_dev_get(state->dev);
 			if (!state->idev)
 				continue;
-			read_lock_bh(&state->idev->lock);
+			read_lock(&state->idev->mc_list_lock);
 			state->im = state->idev->mc_list;
 		}
 		if (!state->im)
@@ -2389,7 +2391,7 @@ static void igmp_mcf_seq_stop(struct seq_file *seq, void *v)
 		state->im = NULL;
 	}
 	if (likely(state->idev != NULL)) {
-		read_unlock_bh(&state->idev->lock);
+		read_unlock(&state->idev->mc_list_lock);
 		in_dev_put(state->idev);
 		state->idev = NULL;
 	}
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 6fd69feff..df083ded1 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -169,14 +169,18 @@ static void ipfrag_secret_rebuild(unsigned long dummy)
 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)
+static __inline__ void frag_kfree_skb(struct sk_buff *skb, int *work)
 {
+	if (work)
+		*work -= skb->truesize;
 	atomic_sub(skb->truesize, &ip_frag_mem);
 	kfree_skb(skb);
 }
 
-static __inline__ void frag_free_queue(struct ipq *qp)
+static __inline__ void frag_free_queue(struct ipq *qp, int *work)
 {
+	if (work)
+		*work -= sizeof(struct ipq);
 	atomic_sub(sizeof(struct ipq), &ip_frag_mem);
 	kfree(qp);
 }
@@ -195,7 +199,7 @@ static __inline__ struct ipq *frag_alloc_queue(void)
 /* Destruction primitives. */
 
 /* Complete destruction of ipq. */
-static void ip_frag_destroy(struct ipq *qp)
+static void ip_frag_destroy(struct ipq *qp, int *work)
 {
 	struct sk_buff *fp;
 
@@ -207,18 +211,18 @@ static void ip_frag_destroy(struct ipq *qp)
 	while (fp) {
 		struct sk_buff *xp = fp->next;
 
-		frag_kfree_skb(fp);
+		frag_kfree_skb(fp, work);
 		fp = xp;
 	}
 
 	/* Finally, release the queue descriptor itself. */
-	frag_free_queue(qp);
+	frag_free_queue(qp, work);
 }
 
-static __inline__ void ipq_put(struct ipq *ipq)
+static __inline__ void ipq_put(struct ipq *ipq, int *work)
 {
 	if (atomic_dec_and_test(&ipq->refcnt))
-		ip_frag_destroy(ipq);
+		ip_frag_destroy(ipq, work);
 }
 
 /* Kill ipq entry. It is not destroyed immediately,
@@ -237,16 +241,19 @@ static void ipq_kill(struct ipq *ipq)
 }
 
 /* Memory limiting on fragments.  Evictor trashes the oldest 
- * fragment queue until we are back under the low threshold.
+ * fragment queue until we are back under the threshold.
  */
-static void ip_evictor(void)
+static void __ip_evictor(int threshold)
 {
 	struct ipq *qp;
 	struct list_head *tmp;
+	int work;
 
-	for(;;) {
-		if (atomic_read(&ip_frag_mem) <= sysctl_ipfrag_low_thresh)
-			return;
+	work = atomic_read(&ip_frag_mem) - threshold;
+	if (work <= 0)
+		return;
+
+	while (work > 0) {
 		read_lock(&ipfrag_lock);
 		if (list_empty(&ipq_lru_list)) {
 			read_unlock(&ipfrag_lock);
@@ -262,11 +269,16 @@ static void ip_evictor(void)
 			ipq_kill(qp);
 		spin_unlock(&qp->lock);
 
-		ipq_put(qp);
+		ipq_put(qp, &work);
 		IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
 	}
 }
 
+static inline void ip_evictor(void)
+{
+	__ip_evictor(sysctl_ipfrag_low_thresh);
+}
+
 /*
  * Oops, a fragment queue timed out.  Kill it and send an ICMP reply.
  */
@@ -294,7 +306,7 @@ static void ip_expire(unsigned long arg)
 	}
 out:
 	spin_unlock(&qp->lock);
-	ipq_put(qp);
+	ipq_put(qp, NULL);
 }
 
 /* Creation primitives. */
@@ -317,7 +329,7 @@ static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in)
 			atomic_inc(&qp->refcnt);
 			write_unlock(&ipfrag_lock);
 			qp_in->last_in |= COMPLETE;
-			ipq_put(qp_in);
+			ipq_put(qp_in, NULL);
 			return qp;
 		}
 	}
@@ -506,7 +518,7 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
 				qp->fragments = next;
 
 			qp->meat -= free_it->len;
-			frag_kfree_skb(free_it);
+			frag_kfree_skb(free_it, NULL);
 		}
 	}
 
@@ -657,7 +669,7 @@ struct sk_buff *ip_defrag(struct sk_buff *skb)
 			ret = ip_frag_reasm(qp, dev);
 
 		spin_unlock(&qp->lock);
-		ipq_put(qp);
+		ipq_put(qp, NULL);
 		return ret;
 	}
 
@@ -677,4 +689,10 @@ void ipfrag_init(void)
 	add_timer(&ipfrag_secret_timer);
 }
 
+void ipfrag_flush(void)
+{
+	__ip_evictor(0);
+}
+
 EXPORT_SYMBOL(ip_defrag);
+EXPORT_SYMBOL(ipfrag_flush);
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 2a3a8fb7e..2c768ecc0 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -36,6 +36,7 @@
 #include <net/ipip.h>
 #include <net/arp.h>
 #include <net/checksum.h>
+#include <net/dsfield.h>
 #include <net/inet_ecn.h>
 #include <net/xfrm.h>
 
@@ -533,11 +534,9 @@ static inline void ipgre_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
 {
 	if (INET_ECN_is_ce(iph->tos)) {
 		if (skb->protocol == htons(ETH_P_IP)) {
-			if (INET_ECN_is_not_ce(skb->nh.iph->tos))
-				IP_ECN_set_ce(skb->nh.iph);
+			IP_ECN_set_ce(skb->nh.iph);
 		} else if (skb->protocol == htons(ETH_P_IPV6)) {
-			if (INET_ECN_is_not_ce(ip6_get_dsfield(skb->nh.ipv6h)))
-				IP6_ECN_set_ce(skb->nh.ipv6h);
+			IP6_ECN_set_ce(skb->nh.ipv6h);
 		}
 	}
 }
@@ -549,7 +548,7 @@ ipgre_ecn_encapsulate(u8 tos, struct iphdr *old_iph, struct sk_buff *skb)
 	if (skb->protocol == htons(ETH_P_IP))
 		inner = old_iph->tos;
 	else if (skb->protocol == htons(ETH_P_IPV6))
-		inner = ip6_get_dsfield((struct ipv6hdr*)old_iph);
+		inner = ipv6_get_dsfield((struct ipv6hdr *)old_iph);
 	return INET_ECN_encapsulate(tos, inner);
 }
 
@@ -605,13 +604,24 @@ int ipgre_rcv(struct sk_buff *skb)
 	if ((tunnel = ipgre_tunnel_lookup(iph->saddr, iph->daddr, key)) != NULL) {
 		secpath_reset(skb);
 
+		skb->protocol = *(u16*)(h + 2);
+		/* WCCP version 1 and 2 protocol decoding.
+		 * - Change protocol to IP
+		 * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
+		 */
+		if (flags == 0 &&
+		    skb->protocol == __constant_htons(ETH_P_WCCP)) {
+			skb->protocol = __constant_htons(ETH_P_IP);
+			if ((*(h + offset) & 0xF0) != 0x40) 
+				offset += 4;
+		}
+
 		skb->mac.raw = skb->nh.raw;
 		skb->nh.raw = __pskb_pull(skb, offset);
 		memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
 		if (skb->ip_summed == CHECKSUM_HW)
 			skb->csum = csum_sub(skb->csum,
 					     csum_partial(skb->mac.raw, skb->nh.raw-skb->mac.raw, 0));
-		skb->protocol = *(u16*)(h + 2);
 		skb->pkt_type = PACKET_HOST;
 #ifdef CONFIG_NET_IPGRE_BROADCAST
 		if (MULTICAST(iph->daddr)) {
@@ -1240,7 +1250,7 @@ static struct net_protocol ipgre_protocol = {
 
 static int __init ipgre_init(void)
 {
-	int err = -EINVAL;
+	int err;
 
 	printk(KERN_INFO "GRE over IPv4 tunneling driver\n");
 
@@ -1253,18 +1263,19 @@ static int __init ipgre_init(void)
 					   ipgre_tunnel_setup);
 	if (!ipgre_fb_tunnel_dev) {
 		err = -ENOMEM;
-		goto fail;
+		goto err1;
 	}
 
 	ipgre_fb_tunnel_dev->init = ipgre_fb_tunnel_init;
 
 	if ((err = register_netdev(ipgre_fb_tunnel_dev)))
-		goto fail;
+		goto err2;
 out:
 	return err;
-fail:
-	inet_del_protocol(&ipgre_protocol, IPPROTO_GRE);
+err2:
 	free_netdev(ipgre_fb_tunnel_dev);
+err1:
+	inet_del_protocol(&ipgre_protocol, IPPROTO_GRE);
 	goto out;
 }
 
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index c7b3b6050..f2e88193d 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -231,10 +231,9 @@ static inline int ip_local_deliver_finish(struct sk_buff *skb)
 		if (raw_sk)
 			raw_v4_input(skb, skb->nh.iph, hash);
 
-		if ((ipprot = inet_protos[hash]) != NULL) {
+		if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) {
 			int ret;
 
-			smp_read_barrier_depends();
 			if (!ipprot->no_policy &&
 			    !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
 				kfree_skb(skb);
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 5a853aac2..8ef2b8263 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -78,6 +78,7 @@
 #include <net/raw.h>
 #include <net/checksum.h>
 #include <net/inetpeer.h>
+#include <net/checksum.h>
 #include <linux/igmp.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_bridge.h>
@@ -304,7 +305,6 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
 	struct ip_options *opt = inet->opt;
 	struct rtable *rt;
 	struct iphdr *iph;
-	u32 mtu;
 
 	/* Skip all of this if the packet is already routed,
 	 * f.e. by something like SCTP.
@@ -365,23 +365,11 @@ packet_routed:
 	skb->nh.iph   = iph;
 	/* Transport layer set skb->h.foo itself. */
 
-	if(opt && opt->optlen) {
+	if (opt && opt->optlen) {
 		iph->ihl += opt->optlen >> 2;
 		ip_options_build(skb, opt, inet->daddr, rt, 0);
 	}
 
-	mtu = dst_pmtu(&rt->u.dst);
-	if (skb->len > mtu && (sk->sk_route_caps & NETIF_F_TSO)) {
-		unsigned int hlen;
-
-		/* Hack zone: all this must be done by TCP. */
-		hlen = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
-		skb_shinfo(skb)->tso_size = mtu - hlen;
-		skb_shinfo(skb)->tso_segs =
-			(skb->len - hlen + skb_shinfo(skb)->tso_size - 1)/
-				skb_shinfo(skb)->tso_size - 1;
-	}
-
 	ip_select_ident_more(iph, &rt->u.dst, sk, skb_shinfo(skb)->tso_segs);
 
 	/* Add an IP checksum. */
@@ -421,6 +409,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
 	nf_conntrack_put(to->nfct);
 	to->nfct = from->nfct;
 	nf_conntrack_get(to->nfct);
+	to->nfctinfo = from->nfctinfo;
 #ifdef CONFIG_BRIDGE_NETFILTER
 	nf_bridge_put(to->nf_bridge);
 	to->nf_bridge = from->nf_bridge;
@@ -712,7 +701,7 @@ csum_page(struct page *page, int offset, int copy)
 /*
  *	ip_append_data() and ip_append_page() can make one large IP datagram
  *	from many pieces of data. Each pieces will be holded on the socket
- *	until ip_push_pending_frames() is called. Eache pieces can be a page
+ *	until ip_push_pending_frames() is called. Each piece can be a page
  *	or non-page data.
  *	
  *	Not only UDP, other transport protocols - e.g. raw sockets - can use
@@ -780,7 +769,7 @@ int ip_append_data(struct sock *sk,
 	hh_len = LL_RESERVED_SPACE(rt->u.dst.dev);
 
 	fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0);
-	maxfraglen = ((mtu-fragheaderlen) & ~7) + fragheaderlen;
+	maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen;
 
 	if (inet->cork.length + length > 0xFFFF - fragheaderlen) {
 		ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->dport, mtu-exthdrlen);
@@ -792,7 +781,7 @@ int ip_append_data(struct sock *sk,
 	 * it won't be fragmented in the future.
 	 */
 	if (transhdrlen &&
-	    length + fragheaderlen <= maxfraglen &&
+	    length + fragheaderlen <= mtu &&
 	    rt->u.dst.dev->features&(NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM) &&
 	    !exthdrlen)
 		csummode = CHECKSUM_HW;
@@ -804,34 +793,42 @@ int ip_append_data(struct sock *sk,
 	 * We use calculated fragment length to generate chained skb,
 	 * each of segments is IP fragment ready for sending to network after
 	 * adding appropriate IP header.
-	 *
-	 * Mistake is:
-	 *
-	 *    If mtu-fragheaderlen is not 0 modulo 8, we generate additional
-	 *    small fragment of length (mtu-fragheaderlen)%8, even though
-	 *    it is not necessary. Not a big bug, but needs a fix.
 	 */
 
 	if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)
 		goto alloc_new_skb;
 
 	while (length > 0) {
-		if ((copy = maxfraglen - skb->len) <= 0) {
+		/* Check if the remaining data fits into current packet. */
+		copy = mtu - skb->len;
+		if (copy < length)
+			copy = maxfraglen - skb->len;
+		if (copy <= 0) {
 			char *data;
 			unsigned int datalen;
 			unsigned int fraglen;
+			unsigned int fraggap;
 			unsigned int alloclen;
-			BUG_TRAP(copy == 0);
-
+			struct sk_buff *skb_prev;
 alloc_new_skb:
-			datalen = maxfraglen - fragheaderlen;
-			if (datalen > length)
-				datalen = length;
+			skb_prev = skb;
+			if (skb_prev)
+				fraggap = skb_prev->len - maxfraglen;
+			else
+				fraggap = 0;
 
+			/*
+			 * If remaining data exceeds the mtu,
+			 * we know we need more fragment(s).
+			 */
+			datalen = length + fraggap;
+			if (datalen > mtu - fragheaderlen)
+				datalen = maxfraglen - fragheaderlen;
 			fraglen = datalen + fragheaderlen;
+
 			if ((flags & MSG_MORE) && 
 			    !(rt->u.dst.dev->features&NETIF_F_SG))
-				alloclen = maxfraglen;
+				alloclen = mtu;
 			else
 				alloclen = datalen + fragheaderlen;
 
@@ -875,15 +872,25 @@ alloc_new_skb:
 			data += fragheaderlen;
 			skb->h.raw = data + exthdrlen;
 
-			copy = datalen - transhdrlen;
-			if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, 0, skb) < 0) {
+			if (fraggap) {
+				skb->csum = skb_copy_and_csum_bits(
+					skb_prev, maxfraglen,
+					data + transhdrlen, fraggap, 0);
+				skb_prev->csum = csum_sub(skb_prev->csum,
+							  skb->csum);
+				data += fraggap;
+				skb_trim(skb_prev, maxfraglen);
+			}
+
+			copy = datalen - transhdrlen - fraggap;
+			if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) {
 				err = -EFAULT;
 				kfree_skb(skb);
 				goto error;
 			}
 
 			offset += copy;
-			length -= datalen;
+			length -= datalen - fraggap;
 			transhdrlen = 0;
 			exthdrlen = 0;
 			csummode = CHECKSUM_NONE;
@@ -978,7 +985,7 @@ ssize_t	ip_append_page(struct sock *sk, struct page *page,
 	int mtu;
 	int len;
 	int err;
-	unsigned int maxfraglen, fragheaderlen;
+	unsigned int maxfraglen, fragheaderlen, fraggap;
 
 	if (inet->hdrincl)
 		return -EPERM;
@@ -1000,7 +1007,7 @@ ssize_t	ip_append_page(struct sock *sk, struct page *page,
 	mtu = inet->cork.fragsize;
 
 	fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0);
-	maxfraglen = ((mtu-fragheaderlen) & ~7) + fragheaderlen;
+	maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen;
 
 	if (inet->cork.length + size > 0xFFFF - fragheaderlen) {
 		ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->dport, mtu);
@@ -1014,13 +1021,25 @@ ssize_t	ip_append_page(struct sock *sk, struct page *page,
 
 	while (size > 0) {
 		int i;
-		if ((len = maxfraglen - skb->len) <= 0) {
+
+		/* Check if the remaining data fits into current packet. */
+		len = mtu - skb->len;
+		if (len < size)
+			len = maxfraglen - skb->len;
+		if (len <= 0) {
+			struct sk_buff *skb_prev;
 			char *data;
 			struct iphdr *iph;
-			BUG_TRAP(len == 0);
+			int alloclen;
+
+			skb_prev = skb;
+			if (skb_prev)
+				fraggap = skb_prev->len - maxfraglen;
+			else
+				fraggap = 0;
 
-			skb = sock_wmalloc(sk, fragheaderlen + hh_len + 15, 1,
-					   sk->sk_allocation);
+			alloclen = fragheaderlen + hh_len + fraggap + 15;
+			skb = sock_wmalloc(sk, alloclen, 1, sk->sk_allocation);
 			if (unlikely(!skb)) {
 				err = -ENOBUFS;
 				goto error;
@@ -1036,11 +1055,20 @@ ssize_t	ip_append_page(struct sock *sk, struct page *page,
 			/*
 			 *	Find where to start putting bytes.
 			 */
-			data = skb_put(skb, fragheaderlen);
+			data = skb_put(skb, fragheaderlen + fraggap);
 			skb->nh.iph = iph = (struct iphdr *)data;
 			data += fragheaderlen;
 			skb->h.raw = data;
 
+			if (fraggap) {
+				skb->csum = skb_copy_and_csum_bits(
+					skb_prev, maxfraglen,
+					data, fraggap, 0);
+				skb_prev->csum = csum_sub(skb_prev->csum,
+							  skb->csum);
+				skb_trim(skb_prev, maxfraglen);
+			}
+
 			/*
 			 * Put the packet on the pending queue.
 			 */
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 7ce7469a3..6845207f2 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -16,25 +16,48 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <asm/scatterlist.h>
+#include <asm/semaphore.h>
 #include <linux/crypto.h>
 #include <linux/pfkeyv2.h>
+#include <linux/percpu.h>
+#include <linux/smp.h>
+#include <linux/list.h>
+#include <linux/vmalloc.h>
+#include <linux/rtnetlink.h>
 #include <net/ip.h>
 #include <net/xfrm.h>
 #include <net/icmp.h>
 #include <net/ipcomp.h>
 
+struct ipcomp_tfms {
+	struct list_head list;
+	struct crypto_tfm **tfms;
+	int users;
+};
+
+static DECLARE_MUTEX(ipcomp_resource_sem);
+static void **ipcomp_scratches;
+static int ipcomp_scratch_users;
+static LIST_HEAD(ipcomp_tfms_list);
+
 static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb)
 {
 	int err, plen, dlen;
 	struct iphdr *iph;
 	struct ipcomp_data *ipcd = x->data;
-	u8 *start, *scratch = ipcd->scratch;
+	u8 *start, *scratch;
+	struct crypto_tfm *tfm;
+	int cpu;
 	
 	plen = skb->len;
 	dlen = IPCOMP_SCRATCH_SIZE;
 	start = skb->data;
 
-	err = crypto_comp_decompress(ipcd->tfm, start, plen, scratch, &dlen);
+	cpu = get_cpu();
+	scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
+	tfm = *per_cpu_ptr(ipcd->tfms, cpu);
+
+	err = crypto_comp_decompress(tfm, start, plen, scratch, &dlen);
 	if (err)
 		goto out;
 
@@ -52,6 +75,7 @@ static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb)
 	iph = skb->nh.iph;
 	iph->tot_len = htons(dlen + iph->ihl * 4);
 out:	
+	put_cpu();
 	return err;
 }
 
@@ -97,14 +121,20 @@ static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb)
 	int err, plen, dlen, ihlen;
 	struct iphdr *iph = skb->nh.iph;
 	struct ipcomp_data *ipcd = x->data;
-	u8 *start, *scratch = ipcd->scratch;
+	u8 *start, *scratch;
+	struct crypto_tfm *tfm;
+	int cpu;
 	
 	ihlen = iph->ihl * 4;
 	plen = skb->len - ihlen;
 	dlen = IPCOMP_SCRATCH_SIZE;
 	start = skb->data + ihlen;
 
-	err = crypto_comp_compress(ipcd->tfm, start, plen, scratch, &dlen);
+	cpu = get_cpu();
+	scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
+	tfm = *per_cpu_ptr(ipcd->tfms, cpu);
+
+	err = crypto_comp_compress(tfm, start, plen, scratch, &dlen);
 	if (err)
 		goto out;
 
@@ -114,26 +144,30 @@ static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb)
 	}
 	
 	memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen);
+	put_cpu();
+
 	pskb_trim(skb, ihlen + dlen + sizeof(struct ip_comp_hdr));
+	return 0;
 	
 out:	
+	put_cpu();
 	return err;
 }
 
-static int ipcomp_output(struct sk_buff **pskb)
+static int ipcomp_output(struct sk_buff *skb)
 {
 	int err;
-	struct dst_entry *dst = (*pskb)->dst;
+	struct dst_entry *dst = skb->dst;
 	struct xfrm_state *x = dst->xfrm;
 	struct iphdr *iph;
 	struct ip_comp_hdr *ipch;
 	struct ipcomp_data *ipcd = x->data;
 	int hdr_len = 0;
 
-	iph = (*pskb)->nh.iph;
-	iph->tot_len = htons((*pskb)->len);
+	iph = skb->nh.iph;
+	iph->tot_len = htons(skb->len);
 	hdr_len = iph->ihl * 4;
-	if (((*pskb)->len - hdr_len) < ipcd->threshold) {
+	if ((skb->len - hdr_len) < ipcd->threshold) {
 		/* Don't bother compressing */
 		if (x->props.mode) {
 			ip_send_check(iph);
@@ -141,17 +175,17 @@ static int ipcomp_output(struct sk_buff **pskb)
 		goto out_ok;
 	}
 
-	if ((skb_is_nonlinear(*pskb) || skb_cloned(*pskb)) &&
-	    skb_linearize(*pskb, GFP_ATOMIC) != 0) {
+	if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
+	    skb_linearize(skb, GFP_ATOMIC) != 0) {
 	    	err = -ENOMEM;
 	    	goto error;
 	}
 	
-	err = ipcomp_compress(x, *pskb);
+	err = ipcomp_compress(x, skb);
 	if (err) {
 		if (err == -EMSGSIZE) {
 			if (x->props.mode) {
-				iph = (*pskb)->nh.iph;
+				iph = skb->nh.iph;
 				ip_send_check(iph);
 			}
 			goto out_ok;
@@ -160,8 +194,8 @@ static int ipcomp_output(struct sk_buff **pskb)
 	}
 
 	/* Install ipcomp header, convert into ipcomp datagram. */
-	iph = (*pskb)->nh.iph;
-	iph->tot_len = htons((*pskb)->len);
+	iph = skb->nh.iph;
+	iph->tot_len = htons(skb->len);
 	ipch = (struct ip_comp_hdr *)((char *)iph + iph->ihl * 4);
 	ipch->nexthdr = iph->protocol;
 	ipch->flags = 0;
@@ -260,12 +294,132 @@ out:
 	return err;
 }
 
+static void ipcomp_free_scratches(void)
+{
+	int i;
+	void **scratches;
+
+	if (--ipcomp_scratch_users)
+		return;
+
+	scratches = ipcomp_scratches;
+	if (!scratches)
+		return;
+
+	for_each_cpu(i) {
+		void *scratch = *per_cpu_ptr(scratches, i);
+		if (scratch)
+			vfree(scratch);
+	}
+
+	free_percpu(scratches);
+}
+
+static void **ipcomp_alloc_scratches(void)
+{
+	int i;
+	void **scratches;
+
+	if (ipcomp_scratch_users++)
+		return ipcomp_scratches;
+
+	scratches = alloc_percpu(void *);
+	if (!scratches)
+		return NULL;
+
+	ipcomp_scratches = scratches;
+
+	for_each_cpu(i) {
+		void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE);
+		if (!scratch)
+			return NULL;
+		*per_cpu_ptr(scratches, i) = scratch;
+	}
+
+	return scratches;
+}
+
+static void ipcomp_free_tfms(struct crypto_tfm **tfms)
+{
+	struct ipcomp_tfms *pos;
+	int cpu;
+
+	list_for_each_entry(pos, &ipcomp_tfms_list, list) {
+		if (pos->tfms == tfms)
+			break;
+	}
+
+	BUG_TRAP(pos);
+
+	if (--pos->users)
+		return;
+
+	list_del(&pos->list);
+	kfree(pos);
+
+	if (!tfms)
+		return;
+
+	for_each_cpu(cpu) {
+		struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu);
+		if (tfm)
+			crypto_free_tfm(tfm);
+	}
+	free_percpu(tfms);
+}
+
+static struct crypto_tfm **ipcomp_alloc_tfms(const char *alg_name)
+{
+	struct ipcomp_tfms *pos;
+	struct crypto_tfm **tfms;
+	int cpu;
+
+	/* This can be any valid CPU ID so we don't need locking. */
+	cpu = smp_processor_id();
+
+	list_for_each_entry(pos, &ipcomp_tfms_list, list) {
+		struct crypto_tfm *tfm;
+
+		tfms = pos->tfms;
+		tfm = *per_cpu_ptr(tfms, cpu);
+
+		if (!strcmp(crypto_tfm_alg_name(tfm), alg_name)) {
+			pos->users++;
+			return tfms;
+		}
+	}
+
+	pos = kmalloc(sizeof(*pos), GFP_KERNEL);
+	if (!pos)
+		return NULL;
+
+	pos->users = 1;
+	INIT_LIST_HEAD(&pos->list);
+	list_add(&pos->list, &ipcomp_tfms_list);
+
+	pos->tfms = tfms = alloc_percpu(struct crypto_tfm *);
+	if (!tfms)
+		goto error;
+
+	for_each_cpu(cpu) {
+		struct crypto_tfm *tfm = crypto_alloc_tfm(alg_name, 0);
+		if (!tfm)
+			goto error;
+		*per_cpu_ptr(tfms, cpu) = tfm;
+	}
+
+	return tfms;
+
+error:
+	ipcomp_free_tfms(tfms);
+	return NULL;
+}
+
 static void ipcomp_free_data(struct ipcomp_data *ipcd)
 {
-	if (ipcd->tfm)
-		crypto_free_tfm(ipcd->tfm);
-	if (ipcd->scratch)
-		kfree(ipcd->scratch);	
+	if (ipcd->tfms)
+		ipcomp_free_tfms(ipcd->tfms);
+	ipcomp_free_scratches();
 }
 
 static void ipcomp_destroy(struct xfrm_state *x)
@@ -274,7 +428,9 @@ static void ipcomp_destroy(struct xfrm_state *x)
 	if (!ipcd)
 		return;
 	xfrm_state_delete_tunnel(x);
+	down(&ipcomp_resource_sem);
 	ipcomp_free_data(ipcd);
+	up(&ipcomp_resource_sem);
 	kfree(ipcd);
 }
 
@@ -288,28 +444,32 @@ static int ipcomp_init_state(struct xfrm_state *x, void *args)
 	if (!x->calg)
 		goto out;
 
+	if (x->encap)
+		goto out;
+
 	err = -ENOMEM;
 	ipcd = kmalloc(sizeof(*ipcd), GFP_KERNEL);
 	if (!ipcd)
-		goto error;
+		goto out;
 
 	memset(ipcd, 0, sizeof(*ipcd));
 	x->props.header_len = 0;
 	if (x->props.mode)
 		x->props.header_len += sizeof(struct iphdr);
 
-	ipcd->scratch = kmalloc(IPCOMP_SCRATCH_SIZE, GFP_KERNEL);
-	if (!ipcd->scratch)
+	down(&ipcomp_resource_sem);
+	if (!ipcomp_alloc_scratches())
 		goto error;
-	
-	ipcd->tfm = crypto_alloc_tfm(x->calg->alg_name, 0);
-	if (!ipcd->tfm)
+
+	ipcd->tfms = ipcomp_alloc_tfms(x->calg->alg_name);
+	if (!ipcd->tfms)
 		goto error;
+	up(&ipcomp_resource_sem);
 
 	if (x->props.mode) {
 		err = ipcomp_tunnel_attach(x);
 		if (err)
-			goto error;
+			goto error_tunnel;
 	}
 
 	calg_desc = xfrm_calg_get_byname(x->calg->alg_name);
@@ -320,11 +480,12 @@ static int ipcomp_init_state(struct xfrm_state *x, void *args)
 out:
 	return err;
 
+error_tunnel:
+	down(&ipcomp_resource_sem);
 error:
-	if (ipcd) {
-		ipcomp_free_data(ipcd);
-		kfree(ipcd);
-	}
+	ipcomp_free_data(ipcd);
+	up(&ipcomp_resource_sem);
+	kfree(ipcd);
 	goto out;
 }
 
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 92db76fe7..a0c8504dc 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -720,6 +720,8 @@ static void __init ic_bootp_send_if(struct ic_device *d, unsigned long jiffies_d
 		b->htype = dev->type;
 	else if (dev->type == ARPHRD_IEEE802_TR) /* fix for token ring */
 		b->htype = ARPHRD_IEEE802;
+	else if (dev->type == ARPHRD_FDDI)
+		b->htype = ARPHRD_ETHER;
 	else {
 		printk("Unknown ARP type 0x%04x for device %s\n", dev->type, dev->name);
 		b->htype = dev->type; /* can cause undefined behavior */
@@ -966,6 +968,9 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
 				break;
 
 			case DHCPACK:
+				if (memcmp(dev->dev_addr, b->hw_addr, dev->addr_len) != 0)
+					goto drop_unlock;
+
 				/* Yeah! */
 				break;
 
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 98ba22404..1c1c2e1d4 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -246,7 +246,6 @@ static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int c
 	nt = dev->priv;
 	SET_MODULE_OWNER(dev);
 	dev->init = ipip_tunnel_init;
-	dev->destructor = free_netdev;
 	nt->parms = *parms;
 
 	if (register_netdevice(dev) < 0) {
@@ -461,8 +460,7 @@ static inline void ipip_ecn_decapsulate(struct iphdr *outer_iph, struct sk_buff
 {
 	struct iphdr *inner_iph = skb->nh.iph;
 
-	if (INET_ECN_is_ce(outer_iph->tos) &&
-	    INET_ECN_is_not_ce(inner_iph->tos))
+	if (INET_ECN_is_ce(outer_iph->tos))
 		IP_ECN_set_ce(inner_iph);
 }
 
@@ -785,6 +783,7 @@ static void ipip_tunnel_setup(struct net_device *dev)
 	dev->get_stats		= ipip_tunnel_get_stats;
 	dev->do_ioctl		= ipip_tunnel_ioctl;
 	dev->change_mtu		= ipip_tunnel_change_mtu;
+	dev->destructor		= free_netdev;
 
 	dev->type		= ARPHRD_TUNNEL;
 	dev->hard_header_len 	= LL_MAX_HEADER + sizeof(struct iphdr);
@@ -877,18 +876,19 @@ static int __init ipip_init(void)
 					   ipip_tunnel_setup);
 	if (!ipip_fb_tunnel_dev) {
 		err = -ENOMEM;
-		goto fail;
+		goto err1;
 	}
 
 	ipip_fb_tunnel_dev->init = ipip_fb_tunnel_init;
 
 	if ((err = register_netdev(ipip_fb_tunnel_dev)))
-	    goto fail;
+		goto err2;
  out:
 	return err;
- fail:
-	xfrm4_tunnel_deregister(&ipip_handler);
+ err2:
 	free_netdev(ipip_fb_tunnel_dev);
+ err1:
+	xfrm4_tunnel_deregister(&ipip_handler);
 	goto out;
 }
 
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index 9f4b94f07..168e5b342 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -383,21 +383,23 @@ ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 	struct ip_vs_conn *cp = NULL;
 	struct iphdr *iph = skb->nh.iph;
 	struct ip_vs_dest *dest;
-	__u16 ports[2];
+	__u16 _ports[2], *pptr;
 
-	if (skb_copy_bits(skb, iph->ihl*4, ports, sizeof(ports)) < 0)
+	pptr = skb_header_pointer(skb, iph->ihl*4,
+				  sizeof(_ports), _ports);
+	if (pptr == NULL)
 		return NULL;
 
 	/*
 	 *    Persistent service
 	 */
 	if (svc->flags & IP_VS_SVC_F_PERSISTENT)
-		return ip_vs_sched_persist(svc, skb, ports);
+		return ip_vs_sched_persist(svc, skb, pptr);
 
 	/*
 	 *    Non-persistent service
 	 */
-	if (!svc->fwmark && ports[1] != svc->port) {
+	if (!svc->fwmark && pptr[1] != svc->port) {
 		if (!svc->port)
 			IP_VS_ERR("Schedule: port zero only supported "
 				  "in persistent services, "
@@ -415,9 +417,9 @@ ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 	 *    Create a connection entry.
 	 */
 	cp = ip_vs_conn_new(iph->protocol,
-			    iph->saddr, ports[0],
-			    iph->daddr, ports[1],
-			    dest->addr, dest->port?dest->port:ports[1],
+			    iph->saddr, pptr[0],
+			    iph->daddr, pptr[1],
+			    dest->addr, dest->port?dest->port:pptr[1],
 			    0,
 			    dest);
 	if (cp == NULL)
@@ -444,10 +446,12 @@ ip_vs_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
 		struct ip_vs_protocol *pp)
 {
-	__u16 ports[2];
+	__u16 _ports[2], *pptr;
 	struct iphdr *iph = skb->nh.iph;
 
-	if (skb_copy_bits(skb, iph->ihl*4, ports, sizeof(ports)) < 0) {
+	pptr = skb_header_pointer(skb, iph->ihl*4,
+				  sizeof(_ports), _ports);
+	if (pptr == NULL) {
 		ip_vs_service_put(svc);
 		return NF_DROP;
 	}
@@ -465,8 +469,8 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
 		/* create a new connection entry */
 		IP_VS_DBG(6, "ip_vs_leave: create a cache_bypass entry\n");
 		cp = ip_vs_conn_new(iph->protocol,
-				    iph->saddr, ports[0],
-				    iph->daddr, ports[1],
+				    iph->saddr, pptr[0],
+				    iph->daddr, pptr[1],
 				    0, 0,
 				    IP_VS_CONN_F_BYPASS,
 				    NULL);
@@ -494,7 +498,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
 	 * listed in the ipvs table), pass the packets, because it is
 	 * not ipvs job to decide to drop the packets.
 	 */
-	if ((svc->port == FTPPORT) && (ports[1] != FTPPORT)) {
+	if ((svc->port == FTPPORT) && (pptr[1] != FTPPORT)) {
 		ip_vs_service_put(svc);
 		return NF_ACCEPT;
 	}
@@ -607,8 +611,8 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related)
 {
 	struct sk_buff *skb = *pskb;
 	struct iphdr *iph;
-	struct icmphdr	icmph;
-	struct iphdr	ciph;	/* The ip header contained within the ICMP */
+	struct icmphdr	_icmph, *ic;
+	struct iphdr	_ciph, *cih;	/* The ip header contained within the ICMP */
 	struct ip_vs_conn *cp;
 	struct ip_vs_protocol *pp;
 	unsigned int offset, ihl, verdict;
@@ -625,11 +629,12 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related)
 
 	iph = skb->nh.iph;
 	offset = ihl = iph->ihl * 4;
-	if (skb_copy_bits(skb, offset, &icmph, sizeof(icmph)) < 0)
+	ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
+	if (ic == NULL)
 		return NF_DROP;
 
 	IP_VS_DBG(12, "Outgoing ICMP (%d,%d) %u.%u.%u.%u->%u.%u.%u.%u\n",
-		  icmph.type, ntohs(icmp_id(&icmph)),
+		  ic->type, ntohs(icmp_id(ic)),
 		  NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
 
 	/*
@@ -639,33 +644,34 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related)
 	 * this means that some packets will manage to get a long way
 	 * down this stack and then be rejected, but that's life.
 	 */
-	if ((icmph.type != ICMP_DEST_UNREACH) &&
-	    (icmph.type != ICMP_SOURCE_QUENCH) &&
-	    (icmph.type != ICMP_TIME_EXCEEDED)) {
+	if ((ic->type != ICMP_DEST_UNREACH) &&
+	    (ic->type != ICMP_SOURCE_QUENCH) &&
+	    (ic->type != ICMP_TIME_EXCEEDED)) {
 		*related = 0;
 		return NF_ACCEPT;
 	}
 
 	/* Now find the contained IP header */
-	offset += sizeof(icmph);
-	if (skb_copy_bits(skb, offset, &ciph, sizeof(ciph)) < 0)
+	offset += sizeof(_icmph);
+	cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+	if (cih == NULL)
 		return NF_ACCEPT; /* The packet looks wrong, ignore */
 
-	pp = ip_vs_proto_get(ciph.protocol);
+	pp = ip_vs_proto_get(cih->protocol);
 	if (!pp)
 		return NF_ACCEPT;
 
 	/* Is the embedded protocol header present? */
-	if (unlikely(ciph.frag_off & __constant_htons(IP_OFFSET) &&
+	if (unlikely(cih->frag_off & __constant_htons(IP_OFFSET) &&
 		     pp->dont_defrag))
 		return NF_ACCEPT;
 
 	IP_VS_DBG_PKT(11, pp, skb, offset, "Checking outgoing ICMP for");
 
-	offset += ciph.ihl * 4;
+	offset += cih->ihl * 4;
 
 	/* The embedded headers contain source and dest in reverse order */
-	cp = pp->conn_out_get(skb, pp, &ciph, offset, 1);
+	cp = pp->conn_out_get(skb, pp, cih, offset, 1);
 	if (!cp)
 		return NF_ACCEPT;
 
@@ -685,7 +691,7 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related)
 		goto out;
 	}
 
-	if (IPPROTO_TCP == ciph.protocol || IPPROTO_UDP == ciph.protocol)
+	if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol)
 		offset += 2 * sizeof(__u16);
 	if (!ip_vs_make_skb_writable(pskb, offset))
 		goto out;
@@ -707,11 +713,13 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related)
 
 static inline int is_tcp_reset(const struct sk_buff *skb)
 {
-	struct tcphdr tcph;
+	struct tcphdr _tcph, *th;
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &tcph, sizeof(tcph)) < 0)
+	th = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+				sizeof(_tcph), &_tcph);
+	if (th == NULL)
 		return 0;
-	return tcph.rst;
+	return th->rst;
 }
 
 /*
@@ -735,13 +743,6 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
 	if (skb->nfcache & NFC_IPVS_PROPERTY)
 		return NF_ACCEPT;
 
-	if (skb->ip_summed == CHECKSUM_HW) {
-		if (skb_checksum_help(pskb, (out == NULL)))
-			return NF_DROP;
-		if (skb != *pskb)
-			skb = *pskb;
-	}
-
 	iph = skb->nh.iph;
 	if (unlikely(iph->protocol == IPPROTO_ICMP)) {
 		int related, verdict = ip_vs_out_icmp(pskb, &related);
@@ -777,12 +778,14 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
 		if (sysctl_ip_vs_nat_icmp_send &&
 		    (pp->protocol == IPPROTO_TCP ||
 		     pp->protocol == IPPROTO_UDP)) {
-			__u16 ports[2];
+			__u16 _ports[2], *pptr;
 
-			if (skb_copy_bits(skb, ihl, ports, sizeof(ports)) < 0)
+			pptr = skb_header_pointer(skb, ihl,
+						  sizeof(_ports), _ports);
+			if (pptr == NULL)
 				return NF_ACCEPT;	/* Not for me */
 			if (ip_vs_lookup_real_service(iph->protocol,
-						      iph->saddr, ports[0])) {
+						      iph->saddr, pptr[0])) {
 				/*
 				 * Notify the real server: there is no
 				 * existing entry if it is not RST
@@ -866,8 +869,8 @@ static int ip_vs_in_icmp(struct sk_buff **pskb, int *related)
 {
 	struct sk_buff *skb = *pskb;
 	struct iphdr *iph;
-	struct icmphdr	icmph;
-	struct iphdr	ciph;	/* The ip header contained within the ICMP */
+	struct icmphdr	_icmph, *ic;
+	struct iphdr	_ciph, *cih;	/* The ip header contained within the ICMP */
 	struct ip_vs_conn *cp;
 	struct ip_vs_protocol *pp;
 	unsigned int offset, ihl, verdict;
@@ -884,11 +887,12 @@ static int ip_vs_in_icmp(struct sk_buff **pskb, int *related)
 
 	iph = skb->nh.iph;
 	offset = ihl = iph->ihl * 4;
-	if (skb_copy_bits(skb, offset, &icmph, sizeof(icmph)) < 0)
+	ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
+	if (ic == NULL)
 		return NF_DROP;
 
 	IP_VS_DBG(12, "Incoming ICMP (%d,%d) %u.%u.%u.%u->%u.%u.%u.%u\n",
-		  icmph.type, ntohs(icmp_id(&icmph)),
+		  ic->type, ntohs(icmp_id(ic)),
 		  NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
 
 	/*
@@ -898,33 +902,34 @@ static int ip_vs_in_icmp(struct sk_buff **pskb, int *related)
 	 * this means that some packets will manage to get a long way
 	 * down this stack and then be rejected, but that's life.
 	 */
-	if ((icmph.type != ICMP_DEST_UNREACH) &&
-	    (icmph.type != ICMP_SOURCE_QUENCH) &&
-	    (icmph.type != ICMP_TIME_EXCEEDED)) {
+	if ((ic->type != ICMP_DEST_UNREACH) &&
+	    (ic->type != ICMP_SOURCE_QUENCH) &&
+	    (ic->type != ICMP_TIME_EXCEEDED)) {
 		*related = 0;
 		return NF_ACCEPT;
 	}
 
 	/* Now find the contained IP header */
-	offset += sizeof(icmph);
-	if (skb_copy_bits(skb, offset, &ciph, sizeof(ciph)) < 0)
+	offset += sizeof(_icmph);
+	cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
+	if (cih == NULL)
 		return NF_ACCEPT; /* The packet looks wrong, ignore */
 
-	pp = ip_vs_proto_get(ciph.protocol);
+	pp = ip_vs_proto_get(cih->protocol);
 	if (!pp)
 		return NF_ACCEPT;
 
 	/* Is the embedded protocol header present? */
-	if (unlikely(ciph.frag_off & __constant_htons(IP_OFFSET) &&
+	if (unlikely(cih->frag_off & __constant_htons(IP_OFFSET) &&
 		     pp->dont_defrag))
 		return NF_ACCEPT;
 
 	IP_VS_DBG_PKT(11, pp, skb, offset, "Checking incoming ICMP for");
 
-	offset += ciph.ihl * 4;
+	offset += cih->ihl * 4;
 
 	/* The embedded headers contain source and dest in reverse order */
-	cp = pp->conn_in_get(skb, pp, &ciph, offset, 1);
+	cp = pp->conn_in_get(skb, pp, cih, offset, 1);
 	if (!cp)
 		return NF_ACCEPT;
 
@@ -941,7 +946,7 @@ static int ip_vs_in_icmp(struct sk_buff **pskb, int *related)
 
 	/* do the statistics and put it back */
 	ip_vs_in_stats(cp, skb);
-	if (IPPROTO_TCP == ciph.protocol || IPPROTO_UDP == ciph.protocol)
+	if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol)
 		offset += 2 * sizeof(__u16);
 	verdict = ip_vs_icmp_xmit(skb, cp, pp, offset);
 	/* do not touch skb anymore */
@@ -981,13 +986,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff **pskb,
 		return NF_ACCEPT;
 	}
 
-	if (skb->ip_summed == CHECKSUM_HW) {
-		if (skb_checksum_help(pskb, (out == NULL)))
-			return NF_DROP;
-		if (skb != *pskb)
-			skb = *pskb;
-	}
-
 	iph = skb->nh.iph;
 	if (unlikely(iph->protocol == IPPROTO_ICMP)) {
 		int related, verdict = ip_vs_in_icmp(pskb, &related);
diff --git a/net/ipv4/ipvs/ip_vs_proto.c b/net/ipv4/ipvs/ip_vs_proto.c
index caf24e375..dfd0a7dd3 100644
--- a/net/ipv4/ipvs/ip_vs_proto.c
+++ b/net/ipv4/ipvs/ip_vs_proto.c
@@ -166,27 +166,33 @@ ip_vs_tcpudp_debug_packet(struct ip_vs_protocol *pp,
 			  const char *msg)
 {
 	char buf[128];
-	__u16 ports[2];
-	struct iphdr iph;
+	struct iphdr _iph, *ih;
 
-	if (skb_copy_bits(skb, offset, &iph, sizeof(iph)) < 0)
+	ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
+	if (ih == NULL)
 		sprintf(buf, "%s TRUNCATED", pp->name);
-	else if (iph.frag_off & __constant_htons(IP_OFFSET))
+	else if (ih->frag_off & __constant_htons(IP_OFFSET))
 		sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u frag",
-			pp->name, NIPQUAD(iph.saddr),
-			NIPQUAD(iph.daddr));
-	else if (skb_copy_bits(skb, offset + iph.ihl*4, ports, sizeof(ports)) < 0)
-		sprintf(buf, "%s TRUNCATED %u.%u.%u.%u->%u.%u.%u.%u",
-			pp->name,
-			NIPQUAD(iph.saddr),
-			NIPQUAD(iph.daddr));
-	else
-		sprintf(buf, "%s %u.%u.%u.%u:%u->%u.%u.%u.%u:%u",
-			pp->name,
-			NIPQUAD(iph.saddr),
-			ntohs(ports[0]),
-			NIPQUAD(iph.daddr),
-			ntohs(ports[1]));
+			pp->name, NIPQUAD(ih->saddr),
+			NIPQUAD(ih->daddr));
+	else {
+		__u16 _ports[2], *pptr
+;
+		pptr = skb_header_pointer(skb, offset + ih->ihl*4,
+					  sizeof(_ports), _ports);
+		if (pptr == NULL)
+			sprintf(buf, "%s TRUNCATED %u.%u.%u.%u->%u.%u.%u.%u",
+				pp->name,
+				NIPQUAD(ih->saddr),
+				NIPQUAD(ih->daddr));
+		else
+			sprintf(buf, "%s %u.%u.%u.%u:%u->%u.%u.%u.%u:%u",
+				pp->name,
+				NIPQUAD(ih->saddr),
+				ntohs(pptr[0]),
+				NIPQUAD(ih->daddr),
+				ntohs(pptr[1]));
+	}
 
 	printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
 }
diff --git a/net/ipv4/ipvs/ip_vs_proto_ah.c b/net/ipv4/ipvs/ip_vs_proto_ah.c
index ffea536b0..453e94a0b 100644
--- a/net/ipv4/ipvs/ip_vs_proto_ah.c
+++ b/net/ipv4/ipvs/ip_vs_proto_ah.c
@@ -129,14 +129,15 @@ ah_debug_packet(struct ip_vs_protocol *pp, const struct sk_buff *skb,
 		int offset, const char *msg)
 {
 	char buf[256];
-	struct iphdr iph;
+	struct iphdr _iph, *ih;
 
-	if (skb_copy_bits(skb, offset, &iph, sizeof(iph)) < 0)
+	ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
+	if (ih == NULL)
 		sprintf(buf, "%s TRUNCATED", pp->name);
 	else
 		sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u",
-			pp->name, NIPQUAD(iph.saddr),
-			NIPQUAD(iph.daddr));
+			pp->name, NIPQUAD(ih->saddr),
+			NIPQUAD(ih->daddr));
 
 	printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
 }
diff --git a/net/ipv4/ipvs/ip_vs_proto_esp.c b/net/ipv4/ipvs/ip_vs_proto_esp.c
index 192238832..478e5c7c7 100644
--- a/net/ipv4/ipvs/ip_vs_proto_esp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_esp.c
@@ -128,14 +128,15 @@ esp_debug_packet(struct ip_vs_protocol *pp, const struct sk_buff *skb,
 		 int offset, const char *msg)
 {
 	char buf[256];
-	struct iphdr iph;
+	struct iphdr _iph, *ih;
 
-	if (skb_copy_bits(skb, offset, &iph, sizeof(iph)) < 0)
+	ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
+	if (ih == NULL)
 		sprintf(buf, "%s TRUNCATED", pp->name);
 	else
 		sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u",
-			pp->name, NIPQUAD(iph.saddr),
-			NIPQUAD(iph.daddr));
+			pp->name, NIPQUAD(ih->saddr),
+			NIPQUAD(ih->daddr));
 
 	printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
 }
diff --git a/net/ipv4/ipvs/ip_vs_proto_icmp.c b/net/ipv4/ipvs/ip_vs_proto_icmp.c
index d611b5a36..747e0333f 100644
--- a/net/ipv4/ipvs/ip_vs_proto_icmp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_icmp.c
@@ -104,24 +104,29 @@ icmp_debug_packet(struct ip_vs_protocol *pp,
 		  const char *msg)
 {
 	char buf[256];
-	struct iphdr iph;
-	struct icmphdr icmph;
+	struct iphdr _iph, *ih;
 
-	if (skb_copy_bits(skb, offset, &iph, sizeof(iph)) < 0)
+	ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
+	if (ih == NULL)
 		sprintf(buf, "%s TRUNCATED", pp->name);
-	else if (iph.frag_off & __constant_htons(IP_OFFSET))
+	else if (ih->frag_off & __constant_htons(IP_OFFSET))
 		sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u frag",
-			pp->name, NIPQUAD(iph.saddr),
-			NIPQUAD(iph.daddr));
-	else if (skb_copy_bits(skb, offset + iph.ihl*4, &icmph, sizeof(icmph)) < 0)
-		sprintf(buf, "%s TRUNCATED to %u bytes\n",
-			pp->name, skb->len - offset);
-	else
-		sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u T:%d C:%d",
-			pp->name, NIPQUAD(iph.saddr),
-			NIPQUAD(iph.daddr),
-			icmph.type, icmph.code);
-
+			pp->name, NIPQUAD(ih->saddr),
+			NIPQUAD(ih->daddr));
+	else {
+		struct icmphdr _icmph, *ic;
+
+		ic = skb_header_pointer(skb, offset + ih->ihl*4,
+					sizeof(_icmph), &_icmph);
+		if (ic == NULL)
+			sprintf(buf, "%s TRUNCATED to %u bytes\n",
+				pp->name, skb->len - offset);
+		else
+			sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u T:%d C:%d",
+				pp->name, NIPQUAD(ih->saddr),
+				NIPQUAD(ih->daddr),
+				ic->type, ic->code);
+	}
 	printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
 }
 
diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c
index 2f00e9142..bd8f898bf 100644
--- a/net/ipv4/ipvs/ip_vs_proto_tcp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c
@@ -29,19 +29,20 @@ static struct ip_vs_conn *
 tcp_conn_in_get(const struct sk_buff *skb, struct ip_vs_protocol *pp,
 		const struct iphdr *iph, unsigned int proto_off, int inverse)
 {
-	__u16 ports[2];
+	__u16 _ports[2], *pptr;
 
-	if (skb_copy_bits(skb, proto_off, ports, sizeof(ports)) < 0)
+	pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
+	if (pptr == NULL)
 		return NULL;
 
 	if (likely(!inverse)) {
 		return ip_vs_conn_in_get(iph->protocol,
-					 iph->saddr, ports[0],
-					 iph->daddr, ports[1]);
+					 iph->saddr, pptr[0],
+					 iph->daddr, pptr[1]);
 	} else {
 		return ip_vs_conn_in_get(iph->protocol,
-					 iph->daddr, ports[1],
-					 iph->saddr, ports[0]);
+					 iph->daddr, pptr[1],
+					 iph->saddr, pptr[0]);
 	}
 }
 
@@ -49,19 +50,20 @@ static struct ip_vs_conn *
 tcp_conn_out_get(const struct sk_buff *skb, struct ip_vs_protocol *pp,
 		 const struct iphdr *iph, unsigned int proto_off, int inverse)
 {
-	__u16 ports[2];
+	__u16 _ports[2], *pptr;
 
-	if (skb_copy_bits(skb, proto_off, ports, sizeof(ports)) < 0)
+	pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
+	if (pptr == NULL)
 		return NULL;
 
 	if (likely(!inverse)) {
 		return ip_vs_conn_out_get(iph->protocol,
-					  iph->saddr, ports[0],
-					  iph->daddr, ports[1]);
+					  iph->saddr, pptr[0],
+					  iph->daddr, pptr[1]);
 	} else {
 		return ip_vs_conn_out_get(iph->protocol,
-					  iph->daddr, ports[1],
-					  iph->saddr, ports[0]);
+					  iph->daddr, pptr[1],
+					  iph->saddr, pptr[0]);
 	}
 }
 
@@ -72,16 +74,18 @@ tcp_conn_schedule(struct sk_buff *skb,
 		  int *verdict, struct ip_vs_conn **cpp)
 {
 	struct ip_vs_service *svc;
-	struct tcphdr tcph;
+	struct tcphdr _tcph, *th;
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0) {
+	th = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+				sizeof(_tcph), &_tcph);
+	if (th == NULL) {
 		*verdict = NF_DROP;
 		return 0;
 	}
 
-	if (tcph.syn &&
+	if (th->syn &&
 	    (svc = ip_vs_service_get(skb->nfmark, skb->nh.iph->protocol,
-				     skb->nh.iph->daddr, tcph.dest))) {
+				     skb->nh.iph->daddr, th->dest))) {
 		if (ip_vs_todrop()) {
 			/*
 			 * It seems that we are very loaded.
@@ -483,13 +487,15 @@ tcp_state_transition(struct ip_vs_conn *cp, int direction,
 		     const struct sk_buff *skb,
 		     struct ip_vs_protocol *pp)
 {
-	struct tcphdr tcph;
+	struct tcphdr _tcph, *th;
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0)
+	th = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+				sizeof(_tcph), &_tcph);
+	if (th == NULL)
 		return 0;
 
 	spin_lock(&cp->lock);
-	set_tcp_state(pp, cp, direction, &tcph);
+	set_tcp_state(pp, cp, direction, th);
 	spin_unlock(&cp->lock);
 
 	return 1;
diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c
index 81501c938..443ec4578 100644
--- a/net/ipv4/ipvs/ip_vs_proto_udp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_udp.c
@@ -26,19 +26,20 @@ udp_conn_in_get(const struct sk_buff *skb, struct ip_vs_protocol *pp,
 		const struct iphdr *iph, unsigned int proto_off, int inverse)
 {
 	struct ip_vs_conn *cp;
-	__u16 ports[2];
+	__u16 _ports[2], *pptr;
 
-	if (skb_copy_bits(skb, proto_off, ports, sizeof(ports)) < 0)
+	pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
+	if (pptr == NULL)
 		return NULL;
 
 	if (likely(!inverse)) {
 		cp = ip_vs_conn_in_get(iph->protocol,
-				       iph->saddr, ports[0],
-				       iph->daddr, ports[1]);
+				       iph->saddr, pptr[0],
+				       iph->daddr, pptr[1]);
 	} else {
 		cp = ip_vs_conn_in_get(iph->protocol,
-				       iph->daddr, ports[1],
-				       iph->saddr, ports[0]);
+				       iph->daddr, pptr[1],
+				       iph->saddr, pptr[0]);
 	}
 
 	return cp;
@@ -50,19 +51,21 @@ udp_conn_out_get(const struct sk_buff *skb, struct ip_vs_protocol *pp,
 		 const struct iphdr *iph, unsigned int proto_off, int inverse)
 {
 	struct ip_vs_conn *cp;
-	__u16 ports[2];
+	__u16 _ports[2], *pptr;
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0)
+	pptr = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+				  sizeof(_ports), _ports);
+	if (pptr == NULL)
 		return NULL;
 
 	if (likely(!inverse)) {
 		cp = ip_vs_conn_out_get(iph->protocol,
-					iph->saddr, ports[0],
-					iph->daddr, ports[1]);
+					iph->saddr, pptr[0],
+					iph->daddr, pptr[1]);
 	} else {
 		cp = ip_vs_conn_out_get(iph->protocol,
-					iph->daddr, ports[1],
-					iph->saddr, ports[0]);
+					iph->daddr, pptr[1],
+					iph->saddr, pptr[0]);
 	}
 
 	return cp;
@@ -74,15 +77,17 @@ udp_conn_schedule(struct sk_buff *skb, struct ip_vs_protocol *pp,
 		  int *verdict, struct ip_vs_conn **cpp)
 {
 	struct ip_vs_service *svc;
-	struct udphdr udph;
+	struct udphdr _udph, *uh;
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &udph, sizeof(udph)) < 0) {
+	uh = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+				sizeof(_udph), &_udph);
+	if (uh == NULL) {
 		*verdict = NF_DROP;
 		return 0;
 	}
 
 	if ((svc = ip_vs_service_get(skb->nfmark, skb->nh.iph->protocol,
-				     skb->nh.iph->daddr, udph.dest))) {
+				     skb->nh.iph->daddr, uh->dest))) {
 		if (ip_vs_todrop()) {
 			/*
 			 * It seems that we are very loaded.
@@ -230,13 +235,14 @@ udp_dnat_handler(struct sk_buff **pskb,
 static int
 udp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp)
 {
-	struct udphdr udph;
+	struct udphdr _udph, *uh;
 	unsigned int udphoff = skb->nh.iph->ihl*4;
 
-	if (skb_copy_bits(skb, udphoff, &udph, sizeof(udph)) < 0)
+	uh = skb_header_pointer(skb, udphoff, sizeof(_udph), &_udph);
+	if (uh == NULL)
 		return 0;
 
-	if (udph.check != 0) {
+	if (uh->check != 0) {
 		switch (skb->ip_summed) {
 		case CHECKSUM_NONE:
 			skb->csum = skb_checksum(skb, udphoff,
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c
index 80fdab71e..45ab05a7f 100644
--- a/net/ipv4/ipvs/ip_vs_sync.c
+++ b/net/ipv4/ipvs/ip_vs_sync.c
@@ -16,6 +16,7 @@
  *	Alexandre Cassen	:	Added master & backup support at a time.
  *	Alexandre Cassen	:	Added SyncID support for incoming sync
  *					messages filtering.
+ *	Justin Ossevoort	:	Fix endian problem on sync message size.
  */
 
 #include <linux/module.h>
@@ -279,6 +280,9 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
 	char *p;
 	int i;
 
+	/* Convert size back to host byte order */
+	m->size = ntohs(m->size);
+
 	if (buflen != m->size) {
 		IP_VS_ERR("bogus message\n");
 		return;
@@ -569,6 +573,19 @@ ip_vs_send_async(struct socket *sock, const char *buffer, const size_t length)
 	return len;
 }
 
+static void
+ip_vs_send_sync_msg(struct socket *sock, struct ip_vs_sync_mesg *msg)
+{
+	int msize;
+
+	msize = msg->size;
+
+	/* Put size in network byte order */
+	msg->size = htons(msg->size);
+
+	if (ip_vs_send_async(sock, (char *)msg, msize) != msize)
+		IP_VS_ERR("ip_vs_send_async error\n");
+}
 
 static int
 ip_vs_receive(struct socket *sock, char *buffer, const size_t buflen)
@@ -605,7 +622,6 @@ static void sync_master_loop(void)
 {
 	struct socket *sock;
 	struct ip_vs_sync_buff *sb;
-	struct ip_vs_sync_mesg *m;
 
 	/* create the sending multicast socket */
 	sock = make_send_sock();
@@ -618,19 +634,13 @@ static void sync_master_loop(void)
 
 	for (;;) {
 		while ((sb=sb_dequeue())) {
-			m = sb->mesg;
-			if (ip_vs_send_async(sock, (char *)m,
-					     m->size) != m->size)
-				IP_VS_ERR("ip_vs_send_async error\n");
+			ip_vs_send_sync_msg(sock, sb->mesg);
 			ip_vs_sync_buff_release(sb);
 		}
 
 		/* check if entries stay in curr_sb for 2 seconds */
 		if ((sb = get_curr_sync_buff(2*HZ))) {
-			m = sb->mesg;
-			if (ip_vs_send_async(sock, (char *)m,
-					     m->size) != m->size)
-				IP_VS_ERR("ip_vs_send_async error\n");
+			ip_vs_send_sync_msg(sock, sb->mesg);
 			ip_vs_sync_buff_release(sb);
 		}
 
diff --git a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c
index 204767be4..58db69d12 100644
--- a/net/ipv4/ipvs/ip_vs_xmit.c
+++ b/net/ipv4/ipvs/ip_vs_xmit.c
@@ -124,10 +124,11 @@ ip_vs_dst_reset(struct ip_vs_dest *dest)
 	dst_release(old_dst);
 }
 
-
 #define IP_VS_XMIT(skb, rt)				\
 do {							\
+	nf_reset_debug(skb);				\
 	(skb)->nfcache |= NFC_IPVS_PROPERTY;		\
+	(skb)->ip_summed = CHECKSUM_NONE;		\
 	NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, (skb), NULL,	\
 		(rt)->u.dst.dev, dst_output);		\
 } while (0)
@@ -201,9 +202,6 @@ ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 	/* Another hack: avoid icmp_send in ip_fragment */
 	skb->local_df = 1;
 
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#endif /* CONFIG_NETFILTER_DEBUG */
 	IP_VS_XMIT(skb, rt);
 
 	LeaveFunction(10);
@@ -234,11 +232,12 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 
 	/* check if it is a connection of no-client-port */
 	if (unlikely(cp->flags & IP_VS_CONN_F_NO_CPORT)) {
-		__u16 pt;
-		if (skb_copy_bits(skb, iph->ihl*4, &pt, sizeof(pt)) < 0)
+		__u16 _pt, *p;
+		p = skb_header_pointer(skb, iph->ihl*4, sizeof(_pt), &_pt);
+		if (p == NULL)
 			goto tx_error;
-		ip_vs_conn_fill_cport(cp, pt);
-		IP_VS_DBG(10, "filled cport=%d\n", ntohs(pt));
+		ip_vs_conn_fill_cport(cp, *p);
+		IP_VS_DBG(10, "filled cport=%d\n", ntohs(*p));
 	}
 
 	if (!(rt = __ip_vs_get_out_rt(cp, RT_TOS(iph->tos))))
@@ -279,9 +278,6 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 	/* Another hack: avoid icmp_send in ip_fragment */
 	skb->local_df = 1;
 
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#endif /* CONFIG_NETFILTER_DEBUG */
 	IP_VS_XMIT(skb, rt);
 
 	LeaveFunction(10);
@@ -412,15 +408,9 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 	ip_select_ident(iph, &rt->u.dst, NULL);
 	ip_send_check(iph);
 
-	skb->ip_summed = CHECKSUM_NONE;
-
 	/* Another hack: avoid icmp_send in ip_fragment */
 	skb->local_df = 1;
 
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#endif /* CONFIG_NETFILTER_DEBUG */
-
 	IP_VS_XMIT(skb, rt);
 
 	LeaveFunction(10);
@@ -479,9 +469,6 @@ ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 	/* Another hack: avoid icmp_send in ip_fragment */
 	skb->local_df = 1;
 
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#endif /* CONFIG_NETFILTER_DEBUG */
 	IP_VS_XMIT(skb, rt);
 
 	LeaveFunction(10);
@@ -556,9 +543,6 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 	/* Another hack: avoid icmp_send in ip_fragment */
 	skb->local_df = 1;
 
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#endif /* CONFIG_NETFILTER_DEBUG */
 	IP_VS_XMIT(skb, rt);
 
 	rc = NF_STOLEN;
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index b58141ead..9d5ad38ff 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -5,6 +5,7 @@
 menu "IP: Netfilter Configuration"
 	depends on INET && NETFILTER
 
+# connection tracking, helpers and protocols
 config IP_NF_CONNTRACK
 	tristate "Connection tracking (required for masq/NAT)"
 	---help---
@@ -19,6 +20,28 @@ config IP_NF_CONNTRACK
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config IP_NF_CT_ACCT
+	bool "Connection tracking flow accounting"
+	depends on IP_NF_CONNTRACK
+	help
+	  If this option is enabled, the connection tracking code will
+	  keep per-flow packet and byte counters.
+
+	  Those counters can be used for flow-based accounting or the
+	  `connbytes' match.
+
+	  If unsure, say `N'.
+
+config IP_NF_CT_PROTO_SCTP
+	tristate  'SCTP protocol connection tracking support (EXPERIMENTAL)'
+	depends on IP_NF_CONNTRACK && EXPERIMENTAL
+	help
+	  With this option enabled, the connection tracking code will
+	  be able to do state tracking on SCTP connections.
+
+	  If you want to compile it as a module, say M here and read
+	  Documentation/modules.txt.  If unsure, say `N'.
+
 config IP_NF_FTP
 	tristate "FTP protocol support"
 	depends on IP_NF_CONNTRACK
@@ -86,7 +109,7 @@ config IP_NF_IPTABLES
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
-# The simple matches.
+# The matches.
 config IP_NF_MATCH_LIMIT
 	tristate "limit match support"
 	depends on IP_NF_IPTABLES
@@ -274,7 +297,52 @@ config IP_NF_MATCH_PHYSDEV
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
-# The targets
+config IP_NF_MATCH_ADDRTYPE
+	tristate  'address type match support'
+	depends on IP_NF_IPTABLES
+	help
+	  This option allows you to match what routing thinks of an address,
+	  eg. UNICAST, LOCAL, BROADCAST, ...
+	
+	  If you want to compile it as a module, say M here and read
+	  Documentation/modules.txt.  If unsure, say `N'.
+
+config IP_NF_MATCH_REALM
+	tristate  'realm match support'
+	depends on IP_NF_IPTABLES
+	select NET_CLS_ROUTE
+	help
+	  This option adds a `realm' match, which allows you to use the realm
+	  key from the routing subsytem inside iptables.
+	
+	  This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option 
+	  in tc world.
+	
+	  If you want to compile it as a module, say M here and read
+	  Documentation/modules.txt.  If unsure, say `N'.
+
+config IP_NF_MATCH_SCTP
+	tristate  'SCTP protocol match support'
+	depends on IP_NF_IPTABLES
+	help
+	  With this option enabled, you will be able to use the iptables
+	  `sctp' match in order to match on SCTP source/destination ports
+	  and SCTP chunk types.
+
+	  If you want to compile it as a module, say M here and read
+	  Documentation/modules.txt.  If unsure, say `N'.
+
+config IP_NF_MATCH_COMMENT
+	tristate  'comment match support'
+	depends on IP_NF_IPTABLES
+	help
+	  This option adds a `comment' dummy-match, which allows you to put
+	  comments in your iptables ruleset.
+
+	  If you want to compile it as a module, say M here and read
+	  Documentation/modules.txt.  If unsure, say `N'.
+
+# `filter', generic and specific targets
 config IP_NF_FILTER
 	tristate "Packet filtering"
 	depends on IP_NF_IPTABLES
@@ -295,6 +363,56 @@ config IP_NF_TARGET_REJECT
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config IP_NF_TARGET_LOG
+	tristate "LOG target support"
+	depends on IP_NF_IPTABLES
+	help
+	  This option adds a `LOG' target, which allows you to create rules in
+	  any iptables table which records the packet header to the syslog.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
+config IP_NF_TARGET_ULOG
+	tristate "ULOG target support"
+	depends on IP_NF_IPTABLES
+	---help---
+	  This option adds a `ULOG' target, which allows you to create rules in
+	  any iptables table. The packet is passed to a userspace logging
+	  daemon using netlink multicast sockets; unlike the LOG target
+	  which can only be viewed through syslog.
+
+	  The apropriate userspace logging daemon (ulogd) may be obtained from
+	  <http://www.gnumonks.org/projects/ulogd/>
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
+config IP_NF_TARGET_TCPMSS
+	tristate "TCPMSS target support"
+	depends on IP_NF_IPTABLES
+	---help---
+	  This option adds a `TCPMSS' target, which allows you to alter the
+	  MSS value of TCP SYN packets, to control the maximum size for that
+	  connection (usually limiting it to your outgoing interface's MTU
+	  minus 40).
+
+	  This is used to overcome criminally braindead ISPs or servers which
+	  block ICMP Fragmentation Needed packets.  The symptoms of this
+	  problem are that everything works fine from your Linux
+	  firewall/router, but machines behind it can never exchange large
+	  packets:
+	  	1) Web browsers connect, then hang with no data received.
+	  	2) Small mail works fine, but large emails hang.
+	  	3) ssh works fine, but scp hangs after initial handshaking.
+
+	  Workaround: activate this option and add a rule to your firewall
+	  configuration like:
+
+	  iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
+	  		 -j TCPMSS --clamp-mss-to-pmtu
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
+# NAT + specific targets
 config IP_NF_NAT
 	tristate "Full NAT"
 	depends on IP_NF_IPTABLES && IP_NF_CONNTRACK
@@ -408,6 +526,7 @@ config IP_NF_NAT_AMANDA
 	default IP_NF_NAT if IP_NF_AMANDA=y
 	default m if IP_NF_AMANDA=m
 
+# mangle + specific targets
 config IP_NF_MANGLE
 	tristate "Packet mangling"
 	depends on IP_NF_IPTABLES
@@ -478,55 +597,34 @@ config IP_NF_TARGET_CLASSIFY
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
-config IP_NF_TARGET_LOG
-	tristate "LOG target support"
+# raw + specific targets
+config IP_NF_RAW
+	tristate  'raw table support (required for NOTRACK/TRACE)'
 	depends on IP_NF_IPTABLES
 	help
-	  This option adds a `LOG' target, which allows you to create rules in
-	  any iptables table which records the packet header to the syslog.
-
-	  To compile it as a module, choose M here.  If unsure, say N.
-
-config IP_NF_TARGET_ULOG
-	tristate "ULOG target support"
-	depends on IP_NF_IPTABLES
-	---help---
-	  This option adds a `ULOG' target, which allows you to create rules in
-	  any iptables table. The packet is passed to a userspace logging
-	  daemon using netlink multicast sockets; unlike the LOG target
-	  which can only be viewed through syslog.
-
-	  The apropriate userspace logging daemon (ulogd) may be obtained from
-	  <http://www.gnumonks.org/projects/ulogd/>
-
-	  To compile it as a module, choose M here.  If unsure, say N.
-
-config IP_NF_TARGET_TCPMSS
-	tristate "TCPMSS target support"
-	depends on IP_NF_IPTABLES
-	---help---
-	  This option adds a `TCPMSS' target, which allows you to alter the
-	  MSS value of TCP SYN packets, to control the maximum size for that
-	  connection (usually limiting it to your outgoing interface's MTU
-	  minus 40).
-
-	  This is used to overcome criminally braindead ISPs or servers which
-	  block ICMP Fragmentation Needed packets.  The symptoms of this
-	  problem are that everything works fine from your Linux
-	  firewall/router, but machines behind it can never exchange large
-	  packets:
-	  	1) Web browsers connect, then hang with no data received.
-	  	2) Small mail works fine, but large emails hang.
-	  	3) ssh works fine, but scp hangs after initial handshaking.
-
-	  Workaround: activate this option and add a rule to your firewall
-	  configuration like:
+	  This option adds a `raw' table to iptables. This table is the very
+	  first in the netfilter framework and hooks in at the PREROUTING
+	  and OUTPUT chains.
+	
+	  If you want to compile it as a module, say M here and read
+	  <file:Documentation/modules.txt>.  If unsure, say `N'.
+	  help
 
-	  iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-	  		 -j TCPMSS --clamp-mss-to-pmtu
+config IP_NF_TARGET_NOTRACK
+	tristate  'NOTRACK target support'
+	depends on IP_NF_RAW
+	depends on IP_NF_CONNTRACK
+	help
+	  The NOTRACK target allows a select rule to specify
+	  which packets *not* to enter the conntrack/NAT
+	  subsystem with all the consequences (no ICMP error tracking,
+	  no protocol helpers for the selected packets).
+	
+	  If you want to compile it as a module, say M here and read
+	  <file:Documentation/modules.txt>.  If unsure, say `N'.
 
-	  To compile it as a module, choose M here.  If unsure, say N.
 
+# ARP tables
 config IP_NF_ARPTABLES
 	tristate "ARP tables support"
 	help
@@ -579,54 +677,5 @@ config IP_NF_COMPAT_IPFWADM
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
-config IP_NF_TARGET_NOTRACK
-	tristate  'NOTRACK target support'
-	depends on IP_NF_RAW
-	depends on IP_NF_CONNTRACK
-	help
-	  The NOTRACK target allows a select rule to specify
-	  which packets *not* to enter the conntrack/NAT
-	  subsystem with all the consequences (no ICMP error tracking,
-	  no protocol helpers for the selected packets).
-	
-	  If you want to compile it as a module, say M here and read
-	  <file:Documentation/modules.txt>.  If unsure, say `N'.
-
-config IP_NF_RAW
-	tristate  'raw table support (required for NOTRACK/TRACE)'
-	depends on IP_NF_IPTABLES
-	help
-	  This option adds a `raw' table to iptables. This table is the very
-	  first in the netfilter framework and hooks in at the PREROUTING
-	  and OUTPUT chains.
-	
-	  If you want to compile it as a module, say M here and read
-	  <file:Documentation/modules.txt>.  If unsure, say `N'.
-	  help
-
-config IP_NF_MATCH_ADDRTYPE
-	tristate  'address type match support'
-	depends on IP_NF_IPTABLES
-	help
-	  This option allows you to match what routing thinks of an address,
-	  eg. UNICAST, LOCAL, BROADCAST, ...
-	
-	  If you want to compile it as a module, say M here and read
-	  Documentation/modules.txt.  If unsure, say `N'.
-
-config IP_NF_MATCH_REALM
-	tristate  'realm match support'
-	depends on IP_NF_IPTABLES
-	select NET_CLS_ROUTE
-	help
-	  This option adds a `realm' match, which allows you to use the realm
-	  key from the routing subsytem inside iptables.
-	
-	  This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option 
-	  in tc world.
-	
-	  If you want to compile it as a module, say M here and read
-	  Documentation/modules.txt.  If unsure, say `N'.
-
 endmenu
 
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index bdb23fde1..caee96d6f 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -19,6 +19,9 @@ ipchains-objs		:= $(ip_nf_compat-objs) ipchains_core.o
 # connection tracking
 obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
 
+# SCTP protocol connection tracking
+obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
+
 # connection tracking helpers
 obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
 obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
@@ -43,31 +46,27 @@ obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
 # matches
 obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
 obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
+obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
 obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
 obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
 obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
-
 obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
 obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
-
 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
-
 obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
 obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o
 obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o
-
 obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
-
 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
 obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
 obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
-
 obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
+obj-$(CONFIG_IP_NF_MATCH_COMMENT) += ipt_comment.o
 
 # targets
 obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 65230e5e1..f2b3e7e5b 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -106,7 +106,7 @@ static inline int arp_packet_match(const struct arphdr *arphdr,
 {
 	char *arpptr = (char *)(arphdr + 1);
 	char *src_devaddr, *tgt_devaddr;
-	u32 *src_ipaddr, *tgt_ipaddr;
+	u32 src_ipaddr, tgt_ipaddr;
 	int i, ret;
 
 #define FWINV(bool,invflg) ((bool) ^ !!(arpinfo->invflags & invflg))
@@ -145,11 +145,11 @@ static inline int arp_packet_match(const struct arphdr *arphdr,
 
 	src_devaddr = arpptr;
 	arpptr += dev->addr_len;
-	src_ipaddr = (u32 *) arpptr;
+	memcpy(&src_ipaddr, arpptr, sizeof(u32));
 	arpptr += sizeof(u32);
 	tgt_devaddr = arpptr;
 	arpptr += dev->addr_len;
-	tgt_ipaddr = (u32 *) arpptr;
+	memcpy(&tgt_ipaddr, arpptr, sizeof(u32));
 
 	if (FWINV(arp_devaddr_compare(&arpinfo->src_devaddr, src_devaddr, dev->addr_len),
 		  ARPT_INV_SRCDEVADDR) ||
@@ -160,19 +160,19 @@ static inline int arp_packet_match(const struct arphdr *arphdr,
 		return 0;
 	}
 
-	if (FWINV(((*src_ipaddr) & arpinfo->smsk.s_addr) != arpinfo->src.s_addr,
+	if (FWINV((src_ipaddr & arpinfo->smsk.s_addr) != arpinfo->src.s_addr,
 		  ARPT_INV_SRCIP) ||
-	    FWINV((((*tgt_ipaddr) & arpinfo->tmsk.s_addr) != arpinfo->tgt.s_addr),
+	    FWINV(((tgt_ipaddr & arpinfo->tmsk.s_addr) != arpinfo->tgt.s_addr),
 		  ARPT_INV_TGTIP)) {
 		dprintf("Source or target IP address mismatch.\n");
 
 		dprintf("SRC: %u.%u.%u.%u. Mask: %u.%u.%u.%u. Target: %u.%u.%u.%u.%s\n",
-			NIPQUAD(*src_ipaddr),
+			NIPQUAD(src_ipaddr),
 			NIPQUAD(arpinfo->smsk.s_addr),
 			NIPQUAD(arpinfo->src.s_addr),
 			arpinfo->invflags & ARPT_INV_SRCIP ? " (INV)" : "");
 		dprintf("TGT: %u.%u.%u.%u Mask: %u.%u.%u.%u Target: %u.%u.%u.%u.%s\n",
-			NIPQUAD(*tgt_ipaddr),
+			NIPQUAD(tgt_ipaddr),
 			NIPQUAD(arpinfo->tmsk.s_addr),
 			NIPQUAD(arpinfo->tgt.s_addr),
 			arpinfo->invflags & ARPT_INV_TGTIP ? " (INV)" : "");
@@ -193,7 +193,10 @@ static inline int arp_packet_match(const struct arphdr *arphdr,
 	}
 
 	for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
-		ret |= (((const unsigned long *)outdev)[i]
+		unsigned long odev;
+		memcpy(&odev, outdev + i*sizeof(unsigned long),
+		       sizeof(unsigned long));
+		ret |= (odev
 			^ ((const unsigned long *)arpinfo->outiface)[i])
 			& ((const unsigned long *)arpinfo->outiface_mask)[i];
 	}
diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c
index 4e8f4d83b..a54ef782f 100644
--- a/net/ipv4/netfilter/ip_conntrack_amanda.c
+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/netfilter.h>
 #include <linux/ip.h>
+#include <linux/moduleparam.h>
 #include <net/checksum.h>
 #include <net/udp.h>
 
@@ -34,7 +35,7 @@ static unsigned int master_timeout = 300;
 MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
 MODULE_DESCRIPTION("Amanda connection tracking module");
 MODULE_LICENSE("GPL");
-MODULE_PARM(master_timeout, "i");
+module_param(master_timeout, int, 0600);
 MODULE_PARM_DESC(master_timeout, "timeout for the master connection");
 
 static char *conns[] = { "DATA ", "MESG ", "INDEX " };
@@ -48,7 +49,7 @@ static int help(struct sk_buff *skb,
 {
 	struct ip_conntrack_expect *exp;
 	struct ip_ct_amanda_expect *exp_amanda_info;
-	char *data, *data_limit, *tmp;
+	char *amp, *data, *data_limit, *tmp;
 	unsigned int dataoff, i;
 	u_int16_t port, len;
 
@@ -58,7 +59,7 @@ static int help(struct sk_buff *skb,
 
 	/* increase the UDP timeout of the master connection as replies from
 	 * Amanda clients to the server can be quite delayed */
-	ip_ct_refresh(ct, master_timeout * HZ);
+	ip_ct_refresh_acct(ct, ctinfo, NULL, master_timeout * HZ);
 
 	/* No data? */
 	dataoff = skb->nh.iph->ihl*4 + sizeof(struct udphdr);
@@ -69,9 +70,11 @@ static int help(struct sk_buff *skb,
 	}
 
 	LOCK_BH(&amanda_buffer_lock);
-	skb_copy_bits(skb, dataoff, amanda_buffer, skb->len - dataoff);
-	data = amanda_buffer;
-	data_limit = amanda_buffer + skb->len - dataoff;
+	amp = skb_header_pointer(skb, dataoff,
+				 skb->len - dataoff, amanda_buffer);
+	BUG_ON(amp == NULL);
+	data = amp;
+	data_limit = amp + skb->len - dataoff;
 	*data_limit = '\0';
 
 	/* Search for the CONNECT string */
@@ -107,7 +110,7 @@ static int help(struct sk_buff *skb,
 		exp->mask.dst.u.tcp.port = 0xFFFF;
 
 		exp_amanda_info = &exp->help.exp_amanda_info;
-		exp_amanda_info->offset = tmp - amanda_buffer;
+		exp_amanda_info->offset = tmp - amp;
 		exp_amanda_info->port   = port;
 		exp_amanda_info->len    = len;
 
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index 00a89f4f8..67caf5f43 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -34,8 +34,9 @@
 #include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/jhash.h>
-/* For ERR_PTR().  Yeah, I know... --RR */
-#include <linux/fs.h>
+#include <linux/err.h>
+#include <linux/percpu.h>
+#include <linux/moduleparam.h>
 
 /* This rwlock protects the main hash table, protocol/helper/expected
    registrations, conntrack timers*/
@@ -59,56 +60,29 @@
 DECLARE_RWLOCK(ip_conntrack_lock);
 DECLARE_RWLOCK(ip_conntrack_expect_tuple_lock);
 
+/* ip_conntrack_standalone needs this */
+atomic_t ip_conntrack_count = ATOMIC_INIT(0);
+EXPORT_SYMBOL(ip_conntrack_count);
+
 void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack) = NULL;
 LIST_HEAD(ip_conntrack_expect_list);
-LIST_HEAD(protocol_list);
+struct ip_conntrack_protocol *ip_ct_protos[MAX_IP_CT_PROTO];
 static LIST_HEAD(helpers);
 unsigned int ip_conntrack_htable_size = 0;
 int ip_conntrack_max;
-static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
 struct list_head *ip_conntrack_hash;
 static kmem_cache_t *ip_conntrack_cachep;
+static kmem_cache_t *ip_conntrack_expect_cachep;
 struct ip_conntrack ip_conntrack_untracked;
+unsigned int ip_ct_log_invalid;
 
-extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
-
-static inline int proto_cmpfn(const struct ip_conntrack_protocol *curr,
-			      u_int8_t protocol)
-{
-	return protocol == curr->proto;
-}
-
-struct ip_conntrack_protocol *__ip_ct_find_proto(u_int8_t protocol)
-{
-	struct ip_conntrack_protocol *p;
-
-	MUST_BE_READ_LOCKED(&ip_conntrack_lock);
-	p = LIST_FIND(&protocol_list, proto_cmpfn,
-		      struct ip_conntrack_protocol *, protocol);
-	if (!p)
-		p = &ip_conntrack_generic_protocol;
-
-	return p;
-}
-
-struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol)
-{
-	struct ip_conntrack_protocol *p;
-
-	READ_LOCK(&ip_conntrack_lock);
-	p = __ip_ct_find_proto(protocol);
-	READ_UNLOCK(&ip_conntrack_lock);
-	return p;
-}
+DEFINE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat);
 
 inline void 
 ip_conntrack_put(struct ip_conntrack *ct)
 {
 	IP_NF_ASSERT(ct);
-	IP_NF_ASSERT(ct->infos[0].master);
-	/* nf_conntrack_put wants to go via an info struct, so feed it
-           one at random. */
-	nf_conntrack_put(&ct->infos[0]);
+	nf_conntrack_put(&ct->ct_general);
 }
 
 static int ip_conntrack_hash_rnd_initted;
@@ -127,11 +101,11 @@ hash_conntrack(const struct ip_conntrack_tuple *tuple)
 }
 
 int
-get_tuple(const struct iphdr *iph,
-	  const struct sk_buff *skb,
-	  unsigned int dataoff,
-	  struct ip_conntrack_tuple *tuple,
-	  const struct ip_conntrack_protocol *protocol)
+ip_ct_get_tuple(const struct iphdr *iph,
+		const struct sk_buff *skb,
+		unsigned int dataoff,
+		struct ip_conntrack_tuple *tuple,
+		const struct ip_conntrack_protocol *protocol)
 {
 	/* Never happen */
 	if (iph->frag_off & htons(IP_OFFSET)) {
@@ -147,10 +121,10 @@ get_tuple(const struct iphdr *iph,
 	return protocol->pkt_to_tuple(skb, dataoff, tuple);
 }
 
-static int
-invert_tuple(struct ip_conntrack_tuple *inverse,
-	     const struct ip_conntrack_tuple *orig,
-	     const struct ip_conntrack_protocol *protocol)
+int
+ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse,
+		   const struct ip_conntrack_tuple *orig,
+		   const struct ip_conntrack_protocol *protocol)
 {
 	inverse->src.ip = orig->dst.ip;
 	inverse->dst.ip = orig->src.ip;
@@ -177,7 +151,8 @@ destroy_expect(struct ip_conntrack_expect *exp)
 	IP_NF_ASSERT(atomic_read(&exp->use) == 0);
 	IP_NF_ASSERT(!timer_pending(&exp->timeout));
 
-	kfree(exp);
+	kmem_cache_free(ip_conntrack_expect_cachep, exp);
+	CONNTRACK_STAT_INC(expect_delete);
 }
 
 inline void ip_conntrack_expect_put(struct ip_conntrack_expect *exp)
@@ -336,7 +311,7 @@ destroy_conntrack(struct nf_conntrack *nfct)
 			list_del(&ct->master->expected_list);
 			master = ct->master->expectant;
 		}
-		kfree(ct->master);
+		kmem_cache_free(ip_conntrack_expect_cachep, ct->master);
 	}
 	WRITE_UNLOCK(&ip_conntrack_lock);
 
@@ -346,12 +321,15 @@ destroy_conntrack(struct nf_conntrack *nfct)
 	DEBUGP("destroy_conntrack: returning ct=%p to slab\n", ct);
 	kmem_cache_free(ip_conntrack_cachep, ct);
 	atomic_dec(&ip_conntrack_count);
+	CONNTRACK_STAT_INC(delete);
 }
 
 static void death_by_timeout(unsigned long ul_conntrack)
 {
 	struct ip_conntrack *ct = (void *)ul_conntrack;
 
+	CONNTRACK_STAT_INC(delete_list);
+
 	WRITE_LOCK(&ip_conntrack_lock);
 	clean_from_lists(ct);
 	WRITE_UNLOCK(&ip_conntrack_lock);
@@ -374,13 +352,19 @@ __ip_conntrack_find(const struct ip_conntrack_tuple *tuple,
 {
 	struct ip_conntrack_tuple_hash *h;
 	unsigned int hash = hash_conntrack(tuple);
+	/* use per_cpu() to avoid multiple calls to smp_processor_id() */
+	unsigned int cpu = smp_processor_id();
 
 	MUST_BE_READ_LOCKED(&ip_conntrack_lock);
-	h = LIST_FIND(&ip_conntrack_hash[hash],
-		      conntrack_tuple_cmp,
-		      struct ip_conntrack_tuple_hash *,
-		      tuple, ignored_conntrack);
-	return h;
+	list_for_each_entry(h, &ip_conntrack_hash[hash], list) {
+		if (conntrack_tuple_cmp(h, tuple, ignored_conntrack)) {
+			per_cpu(ip_conntrack_stat, cpu).found++;
+			return h;
+		}
+		per_cpu(ip_conntrack_stat, cpu).searched++;
+	}
+
+	return NULL;
 }
 
 /* Find a connection corresponding to a tuple. */
@@ -399,36 +383,15 @@ ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
 	return h;
 }
 
-static inline struct ip_conntrack *
-__ip_conntrack_get(struct nf_ct_info *nfct, enum ip_conntrack_info *ctinfo)
-{
-	struct ip_conntrack *ct
-		= (struct ip_conntrack *)nfct->master;
-
-	/* ctinfo is the index of the nfct inside the conntrack */
-	*ctinfo = nfct - ct->infos;
-	IP_NF_ASSERT(*ctinfo >= 0 && *ctinfo < IP_CT_NUMBER);
-	return ct;
-}
-
-/* Return conntrack and conntrack_info given skb->nfct->master */
-struct ip_conntrack *
-ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
-{
-	if (skb->nfct) 
-		return __ip_conntrack_get(skb->nfct, ctinfo);
-	return NULL;
-}
-
-/* Confirm a connection given skb->nfct; places it in hash table */
+/* Confirm a connection given skb; places it in hash table */
 int
-__ip_conntrack_confirm(struct nf_ct_info *nfct)
+__ip_conntrack_confirm(struct sk_buff *skb)
 {
 	unsigned int hash, repl_hash;
 	struct ip_conntrack *ct;
 	enum ip_conntrack_info ctinfo;
 
-	ct = __ip_conntrack_get(nfct, &ctinfo);
+	ct = ip_conntrack_get(skb, &ctinfo);
 
 	/* ipt_REJECT uses ip_conntrack_attach to attach related
 	   ICMP/TCP RST packets in other direction.  Actual packet
@@ -474,10 +437,12 @@ __ip_conntrack_confirm(struct nf_ct_info *nfct)
 		atomic_inc(&ct->ct_general.use);
 		set_bit(IPS_CONFIRMED_BIT, &ct->status);
 		WRITE_UNLOCK(&ip_conntrack_lock);
+		CONNTRACK_STAT_INC(insert);
 		return NF_ACCEPT;
 	}
 
 	WRITE_UNLOCK(&ip_conntrack_lock);
+	CONNTRACK_STAT_INC(insert_failed);
 	return NF_DROP;
 }
 
@@ -496,83 +461,6 @@ ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple,
 	return h != NULL;
 }
 
-/* Returns conntrack if it dealt with ICMP, and filled in skb fields */
-struct ip_conntrack *
-icmp_error_track(struct sk_buff *skb,
-		 enum ip_conntrack_info *ctinfo,
-		 unsigned int hooknum)
-{
-	struct ip_conntrack_tuple innertuple, origtuple;
-	struct {
-		struct icmphdr icmp;
-		struct iphdr ip;
-	} inside;
-	struct ip_conntrack_protocol *innerproto;
-	struct ip_conntrack_tuple_hash *h;
-	int dataoff;
-
-	IP_NF_ASSERT(skb->nfct == NULL);
-
-	/* Not enough header? */
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &inside, sizeof(inside))!=0)
-		return NULL;
-
-	if (inside.icmp.type != ICMP_DEST_UNREACH
-	    && inside.icmp.type != ICMP_SOURCE_QUENCH
-	    && inside.icmp.type != ICMP_TIME_EXCEEDED
-	    && inside.icmp.type != ICMP_PARAMETERPROB
-	    && inside.icmp.type != ICMP_REDIRECT)
-		return NULL;
-
-	/* Ignore ICMP's containing fragments (shouldn't happen) */
-	if (inside.ip.frag_off & htons(IP_OFFSET)) {
-		DEBUGP("icmp_error_track: fragment of proto %u\n",
-		       inside.ip.protocol);
-		return NULL;
-	}
-
-	innerproto = ip_ct_find_proto(inside.ip.protocol);
-	dataoff = skb->nh.iph->ihl*4 + sizeof(inside.icmp) + inside.ip.ihl*4;
-	/* Are they talking about one of our connections? */
-	if (!get_tuple(&inside.ip, skb, dataoff, &origtuple, innerproto)) {
-		DEBUGP("icmp_error: ! get_tuple p=%u", inside.ip.protocol);
-		return NULL;
-	}
-
-	/* Ordinarily, we'd expect the inverted tupleproto, but it's
-	   been preserved inside the ICMP. */
-	if (!invert_tuple(&innertuple, &origtuple, innerproto)) {
-		DEBUGP("icmp_error_track: Can't invert tuple\n");
-		return NULL;
-	}
-
-	*ctinfo = IP_CT_RELATED;
-
-	h = ip_conntrack_find_get(&innertuple, NULL);
-	if (!h) {
-		/* Locally generated ICMPs will match inverted if they
-		   haven't been SNAT'ed yet */
-		/* FIXME: NAT code has to handle half-done double NAT --RR */
-		if (hooknum == NF_IP_LOCAL_OUT)
-			h = ip_conntrack_find_get(&origtuple, NULL);
-
-		if (!h) {
-			DEBUGP("icmp_error_track: no match\n");
-			return NULL;
-		}
-		/* Reverse direction from that found */
-		if (DIRECTION(h) != IP_CT_DIR_REPLY)
-			*ctinfo += IP_CT_IS_REPLY;
-	} else {
-		if (DIRECTION(h) == IP_CT_DIR_REPLY)
-			*ctinfo += IP_CT_IS_REPLY;
-	}
-
-	/* Update skb to refer to this connection */
-	skb->nfct = &h->ctrack->infos[*ctinfo];
-	return h->ctrack;
-}
-
 /* There's a small race here where we may free a just-assured
    connection.  Too bad: we're in trouble anyway. */
 static inline int unreplied(const struct ip_conntrack_tuple_hash *i)
@@ -598,6 +486,7 @@ static int early_drop(struct list_head *chain)
 	if (del_timer(&h->ctrack->timeout)) {
 		death_by_timeout((unsigned long)h->ctrack);
 		dropped = 1;
+		CONNTRACK_STAT_INC(early_drop);
 	}
 	ip_conntrack_put(h->ctrack);
 	return dropped;
@@ -627,8 +516,6 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
 	struct ip_conntrack_tuple repl_tuple;
 	size_t hash;
 	struct ip_conntrack_expect *expected;
-	int i;
-	static unsigned int drop_next;
 
 	if (!ip_conntrack_hash_rnd_initted) {
 		get_random_bytes(&ip_conntrack_hash_rnd, 4);
@@ -637,15 +524,10 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
 
 	hash = hash_conntrack(tuple);
 
-	if (ip_conntrack_max &&
-	    atomic_read(&ip_conntrack_count) >= ip_conntrack_max) {
-		/* Try dropping from random chain, or else from the
-                   chain about to put into (in case they're trying to
-                   bomb one hash chain). */
-		unsigned int next = (drop_next++)%ip_conntrack_htable_size;
-
-		if (!early_drop(&ip_conntrack_hash[next])
-		    && !early_drop(&ip_conntrack_hash[hash])) {
+	if (ip_conntrack_max
+	    && atomic_read(&ip_conntrack_count) >= ip_conntrack_max) {
+		/* Try dropping from this hash chain. */
+		if (!early_drop(&ip_conntrack_hash[hash])) {
 			if (net_ratelimit())
 				printk(KERN_WARNING
 				       "ip_conntrack: table full, dropping"
@@ -654,7 +536,7 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
 		}
 	}
 
-	if (!invert_tuple(&repl_tuple, tuple, protocol)) {
+	if (!ip_ct_invert_tuple(&repl_tuple, tuple, protocol)) {
 		DEBUGP("Can't invert tuple.\n");
 		return NULL;
 	}
@@ -672,9 +554,6 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
 	conntrack->tuplehash[IP_CT_DIR_ORIGINAL].ctrack = conntrack;
 	conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = repl_tuple;
 	conntrack->tuplehash[IP_CT_DIR_REPLY].ctrack = conntrack;
-	for (i=0; i < IP_CT_NUMBER; i++)
-		conntrack->infos[i].master = &conntrack->ct_general;
-
 	if (!protocol->new(conntrack, skb)) {
 		kmem_cache_free(ip_conntrack_cachep, conntrack);
 		return NULL;
@@ -693,41 +572,53 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
 			     struct ip_conntrack_expect *, tuple);
 	READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
 
-	/* If master is not in hash table yet (ie. packet hasn't left
-	   this machine yet), how can other end know about expected?
-	   Hence these are not the droids you are looking for (if
-	   master ct never got confirmed, we'd hold a reference to it
-	   and weird things would happen to future packets). */
-	if (expected && !is_confirmed(expected->expectant))
-		expected = NULL;
-
-	/* Look up the conntrack helper for master connections only */
-	if (!expected)
-		conntrack->helper = ip_ct_find_helper(&repl_tuple);
+	if (expected) {
+		/* If master is not in hash table yet (ie. packet hasn't left
+		   this machine yet), how can other end know about expected?
+		   Hence these are not the droids you are looking for (if
+		   master ct never got confirmed, we'd hold a reference to it
+		   and weird things would happen to future packets). */
+		if (!is_confirmed(expected->expectant)) {
+			conntrack->helper = ip_ct_find_helper(&repl_tuple);
+			goto end;
+		}
 
-	/* If the expectation is dying, then this is a loser. */
-	if (expected
-	    && expected->expectant->helper->timeout
-	    && ! del_timer(&expected->timeout))
-		expected = NULL;
+		/* Expectation is dying... */
+		if (expected->expectant->helper->timeout
+		    && !del_timer(&expected->timeout))
+			goto end;	
 
-	if (expected) {
 		DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
 			conntrack, expected);
 		/* Welcome, Mr. Bond.  We've been expecting you... */
+		IP_NF_ASSERT(expected->expectant);
 		__set_bit(IPS_EXPECTED_BIT, &conntrack->status);
 		conntrack->master = expected;
 		expected->sibling = conntrack;
 		LIST_DELETE(&ip_conntrack_expect_list, expected);
 		expected->expectant->expecting--;
-		nf_conntrack_get(&master_ct(conntrack)->infos[0]);
+		nf_conntrack_get(&master_ct(conntrack)->ct_general);
+
+		/* this is a braindead... --pablo */
+		atomic_inc(&ip_conntrack_count);
+		WRITE_UNLOCK(&ip_conntrack_lock);
+
+		if (expected->expectfn)
+			expected->expectfn(conntrack);
+	
+		CONNTRACK_STAT_INC(expect_new);
+
+		goto ret;
+	} else  {
+		conntrack->helper = ip_ct_find_helper(&repl_tuple);
+
+		CONNTRACK_STAT_INC(new);
 	}
-	atomic_inc(&ip_conntrack_count);
+
+end:	atomic_inc(&ip_conntrack_count);
 	WRITE_UNLOCK(&ip_conntrack_lock);
 
-	if (expected && expected->expectfn)
-		expected->expectfn(conntrack);
-	return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
+ret:	return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
 }
 
 /* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
@@ -743,7 +634,8 @@ resolve_normal_ct(struct sk_buff *skb,
 
 	IP_NF_ASSERT((skb->nh.iph->frag_off & htons(IP_OFFSET)) == 0);
 
-	if (!get_tuple(skb->nh.iph, skb, skb->nh.iph->ihl*4, &tuple, proto))
+	if (!ip_ct_get_tuple(skb->nh.iph, skb, skb->nh.iph->ihl*4, 
+				&tuple,proto))
 		return NULL;
 
 	/* look for tuple match */
@@ -778,7 +670,8 @@ resolve_normal_ct(struct sk_buff *skb,
 		}
 		*set_reply = 0;
 	}
-	skb->nfct = &h->ctrack->infos[*ctinfo];
+	skb->nfct = &h->ctrack->ct_general;
+	skb->nfctinfo = *ctinfo;
 	return h->ctrack;
 }
 
@@ -795,6 +688,12 @@ unsigned int ip_conntrack_in(unsigned int hooknum,
 	int set_reply;
 	int ret;
 
+	/* Previously seen (loopback or untracked)?  Ignore. */
+	if ((*pskb)->nfct) {
+		CONNTRACK_STAT_INC(ignore);
+		return NF_ACCEPT;
+	}
+
 	/* Never happen */
 	if ((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) {
 		if (net_ratelimit()) {
@@ -822,39 +721,47 @@ unsigned int ip_conntrack_in(unsigned int hooknum,
 	}
 #endif
 
-	/* Previously seen (loopback or untracked)?  Ignore. */
-	if ((*pskb)->nfct)
-		return NF_ACCEPT;
-
 	proto = ip_ct_find_proto((*pskb)->nh.iph->protocol);
 
-	/* It may be an icmp error... */
-	if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP 
-	    && icmp_error_track(*pskb, &ctinfo, hooknum))
-		return NF_ACCEPT;
+	/* It may be an special packet, error, unclean...
+	 * inverse of the return code tells to the netfilter
+	 * core what to do with the packet. */
+	if (proto->error != NULL 
+	    && (ret = proto->error(*pskb, &ctinfo, hooknum)) <= 0) {
+		CONNTRACK_STAT_INC(error);
+		CONNTRACK_STAT_INC(invalid);
+		return -ret;
+	}
 
-	if (!(ct = resolve_normal_ct(*pskb, proto,&set_reply,hooknum,&ctinfo)))
+	if (!(ct = resolve_normal_ct(*pskb, proto,&set_reply,hooknum,&ctinfo))) {
 		/* Not valid part of a connection */
+		CONNTRACK_STAT_INC(invalid);
 		return NF_ACCEPT;
+	}
 
-	if (IS_ERR(ct))
+	if (IS_ERR(ct)) {
 		/* Too stressed to deal. */
+		CONNTRACK_STAT_INC(drop);
 		return NF_DROP;
+	}
 
 	IP_NF_ASSERT((*pskb)->nfct);
 
 	ret = proto->packet(ct, *pskb, ctinfo);
-	if (ret == -1) {
-		/* Invalid */
+	if (ret < 0) {
+		/* Invalid: inverse of the return code tells
+		 * the netfilter core what to do*/
 		nf_conntrack_put((*pskb)->nfct);
 		(*pskb)->nfct = NULL;
-		return NF_ACCEPT;
+		CONNTRACK_STAT_INC(invalid);
+		return -ret;
 	}
 
 	if (ret != NF_DROP && ct->helper) {
 		ret = ct->helper->help(*pskb, ct, ctinfo);
 		if (ret == -1) {
 			/* Invalid */
+			CONNTRACK_STAT_INC(invalid);
 			nf_conntrack_put((*pskb)->nfct);
 			(*pskb)->nfct = NULL;
 			return NF_ACCEPT;
@@ -869,7 +776,8 @@ unsigned int ip_conntrack_in(unsigned int hooknum,
 int invert_tuplepr(struct ip_conntrack_tuple *inverse,
 		   const struct ip_conntrack_tuple *orig)
 {
-	return invert_tuple(inverse, orig, ip_ct_find_proto(orig->dst.protonum));
+	return ip_ct_invert_tuple(inverse, orig, 
+				  ip_ct_find_proto(orig->dst.protonum));
 }
 
 static inline int resent_expect(const struct ip_conntrack_expect *i,
@@ -923,9 +831,8 @@ struct ip_conntrack_expect *
 ip_conntrack_expect_alloc(void)
 {
 	struct ip_conntrack_expect *new;
-	
-	new = (struct ip_conntrack_expect *)
-		kmalloc(sizeof(struct ip_conntrack_expect), GFP_ATOMIC);
+
+	new = kmem_cache_alloc(ip_conntrack_expect_cachep, GFP_ATOMIC);
 	if (!new) {
 		DEBUGP("expect_related: OOM allocating expect\n");
 		return NULL;
@@ -933,6 +840,7 @@ ip_conntrack_expect_alloc(void)
 
 	/* tuple_cmp compares whole union, we have to initialized cleanly */
 	memset(new, 0, sizeof(struct ip_conntrack_expect));
+	atomic_set(&new->use, 1);
 
 	return new;
 }
@@ -944,7 +852,6 @@ ip_conntrack_expect_insert(struct ip_conntrack_expect *new,
 	DEBUGP("new expectation %p of conntrack %p\n", new, related_to);
 	new->expectant = related_to;
 	new->sibling = NULL;
-	atomic_set(&new->use, 1);
 
 	/* add to expected list for this connection */
 	list_add_tail(&new->expected_list, &related_to->sibling_list);
@@ -997,7 +904,8 @@ int ip_conntrack_expect_related(struct ip_conntrack_expect *expect,
 		}
 
 		WRITE_UNLOCK(&ip_conntrack_lock);
-		kfree(expect);
+		/* This expectation is not inserted so no need to lock */
+		kmem_cache_free(ip_conntrack_expect_cachep, expect);
 		return -EEXIST;
 
 	} else if (related_to->helper->max_expected && 
@@ -1015,7 +923,7 @@ int ip_conntrack_expect_related(struct ip_conntrack_expect *expect,
 				       related_to->helper->name,
  		    	       	       NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
  		    	       	       NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
-			kfree(expect);
+			kmem_cache_free(ip_conntrack_expect_cachep, expect);
 			return -EPERM;
 		}
 		DEBUGP("ip_conntrack: max number of expected "
@@ -1049,7 +957,7 @@ int ip_conntrack_expect_related(struct ip_conntrack_expect *expect,
 		WRITE_UNLOCK(&ip_conntrack_lock);
 		DEBUGP("expect_related: busy!\n");
 
-		kfree(expect);
+		kmem_cache_free(ip_conntrack_expect_cachep, expect);
 		return -EBUSY;
 	}
 
@@ -1057,6 +965,8 @@ out:	ip_conntrack_expect_insert(expect, related_to);
 
 	WRITE_UNLOCK(&ip_conntrack_lock);
 
+	CONNTRACK_STAT_INC(expect_create);
+
 	return ret;
 }
 
@@ -1164,25 +1074,45 @@ void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
 	synchronize_net();
 }
 
-/* Refresh conntrack for this many jiffies. */
-void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies)
+static inline void ct_add_counters(struct ip_conntrack *ct,
+				   enum ip_conntrack_info ctinfo,
+				   const struct sk_buff *skb)
+{
+#ifdef CONFIG_IP_NF_CT_ACCT
+	if (skb) {
+		ct->counters[CTINFO2DIR(ctinfo)].packets++;
+		ct->counters[CTINFO2DIR(ctinfo)].bytes += 
+					ntohs(skb->nh.iph->tot_len);
+	}
+#endif
+}
+
+/* Refresh conntrack for this many jiffies and do accounting (if skb != NULL) */
+void ip_ct_refresh_acct(struct ip_conntrack *ct, 
+		        enum ip_conntrack_info ctinfo,
+			const struct sk_buff *skb,
+			unsigned long extra_jiffies)
 {
 	IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
 
 	/* If not in hash table, timer will not be active yet */
-	if (!is_confirmed(ct))
+	if (!is_confirmed(ct)) {
 		ct->timeout.expires = extra_jiffies;
-	else {
+		ct_add_counters(ct, ctinfo, skb);
+	} else {
 		WRITE_LOCK(&ip_conntrack_lock);
 		/* Need del_timer for race avoidance (may already be dying). */
 		if (del_timer(&ct->timeout)) {
 			ct->timeout.expires = jiffies + extra_jiffies;
 			add_timer(&ct->timeout);
 		}
+		ct_add_counters(ct, ctinfo, skb);
 		WRITE_UNLOCK(&ip_conntrack_lock);
 	}
 }
 
+int ip_ct_no_defrag;
+
 /* Returns new sk_buff, or NULL */
 struct sk_buff *
 ip_ct_gather_frags(struct sk_buff *skb)
@@ -1191,6 +1121,12 @@ ip_ct_gather_frags(struct sk_buff *skb)
 #ifdef CONFIG_NETFILTER_DEBUG
 	unsigned int olddebug = skb->nf_debug;
 #endif
+
+	if (unlikely(ip_ct_no_defrag)) {
+		kfree_skb(skb);
+		return NULL;
+	}
+
 	if (sk) {
 		sock_hold(sk);
 		skb_orphan(skb);
@@ -1221,23 +1157,23 @@ ip_ct_gather_frags(struct sk_buff *skb)
 }
 
 /* Used by ipt_REJECT. */
-static void ip_conntrack_attach(struct sk_buff *nskb, struct nf_ct_info *nfct)
+static void ip_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb)
 {
 	struct ip_conntrack *ct;
 	enum ip_conntrack_info ctinfo;
 
-	ct = __ip_conntrack_get(nfct, &ctinfo);
-
-	/* This ICMP is in reverse direction to the packet which
-           caused it */
+	/* This ICMP is in reverse direction to the packet which caused it */
+	ct = ip_conntrack_get(skb, &ctinfo);
+	
 	if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL)
 		ctinfo = IP_CT_RELATED + IP_CT_IS_REPLY;
 	else
 		ctinfo = IP_CT_RELATED;
 
-	/* Attach new skbuff, and increment count */
-	nskb->nfct = &ct->infos[ctinfo];
-	atomic_inc(&ct->ct_general.use);
+	/* Attach to new skbuff, and increment count */
+	nskb->nfct = &ct->ct_general;
+	nskb->nfctinfo = ctinfo;
+	nf_conntrack_get(nskb->nfct);
 }
 
 static inline int
@@ -1368,12 +1304,13 @@ void ip_conntrack_cleanup(void)
 	}
 
 	kmem_cache_destroy(ip_conntrack_cachep);
+	kmem_cache_destroy(ip_conntrack_expect_cachep);
 	vfree(ip_conntrack_hash);
 	nf_unregister_sockopt(&so_getorigdst);
 }
 
 static int hashsize;
-MODULE_PARM(hashsize, "i");
+module_param(hashsize, int, 0400);
 
 int __init ip_conntrack_init(void)
 {
@@ -1420,12 +1357,23 @@ int __init ip_conntrack_init(void)
 		printk(KERN_ERR "Unable to create ip_conntrack slab cache\n");
 		goto err_free_hash;
 	}
+
+	ip_conntrack_expect_cachep = kmem_cache_create("ip_conntrack_expect",
+					sizeof(struct ip_conntrack_expect),
+					0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+	if (!ip_conntrack_expect_cachep) {
+		printk(KERN_ERR "Unable to create ip_expect slab cache\n");
+		goto err_free_conntrack_slab;
+	}
+
 	/* Don't NEED lock here, but good form anyway. */
 	WRITE_LOCK(&ip_conntrack_lock);
+	for (i = 0; i < MAX_IP_CT_PROTO; i++)
+		ip_ct_protos[i] = &ip_conntrack_generic_protocol;
 	/* Sew in builtin protocols. */
-	list_append(&protocol_list, &ip_conntrack_protocol_tcp);
-	list_append(&protocol_list, &ip_conntrack_protocol_udp);
-	list_append(&protocol_list, &ip_conntrack_protocol_icmp);
+	ip_ct_protos[IPPROTO_TCP] = &ip_conntrack_protocol_tcp;
+	ip_ct_protos[IPPROTO_UDP] = &ip_conntrack_protocol_udp;
+	ip_ct_protos[IPPROTO_ICMP] = &ip_conntrack_protocol_icmp;
 	WRITE_UNLOCK(&ip_conntrack_lock);
 
 	for (i = 0; i < ip_conntrack_htable_size; i++)
@@ -1439,14 +1387,11 @@ int __init ip_conntrack_init(void)
 	atomic_set(&ip_conntrack_untracked.ct_general.use, 1);
 	/*  - and look it like as a confirmed connection */
 	set_bit(IPS_CONFIRMED_BIT, &ip_conntrack_untracked.status);
-	/*  - and prepare the ctinfo field for REJECT & NAT. */
-	ip_conntrack_untracked.infos[IP_CT_NEW].master =
-	ip_conntrack_untracked.infos[IP_CT_RELATED].master =
-	ip_conntrack_untracked.infos[IP_CT_RELATED + IP_CT_IS_REPLY].master = 
-			&ip_conntrack_untracked.ct_general;
 
 	return ret;
 
+err_free_conntrack_slab:
+	kmem_cache_destroy(ip_conntrack_cachep);
 err_free_hash:
 	vfree(ip_conntrack_hash);
 err_unreg_sockopt:
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
index b9c27d5e4..df7008989 100644
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_ftp.c
@@ -19,6 +19,7 @@
 #include <linux/netfilter_ipv4/lockhelp.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
+#include <linux/moduleparam.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>");
@@ -27,16 +28,16 @@ MODULE_DESCRIPTION("ftp connection tracking helper");
 /* This is slow, but it's simple. --RR */
 static char ftp_buffer[65536];
 
-DECLARE_LOCK(ip_ftp_lock);
+static DECLARE_LOCK(ip_ftp_lock);
 struct module *ip_conntrack_ftp = THIS_MODULE;
 
 #define MAX_PORTS 8
 static int ports[MAX_PORTS];
 static int ports_c;
-MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
+module_param_array(ports, int, ports_c, 0400);
 
 static int loose;
-MODULE_PARM(loose, "i");
+module_param(loose, int, 0600);
 
 #if 0
 #define DEBUGP printk
@@ -247,7 +248,8 @@ static int help(struct sk_buff *skb,
 		enum ip_conntrack_info ctinfo)
 {
 	unsigned int dataoff, datalen;
-	struct tcphdr tcph;
+	struct tcphdr _tcph, *th;
+	char *fb_ptr;
 	u_int32_t old_seq_aft_nl;
 	int old_seq_aft_nl_set, ret;
 	u_int32_t array[6] = { 0 };
@@ -267,10 +269,12 @@ static int help(struct sk_buff *skb,
 		return NF_ACCEPT;
 	}
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) != 0)
+	th = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+				sizeof(_tcph), &_tcph);
+	if (th == NULL)
 		return NF_ACCEPT;
 
-	dataoff = skb->nh.iph->ihl*4 + tcph.doff*4;
+	dataoff = skb->nh.iph->ihl*4 + th->doff*4;
 	/* No data? */
 	if (dataoff >= skb->len) {
 		DEBUGP("ftp: skblen = %u\n", skb->len);
@@ -279,26 +283,28 @@ static int help(struct sk_buff *skb,
 	datalen = skb->len - dataoff;
 
 	LOCK_BH(&ip_ftp_lock);
-	skb_copy_bits(skb, dataoff, ftp_buffer, skb->len - dataoff);
+	fb_ptr = skb_header_pointer(skb, dataoff,
+				    skb->len - dataoff, ftp_buffer);
+	BUG_ON(fb_ptr == NULL);
 
 	old_seq_aft_nl_set = ct_ftp_info->seq_aft_nl_set[dir];
 	old_seq_aft_nl = ct_ftp_info->seq_aft_nl[dir];
 
 	DEBUGP("conntrack_ftp: datalen %u\n", datalen);
-	if (ftp_buffer[datalen - 1] == '\n') {
+	if (fb_ptr[datalen - 1] == '\n') {
 		DEBUGP("conntrack_ftp: datalen %u ends in \\n\n", datalen);
 		if (!old_seq_aft_nl_set
-		    || after(ntohl(tcph.seq) + datalen, old_seq_aft_nl)) {
+		    || after(ntohl(th->seq) + datalen, old_seq_aft_nl)) {
 			DEBUGP("conntrack_ftp: updating nl to %u\n",
-			       ntohl(tcph.seq) + datalen);
+			       ntohl(th->seq) + datalen);
 			ct_ftp_info->seq_aft_nl[dir] = 
-						ntohl(tcph.seq) + datalen;
+						ntohl(th->seq) + datalen;
 			ct_ftp_info->seq_aft_nl_set[dir] = 1;
 		}
 	}
 
 	if(!old_seq_aft_nl_set ||
-			(ntohl(tcph.seq) != old_seq_aft_nl)) {
+			(ntohl(th->seq) != old_seq_aft_nl)) {
 		DEBUGP("ip_conntrack_ftp_help: wrong seq pos %s(%u)\n",
 		       old_seq_aft_nl_set ? "":"(UNSET) ", old_seq_aft_nl);
 		ret = NF_ACCEPT;
@@ -315,7 +321,7 @@ static int help(struct sk_buff *skb,
 	for (i = 0; i < ARRAY_SIZE(search); i++) {
 		if (search[i].dir != dir) continue;
 
-		found = find_pattern(ftp_buffer, skb->len - dataoff,
+		found = find_pattern(fb_ptr, skb->len - dataoff,
 				     search[i].pattern,
 				     search[i].plen,
 				     search[i].skip,
@@ -333,7 +339,7 @@ static int help(struct sk_buff *skb,
 		if (net_ratelimit())
 			printk("conntrack_ftp: partial %s %u+%u\n",
 			       search[i].pattern,
-			       ntohl(tcph.seq), datalen);
+			       ntohl(th->seq), datalen);
 		ret = NF_DROP;
 		goto out;
 	} else if (found == 0) { /* No match */
@@ -343,7 +349,7 @@ static int help(struct sk_buff *skb,
 
 	DEBUGP("conntrack_ftp: match `%.*s' (%u bytes at %u)\n",
 	       (int)matchlen, data + matchoff,
-	       matchlen, ntohl(tcph.seq) + matchoff);
+	       matchlen, ntohl(th->seq) + matchoff);
 
 	/* Allocate expectation which will be inserted */
 	exp = ip_conntrack_expect_alloc();
@@ -357,7 +363,7 @@ static int help(struct sk_buff *skb,
 	/* Update the ftp info */
 	if (htonl((array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3])
 	    == ct->tuplehash[dir].tuple.src.ip) {
-		exp->seq = ntohl(tcph.seq) + matchoff;
+		exp->seq = ntohl(th->seq) + matchoff;
 		exp_ftp_info->len = matchlen;
 		exp_ftp_info->ftptype = search[i].ftptype;
 		exp_ftp_info->port = array[4] << 8 | array[5];
@@ -420,10 +426,10 @@ static int __init init(void)
 	int i, ret;
 	char *tmpname;
 
-	if (ports[0] == 0)
-		ports[0] = FTP_PORT;
+	if (ports_c == 0)
+		ports[ports_c++] = FTP_PORT;
 
-	for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
+	for (i = 0; i < ports_c; i++) {
 		ftp[i].tuple.src.u.tcp.port = htons(ports[i]);
 		ftp[i].tuple.dst.protonum = IPPROTO_TCP;
 		ftp[i].mask.src.u.tcp.port = 0xFFFF;
@@ -449,13 +455,11 @@ static int __init init(void)
 			fini();
 			return ret;
 		}
-		ports_c++;
 	}
 	return 0;
 }
 
 PROVIDES_CONNTRACK(ftp);
-EXPORT_SYMBOL(ip_ftp_lock);
 
 module_init(init);
 module_exit(fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c
index 32b5daee8..d007bc995 100644
--- a/net/ipv4/netfilter/ip_conntrack_irc.c
+++ b/net/ipv4/netfilter/ip_conntrack_irc.c
@@ -32,6 +32,7 @@
 #include <linux/netfilter_ipv4/lockhelp.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
+#include <linux/moduleparam.h>
 
 #define MAX_PORTS 8
 static int ports[MAX_PORTS];
@@ -40,21 +41,21 @@ static int max_dcc_channels = 8;
 static unsigned int dcc_timeout = 300;
 /* This is slow, but it's simple. --RR */
 static char irc_buffer[65536];
+static DECLARE_LOCK(irc_buffer_lock);
 
 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
 MODULE_DESCRIPTION("IRC (DCC) connection tracking helper");
 MODULE_LICENSE("GPL");
-MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
+module_param_array(ports, int, ports_c, 0400);
 MODULE_PARM_DESC(ports, "port numbers of IRC servers");
-MODULE_PARM(max_dcc_channels, "i");
+module_param(max_dcc_channels, int, 0400);
 MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per IRC session");
-MODULE_PARM(dcc_timeout, "i");
+module_param(dcc_timeout, int, 0400);
 MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels");
 
 static char *dccprotos[] = { "SEND ", "CHAT ", "MOVE ", "TSEND ", "SCHAT " };
 #define MINMATCHLEN	5
 
-DECLARE_LOCK(ip_irc_lock);
 struct module *ip_conntrack_irc = THIS_MODULE;
 
 #if 0
@@ -101,8 +102,8 @@ static int help(struct sk_buff *skb,
 		struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
 {
 	unsigned int dataoff;
-	struct tcphdr tcph;
-	char *data, *data_limit;
+	struct tcphdr _tcph, *th;
+	char *data, *data_limit, *ib_ptr;
 	int dir = CTINFO2DIR(ctinfo);
 	struct ip_conntrack_expect *exp;
 	struct ip_ct_irc_expect *exp_irc_info = NULL;
@@ -126,19 +127,23 @@ static int help(struct sk_buff *skb,
 	}
 
 	/* Not a full tcp header? */
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) != 0)
+	th = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+				sizeof(_tcph), &_tcph);
+	if (th == NULL)
 		return NF_ACCEPT;
 
 	/* No data? */
-	dataoff = skb->nh.iph->ihl*4 + tcph.doff*4;
+	dataoff = skb->nh.iph->ihl*4 + th->doff*4;
 	if (dataoff >= skb->len)
 		return NF_ACCEPT;
 
-	LOCK_BH(&ip_irc_lock);
-	skb_copy_bits(skb, dataoff, irc_buffer, skb->len - dataoff);
+	LOCK_BH(&irc_buffer_lock);
+	ib_ptr = skb_header_pointer(skb, dataoff,
+				    skb->len - dataoff, irc_buffer);
+	BUG_ON(ib_ptr == NULL);
 
-	data = irc_buffer;
-	data_limit = irc_buffer + skb->len - dataoff;
+	data = ib_ptr;
+	data_limit = ib_ptr + skb->len - dataoff;
 
 	/* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24
 	 * 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */
@@ -152,8 +157,8 @@ static int help(struct sk_buff *skb,
 		/* we have at least (19+MINMATCHLEN)-5 bytes valid data left */
 
 		DEBUGP("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u...\n",
-			NIPQUAD(iph->saddr), ntohs(tcph.source),
-			NIPQUAD(iph->daddr), ntohs(tcph.dest));
+			NIPQUAD(iph->saddr), ntohs(th->source),
+			NIPQUAD(iph->daddr), ntohs(th->dest));
 
 		for (i = 0; i < ARRAY_SIZE(dccprotos); i++) {
 			if (memcmp(data, dccprotos[i], strlen(dccprotos[i]))) {
@@ -197,8 +202,8 @@ static int help(struct sk_buff *skb,
 
 			/* save position of address in dcc string,
 			 * necessary for NAT */
-			DEBUGP("tcph->seq = %u\n", tcph.seq);
-			exp->seq = ntohl(tcph.seq) + (addr_beg_p - irc_buffer);
+			DEBUGP("tcph->seq = %u\n", th->seq);
+			exp->seq = ntohl(th->seq) + (addr_beg_p - ib_ptr);
 			exp_irc_info->len = (addr_end_p - addr_beg_p);
 			exp_irc_info->port = dcc_port;
 			DEBUGP("wrote info seq=%u (ofs=%u), len=%d\n",
@@ -227,7 +232,7 @@ static int help(struct sk_buff *skb,
 	} /* while data < ... */
 
  out:
-	UNLOCK_BH(&ip_irc_lock);
+	UNLOCK_BH(&irc_buffer_lock);
 	return NF_ACCEPT;
 }
 
@@ -252,10 +257,10 @@ static int __init init(void)
 	}
 	
 	/* If no port given, default to standard irc port */
-	if (ports[0] == 0)
-		ports[0] = IRC_PORT;
+	if (ports_c == 0)
+		ports[ports_c++] = IRC_PORT;
 
-	for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
+	for (i = 0; i < ports_c; i++) {
 		hlpr = &irc_helpers[i];
 		hlpr->tuple.src.u.tcp.port = htons(ports[i]);
 		hlpr->tuple.dst.protonum = IPPROTO_TCP;
@@ -284,7 +289,6 @@ static int __init init(void)
 			fini();
 			return -EBUSY;
 		}
-		ports_c++;
 	}
 	return 0;
 }
@@ -302,7 +306,6 @@ static void fini(void)
 }
 
 PROVIDES_CONNTRACK(irc);
-EXPORT_SYMBOL(ip_irc_lock);
 
 module_init(init);
 module_exit(fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_generic.c b/net/ipv4/netfilter/ip_conntrack_proto_generic.c
index 0df558a58..88c3712bd 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_generic.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_generic.c
@@ -34,15 +34,15 @@ static int generic_invert_tuple(struct ip_conntrack_tuple *tuple,
 }
 
 /* Print out the per-protocol part of the tuple. */
-static unsigned int generic_print_tuple(char *buffer,
-					const struct ip_conntrack_tuple *tuple)
+static int generic_print_tuple(struct seq_file *s,
+			       const struct ip_conntrack_tuple *tuple)
 {
 	return 0;
 }
 
 /* Print out the private part of the conntrack. */
-static unsigned int generic_print_conntrack(char *buffer,
-					    const struct ip_conntrack *state)
+static int generic_print_conntrack(struct seq_file *s,
+				   const struct ip_conntrack *state)
 {
 	return 0;
 }
@@ -50,9 +50,9 @@ static unsigned int generic_print_conntrack(char *buffer,
 /* Returns verdict for packet, or -1 for invalid. */
 static int packet(struct ip_conntrack *conntrack,
 		  const struct sk_buff *skb,
-		  enum ip_conntrack_info conntrackinfo)
+		  enum ip_conntrack_info ctinfo)
 {
-	ip_ct_refresh(conntrack, ip_ct_generic_timeout);
+	ip_ct_refresh_acct(conntrack, ctinfo, skb, ip_ct_generic_timeout);
 	return NF_ACCEPT;
 }
 
@@ -62,8 +62,14 @@ static int new(struct ip_conntrack *conntrack, const struct sk_buff *skb)
 	return 1;
 }
 
-struct ip_conntrack_protocol ip_conntrack_generic_protocol
-= { { NULL, NULL }, 0, "unknown",
-    generic_pkt_to_tuple, generic_invert_tuple, generic_print_tuple,
-    generic_print_conntrack, packet, new, NULL, NULL, NULL };
-
+struct ip_conntrack_protocol ip_conntrack_generic_protocol =
+{
+	.proto			= 0,
+	.name			= "unknown",
+	.pkt_to_tuple		= generic_pkt_to_tuple,
+	.invert_tuple		= generic_invert_tuple,
+	.print_tuple		= generic_print_tuple,
+	.print_conntrack	= generic_print_conntrack,
+	.packet			= packet,
+	.new			= new,
+};
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
index 47114840f..344820a51 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
@@ -12,6 +12,13 @@
 #include <linux/netfilter.h>
 #include <linux/in.h>
 #include <linux/icmp.h>
+#include <linux/seq_file.h>
+#include <net/ip.h>
+#include <net/checksum.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
 
 unsigned long ip_ct_icmp_timeout = 30*HZ;
@@ -26,14 +33,15 @@ static int icmp_pkt_to_tuple(const struct sk_buff *skb,
 			     unsigned int dataoff,
 			     struct ip_conntrack_tuple *tuple)
 {
-	struct icmphdr hdr;
+	struct icmphdr _hdr, *hp;
 
-	if (skb_copy_bits(skb, dataoff, &hdr, sizeof(hdr)) != 0)
+	hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
+	if (hp == NULL)
 		return 0;
 
-	tuple->dst.u.icmp.type = hdr.type;
-	tuple->src.u.icmp.id = hdr.un.echo.id;
-	tuple->dst.u.icmp.code = hdr.code;
+	tuple->dst.u.icmp.type = hp->type;
+	tuple->src.u.icmp.id = hp->un.echo.id;
+	tuple->dst.u.icmp.code = hp->code;
 
 	return 1;
 }
@@ -63,18 +71,18 @@ static int icmp_invert_tuple(struct ip_conntrack_tuple *tuple,
 }
 
 /* Print out the per-protocol part of the tuple. */
-static unsigned int icmp_print_tuple(char *buffer,
-				     const struct ip_conntrack_tuple *tuple)
+static int icmp_print_tuple(struct seq_file *s,
+			    const struct ip_conntrack_tuple *tuple)
 {
-	return sprintf(buffer, "type=%u code=%u id=%u ",
-		       tuple->dst.u.icmp.type,
-		       tuple->dst.u.icmp.code,
-		       ntohs(tuple->src.u.icmp.id));
+	return seq_printf(s, "type=%u code=%u id=%u ",
+			  tuple->dst.u.icmp.type,
+			  tuple->dst.u.icmp.code,
+			  ntohs(tuple->src.u.icmp.id));
 }
 
 /* Print out the private part of the conntrack. */
-static unsigned int icmp_print_conntrack(char *buffer,
-				     const struct ip_conntrack *conntrack)
+static int icmp_print_conntrack(struct seq_file *s,
+				const struct ip_conntrack *conntrack)
 {
 	return 0;
 }
@@ -94,7 +102,7 @@ static int icmp_packet(struct ip_conntrack *ct,
 			ct->timeout.function((unsigned long)ct);
 	} else {
 		atomic_inc(&ct->proto.icmp.count);
-		ip_ct_refresh(ct, ip_ct_icmp_timeout);
+		ip_ct_refresh_acct(ct, ctinfo, skb, ip_ct_icmp_timeout);
 	}
 
 	return NF_ACCEPT;
@@ -122,7 +130,150 @@ static int icmp_new(struct ip_conntrack *conntrack,
 	return 1;
 }
 
-struct ip_conntrack_protocol ip_conntrack_protocol_icmp
-= { { NULL, NULL }, IPPROTO_ICMP, "icmp",
-    icmp_pkt_to_tuple, icmp_invert_tuple, icmp_print_tuple,
-    icmp_print_conntrack, icmp_packet, icmp_new, NULL, NULL, NULL };
+static int
+icmp_error_message(struct sk_buff *skb,
+		   enum ip_conntrack_info *ctinfo,
+		   unsigned int hooknum)
+{
+	struct ip_conntrack_tuple innertuple, origtuple;
+	struct {
+		struct icmphdr icmp;
+		struct iphdr ip;
+	} _in, *inside;
+	struct ip_conntrack_protocol *innerproto;
+	struct ip_conntrack_tuple_hash *h;
+	int dataoff;
+
+	IP_NF_ASSERT(skb->nfct == NULL);
+
+	/* Not enough header? */
+	inside = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_in), &_in);
+	if (inside == NULL)
+		return NF_ACCEPT;
+
+	/* Ignore ICMP's containing fragments (shouldn't happen) */
+	if (inside->ip.frag_off & htons(IP_OFFSET)) {
+		DEBUGP("icmp_error_track: fragment of proto %u\n",
+		       inside->ip.protocol);
+		return NF_ACCEPT;
+	}
+
+	innerproto = ip_ct_find_proto(inside->ip.protocol);
+	dataoff = skb->nh.iph->ihl*4 + sizeof(inside->icmp) + inside->ip.ihl*4;
+	/* Are they talking about one of our connections? */
+	if (!ip_ct_get_tuple(&inside->ip, skb, dataoff, &origtuple, innerproto)) {
+		DEBUGP("icmp_error: ! get_tuple p=%u", inside->ip.protocol);
+		return NF_ACCEPT;
+	}
+
+	/* Ordinarily, we'd expect the inverted tupleproto, but it's
+	   been preserved inside the ICMP. */
+	if (!ip_ct_invert_tuple(&innertuple, &origtuple, innerproto)) {
+		DEBUGP("icmp_error_track: Can't invert tuple\n");
+		return NF_ACCEPT;
+	}
+
+	*ctinfo = IP_CT_RELATED;
+
+	h = ip_conntrack_find_get(&innertuple, NULL);
+	if (!h) {
+		/* Locally generated ICMPs will match inverted if they
+		   haven't been SNAT'ed yet */
+		/* FIXME: NAT code has to handle half-done double NAT --RR */
+		if (hooknum == NF_IP_LOCAL_OUT)
+			h = ip_conntrack_find_get(&origtuple, NULL);
+
+		if (!h) {
+			DEBUGP("icmp_error_track: no match\n");
+			return NF_ACCEPT;
+		}
+		/* Reverse direction from that found */
+		if (DIRECTION(h) != IP_CT_DIR_REPLY)
+			*ctinfo += IP_CT_IS_REPLY;
+	} else {
+		if (DIRECTION(h) == IP_CT_DIR_REPLY)
+			*ctinfo += IP_CT_IS_REPLY;
+	}
+
+	/* Update skb to refer to this connection */
+	skb->nfct = &h->ctrack->ct_general;
+	skb->nfctinfo = *ctinfo;
+	return -NF_ACCEPT;
+}
+
+/* Small and modified version of icmp_rcv */
+static int
+icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
+	   unsigned int hooknum)
+{
+	struct icmphdr _ih, *icmph;
+
+	/* Not enough header? */
+	icmph = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_ih), &_ih);
+	if (icmph == NULL) {
+		if (LOG_INVALID(IPPROTO_ICMP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+				      "ip_ct_icmp: short packet ");
+		return -NF_ACCEPT;
+	}
+
+	/* See ip_conntrack_proto_tcp.c */
+	if (hooknum != NF_IP_PRE_ROUTING)
+		goto checksum_skipped;
+
+	switch (skb->ip_summed) {
+	case CHECKSUM_HW:
+		if (!(u16)csum_fold(skb->csum)) 
+			break;
+		if (LOG_INVALID(IPPROTO_ICMP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+				      "ip_ct_icmp: bad HW ICMP checksum ");
+		return -NF_ACCEPT;
+	case CHECKSUM_NONE:
+		if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) {
+			if (LOG_INVALID(IPPROTO_ICMP))
+				nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+					      "ip_ct_icmp: bad ICMP checksum ");
+			return -NF_ACCEPT;
+		}
+	default:
+		break;
+	}
+
+checksum_skipped:
+	/*
+	 *	18 is the highest 'known' ICMP type. Anything else is a mystery
+	 *
+	 *	RFC 1122: 3.2.2  Unknown ICMP messages types MUST be silently
+	 *		  discarded.
+	 */
+	if (icmph->type > NR_ICMP_TYPES) {
+		if (LOG_INVALID(IPPROTO_ICMP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+				      "ip_ct_icmp: invalid ICMP type ");
+		return -NF_ACCEPT;
+	}
+
+	/* Need to track icmp error message? */
+	if (icmph->type != ICMP_DEST_UNREACH
+	    && icmph->type != ICMP_SOURCE_QUENCH
+	    && icmph->type != ICMP_TIME_EXCEEDED
+	    && icmph->type != ICMP_PARAMETERPROB
+	    && icmph->type != ICMP_REDIRECT)
+		return NF_ACCEPT;
+
+	return icmp_error_message(skb, ctinfo, hooknum);
+}
+
+struct ip_conntrack_protocol ip_conntrack_protocol_icmp =
+{
+	.proto 			= IPPROTO_ICMP,
+	.name 			= "icmp",
+	.pkt_to_tuple		= icmp_pkt_to_tuple,
+	.invert_tuple		= icmp_invert_tuple,
+	.print_tuple		= icmp_print_tuple,
+	.print_conntrack	= icmp_print_conntrack,
+	.packet			= icmp_packet,
+	.new			= icmp_new,
+	.error			= icmp_error,
+};
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
index 463cafa66..8fab05a58 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
@@ -4,8 +4,22 @@
  * 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.
+ *
+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>:
+ *	- Real stateful connection tracking
+ *	- Modified state transitions table
+ *	- Window scaling support added
+ *	- SACK support added
+ *
+ * Willy Tarreau:
+ *	- State table bugfixes
+ *	- More robust state changes
+ *	- Tuning timer parameters
+ *
+ * version 2.2
  */
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
@@ -14,16 +28,19 @@
 #include <linux/in.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
-#include <linux/string.h>
+#include <linux/spinlock.h>
 
 #include <net/tcp.h>
 
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
 #include <linux/netfilter_ipv4/lockhelp.h>
 
 #if 0
 #define DEBUGP printk
+#define DEBUGP_VARS
 #else
 #define DEBUGP(format, args...)
 #endif
@@ -31,28 +48,40 @@
 /* Protects conntrack->proto.tcp */
 static DECLARE_RWLOCK(tcp_lock);
 
-/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
-   closely.  They're more complex. --RR */
+/* "Be conservative in what you do, 
+    be liberal in what you accept from others." 
+    If it's non-zero, we mark only out of window RST segments as INVALID. */
+int ip_ct_tcp_be_liberal = 0;
 
-/* Actually, I believe that neither ipmasq (where this code is stolen
-   from) nor ipfilter do it exactly right.  A new conntrack machine taking
-   into account packet loss (which creates uncertainty as to exactly
-   the conntrack of the connection) is required.  RSN.  --RR */
+/* When connection is picked up from the middle, how many packets are required
+   to pass in each direction when we assume we are in sync - if any side uses
+   window scaling, we lost the game. 
+   If it is set to zero, we disable picking up already established 
+   connections. */
+int ip_ct_tcp_loose = 3;
+
+/* Max number of the retransmitted packets without receiving an (acceptable) 
+   ACK from the destination. If this number is reached, a shorter timer 
+   will be started. */
+int ip_ct_tcp_max_retrans = 3;
+
+  /* FIXME: Examine ipfilter's timeouts and conntrack transitions more
+     closely.  They're more complex. --RR */
 
 static const char *tcp_conntrack_names[] = {
 	"NONE",
-	"ESTABLISHED",
 	"SYN_SENT",
 	"SYN_RECV",
+	"ESTABLISHED",
 	"FIN_WAIT",
-	"TIME_WAIT",
-	"CLOSE",
 	"CLOSE_WAIT",
 	"LAST_ACK",
+	"TIME_WAIT",
+	"CLOSE",
 	"LISTEN"
 };
-
-#define SECS *HZ
+  
+#define SECS * HZ
 #define MINS * 60 SECS
 #define HOURS * 60 MINS
 #define DAYS * 24 HOURS
@@ -66,64 +95,214 @@ unsigned long ip_ct_tcp_timeout_last_ack =     30 SECS;
 unsigned long ip_ct_tcp_timeout_time_wait =     2 MINS;
 unsigned long ip_ct_tcp_timeout_close =        10 SECS;
 
+/* RFC1122 says the R2 limit should be at least 100 seconds.
+   Linux uses 15 packets as limit, which corresponds 
+   to ~13-30min depending on RTO. */
+unsigned long ip_ct_tcp_timeout_max_retrans =     5 MINS;
+ 
 static unsigned long * tcp_timeouts[]
 = { NULL,                              /*      TCP_CONNTRACK_NONE */
-    &ip_ct_tcp_timeout_established,    /*      TCP_CONNTRACK_ESTABLISHED,      */
     &ip_ct_tcp_timeout_syn_sent,       /*      TCP_CONNTRACK_SYN_SENT, */
     &ip_ct_tcp_timeout_syn_recv,       /*      TCP_CONNTRACK_SYN_RECV, */
+    &ip_ct_tcp_timeout_established,    /*      TCP_CONNTRACK_ESTABLISHED,      */
     &ip_ct_tcp_timeout_fin_wait,       /*      TCP_CONNTRACK_FIN_WAIT, */
-    &ip_ct_tcp_timeout_time_wait,      /*      TCP_CONNTRACK_TIME_WAIT,        */
-    &ip_ct_tcp_timeout_close,          /*      TCP_CONNTRACK_CLOSE,    */
     &ip_ct_tcp_timeout_close_wait,     /*      TCP_CONNTRACK_CLOSE_WAIT,       */
     &ip_ct_tcp_timeout_last_ack,       /*      TCP_CONNTRACK_LAST_ACK, */
+    &ip_ct_tcp_timeout_time_wait,      /*      TCP_CONNTRACK_TIME_WAIT,        */
+    &ip_ct_tcp_timeout_close,          /*      TCP_CONNTRACK_CLOSE,    */
     NULL,                              /*      TCP_CONNTRACK_LISTEN */
  };
  
 #define sNO TCP_CONNTRACK_NONE
-#define sES TCP_CONNTRACK_ESTABLISHED
 #define sSS TCP_CONNTRACK_SYN_SENT
 #define sSR TCP_CONNTRACK_SYN_RECV
+#define sES TCP_CONNTRACK_ESTABLISHED
 #define sFW TCP_CONNTRACK_FIN_WAIT
-#define sTW TCP_CONNTRACK_TIME_WAIT
-#define sCL TCP_CONNTRACK_CLOSE
 #define sCW TCP_CONNTRACK_CLOSE_WAIT
 #define sLA TCP_CONNTRACK_LAST_ACK
+#define sTW TCP_CONNTRACK_TIME_WAIT
+#define sCL TCP_CONNTRACK_CLOSE
 #define sLI TCP_CONNTRACK_LISTEN
 #define sIV TCP_CONNTRACK_MAX
+#define sIG TCP_CONNTRACK_IGNORE
 
-static enum tcp_conntrack tcp_conntracks[2][5][TCP_CONNTRACK_MAX] = {
+/* What TCP flags are set from RST/SYN/FIN/ACK. */
+enum tcp_bit_set {
+	TCP_SYN_SET,
+	TCP_SYNACK_SET,
+	TCP_FIN_SET,
+	TCP_ACK_SET,
+	TCP_RST_SET,
+	TCP_NONE_SET,
+};
+  
+/*
+ * The TCP state transition table needs a few words...
+ *
+ * We are the man in the middle. All the packets go through us
+ * but might get lost in transit to the destination.
+ * It is assumed that the destinations can't receive segments 
+ * we haven't seen.
+ *
+ * The checked segment is in window, but our windows are *not*
+ * equivalent with the ones of the sender/receiver. We always
+ * try to guess the state of the current sender.
+ *
+ * The meaning of the states are:
+ *
+ * NONE:	initial state
+ * SYN_SENT:	SYN-only packet seen 
+ * SYN_RECV:	SYN-ACK packet seen
+ * ESTABLISHED:	ACK packet seen
+ * FIN_WAIT:	FIN packet seen
+ * CLOSE_WAIT:	ACK seen (after FIN) 
+ * LAST_ACK:	FIN seen (after FIN)
+ * TIME_WAIT:	last ACK seen
+ * CLOSE:	closed connection
+ *
+ * LISTEN state is not used.
+ *
+ * Packets marked as IGNORED (sIG):
+ *	if they may be either invalid or valid 
+ *	and the receiver may send back a connection 
+ *	closing RST or a SYN/ACK.
+ *
+ * Packets marked as INVALID (sIV):
+ *	if they are invalid
+ *	or we do not support the request (simultaneous open)
+ */
+static enum tcp_conntrack tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
 	{
-/*	ORIGINAL */
-/* 	  sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI 	*/
-/*syn*/	{sSS, sES, sSS, sSR, sSS, sSS, sSS, sSS, sSS, sLI },
-/*fin*/	{sTW, sFW, sSS, sTW, sFW, sTW, sCL, sTW, sLA, sLI },
-/*ack*/	{sES, sES, sSS, sES, sFW, sTW, sCL, sCW, sLA, sES },
-/*rst*/ {sCL, sCL, sSS, sCL, sCL, sTW, sCL, sCL, sCL, sCL },
-/*none*/{sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
+/* ORIGINAL */
+/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
+/*syn*/	   { sSS, sSS, sIG, sIG, sIG, sIG, sIG, sSS, sSS, sIV },
+/*
+ *	sNO -> sSS	Initialize a new connection
+ *	sSS -> sSS	Retransmitted SYN
+ *	sSR -> sIG	Late retransmitted SYN?
+ *	sES -> sIG	Error: SYNs in window outside the SYN_SENT state
+ *			are errors. Receiver will reply with RST 
+ *			and close the connection.
+ *			Or we are not in sync and hold a dead connection.
+ *	sFW -> sIG
+ *	sCW -> sIG
+ *	sLA -> sIG
+ *	sTW -> sSS	Reopened connection (RFC 1122).
+ *	sCL -> sSS
+ */
+/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
+/*synack*/ { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV },
+/*
+ * A SYN/ACK from the client is always invalid:
+ *	- either it tries to set up a simultaneous open, which is 
+ *	  not supported;
+ *	- or the firewall has just been inserted between the two hosts
+ *	  during the session set-up. The SYN will be retransmitted 
+ *	  by the true client (or it'll time out).
+ */
+/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
+/*fin*/    { sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV },
+/*
+ *	sNO -> sIV	Too late and no reason to do anything...
+ *	sSS -> sIV	Client migth not send FIN in this state:
+ *			we enforce waiting for a SYN/ACK reply first.
+ *	sSR -> sFW	Close started.
+ *	sES -> sFW	
+ *	sFW -> sLA	FIN seen in both directions, waiting for
+ *			the last ACK. 
+ *			Migth be a retransmitted FIN as well...
+ *	sCW -> sLA
+ *	sLA -> sLA	Retransmitted FIN. Remain in the same state.
+ *	sTW -> sTW
+ *	sCL -> sCL
+ */
+/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
+/*ack*/	   { sES, sIV, sES, sES, sCW, sCW, sTW, sTW, sCL, sIV },
+/*
+ *	sNO -> sES	Assumed.
+ *	sSS -> sIV	ACK is invalid: we haven't seen a SYN/ACK yet.
+ *	sSR -> sES	Established state is reached.
+ *	sES -> sES	:-)
+ *	sFW -> sCW	Normal close request answered by ACK.
+ *	sCW -> sCW
+ *	sLA -> sTW	Last ACK detected.
+ *	sTW -> sTW	Retransmitted last ACK. Remain in the same state.
+ *	sCL -> sCL
+ */
+/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
+/*rst*/    { sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sIV },
+/*none*/   { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
 	},
 	{
-/*	REPLY */
-/* 	  sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI 	*/
-/*syn*/	{sSR, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSR },
-/*fin*/	{sCL, sCW, sSS, sTW, sTW, sTW, sCL, sCW, sLA, sLI },
-/*ack*/	{sCL, sES, sSS, sSR, sFW, sTW, sCL, sCW, sCL, sLI },
-/*rst*/ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sLA, sLI },
-/*none*/{sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
-	}
+/* REPLY */
+/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
+/*syn*/	   { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV },
+/*
+ *	sNO -> sIV	Never reached.
+ *	sSS -> sIV	Simultaneous open, not supported
+ *	sSR -> sIV	Simultaneous open, not supported.
+ *	sES -> sIV	Server may not initiate a connection.
+ *	sFW -> sIV
+ *	sCW -> sIV
+ *	sLA -> sIV
+ *	sTW -> sIV	Reopened connection, but server may not do it.
+ *	sCL -> sIV
+ */
+/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
+/*synack*/ { sIV, sSR, sSR, sIG, sIG, sIG, sIG, sIG, sIG, sIV },
+/*
+ *	sSS -> sSR	Standard open.
+ *	sSR -> sSR	Retransmitted SYN/ACK.
+ *	sES -> sIG	Late retransmitted SYN/ACK?
+ *	sFW -> sIG
+ *	sCW -> sIG
+ *	sLA -> sIG
+ *	sTW -> sIG
+ *	sCL -> sIG
+ */
+/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
+/*fin*/    { sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV },
+/*
+ *	sSS -> sIV	Server might not send FIN in this state.
+ *	sSR -> sFW	Close started.
+ *	sES -> sFW
+ *	sFW -> sLA	FIN seen in both directions.
+ *	sCW -> sLA
+ *	sLA -> sLA	Retransmitted FIN.
+ *	sTW -> sTW
+ *	sCL -> sCL
+ */
+/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
+/*ack*/	   { sIV, sIV, sIV, sES, sCW, sCW, sTW, sTW, sCL, sIV },
+/*
+ *	sSS -> sIV	ACK is invalid: we haven't seen a SYN/ACK yet.
+ *	sSR -> sIV	Simultaneous open.
+ *	sES -> sES	:-)
+ *	sFW -> sCW	Normal close request answered by ACK.
+ *	sCW -> sCW
+ *	sLA -> sTW	Last ACK detected.
+ *	sTW -> sTW	Retransmitted last ACK.
+ *	sCL -> sCL
+ */
+/* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
+/*rst*/    { sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sIV },
+/*none*/   { sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV }
+  	}
 };
 
 static int tcp_pkt_to_tuple(const struct sk_buff *skb,
-			     unsigned int dataoff,
-			     struct ip_conntrack_tuple *tuple)
+			    unsigned int dataoff,
+			    struct ip_conntrack_tuple *tuple)
 {
-	struct tcphdr hdr;
+	struct tcphdr _hdr, *hp;
 
 	/* Actually only need first 8 bytes. */
-	if (skb_copy_bits(skb, dataoff, &hdr, 8) != 0)
+	hp = skb_header_pointer(skb, dataoff, 8, &_hdr);
+	if (hp == NULL)
 		return 0;
 
-	tuple->src.u.tcp.port = hdr.source;
-	tuple->dst.u.tcp.port = hdr.dest;
+	tuple->src.u.tcp.port = hp->source;
+	tuple->dst.u.tcp.port = hp->dest;
 
 	return 1;
 }
@@ -137,17 +316,17 @@ static int tcp_invert_tuple(struct ip_conntrack_tuple *tuple,
 }
 
 /* Print out the per-protocol part of the tuple. */
-static unsigned int tcp_print_tuple(char *buffer,
-				    const struct ip_conntrack_tuple *tuple)
+static int tcp_print_tuple(struct seq_file *s,
+			   const struct ip_conntrack_tuple *tuple)
 {
-	return sprintf(buffer, "sport=%hu dport=%hu ",
-		       ntohs(tuple->src.u.tcp.port),
-		       ntohs(tuple->dst.u.tcp.port));
+	return seq_printf(s, "sport=%hu dport=%hu ",
+			  ntohs(tuple->src.u.tcp.port),
+			  ntohs(tuple->dst.u.tcp.port));
 }
 
 /* Print out the private part of the conntrack. */
-static unsigned int tcp_print_conntrack(char *buffer,
-					const struct ip_conntrack *conntrack)
+static int tcp_print_conntrack(struct seq_file *s,
+			       const struct ip_conntrack *conntrack)
 {
 	enum tcp_conntrack state;
 
@@ -155,16 +334,493 @@ static unsigned int tcp_print_conntrack(char *buffer,
 	state = conntrack->proto.tcp.state;
 	READ_UNLOCK(&tcp_lock);
 
-	return sprintf(buffer, "%s ", tcp_conntrack_names[state]);
+	return seq_printf(s, "%s ", tcp_conntrack_names[state]);
 }
 
 static unsigned int get_conntrack_index(const struct tcphdr *tcph)
 {
-	if (tcph->rst) return 3;
-	else if (tcph->syn) return 0;
-	else if (tcph->fin) return 1;
-	else if (tcph->ack) return 2;
-	else return 4;
+	if (tcph->rst) return TCP_RST_SET;
+	else if (tcph->syn) return (tcph->ack ? TCP_SYNACK_SET : TCP_SYN_SET);
+	else if (tcph->fin) return TCP_FIN_SET;
+	else if (tcph->ack) return TCP_ACK_SET;
+	else return TCP_NONE_SET;
+}
+
+/* TCP connection tracking based on 'Real Stateful TCP Packet Filtering
+   in IP Filter' by Guido van Rooij.
+   
+   http://www.nluug.nl/events/sane2000/papers.html
+   http://www.iae.nl/users/guido/papers/tcp_filtering.ps.gz
+   
+   The boundaries and the conditions are slightly changed:
+   
+   	td_maxend = max(sack + max(win,1)) seen in reply packets
+	td_maxwin = max(max(win, 1)) + (sack - ack) seen in sent packets
+	td_end    = max(seq + len) seen in sent packets
+   
+   I. 	Upper bound for valid data:	seq + len <= sender.td_maxend
+   II. 	Lower bound for valid data:	seq >= sender.td_end - receiver.td_maxwin
+   III.	Upper bound for valid ack:      sack <= receiver.td_end
+   IV.	Lower bound for valid ack:	ack >= receiver.td_end - MAXACKWINDOW
+   	
+   where sack is the highest right edge of sack block found in the packet.
+   	
+   The upper bound limit for a valid ack is not ignored - 
+   we doesn't have to deal with fragments. 
+*/
+
+static inline __u32 segment_seq_plus_len(__u32 seq,
+					 size_t len,
+					 struct iphdr *iph,
+					 struct tcphdr *tcph)
+  {
+	return (seq + len - (iph->ihl + tcph->doff)*4
+		+ (tcph->syn ? 1 : 0) + (tcph->fin ? 1 : 0));
+}
+  
+/* Fixme: what about big packets? */
+#define MAXACKWINCONST			66000
+#define MAXACKWINDOW(sender)						\
+	((sender)->td_maxwin > MAXACKWINCONST ? (sender)->td_maxwin	\
+					      : MAXACKWINCONST)
+  
+/*
+ * Simplified tcp_parse_options routine from tcp_input.c
+ */
+static void tcp_options(const struct sk_buff *skb,
+			struct iphdr *iph,
+			struct tcphdr *tcph, 
+			struct ip_ct_tcp_state *state)
+{
+	unsigned char buff[(15 * 4) - sizeof(struct tcphdr)];
+	unsigned char *ptr;
+	int length = (tcph->doff*4) - sizeof(struct tcphdr);
+	
+	if (!length)
+		return;
+
+	ptr = skb_header_pointer(skb,
+				 (iph->ihl * 4) + sizeof(struct tcphdr),
+				 length, buff);
+	BUG_ON(ptr == NULL);
+
+	state->td_scale = 
+	state->flags = 0;
+	
+	while (length > 0) {
+		int opcode=*ptr++;
+		int opsize;
+		
+		switch (opcode) {
+		case TCPOPT_EOL:
+			return;
+		case TCPOPT_NOP:	/* Ref: RFC 793 section 3.1 */
+			length--;
+			continue;
+		default:
+			opsize=*ptr++;
+			if (opsize < 2) /* "silly options" */
+				return;
+			if (opsize > length)
+				break;	/* don't parse partial options */
+
+			if (opcode == TCPOPT_SACK_PERM 
+			    && opsize == TCPOLEN_SACK_PERM)
+				state->flags |= IP_CT_TCP_FLAG_SACK_PERM;
+			else if (opcode == TCPOPT_WINDOW
+				 && opsize == TCPOLEN_WINDOW) {
+				state->td_scale = *(u_int8_t *)ptr;
+				
+				if (state->td_scale > 14) {
+					/* See RFC1323 */
+					state->td_scale = 14;
+				}
+				state->flags |=
+					IP_CT_TCP_STATE_FLAG_WINDOW_SCALE;
+			}
+			ptr += opsize - 2;
+			length -= opsize;
+		}
+	}
+}
+
+static void tcp_sack(struct tcphdr *tcph, __u32 *sack)
+{
+	__u32 tmp;
+	unsigned char *ptr;
+	int length = (tcph->doff*4) - sizeof(struct tcphdr);
+	
+	/* Fast path for timestamp-only option */
+	if (length == TCPOLEN_TSTAMP_ALIGNED*4
+	    && *(__u32 *)(tcph + 1) ==
+	        __constant_ntohl((TCPOPT_NOP << 24) 
+	        		 | (TCPOPT_NOP << 16)
+	        		 | (TCPOPT_TIMESTAMP << 8)
+	        		 | TCPOLEN_TIMESTAMP))
+		return;
+		
+	ptr = (unsigned char *)(tcph + 1);
+	while (length > 0) {
+		int opcode=*ptr++;
+		int opsize, i;
+		
+		switch (opcode) {
+		case TCPOPT_EOL:
+			return;
+		case TCPOPT_NOP:	/* Ref: RFC 793 section 3.1 */
+			length--;
+			continue;
+		default:
+			opsize=*ptr++;
+			if (opsize < 2) /* "silly options" */
+				return;
+			if (opsize > length)
+				break;	/* don't parse partial options */
+
+			if (opcode == TCPOPT_SACK 
+			    && opsize >= (TCPOLEN_SACK_BASE 
+			    		  + TCPOLEN_SACK_PERBLOCK)
+			    && !((opsize - TCPOLEN_SACK_BASE) 
+			    	 % TCPOLEN_SACK_PERBLOCK)) {
+			    	for (i = 0;
+			    	     i < (opsize - TCPOLEN_SACK_BASE);
+			    	     i += TCPOLEN_SACK_PERBLOCK) {
+					tmp = ntohl(*((u_int32_t *)(ptr+i)+1));
+					
+					if (after(tmp, *sack))
+						*sack = tmp;
+				}
+				return;
+			}
+			ptr += opsize - 2;
+			length -= opsize;
+		}
+	}
+}
+
+static int tcp_in_window(struct ip_ct_tcp *state, 
+                         enum ip_conntrack_dir dir,
+                         unsigned int *index,
+                         const struct sk_buff *skb,
+                         struct iphdr *iph,
+                         struct tcphdr *tcph)
+{
+	struct ip_ct_tcp_state *sender = &state->seen[dir];
+	struct ip_ct_tcp_state *receiver = &state->seen[!dir];
+	__u32 seq, ack, sack, end, win, swin;
+	int res;
+	
+	/*
+	 * Get the required data from the packet.
+	 */
+	seq = ntohl(tcph->seq);
+	ack = sack = ntohl(tcph->ack_seq);
+	win = ntohs(tcph->window);
+	end = segment_seq_plus_len(seq, skb->len, iph, tcph);
+	
+	if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM)
+		tcp_sack(tcph, &sack);
+		
+	DEBUGP("tcp_in_window: START\n");
+	DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
+	       "seq=%u ack=%u sack=%u win=%u end=%u\n",
+		NIPQUAD(iph->saddr), ntohs(tcph->source), 
+		NIPQUAD(iph->daddr), ntohs(tcph->dest),
+		seq, ack, sack, win, end);
+	DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
+	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
+		sender->td_end, sender->td_maxend, sender->td_maxwin,
+		sender->td_scale, 
+		receiver->td_end, receiver->td_maxend, receiver->td_maxwin, 
+		receiver->td_scale);
+		
+	if (sender->td_end == 0) {
+		/*
+		 * Initialize sender data.
+		 */
+		if (tcph->syn && tcph->ack) {
+			/*
+			 * Outgoing SYN-ACK in reply to a SYN.
+			 */
+			sender->td_end = 
+			sender->td_maxend = end;
+			sender->td_maxwin = (win == 0 ? 1 : win);
+
+			tcp_options(skb, iph, tcph, sender);
+			/* 
+			 * RFC 1323:
+			 * Both sides must send the Window Scale option
+			 * to enable window scaling in either direction.
+			 */
+			if (!(sender->flags & IP_CT_TCP_STATE_FLAG_WINDOW_SCALE
+			      && receiver->flags & IP_CT_TCP_STATE_FLAG_WINDOW_SCALE))
+				sender->td_scale = 
+				receiver->td_scale = 0;
+		} else {
+			/*
+			 * We are in the middle of a connection,
+			 * its history is lost for us.
+			 * Let's try to use the data from the packet.
+		 	 */
+			sender->td_end = end;
+			sender->td_maxwin = (win == 0 ? 1 : win);
+			sender->td_maxend = end + sender->td_maxwin;
+		}
+	} else if (state->state == TCP_CONNTRACK_SYN_SENT
+		   && dir == IP_CT_DIR_ORIGINAL
+		   && after(end, sender->td_end)) {
+		/*
+		 * RFC 793: "if a TCP is reinitialized ... then it need
+		 * not wait at all; it must only be sure to use sequence 
+		 * numbers larger than those recently used."
+		 */
+		sender->td_end =
+		sender->td_maxend = end;
+		sender->td_maxwin = (win == 0 ? 1 : win);
+
+		tcp_options(skb, iph, tcph, sender);
+	}
+	
+	if (!(tcph->ack)) {
+		/*
+		 * If there is no ACK, just pretend it was set and OK.
+		 */
+		ack = sack = receiver->td_end;
+	} else if (((tcp_flag_word(tcph) & (TCP_FLAG_ACK|TCP_FLAG_RST)) == 
+		    (TCP_FLAG_ACK|TCP_FLAG_RST)) 
+		   && (ack == 0)) {
+		/*
+		 * Broken TCP stacks, that set ACK in RST packets as well
+		 * with zero ack value.
+		 */
+		ack = sack = receiver->td_end;
+	}
+
+	if (seq == end)
+		/*
+		 * Packets contains no data: we assume it is valid
+		 * and check the ack value only.
+		 */
+		seq = end = sender->td_end;
+		
+	DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
+	       "seq=%u ack=%u sack =%u win=%u end=%u trim=%u\n",
+		NIPQUAD(iph->saddr), ntohs(tcph->source),
+		NIPQUAD(iph->daddr), ntohs(tcph->dest),
+		seq, ack, sack, win, end, 
+		after(end, sender->td_maxend) && before(seq, sender->td_maxend)
+		? sender->td_maxend : end);
+	DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
+	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
+		sender->td_end, sender->td_maxend, sender->td_maxwin,
+		sender->td_scale, 
+		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
+		receiver->td_scale);
+	
+	/* Ignore data over the right edge of the receiver's window. */
+	if (after(end, sender->td_maxend) &&
+	    before(seq, sender->td_maxend)) {
+		end = sender->td_maxend;
+		if (*index == TCP_FIN_SET)
+			*index = TCP_ACK_SET;
+	}
+	DEBUGP("tcp_in_window: I=%i II=%i III=%i IV=%i\n",
+		before(end, sender->td_maxend + 1) 
+		    || before(seq, sender->td_maxend + 1),
+	    	after(seq, sender->td_end - receiver->td_maxwin - 1) 
+	    	    || after(end, sender->td_end - receiver->td_maxwin - 1),
+	    	before(sack, receiver->td_end + 1),
+	    	after(ack, receiver->td_end - MAXACKWINDOW(sender)));
+	
+	if (sender->loose || receiver->loose ||
+	    (before(end, sender->td_maxend + 1) &&
+	     after(seq, sender->td_end - receiver->td_maxwin - 1) &&
+	     before(sack, receiver->td_end + 1) &&
+	     after(ack, receiver->td_end - MAXACKWINDOW(sender)))) {
+	    	/*
+		 * Take into account window scaling (RFC 1323).
+		 */
+		if (!tcph->syn)
+			win <<= sender->td_scale;
+		
+		/*
+		 * Update sender data.
+		 */
+		swin = win + (sack - ack);
+		if (sender->td_maxwin < swin)
+			sender->td_maxwin = swin;
+		if (after(end, sender->td_end))
+			sender->td_end = end;
+		if (after(sack + win, receiver->td_maxend - 1)) {
+			receiver->td_maxend = sack + win;
+			if (win == 0)
+				receiver->td_maxend++;
+		}
+
+		/* 
+		 * Check retransmissions.
+		 */
+		if (*index == TCP_ACK_SET) {
+			if (state->last_dir == dir
+			    && state->last_seq == seq
+			    && state->last_end == end)
+				state->retrans++;
+			else {
+				state->last_dir = dir;
+				state->last_seq = seq;
+				state->last_end = end;
+				state->retrans = 0;
+			}
+		}
+		/*
+		 * Close the window of disabled window tracking :-)
+		 */
+		if (sender->loose)
+			sender->loose--;
+		
+		res = 1;
+	} else {
+		if (LOG_INVALID(IPPROTO_TCP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+			"ip_ct_tcp: %s ",
+			before(end, sender->td_maxend + 1) ?
+			after(seq, sender->td_end - receiver->td_maxwin - 1) ?
+			before(ack, receiver->td_end + 1) ?
+			after(ack, receiver->td_end - MAXACKWINDOW(sender)) ? "BUG"
+			: "ACK is under the lower bound (possibly overly delayed ACK)"
+			: "ACK is over the upper bound (ACKed data has never seen yet)"
+			: "SEQ is under the lower bound (retransmitted already ACKed data)"
+			: "SEQ is over the upper bound (over the window of the receiver)");
+
+		res = ip_ct_tcp_be_liberal && !tcph->rst;
+  	}
+  
+	DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
+	       "receiver end=%u maxend=%u maxwin=%u\n",
+		res, sender->td_end, sender->td_maxend, sender->td_maxwin, 
+		receiver->td_end, receiver->td_maxend, receiver->td_maxwin);
+
+	return res;
+}
+
+#ifdef CONFIG_IP_NF_NAT_NEEDED
+/* Update sender->td_end after NAT successfully mangled the packet */
+int ip_conntrack_tcp_update(struct sk_buff *skb,
+			    struct ip_conntrack *conntrack, 
+			    int dir)
+{
+	struct iphdr *iph = skb->nh.iph;
+	struct tcphdr *tcph = (void *)skb->nh.iph + skb->nh.iph->ihl*4;
+	__u32 end;
+#ifdef DEBUGP_VARS
+	struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[dir];
+	struct ip_ct_tcp_state *receiver = &conntrack->proto.tcp.seen[!dir];
+#endif
+
+	end = segment_seq_plus_len(ntohl(tcph->seq), skb->len, iph, tcph);
+	
+	WRITE_LOCK(&tcp_lock);
+	/*
+	 * We have to worry for the ack in the reply packet only...
+	 */
+	if (after(end, conntrack->proto.tcp.seen[dir].td_end))
+		conntrack->proto.tcp.seen[dir].td_end = end;
+	conntrack->proto.tcp.last_end = end;
+	WRITE_UNLOCK(&tcp_lock);
+	DEBUGP("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i "
+	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
+		sender->td_end, sender->td_maxend, sender->td_maxwin,
+		sender->td_scale, 
+		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
+		receiver->td_scale);
+		
+	return 1;
+}
+ 
+EXPORT_SYMBOL(ip_conntrack_tcp_update);
+#endif
+
+#define	TH_FIN	0x01
+#define	TH_SYN	0x02
+#define	TH_RST	0x04
+#define	TH_PUSH	0x08
+#define	TH_ACK	0x10
+#define	TH_URG	0x20
+#define	TH_ECE	0x40
+#define	TH_CWR	0x80
+
+/* table of valid flag combinations - ECE and CWR are always valid */
+static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
+{
+	[TH_SYN]			= 1,
+	[TH_SYN|TH_ACK]			= 1,
+	[TH_RST]			= 1,
+	[TH_RST|TH_ACK]			= 1,
+	[TH_RST|TH_ACK|TH_PUSH]		= 1,
+	[TH_FIN|TH_ACK]			= 1,
+	[TH_ACK]			= 1,
+	[TH_ACK|TH_PUSH]		= 1,
+	[TH_ACK|TH_URG]			= 1,
+	[TH_ACK|TH_URG|TH_PUSH]		= 1,
+	[TH_FIN|TH_ACK|TH_PUSH]		= 1,
+	[TH_FIN|TH_ACK|TH_URG]		= 1,
+	[TH_FIN|TH_ACK|TH_URG|TH_PUSH]	= 1,
+};
+
+/* Protect conntrack agaist broken packets. Code taken from ipt_unclean.c.  */
+static int tcp_error(struct sk_buff *skb,
+		     enum ip_conntrack_info *ctinfo,
+		     unsigned int hooknum)
+{
+	struct iphdr *iph = skb->nh.iph;
+	struct tcphdr _tcph, *th;
+	unsigned int tcplen = skb->len - iph->ihl * 4;
+	u_int8_t tcpflags;
+
+	/* Smaller that minimal TCP header? */
+	th = skb_header_pointer(skb, iph->ihl * 4,
+				sizeof(_tcph), &_tcph);
+	if (th == NULL) {
+		if (LOG_INVALID(IPPROTO_TCP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+				"ip_ct_tcp: short packet ");
+		return -NF_ACCEPT;
+  	}
+  
+	/* Not whole TCP header or malformed packet */
+	if (th->doff*4 < sizeof(struct tcphdr) || tcplen < th->doff*4) {
+		if (LOG_INVALID(IPPROTO_TCP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+				"ip_ct_tcp: truncated/malformed packet ");
+		return -NF_ACCEPT;
+	}
+  
+	/* Checksum invalid? Ignore.
+	 * We skip checking packets on the outgoing path
+	 * because the semantic of CHECKSUM_HW is different there 
+	 * and moreover root might send raw packets.
+	 */
+	/* FIXME: Source route IP option packets --RR */
+	if (hooknum == NF_IP_PRE_ROUTING
+	    && csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
+			         skb->ip_summed == CHECKSUM_HW ? skb->csum
+			      	 : skb_checksum(skb, iph->ihl*4, tcplen, 0))) {
+		if (LOG_INVALID(IPPROTO_TCP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+				  "ip_ct_tcp: bad TCP checksum ");
+		return -NF_ACCEPT;
+	}
+
+	/* Check TCP flags. */
+	tcpflags = (((u_int8_t *)th)[13] & ~(TH_ECE|TH_CWR));
+	if (!tcp_valid_flags[tcpflags]) {
+		if (LOG_INVALID(IPPROTO_TCP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+				  "ip_ct_tcp: invalid TCP flag combination ");
+		return -NF_ACCEPT;
+	}
+
+	return NF_ACCEPT;
 }
 
 /* Returns verdict for packet, or -1 for invalid. */
@@ -172,103 +828,260 @@ static int tcp_packet(struct ip_conntrack *conntrack,
 		      const struct sk_buff *skb,
 		      enum ip_conntrack_info ctinfo)
 {
-	enum tcp_conntrack newconntrack, oldtcpstate;
-	struct tcphdr tcph;
-
-	if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &tcph, sizeof(tcph)) != 0)
-		return -1;
-	if (skb->len < skb->nh.iph->ihl * 4 + tcph.doff * 4)
-		return -1;
-
-	/* If only reply is a RST, we can consider ourselves not to
-	   have an established connection: this is a fairly common
-	   problem case, so we can delete the conntrack
-	   immediately.  --RR */
-	if (!test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status) && tcph.rst) {
-		if (del_timer(&conntrack->timeout))
-			conntrack->timeout.function((unsigned long)conntrack);
+	enum tcp_conntrack new_state, old_state;
+	enum ip_conntrack_dir dir;
+	struct iphdr *iph = skb->nh.iph;
+	struct tcphdr *th, _tcph;
+	unsigned long timeout;
+	unsigned int index;
+	
+	th = skb_header_pointer(skb, iph->ihl * 4,
+				sizeof(_tcph), &_tcph);
+	BUG_ON(th == NULL);
+	
+	WRITE_LOCK(&tcp_lock);
+	old_state = conntrack->proto.tcp.state;
+	dir = CTINFO2DIR(ctinfo);
+	index = get_conntrack_index(th);
+	new_state = tcp_conntracks[dir][index][old_state];
+
+	switch (new_state) {
+	case TCP_CONNTRACK_IGNORE:
+		/* Either SYN in ORIGINAL, or SYN/ACK in REPLY direction. */
+		if (index == TCP_SYNACK_SET
+		    && conntrack->proto.tcp.last_index == TCP_SYN_SET
+		    && conntrack->proto.tcp.last_dir != dir
+		    && after(ntohl(th->ack_seq),
+		    	     conntrack->proto.tcp.last_seq)) {
+			/* This SYN/ACK acknowledges a SYN that we earlier 
+			 * ignored as invalid. This means that the client and
+			 * the server are both in sync, while the firewall is
+			 * not. We kill this session and block the SYN/ACK so
+			 * that the client cannot but retransmit its SYN and 
+			 * thus initiate a clean new session.
+			 */
+		    	WRITE_UNLOCK(&tcp_lock);
+			if (LOG_INVALID(IPPROTO_TCP))
+				nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+					  "ip_ct_tcp: killing out of sync session ");
+		    	if (del_timer(&conntrack->timeout))
+		    		conntrack->timeout.function((unsigned long)
+		    					    conntrack);
+		    	return -NF_DROP;
+		}
+		conntrack->proto.tcp.last_index = index;
+		conntrack->proto.tcp.last_dir = dir;
+		conntrack->proto.tcp.last_seq = ntohl(th->seq);
+		
+		WRITE_UNLOCK(&tcp_lock);
+		if (LOG_INVALID(IPPROTO_TCP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+				  "ip_ct_tcp: invalid SYN (ignored) ");
 		return NF_ACCEPT;
+	case TCP_CONNTRACK_MAX:
+		/* Invalid packet */
+		DEBUGP("ip_ct_tcp: Invalid dir=%i index=%u ostate=%u\n",
+		       dir, get_conntrack_index(th),
+		       old_state);
+		WRITE_UNLOCK(&tcp_lock);
+		if (LOG_INVALID(IPPROTO_TCP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+				  "ip_ct_tcp: invalid state ");
+		return -NF_ACCEPT;
+	case TCP_CONNTRACK_SYN_SENT:
+		if (old_state >= TCP_CONNTRACK_TIME_WAIT) {	
+		    	/* Attempt to reopen a closed connection.
+		    	* Delete this connection and look up again. */
+		    	WRITE_UNLOCK(&tcp_lock);
+		    	if (del_timer(&conntrack->timeout))
+		    		conntrack->timeout.function((unsigned long)
+		    					    conntrack);
+		    	return -NF_REPEAT;
+		}
+		break;
+	case TCP_CONNTRACK_CLOSE:
+		if (index == TCP_RST_SET
+		    && test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)
+		    && conntrack->proto.tcp.last_index <= TCP_SYNACK_SET
+		    && after(ntohl(th->ack_seq),
+		    	     conntrack->proto.tcp.last_seq)) {
+			/* Ignore RST closing down invalid SYN 
+			   we had let trough. */ 
+		    	WRITE_UNLOCK(&tcp_lock);
+			if (LOG_INVALID(IPPROTO_TCP))
+				nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+					  "ip_ct_tcp: invalid RST (ignored) ");
+			return NF_ACCEPT;
+		}
+		/* Just fall trough */
+	default:
+		/* Keep compilers happy. */
+		break;
 	}
 
-	WRITE_LOCK(&tcp_lock);
-	oldtcpstate = conntrack->proto.tcp.state;
-	newconntrack
-		= tcp_conntracks
-		[CTINFO2DIR(ctinfo)]
-		[get_conntrack_index(&tcph)][oldtcpstate];
-
-	/* Invalid */
-	if (newconntrack == TCP_CONNTRACK_MAX) {
-		DEBUGP("ip_conntrack_tcp: Invalid dir=%i index=%u conntrack=%u\n",
-		       CTINFO2DIR(ctinfo), get_conntrack_index(&tcph),
-		       conntrack->proto.tcp.state);
+	if (!tcp_in_window(&conntrack->proto.tcp, dir, &index, 
+			   skb, iph, th)) {
 		WRITE_UNLOCK(&tcp_lock);
-		return -1;
+		return -NF_ACCEPT;
 	}
+	/* From now on we have got in-window packets */
+	
+	/* If FIN was trimmed off, we don't change state. */
+	conntrack->proto.tcp.last_index = index;
+	new_state = tcp_conntracks[dir][index][old_state];
 
-	conntrack->proto.tcp.state = newconntrack;
-
-	/* Poor man's window tracking: record SYN/ACK for handshake check */
-	if (oldtcpstate == TCP_CONNTRACK_SYN_SENT
-	    && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
-	    && tcph.syn && tcph.ack) {
-		conntrack->proto.tcp.handshake_ack
-			= htonl(ntohl(tcph.seq) + 1);
-		goto out;
-	}
+	DEBUGP("tcp_conntracks: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
+	       "syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
+		NIPQUAD(iph->saddr), ntohs(th->source),
+		NIPQUAD(iph->daddr), ntohs(th->dest),
+		(th->syn ? 1 : 0), (th->ack ? 1 : 0),
+		(th->fin ? 1 : 0), (th->rst ? 1 : 0),
+		old_state, new_state);
 
-	/* Set ASSURED if we see valid ack in ESTABLISHED after SYN_RECV */
-	if (oldtcpstate == TCP_CONNTRACK_SYN_RECV
-	    && CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL
-	    && tcph.ack && !tcph.syn
-	    && tcph.ack_seq == conntrack->proto.tcp.handshake_ack)
-		set_bit(IPS_ASSURED_BIT, &conntrack->status);
+	conntrack->proto.tcp.state = new_state;
+	timeout = conntrack->proto.tcp.retrans >= ip_ct_tcp_max_retrans
+		  && *tcp_timeouts[new_state] > ip_ct_tcp_timeout_max_retrans
+		  ? ip_ct_tcp_timeout_max_retrans : *tcp_timeouts[new_state];
+	WRITE_UNLOCK(&tcp_lock);
 
-out:	WRITE_UNLOCK(&tcp_lock);
-	ip_ct_refresh(conntrack, *tcp_timeouts[newconntrack]);
+	if (!test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
+		/* If only reply is a RST, we can consider ourselves not to
+		   have an established connection: this is a fairly common
+		   problem case, so we can delete the conntrack
+		   immediately.  --RR */
+		if (th->rst) {
+			if (del_timer(&conntrack->timeout))
+				conntrack->timeout.function((unsigned long)
+							    conntrack);
+			return NF_ACCEPT;
+		}
+	} else if (!test_bit(IPS_ASSURED_BIT, &conntrack->status)
+		   && (old_state == TCP_CONNTRACK_SYN_RECV
+		       || old_state == TCP_CONNTRACK_ESTABLISHED)
+		   && new_state == TCP_CONNTRACK_ESTABLISHED) {
+		/* Set ASSURED if we see see valid ack in ESTABLISHED 
+		   after SYN_RECV or a valid answer for a picked up 
+		   connection. */
+			set_bit(IPS_ASSURED_BIT, &conntrack->status);
+	}
+	ip_ct_refresh_acct(conntrack, ctinfo, skb, timeout);
 
 	return NF_ACCEPT;
 }
-
-/* Called when a new connection for this protocol found. */
-static int tcp_new(struct ip_conntrack *conntrack, const struct sk_buff *skb)
+ 
+  /* Called when a new connection for this protocol found. */
+static int tcp_new(struct ip_conntrack *conntrack,
+		   const struct sk_buff *skb)
 {
-	enum tcp_conntrack newconntrack;
-	struct tcphdr tcph;
-
-	if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &tcph, sizeof(tcph)) != 0)
-		return -1;
+	enum tcp_conntrack new_state;
+	struct iphdr *iph = skb->nh.iph;
+	struct tcphdr *th, _tcph;
+#ifdef DEBUGP_VARS
+	struct ip_ct_tcp_state *sender = &conntrack->proto.tcp.seen[0];
+	struct ip_ct_tcp_state *receiver = &conntrack->proto.tcp.seen[1];
+#endif
 
+	th = skb_header_pointer(skb, iph->ihl * 4,
+				sizeof(_tcph), &_tcph);
+	BUG_ON(th == NULL);
+	
 	/* Don't need lock here: this conntrack not in circulation yet */
-	newconntrack
-		= tcp_conntracks[0][get_conntrack_index(&tcph)]
+	new_state
+		= tcp_conntracks[0][get_conntrack_index(th)]
 		[TCP_CONNTRACK_NONE];
 
 	/* Invalid: delete conntrack */
-	if (newconntrack == TCP_CONNTRACK_MAX) {
-		DEBUGP("ip_conntrack_tcp: invalid new deleting.\n");
+	if (new_state >= TCP_CONNTRACK_MAX) {
+		DEBUGP("ip_ct_tcp: invalid new deleting.\n");
+		return 0;
+	}
+
+	if (new_state == TCP_CONNTRACK_SYN_SENT) {
+		/* SYN packet */
+		conntrack->proto.tcp.seen[0].td_end =
+			segment_seq_plus_len(ntohl(th->seq), skb->len,
+					     iph, th);
+		conntrack->proto.tcp.seen[0].td_maxwin = ntohs(th->window);
+		if (conntrack->proto.tcp.seen[0].td_maxwin == 0)
+			conntrack->proto.tcp.seen[0].td_maxwin = 1;
+		conntrack->proto.tcp.seen[0].td_maxend =
+			conntrack->proto.tcp.seen[0].td_end;
+
+		tcp_options(skb, iph, th, &conntrack->proto.tcp.seen[0]);
+		conntrack->proto.tcp.seen[1].flags = 0;
+		conntrack->proto.tcp.seen[0].loose = 
+		conntrack->proto.tcp.seen[1].loose = 0;
+	} else if (ip_ct_tcp_loose == 0) {
+		/* Don't try to pick up connections. */
 		return 0;
+	} else {
+		/*
+		 * We are in the middle of a connection,
+		 * its history is lost for us.
+		 * Let's try to use the data from the packet.
+		 */
+		conntrack->proto.tcp.seen[0].td_end =
+			segment_seq_plus_len(ntohl(th->seq), skb->len,
+					     iph, th);
+		conntrack->proto.tcp.seen[0].td_maxwin = ntohs(th->window);
+		if (conntrack->proto.tcp.seen[0].td_maxwin == 0)
+			conntrack->proto.tcp.seen[0].td_maxwin = 1;
+		conntrack->proto.tcp.seen[0].td_maxend =
+			conntrack->proto.tcp.seen[0].td_end + 
+			conntrack->proto.tcp.seen[0].td_maxwin;
+		conntrack->proto.tcp.seen[0].td_scale = 0;
+
+		/* We assume SACK. Should we assume window scaling too? */
+		conntrack->proto.tcp.seen[0].flags =
+		conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM;
+		conntrack->proto.tcp.seen[0].loose = 
+		conntrack->proto.tcp.seen[1].loose = ip_ct_tcp_loose;
 	}
+    
+	conntrack->proto.tcp.seen[1].td_end = 0;
+	conntrack->proto.tcp.seen[1].td_maxend = 0;
+	conntrack->proto.tcp.seen[1].td_maxwin = 1;
+	conntrack->proto.tcp.seen[1].td_scale = 0;      
 
-	conntrack->proto.tcp.state = newconntrack;
+	/* tcp_packet will set them */
+	conntrack->proto.tcp.state = TCP_CONNTRACK_NONE;
+	conntrack->proto.tcp.last_index = TCP_NONE_SET;
+	 
+	DEBUGP("tcp_new: sender end=%u maxend=%u maxwin=%u scale=%i "
+	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
+		sender->td_end, sender->td_maxend, sender->td_maxwin,
+		sender->td_scale, 
+		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
+		receiver->td_scale);
 	return 1;
 }
-
+  
 static int tcp_exp_matches_pkt(struct ip_conntrack_expect *exp,
 			       const struct sk_buff *skb)
 {
 	const struct iphdr *iph = skb->nh.iph;
-	struct tcphdr tcph;
+	struct tcphdr *th, _tcph;
 	unsigned int datalen;
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &tcph, sizeof(tcph)) != 0)
+	th = skb_header_pointer(skb, iph->ihl * 4,
+				sizeof(_tcph), &_tcph);
+	if (th == NULL)
 		return 0;
-	datalen = skb->len - iph->ihl*4 - tcph.doff*4;
+	datalen = skb->len - iph->ihl*4 - th->doff*4;
 
-	return between(exp->seq, ntohl(tcph.seq), ntohl(tcph.seq) + datalen);
+	return between(exp->seq, ntohl(th->seq), ntohl(th->seq) + datalen);
 }
 
-struct ip_conntrack_protocol ip_conntrack_protocol_tcp
-= { { NULL, NULL }, IPPROTO_TCP, "tcp",
-    tcp_pkt_to_tuple, tcp_invert_tuple, tcp_print_tuple, tcp_print_conntrack,
-    tcp_packet, tcp_new, NULL, tcp_exp_matches_pkt, NULL };
+struct ip_conntrack_protocol ip_conntrack_protocol_tcp =
+{
+	.proto 			= IPPROTO_TCP,
+	.name 			= "tcp",
+	.pkt_to_tuple 		= tcp_pkt_to_tuple,
+	.invert_tuple 		= tcp_invert_tuple,
+	.print_tuple 		= tcp_print_tuple,
+	.print_conntrack 	= tcp_print_conntrack,
+	.packet 		= tcp_packet,
+	.new 			= tcp_new,
+	.exp_matches_pkt	= tcp_exp_matches_pkt,
+	.error			= tcp_error,
+};
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
index a63c32d18..5bc28a224 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
@@ -12,6 +12,10 @@
 #include <linux/netfilter.h>
 #include <linux/in.h>
 #include <linux/udp.h>
+#include <linux/seq_file.h>
+#include <net/checksum.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
 
 unsigned long ip_ct_udp_timeout = 30*HZ;
@@ -21,14 +25,15 @@ static int udp_pkt_to_tuple(const struct sk_buff *skb,
 			     unsigned int dataoff,
 			     struct ip_conntrack_tuple *tuple)
 {
-	struct udphdr hdr;
+	struct udphdr _hdr, *hp;
 
 	/* Actually only need first 8 bytes. */
-	if (skb_copy_bits(skb, dataoff, &hdr, 8) != 0)
+	hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
+	if (hp == NULL)
 		return 0;
 
-	tuple->src.u.udp.port = hdr.source;
-	tuple->dst.u.udp.port = hdr.dest;
+	tuple->src.u.udp.port = hp->source;
+	tuple->dst.u.udp.port = hp->dest;
 
 	return 1;
 }
@@ -42,17 +47,17 @@ static int udp_invert_tuple(struct ip_conntrack_tuple *tuple,
 }
 
 /* Print out the per-protocol part of the tuple. */
-static unsigned int udp_print_tuple(char *buffer,
-				    const struct ip_conntrack_tuple *tuple)
+static int udp_print_tuple(struct seq_file *s,
+			   const struct ip_conntrack_tuple *tuple)
 {
-	return sprintf(buffer, "sport=%hu dport=%hu ",
-		       ntohs(tuple->src.u.udp.port),
-		       ntohs(tuple->dst.u.udp.port));
+	return seq_printf(s, "sport=%hu dport=%hu ",
+			  ntohs(tuple->src.u.udp.port),
+			  ntohs(tuple->dst.u.udp.port));
 }
 
 /* Print out the private part of the conntrack. */
-static unsigned int udp_print_conntrack(char *buffer,
-					const struct ip_conntrack *conntrack)
+static int udp_print_conntrack(struct seq_file *s,
+			       const struct ip_conntrack *conntrack)
 {
 	return 0;
 }
@@ -60,16 +65,17 @@ static unsigned int udp_print_conntrack(char *buffer,
 /* Returns verdict for packet, and may modify conntracktype */
 static int udp_packet(struct ip_conntrack *conntrack,
 		      const struct sk_buff *skb,
-		      enum ip_conntrack_info conntrackinfo)
+		      enum ip_conntrack_info ctinfo)
 {
 	/* If we've seen traffic both ways, this is some kind of UDP
 	   stream.  Extend timeout. */
 	if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
-		ip_ct_refresh(conntrack, ip_ct_udp_timeout_stream);
+		ip_ct_refresh_acct(conntrack, ctinfo, skb, 
+				   ip_ct_udp_timeout_stream);
 		/* Also, more likely to be important, and not a probe */
 		set_bit(IPS_ASSURED_BIT, &conntrack->status);
 	} else
-		ip_ct_refresh(conntrack, ip_ct_udp_timeout);
+		ip_ct_refresh_acct(conntrack, ctinfo, skb, ip_ct_udp_timeout);
 
 	return NF_ACCEPT;
 }
@@ -80,7 +86,61 @@ static int udp_new(struct ip_conntrack *conntrack, const struct sk_buff *skb)
 	return 1;
 }
 
-struct ip_conntrack_protocol ip_conntrack_protocol_udp
-= { { NULL, NULL }, IPPROTO_UDP, "udp",
-    udp_pkt_to_tuple, udp_invert_tuple, udp_print_tuple, udp_print_conntrack,
-    udp_packet, udp_new, NULL, NULL, NULL };
+static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
+		     unsigned int hooknum)
+{
+	struct iphdr *iph = skb->nh.iph;
+	unsigned int udplen = skb->len - iph->ihl * 4;
+	struct udphdr _hdr, *hdr;
+
+	/* Header is too small? */
+	hdr = skb_header_pointer(skb, iph->ihl*4, sizeof(_hdr), &_hdr);
+	if (hdr == NULL) {
+		if (LOG_INVALID(IPPROTO_UDP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+				  "ip_ct_udp: short packet ");
+		return -NF_ACCEPT;
+	}
+	
+	/* Truncated/malformed packets */
+	if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) {
+		if (LOG_INVALID(IPPROTO_UDP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+				  "ip_ct_udp: truncated/malformed packet ");
+		return -NF_ACCEPT;
+	}
+	
+	/* Packet with no checksum */
+	if (!hdr->check)
+		return NF_ACCEPT;
+
+	/* Checksum invalid? Ignore.
+	 * We skip checking packets on the outgoing path
+	 * because the semantic of CHECKSUM_HW is different there 
+	 * and moreover root might send raw packets.
+	 * FIXME: Source route IP option packets --RR */
+	if (hooknum == NF_IP_PRE_ROUTING
+	    && csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
+			         skb->ip_summed == CHECKSUM_HW ? skb->csum
+			      	 : skb_checksum(skb, iph->ihl*4, udplen, 0))) {
+		if (LOG_INVALID(IPPROTO_UDP))
+			nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
+				  "ip_ct_udp: bad UDP checksum ");
+		return -NF_ACCEPT;
+	}
+	
+	return NF_ACCEPT;
+}
+
+struct ip_conntrack_protocol ip_conntrack_protocol_udp =
+{
+	.proto 			= IPPROTO_UDP,
+	.name			= "udp",
+	.pkt_to_tuple		= udp_pkt_to_tuple,
+	.invert_tuple		= udp_invert_tuple,
+	.print_tuple		= udp_print_tuple,
+	.print_conntrack	= udp_print_conntrack,
+	.packet			= udp_packet,
+	.new			= udp_new,
+	.error			= udp_error,
+};
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 80edac904..9abaf01a7 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -20,6 +20,8 @@
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/percpu.h>
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
 #endif
@@ -43,148 +45,314 @@
 
 MODULE_LICENSE("GPL");
 
+extern atomic_t ip_conntrack_count;
+DECLARE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat);
+
 static int kill_proto(const struct ip_conntrack *i, void *data)
 {
 	return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == 
 			*((u_int8_t *) data));
 }
 
-static unsigned int
-print_tuple(char *buffer, const struct ip_conntrack_tuple *tuple,
+#ifdef CONFIG_PROC_FS
+static int
+print_tuple(struct seq_file *s, const struct ip_conntrack_tuple *tuple,
 	    struct ip_conntrack_protocol *proto)
 {
-	int len;
-
-	len = sprintf(buffer, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",
-		      NIPQUAD(tuple->src.ip), NIPQUAD(tuple->dst.ip));
-
-	len += proto->print_tuple(buffer + len, tuple);
-
-	return len;
+	seq_printf(s, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",
+		   NIPQUAD(tuple->src.ip), NIPQUAD(tuple->dst.ip));
+	return proto->print_tuple(s, tuple);
 }
 
-/* FIXME: Don't print source proto part. --RR */
+#ifdef CONFIG_IP_NF_CT_ACCT
 static unsigned int
-print_expect(char *buffer, const struct ip_conntrack_expect *expect)
+seq_print_counters(struct seq_file *s, struct ip_conntrack_counter *counter)
 {
-	unsigned int len;
+	return seq_printf(s, "packets=%llu bytes=%llu ",
+			  (unsigned long long)counter->packets,
+			  (unsigned long long)counter->bytes);
+}
+#else
+#define seq_print_counters(x, y)	0
+#endif
 
-	if (expect->expectant->helper->timeout)
-		len = sprintf(buffer, "EXPECTING: %lu ",
-			      timer_pending(&expect->timeout)
-			      ? (expect->timeout.expires - jiffies)/HZ : 0);
-	else
-		len = sprintf(buffer, "EXPECTING: - ");
-	len += sprintf(buffer + len, "use=%u proto=%u ",
-		      atomic_read(&expect->use), expect->tuple.dst.protonum);
-	len += print_tuple(buffer + len, &expect->tuple,
-			   __ip_ct_find_proto(expect->tuple.dst.protonum));
-	len += sprintf(buffer + len, "\n");
-	return len;
+static void *ct_seq_start(struct seq_file *s, loff_t *pos)
+{
+	if (*pos >= ip_conntrack_htable_size)
+		return NULL;
+	return &ip_conntrack_hash[*pos];
+}
+  
+static void ct_seq_stop(struct seq_file *s, void *v)
+{
 }
 
-static unsigned int
-print_conntrack(char *buffer, struct ip_conntrack *conntrack)
+static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
-	unsigned int len;
-	struct ip_conntrack_protocol *proto
-		= __ip_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
+	(*pos)++;
+	if (*pos >= ip_conntrack_htable_size)
+		return NULL;
+	return &ip_conntrack_hash[*pos];
+}
+  
+/* return 0 on success, 1 in case of error */
+static int ct_seq_real_show(const struct ip_conntrack_tuple_hash *hash,
+			    struct seq_file *s)
+{
+	struct ip_conntrack *conntrack = hash->ctrack;
+	struct ip_conntrack_protocol *proto;
+
+	MUST_BE_READ_LOCKED(&ip_conntrack_lock);
+
+	IP_NF_ASSERT(conntrack);
+
+	/* we only want to print DIR_ORIGINAL */
+	if (DIRECTION(hash))
+		return 0;
+
+	proto = ip_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
 			       .tuple.dst.protonum);
+	IP_NF_ASSERT(proto);
 
-	len = sprintf(buffer, "%-8s %u %lu ",
+	if (seq_printf(s, "%-8s %u %lu ",
 		      proto->name,
-		      conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
-		      .tuple.dst.protonum,
+		      conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
 		      timer_pending(&conntrack->timeout)
-		      ? (conntrack->timeout.expires - jiffies)/HZ : 0);
+		      ? (conntrack->timeout.expires - jiffies)/HZ : 0) != 0)
+		return 1;
 
-	len += proto->print_conntrack(buffer + len, conntrack);
-	len += print_tuple(buffer + len,
-			   &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
-			   proto);
-	if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
-		len += sprintf(buffer + len, "[UNREPLIED] ");
-	len += print_tuple(buffer + len,
-			   &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
-			   proto);
-	if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
-		len += sprintf(buffer + len, "[ASSURED] ");
-	len += sprintf(buffer + len, "use=%u ",
-		       atomic_read(&conntrack->ct_general.use));
-	len += sprintf(buffer + len, "\n");
+	if (proto->print_conntrack(s, conntrack))
+		return 1;
+  
+	if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
+			proto))
+		return 1;
 
-	return len;
-}
+ 	if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_ORIGINAL]))
+		return 1;
 
-/* Returns true when finished. */
-static inline int
-conntrack_iterate(const struct ip_conntrack_tuple_hash *hash,
-		  char *buffer, off_t offset, off_t *upto,
-		  unsigned int *len, unsigned int maxlen)
-{
-	unsigned int newlen;
-	IP_NF_ASSERT(hash->ctrack);
+	if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
+		if (seq_printf(s, "[UNREPLIED] "))
+			return 1;
 
-	MUST_BE_READ_LOCKED(&ip_conntrack_lock);
+	if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
+			proto))
+		return 1;
 
-	/* Only count originals */
-	if (DIRECTION(hash))
-		return 0;
+ 	if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_REPLY]))
+		return 1;
 
-	if ((*upto)++ < offset)
-		return 0;
+	if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
+		if (seq_printf(s, "[ASSURED] "))
+			return 1;
 
-	newlen = print_conntrack(buffer + *len, hash->ctrack);
-	if (*len + newlen > maxlen)
+	if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
 		return 1;
-	else *len += newlen;
 
 	return 0;
 }
 
-static int
-list_conntracks(char *buffer, char **start, off_t offset, int length)
+static int ct_seq_show(struct seq_file *s, void *v)
 {
-	unsigned int i;
-	unsigned int len = 0;
-	off_t upto = 0;
-	struct list_head *e;
+	struct list_head *list = v;
+	int ret = 0;
 
+	/* FIXME: Simply truncates if hash chain too long. */
 	READ_LOCK(&ip_conntrack_lock);
-	/* Traverse hash; print originals then reply. */
-	for (i = 0; i < ip_conntrack_htable_size; i++) {
-		if (LIST_FIND(&ip_conntrack_hash[i], conntrack_iterate,
-			      struct ip_conntrack_tuple_hash *,
-			      buffer, offset, &upto, &len, length))
-			goto finished;
-	}
+	if (LIST_FIND(list, ct_seq_real_show,
+		      struct ip_conntrack_tuple_hash *, s))
+		ret = -ENOSPC;
+	READ_UNLOCK(&ip_conntrack_lock);
+	return ret;
+}
+	
+static struct seq_operations ct_seq_ops = {
+	.start = ct_seq_start,
+	.next  = ct_seq_next,
+	.stop  = ct_seq_stop,
+	.show  = ct_seq_show
+};
+  
+static int ct_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &ct_seq_ops);
+}
+
+static struct file_operations ct_file_ops = {
+	.owner   = THIS_MODULE,
+	.open    = ct_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release
+};
+  
+/* expects */
+static void *exp_seq_start(struct seq_file *s, loff_t *pos)
+{
+	struct list_head *e = &ip_conntrack_expect_list;
+	loff_t i;
 
-	/* Now iterate through expecteds. */
+	/* strange seq_file api calls stop even if we fail,
+	 * thus we need to grab lock since stop unlocks */
+	READ_LOCK(&ip_conntrack_lock);
 	READ_LOCK(&ip_conntrack_expect_tuple_lock);
-	list_for_each(e, &ip_conntrack_expect_list) {
-		unsigned int last_len;
-		struct ip_conntrack_expect *expect
-			= (struct ip_conntrack_expect *)e;
-		if (upto++ < offset) continue;
-
-		last_len = len;
-		len += print_expect(buffer + len, expect);
-		if (len > length) {
-			len = last_len;
-			goto finished_expects;
-		}
+
+	if (list_empty(e))
+		return NULL;
+
+	for (i = 0; i <= *pos; i++) {
+		e = e->next;
+		if (e == &ip_conntrack_expect_list)
+			return NULL;
 	}
+	return e;
+}
 
- finished_expects:
+static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ 	struct list_head *e = v;
+
+	e = e->next;
+
+	if (e == &ip_conntrack_expect_list)
+		return NULL;
+
+	return e;
+}
+
+static void exp_seq_stop(struct seq_file *s, void *v)
+{
 	READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
- finished:
 	READ_UNLOCK(&ip_conntrack_lock);
+}
+
+static int exp_seq_show(struct seq_file *s, void *v)
+{
+	struct ip_conntrack_expect *expect = v;
 
-	/* `start' hack - see fs/proc/generic.c line ~165 */
-	*start = (char *)((unsigned int)upto - offset);
-	return len;
+	if (expect->expectant->helper->timeout)
+		seq_printf(s, "%lu ", timer_pending(&expect->timeout)
+			   ? (expect->timeout.expires - jiffies)/HZ : 0);
+	else
+		seq_printf(s, "- ");
+
+	seq_printf(s, "use=%u proto=%u ", atomic_read(&expect->use),
+		   expect->tuple.dst.protonum);
+
+	print_tuple(s, &expect->tuple,
+		    ip_ct_find_proto(expect->tuple.dst.protonum));
+	return seq_putc(s, '\n');
 }
 
+static struct seq_operations exp_seq_ops = {
+	.start = exp_seq_start,
+	.next = exp_seq_next,
+	.stop = exp_seq_stop,
+	.show = exp_seq_show
+};
+
+static int exp_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &exp_seq_ops);
+}
+  
+static struct file_operations exp_file_ops = {
+	.owner   = THIS_MODULE,
+	.open    = exp_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release
+};
+
+static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	int cpu;
+
+	if (*pos == 0)
+		return SEQ_START_TOKEN;
+
+	for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) {
+		if (!cpu_possible(cpu))
+			continue;
+		*pos = cpu+1;
+		return &per_cpu(ip_conntrack_stat, cpu);
+	}
+
+	return NULL;
+}
+
+static void *ct_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	int cpu;
+
+	for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
+		if (!cpu_possible(cpu))
+			continue;
+		*pos = cpu+1;
+		return &per_cpu(ip_conntrack_stat, cpu);
+	}
+
+	return NULL;
+}
+
+static void ct_cpu_seq_stop(struct seq_file *seq, void *v)
+{
+}
+
+static int ct_cpu_seq_show(struct seq_file *seq, void *v)
+{
+	unsigned int nr_conntracks = atomic_read(&ip_conntrack_count);
+	struct ip_conntrack_stat *st = v;
+
+	if (v == SEQ_START_TOKEN) {
+		seq_printf(seq, "entries  searched found new invalid ignore delete delete_list insert insert_failed drop early_drop icmp_error  expect_new expect_create expect_delete\n");
+		return 0;
+	}
+
+	seq_printf(seq, "%08x  %08x %08x %08x %08x %08x %08x %08x "
+			"%08x %08x %08x %08x %08x  %08x %08x %08x \n",
+		   nr_conntracks,
+		   st->searched,
+		   st->found,
+		   st->new,
+		   st->invalid,
+		   st->ignore,
+		   st->delete,
+		   st->delete_list,
+		   st->insert,
+		   st->insert_failed,
+		   st->drop,
+		   st->early_drop,
+		   st->error,
+
+		   st->expect_new,
+		   st->expect_create,
+		   st->expect_delete
+		);
+	return 0;
+}
+
+static struct seq_operations ct_cpu_seq_ops = {
+	.start  = ct_cpu_seq_start,
+	.next   = ct_cpu_seq_next,
+	.stop   = ct_cpu_seq_stop,
+	.show   = ct_cpu_seq_show,
+};
+
+static int ct_cpu_seq_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &ct_cpu_seq_ops);
+}
+
+static struct file_operations ct_cpu_seq_fops = {
+	.owner   = THIS_MODULE,
+	.open    = ct_cpu_seq_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release_private,
+};
+#endif
+
 static unsigned int ip_confirm(unsigned int hooknum,
 			       struct sk_buff **pskb,
 			       const struct net_device *in,
@@ -323,6 +491,10 @@ extern unsigned long ip_ct_tcp_timeout_close_wait;
 extern unsigned long ip_ct_tcp_timeout_last_ack;
 extern unsigned long ip_ct_tcp_timeout_time_wait;
 extern unsigned long ip_ct_tcp_timeout_close;
+extern unsigned long ip_ct_tcp_timeout_max_retrans;
+extern int ip_ct_tcp_loose;
+extern int ip_ct_tcp_be_liberal;
+extern int ip_ct_tcp_max_retrans;
 
 /* From ip_conntrack_proto_udp.c */
 extern unsigned long ip_ct_udp_timeout;
@@ -334,6 +506,10 @@ extern unsigned long ip_ct_icmp_timeout;
 /* From ip_conntrack_proto_icmp.c */
 extern unsigned long ip_ct_generic_timeout;
 
+/* Log invalid packets of a given protocol */
+static int log_invalid_proto_min = 0;
+static int log_invalid_proto_max = 255;
+
 static struct ctl_table_header *ip_ct_sysctl_header;
 
 static ctl_table ip_ct_sysctl_table[] = {
@@ -345,6 +521,14 @@ static ctl_table ip_ct_sysctl_table[] = {
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
 	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_COUNT,
+		.procname	= "ip_conntrack_count",
+		.data		= &ip_conntrack_count,
+		.maxlen		= sizeof(int),
+		.mode		= 0444,
+		.proc_handler	= &proc_dointvec,
+	},
 	{
 		.ctl_name	= NET_IPV4_NF_CONNTRACK_BUCKETS,
 		.procname	= "ip_conntrack_buckets",
@@ -449,6 +633,49 @@ static ctl_table ip_ct_sysctl_table[] = {
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec_jiffies,
 	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_LOG_INVALID,
+		.procname	= "ip_conntrack_log_invalid",
+		.data		= &ip_ct_log_invalid,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &log_invalid_proto_min,
+		.extra2		= &log_invalid_proto_max,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS,
+		.procname	= "ip_conntrack_tcp_timeout_max_retrans",
+		.data		= &ip_ct_tcp_timeout_max_retrans,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_LOOSE,
+		.procname	= "ip_conntrack_tcp_loose",
+		.data		= &ip_ct_tcp_loose,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_BE_LIBERAL,
+		.procname	= "ip_conntrack_tcp_be_liberal",
+		.data		= &ip_ct_tcp_be_liberal,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_MAX_RETRANS,
+		.procname	= "ip_conntrack_tcp_max_retrans",
+		.data		= &ip_ct_tcp_max_retrans,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
 	{ .ctl_name = 0 }
 };
 
@@ -491,10 +718,15 @@ static ctl_table ip_ct_net_table[] = {
 	},
 	{ .ctl_name = 0 }
 };
-#endif
+
+EXPORT_SYMBOL(ip_ct_log_invalid);
+#endif /* CONFIG_SYSCTL */
+
 static int init_or_cleanup(int init)
 {
-	struct proc_dir_entry *proc;
+#ifdef CONFIG_PROC_FS
+	struct proc_dir_entry *proc, *proc_exp, *proc_stat;
+#endif
 	int ret = 0;
 
 	if (!init) goto cleanup;
@@ -503,14 +735,26 @@ static int init_or_cleanup(int init)
 	if (ret < 0)
 		goto cleanup_nothing;
 
-	proc = proc_net_create("ip_conntrack", 0440, list_conntracks);
+#ifdef CONFIG_PROC_FS
+	proc = proc_net_fops_create("ip_conntrack", 0440, &ct_file_ops);
 	if (!proc) goto cleanup_init;
-	proc->owner = THIS_MODULE;
+
+	proc_exp = proc_net_fops_create("ip_conntrack_expect", 0440,
+					&exp_file_ops);
+	if (!proc_exp) goto cleanup_proc;
+
+	proc_stat = create_proc_entry("ip_conntrack", S_IRUGO, proc_net_stat);
+	if (!proc_stat)
+		goto cleanup_proc_exp;
+
+	proc_stat->proc_fops = &ct_cpu_seq_fops;
+	proc_stat->owner = THIS_MODULE;
+#endif
 
 	ret = nf_register_hook(&ip_conntrack_defrag_ops);
 	if (ret < 0) {
 		printk("ip_conntrack: can't register pre-routing defrag hook.\n");
-		goto cleanup_proc;
+		goto cleanup_proc_stat;
 	}
 	ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
 	if (ret < 0) {
@@ -561,10 +805,22 @@ static int init_or_cleanup(int init)
  cleanup_defraglocalops:
 	nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
  cleanup_defragops:
+	/* Frag queues may hold fragments with skb->dst == NULL */
+	ip_ct_no_defrag = 1;
+	synchronize_net();
+	local_bh_disable();
+	ipfrag_flush();
+	local_bh_enable();
 	nf_unregister_hook(&ip_conntrack_defrag_ops);
+ cleanup_proc_stat:
+#ifdef CONFIG_PROC_FS
+	proc_net_remove("ip_conntrack_stat");
+cleanup_proc_exp:
+	proc_net_remove("ip_conntrack_exp");
  cleanup_proc:
 	proc_net_remove("ip_conntrack");
  cleanup_init:
+#endif /* CONFIG_PROC_FS */
 	ip_conntrack_cleanup();
  cleanup_nothing:
 	return ret;
@@ -575,19 +831,13 @@ static int init_or_cleanup(int init)
 int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
 {
 	int ret = 0;
-	struct list_head *i;
 
 	WRITE_LOCK(&ip_conntrack_lock);
-	list_for_each(i, &protocol_list) {
-		if (((struct ip_conntrack_protocol *)i)->proto
-		    == proto->proto) {
-			ret = -EBUSY;
-			goto out;
-		}
+	if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) {
+		ret = -EBUSY;
+		goto out;
 	}
-
-	list_prepend(&protocol_list, proto);
-
+	ip_ct_protos[proto->proto] = proto;
  out:
 	WRITE_UNLOCK(&ip_conntrack_lock);
 	return ret;
@@ -596,10 +846,7 @@ int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
 void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
 {
 	WRITE_LOCK(&ip_conntrack_lock);
-
-	/* ip_ct_find_proto() returns proto_generic in case there is no protocol 
-	 * helper. So this should be enough - HW */
-	LIST_DELETE(&protocol_list, proto);
+	ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol;
 	WRITE_UNLOCK(&ip_conntrack_lock);
 	
 	/* Somebody could be still looking at the proto in bh. */
@@ -633,14 +880,13 @@ EXPORT_SYMBOL(ip_conntrack_protocol_unregister);
 EXPORT_SYMBOL(invert_tuplepr);
 EXPORT_SYMBOL(ip_conntrack_alter_reply);
 EXPORT_SYMBOL(ip_conntrack_destroyed);
-EXPORT_SYMBOL(ip_conntrack_get);
 EXPORT_SYMBOL(need_ip_conntrack);
 EXPORT_SYMBOL(ip_conntrack_helper_register);
 EXPORT_SYMBOL(ip_conntrack_helper_unregister);
 EXPORT_SYMBOL(ip_ct_selective_cleanup);
-EXPORT_SYMBOL(ip_ct_refresh);
+EXPORT_SYMBOL(ip_ct_refresh_acct);
+EXPORT_SYMBOL(ip_ct_protos);
 EXPORT_SYMBOL(ip_ct_find_proto);
-EXPORT_SYMBOL(__ip_ct_find_proto);
 EXPORT_SYMBOL(ip_ct_find_helper);
 EXPORT_SYMBOL(ip_conntrack_expect_alloc);
 EXPORT_SYMBOL(ip_conntrack_expect_related);
diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c
index ddee73782..d132a3c48 100644
--- a/net/ipv4/netfilter/ip_conntrack_tftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_tftp.c
@@ -19,6 +19,7 @@
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_conntrack_tftp.h>
+#include <linux/moduleparam.h>
 
 MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>");
 MODULE_DESCRIPTION("tftp connection tracking helper");
@@ -27,7 +28,7 @@ MODULE_LICENSE("GPL");
 #define MAX_PORTS 8
 static int ports[MAX_PORTS];
 static int ports_c;
-MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
+module_param_array(ports, int, ports_c, 0400);
 MODULE_PARM_DESC(ports, "port numbers of tftp servers");
 
 #if 0
@@ -41,14 +42,16 @@ static int tftp_help(struct sk_buff *skb,
 		     struct ip_conntrack *ct,
 		     enum ip_conntrack_info ctinfo)
 {
-	struct tftphdr tftph;
+	struct tftphdr _tftph, *tfh;
 	struct ip_conntrack_expect *exp;
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl * 4 + sizeof(struct udphdr),
-			  &tftph, sizeof(tftph)) != 0)
+	tfh = skb_header_pointer(skb,
+				 skb->nh.iph->ihl * 4 + sizeof(struct udphdr),
+				 sizeof(_tftph), &_tftph);
+	if (tfh == NULL)
 		return NF_ACCEPT;
 
-	switch (ntohs(tftph.opcode)) {
+	switch (ntohs(tfh->opcode)) {
 	/* RRQ and WRQ works the same way */
 	case TFTP_OPCODE_READ:
 	case TFTP_OPCODE_WRITE:
@@ -104,10 +107,10 @@ static int __init init(void)
 	int i, ret;
 	char *tmpname;
 
-	if (!ports[0])
-		ports[0]=TFTP_PORT;
+	if (ports_c == 0)
+		ports[ports_c++] = TFTP_PORT;
 
-	for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
+	for (i = 0; i < ports_c; i++) {
 		/* Create helper structure */
 		memset(&tftp[i], 0, sizeof(struct ip_conntrack_helper));
 
@@ -137,7 +140,6 @@ static int __init init(void)
 			fini();
 			return(ret);
 		}
-		ports_c++;
 	}
 	return(0);
 }
diff --git a/net/ipv4/netfilter/ip_fw_compat_masq.c b/net/ipv4/netfilter/ip_fw_compat_masq.c
index fbd8b9bfe..07fc794c1 100644
--- a/net/ipv4/netfilter/ip_fw_compat_masq.c
+++ b/net/ipv4/netfilter/ip_fw_compat_masq.c
@@ -31,6 +31,7 @@
 
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 #include <linux/netfilter_ipv4/ip_conntrack_core.h>
+#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
 #include <linux/netfilter_ipv4/ip_nat.h>
 #include <linux/netfilter_ipv4/ip_nat_core.h>
 #include <linux/netfilter_ipv4/listhelp.h>
@@ -144,7 +145,8 @@ check_for_demasq(struct sk_buff **pskb)
 	switch ((*pskb)->nh.iph->protocol) {
 	case IPPROTO_ICMP:
 		/* ICMP errors. */
-		ct = icmp_error_track(*pskb, &ctinfo, NF_IP_PRE_ROUTING);
+		protocol->error(*pskb, &ctinfo, NF_IP_PRE_ROUTING);
+		ct = (struct ip_conntrack *)(*pskb)->nfct;
 		if (ct) {
 			/* We only do SNAT in the compatibility layer.
 			   So we can manipulate ICMP errors from
@@ -165,7 +167,8 @@ check_for_demasq(struct sk_buff **pskb)
 	case IPPROTO_UDP:
 		IP_NF_ASSERT(((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) == 0);
 
-		if (!get_tuple((*pskb)->nh.iph, *pskb, (*pskb)->nh.iph->ihl*4, &tuple, protocol)) {
+		if (!ip_ct_get_tuple((*pskb)->nh.iph, *pskb,
+				     (*pskb)->nh.iph->ihl*4, &tuple, protocol)) {
 			if (net_ratelimit())
 				printk("ip_fw_compat_masq: Can't get tuple\n");
 			return NF_ACCEPT;
@@ -184,7 +187,7 @@ check_for_demasq(struct sk_buff **pskb)
 				      NULL, NULL, NULL);
 
 		/* Put back the reference gained from find_get */
-		nf_conntrack_put(&h->ctrack->infos[0]);
+		nf_conntrack_put(&h->ctrack->ct_general);
 		if (ret == NF_ACCEPT) {
 			struct ip_conntrack *ct;
 			ct = ip_conntrack_get(*pskb, &ctinfo);
@@ -203,7 +206,7 @@ check_for_demasq(struct sk_buff **pskb)
 	} else {
 		if (h)
 			/* Put back the reference gained from find_get */
-			nf_conntrack_put(&h->ctrack->infos[0]);
+			nf_conntrack_put(&h->ctrack->ct_general);
 		ret = NF_ACCEPT;
 	}
 
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index 1c6b78106..1ecc3f285 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -48,10 +48,8 @@ static unsigned int ip_nat_htable_size;
 
 static struct list_head *bysource;
 static struct list_head *byipsproto;
-LIST_HEAD(protos);
-LIST_HEAD(helpers);
+struct ip_nat_protocol *ip_nat_protos[MAX_IP_NAT_PROTO];
 
-extern struct ip_nat_protocol unknown_nat_protocol;
 
 /* We keep extra hashes for each conntrack, for fast searching. */
 static inline size_t
@@ -78,9 +76,6 @@ static void ip_nat_cleanup_conntrack(struct ip_conntrack *conn)
 	if (!info->initialized)
 		return;
 
-	IP_NF_ASSERT(info->bysource.conntrack);
-	IP_NF_ASSERT(info->byipsproto.conntrack);
-
 	hs = hash_by_src(&conn->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src,
 	                 conn->tuplehash[IP_CT_DIR_ORIGINAL]
 	                 .tuple.dst.protonum);
@@ -91,8 +86,8 @@ static void ip_nat_cleanup_conntrack(struct ip_conntrack *conn)
 	                      .tuple.dst.protonum);
 
 	WRITE_LOCK(&ip_nat_lock);
-	LIST_DELETE(&bysource[hs], &info->bysource);
-	LIST_DELETE(&byipsproto[hp], &info->byipsproto);
+	list_del(&info->bysource);
+	list_del(&info->byipsproto);
 	WRITE_UNLOCK(&ip_nat_lock);
 }
 
@@ -107,23 +102,6 @@ ip_nat_cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck)
 				      oldcheck^0xFFFF));
 }
 
-static inline int cmp_proto(const struct ip_nat_protocol *i, int proto)
-{
-	return i->protonum == proto;
-}
-
-struct ip_nat_protocol *
-find_nat_proto(u_int16_t protonum)
-{
-	struct ip_nat_protocol *i;
-
-	MUST_BE_READ_LOCKED(&ip_nat_lock);
-	i = LIST_FIND(&protos, cmp_proto, struct ip_nat_protocol *, protonum);
-	if (!i)
-		i = &unknown_nat_protocol;
-	return i;
-}
-
 /* Is this tuple already taken? (not by us) */
 int
 ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
@@ -146,7 +124,7 @@ in_range(const struct ip_conntrack_tuple *tuple,
 	 const struct ip_conntrack_manip *manip,
 	 const struct ip_nat_multi_range *mr)
 {
-	struct ip_nat_protocol *proto = find_nat_proto(tuple->dst.protonum);
+	struct ip_nat_protocol *proto = ip_nat_find_proto(tuple->dst.protonum);
 	unsigned int i;
 	struct ip_conntrack_tuple newtuple = { *manip, tuple->dst };
 
@@ -172,20 +150,18 @@ in_range(const struct ip_conntrack_tuple *tuple,
 }
 
 static inline int
-src_cmp(const struct ip_nat_hash *i,
+src_cmp(const struct ip_conntrack *ct,
 	const struct ip_conntrack_tuple *tuple,
 	const struct ip_nat_multi_range *mr)
 {
-	return (i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum
+	return (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum
 		== tuple->dst.protonum
-		&& i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip
+		&& ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip
 		== tuple->src.ip
-		&& i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.all
+		&& ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.all
 		== tuple->src.u.all
 		&& in_range(tuple,
-			    &i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
-			    .tuple.src,
-			    mr));
+			    &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src, mr));
 }
 
 /* Only called for SRC manip */
@@ -194,14 +170,13 @@ find_appropriate_src(const struct ip_conntrack_tuple *tuple,
 		     const struct ip_nat_multi_range *mr)
 {
 	unsigned int h = hash_by_src(&tuple->src, tuple->dst.protonum);
-	struct ip_nat_hash *i;
+	struct ip_conntrack *ct;
 
 	MUST_BE_READ_LOCKED(&ip_nat_lock);
-	i = LIST_FIND(&bysource[h], src_cmp, struct ip_nat_hash *, tuple, mr);
-	if (i)
-		return &i->conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src;
-	else
-		return NULL;
+	list_for_each_entry(ct, &bysource[h], nat.info.bysource)
+		if (src_cmp(ct, tuple, mr))
+			return &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src;
+	return NULL;
 }
 
 #ifdef CONFIG_IP_NF_NAT_LOCAL
@@ -227,19 +202,17 @@ do_extra_mangle(u_int32_t var_ip, u_int32_t *other_ipp)
 #endif
 
 /* Simple way to iterate through all. */
-static inline int fake_cmp(const struct ip_nat_hash *i,
+static inline int fake_cmp(const struct ip_conntrack *ct,
 			   u_int32_t src, u_int32_t dst, u_int16_t protonum,
-			   unsigned int *score,
-			   const struct ip_conntrack *conntrack)
+			   unsigned int *score, const struct ip_conntrack *ct2)
 {
 	/* Compare backwards: we're dealing with OUTGOING tuples, and
            inside the conntrack is the REPLY tuple.  Don't count this
            conntrack. */
-	if (i->conntrack != conntrack
-	    && i->conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip == dst
-	    && i->conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip == src
-	    && (i->conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum
-		== protonum))
+	if (ct != ct2
+	    && ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip == dst
+	    && ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip == src
+	    && (ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum == protonum))
 		(*score)++;
 	return 0;
 }
@@ -248,13 +221,14 @@ static inline unsigned int
 count_maps(u_int32_t src, u_int32_t dst, u_int16_t protonum,
 	   const struct ip_conntrack *conntrack)
 {
+	struct ip_conntrack *ct;
 	unsigned int score = 0;
 	unsigned int h;
 
 	MUST_BE_READ_LOCKED(&ip_nat_lock);
 	h = hash_by_ipsproto(src, dst, protonum);
-	LIST_FIND(&byipsproto[h], fake_cmp, struct ip_nat_hash *,
-	          src, dst, protonum, &score, conntrack);
+	list_for_each_entry(ct, &byipsproto[h], nat.info.byipsproto)
+		fake_cmp(ct, src, dst, protonum, &score, conntrack);
 
 	return score;
 }
@@ -402,7 +376,7 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple,
 		 unsigned int hooknum)
 {
 	struct ip_nat_protocol *proto
-		= find_nat_proto(orig_tuple->dst.protonum);
+		= ip_nat_find_proto(orig_tuple->dst.protonum);
 	struct ip_nat_range *rptr;
 	unsigned int i;
 	int ret;
@@ -498,13 +472,6 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple,
 	return ret;
 }
 
-static inline int
-helper_cmp(const struct ip_nat_helper *helper,
-	   const struct ip_conntrack_tuple *tuple)
-{
-	return ip_ct_tuple_mask_cmp(tuple, &helper->tuple, &helper->mask);
-}
-
 /* Where to manip the reply packets (will be reverse manip). */
 static unsigned int opposite_hook[NF_IP_NUMHOOKS]
 = { [NF_IP_PRE_ROUTING] = NF_IP_POST_ROUTING,
@@ -643,18 +610,15 @@ ip_nat_setup_info(struct ip_conntrack *conntrack,
 
 	/* If there's a helper, assign it; based on new tuple. */
 	if (!conntrack->master)
-		info->helper = LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,
-					 &reply);
+		info->helper = __ip_nat_find_helper(&reply);
 
 	/* It's done. */
 	info->initialized |= (1 << HOOK2MANIP(hooknum));
 
-	if (in_hashes) {
-		IP_NF_ASSERT(info->bysource.conntrack);
+	if (in_hashes)
 		replace_in_hashes(conntrack, info);
-	} else {
+	else
 		place_in_hashes(conntrack, info);
-	}
 
 	return NF_ACCEPT;
 }
@@ -678,14 +642,9 @@ void replace_in_hashes(struct ip_conntrack *conntrack,
 				   conntrack->tuplehash[IP_CT_DIR_REPLY]
 				   .tuple.dst.protonum);
 
-	IP_NF_ASSERT(info->bysource.conntrack == conntrack);
 	MUST_BE_WRITE_LOCKED(&ip_nat_lock);
-
-	list_del(&info->bysource.list);
-	list_del(&info->byipsproto.list);
-
-	list_prepend(&bysource[srchash], &info->bysource);
-	list_prepend(&byipsproto[ipsprotohash], &info->byipsproto);
+	list_move(&info->bysource, &bysource[srchash]);
+	list_move(&info->byipsproto, &byipsproto[ipsprotohash]);
 }
 
 void place_in_hashes(struct ip_conntrack *conntrack,
@@ -706,14 +665,9 @@ void place_in_hashes(struct ip_conntrack *conntrack,
 				   conntrack->tuplehash[IP_CT_DIR_REPLY]
 				   .tuple.dst.protonum);
 
-	IP_NF_ASSERT(!info->bysource.conntrack);
-
 	MUST_BE_WRITE_LOCKED(&ip_nat_lock);
-	info->byipsproto.conntrack = conntrack;
-	info->bysource.conntrack = conntrack;
-
-	list_prepend(&bysource[srchash], &info->bysource);
-	list_prepend(&byipsproto[ipsprotohash], &info->byipsproto);
+	list_add(&info->bysource, &bysource[srchash]);
+	list_add(&info->byipsproto, &byipsproto[ipsprotohash]);
 }
 
 /* Returns true if succeeded. */
@@ -733,9 +687,8 @@ manip_pkt(u_int16_t proto,
 	iph = (void *)(*pskb)->data + iphdroff;
 
 	/* Manipulate protcol part. */
-	if (!find_nat_proto(proto)->manip_pkt(pskb,
-					      iphdroff + iph->ihl*4,
-					      manip, maniptype))
+	if (!ip_nat_find_proto(proto)->manip_pkt(pskb, iphdroff + iph->ihl*4,
+	                                         manip, maniptype))
 		return 0;
 
 	iph = (void *)(*pskb)->data + iphdroff;
@@ -759,7 +712,7 @@ static inline int exp_for_packet(struct ip_conntrack_expect *exp,
 	int ret = 1;
 
 	MUST_BE_READ_LOCKED(&ip_conntrack_lock);
-	proto = __ip_ct_find_proto(skb->nh.iph->protocol);
+	proto = ip_ct_find_proto(skb->nh.iph->protocol);
 	if (proto->exp_matches_pkt)
 		ret = proto->exp_matches_pkt(exp, skb);
 
@@ -899,12 +852,8 @@ icmp_reply_translation(struct sk_buff **pskb,
 	}
 
 	/* Must be RELATED */
-	IP_NF_ASSERT((*pskb)->nfct
-		     - ((struct ip_conntrack *)(*pskb)->nfct->master)->infos
-		     == IP_CT_RELATED
-		     || (*pskb)->nfct
-		     - ((struct ip_conntrack *)(*pskb)->nfct->master)->infos
-		     == IP_CT_RELATED+IP_CT_IS_REPLY);
+	IP_NF_ASSERT((*pskb)->nfctinfo == IP_CT_RELATED ||
+		     (*pskb)->nfctinfo == IP_CT_RELATED+IP_CT_IS_REPLY);
 
 	/* Redirects on non-null nats must be dropped, else they'll
            start talking to each other without our translation, and be
@@ -1004,9 +953,11 @@ int __init ip_nat_init(void)
 
 	/* Sew in builtin protocols. */
 	WRITE_LOCK(&ip_nat_lock);
-	list_append(&protos, &ip_nat_protocol_tcp);
-	list_append(&protos, &ip_nat_protocol_udp);
-	list_append(&protos, &ip_nat_protocol_icmp);
+	for (i = 0; i < MAX_IP_NAT_PROTO; i++)
+		ip_nat_protos[i] = &ip_nat_unknown_protocol;
+	ip_nat_protos[IPPROTO_TCP] = &ip_nat_protocol_tcp;
+	ip_nat_protos[IPPROTO_UDP] = &ip_nat_protocol_udp;
+	ip_nat_protos[IPPROTO_ICMP] = &ip_nat_protocol_icmp;
 	WRITE_UNLOCK(&ip_nat_lock);
 
 	for (i = 0; i < ip_nat_htable_size; i++) {
diff --git a/net/ipv4/netfilter/ip_nat_ftp.c b/net/ipv4/netfilter/ip_nat_ftp.c
index 946ca05bb..be00284f8 100644
--- a/net/ipv4/netfilter/ip_nat_ftp.c
+++ b/net/ipv4/netfilter/ip_nat_ftp.c
@@ -12,6 +12,7 @@
 #include <linux/netfilter_ipv4.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
+#include <linux/moduleparam.h>
 #include <net/tcp.h>
 #include <linux/netfilter_ipv4/ip_nat.h>
 #include <linux/netfilter_ipv4/ip_nat_helper.h>
@@ -33,9 +34,7 @@ MODULE_DESCRIPTION("ftp NAT helper");
 static int ports[MAX_PORTS];
 static int ports_c;
 
-MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
-
-DECLARE_LOCK_EXTERN(ip_ftp_lock);
+module_param_array(ports, int, ports_c, 0400);
 
 /* FIXME: Time out? --RR */
 
@@ -59,8 +58,6 @@ ftp_nat_expected(struct sk_buff **pskb,
 	DEBUGP("nat_expected: We have a connection!\n");
 	exp_ftp_info = &ct->master->help.exp_ftp_info;
 
-	LOCK_BH(&ip_ftp_lock);
-
 	if (exp_ftp_info->ftptype == IP_CT_FTP_PORT
 	    || exp_ftp_info->ftptype == IP_CT_FTP_EPRT) {
 		/* PORT command: make connection go to the client. */
@@ -75,7 +72,6 @@ ftp_nat_expected(struct sk_buff **pskb,
 		DEBUGP("nat_expected: PASV cmd. %u.%u.%u.%u->%u.%u.%u.%u\n",
 		       NIPQUAD(newsrcip), NIPQUAD(newdstip));
 	}
-	UNLOCK_BH(&ip_ftp_lock);
 
 	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
 		newip = newsrcip;
@@ -111,8 +107,6 @@ mangle_rfc959_packet(struct sk_buff **pskb,
 {
 	char buffer[sizeof("nnn,nnn,nnn,nnn,nnn,nnn")];
 
-	MUST_BE_LOCKED(&ip_ftp_lock);
-
 	sprintf(buffer, "%u,%u,%u,%u,%u,%u",
 		NIPQUAD(newip), port>>8, port&0xFF);
 
@@ -134,8 +128,6 @@ mangle_eprt_packet(struct sk_buff **pskb,
 {
 	char buffer[sizeof("|1|255.255.255.255|65535|")];
 
-	MUST_BE_LOCKED(&ip_ftp_lock);
-
 	sprintf(buffer, "|1|%u.%u.%u.%u|%u|", NIPQUAD(newip), port);
 
 	DEBUGP("calling ip_nat_mangle_tcp_packet\n");
@@ -156,8 +148,6 @@ mangle_epsv_packet(struct sk_buff **pskb,
 {
 	char buffer[sizeof("|||65535|")];
 
-	MUST_BE_LOCKED(&ip_ftp_lock);
-
 	sprintf(buffer, "|||%u|", port);
 
 	DEBUGP("calling ip_nat_mangle_tcp_packet\n");
@@ -177,7 +167,7 @@ static int (*mangle[])(struct sk_buff **, u_int32_t, u_int16_t,
     [IP_CT_FTP_EPSV] = mangle_epsv_packet
 };
 
-static int ftp_data_fixup(const struct ip_ct_ftp_expect *ct_ftp_info,
+static int ftp_data_fixup(const struct ip_ct_ftp_expect *exp_ftp_info,
 			  struct ip_conntrack *ct,
 			  struct sk_buff **pskb,
 			  enum ip_conntrack_info ctinfo,
@@ -189,15 +179,14 @@ static int ftp_data_fixup(const struct ip_ct_ftp_expect *ct_ftp_info,
 	u_int16_t port;
 	struct ip_conntrack_tuple newtuple;
 
-	MUST_BE_LOCKED(&ip_ftp_lock);
 	DEBUGP("FTP_NAT: seq %u + %u in %u\n",
-	       expect->seq, ct_ftp_info->len,
+	       expect->seq, exp_ftp_info->len,
 	       ntohl(tcph->seq));
 
 	/* Change address inside packet to match way we're mapping
 	   this connection. */
-	if (ct_ftp_info->ftptype == IP_CT_FTP_PASV
-	    || ct_ftp_info->ftptype == IP_CT_FTP_EPSV) {
+	if (exp_ftp_info->ftptype == IP_CT_FTP_PASV
+	    || exp_ftp_info->ftptype == IP_CT_FTP_EPSV) {
 		/* PASV/EPSV response: must be where client thinks server
 		   is */
 		newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
@@ -219,7 +208,7 @@ static int ftp_data_fixup(const struct ip_ct_ftp_expect *ct_ftp_info,
 	newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
 
 	/* Try to get same port: if not, try to change it. */
-	for (port = ct_ftp_info->port; port != 0; port++) {
+	for (port = exp_ftp_info->port; port != 0; port++) {
 		newtuple.dst.u.tcp.port = htons(port);
 
 		if (ip_conntrack_change_expect(expect, &newtuple) == 0)
@@ -228,9 +217,9 @@ static int ftp_data_fixup(const struct ip_ct_ftp_expect *ct_ftp_info,
 	if (port == 0)
 		return 0;
 
-	if (!mangle[ct_ftp_info->ftptype](pskb, newip, port,
+	if (!mangle[exp_ftp_info->ftptype](pskb, newip, port,
 					  expect->seq - ntohl(tcph->seq),
-					  ct_ftp_info->len, ct, ctinfo))
+					  exp_ftp_info->len, ct, ctinfo))
 		return 0;
 
 	return 1;
@@ -247,12 +236,12 @@ static unsigned int help(struct ip_conntrack *ct,
 	struct tcphdr *tcph = (void *)iph + iph->ihl*4;
 	unsigned int datalen;
 	int dir;
-	struct ip_ct_ftp_expect *ct_ftp_info;
+	struct ip_ct_ftp_expect *exp_ftp_info;
 
 	if (!exp)
 		DEBUGP("ip_nat_ftp: no exp!!");
 
-	ct_ftp_info = &exp->help.exp_ftp_info;
+	exp_ftp_info = &exp->help.exp_ftp_info;
 
 	/* Only mangle things once: original direction in POST_ROUTING
 	   and reply direction on PRE_ROUTING. */
@@ -268,29 +257,23 @@ static unsigned int help(struct ip_conntrack *ct,
 	}
 
 	datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
-	LOCK_BH(&ip_ftp_lock);
 	/* If it's in the right range... */
-	if (between(exp->seq + ct_ftp_info->len,
+	if (between(exp->seq + exp_ftp_info->len,
 		    ntohl(tcph->seq),
 		    ntohl(tcph->seq) + datalen)) {
-		if (!ftp_data_fixup(ct_ftp_info, ct, pskb, ctinfo, exp)) {
-			UNLOCK_BH(&ip_ftp_lock);
+		if (!ftp_data_fixup(exp_ftp_info, ct, pskb, ctinfo, exp))
 			return NF_DROP;
-		}
 	} else {
 		/* Half a match?  This means a partial retransmisison.
 		   It's a cracker being funky. */
 		if (net_ratelimit()) {
 			printk("FTP_NAT: partial packet %u/%u in %u/%u\n",
-			       exp->seq, ct_ftp_info->len,
+			       exp->seq, exp_ftp_info->len,
 			       ntohl(tcph->seq),
 			       ntohl(tcph->seq) + datalen);
 		}
-		UNLOCK_BH(&ip_ftp_lock);
 		return NF_DROP;
 	}
-	UNLOCK_BH(&ip_ftp_lock);
-
 	return NF_ACCEPT;
 }
 
@@ -313,10 +296,10 @@ static int __init init(void)
 	int i, ret = 0;
 	char *tmpname;
 
-	if (ports[0] == 0)
-		ports[0] = FTP_PORT;
+	if (ports_c == 0)
+		ports[ports_c++] = FTP_PORT;
 
-	for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
+	for (i = 0; i < ports_c; i++) {
 		ftp[i].tuple.dst.protonum = IPPROTO_TCP;
 		ftp[i].tuple.src.u.tcp.port = htons(ports[i]);
 		ftp[i].mask.dst.protonum = 0xFFFF;
@@ -343,7 +326,6 @@ static int __init init(void)
 			fini();
 			return ret;
 		}
-		ports_c++;
 	}
 
 	return ret;
diff --git a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c
index a49c722ad..d7ee32f05 100644
--- a/net/ipv4/netfilter/ip_nat_helper.c
+++ b/net/ipv4/netfilter/ip_nat_helper.c
@@ -47,6 +47,7 @@
 #define DUMP_OFFSET(x)
 #endif
 
+static LIST_HEAD(helpers);
 DECLARE_LOCK(ip_nat_seqofs_lock);
 
 /* Setup TCP sequence correction given this change at this sequence */
@@ -72,7 +73,7 @@ adjust_tcp_sequence(u32 seq,
 
 	LOCK_BH(&ip_nat_seqofs_lock);
 
-	/* SYN adjust. If it's uninitialized, of this is after last
+	/* SYN adjust. If it's uninitialized, or this is after last
 	 * correction, record it: we don't handle more than one
 	 * adjustment in the window, but do deal with common case of a
 	 * retransmit */
@@ -346,7 +347,7 @@ ip_nat_sack_adjust(struct sk_buff **pskb,
 	return 1;
 }
 
-/* TCP sequence number adjustment.  Returns true or false.  */
+/* TCP sequence number adjustment.  Returns 1 on success, 0 on failure */
 int
 ip_nat_seq_adjust(struct sk_buff **pskb, 
 		  struct ip_conntrack *ct, 
@@ -395,7 +396,12 @@ ip_nat_seq_adjust(struct sk_buff **pskb,
 	tcph->seq = newseq;
 	tcph->ack_seq = newack;
 
-	return ip_nat_sack_adjust(pskb, tcph, ct, ctinfo);
+	if (!ip_nat_sack_adjust(pskb, tcph, ct, ctinfo))
+		return 0;
+
+	ip_conntrack_tcp_update(*pskb, ct, dir);
+
+	return 1;
 }
 
 static inline int
@@ -419,6 +425,24 @@ int ip_nat_helper_register(struct ip_nat_helper *me)
 	return ret;
 }
 
+struct ip_nat_helper *
+__ip_nat_find_helper(const struct ip_conntrack_tuple *tuple)
+{
+	return LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *, tuple);
+}
+
+struct ip_nat_helper *
+ip_nat_find_helper(const struct ip_conntrack_tuple *tuple)
+{
+	struct ip_nat_helper *h;
+
+	READ_LOCK(&ip_nat_lock);
+	h = __ip_nat_find_helper(tuple);
+	READ_UNLOCK(&ip_nat_lock);
+
+	return h;
+}
+
 static int
 kill_helper(const struct ip_conntrack *i, void *helper)
 {
diff --git a/net/ipv4/netfilter/ip_nat_irc.c b/net/ipv4/netfilter/ip_nat_irc.c
index dc778dd4a..5eb60a25a 100644
--- a/net/ipv4/netfilter/ip_nat_irc.c
+++ b/net/ipv4/netfilter/ip_nat_irc.c
@@ -27,6 +27,7 @@
 #include <linux/netfilter_ipv4/ip_nat_rule.h>
 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/moduleparam.h>
 
 #if 0
 #define DEBUGP printk
@@ -41,12 +42,9 @@ static int ports_c;
 MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
 MODULE_DESCRIPTION("IRC (DCC) NAT helper");
 MODULE_LICENSE("GPL");
-MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
+module_param_array(ports, int, ports_c, 0400);
 MODULE_PARM_DESC(ports, "port numbers of IRC servers");
 
-/* protects irc part of conntracks */
-DECLARE_LOCK_EXTERN(ip_irc_lock);
-
 /* FIXME: Time out? --RR */
 
 static unsigned int
@@ -87,7 +85,7 @@ irc_nat_expected(struct sk_buff **pskb,
 	return ip_nat_setup_info(ct, &mr, hooknum);
 }
 
-static int irc_data_fixup(const struct ip_ct_irc_expect *ct_irc_info,
+static int irc_data_fixup(const struct ip_ct_irc_expect *exp_irc_info,
 			  struct ip_conntrack *ct,
 			  struct sk_buff **pskb,
 			  enum ip_conntrack_info ctinfo,
@@ -102,23 +100,16 @@ static int irc_data_fixup(const struct ip_ct_irc_expect *ct_irc_info,
 	/* "4294967296 65635 " */
 	char buffer[18];
 
-	MUST_BE_LOCKED(&ip_irc_lock);
-
 	DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n",
-	       expect->seq, ct_irc_info->len,
+	       expect->seq, exp_irc_info->len,
 	       ntohl(tcph->seq));
 
 	newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
 
 	/* Alter conntrack's expectations. */
-
-	/* We can read expect here without conntrack lock, since it's
-	   only set in ip_conntrack_irc, with ip_irc_lock held
-	   writable */
-
 	t = expect->tuple;
 	t.dst.ip = newip;
-	for (port = ct_irc_info->port; port != 0; port++) {
+	for (port = exp_irc_info->port; port != 0; port++) {
 		t.dst.u.tcp.port = htons(port);
 		if (ip_conntrack_change_expect(expect, &t) == 0) {
 			DEBUGP("using port %d", port);
@@ -148,7 +139,7 @@ static int irc_data_fixup(const struct ip_ct_irc_expect *ct_irc_info,
 
 	return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
 					expect->seq - ntohl(tcph->seq),
-					ct_irc_info->len, buffer, 
+					exp_irc_info->len, buffer, 
 					strlen(buffer));
 }
 
@@ -163,12 +154,12 @@ static unsigned int help(struct ip_conntrack *ct,
 	struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
 	unsigned int datalen;
 	int dir;
-	struct ip_ct_irc_expect *ct_irc_info;
+	struct ip_ct_irc_expect *exp_irc_info;
 
 	if (!exp)
 		DEBUGP("ip_nat_irc: no exp!!");
 		
-	ct_irc_info = &exp->help.exp_irc_info;
+	exp_irc_info = &exp->help.exp_irc_info;
 
 	/* Only mangle things once: original direction in POST_ROUTING
 	   and reply direction on PRE_ROUTING. */
@@ -185,30 +176,24 @@ static unsigned int help(struct ip_conntrack *ct,
 	DEBUGP("got beyond not touching\n");
 
 	datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
-	LOCK_BH(&ip_irc_lock);
 	/* Check whether the whole IP/address pattern is carried in the payload */
-	if (between(exp->seq + ct_irc_info->len,
+	if (between(exp->seq + exp_irc_info->len,
 		    ntohl(tcph->seq),
 		    ntohl(tcph->seq) + datalen)) {
-		if (!irc_data_fixup(ct_irc_info, ct, pskb, ctinfo, exp)) {
-			UNLOCK_BH(&ip_irc_lock);
+		if (!irc_data_fixup(exp_irc_info, ct, pskb, ctinfo, exp))
 			return NF_DROP;
-		}
 	} else { 
 		/* Half a match?  This means a partial retransmisison.
 		   It's a cracker being funky. */
 		if (net_ratelimit()) {
 			printk
 			    ("IRC_NAT: partial packet %u/%u in %u/%u\n",
-			     exp->seq, ct_irc_info->len,
+			     exp->seq, exp_irc_info->len,
 			     ntohl(tcph->seq),
 			     ntohl(tcph->seq) + datalen);
 		}
-		UNLOCK_BH(&ip_irc_lock);
 		return NF_DROP;
 	}
-	UNLOCK_BH(&ip_irc_lock);
-
 	return NF_ACCEPT;
 }
 
@@ -235,11 +220,10 @@ static int __init init(void)
 	struct ip_nat_helper *hlpr;
 	char *tmpname;
 
-	if (ports[0] == 0) {
-		ports[0] = IRC_PORT;
-	}
+	if (ports_c == 0)
+		ports[ports_c++] = IRC_PORT;
 
-	for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++) {
+	for (i = 0; i < ports_c; i++) {
 		hlpr = &ip_nat_irc_helpers[i];
 		hlpr->tuple.dst.protonum = IPPROTO_TCP;
 		hlpr->tuple.src.u.tcp.port = htons(ports[i]);
@@ -269,7 +253,6 @@ static int __init init(void)
 			fini();
 			return 1;
 		}
-		ports_c++;
 	}
 	return ret;
 }
diff --git a/net/ipv4/netfilter/ip_nat_proto_icmp.c b/net/ipv4/netfilter/ip_nat_proto_icmp.c
index f7d31f850..6fb50dee5 100644
--- a/net/ipv4/netfilter/ip_nat_proto_icmp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_icmp.c
@@ -104,7 +104,7 @@ icmp_print_range(char *buffer, const struct ip_nat_range *range)
 }
 
 struct ip_nat_protocol ip_nat_protocol_icmp
-= { { NULL, NULL }, "ICMP", IPPROTO_ICMP,
+= { "ICMP", IPPROTO_ICMP,
     icmp_manip_pkt,
     icmp_in_range,
     icmp_unique_tuple,
diff --git a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c
index 731a12d08..197bd01e2 100644
--- a/net/ipv4/netfilter/ip_nat_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c
@@ -162,7 +162,7 @@ tcp_print_range(char *buffer, const struct ip_nat_range *range)
 }
 
 struct ip_nat_protocol ip_nat_protocol_tcp
-= { { NULL, NULL }, "TCP", IPPROTO_TCP,
+= { "TCP", IPPROTO_TCP,
     tcp_manip_pkt,
     tcp_in_range,
     tcp_unique_tuple,
diff --git a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c
index 293846556..240004eed 100644
--- a/net/ipv4/netfilter/ip_nat_proto_udp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_udp.c
@@ -148,7 +148,7 @@ udp_print_range(char *buffer, const struct ip_nat_range *range)
 }
 
 struct ip_nat_protocol ip_nat_protocol_udp
-= { { NULL, NULL }, "UDP", IPPROTO_UDP,
+= { "UDP", IPPROTO_UDP,
     udp_manip_pkt,
     udp_in_range,
     udp_unique_tuple,
diff --git a/net/ipv4/netfilter/ip_nat_proto_unknown.c b/net/ipv4/netfilter/ip_nat_proto_unknown.c
index 2d42a00f0..b57103fa9 100644
--- a/net/ipv4/netfilter/ip_nat_proto_unknown.c
+++ b/net/ipv4/netfilter/ip_nat_proto_unknown.c
@@ -60,8 +60,8 @@ unknown_print_range(char *buffer, const struct ip_nat_range *range)
 	return 0;
 }
 
-struct ip_nat_protocol unknown_nat_protocol = {
-	{ NULL, NULL }, "unknown", 0,
+struct ip_nat_protocol ip_nat_unknown_protocol = {
+	"unknown", 0,
 	unknown_manip_pkt,
 	unknown_in_range,
 	unknown_unique_tuple,
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
index 145b2c573..8ee96d104 100644
--- a/net/ipv4/netfilter/ip_nat_rule.c
+++ b/net/ipv4/netfilter/ip_nat_rule.c
@@ -132,7 +132,8 @@ static unsigned int ipt_snat_target(struct sk_buff **pskb,
 	ct = ip_conntrack_get(*pskb, &ctinfo);
 
 	/* Connection must be valid and new. */
-	IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
+	IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
+	                    || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
 	IP_NF_ASSERT(out);
 
 	return ip_nat_setup_info(ct, targinfo, hooknum);
diff --git a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c
index 539ad18f8..32d6e966a 100644
--- a/net/ipv4/netfilter/ip_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c
@@ -47,6 +47,7 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
+#include <linux/moduleparam.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv4/ip_nat.h>
 #include <linux/netfilter_ipv4/ip_nat_helper.h>
@@ -1252,6 +1253,9 @@ static unsigned int nat_help(struct ip_conntrack *ct,
 	int dir = CTINFO2DIR(ctinfo);
 	struct iphdr *iph = (*pskb)->nh.iph;
 	struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
+	
+	if (!skb_ip_make_writable(pskb, (*pskb)->len))
+		return NF_DROP;
 
 	spin_lock_bh(&snmp_lock);
 	
@@ -1357,4 +1361,4 @@ static void __exit fini(void)
 module_init(init);
 module_exit(fini);
 
-MODULE_PARM(debug, "i");
+module_param(debug, bool, 0600);
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 9765fd2d5..e4e961225 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -99,11 +99,13 @@ ip_nat_fn(unsigned int hooknum,
                    hash table yet).  We must not let this through, in
                    case we're doing NAT to the same network. */
 		if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
-			struct icmphdr hdr;
+			struct icmphdr _hdr, *hp;
 
-			if (skb_copy_bits(*pskb, (*pskb)->nh.iph->ihl*4,
-					  &hdr, sizeof(hdr)) == 0
-			    && hdr.type == ICMP_REDIRECT)
+			hp = skb_header_pointer(*pskb,
+						(*pskb)->nh.iph->ihl*4,
+						sizeof(_hdr), &_hdr);
+			if (hp != NULL &&
+			    hp->type == ICMP_REDIRECT)
 				return NF_DROP;
 		}
 		return NF_ACCEPT;
@@ -281,18 +283,13 @@ static struct nf_hook_ops ip_nat_local_in_ops = {
 int ip_nat_protocol_register(struct ip_nat_protocol *proto)
 {
 	int ret = 0;
-	struct list_head *i;
 
 	WRITE_LOCK(&ip_nat_lock);
-	list_for_each(i, &protos) {
-		if (((struct ip_nat_protocol *)i)->protonum
-		    == proto->protonum) {
-			ret = -EBUSY;
-			goto out;
-		}
+	if (ip_nat_protos[proto->protonum] != &ip_nat_unknown_protocol) {
+		ret = -EBUSY;
+		goto out;
 	}
-
-	list_prepend(&protos, proto);
+	ip_nat_protos[proto->protonum] = proto;
  out:
 	WRITE_UNLOCK(&ip_nat_lock);
 	return ret;
@@ -302,7 +299,7 @@ int ip_nat_protocol_register(struct ip_nat_protocol *proto)
 void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
 {
 	WRITE_LOCK(&ip_nat_lock);
-	LIST_DELETE(&protos, proto);
+	ip_nat_protos[proto->protonum] = &ip_nat_unknown_protocol;
 	WRITE_UNLOCK(&ip_nat_lock);
 
 	/* Someone could be still looking at the proto in a bh. */
@@ -392,4 +389,6 @@ EXPORT_SYMBOL(ip_nat_cheat_check);
 EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);
 EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
 EXPORT_SYMBOL(ip_nat_used_tuple);
+EXPORT_SYMBOL(ip_nat_find_helper);
+EXPORT_SYMBOL(__ip_nat_find_helper);
 MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/ip_nat_tftp.c b/net/ipv4/netfilter/ip_nat_tftp.c
index a2097bfbe..cacaab6f7 100644
--- a/net/ipv4/netfilter/ip_nat_tftp.c
+++ b/net/ipv4/netfilter/ip_nat_tftp.c
@@ -32,6 +32,7 @@
 #include <linux/netfilter_ipv4/ip_conntrack_tftp.h>
 #include <linux/netfilter_ipv4/ip_nat_helper.h>
 #include <linux/netfilter_ipv4/ip_nat_rule.h>
+#include <linux/moduleparam.h>
 
 MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>");
 MODULE_DESCRIPTION("tftp NAT helper");
@@ -41,7 +42,7 @@ MODULE_LICENSE("GPL");
 
 static int ports[MAX_PORTS];
 static int ports_c = 0;
-MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
+module_param_array(ports, int, ports_c, 0400);
 MODULE_PARM_DESC(ports, "port numbers of tftp servers");
 
 #if 0
@@ -59,7 +60,7 @@ tftp_nat_help(struct ip_conntrack *ct,
 	      struct sk_buff **pskb)
 {
 	int dir = CTINFO2DIR(ctinfo);
-	struct tftphdr tftph;
+	struct tftphdr _tftph, *tfh;
 	struct ip_conntrack_tuple repl;
 
 	if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
@@ -71,11 +72,13 @@ tftp_nat_help(struct ip_conntrack *ct,
 		return NF_ACCEPT;
 	}
 
-	if (skb_copy_bits(*pskb, (*pskb)->nh.iph->ihl*4+sizeof(struct udphdr),
-			  &tftph, sizeof(tftph)) != 0)
+	tfh = skb_header_pointer(*pskb,
+				 (*pskb)->nh.iph->ihl*4+sizeof(struct udphdr),
+				 sizeof(_tftph), &_tftph);
+	if (tfh == NULL)
 		return NF_DROP;
 
-	switch (ntohs(tftph.opcode)) {
+	switch (ntohs(tfh->opcode)) {
 	/* RRQ and WRQ works the same way */
 	case TFTP_OPCODE_READ:
 	case TFTP_OPCODE_WRITE:
@@ -108,9 +111,12 @@ tftp_nat_expected(struct sk_buff **pskb,
 #if 0
 	const struct ip_conntrack_tuple *repl =
 			&master->tuplehash[IP_CT_DIR_REPLY].tuple;
-	struct udphdr udph;
+	struct udphdr _udph, *uh;
 
-	if (skb_copy_bits(*pskb,(*pskb)->nh.iph->ihl*4,&udph,sizeof(udph))!=0)
+	uh = skb_header_pointer(*pskb,
+				(*pskb)->nh.iph->ihl*4,
+				sizeof(_udph), &_udph);
+	if (uh == NULL)
 		return NF_DROP;
 #endif
 
@@ -125,8 +131,8 @@ tftp_nat_expected(struct sk_buff **pskb,
 		mr.range[0].min_ip = mr.range[0].max_ip = orig->dst.ip; 
 		DEBUGP("orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
 			"newsrc: %u.%u.%u.%u\n",
-                        NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph.source),
- 			NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph.dest),
+                        NIPQUAD((*pskb)->nh.iph->saddr), ntohs(uh->source),
+ 			NIPQUAD((*pskb)->nh.iph->daddr), ntohs(uh->dest),
 			NIPQUAD(orig->dst.ip));
 	} else {
 		mr.range[0].min_ip = mr.range[0].max_ip = orig->src.ip;
@@ -136,8 +142,8 @@ tftp_nat_expected(struct sk_buff **pskb,
 
 		DEBUGP("orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
 			"newdst: %u.%u.%u.%u:%u\n",
-                        NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph.source),
-                        NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph.dest),
+                        NIPQUAD((*pskb)->nh.iph->saddr), ntohs(uh->source),
+                        NIPQUAD((*pskb)->nh.iph->daddr), ntohs(uh->dest),
                         NIPQUAD(orig->src.ip), ntohs(orig->src.u.udp.port));
 	}
 
@@ -162,10 +168,10 @@ static int __init init(void)
 	int i, ret = 0;
 	char *tmpname;
 
-	if (!ports[0])
-		ports[0] = TFTP_PORT;
+	if (ports_c == 0)
+		ports[ports_c++] = TFTP_PORT;
 
-	for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
+	for (i = 0; i < ports_c; i++) {
 		memset(&tftp[i], 0, sizeof(struct ip_nat_helper));
 
 		tftp[i].tuple.dst.protonum = IPPROTO_UDP;
@@ -194,7 +200,6 @@ static int __init init(void)
 			fini();
 			return ret;
 		}
-		ports_c++;
 	}
 	return ret;
 }
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 906b89df2..26dca38f6 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -619,6 +619,7 @@ static ctl_table ipq_root_table[] = {
 	{ .ctl_name = 0 }
 };
 
+#ifdef CONFIG_PROC_FS
 static int
 ipq_get_info(char *buffer, char **start, off_t offset, int length)
 {
@@ -648,6 +649,7 @@ ipq_get_info(char *buffer, char **start, off_t offset, int length)
 		len = 0;
 	return len;
 }
+#endif /* CONFIG_PROC_FS */
 
 static int
 init_or_cleanup(int init)
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index f24f17b8e..8da90bdb3 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -61,6 +61,8 @@ do {								\
 #endif
 #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
 
+static DECLARE_MUTEX(ipt_mutex);
+
 /* Must have mutex */
 #define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0)
 #define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0)
@@ -1458,21 +1460,27 @@ tcp_find_option(u_int8_t option,
 		int *hotdrop)
 {
 	/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
-	u_int8_t opt[60 - sizeof(struct tcphdr)];
+	u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
 	unsigned int i;
 
 	duprintf("tcp_match: finding option\n");
+
+	if (!optlen)
+		return invert;
+
 	/* If we don't have the whole header, drop packet. */
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4 + sizeof(struct tcphdr),
-			  opt, optlen) < 0) {
+	op = skb_header_pointer(skb,
+				skb->nh.iph->ihl*4 + sizeof(struct tcphdr),
+				optlen, _opt);
+	if (op == NULL) {
 		*hotdrop = 1;
 		return 0;
 	}
 
 	for (i = 0; i < optlen; ) {
-		if (opt[i] == option) return !invert;
-		if (opt[i] < 2) i++;
-		else i += opt[i+1]?:1;
+		if (op[i] == option) return !invert;
+		if (op[i] < 2) i++;
+		else i += op[i+1]?:1;
 	}
 
 	return invert;
@@ -1486,7 +1494,7 @@ tcp_match(const struct sk_buff *skb,
 	  int offset,
 	  int *hotdrop)
 {
-	struct tcphdr tcph;
+	struct tcphdr _tcph, *th;
 	const struct ipt_tcp *tcpinfo = matchinfo;
 
 	if (offset) {
@@ -1506,7 +1514,9 @@ tcp_match(const struct sk_buff *skb,
 
 #define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0) {
+	th = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+				sizeof(_tcph), &_tcph);
+	if (th == NULL) {
 		/* We've been asked to examine this packet, and we
 		   can't.  Hence, no choice but to drop. */
 		duprintf("Dropping evil TCP offset=0 tinygram.\n");
@@ -1515,23 +1525,24 @@ tcp_match(const struct sk_buff *skb,
 	}
 
 	if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
-			ntohs(tcph.source),
+			ntohs(th->source),
 			!!(tcpinfo->invflags & IPT_TCP_INV_SRCPT)))
 		return 0;
 	if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
-			ntohs(tcph.dest),
+			ntohs(th->dest),
 			!!(tcpinfo->invflags & IPT_TCP_INV_DSTPT)))
 		return 0;
-	if (!FWINVTCP((((unsigned char *)&tcph)[13] & tcpinfo->flg_mask)
+	if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
 		      == tcpinfo->flg_cmp,
 		      IPT_TCP_INV_FLAGS))
 		return 0;
 	if (tcpinfo->option) {
-		if (tcph.doff * 4 < sizeof(tcph)) {
+		if (th->doff * 4 < sizeof(_tcph)) {
 			*hotdrop = 1;
 			return 0;
 		}
-		if (!tcp_find_option(tcpinfo->option, skb, tcph.doff*4 - sizeof(tcph),
+		if (!tcp_find_option(tcpinfo->option, skb,
+				     th->doff*4 - sizeof(_tcph),
 				     tcpinfo->invflags & IPT_TCP_INV_OPTION,
 				     hotdrop))
 			return 0;
@@ -1564,14 +1575,16 @@ udp_match(const struct sk_buff *skb,
 	  int offset,
 	  int *hotdrop)
 {
-	struct udphdr udph;
+	struct udphdr _udph, *uh;
 	const struct ipt_udp *udpinfo = matchinfo;
 
 	/* Must not be a fragment. */
 	if (offset)
 		return 0;
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &udph, sizeof(udph)) < 0) {
+	uh = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+				sizeof(_udph), &_udph);
+	if (uh == NULL) {
 		/* We've been asked to examine this packet, and we
 		   can't.  Hence, no choice but to drop. */
 		duprintf("Dropping evil UDP tinygram.\n");
@@ -1580,10 +1593,10 @@ udp_match(const struct sk_buff *skb,
 	}
 
 	return port_match(udpinfo->spts[0], udpinfo->spts[1],
-			  ntohs(udph.source),
+			  ntohs(uh->source),
 			  !!(udpinfo->invflags & IPT_UDP_INV_SRCPT))
 		&& port_match(udpinfo->dpts[0], udpinfo->dpts[1],
-			      ntohs(udph.dest),
+			      ntohs(uh->dest),
 			      !!(udpinfo->invflags & IPT_UDP_INV_DSTPT));
 }
 
@@ -1635,16 +1648,19 @@ icmp_match(const struct sk_buff *skb,
 	   int offset,
 	   int *hotdrop)
 {
-	struct icmphdr icmph;
+	struct icmphdr _icmph, *ic;
 	const struct ipt_icmp *icmpinfo = matchinfo;
 
 	/* Must not be a fragment. */
 	if (offset)
 		return 0;
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &icmph, sizeof(icmph)) < 0){
+	ic = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+				sizeof(_icmph), &_icmph);
+	if (ic == NULL) {
 		/* We've been asked to examine this packet, and we
-		   can't.  Hence, no choice but to drop. */
+		 * can't.  Hence, no choice but to drop.
+		 */
 		duprintf("Dropping evil ICMP tinygram.\n");
 		*hotdrop = 1;
 		return 0;
@@ -1653,7 +1669,7 @@ icmp_match(const struct sk_buff *skb,
 	return icmp_type_code_match(icmpinfo->type,
 				    icmpinfo->code[0],
 				    icmpinfo->code[1],
-				    icmph.type, icmph.code,
+				    ic->type, ic->code,
 				    !!(icmpinfo->invflags&IPT_ICMP_INV));
 }
 
diff --git a/net/ipv4/netfilter/ipchains_core.c b/net/ipv4/netfilter/ipchains_core.c
index 97b5401ef..8fd8c1a5c 100644
--- a/net/ipv4/netfilter/ipchains_core.c
+++ b/net/ipv4/netfilter/ipchains_core.c
@@ -1,3 +1,5 @@
+#warning ipchains is obsolete, and will be removed soon.
+
 /* Minor modifications to fit on compatibility framework:
    Rusty.Russell@rustcorp.com.au
 */
@@ -679,49 +681,53 @@ ip_fw_check(const char *rif,
 		case IPPROTO_TCP:
 			dprintf("TCP ");
 			if (!offset) {
-				struct tcphdr tcph;
+				struct tcphdr _tcph, *th;
 
-				if (skb_copy_bits(*pskb,
-						  (*pskb)->nh.iph->ihl * 4,
-						  &tcph, sizeof(tcph)))
+				th = skb_header_pointer(*pskb,
+							(*pskb)->nh.iph->ihl*4,
+							sizeof(_tcph), &_tcph);
+				if (th == NULL)
 					return FW_BLOCK;
 
-				src_port = ntohs(tcph.source);
-				dst_port = ntohs(tcph.dest);
+				src_port = ntohs(th->source);
+				dst_port = ntohs(th->dest);
 
 				/* Connection initilisation can only
 				 * be made when the syn bit is set and
 				 * neither of the ack or reset is
 				 * set. */
-				if (tcph.syn && !(tcph.ack || tcph.rst))
+				if (th->syn && !(th->ack || th->rst))
 					tcpsyn = 1;
 			}
 			break;
 		case IPPROTO_UDP:
 			dprintf("UDP ");
 			if (!offset) {
-				struct udphdr udph;
+				struct udphdr _udph, *uh;
 
-				if (skb_copy_bits(*pskb,
-						  (*pskb)->nh.iph->ihl * 4,
-						  &udph, sizeof(udph)))
+				uh = skb_header_pointer(*pskb,
+							(*pskb)->nh.iph->ihl*4,
+							sizeof(_udph), &_udph);
+				if (uh == NULL)
 					return FW_BLOCK;
 
-				src_port = ntohs(udph.source);
-				dst_port = ntohs(udph.dest);
+				src_port = ntohs(uh->source);
+				dst_port = ntohs(uh->dest);
 			}
 			break;
 		case IPPROTO_ICMP:
 			if (!offset) {
-				struct icmphdr icmph;
+				struct icmphdr _icmph, *ic;
 
-				if (skb_copy_bits(*pskb,
-						  (*pskb)->nh.iph->ihl * 4,
-						  &icmph, sizeof(icmph)))
+				ic = skb_header_pointer(*pskb,
+							(*pskb)->nh.iph->ihl*4,
+							sizeof(_icmph),
+							&_icmph);
+				if (ic == NULL)
 					return FW_BLOCK;
 
-				src_port = (__u16) icmph.type;
-				dst_port = (__u16) icmph.code;
+				src_port = (__u16) ic->type;
+				dst_port = (__u16) ic->code;
 			}
 			dprintf("ICMP ");
 			break;
diff --git a/net/ipv4/netfilter/ipfwadm_core.c b/net/ipv4/netfilter/ipfwadm_core.c
index 424a9034f..b0f490f9d 100644
--- a/net/ipv4/netfilter/ipfwadm_core.c
+++ b/net/ipv4/netfilter/ipfwadm_core.c
@@ -1,3 +1,5 @@
+#warning ipfwadm is obsolete, and will be removed soon.
+
 /* Minor modifications to fit on compatibility framework:
    Rusty.Russell@rustcorp.com.au
 */
@@ -410,20 +412,21 @@ int ip_fw_chk(struct sk_buff **pskb,
 			dprintf1("TCP ");
 			/* ports stay 0xFFFF if it is not the first fragment */
 			if (!offset) {
-				struct tcphdr tcph;
+				struct tcphdr _tcph, *th;
 
-				if (skb_copy_bits(*pskb,
-						  (*pskb)->nh.iph->ihl * 4,
-						  &tcph, sizeof(tcph)))
+				th = skb_header_pointer(*pskb,
+							(*pskb)->nh.iph->ihl*4,
+							sizeof(_tcph), &_tcph);
+				if (th == NULL)
 					return FW_BLOCK;
 
-				src_port = ntohs(tcph.source);
-				dst_port = ntohs(tcph.dest);
+				src_port = ntohs(th->source);
+				dst_port = ntohs(th->dest);
 
-				if(!tcph.ack && !tcph.rst)
+				if(!th->ack && !th->rst)
 					/* We do NOT have ACK, value TRUE */
 					notcpack = 1;
-				if(!tcph.syn || !notcpack)
+				if(!th->syn || !notcpack)
 					/* We do NOT have SYN, value TRUE */
 					notcpsyn = 1;
 			}
@@ -433,29 +436,32 @@ int ip_fw_chk(struct sk_buff **pskb,
 			dprintf1("UDP ");
 			/* ports stay 0xFFFF if it is not the first fragment */
 			if (!offset) {
-				struct udphdr udph;
+				struct udphdr _udph, *uh;
 
-				if (skb_copy_bits(*pskb,
-						  (*pskb)->nh.iph->ihl * 4,
-						  &udph, sizeof(udph)))
+				uh = skb_header_pointer(*pskb,
+							(*pskb)->nh.iph->ihl*4,
+							sizeof(_udph), &_udph);
+				if (uh == NULL)
 					return FW_BLOCK;
 
-				src_port = ntohs(udph.source);
-				dst_port = ntohs(udph.dest);
+				src_port = ntohs(uh->source);
+				dst_port = ntohs(uh->dest);
 			}
 			prt = IP_FW_F_UDP;
 			break;
 		case IPPROTO_ICMP:
 			/* icmp_type stays 255 if it is not the first fragment */
 			if (!offset) {
-				struct icmphdr icmph;
+				struct icmphdr _icmph, *ic;
 
-				if (skb_copy_bits(*pskb,
-						  (*pskb)->nh.iph->ihl * 4,
-						  &icmph, sizeof(icmph)))
+				ic = skb_header_pointer(*pskb,
+							(*pskb)->nh.iph->ihl*4,
+							sizeof(_icmph),
+							&_icmph);
+				if (ic == NULL)
 					return FW_BLOCK;
 
-				icmp_type = (__u16) icmph.type;
+				icmp_type = (__u16) ic->type;
 			}
 			dprintf2("ICMP:%d ", icmp_type);
 			prt = IP_FW_F_ICMP;
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index 8ca402564..120109cd2 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -52,34 +52,39 @@ set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
 static inline int
 set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo, int inward)
 {
-	struct tcphdr tcph;
+	struct tcphdr _tcph, *th;
 	u_int16_t diffs[2];
 
 	/* Not enought header? */
-	if (skb_copy_bits(*pskb, (*pskb)->nh.iph->ihl*4, &tcph, sizeof(tcph))
-	    < 0)
+	th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl*4,
+				sizeof(_tcph), &_tcph);
+	if (th == NULL)
 		return 0;
 
-	diffs[0] = ((u_int16_t *)&tcph)[6];
+	diffs[0] = ((u_int16_t *)th)[6];
 	if (einfo->operation & IPT_ECN_OP_SET_ECE)
-		tcph.ece = einfo->proto.tcp.ece;
+		th->ece = einfo->proto.tcp.ece;
 
 	if (einfo->operation & IPT_ECN_OP_SET_CWR)
-		tcph.cwr = einfo->proto.tcp.cwr;
-	diffs[1] = ((u_int16_t *)&tcph)[6];
+		th->cwr = einfo->proto.tcp.cwr;
+	diffs[1] = ((u_int16_t *)&th)[6];
 
 	/* Only mangle if it's changed. */
 	if (diffs[0] != diffs[1]) {
 		diffs[0] = diffs[0] ^ 0xFFFF;
 		if (!skb_ip_make_writable(pskb,
-					  (*pskb)->nh.iph->ihl*4+sizeof(tcph)))
+					  (*pskb)->nh.iph->ihl*4+sizeof(_tcph)))
 			return 0;
+
+		if (th != &_tcph)
+			memcpy(&_tcph, th, sizeof(_tcph));
+
 		if ((*pskb)->ip_summed != CHECKSUM_HW)
-			tcph.check = csum_fold(csum_partial((char *)diffs,
-					       sizeof(diffs),
-					       tcph.check^0xFFFF));
+			_tcph.check = csum_fold(csum_partial((char *)diffs,
+							     sizeof(diffs),
+							     _tcph.check^0xFFFF));
 		memcpy((*pskb)->data + (*pskb)->nh.iph->ihl*4,
-		       &tcph, sizeof(tcph));
+		       &_tcph, sizeof(_tcph));
 		if ((*pskb)->ip_summed == CHECKSUM_HW)
 			if (skb_checksum_help(pskb, inward))
 				return 0;
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index b79962e22..2a3e3eb42 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -28,7 +28,7 @@ MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
 MODULE_DESCRIPTION("iptables syslog logging module");
 
 static unsigned int nflog = 1;
-MODULE_PARM(nflog, "i");
+module_param(nflog, int, 0400);
 MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
  
 #if 0
@@ -45,9 +45,10 @@ static void dump_packet(const struct ipt_log_info *info,
 			const struct sk_buff *skb,
 			unsigned int iphoff)
 {
-	struct iphdr iph;
+	struct iphdr _iph, *ih;
 
-	if (skb_copy_bits(skb, iphoff, &iph, sizeof(iph)) < 0) {
+	ih = skb_header_pointer(skb, iphoff, sizeof(_iph), &_iph);
+	if (ih == NULL) {
 		printk("TRUNCATED");
 		return;
 	}
@@ -56,32 +57,34 @@ static void dump_packet(const struct ipt_log_info *info,
 	 * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */
 	/* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */
 	printk("SRC=%u.%u.%u.%u DST=%u.%u.%u.%u ",
-	       NIPQUAD(iph.saddr), NIPQUAD(iph.daddr));
+	       NIPQUAD(ih->saddr), NIPQUAD(ih->daddr));
 
 	/* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */
 	printk("LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ",
-	       ntohs(iph.tot_len), iph.tos & IPTOS_TOS_MASK,
-	       iph.tos & IPTOS_PREC_MASK, iph.ttl, ntohs(iph.id));
+	       ntohs(ih->tot_len), ih->tos & IPTOS_TOS_MASK,
+	       ih->tos & IPTOS_PREC_MASK, ih->ttl, ntohs(ih->id));
 
 	/* Max length: 6 "CE DF MF " */
-	if (ntohs(iph.frag_off) & IP_CE)
+	if (ntohs(ih->frag_off) & IP_CE)
 		printk("CE ");
-	if (ntohs(iph.frag_off) & IP_DF)
+	if (ntohs(ih->frag_off) & IP_DF)
 		printk("DF ");
-	if (ntohs(iph.frag_off) & IP_MF)
+	if (ntohs(ih->frag_off) & IP_MF)
 		printk("MF ");
 
 	/* Max length: 11 "FRAG:65535 " */
-	if (ntohs(iph.frag_off) & IP_OFFSET)
-		printk("FRAG:%u ", ntohs(iph.frag_off) & IP_OFFSET);
+	if (ntohs(ih->frag_off) & IP_OFFSET)
+		printk("FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET);
 
 	if ((info->logflags & IPT_LOG_IPOPT)
-	    && iph.ihl * 4 > sizeof(struct iphdr)) {
-		unsigned char opt[4 * 15 - sizeof(struct iphdr)];
+	    && ih->ihl * 4 > sizeof(struct iphdr)) {
+		unsigned char _opt[4 * 15 - sizeof(struct iphdr)], *op;
 		unsigned int i, optsize;
 
-		optsize = iph.ihl * 4 - sizeof(struct iphdr);
-		if (skb_copy_bits(skb, iphoff+sizeof(iph), opt, optsize) < 0) {
+		optsize = ih->ihl * 4 - sizeof(struct iphdr);
+		op = skb_header_pointer(skb, iphoff+sizeof(_iph),
+					optsize, _opt);
+		if (op == NULL) {
 			printk("TRUNCATED");
 			return;
 		}
@@ -89,67 +92,71 @@ static void dump_packet(const struct ipt_log_info *info,
 		/* Max length: 127 "OPT (" 15*4*2chars ") " */
 		printk("OPT (");
 		for (i = 0; i < optsize; i++)
-			printk("%02X", opt[i]);
+			printk("%02X", op[i]);
 		printk(") ");
 	}
 
-	switch (iph.protocol) {
+	switch (ih->protocol) {
 	case IPPROTO_TCP: {
-		struct tcphdr tcph;
+		struct tcphdr _tcph, *th;
 
 		/* Max length: 10 "PROTO=TCP " */
 		printk("PROTO=TCP ");
 
-		if (ntohs(iph.frag_off) & IP_OFFSET)
+		if (ntohs(ih->frag_off) & IP_OFFSET)
 			break;
 
 		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
-		if (skb_copy_bits(skb, iphoff+iph.ihl*4, &tcph, sizeof(tcph))
-		    < 0) {
+		th = skb_header_pointer(skb, iphoff + ih->ihl * 4,
+					sizeof(_tcph), &_tcph);
+		if (th == NULL) {
 			printk("INCOMPLETE [%u bytes] ",
-			       skb->len - iphoff - iph.ihl*4);
+			       skb->len - iphoff - ih->ihl*4);
 			break;
 		}
 
 		/* Max length: 20 "SPT=65535 DPT=65535 " */
 		printk("SPT=%u DPT=%u ",
-		       ntohs(tcph.source), ntohs(tcph.dest));
+		       ntohs(th->source), ntohs(th->dest));
 		/* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
 		if (info->logflags & IPT_LOG_TCPSEQ)
 			printk("SEQ=%u ACK=%u ",
-			       ntohl(tcph.seq), ntohl(tcph.ack_seq));
+			       ntohl(th->seq), ntohl(th->ack_seq));
 		/* Max length: 13 "WINDOW=65535 " */
-		printk("WINDOW=%u ", ntohs(tcph.window));
+		printk("WINDOW=%u ", ntohs(th->window));
 		/* Max length: 9 "RES=0x3F " */
-		printk("RES=0x%02x ", (u8)(ntohl(tcp_flag_word(&tcph) & TCP_RESERVED_BITS) >> 22));
+		printk("RES=0x%02x ", (u8)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22));
 		/* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
-		if (tcph.cwr)
+		if (th->cwr)
 			printk("CWR ");
-		if (tcph.ece)
+		if (th->ece)
 			printk("ECE ");
-		if (tcph.urg)
+		if (th->urg)
 			printk("URG ");
-		if (tcph.ack)
+		if (th->ack)
 			printk("ACK ");
-		if (tcph.psh)
+		if (th->psh)
 			printk("PSH ");
-		if (tcph.rst)
+		if (th->rst)
 			printk("RST ");
-		if (tcph.syn)
+		if (th->syn)
 			printk("SYN ");
-		if (tcph.fin)
+		if (th->fin)
 			printk("FIN ");
 		/* Max length: 11 "URGP=65535 " */
-		printk("URGP=%u ", ntohs(tcph.urg_ptr));
+		printk("URGP=%u ", ntohs(th->urg_ptr));
 
 		if ((info->logflags & IPT_LOG_TCPOPT)
-		    && tcph.doff * 4 > sizeof(struct tcphdr)) {
-			unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
+		    && th->doff * 4 > sizeof(struct tcphdr)) {
+			unsigned char _opt[4 * 15 - sizeof(struct tcphdr)];
+			unsigned char *op;
 			unsigned int i, optsize;
 
-			optsize = tcph.doff * 4 - sizeof(struct tcphdr);
-			if (skb_copy_bits(skb, iphoff+iph.ihl*4 + sizeof(tcph),
-					  opt, optsize) < 0) {
+			optsize = th->doff * 4 - sizeof(struct tcphdr);
+			op = skb_header_pointer(skb,
+						iphoff+ih->ihl*4+sizeof(_tcph),
+						optsize, _opt);
+			if (op == NULL) {
 				printk("TRUNCATED");
 				return;
 			}
@@ -157,36 +164,37 @@ static void dump_packet(const struct ipt_log_info *info,
 			/* Max length: 127 "OPT (" 15*4*2chars ") " */
 			printk("OPT (");
 			for (i = 0; i < optsize; i++)
-				printk("%02X", opt[i]);
+				printk("%02X", op[i]);
 			printk(") ");
 		}
 		break;
 	}
 	case IPPROTO_UDP: {
-		struct udphdr udph;
+		struct udphdr _udph, *uh;
 
 		/* Max length: 10 "PROTO=UDP " */
 		printk("PROTO=UDP ");
 
-		if (ntohs(iph.frag_off) & IP_OFFSET)
+		if (ntohs(ih->frag_off) & IP_OFFSET)
 			break;
 
 		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
-		if (skb_copy_bits(skb, iphoff+iph.ihl*4, &udph, sizeof(udph))
-		    < 0) {
+		uh = skb_header_pointer(skb, iphoff+ih->ihl*4,
+					sizeof(_udph), &_udph);
+		if (uh == NULL) {
 			printk("INCOMPLETE [%u bytes] ",
-			       skb->len - iphoff - iph.ihl*4);
+			       skb->len - iphoff - ih->ihl*4);
 			break;
 		}
 
 		/* Max length: 20 "SPT=65535 DPT=65535 " */
 		printk("SPT=%u DPT=%u LEN=%u ",
-		       ntohs(udph.source), ntohs(udph.dest),
-		       ntohs(udph.len));
+		       ntohs(uh->source), ntohs(uh->dest),
+		       ntohs(uh->len));
 		break;
 	}
 	case IPPROTO_ICMP: {
-		struct icmphdr icmph;
+		struct icmphdr _icmph, *ich;
 		static size_t required_len[NR_ICMP_TYPES+1]
 			= { [ICMP_ECHOREPLY] = 4,
 			    [ICMP_DEST_UNREACH]
@@ -208,47 +216,48 @@ static void dump_packet(const struct ipt_log_info *info,
 		/* Max length: 11 "PROTO=ICMP " */
 		printk("PROTO=ICMP ");
 
-		if (ntohs(iph.frag_off) & IP_OFFSET)
+		if (ntohs(ih->frag_off) & IP_OFFSET)
 			break;
 
 		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
-		if (skb_copy_bits(skb, iphoff+iph.ihl*4, &icmph, sizeof(icmph))
-		    < 0) {
+		ich = skb_header_pointer(skb, iphoff + ih->ihl * 4,
+					 sizeof(_icmph), &_icmph);
+		if (ich == NULL) {
 			printk("INCOMPLETE [%u bytes] ",
-			       skb->len - iphoff - iph.ihl*4);
+			       skb->len - iphoff - ih->ihl*4);
 			break;
 		}
 
 		/* Max length: 18 "TYPE=255 CODE=255 " */
-		printk("TYPE=%u CODE=%u ", icmph.type, icmph.code);
+		printk("TYPE=%u CODE=%u ", ich->type, ich->code);
 
 		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
-		if (icmph.type <= NR_ICMP_TYPES
-		    && required_len[icmph.type]
-		    && skb->len-iphoff-iph.ihl*4 < required_len[icmph.type]) {
+		if (ich->type <= NR_ICMP_TYPES
+		    && required_len[ich->type]
+		    && skb->len-iphoff-ih->ihl*4 < required_len[ich->type]) {
 			printk("INCOMPLETE [%u bytes] ",
-			       skb->len - iphoff - iph.ihl*4);
+			       skb->len - iphoff - ih->ihl*4);
 			break;
 		}
 
-		switch (icmph.type) {
+		switch (ich->type) {
 		case ICMP_ECHOREPLY:
 		case ICMP_ECHO:
 			/* Max length: 19 "ID=65535 SEQ=65535 " */
 			printk("ID=%u SEQ=%u ",
-			       ntohs(icmph.un.echo.id),
-			       ntohs(icmph.un.echo.sequence));
+			       ntohs(ich->un.echo.id),
+			       ntohs(ich->un.echo.sequence));
 			break;
 
 		case ICMP_PARAMETERPROB:
 			/* Max length: 14 "PARAMETER=255 " */
 			printk("PARAMETER=%u ",
-			       ntohl(icmph.un.gateway) >> 24);
+			       ntohl(ich->un.gateway) >> 24);
 			break;
 		case ICMP_REDIRECT:
 			/* Max length: 24 "GATEWAY=255.255.255.255 " */
 			printk("GATEWAY=%u.%u.%u.%u ",
-			       NIPQUAD(icmph.un.gateway));
+			       NIPQUAD(ich->un.gateway));
 			/* Fall through */
 		case ICMP_DEST_UNREACH:
 		case ICMP_SOURCE_QUENCH:
@@ -257,62 +266,65 @@ static void dump_packet(const struct ipt_log_info *info,
 			if (!iphoff) { /* Only recurse once. */
 				printk("[");
 				dump_packet(info, skb,
-					    iphoff + iph.ihl*4+sizeof(icmph));
+					    iphoff + ih->ihl*4+sizeof(_icmph));
 				printk("] ");
 			}
 
 			/* Max length: 10 "MTU=65535 " */
-			if (icmph.type == ICMP_DEST_UNREACH
-			    && icmph.code == ICMP_FRAG_NEEDED)
-				printk("MTU=%u ", ntohs(icmph.un.frag.mtu));
+			if (ich->type == ICMP_DEST_UNREACH
+			    && ich->code == ICMP_FRAG_NEEDED)
+				printk("MTU=%u ", ntohs(ich->un.frag.mtu));
 		}
 		break;
 	}
 	/* Max Length */
 	case IPPROTO_AH: {
-		struct ip_auth_hdr ah;
+		struct ip_auth_hdr _ahdr, *ah;
 
-		if (ntohs(iph.frag_off) & IP_OFFSET)
+		if (ntohs(ih->frag_off) & IP_OFFSET)
 			break;
 		
 		/* Max length: 9 "PROTO=AH " */
 		printk("PROTO=AH ");
 
 		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
-		if (skb_copy_bits(skb, iphoff+iph.ihl*4, &ah, sizeof(ah)) < 0) {
+		ah = skb_header_pointer(skb, iphoff+ih->ihl*4,
+					sizeof(_ahdr), &_ahdr);
+		if (ah == NULL) {
 			printk("INCOMPLETE [%u bytes] ",
-			       skb->len - iphoff - iph.ihl*4);
+			       skb->len - iphoff - ih->ihl*4);
 			break;
 		}
 
 		/* Length: 15 "SPI=0xF1234567 " */
-		printk("SPI=0x%x ", ntohl(ah.spi));
+		printk("SPI=0x%x ", ntohl(ah->spi));
 		break;
 	}
 	case IPPROTO_ESP: {
-		struct ip_esp_hdr esph;
+		struct ip_esp_hdr _esph, *eh;
 
 		/* Max length: 10 "PROTO=ESP " */
 		printk("PROTO=ESP ");
 
-		if (ntohs(iph.frag_off) & IP_OFFSET)
+		if (ntohs(ih->frag_off) & IP_OFFSET)
 			break;
 
 		/* Max length: 25 "INCOMPLETE [65535 bytes] " */
-		if (skb_copy_bits(skb, iphoff+iph.ihl*4, &esph, sizeof(esph))
-		    < 0) {
+		eh = skb_header_pointer(skb, iphoff+ih->ihl*4,
+					sizeof(_esph), &_esph);
+		if (eh == NULL) {
 			printk("INCOMPLETE [%u bytes] ",
-			       skb->len - iphoff - iph.ihl*4);
+			       skb->len - iphoff - ih->ihl*4);
 			break;
 		}
 
 		/* Length: 15 "SPI=0xF1234567 " */
-		printk("SPI=0x%x ", ntohl(esph.spi));
+		printk("SPI=0x%x ", ntohl(eh->spi));
 		break;
 	}
 	/* Max length: 10 "PROTO 255 " */
 	default:
-		printk("PROTO=%u ", iph.protocol);
+		printk("PROTO=%u ", ih->protocol);
 	}
 
 	/* Proto    Max log string length */
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index 54bc4684c..ea02a12d7 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -92,8 +92,8 @@ masquerade_target(struct sk_buff **pskb,
 		return NF_ACCEPT;
 
 	ct = ip_conntrack_get(*pskb, &ctinfo);
-	IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW
-				  || ctinfo == IP_CT_RELATED));
+	IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
+	                    || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
 
 	mr = targinfo;
 
diff --git a/net/ipv4/netfilter/ipt_NOTRACK.c b/net/ipv4/netfilter/ipt_NOTRACK.c
index 219e04942..a4bb9b3bc 100644
--- a/net/ipv4/netfilter/ipt_NOTRACK.c
+++ b/net/ipv4/netfilter/ipt_NOTRACK.c
@@ -23,7 +23,8 @@ target(struct sk_buff **pskb,
 	   If there is a real ct entry correspondig to this packet, 
 	   it'll hang aroun till timing out. We don't deal with it
 	   for performance reasons. JK */
-	(*pskb)->nfct = &ip_conntrack_untracked.infos[IP_CT_NEW];
+	(*pskb)->nfct = &ip_conntrack_untracked.ct_general;
+	(*pskb)->nfctinfo = IP_CT_NEW;
 	nf_conntrack_get((*pskb)->nfct);
 
 	return IPT_CONTINUE;
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index b8018cb02..b2e05746a 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -41,14 +41,14 @@ MODULE_DESCRIPTION("iptables REJECT target module");
 /* If the original packet is part of a connection, but the connection
    is not confirmed, our manufactured reply will not be associated
    with it, so we need to do this manually. */
-static void connection_attach(struct sk_buff *new_skb, struct nf_ct_info *nfct)
+static void connection_attach(struct sk_buff *new_skb, struct sk_buff *skb)
 {
-	void (*attach)(struct sk_buff *, struct nf_ct_info *);
+	void (*attach)(struct sk_buff *, struct sk_buff *);
 
 	/* Avoid module unload race with ip_ct_attach being NULLed out */
-	if (nfct && (attach = ip_ct_attach) != NULL) {
+	if (skb->nfct && (attach = ip_ct_attach) != NULL) {
 		mb(); /* Just to be sure: must be read before executing this */
-		attach(new_skb, nfct);
+		attach(new_skb, skb);
 	}
 }
 
@@ -103,7 +103,7 @@ static inline struct rtable *route_reverse(struct sk_buff *skb, int hook)
 static void send_reset(struct sk_buff *oldskb, int hook)
 {
 	struct sk_buff *nskb;
-	struct tcphdr otcph, *tcph;
+	struct tcphdr _otcph, *oth, *tcph;
 	struct rtable *rt;
 	u_int16_t tmp_port;
 	u_int32_t tmp_addr;
@@ -114,12 +114,13 @@ static void send_reset(struct sk_buff *oldskb, int hook)
 	if (oldskb->nh.iph->frag_off & htons(IP_OFFSET))
 		return;
 
-	if (skb_copy_bits(oldskb, oldskb->nh.iph->ihl*4,
-			  &otcph, sizeof(otcph)) < 0)
+	oth = skb_header_pointer(oldskb, oldskb->nh.iph->ihl * 4,
+				 sizeof(_otcph), &_otcph);
+	if (oth == NULL)
  		return;
 
 	/* No RST for RST. */
-	if (otcph.rst)
+	if (oth->rst)
 		return;
 
 	/* FIXME: Check checksum --RR */
@@ -167,13 +168,13 @@ static void send_reset(struct sk_buff *oldskb, int hook)
 
 	if (tcph->ack) {
 		needs_ack = 0;
-		tcph->seq = otcph.ack_seq;
+		tcph->seq = oth->ack_seq;
 		tcph->ack_seq = 0;
 	} else {
 		needs_ack = 1;
-		tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin
+		tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin
 				      + oldskb->len - oldskb->nh.iph->ihl*4
-				      - (otcph.doff<<2));
+				      - (oth->doff<<2));
 		tcph->seq = 0;
 	}
 
@@ -208,7 +209,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
 	if (nskb->len > dst_pmtu(nskb->dst))
 		goto free_nskb;
 
-	connection_attach(nskb, oldskb->nfct);
+	connection_attach(nskb, oldskb);
 
 	NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
 		ip_finish_output);
@@ -359,7 +360,7 @@ static void send_unreach(struct sk_buff *skb_in, int code)
 	icmph->checksum = ip_compute_csum((unsigned char *)icmph,
 					  length - sizeof(struct iphdr));
 
-	connection_attach(nskb, skb_in->nfct);
+	connection_attach(nskb, skb_in);
 
 	NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
 		ip_finish_output);
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index c352df54a..51d16d33b 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -34,8 +34,8 @@
  * by that factor.
  *
  * flushtimeout:
- *   Specify, after how many clock ticks (intel: 100 per second) the queue
- * should be flushed even if it is not full yet.
+ *   Specify, after how many hundredths of a second the queue should be
+ *   flushed even if it is not full yet.
  *
  * ipt_ULOG.c,v 1.22 2002/10/30 09:07:31 laforge Exp
  */
@@ -50,6 +50,7 @@
 #include <linux/netlink.h>
 #include <linux/netdevice.h>
 #include <linux/mm.h>
+#include <linux/moduleparam.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ipt_ULOG.h>
@@ -74,15 +75,15 @@ MODULE_DESCRIPTION("iptables userspace logging module");
 #define PRINTR(format, args...) do { if (net_ratelimit()) printk(format , ## args); } while (0)
 
 static unsigned int nlbufsiz = 4096;
-MODULE_PARM(nlbufsiz, "i");
+module_param(nlbufsiz, uint, 0600); /* FIXME: Check size < 128k --RR */
 MODULE_PARM_DESC(nlbufsiz, "netlink buffer size");
 
-static unsigned int flushtimeout = 10 * HZ;
-MODULE_PARM(flushtimeout, "i");
-MODULE_PARM_DESC(flushtimeout, "buffer flush timeout");
+static unsigned int flushtimeout = 10;
+module_param(flushtimeout, int, 0600);
+MODULE_PARM_DESC(flushtimeout, "buffer flush timeout (hundredths of a second)");
 
 static unsigned int nflog = 1;
-MODULE_PARM(nflog, "i");
+module_param(nflog, int, 0400);
 MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
 
 /* global data structures */
@@ -97,7 +98,6 @@ typedef struct {
 static ulog_buff_t ulog_buffers[ULOG_MAXNLGROUPS];	/* array of buffers */
 
 static struct sock *nflognl;	/* our socket */
-static size_t qlen;		/* current length of multipart-nlmsg */
 DECLARE_LOCK(ulog_lock);	/* spinlock */
 
 /* send one ulog_buff_t to userspace */
@@ -116,7 +116,7 @@ static void ulog_send(unsigned int nlgroupnum)
 
 	NETLINK_CB(ub->skb).dst_groups = (1 << nlgroupnum);
 	DEBUGP("ipt_ULOG: throwing %d packets to netlink mask %u\n",
-		ub->qlen, nlgroup);
+		ub->qlen, nlgroupnum);
 	netlink_broadcast(nflognl, ub->skb, 0, (1 << nlgroupnum), GFP_ATOMIC);
 
 	ub->qlen = 0;
@@ -126,7 +126,7 @@ static void ulog_send(unsigned int nlgroupnum)
 }
 
 
-/* timer function to flush queue in ULOG_FLUSH_INTERVAL time */
+/* timer function to flush queue in flushtimeout time */
 static void ulog_timer(unsigned long data)
 {
 	DEBUGP("ipt_ULOG: timer function called, calling ulog_send\n");
@@ -261,20 +261,21 @@ static void ipt_ulog_packet(unsigned int hooknum,
 		ub->lastnlh->nlmsg_flags |= NLM_F_MULTI;
 	}
 
-	/* if threshold is reached, send message to userspace */
-	if (qlen >= loginfo->qthreshold) {
-		if (loginfo->qthreshold > 1)
-			nlh->nlmsg_type = NLMSG_DONE;
-	}
-
 	ub->lastnlh = nlh;
 
 	/* if timer isn't already running, start it */
 	if (!timer_pending(&ub->timer)) {
-		ub->timer.expires = jiffies + flushtimeout;
+		ub->timer.expires = jiffies + flushtimeout * HZ / 100;
 		add_timer(&ub->timer);
 	}
 
+	/* if threshold is reached, send message to userspace */
+	if (ub->qlen >= loginfo->qthreshold) {
+		if (loginfo->qthreshold > 1)
+			nlh->nlmsg_type = NLMSG_DONE;
+		ulog_send(groupnum);
+	}
+
 	UNLOCK_BH(&ulog_lock);
 
 	return;
diff --git a/net/ipv4/netfilter/ipt_ah.c b/net/ipv4/netfilter/ipt_ah.c
index 1f0d7652f..a0fea847c 100644
--- a/net/ipv4/netfilter/ipt_ah.c
+++ b/net/ipv4/netfilter/ipt_ah.c
@@ -43,23 +43,26 @@ match(const struct sk_buff *skb,
       int offset,
       int *hotdrop)
 {
-	struct ip_auth_hdr ah;
+	struct ip_auth_hdr _ahdr, *ah;
 	const struct ipt_ah *ahinfo = matchinfo;
 
 	/* Must not be a fragment. */
 	if (offset)
 		return 0;
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &ah, sizeof(ah)) < 0) {
+	ah = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+				sizeof(_ahdr), &_ahdr);
+	if (ah == NULL) {
 		/* We've been asked to examine this packet, and we
-		   can't.  Hence, no choice but to drop. */
+		 * can't.  Hence, no choice but to drop.
+		 */
 		duprintf("Dropping evil AH tinygram.\n");
 		*hotdrop = 1;
 		return 0;
 	}
 
 	return spi_match(ahinfo->spis[0], ahinfo->spis[1],
-			 ntohl(ah.spi),
+			 ntohl(ah->spi),
 			 !!(ahinfo->invflags & IPT_AH_INV_SPI));
 }
 
diff --git a/net/ipv4/netfilter/ipt_conntrack.c b/net/ipv4/netfilter/ipt_conntrack.c
index 9b04bbb8f..c1d22801b 100644
--- a/net/ipv4/netfilter/ipt_conntrack.c
+++ b/net/ipv4/netfilter/ipt_conntrack.c
@@ -35,7 +35,7 @@ match(const struct sk_buff *skb,
 
 #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
 
-	if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
+	if (ct == &ip_conntrack_untracked)
 		statebit = IPT_CONNTRACK_STATE_UNTRACKED;
 	else if (ct)
  		statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c
index 0e1efd764..b6f7181e8 100644
--- a/net/ipv4/netfilter/ipt_ecn.c
+++ b/net/ipv4/netfilter/ipt_ecn.c
@@ -30,31 +30,34 @@ static inline int match_tcp(const struct sk_buff *skb,
 			    const struct ipt_ecn_info *einfo,
 			    int *hotdrop)
 {
-	struct tcphdr tcph;
+	struct tcphdr _tcph, *th;
 
 	/* In practice, TCP match does this, so can't fail.  But let's
-           be good citizens. */
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0) {
+	 * be good citizens.
+	 */
+	th = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+				sizeof(_tcph), &_tcph);
+	if (th == NULL) {
 		*hotdrop = 0;
 		return 0;
 	}
 
 	if (einfo->operation & IPT_ECN_OP_MATCH_ECE) {
 		if (einfo->invert & IPT_ECN_OP_MATCH_ECE) {
-			if (tcph.ece == 1)
+			if (th->ece == 1)
 				return 0;
 		} else {
-			if (tcph.ece == 0)
+			if (th->ece == 0)
 				return 0;
 		}
 	}
 
 	if (einfo->operation & IPT_ECN_OP_MATCH_CWR) {
 		if (einfo->invert & IPT_ECN_OP_MATCH_CWR) {
-			if (tcph.cwr == 1)
+			if (th->cwr == 1)
 				return 0;
 		} else {
-			if (tcph.cwr == 0)
+			if (th->cwr == 0)
 				return 0;
 		}
 	}
diff --git a/net/ipv4/netfilter/ipt_esp.c b/net/ipv4/netfilter/ipt_esp.c
index c3b889378..e1d0dd31e 100644
--- a/net/ipv4/netfilter/ipt_esp.c
+++ b/net/ipv4/netfilter/ipt_esp.c
@@ -44,23 +44,26 @@ match(const struct sk_buff *skb,
       int offset,
       int *hotdrop)
 {
-	struct ip_esp_hdr esp;
+	struct ip_esp_hdr _esp, *eh;
 	const struct ipt_esp *espinfo = matchinfo;
 
 	/* Must not be a fragment. */
 	if (offset)
 		return 0;
 
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &esp, sizeof(esp)) < 0) {
+	eh = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+				sizeof(_esp), &_esp);
+	if (eh == NULL) {
 		/* We've been asked to examine this packet, and we
-		   can't.  Hence, no choice but to drop. */
+		 * can't.  Hence, no choice but to drop.
+		 */
 		duprintf("Dropping evil ESP tinygram.\n");
 		*hotdrop = 1;
 		return 0;
 	}
 
 	return spi_match(espinfo->spis[0], espinfo->spis[1],
-			 ntohl(esp.spi),
+			 ntohl(eh->spi),
 			 !!(espinfo->invflags & IPT_ESP_INV_SPI));
 }
 
diff --git a/net/ipv4/netfilter/ipt_helper.c b/net/ipv4/netfilter/ipt_helper.c
index ee9881ece..1ea5c1e46 100644
--- a/net/ipv4/netfilter/ipt_helper.c
+++ b/net/ipv4/netfilter/ipt_helper.c
@@ -107,6 +107,7 @@ static struct ipt_match helper_match = {
 
 static int __init init(void)
 {
+	need_ip_conntrack();
 	return ipt_register_match(&helper_match);
 }
 
diff --git a/net/ipv4/netfilter/ipt_mac.c b/net/ipv4/netfilter/ipt_mac.c
index 77109e046..11a459e33 100644
--- a/net/ipv4/netfilter/ipt_mac.c
+++ b/net/ipv4/netfilter/ipt_mac.c
@@ -33,7 +33,7 @@ match(const struct sk_buff *skb,
     return (skb->mac.raw >= skb->head
 	    && (skb->mac.raw + ETH_HLEN) <= skb->data
 	    /* If so, compare... */
-	    && ((memcmp(skb->mac.ethernet->h_source, info->srcaddr, ETH_ALEN)
+	    && ((memcmp(eth_hdr(skb)->h_source, info->srcaddr, ETH_ALEN)
 		== 0) ^ info->invert));
 }
 
diff --git a/net/ipv4/netfilter/ipt_multiport.c b/net/ipv4/netfilter/ipt_multiport.c
index 64e7999b0..7fdf41e22 100644
--- a/net/ipv4/netfilter/ipt_multiport.c
+++ b/net/ipv4/netfilter/ipt_multiport.c
@@ -54,7 +54,7 @@ match(const struct sk_buff *skb,
       int offset,
       int *hotdrop)
 {
-	u16 ports[2];
+	u16 _ports[2], *pptr;
 	const struct ipt_multiport *multiinfo = matchinfo;
 
 	/* Must not be a fragment. */
@@ -63,18 +63,21 @@ match(const struct sk_buff *skb,
 
 	/* Must be big enough to read ports (both UDP and TCP have
            them at the start). */
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
+	pptr = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+				  sizeof(_ports), &_ports[0]);
+	if (pptr == NULL) {
 		/* We've been asked to examine this packet, and we
-		   can't.  Hence, no choice but to drop. */
-			duprintf("ipt_multiport:"
-				 " Dropping evil offset=0 tinygram.\n");
-			*hotdrop = 1;
-			return 0;
+		 * can't.  Hence, no choice but to drop.
+		 */
+		duprintf("ipt_multiport:"
+			 " Dropping evil offset=0 tinygram.\n");
+		*hotdrop = 1;
+		return 0;
 	}
 
 	return ports_match(multiinfo->ports,
 			   multiinfo->flags, multiinfo->count,
-			   ntohs(ports[0]), ntohs(ports[1]));
+			   ntohs(pptr[0]), ntohs(pptr[1]));
 }
 
 /* Called when user tries to insert an entry of this type. */
diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c
index 3b9065e06..65b8365e3 100644
--- a/net/ipv4/netfilter/ipt_owner.c
+++ b/net/ipv4/netfilter/ipt_owner.c
@@ -61,7 +61,7 @@ match_pid(const struct sk_buff *skb, pid_t pid)
 	int i;
 
 	read_lock(&tasklist_lock);
-	p = find_task_by_pid(pid);
+	p = find_task_by_real_pid(pid);
 	if (!p)
 		goto out;
 	task_lock(p);
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 08b786ac3..15472b3e9 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -15,6 +15,7 @@
 #include <linux/ctype.h>
 #include <linux/ip.h>
 #include <linux/vmalloc.h>
+#include <linux/moduleparam.h>
 
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ipt_recent.h>
@@ -37,12 +38,12 @@ KERN_INFO RECENT_NAME " " RECENT_VER ": Stephen Frost <sfrost@snowman.net>.  htt
 MODULE_AUTHOR("Stephen Frost <sfrost@snowman.net>");
 MODULE_DESCRIPTION("IP tables recently seen matching module " RECENT_VER);
 MODULE_LICENSE("GPL");
-MODULE_PARM(ip_list_tot,"i");
-MODULE_PARM(ip_pkt_list_tot,"i");
-MODULE_PARM(ip_list_hash_size,"i");
-MODULE_PARM(ip_list_perms,"i");
+module_param(ip_list_tot, int, 0400);
+module_param(ip_pkt_list_tot, int, 0400);
+module_param(ip_list_hash_size, int, 0400);
+module_param(ip_list_perms, int, 0400);
 #ifdef DEBUG
-MODULE_PARM(debug,"i");
+module_param(debug, int, 0600);
 MODULE_PARM_DESC(debug,"debugging level, defaults to 1");
 #endif
 MODULE_PARM_DESC(ip_list_tot,"number of IPs to remember per list");
diff --git a/net/ipv4/netfilter/ipt_state.c b/net/ipv4/netfilter/ipt_state.c
index a3d40a439..b1511b97e 100644
--- a/net/ipv4/netfilter/ipt_state.c
+++ b/net/ipv4/netfilter/ipt_state.c
@@ -30,9 +30,9 @@ match(const struct sk_buff *skb,
 	enum ip_conntrack_info ctinfo;
 	unsigned int statebit;
 
-	if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
+	if (skb->nfct == &ip_conntrack_untracked.ct_general)
 		statebit = IPT_STATE_UNTRACKED;
-	else if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
+	else if (!ip_conntrack_get(skb, &ctinfo))
 		statebit = IPT_STATE_INVALID;
 	else
 		statebit = IPT_STATE_BIT(ctinfo);
diff --git a/net/ipv4/netfilter/ipt_tcpmss.c b/net/ipv4/netfilter/ipt_tcpmss.c
index c7cb62ade..5cda547e0 100644
--- a/net/ipv4/netfilter/ipt_tcpmss.c
+++ b/net/ipv4/netfilter/ipt_tcpmss.c
@@ -27,37 +27,45 @@ mssoption_match(u_int16_t min, u_int16_t max,
 		int invert,
 		int *hotdrop)
 {
-	struct tcphdr tcph;
+	struct tcphdr _tcph, *th;
 	/* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
-	u8 opt[15 * 4 - sizeof(tcph)];
+	u8 _opt[15 * 4 - sizeof(_tcph)], *op;
 	unsigned int i, optlen;
 
 	/* If we don't have the whole header, drop packet. */
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0)
+	th = skb_header_pointer(skb, skb->nh.iph->ihl * 4,
+				sizeof(_tcph), &_tcph);
+	if (th == NULL)
 		goto dropit;
 
 	/* Malformed. */
-	if (tcph.doff*4 < sizeof(tcph))
+	if (th->doff*4 < sizeof(*th))
 		goto dropit;
 
-	optlen = tcph.doff*4 - sizeof(tcph);
+	optlen = th->doff*4 - sizeof(*th);
+	if (!optlen)
+		goto out;
+
 	/* Truncated options. */
-	if (skb_copy_bits(skb, skb->nh.iph->ihl*4+sizeof(tcph), opt, optlen)<0)
+	op = skb_header_pointer(skb, skb->nh.iph->ihl * 4 + sizeof(*th),
+				optlen, _opt);
+	if (op == NULL)
 		goto dropit;
 
 	for (i = 0; i < optlen; ) {
-		if (opt[i] == TCPOPT_MSS
+		if (op[i] == TCPOPT_MSS
 		    && (optlen - i) >= TCPOLEN_MSS
-		    && opt[i+1] == TCPOLEN_MSS) {
+		    && op[i+1] == TCPOLEN_MSS) {
 			u_int16_t mssval;
 
-			mssval = (opt[i+2] << 8) | opt[i+3];
+			mssval = (op[i+2] << 8) | op[i+3];
 			
 			return (mssval >= min && mssval <= max) ^ invert;
 		}
-		if (opt[i] < 2) i++;
-		else i += opt[i+1]?:1;
+		if (op[i] < 2) i++;
+		else i += op[i+1]?:1;
 	}
+out:
 	return invert;
 
  dropit:
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 8fb2ed9d1..6b291da92 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -11,6 +11,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 
 MODULE_LICENSE("GPL");
@@ -155,7 +156,7 @@ static struct nf_hook_ops ipt_ops[] = {
 
 /* Default to forward because I got too much mail already. */
 static int forward = NF_ACCEPT;
-MODULE_PARM(forward, "i");
+module_param(forward, bool, 0000);
 
 static int __init init(void)
 {
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index fca126a09..912bbcc7f 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -330,7 +330,7 @@ static int netstat_seq_show(struct seq_file *seq, void *v)
 {
 	int i;
 
-	seq_puts(seq, "\nTcpExt:");
+	seq_puts(seq, "TcpExt:");
 	for (i = 0; snmp4_net_list[i].name != NULL; i++)
 		seq_printf(seq, " %s", snmp4_net_list[i].name);
 
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index e378ddcd8..d73ccfa2d 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -104,34 +104,23 @@ static void raw_v4_unhash(struct sock *sk)
 
 
 /*
-	Check if an address is in the list
-*/
-static inline int raw_addr_in_list (
-	u32 rcv_saddr1,
-	u32 rcv_saddr2,
-	u32 loc_addr,
-	struct nx_info *nx_info)
-{
-	int ret = 0;
-	if (loc_addr != 0 &&
-		(rcv_saddr1 == loc_addr || rcv_saddr2 == loc_addr))
-		ret = 1;
-	else if (rcv_saddr1 == 0) {
-		/* Accept any address or only the one in the list */
-		if (nx_info == NULL)
-			ret = 1;
-		else {
-			int n = nx_info->nbipv4;
-			int i;
-			for (i=0; i<n; i++) {
-				if (nx_info->ipv4[i] == loc_addr) {
-					ret = 1;
-					break;
-				}
-			}
-		}
-	}
-	return ret;
+ *	Check if a given address matches for a socket
+ *
+ *	nxi:		the socket's nx_info if any
+ *	addr:		to be verified address
+ *	saddr/baddr:	socket addresses
+ */
+static inline int raw_addr_match (
+	struct nx_info *nxi,
+	uint32_t addr,
+	uint32_t saddr,
+	uint32_t baddr)
+{
+	if (addr && (saddr == addr || baddr == addr))
+		return 1;
+	if (!saddr)
+		return addr_in_nx_info(nxi, addr);
+	return 0;
 }
 
 struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num,
@@ -145,8 +134,8 @@ struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num,
 
 		if (inet->num == num 					&&
 		    !(inet->daddr && inet->daddr != raddr) 		&&
-		    raw_addr_in_list(inet->rcv_saddr, inet->rcv_saddr2,
-			laddr, sk->sk_nx_info) &&
+		    raw_addr_match(sk->sk_nx_info, laddr,
+			inet->rcv_saddr, inet->rcv_saddr2)		&&
 		    !(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif))
 			goto found; /* gotcha */
 	}
@@ -340,7 +329,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, int length,
 	}
 	err = -EPERM;
 	if (!vx_check(0, VX_ADMIN) && !capable(CAP_NET_RAW)
-		&& (!raw_addr_in_list(0, 0, iph->saddr, sk->sk_nx_info)))
+		&& (!addr_in_nx_info(sk->sk_nx_info, iph->saddr)))
 		goto error;
 
 	err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
@@ -360,6 +349,51 @@ error:
 	return err; 
 }
 
+static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
+{
+	struct iovec *iov;
+	u8 __user *type = NULL;
+	u8 __user *code = NULL;
+	int probed = 0;
+	int i;
+
+	if (!msg->msg_iov)
+		return;
+
+	for (i = 0; i < msg->msg_iovlen; i++) {
+		iov = &msg->msg_iov[i];
+		if (!iov)
+			continue;
+
+		switch (fl->proto) {
+		case IPPROTO_ICMP:
+			/* check if one-byte field is readable or not. */
+			if (iov->iov_base && iov->iov_len < 1)
+				break;
+
+			if (!type) {
+				type = iov->iov_base;
+				/* check if code field is readable or not. */
+				if (iov->iov_len > 1)
+					code = type + 1;
+			} else if (!code)
+				code = iov->iov_base;
+
+			if (type && code) {
+				get_user(fl->fl_icmp_type, type);
+				__get_user(fl->fl_icmp_code, code);
+				probed = 1;
+			}
+			break;
+		default:
+			probed = 1;
+			break;
+		}
+		if (probed)
+			break;
+	}
+}
+
 static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 		       size_t len)
 {
@@ -466,7 +500,9 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 				    .proto = inet->hdrincl ? IPPROTO_RAW :
 					    		     sk->sk_protocol,
 				  };
-		
+		if (!inet->hdrincl)
+			raw_probe_proto_opt(&fl, msg);
+
 		if (sk->sk_nx_info) {
 			err = ip_find_src(sk->sk_nx_info, &rt, &fl);
 
@@ -715,6 +751,7 @@ struct proto raw_prot = {
 	.backlog_rcv =	raw_rcv_skb,
 	.hash =		raw_v4_hash,
 	.unhash =	raw_v4_unhash,
+	.slab_obj_size = sizeof(struct raw_sock),
 };
 
 #ifdef CONFIG_PROC_FS
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 15d9eca53..455cc0e77 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -226,26 +226,25 @@ static struct rtable *rt_cache_get_first(struct seq_file *seq)
 	struct rt_cache_iter_state *st = seq->private;
 
 	for (st->bucket = rt_hash_mask; st->bucket >= 0; --st->bucket) {
-		rcu_read_lock();
+		rcu_read_lock_bh();
 		r = rt_hash_table[st->bucket].chain;
 		if (r)
 			break;
-		rcu_read_unlock();
+		rcu_read_unlock_bh();
 	}
 	return r;
 }
 
 static struct rtable *rt_cache_get_next(struct seq_file *seq, struct rtable *r)
 {
-	struct rt_cache_iter_state *st = seq->private;
+	struct rt_cache_iter_state *st = rcu_dereference(seq->private);
 
-	smp_read_barrier_depends();
 	r = r->u.rt_next;
 	while (!r) {
-		rcu_read_unlock();
+		rcu_read_unlock_bh();
 		if (--st->bucket < 0)
 			break;
-		rcu_read_lock();
+		rcu_read_lock_bh();
 		r = rt_hash_table[st->bucket].chain;
 	}
 	return r;
@@ -281,7 +280,7 @@ static void *rt_cache_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 static void rt_cache_seq_stop(struct seq_file *seq, void *v)
 {
 	if (v && v != SEQ_START_TOKEN)
-		rcu_read_unlock();
+		rcu_read_unlock_bh();
 }
 
 static int rt_cache_seq_show(struct seq_file *seq, void *v)
@@ -357,10 +356,13 @@ static void *rt_cpu_seq_start(struct seq_file *seq, loff_t *pos)
 {
 	int cpu;
 
-	for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
+	if (*pos == 0)
+		return SEQ_START_TOKEN;
+
+	for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) {
 		if (!cpu_possible(cpu))
 			continue;
-		*pos = cpu;
+		*pos = cpu+1;
 		return per_cpu_ptr(rt_cache_stat, cpu);
 	}
 	return NULL;
@@ -370,10 +372,10 @@ static void *rt_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	int cpu;
 
-	for (cpu = *pos + 1; cpu < NR_CPUS; ++cpu) {
+	for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
 		if (!cpu_possible(cpu))
 			continue;
-		*pos = cpu;
+		*pos = cpu+1;
 		return per_cpu_ptr(rt_cache_stat, cpu);
 	}
 	return NULL;
@@ -388,6 +390,11 @@ static void rt_cpu_seq_stop(struct seq_file *seq, void *v)
 static int rt_cpu_seq_show(struct seq_file *seq, void *v)
 {
 	struct rt_cache_stat *st = v;
+
+	if (v == SEQ_START_TOKEN) {
+		seq_printf(seq, "entries  in_hit in_slow_tot in_no_route in_brd in_martian_dst in_martian_src  out_hit out_slow_tot out_slow_mc  gc_total gc_ignored gc_goal_miss gc_dst_overflow in_hlist_search out_hlist_search\n");
+		return 0;
+	}
 	
 	seq_printf(seq,"%08x  %08x %08x %08x %08x %08x %08x %08x "
 		   " %08x %08x %08x %08x %08x %08x %08x %08x %08x \n",
@@ -439,13 +446,13 @@ static struct file_operations rt_cpu_seq_fops = {
   
 static __inline__ void rt_free(struct rtable *rt)
 {
-	call_rcu(&rt->u.dst.rcu_head, dst_rcu_free);
+	call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
 }
 
 static __inline__ void rt_drop(struct rtable *rt)
 {
 	ip_rt_put(rt);
-	call_rcu(&rt->u.dst.rcu_head, dst_rcu_free);
+	call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
 }
 
 static __inline__ int rt_fast_clean(struct rtable *rth)
@@ -1004,10 +1011,9 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
 			rthp=&rt_hash_table[hash].chain;
 
 			rcu_read_lock();
-			while ((rth = *rthp) != NULL) {
+			while ((rth = rcu_dereference(*rthp)) != NULL) {
 				struct rtable *rt;
 
-				smp_read_barrier_depends();
 				if (rth->fl.fl4_dst != daddr ||
 				    rth->fl.fl4_src != skeys[i] ||
 				    rth->fl.fl4_tos != tos ||
@@ -1259,9 +1265,8 @@ unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu)
 		unsigned hash = rt_hash_code(daddr, skeys[i], tos);
 
 		rcu_read_lock();
-		for (rth = rt_hash_table[hash].chain; rth;
-		     rth = rth->u.rt_next) {
-			smp_read_barrier_depends();
+		for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
+		     rth = rcu_dereference(rth->u.rt_next)) {
 			if (rth->fl.fl4_dst == daddr &&
 			    rth->fl.fl4_src == skeys[i] &&
 			    rth->rt_dst  == daddr &&
@@ -1342,9 +1347,12 @@ static void ipv4_dst_ifdown(struct dst_entry *dst, int how)
 {
 	struct rtable *rt = (struct rtable *) dst;
 	struct in_device *idev = rt->idev;
-	if (idev) {
-		rt->idev = NULL;
-		in_dev_put(idev);
+	if (idev && idev->dev != &loopback_dev) {
+		struct in_device *loopback_idev = in_dev_get(&loopback_dev);
+		if (loopback_idev) {
+			rt->idev = loopback_idev;
+			in_dev_put(idev);
+		}
 	}
 }
 
@@ -1387,13 +1395,7 @@ void ip_rt_get_source(u8 *addr, struct rtable *rt)
 	if (rt->fl.iif == 0)
 		src = rt->rt_src;
 	else if (fib_lookup(&rt->fl, &res) == 0) {
-#ifdef CONFIG_IP_ROUTE_NAT
-		if (res.type == RTN_NAT)
-			src = inet_select_addr(rt->u.dst.dev, rt->rt_gateway,
-						RT_SCOPE_UNIVERSE);
-		else
-#endif
-			src = FIB_RES_PREFSRC(res);
+		src = FIB_RES_PREFSRC(res);
 		fib_res_put(&res);
 	} else
 		src = inet_select_addr(rt->u.dst.dev, rt->rt_gateway,
@@ -1497,10 +1499,6 @@ static int ip_route_input_mc(struct sk_buff *skb, u32 daddr, u32 saddr,
 #endif
 	rth->fl.fl4_src	= saddr;
 	rth->rt_src	= saddr;
-#ifdef CONFIG_IP_ROUTE_NAT
-	rth->rt_dst_map	= daddr;
-	rth->rt_src_map	= saddr;
-#endif
 #ifdef CONFIG_NET_CLS_ROUTE
 	rth->u.dst.tclassid = itag;
 #endif
@@ -1610,31 +1608,6 @@ static int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr,
 
 	RT_CACHE_STAT_INC(in_slow_tot);
 
-#ifdef CONFIG_IP_ROUTE_NAT
-	/* Policy is applied before mapping destination,
-	   but rerouting after map should be made with old source.
-	 */
-
-	if (1) {
-		u32 src_map = saddr;
-		if (res.r)
-			src_map = fib_rules_policy(saddr, &res, &flags);
-
-		if (res.type == RTN_NAT) {
-			fl.fl4_dst = fib_rules_map_destination(daddr, &res);
-			fib_res_put(&res);
-			free_res = 0;
-			if (fib_lookup(&fl, &res))
-				goto e_inval;
-			free_res = 1;
-			if (res.type != RTN_UNICAST)
-				goto e_inval;
-			flags |= RTCF_DNAT;
-		}
-		fl.fl4_src = src_map;
-	}
-#endif
-
 	if (res.type == RTN_BROADCAST)
 		goto brd_input;
 
@@ -1708,12 +1681,6 @@ static int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr,
 	rth->fl.fl4_src	= saddr;
 	rth->rt_src	= saddr;
 	rth->rt_gateway	= daddr;
-#ifdef CONFIG_IP_ROUTE_NAT
-	rth->rt_src_map	= fl.fl4_src;
-	rth->rt_dst_map	= fl.fl4_dst;
-	if (flags&RTCF_DNAT)
-		rth->rt_gateway	= fl.fl4_dst;
-#endif
 	rth->rt_iif 	=
 	rth->fl.iif	= dev->ifindex;
 	rth->u.dst.dev	= out_dev->dev;
@@ -1776,10 +1743,6 @@ local_input:
 #endif
 	rth->fl.fl4_src	= saddr;
 	rth->rt_src	= saddr;
-#ifdef CONFIG_IP_ROUTE_NAT
-	rth->rt_dst_map	= fl.fl4_dst;
-	rth->rt_src_map	= fl.fl4_src;
-#endif
 #ifdef CONFIG_NET_CLS_ROUTE
 	rth->u.dst.tclassid = itag;
 #endif
@@ -1864,8 +1827,8 @@ int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
 	hash = rt_hash_code(daddr, saddr ^ (iif << 5), tos);
 
 	rcu_read_lock();
-	for (rth = rt_hash_table[hash].chain; rth; rth = rth->u.rt_next) {
-		smp_read_barrier_depends();
+	for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
+	     rth = rcu_dereference(rth->u.rt_next)) {
 		if (rth->fl.fl4_dst == daddr &&
 		    rth->fl.fl4_src == saddr &&
 		    rth->fl.iif == iif &&
@@ -1900,7 +1863,7 @@ int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
 	if (MULTICAST(daddr)) {
 		struct in_device *in_dev;
 
-		read_lock(&inetdev_lock);
+		rcu_read_lock();
 		if ((in_dev = __in_dev_get(dev)) != NULL) {
 			int our = ip_check_mc(in_dev, daddr, saddr,
 				skb->nh.iph->protocol);
@@ -1909,12 +1872,12 @@ int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
 			    || (!LOCAL_MCAST(daddr) && IN_DEV_MFORWARD(in_dev))
 #endif
 			    ) {
-				read_unlock(&inetdev_lock);
+				rcu_read_unlock();
 				return ip_route_input_mc(skb, daddr, saddr,
 							 tos, dev, our);
 			}
 		}
-		read_unlock(&inetdev_lock);
+		rcu_read_unlock();
 		return -EINVAL;
 	}
 	return ip_route_input_slow(skb, daddr, saddr, tos, dev);
@@ -2072,9 +2035,6 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
 	}
 	free_res = 1;
 
-	if (res.type == RTN_NAT)
-		goto e_inval;
-
 	if (res.type == RTN_LOCAL) {
 		if (!fl.fl4_src)
 			fl.fl4_src = fl.fl4_dst;
@@ -2164,10 +2124,6 @@ make_route:
 #endif
 	rth->rt_dst	= fl.fl4_dst;
 	rth->rt_src	= fl.fl4_src;
-#ifdef CONFIG_IP_ROUTE_NAT
-	rth->rt_dst_map	= fl.fl4_dst;
-	rth->rt_src_map	= fl.fl4_src;
-#endif
 	rth->rt_iif	= oldflp->oif ? : dev_out->ifindex;
 	rth->u.dst.dev	= dev_out;
 	dev_hold(dev_out);
@@ -2231,9 +2187,9 @@ int __ip_route_output_key(struct rtable **rp, const struct flowi *flp)
 
 	hash = rt_hash_code(flp->fl4_dst, flp->fl4_src ^ (flp->oif << 5), flp->fl4_tos);
 
-	rcu_read_lock();
-	for (rth = rt_hash_table[hash].chain; rth; rth = rth->u.rt_next) {
-		smp_read_barrier_depends();
+	rcu_read_lock_bh();
+	for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
+		rth = rcu_dereference(rth->u.rt_next)) {
 		if (rth->fl.fl4_dst == flp->fl4_dst &&
 		    rth->fl.fl4_src == flp->fl4_src &&
 		    rth->fl.iif == 0 &&
@@ -2247,33 +2203,38 @@ int __ip_route_output_key(struct rtable **rp, const struct flowi *flp)
 			dst_hold(&rth->u.dst);
 			rth->u.dst.__use++;
 			RT_CACHE_STAT_INC(out_hit);
-			rcu_read_unlock();
+			rcu_read_unlock_bh();
 			*rp = rth;
 			return 0;
 		}
 		RT_CACHE_STAT_INC(out_hlist_search);
 	}
-	rcu_read_unlock();
+	rcu_read_unlock_bh();
 
 	return ip_route_output_slow(rp, flp);
 }
 
-int ip_route_output_key(struct rtable **rp, struct flowi *flp)
+int ip_route_output_flow(struct rtable **rp, struct flowi *flp, struct sock *sk, int flags)
 {
 	int err;
 
 	if ((err = __ip_route_output_key(rp, flp)) != 0)
 		return err;
-	return flp->proto ? xfrm_lookup((struct dst_entry**)rp, flp, NULL, 0) : 0;
+
+	if (flp->proto) {
+		if (!flp->fl4_src)
+			flp->fl4_src = (*rp)->rt_src;
+		if (!flp->fl4_dst)
+			flp->fl4_dst = (*rp)->rt_dst;
+		return xfrm_lookup((struct dst_entry **)rp, flp, sk, flags);
+	}
+
+	return 0;
 }
 
-int ip_route_output_flow(struct rtable **rp, struct flowi *flp, struct sock *sk, int flags)
+int ip_route_output_key(struct rtable **rp, struct flowi *flp)
 {
-	int err;
-
-	if ((err = __ip_route_output_key(rp, flp)) != 0)
-		return err;
-	return flp->proto ? xfrm_lookup((struct dst_entry**)rp, flp, sk, flags) : 0;
+	return ip_route_output_flow(rp, flp, NULL, 0);
 }
 
 static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
@@ -2463,10 +2424,9 @@ int ip_rt_dump(struct sk_buff *skb,  struct netlink_callback *cb)
 		if (h < s_h) continue;
 		if (h > s_h)
 			s_idx = 0;
-		rcu_read_lock();
-		for (rt = rt_hash_table[h].chain, idx = 0; rt;
-		     rt = rt->u.rt_next, idx++) {
-			smp_read_barrier_depends();
+		rcu_read_lock_bh();
+		for (rt = rcu_dereference(rt_hash_table[h].chain), idx = 0; rt;
+		     rt = rcu_dereference(rt->u.rt_next), idx++) {
 			if (idx < s_idx)
 				continue;
 			skb->dst = dst_clone(&rt->u.dst);
@@ -2474,12 +2434,12 @@ int ip_rt_dump(struct sk_buff *skb,  struct netlink_callback *cb)
 					 cb->nlh->nlmsg_seq,
 					 RTM_NEWROUTE, 1) <= 0) {
 				dst_release(xchg(&skb->dst, NULL));
-				rcu_read_unlock();
+				rcu_read_unlock_bh();
 				goto done;
 			}
 			dst_release(xchg(&skb->dst, NULL));
 		}
-		rcu_read_unlock();
+		rcu_read_unlock_bh();
 	}
 
 done:
@@ -2831,12 +2791,16 @@ int __init ip_rt_init(void)
 	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) ||
-	    !proc_net_fops_create("rt_cache_stat", S_IRUGO, &rt_cpu_seq_fops)) {
+	    !(rtstat_pde = create_proc_entry("rt_cache", S_IRUGO, 
+			    		     proc_net_stat))) {
 		free_percpu(rt_cache_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
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 55cc26922..d567f4a9f 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -667,17 +667,17 @@ ctl_table ipv4_table[] = {
 		.proc_handler	= &proc_dointvec,
 	},
 	{
-		.ctl_name	= NET_TCP_DEFAULT_WIN_SCALE,
-		.procname	= "tcp_default_win_scale",
-		.data		= &sysctl_tcp_default_win_scale,
+		.ctl_name	= NET_TCP_MODERATE_RCVBUF,
+		.procname	= "tcp_moderate_rcvbuf",
+		.data		= &sysctl_tcp_moderate_rcvbuf,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
 	},
 	{
-		.ctl_name	= NET_TCP_MODERATE_RCVBUF,
-		.procname	= "tcp_moderate_rcvbuf",
-		.data		= &sysctl_tcp_moderate_rcvbuf,
+		.ctl_name	= NET_TCP_TSO_WIN_DIVISOR,
+		.procname	= "tcp_tso_win_divisor",
+		.data		= &sysctl_tcp_tso_win_divisor,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 90d85538f..462cbda02 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -276,8 +276,6 @@ kmem_cache_t *tcp_timewait_cachep;
 
 atomic_t tcp_orphan_count = ATOMIC_INIT(0);
 
-int sysctl_tcp_default_win_scale = 7;
-
 int sysctl_tcp_mem[3];
 int sysctl_tcp_wmem[3] = { 4 * 1024, 16 * 1024, 128 * 1024 };
 int sysctl_tcp_rmem[3] = { 4 * 1024, 87380, 87380 * 2 };
@@ -693,6 +691,7 @@ new_segment:
 		skb->ip_summed = CHECKSUM_HW;
 		tp->write_seq += copy;
 		TCP_SKB_CB(skb)->end_seq += copy;
+		skb_shinfo(skb)->tso_segs = 0;
 
 		if (!copied)
 			TCP_SKB_CB(skb)->flags &= ~TCPCB_FLAG_PSH;
@@ -939,6 +938,7 @@ new_segment:
 
 			tp->write_seq += copy;
 			TCP_SKB_CB(skb)->end_seq += copy;
+			skb_shinfo(skb)->tso_segs = 0;
 
 			from += copy;
 			copied += copy;
@@ -1593,14 +1593,6 @@ void tcp_destroy_sock(struct sock *sk)
 	/* If it has not 0 inet_sk(sk)->num, it must be bound */
 	BUG_TRAP(!inet_sk(sk)->num || tcp_sk(sk)->bind_hash);
 
-#ifdef TCP_DEBUG
-	if (sk->sk_zapped) {
-		printk(KERN_DEBUG "TCP: double destroy sk=%p\n", sk);
-		sock_hold(sk);
-	}
-	sk->sk_zapped = 1;
-#endif
-
 	sk->sk_prot->destroy(sk);
 
 	sk_stream_kill_queues(sk);
@@ -1820,7 +1812,7 @@ int tcp_disconnect(struct sock *sk, int flags)
 	tp->backoff = 0;
 	tp->snd_cwnd = 2;
 	tp->probes_out = 0;
-	tp->packets_out = 0;
+	tcp_set_pcount(&tp->packets_out, 0);
 	tp->snd_ssthresh = 0x7fffffff;
 	tp->snd_cwnd_cnt = 0;
 	tcp_set_ca_state(tp, TCP_CA_Open);
diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c
index 5506944b7..3e23c6de5 100644
--- a/net/ipv4/tcp_diag.c
+++ b/net/ipv4/tcp_diag.c
@@ -68,31 +68,31 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
 	if (tp->ecn_flags&TCP_ECN_OK)
 		info->tcpi_options |= TCPI_OPT_ECN;
 
-	info->tcpi_rto = (1000000*tp->rto)/HZ;
-	info->tcpi_ato = (1000000*tp->ack.ato)/HZ;
-	info->tcpi_snd_mss = tp->mss_cache;
+	info->tcpi_rto = jiffies_to_usecs(tp->rto);
+	info->tcpi_ato = jiffies_to_usecs(tp->ack.ato);
+	info->tcpi_snd_mss = tp->mss_cache_std;
 	info->tcpi_rcv_mss = tp->ack.rcv_mss;
 
-	info->tcpi_unacked = tp->packets_out;
-	info->tcpi_sacked = tp->sacked_out;
-	info->tcpi_lost = tp->lost_out;
-	info->tcpi_retrans = tp->retrans_out;
-	info->tcpi_fackets = tp->fackets_out;
+	info->tcpi_unacked = tcp_get_pcount(&tp->packets_out);
+	info->tcpi_sacked = tcp_get_pcount(&tp->sacked_out);
+	info->tcpi_lost = tcp_get_pcount(&tp->lost_out);
+	info->tcpi_retrans = tcp_get_pcount(&tp->retrans_out);
+	info->tcpi_fackets = tcp_get_pcount(&tp->fackets_out);
 
-	info->tcpi_last_data_sent = ((now - tp->lsndtime)*1000)/HZ;
-	info->tcpi_last_data_recv = ((now - tp->ack.lrcvtime)*1000)/HZ;
-	info->tcpi_last_ack_recv = ((now - tp->rcv_tstamp)*1000)/HZ;
+	info->tcpi_last_data_sent = jiffies_to_msecs(now - tp->lsndtime);
+	info->tcpi_last_data_recv = jiffies_to_msecs(now - tp->ack.lrcvtime);
+	info->tcpi_last_ack_recv = jiffies_to_msecs(now - tp->rcv_tstamp);
 
 	info->tcpi_pmtu = tp->pmtu_cookie;
 	info->tcpi_rcv_ssthresh = tp->rcv_ssthresh;
-	info->tcpi_rtt = ((1000000*tp->srtt)/HZ)>>3;
-	info->tcpi_rttvar = ((1000000*tp->mdev)/HZ)>>2;
+	info->tcpi_rtt = jiffies_to_usecs(tp->srtt)>>3;
+	info->tcpi_rttvar = jiffies_to_usecs(tp->mdev)>>2;
 	info->tcpi_snd_ssthresh = tp->snd_ssthresh;
 	info->tcpi_snd_cwnd = tp->snd_cwnd;
 	info->tcpi_advmss = tp->advmss;
 	info->tcpi_reordering = tp->reordering;
 
-	info->tcpi_rcv_rtt = ((1000000*tp->rcv_rtt_est.rtt)/HZ)>>3;
+	info->tcpi_rcv_rtt = jiffies_to_usecs(tp->rcv_rtt_est.rtt)>>3;
 	info->tcpi_rcv_space = tp->rcvq_space.space;
 }
 
@@ -116,7 +116,8 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
 		if (ext & (1<<(TCPDIAG_INFO-1)))
 			info = TCPDIAG_PUT(skb, TCPDIAG_INFO, sizeof(*info));
 		
-		if (tcp_is_vegas(tp) && (ext & (1<<(TCPDIAG_VEGASINFO-1))))
+		if ((tcp_is_westwood(tp) || tcp_is_vegas(tp))
+		    && (ext & (1<<(TCPDIAG_VEGASINFO-1))))
 			vinfo = TCPDIAG_PUT(skb, TCPDIAG_VEGASINFO, sizeof(*vinfo));
 	}
 	r->tcpdiag_family = sk->sk_family;
@@ -209,10 +210,17 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
 		tcp_get_info(sk, info);
 
 	if (vinfo) {
-		vinfo->tcpv_enabled = tp->vegas.doing_vegas_now;
-		vinfo->tcpv_rttcnt = tp->vegas.cntRTT;
-		vinfo->tcpv_rtt = tp->vegas.baseRTT;
-		vinfo->tcpv_minrtt = tp->vegas.minRTT;
+		if (tcp_is_vegas(tp)) {
+			vinfo->tcpv_enabled = tp->vegas.doing_vegas_now;
+			vinfo->tcpv_rttcnt = tp->vegas.cntRTT;
+			vinfo->tcpv_rtt = jiffies_to_usecs(tp->vegas.baseRTT);
+			vinfo->tcpv_minrtt = jiffies_to_usecs(tp->vegas.minRTT);
+		} else {
+			vinfo->tcpv_enabled = 0;
+			vinfo->tcpv_rttcnt = 0;
+			vinfo->tcpv_rtt = jiffies_to_usecs(tp->westwood.rtt);
+			vinfo->tcpv_minrtt = jiffies_to_usecs(tp->westwood.rtt_min);
+		}
 	}
 
 	nlh->nlmsg_len = skb->tail - b;
@@ -487,21 +495,22 @@ static int tcpdiag_dump(struct sk_buff *skb, struct netlink_callback *cb)
 			sk_for_each(sk, node, &tcp_listening_hash[i]) {
 				struct inet_opt *inet = inet_sk(sk);
 				if (num < s_num)
-					continue;
+					goto next_listen;
 				if (!(r->tcpdiag_states&TCPF_LISTEN) ||
 				    r->id.tcpdiag_dport)
-					continue;
+					goto next_listen;
 				if (r->id.tcpdiag_sport != inet->sport &&
 				    r->id.tcpdiag_sport)
-					continue;
+					goto next_listen;
 				if (bc && !tcpdiag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), sk))
-					continue;
+					goto next_listen;
 				if (tcpdiag_fill(skb, sk, r->tcpdiag_ext,
 						 NETLINK_CB(cb->skb).pid,
 						 cb->nlh->nlmsg_seq) <= 0) {
 					tcp_listen_unlock();
 					goto done;
 				}
+next_listen:
 				++num;
 			}
 		}
@@ -529,22 +538,23 @@ skip_listen_ht:
 			struct inet_opt *inet = inet_sk(sk);
 
 			if (num < s_num)
-				continue;
+				goto next_normal;
 			if (!(r->tcpdiag_states & (1 << sk->sk_state)))
-				continue;
+				goto next_normal;
 			if (r->id.tcpdiag_sport != inet->sport &&
 			    r->id.tcpdiag_sport)
-				continue;
+				goto next_normal;
 			if (r->id.tcpdiag_dport != inet->dport && r->id.tcpdiag_dport)
-				continue;
+				goto next_normal;
 			if (bc && !tcpdiag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), sk))
-				continue;
+				goto next_normal;
 			if (tcpdiag_fill(skb, sk, r->tcpdiag_ext,
 					 NETLINK_CB(cb->skb).pid,
 					 cb->nlh->nlmsg_seq) <= 0) {
 				read_unlock_bh(&head->lock);
 				goto done;
 			}
+next_normal:
 			++num;
 		}
 
@@ -554,23 +564,22 @@ skip_listen_ht:
 				struct inet_opt *inet = inet_sk(sk);
 
 				if (num < s_num)
-					continue;
-				if (!(r->tcpdiag_states & (1 << sk->sk_zapped)))
-					continue;
+					goto next_dying;
 				if (r->id.tcpdiag_sport != inet->sport &&
 				    r->id.tcpdiag_sport)
-					continue;
+					goto next_dying;
 				if (r->id.tcpdiag_dport != inet->dport &&
 				    r->id.tcpdiag_dport)
-					continue;
+					goto next_dying;
 				if (bc && !tcpdiag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), sk))
-					continue;
+					goto next_dying;
 				if (tcpdiag_fill(skb, sk, r->tcpdiag_ext,
 						 NETLINK_CB(cb->skb).pid,
 						 cb->nlh->nlmsg_seq) <= 0) {
 					read_unlock_bh(&head->lock);
 					goto done;
 				}
+next_dying:
 				++num;
 			}
 		}
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 5e7f70f1c..ece320e60 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -555,17 +555,20 @@ static void tcp_event_data_recv(struct sock *sk, struct tcp_opt *tp, struct sk_b
 		tcp_grow_window(sk, tp, skb);
 }
 
-/* Set up a new TCP connection, depending on whether it should be
- * using Vegas or not.
- */    
-void tcp_vegas_init(struct tcp_opt *tp)
+/* When starting a new connection, pin down the current choice of 
+ * congestion algorithm.
+ */
+void tcp_ca_init(struct tcp_opt *tp)
 {
-	if (sysctl_tcp_vegas_cong_avoid) {
-		tp->vegas.do_vegas = 1;
+	if (sysctl_tcp_westwood) 
+		tp->adv_cong = TCP_WESTWOOD;
+	else if (sysctl_tcp_bic)
+		tp->adv_cong = TCP_BIC;
+	else if (sysctl_tcp_vegas_cong_avoid) {
+		tp->adv_cong = TCP_VEGAS;
 		tp->vegas.baseRTT = 0x7fffffff;
 		tcp_vegas_enable(tp);
-	} else 
-		tcp_vegas_disable(tp);
+	} 
 }
 
 /* Do RTT sampling needed for Vegas.
@@ -799,10 +802,10 @@ __u32 tcp_init_cwnd(struct tcp_opt *tp, struct dst_entry *dst)
 	__u32 cwnd = (dst ? dst_metric(dst, RTAX_INITCWND) : 0);
 
 	if (!cwnd) {
-		if (tp->mss_cache > 1460)
+		if (tp->mss_cache_std > 1460)
 			cwnd = 2;
 		else
-			cwnd = (tp->mss_cache > 1095) ? 3 : 4;
+			cwnd = (tp->mss_cache_std > 1095) ? 3 : 4;
 	}
 	return min_t(__u32, cwnd, tp->snd_cwnd_clamp);
 }
@@ -852,8 +855,10 @@ static void tcp_init_metrics(struct sock *sk)
 	 * to low value, and then abruptly stops to do it and starts to delay
 	 * ACKs, wait for troubles.
 	 */
-	if (dst_metric(dst, RTAX_RTT) > tp->srtt)
+	if (dst_metric(dst, RTAX_RTT) > tp->srtt) {
 		tp->srtt = dst_metric(dst, RTAX_RTT);
+		tp->rtt_seq = tp->snd_nxt;
+	}
 	if (dst_metric(dst, RTAX_RTTVAR) > tp->mdev) {
 		tp->mdev = dst_metric(dst, RTAX_RTTVAR);
 		tp->mdev_max = tp->rttvar = max(tp->mdev, TCP_RTO_MIN);
@@ -895,7 +900,9 @@ static void tcp_update_reordering(struct tcp_opt *tp, int metric, int ts)
 #if FASTRETRANS_DEBUG > 1
 		printk(KERN_DEBUG "Disorder%d %d %u f%u s%u rr%d\n",
 		       tp->sack_ok, tp->ca_state,
-		       tp->reordering, tp->fackets_out, tp->sacked_out,
+		       tp->reordering,
+		       tcp_get_pcount(&tp->fackets_out),
+		       tcp_get_pcount(&tp->sacked_out),
 		       tp->undo_marker ? tp->undo_retrans : 0);
 #endif
 		/* Disable FACK yet. */
@@ -958,7 +965,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
 	unsigned char *ptr = ack_skb->h.raw + TCP_SKB_CB(ack_skb)->sacked;
 	struct tcp_sack_block *sp = (struct tcp_sack_block *)(ptr+2);
 	int num_sacks = (ptr[1] - TCPOLEN_SACK_BASE)>>3;
-	int reord = tp->packets_out;
+	int reord = tcp_get_pcount(&tp->packets_out);
 	int prior_fackets;
 	u32 lost_retrans = 0;
 	int flag = 0;
@@ -972,9 +979,9 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
 		tp->mss_cache = tp->mss_cache_std;
 	}
 
-	if (!tp->sacked_out)
-		tp->fackets_out = 0;
-	prior_fackets = tp->fackets_out;
+	if (!tcp_get_pcount(&tp->sacked_out))
+		tcp_set_pcount(&tp->fackets_out, 0);
+	prior_fackets = tcp_get_pcount(&tp->fackets_out);
 
 	for (i=0; i<num_sacks; i++, sp++) {
 		struct sk_buff *skb;
@@ -1028,7 +1035,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
 			if(!before(TCP_SKB_CB(skb)->seq, end_seq))
 				break;
 
-			fack_count++;
+			fack_count += tcp_skb_pcount(skb);
 
 			in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) &&
 				!before(end_seq, TCP_SKB_CB(skb)->end_seq);
@@ -1072,8 +1079,8 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
 					 */
 					if (sacked & TCPCB_LOST) {
 						TCP_SKB_CB(skb)->sacked &= ~(TCPCB_LOST|TCPCB_SACKED_RETRANS);
-						tp->lost_out--;
-						tp->retrans_out--;
+						tcp_dec_pcount(&tp->lost_out, skb);
+						tcp_dec_pcount(&tp->retrans_out, skb);
 					}
 				} else {
 					/* New sack for not retransmitted frame,
@@ -1085,16 +1092,16 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
 
 					if (sacked & TCPCB_LOST) {
 						TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST;
-						tp->lost_out--;
+						tcp_dec_pcount(&tp->lost_out, skb);
 					}
 				}
 
 				TCP_SKB_CB(skb)->sacked |= TCPCB_SACKED_ACKED;
 				flag |= FLAG_DATA_SACKED;
-				tp->sacked_out++;
+				tcp_inc_pcount(&tp->sacked_out, skb);
 
-				if (fack_count > tp->fackets_out)
-					tp->fackets_out = fack_count;
+				if (fack_count > tcp_get_pcount(&tp->fackets_out))
+					tcp_set_pcount(&tp->fackets_out, fack_count);
 			} else {
 				if (dup_sack && (sacked&TCPCB_RETRANS))
 					reord = min(fack_count, reord);
@@ -1108,7 +1115,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
 			if (dup_sack &&
 			    (TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_RETRANS)) {
 				TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
-				tp->retrans_out--;
+				tcp_dec_pcount(&tp->retrans_out, skb);
 			}
 		}
 	}
@@ -1132,12 +1139,12 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
 			    (IsFack(tp) ||
 			     !before(lost_retrans,
 				     TCP_SKB_CB(skb)->ack_seq + tp->reordering *
-				     tp->mss_cache))) {
+				     tp->mss_cache_std))) {
 				TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
-				tp->retrans_out--;
+				tcp_dec_pcount(&tp->retrans_out, skb);
 
 				if (!(TCP_SKB_CB(skb)->sacked&(TCPCB_LOST|TCPCB_SACKED_ACKED))) {
-					tp->lost_out++;
+					tcp_inc_pcount(&tp->lost_out, skb);
 					TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
 					flag |= FLAG_DATA_SACKED;
 					NET_INC_STATS_BH(LINUX_MIB_TCPLOSTRETRANSMIT);
@@ -1146,15 +1153,20 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
 		}
 	}
 
-	tp->left_out = tp->sacked_out + tp->lost_out;
+	tcp_set_pcount(&tp->left_out,
+		       (tcp_get_pcount(&tp->sacked_out) +
+			tcp_get_pcount(&tp->lost_out)));
 
-	if (reord < tp->fackets_out && tp->ca_state != TCP_CA_Loss)
-		tcp_update_reordering(tp, (tp->fackets_out + 1) - reord, 0);
+	if ((reord < tcp_get_pcount(&tp->fackets_out)) &&
+	    tp->ca_state != TCP_CA_Loss)
+		tcp_update_reordering(tp,
+				      ((tcp_get_pcount(&tp->fackets_out) + 1) -
+				       reord), 0);
 
 #if FASTRETRANS_DEBUG > 0
-	BUG_TRAP((int)tp->sacked_out >= 0);
-	BUG_TRAP((int)tp->lost_out >= 0);
-	BUG_TRAP((int)tp->retrans_out >= 0);
+	BUG_TRAP((int)tcp_get_pcount(&tp->sacked_out) >= 0);
+	BUG_TRAP((int)tcp_get_pcount(&tp->lost_out) >= 0);
+	BUG_TRAP((int)tcp_get_pcount(&tp->retrans_out) >= 0);
 	BUG_TRAP((int)tcp_packets_in_flight(tp) >= 0);
 #endif
 	return flag;
@@ -1184,7 +1196,7 @@ void tcp_enter_frto(struct sock *sk)
 	 * If something was really lost, it is eventually caught up
 	 * in tcp_enter_frto_loss.
 	 */
-	tp->retrans_out = 0;
+	tcp_set_pcount(&tp->retrans_out, 0);
 	tp->undo_marker = tp->snd_una;
 	tp->undo_retrans = 0;
 
@@ -1207,26 +1219,26 @@ static void tcp_enter_frto_loss(struct sock *sk)
 	struct sk_buff *skb;
 	int cnt = 0;
 
-	tp->sacked_out = 0;
-	tp->lost_out = 0;
-	tp->fackets_out = 0;
+	tcp_set_pcount(&tp->sacked_out, 0);
+	tcp_set_pcount(&tp->lost_out, 0);
+	tcp_set_pcount(&tp->fackets_out, 0);
 
 	sk_stream_for_retrans_queue(skb, sk) {
-		cnt++;
+		cnt += tcp_skb_pcount(skb);
 		TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST;
 		if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED)) {
 
 			/* Do not mark those segments lost that were
 			 * forward transmitted after RTO
 			 */
-			if(!after(TCP_SKB_CB(skb)->end_seq,
+			if (!after(TCP_SKB_CB(skb)->end_seq,
 				   tp->frto_highmark)) {
 				TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
-				tp->lost_out++;
+				tcp_inc_pcount(&tp->lost_out, skb);
 			}
 		} else {
-			tp->sacked_out++;
-			tp->fackets_out = cnt;
+			tcp_inc_pcount(&tp->sacked_out, skb);
+			tcp_set_pcount(&tp->fackets_out, cnt);
 		}
 	}
 	tcp_sync_left_out(tp);
@@ -1248,12 +1260,12 @@ static void tcp_enter_frto_loss(struct sock *sk)
 
 void tcp_clear_retrans(struct tcp_opt *tp)
 {
-	tp->left_out = 0;
-	tp->retrans_out = 0;
+	tcp_set_pcount(&tp->left_out, 0);
+	tcp_set_pcount(&tp->retrans_out, 0);
 
-	tp->fackets_out = 0;
-	tp->sacked_out = 0;
-	tp->lost_out = 0;
+	tcp_set_pcount(&tp->fackets_out, 0);
+	tcp_set_pcount(&tp->sacked_out, 0);
+	tcp_set_pcount(&tp->lost_out, 0);
 
 	tp->undo_marker = 0;
 	tp->undo_retrans = 0;
@@ -1287,17 +1299,17 @@ void tcp_enter_loss(struct sock *sk, int how)
 		tp->undo_marker = tp->snd_una;
 
 	sk_stream_for_retrans_queue(skb, sk) {
-		cnt++;
+		cnt += tcp_skb_pcount(skb);
 		if (TCP_SKB_CB(skb)->sacked&TCPCB_RETRANS)
 			tp->undo_marker = 0;
 		TCP_SKB_CB(skb)->sacked &= (~TCPCB_TAGBITS)|TCPCB_SACKED_ACKED;
 		if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED) || how) {
 			TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED;
 			TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
-			tp->lost_out++;
+			tcp_inc_pcount(&tp->lost_out, skb);
 		} else {
-			tp->sacked_out++;
-			tp->fackets_out = cnt;
+			tcp_inc_pcount(&tp->sacked_out, skb);
+			tcp_set_pcount(&tp->fackets_out, cnt);
 		}
 	}
 	tcp_sync_left_out(tp);
@@ -1334,7 +1346,8 @@ static int tcp_check_sack_reneging(struct sock *sk, struct tcp_opt *tp)
 
 static inline int tcp_fackets_out(struct tcp_opt *tp)
 {
-	return IsReno(tp) ? tp->sacked_out+1 : tp->fackets_out;
+	return IsReno(tp) ? tcp_get_pcount(&tp->sacked_out)+1 :
+		tcp_get_pcount(&tp->fackets_out);
 }
 
 static inline int tcp_skb_timedout(struct tcp_opt *tp, struct sk_buff *skb)
@@ -1344,7 +1357,7 @@ static inline int tcp_skb_timedout(struct tcp_opt *tp, struct sk_buff *skb)
 
 static inline int tcp_head_timedout(struct sock *sk, struct tcp_opt *tp)
 {
-	return tp->packets_out &&
+	return tcp_get_pcount(&tp->packets_out) &&
 	       tcp_skb_timedout(tp, skb_peek(&sk->sk_write_queue));
 }
 
@@ -1444,8 +1457,10 @@ static inline int tcp_head_timedout(struct sock *sk, struct tcp_opt *tp)
 static int
 tcp_time_to_recover(struct sock *sk, struct tcp_opt *tp)
 {
+	__u32 packets_out;
+
 	/* Trick#1: The loss is proven. */
-	if (tp->lost_out)
+	if (tcp_get_pcount(&tp->lost_out))
 		return 1;
 
 	/* Not-A-Trick#2 : Classic rule... */
@@ -1461,8 +1476,9 @@ tcp_time_to_recover(struct sock *sk, struct tcp_opt *tp)
 	/* Trick#4: It is still not OK... But will it be useful to delay
 	 * recovery more?
 	 */
-	if (tp->packets_out <= tp->reordering &&
-	    tp->sacked_out >= max_t(__u32, tp->packets_out/2, sysctl_tcp_reordering) &&
+	packets_out = tcp_get_pcount(&tp->packets_out);
+	if (packets_out <= tp->reordering &&
+	    tcp_get_pcount(&tp->sacked_out) >= max_t(__u32, packets_out/2, sysctl_tcp_reordering) &&
 	    !tcp_may_send_now(sk, tp)) {
 		/* We have nothing to send. This connection is limited
 		 * either by receiver window or by application.
@@ -1481,12 +1497,16 @@ static void tcp_check_reno_reordering(struct tcp_opt *tp, int addend)
 {
 	u32 holes;
 
-	holes = max(tp->lost_out, 1U);
-	holes = min(holes, tp->packets_out);
+	holes = max(tcp_get_pcount(&tp->lost_out), 1U);
+	holes = min(holes, tcp_get_pcount(&tp->packets_out));
 
-	if (tp->sacked_out + holes > tp->packets_out) {
-		tp->sacked_out = tp->packets_out - holes;
-		tcp_update_reordering(tp, tp->packets_out+addend, 0);
+	if ((tcp_get_pcount(&tp->sacked_out) + holes) >
+	    tcp_get_pcount(&tp->packets_out)) {
+		tcp_set_pcount(&tp->sacked_out,
+			       (tcp_get_pcount(&tp->packets_out) - holes));
+		tcp_update_reordering(tp,
+				      tcp_get_pcount(&tp->packets_out)+addend,
+				      0);
 	}
 }
 
@@ -1494,7 +1514,7 @@ static void tcp_check_reno_reordering(struct tcp_opt *tp, int addend)
 
 static void tcp_add_reno_sack(struct tcp_opt *tp)
 {
-	++tp->sacked_out;
+	tcp_inc_pcount_explicit(&tp->sacked_out, 1);
 	tcp_check_reno_reordering(tp, 0);
 	tcp_sync_left_out(tp);
 }
@@ -1505,10 +1525,10 @@ static void tcp_remove_reno_sacks(struct sock *sk, struct tcp_opt *tp, int acked
 {
 	if (acked > 0) {
 		/* One ACK acked hole. The rest eat duplicate ACKs. */
-		if (acked-1 >= tp->sacked_out)
-			tp->sacked_out = 0;
+		if (acked-1 >= tcp_get_pcount(&tp->sacked_out))
+			tcp_set_pcount(&tp->sacked_out, 0);
 		else
-			tp->sacked_out -= acked-1;
+			tcp_dec_pcount_explicit(&tp->sacked_out, acked-1);
 	}
 	tcp_check_reno_reordering(tp, acked);
 	tcp_sync_left_out(tp);
@@ -1516,8 +1536,8 @@ static void tcp_remove_reno_sacks(struct sock *sk, struct tcp_opt *tp, int acked
 
 static inline void tcp_reset_reno_sack(struct tcp_opt *tp)
 {
-	tp->sacked_out = 0;
-	tp->left_out = tp->lost_out;
+	tcp_set_pcount(&tp->sacked_out, 0);
+	tcp_set_pcount(&tp->left_out, tcp_get_pcount(&tp->lost_out));
 }
 
 /* Mark head of queue up as lost. */
@@ -1527,14 +1547,15 @@ tcp_mark_head_lost(struct sock *sk, struct tcp_opt *tp, int packets, u32 high_se
 	struct sk_buff *skb;
 	int cnt = packets;
 
-	BUG_TRAP(cnt <= tp->packets_out);
+	BUG_TRAP(cnt <= tcp_get_pcount(&tp->packets_out));
 
 	sk_stream_for_retrans_queue(skb, sk) {
-		if (--cnt < 0 || after(TCP_SKB_CB(skb)->end_seq, high_seq))
+		cnt -= tcp_skb_pcount(skb);
+		if (cnt < 0 || after(TCP_SKB_CB(skb)->end_seq, high_seq))
 			break;
 		if (!(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) {
 			TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
-			tp->lost_out++;
+			tcp_inc_pcount(&tp->lost_out, skb);
 		}
 	}
 	tcp_sync_left_out(tp);
@@ -1545,7 +1566,7 @@ tcp_mark_head_lost(struct sock *sk, struct tcp_opt *tp, int packets, u32 high_se
 static void tcp_update_scoreboard(struct sock *sk, struct tcp_opt *tp)
 {
 	if (IsFack(tp)) {
-		int lost = tp->fackets_out - tp->reordering;
+		int lost = tcp_get_pcount(&tp->fackets_out) - tp->reordering;
 		if (lost <= 0)
 			lost = 1;
 		tcp_mark_head_lost(sk, tp, lost, tp->high_seq);
@@ -1565,7 +1586,7 @@ static void tcp_update_scoreboard(struct sock *sk, struct tcp_opt *tp)
 			if (tcp_skb_timedout(tp, skb) &&
 			    !(TCP_SKB_CB(skb)->sacked&TCPCB_TAGBITS)) {
 				TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
-				tp->lost_out++;
+				tcp_inc_pcount(&tp->lost_out, skb);
 			}
 		}
 		tcp_sync_left_out(tp);
@@ -1630,8 +1651,9 @@ static void DBGUNDO(struct sock *sk, struct tcp_opt *tp, const char *msg)
 	printk(KERN_DEBUG "Undo %s %u.%u.%u.%u/%u c%u l%u ss%u/%u p%u\n",
 	       msg,
 	       NIPQUAD(inet->daddr), ntohs(inet->dport),
-	       tp->snd_cwnd, tp->left_out,
-	       tp->snd_ssthresh, tp->prior_ssthresh, tp->packets_out);
+	       tp->snd_cwnd, tcp_get_pcount(&tp->left_out),
+	       tp->snd_ssthresh, tp->prior_ssthresh,
+	       tcp_get_pcount(&tp->packets_out));
 }
 #else
 #define DBGUNDO(x...) do { } while (0)
@@ -1701,13 +1723,13 @@ static void tcp_try_undo_dsack(struct sock *sk, struct tcp_opt *tp)
 static int tcp_try_undo_partial(struct sock *sk, struct tcp_opt *tp, int acked)
 {
 	/* Partial ACK arrived. Force Hoe's retransmit. */
-	int failed = IsReno(tp) || tp->fackets_out>tp->reordering;
+	int failed = IsReno(tp) || tcp_get_pcount(&tp->fackets_out)>tp->reordering;
 
 	if (tcp_may_undo(tp)) {
 		/* Plain luck! Hole if filled with delayed
 		 * packet, rather than with a retransmit.
 		 */
-		if (tp->retrans_out == 0)
+		if (tcp_get_pcount(&tp->retrans_out) == 0)
 			tp->retrans_stamp = 0;
 
 		tcp_update_reordering(tp, tcp_fackets_out(tp)+acked, 1);
@@ -1734,8 +1756,8 @@ static int tcp_try_undo_loss(struct sock *sk, struct tcp_opt *tp)
 			TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST;
 		}
 		DBGUNDO(sk, tp, "partial loss");
-		tp->lost_out = 0;
-		tp->left_out = tp->sacked_out;
+		tcp_set_pcount(&tp->lost_out, 0);
+		tcp_set_pcount(&tp->left_out, tcp_get_pcount(&tp->sacked_out));
 		tcp_undo_cwr(tp, 1);
 		NET_INC_STATS_BH(LINUX_MIB_TCPLOSSUNDO);
 		tp->retransmits = 0;
@@ -1758,9 +1780,9 @@ static __inline__ void tcp_complete_cwr(struct tcp_opt *tp)
 
 static void tcp_try_to_open(struct sock *sk, struct tcp_opt *tp, int flag)
 {
-	tp->left_out = tp->sacked_out;
+	tcp_set_pcount(&tp->left_out, tcp_get_pcount(&tp->sacked_out));
 
-	if (tp->retrans_out == 0)
+	if (tcp_get_pcount(&tp->retrans_out) == 0)
 		tp->retrans_stamp = 0;
 
 	if (flag&FLAG_ECE)
@@ -1769,8 +1791,8 @@ static void tcp_try_to_open(struct sock *sk, struct tcp_opt *tp, int flag)
 	if (tp->ca_state != TCP_CA_CWR) {
 		int state = TCP_CA_Open;
 
-		if (tp->left_out ||
-		    tp->retrans_out ||
+		if (tcp_get_pcount(&tp->left_out) ||
+		    tcp_get_pcount(&tp->retrans_out) ||
 		    tp->undo_marker)
 			state = TCP_CA_Disorder;
 
@@ -1804,11 +1826,11 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
 
 	/* Some technical things:
 	 * 1. Reno does not count dupacks (sacked_out) automatically. */
-	if (!tp->packets_out)
-		tp->sacked_out = 0;
+	if (!tcp_get_pcount(&tp->packets_out))
+		tcp_set_pcount(&tp->sacked_out, 0);
         /* 2. SACK counts snd_fack in packets inaccurately. */
-	if (tp->sacked_out == 0)
-		tp->fackets_out = 0;
+	if (tcp_get_pcount(&tp->sacked_out) == 0)
+		tcp_set_pcount(&tp->fackets_out, 0);
 
         /* Now state machine starts.
 	 * A. ECE, hence prohibit cwnd undoing, the reduction is required. */
@@ -1816,15 +1838,15 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
 		tp->prior_ssthresh = 0;
 
 	/* B. In all the states check for reneging SACKs. */
-	if (tp->sacked_out && tcp_check_sack_reneging(sk, tp))
+	if (tcp_get_pcount(&tp->sacked_out) && tcp_check_sack_reneging(sk, tp))
 		return;
 
 	/* C. Process data loss notification, provided it is valid. */
 	if ((flag&FLAG_DATA_LOST) &&
 	    before(tp->snd_una, tp->high_seq) &&
 	    tp->ca_state != TCP_CA_Open &&
-	    tp->fackets_out > tp->reordering) {
-		tcp_mark_head_lost(sk, tp, tp->fackets_out-tp->reordering, tp->high_seq);
+	    tcp_get_pcount(&tp->fackets_out) > tp->reordering) {
+		tcp_mark_head_lost(sk, tp, tcp_get_pcount(&tp->fackets_out)-tp->reordering, tp->high_seq);
 		NET_INC_STATS_BH(LINUX_MIB_TCPLOSS);
 	}
 
@@ -1835,7 +1857,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
 	 *    when high_seq is ACKed. */
 	if (tp->ca_state == TCP_CA_Open) {
 		if (!sysctl_tcp_frto)
-			BUG_TRAP(tp->retrans_out == 0);
+			BUG_TRAP(tcp_get_pcount(&tp->retrans_out) == 0);
 		tp->retrans_stamp = 0;
 	} else if (!before(tp->snd_una, tp->high_seq)) {
 		switch (tp->ca_state) {
@@ -1882,7 +1904,8 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
 			if (IsReno(tp) && is_dupack)
 				tcp_add_reno_sack(tp);
 		} else {
-			int acked = prior_packets - tp->packets_out;
+			int acked = prior_packets -
+				tcp_get_pcount(&tp->packets_out);
 			if (IsReno(tp))
 				tcp_remove_reno_sacks(sk, tp, acked);
 			is_dupack = tcp_try_undo_partial(sk, tp, acked);
@@ -1925,7 +1948,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
 		tp->high_seq = tp->snd_nxt;
 		tp->prior_ssthresh = 0;
 		tp->undo_marker = tp->snd_una;
-		tp->undo_retrans = tp->retrans_out;
+		tp->undo_retrans = tcp_get_pcount(&tp->retrans_out);
 
 		if (tp->ca_state < TCP_CA_CWR) {
 			if (!(flag&FLAG_ECE))
@@ -2019,7 +2042,7 @@ tcp_ack_update_rtt(struct tcp_opt *tp, int flag, s32 seq_rtt)
 static inline __u32 bictcp_cwnd(struct tcp_opt *tp)
 {
 	/* orignal Reno behaviour */
-	if (!sysctl_tcp_bic)
+	if (!tcp_is_bic(tp))
 		return tp->snd_cwnd;
 
 	if (tp->bictcp.last_cwnd == tp->snd_cwnd &&
@@ -2154,7 +2177,7 @@ static void vegas_cong_avoid(struct tcp_opt *tp, u32 ack, u32 seq_rtt)
 		 * is the cwnd during the previous RTT.
 		 */
 		old_wnd = (tp->vegas.beg_snd_nxt - tp->vegas.beg_snd_una) /
-			tp->mss_cache;
+			tp->mss_cache_std;
 		old_snd_cwnd = tp->vegas.beg_snd_cwnd;
 
 		/* Save the extent of the current window so we can use this
@@ -2325,13 +2348,89 @@ static inline void tcp_cong_avoid(struct tcp_opt *tp, u32 ack, u32 seq_rtt)
 
 static __inline__ void tcp_ack_packets_out(struct sock *sk, struct tcp_opt *tp)
 {
-	if (tp->packets_out==0) {
+	if (!tcp_get_pcount(&tp->packets_out)) {
 		tcp_clear_xmit_timer(sk, TCP_TIME_RETRANS);
 	} else {
 		tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
 	}
 }
 
+/* There is one downside to this scheme.  Although we keep the
+ * ACK clock ticking, adjusting packet counters and advancing
+ * congestion window, we do not liberate socket send buffer
+ * space.
+ *
+ * Mucking with skb->truesize and sk->sk_wmem_alloc et al.
+ * then making a write space wakeup callback is a possible
+ * future enhancement.  WARNING: it is not trivial to make.
+ */
+static int tcp_tso_acked(struct sock *sk, struct sk_buff *skb,
+			 __u32 now, __s32 *seq_rtt)
+{
+	struct tcp_opt *tp = tcp_sk(sk);
+	struct tcp_skb_cb *scb = TCP_SKB_CB(skb); 
+	__u32 mss = tcp_skb_mss(skb);
+	__u32 snd_una = tp->snd_una;
+	__u32 orig_seq, seq;
+	__u32 packets_acked = 0;
+	int acked = 0;
+
+	/* If we get here, the whole TSO packet has not been
+	 * acked.
+	 */
+	BUG_ON(!after(scb->end_seq, snd_una));
+
+	seq = orig_seq = scb->seq;
+	while (!after(seq + mss, snd_una)) {
+		packets_acked++;
+		seq += mss;
+	}
+
+	if (tcp_trim_head(sk, skb, (seq - orig_seq)))
+		return 0;
+
+	if (packets_acked) {
+		__u8 sacked = scb->sacked;
+
+		acked |= FLAG_DATA_ACKED;
+		if (sacked) {
+			if (sacked & TCPCB_RETRANS) {
+				if (sacked & TCPCB_SACKED_RETRANS)
+					tcp_dec_pcount_explicit(&tp->retrans_out,
+								packets_acked);
+				acked |= FLAG_RETRANS_DATA_ACKED;
+				*seq_rtt = -1;
+			} else if (*seq_rtt < 0)
+				*seq_rtt = now - scb->when;
+			if (sacked & TCPCB_SACKED_ACKED)
+				tcp_dec_pcount_explicit(&tp->sacked_out,
+							packets_acked);
+			if (sacked & TCPCB_LOST)
+				tcp_dec_pcount_explicit(&tp->lost_out,
+							packets_acked);
+			if (sacked & TCPCB_URG) {
+				if (tp->urg_mode &&
+				    !before(seq, tp->snd_up))
+					tp->urg_mode = 0;
+			}
+		} else if (*seq_rtt < 0)
+			*seq_rtt = now - scb->when;
+
+		if (tcp_get_pcount(&tp->fackets_out)) {
+			__u32 dval = min(tcp_get_pcount(&tp->fackets_out),
+					 packets_acked);
+			tcp_dec_pcount_explicit(&tp->fackets_out, dval);
+		}
+		tcp_dec_pcount_explicit(&tp->packets_out, packets_acked);
+
+		BUG_ON(tcp_skb_pcount(skb) == 0);
+		BUG_ON(!before(scb->seq, scb->end_seq));
+	}
+
+	return acked;
+}
+
+
 /* Remove acknowledged frames from the retransmission queue. */
 static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
 {
@@ -2341,7 +2440,8 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
 	int acked = 0;
 	__s32 seq_rtt = -1;
 
-	while ((skb = skb_peek(&sk->sk_write_queue)) && skb != sk->sk_send_head) {
+	while ((skb = skb_peek(&sk->sk_write_queue)) &&
+	       skb != sk->sk_send_head) {
 		struct tcp_skb_cb *scb = TCP_SKB_CB(skb); 
 		__u8 sacked = scb->sacked;
 
@@ -2349,8 +2449,12 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
 		 * discard it as it's confirmed to have arrived at
 		 * the other end.
 		 */
-		if (after(scb->end_seq, tp->snd_una))
+		if (after(scb->end_seq, tp->snd_una)) {
+			if (tcp_skb_pcount(skb) > 1)
+				acked |= tcp_tso_acked(sk, skb,
+						       now, &seq_rtt);
 			break;
+		}
 
 		/* Initial outgoing SYN's get put onto the write_queue
 		 * just like anything else we transmit.  It is not
@@ -2359,7 +2463,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
 		 * connection startup slow start one packet too
 		 * quickly.  This is severely frowned upon behavior.
 		 */
-		if(!(scb->flags & TCPCB_FLAG_SYN)) {
+		if (!(scb->flags & TCPCB_FLAG_SYN)) {
 			acked |= FLAG_DATA_ACKED;
 		} else {
 			acked |= FLAG_SYN_ACKED;
@@ -2367,27 +2471,26 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
 		}
 
 		if (sacked) {
-			if(sacked & TCPCB_RETRANS) {
+			if (sacked & TCPCB_RETRANS) {
 				if(sacked & TCPCB_SACKED_RETRANS)
-					tp->retrans_out--;
+					tcp_dec_pcount(&tp->retrans_out, skb);
 				acked |= FLAG_RETRANS_DATA_ACKED;
 				seq_rtt = -1;
 			} else if (seq_rtt < 0)
 				seq_rtt = now - scb->when;
-			if(sacked & TCPCB_SACKED_ACKED)
-				tp->sacked_out--;
-			if(sacked & TCPCB_LOST)
-				tp->lost_out--;
-			if(sacked & TCPCB_URG) {
+			if (sacked & TCPCB_SACKED_ACKED)
+				tcp_dec_pcount(&tp->sacked_out, skb);
+			if (sacked & TCPCB_LOST)
+				tcp_dec_pcount(&tp->lost_out, skb);
+			if (sacked & TCPCB_URG) {
 				if (tp->urg_mode &&
 				    !before(scb->end_seq, tp->snd_up))
 					tp->urg_mode = 0;
 			}
 		} else if (seq_rtt < 0)
 			seq_rtt = now - scb->when;
-		if (tp->fackets_out)
-			tp->fackets_out--;
-		tp->packets_out--;
+		tcp_dec_pcount_approx(&tp->fackets_out, skb);
+		tcp_packets_out_dec(tp, skb);
 		__skb_unlink(skb, skb->list);
 		sk_stream_free_skb(sk, skb);
 	}
@@ -2398,24 +2501,27 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
 	}
 
 #if FASTRETRANS_DEBUG > 0
-	BUG_TRAP((int)tp->sacked_out >= 0);
-	BUG_TRAP((int)tp->lost_out >= 0);
-	BUG_TRAP((int)tp->retrans_out >= 0);
-	if (!tp->packets_out && tp->sack_ok) {
-		if (tp->lost_out) {
-			printk(KERN_DEBUG "Leak l=%u %d\n", tp->lost_out,
-							    tp->ca_state);
-			tp->lost_out = 0;
+	BUG_TRAP((int)tcp_get_pcount(&tp->sacked_out) >= 0);
+	BUG_TRAP((int)tcp_get_pcount(&tp->lost_out) >= 0);
+	BUG_TRAP((int)tcp_get_pcount(&tp->retrans_out) >= 0);
+	if (!tcp_get_pcount(&tp->packets_out) && tp->sack_ok) {
+		if (tcp_get_pcount(&tp->lost_out)) {
+			printk(KERN_DEBUG "Leak l=%u %d\n",
+			       tcp_get_pcount(&tp->lost_out),
+			       tp->ca_state);
+			tcp_set_pcount(&tp->lost_out, 0);
 		}
-		if (tp->sacked_out) {
-			printk(KERN_DEBUG "Leak s=%u %d\n", tp->sacked_out,
-							    tp->ca_state);
-			tp->sacked_out = 0;
+		if (tcp_get_pcount(&tp->sacked_out)) {
+			printk(KERN_DEBUG "Leak s=%u %d\n",
+			       tcp_get_pcount(&tp->sacked_out),
+			       tp->ca_state);
+			tcp_set_pcount(&tp->sacked_out, 0);
 		}
-		if (tp->retrans_out) {
-			printk(KERN_DEBUG "Leak r=%u %d\n", tp->retrans_out,
-							    tp->ca_state);
-			tp->retrans_out = 0;
+		if (tcp_get_pcount(&tp->retrans_out)) {
+			printk(KERN_DEBUG "Leak r=%u %d\n",
+			       tcp_get_pcount(&tp->retrans_out),
+			       tp->ca_state);
+			tcp_set_pcount(&tp->retrans_out, 0);
 		}
 	}
 #endif
@@ -2594,18 +2700,16 @@ static void westwood_filter(struct sock *sk, __u32 delta)
  * WESTWOOD_RTT_MIN minimum bound since we could be on a LAN!
  */
 
-static inline __u32 westwood_update_rttmin(struct sock *sk)
+static inline __u32 westwood_update_rttmin(const struct sock *sk)
 {
-	struct tcp_opt *tp = tcp_sk(sk);
+	const struct tcp_opt *tp = tcp_sk(sk);
 	__u32 rttmin = tp->westwood.rtt_min;
 
-	if (tp->westwood.rtt == 0)
-		return(rttmin);
-
-	if (tp->westwood.rtt < tp->westwood.rtt_min || !rttmin)
+	if (tp->westwood.rtt != 0 &&
+	    (tp->westwood.rtt < tp->westwood.rtt_min || !rttmin))
 		rttmin = tp->westwood.rtt;
 
-	return(rttmin);
+	return rttmin;
 }
 
 /*
@@ -2613,11 +2717,11 @@ static inline __u32 westwood_update_rttmin(struct sock *sk)
  * Evaluate increases for dk. 
  */
 
-static inline __u32 westwood_acked(struct sock *sk)
+static inline __u32 westwood_acked(const struct sock *sk)
 {
-	struct tcp_opt *tp = tcp_sk(sk);
+	const struct tcp_opt *tp = tcp_sk(sk);
 
-	return ((tp->snd_una) - (tp->westwood.snd_una));
+	return tp->snd_una - tp->westwood.snd_una;
 }
 
 /*
@@ -2629,9 +2733,9 @@ static inline __u32 westwood_acked(struct sock *sk)
  * window, 1 if the sample has to be considered in the next window.
  */
 
-static int westwood_new_window(struct sock *sk)
+static int westwood_new_window(const struct sock *sk)
 {
-	struct tcp_opt *tp = tcp_sk(sk);
+	const struct tcp_opt *tp = tcp_sk(sk);
 	__u32 left_bound;
 	__u32 rtt;
 	int ret = 0;
@@ -2665,14 +2769,13 @@ static void __westwood_update_window(struct sock *sk, __u32 now)
 	struct tcp_opt *tp = tcp_sk(sk);
 	__u32 delta = now - tp->westwood.rtt_win_sx;
 
-        if (!delta)
-                return;
-
-	if (tp->westwood.rtt)
-                westwood_filter(sk, delta);
+        if (delta) {
+		if (tp->westwood.rtt)
+			westwood_filter(sk, delta);
 
-        tp->westwood.bk = 0;
-        tp->westwood.rtt_win_sx = tcp_time_stamp;
+		tp->westwood.bk = 0;
+		tp->westwood.rtt_win_sx = tcp_time_stamp;
+	}
 }
 
 
@@ -2710,19 +2813,19 @@ static void westwood_dupack_update(struct sock *sk)
 {
 	struct tcp_opt *tp = tcp_sk(sk);
 
-	tp->westwood.accounted += tp->mss_cache;
-	tp->westwood.cumul_ack = tp->mss_cache;
+	tp->westwood.accounted += tp->mss_cache_std;
+	tp->westwood.cumul_ack = tp->mss_cache_std;
 }
 
 static inline int westwood_may_change_cumul(struct tcp_opt *tp)
 {
-	return ((tp->westwood.cumul_ack) > tp->mss_cache);
+	return (tp->westwood.cumul_ack > tp->mss_cache_std);
 }
 
 static inline void westwood_partial_update(struct tcp_opt *tp)
 {
 	tp->westwood.accounted -= tp->westwood.cumul_ack;
-	tp->westwood.cumul_ack = tp->mss_cache;
+	tp->westwood.cumul_ack = tp->mss_cache_std;
 }
 
 static inline void westwood_complete_update(struct tcp_opt *tp)
@@ -2737,7 +2840,7 @@ static inline void westwood_complete_update(struct tcp_opt *tp)
  * delayed or partial acks.
  */
 
-static __u32 westwood_acked_count(struct sock *sk)
+static inline __u32 westwood_acked_count(struct sock *sk)
 {
 	struct tcp_opt *tp = tcp_sk(sk);
 
@@ -2751,7 +2854,7 @@ static __u32 westwood_acked_count(struct sock *sk)
 
         if (westwood_may_change_cumul(tp)) {
 		/* Partial or delayed ack */
-		if ((tp->westwood.accounted) >= (tp->westwood.cumul_ack))
+		if (tp->westwood.accounted >= tp->westwood.cumul_ack)
 			westwood_partial_update(tp);
 		else
 			westwood_complete_update(tp);
@@ -2833,7 +2936,7 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
 	 */
 	sk->sk_err_soft = 0;
 	tp->rcv_tstamp = tcp_time_stamp;
-	prior_packets = tp->packets_out;
+	prior_packets = tcp_get_pcount(&tp->packets_out);
 	if (!prior_packets)
 		goto no_queue;
 
@@ -3855,11 +3958,11 @@ static void tcp_new_space(struct sock *sk)
 {
 	struct tcp_opt *tp = tcp_sk(sk);
 
-	if (tp->packets_out < tp->snd_cwnd &&
+	if (tcp_get_pcount(&tp->packets_out) < tp->snd_cwnd &&
 	    !(sk->sk_userlocks & SOCK_SNDBUF_LOCK) &&
 	    !tcp_memory_pressure &&
 	    atomic_read(&tcp_memory_allocated) < sysctl_tcp_mem[0]) {
- 		int sndmem = max_t(u32, tp->mss_clamp, tp->mss_cache) +
+ 		int sndmem = max_t(u32, tp->mss_clamp, tp->mss_cache_std) +
 			MAX_TCP_HEADER + 16 + sizeof(struct sk_buff),
 		    demanded = max_t(unsigned int, tp->snd_cwnd,
 						   tp->reordering + 1);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 514090ffa..68860426e 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -180,62 +180,6 @@ void tcp_bind_hash(struct sock *sk, struct tcp_bind_bucket *tb,
 	tcp_sk(sk)->bind_hash = tb;
 }
 
-/*
-	Return 1 if addr match the socket IP list
-	or the socket is INADDR_ANY
-*/
-static inline int tcp_in_list(struct sock *sk, u32 addr)
-{
-	struct nx_info *nxi = sk->sk_nx_info;
-
-	vxdprintk(VXD_CBIT(net, 2), "tcp_in_list(%p) %p,%p;%lx",
-		sk, nxi, sk->sk_socket,
-		(sk->sk_socket?sk->sk_socket->flags:0));
-
-	if (nxi) {
-		int n = nxi->nbipv4;
-		int i;
-
-		for (i=0; i<n; i++)
-			if (nxi->ipv4[i] == addr)
-				return 1;
-	}
-	else if (!tcp_v4_rcv_saddr(sk) || tcp_v4_rcv_saddr(sk) == addr)
-		return 1;
-	return 0;
-}
-	
-/*
-	Check if the addresses in sk1 conflict with those in sk2
-*/
-int tcp_ipv4_addr_conflict(struct sock *sk1, struct sock *sk2)
-{
-	if (sk1 && sk2)
-	vxdprintk(VXD_CBIT(net, 5),
-		"tcp_ipv4_addr_conflict(%p,%p) %p,%p;%lx %p,%p;%lx",
-		sk1, sk2,
-		sk1->sk_nx_info, sk1->sk_socket,
-		(sk1->sk_socket?sk1->sk_socket->flags:0),
-		sk2->sk_nx_info, sk2->sk_socket,
-		(sk2->sk_socket?sk2->sk_socket->flags:0));
-
-	if (tcp_v4_rcv_saddr(sk1)) {
-		/* Bind to one address only */
-		return tcp_in_list (sk2, tcp_v4_rcv_saddr(sk1));
-	} else if (sk1->sk_nx_info) {
-		/* A restricted bind(any) */
-		struct nx_info *nxi = sk1->sk_nx_info;
-		int n = nxi->nbipv4;
-		int i;
-
-		for (i=0; i<n; i++)
-			if (tcp_in_list (sk2, nxi->ipv4[i]))
-				return 1;
-	} else	/* A bind(any) do not allow other bind on the same port */
-		return 1;
-	return 0;
-}
-
 static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb)
 {
 	struct sock *sk2;
@@ -250,7 +194,8 @@ static inline int tcp_bind_conflict(struct sock *sk, struct tcp_bind_bucket *tb)
 		     sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) {
 			if (!reuse || !sk2->sk_reuse ||
 			    sk2->sk_state == TCP_LISTEN) {
-				if (tcp_ipv4_addr_conflict(sk, sk2))
+				if (nx_addr_conflict(sk->sk_nx_info,
+					tcp_v4_rcv_saddr(sk), sk2))
 					break;
 			}
 		}
@@ -459,34 +404,26 @@ void tcp_unhash(struct sock *sk)
 		wake_up(&tcp_lhash_wait);
 }
 
+
 /*
-	Check if an address is in the list
-*/
-static inline int tcp_addr_in_list(
-	u32 rcv_saddr,
-	u32 daddr,
-	struct nx_info *nx_info)
-{
-	if (rcv_saddr == daddr)
+ *      Check if a given address matches for a tcp socket
+ *
+ *      nxi:	the socket's nx_info if any
+ *      addr:	to be verified address
+ *      saddr:	socket addresses
+ */
+static inline int tcp_addr_match (
+	struct nx_info *nxi,
+	uint32_t addr,
+	uint32_t saddr)
+{
+	if (addr && (saddr == addr))
 		return 1;
-	else if (rcv_saddr == 0) {
-		/* Accept any address or check the list */
-		if (!nx_info)
-			return 1;
-		else {
-			int n = nx_info->nbipv4;
-			int i;
-
-			for (i=0; i<n; i++)
-				if (nx_info->ipv4[i] == daddr)
-					return 1;
-		}
-	}
+	if (!saddr)
+		return addr_in_nx_info(nxi, addr);
 	return 0;
 }
 
-
-
 /* Don't inline this cruft.  Here are some nice properties to
  * exploit here.  The BSD API does not allow a listening TCP
  * to specify the remote port nor the remote address for the
@@ -508,7 +445,7 @@ static struct sock *__tcp_v4_lookup_listener(struct hlist_head *head, u32 daddr,
 			__u32 rcv_saddr = inet->rcv_saddr;
 
 			score = (sk->sk_family == PF_INET ? 1 : 0);
-			if (tcp_addr_in_list(rcv_saddr, daddr, sk->sk_nx_info))
+			if (tcp_addr_match(sk->sk_nx_info, daddr, rcv_saddr))
 				score+=2;
 			else
 				continue;
@@ -542,7 +479,7 @@ inline struct sock *tcp_v4_lookup_listener(u32 daddr, unsigned short hnum,
 
 		if (inet->num == hnum && !sk->sk_node.next &&
 		    (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) &&
-		    tcp_addr_in_list(inet->rcv_saddr, daddr, sk->sk_nx_info) &&
+		    tcp_addr_match(sk->sk_nx_info, daddr, inet->rcv_saddr) &&
 		    !sk->sk_bound_dev_if)
 			goto sherry_cache;
 		sk = __tcp_v4_lookup_listener(head, daddr, hnum, dif);
@@ -1114,11 +1051,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
 
 	switch (type) {
 	case ICMP_SOURCE_QUENCH:
-		/* This is deprecated, but if someone generated it,
-		 * we have no reasons to ignore it.
-		 */
-		if (!sock_owned_by_user(sk))
-			tcp_enter_cwr(tp);
+		/* Just silently ignore these. */
 		goto out;
 	case ICMP_PARAMETERPROB:
 		err = EPROTO;
@@ -2156,7 +2089,7 @@ static int tcp_v4_init_sock(struct sock *sk)
 	 */
 	tp->snd_ssthresh = 0x7fffffff;	/* Infinity */
 	tp->snd_cwnd_clamp = ~0;
-	tp->mss_cache = 536;
+	tp->mss_cache_std = tp->mss_cache = 536;
 
 	tp->reordering = sysctl_tcp_reordering;
 
@@ -2247,9 +2180,10 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
 		while (1) {
 			while (req) {
 				vxdprintk(VXD_CBIT(net, 6),
-					"sk,req: %p [#%d] (from %d)",
-					req->sk, req->sk->sk_xid, current->xid);
-				if (!vx_check(req->sk->sk_xid, VX_IDENT|VX_WATCH))
+					"sk,req: %p [#%d] (from %d)", req->sk,
+					(req->sk)?req->sk->sk_xid:0, current->xid);
+				if (req->sk &&
+					!vx_check(req->sk->sk_xid, VX_IDENT|VX_WATCH))
 					continue;
 				if (req->class->family == st->family) {
 					cur = req;
@@ -2265,8 +2199,14 @@ get_req:
 		sk	  = sk_next(st->syn_wait_sk);
 		st->state = TCP_SEQ_STATE_LISTENING;
 		read_unlock_bh(&tp->syn_wait_lock);
-	} else
+	} else {
+	       	tp = tcp_sk(sk);
+		read_lock_bh(&tp->syn_wait_lock);
+		if (tp->listen_opt && tp->listen_opt->qlen)
+			goto start_req;
+		read_unlock_bh(&tp->syn_wait_lock);
 		sk = sk_next(sk);
+	}
 get_sk:
 	sk_for_each_from(sk, node) {
 		vxdprintk(VXD_CBIT(net, 6), "sk: %p [#%d] (from %d)",
@@ -2280,6 +2220,7 @@ get_sk:
 	       	tp = tcp_sk(sk);
 		read_lock_bh(&tp->syn_wait_lock);
 		if (tp->listen_opt && tp->listen_opt->qlen) {
+start_req:
 			st->uid		= sock_i_uid(sk);
 			st->syn_wait_sk = sk;
 			st->state	= TCP_SEQ_STATE_OPENREQ;
@@ -2721,6 +2662,7 @@ struct proto tcp_prot = {
 	.sysctl_wmem		= sysctl_tcp_wmem,
 	.sysctl_rmem		= sysctl_tcp_rmem,
 	.max_header		= MAX_TCP_HEADER,
+	.slab_obj_size		= sizeof(struct tcp_sock),
 };
 
 
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index c2ef0d903..92b873dbc 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -368,7 +368,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
 		tw->tw_vx_info		= NULL;
 		tw->tw_nid		= sk->sk_nid;
 		tw->tw_nx_info		= NULL;
-		
+
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 		if (tw->tw_family == PF_INET6) {
 			struct ipv6_pinfo *np = inet6_sk(sk);
@@ -694,7 +694,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
 	/* allocate the newsk from the same slab of the master sock,
 	 * if not, at sk_free time we'll try to free it from the wrong
 	 * slabcache (i.e. is it TCPv4 or v6?) -acme */
-	struct sock *newsk = sk_alloc(PF_INET, GFP_ATOMIC, 0, sk->sk_slab);
+	struct sock *newsk = sk_alloc(PF_INET, GFP_ATOMIC, 0, sk->sk_prot->slab);
 
 	if(newsk != NULL) {
 		struct tcp_opt *newtp;
@@ -761,11 +761,11 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
 		newtp->mdev = TCP_TIMEOUT_INIT;
 		newtp->rto = TCP_TIMEOUT_INIT;
 
-		newtp->packets_out = 0;
-		newtp->left_out = 0;
-		newtp->retrans_out = 0;
-		newtp->sacked_out = 0;
-		newtp->fackets_out = 0;
+		tcp_set_pcount(&newtp->packets_out, 0);
+		tcp_set_pcount(&newtp->left_out, 0);
+		tcp_set_pcount(&newtp->retrans_out, 0);
+		tcp_set_pcount(&newtp->sacked_out, 0);
+		tcp_set_pcount(&newtp->fackets_out, 0);
 		newtp->snd_ssthresh = 0x7fffffff;
 
 		/* So many TCP implementations out there (incorrectly) count the
@@ -856,7 +856,8 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
 		if (newtp->ecn_flags&TCP_ECN_OK)
 			newsk->sk_no_largesend = 1;
 
-		tcp_vegas_init(newtp);
+		tcp_ca_init(newtp);
+
 		TCP_INC_STATS_BH(TCP_MIB_PASSIVEOPENS);
 	}
 	return newsk;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 68ab99fc0..39214126c 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -45,6 +45,12 @@
 /* People can turn this off for buggy TCP's found in printers etc. */
 int sysctl_tcp_retrans_collapse = 1;
 
+/* This limits the percentage of the congestion window which we
+ * will allow a single TSO frame to consume.  Building TSO frames
+ * which are too large can cause TCP streams to be bursty.
+ */
+int sysctl_tcp_tso_win_divisor = 8;
+
 static __inline__
 void update_send_head(struct sock *sk, struct tcp_opt *tp, struct sk_buff *skb)
 {
@@ -52,8 +58,7 @@ void update_send_head(struct sock *sk, struct tcp_opt *tp, struct sk_buff *skb)
 	if (sk->sk_send_head == (struct sk_buff *)&sk->sk_write_queue)
 		sk->sk_send_head = NULL;
 	tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
-	if (tp->packets_out++ == 0)
-		tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+	tcp_packets_out_inc(sk, tp, skb);
 }
 
 /* SND.NXT, if window was not shrunk.
@@ -123,7 +128,8 @@ static __inline__ void tcp_event_data_sent(struct tcp_opt *tp, struct sk_buff *s
 {
 	u32 now = tcp_time_stamp;
 
-	if (!tp->packets_out && (s32)(now - tp->lsndtime) > tp->rto)
+	if (!tcp_get_pcount(&tp->packets_out) &&
+	    (s32)(now - tp->lsndtime) > tp->rto)
 		tcp_cwnd_restart(tp, __sk_dst_get(sk));
 
 	tp->lsndtime = now;
@@ -143,6 +149,65 @@ static __inline__ void tcp_event_ack_sent(struct sock *sk)
 	tcp_clear_xmit_timer(sk, TCP_TIME_DACK);
 }
 
+/* Determine a window scaling and initial window to offer.
+ * Based on the assumption that the given amount of space
+ * will be offered. Store the results in the tp structure.
+ * NOTE: for smooth operation initial space offering should
+ * be a multiple of mss if possible. We assume here that mss >= 1.
+ * This MUST be enforced by all callers.
+ */
+void tcp_select_initial_window(int __space, __u32 mss,
+			       __u32 *rcv_wnd, __u32 *window_clamp,
+			       int wscale_ok, __u8 *rcv_wscale)
+{
+	unsigned int space = (__space < 0 ? 0 : __space);
+
+	/* If no clamp set the clamp to the max possible scaled window */
+	if (*window_clamp == 0)
+		(*window_clamp) = (65535 << 14);
+	space = min(*window_clamp, space);
+
+	/* Quantize space offering to a multiple of mss if possible. */
+	if (space > mss)
+		space = (space / mss) * mss;
+
+	/* NOTE: offering an initial window larger than 32767
+	 * will break some buggy TCP stacks. We try to be nice.
+	 * If we are not window scaling, then this truncates
+	 * our initial window offering to 32k. There should also
+	 * be a sysctl option to stop being nice.
+	 */
+	(*rcv_wnd) = min(space, MAX_TCP_WINDOW);
+	(*rcv_wscale) = 0;
+	if (wscale_ok) {
+		/* Set window scaling on max possible window
+		 * See RFC1323 for an explanation of the limit to 14 
+		 */
+		space = max_t(u32, sysctl_tcp_rmem[2], sysctl_rmem_max);
+		while (space > 65535 && (*rcv_wscale) < 14) {
+			space >>= 1;
+			(*rcv_wscale)++;
+		}
+	}
+
+	/* Set initial window to value enough for senders,
+	 * following RFC1414. Senders, not following this RFC,
+	 * will be satisfied with 2.
+	 */
+	if (mss > (1<<*rcv_wscale)) {
+		int init_cwnd = 4;
+		if (mss > 1460*3)
+			init_cwnd = 2;
+		else if (mss > 1460)
+			init_cwnd = 3;
+		if (*rcv_wnd > init_cwnd*mss)
+			*rcv_wnd = init_cwnd*mss;
+	}
+
+	/* Set the clamp no higher than max representable value */
+	(*window_clamp) = min(65535U << (*rcv_wscale), *window_clamp);
+}
+
 /* Chose a new window to advertise, update state in tcp_opt for the
  * socket, and return result with RFC1323 scaling applied.  The return
  * value can be stuffed directly into th->window for an outgoing
@@ -198,9 +263,9 @@ static __inline__ u16 tcp_select_window(struct sock *sk)
  * We are working here with either a clone of the original
  * SKB, or a fresh unique copy made by the retransmit engine.
  */
-int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
+static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
 {
-	if(skb != NULL) {
+	if (skb != NULL) {
 		struct inet_opt *inet = inet_sk(sk);
 		struct tcp_opt *tp = tcp_sk(sk);
 		struct tcp_skb_cb *tcb = TCP_SKB_CB(skb);
@@ -209,6 +274,8 @@ int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
 		int sysctl_flags;
 		int err;
 
+		BUG_ON(!tcp_skb_pcount(skb));
+
 #define SYSCTL_FLAG_TSTAMPS	0x1
 #define SYSCTL_FLAG_WSCALE	0x2
 #define SYSCTL_FLAG_SACK	0x4
@@ -355,13 +422,30 @@ void tcp_push_one(struct sock *sk, unsigned cur_mss)
 		if (!tcp_transmit_skb(sk, skb_clone(skb, sk->sk_allocation))) {
 			sk->sk_send_head = NULL;
 			tp->snd_nxt = TCP_SKB_CB(skb)->end_seq;
-			if (tp->packets_out++ == 0)
-				tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
+			tcp_packets_out_inc(sk, tp, skb);
 			return;
 		}
 	}
 }
 
+void tcp_set_skb_tso_segs(struct sk_buff *skb, unsigned int mss_std)
+{
+	if (skb->len <= mss_std) {
+		/* Avoid the costly divide in the normal
+		 * non-TSO case.
+		 */
+		skb_shinfo(skb)->tso_segs = 1;
+		skb_shinfo(skb)->tso_size = 0;
+	} else {
+		unsigned int factor;
+
+		factor = skb->len + (mss_std - 1);
+		factor /= mss_std;
+		skb_shinfo(skb)->tso_segs = factor;
+		skb_shinfo(skb)->tso_size = mss_std;
+	}
+}
+
 /* Function to create two new TCP segments.  Shrinks the given segment
  * to the specified size and appends a new segment with the rest of the
  * packet to the list.  This won't be called frequently, I hope. 
@@ -394,11 +478,9 @@ static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len)
 	flags = TCP_SKB_CB(skb)->flags;
 	TCP_SKB_CB(skb)->flags = flags & ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH);
 	TCP_SKB_CB(buff)->flags = flags;
-	TCP_SKB_CB(buff)->sacked = TCP_SKB_CB(skb)->sacked&(TCPCB_LOST|TCPCB_EVER_RETRANS|TCPCB_AT_TAIL);
-	if (TCP_SKB_CB(buff)->sacked&TCPCB_LOST) {
-		tp->lost_out++;
-		tp->left_out++;
-	}
+	TCP_SKB_CB(buff)->sacked =
+		(TCP_SKB_CB(skb)->sacked &
+		 (TCPCB_LOST | TCPCB_EVER_RETRANS | TCPCB_AT_TAIL));
 	TCP_SKB_CB(skb)->sacked &= ~TCPCB_AT_TAIL;
 
 	if (!skb_shinfo(skb)->nr_frags && skb->ip_summed != CHECKSUM_HW) {
@@ -421,6 +503,25 @@ static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len)
 	 */
 	TCP_SKB_CB(buff)->when = TCP_SKB_CB(skb)->when;
 
+	if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) {
+		tcp_dec_pcount(&tp->lost_out, skb);
+		tcp_dec_pcount(&tp->left_out, skb);
+	}
+
+	/* Fix up tso_factor for both original and new SKB.  */
+	tcp_set_skb_tso_segs(skb, tp->mss_cache_std);
+	tcp_set_skb_tso_segs(buff, tp->mss_cache_std);
+
+	if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) {
+		tcp_inc_pcount(&tp->lost_out, skb);
+		tcp_inc_pcount(&tp->left_out, skb);
+	}
+
+	if (TCP_SKB_CB(buff)->sacked&TCPCB_LOST) {
+		tcp_inc_pcount(&tp->lost_out, buff);
+		tcp_inc_pcount(&tp->left_out, buff);
+	}
+
 	/* Link BUFF into the send queue. */
 	__skb_append(skb, buff);
 
@@ -431,7 +532,7 @@ static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len)
  * eventually). The difference is that pulled data not copied, but
  * immediately discarded.
  */
-unsigned char * __pskb_trim_head(struct sk_buff *skb, int len)
+static unsigned char *__pskb_trim_head(struct sk_buff *skb, int len)
 {
 	int i, k, eat;
 
@@ -459,8 +560,10 @@ unsigned char * __pskb_trim_head(struct sk_buff *skb, int len)
 	return skb->tail;
 }
 
-static int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
+int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
 {
+	struct tcp_opt *tp = tcp_sk(sk);
+
 	if (skb_cloned(skb) &&
 	    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
 		return -ENOMEM;
@@ -474,6 +577,17 @@ static int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
 
 	TCP_SKB_CB(skb)->seq += len;
 	skb->ip_summed = CHECKSUM_HW;
+
+	skb->truesize	     -= len;
+	sk->sk_queue_shrunk   = 1;
+	sk->sk_wmem_queued   -= len;
+	sk->sk_forward_alloc += len;
+
+	/* Any change of skb->len requires recalculation of tso
+	 * factor and mss.
+	 */
+	tcp_set_skb_tso_segs(skb, tp->mss_cache_std);
+
 	return 0;
 }
 
@@ -500,7 +614,7 @@ static int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
    this function.			--ANK (980731)
  */
 
-int tcp_sync_mss(struct sock *sk, u32 pmtu)
+unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu)
 {
 	struct tcp_opt *tp = tcp_sk(sk);
 	struct dst_entry *dst = __sk_dst_get(sk);
@@ -536,23 +650,71 @@ int tcp_sync_mss(struct sock *sk, u32 pmtu)
 	tp->pmtu_cookie = pmtu;
 	tp->mss_cache = tp->mss_cache_std = mss_now;
 
-	if (sk->sk_route_caps & NETIF_F_TSO) {
-		int large_mss;
+	return mss_now;
+}
+
+/* Compute the current effective MSS, taking SACKs and IP options,
+ * and even PMTU discovery events into account.
+ *
+ * LARGESEND note: !urg_mode is overkill, only frames up to snd_up
+ * cannot be large. However, taking into account rare use of URG, this
+ * is not a big flaw.
+ */
+
+unsigned int tcp_current_mss(struct sock *sk, int large)
+{
+	struct tcp_opt *tp = tcp_sk(sk);
+	struct dst_entry *dst = __sk_dst_get(sk);
+	unsigned int do_large, mss_now;
+
+	mss_now = tp->mss_cache_std;
+	if (dst) {
+		u32 mtu = dst_pmtu(dst);
+		if (mtu != tp->pmtu_cookie ||
+		    tp->ext2_header_len != dst->header_len)
+			mss_now = tcp_sync_mss(sk, mtu);
+	}
+
+	do_large = (large &&
+		    (sk->sk_route_caps & NETIF_F_TSO) &&
+		    !tp->urg_mode);
+
+	if (do_large) {
+		unsigned int large_mss, factor, limit;
 
 		large_mss = 65535 - tp->af_specific->net_header_len -
-			tp->ext_header_len - tp->ext2_header_len - tp->tcp_header_len;
+			tp->ext_header_len - tp->ext2_header_len -
+			tp->tcp_header_len;
 
 		if (tp->max_window && large_mss > (tp->max_window>>1))
-			large_mss = max((tp->max_window>>1), 68U - tp->tcp_header_len);
+			large_mss = max((tp->max_window>>1),
+					68U - tp->tcp_header_len);
+
+		factor = large_mss / mss_now;
 
-		/* Always keep large mss multiple of real mss. */
-		tp->mss_cache = mss_now*(large_mss/mss_now);
+		/* Always keep large mss multiple of real mss, but
+		 * do not exceed 1/tso_win_divisor of the congestion window
+		 * so we can keep the ACK clock ticking and minimize
+		 * bursting.
+		 */
+		limit = tp->snd_cwnd;
+		if (sysctl_tcp_tso_win_divisor)
+			limit /= sysctl_tcp_tso_win_divisor;
+		limit = max(1U, limit);
+		if (factor > limit)
+			factor = limit;
+
+		tp->mss_cache = mss_now * factor;
+
+		mss_now = tp->mss_cache;
 	}
 
+	if (tp->eff_sacks)
+		mss_now -= (TCPOLEN_SACK_BASE_ALIGNED +
+			    (tp->eff_sacks * TCPOLEN_SACK_PERBLOCK));
 	return mss_now;
 }
 
-
 /* This routine writes packets to the network.  It advances the
  * send_head.  This happens as incoming acks open up the remote
  * window for us.
@@ -592,8 +754,12 @@ int tcp_write_xmit(struct sock *sk, int nonagle)
 			TCP_SKB_CB(skb)->when = tcp_time_stamp;
 			if (tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC)))
 				break;
-			/* Advance the send_head.  This one is sent out. */
+
+			/* Advance the send_head.  This one is sent out.
+			 * This call will increment packets_out.
+			 */
 			update_send_head(sk, tp, skb);
+
 			tcp_minshall_update(tp, mss_now, skb);
 			sent_pkts = 1;
 		}
@@ -603,7 +769,7 @@ int tcp_write_xmit(struct sock *sk, int nonagle)
 			return 0;
 		}
 
-		return !tp->packets_out && sk->sk_send_head;
+		return !tcp_get_pcount(&tp->packets_out) && sk->sk_send_head;
 	}
 	return 0;
 }
@@ -729,7 +895,7 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int m
 	/* The first test we must make is that neither of these two
 	 * SKB's are still referenced by someone else.
 	 */
-	if(!skb_cloned(skb) && !skb_cloned(next_skb)) {
+	if (!skb_cloned(skb) && !skb_cloned(next_skb)) {
 		int skb_size = skb->len, next_skb_size = next_skb->len;
 		u16 flags = TCP_SKB_CB(skb)->flags;
 
@@ -749,6 +915,9 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int m
 		    ((skb_size + next_skb_size) > mss_now))
 			return;
 
+		BUG_ON(tcp_skb_pcount(skb) != 1 ||
+		       tcp_skb_pcount(next_skb) != 1);
+
 		/* Ok.  We will be able to collapse the packet. */
 		__skb_unlink(next_skb, next_skb->list);
 
@@ -772,24 +941,23 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int m
 		 */
 		TCP_SKB_CB(skb)->sacked |= TCP_SKB_CB(next_skb)->sacked&(TCPCB_EVER_RETRANS|TCPCB_AT_TAIL);
 		if (TCP_SKB_CB(next_skb)->sacked&TCPCB_SACKED_RETRANS)
-			tp->retrans_out--;
+			tcp_dec_pcount(&tp->retrans_out, next_skb);
 		if (TCP_SKB_CB(next_skb)->sacked&TCPCB_LOST) {
-			tp->lost_out--;
-			tp->left_out--;
+			tcp_dec_pcount(&tp->lost_out, next_skb);
+			tcp_dec_pcount(&tp->left_out, next_skb);
 		}
 		/* Reno case is special. Sigh... */
-		if (!tp->sack_ok && tp->sacked_out) {
-			tp->sacked_out--;
-			tp->left_out--;
+		if (!tp->sack_ok && tcp_get_pcount(&tp->sacked_out)) {
+			tcp_dec_pcount_approx(&tp->sacked_out, next_skb);
+			tcp_dec_pcount(&tp->left_out, next_skb);
 		}
 
 		/* Not quite right: it can be > snd.fack, but
 		 * it is better to underestimate fackets.
 		 */
-		if (tp->fackets_out)
-			tp->fackets_out--;
+		tcp_dec_pcount_approx(&tp->fackets_out, next_skb);
+		tcp_packets_out_dec(tp, next_skb);
 		sk_stream_free_skb(sk, next_skb);
-		tp->packets_out--;
 	}
 }
 
@@ -809,11 +977,11 @@ void tcp_simple_retransmit(struct sock *sk)
 		    !(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED)) {
 			if (TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_RETRANS) {
 				TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS;
-				tp->retrans_out--;
+				tcp_dec_pcount(&tp->retrans_out, skb);
 			}
 			if (!(TCP_SKB_CB(skb)->sacked&TCPCB_LOST)) {
 				TCP_SKB_CB(skb)->sacked |= TCPCB_LOST;
-				tp->lost_out++;
+				tcp_inc_pcount(&tp->lost_out, skb);
 				lost = 1;
 			}
 		}
@@ -879,12 +1047,18 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
 	    && TCP_SKB_CB(skb)->seq != tp->snd_una)
 		return -EAGAIN;
 
-	if(skb->len > cur_mss) {
-		if(tcp_fragment(sk, skb, cur_mss))
+	if (skb->len > cur_mss) {
+		int old_factor = tcp_skb_pcount(skb);
+		int new_factor;
+
+		if (tcp_fragment(sk, skb, cur_mss))
 			return -ENOMEM; /* We'll try again later. */
 
 		/* New SKB created, account for it. */
-		tp->packets_out++;
+		new_factor = tcp_skb_pcount(skb);
+		tcp_dec_pcount_explicit(&tp->packets_out,
+					old_factor - new_factor);
+		tcp_inc_pcount(&tp->packets_out, skb->next);
 	}
 
 	/* Collapse two adjacent packets if worthwhile and we can. */
@@ -908,6 +1082,8 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
 	   tp->snd_una == (TCP_SKB_CB(skb)->end_seq - 1)) {
 		if (!pskb_trim(skb, 0)) {
 			TCP_SKB_CB(skb)->seq = TCP_SKB_CB(skb)->end_seq - 1;
+			skb_shinfo(skb)->tso_segs = 1;
+			skb_shinfo(skb)->tso_size = 0;
 			skb->ip_summed = CHECKSUM_NONE;
 			skb->csum = 0;
 		}
@@ -933,7 +1109,7 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
 		}
 #endif
 		TCP_SKB_CB(skb)->sacked |= TCPCB_RETRANS;
-		tp->retrans_out++;
+		tcp_inc_pcount(&tp->retrans_out, skb);
 
 		/* Save stamp of the first retransmit. */
 		if (!tp->retrans_stamp)
@@ -961,13 +1137,20 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
 {
 	struct tcp_opt *tp = tcp_sk(sk);
 	struct sk_buff *skb;
-	int packet_cnt = tp->lost_out;
+	int packet_cnt = tcp_get_pcount(&tp->lost_out);
 
 	/* First pass: retransmit lost packets. */
 	if (packet_cnt) {
 		sk_stream_for_retrans_queue(skb, sk) {
 			__u8 sacked = TCP_SKB_CB(skb)->sacked;
 
+			/* Assume this retransmit will generate
+			 * only one packet for congestion window
+			 * calculation purposes.  This works because
+			 * tcp_retransmit_skb() will chop up the
+			 * packet to be MSS sized and all the
+			 * packet counting works out.
+			 */
 			if (tcp_packets_in_flight(tp) >= tp->snd_cwnd)
 				return;
 
@@ -985,7 +1168,8 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
 						tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
 				}
 
-				if (--packet_cnt <= 0)
+				packet_cnt -= tcp_skb_pcount(skb);
+				if (packet_cnt <= 0)
 					break;
 			}
 		}
@@ -1004,7 +1188,7 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
 	/* Yeah, we have to make difficult choice between forward transmission
 	 * and retransmission... Both ways have their merits...
 	 *
-	 * For now we do not retrnamsit anything, while we have some new
+	 * For now we do not retransmit anything, while we have some new
 	 * segments to send.
 	 */
 
@@ -1014,17 +1198,23 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
 	packet_cnt = 0;
 
 	sk_stream_for_retrans_queue(skb, sk) {
-		if(++packet_cnt > tp->fackets_out)
+		/* Similar to the retransmit loop above we
+		 * can pretend that the retransmitted SKB
+		 * we send out here will be composed of one
+		 * real MSS sized packet because tcp_retransmit_skb()
+		 * will fragment it if necessary.
+		 */
+		if (++packet_cnt > tcp_get_pcount(&tp->fackets_out))
 			break;
 
 		if (tcp_packets_in_flight(tp) >= tp->snd_cwnd)
 			break;
 
-		if(TCP_SKB_CB(skb)->sacked & TCPCB_TAGBITS)
+		if (TCP_SKB_CB(skb)->sacked & TCPCB_TAGBITS)
 			continue;
 
 		/* Ok, retransmit it. */
-		if(tcp_retransmit_skb(sk, skb))
+		if (tcp_retransmit_skb(sk, skb))
 			break;
 
 		if (skb == skb_peek(&sk->sk_write_queue))
@@ -1042,13 +1232,13 @@ void tcp_send_fin(struct sock *sk)
 {
 	struct tcp_opt *tp = tcp_sk(sk);	
 	struct sk_buff *skb = skb_peek_tail(&sk->sk_write_queue);
-	unsigned int mss_now;
+	int mss_now;
 	
 	/* Optimization, tack on the FIN if we have a queue of
 	 * unsent frames.  But be careful about outgoing SACKS
 	 * and IP options.
 	 */
-	mss_now = tcp_current_mss(sk, 1); 
+	mss_now = tcp_current_mss(sk, 1);
 
 	if (sk->sk_send_head != NULL) {
 		TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_FIN;
@@ -1068,6 +1258,8 @@ void tcp_send_fin(struct sock *sk)
 		skb->csum = 0;
 		TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_FIN);
 		TCP_SKB_CB(skb)->sacked = 0;
+		skb_shinfo(skb)->tso_segs = 1;
+		skb_shinfo(skb)->tso_size = 0;
 
 		/* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */
 		TCP_SKB_CB(skb)->seq = tp->write_seq;
@@ -1099,6 +1291,8 @@ void tcp_send_active_reset(struct sock *sk, int priority)
 	skb->csum = 0;
 	TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_RST);
 	TCP_SKB_CB(skb)->sacked = 0;
+	skb_shinfo(skb)->tso_segs = 1;
+	skb_shinfo(skb)->tso_size = 0;
 
 	/* Send it off. */
 	TCP_SKB_CB(skb)->seq = tcp_acceptable_seq(sk, tp);
@@ -1178,6 +1372,9 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
 	th->dest = req->rmt_port;
 	TCP_SKB_CB(skb)->seq = req->snt_isn;
 	TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1;
+	TCP_SKB_CB(skb)->sacked = 0;
+	skb_shinfo(skb)->tso_segs = 1;
+	skb_shinfo(skb)->tso_size = 0;
 	th->seq = htonl(TCP_SKB_CB(skb)->seq);
 	th->ack_seq = htonl(req->rcv_isn + 1);
 	if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */
@@ -1233,7 +1430,7 @@ static inline void tcp_connect_init(struct sock *sk)
 		tp->window_clamp = dst_metric(dst, RTAX_WINDOW);
 	tp->advmss = dst_metric(dst, RTAX_ADVMSS);
 	tcp_initialize_rcv_mss(sk);
-	tcp_vegas_init(tp);
+	tcp_ca_init(tp);
 
 	tcp_select_initial_window(tcp_full_space(sk),
 				  tp->advmss - (tp->ts_recent_stamp ? tp->tcp_header_len - sizeof(struct tcphdr) : 0),
@@ -1279,19 +1476,21 @@ int tcp_connect(struct sock *sk)
 	TCP_SKB_CB(buff)->flags = TCPCB_FLAG_SYN;
 	TCP_ECN_send_syn(sk, tp, buff);
 	TCP_SKB_CB(buff)->sacked = 0;
+	skb_shinfo(buff)->tso_segs = 1;
+	skb_shinfo(buff)->tso_size = 0;
 	buff->csum = 0;
 	TCP_SKB_CB(buff)->seq = tp->write_seq++;
 	TCP_SKB_CB(buff)->end_seq = tp->write_seq;
 	tp->snd_nxt = tp->write_seq;
 	tp->pushed_seq = tp->write_seq;
-	tcp_vegas_init(tp);
+	tcp_ca_init(tp);
 
 	/* Send it off. */
 	TCP_SKB_CB(buff)->when = tcp_time_stamp;
 	tp->retrans_stamp = TCP_SKB_CB(buff)->when;
 	__skb_queue_tail(&sk->sk_write_queue, buff);
 	sk_charge_skb(sk, buff);
-	tp->packets_out++;
+	tcp_inc_pcount(&tp->packets_out, buff);
 	tcp_transmit_skb(sk, skb_clone(buff, GFP_KERNEL));
 	TCP_INC_STATS(TCP_MIB_ACTIVEOPENS);
 
@@ -1378,6 +1577,8 @@ void tcp_send_ack(struct sock *sk)
 		buff->csum = 0;
 		TCP_SKB_CB(buff)->flags = TCPCB_FLAG_ACK;
 		TCP_SKB_CB(buff)->sacked = 0;
+		skb_shinfo(buff)->tso_segs = 1;
+		skb_shinfo(buff)->tso_size = 0;
 
 		/* Send it off, this clears delayed acks for us. */
 		TCP_SKB_CB(buff)->seq = TCP_SKB_CB(buff)->end_seq = tcp_acceptable_seq(sk, tp);
@@ -1412,6 +1613,8 @@ static int tcp_xmit_probe_skb(struct sock *sk, int urgent)
 	skb->csum = 0;
 	TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK;
 	TCP_SKB_CB(skb)->sacked = urgent;
+	skb_shinfo(skb)->tso_segs = 1;
+	skb_shinfo(skb)->tso_size = 0;
 
 	/* Use a previous sequence.  This should cause the other
 	 * end to send an ack.  Don't queue or clone SKB, just
@@ -1432,8 +1635,8 @@ int tcp_write_wakeup(struct sock *sk)
 		if ((skb = sk->sk_send_head) != NULL &&
 		    before(TCP_SKB_CB(skb)->seq, tp->snd_una+tp->snd_wnd)) {
 			int err;
-			int mss = tcp_current_mss(sk, 0);
-			int seg_size = tp->snd_una+tp->snd_wnd-TCP_SKB_CB(skb)->seq;
+			unsigned int mss = tcp_current_mss(sk, 0);
+			unsigned int seg_size = tp->snd_una+tp->snd_wnd-TCP_SKB_CB(skb)->seq;
 
 			if (before(tp->pushed_seq, TCP_SKB_CB(skb)->end_seq))
 				tp->pushed_seq = TCP_SKB_CB(skb)->end_seq;
@@ -1455,7 +1658,9 @@ int tcp_write_wakeup(struct sock *sk)
 					sk->sk_route_caps &= ~NETIF_F_TSO;
 					tp->mss_cache = tp->mss_cache_std;
 				}
-			}
+			} else if (!tcp_skb_pcount(skb))
+				tcp_set_skb_tso_segs(skb, tp->mss_cache_std);
+
 			TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
 			TCP_SKB_CB(skb)->when = tcp_time_stamp;
 			err = tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC));
@@ -1483,7 +1688,7 @@ void tcp_send_probe0(struct sock *sk)
 
 	err = tcp_write_wakeup(sk);
 
-	if (tp->packets_out || !sk->sk_send_head) {
+	if (tcp_get_pcount(&tp->packets_out) || !sk->sk_send_head) {
 		/* Cancel probe timer, if it is not required. */
 		tp->probes_out = 0;
 		tp->backoff = 0;
@@ -1517,6 +1722,5 @@ EXPORT_SYMBOL(tcp_make_synack);
 EXPORT_SYMBOL(tcp_send_synack);
 EXPORT_SYMBOL(tcp_simple_retransmit);
 EXPORT_SYMBOL(tcp_sync_mss);
-EXPORT_SYMBOL(tcp_transmit_skb);
 EXPORT_SYMBOL(tcp_write_wakeup);
 EXPORT_SYMBOL(tcp_write_xmit);
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 72a5a50b5..c060bb333 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -121,7 +121,7 @@ static int tcp_out_of_resources(struct sock *sk, int do_reset)
 		 *      1. Last segment was sent recently. */
 		if ((s32)(tcp_time_stamp - tp->lsndtime) <= TCP_TIMEWAIT_LEN ||
 		    /*  2. Window is closed. */
-		    (!tp->snd_wnd && !tp->packets_out))
+		    (!tp->snd_wnd && !tcp_get_pcount(&tp->packets_out)))
 			do_reset = 1;
 		if (do_reset)
 			tcp_send_active_reset(sk, GFP_ATOMIC);
@@ -269,7 +269,7 @@ static void tcp_probe_timer(struct sock *sk)
 	struct tcp_opt *tp = tcp_sk(sk);
 	int max_probes;
 
-	if (tp->packets_out || !sk->sk_send_head) {
+	if (tcp_get_pcount(&tp->packets_out) || !sk->sk_send_head) {
 		tp->probes_out = 0;
 		return;
 	}
@@ -316,7 +316,7 @@ static void tcp_retransmit_timer(struct sock *sk)
 {
 	struct tcp_opt *tp = tcp_sk(sk);
 
-	if (tp->packets_out == 0)
+	if (!tcp_get_pcount(&tp->packets_out))
 		goto out;
 
 	BUG_TRAP(!skb_queue_empty(&sk->sk_write_queue));
@@ -606,7 +606,7 @@ static void tcp_keepalive_timer (unsigned long data)
 	elapsed = keepalive_time_when(tp);
 
 	/* It is alive without keepalive 8) */
-	if (tp->packets_out || sk->sk_send_head)
+	if (tcp_get_pcount(&tp->packets_out) || sk->sk_send_head)
 		goto resched;
 
 	elapsed = tcp_time_stamp - tp->rcv_tstamp;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 977286f30..49a9cd061 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -120,8 +120,6 @@ rwlock_t udp_hash_lock = RW_LOCK_UNLOCKED;
 /* Shared by v4/v6 udp. */
 int udp_port_rover;
 
-int tcp_ipv4_addr_conflict(struct sock *sk1, struct sock *sk2);
-
 static int udp_v4_get_port(struct sock *sk, unsigned short snum)
 {
 	struct hlist_node *node;
@@ -176,12 +174,12 @@ gotit:
 			struct inet_opt *inet2 = inet_sk(sk2);
 
 			if (inet2->num == snum &&
-			    sk2 != sk &&
-			    !ipv6_only_sock(sk2) &&
+			    sk2 != sk && !ipv6_only_sock(sk2) &&
 			    (!sk2->sk_bound_dev_if ||
 			     !sk->sk_bound_dev_if ||
 			     sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
-			    tcp_ipv4_addr_conflict(sk2, sk) &&
+			    nx_addr_conflict(sk->sk_nx_info,
+			     tcp_v4_rcv_saddr(sk), sk2) &&
 			    (!sk2->sk_reuse || !sk->sk_reuse))
 				goto fail;
 		}
@@ -1346,6 +1344,7 @@ struct proto udp_prot = {
 	.hash =		udp_v4_hash,
 	.unhash =	udp_v4_unhash,
 	.get_port =	udp_v4_get_port,
+	.slab_obj_size = sizeof(struct udp_sock),
 };
 
 /* ------------------------------------------------------------------------ */
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index b045c8719..47e54d421 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -24,8 +24,7 @@ static inline void ipip_ecn_decapsulate(struct sk_buff *skb)
 	struct iphdr *outer_iph = skb->nh.iph;
 	struct iphdr *inner_iph = skb->h.ipiph;
 
-	if (INET_ECN_is_ce(outer_iph->tos) &&
-	    INET_ECN_is_not_ce(inner_iph->tos))
+	if (INET_ECN_is_ce(outer_iph->tos))
 		IP_ECN_set_ce(inner_iph);
 }
 
@@ -102,6 +101,8 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
 			if (skb_cloned(skb) &&
 			    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
 				goto drop;
+			if (x->props.flags & XFRM_STATE_DECAP_DSCP)
+				ipv4_copy_dscp(iph, skb->h.ipiph);
 			if (!(x->props.flags & XFRM_STATE_NOECN))
 				ipip_ecn_decapsulate(skb);
 			skb->mac.raw = memmove(skb->data - skb->mac_len,
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index 191cec718..21832dfc3 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -58,8 +58,7 @@ static void xfrm4_encap(struct sk_buff *skb)
 	if (!top_iph->frag_off)
 		__ip_select_ident(top_iph, dst, 0);
 
-	/* TTL disclosed */
-	top_iph->ttl = iph->ttl;
+	top_iph->ttl = dst_path_metric(dst, RTAX_HOPLIMIT);
 
 	top_iph->saddr = x->props.saddr.a4;
 	top_iph->daddr = x->id.daddr.a4;
@@ -119,8 +118,7 @@ int xfrm4_output(struct sk_buff **pskb)
 
 	xfrm4_encap(skb);
 
-	err = x->type->output(pskb);
-	skb = *pskb;
+	err = x->type->output(skb);
 	if (err)
 		goto error;
 
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 3aacce604..3ce69883b 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -12,8 +12,8 @@
 #include <net/xfrm.h>
 #include <net/ip.h>
 
-extern struct dst_ops xfrm4_dst_ops;
-extern struct xfrm_policy_afinfo xfrm4_policy_afinfo;
+static struct dst_ops xfrm4_dst_ops;
+static struct xfrm_policy_afinfo xfrm4_policy_afinfo;
 
 static struct xfrm_type_map xfrm4_type_map = { .lock = RW_LOCK_UNLOCKED };
 
@@ -183,6 +183,15 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl)
 			}
 			break;
 
+		case IPPROTO_ICMP:
+			if (pskb_may_pull(skb, xprth + 2 - skb->data)) {
+				u8 *icmp = xprth;
+
+				fl->fl_icmp_type = icmp[0];
+				fl->fl_icmp_code = icmp[1];
+			}
+			break;
+
 		case IPPROTO_ESP:
 			if (pskb_may_pull(skb, xprth + 4 - skb->data)) {
 				u32 *ehdr = (u32 *)xprth;
@@ -234,7 +243,7 @@ static void xfrm4_update_pmtu(struct dst_entry *dst, u32 mtu)
 	path->ops->update_pmtu(path, mtu);
 }
 
-struct dst_ops xfrm4_dst_ops = {
+static struct dst_ops xfrm4_dst_ops = {
 	.family =		AF_INET,
 	.protocol =		__constant_htons(ETH_P_IP),
 	.gc =			xfrm4_garbage_collect,
@@ -243,7 +252,7 @@ struct dst_ops xfrm4_dst_ops = {
 	.entry_size =		sizeof(struct xfrm_dst),
 };
 
-struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
+static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
 	.family = 		AF_INET,
 	.lock = 		RW_LOCK_UNLOCKED,
 	.type_map = 		&xfrm4_type_map,
@@ -254,12 +263,12 @@ struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
 	.decode_session =	_decode_session4,
 };
 
-void __init xfrm4_policy_init(void)
+static void __init xfrm4_policy_init(void)
 {
 	xfrm_policy_register_afinfo(&xfrm4_policy_afinfo);
 }
 
-void __exit xfrm4_policy_fini(void)
+static void __exit xfrm4_policy_fini(void)
 {
 	xfrm_policy_unregister_afinfo(&xfrm4_policy_afinfo);
 }
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index 0d1a0b0c7..dcc04644c 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -4,13 +4,13 @@
  */
 
 #include <linux/skbuff.h>
+#include <linux/module.h>
 #include <net/xfrm.h>
 #include <net/ip.h>
 #include <net/protocol.h>
 
-static int ipip_output(struct sk_buff **pskb)
+static int ipip_output(struct sk_buff *skb)
 {
-	struct sk_buff *skb = *pskb;
 	struct iphdr *iph;
 	
 	iph = skb->nh.iph;
@@ -43,6 +43,8 @@ int xfrm4_tunnel_register(struct xfrm_tunnel *handler)
 	return ret;
 }
 
+EXPORT_SYMBOL(xfrm4_tunnel_register);
+
 int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler)
 {
 	int ret;
@@ -60,6 +62,8 @@ int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler)
 	return ret;
 }
 
+EXPORT_SYMBOL(xfrm4_tunnel_deregister);
+
 static int ipip_rcv(struct sk_buff *skb)
 {
 	struct xfrm_tunnel *handler = ipip_handler;
@@ -68,7 +72,7 @@ static int ipip_rcv(struct sk_buff *skb)
 	if (handler && handler->handler(skb) == 0)
 		return 0;
 
-	return xfrm4_rcv_encap(skb, 0);
+	return xfrm4_rcv(skb);
 }
 
 static void ipip_err(struct sk_buff *skb, u32 info)
@@ -84,6 +88,10 @@ static int ipip_init_state(struct xfrm_state *x, void *args)
 {
 	if (!x->props.mode)
 		return -EINVAL;
+
+	if (x->encap)
+		return -EINVAL;
+
 	x->props.header_len = sizeof(struct iphdr);
 
 	return 0;
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index 23c5759c0..fd87a5a19 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -48,6 +48,7 @@ config INET6_IPCOMP
 	tristate "IPv6: IPComp transformation"
 	depends on IPV6
 	select XFRM
+	select INET6_TUNNEL
 	select CRYPTO
 	select CRYPTO_DEFLATE
 	---help---
@@ -56,9 +57,21 @@ config INET6_IPCOMP
 
 	  If unsure, say Y.
 
+config INET6_TUNNEL
+	tristate "IPv6: tunnel transformation"
+	depends on IPV6
+	select XFRM
+	---help---
+	  Support for generic IPv6-in-IPv6 tunnel transformation, which is
+	  required by the IPv6-in-IPv6 tunneling module as well as tunnel mode
+	  IPComp.
+	  
+	  If unsure, say Y.
+
 config IPV6_TUNNEL
 	tristate "IPv6: IPv6-in-IPv6 tunnel"
 	depends on IPV6
+	select INET6_TUNNEL
 	---help---
 	  Support for IPv6-in-IPv6 tunnels described in RFC 2473.
 
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index d9e309fe8..b39e04940 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -11,12 +11,13 @@ ipv6-objs :=	af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o sit.o \
 		ip6_flowlabel.o ipv6_syms.o
 
 ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \
-	xfrm6_tunnel.o xfrm6_output.o
+	xfrm6_output.o
 ipv6-objs += $(ipv6-y)
 
 obj-$(CONFIG_INET6_AH) += ah6.o
 obj-$(CONFIG_INET6_ESP) += esp6.o
 obj-$(CONFIG_INET6_IPCOMP) += ipcomp6.o
+obj-$(CONFIG_INET6_TUNNEL) += xfrm6_tunnel.o 
 obj-$(CONFIG_NETFILTER)	+= netfilter/
 
 obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 40ad73c5c..4fb96bc80 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -128,6 +128,9 @@ static struct timer_list addr_chk_timer =
 			TIMER_INITIALIZER(addrconf_verify, 0, 0);
 static spinlock_t addrconf_verify_lock = SPIN_LOCK_UNLOCKED;
 
+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, int flags);
@@ -419,33 +422,28 @@ static void dev_forward_change(struct inet6_dev *idev)
 			ipv6_dev_mc_dec(dev, &addr);
 	}
 	for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) {
-		ipv6_addr_prefix(&addr, &ifa->addr, ifa->prefix_len);
-		if (ipv6_addr_any(&addr))
-			continue;
 		if (idev->cnf.forwarding)
-			ipv6_dev_ac_inc(idev->dev, &addr);
+			addrconf_join_anycast(ifa);
 		else
-			ipv6_dev_ac_dec(idev->dev, &addr);
+			addrconf_leave_anycast(ifa);
 	}
 }
 
 
-static void addrconf_forward_change(struct inet6_dev *idev)
+static void addrconf_forward_change(void)
 {
 	struct net_device *dev;
-
-	if (idev) {
-		dev_forward_change(idev);
-		return;
-	}
+	struct inet6_dev *idev;
 
 	read_lock(&dev_base_lock);
 	for (dev=dev_base; dev; dev=dev->next) {
 		read_lock(&addrconf_lock);
 		idev = __in6_dev_get(dev);
 		if (idev) {
+			int changed = (!idev->cnf.forwarding) ^ (!ipv6_devconf.forwarding);
 			idev->cnf.forwarding = ipv6_devconf.forwarding;
-			dev_forward_change(idev);
+			if (changed)
+				dev_forward_change(idev);
 		}
 		read_unlock(&addrconf_lock);
 	}
@@ -472,6 +470,8 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
 		printk("Freeing alive inet6 address %p\n", ifp);
 		return;
 	}
+	dst_release(&ifp->rt->u.dst);
+
 	inet6_ifa_count--;
 	kfree(ifp);
 }
@@ -482,25 +482,33 @@ static struct inet6_ifaddr *
 ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
 	      int scope, unsigned flags)
 {
-	struct inet6_ifaddr *ifa;
+	struct inet6_ifaddr *ifa = NULL;
+	struct rt6_info *rt;
 	int hash;
 	static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+	int err = 0;
 
 	spin_lock_bh(&lock);
 
 	/* Ignore adding duplicate addresses on an interface */
 	if (ipv6_chk_same_addr(addr, idev->dev)) {
-		spin_unlock_bh(&lock);
 		ADBG(("ipv6_add_addr: already assigned\n"));
-		return ERR_PTR(-EEXIST);
+		err = -EEXIST;
+		goto out;
 	}
 
 	ifa = kmalloc(sizeof(struct inet6_ifaddr), GFP_ATOMIC);
 
 	if (ifa == NULL) {
-		spin_unlock_bh(&lock);
 		ADBG(("ipv6_add_addr: malloc failed\n"));
-		return ERR_PTR(-ENOBUFS);
+		err = -ENOBUFS;
+		goto out;
+	}
+
+	rt = addrconf_dst_alloc(idev, addr, 0);
+	if (IS_ERR(rt)) {
+		err = PTR_ERR(rt);
+		goto out;
 	}
 
 	memset(ifa, 0, sizeof(struct inet6_ifaddr));
@@ -517,9 +525,8 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
 	read_lock(&addrconf_lock);
 	if (idev->dead) {
 		read_unlock(&addrconf_lock);
-		spin_unlock_bh(&lock);
-		kfree(ifa);
-		return ERR_PTR(-ENODEV);	/*XXX*/
+		err = -ENODEV;	/*XXX*/
+		goto out;
 	}
 
 	inet6_ifa_count++;
@@ -553,12 +560,20 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
 	}
 #endif
 
+	ifa->rt = rt;
+
 	in6_ifa_hold(ifa);
 	write_unlock_bh(&idev->lock);
 	read_unlock(&addrconf_lock);
+out:
 	spin_unlock_bh(&lock);
 
-	notifier_call_chain(&inet6addr_chain,NETDEV_UP,ifa);
+	if (unlikely(err == 0))
+		notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa);
+	else {
+		kfree(ifa);
+		ifa = ERR_PTR(err);
+	}
 
 	return ifa;
 }
@@ -1045,17 +1060,34 @@ void addrconf_join_solict(struct net_device *dev, struct in6_addr *addr)
 	ipv6_dev_mc_inc(dev, &maddr);
 }
 
-void addrconf_leave_solict(struct net_device *dev, struct in6_addr *addr)
+void addrconf_leave_solict(struct inet6_dev *idev, struct in6_addr *addr)
 {
 	struct in6_addr maddr;
 
-	if (dev->flags&(IFF_LOOPBACK|IFF_NOARP))
+	if (idev->dev->flags&(IFF_LOOPBACK|IFF_NOARP))
 		return;
 
 	addrconf_addr_solict_mult(addr, &maddr);
-	ipv6_dev_mc_dec(dev, &maddr);
+	__ipv6_dev_mc_dec(idev, &maddr);
 }
 
+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);
+}
+
+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 ipv6_generate_eui64(u8 *eui, struct net_device *dev)
 {
@@ -1457,8 +1489,7 @@ ok:
 				spin_unlock(&ifp->lock);
 
 				if (!(flags&IFA_F_TENTATIVE))
-					ipv6_ifa_notify((flags&IFA_F_DEPRECATED) ?
-							0 : RTM_NEWADDR, ifp);
+					ipv6_ifa_notify(0, ifp);
 			} else
 				spin_unlock(&ifp->lock);
 
@@ -2056,6 +2087,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
 		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;
@@ -2091,21 +2123,13 @@ static void addrconf_rs_timer(unsigned long data)
 
 		ndisc_send_rs(ifp->idev->dev, &ifp->addr, &all_routers);
 	} else {
-		struct in6_rtmsg rtmsg;
-
 		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);
-
-		memset(&rtmsg, 0, sizeof(struct in6_rtmsg));
-		rtmsg.rtmsg_type = RTMSG_NEWROUTE;
-		rtmsg.rtmsg_metric = IP6_RT_PRIO_ADDRCONF;
-		rtmsg.rtmsg_flags = (RTF_ALLONLINK | RTF_DEFAULT | RTF_UP);
-
-		rtmsg.rtmsg_ifindex = ifp->idev->dev->ifindex;
-
-		ip6_route_add(&rtmsg, NULL, NULL);
 	}
 
 out:
@@ -2216,14 +2240,6 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
 		addrconf_mod_timer(ifp, AC_RS, ifp->idev->cnf.rtr_solicit_interval);
 		spin_unlock_bh(&ifp->lock);
 	}
-
-	if (ifp->idev->cnf.forwarding) {
-		struct in6_addr addr;
-
-		ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
-		if (!ipv6_addr_any(&addr))
-			ipv6_dev_ac_inc(ifp->idev->dev, &addr);
-	}
 }
 
 #ifdef CONFIG_PROC_FS
@@ -2646,6 +2662,10 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
 	struct ifmcaddr6 *ifmca;
 	struct ifacaddr6 *ifaca;
 
+	/* no ipv6 inside a vserver for now */
+	if (skb->sk && skb->sk->sk_vx_info)
+		return skb->len;
+
 	s_idx = cb->args[0];
 	s_ip_idx = ip_idx = cb->args[1];
 	read_lock(&dev_base_lock);
@@ -2865,6 +2885,10 @@ static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
 	struct net_device *dev;
 	struct inet6_dev *idev;
 
+	/* no ipv6 inside a vserver for now */
+	if (skb->sk && skb->sk->sk_vx_info)
+		return skb->len;
+
 	read_lock(&dev_base_lock);
 	for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
 		if (idx < s_idx)
@@ -2982,19 +3006,21 @@ static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
 
 	switch (event) {
 	case RTM_NEWADDR:
-		ip6_rt_addr_add(&ifp->addr, ifp->idev->dev, 0);
+		dst_hold(&ifp->rt->u.dst);
+		if (ip6_ins_rt(ifp->rt, NULL, NULL))
+			dst_release(&ifp->rt->u.dst);
+		if (ifp->idev->cnf.forwarding)
+			addrconf_join_anycast(ifp);
 		break;
 	case RTM_DELADDR:
-		addrconf_leave_solict(ifp->idev->dev, &ifp->addr);
-		if (ifp->idev->cnf.forwarding) {
-			struct in6_addr addr;
-
-			ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
-			if (!ipv6_addr_any(&addr))
-				ipv6_dev_ac_dec(ifp->idev->dev, &addr);
-		}
-		if (!ipv6_chk_addr(&ifp->addr, ifp->idev->dev, 1))
-			ip6_rt_addr_del(&ifp->addr, ifp->idev->dev);
+		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, NULL, NULL))
+			dst_free(&ifp->rt->u.dst);
+		else
+			dst_release(&ifp->rt->u.dst);
 		break;
 	}
 }
@@ -3011,18 +3037,18 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
 
 	ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
 
-	if (write && *valp != val && valp != &ipv6_devconf_dflt.forwarding) {
-		struct inet6_dev *idev = NULL;
-
+	if (write && valp != &ipv6_devconf_dflt.forwarding) {
 		if (valp != &ipv6_devconf.forwarding) {
-			idev = (struct inet6_dev *)ctl->extra1;
-			if (idev == NULL)
-				return ret;
-		} else
+			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(idev);
-
+			addrconf_forward_change();
+		}
 		if (*valp)
 			rt6_purge_dflt_routers(0);
 	}
@@ -3063,15 +3089,19 @@ static int addrconf_sysctl_forward_strategy(ctl_table *table,
 	}
 
 	if (valp != &ipv6_devconf_dflt.forwarding) {
-		struct inet6_dev *idev;
 		if (valp != &ipv6_devconf.forwarding) {
-			idev = (struct inet6_dev *)table->extra1;
+			struct inet6_dev *idev = (struct inet6_dev *)table->extra1;
+			int changed;
 			if (unlikely(idev == NULL))
 				return -ENODEV;
-		} else
-			idev = NULL;
-		*valp = new;
-		addrconf_forward_change(idev);
+			changed = (!*valp) ^ (!new);
+			*valp = new;
+			if (changed)
+				dev_forward_change(idev);
+		} else {
+			*valp = new;
+			addrconf_forward_change();
+		}
 
 		if (*valp)
 			rt6_purge_dflt_routers(0);
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 83e832e3e..2f3136c3e 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -90,11 +90,6 @@ int sysctl_ipv6_bindv6only;
 atomic_t inet6_sock_nr;
 #endif
 
-/* Per protocol sock slabcache */
-kmem_cache_t *tcp6_sk_cachep;
-kmem_cache_t *udp6_sk_cachep;
-kmem_cache_t *raw6_sk_cachep;
-
 /* The inetsw table contains everything that inet_create needs to
  * build a new socket.
  */
@@ -110,37 +105,11 @@ static void inet6_sock_destruct(struct sock *sk)
 #endif
 }
 
-static __inline__ kmem_cache_t *inet6_sk_slab(int protocol)
-{
-        kmem_cache_t* rc = tcp6_sk_cachep;
-
-        if (protocol == IPPROTO_UDP)
-                rc = udp6_sk_cachep;
-        else if (protocol == IPPROTO_RAW)
-                rc = raw6_sk_cachep;
-        return rc;
-}
-
-static __inline__ int inet6_sk_size(int protocol)
-{
-        int rc = sizeof(struct tcp6_sock);
-
-        if (protocol == IPPROTO_UDP)
-                rc = sizeof(struct udp6_sock);
-        else if (protocol == IPPROTO_RAW)
-                rc = sizeof(struct raw6_sock);
-        return rc;
-}
-
 static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk)
 {
-	struct ipv6_pinfo *rc = (&((struct tcp6_sock *)sk)->inet6);
+	const int offset = sk->sk_prot->slab_obj_size - sizeof(struct ipv6_pinfo);
 
-        if (sk->sk_protocol == IPPROTO_UDP)
-                rc = (&((struct udp6_sock *)sk)->inet6);
-        else if (sk->sk_protocol == IPPROTO_RAW)
-                rc = (&((struct raw6_sock *)sk)->inet6);
-        return rc;
+	return (struct ipv6_pinfo *)(((u8 *)sk) + offset);
 }
 
 static int inet6_create(struct socket *sock, int protocol)
@@ -151,11 +120,10 @@ static int inet6_create(struct socket *sock, int protocol)
 	struct tcp6_sock* tcp6sk;
 	struct list_head *p;
 	struct inet_protosw *answer;
-
-	sk = sk_alloc(PF_INET6, GFP_KERNEL, inet6_sk_size(protocol),
-		      inet6_sk_slab(protocol));
-	if (sk == NULL) 
-		goto do_oom;
+	struct proto *answer_prot;
+	unsigned char answer_flags;
+	char answer_no_check;
+	int rc;
 
 	/* Look for the requested type/protocol pair. */
 	answer = NULL;
@@ -179,22 +147,40 @@ static int inet6_create(struct socket *sock, int protocol)
 		answer = NULL;
 	}
 
+	rc = -ESOCKTNOSUPPORT;
 	if (!answer)
-		goto free_and_badtype;
+		goto out_rcu_unlock;
+	rc = -EPERM;
 	if (answer->capability > 0 && !capable(answer->capability))
-		goto free_and_badperm;
+		goto out_rcu_unlock;
+	rc = -EPROTONOSUPPORT;
 	if (!protocol)
-		goto free_and_noproto;
+		goto out_rcu_unlock;
 
 	sock->ops = answer->ops;
+
+	answer_prot = answer->prot;
+	answer_no_check = answer->no_check;
+	answer_flags = answer->flags;
+	rcu_read_unlock();
+
+	BUG_TRAP(answer_prot->slab != NULL);
+
+	rc = -ENOBUFS;
+	sk = sk_alloc(PF_INET6, GFP_KERNEL,
+		      answer_prot->slab_obj_size,
+		      answer_prot->slab);
+	if (sk == NULL)
+		goto out;
+
 	sock_init_data(sock, sk);
 	sk_set_owner(sk, THIS_MODULE);
 
-	sk->sk_prot = answer->prot;
-	sk->sk_no_check = answer->no_check;
-	if (INET_PROTOSW_REUSE & answer->flags)
+	rc = 0;
+	sk->sk_prot = answer_prot;
+	sk->sk_no_check = answer_no_check;
+	if (INET_PROTOSW_REUSE & answer_flags)
 		sk->sk_reuse = 1;
-	rcu_read_unlock();
 
 	inet = inet_sk(sk);
 
@@ -205,7 +191,6 @@ static int inet6_create(struct socket *sock, int protocol)
 	}
 
 	sk->sk_destruct		= inet6_sock_destruct;
-	sk->sk_zapped		= 0;
 	sk->sk_family		= PF_INET6;
 	sk->sk_protocol		= protocol;
 
@@ -248,28 +233,17 @@ static int inet6_create(struct socket *sock, int protocol)
 		sk->sk_prot->hash(sk);
 	}
 	if (sk->sk_prot->init) {
-		int err = sk->sk_prot->init(sk);
-		if (err != 0) {
+		rc = sk->sk_prot->init(sk);
+		if (rc) {
 			sk_common_release(sk);
-			return err;
+			goto out;
 		}
 	}
-	return 0;
-
-free_and_badtype:
-	rcu_read_unlock();
-	sk_free(sk);
-	return -ESOCKTNOSUPPORT;
-free_and_badperm:
-	rcu_read_unlock();
-	sk_free(sk);
-	return -EPERM;
-free_and_noproto:
+out:
+	return rc;
+out_rcu_unlock:
 	rcu_read_unlock();
-	sk_free(sk);
-	return -EPROTONOSUPPORT;
-do_oom:
-	return -ENOBUFS;
+	goto out;
 }
 
 
@@ -709,24 +683,26 @@ static int __init inet6_init(void)
 #endif
 #endif
 
-	if (sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb))
-	{
+	if (sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb)) {
 		printk(KERN_CRIT "inet6_proto_init: size fault\n");
 		return -EINVAL;
 	}
-	/* allocate our sock slab caches */
-        tcp6_sk_cachep = kmem_cache_create("tcp6_sock",
-					   sizeof(struct tcp6_sock), 0,
-                                           SLAB_HWCACHE_ALIGN, NULL, NULL);
-        udp6_sk_cachep = kmem_cache_create("udp6_sock",
-					   sizeof(struct udp6_sock), 0,
-                                           SLAB_HWCACHE_ALIGN, NULL, NULL);
-        raw6_sk_cachep = kmem_cache_create("raw6_sock",
-					   sizeof(struct raw6_sock), 0,
-                                           SLAB_HWCACHE_ALIGN, NULL, NULL);
-        if (!tcp6_sk_cachep || !udp6_sk_cachep || !raw6_sk_cachep)
-                printk(KERN_CRIT "%s: Can't create protocol sock SLAB "
-		       "caches!\n", __FUNCTION__);
+
+	err = sk_alloc_slab(&tcpv6_prot, "tcpv6_sock");
+	if (err) {
+		sk_alloc_slab_error(&tcpv6_prot);
+		goto out;
+	}
+	err = sk_alloc_slab(&udpv6_prot, "udpv6_sock");
+	if (err) {
+		sk_alloc_slab_error(&udpv6_prot);
+		goto out_tcp_free_slab;
+	}
+	err = sk_alloc_slab(&rawv6_prot, "rawv6_sock");
+	if (err) {
+		sk_alloc_slab_error(&rawv6_prot);
+		goto out_udp_free_slab;
+	}
 
 	/* Register the socket-side information for inet6_create.  */
 	for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r)
@@ -745,7 +721,7 @@ static int __init inet6_init(void)
 	/* Initialise ipv6 mibs */
 	err = init_ipv6_mibs();
 	if (err)
-		goto init_mib_fail;
+		goto out_raw_free_slab;
 	
 	/*
 	 *	ipngwg API draft makes clear that the correct semantics
@@ -798,8 +774,9 @@ static int __init inet6_init(void)
 	/* Init v6 transport protocols. */
 	udpv6_init();
 	tcpv6_init();
-
-	return 0;
+	err = 0;
+out:
+	return err;
 
 #ifdef CONFIG_PROC_FS
 proc_if6_fail:
@@ -824,8 +801,13 @@ icmp_fail:
 	ipv6_sysctl_unregister();
 #endif
 	cleanup_ipv6_mibs();
-init_mib_fail:
-	return err;
+out_raw_free_slab:
+	sk_free_slab(&rawv6_prot);
+out_udp_free_slab:
+	sk_free_slab(&udpv6_prot);
+out_tcp_free_slab:
+	sk_free_slab(&tcpv6_prot);
+	goto out;
 }
 module_init(inet6_init);
 
@@ -854,9 +836,9 @@ static void __exit inet6_exit(void)
 	ipv6_sysctl_unregister();	
 #endif
 	cleanup_ipv6_mibs();
-	kmem_cache_destroy(tcp6_sk_cachep);
-	kmem_cache_destroy(udp6_sk_cachep);
-	kmem_cache_destroy(raw6_sk_cachep);
+	sk_free_slab(&rawv6_prot);
+	sk_free_slab(&udpv6_prot);
+	sk_free_slab(&tcpv6_prot);
 }
 module_exit(inet6_exit);
 
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index eda2737e5..32ecedb04 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -154,11 +154,11 @@ static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len)
 	return 0;
 }
 
-int ah6_output(struct sk_buff **pskb)
+static int ah6_output(struct sk_buff *skb)
 {
 	int err;
 	int extlen;
-	struct dst_entry *dst = (*pskb)->dst;
+	struct dst_entry *dst = skb->dst;
 	struct xfrm_state *x  = dst->xfrm;
 	struct ipv6hdr *top_iph;
 	struct ip_auth_hdr *ah;
@@ -170,11 +170,11 @@ int ah6_output(struct sk_buff **pskb)
 		char hdrs[0];
 	} *tmp_ext;
 
-	top_iph = (struct ipv6hdr *)(*pskb)->data;
-	top_iph->payload_len = htons((*pskb)->len - sizeof(*top_iph));
+	top_iph = (struct ipv6hdr *)skb->data;
+	top_iph->payload_len = htons(skb->len - sizeof(*top_iph));
 
-	nexthdr = *(*pskb)->nh.raw;
-	*(*pskb)->nh.raw = IPPROTO_AH;
+	nexthdr = *skb->nh.raw;
+	*skb->nh.raw = IPPROTO_AH;
 
 	/* When there are no extension headers, we only need to save the first
 	 * 8 bytes of the base IP header.
@@ -182,7 +182,7 @@ int ah6_output(struct sk_buff **pskb)
 	memcpy(tmp_base, top_iph, sizeof(tmp_base));
 
 	tmp_ext = NULL;
-	extlen = (*pskb)->h.raw - (unsigned char *)(top_iph + 1);
+	extlen = skb->h.raw - (unsigned char *)(top_iph + 1);
 	if (extlen) {
 		extlen += sizeof(*tmp_ext);
 		tmp_ext = kmalloc(extlen, GFP_ATOMIC);
@@ -198,7 +198,7 @@ int ah6_output(struct sk_buff **pskb)
 			goto error_free_iph;
 	}
 
-	ah = (struct ip_auth_hdr *)(*pskb)->h.raw;
+	ah = (struct ip_auth_hdr *)skb->h.raw;
 	ah->nexthdr = nexthdr;
 
 	top_iph->priority    = 0;
@@ -214,7 +214,7 @@ int ah6_output(struct sk_buff **pskb)
 	ah->reserved = 0;
 	ah->spi = x->id.spi;
 	ah->seq_no = htonl(++x->replay.oseq);
-	ahp->icv(ahp, *pskb, ah->auth_data);
+	ahp->icv(ahp, skb, ah->auth_data);
 
 	err = 0;
 
@@ -229,7 +229,7 @@ error:
 	return err;
 }
 
-int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
 {
 	/*
 	 * Before process AH
@@ -319,8 +319,8 @@ out:
 	return -EINVAL;
 }
 
-void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 
-	 int type, int code, int offset, __u32 info)
+static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 
+                    int type, int code, int offset, __u32 info)
 {
 	struct ipv6hdr *iph = (struct ipv6hdr*)skb->data;
 	struct ip_auth_hdr *ah = (struct ip_auth_hdr*)(skb->data+offset);
@@ -353,6 +353,9 @@ static int ah6_init_state(struct xfrm_state *x, void *args)
 	if (x->aalg->alg_key_len > 512)
 		goto error;
 
+	if (x->encap)
+		goto error;
+
 	ahp = kmalloc(sizeof(*ahp), GFP_KERNEL);
 	if (ahp == NULL)
 		return -ENOMEM;
@@ -445,7 +448,7 @@ static struct inet6_protocol ah6_protocol = {
 	.flags		=	INET6_PROTO_NOPOLICY,
 };
 
-int __init ah6_init(void)
+static int __init ah6_init(void)
 {
 	if (xfrm_register_type(&ah6_type, AF_INET6) < 0) {
 		printk(KERN_INFO "ipv6 ah init: can't add xfrm type\n");
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index 5b1e4d959..a0de548c5 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -293,6 +293,7 @@ static void aca_put(struct ifacaddr6 *ac)
 {
 	if (atomic_dec_and_test(&ac->aca_refcnt)) {
 		in6_dev_put(ac->aca_idev);
+		dst_release(&ac->aca_rt->u.dst);
 		kfree(ac);
 	}
 }
@@ -304,6 +305,8 @@ int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr)
 {
 	struct ifacaddr6 *aca;
 	struct inet6_dev *idev;
+	struct rt6_info *rt;
+	int err;
 
 	idev = in6_dev_get(dev);
 
@@ -312,17 +315,15 @@ int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr)
 
 	write_lock_bh(&idev->lock);
 	if (idev->dead) {
-		write_unlock_bh(&idev->lock);
-		in6_dev_put(idev);
-		return -ENODEV;
+		err = -ENODEV;
+		goto out;
 	}
 
 	for (aca = idev->ac_list; aca; aca = aca->aca_next) {
 		if (ipv6_addr_cmp(&aca->aca_addr, addr) == 0) {
 			aca->aca_users++;
-			write_unlock_bh(&idev->lock);
-			in6_dev_put(idev);
-			return 0;
+			err = 0;
+			goto out;
 		}
 	}
 
@@ -333,15 +334,22 @@ int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr)
 	aca = kmalloc(sizeof(struct ifacaddr6), GFP_ATOMIC);
 
 	if (aca == NULL) {
-		write_unlock_bh(&idev->lock);
-		in6_dev_put(idev);
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto out;
+	}
+
+	rt = addrconf_dst_alloc(idev, addr, 1);
+	if (IS_ERR(rt)) {
+		kfree(aca);
+		err = PTR_ERR(rt);
+		goto out;
 	}
 
 	memset(aca, 0, sizeof(struct ifacaddr6));
 
 	ipv6_addr_copy(&aca->aca_addr, addr);
 	aca->aca_idev = idev;
+	aca->aca_rt = rt;
 	aca->aca_users = 1;
 	/* aca_tstamp should be updated upon changes */
 	aca->aca_cstamp = aca->aca_tstamp = jiffies;
@@ -352,26 +360,27 @@ int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr)
 	idev->ac_list = aca;
 	write_unlock_bh(&idev->lock);
 
-	ip6_rt_addr_add(&aca->aca_addr, dev, 1);
+	dst_hold(&rt->u.dst);
+	if (ip6_ins_rt(rt, NULL, NULL))
+		dst_release(&rt->u.dst);
 
 	addrconf_join_solict(dev, &aca->aca_addr);
 
 	aca_put(aca);
 	return 0;
+out:
+	write_unlock_bh(&idev->lock);
+	in6_dev_put(idev);
+	return err;
 }
 
 /*
  *	device anycast group decrement
  */
-int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr)
+int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr)
 {
-	struct inet6_dev *idev;
 	struct ifacaddr6 *aca, *prev_aca;
 
-	idev = in6_dev_get(dev);
-	if (idev == NULL)
-		return -ENODEV;
-
 	write_lock_bh(&idev->lock);
 	prev_aca = NULL;
 	for (aca = idev->ac_list; aca; aca = aca->aca_next) {
@@ -381,12 +390,10 @@ int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr)
 	}
 	if (!aca) {
 		write_unlock_bh(&idev->lock);
-		in6_dev_put(idev);
 		return -ENOENT;
 	}
 	if (--aca->aca_users > 0) {
 		write_unlock_bh(&idev->lock);
-		in6_dev_put(idev);
 		return 0;
 	}
 	if (prev_aca)
@@ -394,15 +401,29 @@ int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr)
 	else
 		idev->ac_list = aca->aca_next;
 	write_unlock_bh(&idev->lock);
-	addrconf_leave_solict(dev, &aca->aca_addr);
+	addrconf_leave_solict(idev, &aca->aca_addr);
 
-	ip6_rt_addr_del(&aca->aca_addr, dev);
+	dst_hold(&aca->aca_rt->u.dst);
+	if (ip6_del_rt(aca->aca_rt, NULL, NULL))
+		dst_free(&aca->aca_rt->u.dst);
+	else
+		dst_release(&aca->aca_rt->u.dst);
 
 	aca_put(aca);
-	in6_dev_put(idev);
 	return 0;
 }
 
+int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr)
+{
+	int ret;
+	struct inet6_dev *idev = in6_dev_get(dev);
+	if (idev == NULL)
+		return -ENODEV;
+	ret = __ipv6_dev_ac_dec(idev, addr);
+	in6_dev_put(idev);
+	return ret;
+}
+	
 /*
  *	check if the interface has this anycast address
  */
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 8b1cf3ea4..5e0aecb2d 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -38,7 +38,7 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 	struct sockaddr_in6	*usin = (struct sockaddr_in6 *) uaddr;
 	struct inet_opt      	*inet = inet_sk(sk);
 	struct ipv6_pinfo      	*np = inet6_sk(sk);
-	struct in6_addr		*daddr;
+	struct in6_addr		*daddr, *final_p = NULL, final;
 	struct dst_entry	*dst;
 	struct flowi		fl;
 	struct ip6_flowlabel	*flowlabel = NULL;
@@ -157,16 +157,27 @@ ipv4_connected:
 	if (flowlabel) {
 		if (flowlabel->opt && flowlabel->opt->srcrt) {
 			struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt;
+			ipv6_addr_copy(&final, &fl.fl6_dst);
 			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+			final_p = &final;
 		}
 	} else if (np->opt && np->opt->srcrt) {
 		struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
+		ipv6_addr_copy(&final, &fl.fl6_dst);
 		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+		final_p = &final;
 	}
 
 	err = ip6_dst_lookup(sk, &dst, &fl);
 	if (err)
 		goto out;
+	if (final_p)
+		ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+	if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+		dst_release(dst);
+		goto out;
+	}
 
 	/* source address lookup done in ip6_dst_lookup */
 
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 497727195..77b4ba6f8 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -37,11 +37,11 @@
 #include <net/ipv6.h>
 #include <linux/icmpv6.h>
 
-int esp6_output(struct sk_buff **pskb)
+static int esp6_output(struct sk_buff *skb)
 {
 	int err;
 	int hdr_len;
-	struct dst_entry *dst = (*pskb)->dst;
+	struct dst_entry *dst = skb->dst;
 	struct xfrm_state *x  = dst->xfrm;
 	struct ipv6hdr *top_iph;
 	struct ipv6_esp_hdr *esph;
@@ -54,17 +54,17 @@ int esp6_output(struct sk_buff **pskb)
 	int nfrags;
 
 	esp = x->data;
-	hdr_len = (*pskb)->h.raw - (*pskb)->data +
+	hdr_len = skb->h.raw - skb->data +
 		  sizeof(*esph) + esp->conf.ivlen;
 
 	/* Strip IP+ESP header. */
-	__skb_pull(*pskb, hdr_len);
+	__skb_pull(skb, hdr_len);
 
 	/* Now skb is pure payload to encrypt */
 	err = -ENOMEM;
 
 	/* Round to block size */
-	clen = (*pskb)->len;
+	clen = skb->len;
 
 	alen = esp->auth.icv_trunc_len;
 	tfm = esp->conf.tfm;
@@ -73,24 +73,24 @@ int esp6_output(struct sk_buff **pskb)
 	if (esp->conf.padlen)
 		clen = (clen + esp->conf.padlen-1)&~(esp->conf.padlen-1);
 
-	if ((nfrags = skb_cow_data(*pskb, clen-(*pskb)->len+alen, &trailer)) < 0) {
+	if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0) {
 		goto error;
 	}
 
 	/* Fill padding... */
 	do {
 		int i;
-		for (i=0; i<clen-(*pskb)->len - 2; i++)
+		for (i=0; i<clen-skb->len - 2; i++)
 			*(u8*)(trailer->tail + i) = i+1;
 	} while (0);
-	*(u8*)(trailer->tail + clen-(*pskb)->len - 2) = (clen - (*pskb)->len)-2;
-	pskb_put(*pskb, trailer, clen - (*pskb)->len);
+	*(u8*)(trailer->tail + clen-skb->len - 2) = (clen - skb->len)-2;
+	pskb_put(skb, trailer, clen - skb->len);
 
-	top_iph = (struct ipv6hdr *)__skb_push(*pskb, hdr_len);
-	esph = (struct ipv6_esp_hdr *)(*pskb)->h.raw;
-	top_iph->payload_len = htons((*pskb)->len + alen - sizeof(*top_iph));
-	*(u8*)(trailer->tail - 1) = *(*pskb)->nh.raw;
-	*(*pskb)->nh.raw = IPPROTO_ESP;
+	top_iph = (struct ipv6hdr *)__skb_push(skb, hdr_len);
+	esph = (struct ipv6_esp_hdr *)skb->h.raw;
+	top_iph->payload_len = htons(skb->len + alen - sizeof(*top_iph));
+	*(u8*)(trailer->tail - 1) = *skb->nh.raw;
+	*skb->nh.raw = IPPROTO_ESP;
 
 	esph->spi = x->id.spi;
 	esph->seq_no = htonl(++x->replay.oseq);
@@ -106,7 +106,7 @@ int esp6_output(struct sk_buff **pskb)
 			if (!sg)
 				goto error;
 		}
-		skb_to_sgvec(*pskb, sg, esph->enc_data+esp->conf.ivlen-(*pskb)->data, clen);
+		skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen);
 		crypto_cipher_encrypt(tfm, sg, sg, clen);
 		if (unlikely(sg != &esp->sgbuf[0]))
 			kfree(sg);
@@ -118,9 +118,9 @@ int esp6_output(struct sk_buff **pskb)
 	}
 
 	if (esp->auth.icv_full_len) {
-		esp->auth.icv(esp, *pskb, (u8*)esph-(*pskb)->data,
+		esp->auth.icv(esp, skb, (u8*)esph-skb->data,
 			sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen+clen, trailer->tail);
-		pskb_put(*pskb, trailer, alen);
+		pskb_put(skb, trailer, alen);
 	}
 
 	err = 0;
@@ -129,7 +129,7 @@ error:
 	return err;
 }
 
-int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
+static int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
 {
 	struct ipv6hdr *iph;
 	struct ipv6_esp_hdr *esph;
@@ -252,8 +252,8 @@ static u32 esp6_get_max_size(struct xfrm_state *x, int mtu)
 	return mtu + x->props.header_len + esp->auth.icv_full_len;
 }
 
-void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
-		int type, int code, int offset, __u32 info)
+static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+                     int type, int code, int offset, __u32 info)
 {
 	struct ipv6hdr *iph = (struct ipv6hdr*)skb->data;
 	struct ipv6_esp_hdr *esph = (struct ipv6_esp_hdr*)(skb->data+offset);
@@ -272,7 +272,7 @@ void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 	xfrm_state_put(x);
 }
 
-void esp6_destroy(struct xfrm_state *x)
+static void esp6_destroy(struct xfrm_state *x)
 {
 	struct esp_data *esp = x->data;
 
@@ -298,17 +298,21 @@ void esp6_destroy(struct xfrm_state *x)
 	kfree(esp);
 }
 
-int esp6_init_state(struct xfrm_state *x, void *args)
+static int esp6_init_state(struct xfrm_state *x, void *args)
 {
 	struct esp_data *esp = NULL;
 
+	/* null auth and encryption can have zero length keys */
 	if (x->aalg) {
-		if (x->aalg->alg_key_len == 0 || x->aalg->alg_key_len > 512)
+		if (x->aalg->alg_key_len > 512)
 			goto error;
 	}
 	if (x->ealg == NULL)
 		goto error;
 
+	if (x->encap)
+		goto error;
+
 	esp = kmalloc(sizeof(*esp), GFP_KERNEL);
 	if (esp == NULL)
 		return -ENOMEM;
@@ -398,7 +402,7 @@ static struct inet6_protocol esp6_protocol = {
 	.flags		=	INET6_PROTO_NOPOLICY,
 };
 
-int __init esp6_init(void)
+static int __init esp6_init(void)
 {
 	if (xfrm_register_type(&esp6_type, AF_INET6) < 0) {
 		printk(KERN_INFO "ipv6 esp init: can't add xfrm type\n");
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 464a3f4d6..2b78c840c 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -314,9 +314,11 @@ looped_back:
 	dst_release(xchg(&skb->dst, NULL));
 	ip6_route_input(skb);
 	if (skb->dst->error) {
+		skb_push(skb, skb->data - skb->nh.raw);
 		dst_input(skb);
 		return -1;
 	}
+
 	if (skb->dst->dev->flags&IFF_LOOPBACK) {
 		if (skb->nh.ipv6h->hop_limit <= 1) {
 			IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
@@ -329,6 +331,7 @@ looped_back:
 		goto looped_back;
 	}
 
+	skb_push(skb, skb->data - skb->nh.raw);
 	dst_input(skb);
 	return -1;
 }
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c
index 07151a6c3..6dda815c0 100644
--- a/net/ipv6/exthdrs_core.c
+++ b/net/ipv6/exthdrs_core.c
@@ -68,34 +68,35 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, int len
 	u8 nexthdr = *nexthdrp;
 
 	while (ipv6_ext_hdr(nexthdr)) {
-		struct ipv6_opt_hdr hdr;
+		struct ipv6_opt_hdr _hdr, *hp;
 		int hdrlen;
 
 		if (len < (int)sizeof(struct ipv6_opt_hdr))
 			return -1;
 		if (nexthdr == NEXTHDR_NONE)
 			return -1;
-		if (skb_copy_bits(skb, start, &hdr, sizeof(hdr)))
+		hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
+		if (hp == NULL)
 			BUG();
 		if (nexthdr == NEXTHDR_FRAGMENT) {
-			unsigned short frag_off;
-			if (skb_copy_bits(skb,
-					  start+offsetof(struct frag_hdr,
-							 frag_off),
-					  &frag_off,
-					  sizeof(frag_off))) {
+			unsigned short _frag_off, *fp;
+			fp = skb_header_pointer(skb,
+						start+offsetof(struct frag_hdr,
+							       frag_off),
+						sizeof(_frag_off),
+						&_frag_off);
+			if (fp == NULL)
 				return -1;
-			}
 
-			if (ntohs(frag_off) & ~0x7)
+			if (ntohs(*fp) & ~0x7)
 				break;
 			hdrlen = 8;
 		} else if (nexthdr == NEXTHDR_AUTH)
-			hdrlen = (hdr.hdrlen+2)<<2; 
+			hdrlen = (hp->hdrlen+2)<<2; 
 		else
-			hdrlen = ipv6_optlen(&hdr); 
+			hdrlen = ipv6_optlen(hp); 
 
-		nexthdr = hdr.nexthdr;
+		nexthdr = hp->nexthdr;
 		len -= hdrlen;
 		start += hdrlen;
 	}
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 4faafff32..26273c82f 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -139,10 +139,12 @@ static int is_ineligible(struct sk_buff *skb)
 	if (ptr < 0)
 		return 0;
 	if (nexthdr == IPPROTO_ICMPV6) {
-		u8 type;
-		if (skb_copy_bits(skb, ptr+offsetof(struct icmp6hdr, icmp6_type),
-				  &type, 1)
-		    || !(type & ICMPV6_INFOMSG_MASK))
+		u8 _type, *tp;
+		tp = skb_header_pointer(skb,
+			ptr+offsetof(struct icmp6hdr, icmp6_type),
+			sizeof(_type), &_type);
+		if (tp == NULL ||
+		    !(*tp & ICMPV6_INFOMSG_MASK))
 			return 1;
 	}
 	return 0;
@@ -200,12 +202,13 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type,
 
 static __inline__ int opt_unrec(struct sk_buff *skb, __u32 offset)
 {
-	u8 optval;
+	u8 _optval, *op;
 
 	offset += skb->nh.raw - skb->data;
-	if (skb_copy_bits(skb, offset, &optval, 1))
+	op = skb_header_pointer(skb, offset, sizeof(_optval), &_optval);
+	if (op == NULL)
 		return 1;
-	return (optval&0xC0) == 0x80;
+	return (*op & 0xC0) == 0x80;
 }
 
 int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct icmp6hdr *thdr, int len)
@@ -369,6 +372,8 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
 	err = ip6_dst_lookup(sk, &dst, &fl);
 	if (err)
 		goto out;
+	if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+		goto out_dst_release;
 
 	if (hlimit < 0) {
 		if (ipv6_addr_is_multicast(&fl.fl6_dst))
@@ -455,6 +460,8 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
 	err = ip6_dst_lookup(sk, &dst, &fl);
 	if (err)
 		goto out;
+	if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+		goto out_dst_release;
 
 	if (hlimit < 0) {
 		if (ipv6_addr_is_multicast(&fl.fl6_dst))
@@ -486,6 +493,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
 out_put: 
 	if (likely(idev != NULL))
 		in6_dev_put(idev);
+out_dst_release:
 	dst_release(dst);
 out: 
 	icmpv6_xmit_unlock();
@@ -530,8 +538,7 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info)
 	hash = nexthdr & (MAX_INET_PROTOS - 1);
 
 	rcu_read_lock();
-	ipprot = inet6_protos[hash];
-	smp_read_barrier_depends();
+	ipprot = rcu_dereference(inet6_protos[hash]);
 	if (ipprot && ipprot->err_handler)
 		ipprot->err_handler(skb, NULL, type, code, inner_offset, info);
 	rcu_read_unlock();
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 65a137241..1816b81ae 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -449,9 +449,10 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
 			 *	Same priority level
 			 */
 
-			if ((iter->rt6i_dev == rt->rt6i_dev) &&
-			    (ipv6_addr_cmp(&iter->rt6i_gateway,
-					   &rt->rt6i_gateway) == 0)) {
+			if (iter->rt6i_dev == rt->rt6i_dev &&
+			    iter->rt6i_idev == rt->rt6i_idev &&
+			    ipv6_addr_cmp(&iter->rt6i_gateway,
+					   &rt->rt6i_gateway) == 0) {
 				if (!(iter->rt6i_flags&RTF_EXPIRES))
 					return -EEXIST;
 				iter->rt6i_expires = rt->rt6i_expires;
@@ -514,7 +515,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh,
 	int err = -ENOMEM;
 
 	fn = fib6_add_1(root, &rt->rt6i_dst.addr, sizeof(struct in6_addr),
-			rt->rt6i_dst.plen, (u8*) &rt->rt6i_dst - (u8*) rt);
+			rt->rt6i_dst.plen, offsetof(struct rt6_info, rt6i_dst));
 
 	if (fn == NULL)
 		goto out;
@@ -550,7 +551,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh,
 
 			sn = fib6_add_1(sfn, &rt->rt6i_src.addr,
 					sizeof(struct in6_addr), rt->rt6i_src.plen,
-					(u8*) &rt->rt6i_src - (u8*) rt);
+					offsetof(struct rt6_info, rt6i_src));
 
 			if (sn == NULL) {
 				/* If it is failed, discard just allocated
@@ -571,7 +572,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh,
 		} else {
 			sn = fib6_add_1(fn->subtree, &rt->rt6i_src.addr,
 					sizeof(struct in6_addr), rt->rt6i_src.plen,
-					(u8*) &rt->rt6i_src - (u8*) rt);
+					offsetof(struct rt6_info, rt6i_src));
 
 			if (sn == NULL)
 				goto st_failure;
@@ -680,14 +681,13 @@ struct fib6_node * fib6_lookup(struct fib6_node *root, struct in6_addr *daddr,
 			       struct in6_addr *saddr)
 {
 	struct lookup_args args[2];
-	struct rt6_info *rt = NULL;
 	struct fib6_node *fn;
 
-	args[0].offset = (u8*) &rt->rt6i_dst - (u8*) rt;
+	args[0].offset = offsetof(struct rt6_info, rt6i_dst);
 	args[0].addr = daddr;
 
 #ifdef CONFIG_IPV6_SUBTREES
-	args[1].offset = (u8*) &rt->rt6i_src - (u8*) rt;
+	args[1].offset = offsetof(struct rt6_info, rt6i_src);
 	args[1].addr = saddr;
 #endif
 
@@ -739,11 +739,10 @@ struct fib6_node * fib6_locate(struct fib6_node *root,
 			       struct in6_addr *daddr, int dst_len,
 			       struct in6_addr *saddr, int src_len)
 {
-	struct rt6_info *rt = NULL;
 	struct fib6_node *fn;
 
 	fn = fib6_locate_1(root, daddr, dst_len,
-			   (u8*) &rt->rt6i_dst - (u8*) rt);
+			   offsetof(struct rt6_info, rt6i_dst));
 
 #ifdef CONFIG_IPV6_SUBTREES
 	if (src_len) {
@@ -752,7 +751,7 @@ struct fib6_node * fib6_locate(struct fib6_node *root,
 			fn = fn->subtree;
 		if (fn)
 			fn = fib6_locate_1(fn, saddr, src_len,
-					   (u8*) &rt->rt6i_src - (u8*) rt);
+					   offsetof(struct rt6_info, rt6i_src));
 	}
 #endif
 
@@ -1185,6 +1184,7 @@ static int fib6_age(struct rt6_info *rt, void *arg)
 	if (rt->rt6i_flags&RTF_EXPIRES && rt->rt6i_expires) {
 		if (time_after(now, rt->rt6i_expires)) {
 			RT6_TRACE("expiring %p\n", rt);
+			rt6_reset_dflt_pointer(rt);
 			return -1;
 		}
 		gc_args.more++;
@@ -1193,6 +1193,11 @@ static int fib6_age(struct rt6_info *rt, void *arg)
 		    time_after_eq(now, rt->u.dst.lastuse + gc_args.timeout)) {
 			RT6_TRACE("aging clone %p\n", rt);
 			return -1;
+		} else if ((rt->rt6i_flags & RTF_GATEWAY) &&
+			   (!(rt->rt6i_nexthop->flags & NTF_ROUTER))) {
+			RT6_TRACE("purging route %p via non-router but gateway\n",
+				  rt);
+			return -1;
 		}
 		gc_args.more++;
 	}
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 2c5aab089..15f341adc 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -538,7 +538,8 @@ release:
 
 		/* Do not check for fault */
 		if (!freq.flr_label)
-			copy_to_user(optval + ((u8*)&freq.flr_label - (u8*)&freq), &fl->label, sizeof(fl->label));
+			copy_to_user(&((struct in6_flowlabel_req __user *) optval)->flr_label,
+				     &fl->label, sizeof(fl->label));
 
 		sfl1->fl = fl;
 		sfl1->next = np->ipv6_fl_list;
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 9b9cee7c0..99436a59e 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -167,10 +167,9 @@ resubmit:
 		ipv6_raw_deliver(skb, nexthdr);
 
 	hash = nexthdr & (MAX_INET_PROTOS - 1);
-	if ((ipprot = inet6_protos[hash]) != NULL) {
+	if ((ipprot = rcu_dereference(inet6_protos[hash])) != NULL) {
 		int ret;
 		
-		smp_read_barrier_depends();
 		if (ipprot->flags & INET6_PROTO_FINAL) {
 			struct ipv6hdr *hdr;	
 
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 81eed71dd..33260cfac 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -54,6 +54,7 @@
 #include <net/rawv6.h>
 #include <net/icmp.h>
 #include <net/xfrm.h>
+#include <net/checksum.h>
 
 static int ip6_fragment(struct sk_buff **pskb, int (*output)(struct sk_buff**));
 
@@ -476,6 +477,7 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from)
 	/* Connection association is same as pre-frag packet */
 	to->nfct = from->nfct;
 	nf_conntrack_get(to->nfct);
+	to->nfctinfo = from->nfctinfo;
 #ifdef CONFIG_BRIDGE_NETFILTER
 	nf_bridge_put(to->nf_bridge);
 	to->nf_bridge = from->nf_bridge;
@@ -796,10 +798,6 @@ int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl)
 			goto out_err_release;
 		}
 	}
-	if ((err = xfrm_lookup(dst, fl, sk, 0)) < 0) {
-		err = -ENETUNREACH;
-		goto out_err_release;
-        }
 
 	return 0;
 
@@ -821,7 +819,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offse
 	int exthdrlen;
 	int hh_len;
 	int mtu;
-	int copy = 0;
+	int copy;
 	int err;
 	int offset = 0;
 	int csummode = CHECKSUM_NONE;
@@ -879,29 +877,79 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offse
 		}
 	}
 
+	/*
+	 * Let's try using as much space as possible.
+	 * Use MTU if total length of the message fits into the MTU.
+	 * Otherwise, we need to reserve fragment header and
+	 * fragment alignment (= 8-15 octects, in total).
+	 *
+	 * Note that we may need to "move" the data from the tail of
+	 * of the buffer to the new fragment when we split 
+	 * the message.
+	 *
+	 * FIXME: It may be fragmented into multiple chunks 
+	 *        at once if non-fragmentable extension headers
+	 *        are too large.
+	 * --yoshfuji 
+	 */
+
 	inet->cork.length += length;
 
 	if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)
 		goto alloc_new_skb;
 
 	while (length > 0) {
-		if ((copy = maxfraglen - skb->len) <= 0) {
+		/* Check if the remaining data fits into current packet. */
+		copy = mtu - skb->len;
+		if (copy < length)
+			copy = maxfraglen - skb->len;
+
+		if (copy <= 0) {
 			char *data;
 			unsigned int datalen;
 			unsigned int fraglen;
+			unsigned int fraggap;
 			unsigned int alloclen;
-			BUG_TRAP(copy == 0);
+			struct sk_buff *skb_prev;
 alloc_new_skb:
-			datalen = maxfraglen - fragheaderlen;
-			if (datalen > length)
-				datalen = length;
+			skb_prev = skb;
+
+			/* There's no room in the current skb */
+			if (skb_prev)
+				fraggap = skb_prev->len - maxfraglen;
+			else
+				fraggap = 0;
+
+			/*
+			 * If remaining data exceeds the mtu,
+			 * we know we need more fragment(s).
+			 */
+			datalen = length + fraggap;
+			if (datalen > mtu - fragheaderlen)
+				datalen = maxfraglen - fragheaderlen;
+
 			fraglen = datalen + fragheaderlen;
 			if ((flags & MSG_MORE) &&
 			    !(rt->u.dst.dev->features&NETIF_F_SG))
-				alloclen = maxfraglen;
+				alloclen = mtu;
 			else
-				alloclen = fraglen;
+				alloclen = datalen + fragheaderlen;
+
+			/*
+			 * The last fragment gets additional space at tail.
+			 * Note: we overallocate on fragments with MSG_MODE
+			 * because we have no idea if we're the last one.
+			 */
+			if (datalen == length + fraggap)
+				alloclen += rt->u.dst.trailer_len;
+
+			/*
+			 * We just reserve space for fragment header.
+			 * Note: this may be overallocation if the message 
+			 * (without MSG_MORE) fits into the MTU.
+			 */
 			alloclen += sizeof(struct frag_hdr);
+
 			if (transhdrlen) {
 				skb = sock_alloc_send_skb(sk,
 						alloclen + hh_len,
@@ -923,7 +971,7 @@ alloc_new_skb:
 			 */
 			skb->ip_summed = csummode;
 			skb->csum = 0;
-			/* reserve 8 byte for fragmentation */
+			/* reserve for fragmentation */
 			skb_reserve(skb, hh_len+sizeof(struct frag_hdr));
 
 			/*
@@ -933,15 +981,29 @@ alloc_new_skb:
 			skb->nh.raw = data + exthdrlen;
 			data += fragheaderlen;
 			skb->h.raw = data + exthdrlen;
-			copy = datalen - transhdrlen;
-			if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, 0, skb) < 0) {
+
+			if (fraggap) {
+				skb->csum = skb_copy_and_csum_bits(
+					skb_prev, maxfraglen,
+					data + transhdrlen, fraggap, 0);
+				skb_prev->csum = csum_sub(skb_prev->csum,
+							  skb->csum);
+				data += fraggap;
+				skb_trim(skb_prev, maxfraglen);
+			}
+			copy = datalen - transhdrlen - fraggap;
+			if (copy < 0) {
+				err = -EINVAL;
+				kfree_skb(skb);
+				goto error;
+			} else if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) {
 				err = -EFAULT;
 				kfree_skb(skb);
 				goto error;
 			}
 
 			offset += copy;
-			length -= datalen;
+			length -= datalen - fraggap;
 			transhdrlen = 0;
 			exthdrlen = 0;
 			csummode = CHECKSUM_NONE;
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 0c8db0391..c75dc343b 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -48,6 +48,8 @@
 #include <net/addrconf.h>
 #include <net/ip6_tunnel.h>
 #include <net/xfrm.h>
+#include <net/dsfield.h>
+#include <net/inet_ecn.h>
 
 MODULE_AUTHOR("Ville Nuorvala");
 MODULE_DESCRIPTION("IPv6-in-IPv6 tunnel");
@@ -490,6 +492,15 @@ out:
 	read_unlock(&ip6ip6_lock);
 }
 
+static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph,
+					  struct sk_buff *skb)
+{
+	struct ipv6hdr *inner_iph = skb->nh.ipv6h;
+
+	if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph)))
+		IP6_ECN_set_ce(inner_iph);
+}
+
 /**
  * ip6ip6_rcv - decapsulate IPv6 packet and retransmit it locally
  *   @skb: received socket buffer
@@ -531,6 +542,9 @@ ip6ip6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
 		skb->dev = t->dev;
 		dst_release(skb->dst);
 		skb->dst = NULL;
+		if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY)
+			ipv6_copy_dscp(ipv6h, skb->nh.ipv6h);
+		ip6ip6_ecn_decapsulate(ipv6h, skb);
 		t->stat.rx_packets++;
 		t->stat.rx_bytes += skb->len;
 		netif_rx(skb);
@@ -621,6 +635,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
 	u8 proto;
 	int err;
 	int pkt_len;
+	int dsfield;
 
 	if (t->recursion++) {
 		stats->collisions++;
@@ -646,6 +661,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
 	memcpy(&fl, &t->fl, sizeof (fl));
 	proto = fl.proto;
 
+	dsfield = ipv6_get_dsfield(ipv6h);
 	if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS))
 		fl.fl6_flowlabel |= (*(__u32 *) ipv6h & IPV6_TCLASS_MASK);
 	if ((t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL))
@@ -717,6 +733,8 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
 	skb->nh.raw = skb_push(skb, sizeof(struct ipv6hdr));
 	ipv6h = skb->nh.ipv6h;
 	*(u32*)ipv6h = fl.fl6_flowlabel | htonl(0x60000000);
+	dsfield = INET_ECN_encapsulate(0, dsfield);
+	ipv6_change_dsfield(ipv6h, ~INET_ECN_MASK, dsfield);
 	ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
 	ipv6h->hop_limit = t->parms.hop_limit;
 	ipv6h->nexthdr = proto;
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 04303769d..f3093f2cd 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -36,14 +36,31 @@
 #include <net/xfrm.h>
 #include <net/ipcomp.h>
 #include <asm/scatterlist.h>
+#include <asm/semaphore.h>
 #include <linux/crypto.h>
 #include <linux/pfkeyv2.h>
 #include <linux/random.h>
+#include <linux/percpu.h>
+#include <linux/smp.h>
+#include <linux/list.h>
+#include <linux/vmalloc.h>
+#include <linux/rtnetlink.h>
 #include <net/icmp.h>
 #include <net/ipv6.h>
 #include <linux/ipv6.h>
 #include <linux/icmpv6.h>
 
+struct ipcomp6_tfms {
+	struct list_head list;
+	struct crypto_tfm **tfms;
+	int users;
+};
+
+static DECLARE_MUTEX(ipcomp6_resource_sem);
+static void **ipcomp6_scratches;
+static int ipcomp6_scratch_users;
+static LIST_HEAD(ipcomp6_tfms_list);
+
 static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
 {
 	int err = 0;
@@ -53,7 +70,9 @@ static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, s
 	struct ipv6hdr *iph;
 	int plen, dlen;
 	struct ipcomp_data *ipcd = x->data;
-	u8 *start, *scratch = ipcd->scratch;
+	u8 *start, *scratch;
+	struct crypto_tfm *tfm;
+	int cpu;
 
 	if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
 		skb_linearize(skb, GFP_ATOMIC) != 0) {
@@ -82,20 +101,24 @@ static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, s
 	dlen = IPCOMP_SCRATCH_SIZE;
 	start = skb->data;
 
-	err = crypto_comp_decompress(ipcd->tfm, start, plen, scratch, &dlen);
+	cpu = get_cpu();
+	scratch = *per_cpu_ptr(ipcomp6_scratches, cpu);
+	tfm = *per_cpu_ptr(ipcd->tfms, cpu);
+
+	err = crypto_comp_decompress(tfm, start, plen, scratch, &dlen);
 	if (err) {
 		err = -EINVAL;
-		goto out;
+		goto out_put_cpu;
 	}
 
 	if (dlen < (plen + sizeof(struct ipv6_comp_hdr))) {
 		err = -EINVAL;
-		goto out;
+		goto out_put_cpu;
 	}
 
 	err = pskb_expand_head(skb, 0, dlen - plen, GFP_ATOMIC);
 	if (err) {
-		goto out;
+		goto out_put_cpu;
 	}
 
 	skb_put(skb, dlen - plen);
@@ -104,6 +127,8 @@ static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, s
 	iph = skb->nh.ipv6h;
 	iph->payload_len = htons(skb->len);
 	
+out_put_cpu:
+	put_cpu();
 out:
 	if (tmp_hdr)
 		kfree(tmp_hdr);
@@ -114,56 +139,65 @@ error_out:
 	return err;
 }
 
-static int ipcomp6_output(struct sk_buff **pskb)
+static int ipcomp6_output(struct sk_buff *skb)
 {
 	int err;
-	struct dst_entry *dst = (*pskb)->dst;
+	struct dst_entry *dst = skb->dst;
 	struct xfrm_state *x = dst->xfrm;
 	struct ipv6hdr *top_iph;
 	int hdr_len;
 	struct ipv6_comp_hdr *ipch;
 	struct ipcomp_data *ipcd = x->data;
 	int plen, dlen;
-	u8 *start, *scratch = ipcd->scratch;
+	u8 *start, *scratch;
+	struct crypto_tfm *tfm;
+	int cpu;
 
-	hdr_len = (*pskb)->h.raw - (*pskb)->data;
+	hdr_len = skb->h.raw - skb->data;
 
 	/* check whether datagram len is larger than threshold */
-	if (((*pskb)->len - hdr_len) < ipcd->threshold) {
+	if ((skb->len - hdr_len) < ipcd->threshold) {
 		goto out_ok;
 	}
 
-	if ((skb_is_nonlinear(*pskb) || skb_cloned(*pskb)) &&
-		skb_linearize(*pskb, GFP_ATOMIC) != 0) {
+	if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
+		skb_linearize(skb, GFP_ATOMIC) != 0) {
 		err = -ENOMEM;
 		goto error;
 	}
 
 	/* compression */
-	plen = (*pskb)->len - hdr_len;
+	plen = skb->len - hdr_len;
 	dlen = IPCOMP_SCRATCH_SIZE;
-	start = (*pskb)->h.raw;
+	start = skb->h.raw;
 
-	err = crypto_comp_compress(ipcd->tfm, start, plen, scratch, &dlen);
+	cpu = get_cpu();
+	scratch = *per_cpu_ptr(ipcomp6_scratches, cpu);
+	tfm = *per_cpu_ptr(ipcd->tfms, cpu);
+
+	err = crypto_comp_compress(tfm, start, plen, scratch, &dlen);
 	if (err) {
+		put_cpu();
 		goto error;
 	}
 	if ((dlen + sizeof(struct ipv6_comp_hdr)) >= plen) {
+		put_cpu();
 		goto out_ok;
 	}
 	memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen);
-	pskb_trim(*pskb, hdr_len + dlen + sizeof(struct ip_comp_hdr));
+	put_cpu();
+	pskb_trim(skb, hdr_len + dlen + sizeof(struct ip_comp_hdr));
 
 	/* insert ipcomp header and replace datagram */
-	top_iph = (struct ipv6hdr *)(*pskb)->data;
+	top_iph = (struct ipv6hdr *)skb->data;
 
-	top_iph->payload_len = htons((*pskb)->len - sizeof(struct ipv6hdr));
+	top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
 
 	ipch = (struct ipv6_comp_hdr *)start;
-	ipch->nexthdr = *(*pskb)->nh.raw;
+	ipch->nexthdr = *skb->nh.raw;
 	ipch->flags = 0;
 	ipch->cpi = htons((u16 )ntohl(x->id.spi));
-	*(*pskb)->nh.raw = IPPROTO_COMP;
+	*skb->nh.raw = IPPROTO_COMP;
 
 out_ok:
 	err = 0;
@@ -254,12 +288,132 @@ out:
 	return err;
 }
 
+static void ipcomp6_free_scratches(void)
+{
+	int i;
+	void **scratches;
+
+	if (--ipcomp6_scratch_users)
+		return;
+
+	scratches = ipcomp6_scratches;
+	if (!scratches)
+		return;
+
+	for_each_cpu(i) {
+		void *scratch = *per_cpu_ptr(scratches, i);
+		if (scratch)
+			vfree(scratch);
+	}
+
+	free_percpu(scratches);
+}
+
+static void **ipcomp6_alloc_scratches(void)
+{
+	int i;
+	void **scratches;
+
+	if (ipcomp6_scratch_users++)
+		return ipcomp6_scratches;
+
+	scratches = alloc_percpu(void *);
+	if (!scratches)
+		return NULL;
+
+	ipcomp6_scratches = scratches;
+
+	for_each_cpu(i) {
+		void *scratch = vmalloc(IPCOMP_SCRATCH_SIZE);
+		if (!scratch)
+			return NULL;
+		*per_cpu_ptr(scratches, i) = scratch;
+	}
+
+	return scratches;
+}
+
+static void ipcomp6_free_tfms(struct crypto_tfm **tfms)
+{
+	struct ipcomp6_tfms *pos;
+	int cpu;
+
+	list_for_each_entry(pos, &ipcomp6_tfms_list, list) {
+		if (pos->tfms == tfms)
+			break;
+	}
+
+	BUG_TRAP(pos);
+
+	if (--pos->users)
+		return;
+
+	list_del(&pos->list);
+	kfree(pos);
+
+	if (!tfms)
+		return;
+
+	for_each_cpu(cpu) {
+		struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu);
+		if (tfm)
+			crypto_free_tfm(tfm);
+	}
+	free_percpu(tfms);
+}
+
+static struct crypto_tfm **ipcomp6_alloc_tfms(const char *alg_name)
+{
+	struct ipcomp6_tfms *pos;
+	struct crypto_tfm **tfms;
+	int cpu;
+
+	/* This can be any valid CPU ID so we don't need locking. */
+	cpu = smp_processor_id();
+
+	list_for_each_entry(pos, &ipcomp6_tfms_list, list) {
+		struct crypto_tfm *tfm;
+
+		tfms = pos->tfms;
+		tfm = *per_cpu_ptr(tfms, cpu);
+
+		if (!strcmp(crypto_tfm_alg_name(tfm), alg_name)) {
+			pos->users++;
+			return tfms;
+		}
+	}
+
+	pos = kmalloc(sizeof(*pos), GFP_KERNEL);
+	if (!pos)
+		return NULL;
+
+	pos->users = 1;
+	INIT_LIST_HEAD(&pos->list);
+	list_add(&pos->list, &ipcomp6_tfms_list);
+
+	pos->tfms = tfms = alloc_percpu(struct crypto_tfm *);
+	if (!tfms)
+		goto error;
+
+	for_each_cpu(cpu) {
+		struct crypto_tfm *tfm = crypto_alloc_tfm(alg_name, 0);
+		if (!tfm)
+			goto error;
+		*per_cpu_ptr(tfms, cpu) = tfm;
+	}
+
+	return tfms;
+
+error:
+	ipcomp6_free_tfms(tfms);
+	return NULL;
+}
+
 static void ipcomp6_free_data(struct ipcomp_data *ipcd)
 {
-	if (ipcd->tfm)
-		crypto_free_tfm(ipcd->tfm);
-	if (ipcd->scratch)
-		kfree(ipcd->scratch);
+	if (ipcd->tfms)
+		ipcomp6_free_tfms(ipcd->tfms);
+	ipcomp6_free_scratches();
 }
 
 static void ipcomp6_destroy(struct xfrm_state *x)
@@ -268,7 +422,9 @@ static void ipcomp6_destroy(struct xfrm_state *x)
 	if (!ipcd)
 		return;
 	xfrm_state_delete_tunnel(x);
+	down(&ipcomp6_resource_sem);
 	ipcomp6_free_data(ipcd);
+	up(&ipcomp6_resource_sem);
 	kfree(ipcd);
 
 	xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr);
@@ -284,28 +440,32 @@ static int ipcomp6_init_state(struct xfrm_state *x, void *args)
 	if (!x->calg)
 		goto out;
 
+	if (x->encap)
+		goto out;
+
 	err = -ENOMEM;
 	ipcd = kmalloc(sizeof(*ipcd), GFP_KERNEL);
 	if (!ipcd)
-		goto error;
+		goto out;
 
 	memset(ipcd, 0, sizeof(*ipcd));
 	x->props.header_len = 0;
 	if (x->props.mode)
 		x->props.header_len += sizeof(struct ipv6hdr);
 	
-	ipcd->scratch = kmalloc(IPCOMP_SCRATCH_SIZE, GFP_KERNEL);
-	if (!ipcd->scratch)
+	down(&ipcomp6_resource_sem);
+	if (!ipcomp6_alloc_scratches())
 		goto error;
 
-	ipcd->tfm = crypto_alloc_tfm(x->calg->alg_name, 0);
-	if (!ipcd->tfm)
+	ipcd->tfms = ipcomp6_alloc_tfms(x->calg->alg_name);
+	if (!ipcd->tfms)
 		goto error;
+	up(&ipcomp6_resource_sem);
 
 	if (x->props.mode) {
 		err = ipcomp6_tunnel_attach(x);
 		if (err)
-			goto error;
+			goto error_tunnel;
 	}
 
 	calg_desc = xfrm_calg_get_byname(x->calg->alg_name);
@@ -315,11 +475,12 @@ static int ipcomp6_init_state(struct xfrm_state *x, void *args)
 	err = 0;
 out:
 	return err;
+error_tunnel:
+	down(&ipcomp6_resource_sem);
 error:
-	if (ipcd) {
-		ipcomp6_free_data(ipcd);
-		kfree(ipcd);
-	}
+	ipcomp6_free_data(ipcd);
+	up(&ipcomp6_resource_sem);
+	kfree(ipcd);
 
 	goto out;
 }
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 893fe4081..51193e0f0 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -128,6 +128,8 @@ static rwlock_t ipv6_sk_mc_lock = RW_LOCK_UNLOCKED;
 
 static struct socket *igmp6_socket;
 
+int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr);
+
 static void igmp6_join_group(struct ifmcaddr6 *ma);
 static void igmp6_leave_group(struct ifmcaddr6 *ma);
 static void igmp6_timer_handler(unsigned long data);
@@ -256,9 +258,9 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
 
 				if (idev) {
 					(void) ip6_mc_leave_src(sk,mc_lst,idev);
+					__ipv6_dev_mc_dec(idev, &mc_lst->addr);
 					in6_dev_put(idev);
 				}
-				ipv6_dev_mc_dec(dev, &mc_lst->addr);
 				dev_put(dev);
 			}
 			sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
@@ -322,9 +324,9 @@ void ipv6_sock_mc_close(struct sock *sk)
 
 			if (idev) {
 				(void) ip6_mc_leave_src(sk, mc_lst, idev);
+				__ipv6_dev_mc_dec(idev, &mc_lst->addr);
 				in6_dev_put(idev);
 			}
-			ipv6_dev_mc_dec(dev, &mc_lst->addr);
 			dev_put(dev);
 		}
 
@@ -870,7 +872,7 @@ int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr)
 /*
  *	device multicast group del
  */
-static int __ipv6_dev_mc_dec(struct net_device *dev, struct inet6_dev *idev, struct in6_addr *addr)
+int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr)
 {
 	struct ifmcaddr6 *ma, **map;
 
@@ -903,7 +905,7 @@ int ipv6_dev_mc_dec(struct net_device *dev, struct in6_addr *addr)
 	if (!idev)
 		return -ENODEV;
 
-	err = __ipv6_dev_mc_dec(dev, idev, addr);
+	err = __ipv6_dev_mc_dec(idev, addr);
 
 	in6_dev_put(idev);
 
@@ -2108,7 +2110,12 @@ void ipv6_mc_destroy_dev(struct inet6_dev *idev)
 	 * addrconf.c has NULL'd out dev->ip6_ptr so in6_dev_get() will
 	 * fail.
 	 */
-	__ipv6_dev_mc_dec(idev->dev, idev, &maddr);
+	__ipv6_dev_mc_dec(idev, &maddr);
+
+	if (idev->cnf.forwarding) {
+		ipv6_addr_all_routers(&maddr);
+		__ipv6_dev_mc_dec(idev, &maddr);
+	}
 
 	write_lock_bh(&idev->lock);
 	while ((i = idev->mc_list) != NULL) {
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index b278e5a04..685a02d2e 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -58,6 +58,7 @@
 #include <linux/in6.h>
 #include <linux/route.h>
 #include <linux/init.h>
+#include <linux/rcupdate.h>
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
 #endif
@@ -65,6 +66,7 @@
 #include <linux/if_arp.h>
 #include <linux/ipv6.h>
 #include <linux/icmpv6.h>
+#include <linux/jhash.h>
 
 #include <net/sock.h>
 #include <net/snmp.h>
@@ -269,29 +271,35 @@ int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int d
 
 static u32 ndisc_hash(const void *pkey, const struct net_device *dev)
 {
-	u32 hash_val;
+	const u32 *p32 = pkey;
+	u32 addr_hash, i;
 
-	hash_val = *(u32*)(pkey + sizeof(struct in6_addr) - 4);
-	hash_val ^= (hash_val>>16);
-	hash_val ^= hash_val>>8;
-	hash_val ^= hash_val>>3;
-	hash_val = (hash_val^dev->ifindex)&NEIGH_HASHMASK;
+	addr_hash = 0;
+	for (i = 0; i < (sizeof(struct in6_addr) / sizeof(u32)); i++)
+		addr_hash ^= *p32++;
 
-	return hash_val;
+	return jhash_2words(addr_hash, dev->ifindex, nd_tbl.hash_rnd);
 }
 
 static int ndisc_constructor(struct neighbour *neigh)
 {
 	struct in6_addr *addr = (struct in6_addr*)&neigh->primary_key;
 	struct net_device *dev = neigh->dev;
-	struct inet6_dev *in6_dev = in6_dev_get(dev);
+	struct inet6_dev *in6_dev;
+	struct neigh_parms *parms;
 	int is_multicast = ipv6_addr_is_multicast(addr);
 
-	if (in6_dev == NULL)
+	rcu_read_lock();
+	in6_dev = in6_dev_get(dev);
+	if (in6_dev == NULL) {
+		rcu_read_unlock();
 		return -EINVAL;
+	}
 
-	if (in6_dev->nd_parms)
-		neigh->parms = in6_dev->nd_parms;
+	parms = in6_dev->nd_parms;
+	__neigh_parms_put(neigh->parms);
+	neigh->parms = neigh_parms_clone(parms);
+	rcu_read_unlock();
 
 	neigh->type = is_multicast ? RTN_MULTICAST : RTN_UNICAST;
 	if (dev->hard_header == NULL) {
@@ -794,16 +802,20 @@ static void ndisc_recv_ns(struct sk_buff *skb)
 	}
 
 	if (inc)
-		nd_tbl.stats.rcv_probes_mcast++;
+		NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_mcast);
 	else
-		nd_tbl.stats.rcv_probes_ucast++;
+		NEIGH_CACHE_STAT_INC(&nd_tbl, rcv_probes_ucast);
 
 	/* 
 	 *	update / create cache entry
 	 *	for the source address
 	 */
-	neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, dev);
-
+	neigh = __neigh_lookup(&nd_tbl, saddr, dev,
+			       !inc || lladdr || !dev->addr_len);
+	if (neigh)
+		neigh_update(neigh, lladdr, NUD_STALE, 
+			     NEIGH_UPDATE_F_WEAK_OVERRIDE|
+			     NEIGH_UPDATE_F_OVERRIDE);
 	if (neigh || !dev->hard_header) {
 		ndisc_send_na(dev, neigh, saddr, &msg->target,
 			      idev->cnf.forwarding, 
@@ -886,24 +898,25 @@ static void ndisc_recv_na(struct sk_buff *skb)
 	neigh = neigh_lookup(&nd_tbl, &msg->target, dev);
 
 	if (neigh) {
-		if (neigh->flags & NTF_ROUTER) {
-			if (msg->icmph.icmp6_router == 0) {
-				/*
-				 *	Change: router to host
-				 */
-				struct rt6_info *rt;
-				rt = rt6_get_dflt_router(saddr, dev);
-				if (rt)
-					ip6_del_rt(rt, NULL, NULL);
-			}
-		} else {
-			if (msg->icmph.icmp6_router)
-				neigh->flags |= NTF_ROUTER;
-		}
+		u8 old_flags = neigh->flags;
 
 		neigh_update(neigh, lladdr,
 			     msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE,
-			     msg->icmph.icmp6_override, 1);
+			     NEIGH_UPDATE_F_WEAK_OVERRIDE|
+			     (msg->icmph.icmp6_override ? NEIGH_UPDATE_F_OVERRIDE : 0)|
+			     NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
+			     (msg->icmph.icmp6_router ? NEIGH_UPDATE_F_ISROUTER : 0));
+
+		if ((old_flags & ~neigh->flags) & NTF_ROUTER) {
+			/*
+			 * Change: router to host
+			 */
+			struct rt6_info *rt;
+			rt = rt6_get_dflt_router(saddr, dev);
+			if (rt)
+				ip6_del_rt(rt, NULL, NULL);
+		}
+
 		neigh_release(neigh);
 	}
 }
@@ -1071,7 +1084,11 @@ static void ndisc_router_discovery(struct sk_buff *skb)
 				goto out;
 			}
 		}
-		neigh_update(neigh, lladdr, NUD_STALE, 1, 1);
+		neigh_update(neigh, lladdr, NUD_STALE,
+			     NEIGH_UPDATE_F_WEAK_OVERRIDE|
+			     NEIGH_UPDATE_F_OVERRIDE|
+			     NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
+			     NEIGH_UPDATE_F_ISROUTER);
 	}
 
 	if (ndopts.nd_opts_pi) {
@@ -1188,19 +1205,11 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
 			return;
 		}
 	}
-	/* passed validation tests */
-
-	/*
-	   We install redirect only if nexthop state is valid.
-	 */
 
 	neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1);
 	if (neigh) {
-		neigh_update(neigh, lladdr, NUD_STALE, 1, 1);
-		if (neigh->nud_state&NUD_VALID)
-			rt6_redirect(dest, &skb->nh.ipv6h->saddr, neigh, on_link);
-		else
-			__neigh_event_send(neigh, NULL);
+		rt6_redirect(dest, &skb->nh.ipv6h->saddr, neigh, lladdr, 
+			     on_link);
 		neigh_release(neigh);
 	}
 	in6_dev_put(in6_dev);
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 0e212f21e..20f66572f 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -158,6 +158,15 @@ config IP6_NF_MATCH_EUI64
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config IP6_NF_MATCH_PHYSDEV
+	tristate "Physdev match support"
+	depends on IP6_NF_IPTABLES && BRIDGE_NETFILTER
+	help
+	  Physdev packet matching matches against the physical bridge ports
+	  the IP packet arrived on or will leave by.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 #  dep_tristate '  Multiple port match support' CONFIG_IP6_NF_MATCH_MULTIPORT $CONFIG_IP6_NF_IPTABLES
 #  dep_tristate '  TOS match support' CONFIG_IP6_NF_MATCH_TOS $CONFIG_IP6_NF_IPTABLES
 #  if [ "$CONFIG_IP6_NF_CONNTRACK" != "n" ]; then
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index d7687eb0e..2e5171495 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o
 obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
 obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
 obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
+obj-$(CONFIG_IP6_NF_MATCH_PHYSDEV) += ip6t_physdev.o
 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
 obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index d2ce00d81..0cef15b86 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -66,6 +66,7 @@ do {								\
 #endif
 #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
 
+static DECLARE_MUTEX(ip6t_mutex);
 
 /* Must have mutex */
 #define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0)
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index bb8590bdd..0fc6b1750 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -11,6 +11,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/skbuff.h>
 #include <linux/ip.h>
 #include <linux/spinlock.h>
@@ -26,7 +27,7 @@ MODULE_DESCRIPTION("IP6 tables LOG target module");
 MODULE_LICENSE("GPL");
 
 static unsigned int nflog = 1;
-MODULE_PARM(nflog, "i");
+module_param(nflog, int, 0400);
 MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
  
 struct in_device;
@@ -60,7 +61,7 @@ static u_int8_t ip6_nexthdr(u_int8_t currenthdr, u_int8_t **hdrptr)
 		repeatedly...with a large stick...no, an even LARGER
 		stick...no, you're still not thinking big enough */
 			nexthdr = **hdrptr;
-			hdrlen = *hdrptr[1] * 4 + 8;
+			hdrlen = (*hdrptr)[1] * 4 + 8;
 			*hdrptr = *hdrptr + hdrlen;
 			break;
 		/*stupid rfc2402 */
@@ -68,7 +69,7 @@ static u_int8_t ip6_nexthdr(u_int8_t currenthdr, u_int8_t **hdrptr)
 		case IPPROTO_ROUTING:
 		case IPPROTO_HOPOPTS:
 			nexthdr = **hdrptr;
-			hdrlen = *hdrptr[1] * 8 + 8;
+			hdrlen = (*hdrptr)[1] * 8 + 8;
 			*hdrptr = *hdrptr + hdrlen;
 			break;
 		case IPPROTO_FRAGMENT:
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c
index b6199f25a..3b1340d26 100644
--- a/net/ipv6/netfilter/ip6t_eui64.c
+++ b/net/ipv6/netfilter/ip6t_eui64.c
@@ -41,10 +41,10 @@ match(const struct sk_buff *skb,
     
     memset(eui64, 0, sizeof(eui64));
 
-    if (skb->mac.ethernet->h_proto == ntohs(ETH_P_IPV6)) {
+    if (eth_hdr(skb)->h_proto == ntohs(ETH_P_IPV6)) {
       if (skb->nh.ipv6h->version == 0x6) { 
-         memcpy(eui64, skb->mac.ethernet->h_source, 3);
-         memcpy(eui64 + 5, skb->mac.ethernet->h_source + 3, 3);
+         memcpy(eui64, eth_hdr(skb)->h_source, 3);
+         memcpy(eui64 + 5, eth_hdr(skb)->h_source + 3, 3);
 	 eui64[3]=0xff;
 	 eui64[4]=0xfe;
 	 eui64[0] |= 0x02;
diff --git a/net/ipv6/netfilter/ip6t_mac.c b/net/ipv6/netfilter/ip6t_mac.c
index 4d184e4a9..ea874dd24 100644
--- a/net/ipv6/netfilter/ip6t_mac.c
+++ b/net/ipv6/netfilter/ip6t_mac.c
@@ -35,7 +35,7 @@ match(const struct sk_buff *skb,
     return (skb->mac.raw >= skb->head
 	    && (skb->mac.raw + ETH_HLEN) <= skb->data
 	    /* If so, compare... */
-	    && ((memcmp(skb->mac.ethernet->h_source, info->srcaddr, ETH_ALEN)
+	    && ((memcmp(eth_hdr(skb)->h_source, info->srcaddr, ETH_ALEN)
 		== 0) ^ info->invert));
 }
 
diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c
index 272257b3b..f2b6d1f21 100644
--- a/net/ipv6/netfilter/ip6t_owner.c
+++ b/net/ipv6/netfilter/ip6t_owner.c
@@ -28,7 +28,7 @@ match_pid(const struct sk_buff *skb, pid_t pid)
 	int i;
 
 	read_lock(&tasklist_lock);
-	p = find_task_by_pid(pid);
+	p = find_task_by_real_pid(pid);
 	if (!p)
 		goto out;
 	task_lock(p);
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index 46daa7905..aca6d21cc 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -10,6 +10,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
 
 MODULE_LICENSE("GPL");
@@ -156,7 +157,7 @@ static struct nf_hook_ops ip6t_ops[] = {
 
 /* Default to forward because I got too much mail already. */
 static int forward = NF_ACCEPT;
-MODULE_PARM(forward, "i");
+module_param(forward, bool, 0000);
 
 static int __init init(void)
 {
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 031989611..c73d72011 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -555,12 +555,58 @@ error:
 	IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS);
 	return err; 
 }
+
+static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
+{
+	struct iovec *iov;
+	u8 __user *type = NULL;
+	u8 __user *code = NULL;
+	int probed = 0;
+	int i;
+
+	if (!msg->msg_iov)
+		return;
+
+	for (i = 0; i < msg->msg_iovlen; i++) {
+		iov = &msg->msg_iov[i];
+		if (!iov)
+			continue;
+
+		switch (fl->proto) {
+		case IPPROTO_ICMPV6:
+			/* check if one-byte field is readable or not. */
+			if (iov->iov_base && iov->iov_len < 1)
+				break;
+
+			if (!type) {
+				type = iov->iov_base;
+				/* check if code field is readable or not. */
+				if (iov->iov_len > 1)
+					code = type + 1;
+			} else if (!code)
+				code = iov->iov_base;
+
+			if (type && code) {
+				get_user(fl->fl_icmp_type, type);
+				__get_user(fl->fl_icmp_code, code);
+				probed = 1;
+			}
+			break;
+		default:
+			probed = 1;
+			break;
+		}
+		if (probed)
+			break;
+	}
+}
+
 static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
 		   struct msghdr *msg, size_t len)
 {
 	struct ipv6_txoptions opt_space;
 	struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name;
-	struct in6_addr *daddr;
+	struct in6_addr *daddr, *final_p = NULL, final;
 	struct inet_opt *inet = inet_sk(sk);
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct raw6_opt *raw_opt = raw6_sk(sk);
@@ -674,6 +720,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
 		opt = fl6_merge_options(&opt_space, flowlabel, opt);
 
 	fl.proto = proto;
+	rawv6_probe_proto_opt(&fl, msg);
+ 
 	ipv6_addr_copy(&fl.fl6_dst, daddr);
 	if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
 		ipv6_addr_copy(&fl.fl6_src, &np->saddr);
@@ -681,7 +729,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
 	/* merge ip6_build_xmit from ip6_output */
 	if (opt && opt->srcrt) {
 		struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
+		ipv6_addr_copy(&final, &fl.fl6_dst);
 		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+		final_p = &final;
 	}
 
 	if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
@@ -690,6 +740,13 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
 	err = ip6_dst_lookup(sk, &dst, &fl);
 	if (err)
 		goto out;
+	if (final_p)
+		ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+	if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+		dst_release(dst);
+		goto out;
+	}
 
 	if (hlimit < 0) {
 		if (ipv6_addr_is_multicast(&fl.fl6_dst))
@@ -932,6 +989,7 @@ struct proto rawv6_prot = {
 	.backlog_rcv =	rawv6_rcv_skb,
 	.hash =		raw_v6_hash,
 	.unhash =	raw_v6_unhash,
+	.slab_obj_size = sizeof(struct raw6_sock),
 };
 
 #ifdef CONFIG_PROC_FS
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 836d2ae84..7dac574b5 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -195,14 +195,18 @@ static void ip6_frag_secret_rebuild(unsigned long dummy)
 atomic_t ip6_frag_mem = ATOMIC_INIT(0);
 
 /* Memory Tracking Functions. */
-static inline void frag_kfree_skb(struct sk_buff *skb)
+static inline void frag_kfree_skb(struct sk_buff *skb, int *work)
 {
+	if (work)
+		*work -= skb->truesize;
 	atomic_sub(skb->truesize, &ip6_frag_mem);
 	kfree_skb(skb);
 }
 
-static inline void frag_free_queue(struct frag_queue *fq)
+static inline void frag_free_queue(struct frag_queue *fq, int *work)
 {
+	if (work)
+		*work -= sizeof(struct frag_queue);
 	atomic_sub(sizeof(struct frag_queue), &ip6_frag_mem);
 	kfree(fq);
 }
@@ -220,7 +224,7 @@ static inline struct frag_queue *frag_alloc_queue(void)
 /* Destruction primitives. */
 
 /* Complete destruction of fq. */
-static void ip6_frag_destroy(struct frag_queue *fq)
+static void ip6_frag_destroy(struct frag_queue *fq, int *work)
 {
 	struct sk_buff *fp;
 
@@ -232,17 +236,17 @@ static void ip6_frag_destroy(struct frag_queue *fq)
 	while (fp) {
 		struct sk_buff *xp = fp->next;
 
-		frag_kfree_skb(fp);
+		frag_kfree_skb(fp, work);
 		fp = xp;
 	}
 
-	frag_free_queue(fq);
+	frag_free_queue(fq, work);
 }
 
-static __inline__ void fq_put(struct frag_queue *fq)
+static __inline__ void fq_put(struct frag_queue *fq, int *work)
 {
 	if (atomic_dec_and_test(&fq->refcnt))
-		ip6_frag_destroy(fq);
+		ip6_frag_destroy(fq, work);
 }
 
 /* Kill fq entry. It is not destroyed immediately,
@@ -264,10 +268,13 @@ static void ip6_evictor(void)
 {
 	struct frag_queue *fq;
 	struct list_head *tmp;
+	int work;
 
-	for(;;) {
-		if (atomic_read(&ip6_frag_mem) <= sysctl_ip6frag_low_thresh)
-			return;
+	work = atomic_read(&ip6_frag_mem) - sysctl_ip6frag_low_thresh;
+	if (work <= 0)
+		return;
+
+	while(work > 0) {
 		read_lock(&ip6_frag_lock);
 		if (list_empty(&ip6_frag_lru_list)) {
 			read_unlock(&ip6_frag_lock);
@@ -283,7 +290,7 @@ static void ip6_evictor(void)
 			fq_kill(fq);
 		spin_unlock(&fq->lock);
 
-		fq_put(fq);
+		fq_put(fq, &work);
 		IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
 	}
 }
@@ -320,7 +327,7 @@ static void ip6_frag_expire(unsigned long data)
 	}
 out:
 	spin_unlock(&fq->lock);
-	fq_put(fq);
+	fq_put(fq, NULL);
 }
 
 /* Creation primitives. */
@@ -340,7 +347,7 @@ static struct frag_queue *ip6_frag_intern(unsigned int hash,
 			atomic_inc(&fq->refcnt);
 			write_unlock(&ip6_frag_lock);
 			fq_in->last_in |= COMPLETE;
-			fq_put(fq_in);
+			fq_put(fq_in, NULL);
 			return fq;
 		}
 	}
@@ -539,7 +546,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
 				fq->fragments = next;
 
 			fq->meat -= free_it->len;
-			frag_kfree_skb(free_it);
+			frag_kfree_skb(free_it, NULL);
 		}
 	}
 
@@ -658,7 +665,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
 	head->next = NULL;
 	head->dev = dev;
 	head->stamp = fq->stamp;
-	head->nh.ipv6h->payload_len = ntohs(payload_len);
+	head->nh.ipv6h->payload_len = htons(payload_len);
 
 	*skb_in = head;
 
@@ -734,7 +741,7 @@ static int ipv6_frag_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
 			ret = ip6_frag_reasm(fq, skbp, nhoffp, dev);
 
 		spin_unlock(&fq->lock);
-		fq_put(fq);
+		fq_put(fq, NULL);
 		return ret;
 	}
 
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 2017c69dc..83dc09908 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -155,7 +155,16 @@ static void ip6_dst_destroy(struct dst_entry *dst)
 
 static void ip6_dst_ifdown(struct dst_entry *dst, int how)
 {
-	ip6_dst_destroy(dst);
+	struct rt6_info *rt = (struct rt6_info *)dst;
+	struct inet6_dev *idev = rt->rt6i_idev;
+
+	if (idev != NULL && idev->dev != &loopback_dev) {
+		struct inet6_dev *loopback_idev = in6_dev_get(&loopback_dev);
+		if (loopback_idev != NULL) {
+			rt->rt6i_idev = loopback_idev;
+			in6_dev_put(idev);
+		}
+	}
 }
 
 /*
@@ -174,8 +183,17 @@ static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt,
 			struct net_device *dev = sprt->rt6i_dev;
 			if (dev->ifindex == oif)
 				return sprt;
-			if (dev->flags&IFF_LOOPBACK)
+			if (dev->flags & IFF_LOOPBACK) {
+				if (sprt->rt6i_idev == NULL ||
+				    sprt->rt6i_idev->dev->ifindex != oif) {
+					if (strict && oif)
+						continue;
+					if (local && (!oif || 
+						      local->rt6i_idev->dev->ifindex == oif))
+						continue;
+				}
 				local = sprt;
+			}
 		}
 
 		if (local)
@@ -190,8 +208,18 @@ static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt,
 /*
  *	pointer to the last default router chosen. BH is disabled locally.
  */
-static struct rt6_info *rt6_dflt_pointer;
-static spinlock_t rt6_dflt_lock = SPIN_LOCK_UNLOCKED;
+struct rt6_info *rt6_dflt_pointer;
+spinlock_t rt6_dflt_lock = SPIN_LOCK_UNLOCKED;
+
+void rt6_reset_dflt_pointer(struct rt6_info *rt)
+{
+	spin_lock_bh(&rt6_dflt_lock);
+	if (rt == NULL || rt == rt6_dflt_pointer) {
+		RT6_TRACE("reset default router: %p->NULL\n", rt6_dflt_pointer);
+		rt6_dflt_pointer = NULL;
+	}
+	spin_unlock_bh(&rt6_dflt_lock);
+}
 
 /* Default Router Selection (RFC 2461 6.3.6) */
 static struct rt6_info *rt6_best_dflt(struct rt6_info *rt, int oif)
@@ -209,6 +237,10 @@ static struct rt6_info *rt6_best_dflt(struct rt6_info *rt, int oif)
 		     sprt->rt6i_dev->ifindex == oif))
 			m += 8;
 
+		if ((sprt->rt6i_flags & RTF_EXPIRES) &&
+		    time_after(jiffies, sprt->rt6i_expires))
+			continue;
+
 		if (sprt == rt6_dflt_pointer)
 			m += 4;
 
@@ -336,13 +368,13 @@ struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr,
 	return NULL;
 }
 
-/* rt6_ins is called with FREE rt6_lock.
+/* ip6_ins_rt is called with FREE rt6_lock.
    It takes new route entry, the addition fails by any reason the
    route is freed. In any case, if caller does not hold it, it may
    be destroyed.
  */
 
-static int rt6_ins(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
+int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
 {
 	int err;
 
@@ -390,7 +422,7 @@ static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr,
 
 		dst_hold(&rt->u.dst);
 
-		err = rt6_ins(rt, NULL, NULL);
+		err = ip6_ins_rt(rt, NULL, NULL);
 		if (err == 0)
 			return rt;
 
@@ -608,8 +640,13 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
 				  struct in6_addr *addr,
 				  int (*output)(struct sk_buff **))
 {
-	struct rt6_info *rt = ip6_dst_alloc();
+	struct rt6_info *rt;
+	struct inet6_dev *idev = in6_dev_get(dev);
+
+	if (unlikely(idev == NULL))
+		return NULL;
 
+	rt = ip6_dst_alloc();
 	if (unlikely(rt == NULL))
 		goto out;
 
@@ -620,7 +657,7 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
 		neigh = ndisc_get_neigh(dev, addr);
 
 	rt->rt6i_dev	  = dev;
-	rt->rt6i_idev     = in6_dev_get(dev);
+	rt->rt6i_idev     = idev;
 	rt->rt6i_nexthop  = neigh;
 	atomic_set(&rt->u.dst.__refcnt, 1);
 	rt->u.dst.metrics[RTAX_HOPLIMIT-1] = 255;
@@ -731,8 +768,9 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
 	int err;
 	struct rtmsg *r;
 	struct rtattr **rta;
-	struct rt6_info *rt;
+	struct rt6_info *rt = NULL;
 	struct net_device *dev = NULL;
+	struct inet6_dev *idev = NULL;
 	int addr_type;
 
 	rta = (struct rtattr **) _rtattr;
@@ -744,9 +782,13 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
 		return -EINVAL;
 #endif
 	if (rtmsg->rtmsg_ifindex) {
+		err = -ENODEV;
 		dev = dev_get_by_index(rtmsg->rtmsg_ifindex);
 		if (!dev)
-			return -ENODEV;
+			goto out;
+		idev = in6_dev_get(dev);
+		if (!idev)
+			goto out;
 	}
 
 	if (rtmsg->rtmsg_metric == 0)
@@ -793,10 +835,20 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
 	 */
 	if ((rtmsg->rtmsg_flags&RTF_REJECT) ||
 	    (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) {
-		if (dev)
-			dev_put(dev);
-		dev = &loopback_dev;
-		dev_hold(dev);
+		/* hold loopback dev/idev if we haven't done so. */
+		if (dev != &loopback_dev) {
+			if (dev) {
+				dev_put(dev);
+				in6_dev_put(idev);
+			}
+			dev = &loopback_dev;
+			dev_hold(dev);
+			idev = in6_dev_get(dev);
+			if (!idev) {
+				err = -ENODEV;
+				goto out;
+			}
+		}
 		rt->u.dst.output = ip6_pkt_discard_out;
 		rt->u.dst.input = ip6_pkt_discard;
 		rt->u.dst.error = -ENETUNREACH;
@@ -838,7 +890,9 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
 				}
 			} else {
 				dev = grt->rt6i_dev;
+				idev = grt->rt6i_idev;
 				dev_hold(dev);
+				in6_dev_hold(grt->rt6i_idev);
 			}
 			if (!(grt->rt6i_flags&RTF_GATEWAY))
 				err = 0;
@@ -900,8 +954,8 @@ install_route:
 	if (!rt->u.dst.metrics[RTAX_ADVMSS-1])
 		rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_pmtu(&rt->u.dst));
 	rt->u.dst.dev = dev;
-	rt->rt6i_idev = in6_dev_get(dev);
-	return rt6_ins(rt, nlh, _rtattr);
+	rt->rt6i_idev = idev;
+	return ip6_ins_rt(rt, nlh, _rtattr);
 
 out:
 	if (dev)
@@ -916,9 +970,7 @@ int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
 
 	write_lock_bh(&rt6_lock);
 
-	spin_lock_bh(&rt6_dflt_lock);
-	rt6_dflt_pointer = NULL;
-	spin_unlock_bh(&rt6_dflt_lock);
+	rt6_reset_dflt_pointer(NULL);
 
 	dst_release(&rt->u.dst);
 
@@ -967,7 +1019,7 @@ static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_r
  *	Handle redirects
  */
 void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr,
-		  struct neighbour *neigh, int on_link)
+		  struct neighbour *neigh, u8 *lladdr, int on_link)
 {
 	struct rt6_info *rt, *nrt;
 
@@ -980,22 +1032,13 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr,
 	if (neigh->dev != rt->rt6i_dev)
 		goto out;
 
-	/* Redirect received -> path was valid.
-	   Look, redirects are sent only in response to data packets,
-	   so that this nexthop apparently is reachable. --ANK
-	 */
-	dst_confirm(&rt->u.dst);
-
-	/* Duplicate redirect: silently ignore. */
-	if (neigh == rt->u.dst.neighbour)
-		goto out;
-
-	/* Current route is on-link; redirect is always invalid.
-	   
-	   Seems, previous statement is not true. It could
-	   be node, which looks for us as on-link (f.e. proxy ndisc)
-	   But then router serving it might decide, that we should
-	   know truth 8)8) --ANK (980726).
+	/*
+	 * Current route is on-link; redirect is always invalid.
+	 * 
+	 * Seems, previous statement is not true. It could
+	 * be node, which looks for us as on-link (f.e. proxy ndisc)
+	 * But then router serving it might decide, that we should
+	 * know truth 8)8) --ANK (980726).
 	 */
 	if (!(rt->rt6i_flags&RTF_GATEWAY))
 		goto out;
@@ -1007,7 +1050,6 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr,
 	 *	is a bit fuzzy and one might need to check all default
 	 *	routers.
 	 */
-
 	if (ipv6_addr_cmp(saddr, &rt->rt6i_gateway)) {
 		if (rt->rt6i_flags & RTF_DEFAULT) {
 			struct rt6_info *rt1;
@@ -1036,6 +1078,24 @@ source_ok:
 	 *	We have finally decided to accept it.
 	 */
 
+	neigh_update(neigh, lladdr, NUD_STALE, 
+		     NEIGH_UPDATE_F_WEAK_OVERRIDE|
+		     NEIGH_UPDATE_F_OVERRIDE|
+		     (on_link ? 0 : (NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
+				     NEIGH_UPDATE_F_ISROUTER))
+		     );
+
+	/*
+	 * Redirect received -> path was valid.
+	 * Look, redirects are sent only in response to data packets,
+	 * so that this nexthop apparently is reachable. --ANK
+	 */
+	dst_confirm(&rt->u.dst);
+
+	/* Duplicate redirect: silently ignore. */
+	if (neigh == rt->u.dst.neighbour)
+		goto out;
+
 	nrt = ip6_rt_copy(rt);
 	if (nrt == NULL)
 		goto out;
@@ -1054,7 +1114,7 @@ source_ok:
 	nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev);
 	nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_pmtu(&nrt->u.dst));
 
-	if (rt6_ins(nrt, NULL, NULL))
+	if (ip6_ins_rt(nrt, NULL, NULL))
 		goto out;
 
 	if (rt->rt6i_flags&RTF_CACHE) {
@@ -1144,7 +1204,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
 		dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires);
 		nrt->rt6i_flags |= RTF_DYNAMIC|RTF_CACHE|RTF_EXPIRES;
 		nrt->u.dst.metrics[RTAX_MTU-1] = pmtu;
-		rt6_ins(nrt, NULL, NULL);
+		ip6_ins_rt(nrt, NULL, NULL);
 	}
 
 out:
@@ -1213,7 +1273,7 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr,
 	rtmsg.rtmsg_type = RTMSG_NEWROUTE;
 	ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr);
 	rtmsg.rtmsg_metric = 1024;
-	rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | RTF_UP;
+	rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | RTF_UP | RTF_EXPIRES;
 
 	rtmsg.rtmsg_ifindex = dev->ifindex;
 
@@ -1237,9 +1297,7 @@ restart:
 		if (rt->rt6i_flags & flags) {
 			dst_hold(&rt->u.dst);
 
-			spin_lock_bh(&rt6_dflt_lock);
-			rt6_dflt_pointer = NULL;
-			spin_unlock_bh(&rt6_dflt_lock);
+			rt6_reset_dflt_pointer(NULL);
 
 			read_unlock_bh(&rt6_lock);
 
@@ -1299,27 +1357,32 @@ int ip6_pkt_discard(struct sk_buff *skb)
 
 int ip6_pkt_discard_out(struct sk_buff **pskb)
 {
+	(*pskb)->dev = (*pskb)->dst->dev;
+	BUG_ON(!(*pskb)->dev);
 	return ip6_pkt_discard(*pskb);
 }
 
 /*
- *	Add address
+ *	Allocate a dst for local (unicast / anycast) address.
  */
 
-int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev, int anycast)
+struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
+				    const struct in6_addr *addr,
+				    int anycast)
 {
 	struct rt6_info *rt = ip6_dst_alloc();
 
 	if (rt == NULL)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
 	dev_hold(&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_idev = in6_dev_get(&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_pmtu(&rt->u.dst));
 	rt->u.dst.metrics[RTAX_HOPLIMIT-1] = ipv6_get_hoplimit(rt->rt6i_dev);
@@ -1331,34 +1394,15 @@ int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev, int anycast)
 	rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway);
 	if (rt->rt6i_nexthop == NULL) {
 		dst_free((struct dst_entry *) rt);
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 	}
 
 	ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
 	rt->rt6i_dst.plen = 128;
-	rt6_ins(rt, NULL, NULL);
-
-	return 0;
-}
-
-/* Delete address. Warning: you should check that this address
-   disappeared before calling this function.
- */
-
-int ip6_rt_addr_del(struct in6_addr *addr, struct net_device *dev)
-{
-	struct rt6_info *rt;
-	int err = -ENOENT;
 
-	rt = rt6_lookup(addr, NULL, loopback_dev.ifindex, 1);
-	if (rt) {
-		if (rt->rt6i_dst.plen == 128)
-			err = ip6_del_rt(rt, NULL, NULL);
-		else
-			dst_release(&rt->u.dst);
-	}
+	atomic_set(&rt->u.dst.__refcnt, 1);
 
-	return err;
+	return rt;
 }
 
 static int fib6_ifdown(struct rt6_info *rt, void *arg)
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 23482d1bd..3ddbd6ce3 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -50,6 +50,7 @@
 #include <net/ipip.h>
 #include <net/inet_ecn.h>
 #include <net/xfrm.h>
+#include <net/dsfield.h>
 
 /*
    This version of net/ipv6/sit.c is cloned of net/ipv4/ip_gre.c
@@ -360,8 +361,7 @@ out:
 
 static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
 {
-	if (INET_ECN_is_ce(iph->tos) &&
-	    INET_ECN_is_not_ce(ip6_get_dsfield(skb->nh.ipv6h)))
+	if (INET_ECN_is_ce(iph->tos))
 		IP6_ECN_set_ce(skb->nh.ipv6h);
 }
 
@@ -487,6 +487,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 		}
 	}
 	if (rt->rt_type != RTN_UNICAST) {
+		ip_rt_put(rt);
 		tunnel->stat.tx_carrier_errors++;
 		goto tx_error_icmp;
 	}
@@ -567,7 +568,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 		iph->frag_off	=	0;
 
 	iph->protocol		=	IPPROTO_IPV6;
-	iph->tos		=	INET_ECN_encapsulate(tos, ip6_get_dsfield(iph6));
+	iph->tos		=	INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6));
 	iph->daddr		=	rt->rt_dst;
 	iph->saddr		=	rt->rt_src;
 
@@ -814,18 +815,19 @@ int __init sit_init(void)
 					   ipip6_tunnel_setup);
 	if (!ipip6_fb_tunnel_dev) {
 		err = -ENOMEM;
-		goto fail;
+		goto err1;
 	}
 
 	ipip6_fb_tunnel_dev->init = ipip6_fb_tunnel_init;
 
 	if ((err =  register_netdev(ipip6_fb_tunnel_dev)))
-		goto fail;
+		goto err2;
 
  out:
 	return err;
- fail:
-	inet_del_protocol(&sit_protocol, IPPROTO_IPV6);
+ err2:
 	free_netdev(ipip6_fb_tunnel_dev);
+ err1:
+	inet_del_protocol(&sit_protocol, IPPROTO_IPV6);
 	goto out;
 }
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 5a19b3d75..fa13a7449 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -57,6 +57,7 @@
 #include <net/xfrm.h>
 #include <net/addrconf.h>
 #include <net/snmp.h>
+#include <net/dsfield.h>
 
 #include <asm/uaccess.h>
 
@@ -549,7 +550,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 	struct inet_opt *inet = inet_sk(sk);
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct tcp_opt *tp = tcp_sk(sk);
-	struct in6_addr *saddr = NULL;
+	struct in6_addr *saddr = NULL, *final_p = NULL, final;
 	struct flowi fl;
 	struct dst_entry *dst;
 	int addr_type;
@@ -666,13 +667,21 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 
 	if (np->opt && np->opt->srcrt) {
 		struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
+		ipv6_addr_copy(&final, &fl.fl6_dst);
 		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+		final_p = &final;
 	}
 
 	err = ip6_dst_lookup(sk, &dst, &fl);
-
 	if (err)
 		goto failure;
+	if (final_p)
+		ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+	if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+		dst_release(dst);
+		goto failure;
+	}
 
 	if (saddr == NULL) {
 		saddr = &fl.fl6_src;
@@ -793,6 +802,12 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 				sk->sk_err_soft = -err;
 				goto out;
 			}
+
+			if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+				sk->sk_err_soft = -err;
+				goto out;
+			}
+
 		} else
 			dst_hold(dst);
 
@@ -863,6 +878,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct open_request *req,
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct sk_buff * skb;
 	struct ipv6_txoptions *opt = NULL;
+	struct in6_addr * final_p = NULL, final;
 	struct flowi fl;
 	int err = -1;
 
@@ -888,12 +904,18 @@ static int tcp_v6_send_synack(struct sock *sk, struct open_request *req,
 
 		if (opt && opt->srcrt) {
 			struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
+			ipv6_addr_copy(&final, &fl.fl6_dst);
 			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+			final_p = &final;
 		}
 
 		err = ip6_dst_lookup(sk, &dst, &fl);
 		if (err)
 			goto done;
+		if (final_p)
+			ipv6_addr_copy(&fl.fl6_dst, final_p);
+		if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+			goto done;
 	}
 
 	skb = tcp_make_synack(sk, dst, req);
@@ -981,11 +1003,12 @@ static void tcp_v6_send_reset(struct sk_buff *skb)
 	 * and then put it into the queue to be sent.
 	 */
 
-	buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr), GFP_ATOMIC);
+	buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + sizeof(struct tcphdr),
+			 GFP_ATOMIC);
 	if (buff == NULL) 
 	  	return;
 
-	skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr));
+	skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + sizeof(struct tcphdr));
 
 	t1 = (struct tcphdr *) skb_push(buff,sizeof(struct tcphdr));
 
@@ -1021,6 +1044,12 @@ static void tcp_v6_send_reset(struct sk_buff *skb)
 
 	/* sk = NULL, but it is safe for now. RST socket required. */
 	if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
+
+		if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) {
+			dst_release(buff->dst);
+			return;
+		}
+
 		ip6_xmit(NULL, buff, &fl, NULL, 0);
 		TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
 		TCP_INC_STATS_BH(TCP_MIB_OUTRSTS);
@@ -1037,14 +1066,15 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
 	struct flowi fl;
 	int tot_len = sizeof(struct tcphdr);
 
-	buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr), GFP_ATOMIC);
+	if (ts)
+		tot_len += 3*4;
+
+	buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len,
+			 GFP_ATOMIC);
 	if (buff == NULL)
 		return;
 
-	skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr));
-
-	if (ts)
-		tot_len += 3*4;
+	skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len);
 
 	t1 = (struct tcphdr *) skb_push(buff,tot_len);
 
@@ -1082,6 +1112,10 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
 	fl.fl_ip_sport = t1->source;
 
 	if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
+		if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) {
+			dst_release(buff->dst);
+			return;
+		}
 		ip6_xmit(NULL, buff, &fl, NULL, 0);
 		TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
 		return;
@@ -1313,6 +1347,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
 	}
 
 	if (dst == NULL) {
+		struct in6_addr *final_p = NULL, final;
 		struct flowi fl;
 
 		memset(&fl, 0, sizeof(fl));
@@ -1320,7 +1355,9 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
 		ipv6_addr_copy(&fl.fl6_dst, &req->af.v6_req.rmt_addr);
 		if (opt && opt->srcrt) {
 			struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
+			ipv6_addr_copy(&final, &fl.fl6_dst);
 			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+			final_p = &final;
 		}
 		ipv6_addr_copy(&fl.fl6_src, &req->af.v6_req.loc_addr);
 		fl.oif = sk->sk_bound_dev_if;
@@ -1329,6 +1366,12 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
 
 		if (ip6_dst_lookup(sk, &dst, &fl))
 			goto out;
+
+		if (final_p)
+			ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+		if ((xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+			goto out;
 	} 
 
 	newsk = tcp_create_openreq_child(sk, req, skb);
@@ -1606,7 +1649,7 @@ static int tcp_v6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
 				    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 = ip6_get_dsfield(skb->nh.ipv6h);
+	TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(skb->nh.ipv6h);
 	TCP_SKB_CB(skb)->sacked = 0;
 
 	sk = __tcp_v6_lookup(&skb->nh.ipv6h->saddr, th->source,
@@ -1710,6 +1753,7 @@ static int tcp_v6_rebuild_header(struct sock *sk)
 
 	if (dst == NULL) {
 		struct inet_opt *inet = inet_sk(sk);
+		struct in6_addr *final_p = NULL, final;
 		struct flowi fl;
 
 		memset(&fl, 0, sizeof(fl));
@@ -1723,15 +1767,24 @@ static int tcp_v6_rebuild_header(struct sock *sk)
 
 		if (np->opt && np->opt->srcrt) {
 			struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
+			ipv6_addr_copy(&final, &fl.fl6_dst);
 			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+			final_p = &final;
 		}
 
 		err = ip6_dst_lookup(sk, &dst, &fl);
-
 		if (err) {
 			sk->sk_route_caps = 0;
 			return err;
 		}
+		if (final_p)
+			ipv6_addr_copy(&fl.fl6_dst, final_p);
+
+		if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+			sk->sk_err_soft = -err;
+			dst_release(dst);
+			return err;
+		}
 
 		ip6_dst_store(sk, dst, NULL);
 		sk->sk_route_caps = dst->dev->features &
@@ -1775,6 +1828,12 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok)
 			return err;
 		}
 
+		if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
+			sk->sk_route_caps = 0;
+			dst_release(dst);
+			return err;
+		}
+
 		ip6_dst_store(sk, dst, NULL);
 		sk->sk_route_caps = dst->dev->features &
 			~(NETIF_F_IP_CSUM | NETIF_F_TSO);
@@ -1873,7 +1932,7 @@ static int tcp_v6_init_sock(struct sock *sk)
 	 */
 	tp->snd_ssthresh = 0x7fffffff;
 	tp->snd_cwnd_clamp = ~0;
-	tp->mss_cache = 536;
+	tp->mss_cache_std = tp->mss_cache = 536;
 
 	tp->reordering = sysctl_tcp_reordering;
 
@@ -2089,6 +2148,7 @@ struct proto tcpv6_prot = {
 	.sysctl_wmem		= sysctl_tcp_wmem,
 	.sysctl_rmem		= sysctl_tcp_rmem,
 	.max_header		= MAX_TCP_HEADER,
+	.slab_obj_size		= sizeof(struct tcp6_sock),
 };
 
 static struct inet6_protocol tcpv6_protocol = {
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 7133801bd..ff00dc49c 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -627,7 +627,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
 	struct inet_opt *inet = inet_sk(sk);
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name;
-	struct in6_addr *daddr;
+	struct in6_addr *daddr, *final_p = NULL, final;
 	struct ipv6_txoptions *opt = NULL;
 	struct ip6_flowlabel *flowlabel = NULL;
 	struct flowi *fl = &inet->cork.fl;
@@ -783,7 +783,9 @@ do_udp_sendmsg:
 	/* merge ip6_build_xmit from ip6_output */
 	if (opt && opt->srcrt) {
 		struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
+		ipv6_addr_copy(&final, &fl->fl6_dst);
 		ipv6_addr_copy(&fl->fl6_dst, rt0->addr);
+		final_p = &final;
 	}
 
 	if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst))
@@ -792,6 +794,13 @@ do_udp_sendmsg:
 	err = ip6_dst_lookup(sk, &dst, fl);
 	if (err)
 		goto out;
+	if (final_p)
+		ipv6_addr_copy(&fl->fl6_dst, final_p);
+
+	if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0) {
+		dst_release(dst);
+		goto out;
+	}
 
 	if (hlimit < 0) {
 		if (ipv6_addr_is_multicast(&fl->fl6_dst))
@@ -1037,6 +1046,7 @@ struct proto udpv6_prot = {
 	.hash =		udp_v6_hash,
 	.unhash =	udp_v6_unhash,
 	.get_port =	udp_v6_get_port,
+	.slab_obj_size = sizeof(struct udp6_sock),
 };
 
 extern struct proto_ops inet6_dgram_ops;
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 0791594f8..28c29d783 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -9,7 +9,9 @@
  *		IPv6 support
  */
 
+#include <linux/module.h>
 #include <linux/string.h>
+#include <net/dsfield.h>
 #include <net/inet_ecn.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
@@ -20,16 +22,15 @@ static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
 	struct ipv6hdr *outer_iph = skb->nh.ipv6h;
 	struct ipv6hdr *inner_iph = skb->h.ipv6h;
 
-	if (INET_ECN_is_ce(ip6_get_dsfield(outer_iph)) &&
-	    INET_ECN_is_not_ce(ip6_get_dsfield(inner_iph)))
+	if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph)))
 		IP6_ECN_set_ce(inner_iph);
 }
 
-int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi)
 {
 	struct sk_buff *skb = *pskb;
 	int err;
-	u32 spi, seq;
+	u32 seq;
 	struct sec_decap_state xfrm_vec[XFRM_MAX_DEPTH];
 	struct xfrm_state *x;
 	int xfrm_nr = 0;
@@ -40,7 +41,8 @@ int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
 	nhoff = *nhoffp;
 	nexthdr = skb->nh.raw[nhoff];
 
-	if ((err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
+	seq = 0;
+	if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
 		goto drop;
 	
 	do {
@@ -86,6 +88,8 @@ int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
 			if (skb_cloned(skb) &&
 			    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
 				goto drop;
+			if (x->props.flags & XFRM_STATE_DECAP_DSCP)
+				ipv6_copy_dscp(skb->nh.ipv6h, skb->h.ipv6h);
 			if (!(x->props.flags & XFRM_STATE_NOECN))
 				ipip6_ecn_decapsulate(skb);
 			skb->mac.raw = memmove(skb->data - skb->mac_len,
@@ -137,3 +141,10 @@ drop:
 	kfree_skb(skb);
 	return -1;
 }
+
+EXPORT_SYMBOL(xfrm6_rcv_spi);
+
+int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
+{
+	return xfrm6_rcv_spi(pskb, nhoffp, 0);
+}
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 712856f0f..40612ec54 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -12,6 +12,7 @@
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 #include <linux/icmpv6.h>
+#include <net/dsfield.h>
 #include <net/inet_ecn.h>
 #include <net/ipv6.h>
 #include <net/xfrm.h>
@@ -36,6 +37,7 @@ static void xfrm6_encap(struct sk_buff *skb)
 	struct dst_entry *dst = skb->dst;
 	struct xfrm_state *x = dst->xfrm;
 	struct ipv6hdr *iph, *top_iph;
+	int dsfield;
 
 	skb_push(skb, x->props.header_len);
 	iph = skb->nh.ipv6h;
@@ -58,13 +60,16 @@ static void xfrm6_encap(struct sk_buff *skb)
 
 	top_iph->version = 6;
 	top_iph->priority = iph->priority;
-	if (x->props.flags & XFRM_STATE_NOECN)
-		IP6_ECN_clear(top_iph);
 	top_iph->flow_lbl[0] = iph->flow_lbl[0];
 	top_iph->flow_lbl[1] = iph->flow_lbl[1];
 	top_iph->flow_lbl[2] = iph->flow_lbl[2];
+	dsfield = ipv6_get_dsfield(top_iph);
+	dsfield = INET_ECN_encapsulate(dsfield, dsfield);
+	if (x->props.flags & XFRM_STATE_NOECN)
+		dsfield &= ~INET_ECN_MASK;
+	ipv6_change_dsfield(top_iph, 0, dsfield);
 	top_iph->nexthdr = IPPROTO_IPV6; 
-	top_iph->hop_limit = iph->hop_limit;
+	top_iph->hop_limit = dst_path_metric(dst, RTAX_HOPLIMIT);
 	ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
 	ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
 }
@@ -113,8 +118,7 @@ int xfrm6_output(struct sk_buff **pskb)
 
 	xfrm6_encap(skb);
 
-	err = x->type->output(pskb);
-	skb = *pskb;
+	err = x->type->output(skb);
 	if (err)
 		goto error;
 
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index ab4e40b0a..a0715e2f0 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -17,12 +17,12 @@
 #include <net/ipv6.h>
 #include <net/ip6_route.h>
 
-extern struct dst_ops xfrm6_dst_ops;
-extern struct xfrm_policy_afinfo xfrm6_policy_afinfo;
+static struct dst_ops xfrm6_dst_ops;
+static struct xfrm_policy_afinfo xfrm6_policy_afinfo;
 
 static struct xfrm_type_map xfrm6_type_map = { .lock = RW_LOCK_UNLOCKED };
 
-int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
+static int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
 {
 	int err = 0;
 	*dst = (struct xfrm_dst*)ip6_route_output(NULL, fl);
@@ -213,6 +213,16 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl)
 			fl->proto = nexthdr;
 			return;
 
+		case IPPROTO_ICMPV6:
+			if (pskb_may_pull(skb, skb->nh.raw + offset + 2 - skb->data)) {
+				u8 *icmp = (u8 *)exthdr;
+
+				fl->fl_icmp_type = icmp[0];
+				fl->fl_icmp_code = icmp[1];
+			}
+			fl->proto = nexthdr;
+			return;
+
 		/* XXX Why are there these headers? */
 		case IPPROTO_AH:
 		case IPPROTO_ESP:
@@ -243,7 +253,7 @@ static void xfrm6_update_pmtu(struct dst_entry *dst, u32 mtu)
 	return;
 }
 
-struct dst_ops xfrm6_dst_ops = {
+static struct dst_ops xfrm6_dst_ops = {
 	.family =		AF_INET6,
 	.protocol =		__constant_htons(ETH_P_IPV6),
 	.gc =			xfrm6_garbage_collect,
@@ -252,7 +262,7 @@ struct dst_ops xfrm6_dst_ops = {
 	.entry_size =		sizeof(struct xfrm_dst),
 };
 
-struct xfrm_policy_afinfo xfrm6_policy_afinfo = {
+static struct xfrm_policy_afinfo xfrm6_policy_afinfo = {
 	.family =		AF_INET6,
 	.lock = 		RW_LOCK_UNLOCKED,
 	.type_map = 		&xfrm6_type_map,
@@ -263,12 +273,12 @@ struct xfrm_policy_afinfo xfrm6_policy_afinfo = {
 	.decode_session =	_decode_session6,
 };
 
-void __init xfrm6_policy_init(void)
+static void __init xfrm6_policy_init(void)
 {
 	xfrm_policy_register_afinfo(&xfrm6_policy_afinfo);
 }
 
-void __exit xfrm6_policy_fini(void)
+static void __exit xfrm6_policy_fini(void)
 {
 	xfrm_policy_unregister_afinfo(&xfrm6_policy_afinfo);
 }
@@ -277,12 +287,10 @@ void __init xfrm6_init(void)
 {
 	xfrm6_policy_init();
 	xfrm6_state_init();
-	xfrm6_tunnel_init();
 }
 
 void __exit xfrm6_fini(void)
 {
-	xfrm6_tunnel_fini();
 	//xfrm6_input_fini();
 	xfrm6_policy_fini();
 	xfrm6_state_fini();
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 5766a1334..9616a63cc 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -343,9 +343,8 @@ void xfrm6_tunnel_free_spi(xfrm_address_t *saddr)
 
 EXPORT_SYMBOL(xfrm6_tunnel_free_spi);
 
-static int xfrm6_tunnel_output(struct sk_buff **pskb)
+static int xfrm6_tunnel_output(struct sk_buff *skb)
 {
-	struct sk_buff *skb = *pskb;
 	struct ipv6hdr *top_iph;
 
 	top_iph = (struct ipv6hdr *)skb->data;
@@ -356,17 +355,6 @@ static int xfrm6_tunnel_output(struct sk_buff **pskb)
 
 static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
 {
-	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) 
-		return -EINVAL;
-
-	skb->mac.raw = skb->nh.raw;
-	skb->nh.raw = skb->data;
-	dst_release(skb->dst);
-	skb->dst = NULL;
-	skb->protocol = htons(ETH_P_IPV6);
-	skb->pkt_type = PACKET_HOST;
-	netif_rx(skb);
-
 	return 0;
 }
 
@@ -413,49 +401,15 @@ static int xfrm6_tunnel_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
 {
 	struct sk_buff *skb = *pskb;
 	struct xfrm6_tunnel *handler = xfrm6_tunnel_handler;
-	struct xfrm_state *x = NULL;
 	struct ipv6hdr *iph = skb->nh.ipv6h;
-	int err = 0;
 	u32 spi;
 
 	/* device-like_ip6ip6_handler() */
-	if (handler) {
-		err = handler->handler(pskb, nhoffp);
-		if (!err)
-			goto out;
-	}
+	if (handler && handler->handler(pskb, nhoffp) == 0)
+		return 0;
 
 	spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr);
-	x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, 
-			spi,
-			IPPROTO_IPV6, AF_INET6);
-
-	if (!x)
-		goto drop;
-
-	spin_lock(&x->lock);
-
-	if (unlikely(x->km.state != XFRM_STATE_VALID))
-		goto drop_unlock;
-
-	err = xfrm6_tunnel_input(x, NULL, skb);
-	if (err)
-		goto drop_unlock;
-
-	x->curlft.bytes += skb->len;
-	x->curlft.packets++; 
-	spin_unlock(&x->lock); 
-	xfrm_state_put(x); 
-
-out:
-	return 0;
-
-drop_unlock:
-	spin_unlock(&x->lock);
-	xfrm_state_put(x);
-drop:
-	kfree_skb(skb);
-	return -1;
+	return xfrm6_rcv_spi(pskb, nhoffp, spi);
 }
 
 static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
@@ -517,6 +471,9 @@ static int xfrm6_tunnel_init_state(struct xfrm_state *x, void *args)
 	if (!x->props.mode)
 		return -EINVAL;
 
+	if (x->encap)
+		return -EINVAL;
+
 	x->props.header_len = sizeof(struct ipv6hdr);
 
 	return 0;
@@ -543,31 +500,32 @@ static struct inet6_protocol xfrm6_tunnel_protocol = {
 	.flags          = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
 };
 
-void __init xfrm6_tunnel_init(void)
+static int __init xfrm6_tunnel_init(void)
 {
 	X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
 
 	if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0) {
 		X6TPRINTK1(KERN_ERR
 			   "xfrm6_tunnel init: can't add xfrm type\n");
-		return;
+		return -EAGAIN;
 	}
 	if (inet6_add_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6) < 0) {
 		X6TPRINTK1(KERN_ERR
 			   "xfrm6_tunnel init(): can't add protocol\n");
 		xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
-		return;
+		return -EAGAIN;
 	}
 	if (xfrm6_tunnel_spi_init() < 0) {
 		X6TPRINTK1(KERN_ERR
 			   "xfrm6_tunnel init: failed to initialize spi\n");
 		inet6_del_protocol(&xfrm6_tunnel_protocol, IPPROTO_IPV6);
 		xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
-		return;
+		return -EAGAIN;
 	}
+	return 0;
 }
 
-void __exit xfrm6_tunnel_fini(void)
+static void __exit xfrm6_tunnel_fini(void)
 {
 	X6TPRINTK3(KERN_DEBUG "%s()\n", __FUNCTION__);
 
@@ -579,3 +537,7 @@ void __exit xfrm6_tunnel_fini(void)
 		X6TPRINTK1(KERN_ERR
 			   "xfrm6_tunnel close: can't remove xfrm type\n");
 }
+
+module_init(xfrm6_tunnel_init);
+module_exit(xfrm6_tunnel_fini);
+MODULE_LICENSE("GPL");
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 163223daf..e88d37fe2 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -1621,6 +1621,7 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
 
 	sipx.sipx_family = AF_IPX;
 	sipx.sipx_type	 = ipxs->type;
+	sipx.sipx_zero	 = 0;
 	memcpy(uaddr, &sipx, sizeof(sipx));
 
 	rc = 0;
@@ -1808,6 +1809,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
 		memcpy(sipx->sipx_node, ipx->ipx_source.node, IPX_NODE_LEN);
 		sipx->sipx_network	= IPX_SKB_CB(skb)->ipx_source_net;
 		sipx->sipx_type 	= ipx->ipx_type;
+		sipx->sipx_zero		= 0;
 	}
 	rc = copied;
 
diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c
index fa25d3a97..e6599074e 100644
--- a/net/irda/irlan/irlan_common.c
+++ b/net/irda/irlan/irlan_common.c
@@ -36,6 +36,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/rtnetlink.h>
+#include <linux/moduleparam.h>
 
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -1181,9 +1182,9 @@ MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("The Linux IrDA LAN protocol"); 
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(eth, "i");
+module_param(eth, bool, 0);
 MODULE_PARM_DESC(eth, "Name devices ethX (0) or irlanX (1)");
-MODULE_PARM(access, "i");
+module_param(access, int, 0);
 MODULE_PARM_DESC(access, "Access type DIRECT=1, PEER=2, HOSTED=3");
 
 module_init(irlan_init);
diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c
index 11a2955f8..04bb8925a 100644
--- a/net/irda/irlan/irlan_eth.c
+++ b/net/irda/irlan/irlan_eth.c
@@ -303,10 +303,10 @@ void irlan_eth_send_gratuitous_arp(struct net_device *dev)
 	 */
 #ifdef CONFIG_INET
 	IRDA_DEBUG(4, "IrLAN: Sending gratuitous ARP\n");
-	in_dev = in_dev_get(dev);
+	rcu_read_lock();
+	in_dev = __in_dev_get(dev);
 	if (in_dev == NULL)
-		return;
-	read_lock(&in_dev->lock);
+		goto out;
 	if (in_dev->ifa_list)
 		
 	arp_send(ARPOP_REQUEST, ETH_P_ARP, 
@@ -314,8 +314,8 @@ void irlan_eth_send_gratuitous_arp(struct net_device *dev)
 		 dev, 
 		 in_dev->ifa_list->ifa_address,
 		 NULL, dev->dev_addr, NULL);
-	read_unlock(&in_dev->lock);
-	in_dev_put(in_dev);
+out:
+	rcu_read_unlock();
 #endif /* CONFIG_INET */
 }
 
diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c
index 65a3eb943..ca948a000 100644
--- a/net/irda/irqueue.c
+++ b/net/irda/irqueue.c
@@ -663,8 +663,10 @@ void* hashbin_remove_this( hashbin_t* hashbin, irda_queue_t* entry)
 	} /* Default is no-lock  */
 
 	/* Check if valid and not already removed... */
-	if((entry->q_next == NULL) || (entry->q_prev == NULL))
-		return NULL;
+	if((entry->q_next == NULL) || (entry->q_prev == NULL)) {
+		entry = NULL;
+		goto out;
+	}
 
 	/*
 	 * Locate hashbin
@@ -687,7 +689,7 @@ void* hashbin_remove_this( hashbin_t* hashbin, irda_queue_t* entry)
 	 */
 	if ( entry == hashbin->hb_current)
 		hashbin->hb_current = NULL;
-
+out:
 	/* Release lock */
 	if ( hashbin->hb_type & HB_LOCK ) {
 		spin_unlock_irqrestore(&hashbin->hb_spinlock, flags);
diff --git a/net/key/af_key.c b/net/key/af_key.c
index fdf75a1ba..ed9d9bebd 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -683,6 +683,8 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys,
 	sa->sadb_sa_flags = 0;
 	if (x->props.flags & XFRM_STATE_NOECN)
 		sa->sadb_sa_flags |= SADB_SAFLAGS_NOECN;
+	if (x->props.flags & XFRM_STATE_DECAP_DSCP)
+		sa->sadb_sa_flags |= SADB_SAFLAGS_DECAP_DSCP;
 
 	/* hard time */
 	if (hsc & 2) {
@@ -965,6 +967,8 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
 	x->props.replay_window = sa->sadb_sa_replay;
 	if (sa->sadb_sa_flags & SADB_SAFLAGS_NOECN)
 		x->props.flags |= XFRM_STATE_NOECN;
+	if (sa->sadb_sa_flags & SADB_SAFLAGS_DECAP_DSCP)
+		x->props.flags |= XFRM_STATE_DECAP_DSCP;
 
 	lifetime = (struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_HARD-1];
 	if (lifetime != NULL) {
@@ -1075,15 +1079,6 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
 		n_type = ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1];
 		natt->encap_type = n_type->sadb_x_nat_t_type_type;
 
-		switch (natt->encap_type) {
-		case UDP_ENCAP_ESPINUDP:
-		case UDP_ENCAP_ESPINUDP_NON_IKE:
-			break;
-		default:
-			err = -ENOPROTOOPT;
-			goto out;
-		}
-
 		if (ext_hdrs[SADB_X_EXT_NAT_T_SPORT-1]) {
 			struct sadb_x_nat_t_port* n_port =
 				ext_hdrs[SADB_X_EXT_NAT_T_SPORT-1];
@@ -1165,7 +1160,16 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
 		break;
 #endif
 	}
-	if (xdaddr)
+
+	if (hdr->sadb_msg_seq) {
+		x = xfrm_find_acq_byseq(hdr->sadb_msg_seq);
+		if (x && xfrm_addr_cmp(&x->id.daddr, xdaddr, family)) {
+			xfrm_state_put(x);
+			x = NULL;
+		}
+	}
+
+	if (!x)
 		x = xfrm_find_acq(mode, reqid, proto, xdaddr, xsaddr, 1, family);
 
 	if (x == NULL)
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index d088fe8f6..357a1f045 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -638,7 +638,6 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags)
 	newsk = skb->sk;
 	/* attach connection to a new socket. */
 	llc_ui_sk_init(newsock, newsk);
-	newsk->sk_pair		= NULL;
 	newsk->sk_zapped	= 0;
 	newsk->sk_state		= TCP_ESTABLISHED;
 	newsock->state		= SS_CONNECTED;
diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c
index ecfa9b567..4da6976ef 100644
--- a/net/llc/llc_input.c
+++ b/net/llc/llc_input.c
@@ -111,7 +111,7 @@ static inline int llc_fixup_skb(struct sk_buff *skb)
 	skb->h.raw += llc_len;
 	skb_pull(skb, llc_len);
 	if (skb->protocol == htons(ETH_P_802_2)) {
-		u16 pdulen = ((struct ethhdr *)skb->mac.raw)->h_proto,
+		u16 pdulen = eth_hdr(skb)->h_proto,
 		    data_size = ntohs(pdulen) - llc_len;
 
 		skb_trim(skb, data_size);
diff --git a/net/llc/llc_output.c b/net/llc/llc_output.c
index 66206ebb6..ab5784cf1 100644
--- a/net/llc/llc_output.c
+++ b/net/llc/llc_output.c
@@ -40,7 +40,8 @@ int llc_mac_hdr_init(struct sk_buff *skb, unsigned char *sa, unsigned char *da)
 		struct net_device *dev = skb->dev;
 		struct trh_hdr *trh;
 		
-		trh = (struct trh_hdr *)skb_push(skb, sizeof(*trh));
+		skb->mac.raw = skb_push(skb, sizeof(*trh));
+		trh = tr_hdr(skb);
 		trh->ac = AC;
 		trh->fc = LLC_FRAME;
 		if (sa)
@@ -50,8 +51,8 @@ int llc_mac_hdr_init(struct sk_buff *skb, unsigned char *sa, unsigned char *da)
 		if (da) {
 			memcpy(trh->daddr, da, dev->addr_len);
 			tr_source_route(skb, trh, dev);
+			skb->mac.raw = skb->data;
 		}
-		skb->mac.raw = skb->data;
 		break;
 	}
 #endif
@@ -61,7 +62,7 @@ int llc_mac_hdr_init(struct sk_buff *skb, unsigned char *sa, unsigned char *da)
 		struct ethhdr *eth;
 
 		skb->mac.raw = skb_push(skb, sizeof(*eth));
-		eth = (struct ethhdr *)skb->mac.raw;
+		eth = eth_hdr(skb);
 		eth->h_proto = htons(len);
 		memcpy(eth->h_dest, da, ETH_ALEN);
 		memcpy(eth->h_source, sa, ETH_ALEN);
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 69a81d08d..4aa05030e 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -44,6 +44,10 @@
 #include <linux/smp_lock.h>
 #include <linux/notifier.h>
 #include <linux/security.h>
+#include <linux/vs_base.h>
+#include <linux/vs_context.h>
+#include <linux/vs_network.h>
+#include <linux/vs_limit.h>
 #include <net/sock.h>
 #include <net/scm.h>
 
@@ -242,6 +246,12 @@ static int netlink_create(struct socket *sock, int protocol)
 	sk->sk_destruct = netlink_sock_destruct;
 	atomic_inc(&netlink_sock_nr);
 
+	set_vx_info(&sk->sk_vx_info, current->vx_info);
+	sk->sk_xid = vx_current_xid();
+	vx_sock_inc(sk);
+	set_nx_info(&sk->sk_nx_info, current->nx_info);
+	sk->sk_nid = nx_current_nid();
+
 	sk->sk_protocol = protocol;
 	return 0;
 }
@@ -283,6 +293,12 @@ static int netlink_release(struct socket *sock)
 		notifier_call_chain(&netlink_chain, NETLINK_URELEASE, &n);
 	}	
 	
+	vx_sock_dec(sk);
+	clr_vx_info(&sk->sk_vx_info);
+	sk->sk_xid = -1;
+	clr_nx_info(&sk->sk_nx_info);
+	sk->sk_nid = -1;
+
 	sock_put(sk);
 	return 0;
 }
@@ -536,12 +552,31 @@ void netlink_detachskb(struct sock *sk, struct sk_buff *skb)
 	sock_put(sk);
 }
 
+static inline void netlink_trim(struct sk_buff *skb, int allocation)
+{
+	int delta = skb->end - skb->tail;
+
+	/* If the packet is charged to a socket, the modification
+	 * of truesize below is illegal and will corrupt socket
+	 * buffer accounting state.
+	 */
+	BUG_ON(skb->list != NULL);
+
+	if (delta * 2 < skb->truesize)
+		return;
+	if (pskb_expand_head(skb, 0, -delta, allocation))
+		return;
+	skb->truesize -= delta;
+}
+
 int netlink_unicast(struct sock *ssk, struct sk_buff *skb, u32 pid, int nonblock)
 {
 	struct sock *sk;
 	int err;
 	long timeo;
 
+	netlink_trim(skb, gfp_any());
+
 	timeo = sock_sndtimeo(ssk, nonblock);
 retry:
 	sk = netlink_getsockbypid(ssk, pid);
@@ -588,6 +623,8 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid,
 	int protocol = ssk->sk_protocol;
 	int failure = 0, delivered = 0;
 
+	netlink_trim(skb, allocation);
+
 	/* While we sleep in clone, do not allow to change socket list */
 
 	netlink_lock_table();
@@ -1220,7 +1257,6 @@ MODULE_ALIAS_NETPROTO(PF_NETLINK);
 
 EXPORT_SYMBOL(netlink_ack);
 EXPORT_SYMBOL(netlink_broadcast);
-EXPORT_SYMBOL(netlink_broadcast_deliver);
 EXPORT_SYMBOL(netlink_dump_start);
 EXPORT_SYMBOL(netlink_kernel_create);
 EXPORT_SYMBOL(netlink_register_notifier);
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index 6774669bb..62ff798bf 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -801,7 +801,6 @@ static int nr_accept(struct socket *sock, struct socket *newsock, int flags)
 	remove_wait_queue(sk->sk_sleep, &wait);
 
 	newsk = skb->sk;
-	newsk->sk_pair = NULL;
 	newsk->sk_socket = newsock;
 	newsk->sk_sleep = &newsock->wait;
 
@@ -994,7 +993,6 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
 	nr_make->vl        = 0;
 	nr_make->state     = NR_STATE_3;
 	sk->sk_ack_backlog++;
-	make->sk_pair = sk;
 
 	nr_insert_socket(make);
 
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 93ac3b310..1b441a628 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -65,6 +65,8 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
+#include <asm/page.h>
+#include <asm/io.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/poll.h>
@@ -172,7 +174,7 @@ struct packet_opt
 {
 	struct tpacket_stats	stats;
 #ifdef CONFIG_PACKET_MMAP
-	unsigned long		*pg_vec;
+	char *			*pg_vec;
 	unsigned int		head;
 	unsigned int            frames_per_block;
 	unsigned int		frame_size;
@@ -197,15 +199,15 @@ struct packet_opt
 
 #ifdef CONFIG_PACKET_MMAP
 
-static inline unsigned long packet_lookup_frame(struct packet_opt *po, unsigned int position)
+static inline char *packet_lookup_frame(struct packet_opt *po, unsigned int position)
 {
 	unsigned int pg_vec_pos, frame_offset;
-	unsigned long frame;
+	char *frame;
 
 	pg_vec_pos = position / po->frames_per_block;
 	frame_offset = position % po->frames_per_block;
 
-	frame = (unsigned long) (po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size));
+	frame = po->pg_vec[pg_vec_pos] + (frame_offset * po->frame_size);
 	
 	return frame;
 }
@@ -784,11 +786,13 @@ out:
 static int packet_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
-	struct packet_opt *po = pkt_sk(sk);
+	struct packet_opt *po;
 
 	if (!sk)
 		return 0;
 
+	po = pkt_sk(sk);
+
 	write_lock_bh(&packet_sklist_lock);
 	sk_del_node_init(sk);
 	write_unlock_bh(&packet_sklist_lock);
@@ -1548,7 +1552,12 @@ static struct vm_operations_struct packet_mmap_ops = {
 	.close =packet_mm_close,
 };
 
-static void free_pg_vec(unsigned long *pg_vec, unsigned order, unsigned len)
+static inline struct page *pg_vec_endpage(char *one_pg_vec, unsigned int order)
+{
+	return virt_to_page(one_pg_vec + (PAGE_SIZE << order) - 1);
+}
+
+static void free_pg_vec(char **pg_vec, unsigned order, unsigned len)
 {
 	int i;
 
@@ -1556,10 +1565,10 @@ static void free_pg_vec(unsigned long *pg_vec, unsigned order, unsigned len)
 		if (pg_vec[i]) {
 			struct page *page, *pend;
 
-			pend = virt_to_page(pg_vec[i] + (PAGE_SIZE << order) - 1);
+			pend = pg_vec_endpage(pg_vec[i], order);
 			for (page = virt_to_page(pg_vec[i]); page <= pend; page++)
 				ClearPageReserved(page);
-			free_pages(pg_vec[i], order);
+			free_pages((unsigned long)pg_vec[i], order);
 		}
 	}
 	kfree(pg_vec);
@@ -1568,7 +1577,7 @@ static void free_pg_vec(unsigned long *pg_vec, unsigned order, unsigned len)
 
 static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing)
 {
-	unsigned long *pg_vec = NULL;
+	char **pg_vec = NULL;
 	struct packet_opt *po = pkt_sk(sk);
 	int was_running, num, order = 0;
 	int err = 0;
@@ -1603,18 +1612,18 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing
 
 		err = -ENOMEM;
 
-		pg_vec = kmalloc(req->tp_block_nr*sizeof(unsigned long*), GFP_KERNEL);
+		pg_vec = kmalloc(req->tp_block_nr*sizeof(char *), GFP_KERNEL);
 		if (pg_vec == NULL)
 			goto out;
-		memset(pg_vec, 0, req->tp_block_nr*sizeof(unsigned long*));
+		memset(pg_vec, 0, req->tp_block_nr*sizeof(char **));
 
 		for (i=0; i<req->tp_block_nr; i++) {
 			struct page *page, *pend;
-			pg_vec[i] = __get_free_pages(GFP_KERNEL, order);
+			pg_vec[i] = (char *)__get_free_pages(GFP_KERNEL, order);
 			if (!pg_vec[i])
 				goto out_free_pgvec;
 
-			pend = virt_to_page(pg_vec[i] + (PAGE_SIZE << order) - 1);
+			pend = pg_vec_endpage(pg_vec[i], order);
 			for (page = virt_to_page(pg_vec[i]); page <= pend; page++)
 				SetPageReserved(page);
 		}
@@ -1622,7 +1631,7 @@ static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing
 
 		l = 0;
 		for (i=0; i<req->tp_block_nr; i++) {
-			unsigned long ptr = pg_vec[i];
+			char *ptr = pg_vec[i];
 			struct tpacket_hdr *header;
 			int k;
 
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 31c4ab77e..4f6a9fab4 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -882,7 +882,6 @@ static int rose_accept(struct socket *sock, struct socket *newsock, int flags)
 	remove_wait_queue(sk->sk_sleep, &wait);
 
 	newsk = skb->sk;
-	newsk->sk_pair = NULL;
 	newsk->sk_socket = newsock;
 	newsk->sk_sleep = &newsock->wait;
 
@@ -996,7 +995,6 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros
 	make_rose->vr        = 0;
 	make_rose->vl        = 0;
 	sk->sk_ack_backlog++;
-	make->sk_pair = sk;
 
 	rose_insert_socket(make);
 
diff --git a/net/rxrpc/call.c b/net/rxrpc/call.c
index 6c87fcaec..dfb65d87f 100644
--- a/net/rxrpc/call.c
+++ b/net/rxrpc/call.c
@@ -472,7 +472,7 @@ static inline int __rxrpc_call_gen_normal_ACK(struct rxrpc_call *call,
 {
 	struct rxrpc_message *msg;
 	struct kvec diov[3];
-	unsigned aux[4];
+	__be32 aux[4];
 	int delta, ret;
 
 	/* ACKs default to DELAY */
@@ -840,7 +840,7 @@ static int __rxrpc_call_abort(struct rxrpc_call *call, int errno)
 	struct rxrpc_message *msg;
 	struct kvec diov[1];
 	int ret;
-	u32 _error;
+	__be32 _error;
 
 	_enter("%p{%08x},%p{%d},%d",
 	       conn, ntohl(conn->conn_id), call, ntohl(call->call_id), errno);
@@ -929,7 +929,6 @@ static void rxrpc_call_receive_packet(struct rxrpc_call *call)
 {
 	struct rxrpc_message *msg;
 	struct list_head *_p;
-	uint32_t data32;
 
 	_enter("%p", call);
 
@@ -986,22 +985,21 @@ static void rxrpc_call_receive_packet(struct rxrpc_call *call)
 			break;
 
 			/* deal with abort packets */
-		case RXRPC_PACKET_TYPE_ABORT:
-			data32 = 0;
-			if (skb_copy_bits(msg->pkt, msg->offset,
-					  &data32, sizeof(data32)) < 0) {
+		case RXRPC_PACKET_TYPE_ABORT: {
+			__be32 _dbuf, *dp;
+
+			dp = skb_header_pointer(msg->pkt, msg->offset,
+						sizeof(_dbuf), &_dbuf);
+			if (dp == NULL)
 				printk("Rx Received short ABORT packet\n");
-			}
-			else {
-				data32 = ntohl(data32);
-			}
 
-			_proto("Rx Received Call ABORT { data=%d }", data32);
+			_proto("Rx Received Call ABORT { data=%d }",
+			       (dp ? ntohl(*dp) : 0));
 
 			spin_lock(&call->lock);
 			call->app_call_state	= RXRPC_CSTATE_ERROR;
 			call->app_err_state	= RXRPC_ESTATE_PEER_ABORT;
-			call->app_abort_code	= data32;
+			call->app_abort_code	= (dp ? ntohl(*dp) : 0);
 			call->app_errno		= -ECONNABORTED;
 			call->app_mark		= RXRPC_APP_MARK_EOF;
 			call->app_read_buf	= NULL;
@@ -1013,7 +1011,7 @@ static void rxrpc_call_receive_packet(struct rxrpc_call *call)
 			spin_unlock(&call->lock);
 			call->app_error_func(call);
 			break;
-
+		}
 		default:
 			/* deal with other packet types */
 			_proto("Rx Unsupported packet type %u (#%u)",
@@ -1050,7 +1048,7 @@ static void rxrpc_call_receive_data_packet(struct rxrpc_call *call,
 	struct rxrpc_message *pmsg;
 	struct list_head *_p;
 	int ret, lo, hi, rmtimo;
-	u32 opid;
+	__be32 opid;
 
 	_enter("%p{%u},%p{%u}", call, ntohl(call->call_id), msg, msg->seq);
 
@@ -1271,41 +1269,42 @@ static void rxrpc_call_receive_data_packet(struct rxrpc_call *call,
 static void rxrpc_call_receive_ack_packet(struct rxrpc_call *call,
 					  struct rxrpc_message *msg)
 {
-	struct rxrpc_ackpacket ack;
-	rxrpc_serial_t serial;
+	struct rxrpc_ackpacket _ack, *ap;
+	rxrpc_serial_net_t serial;
 	rxrpc_seq_t seq;
 	int ret;
 
 	_enter("%p{%u},%p{%u}", call, ntohl(call->call_id), msg, msg->seq);
 
 	/* extract the basic ACK record */
-	if (skb_copy_bits(msg->pkt, msg->offset, &ack, sizeof(ack)) < 0) {
+	ap = skb_header_pointer(msg->pkt, msg->offset, sizeof(_ack), &_ack);
+	if (ap == NULL) {
 		printk("Rx Received short ACK packet\n");
 		return;
 	}
-	msg->offset += sizeof(ack);
+	msg->offset += sizeof(_ack);
 
-	serial = ack.serial;
-	seq = ntohl(ack.firstPacket);
+	serial = ap->serial;
+	seq = ntohl(ap->firstPacket);
 
 	_proto("Rx Received ACK %%%d { b=%hu m=%hu f=%u p=%u s=%u r=%s n=%u }",
 	       ntohl(msg->hdr.serial),
-	       ntohs(ack.bufferSpace),
-	       ntohs(ack.maxSkew),
+	       ntohs(ap->bufferSpace),
+	       ntohs(ap->maxSkew),
 	       seq,
-	       ntohl(ack.previousPacket),
+	       ntohl(ap->previousPacket),
 	       ntohl(serial),
-	       rxrpc_acks[ack.reason],
+	       rxrpc_acks[ap->reason],
 	       call->ackr.nAcks
 	       );
 
 	/* check the other side isn't ACK'ing a sequence number I haven't sent
 	 * yet */
-	if (ack.nAcks > 0 &&
+	if (ap->nAcks > 0 &&
 	    (seq > call->snd_seq_count ||
-	     seq + ack.nAcks - 1 > call->snd_seq_count)) {
+	     seq + ap->nAcks - 1 > call->snd_seq_count)) {
 		printk("Received ACK (#%u-#%u) for unsent packet\n",
-		       seq, seq + ack.nAcks - 1);
+		       seq, seq + ap->nAcks - 1);
 		rxrpc_call_abort(call, -EINVAL);
 		_leave("");
 		return;
@@ -1354,7 +1353,7 @@ static void rxrpc_call_receive_ack_packet(struct rxrpc_call *call,
 		}
 	}
 
-	switch (ack.reason) {
+	switch (ap->reason) {
 		/* deal with negative/positive acknowledgement of data
 		 * packets */
 	case RXRPC_ACK_REQUESTED:
@@ -1366,14 +1365,14 @@ static void rxrpc_call_receive_ack_packet(struct rxrpc_call *call,
 	case RXRPC_ACK_OUT_OF_SEQUENCE:
 	case RXRPC_ACK_EXCEEDS_WINDOW:
 		call->snd_resend_cnt = 0;
-		ret = rxrpc_call_record_ACK(call, msg, seq, ack.nAcks);
+		ret = rxrpc_call_record_ACK(call, msg, seq, ap->nAcks);
 		if (ret < 0)
 			rxrpc_call_abort(call, ret);
 		break;
 
 		/* respond to ping packets immediately */
 	case RXRPC_ACK_PING:
-		rxrpc_call_generate_ACK(call, &msg->hdr, &ack);
+		rxrpc_call_generate_ACK(call, &msg->hdr, ap);
 		break;
 
 		/* only record RTT on ping response packets */
@@ -1386,7 +1385,7 @@ static void rxrpc_call_receive_ack_packet(struct rxrpc_call *call,
 			rttmsg = NULL;
 			spin_lock(&call->lock);
 			if (call->snd_ping &&
-			    call->snd_ping->hdr.serial == ack.serial) {
+			    call->snd_ping->hdr.serial == ap->serial) {
 				rttmsg = call->snd_ping;
 				call->snd_ping = NULL;
 			}
@@ -1402,7 +1401,7 @@ static void rxrpc_call_receive_ack_packet(struct rxrpc_call *call,
 		break;
 
 	default:
-		printk("Unsupported ACK reason %u\n", ack.reason);
+		printk("Unsupported ACK reason %u\n", ap->reason);
 		break;
 	}
 
diff --git a/net/rxrpc/connection.c b/net/rxrpc/connection.c
index 929b82f48..a978007bf 100644
--- a/net/rxrpc/connection.c
+++ b/net/rxrpc/connection.c
@@ -88,8 +88,8 @@ static inline int __rxrpc_create_connection(struct rxrpc_peer *peer,
  * create a new connection record for outgoing connections
  */
 int rxrpc_create_connection(struct rxrpc_transport *trans,
-			    uint16_t port,
-			    uint32_t addr,
+			    __be16 port,
+			    __be32 addr,
 			    uint16_t service_id,
 			    void *security,
 			    struct rxrpc_connection **_conn)
@@ -97,7 +97,7 @@ int rxrpc_create_connection(struct rxrpc_transport *trans,
 	struct rxrpc_connection *candidate, *conn;
 	struct rxrpc_peer *peer;
 	struct list_head *_p;
-	uint32_t connid;
+	__be32 connid;
 	int ret;
 
 	_enter("%p{%hu},%u,%hu", trans, trans->port, ntohs(port), service_id);
@@ -169,7 +169,7 @@ int rxrpc_create_connection(struct rxrpc_transport *trans,
 	spin_unlock(&peer->conn_gylock);
 
 	/* pick the new candidate */
-	_debug("created connection: {%08x} [out]", htonl(candidate->conn_id));
+	_debug("created connection: {%08x} [out]", ntohl(candidate->conn_id));
 	atomic_inc(&peer->conn_count);
 	conn = candidate;
 	candidate = NULL;
@@ -199,7 +199,7 @@ int rxrpc_create_connection(struct rxrpc_transport *trans,
 
 	/* handle resurrecting a connection from the graveyard */
  found_in_graveyard:
-	_debug("resurrecting connection: {%08x} [out]", htonl(conn->conn_id));
+	_debug("resurrecting connection: {%08x} [out]", ntohl(conn->conn_id));
 	rxrpc_get_connection(conn);
 	rxrpc_krxtimod_del_timer(&conn->timeout);
 	list_del_init(&conn->link);
@@ -219,8 +219,9 @@ int rxrpc_connection_lookup(struct rxrpc_peer *peer,
 	struct rxrpc_connection *conn, *candidate = NULL;
 	struct list_head *_p;
 	int ret, fresh = 0;
-	u32 x_epoch, x_connid;
-	u16 x_port, x_secix, x_servid;
+	__be32 x_epoch, x_connid;
+	__be16 x_port, x_servid;
+	__u32 x_secix;
 	u8 x_clflag;
 
 	_enter("%p{{%hu}},%u,%hu",
@@ -310,7 +311,7 @@ int rxrpc_connection_lookup(struct rxrpc_peer *peer,
 	}
 
 	/* we can now add the new candidate to the list */
-	_debug("created connection: {%08x} [in]", htonl(candidate->conn_id));
+	_debug("created connection: {%08x} [in]", ntohl(candidate->conn_id));
 	rxrpc_get_peer(peer);
 	conn = candidate;
 	candidate = NULL;
@@ -351,7 +352,7 @@ int rxrpc_connection_lookup(struct rxrpc_peer *peer,
 
 	/* handle resurrecting a connection from the graveyard */
  found_in_graveyard:
-	_debug("resurrecting connection: {%08x} [in]", htonl(conn->conn_id));
+	_debug("resurrecting connection: {%08x} [in]", ntohl(conn->conn_id));
 	rxrpc_get_peer(peer);
 	rxrpc_get_connection(conn);
 	rxrpc_krxtimod_del_timer(&conn->timeout);
@@ -397,7 +398,7 @@ void rxrpc_put_connection(struct rxrpc_connection *conn)
 	}
 
 	/* move to graveyard queue */
-	_debug("burying connection: {%08x}", htonl(conn->conn_id));
+	_debug("burying connection: {%08x}", ntohl(conn->conn_id));
 	list_del(&conn->link);
 	list_add_tail(&conn->link, &peer->conn_graveyard);
 
@@ -442,7 +443,7 @@ void rxrpc_conn_do_timeout(struct rxrpc_connection *conn)
 	}
 
 	_debug("--- Destroying Connection %p{%08x} ---",
-	       conn, htonl(conn->conn_id));
+	       conn, ntohl(conn->conn_id));
 
 	down_write(&rxrpc_conns_sem);
 	list_del(&conn->proc_link);
@@ -640,8 +641,8 @@ int rxrpc_conn_sendmsg(struct rxrpc_connection *conn,
 	_net("Sending message type %d of %Zd bytes to %08x:%d",
 	     msg->hdr.type,
 	     msg->dsize,
-	     htonl(conn->addr.sin_addr.s_addr),
-	     htons(conn->addr.sin_port));
+	     ntohl(conn->addr.sin_addr.s_addr),
+	     ntohs(conn->addr.sin_port));
 
 	/* send the message */
 	ret = kernel_sendmsg(conn->trans->socket, &msghdr,
@@ -699,11 +700,11 @@ int rxrpc_conn_receive_call_packet(struct rxrpc_connection *conn,
 	}
 
 	_proto("Received packet %%%u [%u] on call %hu:%u:%u",
-	       htonl(msg->hdr.serial),
-	       htonl(msg->hdr.seq),
-	       htons(msg->hdr.serviceId),
-	       htonl(conn->conn_id),
-	       htonl(call->call_id));
+	       ntohl(msg->hdr.serial),
+	       ntohl(msg->hdr.seq),
+	       ntohs(msg->hdr.serviceId),
+	       ntohl(conn->conn_id),
+	       ntohl(call->call_id));
 
 	call->pkt_rcv_count++;
 
diff --git a/net/rxrpc/main.c b/net/rxrpc/main.c
index 21623a90b..966667ff6 100644
--- a/net/rxrpc/main.c
+++ b/net/rxrpc/main.c
@@ -32,7 +32,7 @@ MODULE_DESCRIPTION("Rx RPC implementation");
 MODULE_AUTHOR("Red Hat, Inc.");
 MODULE_LICENSE("GPL");
 
-uint32_t rxrpc_epoch;
+__be32 rxrpc_epoch;
 
 /*****************************************************************************/
 /*
diff --git a/net/rxrpc/peer.c b/net/rxrpc/peer.c
index a0665d629..e5c9f12d7 100644
--- a/net/rxrpc/peer.c
+++ b/net/rxrpc/peer.c
@@ -48,7 +48,7 @@ static const struct rxrpc_timer_ops rxrpc_peer_timer_ops = {
 /*
  * create a peer record
  */
-static int __rxrpc_create_peer(struct rxrpc_transport *trans, uint32_t addr,
+static int __rxrpc_create_peer(struct rxrpc_transport *trans, __be32 addr,
 			       struct rxrpc_peer **_peer)
 {
 	struct rxrpc_peer *peer;
@@ -96,7 +96,7 @@ static int __rxrpc_create_peer(struct rxrpc_transport *trans, uint32_t addr,
  * - returns (if successful) with peer record usage incremented
  * - resurrects it from the graveyard if found there
  */
-int rxrpc_peer_lookup(struct rxrpc_transport *trans, uint32_t addr,
+int rxrpc_peer_lookup(struct rxrpc_transport *trans, __be32 addr,
 		      struct rxrpc_peer **_peer)
 {
 	struct rxrpc_peer *peer, *candidate = NULL;
diff --git a/net/rxrpc/transport.c b/net/rxrpc/transport.c
index 577001512..7e015ceec 100644
--- a/net/rxrpc/transport.c
+++ b/net/rxrpc/transport.c
@@ -457,8 +457,8 @@ void rxrpc_trans_receive_packet(struct rxrpc_transport *trans)
 	struct rxrpc_peer *peer;
 	struct sk_buff *pkt;
 	int ret;
-	u32 addr;
-	u16 port;
+	__be32 addr;
+	__be16 port;
 
 	LIST_HEAD(msgq);
 
@@ -612,7 +612,7 @@ int rxrpc_trans_immediate_abort(struct rxrpc_transport *trans,
 	struct sockaddr_in sin;
 	struct msghdr msghdr;
 	struct kvec iov[2];
-	uint32_t _error;
+	__be32 _error;
 	int len, ret;
 
 	_enter("%p,%p,%d", trans, msg, error);
@@ -655,8 +655,8 @@ int rxrpc_trans_immediate_abort(struct rxrpc_transport *trans,
 	_net("Sending message type %d of %d bytes to %08x:%d",
 	     ahdr.type,
 	     len,
-	     htonl(sin.sin_addr.s_addr),
-	     htons(sin.sin_port));
+	     ntohl(sin.sin_addr.s_addr),
+	     ntohs(sin.sin_port));
 
 	/* send the message */
 	ret = kernel_sendmsg(trans->socket, &msghdr, iov, 2, len);
@@ -678,7 +678,7 @@ static void rxrpc_trans_receive_error_report(struct rxrpc_transport *trans)
 	struct list_head connq, *_p;
 	struct errormsg emsg;
 	struct msghdr msg;
-	uint16_t port;
+	__be16 port;
 	int local, err;
 
 	_enter("%p", trans);
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 97a42d9ed..c0df054b5 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -317,7 +317,7 @@ config NET_CLS_U32
 	  module will be called cls_u32.
 
 config CLS_U32_PERF
-	bool "     U32 classifier performance counters"
+	bool "U32 classifier performance counters"
 	depends on NET_CLS_U32
 	help
 	  gathers stats that could be used to tune u32 classifier performance.
@@ -364,7 +364,7 @@ config NET_CLS_RSVP6
 	  module will be called cls_rsvp6.
 
 config NET_CLS_ACT
-	bool '  Packet ACTION ' 
+	bool "Packet ACTION"
 	depends on EXPERIMENTAL && NET_CLS && NET_QOS
 	---help---
 	This option requires you have a new iproute2. It enables
@@ -373,7 +373,7 @@ config NET_CLS_ACT
 	  You MUST NOT turn this on if you dont have an update iproute2.
 
 config NET_ACT_POLICE
-	tristate '      Policing Actions' 
+	tristate "Policing Actions"
         depends on NET_CLS_ACT 
         ---help---
         If you are using a newer iproute2 select this one, otherwise use one
@@ -387,3 +387,15 @@ config NET_CLS_POLICE
 	  Say Y to support traffic policing (bandwidth limits).  Needed for
 	  ingress and egress rate limiting.
 
+config NET_ACT_GACT
+        tristate "generic Actions"
+        depends on NET_CLS_ACT
+        ---help---
+        You must have new iproute2 to use this feature
+        This adds simple filtering actions like drop,accepet etc 
+                                                                                
+config GACT_PROB
+        bool "generic Actions probability"
+        depends on NET_ACT_GACT
+        ---help---
+        Allows generic actions to be randomly  or deterministically used
diff --git a/net/sched/Makefile b/net/sched/Makefile
index daa437f85..912677ad0 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -8,8 +8,9 @@ obj-$(CONFIG_NET_SCHED)		+= sch_api.o sch_fifo.o
 obj-$(CONFIG_NET_ESTIMATOR)	+= estimator.o
 obj-$(CONFIG_NET_CLS)		+= cls_api.o
 obj-$(CONFIG_NET_CLS_ACT)       += act_api.o
-obj-$(CONFIG_NET_ACT_POLICE)    += police.o
-obj-$(CONFIG_NET_CLS_POLICE)    += police.o
+obj-$(CONFIG_NET_ACT_POLICE)	+= police.o
+obj-$(CONFIG_NET_CLS_POLICE)	+= police.o
+obj-$(CONFIG_NET_ACT_GACT)      += gact.o
 obj-$(CONFIG_NET_SCH_CBQ)	+= sch_cbq.o
 obj-$(CONFIG_NET_SCH_HTB)	+= sch_htb.o
 obj-$(CONFIG_NET_SCH_HPFQ)	+= sch_hpfq.o
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 58d37d6bd..b189f5a28 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -155,7 +155,7 @@ struct tc_action_ops *tc_lookup_action_id(u32 type)
 	return a;
 }
 
-int tcf_action_exec(struct sk_buff *skb,struct tc_action *act)
+int tcf_action_exec(struct sk_buff *skb,struct tc_action *act, struct tcf_result *res)
 {
 
 	struct tc_action *a;
@@ -164,7 +164,8 @@ int tcf_action_exec(struct sk_buff *skb,struct tc_action *act)
 	if (skb->tc_verd & TC_NCLS) {
 		skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
 		D2PRINTK("(%p)tcf_action_exec: cleared TC_NCLS in %s out %s\n",skb,skb->input_dev?skb->input_dev->name:"xxx",skb->dev->name);
-		return TC_ACT_OK;
+		ret = TC_ACT_OK;
+		goto exec_done;
 	}
 	while ((a = act) != NULL) {
 repeat:
@@ -186,6 +187,11 @@ repeat:
 	}
 
 exec_done:
+	if (skb->tc_classid > 0) {
+		res->classid = skb->tc_classid;
+		res->class = 0;
+		skb->tc_classid = 0;
+	}
 
 	return ret;
 }
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index e76951381..71c85ad84 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -139,7 +139,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 	struct tcf_proto_ops *tp_ops;
 	struct Qdisc_class_ops *cops;
 	unsigned long cl = 0;
-	unsigned long fh, fh_s;
+	unsigned long fh;
 	int err;
 
 	if (prio == 0) {
@@ -231,8 +231,12 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 		tp->classify = tp_ops->classify;
 		tp->classid = parent;
 		err = -EBUSY;
-		if (!try_module_get(tp_ops->owner) ||
-		    (err = tp_ops->init(tp)) != 0) {
+		if (!try_module_get(tp_ops->owner)) {
+			kfree(tp);
+			goto errout;
+		}
+		if ((err = tp_ops->init(tp)) != 0) {
+			module_put(tp_ops->owner);
 			kfree(tp);
 			goto errout;
 		}
@@ -245,7 +249,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 	} else if (tca[TCA_KIND-1] && rtattr_strcmp(tca[TCA_KIND-1], tp->ops->kind))
 		goto errout;
 
-	fh_s = fh = tp->ops->get(tp, t->tcm_handle);
+	fh = tp->ops->get(tp, t->tcm_handle);
 
 	if (fh == 0) {
 		if (n->nlmsg_type == RTM_DELTFILTER && t->tcm_handle == 0) {
@@ -253,7 +257,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 			*back = tp->next;
 			qdisc_unlock_tree(dev);
 
-			tfilter_notify(skb, n, tp, fh_s, RTM_DELTFILTER);
+			tfilter_notify(skb, n, tp, fh, RTM_DELTFILTER);
 			tcf_destroy(tp);
 			err = 0;
 			goto errout;
@@ -272,7 +276,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 		case RTM_DELTFILTER:
 			err = tp->ops->delete(tp, fh);
 			if (err == 0)
-				tfilter_notify(skb, n, tp, fh_s, RTM_DELTFILTER);
+				tfilter_notify(skb, n, tp, fh, RTM_DELTFILTER);
 			goto errout;
 		case RTM_GETTFILTER:
 			err = tfilter_notify(skb, n, tp, fh, RTM_NEWTFILTER);
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index 7ce360d31..3ef250827 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -102,7 +102,7 @@ static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp,
 			}
 #endif
                                if (f->action) {
-                                       int pol_res = tcf_action_exec(skb, f->action);
+                                       int pol_res = tcf_action_exec(skb, f->action, res);
                                        if (pol_res >= 0)
                                                return pol_res;
                                } else
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 30d26d4fe..bfe785eb0 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -175,12 +175,7 @@ check_terminal:
 #endif
 #ifdef CONFIG_NET_CLS_ACT
 				if (n->action) {
-					int pol_res = tcf_action_exec(skb, n->action);
-					if (skb->tc_classid > 0) {
-						res->classid = skb->tc_classid;
-						skb->tc_classid = 0;
-					}
-
+					int pol_res = tcf_action_exec(skb, n->action, res);
 					if (pol_res >= 0)
 						return pol_res;
 				} else
diff --git a/net/sched/estimator.c b/net/sched/estimator.c
index 393496b2f..17eb0798b 100644
--- a/net/sched/estimator.c
+++ b/net/sched/estimator.c
@@ -66,15 +66,11 @@
 
    * Minimal interval is HZ/4=250msec (it is the greatest common divisor
      for HZ=100 and HZ=1024 8)), maximal interval
-     is (HZ/4)*2^EST_MAX_INTERVAL = 8sec. Shorter intervals
+     is (HZ*2^EST_MAX_INTERVAL)/4 = 8sec. Shorter intervals
      are too expensive, longer ones can be implemented
      at user level painlessly.
  */
 
-#if (HZ%4) != 0
-#error Bad HZ value.
-#endif
-
 #define EST_MAX_INTERVAL	5
 
 struct qdisc_estimator
@@ -128,7 +124,7 @@ static void est_timer(unsigned long arg)
 		spin_unlock(e->stats_lock);
 	}
 
-	mod_timer(&elist[idx].timer, jiffies + ((HZ/4)<<idx));
+	mod_timer(&elist[idx].timer, jiffies + ((HZ<<idx)/4));
 	read_unlock(&est_lock);
 }
 
@@ -161,7 +157,7 @@ int qdisc_new_estimator(struct tc_stats *stats, spinlock_t *stats_lock, struct r
 	if (est->next == NULL) {
 		init_timer(&elist[est->interval].timer);
 		elist[est->interval].timer.data = est->interval;
-		elist[est->interval].timer.expires = jiffies + ((HZ/4)<<est->interval);
+		elist[est->interval].timer.expires = jiffies + ((HZ<<est->interval)/4);
 		elist[est->interval].timer.function = est_timer;
 		add_timer(&elist[est->interval].timer);
 	}
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 1f9bf9d08..5da7b7312 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -371,6 +371,8 @@ int qdisc_graft(struct net_device *dev, struct Qdisc *parent, u32 classid,
 			unsigned long cl = cops->get(parent, classid);
 			if (cl) {
 				err = cops->graft(parent, cl, new, old);
+				if (new)
+					new->parent = classid;
 				cops->put(parent, cl);
 			}
 		}
@@ -389,7 +391,8 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
 {
 	int err;
 	struct rtattr *kind = tca[TCA_KIND-1];
-	struct Qdisc *sch = NULL;
+	void *p = NULL;
+	struct Qdisc *sch;
 	struct Qdisc_ops *ops;
 	int size;
 
@@ -406,21 +409,22 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
 	err = -EINVAL;
 	if (ops == NULL)
 		goto err_out;
-
-	size = sizeof(*sch) + ops->priv_size;
-
-	sch = kmalloc(size, GFP_KERNEL);
-	err = -ENOBUFS;
-	if (!sch)
+	err = -EBUSY;
+	if (!try_module_get(ops->owner))
 		goto err_out;
 
-	/* Grrr... Resolve race condition with module unload */
-
-	err = -EINVAL;
-	if (ops != qdisc_lookup_ops(kind))
-		goto err_out;
+	/* ensure that the Qdisc and the private data are 32-byte aligned */
+	size = ((sizeof(*sch) + QDISC_ALIGN_CONST) & ~QDISC_ALIGN_CONST);
+	size += ops->priv_size + QDISC_ALIGN_CONST;
 
-	memset(sch, 0, size);
+	p = kmalloc(size, GFP_KERNEL);
+	err = -ENOBUFS;
+	if (!p)
+		goto err_out2;
+	memset(p, 0, size);
+	sch = (struct Qdisc *)(((unsigned long)p + QDISC_ALIGN_CONST)
+	                       & ~QDISC_ALIGN_CONST);
+	sch->padded = (char *)sch - (char *)p;
 
 	INIT_LIST_HEAD(&sch->list);
 	skb_queue_head_init(&sch->q);
@@ -439,7 +443,7 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
 		handle = qdisc_alloc_handle(dev);
 		err = -ENOMEM;
 		if (handle == 0)
-			goto err_out;
+			goto err_out3;
 	}
 
 	if (handle == TC_H_INGRESS)
@@ -447,10 +451,6 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
         else
                 sch->handle = handle;
 
-	err = -EBUSY;
-	if (!try_module_get(ops->owner))
-		goto err_out;
-
 	/* enqueue is accessed locklessly - make sure it's visible
 	 * before we set a netdevice's qdisc pointer to sch */
 	smp_wmb();
@@ -466,12 +466,14 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
 #endif
 		return sch;
 	}
+err_out3:
+	dev_put(dev);
+err_out2:
 	module_put(ops->owner);
-
 err_out:
 	*errp = err;
-	if (sch)
-		kfree(sch);
+	if (p)
+		kfree(p);
 	return NULL;
 }
 
@@ -821,7 +823,7 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
 				q_idx++;
 				continue;
 			}
-			if (tc_fill_qdisc(skb, q, 0, NETLINK_CB(cb->skb).pid,
+			if (tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).pid,
 					  cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0) {
 				read_unlock_bh(&qdisc_tree_lock);
 				goto done;
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index ca08449e7..ff61f8e69 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -573,7 +573,6 @@ static int atm_tc_init(struct Qdisc *sch,struct rtattr *opt)
 	struct atm_qdisc_data *p = PRIV(sch);
 
 	DPRINTK("atm_tc_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
-	memset(p,0,sizeof(*p));
 	p->flows = &p->link;
 	if(!(p->link.q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops)))
 		p->link.q = &noop_qdisc;
@@ -715,3 +714,4 @@ static void __exit atm_exit(void)
 
 module_init(atm_init)
 module_exit(atm_exit)
+MODULE_LICENSE("GPL");
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 01dfcb1ab..2ae73826d 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1675,7 +1675,6 @@ cbq_dump_class(struct Qdisc *sch, unsigned long arg,
 	cl->xstats.undertime = 0;
 	if (!PSCHED_IS_PASTPERFECT(cl->undertime))
 		cl->xstats.undertime = PSCHED_TDIFF(cl->undertime, q->now);
-	q->link.xstats.avgidle = q->link.avgidle;
 	if (cbq_copy_xstats(skb, &cl->xstats)) {
 		spin_unlock_bh(&sch->dev->queue_lock);
 		goto rtattr_failure;
@@ -1746,15 +1745,18 @@ static void cbq_destroy_filters(struct cbq_class *cl)
 	}
 }
 
-static void cbq_destroy_class(struct cbq_class *cl)
+static void cbq_destroy_class(struct Qdisc *sch, struct cbq_class *cl)
 {
+	struct cbq_sched_data *q = qdisc_priv(sch);
+
 	cbq_destroy_filters(cl);
 	qdisc_destroy(cl->q);
 	qdisc_put_rtab(cl->R_tab);
 #ifdef CONFIG_NET_ESTIMATOR
 	qdisc_kill_estimator(&cl->stats);
 #endif
-	kfree(cl);
+	if (cl != &q->link)
+		kfree(cl);
 }
 
 static void
@@ -1767,22 +1769,15 @@ cbq_destroy(struct Qdisc* sch)
 #ifdef CONFIG_NET_CLS_POLICE
 	q->rx_class = NULL;
 #endif
-	for (h = 0; h < 16; h++) {
-		for (cl = q->classes[h]; cl; cl = cl->next)
-			cbq_destroy_filters(cl);
-	}
 
 	for (h = 0; h < 16; h++) {
 		struct cbq_class *next;
 
 		for (cl = q->classes[h]; cl; cl = next) {
 			next = cl->next;
-			if (cl != &q->link)
-				cbq_destroy_class(cl);
+			cbq_destroy_class(sch, cl);
 		}
 	}
-
-	qdisc_put_rtab(q->link.R_tab);
 }
 
 static void cbq_put(struct Qdisc *sch, unsigned long arg)
@@ -1799,7 +1794,7 @@ static void cbq_put(struct Qdisc *sch, unsigned long arg)
 		spin_unlock_bh(&sch->dev->queue_lock);
 #endif
 
-		cbq_destroy_class(cl);
+		cbq_destroy_class(sch, cl);
 	}
 }
 
@@ -2035,7 +2030,7 @@ static int cbq_delete(struct Qdisc *sch, unsigned long arg)
 	sch_tree_unlock(sch);
 
 	if (--cl->refcnt == 0)
-		cbq_destroy_class(cl);
+		cbq_destroy_class(sch, cl);
 
 	return 0;
 }
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index e0831a4a4..28b61f0f8 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -331,8 +331,6 @@ int dsmark_init(struct Qdisc *sch,struct rtattr *opt)
 	    !tb[TCA_DSMARK_INDICES-1] ||
 	    RTA_PAYLOAD(tb[TCA_DSMARK_INDICES-1]) < sizeof(__u16))
                 return -EINVAL;
-	memset(p,0,sizeof(*p));
-	p->filter_list = NULL;
 	p->indices = *(__u16 *) RTA_DATA(tb[TCA_DSMARK_INDICES-1]);
 	if (!p->indices)
 		return -EINVAL;
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 82117f9ba..2516dd92a 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -97,46 +97,71 @@ int qdisc_restart(struct net_device *dev)
 
 	/* Dequeue packet */
 	if ((skb = q->dequeue(q)) != NULL) {
-		if (spin_trylock(&dev->xmit_lock)) {
+		unsigned nolock = (dev->features & NETIF_F_LLTX);
+		/*
+		 * 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 (!spin_trylock(&dev->xmit_lock)) {
+			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);
+					return -1;
+				}
+				__get_cpu_var(netdev_rx_stat).cpu_collision++;
+				goto requeue;
+			}
 			/* Remember that the driver is grabbed by us. */
 			dev->xmit_lock_owner = smp_processor_id();
-
+		}
+		
+		{
 			/* And release queue */
 			spin_unlock(&dev->queue_lock);
 
 			if (!netif_queue_stopped(dev)) {
+				int ret;
 				if (netdev_nit)
 					dev_queue_xmit_nit(skb, dev);
 
-				if (dev->hard_start_xmit(skb, dev) == 0) {
-					dev->xmit_lock_owner = -1;
-					spin_unlock(&dev->xmit_lock);
-
+				ret = dev->hard_start_xmit(skb, dev);
+				if (ret == NETDEV_TX_OK) { 
+					if (!nolock) {
+						dev->xmit_lock_owner = -1;
+						spin_unlock(&dev->xmit_lock);
+					}
 					spin_lock(&dev->queue_lock);
 					return -1;
 				}
+				if (ret == NETDEV_TX_LOCKED && nolock) {
+					spin_lock(&dev->queue_lock);
+					goto collision; 
+				}
 			}
 
+			/* NETDEV_TX_BUSY - we need to requeue */
 			/* Release the driver */
-			dev->xmit_lock_owner = -1;
-			spin_unlock(&dev->xmit_lock);
+			if (!nolock) { 
+				dev->xmit_lock_owner = -1;
+				spin_unlock(&dev->xmit_lock);
+			} 
 			spin_lock(&dev->queue_lock);
 			q = dev->qdisc;
-		} else {
-			/* 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);
-				return -1;
-			}
-			__get_cpu_var(netdev_rx_stat).cpu_collision++;
 		}
 
 		/* Device kicked us out :(
@@ -149,6 +174,7 @@ int qdisc_restart(struct net_device *dev)
 		   3. device is buggy (ppp)
 		 */
 
+requeue:
 		q->ops->requeue(skb, q);
 		netif_schedule(dev);
 		return 1;
@@ -415,6 +441,7 @@ struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops)
 	if (!ops->init || ops->init(sch, NULL) == 0)
 		return sch;
 
+	dev_put(dev);
 	kfree(p);
 	return NULL;
 }
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 84ef3ab6a..fa1a9e549 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -62,6 +62,7 @@
 #include <linux/slab.h>
 #include <linux/timer.h>
 #include <linux/list.h>
+#include <linux/rbtree.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
@@ -133,9 +134,11 @@ struct hfsc_class
 	struct list_head children;	/* child classes */
 	struct Qdisc	*qdisc;		/* leaf qdisc */
 
-	struct list_head actlist;	/* active children list */
-	struct list_head alist;		/* active children list member */
-	struct list_head ellist;	/* eligible list member */
+	struct rb_node el_node;		/* qdisc's eligible tree member */
+	struct rb_root vt_tree;		/* active children sorted by cl_vt */
+	struct rb_node vt_node;		/* parent's vt_tree member */
+	struct rb_root cf_tree;		/* active children sorted by cl_f */
+	struct rb_node cf_node;		/* parent's cf_heap member */
 	struct list_head hlist;		/* hash list member */
 	struct list_head dlist;		/* drop list member */
 
@@ -161,6 +164,9 @@ struct hfsc_class
 					   adjustment */
 	u64	cl_vtoff;		/* inter-period cumulative vt offset */
 	u64	cl_cvtmax;		/* max child's vt in the last period */
+	u64	cl_cvtoff;		/* cumulative cvtmax of all periods */
+	u64	cl_pcvtoff;		/* parent's cvtoff at initalization
+					   time */
 
 	struct internal_sc cl_rsc;	/* internal real-time service curve */
 	struct internal_sc cl_fsc;	/* internal fair service curve */
@@ -183,7 +189,7 @@ struct hfsc_sched
 	u16	defcls;				/* default class id */
 	struct hfsc_class root;			/* root class */
 	struct list_head clhash[HFSC_HSIZE];	/* class hash */
-	struct list_head eligible;		/* eligible list */
+	struct rb_root eligible;		/* eligible tree */
 	struct list_head droplist;		/* active leaf class list (for
 						   dropping) */
 	struct sk_buff_head requeue;		/* requeued packet */
@@ -219,82 +225,51 @@ do {									\
 
 
 /*
- * eligible list holds backlogged classes being sorted by their eligible times.
- * there is one eligible list per hfsc instance.
+ * eligible tree holds backlogged classes being sorted by their eligible times.
+ * there is one eligible tree per hfsc instance.
  */
 
 static void
-ellist_insert(struct hfsc_class *cl)
+eltree_insert(struct hfsc_class *cl)
 {
-	struct list_head *head = &cl->sched->eligible;
-	struct hfsc_class *p;
+	struct rb_node **p = &cl->sched->eligible.rb_node;
+	struct rb_node *parent = NULL;
+	struct hfsc_class *cl1;
 
-	/* check the last entry first */
-	if (list_empty(head) ||
-	    ((p = list_entry(head->prev, struct hfsc_class, ellist)) &&
-	     p->cl_e <= cl->cl_e)) {
-		list_add_tail(&cl->ellist, head);
-		return;
-	}
-
-	list_for_each_entry(p, head, ellist) {
-		if (cl->cl_e < p->cl_e) {
-			/* insert cl before p */
-			list_add_tail(&cl->ellist, &p->ellist);
-			return;
-		}
+	while (*p != NULL) {
+		parent = *p;
+		cl1 = rb_entry(parent, struct hfsc_class, el_node);
+		if (cl->cl_e >= cl1->cl_e)
+			p = &parent->rb_right;
+		else
+			p = &parent->rb_left;
 	}
-	ASSERT(0); /* should not reach here */
+	rb_link_node(&cl->el_node, parent, p);
+	rb_insert_color(&cl->el_node, &cl->sched->eligible);
 }
 
 static inline void
-ellist_remove(struct hfsc_class *cl)
+eltree_remove(struct hfsc_class *cl)
 {
-	list_del(&cl->ellist);
+	rb_erase(&cl->el_node, &cl->sched->eligible);
 }
 
-static void
-ellist_update(struct hfsc_class *cl)
+static inline void
+eltree_update(struct hfsc_class *cl)
 {
-	struct list_head *head = &cl->sched->eligible;
-	struct hfsc_class *p, *last;
-
-	/*
-	 * the eligible time of a class increases monotonically.
-	 * if the next entry has a larger eligible time, nothing to do.
-	 */
-	if (cl->ellist.next == head ||
-	    ((p = list_entry(cl->ellist.next, struct hfsc_class, ellist)) &&
-	     cl->cl_e <= p->cl_e))
-		return;
-
-	/* check the last entry */
-	last = list_entry(head->prev, struct hfsc_class, ellist);
-	if (last->cl_e <= cl->cl_e) {
-		list_move_tail(&cl->ellist, head);
-		return;
-	}
-
-	/*
-	 * the new position must be between the next entry
-	 * and the last entry
-	 */
-	list_for_each_entry_continue(p, head, ellist) {
-		if (cl->cl_e < p->cl_e) {
-			list_move_tail(&cl->ellist, &p->ellist);
-			return;
-		}
-	}
-	ASSERT(0); /* should not reach here */
+	eltree_remove(cl);
+	eltree_insert(cl);
 }
 
 /* find the class with the minimum deadline among the eligible classes */
 static inline struct hfsc_class *
-ellist_get_mindl(struct list_head *head, u64 cur_time)
+eltree_get_mindl(struct hfsc_sched *q, u64 cur_time)
 {
 	struct hfsc_class *p, *cl = NULL;
+	struct rb_node *n;
 
-	list_for_each_entry(p, head, ellist) {
+	for (n = rb_first(&q->eligible); n != NULL; n = rb_next(n)) {
+		p = rb_entry(n, struct hfsc_class, el_node);
 		if (p->cl_e > cur_time)
 			break;
 		if (cl == NULL || p->cl_d < cl->cl_d)
@@ -305,92 +280,62 @@ ellist_get_mindl(struct list_head *head, u64 cur_time)
 
 /* find the class with minimum eligible time among the eligible classes */
 static inline struct hfsc_class *
-ellist_get_minel(struct list_head *head)
+eltree_get_minel(struct hfsc_sched *q)
 {
-	if (list_empty(head))
+	struct rb_node *n;
+	
+	n = rb_first(&q->eligible);
+	if (n == NULL)
 		return NULL;
-	return list_entry(head->next, struct hfsc_class, ellist);
+	return rb_entry(n, struct hfsc_class, el_node);
 }
 
 /*
- * active children list holds backlogged child classes being sorted
- * by their virtual time. each intermediate class has one active
- * children list.
+ * vttree holds holds backlogged child classes being sorted by their virtual
+ * time. each intermediate class has one vttree.
  */
 static void
-actlist_insert(struct hfsc_class *cl)
+vttree_insert(struct hfsc_class *cl)
 {
-	struct list_head *head = &cl->cl_parent->actlist;
-	struct hfsc_class *p;
+	struct rb_node **p = &cl->cl_parent->vt_tree.rb_node;
+	struct rb_node *parent = NULL;
+	struct hfsc_class *cl1;
 
-	/* check the last entry first */
-	if (list_empty(head) ||
-	    ((p = list_entry(head->prev, struct hfsc_class, alist)) &&
-	     p->cl_vt <= cl->cl_vt)) {
-		list_add_tail(&cl->alist, head);
-		return;
-	}
-
-	list_for_each_entry(p, head, alist) {
-		if (cl->cl_vt < p->cl_vt) {
-			/* insert cl before p */
-			list_add_tail(&cl->alist, &p->alist);
-			return;
-		}
+	while (*p != NULL) {
+		parent = *p;
+		cl1 = rb_entry(parent, struct hfsc_class, vt_node);
+		if (cl->cl_vt >= cl1->cl_vt)
+			p = &parent->rb_right;
+		else
+			p = &parent->rb_left;
 	}
-	ASSERT(0); /* should not reach here */
+	rb_link_node(&cl->vt_node, parent, p);
+	rb_insert_color(&cl->vt_node, &cl->cl_parent->vt_tree);
 }
 
 static inline void
-actlist_remove(struct hfsc_class *cl)
+vttree_remove(struct hfsc_class *cl)
 {
-	list_del(&cl->alist);
+	rb_erase(&cl->vt_node, &cl->cl_parent->vt_tree);
 }
 
-static void
-actlist_update(struct hfsc_class *cl)
+static inline void
+vttree_update(struct hfsc_class *cl)
 {
-	struct list_head *head = &cl->cl_parent->actlist;
-	struct hfsc_class *p, *last;
-
-	/*
-	 * the virtual time of a class increases monotonically.
-	 * if the next entry has a larger virtual time, nothing to do.
-	 */
-	if (cl->alist.next == head ||
-	    ((p = list_entry(cl->alist.next, struct hfsc_class, alist)) &&
-	     cl->cl_vt <= p->cl_vt))
-		return;
-
-	/* check the last entry */
-	last = list_entry(head->prev, struct hfsc_class, alist);
-	if (last->cl_vt <= cl->cl_vt) {
-		list_move_tail(&cl->alist, head);
-		return;
-	}
-
-	/*
-	 * the new position must be between the next entry
-	 * and the last entry
-	 */
-	list_for_each_entry_continue(p, head, alist) {
-		if (cl->cl_vt < p->cl_vt) {
-			list_move_tail(&cl->alist, &p->alist);
-			return;
-		}
-	}
-	ASSERT(0); /* should not reach here */
+	vttree_remove(cl);
+	vttree_insert(cl);
 }
 
 static inline struct hfsc_class *
-actlist_firstfit(struct hfsc_class *cl, u64 cur_time)
+vttree_firstfit(struct hfsc_class *cl, u64 cur_time)
 {
 	struct hfsc_class *p;
+	struct rb_node *n;
 
-	list_for_each_entry(p, &cl->actlist, alist) {
-		if (p->cl_f <= cur_time) {
+	for (n = rb_first(&cl->vt_tree); n != NULL; n = rb_next(n)) {
+		p = rb_entry(n, struct hfsc_class, vt_node);
+		if (p->cl_f <= cur_time)
 			return p;
-		}
 	}
 	return NULL;
 }
@@ -399,14 +344,14 @@ actlist_firstfit(struct hfsc_class *cl, u64 cur_time)
  * get the leaf class with the minimum vt in the hierarchy
  */
 static struct hfsc_class *
-actlist_get_minvt(struct hfsc_class *cl, u64 cur_time)
+vttree_get_minvt(struct hfsc_class *cl, u64 cur_time)
 {
 	/* if root-class's cfmin is bigger than cur_time nothing to do */
 	if (cl->cl_cfmin > cur_time)
 		return NULL;
 
 	while (cl->level > 0) {
-		cl = actlist_firstfit(cl, cur_time);
+		cl = vttree_firstfit(cl, cur_time);
 		if (cl == NULL)
 			return NULL;
 		/*
@@ -418,6 +363,38 @@ actlist_get_minvt(struct hfsc_class *cl, u64 cur_time)
 	return cl;
 }
 
+static void
+cftree_insert(struct hfsc_class *cl)
+{
+	struct rb_node **p = &cl->cl_parent->cf_tree.rb_node;
+	struct rb_node *parent = NULL;
+	struct hfsc_class *cl1;
+
+	while (*p != NULL) {
+		parent = *p;
+		cl1 = rb_entry(parent, struct hfsc_class, cf_node);
+		if (cl->cl_f >= cl1->cl_f)
+			p = &parent->rb_right;
+		else
+			p = &parent->rb_left;
+	}
+	rb_link_node(&cl->cf_node, parent, p);
+	rb_insert_color(&cl->cf_node, &cl->cl_parent->cf_tree);
+}
+
+static inline void
+cftree_remove(struct hfsc_class *cl)
+{
+	rb_erase(&cl->cf_node, &cl->cl_parent->cf_tree);
+}
+
+static inline void
+cftree_update(struct hfsc_class *cl)
+{
+	cftree_remove(cl);
+	cftree_insert(cl);
+}
+
 /*
  * service curve support functions
  *
@@ -711,7 +688,7 @@ init_ed(struct hfsc_class *cl, unsigned int next_len)
 	cl->cl_e = rtsc_y2x(&cl->cl_eligible, cl->cl_cumul);
 	cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len);
 
-	ellist_insert(cl);
+	eltree_insert(cl);
 }
 
 static void
@@ -720,7 +697,7 @@ update_ed(struct hfsc_class *cl, unsigned int next_len)
 	cl->cl_e = rtsc_y2x(&cl->cl_eligible, cl->cl_cumul);
 	cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len);
 
-	ellist_update(cl);
+	eltree_update(cl);
 }
 
 static inline void
@@ -729,32 +706,25 @@ update_d(struct hfsc_class *cl, unsigned int next_len)
 	cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len);
 }
 
-static void
+static inline void
 update_cfmin(struct hfsc_class *cl)
 {
+	struct rb_node *n = rb_first(&cl->cf_tree);
 	struct hfsc_class *p;
-	u64 cfmin;
 
-	if (list_empty(&cl->actlist)) {
+	if (n == NULL) {
 		cl->cl_cfmin = 0;
 		return;
 	}
-	cfmin = HT_INFINITY;
-	list_for_each_entry(p, &cl->actlist, alist) {
-		if (p->cl_f == 0) {
-			cl->cl_cfmin = 0;
-			return;
-		}
-		if (p->cl_f < cfmin)
-			cfmin = p->cl_f;
-	}
-	cl->cl_cfmin = cfmin;
+	p = rb_entry(n, struct hfsc_class, cf_node);
+	cl->cl_cfmin = p->cl_f;
 }
 
 static void
 init_vf(struct hfsc_class *cl, unsigned int len)
 {
-	struct hfsc_class *max_cl, *p;
+	struct hfsc_class *max_cl;
+	struct rb_node *n;
 	u64 vt, f, cur_time;
 	int go_active;
 
@@ -767,9 +737,9 @@ init_vf(struct hfsc_class *cl, unsigned int len)
 			go_active = 0;
 
 		if (go_active) {
-			if (!list_empty(&cl->cl_parent->actlist)) {
-				max_cl = list_entry(cl->cl_parent->actlist.prev,
-				                    struct hfsc_class, alist);
+			n = rb_last(&cl->cl_parent->vt_tree);
+			if (n != NULL) {
+				max_cl = rb_entry(n, struct hfsc_class,vt_node);
 				/*
 				 * set vt to the average of the min and max
 				 * classes.  if the parent's period didn't
@@ -785,19 +755,20 @@ init_vf(struct hfsc_class *cl, unsigned int len)
 			} else {
 				/*
 				 * first child for a new parent backlog period.
-				 * add parent's cvtmax to vtoff of children
-				 * to make a new vt (vtoff + vt) larger than
-				 * the vt in the last period for all children.
+				 * add parent's cvtmax to cvtoff to make a new
+				 * vt (vtoff + vt) larger than the vt in the
+				 * last period for all children.
 				 */
 				vt = cl->cl_parent->cl_cvtmax;
-				list_for_each_entry(p, &cl->cl_parent->children,
-				                                       siblings)
-					p->cl_vtoff += vt;
-				cl->cl_vt = 0;
+				cl->cl_parent->cl_cvtoff += vt;
 				cl->cl_parent->cl_cvtmax = 0;
 				cl->cl_parent->cl_cvtmin = 0;
+				cl->cl_vt = 0;
 			}
 
+			cl->cl_vtoff = cl->cl_parent->cl_cvtoff -
+							cl->cl_pcvtoff;
+
 			/* update the virtual curve */
 			vt = cl->cl_vt + cl->cl_vtoff;
 			rtsc_min(&cl->cl_virtual, &cl->cl_fsc, vt,
@@ -814,7 +785,8 @@ init_vf(struct hfsc_class *cl, unsigned int len)
 				cl->cl_parentperiod++;
 			cl->cl_f = 0;
 
-			actlist_insert(cl);
+			vttree_insert(cl);
+			cftree_insert(cl);
 
 			if (cl->cl_flags & HFSC_USC) {
 				/* class has upper limit curve */
@@ -834,6 +806,7 @@ init_vf(struct hfsc_class *cl, unsigned int len)
 		f = max(cl->cl_myf, cl->cl_cfmin);
 		if (f != cl->cl_f) {
 			cl->cl_f = f;
+			cftree_update(cl);
 			update_cfmin(cl->cl_parent);
 		}
 	}
@@ -866,9 +839,10 @@ update_vf(struct hfsc_class *cl, unsigned int len, u64 cur_time)
 			if (cl->cl_vt > cl->cl_parent->cl_cvtmax)
 				cl->cl_parent->cl_cvtmax = cl->cl_vt;
 
-			/* remove this class from the vt list */
-			actlist_remove(cl);
+			/* remove this class from the vt tree */
+			vttree_remove(cl);
 
+			cftree_remove(cl);
 			update_cfmin(cl->cl_parent);
 
 			continue;
@@ -890,8 +864,8 @@ update_vf(struct hfsc_class *cl, unsigned int len, u64 cur_time)
 			cl->cl_vt = cl->cl_parent->cl_cvtmin;
 		}
 
-		/* update the vt list */
-		actlist_update(cl);
+		/* update the vt tree */
+		vttree_update(cl);
 
 		if (cl->cl_flags & HFSC_USC) {
 			cl->cl_myf = cl->cl_myfadj + rtsc_y2x(&cl->cl_ulimit,
@@ -921,6 +895,7 @@ update_vf(struct hfsc_class *cl, unsigned int len, u64 cur_time)
 		f = max(cl->cl_myf, cl->cl_cfmin);
 		if (f != cl->cl_f) {
 			cl->cl_f = f;
+			cftree_update(cl);
 			update_cfmin(cl->cl_parent);
 		}
 	}
@@ -941,13 +916,13 @@ static void
 set_passive(struct hfsc_class *cl)
 {
 	if (cl->cl_flags & HFSC_RSC)
-		ellist_remove(cl);
+		eltree_remove(cl);
 
 	list_del(&cl->dlist);
 
 	/*
-	 * actlist is now handled in update_vf() so that update_vf(cl, 0, 0)
-	 * needs to be called explicitly to remove a class from actlist
+	 * vttree is now handled in update_vf() so that update_vf(cl, 0, 0)
+	 * needs to be called explicitly to remove a class from vttree.
 	 */
 }
 
@@ -1171,7 +1146,8 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
 		cl->qdisc = &noop_qdisc;
 	cl->stats_lock = &sch->dev->queue_lock;
 	INIT_LIST_HEAD(&cl->children);
-	INIT_LIST_HEAD(&cl->actlist);
+	cl->vt_tree = RB_ROOT;
+	cl->cf_tree = RB_ROOT;
 
 	sch_tree_lock(sch);
 	list_add_tail(&cl->hlist, &q->clhash[hfsc_hash(classid)]);
@@ -1179,6 +1155,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
 	if (parent->level == 0)
 		hfsc_purge_queue(sch, parent);
 	hfsc_adjust_levels(parent);
+	cl->cl_pcvtoff = parent->cl_cvtoff;
 	sch_tree_unlock(sch);
 
 #ifdef CONFIG_NET_ESTIMATOR
@@ -1528,7 +1505,7 @@ hfsc_schedule_watchdog(struct Qdisc *sch, u64 cur_time)
 	u64 next_time = 0;
 	long delay;
 
-	if ((cl = ellist_get_minel(&q->eligible)) != NULL)
+	if ((cl = eltree_get_minel(q)) != NULL)
 		next_time = cl->cl_e;
 	if (q->root.cl_cfmin != 0) {
 		if (next_time == 0 || next_time > q->root.cl_cfmin)
@@ -1553,13 +1530,12 @@ hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt)
 		return -EINVAL;
 	qopt = RTA_DATA(opt);
 
-	memset(q, 0, sizeof(struct hfsc_sched));
 	sch->stats_lock = &sch->dev->queue_lock;
 
 	q->defcls = qopt->defcls;
 	for (i = 0; i < HFSC_HSIZE; i++)
 		INIT_LIST_HEAD(&q->clhash[i]);
-	INIT_LIST_HEAD(&q->eligible);
+	q->eligible = RB_ROOT;
 	INIT_LIST_HEAD(&q->droplist);
 	skb_queue_head_init(&q->requeue);
 
@@ -1571,7 +1547,8 @@ hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt)
 		q->root.qdisc = &noop_qdisc;
 	q->root.stats_lock = &sch->dev->queue_lock;
 	INIT_LIST_HEAD(&q->root.children);
-	INIT_LIST_HEAD(&q->root.actlist);
+	q->root.vt_tree = RB_ROOT;
+	q->root.cf_tree = RB_ROOT;
 
 	list_add(&q->root.hlist, &q->clhash[hfsc_hash(q->root.classid)]);
 
@@ -1611,6 +1588,8 @@ hfsc_reset_class(struct hfsc_class *cl)
 	cl->cl_vtoff        = 0;
 	cl->cl_cvtmin       = 0;
 	cl->cl_cvtmax       = 0;
+	cl->cl_cvtoff       = 0;
+	cl->cl_pcvtoff      = 0;
 	cl->cl_vtperiod     = 0;
 	cl->cl_parentperiod = 0;
 	cl->cl_f            = 0;
@@ -1618,7 +1597,9 @@ hfsc_reset_class(struct hfsc_class *cl)
 	cl->cl_myfadj       = 0;
 	cl->cl_cfmin        = 0;
 	cl->cl_nactive      = 0;
-	INIT_LIST_HEAD(&cl->actlist);
+
+	cl->vt_tree = RB_ROOT;
+	cl->cf_tree = RB_ROOT;
 	qdisc_reset(cl->qdisc);
 
 	if (cl->cl_flags & HFSC_RSC)
@@ -1641,7 +1622,7 @@ hfsc_reset_qdisc(struct Qdisc *sch)
 			hfsc_reset_class(cl);
 	}
 	__skb_queue_purge(&q->requeue);
-	INIT_LIST_HEAD(&q->eligible);
+	q->eligible = RB_ROOT;
 	INIT_LIST_HEAD(&q->droplist);
 	del_timer(&q->wd_timer);
 	sch->flags &= ~TCQ_F_THROTTLED;
@@ -1749,14 +1730,14 @@ hfsc_dequeue(struct Qdisc *sch)
 	 * find the class with the minimum deadline among
 	 * the eligible classes.
 	 */
-	if ((cl = ellist_get_mindl(&q->eligible, cur_time)) != NULL) {
+	if ((cl = eltree_get_mindl(q, cur_time)) != NULL) {
 		realtime = 1;
 	} else {
 		/*
 		 * use link-sharing criteria
 		 * get the class with the minimum vt in the hierarchy
 		 */
-		cl = actlist_get_minvt(&q->root, cur_time);
+		cl = vttree_get_minvt(&q->root, cur_time);
 		if (cl == NULL) {
 			sch->stats.overlimits++;
 			hfsc_schedule_watchdog(sch, cur_time);
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index d07dfd8b5..61c8fa4db 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -1277,7 +1277,6 @@ static int htb_init(struct Qdisc *sch, struct rtattr *opt)
 				HTB_VER >> 16,HTB_VER & 0xffff,gopt->version);
 		return -EINVAL;
 	}
-	memset(q,0,sizeof(*q));
 	q->debug = gopt->debug;
 	HTB_DBG(0,1,"htb_init sch=%p handle=%X r2q=%d\n",sch,sch->handle,gopt->rate2quantum);
 
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
index 30f2176b9..13b5c3414 100644
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -283,21 +283,18 @@ int ingress_init(struct Qdisc *sch,struct rtattr *opt)
 #ifndef CONFIG_NET_CLS_ACT
 #ifndef CONFIG_NETFILTER
 	printk("You MUST compile classifier actions into the kernel\n");
-	goto error;
+	return -EINVAL;
 #else
 	printk("Ingress scheduler: Classifier actions prefered over netfilter\n");
 #endif
 #endif
                                                                                 
-	if (NULL == p)
-		goto error;
-
 #ifndef CONFIG_NET_CLS_ACT
 #ifdef CONFIG_NETFILTER
 	if (!nf_registered) {
 		if (nf_register_hook(&ing_ops) < 0) {
 			printk("ingress qdisc registration error \n");
-			goto error;
+			return -EINVAL;
 		}
 		nf_registered++;
 	}
@@ -305,12 +302,8 @@ int ingress_init(struct Qdisc *sch,struct rtattr *opt)
 #endif
 
 	DPRINTK("ingress_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
-	memset(p, 0, sizeof(*p));
-	p->filter_list = NULL;
 	p->q = &noop_qdisc;
 	return 0;
-error:
-	return -EINVAL;
 }
 
 
@@ -346,9 +339,6 @@ static void ingress_destroy(struct Qdisc *sch)
 		p->filter_list = tp->next;
 		tcf_destroy(tp);
 	}
-	memset(p, 0, sizeof(*p));
-	p->filter_list = NULL;
-
 #if 0
 /* for future use */
 	qdisc_destroy(p->q);
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 4d91d697b..d29df1cab 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -6,6 +6,9 @@
  * 		as published by the Free Software Foundation; either version
  * 		2 of the License, or (at your option) any later version.
  *
+ *  		Many of the algorithms and ideas for this came from
+ *		NIST Net which is not copyrighted. 
+ *
  * Authors:	Stephen Hemminger <shemminger@osdl.org>
  *		Catalin(ux aka Dino) BOIE <catab at umbrella dot ro>
  */
@@ -22,11 +25,31 @@
 
 #include <net/pkt_sched.h>
 
-/*	Network emulator
- *
- *	This scheduler can alters spacing and order
- *	Similar to NISTnet and BSD Dummynet.
- */
+/*	Network Emulation Queuing algorithm.
+	====================================
+
+	Sources: [1] Mark Carson, Darrin Santay, "NIST Net - A Linux-based
+		 Network Emulation Tool
+		 [2] Luigi Rizzo, DummyNet for FreeBSD
+
+	 ----------------------------------------------------------------
+
+	 This started out as a simple way to delay outgoing packets to
+	 test TCP but has grown to include most of the functionality
+	 of a full blown network emulator like NISTnet. It can delay
+	 packets and add random jitter (and correlation). The random
+	 distribution can be loaded from a table as well to provide
+	 normal, Pareto, or experimental curves. Packet loss,
+	 duplication, and reordering can also be emulated.
+
+	 This qdisc does not do classification that can be handled in
+	 layering other disciplines.  It does not need to do bandwidth
+	 control either since that can be handled by using token
+	 bucket or other rate control.
+
+	 The simulator is limited by the Linux timer resolution
+	 and will create packet bursts on the HZ boundary (1ms).
+*/
 
 struct netem_sched_data {
 	struct Qdisc	*qdisc;
@@ -39,6 +62,17 @@ struct netem_sched_data {
 	u32 counter;
 	u32 gap;
 	u32 jitter;
+	u32 duplicate;
+
+	struct crndstate {
+		unsigned long last;
+		unsigned long rho;
+	} delay_cor, loss_cor, dup_cor;
+
+	struct disttable {
+		u32  size;
+		s16 table[0];
+	} *delay_dist;
 };
 
 /* Time stamp put into socket buffer control block */
@@ -46,576 +80,110 @@ struct netem_skb_cb {
 	psched_time_t	time_to_send;
 };
 
-/* This is the distribution table for the normal distribution produced
- * with NISTnet tools.
- * The entries represent a scaled inverse of the cumulative distribution
- * function.
+/* init_crandom - initialize correlated random number generator
+ * Use entropy source for initial seed.
  */
-#define TABLESIZE	2048
-#define TABLEFACTOR	8192
-
-static const short disttable[TABLESIZE] = {
-	-31473,		-26739,		-25226,		-24269,
-	-23560,		-22993,		-22518,		-22109,
-	-21749,		-21426,		-21133,		-20865,
-	-20618,		-20389,		-20174,		-19972,
-	-19782,		-19601,		-19430,		-19267,
-	-19112,		-18962,		-18819,		-18681,
-	-18549,		-18421,		-18298,		-18178,
-	-18062,		-17950,		-17841,		-17735,
-	-17632,		-17532,		-17434,		-17339,
-	-17245,		-17155,		-17066,		-16979,
-	-16894,		-16811,		-16729,		-16649,
-	-16571,		-16494,		-16419,		-16345,
-	-16272,		-16201,		-16130,		-16061,
-	-15993,		-15926,		-15861,		-15796,
-	-15732,		-15669,		-15607,		-15546,
-	-15486,		-15426,		-15368,		-15310,
-	-15253,		-15196,		-15140,		-15086,
-	-15031,		-14977,		-14925,		-14872,
-	-14821,		-14769,		-14719,		-14669,
-	-14619,		-14570,		-14522,		-14473,
-	-14426,		-14379,		-14332,		-14286,
-	-14241,		-14196,		-14150,		-14106,
-	-14062,		-14019,		-13976,		-13933,
-	-13890,		-13848,		-13807,		-13765,
-	-13724,		-13684,		-13643,		-13604,
-	-13564,		-13525,		-13486,		-13447,
-	-13408,		-13370,		-13332,		-13295,
-	-13258,		-13221,		-13184,		-13147,
-	-13111,		-13075,		-13040,		-13004,
-	-12969,		-12934,		-12899,		-12865,
-	-12830,		-12796,		-12762,		-12729,
-	-12695,		-12662,		-12629,		-12596,
-	-12564,		-12531,		-12499,		-12467,
-	-12435,		-12404,		-12372,		-12341,
-	-12310,		-12279,		-12248,		-12218,
-	-12187,		-12157,		-12127,		-12097,
-	-12067,		-12038,		-12008,		-11979,
-	-11950,		-11921,		-11892,		-11863,
-	-11835,		-11806,		-11778,		-11750,
-	-11722,		-11694,		-11666,		-11639,
-	-11611,		-11584,		-11557,		-11530,
-	-11503,		-11476,		-11450,		-11423,
-	-11396,		-11370,		-11344,		-11318,
-	-11292,		-11266,		-11240,		-11214,
-	-11189,		-11164,		-11138,		-11113,
-	-11088,		-11063,		-11038,		-11013,
-	-10988,		-10964,		-10939,		-10915,
-	-10891,		-10866,		-10843,		-10818,
-	-10794,		-10770,		-10747,		-10723,
-	-10700,		-10676,		-10652,		-10630,
-	-10606,		-10583,		-10560,		-10537,
-	-10514,		-10491,		-10469,		-10446,
-	-10424,		-10401,		-10378,		-10356,
-	-10334,		-10312,		-10290,		-10267,
-	-10246,		-10224,		-10202,		-10180,
-	-10158,		-10137,		-10115,		-10094,
-	-10072,		-10051,		-10030,		-10009,
-	-9988,		-9967,		-9945,		-9925,
-	-9904,		-9883,		-9862,		-9842,
-	-9821,		-9800,		-9780,		-9760,
-	-9739,		-9719,		-9699,		-9678,
-	-9658,		-9638,		-9618,		-9599,
-	-9578,		-9559,		-9539,		-9519,
-	-9499,		-9480,		-9461,		-9441,
-	-9422,		-9402,		-9383,		-9363,
-	-9344,		-9325,		-9306,		-9287,
-	-9268,		-9249,		-9230,		-9211,
-	-9192,		-9173,		-9155,		-9136,
-	-9117,		-9098,		-9080,		-9062,
-	-9043,		-9025,		-9006,		-8988,
-	-8970,		-8951,		-8933,		-8915,
-	-8897,		-8879,		-8861,		-8843,
-	-8825,		-8807,		-8789,		-8772,
-	-8754,		-8736,		-8718,		-8701,
-	-8683,		-8665,		-8648,		-8630,
-	-8613,		-8595,		-8578,		-8561,
-	-8543,		-8526,		-8509,		-8492,
-	-8475,		-8458,		-8441,		-8423,
-	-8407,		-8390,		-8373,		-8356,
-	-8339,		-8322,		-8305,		-8289,
-	-8272,		-8255,		-8239,		-8222,
-	-8206,		-8189,		-8172,		-8156,
-	-8140,		-8123,		-8107,		-8090,
-	-8074,		-8058,		-8042,		-8025,
-	-8009,		-7993,		-7977,		-7961,
-	-7945,		-7929,		-7913,		-7897,
-	-7881,		-7865,		-7849,		-7833,
-	-7817,		-7802,		-7786,		-7770,
-	-7754,		-7739,		-7723,		-7707,
-	-7692,		-7676,		-7661,		-7645,
-	-7630,		-7614,		-7599,		-7583,
-	-7568,		-7553,		-7537,		-7522,
-	-7507,		-7492,		-7476,		-7461,
-	-7446,		-7431,		-7416,		-7401,
-	-7385,		-7370,		-7356,		-7340,
-	-7325,		-7311,		-7296,		-7281,
-	-7266,		-7251,		-7236,		-7221,
-	-7207,		-7192,		-7177,		-7162,
-	-7148,		-7133,		-7118,		-7104,
-	-7089,		-7075,		-7060,		-7046,
-	-7031,		-7016,		-7002,		-6988,
-	-6973,		-6959,		-6944,		-6930,
-	-6916,		-6901,		-6887,		-6873,
-	-6859,		-6844,		-6830,		-6816,
-	-6802,		-6788,		-6774,		-6760,
-	-6746,		-6731,		-6717,		-6704,
-	-6690,		-6675,		-6661,		-6647,
-	-6633,		-6620,		-6606,		-6592,
-	-6578,		-6564,		-6550,		-6537,
-	-6523,		-6509,		-6495,		-6482,
-	-6468,		-6454,		-6441,		-6427,
-	-6413,		-6400,		-6386,		-6373,
-	-6359,		-6346,		-6332,		-6318,
-	-6305,		-6291,		-6278,		-6264,
-	-6251,		-6238,		-6224,		-6211,
-	-6198,		-6184,		-6171,		-6158,
-	-6144,		-6131,		-6118,		-6105,
-	-6091,		-6078,		-6065,		-6052,
-	-6039,		-6025,		-6012,		-5999,
-	-5986,		-5973,		-5960,		-5947,
-	-5934,		-5921,		-5908,		-5895,
-	-5882,		-5869,		-5856,		-5843,
-	-5830,		-5817,		-5804,		-5791,
-	-5779,		-5766,		-5753,		-5740,
-	-5727,		-5714,		-5702,		-5689,
-	-5676,		-5663,		-5650,		-5638,
-	-5625,		-5612,		-5600,		-5587,
-	-5575,		-5562,		-5549,		-5537,
-	-5524,		-5512,		-5499,		-5486,
-	-5474,		-5461,		-5449,		-5436,
-	-5424,		-5411,		-5399,		-5386,
-	-5374,		-5362,		-5349,		-5337,
-	-5324,		-5312,		-5299,		-5287,
-	-5275,		-5263,		-5250,		-5238,
-	-5226,		-5213,		-5201,		-5189,
-	-5177,		-5164,		-5152,		-5140,
-	-5128,		-5115,		-5103,		-5091,
-	-5079,		-5067,		-5055,		-5043,
-	-5030,		-5018,		-5006,		-4994,
-	-4982,		-4970,		-4958,		-4946,
-	-4934,		-4922,		-4910,		-4898,
-	-4886,		-4874,		-4862,		-4850,
-	-4838,		-4826,		-4814,		-4803,
-	-4791,		-4778,		-4767,		-4755,
-	-4743,		-4731,		-4719,		-4708,
-	-4696,		-4684,		-4672,		-4660,
-	-4649,		-4637,		-4625,		-4613,
-	-4601,		-4590,		-4578,		-4566,
-	-4554,		-4543,		-4531,		-4520,
-	-4508,		-4496,		-4484,		-4473,
-	-4461,		-4449,		-4438,		-4427,
-	-4415,		-4403,		-4392,		-4380,
-	-4368,		-4357,		-4345,		-4334,
-	-4322,		-4311,		-4299,		-4288,
-	-4276,		-4265,		-4253,		-4242,
-	-4230,		-4219,		-4207,		-4196,
-	-4184,		-4173,		-4162,		-4150,
-	-4139,		-4128,		-4116,		-4105,
-	-4094,		-4082,		-4071,		-4060,
-	-4048,		-4037,		-4026,		-4014,
-	-4003,		-3992,		-3980,		-3969,
-	-3958,		-3946,		-3935,		-3924,
-	-3913,		-3901,		-3890,		-3879,
-	-3868,		-3857,		-3845,		-3834,
-	-3823,		-3812,		-3801,		-3790,
-	-3779,		-3767,		-3756,		-3745,
-	-3734,		-3723,		-3712,		-3700,
-	-3689,		-3678,		-3667,		-3656,
-	-3645,		-3634,		-3623,		-3612,
-	-3601,		-3590,		-3579,		-3568,
-	-3557,		-3545,		-3535,		-3524,
-	-3513,		-3502,		-3491,		-3480,
-	-3469,		-3458,		-3447,		-3436,
-	-3425,		-3414,		-3403,		-3392,
-	-3381,		-3370,		-3360,		-3348,
-	-3337,		-3327,		-3316,		-3305,
-	-3294,		-3283,		-3272,		-3262,
-	-3251,		-3240,		-3229,		-3218,
-	-3207,		-3197,		-3185,		-3175,
-	-3164,		-3153,		-3142,		-3132,
-	-3121,		-3110,		-3099,		-3088,
-	-3078,		-3067,		-3056,		-3045,
-	-3035,		-3024,		-3013,		-3003,
-	-2992,		-2981,		-2970,		-2960,
-	-2949,		-2938,		-2928,		-2917,
-	-2906,		-2895,		-2885,		-2874,
-	-2864,		-2853,		-2842,		-2832,
-	-2821,		-2810,		-2800,		-2789,
-	-2778,		-2768,		-2757,		-2747,
-	-2736,		-2725,		-2715,		-2704,
-	-2694,		-2683,		-2673,		-2662,
-	-2651,		-2641,		-2630,		-2620,
-	-2609,		-2599,		-2588,		-2578,
-	-2567,		-2556,		-2546,		-2535,
-	-2525,		-2515,		-2504,		-2493,
-	-2483,		-2472,		-2462,		-2451,
-	-2441,		-2431,		-2420,		-2410,
-	-2399,		-2389,		-2378,		-2367,
-	-2357,		-2347,		-2336,		-2326,
-	-2315,		-2305,		-2295,		-2284,
-	-2274,		-2263,		-2253,		-2243,
-	-2232,		-2222,		-2211,		-2201,
-	-2191,		-2180,		-2170,		-2159,
-	-2149,		-2139,		-2128,		-2118,
-	-2107,		-2097,		-2087,		-2076,
-	-2066,		-2056,		-2046,		-2035,
-	-2025,		-2014,		-2004,		-1994,
-	-1983,		-1973,		-1963,		-1953,
-	-1942,		-1932,		-1921,		-1911,
-	-1901,		-1891,		-1880,		-1870,
-	-1860,		-1849,		-1839,		-1829,
-	-1819,		-1808,		-1798,		-1788,
-	-1778,		-1767,		-1757,		-1747,
-	-1736,		-1726,		-1716,		-1706,
-	-1695,		-1685,		-1675,		-1665,
-	-1654,		-1644,		-1634,		-1624,
-	-1613,		-1603,		-1593,		-1583,
-	-1573,		-1563,		-1552,		-1542,
-	-1532,		-1522,		-1511,		-1501,
-	-1491,		-1481,		-1471,		-1461,
-	-1450,		-1440,		-1430,		-1420,
-	-1409,		-1400,		-1389,		-1379,
-	-1369,		-1359,		-1348,		-1339,
-	-1328,		-1318,		-1308,		-1298,
-	-1288,		-1278,		-1267,		-1257,
-	-1247,		-1237,		-1227,		-1217,
-	-1207,		-1196,		-1186,		-1176,
-	-1166,		-1156,		-1146,		-1135,
-	-1126,		-1115,		-1105,		-1095,
-	-1085,		-1075,		-1065,		-1055,
-	-1044,		-1034,		-1024,		-1014,
-	-1004,		-994,		-984,		-974,
-	-964,		-954,		-944,		-933,
-	-923,		-913,		-903,		-893,
-	-883,		-873,		-863,		-853,
-	-843,		-833,		-822,		-812,
-	-802,		-792,		-782,		-772,
-	-762,		-752,		-742,		-732,
-	-722,		-712,		-702,		-691,
-	-682,		-671,		-662,		-651,
-	-641,		-631,		-621,		-611,
-	-601,		-591,		-581,		-571,
-	-561,		-551,		-541,		-531,
-	-521,		-511,		-501,		-491,
-	-480,		-471,		-460,		-451,
-	-440,		-430,		-420,		-410,
-	-400,		-390,		-380,		-370,
-	-360,		-350,		-340,		-330,
-	-320,		-310,		-300,		-290,
-	-280,		-270,		-260,		-250,
-	-240,		-230,		-220,		-210,
-	-199,		-190,		-179,		-170,
-	-159,		-150,		-139,		-129,
-	-119,		-109,		-99,		-89,
-	-79,		-69,		-59,		-49,
-	-39,		-29,		-19,		-9,
-	1,		11,		21,		31,
-	41,		51,		61,		71,
-	81,		91,		101,		111,
-	121,		131,		141,		152,
-	161,		172,		181,		192,
-	202,		212,		222,		232,
-	242,		252,		262,		272,
-	282,		292,		302,		312,
-	322,		332,		342,		352,
-	362,		372,		382,		392,
-	402,		412,		422,		433,
-	442,		453,		462,		473,
-	483,		493,		503,		513,
-	523,		533,		543,		553,
-	563,		573,		583,		593,
-	603,		613,		623,		633,
-	643,		653,		664,		673,
-	684,		694,		704,		714,
-	724,		734,		744,		754,
-	764,		774,		784,		794,
-	804,		815,		825,		835,
-	845,		855,		865,		875,
-	885,		895,		905,		915,
-	925,		936,		946,		956,
-	966,		976,		986,		996,
-	1006,		1016,		1026,		1037,
-	1047,		1057,		1067,		1077,
-	1087,		1097,		1107,		1117,
-	1128,		1138,		1148,		1158,
-	1168,		1178,		1188,		1198,
-	1209,		1219,		1229,		1239,
-	1249,		1259,		1269,		1280,
-	1290,		1300,		1310,		1320,
-	1330,		1341,		1351,		1361,
-	1371,		1381,		1391,		1402,
-	1412,		1422,		1432,		1442,
-	1452,		1463,		1473,		1483,
-	1493,		1503,		1513,		1524,
-	1534,		1544,		1554,		1565,
-	1575,		1585,		1595,		1606,
-	1616,		1626,		1636,		1647,
-	1656,		1667,		1677,		1687,
-	1697,		1708,		1718,		1729,
-	1739,		1749,		1759,		1769,
-	1780,		1790,		1800,		1810,
-	1821,		1831,		1841,		1851,
-	1862,		1872,		1883,		1893,
-	1903,		1913,		1923,		1934,
-	1944,		1955,		1965,		1975,
-	1985,		1996,		2006,		2016,
-	2027,		2037,		2048,		2058,
-	2068,		2079,		2089,		2099,
-	2110,		2120,		2130,		2141,
-	2151,		2161,		2172,		2182,
-	2193,		2203,		2213,		2224,
-	2234,		2245,		2255,		2265,
-	2276,		2286,		2297,		2307,
-	2318,		2328,		2338,		2349,
-	2359,		2370,		2380,		2391,
-	2401,		2412,		2422,		2433,
-	2443,		2454,		2464,		2475,
-	2485,		2496,		2506,		2517,
-	2527,		2537,		2548,		2559,
-	2569,		2580,		2590,		2601,
-	2612,		2622,		2632,		2643,
-	2654,		2664,		2675,		2685,
-	2696,		2707,		2717,		2728,
-	2738,		2749,		2759,		2770,
-	2781,		2791,		2802,		2813,
-	2823,		2834,		2845,		2855,
-	2866,		2877,		2887,		2898,
-	2909,		2919,		2930,		2941,
-	2951,		2962,		2973,		2984,
-	2994,		3005,		3015,		3027,
-	3037,		3048,		3058,		3069,
-	3080,		3091,		3101,		3113,
-	3123,		3134,		3145,		3156,
-	3166,		3177,		3188,		3199,
-	3210,		3220,		3231,		3242,
-	3253,		3264,		3275,		3285,
-	3296,		3307,		3318,		3329,
-	3340,		3351,		3362,		3373,
-	3384,		3394,		3405,		3416,
-	3427,		3438,		3449,		3460,
-	3471,		3482,		3493,		3504,
-	3515,		3526,		3537,		3548,
-	3559,		3570,		3581,		3592,
-	3603,		3614,		3625,		3636,
-	3647,		3659,		3670,		3681,
-	3692,		3703,		3714,		3725,
-	3736,		3747,		3758,		3770,
-	3781,		3792,		3803,		3814,
-	3825,		3837,		3848,		3859,
-	3870,		3881,		3893,		3904,
-	3915,		3926,		3937,		3949,
-	3960,		3971,		3983,		3994,
-	4005,		4017,		4028,		4039,
-	4051,		4062,		4073,		4085,
-	4096,		4107,		4119,		4130,
-	4141,		4153,		4164,		4175,
-	4187,		4198,		4210,		4221,
-	4233,		4244,		4256,		4267,
-	4279,		4290,		4302,		4313,
-	4325,		4336,		4348,		4359,
-	4371,		4382,		4394,		4406,
-	4417,		4429,		4440,		4452,
-	4464,		4475,		4487,		4499,
-	4510,		4522,		4533,		4545,
-	4557,		4569,		4581,		4592,
-	4604,		4616,		4627,		4639,
-	4651,		4663,		4674,		4686,
-	4698,		4710,		4722,		4734,
-	4746,		4758,		4769,		4781,
-	4793,		4805,		4817,		4829,
-	4841,		4853,		4865,		4877,
-	4889,		4900,		4913,		4925,
-	4936,		4949,		4961,		4973,
-	4985,		4997,		5009,		5021,
-	5033,		5045,		5057,		5070,
-	5081,		5094,		5106,		5118,
-	5130,		5143,		5155,		5167,
-	5179,		5191,		5204,		5216,
-	5228,		5240,		5253,		5265,
-	5278,		5290,		5302,		5315,
-	5327,		5340,		5352,		5364,
-	5377,		5389,		5401,		5414,
-	5426,		5439,		5451,		5464,
-	5476,		5489,		5502,		5514,
-	5527,		5539,		5552,		5564,
-	5577,		5590,		5603,		5615,
-	5628,		5641,		5653,		5666,
-	5679,		5691,		5704,		5717,
-	5730,		5743,		5756,		5768,
-	5781,		5794,		5807,		5820,
-	5833,		5846,		5859,		5872,
-	5885,		5897,		5911,		5924,
-	5937,		5950,		5963,		5976,
-	5989,		6002,		6015,		6028,
-	6042,		6055,		6068,		6081,
-	6094,		6108,		6121,		6134,
-	6147,		6160,		6174,		6187,
-	6201,		6214,		6227,		6241,
-	6254,		6267,		6281,		6294,
-	6308,		6321,		6335,		6348,
-	6362,		6375,		6389,		6403,
-	6416,		6430,		6443,		6457,
-	6471,		6485,		6498,		6512,
-	6526,		6540,		6554,		6567,
-	6581,		6595,		6609,		6623,
-	6637,		6651,		6665,		6679,
-	6692,		6706,		6721,		6735,
-	6749,		6763,		6777,		6791,
-	6805,		6819,		6833,		6848,
-	6862,		6876,		6890,		6905,
-	6919,		6933,		6948,		6962,
-	6976,		6991,		7005,		7020,
-	7034,		7049,		7064,		7078,
-	7093,		7107,		7122,		7136,
-	7151,		7166,		7180,		7195,
-	7210,		7225,		7240,		7254,
-	7269,		7284,		7299,		7314,
-	7329,		7344,		7359,		7374,
-	7389,		7404,		7419,		7434,
-	7449,		7465,		7480,		7495,
-	7510,		7526,		7541,		7556,
-	7571,		7587,		7602,		7618,
-	7633,		7648,		7664,		7680,
-	7695,		7711,		7726,		7742,
-	7758,		7773,		7789,		7805,
-	7821,		7836,		7852,		7868,
-	7884,		7900,		7916,		7932,
-	7948,		7964,		7981,		7997,
-	8013,		8029,		8045,		8061,
-	8078,		8094,		8110,		8127,
-	8143,		8160,		8176,		8193,
-	8209,		8226,		8242,		8259,
-	8276,		8292,		8309,		8326,
-	8343,		8360,		8377,		8394,
-	8410,		8428,		8444,		8462,
-	8479,		8496,		8513,		8530,
-	8548,		8565,		8582,		8600,
-	8617,		8634,		8652,		8670,
-	8687,		8704,		8722,		8740,
-	8758,		8775,		8793,		8811,
-	8829,		8847,		8865,		8883,
-	8901,		8919,		8937,		8955,
-	8974,		8992,		9010,		9029,
-	9047,		9066,		9084,		9103,
-	9121,		9140,		9159,		9177,
-	9196,		9215,		9234,		9253,
-	9272,		9291,		9310,		9329,
-	9349,		9368,		9387,		9406,
-	9426,		9445,		9465,		9484,
-	9504,		9524,		9544,		9563,
-	9583,		9603,		9623,		9643,
-	9663,		9683,		9703,		9723,
-	9744,		9764,		9785,		9805,
-	9826,		9846,		9867,		9888,
-	9909,		9930,		9950,		9971,
-	9993,		10013,		10035,		10056,
-	10077,		10099,		10120,		10142,
-	10163,		10185,		10207,		10229,
-	10251,		10273,		10294,		10317,
-	10339,		10361,		10384,		10406,
-	10428,		10451,		10474,		10496,
-	10519,		10542,		10565,		10588,
-	10612,		10635,		10658,		10682,
-	10705,		10729,		10752,		10776,
-	10800,		10824,		10848,		10872,
-	10896,		10921,		10945,		10969,
-	10994,		11019,		11044,		11069,
-	11094,		11119,		11144,		11169,
-	11195,		11221,		11246,		11272,
-	11298,		11324,		11350,		11376,
-	11402,		11429,		11456,		11482,
-	11509,		11536,		11563,		11590,
-	11618,		11645,		11673,		11701,
-	11728,		11756,		11785,		11813,
-	11842,		11870,		11899,		11928,
-	11957,		11986,		12015,		12045,
-	12074,		12104,		12134,		12164,
-	12194,		12225,		12255,		12286,
-	12317,		12348,		12380,		12411,
-	12443,		12475,		12507,		12539,
-	12571,		12604,		12637,		12670,
-	12703,		12737,		12771,		12804,
-	12839,		12873,		12907,		12942,
-	12977,		13013,		13048,		13084,
-	13120,		13156,		13192,		13229,
-	13267,		13304,		13341,		13379,
-	13418,		13456,		13495,		13534,
-	13573,		13613,		13653,		13693,
-	13734,		13775,		13817,		13858,
-	13901,		13943,		13986,		14029,
-	14073,		14117,		14162,		14206,
-	14252,		14297,		14343,		14390,
-	14437,		14485,		14533,		14582,
-	14631,		14680,		14731,		14782,
-	14833,		14885,		14937,		14991,
-	15044,		15099,		15154,		15210,
-	15266,		15324,		15382,		15441,
-	15500,		15561,		15622,		15684,
-	15747,		15811,		15877,		15943,
-	16010,		16078,		16148,		16218,
-	16290,		16363,		16437,		16513,
-	16590,		16669,		16749,		16831,
-	16915,		17000,		17088,		17177,
-	17268,		17362,		17458,		17556,
-	17657,		17761,		17868,		17977,
-	18090,		18207,		18328,		18452,
-	18581,		18715,		18854,		18998,
-	19149,		19307,		19472,		19645,
-	19828,		20021,		20226,		20444,
-	20678,		20930,		21204,		21503,
-	21835,		22206,		22630,		23124,
-	23721,		24478,		25529,		27316,
-};
+static void init_crandom(struct crndstate *state, unsigned long rho)
+{
+	state->rho = rho;
+	state->last = net_random();
+}
+
+/* get_crandom - correlated random number generator
+ * Next number depends on last value.
+ * rho is scaled to avoid floating point.
+ */
+static unsigned long get_crandom(struct crndstate *state)
+{
+	u64 value, rho;
+	unsigned long answer;
+
+	if (state->rho == 0)	/* no correllation */
+		return net_random();
+
+	value = net_random();
+	rho = (u64)state->rho + 1;
+	answer = (value * ((1ull<<32) - rho) + state->last * rho) >> 32;
+	state->last = answer;
+	return answer;
+}
 
 /* tabledist - return a pseudo-randomly distributed value with mean mu and
  * std deviation sigma.  Uses table lookup to approximate the desired
  * distribution, and a uniformly-distributed pseudo-random source.
  */
-static inline int tabledist(int mu, int sigma)
+static long tabledist(unsigned long mu, long sigma, 
+		      struct crndstate *state, const struct disttable *dist)
 {
-	int x;
-	int index;
-	int sigmamod, sigmadiv;
+	long t, x;
+	unsigned long rnd;
 
 	if (sigma == 0)
 		return mu;
 
-	index = (net_random() & (TABLESIZE-1));
-	sigmamod = sigma%TABLEFACTOR;
-	sigmadiv = sigma/TABLEFACTOR;
-	x = sigmamod*disttable[index];
+	rnd = get_crandom(state);
 
+	/* default uniform distribution */
+	if (dist == NULL) 
+		return (rnd % (2*sigma)) - sigma + mu;
+
+	t = dist->table[rnd % dist->size];
+	x = (sigma % NETEM_DIST_SCALE) * t;
 	if (x >= 0)
-		x += TABLEFACTOR/2;
+		x += NETEM_DIST_SCALE/2;
 	else
-		x -= TABLEFACTOR/2;
+		x -= NETEM_DIST_SCALE/2;
 
-	x /= TABLEFACTOR;
-	x += sigmadiv*disttable[index];
-	x += mu;
-	return x;
+	return  x / NETEM_DIST_SCALE + (sigma / NETEM_DIST_SCALE) * t + mu;
 }
 
-/* Enqueue packets with underlying discipline (fifo)
- * but mark them with current time first.
- */
-static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+/* Put skb in the private delayed queue. */
+static int delay_skb(struct Qdisc *sch, struct sk_buff *skb)
 {
 	struct netem_sched_data *q = qdisc_priv(sch);
 	struct netem_skb_cb *cb = (struct netem_skb_cb *)skb->cb;
 	psched_time_t now;
-	long delay;
+	
+	PSCHED_GET_TIME(now);
+	PSCHED_TADD2(now, tabledist(q->latency, q->jitter, 
+				    &q->delay_cor, q->delay_dist),
+		     cb->time_to_send);
+	
+	/* Always queue at tail to keep packets in order */
+	if (likely(q->delayed.qlen < q->limit)) {
+		__skb_queue_tail(&q->delayed, skb);
+		sch->q.qlen++;
+		sch->stats.bytes += skb->len;
+		sch->stats.packets++;
+		return NET_XMIT_SUCCESS;
+	}
+
+	sch->stats.drops++;
+	kfree_skb(skb);
+	return NET_XMIT_DROP;
+}
+
+static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+{
+	struct netem_sched_data *q = qdisc_priv(sch);
 
 	pr_debug("netem_enqueue skb=%p @%lu\n", skb, jiffies);
 
 	/* Random packet drop 0 => none, ~0 => all */
-	if (q->loss && q->loss >= net_random()) {
+	if (q->loss && q->loss >= get_crandom(&q->loss_cor)) {
+		pr_debug("netem_enqueue: random loss\n");
 		sch->stats.drops++;
 		return 0;	/* lie about loss so TCP doesn't know */
 	}
 
+	/* Random duplication */
+	if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor)) {
+		struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
+
+		pr_debug("netem_enqueue: dup %p\n", skb2);
+		if (skb2)
+			delay_skb(sch, skb2);
+	}
 
 	/* If doing simple delay then gap == 0 so all packets
 	 * go into the delayed holding queue
@@ -633,27 +201,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 	}
 	
 	q->counter = 0;
-	
-	PSCHED_GET_TIME(now);
-	if (q->jitter) 
-		delay = tabledist(q->latency, q->jitter);
-	else
-		delay = q->latency;
-
-	PSCHED_TADD2(now, delay, cb->time_to_send);
-	
-	/* Always queue at tail to keep packets in order */
-	if (likely(q->delayed.qlen < q->limit)) {
-		__skb_queue_tail(&q->delayed, skb);
-		sch->q.qlen++;
-		sch->stats.bytes += skb->len;
-		sch->stats.packets++;
-		return 0;
-	}
 
-	sch->stats.drops++;
-	kfree_skb(skb);
-	return NET_XMIT_DROP;
+	return delay_skb(sch, skb);
 }
 
 /* Requeue packets but don't change time stamp */
@@ -752,39 +301,97 @@ static int set_fifo_limit(struct Qdisc *q, int limit)
 	return ret;
 }
 
-static int netem_change(struct Qdisc *sch, struct rtattr *opt)
+/*
+ * Distribution data is a variable size payload containing
+ * signed 16 bit values.
+ */
+static int get_dist_table(struct Qdisc *sch, const struct rtattr *attr)
 {
 	struct netem_sched_data *q = qdisc_priv(sch);
-	struct tc_netem_qopt *qopt = RTA_DATA(opt);
-	struct Qdisc *child;
-	int ret;
+	unsigned long n = RTA_PAYLOAD(attr)/sizeof(__s16);
+	const __s16 *data = RTA_DATA(attr);
+	struct disttable *d;
+	int i;
 
-	if (opt->rta_len < RTA_LENGTH(sizeof(*qopt)))
+	if (n > 65536)
 		return -EINVAL;
 
-	child = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
-	if (!child)
+	d = kmalloc(sizeof(*d) + n*sizeof(d->table[0]), GFP_KERNEL);
+	if (!d)
+		return -ENOMEM;
+
+	d->size = n;
+	for (i = 0; i < n; i++)
+		d->table[i] = data[i];
+	
+	spin_lock_bh(&sch->dev->queue_lock);
+	d = xchg(&q->delay_dist, d);
+	spin_unlock_bh(&sch->dev->queue_lock);
+
+	kfree(d);
+	return 0;
+}
+
+static int get_correlation(struct Qdisc *sch, const struct rtattr *attr)
+{
+	struct netem_sched_data *q = qdisc_priv(sch);
+	const struct tc_netem_corr *c = RTA_DATA(attr);
+
+	if (RTA_PAYLOAD(attr) != sizeof(*c))
 		return -EINVAL;
 
-	ret = set_fifo_limit(child, qopt->limit);
+	init_crandom(&q->delay_cor, c->delay_corr);
+	init_crandom(&q->loss_cor, c->loss_corr);
+	init_crandom(&q->dup_cor, c->dup_corr);
+	return 0;
+}
+
+static int netem_change(struct Qdisc *sch, struct rtattr *opt)
+{
+	struct netem_sched_data *q = qdisc_priv(sch);
+	struct tc_netem_qopt *qopt;
+	int ret;
+	
+	if (opt == NULL || RTA_PAYLOAD(opt) < sizeof(*qopt))
+		return -EINVAL;
+
+	qopt = RTA_DATA(opt);
+	ret = set_fifo_limit(q->qdisc, qopt->limit);
 	if (ret) {
-		qdisc_destroy(child);
+		pr_debug("netem: can't set fifo limit\n");
 		return ret;
 	}
-
-	sch_tree_lock(sch);
-	if (child) {
-		child = xchg(&q->qdisc, child);
-		if (child != &noop_qdisc)
-			qdisc_destroy(child);
 	
-		q->latency = qopt->latency;
-		q->jitter = qopt->jitter;
-		q->limit = qopt->limit;
-		q->gap = qopt->gap;
-		q->loss = qopt->loss;
+	q->latency = qopt->latency;
+	q->jitter = qopt->jitter;
+	q->limit = qopt->limit;
+	q->gap = qopt->gap;
+	q->loss = qopt->loss;
+	q->duplicate = qopt->duplicate;
+
+	/* Handle nested options after initial queue options.
+	 * Should have put all options in nested format but too late now.
+	 */ 
+	if (RTA_PAYLOAD(opt) > sizeof(*qopt)) {
+		struct rtattr *tb[TCA_NETEM_MAX];
+		if (rtattr_parse(tb, TCA_NETEM_MAX, 
+				 RTA_DATA(opt) + sizeof(*qopt),
+				 RTA_PAYLOAD(opt) - sizeof(*qopt)))
+			return -EINVAL;
+
+		if (tb[TCA_NETEM_CORR-1]) {
+			ret = get_correlation(sch, tb[TCA_NETEM_CORR-1]);
+			if (ret)
+				return ret;
+		}
+
+		if (tb[TCA_NETEM_DELAY_DIST-1]) {
+			ret = get_dist_table(sch, tb[TCA_NETEM_DELAY_DIST-1]);
+			if (ret)
+				return ret;
+		}
 	}
-	sch_tree_unlock(sch);
+
 
 	return 0;
 }
@@ -792,19 +399,29 @@ static int netem_change(struct Qdisc *sch, struct rtattr *opt)
 static int netem_init(struct Qdisc *sch, struct rtattr *opt)
 {
 	struct netem_sched_data *q = qdisc_priv(sch);
+	int ret;
 
 	if (!opt)
 		return -EINVAL;
 
 	skb_queue_head_init(&q->delayed);
-	q->qdisc = &noop_qdisc;
-
 	init_timer(&q->timer);
 	q->timer.function = netem_watchdog;
 	q->timer.data = (unsigned long) sch;
 	q->counter = 0;
 
-	return netem_change(sch, opt);
+	q->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+	if (!q->qdisc) {
+		pr_debug("netem: qdisc create failed\n");
+		return -ENOMEM;
+	}
+
+	ret = netem_change(sch, opt);
+	if (ret) {
+		pr_debug("netem: change failed\n");
+		qdisc_destroy(q->qdisc);
+	}
+	return ret;
 }
 
 static void netem_destroy(struct Qdisc *sch)
@@ -813,22 +430,31 @@ static void netem_destroy(struct Qdisc *sch)
 
 	del_timer_sync(&q->timer);
 	qdisc_destroy(q->qdisc);
+	kfree(q->delay_dist);
 }
 
 static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
 {
-	struct netem_sched_data *q = qdisc_priv(sch);
+	const struct netem_sched_data *q = qdisc_priv(sch);
 	unsigned char	 *b = skb->tail;
+	struct rtattr *rta = (struct rtattr *) b;
 	struct tc_netem_qopt qopt;
+	struct tc_netem_corr cor;
 
 	qopt.latency = q->latency;
 	qopt.jitter = q->jitter;
 	qopt.limit = q->limit;
 	qopt.loss = q->loss;
 	qopt.gap = q->gap;
-
+	qopt.duplicate = q->duplicate;
 	RTA_PUT(skb, TCA_OPTIONS, sizeof(qopt), &qopt);
 
+	cor.delay_corr = q->delay_cor.rho;
+	cor.loss_corr = q->loss_cor.rho;
+	cor.dup_corr = q->dup_cor.rho;
+	RTA_PUT(skb, TCA_NETEM_CORR, sizeof(cor), &cor);
+	rta->rta_len = skb->tail - b;
+
 	return skb->len;
 
 rtattr_failure:
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index 5630abb20..e98f79bdb 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -40,6 +40,7 @@
 #include <net/sock.h>
 #include <net/pkt_sched.h>
 #include <net/inet_ecn.h>
+#include <net/dsfield.h>
 
 
 /*	Random Early Detection (RED) algorithm.
@@ -162,13 +163,12 @@ static int red_ecn_mark(struct sk_buff *skb)
 
 	switch (skb->protocol) {
 	case __constant_htons(ETH_P_IP):
-		if (!INET_ECN_is_capable(skb->nh.iph->tos))
+		if (INET_ECN_is_not_ect(skb->nh.iph->tos))
 			return 0;
-		if (INET_ECN_is_not_ce(skb->nh.iph->tos))
-			IP_ECN_set_ce(skb->nh.iph);
+		IP_ECN_set_ce(skb->nh.iph);
 		return 1;
 	case __constant_htons(ETH_P_IPV6):
-		if (!INET_ECN_is_capable(ip6_get_dsfield(skb->nh.ipv6h)))
+		if (INET_ECN_is_not_ect(ipv6_get_dsfield(skb->nh.ipv6h)))
 			return 0;
 		IP6_ECN_set_ce(skb->nh.ipv6h);
 		return 1;
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index f37d9cdd0..ac668b08e 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -372,7 +372,6 @@ static void sfq_perturbation(unsigned long arg)
 	struct sfq_sched_data *q = qdisc_priv(sch);
 
 	q->perturbation = net_random()&0x1F;
-	q->perturb_timer.expires = jiffies + q->perturb_period;
 
 	if (q->perturb_period) {
 		q->perturb_timer.expires = jiffies + q->perturb_period;
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index 963e87a5b..dd169094a 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -31,6 +31,7 @@
 #include <net/ip.h>
 #include <net/route.h>
 #include <linux/skbuff.h>
+#include <linux/moduleparam.h>
 #include <net/sock.h>
 #include <net/pkt_sched.h>
 
@@ -449,7 +450,7 @@ static __init void teql_master_setup(struct net_device *dev)
 
 static LIST_HEAD(master_dev_list);
 static int max_equalizers = 1;
-MODULE_PARM(max_equalizers, "i");
+module_param(max_equalizers, int, 0);
 MODULE_PARM_DESC(max_equalizers, "Max number of link equalizers");
 
 static int __init teql_init(void)
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 09e6df208..8765177be 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -583,8 +583,8 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk,
 	struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
 	struct sctp6_sock *newsctp6sk;
 
-	newsk = sk_alloc(PF_INET6, GFP_KERNEL, sizeof(struct sctp6_sock),
-			 sk->sk_slab);
+	newsk = sk_alloc(PF_INET6, GFP_KERNEL, sk->sk_prot->slab_obj_size,
+			 sk->sk_prot->slab);
 	if (!newsk)
 		goto out;
 
@@ -892,7 +892,7 @@ static struct proto_ops inet6_seqpacket_ops = {
 static struct inet_protosw sctpv6_seqpacket_protosw = {
 	.type          = SOCK_SEQPACKET,
 	.protocol      = IPPROTO_SCTP,
-	.prot 	       = &sctp_prot,
+	.prot 	       = &sctpv6_prot,
 	.ops           = &inet6_seqpacket_ops,
 	.capability    = -1,
 	.no_check      = 0,
@@ -901,7 +901,7 @@ static struct inet_protosw sctpv6_seqpacket_protosw = {
 static struct inet_protosw sctpv6_stream_protosw = {
 	.type          = SOCK_STREAM,
 	.protocol      = IPPROTO_SCTP,
-	.prot 	       = &sctp_prot,
+	.prot 	       = &sctpv6_prot,
 	.ops           = &inet6_seqpacket_ops,
 	.capability    = -1,
 	.no_check      = 0,
@@ -963,9 +963,14 @@ static struct sctp_pf sctp_pf_inet6_specific = {
 /* Initialize IPv6 support and register with inet6 stack.  */
 int sctp_v6_init(void)
 {
+	int rc = sk_alloc_slab(&sctpv6_prot, "sctpv6_sock");
+
+	if (rc)
+		goto out;
 	/* Register inet6 protocol. */
+	rc = -EAGAIN;
 	if (inet6_add_protocol(&sctpv6_protocol, IPPROTO_SCTP) < 0)
-		return -EAGAIN;
+		goto out_sctp_free_slab;
 
 	/* Add SCTPv6(UDP and TCP style) to inetsw6 linked list. */
 	inet6_register_protosw(&sctpv6_seqpacket_protosw);
@@ -979,8 +984,12 @@ int sctp_v6_init(void)
 
 	/* Register notifier for inet6 address additions/deletions. */
 	register_inet6addr_notifier(&sctp_inetaddr_notifier);
-
-	return 0;
+	rc = 0;
+out:
+	return rc;
+out_sctp_free_slab:
+	sk_free_slab(&sctpv6_prot);
+	goto out;
 }
 
 /* IPv6 specific exit support. */
@@ -991,4 +1000,5 @@ void sctp_v6_exit(void)
 	inet6_unregister_protosw(&sctpv6_seqpacket_protosw);
 	inet6_unregister_protosw(&sctpv6_stream_protosw);
 	unregister_inet6addr_notifier(&sctp_inetaddr_notifier);
+	sk_free_slab(&sctpv6_prot);
 }
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 16a57cf9b..191682be4 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -81,8 +81,6 @@ static struct sctp_af *sctp_af_v6_specific;
 kmem_cache_t *sctp_chunk_cachep;
 kmem_cache_t *sctp_bucket_cachep;
 
-extern struct net_proto_family inet_family_ops;
-
 extern int sctp_snmp_proc_init(void);
 extern int sctp_snmp_proc_exit(void);
 extern int sctp_eps_proc_init(void);
@@ -148,13 +146,12 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist,
 	struct in_ifaddr *ifa;
 	struct sctp_sockaddr_entry *addr;
 
-	read_lock(&inetdev_lock);
+	rcu_read_lock();
 	if ((in_dev = __in_dev_get(dev)) == NULL) {
-		read_unlock(&inetdev_lock);
+		rcu_read_unlock();
 		return;
 	}
 
-	read_lock(&in_dev->lock);
 	for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
 		/* Add the address to the local list.  */
 		addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC);
@@ -166,8 +163,7 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist,
 		}
 	}
 
-	read_unlock(&in_dev->lock);
-	read_unlock(&inetdev_lock);
+	rcu_read_unlock();
 }
 
 /* Extract our IP addresses from the system and stash them in the
@@ -558,8 +554,8 @@ struct sock *sctp_v4_create_accept_sk(struct sock *sk,
 	struct inet_opt *inet = inet_sk(sk);
 	struct inet_opt *newinet;
 
-	newsk = sk_alloc(PF_INET, GFP_KERNEL, sizeof(struct sctp_sock),
-			 sk->sk_slab);
+	newsk = sk_alloc(PF_INET, GFP_KERNEL, sk->sk_prot->slab_obj_size,
+			 sk->sk_prot->slab);
 	if (!newsk)
 		goto out;
 
@@ -966,23 +962,29 @@ static void cleanup_sctp_mibs(void)
 __init int sctp_init(void)
 {
 	int i;
-	int status = 0;
+	int status = -EINVAL;
 	unsigned long goal;
 	int order;
 
 	/* SCTP_DEBUG sanity check. */
 	if (!sctp_sanity_check())
-		return -EINVAL;
+		goto out;
+
+	status = sk_alloc_slab(&sctp_prot, "sctp_sock");
+	if (status)
+		goto out;
 
 	/* Add SCTP to inet_protos hash table.  */
+	status = -EAGAIN;
 	if (inet_add_protocol(&sctp_protocol, IPPROTO_SCTP) < 0)
-		return -EAGAIN;
+		goto err_add_protocol;
 
 	/* Add SCTP(TCP and UDP style) to inetsw linked list.  */
 	inet_register_protosw(&sctp_seqpacket_protosw);
 	inet_register_protosw(&sctp_stream_protosw);
 
 	/* Allocate a cache pools. */
+	status = -ENOBUFS;
 	sctp_bucket_cachep = kmem_cache_create("sctp_bind_bucket",
 					       sizeof(struct sctp_bind_bucket),
 					       0, SLAB_HWCACHE_ALIGN,
@@ -1158,8 +1160,11 @@ __init int sctp_init(void)
 	sctp_get_local_addr_list();
 
 	__unsafe(THIS_MODULE);
-	return 0;
-
+	status = 0;
+out:
+	return status;
+err_add_protocol:
+	sk_free_slab(&sctp_prot);
 err_ctl_sock_init:
 	sctp_v6_exit();
 err_v6_init:
@@ -1187,7 +1192,7 @@ err_bucket_cachep:
 	inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
 	inet_unregister_protosw(&sctp_seqpacket_protosw);
 	inet_unregister_protosw(&sctp_stream_protosw);
-	return status;
+	goto out;
 }
 
 /* Exit handler for the SCTP protocol.  */
@@ -1228,6 +1233,7 @@ __exit void sctp_exit(void)
 	inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
 	inet_unregister_protosw(&sctp_seqpacket_protosw);
 	inet_unregister_protosw(&sctp_stream_protosw);
+	sk_free_slab(&sctp_prot);
 }
 
 module_init(sctp_init);
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 698a2c561..0d1bc4507 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -108,7 +108,6 @@ static void sctp_sock_migrate(struct sock *, struct sock *,
 static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG;
 
 extern kmem_cache_t *sctp_bucket_cachep;
-extern int sctp_assoc_valid(struct sock *sk, struct sctp_association *asoc);
 
 /* Get the sndbuf space available at the time on the association.  */
 static inline int sctp_wspace(struct sctp_association *asoc)
@@ -4623,4 +4622,29 @@ struct proto sctp_prot = {
 	.hash        =	sctp_hash,
 	.unhash      =	sctp_unhash,
 	.get_port    =	sctp_get_port,
+	.slab_obj_size = sizeof(struct sctp_sock),
 };
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+struct proto sctpv6_prot = {
+	.name		= "SCTPv6",
+	.close		= sctp_close,
+	.connect	= sctp_connect,
+	.disconnect	= sctp_disconnect,
+	.accept		= sctp_accept,
+	.ioctl		= sctp_ioctl,
+	.init		= sctp_init_sock,
+	.destroy	= sctp_destroy_sock,
+	.shutdown	= sctp_shutdown,
+	.setsockopt	= sctp_setsockopt,
+	.getsockopt	= sctp_getsockopt,
+	.sendmsg	= sctp_sendmsg,
+	.recvmsg	= sctp_recvmsg,
+	.bind		= sctp_bind,
+	.backlog_rcv	= sctp_backlog_rcv,
+	.hash		= sctp_hash,
+	.unhash		= sctp_unhash,
+	.get_port	= sctp_get_port,
+	.slab_obj_size	= sizeof(struct sctp6_sock),
+};
+#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
diff --git a/net/sunrpc/auth_gss/Makefile b/net/sunrpc/auth_gss/Makefile
index 9495e5278..fe1b87408 100644
--- a/net/sunrpc/auth_gss/Makefile
+++ b/net/sunrpc/auth_gss/Makefile
@@ -12,3 +12,7 @@ obj-$(CONFIG_RPCSEC_GSS_KRB5) += rpcsec_gss_krb5.o
 rpcsec_gss_krb5-objs := gss_krb5_mech.o gss_krb5_seal.o gss_krb5_unseal.o \
 	gss_krb5_seqnum.o
 
+obj-$(CONFIG_RPCSEC_GSS_SPKM3) += rpcsec_gss_spkm3.o
+
+rpcsec_gss_spkm3-objs := gss_spkm3_mech.o gss_spkm3_seal.o gss_spkm3_unseal.o \
+	gss_spkm3_token.o
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index e32f2a709..927b72c89 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -246,7 +246,7 @@ gss_parse_init_downcall(struct gss_api_mech *gm, struct xdr_netobj *buf,
 	spin_lock_init(&ctx->gc_seq_lock);
 	atomic_set(&ctx->count,1);
 
-	if (simple_get_bytes(&p, end, uid, sizeof(uid)))
+	if (simple_get_bytes(&p, end, uid, sizeof(*uid)))
 		goto err_free_ctx;
 	/* FIXME: discarded timeout for now */
 	if (simple_get_bytes(&p, end, &timeout, sizeof(timeout)))
@@ -397,7 +397,7 @@ retry:
 		spin_unlock(&gss_auth->lock);
 	}
 	gss_release_msg(gss_msg);
-	dprintk("RPC: %4u gss_upcall for uid %u result %d", task->tk_pid,
+	dprintk("RPC: %4u gss_upcall for uid %u result %d\n", task->tk_pid,
 			uid, res);
 	return res;
 out_sleep:
diff --git a/net/sunrpc/auth_gss/gss_generic_token.c b/net/sunrpc/auth_gss/gss_generic_token.c
index d7b040809..b0951d115 100644
--- a/net/sunrpc/auth_gss/gss_generic_token.c
+++ b/net/sunrpc/auth_gss/gss_generic_token.c
@@ -179,7 +179,7 @@ EXPORT_SYMBOL(g_make_token_header);
  */
 u32
 g_verify_token_header(struct xdr_netobj *mech, int *body_size,
-		      unsigned char **buf_in, int tok_type, int toksize)
+		      unsigned char **buf_in, int toksize)
 {
 	unsigned char *buf = *buf_in;
 	int seqsize;
diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c
index dcde40fe7..8767fc531 100644
--- a/net/sunrpc/auth_gss/gss_krb5_unseal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c
@@ -96,7 +96,7 @@ krb5_read_token(struct krb5_ctx *ctx,
 
 	dprintk("RPC:      krb5_read_token\n");
 
-	if (g_verify_token_header(&ctx->mech_used, &bodysize, &ptr, toktype,
+	if (g_verify_token_header(&ctx->mech_used, &bodysize, &ptr,
 					read_token->len))
 		goto out;
 
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 5822ab211..ee2e9cef9 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -643,7 +643,6 @@ svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name)
 	if (!new)
 		goto out;
 	cache_init(&new->h.h);
-	atomic_inc(&new->h.h.refcnt);
 	new->h.name = kmalloc(strlen(name) + 1, GFP_KERNEL);
 	if (!new->h.name)
 		goto out_free_dom;
@@ -651,7 +650,6 @@ svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name)
 	new->h.flavour = RPC_AUTH_GSS;
 	new->pseudoflavor = pseudoflavor;
 	new->h.h.expiry_time = NEVER;
-	new->h.h.flags = 0;
 
 	test = auth_domain_lookup(&new->h, 1);
 	if (test == &new->h) {
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index bb54be851..d508a513d 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -38,7 +38,7 @@ void cache_init(struct cache_head *h)
 	time_t now = get_seconds();
 	h->next = NULL;
 	h->flags = 0;
-	atomic_set(&h->refcnt, 0);
+	atomic_set(&h->refcnt, 1);
 	h->expiry_time = now + CACHE_NEW_EXPIRY;
 	h->last_refresh = now;
 }
@@ -400,9 +400,10 @@ void cache_flush(void)
 
 void cache_purge(struct cache_detail *detail)
 {
-	detail->flush_time = get_seconds()+1;
+	detail->flush_time = LONG_MAX;
 	detail->nextcheck = get_seconds();
 	cache_flush();
+	detail->flush_time = 1;
 }
 
 
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index e06577901..4f4cdb904 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -196,7 +196,15 @@ rpc_clone_client(struct rpc_clnt *clnt)
 	memcpy(new, clnt, sizeof(*new));
 	atomic_set(&new->cl_count, 1);
 	atomic_set(&new->cl_users, 0);
-	atomic_inc(&new->cl_parent->cl_count);
+	new->cl_parent = clnt;
+	atomic_inc(&clnt->cl_count);
+	/* Duplicate portmapper */
+	rpc_init_wait_queue(&new->cl_pmap_default.pm_bindwait, "bindwait");
+	/* 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);
 	return new;
@@ -335,7 +343,7 @@ void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset)
  */
 int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
 {
-	struct rpc_task	my_task, *task = &my_task;
+	struct rpc_task	*task;
 	sigset_t	oldset;
 	int		status;
 
@@ -343,15 +351,15 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
 	if (clnt->cl_dead) 
 		return -EIO;
 
-	if (flags & RPC_TASK_ASYNC) {
-		printk("rpc_call_sync: Illegal flag combination for synchronous task\n");
-		flags &= ~RPC_TASK_ASYNC;
-	}
+	BUG_ON(flags & RPC_TASK_ASYNC);
 
 	rpc_clnt_sigmask(clnt, &oldset);		
 
-	/* Create/initialize a new RPC task */
-	rpc_init_task(task, clnt, NULL, flags);
+	status = -ENOMEM;
+	task = rpc_new_task(clnt, NULL, flags);
+	if (task == NULL)
+		goto out;
+
 	rpc_call_setup(task, msg, 0);
 
 	/* Set up the call info struct and execute the task */
@@ -362,6 +370,7 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
 		rpc_release_task(task);
 	}
 
+out:
 	rpc_clnt_sigunmask(clnt, &oldset);		
 
 	return status;
@@ -958,8 +967,12 @@ call_header(struct rpc_task *task)
 static u32 *
 call_verify(struct rpc_task *task)
 {
-	u32	*p = task->tk_rqstp->rq_rcv_buf.head[0].iov_base, n;
+	struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0];
+	int len = task->tk_rqstp->rq_rcv_buf.len >> 2;
+	u32	*p = iov->iov_base, n;
 
+	if ((len -= 3) < 0)
+		goto garbage;
 	p += 1;	/* skip XID */
 
 	if ((n = ntohl(*p++)) != RPC_REPLY) {
@@ -969,9 +982,11 @@ call_verify(struct rpc_task *task)
 	if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
 		int	error = -EACCES;
 
+		if (--len < 0)
+			goto garbage;
 		if ((n = ntohl(*p++)) != RPC_AUTH_ERROR) {
 			printk(KERN_WARNING "call_verify: RPC call rejected: %x\n", n);
-		} else
+		} else if (--len < 0)
 		switch ((n = ntohl(*p++))) {
 		case RPC_AUTH_REJECTEDCRED:
 		case RPC_AUTH_REJECTEDVERF:
@@ -1002,7 +1017,8 @@ call_verify(struct rpc_task *task)
 		default:
 			printk(KERN_WARNING "call_verify: unknown auth error: %x\n", n);
 			error = -EIO;
-		}
+		} else
+			goto garbage;
 		dprintk("RPC: %4d call_verify: call rejected %d\n",
 						task->tk_pid, n);
 		rpc_exit(task, error);
@@ -1012,6 +1028,9 @@ call_verify(struct rpc_task *task)
 		printk(KERN_WARNING "call_verify: auth check failed\n");
 		goto garbage;		/* bad verifier, retry */
 	}
+	len = p - (u32 *)iov->iov_base - 1;
+	if (len < 0)
+		goto garbage;
 	switch ((n = ntohl(*p++))) {
 	case RPC_SUCCESS:
 		return p;
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index ae45a763a..aa2205a2c 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -698,7 +698,7 @@ __rpc_execute(struct rpc_task *task)
 		if (current->pid == rpciod_pid)
 			printk(KERN_ERR "RPC: rpciod waiting on sync task!\n");
 
-		if (!task->tk_client->cl_intr) {
+		if (RPC_TASK_UNINTERRUPTIBLE(task)) {
 			__wait_event(task->tk_wait, !RPC_IS_SLEEPING(task));
 		} else {
 			__wait_event_interruptible(task->tk_wait, !RPC_IS_SLEEPING(task), status);
@@ -884,6 +884,8 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, rpc_action call
 		atomic_inc(&clnt->cl_users);
 		if (clnt->cl_softrtry)
 			task->tk_flags |= RPC_TASK_SOFT;
+		if (!clnt->cl_intr)
+			task->tk_flags |= RPC_TASK_NOINTR;
 	}
 
 #ifdef RPC_DEBUG
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index b6ef7772b..51f0392ae 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -89,6 +89,7 @@ EXPORT_SYMBOL(svc_makesock);
 EXPORT_SYMBOL(svc_reserve);
 EXPORT_SYMBOL(svc_auth_register);
 EXPORT_SYMBOL(auth_domain_lookup);
+EXPORT_SYMBOL(svc_authenticate);
 
 /* RPC statistics */
 #ifdef CONFIG_PROC_FS
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index db65a24a1..8c5b0517d 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -263,6 +263,7 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
 	u32			*statp;
 	u32			dir, prog, vers, proc,
 				auth_stat, rpc_stat;
+	int			auth_res;
 
 	rpc_stat = rpc_success;
 
@@ -304,12 +305,17 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
 	rqstp->rq_vers = vers = ntohl(svc_getu32(argv));	/* version number */
 	rqstp->rq_proc = proc = ntohl(svc_getu32(argv));	/* procedure number */
 
+	progp = serv->sv_program;
 	/*
 	 * Decode auth data, and add verifier to reply buffer.
 	 * We do this before anything else in order to get a decent
 	 * auth verifier.
 	 */
-	switch (svc_authenticate(rqstp, &auth_stat)) {
+	if (progp->pg_authenticate != NULL)
+		auth_res = progp->pg_authenticate(rqstp, &auth_stat);
+	else
+		auth_res = svc_authenticate(rqstp, &auth_stat);
+	switch (auth_res) {
 	case SVC_OK:
 		break;
 	case SVC_GARBAGE:
@@ -326,7 +332,6 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
 		goto sendit;
 	}
 		
-	progp = serv->sv_program;
 	if (prog != progp->pg_prog)
 		goto err_bad_prog;
 
diff --git a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c
index 54ea89629..d9f09e61d 100644
--- a/net/sunrpc/svcauth.c
+++ b/net/sunrpc/svcauth.c
@@ -156,25 +156,49 @@ static inline int auth_domain_match(struct auth_domain *tmp, struct auth_domain
 {
 	return strcmp(tmp->name, item->name) == 0;
 }
-DefineCacheLookup(struct auth_domain,
-		  h,
-		  auth_domain_lookup,
-		  (struct auth_domain *item, int set),
-		  /* no setup */,
-		  &auth_domain_cache,
-		  auth_domain_hash(item),
-		  auth_domain_match(tmp, item),
-		  kfree(new); if(!set) {
-			if (new)
-				write_unlock(&auth_domain_cache.hash_lock);
-			else
-				read_unlock(&auth_domain_cache.hash_lock);
-			return NULL;
-		  }
-		  new=item; atomic_inc(&new->h.refcnt),
-		  /* no update */,
-		  0 /* no inplace updates */
-		  )
+
+struct auth_domain *
+auth_domain_lookup(struct auth_domain *item, int set)
+{
+	struct auth_domain *tmp = NULL;
+	struct cache_head **hp, **head;
+	head = &auth_domain_cache.hash_table[auth_domain_hash(item)];
+
+	if (set)
+		write_lock(&auth_domain_cache.hash_lock);
+	else
+		read_lock(&auth_domain_cache.hash_lock);
+	for (hp=head; *hp != NULL; hp = &tmp->h.next) {
+		tmp = container_of(*hp, struct auth_domain, h);
+		if (!auth_domain_match(tmp, item))
+			continue;
+		cache_get(&tmp->h);
+		if (!set)
+			goto out_noset;
+		*hp = tmp->h.next;
+		tmp->h.next = NULL;
+		clear_bit(CACHE_HASHED, &tmp->h.flags);
+		auth_domain_drop(&tmp->h, &auth_domain_cache);
+		goto out_set;
+	}
+	/* Didn't find anything */
+	if (!set)
+		goto out_nada;
+	auth_domain_cache.entries++;
+out_set:
+	set_bit(CACHE_HASHED, &item->h.flags);
+	item->h.next = *head;
+	*head = &item->h;
+	write_unlock(&auth_domain_cache.hash_lock);
+	cache_fresh(&auth_domain_cache, &item->h, item->h.expiry_time);
+	cache_get(&item->h);
+	return item;
+out_nada:
+	tmp = NULL;
+out_noset:
+	read_unlock(&auth_domain_cache.hash_lock);
+	return tmp;
+}
 
 struct auth_domain *auth_domain_find(char *name)
 {
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 6d98c3bc6..b370aad96 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -55,12 +55,10 @@ struct auth_domain *unix_domain_find(char *name)
 	if (new == NULL)
 		return NULL;
 	cache_init(&new->h.h);
-	atomic_inc(&new->h.h.refcnt);
 	new->h.name = strdup(name);
 	new->h.flavour = RPC_AUTH_UNIX;
 	new->addr_changes = 0;
 	new->h.h.expiry_time = NEVER;
-	new->h.h.flags = 0;
 
 	rv = auth_domain_lookup(&new->h, 2);
 	if (rv == &new->h) {
@@ -92,7 +90,7 @@ static void svcauth_unix_domain_release(struct auth_domain *dom)
 
 struct ip_map {
 	struct cache_head	h;
-	char			*m_class; /* e.g. "nfsd" */
+	char			m_class[8]; /* e.g. "nfsd" */
 	struct in_addr		m_addr;
 	struct unix_domain	*m_client;
 	int			m_add_change;
@@ -122,8 +120,7 @@ static inline int ip_map_match(struct ip_map *item, struct ip_map *tmp)
 }
 static inline void ip_map_init(struct ip_map *new, struct ip_map *item)
 {
-	new->m_class = item->m_class;
-	item->m_class = NULL;
+	strcpy(new->m_class, item->m_class);
 	new->m_addr.s_addr = item->m_addr.s_addr;
 }
 static inline void ip_map_update(struct ip_map *new, struct ip_map *item)
@@ -172,6 +169,8 @@ static int ip_map_parse(struct cache_detail *cd,
 	/* class */
 	len = qword_get(&mesg, class, 50);
 	if (len <= 0) return -EINVAL;
+	if (len >= sizeof(ipm.m_class))
+		return -EINVAL;
 
 	/* ip address */
 	len = qword_get(&mesg, buf, 50);
@@ -195,9 +194,7 @@ static int ip_map_parse(struct cache_detail *cd,
 	} else
 		dom = NULL;
 
-	ipm.m_class = strdup(class);
-	if (ipm.m_class == NULL)
-		return -ENOMEM;
+	strcpy(ipm.m_class, class);
 	ipm.m_addr.s_addr =
 		htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
 	ipm.h.flags = 0;
@@ -213,7 +210,6 @@ static int ip_map_parse(struct cache_detail *cd,
 		ip_map_put(&ipmp->h, &ip_map_cache);
 	if (dom)
 		auth_domain_put(dom);
-	if (ipm.m_class) kfree(ipm.m_class);
 	if (!ipmp)
 		return -ENOMEM;
 	cache_flush();
@@ -273,9 +269,7 @@ int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom)
 	if (dom->flavour != RPC_AUTH_UNIX)
 		return -EINVAL;
 	udom = container_of(dom, struct unix_domain, h);
-	ip.m_class = strdup("nfsd");
-	if (!ip.m_class)
-		return -ENOMEM;
+	strcpy(ip.m_class, "nfsd");
 	ip.m_addr = addr;
 	ip.m_client = udom;
 	ip.m_add_change = udom->addr_changes+1;
@@ -283,7 +277,7 @@ int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom)
 	ip.h.expiry_time = NEVER;
 	
 	ipmp = ip_map_lookup(&ip, 1);
-	if (ip.m_class) kfree(ip.m_class);
+
 	if (ipmp) {
 		ip_map_put(&ipmp->h, &ip_map_cache);
 		return 0;
@@ -307,7 +301,7 @@ struct auth_domain *auth_unix_lookup(struct in_addr addr)
 	struct ip_map key, *ipm;
 	struct auth_domain *rv;
 
-	key.m_class = "nfsd";
+	strcpy(key.m_class, "nfsd");
 	key.m_addr = addr;
 
 	ipm = ip_map_lookup(&key, 0);
@@ -318,7 +312,8 @@ struct auth_domain *auth_unix_lookup(struct in_addr addr)
 		return NULL;
 
 	if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) {
-		set_bit(CACHE_NEGATIVE, &ipm->h.flags);
+		if (test_and_set_bit(CACHE_NEGATIVE, &ipm->h.flags) == 0)
+			auth_domain_put(&ipm->m_client->h);
 		rv = NULL;
 	} else {
 		rv = &ipm->m_client->h;
@@ -368,7 +363,7 @@ svcauth_null_accept(struct svc_rqst *rqstp, u32 *authp)
 	svc_putu32(resv, RPC_AUTH_NULL);
 	svc_putu32(resv, 0);
 
-	key.m_class = rqstp->rq_server->sv_program->pg_class;
+	strcpy(key.m_class, rqstp->rq_server->sv_program->pg_class);
 	key.m_addr = rqstp->rq_addr.sin_addr;
 
 	ipm = ip_map_lookup(&key, 0);
@@ -405,6 +400,9 @@ svcauth_null_release(struct svc_rqst *rqstp)
 	if (rqstp->rq_client)
 		auth_domain_put(rqstp->rq_client);
 	rqstp->rq_client = NULL;
+	if (rqstp->rq_cred.cr_group_info)
+		put_group_info(rqstp->rq_cred.cr_group_info);
+	rqstp->rq_cred.cr_group_info = NULL;
 
 	return 0; /* don't drop */
 }
@@ -461,7 +459,7 @@ svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp)
 	}
 
 
-	key.m_class = rqstp->rq_server->sv_program->pg_class;
+	strcpy(key.m_class, rqstp->rq_server->sv_program->pg_class);
 	key.m_addr = rqstp->rq_addr.sin_addr;
 
 
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index a7ab07fe5..de4bccc1c 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -753,7 +753,7 @@ udp_data_ready(struct sock *sk, int len)
 	struct rpc_rqst *rovr;
 	struct sk_buff	*skb;
 	int err, repsize, copied;
-	u32 xid;
+	u32 _xid, *xp;
 
 	read_lock(&sk->sk_callback_lock);
 	dprintk("RPC:      udp_data_ready...\n");
@@ -777,12 +777,14 @@ udp_data_ready(struct sock *sk, int len)
 	}
 
 	/* Copy the XID from the skb... */
-	if (skb_copy_bits(skb, sizeof(struct udphdr), &xid, sizeof(xid)) < 0)
+	xp = skb_header_pointer(skb, sizeof(struct udphdr),
+				sizeof(_xid), &_xid);
+	if (xp == NULL)
 		goto dropit;
 
 	/* Look up and lock the request corresponding to the given XID */
 	spin_lock(&xprt->sock_lock);
-	rovr = xprt_lookup_rqst(xprt, xid);
+	rovr = xprt_lookup_rqst(xprt, *xp);
 	if (!rovr)
 		goto out_unlock;
 	task = rovr->rq_task;
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 08432ceda..828d62c9f 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -147,7 +147,7 @@ static inline unsigned unix_hash_fold(unsigned hash)
 	return hash&(UNIX_HASH_SIZE-1);
 }
 
-#define unix_peer(sk) ((sk)->sk_pair)
+#define unix_peer(sk) (unix_sk(sk)->peer)
 
 static inline int unix_our_peer(struct sock *sk, struct sock *osk)
 {
diff --git a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c
index 4776ec1ea..5acdc5a51 100644
--- a/net/wanrouter/af_wanpipe.c
+++ b/net/wanrouter/af_wanpipe.c
@@ -2423,7 +2423,6 @@ static int wanpipe_accept(struct socket *sock, struct socket *newsock, int flags
 	write_unlock(&wanpipe_sklist_lock);
 	clear_bit(1,&wanpipe_tx_critical);
 
-	newsk->sk_pair = NULL;
 	newsk->sk_socket = newsock;
 	newsk->sk_sleep = &newsock->wait;
 
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 17d20343a..be33fd881 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -769,7 +769,6 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
 	if (!skb->sk)
 		goto out2;
 	newsk		 = skb->sk;
-	newsk->sk_pair   = NULL;
 	newsk->sk_socket = newsock;
 	newsk->sk_sleep  = &newsock->wait;
 
@@ -887,7 +886,6 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
 	makex25->state = X25_STATE_3;
 
 	sk->sk_ack_backlog++;
-	make->sk_pair = sk;
 
 	x25_insert_socket(make);
 
diff --git a/net/xfrm/xfrm_export.c b/net/xfrm/xfrm_export.c
index f72754953..9f335640d 100644
--- a/net/xfrm/xfrm_export.c
+++ b/net/xfrm/xfrm_export.c
@@ -33,8 +33,6 @@ EXPORT_SYMBOL(secpath_dup);
 EXPORT_SYMBOL(xfrm_get_acqseq);
 EXPORT_SYMBOL(xfrm_parse_spi);
 EXPORT_SYMBOL(xfrm4_rcv);
-EXPORT_SYMBOL(xfrm4_tunnel_register);
-EXPORT_SYMBOL(xfrm4_tunnel_deregister);
 EXPORT_SYMBOL(xfrm_register_type);
 EXPORT_SYMBOL(xfrm_unregister_type);
 EXPORT_SYMBOL(xfrm_get_type);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index e7db9f8b7..8967012a0 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -711,25 +711,11 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
 {
 	struct xfrm_policy *policy;
 	struct xfrm_state *xfrm[XFRM_MAX_DEPTH];
-	struct rtable *rt = (struct rtable*)*dst_p;
-	struct dst_entry *dst;
+	struct dst_entry *dst, *dst_orig = *dst_p;
 	int nx = 0;
 	int err;
 	u32 genid;
-	u16 family = (*dst_p)->ops->family;
-
-	switch (family) {
-	case AF_INET:
-		if (!fl->fl4_src)
-			fl->fl4_src = rt->rt_src;
-		if (!fl->fl4_dst)
-			fl->fl4_dst = rt->rt_dst;
-	case AF_INET6:
-		/* Still not clear... */
-	default:
-		/* nothing */;
-	}
-
+	u16 family = dst_orig->ops->family;
 restart:
 	genid = atomic_read(&flow_cache_genid);
 	policy = NULL;
@@ -738,7 +724,7 @@ restart:
 
 	if (!policy) {
 		/* To accelerate a bit...  */
-		if ((rt->u.dst.flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT])
+		if ((dst_orig->flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT])
 			return 0;
 
 		policy = flow_cache_lookup(fl, family,
@@ -813,7 +799,7 @@ restart:
 			return 0;
 		}
 
-		dst = &rt->u.dst;
+		dst = dst_orig;
 		err = xfrm_bundle_create(policy, xfrm, nx, fl, &dst, family);
 
 		if (unlikely(err)) {
@@ -843,12 +829,12 @@ restart:
 		write_unlock_bh(&policy->lock);
 	}
 	*dst_p = dst;
-	ip_rt_put(rt);
+	dst_release(dst_orig);
 	xfrm_pol_put(policy);
 	return 0;
 
 error:
-	ip_rt_put(rt);
+	dst_release(dst_orig);
 	xfrm_pol_put(policy);
 	*dst_p = NULL;
 	return err;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index f45fa55c2..2317ae179 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -387,13 +387,17 @@ void xfrm_state_insert(struct xfrm_state *x)
 	spin_unlock_bh(&xfrm_state_lock);
 }
 
+static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq);
+
 int xfrm_state_add(struct xfrm_state *x)
 {
 	struct xfrm_state_afinfo *afinfo;
 	struct xfrm_state *x1;
+	int family;
 	int err;
 
-	afinfo = xfrm_state_get_afinfo(x->props.family);
+	family = x->props.family;
+	afinfo = xfrm_state_get_afinfo(family);
 	if (unlikely(afinfo == NULL))
 		return -EAFNOSUPPORT;
 
@@ -407,9 +411,18 @@ int xfrm_state_add(struct xfrm_state *x)
 		goto out;
 	}
 
-	x1 = afinfo->find_acq(
-		x->props.mode, x->props.reqid, x->id.proto,
-		&x->id.daddr, &x->props.saddr, 0);
+	if (x->km.seq) {
+		x1 = __xfrm_find_acq_byseq(x->km.seq);
+		if (x1 && xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family)) {
+			xfrm_state_put(x1);
+			x1 = NULL;
+		}
+	}
+
+	if (!x1)
+		x1 = afinfo->find_acq(
+			x->props.mode, x->props.reqid, x->id.proto,
+			&x->id.daddr, &x->props.saddr, 0);
 
 	__xfrm_state_insert(x);
 	err = 0;
@@ -570,24 +583,31 @@ xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
 
 /* Silly enough, but I'm lazy to build resolution list */
 
-struct xfrm_state * xfrm_find_acq_byseq(u32 seq)
+static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq)
 {
 	int i;
 	struct xfrm_state *x;
 
-	spin_lock_bh(&xfrm_state_lock);
 	for (i = 0; i < XFRM_DST_HSIZE; i++) {
 		list_for_each_entry(x, xfrm_state_bydst+i, bydst) {
 			if (x->km.seq == seq) {
 				xfrm_state_hold(x);
-				spin_unlock_bh(&xfrm_state_lock);
 				return x;
 			}
 		}
 	}
-	spin_unlock_bh(&xfrm_state_lock);
 	return NULL;
 }
+
+struct xfrm_state *xfrm_find_acq_byseq(u32 seq)
+{
+	struct xfrm_state *x;
+
+	spin_lock_bh(&xfrm_state_lock);
+	x = __xfrm_find_acq_byseq(seq);
+	spin_unlock_bh(&xfrm_state_lock);
+	return x;
+}
  
 u32 xfrm_get_acqseq(void)
 {
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index eccc0231f..db2087c26 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -78,15 +78,6 @@ static int verify_encap_tmpl(struct rtattr **xfrma)
 	if ((rt->rta_len - sizeof(*rt)) < sizeof(*encap))
 		return -EINVAL;
 
-	encap = RTA_DATA(rt);
-	switch (encap->encap_type) {
-	case UDP_ENCAP_ESPINUDP:
-	case UDP_ENCAP_ESPINUDP_NON_IKE:
-		break;
-	default:
-		return -ENOPROTOOPT;
-	}
-
 	return 0;
 }
 
@@ -164,15 +155,24 @@ out:
 	return err;
 }
 
-static int attach_one_algo(struct xfrm_algo **algpp, struct rtattr *u_arg)
+static int attach_one_algo(struct xfrm_algo **algpp, u8 *props,
+			   struct xfrm_algo_desc *(*get_byname)(char *),
+			   struct rtattr *u_arg)
 {
 	struct rtattr *rta = u_arg;
 	struct xfrm_algo *p, *ualg;
+	struct xfrm_algo_desc *algo;
 
 	if (!rta)
 		return 0;
 
 	ualg = RTA_DATA(rta);
+
+	algo = get_byname(ualg->alg_name);
+	if (!algo)
+		return -ENOSYS;
+	*props = algo->desc.sadb_alg_id;
+
 	p = kmalloc(sizeof(*ualg) + ualg->alg_key_len, GFP_KERNEL);
 	if (!p)
 		return -ENOMEM;
@@ -225,11 +225,17 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p,
 
 	copy_from_user_state(x, p);
 
-	if ((err = attach_one_algo(&x->aalg, xfrma[XFRMA_ALG_AUTH-1])))
+	if ((err = attach_one_algo(&x->aalg, &x->props.aalgo,
+				   xfrm_aalg_get_byname,
+				   xfrma[XFRMA_ALG_AUTH-1])))
 		goto error;
-	if ((err = attach_one_algo(&x->ealg, xfrma[XFRMA_ALG_CRYPT-1])))
+	if ((err = attach_one_algo(&x->ealg, &x->props.ealgo,
+				   xfrm_ealg_get_byname,
+				   xfrma[XFRMA_ALG_CRYPT-1])))
 		goto error;
-	if ((err = attach_one_algo(&x->calg, xfrma[XFRMA_ALG_COMP-1])))
+	if ((err = attach_one_algo(&x->calg, &x->props.calgo,
+				   xfrm_calg_get_byname,
+				   xfrma[XFRMA_ALG_COMP-1])))
 		goto error;
 	if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1])))
 		goto error;
@@ -464,16 +470,32 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, void **
 	struct xfrm_state *x;
 	struct xfrm_userspi_info *p;
 	struct sk_buff *resp_skb;
+	xfrm_address_t *daddr;
+	int family;
 	int err;
 
 	p = NLMSG_DATA(nlh);
 	err = verify_userspi_info(p);
 	if (err)
 		goto out_noput;
-	x = xfrm_find_acq(p->info.mode, p->info.reqid, p->info.id.proto,
-			  &p->info.id.daddr,
-			  &p->info.saddr, 1,
-			  p->info.family);
+
+	family = p->info.family;
+	daddr = &p->info.id.daddr;
+
+	x = NULL;
+	if (p->info.seq) {
+		x = xfrm_find_acq_byseq(p->info.seq);
+		if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) {
+			xfrm_state_put(x);
+			x = NULL;
+		}
+	}
+
+	if (!x)
+		x = xfrm_find_acq(p->info.mode, p->info.reqid,
+				  p->info.id.proto, daddr,
+				  &p->info.saddr, 1,
+				  family);
 	err = -ENOENT;
 	if (x == NULL)
 		goto out_noput;
diff --git a/scripts/Makefile b/scripts/Makefile
index 81c913c1e..67763eeb8 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -2,14 +2,21 @@
 # scripts contains sources for various helper programs used throughout
 # the kernel for the build process.
 # ---------------------------------------------------------------------------
-# docproc: 	 Preprocess .tmpl file in order to generate .sgml docs
+# kallsyms:      Find all symbols in vmlinux
+# pnmttologo:    Convert pnm files to logo files
+# conmakehash:   Create chartable
 # conmakehash:	 Create arrays for initializing the kernel console tables
 
-host-progs	:= conmakehash kallsyms pnmtologo bin2c
-always		:= $(host-progs)
+hostprogs-$(CONFIG_KALLSYMS)     += kallsyms
+hostprogs-$(CONFIG_LOGO)         += pnmtologo
+hostprogs-$(CONFIG_VT)           += conmakehash
+hostprogs-$(CONFIG_PROM_CONSOLE) += conmakehash
+hostprogs-$(CONFIG_IKCONFIG)     += bin2c
 
-subdir-$(CONFIG_MODVERSIONS)	+= genksyms
-subdir-y	+= mod
+always		:= $(hostprogs-y)
+
+subdir-$(CONFIG_MODVERSIONS) += genksyms
+subdir-$(CONFIG_MODULES)     += mod
 
 # Let clean descend into subdirs
 subdir-	+= basic lxdialog kconfig package
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 008ac6cfd..672b0082e 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -14,6 +14,18 @@ include $(obj)/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))
@@ -71,8 +83,13 @@ __build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
 
 # Linus' kernel sanity checking tool
 ifneq ($(KBUILD_CHECKSRC),0)
-quiet_cmd_checksrc = CHECK   $<
-      cmd_checksrc = $(CHECK) $(c_flags) $< ;
+  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
 
 
@@ -143,9 +160,7 @@ else
 
 cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $<
 cmd_modversions =							\
-	if ! $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then	\
-		mv $(@D)/.tmp_$(@F) $@;					\
-	else								\
+	if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then	\
 		$(CPP) -D__GENKSYMS__ $(c_flags) $<			\
 		| $(GENKSYMS)						\
 		> $(@D)/.tmp_$(@F:.o=.ver);				\
@@ -153,6 +168,8 @@ cmd_modversions =							\
 		$(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 $(@D)/.tmp_$(@F) $@;					\
 	fi;
 endif
 
@@ -170,11 +187,13 @@ endef
 # Built-in and composite module parts
 
 %.o: %.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): %.o: %.c FORCE
+	$(call cmd,force_checksrc)
 	$(call if_changed_rule,cc_o_c)
 	@{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod)
 
@@ -209,6 +228,14 @@ cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $<
 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 $@ $<
+
+%.lds: %.lds.S FORCE
+	$(call if_changed_dep,cpp_lds_S)
+
 # Build the compiled-in targets
 # ---------------------------------------------------------------------------
 
@@ -275,90 +302,6 @@ $(multi-used-m) : %.o: $(multi-objs-m) FORCE
 
 targets += $(multi-used-y) $(multi-used-m)
 
-# Compile programs on the host
-# ===========================================================================
-# host-progs := bin2hex
-# Will compile bin2hex.c and create an executable named bin2hex
-#
-# host-progs    := lxdialog
-# lxdialog-objs := checklist.o lxdialog.o
-# Will compile lxdialog.c and checklist.c, and then link the executable
-# lxdialog, based on checklist.o and lxdialog.o
-#
-# host-progs      := qconf
-# qconf-cxxobjs   := qconf.o
-# qconf-objs      := menu.o
-# Will compile qconf as a C++ program, and menu as a C program.
-# They are linked as C++ code to the executable qconf
-
-# host-progs := conf
-# conf-objs  := conf.o libkconfig.so
-# libkconfig-objs := expr.o type.o
-# Will create a shared library named libkconfig.so that consist of
-# expr.o and type.o (they are both compiled as C code and the object file
-# are made as position independent code).
-# conf.c is compiled as a c program, and conf.o is linked together with
-# libkconfig.so as the executable conf.
-# Note: Shared libraries consisting of C++ files are not supported  
-#
-
-# Create executable from a single .c file
-# host-csingle -> Executable
-quiet_cmd_host-csingle 	= HOSTCC  $@
-      cmd_host-csingle	= $(HOSTCC) $(hostc_flags) $(HOST_LOADLIBES) -o $@ $<
-$(host-csingle): %: %.c FORCE
-	$(call if_changed_dep,host-csingle)
-
-# Link an executable based on list of .o files, all plain c
-# host-cmulti -> executable
-quiet_cmd_host-cmulti	= HOSTLD  $@
-      cmd_host-cmulti	= $(HOSTCC) $(HOSTLDFLAGS) -o $@ \
-			  $(addprefix $(obj)/,$($(@F)-objs)) \
-			  $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
-$(host-cmulti): %: $(host-cobjs) $(host-cshlib) FORCE
-	$(call if_changed,host-cmulti)
-
-# Create .o file from a single .c file
-# host-cobjs -> .o
-quiet_cmd_host-cobjs	= HOSTCC  $@
-      cmd_host-cobjs	= $(HOSTCC) $(hostc_flags) -c -o $@ $<
-$(host-cobjs): %.o: %.c FORCE
-	$(call if_changed_dep,host-cobjs)
-
-# Link an executable based on list of .o files, a mixture of .c and .cc
-# host-cxxmulti -> executable
-quiet_cmd_host-cxxmulti	= HOSTLD  $@
-      cmd_host-cxxmulti	= $(HOSTCXX) $(HOSTLDFLAGS) -o $@ \
-			  $(foreach o,objs cxxobjs,\
-			  $(addprefix $(obj)/,$($(@F)-$(o)))) \
-			  $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
-$(host-cxxmulti): %: $(host-cobjs) $(host-cxxobjs) $(host-cshlib) FORCE
-	$(call if_changed,host-cxxmulti)
-
-# Create .o file from a single .cc (C++) file
-quiet_cmd_host-cxxobjs	= HOSTCXX $@
-      cmd_host-cxxobjs	= $(HOSTCXX) $(hostcxx_flags) -c -o $@ $<
-$(host-cxxobjs): %.o: %.cc FORCE
-	$(call if_changed_dep,host-cxxobjs)
-
-# Compile .c file, create position independent .o file
-# host-cshobjs -> .o
-quiet_cmd_host-cshobjs	= HOSTCC  -fPIC $@
-      cmd_host-cshobjs	= $(HOSTCC) $(hostc_flags) -fPIC -c -o $@ $<
-$(host-cshobjs): %.o: %.c FORCE
-	$(call if_changed_dep,host-cshobjs)
-
-# Link a shared library, based on position independent .o files
-# *.o -> .so shared library (host-cshlib)
-quiet_cmd_host-cshlib	= HOSTLLD -shared $@
-      cmd_host-cshlib	= $(HOSTCC) $(HOSTLDFLAGS) -shared -o $@ \
-			  $(addprefix $(obj)/,$($(@F:.so=-objs))) \
-			  $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
-$(host-cshlib): %: $(host-cshobjs) FORCE
-	$(call if_changed,host-cshlib)
-
-targets += $(host-csingle)  $(host-cmulti) $(host-cobjs)\
-	   $(host-cxxmulti) $(host-cxxobjs) $(host-cshlib) $(host-cshobjs) 
 
 # Descending
 # ---------------------------------------------------------------------------
diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
index 7277dd208..b02ab1fb2 100644
--- a/scripts/Makefile.clean
+++ b/scripts/Makefile.clean
@@ -29,21 +29,49 @@ subdir-ymn      := $(sort $(subdir-ym) $(subdir-n) $(subdir-))
 # Add subdir path
 
 subdir-ymn	:= $(addprefix $(obj)/,$(subdir-ymn))
-__clean-files	:= $(wildcard $(addprefix $(obj)/, \
-		   $(extra-y) $(EXTRA_TARGETS) $(always) $(host-progs) \
-		   $(targets) $(clean-files)))
+
+# build a list of files to remove, usually releative to the current
+# directory
+
+__clean-files	:= $(extra-y) $(EXTRA_TARGETS) $(always) \
+		   $(targets) $(clean-files)             \
+		   $(host-progs)                         \
+		   $(hostprogs-y) $(hostprogs-m) $(hostprogs-)
+
+# as clean-files is given relative to the current directory, this adds
+# a $(obj) prefix, except for absolute paths
+
+__clean-files   := $(wildcard                                               \
+                   $(addprefix $(obj)/, $(filter-out /%, $(__clean-files))) \
+		   $(filter /%, $(__clean-files)))
+
+# as clean-dirs is given relative to the current directory, this adds
+# a $(obj) prefix, except for absolute paths
+
+__clean-dirs    := $(wildcard                                               \
+                   $(addprefix $(obj)/, $(filter-out /%, $(clean-dirs)))    \
+		   $(filter /%, $(clean-dirs)))
 
 # ==========================================================================
 
-quiet_cmd_clean = CLEAN   $(obj)
-      cmd_clean = rm -f $(__clean-files); $(clean-rule)
+quiet_cmd_clean    = CLEAN   $(obj)
+      cmd_clean    = rm -f $(__clean-files)
+quiet_cmd_cleandir = CLEAN   $(__clean-dirs)
+      cmd_cleandir = rm -rf $(__clean-dirs)
+
 
 __clean: $(subdir-ymn)
-ifneq ($(strip $(__clean-files) $(clean-rule)),)
+ifneq ($(strip $(__clean-files)),)
 	+$(call cmd,clean)
-else
-	@:
 endif
+ifneq ($(strip $(__clean-dirs)),)
+	+$(call cmd,cleandir)
+endif
+ifneq ($(strip $(clean-rule)),)
+	+$(clean-rule)
+endif
+	@:
+
 
 # ===========================================================================
 # Generic stuff
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index a47abc8af..3a7663b90 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -60,41 +60,11 @@ subdir-obj-y := $(foreach o,$(obj-y),$(if $(filter-out $(o),$(notdir $(o))),$(o)
 
 # $(obj-dirs) is a list of directories that contain object files
 obj-dirs := $(dir $(multi-objs) $(subdir-obj-y))
-obj-dirs += $(foreach f,$(host-progs), $(if $(dir $(f)),$(dir $(f))))
-obj-dirs := $(strip $(sort $(filter-out ./,$(obj-dirs))))
 
 # Replace multi-part objects by their individual parts, look at local dir only
 real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) $(extra-y)
 real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m)))
 
-# C code
-# Executables compiled from a single .c file
-host-csingle	:= $(foreach m,$(host-progs),$(if $($(m)-objs),,$(m)))
-
-# C executables linked based on several .o files
-host-cmulti	:= $(foreach m,$(host-progs),\
-		   $(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m))))
-
-# Object (.o) files compiled from .c files
-host-cobjs	:= $(sort $(foreach m,$(host-progs),$($(m)-objs)))
-
-# C++ code
-# C++ executables compiled from at least on .cc file
-# and zero or more .c files
-host-cxxmulti	:= $(foreach m,$(host-progs),$(if $($(m)-cxxobjs),$(m)))
-
-# C++ Object (.o) files compiled from .cc files
-host-cxxobjs	:= $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs)))
-
-# Shared libaries (only .c supported)
-# Shared libraries (.so) - all .so files referenced in "xxx-objs"
-host-cshlib	:= $(sort $(filter %.so, $(host-cobjs)))
-# Remove .so files from "xxx-objs"
-host-cobjs	:= $(filter-out %.so,$(host-cobjs))
-
-#Object (.o) files used by the shared libaries
-host-cshobjs	:= $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs))))
-
 # Add subdir path
 
 extra-y		:= $(addprefix $(obj)/,$(extra-y))
@@ -113,14 +83,6 @@ multi-objs-y	:= $(addprefix $(obj)/,$(multi-objs-y))
 multi-objs-m	:= $(addprefix $(obj)/,$(multi-objs-m))
 subdir-ym	:= $(addprefix $(obj)/,$(subdir-ym))
 obj-dirs	:= $(addprefix $(obj)/,$(obj-dirs))
-host-progs      := $(addprefix $(obj)/,$(host-progs))
-host-csingle	:= $(addprefix $(obj)/,$(host-csingle))
-host-cmulti	:= $(addprefix $(obj)/,$(host-cmulti))
-host-cobjs	:= $(addprefix $(obj)/,$(host-cobjs))
-host-cxxmulti	:= $(addprefix $(obj)/,$(host-cxxmulti))
-host-cxxobjs	:= $(addprefix $(obj)/,$(host-cxxobjs))
-host-cshlib	:= $(addprefix $(obj)/,$(host-cshlib))
-host-cshobjs	:= $(addprefix $(obj)/,$(host-cshobjs))
 
 # The temporary file to save gcc -MD generated dependencies must not
 # contain a comma
@@ -136,12 +98,9 @@ depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
 basename_flags = -DKBUILD_BASENAME=$(subst $(comma),_,$(subst -,_,$(*F)))
 modname_flags  = $(if $(filter 1,$(words $(modname))),-DKBUILD_MODNAME=$(subst $(comma),_,$(subst -,_,$(modname))))
 
-
 _c_flags       = $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o)
 _a_flags       = $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$(*F).o)
-_hostc_flags   = $(HOSTCFLAGS)   $(HOST_EXTRACFLAGS)   $(HOSTCFLAGS_$(*F).o)
-_hostcxx_flags = $(HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) $(HOSTCXXFLAGS_$(*F).o)
-
+_cpp_flags     = $(CPPFLAGS) $(EXTRA_CPPFLAGS) $(CPPFLAGS_$(@F))
 
 # If building the kernel in a separate objtree expand all occurrences
 # of -Idir to -I$(srctree)/dir except for absolute paths (starting with '/').
@@ -149,8 +108,7 @@ _hostcxx_flags = $(HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) $(HOSTCXXFLAGS_$(*F).o)
 ifeq ($(KBUILD_SRC),)
 __c_flags	= $(_c_flags)
 __a_flags	= $(_a_flags)
-__hostc_flags	= $(_hostc_flags)
-__hostcxx_flags	= $(_hostcxx_flags)
+__cpp_flags     = $(_cpp_flags)
 else
 
 # Prefix -I with $(srctree) if it is not an absolute path
@@ -164,8 +122,7 @@ flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o)))
 # FIXME: Replace both with specific CFLAGS* statements in the makefiles
 __c_flags	= $(call addtree,-I$(obj)) $(call flags,_c_flags)
 __a_flags	=                          $(call flags,_a_flags)
-__hostc_flags	= -I$(obj)                 $(call flags,_hostc_flags)
-__hostcxx_flags	= -I$(obj)                 $(call flags,_hostcxx_flags)
+__cpp_flags     =                          $(call flags,_cpp_flags)
 endif
 
 c_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \
@@ -175,8 +132,7 @@ c_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \
 a_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(CPPFLAGS) \
 		 $(__a_flags) $(modkern_aflags)
 
-hostc_flags    = -Wp,-MD,$(depfile) $(__hostc_flags)
-hostcxx_flags  = -Wp,-MD,$(depfile) $(__hostcxx_flags)
+cpp_flags      = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(__cpp_flags)
 
 ld_flags       = $(LDFLAGS) $(EXTRA_LDFLAGS)
 
diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst
index 2f997b9b1..b9ab77d5d 100644
--- a/scripts/Makefile.modinst
+++ b/scripts/Makefile.modinst
@@ -9,7 +9,7 @@ include scripts/Makefile.lib
 
 #
 
-__modules := $(sort $(shell head -q -n1 /dev/null $(wildcard $(MODVERDIR)/*.mod)))
+__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
 modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o)))
 
 .PHONY: $(modules)
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 19f534527..b3d31b559 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -41,7 +41,7 @@ include scripts/Makefile.lib
 symverfile := $(objtree)/Module.symvers
 
 # Step 1), find all modules listed in $(MODVERDIR)/
-__modules := $(sort $(shell head -q -n1 /dev/null $(wildcard $(MODVERDIR)/*.mod)))
+__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
 modules   := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o)))
 
 _modpost: $(modules)
@@ -50,7 +50,8 @@ _modpost: $(modules)
 # Step 2), invoke modpost
 #  Includes step 3,4
 quiet_cmd_modpost = MODPOST
-      cmd_modpost = scripts/mod/modpost \
+      cmd_modpost = scripts/mod/modpost            \
+        $(if $(CONFIG_MODVERSIONS),-m)             \
 	$(if $(KBUILD_EXTMOD),-i,-o) $(symverfile) \
 	$(filter-out FORCE,$^)
 
diff --git a/scripts/basic/Makefile b/scripts/basic/Makefile
index 3afb3bf4d..f22e94c3a 100644
--- a/scripts/basic/Makefile
+++ b/scripts/basic/Makefile
@@ -11,8 +11,8 @@
 #                include/config/...
 # docproc:	 Used in Documentation/docbook
 
-host-progs	:= fixdep split-include docproc
-always		:= $(host-progs)
+hostprogs-y	:= fixdep split-include docproc
+always		:= $(hostprogs-y)
 
 # fixdep is needed to compile other host programs
 $(addprefix $(obj)/,$(filter-out fixdep,$(always))): $(obj)/fixdep
diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
index 8bd644222..8c4c70395 100644
--- a/scripts/basic/fixdep.c
+++ b/scripts/basic/fixdep.c
@@ -93,6 +93,14 @@
  * (Note: it'd be easy to port over the complete mkdep state machine,
  *  but I don't think the added complexity is worth it)
  */
+/*
+ * Note 2: if somebody writes HELLO_CONFIG_BOOM in a file, it will depend onto
+ * CONFIG_BOOM. This could seem a bug (not too hard to fix), but please do not
+ * fix it! Some UserModeLinux files (look at arch/um/) call CONFIG_BOOM as
+ * UML_CONFIG_BOOM, to avoid conflicts with /usr/include/linux/autoconf.h,
+ * through arch/um/include/uml-config.h; this fixdep "bug" makes sure that
+ * those files will have correct dependencies.
+ */
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -104,7 +112,7 @@
 #include <stdio.h>
 #include <limits.h>
 #include <ctype.h>
-#include <netinet/in.h>
+#include <arpa/inet.h>
 
 #define INT_CONF ntohl(0x434f4e46)
 #define INT_ONFI ntohl(0x4f4e4649)
@@ -310,6 +318,7 @@ void parse_dep_file(void *map, size_t len)
 		}
 		memcpy(s, m, p-m); s[p-m] = 0;
 		if (strrcmp(s, "include/linux/autoconf.h") &&
+		    strrcmp(s, "arch/um/include/uml-config.h") &&
 		    strrcmp(s, ".ver")) {
 			printf("  %s \\\n", s);
 			do_config_file(s);
diff --git a/scripts/binoffset.c b/scripts/binoffset.c
index 7b8100d8e..591309d85 100644
--- a/scripts/binoffset.c
+++ b/scripts/binoffset.c
@@ -41,7 +41,7 @@
 char		*progname;
 char		*inputname;
 int		inputfd;
-int		bix;			/* buf index */
+unsigned int	bix;			/* buf index */
 unsigned char	patterns [PAT_SIZE] = {0}; /* byte-sized pattern array */
 int		pat_len;		/* actual number of pattern bytes */
 unsigned char	*madr;			/* mmap address */
@@ -58,7 +58,7 @@ void usage (void)
 	exit (1);
 }
 
-int get_pattern (int pat_count, char *pats [])
+void get_pattern (int pat_count, char *pats [])
 {
 	int ix, err, tmp;
 
@@ -81,7 +81,7 @@ int get_pattern (int pat_count, char *pats [])
 	pat_len = pat_count;
 }
 
-int search_pattern (void)
+void search_pattern (void)
 {
 	for (bix = 0; bix < filesize; bix++) {
 		if (madr[bix] == patterns[0]) {
@@ -109,7 +109,7 @@ size_t get_filesize (int fd)
 	struct stat stat;
 
 	err = fstat (fd, &stat);
-	fprintf (stderr, "filesize: %d\n", err < 0 ? err : stat.st_size);
+	fprintf (stderr, "filesize: %ld\n", err < 0 ? (long)err : stat.st_size);
 	if (err < 0)
 		return err;
 	return (size_t) stat.st_size;
@@ -154,8 +154,8 @@ int main (int argc, char *argv [])
 	fprintf (stderr, "number of pattern matches = %d\n", num_matches);
 	if (num_matches == 0)
 		firstloc = ~0;
-	printf ("%d\n", firstloc);
-	fprintf (stderr, "%d\n", firstloc);
+	printf ("%ld\n", firstloc);
+	fprintf (stderr, "%ld\n", firstloc);
 
 	exit (num_matches ? 0 : 2);
 }
diff --git a/scripts/genksyms/Makefile b/scripts/genksyms/Makefile
index 76f1fd10e..5875f29a8 100644
--- a/scripts/genksyms/Makefile
+++ b/scripts/genksyms/Makefile
@@ -1,6 +1,6 @@
 
-host-progs	:= genksyms
-always		:= $(host-progs)
+hostprogs-y	:= genksyms
+always		:= $(hostprogs-y)
 
 genksyms-objs	:= genksyms.o parse.o lex.o
 
diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c
index 9cf074bc3..416a694b0 100644
--- a/scripts/genksyms/genksyms.c
+++ b/scripts/genksyms/genksyms.c
@@ -27,7 +27,9 @@
 #include <unistd.h>
 #include <assert.h>
 #include <stdarg.h>
+#ifdef __GNU_LIBRARY__
 #include <getopt.h>
+#endif /* __GNU_LIBRARY__ */
 
 #include "genksyms.h"
 
@@ -502,12 +504,21 @@ void genksyms_usage(void)
 	fputs("Usage:\n"
 	      "genksyms [-dDwqhV] > /path/to/.tmp_obj.ver\n"
 	      "\n"
+#ifdef __GNU_LIBRARY__
 	      "  -d, --debug           Increment the debug level (repeatable)\n"
 	      "  -D, --dump            Dump expanded symbol defs (for debugging only)\n"
 	      "  -w, --warnings        Enable warnings\n"
 	      "  -q, --quiet           Disable warnings (default)\n"
 	      "  -h, --help            Print this message\n"
 	      "  -V, --version         Print the release version\n"
+#else  /* __GNU_LIBRARY__ */
+             "  -d                    Increment the debug level (repeatable)\n"
+             "  -D                    Dump expanded symbol defs (for debugging only)\n"
+             "  -w                    Enable warnings\n"
+             "  -q                    Disable warnings (default)\n"
+             "  -h                    Print this message\n"
+             "  -V                    Print the release version\n"
+#endif /* __GNU_LIBRARY__ */
 	      , stderr);
 }
 
@@ -516,6 +527,7 @@ main(int argc, char **argv)
 {
   int o;
 
+#ifdef __GNU_LIBRARY__
   struct option long_opts[] = {
     {"debug", 0, 0, 'd'},
     {"warnings", 0, 0, 'w'},
@@ -528,6 +540,9 @@ main(int argc, char **argv)
 
   while ((o = getopt_long(argc, argv, "dwqVDk:p:",
 			  &long_opts[0], NULL)) != EOF)
+#else  /* __GNU_LIBRARY__ */
+  while ((o = getopt(argc, argv, "dwqVDk:p:")) != EOF)
+#endif /* __GNU_LIBRARY__ */
     switch (o)
       {
       case 'd':
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 89b986abd..6377641dd 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -67,7 +67,7 @@ help:
 
 libkconfig-objs := zconf.tab.o
 
-host-progs	:= conf mconf qconf gconf
+hostprogs-y	:= conf mconf qconf gconf
 conf-objs	:= conf.o  libkconfig.so
 mconf-objs	:= mconf.o libkconfig.so
 
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 90247d2e8..7b6285e7c 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -8,6 +8,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 #include <unistd.h>
 
 #define LKC_DIRECT_LINK
@@ -268,6 +269,7 @@ int conf_write(const char *name)
 	char dirname[128], tmpname[128], newname[128];
 	int type, l;
 	const char *str;
+	time_t now;
 
 	dirname[0] = 0;
 	if (name && name[0]) {
@@ -301,14 +303,25 @@ int conf_write(const char *name)
 		if (!out_h)
 			return 1;
 	}
+	sym = sym_lookup("KERNELRELEASE", 0);
+	sym_calc_value(sym);
+	time(&now);
 	fprintf(out, "#\n"
 		     "# Automatically generated make config: don't edit\n"
-		     "#\n");
+		     "# Linux kernel version: %s\n"
+		     "# %s"
+		     "#\n",
+		     sym_get_string_value(sym),
+		     ctime(&now));
 	if (out_h)
 		fprintf(out_h, "/*\n"
 			       " * Automatically generated C config: don't edit\n"
+			       " * Linux kernel version: %s\n"
+			       " * %s"
 			       " */\n"
-			       "#define AUTOCONF_INCLUDED\n");
+			       "#define AUTOCONF_INCLUDED\n",
+			       sym_get_string_value(sym),
+			       ctime(&now));
 
 	if (!sym_change_count)
 		sym_clear_all_valid();
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
index 489c4ff02..0b956e32b 100644
--- a/scripts/kconfig/gconf.c
+++ b/scripts/kconfig/gconf.c
@@ -275,9 +275,8 @@ void init_main_window(const gchar * glade_file)
 					  /*"style", PANGO_STYLE_OBLIQUE, */
 					  NULL);
 
-	sprintf(title, "Linux Kernel v%s.%s.%s%s Configuration",
-		getenv("VERSION"), getenv("PATCHLEVEL"),
-		getenv("SUBLEVEL"), getenv("EXTRAVERSION"));
+	sprintf(title, "Linux Kernel v%s Configuration",
+		getenv("KERNELRELEASE"));
 	gtk_window_set_title(GTK_WINDOW(main_wnd), title);
 
 	gtk_widget_show(main_wnd);
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index dd040f7a8..e348ee7d8 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -59,9 +59,6 @@ void menu_set_type(int type);
 struct file *file_lookup(const char *name);
 int file_write_dep(const char *name);
 
-extern struct menu *current_entry;
-extern struct menu *current_menu;
-
 /* symbol.c */
 void sym_init(void);
 void sym_clear_all_valid(void);
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index 6f8bf9904..91789cc9d 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -18,6 +18,7 @@
 #include <string.h>
 #include <termios.h>
 #include <unistd.h>
+#include <regex.h>
 
 #define LKC_DIRECT_LINK
 #include "lkc.h"
@@ -28,7 +29,7 @@ static const char menu_instructions[] =
 	"<Enter> selects submenus --->.  "
 	"Highlighted letters are hotkeys.  "
 	"Pressing <Y> includes, <N> excludes, <M> modularizes features.  "
-	"Press <Esc><Esc> to exit, <?> for Help.  "
+	"Press <Esc><Esc> to exit, <?> for Help, </> for Search.  "
 	"Legend: [*] built-in  [ ] excluded  <M> module  < > module capable",
 radiolist_instructions[] =
 	"Use the arrow keys to navigate this window or "
@@ -102,6 +103,10 @@ static void show_textbox(const char *title, const char *text, int r, int c);
 static void show_helptext(const char *title, const char *text);
 static void show_help(struct menu *menu);
 static void show_readme(void);
+static void show_file(const char *filename, const char *title, int r, int c);
+static void show_expr(struct menu *menu, FILE *fp);
+static void search_conf(char *pattern);
+static int regex_match(const char *string, regex_t *re);
 
 static void cprint_init(void);
 static int cprint1(const char *fmt, ...);
@@ -274,6 +279,114 @@ static int exec_conf(void)
 	return WEXITSTATUS(stat);
 }
 
+static int regex_match(const char *string, regex_t *re)
+{
+	int rc;
+
+	rc = regexec(re, string, (size_t) 0, NULL, 0);
+	if (rc)
+		return 0;
+	return 1;
+}
+
+static void show_expr(struct menu *menu, FILE *fp)
+{
+	bool hit = false;
+	fprintf(fp, "Depends:\n ");
+	if (menu->prompt->visible.expr) {
+		if (!hit)
+			hit = true;
+		expr_fprint(menu->prompt->visible.expr, fp);
+	}
+	if (!hit)
+		fprintf(fp, "None");
+	if (menu->sym) {
+		struct property *prop;
+		hit = false;
+		fprintf(fp, "\nSelects:\n ");
+		for_all_properties(menu->sym, prop, P_SELECT) {
+			if (!hit)
+				hit = true;
+			expr_fprint(prop->expr, fp);
+		}
+		if (!hit)
+			fprintf(fp, "None");
+		hit = false;
+		fprintf(fp, "\nSelected by:\n ");
+		if (menu->sym->rev_dep.expr) {
+			hit = true;
+			expr_fprint(menu->sym->rev_dep.expr, fp);
+		}
+		if (!hit)
+			fprintf(fp, "None");
+	}
+}
+
+static void search_conf(char *pattern)
+{
+	struct symbol *sym = NULL;
+	struct menu *menu[32] = { 0 };
+	struct property *prop = NULL;
+	FILE *fp = NULL;
+	bool hit = false;
+	int i, j, k, l;
+	regex_t re;
+
+	if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB))
+		return;
+
+	fp = fopen(".search.tmp", "w");
+	if (fp == NULL) {
+		perror("fopen");
+		return;
+	}
+	for_all_symbols(i, sym) {
+		if (!sym->name)
+			continue;
+		if (!regex_match(sym->name, &re))
+			continue;
+		for_all_prompts(sym, prop) {
+			struct menu *submenu = prop->menu;
+			if (!submenu)
+				continue;
+			j = 0;
+			hit = false;
+			while (submenu) {
+				menu[j++] = submenu;
+				submenu = submenu->parent;
+			}
+			if (j > 0) {
+				if (!hit)
+					hit = true;
+				fprintf(fp, "%s (%s)\n", prop->text, sym->name);
+				fprintf(fp, "Location:\n");
+			}
+			for (k = j-2, l=1; k > 0; k--, l++) {
+				const char *prompt = menu_get_prompt(menu[k]);
+				if (menu[k]->sym)
+					fprintf(fp, "%*c-> %s (%s)\n",
+								l, ' ',
+								prompt,
+								menu[k]->sym->name);
+				else
+					fprintf(fp, "%*c-> %s\n",
+								l, ' ',
+								prompt);
+			}
+			if (hit) {
+				show_expr(menu[0], fp);
+				fprintf(fp, "\n\n\n");
+			}
+		}
+	}
+	if (!hit)
+		fprintf(fp, "No matches found.");
+	regfree(&re);
+	fclose(fp);
+	show_file(".search.tmp", "Search Results", rows, cols);
+	unlink(".search.tmp");
+}
+
 static void build_conf(struct menu *menu)
 {
 	struct symbol *sym;
@@ -463,6 +576,23 @@ static void conf(struct menu *menu)
 			cprint("    Save Configuration to an Alternate File");
 		}
 		stat = exec_conf();
+		if (stat == 26) {
+			char *pattern;
+
+			if (!strlen(input_buf))
+				continue;
+			pattern = malloc(sizeof(char)*sizeof(input_buf));
+			if (pattern == NULL) {
+				perror("malloc");
+				continue;
+			}
+			for (i = 0; input_buf[i]; i++)
+				pattern[i] = toupper(input_buf[i]);
+			pattern[i] = '\0';
+			search_conf(pattern);
+			free(pattern);
+			continue;
+		}
 		if (stat < 0)
 			continue;
 
@@ -550,17 +680,7 @@ static void show_textbox(const char *title, const char *text, int r, int c)
 	fd = creat(".help.tmp", 0777);
 	write(fd, text, strlen(text));
 	close(fd);
-	do {
-		cprint_init();
-		if (title) {
-			cprint("--title");
-			cprint("%s", title);
-		}
-		cprint("--textbox");
-		cprint(".help.tmp");
-		cprint("%d", r);
-		cprint("%d", c);
-	} while (exec_conf() < 0);
+	show_file(".help.tmp", title, r, c);
 	unlink(".help.tmp");
 }
 
@@ -588,14 +708,23 @@ static void show_help(struct menu *menu)
 }
 
 static void show_readme(void)
+{
+	show_file("scripts/README.Menuconfig", NULL, rows, cols);
+}
+
+static void show_file(const char *filename, const char *title, int r, int c)
 {
 	do {
 		cprint_init();
+		if (title) {
+			cprint("--title");
+			cprint("%s", title);
+		}
 		cprint("--textbox");
-		cprint("scripts/README.Menuconfig");
-		cprint("%d", rows);
-		cprint("%d", cols);
-	} while (exec_conf() == -1);
+		cprint("%s", filename);
+		cprint("%d", r);
+		cprint("%d", c);
+	} while (exec_conf() < 0);
 }
 
 static void conf_choice(struct menu *menu)
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 38046c606..7b26f982b 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -10,7 +10,6 @@
 #include "lkc.h"
 
 struct menu rootmenu;
-struct menu *current_menu, *current_entry;
 static struct menu **last_entry_ptr;
 
 struct file *file_list;
diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped
index c9bfdb451..a48105a40 100644
--- a/scripts/kconfig/zconf.tab.c_shipped
+++ b/scripts/kconfig/zconf.tab.c_shipped
@@ -175,6 +175,8 @@ static bool zconf_endtoken(int token, int starttoken, int endtoken);
 
 struct symbol *symbol_hash[257];
 
+static struct menu *current_menu, *current_entry;
+
 #define YYERROR_VERBOSE
 
 
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
index 459b69011..aad1f5114 100644
--- a/scripts/kconfig/zconf.y
+++ b/scripts/kconfig/zconf.y
@@ -25,6 +25,8 @@ static bool zconf_endtoken(int token, int starttoken, int endtoken);
 
 struct symbol *symbol_hash[257];
 
+static struct menu *current_menu, *current_entry;
+
 #define YYERROR_VERBOSE
 %}
 %expect 40
diff --git a/scripts/lxdialog/Makefile b/scripts/lxdialog/Makefile
index 2f22b2f69..cdc4024a8 100644
--- a/scripts/lxdialog/Makefile
+++ b/scripts/lxdialog/Makefile
@@ -15,8 +15,8 @@ endif
 endif
 endif
 
-host-progs	:= lxdialog
-always		:= ncurses $(host-progs)
+hostprogs-y	:= lxdialog
+always		:= ncurses $(hostprogs-y)
 
 lxdialog-objs := checklist.o menubox.o textbox.o yesno.o inputbox.o \
 		 util.o lxdialog.o msgbox.o
diff --git a/scripts/lxdialog/menubox.c b/scripts/lxdialog/menubox.c
index 9544b3c1f..124459c04 100644
--- a/scripts/lxdialog/menubox.c
+++ b/scripts/lxdialog/menubox.c
@@ -276,6 +276,15 @@ dialog_menu (const char *title, const char *prompt, int height, int width,
 
     while (key != ESC) {
 	key = wgetch(menu);
+	if ( key == '/' ) {
+		int ret = dialog_inputbox("Search Configuration Parameter",
+					"Enter Keyword", height, width,
+					(char *) NULL);
+		if (ret == 0) {
+			fprintf(stderr, "%s", dialog_input_result);
+			return 26;
+		}
+	}
 
 	if (key < 256 && isalpha(key)) key = tolower(key);
 
diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile
index f66bf5262..11d69c35e 100644
--- a/scripts/mod/Makefile
+++ b/scripts/mod/Makefile
@@ -1,5 +1,5 @@
-host-progs	:= modpost mk_elfconfig
-always		:= $(host-progs) empty.o
+hostprogs-y	:= modpost mk_elfconfig
+always		:= $(hostprogs-y) empty.o
 
 modpost-objs	:= modpost.o file2alias.o sumversion.o
 
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 662e75b2f..2a174e504 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -343,7 +343,6 @@ handle_modversions(struct module *mod, struct elf_info *info,
 			crc = (unsigned int) sym->st_value;
 			add_exported_symbol(symname + strlen(CRC_PFX),
 					    mod, &crc);
-			modversions = 1;
 		}
 		break;
 	case SHN_UNDEF:
@@ -377,6 +376,10 @@ handle_modversions(struct module *mod, struct elf_info *info,
 			add_exported_symbol(symname + strlen(KSYMTAB_PFX),
 					    mod, NULL);
 		}
+		if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0)
+			mod->has_init = 1;
+		if (strcmp(symname, MODULE_SYMBOL_PREFIX "cleanup_module") == 0)
+			mod->has_cleanup = 1;
 		break;
 	}
 }
@@ -411,9 +414,6 @@ read_symbols(char *modname)
 	if (is_vmlinux(modname)) {
 		unsigned int fake_crc = 0;
 		have_vmlinux = 1;
-		/* May not have this if !CONFIG_MODULE_UNLOAD: fake it.
-		   If it appears, we'll get the real CRC. */
-		add_exported_symbol("cleanup_module", mod, &fake_crc);
 		add_exported_symbol("struct_module", mod, &fake_crc);
 		mod->skip = 1;
 	}
@@ -432,14 +432,8 @@ read_symbols(char *modname)
 	 * never passed as an argument to an exported function, so
 	 * the automatic versioning doesn't pick it up, but it's really
 	 * important anyhow */
-	if (modversions) {
+	if (modversions)
 		mod->unres = alloc_symbol("struct_module", mod->unres);
-
-		/* Always version init_module and cleanup_module, in
-		 * case module doesn't have its own. */
-		mod->unres = alloc_symbol("init_module", mod->unres);
-		mod->unres = alloc_symbol("cleanup_module", mod->unres);
-	}
 }
 
 #define SZ 500
@@ -480,7 +474,7 @@ buf_write(struct buffer *buf, const char *s, int len)
 /* Header for the generated file */
 
 void
-add_header(struct buffer *b)
+add_header(struct buffer *b, struct module *mod)
 {
 	buf_printf(b, "#include <linux/module.h>\n");
 	buf_printf(b, "#include <linux/vermagic.h>\n");
@@ -492,10 +486,12 @@ add_header(struct buffer *b)
 	buf_printf(b, "struct module __this_module\n");
 	buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n");
 	buf_printf(b, " .name = __stringify(KBUILD_MODNAME),\n");
-	buf_printf(b, " .init = init_module,\n");
-	buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD\n");
-	buf_printf(b, " .exit = cleanup_module,\n");
-	buf_printf(b, "#endif\n");
+	if (mod->has_init)
+		buf_printf(b, " .init = init_module,\n");
+	if (mod->has_cleanup)
+		buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD\n"
+			      " .exit = cleanup_module,\n"
+			      "#endif\n");
 	buf_printf(b, "};\n");
 }
 
@@ -649,7 +645,6 @@ read_dump(const char *fname)
 
 		if (!(mod = find_module(modname))) {
 			if (is_vmlinux(modname)) {
-				modversions = 1;
 				have_vmlinux = 1;
 			}
 			mod = new_module(NOFAIL(strdup(modname)));
@@ -696,11 +691,14 @@ main(int argc, char **argv)
 	char *dump_read = NULL, *dump_write = NULL;
 	int opt;
 
-	while ((opt = getopt(argc, argv, "i:o:")) != -1) {
+	while ((opt = getopt(argc, argv, "i:mo:")) != -1) {
 		switch(opt) {
 			case 'i':
 				dump_read = optarg;
 				break;
+			case 'm':
+				modversions = 1;
+				break;
 			case 'o':
 				dump_write = optarg;
 				break;
@@ -722,7 +720,7 @@ main(int argc, char **argv)
 
 		buf.pos = 0;
 
-		add_header(&buf);
+		add_header(&buf, mod);
 		add_versions(&buf, mod);
 		add_depends(&buf, mod, modules);
 		add_moddevtable(&buf, mod);
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index ddb013d9f..4871343e1 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -74,6 +74,8 @@ struct module {
 	struct symbol *unres;
 	int seen;
 	int skip;
+	int has_init;
+	int has_cleanup;
 	struct buffer dev_table_buf;
 };
 
diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c
index b41b718ed..86ea6a34d 100644
--- a/scripts/mod/sumversion.c
+++ b/scripts/mod/sumversion.c
@@ -1,5 +1,9 @@
 #include <netinet/in.h>
+#ifdef __sun__
+#include <inttypes.h>
+#else
 #include <stdint.h>
+#endif
 #include <ctype.h>
 #include <errno.h>
 #include <string.h>
diff --git a/scripts/package/Makefile b/scripts/package/Makefile
index 48f89e17a..3b1f2eff2 100644
--- a/scripts/package/Makefile
+++ b/scripts/package/Makefile
@@ -51,7 +51,7 @@ rpm-pkg rpm: $(objtree)/kernel.spec
 	$(RPM) --target $(UTS_MACHINE) -ta ../$(KERNELPATH).tar.gz
 	rm ../$(KERNELPATH).tar.gz
 
-clean-rule +=  rm -f $(objtree)/kernel.spec
+clean-files := $(objtree)/kernel.spec
 
 # binrpm-pkg
 .PHONY: binrpm-pkg
@@ -67,7 +67,7 @@ binrpm-pkg: $(objtree)/binkernel.spec
 
 	$(RPM) --define "_builddir $(srctree)" --target $(UTS_MACHINE) -bb $<
 
-clean-rule += rm -f $(objtree)/binkernel.spec
+clean-files += $(objtree)/binkernel.spec
 
 # Deb target
 # ---------------------------------------------------------------------------
@@ -77,7 +77,7 @@ deb-pkg:
 	$(MAKE)
 	$(CONFIG_SHELL) $(srctree)/scripts/package/builddeb
 
-clean-rule += && rm -rf $(objtree)/debian/
+clean-dirs += $(objtree)/debian/
 
 
 # Help text displayed when executing 'make help'
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index 968a0a77d..c279b6310 100644
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -12,7 +12,7 @@
 set -e
 
 # Some variables and settings used throughout the script
-version="$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+version=$KERNELRELEASE
 tmpdir="$objtree/debian/tmp"
 
 # Setup the directory structure
diff --git a/scripts/package/mkspec b/scripts/package/mkspec
index 5d94e452a..6e7a58f14 100644
--- a/scripts/package/mkspec
+++ b/scripts/package/mkspec
@@ -21,11 +21,12 @@ if [ "`grep CONFIG_DRM=y .config | cut -f2 -d\=`" = "y" ]; then
 	PROVIDES=kernel-drm
 fi
 
-PROVIDES="$PROVIDES kernel-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+PROVIDES="$PROVIDES kernel-$KERNELRELEASE"
+__KERNELRELEASE=`echo $KERNELRELEASE | sed -e "s/-//g"`
 
 echo "Name: kernel"
 echo "Summary: The Linux Kernel"
-echo "Version: "$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION | sed -e "s/-//g"
+echo "Version: $__KERNELRELEASE"
 # we need to determine the NEXT version number so that uname and
 # rpm -q will agree
 echo "Release: `. $srctree/scripts/mkversion`"
@@ -35,8 +36,7 @@ echo "Vendor: The Linux Community"
 echo "URL: http://www.kernel.org"
 
 if ! $PREBUILT; then
-echo -n "Source: kernel-$VERSION.$PATCHLEVEL.$SUBLEVEL"
-echo "$EXTRAVERSION.tar.gz" | sed -e "s/-//g"
+echo "Source: kernel-$__KERNELRELEASE.tar.gz"
 fi
 
 echo "BuildRoot: /var/tmp/%{name}-%{PACKAGE_VERSION}-root"
@@ -57,19 +57,19 @@ fi
 echo "%build"
 
 if ! $PREBUILT; then
-echo "make clean && make"
+echo "make clean && make %{_smp_mflags}"
 echo ""
 fi
 
 echo "%install"
 echo 'mkdir -p $RPM_BUILD_ROOT/boot $RPM_BUILD_ROOT/lib $RPM_BUILD_ROOT/lib/modules'
 
-echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make modules_install'
-echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make %{_smp_mflags} modules_install'
+echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$KERNELRELEASE"
 
-echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$KERNELRELEASE"
 
-echo 'cp .config $RPM_BUILD_ROOT'"/boot/config-$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+echo 'cp .config $RPM_BUILD_ROOT'"/boot/config-$KERNELRELEASE"
 echo ""
 echo "%clean"
 echo '#echo -rf $RPM_BUILD_ROOT'
@@ -77,6 +77,6 @@ echo ""
 echo "%files"
 echo '%defattr (-, root, root)'
 echo "%dir /lib/modules"
-echo "/lib/modules/$VERSION.$PATCHLEVEL.$SUBLEVEL$EXTRAVERSION"
+echo "/lib/modules/$KERNELRELEASE"
 echo "/boot/*"
 echo ""
diff --git a/scripts/patch-kernel b/scripts/patch-kernel
index 3f316b6c4..43af01075 100755
--- a/scripts/patch-kernel
+++ b/scripts/patch-kernel
@@ -40,17 +40,24 @@
 #
 # Added -ac option, use -ac or -ac9 (say) to stop at a particular version
 #       Dave Gilbert <linux@treblig.org>, 29th September 2001.
+#
+# Add support for (use of) EXTRAVERSION (to support 2.6.8.x, e.g.);
+# update usage message;
+# fix some whitespace damage;
+# be smarter about stopping when current version is larger than requested;
+#	Randy Dunlap <rddunlap@osdl.org>, 2004-AUG-18.
 
 # Set directories from arguments, or use defaults.
 sourcedir=${1-/usr/src/linux}
 patchdir=${2-.}
-stopvers=${3-imnotaversion}
+stopvers=${3-default}
 
-if [ "$1" = -h -o "$1" = --help -o ! -r "$sourcedir/Makefile" ]; then
+if [ "$1" == -h -o "$1" == --help -o ! -r "$sourcedir/Makefile" ]; then
 cat << USAGE
 usage: patch-kernel [-h] [ sourcedir [ patchdir [ stopversion ] [ -acxx ] ] ]
-  The source directory defaults to /usr/src/linux, and
-  the patch directory defaults to the current directory.
+  source directory defaults to /usr/src/linux,
+  patch directory defaults to the current directory,
+  stopversion defaults to <all in patchdir>.
 USAGE
 exit 1
 fi
@@ -77,7 +84,7 @@ findFile () {
 		uncomp="gunzip -dc"
   elif [ -r ${filebase}.bz  ]; then
 		ext=".bz"
-    name="bzip"
+		name="bzip"
 		uncomp="bunzip -dc"
   elif [ -r ${filebase}.bz2 ]; then
 		ext=".bz2"
@@ -96,8 +103,8 @@ findFile () {
 		name="plaintext"
 		uncomp="cat"
   else
-	  return 1;
-	fi
+	return 1;
+  fi
 
   return 0;
 }
@@ -126,48 +133,100 @@ applyPatch () {
   return 0;
 }
 
-# set current VERSION, PATCHLEVEL, SUBLEVEL, EXTERVERSION
-eval `sed -n -e 's/^\([A-Z]*\) = \([0-9]*\)$/\1=\2/p' -e 's/^\([A-Z]*\) = \(-[-a-z0-9]*\)$/\1=\2/p' $sourcedir/Makefile`
+# set current VERSION, PATCHLEVEL, SUBLEVEL, EXTRAVERSION
+TMPFILE=`mktemp .tmpver.XXXXXX` || { echo "cannot make temp file" ; exit 1; }
+grep -E "^(VERSION|PATCHLEVEL|SUBLEVEL|EXTRAVERSION)" $sourcedir/Makefile > $TMPFILE
+tr -d [:blank:] < $TMPFILE > $TMPFILE.1
+source $TMPFILE.1
+rm -f $TMPFILE*
 if [ -z "$VERSION" -o -z "$PATCHLEVEL" -o -z "$SUBLEVEL" ]
 then
     echo "unable to determine current kernel version" >&2
     exit 1
 fi
 
-echo "Current kernel version is $VERSION.$PATCHLEVEL.$SUBLEVEL${EXTRAVERSION}"
+NAME=`grep ^NAME $sourcedir/Makefile`
+NAME=${NAME##*=}
 
+echo "Current kernel version is $VERSION.$PATCHLEVEL.$SUBLEVEL${EXTRAVERSION} ($NAME)"
+
+# strip EXTRAVERSION to just a number (drop leading '.' and trailing additions)
+EXTRAVER=
 if [ x$EXTRAVERSION != "x" ]
 then
-  echo "I'm sorry but patch-kernel can't work with a kernel source tree that is not a base version"
-	exit 1;
+	if [ ${EXTRAVERSION:0:1} == "." ]; then
+		EXTRAVER=${EXTRAVERSION:1}
+	else
+		EXTRAVER=$EXTRAVERSION
+	fi
+	EXTRAVER=${EXTRAVER%%[[:punct:]]*}
+	#echo "patch-kernel: changing EXTRAVERSION from $EXTRAVERSION to $EXTRAVER"
+fi
+
+#echo "stopvers=$stopvers"
+if [ $stopvers != "default" ]; then
+	STOPSUBLEVEL=`echo $stopvers | cut -d. -f3`
+	STOPEXTRA=`echo $stopvers | cut -d. -f4`
+	#echo "STOPSUBLEVEL=$STOPSUBLEVEL, STOPEXTRA=$STOPEXTRA"
+else
+	STOPSUBLEVEL=9999
+	STOPEXTRA=9999
 fi
 
-while :
+while :				# incrementing SUBLEVEL (s in v.p.s)
 do
-    CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL"
-    if [ $stopvers = $CURRENTFULLVERSION ]
-    then
-        echo "Stoping at $CURRENTFULLVERSION base as requested."
+    if [ x$EXTRAVER != "x" ]; then
+	CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL.$EXTRAVER"
+    else
+	CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL"
+    fi
+
+    if [ $stopvers == $CURRENTFULLVERSION ]; then
+        echo "Stopping at $CURRENTFULLVERSION base as requested."
         break
     fi
 
-    SUBLEVEL=`expr $SUBLEVEL + 1`
+    while :			# incrementing EXTRAVER (x in v.p.s.x)
+    do
+	EXTRAVER=$((EXTRAVER + 1))
+	FULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL.$EXTRAVER"
+	#echo "... trying $FULLVERSION ..."
+
+	patch=patch-$FULLVERSION
+
+	# See if the file exists and find extension
+	findFile $patchdir/${patch} || break
+
+	# Apply the patch and check all is OK
+	applyPatch $patch || break
+
+	continue 2
+    done
+
+    EXTRAVER=
+    SUBLEVEL=$((SUBLEVEL + 1))
     FULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL"
+    #echo "___ trying $FULLVERSION ___"
+
+    if [ $((SUBLEVEL)) -gt $((STOPSUBLEVEL)) ]; then
+	echo "Stopping since sublevel ($SUBLEVEL) is beyond stop-sublevel ($STOPSUBLEVEL)"
+	exit 1
+    fi
 
     patch=patch-$FULLVERSION
 
-		# See if the file exists and find extension
-		findFile $patchdir/${patch} || break
+    # See if the file exists and find extension
+    findFile $patchdir/${patch} || break
 
     # Apply the patch and check all is OK
     applyPatch $patch || break
 done
+#echo "base all done"
 
 if [ x$gotac != x ]; then
   # Out great user wants the -ac patches
 	# They could have done -ac (get latest) or -acxx where xx=version they want
-	if [ $gotac == "-ac" ]
-	then
+	if [ $gotac == "-ac" ]; then
 	  # They want the latest version
 		HIGHESTPATCH=0
 		for PATCHNAMES in $patchdir/patch-${CURRENTFULLVERSION}-ac*\.*
@@ -176,18 +235,16 @@ if [ x$gotac != x ]; then
 			# Check it is actually a recognised patch type
 			findFile $patchdir/patch-${CURRENTFULLVERSION}-ac${ACVALUE} || break
 
-		  if [ $ACVALUE -gt $HIGHESTPATCH ]
-			then
+		  if [ $ACVALUE -gt $HIGHESTPATCH ]; then
 			  HIGHESTPATCH=$ACVALUE
 		  fi
 		done
 
-		if [ $HIGHESTPATCH -ne 0 ]
-		then
+		if [ $HIGHESTPATCH -ne 0 ]; then
 			findFile $patchdir/patch-${CURRENTFULLVERSION}-ac${HIGHESTPATCH} || break
 			applyPatch patch-${CURRENTFULLVERSION}-ac${HIGHESTPATCH}
 		else
-		  echo "No ac patches found"
+		  echo "No -ac patches found"
 		fi
 	else
 	  # They want an exact version
@@ -198,5 +255,3 @@ if [ x$gotac != x ]; then
 		applyPatch patch-${CURRENTFULLVERSION}${gotac}
 	fi
 fi
-
-
diff --git a/scripts/ver_linux b/scripts/ver_linux
index 47f14cbac..8b5c009ca 100755
--- a/scripts/ver_linux
+++ b/scripts/ver_linux
@@ -37,8 +37,11 @@ tune2fs 2>&1 | grep "^tune2fs" | sed 's/,//' |  awk \
 fsck.jfs -V 2>&1 | grep version | sed 's/,//' |  awk \
 'NR==1 {print "jfsutils              ", $3}'
 
-reiserfsck -V 2>&1 | grep reiserfsprogs | awk \
-'NR==1{print "reiserfsprogs         ", $NF}'
+reiserfsck -V 2>&1 | grep reiserfsck | awk \
+'NR==1{print "reiserfsprogs         ", $2}'
+
+fsck.reiser4 -V 2>&1 | grep fsck.reiser4 | awk \
+'NR==1{print "reiser4progs          ", $2}'
 
 xfs_db -V 2>&1 | grep version | awk \
 'NR==1{print "xfsprogs              ", $3}'
diff --git a/security/Kconfig b/security/Kconfig
index d6bc08317..ddde53ba6 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -26,14 +26,14 @@ config SECURITY_NETWORK
 
 config SECURITY_CAPABILITIES
 	tristate "Default Linux Capabilities"
-	depends on SECURITY!=n
+	depends on SECURITY
 	help
 	  This enables the "default" Linux capabilities functionality.
 	  If you are unsure how to answer this question, answer Y.
 
 config SECURITY_ROOTPLUG
 	tristate "Root Plug Support"
-	depends on USB && SECURITY!=n
+	depends on USB && SECURITY
 	help
 	  This is a sample LSM module that should only be used as such.
 	  It prevents any programs running with egid == 0 if a specific
diff --git a/security/commoncap.c b/security/commoncap.c
index 5f629be72..1e7895a23 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -314,10 +314,10 @@ int cap_vm_enough_memory(long pages)
 	/*
 	 * Sometimes we want to use more memory than we have
 	 */
-	if (sysctl_overcommit_memory == 1)
+	if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS)
 		return 0;
 
-	if (sysctl_overcommit_memory == 0) {
+	if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) {
 		unsigned long n;
 
 		free = get_page_cache_size();
@@ -357,6 +357,11 @@ int cap_vm_enough_memory(long pages)
 
 	allowed = (totalram_pages - hugetlb_total_pages())
 	       	* sysctl_overcommit_ratio / 100;
+	/*
+	 * Leave the last 3% for root
+	 */
+	if (!capable(CAP_SYS_ADMIN))
+		allowed -= allowed / 32;
 	allowed += total_swap_pages;
 
 	if (atomic_read(&vm_committed_space) < allowed)
diff --git a/security/dummy.c b/security/dummy.c
index 05d988588..a9e696595 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -121,10 +121,10 @@ static int dummy_vm_enough_memory(long pages)
 	/*
 	 * Sometimes we want to use more memory than we have
 	 */
-	if (sysctl_overcommit_memory == 1)
+	if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS)
 		return 0;
 
-	if (sysctl_overcommit_memory == 0) {
+	if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) {
 		free = get_page_cache_size();
 		free += nr_free_pages();
 		free += nr_swap_pages;
diff --git a/security/security.c b/security/security.c
index d74f708c5..70a9fcfde 100644
--- a/security/security.c
+++ b/security/security.c
@@ -49,7 +49,7 @@ static void __init do_security_initcalls(void)
 }
 
 /**
- * security_scaffolding_startup - initialzes the security scaffolding framework
+ * security_scaffolding_startup - initializes the security scaffolding framework
  *
  * This should be called early in the kernel initialization sequence.
  */
@@ -183,7 +183,7 @@ int mod_unreg_security (const char *name, struct security_operations *ops)
  * capable - calls the currently loaded security module's capable() function with the specified capability
  * @cap: the requested capability level.
  *
- * This function calls the currently loaded security module's cabable()
+ * This function calls the currently loaded security module's capable()
  * function with a pointer to the current task and the specified @cap value.
  *
  * This allows the security module to implement the capable function call
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
index 8819822d8..5a4a7988a 100644
--- a/security/selinux/Kconfig
+++ b/security/selinux/Kconfig
@@ -24,6 +24,21 @@ config SECURITY_SELINUX_BOOTPARAM
 
 	  If you are unsure how to answer this question, answer N.
 
+config SECURITY_SELINUX_BOOTPARAM_VALUE
+	int "NSA SELinux boot parameter default value"
+	depends on SECURITY_SELINUX_BOOTPARAM
+	range 0 1
+	default 1
+	help
+	  This option sets the default value for the kernel parameter
+	  'selinux', which allows SELinux to be disabled at boot.  If this
+	  option is set to 0 (zero), the SELinux kernel parameter will
+	  default to 0, disabling SELinux at bootup.  If this option is
+	  set to 1 (one), the SELinux kernel paramater will default to 1,
+	  enabling SELinux at bootup.
+
+	  If you are unsure how to answer this question, answer 1.
+
 config SECURITY_SELINUX_DISABLE
 	bool "NSA SELinux runtime disable"
 	depends on SECURITY_SELINUX
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 52fa3cfdf..f844e402b 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -43,6 +43,7 @@
 #include <linux/kd.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv6.h>
+#include <linux/tty.h>
 #include <net/icmp.h>
 #include <net/ip.h>		/* for sysctl_local_port_range[] */
 #include <net/tcp.h>		/* struct or_callable used in sock_rcv_skb */
@@ -62,7 +63,6 @@
 #include <linux/nfs_mount.h>
 #include <net/ipv6.h>
 #include <linux/hugetlb.h>
-#include <linux/major.h>
 #include <linux/personality.h>
 
 #include "avc.h"
@@ -87,7 +87,7 @@ __setup("enforcing=", enforcing_setup);
 #endif
 
 #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
-int selinux_enabled = 1;
+int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
 
 static int __init selinux_enabled_setup(char *str)
 {
@@ -1266,6 +1266,12 @@ static inline u32 file_to_av(struct file *file)
 int inode_security_set_sid(struct inode *inode, u32 sid)
 {
 	struct inode_security_struct *isec = inode->i_security;
+	struct superblock_security_struct *sbsec = inode->i_sb->s_security;
+
+	if (!sbsec->initialized) {
+		/* Defer initialization to selinux_complete_init. */
+		return 0;
+	}
 
 	down(&isec->sem);
 	isec->sclass = inode_mode_to_security_class(inode->i_mode);
@@ -1548,10 +1554,10 @@ static int selinux_vm_enough_memory(long pages)
         /*
 	 * Sometimes we want to use more memory than we have
 	 */
-	if (sysctl_overcommit_memory == 1)
+	if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS)
 		return 0;
 
-	if (sysctl_overcommit_memory == 0) {
+	if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) {
 		free = get_page_cache_size();
 		free += nr_free_pages();
 		free += nr_swap_pages;
@@ -1726,72 +1732,40 @@ static void selinux_bprm_free_security(struct linux_binprm *bprm)
 	kfree(bsec);
 }
 
-/* Create an open file that refers to the null device.
-   Derived from the OpenWall LSM. */
-struct file *open_devnull(void)
-{
-	struct inode *inode;
-	struct dentry *dentry;
-	struct file *file = NULL;
-	struct inode_security_struct *isec;
-	dev_t dev;
-
-	inode = new_inode(current->fs->rootmnt->mnt_sb);
-	if (!inode)
-		goto out;
-
-	dentry = dget(d_alloc_root(inode));
-	if (!dentry)
-		goto out_iput;
-
-	file = get_empty_filp();
-	if (!file)
-		goto out_dput;
-
-	dev = MKDEV(MEM_MAJOR, 3); /* null device */
-
-	inode->i_uid = current->fsuid;
-	inode->i_gid = current->fsgid;
-	inode->i_blksize = PAGE_SIZE;
-	inode->i_blocks = 0;
-	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	inode->i_state = I_DIRTY; /* so that mark_inode_dirty won't touch us */
-
-	isec = inode->i_security;
-	isec->sid = SECINITSID_DEVNULL;
-	isec->sclass = SECCLASS_CHR_FILE;
-	isec->initialized = 1;
-
-	file->f_flags = O_RDWR;
-	file->f_mode = FMODE_READ | FMODE_WRITE;
-	file->f_dentry = dentry;
-	file->f_vfsmnt = mntget(current->fs->rootmnt);
-	file->f_pos = 0;
-
-	init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, dev);
-	if (inode->i_fop->open(inode, file))
-		goto out_fput;
-
-out:
-	return file;
-out_fput:
-	mntput(file->f_vfsmnt);
-	put_filp(file);
-out_dput:
-	dput(dentry);
-out_iput:
-	iput(inode);
-	file = NULL;
-	goto out;
-}
+extern struct vfsmount *selinuxfs_mount;
+extern struct dentry *selinux_null;
 
 /* Derived from fs/exec.c:flush_old_files. */
 static inline void flush_unauthorized_files(struct files_struct * files)
 {
 	struct avc_audit_data ad;
 	struct file *file, *devnull = NULL;
+	struct tty_struct *tty = current->signal->tty;
 	long j = -1;
 
+	if (tty) {
+		file_list_lock();
+		file = list_entry(tty->tty_files.next, typeof(*file), f_list);
+		if (file) {
+			/* Revalidate access to controlling tty.
+			   Use inode_has_perm on the tty inode directly rather
+			   than using file_has_perm, as this particular open
+			   file may belong to another process and we are only
+			   interested in the inode-based check here. */
+			struct inode *inode = file->f_dentry->d_inode;
+			if (inode_has_perm(current, inode,
+					   FILE__READ | FILE__WRITE,
+					   NULL, NULL)) {
+				/* Reset controlling tty. */
+				current->signal->tty = NULL;
+				current->signal->tty_old_pgrp = 0;
+			}
+		}
+		file_list_unlock();
+	}
+
+	/* Revalidate access to inherited open files. */
+
 	AVC_AUDIT_DATA_INIT(&ad,FS);
 
 	spin_lock(&files->file_lock);
@@ -1826,7 +1800,7 @@ static inline void flush_unauthorized_files(struct files_struct * files)
 					if (devnull) {
 						atomic_inc(&devnull->f_count);
 					} else {
-						devnull = open_devnull();
+						devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR);
 						if (!devnull) {
 							put_unused_fd(fd);
 							fput(file);
@@ -2492,21 +2466,14 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
 	return error;
 }
 
-static int selinux_file_mmap(struct file *file, unsigned long prot, unsigned long flags)
+static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
 {
-	u32 av;
-	int rc;
-
-	rc = secondary_ops->file_mmap(file, prot, flags);
-	if (rc)
-		return rc;
-
 	if (file) {
 		/* read access is always possible with a mapping */
-		av = FILE__READ;
+		u32 av = FILE__READ;
 
 		/* write access only matters if the mapping is shared */
-		if ((flags & MAP_TYPE) == MAP_SHARED && (prot & PROT_WRITE))
+		if (shared && (prot & PROT_WRITE))
 			av |= FILE__WRITE;
 
 		if (prot & PROT_EXEC)
@@ -2517,6 +2484,18 @@ static int selinux_file_mmap(struct file *file, unsigned long prot, unsigned lon
 	return 0;
 }
 
+static int selinux_file_mmap(struct file *file, unsigned long prot, unsigned long flags)
+{
+	int rc;
+
+	rc = secondary_ops->file_mmap(file, prot, flags);
+	if (rc)
+		return rc;
+
+	return file_map_prot_check(file, prot,
+				   (flags & MAP_TYPE) == MAP_SHARED);
+}
+
 static int selinux_file_mprotect(struct vm_area_struct *vma,
 				 unsigned long prot)
 {
@@ -2526,7 +2505,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
 	if (rc)
 		return rc;
 
-	return selinux_file_mmap(vma->vm_file, prot, vma->vm_flags);
+	return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
 }
 
 static int selinux_file_lock(struct file *file, unsigned int cmd)
@@ -2651,6 +2630,11 @@ static int selinux_task_alloc_security(struct task_struct *tsk)
 	tsec2->exec_sid = tsec1->exec_sid;
 	tsec2->create_sid = tsec1->create_sid;
 
+	/* Retain ptracer SID across fork, if any.
+	   This will be reset by the ptrace hook upon any
+	   subsequent ptrace_attach operations. */
+	tsec2->ptrace_sid = tsec1->ptrace_sid;
+
 	return 0;
 }
 
@@ -2822,49 +2806,52 @@ static void selinux_task_to_inode(struct task_struct *p,
 /* Returns error only if unable to parse addresses */
 static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad)
 {
-	int offset, ihlen, ret;
-	struct iphdr iph;
+	int offset, ihlen, ret = -EINVAL;
+	struct iphdr _iph, *ih;
 
 	offset = skb->nh.raw - skb->data;
-	ret = skb_copy_bits(skb, offset, &iph, sizeof(iph));
-	if (ret)
+	ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
+	if (ih == NULL)
 		goto out;
 
-	ihlen = iph.ihl * 4;
-	if (ihlen < sizeof(iph))
+	ihlen = ih->ihl * 4;
+	if (ihlen < sizeof(_iph))
 		goto out;
 
-	ad->u.net.v4info.saddr = iph.saddr;
-	ad->u.net.v4info.daddr = iph.daddr;
+	ad->u.net.v4info.saddr = ih->saddr;
+	ad->u.net.v4info.daddr = ih->daddr;
+	ret = 0;
 
-	switch (iph.protocol) {
+	switch (ih->protocol) {
         case IPPROTO_TCP: {
-        	struct tcphdr tcph;
+        	struct tcphdr _tcph, *th;
 
-        	if (ntohs(iph.frag_off) & IP_OFFSET)
+        	if (ntohs(ih->frag_off) & IP_OFFSET)
         		break;
 
 		offset += ihlen;
-		if (skb_copy_bits(skb, offset, &tcph, sizeof(tcph)) < 0)
+		th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
+		if (th == NULL)
 			break;
 
-		ad->u.net.sport = tcph.source;
-		ad->u.net.dport = tcph.dest;
+		ad->u.net.sport = th->source;
+		ad->u.net.dport = th->dest;
 		break;
         }
         
         case IPPROTO_UDP: {
-        	struct udphdr udph;
+        	struct udphdr _udph, *uh;
         	
-        	if (ntohs(iph.frag_off) & IP_OFFSET)
+        	if (ntohs(ih->frag_off) & IP_OFFSET)
         		break;
         		
 		offset += ihlen;
-        	if (skb_copy_bits(skb, offset, &udph, sizeof(udph)) < 0)
-        		break;	
+        	uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
+		if (uh == NULL)
+			break;	
 
-        	ad->u.net.sport = udph.source;
-        	ad->u.net.dport = udph.dest;
+        	ad->u.net.sport = uh->source;
+        	ad->u.net.dport = uh->dest;
         	break;
         }
 
@@ -2881,19 +2868,20 @@ out:
 static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad)
 {
 	u8 nexthdr;
-	int ret, offset;
-	struct ipv6hdr ipv6h;
+	int ret = -EINVAL, offset;
+	struct ipv6hdr _ipv6h, *ip6;
 
 	offset = skb->nh.raw - skb->data;
-	ret = skb_copy_bits(skb, offset, &ipv6h, sizeof(ipv6h));
-	if (ret)
+	ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
+	if (ip6 == NULL)
 		goto out;
 
-	ipv6_addr_copy(&ad->u.net.v6info.saddr, &ipv6h.saddr);
-	ipv6_addr_copy(&ad->u.net.v6info.daddr, &ipv6h.daddr);
+	ipv6_addr_copy(&ad->u.net.v6info.saddr, &ip6->saddr);
+	ipv6_addr_copy(&ad->u.net.v6info.daddr, &ip6->daddr);
+	ret = 0;
 
-	nexthdr = ipv6h.nexthdr;
-	offset += sizeof(ipv6h);
+	nexthdr = ip6->nexthdr;
+	offset += sizeof(_ipv6h);
 	offset = ipv6_skip_exthdr(skb, offset, &nexthdr,
 				  skb->tail - skb->head - offset);
 	if (offset < 0)
@@ -2901,24 +2889,26 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad
 
 	switch (nexthdr) {
 	case IPPROTO_TCP: {
-        	struct tcphdr tcph;
+        	struct tcphdr _tcph, *th;
 
-		if (skb_copy_bits(skb, offset, &tcph, sizeof(tcph)) < 0)
+		th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
+		if (th == NULL)
 			break;
 
-		ad->u.net.sport = tcph.source;
-		ad->u.net.dport = tcph.dest;
+		ad->u.net.sport = th->source;
+		ad->u.net.dport = th->dest;
 		break;
 	}
 
 	case IPPROTO_UDP: {
-		struct udphdr udph;
+		struct udphdr _udph, *uh;
 
-		if (skb_copy_bits(skb, offset, &udph, sizeof(udph)) < 0)
+		uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
+		if (uh == NULL)
 			break;
 
-		ad->u.net.sport = udph.source;
-		ad->u.net.dport = udph.dest;
+		ad->u.net.sport = uh->source;
+		ad->u.net.dport = uh->dest;
 		break;
 	}
 
@@ -3078,6 +3068,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
 				goto out;
 			AVC_AUDIT_DATA_INIT(&ad,NET);
 			ad.u.net.sport = htons(snum);
+			ad.u.net.family = family;
 			err = avc_has_perm(isec->sid, sid,
 					   isec->sclass,
 					   SOCKET__NAME_BIND, NULL, &ad);
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
index 42759196b..6c1b219ba 100644
--- a/security/selinux/include/avc.h
+++ b/security/selinux/include/avc.h
@@ -111,7 +111,6 @@ struct avc_audit_data {
 struct audit_buffer;
 void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av);
 void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tclass);
-void avc_dump_cache(struct audit_buffer *ab, char *tag);
 
 /*
  * AVC operations
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 975a17708..57c2c8eaf 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/security.h>
+#include <linux/major.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
 
@@ -68,40 +69,15 @@ enum sel_inos {
 	SEL_DISABLE	/* disable SELinux until next reboot */
 };
 
+#define TMPBUFLEN	12
 static ssize_t sel_read_enforce(struct file *filp, char __user *buf,
 				size_t count, loff_t *ppos)
 {
-	char *page;
+	char tmpbuf[TMPBUFLEN];
 	ssize_t length;
-	ssize_t end;
-
-	if (count < 0 || count > PAGE_SIZE)
-		return -EINVAL;
-	if (!(page = (char*)__get_free_page(GFP_KERNEL)))
-		return -ENOMEM;
-	memset(page, 0, PAGE_SIZE);
 
-	length = scnprintf(page, PAGE_SIZE, "%d", selinux_enforcing);
-	if (length < 0) {
-		free_page((unsigned long)page);
-		return length;
-	}
-
-	if (*ppos >= length) {
-		free_page((unsigned long)page);
-		return 0;
-	}
-	if (count + *ppos > length)
-		count = length - *ppos;
-	end = count + *ppos;
-	if (copy_to_user(buf, (char *) page + *ppos, count)) {
-		count = -EFAULT;
-		goto out;
-	}
-	*ppos = end;
-out:
-	free_page((unsigned long)page);
-	return count;
+	length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_enforcing);
+	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
 }
 
 #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
@@ -119,10 +95,9 @@ static ssize_t sel_write_enforce(struct file * file, const char __user * buf,
 		/* No partial writes. */
 		return -EINVAL;
 	}
-	page = (char*)__get_free_page(GFP_KERNEL);
+	page = (char*)get_zeroed_page(GFP_KERNEL);
 	if (!page)
 		return -ENOMEM;
-	memset(page, 0, PAGE_SIZE);
 	length = -EFAULT;
 	if (copy_from_user(page, buf, count))
 		goto out;
@@ -170,10 +145,9 @@ static ssize_t sel_write_disable(struct file * file, const char __user * buf,
 		/* No partial writes. */
 		return -EINVAL;
 	}
-	page = (char*)__get_free_page(GFP_KERNEL);
+	page = (char*)get_zeroed_page(GFP_KERNEL);
 	if (!page)
 		return -ENOMEM;
-	memset(page, 0, PAGE_SIZE);
 	length = -EFAULT;
 	if (copy_from_user(page, buf, count))
 		goto out;
@@ -204,37 +178,11 @@ static struct file_operations sel_disable_ops = {
 static ssize_t sel_read_policyvers(struct file *filp, char __user *buf,
                                    size_t count, loff_t *ppos)
 {
-	char *page;
+	char tmpbuf[TMPBUFLEN];
 	ssize_t length;
-	ssize_t end;
 
-	if (count < 0 || count > PAGE_SIZE)
-		return -EINVAL;
-	if (!(page = (char*)__get_free_page(GFP_KERNEL)))
-		return -ENOMEM;
-	memset(page, 0, PAGE_SIZE);
-
-	length = scnprintf(page, PAGE_SIZE, "%u", POLICYDB_VERSION_MAX);
-	if (length < 0) {
-		free_page((unsigned long)page);
-		return length;
-	}
-
-	if (*ppos >= length) {
-		free_page((unsigned long)page);
-		return 0;
-	}
-	if (count + *ppos > length)
-		count = length - *ppos;
-	end = count + *ppos;
-	if (copy_to_user(buf, (char *) page + *ppos, count)) {
-		count = -EFAULT;
-		goto out;
-	}
-	*ppos = end;
-out:
-	free_page((unsigned long)page);
-	return count;
+	length = scnprintf(tmpbuf, TMPBUFLEN, "%u", POLICYDB_VERSION_MAX);
+	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
 }
 
 static struct file_operations sel_policyvers_ops = {
@@ -247,37 +195,11 @@ static int sel_make_bools(void);
 static ssize_t sel_read_mls(struct file *filp, char __user *buf,
 				size_t count, loff_t *ppos)
 {
-	char *page;
+	char tmpbuf[TMPBUFLEN];
 	ssize_t length;
-	ssize_t end;
-
-	if (count < 0 || count > PAGE_SIZE)
-		return -EINVAL;
-	if (!(page = (char*)__get_free_page(GFP_KERNEL)))
-		return -ENOMEM;
-	memset(page, 0, PAGE_SIZE);
 
-	length = scnprintf(page, PAGE_SIZE, "%d", selinux_mls_enabled);
-	if (length < 0) {
-		free_page((unsigned long)page);
-		return length;
-	}
-
-	if (*ppos >= length) {
-		free_page((unsigned long)page);
-		return 0;
-	}
-	if (count + *ppos > length)
-		count = length - *ppos;
-	end = count + *ppos;
-	if (copy_to_user(buf, (char *) page + *ppos, count)) {
-		count = -EFAULT;
-		goto out;
-	}
-	*ppos = end;
-out:
-	free_page((unsigned long)page);
-	return count;
+	length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_mls_enabled);
+	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
 }
 
 static struct file_operations sel_mls_ops = {
@@ -352,10 +274,9 @@ static ssize_t sel_write_context(struct file * file, const char __user * buf,
 		/* No partial writes. */
 		return -EINVAL;
 	}
-	page = (char*)__get_free_page(GFP_KERNEL);
+	page = (char*)get_zeroed_page(GFP_KERNEL);
 	if (!page)
 		return -ENOMEM;
-	memset(page, 0, PAGE_SIZE);
 	length = -EFAULT;
 	if (copy_from_user(page, buf, count))
 		goto out;
@@ -390,103 +311,31 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
 	[SEL_USER] = sel_write_user,
 };
 
-/* an argresp is stored in an allocated page and holds the
- * size of the argument or response, along with its content
- */
-struct argresp {
-	ssize_t size;
-	char data[0];
-};
-
-#define PAYLOAD_SIZE (PAGE_SIZE - sizeof(struct argresp))
-
-/*
- * transaction based IO methods.
- * The file expects a single write which triggers the transaction, and then
- * possibly a read which collects the result - which is stored in a
- * file-local buffer.
- */
-static ssize_t TA_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
+static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
 {
 	ino_t ino =  file->f_dentry->d_inode->i_ino;
-	struct argresp *ar;
-	ssize_t rv = 0;
+	char *data;
+	ssize_t rv;
 
 	if (ino >= sizeof(write_op)/sizeof(write_op[0]) || !write_op[ino])
 		return -EINVAL;
-	if (file->private_data)
-		return -EINVAL; /* only one write allowed per open */
-	if (size > PAYLOAD_SIZE - 1) /* allow one byte for null terminator */
-		return -EFBIG;
 
-	ar = kmalloc(PAGE_SIZE, GFP_KERNEL);
-	if (!ar)
-		return -ENOMEM;
-	memset(ar, 0, PAGE_SIZE); /* clear buffer, particularly last byte */
-	ar->size = 0;
-	down(&file->f_dentry->d_inode->i_sem);
-	if (file->private_data)
-		rv = -EINVAL;
-	else
-		file->private_data = ar;
-	up(&file->f_dentry->d_inode->i_sem);
-	if (rv) {
-		kfree(ar);
-		return rv;
-	}
-	if (copy_from_user(ar->data, buf, size))
-		return -EFAULT;
+	data = simple_transaction_get(file, buf, size);
+	if (IS_ERR(data))
+		return PTR_ERR(data);
 
-	rv =  write_op[ino](file, ar->data, size);
+	rv =  write_op[ino](file, data, size);
 	if (rv>0) {
-		ar->size = rv;
+		simple_transaction_set(file, rv);
 		rv = size;
 	}
 	return rv;
 }
 
-static ssize_t TA_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
-{
-	struct argresp *ar;
-	ssize_t rv = 0;
-
-	if (file->private_data == NULL)
-		rv = TA_write(file, buf, 0, pos);
-	if (rv < 0)
-		return rv;
-
-	ar = file->private_data;
-	if (!ar)
-		return 0;
-	if (*pos >= ar->size)
-		return 0;
-	if (*pos + size > ar->size)
-		size = ar->size - *pos;
-	if (copy_to_user(buf, ar->data + *pos, size))
-		return -EFAULT;
-	*pos += size;
-	return size;
-}
-
-static int TA_open(struct inode *inode, struct file *file)
-{
-	file->private_data = NULL;
-	return 0;
-}
-
-static int TA_release(struct inode *inode, struct file *file)
-{
-	void *p = file->private_data;
-	file->private_data = NULL;
-	kfree(p);
-	return 0;
-}
-
 static struct file_operations transaction_ops = {
-	.write		= TA_write,
-	.read		= TA_read,
-	.open		= TA_open,
-	.release	= TA_release,
+	.write		= selinux_transaction_write,
+	.read		= simple_transaction_read,
+	.release	= simple_transaction_release,
 };
 
 /*
@@ -534,7 +383,8 @@ static ssize_t sel_write_access(struct file * file, char *buf, size_t size)
 	if (length < 0)
 		goto out2;
 
-	length = scnprintf(buf, PAYLOAD_SIZE, "%x %x %x %x %u",
+	length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT,
+			  "%x %x %x %x %u",
 			  avd.allowed, avd.decided,
 			  avd.auditallow, avd.auditdeny,
 			  avd.seqno);
@@ -588,7 +438,7 @@ static ssize_t sel_write_create(struct file * file, char *buf, size_t size)
 	if (length < 0)
 		goto out2;
 
-	if (len > PAYLOAD_SIZE) {
+	if (len > SIMPLE_TRANSACTION_LIMIT) {
 		printk(KERN_ERR "%s:  context size (%u) exceeds payload "
 		       "max\n", __FUNCTION__, len);
 		length = -ERANGE;
@@ -649,7 +499,7 @@ static ssize_t sel_write_relabel(struct file * file, char *buf, size_t size)
 	if (length < 0)
 		goto out2;
 
-	if (len > PAYLOAD_SIZE) {
+	if (len > SIMPLE_TRANSACTION_LIMIT) {
 		length = -ERANGE;
 		goto out3;
 	}
@@ -709,7 +559,7 @@ static ssize_t sel_write_user(struct file * file, char *buf, size_t size)
 			length = rc;
 			goto out3;
 		}
-		if ((length + len) >= PAYLOAD_SIZE) {
+		if ((length + len) >= SIMPLE_TRANSACTION_LIMIT) {
 			kfree(newcon);
 			length = -ERANGE;
 			goto out3;
@@ -766,11 +616,10 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf,
 		ret = -EINVAL;
 		goto out;
 	}
-	if (!(page = (char*)__get_free_page(GFP_KERNEL))) {
+	if (!(page = (char*)get_zeroed_page(GFP_KERNEL))) {
 		ret = -ENOMEM;
 		goto out;
 	}
-	memset(page, 0, PAGE_SIZE);
 
 	inode = filep->f_dentry->d_inode;
 	cur_enforcing = security_get_bool_value(inode->i_ino - BOOL_INO_OFFSET);
@@ -832,12 +681,11 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
 		/* No partial writes. */
 		goto out;
 	}
-	page = (char*)__get_free_page(GFP_KERNEL);
+	page = (char*)get_zeroed_page(GFP_KERNEL);
 	if (!page) {
 		length = -ENOMEM;
 		goto out;
 	}
-	memset(page, 0, PAGE_SIZE);
 
 	if (copy_from_user(page, buf, count))
 		goto out;
@@ -891,14 +739,12 @@ static ssize_t sel_commit_bools_write(struct file *filep,
 		/* No partial writes. */
 		goto out;
 	}
-	page = (char*)__get_free_page(GFP_KERNEL);
+	page = (char*)get_zeroed_page(GFP_KERNEL);
 	if (!page) {
 		length = -ENOMEM;
 		goto out;
 	}
 
-	memset(page, 0, PAGE_SIZE);
-
 	if (copy_from_user(page, buf, count))
 		goto out;
 
@@ -984,9 +830,8 @@ static int sel_make_bools(void)
 
 	sel_remove_bools(dir);
 
-	if (!(page = (char*)__get_free_page(GFP_KERNEL)))
+	if (!(page = (char*)get_zeroed_page(GFP_KERNEL)))
 		return -ENOMEM;
-	memset(page, 0, PAGE_SIZE);
 
 	ret = security_get_bools(&num, &names, &values);
 	if (ret != 0)
@@ -1042,12 +887,17 @@ err:
 	goto out;
 }
 
+#define NULL_FILE_NAME "null"
+
+struct dentry *selinux_null = NULL;
+
 static int sel_fill_super(struct super_block * sb, void * data, int silent)
 {
 	int ret;
 	struct dentry *dentry;
 	struct inode *inode;
 	struct qstr qname;
+	struct inode_security_struct *isec;
 
 	static struct tree_descr selinux_files[] = {
 		[SEL_LOAD] = {"load", &sel_load_ops, S_IRUSR|S_IWUSR},
@@ -1085,10 +935,29 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
 	if (ret)
 		goto out;
 
+	qname.name = NULL_FILE_NAME;
+	qname.len = strlen(qname.name);
+	qname.hash = full_name_hash(qname.name, qname.len);
+	dentry = d_alloc(sb->s_root, &qname);
+	if (!dentry)
+		return -ENOMEM;
+
+	inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO);
+	if (!inode)
+		goto out;
+	isec = (struct inode_security_struct*)inode->i_security;
+	isec->sid = SECINITSID_DEVNULL;
+	isec->sclass = SECCLASS_CHR_FILE;
+	isec->initialized = 1;
+
+	init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3));
+	d_add(dentry, inode);
+	selinux_null = dentry;
+
 	return 0;
 out:
 	dput(dentry);
-	printk(KERN_ERR "security:	error creating conditional out_dput\n");
+	printk(KERN_ERR "%s:  failed while creating inodes\n", __FUNCTION__);
 	return -ENOMEM;
 }
 
@@ -1104,9 +973,24 @@ static struct file_system_type sel_fs_type = {
 	.kill_sb	= kill_litter_super,
 };
 
+struct vfsmount *selinuxfs_mount;
+
 static int __init init_sel_fs(void)
 {
-	return selinux_enabled ? register_filesystem(&sel_fs_type) : 0;
+	int err;
+
+	if (!selinux_enabled)
+		return 0;
+	err = register_filesystem(&sel_fs_type);
+	if (!err) {
+		selinuxfs_mount = kern_mount(&sel_fs_type);
+		if (IS_ERR(selinuxfs_mount)) {
+			printk(KERN_ERR "selinuxfs:  could not mount!\n");
+			err = PTR_ERR(selinuxfs_mount);
+			selinuxfs_mount = NULL;
+		}
+	}
+	return err;
 }
 
 __initcall(init_sel_fs);
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index 8b4f596d0..66fbdbb58 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -28,12 +28,14 @@
  (keyp->source_type << 9)) & \
  AVTAB_HASH_MASK)
 
+static kmem_cache_t *avtab_node_cachep;
+
 static struct avtab_node*
 avtab_insert_node(struct avtab *h, int hvalue, struct avtab_node * prev, struct avtab_node * cur,
 		  struct avtab_key *key, struct avtab_datum *datum)
 {
 	struct avtab_node * newnode;
-	newnode = (struct avtab_node *) kmalloc(sizeof(struct avtab_node),GFP_KERNEL);
+	newnode = kmem_cache_alloc(avtab_node_cachep, SLAB_KERNEL);
 	if (newnode == NULL)
 		return NULL;
 	memset(newnode, 0, sizeof(struct avtab_node));
@@ -226,7 +228,7 @@ void avtab_destroy(struct avtab *h)
 		while (cur != NULL) {
 			temp = cur;
 			cur = cur->next;
-			kfree(temp);
+			kmem_cache_free(avtab_node_cachep, temp);
 		}
 		h->htable[i] = NULL;
 	}
@@ -399,3 +401,9 @@ bad:
 	goto out;
 }
 
+void avtab_cache_init(void)
+{
+	avtab_node_cachep = kmem_cache_create("avtab_node",
+					      sizeof(struct avtab_node),
+					      0, SLAB_PANIC, NULL, NULL);
+}
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h
index 842636de1..f1d17575d 100644
--- a/security/selinux/ss/avtab.h
+++ b/security/selinux/ss/avtab.h
@@ -78,6 +78,8 @@ struct avtab_node *avtab_search_node(struct avtab *h, struct avtab_key *key, int
 
 struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified);
 
+void avtab_cache_init(void);
+
 #define AVTAB_HASH_BITS 15
 #define AVTAB_HASH_BUCKETS (1 << AVTAB_HASH_BITS)
 #define AVTAB_HASH_MASK (AVTAB_HASH_BUCKETS-1)
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index 8b800ad63..31321c143 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -251,7 +251,6 @@ struct policydb {
 extern int policydb_init(struct policydb *p);
 extern int policydb_index_classes(struct policydb *p);
 extern int policydb_index_others(struct policydb *p);
-extern int constraint_expr_destroy(struct constraint_expr *expr);
 extern void policydb_destroy(struct policydb *p);
 extern int policydb_load_isids(struct policydb *p, struct sidtab *s);
 extern int policydb_context_isvalid(struct policydb *p, struct context *c);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 8e4423b1c..cad425719 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1034,6 +1034,7 @@ int security_load_policy(void *data, size_t len)
 	LOAD_LOCK;
 
 	if (!ss_initialized) {
+		avtab_cache_init();
 		if (policydb_read(&policydb, fp)) {
 			LOAD_UNLOCK;
 			return -EINVAL;
diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c
index 59916802c..782fed3c9 100644
--- a/sound/arm/sa11xx-uda1341.c
+++ b/sound/arm/sa11xx-uda1341.c
@@ -21,7 +21,7 @@
  *                              merged HAL layer (patches from Brian)
  */
 
-/* $Id: sa11xx-uda1341.c,v 1.15 2004/05/03 17:36:50 tiwai Exp $ */
+/* $Id: sa11xx-uda1341.c,v 1.18 2004/07/20 15:54:09 cladisch Exp $ */
 
 /***************************************************************************************************
 *
@@ -108,16 +108,13 @@
 MODULE_AUTHOR("Tomas Kasparek <tomas.kasparek@seznam.cz>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("SA1100/SA1111 + UDA1341TS driver for ALSA");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{UDA1341,iPAQ H3600 UDA1341TS}}");
+MODULE_SUPPORTED_DEVICE("{{UDA1341,iPAQ H3600 UDA1341TS}}");
 
 static char *id = NULL;	/* ID for this card */
 
 module_param(id, charp, 0444);
 MODULE_PARM_DESC(id, "ID string for SA1100/SA1111 + UDA1341TS soundcard.");
 
-#define chip_t sa11xx_uda1341_t
-
 typedef struct audio_stream {
 	char *id;		/* identification string */
 	int stream_id;		/* numeric identification */	
@@ -152,10 +149,8 @@ static unsigned int rates[] = {
 	29400, 32000, 44100, 48000,
 };
 
-#define RATES sizeof(rates) / sizeof(rates[0])
-
 static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
-	.count	= RATES,
+	.count	= ARRAY_SIZE(rates),
 	.list	= rates,
 	.mask	= 0,
 };
@@ -869,7 +864,7 @@ static int __init snd_card_sa11xx_uda1341_pcm(sa11xx_uda1341_t *sa11xx_uda1341,
 
 static int snd_sa11xx_uda1341_suspend(snd_card_t *card, unsigned int state)
 {
-	sa11xx_uda1341_t *chip = snd_magic_cast(sa11x_uda1341_t, card->pm_private_data, return -EINVAL);
+	sa11xx_uda1341_t *chip = card->pm_private_data;
 
 	snd_pcm_suspend_all(chip->pcm);
 #ifdef HH_VERSION	
@@ -886,7 +881,7 @@ static int snd_sa11xx_uda1341_suspend(snd_card_t *card, unsigned int state)
 
 static int snd_sa11xx_uda1341_resume(snd_card_t *card, unsigned int state)
 {
-	sa11xx_uda1341_t *chip = snd_magic_cast(sa11x_uda1341_t, card->pm_private_data, return -EINVAL);
+	sa11xx_uda1341_t *chip = card->pm_private_data;
 
 	sa11xx_uda1341_audio_init(chip);
 	l3_command(chip->uda1341, CMD_RESUME, NULL);
@@ -903,7 +898,7 @@ static int snd_sa11xx_uda1341_resume(snd_card_t *card, unsigned int state)
 
 void snd_sa11xx_uda1341_free(snd_card_t *card)
 {
-	sa11xx_uda1341_t *chip = snd_magic_cast(sa11xx_uda1341_t, card->private_data, return);
+	sa11xx_uda1341_t *chip = card->private_data;
 
 	audio_dma_free(&chip->s[SNDRV_PCM_STREAM_PLAYBACK]);
 	audio_dma_free(&chip->s[SNDRV_PCM_STREAM_CAPTURE]);
@@ -925,7 +920,7 @@ static int __init sa11xx_uda1341_init(void)
 	if (card == NULL)
 		return -ENOMEM;
 
-	sa11xx_uda1341 = snd_magic_kcalloc(sa11xx_uda1341_t, 0, GFP_KERNEL);
+	sa11xx_uda1341 = kcalloc(1, sizeof(*sa11xx_uda1341), GFP_KERNEL);
 	if (sa11xx_uda1341 == NULL)
 		return -ENOMEM;	
 	spin_lock_init(&chip->s[0].dma_lock);
diff --git a/sound/core/control.c b/sound/core/control.c
index c39afa644..9b000f7ec 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -22,6 +22,7 @@
 #include <sound/driver.h>
 #include <linux/threads.h>
 #include <linux/interrupt.h>
+#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/time.h>
@@ -62,7 +63,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
 		err = -EFAULT;
 		goto __error2;
 	}
-	ctl = snd_magic_kcalloc(snd_ctl_file_t, 0, GFP_KERNEL);
+	ctl = kcalloc(1, sizeof(*ctl), GFP_KERNEL);
 	if (ctl == NULL) {
 		err = -ENOMEM;
 		goto __error;
@@ -108,7 +109,7 @@ static int snd_ctl_release(struct inode *inode, struct file *file)
 	snd_kcontrol_t *control;
 	unsigned int idx;
 
-	ctl = snd_magic_cast(snd_ctl_file_t, file->private_data, return -ENXIO);
+	ctl = file->private_data;
 	fasync_helper(-1, file, 0, &ctl->fasync);
 	file->private_data = NULL;
 	card = ctl->card;
@@ -124,7 +125,7 @@ static int snd_ctl_release(struct inode *inode, struct file *file)
 	}
 	up_write(&card->controls_rwsem);
 	snd_ctl_empty_read_queue(ctl);
-	snd_magic_kfree(ctl);
+	kfree(ctl);
 	module_put(card->module);
 	snd_card_file_remove(card, file);
 	return 0;
@@ -155,7 +156,7 @@ void snd_ctl_notify(snd_card_t *card, unsigned int mask, snd_ctl_elem_id_t *id)
 				goto _found;
 			}
 		}
-		ev = snd_kcalloc(sizeof(*ev), GFP_ATOMIC);
+		ev = kcalloc(1, sizeof(*ev), GFP_ATOMIC);
 		if (ev) {
 			ev->id = *id;
 			ev->mask = mask;
@@ -188,9 +189,7 @@ snd_kcontrol_t *snd_ctl_new(snd_kcontrol_t * control, unsigned int access)
 	
 	snd_runtime_check(control != NULL, return NULL);
 	snd_runtime_check(control->count > 0, return NULL);
-	kctl = (snd_kcontrol_t *)snd_magic_kcalloc(snd_kcontrol_t,
-						   sizeof(snd_kcontrol_volatile_t) * control->count,
-						   GFP_KERNEL);
+	kctl = kcalloc(1, sizeof(*kctl) + sizeof(snd_kcontrol_volatile_t) * control->count, GFP_KERNEL);
 	if (kctl == NULL)
 		return NULL;
 	*kctl = *control;
@@ -249,7 +248,7 @@ void snd_ctl_free_one(snd_kcontrol_t * kcontrol)
 	if (kcontrol) {
 		if (kcontrol->private_free)
 			kcontrol->private_free(kcontrol);
-		snd_magic_kfree(kcontrol);
+		kfree(kcontrol);
 	}
 }
 
@@ -927,7 +926,7 @@ static int snd_ctl_elem_add(snd_ctl_file_t *file, snd_ctl_elem_info_t __user *_i
 	if (!(info.access & SNDRV_CTL_ELEM_ACCESS_DINDIRECT))
 		for (idx = 0; idx < 4 && info.dimen.d[idx]; idx++)
 			dimen_size += sizeof(unsigned short);
-	ue = snd_kcalloc(sizeof(struct user_element) + dimen_size + private_size + extra_size, GFP_KERNEL);
+	ue = kcalloc(1, sizeof(struct user_element) + dimen_size + private_size + extra_size, GFP_KERNEL);
 	if (ue == NULL)
 		return -ENOMEM;
 	ue->type = info.type;
@@ -1022,8 +1021,8 @@ static int snd_ctl_set_power_state(snd_card_t *card, unsigned int power_state)
 }
 #endif
 
-static int snd_ctl_ioctl(struct inode *inode, struct file *file,
-			 unsigned int cmd, unsigned long arg)
+static inline int _snd_ctl_ioctl(struct inode *inode, struct file *file,
+				 unsigned int cmd, unsigned long arg)
 {
 	snd_ctl_file_t *ctl;
 	snd_card_t *card;
@@ -1033,7 +1032,7 @@ static int snd_ctl_ioctl(struct inode *inode, struct file *file,
 	int __user *ip = argp;
 	int err;
 
-	ctl = snd_magic_cast(snd_ctl_file_t, file->private_data, return -ENXIO);
+	ctl = file->private_data;
 	card = ctl->card;
 	snd_assert(card != NULL, return -ENXIO);
 	switch (cmd) {
@@ -1096,13 +1095,24 @@ static int snd_ctl_ioctl(struct inode *inode, struct file *file,
 	return -ENOTTY;
 }
 
+/* FIXME: need to unlock BKL to allow preemption */
+static int snd_ctl_ioctl(struct inode *inode, struct file *file,
+			 unsigned int cmd, unsigned long arg)
+{
+	int err;
+	unlock_kernel();
+	err = _snd_ctl_ioctl(inode, file, cmd, arg);
+	lock_kernel();
+	return err;
+}
+
 static ssize_t snd_ctl_read(struct file *file, char __user *buffer, size_t count, loff_t * offset)
 {
 	snd_ctl_file_t *ctl;
 	int err = 0;
 	ssize_t result = 0;
 
-	ctl = snd_magic_cast(snd_ctl_file_t, file->private_data, return -ENXIO);
+	ctl = file->private_data;
 	snd_assert(ctl != NULL && ctl->card != NULL, return -ENXIO);
 	if (!ctl->subscribed)
 		return -EBADFD;
@@ -1116,7 +1126,7 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer, size_t count
 			wait_queue_t wait;
 			if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
 				err = -EAGAIN;
-				goto __end;
+				goto __end_lock;
 			}
 			init_waitqueue_entry(&wait, current);
 			add_wait_queue(&ctl->change_sleep, &wait);
@@ -1137,16 +1147,16 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer, size_t count
 		kfree(kev);
 		if (copy_to_user(buffer, &ev, sizeof(snd_ctl_event_t))) {
 			err = -EFAULT;
-			goto out;
+			goto __end;
 		}
 		spin_lock_irq(&ctl->read_lock);
 		buffer += sizeof(snd_ctl_event_t);
 		count -= sizeof(snd_ctl_event_t);
 		result += sizeof(snd_ctl_event_t);
 	}
-__end:
+      __end_lock:
 	spin_unlock_irq(&ctl->read_lock);
-out:
+      __end:
       	return result > 0 ? result : err;
 }
 
@@ -1155,7 +1165,7 @@ static unsigned int snd_ctl_poll(struct file *file, poll_table * wait)
 	unsigned int mask;
 	snd_ctl_file_t *ctl;
 
-	ctl = snd_magic_cast(snd_ctl_file_t, file->private_data, return 0);
+	ctl = file->private_data;
 	if (!ctl->subscribed)
 		return 0;
 	poll_wait(file, &ctl->change_sleep, wait);
@@ -1175,8 +1185,7 @@ int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn)
 {
 	snd_kctl_ioctl_t *pn;
 
-	pn = (snd_kctl_ioctl_t *)
-		snd_kcalloc(sizeof(snd_kctl_ioctl_t), GFP_KERNEL);
+	pn = kcalloc(1, sizeof(snd_kctl_ioctl_t), GFP_KERNEL);
 	if (pn == NULL)
 		return -ENOMEM;
 	pn->fioctl = fcn;
@@ -1214,7 +1223,7 @@ static int snd_ctl_fasync(int fd, struct file * file, int on)
 {
 	snd_ctl_file_t *ctl;
 	int err;
-	ctl = snd_magic_cast(snd_ctl_file_t, file->private_data, return -ENXIO);
+	ctl = file->private_data;
 	err = fasync_helper(fd, file, on, &ctl->fasync);
 	if (err < 0)
 		return err;
diff --git a/sound/core/device.c b/sound/core/device.c
index ab57ca6b6..18c71f913 100644
--- a/sound/core/device.c
+++ b/sound/core/device.c
@@ -47,7 +47,7 @@ int snd_device_new(snd_card_t *card, snd_device_type_t type,
 	snd_device_t *dev;
 
 	snd_assert(card != NULL && device_data != NULL && ops != NULL, return -ENXIO);
-	dev = (snd_device_t *) snd_magic_kcalloc(snd_device_t, 0, GFP_KERNEL);
+	dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL)
 		return -ENOMEM;
 	dev->card = card;
@@ -94,7 +94,7 @@ int snd_device_free(snd_card_t *card, void *device_data)
 					snd_printk(KERN_ERR "device free failure\n");
 			}
 		}
-		snd_magic_kfree(dev);
+		kfree(dev);
 		return 0;
 	}
 	snd_printd("device free %p (from %p), not found\n", device_data, __builtin_return_address(0));
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index d18e4769d..b79f23156 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -22,6 +22,7 @@
 #include <sound/driver.h>
 #include <linux/major.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <sound/core.h>
@@ -49,7 +50,7 @@ static int snd_hwdep_dev_unregister(snd_device_t *device);
 
 static loff_t snd_hwdep_llseek(struct file * file, loff_t offset, int orig)
 {
-	snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return -ENXIO);
+	snd_hwdep_t *hw = file->private_data;
 	if (hw->ops.llseek)
 		return hw->ops.llseek(hw, file, offset, orig);
 	return -ENXIO;
@@ -57,7 +58,7 @@ static loff_t snd_hwdep_llseek(struct file * file, loff_t offset, int orig)
 
 static ssize_t snd_hwdep_read(struct file * file, char __user *buf, size_t count, loff_t *offset)
 {
-	snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return -ENXIO);
+	snd_hwdep_t *hw = file->private_data;
 	if (hw->ops.read)
 		return hw->ops.read(hw, buf, count, offset);
 	return -ENXIO;	
@@ -65,7 +66,7 @@ static ssize_t snd_hwdep_read(struct file * file, char __user *buf, size_t count
 
 static ssize_t snd_hwdep_write(struct file * file, const char __user *buf, size_t count, loff_t *offset)
 {
-	snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return -ENXIO);
+	snd_hwdep_t *hw = file->private_data;
 	if (hw->ops.write)
 		return hw->ops.write(hw, buf, count, offset);
 	return -ENXIO;	
@@ -157,7 +158,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
 static int snd_hwdep_release(struct inode *inode, struct file * file)
 {
 	int err = -ENXIO;
-	snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return -ENXIO);
+	snd_hwdep_t *hw = file->private_data;
 	down(&hw->open_mutex);
 	if (hw->ops.release) {
 		err = hw->ops.release(hw, file);
@@ -173,7 +174,7 @@ static int snd_hwdep_release(struct inode *inode, struct file * file)
 
 static unsigned int snd_hwdep_poll(struct file * file, poll_table * wait)
 {
-	snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return 0);
+	snd_hwdep_t *hw = file->private_data;
 	if (hw->ops.poll)
 		return hw->ops.poll(hw, file, wait);
 	return 0;
@@ -231,10 +232,10 @@ static int snd_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t __user *_in
 	return 0;
 }
 
-static int snd_hwdep_ioctl(struct inode *inode, struct file * file,
-			   unsigned int cmd, unsigned long arg)
+static inline int _snd_hwdep_ioctl(struct inode *inode, struct file * file,
+				   unsigned int cmd, unsigned long arg)
 {
-	snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return -ENXIO);
+	snd_hwdep_t *hw = file->private_data;
 	void __user *argp = (void __user *)arg;
 	switch (cmd) {
 	case SNDRV_HWDEP_IOCTL_PVERSION:
@@ -251,9 +252,20 @@ static int snd_hwdep_ioctl(struct inode *inode, struct file * file,
 	return -ENOTTY;
 }
 
+/* FIXME: need to unlock BKL to allow preemption */
+static int snd_hwdep_ioctl(struct inode *inode, struct file * file,
+			   unsigned int cmd, unsigned long arg)
+{
+	int err;
+	unlock_kernel();
+	err = _snd_hwdep_ioctl(inode, file, cmd, arg);
+	lock_kernel();
+	return err;
+}
+
 static int snd_hwdep_mmap(struct file * file, struct vm_area_struct * vma)
 {
-	snd_hwdep_t *hw = snd_magic_cast(snd_hwdep_t, file->private_data, return -ENXIO);
+	snd_hwdep_t *hw = file->private_data;
 	if (hw->ops.mmap)
 		return hw->ops.mmap(hw, file, vma);
 	return -ENXIO;
@@ -352,7 +364,7 @@ int snd_hwdep_new(snd_card_t * card, char *id, int device, snd_hwdep_t ** rhwdep
 	snd_assert(rhwdep != NULL, return -EINVAL);
 	*rhwdep = NULL;
 	snd_assert(card != NULL, return -ENXIO);
-	hwdep = snd_magic_kcalloc(snd_hwdep_t, 0, GFP_KERNEL);
+	hwdep = kcalloc(1, sizeof(*hwdep), GFP_KERNEL);
 	if (hwdep == NULL)
 		return -ENOMEM;
 	hwdep->card = card;
@@ -378,19 +390,19 @@ static int snd_hwdep_free(snd_hwdep_t *hwdep)
 	snd_assert(hwdep != NULL, return -ENXIO);
 	if (hwdep->private_free)
 		hwdep->private_free(hwdep);
-	snd_magic_kfree(hwdep);
+	kfree(hwdep);
 	return 0;
 }
 
 static int snd_hwdep_dev_free(snd_device_t *device)
 {
-	snd_hwdep_t *hwdep = snd_magic_cast(snd_hwdep_t, device->device_data, return -ENXIO);
+	snd_hwdep_t *hwdep = device->device_data;
 	return snd_hwdep_free(hwdep);
 }
 
 static int snd_hwdep_dev_register(snd_device_t *device)
 {
-	snd_hwdep_t *hwdep = snd_magic_cast(snd_hwdep_t, device->device_data, return -ENXIO);
+	snd_hwdep_t *hwdep = device->device_data;
 	int idx, err;
 	char name[32];
 
@@ -433,7 +445,7 @@ static int snd_hwdep_dev_register(snd_device_t *device)
 
 static int snd_hwdep_dev_unregister(snd_device_t *device)
 {
-	snd_hwdep_t *hwdep = snd_magic_cast(snd_hwdep_t, device->device_data, return -ENXIO);
+	snd_hwdep_t *hwdep = device->device_data;
 	int idx;
 
 	snd_assert(hwdep != NULL, return -ENXIO);
diff --git a/sound/core/info.c b/sound/core/info.c
index 1eb7d916a..db1e2575f 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -139,7 +139,7 @@ static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig)
 	struct snd_info_entry *entry;
 	loff_t ret;
 
-	data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
+	data = file->private_data;
 	entry = data->entry;
 	lock_kernel();
 	switch (entry->content) {
@@ -183,7 +183,7 @@ static ssize_t snd_info_entry_read(struct file *file, char __user *buffer,
 	size_t size = 0;
 	loff_t pos;
 
-	data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
+	data = file->private_data;
 	snd_assert(data != NULL, return -ENXIO);
 	pos = *offset;
 	if (pos < 0 || (long) pos != pos || (ssize_t) count < 0)
@@ -224,7 +224,7 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer
 	size_t size = 0;
 	loff_t pos;
 
-	data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
+	data = file->private_data;
 	snd_assert(data != NULL, return -ENXIO);
 	entry = data->entry;
 	pos = *offset;
@@ -296,7 +296,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
 		    	goto __error;
 		}
 	}
-	data = snd_magic_kcalloc(snd_info_private_data_t, 0, GFP_KERNEL);
+	data = kcalloc(1, sizeof(*data), GFP_KERNEL);
 	if (data == NULL) {
 		err = -ENOMEM;
 		goto __error;
@@ -305,10 +305,9 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
 	switch (entry->content) {
 	case SNDRV_INFO_CONTENT_TEXT:
 		if (mode == O_RDONLY || mode == O_RDWR) {
-			buffer = (snd_info_buffer_t *)
-				 	snd_kcalloc(sizeof(snd_info_buffer_t), GFP_KERNEL);
+			buffer = kcalloc(1, sizeof(*buffer), GFP_KERNEL);
 			if (buffer == NULL) {
-				snd_magic_kfree(data);
+				kfree(data);
 				err = -ENOMEM;
 				goto __error;
 			}
@@ -317,7 +316,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
 			buffer->buffer = vmalloc(buffer->len);
 			if (buffer->buffer == NULL) {
 				kfree(buffer);
-				snd_magic_kfree(data);
+				kfree(data);
 				err = -ENOMEM;
 				goto __error;
 			}
@@ -325,14 +324,13 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
 			data->rbuffer = buffer;
 		}
 		if (mode == O_WRONLY || mode == O_RDWR) {
-			buffer = (snd_info_buffer_t *)
-					snd_kcalloc(sizeof(snd_info_buffer_t), GFP_KERNEL);
+			buffer = kcalloc(1, sizeof(*buffer), GFP_KERNEL);
 			if (buffer == NULL) {
 				if (mode == O_RDWR) {
 					vfree(data->rbuffer->buffer);
 					kfree(data->rbuffer);
 				}
-				snd_magic_kfree(data);
+				kfree(data);
 				err = -ENOMEM;
 				goto __error;
 			}
@@ -345,7 +343,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
 					kfree(data->rbuffer);
 				}
 				kfree(buffer);
-				snd_magic_kfree(data);
+				kfree(data);
 				err = -ENOMEM;
 				goto __error;
 			}
@@ -357,7 +355,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
 		if (entry->c.ops->open) {
 			if ((err = entry->c.ops->open(entry, mode,
 						      &data->file_private_data)) < 0) {
-				snd_magic_kfree(data);
+				kfree(data);
 				goto __error;
 			}
 		}
@@ -389,7 +387,7 @@ static int snd_info_entry_release(struct inode *inode, struct file *file)
 	int mode;
 
 	mode = file->f_flags & O_ACCMODE;
-	data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
+	data = file->private_data;
 	entry = data->entry;
 	switch (entry->content) {
 	case SNDRV_INFO_CONTENT_TEXT:
@@ -417,7 +415,7 @@ static int snd_info_entry_release(struct inode *inode, struct file *file)
 		break;
 	}
 	module_put(entry->module);
-	snd_magic_kfree(data);
+	kfree(data);
 	return 0;
 }
 
@@ -427,7 +425,7 @@ static unsigned int snd_info_entry_poll(struct file *file, poll_table * wait)
 	struct snd_info_entry *entry;
 	unsigned int mask;
 
-	data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
+	data = file->private_data;
 	if (data == NULL)
 		return 0;
 	entry = data->entry;
@@ -447,13 +445,13 @@ static unsigned int snd_info_entry_poll(struct file *file, poll_table * wait)
 	return mask;
 }
 
-static int snd_info_entry_ioctl(struct inode *inode, struct file *file,
-				unsigned int cmd, unsigned long arg)
+static inline int _snd_info_entry_ioctl(struct inode *inode, struct file *file,
+					unsigned int cmd, unsigned long arg)
 {
 	snd_info_private_data_t *data;
 	struct snd_info_entry *entry;
 
-	data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
+	data = file->private_data;
 	if (data == NULL)
 		return 0;
 	entry = data->entry;
@@ -468,13 +466,24 @@ static int snd_info_entry_ioctl(struct inode *inode, struct file *file,
 	return -ENOTTY;
 }
 
+/* FIXME: need to unlock BKL to allow preemption */
+static int snd_info_entry_ioctl(struct inode *inode, struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	int err;
+	unlock_kernel();
+	err = _snd_info_entry_ioctl(inode, file, cmd, arg);
+	lock_kernel();
+	return err;
+}
+
 static int snd_info_entry_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	snd_info_private_data_t *data;
 	struct snd_info_entry *entry;
 
-	data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
+	data = file->private_data;
 	if (data == NULL)
 		return 0;
 	entry = data->entry;
@@ -744,12 +753,12 @@ char *snd_info_get_str(char *dest, char *src, int len)
 static snd_info_entry_t *snd_info_create_entry(const char *name)
 {
 	snd_info_entry_t *entry;
-	entry = snd_magic_kcalloc(snd_info_entry_t, 0, GFP_KERNEL);
+	entry = kcalloc(1, sizeof(*entry), GFP_KERNEL);
 	if (entry == NULL)
 		return NULL;
 	entry->name = snd_kmalloc_strdup(name, GFP_KERNEL);
 	if (entry->name == NULL) {
-		snd_magic_kfree(entry);
+		kfree(entry);
 		return NULL;
 	}
 	entry->mode = S_IFREG | S_IRUGO;
@@ -805,27 +814,27 @@ snd_info_entry_t *snd_info_create_card_entry(snd_card_t * card,
 
 static int snd_info_dev_free_entry(snd_device_t *device)
 {
-	snd_info_entry_t *entry = snd_magic_cast(snd_info_entry_t, device->device_data, return -ENXIO);
+	snd_info_entry_t *entry = device->device_data;
 	snd_info_free_entry(entry);
 	return 0;
 }
 
 static int snd_info_dev_register_entry(snd_device_t *device)
 {
-	snd_info_entry_t *entry = snd_magic_cast(snd_info_entry_t, device->device_data, return -ENXIO);
+	snd_info_entry_t *entry = device->device_data;
 	return snd_info_register(entry);
 }
 
 static int snd_info_dev_disconnect_entry(snd_device_t *device)
 {
-	snd_info_entry_t *entry = snd_magic_cast(snd_info_entry_t, device->device_data, return -ENXIO);
+	snd_info_entry_t *entry = device->device_data;
 	entry->disconnected = 1;
 	return 0;
 }
 
 static int snd_info_dev_unregister_entry(snd_device_t *device)
 {
-	snd_info_entry_t *entry = snd_magic_cast(snd_info_entry_t, device->device_data, return -ENXIO);
+	snd_info_entry_t *entry = device->device_data;
 	return snd_info_unregister(entry);
 }
 
@@ -887,7 +896,7 @@ void snd_info_free_entry(snd_info_entry_t * entry)
 		kfree((char *)entry->name);
 	if (entry->private_free)
 		entry->private_free(entry);
-	snd_magic_kfree(entry);
+	kfree(entry);
 }
 
 /**
diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c
index 23261068b..f9e4ce443 100644
--- a/sound/core/info_oss.c
+++ b/sound/core/info_oss.c
@@ -134,16 +134,4 @@ int snd_info_minor_unregister(void)
 	return 0;
 }
 
-#else
-
-int snd_info_minor_register(void)
-{
-	return 0;
-}
-
-int snd_info_minor_unregister(void)
-{
-	return 0;
-}
-
 #endif /* CONFIG_SND_OSSEMUL */
diff --git a/sound/core/init.c b/sound/core/init.c
index 9c3df614a..1ff7667d7 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -73,7 +73,7 @@ snd_card_t *snd_card_new(int idx, const char *xid,
 
 	if (extra_size < 0)
 		extra_size = 0;
-	card = (snd_card_t *) snd_kcalloc(sizeof(snd_card_t) + extra_size, GFP_KERNEL);
+	card = kcalloc(1, sizeof(*card) + extra_size, GFP_KERNEL);
 	if (card == NULL)
 		return NULL;
 	if (xid) {
@@ -800,6 +800,8 @@ int snd_card_pci_resume(struct pci_dev *dev)
 		return 0;
 	if (card->power_state == SNDRV_CTL_POWER_D0)
 		return 0;
+	/* restore the PCI config space */
+	pci_restore_state(dev, dev->saved_config_space);
 	/* FIXME: correct state value? */
 	return card->pm_resume(card, 0);
 }
diff --git a/sound/core/ioctl32/ioctl32.c b/sound/core/ioctl32/ioctl32.c
index 5c0d30c77..dad9cb1eb 100644
--- a/sound/core/ioctl32/ioctl32.c
+++ b/sound/core/ioctl32/ioctl32.c
@@ -257,7 +257,7 @@ static int get_ctl_type(struct file *file, snd_ctl_elem_id_t *id)
 	snd_ctl_elem_info_t info;
 	int err;
 
-	ctl = snd_magic_cast(snd_ctl_file_t, file->private_data, return -ENXIO);
+	ctl = file->private_data;
 
 	down_read(&ctl->card->controls_rwsem);
 	kctl = snd_ctl_find_id(ctl->card, id);
diff --git a/sound/core/ioctl32/pcm32.c b/sound/core/ioctl32/pcm32.c
index 41ea1dabe..caf5ee4c0 100644
--- a/sound/core/ioctl32/pcm32.c
+++ b/sound/core/ioctl32/pcm32.c
@@ -69,7 +69,7 @@ struct sndrv_pcm_hw_params32 {
 	unsigned char reserved[64];
 } __attribute__((packed));
 
-#define numberof(array)  (sizeof(array)/sizeof(array[0]))
+#define numberof(array) ARRAY_SIZE(array)
 
 #define CVT_sndrv_pcm_hw_params()\
 {\
@@ -235,7 +235,7 @@ static int _snd_ioctl32_xfern(unsigned int fd, unsigned int cmd, unsigned long a
 
 	/* FIXME: need to check whether fop->ioctl is sane */
 
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return -ENXIO);
+	pcm_file = file->private_data;
 	substream = pcm_file->substream;
 	snd_assert(substream != NULL && substream->runtime, return -ENXIO);
 
@@ -313,7 +313,7 @@ static void snd_pcm_hw_convert_from_old_params(snd_pcm_hw_params_t *params, stru
 
 	memset(params, 0, sizeof(*params));
 	params->flags = oparams->flags;
-	for (i = 0; i < sizeof(oparams->masks) / sizeof(unsigned int); i++)
+	for (i = 0; i < ARRAY_SIZE(oparams->masks); i++)
 		params->masks[i].bits[0] = oparams->masks[i];
 	memcpy(params->intervals, oparams->intervals, sizeof(oparams->intervals));
 	params->rmask = __OLD_TO_NEW_MASK(oparams->rmask);
@@ -331,7 +331,7 @@ static void snd_pcm_hw_convert_to_old_params(struct sndrv_pcm_hw_params_old32 *o
 
 	memset(oparams, 0, sizeof(*oparams));
 	oparams->flags = params->flags;
-	for (i = 0; i < sizeof(oparams->masks) / sizeof(unsigned int); i++)
+	for (i = 0; i < ARRAY_SIZE(oparams->masks); i++)
 		oparams->masks[i] = params->masks[i].bits[0];
 	memcpy(oparams->intervals, params->intervals, sizeof(oparams->intervals));
 	oparams->rmask = __NEW_TO_OLD_MASK(params->rmask);
@@ -350,8 +350,8 @@ static int _snd_ioctl32_pcm_hw_params_old(unsigned int fd, unsigned int cmd, uns
 	mm_segment_t oldseg;
 	int err;
 
-	data32 = snd_kcalloc(sizeof(*data32), GFP_KERNEL);
-	data = snd_kcalloc(sizeof(*data), GFP_KERNEL);
+	data32 = kcalloc(1, sizeof(*data32), GFP_KERNEL);
+	data = kcalloc(1, sizeof(*data), GFP_KERNEL);
 	if (data32 == NULL || data == NULL) {
 		err = -ENOMEM;
 		goto __end;
@@ -379,6 +379,45 @@ static int _snd_ioctl32_pcm_hw_params_old(unsigned int fd, unsigned int cmd, uns
 	return err;
 }
 
+struct sndrv_pcm_mmap_status32 {
+	s32 state;
+	s32 pad1;
+	u32 hw_ptr;
+	struct compat_timespec tstamp;
+	s32 suspended_state;
+} __attribute__((packed));
+
+struct sndrv_pcm_mmap_control32 {
+	u32 appl_ptr;
+	u32 avail_min;
+} __attribute__((packed));
+
+struct sndrv_pcm_sync_ptr32 {
+	u32 flags;
+	union {
+		struct sndrv_pcm_mmap_status32 status;
+		unsigned char reserved[64];
+	} s;
+	union {
+		struct sndrv_pcm_mmap_control32 control;
+		unsigned char reserved[64];
+	} c;
+} __attribute__((packed));
+
+#define CVT_sndrv_pcm_sync_ptr()\
+{\
+	COPY(flags);\
+	COPY(s.status.state);\
+	COPY(s.status.pad1);\
+	COPY(s.status.hw_ptr);\
+	COPY(s.status.tstamp.tv_sec);\
+	COPY(s.status.tstamp.tv_nsec);\
+	COPY(s.status.suspended_state);\
+	COPY(c.control.appl_ptr);\
+	COPY(c.control.avail_min);\
+}
+
+DEFINE_ALSA_IOCTL_BIG(pcm_sync_ptr);
 
 /*
  */
@@ -396,6 +435,7 @@ DEFINE_ALSA_IOCTL_ENTRY(pcm_readi, xferi, SNDRV_PCM_IOCTL_READI_FRAMES);
 DEFINE_ALSA_IOCTL_ENTRY(pcm_writei, xferi, SNDRV_PCM_IOCTL_WRITEI_FRAMES);
 DEFINE_ALSA_IOCTL_ENTRY(pcm_readn, xfern, SNDRV_PCM_IOCTL_READN_FRAMES);
 DEFINE_ALSA_IOCTL_ENTRY(pcm_writen, xfern, SNDRV_PCM_IOCTL_WRITEN_FRAMES);
+DEFINE_ALSA_IOCTL_ENTRY(pcm_sync_ptr, pcm_sync_ptr, SNDRV_PCM_IOCTL_SYNC_PTR);
 
 
 /*
@@ -416,6 +456,7 @@ enum {
 	SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct sndrv_xfern32),
 	SNDRV_PCM_IOCTL_HW_REFINE_OLD32 = _IOWR('A', 0x10, struct sndrv_pcm_hw_params_old32),
 	SNDRV_PCM_IOCTL_HW_PARAMS_OLD32 = _IOWR('A', 0x11, struct sndrv_pcm_hw_params_old32),
+	SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct sndrv_pcm_sync_ptr),
 
 };
 
@@ -431,6 +472,8 @@ struct ioctl32_mapper pcm_mappers[] = {
 	{ SNDRV_PCM_IOCTL_SW_PARAMS32, AP(pcm_sw_params) },
 	{ SNDRV_PCM_IOCTL_STATUS32, AP(pcm_status) },
 	{ SNDRV_PCM_IOCTL_DELAY32, AP(pcm_delay) },
+	MAP_COMPAT(SNDRV_PCM_IOCTL_HWSYNC),
+	{ SNDRV_PCM_IOCTL_SYNC_PTR32, AP(pcm_sync_ptr) },
 	{ SNDRV_PCM_IOCTL_CHANNEL_INFO32, AP(pcm_channel_info) },
 	MAP_COMPAT(SNDRV_PCM_IOCTL_PREPARE),
 	MAP_COMPAT(SNDRV_PCM_IOCTL_RESET),
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index bc1e344e3..cc0b6028c 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -45,15 +45,19 @@ MODULE_LICENSE("GPL");
 #ifndef SNDRV_CARDS
 #define SNDRV_CARDS	8
 #endif
+
+/* FIXME: so far only some PCI devices have the preallocation table */
+#ifdef CONFIG_PCI
 static int enable[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
 static int boot_devs;
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable cards to allocate buffers.");
+#endif
 
 /*
  */
 
-void *snd_malloc_sgbuf_pages(const struct snd_dma_device *dev,
+void *snd_malloc_sgbuf_pages(struct device *device,
                              size_t size, struct snd_dma_buffer *dmab,
 			     size_t *res_size);
 int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab);
@@ -66,9 +70,8 @@ static LIST_HEAD(mem_list_head);
 
 /* buffer preservation list */
 struct snd_mem_list {
-	struct snd_dma_device dev;
 	struct snd_dma_buffer buffer;
-	int used;
+	unsigned int id;
 	struct list_head list;
 };
 
@@ -148,6 +151,10 @@ static void *snd_dma_hack_alloc_coherent(struct device *dev, size_t size,
 
 #endif /* arch */
 
+#if ! defined(__arm__)
+#define NEED_RESERVE_PAGES
+#endif
+
 /*
  *
  *  Generic memory allocators
@@ -156,22 +163,28 @@ static void *snd_dma_hack_alloc_coherent(struct device *dev, size_t size,
 
 static long snd_allocated_pages; /* holding the number of allocated pages */
 
-static void mark_pages(void *res, int order)
+static inline void inc_snd_pages(int order)
+{
+	snd_allocated_pages += 1 << order;
+}
+
+static inline void dec_snd_pages(int order)
+{
+	snd_allocated_pages -= 1 << order;
+}
+
+static void mark_pages(struct page *page, int order)
 {
-	struct page *page = virt_to_page(res);
 	struct page *last_page = page + (1 << order);
 	while (page < last_page)
 		SetPageReserved(page++);
-	snd_allocated_pages += 1 << order;
 }
 
-static void unmark_pages(void *res, int order)
+static void unmark_pages(struct page *page, int order)
 {
-	struct page *page = virt_to_page(res);
 	struct page *last_page = page + (1 << order);
 	while (page < last_page)
 		ClearPageReserved(page++);
-	snd_allocated_pages -= 1 << order;
 }
 
 /**
@@ -190,42 +203,14 @@ void *snd_malloc_pages(size_t size, unsigned int gfp_flags)
 
 	snd_assert(size > 0, return NULL);
 	snd_assert(gfp_flags != 0, return NULL);
-	for (pg = 0; PAGE_SIZE * (1 << pg) < size; pg++);
+	pg = get_order(size);
 	if ((res = (void *) __get_free_pages(gfp_flags, pg)) != NULL) {
-		mark_pages(res, pg);
+		mark_pages(virt_to_page(res), pg);
+		inc_snd_pages(pg);
 	}
 	return res;
 }
 
-/**
- * snd_malloc_pages_fallback - allocate pages with the given size with fallback
- * @size: the requested size to allocate in bytes
- * @gfp_flags: the allocation conditions, GFP_XXX
- * @res_size: the pointer to store the size of buffer actually allocated
- *
- * Allocates the physically contiguous pages with the given request
- * size.  When no space is left, this function reduces the size and
- * tries to allocate again.  The size actually allocated is stored in
- * res_size argument.
- *
- * Returns the pointer of the buffer, or NULL if no enoguh memory.
- */            
-void *snd_malloc_pages_fallback(size_t size, unsigned int gfp_flags, size_t *res_size)
-{
-	void *res;
-
-	snd_assert(size > 0, return NULL);
-	snd_assert(res_size != NULL, return NULL);
-	do {
-		if ((res = snd_malloc_pages(size, gfp_flags)) != NULL) {
-			*res_size = size;
-			return res;
-		}
-		size >>= 1;
-	} while (size >= PAGE_SIZE);
-	return NULL;
-}
-
 /**
  * snd_free_pages - release the pages
  * @ptr: the buffer pointer to release
@@ -239,8 +224,9 @@ void snd_free_pages(void *ptr, size_t size)
 
 	if (ptr == NULL)
 		return;
-	for (pg = 0; PAGE_SIZE * (1 << pg) < size; pg++);
-	unmark_pages(ptr, pg);
+	pg = get_order(size);
+	dec_snd_pages(pg);
+	unmark_pages(virt_to_page(ptr), pg);
 	free_pages((unsigned long) ptr, pg);
 }
 
@@ -250,6 +236,7 @@ void snd_free_pages(void *ptr, size_t size)
  *
  */
 
+/* allocate the coherent DMA pages */
 static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *dma)
 {
 	int pg;
@@ -263,28 +250,17 @@ static void *snd_malloc_dev_pages(struct device *dev, size_t size, dma_addr_t *d
 	if (pg > 0)
 		gfp_flags |= __GFP_NOWARN;
 	res = dma_alloc_coherent(dev, PAGE_SIZE << pg, dma, gfp_flags);
-	if (res != NULL)
-		mark_pages(res, pg);
+	if (res != NULL) {
+#ifdef NEED_RESERVE_PAGES
+		mark_pages(virt_to_page(res), pg); /* should be dma_to_page() */
+#endif
+		inc_snd_pages(pg);
+	}
 
 	return res;
 }
 
-static void *snd_malloc_dev_pages_fallback(struct device *dev, size_t size,
-					   dma_addr_t *dma, size_t *res_size)
-{
-	void *res;
-
-	snd_assert(res_size != NULL, return NULL);
-	do {
-		if ((res = snd_malloc_dev_pages(dev, size, dma)) != NULL) {
-			*res_size = size;
-			return res;
-		}
-		size >>= 1;
-	} while (size >= PAGE_SIZE);
-	return NULL;
-}
-
+/* free the coherent DMA pages */
 static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr,
 			       dma_addr_t dma)
 {
@@ -293,7 +269,10 @@ static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr,
 	if (ptr == NULL)
 		return;
 	pg = get_order(size);
-	unmark_pages(ptr, pg);
+	dec_snd_pages(pg);
+#ifdef NEED_RESERVE_PAGES
+	unmark_pages(virt_to_page(ptr), pg); /* should be dma_to_page() */
+#endif
 	dma_free_coherent(dev, PAGE_SIZE << pg, ptr, dma);
 }
 
@@ -308,30 +287,13 @@ static void *snd_malloc_sbus_pages(struct device *dev, size_t size,
 
 	snd_assert(size > 0, return NULL);
 	snd_assert(dma_addr != NULL, return NULL);
-	for (pg = 0; PAGE_SIZE * (1 << pg) < size; pg++);
+	pg = get_order(size);
 	res = sbus_alloc_consistent(sdev, PAGE_SIZE * (1 << pg), dma_addr);
-	if (res != NULL) {
-		mark_pages(res, pg);
-	}
+	if (res != NULL)
+		inc_snd_pages(pg);
 	return res;
 }
 
-static void *snd_malloc_sbus_pages_fallback(struct device *dev, size_t size,
-					    dma_addr_t *dma_addr, size_t *res_size)
-{
-	void *res;
-
-	snd_assert(res_size != NULL, return NULL);
-	do {
-		if ((res = snd_malloc_sbus_pages(dev, size, dma_addr)) != NULL) {
-			*res_size = size;
-			return res;
-		}
-		size >>= 1;
-	} while (size >= PAGE_SIZE);
-	return NULL;
-}
-
 static void snd_free_sbus_pages(struct device *dev, size_t size,
 				void *ptr, dma_addr_t dma_addr)
 {
@@ -340,8 +302,8 @@ static void snd_free_sbus_pages(struct device *dev, size_t size,
 
 	if (ptr == NULL)
 		return;
-	for (pg = 0; PAGE_SIZE * (1 << pg) < size; pg++);
-	unmark_pages(ptr, pg);
+	pg = get_order(size);
+	dec_snd_pages(pg);
 	sbus_free_consistent(sdev, PAGE_SIZE * (1 << pg), ptr, dma_addr);
 }
 
@@ -354,24 +316,10 @@ static void snd_free_sbus_pages(struct device *dev, size_t size,
  */
 
 
-/*
- * compare the two devices
- * returns non-zero if matched.
- */
-static int compare_device(const struct snd_dma_device *a, const struct snd_dma_device *b, int allow_unused)
-{
-	if (a->type != b->type)
-		return 0;
-	if (a->id != b->id) {
-		if (! allow_unused || (a->id != SNDRV_DMA_DEVICE_UNUSED && b->id != SNDRV_DMA_DEVICE_UNUSED))
-			return 0;
-	}
-	return a->dev == b->dev;
-}
-
 /**
  * snd_dma_alloc_pages - allocate the buffer area according to the given type
- * @dev: the buffer device info
+ * @type: the DMA buffer type
+ * @device: the device pointer
  * @size: the buffer size to allocate
  * @dmab: buffer allocation record to store the allocated data
  *
@@ -381,32 +329,33 @@ static int compare_device(const struct snd_dma_device *a, const struct snd_dma_d
  * Returns zero if the buffer with the given size is allocated successfuly,
  * other a negative value at error.
  */
-int snd_dma_alloc_pages(const struct snd_dma_device *dev, size_t size,
+int snd_dma_alloc_pages(int type, struct device *device, size_t size,
 			struct snd_dma_buffer *dmab)
 {
-	snd_assert(dev != NULL, return -ENXIO);
 	snd_assert(size > 0, return -ENXIO);
 	snd_assert(dmab != NULL, return -ENXIO);
 
+	dmab->dev.type = type;
+	dmab->dev.dev = device;
 	dmab->bytes = 0;
-	switch (dev->type) {
+	switch (type) {
 	case SNDRV_DMA_TYPE_CONTINUOUS:
-		dmab->area = snd_malloc_pages(size, (unsigned long)dev->dev);
+		dmab->area = snd_malloc_pages(size, (unsigned long)device);
 		dmab->addr = 0;
 		break;
 #ifdef CONFIG_SBUS
 	case SNDRV_DMA_TYPE_SBUS:
-		dmab->area = snd_malloc_sbus_pages(dev->dev, size, &dmab->addr);
+		dmab->area = snd_malloc_sbus_pages(device, size, &dmab->addr);
 		break;
 #endif
 	case SNDRV_DMA_TYPE_DEV:
-		dmab->area = snd_malloc_dev_pages(dev->dev, size, &dmab->addr);
+		dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr);
 		break;
 	case SNDRV_DMA_TYPE_DEV_SG:
-		snd_malloc_sgbuf_pages(dev, size, dmab, NULL);
+		snd_malloc_sgbuf_pages(device, size, dmab, NULL);
 		break;
 	default:
-		printk(KERN_ERR "snd-malloc: invalid device type %d\n", dev->type);
+		printk(KERN_ERR "snd-malloc: invalid device type %d\n", type);
 		dmab->area = NULL;
 		dmab->addr = 0;
 		return -ENXIO;
@@ -419,7 +368,8 @@ int snd_dma_alloc_pages(const struct snd_dma_device *dev, size_t size,
 
 /**
  * snd_dma_alloc_pages_fallback - allocate the buffer area according to the given type with fallback
- * @dev: the buffer device info
+ * @type: the DMA buffer type
+ * @device: the device pointer
  * @size: the buffer size to allocate
  * @dmab: buffer allocation record to store the allocated data
  *
@@ -431,35 +381,20 @@ int snd_dma_alloc_pages(const struct snd_dma_device *dev, size_t size,
  * Returns zero if the buffer with the given size is allocated successfuly,
  * other a negative value at error.
  */
-int snd_dma_alloc_pages_fallback(const struct snd_dma_device *dev, size_t size,
+int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size,
 				 struct snd_dma_buffer *dmab)
 {
-	snd_assert(dev != NULL, return -ENXIO);
+	int err;
+
 	snd_assert(size > 0, return -ENXIO);
 	snd_assert(dmab != NULL, return -ENXIO);
 
-	dmab->bytes = 0;
-	switch (dev->type) {
-	case SNDRV_DMA_TYPE_CONTINUOUS:
-		dmab->area = snd_malloc_pages_fallback(size, (unsigned long)dev->dev, &dmab->bytes);
-		dmab->addr = 0;
-		break;
-#ifdef CONFIG_SBUS
-	case SNDRV_DMA_TYPE_SBUS:
-		dmab->area = snd_malloc_sbus_pages_fallback(dev->dev, size, &dmab->addr, &dmab->bytes);
-		break;
-#endif
-	case SNDRV_DMA_TYPE_DEV:
-		dmab->area = snd_malloc_dev_pages_fallback(dev->dev, size, &dmab->addr, &dmab->bytes);
-		break;
-	case SNDRV_DMA_TYPE_DEV_SG:
-		snd_malloc_sgbuf_pages(dev, size, dmab, &dmab->bytes);
-		break;
-	default:
-		printk(KERN_ERR "snd-malloc: invalid device type %d\n", dev->type);
-		dmab->area = NULL;
-		dmab->addr = 0;
-		return -ENXIO;
+	while ((err = snd_dma_alloc_pages(type, device, size, dmab)) < 0) {
+		if (err != -ENOMEM)
+			return err;
+		size >>= 1;
+		if (size <= PAGE_SIZE)
+			return -ENOMEM;
 	}
 	if (! dmab->area)
 		return -ENOMEM;
@@ -469,152 +404,87 @@ int snd_dma_alloc_pages_fallback(const struct snd_dma_device *dev, size_t size,
 
 /**
  * snd_dma_free_pages - release the allocated buffer
- * @dev: the buffer device info
- * @dmbab: the buffer allocation record to release
+ * @dmab: the buffer allocation record to release
  *
  * Releases the allocated buffer via snd_dma_alloc_pages().
  */
-void snd_dma_free_pages(const struct snd_dma_device *dev, struct snd_dma_buffer *dmab)
+void snd_dma_free_pages(struct snd_dma_buffer *dmab)
 {
-	switch (dev->type) {
+	switch (dmab->dev.type) {
 	case SNDRV_DMA_TYPE_CONTINUOUS:
 		snd_free_pages(dmab->area, dmab->bytes);
 		break;
 #ifdef CONFIG_SBUS
 	case SNDRV_DMA_TYPE_SBUS:
-		snd_free_sbus_pages(dev->dev, dmab->bytes, dmab->area, dmab->addr);
+		snd_free_sbus_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
 		break;
 #endif
 	case SNDRV_DMA_TYPE_DEV:
-		snd_free_dev_pages(dev->dev, dmab->bytes, dmab->area, dmab->addr);
+		snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
 		break;
 	case SNDRV_DMA_TYPE_DEV_SG:
 		snd_free_sgbuf_pages(dmab);
 		break;
 	default:
-		printk(KERN_ERR "snd-malloc: invalid device type %d\n", dev->type);
+		printk(KERN_ERR "snd-malloc: invalid device type %d\n", dmab->dev.type);
 	}
 }
 
 
-/*
- * search for the device
- */
-static struct snd_mem_list *mem_list_find(const struct snd_dma_device *dev, int search_empty)
-{
-	struct list_head *p;
-	struct snd_mem_list *mem;
-
-	list_for_each(p, &mem_list_head) {
-		mem = list_entry(p, struct snd_mem_list, list);
-		if (mem->used && search_empty)
-			continue;
-		if (compare_device(&mem->dev, dev, search_empty))
-			return mem;
-	}
-	return NULL;
-}
-
 /**
  * snd_dma_get_reserved - get the reserved buffer for the given device
- * @dev: the buffer device info
  * @dmab: the buffer allocation record to store
+ * @id: the buffer id
  *
  * Looks for the reserved-buffer list and re-uses if the same buffer
- * is found in the list.  When the buffer is found, it's marked as used.
- * For unmarking the buffer, call snd_dma_free_reserved().
+ * is found in the list.  When the buffer is found, it's removed from the free list.
  *
  * Returns the size of buffer if the buffer is found, or zero if not found.
  */
-size_t snd_dma_get_reserved(const struct snd_dma_device *dev, struct snd_dma_buffer *dmab)
+size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id)
 {
+	struct list_head *p;
 	struct snd_mem_list *mem;
 
-	snd_assert(dev && dmab, return 0);
+	snd_assert(dmab, return 0);
 
 	down(&list_mutex);
-	mem = mem_list_find(dev, 1);
-	if (mem) {
-		mem->used = 1;
-		mem->dev = *dev;
-		*dmab = mem->buffer;
-		up(&list_mutex);
-		return dmab->bytes;
+	list_for_each(p, &mem_list_head) {
+		mem = list_entry(p, struct snd_mem_list, list);
+		if (mem->id == id &&
+		    ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev))) {
+			list_del(p);
+			*dmab = mem->buffer;
+			kfree(mem);
+			up(&list_mutex);
+			return dmab->bytes;
+		}
 	}
 	up(&list_mutex);
 	return 0;
 }
 
 /**
- * snd_dma_free_reserved - unmark the reserved buffer
- * @dev: the buffer device info
- *
- * Looks for the matching reserved buffer and erases the mark on it
- * if found.
- *
- * Returns zero.
- */
-int snd_dma_free_reserved(const struct snd_dma_device *dev)
-{
-	struct snd_mem_list *mem;
-
-	snd_assert(dev, return -EINVAL);
-	down(&list_mutex);
-	mem = mem_list_find(dev, 0);
-	if (mem)
-		mem->used = 0;
-	up(&list_mutex);
-	return 0;
-}
-
-/**
- * snd_dma_set_reserved - reserve the buffer
- * @dev: the buffer device info
+ * snd_dma_reserve_buf - reserve the buffer
  * @dmab: the buffer to reserve
+ * @id: the buffer id
  *
  * Reserves the given buffer as a reserved buffer.
- * When an old reserved buffer already exists, the old one is released
- * and replaced with the new one.
- *
- * When NULL buffer pointer or zero buffer size is given, the existing
- * buffer is released and the entry is removed.
  * 
  * Returns zero if successful, or a negative code at error.
  */
-int snd_dma_set_reserved(const struct snd_dma_device *dev, struct snd_dma_buffer *dmab)
+int snd_dma_reserve_buf(struct snd_dma_buffer *dmab, unsigned int id)
 {
 	struct snd_mem_list *mem;
 
-	snd_assert(dev, return -EINVAL);
+	snd_assert(dmab, return -EINVAL);
+	mem = kmalloc(sizeof(*mem), GFP_KERNEL);
+	if (! mem)
+		return -ENOMEM;
 	down(&list_mutex);
-	mem = mem_list_find(dev, 0);
-	if (mem) {
-		if (mem->used)
-			printk(KERN_WARNING "snd-page-alloc: releasing the used block (type=%d, id=0x%x\n", mem->dev.type, mem->dev.id);
-		snd_dma_free_pages(dev, &mem->buffer);
-		if (! dmab || ! dmab->bytes) {
-			/* remove the entry */
-			list_del(&mem->list);
-			kfree(mem);
-			up(&list_mutex);
-			return 0;
-		}
-	} else {
-		if (! dmab || ! dmab->bytes) {
-			up(&list_mutex);
-			return 0;
-		}
-		mem = kmalloc(sizeof(*mem), GFP_KERNEL);
-		if (! mem) {
-			up(&list_mutex);
-			return -ENOMEM;
-		}
-		mem->dev = *dev;
-		list_add_tail(&mem->list, &mem_list_head);
-	}
-	/* store the entry */
-	mem->used = 1;
 	mem->buffer = *dmab;
+	mem->id = id;
+	list_add_tail(&mem->list, &mem_list_head);
 	up(&list_mutex);
 	return 0;
 }
@@ -632,7 +502,7 @@ static void free_all_reserved_pages(void)
 		p = mem_list_head.next;
 		mem = list_entry(p, struct snd_mem_list, list);
 		list_del(p);
-		snd_dma_free_pages(&mem->dev, &mem->buffer);
+		snd_dma_free_pages(&mem->buffer);
 		kfree(mem);
 	}
 	up(&list_mutex);
@@ -654,7 +524,7 @@ struct prealloc_dev {
 	unsigned int buffers;
 };
 
-#define HAMMERFALL_BUFFER_SIZE    (16*1024*4*(26+1))
+#define HAMMERFALL_BUFFER_SIZE    (16*1024*4*(26+1)+0x10000)
 
 static struct prealloc_dev prealloc_devices[] __initdata = {
 	{
@@ -676,17 +546,6 @@ static struct prealloc_dev prealloc_devices[] __initdata = {
 	{ }, /* terminator */
 };
 
-/*
- * compose a snd_dma_device struct for the PCI device
- */
-static inline void snd_dma_device_pci(struct snd_dma_device *dev, struct pci_dev *pci, unsigned int id)
-{
-	memset(dev, 0, sizeof(*dev));
-	dev->type = SNDRV_DMA_TYPE_DEV;
-	dev->dev = snd_dma_pci_data(pci);
-	dev->id = id;
-}
-
 static void __init preallocate_cards(void)
 {
 	struct pci_dev *pci = NULL;
@@ -716,22 +575,13 @@ static void __init preallocate_cards(void)
 			continue;
 		}
 		for (i = 0; i < dev->buffers; i++) {
-			struct snd_mem_list *mem;
-			mem = kmalloc(sizeof(*mem), GFP_KERNEL);
-			if (! mem) {
-				printk(KERN_WARNING "snd-page-alloc: can't malloc memlist\n");
-				break;
-			}
-			memset(mem, 0, sizeof(*mem));
-			snd_dma_device_pci(&mem->dev, pci, SNDRV_DMA_DEVICE_UNUSED);
-			if (snd_dma_alloc_pages(&mem->dev, dev->size, &mem->buffer) < 0) {
+			struct snd_dma_buffer dmab;
+			memset(&dmab, 0, sizeof(dmab));
+			if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+						dev->size, &dmab) < 0)
 				printk(KERN_WARNING "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", dev->size);
-				kfree(mem);
-			} else {
-				down(&list_mutex);
-				list_add_tail(&mem->list, &mem_list_head);
-				up(&list_mutex);
-			}
+			else
+				snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci));
 		}
 	}
 }
@@ -752,48 +602,22 @@ static int snd_mem_proc_read(char *page, char **start, off_t off,
 	struct list_head *p;
 	struct snd_mem_list *mem;
 	int devno;
+	static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG", "SBUS" };
 
 	down(&list_mutex);
-	len += sprintf(page + len, "pages  : %li bytes (%li pages per %likB)\n",
-		       pages * PAGE_SIZE, pages, PAGE_SIZE / 1024);
+	len += snprintf(page + len, count - len,
+			"pages  : %li bytes (%li pages per %likB)\n",
+			pages * PAGE_SIZE, pages, PAGE_SIZE / 1024);
 	devno = 0;
 	list_for_each(p, &mem_list_head) {
 		mem = list_entry(p, struct snd_mem_list, list);
 		devno++;
-		len += sprintf(page + len, "buffer %d : ", devno);
-		if (mem->dev.id == SNDRV_DMA_DEVICE_UNUSED)
-			len += sprintf(page + len, "UNUSED");
-		else
-			len += sprintf(page + len, "ID %08x", mem->dev.id);
-		len += sprintf(page + len, " : type ");
-		switch (mem->dev.type) {
-		case SNDRV_DMA_TYPE_CONTINUOUS:
-			len += sprintf(page + len, "CONT [%p]", mem->dev.dev);
-			break;
-#ifdef CONFIG_SBUS
-		case SNDRV_DMA_TYPE_SBUS:
-			{
-				struct sbus_dev *sdev = (struct sbus_dev *)(mem->dev.dev);
-				len += sprintf(page + len, "SBUS [%x]", sdev->slot);
-			}
-			break;
-#endif
-		case SNDRV_DMA_TYPE_DEV:
-		case SNDRV_DMA_TYPE_DEV_SG:
-			if (mem->dev.dev) {
-				len += sprintf(page + len, "%s [%s]",
-					       mem->dev.type == SNDRV_DMA_TYPE_DEV_SG ? "DEV-SG" : "DEV",
-					       mem->dev.dev->bus_id);
-			} else
-				len += sprintf(page + len, "ISA");
-			break;
-		default:
-			len += sprintf(page + len, "UNKNOWN");
-			break;
-		}
-		len += sprintf(page + len, "\n  addr = 0x%lx, size = %d bytes, used = %s\n",
-			       (unsigned long)mem->buffer.addr, (int)mem->buffer.bytes,
-			       mem->used ? "yes" : "no");
+		len += snprintf(page + len, count - len,
+				"buffer %d : ID %08x : type %s\n",
+				devno, mem->id, types[mem->buffer.dev.type]);
+		len += snprintf(page + len, count - len,
+				"  addr = 0x%lx, size = %d bytes\n",
+				(unsigned long)mem->buffer.addr, (int)mem->buffer.bytes);
 	}
 	up(&list_mutex);
 	return len;
@@ -833,10 +657,8 @@ EXPORT_SYMBOL(snd_dma_alloc_pages);
 EXPORT_SYMBOL(snd_dma_alloc_pages_fallback);
 EXPORT_SYMBOL(snd_dma_free_pages);
 
-EXPORT_SYMBOL(snd_dma_get_reserved);
-EXPORT_SYMBOL(snd_dma_free_reserved);
-EXPORT_SYMBOL(snd_dma_set_reserved);
+EXPORT_SYMBOL(snd_dma_get_reserved_buf);
+EXPORT_SYMBOL(snd_dma_reserve_buf);
 
 EXPORT_SYMBOL(snd_malloc_pages);
-EXPORT_SYMBOL(snd_malloc_pages_fallback);
 EXPORT_SYMBOL(snd_free_pages);
diff --git a/sound/core/memory.c b/sound/core/memory.c
index cf4f75cec..21f76c2c8 100644
--- a/sound/core/memory.c
+++ b/sound/core/memory.c
@@ -71,8 +71,7 @@ void snd_memory_done(void)
 		snd_printk(KERN_ERR "Not freed snd_alloc_kmalloc = %li\n", snd_alloc_kmalloc);
 	if (snd_alloc_vmalloc > 0)
 		snd_printk(KERN_ERR "Not freed snd_alloc_vmalloc = %li\n", snd_alloc_vmalloc);
-	for (head = snd_alloc_kmalloc_list.prev;
-	     head != &snd_alloc_kmalloc_list; head = head->prev) {
+	list_for_each_prev(head, &snd_alloc_kmalloc_list) {
 		t = list_entry(head, struct snd_alloc_track, list);
 		if (t->magic != KMALLOC_MAGIC) {
 			snd_printk(KERN_ERR "Corrupted kmalloc\n");
@@ -80,8 +79,7 @@ void snd_memory_done(void)
 		}
 		snd_printk(KERN_ERR "kmalloc(%ld) from %p not freed\n", (long) t->size, t->caller);
 	}
-	for (head = snd_alloc_vmalloc_list.prev;
-	     head != &snd_alloc_vmalloc_list; head = head->prev) {
+	list_for_each_prev(head, &snd_alloc_vmalloc_list) {
 		t = list_entry(head, struct snd_alloc_track, list);
 		if (t->magic != VMALLOC_MAGIC) {
 			snd_printk(KERN_ERR "Corrupted vmalloc\n");
@@ -118,6 +116,17 @@ void *snd_hidden_kmalloc(size_t size, int flags)
 	return _snd_kmalloc(size, flags);
 }
 
+void *snd_hidden_kcalloc(size_t n, size_t size, int flags)
+{
+	void *ret = NULL;
+	if (n != 0 && size > INT_MAX / n)
+		return ret;
+	ret = _snd_kmalloc(n * size, flags);
+	if (ret)
+		memset(ret, 0, n * size);
+	return ret;
+}
+
 void snd_hidden_kfree(const void *obj)
 {
 	unsigned long flags;
@@ -140,46 +149,6 @@ void snd_hidden_kfree(const void *obj)
 	snd_wrapper_kfree(obj);
 }
 
-void *_snd_magic_kcalloc(unsigned long magic, size_t size, int flags)
-{
-	unsigned long *ptr;
-	ptr = _snd_kmalloc(size + sizeof(unsigned long), flags);
-	if (ptr) {
-		*ptr++ = magic;
-		memset(ptr, 0, size);
-	}
-	return ptr;
-}
-
-void *_snd_magic_kmalloc(unsigned long magic, size_t size, int flags)
-{
-	unsigned long *ptr;
-	ptr = _snd_kmalloc(size + sizeof(unsigned long), flags);
-	if (ptr)
-		*ptr++ = magic;
-	return ptr;
-}
-
-void snd_magic_kfree(void *_ptr)
-{
-	unsigned long *ptr = _ptr;
-	if (ptr == NULL) {
-		snd_printk(KERN_WARNING "null snd_magic_kfree (called from %p)\n", __builtin_return_address(0));
-		return;
-	}
-	*--ptr = 0;
-	{
-		struct snd_alloc_track *t;
-		t = snd_alloc_track_entry(ptr);
-		if (t->magic != KMALLOC_MAGIC) {
-			snd_printk(KERN_ERR "bad snd_magic_kfree (called from %p)\n", __builtin_return_address(0));
-			return;
-		}
-	}
-	snd_hidden_kfree(ptr);
-	return;
-}
-
 void *snd_hidden_vmalloc(unsigned long size)
 {
 	void *ptr;
@@ -255,25 +224,6 @@ int __exit snd_memory_info_done(void)
 
 #endif /* CONFIG_SND_DEBUG_MEMORY */
 
-/**
- * snd_kcalloc - memory allocation and zero-clear
- * @size: the size to allocate in bytes
- * @flags: allocation conditions, GFP_XXX
- *
- * Allocates a memory chunk via kmalloc() and initializes it to zero.
- *
- * Returns the pointer, or NULL if no enoguh memory.
- */
-void *snd_kcalloc(size_t size, int flags)
-{
-	void *ptr;
-	
-	ptr = _snd_kmalloc(size, flags);
-	if (ptr)
-		memset(ptr, 0, size);
-	return ptr;
-}
-
 /**
  * snd_kmalloc_strdup - copy the string
  * @string: the original string
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index d8359d301..caab3ee27 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -21,6 +21,7 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <sound/core.h>
@@ -51,7 +52,7 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
 	err = snd_card_file_add(card, file);
 	if (err < 0)
 		return err;
-	fmixer = (snd_mixer_oss_file_t *)snd_kcalloc(sizeof(*fmixer), GFP_KERNEL);
+	fmixer = kcalloc(1, sizeof(*fmixer), GFP_KERNEL);
 	if (fmixer == NULL) {
 		snd_card_file_remove(card, file);
 		return -ENOMEM;
@@ -358,10 +359,16 @@ static int snd_mixer_oss_ioctl1(snd_mixer_oss_file_t *fmixer, unsigned int cmd,
 	return -ENXIO;
 }
 
+/* FIXME: need to unlock BKL to allow preemption */
 int snd_mixer_oss_ioctl(struct inode *inode, struct file *file,
 			unsigned int cmd, unsigned long arg)
 {
-	return snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg);
+	int err;
+	/* FIXME: need to unlock BKL to allow preemption */
+	unlock_kernel();
+	err = snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg);
+	lock_kernel();
+	return err;
 }
 
 int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long arg)
@@ -508,8 +515,8 @@ static void snd_mixer_oss_get_volume1_vol(snd_mixer_oss_file_t *fmixer,
 		up_read(&card->controls_rwsem);
 		return;
 	}
-	uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-	uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+	uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+	uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
 	if (uinfo == NULL || uctl == NULL)
 		goto __unalloc;
 	snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -544,8 +551,8 @@ static void snd_mixer_oss_get_volume1_sw(snd_mixer_oss_file_t *fmixer,
 		up_read(&card->controls_rwsem);
 		return;
 	}
-	uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-	uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+	uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+	uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
 	if (uinfo == NULL || uctl == NULL)
 		goto __unalloc;
 	snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -607,8 +614,8 @@ static void snd_mixer_oss_put_volume1_vol(snd_mixer_oss_file_t *fmixer,
 	down_read(&card->controls_rwsem);
 	if ((kctl = snd_ctl_find_numid(card, numid)) == NULL)
 		return;
-	uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-	uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+	uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+	uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
 	if (uinfo == NULL || uctl == NULL)
 		goto __unalloc;
 	snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -646,8 +653,8 @@ static void snd_mixer_oss_put_volume1_sw(snd_mixer_oss_file_t *fmixer,
 		up_read(&fmixer->card->controls_rwsem);
 		return;
 	}
-	uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-	uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+	uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+	uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
 	if (uinfo == NULL || uctl == NULL)
 		goto __unalloc;
 	snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
@@ -767,8 +774,8 @@ static int snd_mixer_oss_get_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int
 	snd_ctl_elem_value_t *uctl;
 	int err, idx;
 	
-	uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-	uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+	uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+	uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
 	if (uinfo == NULL || uctl == NULL) {
 		err = -ENOMEM;
 		goto __unlock;
@@ -814,8 +821,8 @@ static int snd_mixer_oss_put_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int
 	int err;
 	unsigned int idx;
 
-	uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL);
-	uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+	uinfo = kcalloc(1, sizeof(*uinfo), GFP_KERNEL);
+	uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
 	if (uinfo == NULL || uctl == NULL) {
 		err = -ENOMEM;
 		goto __unlock;
@@ -968,8 +975,10 @@ static int snd_mixer_oss_build_input(snd_mixer_oss_t *mixer, struct snd_mixer_os
 		snd_ctl_elem_info_t uinfo;
 
 		memset(&uinfo, 0, sizeof(uinfo));
-		if (kctl->info(kctl, &uinfo))
+		if (kctl->info(kctl, &uinfo)) {
+			up_read(&mixer->card->controls_rwsem);
 			return 0;
+		}
 		strcpy(str, ptr->name);
 		if (!strcmp(str, "Master"))
 			strcpy(str, "Mix");
@@ -1060,7 +1069,7 @@ static char *oss_mixer_names[SNDRV_OSS_MAX_MIXERS] = {
 static void snd_mixer_oss_proc_read(snd_info_entry_t *entry,
 				    snd_info_buffer_t * buffer)
 {
-	snd_mixer_oss_t *mixer = snd_magic_cast(snd_mixer_oss_t, entry->private_data, return);
+	snd_mixer_oss_t *mixer = entry->private_data;
 	int i;
 
 	down(&mixer->reg_mutex);
@@ -1084,7 +1093,7 @@ static void snd_mixer_oss_proc_read(snd_info_entry_t *entry,
 static void snd_mixer_oss_proc_write(snd_info_entry_t *entry,
 				     snd_info_buffer_t * buffer)
 {
-	snd_mixer_oss_t *mixer = snd_magic_cast(snd_mixer_oss_t, entry->private_data, return);
+	snd_mixer_oss_t *mixer = entry->private_data;
 	char line[128], str[32], idxstr[16], *cptr;
 	int ch, idx;
 	struct snd_mixer_oss_assign_table *tbl;
@@ -1210,7 +1219,7 @@ static void snd_mixer_oss_build(snd_mixer_oss_t *mixer)
 	};
 	unsigned int idx;
 	
-	for (idx = 0; idx < sizeof(table) / sizeof(struct snd_mixer_oss_assign_table); idx++)
+	for (idx = 0; idx < ARRAY_SIZE(table); idx++)
 		snd_mixer_oss_build_input(mixer, &table[idx], 0, 0);
 	if (mixer->mask_recsrc) {
 		mixer->get_recsrc = snd_mixer_oss_get_recsrc2;
@@ -1224,7 +1233,7 @@ static void snd_mixer_oss_build(snd_mixer_oss_t *mixer)
 
 static int snd_mixer_oss_free1(void *private)
 {
-	snd_mixer_oss_t *mixer = snd_magic_cast(snd_mixer_oss_t, private, return -ENXIO);
+	snd_mixer_oss_t *mixer = private;
 	snd_card_t * card;
 	int idx;
  
@@ -1237,7 +1246,7 @@ static int snd_mixer_oss_free1(void *private)
 		if (chn->private_free)
 			chn->private_free(chn);
 	}
-	snd_magic_kfree(mixer);
+	kfree(mixer);
 	return 0;
 }
 
@@ -1249,7 +1258,7 @@ static int snd_mixer_oss_notify_handler(snd_card_t * card, int cmd)
 		char name[128];
 		int idx, err;
 
-		mixer = snd_magic_kcalloc(snd_mixer_oss_t, sizeof(snd_mixer_oss_t), GFP_KERNEL);
+		mixer = kcalloc(2, sizeof(*mixer), GFP_KERNEL);
 		if (mixer == NULL)
 			return -ENOMEM;
 		init_MUTEX(&mixer->reg_mutex);
@@ -1259,7 +1268,7 @@ static int snd_mixer_oss_notify_handler(snd_card_t * card, int cmd)
 						   &snd_mixer_oss_reg,
 						   name)) < 0) {
 			snd_printk("unable to register OSS mixer device %i:%i\n", card->number, 0);
-			snd_magic_kfree(mixer);
+			kfree(mixer);
 			return err;
 		}
 		mixer->oss_dev_alloc = 1;
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 099d230f3..5d87847c6 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -28,6 +28,7 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/vmalloc.h>
@@ -53,13 +54,10 @@ MODULE_DESCRIPTION("PCM OSS emulation for ALSA.");
 MODULE_LICENSE("GPL");
 module_param_array(dsp_map, int, boot_devs, 0444);
 MODULE_PARM_DESC(dsp_map, "PCM device number assigned to 1st OSS device.");
-MODULE_PARM_SYNTAX(dsp_map, "default:0,skill:advanced");
 module_param_array(adsp_map, int, boot_devs, 0444);
 MODULE_PARM_DESC(adsp_map, "PCM device number assigned to 2nd OSS device.");
-MODULE_PARM_SYNTAX(adsp_map, "default:1,skill:advanced");
 module_param(nonblock_open, bool, 0644);
 MODULE_PARM_DESC(nonblock_open, "Don't block opening busy PCM devices.");
-MODULE_PARM_SYNTAX(nonblock_open, "default:0,skill:advanced");
 MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM);
 MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM1);
 
@@ -1177,10 +1175,11 @@ static int snd_pcm_oss_get_formats(snd_pcm_oss_file_t *pcm_oss_file)
 	snd_pcm_substream_t *substream;
 	int err;
 	int direct;
-	snd_pcm_hw_params_t params;
+	snd_pcm_hw_params_t *params;
 	unsigned int formats = 0;
 	snd_mask_t format_mask;
 	int fmt;
+
 	if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
 		return err;
 	if (atomic_read(&substream->runtime->mmap_count)) {
@@ -1194,10 +1193,14 @@ static int snd_pcm_oss_get_formats(snd_pcm_oss_file_t *pcm_oss_file)
 		       AFMT_S16_LE | AFMT_S16_BE |
 		       AFMT_S8 | AFMT_U16_LE |
 		       AFMT_U16_BE;
-	_snd_pcm_hw_params_any(&params);
-	err = snd_pcm_hw_refine(substream, &params);
+	params = kmalloc(sizeof(*params), GFP_KERNEL);
+	if (!params)
+		return -ENOMEM;
+	_snd_pcm_hw_params_any(params);
+	err = snd_pcm_hw_refine(substream, params);
+	format_mask = *hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 
+	kfree(params);
 	snd_assert(err >= 0, return err);
-	format_mask = *hw_param_mask(&params, SNDRV_PCM_HW_PARAM_FORMAT); 
 	for (fmt = 0; fmt < 32; ++fmt) {
 		if (snd_mask_test(&format_mask, fmt)) {
 			int f = snd_pcm_oss_format_to(fmt);
@@ -1693,7 +1696,7 @@ static int snd_pcm_oss_release_file(snd_pcm_oss_file_t *pcm_oss_file)
 		snd_pcm_oss_release_substream(substream);
 		snd_pcm_release_substream(substream);
 	}
-	snd_magic_kfree(pcm_oss_file);
+	kfree(pcm_oss_file);
 	return 0;
 }
 
@@ -1712,7 +1715,7 @@ static int snd_pcm_oss_open_file(struct file *file,
 	snd_assert(rpcm_oss_file != NULL, return -EINVAL);
 	*rpcm_oss_file = NULL;
 
-	pcm_oss_file = snd_magic_kcalloc(snd_pcm_oss_file_t, 0, GFP_KERNEL);
+	pcm_oss_file = kcalloc(1, sizeof(*pcm_oss_file), GFP_KERNEL);
 	if (pcm_oss_file == NULL)
 		return -ENOMEM;
 
@@ -1892,7 +1895,7 @@ static int snd_pcm_oss_release(struct inode *inode, struct file *file)
 	snd_pcm_substream_t *substream;
 	snd_pcm_oss_file_t *pcm_oss_file;
 
-	pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO);
+	pcm_oss_file = file->private_data;
 	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
 	if (substream == NULL)
 		substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
@@ -1908,14 +1911,14 @@ static int snd_pcm_oss_release(struct inode *inode, struct file *file)
 	return 0;
 }
 
-static int snd_pcm_oss_ioctl(struct inode *inode, struct file *file,
-                             unsigned int cmd, unsigned long arg)
+static inline int _snd_pcm_oss_ioctl(struct inode *inode, struct file *file,
+				     unsigned int cmd, unsigned long arg)
 {
 	snd_pcm_oss_file_t *pcm_oss_file;
 	int __user *p = (int __user *)arg;
 	int res;
 
-	pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO);
+	pcm_oss_file = file->private_data;
 	if (cmd == OSS_GETVERSION)
 		return put_user(SNDRV_OSS_VERSION, p);
 	if (cmd == OSS_ALSAEMULVER)
@@ -2068,12 +2071,23 @@ static int snd_pcm_oss_ioctl(struct inode *inode, struct file *file,
 	return -EINVAL;
 }
 
+/* FIXME: need to unlock BKL to allow preemption */
+static int snd_pcm_oss_ioctl(struct inode *inode, struct file *file,
+			     unsigned int cmd, unsigned long arg)
+{
+	int err;
+	unlock_kernel();
+	err = _snd_pcm_oss_ioctl(inode, file, cmd, arg);
+	lock_kernel();
+	return err;
+}
+
 static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
 {
 	snd_pcm_oss_file_t *pcm_oss_file;
 	snd_pcm_substream_t *substream;
 
-	pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO);
+	pcm_oss_file = file->private_data;
 	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
 	if (substream == NULL)
 		return -ENXIO;
@@ -2094,7 +2108,7 @@ static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size
 	snd_pcm_substream_t *substream;
 	long result;
 
-	pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO);
+	pcm_oss_file = file->private_data;
 	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
 	if (substream == NULL)
 		return -ENXIO;
@@ -2131,7 +2145,7 @@ static unsigned int snd_pcm_oss_poll(struct file *file, poll_table * wait)
 	unsigned int mask;
 	snd_pcm_substream_t *psubstream = NULL, *csubstream = NULL;
 	
-	pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return 0);
+	pcm_oss_file = file->private_data;
 
 	psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
 	csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
@@ -2178,7 +2192,7 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
 #ifdef OSS_DEBUG
 	printk("pcm_oss: mmap begin\n");
 #endif
-	pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO);
+	pcm_oss_file = file->private_data;
 	switch ((area->vm_flags & (VM_READ | VM_WRITE))) {
 	case VM_READ | VM_WRITE:
 		substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
@@ -2280,7 +2294,7 @@ static void snd_pcm_oss_proc_write(snd_info_entry_t *entry,
 				   snd_info_buffer_t * buffer)
 {
 	snd_pcm_str_t *pstr = (snd_pcm_str_t *)entry->private_data;
-	char line[512], str[32], task_name[32], *ptr;
+	char line[256], str[32], task_name[32], *ptr;
 	int idx1;
 	snd_pcm_oss_setup_t *setup, *setup1, template;
 
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
index 6fd63ca66..855071fcb 100644
--- a/sound/core/oss/pcm_plugin.c
+++ b/sound/core/oss/pcm_plugin.c
@@ -172,7 +172,7 @@ int snd_pcm_plugin_build(snd_pcm_plug_t *plug,
 	
 	snd_assert(plug != NULL, return -ENXIO);
 	snd_assert(src_format != NULL && dst_format != NULL, return -ENXIO);
-	plugin = (snd_pcm_plugin_t *)snd_kcalloc(sizeof(*plugin) + extra, GFP_KERNEL);
+	plugin = kcalloc(1, sizeof(*plugin) + extra, GFP_KERNEL);
 	if (plugin == NULL)
 		return -ENOMEM;
 	plugin->name = name;
@@ -189,7 +189,7 @@ int snd_pcm_plugin_build(snd_pcm_plug_t *plug,
 		channels = src_format->channels;
 	else
 		channels = dst_format->channels;
-	plugin->buf_channels = snd_kcalloc(channels * sizeof(*plugin->buf_channels), GFP_KERNEL);
+	plugin->buf_channels = kcalloc(channels, sizeof(*plugin->buf_channels), GFP_KERNEL);
 	if (plugin->buf_channels == NULL) {
 		snd_pcm_plugin_free(plugin);
 		return -ENOMEM;
@@ -370,7 +370,7 @@ int snd_pcm_plug_slave_format(int format, snd_mask_t *format_mask)
 		unsigned int i;
 		switch (format) {
 		case SNDRV_PCM_FORMAT_MU_LAW:
-			for (i = 0; i < sizeof(preferred_formats) / sizeof(preferred_formats[0]); ++i) {
+			for (i = 0; i < ARRAY_SIZE(preferred_formats); ++i) {
 				int format1 = preferred_formats[i];
 				if (snd_mask_test(format_mask, format1))
 					return format1;
@@ -468,7 +468,7 @@ int snd_pcm_plug_format_plugins(snd_pcm_plug_t *plug,
 	if (srcformat.channels > dstformat.channels) {
 		int sv = srcformat.channels;
 		int dv = dstformat.channels;
-		route_ttable_entry_t *ttable = snd_kcalloc(dv*sv*sizeof(*ttable), GFP_KERNEL);
+		route_ttable_entry_t *ttable = kcalloc(dv * sv, sizeof(*ttable), GFP_KERNEL);
 		if (ttable == NULL)
 			return -ENOMEM;
 #if 1
@@ -531,7 +531,7 @@ int snd_pcm_plug_format_plugins(snd_pcm_plug_t *plug,
 	if (srcformat.channels < dstformat.channels) {
 		int sv = srcformat.channels;
 		int dv = dstformat.channels;
-		route_ttable_entry_t *ttable = snd_kcalloc(dv * sv * sizeof(*ttable), GFP_KERNEL);
+		route_ttable_entry_t *ttable = kcalloc(dv * sv, sizeof(*ttable), GFP_KERNEL);
 		if (ttable == NULL)
 			return -ENOMEM;
 #if 0
@@ -846,41 +846,31 @@ int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_area, size_t dst_offs
 			 size_t samples, int format)
 {
 	/* FIXME: sub byte resolution and odd dst_offset */
-	char *dst;
+	unsigned char *dst;
 	unsigned int dst_step;
 	int width;
-	u_int64_t silence;
+	const unsigned char *silence;
 	if (!dst_area->addr)
 		return 0;
 	dst = dst_area->addr + (dst_area->first + dst_area->step * dst_offset) / 8;
 	width = snd_pcm_format_physical_width(format);
+	if (width <= 0)
+		return -EINVAL;
+	if (dst_area->step == (unsigned int) width && width >= 8)
+		return snd_pcm_format_set_silence(format, dst, samples);
 	silence = snd_pcm_format_silence_64(format);
-	if (dst_area->step == (unsigned int) width) {
-		size_t dwords = samples * width / 64;
-		u_int64_t *dst64 = (u_int64_t *)dst;
-
-		samples -= dwords * 64 / width;
-		while (dwords-- > 0)
-			*dst64++ = silence;
-		if (samples == 0)
-			return 0;
-		dst = (char *)dst64;
-	}
+	if (! silence)
+		return -EINVAL;
 	dst_step = dst_area->step / 8;
-	switch (width) {
-	case 4: {
-		u_int8_t s0 = silence & 0xf0;
-		u_int8_t s1 = silence & 0x0f;
+	if (width == 4) {
+		/* Ima ADPCM */
 		int dstbit = dst_area->first % 8;
 		int dstbit_step = dst_area->step % 8;
 		while (samples-- > 0) {
-			if (dstbit) {
+			if (dstbit)
 				*dst &= 0xf0;
-				*dst |= s1;
-			} else {
+			else
 				*dst &= 0x0f;
-				*dst |= s0;
-			}
 			dst += dst_step;
 			dstbit += dstbit_step;
 			if (dstbit == 8) {
@@ -888,41 +878,12 @@ int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_area, size_t dst_offs
 				dstbit = 0;
 			}
 		}
-		break;
-	}
-	case 8: {
-		u_int8_t sil = silence;
-		while (samples-- > 0) {
-			*dst = sil;
-			dst += dst_step;
-		}
-		break;
-	}
-	case 16: {
-		u_int16_t sil = silence;
-		while (samples-- > 0) {
-			*(u_int16_t*)dst = sil;
-			dst += dst_step;
-		}
-		break;
-	}
-	case 32: {
-		u_int32_t sil = silence;
-		while (samples-- > 0) {
-			*(u_int32_t*)dst = sil;
-			dst += dst_step;
-		}
-		break;
-	}
-	case 64: {
+	} else {
+		width /= 8;
 		while (samples-- > 0) {
-			*(u_int64_t*)dst = silence;
+			memcpy(dst, silence, width);
 			dst += dst_step;
 		}
-		break;
-	}
-	default:
-		snd_BUG();
 	}
 	return 0;
 }
@@ -942,18 +903,18 @@ int snd_pcm_area_copy(const snd_pcm_channel_area_t *src_area, size_t src_offset,
 	if (!dst_area->addr)
 		return 0;
 	width = snd_pcm_format_physical_width(format);
+	if (width <= 0)
+		return -EINVAL;
 	if (src_area->step == (unsigned int) width &&
-	    dst_area->step == (unsigned int) width) {
+	    dst_area->step == (unsigned int) width && width >= 8) {
 		size_t bytes = samples * width / 8;
-		samples -= bytes * 8 / width;
 		memcpy(dst, src, bytes);
-		if (samples == 0)
-			return 0;
+		return 0;
 	}
 	src_step = src_area->step / 8;
 	dst_step = dst_area->step / 8;
-	switch (width) {
-	case 4: {
+	if (width == 4) {
+		/* Ima ADPCM */
 		int srcbit = src_area->first % 8;
 		int srcbit_step = src_area->step % 8;
 		int dstbit = dst_area->first % 8;
@@ -963,12 +924,11 @@ int snd_pcm_area_copy(const snd_pcm_channel_area_t *src_area, size_t src_offset,
 			if (srcbit)
 				srcval = *src & 0x0f;
 			else
-				srcval = *src & 0xf0;
+				srcval = (*src & 0xf0) >> 4;
 			if (dstbit)
-				*dst &= 0xf0;
+				*dst = (*dst & 0xf0) | srcval;
 			else
-				*dst &= 0x0f;
-			*dst |= srcval;
+				*dst = (*dst & 0x0f) | (srcval << 4);
 			src += src_step;
 			srcbit += srcbit_step;
 			if (srcbit == 8) {
@@ -982,42 +942,13 @@ int snd_pcm_area_copy(const snd_pcm_channel_area_t *src_area, size_t src_offset,
 				dstbit = 0;
 			}
 		}
-		break;
-	}
-	case 8: {
-		while (samples-- > 0) {
-			*dst = *src;
-			src += src_step;
-			dst += dst_step;
-		}
-		break;
-	}
-	case 16: {
-		while (samples-- > 0) {
-			*(u_int16_t*)dst = *(u_int16_t*)src;
-			src += src_step;
-			dst += dst_step;
-		}
-		break;
-	}
-	case 32: {
-		while (samples-- > 0) {
-			*(u_int32_t*)dst = *(u_int32_t*)src;
-			src += src_step;
-			dst += dst_step;
-		}
-		break;
-	}
-	case 64: {
+	} else {
+		width /= 8;
 		while (samples-- > 0) {
-			*(u_int64_t*)dst = *(u_int64_t*)src;
+			memcpy(dst, src, width);
 			src += src_step;
 			dst += dst_step;
 		}
-		break;
-	}
-	default:
-		snd_BUG();
 	}
 	return 0;
 }
diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h
index 342ec0964..e21c13648 100644
--- a/sound/core/oss/pcm_plugin.h
+++ b/sound/core/oss/pcm_plugin.h
@@ -35,7 +35,7 @@ static inline size_t bitset_size(int nbits)
 
 static inline bitset_t *bitset_alloc(int nbits)
 {
-	return snd_kcalloc(bitset_size(nbits) * sizeof(bitset_t), GFP_KERNEL);
+	return kcalloc(bitset_size(nbits), sizeof(bitset_t), GFP_KERNEL);
 }
 	
 static inline void bitset_set(bitset_t *bitmap, unsigned int pos)
diff --git a/sound/core/oss/route.c b/sound/core/oss/route.c
index a33764fd6..4d53bea2e 100644
--- a/sound/core/oss/route.c
+++ b/sound/core/oss/route.c
@@ -458,7 +458,7 @@ static int route_load_ttable(snd_pcm_plugin_t *plugin,
 			dptr->func = route_to_channel;
 		if (nsrcs > 0) {
                         int srcidx;
-			dptr->srcs = snd_kcalloc(nsrcs * sizeof(*srcs), GFP_KERNEL);
+			dptr->srcs = kcalloc(nsrcs, sizeof(*srcs), GFP_KERNEL);
                         for(srcidx = 0; srcidx < nsrcs; srcidx++)
 				dptr->srcs[srcidx] = srcs[srcidx];
 		} else
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 8ee8fa709..d25dad47e 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -585,7 +585,7 @@ int snd_pcm_new_stream(snd_pcm_t *pcm, int stream, int substream_count)
 	}
 	prev = NULL;
 	for (idx = 0, prev = NULL; idx < substream_count; idx++) {
-		substream = snd_magic_kcalloc(snd_pcm_substream_t, 0, GFP_KERNEL);
+		substream = kcalloc(1, sizeof(*substream), GFP_KERNEL);
 		if (substream == NULL)
 			return -ENOMEM;
 		substream->pcm = pcm;
@@ -600,7 +600,7 @@ int snd_pcm_new_stream(snd_pcm_t *pcm, int stream, int substream_count)
 			prev->next = substream;
 		err = snd_pcm_substream_proc_init(substream);
 		if (err < 0) {
-			snd_magic_kfree(substream);
+			kfree(substream);
 			return err;
 		}
 		substream->group = &substream->self_group;
@@ -645,7 +645,7 @@ int snd_pcm_new(snd_card_t * card, char *id, int device,
 	snd_assert(rpcm != NULL, return -EINVAL);
 	*rpcm = NULL;
 	snd_assert(card != NULL, return -ENXIO);
-	pcm = snd_magic_kcalloc(snd_pcm_t, 0, GFP_KERNEL);
+	pcm = kcalloc(1, sizeof(*pcm), GFP_KERNEL);
 	if (pcm == NULL)
 		return -ENOMEM;
 	pcm->card = card;
@@ -681,7 +681,7 @@ static void snd_pcm_free_stream(snd_pcm_str_t * pstr)
 	while (substream) {
 		substream_next = substream->next;
 		snd_pcm_substream_proc_done(substream);
-		snd_magic_kfree(substream);
+		kfree(substream);
 		substream = substream_next;
 	}
 	snd_pcm_stream_proc_done(pstr);
@@ -702,13 +702,13 @@ static int snd_pcm_free(snd_pcm_t *pcm)
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 	snd_pcm_free_stream(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK]);
 	snd_pcm_free_stream(&pcm->streams[SNDRV_PCM_STREAM_CAPTURE]);
-	snd_magic_kfree(pcm);
+	kfree(pcm);
 	return 0;
 }
 
 static int snd_pcm_dev_free(snd_device_t *device)
 {
-	snd_pcm_t *pcm = snd_magic_cast(snd_pcm_t, device->device_data, return -ENXIO);
+	snd_pcm_t *pcm = device->device_data;
 	return snd_pcm_free(pcm);
 }
 
@@ -783,7 +783,7 @@ int snd_pcm_open_substream(snd_pcm_t *pcm, int stream,
 	if (substream == NULL)
 		return -EAGAIN;
 
-	runtime = snd_kcalloc(sizeof(snd_pcm_runtime_t), GFP_KERNEL);
+	runtime = kcalloc(1, sizeof(*runtime), GFP_KERNEL);
 	if (runtime == NULL)
 		return -ENOMEM;
 
@@ -843,7 +843,7 @@ static int snd_pcm_dev_register(snd_device_t *device)
 	snd_pcm_substream_t *substream;
 	struct list_head *list;
 	char str[16];
-	snd_pcm_t *pcm = snd_magic_cast(snd_pcm_t, device->device_data, return -ENXIO);
+	snd_pcm_t *pcm = device->device_data;
 
 	snd_assert(pcm != NULL && device != NULL, return -ENXIO);
 	down(&register_mutex);
@@ -888,7 +888,7 @@ static int snd_pcm_dev_register(snd_device_t *device)
 
 static int snd_pcm_dev_disconnect(snd_device_t *device)
 {
-	snd_pcm_t *pcm = snd_magic_cast(snd_pcm_t, device->device_data, return -ENXIO);
+	snd_pcm_t *pcm = device->device_data;
 	struct list_head *list;
 	snd_pcm_substream_t *substream;
 	int idx, cidx;
@@ -914,7 +914,7 @@ static int snd_pcm_dev_unregister(snd_device_t *device)
 	int idx, cidx, devtype;
 	snd_pcm_substream_t *substream;
 	struct list_head *list;
-	snd_pcm_t *pcm = snd_magic_cast(snd_pcm_t, device->device_data, return -ENXIO);
+	snd_pcm_t *pcm = device->device_data;
 
 	snd_assert(pcm != NULL, return -ENXIO);
 	down(&register_mutex);
@@ -1050,6 +1050,9 @@ EXPORT_SYMBOL(snd_pcm_release);
 EXPORT_SYMBOL(snd_pcm_playback_poll);
 EXPORT_SYMBOL(snd_pcm_capture_poll);
 EXPORT_SYMBOL(snd_pcm_mmap_data);
+#if SNDRV_PCM_INFO_MMAP_IOMEM
+EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
+#endif
  /* pcm_misc.c */
 EXPORT_SYMBOL(snd_pcm_format_signed);
 EXPORT_SYMBOL(snd_pcm_format_unsigned);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index b104d3815..743464536 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -128,12 +128,29 @@ void snd_pcm_playback_silence(snd_pcm_substream_t *substream, snd_pcm_uframes_t
 	}
 }
 
+static void xrun(snd_pcm_substream_t *substream)
+{
+	snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+#ifdef CONFIG_SND_DEBUG
+	if (substream->pstr->xrun_debug) {
+		snd_printd(KERN_DEBUG "XRUN: pcmC%dD%d%c\n",
+			   substream->pcm->card->number,
+			   substream->pcm->device,
+			   substream->stream ? 'c' : 'p');
+		if (substream->pstr->xrun_debug > 1)
+			dump_stack();
+	}
+#endif
+}
+
 static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(snd_pcm_substream_t *substream,
 							  snd_pcm_runtime_t *runtime)
 {
 	snd_pcm_uframes_t pos;
 
 	pos = substream->ops->pointer(substream);
+	if (pos == SNDRV_PCM_POS_XRUN)
+		return pos; /* XRUN */
 	if (runtime->tstamp_mode & SNDRV_PCM_TSTAMP_MMAP)
 		snd_timestamp_now((snd_timestamp_t*)&runtime->status->tstamp, runtime->tstamp_timespec);
 #ifdef CONFIG_SND_DEBUG
@@ -158,19 +175,10 @@ static inline int snd_pcm_update_hw_ptr_post(snd_pcm_substream_t *substream,
 	if (avail > runtime->avail_max)
 		runtime->avail_max = avail;
 	if (avail >= runtime->stop_threshold) {
-		snd_pcm_stop(substream,
-			     runtime->status->state == SNDRV_PCM_STATE_DRAINING ?
-			     SNDRV_PCM_STATE_SETUP : SNDRV_PCM_STATE_XRUN);
-#ifdef CONFIG_SND_DEBUG
-		if (substream->pstr->xrun_debug) {
-			snd_printd(KERN_DEBUG "XRUN: pcmC%dD%d%c\n",
-				   substream->pcm->card->number,
-				   substream->pcm->device,
-				   substream->stream ? 'c' : 'p');
-			if (substream->pstr->xrun_debug > 1)
-				dump_stack();
-		}
-#endif
+		if (substream->runtime->status->state == SNDRV_PCM_STATE_DRAINING)
+			snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
+		else
+			xrun(substream);
 		return -EPIPE;
 	}
 	if (avail >= runtime->control->avail_min)
@@ -186,6 +194,10 @@ static inline int snd_pcm_update_hw_ptr_interrupt(snd_pcm_substream_t *substream
 	snd_pcm_sframes_t delta;
 
 	pos = snd_pcm_update_hw_ptr_pos(substream, runtime);
+	if (pos == SNDRV_PCM_POS_XRUN) {
+		xrun(substream);
+		return -EPIPE;
+	}
 	if (runtime->period_size == runtime->buffer_size)
 		goto __next_buf;
 	new_hw_ptr = runtime->hw_ptr_base + pos;
@@ -230,6 +242,10 @@ int snd_pcm_update_hw_ptr(snd_pcm_substream_t *substream)
 
 	old_hw_ptr = runtime->status->hw_ptr;
 	pos = snd_pcm_update_hw_ptr_pos(substream, runtime);
+	if (pos == SNDRV_PCM_POS_XRUN) {
+		xrun(substream);
+		return -EPIPE;
+	}
 	new_hw_ptr = runtime->hw_ptr_base + pos;
 
 	delta = old_hw_ptr - new_hw_ptr;
@@ -887,22 +903,18 @@ int snd_pcm_hw_rule_add(snd_pcm_runtime_t *runtime, unsigned int cond,
 	va_list args;
 	va_start(args, dep);
 	if (constrs->rules_num >= constrs->rules_all) {
-		snd_pcm_hw_rule_t *old = constrs->rules;
-		if (constrs->rules_all == 0)
-			constrs->rules_all = 32;
-		else {
-			old = constrs->rules;
-			constrs->rules_all += 10;
-		}
-		constrs->rules = snd_kcalloc(constrs->rules_all * sizeof(*c),
-					     GFP_KERNEL);
-		if (!constrs->rules)
+		snd_pcm_hw_rule_t *new;
+		unsigned int new_rules = constrs->rules_all + 16;
+		new = kcalloc(new_rules, sizeof(*c), GFP_KERNEL);
+		if (!new)
 			return -ENOMEM;
-		if (old) {
-			memcpy(constrs->rules, old,
+		if (constrs->rules) {
+			memcpy(new, constrs->rules,
 			       constrs->rules_num * sizeof(*c));
-			kfree(old);
+			kfree(constrs->rules);
 		}
+		constrs->rules = new;
+		constrs->rules_all = new_rules;
 	}
 	c = &constrs->rules[constrs->rules_num];
 	c->cond = cond;
@@ -911,7 +923,7 @@ int snd_pcm_hw_rule_add(snd_pcm_runtime_t *runtime, unsigned int cond,
 	c->private = private;
 	k = 0;
 	while (1) {
-		snd_assert(k < sizeof(c->deps) / sizeof(c->deps[0]), return -EINVAL);
+		snd_assert(k < ARRAY_SIZE(c->deps), return -EINVAL);
 		c->deps[k++] = dep;
 		if (dep < 0)
 			break;
@@ -1109,7 +1121,7 @@ static int snd_pcm_hw_rule_pow2(snd_pcm_hw_params_t *params, snd_pcm_hw_rule_t *
 		1<<24, 1<<25, 1<<26, 1<<27, 1<<28, 1<<29, 1<<30
 	};
 	return snd_interval_list(hw_param_interval(params, rule->var),
-				 sizeof(pow2_sizes)/sizeof(int), pow2_sizes, 0);
+				 ARRAY_SIZE(pow2_sizes), pow2_sizes, 0);
 }		
 
 /**
@@ -1769,12 +1781,14 @@ static int snd_pcm_lib_ioctl_reset(snd_pcm_substream_t *substream,
 				   void *arg)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
+	unsigned long flags;
+	snd_pcm_stream_lock_irqsave(substream, flags);
 	if (snd_pcm_running(substream) &&
-	    snd_pcm_update_hw_ptr(substream) >= 0) {
+	    snd_pcm_update_hw_ptr(substream) >= 0)
 		runtime->status->hw_ptr %= runtime->buffer_size;
-		return 0;
-	}
-	runtime->status->hw_ptr = 0;
+	else
+		runtime->status->hw_ptr = 0;
+	snd_pcm_stream_unlock_irqrestore(substream, flags);
 	return 0;
 }
 
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index ab70ba7b6..16a81240a 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -32,12 +32,10 @@
 static int preallocate_dma = 1;
 module_param(preallocate_dma, int, 0444);
 MODULE_PARM_DESC(preallocate_dma, "Preallocate DMA memory when the PCM devices are initialized.");
-MODULE_PARM_SYNTAX(preallocate_dma, SNDRV_BOOLEAN_TRUE_DESC);
 
 static int maximum_substreams = 4;
 module_param(maximum_substreams, int, 0444);
 MODULE_PARM_DESC(maximum_substreams, "Maximum substreams with preallocated DMA memory.");
-MODULE_PARM_SYNTAX(maximum_substreams, SNDRV_BOOLEAN_TRUE_DESC);
 
 const static size_t snd_minimum_buffer = 16384;
 
@@ -56,26 +54,21 @@ static int preallocate_pcm_pages(snd_pcm_substream_t *substream, size_t size)
 	snd_assert(size > 0, return -EINVAL);
 
 	/* already reserved? */
-	if (snd_dma_get_reserved(&substream->dma_device, dmab) > 0) {
+	if (snd_dma_get_reserved_buf(dmab, substream->dma_buf_id) > 0) {
 		if (dmab->bytes >= size)
 			return 0; /* yes */
-		/* no, reset the reserved block */
-		/* if we can find bigger pages below, this block will be
-		 * automatically removed in snd_dma_set_reserved().
-		 */
-		snd_dma_free_reserved(&substream->dma_device);
+		/* no, free the reserved block */
+		snd_dma_free_pages(dmab);
 		dmab->bytes = 0;
 	}
 
 	do {
-		if ((err = snd_dma_alloc_pages(&substream->dma_device, size, dmab)) < 0) {
+		if ((err = snd_dma_alloc_pages(dmab->dev.type, dmab->dev.dev,
+					       size, dmab)) < 0) {
 			if (err != -ENOMEM)
 				return err; /* fatal error */
-		} else {
-			/* remember this one */
-			snd_dma_set_reserved(&substream->dma_device, dmab);
+		} else
 			return 0;
-		}
 		size >>= 1;
 	} while (size >= snd_minimum_buffer);
 	dmab->bytes = 0; /* tell error */
@@ -89,7 +82,10 @@ static void snd_pcm_lib_preallocate_dma_free(snd_pcm_substream_t *substream)
 {
 	if (substream->dma_buffer.area == NULL)
 		return;
-	snd_dma_free_reserved(&substream->dma_device);
+	if (substream->dma_buf_id)
+		snd_dma_reserve_buf(&substream->dma_buffer, substream->dma_buf_id);
+	else
+		snd_dma_free_pages(&substream->dma_buffer);
 	substream->dma_buffer.area = NULL;
 }
 
@@ -108,7 +104,6 @@ int snd_pcm_lib_preallocate_free(snd_pcm_substream_t *substream)
 		snd_info_unregister(substream->proc_prealloc_entry);
 		substream->proc_prealloc_entry = NULL;
 	}
-	substream->dma_device.type = SNDRV_DMA_TYPE_UNKNOWN;
 	return 0;
 }
 
@@ -170,18 +165,20 @@ static void snd_pcm_lib_preallocate_proc_write(snd_info_entry_t *entry,
 		if (substream->dma_buffer.bytes == size)
 			return;
 		memset(&new_dmab, 0, sizeof(new_dmab));
+		new_dmab.dev = substream->dma_buffer.dev;
 		if (size > 0) {
-
-			if (snd_dma_alloc_pages(&substream->dma_device, size, &new_dmab) < 0) {
+			if (snd_dma_alloc_pages(substream->dma_buffer.dev.type,
+						substream->dma_buffer.dev.dev,
+						size, &new_dmab) < 0) {
 				buffer->error = -ENOMEM;
 				return;
 			}
 			substream->buffer_bytes_max = size;
-			snd_dma_free_reserved(&substream->dma_device);
 		} else {
 			substream->buffer_bytes_max = UINT_MAX;
 		}
-		snd_dma_set_reserved(&substream->dma_device, &new_dmab);
+		if (substream->dma_buffer.area)
+			snd_dma_free_pages(&substream->dma_buffer);
 		substream->dma_buffer = new_dmab;
 	} else {
 		buffer->error = -EINVAL;
@@ -196,7 +193,6 @@ static int snd_pcm_lib_preallocate_pages1(snd_pcm_substream_t *substream,
 {
 	snd_info_entry_t *entry;
 
-	memset(&substream->dma_buffer, 0, sizeof(substream->dma_buffer));
 	if (size > 0 && preallocate_dma && substream->number < maximum_substreams)
 		preallocate_pcm_pages(substream, size);
 
@@ -219,20 +215,6 @@ static int snd_pcm_lib_preallocate_pages1(snd_pcm_substream_t *substream,
 }
 
 
-/*
- * set up the unique pcm id
- */
-static inline void setup_pcm_id(snd_pcm_substream_t *subs)
-{
-	if (! subs->dma_device.id) {
-		subs->dma_device.id = subs->pcm->device << 16 |
-			subs->stream << 8 | (subs->number + 1);
-		if (subs->dma_device.type == SNDRV_DMA_TYPE_CONTINUOUS ||
-		    subs->dma_device.dev == NULL)
-			subs->dma_device.id |= (subs->pcm->card->number + 1) << 24;
-	}
-}
-
 /**
  * snd_pcm_lib_preallocate_pages - pre-allocation for the given DMA type
  * @substream: the pcm substream instance
@@ -241,7 +223,12 @@ static inline void setup_pcm_id(snd_pcm_substream_t *subs)
  * @size: the requested pre-allocation size in bytes
  * @max: the max. allowed pre-allocation size
  *
- * Do pre-allocation for the given DMA type.
+ * Do pre-allocation for the given DMA buffer type.
+ *
+ * When substream->dma_buf_id is set, the function tries to look for
+ * the reserved buffer, and the buffer is not freed but reserved at
+ * destruction time.  The dma_buf_id must be unique for all systems
+ * (in the same DMA buffer type) e.g. using snd_dma_pci_buf_id().
  *
  * Returns zero if successful, or a negative error code on failure.
  */
@@ -249,9 +236,8 @@ int snd_pcm_lib_preallocate_pages(snd_pcm_substream_t *substream,
 				  int type, struct device *data,
 				  size_t size, size_t max)
 {
-	substream->dma_device.type = type;
-	substream->dma_device.dev = data;
-	setup_pcm_id(substream);
+	substream->dma_buffer.dev.type = type;
+	substream->dma_buffer.dev.dev = data;
 	return snd_pcm_lib_preallocate_pages1(substream, size, max);
 }
 
@@ -314,31 +300,38 @@ struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned lon
 int snd_pcm_lib_malloc_pages(snd_pcm_substream_t *substream, size_t size)
 {
 	snd_pcm_runtime_t *runtime;
-	struct snd_dma_buffer dmab;
+	struct snd_dma_buffer *dmab = NULL;
 
-	snd_assert(substream->dma_device.type != SNDRV_DMA_TYPE_UNKNOWN, return -EINVAL);
+	snd_assert(substream->dma_buffer.dev.type != SNDRV_DMA_TYPE_UNKNOWN, return -EINVAL);
 	snd_assert(substream != NULL, return -EINVAL);
 	runtime = substream->runtime;
-	snd_assert(runtime != NULL, return -EINVAL);	
+	snd_assert(runtime != NULL, return -EINVAL);
 
-	if (runtime->dma_area != NULL) {
+	if (runtime->dma_buffer_p) {
 		/* perphaps, we might free the large DMA memory region
 		   to save some space here, but the actual solution
 		   costs us less time */
-		if (runtime->dma_bytes >= size)
+		if (runtime->dma_buffer_p->bytes >= size) {
+			runtime->dma_bytes = size;
 			return 0;	/* ok, do not change */
+		}
 		snd_pcm_lib_free_pages(substream);
 	}
 	if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) {
-		dmab = substream->dma_buffer; /* use the pre-allocated buffer */
+		dmab = &substream->dma_buffer; /* use the pre-allocated buffer */
 	} else {
-		memset(&dmab, 0, sizeof(dmab)); /* allocate a new buffer */
-		if (snd_dma_alloc_pages(&substream->dma_device, size, &dmab) < 0)
+		dmab = kcalloc(1, sizeof(*dmab), GFP_KERNEL);
+		if (! dmab)
+			return -ENOMEM;
+		dmab->dev = substream->dma_buffer.dev;
+		if (snd_dma_alloc_pages(substream->dma_buffer.dev.type,
+					substream->dma_buffer.dev.dev,
+					size, dmab) < 0) {
+			kfree(dmab);
 			return -ENOMEM;
+		}
 	}
-	runtime->dma_area = dmab.area;
-	runtime->dma_addr = dmab.addr;
-	runtime->dma_private = dmab.private_data;
+	snd_pcm_set_runtime_buffer(substream, dmab);
 	runtime->dma_bytes = size;
 	return 1;			/* area was changed */
 }
@@ -360,34 +353,11 @@ int snd_pcm_lib_free_pages(snd_pcm_substream_t *substream)
 	snd_assert(runtime != NULL, return -EINVAL);
 	if (runtime->dma_area == NULL)
 		return 0;
-	if (runtime->dma_area != substream->dma_buffer.area) {
+	if (runtime->dma_buffer_p != &substream->dma_buffer) {
 		/* it's a newly allocated buffer.  release it now. */
-		struct snd_dma_buffer dmab;
-		memset(&dmab, 0, sizeof(dmab));
-		dmab.area = runtime->dma_area;
-		dmab.addr = runtime->dma_addr;
-		dmab.bytes = runtime->dma_bytes;
-		dmab.private_data = runtime->dma_private;
-		snd_dma_free_pages(&substream->dma_device, &dmab);
+		snd_dma_free_pages(runtime->dma_buffer_p);
+		kfree(runtime->dma_buffer_p);
 	}
-	runtime->dma_area = NULL;
-	runtime->dma_addr = 0UL;
-	runtime->dma_bytes = 0;
-	runtime->dma_private = NULL;
+	snd_pcm_set_runtime_buffer(substream, NULL);
 	return 0;
 }
-
-#ifndef MODULE
-
-/* format is: snd-pcm=preallocate_dma,maximum_substreams */
-
-static int __init alsa_pcm_setup(char *str)
-{
-	(void)(get_option(&str,&preallocate_dma) == 2 &&
-	       get_option(&str,&maximum_substreams) == 2);
-	return 1;
-}
-
-__setup("snd-pcm=", alsa_pcm_setup);
-
-#endif /* ifndef MODULE */
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
index a35ed275d..794372b6d 100644
--- a/sound/core/pcm_misc.c
+++ b/sound/core/pcm_misc.c
@@ -23,12 +23,169 @@
 #include <linux/time.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
-#define bswap_16 swab16
-#define bswap_32 swab32
-#define bswap_64 swab64
 #define SND_PCM_FORMAT_UNKNOWN (-1)
-#define snd_enum_to_int(v) (v)
-#define snd_int_to_enum(v) (v)
+
+struct pcm_format_data {
+	char width;	/* bit width */
+	char phys;	/* physical bit width */
+	char le;	/* 0 = big-endian, 1 = little-endian, -1 = others */
+	char signd;	/* 0 = unsigned, 1 = signed, -1 = others */
+	unsigned char silence[8];	/* silence data to fill */
+};
+
+static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = {
+	[SNDRV_PCM_FORMAT_S8] = {
+		.width = 8, .phys = 8, .le = -1, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_U8] = {
+		.width = 8, .phys = 8, .le = -1, .signd = 0,
+		.silence = { 0x80 },
+	},
+	[SNDRV_PCM_FORMAT_S16_LE] = {
+		.width = 16, .phys = 16, .le = 1, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_S16_BE] = {
+		.width = 16, .phys = 16, .le = 0, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_U16_LE] = {
+		.width = 16, .phys = 16, .le = 1, .signd = 0,
+		.silence = { 0x00, 0x80 },
+	},
+	[SNDRV_PCM_FORMAT_U16_BE] = {
+		.width = 16, .phys = 16, .le = 0, .signd = 0,
+		.silence = { 0x80, 0x00 },
+	},
+	[SNDRV_PCM_FORMAT_S24_LE] = {
+		.width = 24, .phys = 32, .le = 1, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_S24_BE] = {
+		.width = 24, .phys = 32, .le = 0, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_U24_LE] = {
+		.width = 24, .phys = 32, .le = 1, .signd = 0,
+		.silence = { 0x00, 0x00, 0x80 },
+	},
+	[SNDRV_PCM_FORMAT_U24_BE] = {
+		.width = 24, .phys = 32, .le = 0, .signd = 0,
+		.silence = { 0x80, 0x00, 0x00 },
+	},
+	[SNDRV_PCM_FORMAT_S32_LE] = {
+		.width = 32, .phys = 32, .le = 1, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_S32_BE] = {
+		.width = 32, .phys = 32, .le = 0, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_U32_LE] = {
+		.width = 32, .phys = 32, .le = 1, .signd = 0,
+		.silence = { 0x00, 0x00, 0x00, 0x80 },
+	},
+	[SNDRV_PCM_FORMAT_U32_BE] = {
+		.width = 32, .phys = 32, .le = 0, .signd = 0,
+		.silence = { 0x80, 0x00, 0x00, 0x00 },
+	},
+	[SNDRV_PCM_FORMAT_FLOAT_LE] = {
+		.width = 32, .phys = 32, .le = 1, .signd = -1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_FLOAT_BE] = {
+		.width = 32, .phys = 32, .le = 0, .signd = -1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_FLOAT64_LE] = {
+		.width = 64, .phys = 64, .le = 1, .signd = -1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_FLOAT64_BE] = {
+		.width = 64, .phys = 64, .le = 0, .signd = -1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE] = {
+		.width = 32, .phys = 32, .le = 1, .signd = -1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE] = {
+		.width = 32, .phys = 32, .le = 0, .signd = -1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_MU_LAW] = {
+		.width = 8, .phys = 8, .le = -1, .signd = -1,
+		.silence = { 0x7f },
+	},
+	[SNDRV_PCM_FORMAT_A_LAW] = {
+		.width = 8, .phys = 8, .le = -1, .signd = -1,
+		.silence = { 0x55 },
+	},
+	[SNDRV_PCM_FORMAT_IMA_ADPCM] = {
+		.width = 4, .phys = 4, .le = -1, .signd = -1,
+		.silence = {},
+	},
+	/* FIXME: the following three formats are not defined properly yet */
+	[SNDRV_PCM_FORMAT_MPEG] = {
+		.le = -1, .signd = -1,
+	},
+	[SNDRV_PCM_FORMAT_GSM] = {
+		.le = -1, .signd = -1,
+	},
+	[SNDRV_PCM_FORMAT_SPECIAL] = {
+		.le = -1, .signd = -1,
+	},
+	[SNDRV_PCM_FORMAT_S24_3LE] = {
+		.width = 24, .phys = 24, .le = 1, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_S24_3BE] = {
+		.width = 24, .phys = 24, .le = 0, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_U24_3LE] = {
+		.width = 24, .phys = 24, .le = 1, .signd = 0,
+		.silence = { 0x00, 0x00, 0x80 },
+	},
+	[SNDRV_PCM_FORMAT_U24_3BE] = {
+		.width = 24, .phys = 24, .le = 0, .signd = 0,
+		.silence = { 0x80, 0x00, 0x00 },
+	},
+	[SNDRV_PCM_FORMAT_S20_3LE] = {
+		.width = 20, .phys = 24, .le = 1, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_S20_3BE] = {
+		.width = 20, .phys = 24, .le = 0, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_U20_3LE] = {
+		.width = 20, .phys = 24, .le = 1, .signd = 0,
+		.silence = { 0x00, 0x00, 0x08 },
+	},
+	[SNDRV_PCM_FORMAT_U20_3BE] = {
+		.width = 20, .phys = 24, .le = 0, .signd = 0,
+		.silence = { 0x08, 0x00, 0x00 },
+	},
+	[SNDRV_PCM_FORMAT_S18_3LE] = {
+		.width = 18, .phys = 24, .le = 1, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_S18_3BE] = {
+		.width = 18, .phys = 24, .le = 0, .signd = 1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_U18_3LE] = {
+		.width = 18, .phys = 24, .le = 1, .signd = 0,
+		.silence = { 0x00, 0x00, 0x02 },
+	},
+	[SNDRV_PCM_FORMAT_U18_3BE] = {
+		.width = 18, .phys = 24, .le = 0, .signd = 0,
+		.silence = { 0x02, 0x00, 0x00 },
+	},
+};
+
 
 /**
  * snd_pcm_format_signed - Check the PCM format is signed linear
@@ -39,38 +196,12 @@
  */
 int snd_pcm_format_signed(snd_pcm_format_t format)
 {
-	switch (snd_enum_to_int(format)) {
-	case SNDRV_PCM_FORMAT_S8:
-	case SNDRV_PCM_FORMAT_S16_LE:
-	case SNDRV_PCM_FORMAT_S16_BE:
-	case SNDRV_PCM_FORMAT_S24_LE:
-	case SNDRV_PCM_FORMAT_S24_BE:
-	case SNDRV_PCM_FORMAT_S32_LE:
-	case SNDRV_PCM_FORMAT_S32_BE:
-	case SNDRV_PCM_FORMAT_S24_3LE:
-	case SNDRV_PCM_FORMAT_S24_3BE:
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S20_3BE:
-	case SNDRV_PCM_FORMAT_S18_3LE:
-	case SNDRV_PCM_FORMAT_S18_3BE:
-		return 1;
-	case SNDRV_PCM_FORMAT_U8:
-	case SNDRV_PCM_FORMAT_U16_LE:
-	case SNDRV_PCM_FORMAT_U16_BE:
-	case SNDRV_PCM_FORMAT_U24_LE:
-	case SNDRV_PCM_FORMAT_U24_BE:
-	case SNDRV_PCM_FORMAT_U32_LE:
-	case SNDRV_PCM_FORMAT_U32_BE:
-	case SNDRV_PCM_FORMAT_U24_3LE:
-	case SNDRV_PCM_FORMAT_U24_3BE:
-	case SNDRV_PCM_FORMAT_U20_3LE:
-	case SNDRV_PCM_FORMAT_U20_3BE:
-	case SNDRV_PCM_FORMAT_U18_3LE:
-	case SNDRV_PCM_FORMAT_U18_3BE:
-		return 0;
-	default:
+	int val;
+	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
 		return -EINVAL;
-	}
+	if ((val = pcm_formats[format].signd) < 0)
+		return -EINVAL;
+	return val;
 }
 
 /**
@@ -110,42 +241,12 @@ int snd_pcm_format_linear(snd_pcm_format_t format)
  */
 int snd_pcm_format_little_endian(snd_pcm_format_t format)
 {
-	switch (snd_enum_to_int(format)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
-	case SNDRV_PCM_FORMAT_U16_LE:
-	case SNDRV_PCM_FORMAT_S24_LE:
-	case SNDRV_PCM_FORMAT_U24_LE:
-	case SNDRV_PCM_FORMAT_S32_LE:
-	case SNDRV_PCM_FORMAT_U32_LE:
-	case SNDRV_PCM_FORMAT_FLOAT_LE:
-	case SNDRV_PCM_FORMAT_FLOAT64_LE:
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
-	case SNDRV_PCM_FORMAT_S24_3LE:
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S18_3LE:
-	case SNDRV_PCM_FORMAT_U24_3LE:
-	case SNDRV_PCM_FORMAT_U20_3LE:
-	case SNDRV_PCM_FORMAT_U18_3LE:
-		return 1;
-	case SNDRV_PCM_FORMAT_S16_BE:
-	case SNDRV_PCM_FORMAT_U16_BE:
-	case SNDRV_PCM_FORMAT_S24_BE:
-	case SNDRV_PCM_FORMAT_U24_BE:
-	case SNDRV_PCM_FORMAT_S32_BE:
-	case SNDRV_PCM_FORMAT_U32_BE:
-	case SNDRV_PCM_FORMAT_FLOAT_BE:
-	case SNDRV_PCM_FORMAT_FLOAT64_BE:
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
-	case SNDRV_PCM_FORMAT_S24_3BE:
-	case SNDRV_PCM_FORMAT_S20_3BE:
-	case SNDRV_PCM_FORMAT_S18_3BE:
-	case SNDRV_PCM_FORMAT_U24_3BE:
-	case SNDRV_PCM_FORMAT_U20_3BE:
-	case SNDRV_PCM_FORMAT_U18_3BE:
-		return 0;
-	default:
+	int val;
+	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
 		return -EINVAL;
-	}
+	if ((val = pcm_formats[format].le) < 0)
+		return -EINVAL;
+	return val;
 }
 
 /**
@@ -190,55 +291,12 @@ int snd_pcm_format_cpu_endian(snd_pcm_format_t format)
  */
 int snd_pcm_format_width(snd_pcm_format_t format)
 {
-	switch (snd_enum_to_int(format)) {
-	case SNDRV_PCM_FORMAT_S8:
-	case SNDRV_PCM_FORMAT_U8:
-		return 8;
-	case SNDRV_PCM_FORMAT_S16_LE:
-	case SNDRV_PCM_FORMAT_S16_BE:
-	case SNDRV_PCM_FORMAT_U16_LE:
-	case SNDRV_PCM_FORMAT_U16_BE:
-		return 16;
-	case SNDRV_PCM_FORMAT_S18_3LE:
-	case SNDRV_PCM_FORMAT_S18_3BE:
-	case SNDRV_PCM_FORMAT_U18_3LE:
-	case SNDRV_PCM_FORMAT_U18_3BE:
-		return 18;
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S20_3BE:
-	case SNDRV_PCM_FORMAT_U20_3LE:
-	case SNDRV_PCM_FORMAT_U20_3BE:
-		return 20;
-	case SNDRV_PCM_FORMAT_S24_LE:
-	case SNDRV_PCM_FORMAT_S24_BE:
-	case SNDRV_PCM_FORMAT_U24_LE:
-	case SNDRV_PCM_FORMAT_U24_BE:
-	case SNDRV_PCM_FORMAT_S24_3LE:
-	case SNDRV_PCM_FORMAT_S24_3BE:
-	case SNDRV_PCM_FORMAT_U24_3LE:
-	case SNDRV_PCM_FORMAT_U24_3BE:
-		return 24;
-	case SNDRV_PCM_FORMAT_S32_LE:
-	case SNDRV_PCM_FORMAT_S32_BE:
-	case SNDRV_PCM_FORMAT_U32_LE:
-	case SNDRV_PCM_FORMAT_U32_BE:
-	case SNDRV_PCM_FORMAT_FLOAT_LE:
-	case SNDRV_PCM_FORMAT_FLOAT_BE:
-		return 32;
-	case SNDRV_PCM_FORMAT_FLOAT64_LE:
-	case SNDRV_PCM_FORMAT_FLOAT64_BE:
-		return 64;
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
-		return 32;
-	case SNDRV_PCM_FORMAT_MU_LAW:
-	case SNDRV_PCM_FORMAT_A_LAW:
-		return 8;
-	case SNDRV_PCM_FORMAT_IMA_ADPCM:
-		return 4;
-	default:
+	int val;
+	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
 		return -EINVAL;
-	}
+	if ((val = pcm_formats[format].width) == 0)
+		return -EINVAL;
+	return val;
 }
 
 /**
@@ -250,52 +308,12 @@ int snd_pcm_format_width(snd_pcm_format_t format)
  */
 int snd_pcm_format_physical_width(snd_pcm_format_t format)
 {
-	switch (snd_enum_to_int(format)) {
-	case SNDRV_PCM_FORMAT_S8:
-	case SNDRV_PCM_FORMAT_U8:
-		return 8;
-	case SNDRV_PCM_FORMAT_S16_LE:
-	case SNDRV_PCM_FORMAT_S16_BE:
-	case SNDRV_PCM_FORMAT_U16_LE:
-	case SNDRV_PCM_FORMAT_U16_BE:
-		return 16;
-	case SNDRV_PCM_FORMAT_S18_3LE:
-	case SNDRV_PCM_FORMAT_S18_3BE:
-	case SNDRV_PCM_FORMAT_U18_3LE:
-	case SNDRV_PCM_FORMAT_U18_3BE:
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S20_3BE:
-	case SNDRV_PCM_FORMAT_U20_3LE:
-	case SNDRV_PCM_FORMAT_U20_3BE:
-	case SNDRV_PCM_FORMAT_S24_3LE:
-	case SNDRV_PCM_FORMAT_S24_3BE:
-	case SNDRV_PCM_FORMAT_U24_3LE:
-	case SNDRV_PCM_FORMAT_U24_3BE:
-		return 24;
-	case SNDRV_PCM_FORMAT_S24_LE:
-	case SNDRV_PCM_FORMAT_S24_BE:
-	case SNDRV_PCM_FORMAT_U24_LE:
-	case SNDRV_PCM_FORMAT_U24_BE:
-	case SNDRV_PCM_FORMAT_S32_LE:
-	case SNDRV_PCM_FORMAT_S32_BE:
-	case SNDRV_PCM_FORMAT_U32_LE:
-	case SNDRV_PCM_FORMAT_U32_BE:
-	case SNDRV_PCM_FORMAT_FLOAT_LE:
-	case SNDRV_PCM_FORMAT_FLOAT_BE:
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
-		return 32;
-	case SNDRV_PCM_FORMAT_FLOAT64_LE:
-	case SNDRV_PCM_FORMAT_FLOAT64_BE:
-		return 64;
-	case SNDRV_PCM_FORMAT_MU_LAW:
-	case SNDRV_PCM_FORMAT_A_LAW:
-		return 8;
-	case SNDRV_PCM_FORMAT_IMA_ADPCM:
-		return 4;
-	default:
+	int val;
+	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
 		return -EINVAL;
-	}
+	if ((val = pcm_formats[format].phys) == 0)
+		return -EINVAL;
+	return val;
 }
 
 /**
@@ -307,216 +325,25 @@ int snd_pcm_format_physical_width(snd_pcm_format_t format)
  */
 ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples)
 {
-	switch (snd_enum_to_int(format)) {
-	case SNDRV_PCM_FORMAT_S8:
-	case SNDRV_PCM_FORMAT_U8:
-		return samples;
-	case SNDRV_PCM_FORMAT_S16_LE:
-	case SNDRV_PCM_FORMAT_S16_BE:
-	case SNDRV_PCM_FORMAT_U16_LE:
-	case SNDRV_PCM_FORMAT_U16_BE:
-		return samples * 2;
-	case SNDRV_PCM_FORMAT_S18_3LE:
-	case SNDRV_PCM_FORMAT_S18_3BE:
-	case SNDRV_PCM_FORMAT_U18_3LE:
-	case SNDRV_PCM_FORMAT_U18_3BE:
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S20_3BE:
-	case SNDRV_PCM_FORMAT_U20_3LE:
-	case SNDRV_PCM_FORMAT_U20_3BE:
-	case SNDRV_PCM_FORMAT_S24_3LE:
-	case SNDRV_PCM_FORMAT_S24_3BE:
-	case SNDRV_PCM_FORMAT_U24_3LE:
-	case SNDRV_PCM_FORMAT_U24_3BE:
-		return samples * 3;
-	case SNDRV_PCM_FORMAT_S24_LE:
-	case SNDRV_PCM_FORMAT_S24_BE:
-	case SNDRV_PCM_FORMAT_U24_LE:
-	case SNDRV_PCM_FORMAT_U24_BE:
-	case SNDRV_PCM_FORMAT_S32_LE:
-	case SNDRV_PCM_FORMAT_S32_BE:
-	case SNDRV_PCM_FORMAT_U32_LE:
-	case SNDRV_PCM_FORMAT_U32_BE:
-	case SNDRV_PCM_FORMAT_FLOAT_LE:
-	case SNDRV_PCM_FORMAT_FLOAT_BE:
-		return samples * 4;
-	case SNDRV_PCM_FORMAT_FLOAT64_LE:
-	case SNDRV_PCM_FORMAT_FLOAT64_BE:
-		return samples * 8;
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
-		return samples * 4;
-	case SNDRV_PCM_FORMAT_MU_LAW:
-	case SNDRV_PCM_FORMAT_A_LAW:
-		return samples;
-	case SNDRV_PCM_FORMAT_IMA_ADPCM:
-		if (samples & 1)
-			return -EINVAL;
-		return samples / 2;
-	default:
+	int phys_width = snd_pcm_format_physical_width(format);
+	if (phys_width < 0)
 		return -EINVAL;
-	}
+	return samples * phys_width / 8;
 }
 
 /**
- * snd_pcm_format_silence_64 - return the silent data in 64bit integer
+ * snd_pcm_format_silence_64 - return the silent data in 8 bytes array
  * @format: the format to check
  *
- * Returns the silent data in 64bit integer for the given format.
+ * Returns the format pattern to fill or NULL if error.
  */
-u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format)
+const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format)
 {
-	switch (snd_enum_to_int(format)) {
-	case SNDRV_PCM_FORMAT_S8:
-	case SNDRV_PCM_FORMAT_S16_LE:
-	case SNDRV_PCM_FORMAT_S16_BE:
-	case SNDRV_PCM_FORMAT_S24_LE:
-	case SNDRV_PCM_FORMAT_S24_BE:
-	case SNDRV_PCM_FORMAT_S32_LE:
-	case SNDRV_PCM_FORMAT_S32_BE:
-	case SNDRV_PCM_FORMAT_S24_3LE:
-	case SNDRV_PCM_FORMAT_S24_3BE:
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S20_3BE:
-	case SNDRV_PCM_FORMAT_S18_3LE:
-	case SNDRV_PCM_FORMAT_S18_3BE:
-		return 0;
-	case SNDRV_PCM_FORMAT_U8:
-		return 0x8080808080808080ULL;
-#ifdef SNDRV_LITTLE_ENDIAN
-	case SNDRV_PCM_FORMAT_U16_LE:
-		return 0x8000800080008000ULL;
-	case SNDRV_PCM_FORMAT_U24_LE:
-		return 0x0080000000800000ULL;
-	case SNDRV_PCM_FORMAT_U32_LE:
-		return 0x8000000080000000ULL;
-	case SNDRV_PCM_FORMAT_U16_BE:
-		return 0x0080008000800080ULL;
-	case SNDRV_PCM_FORMAT_U24_BE:
-		return 0x0000800000008000ULL;
-	case SNDRV_PCM_FORMAT_U32_BE:
-		return 0x0000008000000080ULL;
-	case SNDRV_PCM_FORMAT_U24_3LE:
-		return 0x0000800000800000ULL;
-	case SNDRV_PCM_FORMAT_U24_3BE:
-		return 0x0080000080000080ULL;
-	case SNDRV_PCM_FORMAT_U20_3LE:
-		return 0x0000080000080000ULL;
-	case SNDRV_PCM_FORMAT_U20_3BE:
-		return 0x0008000008000008ULL;
-	case SNDRV_PCM_FORMAT_U18_3LE:
-		return 0x0000020000020000ULL;
-	case SNDRV_PCM_FORMAT_U18_3BE:
-		return 0x0002000002000002ULL;
-#else
-	case SNDRV_PCM_FORMAT_U16_LE:
-		return 0x0080008000800080ULL;
-	case SNDRV_PCM_FORMAT_U24_LE:
-		return 0x0000800000008000ULL;
-	case SNDRV_PCM_FORMAT_U32_LE:
-		return 0x0000008000000080ULL;
-	case SNDRV_PCM_FORMAT_U16_BE:
-		return 0x8000800080008000ULL;
-	case SNDRV_PCM_FORMAT_U24_BE:
-		return 0x0080000000800000ULL;
-	case SNDRV_PCM_FORMAT_U32_BE:
-		return 0x8000000080000000ULL;
-	case SNDRV_PCM_FORMAT_U24_3LE:
-		return 0x0080000080000080ULL;
-	case SNDRV_PCM_FORMAT_U24_3BE:
-		return 0x0000800000800000ULL;
-	case SNDRV_PCM_FORMAT_U20_3LE:
-		return 0x0008000008000008ULL;
-	case SNDRV_PCM_FORMAT_U20_3BE:
-		return 0x0000080000080000ULL;
-	case SNDRV_PCM_FORMAT_U18_3LE:
-		return 0x0002000002000002ULL;
-	case SNDRV_PCM_FORMAT_U18_3BE:
-		return 0x0000020000020000ULL;
-#endif
-	case SNDRV_PCM_FORMAT_FLOAT_LE:
-	{
-		union {
-			float f;
-			u_int32_t i;
-		} u;
-		u.f = 0.0;
-#ifdef SNDRV_LITTLE_ENDIAN
-		return u.i;
-#else
-		return bswap_32(u.i);
-#endif
-	}
-	case SNDRV_PCM_FORMAT_FLOAT64_LE:
-	{
-		union {
-			double f;
-			u_int64_t i;
-		} u;
-		u.f = 0.0;
-#ifdef SNDRV_LITTLE_ENDIAN
-		return u.i;
-#else
-		return bswap_64(u.i);
-#endif
-	}
-	case SNDRV_PCM_FORMAT_FLOAT_BE:		
-	{
-		union {
-			float f;
-			u_int32_t i;
-		} u;
-		u.f = 0.0;
-#ifdef SNDRV_LITTLE_ENDIAN
-		return bswap_32(u.i);
-#else
-		return u.i;
-#endif
-	}
-	case SNDRV_PCM_FORMAT_FLOAT64_BE:
-	{
-		union {
-			double f;
-			u_int64_t i;
-		} u;
-		u.f = 0.0;
-#ifdef SNDRV_LITTLE_ENDIAN
-		return bswap_64(u.i);
-#else
-		return u.i;
-#endif
-	}
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
-	case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
-		return 0;	
-	case SNDRV_PCM_FORMAT_MU_LAW:
-		return 0x7f7f7f7f7f7f7f7fULL;
-	case SNDRV_PCM_FORMAT_A_LAW:
-		return 0x5555555555555555ULL;
-	case SNDRV_PCM_FORMAT_IMA_ADPCM:	/* special case */
-	case SNDRV_PCM_FORMAT_MPEG:
-	case SNDRV_PCM_FORMAT_GSM:
-	case SNDRV_PCM_FORMAT_SPECIAL:
-		return 0;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-u_int32_t snd_pcm_format_silence_32(snd_pcm_format_t format)
-{
-	return (u_int32_t)snd_pcm_format_silence_64(format);
-}
-
-u_int16_t snd_pcm_format_silence_16(snd_pcm_format_t format)
-{
-	return (u_int16_t)snd_pcm_format_silence_64(format);
-}
-
-u_int8_t snd_pcm_format_silence(snd_pcm_format_t format)
-{
-	return (u_int8_t)snd_pcm_format_silence_64(format);
+	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
+		return NULL;
+	if (! pcm_formats[format].phys)
+		return NULL;
+	return pcm_formats[format].silence;
 }
 
 /**
@@ -531,99 +358,73 @@ u_int8_t snd_pcm_format_silence(snd_pcm_format_t format)
  */
 int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int samples)
 {
+	int width;
+	unsigned char *dst, *pat;
+
+	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
+		return -EINVAL;
 	if (samples == 0)
 		return 0;
-	switch (snd_pcm_format_width(format)) {
-	case 4: {
-		u_int8_t silence = snd_pcm_format_silence_64(format);
-		unsigned int samples1;
-		if (samples % 2 != 0)
-			return -EINVAL;
-		samples1 = samples / 2;
-		memset(data, silence, samples1);
-		break;
+	width = pcm_formats[format].phys; /* physical width */
+	pat = pcm_formats[format].silence;
+	if (! width)
+		return -EINVAL;
+	/* signed or 1 byte data */
+	if (pcm_formats[format].signd == 1 || width <= 8) {
+		unsigned int bytes = samples * width / 8;
+		memset(data, *pat, bytes);
+		return 0;
 	}
-	case 8: {
-		u_int8_t silence = snd_pcm_format_silence_64(format);
-		memset(data, silence, samples);
-		break;
+	/* non-zero samples, fill using a loop */
+	width /= 8;
+	dst = data;
+#if 0
+	while (samples--) {
+		memcpy(dst, pat, width);
+		dst += width;
 	}
-	case 16: {
-		u_int16_t silence = snd_pcm_format_silence_64(format);
-		if (! silence)
-			memset(data, 0, samples * 2);
-		else {
-			u_int16_t *data16 = data;
-			while (samples-- > 0)
-				*data16++ = silence;
+#else
+	/* a bit optimization for constant width */
+	switch (width) {
+	case 2:
+		while (samples--) {
+			memcpy(dst, pat, 2);
+			dst += 2;
 		}
 		break;
-	}
-	case 24: {
-		u_int32_t silence = snd_pcm_format_silence_64(format);
-		if (! silence)
-			memset(data, 0, samples * 3);
-		else {
-			while (samples-- > 0) {
-				u_int8_t *data8 = data;
-#ifdef SNDRV_LITTLE_ENDIAN
-				*data8++ = silence >> 0;
-				*data8++ = silence >> 8;
-				*data8++ = silence >> 16;
-#else
-				*data8++ = silence >> 16;
-				*data8++ = silence >> 8;
-				*data8++ = silence >> 0;
-#endif
-			}
+	case 3:
+		while (samples--) {
+			memcpy(dst, pat, 3);
+			dst += 3;
 		}
 		break;
-	}
-	case 32: {
-		u_int32_t silence = snd_pcm_format_silence_64(format);
-		if (! silence)
-			memset(data, 0, samples * 4);
-		else {
-			u_int32_t *data32 = data;
-			while (samples-- > 0)
-				*data32++ = silence;
+	case 4:
+		while (samples--) {
+			memcpy(dst, pat, 4);
+			dst += 4;
 		}
 		break;
-	}
-	case 64: {
-		u_int64_t silence = snd_pcm_format_silence_64(format);
-		if (! silence)
-			memset(data, 0, samples * 8);
-		else {
-			u_int64_t *data64 = data;
-			while (samples-- > 0)
-				*data64++ = silence;
+	case 8:
+		while (samples--) {
+			memcpy(dst, pat, 8);
+			dst += 8;
 		}
 		break;
 	}
-	default:
-		return -EINVAL;
-	}
+#endif
 	return 0;
 }
 
-static int linear_formats[4*2*2] = {
-	SNDRV_PCM_FORMAT_S8,
-	SNDRV_PCM_FORMAT_S8,
-	SNDRV_PCM_FORMAT_U8,
-	SNDRV_PCM_FORMAT_U8,
-	SNDRV_PCM_FORMAT_S16_LE,
-	SNDRV_PCM_FORMAT_S16_BE,
-	SNDRV_PCM_FORMAT_U16_LE,
-	SNDRV_PCM_FORMAT_U16_BE,
-	SNDRV_PCM_FORMAT_S24_LE,
-	SNDRV_PCM_FORMAT_S24_BE,
-	SNDRV_PCM_FORMAT_U24_LE,
-	SNDRV_PCM_FORMAT_U24_BE,
-	SNDRV_PCM_FORMAT_S32_LE,
-	SNDRV_PCM_FORMAT_S32_BE,
-	SNDRV_PCM_FORMAT_U32_LE,
-	SNDRV_PCM_FORMAT_U32_BE
+/* [width][unsigned][bigendian] */
+static int linear_formats[4][2][2] = {
+	{{ SNDRV_PCM_FORMAT_S8, SNDRV_PCM_FORMAT_S8},
+	 { SNDRV_PCM_FORMAT_U8, SNDRV_PCM_FORMAT_U8}},
+	{{SNDRV_PCM_FORMAT_S16_LE, SNDRV_PCM_FORMAT_S16_BE},
+	 {SNDRV_PCM_FORMAT_U16_LE, SNDRV_PCM_FORMAT_U16_BE}},
+	{{SNDRV_PCM_FORMAT_S24_LE, SNDRV_PCM_FORMAT_S24_BE},
+	 {SNDRV_PCM_FORMAT_U24_LE, SNDRV_PCM_FORMAT_U24_BE}},
+	{{SNDRV_PCM_FORMAT_S32_LE, SNDRV_PCM_FORMAT_S32_BE},
+	 {SNDRV_PCM_FORMAT_U32_LE, SNDRV_PCM_FORMAT_U32_BE}}
 };
 
 /**
@@ -636,23 +437,12 @@ static int linear_formats[4*2*2] = {
  */
 snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian)
 {
-	switch (width) {
-	case 8:
-		width = 0;
-		break;
-	case 16:
-		width = 1;
-		break;
-	case 24:
-		width = 2;
-		break;
-	case 32:
-		width = 3;
-		break;
-	default:
+	if (width & 7)
 		return SND_PCM_FORMAT_UNKNOWN;
-	}
-	return snd_int_to_enum(((int(*)[2][2])linear_formats)[width][!!unsignd][!!big_endian]);
+	width = (width / 8) - 1;
+	if (width < 0 || width >= 4)
+		return SND_PCM_FORMAT_UNKNOWN;
+	return linear_formats[width][!!unsignd][!!big_endian];
 }
 
 /**
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 6d5271f3f..b35253508 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -21,6 +21,7 @@
 
 #include <sound/driver.h>
 #include <linux/mm.h>
+#include <linux/smp_lock.h>
 #include <linux/file.h>
 #include <linux/slab.h>
 #include <linux/time.h>
@@ -32,6 +33,7 @@
 #include <sound/pcm_params.h>
 #include <sound/timer.h>
 #include <sound/minors.h>
+#include <asm/io.h>
 
 /*
  *  Compatibility
@@ -64,6 +66,7 @@ static int snd_pcm_hw_params_old_user(snd_pcm_substream_t * substream, struct sn
  */
 
 rwlock_t snd_pcm_link_rwlock = RW_LOCK_UNLOCKED;
+static DECLARE_RWSEM(snd_pcm_link_rwsem);
 
 
 static inline mm_segment_t snd_enter_user(void)
@@ -304,13 +307,25 @@ int snd_pcm_hw_refine(snd_pcm_substream_t *substream,
 
 static int snd_pcm_hw_refine_user(snd_pcm_substream_t * substream, snd_pcm_hw_params_t __user * _params)
 {
-	snd_pcm_hw_params_t params;
+	snd_pcm_hw_params_t *params;
 	int err;
-	if (copy_from_user(&params, _params, sizeof(params)))
-		return -EFAULT;
-	err = snd_pcm_hw_refine(substream, &params);
-	if (copy_to_user(_params, &params, sizeof(params)))
-		return -EFAULT;
+
+	params = kmalloc(sizeof(*params), GFP_KERNEL);
+	if (!params) {
+		err = -ENOMEM;
+		goto out;
+	}
+	if (copy_from_user(params, _params, sizeof(*params))) {
+		err = -EFAULT;
+		goto out;
+	}
+	err = snd_pcm_hw_refine(substream, params);
+	if (copy_to_user(_params, params, sizeof(*params))) {
+		if (!err)
+			err = -EFAULT;
+	}
+out:
+	kfree(params);
 	return err;
 }
 
@@ -325,14 +340,17 @@ static int snd_pcm_hw_params(snd_pcm_substream_t *substream,
 	snd_assert(substream != NULL, return -ENXIO);
 	runtime = substream->runtime;
 	snd_assert(runtime != NULL, return -ENXIO);
+	snd_pcm_stream_lock_irq(substream);
 	switch (runtime->status->state) {
 	case SNDRV_PCM_STATE_OPEN:
 	case SNDRV_PCM_STATE_SETUP:
 	case SNDRV_PCM_STATE_PREPARED:
 		break;
 	default:
+		snd_pcm_stream_unlock_irq(substream);
 		return -EBADFD;
 	}
+	snd_pcm_stream_unlock_irq(substream);
 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
 	if (!substream->oss.oss)
 #endif
@@ -408,13 +426,25 @@ static int snd_pcm_hw_params(snd_pcm_substream_t *substream,
 
 static int snd_pcm_hw_params_user(snd_pcm_substream_t * substream, snd_pcm_hw_params_t __user * _params)
 {
-	snd_pcm_hw_params_t params;
+	snd_pcm_hw_params_t *params;
 	int err;
-	if (copy_from_user(&params, _params, sizeof(params)))
-		return -EFAULT;
-	err = snd_pcm_hw_params(substream, &params);
-	if (copy_to_user(_params, &params, sizeof(params)))
-		return -EFAULT;
+
+	params = kmalloc(sizeof(*params), GFP_KERNEL);
+	if (!params) {
+		err = -ENOMEM;
+		goto out;
+	}
+	if (copy_from_user(params, _params, sizeof(*params))) {
+		err = -EFAULT;
+		goto out;
+	}
+	err = snd_pcm_hw_params(substream, params);
+	if (copy_to_user(_params, params, sizeof(*params))) {
+		if (!err)
+			err = -EFAULT;
+	}
+out:
+	kfree(params);
 	return err;
 }
 
@@ -426,13 +456,16 @@ static int snd_pcm_hw_free(snd_pcm_substream_t * substream)
 	snd_assert(substream != NULL, return -ENXIO);
 	runtime = substream->runtime;
 	snd_assert(runtime != NULL, return -ENXIO);
+	snd_pcm_stream_lock_irq(substream);
 	switch (runtime->status->state) {
 	case SNDRV_PCM_STATE_SETUP:
 	case SNDRV_PCM_STATE_PREPARED:
 		break;
 	default:
+		snd_pcm_stream_unlock_irq(substream);
 		return -EBADFD;
 	}
+	snd_pcm_stream_unlock_irq(substream);
 	if (atomic_read(&runtime->mmap_count))
 		return -EBADFD;
 	if (substream->ops->hw_free == NULL) {
@@ -447,11 +480,16 @@ static int snd_pcm_hw_free(snd_pcm_substream_t * substream)
 static int snd_pcm_sw_params(snd_pcm_substream_t * substream, snd_pcm_sw_params_t *params)
 {
 	snd_pcm_runtime_t *runtime;
+
 	snd_assert(substream != NULL, return -ENXIO);
 	runtime = substream->runtime;
 	snd_assert(runtime != NULL, return -ENXIO);
-	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+	snd_pcm_stream_lock_irq(substream);
+	if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
+		snd_pcm_stream_unlock_irq(substream);
 		return -EBADFD;
+	}
+	snd_pcm_stream_unlock_irq(substream);
 
 	if (params->tstamp_mode > SNDRV_PCM_TSTAMP_LAST)
 		return -EINVAL;
@@ -579,8 +617,12 @@ static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel
 		return -EFAULT;
 	channel = info.channel;
 	runtime = substream->runtime;
-	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+	snd_pcm_stream_lock_irq(substream);
+	if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
+		snd_pcm_stream_unlock_irq(substream);
 		return -EBADFD;
+	}
+	snd_pcm_stream_unlock_irq(substream);
 	if (channel >= runtime->channels)
 		return -EINVAL;
 	memset(&info, 0, sizeof(info));
@@ -620,7 +662,7 @@ struct action_ops {
  */
 static int snd_pcm_action_group(struct action_ops *ops,
 				snd_pcm_substream_t *substream,
-				int state, int atomic_only)
+				int state, int do_lock)
 {
 	struct list_head *pos;
 	snd_pcm_substream_t *s = NULL;
@@ -628,9 +670,7 @@ static int snd_pcm_action_group(struct action_ops *ops,
 
 	snd_pcm_group_for_each(pos, substream) {
 		s = snd_pcm_group_substream_entry(pos);
-		if (atomic_only && (s->pcm->info_flags & SNDRV_PCM_INFO_NONATOMIC_OPS))
-			continue;
-		if (s != substream)
+		if (do_lock && s != substream)
 			spin_lock(&s->self_group.lock);
 		res = ops->pre_action(s, state);
 		if (res < 0)
@@ -639,8 +679,6 @@ static int snd_pcm_action_group(struct action_ops *ops,
 	if (res >= 0) {
 		snd_pcm_group_for_each(pos, substream) {
 			s = snd_pcm_group_substream_entry(pos);
-			if (atomic_only && (s->pcm->info_flags & SNDRV_PCM_INFO_NONATOMIC_OPS))
-				continue;
 			err = ops->do_action(s, state);
 			if (err < 0) {
 				if (res == 0)
@@ -648,17 +686,15 @@ static int snd_pcm_action_group(struct action_ops *ops,
 			} else {
 				ops->post_action(s, state);
 			}
-			if (s != substream)
+			if (do_lock && s != substream)
 				spin_unlock(&s->self_group.lock);
 		}
-	} else {
+	} else if (do_lock) {
 		snd_pcm_substream_t *s1;
 		/* unlock all streams */
 		snd_pcm_group_for_each(pos, substream) {
 			s1 = snd_pcm_group_substream_entry(pos);
-			if (atomic_only && (s1->pcm->info_flags & SNDRV_PCM_INFO_NONATOMIC_OPS))
-				;
-			else if (s1 != substream)
+			if (s1 != substream)
 				spin_unlock(&s1->self_group.lock);
 			if (s1 == s)	/* end */
 				break;
@@ -688,8 +724,6 @@ static int snd_pcm_action_single(struct action_ops *ops,
 
 /*
  *  Note: call with stream lock
- *
- * NB2: this won't handle the non-atomic callbacks
  */
 static int snd_pcm_action(struct action_ops *ops,
 			  snd_pcm_substream_t *substream,
@@ -703,7 +737,7 @@ static int snd_pcm_action(struct action_ops *ops,
 			spin_lock(&substream->group->lock);
 			spin_lock(&substream->self_group.lock);
 		}
-		res = snd_pcm_action_group(ops, substream, state, 0);
+		res = snd_pcm_action_group(ops, substream, state, 1);
 		spin_unlock(&substream->group->lock);
 	} else {
 		res = snd_pcm_action_single(ops, substream, state);
@@ -713,14 +747,10 @@ static int snd_pcm_action(struct action_ops *ops,
 
 /*
  *  Note: don't use any locks before
- *
- * NB2: this can handle the non-atomic callbacks if allow_nonatomic = 1
- *      when the pcm->info_flags has NONATOMIC_OPS bit, it's handled
- *      ouside the lock to allow sleep in the callback.
  */
 static int snd_pcm_action_lock_irq(struct action_ops *ops,
 				   snd_pcm_substream_t *substream,
-				   int state, int allow_nonatomic)
+				   int state)
 {
 	int res;
 
@@ -728,43 +758,10 @@ static int snd_pcm_action_lock_irq(struct action_ops *ops,
 	if (snd_pcm_stream_linked(substream)) {
 		spin_lock(&substream->group->lock);
 		spin_lock(&substream->self_group.lock);
-		res = snd_pcm_action_group(ops, substream, state, allow_nonatomic);
+		res = snd_pcm_action_group(ops, substream, state, 1);
 		spin_unlock(&substream->self_group.lock);
 		spin_unlock(&substream->group->lock);
-		if (res >= 0 && allow_nonatomic) {
-			/* now process the non-atomic substreams separately
-			 * outside the lock
-			 */
-#define MAX_LINKED_STREAMS	16	/* FIXME: should be variable */
-
-			struct list_head *pos;
-			int i, num_s = 0;
-			snd_pcm_substream_t *s;
-			snd_pcm_substream_t *subs[MAX_LINKED_STREAMS];
-			snd_pcm_group_for_each(pos, substream) {
-				if (num_s >= MAX_LINKED_STREAMS) {
-					res = -ENOMEM;
-					num_s = 0; /* don't proceed */
-					break;
-				}
-				s = snd_pcm_group_substream_entry(pos);
-				if (s->pcm->info_flags & SNDRV_PCM_INFO_NONATOMIC_OPS)
-					subs[num_s++] = s;
-			}
-			if (num_s > 0) {
-				read_unlock_irq(&snd_pcm_link_rwlock);
-				for (i = 0; i < num_s && res >= 0; i++)
-					res = snd_pcm_action_single(ops, subs[i], state);
-				return res;
-			}
-		}
 	} else {
-		if (allow_nonatomic &&
-		    (substream->pcm->info_flags & SNDRV_PCM_INFO_NONATOMIC_OPS)) {
-			read_unlock_irq(&snd_pcm_link_rwlock);
-			/* process outside the lock */
-			return snd_pcm_action_single(ops, substream, state);
-		}
 		spin_lock(&substream->self_group.lock);
 		res = snd_pcm_action_single(ops, substream, state);
 		spin_unlock(&substream->self_group.lock);
@@ -773,6 +770,23 @@ static int snd_pcm_action_lock_irq(struct action_ops *ops,
 	return res;
 }
 
+/*
+ */
+static int snd_pcm_action_nonatomic(struct action_ops *ops,
+				    snd_pcm_substream_t *substream,
+				    int state)
+{
+	int res;
+
+	down_read(&snd_pcm_link_rwsem);
+	if (snd_pcm_stream_linked(substream))
+		res = snd_pcm_action_group(ops, substream, state, 0);
+	else
+		res = snd_pcm_action_single(ops, substream, state);
+	up_read(&snd_pcm_link_rwsem);
+	return res;
+}
+
 static int snd_pcm_pre_start(snd_pcm_substream_t *substream, int state)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
@@ -1038,7 +1052,7 @@ static int snd_pcm_resume(snd_pcm_substream_t *substream)
 
 	snd_power_lock(card);
 	if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile)) >= 0)
-		res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0, 0);
+		res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0);
 	snd_power_unlock(card);
 	return res;
 }
@@ -1128,7 +1142,7 @@ static struct action_ops snd_pcm_action_reset = {
 
 static int snd_pcm_reset(snd_pcm_substream_t *substream)
 {
-	return snd_pcm_action_lock_irq(&snd_pcm_action_reset, substream, 0, 0);
+	return snd_pcm_action_nonatomic(&snd_pcm_action_reset, substream, 0);
 }
 
 static int snd_pcm_pre_prepare(snd_pcm_substream_t * substream, int state)
@@ -1176,7 +1190,7 @@ int snd_pcm_prepare(snd_pcm_substream_t *substream)
 
 	snd_power_lock(card);
 	if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile)) >= 0)
-		res = snd_pcm_action_lock_irq(&snd_pcm_action_prepare, substream, 0, 1); /* allow sleep if specified */
+		res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, substream, 0);
 	snd_power_unlock(card);
 	return res;
 }
@@ -1498,13 +1512,18 @@ static int snd_pcm_link(snd_pcm_substream_t *substream, int fd)
 	snd_pcm_file_t *pcm_file;
 	snd_pcm_substream_t *substream1;
 
-	if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
+	snd_pcm_stream_lock_irq(substream);
+	if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
+		snd_pcm_stream_unlock_irq(substream);
 		return -EBADFD;
+	}
+	snd_pcm_stream_unlock_irq(substream);
 	file = snd_pcm_file_fd(fd);
 	if (!file)
 		return -EBADFD;
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return -ENXIO);
+	pcm_file = file->private_data;
 	substream1 = pcm_file->substream;
+	down_write(&snd_pcm_link_rwsem);
 	write_lock_irq(&snd_pcm_link_rwlock);
 	if (substream->runtime->status->state != substream1->runtime->status->state) {
 		res = -EBADFD;
@@ -1528,6 +1547,7 @@ static int snd_pcm_link(snd_pcm_substream_t *substream, int fd)
 	substream1->group = substream->group;
  _end:
 	write_unlock_irq(&snd_pcm_link_rwlock);
+	up_write(&snd_pcm_link_rwsem);
 	fput(file);
 	return res;
 }
@@ -1544,6 +1564,7 @@ static int snd_pcm_unlink(snd_pcm_substream_t *substream)
 	struct list_head *pos;
 	int res = 0, count = 0;
 
+	down_write(&snd_pcm_link_rwsem);
 	write_lock_irq(&snd_pcm_link_rwlock);
 	if (!snd_pcm_stream_linked(substream)) {
 		res = -EALREADY;
@@ -1564,6 +1585,7 @@ static int snd_pcm_unlink(snd_pcm_substream_t *substream)
 	relink_to_local(substream);
        _end:
 	write_unlock_irq(&snd_pcm_link_rwlock);
+	up_write(&snd_pcm_link_rwsem);
 	return res;
 }
 
@@ -1658,13 +1680,12 @@ static int snd_pcm_hw_rule_sample_bits(snd_pcm_hw_params_t *params,
 static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100,
                                  48000, 64000, 88200, 96000, 176400, 192000 };
 
-#define RATES (sizeof(rates) / sizeof(rates[0]))
-
 static int snd_pcm_hw_rule_rate(snd_pcm_hw_params_t *params,
 				snd_pcm_hw_rule_t *rule)
 {
 	snd_pcm_hardware_t *hw = rule->private;
-	return snd_interval_list(hw_param_interval(params, rule->var), RATES, rates, hw->rates);
+	return snd_interval_list(hw_param_interval(params, rule->var),
+				 ARRAY_SIZE(rates), rates, hw->rates);
 }		
 
 static int snd_pcm_hw_rule_buffer_bytes_max(snd_pcm_hw_params_t *params,
@@ -1923,7 +1944,7 @@ static int snd_pcm_release_file(snd_pcm_file_t * pcm_file)
 	substream->ffile = NULL;
 	snd_pcm_remove_file(str, pcm_file);
 	snd_pcm_release_substream(substream);
-	snd_magic_kfree(pcm_file);
+	kfree(pcm_file);
 	return 0;
 }
 
@@ -1940,13 +1961,13 @@ static int snd_pcm_open_file(struct file *file,
 	snd_assert(rpcm_file != NULL, return -EINVAL);
 	*rpcm_file = NULL;
 
-	pcm_file = snd_magic_kcalloc(snd_pcm_file_t, 0, GFP_KERNEL);
+	pcm_file = kcalloc(1, sizeof(*pcm_file), GFP_KERNEL);
 	if (pcm_file == NULL) {
 		return -ENOMEM;
 	}
 
 	if ((err = snd_pcm_open_substream(pcm, stream, &substream)) < 0) {
-		snd_magic_kfree(pcm_file);
+		kfree(pcm_file);
 		return err;
 	}
 
@@ -2050,7 +2071,7 @@ int snd_pcm_release(struct inode *inode, struct file *file)
 	snd_pcm_substream_t *substream;
 	snd_pcm_file_t *pcm_file;
 
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return -ENXIO);
+	pcm_file = file->private_data;
 	substream = pcm_file->substream;
 	snd_assert(substream != NULL, return -ENXIO);
 	snd_assert(!atomic_read(&substream->runtime->mmap_count), );
@@ -2414,7 +2435,7 @@ static int snd_pcm_common_ioctl1(snd_pcm_substream_t *substream,
 	case SNDRV_PCM_IOCTL_RESET:
 		return snd_pcm_reset(substream);
 	case SNDRV_PCM_IOCTL_START:
-		return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, 0, 0);
+		return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, 0);
 	case SNDRV_PCM_IOCTL_LINK:
 		return snd_pcm_link(substream, (int)(unsigned long) arg);
 	case SNDRV_PCM_IOCTL_UNLINK:
@@ -2616,26 +2637,36 @@ static int snd_pcm_playback_ioctl(struct inode *inode, struct file *file,
 				  unsigned int cmd, unsigned long arg)
 {
 	snd_pcm_file_t *pcm_file;
+	int err;
 
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return -ENXIO);
+	pcm_file = file->private_data;
 
 	if (((cmd >> 8) & 0xff) != 'A')
 		return -ENOTTY;
 
-	return snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
+	/* FIXME: need to unlock BKL to allow preemption */
+	unlock_kernel();
+	err = snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
+	lock_kernel();
+	return err;
 }
 
 static int snd_pcm_capture_ioctl(struct inode *inode, struct file *file,
 				 unsigned int cmd, unsigned long arg)
 {
 	snd_pcm_file_t *pcm_file;
+	int err;
 
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return -ENXIO);
+	pcm_file = file->private_data;
 
 	if (((cmd >> 8) & 0xff) != 'A')
 		return -ENOTTY;
 
-	return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
+	/* FIXME: need to unlock BKL to allow preemption */
+	unlock_kernel();
+	err = snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
+	lock_kernel();
+	return err;
 }
 
 int snd_pcm_kernel_playback_ioctl(snd_pcm_substream_t *substream,
@@ -2682,7 +2713,7 @@ static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, l
 	snd_pcm_runtime_t *runtime;
 	snd_pcm_sframes_t result;
 
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return -ENXIO);
+	pcm_file = file->private_data;
 	substream = pcm_file->substream;
 	snd_assert(substream != NULL, return -ENXIO);
 	runtime = substream->runtime;
@@ -2704,7 +2735,7 @@ static ssize_t snd_pcm_write(struct file *file, const char __user *buf, size_t c
 	snd_pcm_runtime_t *runtime;
 	snd_pcm_sframes_t result;
 
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, result = -ENXIO; goto end);
+	pcm_file = file->private_data;
 	substream = pcm_file->substream;
 	snd_assert(substream != NULL, result = -ENXIO; goto end);
 	runtime = substream->runtime;
@@ -2736,7 +2767,7 @@ static ssize_t snd_pcm_readv(struct file *file, const struct iovec *_vector,
 	void __user **bufs;
 	snd_pcm_uframes_t frames;
 
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return -ENXIO);
+	pcm_file = file->private_data;
 	substream = pcm_file->substream;
 	snd_assert(substream != NULL, return -ENXIO);
 	runtime = substream->runtime;
@@ -2770,7 +2801,7 @@ static ssize_t snd_pcm_writev(struct file *file, const struct iovec *_vector,
 	void __user **bufs;
 	snd_pcm_uframes_t frames;
 
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, result = -ENXIO; goto end);
+	pcm_file = file->private_data;
 	substream = pcm_file->substream;
 	snd_assert(substream != NULL, result = -ENXIO; goto end);
 	runtime = substream->runtime;
@@ -2805,7 +2836,7 @@ unsigned int snd_pcm_playback_poll(struct file *file, poll_table * wait)
         unsigned int mask;
 	snd_pcm_uframes_t avail;
 
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return 0);
+	pcm_file = file->private_data;
 
 	substream = pcm_file->substream;
 	snd_assert(substream != NULL, return -ENXIO);
@@ -2843,7 +2874,7 @@ unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait)
         unsigned int mask;
 	snd_pcm_uframes_t avail;
 
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return 0);
+	pcm_file = file->private_data;
 
 	substream = pcm_file->substream;
 	snd_assert(substream != NULL, return -ENXIO);
@@ -2877,6 +2908,18 @@ unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait)
 	return mask;
 }
 
+/*
+ * mmap support
+ */
+
+/*
+ * Only on coherent architectures, we can mmap the status and the control records
+ * for effcient data transfer.  On others, we have to use HWSYNC ioctl...
+ */
+#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_ALPHA)
+/*
+ * mmap status record
+ */
 static struct page * snd_pcm_mmap_status_nopage(struct vm_area_struct *area, unsigned long address, int *type)
 {
 	snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
@@ -2899,8 +2942,8 @@ static struct vm_operations_struct snd_pcm_vm_ops_status =
 	.nopage =	snd_pcm_mmap_status_nopage,
 };
 
-int snd_pcm_mmap_status(snd_pcm_substream_t *substream, struct file *file,
-			struct vm_area_struct *area)
+static int snd_pcm_mmap_status(snd_pcm_substream_t *substream, struct file *file,
+			       struct vm_area_struct *area)
 {
 	snd_pcm_runtime_t *runtime;
 	long size;
@@ -2917,6 +2960,9 @@ int snd_pcm_mmap_status(snd_pcm_substream_t *substream, struct file *file,
 	return 0;
 }
 
+/*
+ * mmap control record
+ */
 static struct page * snd_pcm_mmap_control_nopage(struct vm_area_struct *area, unsigned long address, int *type)
 {
 	snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
@@ -2956,20 +3002,26 @@ static int snd_pcm_mmap_control(snd_pcm_substream_t *substream, struct file *fil
 	area->vm_flags |= VM_RESERVED;
 	return 0;
 }
-
-static void snd_pcm_mmap_data_open(struct vm_area_struct *area)
+#else /* ! coherent mmap */
+/*
+ * don't support mmap for status and control records.
+ */
+static int snd_pcm_mmap_status(snd_pcm_substream_t *substream, struct file *file,
+			       struct vm_area_struct *area)
 {
-	snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
-	atomic_inc(&substream->runtime->mmap_count);
+	return -ENXIO;
 }
-
-static void snd_pcm_mmap_data_close(struct vm_area_struct *area)
+static int snd_pcm_mmap_control(snd_pcm_substream_t *substream, struct file *file,
+				struct vm_area_struct *area)
 {
-	snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
-	atomic_dec(&substream->runtime->mmap_count);
+	return -ENXIO;
 }
+#endif /* coherent mmap */
 
-static struct page * snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsigned long address, int *type)
+/*
+ * nopage callback for mmapping a RAM page
+ */
+static struct page *snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsigned long address, int *type)
 {
 	snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data;
 	snd_pcm_runtime_t *runtime;
@@ -3009,6 +3061,52 @@ static struct vm_operations_struct snd_pcm_vm_ops_data =
 	.nopage =	snd_pcm_mmap_data_nopage,
 };
 
+/*
+ * mmap the DMA buffer on RAM
+ */
+static int snd_pcm_default_mmap(snd_pcm_substream_t *substream, struct vm_area_struct *area)
+{
+	area->vm_ops = &snd_pcm_vm_ops_data;
+	area->vm_private_data = substream;
+	area->vm_flags |= VM_RESERVED;
+	atomic_inc(&substream->runtime->mmap_count);
+	return 0;
+}
+
+/*
+ * mmap the DMA buffer on I/O memory area
+ */
+#if SNDRV_PCM_INFO_MMAP_IOMEM
+static struct vm_operations_struct snd_pcm_vm_ops_data_mmio =
+{
+	.open =		snd_pcm_mmap_data_open,
+	.close =	snd_pcm_mmap_data_close,
+};
+
+int snd_pcm_lib_mmap_iomem(snd_pcm_substream_t *substream, struct vm_area_struct *area)
+{
+	long size;
+	unsigned long offset;
+
+#ifdef pgprot_noncached
+	area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
+#endif
+	area->vm_ops = &snd_pcm_vm_ops_data_mmio;
+	area->vm_flags |= VM_IO;
+	size = area->vm_end - area->vm_start;
+	offset = area->vm_pgoff << PAGE_SHIFT;
+	if (io_remap_page_range(area, area->vm_start,
+				substream->runtime->dma_addr + offset,
+				size, area->vm_page_prot))
+		return -EAGAIN;
+	atomic_inc(&substream->runtime->mmap_count);
+	return 0;
+}
+#endif /* SNDRV_PCM_INFO_MMAP */
+
+/*
+ * mmap DMA buffer
+ */
 int snd_pcm_mmap_data(snd_pcm_substream_t *substream, struct file *file,
 		      struct vm_area_struct *area)
 {
@@ -3041,11 +3139,10 @@ int snd_pcm_mmap_data(snd_pcm_substream_t *substream, struct file *file,
 	if (offset > dma_bytes - size)
 		return -EINVAL;
 
-	area->vm_ops = &snd_pcm_vm_ops_data;
-	area->vm_private_data = substream;
-	area->vm_flags |= VM_RESERVED;
-	atomic_inc(&runtime->mmap_count);
-	return 0;
+	if (substream->ops->mmap)
+		return substream->ops->mmap(substream, area);
+	else
+		return snd_pcm_default_mmap(substream, area);
 }
 
 static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
@@ -3054,7 +3151,7 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
 	snd_pcm_substream_t *substream;	
 	unsigned long offset;
 	
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return -ENXIO);
+	pcm_file = file->private_data;
 	substream = pcm_file->substream;
 	snd_assert(substream != NULL, return -ENXIO);
 
@@ -3077,7 +3174,7 @@ static int snd_pcm_fasync(int fd, struct file * file, int on)
 	snd_pcm_runtime_t *runtime;
 	int err;
 
-	pcm_file = snd_magic_cast(snd_pcm_file_t, file->private_data, return -ENXIO);
+	pcm_file = file->private_data;
 	substream = pcm_file->substream;
 	snd_assert(substream != NULL, return -ENXIO);
 	runtime = substream->runtime;
@@ -3101,7 +3198,7 @@ static void snd_pcm_hw_convert_from_old_params(snd_pcm_hw_params_t *params, stru
 
 	memset(params, 0, sizeof(*params));
 	params->flags = oparams->flags;
-	for (i = 0; i < sizeof(oparams->masks) / sizeof(unsigned int); i++)
+	for (i = 0; i < ARRAY_SIZE(oparams->masks); i++)
 		params->masks[i].bits[0] = oparams->masks[i];
 	memcpy(params->intervals, oparams->intervals, sizeof(oparams->intervals));
 	params->rmask = __OLD_TO_NEW_MASK(oparams->rmask);
@@ -3119,7 +3216,7 @@ static void snd_pcm_hw_convert_to_old_params(struct sndrv_pcm_hw_params_old *opa
 
 	memset(oparams, 0, sizeof(*oparams));
 	oparams->flags = params->flags;
-	for (i = 0; i < sizeof(oparams->masks) / sizeof(unsigned int); i++)
+	for (i = 0; i < ARRAY_SIZE(oparams->masks); i++)
 		oparams->masks[i] = params->masks[i].bits[0];
 	memcpy(oparams->intervals, params->intervals, sizeof(oparams->intervals));
 	oparams->rmask = __NEW_TO_OLD_MASK(params->rmask);
@@ -3133,31 +3230,68 @@ static void snd_pcm_hw_convert_to_old_params(struct sndrv_pcm_hw_params_old *opa
 
 static int snd_pcm_hw_refine_old_user(snd_pcm_substream_t * substream, struct sndrv_pcm_hw_params_old __user * _oparams)
 {
-	snd_pcm_hw_params_t params;
-	struct sndrv_pcm_hw_params_old oparams;
+	snd_pcm_hw_params_t *params;
+	struct sndrv_pcm_hw_params_old *oparams = NULL;
 	int err;
-	if (copy_from_user(&oparams, _oparams, sizeof(oparams)))
-		return -EFAULT;
-	snd_pcm_hw_convert_from_old_params(&params, &oparams);
-	err = snd_pcm_hw_refine(substream, &params);
-	snd_pcm_hw_convert_to_old_params(&oparams, &params);
-	if (copy_to_user(_oparams, &oparams, sizeof(oparams)))
-		return -EFAULT;
+
+	params = kmalloc(sizeof(*params), GFP_KERNEL);
+	if (!params) {
+		err = -ENOMEM;
+		goto out;
+	}
+	oparams = kmalloc(sizeof(*oparams), GFP_KERNEL);
+	if (!oparams) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	if (copy_from_user(oparams, _oparams, sizeof(*oparams))) {
+		err = -EFAULT;
+		goto out;
+	}
+	snd_pcm_hw_convert_from_old_params(params, oparams);
+	err = snd_pcm_hw_refine(substream, params);
+	snd_pcm_hw_convert_to_old_params(oparams, params);
+	if (copy_to_user(_oparams, oparams, sizeof(*oparams))) {
+		if (!err)
+			err = -EFAULT;
+	}
+out:
+	kfree(params);
+	kfree(oparams);
 	return err;
 }
 
 static int snd_pcm_hw_params_old_user(snd_pcm_substream_t * substream, struct sndrv_pcm_hw_params_old __user * _oparams)
 {
-	snd_pcm_hw_params_t params;
-	struct sndrv_pcm_hw_params_old oparams;
+	snd_pcm_hw_params_t *params;
+	struct sndrv_pcm_hw_params_old *oparams = NULL;
 	int err;
-	if (copy_from_user(&oparams, _oparams, sizeof(oparams)))
-		return -EFAULT;
-	snd_pcm_hw_convert_from_old_params(&params, &oparams);
-	err = snd_pcm_hw_params(substream, &params);
-	snd_pcm_hw_convert_to_old_params(&oparams, &params);
-	if (copy_to_user(_oparams, &oparams, sizeof(oparams)))
-		return -EFAULT;
+
+	params = kmalloc(sizeof(*params), GFP_KERNEL);
+	if (!params) {
+		err = -ENOMEM;
+		goto out;
+	}
+	oparams = kmalloc(sizeof(*oparams), GFP_KERNEL);
+	if (!oparams) {
+		err = -ENOMEM;
+		goto out;
+	}
+	if (copy_from_user(oparams, _oparams, sizeof(*oparams))) {
+		err = -EFAULT;
+		goto out;
+	}
+	snd_pcm_hw_convert_from_old_params(params, oparams);
+	err = snd_pcm_hw_params(substream, params);
+	snd_pcm_hw_convert_to_old_params(oparams, params);
+	if (copy_to_user(_oparams, oparams, sizeof(*oparams))) {
+		if (!err)
+			err = -EFAULT;
+	}
+out:
+	kfree(params);
+	kfree(oparams);
 	return err;
 }
 
diff --git a/sound/core/pcm_timer.c b/sound/core/pcm_timer.c
index 40121971e..884eaea31 100644
--- a/sound/core/pcm_timer.c
+++ b/sound/core/pcm_timer.c
@@ -25,8 +25,6 @@
 #include <sound/pcm.h>
 #include <sound/timer.h>
 
-#define chip_t snd_pcm_substream_t
-
 /*
  *  Timer functions
  */
@@ -49,7 +47,7 @@ static unsigned long gcd(unsigned long a, unsigned long b)
 
 void snd_pcm_timer_resolution_change(snd_pcm_substream_t *substream)
 {
-	unsigned long rate, mult, fsize, l;
+	unsigned long rate, mult, fsize, l, post;
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	
         mult = 1000000000;
@@ -63,23 +61,24 @@ void snd_pcm_timer_resolution_change(snd_pcm_substream_t *substream)
 	l = gcd(rate, fsize);
 	rate /= l;
 	fsize /= l;
+	post = 1;
 	while ((mult * fsize) / fsize != mult) {
 		mult /= 2;
-		rate /= 2;
+		post *= 2;
 	}
 	if (rate == 0) {
 		snd_printk(KERN_ERR "pcm timer resolution out of range (rate = %u, period_size = %lu)\n", runtime->rate, runtime->period_size);
 		runtime->timer_resolution = -1;
 		return;
 	}
-	runtime->timer_resolution = mult * fsize / rate;
+	runtime->timer_resolution = (mult * fsize / rate) * post;
 }
 
 static unsigned long snd_pcm_timer_resolution(snd_timer_t * timer)
 {
 	snd_pcm_substream_t * substream;
 	
-	substream = snd_magic_cast(snd_pcm_substream_t, timer->private_data, return -ENXIO);
+	substream = timer->private_data;
 	return substream->runtime ? substream->runtime->timer_resolution : 0;
 }
 
@@ -123,7 +122,7 @@ static struct _snd_timer_hardware snd_pcm_timer =
 
 static void snd_pcm_timer_free(snd_timer_t *timer)
 {
-	snd_pcm_substream_t *substream = snd_magic_cast(snd_pcm_substream_t, timer->private_data, return);
+	snd_pcm_substream_t *substream = timer->private_data;
 	substream->timer = NULL;
 }
 
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index df904d18d..1c753cda6 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -23,6 +23,7 @@
 #include <sound/core.h>
 #include <linux/major.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/time.h>
@@ -44,10 +45,8 @@ static int amidi_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
 static int boot_devs;
 module_param_array(midi_map, int, boot_devs, 0444);
 MODULE_PARM_DESC(midi_map, "Raw MIDI device number assigned to 1st OSS device.");
-MODULE_PARM_SYNTAX(midi_map, "default:0,skill:advanced");
 module_param_array(amidi_map, int, boot_devs, 0444);
 MODULE_PARM_DESC(amidi_map, "Raw MIDI device number assigned to 2nd OSS device.");
-MODULE_PARM_SYNTAX(amidi_map, "default:1,skill:advanced");
 #endif /* CONFIG_SND_OSSEMUL */
 
 static int snd_rawmidi_free(snd_rawmidi_t *rawmidi);
@@ -269,7 +268,7 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice,
 		list2 = list2->next;
 	}
 	if (mode & SNDRV_RAWMIDI_LFLG_INPUT) {
-		input = snd_kcalloc(sizeof(snd_rawmidi_runtime_t), GFP_KERNEL);
+		input = kcalloc(1, sizeof(*input), GFP_KERNEL);
 		if (input == NULL) {
 			err = -ENOMEM;
 			goto __error;
@@ -291,7 +290,7 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice,
 	if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {
 		if (soutput->opened)
 			goto __skip_output;
-		output = snd_kcalloc(sizeof(snd_rawmidi_runtime_t), GFP_KERNEL);
+		output = kcalloc(1, sizeof(*output), GFP_KERNEL);
 		if (output == NULL) {
 			err = -ENOMEM;
 			goto __error;
@@ -398,7 +397,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
 	if ((file->f_flags & O_APPEND) || maj != CONFIG_SND_MAJOR) /* OSS emul? */
 		fflags |= SNDRV_RAWMIDI_LFLG_APPEND;
 	fflags |= SNDRV_RAWMIDI_LFLG_NOOPENLOCK;
-	rawmidi_file = snd_magic_kmalloc(snd_rawmidi_file_t, 0, GFP_KERNEL);
+	rawmidi_file = kmalloc(sizeof(*rawmidi_file), GFP_KERNEL);
 	if (rawmidi_file == NULL) {
 		snd_card_file_remove(card, file);
 		return -ENOMEM;
@@ -447,7 +446,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
 		file->private_data = rawmidi_file;
 	} else {
 		snd_card_file_remove(card, file);
-		snd_magic_kfree(rawmidi_file);
+		kfree(rawmidi_file);
 	}
 	up(&rmidi->open_mutex);
 	return err;
@@ -512,11 +511,11 @@ static int snd_rawmidi_release(struct inode *inode, struct file *file)
 	snd_rawmidi_t *rmidi;
 	int err;
 
-	rfile = snd_magic_cast(snd_rawmidi_file_t, file->private_data, return -ENXIO);
+	rfile = file->private_data;
 	err = snd_rawmidi_kernel_release(rfile);
 	rmidi = rfile->rmidi;
 	wake_up(&rmidi->open_wait);
-	snd_magic_kfree(rfile);
+	kfree(rfile);
 	snd_card_file_remove(rmidi->card, file);
 	return err;
 }
@@ -675,13 +674,13 @@ static int snd_rawmidi_input_status(snd_rawmidi_substream_t * substream,
 	return 0;
 }
 
-static int snd_rawmidi_ioctl(struct inode *inode, struct file *file,
-			     unsigned int cmd, unsigned long arg)
+static inline int _snd_rawmidi_ioctl(struct inode *inode, struct file *file,
+				     unsigned int cmd, unsigned long arg)
 {
 	snd_rawmidi_file_t *rfile;
 	void __user *argp = (void __user *)arg;
 
-	rfile = snd_magic_cast(snd_rawmidi_file_t, file->private_data, return -ENXIO);
+	rfile = file->private_data;
 	if (((cmd >> 8) & 0xff) != 'W')
 		return -ENOTTY;
 	switch (cmd) {
@@ -786,6 +785,17 @@ static int snd_rawmidi_ioctl(struct inode *inode, struct file *file,
 	return -ENOTTY;
 }
 
+/* FIXME: need to unlock BKL to allow preemption */
+static int snd_rawmidi_ioctl(struct inode *inode, struct file *file,
+			     unsigned int cmd, unsigned long arg)
+{
+	int err;
+	unlock_kernel();
+	err = _snd_rawmidi_ioctl(inode, file, cmd, arg);
+	lock_kernel();
+	return err;
+}
+
 int snd_rawmidi_control_ioctl(snd_card_t * card, snd_ctl_file_t * control,
 			      unsigned int cmd, unsigned long arg)
 {
@@ -944,7 +954,7 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
 	snd_rawmidi_substream_t *substream;
 	snd_rawmidi_runtime_t *runtime;
 
-	rfile = snd_magic_cast(snd_rawmidi_file_t, file->private_data, return -ENXIO);
+	rfile = file->private_data;
 	substream = rfile->input;
 	if (substream == NULL)
 		return -EIO;
@@ -974,6 +984,8 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
 		}
 		spin_unlock_irq(&runtime->lock);
 		count1 = snd_rawmidi_kernel_read1(substream, buf, count, 0);
+		if (count1 < 0)
+			return result > 0 ? result : count1;
 		result += count1;
 		buf += count1;
 		count -= count1;
@@ -1176,7 +1188,7 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, size
 	snd_rawmidi_runtime_t *runtime;
 	snd_rawmidi_substream_t *substream;
 
-	rfile = snd_magic_cast(snd_rawmidi_file_t, file->private_data, return -ENXIO);
+	rfile = file->private_data;
 	substream = rfile->output;
 	runtime = substream->runtime;
 	/* we cannot put an atomic message to our buffer */
@@ -1206,14 +1218,14 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, size
 		spin_unlock_irq(&runtime->lock);
 		count1 = snd_rawmidi_kernel_write1(substream, buf, count, 0);
 		if (count1 < 0)
-			continue;
+			return result > 0 ? result : count1;
 		result += count1;
 		buf += count1;
 		if ((size_t)count1 < count && (file->f_flags & O_NONBLOCK))
 			break;
 		count -= count1;
 	}
-	while (file->f_flags & O_SYNC) {
+	if (file->f_flags & O_SYNC) {
 		spin_lock_irq(&runtime->lock);
 		while (runtime->avail != runtime->buffer_size) {
 			wait_queue_t wait;
@@ -1241,7 +1253,7 @@ static unsigned int snd_rawmidi_poll(struct file *file, poll_table * wait)
 	snd_rawmidi_runtime_t *runtime;
 	unsigned int mask;
 
-	rfile = snd_magic_cast(snd_rawmidi_file_t, file->private_data, return 0);
+	rfile = file->private_data;
 	if (rfile->input != NULL) {
 		runtime = rfile->input->runtime;
 		runtime->trigger = 1;
@@ -1276,7 +1288,7 @@ static void snd_rawmidi_proc_info_read(snd_info_entry_t *entry,
 	snd_rawmidi_runtime_t *runtime;
 	struct list_head *list;
 
-	rmidi = snd_magic_cast(snd_rawmidi_t, entry->private_data, return);
+	rmidi = entry->private_data;
 	snd_iprintf(buffer, "%s\n\n", rmidi->name);
 	down(&rmidi->open_mutex);
 	if (rmidi->info_flags & SNDRV_RAWMIDI_INFO_OUTPUT) {
@@ -1353,7 +1365,7 @@ static int snd_rawmidi_alloc_substreams(snd_rawmidi_t *rmidi,
 
 	INIT_LIST_HEAD(&stream->substreams);
 	for (idx = 0; idx < count; idx++) {
-		substream = snd_kcalloc(sizeof(snd_rawmidi_substream_t), GFP_KERNEL);
+		substream = kcalloc(1, sizeof(*substream), GFP_KERNEL);
 		if (substream == NULL)
 			return -ENOMEM;
 		substream->stream = direction;
@@ -1396,7 +1408,7 @@ int snd_rawmidi_new(snd_card_t * card, char *id, int device,
 	snd_assert(rrawmidi != NULL, return -EINVAL);
 	*rrawmidi = NULL;
 	snd_assert(card != NULL, return -ENXIO);
-	rmidi = snd_magic_kcalloc(snd_rawmidi_t, 0, GFP_KERNEL);
+	rmidi = kcalloc(1, sizeof(*rmidi), GFP_KERNEL);
 	if (rmidi == NULL)
 		return -ENOMEM;
 	rmidi->card = card;
@@ -1439,20 +1451,20 @@ static int snd_rawmidi_free(snd_rawmidi_t *rmidi)
 	snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]);
 	if (rmidi->private_free)
 		rmidi->private_free(rmidi);
-	snd_magic_kfree(rmidi);
+	kfree(rmidi);
 	return 0;
 }
 
 static int snd_rawmidi_dev_free(snd_device_t *device)
 {
-	snd_rawmidi_t *rmidi = snd_magic_cast(snd_rawmidi_t, device->device_data, return -ENXIO);
+	snd_rawmidi_t *rmidi = device->device_data;
 	return snd_rawmidi_free(rmidi);
 }
 
 #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
 static void snd_rawmidi_dev_seq_free(snd_seq_device_t *device)
 {
-	snd_rawmidi_t *rmidi = snd_magic_cast(snd_rawmidi_t, device->private_data, return);
+	snd_rawmidi_t *rmidi = device->private_data;
 	rmidi->seq_dev = NULL;
 }
 #endif
@@ -1462,7 +1474,7 @@ static int snd_rawmidi_dev_register(snd_device_t *device)
 	int idx, err;
 	snd_info_entry_t *entry;
 	char name[16];
-	snd_rawmidi_t *rmidi = snd_magic_cast(snd_rawmidi_t, device->device_data, return -ENXIO);
+	snd_rawmidi_t *rmidi = device->device_data;
 
 	if (rmidi->device >= SNDRV_RAWMIDI_DEVICES)
 		return -ENOMEM;
@@ -1539,7 +1551,7 @@ static int snd_rawmidi_dev_register(snd_device_t *device)
 
 static int snd_rawmidi_dev_disconnect(snd_device_t *device)
 {
-	snd_rawmidi_t *rmidi = snd_magic_cast(snd_rawmidi_t, device->device_data, return -ENXIO);
+	snd_rawmidi_t *rmidi = device->device_data;
 	int idx;
 
 	down(&register_mutex);
@@ -1552,7 +1564,7 @@ static int snd_rawmidi_dev_disconnect(snd_device_t *device)
 static int snd_rawmidi_dev_unregister(snd_device_t *device)
 {
 	int idx;
-	snd_rawmidi_t *rmidi = snd_magic_cast(snd_rawmidi_t, device->device_data, return -ENXIO);
+	snd_rawmidi_t *rmidi = device->device_data;
 
 	snd_assert(rmidi != NULL, return -ENXIO);
 	down(&register_mutex);
diff --git a/sound/core/seq/Makefile b/sound/core/seq/Makefile
index e731cdc2e..d7b79d976 100644
--- a/sound/core/seq/Makefile
+++ b/sound/core/seq/Makefile
@@ -19,9 +19,6 @@ snd-seq-instr-objs := seq_instr.o
 snd-seq-dummy-objs := seq_dummy.o
 snd-seq-virmidi-objs := seq_virmidi.o
 
-RAWMIDI_OBJS = snd-seq-midi.o snd-seq-midi-event.o
-OPL3_OBJS = snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
-
 #
 # this function returns:
 #   "m" - CONFIG_SND_SEQUENCER is m
@@ -38,53 +35,8 @@ obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_VIRMIDI) += snd-seq-virmidi.o snd-seq-midi-event.o
-obj-$(call sequencer,$(CONFIG_SND_SERIAL_U16550)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_MTPAV)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_MPU401)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ALS100)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_AZT2320)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_AZT3328)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_DT019X)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ES18XX)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_OPL3SA2)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_AD1816A)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_CS4231)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_CS4232)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_CS4236)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ES1688)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_GUSCLASSIC)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_GUSMAX)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_GUSEXTREME)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_INTERWAVE)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_INTERWAVE_STB)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_OPTI92X_AD1848)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_OPTI92X_CS4231)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_OPTI93X)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_SB8)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_SB16)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += $(RAWMIDI_OBJS) $(OPL3_OBJS) snd-seq-virmidi.o
-obj-$(call sequencer,$(CONFIG_SND_ES968)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_WAVEFRONT)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_SSCAPE)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ALS4000)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_CMIPCI)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_CS4281)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ENS1370)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ENS1371)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ES1938)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ES1968)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_FM801)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ICE1712)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ICE1724)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_INTEL8X0)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_SONICVIBES)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_VIA82XX)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_ALI5451)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_CS46XX)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_EMU10K1)) += $(RAWMIDI_OBJS) snd-seq-midi-emul.o snd-seq-virmidi.o
-obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += $(RAWMIDI_OBJS) snd-seq-midi-emul.o snd-seq-instr.o
-obj-$(call sequencer,$(CONFIG_SND_YMFPCI)) += $(RAWMIDI_OBJS) $(OPL3_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_USB_AUDIO)) += $(RAWMIDI_OBJS)
-obj-$(call sequencer,$(CONFIG_SND_HDSP)) += $(RAWMIDI_OBJS)
-
-obj-m := $(sort $(obj-m))
+obj-$(call sequencer,$(CONFIG_SND_RAWMIDI)) += snd-seq-midi.o snd-seq-midi-event.o
+obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-seq-midi-event.o snd-seq-midi-emul.o snd-seq-instr.o
+obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-seq-midi-emul.o snd-seq-virmidi.o
+obj-$(call sequencer,$(CONFIG_SND_EMU10K1)) += snd-seq-midi-emul.o snd-seq-virmidi.o
+obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += snd-seq-midi-emul.o snd-seq-instr.o
diff --git a/sound/core/seq/instr/Makefile b/sound/core/seq/instr/Makefile
index 5ae3552af..69138f30a 100644
--- a/sound/core/seq/instr/Makefile
+++ b/sound/core/seq/instr/Makefile
@@ -17,35 +17,7 @@ snd-ainstr-iw-objs := ainstr_iw.o
 sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1)))
 
 # Toplevel Module Dependency
-obj-$(call sequencer,$(CONFIG_SND_ALS100)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_AZT2320)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_AZT3328)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_DT019X)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_ES18XX)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_OPL3SA2)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_AD1816A)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_CS4232)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_CS4236)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_ES1688)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_GUSCLASSIC)) += snd-ainstr-iw.o snd-ainstr-gf1.o snd-ainstr-simple.o
-obj-$(call sequencer,$(CONFIG_SND_GUSMAX)) += snd-ainstr-iw.o snd-ainstr-gf1.o snd-ainstr-simple.o
-obj-$(call sequencer,$(CONFIG_SND_GUSEXTREME)) += snd-ainstr-iw.o snd-ainstr-gf1.o snd-ainstr-simple.o snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_INTERWAVE)) += snd-ainstr-iw.o snd-ainstr-gf1.o snd-ainstr-simple.o
-obj-$(call sequencer,$(CONFIG_SND_INTERWAVE_STB)) += snd-ainstr-iw.o snd-ainstr-gf1.o snd-ainstr-simple.o
-obj-$(call sequencer,$(CONFIG_SND_OPTI92X_AD1848)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_OPTI92X_CS4231)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_OPTI93X)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_SB8)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_SB16)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_SBAWE)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_WAVEFRONT)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_ALS4000)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_CMIPCI)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_CS4281)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_ES1938)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_FM801)) += snd-ainstr-fm.o
-obj-$(call sequencer,$(CONFIG_SND_SONICVIBES)) += snd-ainstr-fm.o
+obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-ainstr-fm.o
+obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-ainstr-fm.o
+obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-ainstr-gf1.o snd-ainstr-simple.o snd-ainstr-iw.o
 obj-$(call sequencer,$(CONFIG_SND_TRIDENT)) += snd-ainstr-simple.o
-obj-$(call sequencer,$(CONFIG_SND_YMFPCI)) += snd-ainstr-fm.o
-
-obj-m := $(sort $(obj-m))
diff --git a/sound/core/seq/instr/ainstr_fm.c b/sound/core/seq/instr/ainstr_fm.c
index 648a7b89c..52a070b90 100644
--- a/sound/core/seq/instr/ainstr_fm.c
+++ b/sound/core/seq/instr/ainstr_fm.c
@@ -29,8 +29,6 @@
 MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture FM Instrument support.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 char *snd_seq_fm_id = SNDRV_SEQ_INSTR_ID_OPL2_3;
 
diff --git a/sound/core/seq/instr/ainstr_gf1.c b/sound/core/seq/instr/ainstr_gf1.c
index 13b46beff..6c21e52ca 100644
--- a/sound/core/seq/instr/ainstr_gf1.c
+++ b/sound/core/seq/instr/ainstr_gf1.c
@@ -30,8 +30,6 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture GF1 (GUS) Patch support.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 char *snd_seq_gf1_id = SNDRV_SEQ_INSTR_ID_GUS_PATCH;
 
@@ -64,7 +62,7 @@ static int snd_seq_gf1_copy_wave_from_stream(snd_gf1_ops_t *ops,
 		return -EFAULT;
 	*data += sizeof(xp);
 	*len -= sizeof(xp);
-	wp = (gf1_wave_t *)snd_kcalloc(sizeof(*wp), gfp_mask);
+	wp = kcalloc(1, sizeof(*wp), gfp_mask);
 	if (wp == NULL)
 		return -ENOMEM;
 	wp->share_id[0] = le32_to_cpu(xp.share_id[0]);
diff --git a/sound/core/seq/instr/ainstr_iw.c b/sound/core/seq/instr/ainstr_iw.c
index cd9ea5545..005171abe 100644
--- a/sound/core/seq/instr/ainstr_iw.c
+++ b/sound/core/seq/instr/ainstr_iw.c
@@ -30,8 +30,6 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture IWFFFF support.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 char *snd_seq_iwffff_id = SNDRV_SEQ_INSTR_ID_INTERWAVE;
 
@@ -96,7 +94,7 @@ static int snd_seq_iwffff_copy_env_from_stream(__u32 req_stype,
 		points_size = (le16_to_cpu(rx.nattack) + le16_to_cpu(rx.nrelease)) * 2 * sizeof(__u16);
 		if (points_size > *len)
 			return -EINVAL;
-		rp = (iwffff_env_record_t *)snd_kcalloc(sizeof(*rp) + points_size, gfp_mask);
+		rp = kcalloc(1, sizeof(*rp) + points_size, gfp_mask);
 		if (rp == NULL)
 			return -ENOMEM;
 		rp->nattack = le16_to_cpu(rx.nattack);
@@ -142,7 +140,7 @@ static int snd_seq_iwffff_copy_wave_from_stream(snd_iwffff_ops_t *ops,
 		return -EFAULT;
 	*data += sizeof(xp);
 	*len -= sizeof(xp);
-	wp = (iwffff_wave_t *)snd_kcalloc(sizeof(*wp), gfp_mask);
+	wp = kcalloc(1, sizeof(*wp), gfp_mask);
 	if (wp == NULL)
 		return -ENOMEM;
 	wp->share_id[0] = le32_to_cpu(xp.share_id[0]);
@@ -275,7 +273,7 @@ static int snd_seq_iwffff_put(void *private_data, snd_seq_kinstr_t *instr,
 			snd_seq_iwffff_instr_free(ops, ip, atomic);
 			return -EINVAL;
 		}
-		lp = (iwffff_layer_t *)snd_kcalloc(sizeof(*lp), gfp_mask);
+		lp = kcalloc(1, sizeof(*lp), gfp_mask);
 		if (lp == NULL) {
 			snd_seq_iwffff_instr_free(ops, ip, atomic);
 			return -ENOMEM;
diff --git a/sound/core/seq/instr/ainstr_simple.c b/sound/core/seq/instr/ainstr_simple.c
index 0f8117838..8ae5d10e5 100644
--- a/sound/core/seq/instr/ainstr_simple.c
+++ b/sound/core/seq/instr/ainstr_simple.c
@@ -30,8 +30,6 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture Simple Instrument support.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 char *snd_seq_simple_id = SNDRV_SEQ_INSTR_ID_SIMPLE;
 
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
index 5681563fa..27c5cac26 100644
--- a/sound/core/seq/oss/seq_oss.c
+++ b/sound/core/seq/oss/seq_oss.c
@@ -22,6 +22,7 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <linux/moduleparam.h>
 #include <sound/core.h>
 #include <sound/minors.h>
@@ -35,7 +36,6 @@
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("OSS-compatible sequencer module");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 /* Takashi says this is really only for sound-service-0-, but this is OK. */
 MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_SEQUENCER);
 MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_MUSIC);
@@ -177,9 +177,14 @@ static int
 odev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
 	seq_oss_devinfo_t *dp;
+	int err;
 	dp = file->private_data;
 	snd_assert(dp != NULL, return -EIO);
-	return snd_seq_oss_ioctl(dp, cmd, arg);
+	/* FIXME: need to unlock BKL to allow preemption */
+	unlock_kernel();
+	err = snd_seq_oss_ioctl(dp, cmd, arg);
+	lock_kernel();
+	return err;
 }
 
 
diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c
index c8b199dc1..cecf3f825 100644
--- a/sound/core/seq/oss/seq_oss_init.c
+++ b/sound/core/seq/oss/seq_oss_init.c
@@ -183,7 +183,7 @@ snd_seq_oss_open(struct file *file, int level)
 	int i, rc;
 	seq_oss_devinfo_t *dp;
 
-	if ((dp = snd_kcalloc(sizeof(*dp), GFP_KERNEL)) == NULL) {
+	if ((dp = kcalloc(1, sizeof(*dp), GFP_KERNEL)) == NULL) {
 		snd_printk(KERN_ERR "can't malloc device info\n");
 		return -ENOMEM;
 	}
@@ -211,7 +211,7 @@ snd_seq_oss_open(struct file *file, int level)
 	snd_seq_oss_midi_setup(dp);
 
 	if (dp->synth_opened == 0 && dp->max_mididev == 0) {
-		snd_printk(KERN_ERR "no device found\n");
+		/* snd_printk(KERN_ERR "no device found\n"); */
 		rc = -ENODEV;
 		goto _error;
 	}
diff --git a/sound/core/seq/oss/seq_oss_ioctl.c b/sound/core/seq/oss/seq_oss_ioctl.c
index 6d783cd14..e86f18d00 100644
--- a/sound/core/seq/oss/seq_oss_ioctl.c
+++ b/sound/core/seq/oss/seq_oss_ioctl.c
@@ -28,16 +28,54 @@
 #include "seq_oss_midi.h"
 #include "seq_oss_event.h"
 
+static int snd_seq_oss_synth_info_user(seq_oss_devinfo_t *dp, void __user *arg)
+{
+	struct synth_info info;
+
+	if (copy_from_user(&info, arg, sizeof(info)))
+		return -EFAULT;
+	if (snd_seq_oss_synth_make_info(dp, info.device, &info) < 0)
+		return -EINVAL;
+	if (copy_to_user(arg, &info, sizeof(info)))
+		return -EFAULT;
+	return 0;
+}
+
+static int snd_seq_oss_midi_info_user(seq_oss_devinfo_t *dp, void __user *arg)
+{
+	struct midi_info info;
+
+	if (copy_from_user(&info, arg, sizeof(info)))
+		return -EFAULT;
+	if (snd_seq_oss_midi_make_info(dp, info.device, &info) < 0)
+		return -EINVAL;
+	if (copy_to_user(arg, &info, sizeof(info)))
+		return -EFAULT;
+	return 0;
+}
+
+static int snd_seq_oss_oob_user(seq_oss_devinfo_t *dp, void __user *arg)
+{
+	unsigned char ev[8];
+	snd_seq_event_t tmpev;
+
+	if (copy_from_user(ev, arg, 8))
+		return -EFAULT;
+	memset(&tmpev, 0, sizeof(tmpev));
+	snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.port, dp->addr.client);
+	tmpev.time.tick = 0;
+	if (! snd_seq_oss_process_event(dp, (evrec_t*)ev, &tmpev)) {
+		snd_seq_oss_dispatch(dp, &tmpev, 0, 0);
+	}
+	return 0;
+}
+
 int
 snd_seq_oss_ioctl(seq_oss_devinfo_t *dp, unsigned int cmd, unsigned long carg)
 {
 	int dev, val;
-	struct synth_info inf;
-	struct midi_info minf;
-	unsigned char ev[8];
 	void __user *arg = (void __user *)carg;
 	int __user *p = arg;
-	snd_seq_event_t tmpev;
 
 	switch (cmd) {
 	case SNDCTL_TMR_TIMEBASE:
@@ -124,35 +162,15 @@ snd_seq_oss_ioctl(seq_oss_devinfo_t *dp, unsigned int cmd, unsigned long carg)
 	case SNDCTL_SYNTH_INFO:
 	case SNDCTL_SYNTH_ID:
 		debug_printk(("synth info\n"));
-		if (copy_from_user(&inf, arg, sizeof(inf)))
-			return -EFAULT;
-		if (snd_seq_oss_synth_make_info(dp, inf.device, &inf) < 0)
-			return -EINVAL;
-		if (copy_to_user(arg, &inf, sizeof(inf)))
-			return -EFAULT;
-		return 0;
+		return snd_seq_oss_synth_info_user(dp, arg);
 
 	case SNDCTL_SEQ_OUTOFBAND:
-		debug_printk(("out of bound\n"));
-		if (copy_from_user(ev, arg, 8))
-			return -EFAULT;
-		memset(&tmpev, 0, sizeof(tmpev));
-		snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.port, dp->addr.client);
-		tmpev.time.tick = 0;
-		if (! snd_seq_oss_process_event(dp, (evrec_t*)ev, &tmpev)) {
-			snd_seq_oss_dispatch(dp, &tmpev, 0, 0);
-		}
-		return 0;
+		debug_printk(("out of band\n"));
+		return snd_seq_oss_oob_user(dp, arg);
 
 	case SNDCTL_MIDI_INFO:
 		debug_printk(("midi info\n"));
-		if (copy_from_user(&minf, arg, sizeof(minf)))
-			return -EFAULT;
-		if (snd_seq_oss_midi_make_info(dp, minf.device, &minf) < 0)
-			return -EINVAL;
-		if (copy_to_user(arg, &minf, sizeof(minf)))
-			return -EFAULT;
-		return 0;
+		return snd_seq_oss_midi_info_user(dp, arg);
 
 	case SNDCTL_SEQ_THRESHOLD:
 		debug_printk(("threshold\n"));
diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c
index f7e82fc37..60fb5fb27 100644
--- a/sound/core/seq/oss/seq_oss_midi.c
+++ b/sound/core/seq/oss/seq_oss_midi.c
@@ -171,7 +171,7 @@ snd_seq_oss_midi_check_new_port(snd_seq_port_info_t *pinfo)
 	/*
 	 * allocate midi info record
 	 */
-	if ((mdev = snd_kcalloc(sizeof(*mdev), GFP_KERNEL)) == NULL) {
+	if ((mdev = kcalloc(1, sizeof(*mdev), GFP_KERNEL)) == NULL) {
 		snd_printk(KERN_ERR "can't malloc midi info\n");
 		return -ENOMEM;
 	}
diff --git a/sound/core/seq/oss/seq_oss_readq.c b/sound/core/seq/oss/seq_oss_readq.c
index 9690f8009..dfe6a5c83 100644
--- a/sound/core/seq/oss/seq_oss_readq.c
+++ b/sound/core/seq/oss/seq_oss_readq.c
@@ -45,12 +45,12 @@ snd_seq_oss_readq_new(seq_oss_devinfo_t *dp, int maxlen)
 {
 	seq_oss_readq_t *q;
 
-	if ((q = snd_kcalloc(sizeof(*q), GFP_KERNEL)) == NULL) {
+	if ((q = kcalloc(1, sizeof(*q), GFP_KERNEL)) == NULL) {
 		snd_printk(KERN_ERR "can't malloc read queue\n");
 		return NULL;
 	}
 
-	if ((q->q = snd_kcalloc(sizeof(evrec_t) * maxlen, GFP_KERNEL)) == NULL) {
+	if ((q->q = kcalloc(maxlen, sizeof(evrec_t), GFP_KERNEL)) == NULL) {
 		snd_printk(KERN_ERR "can't malloc read queue buffer\n");
 		kfree(q);
 		return NULL;
@@ -74,7 +74,6 @@ void
 snd_seq_oss_readq_delete(seq_oss_readq_t *q)
 {
 	if (q) {
-		snd_seq_oss_readq_clear(q);	/* to be sure */
 		if (q->q)
 			kfree(q->q);
 		kfree(q);
@@ -106,9 +105,9 @@ snd_seq_oss_readq_puts(seq_oss_readq_t *q, int dev, unsigned char *data, int len
 	evrec_t rec;
 	int result;
 
+	memset(&rec, 0, sizeof(rec));
 	rec.c[0] = SEQ_MIDIPUTC;
 	rec.c[2] = dev;
-	rec.c[3] = 0;
 
 	while (len-- > 0) {
 		rec.c[1] = *data++;
@@ -134,7 +133,7 @@ snd_seq_oss_readq_put_event(seq_oss_readq_t *q, evrec_t *ev)
 		return -ENOMEM;
 	}
 
-	memcpy(&q->q[q->tail], ev, ev_length(ev));
+	memcpy(&q->q[q->tail], ev, sizeof(*ev));
 	q->tail = (q->tail + 1) % q->maxlen;
 	q->qlen++;
 
@@ -150,50 +149,37 @@ snd_seq_oss_readq_put_event(seq_oss_readq_t *q, evrec_t *ev)
 
 /*
  * pop queue
+ * caller must hold lock
  */
-evrec_t *
-snd_seq_oss_readq_pick(seq_oss_readq_t *q, int blocking, unsigned long *rflags)
+int
+snd_seq_oss_readq_pick(seq_oss_readq_t *q, evrec_t *rec)
 {
-	evrec_t *p;
-
-	spin_lock_irqsave(&q->lock, *rflags);
-	if (q->qlen == 0) {
-		if (blocking) {
-			spin_unlock(&q->lock);
-			interruptible_sleep_on_timeout(&q->midi_sleep,
-						       q->pre_event_timeout);
-			spin_lock(&q->lock);
-		}
-		if (q->qlen == 0) {
-			spin_unlock_irqrestore(&q->lock, *rflags);
-			return NULL;
-		}
-	}
-	p = q->q + q->head;
-
-	return p;
+	if (q->qlen == 0)
+		return -EAGAIN;
+	memcpy(rec, &q->q[q->head], sizeof(*rec));
+	return 0;
 }
 
 /*
- * unlock queue
+ * sleep until ready
  */
 void
-snd_seq_oss_readq_unlock(seq_oss_readq_t *q, unsigned long flags)
+snd_seq_oss_readq_wait(seq_oss_readq_t *q)
 {
-	spin_unlock_irqrestore(&q->lock, flags);
+	interruptible_sleep_on_timeout(&q->midi_sleep, q->pre_event_timeout);
 }
 
 /*
- * drain one record and unlock queue
+ * drain one record
+ * caller must hold lock
  */
 void
-snd_seq_oss_readq_free(seq_oss_readq_t *q, unsigned long flags)
+snd_seq_oss_readq_free(seq_oss_readq_t *q)
 {
 	if (q->qlen > 0) {
 		q->head = (q->head + 1) % q->maxlen;
 		q->qlen--;
 	}
-	spin_unlock_irqrestore(&q->lock, flags);
 }
 
 /*
@@ -215,6 +201,7 @@ snd_seq_oss_readq_put_timestamp(seq_oss_readq_t *q, unsigned long curt, int seq_
 {
 	if (curt != q->input_time) {
 		evrec_t rec;
+		memset(&rec, 0, sizeof(rec));
 		switch (seq_mode) {
 		case SNDRV_SEQ_OSS_MODE_SYNTH:
 			rec.echo = (curt << 8) | SEQ_WAIT;
diff --git a/sound/core/seq/oss/seq_oss_readq.h b/sound/core/seq/oss/seq_oss_readq.h
index 22b2946c7..303b9298f 100644
--- a/sound/core/seq/oss/seq_oss_readq.h
+++ b/sound/core/seq/oss/seq_oss_readq.h
@@ -46,8 +46,11 @@ unsigned int snd_seq_oss_readq_poll(seq_oss_readq_t *readq, struct file *file, p
 int snd_seq_oss_readq_puts(seq_oss_readq_t *readq, int dev, unsigned char *data, int len);
 int snd_seq_oss_readq_put_event(seq_oss_readq_t *readq, evrec_t *ev);
 int snd_seq_oss_readq_put_timestamp(seq_oss_readq_t *readq, unsigned long curt, int seq_mode);
-evrec_t *snd_seq_oss_readq_pick(seq_oss_readq_t *q, int blocking, unsigned long *rflags);
-void snd_seq_oss_readq_unlock(seq_oss_readq_t *q, unsigned long flags);
-void snd_seq_oss_readq_free(seq_oss_readq_t *q, unsigned long flags);
+int snd_seq_oss_readq_pick(seq_oss_readq_t *q, evrec_t *rec);
+void snd_seq_oss_readq_wait(seq_oss_readq_t *q);
+void snd_seq_oss_readq_free(seq_oss_readq_t *q);
+
+#define snd_seq_oss_readq_lock(q, flags) spin_lock_irqsave(&(q)->lock, flags)
+#define snd_seq_oss_readq_unlock(q, flags) spin_unlock_irqrestore(&(q)->lock, flags)
 
 #endif
diff --git a/sound/core/seq/oss/seq_oss_rw.c b/sound/core/seq/oss/seq_oss_rw.c
index 811a47660..1d8fbd22e 100644
--- a/sound/core/seq/oss/seq_oss_rw.c
+++ b/sound/core/seq/oss/seq_oss_rw.c
@@ -44,35 +44,47 @@ int
 snd_seq_oss_read(seq_oss_devinfo_t *dp, char __user *buf, int count)
 {
 	seq_oss_readq_t *readq = dp->readq;
-	int cnt, pos;
-	evrec_t *q;
+	int result = 0, err = 0;
+	int ev_len;
+	evrec_t rec;
 	unsigned long flags;
 
 	if (readq == NULL || ! is_read_mode(dp->file_mode))
-		return -EIO;
-
-	/* copy queued events to read buffer */
-	cnt = count;
-	pos = 0;
-	q = snd_seq_oss_readq_pick(readq, !is_nonblock_mode(dp->file_mode), &flags);
-	if (q == NULL)
-		return 0;
-	do {
-		int ev_len;
-		/* tansfer the data */
-		ev_len = ev_length(q);
-		if (copy_to_user(buf + pos, q, ev_len)) {
+		return -ENXIO;
+
+	while (count >= SHORT_EVENT_SIZE) {
+		snd_seq_oss_readq_lock(readq, flags);
+		err = snd_seq_oss_readq_pick(readq, &rec);
+		if (err == -EAGAIN &&
+		    !is_nonblock_mode(dp->file_mode) && result == 0) {
+			snd_seq_oss_readq_unlock(readq, flags);
+			snd_seq_oss_readq_wait(readq);
+			snd_seq_oss_readq_lock(readq, flags);
+			if (signal_pending(current))
+				err = -ERESTARTSYS;
+			else
+				err = snd_seq_oss_readq_pick(readq, &rec);
+		}
+		if (err < 0) {
 			snd_seq_oss_readq_unlock(readq, flags);
 			break;
 		}
-		snd_seq_oss_readq_free(readq, flags);
-		pos += ev_len;
-		cnt -= ev_len;
-		if (cnt < ev_len)
+		ev_len = ev_length(&rec);
+		if (ev_len < count) {
+			snd_seq_oss_readq_unlock(readq, flags);
 			break;
-	} while ((q = snd_seq_oss_readq_pick(readq, 0, &flags)) != NULL);
-
-	return count - cnt;
+		}
+		snd_seq_oss_readq_free(readq);
+		snd_seq_oss_readq_unlock(readq, flags);
+		if (copy_to_user(buf, &rec, ev_len)) {
+			err = -EFAULT;
+			break;
+		}
+		result += ev_len;
+		buf += ev_len;
+		count -= ev_len;
+	}
+	return result > 0 ? result : err;
 }
 
 
@@ -83,56 +95,64 @@ snd_seq_oss_read(seq_oss_devinfo_t *dp, char __user *buf, int count)
 int
 snd_seq_oss_write(seq_oss_devinfo_t *dp, const char __user *buf, int count, struct file *opt)
 {
-	int rc, c, p, ev_size;
+	int result = 0, err = 0;
+	int ev_size, fmt;
 	evrec_t rec;
 
 	if (! is_write_mode(dp->file_mode) || dp->writeq == NULL)
-		return -EIO;
+		return -ENXIO;
 
-	c = count;
-	p = 0;
-	while (c >= SHORT_EVENT_SIZE) {
-		if (copy_from_user(rec.c, buf + p, SHORT_EVENT_SIZE))
+	while (count >= SHORT_EVENT_SIZE) {
+		if (copy_from_user(&rec, buf, SHORT_EVENT_SIZE)) {
+			err = -EFAULT;
 			break;
-		p += SHORT_EVENT_SIZE;
-
+		}
 		if (rec.s.code == SEQ_FULLSIZE) {
 			/* load patch */
-			int fmt = (*(unsigned short *)rec.c) & 0xffff;
-			return snd_seq_oss_synth_load_patch(dp, rec.s.dev, fmt, buf, p, c);
-
+			if (result > 0) {
+				err = -EINVAL;
+				break;
+			}
+			fmt = (*(unsigned short *)rec.c) & 0xffff;
+			/* FIXME the return value isn't correct */
+			return snd_seq_oss_synth_load_patch(dp, rec.s.dev,
+							    fmt, buf, 0, count);
 		}
 		if (ev_is_long(&rec)) {
 			/* extended code */
 			if (rec.s.code == SEQ_EXTENDED &&
-			    dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
-				return -EINVAL;
+			    dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) {
+				err = -EINVAL;
+				break;
+			}
 			ev_size = LONG_EVENT_SIZE;
-			if (c < ev_size)
+			if (count < ev_size)
 				break;
 			/* copy the reset 4 bytes */
-			if (copy_from_user(rec.c + SHORT_EVENT_SIZE, buf + p,
-					   LONG_EVENT_SIZE - SHORT_EVENT_SIZE))
+			if (copy_from_user(rec.c + SHORT_EVENT_SIZE,
+					   buf + SHORT_EVENT_SIZE,
+					   LONG_EVENT_SIZE - SHORT_EVENT_SIZE)) {
+				err = -EFAULT;
 				break;
-			p += LONG_EVENT_SIZE - SHORT_EVENT_SIZE;
-
+			}
 		} else {
 			/* old-type code */
-			if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC)
-				return -EINVAL;
+			if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) {
+				err = -EINVAL;
+				break;
+			}
 			ev_size = SHORT_EVENT_SIZE;
 		}
 
 		/* insert queue */
-		if ((rc = insert_queue(dp, &rec, opt)) < 0)
+		if ((err = insert_queue(dp, &rec, opt)) < 0)
 			break;
 
-		c -= ev_size;
+		result += ev_size;
+		buf += ev_size;
+		count -= ev_size;
 	}
-
-	if (count == c && is_nonblock_mode(dp->file_mode))
-		return -EAGAIN;
-	return count - c;
+	return result > 0 ? result : err;
 }
 
 
diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
index 4262dbd23..dc44e665d 100644
--- a/sound/core/seq/oss/seq_oss_synth.c
+++ b/sound/core/seq/oss/seq_oss_synth.c
@@ -103,7 +103,7 @@ snd_seq_oss_synth_register(snd_seq_device_t *dev)
 	snd_seq_oss_reg_t *reg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
 	unsigned long flags;
 
-	if ((rec = snd_kcalloc(sizeof(*rec), GFP_KERNEL)) == NULL) {
+	if ((rec = kcalloc(1, sizeof(*rec), GFP_KERNEL)) == NULL) {
 		snd_printk(KERN_ERR "can't malloc synth info\n");
 		return -ENOMEM;
 	}
@@ -244,7 +244,9 @@ snd_seq_oss_synth_setup(seq_oss_devinfo_t *dp)
 		}
 		info->nr_voices = rec->nr_voices;
 		if (info->nr_voices > 0) {
-			info->ch = snd_kcalloc(sizeof(seq_oss_chinfo_t) * info->nr_voices, GFP_KERNEL);
+			info->ch = kcalloc(info->nr_voices, sizeof(seq_oss_chinfo_t), GFP_KERNEL);
+			if (!info->ch)
+				BUG();
 			reset_channels(info);
 		}
 		debug_printk(("synth %d assigned\n", i));
@@ -505,7 +507,7 @@ snd_seq_oss_synth_sysex(seq_oss_devinfo_t *dp, int dev, unsigned char *buf, snd_
 
 	sysex = dp->synths[dev].sysex;
 	if (sysex == NULL) {
-		sysex = snd_kcalloc(sizeof(*sysex), GFP_KERNEL);
+		sysex = kcalloc(1, sizeof(*sysex), GFP_KERNEL);
 		if (sysex == NULL)
 			return -ENOMEM;
 		dp->synths[dev].sysex = sysex;
diff --git a/sound/core/seq/oss/seq_oss_timer.c b/sound/core/seq/oss/seq_oss_timer.c
index b0d72a883..b17c1f8d1 100644
--- a/sound/core/seq/oss/seq_oss_timer.c
+++ b/sound/core/seq/oss/seq_oss_timer.c
@@ -46,7 +46,7 @@ snd_seq_oss_timer_new(seq_oss_devinfo_t *dp)
 {
 	seq_oss_timer_t *rec;
 
-	rec = snd_kcalloc(sizeof(*rec), GFP_KERNEL);
+	rec = kcalloc(1, sizeof(*rec), GFP_KERNEL);
 	if (rec == NULL)
 		return NULL;
 
@@ -168,7 +168,7 @@ snd_seq_oss_timer_start(seq_oss_timer_t *timer)
 	tmprec.queue = dp->queue;
 	tmprec.ppq = timer->ppq;
 	tmprec.tempo = timer->tempo;
-	snd_seq_kernel_client_ctl(dp->cseq, SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO, &tmprec);
+	snd_seq_set_queue_tempo(dp->cseq, &tmprec);
 
 	send_timer_event(dp, SNDRV_SEQ_EVENT_START, 0);
 	timer->running = 1;
diff --git a/sound/core/seq/oss/seq_oss_writeq.c b/sound/core/seq/oss/seq_oss_writeq.c
index 9f8a5438d..138203864 100644
--- a/sound/core/seq/oss/seq_oss_writeq.c
+++ b/sound/core/seq/oss/seq_oss_writeq.c
@@ -37,7 +37,7 @@ snd_seq_oss_writeq_new(seq_oss_devinfo_t *dp, int maxlen)
 	seq_oss_writeq_t *q;
 	snd_seq_client_pool_t pool;
 
-	if ((q = snd_kcalloc(sizeof(*q), GFP_KERNEL)) == NULL)
+	if ((q = kcalloc(1, sizeof(*q), GFP_KERNEL)) == NULL)
 		return NULL;
 	q->dp = dp;
 	q->maxlen = maxlen;
diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c
index 5f8beb4a2..f8d629362 100644
--- a/sound/core/seq/seq.c
+++ b/sound/core/seq/seq.c
@@ -50,8 +50,6 @@ int seq_default_timer_resolution = 0;	/* Hz */
 MODULE_AUTHOR("Frank van de Pol <fvdpol@coil.demon.nl>, Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 static int boot_devs;
 module_param_array(seq_client_load, int, boot_devs, 0444);
@@ -133,6 +131,7 @@ EXPORT_SYMBOL(snd_seq_kernel_client_enqueue_blocking);
 EXPORT_SYMBOL(snd_seq_kernel_client_dispatch);
 EXPORT_SYMBOL(snd_seq_kernel_client_ctl);
 EXPORT_SYMBOL(snd_seq_kernel_client_write_poll);
+EXPORT_SYMBOL(snd_seq_set_queue_tempo);
   /* seq_memory.c */
 EXPORT_SYMBOL(snd_seq_expand_var_event);
 EXPORT_SYMBOL(snd_seq_dump_var_event);
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index eff36938f..b30fda808 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -23,6 +23,7 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/minors.h>
@@ -202,7 +203,7 @@ static client_t *seq_create_client1(int client_index, int poolsize)
 	client_t *client;
 
 	/* init client data */
-	client = snd_kcalloc(sizeof(client_t), GFP_KERNEL);
+	client = kcalloc(1, sizeof(*client), GFP_KERNEL);
 	if (client == NULL)
 		return NULL;
 	client->pool = snd_seq_pool_new(poolsize);
@@ -546,36 +547,6 @@ static int update_timestamp_of_queue(snd_seq_event_t *event, int queue, int real
 }
 
 
-/*
- * expand a quoted event.
- */
-static int expand_quoted_event(snd_seq_event_t *event)
-{
-	snd_seq_event_t *quoted;
-
-	quoted = event->data.quote.event;
-	if (quoted == NULL) {
-		snd_printd("seq: quoted event is NULL\n");
-		return -EINVAL;
-	}
-
-	event->type = quoted->type;
-	event->tag = quoted->tag;
-	event->source = quoted->source;
-	/* don't use quoted destination */
-	event->data = quoted->data;
-	/* use quoted timestamp only if subscription/port didn't update it */
-	if (event->queue == SNDRV_SEQ_QUEUE_DIRECT) {
-		event->flags = quoted->flags;
-		event->queue = quoted->queue;
-		event->time = quoted->time;
-	} else {
-		event->flags = (event->flags & SNDRV_SEQ_TIME_STAMP_MASK)
-			| (quoted->flags & ~SNDRV_SEQ_TIME_STAMP_MASK);
-	}
-	return 0;
-}
-
 /*
  * deliver an event to the specified destination.
  * if filter is non-zero, client filter bitmap is tested.
@@ -590,7 +561,7 @@ static int snd_seq_deliver_single_event(client_t *client,
 	client_t *dest = NULL;
 	client_port_t *dest_port = NULL;
 	int result = -ENOENT;
-	int direct, quoted = 0;
+	int direct;
 
 	direct = snd_seq_ev_is_direct(event);
 
@@ -611,14 +582,6 @@ static int snd_seq_deliver_single_event(client_t *client,
 		update_timestamp_of_queue(event, dest_port->time_queue,
 					  dest_port->time_real);
 
-	if (event->type == SNDRV_SEQ_EVENT_KERNEL_QUOTE) {
-		quoted = 1;
-		if (expand_quoted_event(event) < 0) {
-			result = 0; /* do not send bounce error */
-			goto __skip;
-		}
-	}
-
 	switch (dest->type) {
 	case USER_CLIENT:
 		if (dest->data.user.fifo)
@@ -641,14 +604,7 @@ static int snd_seq_deliver_single_event(client_t *client,
 		snd_seq_client_unlock(dest);
 
 	if (result < 0 && !direct) {
-		if (quoted) {
-			/* return directly to the original source */
-			dest = snd_seq_client_use_ptr(event->source.client);
-			result = bounce_error_event(dest, event, result, atomic, hop);
-			snd_seq_client_unlock(dest);
-		} else {
-			result = bounce_error_event(client, event, result, atomic, hop);
-		}
+		result = bounce_error_event(client, event, result, atomic, hop);
 	}
 	return result;
 }
@@ -1694,6 +1650,13 @@ static int snd_seq_ioctl_get_queue_tempo(client_t * client, void __user *arg)
 
 
 /* SET_QUEUE_TEMPO ioctl() */
+int snd_seq_set_queue_tempo(int client, snd_seq_queue_tempo_t *tempo)
+{
+	if (!snd_seq_queue_check_access(tempo->queue, client))
+		return -EPERM;
+	return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo);
+}
+
 static int snd_seq_ioctl_set_queue_tempo(client_t * client, void __user *arg)
 {
 	int result;
@@ -1702,15 +1665,8 @@ static int snd_seq_ioctl_set_queue_tempo(client_t * client, void __user *arg)
 	if (copy_from_user(&tempo, arg, sizeof(tempo)))
 		return -EFAULT;
 
-	if (snd_seq_queue_check_access(tempo.queue, client->number)) {
-		result = snd_seq_queue_timer_set_tempo(tempo.queue, client->number, &tempo);
-		if (result < 0)
-			return result;
-	} else {
-		return -EPERM;
-	}	
-
-	return 0;
+	result = snd_seq_set_queue_tempo(client->number, &tempo);
+	return result < 0 ? result : 0;
 }
 
 
@@ -2176,10 +2132,15 @@ static int snd_seq_ioctl(struct inode *inode, struct file *file,
 			 unsigned int cmd, unsigned long arg)
 {
 	client_t *client = (client_t *) file->private_data;
+	int err;
 
 	snd_assert(client != NULL, return -ENXIO);
 		
-	return snd_seq_do_ioctl(client, cmd, (void __user *) arg);
+	/* FIXME: need to unlock BKL to allow preemption */
+	unlock_kernel();
+	err = snd_seq_do_ioctl(client, cmd, (void __user *) arg);
+	lock_kernel();
+	return err;
 }
 
 
@@ -2261,8 +2222,7 @@ static int kernel_client_enqueue(int client, snd_seq_event_t *ev,
 
 	if (ev->type == SNDRV_SEQ_EVENT_NONE)
 		return 0; /* ignore this */
-	if (ev->type == SNDRV_SEQ_EVENT_KERNEL_ERROR ||
-	    ev->type == SNDRV_SEQ_EVENT_KERNEL_QUOTE)
+	if (ev->type == SNDRV_SEQ_EVENT_KERNEL_ERROR)
 		return -EINVAL; /* quoted events can't be enqueued */
 
 	/* fill in client number */
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index 398b6209a..0545ff8bb 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -48,8 +48,6 @@
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("ALSA sequencer device management");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 /*
  * driver list
@@ -181,7 +179,7 @@ int snd_seq_device_new(snd_card_t *card, int device, char *id, int argsize,
 	if (ops == NULL)
 		return -ENOMEM;
 
-	dev = snd_magic_kcalloc(snd_seq_device_t, sizeof(*dev) + argsize, GFP_KERNEL);
+	dev = kcalloc(1, sizeof(*dev)*2 + argsize, GFP_KERNEL);
 	if (dev == NULL) {
 		unlock_driver(ops);
 		return -ENOMEM;
@@ -235,7 +233,7 @@ static int snd_seq_device_free(snd_seq_device_t *dev)
 	free_device(dev, ops);
 	if (dev->private_free)
 		dev->private_free(dev);
-	snd_magic_kfree(dev);
+	kfree(dev);
 
 	unlock_driver(ops);
 
@@ -244,7 +242,7 @@ static int snd_seq_device_free(snd_seq_device_t *dev)
 
 static int snd_seq_device_dev_free(snd_device_t *device)
 {
-	snd_seq_device_t *dev = snd_magic_cast(snd_seq_device_t, device->device_data, return -ENXIO);
+	snd_seq_device_t *dev = device->device_data;
 	return snd_seq_device_free(dev);
 }
 
@@ -253,7 +251,7 @@ static int snd_seq_device_dev_free(snd_device_t *device)
  */
 static int snd_seq_device_dev_register(snd_device_t *device)
 {
-	snd_seq_device_t *dev = snd_magic_cast(snd_seq_device_t, device->device_data, return -ENXIO);
+	snd_seq_device_t *dev = device->device_data;
 	ops_list_t *ops;
 
 	ops = find_driver(dev->id, 0);
@@ -275,7 +273,7 @@ static int snd_seq_device_dev_register(snd_device_t *device)
  */
 static int snd_seq_device_dev_disconnect(snd_device_t *device)
 {
-	snd_seq_device_t *dev = snd_magic_cast(snd_seq_device_t, device->device_data, return -ENXIO);
+	snd_seq_device_t *dev = device->device_data;
 	ops_list_t *ops;
 
 	ops = find_driver(dev->id, 0);
@@ -293,7 +291,7 @@ static int snd_seq_device_dev_disconnect(snd_device_t *device)
  */
 static int snd_seq_device_dev_unregister(snd_device_t *device)
 {
-	snd_seq_device_t *dev = snd_magic_cast(snd_seq_device_t, device->device_data, return -ENXIO);
+	snd_seq_device_t *dev = device->device_data;
 	return snd_seq_device_free(dev);
 }
 
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
index eb7f13b5f..f350bcd68 100644
--- a/sound/core/seq/seq_dummy.c
+++ b/sound/core/seq/seq_dummy.c
@@ -63,8 +63,6 @@
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("ALSA sequencer MIDI-through client");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 static int ports = 1;
 static int duplex = 0;
@@ -95,7 +93,7 @@ dummy_unuse(void *private_data, snd_seq_port_subscribe_t *info)
 	int i;
 	snd_seq_event_t ev;
 
-	p = snd_magic_cast(snd_seq_dummy_port_t, private_data, return -EINVAL);
+	p = private_data;
 	memset(&ev, 0, sizeof(ev));
 	if (p->duplex)
 		ev.source.port = p->connect;
@@ -122,18 +120,11 @@ dummy_input(snd_seq_event_t *ev, int direct, void *private_data, int atomic, int
 	snd_seq_dummy_port_t *p;
 	snd_seq_event_t tmpev;
 
-	p = snd_magic_cast(snd_seq_dummy_port_t, private_data, return -EINVAL);
+	p = private_data;
 	if (ev->source.client == SNDRV_SEQ_CLIENT_SYSTEM ||
 	    ev->type == SNDRV_SEQ_EVENT_KERNEL_ERROR)
 		return 0; /* ignore system messages */
-	/* save the original sender */
-	tmpev.type = SNDRV_SEQ_EVENT_KERNEL_QUOTE;
-	tmpev.flags = (ev->flags & ~SNDRV_SEQ_EVENT_LENGTH_MASK)
-		| SNDRV_SEQ_EVENT_LENGTH_FIXED;
-	tmpev.tag = ev->tag;
-	tmpev.time = ev->time;
-	tmpev.data.quote.origin = ev->source;
-	tmpev.data.quote.event = ev;
+	tmpev = *ev;
 	if (p->duplex)
 		tmpev.source.port = p->connect;
 	else
@@ -150,8 +141,8 @@ dummy_free(void *private_data)
 {
 	snd_seq_dummy_port_t *p;
 
-	p = snd_magic_cast(snd_seq_dummy_port_t, private_data, return);
-	snd_magic_kfree(p);
+	p = private_data;
+	kfree(p);
 }
 
 /*
@@ -164,7 +155,7 @@ create_port(int idx, int type)
 	snd_seq_port_callback_t pcb;
 	snd_seq_dummy_port_t *rec;
 
-	if ((rec = snd_magic_kcalloc(snd_seq_dummy_port_t, 0, GFP_KERNEL)) == NULL)
+	if ((rec = kcalloc(1, sizeof(*rec), GFP_KERNEL)) == NULL)
 		return NULL;
 
 	rec->client = my_client;
@@ -190,7 +181,7 @@ create_port(int idx, int type)
 	pcb.private_data = rec;
 	pinfo.kernel = &pcb;
 	if (snd_seq_kernel_client_ctl(my_client, SNDRV_SEQ_IOCTL_CREATE_PORT, &pinfo) < 0) {
-		snd_magic_kfree(rec);
+		kfree(rec);
 		return NULL;
 	}
 	rec->port = pinfo.addr.port;
diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c
index 68da258b1..3b7647ca7 100644
--- a/sound/core/seq/seq_fifo.c
+++ b/sound/core/seq/seq_fifo.c
@@ -33,7 +33,7 @@ fifo_t *snd_seq_fifo_new(int poolsize)
 {
 	fifo_t *f;
 
-	f = snd_kcalloc(sizeof(fifo_t), GFP_KERNEL);
+	f = kcalloc(1, sizeof(*f), GFP_KERNEL);
 	if (f == NULL) {
 		snd_printd("malloc failed for snd_seq_fifo_new() \n");
 		return NULL;
diff --git a/sound/core/seq/seq_instr.c b/sound/core/seq/seq_instr.c
index d8ca16f6f..3949fd9fa 100644
--- a/sound/core/seq/seq_instr.c
+++ b/sound/core/seq/seq_instr.c
@@ -29,8 +29,6 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer instrument library.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 
 static void snd_instr_lock_ops(snd_seq_kinstr_list_t *list)
@@ -53,10 +51,7 @@ static void snd_instr_unlock_ops(snd_seq_kinstr_list_t *list)
 
 snd_seq_kcluster_t *snd_seq_cluster_new(int atomic)
 {
-	snd_seq_kcluster_t *cluster;
-	
-	cluster = (snd_seq_kcluster_t *) snd_kcalloc(sizeof(snd_seq_kcluster_t), atomic ? GFP_ATOMIC : GFP_KERNEL);
-	return cluster;
+	return kcalloc(1, sizeof(snd_seq_kcluster_t), atomic ? GFP_ATOMIC : GFP_KERNEL);
 }
 
 void snd_seq_cluster_free(snd_seq_kcluster_t *cluster, int atomic)
@@ -70,7 +65,7 @@ snd_seq_kinstr_t *snd_seq_instr_new(int add_len, int atomic)
 {
 	snd_seq_kinstr_t *instr;
 	
-	instr = (snd_seq_kinstr_t *) snd_kcalloc(sizeof(snd_seq_kinstr_t) + add_len, atomic ? GFP_ATOMIC : GFP_KERNEL);
+	instr = kcalloc(1, sizeof(snd_seq_kinstr_t) + add_len, atomic ? GFP_ATOMIC : GFP_KERNEL);
 	if (instr == NULL)
 		return NULL;
 	instr->add_len = add_len;
@@ -94,7 +89,7 @@ snd_seq_kinstr_list_t *snd_seq_instr_list_new(void)
 {
 	snd_seq_kinstr_list_t *list;
 
-	list = (snd_seq_kinstr_list_t *) snd_kcalloc(sizeof(snd_seq_kinstr_list_t), GFP_KERNEL);
+	list = kcalloc(1, sizeof(snd_seq_kinstr_list_t), GFP_KERNEL);
 	if (list == NULL)
 		return NULL;
 	spin_lock_init(&list->lock);
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index fbcfd3c8a..a404088ec 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -95,7 +95,7 @@ int snd_seq_dump_var_event(const snd_seq_event_t *event, snd_seq_dump_func_t fun
 			int size = sizeof(buf);
 			if (len < size)
 				size = len;
-			if (copy_from_user(buf, curptr, size) < 0)
+			if (copy_from_user(buf, curptr, size))
 				return -EFAULT;
 			err = func(private_data, buf, size);
 			if (err < 0)
@@ -158,7 +158,7 @@ int snd_seq_expand_var_event(const snd_seq_event_t *event, int count, char *buf,
 	if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
 		if (! in_kernel)
 			return -EINVAL;
-		if (copy_from_user(buf, event->data.ext.ptr, len) < 0)
+		if (copy_from_user(buf, event->data.ext.ptr, len))
 			return -EFAULT;
 		return newlen;
 	}
@@ -453,7 +453,7 @@ pool_t *snd_seq_pool_new(int poolsize)
 	pool_t *pool;
 
 	/* create pool block */
-	pool = snd_kcalloc(sizeof(pool_t), GFP_KERNEL);
+	pool = kcalloc(1, sizeof(*pool), GFP_KERNEL);
 	if (pool == NULL) {
 		snd_printd("seq: malloc failed for pool\n");
 		return NULL;
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index a2a4b83f8..202bbea92 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -43,8 +43,6 @@ Possible options for midisynth module:
 MODULE_AUTHOR("Frank van de Pol <fvdpol@coil.demon.nl>, Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer MIDI synth.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 int output_buffer_size = PAGE_SIZE;
 module_param(output_buffer_size, int, 0644);
 MODULE_PARM_DESC(output_buffer_size, "Output buffer size in bytes.");
@@ -323,7 +321,7 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
 	client = synths[card->number];
 	if (client == NULL) {
 		newclient = 1;
-		client = snd_kcalloc(sizeof(seq_midisynth_client_t), GFP_KERNEL);
+		client = kcalloc(1, sizeof(*client), GFP_KERNEL);
 		if (client == NULL) {
 			up(&register_mutex);
 			return -ENOMEM;
@@ -341,7 +339,7 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
 	} else if (device == 0)
 		set_client_name(client, card, &info); /* use the first device's name */
 
-	msynth = snd_kcalloc(sizeof(seq_midisynth_t) * ports, GFP_KERNEL);
+	msynth = kcalloc(ports, sizeof(seq_midisynth_t), GFP_KERNEL);
 	if (msynth == NULL)
 		goto __nomem;
 
diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c
index 4c200a111..7ea8db2cf 100644
--- a/sound/core/seq/seq_midi_emul.c
+++ b/sound/core/seq/seq_midi_emul.c
@@ -42,8 +42,6 @@
 MODULE_AUTHOR("Takashi Iwai / Steve Ratcliffe");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer MIDI emulation.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 
 /* Prototypes for static functions */
 static void note_off(snd_midi_op_t *ops, void *drv, snd_midi_channel_t *chan, int note, int vel);
diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c
index 41c165a8b..7e549257e 100644
--- a/sound/core/seq/seq_midi_event.c
+++ b/sound/core/seq/seq_midi_event.c
@@ -118,7 +118,7 @@ int snd_midi_event_new(int bufsize, snd_midi_event_t **rdev)
 	snd_midi_event_t *dev;
 
 	*rdev = NULL;
-	dev = (snd_midi_event_t *)snd_kcalloc(sizeof(snd_midi_event_t), GFP_KERNEL);
+	dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
 	if (dev == NULL)
 		return -ENOMEM;
 	if (bufsize > 0) {
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index 6ce21e52e..b976951fc 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -141,7 +141,7 @@ client_port_t *snd_seq_create_port(client_t *client, int port)
 	}
 
 	/* create a new port */
-	new_port = snd_kcalloc(sizeof(client_port_t), GFP_KERNEL);
+	new_port = kcalloc(1, sizeof(*new_port), GFP_KERNEL);
 	if (! new_port) {
 		snd_printd("malloc failed for registering client port\n");
 		return NULL;	/* failure, out of memory */
@@ -488,7 +488,7 @@ int snd_seq_port_connect(client_t *connector,
 	unsigned long flags;
 	int exclusive;
 
-	subs = snd_kcalloc(sizeof(*subs), GFP_KERNEL);
+	subs = kcalloc(1, sizeof(*subs), GFP_KERNEL);
 	if (! subs)
 		return -ENOMEM;
 
diff --git a/sound/core/seq/seq_prioq.c b/sound/core/seq/seq_prioq.c
index 59f775ca3..a519732ed 100644
--- a/sound/core/seq/seq_prioq.c
+++ b/sound/core/seq/seq_prioq.c
@@ -59,7 +59,7 @@ prioq_t *snd_seq_prioq_new(void)
 {
 	prioq_t *f;
 
-	f = snd_kcalloc(sizeof(prioq_t), GFP_KERNEL);
+	f = kcalloc(1, sizeof(*f), GFP_KERNEL);
 	if (f == NULL) {
 		snd_printd("oops: malloc failed for snd_seq_prioq_new()\n");
 		return NULL;
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index c9ac37e8d..afb14604e 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -111,7 +111,7 @@ static queue_t *queue_new(int owner, int locked)
 {
 	queue_t *q;
 
-	q = snd_kcalloc(sizeof(queue_t), GFP_KERNEL);
+	q = kcalloc(1, sizeof(*q), GFP_KERNEL);
 	if (q == NULL) {
 		snd_printd("malloc failed for snd_seq_queue_new()\n");
 		return NULL;
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c
index 78b244191..753f1c086 100644
--- a/sound/core/seq/seq_timer.c
+++ b/sound/core/seq/seq_timer.c
@@ -59,7 +59,7 @@ seq_timer_t *snd_seq_timer_new(void)
 {
 	seq_timer_t *tmr;
 	
-	tmr = snd_kcalloc(sizeof(seq_timer_t), GFP_KERNEL);
+	tmr = kcalloc(1, sizeof(*tmr), GFP_KERNEL);
 	if (tmr == NULL) {
 		snd_printd("malloc failed for snd_seq_timer_new() \n");
 		return NULL;
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index c493a659d..278548629 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -115,7 +115,7 @@ int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev)
 {
 	snd_virmidi_dev_t *rdev;
 
-	rdev = snd_magic_cast(snd_virmidi_dev_t, rmidi->private_data, return -EINVAL);
+	rdev = rmidi->private_data;
 	return snd_virmidi_dev_receive_event(rdev, ev);
 }
 
@@ -127,7 +127,7 @@ static int snd_virmidi_event_input(snd_seq_event_t *ev, int direct,
 {
 	snd_virmidi_dev_t *rdev;
 
-	rdev = snd_magic_cast(snd_virmidi_dev_t, private_data, return -EINVAL);
+	rdev = private_data;
 	if (!(rdev->flags & SNDRV_VIRMIDI_USE))
 		return 0; /* ignored */
 	return snd_virmidi_dev_receive_event(rdev, ev);
@@ -138,7 +138,7 @@ static int snd_virmidi_event_input(snd_seq_event_t *ev, int direct,
  */
 static void snd_virmidi_input_trigger(snd_rawmidi_substream_t * substream, int up)
 {
-	snd_virmidi_t *vmidi = snd_magic_cast(snd_virmidi_t, substream->runtime->private_data, return);
+	snd_virmidi_t *vmidi = substream->runtime->private_data;
 
 	if (up) {
 		vmidi->trigger = 1;
@@ -152,7 +152,7 @@ static void snd_virmidi_input_trigger(snd_rawmidi_substream_t * substream, int u
  */
 static void snd_virmidi_output_trigger(snd_rawmidi_substream_t * substream, int up)
 {
-	snd_virmidi_t *vmidi = snd_magic_cast(snd_virmidi_t, substream->runtime->private_data, return);
+	snd_virmidi_t *vmidi = substream->runtime->private_data;
 	int count, res;
 	unsigned char buf[32], *pbuf;
 
@@ -199,17 +199,17 @@ static void snd_virmidi_output_trigger(snd_rawmidi_substream_t * substream, int
  */
 static int snd_virmidi_input_open(snd_rawmidi_substream_t * substream)
 {
-	snd_virmidi_dev_t *rdev = snd_magic_cast(snd_virmidi_dev_t, substream->rmidi->private_data, return -EINVAL);
+	snd_virmidi_dev_t *rdev = substream->rmidi->private_data;
 	snd_rawmidi_runtime_t *runtime = substream->runtime;
 	snd_virmidi_t *vmidi;
 	unsigned long flags;
 
-	vmidi = snd_magic_kcalloc(snd_virmidi_t, 0, GFP_KERNEL);
+	vmidi = kcalloc(1, sizeof(*vmidi), GFP_KERNEL);
 	if (vmidi == NULL)
 		return -ENOMEM;
 	vmidi->substream = substream;
 	if (snd_midi_event_new(0, &vmidi->parser) < 0) {
-		snd_magic_kfree(vmidi);
+		kfree(vmidi);
 		return -ENOMEM;
 	}
 	vmidi->seq_mode = rdev->seq_mode;
@@ -228,16 +228,16 @@ static int snd_virmidi_input_open(snd_rawmidi_substream_t * substream)
  */
 static int snd_virmidi_output_open(snd_rawmidi_substream_t * substream)
 {
-	snd_virmidi_dev_t *rdev = snd_magic_cast(snd_virmidi_dev_t, substream->rmidi->private_data, return -EINVAL);
+	snd_virmidi_dev_t *rdev = substream->rmidi->private_data;
 	snd_rawmidi_runtime_t *runtime = substream->runtime;
 	snd_virmidi_t *vmidi;
 
-	vmidi = snd_magic_kcalloc(snd_virmidi_t, 0, GFP_KERNEL);
+	vmidi = kcalloc(1, sizeof(*vmidi), GFP_KERNEL);
 	if (vmidi == NULL)
 		return -ENOMEM;
 	vmidi->substream = substream;
 	if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &vmidi->parser) < 0) {
-		snd_magic_kfree(vmidi);
+		kfree(vmidi);
 		return -ENOMEM;
 	}
 	vmidi->seq_mode = rdev->seq_mode;
@@ -254,11 +254,11 @@ static int snd_virmidi_output_open(snd_rawmidi_substream_t * substream)
  */
 static int snd_virmidi_input_close(snd_rawmidi_substream_t * substream)
 {
-	snd_virmidi_t *vmidi = snd_magic_cast(snd_virmidi_t, substream->runtime->private_data, return -EINVAL);
+	snd_virmidi_t *vmidi = substream->runtime->private_data;
 	snd_midi_event_free(vmidi->parser);
 	list_del(&vmidi->list);
 	substream->runtime->private_data = NULL;
-	snd_magic_kfree(vmidi);
+	kfree(vmidi);
 	return 0;
 }
 
@@ -267,10 +267,10 @@ static int snd_virmidi_input_close(snd_rawmidi_substream_t * substream)
  */
 static int snd_virmidi_output_close(snd_rawmidi_substream_t * substream)
 {
-	snd_virmidi_t *vmidi = snd_magic_cast(snd_virmidi_t, substream->runtime->private_data, return -EINVAL);
+	snd_virmidi_t *vmidi = substream->runtime->private_data;
 	snd_midi_event_free(vmidi->parser);
 	substream->runtime->private_data = NULL;
-	snd_magic_kfree(vmidi);
+	kfree(vmidi);
 	return 0;
 }
 
@@ -281,7 +281,7 @@ static int snd_virmidi_subscribe(void *private_data, snd_seq_port_subscribe_t *i
 {
 	snd_virmidi_dev_t *rdev;
 
-	rdev = snd_magic_cast(snd_virmidi_dev_t, private_data, return -EINVAL);
+	rdev = private_data;
 	if (!try_module_get(rdev->card->module))
 		return -EFAULT;
 	rdev->flags |= SNDRV_VIRMIDI_SUBSCRIBE;
@@ -295,7 +295,7 @@ static int snd_virmidi_unsubscribe(void *private_data, snd_seq_port_subscribe_t
 {
 	snd_virmidi_dev_t *rdev;
 
-	rdev = snd_magic_cast(snd_virmidi_dev_t, private_data, return -EINVAL);
+	rdev = private_data;
 	rdev->flags &= ~SNDRV_VIRMIDI_SUBSCRIBE;
 	module_put(rdev->card->module);
 	return 0;
@@ -309,7 +309,7 @@ static int snd_virmidi_use(void *private_data, snd_seq_port_subscribe_t *info)
 {
 	snd_virmidi_dev_t *rdev;
 
-	rdev = snd_magic_cast(snd_virmidi_dev_t, private_data, return -EINVAL);
+	rdev = private_data;
 	if (!try_module_get(rdev->card->module))
 		return -EFAULT;
 	rdev->flags |= SNDRV_VIRMIDI_USE;
@@ -323,7 +323,7 @@ static int snd_virmidi_unuse(void *private_data, snd_seq_port_subscribe_t *info)
 {
 	snd_virmidi_dev_t *rdev;
 
-	rdev = snd_magic_cast(snd_virmidi_dev_t, private_data, return -EINVAL);
+	rdev = private_data;
 	rdev->flags &= ~SNDRV_VIRMIDI_USE;
 	module_put(rdev->card->module);
 	return 0;
@@ -424,7 +424,7 @@ static void snd_virmidi_dev_detach_seq(snd_virmidi_dev_t *rdev)
  */
 static int snd_virmidi_dev_register(snd_rawmidi_t *rmidi)
 {
-	snd_virmidi_dev_t *rdev = snd_magic_cast(snd_virmidi_dev_t, rmidi->private_data, return -ENXIO);
+	snd_virmidi_dev_t *rdev = rmidi->private_data;
 	int err;
 
 	switch (rdev->seq_mode) {
@@ -451,7 +451,7 @@ static int snd_virmidi_dev_register(snd_rawmidi_t *rmidi)
  */
 static int snd_virmidi_dev_unregister(snd_rawmidi_t *rmidi)
 {
-	snd_virmidi_dev_t *rdev = snd_magic_cast(snd_virmidi_dev_t, rmidi->private_data, return -ENXIO);
+	snd_virmidi_dev_t *rdev = rmidi->private_data;
 
 	if (rdev->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH)
 		snd_virmidi_dev_detach_seq(rdev);
@@ -471,8 +471,8 @@ static snd_rawmidi_global_ops_t snd_virmidi_global_ops = {
  */
 static void snd_virmidi_free(snd_rawmidi_t *rmidi)
 {
-	snd_virmidi_dev_t *rdev = snd_magic_cast(snd_virmidi_dev_t, rmidi->private_data, return);
-	snd_magic_kfree(rdev);
+	snd_virmidi_dev_t *rdev = rmidi->private_data;
+	kfree(rdev);
 }
 
 /*
@@ -493,7 +493,7 @@ int snd_virmidi_new(snd_card_t *card, int device, snd_rawmidi_t **rrmidi)
 				   &rmidi)) < 0)
 		return err;
 	strcpy(rmidi->name, rmidi->id);
-	rdev = snd_magic_kcalloc(snd_virmidi_dev_t, 0, GFP_KERNEL);
+	rdev = kcalloc(1, sizeof(*rdev), GFP_KERNEL);
 	if (rdev == NULL) {
 		snd_device_free(card, rmidi);
 		return -ENOMEM;
diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c
index ab8c9b1f8..1ca1f6d01 100644
--- a/sound/core/sgbuf.c
+++ b/sound/core/sgbuf.c
@@ -39,11 +39,13 @@ int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab)
 	if (! sgbuf)
 		return -EINVAL;
 
+	tmpb.dev.type = SNDRV_DMA_TYPE_DEV;
+	tmpb.dev.dev = sgbuf->dev;
 	for (i = 0; i < sgbuf->pages; i++) {
 		tmpb.area = sgbuf->table[i].buf;
 		tmpb.addr = sgbuf->table[i].addr;
 		tmpb.bytes = PAGE_SIZE;
-		snd_dma_free_pages(&sgbuf->dev, &tmpb);
+		snd_dma_free_pages(&tmpb);
 	}
 	if (dmab->area)
 		vunmap(dmab->area);
@@ -59,7 +61,7 @@ int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab)
 	return 0;
 }
 
-void *snd_malloc_sgbuf_pages(const struct snd_dma_device *dev,
+void *snd_malloc_sgbuf_pages(struct device *device,
 			     size_t size, struct snd_dma_buffer *dmab,
 			     size_t *res_size)
 {
@@ -73,8 +75,7 @@ void *snd_malloc_sgbuf_pages(const struct snd_dma_device *dev,
 	if (! sgbuf)
 		return NULL;
 	memset(sgbuf, 0, sizeof(*sgbuf));
-	sgbuf->dev = *dev;
-	sgbuf->dev.type = SNDRV_DMA_TYPE_DEV;
+	sgbuf->dev = device;
 	pages = snd_sgbuf_aligned_pages(size);
 	sgbuf->tblsize = sgbuf_align_table(pages);
 	sgbuf->table = kmalloc(sizeof(*sgbuf->table) * sgbuf->tblsize, GFP_KERNEL);
@@ -88,7 +89,7 @@ void *snd_malloc_sgbuf_pages(const struct snd_dma_device *dev,
 
 	/* allocate each page */
 	for (i = 0; i < pages; i++) {
-		if (snd_dma_alloc_pages(&sgbuf->dev, PAGE_SIZE, &tmpb) < 0) {
+		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, device, PAGE_SIZE, &tmpb) < 0) {
 			if (res_size == NULL)
 				goto _failed;
 			*res_size = size = sgbuf->pages * PAGE_SIZE;
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 558a8dbaa..a9e477c2e 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -44,19 +44,14 @@ static int device_mode = S_IFCHR | S_IRUGO | S_IWUGO;
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Advanced Linux Sound Architecture driver for soundcards.");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_SUPPORTED_DEVICE("sound");
 module_param(major, int, 0444);
 MODULE_PARM_DESC(major, "Major # for sound driver.");
-MODULE_PARM_SYNTAX(major, "default:116,skill:devel");
 module_param(cards_limit, int, 0444);
 MODULE_PARM_DESC(cards_limit, "Count of auto-loadable soundcards.");
-MODULE_PARM_SYNTAX(cards_limit, "default:8,skill:advanced");
 MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
 #ifdef CONFIG_DEVFS_FS
 module_param(device_mode, int, 0444);
 MODULE_PARM_DESC(device_mode, "Device file permission mask for devfs.");
-MODULE_PARM_SYNTAX(device_mode, "default:0666,base:8");
 #endif
 MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
 
@@ -339,39 +334,29 @@ int __exit snd_minor_info_done(void)
 static int __init alsa_sound_init(void)
 {
 	short controlnum;
-#ifdef CONFIG_SND_OSSEMUL
 	int err;
-#endif
 	int card;
 
 	snd_major = major;
 	snd_ecards_limit = cards_limit;
 	for (card = 0; card < SNDRV_CARDS; card++)
 		INIT_LIST_HEAD(&snd_minors_hash[card]);
-#ifdef CONFIG_SND_OSSEMUL
 	if ((err = snd_oss_init_module()) < 0)
 		return err;
-#endif
 	devfs_mk_dir("snd");
 	if (register_chrdev(major, "alsa", &snd_fops)) {
 		snd_printk(KERN_ERR "unable to register native major device number %d\n", major);
 		devfs_remove("snd");
 		return -EIO;
 	}
-#ifdef CONFIG_SND_DEBUG_MEMORY
 	snd_memory_init();
-#endif
 	if (snd_info_init() < 0) {
-#ifdef CONFIG_SND_DEBUG_MEMORY
 		snd_memory_done();
-#endif
 		unregister_chrdev(major, "alsa");
 		devfs_remove("snd");
 		return -ENOMEM;
 	}
-#ifdef CONFIG_SND_OSSEMUL
 	snd_info_minor_register();
-#endif
 	for (controlnum = 0; controlnum < cards_limit; controlnum++) {
 		devfs_mk_cdev(MKDEV(major, controlnum<<5), S_IFCHR | device_mode, "snd/controlC%d", controlnum);
 		class_simple_device_add(sound_class, MKDEV(major, controlnum<<5), NULL, "controlC%d", controlnum);
@@ -391,13 +376,9 @@ static void __exit alsa_sound_exit(void)
 		class_simple_device_remove(MKDEV(major, controlnum<<5));
 	}
 
-#ifdef CONFIG_SND_OSSEMUL
 	snd_info_minor_unregister();
-#endif
 	snd_info_done();
-#ifdef CONFIG_SND_DEBUG_MEMORY
 	snd_memory_done();
-#endif
 	if (unregister_chrdev(major, "alsa") != 0)
 		snd_printk(KERN_ERR "unable to unregister major device number %d\n", major);
 	devfs_remove("snd");
@@ -406,24 +387,6 @@ static void __exit alsa_sound_exit(void)
 module_init(alsa_sound_init)
 module_exit(alsa_sound_exit)
 
-#ifndef MODULE
-
-/* format is: snd=major,cards_limit[,device_mode] */
-
-static int __init alsa_sound_setup(char *str)
-{
-	(void)(get_option(&str,&major) == 2 &&
-	       get_option(&str,&cards_limit) == 2);
-#ifdef CONFIG_DEVFS_FS
-	(void)(get_option(&str,&device_mode) == 2);
-#endif
-	return 1;
-}
-
-__setup("snd=", alsa_sound_setup);
-
-#endif /* ifndef MODULE */
-
   /* sound.c */
 EXPORT_SYMBOL(snd_major);
 EXPORT_SYMBOL(snd_ecards_limit);
@@ -439,14 +402,11 @@ EXPORT_SYMBOL(snd_unregister_oss_device);
   /* memory.c */
 #ifdef CONFIG_SND_DEBUG_MEMORY
 EXPORT_SYMBOL(snd_hidden_kmalloc);
+EXPORT_SYMBOL(snd_hidden_kcalloc);
 EXPORT_SYMBOL(snd_hidden_kfree);
 EXPORT_SYMBOL(snd_hidden_vmalloc);
 EXPORT_SYMBOL(snd_hidden_vfree);
-EXPORT_SYMBOL(_snd_magic_kmalloc);
-EXPORT_SYMBOL(_snd_magic_kcalloc);
-EXPORT_SYMBOL(snd_magic_kfree);
 #endif
-EXPORT_SYMBOL(snd_kcalloc);
 EXPORT_SYMBOL(snd_kmalloc_strdup);
 EXPORT_SYMBOL(copy_to_user_fromio);
 EXPORT_SYMBOL(copy_from_user_toio);
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 6f6d89c43..cee5f47c7 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -22,6 +22,7 @@
 #include <sound/driver.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/moduleparam.h>
@@ -46,7 +47,6 @@ static int timer_limit = DEFAULT_TIMER_LIMIT;
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("ALSA timer interface");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 module_param(timer_limit, int, 0444);
 MODULE_PARM_DESC(timer_limit, "Maximum global timers in system.");
 
@@ -94,7 +94,7 @@ static void snd_timer_reschedule(snd_timer_t * timer, unsigned long ticks_left);
 static snd_timer_instance_t *snd_timer_instance_new(char *owner, snd_timer_t *timer)
 {
 	snd_timer_instance_t *timeri;
-	timeri = snd_kcalloc(sizeof(snd_timer_instance_t), GFP_KERNEL);
+	timeri = kcalloc(1, sizeof(*timeri), GFP_KERNEL);
 	if (timeri == NULL)
 		return NULL;
 	timeri->owner = snd_kmalloc_strdup(owner, GFP_KERNEL);
@@ -761,7 +761,7 @@ int snd_timer_new(snd_card_t *card, char *id, snd_timer_id_t *tid, snd_timer_t *
 	snd_assert(tid != NULL, return -EINVAL);
 	snd_assert(rtimer != NULL, return -EINVAL);
 	*rtimer = NULL;
-	timer = snd_magic_kcalloc(snd_timer_t, 0, GFP_KERNEL);
+	timer = kcalloc(1, sizeof(*timer), GFP_KERNEL);
 	if (timer == NULL)
 		return -ENOMEM;
 	timer->tmr_class = tid->dev_class;
@@ -792,19 +792,19 @@ static int snd_timer_free(snd_timer_t *timer)
 	snd_assert(timer != NULL, return -ENXIO);
 	if (timer->private_free)
 		timer->private_free(timer);
-	snd_magic_kfree(timer);
+	kfree(timer);
 	return 0;
 }
 
 int snd_timer_dev_free(snd_device_t *device)
 {
-	snd_timer_t *timer = snd_magic_cast(snd_timer_t, device->device_data, return -ENXIO);
+	snd_timer_t *timer = device->device_data;
 	return snd_timer_free(timer);
 }
 
 int snd_timer_dev_register(snd_device_t *dev)
 {
-	snd_timer_t *timer = snd_magic_cast(snd_timer_t, dev->device_data, return -ENXIO);
+	snd_timer_t *timer = dev->device_data;
 	snd_timer_t *timer1;
 	struct list_head *p;
 
@@ -865,7 +865,7 @@ int snd_timer_unregister(snd_timer_t *timer)
 
 static int snd_timer_dev_unregister(snd_device_t *device)
 {
-	snd_timer_t *timer = snd_magic_cast(snd_timer_t, device->device_data, return -ENXIO);
+	snd_timer_t *timer = device->device_data;
 	return snd_timer_unregister(timer);
 }
 
@@ -1018,7 +1018,7 @@ static int snd_timer_register_system(void)
 		return err;
 	strcpy(timer->name, "system timer");
 	timer->hw = snd_timer_system;
-	priv = (struct snd_timer_system_private *) snd_kcalloc(sizeof(struct snd_timer_system_private), GFP_KERNEL);
+	priv = kcalloc(1, sizeof(*priv), GFP_KERNEL);
 	if (priv == NULL) {
 		snd_timer_free(timer);
 		return -ENOMEM;
@@ -1086,7 +1086,7 @@ static void snd_timer_user_interrupt(snd_timer_instance_t *timeri,
 				     unsigned long resolution,
 				     unsigned long ticks)
 {
-	snd_timer_user_t *tu = snd_magic_cast(snd_timer_user_t, timeri->callback_data, return);
+	snd_timer_user_t *tu = timeri->callback_data;
 	snd_timer_read_t *r;
 	int prev;
 	
@@ -1129,7 +1129,7 @@ static void snd_timer_user_ccallback(snd_timer_instance_t *timeri,
 				     struct timespec *tstamp,
 				     unsigned long resolution)
 {
-	snd_timer_user_t *tu = snd_magic_cast(snd_timer_user_t, timeri->callback_data, return);
+	snd_timer_user_t *tu = timeri->callback_data;
 	snd_timer_tread_t r1;
 
 	if (event >= SNDRV_TIMER_EVENT_START && event <= SNDRV_TIMER_EVENT_PAUSE)
@@ -1148,7 +1148,7 @@ static void snd_timer_user_tinterrupt(snd_timer_instance_t *timeri,
 				      unsigned long resolution,
 				      unsigned long ticks)
 {
-	snd_timer_user_t *tu = snd_magic_cast(snd_timer_user_t, timeri->callback_data, return);
+	snd_timer_user_t *tu = timeri->callback_data;
 	snd_timer_tread_t *r, r1;
 	struct timespec tstamp;
 	int prev, append = 0;
@@ -1200,7 +1200,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file)
 {
 	snd_timer_user_t *tu;
 	
-	tu = snd_magic_kcalloc(snd_timer_user_t, 0, GFP_KERNEL);
+	tu = kcalloc(1, sizeof(*tu), GFP_KERNEL);
 	if (tu == NULL)
 		return -ENOMEM;
 	spin_lock_init(&tu->qlock);
@@ -1209,7 +1209,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file)
 	tu->queue_size = 128;
 	tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL);
 	if (tu->queue == NULL) {
-		snd_magic_kfree(tu);
+		kfree(tu);
 		return -ENOMEM;
 	}
 	file->private_data = tu;
@@ -1221,7 +1221,7 @@ static int snd_timer_user_release(struct inode *inode, struct file *file)
 	snd_timer_user_t *tu;
 
 	if (file->private_data) {
-		tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
+		tu = file->private_data;
 		file->private_data = NULL;
 		fasync_helper(-1, file, 0, &tu->fasync);
 		if (tu->timeri)
@@ -1230,7 +1230,7 @@ static int snd_timer_user_release(struct inode *inode, struct file *file)
 			kfree(tu->queue);
 		if (tu->tqueue)
 			kfree(tu->tqueue);
-		snd_magic_kfree(tu);
+		kfree(tu);
 	}
 	return 0;
 }
@@ -1449,7 +1449,7 @@ static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user *
 	char str[32];
 	int err;
 	
-	tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
+	tu = file->private_data;
 	if (tu->timeri)
 		snd_timer_close(tu->timeri);
 	if (copy_from_user(&tselect, _tselect, sizeof(tselect)))
@@ -1495,7 +1495,7 @@ static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info
 	snd_timer_info_t info;
 	snd_timer_t *t;
 
-	tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
+	tu = file->private_data;
 	snd_assert(tu->timeri != NULL, return -ENXIO);
 	t = tu->timeri->timer;
 	snd_assert(t != NULL, return -ENXIO);
@@ -1520,7 +1520,7 @@ static int snd_timer_user_params(struct file *file, snd_timer_params_t __user *_
 	snd_timer_tread_t *ttr;
 	int err;
 	
-	tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
+	tu = file->private_data;
 	snd_assert(tu->timeri != NULL, return -ENXIO);
 	t = tu->timeri->timer;
 	snd_assert(t != NULL, return -ENXIO);
@@ -1608,7 +1608,7 @@ static int snd_timer_user_status(struct file *file, snd_timer_status_t __user *_
 	snd_timer_user_t *tu;
 	snd_timer_status_t status;
 	
-	tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
+	tu = file->private_data;
 	snd_assert(tu->timeri != NULL, return -ENXIO);
 	memset(&status, 0, sizeof(status));
 	status.tstamp = tu->tstamp;
@@ -1628,7 +1628,7 @@ static int snd_timer_user_start(struct file *file)
 	int err;
 	snd_timer_user_t *tu;
 		
-	tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
+	tu = file->private_data;
 	snd_assert(tu->timeri != NULL, return -ENXIO);
 	snd_timer_stop(tu->timeri);
 	tu->timeri->lost = 0;
@@ -1641,7 +1641,7 @@ static int snd_timer_user_stop(struct file *file)
 	int err;
 	snd_timer_user_t *tu;
 		
-	tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
+	tu = file->private_data;
 	snd_assert(tu->timeri != NULL, return -ENXIO);
 	return (err = snd_timer_stop(tu->timeri)) < 0 ? err : 0;
 }
@@ -1651,20 +1651,20 @@ static int snd_timer_user_continue(struct file *file)
 	int err;
 	snd_timer_user_t *tu;
 		
-	tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
+	tu = file->private_data;
 	snd_assert(tu->timeri != NULL, return -ENXIO);
 	tu->timeri->lost = 0;
 	return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0;
 }
 
-static int snd_timer_user_ioctl(struct inode *inode, struct file *file,
-				unsigned int cmd, unsigned long arg)
+static inline int _snd_timer_user_ioctl(struct inode *inode, struct file *file,
+					unsigned int cmd, unsigned long arg)
 {
 	snd_timer_user_t *tu;
 	void __user *argp = (void __user *)arg;
 	int __user *p = argp;
 	
-	tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
+	tu = file->private_data;
 	switch (cmd) {
 	case SNDRV_TIMER_IOCTL_PVERSION:
 		return put_user(SNDRV_TIMER_VERSION, p) ? -EFAULT : 0;
@@ -1705,12 +1705,23 @@ static int snd_timer_user_ioctl(struct inode *inode, struct file *file,
 	return -ENOTTY;
 }
 
+/* FIXME: need to unlock BKL to allow preemption */
+static int snd_timer_user_ioctl(struct inode *inode, struct file * file,
+				unsigned int cmd, unsigned long arg)
+{
+	int err;
+	unlock_kernel();
+	err = _snd_timer_user_ioctl(inode, file, cmd, arg);
+	lock_kernel();
+	return err;
+}
+
 static int snd_timer_user_fasync(int fd, struct file * file, int on)
 {
 	snd_timer_user_t *tu;
 	int err;
 	
-	tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
+	tu = file->private_data;
 	err = fasync_helper(fd, file, on, &tu->fasync);
         if (err < 0)
 		return err;
@@ -1723,7 +1734,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, size_
 	long result = 0, unit;
 	int err = 0;
 	
-	tu = snd_magic_cast(snd_timer_user_t, file->private_data, return -ENXIO);
+	tu = file->private_data;
 	unit = tu->tread ? sizeof(snd_timer_tread_t) : sizeof(snd_timer_read_t);
 	spin_lock_irq(&tu->qlock);
 	while ((long)count - result >= unit) {
@@ -1785,7 +1796,7 @@ static unsigned int snd_timer_user_poll(struct file *file, poll_table * wait)
         unsigned int mask;
         snd_timer_user_t *tu;
 
-        tu = snd_magic_cast(snd_timer_user_t, file->private_data, return 0);
+        tu = file->private_data;
 
         poll_wait(file, &tu->qchange_sleep, wait);
 	
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index b6fba1a97..fb469d9d8 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -34,8 +34,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Dummy soundcard (/dev/null)");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ALSA,Dummy soundcard}}");
+MODULE_SUPPORTED_DEVICE("{{ALSA,Dummy soundcard}}");
 
 #define MAX_PCM_DEVICES		4
 #define MAX_PCM_SUBSTREAMS	16
@@ -133,22 +132,16 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for dummy soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for dummy soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable this dummy soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(pcm_devs, int, boot_devs, 0444);
 MODULE_PARM_DESC(pcm_devs, "PCM devices # (0-4) for dummy driver.");
-MODULE_PARM_SYNTAX(pcm_devs, SNDRV_ENABLED ",allows:{{0,4}},default:1,dialog:list");
 module_param_array(pcm_substreams, int, boot_devs, 0444);
 MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-16) for dummy driver.");
-MODULE_PARM_SYNTAX(pcm_substreams, SNDRV_ENABLED ",allows:{{1,16}},default:8,dialog:list");
 //module_param_array(midi_devs, int, boot_devs, 0444);
 //MODULE_PARM_DESC(midi_devs, "MIDI devices # (0-2) for dummy driver.");
-//MODULE_PARM_SYNTAX(midi_devs, SNDRV_ENABLED ",allows:{{0,2}},default:8,dialog:list");
 
 #define MIXER_ADDR_MASTER	0
 #define MIXER_ADDR_LINE		1
@@ -180,24 +173,10 @@ typedef struct snd_card_dummy_pcm {
 static snd_card_t *snd_dummy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
 
-static int snd_card_dummy_playback_ioctl(snd_pcm_substream_t * substream,
-				         unsigned int cmd,
-				         void *arg)
-{
-	return snd_pcm_lib_ioctl(substream, cmd, arg);
-}
-
-static int snd_card_dummy_capture_ioctl(snd_pcm_substream_t * substream,
-					unsigned int cmd,
-					void *arg)
-{
-	return snd_pcm_lib_ioctl(substream, cmd, arg);
-}
-
 static void snd_card_dummy_pcm_timer_start(snd_pcm_substream_t * substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_card_dummy_pcm_t *dpcm = snd_magic_cast(snd_card_dummy_pcm_t, runtime->private_data, return);
+	snd_card_dummy_pcm_t *dpcm = runtime->private_data;
 
 	dpcm->timer.expires = 1 + jiffies;
 	add_timer(&dpcm->timer);
@@ -206,7 +185,7 @@ static void snd_card_dummy_pcm_timer_start(snd_pcm_substream_t * substream)
 static void snd_card_dummy_pcm_timer_stop(snd_pcm_substream_t * substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_card_dummy_pcm_t *dpcm = snd_magic_cast(snd_card_dummy_pcm_t, runtime->private_data, return);
+	snd_card_dummy_pcm_t *dpcm = runtime->private_data;
 
 	del_timer(&dpcm->timer);
 }
@@ -240,7 +219,7 @@ static int snd_card_dummy_capture_trigger(snd_pcm_substream_t * substream,
 static int snd_card_dummy_pcm_prepare(snd_pcm_substream_t * substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_card_dummy_pcm_t *dpcm = snd_magic_cast(snd_card_dummy_pcm_t, runtime->private_data, return -ENXIO);
+	snd_card_dummy_pcm_t *dpcm = runtime->private_data;
 	unsigned int bps;
 
 	bps = runtime->rate * runtime->channels;
@@ -269,7 +248,7 @@ static int snd_card_dummy_capture_prepare(snd_pcm_substream_t * substream)
 
 static void snd_card_dummy_pcm_timer_function(unsigned long data)
 {
-	snd_card_dummy_pcm_t *dpcm = snd_magic_cast(snd_card_dummy_pcm_t, (void *)data, return);
+	snd_card_dummy_pcm_t *dpcm = (snd_card_dummy_pcm_t *)data;
 	
 	dpcm->timer.expires = 1 + jiffies;
 	add_timer(&dpcm->timer);
@@ -287,7 +266,7 @@ static void snd_card_dummy_pcm_timer_function(unsigned long data)
 static snd_pcm_uframes_t snd_card_dummy_playback_pointer(snd_pcm_substream_t * substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_card_dummy_pcm_t *dpcm = snd_magic_cast(snd_card_dummy_pcm_t, runtime->private_data, return -ENXIO);
+	snd_card_dummy_pcm_t *dpcm = runtime->private_data;
 
 	return bytes_to_frames(runtime, dpcm->pcm_buf_pos);
 }
@@ -295,7 +274,7 @@ static snd_pcm_uframes_t snd_card_dummy_playback_pointer(snd_pcm_substream_t * s
 static snd_pcm_uframes_t snd_card_dummy_capture_pointer(snd_pcm_substream_t * substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_card_dummy_pcm_t *dpcm = snd_magic_cast(snd_card_dummy_pcm_t, runtime->private_data, return -ENXIO);
+	snd_card_dummy_pcm_t *dpcm = runtime->private_data;
 
 	return bytes_to_frames(runtime, dpcm->pcm_buf_pos);
 }
@@ -338,8 +317,19 @@ static snd_pcm_hardware_t snd_card_dummy_capture =
 
 static void snd_card_dummy_runtime_free(snd_pcm_runtime_t *runtime)
 {
-	snd_card_dummy_pcm_t *dpcm = snd_magic_cast(snd_card_dummy_pcm_t, runtime->private_data, return);
-	snd_magic_kfree(dpcm);
+	snd_card_dummy_pcm_t *dpcm = runtime->private_data;
+	kfree(dpcm);
+}
+
+static int snd_card_dummy_hw_params(snd_pcm_substream_t * substream,
+				    snd_pcm_hw_params_t * hw_params)
+{
+	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+}
+
+static int snd_card_dummy_hw_free(snd_pcm_substream_t * substream)
+{
+	return snd_pcm_lib_free_pages(substream);
 }
 
 static int snd_card_dummy_playback_open(snd_pcm_substream_t * substream)
@@ -348,13 +338,9 @@ static int snd_card_dummy_playback_open(snd_pcm_substream_t * substream)
 	snd_card_dummy_pcm_t *dpcm;
 	int err;
 
-	dpcm = snd_magic_kcalloc(snd_card_dummy_pcm_t, 0, GFP_KERNEL);
+	dpcm = kcalloc(1, sizeof(*dpcm), GFP_KERNEL);
 	if (dpcm == NULL)
 		return -ENOMEM;
-	if ((runtime->dma_area = snd_malloc_pages_fallback(MAX_BUFFER_SIZE, GFP_KERNEL, &runtime->dma_bytes)) == NULL) {
-		snd_magic_kfree(dpcm);
-		return -ENOMEM;
-	}
 	init_timer(&dpcm->timer);
 	dpcm->timer.data = (unsigned long) dpcm;
 	dpcm->timer.function = snd_card_dummy_pcm_timer_function;
@@ -370,7 +356,7 @@ static int snd_card_dummy_playback_open(snd_pcm_substream_t * substream)
 	if (substream->pcm->device & 2)
 		runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID);
 	if ((err = add_playback_constraints(runtime)) < 0) {
-		snd_magic_kfree(dpcm);
+		kfree(dpcm);
 		return err;
 	}
 
@@ -383,14 +369,9 @@ static int snd_card_dummy_capture_open(snd_pcm_substream_t * substream)
 	snd_card_dummy_pcm_t *dpcm;
 	int err;
 
-	dpcm = snd_magic_kcalloc(snd_card_dummy_pcm_t, 0, GFP_KERNEL);
+	dpcm = kcalloc(1, sizeof(*dpcm), GFP_KERNEL);
 	if (dpcm == NULL)
 		return -ENOMEM;
-	if ((runtime->dma_area = snd_malloc_pages_fallback(MAX_BUFFER_SIZE, GFP_KERNEL, &runtime->dma_bytes)) == NULL) {
-		snd_magic_kfree(dpcm);
-		return -ENOMEM;
-	}
-	memset(runtime->dma_area, 0, runtime->dma_bytes);
 	init_timer(&dpcm->timer);
 	dpcm->timer.data = (unsigned long) dpcm;
 	dpcm->timer.function = snd_card_dummy_pcm_timer_function;
@@ -406,7 +387,7 @@ static int snd_card_dummy_capture_open(snd_pcm_substream_t * substream)
 	if (substream->pcm->device & 2)
 		runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID);
 	if ((err = add_capture_constraints(runtime)) < 0) {
-		snd_magic_kfree(dpcm);
+		kfree(dpcm);
 		return err;
 	}
 
@@ -415,24 +396,20 @@ static int snd_card_dummy_capture_open(snd_pcm_substream_t * substream)
 
 static int snd_card_dummy_playback_close(snd_pcm_substream_t * substream)
 {
-	snd_pcm_runtime_t *runtime = substream->runtime;
-
-	snd_free_pages(runtime->dma_area, runtime->dma_bytes);
 	return 0;
 }
 
 static int snd_card_dummy_capture_close(snd_pcm_substream_t * substream)
 {
-	snd_pcm_runtime_t *runtime = substream->runtime;
-
-	snd_free_pages(runtime->dma_area, runtime->dma_bytes);
 	return 0;
 }
 
 static snd_pcm_ops_t snd_card_dummy_playback_ops = {
 	.open =			snd_card_dummy_playback_open,
 	.close =		snd_card_dummy_playback_close,
-	.ioctl =		snd_card_dummy_playback_ioctl,
+	.ioctl =		snd_pcm_lib_ioctl,
+	.hw_params =		snd_card_dummy_hw_params,
+	.hw_free =		snd_card_dummy_hw_free,
 	.prepare =		snd_card_dummy_playback_prepare,
 	.trigger =		snd_card_dummy_playback_trigger,
 	.pointer =		snd_card_dummy_playback_pointer,
@@ -441,7 +418,9 @@ static snd_pcm_ops_t snd_card_dummy_playback_ops = {
 static snd_pcm_ops_t snd_card_dummy_capture_ops = {
 	.open =			snd_card_dummy_capture_open,
 	.close =		snd_card_dummy_capture_close,
-	.ioctl =		snd_card_dummy_capture_ioctl,
+	.ioctl =		snd_pcm_lib_ioctl,
+	.hw_params =		snd_card_dummy_hw_params,
+	.hw_free =		snd_card_dummy_hw_free,
 	.prepare =		snd_card_dummy_capture_prepare,
 	.trigger =		snd_card_dummy_capture_trigger,
 	.pointer =		snd_card_dummy_capture_pointer,
@@ -459,6 +438,9 @@ static int __init snd_card_dummy_pcm(snd_card_dummy_t *dummy, int device, int su
 	pcm->private_data = dummy;
 	pcm->info_flags = 0;
 	strcpy(pcm->name, "Dummy PCM");
+	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+					      snd_dma_continuous_data(GFP_KERNEL),
+					      0, 64*1024);
 	return 0;
 }
 
@@ -479,7 +461,7 @@ static int snd_dummy_volume_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t
  
 static int snd_dummy_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	snd_card_dummy_t *dummy = _snd_kcontrol_chip(kcontrol);
+	snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol);
 	unsigned long flags;
 	int addr = kcontrol->private_value;
 
@@ -488,11 +470,11 @@ static int snd_dummy_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 	ucontrol->value.integer.value[1] = dummy->mixer_volume[addr][1];
 	spin_unlock_irqrestore(&dummy->mixer_lock, flags);
 	return 0;
-}                                                                                                                                                                                                                                                                                                            
+}
 
 static int snd_dummy_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	snd_card_dummy_t *dummy = _snd_kcontrol_chip(kcontrol);
+	snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol);
 	unsigned long flags;
 	int change, addr = kcontrol->private_value;
 	int left, right;
@@ -514,7 +496,7 @@ static int snd_dummy_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 	dummy->mixer_volume[addr][1] = right;
 	spin_unlock_irqrestore(&dummy->mixer_lock, flags);
 	return change;
-}                                                                                                                                                                                                                                                                                                            
+}
 
 #define DUMMY_CAPSRC(xname, xindex, addr) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
@@ -533,7 +515,7 @@ static int snd_dummy_capsrc_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t
  
 static int snd_dummy_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	snd_card_dummy_t *dummy = _snd_kcontrol_chip(kcontrol);
+	snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol);
 	unsigned long flags;
 	int addr = kcontrol->private_value;
 
@@ -546,7 +528,7 @@ static int snd_dummy_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 
 static int snd_dummy_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	snd_card_dummy_t *dummy = _snd_kcontrol_chip(kcontrol);
+	snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol);
 	unsigned long flags;
 	int change, addr = kcontrol->private_value;
 	int left, right;
@@ -560,9 +542,7 @@ static int snd_dummy_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 	dummy->capture_source[addr][1] = right;
 	spin_unlock_irqrestore(&dummy->mixer_lock, flags);
 	return change;
-}                                                                                                                                                                                                                                                                                                            
-
-#define DUMMY_CONTROLS (sizeof(snd_dummy_controls)/sizeof(snd_kcontrol_new_t))
+}
 
 static snd_kcontrol_new_t snd_dummy_controls[] = {
 DUMMY_VOLUME("Master Volume", 0, MIXER_ADDR_MASTER),
@@ -587,7 +567,7 @@ int __init snd_card_dummy_new_mixer(snd_card_dummy_t * dummy)
 	spin_lock_init(&dummy->mixer_lock);
 	strcpy(card->mixername, "Dummy Mixer");
 
-	for (idx = 0; idx < DUMMY_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_dummy_controls); idx++) {
 		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_dummy_controls[idx], dummy))) < 0)
 			return err;
 	}
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
index 4b0025030..adc12bb91 100644
--- a/sound/drivers/mpu401/mpu401.c
+++ b/sound/drivers/mpu401/mpu401.c
@@ -28,7 +28,7 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #ifdef CONFIG_ACPI_BUS
-#include <acpi/acpi_bus.h>
+#include <linux/acpi.h>
 #endif
 #include <linux/moduleparam.h>
 #include <sound/core.h>
@@ -42,7 +42,6 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("MPU-401 UART");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -56,24 +55,18 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for MPU-401 device.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for MPU-401 device.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable MPU-401 device.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 #ifdef USE_ACPI_PNP
 module_param_array(acpipnp, bool, boot_devs, 0444);
 MODULE_PARM_DESC(acpipnp, "ACPI PnP detection for MPU-401 device.");
-MODULE_PARM_SYNTAX(acpipnp, SNDRV_ENABLED "," SNDRV_BOOLEAN_TRUE_DESC);
 #endif
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for MPU-401 device.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 
 #ifndef CONFIG_ACPI_BUS
 struct acpi_device;
@@ -98,13 +91,9 @@ static acpi_status __devinit snd_mpu401_acpi_resource(struct acpi_resource *res,
 
 	if (res->id == ACPI_RSTYPE_IRQ) {
 		if (res->data.irq.number_of_interrupts > 0) {
-#ifdef CONFIG_IA64
-			resources->irq = acpi_register_irq(res->data.irq.interrupts[0],
-							   res->data.irq.active_high_low,
-							   res->data.irq.edge_level);
-#else
-			resources->irq = res->data.irq.interrupts[0];
-#endif
+			resources->irq = acpi_register_gsi(res->data.irq.interrupts[0],
+							   res->data.irq.edge_level,
+							   res->data.irq.active_high_low);
 		}
 	} else if (res->id == ACPI_RSTYPE_IO) {
 		if (res->data.io.range_length >= 2) {
@@ -175,7 +164,7 @@ static int __devinit snd_card_mpu401_probe(int dev, struct acpi_device *device)
 	}
 #ifdef USE_ACPI_PNP
 	if (device) {
-		strcat(card->longname, ", bus id ");
+		strcat(card->longname, ", ACPI id ");
 		strlcat(card->longname, acpi_device_bid(device), sizeof(card->longname));
 	}
 #endif
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index 5d26ccf25..0e15942dd 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -123,7 +123,7 @@ static void _snd_mpu401_uart_interrupt(mpu401_t *mpu)
  */
 irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	mpu401_t *mpu = snd_magic_cast(mpu401_t, dev_id, return IRQ_NONE);
+	mpu401_t *mpu = dev_id;
 	
 	if (mpu == NULL)
 		return IRQ_NONE;
@@ -137,7 +137,7 @@ irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *reg
  */
 static void snd_mpu401_uart_timer(unsigned long data)
 {
-	mpu401_t *mpu = snd_magic_cast(mpu401_t, (void *)data, return);
+	mpu401_t *mpu = (mpu401_t *)data;
 
 	spin_lock(&mpu->timer_lock);
 	/*mpu->mode |= MPU401_MODE_TIMER;*/
@@ -235,7 +235,7 @@ static int snd_mpu401_uart_input_open(snd_rawmidi_substream_t * substream)
 	mpu401_t *mpu;
 	int err;
 
-	mpu = snd_magic_cast(mpu401_t, substream->rmidi->private_data, return -ENXIO);
+	mpu = substream->rmidi->private_data;
 	if (mpu->open_input && (err = mpu->open_input(mpu)) < 0)
 		return err;
 	if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) {
@@ -253,7 +253,7 @@ static int snd_mpu401_uart_output_open(snd_rawmidi_substream_t * substream)
 	mpu401_t *mpu;
 	int err;
 
-	mpu = snd_magic_cast(mpu401_t, substream->rmidi->private_data, return -ENXIO);
+	mpu = substream->rmidi->private_data;
 	if (mpu->open_output && (err = mpu->open_output(mpu)) < 0)
 		return err;
 	if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
@@ -270,7 +270,7 @@ static int snd_mpu401_uart_input_close(snd_rawmidi_substream_t * substream)
 {
 	mpu401_t *mpu;
 
-	mpu = snd_magic_cast(mpu401_t, substream->rmidi->private_data, return -ENXIO);
+	mpu = substream->rmidi->private_data;
 	clear_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
 	mpu->substream_input = NULL;
 	if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode))
@@ -284,7 +284,7 @@ static int snd_mpu401_uart_output_close(snd_rawmidi_substream_t * substream)
 {
 	mpu401_t *mpu;
 
-	mpu = snd_magic_cast(mpu401_t, substream->rmidi->private_data, return -ENXIO);
+	mpu = substream->rmidi->private_data;
 	clear_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
 	mpu->substream_output = NULL;
 	if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode))
@@ -303,7 +303,7 @@ static void snd_mpu401_uart_input_trigger(snd_rawmidi_substream_t * substream, i
 	mpu401_t *mpu;
 	int max = 64;
 
-	mpu = snd_magic_cast(mpu401_t, substream->rmidi->private_data, return);
+	mpu = substream->rmidi->private_data;
 	if (up) {
 		if (! test_and_set_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) {
 			/* first time - flush FIFO */
@@ -394,7 +394,7 @@ static void snd_mpu401_uart_output_trigger(snd_rawmidi_substream_t * substream,
 	unsigned long flags;
 	mpu401_t *mpu;
 
-	mpu = snd_magic_cast(mpu401_t, substream->rmidi->private_data, return);
+	mpu = substream->rmidi->private_data;
 	if (up) {
 		set_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
 
@@ -441,14 +441,14 @@ static snd_rawmidi_ops_t snd_mpu401_uart_input =
 
 static void snd_mpu401_uart_free(snd_rawmidi_t *rmidi)
 {
-	mpu401_t *mpu = snd_magic_cast(mpu401_t, rmidi->private_data, return);
+	mpu401_t *mpu = rmidi->private_data;
 	if (mpu->irq_flags && mpu->irq >= 0)
 		free_irq(mpu->irq, (void *) mpu);
 	if (mpu->res) {
 		release_resource(mpu->res);
 		kfree_nocheck(mpu->res);
 	}
-	snd_magic_kfree(mpu);
+	kfree(mpu);
 }
 
 /**
@@ -484,7 +484,7 @@ int snd_mpu401_uart_new(snd_card_t * card, int device,
 		*rrawmidi = NULL;
 	if ((err = snd_rawmidi_new(card, "MPU-401U", device, 1, 1, &rmidi)) < 0)
 		return err;
-	mpu = snd_magic_kcalloc(mpu401_t, 0, GFP_KERNEL);
+	mpu = kcalloc(1, sizeof(*mpu), GFP_KERNEL);
 	if (mpu == NULL) {
 		snd_device_free(card, rmidi);
 		return -ENOMEM;
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
index d6529a444..2c572345c 100644
--- a/sound/drivers/mtpav.c
+++ b/sound/drivers/mtpav.c
@@ -69,8 +69,7 @@
 MODULE_AUTHOR("Michael T. Mayers");
 MODULE_DESCRIPTION("MOTU MidiTimePiece AV multiport MIDI");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{MOTU,MidiTimePiece AV multiport MIDI}}");
+MODULE_SUPPORTED_DEVICE("{{MOTU,MidiTimePiece AV multiport MIDI}}");
 
 // io resources
 #define MTPAV_IOBASE		0x378
@@ -85,19 +84,14 @@ static int hwports = MTPAV_MAX_PORTS;	/* use hardware ports 1-8 */
 
 module_param(index, int, 0444);
 MODULE_PARM_DESC(index, "Index value for MotuMTPAV MIDI.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param(id, charp, 0444);
 MODULE_PARM_DESC(id, "ID string for MotuMTPAV MIDI.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param(port, long, 0444);
 MODULE_PARM_DESC(port, "Parallel port # for MotuMTPAV MIDI.");
-MODULE_PARM_SYNTAX(port, SNDRV_ENABLED ",allows:{{0x378},{0x278}},dialog:list");
 module_param(irq, int, 0444);
 MODULE_PARM_DESC(irq, "Parallel IRQ # for MotuMTPAV MIDI.");
-MODULE_PARM_SYNTAX(irq,  SNDRV_ENABLED ",allows:{{7},{5}},dialog:list");
 module_param(hwports, int, 0444);
 MODULE_PARM_DESC(hwports, "Hardware ports # for MotuMTPAV MIDI.");
-MODULE_PARM_SYNTAX(hwports, SNDRV_ENABLED ",allows:{{1,8}},dialog:list");
 
 /*
  *      defines
@@ -419,7 +413,7 @@ static void snd_mtpav_input_trigger(snd_rawmidi_substream_t * substream, int up)
 
 static void snd_mtpav_output_timer(unsigned long data)
 {
-	mtpav_t *chip = snd_magic_cast(mtpav_t, (void *)data, return);
+	mtpav_t *chip = (mtpav_t *)data;
 	int p;
 
 	spin_lock(&chip->spinlock);
@@ -587,7 +581,7 @@ static void snd_mtpav_read_bytes(mtpav_t * mcrd)
 
 static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id, struct pt_regs *regs)
 {
-	mtpav_t *mcard = snd_magic_cast(mtpav_t, dev_id, return IRQ_NONE);
+	mtpav_t *mcard = dev_id;
 
 	//printk("irqh()\n");
 	spin_lock(&mcard->spinlock);
@@ -695,7 +689,7 @@ static int snd_mtpav_get_RAWMIDI(mtpav_t * mcard)
 
 static mtpav_t *new_mtpav(void)
 {
-	mtpav_t *ncrd = (mtpav_t *) snd_magic_kcalloc(mtpav_t, 0, GFP_KERNEL);
+	mtpav_t *ncrd = kcalloc(1, sizeof(*ncrd), GFP_KERNEL);
 	if (ncrd != NULL) {
 		spin_lock_init(&ncrd->spinlock);
 
@@ -728,7 +722,7 @@ static void free_mtpav(mtpav_t * crd)
 		release_resource(crd->res_port);
 		kfree_nocheck(crd->res_port);
 	}
-	snd_magic_kfree(crd);
+	kfree(crd);
 }
 
 /*
diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c
index 965ffd050..e2315afa6 100644
--- a/sound/drivers/opl3/opl3_lib.c
+++ b/sound/drivers/opl3/opl3_lib.c
@@ -35,8 +35,6 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Hannu Savolainen 1993-1996, Rob
 MODULE_DESCRIPTION("Routines for control of AdLib FM cards (OPL2/OPL3/OPL4 chips)");
 MODULE_LICENSE("GPL");
 
-#define chip_t opl3_t
-
 extern char snd_opl3_regmap[MAX_OPL2_VOICES][4];
 
 void snd_opl2_command(opl3_t * opl3, unsigned short cmd, unsigned char val)
@@ -322,7 +320,7 @@ void snd_opl3_interrupt(snd_hwdep_t * hw)
 	if (hw == NULL)
 		return;
 
-	opl3 = snd_magic_cast(opl3_t, hw->private_data, return);
+	opl3 = hw->private_data;
 	status = inb(opl3->l_port);
 #if 0
 	snd_printk("AdLib IRQ status = 0x%x\n", status);
@@ -354,13 +352,13 @@ static int snd_opl3_free(opl3_t *opl3)
 		release_resource(opl3->res_r_port);
 		kfree_nocheck(opl3->res_r_port);
 	}
-	snd_magic_kfree(opl3);
+	kfree(opl3);
 	return 0;
 }
 
 static int snd_opl3_dev_free(snd_device_t *device)
 {
-	opl3_t *opl3 = snd_magic_cast(opl3_t, device->device_data, return -ENXIO);
+	opl3_t *opl3 = device->device_data;
 	return snd_opl3_free(opl3);
 }
 
@@ -379,7 +377,7 @@ int snd_opl3_create(snd_card_t * card,
 
 	*ropl3 = NULL;
 
-	opl3 = snd_magic_kcalloc(opl3_t, 0, GFP_KERNEL);
+	opl3 = kcalloc(1, sizeof(*opl3), GFP_KERNEL);
 	if (opl3 == NULL)
 		return -ENOMEM;
 
diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c
index 5862fa29a..ebec070a8 100644
--- a/sound/drivers/opl3/opl3_midi.c
+++ b/sound/drivers/opl3/opl3_midi.c
@@ -313,7 +313,7 @@ void snd_opl3_note_on(void *p, int note, int vel, snd_midi_channel_t *chan)
 	fm_instrument_t *fm;
 	unsigned long flags;
 
-	opl3 = snd_magic_cast(opl3_t, p, return);
+	opl3 = p;
 
 #ifdef DEBUG_MIDI
 	snd_printk("Note on, ch %i, inst %i, note %i, vel %i\n",
@@ -672,7 +672,7 @@ void snd_opl3_note_off(void *p, int note, int vel, snd_midi_channel_t *chan)
 
 	unsigned long flags;
 
-	opl3 = snd_magic_cast(opl3_t, p, return);
+	opl3 = p;
 
 #ifdef DEBUG_MIDI
 	snd_printk("Note off, ch %i, inst %i, note %i\n",
@@ -712,7 +712,7 @@ void snd_opl3_key_press(void *p, int note, int vel, snd_midi_channel_t *chan)
 {
   	opl3_t *opl3;
 
-	opl3 = snd_magic_cast(opl3_t, p, return);
+	opl3 = p;
 #ifdef DEBUG_MIDI
 	snd_printk("Key pressure, ch#: %i, inst#: %i\n",
 		   chan->number, chan->midi_program);
@@ -726,7 +726,7 @@ void snd_opl3_terminate_note(void *p, int note, snd_midi_channel_t *chan)
 {
   	opl3_t *opl3;
 
-	opl3 = snd_magic_cast(opl3_t, p, return);
+	opl3 = p;
 #ifdef DEBUG_MIDI
 	snd_printk("Terminate note, ch#: %i, inst#: %i\n",
 		   chan->number, chan->midi_program);
@@ -814,7 +814,7 @@ void snd_opl3_control(void *p, int type, snd_midi_channel_t *chan)
 {
   	opl3_t *opl3;
 
-	opl3 = snd_magic_cast(opl3_t, p, return);
+	opl3 = p;
 #ifdef DEBUG_MIDI
 	snd_printk("Controller, TYPE = %i, ch#: %i, inst#: %i\n",
 		   type, chan->number, chan->midi_program);
@@ -851,7 +851,7 @@ void snd_opl3_nrpn(void *p, snd_midi_channel_t *chan,
 {
   	opl3_t *opl3;
 
-	opl3 = snd_magic_cast(opl3_t, p, return);
+	opl3 = p;
 #ifdef DEBUG_MIDI
 	snd_printk("NRPN, ch#: %i, inst#: %i\n",
 		   chan->number, chan->midi_program);
@@ -866,7 +866,7 @@ void snd_opl3_sysex(void *p, unsigned char *buf, int len,
 {
   	opl3_t *opl3;
 
-	opl3 = snd_magic_cast(opl3_t, p, return);
+	opl3 = p;
 #ifdef DEBUG_MIDI
 	snd_printk("SYSEX\n");
 #endif
diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c
index d3193b03e..33da334ae 100644
--- a/sound/drivers/opl3/opl3_oss.c
+++ b/sound/drivers/opl3/opl3_oss.c
@@ -57,7 +57,7 @@ static snd_seq_oss_callback_t oss_callback = {
 static int snd_opl3_oss_event_input(snd_seq_event_t *ev, int direct,
 				    void *private_data, int atomic, int hop)
 {
-	opl3_t *opl3 = snd_magic_cast(opl3_t, private_data, return -EINVAL);
+	opl3_t *opl3 = private_data;
 
 	if (ev->type != SNDRV_SEQ_EVENT_OSS)
 		snd_midi_process_event(&opl3_ops, ev, opl3->oss_chset);
@@ -68,7 +68,7 @@ static int snd_opl3_oss_event_input(snd_seq_event_t *ev, int direct,
 
 static void snd_opl3_oss_free_port(void *private_data)
 {
-	opl3_t *opl3 = snd_magic_cast(opl3_t, private_data, return);
+	opl3_t *opl3 = private_data;
 
 	snd_midi_channel_free_set(opl3->oss_chset);
 }
@@ -156,7 +156,7 @@ void snd_opl3_free_seq_oss(opl3_t *opl3)
 /* open OSS sequencer */
 static int snd_opl3_open_seq_oss(snd_seq_oss_arg_t *arg, void *closure)
 {
-	opl3_t *opl3 = snd_magic_cast(opl3_t, closure, return -EINVAL);
+	opl3_t *opl3 = closure;
 	int err;
 
 	snd_assert(arg != NULL, return -ENXIO);
@@ -182,7 +182,7 @@ static int snd_opl3_close_seq_oss(snd_seq_oss_arg_t *arg)
 	opl3_t *opl3;
 
 	snd_assert(arg != NULL, return -ENXIO);
-	opl3 = snd_magic_cast(opl3_t, arg->private_data, return -EINVAL);
+	opl3 = arg->private_data;
 
 	snd_opl3_synth_cleanup(opl3);
 
@@ -213,7 +213,7 @@ static int snd_opl3_load_patch_seq_oss(snd_seq_oss_arg_t *arg, int format,
 	int err = -EINVAL;
 
 	snd_assert(arg != NULL, return -ENXIO);
-	opl3 = snd_magic_cast(opl3_t, arg->private_data, return -EINVAL);
+	opl3 = arg->private_data;
 
 	if ((format == FM_PATCH) || (format == OPL3_PATCH)) {
 		struct sbi_instrument sbi;
@@ -241,7 +241,7 @@ static int snd_opl3_load_patch_seq_oss(snd_seq_oss_arg_t *arg, int format,
 		}
 
 		size = sizeof(*put) + sizeof(fm_xinstrument_t);
-		put = (snd_seq_instr_header_t *)snd_kcalloc(size, GFP_KERNEL);
+		put = kcalloc(1, size, GFP_KERNEL);
 		if (put == NULL)
 			return -ENOMEM;
 		/* build header */
@@ -325,7 +325,7 @@ static int snd_opl3_ioctl_seq_oss(snd_seq_oss_arg_t *arg, unsigned int cmd,
 	opl3_t *opl3;
 
 	snd_assert(arg != NULL, return -ENXIO);
-	opl3 = snd_magic_cast(opl3_t, arg->private_data, return -EINVAL);
+	opl3 = arg->private_data;
 	switch (cmd) {
 		case SNDCTL_FM_LOAD_INSTR:
 			snd_printk("OPL3: Obsolete ioctl(SNDCTL_FM_LOAD_INSTR) used. Fix the program.\n");
@@ -350,7 +350,7 @@ static int snd_opl3_reset_seq_oss(snd_seq_oss_arg_t *arg)
 	opl3_t *opl3;
 
 	snd_assert(arg != NULL, return -ENXIO);
-	opl3 = snd_magic_cast(opl3_t, arg->private_data, return -EINVAL);
+	opl3 = arg->private_data;
 
 	return 0;
 }
diff --git a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c
index c6953b89c..048b33ac5 100644
--- a/sound/drivers/opl3/opl3_seq.c
+++ b/sound/drivers/opl3/opl3_seq.c
@@ -30,7 +30,6 @@
 MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("ALSA driver for OPL3 FM synth");
-MODULE_CLASSES("{sound}");
 
 int use_internal_drums = 0;
 module_param(use_internal_drums, bool, 0444);
@@ -99,7 +98,7 @@ void snd_opl3_synth_cleanup(opl3_t * opl3)
 
 int snd_opl3_synth_use(void *private_data, snd_seq_port_subscribe_t * info)
 {
-	opl3_t *opl3 = snd_magic_cast(opl3_t, private_data, return -ENXIO);
+	opl3_t *opl3 = private_data;
 	int err;
 
 	if ((err = snd_opl3_synth_setup(opl3)) < 0)
@@ -126,7 +125,7 @@ int snd_opl3_synth_use(void *private_data, snd_seq_port_subscribe_t * info)
 
 int snd_opl3_synth_unuse(void *private_data, snd_seq_port_subscribe_t * info)
 {
-	opl3_t *opl3 = snd_magic_cast(opl3_t, private_data, return -ENXIO);
+	opl3_t *opl3 = private_data;
 
 	snd_opl3_synth_cleanup(opl3);
 
@@ -151,7 +150,7 @@ snd_midi_op_t opl3_ops = {
 static int snd_opl3_synth_event_input(snd_seq_event_t * ev, int direct,
 				      void *private_data, int atomic, int hop)
 {
-	opl3_t *opl3 = snd_magic_cast(opl3_t, private_data, return -EINVAL);
+	opl3_t *opl3 = private_data;
 
 	if (ev->type >= SNDRV_SEQ_EVENT_INSTR_BEGIN &&
 	    ev->type <= SNDRV_SEQ_EVENT_INSTR_CHANGE) {
@@ -169,7 +168,7 @@ static int snd_opl3_synth_event_input(snd_seq_event_t * ev, int direct,
 
 static void snd_opl3_synth_free_port(void *private_data)
 {
-	opl3_t *opl3 = snd_magic_cast(opl3_t, private_data, return);
+	opl3_t *opl3 = private_data;
 
 	snd_midi_channel_free_set(opl3->chset);
 }
diff --git a/sound/drivers/opl3/opl3_synth.c b/sound/drivers/opl3/opl3_synth.c
index 1e6472e3b..04f9f955e 100644
--- a/sound/drivers/opl3/opl3_synth.c
+++ b/sound/drivers/opl3/opl3_synth.c
@@ -74,7 +74,7 @@ static int snd_opl3_set_connection(opl3_t * opl3, int connection);
  */
 int snd_opl3_open(snd_hwdep_t * hw, struct file *file)
 {
-	opl3_t *opl3 = snd_magic_cast(opl3_t, hw->private_data, return -ENXIO);
+	opl3_t *opl3 = hw->private_data;
 
 	down(&opl3->access_mutex);
 	if (opl3->used) {
@@ -93,7 +93,7 @@ int snd_opl3_open(snd_hwdep_t * hw, struct file *file)
 int snd_opl3_ioctl(snd_hwdep_t * hw, struct file *file,
 		   unsigned int cmd, unsigned long arg)
 {
-	opl3_t *opl3 = snd_magic_cast(opl3_t, hw->private_data, return -ENXIO);
+	opl3_t *opl3 = hw->private_data;
 	void __user *argp = (void __user *)arg;
 
 	snd_assert(opl3 != NULL, return -EINVAL);
@@ -176,7 +176,7 @@ int snd_opl3_ioctl(snd_hwdep_t * hw, struct file *file,
  */
 int snd_opl3_release(snd_hwdep_t * hw, struct file *file)
 {
-	opl3_t *opl3 = snd_magic_cast(opl3_t, hw->private_data, return -ENXIO);
+	opl3_t *opl3 = hw->private_data;
 
 	snd_opl3_reset(opl3);
 	down(&opl3->access_mutex);
diff --git a/sound/drivers/opl4/Makefile b/sound/drivers/opl4/Makefile
index 45896fade..141aacbaf 100644
--- a/sound/drivers/opl4/Makefile
+++ b/sound/drivers/opl4/Makefile
@@ -15,4 +15,4 @@ snd-opl4-synth-objs := opl4_seq.o opl4_synth.o yrw801.o
 sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1)))
 
 obj-$(CONFIG_SND_OPL4_LIB) += snd-opl4-lib.o
-obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-opl4-synth.o
\ No newline at end of file
+obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-opl4-synth.o
diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c
index a361364bb..5ede4281c 100644
--- a/sound/drivers/opl4/opl4_lib.c
+++ b/sound/drivers/opl4/opl4_lib.c
@@ -26,7 +26,6 @@
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
 MODULE_DESCRIPTION("OPL4 driver");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 
 static void inline snd_opl4_wait(opl4_t *opl4)
 {
@@ -37,62 +36,68 @@ static void inline snd_opl4_wait(opl4_t *opl4)
 
 void snd_opl4_write(opl4_t *opl4, u8 reg, u8 value)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&opl4->reg_lock, flags);
-
 	snd_opl4_wait(opl4);
 	outb(reg, opl4->pcm_port);
 
 	snd_opl4_wait(opl4);
 	outb(value, opl4->pcm_port + 1);
-
-	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 u8 snd_opl4_read(opl4_t *opl4, u8 reg)
 {
-	unsigned long flags;
-	u8 value;
-
-	spin_lock_irqsave(&opl4->reg_lock, flags);
-
 	snd_opl4_wait(opl4);
 	outb(reg, opl4->pcm_port);
 
 	snd_opl4_wait(opl4);
-	value = inb(opl4->pcm_port + 1);
-
-	spin_unlock_irqrestore(&opl4->reg_lock, flags);
-	return value;
+	return inb(opl4->pcm_port + 1);
 }
 
 void snd_opl4_read_memory(opl4_t *opl4, char *buf, int offset, int size)
 {
-	u8 memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
+	unsigned long flags;
+	u8 memcfg;
+
+	spin_lock_irqsave(&opl4->reg_lock, flags);
+
+	memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
 	snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT);
 
 	snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_HIGH, offset >> 16);
 	snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_MID, offset >> 8);
 	snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_LOW, offset);
-	for (; size > 0; size--)
-		*buf++ = snd_opl4_read(opl4, OPL4_REG_MEMORY_DATA);
+
+	snd_opl4_wait(opl4);
+	outb(OPL4_REG_MEMORY_DATA, opl4->pcm_port);
+	snd_opl4_wait(opl4);
+	insb(opl4->pcm_port + 1, buf, size);
 
 	snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg);
+
+	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 void snd_opl4_write_memory(opl4_t *opl4, const char *buf, int offset, int size)
 {
-	u8 memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
+	unsigned long flags;
+	u8 memcfg;
+
+	spin_lock_irqsave(&opl4->reg_lock, flags);
+
+	memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
 	snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT);
 
 	snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_HIGH, offset >> 16);
 	snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_MID, offset >> 8);
 	snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_LOW, offset);
-	for (; size > 0; size--)
-		snd_opl4_write(opl4, OPL4_REG_MEMORY_DATA, *buf++);
+
+	snd_opl4_wait(opl4);
+	outb(OPL4_REG_MEMORY_DATA, opl4->pcm_port);
+	snd_opl4_wait(opl4);
+	outsb(opl4->pcm_port + 1, buf, size);
 
 	snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg);
+
+	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 static void snd_opl4_enable_opl4(opl4_t *opl4)
@@ -141,7 +146,7 @@ static int snd_opl4_detect(opl4_t *opl4)
 #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
 static void snd_opl4_seq_dev_free(snd_seq_device_t *seq_dev)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, seq_dev->private_data, return);
+	opl4_t *opl4 = seq_dev->private_data;
 	opl4->seq_dev = NULL;
 }
 
@@ -172,12 +177,12 @@ static void snd_opl4_free(opl4_t *opl4)
 		release_resource(opl4->res_pcm_port);
 		kfree_nocheck(opl4->res_pcm_port);
 	}
-	snd_magic_kfree(opl4);
+	kfree(opl4);
 }
 
 static int snd_opl4_dev_free(snd_device_t *device)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, device->device_data, return -ENXIO);
+	opl4_t *opl4 = device->device_data;
 	snd_opl4_free(opl4);
 	return 0;
 }
@@ -199,7 +204,7 @@ int snd_opl4_create(snd_card_t *card,
 	if (ropl4)
 		*ropl4 = NULL;
 
-	opl4 = snd_magic_kcalloc(opl4_t, 0, GFP_KERNEL);
+	opl4 = kcalloc(1, sizeof(*opl4), GFP_KERNEL);
 	if (!opl4)
 		return -ENOMEM;
 
@@ -231,7 +236,7 @@ int snd_opl4_create(snd_card_t *card,
 	}
 
 	/* opl3 initialization disabled opl4, so reenable */
-	snd_opl4_enable_opl4(opl4); 
+	snd_opl4_enable_opl4(opl4);
 
 	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, opl4, &ops);
 	if (err < 0) {
diff --git a/sound/drivers/opl4/opl4_local.h b/sound/drivers/opl4/opl4_local.h
index e7a601abc..c45568084 100644
--- a/sound/drivers/opl4/opl4_local.h
+++ b/sound/drivers/opl4/opl4_local.h
@@ -195,7 +195,6 @@ struct opl4 {
 	opl4_voice_t voices[OPL4_MAX_VOICES];
 	struct list_head off_voices;
 	struct list_head on_voices;
-	spinlock_t voices_lock;
 #endif
 };
 
diff --git a/sound/drivers/opl4/opl4_mixer.c b/sound/drivers/opl4/opl4_mixer.c
index 1e15482c0..ec7a228fb 100644
--- a/sound/drivers/opl4/opl4_mixer.c
+++ b/sound/drivers/opl4/opl4_mixer.c
@@ -20,8 +20,6 @@
 #include "opl4_local.h"
 #include <sound/control.h>
 
-#define chip_t opl4_t
-
 static int snd_opl4_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -34,10 +32,13 @@ static int snd_opl4_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinf
 static int snd_opl4_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	opl4_t *opl4 = snd_kcontrol_chip(kcontrol);
+	unsigned long flags;
 	u8 reg = kcontrol->private_value;
 	u8 value;
 
+	spin_lock_irqsave(&opl4->reg_lock, flags);
 	value = snd_opl4_read(opl4, reg);
+	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 	ucontrol->value.integer.value[0] = 7 - (value & 7);
 	ucontrol->value.integer.value[1] = 7 - ((value >> 3) & 7);
 	return 0;
@@ -46,13 +47,16 @@ static int snd_opl4_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
 static int snd_opl4_ctl_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	opl4_t *opl4 = snd_kcontrol_chip(kcontrol);
+	unsigned long flags;
 	u8 reg = kcontrol->private_value;
 	u8 value, old_value;
 
 	value = (7 - (ucontrol->value.integer.value[0] & 7)) |
 		((7 - (ucontrol->value.integer.value[1] & 7)) << 3);
+	spin_lock_irqsave(&opl4->reg_lock, flags);
 	old_value = snd_opl4_read(opl4, reg);
 	snd_opl4_write(opl4, reg, value);
+	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 	return value != old_value;
 }
 
@@ -80,9 +84,7 @@ int snd_opl4_create_mixer(opl4_t *opl4)
 	snd_card_t *card = opl4->card;
 	int i, err;
 
-#if 0	/* already set by the codec driver */
-	strcpy(card->mixername, "OPL4 Mixer");
-#endif
+	strcat(card->mixername, ",OPL4");
 
 	for (i = 0; i < 2; ++i) {
 		err = snd_ctl_add(card, snd_ctl_new1(&snd_opl4_controls[i], opl4));
diff --git a/sound/drivers/opl4/opl4_proc.c b/sound/drivers/opl4/opl4_proc.c
index bbea9ab1c..6a1486258 100644
--- a/sound/drivers/opl4/opl4_proc.c
+++ b/sound/drivers/opl4/opl4_proc.c
@@ -26,7 +26,7 @@
 static int snd_opl4_mem_proc_open(snd_info_entry_t *entry,
 				  unsigned short mode, void **file_private_data)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, entry->private_data, return -ENXIO);
+	opl4_t *opl4 = entry->private_data;
 
 	down(&opl4->access_mutex);
 	if (opl4->memory_access) {
@@ -41,7 +41,7 @@ static int snd_opl4_mem_proc_open(snd_info_entry_t *entry,
 static int snd_opl4_mem_proc_release(snd_info_entry_t *entry,
 				     unsigned short mode, void *file_private_data)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, entry->private_data, return -ENXIO);
+	opl4_t *opl4 = entry->private_data;
 
 	down(&opl4->access_mutex);
 	opl4->memory_access--;
@@ -53,7 +53,7 @@ static long snd_opl4_mem_proc_read(snd_info_entry_t *entry, void *file_private_d
 				   struct file *file, char __user *_buf,
 				   unsigned long count, unsigned long pos)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, entry->private_data, return -ENXIO);
+	opl4_t *opl4 = entry->private_data;
 	long size;
 	char* buf;
 
@@ -79,7 +79,7 @@ static long snd_opl4_mem_proc_write(snd_info_entry_t *entry, void *file_private_
 				    struct file *file, const char __user *_buf,
 				    unsigned long count, unsigned long pos)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, entry->private_data, return -ENXIO);
+	opl4_t *opl4 = entry->private_data;
 	long size;
 	char *buf;
 
diff --git a/sound/drivers/opl4/opl4_seq.c b/sound/drivers/opl4/opl4_seq.c
index cc0dee9c2..958dfe884 100644
--- a/sound/drivers/opl4/opl4_seq.c
+++ b/sound/drivers/opl4/opl4_seq.c
@@ -39,13 +39,11 @@
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
 MODULE_DESCRIPTION("OPL4 wavetable synth driver");
 MODULE_LICENSE("Dual BSD/GPL");
-MODULE_CLASSES("{sound}");
 
 int volume_boost = 8;
 
 module_param(volume_boost, int, 0644);
 MODULE_PARM_DESC(volume_boost, "Additional volume for OPL4 wavetable sounds.");
-MODULE_PARM_SYNTAX(volume_boost, "default:8");
 
 static int snd_opl4_seq_use_inc(opl4_t *opl4)
 {
@@ -61,7 +59,7 @@ static void snd_opl4_seq_use_dec(opl4_t *opl4)
 
 static int snd_opl4_seq_use(void *private_data, snd_seq_port_subscribe_t *info)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return -ENXIO);
+	opl4_t *opl4 = private_data;
 	int err;
 
 	down(&opl4->access_mutex);
@@ -88,7 +86,7 @@ static int snd_opl4_seq_use(void *private_data, snd_seq_port_subscribe_t *info)
 
 static int snd_opl4_seq_unuse(void *private_data, snd_seq_port_subscribe_t *info)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return -ENXIO);
+	opl4_t *opl4 = private_data;
 
 	snd_opl4_synth_shutdown(opl4);
 
@@ -112,7 +110,7 @@ static snd_midi_op_t opl4_ops = {
 static int snd_opl4_seq_event_input(snd_seq_event_t *ev, int direct,
 				    void *private_data, int atomic, int hop)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return -ENXIO);
+	opl4_t *opl4 = private_data;
 
 	snd_midi_process_event(&opl4_ops, ev, opl4->chset);
 	return 0;
@@ -120,7 +118,7 @@ static int snd_opl4_seq_event_input(snd_seq_event_t *ev, int direct,
 
 static void snd_opl4_seq_free_port(void *private_data)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return);
+	opl4_t *opl4 = private_data;
 
 	snd_midi_channel_free_set(opl4->chset);
 }
diff --git a/sound/drivers/opl4/opl4_synth.c b/sound/drivers/opl4/opl4_synth.c
index d4499d1ba..b146a1c99 100644
--- a/sound/drivers/opl4/opl4_synth.c
+++ b/sound/drivers/opl4/opl4_synth.c
@@ -272,12 +272,14 @@ static unsigned char snd_opl4_volume_table[128] = {
  */
 void snd_opl4_synth_reset(opl4_t *opl4)
 {
+	unsigned long flags;
 	int i;
 
+	spin_lock_irqsave(&opl4->reg_lock, flags);
 	for (i = 0; i < OPL4_MAX_VOICES; i++)
 		snd_opl4_write(opl4, OPL4_REG_MISC + i, OPL4_DAMP_BIT);
+	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 
-	spin_lock_init(&opl4->voices_lock);
 	INIT_LIST_HEAD(&opl4->off_voices);
 	INIT_LIST_HEAD(&opl4->on_voices);
 	memset(opl4->voices, 0, sizeof(opl4->voices));
@@ -294,11 +296,14 @@ void snd_opl4_synth_reset(opl4_t *opl4)
  */
 void snd_opl4_synth_shutdown(opl4_t *opl4)
 {
+	unsigned long flags;
 	int i;
 
+	spin_lock_irqsave(&opl4->reg_lock, flags);
 	for (i = 0; i < OPL4_MAX_VOICES; i++)
 		snd_opl4_write(opl4, OPL4_REG_MISC + i,
 			       opl4->voices[i].reg_misc & ~OPL4_KEY_ON_BIT);
+	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 /*
@@ -311,14 +316,14 @@ static void snd_opl4_do_for_note(opl4_t *opl4, int note, snd_midi_channel_t *cha
 	unsigned long flags;
 	opl4_voice_t *voice;
 
-	spin_lock_irqsave(&opl4->voices_lock, flags);
+	spin_lock_irqsave(&opl4->reg_lock, flags);
 	for (i = 0; i < OPL4_MAX_VOICES; i++) {
 		voice = &opl4->voices[i];
 		if (voice->chan == chan && voice->note == note) {
 			func(opl4, voice);
 		}
 	}
-	spin_unlock_irqrestore(&opl4->voices_lock, flags);
+	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 /*
@@ -331,14 +336,14 @@ static void snd_opl4_do_for_channel(opl4_t *opl4, snd_midi_channel_t *chan,
 	unsigned long flags;
 	opl4_voice_t *voice;
 
-	spin_lock_irqsave(&opl4->voices_lock, flags);
+	spin_lock_irqsave(&opl4->reg_lock, flags);
 	for (i = 0; i < OPL4_MAX_VOICES; i++) {
 		voice = &opl4->voices[i];
 		if (voice->chan == chan) {
 			func(opl4, voice);
 		}
 	}
-	spin_unlock_irqrestore(&opl4->voices_lock, flags);
+	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 /*
@@ -351,13 +356,13 @@ static void snd_opl4_do_for_all(opl4_t *opl4,
 	unsigned long flags;
 	opl4_voice_t *voice;
 
-	spin_lock_irqsave(&opl4->voices_lock, flags);
+	spin_lock_irqsave(&opl4->reg_lock, flags);
 	for (i = 0; i < OPL4_MAX_VOICES; i++) {
 		voice = &opl4->voices[i];
 		if (voice->chan)
 			func(opl4, voice);
 	}
-	spin_unlock_irqrestore(&opl4->voices_lock, flags);
+	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 static void snd_opl4_update_volume(opl4_t *opl4, opl4_voice_t *voice)
@@ -472,7 +477,7 @@ static void snd_opl4_wait_for_wave_headers(opl4_t *opl4)
 
 void snd_opl4_note_on(void *private_data, int note, int vel, snd_midi_channel_t *chan)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return);
+	opl4_t *opl4 = private_data;
 	const opl4_region_ptr_t *regions;
 	opl4_voice_t *voice[2];
 	const opl4_sound_t *sound[2];
@@ -492,7 +497,7 @@ void snd_opl4_note_on(void *private_data, int note, int vel, snd_midi_channel_t
 	}
 
 	/* allocate and initialize the needed voices */
-	spin_lock_irqsave(&opl4->voices_lock, flags);
+	spin_lock_irqsave(&opl4->reg_lock, flags);
 	for (i = 0; i < voices; i++) {
 		voice[i] = snd_opl4_get_voice(opl4);
 		list_del(&voice[i]->list);
@@ -502,7 +507,6 @@ void snd_opl4_note_on(void *private_data, int note, int vel, snd_midi_channel_t
 		voice[i]->velocity = vel & 0x7f;
 		voice[i]->sound = sound[i];
 	}
-	spin_unlock_irqrestore(&opl4->voices_lock, flags);
 
 	/* set tone number (triggers header loading) */
 	for (i = 0; i < voices; i++) {
@@ -522,11 +526,13 @@ void snd_opl4_note_on(void *private_data, int note, int vel, snd_midi_channel_t
 		voice[i]->level_direct = OPL4_LEVEL_DIRECT_BIT;
 		snd_opl4_update_volume(opl4, voice[i]);
 	}
+	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 
 	/* wait for completion of loading */
 	snd_opl4_wait_for_wave_headers(opl4);
 
 	/* set remaining parameters */
+	spin_lock_irqsave(&opl4->reg_lock, flags);
 	for (i = 0; i < voices; i++) {
 		snd_opl4_update_tone_parameters(opl4, voice[i]);
 		voice[i]->reg_lfo_vibrato = voice[i]->sound->reg_lfo_vibrato;
@@ -540,6 +546,7 @@ void snd_opl4_note_on(void *private_data, int note, int vel, snd_midi_channel_t
 		snd_opl4_write(opl4, OPL4_REG_MISC + voice[i]->number,
 			       voice[i]->reg_misc);
 	}
+	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
 static void snd_opl4_voice_off(opl4_t *opl4, opl4_voice_t *voice)
@@ -553,7 +560,7 @@ static void snd_opl4_voice_off(opl4_t *opl4, opl4_voice_t *voice)
 
 void snd_opl4_note_off(void *private_data, int note, int vel, snd_midi_channel_t *chan)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return);
+	opl4_t *opl4 = private_data;
 
 	snd_opl4_do_for_note(opl4, note, chan, snd_opl4_voice_off);
 }
@@ -569,14 +576,14 @@ static void snd_opl4_terminate_voice(opl4_t *opl4, opl4_voice_t *voice)
 
 void snd_opl4_terminate_note(void *private_data, int note, snd_midi_channel_t *chan)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return);
+	opl4_t *opl4 = private_data;
 
 	snd_opl4_do_for_note(opl4, note, chan, snd_opl4_terminate_voice);
 }
 
 void snd_opl4_control(void *private_data, int type, snd_midi_channel_t *chan)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return);
+	opl4_t *opl4 = private_data;
 
 	switch (type) {
 	case MIDI_CTL_MSB_MODWHEEL:
@@ -616,7 +623,7 @@ void snd_opl4_control(void *private_data, int type, snd_midi_channel_t *chan)
 void snd_opl4_sysex(void *private_data, unsigned char *buf, int len,
 		    int parsed, snd_midi_channel_set_t *chset)
 {
-	opl4_t *opl4 = snd_magic_cast(opl4_t, private_data, return);
+	opl4_t *opl4 = private_data;
 
 	if (parsed == SNDRV_MIDI_SYSEX_GS_MASTER_VOLUME)
 		snd_opl4_do_for_all(opl4, snd_opl4_update_volume);
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index 2662f5c12..5dd2bc8a4 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -46,8 +46,7 @@
 
 MODULE_DESCRIPTION("MIDI serial u16550");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ALSA, MIDI serial u16550}}");
+MODULE_SUPPORTED_DEVICE("{{ALSA, MIDI serial u16550}}");
 
 #define SNDRV_SERIAL_SOUNDCANVAS 0 /* Roland Soundcanvas; F5 NN selects part */
 #define SNDRV_SERIAL_MS124T 1      /* Midiator MS-124T */
@@ -81,38 +80,27 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Serial MIDI.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Serial MIDI.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable UART16550A chip.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for UART16550A chip.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for UART16550A chip.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(speed, int, boot_devs, 0444);
 MODULE_PARM_DESC(speed, "Speed in bauds.");
-MODULE_PARM_SYNTAX(speed, SNDRV_ENABLED ",allows:{9600,19200,38400,57600,115200},dialog:list");
 module_param_array(base, int, boot_devs, 0444);
 MODULE_PARM_DESC(base, "Base for divisor in bauds.");
-MODULE_PARM_SYNTAX(base, SNDRV_ENABLED ",allows:{57600,115200,230400,460800},dialog:list");
 module_param_array(outs, int, boot_devs, 0444);
 MODULE_PARM_DESC(outs, "Number of MIDI outputs.");
 module_param_array(ins, int, boot_devs, 0444);
 MODULE_PARM_DESC(ins, "Number of MIDI inputs.");
 module_param_array(droponfull, bool, boot_devs, 0444);
 MODULE_PARM_DESC(droponfull, "Flag to enable drop-on-full buffer mode");
-MODULE_PARM_SYNTAX(droponfull, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 
-MODULE_PARM_SYNTAX(outs, SNDRV_ENABLED ",allows:{{1,16}},dialog:list");
-MODULE_PARM_SYNTAX(ins, SNDRV_ENABLED ",allows:{{1,16}},dialog:list");
 module_param_array(adaptor, int, boot_devs, 0444);
 MODULE_PARM_DESC(adaptor, "Type of adaptor.");
-MODULE_PARM_SYNTAX(adaptor, SNDRV_ENABLED ",allows:{{0=Soundcanvas,1=MS-124T,2=MS-124W S/A,3=MS-124W M/B,4=Generic}},dialog:list");
 
 /*#define SNDRV_SERIAL_MS124W_MB_NOCOMBO 1*/  /* Address outs as 0-3 instead of bitmap */
 
@@ -524,7 +512,7 @@ static void snd_uart16550_do_close(snd_uart16550_t * uart)
 static int snd_uart16550_input_open(snd_rawmidi_substream_t * substream)
 {
 	unsigned long flags;
-	snd_uart16550_t *uart = snd_magic_cast(snd_uart16550_t, substream->rmidi->private_data, return -ENXIO);
+	snd_uart16550_t *uart = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&uart->open_lock, flags);
 	if (uart->filemode == SERIAL_MODE_NOT_OPENED)
@@ -538,7 +526,7 @@ static int snd_uart16550_input_open(snd_rawmidi_substream_t * substream)
 static int snd_uart16550_input_close(snd_rawmidi_substream_t * substream)
 {
 	unsigned long flags;
-	snd_uart16550_t *uart = snd_magic_cast(snd_uart16550_t, substream->rmidi->private_data, return -ENXIO);
+	snd_uart16550_t *uart = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&uart->open_lock, flags);
 	uart->filemode &= ~SERIAL_MODE_INPUT_OPEN;
@@ -552,7 +540,7 @@ static int snd_uart16550_input_close(snd_rawmidi_substream_t * substream)
 static void snd_uart16550_input_trigger(snd_rawmidi_substream_t * substream, int up)
 {
 	unsigned long flags;
-	snd_uart16550_t *uart = snd_magic_cast(snd_uart16550_t, substream->rmidi->private_data, return);
+	snd_uart16550_t *uart = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&uart->open_lock, flags);
 	if (up) {
@@ -566,7 +554,7 @@ static void snd_uart16550_input_trigger(snd_rawmidi_substream_t * substream, int
 static int snd_uart16550_output_open(snd_rawmidi_substream_t * substream)
 {
 	unsigned long flags;
-	snd_uart16550_t *uart = snd_magic_cast(snd_uart16550_t, substream->rmidi->private_data, return -ENXIO);
+	snd_uart16550_t *uart = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&uart->open_lock, flags);
 	if (uart->filemode == SERIAL_MODE_NOT_OPENED)
@@ -580,7 +568,7 @@ static int snd_uart16550_output_open(snd_rawmidi_substream_t * substream)
 static int snd_uart16550_output_close(snd_rawmidi_substream_t * substream)
 {
 	unsigned long flags;
-	snd_uart16550_t *uart = snd_magic_cast(snd_uart16550_t, substream->rmidi->private_data, return -ENXIO);
+	snd_uart16550_t *uart = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&uart->open_lock, flags);
 	uart->filemode &= ~SERIAL_MODE_OUTPUT_OPEN;
@@ -652,7 +640,7 @@ static void snd_uart16550_output_write(snd_rawmidi_substream_t * substream)
 {
 	unsigned long flags;
 	unsigned char midi_byte, addr_byte;
-	snd_uart16550_t *uart = snd_magic_cast(snd_uart16550_t, substream->rmidi->private_data, return);
+	snd_uart16550_t *uart = substream->rmidi->private_data;
 	char first;
 	static unsigned long lasttime=0;
 	
@@ -730,7 +718,7 @@ static void snd_uart16550_output_write(snd_rawmidi_substream_t * substream)
 static void snd_uart16550_output_trigger(snd_rawmidi_substream_t * substream, int up)
 {
 	unsigned long flags;
-	snd_uart16550_t *uart = snd_magic_cast(snd_uart16550_t, substream->rmidi->private_data, return);
+	snd_uart16550_t *uart = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&uart->open_lock, flags);
 	if (up) {
@@ -765,13 +753,13 @@ static int snd_uart16550_free(snd_uart16550_t *uart)
 		release_resource(uart->res_base);
 		kfree_nocheck(uart->res_base);
 	}
-	snd_magic_kfree(uart);
+	kfree(uart);
 	return 0;
 };
 
 static int snd_uart16550_dev_free(snd_device_t *device)
 {
-	snd_uart16550_t *uart = snd_magic_cast(snd_uart16550_t, device->device_data, return -ENXIO);
+	snd_uart16550_t *uart = device->device_data;
 	return snd_uart16550_free(uart);
 }
 
@@ -791,7 +779,7 @@ static int __init snd_uart16550_create(snd_card_t * card,
 	int err;
 
 
-	if ((uart = snd_magic_kcalloc(snd_uart16550_t, 0, GFP_KERNEL)) == NULL)
+	if ((uart = kcalloc(1, sizeof(*uart), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 	uart->adaptor = adaptor;
 	uart->card = card;
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c
index 73eefd29c..f84b271e8 100644
--- a/sound/drivers/virmidi.c
+++ b/sound/drivers/virmidi.c
@@ -57,8 +57,7 @@
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("Dummy soundcard for virtual rawmidi devices");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ALSA,Virtual rawmidi device}}");
+MODULE_SUPPORTED_DEVICE("{{ALSA,Virtual rawmidi device}}");
 
 #define MAX_MIDI_DEVICES	8
 
@@ -70,16 +69,12 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for virmidi soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for virmidi soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable this soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(midi_devs, int, boot_devs, 0444);
 MODULE_PARM_DESC(midi_devs, "MIDI devices # (1-8)");
-MODULE_PARM_SYNTAX(midi_devs, SNDRV_ENABLED ",allows:{{1,8}}");
 
 typedef struct snd_card_virmidi {
 	snd_card_t *card;
@@ -113,7 +108,7 @@ static int __init snd_card_virmidi_probe(int dev)
 		snd_virmidi_dev_t *rdev;
 		if ((err = snd_virmidi_new(card, idx, &rmidi)) < 0)
 			goto __nodev;
-		rdev = snd_magic_cast(snd_virmidi_dev_t, rmidi->private_data, continue);
+		rdev = rmidi->private_data;
 		vmidi->midi[idx] = rmidi;
 		strcpy(rmidi->name, "Virtual Raw MIDI");
 		rdev->seq_mode = SNDRV_VIRMIDI_SEQ_DISPATCH;
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
index 31a94efd6..a4d72534b 100644
--- a/sound/drivers/vx/vx_core.c
+++ b/sound/drivers/vx/vx_core.c
@@ -506,7 +506,7 @@ static int vx_test_irq_src(vx_core_t *chip, unsigned int *ret)
  */
 static void vx_interrupt(unsigned long private_data)
 {
-	vx_core_t *chip = snd_magic_cast(vx_core_t, (void*)private_data, return);
+	vx_core_t *chip = (vx_core_t *) private_data;
 	unsigned int events;
 		
 	if (chip->chip_status & VX_STAT_IS_STALE)
@@ -550,7 +550,7 @@ static void vx_interrupt(unsigned long private_data)
  */
 irqreturn_t snd_vx_irq_handler(int irq, void *dev, struct pt_regs *regs)
 {
-	vx_core_t *chip = snd_magic_cast(vx_core_t, dev, return IRQ_NONE);
+	vx_core_t *chip = dev;
 
 	if (! (chip->chip_status & VX_STAT_CHIP_INIT) ||
 	    (chip->chip_status & VX_STAT_IS_STALE))
@@ -572,6 +572,7 @@ static void vx_reset_board(vx_core_t *chip, int cold_reset)
 	if (cold_reset) {
 		chip->audio_source_target = chip->audio_source;
 		chip->clock_source = INTERNAL_QUARTZ;
+		chip->clock_mode = VX_CLOCK_MODE_AUTO;
 		chip->freq = 48000;
 		chip->uer_detected = VX_UER_MODE_NOT_PRESENT;
 		chip->uer_bits = SNDRV_PCM_DEFAULT_CON_SPDIF;
@@ -603,9 +604,10 @@ static void vx_reset_board(vx_core_t *chip, int cold_reset)
 
 static void vx_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
 {
-	vx_core_t *chip = snd_magic_cast(vx_core_t, entry->private_data, return);
+	vx_core_t *chip = entry->private_data;
 	static char *audio_src_vxp[] = { "Line", "Mic", "Digital" };
 	static char *audio_src_vx2[] = { "Analog", "Analog", "Digital" };
+	static char *clock_mode[] = { "Auto", "Internal", "External" };
 	static char *clock_src[] = { "Internal", "External" };
 	static char *uer_type[] = { "Consumer", "Professional", "Not Present" };
 	
@@ -629,6 +631,7 @@ static void vx_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
 	snd_iprintf(buffer, "Input Source: %s\n", vx_is_pcmcia(chip) ?
 		    audio_src_vxp[chip->audio_source] :
 		    audio_src_vx2[chip->audio_source]);
+	snd_iprintf(buffer, "Clock Mode: %s\n", clock_mode[chip->clock_mode]);
 	snd_iprintf(buffer, "Clock Source: %s\n", clock_src[chip->clock_source]);
 	snd_iprintf(buffer, "Frequency: %d\n", chip->freq);
 	snd_iprintf(buffer, "Detected Frequency: %d\n", chip->freq_detected);
@@ -731,7 +734,7 @@ vx_core_t *snd_vx_create(snd_card_t *card, struct snd_vx_hardware *hw,
 
 	snd_assert(card && hw && ops, return NULL);
 
-	chip = snd_magic_kcalloc(vx_core_t, extra_size, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(chip) + extra_size, GFP_KERNEL);
 	if (! chip) {
 		snd_printk(KERN_ERR "vx_core: no memory\n");
 		return NULL;
diff --git a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c
index 8a69c02e9..9d153eac9 100644
--- a/sound/drivers/vx/vx_hwdep.c
+++ b/sound/drivers/vx/vx_hwdep.c
@@ -44,7 +44,7 @@ static int vx_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t *info)
 		[VX_TYPE_VXPOCKET] = "vxpocket",
 		[VX_TYPE_VXP440] = "vxp440",
 	};
-	vx_core_t *vx = snd_magic_cast(vx_core_t, hw->private_data, return -ENXIO);
+	vx_core_t *vx = hw->private_data;
 
 	snd_assert(type_ids[vx->type], return -EINVAL);
 	strcpy(info->id, type_ids[vx->type]);
@@ -60,7 +60,7 @@ static int vx_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t *info)
 
 static int vx_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp)
 {
-	vx_core_t *vx = snd_magic_cast(vx_core_t, hw->private_data, return -ENXIO);
+	vx_core_t *vx = hw->private_data;
 	int index, err;
 
 	snd_assert(vx->ops->load_dsp, return -ENXIO);
diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c
index 52cfb80b5..f00c88886 100644
--- a/sound/drivers/vx/vx_mixer.c
+++ b/sound/drivers/vx/vx_mixer.c
@@ -26,8 +26,6 @@
 #include <sound/vx_core.h>
 #include "vx_cmd.h"
 
-#define chip_t vx_core_t
-
 
 /*
  * write a codec data (24bit)
@@ -523,6 +521,54 @@ static snd_kcontrol_new_t vx_control_audio_src = {
 	.put =		vx_audio_src_put,
 };
 
+/*
+ * clock mode selection
+ */
+static int vx_clock_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	static char *texts[3] = {
+		"Auto", "Internal", "External"
+	};
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 3;
+	if (uinfo->value.enumerated.item > 2)
+		uinfo->value.enumerated.item = 2;
+	strcpy(uinfo->value.enumerated.name,
+	       texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int vx_clock_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.enumerated.item[0] = chip->clock_mode;
+	return 0;
+}
+
+static int vx_clock_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	vx_core_t *chip = snd_kcontrol_chip(kcontrol);
+	down(&chip->mixer_mutex);
+	if (chip->clock_mode != ucontrol->value.enumerated.item[0]) {
+		chip->clock_mode = ucontrol->value.enumerated.item[0];
+		vx_set_clock(chip, chip->freq);
+		up(&chip->mixer_mutex);
+		return 1;
+	}
+	up(&chip->mixer_mutex);
+	return 0;
+}
+
+static snd_kcontrol_new_t vx_control_clock_mode = {
+	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name =		"Clock Mode",
+	.info =		vx_clock_mode_info,
+	.get =		vx_clock_mode_get,
+	.put =		vx_clock_mode_put,
+};
+
 /*
  * Audio Gain
  */
@@ -913,6 +959,9 @@ int snd_vx_mixer_new(vx_core_t *chip)
 	/* Audio source */
 	if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_audio_src, chip))) < 0)
 		return err;
+	/* clock mode */
+	if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_clock_mode, chip))) < 0)
+		return err;
 	/* IEC958 controls */
 	if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958_mask, chip))) < 0)
 		return err;
diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c
index 2f7d85f64..d1bd1efeb 100644
--- a/sound/drivers/vx/vx_pcm.c
+++ b/sound/drivers/vx/vx_pcm.c
@@ -48,14 +48,13 @@
 #include <sound/driver.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/delay.h>
 #include <sound/core.h>
 #include <sound/asoundef.h>
 #include <sound/pcm.h>
 #include <sound/vx_core.h>
 #include "vx_cmd.h"
 
-#define chip_t	vx_core_t
-
 
 /*
  * we use a vmalloc'ed (sg-)buffer
@@ -381,7 +380,7 @@ static int vx_send_irqa(vx_core_t *chip)
  */
 static int vx_toggle_pipe(vx_core_t *chip, vx_pipe_t *pipe, int state)
 {
-	int err, i, cur_state, delay;
+	int err, i, cur_state;
 
 	/* Check the pipe is not already in the requested state */
 	if (vx_get_pipe_state(chip, pipe, &cur_state) < 0)
@@ -394,17 +393,14 @@ static int vx_toggle_pipe(vx_core_t *chip, vx_pipe_t *pipe, int state)
 	 * enough sound buffer for this pipe)
 	 */
 	if (state) {
-		int delay = CAN_START_DELAY;
 		for (i = 0 ; i < MAX_WAIT_FOR_DSP; i++) {
-			snd_vx_delay(chip, delay);
 			err = vx_pipe_can_start(chip, pipe);
 			if (err > 0)
 				break;
 			/* Wait for a few, before asking again
 			 * to avoid flooding the DSP with our requests
 			 */
-			if ((i % 4 ) == 0)
-				delay <<= 1;
+			mdelay(1);
 		}
 	}
     
@@ -418,15 +414,12 @@ static int vx_toggle_pipe(vx_core_t *chip, vx_pipe_t *pipe, int state)
 	 * reaching the expected state before returning
 	 * Check one pipe only (since they are synchronous)
 	 */
-	delay = WAIT_STATE_DELAY;
 	for (i = 0; i < MAX_WAIT_FOR_DSP; i++) {
-		snd_vx_delay(chip, delay);
 		err = vx_get_pipe_state(chip, pipe, &cur_state);
 		if (err < 0 || cur_state == state)
 			break;
 		err = -EIO;
-		if ((i % 4 ) == 0)
-			delay <<= 1;
+		mdelay(1);
 	}
 	return err < 0 ? -EIO : 0;
 }
@@ -480,7 +473,7 @@ static int vx_alloc_pipe(vx_core_t *chip, int capture,
 		return err;
 
 	/* initialize the pipe record */
-	pipe = snd_magic_kcalloc(vx_pipe_t, 0, GFP_KERNEL);
+	pipe = kcalloc(1, sizeof(*pipe), GFP_KERNEL);
 	if (! pipe) {
 		/* release the pipe */
 		vx_init_rmh(&rmh, CMD_FREE_PIPE);
@@ -514,7 +507,7 @@ static int vx_free_pipe(vx_core_t *chip, vx_pipe_t *pipe)
 	vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
 	vx_send_msg(chip, &rmh);
 
-	snd_magic_kfree(pipe);
+	kfree(pipe);
 	return 0;
 }
 
@@ -629,7 +622,7 @@ static int vx_pcm_playback_close(snd_pcm_substream_t *subs)
 	if (! subs->runtime->private_data)
 		return -EINVAL;
 
-	pipe = snd_magic_cast(vx_pipe_t, subs->runtime->private_data, return -EINVAL);
+	pipe = subs->runtime->private_data;
 
 	if (--pipe->references == 0) {
 		chip->playback_pipes[pipe->number] = NULL;
@@ -778,8 +771,8 @@ static void vx_pcm_playback_update(vx_core_t *chip, snd_pcm_substream_t *subs, v
 static void vx_pcm_delayed_start(unsigned long arg)
 {
 	snd_pcm_substream_t *subs = (snd_pcm_substream_t *)arg;
-	vx_core_t *chip = snd_magic_cast(vx_core_t, subs->pcm->private_data, return);
-	vx_pipe_t *pipe = snd_magic_cast(vx_pipe_t, subs->runtime->private_data, return);
+	vx_core_t *chip = subs->pcm->private_data;
+	vx_pipe_t *pipe = subs->runtime->private_data;
 	int err;
 
 	/*  printk( KERN_DEBUG "DDDD tasklet delayed start jiffies = %ld\n", jiffies);*/
@@ -801,7 +794,7 @@ static void vx_pcm_delayed_start(unsigned long arg)
 static int vx_pcm_trigger(snd_pcm_substream_t *subs, int cmd)
 {
 	vx_core_t *chip = snd_pcm_substream_chip(subs);
-	vx_pipe_t *pipe = snd_magic_cast(vx_pipe_t, subs->runtime->private_data, return -EINVAL);
+	vx_pipe_t *pipe = subs->runtime->private_data;
 	int err;
 
 	if (chip->chip_status & VX_STAT_IS_STALE)
@@ -846,7 +839,7 @@ static int vx_pcm_trigger(snd_pcm_substream_t *subs, int cmd)
 static snd_pcm_uframes_t vx_pcm_playback_pointer(snd_pcm_substream_t *subs)
 {
 	snd_pcm_runtime_t *runtime = subs->runtime;
-	vx_pipe_t *pipe = snd_magic_cast(vx_pipe_t, runtime->private_data, return -EINVAL);
+	vx_pipe_t *pipe = runtime->private_data;
 	return pipe->position;
 }
 
@@ -874,7 +867,7 @@ static int vx_pcm_prepare(snd_pcm_substream_t *subs)
 {
 	vx_core_t *chip = snd_pcm_substream_chip(subs);
 	snd_pcm_runtime_t *runtime = subs->runtime;
-	vx_pipe_t *pipe = snd_magic_cast(vx_pipe_t, runtime->private_data, return -EINVAL);
+	vx_pipe_t *pipe = runtime->private_data;
 	int err, data_mode;
 	// int max_size, nchunks;
 
@@ -1037,7 +1030,7 @@ static int vx_pcm_capture_close(snd_pcm_substream_t *subs)
 	
 	if (! subs->runtime->private_data)
 		return -EINVAL;
-	pipe = snd_magic_cast(vx_pipe_t, subs->runtime->private_data, return -EINVAL);
+	pipe = subs->runtime->private_data;
 	chip->capture_pipes[pipe->number] = NULL;
 
 	pipe_out_monitoring = pipe->monitoring_pipe;
@@ -1141,7 +1134,7 @@ static void vx_pcm_capture_update(vx_core_t *chip, snd_pcm_substream_t *subs, vx
 static snd_pcm_uframes_t vx_pcm_capture_pointer(snd_pcm_substream_t *subs)
 {
 	snd_pcm_runtime_t *runtime = subs->runtime;
-	vx_pipe_t *pipe = snd_magic_cast(vx_pipe_t, runtime->private_data, return -EINVAL);
+	vx_pipe_t *pipe = runtime->private_data;
 	return bytes_to_frames(runtime, pipe->hw_ptr);
 }
 
@@ -1265,7 +1258,7 @@ static int vx_init_audio_io(vx_core_t *chip)
  */
 static void snd_vx_pcm_free(snd_pcm_t *pcm)
 {
-	vx_core_t *chip = snd_magic_cast(vx_core_t, pcm->private_data, return);
+	vx_core_t *chip = pcm->private_data;
 	chip->pcm[pcm->device] = NULL;
 	if (chip->playback_pipes) {
 		kfree(chip->playback_pipes);
diff --git a/sound/drivers/vx/vx_uer.c b/sound/drivers/vx/vx_uer.c
index 54609aac8..5db41f136 100644
--- a/sound/drivers/vx/vx_uer.c
+++ b/sound/drivers/vx/vx_uer.c
@@ -263,17 +263,17 @@ int vx_set_clock(vx_core_t *chip, unsigned int freq)
 	/* change the audio source if possible */
 	vx_sync_audio_source(chip);
 
-	switch (chip->audio_source) {
-	case VX_AUDIO_SRC_DIGITAL:
+	if (chip->clock_mode == VX_CLOCK_MODE_EXTERNAL ||
+	    (chip->clock_mode == VX_CLOCK_MODE_AUTO &&
+	     chip->audio_source == VX_AUDIO_SRC_DIGITAL)) {
 		if (chip->clock_source != UER_SYNC) {
 			vx_change_clock_source(chip, UER_SYNC);
 			mdelay(6);
 			src_changed = 1;
 		}
-		if (chip->freq == freq)
-			return 0;
-		break;
-	default:
+	} else if (chip->clock_mode == VX_CLOCK_MODE_INTERNAL ||
+		   (chip->clock_mode == VX_CLOCK_MODE_AUTO &&
+		    chip->audio_source != VX_AUDIO_SRC_DIGITAL)) {
 		if (chip->clock_source != INTERNAL_QUARTZ) {
 			vx_change_clock_source(chip, INTERNAL_QUARTZ);
 			src_changed = 1;
@@ -283,8 +283,9 @@ int vx_set_clock(vx_core_t *chip, unsigned int freq)
 		vx_set_internal_clock(chip, freq);
 		if (src_changed)
 			vx_modify_board_inputs(chip);
-		break;
 	}
+	if (chip->freq == freq)
+		return 0;
 	chip->freq = freq;
 	vx_modify_board_clock(chip, 1);
 	return 0;
diff --git a/sound/i2c/cs8427.c b/sound/i2c/cs8427.c
index c8f148ea2..7510773b6 100644
--- a/sound/i2c/cs8427.c
+++ b/sound/i2c/cs8427.c
@@ -34,8 +34,6 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("IEC958 (S/PDIF) receiver & transmitter by Cirrus Logic");
 MODULE_LICENSE("GPL");
 
-#define chip_t snd_i2c_device_t
-
 #define CS8427_ADDR			(0x20>>1) /* fixed address */
 
 typedef struct {
@@ -109,7 +107,7 @@ int snd_cs8427_reg_read(snd_i2c_device_t *device, unsigned char reg)
 
 static int snd_cs8427_select_corudata(snd_i2c_device_t *device, int udata)
 {
-	cs8427_t *chip = snd_magic_cast(cs8427_t, device->private_data, return -ENXIO);
+	cs8427_t *chip = device->private_data;
 	int err;
 
 	udata = udata ? CS8427_BSEL : 0;
@@ -128,7 +126,7 @@ static int snd_cs8427_send_corudata(snd_i2c_device_t *device,
 				    unsigned char *ndata,
 				    int count)
 {
-	cs8427_t *chip = snd_magic_cast(cs8427_t, device->private_data, return -ENXIO);
+	cs8427_t *chip = device->private_data;
 	char *hw_data = udata ? chip->playback.hw_udata : chip->playback.hw_status;
 	char data[32];
 	int err, idx;
@@ -159,7 +157,7 @@ static int snd_cs8427_send_corudata(snd_i2c_device_t *device,
 static void snd_cs8427_free(snd_i2c_device_t *device)
 {
 	if (device->private_data)
-		snd_magic_kfree(device->private_data);
+		kfree(device->private_data);
 }
 
 int snd_cs8427_create(snd_i2c_bus_t *bus,
@@ -211,7 +209,7 @@ int snd_cs8427_create(snd_i2c_bus_t *bus,
 
 	if ((err = snd_i2c_device_create(bus, "CS8427", CS8427_ADDR | (addr & 7), &device)) < 0)
 		return err;
-	chip = device->private_data = snd_magic_kcalloc(cs8427_t, 0, GFP_KERNEL);
+	chip = device->private_data = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL) {
 	      	snd_i2c_device_free(device);
 		return -ENOMEM;
@@ -297,7 +295,7 @@ void snd_cs8427_reset(snd_i2c_device_t *cs8427)
 	int data;
 
 	snd_assert(cs8427, return);
-	chip = snd_magic_cast(cs8427_t, cs8427->private_data, return);
+	chip = cs8427->private_data;
 	snd_i2c_lock(cs8427->bus);
 	chip->regmap[CS8427_REG_CLOCKSOURCE] &= ~(CS8427_RUN | CS8427_RXDMASK);
 	snd_cs8427_reg_write(cs8427, CS8427_REG_CLOCKSOURCE, chip->regmap[CS8427_REG_CLOCKSOURCE]);
@@ -389,7 +387,7 @@ static int snd_cs8427_spdif_get(snd_kcontrol_t * kcontrol,
 				snd_ctl_elem_value_t * ucontrol)
 {
 	snd_i2c_device_t *device = snd_kcontrol_chip(kcontrol);
-	cs8427_t *chip = snd_magic_cast(cs8427_t, device->private_data, return -ENXIO);
+	cs8427_t *chip = device->private_data;
 	
 	snd_i2c_lock(device->bus);
 	memcpy(ucontrol->value.iec958.status, chip->playback.def_status, 24);
@@ -401,7 +399,7 @@ static int snd_cs8427_spdif_put(snd_kcontrol_t * kcontrol,
 				snd_ctl_elem_value_t * ucontrol)
 {
 	snd_i2c_device_t *device = snd_kcontrol_chip(kcontrol);
-	cs8427_t *chip = snd_magic_cast(cs8427_t, device->private_data, return -ENXIO);
+	cs8427_t *chip = device->private_data;
 	unsigned char *status = kcontrol->private_value ? chip->playback.pcm_status : chip->playback.def_status;
 	snd_pcm_runtime_t *runtime = chip->playback.substream ? chip->playback.substream->runtime : NULL;
 	int err, change;
@@ -432,8 +430,6 @@ static int snd_cs8427_spdif_mask_get(snd_kcontrol_t * kcontrol,
 	return 0;
 }
 
-#define CONTROLS (sizeof(snd_cs8427_iec958_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs8427_iec958_controls[] = {
 {
 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
@@ -487,13 +483,13 @@ int snd_cs8427_iec958_build(snd_i2c_device_t *cs8427,
 			    snd_pcm_substream_t *play_substream,
 			    snd_pcm_substream_t *cap_substream)
 {
-	cs8427_t *chip = snd_magic_cast(cs8427_t, cs8427->private_data, return -ENXIO);
+	cs8427_t *chip = cs8427->private_data;
 	snd_kcontrol_t *kctl;
 	unsigned int idx;
 	int err;
 
 	snd_assert(play_substream && cap_substream, return -EINVAL);
-	for (idx = 0; idx < CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_cs8427_iec958_controls); idx++) {
 		kctl = snd_ctl_new1(&snd_cs8427_iec958_controls[idx], cs8427);
 		if (kctl == NULL)
 			return -ENOMEM;
@@ -517,7 +513,7 @@ int snd_cs8427_iec958_active(snd_i2c_device_t *cs8427, int active)
 	cs8427_t *chip;
 
 	snd_assert(cs8427, return -ENXIO);
-	chip = snd_magic_cast(cs8427_t, cs8427->private_data, return -ENXIO);
+	chip = cs8427->private_data;
 	if (active)
 		memcpy(chip->playback.pcm_status, chip->playback.def_status, 24);
 	chip->playback.pcm_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
@@ -533,7 +529,7 @@ int snd_cs8427_iec958_pcm(snd_i2c_device_t *cs8427, unsigned int rate)
 	int err, reset;
 
 	snd_assert(cs8427, return -ENXIO);
-	chip = snd_magic_cast(cs8427_t, cs8427->private_data, return -ENXIO);
+	chip = cs8427->private_data;
 	status = chip->playback.pcm_status;
 	snd_i2c_lock(cs8427->bus);
 	if (status[0] & IEC958_AES0_PROFESSIONAL) {
diff --git a/sound/i2c/i2c.c b/sound/i2c/i2c.c
index 287f21aaf..e31f49105 100644
--- a/sound/i2c/i2c.c
+++ b/sound/i2c/i2c.c
@@ -62,13 +62,13 @@ static int snd_i2c_bus_free(snd_i2c_bus_t *bus)
 	}
 	if (bus->private_free)
 		bus->private_free(bus);
-	snd_magic_kfree(bus);
+	kfree(bus);
 	return 0;
 }
 
 static int snd_i2c_bus_dev_free(snd_device_t *device)
 {
-	snd_i2c_bus_t *bus = snd_magic_cast(snd_i2c_bus_t, device->device_data, return -ENXIO);
+	snd_i2c_bus_t *bus = device->device_data;
 	return snd_i2c_bus_free(bus);
 }
 
@@ -81,7 +81,7 @@ int snd_i2c_bus_create(snd_card_t *card, const char *name, snd_i2c_bus_t *master
 	};
 
 	*ri2c = NULL;
-	bus = (snd_i2c_bus_t *)snd_magic_kcalloc(snd_i2c_bus_t, 0, GFP_KERNEL);
+	bus = kcalloc(1, sizeof(*bus), GFP_KERNEL);
 	if (bus == NULL)
 		return -ENOMEM;
 	init_MUTEX(&bus->lock_mutex);
@@ -108,7 +108,7 @@ int snd_i2c_device_create(snd_i2c_bus_t *bus, const char *name, unsigned char ad
 
 	*rdevice = NULL;
 	snd_assert(bus != NULL, return -EINVAL);
-	device = (snd_i2c_device_t *)snd_magic_kcalloc(snd_i2c_device_t, 0, GFP_KERNEL);
+	device = kcalloc(1, sizeof(*device), GFP_KERNEL);
 	if (device == NULL)
 		return -ENOMEM;
 	device->addr = addr;
@@ -125,7 +125,7 @@ int snd_i2c_device_free(snd_i2c_device_t *device)
 		list_del(&device->list);
 	if (device->private_free)
 		device->private_free(device);
-	snd_magic_kfree(device);
+	kfree(device);
 	return 0;
 }
 
diff --git a/sound/i2c/l3/uda1341.c b/sound/i2c/l3/uda1341.c
index 395ada0aa..4f2229d30 100644
--- a/sound/i2c/l3/uda1341.c
+++ b/sound/i2c/l3/uda1341.c
@@ -17,7 +17,7 @@
  * 2002-05-12   Tomas Kasparek  another code cleanup
  */
 
-/* $Id: uda1341.c,v 1.10 2003/10/23 14:34:52 perex Exp $ */
+/* $Id: uda1341.c,v 1.13 2004/07/20 15:54:13 cladisch Exp $ */
 
 #include <sound/driver.h>
 #include <linux/module.h>
@@ -131,7 +131,6 @@ struct uda1341 {
 
 //hack for ALSA magic casting
 typedef struct l3_client l3_client_t;
-#define chip_t l3_client_t      
 
 /* transfer 8bit integer into string with binary representation */
 void int2str_bin8(uint8_t val, char *buf){
@@ -332,7 +331,7 @@ int snd_uda1341_cfg_write(struct l3_client *clnt, unsigned short what,
 static void snd_uda1341_proc_read(snd_info_entry_t *entry, 
 				  snd_info_buffer_t * buffer)
 {
-	struct l3_client *clnt = snd_magic_cast(l3_client_t, entry->private_data, return);
+	struct l3_client *clnt = entry->private_data;
 	struct uda1341 *uda = clnt->driver_data;
 	int peak;
 
@@ -397,7 +396,7 @@ static void snd_uda1341_proc_read(snd_info_entry_t *entry,
 static void snd_uda1341_proc_regs_read(snd_info_entry_t *entry, 
 				       snd_info_buffer_t * buffer)
 {
-	struct l3_client *clnt = snd_magic_cast(l3_client_t, entry->private_data, return);
+	struct l3_client *clnt = entry->private_data;
 	struct uda1341 *uda = clnt->driver_data;		
 	int reg;
 	char buf[12];
@@ -618,8 +617,6 @@ static int snd_uda1341_put_2regs(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 
 /* }}} */
   
-#define UDA1341_CONTROLS (sizeof(snd_uda1341_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_uda1341_controls[] = {
 	UDA1341_SINGLE("Master Playback Switch", CMD_MUTE, data0_2, 2, 1, 1),
 	UDA1341_SINGLE("Master Playback Volume", CMD_VOLUME, data0_0, 0, 63, 1),
@@ -653,12 +650,12 @@ static snd_kcontrol_new_t snd_uda1341_controls[] = {
 static void uda1341_free(struct l3_client *uda1341)
 {
 	l3_detach_client(uda1341); // calls kfree for driver_data (uda1341_t)
-	snd_magic_kfree(uda1341);
+	kfree(uda1341);
 }
 
 static int uda1341_dev_free(snd_device_t *device)
 {
-	struct l3_client *clnt = snd_magic_cast(l3_client_t, device->device_data, return);
+	struct l3_client *clnt = device->device_data;
 	uda1341_free(clnt);
 	return 0;
 }
@@ -673,7 +670,7 @@ int __init snd_chip_uda1341_mixer_new(snd_card_t *card, struct l3_client **clnt)
 
 	snd_assert(card != NULL, return -EINVAL);
 
-	uda1341 = snd_magic_kcalloc(l3_client_t, 0, GFP_KERNEL);
+	uda1341 = kcalloc(1, sizeof(*uda1341), GFP_KERNEL);
 	if (uda1341 == NULL)
 		return -ENOMEM;
          
@@ -688,7 +685,7 @@ int __init snd_chip_uda1341_mixer_new(snd_card_t *card, struct l3_client **clnt)
 		return err;
 	}
 
-	for (idx = 0; idx < UDA1341_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_uda1341_controls); idx++) {
 		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_uda1341_controls[idx], uda1341))) < 0)
 			return err;
 	}
@@ -710,7 +707,7 @@ static int uda1341_attach(struct l3_client *clnt)
 {
 	struct uda1341 *uda;
 
-	uda = snd_magic_kcalloc(uda1341_t, 0, GFP_KERNEL);
+	uda = kcalloc(1, sizeof(*uda), 0, GFP_KERNEL);
 	if (!uda)
 		return -ENOMEM;
 
@@ -734,7 +731,7 @@ static int uda1341_attach(struct l3_client *clnt)
 static void uda1341_detach(struct l3_client *clnt)
 {
 	if (clnt->driver_data)
-		snd_magic_kfree(clnt->driver_data);
+		kfree(clnt->driver_data);
 }
 
 static int
@@ -821,8 +818,7 @@ module_exit(uda1341_exit);
 MODULE_AUTHOR("Tomas Kasparek <tomas.kasparek@seznam.cz>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Philips UDA1341 CODEC driver for ALSA");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{UDA1341,UDA1341TS}}");
+MODULE_SUPPORTED_DEVICE("{{UDA1341,UDA1341TS}}");
 
 EXPORT_SYMBOL(snd_chip_uda1341_mixer_new);
 
diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c
index 276af5f68..7a70055b4 100644
--- a/sound/i2c/other/ak4117.c
+++ b/sound/i2c/other/ak4117.c
@@ -33,8 +33,6 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("AK4117 IEC958 (S/PDIF) receiver by Asahi Kasei");
 MODULE_LICENSE("GPL");
 
-#define chip_t ak4117_t
-
 #define AK4117_ADDR			0x00 /* fixed address */
 
 static void snd_ak4117_timer(unsigned long data);
@@ -65,12 +63,12 @@ static void reg_dump(ak4117_t *ak4117)
 static void snd_ak4117_free(ak4117_t *chip)
 {
 	del_timer(&chip->timer);
-	snd_magic_kfree(chip);
+	kfree(chip);
 }
 
 static int snd_ak4117_dev_free(snd_device_t *device)
 {
-	ak4117_t *chip = snd_magic_cast(ak4117_t, device->device_data, return -ENXIO);
+	ak4117_t *chip = device->device_data;
 	snd_ak4117_free(chip);
 	return 0;
 }
@@ -85,7 +83,7 @@ int snd_ak4117_create(snd_card_t *card, ak4117_read_t *read, ak4117_write_t *wri
 		.dev_free =     snd_ak4117_dev_free,
 	};
 
-	chip = (ak4117_t *)snd_magic_kcalloc(ak4117_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->lock);
@@ -544,7 +542,7 @@ int snd_ak4117_check_rate_and_errors(ak4117_t *ak4117, unsigned int flags)
 
 static void snd_ak4117_timer(unsigned long data)
 {
-	ak4117_t *chip = snd_magic_cast(ak4117_t, (void *)data, return);
+	ak4117_t *chip = (ak4117_t *)data;
 
 	if (chip->init)
 		return;
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index bd378dfad..abd82625b 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -237,7 +237,7 @@ static int snd_akm4xxx_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
 
 static int snd_akm4xxx_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	akm4xxx_t *ak = _snd_kcontrol_chip(kcontrol);
+	akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
 	int chip = AK_GET_CHIP(kcontrol->private_value);
 	int addr = AK_GET_ADDR(kcontrol->private_value);
 	int invert = AK_GET_INVERT(kcontrol->private_value);
@@ -250,7 +250,7 @@ static int snd_akm4xxx_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
 
 static int snd_akm4xxx_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	akm4xxx_t *ak = _snd_kcontrol_chip(kcontrol);
+	akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
 	int chip = AK_GET_CHIP(kcontrol->private_value);
 	int addr = AK_GET_ADDR(kcontrol->private_value);
 	int invert = AK_GET_INVERT(kcontrol->private_value);
@@ -277,7 +277,7 @@ static int snd_akm4xxx_ipga_gain_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
 
 static int snd_akm4xxx_ipga_gain_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	akm4xxx_t *ak = _snd_kcontrol_chip(kcontrol);
+	akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
 	int chip = AK_GET_CHIP(kcontrol->private_value);
 	int addr = AK_GET_ADDR(kcontrol->private_value);
 	ucontrol->value.integer.value[0] = snd_akm4xxx_get_ipga(ak, chip, addr) & 0x7f;
@@ -286,7 +286,7 @@ static int snd_akm4xxx_ipga_gain_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_valu
 
 static int snd_akm4xxx_ipga_gain_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	akm4xxx_t *ak = _snd_kcontrol_chip(kcontrol);
+	akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
 	int chip = AK_GET_CHIP(kcontrol->private_value);
 	int addr = AK_GET_ADDR(kcontrol->private_value);
 	unsigned char nval = (ucontrol->value.integer.value[0] % 37) | 0x80;
@@ -312,7 +312,7 @@ static int snd_akm4xxx_deemphasis_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_in
 
 static int snd_akm4xxx_deemphasis_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	akm4xxx_t *ak = _snd_kcontrol_chip(kcontrol);
+	akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
 	int chip = AK_GET_CHIP(kcontrol->private_value);
 	int addr = AK_GET_ADDR(kcontrol->private_value);
 	int shift = AK_GET_SHIFT(kcontrol->private_value);
@@ -322,7 +322,7 @@ static int snd_akm4xxx_deemphasis_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_va
 
 static int snd_akm4xxx_deemphasis_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	akm4xxx_t *ak = _snd_kcontrol_chip(kcontrol);
+	akm4xxx_t *ak = snd_kcontrol_chip(kcontrol);
 	int chip = AK_GET_CHIP(kcontrol->private_value);
 	int addr = AK_GET_ADDR(kcontrol->private_value);
 	int shift = AK_GET_SHIFT(kcontrol->private_value);
diff --git a/sound/i2c/tea6330t.c b/sound/i2c/tea6330t.c
index 8b0b1bb3c..bb503e70b 100644
--- a/sound/i2c/tea6330t.c
+++ b/sound/i2c/tea6330t.c
@@ -30,8 +30,6 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Routines for control of the TEA6330T circuit via i2c bus");
 MODULE_LICENSE("GPL");
 
-#define chip_t tea6330t_t
-
 #define TEA6330T_ADDR			(0x80>>1) /* fixed address */
 
 #define TEA6330T_SADDR_VOLUME_LEFT	0x00	/* volume left */
@@ -259,8 +257,6 @@ static int snd_tea6330t_put_treble(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
 	return change;
 }
 
-#define TEA6330T_CONTROLS (sizeof(snd_tea6330t_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_tea6330t_controls[] = {
 TEA6330T_MASTER_SWITCH("Master Playback Switch", 0),
 TEA6330T_MASTER_VOLUME("Master Playback Volume", 0),
@@ -270,8 +266,8 @@ TEA6330T_TREBLE("Tone Control - Treble", 0)
 
 static void snd_tea6330_free(snd_i2c_device_t *device)
 {
-	tea6330t_t *tea = snd_magic_cast(tea6330t_t, device->private_data, return);
-	snd_magic_kfree(tea);
+	tea6330t_t *tea = device->private_data;
+	kfree(tea);
 }
                                         
 int snd_tea6330t_update_mixer(snd_card_t * card,
@@ -286,11 +282,11 @@ int snd_tea6330t_update_mixer(snd_card_t * card,
 	u8 default_treble, default_bass;
 	unsigned char bytes[7];
 
-	tea = snd_magic_kcalloc(tea6330t_t, 0, GFP_KERNEL);
+	tea = kcalloc(1, sizeof(*tea), GFP_KERNEL);
 	if (tea == NULL)
 		return -ENOMEM;
 	if ((err = snd_i2c_device_create(bus, "TEA6330T", TEA6330T_ADDR, &device)) < 0) {
-		snd_magic_kfree(tea);
+		kfree(tea);
 		return err;
 	}
 	tea->device = device;
@@ -336,7 +332,7 @@ int snd_tea6330t_update_mixer(snd_card_t * card,
 	if ((err = snd_component_add(card, "TEA6330T")) < 0)
 		goto __error;
 
-	for (idx = 0; idx < TEA6330T_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_tea6330t_controls); idx++) {
 		knew = &snd_tea6330t_controls[idx];
 		if (tea->treble == 0 && !strcmp(knew->name, "Tone Control - Treble"))
 			continue;
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index 11b4240b1..f5f949c0f 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -77,11 +77,15 @@ config SND_ES18XX
 	help
 	  Say 'Y' or 'M' to include support for ESS AudioDrive ES18xx chips.
 
+config SND_GUS_SYNTH
+	tristate
+
 config SND_GUSCLASSIC
 	tristate "Gravis UltraSound Classic"
 	depends on SND
 	select SND_RAWMIDI
 	select SND_PCM
+	select SND_GUS_SYNTH
 	help
 	  Say 'Y' or 'M' to include support for Gravis UltraSound Classic soundcard.
 
@@ -91,6 +95,7 @@ config SND_GUSEXTREME
 	select SND_HWDEP
 	select SND_MPU401_UART
 	select SND_PCM
+	select SND_GUS_SYNTH
 	help
 	  Say 'Y' or 'M' to include support for Gravis UltraSound Extreme soundcard.
 
@@ -99,6 +104,7 @@ config SND_GUSMAX
 	depends on SND
 	select SND_RAWMIDI
 	select SND_PCM
+	select SND_GUS_SYNTH
 	help
 	  Say 'Y' or 'M' to include support for Gravis UltraSound MAX soundcard.
 
@@ -107,6 +113,7 @@ config SND_INTERWAVE
 	depends on SND
 	select SND_RAWMIDI
 	select SND_PCM
+	select SND_GUS_SYNTH
 	help
 	  Say 'Y' or 'M' to include support for AMD InterWave based soundcards
 	  (Gravis UltraSound Plug & Play, STB SoundRage32, MED3210, Dynasonic Pro,
@@ -117,6 +124,7 @@ config SND_INTERWAVE_STB
 	depends on SND
 	select SND_RAWMIDI
 	select SND_PCM
+	select SND_GUS_SYNTH
 	help
 	  Say 'Y' or 'M' to include support for AMD InterWave based soundcards
 	  with TEA6330T bass and treble regulator (UltraSound 32-Pro).
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c
index 3a5671838..9677dae68 100644
--- a/sound/isa/ad1816a/ad1816a.c
+++ b/sound/isa/ad1816a/ad1816a.c
@@ -30,15 +30,12 @@
 #include <sound/mpu401.h>
 #include <sound/opl3.h>
 
-#define chip_t ad1816a_t
-
 #define PFX "ad1816a: "
 
 MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
 MODULE_DESCRIPTION("AD1816A, AD1815");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Highscreen,Sound-Boostar 16 3D},"
+MODULE_SUPPORTED_DEVICE("{{Highscreen,Sound-Boostar 16 3D},"
 		"{Analog Devices,AD1815},"
 		"{Analog Devices,AD1816A},"
 		"{TerraTec,Base 64},"
@@ -60,34 +57,24 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for ad1816a based soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for ad1816a based soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable ad1816a based soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for ad1816a driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for ad1816a driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT12_DESC);
 module_param_array(fm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for ad1816a driver.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for ad1816a driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(mpu_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for ad1816a driver.");
-MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC);
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "1st DMA # for ad1816a driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
 module_param_array(dma2, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma2, "2nd DMA # for ad1816a driver.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC);
 
 struct snd_card_ad1816a {
 	struct pnp_dev *dev;
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
index 4415a9f9e..026198317 100644
--- a/sound/isa/ad1816a/ad1816a_lib.c
+++ b/sound/isa/ad1816a/ad1816a_lib.c
@@ -34,8 +34,6 @@ MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
 MODULE_DESCRIPTION("lowlevel code for Analog Devices AD1816A chip");
 MODULE_LICENSE("GPL");
 
-#define chip_t ad1816a_t
-
 static inline int snd_ad1816a_busy_wait(ad1816a_t *chip)
 {
 	int timeout;
@@ -313,7 +311,7 @@ static snd_pcm_uframes_t snd_ad1816a_capture_pointer(snd_pcm_substream_t *substr
 
 static irqreturn_t snd_ad1816a_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	ad1816a_t *chip = snd_magic_cast(ad1816a_t, dev_id, return IRQ_NONE);
+	ad1816a_t *chip = dev_id;
 	unsigned char status;
 
 	spin_lock(&chip->lock);
@@ -550,13 +548,13 @@ static int snd_ad1816a_free(ad1816a_t *chip)
 		snd_dma_disable(chip->dma2);
 		free_dma(chip->dma2);
 	}
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_ad1816a_dev_free(snd_device_t *device)
 {
-	ad1816a_t *chip = snd_magic_cast(ad1816a_t, device->device_data, return -ENXIO);
+	ad1816a_t *chip = device->device_data;
 	return snd_ad1816a_free(chip);
 }
 
@@ -585,7 +583,7 @@ int snd_ad1816a_create(snd_card_t *card,
 
 	*rchip = NULL;
 
-	chip = snd_magic_kcalloc(ad1816a_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	chip->irq = -1;
@@ -661,7 +659,7 @@ static snd_pcm_ops_t snd_ad1816a_capture_ops = {
 
 static void snd_ad1816a_pcm_free(snd_pcm_t *pcm)
 {
-	ad1816a_t *chip = snd_magic_cast(ad1816a_t, pcm->private_data, return);
+	ad1816a_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -696,7 +694,7 @@ int snd_ad1816a_pcm(ad1816a_t *chip, int device, snd_pcm_t **rpcm)
 
 static void snd_ad1816a_timer_free(snd_timer_t *timer)
 {
-	ad1816a_t *chip = snd_magic_cast(ad1816a_t, timer->private_data, return);
+	ad1816a_t *chip = timer->private_data;
 	chip->timer = NULL;
 }
 
@@ -901,8 +899,6 @@ static int snd_ad1816a_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
 	return change;
 }
 
-#define AD1816A_CONTROLS (sizeof(snd_ad1816a_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_ad1816a_controls[] = {
 AD1816A_DOUBLE("Master Playback Switch", AD1816A_MASTER_ATT, 15, 7, 1, 1),
 AD1816A_DOUBLE("Master Playback Volume", AD1816A_MASTER_ATT, 8, 0, 31, 1),
@@ -950,7 +946,7 @@ int snd_ad1816a_mixer(ad1816a_t *chip)
 
 	strcpy(card->mixername, snd_ad1816a_chip_id(chip));
 
-	for (idx = 0; idx < AD1816A_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_ad1816a_controls); idx++) {
 		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ad1816a_controls[idx], chip))) < 0)
 			return err;
 	}
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index afd232fd5..bcf355779 100644
--- a/sound/isa/ad1848/ad1848.c
+++ b/sound/isa/ad1848/ad1848.c
@@ -30,13 +30,10 @@
 #include <sound/ad1848.h>
 #include <sound/initval.h>
 
-#define chip_t ad1848_t
-
 MODULE_AUTHOR("Tugrul Galatali <galatalt@stuy.edu>, Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("AD1848/AD1847/CS4248");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Analog Devices,AD1848},"
+MODULE_SUPPORTED_DEVICE("{{Analog Devices,AD1848},"
 	        "{Analog Devices,AD1847},"
 		"{Crystal Semiconductors,CS4248}}");
 
@@ -51,25 +48,18 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for AD1848 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for AD1848 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable AD1848 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for AD1848 driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for AD1848 driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for AD1848 driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
 module_param_array(thinkpad, bool, boot_devs, 0444);
 MODULE_PARM_DESC(thinkpad, "Enable only for the onboard CS4248 of IBM Thinkpad 360/750/755 series.");
-MODULE_PARM_SYNTAX(thinkpad,  SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 
 static snd_card_t *snd_ad1848_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c
index fe913bf4f..d0a62f71b 100644
--- a/sound/isa/ad1848/ad1848_lib.c
+++ b/sound/isa/ad1848/ad1848_lib.c
@@ -39,8 +39,6 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Routines for control of AD1848/AD1847/CS4248");
 MODULE_LICENSE("GPL");
 
-#define chip_t ad1848_t
-
 #if 0
 #define SNDRV_DEBUG_MCE
 #endif
@@ -588,7 +586,7 @@ static int snd_ad1848_capture_prepare(snd_pcm_substream_t * substream)
 
 irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	ad1848_t *chip = snd_magic_cast(ad1848_t, dev_id, return IRQ_NONE);
+	ad1848_t *chip = dev_id;
 
 	if ((chip->mode & AD1848_MODE_PLAY) && chip->playback_substream &&
 	    (chip->mode & AD1848_MODE_RUNNING))
@@ -649,7 +647,7 @@ static void snd_ad1848_thinkpad_twiddle(ad1848_t *chip, int on) {
 #ifdef CONFIG_PM
 static int snd_ad1848_suspend(snd_card_t *card, unsigned int state)
 {
-	ad1848_t *chip = snd_magic_cast(ad1848_t, card->pm_private_data, return -EINVAL);
+	ad1848_t *chip = card->pm_private_data;
 
 	if (card->power_state == SNDRV_CTL_POWER_D3hot)
 		return 0;
@@ -666,7 +664,7 @@ static int snd_ad1848_suspend(snd_card_t *card, unsigned int state)
 
 static int snd_ad1848_resume(snd_card_t *card, unsigned int state)
 {
-	ad1848_t *chip = snd_magic_cast(ad1848_t, card->pm_private_data, return -EINVAL);
+	ad1848_t *chip = card->pm_private_data;
 
 	if (card->power_state == SNDRV_CTL_POWER_D0)
 		return 0;
@@ -867,13 +865,13 @@ static int snd_ad1848_free(ad1848_t *chip)
 		snd_dma_disable(chip->dma);
 		free_dma(chip->dma);
 	}
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_ad1848_dev_free(snd_device_t *device)
 {
-	ad1848_t *chip = snd_magic_cast(ad1848_t, device->device_data, return -ENXIO);
+	ad1848_t *chip = device->device_data;
 	return snd_ad1848_free(chip);
 }
 
@@ -901,7 +899,7 @@ int snd_ad1848_create(snd_card_t * card,
 	int err;
 
 	*rchip = NULL;
-	chip = snd_magic_kcalloc(ad1848_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
@@ -977,7 +975,7 @@ static snd_pcm_ops_t snd_ad1848_capture_ops = {
 
 static void snd_ad1848_pcm_free(snd_pcm_t *pcm)
 {
-	ad1848_t *chip = snd_magic_cast(ad1848_t, pcm->private_data, return);
+	ad1848_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
diff --git a/sound/isa/als100.c b/sound/isa/als100.c
index 6babe7ca3..ea00ec651 100644
--- a/sound/isa/als100.c
+++ b/sound/isa/als100.c
@@ -32,15 +32,12 @@
 #include <sound/opl3.h>
 #include <sound/sb.h>
 
-#define chip_t sb_t
-
 #define PFX "als100: "
 
 MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
 MODULE_DESCRIPTION("Avance Logic ALS1X0");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Avance Logic,ALS100 - PRO16PNP},"
+MODULE_SUPPORTED_DEVICE("{{Avance Logic,ALS100 - PRO16PNP},"
 	        "{Avance Logic,ALS110},"
 	        "{Avance Logic,ALS120},"
 	        "{Avance Logic,ALS200},"
@@ -63,34 +60,24 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for als100 based soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for als100 based soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable als100 based soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for als100 driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for als100 driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT12_DESC);
 module_param_array(fm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for als100 driver.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for als100 driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(mpu_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for als100 driver.");
-MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC);
 module_param_array(dma8, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma8, "8-bit DMA # for als100 driver.");
-MODULE_PARM_SYNTAX(dma8, SNDRV_DMA8_DESC);
 module_param_array(dma16, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma16, "16-bit DMA # for als100 driver.");
-MODULE_PARM_SYNTAX(dma16, SNDRV_DMA16_DESC);
 
 struct snd_card_als100 {
 	int dev_no;
diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c
index 4c71d4c0e..25a6db27e 100644
--- a/sound/isa/azt2320.c
+++ b/sound/isa/azt2320.c
@@ -43,15 +43,12 @@
 #include <sound/mpu401.h>
 #include <sound/opl3.h>
 
-#define chip_t cs4231_t
-
 #define PFX "azt2320: "
 
 MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
 MODULE_DESCRIPTION("Aztech Systems AZT2320");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Aztech Systems,PRO16V},"
+MODULE_SUPPORTED_DEVICE("{{Aztech Systems,PRO16V},"
 		"{Aztech Systems,AZT2320},"
 		"{Aztech Systems,AZT3300},"
 		"{Aztech Systems,AZT2320},"
@@ -72,37 +69,26 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for azt2320 based soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for azt2320 based soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable azt2320 based soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for azt2320 driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(wss_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(wss_port, "WSS Port # for azt2320 driver.");
-MODULE_PARM_SYNTAX(wss_port, SNDRV_PORT12_DESC);
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for azt2320 driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT12_DESC);
 module_param_array(fm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for azt2320 driver.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for azt2320 driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(mpu_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for azt2320 driver.");
-MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC);
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "1st DMA # for azt2320 driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
 module_param_array(dma2, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma2, "2nd DMA # for azt2320 driver.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC);
 
 struct snd_card_azt2320 {
 	int dev_no;
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index 60a6f4f83..631d81dfc 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -63,8 +63,7 @@
 MODULE_AUTHOR("George Talusan <gstalusan@uwaterloo.ca>");
 MODULE_DESCRIPTION("C-Media CMI8330");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{C-Media,CMI8330,isapnp:{CMI0001,@@@0001,@X@0001}}}");
+MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8330,isapnp:{CMI0001,@@@0001,@X@0001}}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
@@ -83,41 +82,30 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for CMI8330 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string  for CMI8330 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable CMI8330 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 #ifdef CONFIG_PNP
 module_param_array(isapnp, bool, boot_devs, 0444);
 MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");
-MODULE_PARM_SYNTAX(isapnp, SNDRV_ISAPNP_DESC);
 #endif
 
 module_param_array(sbport, long, boot_devs, 0444);
 MODULE_PARM_DESC(sbport, "Port # for CMI8330 SB driver.");
-MODULE_PARM_SYNTAX(sbport, SNDRV_ENABLED ",allows:{{0x220,0x280,0x20}},prefers:{0x220},base:16,dialog:list");
 module_param_array(sbirq, int, boot_devs, 0444);
 MODULE_PARM_DESC(sbirq, "IRQ # for CMI8330 SB driver.");
-MODULE_PARM_SYNTAX(sbirq, SNDRV_ENABLED ",allows:{{5},{7},{9},{10},{11},{12}},prefers:{5},dialog:list");
 module_param_array(sbdma8, int, boot_devs, 0444);
 MODULE_PARM_DESC(sbdma8, "DMA8 for CMI8330 SB driver.");
-MODULE_PARM_SYNTAX(sbdma8, SNDRV_DMA8_DESC ",prefers:{1}");
 module_param_array(sbdma16, int, boot_devs, 0444);
 MODULE_PARM_DESC(sbdma16, "DMA16 for CMI8330 SB driver.");
-MODULE_PARM_SYNTAX(sbdma16, SNDRV_ENABLED ",allows:{{5},{7}},prefers:{5},dialog:list");
 
 module_param_array(wssport, long, boot_devs, 0444);
 MODULE_PARM_DESC(wssport, "Port # for CMI8330 WSS driver.");
-MODULE_PARM_SYNTAX(wssport, SNDRV_ENABLED ",allows:{{0x530},{0xe80,0xf40,0xc0}},prefers:{0x530},base:16,dialog:list");
 module_param_array(wssirq, int, boot_devs, 0444);
 MODULE_PARM_DESC(wssirq, "IRQ # for CMI8330 WSS driver.");
-MODULE_PARM_SYNTAX(wssirq, SNDRV_ENABLED ",allows:{{5},{7},{9},{10},{11},{12}},prefers:{11},dialog:list");
 module_param_array(wssdma, int, boot_devs, 0444);
 MODULE_PARM_DESC(wssdma, "DMA for CMI8330 WSS driver.");
-MODULE_PARM_SYNTAX(wssdma, SNDRV_DMA8_DESC ",prefers:{0}");
 
 #define CMI8330_RMUX3D    16
 #define CMI8330_MUTEMUX   17
@@ -385,7 +373,7 @@ static int __devinit snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard,
 
 static int snd_cmi8330_playback_open(snd_pcm_substream_t * substream)
 {
-	struct snd_cmi8330 *chip = (struct snd_cmi8330 *)_snd_pcm_substream_chip(substream);
+	struct snd_cmi8330 *chip = snd_pcm_substream_chip(substream);
 
 	/* replace the private_data and call the original open callback */
 	substream->private_data = chip->streams[SNDRV_PCM_STREAM_PLAYBACK].private_data;
@@ -394,7 +382,7 @@ static int snd_cmi8330_playback_open(snd_pcm_substream_t * substream)
 
 static int snd_cmi8330_capture_open(snd_pcm_substream_t * substream)
 {
-	struct snd_cmi8330 *chip = (struct snd_cmi8330 *)_snd_pcm_substream_chip(substream);
+	struct snd_cmi8330 *chip = snd_pcm_substream_chip(substream);
 
 	/* replace the private_data and call the original open callback */
 	substream->private_data = chip->streams[SNDRV_PCM_STREAM_CAPTURE].private_data;
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
index 205638d50..460a94aba 100644
--- a/sound/isa/cs423x/cs4231.c
+++ b/sound/isa/cs423x/cs4231.c
@@ -30,13 +30,10 @@
 #include <sound/mpu401.h>
 #include <sound/initval.h>
 
-#define chip_t cs4231_t
-
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Generic CS4231");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Crystal Semiconductors,CS4231}}");
+MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4231}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -51,31 +48,22 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for CS4231 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for CS4231 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable CS4231 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for CS4231 driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for CS4231 driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for CS4231 driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(mpu_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for CS4231 driver.");
-MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC);
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for CS4231 driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
 module_param_array(dma2, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for CS4231 driver.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC);
 
 static snd_card_t *snd_cs4231_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
diff --git a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c
index 741ea0d4b..d323e3637 100644
--- a/sound/isa/cs423x/cs4231_lib.c
+++ b/sound/isa/cs423x/cs4231_lib.c
@@ -43,8 +43,6 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips");
 MODULE_LICENSE("GPL");
 
-#define chip_t cs4231_t
-
 #if 0
 #define SNDRV_DEBUG_MCE
 #endif
@@ -969,7 +967,7 @@ static void snd_cs4231_overrange(cs4231_t *chip)
 
 irqreturn_t snd_cs4231_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	cs4231_t *chip = snd_magic_cast(cs4231_t, dev_id, return IRQ_NONE);
+	cs4231_t *chip = dev_id;
 	unsigned char status;
 
 	status = snd_cs4231_in(chip, CS4231_IRQ_STATUS);
@@ -1407,7 +1405,7 @@ static void snd_cs4231_resume(cs4231_t *chip)
 
 static int snd_cs4231_pm_suspend(snd_card_t *card, unsigned int state)
 {
-	cs4231_t *chip = snd_magic_cast(cs4231_t, card->pm_private_data, return -EINVAL);
+	cs4231_t *chip = card->pm_private_data;
 	if (chip->suspend) {
 		chip->suspend(chip);
 		snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
@@ -1417,7 +1415,7 @@ static int snd_cs4231_pm_suspend(snd_card_t *card, unsigned int state)
 
 static int snd_cs4231_pm_resume(snd_card_t *card, unsigned int state)
 {
-	cs4231_t *chip = snd_magic_cast(cs4231_t, card->pm_private_data, return -EINVAL);
+	cs4231_t *chip = card->pm_private_data;
 	if (chip->resume) {
 		chip->resume(chip);
 		snd_power_change_state(card, SNDRV_CTL_POWER_D0);
@@ -1453,13 +1451,13 @@ static int snd_cs4231_free(cs4231_t *chip)
 	}
 	if (chip->timer)
 		snd_device_free(chip->card, chip->timer);
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_cs4231_dev_free(snd_device_t *device)
 {
-	cs4231_t *chip = snd_magic_cast(cs4231_t, device->device_data, return -ENXIO);
+	cs4231_t *chip = device->device_data;
 	return snd_cs4231_free(chip);	
 }
 
@@ -1493,7 +1491,7 @@ static int snd_cs4231_new(snd_card_t * card,
 	cs4231_t *chip;
 
 	*rchip = NULL;
-	chip = snd_magic_kcalloc(cs4231_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	chip->hardware = hardware;
@@ -1626,7 +1624,7 @@ static snd_pcm_ops_t snd_cs4231_capture_ops = {
 
 static void snd_cs4231_pcm_free(snd_pcm_t *pcm)
 {
-	cs4231_t *chip = snd_magic_cast(cs4231_t, pcm->private_data, return);
+	cs4231_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1686,7 +1684,7 @@ int snd_cs4231_pcm(cs4231_t *chip, int device, snd_pcm_t **rpcm)
 
 static void snd_cs4231_timer_free(snd_timer_t *timer)
 {
-	cs4231_t *chip = snd_magic_cast(cs4231_t, timer->private_data, return);
+	cs4231_t *chip = timer->private_data;
 	chip->timer = NULL;
 }
 
@@ -1898,8 +1896,6 @@ int snd_cs4231_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucon
 	return change;
 }
 
-#define CS4231_CONTROLS (sizeof(snd_cs4231_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs4231_controls[] = {
 CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
 CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
@@ -1938,7 +1934,7 @@ int snd_cs4231_mixer(cs4231_t *chip)
 
 	strcpy(card->mixername, chip->pcm->name);
 
-	for (idx = 0; idx < CS4231_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_cs4231_controls); idx++) {
 		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4231_controls[idx], chip))) < 0)
 			return err;
 	}
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index b2fa15a3d..ea1ee923e 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -30,14 +30,11 @@
 #include <sound/opl3.h>
 #include <sound/initval.h>
 
-#define chip_t cs4231_t
-
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 #ifdef CS4232
 MODULE_DESCRIPTION("Cirrus Logic CS4232");
-MODULE_DEVICES("{{Turtle Beach,TBS-2000},"
+MODULE_SUPPORTED_DEVICE("{{Turtle Beach,TBS-2000},"
 		"{Turtle Beach,Tropez Plus},"
 		"{SIC CrystalWave 32},"
 		"{Hewlett Packard,Omnibook 5500},"
@@ -45,7 +42,7 @@ MODULE_DEVICES("{{Turtle Beach,TBS-2000},"
 		"{Philips,PCA70PS}}");
 #else
 MODULE_DESCRIPTION("Cirrus Logic CS4235-9");
-MODULE_DEVICES("{{Crystal Semiconductors,CS4235},"
+MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4235},"
 		"{Crystal Semiconductors,CS4236},"
 		"{Crystal Semiconductors,CS4237},"
 		"{Crystal Semiconductors,CS4238},"
@@ -99,45 +96,32 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for " IDENT " soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for " IDENT " soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable " IDENT " soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 #ifdef CONFIG_PNP
 module_param_array(isapnp, bool, boot_devs, 0444);
 MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard.");
-MODULE_PARM_SYNTAX(isapnp, SNDRV_ISAPNP_DESC);
 #endif
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(cport, long, boot_devs, 0444);
 MODULE_PARM_DESC(cport, "Control port # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(cport, SNDRV_PORT12_DESC);
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT12_DESC);
 module_param_array(fm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_PORT12_DESC);
 module_param_array(sb_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(sb_port, "SB port # for " IDENT " driver (optional).");
-MODULE_PARM_SYNTAX(sb_port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(mpu_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC);
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
 module_param_array(dma2, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC);
 
 struct snd_card_cs4236 {
 	struct resource *res_sb_port;
diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c
index 788fac614..2128d4bde 100644
--- a/sound/isa/cs423x/cs4236_lib.c
+++ b/sound/isa/cs423x/cs4236_lib.c
@@ -93,8 +93,6 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Routines for control of CS4235/4236B/4237B/4238B/4239 chips");
 MODULE_LICENSE("GPL");
 
-#define chip_t cs4231_t
-
 /*
  *
  */
@@ -707,8 +705,6 @@ static int snd_cs4235_put_output_accu(snd_kcontrol_t * kcontrol, snd_ctl_elem_va
 	return change;
 }
 
-#define CS4236_CONTROLS (sizeof(snd_cs4236_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs4236_controls[] = {
 
 CS4236_DOUBLE("Master Digital Playback Switch", 0, CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),
@@ -760,8 +756,6 @@ CS4231_SINGLE("Digital Loopback Playback Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
 CS4236_DOUBLE1("Digital Loopback Playback Volume", 0, CS4231_LOOPBACK, CS4236_RIGHT_LOOPBACK, 2, 0, 63, 1)
 };
 
-#define CS4235_CONTROLS (sizeof(snd_cs4235_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs4235_controls[] = {
 
 CS4231_DOUBLE("Master Switch", 0, CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1),
@@ -871,8 +865,6 @@ static int snd_cs4236_put_iec958_switch(snd_kcontrol_t * kcontrol, snd_ctl_elem_
 	return change;
 }
 
-#define CS4236_IEC958_CONTROLS (sizeof(snd_cs4236_iec958_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs4236_iec958_controls[] = {
 CS4236_IEC958_ENABLE("IEC958 Output Enable", 0),
 CS4236_SINGLEC("IEC958 Output Validity", 0, 4, 4, 1, 0),
@@ -882,15 +874,11 @@ CS4236_SINGLEC("IEC958 Output Channel Status Low", 0, 5, 1, 127, 0),
 CS4236_SINGLEC("IEC958 Output Channel Status High", 0, 6, 0, 255, 0)
 };
 
-#define CS4236_3D_CONTROLS_CS4235 (sizeof(snd_cs4236_3d_controls_cs4235)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs4236_3d_controls_cs4235[] = {
 CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0),
 CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1)
 };
 
-#define CS4236_3D_CONTROLS_CS4237 (sizeof(snd_cs4236_3d_controls_cs4237)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs4236_3d_controls_cs4237[] = {
 CS4236_SINGLEC("3D Control - Switch", 0, 3, 7, 1, 0),
 CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1),
@@ -899,8 +887,6 @@ CS4236_SINGLEC("3D Control - Mono", 0, 3, 6, 1, 0),
 CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0)
 };
 
-#define CS4236_3D_CONTROLS_CS4238 (sizeof(snd_cs4236_3d_controls_cs4238)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cs4236_3d_controls_cs4238[] = {
 CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0),
 CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1),
@@ -921,12 +907,12 @@ int snd_cs4236_mixer(cs4231_t *chip)
 
 	if (chip->hardware == CS4231_HW_CS4235 ||
 	    chip->hardware == CS4231_HW_CS4239) {
-		for (idx = 0; idx < CS4235_CONTROLS; idx++) {
+		for (idx = 0; idx < ARRAY_SIZE(snd_cs4235_controls); idx++) {
 			if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4235_controls[idx], chip))) < 0)
 				return err;
 		}
 	} else {
-		for (idx = 0; idx < CS4236_CONTROLS; idx++) {
+		for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_controls); idx++) {
 			if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_controls[idx], chip))) < 0)
 				return err;
 		}
@@ -934,15 +920,15 @@ int snd_cs4236_mixer(cs4231_t *chip)
 	switch (chip->hardware) {
 	case CS4231_HW_CS4235:
 	case CS4231_HW_CS4239:
-		count = CS4236_3D_CONTROLS_CS4235;
+		count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4235);
 		kcontrol = snd_cs4236_3d_controls_cs4235;
 		break;
 	case CS4231_HW_CS4237B:
-		count = CS4236_3D_CONTROLS_CS4237;
+		count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4237);
 		kcontrol = snd_cs4236_3d_controls_cs4237;
 		break;
 	case CS4231_HW_CS4238B:
-		count = CS4236_3D_CONTROLS_CS4238;
+		count = ARRAY_SIZE(snd_cs4236_3d_controls_cs4238);
 		kcontrol = snd_cs4236_3d_controls_cs4238;
 		break;
 	default:
@@ -955,7 +941,7 @@ int snd_cs4236_mixer(cs4231_t *chip)
 	}
 	if (chip->hardware == CS4231_HW_CS4237B ||
 	    chip->hardware == CS4231_HW_CS4238B) {
-		for (idx = 0; idx < CS4236_IEC958_CONTROLS; idx++) {
+		for (idx = 0; idx < ARRAY_SIZE(snd_cs4236_iec958_controls); idx++) {
 			if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cs4236_iec958_controls[idx], chip))) < 0)
 				return err;
 		}
diff --git a/sound/isa/dt019x.c b/sound/isa/dt019x.c
index 40132645d..e40a5f0ab 100644
--- a/sound/isa/dt019x.c
+++ b/sound/isa/dt019x.c
@@ -33,15 +33,12 @@
 #include <sound/opl3.h>
 #include <sound/sb.h>
 
-#define chip_t sb_t
-
 #define PFX "dt019x: "
 
 MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
 MODULE_DESCRIPTION("Diamond Technologies DT-019X / Avance Logic ALS-007");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Diamond Technologies DT-019X},"
+MODULE_SUPPORTED_DEVICE("{{Diamond Technologies DT-019X},"
 	       "{Avance Logic ALS-007}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
@@ -57,31 +54,22 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for DT-019X based soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for DT-019X based soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable DT-019X based soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for dt019x driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for dt019x driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT12_DESC);
 module_param_array(fm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for dt019x driver.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for dt019x driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(mpu_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for dt019x driver.");
-MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC);
 module_param_array(dma8, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma8, "8-bit DMA # for dt019x driver.");
-MODULE_PARM_SYNTAX(dma8, SNDRV_DMA8_DESC);
 
 struct snd_card_dt019x {
 	struct pnp_dev *dev;
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
index a4a5a7c9a..dcb274b22 100644
--- a/sound/isa/es1688/es1688.c
+++ b/sound/isa/es1688/es1688.c
@@ -37,8 +37,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("ESS ESx688 AudioDrive");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ESS,ES688 PnP AudioDrive,pnp:ESS0100},"
+MODULE_SUPPORTED_DEVICE("{{ESS,ES688 PnP AudioDrive,pnp:ESS0100},"
 	        "{ESS,ES1688 PnP AudioDrive,pnp:ESS0102},"
 	        "{ESS,ES688 AudioDrive,pnp:ESS6881},"
 	        "{ESS,ES1688 AudioDrive,pnp:ESS1681}}");
@@ -55,28 +54,20 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for ESx688 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for ESx688 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable ESx688 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for ESx688 driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for ESx688 driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for ESx688 driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(mpu_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for ESx688 driver.");
-MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC);
 module_param_array(dma8, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma8, "8-bit DMA # for ESx688 driver.");
-MODULE_PARM_SYNTAX(dma8, SNDRV_DMA8_DESC);
 
 static snd_card_t *snd_audiodrive_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c
index 66d08b804..c20bc7fc8 100644
--- a/sound/isa/es1688/es1688_lib.c
+++ b/sound/isa/es1688/es1688_lib.c
@@ -34,7 +34,6 @@
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("ESS ESx688 lowlevel module");
-MODULE_CLASSES("{sound}");
 MODULE_LICENSE("GPL");
 
 static int snd_es1688_dsp_command(es1688_t *chip, unsigned char val)
@@ -482,7 +481,7 @@ static int snd_es1688_capture_trigger(snd_pcm_substream_t * substream,
 
 irqreturn_t snd_es1688_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	es1688_t *chip = snd_magic_cast(es1688_t, dev_id, return IRQ_NONE);
+	es1688_t *chip = dev_id;
 
 	if (chip->trigger_value == 0x05)	/* ok.. playback is active */
 		snd_pcm_period_elapsed(chip->playback_substream);
@@ -616,13 +615,13 @@ static int snd_es1688_free(es1688_t *chip)
 		disable_dma(chip->dma8);
 		free_dma(chip->dma8);
 	}
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_es1688_dev_free(snd_device_t *device)
 {
-	es1688_t *chip = snd_magic_cast(es1688_t, device->device_data, return -ENXIO);
+	es1688_t *chip = device->device_data;
 	return snd_es1688_free(chip);
 }
 
@@ -650,7 +649,7 @@ int snd_es1688_create(snd_card_t * card,
 	int err;
 
 	*rchip = NULL;
-	chip = snd_magic_kcalloc(es1688_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	chip->irq = -1;
@@ -728,7 +727,7 @@ static snd_pcm_ops_t snd_es1688_capture_ops = {
 
 static void snd_es1688_pcm_free(snd_pcm_t *pcm)
 {
-	es1688_t *chip = snd_magic_cast(es1688_t, pcm->private_data, return);
+	es1688_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -978,8 +977,6 @@ static int snd_es1688_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 	return change;
 }
 
-#define ES1688_CONTROLS (sizeof(snd_es1688_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_es1688_controls[] = {
 ES1688_DOUBLE("Master Playback Volume", 0, ES1688_MASTER_DEV, ES1688_MASTER_DEV, 4, 0, 15, 0),
 ES1688_DOUBLE("PCM Playback Volume", 0, ES1688_PCM_DEV, ES1688_PCM_DEV, 4, 0, 15, 0),
@@ -1028,7 +1025,7 @@ int snd_es1688_mixer(es1688_t *chip)
 
 	strcpy(card->mixername, snd_es1688_chip_id(chip));
 
-	for (idx = 0; idx < ES1688_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_es1688_controls); idx++) {
 		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es1688_controls[idx], chip))) < 0)
 			return err;
 	}
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 202eab49e..1b974f963 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -157,8 +157,6 @@ struct _snd_es18xx {
 
 typedef struct _snd_es18xx es18xx_t;
 
-#define chip_t es18xx_t
-
 /* Lowlevel */
 
 #define DAC1 0x01
@@ -728,7 +726,7 @@ static int snd_es18xx_playback_trigger(snd_pcm_substream_t *substream,
 
 static irqreturn_t snd_es18xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	es18xx_t *chip = snd_magic_cast(es18xx_t, dev_id, return IRQ_NONE);
+	es18xx_t *chip = dev_id;
 	unsigned char status;
 
 	if (chip->caps & ES18XX_CONTROL) {
@@ -1027,7 +1025,7 @@ static int snd_es18xx_get_hw_switch(snd_kcontrol_t * kcontrol, snd_ctl_elem_valu
 
 static void snd_es18xx_hwv_free(snd_kcontrol_t *kcontrol)
 {
-	es18xx_t *chip = snd_magic_cast(es18xx_t, _snd_kcontrol_chip(kcontrol), return);
+	es18xx_t *chip = snd_kcontrol_chip(kcontrol);
 	chip->master_volume = NULL;
 	chip->master_switch = NULL;
 	chip->hw_volume = NULL;
@@ -1561,7 +1559,7 @@ static snd_pcm_ops_t snd_es18xx_capture_ops = {
 
 static void snd_es18xx_pcm_free(snd_pcm_t *pcm)
 {
-	es18xx_t *codec = snd_magic_cast(es18xx_t, pcm->private_data, return);
+	es18xx_t *codec = pcm->private_data;
 	codec->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1611,7 +1609,7 @@ int __devinit snd_es18xx_pcm(es18xx_t *chip, int device, snd_pcm_t ** rpcm)
 #ifdef CONFIG_PM
 static int snd_es18xx_suspend(snd_card_t *card, unsigned int state)
 {
-	es18xx_t *chip = snd_magic_cast(es18xx_t, card->pm_private_data, return -EINVAL);
+	es18xx_t *chip = card->pm_private_data;
 
 	snd_pcm_suspend_all(chip->pcm);
 
@@ -1627,7 +1625,7 @@ static int snd_es18xx_suspend(snd_card_t *card, unsigned int state)
 
 static int snd_es18xx_resume(snd_card_t *card, unsigned int state)
 {
-	es18xx_t *chip = snd_magic_cast(es18xx_t, card->pm_private_data, return -EINVAL);
+	es18xx_t *chip = card->pm_private_data;
 
 	/* restore PM register, we won't wake till (not 0x07) i/o activity though */
 	snd_es18xx_write(chip, ES18XX_PM, chip->pm_reg ^= ES18XX_PM_FM);
@@ -1661,13 +1659,13 @@ static int snd_es18xx_free(es18xx_t *chip)
 		disable_dma(chip->dma2);
 		free_dma(chip->dma2);
 	}
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_es18xx_dev_free(snd_device_t *device)
 {
-	es18xx_t *chip = snd_magic_cast(es18xx_t, device->device_data, return -ENXIO);
+	es18xx_t *chip = device->device_data;
 	return snd_es18xx_free(chip);
 }
 
@@ -1685,7 +1683,7 @@ static int __devinit snd_es18xx_new_device(snd_card_t * card,
 	int err;
 
 	*rchip = NULL;
-        chip = snd_magic_kcalloc(es18xx_t, 0, GFP_KERNEL);
+        chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
@@ -1830,8 +1828,7 @@ static int __devinit snd_es18xx_mixer(es18xx_t *chip)
 MODULE_AUTHOR("Christian Fischbach <fishbach@pool.informatik.rwth-aachen.de>, Abramo Bagnara <abramo@alsa-project.org>");  
 MODULE_DESCRIPTION("ESS ES18xx AudioDrive");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ESS,ES1868 PnP AudioDrive},"
+MODULE_SUPPORTED_DEVICE("{{ESS,ES1868 PnP AudioDrive},"
 		"{ESS,ES1869 PnP AudioDrive},"
 		"{ESS,ES1878 PnP AudioDrive},"
 		"{ESS,ES1879 PnP AudioDrive},"
@@ -1860,36 +1857,26 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for ES18xx soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for ES18xx soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable ES18xx soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 #ifdef CONFIG_PNP
 module_param_array(isapnp, bool, boot_devs, 0444);
 MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");
-MODULE_PARM_SYNTAX(isapnp, SNDRV_ISAPNP_DESC);
 #endif
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for ES18xx driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_ENABLED ",allows:{{0x220,0x280,0x20}},prefers:{0x220},base:16,dialog:list");
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for ES18xx driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_ENABLED ",allows:{{0x300,0x330,0x30},{0x800,0xffe,0x2}},prefers:{0x330,0x300},base:16,dialog:combo");
 module_param_array(fm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for ES18xx driver.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_ENABLED ",allows:{{0x388},{0x800,0xffc,0x4}},prefers:{0x388},base:16,dialog:combo");
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for ES18xx driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC ",prefers:{5}");
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "DMA 1 # for ES18xx driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA8_DESC ",prefers:{1}");
 module_param_array(dma2, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma2, "DMA 2 # for ES18xx driver.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_ENABLED ",allows:{{0},{1},{3},{5}},dialog:list,prefers:{0}");
 
 struct snd_audiodrive {
 #ifdef CONFIG_PNP
diff --git a/sound/isa/gus/Makefile b/sound/isa/gus/Makefile
index 00df354fd..bae5dbd6c 100644
--- a/sound/isa/gus/Makefile
+++ b/sound/isa/gus/Makefile
@@ -27,14 +27,10 @@ sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_GUSCLASSIC) += snd-gusclassic.o snd-gus-lib.o
-obj-$(call sequencer,$(CONFIG_SND_GUSCLASSIC)) += snd-gus-synth.o
 obj-$(CONFIG_SND_GUSMAX) += snd-gusmax.o snd-gus-lib.o
-obj-$(call sequencer,$(CONFIG_SND_GUSMAX)) += snd-gus-synth.o
 obj-$(CONFIG_SND_GUSEXTREME) += snd-gusextreme.o snd-gus-lib.o
-obj-$(call sequencer,$(CONFIG_SND_GUSEXTREME)) += snd-gus-synth.o
 obj-$(CONFIG_SND_INTERWAVE) += snd-interwave.o snd-gus-lib.o
-obj-$(call sequencer,$(CONFIG_SND_INTERWAVE)) += snd-gus-synth.o
 obj-$(CONFIG_SND_INTERWAVE_STB) += snd-interwave-stb.o snd-gus-lib.o
-obj-$(call sequencer,$(CONFIG_SND_INTERWAVE_STB)) += snd-gus-synth.o
+obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-gus-synth.o
 
 obj-m := $(sort $(obj-m))
diff --git a/sound/isa/gus/gus_dram.c b/sound/isa/gus/gus_dram.c
index 0b73d4c5f..22120b868 100644
--- a/sound/isa/gus/gus_dram.c
+++ b/sound/isa/gus/gus_dram.c
@@ -31,12 +31,12 @@ static int snd_gus_dram_poke(snd_gus_card_t *gus, char __user *_buffer,
 {
 	unsigned long flags;
 	unsigned int size1, size2;
-	char buffer[512], *pbuffer;
+	char buffer[256], *pbuffer;
 
 	while (size > 0) {
-		if (copy_from_user(buffer, _buffer, 512))
+		size1 = size > sizeof(buffer) ? sizeof(buffer) : size;
+		if (copy_from_user(buffer, _buffer, size1))
 			return -EFAULT;
-		size1 = size > 512 ? 512 : size;
 		if (gus->interwave) {
 			spin_lock_irqsave(&gus->reg_lock, flags);
 			snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, 0x01);
@@ -69,10 +69,10 @@ static int snd_gus_dram_peek(snd_gus_card_t *gus, char __user *_buffer,
 {
 	unsigned long flags;
 	unsigned int size1, size2;
-	char buffer[512], *pbuffer;
+	char buffer[256], *pbuffer;
 
 	while (size > 0) {
-		size1 = size > 512 ? 512 : size;
+		size1 = size > sizeof(buffer) ? sizeof(buffer) : size;
 		if (gus->interwave) {
 			spin_lock_irqsave(&gus->reg_lock, flags);
 			snd_gf1_write8(gus, SNDRV_GF1_GB_MEMORY_CONTROL, rom ? 0x03 : 0x01);
diff --git a/sound/isa/gus/gus_instr.c b/sound/isa/gus/gus_instr.c
index e819e907b..591a9a17f 100644
--- a/sound/isa/gus/gus_instr.c
+++ b/sound/isa/gus/gus_instr.c
@@ -31,7 +31,7 @@
 int snd_gus_iwffff_put_sample(void *private_data, iwffff_wave_t *wave,
 			      char __user *data, long len, int atomic)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+	snd_gus_card_t *gus = private_data;
 	snd_gf1_mem_block_t *block;
 	int err;
 
@@ -61,7 +61,7 @@ int snd_gus_iwffff_put_sample(void *private_data, iwffff_wave_t *wave,
 int snd_gus_iwffff_get_sample(void *private_data, iwffff_wave_t *wave,
 			      char __user *data, long len, int atomic)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+	snd_gus_card_t *gus = private_data;
 
 	return snd_gus_dram_read(gus, data, wave->address.memory, wave->size,
 				 wave->format & IWFFFF_WAVE_ROM ? 1 : 0);
@@ -70,7 +70,7 @@ int snd_gus_iwffff_get_sample(void *private_data, iwffff_wave_t *wave,
 int snd_gus_iwffff_remove_sample(void *private_data, iwffff_wave_t *wave,
 				 int atomic)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+	snd_gus_card_t *gus = private_data;
 
 	if (wave->format & IWFFFF_WAVE_ROM)
 		return 0;	/* it's probably ok - verify the address? */	
@@ -84,7 +84,7 @@ int snd_gus_iwffff_remove_sample(void *private_data, iwffff_wave_t *wave,
 int snd_gus_gf1_put_sample(void *private_data, gf1_wave_t *wave,
 			   char __user *data, long len, int atomic)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+	snd_gus_card_t *gus = private_data;
 	snd_gf1_mem_block_t *block;
 	int err;
 
@@ -112,7 +112,7 @@ int snd_gus_gf1_put_sample(void *private_data, gf1_wave_t *wave,
 int snd_gus_gf1_get_sample(void *private_data, gf1_wave_t *wave,
 			   char __user *data, long len, int atomic)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+	snd_gus_card_t *gus = private_data;
 
 	return snd_gus_dram_read(gus, data, wave->address.memory, wave->size, 0);
 }
@@ -120,7 +120,7 @@ int snd_gus_gf1_get_sample(void *private_data, gf1_wave_t *wave,
 int snd_gus_gf1_remove_sample(void *private_data, gf1_wave_t *wave,
 			      int atomic)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+	snd_gus_card_t *gus = private_data;
 
 	return snd_gf1_mem_free(&gus->gf1.mem_alloc, wave->address.memory);
 }
@@ -132,7 +132,7 @@ int snd_gus_gf1_remove_sample(void *private_data, gf1_wave_t *wave,
 int snd_gus_simple_put_sample(void *private_data, simple_instrument_t *instr,
 			      char __user *data, long len, int atomic)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+	snd_gus_card_t *gus = private_data;
 	snd_gf1_mem_block_t *block;
 	int err;
 
@@ -159,7 +159,7 @@ int snd_gus_simple_put_sample(void *private_data, simple_instrument_t *instr,
 int snd_gus_simple_get_sample(void *private_data, simple_instrument_t *instr,
 			      char __user *data, long len, int atomic)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+	snd_gus_card_t *gus = private_data;
 
 	return snd_gus_dram_read(gus, data, instr->address.memory, instr->size, 0);
 }
@@ -167,7 +167,7 @@ int snd_gus_simple_get_sample(void *private_data, simple_instrument_t *instr,
 int snd_gus_simple_remove_sample(void *private_data, simple_instrument_t *instr,
 			         int atomic)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return -ENXIO);
+	snd_gus_card_t *gus = private_data;
 
 	return snd_gf1_mem_free(&gus->gf1.mem_alloc, instr->address.memory);
 }
diff --git a/sound/isa/gus/gus_irq.c b/sound/isa/gus/gus_irq.c
index 4aeabe8eb..1e2a15eb8 100644
--- a/sound/isa/gus/gus_irq.c
+++ b/sound/isa/gus/gus_irq.c
@@ -32,7 +32,7 @@
 
 irqreturn_t snd_gus_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	snd_gus_card_t * gus = snd_magic_cast(snd_gus_card_t, dev_id, return IRQ_NONE);
+	snd_gus_card_t * gus = dev_id;
 	unsigned char status;
 	int loop = 100;
 	int handled = 0;
@@ -114,7 +114,7 @@ static void snd_gus_irq_info_read(snd_info_entry_t *entry,
 	snd_gus_voice_t *pvoice;
 	int idx;
 
-	gus = snd_magic_cast(snd_gus_card_t, entry->private_data, return);
+	gus = entry->private_data;
 	snd_iprintf(buffer, "midi out = %u\n", gus->gf1.interrupt_stat_midi_out);
 	snd_iprintf(buffer, "midi in = %u\n", gus->gf1.interrupt_stat_midi_in);
 	snd_iprintf(buffer, "timer1 = %u\n", gus->gf1.interrupt_stat_timer1);
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
index 64558c209..73f81c14f 100644
--- a/sound/isa/gus/gus_main.c
+++ b/sound/isa/gus/gus_main.c
@@ -35,8 +35,6 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards");
 MODULE_LICENSE("GPL");
 
-#define chip_t snd_gus_card_t
-
 static int snd_gus_init_dma_irq(snd_gus_card_t * gus, int latches);
 
 int snd_gus_use_inc(snd_gus_card_t * gus)
@@ -133,13 +131,13 @@ static int snd_gus_free(snd_gus_card_t *gus)
 		disable_dma(gus->gf1.dma2);
 		free_dma(gus->gf1.dma2);
 	}
-	snd_magic_kfree(gus);
+	kfree(gus);
 	return 0;
 }
 
 static int snd_gus_dev_free(snd_device_t *device)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, device->device_data, return -ENXIO);
+	snd_gus_card_t *gus = device->device_data;
 	return snd_gus_free(gus);
 }
 
@@ -159,7 +157,7 @@ int snd_gus_create(snd_card_t * card,
 	};
 
 	*rgus = NULL;
-	gus = snd_magic_kcalloc(snd_gus_card_t, 0, GFP_KERNEL);
+	gus = kcalloc(1, sizeof(*gus), GFP_KERNEL);
 	if (gus == NULL)
 		return -ENOMEM;
 	gus->gf1.irq = -1;
@@ -421,7 +419,7 @@ static int snd_gus_check_version(snd_gus_card_t * gus)
 
 static void snd_gus_seq_dev_free(snd_seq_device_t *seq_dev)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, seq_dev->private_data, return);
+	snd_gus_card_t *gus = seq_dev->private_data;
 	gus->seq_dev = NULL;
 }
 
diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c
index 783f5dd4f..75ae3aa48 100644
--- a/sound/isa/gus/gus_mem.c
+++ b/sound/isa/gus/gus_mem.c
@@ -297,7 +297,7 @@ static void snd_gf1_mem_info_read(snd_info_entry_t *entry,
 	unsigned int total, used;
 	int i;
 
-	gus = snd_magic_cast(snd_gus_card_t, entry->private_data, return);
+	gus = entry->private_data;
 	alloc = &gus->gf1.mem_alloc;
 	down(&alloc->memory_mutex);
 	snd_iprintf(buffer, "8-bit banks       : \n    ");
diff --git a/sound/isa/gus/gus_mem_proc.c b/sound/isa/gus/gus_mem_proc.c
index 6ee2d76ee..886763f12 100644
--- a/sound/isa/gus/gus_mem_proc.c
+++ b/sound/isa/gus/gus_mem_proc.c
@@ -37,7 +37,7 @@ static long snd_gf1_mem_proc_dump(snd_info_entry_t *entry, void *file_private_da
 			          unsigned long count, unsigned long pos)
 {
 	long size;
-	gus_proc_private_t *priv = snd_magic_cast(gus_proc_private_t, entry->private_data, return -ENXIO);
+	gus_proc_private_t *priv = entry->private_data;
 	snd_gus_card_t *gus = priv->gus;
 	int err;
 
@@ -58,7 +58,7 @@ static long long snd_gf1_mem_proc_llseek(snd_info_entry_t *entry,
 					long long offset,
 					int orig)
 {
-	gus_proc_private_t *priv = snd_magic_cast(gus_proc_private_t, entry->private_data, return -ENXIO);
+	gus_proc_private_t *priv = entry->private_data;
 
 	switch (orig) {
 	case 0:	/* SEEK_SET */
@@ -80,8 +80,8 @@ static long long snd_gf1_mem_proc_llseek(snd_info_entry_t *entry,
 
 static void snd_gf1_mem_proc_free(snd_info_entry_t *entry)
 {
-	gus_proc_private_t *priv = snd_magic_cast(gus_proc_private_t, entry->private_data, return);
-	snd_magic_kfree(priv);
+	gus_proc_private_t *priv = entry->private_data;
+	kfree(priv);
 }
 
 static struct snd_info_entry_ops snd_gf1_mem_proc_ops = {
@@ -98,7 +98,7 @@ int snd_gf1_mem_proc_init(snd_gus_card_t * gus)
 
 	for (idx = 0; idx < 4; idx++) {
 		if (gus->gf1.mem_alloc.banks_8[idx].size > 0) {
-			priv = snd_magic_kcalloc(gus_proc_private_t, 0, GFP_KERNEL);
+			priv = kcalloc(1, sizeof(*priv), GFP_KERNEL);
 			if (priv == NULL)
 				return -ENOMEM;
 			priv->gus = gus;
@@ -115,7 +115,7 @@ int snd_gf1_mem_proc_init(snd_gus_card_t * gus)
 	}
 	for (idx = 0; idx < 4; idx++) {
 		if (gus->gf1.rom_present & (1 << idx)) {
-			priv = snd_magic_kcalloc(gus_proc_private_t, 0, GFP_KERNEL);
+			priv = kcalloc(1, sizeof(*priv), GFP_KERNEL);
 			if (priv == NULL)
 				return -ENOMEM;
 			priv->rom = 1;
diff --git a/sound/isa/gus/gus_mixer.c b/sound/isa/gus/gus_mixer.c
index 651071a4b..a051094d5 100644
--- a/sound/isa/gus/gus_mixer.c
+++ b/sound/isa/gus/gus_mixer.c
@@ -26,8 +26,6 @@
 #include <sound/control.h>
 #include <sound/gus.h>
 
-#define chip_t snd_gus_card_t
-
 /*
  *
  */
@@ -148,16 +146,12 @@ static int snd_ics_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
 	return change;
 }
 
-#define GF1_CONTROLS (sizeof(snd_gf1_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_gf1_controls[] = {
 GF1_SINGLE("Master Playback Switch", 0, 1, 1),
 GF1_SINGLE("Line Switch", 0, 0, 1),
 GF1_SINGLE("Mic Switch", 0, 2, 0)
 };
 
-#define ICS_CONTROLS (sizeof(snd_ics_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_ics_controls[] = {
 GF1_SINGLE("Master Playback Switch", 0, 1, 1),
 ICS_DOUBLE("Master Playback Volume", 0, SNDRV_ICS_MASTER_DEV),
@@ -190,13 +184,13 @@ int snd_gf1_new_mixer(snd_gus_card_t * gus)
 	}
 
 	if (!gus->ics_flag) {
-		max = gus->ess_flag ? 1 : GF1_CONTROLS;
+		max = gus->ess_flag ? 1 : ARRAY_SIZE(snd_gf1_controls);
 		for (idx = 0; idx < max; idx++) {
 			if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_gf1_controls[idx], gus))) < 0)
 				return err;
 		}
 	} else {
-		for (idx = 0; idx < ICS_CONTROLS; idx++) {
+		for (idx = 0; idx < ARRAY_SIZE(snd_ics_controls); idx++) {
 			if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ics_controls[idx], gus))) < 0)
 				return err;
 		}
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
index 040804ca8..aca7f3ad3 100644
--- a/sound/isa/gus/gus_pcm.c
+++ b/sound/isa/gus/gus_pcm.c
@@ -34,8 +34,6 @@
 #include <sound/pcm_params.h>
 #include "gus_tables.h"
 
-#define chip_t snd_gus_card_t
-
 /* maximum rate */
 
 #define SNDRV_GF1_PCM_RATE		48000
@@ -66,7 +64,7 @@ static int snd_gf1_pcm_use_dma = 1;
 
 static void snd_gf1_pcm_block_change_ack(snd_gus_card_t * gus, void *private_data)
 {
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, private_data, return);
+	gus_pcm_private_t *pcmp = private_data;
 
 	if (pcmp) {
 		atomic_dec(&pcmp->dma_count);
@@ -81,7 +79,7 @@ static int snd_gf1_pcm_block_change(snd_pcm_substream_t * substream,
 {
 	snd_gf1_dma_block_t block;
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+	gus_pcm_private_t *pcmp = runtime->private_data;
 
 	count += offset & 31;
 	offset &= ~31;
@@ -106,7 +104,7 @@ static int snd_gf1_pcm_block_change(snd_pcm_substream_t * substream,
 static void snd_gf1_pcm_trigger_up(snd_pcm_substream_t * substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return);
+	gus_pcm_private_t *pcmp = runtime->private_data;
 	snd_gus_card_t * gus = pcmp->gus;
 	unsigned long flags;
 	unsigned char voice_ctrl, ramp_ctrl;
@@ -194,7 +192,7 @@ static void snd_gf1_pcm_interrupt_wave(snd_gus_card_t * gus, snd_gus_voice_t *pv
 		snd_gf1_smart_stop_voice(gus, pvoice->number);
 		return;
 	}
-	pcmp = snd_magic_cast(gus_pcm_private_t, pvoice->private_data, return);
+	pcmp = pvoice->private_data;
 	if (pcmp == NULL) {
 		snd_printd("snd_gf1_pcm: unknown wave irq?\n");
 		snd_gf1_smart_stop_voice(gus, pvoice->number);
@@ -267,7 +265,7 @@ static void snd_gf1_pcm_interrupt_volume(snd_gus_card_t * gus, snd_gus_voice_t *
 {
 	unsigned short vol;
 	int cvoice;
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, pvoice->private_data, return);
+	gus_pcm_private_t *pcmp = pvoice->private_data;
 
 	/* stop ramp, but leave rollover bit untouched */
 	spin_lock(&gus->reg_lock);
@@ -350,7 +348,7 @@ static int snd_gf1_pcm_playback_copy(snd_pcm_substream_t *substream,
 				     snd_pcm_uframes_t count)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+	gus_pcm_private_t *pcmp = runtime->private_data;
 	unsigned int bpos, len;
 	
 	bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2));
@@ -379,7 +377,7 @@ static int snd_gf1_pcm_playback_silence(snd_pcm_substream_t *substream,
 					snd_pcm_uframes_t count)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+	gus_pcm_private_t *pcmp = runtime->private_data;
 	unsigned int bpos, len;
 	
 	bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2));
@@ -406,7 +404,7 @@ static int snd_gf1_pcm_playback_hw_params(snd_pcm_substream_t * substream,
 {
 	snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+	gus_pcm_private_t *pcmp = runtime->private_data;
 	int err;
 	
 	if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
@@ -453,7 +451,7 @@ static int snd_gf1_pcm_playback_hw_params(snd_pcm_substream_t * substream,
 static int snd_gf1_pcm_playback_hw_free(snd_pcm_substream_t * substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+	gus_pcm_private_t *pcmp = runtime->private_data;
 
 	snd_pcm_lib_free_pages(substream);
 	if (pcmp->pvoices[0]) {
@@ -474,7 +472,7 @@ static int snd_gf1_pcm_playback_hw_free(snd_pcm_substream_t * substream)
 static int snd_gf1_pcm_playback_prepare(snd_pcm_substream_t * substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+	gus_pcm_private_t *pcmp = runtime->private_data;
 
 	pcmp->bpos = 0;
 	pcmp->dma_size = snd_pcm_lib_buffer_bytes(substream);
@@ -488,7 +486,7 @@ static int snd_gf1_pcm_playback_trigger(snd_pcm_substream_t * substream,
 {
 	snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+	gus_pcm_private_t *pcmp = runtime->private_data;
 	int voice;
 
 	if (cmd == SNDRV_PCM_TRIGGER_START) {
@@ -513,7 +511,7 @@ static snd_pcm_uframes_t snd_gf1_pcm_playback_pointer(snd_pcm_substream_t * subs
 {
 	snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+	gus_pcm_private_t *pcmp = runtime->private_data;
 	unsigned int pos;
 	unsigned char voice_ctrl;
 
@@ -657,8 +655,8 @@ static snd_pcm_hardware_t snd_gf1_pcm_capture =
 
 static void snd_gf1_pcm_playback_free(snd_pcm_runtime_t *runtime)
 {
-	gus_pcm_private_t * pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return);
-	snd_magic_kfree(pcmp);
+	gus_pcm_private_t * pcmp = runtime->private_data;
+	kfree(pcmp);
 }
 
 static int snd_gf1_pcm_playback_open(snd_pcm_substream_t *substream)
@@ -668,7 +666,7 @@ static int snd_gf1_pcm_playback_open(snd_pcm_substream_t *substream)
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int err;
 
-	pcmp = snd_magic_kcalloc(gus_pcm_private_t, 0, GFP_KERNEL);
+	pcmp = kcalloc(1, sizeof(*pcmp), GFP_KERNEL);
 	if (pcmp == NULL)
 		return -ENOMEM;
 	pcmp->gus = gus;
@@ -697,7 +695,7 @@ static int snd_gf1_pcm_playback_close(snd_pcm_substream_t * substream)
 {
 	snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	gus_pcm_private_t *pcmp = snd_magic_cast(gus_pcm_private_t, runtime->private_data, return -ENXIO);
+	gus_pcm_private_t *pcmp = runtime->private_data;
 	unsigned long jiffies_old;
 
 	jiffies_old = jiffies;
@@ -738,7 +736,7 @@ static int snd_gf1_pcm_capture_close(snd_pcm_substream_t * substream)
 
 static void snd_gf1_pcm_free(snd_pcm_t *pcm)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, pcm->private_data, return);
+	snd_gus_card_t *gus = pcm->private_data;
 	gus->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -790,7 +788,7 @@ static int snd_gf1_pcm_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
 		pvoice = &gus->gf1.voices[idx];
 		if (!pvoice->pcm)
 			continue;
-		pcmp = snd_magic_cast(gus_pcm_private_t, pvoice->private_data, return -ENXIO);
+		pcmp = pvoice->private_data;
 		if (!(pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE))
 			continue;
 		/* load real volume - better precision */
diff --git a/sound/isa/gus/gus_synth.c b/sound/isa/gus/gus_synth.c
index 47f88a2ee..c7ff30443 100644
--- a/sound/isa/gus/gus_synth.c
+++ b/sound/isa/gus/gus_synth.c
@@ -134,7 +134,7 @@ static void snd_gus_synth_instr_notify(void *private_data,
 				       int what)
 {
 	unsigned int idx;
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, private_data, return);
+	snd_gus_card_t *gus = private_data;
 	snd_gus_voice_t *pvoice;
 	unsigned long flags;
 	
diff --git a/sound/isa/gus/gus_timer.c b/sound/isa/gus/gus_timer.c
index 854b35db7..9876603ff 100644
--- a/sound/isa/gus/gus_timer.c
+++ b/sound/isa/gus/gus_timer.c
@@ -26,8 +26,6 @@
 #include <sound/core.h>
 #include <sound/gus.h>
 
-#define chip_t snd_gus_card_t
-
 /*
  *  Timer 1 - 80us
  */
@@ -146,13 +144,13 @@ static struct _snd_timer_hardware snd_gf1_timer2 =
 
 static void snd_gf1_timer1_free(snd_timer_t *timer)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, timer->private_data, return);
+	snd_gus_card_t *gus = timer->private_data;
 	gus->gf1.timer1 = NULL;
 }
 
 static void snd_gf1_timer2_free(snd_timer_t *timer)
 {
-	snd_gus_card_t *gus = snd_magic_cast(snd_gus_card_t, timer->private_data, return);
+	snd_gus_card_t *gus = timer->private_data;
 	gus->gf1.timer2 = NULL;
 }
 
diff --git a/sound/isa/gus/gus_uart.c b/sound/isa/gus/gus_uart.c
index 8b09be2a2..1bc2da878 100644
--- a/sound/isa/gus/gus_uart.c
+++ b/sound/isa/gus/gus_uart.c
@@ -95,7 +95,7 @@ static int snd_gf1_uart_output_open(snd_rawmidi_substream_t * substream)
 	unsigned long flags;
 	snd_gus_card_t *gus;
 
-	gus = snd_magic_cast(snd_gus_card_t, substream->rmidi->private_data, return -ENXIO);
+	gus = substream->rmidi->private_data;
 	spin_lock_irqsave(&gus->uart_cmd_lock, flags);
 	if (!(gus->gf1.uart_cmd & 0x80)) {	/* input active? */
 		snd_gf1_uart_reset(gus, 0);
@@ -115,7 +115,7 @@ static int snd_gf1_uart_input_open(snd_rawmidi_substream_t * substream)
 	snd_gus_card_t *gus;
 	int i;
 
-	gus = snd_magic_cast(snd_gus_card_t, substream->rmidi->private_data, return -ENXIO);
+	gus = substream->rmidi->private_data;
 	spin_lock_irqsave(&gus->uart_cmd_lock, flags);
 	if (gus->gf1.interrupt_handler_midi_out != snd_gf1_interrupt_midi_out) {
 		snd_gf1_uart_reset(gus, 0);
@@ -141,7 +141,7 @@ static int snd_gf1_uart_output_close(snd_rawmidi_substream_t * substream)
 	unsigned long flags;
 	snd_gus_card_t *gus;
 
-	gus = snd_magic_cast(snd_gus_card_t, substream->rmidi->private_data, return -ENXIO);
+	gus = substream->rmidi->private_data;
 	spin_lock_irqsave(&gus->uart_cmd_lock, flags);
 	if (gus->gf1.interrupt_handler_midi_in != snd_gf1_interrupt_midi_in)
 		snd_gf1_uart_reset(gus, 1);
@@ -156,7 +156,7 @@ static int snd_gf1_uart_input_close(snd_rawmidi_substream_t * substream)
 	unsigned long flags;
 	snd_gus_card_t *gus;
 
-	gus = snd_magic_cast(snd_gus_card_t, substream->rmidi->private_data, return -ENXIO);
+	gus = substream->rmidi->private_data;
 	spin_lock_irqsave(&gus->uart_cmd_lock, flags);
 	if (gus->gf1.interrupt_handler_midi_out != snd_gf1_interrupt_midi_out)
 		snd_gf1_uart_reset(gus, 1);
@@ -171,7 +171,7 @@ static void snd_gf1_uart_input_trigger(snd_rawmidi_substream_t * substream, int
 	snd_gus_card_t *gus;
 	unsigned long flags;
 
-	gus = snd_magic_cast(snd_gus_card_t, substream->rmidi->private_data, return);
+	gus = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&gus->uart_cmd_lock, flags);
 	if (up) {
@@ -191,7 +191,7 @@ static void snd_gf1_uart_output_trigger(snd_rawmidi_substream_t * substream, int
 	char byte;
 	int timeout;
 
-	gus = snd_magic_cast(snd_gus_card_t, substream->rmidi->private_data, return);
+	gus = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&gus->uart_cmd_lock, flags);
 	if (up) {
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
index e876402c3..83b472da6 100644
--- a/sound/isa/gus/gusclassic.c
+++ b/sound/isa/gus/gusclassic.c
@@ -35,8 +35,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Gravis UltraSound Classic");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Gravis,UltraSound Classic}}");
+MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Classic}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -53,34 +52,24 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for GUS Classic soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for GUS Classic soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable GUS Classic soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for GUS Classic driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_ENABLED ",allows:{{0x220,0x260,0x10}},dialog:list");
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for GUS Classic driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_ENABLED ",allows:{{3},{5},{9},{11},{12},{15}},dialog:list");
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for GUS Classic driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_ENABLED ",allows:{{1},{3},{5},{6},{7}},dialog:list");
 module_param_array(dma2, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for GUS Classic driver.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_ENABLED ",allows:{{1},{3},{5},{6},{7}},dialog:list");
 module_param_array(joystick_dac, int, boot_devs, 0444);
 MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for GUS Classic driver.");
-MODULE_PARM_SYNTAX(joystick_dac, SNDRV_ENABLED ",allows:{{0,31}}");
 module_param_array(channels, int, boot_devs, 0444);
 MODULE_PARM_DESC(channels, "GF1 channels for GUS Classic driver.");
-MODULE_PARM_SYNTAX(channels,  SNDRV_ENABLED ",allows:{{14,32}}");
 module_param_array(pcm_channels, int, boot_devs, 0444);
 MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Classic driver.");
-MODULE_PARM_SYNTAX(pcm_channels, SNDRV_ENABLED ",allows:{{2,16}}");
 
 static snd_card_t *snd_gusclassic_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
index ba39f7038..91b5169ce 100644
--- a/sound/isa/gus/gusextreme.c
+++ b/sound/isa/gus/gusextreme.c
@@ -38,8 +38,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Gravis UltraSound Extreme");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Gravis,UltraSound Extreme}}");
+MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Extreme}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -60,46 +59,32 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for GUS Extreme soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for GUS Extreme soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable GUS Extreme soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for GUS Extreme driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_ENABLED ",allows:{{0x220,0x260,0x20}},dialog:list");
 module_param_array(gf1_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(gf1_port, "GF1 port # for GUS Extreme driver (optional).");
-MODULE_PARM_SYNTAX(gf1_port, SNDRV_ENABLED ",allows:{{0x210,0x270,0x10}},dialog:list");
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for GUS Extreme driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_ENABLED ",allows:{{0x300,0x320,0x10}},dialog:list");
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for GUS Extreme driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_ENABLED ",allows:{{5},{7},{9},{10}},dialog:list");
 module_param_array(mpu_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for GUS Extreme driver.");
-MODULE_PARM_SYNTAX(mpu_irq, SNDRV_ENABLED ",allows:{{5},{7},{9},{10}},dialog:list");
 module_param_array(gf1_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(gf1_irq, "GF1 IRQ # for GUS Extreme driver.");
-MODULE_PARM_SYNTAX(gf1_irq, SNDRV_ENABLED ",allows:{{2},{3},{5},{9},{11},{12},{15}},dialog:list");
 module_param_array(dma8, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma8, "8-bit DMA # for GUS Extreme driver.");
-MODULE_PARM_SYNTAX(dma8, SNDRV_DMA8_DESC);
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "GF1 DMA # for GUS Extreme driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
 module_param_array(joystick_dac, int, boot_devs, 0444);
 MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for GUS Extreme driver.");
-MODULE_PARM_SYNTAX(joystick_dac, SNDRV_ENABLED ",allows:{{0,31}}");
 module_param_array(channels, int, boot_devs, 0444);
 MODULE_PARM_DESC(channels, "GF1 channels for GUS Extreme driver.");
-MODULE_PARM_SYNTAX(channels, SNDRV_ENABLED ",allows:{{14,32}}");
 module_param_array(pcm_channels, int, boot_devs, 0444);
 MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Extreme driver.");
-MODULE_PARM_SYNTAX(pcm_channels, SNDRV_ENABLED ",allows:{{2,16}}");
 
 static snd_card_t *snd_gusextreme_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index 9d7c62a52..aa477ebec 100644
--- a/sound/isa/gus/gusmax.c
+++ b/sound/isa/gus/gusmax.c
@@ -36,8 +36,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Gravis UltraSound MAX");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Gravis,UltraSound MAX}}");
+MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound MAX}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -54,34 +53,24 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for GUS MAX soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for GUS MAX soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable GUS MAX soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for GUS MAX driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_ENABLED ",allows:{{0x220},{0x230},{0x240},{0x250},{0x260}},dialog:list");
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for GUS MAX driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_ENABLED ",allows:{{3},{5},{9},{11},{12},{15}},dialog:list");
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for GUS MAX driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
 module_param_array(dma2, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for GUS MAX driver.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC);
 module_param_array(joystick_dac, int, boot_devs, 0444);
 MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for GUS MAX driver.");
-MODULE_PARM_SYNTAX(joystick_dac, SNDRV_ENABLED ",allows:{{0,31}}");
 module_param_array(channels, int, boot_devs, 0444);
 MODULE_PARM_DESC(channels, "Used GF1 channels for GUS MAX driver.");
-MODULE_PARM_SYNTAX(channels, SNDRV_ENABLED ",allows:{{14,32}}");
 module_param_array(pcm_channels, int, boot_devs, 0444);
 MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS MAX driver.");
-MODULE_PARM_SYNTAX(pcm_channels, SNDRV_ENABLED ",allows:{{2,16}}");
 
 struct snd_gusmax {
 	int irq;
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index b2c3544bf..22567f68a 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -41,18 +41,17 @@
 #include <sound/initval.h>
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
-MODULE_CLASSES("{sound}");
 MODULE_LICENSE("GPL");
 #ifndef SNDRV_STB
 MODULE_DESCRIPTION("AMD InterWave");
-MODULE_DEVICES("{{Gravis,UltraSound Plug & Play},"
+MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Plug & Play},"
 		"{STB,SoundRage32},"
 		"{MED,MED3210},"
 		"{Dynasonix,Dynasonix Pro},"
 		"{Panasonic,PCA761AW}}");
 #else
 MODULE_DESCRIPTION("AMD InterWave STB with TEA6330T");
-MODULE_DEVICES("{{AMD,InterWave STB with TEA6330T}}");
+MODULE_SUPPORTED_DEVICE("{{AMD,InterWave STB with TEA6330T}}");
 #endif
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
@@ -77,47 +76,32 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for InterWave soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for InterWave soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable InterWave soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
-#ifdef CONFIG_PNP
 module_param_array(isapnp, bool, boot_devs, 0444);
 MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard.");
-MODULE_PARM_SYNTAX(isapnp, SNDRV_ISAPNP_DESC);
-#endif
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for InterWave driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_ENABLED ",allows:{{0x210,0x260,0x10}},dialog:list");
 #ifdef SNDRV_STB
 module_param_array(port_tc, long, boot_devs, 0444);
 MODULE_PARM_DESC(port_tc, "Tone control (TEA6330T - i2c bus) port # for InterWave driver.");
-MODULE_PARM_SYNTAX(port_tc, SNDRV_ENABLED ",allows:{{0x350,0x380,0x10}},dialog:list");
 #endif
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for InterWave driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_ENABLED ",allows:{{3},{5},{9},{11},{12},{15}},dialog:list");
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for InterWave driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
 module_param_array(dma2, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for InterWave driver.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC);
 module_param_array(joystick_dac, int, boot_devs, 0444);
 MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for InterWave driver.");
-MODULE_PARM_SYNTAX(joystick_dac, SNDRV_ENABLED ",allows:{{0,31}}");
 module_param_array(midi, int, boot_devs, 0444);
 MODULE_PARM_DESC(midi, "MIDI UART enable for InterWave driver.");
-MODULE_PARM_SYNTAX(midi, SNDRV_ENABLED "," SNDRV_ENABLE_DESC);
 module_param_array(pcm_channels, int, boot_devs, 0444);
 MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for InterWave driver.");
-MODULE_PARM_SYNTAX(pcm_channels, SNDRV_ENABLED ",allows:{{2,16}}");
 module_param_array(effect, int, boot_devs, 0444);
 MODULE_PARM_DESC(effect, "Effects enable for InterWave driver.");
-MODULE_PARM_SYNTAX(effect, SNDRV_ENABLED "," SNDRV_ENABLE_DESC);
 
 struct snd_interwave {
 	int irq;
@@ -411,8 +395,8 @@ static void __devinit snd_interwave_detect_memory(snd_gus_card_t * gus)
 	int bank_pos, pages;
 	unsigned int i, lmct;
 	int psizes[4];
+	unsigned char iwave[8];
 	unsigned char csum;
-	struct rom_hdr romh;
 
 	snd_interwave_reset(gus);
 	snd_gf1_write8(gus, SNDRV_GF1_GB_GLOBAL_MODE, snd_gf1_read8(gus, SNDRV_GF1_GB_GLOBAL_MODE) | 0x01);		/* enhanced mode */
@@ -434,7 +418,7 @@ static void __devinit snd_interwave_detect_memory(snd_gus_card_t * gus)
 #if 0
 		printk("lmct = 0x%08x\n", lmct);
 #endif
-		for (i = 0; i < sizeof(lmc) / sizeof(unsigned int); i++)
+		for (i = 0; i < ARRAY_SIZE(lmc); i++)
 			if (lmct == lmc[i]) {
 #if 0
 				printk("found !!! %i\n", i);
@@ -443,7 +427,7 @@ static void __devinit snd_interwave_detect_memory(snd_gus_card_t * gus)
 				snd_interwave_bank_sizes(gus, psizes);
 				break;
 			}
-		if (i >= sizeof(lmc) / sizeof(unsigned int) && !gus->gf1.enh_mode)
+		if (i >= ARRAY_SIZE(lmc) && !gus->gf1.enh_mode)
 			 snd_gf1_write16(gus, SNDRV_GF1_GW_MEMORY_CONFIG, (snd_gf1_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG) & 0xfff0) | 2);
 		for (i = 0; i < 4; i++) {
 			gus->gf1.mem_alloc.banks_8[i].address =
@@ -461,33 +445,29 @@ static void __devinit snd_interwave_detect_memory(snd_gus_card_t * gus)
 	gus->gf1.rom_banks = 0;
 	gus->gf1.rom_memory = 0;
 	for (bank_pos = 0; bank_pos < 16L * 1024L * 1024L; bank_pos += 4L * 1024L * 1024L) {
-		for (i = 0; i < sizeof(struct rom_hdr); i++)
-			*(((unsigned char *) &romh) + i) = snd_gf1_peek(gus, i + bank_pos);
+		for (i = 0; i < 8; ++i)
+			iwave[i] = snd_gf1_peek(gus, bank_pos + i);
 #ifdef CONFIG_SND_DEBUG_ROM
 		printk("ROM at 0x%06x = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", bank_pos,
-		       romh.iwave[0], romh.iwave[1], romh.iwave[2], romh.iwave[3],
-		       romh.iwave[4], romh.iwave[5], romh.iwave[6], romh.iwave[7]);
+		       iwave[0], iwave[1], iwave[2], iwave[3],
+		       iwave[4], iwave[5], iwave[6], iwave[7]);
 #endif
-		if (strncmp(romh.iwave, "INTRWAVE", 8))
+		if (strncmp(iwave, "INTRWAVE", 8))
 			continue;	/* first check */
 		csum = 0;
-		for (i = 0; i < sizeof(struct rom_hdr) - 1; i++)
-			csum += *(((unsigned char *) &romh) + i);
+		for (i = 0; i < sizeof(struct rom_hdr); i++)
+			csum += snd_gf1_peek(gus, bank_pos + i);
 #ifdef CONFIG_SND_DEBUG_ROM
-		printk("ROM checksum = 0x%x == 0x%x (computed)\n", romh.csum, (unsigned char) (256 - csum));
+		printk("ROM checksum = 0x%x (computed)\n", csum);
 #endif
-		if (256 - csum != romh.csum)
+		if (csum != 0)
 			continue;	/* not valid rom */
 		gus->gf1.rom_banks++;
 		gus->gf1.rom_present |= 1 << (bank_pos >> 22);
-#ifdef SNDRV_LITTLE_ENDIAN
-		gus->gf1.rom_memory = romh.rom_size;
-#else
-		gus->gf1.rom_memory = ((romh.rom_size >> 24) & 0x000000ff) |
-				      ((romh.rom_size >>  8) & 0x0000ff00) |
-				      ((romh.rom_size <<  8) & 0x00ff0000) |
-				      ((romh.rom_size << 24) & 0xff000000);
-#endif
+		gus->gf1.rom_memory = snd_gf1_peek(gus, bank_pos + 40) |
+				     (snd_gf1_peek(gus, bank_pos + 41) << 8) |
+				     (snd_gf1_peek(gus, bank_pos + 42) << 16) |
+				     (snd_gf1_peek(gus, bank_pos + 43) << 24);
 	}
 #if 0
 	if (gus->gf1.rom_memory > 0) {
@@ -523,8 +503,6 @@ static void __devinit snd_interwave_init(int dev, snd_gus_card_t * gus)
 
 }
 
-#define INTERWAVE_CONTROLS (sizeof(snd_interwave_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_interwave_controls[] = {
 CS4231_DOUBLE("Master Playback Switch", 0, CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 7, 7, 1, 1),
 CS4231_DOUBLE("Master Playback Volume", 0, CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 0, 0, 31, 1),
@@ -552,7 +530,7 @@ static int __devinit snd_interwave_mixer(cs4231_t *chip)
 		return err;
 #endif
 	/* add new master and mic controls */
-	for (idx = 0; idx < INTERWAVE_CONTROLS; idx++)
+	for (idx = 0; idx < ARRAY_SIZE(snd_interwave_controls); idx++)
 		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_interwave_controls[idx], chip))) < 0)
 			return err;
 	snd_cs4231_out(chip, CS4231_LINE_LEFT_OUTPUT, 0x9f);
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 2bea92fd0..e25303843 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -37,8 +37,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Yamaha OPL3SA2+");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Yamaha,YMF719E-S},"
+MODULE_SUPPORTED_DEVICE("{{Yamaha,YMF719E-S},"
 		"{Genius,Sound Maker 3DX},"
 		"{Yamaha,OPL3SA3},"
 		"{Intel,AL440LX sound},"
@@ -63,45 +62,32 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for OPL3-SA soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for OPL3-SA soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable OPL3-SA soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 #ifdef CONFIG_PNP
 module_param_array(isapnp, bool, boot_devs, 0444);
 MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");
-MODULE_PARM_SYNTAX(isapnp, SNDRV_ISAPNP_DESC);
 #endif
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for OPL3-SA driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_ENABLED ",allows:{{0xf86},{0x370},{0x100}},dialog:list");
 module_param_array(sb_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(sb_port, "SB port # for OPL3-SA driver.");
-MODULE_PARM_SYNTAX(sb_port, SNDRV_ENABLED ",allows:{{0x220},{0x240},{0x260}},dialog:list");
 module_param_array(wss_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(wss_port, "WSS port # for OPL3-SA driver.");
-MODULE_PARM_SYNTAX(wss_port, SNDRV_ENABLED ",allows:{{0x530},{0xe80},{0xf40},{0x604}},dialog:list");
 module_param_array(fm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for OPL3-SA driver.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_ENABLED ",allows:{{0x388}},dialog:list");
 module_param_array(midi_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(midi_port, "MIDI port # for OPL3-SA driver.");
-MODULE_PARM_SYNTAX(midi_port, SNDRV_ENABLED ",allows:{{0x330},{0x300}},dialog:list");
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for OPL3-SA driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_ENABLED ",allows:{{0},{1},{3},{5},{9},{11},{12},{15}},dialog:list");
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for OPL3-SA driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_ENABLED ",allows:{{1},{3},{5},{6},{7}},dialog:list");
 module_param_array(dma2, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for OPL3-SA driver.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_ENABLED ",allows:{{1},{3},{5},{6},{7}},dialog:list");
 module_param_array(opl3sa3_ymode, int, boot_devs, 0444);
 MODULE_PARM_DESC(opl3sa3_ymode, "Speaker size selection for 3D Enhancement mode: Desktop/Large Notebook/Small Notebook/HiFi.");
-MODULE_PARM_SYNTAX(opl3sa3_ymode, SNDRV_ENABLED ",allows:{{0,3}},dialog:list");  /* SL Added */
 
 /* control ports */
 #define OPL3SA2_PM_CTRL		0x01
@@ -131,7 +117,6 @@ MODULE_PARM_SYNTAX(opl3sa3_ymode, SNDRV_ENABLED ",allows:{{0,3}},dialog:list");
 #define OPL3SA2_PM_D3	(OPL3SA2_PM_ADOWN|OPL3SA2_PM_PSV|OPL3SA2_PM_PDN|OPL3SA2_PM_PDX)
 
 typedef struct snd_opl3sa2 opl3sa2_t;
-#define chip_t opl3sa2_t
 
 struct snd_opl3sa2 {
 	snd_card_t *card;
@@ -304,7 +289,7 @@ static int __init snd_opl3sa2_detect(opl3sa2_t *chip)
 static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	unsigned short status;
-	opl3sa2_t *chip = snd_magic_cast(opl3sa2_t, dev_id, return IRQ_NONE);
+	opl3sa2_t *chip = dev_id;
 	int handled = 0;
 
 	if (chip == NULL || chip->card == NULL)
@@ -477,8 +462,6 @@ int snd_opl3sa2_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * uco
 	return change;
 }
 
-#define OPL3SA2_CONTROLS (sizeof(snd_opl3sa2_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_opl3sa2_controls[] = {
 OPL3SA2_DOUBLE("Master Playback Switch", 0, 0x07, 0x08, 7, 7, 1, 1),
 OPL3SA2_DOUBLE("Master Playback Volume", 0, 0x07, 0x08, 0, 0, 15, 1),
@@ -486,8 +469,6 @@ OPL3SA2_SINGLE("Mic Playback Switch", 0, 0x09, 7, 1, 1),
 OPL3SA2_SINGLE("Mic Playback Volume", 0, 0x09, 0, 31, 1)
 };
 
-#define OPL3SA2_TONE_CONTROLS (sizeof(snd_opl3sa2_tone_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_opl3sa2_tone_controls[] = {
 OPL3SA2_DOUBLE("3D Control - Wide", 0, 0x14, 0x14, 4, 0, 7, 0),
 OPL3SA2_DOUBLE("Tone Control - Bass", 0, 0x15, 0x15, 4, 0, 7, 0),
@@ -496,7 +477,7 @@ OPL3SA2_DOUBLE("Tone Control - Treble", 0, 0x16, 0x16, 4, 0, 7, 0)
 
 static void snd_opl3sa2_master_free(snd_kcontrol_t *kcontrol)
 {
-	opl3sa2_t *chip = snd_magic_cast(opl3sa2_t, _snd_kcontrol_chip(kcontrol), return);
+	opl3sa2_t *chip = snd_kcontrol_chip(kcontrol);
 	chip->master_switch = NULL;
 	chip->master_volume = NULL;
 }
@@ -531,7 +512,7 @@ static int __init snd_opl3sa2_mixer(opl3sa2_t *chip)
         if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
                 return err;
 	/* add OPL3SA2 controls */
-	for (idx = 0; idx < OPL3SA2_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_opl3sa2_controls); idx++) {
 		if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_opl3sa2_controls[idx], chip))) < 0)
 			return err;
 		switch (idx) {
@@ -540,7 +521,7 @@ static int __init snd_opl3sa2_mixer(opl3sa2_t *chip)
 		}
 	}
 	if (chip->version > 2) {
-		for (idx = 0; idx < OPL3SA2_TONE_CONTROLS; idx++)
+		for (idx = 0; idx < ARRAY_SIZE(snd_opl3sa2_tone_controls); idx++)
 			if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_opl3sa2_tone_controls[idx], chip))) < 0)
 				return err;
 	}
@@ -551,7 +532,7 @@ static int __init snd_opl3sa2_mixer(opl3sa2_t *chip)
 #ifdef CONFIG_PM
 static int snd_opl3sa2_suspend(snd_card_t *card, unsigned int state)
 {
-	opl3sa2_t *chip = snd_magic_cast(opl3sa2_t, card->pm_private_data, return -EINVAL);
+	opl3sa2_t *chip = card->pm_private_data;
 
 	snd_pcm_suspend_all(chip->cs4231->pcm); /* stop before saving regs */
 	chip->cs4231_suspend(chip->cs4231);
@@ -565,7 +546,7 @@ static int snd_opl3sa2_suspend(snd_card_t *card, unsigned int state)
 
 static int snd_opl3sa2_resume(snd_card_t *card, unsigned int state)
 {
-	opl3sa2_t *chip = snd_magic_cast(opl3sa2_t, card->pm_private_data, return -EINVAL);
+	opl3sa2_t *chip = card->pm_private_data;
 	int i;
 
 	/* power up */
@@ -656,13 +637,13 @@ static int snd_opl3sa2_free(opl3sa2_t *chip)
 		release_resource(chip->res_port);
 		kfree_nocheck(chip->res_port);
 	}
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_opl3sa2_dev_free(snd_device_t *device)
 {
-	opl3sa2_t *chip = snd_magic_cast(opl3sa2_t, device->device_data, return -ENXIO);
+	opl3sa2_t *chip = device->device_data;
 	return snd_opl3sa2_free(chip);
 }
 
@@ -707,7 +688,7 @@ static int __devinit snd_opl3sa2_probe(int dev,
 		return -ENOMEM;
 	strcpy(card->driver, "OPL3SA2");
 	strcpy(card->shortname, "Yamaha OPL3-SA2");
-	chip = snd_magic_kcalloc(opl3sa2_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL) {
 		err = -ENOMEM;
 		goto __error;
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index 846b00acc..c4fbf6fff 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -52,19 +52,18 @@
 #include <sound/initval.h>
 
 MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
-MODULE_CLASSES("{sound}");
 MODULE_LICENSE("GPL");
 #ifdef OPTi93X
 MODULE_DESCRIPTION("OPTi93X");
-MODULE_DEVICES("{{OPTi,82C931/3}}");
+MODULE_SUPPORTED_DEVICE("{{OPTi,82C931/3}}");
 #else	/* OPTi93X */
 #ifdef CS4231
 MODULE_DESCRIPTION("OPTi92X - CS4231");
-MODULE_DEVICES("{{OPTi,82C924 (CS4231)},"
+MODULE_SUPPORTED_DEVICE("{{OPTi,82C924 (CS4231)},"
 		"{OPTi,82C925 (CS4231)}}");
 #else	/* CS4231 */
 MODULE_DESCRIPTION("OPTi92X - AD1848");
-MODULE_DEVICES("{{OPTi,82C924 (AD1848)},"
+MODULE_SUPPORTED_DEVICE("{{OPTi,82C924 (AD1848)},"
 		"{OPTi,82C925 (AD1848)},"
 	        "{OAK,Mozart}}");
 #endif	/* CS4231 */
@@ -86,38 +85,27 @@ static int dma2 = SNDRV_DEFAULT_DMA1;		/* 0,1,3 */
 
 module_param(index, int, 0444);
 MODULE_PARM_DESC(index, "Index value for opti9xx based soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param(id, charp, 0444);
 MODULE_PARM_DESC(id, "ID string for opti9xx based soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 //module_param(enable, bool, 0444);
 //MODULE_PARM_DESC(enable, "Enable opti9xx soundcard.");
-//MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param(isapnp, bool, 0444);
 MODULE_PARM_DESC(isapnp, "Enable ISA PnP detection for specified soundcard.");
-MODULE_PARM_SYNTAX(isapnp, SNDRV_ISAPNP_DESC);
 module_param(port, long, 0444);
 MODULE_PARM_DESC(port, "WSS port # for opti9xx driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT_DESC);
 module_param(mpu_port, long, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for opti9xx driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT_DESC);
 module_param(fm_port, long, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for opti9xx driver.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_PORT_DESC);
 module_param(irq, int, 0444);
 MODULE_PARM_DESC(irq, "WSS irq # for opti9xx driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param(mpu_irq, int, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 irq # for opti9xx driver.");
-MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC);
 module_param(dma1, int, 0444);
 MODULE_PARM_DESC(dma1, "1st dma # for opti9xx driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
 #if defined(CS4231) || defined(OPTi93X)
 module_param(dma2, int, 0444);
 MODULE_PARM_DESC(dma2, "2nd dma # for opti9xx driver.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC);
 #endif	/* CS4231 || OPTi93X */
 
 #define OPTi9XX_HW_DETECT	0
@@ -474,7 +462,6 @@ static int __devinit snd_opti9xx_configure(opti9xx_t *chip)
 	unsigned char dma_bits;
 	unsigned char mpu_port_bits = 0;
 	unsigned char mpu_irq_bits;
-	unsigned long flags;
 
 	switch (chip->hardware) {
 #ifndef OPTi93X
@@ -601,13 +588,11 @@ __skip_base:
 	dma_bits |= 0x04;
 #endif	/* CS4231 || OPTi93X */
 
-	spin_lock_irqsave(&chip->lock, flags);
 #ifndef OPTi93X
 	 outb(irq_bits << 3 | dma_bits, chip->wss_base);
 #else /* OPTi93X */
 	snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits));
 #endif /* OPTi93X */
-	spin_unlock_irqrestore(&chip->lock, flags);
 
 __skip_resources:
 	if (chip->hardware > OPTi9XX_HW_82C928) {
@@ -664,8 +649,6 @@ __skip_mpu:
 
 #ifdef OPTi93X
 
-#define chip_t opti93x_t
-
 static unsigned char snd_opti93x_default_image[32] =
 {
 	0x00,		/* 00/00 - l_mixout_outctrl */
@@ -767,15 +750,10 @@ static void snd_opti93x_mce_down(opti93x_t *chip)
 
 static void snd_opti93x_mute(opti93x_t *chip, int mute)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->lock, flags);
-
 	mute = mute ? 1 : 0;
-	if (chip->mute == mute) {
-		spin_unlock_irqrestore(&chip->lock, flags);
+	if (chip->mute == mute)
 		return;
-	}
+
 	chip->mute = mute;
 
 	snd_opti93x_mute_reg(chip, OPTi93X_CD_LEFT_INPUT, mute);
@@ -800,8 +778,6 @@ static void snd_opti93x_mute(opti93x_t *chip, int mute)
 	snd_opti93x_mute_reg(chip, OPTi93X_MIC_RIGHT_INPUT, mute);
 	snd_opti93x_mute_reg(chip, OPTi93X_OUT_LEFT, mute);
 	snd_opti93x_mute_reg(chip, OPTi93X_OUT_RIGHT, mute);
-
-	spin_unlock_irqrestore(&chip->lock, flags);
 }
 
 
@@ -822,7 +798,7 @@ static unsigned int snd_opti93x_get_count(unsigned char format,
 static unsigned int rates[] = {  5512,  6615,  8000,  9600, 11025, 16000, 
 				18900, 22050, 27428, 32000, 33075, 37800,
 				44100, 48000 };
-#define RATES sizeof(rates) / sizeof(rates[0])
+#define RATES ARRAY_SIZE(rates)
 
 static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
 	.count = RATES,
@@ -873,10 +849,8 @@ static unsigned char snd_opti93x_get_format(opti93x_t *chip,
 
 static void snd_opti93x_playback_format(opti93x_t *chip, unsigned char fmt)
 {
-	unsigned long flags;
 	unsigned char mask;
 
-	spin_lock_irqsave(&chip->lock, flags);
 	snd_opti93x_mute(chip, 1);
 
 	snd_opti93x_mce_up(chip);
@@ -885,14 +859,10 @@ static void snd_opti93x_playback_format(opti93x_t *chip, unsigned char fmt)
 	snd_opti93x_mce_down(chip);
 
 	snd_opti93x_mute(chip, 0);
-	spin_unlock_irqrestore(&chip->lock, flags);
 }
 
 static void snd_opti93x_capture_format(opti93x_t *chip, unsigned char fmt)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->lock, flags);
 	snd_opti93x_mute(chip, 1);
 
 	snd_opti93x_mce_up(chip);
@@ -904,7 +874,6 @@ static void snd_opti93x_capture_format(opti93x_t *chip, unsigned char fmt)
 	snd_opti93x_mce_down(chip);
 
 	snd_opti93x_mute(chip, 0);
-	spin_unlock_irqrestore(&chip->lock, flags);
 }
 
 
@@ -1128,7 +1097,7 @@ static void snd_opti93x_overrange(opti93x_t *chip)
 
 irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	opti93x_t *codec = snd_magic_cast(opti93x_t, dev_id, return IRQ_NONE);
+	opti93x_t *codec = dev_id;
 	unsigned char status;
 
 	status = snd_opti9xx_read(codec->chip, OPTi9XX_MC_REG(11));
@@ -1274,13 +1243,13 @@ static int snd_opti93x_free(opti93x_t *chip)
 	if (chip->irq >= 0) {
 	  free_irq(chip->irq, chip);
 	}
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_opti93x_dev_free(snd_device_t *device)
 {
-	opti93x_t *chip = snd_magic_cast(opti93x_t, device->device_data, return -ENXIO);
+	opti93x_t *chip = device->device_data;
 	return snd_opti93x_free(chip);
 }
 
@@ -1305,7 +1274,7 @@ int snd_opti93x_create(snd_card_t *card, opti9xx_t *chip,
 	opti93x_t *codec;
 
 	*rcodec = NULL;
-	codec = snd_magic_kcalloc(opti93x_t, 0, GFP_KERNEL);
+	codec = kcalloc(1, sizeof(*codec), GFP_KERNEL);
 	if (codec == NULL)
 		return -ENOMEM;
 	codec->irq = -1;
@@ -1385,7 +1354,7 @@ static snd_pcm_ops_t snd_opti93x_capture_ops = {
 
 static void snd_opti93x_pcm_free(snd_pcm_t *pcm)
 {
-	opti93x_t *codec = snd_magic_cast(opti93x_t, pcm->private_data, return);
+	opti93x_t *codec = pcm->private_data;
 	codec->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1608,8 +1577,6 @@ static int snd_opti93x_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
 	return change;
 }
 
-#define OPTi93X_CONTROLS (sizeof(snd_opti93x_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_opti93x_controls[] = {
 OPTi93X_DOUBLE("Master Playback Switch", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
 OPTi93X_DOUBLE("Master Playback Volume", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1), 
@@ -1649,7 +1616,7 @@ int snd_opti93x_mixer(opti93x_t *chip)
 
 	strcpy(card->mixername, snd_opti93x_chip_id(chip));
 
-	for (idx = 0; idx < OPTi93X_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_opti93x_controls); idx++) {
 		knew = snd_opti93x_controls[idx];
 		if (chip->hardware == OPTi9XX_HW_82C930) {
 			if (strstr(knew.name, "FM"))	/* skip FM controls */
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
index 78e71562d..bc29b25b6 100644
--- a/sound/isa/sb/emu8000.c
+++ b/sound/isa/sb/emu8000.c
@@ -345,8 +345,6 @@ send_array(emu8000_t *emu, unsigned short *data, int size)
 		EMU8000_INIT4_WRITE(emu, i, *p);
 }
 
-#define NELEM(arr) (sizeof(arr)/sizeof((arr)[0]))
-
 
 /*
  * Send initialization arrays to start up, this just follows the
@@ -355,18 +353,18 @@ send_array(emu8000_t *emu, unsigned short *data, int size)
 static void __init
 init_arrays(emu8000_t *emu)
 {
-	send_array(emu, init1, NELEM(init1)/4);
+	send_array(emu, init1, ARRAY_SIZE(init1)/4);
 
 	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout((HZ * (44099 + 1024)) / 44100); /* wait for 1024 clocks */
-	send_array(emu, init2, NELEM(init2)/4);
-	send_array(emu, init3, NELEM(init3)/4);
+	send_array(emu, init2, ARRAY_SIZE(init2)/4);
+	send_array(emu, init3, ARRAY_SIZE(init3)/4);
 
 	EMU8000_HWCF4_WRITE(emu, 0);
 	EMU8000_HWCF5_WRITE(emu, 0x83);
 	EMU8000_HWCF6_WRITE(emu, 0x8000);
 
-	send_array(emu, init4, NELEM(init4)/4);
+	send_array(emu, init4, ARRAY_SIZE(init4)/4);
 }
 
 
@@ -821,8 +819,6 @@ snd_emu8000_update_reverb_mode(emu8000_t *emu)
  * mixer interface
  *----------------------------------------------------------------*/
 
-#define chip_t	emu8000_t
-
 /*
  * bass/treble
  */
@@ -1070,7 +1066,7 @@ static int snd_emu8000_free(emu8000_t *hw)
 		release_resource(hw->res_port3);
 		kfree_nocheck(hw->res_port3);
 	}
-	snd_magic_kfree(hw);
+	kfree(hw);
 	return 0;
 }
 
@@ -1078,7 +1074,7 @@ static int snd_emu8000_free(emu8000_t *hw)
  */
 static int snd_emu8000_dev_free(snd_device_t *device)
 {
-	emu8000_t *hw = snd_magic_cast(emu8000_t, device->device_data, return -ENXIO);
+	emu8000_t *hw = device->device_data;
 	return snd_emu8000_free(hw);
 }
 
@@ -1101,7 +1097,7 @@ snd_emu8000_new(snd_card_t *card, int index, long port, int seq_ports, snd_seq_d
 	if (seq_ports <= 0)
 		return 0;
 
-	hw = snd_magic_kcalloc(emu8000_t, 0, GFP_KERNEL);
+	hw = kcalloc(1, sizeof(*hw), GFP_KERNEL);
 	if (hw == NULL)
 		return -ENOMEM;
 	spin_lock_init(&hw->reg_lock);
diff --git a/sound/isa/sb/emu8000_callback.c b/sound/isa/sb/emu8000_callback.c
index 868474a08..05565f31d 100644
--- a/sound/isa/sb/emu8000_callback.c
+++ b/sound/isa/sb/emu8000_callback.c
@@ -94,7 +94,7 @@ release_voice(snd_emux_voice_t *vp)
 	int dcysusv;
 	emu8000_t *hw;
 
-	hw = snd_magic_cast(emu8000_t, vp->hw, return);
+	hw = vp->hw;
 	dcysusv = 0x8000 | (unsigned char)vp->reg.parm.modrelease;
 	EMU8000_DCYSUS_WRITE(hw, vp->ch, dcysusv);
 	dcysusv = 0x8000 | (unsigned char)vp->reg.parm.volrelease;
@@ -109,7 +109,7 @@ terminate_voice(snd_emux_voice_t *vp)
 {
 	emu8000_t *hw; 
 
-	hw = snd_magic_cast(emu8000_t, vp->hw, return);
+	hw = vp->hw;
 	EMU8000_DCYSUSV_WRITE(hw, vp->ch, 0x807F);
 }
 
@@ -121,7 +121,7 @@ update_voice(snd_emux_voice_t *vp, int update)
 {
 	emu8000_t *hw;
 
-	hw = snd_magic_cast(emu8000_t, vp->hw, return);
+	hw = vp->hw;
 	if (update & SNDRV_EMUX_UPDATE_VOLUME)
 		set_volume(hw, vp);
 	if (update & SNDRV_EMUX_UPDATE_PITCH)
@@ -168,7 +168,7 @@ get_voice(snd_emux_t *emu, snd_emux_port_t *port)
 	} best[END];
 	struct best *bp;
 
-	hw = snd_magic_cast(emu8000_t, emu->hw, return NULL);
+	hw = emu->hw;
 
 	for (i = 0; i < END; i++) {
 		best[i].time = (unsigned int)(-1); /* XXX MAX_?INT really */;
@@ -235,7 +235,7 @@ start_voice(snd_emux_voice_t *vp)
 	snd_midi_channel_t *chan;
 	emu8000_t *hw;
 
-	hw = snd_magic_cast(emu8000_t, vp->hw, return -EINVAL);
+	hw = vp->hw;
 	ch = vp->ch;
 	chan = vp->chan;
 
@@ -313,7 +313,7 @@ trigger_voice(snd_emux_voice_t *vp)
 	unsigned int temp;
 	emu8000_t *hw;
 
-	hw = snd_magic_cast(emu8000_t, vp->hw, return);
+	hw = vp->hw;
 
 	/* set reverb and pitch target */
 	temp = vp->reg.parm.reverb;
@@ -333,7 +333,7 @@ reset_voice(snd_emux_t *emu, int ch)
 {
 	emu8000_t *hw;
 
-	hw = snd_magic_cast(emu8000_t, emu->hw, return);
+	hw = emu->hw;
 	EMU8000_DCYSUSV_WRITE(hw, ch, 0x807F);
 	snd_emu8000_tweak_voice(hw, ch);
 }
@@ -457,7 +457,7 @@ sysex(snd_emux_t *emu, char *buf, int len, int parsed, snd_midi_channel_set_t *c
 {
 	emu8000_t *hw;
 
-	hw = snd_magic_cast(emu8000_t, emu->hw, return);
+	hw = emu->hw;
 
 	switch (parsed) {
 	case SNDRV_MIDI_SYSEX_GS_CHORUS_MODE:
@@ -482,7 +482,7 @@ oss_ioctl(snd_emux_t *emu, int cmd, int p1, int p2)
 {
 	emu8000_t *hw;
 
-	hw = snd_magic_cast(emu8000_t, emu->hw, return -EINVAL);
+	hw = emu->hw;
 
 	switch (cmd) {
 	case _EMUX_OSS_REVERB_MODE:
@@ -526,7 +526,7 @@ static int
 load_fx(snd_emux_t *emu, int type, int mode, const void __user *buf, long len)
 {
 	emu8000_t *hw;
-	hw = snd_magic_cast(emu8000_t, emu->hw, return -EINVAL);
+	hw = emu->hw;
 
 	switch (type) {
 	case SNDRV_EMU8000_LOAD_CHORUS_FX:
diff --git a/sound/isa/sb/emu8000_local.h b/sound/isa/sb/emu8000_local.h
index 00bf0455c..ea4996a89 100644
--- a/sound/isa/sb/emu8000_local.h
+++ b/sound/isa/sb/emu8000_local.h
@@ -29,8 +29,6 @@
 #include <sound/emu8000.h>
 #include <sound/emu8000_reg.h>
 
-#define NELEM(arr) (sizeof(arr)/sizeof((arr)[0]))
-
 /* emu8000_patch.c */
 int snd_emu8000_sample_new(snd_emux_t *rec, snd_sf_sample_t *sp, snd_util_memhdr_t *hdr, const void __user *data, long count);
 int snd_emu8000_sample_free(snd_emux_t *rec, snd_sf_sample_t *sp, snd_util_memhdr_t *hdr);
diff --git a/sound/isa/sb/emu8000_patch.c b/sound/isa/sb/emu8000_patch.c
index 9ecd53c21..cea56e016 100644
--- a/sound/isa/sb/emu8000_patch.c
+++ b/sound/isa/sb/emu8000_patch.c
@@ -155,7 +155,7 @@ snd_emu8000_sample_new(snd_emux_t *rec, snd_sf_sample_t *sp,
 	int  dram_offset, dram_start;
 	emu8000_t *emu;
 
-	emu = snd_magic_cast(emu8000_t, rec->hw, return -EINVAL);
+	emu = rec->hw;
 	snd_assert(sp != NULL, return -EINVAL);
 
 	if (sp->v.size == 0)
diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c
index 5c4def8d0..a6fd8d7ca 100644
--- a/sound/isa/sb/emu8000_pcm.c
+++ b/sound/isa/sb/emu8000_pcm.c
@@ -23,8 +23,6 @@
 #include <sound/initval.h>
 #include <sound/pcm.h>
 
-#define chip_t emu8000_t
-
 /*
  * define the following if you want to use this pcm with non-interleaved mode
  */
@@ -235,7 +233,7 @@ static int emu8k_pcm_open(snd_pcm_substream_t *subs)
 	emu8k_pcm_t *rec;
 	snd_pcm_runtime_t *runtime = subs->runtime;
 
-	rec = snd_kcalloc(sizeof(*rec), GFP_KERNEL);
+	rec = kcalloc(1, sizeof(*rec), GFP_KERNEL);
 	if (! rec)
 		return -ENOMEM;
 
diff --git a/sound/isa/sb/emu8000_synth.c b/sound/isa/sb/emu8000_synth.c
index 817748c5e..1f63aa52d 100644
--- a/sound/isa/sb/emu8000_synth.c
+++ b/sound/isa/sb/emu8000_synth.c
@@ -27,7 +27,6 @@
 MODULE_AUTHOR("Takashi Iwai, Steve Ratcliffe");
 MODULE_DESCRIPTION("Emu8000 synth plug-in routine");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 
 /*----------------------------------------------------------------*/
 
diff --git a/sound/isa/sb/es968.c b/sound/isa/sb/es968.c
index c44efdba9..15a77e866 100644
--- a/sound/isa/sb/es968.c
+++ b/sound/isa/sb/es968.c
@@ -29,15 +29,12 @@
 #include <sound/initval.h>
 #include <sound/sb.h>
 
-#define chip_t sb_t
-
 #define PFX "es968: "
 
 MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
 MODULE_DESCRIPTION("ESS AudioDrive ES968");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ESS,AudioDrive ES968}}");
+MODULE_SUPPORTED_DEVICE("{{ESS,AudioDrive ES968}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -49,22 +46,16 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for es968 based soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for es968 based soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable es968 based soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for es968 driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for es968 driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(dma8, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma8, "8-bit DMA # for es968 driver.");
-MODULE_PARM_SYNTAX(dma8, SNDRV_DMA8_DESC);
 
 struct snd_card_es968 {
 	struct pnp_dev *dev;
@@ -82,7 +73,7 @@ MODULE_DEVICE_TABLE(pnp_card, snd_es968_pnpids);
 static irqreturn_t snd_card_es968_interrupt(int irq, void *dev_id,
 					    struct pt_regs *regs)
 {
-	sb_t *chip = snd_magic_cast(sb_t, dev_id, return IRQ_NONE);
+	sb_t *chip = dev_id;
 
 	if (chip->open & SB_OPEN_PCM) {
 		return snd_sb8dsp_interrupt(chip);
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index cdf00d306..c631b33aa 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -37,8 +37,6 @@
 #define SNDRV_LEGACY_FIND_FREE_DMA
 #include <sound/initval.h>
 
-#define chip_t sb_t
-
 #ifdef SNDRV_SBAWE
 #define PFX "sbawe: "
 #else
@@ -47,17 +45,16 @@
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 #ifndef SNDRV_SBAWE
 MODULE_DESCRIPTION("Sound Blaster 16");
-MODULE_DEVICES("{{Creative Labs,SB 16},"
+MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB 16},"
 		"{Creative Labs,SB Vibra16S},"
 		"{Creative Labs,SB Vibra16C},"
 		"{Creative Labs,SB Vibra16CL},"
 		"{Creative Labs,SB Vibra16X}}");
 #else
 MODULE_DESCRIPTION("Sound Blaster AWE");
-MODULE_DEVICES("{{Creative Labs,SB AWE 32},"
+MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB AWE 32},"
 		"{Creative Labs,SB AWE 64},"
 		"{Creative Labs,SB AWE 64 Gold}}");
 #endif
@@ -96,53 +93,39 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for SoundBlaster 16 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for SoundBlaster 16 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable SoundBlaster 16 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 #ifdef CONFIG_PNP
 module_param_array(isapnp, bool, boot_devs, 0444);
 MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");
-MODULE_PARM_SYNTAX(isapnp, SNDRV_ISAPNP_DESC);
 #endif
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for SB16 driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_ENABLED ",allows:{{0x220},{0x240},{0x260},{0x280}},dialog:list");
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for SB16 driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_ENABLED ",allows:{{0x330},{0x300}},dialog:list");
 module_param_array(fm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for SB16 PnP driver.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_ENABLED ",allows:{{0x388},{0x38c},{0x390},{0x394}},dialog:list");
 #ifdef SNDRV_SBAWE_EMU8000
 module_param_array(awe_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(awe_port, "AWE port # for SB16 PnP driver.");
-MODULE_PARM_SYNTAX(awe_port, SNDRV_ENABLED ",allows:{{0x620},{0x640},{0x660},{0x680}},dialog:list");
 #endif
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for SB16 driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(dma8, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma8, "8-bit DMA # for SB16 driver.");
-MODULE_PARM_SYNTAX(dma8, SNDRV_DMA8_DESC);
 module_param_array(dma16, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma16, "16-bit DMA # for SB16 driver.");
-MODULE_PARM_SYNTAX(dma16, SNDRV_DMA16_DESC);
 module_param_array(mic_agc, int, boot_devs, 0444);
 MODULE_PARM_DESC(mic_agc, "Mic Auto-Gain-Control switch.");
-MODULE_PARM_SYNTAX(mic_agc, SNDRV_ENABLED "," SNDRV_BOOLEAN_TRUE_DESC);
 #ifdef CONFIG_SND_SB16_CSP
 module_param_array(csp, int, boot_devs, 0444);
 MODULE_PARM_DESC(csp, "ASP/CSP chip support.");
-MODULE_PARM_SYNTAX(csp, SNDRV_ENABLED "," SNDRV_ENABLE_DESC);
 #endif
 #ifdef SNDRV_SBAWE_EMU8000
 module_param_array(seq_ports, int, boot_devs, 0444);
 MODULE_PARM_DESC(seq_ports, "Number of sequencer ports for WaveTable synth.");
-MODULE_PARM_SYNTAX(seq_ports, SNDRV_ENABLED ",allows:{{0,8}},skill:advanced");
 #endif
 
 struct snd_card_sb16 {
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
index 6cbef4688..b62920eea 100644
--- a/sound/isa/sb/sb16_csp.c
+++ b/sound/isa/sb/sb16_csp.c
@@ -33,12 +33,9 @@
 #include <sound/sb16_csp.h>
 #include <sound/initval.h>
 
-#define chip_t snd_sb_csp_t
-
 MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>");
 MODULE_DESCRIPTION("ALSA driver for SB16 Creative Signal Processor");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 
 #ifdef SNDRV_LITTLE_ENDIAN
 #define CSP_HDR_VALUE(a,b,c,d)	((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
@@ -127,7 +124,7 @@ int snd_sb_csp_new(sb_t *chip, int device, snd_hwdep_t ** rhwdep)
 	if ((err = snd_hwdep_new(chip->card, "SB16-CSP", device, &hw)) < 0)
 		return err;
 
-	if ((p = snd_magic_kcalloc(snd_sb_csp_t, 0, GFP_KERNEL)) == NULL) {
+	if ((p = kcalloc(1, sizeof(*p), GFP_KERNEL)) == NULL) {
 		snd_device_free(chip->card, hw);
 		return -ENOMEM;
 	}
@@ -165,11 +162,11 @@ int snd_sb_csp_new(sb_t *chip, int device, snd_hwdep_t ** rhwdep)
  */
 static void snd_sb_csp_free(snd_hwdep_t *hwdep)
 {
-	snd_sb_csp_t *p = snd_magic_cast(snd_sb_csp_t, hwdep->private_data, return);
+	snd_sb_csp_t *p = hwdep->private_data;
 	if (p) {
 		if (p->running & SNDRV_SB_CSP_ST_RUNNING)
 			snd_sb_csp_stop(p);
-		snd_magic_kfree(p);
+		kfree(p);
 	}
 }
 
@@ -180,7 +177,7 @@ static void snd_sb_csp_free(snd_hwdep_t *hwdep)
  */
 static int snd_sb_csp_open(snd_hwdep_t * hw, struct file *file)
 {
-	snd_sb_csp_t *p = snd_magic_cast(snd_sb_csp_t, hw->private_data, return -ENXIO);
+	snd_sb_csp_t *p = hw->private_data;
 	return (snd_sb_csp_use(p));
 }
 
@@ -189,7 +186,7 @@ static int snd_sb_csp_open(snd_hwdep_t * hw, struct file *file)
  */
 static int snd_sb_csp_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cmd, unsigned long arg)
 {
-	snd_sb_csp_t *p = snd_magic_cast(snd_sb_csp_t, hw->private_data, return -ENXIO);
+	snd_sb_csp_t *p = hw->private_data;
 	snd_sb_csp_info_t info;
 	snd_sb_csp_start_t start_info;
 	int err;
@@ -258,7 +255,7 @@ static int snd_sb_csp_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cm
  */
 static int snd_sb_csp_release(snd_hwdep_t * hw, struct file *file)
 {
-	snd_sb_csp_t *p = snd_magic_cast(snd_sb_csp_t, hw->private_data, return -ENXIO);
+	snd_sb_csp_t *p = hw->private_data;
 	return (snd_sb_csp_unuse(p));
 }
 
@@ -1110,7 +1107,7 @@ static int init_proc_entry(snd_sb_csp_t * p, int device)
 
 static void info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-	snd_sb_csp_t *p = snd_magic_cast(snd_sb_csp_t, entry->private_data, return);
+	snd_sb_csp_t *p = entry->private_data;
 
 	snd_iprintf(buffer, "Creative Signal Processor [v%d.%d]\n", (p->version >> 4), (p->version & 0x0f));
 	snd_iprintf(buffer, "State: %cx%c%c%c\n", ((p->running & SNDRV_SB_CSP_ST_QSOUND) ? 'Q' : '-'),
diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c
index f67e36845..e58f486d9 100644
--- a/sound/isa/sb/sb16_main.c
+++ b/sound/isa/sb/sb16_main.c
@@ -49,13 +49,11 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Routines for control of 16-bit SoundBlaster cards and clones");
 MODULE_LICENSE("GPL");
 
-#define chip_t sb_t
-
 #ifdef CONFIG_SND_SB16_CSP
 static void snd_sb16_csp_playback_prepare(sb_t *chip, snd_pcm_runtime_t *runtime)
 {
 	if (chip->hardware == SB_HW_16CSP) {
-		snd_sb_csp_t *csp = snd_magic_cast(snd_sb_csp_t, chip->csp, return);
+		snd_sb_csp_t *csp = chip->csp;
 
 		if (csp->running & SNDRV_SB_CSP_ST_LOADED) {
 			/* manually loaded codec */
@@ -103,7 +101,7 @@ static void snd_sb16_csp_playback_prepare(sb_t *chip, snd_pcm_runtime_t *runtime
 static void snd_sb16_csp_capture_prepare(sb_t *chip, snd_pcm_runtime_t *runtime)
 {
 	if (chip->hardware == SB_HW_16CSP) {
-		snd_sb_csp_t *csp = snd_magic_cast(snd_sb_csp_t, chip->csp, return);
+		snd_sb_csp_t *csp = chip->csp;
 
 		if (csp->running & SNDRV_SB_CSP_ST_LOADED) {
 			/* manually loaded codec */
@@ -141,7 +139,7 @@ static void snd_sb16_csp_capture_prepare(sb_t *chip, snd_pcm_runtime_t *runtime)
 static void snd_sb16_csp_update(sb_t *chip)
 {
 	if (chip->hardware == SB_HW_16CSP) {
-		snd_sb_csp_t *csp = snd_magic_cast(snd_sb_csp_t, chip->csp, return);
+		snd_sb_csp_t *csp = chip->csp;
 
 		if (csp->qpos_changed) {
 			spin_lock(&chip->reg_lock);
@@ -155,7 +153,7 @@ static void snd_sb16_csp_playback_open(sb_t *chip, snd_pcm_runtime_t *runtime)
 {
 	/* CSP decoders (QSound excluded) support only 16bit transfers */
 	if (chip->hardware == SB_HW_16CSP) {
-		snd_sb_csp_t *csp = snd_magic_cast(snd_sb_csp_t, chip->csp, return);
+		snd_sb_csp_t *csp = chip->csp;
 
 		if (csp->running & SNDRV_SB_CSP_ST_LOADED) {
 			/* manually loaded codec */
@@ -173,7 +171,7 @@ static void snd_sb16_csp_playback_open(sb_t *chip, snd_pcm_runtime_t *runtime)
 static void snd_sb16_csp_playback_close(sb_t *chip)
 {
 	if ((chip->hardware == SB_HW_16CSP) && (chip->open == SNDRV_SB_CSP_MODE_DSP_WRITE)) {
-		snd_sb_csp_t *csp = snd_magic_cast(snd_sb_csp_t, chip->csp, return);
+		snd_sb_csp_t *csp = chip->csp;
 
 		if (csp->ops.csp_stop(csp) == 0) {
 			csp->ops.csp_unuse(csp);
@@ -186,7 +184,7 @@ static void snd_sb16_csp_capture_open(sb_t *chip, snd_pcm_runtime_t *runtime)
 {
 	/* CSP coders support only 16bit transfers */
 	if (chip->hardware == SB_HW_16CSP) {
-		snd_sb_csp_t *csp = snd_magic_cast(snd_sb_csp_t, chip->csp, return);
+		snd_sb_csp_t *csp = chip->csp;
 
 		if (csp->running & SNDRV_SB_CSP_ST_LOADED) {
 			/* manually loaded codec */
@@ -204,7 +202,7 @@ static void snd_sb16_csp_capture_open(sb_t *chip, snd_pcm_runtime_t *runtime)
 static void snd_sb16_csp_capture_close(sb_t *chip)
 {
 	if ((chip->hardware == SB_HW_16CSP) && (chip->open == SNDRV_SB_CSP_MODE_DSP_READ)) {
-		snd_sb_csp_t *csp = snd_magic_cast(snd_sb_csp_t, chip->csp, return);
+		snd_sb_csp_t *csp = chip->csp;
 
 		if (csp->ops.csp_stop(csp) == 0) {
 			csp->ops.csp_unuse(csp);
@@ -395,7 +393,7 @@ static int snd_sb16_capture_trigger(snd_pcm_substream_t * substream,
 
 irqreturn_t snd_sb16dsp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	sb_t *chip = snd_magic_cast(sb_t, dev_id, return IRQ_NONE);
+	sb_t *chip = dev_id;
 	unsigned char status;
 	int ok;
 
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index feac3efc1..2f1404394 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -30,13 +30,10 @@
 #define SNDRV_LEGACY_AUTO_PROBE
 #include <sound/initval.h>
 
-#define chip_t sb_t
-
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Sound Blaster 1.0/2.0/Pro");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Creative Labs,SB 1.0/SB 2.0/SB Pro}}");
+MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB 1.0/SB 2.0/SB Pro}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -48,22 +45,16 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Sound Blaster soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Sound Blaster soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Sound Blaster soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for SB8 driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC);
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for SB8 driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 module_param_array(dma8, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma8, "8-bit DMA # for SB8 driver.");
-MODULE_PARM_SYNTAX(dma8, SNDRV_DMA8_DESC);
 
 struct snd_sb8 {
 	struct resource *fm_res;	/* used to block FM i/o region for legacy cards */
@@ -73,7 +64,7 @@ static snd_card_t *snd_sb8_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
 static irqreturn_t snd_sb8_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	sb_t *chip = snd_magic_cast(sb_t, dev_id, return IRQ_NONE);
+	sb_t *chip = dev_id;
 
 	if (chip->open & SB_OPEN_PCM) {
 		return snd_sb8dsp_interrupt(chip);
diff --git a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c
index bac9f1610..d2e3abed2 100644
--- a/sound/isa/sb/sb8_main.c
+++ b/sound/isa/sb/sb8_main.c
@@ -42,8 +42,6 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Uros Bizjak <uros@kss-loka.si>")
 MODULE_DESCRIPTION("Routines for control of 8-bit SoundBlaster cards and clones");
 MODULE_LICENSE("GPL");
 
-#define chip_t sb_t
-
 #define SB8_CLOCK	1000000
 #define SB8_DEN(v)	((SB8_CLOCK + (v) / 2) / (v))
 #define SB8_RATE(v)	(SB8_CLOCK / SB8_DEN(v))
diff --git a/sound/isa/sb/sb8_midi.c b/sound/isa/sb/sb8_midi.c
index 17e0f4d1e..90b01e798 100644
--- a/sound/isa/sb/sb8_midi.c
+++ b/sound/isa/sb/sb8_midi.c
@@ -73,7 +73,7 @@ static int snd_sb8dsp_midi_input_open(snd_rawmidi_substream_t * substream)
 	sb_t *chip;
 	unsigned int valid_open_flags;
 
-	chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return -ENXIO);
+	chip = substream->rmidi->private_data;
 	valid_open_flags = chip->hardware >= SB_HW_20
 		? SB_OPEN_MIDI_OUTPUT | SB_OPEN_MIDI_OUTPUT_TRIGGER : 0;
 	spin_lock_irqsave(&chip->open_lock, flags);
@@ -100,7 +100,7 @@ static int snd_sb8dsp_midi_output_open(snd_rawmidi_substream_t * substream)
 	sb_t *chip;
 	unsigned int valid_open_flags;
 
-	chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return -ENXIO);
+	chip = substream->rmidi->private_data;
 	valid_open_flags = chip->hardware >= SB_HW_20
 		? SB_OPEN_MIDI_INPUT | SB_OPEN_MIDI_INPUT_TRIGGER : 0;
 	spin_lock_irqsave(&chip->open_lock, flags);
@@ -126,7 +126,7 @@ static int snd_sb8dsp_midi_input_close(snd_rawmidi_substream_t * substream)
 	unsigned long flags;
 	sb_t *chip;
 
-	chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return -ENXIO);
+	chip = substream->rmidi->private_data;
 	spin_lock_irqsave(&chip->open_lock, flags);
 	chip->open &= ~(SB_OPEN_MIDI_INPUT | SB_OPEN_MIDI_INPUT_TRIGGER);
 	chip->midi_substream_input = NULL;
@@ -144,7 +144,7 @@ static int snd_sb8dsp_midi_output_close(snd_rawmidi_substream_t * substream)
 	unsigned long flags;
 	sb_t *chip;
 
-	chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return -ENXIO);
+	chip = substream->rmidi->private_data;
 	spin_lock_irqsave(&chip->open_lock, flags);
 	chip->open &= ~(SB_OPEN_MIDI_OUTPUT | SB_OPEN_MIDI_OUTPUT_TRIGGER);
 	chip->midi_substream_output = NULL;
@@ -162,7 +162,7 @@ static void snd_sb8dsp_midi_input_trigger(snd_rawmidi_substream_t * substream, i
 	unsigned long flags;
 	sb_t *chip;
 
-	chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return);
+	chip = substream->rmidi->private_data;
 	spin_lock_irqsave(&chip->open_lock, flags);
 	if (up) {
 		if (!(chip->open & SB_OPEN_MIDI_INPUT_TRIGGER)) {
@@ -188,7 +188,7 @@ static void snd_sb8dsp_midi_output_write(snd_rawmidi_substream_t * substream)
 	int max = 32;
 
 	/* how big is Tx FIFO? */
-	chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return);
+	chip = substream->rmidi->private_data;
 	while (max-- > 0) {
 		spin_lock_irqsave(&chip->open_lock, flags);
 		if (snd_rawmidi_transmit_peek(substream, &byte, 1) != 1) {
@@ -219,7 +219,7 @@ static void snd_sb8dsp_midi_output_write(snd_rawmidi_substream_t * substream)
 static void snd_sb8dsp_midi_output_timer(unsigned long data)
 {
 	snd_rawmidi_substream_t * substream = (snd_rawmidi_substream_t *) data;
-	sb_t * chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return);
+	sb_t * chip = substream->rmidi->private_data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&chip->open_lock, flags);
@@ -234,7 +234,7 @@ static void snd_sb8dsp_midi_output_trigger(snd_rawmidi_substream_t * substream,
 	unsigned long flags;
 	sb_t *chip;
 
-	chip = snd_magic_cast(sb_t, substream->rmidi->private_data, return);
+	chip = substream->rmidi->private_data;
 	spin_lock_irqsave(&chip->open_lock, flags);
 	if (up) {
 		if (!(chip->open & SB_OPEN_MIDI_OUTPUT_TRIGGER)) {
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c
index f36383a3f..8935ae93d 100644
--- a/sound/isa/sb/sb_common.c
+++ b/sound/isa/sb/sb_common.c
@@ -33,12 +33,9 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 
-#define chip_t sb_t
-
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("ALSA lowlevel driver for Sound Blaster cards");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 
 #define BUSY_LOOPS 100000
 
@@ -197,13 +194,13 @@ static int snd_sbdsp_free(sb_t *chip)
 		free_dma(chip->dma16);
 	}
 #endif
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_sbdsp_dev_free(snd_device_t *device)
 {
-	sb_t *chip = snd_magic_cast(sb_t, device->device_data, return -ENXIO);
+	sb_t *chip = device->device_data;
 	return snd_sbdsp_free(chip);
 }
 
@@ -224,7 +221,7 @@ int snd_sbdsp_create(snd_card_t *card,
 
 	snd_assert(r_chip != NULL, return -EINVAL);
 	*r_chip = NULL;
-	chip = snd_magic_kcalloc(sb_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c
index 31baf2030..cc5a2c6de 100644
--- a/sound/isa/sb/sb_mixer.c
+++ b/sound/isa/sb/sb_mixer.c
@@ -27,8 +27,6 @@
 #include <sound/sb.h>
 #include <sound/control.h>
 
-#define chip_t sb_t
-
 #undef IO_DEBUG
 
 void snd_sbmixer_write(sb_t *chip, unsigned char reg, unsigned char data)
diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c
index c59a84cba..a410ecaf9 100644
--- a/sound/isa/sgalaxy.c
+++ b/sound/isa/sgalaxy.c
@@ -39,8 +39,7 @@
 MODULE_AUTHOR("Christopher Butler <chrisb@sandy.force9.co.uk>");
 MODULE_DESCRIPTION("Aztech Sound Galaxy");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Aztech Systems,Sound Galaxy}}");
+MODULE_SUPPORTED_DEVICE("{{Aztech Systems,Sound Galaxy}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -53,22 +52,16 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Sound Galaxy soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Sound Galaxy soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(sbport, long, boot_devs, 0444);
 MODULE_PARM_DESC(sbport, "Port # for Sound Galaxy SB driver.");
-MODULE_PARM_SYNTAX(sbport, SNDRV_ENABLED ",allows:{{0x220},{0x240}},dialog:list");
 module_param_array(wssport, long, boot_devs, 0444);
 MODULE_PARM_DESC(wssport, "Port # for Sound Galaxy WSS driver.");
-MODULE_PARM_SYNTAX(wssport, SNDRV_ENABLED ",allows:{{0x530},{0xe80},{0xf40},{0x604}},dialog:list");
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for Sound Galaxy driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_ENABLED ",allows:{{7},{9},{10},{11}},dialog:list");
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for Sound Galaxy driver.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA8_DESC);
 
 #define SGALAXY_AUXC_LEFT 18
 #define SGALAXY_AUXC_RIGHT 19
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index c45061308..51e7a63cd 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -36,8 +36,6 @@
 
 #include <sound/sscape_ioctl.h>
 
-#define chip_t cs4231_t
-
 
 MODULE_AUTHOR("Chris Rankin");
 MODULE_DESCRIPTION("ENSONIQ SoundScape PnP driver");
@@ -53,27 +51,21 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index number for SoundScape soundcard");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "Description for SoundScape card");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 
 module_param_array(port, long, boot_devs, 0444);
 MODULE_PARM_DESC(port, "Port # for SoundScape driver.");
-MODULE_PARM_SYNTAX(port, SNDRV_ENABLED);
 
 module_param_array(irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for SoundScape driver.");
-MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC);
 
 module_param_array(mpu_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU401 IRQ # for SoundScape driver.");
-MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC);
 
 module_param_array(dma, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma, "DMA # for SoundScape driver.");
-MODULE_PARM_SYNTAX(dma, SNDRV_DMA8_DESC);
   
 #ifdef CONFIG_PNP
 static struct pnp_card_device_id sscape_pnpids[] = {
@@ -177,11 +169,8 @@ static inline struct soundscape *get_hwdep_soundscape(snd_hwdep_t * hw)
 static struct snd_dma_buffer *get_dmabuf(struct snd_dma_buffer *buf, unsigned long size)
 {
 	if (buf) {
-		struct snd_dma_device dev;
-		memset(&dev, 0, sizeof(dev));
-		dev.type = SNDRV_DMA_TYPE_DEV;
-		dev.dev = snd_dma_isa_data();
-		if (snd_dma_alloc_pages_fallback(&dev, size, buf) < 0) {
+		if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV, snd_dma_isa_data(),
+						 size, buf) < 0) {
 			snd_printk(KERN_ERR "sscape: Failed to allocate %lu bytes for DMA\n", size);
 			return NULL;
 		}
@@ -195,13 +184,8 @@ static struct snd_dma_buffer *get_dmabuf(struct snd_dma_buffer *buf, unsigned lo
  */
 static void free_dmabuf(struct snd_dma_buffer *buf)
 {
-	if (buf && buf->area) {
-		struct snd_dma_device dev;
-		memset(&dev, 0, sizeof(dev));
-		dev.type = SNDRV_DMA_TYPE_DEV;
-		dev.dev = snd_dma_isa_data();
-		snd_dma_free_pages(&dev, buf);
-	}
+	if (buf && buf->area)
+		snd_dma_free_pages(buf);
 }
 
 
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index e0c8e1430..cb0322fcb 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -30,13 +30,10 @@
 #include <sound/opl3.h>
 #include <sound/snd_wavefront.h>
 
-#define chip_t cs4231_t
-
 MODULE_AUTHOR("Paul Barton-Davis <pbd@op.net>");
 MODULE_DESCRIPTION("Turtle Beach Wavefront");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Turtle Beach,Maui/Tropez/Tropez+}}");
+MODULE_SUPPORTED_DEVICE("{{Turtle Beach,Maui/Tropez/Tropez+}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	    /* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	    /* ID for this card */
@@ -56,48 +53,34 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for WaveFront soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for WaveFront soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable WaveFront soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 #ifdef CONFIG_PNP
 module_param_array(isapnp, bool, boot_devs, 0444);
 MODULE_PARM_DESC(isapnp, "ISA PnP detection for WaveFront soundcards.");
-MODULE_PARM_SYNTAX(isapnp, SNDRV_ISAPNP_DESC);
 #endif
 module_param_array(cs4232_pcm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(cs4232_pcm_port, "Port # for CS4232 PCM interface.");
-MODULE_PARM_SYNTAX(cs4232_pcm_port, SNDRV_PORT12_DESC);
 module_param_array(cs4232_pcm_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(cs4232_pcm_irq, "IRQ # for CS4232 PCM interface.");
-MODULE_PARM_SYNTAX(cs4232_pcm_irq, SNDRV_ENABLED ",allows:{{5},{7},{9},{11},{12},{15}},dialog:list");
 module_param_array(dma1, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for CS4232 PCM interface.");
-MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC);
 module_param_array(dma2, int, boot_devs, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for CS4232 PCM interface.");
-MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC);
 module_param_array(cs4232_mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(cs4232_mpu_port, "port # for CS4232 MPU-401 interface.");
-MODULE_PARM_SYNTAX(cs4232_mpu_port, SNDRV_PORT12_DESC);
 module_param_array(cs4232_mpu_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(cs4232_mpu_irq, "IRQ # for CS4232 MPU-401 interface.");
-MODULE_PARM_SYNTAX(cs4232_mpu_irq, SNDRV_ENABLED ",allows:{{9},{11},{12},{15}},dialog:list");
 module_param_array(ics2115_irq, int, boot_devs, 0444);
 MODULE_PARM_DESC(ics2115_irq, "IRQ # for ICS2115.");
-MODULE_PARM_SYNTAX(ics2115_irq, SNDRV_ENABLED ",allows:{{9},{11},{12},{15}},dialog:list");
 module_param_array(ics2115_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(ics2115_port, "Port # for ICS2115.");
-MODULE_PARM_SYNTAX(ics2115_port, SNDRV_PORT12_DESC);
 module_param_array(fm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(fm_port, "FM port #.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_PORT12_DESC);
 module_param_array(use_cs4232_midi, bool, boot_devs, 0444);
 MODULE_PARM_DESC(use_cs4232_midi, "Use CS4232 MPU-401 interface (inaccessibly located inside your computer)");
-MODULE_PARM_SYNTAX(use_cs4232_midi, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 
 static snd_card_t *snd_wavefront_legacy[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c
index 92aa782d6..2d42c694f 100644
--- a/sound/isa/wavefront/wavefront_fx.c
+++ b/sound/isa/wavefront/wavefront_fx.c
@@ -34,7 +34,7 @@
 
 /* weird stuff, derived from port I/O tracing with dosemu */
 
-static unsigned char page_zero[] __initdata = {
+unsigned char page_zero[] __initdata = {
 0x01, 0x7c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x00,
 0x11, 0x00, 0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x13, 0x00, 0x00,
 0x00, 0x14, 0x02, 0x76, 0x00, 0x60, 0x00, 0x80, 0x02, 0x00, 0x00,
@@ -61,7 +61,7 @@ static unsigned char page_zero[] __initdata = {
 0x1d, 0x02, 0xdf
 };
 
-static unsigned char page_one[] __initdata = {
+unsigned char page_one[] __initdata = {
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x19, 0x00,
 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xd8, 0x00, 0x00,
 0x02, 0x20, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01,
@@ -88,7 +88,7 @@ static unsigned char page_one[] __initdata = {
 0x60, 0x00, 0x1b
 };
 
-static unsigned char page_two[] __initdata = {
+unsigned char page_two[] __initdata = {
 0xc4, 0x00, 0x44, 0x07, 0x44, 0x00, 0x40, 0x25, 0x01, 0x06, 0xc4,
 0x07, 0x40, 0x25, 0x01, 0x00, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -103,7 +103,7 @@ static unsigned char page_two[] __initdata = {
 0x46, 0x05, 0x46, 0x07, 0x46, 0x07, 0x44
 };
 
-static unsigned char page_three[] __initdata = {
+unsigned char page_three[] __initdata = {
 0x07, 0x40, 0x00, 0x00, 0x00, 0x47, 0x00, 0x40, 0x00, 0x40, 0x06,
 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -118,7 +118,7 @@ static unsigned char page_three[] __initdata = {
 0x02, 0x00, 0x42, 0x00, 0xc0, 0x00, 0x40
 };
 
-static unsigned char page_four[] __initdata = {
+unsigned char page_four[] __initdata = {
 0x63, 0x03, 0x26, 0x02, 0x2c, 0x00, 0x24, 0x00, 0x2e, 0x02, 0x02,
 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -133,7 +133,7 @@ static unsigned char page_four[] __initdata = {
 0x02, 0x62, 0x02, 0x20, 0x01, 0x21, 0x01
 };
 
-static unsigned char page_six[] __initdata = {
+unsigned char page_six[] __initdata = {
 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00,
 0x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0e,
 0x00, 0x00, 0x10, 0x00, 0x00, 0x12, 0x00, 0x00, 0x14, 0x00, 0x00,
@@ -154,7 +154,7 @@ static unsigned char page_six[] __initdata = {
 0x80, 0x00, 0x7e, 0x80, 0x80
 };
 
-static unsigned char page_seven[] __initdata = {
+unsigned char page_seven[] __initdata = {
 0x0f, 0xff, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
 0x08, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f,
@@ -181,7 +181,7 @@ static unsigned char page_seven[] __initdata = {
 0x00, 0x02, 0x00
 };
 
-static unsigned char page_zero_v2[] __initdata = {
+unsigned char page_zero_v2[] __initdata = {
 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -193,7 +193,7 @@ static unsigned char page_zero_v2[] __initdata = {
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
-static unsigned char page_one_v2[] __initdata = {
+unsigned char page_one_v2[] __initdata = {
 0x01, 0xc0, 0x01, 0xfa, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -205,21 +205,21 @@ static unsigned char page_one_v2[] __initdata = {
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
-static unsigned char page_two_v2[] __initdata = {
+unsigned char page_two_v2[] __initdata = {
 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00
 };
-static unsigned char page_three_v2[] __initdata = {
+unsigned char page_three_v2[] __initdata = {
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00
 };
-static unsigned char page_four_v2[] __initdata = {
+unsigned char page_four_v2[] __initdata = {
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -227,7 +227,7 @@ static unsigned char page_four_v2[] __initdata = {
 0x00, 0x00, 0x00, 0x00
 };
 
-static unsigned char page_seven_v2[] __initdata = {
+unsigned char page_seven_v2[] __initdata = {
 0x0f, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -239,7 +239,7 @@ static unsigned char page_seven_v2[] __initdata = {
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
-static unsigned char mod_v2[] __initdata = {
+unsigned char mod_v2[] __initdata = {
 0x01, 0x00, 0x02, 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02,
 0x00, 0x01, 0x03, 0x02, 0x00, 0x01, 0x04, 0x02, 0x00, 0x01, 0x05,
 0x02, 0x00, 0x01, 0x06, 0x02, 0x00, 0x01, 0x07, 0x02, 0x00, 0xb0,
@@ -269,7 +269,7 @@ static unsigned char mod_v2[] __initdata = {
 0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x05, 0x02, 0x01, 0x01,
 0x06, 0x02, 0x01, 0x01, 0x07, 0x02, 0x01
 };
-static unsigned char coefficients[] __initdata = {
+unsigned char coefficients[] __initdata = {
 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x03,
 0x11, 0x00, 0x4d, 0x01, 0x32, 0x07, 0x46, 0x00, 0x00, 0x07, 0x49,
 0x00, 0x00, 0x07, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x01,
@@ -305,14 +305,14 @@ static unsigned char coefficients[] __initdata = {
 0x06, 0x6c, 0x4c, 0x6c, 0x06, 0x50, 0x52, 0xe2, 0x06, 0x42, 0x02,
 0xba
 };
-static unsigned char coefficients2[] __initdata = {
+unsigned char coefficients2[] __initdata = {
 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x45, 0x0f,
 0xff, 0x07, 0x48, 0x0f, 0xff, 0x07, 0x7b, 0x04, 0xcc, 0x07, 0x7d,
 0x04, 0xcc, 0x07, 0x7c, 0x00, 0x00, 0x07, 0x7e, 0x00, 0x00, 0x07,
 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x47, 0x00, 0x00,
 0x07, 0x4a, 0x00, 0x00, 0x07, 0x4c, 0x00, 0x00, 0x07, 0x4e, 0x00, 0x00
 };
-static unsigned char coefficients3[] __initdata = {
+unsigned char coefficients3[] __initdata = {
 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x28, 0x00, 0x51, 0x00,
 0x51, 0x00, 0x7a, 0x00, 0x7a, 0x00, 0xa3, 0x00, 0xa3, 0x00, 0xcc,
 0x00, 0xcc, 0x00, 0xf5, 0x00, 0xf5, 0x01, 0x1e, 0x01, 0x1e, 0x01,
@@ -486,8 +486,9 @@ snd_wavefront_fx_ioctl (snd_hwdep_t *sdev, struct file *file,
 	snd_wavefront_card_t *acard;
 	snd_wavefront_t *dev;
 	wavefront_fx_info r;
-	unsigned short page_data[256];
+	unsigned short *page_data = NULL;
 	unsigned short *pd;
+	int err = 0;
 
 	snd_assert(sdev->card != NULL, return -ENODEV);
 	
@@ -514,23 +515,30 @@ snd_wavefront_fx_ioctl (snd_hwdep_t *sdev, struct file *file,
 		} else if (r.data[2] == 1) {
 			pd = (unsigned short *) &r.data[3];
 		} else {
-			if (r.data[2] > (long)sizeof (page_data)) {
+			if (r.data[2] > 256) {
 				snd_printk ("cannot write "
-					    "> 255 bytes to FX\n");
+					    "> 512 bytes to FX\n");
 				return -EIO;
 			}
+			page_data = kmalloc(r.data[2] * sizeof(short), GFP_KERNEL);
+			if (!page_data)
+				return -ENOMEM;
 			if (copy_from_user (page_data,
 					    (unsigned char __user *) r.data[3],
-					    r.data[2]))
+					    r.data[2] * sizeof(short))) {
+				kfree(page_data);
 				return -EFAULT;
+			}
 			pd = page_data;
 		}
 
-		wavefront_fx_memset (dev,
+		err = wavefront_fx_memset (dev,
 			     r.data[0], /* page */
 			     r.data[1], /* addr */
 			     r.data[2], /* cnt */
 			     pd);
+		if (page_data)
+			kfree(page_data);
 		break;
 
 	default:
@@ -538,7 +546,7 @@ snd_wavefront_fx_ioctl (snd_hwdep_t *sdev, struct file *file,
 			    r.request);
 		return -ENOTTY;
 	}
-	return 0;
+	return err;
 }
 
 /* YSS225 initialization.
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
index b4fab43e4..1d9ee967b 100644
--- a/sound/isa/wavefront/wavefront_synth.c
+++ b/sound/isa/wavefront/wavefront_synth.c
@@ -1961,6 +1961,12 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path)
 			break;
 		}
 
+		if (section_length < 0 || section_length > WF_SECTION_MAX) {
+			snd_printk ("invalid firmware section length %d\n",
+				    section_length);
+			goto failure;
+		}
+
 		if (sys_read (fd, section, section_length) != section_length) {
 			snd_printk ("firmware section "
 				"read error.\n");
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index 05f6bc8ec..46022a534 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -127,8 +127,8 @@ config SOUND_ES1371
 	  <file:Documentation/sound/oss/es1371>.
 
 config SOUND_ESSSOLO1
-	tristate "ESS Technology Solo1"
-	depends on SOUND_PRIME!=n && SOUND && SOUND_GAMEPORT
+	tristate "ESS Technology Solo1" 
+	depends on SOUND_PRIME!=n && SOUND && SOUND_GAMEPORT && PCI
 	help
 	  Say Y or M if you have a PCI sound card utilizing the ESS Technology
 	  Solo1 chip. To find out if your sound card uses a
@@ -139,7 +139,7 @@ config SOUND_ESSSOLO1
 
 config SOUND_MAESTRO
 	tristate "ESS Maestro, Maestro2, Maestro2E driver"
-	depends on SOUND_PRIME!=n && SOUND
+	depends on SOUND_PRIME!=n && SOUND && PCI
 	help
 	  Say Y or M if you have a sound system driven by ESS's Maestro line
 	  of PCI sound chips.  These include the Maestro 1, Maestro 2, and
@@ -162,7 +162,10 @@ config SOUND_ICH
 
 config SOUND_HARMONY
 	tristate "PA Harmony audio driver"
-	depends on GSC_LASI && SOUND
+	depends on GSC_LASI && SOUND_PRIME!=n
+	help
+	  Say 'Y' or 'M' to include support for Harmony soundchip
+	  on HP 712, 715/new and many other GSC based machines.
 
 config SOUND_SONICVIBES
 	tristate "S3 SonicVibes"
diff --git a/sound/oss/Makefile b/sound/oss/Makefile
index 6fc30dc7f..226b395bb 100644
--- a/sound/oss/Makefile
+++ b/sound/oss/Makefile
@@ -103,7 +103,7 @@ sb_lib-objs	:= sb_common.o sb_audio.o sb_midi.o sb_mixer.o sb_ess.o
 vidc_mod-objs	:= vidc.o vidc_fill.o
 wavefront-objs  := wavfront.o wf_midi.o yss225.o
 
-host-progs	:= bin2hex hex2hex
+hostprogs-y	:= bin2hex hex2hex
 
 # Files generated that shall be removed upon make clean
 clean-files := maui_boot.h msndperm.c msndinit.c pndsperm.c pndspini.c \
diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c
index af1225d9f..c78a5a11d 100644
--- a/sound/oss/ad1848.c
+++ b/sound/oss/ad1848.c
@@ -1538,7 +1538,7 @@ static void ad1848_init_hw(ad1848_info * devc)
 	ad1848_mixer_reset(devc);
 }
 
-int ad1848_detect(int io_base, int *ad_flags, int *osp)
+int ad1848_detect(struct resource *ports, int *ad_flags, int *osp)
 {
 	unsigned char tmp;
 	ad1848_info *devc = &adev_info[nr_ad1848_devs];
@@ -1548,6 +1548,7 @@ int ad1848_detect(int io_base, int *ad_flags, int *osp)
 	int ad1847_flag = 0;
 	int cs4248_flag = 0;
 	int sscape_flag = 0;
+	int io_base = ports->start;
 
 	int i;
 
@@ -1578,11 +1579,6 @@ int ad1848_detect(int io_base, int *ad_flags, int *osp)
 		printk(KERN_ERR "ad1848 - Too many audio devices\n");
 		return 0;
 	}
-	if (check_region(io_base, 4))
-	{
-		printk(KERN_ERR "ad1848.c: Port %x not free.\n", io_base);
-		return 0;
-	}
 	spin_lock_init(&devc->lock);
 	devc->base = io_base;
 	devc->irq_ok = 0;
@@ -1951,7 +1947,7 @@ int ad1848_detect(int io_base, int *ad_flags, int *osp)
 	return 1;
 }
 
-int ad1848_init (char *name, int io_base, int irq, int dma_playback,
+int ad1848_init (char *name, struct resource *ports, int irq, int dma_playback,
 		int dma_capture, int share_dma, int *osp, struct module *owner)
 {
 	/*
@@ -1986,8 +1982,7 @@ int ad1848_init (char *name, int io_base, int irq, int dma_playback,
 		sprintf(dev_name,
 			"Generic audio codec (%s)", devc->chip_name);
 
-	if (!request_region(devc->base, 4, devc->name))
-		return -1;
+	rename_region(ports, devc->name);
 
 	conf_printf2(dev_name, devc->base, devc->irq, dma_playback, dma_capture);
 
@@ -2522,21 +2517,16 @@ static int init_deskpro(struct address_info *hw_config)
 	return 1;
 }
 
-int probe_ms_sound(struct address_info *hw_config)
+int probe_ms_sound(struct address_info *hw_config, struct resource *ports)
 {
 	unsigned char   tmp;
 
 	DDB(printk("Entered probe_ms_sound(%x, %d)\n", hw_config->io_base, hw_config->card_subtype));
 
-	if (check_region(hw_config->io_base, 8))
-	{
-		printk(KERN_ERR "MSS: I/O port conflict\n");
-		return 0;
-	}
 	if (hw_config->card_subtype == 1)	/* Has no IRQ/DMA registers */
 	{
 		/* check_opl3(0x388, hw_config); */
-		return ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp);
+		return ad1848_detect(ports, NULL, hw_config->osp);
 	}
 
 	if (deskpro_xl && hw_config->card_subtype == 2)	/* Compaq Deskpro XL */
@@ -2562,7 +2552,7 @@ int probe_ms_sound(struct address_info *hw_config)
 		  int             ret;
 
 		  DDB(printk("I/O address is inactive (%x)\n", tmp));
-		  if (!(ret = ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp)))
+		  if (!(ret = ad1848_detect(ports, NULL, hw_config->osp)))
 			  return 0;
 		  return 1;
 	}
@@ -2575,7 +2565,7 @@ int probe_ms_sound(struct address_info *hw_config)
 
 		MDB(printk(KERN_ERR "No MSS signature detected on port 0x%x (0x%x)\n", hw_config->io_base, (int) inb(hw_config->io_base + 3)));
 		DDB(printk("Trying to detect codec anyway but IRQ/DMA may not work\n"));
-		if (!(ret = ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp)))
+		if (!(ret = ad1848_detect(ports, NULL, hw_config->osp)))
 			return 0;
 
 		hw_config->card_subtype = 1;
@@ -2610,10 +2600,10 @@ int probe_ms_sound(struct address_info *hw_config)
 		printk(KERN_ERR "MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq);
 		return 0;
 	}
-	return ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp);
+	return ad1848_detect(ports, NULL, hw_config->osp);
 }
 
-void attach_ms_sound(struct address_info *hw_config, struct module *owner)
+void attach_ms_sound(struct address_info *hw_config, struct resource *ports, struct module *owner)
 {
 	static signed char interrupt_bits[12] =
 	{
@@ -2634,13 +2624,12 @@ void attach_ms_sound(struct address_info *hw_config, struct module *owner)
 
 	if (hw_config->card_subtype == 1)	/* Has no IRQ/DMA registers */
 	{
-		hw_config->slots[0] = ad1848_init("MS Sound System", hw_config->io_base + 4,
+		hw_config->slots[0] = ad1848_init("MS Sound System", ports,
 						    hw_config->irq,
 						    hw_config->dma,
 						    hw_config->dma2, 0, 
 						    hw_config->osp,
 						    owner);
-		request_region(hw_config->io_base, 4, "WSS config");
 		return;
 	}
 	/*
@@ -2651,6 +2640,8 @@ void attach_ms_sound(struct address_info *hw_config, struct module *owner)
 	if (bits == -1)
 	{
 		printk(KERN_ERR "MSS: Bad IRQ %d\n", hw_config->irq);
+		release_region(ports->start, 4);
+		release_region(ports->start - 4, 4);
 		return;
 	}
 	outb((bits | 0x40), config_port);
@@ -2694,12 +2685,11 @@ void attach_ms_sound(struct address_info *hw_config, struct module *owner)
 
 	outb((bits | dma_bits[dma] | dma2_bit), config_port);	/* Write IRQ+DMA setup */
 
-	hw_config->slots[0] = ad1848_init("MS Sound System", hw_config->io_base + 4,
+	hw_config->slots[0] = ad1848_init("MS Sound System", ports,
 					  hw_config->irq,
 					  dma, dma2, 0,
 					  hw_config->osp,
 					  THIS_MODULE);
-	request_region(hw_config->io_base, 4, "WSS config");
 }
 
 void unload_ms_sound(struct address_info *hw_config)
@@ -3095,6 +3085,7 @@ static int __init init_ad1848(void)
 #endif
 
 	if(io != -1) {
+		struct resource *ports;
 	        if( isapnp == 0 )
 	        {
 			if(irq == -1 || dma == -1) {
@@ -3109,9 +3100,22 @@ static int __init init_ad1848(void)
 			cfg.card_subtype = type;
 	        }
 
-		if(!probe_ms_sound(&cfg))
+		ports = request_region(io + 4, 4, "ad1848");
+
+		if (!ports)
+			return -EBUSY;
+
+		if (!request_region(io, 4, "WSS config")) {
+			release_region(io + 4, 4);
+			return -EBUSY;
+		}
+
+		if (!probe_ms_sound(&cfg, ports)) {
+			release_region(io + 4, 4);
+			release_region(io, 4);
 			return -ENODEV;
-		attach_ms_sound(&cfg, THIS_MODULE);
+		}
+		attach_ms_sound(&cfg, ports, THIS_MODULE);
 		loaded = 1;
 	}
 	return 0;
diff --git a/sound/oss/ad1848.h b/sound/oss/ad1848.h
index 76e3c6a1d..d0573b023 100644
--- a/sound/oss/ad1848.h
+++ b/sound/oss/ad1848.h
@@ -11,15 +11,15 @@
                 ad1848_control(AD1848_MIXER_REROUTE, ((oldctl)<<8)|(newctl))
 		
 
-int ad1848_init(char *name, int io_base, int irq, int dma_playback,
+int ad1848_init(char *name, struct resource *ports, int irq, int dma_playback,
 	int dma_capture, int share_dma, int *osp, struct module *owner);
 void ad1848_unload (int io_base, int irq, int dma_playback, int dma_capture, int share_dma);
 
-int ad1848_detect (int io_base, int *flags, int *osp);
+int ad1848_detect (struct resource *ports, int *flags, int *osp);
 int ad1848_control(int cmd, int arg);
 
 irqreturn_t adintr(int irq, void *dev_id, struct pt_regs * dummy);
-void attach_ms_sound(struct address_info * hw_config, struct module * owner);
+void attach_ms_sound(struct address_info * hw_config, struct resource *ports, struct module * owner);
 
-int probe_ms_sound(struct address_info *hw_config);
+int probe_ms_sound(struct address_info *hw_config, struct resource *ports);
 void unload_ms_sound(struct address_info *hw_info);
diff --git a/sound/oss/ad1889.c b/sound/oss/ad1889.c
index 2423b1f2d..254773653 100644
--- a/sound/oss/ad1889.c
+++ b/sound/oss/ad1889.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001 Randolph Chung <tausq@debian.org>
+ *  Copyright 2001-2004 Randolph Chung <tausq@debian.org>
  *
  *  Analog Devices 1889 PCI audio driver (AD1819 AC97-compatible codec)
  *
@@ -61,6 +61,7 @@
 #define AD1889_WRITEL(dev,reg,val) writel((val), dev->regbase + reg)
 
 //now 100ms
+/* #define WAIT_10MS()	schedule_timeout(HZ/10) */
 #define WAIT_10MS()	do { int __i; for (__i = 0; __i < 100; __i++) udelay(1000); } while(0)
 
 /* currently only support a single device */
@@ -69,25 +70,43 @@ static ad1889_dev_t *ad1889_dev = NULL;
 /************************* helper routines ***************************** */
 static inline void ad1889_set_wav_rate(ad1889_dev_t *dev, int rate)
 {
+	struct ac97_codec *ac97_codec = dev->ac97_codec;
+
+	DBG("Setting WAV rate to %d\n", rate);
 	dev->state[AD_WAV_STATE].dmabuf.rate = rate;
 	AD1889_WRITEW(dev, AD_DSWAS, rate);
+
+	/* Cycle the DAC to enable the new rate */
+	ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0x0200);
+	WAIT_10MS();
+	ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0);
 }
 
 static inline void ad1889_set_adc_rate(ad1889_dev_t *dev, int rate)
 {
+	struct ac97_codec *ac97_codec = dev->ac97_codec;
+
+	DBG("Setting ADC rate to %d\n", rate);
 	dev->state[AD_ADC_STATE].dmabuf.rate = rate;
 	AD1889_WRITEW(dev, AD_DSRES, rate);
+
+	/* Cycle the ADC to enable the new rate */
+	ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0x0100);
+	WAIT_10MS();
+	ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0);
 }
 
 static inline void ad1889_set_wav_fmt(ad1889_dev_t *dev, int fmt)
 {
 	u16 tmp;
 
+	DBG("Setting WAV format to 0x%x\n", fmt);
+
 	tmp = AD1889_READW(ad1889_dev, AD_DSWSMC);
-	if (fmt == AFMT_S16_LE) {
+	if (fmt & AFMT_S16_LE) {
 		//tmp |= 0x0100; /* set WA16 */
 		tmp |= 0x0300; /* set WA16 stereo */
-	} else if (fmt == AFMT_U8) {
+	} else if (fmt & AFMT_U8) {
 		tmp &= ~0x0100; /* clear WA16 */
 	} 
 	AD1889_WRITEW(ad1889_dev, AD_DSWSMC, tmp);
@@ -97,10 +116,12 @@ static inline void ad1889_set_adc_fmt(ad1889_dev_t *dev, int fmt)
 {
 	u16 tmp;
 
+	DBG("Setting ADC format to 0x%x\n", fmt);
+
 	tmp = AD1889_READW(ad1889_dev, AD_DSRAMC);
-	if (fmt == AFMT_S16_LE) {
+	if (fmt & AFMT_S16_LE) {
 		tmp |= 0x0100; /* set WA16 */
-	} else if (fmt == AFMT_U8) {
+	} else if (fmt & AFMT_U8) {
 		tmp &= ~0x0100; /* clear WA16 */
 	} 
 	AD1889_WRITEW(ad1889_dev, AD_DSRAMC, tmp);
@@ -133,6 +154,9 @@ static void ad1889_start_wav(ad1889_state_t *state)
 	dmabuf->dma_len = cnt;
 	dmabuf->ready = 1;
 
+	DBG("Starting playback at 0x%p for %ld bytes\n", dmabuf->rawbuf +
+	    dmabuf->rd_ptr, dmabuf->dma_len);
+
         /* load up the current register set */
 	AD1889_WRITEL(ad1889_dev, AD_DMAWAVCC, cnt);
 	AD1889_WRITEL(ad1889_dev, AD_DMAWAVICC, cnt);
@@ -243,7 +267,7 @@ static ad1889_dev_t *ad1889_alloc_dev(struct pci_dev *pci)
 		dmabuf->dma_handle = 0;
 		dmabuf->rd_ptr = dmabuf->wr_ptr = dmabuf->dma_len = 0UL;
 		dmabuf->ready = 0;
-		dmabuf->rate = 44100;
+		dmabuf->rate = 48000;
 	}
 	return dev;
 
@@ -472,7 +496,6 @@ static ssize_t ad1889_write(struct file *file, const char __user *buffer, size_t
 		long cnt = count;
 		unsigned long flags;
 
-
 		for (;;) {
 			long used_bytes;
 			long timeout;	/* max time for DMA in jiffies */
@@ -498,17 +521,11 @@ static ssize_t ad1889_write(struct file *file, const char __user *buffer, size_t
 			}
 
 			set_current_state(TASK_INTERRUPTIBLE);
-			if (!schedule_timeout(timeout + 1))
-				printk(KERN_WARNING "AD1889 timeout(%ld) r/w %lx/%lx len %lx\n",
-				    timeout+1,
-				    dmabuf->rd_ptr, dmabuf->wr_ptr,
-				    dmabuf->dma_len);
-
+			schedule_timeout(timeout + 1);
 			if (signal_pending(current)) {
 				ret = -ERESTARTSYS;
 				goto err2;
 			}
-
 		}
 
 		/* watch out for wrapping around static buffer */
@@ -616,6 +633,8 @@ static int ad1889_ioctl(struct inode *inode, struct file *file, unsigned int cmd
 	audio_buf_info abinfo;
 	int __user *p = (int __user *)arg;
 
+	DBG("ad1889_ioctl cmd 0x%x arg %lu\n", cmd, arg);
+
 	switch (cmd)
 	{
 	case OSS_GETVERSION:
@@ -674,11 +693,15 @@ static int ad1889_ioctl(struct inode *inode, struct file *file, unsigned int cmd
 		if (get_user(val, p))
 			return -EFAULT;
 
-		if (file->f_mode & FMODE_READ) 
-			ad1889_set_adc_fmt(dev, val);
+		if (val == 0) {
+			if (file->f_mode & FMODE_READ) 
+				ad1889_set_adc_fmt(dev, val);
 
-		if (file->f_mode & FMODE_WRITE) 
-			ad1889_set_wav_fmt(dev, val);
+			if (file->f_mode & FMODE_WRITE) 
+				ad1889_set_wav_fmt(dev, val);
+		} else {
+			val = AFMT_S16_LE | AFMT_U8;
+		}
 
 		return put_user(val, p);
 
@@ -758,7 +781,7 @@ static int ad1889_open(struct inode *inode, struct file *file)
 	
 	file->private_data = ad1889_dev;
 
-	ad1889_set_wav_rate(ad1889_dev, 44100);
+	ad1889_set_wav_rate(ad1889_dev, 48000);
 	ad1889_set_wav_fmt(ad1889_dev, AFMT_S16_LE);
 	AD1889_WRITEW(ad1889_dev, AD_DSWADA, 0x0404); /* attenuation */
 	return nonseekable_open(inode, file);
@@ -938,7 +961,6 @@ static irqreturn_t ad1889_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 			ad1889_stop_wav(&dev->state[AD_WAV_STATE]);	/* clean up */
 			ad1889_start_wav(&dev->state[AD_WAV_STATE]);	/* start new */
 		}
-
 	}
 
 	if ((stat & 0x2) && dev->state[AD_ADC_STATE].dmabuf.ready) { /* ADCI */
@@ -952,18 +974,19 @@ static irqreturn_t ad1889_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
 static void ad1889_initcfg(ad1889_dev_t *dev)
 {
-	u16 tmp;
+	u16 tmp16;
+	u32 tmp32;
 
 	/* make sure the interrupt bits are setup the way we want */
-	tmp = AD1889_READW(dev, AD_DMAWAVCTRL);
-	tmp &= ~0x00ff; /* flat dma, no sg, mask out the intr bits */
-	tmp |= 0x0004;  /* intr on count, loop */
-	AD1889_WRITEW(dev, AD_DMAWAVCTRL, tmp);
+	tmp32 = AD1889_READL(dev, AD_DMAWAVCTRL);
+	tmp32 &= ~0xff; /* flat dma, no sg, mask out the intr bits */
+	tmp32 |= 0x6;  /* intr on count, loop */
+	AD1889_WRITEL(dev, AD_DMAWAVCTRL, tmp32);
 
 	/* unmute... */
-	tmp = AD1889_READW(dev, AD_DSWADA);
-	tmp &= ~0x8080;
-	AD1889_WRITEW(dev, AD_DSWADA, tmp);
+	tmp16 = AD1889_READW(dev, AD_DSWADA);
+	tmp16 &= ~0x8080;
+	AD1889_WRITEW(dev, AD_DSWADA, tmp16);
 }
 
 static int __devinit ad1889_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
diff --git a/sound/oss/ad1889.h b/sound/oss/ad1889.h
index 5d13ef11d..964a6b4d5 100644
--- a/sound/oss/ad1889.h
+++ b/sound/oss/ad1889.h
@@ -34,9 +34,9 @@
 #define AD_DMAWAVICC	0x98	/* WAV interrupt current count */
 #define AD_DMAWAVIBC	0x9c	/* WAV interrupt base count */
 #define AD_DMARESCTRL	0xa0	/* RES PCI control/status */
-#define AD_DMAADCCTRL	0xa8	/* RES PCI control/status */
-#define AD_DMASYNCTRL	0xb0	/* RES PCI control/status */
-#define AD_DMAWAVCTRL	0xb8	/* RES PCI control/status */
+#define AD_DMAADCCTRL	0xa8	/* ADC PCI control/status */
+#define AD_DMASYNCTRL	0xb0	/* SYN PCI control/status */
+#define AD_DMAWAVCTRL	0xb8	/* WAV PCI control/status */
 #define AD_DMADISR	0xc0	/* PCI DMA intr status */
 #define AD_DMACHSS	0xc4	/* PCI DMA channel stop status */
 
diff --git a/sound/oss/ali5455.c b/sound/oss/ali5455.c
index a7e2c3c0a..8976224f5 100644
--- a/sound/oss/ali5455.c
+++ b/sound/oss/ali5455.c
@@ -65,7 +65,6 @@
 #include <linux/ac97_codec.h>
 #include <linux/interrupt.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 
 #ifndef PCI_DEVICE_ID_ALI_5455
 #define PCI_DEVICE_ID_ALI_5455	0x5455
diff --git a/sound/oss/au1000.c b/sound/oss/au1000.c
index ccfbad2dd..c5d220e36 100644
--- a/sound/oss/au1000.c
+++ b/sound/oss/au1000.c
@@ -67,9 +67,9 @@
 #include <linux/smp_lock.h>
 #include <linux/ac97_codec.h>
 #include <linux/wrapper.h>
+#include <linux/interrupt.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 #include <asm/au1000.h>
 #include <asm/au1000_dma.h>
 
diff --git a/sound/oss/awe_wave.c b/sound/oss/awe_wave.c
index f49a2dee4..c80d97c55 100644
--- a/sound/oss/awe_wave.c
+++ b/sound/oss/awe_wave.c
@@ -4130,7 +4130,7 @@ static void __init attach_mixer(void)
 	}
 }
 
-static void __exit unload_mixer(void)
+static void unload_mixer(void)
 {
 	if (my_mixerdev >= 0)
 		sound_unload_mixerdev(my_mixerdev);
@@ -4968,7 +4968,7 @@ static void __init attach_midiemu(void)
 		midi_devs[my_mididev] = &awe_midi_operations;
 }
 
-static void __exit unload_midiemu(void)
+static void unload_midiemu(void)
 {
 	if (my_mididev >= 0)
 		sound_unload_mididev(my_mididev);
diff --git a/sound/oss/btaudio.c b/sound/oss/btaudio.c
index 2a7ea80c5..0d76e7889 100644
--- a/sound/oss/btaudio.c
+++ b/sound/oss/btaudio.c
@@ -961,7 +961,7 @@ static int __devinit btaudio_probe(struct pci_dev *pci_dev,
 	/* init hw */
         btwrite(0, REG_GPIO_DMA_CTL);
         btwrite(0, REG_INT_MASK);
-        btwrite(~0x0UL, REG_INT_STAT);
+        btwrite(~0U, REG_INT_STAT);
 	pci_set_master(pci_dev);
 
 	if ((rc = request_irq(bta->irq, btaudio_irq, SA_SHIRQ|SA_INTERRUPT,
@@ -1033,7 +1033,7 @@ static void __devexit btaudio_remove(struct pci_dev *pci_dev)
 	/* turn off all DMA / IRQs */
         btand(~15, REG_GPIO_DMA_CTL);
         btwrite(0, REG_INT_MASK);
-        btwrite(~0x0UL, REG_INT_STAT);
+        btwrite(~0U, REG_INT_STAT);
 
 	/* unregister devices */
 	if (digital) {
diff --git a/sound/oss/cmpci.c b/sound/oss/cmpci.c
index 386107f47..a862958ac 100644
--- a/sound/oss/cmpci.c
+++ b/sound/oss/cmpci.c
@@ -3000,6 +3000,8 @@ static int __devinit cm_probe(struct pci_dev *pcidev, const struct pci_device_id
 	mm_segment_t fs;
 	int i, val, ret;
 	unsigned char reg_mask;
+	int timeout;
+	struct resource *ports;
 	struct {
 		unsigned short	deviceid;
 		char		*devicename;
@@ -3184,54 +3186,55 @@ static int __devinit cm_probe(struct pci_dev *pcidev, const struct pci_device_id
 	}
 #endif
 #ifdef CONFIG_SOUND_CMPCI_MIDI
+	switch (s->iomidi) {
+	    case 0x330:
+		reg_mask = 0;
+		break;
+	    case 0x320:
+		reg_mask = 0x20;
+		break;
+	    case 0x310:
+		reg_mask = 0x40;
+		break;
+	    case 0x300:
+		reg_mask = 0x60;
+		break;
+	    default:
+		s->iomidi = 0;
+		goto skip_mpu;
+	}
+	ports = request_region(s->iomidi, 2, "mpu401");
+	if (!ports)
+		goto skip_mpu;
 	/* disable MPU-401 */
 	maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x04, 0);
 	s->mpu_data.name = "cmpci mpu";
 	s->mpu_data.io_base = s->iomidi;
 	s->mpu_data.irq = -s->irq;	// tell mpu401 to share irq
-	if (probe_mpu401(&s->mpu_data))
+	if (probe_mpu401(&s->mpu_data, ports)) {
+		release_region(s->iomidi, 2);
 		s->iomidi = 0;
-	if (s->iomidi) {
-		/* set IO based at 0x330 */
-		switch (s->iomidi) {
-		    case 0x330:
-			reg_mask = 0;
-			break;
-		    case 0x320:
-			reg_mask = 0x20;
-			break;
-		    case 0x310:
-			reg_mask = 0x40;
-			break;
-		    case 0x300:
-			reg_mask = 0x60;
-			break;
-		    default:
-			s->iomidi = 0;
+		goto skip_mpu;
+	}
+	maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3, ~0x60, reg_mask);
+	/* enable MPU-401 */
+	maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x04);
+	/* clear all previously received interrupt */
+	for (timeout = 900000; timeout > 0; timeout--) {
+		if ((inb(s->iomidi + 1) && 0x80) == 0)
+			inb(s->iomidi);
+		else
 			break;
-		}
-		maskb(s->iobase + CODEC_CMI_LEGACY_CTRL + 3, ~0x60, reg_mask);
-		/* enable MPU-401 */
-		if (s->iomidi) {
-			int timeout;
-
-			maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x04);
-			/* clear all previously received interrupt */
-			for (timeout = 900000; timeout > 0; timeout--) {
-				if ((inb(s->iomidi + 1) && 0x80) == 0)
-					inb(s->iomidi);
-				else
-					break;
-			}
-	    		if (!probe_mpu401(&s->mpu_data)) {
-				s->iomidi = 0;
-				maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x04);
-			} else {
-				attach_mpu401(&s->mpu_data, THIS_MODULE);
-				s->midi_devc = s->mpu_data.slots[1];
-			}
-		}
 	}
+	if (!probe_mpu401(&s->mpu_data, ports)) {
+		release_region(s->iomidi, 2);
+		s->iomidi = 0;
+		maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x04);
+	} else {
+		attach_mpu401(&s->mpu_data, THIS_MODULE);
+		s->midi_devc = s->mpu_data.slots[1];
+	}
+skip_mpu:
 #endif
 #ifdef CONFIG_SOUND_CMPCI_JOYSTICK
 	/* enable joystick */
diff --git a/sound/oss/cs4232.c b/sound/oss/cs4232.c
index d05db7e96..1d0f6edc2 100644
--- a/sound/oss/cs4232.c
+++ b/sound/oss/cs4232.c
@@ -128,27 +128,33 @@ static void enable_xctrl(int baseio)
         outb(((unsigned char) (ENABLE_PINS | regd)), baseio + INDEX_DATA );
 }
 
-int __init probe_cs4232(struct address_info *hw_config, int isapnp_configured)
+static int __init probe_cs4232(struct address_info *hw_config, int isapnp_configured)
 {
 	int i, n;
 	int base = hw_config->io_base, irq = hw_config->irq;
 	int dma1 = hw_config->dma, dma2 = hw_config->dma2;
+	struct resource *ports;
+
+	if (base == -1 || irq == -1 || dma1 == -1) {
+		printk(KERN_ERR "cs4232: dma, irq and io must be set.\n");
+		return 0;
+	}
 
 	/*
 	 * Verify that the I/O port range is free.
 	 */
 
-	if (check_region(base, 4))
-	{
+	ports = request_region(base, 4, "ad1848");
+	if (!ports) {
 		printk(KERN_ERR "cs4232.c: I/O port 0x%03x not free\n", base);
 		return 0;
 	}
-	if (ad1848_detect(hw_config->io_base, NULL, hw_config->osp)) {
-		return 1;	/* The card is already active */
+	if (ad1848_detect(ports, NULL, hw_config->osp)) {
+		goto got_it;	/* The card is already active */
 	}
 	if (isapnp_configured) {
 		printk(KERN_ERR "cs4232.c: ISA PnP configured, but not detected?\n");
-		return 0;
+		goto fail;
 	}
 
 	/*
@@ -241,30 +247,20 @@ int __init probe_cs4232(struct address_info *hw_config, int isapnp_configured)
 		 * Then try to detect the codec part of the chip
 		 */
 
-		if (ad1848_detect(hw_config->io_base, NULL, hw_config->osp))
-			return 1;
+		if (ad1848_detect(ports, NULL, hw_config->osp))
+			goto got_it;
 		
 		sleep(HZ);
 	}
+fail:
+	release_region(base, 4);
 	return 0;
-}
-
-void __init attach_cs4232(struct address_info *hw_config)
-{
-	int base = hw_config->io_base,
-		irq = hw_config->irq,
-		dma1 = hw_config->dma,
-		dma2 = hw_config->dma2;
-
-	if (base == -1 || irq == -1 || dma1 == -1) {
-		printk(KERN_ERR "cs4232: dma, irq and io must be set.\n");
-		return;
-	}
 
+got_it:
 	if (dma2 == -1)
 		dma2 = dma1;
 
-	hw_config->slots[0] = ad1848_init("Crystal audio controller", base,
+	hw_config->slots[0] = ad1848_init("Crystal audio controller", ports,
 					  irq,
 					  dma1,		/* Playback DMA */
 					  dma2,		/* Capture DMA */
@@ -308,9 +304,9 @@ void __init attach_cs4232(struct address_info *hw_config)
 	}
 	
 	if (bss)
-	{
         	enable_xctrl(base);
-	}
+
+	return 1;
 }
 
 static void __devexit unload_cs4232(struct address_info *hw_config)
@@ -423,7 +419,6 @@ static int cs4232_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev
 		kfree(isapnpcfg);
 		return -ENODEV;
 	}
-	attach_cs4232(isapnpcfg);
 	pnp_set_drvdata(dev,isapnpcfg);
 	return 0;
 }
@@ -486,7 +481,6 @@ static int __init init_cs4232(void)
 
 	if (probe_cs4232(&cfg,FALSE) == 0)
 		return -ENODEV;
-	attach_cs4232(&cfg);
 
 	return 0;
 }
diff --git a/sound/oss/cs4232.h b/sound/oss/cs4232.h
index 31c8d8b23..a5a00292c 100644
--- a/sound/oss/cs4232.h
+++ b/sound/oss/cs4232.h
@@ -1,5 +1,3 @@
 
-int probe_cs4232 (struct address_info *hw_config,int useisapnp);
-void attach_cs4232 (struct address_info *hw_config);
 int probe_cs4232_mpu (struct address_info *hw_config);
 void attach_cs4232_mpu (struct address_info *hw_config);
diff --git a/sound/oss/cs46xx.c b/sound/oss/cs46xx.c
index 418f976c4..c212b948c 100644
--- a/sound/oss/cs46xx.c
+++ b/sound/oss/cs46xx.c
@@ -94,7 +94,6 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 
 #include "cs46xxpm-24.h"
 #include "cs46xx_wrapper-24.h"
@@ -2096,7 +2095,7 @@ static ssize_t cs_read(struct file *file, char __user *buffer, size_t count, lof
 	unsigned copied=0;
 
 	CS_DBGOUT(CS_WAVE_READ | CS_FUNCTION, 4, 
-		printk("cs46xx: cs_read()+ %d\n",count) );
+		printk("cs46xx: cs_read()+ %zd\n",count) );
 	state = (struct cs_state *)card->states[0];
 	if(!state)
 		return -ENODEV;
@@ -2157,9 +2156,9 @@ static ssize_t cs_read(struct file *file, char __user *buffer, size_t count, lof
 		}
 
 		CS_DBGOUT(CS_WAVE_READ, 2, printk(KERN_INFO 
-			"_read() copy_to cnt=%d count=%d ", cnt,count) );
+			"_read() copy_to cnt=%d count=%zd ", cnt,count) );
 		CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO 
-			" .dmasize=%d .count=%d buffer=%p ret=%d\n",
+			" .dmasize=%d .count=%d buffer=%p ret=%zd\n",
 			dmabuf->dmasize,dmabuf->count,buffer,ret) );
 
                 if (cs_copy_to_user(state, buffer, 
@@ -2184,7 +2183,7 @@ out2:
 	up(&state->sem);
 	set_current_state(TASK_RUNNING);
 	CS_DBGOUT(CS_WAVE_READ | CS_FUNCTION, 4, 
-		printk("cs46xx: cs_read()- %d\n",ret) );
+		printk("cs46xx: cs_read()- %zd\n",ret) );
 	return ret;
 }
 
@@ -2202,7 +2201,7 @@ static ssize_t cs_write(struct file *file, const char __user *buffer, size_t cou
 	int cnt;
 
 	CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 4,
-		printk("cs46xx: cs_write called, count = %d\n", count) );
+		printk("cs46xx: cs_write called, count = %zd\n", count) );
 	state = (struct cs_state *)card->states[1];
 	if(!state)
 		return -ENODEV;
@@ -2309,7 +2308,7 @@ out:
 	set_current_state(TASK_RUNNING);
 
 	CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 2, 
-		printk("cs46xx: cs_write()- ret=0x%x\n", ret) );
+		printk("cs46xx: cs_write()- ret=%zd\n", ret) );
 	return ret;
 }
 
diff --git a/sound/oss/dmasound/Kconfig b/sound/oss/dmasound/Kconfig
index 0ffb08216..cb845580f 100644
--- a/sound/oss/dmasound/Kconfig
+++ b/sound/oss/dmasound/Kconfig
@@ -14,7 +14,7 @@ config DMASOUND_ATARI
 
 config DMASOUND_PMAC
 	tristate "PowerMac DMA sound support"
-	depends on PPC_PMAC && SOUND && I2C
+	depends on PPC32 && PPC_PMAC && SOUND && I2C
  	select DMASOUND
 	help
 	  If you want to use the internal audio of your PowerMac in Linux,
diff --git a/sound/oss/emu10k1/midi.c b/sound/oss/emu10k1/midi.c
index ec2424db4..f0a48f39f 100644
--- a/sound/oss/emu10k1/midi.c
+++ b/sound/oss/emu10k1/midi.c
@@ -320,7 +320,6 @@ static ssize_t emu10k1_midi_write(struct file *file, const char __user *buffer,
 {
 	struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data;
 	struct midi_hdr *midihdr;
-	ssize_t ret = 0;
 	unsigned long flags;
 
 	DPD(4, "emu10k1_midi_write(), count=%#x\n", (u32) count);
@@ -344,7 +343,7 @@ static ssize_t emu10k1_midi_write(struct file *file, const char __user *buffer,
 	if (copy_from_user(midihdr->data, buffer, count)) {
 		kfree(midihdr->data);
 		kfree(midihdr);
-		return ret ? ret : -EFAULT;
+		return -EFAULT;
 	}
 
 	spin_lock_irqsave(&midi_spinlock, flags);
diff --git a/sound/oss/forte.c b/sound/oss/forte.c
index ac4badae5..67b2bbb2a 100644
--- a/sound/oss/forte.c
+++ b/sound/oss/forte.c
@@ -45,7 +45,6 @@
 #include <linux/proc_fs.h>
 
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 #include <asm/io.h>
 
 #define DRIVER_NAME	"forte"
diff --git a/sound/oss/gus_card.c b/sound/oss/gus_card.c
index 88f5ca1cf..e0111a7b6 100644
--- a/sound/oss/gus_card.c
+++ b/sound/oss/gus_card.c
@@ -160,22 +160,29 @@ irqreturn_t gusintr(int irq, void *dev_id, struct pt_regs *dummy)
 
 #ifdef CONFIG_SOUND_GUS16
 
-static int __init probe_gus_db16(struct address_info *hw_config)
+static int __init init_gus_db16(struct address_info *hw_config)
 {
-	return ad1848_detect(hw_config->io_base, NULL, hw_config->osp);
-}
+	struct resource *ports;
+
+	ports = request_region(hw_config->io_base, 4, "ad1848");
+	if (!ports)
+		return 0;
+
+	if (!ad1848_detect(ports, NULL, hw_config->osp)) {
+		release_region(hw_config->io_base, 4);
+		return 0;
+	}
 
-static void __init attach_gus_db16(struct address_info *hw_config)
-{
 	gus_pcm_volume = 100;
 	gus_wave_volume = 90;
 
-	hw_config->slots[3] = ad1848_init("GUS 16 bit sampling", hw_config->io_base,
+	hw_config->slots[3] = ad1848_init("GUS 16 bit sampling", ports,
 					  hw_config->irq,
 					  hw_config->dma,
 					  hw_config->dma, 0,
 					  hw_config->osp,
 					  THIS_MODULE);
+	return 1;
 }
 
 static void __exit unload_gus_db16(struct address_info *hw_config)
@@ -244,11 +251,8 @@ static int __init init_gus(void)
 	}
 
 #ifdef CONFIG_SOUND_GUS16
-	if (probe_gus_db16(&cfg) && gus16) {
-		/* FIXME: This can't work, can it ? -- Christoph */
-		attach_gus_db16(&cfg);
+	if (gus16 && init_gus_db16(&cfg))
 		db16 = 1;
-	}	
 #endif
 	if (!probe_gus(&cfg))
 		return -ENODEV;
diff --git a/sound/oss/gus_wave.c b/sound/oss/gus_wave.c
index ed7333ca2..2cc924d7b 100644
--- a/sound/oss/gus_wave.c
+++ b/sound/oss/gus_wave.c
@@ -2942,6 +2942,8 @@ void __init gus_wave_init(struct address_info *hw_config)
 		}
 		else
 		{
+			struct resource *ports;
+			ports = request_region(gus_base + 0x10c, 4, "ad1848");
 			model_num = "MAX";
 			gus_type = 0x40;
 			mixer_type = CS4231;
@@ -2963,7 +2965,10 @@ void __init gus_wave_init(struct address_info *hw_config)
 				outb((max_config), gus_base + 0x106);	/* UltraMax control */
 			}
 
-			if (ad1848_detect(gus_base + 0x10c, &ad_flags, hw_config->osp))
+			if (!ports)
+				goto no_cs4231;
+
+			if (ad1848_detect(ports, &ad_flags, hw_config->osp))
 			{
 				char           *name = "GUS MAX";
 				int             old_num_mixers = num_mixers;
@@ -2977,7 +2982,7 @@ void __init gus_wave_init(struct address_info *hw_config)
 				if (hw_config->name)
 					name = hw_config->name;
 
-				hw_config->slots[1] = ad1848_init(name, gus_base + 0x10c,
+				hw_config->slots[1] = ad1848_init(name, ports,
 							-irq, gus_dma2,	/* Playback DMA */
 							gus_dma,	/* Capture DMA */
 							1,		/* Share DMA channels with GF1 */
@@ -2992,8 +2997,11 @@ void __init gus_wave_init(struct address_info *hw_config)
 					AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE);
 				}
 			}
-			else
+			else {
+				release_region(gus_base + 0x10c, 4);
+			no_cs4231:
 				printk(KERN_WARNING "GUS: No CS4231 ??");
+			}
 #else
 			printk(KERN_ERR "GUS MAX found, but not compiled in\n");
 #endif
diff --git a/sound/oss/harmony.c b/sound/oss/harmony.c
index 22f0eff13..2f83ac8a4 100644
--- a/sound/oss/harmony.c
+++ b/sound/oss/harmony.c
@@ -8,10 +8,11 @@
 	On older 715 machines you'll find the technically identical chip 
 	called 'Vivace'. Both Harmony and Vicace are supported by this driver.
 
-	Copyright 2000 (c) Linuxcare Canada, Alex deVries <alex@linuxcare.com>
+	Copyright 2000 (c) Linuxcare Canada, Alex deVries <alex@onefishtwo.ca>
 	Copyright 2000-2003 (c) Helge Deller <deller@gmx.de>
 	Copyright 2001 (c) Matthieu Delahaye <delahaym@esiee.fr>
 	Copyright 2001 (c) Jean-Christophe Vaugeois <vaugeoij@esiee.fr>
+	Copyright 2004 (c) Stuart Brady <sdbrady@ntlworld.com>
 
 				
 TODO:
@@ -124,9 +125,17 @@ TODO:
 #define GAIN_RO_MASK    ( 0x3f << GAIN_RO_SHIFT) 
 
 
-#define MAX_OUTPUT_LEVEL (GAIN_RO_MASK >> GAIN_RO_SHIFT)
-#define MAX_INPUT_LEVEL  (GAIN_RI_MASK >> GAIN_RI_SHIFT)
-#define MAX_VOLUME_LEVEL (GAIN_MA_MASK >> GAIN_MA_SHIFT)
+#define MAX_OUTPUT_LEVEL  (GAIN_RO_MASK >> GAIN_RO_SHIFT)
+#define MAX_INPUT_LEVEL   (GAIN_RI_MASK >> GAIN_RI_SHIFT)
+#define MAX_MONITOR_LEVEL (GAIN_MA_MASK >> GAIN_MA_SHIFT)
+
+#define MIXER_INTERNAL   SOUND_MIXER_LINE1
+#define MIXER_LINEOUT    SOUND_MIXER_LINE2
+#define MIXER_HEADPHONES SOUND_MIXER_LINE3
+
+#define MASK_INTERNAL   SOUND_MASK_LINE1
+#define MASK_LINEOUT    SOUND_MASK_LINE2
+#define MASK_HEADPHONES SOUND_MASK_LINE3
 
 /*
  * Channels Mask in mixer register
@@ -543,6 +552,7 @@ static ssize_t harmony_audio_write(struct file *file,
 	int count = 0;
 	int frame_size;
 	int buf_to_fill;
+	int fresh_buffer;
 
 	if (!harmony.format_initialized) {
 		if (harmony_format_auto_detect(buffer, total_count))
@@ -564,12 +574,16 @@ static ssize_t harmony_audio_write(struct file *file,
 		
 		
 		buf_to_fill = (harmony.first_filled_play+harmony.nb_filled_play); 
-		if (harmony.play_offset)
+		if (harmony.play_offset) {
 			buf_to_fill--;
+			buf_to_fill += MAX_BUFS;
+		}
 		buf_to_fill %= MAX_BUFS;
-
+		
+		fresh_buffer = (harmony.play_offset == 0);
+		
 		/* Figure out the size of the frame */
-		if ((total_count-count) > HARMONY_BUF_SIZE - harmony.play_offset) {
+		if ((total_count-count) >= HARMONY_BUF_SIZE - harmony.play_offset) {
 			frame_size = HARMONY_BUF_SIZE - harmony.play_offset;
 		} else {
 			frame_size = total_count - count;
@@ -587,7 +601,7 @@ static ssize_t harmony_audio_write(struct file *file,
 		CHECK_WBACK_INV_OFFSET(played_buf, (HARMONY_BUF_SIZE*buf_to_fill + harmony.play_offset), 
 				frame_size);
 	
-		if (!harmony.play_offset)
+		if (fresh_buffer)
 			harmony.nb_filled_play++;
 		
 		count += frame_size;
@@ -650,18 +664,17 @@ static int harmony_audio_ioctl(struct inode *inode,
 			switch (ival) {
 			case AFMT_MU_LAW:	new_format = HARMONY_DF_8BIT_ULAW; break;
 			case AFMT_A_LAW:	new_format = HARMONY_DF_8BIT_ALAW; break;
-			case AFMT_S16_LE:	/* fall through, but not really supported */
-			case AFMT_S16_BE:	new_format = HARMONY_DF_16BIT_LINEAR;
-						ival = AFMT_S16_BE;
-						break; 
+			case AFMT_S16_BE:	new_format = HARMONY_DF_16BIT_LINEAR; break;
 			default: {
 				DPRINTK(KERN_WARNING PFX 
 					"unsupported sound format 0x%04x requested.\n",
 					ival);
-				return -EINVAL;
+				ival = AFMT_S16_BE;
+				return put_user(ival, (int *) arg);
 			}
 			}
 			harmony_set_format(new_format);
+			return 0;
 		} else {
 			switch (harmony.data_format) {
 			case HARMONY_DF_8BIT_ULAW:	ival = AFMT_MU_LAW; break;
@@ -669,8 +682,8 @@ static int harmony_audio_ioctl(struct inode *inode,
 			case HARMONY_DF_16BIT_LINEAR:	ival = AFMT_U16_BE; break;
 			default: ival = 0;
 			}
+			return put_user(ival, (int *) arg);
 		}
-		return put_user(ival, (int *) arg);
 
 	case SOUND_PCM_READ_RATE:
 		ival = harmony.dac_rate;
@@ -689,7 +702,17 @@ static int harmony_audio_ioctl(struct inode *inode,
 		if (ival != 0 && ival != 1)
 			return -EINVAL;
 		harmony_set_stereo(ival);
-		return put_user(ival, (int *) arg);
+ 		return 0;
+ 
+ 	case SNDCTL_DSP_CHANNELS:
+ 		if (get_user(ival, (int *) arg))
+ 			return -EFAULT;
+ 		if (ival != 1 && ival != 2) {
+ 			ival = harmony.stereo_select == HARMONY_SS_MONO ? 1 : 2;
+ 			return put_user(ival, (int *) arg);
+ 		}
+ 		harmony_set_stereo(ival-1);
+ 		return 0;
 
 	case SNDCTL_DSP_GETBLKSIZE:
 		ival = HARMONY_BUF_SIZE;
@@ -887,7 +910,7 @@ static int harmony_mixer_get_level(int channel)
 	int right_level;
 
 	switch (channel) {
-		case SOUND_MIXER_OGAIN:
+		case SOUND_MIXER_VOLUME:
 			left_level  = (harmony.current_gain & GAIN_LO_MASK) >> GAIN_LO_SHIFT;
 			right_level = (harmony.current_gain & GAIN_RO_MASK) >> GAIN_RO_SHIFT;
 			left_level  = to_oss_level(MAX_OUTPUT_LEVEL - left_level, MAX_OUTPUT_LEVEL);
@@ -901,10 +924,10 @@ static int harmony_mixer_get_level(int channel)
 			right_level= to_oss_level(right_level, MAX_INPUT_LEVEL);
 			return (right_level << 8)+left_level;
 			
-		case SOUND_MIXER_VOLUME:
+		case SOUND_MIXER_MONITOR:
 			left_level = (harmony.current_gain & GAIN_MA_MASK) >> GAIN_MA_SHIFT;
-			left_level = to_oss_level(MAX_VOLUME_LEVEL-left_level, MAX_VOLUME_LEVEL);
-			return left_level;
+			left_level = to_oss_level(MAX_MONITOR_LEVEL-left_level, MAX_MONITOR_LEVEL);
+			return (left_level << 8)+left_level;
 	}
 	return -EINVAL;
 }
@@ -926,9 +949,11 @@ static int harmony_mixer_set_level(int channel, int value)
 
 	right_level = (value & 0x0000ff00) >> 8;
 	left_level = value & 0x000000ff;
+	if (right_level > 100) right_level = 100;
+	if (left_level > 100) left_level = 100;
   
 	switch (channel) {
-		case SOUND_MIXER_OGAIN:
+		case SOUND_MIXER_VOLUME:
 			right_level = to_harmony_level(100-right_level, MAX_OUTPUT_LEVEL);
 			left_level  = to_harmony_level(100-left_level, MAX_OUTPUT_LEVEL);
 			new_right_level = to_oss_level(MAX_OUTPUT_LEVEL - right_level, MAX_OUTPUT_LEVEL);
@@ -948,12 +973,12 @@ static int harmony_mixer_set_level(int channel, int value)
 			harmony_mixer_set_gain();
 			return (new_right_level << 8) + new_left_level;
 	
-		case SOUND_MIXER_VOLUME:
-			left_level = to_harmony_level(100-left_level, MAX_VOLUME_LEVEL);
-			new_left_level = to_oss_level(MAX_VOLUME_LEVEL-left_level, MAX_VOLUME_LEVEL);
-			harmony.current_gain = (harmony.current_gain & ~GAIN_MA_MASK)| (left_level << GAIN_MA_SHIFT);
+		case SOUND_MIXER_MONITOR:
+			left_level = to_harmony_level(100-left_level, MAX_MONITOR_LEVEL);
+			new_left_level = to_oss_level(MAX_MONITOR_LEVEL-left_level, MAX_MONITOR_LEVEL);
+			harmony.current_gain = (harmony.current_gain & ~GAIN_MA_MASK) | (left_level << GAIN_MA_SHIFT);
 			harmony_mixer_set_gain();
-			return new_left_level;
+			return (new_left_level << 8) + new_left_level;
 	}
 
 	return -EINVAL;
@@ -986,11 +1011,15 @@ static int harmony_mixer_set_recmask(int recmask)
 {
 	int new_input_line;
 	int new_input_mask;
-
-	if ((recmask & SOUND_MASK_LINE)) {
+	int current_input_line;
+	
+	current_input_line = (harmony.current_gain & GAIN_IS_MASK)
+				    >> GAIN_IS_SHIFT;
+	if ((current_input_line && ((recmask & SOUND_MASK_LINE) || !(recmask & SOUND_MASK_MIC))) ||
+		(!current_input_line && ((recmask & SOUND_MASK_LINE) && !(recmask & SOUND_MASK_MIC)))) {
 		new_input_line = 0;
 		new_input_mask = SOUND_MASK_LINE;
-	} else  {
+	} else {
 		new_input_line = 1;
 		new_input_mask = SOUND_MASK_MIC;
 	}
@@ -1009,9 +1038,9 @@ static int harmony_mixer_get_outmask(void)
 {
 	int outmask = 0;
 	
-	if (harmony.current_gain & GAIN_HE_MASK) outmask |=SOUND_MASK_PHONEOUT;
-	if (harmony.current_gain & GAIN_LE_MASK) outmask |=SOUND_MASK_LINE;
-	if (harmony.current_gain & GAIN_SE_MASK) outmask |=SOUND_MASK_SPEAKER;
+	if (harmony.current_gain & GAIN_SE_MASK) outmask |= MASK_INTERNAL;
+	if (harmony.current_gain & GAIN_LE_MASK) outmask |= MASK_LINEOUT;
+	if (harmony.current_gain & GAIN_HE_MASK) outmask |= MASK_HEADPHONES;
 	
 	return outmask;
 }
@@ -1019,24 +1048,24 @@ static int harmony_mixer_get_outmask(void)
 
 static int harmony_mixer_set_outmask(int outmask)
 {
-	if (outmask & SOUND_MASK_PHONEOUT) 
-		harmony.current_gain |= GAIN_HE_MASK; 
+	if (outmask & MASK_INTERNAL) 
+		harmony.current_gain |= GAIN_SE_MASK;
 	else 
-		harmony.current_gain &= ~GAIN_HE_MASK;
+		harmony.current_gain &= ~GAIN_SE_MASK;
 	
-	if (outmask & SOUND_MASK_LINE) 
+	if (outmask & MASK_LINEOUT) 
 		harmony.current_gain |= GAIN_LE_MASK;
 	else 
 		harmony.current_gain &= ~GAIN_LE_MASK;
 	
-	if (outmask & SOUND_MASK_SPEAKER) 
-		harmony.current_gain |= GAIN_SE_MASK;
+	if (outmask & MASK_HEADPHONES) 
+		harmony.current_gain |= GAIN_HE_MASK; 
 	else 
-		harmony.current_gain &= ~GAIN_SE_MASK;
+		harmony.current_gain &= ~GAIN_HE_MASK;
 	
 	harmony_mixer_set_gain();
 
-	return (outmask & (SOUND_MASK_PHONEOUT | SOUND_MASK_LINE | SOUND_MASK_SPEAKER));
+	return (outmask & (MASK_INTERNAL | MASK_LINEOUT | MASK_HEADPHONES));
 }
 
 /*
@@ -1074,19 +1103,19 @@ static int harmony_mixer_ioctl(struct inode * inode, struct file * file,
 		ret = SOUND_CAP_EXCL_INPUT;
 		break;
 	case MIXER_READ(SOUND_MIXER_STEREODEVS):
-		ret = SOUND_MASK_IGAIN | SOUND_MASK_OGAIN;
+		ret = SOUND_MASK_VOLUME | SOUND_MASK_IGAIN;
 		break;
 		
 	case MIXER_READ(SOUND_MIXER_RECMASK):
 		ret = SOUND_MASK_MIC | SOUND_MASK_LINE;
 		break;
 	case MIXER_READ(SOUND_MIXER_DEVMASK):
-		ret = SOUND_MASK_OGAIN | SOUND_MASK_IGAIN |
-			SOUND_MASK_VOLUME;
+		ret = SOUND_MASK_VOLUME | SOUND_MASK_IGAIN |
+			SOUND_MASK_MONITOR;
 		break;
 	case MIXER_READ(SOUND_MIXER_OUTMASK):
-		ret = SOUND_MASK_SPEAKER | SOUND_MASK_LINE |
-			SOUND_MASK_PHONEOUT;
+		ret = MASK_INTERNAL | MASK_LINEOUT |
+			MASK_HEADPHONES;
 		break;
 		
 	case MIXER_WRITE(SOUND_MIXER_RECSRC):
@@ -1103,15 +1132,15 @@ static int harmony_mixer_ioctl(struct inode * inode, struct file * file,
 		ret = harmony_mixer_get_outmask();
 		break;
 	
-	case MIXER_WRITE(SOUND_MIXER_OGAIN):
-	case MIXER_WRITE(SOUND_MIXER_IGAIN):
 	case MIXER_WRITE(SOUND_MIXER_VOLUME):
+	case MIXER_WRITE(SOUND_MIXER_IGAIN):
+	case MIXER_WRITE(SOUND_MIXER_MONITOR):
 		ret = harmony_mixer_set_level(cmd & 0xff, val);
 		break;
 
-	case MIXER_READ(SOUND_MIXER_OGAIN):
-	case MIXER_READ(SOUND_MIXER_IGAIN):
 	case MIXER_READ(SOUND_MIXER_VOLUME):
+	case MIXER_READ(SOUND_MIXER_IGAIN):
+	case MIXER_READ(SOUND_MIXER_MONITOR):
 		ret = harmony_mixer_get_level(cmd & 0xff);
 		break;
 
@@ -1201,16 +1230,15 @@ harmony_driver_probe(struct parisc_device *dev)
 		return -EBUSY;
 	}
 
-	harmony.dev = dev;
-
-	/* Set the HPA of harmony */
-	harmony.hpa = (struct harmony_hpa *)dev->hpa;
-
-	if (!harmony.dev->irq) {
+	if (!dev->irq) {
 		printk(KERN_ERR PFX "no irq found\n");
 		return -ENODEV;
 	}
 
+	/* Set the HPA of harmony */
+	harmony.hpa = (struct harmony_hpa *)dev->hpa;
+	harmony.dev = dev;
+
 	/* Grab the ID and revision from the device */
 	id = gsc_readb(&harmony.hpa->id);
 	if ((id | 1) != 0x15) {
@@ -1293,7 +1321,7 @@ static void __exit cleanup_harmony(void)
 }
 
 
-MODULE_AUTHOR("Alex DeVries <alex@linuxcare.com>");
+MODULE_AUTHOR("Alex DeVries <alex@onefishtwo.ca>");
 MODULE_DESCRIPTION("Harmony sound driver");
 MODULE_LICENSE("GPL");
 
diff --git a/sound/oss/i810_audio.c b/sound/oss/i810_audio.c
index 918c2a23b..47e5bed02 100644
--- a/sound/oss/i810_audio.c
+++ b/sound/oss/i810_audio.c
@@ -101,7 +101,6 @@
 #include <linux/ac97_codec.h>
 #include <linux/bitops.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 
 #define DRIVER_VERSION "1.01"
 
@@ -3216,8 +3215,14 @@ static int __devinit i810_probe(struct pci_dev *pci_dev, const struct pci_device
 	}
 
 	/* claim our iospace and irq */
-	request_region(card->iobase, 64, card_names[pci_id->driver_data]);
-	request_region(card->ac97base, 256, card_names[pci_id->driver_data]);
+	if (!request_region(card->iobase, 64, card_names[pci_id->driver_data])) {
+		printk(KERN_ERR "i810_audio: unable to allocate region %lx\n", card->iobase);
+		goto out_region1;
+	}
+	if (!request_region(card->ac97base, 256, card_names[pci_id->driver_data])) {
+		printk(KERN_ERR "i810_audio: unable to allocate region %lx\n", card->ac97base);
+		goto out_region2;
+	}
 
 	if (request_irq(card->irq, &i810_interrupt, SA_SHIRQ,
 			card_names[pci_id->driver_data], card)) {
@@ -3291,7 +3296,9 @@ out_iospace:
 	}
 out_pio:	
 	release_region(card->iobase, 64);
+out_region2:
 	release_region(card->ac97base, 256);
+out_region1:
 	pci_free_consistent(pci_dev, sizeof(struct i810_channel)*NR_HW_CH,
 	    card->channel, card->chandma);
 out_mem:
diff --git a/sound/oss/ite8172.c b/sound/oss/ite8172.c
index 16e7d01ef..f98413314 100644
--- a/sound/oss/ite8172.c
+++ b/sound/oss/ite8172.c
@@ -70,10 +70,10 @@
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
 #include <linux/ac97_codec.h>
+#include <linux/interrupt.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 #include <asm/it8172/it8172.h>
 
 /* --------------------------------------------------------------------- */
diff --git a/sound/oss/kahlua.c b/sound/oss/kahlua.c
index 0913d4969..3d1d63680 100644
--- a/sound/oss/kahlua.c
+++ b/sound/oss/kahlua.c
@@ -156,10 +156,14 @@ static int __devinit probe_one(struct pci_dev *pdev, const struct pci_device_id
 	hw_config->dma2 = dma16;
 	hw_config->name = "Cyrix XpressAudio";
 	hw_config->driver_use_1 = SB_NO_MIDI | SB_PCI_IRQ;
+
+	if (!request_region(io, 16, "soundblaster"))
+		goto err_out_free;
 	
 	if(sb_dsp_detect(hw_config, 0, 0, NULL)==0)
 	{
 		printk(KERN_ERR "kahlua: audio not responding.\n");
+		release_region(io, 16);
 		goto err_out_free;
 	}
 
diff --git a/sound/oss/mad16.c b/sound/oss/mad16.c
index b7ef7def6..4c5db81ed 100644
--- a/sound/oss/mad16.c
+++ b/sound/oss/mad16.c
@@ -54,7 +54,6 @@ static int      mad16_conf;
 static int      mad16_cdsel;
 static struct gameport gameport;
 static spinlock_t lock=SPIN_LOCK_UNLOCKED;
-static int      already_initialized;
 
 #define C928	1
 #define MOZART	2
@@ -313,19 +312,6 @@ static int __init detect_mad16(void)
 
 static int __init wss_init(struct address_info *hw_config)
 {
-	int ad_flags = 0;
-
-	/*
-	 *    Verify the WSS parameters
-	 */
-
-	if (check_region(hw_config->io_base, 8))
-	{
-		printk(KERN_ERR "MSS: I/O port conflict\n");
-		return 0;
-	}
-	if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp))
-		return 0;
 	/*
 	 * Check if the IO port returns valid signature. The original MS Sound
 	 * system returns 0x04 while some cards (AudioTrix Pro for example)
@@ -338,31 +324,20 @@ static int __init wss_init(struct address_info *hw_config)
 		DDB(printk("No MSS signature detected on port 0x%x (0x%x)\n", hw_config->io_base, inb(hw_config->io_base + 3)));
 		return 0;
 	}
-	if (hw_config->irq > 11)
-	{
-		printk(KERN_ERR "MSS: Bad IRQ %d\n", hw_config->irq);
-		return 0;
-	}
-	if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)
-	{
-		printk(KERN_ERR "MSS: Bad DMA %d\n", hw_config->dma);
-		return 0;
-	}
 	/*
 	 * Check that DMA0 is not in use with a 8 bit board.
 	 */
-
 	if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80)
 	{
 		printk("MSS: Can't use DMA0 with a 8 bit card/slot\n");
 		return 0;
 	}
-	if (hw_config->irq > 7 && hw_config->irq != 9 && inb(hw_config->io_base + 3) & 0x80)
+	if (hw_config->irq > 9 && inb(hw_config->io_base + 3) & 0x80)
 		printk(KERN_ERR "MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq);
 	return 1;
 }
 
-static int __init init_c930(struct address_info *hw_config)
+static void __init init_c930(struct address_info *hw_config, int base)
 {
 	unsigned char cfg = 0;
 
@@ -376,25 +351,7 @@ static int __init init_c930(struct address_info *hw_config)
 		   somewhere else. */
 		cfg =  (cfg & 0x09) ^ 0x07;
 	}
-
-	switch (hw_config->io_base)
-	{
-		case 0x530:
-			cfg |= 0x00;
-			break;
-		case 0xe80:
-			cfg |= 0x10;
-			break;
-		case 0xf40:
-			cfg |= 0x20;
-			break;
-		case 0x604:
-			cfg |= 0x30;
-			break;
-		default:
-			printk(KERN_ERR "MAD16: Invalid codec port %x\n", hw_config->io_base);
-			return 0;
-	}
+	cfg |= base << 4;
 	mad_write(MC1_PORT, cfg);
 
 	/* MC2 is CD configuration. Don't touch it. */
@@ -414,8 +371,6 @@ static int __init init_c930(struct address_info *hw_config)
 	mad_write(MC6_PORT, 0x02);	/* Enable WSS, Disable MPU and SB */
 	mad_write(MC7_PORT, 0xCB);
 	mad_write(MC10_PORT, 0x11);
-
-	return wss_init(hw_config);
 }
 
 static int __init chip_detect(void)
@@ -508,20 +463,48 @@ static int __init chip_detect(void)
 static int __init probe_mad16(struct address_info *hw_config)
 {
 	int i;
-	static int valid_ports[] = 
-	{
-		0x530, 0xe80, 0xf40, 0x604
-	};
 	unsigned char tmp;
 	unsigned char cs4231_mode = 0;
 
 	int ad_flags = 0;
 
-	if (already_initialized)
-		return 0;
+	signed char bits;
+
+	static char     dma_bits[4] = {
+		1, 2, 0, 3
+	};
+
+	int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3;
+	int dma = hw_config->dma, dma2 = hw_config->dma2;
+	unsigned char dma2_bit = 0;
+	int base;
+	struct resource *ports;
 
 	mad16_osp = hw_config->osp;
 
+	switch (hw_config->io_base) {
+	case 0x530:
+		base = 0;
+		break;
+	case 0xe80:
+		base = 1;
+		break;
+	case 0xf40:
+		base = 2;
+		break;
+	case 0x604:
+		base = 3;
+		break;
+	default:
+		printk(KERN_ERR "MAD16/Mozart: Bad WSS base address 0x%x\n", hw_config->io_base);
+		return 0;
+	}
+
+	if (dma != 0 && dma != 1 && dma != 3) {
+		printk(KERN_ERR "MSS: Bad DMA %d\n", dma);
+		return 0;
+	}
+
 	/*
 	 *    Check that all ports return 0xff (bus float) when no password
 	 *      is written to the password register.
@@ -531,9 +514,44 @@ static int __init probe_mad16(struct address_info *hw_config)
 	if (!chip_detect())
 		return 0;
 
-	if (board_type == C930)
-		return init_c930(hw_config);
+	switch (hw_config->irq) {
+	case 7:
+		bits = 8;
+		break;
+	case 9:
+		bits = 0x10;
+		break;
+	case 10:
+		bits = 0x18;
+		break;
+	case 12:
+		bits = 0x20;
+		break;
+	case 5:	/* Also IRQ5 is possible on C930 */
+		if (board_type == C930 || c924pnp) {
+			bits = 0x28;
+			break;
+		}
+	default:
+		printk(KERN_ERR "MAD16/Mozart: Bad IRQ %d\n", hw_config->irq);
+		return 0;
+	}
+
+	ports = request_region(hw_config->io_base + 4, 4, "ad1848");
+	if (!ports) {
+		printk(KERN_ERR "MSS: I/O port conflict\n");
+		return 0;
+	}
+	if (!request_region(hw_config->io_base, 4, "mad16 WSS config")) {
+		release_region(hw_config->io_base + 4, 4);
+		printk(KERN_ERR "MSS: I/O port conflict\n");
+		return 0;
+	}
 
+	if (board_type == C930) {
+		init_c930(hw_config, base);
+		goto got_it;
+	}
 
 	for (i = 0xf8d; i <= 0xf93; i++) {
 		if (!c924pnp)
@@ -547,20 +565,7 @@ static int __init probe_mad16(struct address_info *hw_config)
  */
 
 	tmp = (mad_read(MC1_PORT) & 0x0f) | 0x80;	/* Enable WSS, Disable SB */
-
-	for (i = 0; i < 5; i++)
-	{
-		if (i > 3)	/* Not a valid port */
-		{
-			printk(KERN_ERR "MAD16/Mozart: Bad WSS base address 0x%x\n", hw_config->io_base);
-			return 0;
-		}
-		if (valid_ports[i] == hw_config->io_base)
-		{
-			tmp |= i << 4;	/* WSS port select bits */
-			break;
-		}
-	}
+	tmp |= base << 4;	/* WSS port select bits */
 
 	/*
 	 * Set optional CD-ROM and joystick settings.
@@ -580,8 +585,8 @@ static int __init probe_mad16(struct address_info *hw_config)
 		mad_write(MC5_PORT, 0x05);
 		mad_write(MC6_PORT, 0x03);
 	}
-	if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp))
-		return 0;
+	if (!ad1848_detect(ports, &ad_flags, mad16_osp))
+		goto fail;
 
 	if (ad_flags & (AD_F_CS4231 | AD_F_CS4248))
 		cs4231_mode = 0x02;	/* CS4248/CS4231 sync delay switch */
@@ -604,43 +609,19 @@ static int __init probe_mad16(struct address_info *hw_config)
 		else
 			DDB(printk("port %03x after init = %02x\n", i-0x80, mad_read(i)));
 	}
-	wss_init(hw_config);
 
-	return 1;
-}
+got_it:
+	ad_flags = 0;
+	if (!ad1848_detect(ports, &ad_flags, mad16_osp))
+		goto fail;
 
-static void __init attach_mad16(struct address_info *hw_config)
-{
-
-	static signed char     interrupt_bits[12] = {
-		-1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20
-	};
-	signed char bits;
-
-	static char     dma_bits[4] = {
-		1, 2, 0, 3
-	};
-
-	int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3;
-	int ad_flags = 0, dma = hw_config->dma, dma2 = hw_config->dma2;
-	unsigned char dma2_bit = 0;
-
-	already_initialized = 1;
-
-	if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp))
-		return;
+	if (!wss_init(hw_config))
+		goto fail;
 
 	/*
 	 * Set the IRQ and DMA addresses.
 	 */
 	
-	if (board_type == C930 || c924pnp)
-		interrupt_bits[5] = 0x28;	/* Also IRQ5 is possible on C930 */
-
-	bits = interrupt_bits[hw_config->irq];
-	if (bits == -1)
-		return;
-
 	outb((bits | 0x40), config_port);
 	if ((inb(version_port) & 0x40) == 0)
 		printk(KERN_ERR "[IRQ Conflict?]\n");
@@ -675,27 +656,24 @@ static void __init attach_mad16(struct address_info *hw_config)
 
 	outb((bits | dma_bits[dma] | dma2_bit), config_port);	/* Write IRQ+DMA setup */
 
-	hw_config->slots[0] = ad1848_init("mad16 WSS", hw_config->io_base + 4,
+	hw_config->slots[0] = ad1848_init("mad16 WSS", ports,
 					  hw_config->irq,
 					  dma,
 					  dma2, 0,
 					  hw_config->osp,
 					  THIS_MODULE);
-	request_region(hw_config->io_base, 4, "mad16 WSS config");
+	return 1;
+
+fail:
+	release_region(hw_config->io_base + 4, 4);
+	release_region(hw_config->io_base, 4);
+	return 0;
 }
 
 static int __init probe_mad16_mpu(struct address_info *hw_config)
 {
-	static int mpu_attached;
 	unsigned char tmp;
 
-	if (!already_initialized)	/* The MSS port must be initialized first */
-		return 0;
-
-	if (mpu_attached)		/* Don't let them call this twice */
-		return 0;
-	mpu_attached = 1;
-
 	if (board_type < C929)	/* Early chip. No MPU support. Just SB MIDI */
 	{
 
@@ -732,8 +710,12 @@ static int __init probe_mad16_mpu(struct address_info *hw_config)
 
 		mad_write(MC3_PORT, tmp | 0x04);
 		hw_config->driver_use_1 = SB_MIDI_ONLY;
-		if (!sb_dsp_detect(hw_config, 0, 0, NULL))
+		if (!request_region(hw_config->io_base, 16, "soundblaster"))
+			return 0;
+		if (!sb_dsp_detect(hw_config, 0, 0, NULL)) {
+			release_region(hw_config->io_base, 16);
 			return 0;
+		}
 
 		if (mad_read(MC1_PORT) & 0x20)
 			hw_config->io_base = 0x240;
@@ -1031,15 +1013,18 @@ static int __init init_mad16(void)
 		printk(KERN_ERR "I/O, DMA and irq are mandatory\n");
 		return -EINVAL;
 	}
-	
-	if (!probe_mad16(&cfg))
+
+	if (!request_region(MC0_PORT, 12, "mad16"))
+		return -EBUSY;
+
+	if (!probe_mad16(&cfg)) {
+		release_region(MC0_PORT, 12);
 		return -ENODEV;
+	}
 
 	cfg_mpu.io_base = mpu_io;
 	cfg_mpu.irq = mpu_irq;
 
-	attach_mad16(&cfg);
-
 	found_mpu = probe_mad16_mpu(&cfg_mpu);
 
 	if (joystick == 1) {
@@ -1067,6 +1052,7 @@ static void __exit cleanup_mad16(void)
 		release_region(0x201, 1);
 	}
 	unload_mad16(&cfg);
+	release_region(MC0_PORT, 12);
 }
 
 module_init(init_mad16);
diff --git a/sound/oss/maui.c b/sound/oss/maui.c
index 1de0fb55b..0c0d53e87 100644
--- a/sound/oss/maui.c
+++ b/sound/oss/maui.c
@@ -301,17 +301,23 @@ static int maui_load_patch(int dev, int format, const char __user *addr,
 
 static int __init probe_maui(struct address_info *hw_config)
 {
+	struct resource *ports;
+	int this_dev;
 	int i;
 	int tmp1, tmp2, ret;
 
-	if (check_region(hw_config->io_base, 8))
+	ports = request_region(hw_config->io_base, 2, "mpu401");
+	if (!ports)
 		return 0;
 
+	if (!request_region(hw_config->io_base + 2, 6, "Maui"))
+		goto out;
+
 	maui_base = hw_config->io_base;
 	maui_osp = hw_config->osp;
 
 	if (request_irq(hw_config->irq, mauiintr, 0, "Maui", NULL) < 0)
-		return 0;
+		goto out2;
 
 	/*
 	 * Initialize the processor if necessary
@@ -322,36 +328,30 @@ static int __init probe_maui(struct address_info *hw_config)
 			!maui_write(0x9F) ||	/* Report firmware version */
 			!maui_short_wait(STAT_RX_AVAIL) ||
 			maui_read() == -1 || maui_read() == -1)
-			if (!maui_init(hw_config->irq)) {
-				free_irq(hw_config->irq, NULL);
-				return 0;
-			}
+			if (!maui_init(hw_config->irq))
+				goto out3;
 	}
 	if (!maui_write(0xCF))	/* Report hardware version */ {
 		printk(KERN_ERR "No WaveFront firmware detected (card uninitialized?)\n");
-		free_irq(hw_config->irq, NULL);
-		return 0;
+		goto out3;
 	}
 	if ((tmp1 = maui_read()) == -1 || (tmp2 = maui_read()) == -1) {
 		printk(KERN_ERR "No WaveFront firmware detected (card uninitialized?)\n");
-		free_irq(hw_config->irq, NULL);
-		return 0;
-	}
-	if (tmp1 == 0xff || tmp2 == 0xff) {
-		free_irq(hw_config->irq, NULL);
-		return 0;
+		goto out3;
 	}
+	if (tmp1 == 0xff || tmp2 == 0xff)
+		goto out3;
 	printk(KERN_DEBUG "WaveFront hardware version %d.%d\n", tmp1, tmp2);
 
 	if (!maui_write(0x9F))	/* Report firmware version */
-		return 0;
+		goto out3;
 	if ((tmp1 = maui_read()) == -1 || (tmp2 = maui_read()) == -1)
-		return 0;
+		goto out3;
 
 	printk(KERN_DEBUG "WaveFront firmware version %d.%d\n", tmp1, tmp2);
 
 	if (!maui_write(0x85))	/* Report free DRAM */
-		return 0;
+		goto out3;
 	tmp1 = 0;
 	for (i = 0; i < 4; i++) {
 		tmp1 |= maui_read() << (7 * i);
@@ -359,20 +359,12 @@ static int __init probe_maui(struct address_info *hw_config)
 	printk(KERN_DEBUG "Available DRAM %dk\n", tmp1 / 1024);
 
 	for (i = 0; i < 1000; i++)
-		if (probe_mpu401(hw_config))
+		if (probe_mpu401(hw_config, ports))
 			break;
 
-	ret = probe_mpu401(hw_config);
-
-	if (ret)
-		request_region(hw_config->io_base + 2, 6, "Maui");
-
-	return ret;
-}
-
-static void __init attach_maui(struct address_info *hw_config)
-{
-	int this_dev;
+	ret = probe_mpu401(hw_config, ports);
+	if (!ret)
+		goto out3;
 
 	conf_printf("Maui", hw_config);
 
@@ -391,14 +383,22 @@ static void __init attach_maui(struct address_info *hw_config)
 		 */
 
 		synth = midi_devs[this_dev]->converter;
-		synth->id = "MAUI";
-
 		if (synth != NULL) {
+			synth->id = "MAUI";
 			orig_load_patch = synth->load_patch;
 			synth->load_patch = &maui_load_patch;
 		} else
 			printk(KERN_ERR "Maui: Can't install patch loader\n");
 	}
+	return 1;
+
+out3:
+	free_irq(hw_config->irq, NULL);
+out2:
+	release_region(hw_config->io_base + 2, 6);
+out:
+	release_region(hw_config->io_base, 2);
+	return 0;
 }
 
 static void __exit unload_maui(struct address_info *hw_config)
@@ -445,7 +445,6 @@ static int __init init_maui(void)
 	}
 	if (probe_maui(&cfg) == 0)
 		return -ENODEV;
-	attach_maui(&cfg);
 
 	return 0;
 }
diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c
index 341983bff..73c3ce32a 100644
--- a/sound/oss/mpu401.c
+++ b/sound/oss/mpu401.c
@@ -1026,12 +1026,6 @@ int attach_mpu401(struct address_info *hw_config, struct module *owner)
 			spin_unlock_irqrestore(&devc->lock,flags);
 	}
 
-	if (!request_region(hw_config->io_base, 2, "mpu401"))
-	{
-		ret = -ENOMEM;
-		goto out_irq;
-	}	
-
 	if (devc->version != 0)
 		if (mpu_cmd(m, 0xC5, 0) >= 0)	/* Set timebase OK */
 			if (mpu_cmd(m, 0xE0, 120) >= 0)		/* Set tempo OK */
@@ -1044,7 +1038,7 @@ int attach_mpu401(struct address_info *hw_config, struct module *owner)
 	{
 		printk(KERN_ERR "mpu401: Can't allocate memory\n");
 		ret = -ENOMEM;
-		goto out_resource;
+		goto out_irq;
 	}
 	if (!(devc->capabilities & MPU_CAP_INTLG))	/* No intelligent mode */
 	{
@@ -1126,13 +1120,12 @@ int attach_mpu401(struct address_info *hw_config, struct module *owner)
 	
 	return 0;
 
-out_resource:
-	release_region(hw_config->io_base, 2);
 out_irq:
 	free_irq(devc->irq, (void *)m);
 out_mididev:
 	sound_unload_mididev(m);
 out_err:
+	release_region(hw_config->io_base, 2);
 	return ret;
 }
 
@@ -1207,16 +1200,11 @@ static void set_uart_mode(int dev, struct mpu_config *devc, int arg)
 
 }
 
-int probe_mpu401(struct address_info *hw_config)
+int probe_mpu401(struct address_info *hw_config, struct resource *ports)
 {
 	int ok = 0;
 	struct mpu_config tmp_devc;
 
-	if (check_region(hw_config->io_base, 2))
-	{
-		printk(KERN_ERR "mpu401: I/O port %x already in use\n\n", hw_config->io_base);
-		return 0;
-	}
 	tmp_devc.base = hw_config->io_base;
 	tmp_devc.irq = hw_config->irq;
 	tmp_devc.initialized = 0;
@@ -1791,10 +1779,16 @@ static int __init init_mpu401(void)
 	/* Can be loaded either for module use or to provide functions
 	   to others */
 	if (io != -1 && irq != -1) {
+		struct resource *ports;
 	        cfg.irq = irq;
 		cfg.io_base = io;
-		if (probe_mpu401(&cfg) == 0)
+		ports = request_region(io, 2, "mpu401");
+		if (!ports)
+			return -EBUSY;
+		if (probe_mpu401(&cfg, ports) == 0) {
+			release_region(io, 2);
 			return -ENODEV;
+		}
 		if ((ret = attach_mpu401(&cfg, THIS_MODULE)))
 			return ret;
 	}
diff --git a/sound/oss/mpu401.h b/sound/oss/mpu401.h
index 43ff5430c..bdc5bde64 100644
--- a/sound/oss/mpu401.h
+++ b/sound/oss/mpu401.h
@@ -6,7 +6,7 @@ void unload_uart401 (struct address_info *hw_config);
 irqreturn_t uart401intr (int irq, void *dev_id, struct pt_regs * dummy);
 
 /*	From mpu401.c */
-int probe_mpu401(struct address_info *hw_config);
+int probe_mpu401(struct address_info *hw_config, struct resource *ports);
 int attach_mpu401(struct address_info * hw_config, struct module *owner);
 void unload_mpu401(struct address_info *hw_info);
 
diff --git a/sound/oss/msnd.c b/sound/oss/msnd.c
index 6ccdd096f..047f2b41a 100644
--- a/sound/oss/msnd.c
+++ b/sound/oss/msnd.c
@@ -207,7 +207,7 @@ int msnd_wait_TXDE(multisound_dev_t *dev)
 	register int timeout = 1000;
     
 	while(timeout-- > 0)
-		if (inb(io + HP_ISR) & HPISR_TXDE)
+		if (msnd_inb(io + HP_ISR) & HPISR_TXDE)
 			return 0;
 
 	return -EIO;
@@ -219,7 +219,7 @@ int msnd_wait_HC0(multisound_dev_t *dev)
 	register int timeout = 1000;
 
 	while(timeout-- > 0)
-		if (!(inb(io + HP_CVR) & HPCVR_HC))
+		if (!(msnd_inb(io + HP_CVR) & HPCVR_HC))
 			return 0;
 
 	return -EIO;
@@ -231,7 +231,7 @@ int msnd_send_dsp_cmd(multisound_dev_t *dev, BYTE cmd)
 
 	spin_lock_irqsave(&dev->lock, flags);
 	if (msnd_wait_HC0(dev) == 0) {
-		outb(cmd, dev->io + HP_CVR);
+		msnd_outb(cmd, dev->io + HP_CVR);
 		spin_unlock_irqrestore(&dev->lock, flags);
 		return 0;
 	}
@@ -248,9 +248,9 @@ int msnd_send_word(multisound_dev_t *dev, unsigned char high,
 	register unsigned int io = dev->io;
 
 	if (msnd_wait_TXDE(dev) == 0) {
-		outb(high, io + HP_TXH);
-		outb(mid, io + HP_TXM);
-		outb(low, io + HP_TXL);
+		msnd_outb(high, io + HP_TXH);
+		msnd_outb(mid, io + HP_TXM);
+		msnd_outb(low, io + HP_TXL);
 		return 0;
 	}
 
@@ -272,8 +272,8 @@ int msnd_upload_host(multisound_dev_t *dev, char *bin, int len)
 		if (msnd_send_word(dev, bin[i], bin[i + 1], bin[i + 2]) != 0)
 			return -EIO;
 
-	inb(dev->io + HP_RXL);
-	inb(dev->io + HP_CVR);
+	msnd_inb(dev->io + HP_RXL);
+	msnd_inb(dev->io + HP_CVR);
 
 	return 0;
 }
@@ -289,11 +289,11 @@ int msnd_enable_irq(multisound_dev_t *dev)
 
 	spin_lock_irqsave(&dev->lock, flags);
 	if (msnd_wait_TXDE(dev) == 0) {
-		outb(inb(dev->io + HP_ICR) | HPICR_TREQ, dev->io + HP_ICR);
+		msnd_outb(msnd_inb(dev->io + HP_ICR) | HPICR_TREQ, dev->io + HP_ICR);
 		if (dev->type == msndClassic)
-			outb(dev->irqid, dev->io + HP_IRQM);
-		outb(inb(dev->io + HP_ICR) & ~HPICR_TREQ, dev->io + HP_ICR);
-		outb(inb(dev->io + HP_ICR) | HPICR_RREQ, dev->io + HP_ICR);
+			msnd_outb(dev->irqid, dev->io + HP_IRQM);
+		msnd_outb(msnd_inb(dev->io + HP_ICR) & ~HPICR_TREQ, dev->io + HP_ICR);
+		msnd_outb(msnd_inb(dev->io + HP_ICR) | HPICR_RREQ, dev->io + HP_ICR);
 		enable_irq(dev->irq);
 		msnd_init_queue(dev->DSPQ, dev->dspq_data_buff, dev->dspq_buff_size);
 		spin_unlock_irqrestore(&dev->lock, flags);
@@ -320,9 +320,9 @@ int msnd_disable_irq(multisound_dev_t *dev)
 
 	spin_lock_irqsave(&dev->lock, flags);
 	if (msnd_wait_TXDE(dev) == 0) {
-		outb(inb(dev->io + HP_ICR) & ~HPICR_RREQ, dev->io + HP_ICR);
+		msnd_outb(msnd_inb(dev->io + HP_ICR) & ~HPICR_RREQ, dev->io + HP_ICR);
 		if (dev->type == msndClassic)
-			outb(HPIRQ_NONE, dev->io + HP_IRQM);
+			msnd_outb(HPIRQ_NONE, dev->io + HP_IRQM);
 		disable_irq(dev->irq);
 		spin_unlock_irqrestore(&dev->lock, flags);
 		return 0;
diff --git a/sound/oss/msnd.h b/sound/oss/msnd.h
index 73148d2ee..35894807e 100644
--- a/sound/oss/msnd.h
+++ b/sound/oss/msnd.h
@@ -154,10 +154,11 @@
 #define DSPTOPC_BASED(w)	(((w) - DSP_BASE_ADDR) * 2)
 
 #ifdef SLOWIO
-#  undef outb
-#  undef inb
-#  define outb			outb_p
-#  define inb			inb_p
+#define msnd_outb			outb_p
+#define msnd_inb			inb_p
+#else
+#define msnd_outb			outb
+#define msnd_inb			inb
 #endif
 
 /* JobQueueStruct */
diff --git a/sound/oss/msnd_pinnacle.c b/sound/oss/msnd_pinnacle.c
index eb345b603..7ebc5d33b 100644
--- a/sound/oss/msnd_pinnacle.c
+++ b/sound/oss/msnd_pinnacle.c
@@ -136,9 +136,9 @@ static void reset_record_queue(void)
 
 	/* Critical section: bank 1 access */
 	spin_lock_irqsave(&dev.lock, flags);
-	outb(HPBLKSEL_1, dev.io + HP_BLKS);
+	msnd_outb(HPBLKSEL_1, dev.io + HP_BLKS);
 	isa_memset_io(dev.base, 0, DAR_BUFF_SIZE * 3);
-	outb(HPBLKSEL_0, dev.io + HP_BLKS);
+	msnd_outb(HPBLKSEL_0, dev.io + HP_BLKS);
 	spin_unlock_irqrestore(&dev.lock, flags);
 
 	for (n = 0, lpDAQ = dev.base + DARQ_DATA_BUFF; n < 3; ++n, lpDAQ += DAQDS__size) {
@@ -830,12 +830,12 @@ static __inline__ int pack_DARQ_to_DARF(register int bank)
 
 	/* Read data from the head (unprotected bank 1 access okay
            since this is only called inside an interrupt) */
-	outb(HPBLKSEL_1, dev.io + HP_BLKS);
+	msnd_outb(HPBLKSEL_1, dev.io + HP_BLKS);
 	msnd_fifo_write(
 		&dev.DARF,
 		(char *)(dev.base + bank * DAR_BUFF_SIZE),
 		size);
-	outb(HPBLKSEL_0, dev.io + HP_BLKS);
+	msnd_outb(HPBLKSEL_0, dev.io + HP_BLKS);
 
 	return 1;
 }
@@ -1091,7 +1091,7 @@ static __inline__ void eval_dsp_msg(register WORD wMessage)
 static irqreturn_t intr(int irq, void *dev_id, struct pt_regs *regs)
 {
 	/* Send ack to DSP */
-	inb(dev.io + HP_RXL);
+	msnd_inb(dev.io + HP_RXL);
 
 	/* Evaluate queued DSP messages */
 	while (isa_readw(dev.DSPQ + JQS_wTail) != isa_readw(dev.DSPQ + JQS_wHead)) {
@@ -1120,15 +1120,15 @@ static int reset_dsp(void)
 {
 	int timeout = 100;
 
-	outb(HPDSPRESET_ON, dev.io + HP_DSPR);
+	msnd_outb(HPDSPRESET_ON, dev.io + HP_DSPR);
 	mdelay(1);
 #ifndef MSND_CLASSIC
-	dev.info = inb(dev.io + HP_INFO);
+	dev.info = msnd_inb(dev.io + HP_INFO);
 #endif
-	outb(HPDSPRESET_OFF, dev.io + HP_DSPR);
+	msnd_outb(HPDSPRESET_OFF, dev.io + HP_DSPR);
 	mdelay(1);
 	while (timeout-- > 0) {
-		if (inb(dev.io + HP_CVR) == HP_CVR_DEF)
+		if (msnd_inb(dev.io + HP_CVR) == HP_CVR_DEF)
 			return 0;
 		mdelay(1);
 	}
@@ -1202,9 +1202,9 @@ static int init_sma(void)
 	unsigned long flags;
 
 #ifdef MSND_CLASSIC
-	outb(dev.memid, dev.io + HP_MEMM);
+	msnd_outb(dev.memid, dev.io + HP_MEMM);
 #endif
-	outb(HPBLKSEL_0, dev.io + HP_BLKS);
+	msnd_outb(HPBLKSEL_0, dev.io + HP_BLKS);
 	if (initted) {
 		mastVolLeft = isa_readw(dev.SMA + SMA_wCurrMastVolLeft);
 		mastVolRight = isa_readw(dev.SMA + SMA_wCurrMastVolRight);
@@ -1214,9 +1214,9 @@ static int init_sma(void)
 
 	/* Critical section: bank 1 access */
 	spin_lock_irqsave(&dev.lock, flags);
-	outb(HPBLKSEL_1, dev.io + HP_BLKS);
+	msnd_outb(HPBLKSEL_1, dev.io + HP_BLKS);
 	isa_memset_io(dev.base, 0, 0x8000);
-	outb(HPBLKSEL_0, dev.io + HP_BLKS);
+	msnd_outb(HPBLKSEL_0, dev.io + HP_BLKS);
 	spin_unlock_irqrestore(&dev.lock, flags);
 
 	dev.pwDSPQData = (dev.base + DSPQ_DATA_BUFF);
@@ -1289,7 +1289,7 @@ static int __init calibrate_adc(WORD srate)
 
 static int upload_dsp_code(void)
 {
-	outb(HPBLKSEL_0, dev.io + HP_BLKS);
+	msnd_outb(HPBLKSEL_0, dev.io + HP_BLKS);
 #ifndef HAVE_DSPCODEH
 	INITCODESIZE = mod_firmware_load(INITCODEFILE, &INITCODE);
 	if (!INITCODE) {
@@ -1326,9 +1326,9 @@ static int upload_dsp_code(void)
 #ifdef MSND_CLASSIC
 static void reset_proteus(void)
 {
-	outb(HPPRORESET_ON, dev.io + HP_PROR);
+	msnd_outb(HPPRORESET_ON, dev.io + HP_PROR);
 	mdelay(TIME_PRO_RESET);
-	outb(HPPRORESET_OFF, dev.io + HP_PROR);
+	msnd_outb(HPPRORESET_OFF, dev.io + HP_PROR);
 	mdelay(TIME_PRO_RESET_DONE);
 }
 #endif
@@ -1338,8 +1338,8 @@ static int initialize(void)
 	int err, timeout;
 
 #ifdef MSND_CLASSIC
-	outb(HPWAITSTATE_0, dev.io + HP_WAIT);
-	outb(HPBITMODE_16, dev.io + HP_BITM);
+	msnd_outb(HPWAITSTATE_0, dev.io + HP_WAIT);
+	msnd_outb(HPBITMODE_16, dev.io + HP_BITM);
 
 	reset_proteus();
 #endif
@@ -1455,9 +1455,9 @@ static void __exit unload_multisound(void)
 
 static int __init msnd_write_cfg(int cfg, int reg, int value)
 {
-	outb(reg, cfg);
-	outb(value, cfg + 1);
-	if (value != inb(cfg + 1)) {
+	msnd_outb(reg, cfg);
+	msnd_outb(value, cfg + 1);
+	if (value != msnd_inb(cfg + 1)) {
 		printk(KERN_ERR LOGNAME ": msnd_write_cfg: I/O error\n");
 		return -EIO;
 	}
diff --git a/sound/oss/nec_vrc5477.c b/sound/oss/nec_vrc5477.c
index b40611b42..0242f9021 100644
--- a/sound/oss/nec_vrc5477.c
+++ b/sound/oss/nec_vrc5477.c
@@ -82,7 +82,6 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 
 /* -------------------debug macros -------------------------------------- */
 /* #undef VRC5477_AC97_DEBUG */
diff --git a/sound/oss/opl3sa.c b/sound/oss/opl3sa.c
index 079e5fc5d..99f4ed66f 100644
--- a/sound/oss/opl3sa.c
+++ b/sound/oss/opl3sa.c
@@ -36,10 +36,7 @@
 static int sb_initialized;
 #endif
 
-static int kilroy_was_here;	/* Don't detect twice */
-static int mpu_initialized;
 static spinlock_t lock=SPIN_LOCK_UNLOCKED;
-static int *opl3sa_osp;
 
 static unsigned char opl3sa_read(int addr)
 {
@@ -106,26 +103,16 @@ static int __init opl3sa_detect(void)
  *     OPL3-SA
  */
 
-static int __init probe_opl3sa_wss(struct address_info *hw_config)
+static int __init probe_opl3sa_wss(struct address_info *hw_config, struct resource *ports)
 {
-	int ret;
 	unsigned char tmp = 0x24;	/* WSS enable */
 
-	if (check_region(0xf86, 2))	/* Control port is busy */
-		return 0;
 	/*
 	 * Check if the IO port returns valid signature. The original MS Sound
 	 * system returns 0x04 while some cards (OPL3-SA for example)
 	 * return 0x00.
 	 */
 
-	if (check_region(hw_config->io_base, 8))
-	{
-		printk(KERN_ERR "OPL3-SA: MSS I/O port conflict (%x)\n", hw_config->io_base);
-		return 0;
-	}
-	opl3sa_osp = hw_config->osp;
-
 	if (!opl3sa_detect())
 	{
 		printk(KERN_ERR "OSS: OPL3-SA chip not found\n");
@@ -152,21 +139,16 @@ static int __init probe_opl3sa_wss(struct address_info *hw_config)
 	}
 
 	opl3sa_write(0x01, tmp);	/* WSS setup register */
-	kilroy_was_here = 1;
 
-	ret = probe_ms_sound(hw_config);
-	if (ret)
-		request_region(0xf86, 2, "OPL3-SA");
-
-	return ret;
+	return probe_ms_sound(hw_config, ports);
 }
 
-static void __init attach_opl3sa_wss(struct address_info *hw_config)
+static void __init attach_opl3sa_wss(struct address_info *hw_config, struct resource *ports)
 {
 	int nm = num_mixers;
 
 	/* FIXME */
-	attach_ms_sound(hw_config, THIS_MODULE);
+	attach_ms_sound(hw_config, ports, THIS_MODULE);
 	if (num_mixers > nm)	/* A mixer was installed */
 	{
 		AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD);
@@ -183,14 +165,6 @@ static int __init probe_opl3sa_mpu(struct address_info *hw_config)
 		-1, -1, -1, -1, -1, 1, -1, 2, -1, 3, 4
 	};
 
-	if (!kilroy_was_here)
-		return 0;	/* OPL3-SA has not been detected earlier */
-
-	if (mpu_initialized)
-	{
-		DDB(printk("OPL3-SA: MPU mode already initialized\n"));
-		return 0;
-	}
 	if (hw_config->irq > 10)
 	{
 		printk(KERN_ERR "OPL3-SA: Bad MPU IRQ %d\n", hw_config->irq);
@@ -224,7 +198,6 @@ static int __init probe_opl3sa_mpu(struct address_info *hw_config)
 
 	opl3sa_write(0x03, conf);
 
-	mpu_initialized = 1;
 	hw_config->name = "OPL3-SA (MPU401)";
 
 	return probe_uart401(hw_config, THIS_MODULE);
@@ -281,6 +254,7 @@ MODULE_PARM(mpu_irq,"i");
 
 static int __init init_opl3sa(void)
 {
+	struct resource *ports;
 	if (io == -1 || irq == -1 || dma == -1) {
 		printk(KERN_ERR "opl3sa: dma, irq and io must be set.\n");
 		return -EINVAL;
@@ -294,12 +268,31 @@ static int __init init_opl3sa(void)
 	cfg_mpu.io_base = mpu_io;
 	cfg_mpu.irq = mpu_irq;
 
-	if (probe_opl3sa_wss(&cfg) == 0)
+	ports = request_region(io + 4, 4, "ad1848");
+	if (!ports)
+		return -EBUSY;
+
+	if (!request_region(0xf86, 2, "OPL3-SA"))/* Control port is busy */ {
+		release_region(io + 4, 4);
+		return 0;
+	}
+
+	if (!request_region(io, 4, "WSS config")) {
+		release_region(0x86, 2);
+		release_region(io + 4, 4);
+		return 0;
+	}
+
+	if (probe_opl3sa_wss(&cfg, ports) == 0) {
+		release_region(0xf86, 2);
+		release_region(io, 4);
+		release_region(io + 4, 4);
 		return -ENODEV;
+	}
 
 	found_mpu=probe_opl3sa_mpu(&cfg_mpu);
 
-	attach_opl3sa_wss(&cfg);
+	attach_opl3sa_wss(&cfg, ports);
 	return 0;
 }
 
diff --git a/sound/oss/opl3sa2.c b/sound/oss/opl3sa2.c
index 6daba626e..7d7a98173 100644
--- a/sound/oss/opl3sa2.c
+++ b/sound/oss/opl3sa2.c
@@ -539,36 +539,18 @@ static struct mixer_operations opl3sa3_mixer_operations =
  * Component probe, attach, unload functions
  */
 
-static inline int __init probe_opl3sa2_mpu(struct address_info* hw_config)
-{
-	return probe_mpu401(hw_config);
-}
-
-
-static inline int __init attach_opl3sa2_mpu(struct address_info* hw_config)
-{
-	return attach_mpu401(hw_config, THIS_MODULE);
-}
-
-
 static inline void __exit unload_opl3sa2_mpu(struct address_info *hw_config)
 {
 	unload_mpu401(hw_config);
 }
 
 
-static inline int __init probe_opl3sa2_mss(struct address_info* hw_config)
-{
-	return probe_ms_sound(hw_config);
-}
-
-
-static void __init attach_opl3sa2_mss(struct address_info* hw_config)
+static void __init attach_opl3sa2_mss(struct address_info* hw_config, struct resource *ports)
 {
 	int initial_mixers;
 
 	initial_mixers = num_mixers;
-	attach_ms_sound(hw_config, THIS_MODULE);	/* Slot 0 */
+	attach_ms_sound(hw_config, ports, THIS_MODULE);	/* Slot 0 */
 	if (hw_config->slots[0] != -1) {
 		/* Did the MSS driver install? */
 		if(num_mixers == (initial_mixers + 1)) {
@@ -957,6 +939,8 @@ static int __init init_opl3sa2(void)
 
 	for (card = 0; card < max; card++) {
 		/* If a user wants an I/O then assume they meant it */
+		struct resource *ports;
+		int base;
 		
 		if (!isapnp) {
 			if (io == -1 || irq == -1 || dma == -1 ||
@@ -995,17 +979,30 @@ static int __init init_opl3sa2(void)
 			opl3sa2_clear_slots(&opl3sa2_state[card].cfg_mpu);
 		}
 
+		/* FIXME: leak */
 		if (probe_opl3sa2(&opl3sa2_state[card].cfg, card))
 			return -ENODEV;
 
+		base = opl3sa2_state[card].cfg_mss.io_base;
 
-		if (!probe_opl3sa2_mss(&opl3sa2_state[card].cfg_mss)) {
+		if (!request_region(base, 4, "WSS config"))
+			goto failed;
+
+		ports = request_region(base + 4, 4, "ad1848");
+		if (!ports)
+			goto failed2;
+
+		if (!probe_ms_sound(&opl3sa2_state[card].cfg_mss, ports)) {
 			/*
 			 * If one or more cards are already registered, don't
 			 * return an error but print a warning.  Note, this
 			 * should never really happen unless the hardware or
 			 * ISA PnP screwed up.
 			 */
+			release_region(base + 4, 4);
+		failed2:
+			release_region(base, 4);
+		failed:
 			release_region(opl3sa2_state[card].cfg.io_base, 2);
 
 			if (opl3sa2_cards_num) {
@@ -1021,7 +1018,7 @@ static int __init init_opl3sa2(void)
 		attach_opl3sa2(&opl3sa2_state[card].cfg, card);
 		conf_printf(opl3sa2_state[card].chipset_name, &opl3sa2_state[card].cfg);
 		attach_opl3sa2_mixer(&opl3sa2_state[card].cfg, card);
-		attach_opl3sa2_mss(&opl3sa2_state[card].cfg_mss);
+		attach_opl3sa2_mss(&opl3sa2_state[card].cfg_mss, ports);
 
 		/* ewww =) */
 		opl3sa2_state[card].card = card;
@@ -1054,15 +1051,23 @@ static int __init init_opl3sa2(void)
 		
 		/* Attach MPU if we've been asked to do so, failure isn't fatal */
 		if (opl3sa2_state[card].cfg_mpu.io_base != -1) {
-			if (probe_opl3sa2_mpu(&opl3sa2_state[card].cfg_mpu)) {
-				if (attach_opl3sa2_mpu(&opl3sa2_state[card].cfg_mpu)) {
-					printk(KERN_ERR PFX "failed to attach MPU401\n");
-					opl3sa2_state[card].cfg_mpu.slots[1] = -1;
-				}
+			int base = opl3sa2_state[card].cfg_mpu.io_base;
+			struct resource *ports;
+			ports = request_region(base, 2, "mpu401");
+			if (!ports)
+				goto out;
+			if (!probe_mpu401(&opl3sa2_state[card].cfg_mpu, ports)) {
+				release_region(base, 2);
+				goto out;
+			}
+			if (attach_mpu401(&opl3sa2_state[card].cfg_mpu, THIS_MODULE)) {
+				printk(KERN_ERR PFX "failed to attach MPU401\n");
+				opl3sa2_state[card].cfg_mpu.slots[1] = -1;
 			}
 		}
 	}
 
+out:
 	if (isapnp) {
 		printk(KERN_NOTICE PFX "%d PnP card(s) found.\n", opl3sa2_cards_num);
 	}
diff --git a/sound/oss/pss.c b/sound/oss/pss.c
index 38019143b..af3f96ad0 100644
--- a/sound/oss/pss.c
+++ b/sound/oss/pss.c
@@ -149,6 +149,7 @@ static int      pss_initialized;
 static int      nonstandard_microcode;
 static int	pss_cdrom_port = -1;	/* Parameter for the PSS cdrom port */
 static int	pss_enable_joystick;    /* Parameter for enabling the joystick */
+static coproc_operations pss_coproc_operations;
 
 static void pss_write(pss_confdata *devc, int data)
 {
@@ -174,7 +175,7 @@ static void pss_write(pss_confdata *devc, int data)
  	printk(KERN_WARNING "PSS: DSP Command (%04x) Timeout.\n", data);
 }
 
-int __init probe_pss(struct address_info *hw_config)
+static int __init probe_pss(struct address_info *hw_config)
 {
 	unsigned short id;
 	int irq, dma;
@@ -188,13 +189,19 @@ int __init probe_pss(struct address_info *hw_config)
 		if (devc->base != 0x230 && devc->base != 0x250)		/* Some cards use these */
 			return 0;
 
-	if (check_region(devc->base, 0x19 /*16*/)) { 
+	if (!request_region(devc->base, 0x10, "PSS mixer, SB emulation")) {
 		printk(KERN_ERR "PSS: I/O port conflict\n");
 		return 0;
 	}
 	id = inw(REG(PSS_ID));
 	if ((id >> 8) != 'E') {
 		printk(KERN_ERR "No PSS signature detected at 0x%x (0x%x)\n",  devc->base,  id); 
+		release_region(devc->base, 0x10);
+		return 0;
+	}
+	if (!request_region(devc->base + 0x10, 0x9, "PSS config")) {
+		printk(KERN_ERR "PSS: I/O port conflict\n");
+		release_region(devc->base, 0x10);
 		return 0;
 	}
 	return 1;
@@ -685,7 +692,7 @@ void configure_nonsound_components(void)
 	}
 }
 
-void __init attach_pss(struct address_info *hw_config)
+static int __init attach_pss(struct address_info *hw_config)
 {
 	unsigned short  id;
 	char tmp[100];
@@ -697,10 +704,7 @@ void __init attach_pss(struct address_info *hw_config)
 	devc->ad_mixer_dev = NO_WSS_MIXER;
 
 	if (!probe_pss(hw_config))
-		return;
-
-	request_region(hw_config->io_base, 0x10, "PSS mixer, SB emulation");
-	request_region(hw_config->io_base + 0x10, 0x9, "PSS config");
+		return 0;
 
 	id = inw(REG(PSS_ID)) & 0x00ff;
 
@@ -714,17 +718,23 @@ void __init attach_pss(struct address_info *hw_config)
 	if (sound_alloc_dma(hw_config->dma, "PSS"))
 	{
 		printk("pss.c: Can't allocate DMA channel.\n");
-		return;
+		release_region(hw_config->io_base, 0x10);
+		release_region(hw_config->io_base+0x10, 0x9);
+		return 0;
 	}
 	if (!set_irq(devc, CONF_PSS, devc->irq))
 	{
 		printk("PSS: IRQ allocation error.\n");
-		return;
+		release_region(hw_config->io_base, 0x10);
+		release_region(hw_config->io_base+0x10, 0x9);
+		return 0;
 	}
 	if (!set_dma(devc, CONF_PSS, devc->dma))
 	{
 		printk(KERN_ERR "PSS: DMA allocation error\n");
-		return;
+		release_region(hw_config->io_base, 0x10);
+		release_region(hw_config->io_base+0x10, 0x9);
+		return 0;
 	}
 #endif
 
@@ -732,39 +742,38 @@ void __init attach_pss(struct address_info *hw_config)
 	pss_initialized = 1;
 	sprintf(tmp, "ECHO-PSS  Rev. %d", id);
 	conf_printf(tmp, hw_config);
+	return 1;
 }
 
-int __init probe_pss_mpu(struct address_info *hw_config)
+static int __init probe_pss_mpu(struct address_info *hw_config)
 {
+	struct resource *ports;
 	int timeout;
 
 	if (!pss_initialized)
 		return 0;
 
-	if (check_region(hw_config->io_base, 2))
-	{
+	ports = request_region(hw_config->io_base, 2, "mpu401");
+
+	if (!ports) {
 		printk(KERN_ERR "PSS: MPU I/O port conflict\n");
 		return 0;
 	}
-	if (!set_io_base(devc, CONF_MIDI, hw_config->io_base))
-	{
-		  printk(KERN_ERR "PSS: MIDI base could not be set.\n");
-		  return 0;
+	if (!set_io_base(devc, CONF_MIDI, hw_config->io_base)) {
+		printk(KERN_ERR "PSS: MIDI base could not be set.\n");
+		goto fail;
 	}
-	if (!set_irq(devc, CONF_MIDI, hw_config->irq))
-	{
-		  printk(KERN_ERR "PSS: MIDI IRQ allocation error.\n");
-		  return 0;
+	if (!set_irq(devc, CONF_MIDI, hw_config->irq)) {
+		printk(KERN_ERR "PSS: MIDI IRQ allocation error.\n");
+		goto fail;
 	}
-	if (!pss_synthLen)
-	{
+	if (!pss_synthLen) {
 		printk(KERN_ERR "PSS: Can't enable MPU. MIDI synth microcode not available.\n");
-		return 0;
+		goto fail;
 	}
-	if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST))
-	{
+	if (!pss_download_boot(devc, pss_synth, pss_synthLen, CPF_FIRST | CPF_LAST)) {
 		printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n");
-		return 0;
+		goto fail;
 	}
 
 	/*
@@ -780,7 +789,16 @@ int __init probe_pss_mpu(struct address_info *hw_config)
 			break;	/* No more input */
 	}
 
-	return probe_mpu401(hw_config);
+	if (!probe_mpu401(hw_config, ports))
+		goto fail;
+
+	attach_mpu401(hw_config, THIS_MODULE);	/* Slot 1 */
+	if (hw_config->slots[1] != -1)	/* The MPU driver installed itself */
+		midi_devs[hw_config->slots[1]]->coproc = &pss_coproc_operations;
+	return 1;
+fail:
+	release_region(hw_config->io_base, 2);
+	return 0;
 }
 
 static int pss_coproc_open(void *dev_info, int sub_device)
@@ -1021,39 +1039,36 @@ static coproc_operations pss_coproc_operations =
 	&pss_data
 };
 
-static void __init attach_pss_mpu(struct address_info *hw_config)
-{
-	attach_mpu401(hw_config, THIS_MODULE);	/* Slot 1 */
-	if (hw_config->slots[1] != -1)	/* The MPU driver installed itself */
-		midi_devs[hw_config->slots[1]]->coproc = &pss_coproc_operations;
-}
-
 static int __init probe_pss_mss(struct address_info *hw_config)
 {
 	volatile int timeout;
+	struct resource *ports;
+	int        my_mix = -999;	/* gcc shut up */
 
 	if (!pss_initialized)
 		return 0;
 
-	if (check_region(hw_config->io_base, 8))
-	{
-		  printk(KERN_ERR "PSS: WSS I/O port conflicts.\n");
-		  return 0;
+	if (!request_region(hw_config->io_base, 4, "WSS config")) {
+		printk(KERN_ERR "PSS: WSS I/O port conflicts.\n");
+		return 0;
 	}
-	if (!set_io_base(devc, CONF_WSS, hw_config->io_base))
-	{
-		printk("PSS: WSS base not settable.\n");
+	ports = request_region(hw_config->io_base + 4, 4, "ad1848");
+	if (!ports) {
+		printk(KERN_ERR "PSS: WSS I/O port conflicts.\n");
+		release_region(hw_config->io_base, 4);
 		return 0;
 	}
-	if (!set_irq(devc, CONF_WSS, hw_config->irq))
-	{
+	if (!set_io_base(devc, CONF_WSS, hw_config->io_base)) {
+		printk("PSS: WSS base not settable.\n");
+		goto fail;
+	}
+	if (!set_irq(devc, CONF_WSS, hw_config->irq)) {
 		printk("PSS: WSS IRQ allocation error.\n");
-		return 0;
+		goto fail;
 	}
-	if (!set_dma(devc, CONF_WSS, hw_config->dma))
-	{
+	if (!set_dma(devc, CONF_WSS, hw_config->dma)) {
 		printk(KERN_ERR "PSS: WSS DMA allocation error\n");
-		return 0;
+		goto fail;
 	}
 	/*
 	 * For some reason the card returns 0xff in the WSS status register
@@ -1071,13 +1086,9 @@ static int __init probe_pss_mss(struct address_info *hw_config)
 	  (timeout < 100000); timeout++)
 		;
 
-	return probe_ms_sound(hw_config);
-}
+	if (!probe_ms_sound(hw_config, ports))
+		goto fail;
 
-static void __init attach_pss_mss(struct address_info *hw_config)
-{
-	int        my_mix = -999;	/* gcc shut up */
-	
 	devc->ad_mixer_dev = NO_WSS_MIXER;
 	if (pss_mixer) 
 	{
@@ -1088,11 +1099,11 @@ static void __init attach_pss_mss(struct address_info *hw_config)
 			devc)) < 0) 
 		{
 			printk(KERN_ERR "Could not install PSS mixer\n");
-			return;
+			goto fail;
 		}
 	}
 	pss_mixer_reset(devc);
-	attach_ms_sound(hw_config, THIS_MODULE);	/* Slot 0 */
+	attach_ms_sound(hw_config, ports, THIS_MODULE);	/* Slot 0 */
 
 	if (hw_config->slots[0] != -1)
 	{
@@ -1104,6 +1115,11 @@ static void __init attach_pss_mss(struct address_info *hw_config)
 			devc->ad_mixer_dev = audio_devs[hw_config->slots[0]]->mixer_dev;
 		}
 	}
+	return 1;
+fail:
+	release_region(hw_config->io_base + 4, 4);
+	release_region(hw_config->io_base, 4);
+	return 0;
 }
 
 static inline void __exit unload_pss(struct address_info *hw_config)
@@ -1185,6 +1201,8 @@ static int __init init_pss(void)
 		printk(KERN_INFO "PSS: loading in no sound mode.\n");
 		disable_all_emulations();
 		configure_nonsound_components();
+		release_region(pss_io, 0x10);
+		release_region(pss_io + 0x10, 0x9);
 		return 0;
 	}
 
@@ -1206,20 +1224,16 @@ static int __init init_pss(void)
 		fw_load = 1;
 		pss_synthLen = mod_firmware_load(pss_firmware, (void *) &pss_synth);
 	}
-	if (!probe_pss(&cfg))
+	if (!attach_pss(&cfg))
 		return -ENODEV;
-	attach_pss(&cfg);
 	/*
 	 *    Attach stuff
 	 */
-	if (probe_pss_mpu(&cfg_mpu)) {
+	if (probe_pss_mpu(&cfg_mpu))
 		pssmpu = 1;
-		attach_pss_mpu(&cfg_mpu);
-	}
-	if (probe_pss_mss(&cfg2)) {
+
+	if (probe_pss_mss(&cfg2))
 		pssmss = 1;
-		attach_pss_mss(&cfg2);
-	}
 
 	return 0;
 }
diff --git a/sound/oss/rme96xx.c b/sound/oss/rme96xx.c
index 3df045dd5..c770137f7 100644
--- a/sound/oss/rme96xx.c
+++ b/sound/oss/rme96xx.c
@@ -54,7 +54,7 @@ TODO:
 #include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <asm/hardirq.h>
+#include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/poll.h>
diff --git a/sound/oss/sb_card.c b/sound/oss/sb_card.c
index 012f6d2d8..07191b3ae 100644
--- a/sound/oss/sb_card.c
+++ b/sound/oss/sb_card.c
@@ -100,7 +100,14 @@ MODULE_PARM_DESC(uart401,  "When set to 1, will attempt to detect and enable"\
 /* OSS subsystem card registration shared by PnP and legacy routines */
 static int sb_register_oss(struct sb_card_config *scc, struct sb_module_options *sbmo)
 {
-	if(!sb_dsp_detect(&scc->conf, 0, 0, sbmo)) {
+	if (!request_region(scc->conf.io_base, 16, "soundblaster")) {
+		printk(KERN_ERR "sb: ports busy.\n");
+		kfree(scc);
+		return -EBUSY;
+	}
+
+	if (!sb_dsp_detect(&scc->conf, 0, 0, sbmo)) {
+		release_region(scc->conf.io_base, 16);
 		printk(KERN_ERR "sb: Failed DSP Detect.\n");
 		kfree(scc);
 		return -ENODEV;
diff --git a/sound/oss/sb_common.c b/sound/oss/sb_common.c
index 1ab1eb129..e33a50e82 100644
--- a/sound/oss/sb_common.c
+++ b/sound/oss/sb_common.c
@@ -520,13 +520,6 @@ int sb_dsp_detect(struct address_info *hw_config, int pci, int pciio, struct sb_
 	 */
 	
 	DDB(printk("sb_dsp_detect(%x) entered\n", hw_config->io_base));
-	if (check_region(hw_config->io_base, 16))
-	{
-#ifdef MODULE
-		printk(KERN_INFO "sb: I/O region in use.\n");
-#endif
-		return 0;
-	}
 
 	devc->lock = SPIN_LOCK_UNLOCKED;
 	devc->type = hw_config->card_subtype;
@@ -668,6 +661,7 @@ int sb_dsp_init(struct address_info *hw_config, struct module *owner)
 	if (devc->base != hw_config->io_base)
 	{
 		DDB(printk("I/O port mismatch\n"));
+		release_region(devc->base, 16);
 		return 0;
 	}
 	/*
@@ -689,6 +683,7 @@ int sb_dsp_init(struct address_info *hw_config, struct module *owner)
 		if (request_irq(hw_config->irq, sbintr, i, "soundblaster", devc) < 0)
 		{
 			printk(KERN_ERR "SB: Can't allocate IRQ%d\n", hw_config->irq);
+			release_region(devc->base, 16);
 			return 0;
 		}
 		devc->irq_ok = 0;
@@ -697,6 +692,7 @@ int sb_dsp_init(struct address_info *hw_config, struct module *owner)
 			if (!sb16_set_irq_hw(devc, devc->irq))	/* Unsupported IRQ */
 			{
 				free_irq(devc->irq, devc);
+				release_region(devc->base, 16);
 				return 0;
 			}
 		if ((devc->type == 0 || devc->type == MDL_ESS) &&
@@ -735,7 +731,6 @@ int sb_dsp_init(struct address_info *hw_config, struct module *owner)
 			}
 		}
 	}			/* IRQ setup */
-	request_region(hw_config->io_base, 16, "soundblaster");
 
 	last_sb = devc;
 	
@@ -1224,17 +1219,22 @@ int probe_sbmpu(struct address_info *hw_config, struct module *owner)
 #if defined(CONFIG_SOUND_MPU401)
 	if (devc->model == MDL_ESS)
 	{
-		if (check_region(hw_config->io_base, 2))
-		{
+		struct resource *ports;
+		ports = request_region(hw_config->io_base, 2, "mpu401");
+		if (!ports) {
 			printk(KERN_ERR "sbmpu: I/O port conflict (%x)\n", hw_config->io_base);
 			return 0;
 		}
-		if (!ess_midi_init(devc, hw_config))
+		if (!ess_midi_init(devc, hw_config)) {
+			release_region(hw_config->io_base, 2);
 			return 0;
+		}
 		hw_config->name = "ESS1xxx MPU";
 		devc->midi_irq_cookie = NULL;
-		if (!probe_mpu401(hw_config))
+		if (!probe_mpu401(hw_config, ports)) {
+			release_region(hw_config->io_base, 2);
 			return 0;
+		}
 		attach_mpu401(hw_config, owner);
 		if (last_sb->irq == -hw_config->irq)
 			last_sb->midi_irq_cookie=(void *)hw_config->slots[1];
diff --git a/sound/oss/sgalaxy.c b/sound/oss/sgalaxy.c
index 1e3109716..16cc9ab50 100644
--- a/sound/oss/sgalaxy.c
+++ b/sound/oss/sgalaxy.c
@@ -86,19 +86,31 @@ static int __init sb_cmd( int base, unsigned char val )
 
 static int __init probe_sgalaxy( struct address_info *ai )
 {
-	if ( check_region( ai->io_base, 8 ) ) {
+	struct resource *ports;
+	int n;
+
+	if (!request_region(ai->io_base, 4, "WSS config")) {
 		printk(KERN_ERR "sgalaxy: WSS IO port 0x%03x not available\n", ai->io_base);
 		return 0;
 	}
-        
-	if ( ad1848_detect( ai->io_base+4, NULL, ai->osp ) )
-		return probe_ms_sound(ai);  /* The card is already active, check irq etc... */
 
-	if ( check_region( ai->ai_sgbase, 0x10 ) ) {
+	ports = request_region(ai->io_base + 4, 4, "ad1848");
+	if (!ports) {
+		printk(KERN_ERR "sgalaxy: WSS IO port 0x%03x not available\n", ai->io_base);
+		release_region(ai->io_base, 4);
+		return 0;
+	}
+
+	if (!request_region( ai->ai_sgbase, 0x10, "SoundGalaxy SB")) {
 		printk(KERN_ERR "sgalaxy: SB IO port 0x%03x not available\n", ai->ai_sgbase);
+		release_region(ai->io_base + 4, 4);
+		release_region(ai->io_base, 4);
 		return 0;
 	}
         
+	if (ad1848_detect(ports, NULL, ai->osp))
+		goto out;  /* The card is already active, check irq etc... */
+        
 	/* switch to MSS/WSS mode */
    
 	sb_rst( ai->ai_sgbase );
@@ -108,16 +120,15 @@ static int __init probe_sgalaxy( struct address_info *ai )
 
 	sleep( HZ/10 );
 
-      	return probe_ms_sound(ai);
-}
+out:
+      	if (!probe_ms_sound(ai, ports)) {
+		release_region(ai->io_base + 4, 4);
+		release_region(ai->io_base, 4);
+		release_region(ai->ai_sgbase, 0x10);
+		return 0;
+	}
 
-static void __init attach_sgalaxy( struct address_info *ai )
-{
-	int n;
-	
-	request_region( ai->ai_sgbase, 0x10, "SoundGalaxy SB" );
- 
-	attach_ms_sound(ai, THIS_MODULE);
+	attach_ms_sound(ai, ports, THIS_MODULE);
 	n=ai->slots[0];
 	
 	if (n!=-1 && audio_devs[n]->mixer_dev != -1 ) {
@@ -125,6 +136,7 @@ static void __init attach_sgalaxy( struct address_info *ai )
 		AD1848_REROUTE( SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH );  /* FM+Wavetable*/
 		AD1848_REROUTE( SOUND_MIXER_LINE3, SOUND_MIXER_CD );     /* CD */
 	}
+	return 1;
 }
 
 static void __exit unload_sgalaxy( struct address_info *ai )
@@ -163,8 +175,6 @@ static int __init init_sgalaxy(void)
 	if ( probe_sgalaxy(&cfg) == 0 )
 		return -ENODEV;
 
-	attach_sgalaxy(&cfg);
-
 	return 0;
 }
 
diff --git a/sound/oss/sscape.c b/sound/oss/sscape.c
index 733bfc187..7c9b5d41b 100644
--- a/sound/oss/sscape.c
+++ b/sound/oss/sscape.c
@@ -600,10 +600,10 @@ static coproc_operations sscape_coproc_operations =
 	&adev_info
 };
 
-static int sscape_detected;
+static struct resource *sscape_ports;
 static int sscape_is_pnp;
 
-void __init attach_sscape(struct address_info *hw_config)
+static void __init attach_sscape(struct address_info *hw_config)
 {
 #ifndef SSCAPE_REGS
 	/*
@@ -638,10 +638,6 @@ void __init attach_sscape(struct address_info *hw_config)
 
 	int i, irq_bits = 0xff;
 
-	if (sscape_detected != hw_config->io_base)
-		return;
-
-	request_region(devc->base + 2, 6, "SoundScape");
 	if (old_hardware)
 	{
 		valid_interrupts = valid_interrupts_old;
@@ -650,7 +646,7 @@ void __init attach_sscape(struct address_info *hw_config)
 	else
 		conf_printf("Ensoniq SoundScape", hw_config);
 
-	for (i = 0; i < sizeof(valid_interrupts); i++)
+	for (i = 0; i < 4; i++)
 	{
 		if (hw_config->irq == valid_interrupts[i])
 		{
@@ -661,45 +657,32 @@ void __init attach_sscape(struct address_info *hw_config)
 	if (hw_config->irq > 15 || (regs[4] = irq_bits == 0xff))
 	{
 		printk(KERN_ERR "Invalid IRQ%d\n", hw_config->irq);
+		release_region(devc->base, 2);
+		release_region(devc->base + 2, 6);
+		if (sscape_is_pnp)
+			release_region(devc->codec, 2);
 		return;
 	}
 	
 	if (!sscape_is_pnp) {
 	
 		spin_lock_irqsave(&devc->lock,flags);
-	    for (i = 1; i < 10; i++)
-	    {
-		switch (i)
-		{
-			case 1:	/* Host interrupt enable */
-				sscape_write(devc, i, 0xf0);	/* All interrupts enabled */
-				break;
-
-			case 2:	/* DMA A status/trigger register */
-			case 3:	/* DMA B status/trigger register */
-				sscape_write(devc, i, 0x20);	/* DMA channel disabled */
-				break;
-
-			case 4:	/* Host interrupt config reg */
-				sscape_write(devc, i, 0xf0 | (irq_bits << 2) | irq_bits);
-				break;
-
-			case 5:	/* Don't destroy CD-ROM DMA config bits (0xc0) */
-				sscape_write(devc, i, (regs[i] & 0x3f) | (sscape_read(devc, i) & 0xc0));
-				break;
-
-			case 6:	/* CD-ROM config (WSS codec actually) */
-				sscape_write(devc, i, regs[i]);
-				break;
-
-			case 9:	/* Master control reg. Don't modify CR-ROM bits. Disable SB emul */
-				sscape_write(devc, i, (sscape_read(devc, i) & 0xf0) | 0x08);
-				break;
-
-			default:
-				sscape_write(devc, i, regs[i]);
-		}
-	    }
+		/* Host interrupt enable */
+		sscape_write(devc, 1, 0xf0);	/* All interrupts enabled */
+		/* DMA A status/trigger register */
+		sscape_write(devc, 2, 0x20);	/* DMA channel disabled */
+		/* DMA B status/trigger register */
+		sscape_write(devc, 3, 0x20);	/* DMA channel disabled */
+		/* Host interrupt config reg */
+		sscape_write(devc, 4, 0xf0 | (irq_bits << 2) | irq_bits);
+		/* Don't destroy CD-ROM DMA config bits (0xc0) */
+		sscape_write(devc, 5, (regs[5] & 0x3f) | (sscape_read(devc, 5) & 0xc0));
+		/* CD-ROM config (WSS codec actually) */
+		sscape_write(devc, 6, regs[6]);
+		sscape_write(devc, 7, regs[7]);
+		sscape_write(devc, 8, regs[8]);
+		/* Master control reg. Don't modify CR-ROM bits. Disable SB emul */
+		sscape_write(devc, 9, (sscape_read(devc, 9) & 0xf0) | 0x08);
 		spin_unlock_irqrestore(&devc->lock,flags);
 	}
 #ifdef SSCAPE_DEBUG2
@@ -715,7 +698,7 @@ void __init attach_sscape(struct address_info *hw_config)
 	}
 #endif
 
-	if (probe_mpu401(hw_config))
+	if (probe_mpu401(hw_config, sscape_ports))
 		hw_config->always_detect = 1;
 	hw_config->name = "SoundScape";
 
@@ -739,9 +722,6 @@ static int detect_ga(sscape_info * devc)
 
 	DDB(printk("Entered Soundscape detect_ga(%x)\n", devc->base));
 
-	if (check_region(devc->base, 8))
-		return 0;
-
 	/*
 	 * First check that the address register of "ODIE" is
 	 * there and that it has exactly 4 writable bits.
@@ -1115,9 +1095,9 @@ static void __init sscape_pnp_init_hw(sscape_info* devc)
 		sscape_write( devc, 9, i | 3 );
 		sscape_write( devc, 3, 0x40);
 
-		if (check_region(0x228, 1)) {
-		    	    outb(0, 0x228);
-			    release_region(0x228,1);
+		if (request_region(0x228, 1, "sscape setup junk")) {
+			outb(0, 0x228);
+			release_region(0x228,1);
 		}
 		sscape_write( devc, 3, (devc -> dma << 4) | 0x80);
 		sscape_write( devc, 9, i );
@@ -1134,50 +1114,46 @@ static int __init detect_sscape_pnp(sscape_info* devc)
 
 	DDB(printk("Entered detect_sscape_pnp(%x)\n", devc->base));
 
-	if (check_region(devc->base, 8)) {
-		printk(KERN_ERR "detect_sscape_pnp: port %x is not free\n", devc->base);	
-		return 0;
-	}
-		
-	if (check_region(devc->codec, 2)) {
+	if (!request_region(devc->codec, 2, "sscape codec")) {
 		printk(KERN_ERR "detect_sscape_pnp: port %x is not free\n", devc->codec);	
 		return 0;
 	}
 
-	if ( (inb( devc -> base + 2) & 0x78) != 0) return 0;
+	if ((inb(devc->base + 2) & 0x78) != 0)
+		goto fail;
 
 	d = inb ( devc -> base + 4) & 0xF0;
-	if (  (d & 0x80) != 0)  return 0;
+	if (d & 0x80)
+		goto fail;
 	
 	if (d == 0) {
-			devc->codec_type = 1;
-			devc->ic_type = IC_ODIE;
-	}
-	else if ( (d & 0x60) != 0) {
-			devc->codec_type = 2;
-			devc->ic_type = IC_OPUS;
-	}
-	else if ( (d & 0x40) != 0) {
-			devc->codec_type = 2;
-			devc->ic_type = IC_ODIE;
-	} 
-	else return 0;
+		devc->codec_type = 1;
+		devc->ic_type = IC_ODIE;
+	} else if ( (d & 0x60) != 0) {
+		devc->codec_type = 2;
+		devc->ic_type = IC_OPUS;
+	} else if ( (d & 0x40) != 0) {	/* WTF? */
+		devc->codec_type = 2;
+		devc->ic_type = IC_ODIE;
+	} else
+		goto fail;
 	
 	sscape_is_pnp = 1;
 		
 	outb(0xFA, devc -> base+4);
 	if  ((inb( devc -> base+4) & 0x9F) != 0x0A)
-		return 0;
+		goto fail;
 	outb(0xFE, devc -> base+4);
 	if  ( (inb(devc -> base+4) & 0x9F) != 0x0E)
-		return 0;
+		goto fail;
 	if  ( (inb(devc -> base+5) & 0x9F) != 0x0E)
-		return 0;
+		goto fail;
 
 	if (devc->codec_type == 2) {
-		if (devc -> codec != devc -> base + 8)
+		if (devc->codec != devc->base + 8) {
 			printk("soundscape warning: incorrect codec port specified\n");
-		devc -> codec = devc -> base + 8;
+			goto fail;
+		}
 		d = 0x10 | (sscape_read(devc, 9)  & 0xCF);
 		sscape_write(devc, 9, d);
 		sscape_write(devc, 6, 0x80);
@@ -1193,9 +1169,9 @@ static int __init detect_sscape_pnp(sscape_info* devc)
 
 	d = inb(devc -> codec);
 	if (d & 0x80)
-		return 0;
+		goto fail;
 	if ( inb(devc -> codec + 2) == 0xFF)
-		return 0;
+		goto fail;
 
 	sscape_write(devc, 9, sscape_read(devc, 9)  & 0x3F );
 
@@ -1217,7 +1193,7 @@ static int __init detect_sscape_pnp(sscape_info* devc)
 		
 	sscape_pnp_init_hw(devc);
 
-	for (i = 0; i < sizeof(valid_interrupts); i++)
+	for (i = 0; i < 4; i++)
 	{
 		if (devc->codec_irq == valid_interrupts[i]) {
 			irq_bits = i;
@@ -1234,15 +1210,14 @@ static int __init detect_sscape_pnp(sscape_info* devc)
 	sscape_pnp_write_codec( devc, 0, sscape_pnp_read_codec( devc, 0) | 0x20);
 	sscape_pnp_write_codec( devc, 0, sscape_pnp_read_codec( devc, 1) | 0x20);
 
-	return 1;	
+	return 1;
+fail:
+	release_region(devc->codec, 2);
+	return 0;
 }
 
 static int __init probe_sscape(struct address_info *hw_config)
 {
-
-	if (sscape_detected != 0 && sscape_detected != hw_config->io_base)
-		return 0;
-
 	devc->base = hw_config->io_base;
 	devc->irq = hw_config->irq;
 	devc->dma = hw_config->dma;
@@ -1262,12 +1237,21 @@ static int __init probe_sscape(struct address_info *hw_config)
 #endif
 	devc->failed = 1;
 
+	sscape_ports = request_region(devc->base, 2, "mpu401");
+	if (!sscape_ports)
+		return 0;
+
+	if (!request_region(devc->base + 2, 6, "SoundScape")) {
+		release_region(devc->base, 2);
+		return 0;
+	}
+
 	if (!detect_ga(devc)) {
-		if (detect_sscape_pnp(devc)) {		        
-			sscape_detected = hw_config->io_base;
+		if (detect_sscape_pnp(devc))
 			return 1;
-		} 
-		else return 0;
+		release_region(devc->base, 2);
+		release_region(devc->base + 2, 6);
+		return 0;
 	}
 
 	if (old_hardware)	/* Check that it's really an old Spea/Reveal card. */
@@ -1282,14 +1266,14 @@ static int __init probe_sscape(struct address_info *hw_config)
 				inb(devc->base + ODIE_ADDR);
 		}
 	}
-	sscape_detected = hw_config->io_base;
 	return 1;
 }
 
-static int __init probe_ss_ms_sound(struct address_info *hw_config)
+static int __init init_ss_ms_sound(struct address_info *hw_config)
 {
 	int i, irq_bits = 0xff;
 	int ad_flags = 0;
+	struct resource *ports;
 	
 	if (devc->failed)
 	{
@@ -1301,7 +1285,7 @@ static int __init probe_ss_ms_sound(struct address_info *hw_config)
 		printk(KERN_ERR "soundscape: Invalid initialization order.\n");
 		return 0;
 	}
-	for (i = 0; i < sizeof(valid_interrupts); i++)
+	for (i = 0; i < 4; i++)
 	{
 		if (hw_config->irq == valid_interrupts[i])
 		{
@@ -1309,37 +1293,27 @@ static int __init probe_ss_ms_sound(struct address_info *hw_config)
 			break;
 		}
 	}
-	if (hw_config->irq > 15 || irq_bits == 0xff)
-	{
+	if (irq_bits == 0xff) {
 		printk(KERN_ERR "soundscape: Invalid MSS IRQ%d\n", hw_config->irq);
 		return 0;
 	}
 	
-	if (!sscape_is_pnp) {
-		if (old_hardware)
-			ad_flags = 0x12345677;	/* Tell that we may have a CS4248 chip (Spea-V7 Media FX) */
-		return ad1848_detect(hw_config->io_base, &ad_flags, hw_config->osp);
-	} 
-	else {
-		if (old_hardware)
-			ad_flags = 0x12345677;	/* Tell that we may have a CS4248 chip (Spea-V7 Media FX) */
-		else
-			ad_flags = 0x87654321;  /* Tell that we have a soundscape pnp with 1845 chip */
-		return ad1848_detect(hw_config->io_base, &ad_flags, hw_config->osp);
-	}
-}
+	if (old_hardware)
+		ad_flags = 0x12345677;	/* Tell that we may have a CS4248 chip (Spea-V7 Media FX) */
+	else if (sscape_is_pnp)
+		ad_flags = 0x87654321;  /* Tell that we have a soundscape pnp with 1845 chip */
 
-static void __init attach_ss_ms_sound(struct address_info *hw_config)
-{
-	/*
-	 * This routine configures the SoundScape card for use with the
-	 * Win Sound System driver. The AD1848 codec interface uses the CD-ROM
-	 * config registers of the "ODIE".
-	 */
+	ports = request_region(hw_config->io_base, 4, "ad1848");
+	if (!ports) {
+		printk(KERN_ERR "soundscape: ports busy\n");
+		return 0;
+	}
 
-	int i, irq_bits = 0xff;
+	if (!ad1848_detect(ports, &ad_flags, hw_config->osp)) {
+		release_region(hw_config->io_base, 4);
+		return 0;
+	}
 
- 		
  	if (!sscape_is_pnp)  /*pnp is already setup*/
  	{
  		/*
@@ -1355,14 +1329,6 @@ static void __init attach_ss_ms_sound(struct address_info *hw_config)
  		/*
  		 * Init the AD1848 (CD-ROM) config reg.
  		 */
- 		for (i = 0; i < sizeof(valid_interrupts); i++)
- 		{
- 			if (hw_config->irq == valid_interrupts[i])
- 			{
- 				irq_bits = i;
- 				break;
- 			}
- 		}	
  		sscape_write(devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) | (irq_bits << 1));
  	}
  	
@@ -1371,7 +1337,7 @@ static void __init attach_ss_ms_sound(struct address_info *hw_config)
  				
 	hw_config->slots[0] = ad1848_init(
 			sscape_is_pnp ? "SoundScape" : "SoundScape PNP",
-			hw_config->io_base,
+			ports,
 			hw_config->irq,
 			hw_config->dma,
 			hw_config->dma,
@@ -1402,13 +1368,15 @@ static void __init attach_ss_ms_sound(struct address_info *hw_config)
 			printk("I%d = %02x\n", i, sscape_read(devc, i));
 	}
 #endif
-
+	return 1;
 }
 
 static void __exit unload_sscape(struct address_info *hw_config)
 {
 	release_region(devc->base + 2, 6);
 	unload_mpu401(hw_config);
+	if (sscape_is_pnp)
+		release_region(devc->codec, 2);
 }
 
 static void __exit unload_ss_ms_sound(struct address_info *hw_config)
@@ -1480,10 +1448,7 @@ static int __init init_sscape(void)
 
 	attach_sscape(&cfg_mpu);
 	
-	mss = probe_ss_ms_sound(&cfg);
-
-	if (mss)
-		attach_ss_ms_sound(&cfg);
+	mss = init_ss_ms_sound(&cfg);
 
 	return 0;
 }
diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c
index 4846dc2cb..dee5a912d 100644
--- a/sound/oss/swarm_cs4297a.c
+++ b/sound/oss/swarm_cs4297a.c
@@ -70,6 +70,7 @@
 #include <linux/ac97_codec.h>
 #include <linux/pci.h>
 #include <linux/bitops.h>
+#include <linux/interrupt.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <linux/init.h>
@@ -77,7 +78,6 @@
 #include <linux/smp_lock.h>
 #include <linux/wrapper.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 
 #include <asm/sibyte/sb1250_regs.h>
 #include <asm/sibyte/sb1250_int.h>
diff --git a/sound/oss/trident.c b/sound/oss/trident.c
index 1beb4e9ff..813a27e18 100644
--- a/sound/oss/trident.c
+++ b/sound/oss/trident.c
@@ -217,7 +217,6 @@
 #include <linux/gameport.h>
 #include <linux/kernel.h>
 #include <asm/uaccess.h>
-#include <asm/hardirq.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
diff --git a/sound/oss/trix.c b/sound/oss/trix.c
index 37ffed14c..13c3d7939 100644
--- a/sound/oss/trix.c
+++ b/sound/oss/trix.c
@@ -29,12 +29,6 @@
 
 #include "trix_boot.h"
 
-static int kilroy_was_here;	/* Don't detect twice */
-static int sb_initialized;
-static int mpu_initialized;
-
-static int *trix_osp;
-
 static int mpu;
 
 static int joystick;
@@ -82,20 +76,11 @@ static int trix_set_wss_port(struct address_info *hw_config)
 {
 	unsigned char   addr_bits;
 
-	if (check_region(0x390, 2))
-	{
-		printk(KERN_ERR "AudioTrix: Config port I/O conflict\n");
-		return 0;
-	}
-	if (kilroy_was_here)	/* Already initialized */
-		return 0;
-
 	if (trix_read(0x15) != 0x71)	/* No ASIC signature */
 	{
 		MDB(printk(KERN_ERR "No AudioTrix ASIC signature found\n"));
 		return 0;
 	}
-	kilroy_was_here = 1;
 
 	/*
 	 * Reset some registers.
@@ -135,107 +120,114 @@ static int trix_set_wss_port(struct address_info *hw_config)
  *      AudioTrix Pro
  */
 
-static int __init probe_trix_wss(struct address_info *hw_config)
+static int __init init_trix_wss(struct address_info *hw_config)
 {
+	static unsigned char dma_bits[4] = {
+		1, 2, 0, 3
+	};
+	struct resource *ports;
+	int config_port = hw_config->io_base + 0;
+	int dma1 = hw_config->dma, dma2 = hw_config->dma2;
+	int old_num_mixers = num_mixers;
+	u8 config, bits;
 	int ret;
+ 
+	switch(hw_config->irq) {
+	case 7:
+		bits = 8;
+		break;
+	case 9:
+		bits = 0x10;
+		break;
+	case 10:
+		bits = 0x18;
+		break;
+	case 11:
+		bits = 0x20;
+		break;
+	default:
+		printk(KERN_ERR "AudioTrix: Bad WSS IRQ %d\n", hw_config->irq);
+		return 0;
+	}
+
+	switch (dma1) {
+	case 0:
+	case 1:
+	case 3:
+		break;
+	default:
+		printk(KERN_ERR "AudioTrix: Bad WSS DMA %d\n", dma1);
+		return 0;
+	}
+
+	switch (dma2) {
+	case -1:
+	case 0:
+	case 1:
+	case 3:
+		break;
+	default:
+		printk(KERN_ERR "AudioTrix: Bad capture DMA %d\n", dma2);
+		return 0;
+	}
 
 	/*
 	 * Check if the IO port returns valid signature. The original MS Sound
 	 * system returns 0x04 while some cards (AudioTrix Pro for example)
 	 * return 0x00.
 	 */
-	if (check_region(hw_config->io_base, 8))
-	{
+	ports = request_region(hw_config->io_base + 4, 4, "ad1848");
+	if (!ports) {
 		printk(KERN_ERR "AudioTrix: MSS I/O port conflict (%x)\n", hw_config->io_base);
 		return 0;
 	}
-	trix_osp = hw_config->osp;
 
-	if (!trix_set_wss_port(hw_config))
+	if (!request_region(hw_config->io_base, 4, "MSS config")) {
+		printk(KERN_ERR "AudioTrix: MSS I/O port conflict (%x)\n", hw_config->io_base);
+		release_region(hw_config->io_base + 4, 4);
 		return 0;
+	}
+
+	if (!trix_set_wss_port(hw_config))
+		goto fail;
 
-	if ((inb(hw_config->io_base + 3) & 0x3f) != 0x00)
+	config = inb(hw_config->io_base + 3);
+
+	if ((config & 0x3f) != 0x00)
 	{
 		MDB(printk(KERN_ERR "No MSS signature detected on port 0x%x\n", hw_config->io_base));
-		return 0;
-	}
-	if (hw_config->irq > 11)
-	{
-		printk(KERN_ERR "AudioTrix: Bad WSS IRQ %d\n", hw_config->irq);
-		return 0;
-	}
-	if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3)
-	{
-		printk(KERN_ERR "AudioTrix: Bad WSS DMA %d\n", hw_config->dma);
-		return 0;
+		goto fail;
 	}
-	if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma)
-		if (hw_config->dma2 != 0 && hw_config->dma2 != 1 && hw_config->dma2 != 3)
-		{
-			  printk(KERN_ERR "AudioTrix: Bad capture DMA %d\n", hw_config->dma2);
-			  return 0;
-		}
+
 	/*
 	 * Check that DMA0 is not in use with a 8 bit board.
 	 */
 
-	if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80)
+	if (dma1 == 0 && config & 0x80)
 	{
 		printk(KERN_ERR "AudioTrix: Can't use DMA0 with a 8 bit card slot\n");
-		return 0;
+		goto fail;
 	}
-	if (hw_config->irq > 7 && hw_config->irq != 9 && inb(hw_config->io_base + 3) & 0x80)
+	if (hw_config->irq > 9 && config & 0x80)
 	{
 		printk(KERN_ERR "AudioTrix: Can't use IRQ%d with a 8 bit card slot\n", hw_config->irq);
-		return 0;
-	}
-	ret = ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp);
-
-	if (ret)
-	{
-		if(joystick==1)
-			trix_write(0x15, 0x80);
-		request_region(0x390, 2, "AudioTrix");
+		goto fail;
 	}
-	return ret;
-}
-
-static void __init attach_trix_wss(struct address_info *hw_config)
-{
-	static unsigned char interrupt_bits[12] = {
-		0, 0, 0, 0, 0, 0, 0, 0x08, 0, 0x10, 0x18, 0x20
-	};
-	char bits;
-
-	static unsigned char dma_bits[4] = {
-		1, 2, 0, 3
-	};
 
-	int config_port = hw_config->io_base + 0;
-	int dma1 = hw_config->dma, dma2 = hw_config->dma2;
-	int old_num_mixers = num_mixers;
+	ret = ad1848_detect(ports, NULL, hw_config->osp);
+	if (!ret)
+		goto fail;
 
-	trix_osp = hw_config->osp;
+	if (joystick==1)
+		trix_write(0x15, 0x80);
 
-	if (!kilroy_was_here)
-	{
-		DDB(printk("AudioTrix: Attach called but not probed yet???\n"));
-		return;
-	}
-	
 	/*
 	 * Set the IRQ and DMA addresses.
 	 */
 
-	bits = interrupt_bits[hw_config->irq];
-	if (bits == 0)
-	{
-		printk("AudioTrix: Bad IRQ (%d)\n", hw_config->irq);
-		return;
-	}
 	outb((bits | 0x40), config_port);
 
-	if (hw_config->dma2 == -1 || hw_config->dma2 == hw_config->dma)
+	if (dma2 == -1 || dma2 == dma1)
 	{
 		  bits |= dma_bits[dma1];
 		  dma2 = dma1;
@@ -253,14 +245,13 @@ static void __init attach_trix_wss(struct address_info *hw_config)
 
 	outb((bits), config_port);	/* Write IRQ+DMA setup */
 
-	hw_config->slots[0] = ad1848_init("AudioTrix Pro", hw_config->io_base + 4,
+	hw_config->slots[0] = ad1848_init("AudioTrix Pro", ports,
 					  hw_config->irq,
 					  dma1,
 					  dma2,
 					  0,
 					  hw_config->osp,
 					  THIS_MODULE);
-	request_region(hw_config->io_base, 4, "MSS config");
 
 	if (num_mixers > old_num_mixers)	/* Mixer got installed */
 	{
@@ -269,6 +260,12 @@ static void __init attach_trix_wss(struct address_info *hw_config)
 		AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_SYNTH);		/* OPL4 */
 		AD1848_REROUTE(SOUND_MIXER_SPEAKER, SOUND_MIXER_ALTPCM);	/* SB */
 	}
+	return 1;
+
+fail:
+	release_region(hw_config->io_base, 4);
+	release_region(hw_config->io_base + 4, 4);
+	return 0;
 }
 
 static int __init probe_trix_sb(struct address_info *hw_config)
@@ -276,6 +273,8 @@ static int __init probe_trix_sb(struct address_info *hw_config)
 
 	int tmp;
 	unsigned char conf;
+	extern int sb_be_quiet;
+	int old_quiet;
 	static signed char irq_translate[] = {
 		-1, -1, -1, 0, 1, 2, -1, 3
 	};
@@ -283,17 +282,6 @@ static int __init probe_trix_sb(struct address_info *hw_config)
 	if (trix_boot_len == 0)
 		return 0;	/* No boot code -> no fun */
 
-	if (!kilroy_was_here)
-		return 0;	/* AudioTrix Pro has not been detected earlier */
-
-	if (sb_initialized)
-		return 0;
-
-	if (check_region(hw_config->io_base, 16))
-	{
-		printk(KERN_ERR "AudioTrix: SB I/O port conflict (%x)\n", hw_config->io_base);
-		return 0;
-	}
 	if ((hw_config->io_base & 0xffffff8f) != 0x200)
 		return 0;
 
@@ -307,6 +295,11 @@ static int __init probe_trix_sb(struct address_info *hw_config)
 	if (tmp != 1 && tmp != 3)
 		return 0;
 
+	if (!request_region(hw_config->io_base, 16, "soundblaster")) {
+		printk(KERN_ERR "AudioTrix: SB I/O port conflict (%x)\n", hw_config->io_base);
+		return 0;
+	}
+
 	conf = 0x84;		/* DMA and IRQ enable */
 	conf |= hw_config->io_base & 0x70;	/* I/O address bits */
 	conf |= irq_translate[hw_config->irq];
@@ -315,16 +308,12 @@ static int __init probe_trix_sb(struct address_info *hw_config)
 	trix_write(0x1b, conf);
 
 	download_boot(hw_config->io_base);
-	sb_initialized = 1;
 
 	hw_config->name = "AudioTrix SB";
-	return sb_dsp_detect(hw_config, 0, 0, NULL);
-}
-
-static void __init attach_trix_sb(struct address_info *hw_config)
-{
-	extern int sb_be_quiet;
-	int old_quiet;
+	if (!sb_dsp_detect(hw_config, 0, 0, NULL)) {
+		release_region(hw_config->io_base, 16);
+		return 0;
+	}
 
 	hw_config->driver_use_1 = SB_NO_MIDI | SB_NO_MIXER | SB_NO_RECORDING;
 
@@ -335,6 +324,7 @@ static void __init attach_trix_sb(struct address_info *hw_config)
 	sb_dsp_init(hw_config, THIS_MODULE);
 
 	sb_be_quiet = old_quiet;
+	return 1;
 }
 
 static int __init probe_trix_mpu(struct address_info *hw_config)
@@ -344,21 +334,6 @@ static int __init probe_trix_mpu(struct address_info *hw_config)
 		-1, -1, -1, 1, 2, 3, -1, 4, -1, 5
 	};
 
-	if (!kilroy_was_here)
-	{
-		DDB(printk("Trix: WSS and SB modes must be initialized before MPU\n"));
-		return 0;	/* AudioTrix Pro has not been detected earlier */
-	}
-	if (!sb_initialized)
-	{
-		DDB(printk("Trix: SB mode must be initialized before MPU\n"));
-		return 0;
-	}
-	if (mpu_initialized)
-	{
-		DDB(printk("Trix: MPU mode already initialized\n"));
-		return 0;
-	}
 	if (hw_config->irq > 9)
 	{
 		printk(KERN_ERR "AudioTrix: Bad MPU IRQ %d\n", hw_config->irq);
@@ -389,7 +364,6 @@ static int __init probe_trix_mpu(struct address_info *hw_config)
 
 	conf |= irq_bits[hw_config->irq] << 4;
 	trix_write(0x19, (trix_read(0x19) & 0x83) | conf);
-	mpu_initialized = 1;
 	hw_config->name = "AudioTrix Pro";
 	return probe_uart401(hw_config, THIS_MODULE);
 }
@@ -485,9 +459,16 @@ static int __init init_trix(void)
 		trix_boot_len = mod_firmware_load("/etc/sound/trxpro.bin",
 						    (char **) &trix_boot);
 	}
-	if (!probe_trix_wss(&cfg))
+
+	if (!request_region(0x390, 2, "AudioTrix")) {
+		printk(KERN_ERR "AudioTrix: Config port I/O conflict\n");
+		return -ENODEV;
+	}
+
+	if (!init_trix_wss(&cfg)) {
+		release_region(0x390, 2);
 		return -ENODEV;
-	attach_trix_wss(&cfg);
+	}
 
 	/*
 	 *    We must attach in the right order to get the firmware
@@ -496,8 +477,6 @@ static int __init init_trix(void)
 
 	if (cfg2.io_base != -1) {
 		sb = probe_trix_sb(&cfg2);
-		if (sb)
-			attach_trix_sb(&cfg2);
 	}
 	
 	if (cfg_mpu.io_base != -1)
diff --git a/sound/oss/v_midi.c b/sound/oss/v_midi.c
index 656c06366..077b76797 100644
--- a/sound/oss/v_midi.c
+++ b/sound/oss/v_midi.c
@@ -90,11 +90,12 @@ static void v_midi_close (int dev)
 static int v_midi_out (int dev, unsigned char midi_byte)
 {
 	vmidi_devc *devc = midi_devs[dev]->devc;
-	vmidi_devc *pdevc = midi_devs[devc->pair_mididev]->devc;
+	vmidi_devc *pdevc;
 
 	if (devc == NULL)
-		return -(ENXIO);
+		return -ENXIO;
 
+	pdevc = midi_devs[devc->pair_mididev]->devc;
 	if (pdevc->input_opened > 0){
 		if (MIDIbuf_avail(pdevc->my_mididev) > 500)
 			return 0;
diff --git a/sound/oss/waveartist.c b/sound/oss/waveartist.c
index 44ab69867..438e64ecb 100644
--- a/sound/oss/waveartist.c
+++ b/sound/oss/waveartist.c
@@ -1346,18 +1346,20 @@ static int __init probe_waveartist(struct address_info *hw_config)
 		return 0;
 	}
 
-	if (check_region(hw_config->io_base, 15))  {
+	if (!request_region(hw_config->io_base, 15, hw_config->name))  {
 		printk(KERN_WARNING "WaveArtist: I/O port conflict\n");
 		return 0;
 	}
 
 	if (hw_config->irq > 15 || hw_config->irq < 0) {
+		release_region(hw_config->io_base, 15);
 		printk(KERN_WARNING "WaveArtist: Bad IRQ %d\n",
 		       hw_config->irq);
 		return 0;
 	}
 
 	if (hw_config->dma != 3) {
+		release_region(hw_config->io_base, 15);
 		printk(KERN_WARNING "WaveArtist: Bad DMA %d\n",
 		       hw_config->dma);
 		return 0;
@@ -1392,8 +1394,6 @@ attach_waveartist(struct address_info *hw, const struct waveartist_mixer_info *m
 	if (hw->dma != hw->dma2 && hw->dma2 != NO_DMA)
 		devc->audio_flags |= DMA_DUPLEX;
 
-	request_region(hw->io_base, 15, devc->hw.name);
-
 	devc->mix = mix;
 	devc->dev_no = waveartist_init(devc);
 
diff --git a/sound/oss/wavfront.c b/sound/oss/wavfront.c
index e0ecd44a3..4875565a0 100644
--- a/sound/oss/wavfront.c
+++ b/sound/oss/wavfront.c
@@ -1402,7 +1402,7 @@ wavefront_fetch_multisample (wavefront_patch_info *header)
 	num_samples = (1 << log_ns[0]);
     
 	for (i = 0; i < num_samples; i++) {
-		char d[2];
+		s8 d[2];
 	
 		if ((d[0] = wavefront_read ()) == -1) {
 			printk (KERN_ERR LOGNAME "upload multisample failed "
@@ -2961,8 +2961,8 @@ wffx_memset (int page,
 		if (i != cnt) {
 			printk (KERN_WARNING LOGNAME
 				"FX memset "
-				"(0x%x, 0x%x, 0x%x, %d) incomplete\n",
-				page, addr, (int) data, cnt);
+				"(0x%x, 0x%x, %p, %d) incomplete\n",
+				page, addr, data, cnt);
 			return -(EIO);
 		}
 	}
diff --git a/sound/oss/wf_midi.c b/sound/oss/wf_midi.c
index 379e70f2c..3ced960e5 100644
--- a/sound/oss/wf_midi.c
+++ b/sound/oss/wf_midi.c
@@ -784,7 +784,7 @@ virtual_midi_disable (void)
 
 int __init detect_wf_mpu (int irq, int io_base)
 {
-	if (check_region (io_base, 2)) {
+	if (!request_region(io_base, 2, "wavefront midi")) {
 		printk (KERN_WARNING "WF-MPU: I/O port %x already in use.\n",
 			io_base);
 		return -1;
@@ -803,11 +803,10 @@ int __init install_wf_mpu (void)
 	if ((phys_dev->devno = sound_alloc_mididev()) < 0){
 
 		printk (KERN_ERR "WF-MPU: Too many MIDI devices detected.\n");
+		release_region(phys_dev->base, 2);
 		return -1;
-
 	}
 
-	request_region (phys_dev->base, 2, "wavefront midi");
 	phys_dev->isvirtual = 0;
 
 	if (config_wf_mpu (phys_dev)) {
diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c
index 423ab05c0..0c02a5f45 100644
--- a/sound/parisc/harmony.c
+++ b/sound/parisc/harmony.c
@@ -6,7 +6,7 @@
  *
  *	Harmony is found in HP 712s, 715/new and many other GSC based machines.
  *	On older 715 machines you'll find the technically identical chip 
- *	called 'Vivace'. Both Harmony and Vicace are supported by this driver.
+ *	called 'Vivace'. Both Harmony and Vivace are supported by this driver.
  *
  *  this ALSA driver is based on OSS driver by:
  *	Copyright 2000 (c) Linuxcare Canada, Alex deVries <alex@linuxcare.com>
@@ -43,7 +43,7 @@
  * to be recorded is put in RNXTADD. There is 2 read-only registers, PCURADD and 
  * RCURADD that provides adress of current page.
  * 
- * Harmony has no way to controll full duplex or half duplex mode. It means
+ * Harmony has no way to control full duplex or half duplex mode. It means
  * that we always need to provide adresses of playback and capture data, even
  * when this is not needed. That's why we statically alloc one graveyard
  * buffer (to put recorded data in play-only mode) and a silence buffer.
@@ -80,8 +80,7 @@
 MODULE_AUTHOR("Laurent Canet <canetl@esiee.fr>");
 MODULE_DESCRIPTION("ALSA Harmony sound driver");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ALSA,Harmony soundcard}}");
+MODULE_SUPPORTED_DEVICE("{{ALSA,Harmony soundcard}}");
 
 #undef DEBUG
 #ifdef DEBUG
@@ -138,13 +137,10 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Sun CS4231 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Sun CS4231 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Sun CS4231 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 
 /* Register offset (from base hpa) */
 #define REG_ID		0x00
@@ -216,7 +212,6 @@ typedef struct snd_card_harmony {
 	snd_pcm_substream_t *capture_substream;
 	snd_info_entry_t *proc_entry;
 } snd_card_harmony_t;
-#define chip_t snd_card_harmony_t
 
 static snd_card_t *snd_harmony_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
 
@@ -243,10 +238,8 @@ static unsigned int snd_card_harmony_rates[] = {
 	44100, 48000
 };
 
-#define RATES sizeof(snd_card_harmony_rates) / sizeof(snd_card_harmony_rates[0])
-
 static snd_pcm_hw_constraint_list_t hw_constraint_rates = {
-	.count = RATES,
+	.count = ARRAY_SIZE(snd_card_harmony_rates),
 	.list = snd_card_harmony_rates,
 	.mask = 0,
 };
@@ -283,7 +276,7 @@ static unsigned int snd_card_harmony_rate_bits(int rate)
 {
 	unsigned int idx;
 	
-	for (idx = 0; idx <= RATES; idx++)
+	for (idx = 0; idx <= ARRAY_SIZE(snd_card_harmony_rates); idx++)
 		if (snd_card_harmony_rates[idx] == rate)
 			return rate_bits[idx];
 	return HARMONY_SR_44KHZ; /* fallback */
@@ -556,7 +549,7 @@ static int snd_card_harmony_playback_prepare(snd_pcm_substream_t * substream)
 	harmony->sample_rate = snd_card_harmony_rate_bits(runtime->rate);
 
 	/* data format */
-	harmony->data_format = snd_harmony_set_data_format(haromny, runtime->format);
+	harmony->data_format = snd_harmony_set_data_format(harmony, runtime->format);
 
 	/* number of channels */
 	if (runtime->channels == 2)
@@ -587,7 +580,7 @@ static int snd_card_harmony_capture_prepare(snd_pcm_substream_t * substream)
 	harmony->sample_rate = snd_card_harmony_rate_bits(runtime->rate);
 	
 	/* data format */
-	harmony->data_format = snd_harmony_set_data_format(haromny, runtime->format);
+	harmony->data_format = snd_harmony_set_data_format(harmony, runtime->format);
 	
 	/* number of channels */
 	if (runtime->channels == 1)
@@ -751,6 +744,8 @@ static int snd_card_harmony_hw_params(snd_pcm_substream_t *substream,
 	int err;
 	
 	err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+	if (err > 0 && substream->dma_device.type == SNDRV_DMA_TYPE_CONTINUOUS)
+		substream->runtime->dma_addr = __pa(substream->runtime->dma_area);
 	DPRINTK(KERN_INFO PFX "HW Params returned %d, dma_addr %lx\n", err,
 			(unsigned long)substream->runtime->dma_addr);
 	return err;
@@ -784,7 +779,7 @@ static snd_pcm_ops_t snd_card_harmony_capture_ops = {
 	.pointer =		snd_card_harmony_capture_pointer,
 };
 
-static int snd_card_harmony_pcm_init(snd_card_harmony_t *harmony, int device)
+static int snd_card_harmony_pcm_init(snd_card_harmony_t *harmony)
 {
 	snd_pcm_t *pcm;
 	int err;
@@ -797,7 +792,7 @@ static int snd_card_harmony_pcm_init(snd_card_harmony_t *harmony, int device)
 	
 	snd_harmony_disable_interrupts(harmony);
 	
-   	if ((err = snd_pcm_new(harmony->card, "Harmony", device, 1, 1, &pcm)) < 0)
+   	if ((err = snd_pcm_new(harmony->card, "Harmony", 0, 1, 1, &pcm)) < 0)
 		return err;
 	
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_harmony_playback_ops);
@@ -811,28 +806,54 @@ static int snd_card_harmony_pcm_init(snd_card_harmony_t *harmony, int device)
 	/* initialize graveyard buffer */
 	harmony->dma_dev.type = SNDRV_DMA_TYPE_DEV;
 	harmony->dma_dev.dev = &harmony->pa_dev->dev;
-	err = snd_dma_alloc_pages(&harmony->dma_dev, HARMONY_BUF_SIZE*GRAVEYARD_BUFS,
+	err = snd_dma_alloc_pages(harmony->dma_dev.type,
+				  harmony->dma_dev.dev,
+				  HARMONY_BUF_SIZE*GRAVEYARD_BUFS,
 				  &harmony->graveyard_dma);
-	if (err < 0)
+	if (err == -ENOMEM) {
+		/* use continuous buffers */
+		harmony->dma_dev.type = SNDRV_DMA_TYPE_CONTINUOUS;
+		harmony->dma_dev.dev = snd_dma_continuous_data(GFP_KERNEL);
+		err = snd_dma_alloc_pages(harmony->dma_dev.type,
+					  harmony->dma_dev.dev,
+					  HARMONY_BUF_SIZE*GRAVEYARD_BUFS,
+					  &harmony->graveyard_dma);
+	}
+	if (err < 0) {
+		printk(KERN_ERR PFX "can't allocate graveyard buffer\n");
 		return err;
+	}
 	harmony->graveyard_count = 0;
 	
 	/* initialize silence buffers */
-	err = snd_dma_alloc_pages(&harmony->dma_dev, HARMONY_BUF_SIZE*SILENCE_BUFS,
+	err = snd_dma_alloc_pages(harmony->dma_dev.type,
+				  harmony->dma_dev.dev,
+				  HARMONY_BUF_SIZE*SILENCE_BUFS,
 				  &harmony->silence_dma);
-	if (err < 0)
+	if (err < 0) {
+		printk(KERN_ERR PFX "can't allocate silence buffer\n");
 		return err;
+	}
 	harmony->silence_count = 0;
 
+	if (harmony->dma_dev.type == SNDRV_DMA_TYPE_CONTINUOUS) {
+		harmony->graveyard_dma.addr = __pa(harmony->graveyard_dma.area);
+		harmony->silence_dma.addr = __pa(harmony->silence_dma.area);
+	}
+
 	harmony->ply_stopped = harmony->cap_stopped = 1;
 	
 	harmony->playback_substream = NULL;
 	harmony->capture_substream = NULL;
 	harmony->graveyard_count = 0;
-	
-	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-					      &harmony->pa_dev->dev,
-					      MAX_BUFFER_SIZE, MAX_BUFFER_SIZE);
+
+	err = snd_pcm_lib_preallocate_pages_for_all(pcm, harmony->dma_dev.type,
+						    harmony->dma_dev.dev,
+						    MAX_BUFFER_SIZE, MAX_BUFFER_SIZE);
+	if (err < 0) {
+		printk(KERN_ERR PFX "buffer allocation error %d\n", err);
+		// return err;
+	}
 
 	return 0;
 }
@@ -871,7 +892,7 @@ static int snd_harmony_mixercontrol_info(snd_kcontrol_t * kcontrol, snd_ctl_elem
  
 static int snd_harmony_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	snd_card_harmony_t *harmony = _snd_kcontrol_chip(kcontrol);
+	snd_card_harmony_t *harmony = snd_kcontrol_chip(kcontrol);
 	int shift_left = (kcontrol->private_value) & 0xff;
 	int shift_right = (kcontrol->private_value >> 8) & 0xff;
 	int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -896,7 +917,7 @@ static int snd_harmony_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
 
 static int snd_harmony_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	snd_card_harmony_t *harmony = _snd_kcontrol_chip(kcontrol);
+	snd_card_harmony_t *harmony = snd_kcontrol_chip(kcontrol);
 	int shift_left = (kcontrol->private_value) & 0xff;
 	int shift_right = (kcontrol->private_value >> 8) & 0xff;
 	int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -1037,7 +1058,7 @@ static int __init snd_card_harmony_probe(struct parisc_device *pa_dev)
 		snd_card_free(card);
 		return err;
 	}
-	if ((err = snd_card_harmony_pcm_init(chip, dev)) < 0) {
+	if ((err = snd_card_harmony_pcm_init(chip)) < 0) {
 		printk(KERN_ERR PFX "PCM Init failed\n");
 		snd_card_free(card);
 		return err;
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 9f922b029..e2ddc227c 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -22,6 +22,14 @@ config SND_ATIIXP
 	help
 	  Say 'Y' or 'M' to include support for ATI IXP 150/200/250/300 AC97 controller.
 
+config SND_ATIIXP_MODEM
+	tristate "ATI IXP 150/200/250 Modem"
+	depends on SND
+	select SND_AC97_CODEC
+	help
+	  Say 'Y' or 'M' to include support for ATI IXP 150/200/250 AC97 modem
+	  controller.
+
 config SND_AU8810
         tristate "Aureal Advantage"
         depends on SND
@@ -290,12 +298,12 @@ config SND_INTEL8X0
 	  SiS 7012, AMD768/8111, NVidia NForce and ALi 5455 chips.
 
 config SND_INTEL8X0M
-	tristate "Intel i8x0/MX440; AMD768/8111 modems (EXPERIMENTAL)"
+	tristate "Intel i8x0/MX440; SiS 7013; NForce; AMD768/8111 modems (EXPERIMENTAL)"
 	depends on SND && EXPERIMENTAL
 	select SND_AC97_CODEC
 	help
-	  Say 'Y' or 'M' to include support for Intel8x0 and AMD768/8111 based
-	  modems.
+	  Say 'Y' or 'M' to include support for Intel8x0, SiS 7013, NVidia NForce
+          and AMD768/8111 based modems.
 
 config SND_SONICVIBES
 	tristate "S3 SonicVibes"
diff --git a/sound/pci/Makefile b/sound/pci/Makefile
index cfef27722..f588cd687 100644
--- a/sound/pci/Makefile
+++ b/sound/pci/Makefile
@@ -5,6 +5,7 @@
 
 snd-als4000-objs := als4000.o
 snd-atiixp-objs := atiixp.o
+snd-atiixp-modem-objs := atiixp_modem.o
 snd-azt3328-objs := azt3328.o
 snd-bt87x-objs := bt87x.o
 snd-cmipci-objs := cmipci.o
@@ -25,6 +26,7 @@ snd-via82xx-objs := via82xx.o
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_ALS4000) += snd-als4000.o
 obj-$(CONFIG_SND_ATIIXP) += snd-atiixp.o
+obj-$(CONFIG_SND_ATIIXP_MODEM) += snd-atiixp-modem.o
 obj-$(CONFIG_SND_AZT3328) += snd-azt3328.o
 obj-$(CONFIG_SND_BT87X) += snd-bt87x.o
 obj-$(CONFIG_SND_CMIPCI) += snd-cmipci.o
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 8f43dd60d..b88a1989e 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -45,9 +45,6 @@ static int enable_loopback;
 
 module_param(enable_loopback, bool, 0444);
 MODULE_PARM_DESC(enable_loopback, "Enable AC97 ADC/DAC Loopback Control");
-MODULE_PARM_SYNTAX(enable_loopback, SNDRV_BOOLEAN_FALSE_DESC);
-
-#define chip_t ac97_t
 
 /*
 
@@ -108,12 +105,13 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
 { 0x41445375, 0xffffffff, "AD1985",		patch_ad1985,	NULL },
 { 0x414c4300, 0xffffff00, "ALC100/100P", 	NULL,		NULL },
 { 0x414c4710, 0xfffffff0, "ALC200/200P",	NULL,		NULL },
+{ 0x414c4721, 0xffffffff, "ALC650D",		NULL,	NULL }, /* already patched */
+{ 0x414c4722, 0xffffffff, "ALC650E",		NULL,	NULL }, /* already patched */
+{ 0x414c4723, 0xffffffff, "ALC650F",		NULL,	NULL }, /* already patched */
 { 0x414c4720, 0xfffffff0, "ALC650",		patch_alc650,	NULL },
-{ 0x414c4721, 0xfffffff0, "ALC650D",		patch_alc650,	NULL },
-{ 0x414c4722, 0xfffffff0, "ALC650E",		patch_alc650,	NULL },
-{ 0x414c4723, 0xfffffff0, "ALC650F",		patch_alc650,	NULL },
 { 0x414c4760, 0xfffffff0, "ALC655",		patch_alc655,	NULL },
 { 0x414c4780, 0xfffffff0, "ALC658",		patch_alc655,	NULL },
+{ 0x414c4790, 0xfffffff0, "ALC850",		patch_alc850,	NULL },
 { 0x414c4730, 0xffffffff, "ALC101",		NULL,		NULL },
 { 0x414c4740, 0xfffffff0, "ALC202",		NULL,		NULL },
 { 0x414c4750, 0xfffffff0, "ALC250",		NULL,		NULL },
@@ -213,6 +211,13 @@ const char *snd_ac97_stereo_enhancements[] =
   /*  31 */ "Reserved 31"
 };
 
+/*
+ * Shared AC97 controllers (ICH, ATIIXP...)
+ */
+static DECLARE_MUTEX(shared_codec_mutex);
+static ac97_t *shared_codec[AC97_SHARED_TYPES][4];
+
+
 /*
  *  I/O routines
  */
@@ -274,12 +279,12 @@ void snd_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short value)
 {
 	if (!snd_ac97_valid_reg(ac97, reg))
 		return;
-	if ((ac97->id & 0xffffff00) == 0x414c4300) {
+	if ((ac97->id & 0xffffff00) == AC97_ID_ALC100) {
 		/* Fix H/W bug of ALC100/100P */
 		if (reg == AC97_MASTER || reg == AC97_HEADPHONE)
-			ac97->bus->write(ac97, AC97_RESET, 0);	/* reset audio codec */
+			ac97->bus->ops->write(ac97, AC97_RESET, 0);	/* reset audio codec */
 	}
-	ac97->bus->write(ac97, reg, value);
+	ac97->bus->ops->write(ac97, reg, value);
 }
 
 /**
@@ -297,14 +302,14 @@ unsigned short snd_ac97_read(ac97_t *ac97, unsigned short reg)
 {
 	if (!snd_ac97_valid_reg(ac97, reg))
 		return 0;
-	return ac97->bus->read(ac97, reg);
+	return ac97->bus->ops->read(ac97, reg);
 }
 
 /* read a register - return the cached value if already read */
 static inline unsigned short snd_ac97_read_cache(ac97_t *ac97, unsigned short reg)
 {
 	if (! test_bit(reg, ac97->reg_accessed)) {
-		ac97->regs[reg] = ac97->bus->read(ac97, reg);
+		ac97->regs[reg] = ac97->bus->ops->read(ac97, reg);
 		// set_bit(reg, ac97->reg_accessed);
 	}
 	return ac97->regs[reg];
@@ -327,7 +332,7 @@ void snd_ac97_write_cache(ac97_t *ac97, unsigned short reg, unsigned short value
 	spin_lock(&ac97->reg_lock);
 	ac97->regs[reg] = value;
 	spin_unlock(&ac97->reg_lock);
-	ac97->bus->write(ac97, reg, value);
+	ac97->bus->ops->write(ac97, reg, value);
 	set_bit(reg, ac97->reg_accessed);
 }
 
@@ -354,7 +359,7 @@ int snd_ac97_update(ac97_t *ac97, unsigned short reg, unsigned short value)
 	if (change) {
 		ac97->regs[reg] = value;
 		spin_unlock(&ac97->reg_lock);
-		ac97->bus->write(ac97, reg, value);
+		ac97->bus->ops->write(ac97, reg, value);
 	} else
 		spin_unlock(&ac97->reg_lock);
 	return change;
@@ -387,7 +392,7 @@ int snd_ac97_update_bits(ac97_t *ac97, unsigned short reg, unsigned short mask,
 	if (change) {
 		ac97->regs[reg] = new;
 		spin_unlock(&ac97->reg_lock);
-		ac97->bus->write(ac97, reg, new);
+		ac97->bus->ops->write(ac97, reg, new);
 	} else
 		spin_unlock(&ac97->reg_lock);
 	return change;
@@ -398,7 +403,7 @@ static int snd_ac97_ad18xx_update_pcm_bits(ac97_t *ac97, int codec, unsigned sho
 	int change;
 	unsigned short old, new, cfg;
 
-	down(&ac97->spec.ad18xx.mutex);
+	down(&ac97->mutex);
 	spin_lock(&ac97->reg_lock);
 	old = ac97->spec.ad18xx.pcmreg[codec];
 	new = (old & ~mask) | value;
@@ -408,17 +413,17 @@ static int snd_ac97_ad18xx_update_pcm_bits(ac97_t *ac97, int codec, unsigned sho
 		ac97->spec.ad18xx.pcmreg[codec] = new;
 		spin_unlock(&ac97->reg_lock);
 		/* select single codec */
-		ac97->bus->write(ac97, AC97_AD_SERIAL_CFG,
+		ac97->bus->ops->write(ac97, AC97_AD_SERIAL_CFG,
 				 (cfg & ~0x7000) |
 				 ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]);
 		/* update PCM bits */
-		ac97->bus->write(ac97, AC97_PCM, new);
+		ac97->bus->ops->write(ac97, AC97_PCM, new);
 		/* select all codecs */
-		ac97->bus->write(ac97, AC97_AD_SERIAL_CFG,
+		ac97->bus->ops->write(ac97, AC97_AD_SERIAL_CFG,
 				 cfg | 0x7000);
 	} else
 		spin_unlock(&ac97->reg_lock);
-	up(&ac97->spec.ad18xx.mutex);
+	up(&ac97->mutex);
 	return change;
 }
 
@@ -545,7 +550,7 @@ int snd_ac97_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontr
 	int reg = kcontrol->private_value & 0xff;
 	int shift = (kcontrol->private_value >> 8) & 0xff;
 	int mask = (kcontrol->private_value >> 16) & 0xff;
-	int invert = (kcontrol->private_value >> 24) & 0xff;
+	int invert = (kcontrol->private_value >> 24) & 0x01;
 	
 	ucontrol->value.integer.value[0] = (snd_ac97_read_cache(ac97, reg) >> shift) & mask;
 	if (invert)
@@ -559,7 +564,7 @@ int snd_ac97_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontr
 	int reg = kcontrol->private_value & 0xff;
 	int shift = (kcontrol->private_value >> 8) & 0xff;
 	int mask = (kcontrol->private_value >> 16) & 0xff;
-	int invert = (kcontrol->private_value >> 24) & 0xff;
+	int invert = (kcontrol->private_value >> 24) & 0x01;
 	unsigned short val;
 	
 	val = (ucontrol->value.integer.value[0] & mask);
@@ -625,6 +630,40 @@ static int snd_ac97_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
 				    (val1 << shift_left) | (val2 << shift_right));
 }
 
+int snd_ac97_getput_page(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol,
+			 int (*func)(snd_kcontrol_t *, snd_ctl_elem_value_t *))
+{
+	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+	int reg = kcontrol->private_value & 0xff;
+	int err;
+
+	if ((ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23 &&
+	    (reg >= 0x60 && reg < 0x70)) {
+		unsigned short page_save;
+		unsigned short page = (kcontrol->private_value >> 25) & 0x0f;
+		down(&ac97->mutex); /* lock paging */
+		page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
+		snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page);
+		err = func(kcontrol, ucontrol);
+		snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save);
+		up(&ac97->mutex); /* unlock paging */
+	} else
+		err = func(kcontrol, ucontrol);
+	return err;
+}
+
+/* for rev2.3 paging */
+int snd_ac97_page_get_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	return snd_ac97_getput_page(kcontrol, ucontrol, snd_ac97_get_single);
+}
+
+/* for rev2.3 paging */
+int snd_ac97_page_put_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	return snd_ac97_getput_page(kcontrol, ucontrol, snd_ac97_put_single);
+}
+
 static const snd_kcontrol_new_t snd_ac97_controls_master_mono[2] = {
 AC97_SINGLE("Master Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1),
 AC97_SINGLE("Master Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1)
@@ -1009,14 +1048,14 @@ static int snd_ac97_bus_free(ac97_bus_t *bus)
 			kfree(bus->pcms);
 		if (bus->private_free)
 			bus->private_free(bus);
-		snd_magic_kfree(bus);
+		kfree(bus);
 	}
 	return 0;
 }
 
 static int snd_ac97_bus_dev_free(snd_device_t *device)
 {
-	ac97_bus_t *bus = snd_magic_cast(ac97_bus_t, device->device_data, return -ENXIO);
+	ac97_bus_t *bus = device->device_data;
 	return snd_ac97_bus_free(bus);
 }
 
@@ -1024,18 +1063,24 @@ static int snd_ac97_free(ac97_t *ac97)
 {
 	if (ac97) {
 		snd_ac97_proc_done(ac97);
-		if (ac97->bus)
+		if (ac97->bus) {
 			ac97->bus->codec[ac97->num] = NULL;
+			if (ac97->bus->shared_type) {
+				down(&shared_codec_mutex);
+				shared_codec[ac97->bus->shared_type-1][ac97->num] = NULL;
+				up(&shared_codec_mutex);
+			}
+		}
 		if (ac97->private_free)
 			ac97->private_free(ac97);
-		snd_magic_kfree(ac97);
+		kfree(ac97);
 	}
 	return 0;
 }
 
 static int snd_ac97_dev_free(snd_device_t *device)
 {
-	ac97_t *ac97 = snd_magic_cast(ac97_t, device->device_data, return -ENXIO);
+	ac97_t *ac97 = device->device_data;
 	snd_ac97_powerdown(ac97); /* for avoiding click noises during shut down */
 	return snd_ac97_free(ac97);
 }
@@ -1120,6 +1165,7 @@ static void snd_ac97_change_volume_params1(ac97_t * ac97, int reg, unsigned char
 	snd_ac97_write_cache(ac97, reg, 0x8000);
 }
 
+/* check the volume resolution of center/lfe */
 static void snd_ac97_change_volume_params2(ac97_t * ac97, int reg, int shift, unsigned char *max)
 {
 	unsigned short val, val1;
@@ -1135,6 +1181,7 @@ static void snd_ac97_change_volume_params2(ac97_t * ac97, int reg, int shift, un
 	snd_ac97_write_cache(ac97, reg, 0x8080);
 }
 
+/* check whether the volume resolution is 4 or 5 bits */
 static void snd_ac97_change_volume_params3(ac97_t * ac97, int reg, unsigned char *max)
 {
 	unsigned short val, val1;
@@ -1150,6 +1197,18 @@ static void snd_ac97_change_volume_params3(ac97_t * ac97, int reg, unsigned char
 	snd_ac97_write_cache(ac97, reg, 0x8000);
 }
 
+/* check whether the volume is mono or stereo */
+static int snd_ac97_is_stereo_vol(ac97_t *ac97, int reg)
+{
+	unsigned short val, val1, val2;
+	val = snd_ac97_read(ac97, reg);
+	val1 = val | 0x8000 | (0x01 << 8);
+	snd_ac97_write(ac97, reg, val1);
+	val2 = snd_ac97_read(ac97, reg);
+	snd_ac97_write(ac97, reg, val); /* restore */
+	return val1 == val2;
+}
+
 static inline int printable(unsigned int x)
 {
 	x &= 0xff;
@@ -1178,6 +1237,9 @@ static int snd_ac97_cmute_new(snd_card_t *card, char *name, int reg, ac97_t *ac9
 	snd_kcontrol_t *kctl;
 	int stereo = 0;
 
+	if (! snd_ac97_valid_reg(ac97, reg))
+		return 0;
+
 	if (ac97->flags & AC97_STEREO_MUTES) {
 		/* check whether both mute bits work */
 		unsigned short val, val1;
@@ -1208,6 +1270,9 @@ static int snd_ac97_cvol_new(snd_card_t *card, char *name, int reg, unsigned int
 	int err;
 	snd_kcontrol_new_t tmp = AC97_DOUBLE(name, reg, 8, 0, (unsigned int)max, 1);
 	tmp.index = ac97->num;
+
+	if (! snd_ac97_valid_reg(ac97, reg))
+		return 0;
 	if ((err = snd_ctl_add(card, snd_ctl_new1(&tmp, ac97))) < 0)
 		return err;
 	snd_ac97_write_cache(ac97, reg,
@@ -1225,6 +1290,9 @@ static int snd_ac97_cmix_new(snd_card_t *card, const char *pfx, int reg, int che
 	char name[44];
 	unsigned char max;
 
+	if (! snd_ac97_valid_reg(ac97, reg))
+		return 0;
+
 	sprintf(name, "%s Switch", pfx);
 	if ((err = snd_ac97_cmute_new(card, name, reg, ac97)) < 0)
 		return err;
@@ -1239,6 +1307,8 @@ static int snd_ac97_cmix_new(snd_card_t *card, const char *pfx, int reg, int che
 }
 
 
+static unsigned int snd_ac97_determine_spdif_rates(ac97_t *ac97);
+
 static int snd_ac97_mixer_build(ac97_t * ac97)
 {
 	snd_card_t *card = ac97->bus->card;
@@ -1293,11 +1363,8 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
 	}
 
 	/* build headphone controls */
-	if (snd_ac97_try_volume_mix(ac97, AC97_HEADPHONE) || ac97->id == AC97_ID_STAC9708) {
-		const char *name = ac97->id == AC97_ID_STAC9708 ? 
-			"Sigmatel Surround Playback" :
-			"Headphone Playback";
-		if ((err = snd_ac97_cmix_new(card, name, AC97_HEADPHONE, 1, ac97)) < 0)
+	if (snd_ac97_try_volume_mix(ac97, AC97_HEADPHONE)) {
+		if ((err = snd_ac97_cmix_new(card, "Headphone Playback", AC97_HEADPHONE, 1, ac97)) < 0)
 			return err;
 	}
 	
@@ -1332,7 +1399,8 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
 		for (idx = 0; idx < 2; idx++)
 			if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97))) < 0)
 				return err;
-		snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x801e);
+		snd_ac97_write_cache(ac97, AC97_PC_BEEP,
+				     snd_ac97_read(ac97, AC97_PC_BEEP) | 0x801e);
 	}
 	
 	/* build Phone controls */
@@ -1349,15 +1417,26 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
 	
 	/* build MIC controls */
 	snd_ac97_change_volume_params3(ac97, AC97_MIC, &max);
-	for (idx = 0; idx < 3; idx++) {
-		if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_mic[idx], ac97))) < 0)
+	if (snd_ac97_is_stereo_vol(ac97, AC97_MIC)) {
+		/* build stereo mic */
+		if ((err = snd_ac97_cmute_new(card, "Mic Playback Switch", AC97_MIC, ac97)) < 0)
 			return err;
-		if (idx == 1) {		// volume
-			kctl->private_value &= ~(0xff << 16);
-			kctl->private_value |= (int)max << 16;
+		if ((err = snd_ac97_cvol_new(card, "Mic Playback Volume", AC97_MIC, max, ac97)) < 0)
+			return err;
+		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic[2], ac97))) < 0)
+			return err;
+	} else {
+		/* build mono mic */
+		for (idx = 0; idx < 3; idx++) {
+			if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_mic[idx], ac97))) < 0)
+				return err;
+			if (idx == 1) {		// volume
+				kctl->private_value &= ~(0xff << 16);
+				kctl->private_value |= (int)max << 16;
+			}
 		}
+		snd_ac97_write_cache(ac97, AC97_MIC, 0x8000 | max);
 	}
-	snd_ac97_write_cache(ac97, AC97_MIC, 0x8000 | max);
 
 	/* build Line controls */
 	if ((err = snd_ac97_cmix_new(card, "Line Playback", AC97_LINE, 0, ac97)) < 0)
@@ -1410,9 +1489,7 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
 		if ((err = snd_ac97_cmute_new(card, "PCM Playback Switch", AC97_PCM, ac97)) < 0)
 			return err;
 		/* FIXME: C-Media chips have no PCM volume!! */
-		if (/*ac97->id == 0x434d4941 ||*/
-		    ac97->id == 0x434d4942 ||
-		    ac97->id == 0x434d4961)
+		if (ac97->id == AC97_ID_CM9739)
 			snd_ac97_write_cache(ac97, AC97_PCM, 0x9f1f);
 		else {
 			if ((err = snd_ac97_cvol_new(card, "PCM Playback Volume", AC97_PCM, 31, ac97)) < 0)
@@ -1423,8 +1500,10 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
 	/* build Capture controls */
 	if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_src, ac97))) < 0)
 		return err;
-	if ((err = snd_ac97_cmute_new(card, "Capture Switch", AC97_REC_GAIN, ac97)) < 0)
-		return err;
+	if (snd_ac97_try_bit(ac97, AC97_REC_GAIN, 15)) {
+		if ((err = snd_ac97_cmute_new(card, "Capture Switch", AC97_REC_GAIN, ac97)) < 0)
+			return err;
+	}
 	if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_vol, ac97))) < 0)
 		return err;
 	snd_ac97_write_cache(ac97, AC97_REC_SEL, 0x0000);
@@ -1520,6 +1599,7 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
 			/* set default PCM S/PDIF params */
 			/* consumer,PCM audio,no copyright,no preemphasis,PCM coder,original,48000Hz */
 			snd_ac97_write_cache(ac97, AC97_SPDIF, 0x2a20);
+			ac97->rates[AC97_RATES_SPDIF] = snd_ac97_determine_spdif_rates(ac97);
 		}
 		ac97->spdif_status = SNDRV_PCM_DEFAULT_CON_SPDIF;
 	}
@@ -1672,10 +1752,10 @@ static int ac97_reset_wait(ac97_t *ac97, int timeout, int with_modem)
 		 */
 		/* test if we can write to the record gain volume register */
 		snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a05);
-		if (snd_ac97_read(ac97, AC97_REC_GAIN) == 0x8a05)
+		if ((snd_ac97_read(ac97, AC97_REC_GAIN) & 0x7fff) == 0x0a05)
 			return 0;
 		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ/100);
+		schedule_timeout(1);
 	} while (time_after_eq(end_time, jiffies));
 	return -ENODEV;
 }
@@ -1683,45 +1763,47 @@ static int ac97_reset_wait(ac97_t *ac97, int timeout, int with_modem)
 /**
  * snd_ac97_bus - create an AC97 bus component
  * @card: the card instance
- * @_bus: the template of AC97 bus, callbacks and
- *         the private data.
+ * @num: the bus number
+ * @ops: the bus callbacks table
+ * @private_data: private data pointer for the new instance
  * @rbus: the pointer to store the new AC97 bus instance.
  *
  * Creates an AC97 bus component.  An ac97_bus_t instance is newly
- * allocated and initialized from the template (_bus).
+ * allocated and initialized.
  *
- * The template must include the valid callbacks (at least read and
- * write), the bus number (num), and the private data (private_data).
- * The other callbacks, wait and reset, are not mandatory.
+ * The ops table must include valid callbacks (at least read and
+ * write).  The other callbacks, wait and reset, are not mandatory.
  * 
  * The clock is set to 48000.  If another clock is needed, set
- * bus->clock manually.
+ * (*rbus)->clock manually.
  *
  * The AC97 bus instance is registered as a low-level device, so you don't
  * have to release it manually.
  *
  * Returns zero if successful, or a negative error code on failure.
  */
-int snd_ac97_bus(snd_card_t * card, ac97_bus_t * _bus, ac97_bus_t ** rbus)
+int snd_ac97_bus(snd_card_t *card, int num, ac97_bus_ops_t *ops,
+		 void *private_data, ac97_bus_t **rbus)
 {
 	int err;
 	ac97_bus_t *bus;
-	static snd_device_ops_t ops = {
+	static snd_device_ops_t dev_ops = {
 		.dev_free =	snd_ac97_bus_dev_free,
 	};
 
 	snd_assert(card != NULL, return -EINVAL);
-	snd_assert(_bus != NULL && rbus != NULL, return -EINVAL);
-	bus = snd_magic_kmalloc(ac97_bus_t, 0, GFP_KERNEL);
+	snd_assert(rbus != NULL, return -EINVAL);
+	bus = kcalloc(1, sizeof(*bus), GFP_KERNEL);
 	if (bus == NULL)
 		return -ENOMEM;
-	*bus = *_bus;
 	bus->card = card;
-	if (bus->clock == 0)
-		bus->clock = 48000;
+	bus->num = num;
+	bus->ops = ops;
+	bus->private_data = private_data;
+	bus->clock = 48000;
 	spin_lock_init(&bus->bus_lock);
 	snd_ac97_bus_proc_init(bus);
-	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, bus, &ops)) < 0) {
+	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, bus, &dev_ops)) < 0) {
 		snd_ac97_bus_free(bus);
 		return err;
 	}
@@ -1732,25 +1814,23 @@ int snd_ac97_bus(snd_card_t * card, ac97_bus_t * _bus, ac97_bus_t ** rbus)
 /**
  * snd_ac97_mixer - create an Codec97 component
  * @bus: the AC97 bus which codec is attached to
- * @_ac97: the template of ac97, including index, callbacks and
+ * @template: the template of ac97, including index, callbacks and
  *         the private data.
  * @rac97: the pointer to store the new ac97 instance.
  *
  * Creates an Codec97 component.  An ac97_t instance is newly
- * allocated and initialized from the template (_ac97).  The codec
+ * allocated and initialized from the template.  The codec
  * is then initialized by the standard procedure.
  *
- * The template must include the valid callbacks (at least read and
- * write), the codec number (num) and address (addr), and the private
- * data (private_data).  The other callbacks, wait and reset, are not
- * mandatory.
+ * The template must include the codec number (num) and address (addr),
+ * and the private data (private_data).
  * 
  * The ac97 instance is registered as a low-level device, so you don't
  * have to release it manually.
  *
  * Returns zero if successful, or a negative error code on failure.
  */
-int snd_ac97_mixer(ac97_bus_t * bus, ac97_t * _ac97, ac97_t ** rac97)
+int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
 {
 	int err;
 	ac97_t *ac97;
@@ -1764,33 +1844,63 @@ int snd_ac97_mixer(ac97_bus_t * bus, ac97_t * _ac97, ac97_t ** rac97)
 
 	snd_assert(rac97 != NULL, return -EINVAL);
 	*rac97 = NULL;
-	snd_assert(bus != NULL && _ac97 != NULL, return -EINVAL);
-	snd_assert(_ac97->num < 4 && bus->codec[_ac97->num] == NULL, return -EINVAL);
+	snd_assert(bus != NULL && template != NULL, return -EINVAL);
+	snd_assert(template->num < 4 && bus->codec[template->num] == NULL, return -EINVAL);
+
+	snd_assert(bus->shared_type <= AC97_SHARED_TYPES, return -EINVAL);
+	if (bus->shared_type) {
+		/* already shared? */
+		down(&shared_codec_mutex);
+		ac97 = shared_codec[bus->shared_type-1][template->num];
+		if (ac97) {
+			if ((ac97_is_audio(ac97) && (template->scaps & AC97_SCAP_SKIP_AUDIO)) ||
+			    (ac97_is_modem(ac97) && (template->scaps & AC97_SCAP_SKIP_MODEM))) {
+				up(&shared_codec_mutex);
+				return -EACCES; /* skip this */
+			}
+		}
+		up(&shared_codec_mutex);
+	}
+
 	card = bus->card;
-	ac97 = snd_magic_kmalloc(ac97_t, 0, GFP_KERNEL);
+	ac97 = kcalloc(1, sizeof(*ac97), GFP_KERNEL);
 	if (ac97 == NULL)
 		return -ENOMEM;
-	*ac97 = *_ac97;
+	ac97->private_data = template->private_data;
+	ac97->private_free = template->private_free;
 	ac97->bus = bus;
+	ac97->pci = template->pci;
+	ac97->num = template->num;
+	ac97->addr = template->addr;
+	ac97->scaps = template->scaps;
+	ac97->limited_regs = template->limited_regs;
+	memcpy(ac97->reg_accessed, template->reg_accessed, sizeof(ac97->reg_accessed));
 	bus->codec[ac97->num] = ac97;
 	spin_lock_init(&ac97->reg_lock);
+	init_MUTEX(&ac97->mutex);
 
 	if (ac97->pci) {
 		pci_read_config_word(ac97->pci, PCI_SUBSYSTEM_VENDOR_ID, &ac97->subsystem_vendor);
 		pci_read_config_word(ac97->pci, PCI_SUBSYSTEM_ID, &ac97->subsystem_device);
 	}
-	if (bus->reset) {
-		bus->reset(ac97);
+	if (bus->ops->reset) {
+		bus->ops->reset(ac97);
 		goto __access_ok;
 	}
 
 	snd_ac97_write(ac97, AC97_RESET, 0);	/* reset to defaults */
-	if (bus->wait)
-		bus->wait(ac97);
+	if (bus->ops->wait)
+		bus->ops->wait(ac97);
 	else {
 		udelay(50);
-		if (ac97_reset_wait(ac97, HZ/2, 0) < 0 &&
-		    ac97_reset_wait(ac97, HZ/2, 1) < 0) {
+		if (ac97->scaps & AC97_SCAP_SKIP_AUDIO)
+			err = ac97_reset_wait(ac97, HZ/2, 1);
+		else {
+			err = ac97_reset_wait(ac97, HZ/2, 0);
+			if (err < 0)
+				err = ac97_reset_wait(ac97, HZ/2, 1);
+		}
+		if (err < 0) {
 			snd_printk(KERN_WARNING "AC'97 %d does not respond - RESET\n", ac97->num);
 			/* proceed anyway - it's often non-critical */
 		}
@@ -1803,26 +1913,12 @@ int snd_ac97_mixer(ac97_bus_t * bus, ac97_t * _ac97, ac97_t ** rac97)
 		snd_ac97_free(ac97);
 		return -EIO;
 	}
-	/* AC97 audio codec chip revision detection. */
-	/* Currently only Realtek ALC650 detection implemented. */
-	switch(ac97->id & 0xfffffff0) {
-	case 0x414c4720:        /* ALC650 */
-		reg = snd_ac97_read(ac97, AC97_ALC650_REVISION);
-		if (((reg & 0x3f) >= 0) && ((reg & 0x3f) < 3))
-			ac97->id = 0x414c4720;          /* Old version */
-		else if (((reg & 0x3f) >= 3) && ((reg & 0x3f) < 0x10))
-			ac97->id = 0x414c4721;          /* D version */
-		else if ((reg&0x30) == 0x10)
-			ac97->id = 0x414c4722;          /* E version */
-		else if ((reg&0x30) == 0x20)
-			ac97->id = 0x414c4723;          /* F version */
-        }
 	
 	/* test for AC'97 */
 	if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO) && !(ac97->scaps & AC97_SCAP_AUDIO)) {
 		/* test if we can write to the record gain volume register */
 		snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a06);
-		if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a06)
+		if (((err = snd_ac97_read(ac97, AC97_REC_GAIN)) & 0x7fff) == 0x0a06)
 			ac97->scaps |= AC97_SCAP_AUDIO;
 	}
 	if (ac97->scaps & AC97_SCAP_AUDIO) {
@@ -1848,7 +1944,7 @@ int snd_ac97_mixer(ac97_bus_t * bus, ac97_t * _ac97, ac97_t ** rac97)
 		return -EACCES;
 	}
 
-	if (bus->reset) // FIXME: always skipping?
+	if (bus->ops->reset) // FIXME: always skipping?
 		goto __ready_ok;
 
 	/* FIXME: add powerdown control */
@@ -1865,9 +1961,9 @@ int snd_ac97_mixer(ac97_bus_t * bus, ac97_t * _ac97, ac97_t ** rac97)
 			if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f)
 				goto __ready_ok;
 			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout(HZ/10);
+			schedule_timeout(1);
 		} while (time_after_eq(end_time, jiffies));
-		snd_printk(KERN_ERR "AC'97 %d analog subsections not ready\n", ac97->num);
+		snd_printk(KERN_WARNING "AC'97 %d analog subsections not ready\n", ac97->num);
 	}
 
 	/* FIXME: add powerdown control */
@@ -1898,9 +1994,9 @@ int snd_ac97_mixer(ac97_bus_t * bus, ac97_t * _ac97, ac97_t ** rac97)
 			if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp)
 				goto __ready_ok;
 			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout(HZ/10);
+			schedule_timeout(1);
 		} while (time_after_eq(end_time, jiffies));
-		snd_printk(KERN_ERR "MC'97 %d converters and GPIO not ready (0x%x)\n", ac97->num, snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS));
+		snd_printk(KERN_WARNING "MC'97 %d converters and GPIO not ready (0x%x)\n", ac97->num, snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS));
 	}
 	
       __ready_ok:
@@ -1919,12 +2015,7 @@ int snd_ac97_mixer(ac97_bus_t * bus, ac97_t * _ac97, ac97_t ** rac97)
 	}
 	if (ac97->ext_id & AC97_EI_SPDIF) {
 		/* codec specific code (patch) should override these values */
-		if (ac97->flags & AC97_CS_SPDIF)
-			ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100;
-		else if (ac97->id == AC97_ID_CM9739)
-			ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000;
-		else
-			ac97->rates[AC97_RATES_SPDIF] = snd_ac97_determine_spdif_rates(ac97);
+		ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_32000;
 	}
 	if (ac97->ext_id & AC97_EI_VRM) {	/* MIC VRA support */
 		snd_ac97_determine_rates(ac97, AC97_PCM_MIC_ADC_RATE, 0, &ac97->rates[AC97_RATES_MIC_ADC]);
@@ -1940,10 +2031,10 @@ int snd_ac97_mixer(ac97_bus_t * bus, ac97_t * _ac97, ac97_t ** rac97)
 		ac97->scaps |= AC97_SCAP_CENTER_LFE_DAC;
 	}
 	/* additional initializations */
-	if (bus->init)
-		bus->init(ac97);
-	snd_ac97_get_name(ac97, ac97->id, name, 0);
-	snd_ac97_get_name(NULL, ac97->id, name, 0);  // ac97->id might be changed in the special setup code
+	if (bus->ops->init)
+		bus->ops->init(ac97);
+	snd_ac97_get_name(ac97, ac97->id, name, !ac97_is_audio(ac97));
+	snd_ac97_get_name(NULL, ac97->id, name, !ac97_is_audio(ac97));  // ac97->id might be changed in the special setup code
 	if (ac97_is_audio(ac97)) {
 		if (card->mixername[0] == '\0') {
 			strcpy(card->mixername, name);
@@ -1995,6 +2086,13 @@ int snd_ac97_mixer(ac97_bus_t * bus, ac97_t * _ac97, ac97_t ** rac97)
 		return err;
 	}
 	*rac97 = ac97;
+
+	if (bus->shared_type) {
+		down(&shared_codec_mutex);
+		shared_codec[bus->shared_type-1][ac97->num] = ac97;
+		up(&shared_codec_mutex);
+	}
+
 	return 0;
 }
 
@@ -2054,8 +2152,8 @@ void snd_ac97_resume(ac97_t *ac97)
 {
 	int i, is_ad18xx, codec;
 
-	if (ac97->bus->reset) {
-		ac97->bus->reset(ac97);
+	if (ac97->bus->ops->reset) {
+		ac97->bus->ops->reset(ac97);
 		goto  __reset_ready;
 	}
 
@@ -2066,23 +2164,33 @@ void snd_ac97_resume(ac97_t *ac97)
 	snd_ac97_write(ac97, AC97_GENERAL_PURPOSE, 0);
 
 	snd_ac97_write(ac97, AC97_POWERDOWN, ac97->regs[AC97_POWERDOWN]);
-	ac97->bus->write(ac97, AC97_MASTER, 0x8101);
-	for (i = 0; i < 10; i++) {
-		if (snd_ac97_read(ac97, AC97_MASTER) == 0x8101)
-			break;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(1);
-	}
-	/* FIXME: extra delay */
-	ac97->bus->write(ac97, AC97_MASTER, 0x8000);
-	if (snd_ac97_read(ac97, AC97_MASTER) != 0x8000) {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ/4);
+	if (ac97_is_audio(ac97)) {
+		ac97->bus->ops->write(ac97, AC97_MASTER, 0x8101);
+		for (i = HZ/10; i >= 0; i--) {
+			if (snd_ac97_read(ac97, AC97_MASTER) == 0x8101)
+				break;
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(1);
+		}
+		/* FIXME: extra delay */
+		ac97->bus->ops->write(ac97, AC97_MASTER, 0x8000);
+		if (snd_ac97_read(ac97, AC97_MASTER) != 0x8000) {
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(HZ/4);
+		}
+	} else {
+		for (i = HZ/10; i >= 0; i--) {
+			unsigned short val = snd_ac97_read(ac97, AC97_EXTENDED_MID);
+			if (val != 0xffff && (val & 1) != 0)
+				break;
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(1);
+		}
 	}
 __reset_ready:
 
-	if (ac97->bus->init)
-		ac97->bus->init(ac97);
+	if (ac97->bus->ops->init)
+		ac97->bus->ops->init(ac97);
 
 	is_ad18xx = (ac97->flags & AC97_AD_MULTI);
 	if (is_ad18xx) {
@@ -2093,7 +2201,7 @@ __reset_ready:
 			/* select single codec */
 			snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
 					     ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]);
-			ac97->bus->write(ac97, AC97_AD_CODEC_CFG, ac97->spec.ad18xx.codec_cfg[codec]);
+			ac97->bus->ops->write(ac97, AC97_AD_CODEC_CFG, ac97->spec.ad18xx.codec_cfg[codec]);
 		}
 		/* select all codecs */
 		snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
@@ -2118,7 +2226,7 @@ __reset_ready:
 						snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
 								     ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]);
 						/* update PCM bits */
-						ac97->bus->write(ac97, AC97_PCM, ac97->spec.ad18xx.pcmreg[codec]);
+						ac97->bus->ops->write(ac97, AC97_PCM, ac97->spec.ad18xx.pcmreg[codec]);
 					}
 					/* select all codecs */
 					snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
@@ -2151,42 +2259,57 @@ __reset_ready:
 
 /*
  */
-int snd_ac97_remove_ctl(ac97_t *ac97, const char *name)
+static void set_ctl_name(char *dst, const char *src, const char *suffix)
+{
+	if (suffix)
+		sprintf(dst, "%s %s", src, suffix);
+	else
+		strcpy(dst, src);
+}	
+
+int snd_ac97_remove_ctl(ac97_t *ac97, const char *name, const char *suffix)
 {
 	snd_ctl_elem_id_t id;
 	memset(&id, 0, sizeof(id));
-	strcpy(id.name, name);
+	set_ctl_name(id.name, name, suffix);
 	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
 	return snd_ctl_remove_id(ac97->bus->card, &id);
 }
 
-static snd_kcontrol_t *ctl_find(ac97_t *ac97, const char *name)
+static snd_kcontrol_t *ctl_find(ac97_t *ac97, const char *name, const char *suffix)
 {
 	snd_ctl_elem_id_t sid;
 	memset(&sid, 0, sizeof(sid));
-	strcpy(sid.name, name);
+	set_ctl_name(sid.name, name, suffix);
 	sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
 	return snd_ctl_find_id(ac97->bus->card, &sid);
 }
 
-int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst)
+int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst, const char *suffix)
 {
-	snd_kcontrol_t *kctl = ctl_find(ac97, src);
+	snd_kcontrol_t *kctl = ctl_find(ac97, src, suffix);
 	if (kctl) {
-		strcpy(kctl->id.name, dst);
+		set_ctl_name(kctl->id.name, dst, suffix);
 		return 0;
 	}
 	return -ENOENT;
 }
 
-int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2)
+/* rename both Volume and Switch controls - don't check the return value */
+void snd_ac97_rename_vol_ctl(ac97_t *ac97, const char *src, const char *dst)
+{
+	snd_ac97_rename_ctl(ac97, src, dst, "Switch");
+	snd_ac97_rename_ctl(ac97, src, dst, "Volume");
+}
+
+int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2, const char *suffix)
 {
 	snd_kcontrol_t *kctl1, *kctl2;
-	kctl1 = ctl_find(ac97, s1);
-	kctl2 = ctl_find(ac97, s2);
+	kctl1 = ctl_find(ac97, s1, suffix);
+	kctl2 = ctl_find(ac97, s2, suffix);
 	if (kctl1 && kctl2) {
-		strcpy(kctl1->id.name, s2);
-		strcpy(kctl2->id.name, s1);
+		set_ctl_name(kctl1->id.name, s2, suffix);
+		set_ctl_name(kctl2->id.name, s1, suffix);
 		return 0;
 	}
 	return -ENOENT;
@@ -2194,26 +2317,22 @@ int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2)
 
 static int swap_headphone(ac97_t *ac97, int remove_master)
 {
-	/* FIXME: error checks.. */
 	if (remove_master) {
-		if (ctl_find(ac97, "Headphone Playback Switch") == NULL)
+		if (ctl_find(ac97, "Headphone Playback Switch", NULL) == NULL)
 			return 0;
-		snd_ac97_remove_ctl(ac97, "Master Playback Switch");
-		snd_ac97_remove_ctl(ac97, "Master Playback Volume");
-	} else {
-		snd_ac97_rename_ctl(ac97, "Master Playback Switch", "Line-Out Playback Switch");
-		snd_ac97_rename_ctl(ac97, "Master Playback Volume", "Line-Out Playback Volume");
-	}
-	snd_ac97_rename_ctl(ac97, "Headphone Playback Switch", "Master Playback Switch");
-	snd_ac97_rename_ctl(ac97, "Headphone Playback Volume", "Master Playback Volume");
+		snd_ac97_remove_ctl(ac97, "Master Playback", "Switch");
+		snd_ac97_remove_ctl(ac97, "Master Playback", "Volume");
+	} else
+		snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Line-Out Playback");
+	snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
 	return 0;
 }
 
 static int swap_surround(ac97_t *ac97)
 {
 	/* FIXME: error checks.. */
-	snd_ac97_swap_ctl(ac97, "Master Playback Switch", "Surround Playback Switch");
-	snd_ac97_swap_ctl(ac97, "Master Playback Volume", "Surround Playback Volume");
+	snd_ac97_swap_ctl(ac97, "Master Playback", "Surround Playback", "Switch");
+	snd_ac97_swap_ctl(ac97, "Master Playback", "Surround Playback", "Volume");
 	return 0;
 }
 
diff --git a/sound/pci/ac97/ac97_id.h b/sound/pci/ac97/ac97_id.h
index fa75c06fd..24a9f6cc3 100644
--- a/sound/pci/ac97/ac97_id.h
+++ b/sound/pci/ac97/ac97_id.h
@@ -45,7 +45,14 @@
 #define AC97_ID_CS4201		0x43525948
 #define AC97_ID_CS4205		0x43525958
 #define AC97_ID_CS_MASK		0xfffffff8	/* bit 0-2: rev */
+#define AC97_ID_ALC100		0x414c4300
 #define AC97_ID_ALC650		0x414c4720
+#define AC97_ID_ALC650D		0x414c4721
+#define AC97_ID_ALC650E		0x414c4722
+#define AC97_ID_ALC650F		0x414c4723
+#define AC97_ID_ALC655		0x414c4760
+#define AC97_ID_ALC658		0x414c4780
+#define AC97_ID_ALC850		0x414c4790
 #define AC97_ID_YMF753		0x594d4803
 #define AC97_ID_VT1616		0x49434551
 #define AC97_ID_CM9738		0x434d4941
diff --git a/sound/pci/ac97/ac97_local.h b/sound/pci/ac97/ac97_local.h
index 838656f76..27d3236ee 100644
--- a/sound/pci/ac97/ac97_local.h
+++ b/sound/pci/ac97/ac97_local.h
@@ -23,10 +23,15 @@
  */
 
 #define AC97_SINGLE_VALUE(reg,shift,mask,invert) ((reg) | ((shift) << 8) | ((mask) << 16) | ((invert) << 24))
+#define AC97_PAGE_SINGLE_VALUE(reg,shift,mask,invert,page) ((reg) | ((shift) << 8) | ((mask) << 16) | ((invert) << 24) | ((page) << 25))
 #define AC97_SINGLE(xname, reg, shift, mask, invert) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_single, \
   .get = snd_ac97_get_single, .put = snd_ac97_put_single, \
   .private_value =  AC97_SINGLE_VALUE(reg, shift, mask, invert) }
+#define AC97_PAGE_SINGLE(xname, reg, shift, mask, invert, page)		\
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_single, \
+  .get = snd_ac97_page_get_single, .put = snd_ac97_page_put_single, \
+  .private_value =  AC97_PAGE_SINGLE_VALUE(reg, shift, mask, invert, page) }
 
 /* ac97_codec.c */
 extern const char *snd_ac97_stereo_enhancements[];
@@ -37,10 +42,13 @@ void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem);
 int snd_ac97_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo);
 int snd_ac97_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
 int snd_ac97_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
+int snd_ac97_page_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
+int snd_ac97_page_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
 int snd_ac97_try_bit(ac97_t * ac97, int reg, int bit);
-int snd_ac97_remove_ctl(ac97_t *ac97, const char *name);
-int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst);
-int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2);
+int snd_ac97_remove_ctl(ac97_t *ac97, const char *name, const char *suffix);
+int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst, const char *suffix);
+int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2, const char *suffix);
+void snd_ac97_rename_vol_ctl(ac97_t *ac97, const char *src, const char *dst);
 
 /* ac97_proc.c */
 void snd_ac97_bus_proc_init(ac97_bus_t * ac97);
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index 85124051e..1ad062a19 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -35,8 +35,6 @@
 #include "ac97_id.h"
 #include "ac97_local.h"
 
-#define chip_t ac97_t
-
 /*
  *  Chip specific initialization
  */
@@ -51,6 +49,21 @@ static int patch_build_controls(ac97_t * ac97, const snd_kcontrol_new_t *control
 	return 0;
 }
 
+/* set to the page, update bits and restore the page */
+static int ac97_update_bits_page(ac97_t *ac97, unsigned short reg, unsigned short mask, unsigned short value, unsigned short page)
+{
+	unsigned short page_save;
+	int ret;
+
+	down(&ac97->mutex);
+	page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
+	snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page);
+	ret = snd_ac97_update_bits(ac97, reg, mask, value);
+	snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save);
+	up(&ac97->mutex); /* unlock paging */
+	return ret;
+}
+
 /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */
 
 /* It is possible to indicate to the Yamaha YMF753 the type of speakers being used. */
@@ -204,7 +217,7 @@ static int patch_yamaha_ymf753_3d(ac97_t * ac97)
 	if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
 		return err;
 	strcpy(kctl->id.name, "3D Control - Wide");
-	kctl->private_value = AC97_3D_CONTROL | (9 << 8) | (7 << 16);
+	kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 9, 7, 0);
 	snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
 	if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&snd_ac97_ymf753_controls_speaker, ac97))) < 0)
 		return err;
@@ -315,7 +328,7 @@ static int patch_sigmatel_stac9700_3d(ac97_t * ac97)
 	if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
 		return err;
 	strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
-	kctl->private_value = AC97_3D_CONTROL | (3 << 16);
+	kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0);
 	snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
 	return 0;
 }
@@ -328,11 +341,11 @@ static int patch_sigmatel_stac9708_3d(ac97_t * ac97)
 	if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
 		return err;
 	strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
-	kctl->private_value = AC97_3D_CONTROL | (3 << 16);
+	kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 0, 3, 0);
 	if ((err = snd_ctl_add(ac97->bus->card, kctl = snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
 		return err;
 	strcpy(kctl->id.name, "3D Control Sigmatel - Rear Depth");
-	kctl->private_value = AC97_3D_CONTROL | (2 << 8) | (3 << 16);
+	kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0);
 	snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
 	return 0;
 }
@@ -373,22 +386,29 @@ static struct snd_ac97_build_ops patch_sigmatel_stac9700_ops = {
 	.build_specific	= patch_sigmatel_stac97xx_specific
 };
 
-static struct snd_ac97_build_ops patch_sigmatel_stac9708_ops = {
-	.build_3d	= patch_sigmatel_stac9708_3d,
-	.build_specific	= patch_sigmatel_stac97xx_specific
-};
-
 int patch_sigmatel_stac9700(ac97_t * ac97)
 {
 	ac97->build_ops = &patch_sigmatel_stac9700_ops;
 	return 0;
 }
 
+static int patch_sigmatel_stac9708_specific(ac97_t *ac97)
+{
+	snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround Playback");
+	return patch_sigmatel_stac97xx_specific(ac97);
+}
+
+static struct snd_ac97_build_ops patch_sigmatel_stac9708_ops = {
+	.build_3d	= patch_sigmatel_stac9708_3d,
+	.build_specific	= patch_sigmatel_stac9708_specific
+};
+
 int patch_sigmatel_stac9708(ac97_t * ac97)
 {
 	unsigned int codec72, codec6c;
 
 	ac97->build_ops = &patch_sigmatel_stac9708_ops;
+	ac97->caps |= 0x10;	/* HP (sigmatel surround) support */
 
 	codec72 = snd_ac97_read(ac97, AC97_SIGMATEL_BIAS2) & 0x8000;
 	codec6c = snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG);
@@ -467,11 +487,11 @@ static int snd_ac97_stac9758_output_jack_get(snd_kcontrol_t *kcontrol, snd_ctl_e
 	int shift = kcontrol->private_value;
 	unsigned short val;
 
-	val = ac97->regs[AC97_SIGMATEL_OUTSEL];
-	if (!((val >> shift) & 4))
+	val = ac97->regs[AC97_SIGMATEL_OUTSEL] >> shift;
+	if (!(val & 4))
 		ucontrol->value.enumerated.item[0] = 0;
 	else
-		ucontrol->value.enumerated.item[0] = 1 + ((val >> shift) & 3);
+		ucontrol->value.enumerated.item[0] = 1 + (val & 3);
 	return 0;
 }
 
@@ -487,8 +507,8 @@ static int snd_ac97_stac9758_output_jack_put(snd_kcontrol_t *kcontrol, snd_ctl_e
 		val = 0;
 	else
 		val = 4 | (ucontrol->value.enumerated.item[0] - 1);
-	return snd_ac97_update_bits(ac97, AC97_SIGMATEL_OUTSEL,
-				    7 << shift, val << shift);
+	return ac97_update_bits_page(ac97, AC97_SIGMATEL_OUTSEL,
+				     7 << shift, val << shift, 0);
 }
 
 static int snd_ac97_stac9758_input_jack_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
@@ -521,8 +541,8 @@ static int snd_ac97_stac9758_input_jack_put(snd_kcontrol_t *kcontrol, snd_ctl_el
 	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
 	int shift = kcontrol->private_value;
 
-	return snd_ac97_update_bits(ac97, AC97_SIGMATEL_INSEL, 7 << shift,
-				    ucontrol->value.enumerated.item[0] << shift);
+	return ac97_update_bits_page(ac97, AC97_SIGMATEL_INSEL, 7 << shift,
+				     ucontrol->value.enumerated.item[0] << shift, 0);
 }
 
 static int snd_ac97_stac9758_phonesel_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
@@ -550,8 +570,8 @@ static int snd_ac97_stac9758_phonesel_put(snd_kcontrol_t *kcontrol, snd_ctl_elem
 {
 	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
 
-	return snd_ac97_update_bits(ac97, AC97_SIGMATEL_IOMISC, 3,
-				    ucontrol->value.enumerated.item[0]);
+	return ac97_update_bits_page(ac97, AC97_SIGMATEL_IOMISC, 3,
+				     ucontrol->value.enumerated.item[0], 0);
 }
 
 #define STAC9758_OUTPUT_JACK(xname, shift) \
@@ -596,6 +616,14 @@ static int patch_sigmatel_stac9758_specific(ac97_t *ac97)
 				   ARRAY_SIZE(snd_ac97_sigmatel_stac9758_controls));
 	if (err < 0)
 		return err;
+	/* DAC-A direct */
+	snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Front Playback");
+	/* DAC-A to Mix = PCM */
+	/* DAC-B direct = Surround */
+	/* DAC-B to Mix */
+	snd_ac97_rename_vol_ctl(ac97, "Video Playback", "Surround Mix Playback");
+	/* DAC-C direct = Center/LFE */
+
 	return 0;
 }
 
@@ -613,16 +641,16 @@ int patch_sigmatel_stac9758(ac97_t * ac97)
 		AC97_SIGMATEL_VARIOUS
 	};
 	static unsigned short def_regs[4] = {
-		/* OUTSEL */ 0xd794,
+		/* OUTSEL */ 0xd794, /* CL:CL, SR:SR, LO:MX, LI:DS, MI:DS */
 		/* IOMISC */ 0x2001,
-		/* INSEL */ 0x0201,
+		/* INSEL */ 0x0201, /* LI:LI, MI:M1 */
 		/* VARIOUS */ 0x0040
 	};
 	static unsigned short m675_regs[4] = {
-		/* OUTSEL */ 0x9040,
-		/* IOMISC */ 0x2102,
-		/* INSEL */ 0x0203,
-		/* VARIOUS */ 0x0041
+		/* OUTSEL */ 0xfc70, /* CL:MX, SR:MX, LO:DS, LI:MX, MI:DS */
+		/* IOMISC */ 0x2102, /* HP amp on */
+		/* INSEL */ 0x0203, /* LI:LI, MI:FR */
+		/* VARIOUS */ 0x0041 /* stereo mic */
 	};
 	unsigned short *pregs = def_regs;
 	int i;
@@ -635,6 +663,8 @@ int patch_sigmatel_stac9758(ac97_t * ac97)
 
 	// patch for SigmaTel
 	ac97->build_ops = &patch_sigmatel_stac9758_ops;
+	/* FIXME: assume only page 0 for writing cache */
+	snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
 	for (i = 0; i < 4; i++)
 		snd_ac97_write_cache(ac97, regs[i], pregs[i]);
 
@@ -654,8 +684,10 @@ static int patch_cirrus_build_spdif(ac97_t * ac97)
 {
 	int err;
 
+	/* con mask, pro mask, default */
 	if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0)
 		return err;
+	/* switch, spsa */
 	if ((err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[0], 1)) < 0)
 		return err;
 	switch (ac97->id & AC97_ID_CS_MASK) {
@@ -714,8 +746,10 @@ static int patch_conexant_build_spdif(ac97_t * ac97)
 {
 	int err;
 
+	/* con mask, pro mask, default */
 	if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0)
 		return err;
+	/* switch */
 	if ((err = patch_build_controls(ac97, &snd_ac97_conexant_controls_spdif[0], 1)) < 0)
 		return err;
 	/* set default PCM S/PDIF params */
@@ -734,6 +768,7 @@ int patch_conexant(ac97_t * ac97)
 	ac97->build_ops = &patch_conexant_ops;
 	ac97->flags |= AC97_CX_SPDIF;
         ac97->ext_id |= AC97_EI_SPDIF;	/* force the detection of spdif */
+	ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
 	return 0;
 }
 
@@ -821,8 +856,6 @@ int patch_ad1881(ac97_t * ac97)
 	unsigned short val;
 	int idx, num;
 
-	init_MUTEX(&ac97->spec.ad18xx.mutex);
-
 	val = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG);
 	snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, val);
 	codecs[0] = patch_ad1881_unchained(ac97, 0, (1<<12));
@@ -872,6 +905,8 @@ static const snd_kcontrol_new_t snd_ac97_controls_ad1885[] = {
 	/* AC97_SINGLE("Digital Audio Mode", AC97_AD_MISC, 12, 1, 0), */ /* seems problematic */
 	AC97_SINGLE("Low Power Mixer", AC97_AD_MISC, 14, 1, 0),
 	AC97_SINGLE("Zero Fill DAC", AC97_AD_MISC, 15, 1, 0),
+	AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 9, 1, 1), /* inverted */
+	AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 8, 1, 1), /* inverted */
 };
 
 static int patch_ad1885_specific(ac97_t * ac97)
@@ -889,16 +924,10 @@ static struct snd_ac97_build_ops patch_ad1885_build_ops = {
 
 int patch_ad1885(ac97_t * ac97)
 {
-	unsigned short jack;
-
 	patch_ad1881(ac97);
 	/* This is required to deal with the Intel D815EEAL2 */
 	/* i.e. Line out is actually headphone out from codec */
 
-	/* turn off jack sense bits D8 & D9 */
-	jack = snd_ac97_read(ac97, AC97_AD_JACK_SPDIF);
-	snd_ac97_write_cache(ac97, AC97_AD_JACK_SPDIF, jack | 0x0300);
-
 	/* set default */
 	snd_ac97_write_cache(ac97, AC97_AD_MISC, 0x0404);
 
@@ -1114,10 +1143,8 @@ static const snd_kcontrol_new_t snd_ac97_ad1888_controls[] = {
 static int patch_ad1888_specific(ac97_t *ac97)
 {
 	/* rename 0x04 as "Master" and 0x02 as "Master Surround" */
-	snd_ac97_rename_ctl(ac97, "Master Playback Switch", "Master Surround Playback Switch");
-	snd_ac97_rename_ctl(ac97, "Master Playback Volume", "Master Surround Playback Volume");
-	snd_ac97_rename_ctl(ac97, "Headphone Playback Switch", "Master Playback Switch");
-	snd_ac97_rename_ctl(ac97, "Headphone Playback Volume", "Master Playback Volume");
+	snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Master Surround Playback");
+	snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
 	return patch_build_controls(ac97, snd_ac97_ad1888_controls, ARRAY_SIZE(snd_ac97_ad1888_controls));
 }
 
@@ -1213,7 +1240,7 @@ int patch_ad1985(ac97_t * ac97)
 }
 
 /*
- * realtek ALC65x codecs
+ * realtek ALC65x/850 codecs
  */
 static int snd_ac97_alc650_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
@@ -1303,6 +1330,17 @@ int patch_alc650(ac97_t * ac97)
 
 	ac97->build_ops = &patch_alc650_ops;
 
+	/* determine the revision */
+	val = snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f;
+	if (val < 3)
+		ac97->id = 0x414c4720;          /* Old version */
+	else if (val < 0x10)
+		ac97->id = 0x414c4721;          /* D version */
+	else if (val < 0x20)
+		ac97->id = 0x414c4722;          /* E version */
+	else if (val < 0x30)
+		ac97->id = 0x414c4723;          /* F version */
+
 	/* revision E or F */
 	/* FIXME: what about revision D ? */
 	ac97->spec.dev_flags = (ac97->id == 0x414c4722 ||
@@ -1351,20 +1389,19 @@ static int snd_ac97_alc655_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
 static int snd_ac97_alc655_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
         ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-        int change;
 
 	/* misc control; vrefout disable */
 	snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
 			     ucontrol->value.integer.value[0] ? (1 << 12) : 0);
-	change = snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
-				      ucontrol->value.integer.value[0] ? (1 << 10) : 0);
-	return change;
+	return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10,
+				     ucontrol->value.integer.value[0] ? (1 << 10) : 0,
+				     0);
 }
 
 
 static const snd_kcontrol_new_t snd_ac97_controls_alc655[] = {
-	AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
-	AC97_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0),
+	AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
+	AC97_PAGE_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0, 0),
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Mic As Center/LFE",
@@ -1391,7 +1428,6 @@ static int alc655_iec958_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_
 	       texts_658[uinfo->value.enumerated.item] :
 	       texts_655[uinfo->value.enumerated.item]);
 	return 0;
-
 }
 
 static int alc655_iec958_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
@@ -1410,13 +1446,15 @@ static int alc655_iec958_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
 static int alc655_iec958_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-	return snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 3 << 12,
-				    (unsigned short)ucontrol->value.enumerated.item[0]);
+
+	return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 3 << 12,
+				     (unsigned short)ucontrol->value.enumerated.item[0],
+				     0);
 }
 
 static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc655[] = {
-        AC97_SINGLE("IEC958 Capture Switch", AC97_ALC650_MULTICH, 11, 1, 0),
-        AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 14, 1, 0),
+        AC97_PAGE_SINGLE("IEC958 Capture Switch", AC97_ALC650_MULTICH, 11, 1, 0, 0),
+        AC97_PAGE_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 14, 1, 0, 0),
 	{
 		.iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name   = "IEC958 Playback Route",
@@ -1451,6 +1489,9 @@ int patch_alc655(ac97_t * ac97)
 
 	ac97->build_ops = &patch_alc655_ops;
 
+	/* assume only page 0 for writing cache */
+	snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
+
 	/* adjust default values */
 	val = snd_ac97_read(ac97, 0x7a); /* misc control */
 	val |= (1 << 1); /* spdif input pin */
@@ -1469,6 +1510,120 @@ int patch_alc655(ac97_t * ac97)
 	return 0;
 }
 
+
+#define AC97_ALC850_JACK_SELECT	0x76
+#define AC97_ALC850_MISC1	0x7a
+
+static int ac97_alc850_surround_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+        ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 12) & 7) == 2;
+        return 0;
+}
+
+static int ac97_alc850_surround_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+
+	/* SURR 1kOhm (bit4), Amp (bit5) */
+	snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5),
+			     ucontrol->value.integer.value[0] ? (1<<5) : (1<<4));
+	/* LINE-IN = 0, SURROUND = 2 */
+	return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12,
+				    ucontrol->value.integer.value[0] ? (2<<12) : (0<<12));
+}
+
+static int ac97_alc850_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+        ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 4) & 7) == 2;
+        return 0;
+}
+
+static int ac97_alc850_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+
+	/* Vref disable (bit12), 1kOhm (bit13) */
+	snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13),
+			     ucontrol->value.integer.value[0] ? (1<<12) : (1<<13));
+	/* MIC-IN = 1, CENTER-LFE = 2 */
+	return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
+				    ucontrol->value.integer.value[0] ? (2<<4) : (1<<4));
+}
+
+static const snd_kcontrol_new_t snd_ac97_controls_alc850[] = {
+	AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Line-In As Surround",
+		.info = snd_ac97_info_single,
+		.get = ac97_alc850_surround_get,
+		.put = ac97_alc850_surround_put,
+		.private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Mic As Center/LFE",
+		.info = snd_ac97_info_single,
+		.get = ac97_alc850_mic_get,
+		.put = ac97_alc850_mic_put,
+		.private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
+	},
+
+};
+
+static int patch_alc850_specific(ac97_t *ac97)
+{
+	int err;
+
+	if ((err = patch_build_controls(ac97, snd_ac97_controls_alc850, ARRAY_SIZE(snd_ac97_controls_alc850))) < 0)
+		return err;
+	if (ac97->ext_id & AC97_EI_SPDIF) {
+		if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc655, ARRAY_SIZE(snd_ac97_spdif_controls_alc655))) < 0)
+			return err;
+	}
+	return 0;
+}
+
+static struct snd_ac97_build_ops patch_alc850_ops = {
+	.build_specific	= patch_alc850_specific
+};
+
+int patch_alc850(ac97_t *ac97)
+{
+	ac97->build_ops = &patch_alc850_ops;
+
+	ac97->spec.dev_flags = 0; /* for IEC958 playback route - ALC655 compatible */
+
+	/* assume only page 0 for writing cache */
+	snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
+
+	/* adjust default values */
+	/* set default: spdif-in enabled,
+	   spdif-in monitor off, spdif-in PCM off
+	   center on mic off, surround on line-in off
+	   duplicate front off
+	*/
+	snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15);
+	/* SURR_OUT: on, Surr 1kOhm: on, Surr Amp: off, Front 1kOhm: off
+	 * Front Amp: on, Vref: enable, Center 1kOhm: on, Mix: on
+	 */
+	snd_ac97_write_cache(ac97, 0x7a, (1<<1)|(1<<4)|(0<<5)|(1<<6)|
+			     (1<<7)|(0<<12)|(1<<13)|(0<<14));
+	/* detection UIO2,3: all path floating, UIO3: MIC, Vref2: disable,
+	 * UIO1: FRONT, Vref3: disable, UIO3: LINE, Front-Mic: mute
+	 */
+	snd_ac97_write_cache(ac97, 0x76, (0<<0)|(0<<2)|(1<<4)|(1<<7)|(2<<8)|
+			     (1<<11)|(0<<12)|(1<<15));
+
+	/* full DAC volume */
+	snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
+	snd_ac97_write_cache(ac97, AC97_ALC650_LFE_DAC_VOL, 0x0808);
+	return 0;
+}
+
+
 /*
  * C-Media CM97xx codecs
  */
@@ -1599,8 +1754,10 @@ int patch_cm9739(ac97_t * ac97)
 		/* enable spdif in */
 		snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL,
 				     snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) | 0x01);
+		ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
 	} else {
 		ac97->ext_id &= ~AC97_EI_SPDIF; /* disable extended-id */
+		ac97->rates[AC97_RATES_SPDIF] = 0;
 	}
 
 	/* set-up multi channel */
diff --git a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h
index 3e78799c5..a619d7276 100644
--- a/sound/pci/ac97/ac97_patch.h
+++ b/sound/pci/ac97/ac97_patch.h
@@ -49,6 +49,7 @@ int patch_ad1981b(ac97_t * ac97);
 int patch_ad1985(ac97_t * ac97);
 int patch_alc650(ac97_t * ac97);
 int patch_alc655(ac97_t * ac97);
+int patch_alc850(ac97_t * ac97);
 int patch_cm9738(ac97_t * ac97);
 int patch_cm9739(ac97_t * ac97);
 int patch_vt1616(ac97_t * ac97);
diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c
index 11e80ef23..04f3b6096 100644
--- a/sound/pci/ac97/ac97_pcm.c
+++ b/sound/pci/ac97/ac97_pcm.c
@@ -36,8 +36,6 @@
 #include "ac97_id.h"
 #include "ac97_local.h"
 
-#define chip_t ac97_t
-
 /*
  *  PCM support
  */
@@ -430,7 +428,7 @@ int snd_ac97_pcm_assign(ac97_bus_t *bus,
 	unsigned int rates;
 	ac97_t *codec;
 
-	rpcms = snd_kcalloc(sizeof(struct ac97_pcm) * pcms_count, GFP_KERNEL);
+	rpcms = kcalloc(pcms_count, sizeof(struct ac97_pcm), GFP_KERNEL);
 	if (rpcms == NULL)
 		return -ENOMEM;
 	memset(avail_slots, 0, sizeof(avail_slots));
@@ -489,7 +487,10 @@ int snd_ac97_pcm_assign(ac97_bus_t *bus,
 				rpcm->r[0].rslots[j] = tmp;
 				rpcm->r[0].codec[j] = bus->codec[j];
 				rpcm->r[0].rate_table[j] = rate_table[pcm->stream][j];
-				rates = get_rates(rpcm, j, tmp, 0);
+				if (bus->no_vra)
+					rates = SNDRV_PCM_RATE_48000;
+				else
+					rates = get_rates(rpcm, j, tmp, 0);
 				if (pcm->exclusive)
 					avail_slots[pcm->stream][j] &= ~tmp;
 			}
diff --git a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c
index 40b3e9fd8..007a4b8d0 100644
--- a/sound/pci/ac97/ac97_proc.c
+++ b/sound/pci/ac97/ac97_proc.c
@@ -290,11 +290,11 @@ static void snd_ac97_proc_read_main(ac97_t *ac97, snd_info_buffer_t * buffer, in
 
 static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-	ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return);
+	ac97_t *ac97 = entry->private_data;
 	
+	down(&ac97->mutex);
 	if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) {	// Analog Devices AD1881/85/86
 		int idx;
-		down(&ac97->spec.ad18xx.mutex);
 		for (idx = 0; idx < 3; idx++)
 			if (ac97->spec.ad18xx.id[idx]) {
 				/* select single codec */
@@ -305,7 +305,6 @@ static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buff
 			}
 		/* select all codecs */
 		snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
-		up(&ac97->spec.ad18xx.mutex);
 		
 		snd_iprintf(buffer, "\nAD18XX configuration\n");
 		snd_iprintf(buffer, "Unchained        : 0x%04x,0x%04x,0x%04x\n",
@@ -319,22 +318,25 @@ static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buff
 	} else {
 		snd_ac97_proc_read_main(ac97, buffer, 0);
 	}
+	up(&ac97->mutex);
 }
 
 #ifdef CONFIG_SND_DEBUG
 /* direct register write for debugging */
 static void snd_ac97_proc_regs_write(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
 {
-	ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return);
+	ac97_t *ac97 = entry->private_data;
 	char line[64];
 	unsigned int reg, val;
+	down(&ac97->mutex);
 	while (!snd_info_get_line(buffer, line, sizeof(line))) {
 		if (sscanf(line, "%x %x", &reg, &val) != 2)
 			continue;
-		/* register must be odd */
+		/* register must be even */
 		if (reg < 0x80 && (reg & 1) == 0 && val <= 0xffff)
 			snd_ac97_write_cache(ac97, reg, val);
 	}
+	up(&ac97->mutex);
 }
 #endif
 
@@ -351,12 +353,12 @@ static void snd_ac97_proc_regs_read_main(ac97_t *ac97, snd_info_buffer_t * buffe
 static void snd_ac97_proc_regs_read(snd_info_entry_t *entry, 
 				    snd_info_buffer_t * buffer)
 {
-	ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return);
+	ac97_t *ac97 = entry->private_data;
 
+	down(&ac97->mutex);
 	if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) {	// Analog Devices AD1881/85/86
 
 		int idx;
-		down(&ac97->spec.ad18xx.mutex);
 		for (idx = 0; idx < 3; idx++)
 			if (ac97->spec.ad18xx.id[idx]) {
 				/* select single codec */
@@ -366,10 +368,10 @@ static void snd_ac97_proc_regs_read(snd_info_entry_t *entry,
 			}
 		/* select all codecs */
 		snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
-		up(&ac97->spec.ad18xx.mutex);
 	} else {
 		snd_ac97_proc_regs_read_main(ac97, buffer, 0);
 	}	
+	up(&ac97->mutex);
 }
 
 void snd_ac97_proc_init(ac97_t * ac97)
diff --git a/sound/pci/ac97/ak4531_codec.c b/sound/pci/ac97/ak4531_codec.c
index b0c621455..d33cd4202 100644
--- a/sound/pci/ac97/ak4531_codec.c
+++ b/sound/pci/ac97/ak4531_codec.c
@@ -30,8 +30,6 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Universal routines for AK4531 codec");
 MODULE_LICENSE("GPL");
 
-#define chip_t ak4531_t
-
 static void snd_ak4531_proc_init(snd_card_t * card, ak4531_t * ak4531);
 
 /*
@@ -89,7 +87,7 @@ static int snd_ak4531_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 	}
 	ucontrol->value.integer.value[0] = val;
 	return 0;
-}                                                                                                                                                                                                                                                                                                            
+}
 
 static int snd_ak4531_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
@@ -113,7 +111,7 @@ static int snd_ak4531_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 	ak4531->write(ak4531, reg, ak4531->regs[reg] = val);
 	spin_unlock_irqrestore(&ak4531->reg_lock, flags);
 	return change;
-}                                                                                                                                                                                                                                                                                                            
+}
 
 #define AK4531_DOUBLE(xname, xindex, left_reg, right_reg, left_shift, right_shift, mask, invert) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
@@ -155,7 +153,7 @@ static int snd_ak4531_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 	ucontrol->value.integer.value[0] = left;
 	ucontrol->value.integer.value[1] = right;
 	return 0;
-}                                                                                                                                                                                                                                                                                                            
+}
 
 static int snd_ak4531_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
@@ -192,7 +190,7 @@ static int snd_ak4531_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 	}
 	spin_unlock_irqrestore(&ak4531->reg_lock, flags);
 	return change;
-}                                                                                                                                                                                                                                                                                                            
+}
 
 #define AK4531_INPUT_SW(xname, xindex, reg1, reg2, left_shift, right_shift) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
@@ -225,7 +223,7 @@ static int snd_ak4531_get_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
 	ucontrol->value.integer.value[3] = (ak4531->regs[reg2] >> right_shift) & 1;
 	spin_unlock_irqrestore(&ak4531->reg_lock, flags);
 	return 0;
-}                                                                                                                                                                                                                                                                                                            
+}
 
 static int snd_ak4531_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
@@ -250,9 +248,7 @@ static int snd_ak4531_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
 	ak4531->write(ak4531, reg2, ak4531->regs[reg2] = val2);
 	spin_unlock_irqrestore(&ak4531->reg_lock, flags);
 	return change;
-}                                                                                                                                                                                                                                                                                                            
-
-#define AK4531_CONTROLS (sizeof(snd_ak4531_controls)/sizeof(snd_kcontrol_new_t))
+}
 
 static snd_kcontrol_new_t snd_ak4531_controls[] = {
 
@@ -315,14 +311,14 @@ static int snd_ak4531_free(ak4531_t *ak4531)
 	if (ak4531) {
 		if (ak4531->private_free)
 			ak4531->private_free(ak4531);
-		snd_magic_kfree(ak4531);
+		kfree(ak4531);
 	}
 	return 0;
 }
 
 static int snd_ak4531_dev_free(snd_device_t *device)
 {
-	ak4531_t *ak4531 = snd_magic_cast(ak4531_t, device->device_data, return -ENXIO);
+	ak4531_t *ak4531 = device->device_data;
 	return snd_ak4531_free(ak4531);
 }
 
@@ -367,7 +363,7 @@ int snd_ak4531_mixer(snd_card_t * card, ak4531_t * _ak4531, ak4531_t ** rak4531)
 	snd_assert(rak4531 != NULL, return -EINVAL);
 	*rak4531 = NULL;
 	snd_assert(card != NULL && _ak4531 != NULL, return -EINVAL);
-	ak4531 = snd_magic_kcalloc(ak4531_t, 0, GFP_KERNEL);
+	ak4531 = kcalloc(1, sizeof(*ak4531), GFP_KERNEL);
 	if (ak4531 == NULL)
 		return -ENOMEM;
 	*ak4531 = *_ak4531;
@@ -385,7 +381,7 @@ int snd_ak4531_mixer(snd_card_t * card, ak4531_t * _ak4531, ak4531_t ** rak4531)
 			continue;
 		ak4531->write(ak4531, idx, ak4531->regs[idx] = snd_ak4531_initial_map[idx]);	/* recording source is mixer */
 	}
-	for (idx = 0; idx < AK4531_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_ak4531_controls); idx++) {
 		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ak4531_controls[idx], ak4531))) < 0) {
 			snd_ak4531_free(ak4531);
 			return err;
@@ -411,7 +407,7 @@ int snd_ak4531_mixer(snd_card_t * card, ak4531_t * _ak4531, ak4531_t ** rak4531)
 static void snd_ak4531_proc_read(snd_info_entry_t *entry, 
 				 snd_info_buffer_t * buffer)
 {
-	ak4531_t *ak4531 = snd_magic_cast(ak4531_t, entry->private_data, return);
+	ak4531_t *ak4531 = entry->private_data;
 
 	snd_iprintf(buffer, "Asahi Kasei AK4531\n\n");
 	snd_iprintf(buffer, "Recording source   : %s\n"
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index 670b10680..e97e48894 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -43,8 +43,7 @@
 MODULE_AUTHOR("Matt Wu <Matt_Wu@acersoftech.com.cn>");
 MODULE_DESCRIPTION("ALI M5451");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ALI,M5451,pci},{ALI,M5451}}");
+MODULE_SUPPORTED_DEVICE("{{ALI,M5451,pci},{ALI,M5451}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -55,19 +54,14 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for ALI M5451 PCI Audio.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for ALI M5451 PCI Audio.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable ALI 5451 PCI Audio.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(pcm_channels, int, boot_devs, 0444);
 MODULE_PARM_DESC(pcm_channels, "PCM Channels");
-MODULE_PARM_SYNTAX(pcm_channels, SNDRV_ENABLED ",default:32,allows:{{1,32}}");
 module_param_array(spdif, bool, boot_devs, 0444);
 MODULE_PARM_DESC(spdif, "Support SPDIF I/O");
-MODULE_PARM_SYNTAX(spdif, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 
 /*
  *  Debug part definitions
@@ -171,7 +165,6 @@ MODULE_PARM_SYNTAX(spdif, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 
 typedef struct snd_stru_ali ali_t;
 typedef struct snd_ali_stru_voice snd_ali_voice_t;
-#define chip_t ali_t
 
 typedef struct snd_ali_channel_control {
 	// register data
@@ -247,7 +240,6 @@ struct snd_stru_ali {
 
 	unsigned int hw_initialized: 1;
 	unsigned int spdif_support: 1;
-	struct resource *res_port;
 
 	struct pci_dev	*pci;
 	struct pci_dev	*pci_m1533;
@@ -495,7 +487,7 @@ static void snd_ali_codec_write(ac97_t *ac97,
 				unsigned short reg,
 				unsigned short val )
 {
-	ali_t *codec = snd_magic_cast(ali_t, ac97->private_data, return);
+	ali_t *codec = ac97->private_data;
 
 	snd_ali_printk("codec_write: reg=%xh data=%xh.\n", reg, val);
 	snd_ali_codec_poke(codec, 0, reg, val);
@@ -505,7 +497,7 @@ static void snd_ali_codec_write(ac97_t *ac97,
 
 static unsigned short snd_ali_codec_read(ac97_t *ac97, unsigned short reg)
 {
-	ali_t *codec = snd_magic_cast(ali_t, ac97->private_data, return -ENXIO);
+	ali_t *codec = ac97->private_data;
 
 	snd_ali_printk("codec_read reg=%xh.\n", reg);
 	return (snd_ali_codec_peek(codec, 0, reg));
@@ -1051,7 +1043,7 @@ static irqreturn_t snd_ali_card_interrupt(int irq,
 				   void *dev_id,
 				   struct pt_regs *regs)
 {
-	ali_t 	*codec = snd_magic_cast(ali_t, dev_id, return IRQ_NONE);
+	ali_t 	*codec = dev_id;
 
 	if (codec == NULL)
 		return IRQ_NONE;
@@ -1247,7 +1239,7 @@ static int snd_ali_trigger(snd_pcm_substream_t *substream,
 	what = whati = capture_flag = 0;
 	snd_pcm_group_for_each(pos, substream) {
 		s = snd_pcm_group_substream_entry(pos);
-		if ((ali_t *) _snd_pcm_chip(s->pcm) == codec) {
+		if ((ali_t *) snd_pcm_substream_chip(s) == codec) {
 			pvoice = (snd_ali_voice_t *) s->runtime->private_data;
 			evoice = pvoice->extra;
 			what |= 1 << (pvoice->number & 0x1f);
@@ -1528,16 +1520,15 @@ static snd_pcm_uframes_t snd_ali_playback_pointer(snd_pcm_substream_t *substream
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;
 	unsigned int cso;
-	unsigned long flags;
 
-	spin_lock_irqsave(&codec->reg_lock, flags);
+	spin_lock(&codec->reg_lock);
 	if (!pvoice->running) {
-		spin_unlock_irqrestore(&codec->reg_lock, flags);
+		spin_unlock(&codec->reg_lock);
 		return 0;
 	}
 	outb(pvoice->number, ALI_REG(codec, ALI_GC_CIR));
 	cso = inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2));
-	spin_unlock_irqrestore(&codec->reg_lock, flags);
+	spin_unlock(&codec->reg_lock);
 	snd_ali_printk("playback pointer returned cso=%xh.\n", cso);
 
 	return cso;
@@ -1720,7 +1711,7 @@ static snd_pcm_ops_t snd_ali_capture_ops = {
 
 static void snd_ali_pcm_free(snd_pcm_t *pcm)
 {
-	ali_t *codec = snd_magic_cast(ali_t, pcm->private_data, return);
+	ali_t *codec = pcm->private_data;
 	codec->pcm = NULL;
 }
 
@@ -1769,7 +1760,7 @@ static int snd_ali5451_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
 static int snd_ali5451_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	unsigned long flags;
-	ali_t *codec = snd_magic_cast(ali_t, kcontrol->private_data, -ENXIO);
+	ali_t *codec = kcontrol->private_data;
 	unsigned int enable;
 
 	enable = ucontrol->value.integer.value[0] ? 1 : 0;
@@ -1796,7 +1787,7 @@ static int snd_ali5451_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 static int snd_ali5451_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	unsigned long flags;
-	ali_t *codec = snd_magic_cast(ali_t, kcontrol->private_data, -ENXIO);
+	ali_t *codec = kcontrol->private_data;
 	unsigned int change = 0, enable = 0;
 
 	enable = ucontrol->value.integer.value[0] ? 1 : 0;
@@ -1863,30 +1854,29 @@ static snd_kcontrol_new_t snd_ali5451_mixer_spdif[] __devinitdata = {
 
 static void snd_ali_mixer_free_ac97_bus(ac97_bus_t *bus)
 {
-	ali_t *codec = snd_magic_cast(ali_t, bus->private_data, return);
+	ali_t *codec = bus->private_data;
 	codec->ac97_bus = NULL;
 }
 
 static void snd_ali_mixer_free_ac97(ac97_t *ac97)
 {
-	ali_t *codec = snd_magic_cast(ali_t, ac97->private_data, return);
+	ali_t *codec = ac97->private_data;
 	codec->ac97 = NULL;
 }
 
 static int __devinit snd_ali_mixer(ali_t * codec)
 {
-	ac97_bus_t bus;
-	ac97_t ac97;
+	ac97_template_t ac97;
 	unsigned int idx;
 	int err;
+	static ac97_bus_ops_t ops = {
+		.write = snd_ali_codec_write,
+		.read = snd_ali_codec_read,
+	};
 
-	memset(&bus, 0, sizeof(bus));
-	bus.write = snd_ali_codec_write;
-	bus.read = snd_ali_codec_read;
-	bus.private_data = codec;
-	bus.private_free = snd_ali_mixer_free_ac97_bus;
-	if ((err = snd_ac97_bus(codec->card, &bus, &codec->ac97_bus)) < 0)
+	if ((err = snd_ac97_bus(codec->card, 0, &ops, codec, &codec->ac97_bus)) < 0)
 		return err;
+	codec->ac97_bus->private_free = snd_ali_mixer_free_ac97_bus;
 
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = codec;
@@ -1907,7 +1897,7 @@ static int __devinit snd_ali_mixer(ali_t * codec)
 #ifdef CONFIG_PM
 static int ali_suspend(snd_card_t *card, unsigned int state)
 {
-	ali_t *chip = snd_magic_cast(ali_t, card->pm_private_data, return -EINVAL);
+	ali_t *chip = card->pm_private_data;
 	ali_image_t *im;
 	int i, j;
 
@@ -1943,12 +1933,13 @@ static int ali_suspend(snd_card_t *card, unsigned int state)
 	outl(0xffffffff, ALI_REG(chip, ALI_STOP));
 
 	spin_unlock_irq(&chip->reg_lock);
+	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
 	return 0;
 }
 
 static int ali_resume(snd_card_t *card, unsigned int state)
 {
-	ali_t *chip = snd_magic_cast(ali_t, card->pm_private_data, return -EINVAL);
+	ali_t *chip = card->pm_private_data;
 	ali_image_t *im;
 	int i, j;
 
@@ -1980,6 +1971,7 @@ static int ali_resume(snd_card_t *card, unsigned int state)
 	spin_unlock_irq(&chip->reg_lock);
 
 	snd_ac97_resume(chip->ac97);
+	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
 	
 	return 0;
 }
@@ -1993,15 +1985,13 @@ static int snd_ali_free(ali_t * codec)
 		synchronize_irq(codec->irq);
 		free_irq(codec->irq, (void *)codec);
 	}
-	if (codec->res_port) {
-		release_resource(codec->res_port);
-		kfree_nocheck(codec->res_port);
-	}
+	if (codec->port)
+		pci_release_regions(codec->pci);
 #ifdef CONFIG_PM
 	if (codec->image)
 		kfree(codec->image);
 #endif
-	snd_magic_kfree(codec);
+	kfree(codec);
 	return 0;
 }
 
@@ -2055,11 +2045,12 @@ static int snd_ali_chip_init(ali_t *codec)
 
 static int __devinit snd_ali_resources(ali_t *codec)
 {
+	int err;
+
 	snd_ali_printk("resouces allocation ...\n");
-	if ((codec->res_port = request_region(codec->port, 0x100, "ALI 5451")) == NULL) {
-		snd_printk("Unalbe to request io ports.\n");
-		return -EBUSY;
-	}
+	if ((err = pci_request_regions(codec->pci, "ALI 5451")) < 0)
+		return err;
+	codec->port = pci_resource_start(codec->pci, 0);
 
 	if (request_irq(codec->pci->irq, snd_ali_card_interrupt, SA_INTERRUPT|SA_SHIRQ, "ALI 5451", (void *)codec)) {
 		snd_printk("Unable to request irq.\n");
@@ -2071,7 +2062,7 @@ static int __devinit snd_ali_resources(ali_t *codec)
 }
 static int snd_ali_dev_free(snd_device_t *device) 
 {
-	ali_t *codec=snd_magic_cast(ali_t, device->device_data, return -ENXIO);
+	ali_t *codec=device->device_data;
 	snd_ali_free(codec);
 	return 0;
 }
@@ -2106,7 +2097,7 @@ static int __devinit snd_ali_create(snd_card_t * card,
 		return -ENXIO;
 	}
 
-	if ((codec = snd_magic_kcalloc(ali_t, 0, GFP_KERNEL)) == NULL)
+	if ((codec = kcalloc(1, sizeof(*codec), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 
 	spin_lock_init(&codec->reg_lock);
@@ -2115,7 +2106,6 @@ static int __devinit snd_ali_create(snd_card_t * card,
 	codec->card = card;
 	codec->pci = pci;
 	codec->irq = -1;
-	codec->port = pci_resource_start(pci, 0);
 	pci_read_config_byte(pci, PCI_REVISION_ID, &codec->revision);
 	codec->spdif_support = spdif_support;
 
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index 73b1d3a08..d9ae7e5fe 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -76,8 +76,7 @@
 MODULE_AUTHOR("Bart Hartgers <bart@etpmod.phys.tue.nl>");
 MODULE_DESCRIPTION("Avance Logic ALS4000");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Avance Logic,ALS4000}}");
+MODULE_SUPPORTED_DEVICE("{{Avance Logic,ALS4000}}");
 
 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
 #define SUPPORT_JOYSTICK 1
@@ -93,24 +92,18 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for ALS4000 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for ALS4000 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable ALS4000 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_INDEX_DESC);
 #ifdef SUPPORT_JOYSTICK
 module_param_array(joystick_port, int, boot_devs, 0444);
 MODULE_PARM_DESC(joystick_port, "Joystick port address for ALS4000 soundcard. (0 = disabled)");
-MODULE_PARM_SYNTAX(joystick_port, SNDRV_ENABLED);
 #endif
 
-#define chip_t sb_t
-
 typedef struct {
+	struct pci_dev *pci;
 	unsigned long gcr;
-	struct resource *res_gcr;
 #ifdef SUPPORT_JOYSTICK
 	struct gameport gameport;
 	struct resource *res_joystick;
@@ -304,11 +297,10 @@ static int snd_als4000_playback_prepare(snd_pcm_substream_t *substream)
 
 static int snd_als4000_capture_trigger(snd_pcm_substream_t * substream, int cmd)
 {
-	unsigned long flags;
 	sb_t *chip = snd_pcm_substream_chip(substream);
 	int result = 0;
 	
-	spin_lock_irqsave(&chip->mixer_lock, flags);
+	spin_lock(&chip->mixer_lock);
 	if (cmd == SNDRV_PCM_TRIGGER_START) {
 		chip->mode |= SB_RATE_LOCK_CAPTURE;
 		snd_sbmixer_write(chip, 0xde, capture_cmd(chip));
@@ -318,17 +310,16 @@ static int snd_als4000_capture_trigger(snd_pcm_substream_t * substream, int cmd)
 	} else {
 		result = -EINVAL;
 	}
-	spin_unlock_irqrestore(&chip->mixer_lock, flags);
+	spin_unlock(&chip->mixer_lock);
 	return result;
 }
 
 static int snd_als4000_playback_trigger(snd_pcm_substream_t * substream, int cmd)
 {
-	unsigned long flags;
 	sb_t *chip = snd_pcm_substream_chip(substream);
 	int result = 0;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
 	if (cmd == SNDRV_PCM_TRIGGER_START) {
 		chip->mode |= SB_RATE_LOCK_PLAYBACK;
 		snd_sbdsp_command(chip, playback_cmd(chip).dma_on);
@@ -338,38 +329,35 @@ static int snd_als4000_playback_trigger(snd_pcm_substream_t * substream, int cmd
 	} else {
 		result = -EINVAL;
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return result;
 }
 
 static snd_pcm_uframes_t snd_als4000_capture_pointer(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
 	sb_t *chip = snd_pcm_substream_chip(substream);
 	unsigned int result;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);	
+	spin_lock(&chip->reg_lock);	
 	result = snd_als4000_gcr_read(chip, 0xa4) & 0xffff;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return bytes_to_frames( substream->runtime, result );
 }
 
 static snd_pcm_uframes_t snd_als4000_playback_pointer(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
 	sb_t *chip = snd_pcm_substream_chip(substream);
 	unsigned result;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);	
+	spin_lock(&chip->reg_lock);	
 	result = snd_als4000_gcr_read(chip, 0xa0) & 0xffff;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return bytes_to_frames( substream->runtime, result );
 }
 
 static irqreturn_t snd_als4000_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	sb_t *chip = snd_magic_cast(sb_t, dev_id, return IRQ_NONE);
-	unsigned long flags;
+	sb_t *chip = dev_id;
 	unsigned gcr_status;
 	unsigned sb_status;
 
@@ -385,9 +373,9 @@ static irqreturn_t snd_als4000_interrupt(int irq, void *dev_id, struct pt_regs *
 	/* release the gcr */
 	outb(gcr_status, chip->alt_port + 0xe);
 	
-	spin_lock_irqsave(&chip->mixer_lock, flags);
+	spin_lock(&chip->mixer_lock);
 	sb_status = snd_sbmixer_read(chip, SB_DSP4_IRQSTATUS);
-	spin_unlock_irqrestore(&chip->mixer_lock, flags);
+	spin_unlock(&chip->mixer_lock);
 	
 	if (sb_status & SB_IRQTYPE_8BIT) 
 		snd_sb_ack_8bit(chip);
@@ -506,7 +494,7 @@ static snd_pcm_ops_t snd_als4000_capture_ops = {
 
 static void snd_als4000_pcm_free(snd_pcm_t *pcm)
 {
-	sb_t *chip = snd_magic_cast(sb_t, pcm->private_data, return);
+	sb_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -557,27 +545,26 @@ static void snd_als4000_set_addr(unsigned long gcr,
 
 static void __devinit snd_als4000_configure(sb_t *chip)
 {
-	unsigned long flags;
 	unsigned tmp;
 	int i;
 
 	/* do some more configuration */
-	spin_lock_irqsave(&chip->mixer_lock, flags);
+	spin_lock_irq(&chip->mixer_lock);
 	tmp = snd_sbmixer_read(chip, 0xc0);
 	snd_sbmixer_write(chip, 0xc0, tmp|0x80);
 	/* always select DMA channel 0, since we do not actually use DMA */
 	snd_sbmixer_write(chip, SB_DSP4_DMASETUP, SB_DMASETUP_DMA0);
 	snd_sbmixer_write(chip, 0xc0, tmp&0x7f);
-	spin_unlock_irqrestore(&chip->mixer_lock, flags);
+	spin_unlock_irq(&chip->mixer_lock);
 	
-	spin_lock_irqsave(&chip->reg_lock,flags);
+	spin_lock_irq(&chip->reg_lock);
 	/* magic number. Enables interrupts(?) */
 	snd_als4000_gcr_write(chip, 0x8c, 0x28000);
 	for(i = 0x91; i <= 0x96; ++i)
 		snd_als4000_gcr_write(chip, i, 0);
 	
 	snd_als4000_gcr_write(chip, 0x99, snd_als4000_gcr_read(chip, 0x99));
-	spin_unlock_irqrestore(&chip->reg_lock,flags);
+	spin_unlock_irq(&chip->reg_lock);
 }
 
 static void snd_card_als4000_free( snd_card_t *card )
@@ -595,8 +582,7 @@ static void snd_card_als4000_free( snd_card_t *card )
 		kfree_nocheck(acard->res_joystick);
 	}
 #endif
-	release_resource(acard->res_gcr);
-	kfree_nocheck(acard->res_gcr);
+	pci_release_regions(acard->pci);
 }
 
 static int __devinit snd_card_als4000_probe(struct pci_dev *pci,
@@ -606,7 +592,6 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci,
 	snd_card_t *card;
 	snd_card_als4000_t *acard;
 	unsigned long gcr;
-	struct resource *res_gcr_port;
 	sb_t *chip;
 	opl3_t *opl3;
 	unsigned short word;
@@ -631,11 +616,9 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci,
 		return -ENXIO;
 	}
 
+	if ((err = pci_request_regions(pci, "ALS4000")) < 0)
+		return err;
 	gcr = pci_resource_start(pci, 0);
-	if ((res_gcr_port = request_region(gcr, 0x40, "ALS4000")) == NULL) {
-		snd_printk("unable to grab region 0x%lx-0x%lx\n", gcr, gcr + 0x40 - 1);
-		return -EBUSY;
-	}
 
 	pci_read_config_word(pci, PCI_COMMAND, &word);
 	pci_write_config_word(pci, PCI_COMMAND, word | PCI_COMMAND_IO);
@@ -644,14 +627,13 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci,
 	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 
 			    sizeof( snd_card_als4000_t ) );
 	if (card == NULL) {
-		release_resource(res_gcr_port);
-		kfree_nocheck(res_gcr_port);
+		pci_release_regions(pci);
 		return -ENOMEM;
 	}
 
 	acard = (snd_card_als4000_t *)card->private_data;
+	acard->pci = pci;
 	acard->gcr = gcr;
-	acard->res_gcr = res_gcr_port;
 	card->private_free = snd_card_als4000_free;
 
 	/* disable all legacy ISA stuff except for joystick */
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 8869e7a68..61319fb59 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -1,5 +1,5 @@
 /*
- *   ALSA driver for ATI IXP 150/200/250 AC97 controllers
+ *   ALSA driver for ATI IXP 150/200/250/300 AC97 controllers
  *
  *	Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
  *
@@ -37,8 +37,7 @@
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("ATI IXP AC97 controller");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ATI,IXP150/200/250/300}}");
+MODULE_SUPPORTED_DEVICE("{{ATI,IXP150/200/250/300/400}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -49,19 +48,14 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for ATI IXP controller.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for ATI IXP controller.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable audio part of ATI IXP controller.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(ac97_clock, int, boot_devs, 0444);
 MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz).");
-MODULE_PARM_SYNTAX(ac97_clock, SNDRV_ENABLED ",default:48000");
 module_param_array(spdif_aclink, bool, boot_devs, 0444);
 MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link.");
-MODULE_PARM_SYNTAX(spdif_aclink, SNDRV_ENABLED "," SNDRV_BOOLEAN_TRUE_DESC);
 
 
 /*
@@ -197,7 +191,6 @@ MODULE_PARM_SYNTAX(spdif_aclink, SNDRV_ENABLED "," SNDRV_BOOLEAN_TRUE_DESC);
 #define  ATI_REG_DMA_STATE		(7U<<26)
 
 
-#define ATI_MEM_REGION		256	/* i/o memory size */
 #define ATI_MAX_DESCRIPTORS	256	/* max number of descriptor packets */
 
 
@@ -207,7 +200,6 @@ MODULE_PARM_SYNTAX(spdif_aclink, SNDRV_ENABLED "," SNDRV_BOOLEAN_TRUE_DESC);
 typedef struct snd_atiixp atiixp_t;
 typedef struct snd_atiixp_dma atiixp_dma_t;
 typedef struct snd_atiixp_dma_ops atiixp_dma_ops_t;
-#define chip_t atiixp_t
 
 
 /*
@@ -248,7 +240,6 @@ struct snd_atiixp_dma_ops {
  */
 struct snd_atiixp_dma {
 	const atiixp_dma_ops_t *ops;
-	struct snd_dma_device desc_dev;
 	struct snd_dma_buffer desc_buf;
 	snd_pcm_substream_t *substream;	/* assigned PCM substream */
 	unsigned int buf_addr, buf_bytes;	/* DMA buffer address, bytes */
@@ -266,9 +257,8 @@ struct snd_atiixp {
 	snd_card_t *card;
 	struct pci_dev *pci;
 
-	struct resource *res;		/* memory i/o */
 	unsigned long addr;
-	unsigned long remap_addr;
+	void __iomem *remap_addr;
 	int irq;
 	
 	ac97_bus_t *ac97_bus;
@@ -287,10 +277,6 @@ struct snd_atiixp {
 
 	int spdif_over_aclink;		/* passed from the module option */
 	struct semaphore open_mutex;	/* playback open mutex */
-
-#ifdef CONFIG_PM
-	u32 pci_state[16];
-#endif
 };
 
 
@@ -299,6 +285,7 @@ struct snd_atiixp {
 static struct pci_device_id snd_atiixp_ids[] = {
 	{ 0x1002, 0x4341, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB200 */
 	{ 0x1002, 0x4361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB300 */
+	{ 0x1002, 0x4370, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB400 */
 	{ 0, }
 };
 
@@ -316,7 +303,7 @@ MODULE_DEVICE_TABLE(pci, snd_atiixp_ids);
 static int snd_atiixp_update_bits(atiixp_t *chip, unsigned int reg,
 				 unsigned int mask, unsigned int value)
 {
-	unsigned long addr = chip->remap_addr + reg;
+	void __iomem *addr = chip->remap_addr + reg;
 	unsigned int data, old_data;
 	old_data = data = readl(addr);
 	data &= ~mask;
@@ -376,15 +363,13 @@ static int atiixp_build_dma_packets(atiixp_t *chip, atiixp_dma_t *dma,
 		return -ENOMEM;
 
 	if (dma->desc_buf.area == NULL) {
-		memset(&dma->desc_dev, 0, sizeof(dma->desc_dev));
-		dma->desc_dev.type = SNDRV_DMA_TYPE_DEV;
-		dma->desc_dev.dev = snd_dma_pci_data(chip->pci);
-		if (snd_dma_alloc_pages(&dma->desc_dev, ATI_DESC_LIST_SIZE, &dma->desc_buf) < 0)
+		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+					ATI_DESC_LIST_SIZE, &dma->desc_buf) < 0)
 			return -ENOMEM;
 		dma->period_bytes = dma->periods = 0; /* clear */
 	}
 
-	if (dma->periods == dma->periods && dma->period_bytes == period_bytes)
+	if (dma->periods == periods && dma->period_bytes == period_bytes)
 		return 0;
 
 	/* reset DMA before changing the descriptor table */
@@ -426,7 +411,7 @@ static void atiixp_clear_dma_packets(atiixp_t *chip, atiixp_dma_t *dma, snd_pcm_
 {
 	if (dma->desc_buf.area) {
 		writel(0, chip->remap_addr + dma->ops->llp_offset);
-		snd_dma_free_pages(&dma->desc_dev, &dma->desc_buf);
+		snd_dma_free_pages(&dma->desc_buf);
 		dma->desc_buf.area = NULL;
 	}
 }
@@ -491,7 +476,7 @@ static void snd_atiixp_codec_write(atiixp_t *chip, unsigned short codec, unsigne
 
 static unsigned short snd_atiixp_ac97_read(ac97_t *ac97, unsigned short reg)
 {
-	atiixp_t *chip = snd_magic_cast(atiixp_t, ac97->private_data, return 0xffff);
+	atiixp_t *chip = ac97->private_data;
 	unsigned short data;
 	spin_lock(&chip->ac97_lock);
 	data = snd_atiixp_codec_read(chip, ac97->num, reg);
@@ -502,7 +487,7 @@ static unsigned short snd_atiixp_ac97_read(ac97_t *ac97, unsigned short reg)
 
 static void snd_atiixp_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
 {
-	atiixp_t *chip = snd_magic_cast(atiixp_t, ac97->private_data, return);
+	atiixp_t *chip = ac97->private_data;
 	spin_lock(&chip->ac97_lock);
 	snd_atiixp_codec_write(chip, ac97->num, reg, val);
 	spin_unlock(&chip->ac97_lock);
@@ -653,9 +638,8 @@ static snd_pcm_uframes_t snd_atiixp_pcm_pointer(snd_pcm_substream_t *substream)
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	atiixp_dma_t *dma = (atiixp_dma_t *)runtime->private_data;
 	unsigned int curptr;
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
 	curptr = readl(chip->remap_addr + dma->ops->dt_cur);
 	if (curptr < dma->buf_addr) {
 		snd_printdd("curptr = %x, base = %x\n", curptr, dma->buf_addr);
@@ -667,7 +651,7 @@ static snd_pcm_uframes_t snd_atiixp_pcm_pointer(snd_pcm_substream_t *substream)
 			curptr = 0;
 		}
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return bytes_to_frames(runtime, curptr);
 }
 
@@ -852,7 +836,7 @@ static int snd_atiixp_spdif_prepare(snd_pcm_substream_t *substream)
 {
 	atiixp_t *chip = snd_pcm_substream_chip(substream);
 
-	spin_lock(&chip->reg_lock);
+	spin_lock_irq(&chip->reg_lock);
 	if (chip->spdif_over_aclink) {
 		unsigned int data;
 		/* enable slots 10/11 */
@@ -870,7 +854,7 @@ static int snd_atiixp_spdif_prepare(snd_pcm_substream_t *substream)
 		atiixp_update(chip, CMD, ATI_REG_CMD_SPDF_CONFIG_MASK, 0);
 		atiixp_update(chip, CMD, ATI_REG_CMD_INTERLEAVE_SPDF, 0);
 	}
-	spin_unlock(&chip->reg_lock);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -880,7 +864,7 @@ static int snd_atiixp_playback_prepare(snd_pcm_substream_t *substream)
 	atiixp_t *chip = snd_pcm_substream_chip(substream);
 	unsigned int data;
 
-	spin_lock(&chip->reg_lock);
+	spin_lock_irq(&chip->reg_lock);
 	data = atiixp_read(chip, OUT_DMA_SLOT) & ~ATI_REG_OUT_DMA_SLOT_MASK;
 	switch (substream->runtime->channels) {
 	case 8:
@@ -915,7 +899,7 @@ static int snd_atiixp_playback_prepare(snd_pcm_substream_t *substream)
 	atiixp_update(chip, 6CH_REORDER, ATI_REG_6CH_REORDER_EN,
 		      substream->runtime->channels >= 6 ? ATI_REG_6CH_REORDER_EN: 0);
     
-	spin_unlock(&chip->reg_lock);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -924,11 +908,11 @@ static int snd_atiixp_capture_prepare(snd_pcm_substream_t *substream)
 {
 	atiixp_t *chip = snd_pcm_substream_chip(substream);
 
-	spin_lock(&chip->reg_lock);
+	spin_lock_irq(&chip->reg_lock);
 	atiixp_update(chip, CMD, ATI_REG_CMD_INTERLEAVE_IN,
 		      substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE ?
 		      ATI_REG_CMD_INTERLEAVE_IN : 0);
-	spin_unlock(&chip->reg_lock);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -996,6 +980,7 @@ static snd_pcm_hardware_t snd_atiixp_pcm_hw =
 {
 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
+				 SNDRV_PCM_INFO_RESUME |
 				 SNDRV_PCM_INFO_MMAP_VALID),
 	.formats =		SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
 	.rates =		SNDRV_PCM_RATE_48000,
@@ -1014,7 +999,6 @@ static int snd_atiixp_pcm_open(snd_pcm_substream_t *substream, atiixp_dma_t *dma
 {
 	atiixp_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	unsigned long flags;
 	int err;
 
 	snd_assert(dma->ops && dma->ops->enable_dma, return -EINVAL);
@@ -1036,9 +1020,9 @@ static int snd_atiixp_pcm_open(snd_pcm_substream_t *substream, atiixp_dma_t *dma
 	runtime->private_data = dma;
 
 	/* enable DMA bits */
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	dma->ops->enable_dma(chip, 1);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	dma->opened = 1;
 
 	return 0;
@@ -1308,7 +1292,7 @@ static int __devinit snd_atiixp_pcm_new(atiixp_t *chip)
  */
 static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	atiixp_t *chip = snd_magic_cast(atiixp_t, dev_id, return IRQ_NONE);
+	atiixp_t *chip = dev_id;
 	unsigned int status;
 
 	status = atiixp_read(chip, ISR);
@@ -1355,10 +1339,14 @@ static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id, struct pt_regs *r
 
 static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock)
 {
-	ac97_bus_t bus, *pbus;
-	ac97_t ac97;
+	ac97_bus_t *pbus;
+	ac97_template_t ac97;
 	int i, err;
 	int codec_count;
+	static ac97_bus_ops_t ops = {
+		.write = snd_atiixp_ac97_write,
+		.read = snd_atiixp_ac97_read,
+	};
 	static unsigned int codec_skip[NUM_ATI_CODECS] = {
 		ATI_REG_ISR_CODEC0_NOT_READY,
 		ATI_REG_ISR_CODEC1_NOT_READY,
@@ -1368,13 +1356,10 @@ static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock)
 	if (snd_atiixp_codec_detect(chip) < 0)
 		return -ENXIO;
 
-	memset(&bus, 0, sizeof(bus));
-	bus.write = snd_atiixp_ac97_write;
-	bus.read = snd_atiixp_ac97_read;
-	bus.private_data = chip;
-	bus.clock = clock;
-	if ((err = snd_ac97_bus(chip->card, &bus, &pbus)) < 0)
+	if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0)
 		return err;
+	pbus->clock = clock;
+	pbus->shared_type = AC97_SHARED_TYPE_ATIIXP;	/* shared with modem driver */
 	chip->ac97_bus = pbus;
 
 	codec_count = 0;
@@ -1387,17 +1372,9 @@ static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock)
 		ac97.num = i;
 		ac97.scaps = AC97_SCAP_SKIP_MODEM;
 		if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) {
-			if (chip->codec_not_ready_bits)
-				/* codec(s) was detected but not available.
-				 * return the error
-				 */
-				return err;
-			else {
-				/* codec(s) was NOT detected, so just ignore here */
-				chip->ac97[i] = NULL; /* to be sure */
-				snd_printd("atiixp: codec %d not found\n", i);
-				continue;
-			}
+			chip->ac97[i] = NULL; /* to be sure */
+			snd_printdd("atiixp: codec %d not available for audio\n", i);
+			continue;
 		}
 		codec_count++;
 	}
@@ -1419,7 +1396,7 @@ static int __devinit snd_atiixp_mixer_new(atiixp_t *chip, int clock)
  */
 static int snd_atiixp_suspend(snd_card_t *card, unsigned int state)
 {
-	atiixp_t *chip = snd_magic_cast(atiixp_t, card->pm_private_data, return -EINVAL);
+	atiixp_t *chip = card->pm_private_data;
 	int i;
 
 	for (i = 0; i < NUM_ATI_PCMDEVS; i++)
@@ -1431,7 +1408,6 @@ static int snd_atiixp_suspend(snd_card_t *card, unsigned int state)
 	snd_atiixp_aclink_down(chip);
 	snd_atiixp_chip_stop(chip);
 
-	pci_save_state(chip->pci, chip->pci_state);
 	pci_set_power_state(chip->pci, 3);
 	pci_disable_device(chip->pci);
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
@@ -1440,11 +1416,10 @@ static int snd_atiixp_suspend(snd_card_t *card, unsigned int state)
 
 static int snd_atiixp_resume(snd_card_t *card, unsigned int state)
 {
-	atiixp_t *chip = snd_magic_cast(atiixp_t, card->pm_private_data, return -EINVAL);
+	atiixp_t *chip = card->pm_private_data;
 	int i;
 
 	pci_enable_device(chip->pci);
-	pci_restore_state(chip->pci, chip->pci_state);
 	pci_set_power_state(chip->pci, 0);
 
 	snd_atiixp_aclink_reset(chip);
@@ -1466,7 +1441,7 @@ static int snd_atiixp_resume(snd_card_t *card, unsigned int state)
 
 static void snd_atiixp_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
 {
-	atiixp_t *chip = snd_magic_cast(atiixp_t, entry->private_data, return);
+	atiixp_t *chip = entry->private_data;
 	int i;
 
 	for (i = 0; i < 256; i += 4)
@@ -1494,21 +1469,18 @@ static int snd_atiixp_free(atiixp_t *chip)
 	snd_atiixp_chip_stop(chip);
 	synchronize_irq(chip->irq);
       __hw_end:
-	if (chip->remap_addr)
-		iounmap((void *) chip->remap_addr);
-	if (chip->res) {
-		release_resource(chip->res);
-		kfree_nocheck(chip->res);
-	}
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void *)chip);
-	snd_magic_kfree(chip);
+	if (chip->remap_addr)
+		iounmap(chip->remap_addr);
+	pci_release_regions(chip->pci);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_atiixp_dev_free(snd_device_t *device)
 {
-	atiixp_t *chip = snd_magic_cast(atiixp_t, device->device_data, return -ENXIO);
+	atiixp_t *chip = device->device_data;
 	return snd_atiixp_free(chip);
 }
 
@@ -1528,7 +1500,7 @@ static int __devinit snd_atiixp_create(snd_card_t *card,
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	chip = snd_magic_kcalloc(atiixp_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 
@@ -1538,13 +1510,12 @@ static int __devinit snd_atiixp_create(snd_card_t *card,
 	chip->card = card;
 	chip->pci = pci;
 	chip->irq = -1;
-	chip->addr = pci_resource_start(pci, 0);
-	if ((chip->res = request_mem_region(chip->addr, ATI_MEM_REGION, "ATI IXP AC97")) == NULL) {
-		snd_printk(KERN_ERR "unable to grab I/O memory 0x%lx\n", chip->addr);
-		snd_atiixp_free(chip);
-		return -EBUSY;
+	if ((err = pci_request_regions(pci, "ATI IXP AC97")) < 0) {
+		kfree(chip);
+		return err;
 	}
-	chip->remap_addr = (unsigned long) ioremap_nocache(chip->addr, ATI_MEM_REGION);
+	chip->addr = pci_resource_start(pci, 0);
+	chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci, 0));
 	if (chip->remap_addr == 0) {
 		snd_printk(KERN_ERR "AC'97 space ioremap problem\n");
 		snd_atiixp_free(chip);
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index 5c6a78b98..94eff496d 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -31,23 +31,16 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(pcifix, int, boot_devs, 0444);
 MODULE_PARM_DESC(pcifix, "Enable VIA-workaround for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(pcifix,
-		   SNDRV_ENABLED
-		   ",allows:{{0,Disabled},{1,Latency},{2,Bridge},{3,Both},{255,Auto}},default:4,dialog:check");
 
 MODULE_DESCRIPTION("Aureal vortex");
-MODULE_CLASSES("{sound}");
 MODULE_LICENSE("GPL");
-MODULE_DEVICES("{{Aureal Semiconductor Inc., Aureal Vortex Sound Processor}}");
+MODULE_SUPPORTED_DEVICE("{{Aureal Semiconductor Inc., Aureal Vortex Sound Processor}}");
 
 MODULE_DEVICE_TABLE(pci, snd_vortex_ids);
 
@@ -122,8 +115,7 @@ static void __devinit snd_vortex_workaround(struct pci_dev *vortex, int fix)
 // (see "Management of Cards and Components")
 static int snd_vortex_dev_free(snd_device_t * device)
 {
-	vortex_t *vortex = snd_magic_cast(vortex_t, device->device_data,
-					  return -ENXIO);
+	vortex_t *vortex = device->device_data;
 
 	vortex_gameport_unregister(vortex);
 	vortex_core_shutdown(vortex);
@@ -132,7 +124,7 @@ static int snd_vortex_dev_free(snd_device_t * device)
 	free_irq(vortex->irq, vortex);
 	pci_release_regions(vortex->pci_dev);
 	pci_disable_device(vortex->pci_dev);
-	snd_magic_kfree(vortex);
+	kfree(vortex);
 
 	return 0;
 }
@@ -159,7 +151,7 @@ snd_vortex_create(snd_card_t * card, struct pci_dev *pci, vortex_t ** rchip)
 	}
 	pci_set_dma_mask(pci, VORTEX_DMA_MASK);
 
-	chip = snd_magic_kcalloc(vortex_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 
diff --git a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h
index bf6097d04..7db9acf7b 100644
--- a/sound/pci/au88x0/au88x0.h
+++ b/sound/pci/au88x0/au88x0.h
@@ -180,8 +180,6 @@ struct snd_vortex {
 	u8 rev;
 };
 
-#define chip_t vortex_t
-
 /* Functions. */
 
 /* SRC */
diff --git a/sound/pci/au88x0/au88x0_a3d.c b/sound/pci/au88x0/au88x0_a3d.c
index 8d4919ca2..9ea2ba7bc 100644
--- a/sound/pci/au88x0/au88x0_a3d.c
+++ b/sound/pci/au88x0/au88x0_a3d.c
@@ -567,7 +567,7 @@ static int Vort3DRend_Initialize(vortex_t * v, unsigned short mode)
 	v->xt_mode = mode;	/* this_14 */
 
 	vortex_XtalkHw_init(v);
-	vortex_XtalkHw_SetGains(v, asXtalkGainsAllChan);
+	vortex_XtalkHw_SetGainsAllChan(v);
 	switch (v->xt_mode) {
 	case XT_SPEAKER0:
 		vortex_XtalkHw_ProgramXtalkNarrow(v);
@@ -862,9 +862,8 @@ static int vortex_a3d_register_controls(vortex_t * vortex)
 	/* HRTF controls. */
 	for (i = 0; i < NR_A3D; i++) {
 		if ((kcontrol =
-		     snd_ctl_new1(&vortex_a3d_kcontrol, vortex)) == NULL)
+		     snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL)
 			return -ENOMEM;
-		kcontrol->private_data = &vortex->a3d[i];
 		kcontrol->id.numid = CTRLID_HRTF;
 		kcontrol->info = snd_vortex_a3d_hrtf_info;
 		kcontrol->put = snd_vortex_a3d_hrtf_put;
@@ -874,9 +873,8 @@ static int vortex_a3d_register_controls(vortex_t * vortex)
 	/* ITD controls. */
 	for (i = 0; i < NR_A3D; i++) {
 		if ((kcontrol =
-		     snd_ctl_new1(&vortex_a3d_kcontrol, vortex)) == NULL)
+		     snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL)
 			return -ENOMEM;
-		kcontrol->private_data = &vortex->a3d[i];
 		kcontrol->id.numid = CTRLID_ITD;
 		kcontrol->info = snd_vortex_a3d_itd_info;
 		kcontrol->put = snd_vortex_a3d_itd_put;
@@ -886,9 +884,8 @@ static int vortex_a3d_register_controls(vortex_t * vortex)
 	/* ILD (gains) controls. */
 	for (i = 0; i < NR_A3D; i++) {
 		if ((kcontrol =
-		     snd_ctl_new1(&vortex_a3d_kcontrol, vortex)) == NULL)
+		     snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL)
 			return -ENOMEM;
-		kcontrol->private_data = &vortex->a3d[i];
 		kcontrol->id.numid = CTRLID_GAINS;
 		kcontrol->info = snd_vortex_a3d_ild_info;
 		kcontrol->put = snd_vortex_a3d_ild_put;
@@ -898,9 +895,8 @@ static int vortex_a3d_register_controls(vortex_t * vortex)
 	/* Filter controls. */
 	for (i = 0; i < NR_A3D; i++) {
 		if ((kcontrol =
-		     snd_ctl_new1(&vortex_a3d_kcontrol, vortex)) == NULL)
+		     snd_ctl_new1(&vortex_a3d_kcontrol, &vortex->a3d[i])) == NULL)
 			return -ENOMEM;
-		kcontrol->private_data = &vortex->a3d[i];
 		kcontrol->id.numid = CTRLID_FILTER;
 		kcontrol->info = snd_vortex_a3d_filter_info;
 		kcontrol->put = snd_vortex_a3d_filter_put;
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c
index d8fccffbe..684f639a2 100644
--- a/sound/pci/au88x0/au88x0_core.c
+++ b/sound/pci/au88x0/au88x0_core.c
@@ -2362,7 +2362,7 @@ static void vortex_disable_int(vortex_t * card)
 
 static irqreturn_t vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	vortex_t *vortex = snd_magic_cast(vortex_t, dev_id, return IRQ_NONE);
+	vortex_t *vortex = dev_id;
 	int i, handled;
 	u32 source;
 
diff --git a/sound/pci/au88x0/au88x0_eq.c b/sound/pci/au88x0/au88x0_eq.c
index fdf0014f0..f8f52638c 100644
--- a/sound/pci/au88x0/au88x0_eq.c
+++ b/sound/pci/au88x0/au88x0_eq.c
@@ -40,135 +40,120 @@
 #include "au88x0_eq.h"
 #include "au88x0_eqdata.c"
 
+#define VORTEX_EQ_BASE	 0x2b000
+#define VORTEX_EQ_DEST   (VORTEX_EQ_BASE + 0x410)
+#define VORTEX_EQ_SOURCE (VORTEX_EQ_BASE + 0x430)
+#define VORTEX_EQ_CTRL   (VORTEX_EQ_BASE + 0x440)
+
 /* CEqHw.s */
-static void vortex_EqHw_SetTimeConsts(vortex_t * vortex, u16 a, u16 b)
+static void vortex_EqHw_SetTimeConsts(vortex_t * vortex, u16 gain, u16 level)
 {
-	hwwrite(vortex->mmio, 0x2b3c4, a);
-	hwwrite(vortex->mmio, 0x2b3c8, b);
+	hwwrite(vortex->mmio, 0x2b3c4, gain);
+	hwwrite(vortex->mmio, 0x2b3c8, level);
 }
 
-static void vortex_EqHw_SetLeftCoefs(vortex_t * vortex, u16 a[])
+static void vortex_EqHw_SetLeftCoefs(vortex_t * vortex, u16 coefs[])
 {
 	eqhw_t *eqhw = &(vortex->eq.this04);
-	int eax, i = 0, n /*esp2c */  = 0;
-
-	if (eqhw->this04 <= n)
-		return;
+	int eax, i = 0, n /*esp2c */;
 
-	do {
-		hwwrite(vortex->mmio, 0x2b000 + n * 0x30, a[i + 0]);
-		hwwrite(vortex->mmio, 0x2b004 + n * 0x30, a[i + 1]);
+	for (n = 0; n < eqhw->this04; n++) {
+		hwwrite(vortex->mmio, 0x2b000 + n * 0x30, coefs[i + 0]);
+		hwwrite(vortex->mmio, 0x2b004 + n * 0x30, coefs[i + 1]);
 
 		if (eqhw->this08 == 0) {
-			hwwrite(vortex->mmio, 0x2b008 + n * 0x30, a[i + 2]);
-			hwwrite(vortex->mmio, 0x2b00c + n * 0x30, a[i + 3]);
-			eax = a[i + 4];	//esp24;
+			hwwrite(vortex->mmio, 0x2b008 + n * 0x30, coefs[i + 2]);
+			hwwrite(vortex->mmio, 0x2b00c + n * 0x30, coefs[i + 3]);
+			eax = coefs[i + 4];	//esp24;
 		} else {
-			if (a[2 + i] == 0x8000)
+			if (coefs[2 + i] == 0x8000)
 				eax = 0x7fff;
 			else
-				eax = ~a[2 + i];
+				eax = ~coefs[2 + i];
 			hwwrite(vortex->mmio, 0x2b008 + n * 0x30, eax & 0xffff);
-			if (a[3 + i] == 0x8000)
+			if (coefs[3 + i] == 0x8000)
 				eax = 0x7fff;
 			else
-				eax = ~a[3 + i];
+				eax = ~coefs[3 + i];
 			hwwrite(vortex->mmio, 0x2b00c + n * 0x30, eax & 0xffff);
-			if (a[4 + i] == 0x8000)
+			if (coefs[4 + i] == 0x8000)
 				eax = 0x7fff;
 			else
-				eax = ~a[4 + i];
+				eax = ~coefs[4 + i];
 		}
 		hwwrite(vortex->mmio, 0x2b010 + n * 0x30, eax);
 
-		n++;
 		i += 5;
 	}
-	while (n < eqhw->this04);
 }
 
-static void vortex_EqHw_SetRightCoefs(vortex_t * vortex, u16 a[])
+static void vortex_EqHw_SetRightCoefs(vortex_t * vortex, u16 coefs[])
 {
 	eqhw_t *eqhw = &(vortex->eq.this04);
-	int i = 0, n /*esp2c */  = 0, eax;
+	int i = 0, n /*esp2c */, eax;
 
-	if (eqhw->this04 <= n)
-		return;
-
-	do {
-		hwwrite(vortex->mmio, 0x2b1e0 + n * 0x30, a[0 + i]);
-		hwwrite(vortex->mmio, 0x2b1e4 + n * 0x30, a[1 + i]);
+	for (n = 0; n < eqhw->this04; n++) {
+		hwwrite(vortex->mmio, 0x2b1e0 + n * 0x30, coefs[0 + i]);
+		hwwrite(vortex->mmio, 0x2b1e4 + n * 0x30, coefs[1 + i]);
 
 		if (eqhw->this08 == 0) {
-			hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, a[2 + i]);
-			hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, a[3 + i]);
-			eax = a[4 + i];	//*esp24;
+			hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, coefs[2 + i]);
+			hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, coefs[3 + i]);
+			eax = coefs[4 + i];	//*esp24;
 		} else {
-			if (a[2 + i] == 0x8000)
+			if (coefs[2 + i] == 0x8000)
 				eax = 0x7fff;
 			else
-				eax = ~(a[2 + i]);
+				eax = ~(coefs[2 + i]);
 			hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, eax & 0xffff);
-			if (a[3 + i] == 0x8000)
+			if (coefs[3 + i] == 0x8000)
 				eax = 0x7fff;
 			else
-				eax = ~a[3 + i];
+				eax = ~coefs[3 + i];
 			hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, eax & 0xffff);
-			if (a[4 + i] == 0x8000)
+			if (coefs[4 + i] == 0x8000)
 				eax = 0x7fff;
 			else
-				eax = ~a[4 + i];
+				eax = ~coefs[4 + i];
 		}
 		hwwrite(vortex->mmio, 0x2b1f0 + n * 0x30, eax);
 		i += 5;
-		n++;
 	}
-	while (n < eqhw->this04);
 
 }
 
 static void vortex_EqHw_SetLeftStates(vortex_t * vortex, u16 a[], u16 b[])
 {
 	eqhw_t *eqhw = &(vortex->eq.this04);
-	int i = 0, ebx = 0;
+	int i = 0, ebx;
 
 	hwwrite(vortex->mmio, 0x2b3fc, a[0]);
 	hwwrite(vortex->mmio, 0x2b400, a[1]);
 
-	if (eqhw->this04 < 0)
-		return;
-
-	do {
+	for (ebx = 0; ebx < eqhw->this04; ebx++) {
 		hwwrite(vortex->mmio, 0x2b014 + (i * 0xc), b[i]);
 		hwwrite(vortex->mmio, 0x2b018 + (i * 0xc), b[1 + i]);
 		hwwrite(vortex->mmio, 0x2b01c + (i * 0xc), b[2 + i]);
 		hwwrite(vortex->mmio, 0x2b020 + (i * 0xc), b[3 + i]);
 		i += 4;
-		ebx++;
 	}
-	while (eqhw->this04 > ebx);
 }
 
 static void vortex_EqHw_SetRightStates(vortex_t * vortex, u16 a[], u16 b[])
 {
 	eqhw_t *eqhw = &(vortex->eq.this04);
-	int i = 0, ebx = 0;
+	int i = 0, ebx;
 
 	hwwrite(vortex->mmio, 0x2b404, a[0]);
 	hwwrite(vortex->mmio, 0x2b408, a[1]);
 
-	if (eqhw->this04 < 0)
-		return;
-
-	do {
+	for (ebx = 0; ebx < eqhw->this04; ebx++) {
 		hwwrite(vortex->mmio, 0x2b1f4 + (i * 0xc), b[i]);
 		hwwrite(vortex->mmio, 0x2b1f8 + (i * 0xc), b[1 + i]);
 		hwwrite(vortex->mmio, 0x2b1fc + (i * 0xc), b[2 + i]);
 		hwwrite(vortex->mmio, 0x2b200 + (i * 0xc), b[3 + i]);
 		i += 4;
-		ebx++;
 	}
-	while (ebx < eqhw->this04);
 }
 
 #if 0
@@ -260,60 +245,41 @@ vortex_EqHw_SetRightGainsSingleTarget(vortex_t * vortex, u16 index, u16 b)
 static void vortex_EqHw_SetLeftGainsTarget(vortex_t * vortex, u16 a[])
 {
 	eqhw_t *eqhw = &(vortex->eq.this04);
-	int ebx = 0;
+	int ebx;
 
-	if (eqhw->this04 < 0)
-		return;
-	do {
+	for (ebx = 0; ebx < eqhw->this04; ebx++) {
 		hwwrite(vortex->mmio, 0x2b02c + ebx * 0x30, a[ebx]);
-		ebx++;
 	}
-	while (ebx < eqhw->this04);
 }
 
 static void vortex_EqHw_SetRightGainsTarget(vortex_t * vortex, u16 a[])
 {
 	eqhw_t *eqhw = &(vortex->eq.this04);
-	int ebx = 0;
-
-	if (eqhw->this04 < 0)
-		return;
+	int ebx;
 
-	do {
+	for (ebx = 0; ebx < eqhw->this04; ebx++) {
 		hwwrite(vortex->mmio, 0x2b20c + ebx * 0x30, a[ebx]);
-		ebx++;
 	}
-	while (ebx < eqhw->this04);
 }
 
 static void vortex_EqHw_SetLeftGainsCurrent(vortex_t * vortex, u16 a[])
 {
 	eqhw_t *eqhw = &(vortex->eq.this04);
-	int ebx = 0;
-
-	if (eqhw->this04 < 0)
-		return;
+	int ebx;
 
-	do {
+	for (ebx = 0; ebx < eqhw->this04; ebx++) {
 		hwwrite(vortex->mmio, 0x2b028 + ebx * 0x30, a[ebx]);
-		ebx++;
 	}
-	while (ebx < eqhw->this04);
 }
 
 static void vortex_EqHw_SetRightGainsCurrent(vortex_t * vortex, u16 a[])
 {
 	eqhw_t *eqhw = &(vortex->eq.this04);
-	int ebx = 0;
-
-	if (eqhw->this04 < 0)
-		return;
+	int ebx;
 
-	do {
+	for (ebx = 0; ebx < eqhw->this04; ebx++) {
 		hwwrite(vortex->mmio, 0x2b208 + ebx * 0x30, a[ebx]);
-		ebx++;
 	}
-	while (ebx < eqhw->this04);
 }
 
 #if 0
@@ -384,26 +350,17 @@ static void vortex_EqHw_SetLevels(vortex_t * vortex, u16 a[])
 	eqhw_t *eqhw = &(vortex->eq.this04);
 	int ebx;
 
-	if (eqhw->this04 < 0)
-		return;
-
-	ebx = 0;
-	do {
+	for (ebx = 0; ebx < eqhw->this04; ebx++) {
 		hwwrite(vortex->mmio, 0x2b024 + ebx * 0x30, a[ebx]);
-		ebx++;
 	}
-	while (ebx < eqhw->this04);
 
 	hwwrite(vortex->mmio, 0x2b3cc, a[eqhw->this04]);
 	hwwrite(vortex->mmio, 0x2b3d8, a[eqhw->this04 + 1]);
 
-	ebx = 0;
-	do {
+	for (ebx = 0; ebx < eqhw->this04; ebx++) {
 		hwwrite(vortex->mmio, 0x2b204 + ebx * 0x30,
 			a[ebx + (eqhw->this04 + 2)]);
-		ebx++;
 	}
-	while (ebx < eqhw->this04);
 
 	hwwrite(vortex->mmio, 0x2b3e4, a[2 + (eqhw->this04 * 2)]);
 	hwwrite(vortex->mmio, 0x2b3f0, a[3 + (eqhw->this04 * 2)]);
@@ -466,12 +423,12 @@ static void vortex_EqHw_GetSampleRate(vortex_t * vortex, int *sr)
 #endif
 static void vortex_EqHw_Enable(vortex_t * vortex)
 {
-	hwwrite(vortex->mmio, 0x2b440, 0xf001);
+	hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf001);
 }
 
 static void vortex_EqHw_Disable(vortex_t * vortex)
 {
-	hwwrite(vortex->mmio, 0x2b440, 0xf000);
+	hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf000);
 }
 
 /* Reset (zero) buffers */
@@ -479,16 +436,16 @@ static void vortex_EqHw_ZeroIO(vortex_t * vortex)
 {
 	int i;
 	for (i = 0; i < 0x8; i++)
-		hwwrite(vortex->mmio, 0x2b410 + (i << 2), 0x0);
+		hwwrite(vortex->mmio, VORTEX_EQ_DEST + (i << 2), 0x0);
 	for (i = 0; i < 0x4; i++)
-		hwwrite(vortex->mmio, 0x2b430 + (i << 2), 0x0);
+		hwwrite(vortex->mmio, VORTEX_EQ_SOURCE + (i << 2), 0x0);
 }
 
 static void vortex_EqHw_ZeroA3DIO(vortex_t * vortex)
 {
 	int i;
 	for (i = 0; i < 0x4; i++)
-		hwwrite(vortex->mmio, 0x2b410 + (i << 2), 0x0);
+		hwwrite(vortex->mmio, VORTEX_EQ_DEST + (i << 2), 0x0);
 }
 
 static void vortex_EqHw_ZeroState(vortex_t * vortex)
@@ -659,11 +616,10 @@ vortex_Eqlzr_SetAllBands(vortex_t * vortex, u16 gains[], unsigned long count)
 	if (((eq->this10) * 2 != count) || (eq->this28 == 0))
 		return 1;
 
-	if (0 < count) {
-		for (i = 0; i < count; i++) {
-			eq->this130[i] = gains[i];
-		}
+	for (i = 0; i < count; i++) {
+		eq->this130[i] = gains[i];
 	}
+	
 	if (eq->this54)
 		return 0;
 	return vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex);
diff --git a/sound/pci/au88x0/au88x0_game.c b/sound/pci/au88x0/au88x0_game.c
index 6cc70af17..d47bff1eb 100644
--- a/sound/pci/au88x0/au88x0_game.c
+++ b/sound/pci/au88x0/au88x0_game.c
@@ -96,7 +96,7 @@ static int vortex_game_open(struct gameport *gameport, int mode)
 
 static int vortex_gameport_register(vortex_t * vortex)
 {
-	if ((vortex->gameport = snd_kcalloc(sizeof(struct gameport), GFP_KERNEL)) == NULL) {
+	if ((vortex->gameport = kcalloc(1, sizeof(struct gameport), GFP_KERNEL)) == NULL) {
 		return -1;
 	};
 	
diff --git a/sound/pci/au88x0/au88x0_mixer.c b/sound/pci/au88x0/au88x0_mixer.c
index c4f941344..477b2d15b 100644
--- a/sound/pci/au88x0/au88x0_mixer.c
+++ b/sound/pci/au88x0/au88x0_mixer.c
@@ -13,14 +13,15 @@
 
 static int __devinit snd_vortex_mixer(vortex_t * vortex)
 {
-	ac97_bus_t bus, *pbus;
-	ac97_t ac97;
+	ac97_bus_t *pbus;
+	ac97_template_t ac97;
 	int err;
+	static ac97_bus_ops_t ops = {
+		.write = vortex_codec_write,
+		.read = vortex_codec_read,
+	};
 
-	memset(&bus, 0, sizeof(bus));
-	bus.write = vortex_codec_write;
-	bus.read = vortex_codec_read;
-	if ((err = snd_ac97_bus(vortex->card, &bus, &pbus)) < 0)
+	if ((err = snd_ac97_bus(vortex->card, 0, &ops, NULL, &pbus)) < 0)
 		return err;
 	memset(&ac97, 0, sizeof(ac97));
 	// Intialize AC97 codec stuff.
diff --git a/sound/pci/au88x0/au88x0_mpu401.c b/sound/pci/au88x0/au88x0_mpu401.c
index 3027c35d3..c0c23466e 100644
--- a/sound/pci/au88x0/au88x0_mpu401.c
+++ b/sound/pci/au88x0/au88x0_mpu401.c
@@ -104,7 +104,7 @@ static int __devinit snd_vortex_midi(vortex_t * vortex)
 			 ~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN);
 		return temp;
 	}
-	mpu = snd_magic_cast(mpu401_t, rmidi->private_data, return -ENOMEM);
+	mpu = rmidi->private_data;
 	mpu->cport = (unsigned long)(vortex->mmio + (VORTEX_MIDI_CMD >> 2));
 #endif
 	vortex->rmidi = rmidi;
diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c
index 6df634ebc..8e6322158 100644
--- a/sound/pci/au88x0/au88x0_pcm.c
+++ b/sound/pci/au88x0/au88x0_pcm.c
@@ -28,7 +28,6 @@
 #include <sound/pcm_params.h>
 #include "au88x0.h"
 
-#define chip_t vortex_t
 #define VORTEX_PCM_TYPE(x) (x->name[40])
 
 /* hardware definition */
@@ -189,7 +188,7 @@ static int
 snd_vortex_pcm_hw_params(snd_pcm_substream_t * substream,
 			 snd_pcm_hw_params_t * hw_params)
 {
-	chip_t *chip = snd_pcm_substream_chip(substream);
+	vortex_t *chip = snd_pcm_substream_chip(substream);
 	stream_t *stream = (stream_t *) (substream->runtime->private_data);
 	snd_pcm_sgbuf_t *sgbuf;
 	int err;
@@ -250,7 +249,7 @@ snd_vortex_pcm_hw_params(snd_pcm_substream_t * substream,
 /* hw_free callback */
 static int snd_vortex_pcm_hw_free(snd_pcm_substream_t * substream)
 {
-	chip_t *chip = snd_pcm_substream_chip(substream);
+	vortex_t *chip = snd_pcm_substream_chip(substream);
 	stream_t *stream = (stream_t *) (substream->runtime->private_data);
 
 	// Delete audio routes.
@@ -305,7 +304,7 @@ static int snd_vortex_pcm_prepare(snd_pcm_substream_t * substream)
 /* trigger callback */
 static int snd_vortex_pcm_trigger(snd_pcm_substream_t * substream, int cmd)
 {
-	chip_t *chip = snd_pcm_substream_chip(substream);
+	vortex_t *chip = snd_pcm_substream_chip(substream);
 	stream_t *stream = (stream_t *) substream->runtime->private_data;
 	int dma = stream->dma;
 
diff --git a/sound/pci/au88x0/au88x0_xtalk.c b/sound/pci/au88x0/au88x0_xtalk.c
index 9c0700c6a..df915fa3f 100644
--- a/sound/pci/au88x0/au88x0_xtalk.c
+++ b/sound/pci/au88x0/au88x0_xtalk.c
@@ -540,6 +540,12 @@ vortex_XtalkHw_SetGains(vortex_t * vortex, xtalk_gains_t const gains)
 	}
 }
 
+static void
+vortex_XtalkHw_SetGainsAllChan(vortex_t * vortex)
+{
+	vortex_XtalkHw_SetGains(vortex, asXtalkGainsAllChan);
+}
+
 #if 0
 static void vortex_XtalkHw_GetGains(vortex_t * vortex, xtalk_gains_t gains)
 {
diff --git a/sound/pci/au88x0/au88x0_xtalk.h b/sound/pci/au88x0/au88x0_xtalk.h
index 832f62f7b..0b8d7b640 100644
--- a/sound/pci/au88x0/au88x0_xtalk.h
+++ b/sound/pci/au88x0/au88x0_xtalk.h
@@ -45,10 +45,9 @@ typedef short xtalk_instate_t[XTINST_SZ];
 typedef short xtalk_coefs_t[5][5];
 typedef short xtalk_state_t[5][4];
 
-extern xtalk_gains_t const asXtalkGainsAllChan;
-
 static void vortex_XtalkHw_SetGains(vortex_t * vortex,
 				    xtalk_gains_t const gains);
+static void vortex_XtalkHw_SetGainsAllChan(vortex_t * vortex);
 static void vortex_XtalkHw_SetSampleRate(vortex_t * vortex, int sr);
 static void vortex_XtalkHw_ProgramPipe(vortex_t * vortex);
 static void vortex_XtalkHw_ProgramPipe(vortex_t * vortex);
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 313411a73..c3d65d90f 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -111,8 +111,7 @@
 MODULE_AUTHOR("Andreas Mohr <hw7oshyuv3001@sneakemail.com>");
 MODULE_DESCRIPTION("Aztech AZF3328 (PCI168)");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Aztech,AZF3328}}");
+MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}");
 
 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
 #define SUPPORT_JOYSTICK 1
@@ -170,35 +169,25 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for AZF3328 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for AZF3328 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable AZF3328 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_INDEX_DESC);
 #ifdef SUPPORT_JOYSTICK
 module_param_array(joystick, bool, boot_devs, 0444);
 MODULE_PARM_DESC(joystick, "Enable joystick for AZF3328 soundcard.");
-MODULE_PARM_SYNTAX(joystick, SNDRV_BOOLEAN_FALSE_DESC);
 #endif
 
 typedef struct _snd_azf3328 azf3328_t;
-#define chip_t azf3328_t
 
 struct _snd_azf3328 {
 	int irq;
 
 	unsigned long codec_port;
-	struct resource *res_codec_port;
 	unsigned long io2_port;
-	struct resource *res_io2_port;
 	unsigned long mpu_port;
-	struct resource *res_mpu_port;
 	unsigned long synth_port;
-	struct resource *res_synth_port;
 	unsigned long mixer_port;
-	struct resource *res_mixer_port;
 
 #ifdef SUPPORT_JOYSTICK
 	struct gameport gameport;
@@ -553,8 +542,6 @@ static int snd_azf3328_put_mixer_enum(snd_kcontrol_t * kcontrol, snd_ctl_elem_va
 	return (nreg != oreg);
 }
 
-#define NUM_CONTROLS(ary) (sizeof(ary) / sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_azf3328_mixer_controls[] __devinitdata = {
 	AZF3328_MIXER_SWITCH("Master Playback Switch", IDX_MIXER_PLAY_MASTER, 15, 1),
 	AZF3328_MIXER_VOL_STEREO("Master Playback Volume", IDX_MIXER_PLAY_MASTER, 0x1f, 1),
@@ -650,7 +637,7 @@ static int __devinit snd_azf3328_mixer_new(azf3328_t *chip)
 	
 	/* add mixer controls */
 	sw = snd_azf3328_mixer_controls;
-	for (idx = 0; idx < NUM_CONTROLS(snd_azf3328_mixer_controls); idx++, sw++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_azf3328_mixer_controls); idx++, sw++) {
 		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(sw, chip))) < 0)
 			return err;
 	}
@@ -813,7 +800,6 @@ static int snd_azf3328_capture_prepare(snd_pcm_substream_t * substream)
 
 static int snd_azf3328_playback_trigger(snd_pcm_substream_t * substream, int cmd)
 {
-	unsigned long flags;
 	azf3328_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int result = 0;
@@ -830,7 +816,7 @@ static int snd_azf3328_playback_trigger(snd_pcm_substream_t * substream, int cmd
 
 		snd_azf3328_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT, runtime->rate, snd_pcm_format_width(runtime->format), runtime->channels);
 
-		spin_lock_irqsave(&chip->reg_lock, flags);
+		spin_lock(&chip->reg_lock);
 		/* stop playback */
 		status1 = inw(chip->codec_port+IDX_IO_PLAY_FLAGS);
 		status1 &= ~DMA_RESUME;
@@ -838,11 +824,11 @@ static int snd_azf3328_playback_trigger(snd_pcm_substream_t * substream, int cmd
 	    
 		/* FIXME: clear interrupts or what??? */
 		outw(0xffff, chip->codec_port+IDX_IO_PLAY_IRQMASK);
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		spin_unlock(&chip->reg_lock);
 
 		snd_azf3328_setdmaa(chip, runtime->dma_addr, snd_pcm_lib_period_bytes(substream), snd_pcm_lib_buffer_bytes(substream), 0);
 
-		spin_lock_irqsave(&chip->reg_lock, flags);
+		spin_lock(&chip->reg_lock);
 #ifdef WIN9X
 		/* FIXME: enable playback/recording??? */
 		status1 |= DMA_PLAY_SOMETHING1 | DMA_PLAY_SOMETHING2;
@@ -858,7 +844,7 @@ static int snd_azf3328_playback_trigger(snd_pcm_substream_t * substream, int cmd
 		outw(DMA_PLAY_SOMETHING1|DMA_PLAY_SOMETHING2, chip->codec_port+IDX_IO_PLAY_FLAGS);
 		outw(DMA_RESUME|SOMETHING_ALMOST_ALWAYS_SET|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port+IDX_IO_PLAY_FLAGS);
 #endif
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		spin_unlock(&chip->reg_lock);
 
 		/* now unmute WaveOut */
 		snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0);
@@ -870,7 +856,7 @@ static int snd_azf3328_playback_trigger(snd_pcm_substream_t * substream, int cmd
 		/* mute WaveOut */
 		snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1);
 
-		spin_lock_irqsave(&chip->reg_lock, flags);
+		spin_lock(&chip->reg_lock);
 		/* stop playback */
 		status1 = inw(chip->codec_port+IDX_IO_PLAY_FLAGS);
 
@@ -882,7 +868,7 @@ static int snd_azf3328_playback_trigger(snd_pcm_substream_t * substream, int cmd
 
 		status1 &= ~DMA_PLAY_SOMETHING1;
 		outw(status1, chip->codec_port+IDX_IO_PLAY_FLAGS);
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		spin_unlock(&chip->reg_lock);
 	    
 		/* now unmute WaveOut */
 		snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0);
@@ -906,7 +892,6 @@ static int snd_azf3328_playback_trigger(snd_pcm_substream_t * substream, int cmd
  * should actually be triggered like that */
 static int snd_azf3328_capture_trigger(snd_pcm_substream_t * substream, int cmd)
 {
-	unsigned long flags;
 	azf3328_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int result = 0;
@@ -920,7 +905,7 @@ static int snd_azf3328_capture_trigger(snd_pcm_substream_t * substream, int cmd)
 
 		snd_azf3328_setfmt(chip, IDX_IO_REC_SOUNDFORMAT, runtime->rate, snd_pcm_format_width(runtime->format), runtime->channels);
 
-		spin_lock_irqsave(&chip->reg_lock, flags);
+		spin_lock(&chip->reg_lock);
 		/* stop recording */
 		status1 = inw(chip->codec_port+IDX_IO_REC_FLAGS);
 		status1 &= ~DMA_RESUME;
@@ -928,11 +913,11 @@ static int snd_azf3328_capture_trigger(snd_pcm_substream_t * substream, int cmd)
 	    
 		/* FIXME: clear interrupts or what??? */
 		outw(0xffff, chip->codec_port+IDX_IO_REC_IRQMASK);
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		spin_unlock(&chip->reg_lock);
 
 		snd_azf3328_setdmaa(chip, runtime->dma_addr, snd_pcm_lib_period_bytes(substream), snd_pcm_lib_buffer_bytes(substream), 1);
 
-		spin_lock_irqsave(&chip->reg_lock, flags);
+		spin_lock(&chip->reg_lock);
 #ifdef WIN9X
 		/* FIXME: enable playback/recording??? */
 		status1 |= DMA_PLAY_SOMETHING1 | DMA_PLAY_SOMETHING2;
@@ -948,13 +933,13 @@ static int snd_azf3328_capture_trigger(snd_pcm_substream_t * substream, int cmd)
 		outw(DMA_PLAY_SOMETHING1|DMA_PLAY_SOMETHING2, chip->codec_port+IDX_IO_REC_FLAGS);
 		outw(DMA_RESUME|SOMETHING_ALMOST_ALWAYS_SET|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port+IDX_IO_REC_FLAGS);
 #endif
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		spin_unlock(&chip->reg_lock);
 
 		snd_azf3328_dbgio(chip, "trigger2");
 		chip->is_playing = 1;
 		break;
         case SNDRV_PCM_TRIGGER_STOP:
-		spin_lock_irqsave(&chip->reg_lock, flags);
+		spin_lock(&chip->reg_lock);
 		/* stop recording */
 		status1 = inw(chip->codec_port+IDX_IO_REC_FLAGS);
 
@@ -966,7 +951,7 @@ static int snd_azf3328_capture_trigger(snd_pcm_substream_t * substream, int cmd)
 
 		status1 &= ~DMA_PLAY_SOMETHING1;
 		outw(status1, chip->codec_port+IDX_IO_REC_FLAGS);
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		spin_unlock(&chip->reg_lock);
 	    
 		chip->is_playing = 0;
 		break;
@@ -990,16 +975,13 @@ static snd_pcm_uframes_t snd_azf3328_playback_pointer(snd_pcm_substream_t * subs
 	unsigned long bufptr, playptr;
 	unsigned long result;
 	snd_pcm_uframes_t frmres;
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
 #ifdef QUERY_HARDWARE
 	bufptr = inl(chip->codec_port+IDX_IO_PLAY_DMA_START_1);
 #else
 	bufptr = substream->runtime->dma_addr;
 #endif
 	playptr = inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
 
 	result = playptr - bufptr;
 	frmres = bytes_to_frames( substream->runtime, result );
@@ -1013,16 +995,13 @@ static snd_pcm_uframes_t snd_azf3328_capture_pointer(snd_pcm_substream_t * subst
 	unsigned long bufptr, recptr;
 	unsigned long result;
 	snd_pcm_uframes_t frmres;
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
 #ifdef QUERY_HARDWARE
 	bufptr = inl(chip->codec_port+IDX_IO_REC_DMA_START_1);
 #else
 	bufptr = substream->runtime->dma_addr;
 #endif
 	recptr = inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
 
 	result = recptr - bufptr;
 	frmres = bytes_to_frames( substream->runtime, result );
@@ -1032,7 +1011,7 @@ static snd_pcm_uframes_t snd_azf3328_capture_pointer(snd_pcm_substream_t * subst
 
 static irqreturn_t snd_azf3328_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	azf3328_t *chip = snd_magic_cast(azf3328_t, dev_id, return IRQ_NONE);
+	azf3328_t *chip = dev_id;
 	unsigned int status, which;
 	static unsigned long count;
 
@@ -1232,7 +1211,7 @@ static snd_pcm_ops_t snd_azf3328_capture_ops = {
 
 static void snd_azf3328_pcm_free(snd_pcm_t *pcm)
 {
-	azf3328_t *chip = snd_magic_cast(azf3328_t, pcm->private_data, return);
+	azf3328_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1287,36 +1266,17 @@ static int snd_azf3328_free(azf3328_t *chip)
 		kfree_nocheck(chip->res_joystick);
 	}
 #endif
-        if (chip->res_codec_port) {
-		release_resource(chip->res_codec_port);
-		kfree_nocheck(chip->res_codec_port);
-	}
-        if (chip->res_io2_port) {
-		release_resource(chip->res_io2_port);
-		kfree_nocheck(chip->res_io2_port);
-	}
-        if (chip->res_mpu_port) {
-		release_resource(chip->res_mpu_port);
-		kfree_nocheck(chip->res_mpu_port);
-	}
-        if (chip->res_synth_port) {
-		release_resource(chip->res_synth_port);
-		kfree_nocheck(chip->res_synth_port);
-	}
-        if (chip->res_mixer_port) {
-		release_resource(chip->res_mixer_port);
-		kfree_nocheck(chip->res_mixer_port);
-	}
         if (chip->irq >= 0)
 		free_irq(chip->irq, (void *)chip);
+	pci_release_regions(chip->pci);
 
-        snd_magic_kfree(chip);
+        kfree(chip);
         return 0;
 }
 
 static int snd_azf3328_dev_free(snd_device_t *device)
 {
-	azf3328_t *chip = snd_magic_cast(azf3328_t, device->device_data, return -ENXIO);
+	azf3328_t *chip = device->device_data;
 	return snd_azf3328_free(chip);
 }
 
@@ -1345,7 +1305,6 @@ static int __devinit snd_azf3328_create(snd_card_t * card,
                                          unsigned long device_type,
                                          azf3328_t ** rchip)
 {
-	unsigned long flags;
 	azf3328_t *chip;
 	int err;
 	static snd_device_ops_t ops = {
@@ -1358,7 +1317,7 @@ static int __devinit snd_azf3328_create(snd_card_t * card,
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	chip = snd_magic_kcalloc(azf3328_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
@@ -1373,36 +1332,16 @@ static int __devinit snd_azf3328_create(snd_card_t * card,
 		return -ENXIO;
 	}
 
-	chip->codec_port = pci_resource_start(pci, 0);
-	if ((chip->res_codec_port = request_region(chip->codec_port, 0x80, "Aztech AZF3328 I/O")) == NULL) {
-		snd_printk("unable to grab I/O port at 0x%lx-0x%lx\n", chip->codec_port, chip->codec_port + 0x80 - 1);
-		snd_azf3328_free(chip);
-		return -EBUSY;
+	if ((err = pci_request_regions(pci, "Aztech AZF3328")) < 0) {
+		kfree(chip);
+		return err;
 	}
+
+	chip->codec_port = pci_resource_start(pci, 0);
 	chip->io2_port = pci_resource_start(pci, 1);
-	if ((chip->res_io2_port = request_region(chip->io2_port, 0x08, "Aztech AZF3328 I/O 2")) == NULL) {
-		snd_printk("unable to grab I/O 2 port at 0x%lx-0x%lx\n", chip->io2_port, chip->io2_port + 0x08 - 1);
-		snd_azf3328_free(chip);
-		return -EBUSY;
-	}
 	chip->mpu_port = pci_resource_start(pci, 2);
-	if ((chip->res_mpu_port = request_region(chip->mpu_port, 0x04, "Aztech AZF3328 MPU401")) == NULL) {
-		snd_printk("unable to grab MPU401 port at 0x%lx-0x%lx\n", chip->mpu_port, chip->mpu_port + 0x04 - 1);
-		snd_azf3328_free(chip);
-		return -EBUSY;
-	}
 	chip->synth_port = pci_resource_start(pci, 3);
-	if ((chip->res_synth_port = request_region(chip->synth_port, 0x08, "Aztech AZF3328 OPL3")) == NULL) {
-		snd_printk("unable to grab OPL3 port at 0x%lx-0x%lx\n", chip->synth_port, chip->synth_port + 0x08 - 1);
-		snd_azf3328_free(chip);
-		return -EBUSY;
-	}
 	chip->mixer_port = pci_resource_start(pci, 4);
-	if ((chip->res_mixer_port = request_region(chip->mixer_port, 0x40, "Aztech AZF3328 Mixer")) == NULL) {
-                snd_printk("unable to grab mixer port at 0x%lx-0x%lx\n", chip->mixer_port, chip->mixer_port + 0x40 - 1);
-		snd_azf3328_free(chip);
-		return -EBUSY;
-	}
 
 	if (request_irq(pci->irq, snd_azf3328_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
@@ -1435,13 +1374,13 @@ static int __devinit snd_azf3328_create(snd_card_t * card,
 #endif
 
 	/* standard chip init stuff */
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	outb(DMA_PLAY_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port + IDX_IO_PLAY_FLAGS);
 	outb(DMA_PLAY_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port + IDX_IO_SOMETHING_FLAGS);
 	outb(DMA_PLAY_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port + IDX_IO_REC_FLAGS);
 	outb(0x0, chip->codec_port + IDX_IO_IRQ63H);
 
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 
 	snd_card_set_dev(card, &pci->dev);
 
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 3c232660f..2e0ba15eb 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -38,8 +38,7 @@
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
 MODULE_DESCRIPTION("Brooktree Bt87x audio driver");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Brooktree,Bt878},"
+MODULE_SUPPORTED_DEVICE("{{Brooktree,Bt878},"
 		"{Brooktree,Bt879}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
@@ -50,16 +49,12 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Bt87x soundcard");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Bt87x soundcard");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Bt87x soundcard");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(digital_rate, int, boot_devs, 0444);
 MODULE_PARM_DESC(digital_rate, "Digital input rate for Bt87x soundcard");
-MODULE_PARM_SYNTAX(digital_rate, SNDRV_ENABLED);
 
 
 #ifndef PCI_VENDOR_ID_BROOKTREE
@@ -152,14 +147,12 @@ MODULE_PARM_SYNTAX(digital_rate, SNDRV_ENABLED);
 /* SYNC, one WRITE per line, one extra WRITE per page boundary, SYNC, JUMP */
 #define MAX_RISC_SIZE ((1 + 255 + (PAGE_ALIGN(255 * 4092) / PAGE_SIZE - 1) + 1 + 1) * 8)
 
-#define chip_t bt87x_t
 typedef struct snd_bt87x bt87x_t;
 struct snd_bt87x {
 	snd_card_t *card;
 	struct pci_dev *pci;
 
 	void *mmio;
-	struct resource *res_mmio;
 	int irq;
 
 	int dig_rate;
@@ -168,7 +161,6 @@ struct snd_bt87x {
 	long opened;
 	snd_pcm_substream_t *substream;
 
-	struct snd_dma_device dma_dev;
 	struct snd_dma_buffer dma_risc;
 	unsigned int line_bytes;
 	unsigned int lines;
@@ -197,10 +189,8 @@ static int snd_bt87x_create_risc(bt87x_t *chip, snd_pcm_substream_t *substream,
 	u32 *risc;
 
 	if (chip->dma_risc.area == NULL) {
-		memset(&chip->dma_dev, 0, sizeof(chip->dma_dev));
-		chip->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-		chip->dma_dev.dev = snd_dma_pci_data(chip->pci);
-		if (snd_dma_alloc_pages(&chip->dma_dev, PAGE_ALIGN(MAX_RISC_SIZE), &chip->dma_risc) < 0)
+		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+					PAGE_ALIGN(MAX_RISC_SIZE), &chip->dma_risc) < 0)
 			return -ENOMEM;
 	}
 	risc = (u32 *)chip->dma_risc.area;
@@ -244,14 +234,14 @@ static int snd_bt87x_create_risc(bt87x_t *chip, snd_pcm_substream_t *substream,
 static void snd_bt87x_free_risc(bt87x_t *chip)
 {
 	if (chip->dma_risc.area) {
-		snd_dma_free_pages(&chip->dma_dev, &chip->dma_risc);
+		snd_dma_free_pages(&chip->dma_risc);
 		chip->dma_risc.area = NULL;
 	}
 }
 
 static irqreturn_t snd_bt87x_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	bt87x_t *chip = snd_magic_cast(bt87x_t, dev_id, return IRQ_NONE);
+	bt87x_t *chip = dev_id;
 	unsigned int status;
 
 	status = snd_bt87x_readl(chip, REG_INT_STAT);
@@ -314,7 +304,7 @@ static snd_pcm_hardware_t snd_bt87x_analog_hw = {
 		SNDRV_PCM_INFO_MMAP_VALID,
 	.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
 	.rates = SNDRV_PCM_RATE_KNOT,
-	.rate_min = 119467,
+	.rate_min = 119466,
 	.rate_max = 448000,
 	.channels_min = 1,
 	.channels_max = 1,
@@ -356,20 +346,21 @@ static int snd_bt87x_set_digital_hw(bt87x_t *chip, snd_pcm_runtime_t *runtime)
 
 static int snd_bt87x_set_analog_hw(bt87x_t *chip, snd_pcm_runtime_t *runtime)
 {
-	static unsigned int rates[] = {
-		119467, 128000, 137846, 149333, 162909, 179200,
-		199111, 224000, 256000, 298667, 358400, 448000
+	static ratnum_t analog_clock = {
+		.num = 1792000,
+		.den_min = 4,
+		.den_max = 15,
+		.den_step = 1
 	};
-	static snd_pcm_hw_constraint_list_t constraint_rates = {
-		.count = ARRAY_SIZE(rates),
-		.list = rates,
-		.mask = 0,
+	static snd_pcm_hw_constraint_ratnums_t constraint_rates = {
+		.nrats = 1,
+		.rats = &analog_clock
 	};
 
 	chip->reg_control &= ~CTL_DA_IOM_DA;
 	runtime->hw = snd_bt87x_analog_hw;
-	return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
-					  &constraint_rates);
+	return snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+					     &constraint_rates);
 }
 
 static int snd_bt87x_pcm_open(snd_pcm_substream_t *substream)
@@ -439,25 +430,22 @@ static int snd_bt87x_prepare(snd_pcm_substream_t *substream)
 {
 	bt87x_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	unsigned long flags;
 	int decimation;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	chip->reg_control &= ~(CTL_DA_SDR_MASK | CTL_DA_SBR);
-	decimation = (1792000 + 5) / runtime->rate;
+	decimation = (1792000 + runtime->rate / 4) / runtime->rate;
 	chip->reg_control |= decimation << CTL_DA_SDR_SHIFT;
 	if (runtime->format == SNDRV_PCM_FORMAT_S8)
 		chip->reg_control |= CTL_DA_SBR;
 	snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
 static int snd_bt87x_start(bt87x_t *chip)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
 	chip->current_line = 0;
 	chip->reg_control |= CTL_FIFO_ENABLE | CTL_RISC_ENABLE | CTL_ACAP_EN;
 	snd_bt87x_writel(chip, REG_RISC_STRT_ADD, chip->dma_risc.addr);
@@ -465,20 +453,18 @@ static int snd_bt87x_start(bt87x_t *chip)
 			 chip->line_bytes | (chip->lines << 16));
 	snd_bt87x_writel(chip, REG_INT_MASK, MY_INTERRUPTS);
 	snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return 0;
 }
 
 static int snd_bt87x_stop(bt87x_t *chip)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
 	chip->reg_control &= ~(CTL_FIFO_ENABLE | CTL_RISC_ENABLE | CTL_ACAP_EN);
 	snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control);
 	snd_bt87x_writel(chip, REG_INT_MASK, 0);
 	snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return 0;
 }
 
@@ -536,17 +522,16 @@ static int snd_bt87x_capture_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_v
 static int snd_bt87x_capture_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)
 {
 	bt87x_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	u32 old_control;
 	int changed;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	old_control = chip->reg_control;
 	chip->reg_control = (chip->reg_control & ~CTL_A_GAIN_MASK)
 		| (value->value.integer.value[0] << CTL_A_GAIN_SHIFT);
 	snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control);
 	changed = old_control != chip->reg_control;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return changed;
 }
 
@@ -578,17 +563,16 @@ static int snd_bt87x_capture_boost_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_va
 static int snd_bt87x_capture_boost_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)
 {
 	bt87x_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	u32 old_control;
 	int changed;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	old_control = chip->reg_control;
 	chip->reg_control = (chip->reg_control & ~CTL_A_G2X)
 		| (value->value.integer.value[0] ? CTL_A_G2X : 0);
 	snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control);
 	changed = chip->reg_control != old_control;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return changed;
 }
 
@@ -624,17 +608,16 @@ static int snd_bt87x_capture_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_v
 static int snd_bt87x_capture_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)
 {
 	bt87x_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	u32 old_control;
 	int changed;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	old_control = chip->reg_control;
 	chip->reg_control = (chip->reg_control & ~CTL_A_SEL_MASK)
 		| (value->value.enumerated.item[0] << CTL_A_SEL_SHIFT);
 	snd_bt87x_writel(chip, REG_GPIO_DMA_CTL, chip->reg_control);
 	changed = chip->reg_control != old_control;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return changed;
 }
 
@@ -655,19 +638,16 @@ static int snd_bt87x_free(bt87x_t *chip)
 
 		iounmap(chip->mmio);
 	}
-	if (chip->res_mmio) {
-		release_resource(chip->res_mmio);
-		kfree_nocheck(chip->res_mmio);
-	}
 	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
-	snd_magic_kfree(chip);
+	pci_release_regions(chip->pci);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_bt87x_dev_free(snd_device_t *device)
 {
-	bt87x_t *chip = snd_magic_cast(bt87x_t, device->device_data, return -ENXIO);
+	bt87x_t *chip = device->device_data;
 	return snd_bt87x_free(chip);
 }
 
@@ -705,7 +685,7 @@ static int __devinit snd_bt87x_create(snd_card_t *card,
 	if (err < 0)
 		return err;
 
-	chip = snd_magic_kcalloc(bt87x_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (!chip)
 		return -ENOMEM;
 	chip->card = card;
@@ -713,13 +693,9 @@ static int __devinit snd_bt87x_create(snd_card_t *card,
 	chip->irq = -1;
 	spin_lock_init(&chip->reg_lock);
 
-	chip->res_mmio = request_mem_region(pci_resource_start(pci, 0),
-					    pci_resource_len(pci, 0),
-					    "Bt87x audio");
-	if (!chip->res_mmio) {
-		snd_bt87x_free(chip);
-		snd_printk(KERN_ERR "cannot allocate io memory\n");
-		return -EBUSY;
+	if ((err = pci_request_regions(pci, "Bt87x audio")) < 0) {
+		kfree(chip);
+		return err;
 	}
 	chip->mmio = ioremap_nocache(pci_resource_start(pci, 0),
 				     pci_resource_len(pci, 0));
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index a5ce7233a..768a7a224 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -43,8 +43,7 @@
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("C-Media CMI8x38 PCI");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{C-Media,CMI8738},"
+MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8738},"
 		"{C-Media,CMI8738B},"
 		"{C-Media,CMI8338A},"
 		"{C-Media,CMI8338B}}");
@@ -66,25 +65,19 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for C-Media PCI soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for C-Media PCI soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable C-Media PCI soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_ENABLED ",allows:{{0},{0x330},{0x320},{0x310},{0x300}},dialog:list");
 module_param_array(fm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(fm_port, "FM port.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_ENABLED ",allows:{{0},{0x388},{0x3c8},{0x3e0},{0x3e8}},dialog:list");
 module_param_array(soft_ac3, bool, boot_devs, 0444);
 MODULE_PARM_DESC(soft_ac3, "Sofware-conversion of raw SPDIF packets (model 033 only).");
 #ifdef SUPPORT_JOYSTICK
 module_param_array(joystick_port, int, boot_devs, 0444);
 MODULE_PARM_DESC(joystick_port, "Joystick port address.");
-MODULE_PARM_SYNTAX(joystick_port, SNDRV_ENABLED ",allows:{{0},{1},{0x200},{0x201}},dialog:list");
 #endif
 
 #ifndef PCI_DEVICE_ID_CMEDIA_CM8738
@@ -405,8 +398,6 @@ MODULE_PARM_SYNTAX(joystick_port, SNDRV_ENABLED ",allows:{{0},{1},{0x200},{0x201
 typedef struct snd_stru_cmipci cmipci_t;
 typedef struct snd_stru_cmipci_pcm cmipci_pcm_t;
 
-#define chip_t cmipci_t
-
 struct snd_stru_cmipci_pcm {
 	snd_pcm_substream_t *substream;
 	int running;		/* dac/adc running? */
@@ -442,7 +433,6 @@ struct snd_stru_cmipci {
 	int irq;
 
 	unsigned long iobase;
-	struct resource *res_iobase;
 	unsigned int ctrl;	/* FUNCTRL0 current value */
 
 	snd_pcm_t *pcm;		/* DAC/ADC PCM */
@@ -699,15 +689,13 @@ static snd_pcm_hw_constraint_list_t hw_constraints_channels_6 = {
 
 static int set_dac_channels(cmipci_t *cm, cmipci_pcm_t *rec, int channels)
 {
-	unsigned long flags;
-
 	if (channels > 2) {
 		if (! cm->can_multi_ch)
 			return -EINVAL;
 		if (rec->fmt != 0x03) /* stereo 16bit only */
 			return -EINVAL;
 
-		spin_lock_irqsave(&cm->reg_lock, flags);
+		spin_lock_irq(&cm->reg_lock);
 		snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG);
 		snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC);
 		if (channels > 4) {
@@ -724,18 +712,18 @@ static int set_dac_channels(cmipci_t *cm, cmipci_pcm_t *rec, int channels)
 			snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C);
 			snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER);
 		}
-		spin_unlock_irqrestore(&cm->reg_lock, flags);
+		spin_unlock_irq(&cm->reg_lock);
 
 	} else {
 		if (cm->can_multi_ch) {
-			spin_lock_irqsave(&cm->reg_lock, flags);
+			spin_lock_irq(&cm->reg_lock);
 			snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_NXCHG);
 			snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D);
 			snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C);
 			snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C);
 			snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER);
 			snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_XCHGDAC);
-			spin_unlock_irqrestore(&cm->reg_lock, flags);
+			spin_unlock_irq(&cm->reg_lock);
 		}
 	}
 	return 0;
@@ -749,7 +737,6 @@ static int set_dac_channels(cmipci_t *cm, cmipci_pcm_t *rec, int channels)
 static int snd_cmipci_pcm_prepare(cmipci_t *cm, cmipci_pcm_t *rec,
 				 snd_pcm_substream_t *substream)
 {
-	unsigned long flags;
 	unsigned int reg, freq, val;
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
@@ -777,7 +764,7 @@ static int snd_cmipci_pcm_prepare(cmipci_t *cm, cmipci_pcm_t *rec,
 		rec->period_size = (rec->period_size * runtime->channels) / 2;
 	}
 
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 
 	/* set buffer address */
 	reg = rec->ch ? CM_REG_CH1_FRAME1 : CM_REG_CH0_FRAME1;
@@ -822,7 +809,7 @@ static int snd_cmipci_pcm_prepare(cmipci_t *cm, cmipci_pcm_t *rec,
 	//snd_printd("cmipci: chformat = %08x\n", val);
 
 	rec->running = 0;
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 
 	return 0;
 }
@@ -954,13 +941,12 @@ static int snd_cmipci_spdif_default_get(snd_kcontrol_t *kcontrol,
 					snd_ctl_elem_value_t *ucontrol)
 {
 	cmipci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int i;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	for (i = 0; i < 4; i++)
 		ucontrol->value.iec958.status[i] = (chip->dig_status >> (i * 8)) & 0xff;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -968,17 +954,16 @@ static int snd_cmipci_spdif_default_put(snd_kcontrol_t * kcontrol,
 					 snd_ctl_elem_value_t * ucontrol)
 {
 	cmipci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int i, change;
 	unsigned int val;
 
 	val = 0;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	for (i = 0; i < 4; i++)
 		val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
 	change = val != chip->dig_status;
 	chip->dig_status = val;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return change;
 }
 
@@ -1030,13 +1015,12 @@ static int snd_cmipci_spdif_stream_get(snd_kcontrol_t *kcontrol,
 				       snd_ctl_elem_value_t *ucontrol)
 {
 	cmipci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int i;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	for (i = 0; i < 4; i++)
 		ucontrol->value.iec958.status[i] = (chip->dig_pcm_status >> (i * 8)) & 0xff;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -1044,17 +1028,16 @@ static int snd_cmipci_spdif_stream_put(snd_kcontrol_t *kcontrol,
 				       snd_ctl_elem_value_t *ucontrol)
 {
 	cmipci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int i, change;
 	unsigned int val;
 
 	val = 0;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	for (i = 0; i < 4; i++)
 		val |= (unsigned int)ucontrol->value.iec958.status[i] << (i * 8);
 	change = val != chip->dig_pcm_status;
 	chip->dig_pcm_status = val;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return change;
 }
 
@@ -1072,30 +1055,36 @@ static snd_kcontrol_new_t snd_cmipci_spdif_stream __devinitdata =
  */
 
 /* save mixer setting and mute for AC3 playback */
-static void save_mixer_state(cmipci_t *cm)
+static int save_mixer_state(cmipci_t *cm)
 {
 	if (! cm->mixer_insensitive) {
+		snd_ctl_elem_value_t *val;
 		unsigned int i;
+
+		val = kmalloc(sizeof(*val), GFP_ATOMIC);
+		if (!val)
+			return -ENOMEM;
 		for (i = 0; i < CM_SAVED_MIXERS; i++) {
 			snd_kcontrol_t *ctl = cm->mixer_res_ctl[i];
 			if (ctl) {
-				snd_ctl_elem_value_t val;
 				int event;
-				memset(&val, 0, sizeof(val));
-				ctl->get(ctl, &val);
-				cm->mixer_res_status[i] = val.value.integer.value[0];
-				val.value.integer.value[0] = cm_saved_mixer[i].toggle_on;
+				memset(val, 0, sizeof(*val));
+				ctl->get(ctl, val);
+				cm->mixer_res_status[i] = val->value.integer.value[0];
+				val->value.integer.value[0] = cm_saved_mixer[i].toggle_on;
 				event = SNDRV_CTL_EVENT_MASK_INFO;
-				if (cm->mixer_res_status[i] != val.value.integer.value[0]) {
-					ctl->put(ctl, &val); /* toggle */
+				if (cm->mixer_res_status[i] != val->value.integer.value[0]) {
+					ctl->put(ctl, val); /* toggle */
 					event |= SNDRV_CTL_EVENT_MASK_VALUE;
 				}
 				ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 				snd_ctl_notify(cm->card, event, &ctl->id);
 			}
 		}
+		kfree(val);
 		cm->mixer_insensitive = 1;
 	}
+	return 0;
 }
 
 
@@ -1103,27 +1092,32 @@ static void save_mixer_state(cmipci_t *cm)
 static void restore_mixer_state(cmipci_t *cm)
 {
 	if (cm->mixer_insensitive) {
+		snd_ctl_elem_value_t *val;
 		unsigned int i;
+
+		val = kmalloc(sizeof(*val), GFP_KERNEL);
+		if (!val)
+			return;
 		cm->mixer_insensitive = 0; /* at first clear this;
 					      otherwise the changes will be ignored */
 		for (i = 0; i < CM_SAVED_MIXERS; i++) {
 			snd_kcontrol_t *ctl = cm->mixer_res_ctl[i];
 			if (ctl) {
-				snd_ctl_elem_value_t val;
 				int event;
 
-				memset(&val, 0, sizeof(val));
+				memset(val, 0, sizeof(*val));
 				ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
-				ctl->get(ctl, &val);
+				ctl->get(ctl, val);
 				event = SNDRV_CTL_EVENT_MASK_INFO;
-				if (val.value.integer.value[0] != cm->mixer_res_status[i]) {
-					val.value.integer.value[0] = cm->mixer_res_status[i];
-					ctl->put(ctl, &val);
+				if (val->value.integer.value[0] != cm->mixer_res_status[i]) {
+					val->value.integer.value[0] = cm->mixer_res_status[i];
+					ctl->put(ctl, val);
 					event |= SNDRV_CTL_EVENT_MASK_VALUE;
 				}
 				snd_ctl_notify(cm->card, event, &ctl->id);
 			}
 		}
+		kfree(val);
 	}
 }
 
@@ -1175,17 +1169,17 @@ static void setup_ac3(cmipci_t *cm, snd_pcm_substream_t *subs, int do_ac3, int r
 	}
 }
 
-static void setup_spdif_playback(cmipci_t *cm, snd_pcm_substream_t *subs, int up, int do_ac3)
+static int setup_spdif_playback(cmipci_t *cm, snd_pcm_substream_t *subs, int up, int do_ac3)
 {
-	int rate;
-	unsigned long flags;
+	int rate, err;
 
 	rate = subs->runtime->rate;
 
 	if (up && do_ac3)
-		save_mixer_state(cm);
+		if ((err = save_mixer_state(cm)) < 0)
+			return err;
 
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	cm->spdif_playback_avail = up;
 	if (up) {
 		/* they are controlled via "IEC958 Output Switch" */
@@ -1207,7 +1201,8 @@ static void setup_spdif_playback(cmipci_t *cm, snd_pcm_substream_t *subs, int up
 		snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_PLAYBACK_SPDF);
 		setup_ac3(cm, subs, 0, 0);
 	}
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
+	return 0;
 }
 
 
@@ -1220,13 +1215,15 @@ static int snd_cmipci_playback_prepare(snd_pcm_substream_t *substream)
 {
 	cmipci_t *cm = snd_pcm_substream_chip(substream);
 	int rate = substream->runtime->rate;
-	int do_spdif, do_ac3 = 0;
+	int err, do_spdif, do_ac3 = 0;
+
 	do_spdif = ((rate == 44100 || rate == 48000) &&
 		    substream->runtime->format == SNDRV_PCM_FORMAT_S16_LE &&
 		    substream->runtime->channels == 2);
 	if (do_spdif && cm->can_ac3_hw) 
 		do_ac3 = cm->dig_pcm_status & IEC958_AES0_NONAUDIO;
-	setup_spdif_playback(cm, substream, do_spdif, do_ac3);
+	if ((err = setup_spdif_playback(cm, substream, do_spdif, do_ac3)) < 0)
+		return err;
 	return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_PLAY], substream);
 }
 
@@ -1234,12 +1231,14 @@ static int snd_cmipci_playback_prepare(snd_pcm_substream_t *substream)
 static int snd_cmipci_playback_spdif_prepare(snd_pcm_substream_t *substream)
 {
 	cmipci_t *cm = snd_pcm_substream_chip(substream);
-	int do_ac3;
+	int err, do_ac3;
+
 	if (cm->can_ac3_hw) 
 		do_ac3 = cm->dig_pcm_status & IEC958_AES0_NONAUDIO;
 	else
 		do_ac3 = 1; /* doesn't matter */
-	setup_spdif_playback(cm, substream, 1, do_ac3);
+	if ((err = setup_spdif_playback(cm, substream, 1, do_ac3)) < 0)
+		return err;
 	return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_PLAY], substream);
 }
 
@@ -1262,11 +1261,10 @@ static int snd_cmipci_capture_prepare(snd_pcm_substream_t *substream)
 static int snd_cmipci_capture_spdif_prepare(snd_pcm_substream_t *substream)
 {
 	cmipci_t *cm = snd_pcm_substream_chip(substream);
-	unsigned long flags;
 
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_CAPTURE_SPDF);
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 
 	return snd_cmipci_pcm_prepare(cm, &cm->channel[CM_CH_CAPT], substream);
 }
@@ -1274,11 +1272,10 @@ static int snd_cmipci_capture_spdif_prepare(snd_pcm_substream_t *substream)
 static int snd_cmipci_capture_spdif_hw_free(snd_pcm_substream_t *subs)
 {
 	cmipci_t *cm = snd_pcm_substream_chip(subs);
-	unsigned long flags;
 
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_CAPTURE_SPDF);
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 
 	return snd_cmipci_hw_free(subs);
 }
@@ -1289,7 +1286,7 @@ static int snd_cmipci_capture_spdif_hw_free(snd_pcm_substream_t *subs)
  */
 static irqreturn_t snd_cmipci_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	cmipci_t *cm = snd_magic_cast(cmipci_t, dev_id, return IRQ_NONE);
+	cmipci_t *cm = dev_id;
 	unsigned int status, mask = 0;
 	
 	/* fastpath out, to ease interrupt sharing */
@@ -1448,7 +1445,6 @@ static snd_pcm_hardware_t snd_cmipci_capture_spdif =
  */
 static int open_device_check(cmipci_t *cm, int mode, snd_pcm_substream_t *subs)
 {
-	unsigned long flags;
 	int ch = mode & CM_OPEN_CH_MASK;
 
 	/* FIXME: a file should wait until the device becomes free
@@ -1466,9 +1462,9 @@ static int open_device_check(cmipci_t *cm, int mode, snd_pcm_substream_t *subs)
 	if (! (mode & CM_OPEN_DAC)) {
 		/* disable dual DAC mode */
 		cm->channel[ch].is_dac = 0;
-		spin_lock_irqsave(&cm->reg_lock, flags);
+		spin_lock_irq(&cm->reg_lock);
 		snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENDBDAC);
-		spin_unlock_irqrestore(&cm->reg_lock, flags);
+		spin_unlock_irq(&cm->reg_lock);
 	}
 	up(&cm->open_mutex);
 	return 0;
@@ -1476,7 +1472,6 @@ static int open_device_check(cmipci_t *cm, int mode, snd_pcm_substream_t *subs)
 
 static void close_device_check(cmipci_t *cm, int mode)
 {
-	unsigned long flags;
 	int ch = mode & CM_OPEN_CH_MASK;
 
 	down(&cm->open_mutex);
@@ -1490,9 +1485,9 @@ static void close_device_check(cmipci_t *cm, int mode)
 		if (! cm->channel[ch].is_dac) {
 			/* enable dual DAC mode again */
 			cm->channel[ch].is_dac = 1;
-			spin_lock_irqsave(&cm->reg_lock, flags);
+			spin_lock_irq(&cm->reg_lock);
 			snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_ENDBDAC);
-			spin_unlock_irqrestore(&cm->reg_lock, flags);
+			spin_unlock_irq(&cm->reg_lock);
 		}
 	}
 	up(&cm->open_mutex);
@@ -1840,12 +1835,11 @@ static int snd_cmipci_info_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t
 static int snd_cmipci_get_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	cmipci_t *cm = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	cmipci_sb_reg_t reg;
 	int val;
 
 	cmipci_sb_reg_decode(&reg, kcontrol->private_value);
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	val = (snd_cmipci_mixer_read(cm, reg.left_reg) >> reg.left_shift) & reg.mask;
 	if (reg.invert)
 		val = reg.mask - val;
@@ -1856,14 +1850,13 @@ static int snd_cmipci_get_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 			val = reg.mask - val;
 		 ucontrol->value.integer.value[1] = val;
 	}
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 	return 0;
 }
 
 static int snd_cmipci_put_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	cmipci_t *cm = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	cmipci_sb_reg_t reg;
 	int change;
 	int left, right, oleft, oright;
@@ -1880,7 +1873,7 @@ static int snd_cmipci_put_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 		right <<= reg.right_shift;
 	} else
 		right = 0;
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	oleft = snd_cmipci_mixer_read(cm, reg.left_reg);
 	left |= oleft & ~(reg.mask << reg.left_shift);
 	change = left != oleft;
@@ -1895,7 +1888,7 @@ static int snd_cmipci_put_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 		snd_cmipci_mixer_write(cm, reg.right_reg, right);
 	} else
 		snd_cmipci_mixer_write(cm, reg.left_reg, left);
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 	return change;
 }
 
@@ -1921,15 +1914,14 @@ static int snd_cmipci_info_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_info
 static int snd_cmipci_get_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	cmipci_t *cm = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	cmipci_sb_reg_t reg;
 	int val1, val2;
 
 	cmipci_sb_reg_decode(&reg, kcontrol->private_value);
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	val1 = snd_cmipci_mixer_read(cm, reg.left_reg);
 	val2 = snd_cmipci_mixer_read(cm, reg.right_reg);
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 	ucontrol->value.integer.value[0] = (val1 >> reg.left_shift) & 1;
 	ucontrol->value.integer.value[1] = (val2 >> reg.left_shift) & 1;
 	ucontrol->value.integer.value[2] = (val1 >> reg.right_shift) & 1;
@@ -1940,13 +1932,12 @@ static int snd_cmipci_get_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
 static int snd_cmipci_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	cmipci_t *cm = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	cmipci_sb_reg_t reg;
 	int change;
 	int val1, val2, oval1, oval2;
 
 	cmipci_sb_reg_decode(&reg, kcontrol->private_value);
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	oval1 = snd_cmipci_mixer_read(cm, reg.left_reg);
 	oval2 = snd_cmipci_mixer_read(cm, reg.right_reg);
 	val1 = oval1 & ~((1 << reg.left_shift) | (1 << reg.right_shift));
@@ -1958,7 +1949,7 @@ static int snd_cmipci_put_input_sw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
 	change = val1 != oval1 || val2 != oval2;
 	snd_cmipci_mixer_write(cm, reg.left_reg, val1);
 	snd_cmipci_mixer_write(cm, reg.right_reg, val2);
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 	return change;
 }
 
@@ -2011,11 +2002,10 @@ static int snd_cmipci_get_native_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_v
 {
 	cmipci_t *cm = snd_kcontrol_chip(kcontrol);
 	cmipci_sb_reg_t reg;
-	unsigned long flags;
 	unsigned char oreg, val;
 
 	cmipci_sb_reg_decode(&reg, kcontrol->private_value);
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	oreg = inb(cm->iobase + reg.left_reg);
 	val = (oreg >> reg.left_shift) & reg.mask;
 	if (reg.invert)
@@ -2027,7 +2017,7 @@ static int snd_cmipci_get_native_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_v
 			val = reg.mask - val;
 		ucontrol->value.integer.value[1] = val;
 	}
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 	return 0;
 }
 
@@ -2035,11 +2025,10 @@ static int snd_cmipci_put_native_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_v
 {
 	cmipci_t *cm = snd_kcontrol_chip(kcontrol);
 	cmipci_sb_reg_t reg;
-	unsigned long flags;
 	unsigned char oreg, nreg, val;
 
 	cmipci_sb_reg_decode(&reg, kcontrol->private_value);
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	oreg = inb(cm->iobase + reg.left_reg);
 	val = ucontrol->value.integer.value[0] & reg.mask;
 	if (reg.invert)
@@ -2054,7 +2043,7 @@ static int snd_cmipci_put_native_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_v
 		nreg |= (val << reg.right_shift);
 	}
 	outb(nreg, cm->iobase + reg.left_reg);
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 	return (nreg != oreg);
 }
 
@@ -2078,8 +2067,6 @@ static int snd_cmipci_put_native_mixer_sensitive(snd_kcontrol_t *kcontrol, snd_c
 }
 
 
-#define num_controls(ary) (sizeof(ary) / sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_cmipci_mixers[] __devinitdata = {
 	CMIPCI_SB_VOL_STEREO("Master Playback Volume", SB_DSP4_MASTER_DEV, 3, 31),
 	CMIPCI_MIXER_SW_MONO("3D Control - Switch", CM_REG_MIXER1, CM_X3DEN_SHIFT, 0),
@@ -2137,14 +2124,13 @@ static int snd_cmipci_uswitch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
 
 static int _snd_cmipci_uswitch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol, snd_cmipci_switch_args_t *args)
 {
-	unsigned long flags;
 	unsigned int val;
 	cmipci_t *cm = snd_kcontrol_chip(kcontrol);
 
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	if (args->ac3_sensitive && cm->mixer_insensitive) {
 		ucontrol->value.integer.value[0] = 0;
-		spin_unlock_irqrestore(&cm->reg_lock, flags);
+		spin_unlock_irq(&cm->reg_lock);
 		return 0;
 	}
 	if (args->is_byte)
@@ -2152,7 +2138,7 @@ static int _snd_cmipci_uswitch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
 	else
 		val = snd_cmipci_read(cm, args->reg);
 	ucontrol->value.integer.value[0] = ((val & args->mask) == args->mask_on) ? 1 : 0;
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 	return 0;
 }
 
@@ -2165,15 +2151,14 @@ static int snd_cmipci_uswitch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
 
 static int _snd_cmipci_uswitch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol, snd_cmipci_switch_args_t *args)
 {
-	unsigned long flags;
 	unsigned int val;
 	int change;
 	cmipci_t *cm = snd_kcontrol_chip(kcontrol);
 
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	if (args->ac3_sensitive && cm->mixer_insensitive) {
 		/* ignored */
-		spin_unlock_irqrestore(&cm->reg_lock, flags);
+		spin_unlock_irq(&cm->reg_lock);
 		return 0;
 	}
 	if (args->is_byte)
@@ -2192,7 +2177,7 @@ static int _snd_cmipci_uswitch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
 		else
 			snd_cmipci_write(cm, args->reg, val);
 	}
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 	return change;
 }
 
@@ -2345,7 +2330,6 @@ static snd_kcontrol_new_t snd_cmipci_control_switches[] __devinitdata = {
 
 static int __devinit snd_cmipci_mixer_new(cmipci_t *cm, int pcm_spdif_device)
 {
-	unsigned long flags;
 	snd_card_t *card;
 	snd_kcontrol_new_t *sw;
 	snd_kcontrol_t *kctl;
@@ -2358,18 +2342,18 @@ static int __devinit snd_cmipci_mixer_new(cmipci_t *cm, int pcm_spdif_device)
 
 	strcpy(card->mixername, "CMedia PCI");
 
-	spin_lock_irqsave(&cm->reg_lock, flags);
+	spin_lock_irq(&cm->reg_lock);
 	snd_cmipci_mixer_write(cm, 0x00, 0x00);		/* mixer reset */
-	spin_unlock_irqrestore(&cm->reg_lock, flags);
+	spin_unlock_irq(&cm->reg_lock);
 
-	for (idx = 0; idx < num_controls(snd_cmipci_mixers); idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_mixers); idx++) {
 		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cmipci_mixers[idx], cm))) < 0)
 			return err;
 	}
 
 	/* mixer switches */
 	sw = snd_cmipci_mixer_switches;
-	for (idx = 0; idx < num_controls(snd_cmipci_mixer_switches); idx++, sw++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_mixer_switches); idx++, sw++) {
 		err = snd_ctl_add(cm->card, snd_ctl_new1(sw, cm));
 		if (err < 0)
 			return err;
@@ -2382,7 +2366,7 @@ static int __devinit snd_cmipci_mixer_new(cmipci_t *cm, int pcm_spdif_device)
 	if (cm->device == PCI_DEVICE_ID_CMEDIA_CM8738 ||
 	    cm->device == PCI_DEVICE_ID_CMEDIA_CM8738B) {
 		sw = snd_cmipci_8738_mixer_switches;
-		for (idx = 0; idx < num_controls(snd_cmipci_8738_mixer_switches); idx++, sw++) {
+		for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_8738_mixer_switches); idx++, sw++) {
 			err = snd_ctl_add(cm->card, snd_ctl_new1(sw, cm));
 			if (err < 0)
 				return err;
@@ -2400,7 +2384,7 @@ static int __devinit snd_cmipci_mixer_new(cmipci_t *cm, int pcm_spdif_device)
 		}
 		if (cm->chip_version <= 37) {
 			sw = snd_cmipci_old_mixer_switches;
-			for (idx = 0; idx < num_controls(snd_cmipci_old_mixer_switches); idx++, sw++) {
+			for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_old_mixer_switches); idx++, sw++) {
 				err = snd_ctl_add(cm->card, snd_ctl_new1(sw, cm));
 				if (err < 0)
 					return err;
@@ -2409,7 +2393,7 @@ static int __devinit snd_cmipci_mixer_new(cmipci_t *cm, int pcm_spdif_device)
 	}
 	if (cm->chip_version >= 39) {
 		sw = snd_cmipci_extra_mixer_switches;
-		for (idx = 0; idx < num_controls(snd_cmipci_extra_mixer_switches); idx++, sw++) {
+		for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_extra_mixer_switches); idx++, sw++) {
 			err = snd_ctl_add(cm->card, snd_ctl_new1(sw, cm));
 			if (err < 0)
 				return err;
@@ -2418,7 +2402,7 @@ static int __devinit snd_cmipci_mixer_new(cmipci_t *cm, int pcm_spdif_device)
 
 	/* card switches */
 	sw = snd_cmipci_control_switches;
-	for (idx = 0; idx < num_controls(snd_cmipci_control_switches); idx++, sw++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_control_switches); idx++, sw++) {
 		err = snd_ctl_add(cm->card, snd_ctl_new1(sw, cm));
 		if (err < 0)
 			return err;
@@ -2446,7 +2430,7 @@ static int __devinit snd_cmipci_mixer_new(cmipci_t *cm, int pcm_spdif_device)
 static void snd_cmipci_proc_read(snd_info_entry_t *entry, 
 				 snd_info_buffer_t *buffer)
 {
-	cmipci_t *cm = snd_magic_cast(cmipci_t, entry->private_data, return);
+	cmipci_t *cm = entry->private_data;
 	int i;
 	
 	snd_iprintf(buffer, "%s\n\n", cm->card->longname);
@@ -2566,17 +2550,14 @@ static int snd_cmipci_free(cmipci_t *cm)
 		kfree_nocheck(cm->res_joystick);
 	}
 #endif
-	if (cm->res_iobase) {
-		release_resource(cm->res_iobase);
-		kfree_nocheck(cm->res_iobase);
-	}
-	snd_magic_kfree(cm);
+	pci_release_regions(cm->pci);
+	kfree(cm);
 	return 0;
 }
 
 static int snd_cmipci_dev_free(snd_device_t *device)
 {
-	cmipci_t *cm = snd_magic_cast(cmipci_t, device->device_data, return -ENXIO);
+	cmipci_t *cm = device->device_data;
 	return snd_cmipci_free(cm);
 }
 
@@ -2598,7 +2579,7 @@ static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci,
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	cm = snd_magic_kcalloc(cmipci_t, 0, GFP_KERNEL);
+	cm = kcalloc(1, sizeof(*cm), GFP_KERNEL);
 	if (cm == NULL)
 		return -ENOMEM;
 
@@ -2608,16 +2589,16 @@ static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci,
 	cm->card = card;
 	cm->pci = pci;
 	cm->irq = -1;
-	cm->iobase = pci_resource_start(pci, 0);
 	cm->channel[0].ch = 0;
 	cm->channel[1].ch = 1;
 	cm->channel[0].is_dac = cm->channel[1].is_dac = 1; /* dual DAC mode */
 
-	if ((cm->res_iobase = request_region(cm->iobase, CM_EXTENT_CODEC, card->driver)) == NULL) {
-		snd_printk("unable to grab ports 0x%lx-0x%lx\n", cm->iobase, cm->iobase + CM_EXTENT_CODEC - 1);
-		err = -EBUSY;
-		goto __error;
+	if ((err = pci_request_regions(pci, card->driver)) < 0) {
+		kfree(cm);
+		return err;
 	}
+	cm->iobase = pci_resource_start(pci, 0);
+
 	if (request_irq(pci->irq, snd_cmipci_interrupt, SA_INTERRUPT|SA_SHIRQ, card->driver, (void *)cm)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
 		err = -EBUSY;
@@ -2776,12 +2757,12 @@ static int __devinit snd_cmipci_create(snd_card_t *card, struct pci_dev *pci,
 			int i;
 			for (i = 0; ports[i]; i++) {
 				joystick_port[dev] = ports[i];
-				cm->res_joystick = request_region(ports[i], 8, "CMIPCI gameport");
+				cm->res_joystick = request_region(ports[i], 1, "CMIPCI gameport");
 				if (cm->res_joystick)
 					break;
 			}
 		} else {
-			cm->res_joystick = request_region(joystick_port[dev], 8, "CMIPCI gameport");
+			cm->res_joystick = request_region(joystick_port[dev], 1, "CMIPCI gameport");
 		}
 	}
 	if (cm->res_joystick) {
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index 86430a0bc..65bc9ba24 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -40,8 +40,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Cirrus Logic CS4281");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Cirrus Logic,CS4281}}");
+MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,CS4281}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -51,16 +50,12 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for CS4281 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for CS4281 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable CS4281 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(dual_codec, bool, boot_devs, 0444);
 MODULE_PARM_DESC(dual_codec, "Secondary Codec ID (0 = disabled).");
-MODULE_PARM_SYNTAX(dual_codec, SNDRV_ENABLED ",allows:{{0,3}}");
 
 /*
  *
@@ -441,8 +436,6 @@ MODULE_PARM_SYNTAX(dual_codec, SNDRV_ENABLED ",allows:{{0,3}}");
  *
  */
 
-#define chip_t cs4281_t
-
 typedef struct snd_cs4281 cs4281_t;
 typedef struct snd_cs4281_dma cs4281_dma_t;
 
@@ -475,8 +468,6 @@ struct snd_cs4281 {
 	unsigned long ba1;		/* virtual (accessible) address */
 	unsigned long ba0_addr;
 	unsigned long ba1_addr;
-	struct resource *ba0_res;
-	struct resource *ba1_res;
 
 	int dual_codec;
 
@@ -575,7 +566,7 @@ static void snd_cs4281_ac97_write(ac97_t *ac97,
 	 *  4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h
 	 *  5. if DCV not cleared, break and return error
 	 */
-	cs4281_t *chip = snd_magic_cast(cs4281_t, ac97->private_data, return);
+	cs4281_t *chip = ac97->private_data;
 	int count;
 
 	/*
@@ -613,7 +604,7 @@ static void snd_cs4281_ac97_write(ac97_t *ac97,
 static unsigned short snd_cs4281_ac97_read(ac97_t *ac97,
 					   unsigned short reg)
 {
-	cs4281_t *chip = snd_magic_cast(cs4281_t, ac97->private_data, return -ENXIO);
+	cs4281_t *chip = ac97->private_data;
 	int count;
 	unsigned short result;
 	// FIXME: volatile is necessary in the following due to a bug of
@@ -709,9 +700,8 @@ static int snd_cs4281_trigger(snd_pcm_substream_t *substream, int cmd)
 {
 	cs4281_dma_t *dma = (cs4281_dma_t *)substream->runtime->private_data;
 	cs4281_t *chip = snd_pcm_substream_chip(substream);
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 		dma->valDCR |= BA0_DCR_MSK;
@@ -738,13 +728,13 @@ static int snd_cs4281_trigger(snd_pcm_substream_t *substream, int cmd)
 			dma->valFCR &= ~BA0_FCR_FEN;
 		break;
 	default:
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		spin_unlock(&chip->reg_lock);
 		return -EINVAL;
 	}
 	snd_cs4281_pokeBA0(chip, dma->regDMR, dma->valDMR);
 	snd_cs4281_pokeBA0(chip, dma->regFCR, dma->valFCR);
 	snd_cs4281_pokeBA0(chip, dma->regDCR, dma->valDCR);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return 0;
 }
 
@@ -851,11 +841,10 @@ static int snd_cs4281_playback_prepare(snd_pcm_substream_t * substream)
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	cs4281_dma_t *dma = (cs4281_dma_t *)runtime->private_data;
 	cs4281_t *chip = snd_pcm_substream_chip(substream);
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	snd_cs4281_mode(chip, dma, runtime, 0, 1);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -864,11 +853,10 @@ static int snd_cs4281_capture_prepare(snd_pcm_substream_t * substream)
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	cs4281_dma_t *dma = (cs4281_dma_t *)runtime->private_data;
 	cs4281_t *chip = snd_pcm_substream_chip(substream);
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	snd_cs4281_mode(chip, dma, runtime, 1, 1);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -1015,7 +1003,7 @@ static snd_pcm_ops_t snd_cs4281_capture_ops = {
 
 static void snd_cs4281_pcm_free(snd_pcm_t *pcm)
 {
-	cs4281_t *chip = snd_magic_cast(cs4281_t, pcm->private_data, return);
+	cs4281_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1124,13 +1112,13 @@ static snd_kcontrol_new_t snd_cs4281_pcm_vol =
 
 static void snd_cs4281_mixer_free_ac97_bus(ac97_bus_t *bus)
 {
-	cs4281_t *chip = snd_magic_cast(cs4281_t, bus->private_data, return);
+	cs4281_t *chip = bus->private_data;
 	chip->ac97_bus = NULL;
 }
 
 static void snd_cs4281_mixer_free_ac97(ac97_t *ac97)
 {
-	cs4281_t *chip = snd_magic_cast(cs4281_t, ac97->private_data, return);
+	cs4281_t *chip = ac97->private_data;
 	if (ac97->num)
 		chip->ac97_secondary = NULL;
 	else
@@ -1140,17 +1128,16 @@ static void snd_cs4281_mixer_free_ac97(ac97_t *ac97)
 static int __devinit snd_cs4281_mixer(cs4281_t * chip)
 {
 	snd_card_t *card = chip->card;
-	ac97_bus_t bus;
-	ac97_t ac97;
+	ac97_template_t ac97;
 	int err;
+	static ac97_bus_ops_t ops = {
+		.write = snd_cs4281_ac97_write,
+		.read = snd_cs4281_ac97_read,
+	};
 
-	memset(&bus, 0, sizeof(bus));
-	bus.write = snd_cs4281_ac97_write;
-	bus.read = snd_cs4281_ac97_read;
-	bus.private_data = chip;
-	bus.private_free = snd_cs4281_mixer_free_ac97_bus;
-	if ((err = snd_ac97_bus(card, &bus, &chip->ac97_bus)) < 0)
+	if ((err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus)) < 0)
 		return err;
+	chip->ac97_bus->private_free = snd_cs4281_mixer_free_ac97_bus;
 
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = chip;
@@ -1177,7 +1164,7 @@ static int __devinit snd_cs4281_mixer(cs4281_t * chip)
 static void snd_cs4281_proc_read(snd_info_entry_t *entry, 
 				  snd_info_buffer_t * buffer)
 {
-	cs4281_t *chip = snd_magic_cast(cs4281_t, entry->private_data, return);
+	cs4281_t *chip = entry->private_data;
 
 	snd_iprintf(buffer, "Cirrus Logic CS4281\n\n");
 	snd_iprintf(buffer, "Spurious half IRQs   : %u\n", chip->spurious_dhtc_irq);
@@ -1189,7 +1176,7 @@ static long snd_cs4281_BA0_read(snd_info_entry_t *entry, void *file_private_data
 				unsigned long count, unsigned long pos)
 {
 	long size;
-	cs4281_t *chip = snd_magic_cast(cs4281_t, entry->private_data, return -ENXIO);
+	cs4281_t *chip = entry->private_data;
 	
 	size = count;
 	if (pos + size > CS4281_BA0_SIZE)
@@ -1206,7 +1193,7 @@ static long snd_cs4281_BA1_read(snd_info_entry_t *entry, void *file_private_data
 				unsigned long count, unsigned long pos)
 {
 	long size;
-	cs4281_t *chip = snd_magic_cast(cs4281_t, entry->private_data, return -ENXIO);
+	cs4281_t *chip = entry->private_data;
 	
 	size = count;
 	if (pos + size > CS4281_BA1_SIZE)
@@ -1262,7 +1249,7 @@ static void snd_cs4281_gameport_trigger(struct gameport *gameport)
 	cs4281_gameport_t *gp = (cs4281_gameport_t *)gameport;
 	cs4281_t *chip;
 	snd_assert(gp, return);
-	chip = snd_magic_cast(cs4281_t, gp->chip, return);
+	chip = gp->chip;
 	snd_cs4281_pokeBA0(chip, BA0_JSPT, 0xff);
 }
 
@@ -1271,7 +1258,7 @@ static unsigned char snd_cs4281_gameport_read(struct gameport *gameport)
 	cs4281_gameport_t *gp = (cs4281_gameport_t *)gameport;
 	cs4281_t *chip;
 	snd_assert(gp, return 0);
-	chip = snd_magic_cast(cs4281_t, gp->chip, return 0);
+	chip = gp->chip;
 	return snd_cs4281_peekBA0(chip, BA0_JSPT);
 }
 
@@ -1283,7 +1270,7 @@ static int snd_cs4281_gameport_cooked_read(struct gameport *gameport, int *axes,
 	unsigned js1, js2, jst;
 	
 	snd_assert(gp, return 0);
-	chip = snd_magic_cast(cs4281_t, gp->chip, return 0);
+	chip = gp->chip;
 
 	js1 = snd_cs4281_peekBA0(chip, BA0_JSC1);
 	js2 = snd_cs4281_peekBA0(chip, BA0_JSC2);
@@ -1369,28 +1356,21 @@ static int snd_cs4281_free(cs4281_t *chip)
 	/* PCI interface - D3 state */
 	pci_set_power_state(chip->pci, 3);
 
+	if (chip->irq >= 0)
+		free_irq(chip->irq, (void *)chip);
 	if (chip->ba0)
 		iounmap((void *) chip->ba0);
 	if (chip->ba1)
 		iounmap((void *) chip->ba1);
-	if (chip->ba0_res) {
-		release_resource(chip->ba0_res);
-		kfree_nocheck(chip->ba0_res);
-	}
-	if (chip->ba1_res) {
-		release_resource(chip->ba1_res);
-		kfree_nocheck(chip->ba1_res);
-	}
-	if (chip->irq >= 0)
-		free_irq(chip->irq, (void *)chip);
+	pci_release_regions(chip->pci);
 
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_cs4281_dev_free(snd_device_t *device)
 {
-	cs4281_t *chip = snd_magic_cast(cs4281_t, device->device_data, return -ENXIO);
+	cs4281_t *chip = device->device_data;
 	return snd_cs4281_free(chip);
 }
 
@@ -1415,15 +1395,13 @@ static int __devinit snd_cs4281_create(snd_card_t * card,
 	*rchip = NULL;
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
-	chip = snd_magic_kcalloc(cs4281_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
 	chip->card = card;
 	chip->pci = pci;
 	chip->irq = -1;
-	chip->ba0_addr = pci_resource_start(pci, 0);
-	chip->ba1_addr = pci_resource_start(pci, 1);
 	pci_set_master(pci);
 	if (dual_codec < 0 || dual_codec > 3) {
 		snd_printk(KERN_ERR "invalid dual_codec option %d\n", dual_codec);
@@ -1431,16 +1409,13 @@ static int __devinit snd_cs4281_create(snd_card_t * card,
 	}
 	chip->dual_codec = dual_codec;
 
-	if ((chip->ba0_res = request_mem_region(chip->ba0_addr, CS4281_BA0_SIZE, "CS4281 BA0")) == NULL) {
-		snd_printk(KERN_ERR "unable to grab memory region 0x%lx-0x%lx\n", chip->ba0_addr, chip->ba0_addr + CS4281_BA0_SIZE - 1);
-		snd_cs4281_free(chip);
-		return -ENOMEM;
-	}
-	if ((chip->ba1_res = request_mem_region(chip->ba1_addr, CS4281_BA1_SIZE, "CS4281 BA1")) == NULL) {
-		snd_printk(KERN_ERR "unable to grab memory region 0x%lx-0x%lx\n", chip->ba1_addr, chip->ba1_addr + CS4281_BA1_SIZE - 1);
-		snd_cs4281_free(chip);
-		return -ENOMEM;
+	if ((err = pci_request_regions(pci, "CS4281")) < 0) {
+		kfree(chip);
+		return err;
 	}
+	chip->ba0_addr = pci_resource_start(pci, 0);
+	chip->ba1_addr = pci_resource_start(pci, 1);
+
 	if (request_irq(pci->irq, snd_cs4281_interrupt, SA_INTERRUPT|SA_SHIRQ, "CS4281", (void *)chip)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_cs4281_free(chip);
@@ -1448,8 +1423,8 @@ static int __devinit snd_cs4281_create(snd_card_t * card,
 	}
 	chip->irq = pci->irq;
 
-	chip->ba0 = (unsigned long) ioremap_nocache(chip->ba0_addr, CS4281_BA0_SIZE);
-	chip->ba1 = (unsigned long) ioremap_nocache(chip->ba1_addr, CS4281_BA1_SIZE);
+	chip->ba0 = (unsigned long) ioremap_nocache(chip->ba0_addr, pci_resource_len(pci, 0));
+	chip->ba1 = (unsigned long) ioremap_nocache(chip->ba1_addr, pci_resource_len(pci, 1));
 	if (!chip->ba0 || !chip->ba1) {
 		snd_cs4281_free(chip);
 		return -ENOMEM;
@@ -1713,10 +1688,9 @@ static void snd_cs4281_midi_reset(cs4281_t *chip)
 
 static int snd_cs4281_midi_input_open(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return -ENXIO);
+	cs4281_t *chip = substream->rmidi->private_data;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
  	chip->midcr |= BA0_MIDCR_RXE;
 	chip->midi_input = substream;
 	if (!(chip->uartm & CS4281_MODE_OUTPUT)) {
@@ -1724,16 +1698,15 @@ static int snd_cs4281_midi_input_open(snd_rawmidi_substream_t * substream)
 	} else {
 		snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr);
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
 static int snd_cs4281_midi_input_close(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return -ENXIO);
+	cs4281_t *chip = substream->rmidi->private_data;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	chip->midcr &= ~(BA0_MIDCR_RXE | BA0_MIDCR_RIE);
 	chip->midi_input = NULL;
 	if (!(chip->uartm & CS4281_MODE_OUTPUT)) {
@@ -1742,16 +1715,15 @@ static int snd_cs4281_midi_input_close(snd_rawmidi_substream_t * substream)
 		snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr);
 	}
 	chip->uartm &= ~CS4281_MODE_INPUT;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
 static int snd_cs4281_midi_output_open(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return -ENXIO);
+	cs4281_t *chip = substream->rmidi->private_data;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	chip->uartm |= CS4281_MODE_OUTPUT;
 	chip->midcr |= BA0_MIDCR_TXE;
 	chip->midi_output = substream;
@@ -1760,16 +1732,15 @@ static int snd_cs4281_midi_output_open(snd_rawmidi_substream_t * substream)
 	} else {
 		snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr);
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
 static int snd_cs4281_midi_output_close(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return -ENXIO);
+	cs4281_t *chip = substream->rmidi->private_data;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	chip->midcr &= ~(BA0_MIDCR_TXE | BA0_MIDCR_TIE);
 	chip->midi_output = NULL;
 	if (!(chip->uartm & CS4281_MODE_INPUT)) {
@@ -1778,14 +1749,14 @@ static int snd_cs4281_midi_output_close(snd_rawmidi_substream_t * substream)
 		snd_cs4281_pokeBA0(chip, BA0_MIDCR, chip->midcr);
 	}
 	chip->uartm &= ~CS4281_MODE_OUTPUT;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
 static void snd_cs4281_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
 {
 	unsigned long flags;
-	cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return);
+	cs4281_t *chip = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&chip->reg_lock, flags);
 	if (up) {
@@ -1805,7 +1776,7 @@ static void snd_cs4281_midi_input_trigger(snd_rawmidi_substream_t * substream, i
 static void snd_cs4281_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
 {
 	unsigned long flags;
-	cs4281_t *chip = snd_magic_cast(cs4281_t, substream->rmidi->private_data, return);
+	cs4281_t *chip = substream->rmidi->private_data;
 	unsigned char byte;
 
 	spin_lock_irqsave(&chip->reg_lock, flags);
@@ -1872,7 +1843,7 @@ static int __devinit snd_cs4281_midi(cs4281_t * chip, int device, snd_rawmidi_t
 
 static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	cs4281_t *chip = snd_magic_cast(cs4281_t, dev_id, return IRQ_NONE);
+	cs4281_t *chip = dev_id;
 	unsigned int status, dma, val;
 	cs4281_dma_t *cdma;
 
@@ -1919,7 +1890,9 @@ static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *r
 			c = snd_cs4281_peekBA0(chip, BA0_MIDRP);
 			if ((chip->midcr & BA0_MIDCR_RIE) == 0)
 				continue;
+			spin_unlock(&chip->reg_lock);
 			snd_rawmidi_receive(chip->midi_input, &c, 1);
+			spin_lock(&chip->reg_lock);
 		}
 		while ((snd_cs4281_peekBA0(chip, BA0_MIDSR) & BA0_MIDSR_TBF) == 0) {
 			if ((chip->midcr & BA0_MIDCR_TIE) == 0)
@@ -2034,13 +2007,11 @@ static int saved_regs[SUSPEND_REGISTERS] = {
 	BA0_PPRVC,
 };
 
-#define number_of(array)	(sizeof(array) / sizeof(array[0]))
-
 #define CLKCR1_CKRA                             0x00010000L
 
 static int cs4281_suspend(snd_card_t *card, unsigned int state)
 {
-	cs4281_t *chip = snd_magic_cast(cs4281_t, card->pm_private_data, return -EINVAL);
+	cs4281_t *chip = card->pm_private_data;
 	u32 ulCLK;
 	unsigned int i;
 
@@ -2059,7 +2030,7 @@ static int cs4281_suspend(snd_card_t *card, unsigned int state)
 	snd_cs4281_pokeBA0(chip, BA0_HICR, BA0_HICR_CHGM);
 
 	/* remember the status registers */
-	for (i = 0; i < number_of(saved_regs); i++)
+	for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
 		if (saved_regs[i])
 			chip->suspend_regs[i] = snd_cs4281_peekBA0(chip, saved_regs[i]);
 
@@ -2085,7 +2056,7 @@ static int cs4281_suspend(snd_card_t *card, unsigned int state)
 
 static int cs4281_resume(snd_card_t *card, unsigned int state)
 {
-	cs4281_t *chip = snd_magic_cast(cs4281_t, card->pm_private_data, return -EINVAL);
+	cs4281_t *chip = card->pm_private_data;
 	unsigned int i;
 	u32 ulCLK;
 
@@ -2098,7 +2069,7 @@ static int cs4281_resume(snd_card_t *card, unsigned int state)
 	snd_cs4281_chip_init(chip);
 
 	/* restore the status registers */
-	for (i = 0; i < number_of(saved_regs); i++)
+	for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
 		if (saved_regs[i])
 			snd_cs4281_pokeBA0(chip, saved_regs[i], chip->suspend_regs[i]);
 
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index 8b63705c4..e42fae563 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -37,8 +37,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Cirrus Logic Sound Fusion CS46XX");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Cirrus Logic,Sound Fusion (CS4280)},"
+MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,Sound Fusion (CS4280)},"
 		"{Cirrus Logic,Sound Fusion (CS4610)},"
 		"{Cirrus Logic,Sound Fusion (CS4612)},"
 		"{Cirrus Logic,Sound Fusion (CS4615)},"
@@ -56,22 +55,16 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for the CS46xx soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for the CS46xx soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable CS46xx soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(external_amp, bool, boot_devs, 0444);
 MODULE_PARM_DESC(external_amp, "Force to enable external amplifer.");
-MODULE_PARM_SYNTAX(external_amp, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 module_param_array(thinkpad, bool, boot_devs, 0444);
 MODULE_PARM_DESC(thinkpad, "Force to enable Thinkpad's CLKRUN control.");
-MODULE_PARM_SYNTAX(thinkpad, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 module_param_array(mmap_valid, bool, boot_devs, 0444);
 MODULE_PARM_DESC(mmap_valid, "Support OSS mmap.");
-MODULE_PARM_SYNTAX(mmap_valid, SNDRV_ENABLED "," SNDRV_BOOLEAN_TRUE_DESC);
 
 static struct pci_device_id snd_cs46xx_ids[] = {
         { 0x1013, 0x6001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },   /* CS4280 */
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index e9810d2ea..9b1868141 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -79,6 +79,8 @@ static unsigned short snd_cs46xx_codec_read(cs46xx_t *chip,
 		     (codec_index == CS46XX_SECONDARY_CODEC_INDEX),
 		     return -EINVAL);
 
+	chip->active_ctrl(chip, 1);
+
 	if (codec_index == CS46XX_SECONDARY_CODEC_INDEX)
 		offset = CS46XX_SECONDARY_CODEC_OFFSET;
 
@@ -184,27 +186,22 @@ static unsigned short snd_cs46xx_codec_read(cs46xx_t *chip,
 	//snd_cs46xx_peekBA0(chip, BA0_ACCAD);
 	result = snd_cs46xx_peekBA0(chip, BA0_ACSDA + offset);
  end:
+	chip->active_ctrl(chip, -1);
 	return result;
 }
 
 static unsigned short snd_cs46xx_ac97_read(ac97_t * ac97,
 					    unsigned short reg)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, ac97->private_data, return -ENXIO);
+	cs46xx_t *chip = ac97->private_data;
 	unsigned short val;
-	int codec_index = -1;
-
-	/* UGGLY: nr_ac97_codecs == 0 primery codec detection is in progress */
-	if (ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] || chip->nr_ac97_codecs == 0)
-		codec_index = CS46XX_PRIMARY_CODEC_INDEX;
-	/* UGGLY: nr_ac97_codecs == 1 secondary codec detection is in progress */
-	else if (ac97 == chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] || chip->nr_ac97_codecs == 1)
-		codec_index = CS46XX_SECONDARY_CODEC_INDEX;
-	else
-		snd_assert(0, return 0xffff);
-	chip->active_ctrl(chip, 1);
+	int codec_index = ac97->num;
+
+	snd_assert(codec_index == CS46XX_PRIMARY_CODEC_INDEX ||
+		   codec_index == CS46XX_SECONDARY_CODEC_INDEX,
+		   return 0xffff);
+
 	val = snd_cs46xx_codec_read(chip, reg, codec_index);
-	chip->active_ctrl(chip, -1);
 
 	/* HACK: voyetra uses EAPD bit in the reverse way.
 	 * we flip the bit to show the mixer status correctly
@@ -227,6 +224,8 @@ static void snd_cs46xx_codec_write(cs46xx_t *chip,
 		    (codec_index == CS46XX_SECONDARY_CODEC_INDEX),
 		    return);
 
+	chip->active_ctrl(chip, 1);
+
 	/*
 	 *  1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
 	 *  2. Write ACCDA = Command Data Register = 470h    for data to write to AC97
@@ -271,27 +270,24 @@ static void snd_cs46xx_codec_write(cs46xx_t *chip,
 		 *  ACCTL = 460h, DCV should be reset by now and 460h = 07h
 		 */
 		if (!(snd_cs46xx_peekBA0(chip, BA0_ACCTL) & ACCTL_DCV)) {
-			return;
+			goto end;
 		}
 	}
 	snd_printk("AC'97 write problem, codec_index = %d, reg = 0x%x, val = 0x%x\n", codec_index, reg, val);
+ end:
+	chip->active_ctrl(chip, -1);
 }
 
 static void snd_cs46xx_ac97_write(ac97_t *ac97,
 				   unsigned short reg,
 				   unsigned short val)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, ac97->private_data, return);
-	int codec_index = -1;
+	cs46xx_t *chip = ac97->private_data;
+	int codec_index = ac97->num;
 
-	/* UGGLY: nr_ac97_codecs == 0 primery codec detection is in progress */
-	if (ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] || chip->nr_ac97_codecs == 0)
-		codec_index = CS46XX_PRIMARY_CODEC_INDEX;
-	/* UGGLY: nr_ac97_codecs == 1 secondary codec detection is in progress */
-	else  if (ac97 == chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] || chip->nr_ac97_codecs == 1)
-		codec_index = CS46XX_SECONDARY_CODEC_INDEX;
-	else
-		snd_assert(0,return);
+	snd_assert(codec_index == CS46XX_PRIMARY_CODEC_INDEX ||
+		   codec_index == CS46XX_SECONDARY_CODEC_INDEX,
+		   return);
 
 	/* HACK: voyetra uses EAPD bit in the reverse way.
 	 * we flip the bit to show the mixer status correctly
@@ -299,9 +295,7 @@ static void snd_cs46xx_ac97_write(ac97_t *ac97,
 	if (reg == AC97_POWERDOWN && chip->amplifier_ctrl == amp_voyetra)
 		val ^= 0x8000;
 
-	chip->active_ctrl(chip, 1);
 	snd_cs46xx_codec_write(chip, reg, val, codec_index);
-	chip->active_ctrl(chip, -1);
 }
 
 
@@ -688,84 +682,35 @@ static void snd_cs46xx_set_capture_sample_rate(cs46xx_t *chip, unsigned int rate
  *  PCM part
  */
 
+static void snd_cs46xx_pb_trans_copy(snd_pcm_substream_t *substream,
+				     snd_pcm_indirect_t *rec, size_t bytes)
+{
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	cs46xx_pcm_t * cpcm = runtime->private_data;
+	memcpy(cpcm->hw_buf.area + rec->hw_data, runtime->dma_area + rec->sw_data, bytes);
+}
+
 static int snd_cs46xx_playback_transfer(snd_pcm_substream_t *substream)
 {
-	/* cs46xx_t *chip = snd_pcm_substream_chip(substream); */
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	cs46xx_pcm_t * cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO);
-	snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
-	snd_pcm_sframes_t diff = appl_ptr - cpcm->appl_ptr;
-	int buffer_size = runtime->period_size * CS46XX_FRAGS << cpcm->shift;
-
-	if (diff) {
-		if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
-			diff += runtime->boundary;
-		cpcm->sw_ready += diff * (1 << cpcm->shift);
-		cpcm->appl_ptr = appl_ptr;
-	}
-	while (cpcm->hw_ready < buffer_size && 
-	       cpcm->sw_ready > 0) {
-		size_t hw_to_end = buffer_size - cpcm->hw_data;
-		size_t sw_to_end = cpcm->sw_bufsize - cpcm->sw_data;
-		size_t bytes = buffer_size - cpcm->hw_ready;
-		if (cpcm->sw_ready < (int)bytes)
-			bytes = cpcm->sw_ready;
-		if (hw_to_end < bytes)
-			bytes = hw_to_end;
-		if (sw_to_end < bytes)
-			bytes = sw_to_end;
-		memcpy(cpcm->hw_buf.area + cpcm->hw_data,
-		       runtime->dma_area + cpcm->sw_data,
-		       bytes);
-		cpcm->hw_data += bytes;
-		if ((int)cpcm->hw_data == buffer_size)
-			cpcm->hw_data = 0;
-		cpcm->sw_data += bytes;
-		if (cpcm->sw_data == cpcm->sw_bufsize)
-			cpcm->sw_data = 0;
-		cpcm->hw_ready += bytes;
-		cpcm->sw_ready -= bytes;
-	}
+	cs46xx_pcm_t * cpcm = runtime->private_data;
+	snd_pcm_indirect_playback_transfer(substream, &cpcm->pcm_rec, snd_cs46xx_pb_trans_copy);
 	return 0;
 }
 
-static int snd_cs46xx_capture_transfer(snd_pcm_substream_t *substream)
+static void snd_cs46xx_cp_trans_copy(snd_pcm_substream_t *substream,
+				     snd_pcm_indirect_t *rec, size_t bytes)
 {
 	cs46xx_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
-	snd_pcm_sframes_t diff = appl_ptr - chip->capt.appl_ptr;
-	int buffer_size = runtime->period_size * CS46XX_FRAGS << chip->capt.shift;
-
-	if (diff) {
-		if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
-			diff += runtime->boundary;
-		chip->capt.sw_ready -= diff * (1 << chip->capt.shift);
-		chip->capt.appl_ptr = appl_ptr;
-	}
-	while (chip->capt.hw_ready > 0 && 
-	       chip->capt.sw_ready < (int)chip->capt.sw_bufsize) {
-		size_t hw_to_end = buffer_size - chip->capt.hw_data;
-		size_t sw_to_end = chip->capt.sw_bufsize - chip->capt.sw_data;
-		size_t bytes = chip->capt.sw_bufsize - chip->capt.sw_ready;
-		if (chip->capt.hw_ready < (int)bytes)
-			bytes = chip->capt.hw_ready;
-		if (hw_to_end < bytes)
-			bytes = hw_to_end;
-		if (sw_to_end < bytes)
-			bytes = sw_to_end;
-		memcpy(runtime->dma_area + chip->capt.sw_data,
-		       chip->capt.hw_buf.area + chip->capt.hw_data,
-		       bytes);
-		chip->capt.hw_data += bytes;
-		if ((int)chip->capt.hw_data == buffer_size)
-			chip->capt.hw_data = 0;
-		chip->capt.sw_data += bytes;
-		if (chip->capt.sw_data == chip->capt.sw_bufsize)
-			chip->capt.sw_data = 0;
-		chip->capt.hw_ready -= bytes;
-		chip->capt.sw_ready += bytes;
-	}
+	memcpy(runtime->dma_area + rec->sw_data,
+	       chip->capt.hw_buf.area + rec->hw_data, bytes);
+}
+
+static int snd_cs46xx_capture_transfer(snd_pcm_substream_t *substream)
+{
+	cs46xx_t *chip = snd_pcm_substream_chip(substream);
+	snd_pcm_indirect_capture_transfer(substream, &chip->capt.pcm_rec, snd_cs46xx_cp_trans_copy);
 	return 0;
 }
 
@@ -773,7 +718,7 @@ static snd_pcm_uframes_t snd_cs46xx_playback_direct_pointer(snd_pcm_substream_t
 {
 	cs46xx_t *chip = snd_pcm_substream_chip(substream);
 	size_t ptr;
-	cs46xx_pcm_t *cpcm = snd_magic_cast(cs46xx_pcm_t, substream->runtime->private_data, return -ENXIO);
+	cs46xx_pcm_t *cpcm = substream->runtime->private_data;
 	snd_assert (cpcm->pcm_channel,return -ENXIO);
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
@@ -789,9 +734,7 @@ static snd_pcm_uframes_t snd_cs46xx_playback_indirect_pointer(snd_pcm_substream_
 {
 	cs46xx_t *chip = snd_pcm_substream_chip(substream);
 	size_t ptr;
-	cs46xx_pcm_t *cpcm = snd_magic_cast(cs46xx_pcm_t, substream->runtime->private_data, return -ENXIO);
-	ssize_t bytes;
-	int buffer_size = substream->runtime->period_size * CS46XX_FRAGS << cpcm->shift;
+	cs46xx_pcm_t *cpcm = substream->runtime->private_data;
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
 	snd_assert (cpcm->pcm_channel,return -ENXIO);
@@ -800,18 +743,7 @@ static snd_pcm_uframes_t snd_cs46xx_playback_indirect_pointer(snd_pcm_substream_
 	ptr = snd_cs46xx_peek(chip, BA1_PBA);
 #endif
 	ptr -= cpcm->hw_buf.addr;
-
-	bytes = ptr - cpcm->hw_io;
-
-	if (bytes < 0)
-		bytes += buffer_size;
-	cpcm->hw_io = ptr;
-	cpcm->hw_ready -= bytes;
-	cpcm->sw_io += bytes;
-	if (cpcm->sw_io >= cpcm->sw_bufsize)
-		cpcm->sw_io -= cpcm->sw_bufsize;
-	snd_cs46xx_playback_transfer(substream);
-	return cpcm->sw_io >> cpcm->shift;
+	return snd_pcm_indirect_playback_pointer(substream, &cpcm->pcm_rec, ptr);
 }
 
 static snd_pcm_uframes_t snd_cs46xx_capture_direct_pointer(snd_pcm_substream_t * substream)
@@ -825,18 +757,7 @@ static snd_pcm_uframes_t snd_cs46xx_capture_indirect_pointer(snd_pcm_substream_t
 {
 	cs46xx_t *chip = snd_pcm_substream_chip(substream);
 	size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_buf.addr;
-	ssize_t bytes = ptr - chip->capt.hw_io;
-	int buffer_size = substream->runtime->period_size * CS46XX_FRAGS << chip->capt.shift;
-
-	if (bytes < 0)
-		bytes += buffer_size;
-	chip->capt.hw_io = ptr;
-	chip->capt.hw_ready += bytes;
-	chip->capt.sw_io += bytes;
-	if (chip->capt.sw_io >= chip->capt.sw_bufsize)
-		chip->capt.sw_io -= chip->capt.sw_bufsize;
-	snd_cs46xx_capture_transfer(substream);
-	return chip->capt.sw_io >> chip->capt.shift;
+	return snd_pcm_indirect_capture_pointer(substream, &chip->capt.pcm_rec, ptr);
 }
 
 static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
@@ -847,13 +768,7 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
 	int result = 0;
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
-	cs46xx_pcm_t *cpcm = snd_magic_cast(cs46xx_pcm_t, substream->runtime->private_data, return -ENXIO);
-#else
-	spin_lock(&chip->reg_lock);
-#endif
-
-#ifdef CONFIG_SND_CS46XX_NEW_DSP
-
+	cs46xx_pcm_t *cpcm = substream->runtime->private_data;
 	if (! cpcm->pcm_channel) {
 		return -ENXIO;
 	}
@@ -872,6 +787,7 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
 		if (substream->runtime->periods != CS46XX_FRAGS)
 			snd_cs46xx_playback_transfer(substream);
 #else
+		spin_lock(&chip->reg_lock);
 		if (substream->runtime->periods != CS46XX_FRAGS)
 			snd_cs46xx_playback_transfer(substream);
 		{ unsigned int tmp;
@@ -879,6 +795,7 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
 		tmp &= 0x0000ffff;
 		snd_cs46xx_poke(chip, BA1_PCTL, chip->play_ctl | tmp);
 		}
+		spin_unlock(&chip->reg_lock);
 #endif
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
@@ -891,11 +808,13 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
 		if (!cpcm->pcm_channel->unlinked)
 			cs46xx_dsp_pcm_unlink(chip,cpcm->pcm_channel);
 #else
+		spin_lock(&chip->reg_lock);
 		{ unsigned int tmp;
 		tmp = snd_cs46xx_peek(chip, BA1_PCTL);
 		tmp &= 0x0000ffff;
 		snd_cs46xx_poke(chip, BA1_PCTL, tmp);
 		}
+		spin_unlock(&chip->reg_lock);
 #endif
 		break;
 	default:
@@ -903,10 +822,6 @@ static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
 		break;
 	}
 
-#ifndef CONFIG_SND_CS46XX_NEW_DSP
-	spin_unlock(&chip->reg_lock);
-#endif
-
 	return result;
 }
 
@@ -987,7 +902,7 @@ static int snd_cs46xx_playback_hw_params(snd_pcm_substream_t * substream,
 	int sample_rate = params_rate(hw_params);
 	int period_size = params_period_bytes(hw_params);
 #endif
-	cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO);
+	cpcm = runtime->private_data;
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
 	snd_assert (sample_rate != 0, return -ENXIO);
@@ -1084,7 +999,7 @@ static int snd_cs46xx_playback_hw_free(snd_pcm_substream_t * substream)
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	cs46xx_pcm_t *cpcm;
 
-	cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO);
+	cpcm = runtime->private_data;
 
 	/* if play_back open fails, then this function
 	   is called and cpcm can actually be NULL here */
@@ -1108,7 +1023,7 @@ static int snd_cs46xx_playback_prepare(snd_pcm_substream_t * substream)
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	cs46xx_pcm_t *cpcm;
 
-	cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO);
+	cpcm = runtime->private_data;
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
     snd_assert (cpcm->pcm_channel != NULL, return -ENXIO);
@@ -1143,10 +1058,9 @@ static int snd_cs46xx_playback_prepare(snd_pcm_substream_t * substream)
 			pfie |= 0x00004000;
 	}
 	
-	cpcm->sw_bufsize = snd_pcm_lib_buffer_bytes(substream);
-	cpcm->sw_data = cpcm->sw_io = cpcm->sw_ready = 0;
-	cpcm->hw_data = cpcm->hw_io = cpcm->hw_ready = 0;
-	cpcm->appl_ptr = 0;
+	memset(&cpcm->pcm_rec, 0, sizeof(cpcm->pcm_rec));
+	cpcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+	cpcm->pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << cpcm->shift;
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
 
@@ -1223,10 +1137,9 @@ static int snd_cs46xx_capture_prepare(snd_pcm_substream_t * substream)
 
 	snd_cs46xx_poke(chip, BA1_CBA, chip->capt.hw_buf.addr);
 	chip->capt.shift = 2;
-	chip->capt.sw_bufsize = snd_pcm_lib_buffer_bytes(substream);
-	chip->capt.sw_data = chip->capt.sw_io = chip->capt.sw_ready = 0;
-	chip->capt.hw_data = chip->capt.hw_io = chip->capt.hw_ready = 0;
-	chip->capt.appl_ptr = 0;
+	memset(&chip->capt.pcm_rec, 0, sizeof(chip->capt.pcm_rec));
+	chip->capt.pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+	chip->capt.pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << 2;
 	snd_cs46xx_set_capture_sample_rate(chip, runtime->rate);
 
 	return 0;
@@ -1234,7 +1147,7 @@ static int snd_cs46xx_capture_prepare(snd_pcm_substream_t * substream)
 
 static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, dev_id, return IRQ_NONE);
+	cs46xx_t *chip = dev_id;
 	u32 status1;
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
 	dsp_spos_instance_t * ins = chip->dsp_spos_instance;
@@ -1265,7 +1178,7 @@ static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *r
 					if (ins->pcm_channels[i].active &&
 					    ins->pcm_channels[i].private_data &&
 					    !ins->pcm_channels[i].unlinked) {
-						cpcm = snd_magic_cast(cs46xx_pcm_t, ins->pcm_channels[i].private_data, continue);
+						cpcm = ins->pcm_channels[i].private_data;
 						snd_pcm_period_elapsed(cpcm->substream);
 					}
 				}
@@ -1275,7 +1188,7 @@ static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *r
 				if (ins->pcm_channels[i].active && 
 				    ins->pcm_channels[i].private_data &&
 				    !ins->pcm_channels[i].unlinked) {
-					cpcm = snd_magic_cast(cs46xx_pcm_t, ins->pcm_channels[i].private_data, continue);
+					cpcm = ins->pcm_channels[i].private_data;
 					snd_pcm_period_elapsed(cpcm->substream);
 				}
 			}
@@ -1302,7 +1215,9 @@ static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *r
 			c = snd_cs46xx_peekBA0(chip, BA0_MIDRP);
 			if ((chip->midcr & MIDCR_RIE) == 0)
 				continue;
+			spin_unlock(&chip->reg_lock);
 			snd_rawmidi_receive(chip->midi_input, &c, 1);
+			spin_lock(&chip->reg_lock);
 		}
 		while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) {
 			if ((chip->midcr & MIDCR_TIE) == 0)
@@ -1370,10 +1285,8 @@ static snd_pcm_hardware_t snd_cs46xx_capture =
 
 static unsigned int period_sizes[] = { 32, 64, 128, 256, 512, 1024, 2048 };
 
-#define PERIOD_SIZES sizeof(period_sizes) / sizeof(period_sizes[0])
-
 static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = {
-	.count = PERIOD_SIZES,
+	.count = ARRAY_SIZE(period_sizes),
 	.list = period_sizes,
 	.mask = 0
 };
@@ -1382,10 +1295,8 @@ static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = {
 
 static void snd_cs46xx_pcm_free_substream(snd_pcm_runtime_t *runtime)
 {
-	cs46xx_pcm_t * cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return);
-	
-	if (cpcm)
-		snd_magic_kfree(cpcm);
+	cs46xx_pcm_t * cpcm = runtime->private_data;
+	kfree(cpcm);
 }
 
 static int _cs46xx_playback_open_channel (snd_pcm_substream_t * substream,int pcm_channel_id)
@@ -1394,11 +1305,12 @@ static int _cs46xx_playback_open_channel (snd_pcm_substream_t * substream,int pc
 	cs46xx_pcm_t * cpcm;
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
-	cpcm = snd_magic_kcalloc(cs46xx_pcm_t, 0, GFP_KERNEL);
+	cpcm = kcalloc(1, sizeof(*cpcm), GFP_KERNEL);
 	if (cpcm == NULL)
 		return -ENOMEM;
-	if (snd_dma_alloc_pages(&chip->dma_dev, PAGE_SIZE, &cpcm->hw_buf) < 0) {
-		snd_magic_kfree(cpcm);
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+				PAGE_SIZE, &cpcm->hw_buf) < 0) {
+		kfree(cpcm);
 		return -ENOMEM;
 	}
 
@@ -1486,7 +1398,8 @@ static int snd_cs46xx_capture_open(snd_pcm_substream_t * substream)
 {
 	cs46xx_t *chip = snd_pcm_substream_chip(substream);
 
-	if (snd_dma_alloc_pages(&chip->dma_dev, PAGE_SIZE, &chip->capt.hw_buf) < 0)
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+				PAGE_SIZE, &chip->capt.hw_buf) < 0)
 		return -ENOMEM;
 	chip->capt.substream = substream;
 	substream->runtime->hw = snd_cs46xx_capture;
@@ -1510,7 +1423,7 @@ static int snd_cs46xx_playback_close(snd_pcm_substream_t * substream)
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	cs46xx_pcm_t * cpcm;
 
-	cpcm = snd_magic_cast(cs46xx_pcm_t, runtime->private_data, return -ENXIO);
+	cpcm = runtime->private_data;
 
 	/* when playback_open fails, then cpcm can be NULL */
 	if (!cpcm) return -ENXIO;
@@ -1527,7 +1440,7 @@ static int snd_cs46xx_playback_close(snd_pcm_substream_t * substream)
 #endif
 
 	cpcm->substream = NULL;
-	snd_dma_free_pages(&chip->dma_dev, &cpcm->hw_buf);
+	snd_dma_free_pages(&cpcm->hw_buf);
 	chip->active_ctrl(chip, -1);
 
 	return 0;
@@ -1538,7 +1451,7 @@ static int snd_cs46xx_capture_close(snd_pcm_substream_t * substream)
 	cs46xx_t *chip = snd_pcm_substream_chip(substream);
 
 	chip->capt.substream = NULL;
-	snd_dma_free_pages(&chip->dma_dev, &chip->capt.hw_buf);
+	snd_dma_free_pages(&chip->capt.hw_buf);
 	chip->active_ctrl(chip, -1);
 
 	return 0;
@@ -1664,7 +1577,7 @@ snd_pcm_ops_t snd_cs46xx_capture_indirect_ops = {
 
 static void snd_cs46xx_pcm_free(snd_pcm_t *pcm)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, pcm->private_data, return);
+	cs46xx_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1672,21 +1585,21 @@ static void snd_cs46xx_pcm_free(snd_pcm_t *pcm)
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
 static void snd_cs46xx_pcm_rear_free(snd_pcm_t *pcm)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, pcm->private_data, return);
+	cs46xx_t *chip = pcm->private_data;
 	chip->pcm_rear = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
 static void snd_cs46xx_pcm_center_lfe_free(snd_pcm_t *pcm)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, pcm->private_data, return);
+	cs46xx_t *chip = pcm->private_data;
 	chip->pcm_center_lfe = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
 static void snd_cs46xx_pcm_iec958_free(snd_pcm_t *pcm)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, pcm->private_data, return);
+	cs46xx_t *chip = pcm->private_data;
 	chip->pcm_iec958 = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1824,14 +1737,14 @@ int __devinit snd_cs46xx_pcm_iec958(cs46xx_t *chip, int device, snd_pcm_t ** rpc
  */
 static void snd_cs46xx_mixer_free_ac97_bus(ac97_bus_t *bus)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, bus->private_data, return);
+	cs46xx_t *chip = bus->private_data;
 
 	chip->ac97_bus = NULL;
 }
 
 static void snd_cs46xx_mixer_free_ac97(ac97_t *ac97)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, ac97->private_data, return);
+	cs46xx_t *chip = ac97->private_data;
 
 	snd_assert ((ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]) ||
 		    (ac97 == chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]),
@@ -2420,7 +2333,7 @@ static void snd_cs46xx_codec_reset (ac97_t * ac97)
 {
 	unsigned long end_time;
 	int err;
-	cs46xx_t * chip = snd_magic_cast(cs46xx_t,ac97->private_data,return /* -ENXIO */);
+	cs46xx_t * chip = ac97->private_data;
 
 	/* reset to defaults */
 	snd_ac97_write(ac97, AC97_RESET, 0);	
@@ -2470,39 +2383,38 @@ static void snd_cs46xx_codec_reset (ac97_t * ac97)
 int __devinit snd_cs46xx_mixer(cs46xx_t *chip)
 {
 	snd_card_t *card = chip->card;
-	ac97_bus_t bus;
-	ac97_t ac97;
+	ac97_template_t ac97;
 	snd_ctl_elem_id_t id;
 	int err;
 	unsigned int idx;
+	static ac97_bus_ops_t ops = {
+#ifdef CONFIG_SND_CS46XX_NEW_DSP
+		.reset = snd_cs46xx_codec_reset,
+#endif
+		.write = snd_cs46xx_ac97_write,
+		.read = snd_cs46xx_ac97_read,
+	};
 
 	/* detect primary codec */
 	chip->nr_ac97_codecs = 0;
 	snd_printdd("snd_cs46xx: detecting primary codec\n");
-	memset(&bus, 0, sizeof(bus));
-	bus.write = snd_cs46xx_ac97_write;
-	bus.read = snd_cs46xx_ac97_read;
-#ifdef CONFIG_SND_CS46XX_NEW_DSP
-	bus.reset = snd_cs46xx_codec_reset;
-#endif
-	bus.private_data = chip;
-	bus.private_free = snd_cs46xx_mixer_free_ac97_bus;
-	if ((err = snd_ac97_bus(card, &bus, &chip->ac97_bus)) < 0)
+	if ((err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus)) < 0)
 		return err;
+	chip->ac97_bus->private_free = snd_cs46xx_mixer_free_ac97_bus;
 
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = chip;
 	ac97.private_free = snd_cs46xx_mixer_free_ac97;
-	chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] = &ac97;
 
-	snd_cs46xx_ac97_write(&ac97, AC97_MASTER, 0x8000);
+	snd_cs46xx_codec_write(chip, AC97_MASTER, 0x8000,
+			       CS46XX_PRIMARY_CODEC_INDEX);
 	for (idx = 0; idx < 100; ++idx) {
-		if (snd_cs46xx_ac97_read(&ac97, AC97_MASTER) == 0x8000)
+		if (snd_cs46xx_codec_read(chip, AC97_MASTER,
+					  CS46XX_PRIMARY_CODEC_INDEX) == 0x8000)
 			goto _ok;
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(HZ/100);
 	}
-	chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] = NULL;
 	return -ENXIO;
 
  _ok:
@@ -2519,18 +2431,21 @@ int __devinit snd_cs46xx_mixer(cs46xx_t *chip)
 	ac97.private_free = snd_cs46xx_mixer_free_ac97;
 	ac97.num = CS46XX_SECONDARY_CODEC_INDEX;
 
-	snd_cs46xx_ac97_write(&ac97, AC97_RESET, 0);
+	snd_cs46xx_codec_write(chip, AC97_RESET, 0,
+			       CS46XX_SECONDARY_CODEC_INDEX);
 	udelay(10);
 
-	if (snd_cs46xx_ac97_read(&ac97, AC97_RESET) & 0x8000) {
+	if (snd_cs46xx_codec_read(chip, AC97_RESET,
+				  CS46XX_SECONDARY_CODEC_INDEX) & 0x8000) {
 		snd_printdd("snd_cs46xx: seconadry codec not present\n");
 		goto _no_sec_codec;
 	}
 
-	chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] = &ac97;
-	snd_cs46xx_ac97_write(&ac97, AC97_MASTER, 0x8000);
+	snd_cs46xx_codec_write(chip, AC97_MASTER, 0x8000,
+			       CS46XX_SECONDARY_CODEC_INDEX);
 	for (idx = 0; idx < 100; ++idx) {
-		if (snd_cs46xx_ac97_read(&ac97, AC97_MASTER) == 0x8000) {
+		if (snd_cs46xx_codec_read(chip, AC97_MASTER,
+					  CS46XX_SECONDARY_CODEC_INDEX) == 0x8000) {
 			goto _ok2;
 		}
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -2540,7 +2455,6 @@ int __devinit snd_cs46xx_mixer(cs46xx_t *chip)
  _no_sec_codec:
 	snd_printdd("snd_cs46xx: secondary codec did not respond ...\n");
 
-	chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] = NULL;
 	chip->nr_ac97_codecs = 1;
     
 	/* well, one codec only ... */
@@ -2605,11 +2519,10 @@ static void snd_cs46xx_midi_reset(cs46xx_t *chip)
 
 static int snd_cs46xx_midi_input_open(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return -ENXIO);
+	cs46xx_t *chip = substream->rmidi->private_data;
 
 	chip->active_ctrl(chip, 1);
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	chip->uartm |= CS46XX_MODE_INPUT;
 	chip->midcr |= MIDCR_RXE;
 	chip->midi_input = substream;
@@ -2618,16 +2531,15 @@ static int snd_cs46xx_midi_input_open(snd_rawmidi_substream_t * substream)
 	} else {
 		snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
 static int snd_cs46xx_midi_input_close(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return -ENXIO);
+	cs46xx_t *chip = substream->rmidi->private_data;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	chip->midcr &= ~(MIDCR_RXE | MIDCR_RIE);
 	chip->midi_input = NULL;
 	if (!(chip->uartm & CS46XX_MODE_OUTPUT)) {
@@ -2636,19 +2548,18 @@ static int snd_cs46xx_midi_input_close(snd_rawmidi_substream_t * substream)
 		snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
 	}
 	chip->uartm &= ~CS46XX_MODE_INPUT;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	chip->active_ctrl(chip, -1);
 	return 0;
 }
 
 static int snd_cs46xx_midi_output_open(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return -ENXIO);
+	cs46xx_t *chip = substream->rmidi->private_data;
 
 	chip->active_ctrl(chip, 1);
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	chip->uartm |= CS46XX_MODE_OUTPUT;
 	chip->midcr |= MIDCR_TXE;
 	chip->midi_output = substream;
@@ -2657,16 +2568,15 @@ static int snd_cs46xx_midi_output_open(snd_rawmidi_substream_t * substream)
 	} else {
 		snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
 static int snd_cs46xx_midi_output_close(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return -ENXIO);
+	cs46xx_t *chip = substream->rmidi->private_data;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	chip->midcr &= ~(MIDCR_TXE | MIDCR_TIE);
 	chip->midi_output = NULL;
 	if (!(chip->uartm & CS46XX_MODE_INPUT)) {
@@ -2675,7 +2585,7 @@ static int snd_cs46xx_midi_output_close(snd_rawmidi_substream_t * substream)
 		snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
 	}
 	chip->uartm &= ~CS46XX_MODE_OUTPUT;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	chip->active_ctrl(chip, -1);
 	return 0;
 }
@@ -2683,7 +2593,7 @@ static int snd_cs46xx_midi_output_close(snd_rawmidi_substream_t * substream)
 static void snd_cs46xx_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
 {
 	unsigned long flags;
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return);
+	cs46xx_t *chip = substream->rmidi->private_data;
 
 	spin_lock_irqsave(&chip->reg_lock, flags);
 	if (up) {
@@ -2703,7 +2613,7 @@ static void snd_cs46xx_midi_input_trigger(snd_rawmidi_substream_t * substream, i
 static void snd_cs46xx_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
 {
 	unsigned long flags;
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, substream->rmidi->private_data, return);
+	cs46xx_t *chip = substream->rmidi->private_data;
 	unsigned char byte;
 
 	spin_lock_irqsave(&chip->reg_lock, flags);
@@ -2781,7 +2691,7 @@ static void snd_cs46xx_gameport_trigger(struct gameport *gameport)
 	cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport;
 	cs46xx_t *chip;
 	snd_assert(gp, return);
-	chip = snd_magic_cast(cs46xx_t, gp->chip, return);
+	chip = gp->chip;
 	snd_cs46xx_pokeBA0(chip, BA0_JSPT, 0xFF);  //outb(gameport->io, 0xFF);
 }
 
@@ -2790,7 +2700,7 @@ static unsigned char snd_cs46xx_gameport_read(struct gameport *gameport)
 	cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport;
 	cs46xx_t *chip;
 	snd_assert(gp, return 0);
-	chip = snd_magic_cast(cs46xx_t, gp->chip, return 0);
+	chip = gp->chip;
 	return snd_cs46xx_peekBA0(chip, BA0_JSPT); //inb(gameport->io);
 }
 
@@ -2801,7 +2711,7 @@ static int snd_cs46xx_gameport_cooked_read(struct gameport *gameport, int *axes,
 	unsigned js1, js2, jst;
 	
 	snd_assert(gp, return 0);
-	chip = snd_magic_cast(cs46xx_t, gp->chip, return 0);
+	chip = gp->chip;
 
 	js1 = snd_cs46xx_peekBA0(chip, BA0_JSC1);
 	js2 = snd_cs46xx_peekBA0(chip, BA0_JSC2);
@@ -3011,13 +2921,13 @@ static int snd_cs46xx_free(cs46xx_t *chip)
 	}
 #endif
 	
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_cs46xx_dev_free(snd_device_t *device)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, device->device_data, return -ENXIO);
+	cs46xx_t *chip = device->device_data;
 	return snd_cs46xx_free(chip);
 }
 
@@ -3786,7 +3696,7 @@ static struct cs_card_type __devinitdata cards[] = {
 #ifdef CONFIG_PM
 static int snd_cs46xx_suspend(snd_card_t *card, unsigned int state)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, card->pm_private_data, return -EINVAL);
+	cs46xx_t *chip = card->pm_private_data;
 	int amp_saved;
 
 	snd_pcm_suspend_all(chip->pcm);
@@ -3810,7 +3720,7 @@ static int snd_cs46xx_suspend(snd_card_t *card, unsigned int state)
 
 static int snd_cs46xx_resume(snd_card_t *card, unsigned int state)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, card->pm_private_data, return -EINVAL);
+	cs46xx_t *chip = card->pm_private_data;
 	int amp_saved;
 
 	pci_enable_device(chip->pci);
@@ -3869,7 +3779,7 @@ int __devinit snd_cs46xx_create(snd_card_t * card,
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	chip = snd_magic_kcalloc(cs46xx_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
@@ -3913,10 +3823,6 @@ int __devinit snd_cs46xx_create(snd_card_t * card,
 	region->base = chip->ba1_addr + BA1_SP_REG;
 	region->size = CS46XX_BA1_REG_SIZE;
 
-	memset(&chip->dma_dev, 0, sizeof(chip->dma_dev));
-	chip->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	chip->dma_dev.dev = snd_dma_pci_data(pci);
-
 	/* set up amp and clkrun hack */
 	pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &ss_vendor);
 	pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &ss_card);
diff --git a/sound/pci/cs46xx/cs46xx_lib.h b/sound/pci/cs46xx/cs46xx_lib.h
index 3eae4f233..52575f924 100644
--- a/sound/pci/cs46xx/cs46xx_lib.h
+++ b/sound/pci/cs46xx/cs46xx_lib.h
@@ -22,8 +22,6 @@
 #ifndef __CS46XX_LIB_H__
 #define __CS46XX_LIB_H__
 
-#define chip_t cs46xx_t
-
 /*
  *  constants
  */
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c
index 95fc96f9f..0bd4b33d0 100644
--- a/sound/pci/cs46xx/dsp_spos.c
+++ b/sound/pci/cs46xx/dsp_spos.c
@@ -74,7 +74,7 @@ static int shadow_and_reallocate_code (cs46xx_t * chip,u32 * data,u32 size, u32
 			    (mop_operands & WIDE_LADD_INSTR_MASK) == 0 &&
 			    (mop_operands & WIDE_INSTR_MASK) != 0) {
 				wide_op = loval & 0x7f;
-				for (j = 0;j < sizeof(wide_opcodes) / sizeof(wide_opcode_t); ++j) {
+				for (j = 0;j < ARRAY_SIZE(wide_opcodes); ++j) {
 					if (wide_opcodes[j] == wide_op) {
 						/* need to reallocate instruction */
 						address  = (hival & 0x00FFF) << 5;
@@ -462,7 +462,7 @@ symbol_entry_t * cs46xx_dsp_lookup_symbol_addr (cs46xx_t * chip, u32 address, in
 
 static void cs46xx_dsp_proc_symbol_table_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, entry->private_data, return);
+	cs46xx_t *chip = entry->private_data;
 	dsp_spos_instance_t * ins = chip->dsp_spos_instance;
 	int i;
 
@@ -489,7 +489,7 @@ static void cs46xx_dsp_proc_symbol_table_read (snd_info_entry_t *entry, snd_info
 
 static void cs46xx_dsp_proc_modules_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, entry->private_data, return);
+	cs46xx_t *chip = entry->private_data;
 	dsp_spos_instance_t * ins = chip->dsp_spos_instance;
 	int i,j;
 
@@ -511,7 +511,7 @@ static void cs46xx_dsp_proc_modules_read (snd_info_entry_t *entry, snd_info_buff
 
 static void cs46xx_dsp_proc_task_tree_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, entry->private_data, return);
+	cs46xx_t *chip = entry->private_data;
 	dsp_spos_instance_t * ins = chip->dsp_spos_instance;
 	int i,j,col;
 	unsigned long dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
@@ -538,7 +538,7 @@ static void cs46xx_dsp_proc_task_tree_read (snd_info_entry_t *entry, snd_info_bu
 
 static void cs46xx_dsp_proc_scb_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, entry->private_data, return);
+	cs46xx_t *chip = entry->private_data;
 	dsp_spos_instance_t * ins = chip->dsp_spos_instance;
 	int i;
 
@@ -570,7 +570,7 @@ static void cs46xx_dsp_proc_scb_read (snd_info_entry_t *entry, snd_info_buffer_t
 
 static void cs46xx_dsp_proc_parameter_dump_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, entry->private_data, return);
+	cs46xx_t *chip = entry->private_data;
 	/*dsp_spos_instance_t * ins = chip->dsp_spos_instance; */
 	unsigned int i,col = 0;
 	unsigned long dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
@@ -597,7 +597,7 @@ static void cs46xx_dsp_proc_parameter_dump_read (snd_info_entry_t *entry, snd_in
 
 static void cs46xx_dsp_proc_sample_dump_read (snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, entry->private_data, return);
+	cs46xx_t *chip = entry->private_data;
 	int i,col = 0;
 	unsigned long dst = chip->region.idx[2].remap_addr;
 
@@ -1057,7 +1057,7 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
 	
 	int fifo_addr,fifo_span,valid_slots;
 
-	spos_control_block_t sposcb = {
+	static spos_control_block_t sposcb = {
 		/* 0 */ HFG_TREE_SCB,HFG_STACK,
 		/* 1 */ SPOSCB_ADDR,BG_TREE_SCB_ADDR,
 		/* 2 */ DSP_SPOS_DC,0,
@@ -1110,18 +1110,18 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
   
 	{
 		/* create the null SCB */
-		generic_scb_t null_scb = {
+		static generic_scb_t null_scb = {
 			{ 0, 0, 0, 0 },
 			{ 0, 0, 0, 0, 0 },
 			NULL_SCB_ADDR, NULL_SCB_ADDR,
-			null_algorithm->address, 0,
-			0,0,0,
+			0, 0, 0, 0, 0,
 			{
 				0,0,
 				0,0,
 			}
 		};
 
+		null_scb.entry_point = null_algorithm->address;
 		ins->the_null_scb = cs46xx_dsp_create_scb(chip, "nullSCB", (u32 *)&null_scb, NULL_SCB_ADDR);
 		ins->the_null_scb->task_entry = null_algorithm;
 		ins->the_null_scb->sub_list_ptr = ins->the_null_scb;
@@ -1132,7 +1132,7 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
 
 	{
 		/* setup foreground task tree */
-		task_tree_control_block_t fg_task_tree_hdr =  {
+		static task_tree_control_block_t fg_task_tree_hdr =  {
 			{ FG_TASK_HEADER_ADDR | (DSP_SPOS_DC << 0x10),
 			  DSP_SPOS_DC_DC,
 			  DSP_SPOS_DC_DC,
@@ -1145,7 +1145,7 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
     
 			{
 				BG_TREE_SCB_ADDR,TIMINGMASTER_SCB_ADDR, 
-				fg_task_tree_header_code->address,
+				0,
 				FG_TASK_HEADER_ADDR + TCBData,                  
 			},
 
@@ -1158,7 +1158,7 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
 			},
 
 			{
-				DSP_SPOS_DC,task_tree_thread->address,
+				DSP_SPOS_DC,0,
 				DSP_SPOS_DC,DSP_SPOS_DC,
 				DSP_SPOS_DC,DSP_SPOS_DC,
 				DSP_SPOS_DC,DSP_SPOS_DC,
@@ -1200,13 +1200,15 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
 			}
 		};
 
+		fg_task_tree_hdr.links.entry_point = fg_task_tree_header_code->address;
+		fg_task_tree_hdr.context_blk.stack0 = task_tree_thread->address;
 		cs46xx_dsp_create_task_tree(chip,"FGtaskTreeHdr",(u32 *)&fg_task_tree_hdr,FG_TASK_HEADER_ADDR,0x35);
 	}
 
 
 	{
 		/* setup foreground task tree */
-		task_tree_control_block_t bg_task_tree_hdr =  {
+		static task_tree_control_block_t bg_task_tree_hdr =  {
 			{ DSP_SPOS_DC_DC,
 			  DSP_SPOS_DC_DC,
 			  DSP_SPOS_DC_DC,
@@ -1219,7 +1221,7 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
     
 			{
 				NULL_SCB_ADDR,NULL_SCB_ADDR,  /* Set up the background to do nothing */
-				task_tree_header_code->address,
+				0,
 				BG_TREE_SCB_ADDR + TCBData,
 			},
 
@@ -1232,7 +1234,7 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
 			},
 
 			{
-				DSP_SPOS_DC,task_tree_thread->address,
+				DSP_SPOS_DC,0,
 				DSP_SPOS_DC,DSP_SPOS_DC,
 				DSP_SPOS_DC,DSP_SPOS_DC,
 				DSP_SPOS_DC,DSP_SPOS_DC,
@@ -1273,6 +1275,9 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
 				0,0
 			}
 		};
+
+		bg_task_tree_hdr.links.entry_point = task_tree_header_code->address;
+		bg_task_tree_hdr.context_blk.stack0 = task_tree_thread->address;
 		cs46xx_dsp_create_task_tree(chip,"BGtaskTreeHdr",(u32 *)&bg_task_tree_hdr,BG_TREE_SCB_ADDR,0x35);
 	}
 
@@ -1312,7 +1317,7 @@ int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip)
 	if (!write_back_scb) goto _fail_end;
 
 	{
-		mix2_ostream_spb_t mix2_ostream_spb = {
+		static mix2_ostream_spb_t mix2_ostream_spb = {
 			0x00020000,
 			0x0000ffff
 		};
diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c
index c02a9497c..4bf170bda 100644
--- a/sound/pci/cs46xx/dsp_spos_scb_lib.c
+++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c
@@ -69,7 +69,7 @@ static void cs46xx_dsp_proc_scb_info_read (snd_info_entry_t *entry, snd_info_buf
 	proc_scb_info_t * scb_info  = (proc_scb_info_t *)entry->private_data;
 	dsp_scb_descriptor_t * scb = scb_info->scb_desc;
 	dsp_spos_instance_t * ins;
-	cs46xx_t *chip = snd_magic_cast(cs46xx_t, scb_info->chip, return);
+	cs46xx_t *chip = scb_info->chip;
 	int j,col;
 	unsigned long dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
 
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index 552bdee31..e49731b6f 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -31,8 +31,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("EMU10K1");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Creative Labs,SB Live!/PCI512/E-mu APS},"
+MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB Live!/PCI512/E-mu APS},"
 	       "{Creative Labs,SB Audigy}}");
 
 #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
@@ -53,37 +52,25 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for the EMU10K1 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for the EMU10K1 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable the EMU10K1 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(extin, int, boot_devs, 0444);
 MODULE_PARM_DESC(extin, "Available external inputs for FX8010. Zero=default.");
-MODULE_PARM_SYNTAX(extin, SNDRV_ENABLED "allows:{{0,0x0ffff}},base:16");
 module_param_array(extout, int, boot_devs, 0444);
 MODULE_PARM_DESC(extout, "Available external outputs for FX8010. Zero=default.");
-MODULE_PARM_SYNTAX(extout, SNDRV_ENABLED "allows:{{0,0x0ffff}},base:16");
 module_param_array(seq_ports, int, boot_devs, 0444);
 MODULE_PARM_DESC(seq_ports, "Allocated sequencer ports for internal synthesizer.");
-MODULE_PARM_SYNTAX(seq_ports, SNDRV_ENABLED "allows:{{0,32}}");
 module_param_array(max_synth_voices, int, boot_devs, 0444);
 MODULE_PARM_DESC(max_synth_voices, "Maximum number of voices for WaveTable.");
-MODULE_PARM_SYNTAX(max_synth_voices, SNDRV_ENABLED);
 module_param_array(max_buffer_size, int, boot_devs, 0444);
 MODULE_PARM_DESC(max_buffer_size, "Maximum sample buffer size in MB.");
-MODULE_PARM_SYNTAX(max_buffer_size, SNDRV_ENABLED);
 module_param_array(enable_ir, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable_ir, "Enable IR.");
-MODULE_PARM_SYNTAX(enable_ir, SNDRV_ENABLE_DESC);
 
 static struct pci_device_id snd_emu10k1_ids[] = {
 	{ 0x1102, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	/* EMU10K1 */
-#if 0 /* FIXME: not working! */
-	{ 0x1102, 0x0006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	/* Dell OEM version (EMU10K1) */
-#endif
 	{ 0x1102, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },	/* Audigy */
 	{ 0, }
 };
@@ -134,10 +121,6 @@ static int __devinit snd_card_emu10k1_probe(struct pci_dev *pci,
 		snd_card_free(card);
 		return err;
 	}		
-	if ((err = snd_emu10k1_fx8010_pcm(emu, 3, NULL)) < 0) {
-		snd_card_free(card);
-		return err;
-	}		
 	if ((err = snd_emu10k1_mixer(emu)) < 0) {
 		snd_card_free(card);
 		return err;
diff --git a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c
index c3975fbaa..580701e90 100644
--- a/sound/pci/emu10k1/emu10k1_callback.c
+++ b/sound/pci/emu10k1/emu10k1_callback.c
@@ -93,7 +93,7 @@ snd_emu10k1_synth_get_voice(emu10k1_t *hw)
 	unsigned long flags;
 	int i;
 
-	emu = snd_magic_cast(snd_emux_t, hw->synth, return -EINVAL);
+	emu = hw->synth;
 
 	spin_lock_irqsave(&emu->voice_lock, flags);
 	lookup_voices(emu, hw, best, 1); /* no OFF voices */
@@ -128,7 +128,7 @@ release_voice(snd_emux_voice_t *vp)
 	int dcysusv;
 	emu10k1_t *hw;
 	
-	hw = snd_magic_cast(emu10k1_t, vp->hw, return);
+	hw = vp->hw;
 	dcysusv = 0x8000 | (unsigned char)vp->reg.parm.modrelease;
 	snd_emu10k1_ptr_write(hw, DCYSUSM, vp->ch, dcysusv);
 	dcysusv = 0x8000 | (unsigned char)vp->reg.parm.volrelease | DCYSUSV_CHANNELENABLE_MASK;
@@ -145,7 +145,7 @@ terminate_voice(snd_emux_voice_t *vp)
 	emu10k1_t *hw;
 	
 	snd_assert(vp, return);
-	hw = snd_magic_cast(emu10k1_t, vp->hw, return);
+	hw = vp->hw;
 	snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK);
 	if (vp->block) {
 		emu10k1_memblk_t *emem;
@@ -163,7 +163,7 @@ free_voice(snd_emux_voice_t *vp)
 {
 	emu10k1_t *hw;
 	
-	hw = snd_magic_cast(emu10k1_t, vp->hw, return);
+	hw = vp->hw;
 	if (vp->ch >= 0) {
 		snd_emu10k1_ptr_write(hw, IFATN, vp->ch, 0xff00);
 		snd_emu10k1_ptr_write(hw, DCYSUSV, vp->ch, 0x807f | DCYSUSV_CHANNELENABLE_MASK);
@@ -185,7 +185,7 @@ update_voice(snd_emux_voice_t *vp, int update)
 {
 	emu10k1_t *hw;
 	
-	hw = snd_magic_cast(emu10k1_t, vp->hw, return);
+	hw = vp->hw;
 	if (update & SNDRV_EMUX_UPDATE_VOLUME)
 		snd_emu10k1_ptr_write(hw, IFATN_ATTENUATION, vp->ch, vp->avol);
 	if (update & SNDRV_EMUX_UPDATE_PITCH)
@@ -282,7 +282,7 @@ get_voice(snd_emux_t *emu, snd_emux_port_t *port)
 	best_voice_t best[V_END];
 	int i;
 
-	hw = snd_magic_cast(emu10k1_t, emu->hw, return NULL);
+	hw = emu->hw;
 
 	lookup_voices(emu, hw, best, 0);
 	for (i = 0; i < V_END; i++) {
@@ -317,7 +317,7 @@ start_voice(snd_emux_voice_t *vp)
 	emu10k1_t *hw;
 	emu10k1_memblk_t *emem;
 	
-	hw = snd_magic_cast(emu10k1_t, vp->hw, return -EINVAL);
+	hw = vp->hw;
 	ch = vp->ch;
 	snd_assert(ch >= 0, return -EINVAL);
 	chan = vp->chan;
@@ -469,7 +469,7 @@ trigger_voice(snd_emux_voice_t *vp)
 	emu10k1_t *hw;
 	emu10k1_memblk_t *emem;
 	
-	hw = snd_magic_cast(emu10k1_t, vp->hw, return);
+	hw = vp->hw;
 
 	emem = (emu10k1_memblk_t *)vp->block;
 	if (! emem || emem->mapped_page < 0)
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 9f4c8b359..4f7a0ea60 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -119,8 +119,10 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir)
 	snd_emu10k1_ptr_write(emu, SOLEH, 0, 0);
 
 	if (emu->audigy){
-		snd_emu10k1_ptr_write(emu, 0x5e, 0, 0xf00); /* ?? */
-		snd_emu10k1_ptr_write(emu, 0x5f, 0, 0x3); /* ?? */
+		/* set SPDIF bypass mode */
+		snd_emu10k1_ptr_write(emu, SPBYPASS, 0, SPBYPASS_FORMAT);
+		/* enable rear left + rear right AC97 slots */
+		snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_REAR_RIGHT | AC97SLOT_REAR_LEFT);
 	}
 
 	/* init envelope engine */
@@ -329,7 +331,7 @@ static int snd_emu10k1_done(emu10k1_t * emu)
 	if (emu->audigy)
 		snd_emu10k1_ptr_write(emu, A_DBG, 0, A_DBG_SINGLE_STEP);
 	else
-		snd_emu10k1_ptr_write(emu, DBG, 0, 0x8000);
+		snd_emu10k1_ptr_write(emu, DBG, 0, EMU10K1_DBG_SINGLE_STEP);
 
 	/* disable channel interrupt */
 	snd_emu10k1_ptr_write(emu, CLIEL, 0, 0);
@@ -541,33 +543,31 @@ static int __devinit snd_emu10k1_ecard_init(emu10k1_t * emu)
 
 static int snd_emu10k1_free(emu10k1_t *emu)
 {
-	if (emu->res_port != NULL) {	/* avoid access to already used hardware */
+	if (emu->port) {	/* avoid access to already used hardware */
 	       	snd_emu10k1_fx8010_tram_setup(emu, 0);
 		snd_emu10k1_done(emu);
        	}
 	if (emu->memhdr)
 		snd_util_memhdr_free(emu->memhdr);
 	if (emu->silent_page.area)
-		snd_dma_free_pages(&emu->dma_dev, &emu->silent_page);
+		snd_dma_free_pages(&emu->silent_page);
 	if (emu->ptb_pages.area)
-		snd_dma_free_pages(&emu->dma_dev, &emu->ptb_pages);
+		snd_dma_free_pages(&emu->ptb_pages);
 	if (emu->page_ptr_table)
 		vfree(emu->page_ptr_table);
 	if (emu->page_addr_table)
 		vfree(emu->page_addr_table);
-	if (emu->res_port) {
-		release_resource(emu->res_port);
-		kfree_nocheck(emu->res_port);
-	}
 	if (emu->irq >= 0)
 		free_irq(emu->irq, (void *)emu);
-	snd_magic_kfree(emu);
+	if (emu->port)
+		pci_release_regions(emu->pci);
+	kfree(emu);
 	return 0;
 }
 
 static int snd_emu10k1_dev_free(snd_device_t *device)
 {
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, device->device_data, return -ENXIO);
+	emu10k1_t *emu = device->device_data;
 	return snd_emu10k1_free(emu);
 }
 
@@ -595,7 +595,7 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	emu = snd_magic_kcalloc(emu10k1_t, 0, GFP_KERNEL);
+	emu = kcalloc(1, sizeof(*emu), GFP_KERNEL);
 	if (emu == NULL)
 		return -ENOMEM;
 	/* set the DMA transfer mask */
@@ -603,7 +603,7 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
 	if (pci_set_dma_mask(pci, emu->dma_mask) < 0 ||
 	    pci_set_consistent_dma_mask(pci, emu->dma_mask) < 0) {
 		snd_printk(KERN_ERR "architecture does not support PCI busmaster DMA with mask 0x%lx\n", emu->dma_mask);
-		snd_magic_kfree(emu);
+		kfree(emu);
 		return -ENXIO;
 	}
 	emu->card = card;
@@ -620,7 +620,6 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
 	emu->irq = -1;
 	emu->synth = NULL;
 	emu->get_synth_voice = NULL;
-	emu->port = pci_resource_start(pci, 0);
 
 	emu->audigy = is_audigy;
 	if (is_audigy)
@@ -628,10 +627,11 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
 	else
 		emu->gpr_base = FXGPREGBASE;
 
-	if ((emu->res_port = request_region(emu->port, 0x20, "EMU10K1")) == NULL) {
-		snd_emu10k1_free(emu);
-		return -EBUSY;
+	if ((err = pci_request_regions(pci, "EMU10K1")) < 0) {
+		kfree(emu);
+		return err;
 	}
+	emu->port = pci_resource_start(pci, 0);
 
 	if (request_irq(pci->irq, snd_emu10k1_interrupt, SA_INTERRUPT|SA_SHIRQ, "EMU10K1", (void *)emu)) {
 		snd_emu10k1_free(emu);
@@ -639,12 +639,9 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
 	}
 	emu->irq = pci->irq;
 
-	memset(&emu->dma_dev, 0, sizeof(emu->dma_dev));
-	emu->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	emu->dma_dev.dev = snd_dma_pci_data(pci);
-
 	emu->max_cache_pages = max_cache_bytes >> PAGE_SHIFT;
-	if (snd_dma_alloc_pages(&emu->dma_dev, 32 * 1024, &emu->ptb_pages) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				32 * 1024, &emu->ptb_pages) < 0) {
 		snd_emu10k1_free(emu);
 		return -ENOMEM;
 	}
@@ -656,7 +653,8 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
 		return -ENOMEM;
 	}
 
-	if (snd_dma_alloc_pages(&emu->dma_dev, EMUPAGESIZE, &emu->silent_page) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				EMUPAGESIZE, &emu->silent_page) < 0) {
 		snd_emu10k1_free(emu);
 		return -ENOMEM;
 	}
@@ -682,10 +680,17 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
 		/* Audigy 2 EX has apparently no effective AC97 controls
 		 * (for both input and output), so we skip the AC97 detections
 		 */
-		snd_printdd(KERN_INFO "Audigy2 EX is detected. skpping ac97.\n");
-		emu->no_ac97 = 1;
+		snd_printdd(KERN_INFO "Audigy2 EX is detected. skipping ac97.\n");
+		emu->no_ac97 = 1;	
 	}
 	
+	if (emu->revision == 4 && emu->model == 0x2002) {
+		/* Audigy 2 ZS */
+		snd_printdd(KERN_INFO "Audigy2 ZS is detected. setting 7.1 mode.\n");
+		emu->spk71 = 1;
+	}
+	
+	
 	emu->fx8010.fxbus_mask = 0x303f;
 	if (extin_mask == 0)
 		extin_mask = 0x3fcf;
diff --git a/sound/pci/emu10k1/emu10k1_patch.c b/sound/pci/emu10k1/emu10k1_patch.c
index 14bf206ce..4df668eb3 100644
--- a/sound/pci/emu10k1/emu10k1_patch.c
+++ b/sound/pci/emu10k1/emu10k1_patch.c
@@ -44,7 +44,7 @@ snd_emu10k1_sample_new(snd_emux_t *rec, snd_sf_sample_t *sp,
 	unsigned int start_addr;
 	emu10k1_t *emu;
 
-	emu = snd_magic_cast(emu10k1_t, rec->hw, return -ENXIO);
+	emu = rec->hw;
 	snd_assert(sp != NULL, return -EINVAL);
 	snd_assert(hdr != NULL, return -EINVAL);
 
@@ -210,7 +210,7 @@ snd_emu10k1_sample_free(snd_emux_t *rec, snd_sf_sample_t *sp,
 {
 	emu10k1_t *emu;
 
-	emu = snd_magic_cast(emu10k1_t, rec->hw, return -ENXIO);
+	emu = rec->hw;
 	snd_assert(sp != NULL, return -EINVAL);
 	snd_assert(hdr != NULL, return -EINVAL);
 
diff --git a/sound/pci/emu10k1/emu10k1_synth.c b/sound/pci/emu10k1/emu10k1_synth.c
index 9e562ae25..2af8ffa6b 100644
--- a/sound/pci/emu10k1/emu10k1_synth.c
+++ b/sound/pci/emu10k1/emu10k1_synth.c
@@ -85,9 +85,9 @@ int snd_emu10k1_synth_delete_device(snd_seq_device_t *dev)
 	if (dev->driver_data == NULL)
 		return 0; /* not registered actually */
 
-	emu = snd_magic_cast(snd_emux_t, dev->driver_data, return -EINVAL);
+	emu = dev->driver_data;
 
-	hw = snd_magic_cast(emu10k1_t, emu->hw, return -EINVAL);
+	hw = emu->hw;
 	spin_lock_irqsave(&hw->voice_lock, flags);
 	hw->synth = NULL;
 	hw->get_synth_voice = NULL;
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index c4f763000..6290ed577 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -33,8 +33,6 @@
 #include <sound/core.h>
 #include <sound/emu10k1.h>
 
-#define chip_t emu10k1_t
-
 #if 0		/* for testing purposes - digital out -> capture */
 #define EMU10K1_CAPTURE_DIGITAL_OUT
 #endif
@@ -405,7 +403,7 @@ static void snd_emu10k1_fx8010_interrupt(emu10k1_t *emu)
 	}
 }
 
-static int snd_emu10k1_fx8010_register_irq_handler(emu10k1_t *emu,
+int snd_emu10k1_fx8010_register_irq_handler(emu10k1_t *emu,
 						   snd_fx8010_irq_handler_t *handler,
 						   unsigned char gpr_running,
 						   void *private_data,
@@ -438,7 +436,7 @@ static int snd_emu10k1_fx8010_register_irq_handler(emu10k1_t *emu,
 	return 0;
 }
 
-static int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
+int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
 						     snd_emu10k1_fx8010_irq_t *irq)
 {
 	snd_emu10k1_fx8010_irq_t *tmp;
@@ -463,312 +461,6 @@ static int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
 	return 0;
 }
 
-/*
- *   PCM streams
- */
-
-#define INITIAL_TRAM_SHIFT     14
-#define INITIAL_TRAM_POS(size) ((((size) / 2) - INITIAL_TRAM_SHIFT) - 1)
-
-static void snd_emu10k1_fx8010_playback_irq(emu10k1_t *emu, void *private_data)
-{
-	snd_pcm_substream_t *substream = snd_magic_cast(snd_pcm_substream_t, private_data, return);
-	snd_pcm_period_elapsed(substream);
-}
-
-static void snd_emu10k1_fx8010_playback_tram_poke1(unsigned short *dst_left,
-						   unsigned short *dst_right,
-						   unsigned short *src,
-						   unsigned int count,
-						   unsigned int tram_shift)
-{
-	// printk("tram_poke1: dst_left = 0x%p, dst_right = 0x%p, src = 0x%p, count = 0x%x\n", dst_left, dst_right, src, count);
-	if ((tram_shift & 1) == 0) {
-		while (count--) {
-			*dst_left-- = *src++;
-			*dst_right-- = *src++;
-		}
-	} else {
-		while (count--) {
-			*dst_right-- = *src++;
-			*dst_left-- = *src++;
-		}
-	}
-}
-
-static void snd_emu10k1_fx8010_playback_tram_poke(emu10k1_t *emu,
-						  unsigned int *tram_pos,
-						  unsigned int *tram_shift,
-						  unsigned int tram_size,
-						  unsigned short *src,
-						  unsigned int frames)
-{
-	unsigned int count;
-
-	while (frames > *tram_pos) {
-		count = *tram_pos + 1;
-		snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + *tram_pos,
-						       (unsigned short *)emu->fx8010.etram_pages.area + *tram_pos + tram_size / 2,
-						       src, count, *tram_shift);
-		src += count * 2;
-		frames -= count;
-		*tram_pos = (tram_size / 2) - 1;
-		(*tram_shift)++;
-	}
-	snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + *tram_pos,
-					       (unsigned short *)emu->fx8010.etram_pages.area + *tram_pos + tram_size / 2,
-					       src, frames, *tram_shift++);
-	*tram_pos -= frames;
-}
-
-static int snd_emu10k1_fx8010_playback_transfer(snd_pcm_substream_t *substream)
-{
-	emu10k1_t *emu = snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
-	snd_pcm_uframes_t appl_ptr = runtime->control->appl_ptr;
-	snd_pcm_sframes_t diff = appl_ptr - pcm->appl_ptr;
-	snd_pcm_uframes_t buffer_size = pcm->buffer_size / 2;
-
-	if (diff) {
-		if (diff < -(snd_pcm_sframes_t) (runtime->boundary / 2))
-			diff += runtime->boundary;
-		pcm->sw_ready += diff;
-		pcm->appl_ptr = appl_ptr;
-	}
-	while (pcm->hw_ready < buffer_size &&
-	       pcm->sw_ready > 0) {
-	       	size_t hw_to_end = buffer_size - pcm->hw_data;
-	       	size_t sw_to_end = (runtime->buffer_size << 2) - pcm->sw_data;
-	       	size_t tframes = buffer_size - pcm->hw_ready;
-	       	if (pcm->sw_ready < tframes)
-	       		tframes = pcm->sw_ready;
-	       	if (hw_to_end < tframes)
-	       		tframes = hw_to_end;
-	       	if (sw_to_end < tframes)
-	       		tframes = sw_to_end;
-	       	snd_emu10k1_fx8010_playback_tram_poke(emu, &pcm->tram_pos, &pcm->tram_shift,
-	       					      pcm->buffer_size,
-	       					      (unsigned short *)(runtime->dma_area + (pcm->sw_data << 2)),
-	       					      tframes);
-		pcm->hw_data += tframes;
-		if (pcm->hw_data == buffer_size)
-			pcm->hw_data = 0;
-		pcm->sw_data += tframes;
-		if (pcm->sw_data == runtime->buffer_size)
-			pcm->sw_data = 0;
-		pcm->hw_ready += tframes;
-		pcm->sw_ready -= tframes;
-	}
-	return 0;
-}
-
-static int snd_emu10k1_fx8010_playback_hw_params(snd_pcm_substream_t * substream,
-						 snd_pcm_hw_params_t * hw_params)
-{
-	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-static int snd_emu10k1_fx8010_playback_hw_free(snd_pcm_substream_t * substream)
-{
-	emu10k1_t *emu = snd_pcm_substream_chip(substream);
-	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
-	unsigned int i;
-
-	for (i = 0; i < pcm->channels; i++)
-		snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, 0);
-	snd_pcm_lib_free_pages(substream);
-	return 0;
-}
-
-static int snd_emu10k1_fx8010_playback_prepare(snd_pcm_substream_t * substream)
-{
-	emu10k1_t *emu = snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
-	unsigned int i;
-	
-	// printk("prepare: etram_pages = 0x%p, dma_area = 0x%x, buffer_size = 0x%x (0x%x)\n", emu->fx8010.etram_pages, runtime->dma_area, runtime->buffer_size, runtime->buffer_size << 2);
-	pcm->sw_data = pcm->sw_io = pcm->sw_ready = 0;
-	pcm->hw_data = pcm->hw_io = pcm->hw_ready = 0;
-	pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size);
-	pcm->tram_shift = 0;
-	pcm->appl_ptr = 0;
-	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_running, 0, 0);	/* reset */
-	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0);	/* reset */
-	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_size, 0, runtime->buffer_size);
-	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_ptr, 0, 0);		/* reset ptr number */
-	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_count, 0, runtime->period_size);
-	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_tmpcount, 0, runtime->period_size);
-	for (i = 0; i < pcm->channels; i++)
-		snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, (TANKMEMADDRREG_READ|TANKMEMADDRREG_ALIGN) + i * (runtime->buffer_size / pcm->channels));
-	return 0;
-}
-
-static int snd_emu10k1_fx8010_playback_trigger(snd_pcm_substream_t * substream, int cmd)
-{
-	emu10k1_t *emu = snd_pcm_substream_chip(substream);
-	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
-	unsigned long flags;
-	int result = 0;
-
-	spin_lock_irqsave(&emu->reg_lock, flags);
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		/* follow thru */
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-#ifdef EMU10K1_SET_AC3_IEC958
-	{
-		int i;
-		for (i = 0; i < 3; i++) {
-			unsigned int bits;
-			bits = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
-			       SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS |
-			       0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT | SPCS_NOTAUDIODATA;
-			snd_emu10k1_ptr_write(emu, SPCS0 + i, 0, bits);
-		}
-	}
-#endif
-		result = snd_emu10k1_fx8010_register_irq_handler(emu, snd_emu10k1_fx8010_playback_irq, pcm->gpr_running, substream, &pcm->irq);
-		if (result < 0)
-			goto __err;
-		snd_emu10k1_fx8010_playback_transfer(substream);	/* roll the ball */
-		snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 1);
-		break;
-	case SNDRV_PCM_TRIGGER_STOP:
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		snd_emu10k1_fx8010_unregister_irq_handler(emu, pcm->irq); pcm->irq = NULL;
-		snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0);
-		pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size);
-		pcm->tram_shift = 0;
-		break;
-	default:
-		result = -EINVAL;
-		break;
-	}
-      __err:
-	spin_unlock_irqrestore(&emu->reg_lock, flags);
-	return result;
-}
-
-static snd_pcm_uframes_t snd_emu10k1_fx8010_playback_pointer(snd_pcm_substream_t * substream)
-{
-	emu10k1_t *emu = snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
-	size_t ptr;
-	snd_pcm_sframes_t frames;
-
-	if (!snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_trigger, 0))
-		return 0;
-	ptr = snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_ptr, 0);
-	frames = ptr - pcm->hw_io;
-	if (frames < 0)
-		frames += runtime->buffer_size;
-	pcm->hw_io = ptr;
-	pcm->hw_ready -= frames;
-	pcm->sw_io += frames;
-	if (pcm->sw_io >= runtime->buffer_size)
-		pcm->sw_io -= runtime->buffer_size;
-	snd_emu10k1_fx8010_playback_transfer(substream);
-	return pcm->sw_io;
-}
-
-static snd_pcm_hardware_t snd_emu10k1_fx8010_playback =
-{
-	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
-				 /* SNDRV_PCM_INFO_MMAP_VALID | */ SNDRV_PCM_INFO_PAUSE),
-	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
-	.rates =		SNDRV_PCM_RATE_48000,
-	.rate_min =		48000,
-	.rate_max =		48000,
-	.channels_min =		1,
-	.channels_max =		1,
-	.buffer_bytes_max =	(128*1024),
-	.period_bytes_min =	1024,
-	.period_bytes_max =	(128*1024),
-	.periods_min =		1,
-	.periods_max =		1024,
-	.fifo_size =		0,
-};
-
-static int snd_emu10k1_fx8010_playback_open(snd_pcm_substream_t * substream)
-{
-	emu10k1_t *emu = snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
-
-	runtime->hw = snd_emu10k1_fx8010_playback;
-	runtime->hw.channels_min = runtime->hw.channels_max = pcm->channels;
-	runtime->hw.period_bytes_max = (pcm->buffer_size * 2) / 2;
-	spin_lock(&emu->reg_lock);
-	if (pcm->valid == 0) {
-		spin_unlock(&emu->reg_lock);
-		return -ENODEV;
-	}
-	pcm->opened = 1;
-	spin_unlock(&emu->reg_lock);
-	return 0;
-}
-
-static int snd_emu10k1_fx8010_playback_close(snd_pcm_substream_t * substream)
-{
-	emu10k1_t *emu = snd_pcm_substream_chip(substream);
-	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
-
-	spin_lock(&emu->reg_lock);
-	pcm->opened = 0;
-	spin_unlock(&emu->reg_lock);
-	return 0;
-}
-
-static snd_pcm_ops_t snd_emu10k1_fx8010_playback_ops = {
-	.open =			snd_emu10k1_fx8010_playback_open,
-	.close =		snd_emu10k1_fx8010_playback_close,
-	.ioctl =		snd_pcm_lib_ioctl,
-	.hw_params =		snd_emu10k1_fx8010_playback_hw_params,
-	.hw_free =		snd_emu10k1_fx8010_playback_hw_free,
-	.prepare =		snd_emu10k1_fx8010_playback_prepare,
-	.trigger =		snd_emu10k1_fx8010_playback_trigger,
-	.pointer =		snd_emu10k1_fx8010_playback_pointer,
-	.ack =			snd_emu10k1_fx8010_playback_transfer,
-};
-
-static void snd_emu10k1_fx8010_pcm_free(snd_pcm_t *pcm)
-{
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return);
-	emu->pcm_fx8010 = NULL;
-	snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
-int snd_emu10k1_fx8010_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm)
-{
-	snd_pcm_t *pcm;
-	int err;
-
-	if (rpcm)
-		*rpcm = NULL;
-
-	if ((err = snd_pcm_new(emu->card, "emu10k1", device, 8, 0, &pcm)) < 0)
-		return err;
-
-	pcm->private_data = emu;
-	pcm->private_free = snd_emu10k1_fx8010_pcm_free;
-
-	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_fx8010_playback_ops);
-
-	pcm->info_flags = 0;
-	strcpy(pcm->name, "EMU10K1 FX8010");
-	emu->pcm_fx8010 = pcm;
-	
-	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 0);
-
-	if (rpcm)
-		*rpcm = pcm;
-
-	return 0;
-}
-
 /*************************************************************************
  * EMU10K1 effect manager
  *************************************************************************/
@@ -1193,7 +885,7 @@ static int snd_emu10k1_ipcm_peek(emu10k1_t *emu, emu10k1_fx8010_pcm_t *ipcm)
 
 #define SND_EMU10K1_GPR_CONTROLS	41
 #define SND_EMU10K1_INPUTS		10
-#define SND_EMU10K1_PLAYBACK_CHANNELS	6
+#define SND_EMU10K1_PLAYBACK_CHANNELS	8
 #define SND_EMU10K1_CAPTURE_CHANNELS	4
 
 static void __devinit snd_emu10k1_init_mono_control(emu10k1_fx8010_control_gpr_t *ctl, const char *name, int gpr, int defval)
@@ -1262,9 +954,9 @@ static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
 	spin_lock_init(&emu->fx8010.irq_lock);
 	INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
 
-	if ((icode = snd_kcalloc(sizeof(emu10k1_fx8010_code_t), GFP_KERNEL)) == NULL)
+	if ((icode = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
-	if ((controls = snd_kcalloc(sizeof(emu10k1_fx8010_control_gpr_t) * SND_EMU10K1_GPR_CONTROLS, GFP_KERNEL)) == NULL) {
+	if ((controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(*controls), GFP_KERNEL)) == NULL) {
 		kfree(icode);
 		return -ENOMEM;
 	}
@@ -1292,6 +984,14 @@ static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
 	A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_REAR));
 	snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Surround Playback Volume", gpr, 100);
 	gpr += 2;
+	
+	/* PCM Side Playback (independent from stereo mix) */
+	if (emu->spk71) {
+		A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_SIDE));
+		A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_SIDE));
+		snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Side Playback Volume", gpr, 100);
+		gpr += 2;
+	}
 
 	/* PCM Center Playback (independent from stereo mix) */
 	A_OP(icode, &ptr, iMAC0, A_GPR(playback+4), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_CENTER));
@@ -1440,6 +1140,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
 	A_OP(icode, &ptr, iMAC0, A_GPR(playback+5), A_GPR(playback+5), A_GPR(gpr), A_GPR(tmp));
 	snd_emu10k1_init_mono_control(&controls[nctl++], "LFE Playback Volume", gpr, 0);
 	gpr++;
+	
+	if (emu->spk71) {
+		/* Stereo Mix Side Playback */
+		A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_GPR(playback+6), A_GPR(gpr), A_GPR(stereo_mix));
+		A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_GPR(playback+7), A_GPR(gpr+1), A_GPR(stereo_mix+1));
+		snd_emu10k1_init_stereo_control(&controls[nctl++], "Side Playback Volume", gpr, 0);
+		gpr += 2;
+	}
 
 	/*
 	 * outputs
@@ -1467,6 +1175,11 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
 	A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 3), A_GPR(playback + 3), A_C_00000000, A_C_00000000); /* rear right */
 	A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), A_GPR(playback + 4), A_C_00000000, A_C_00000000); /* center */
 	A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), A_GPR(playback + 5), A_C_00000000, A_C_00000000); /* LFE */
+	if (emu->spk71) {
+		A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 6), A_GPR(playback + 6), A_C_00000000, A_C_00000000); /* side left */
+		A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 7), A_GPR(playback + 7), A_C_00000000, A_C_00000000); /* side right */
+	}
+	
 
 	ctl = &controls[nctl + 0];
 	ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
@@ -1497,7 +1210,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
 			controls[nctl + 1].gpr[z * 2 + j] = TREBLE_GPR + z * 2 + j;
 		}
 	}
-	for (z = 0; z < 3; z++) {		/* front/rear/center-lfe */
+	for (z = 0; z < 4; z++) {		/* front/rear/center-lfe/side */
 		int j, k, l, d;
 		for (j = 0; j < 2; j++) {	/* left/right */
 			k = 0xb0 + (z * 8) + (j * 4);
@@ -1529,7 +1242,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
 #undef BASS_GPR
 #undef TREBLE_GPR
 
-	for (z = 0; z < 6; z++) {
+	for (z = 0; z < 8; z++) {
 		A_SWITCH(icode, &ptr, tmp + 0, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, gpr + 0);
 		A_SWITCH_NEG(icode, &ptr, tmp + 1, gpr + 0);
 		A_SWITCH(icode, &ptr, tmp + 1, playback + z, tmp + 1);
@@ -1540,12 +1253,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
 
 	/* Master volume (will be renamed later) */
 	A_OP(icode, &ptr, iMAC0, A_GPR(playback+0+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+0+SND_EMU10K1_PLAYBACK_CHANNELS));
-	A_OP(icode, &ptr, iMAC0, A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr+1), A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS));
-	A_OP(icode, &ptr, iMAC0, A_GPR(playback+2+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr+1), A_GPR(playback+2+SND_EMU10K1_PLAYBACK_CHANNELS));
-	A_OP(icode, &ptr, iMAC0, A_GPR(playback+3+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr+1), A_GPR(playback+3+SND_EMU10K1_PLAYBACK_CHANNELS));
-	A_OP(icode, &ptr, iMAC0, A_GPR(playback+4+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr+1), A_GPR(playback+4+SND_EMU10K1_PLAYBACK_CHANNELS));
-	A_OP(icode, &ptr, iMAC0, A_GPR(playback+5+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr+1), A_GPR(playback+5+SND_EMU10K1_PLAYBACK_CHANNELS));
-	snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Master Playback Volume", gpr, 0);
+	A_OP(icode, &ptr, iMAC0, A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS));
+	A_OP(icode, &ptr, iMAC0, A_GPR(playback+2+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+2+SND_EMU10K1_PLAYBACK_CHANNELS));
+	A_OP(icode, &ptr, iMAC0, A_GPR(playback+3+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+3+SND_EMU10K1_PLAYBACK_CHANNELS));
+	A_OP(icode, &ptr, iMAC0, A_GPR(playback+4+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+4+SND_EMU10K1_PLAYBACK_CHANNELS));
+	A_OP(icode, &ptr, iMAC0, A_GPR(playback+5+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+5+SND_EMU10K1_PLAYBACK_CHANNELS));
+	A_OP(icode, &ptr, iMAC0, A_GPR(playback+6+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+6+SND_EMU10K1_PLAYBACK_CHANNELS));
+	A_OP(icode, &ptr, iMAC0, A_GPR(playback+7+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+7+SND_EMU10K1_PLAYBACK_CHANNELS));
+	snd_emu10k1_init_mono_control(&controls[nctl++], "Wave Master Playback Volume", gpr, 0);
 	gpr += 2;
 
 	/* analog speakers */
@@ -1553,6 +1268,8 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
 	A_PUT_STEREO_OUTPUT(A_EXTOUT_AREAR_L, A_EXTOUT_AREAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS);
 	A_PUT_OUTPUT(A_EXTOUT_ACENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS);
 	A_PUT_OUTPUT(A_EXTOUT_ALFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS);
+	if (emu->spk71)
+		A_PUT_STEREO_OUTPUT(A_EXTOUT_ASIDE_L, A_EXTOUT_ASIDE_R, playback+6 + SND_EMU10K1_PLAYBACK_CHANNELS);
 
 	/* headphone */
 	A_PUT_STEREO_OUTPUT(A_EXTOUT_HEADPHONE_L, A_EXTOUT_HEADPHONE_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
@@ -1674,13 +1391,13 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
 	spin_lock_init(&emu->fx8010.irq_lock);
 	INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
 
-	if ((icode = snd_kcalloc(sizeof(emu10k1_fx8010_code_t), GFP_KERNEL)) == NULL)
+	if ((icode = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
-	if ((controls = snd_kcalloc(sizeof(emu10k1_fx8010_control_gpr_t) * SND_EMU10K1_GPR_CONTROLS, GFP_KERNEL)) == NULL) {
+	if ((controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(emu10k1_fx8010_control_gpr_t), GFP_KERNEL)) == NULL) {
 		kfree(icode);
 		return -ENOMEM;
 	}
-	if ((ipcm = snd_kcalloc(sizeof(emu10k1_fx8010_pcm_t), GFP_KERNEL)) == NULL) {
+	if ((ipcm = kcalloc(1, sizeof(*ipcm), GFP_KERNEL)) == NULL) {
 		kfree(controls);
 		kfree(icode);
 		return -ENOMEM;
@@ -2236,13 +1953,14 @@ int snd_emu10k1_fx8010_tram_setup(emu10k1_t *emu, u32 size)
 	snd_emu10k1_ptr_write(emu, TCB, 0, 0);
 	snd_emu10k1_ptr_write(emu, TCBS, 0, 0);
 	if (emu->fx8010.etram_pages.area != NULL) {
-		snd_dma_free_pages(&emu->dma_dev, &emu->fx8010.etram_pages);
+		snd_dma_free_pages(&emu->fx8010.etram_pages);
 		emu->fx8010.etram_pages.area = NULL;
 		emu->fx8010.etram_pages.bytes = 0;
 	}
 
 	if (size > 0) {
-		if (snd_dma_alloc_pages(&emu->dma_dev, size * 2, &emu->fx8010.etram_pages) < 0)
+		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci),
+					size * 2, &emu->fx8010.etram_pages) < 0)
 			return -ENOMEM;
 		memset(emu->fx8010.etram_pages.area, 0, size * 2);
 		snd_emu10k1_ptr_write(emu, TCB, 0, emu->fx8010.etram_pages.addr);
@@ -2297,7 +2015,7 @@ static int snd_emu10k1_fx8010_info(emu10k1_t *emu, emu10k1_fx8010_info_t *info)
 
 static int snd_emu10k1_fx8010_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cmd, unsigned long arg)
 {
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, hw->private_data, return -ENXIO);
+	emu10k1_t *emu = hw->private_data;
 	emu10k1_fx8010_info_t *info;
 	emu10k1_fx8010_code_t *icode;
 	emu10k1_fx8010_pcm_t *ipcm;
@@ -2364,7 +2082,7 @@ static int snd_emu10k1_fx8010_ioctl(snd_hwdep_t * hw, struct file *file, unsigne
 	case SNDRV_EMU10K1_IOCTL_PCM_PEEK:
 		if (emu->audigy)
 			return -EINVAL;
-		ipcm = (emu10k1_fx8010_pcm_t *)snd_kcalloc(sizeof(*ipcm), GFP_KERNEL);
+		ipcm = kcalloc(1, sizeof(*ipcm), GFP_KERNEL);
 		if (ipcm == NULL)
 			return -ENOMEM;
 		if (copy_from_user(ipcm, argp, sizeof(*ipcm))) {
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
index 45692f56a..f73ac0ef6 100644
--- a/sound/pci/emu10k1/emumixer.c
+++ b/sound/pci/emu10k1/emumixer.c
@@ -32,8 +32,6 @@
 #include <sound/core.h>
 #include <sound/emu10k1.h>
 
-#define chip_t emu10k1_t
-
 #define AC97_ID_STAC9758	0x83847658
 
 static int snd_emu10k1_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
@@ -421,7 +419,7 @@ static snd_kcontrol_new_t snd_audigy_shared_spdif __devinitdata =
  */
 static void snd_emu10k1_mixer_free_ac97(ac97_t *ac97)
 {
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, ac97->private_data, return);
+	emu10k1_t *emu = ac97->private_data;
 	emu->ac97 = NULL;
 }
 
@@ -512,13 +510,14 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
 	};
 
 	if (!emu->no_ac97) {
-		ac97_bus_t bus, *pbus;
-		ac97_t ac97;
-
-		memset(&bus, 0, sizeof(bus));
-		bus.write = snd_emu10k1_ac97_write;
-		bus.read = snd_emu10k1_ac97_read;
-		if ((err = snd_ac97_bus(emu->card, &bus, &pbus)) < 0)
+		ac97_bus_t *pbus;
+		ac97_template_t ac97;
+		static ac97_bus_ops_t ops = {
+			.write = snd_emu10k1_ac97_write,
+			.read = snd_emu10k1_ac97_read,
+		};
+
+		if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0)
 			return err;
 		
 		memset(&ac97, 0, sizeof(ac97));
@@ -528,7 +527,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
 			return err;
 		if (emu->audigy) {
 			/* set master volume to 0 dB */
-			snd_ac97_write(emu->ac97, AC97_MASTER, 0x0202);
+			snd_ac97_write(emu->ac97, AC97_MASTER, 0x0000);
 			/* set capture source to mic */
 			snd_ac97_write(emu->ac97, AC97_REC_SEL, 0x0000);
 			c = audigy_remove_ctls;
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index 39d7e3255..9fbbf6ce4 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -34,8 +34,6 @@
 #include <sound/core.h>
 #include <sound/emu10k1.h>
 
-#define chip_t emu10k1_t
-
 static void snd_emu10k1_pcm_interrupt(emu10k1_t *emu, emu10k1_voice_t *voice)
 {
 	emu10k1_pcm_t *epcm;
@@ -354,7 +352,7 @@ static int snd_emu10k1_playback_hw_params(snd_pcm_substream_t * substream,
 {
 	emu10k1_t *emu = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+	emu10k1_pcm_t *epcm = runtime->private_data;
 	int err;
 
 	if ((err = snd_emu10k1_pcm_channel_alloc(epcm, params_channels(hw_params))) < 0)
@@ -383,7 +381,7 @@ static int snd_emu10k1_playback_hw_free(snd_pcm_substream_t * substream)
 
 	if (runtime->private_data == NULL)
 		return 0;
-	epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+	epcm = runtime->private_data;
 	if (epcm->extra) {
 		snd_emu10k1_voice_free(epcm->emu, epcm->extra);
 		epcm->extra = NULL;
@@ -409,7 +407,7 @@ static int snd_emu10k1_playback_prepare(snd_pcm_substream_t * substream)
 {
 	emu10k1_t *emu = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+	emu10k1_pcm_t *epcm = runtime->private_data;
 	unsigned int start_addr, end_addr;
 
 	start_addr = epcm->start_addr;
@@ -443,7 +441,7 @@ static int snd_emu10k1_capture_prepare(snd_pcm_substream_t * substream)
 {
 	emu10k1_t *emu = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+	emu10k1_pcm_t *epcm = runtime->private_data;
 	int idx;
 
 	snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, 0);
@@ -452,7 +450,11 @@ static int snd_emu10k1_capture_prepare(snd_pcm_substream_t * substream)
 		snd_emu10k1_ptr_write(emu, ADCCR, 0, 0);
 		break;
 	case CAPTURE_EFX:
-		snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
+		if (emu->audigy) {
+			snd_emu10k1_ptr_write(emu, A_FXWC1, 0, 0);
+			snd_emu10k1_ptr_write(emu, A_FXWC2, 0, 0);
+		} else
+			snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
 		break;
 	default:
 		break;
@@ -565,12 +567,11 @@ static int snd_emu10k1_playback_trigger(snd_pcm_substream_t * substream,
 {
 	emu10k1_t *emu = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
-	unsigned long flags;
+	emu10k1_pcm_t *epcm = runtime->private_data;
 	int result = 0;
 
 	// printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream));
-	spin_lock_irqsave(&emu->reg_lock, flags);
+	spin_lock(&emu->reg_lock);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 		snd_emu10k1_playback_invalidate_cache(emu, epcm->extra);	/* do we need this? */
@@ -593,7 +594,7 @@ static int snd_emu10k1_playback_trigger(snd_pcm_substream_t * substream,
 		result = -EINVAL;
 		break;
 	}
-	spin_unlock_irqrestore(&emu->reg_lock, flags);
+	spin_unlock(&emu->reg_lock);
 	return result;
 }
 
@@ -602,12 +603,11 @@ static int snd_emu10k1_capture_trigger(snd_pcm_substream_t * substream,
 {
 	emu10k1_t *emu = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
-	unsigned long flags;
+	emu10k1_pcm_t *epcm = runtime->private_data;
 	int result = 0;
 
 	// printk("trigger - emu10k1 = %p, cmd = %i, pointer = %i\n", emu, cmd, substream->ops->pointer(substream));
-	spin_lock_irqsave(&emu->reg_lock, flags);
+	spin_lock(&emu->reg_lock);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 		outl(epcm->capture_ipr, emu->port + IPR);
@@ -618,7 +618,11 @@ static int snd_emu10k1_capture_trigger(snd_pcm_substream_t * substream,
 			snd_emu10k1_ptr_write(emu, ADCCR, 0, epcm->capture_cr_val);
 			break;
 		case CAPTURE_EFX:
-			snd_emu10k1_ptr_write(emu, FXWC, 0, epcm->capture_cr_val);
+			if (emu->audigy) {
+				snd_emu10k1_ptr_write(emu, A_FXWC1, 0, epcm->capture_cr_val);
+				snd_emu10k1_ptr_write(emu, A_FXWC2, 0, epcm->capture_cr_val2);
+			} else
+				snd_emu10k1_ptr_write(emu, FXWC, 0, epcm->capture_cr_val);
 			break;
 		default:	
 			break;
@@ -637,7 +641,11 @@ static int snd_emu10k1_capture_trigger(snd_pcm_substream_t * substream,
 			snd_emu10k1_ptr_write(emu, ADCCR, 0, 0);
 			break;
 		case CAPTURE_EFX:
-			snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
+			if (emu->audigy) {
+				snd_emu10k1_ptr_write(emu, A_FXWC1, 0, 0);
+				snd_emu10k1_ptr_write(emu, A_FXWC2, 0, 0);
+			} else
+				snd_emu10k1_ptr_write(emu, FXWC, 0, 0);
 			break;
 		default:
 			break;
@@ -646,7 +654,7 @@ static int snd_emu10k1_capture_trigger(snd_pcm_substream_t * substream,
 	default:
 		result = -EINVAL;
 	}
-	spin_unlock_irqrestore(&emu->reg_lock, flags);
+	spin_unlock(&emu->reg_lock);
 	return result;
 }
 
@@ -654,7 +662,7 @@ static snd_pcm_uframes_t snd_emu10k1_playback_pointer(snd_pcm_substream_t * subs
 {
 	emu10k1_t *emu = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+	emu10k1_pcm_t *epcm = runtime->private_data;
 	unsigned int ptr;
 
 	if (!epcm->running)
@@ -681,7 +689,7 @@ static snd_pcm_uframes_t snd_emu10k1_capture_pointer(snd_pcm_substream_t * subst
 {
 	emu10k1_t *emu = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return -ENXIO);
+	emu10k1_pcm_t *epcm = runtime->private_data;
 	unsigned int ptr;
 
 	if (!epcm->running)
@@ -767,10 +775,10 @@ static void snd_emu10k1_pcm_mixer_notify(emu10k1_t *emu, int idx, int activate)
 
 static void snd_emu10k1_pcm_free_substream(snd_pcm_runtime_t *runtime)
 {
-	emu10k1_pcm_t *epcm = snd_magic_cast(emu10k1_pcm_t, runtime->private_data, return);
+	emu10k1_pcm_t *epcm = runtime->private_data;
 
 	if (epcm)
-		snd_magic_kfree(epcm);
+		kfree(epcm);
 }
 
 static int snd_emu10k1_playback_open(snd_pcm_substream_t * substream)
@@ -781,7 +789,7 @@ static int snd_emu10k1_playback_open(snd_pcm_substream_t * substream)
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int i, err;
 
-	epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL);
+	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
 	if (epcm == NULL)
 		return -ENOMEM;
 	epcm->emu = emu;
@@ -791,11 +799,11 @@ static int snd_emu10k1_playback_open(snd_pcm_substream_t * substream)
 	runtime->private_free = snd_emu10k1_pcm_free_substream;
 	runtime->hw = snd_emu10k1_playback;
 	if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) {
-		snd_magic_kfree(epcm);
+		kfree(epcm);
 		return err;
 	}
 	if ((err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX)) < 0) {
-		snd_magic_kfree(epcm);
+		kfree(epcm);
 		return err;
 	}
 	mix = &emu->pcm_mixer[substream->number];
@@ -826,7 +834,7 @@ static int snd_emu10k1_capture_open(snd_pcm_substream_t * substream)
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	emu10k1_pcm_t *epcm;
 
-	epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL);
+	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
 	if (epcm == NULL)
 		return -ENOMEM;
 	epcm->emu = emu;
@@ -842,7 +850,7 @@ static int snd_emu10k1_capture_open(snd_pcm_substream_t * substream)
 	runtime->hw = snd_emu10k1_capture;
 	emu->capture_interrupt = snd_emu10k1_pcm_ac97adc_interrupt;
 	emu->pcm_capture_substream = substream;
-	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
+	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes);
 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_capture_rates);
 	return 0;
 }
@@ -862,7 +870,7 @@ static int snd_emu10k1_capture_mic_open(snd_pcm_substream_t * substream)
 	emu10k1_pcm_t *epcm;
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
-	epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL);
+	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
 	if (epcm == NULL)
 		return -ENOMEM;
 	epcm->emu = emu;
@@ -881,7 +889,7 @@ static int snd_emu10k1_capture_mic_open(snd_pcm_substream_t * substream)
 	runtime->hw.channels_min = 1;
 	emu->capture_mic_interrupt = snd_emu10k1_pcm_ac97mic_interrupt;
 	emu->pcm_capture_mic_substream = substream;
-	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
+	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes);
 	return 0;
 }
 
@@ -899,11 +907,10 @@ static int snd_emu10k1_capture_efx_open(snd_pcm_substream_t * substream)
 	emu10k1_t *emu = snd_pcm_substream_chip(substream);
 	emu10k1_pcm_t *epcm;
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	unsigned long flags;
 	int nefx = emu->audigy ? 64 : 32;
 	int idx;
 
-	epcm = snd_magic_kcalloc(emu10k1_pcm_t, 0, GFP_KERNEL);
+	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
 	if (epcm == NULL)
 		return -ENOMEM;
 	epcm->emu = emu;
@@ -919,7 +926,7 @@ static int snd_emu10k1_capture_efx_open(snd_pcm_substream_t * substream)
 	runtime->hw = snd_emu10k1_capture;
 	runtime->hw.rates = SNDRV_PCM_RATE_48000;
 	runtime->hw.rate_min = runtime->hw.rate_max = 48000;
-	spin_lock_irqsave(&emu->reg_lock, flags);
+	spin_lock_irq(&emu->reg_lock);
 	runtime->hw.channels_min = runtime->hw.channels_max = 0;
 	for (idx = 0; idx < nefx; idx++) {
 		if (emu->efx_voices_mask[idx/32] & (1 << (idx%32))) {
@@ -929,10 +936,10 @@ static int snd_emu10k1_capture_efx_open(snd_pcm_substream_t * substream)
 	}
 	epcm->capture_cr_val = emu->efx_voices_mask[0];
 	epcm->capture_cr_val2 = emu->efx_voices_mask[1];
-	spin_unlock_irqrestore(&emu->reg_lock, flags);
+	spin_unlock_irq(&emu->reg_lock);
 	emu->capture_efx_interrupt = snd_emu10k1_pcm_efx_interrupt;
 	emu->pcm_capture_efx_substream = substream;
-	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_capture_period_sizes);
+	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_capture_period_sizes);
 	return 0;
 }
 
@@ -970,7 +977,7 @@ static snd_pcm_ops_t snd_emu10k1_capture_ops = {
 
 static void snd_emu10k1_pcm_free(snd_pcm_t *pcm)
 {
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return);
+	emu10k1_t *emu = pcm->private_data;
 	emu->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1024,7 +1031,7 @@ static snd_pcm_ops_t snd_emu10k1_capture_mic_ops = {
 
 static void snd_emu10k1_pcm_mic_free(snd_pcm_t *pcm)
 {
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return);
+	emu10k1_t *emu = pcm->private_data;
 	emu->pcm_mic = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1070,21 +1077,19 @@ static int snd_emu10k1_pcm_efx_voices_mask_info(snd_kcontrol_t *kcontrol, snd_ct
 static int snd_emu10k1_pcm_efx_voices_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int nefx = emu->audigy ? 64 : 32;
 	int idx;
 	
-	spin_lock_irqsave(&emu->reg_lock, flags);
+	spin_lock_irq(&emu->reg_lock);
 	for (idx = 0; idx < nefx; idx++)
 		ucontrol->value.integer.value[idx] = (emu->efx_voices_mask[idx / 32] & (1 << (idx % 32))) ? 1 : 0;
-	spin_unlock_irqrestore(&emu->reg_lock, flags);
+	spin_unlock_irq(&emu->reg_lock);
 	return 0;
 }
 
 static int snd_emu10k1_pcm_efx_voices_mask_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned int nval[2], bits;
 	int nefx = emu->audigy ? 64 : 32;
 	int change, idx;
@@ -1097,12 +1102,12 @@ static int snd_emu10k1_pcm_efx_voices_mask_put(snd_kcontrol_t * kcontrol, snd_ct
 		}
 	if (bits != 1 && bits != 2 && bits != 4 && bits != 8)
 		return -EINVAL;
-	spin_lock_irqsave(&emu->reg_lock, flags);
+	spin_lock_irq(&emu->reg_lock);
 	change = (nval[0] != emu->efx_voices_mask[0]) ||
 		(nval[1] != emu->efx_voices_mask[1]);
 	emu->efx_voices_mask[0] = nval[0];
 	emu->efx_voices_mask[1] = nval[1];
-	spin_unlock_irqrestore(&emu->reg_lock, flags);
+	spin_unlock_irq(&emu->reg_lock);
 	return change;
 }
 
@@ -1125,9 +1130,238 @@ static snd_pcm_ops_t snd_emu10k1_capture_efx_ops = {
 	.pointer =		snd_emu10k1_capture_pointer,
 };
 
+
+/* EFX playback */
+
+#define INITIAL_TRAM_SHIFT     14
+#define INITIAL_TRAM_POS(size) ((((size) / 2) - INITIAL_TRAM_SHIFT) - 1)
+
+static void snd_emu10k1_fx8010_playback_irq(emu10k1_t *emu, void *private_data)
+{
+	snd_pcm_substream_t *substream = private_data;
+	snd_pcm_period_elapsed(substream);
+}
+
+static void snd_emu10k1_fx8010_playback_tram_poke1(unsigned short *dst_left,
+						   unsigned short *dst_right,
+						   unsigned short *src,
+						   unsigned int count,
+						   unsigned int tram_shift)
+{
+	// printk("tram_poke1: dst_left = 0x%p, dst_right = 0x%p, src = 0x%p, count = 0x%x\n", dst_left, dst_right, src, count);
+	if ((tram_shift & 1) == 0) {
+		while (count--) {
+			*dst_left-- = *src++;
+			*dst_right-- = *src++;
+		}
+	} else {
+		while (count--) {
+			*dst_right-- = *src++;
+			*dst_left-- = *src++;
+		}
+	}
+}
+
+static void fx8010_pb_trans_copy(snd_pcm_substream_t *substream,
+				 snd_pcm_indirect_t *rec, size_t bytes)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+	unsigned int tram_size = pcm->buffer_size;
+	unsigned short *src = (unsigned short *)(substream->runtime->dma_area + rec->sw_data);
+	unsigned int frames = bytes >> 2, count;
+	unsigned int tram_pos = pcm->tram_pos;
+	unsigned int tram_shift = pcm->tram_shift;
+
+	while (frames > tram_pos) {
+		count = tram_pos + 1;
+		snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + tram_pos,
+						       (unsigned short *)emu->fx8010.etram_pages.area + tram_pos + tram_size / 2,
+						       src, count, tram_shift);
+		src += count * 2;
+		frames -= count;
+		tram_pos = (tram_size / 2) - 1;
+		tram_shift++;
+	}
+	snd_emu10k1_fx8010_playback_tram_poke1((unsigned short *)emu->fx8010.etram_pages.area + tram_pos,
+					       (unsigned short *)emu->fx8010.etram_pages.area + tram_pos + tram_size / 2,
+					       src, frames, tram_shift++);
+	tram_pos -= frames;
+	pcm->tram_pos = tram_pos;
+	pcm->tram_shift = tram_shift;
+}
+
+static int snd_emu10k1_fx8010_playback_transfer(snd_pcm_substream_t *substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+
+	snd_pcm_indirect_playback_transfer(substream, &pcm->pcm_rec, fx8010_pb_trans_copy);
+	return 0;
+}
+
+static int snd_emu10k1_fx8010_playback_hw_params(snd_pcm_substream_t * substream,
+						 snd_pcm_hw_params_t * hw_params)
+{
+	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+}
+
+static int snd_emu10k1_fx8010_playback_hw_free(snd_pcm_substream_t * substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+	unsigned int i;
+
+	for (i = 0; i < pcm->channels; i++)
+		snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, 0);
+	snd_pcm_lib_free_pages(substream);
+	return 0;
+}
+
+static int snd_emu10k1_fx8010_playback_prepare(snd_pcm_substream_t * substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+	unsigned int i;
+	
+	// printk("prepare: etram_pages = 0x%p, dma_area = 0x%x, buffer_size = 0x%x (0x%x)\n", emu->fx8010.etram_pages, runtime->dma_area, runtime->buffer_size, runtime->buffer_size << 2);
+	memset(&pcm->pcm_rec, 0, sizeof(pcm->pcm_rec));
+	pcm->pcm_rec.hw_buffer_size = pcm->buffer_size * 2; /* byte size */
+	pcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+	pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size);
+	pcm->tram_shift = 0;
+	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_running, 0, 0);	/* reset */
+	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0);	/* reset */
+	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_size, 0, runtime->buffer_size);
+	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_ptr, 0, 0);		/* reset ptr number */
+	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_count, 0, runtime->period_size);
+	snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_tmpcount, 0, runtime->period_size);
+	for (i = 0; i < pcm->channels; i++)
+		snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, (TANKMEMADDRREG_READ|TANKMEMADDRREG_ALIGN) + i * (runtime->buffer_size / pcm->channels));
+	return 0;
+}
+
+static int snd_emu10k1_fx8010_playback_trigger(snd_pcm_substream_t * substream, int cmd)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+	int result = 0;
+
+	spin_lock(&emu->reg_lock);
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		/* follow thru */
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+#ifdef EMU10K1_SET_AC3_IEC958
+	{
+		int i;
+		for (i = 0; i < 3; i++) {
+			unsigned int bits;
+			bits = SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
+			       SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS |
+			       0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT | SPCS_NOTAUDIODATA;
+			snd_emu10k1_ptr_write(emu, SPCS0 + i, 0, bits);
+		}
+	}
+#endif
+		result = snd_emu10k1_fx8010_register_irq_handler(emu, snd_emu10k1_fx8010_playback_irq, pcm->gpr_running, substream, &pcm->irq);
+		if (result < 0)
+			goto __err;
+		snd_emu10k1_fx8010_playback_transfer(substream);	/* roll the ball */
+		snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 1);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		snd_emu10k1_fx8010_unregister_irq_handler(emu, pcm->irq); pcm->irq = NULL;
+		snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0);
+		pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size);
+		pcm->tram_shift = 0;
+		break;
+	default:
+		result = -EINVAL;
+		break;
+	}
+      __err:
+	spin_unlock(&emu->reg_lock);
+	return result;
+}
+
+static snd_pcm_uframes_t snd_emu10k1_fx8010_playback_pointer(snd_pcm_substream_t * substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+	size_t ptr; /* byte pointer */
+
+	if (!snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_trigger, 0))
+		return 0;
+	ptr = snd_emu10k1_ptr_read(emu, emu->gpr_base + pcm->gpr_ptr, 0) << 2;
+	return snd_pcm_indirect_playback_pointer(substream, &pcm->pcm_rec, ptr);
+}
+
+static snd_pcm_hardware_t snd_emu10k1_fx8010_playback =
+{
+	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+				 /* SNDRV_PCM_INFO_MMAP_VALID | */ SNDRV_PCM_INFO_PAUSE),
+	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
+	.rates =		SNDRV_PCM_RATE_48000,
+	.rate_min =		48000,
+	.rate_max =		48000,
+	.channels_min =		1,
+	.channels_max =		1,
+	.buffer_bytes_max =	(128*1024),
+	.period_bytes_min =	1024,
+	.period_bytes_max =	(128*1024),
+	.periods_min =		1,
+	.periods_max =		1024,
+	.fifo_size =		0,
+};
+
+static int snd_emu10k1_fx8010_playback_open(snd_pcm_substream_t * substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+
+	runtime->hw = snd_emu10k1_fx8010_playback;
+	runtime->hw.channels_min = runtime->hw.channels_max = pcm->channels;
+	runtime->hw.period_bytes_max = (pcm->buffer_size * 2) / 2;
+	spin_lock_irq(&emu->reg_lock);
+	if (pcm->valid == 0) {
+		spin_unlock_irq(&emu->reg_lock);
+		return -ENODEV;
+	}
+	pcm->opened = 1;
+	spin_unlock_irq(&emu->reg_lock);
+	return 0;
+}
+
+static int snd_emu10k1_fx8010_playback_close(snd_pcm_substream_t * substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_emu10k1_fx8010_pcm_t *pcm = &emu->fx8010.pcm[substream->number];
+
+	spin_lock_irq(&emu->reg_lock);
+	pcm->opened = 0;
+	spin_unlock_irq(&emu->reg_lock);
+	return 0;
+}
+
+static snd_pcm_ops_t snd_emu10k1_fx8010_playback_ops = {
+	.open =			snd_emu10k1_fx8010_playback_open,
+	.close =		snd_emu10k1_fx8010_playback_close,
+	.ioctl =		snd_pcm_lib_ioctl,
+	.hw_params =		snd_emu10k1_fx8010_playback_hw_params,
+	.hw_free =		snd_emu10k1_fx8010_playback_hw_free,
+	.prepare =		snd_emu10k1_fx8010_playback_prepare,
+	.trigger =		snd_emu10k1_fx8010_playback_trigger,
+	.pointer =		snd_emu10k1_fx8010_playback_pointer,
+	.ack =			snd_emu10k1_fx8010_playback_transfer,
+};
+
 static void snd_emu10k1_pcm_efx_free(snd_pcm_t *pcm)
 {
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, pcm->private_data, return);
+	emu10k1_t *emu = pcm->private_data;
 	emu->pcm_efx = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1140,12 +1374,13 @@ int __devinit snd_emu10k1_pcm_efx(emu10k1_t * emu, int device, snd_pcm_t ** rpcm
 	if (rpcm)
 		*rpcm = NULL;
 
-	if ((err = snd_pcm_new(emu->card, "emu10k1 efx", device, 0, 1, &pcm)) < 0)
+	if ((err = snd_pcm_new(emu->card, "emu10k1 efx", device, 8, 1, &pcm)) < 0)
 		return err;
 
 	pcm->private_data = emu;
 	pcm->private_free = snd_emu10k1_pcm_efx_free;
 
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_fx8010_playback_ops);
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_emu10k1_capture_efx_ops);
 
 	pcm->info_flags = 0;
diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
index 9582c3179..994066c67 100644
--- a/sound/pci/emu10k1/emuproc.c
+++ b/sound/pci/emu10k1/emuproc.c
@@ -71,31 +71,32 @@ static void snd_emu10k1_proc_spdif_status(emu10k1_t * emu,
 static void snd_emu10k1_proc_read(snd_info_entry_t *entry, 
 				  snd_info_buffer_t * buffer)
 {
-	static char *outputs[32] = {
-		/* 00 */ "PCM Left",
-		/* 01 */ "PCM Right",
-		/* 02 */ "PCM Surround Left",
-		/* 03 */ "PCM Surround Right",
-		/* 04 */ "MIDI Left",
-		/* 05 */ "MIDI Right",
-		/* 06 */ "PCM Center",
-		/* 07 */ "PCM LFE",
-		/* 08 */ "???",
-		/* 09 */ "???",
-		/* 10 */ "???",
-		/* 11 */ "???",
-		/* 12 */ "MIDI Reverb",
-		/* 13 */ "MIDI Chorus",
-		/* 14 */ "???",
+	/* FIXME - output names are in emufx.c too */
+	static char *creative_outs[32] = {
+		/* 00 */ "AC97 Left",
+		/* 01 */ "AC97 Right",
+		/* 02 */ "Optical IEC958 Left",
+		/* 03 */ "Optical IEC958 Right",
+		/* 04 */ "Center",
+		/* 05 */ "LFE",
+		/* 06 */ "Headphone Left",
+		/* 07 */ "Headphone Right",
+		/* 08 */ "Surround Left",
+		/* 09 */ "Surround Right",
+		/* 10 */ "PCM Capture Left",
+		/* 11 */ "PCM Capture Right",
+		/* 12 */ "MIC Capture",
+		/* 13 */ "AC97 Surround Left",
+		/* 14 */ "AC97 Surround Right",
 		/* 15 */ "???",
 		/* 16 */ "???",
-		/* 17 */ "???",
-		/* 18 */ "ADC Left / CDROM S/PDIF Left",
-		/* 19 */ "ADC Right / CDROM S/PDIF Right",
-		/* 20 */ "MIC / Zoom Video Left",
-		/* 21 */ "Zoom Video Right",
-		/* 22 */ "S/PDIF Left",
-		/* 23 */ "S/PDIF Right",
+		/* 17 */ "Analog Center",
+		/* 18 */ "Analog LFE",
+		/* 19 */ "???",
+		/* 20 */ "???",
+		/* 21 */ "???",
+		/* 22 */ "???",
+		/* 23 */ "???",
 		/* 24 */ "???",
 		/* 25 */ "???",
 		/* 26 */ "???",
@@ -105,9 +106,78 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry,
 		/* 30 */ "???",
 		/* 31 */ "???"
 	};
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, entry->private_data, return);
+
+	static char *audigy_outs[64] = {
+		/* 00 */ "Digital Front Left",
+		/* 01 */ "Digital Front Right",
+		/* 02 */ "Digital Center",
+		/* 03 */ "Digital LEF",
+		/* 04 */ "Headphone Left",
+		/* 05 */ "Headphone Right",
+		/* 06 */ "Digital Rear Left",
+		/* 07 */ "Digital Rear Right",
+		/* 08 */ "Front Left",
+		/* 09 */ "Front Right",
+		/* 10 */ "Center",
+		/* 11 */ "LFE",
+		/* 12 */ "???",
+		/* 13 */ "???",
+		/* 14 */ "Rear Left",
+		/* 15 */ "Rear Right",
+		/* 16 */ "AC97 Front Left",
+		/* 17 */ "AC97 Front Right",
+		/* 18 */ "ADC Caputre Left",
+		/* 19 */ "ADC Capture Right",
+		/* 20 */ "???",
+		/* 21 */ "???",
+		/* 22 */ "???",
+		/* 23 */ "???",
+		/* 24 */ "???",
+		/* 25 */ "???",
+		/* 26 */ "???",
+		/* 27 */ "???",
+		/* 28 */ "???",
+		/* 29 */ "???",
+		/* 30 */ "???",
+		/* 31 */ "???",
+		/* 32 */ "???",
+		/* 33 */ "???",
+		/* 34 */ "???",
+		/* 35 */ "???",
+		/* 36 */ "???",
+		/* 37 */ "???",
+		/* 38 */ "???",
+		/* 39 */ "???",
+		/* 40 */ "???",
+		/* 41 */ "???",
+		/* 42 */ "???",
+		/* 43 */ "???",
+		/* 44 */ "???",
+		/* 45 */ "???",
+		/* 46 */ "???",
+		/* 47 */ "???",
+		/* 48 */ "???",
+		/* 49 */ "???",
+		/* 50 */ "???",
+		/* 51 */ "???",
+		/* 52 */ "???",
+		/* 53 */ "???",
+		/* 54 */ "???",
+		/* 55 */ "???",
+		/* 56 */ "???",
+		/* 57 */ "???",
+		/* 58 */ "???",
+		/* 59 */ "???",
+		/* 60 */ "???",
+		/* 61 */ "???",
+		/* 62 */ "???",
+		/* 33 */ "???"
+	};
+
+	emu10k1_t *emu = entry->private_data;
 	unsigned int val;
 	int nefx = emu->audigy ? 64 : 32;
+	char **outputs = emu->audigy ? audigy_outs : creative_outs;
 	int idx;
 	
 	snd_iprintf(buffer, "EMU10K1\n\n");
@@ -117,7 +187,7 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry,
 	snd_iprintf(buffer, "Card                  : %s\n",
 		    emu->audigy ? "Audigy" : (emu->APS ? "EMU APS" : "Creative"));
 	snd_iprintf(buffer, "Internal TRAM (words) : 0x%x\n", emu->fx8010.itram_size);
-	snd_iprintf(buffer, "External TRAM (words) : 0x%x\n", emu->fx8010.etram_pages.bytes);
+	snd_iprintf(buffer, "External TRAM (words) : 0x%x\n", (int)emu->fx8010.etram_pages.bytes);
 	snd_iprintf(buffer, "\n");
 	if (emu->audigy) {
 		snd_iprintf(buffer, "Effect Send Routing   : A=%i, B=%i, C=%i, D=%i\n",
@@ -135,7 +205,7 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry,
 	snd_iprintf(buffer, "\nCaptured FX Outputs   :\n");
 	for (idx = 0; idx < nefx; idx++) {
 		if (emu->efx_voices_mask[idx/32] & (1 << (idx%32)))
-			snd_iprintf(buffer, "  Output %02i [%s]\n", idx, outputs[idx%32]);
+			snd_iprintf(buffer, "  Output %02i [%s]\n", idx, outputs[idx]);
 	}
 	snd_iprintf(buffer, "\nAll FX Outputs        :\n");
 	for (idx = 0; idx < 32; idx++)
@@ -155,7 +225,7 @@ static void snd_emu10k1_proc_acode_read(snd_info_entry_t *entry,
 				        snd_info_buffer_t * buffer)
 {
 	u32 pc;
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, entry->private_data, return);
+	emu10k1_t *emu = entry->private_data;
 
 	snd_iprintf(buffer, "FX8010 Instruction List '%s'\n", emu->fx8010.name);
 	snd_iprintf(buffer, "  Code dump      :\n");
@@ -195,7 +265,7 @@ static long snd_emu10k1_fx8010_read(snd_info_entry_t *entry, void *file_private_
 				    unsigned long count, unsigned long pos)
 {
 	long size;
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, entry->private_data, return -ENXIO);
+	emu10k1_t *emu = entry->private_data;
 	unsigned int offset;
 	
 	if (!strcmp(entry->name, "fx8010_tram_addr")) {
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c
index 95f85d770..22d8e3dd6 100644
--- a/sound/pci/emu10k1/io.c
+++ b/sound/pci/emu10k1/io.c
@@ -231,7 +231,7 @@ void snd_emu10k1_wait(emu10k1_t *emu, unsigned int wait)
 
 unsigned short snd_emu10k1_ac97_read(ac97_t *ac97, unsigned short reg)
 {
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, ac97->private_data, return -ENXIO);
+	emu10k1_t *emu = ac97->private_data;
 	unsigned long flags;
 	unsigned short val;
 
@@ -244,7 +244,7 @@ unsigned short snd_emu10k1_ac97_read(ac97_t *ac97, unsigned short reg)
 
 void snd_emu10k1_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short data)
 {
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, ac97->private_data, return);
+	emu10k1_t *emu = ac97->private_data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&emu->emu_lock, flags);
diff --git a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c
index 17595a41d..e960828e0 100644
--- a/sound/pci/emu10k1/irq.c
+++ b/sound/pci/emu10k1/irq.c
@@ -32,7 +32,7 @@
 
 irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	emu10k1_t *emu = snd_magic_cast(emu10k1_t, dev_id, return IRQ_NONE);
+	emu10k1_t *emu = dev_id;
 	unsigned int status, orig_status;
 	int handled = 0;
 
diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c
index 90e69535a..7a595f0dd 100644
--- a/sound/pci/emu10k1/memory.c
+++ b/sound/pci/emu10k1/memory.c
@@ -22,6 +22,7 @@
  */
 
 #include <sound/driver.h>
+#include <linux/pci.h>
 #include <linux/time.h>
 #include <sound/core.h>
 #include <sound/emu10k1.h>
@@ -291,7 +292,7 @@ snd_util_memblk_t *
 snd_emu10k1_alloc_pages(emu10k1_t *emu, snd_pcm_substream_t *substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	struct snd_sg_buf *sgbuf = runtime->dma_private;
+	struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
 	snd_util_memhdr_t *hdr;
 	emu10k1_memblk_t *blk;
 	int page, err, idx;
@@ -441,10 +442,11 @@ static int synth_alloc_pages(emu10k1_t *emu, emu10k1_memblk_t *blk)
 	get_single_page_range(emu->memhdr, blk, &first_page, &last_page);
 	/* allocate kernel pages */
 	for (page = first_page; page <= last_page; page++) {
-		if (snd_dma_alloc_pages(&emu->dma_dev, PAGE_SIZE, &dmab) < 0)
+		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci),
+					PAGE_SIZE, &dmab) < 0)
 			goto __fail;
 		if (! is_valid_page(emu, dmab.addr)) {
-			snd_dma_free_pages(&emu->dma_dev, &dmab);
+			snd_dma_free_pages(&dmab);
 			goto __fail;
 		}
 		emu->page_addr_table[page] = dmab.addr;
@@ -459,7 +461,7 @@ __fail:
 		dmab.area = emu->page_ptr_table[page];
 		dmab.addr = emu->page_addr_table[page];
 		dmab.bytes = PAGE_SIZE;
-		snd_dma_free_pages(&emu->dma_dev, &dmab);
+		snd_dma_free_pages(&dmab);
 		emu->page_addr_table[page] = 0;
 		emu->page_ptr_table[page] = NULL;
 	}
@@ -476,13 +478,15 @@ static int synth_free_pages(emu10k1_t *emu, emu10k1_memblk_t *blk)
 	struct snd_dma_buffer dmab;
 
 	get_single_page_range(emu->memhdr, blk, &first_page, &last_page);
+	dmab.dev.type = SNDRV_DMA_TYPE_DEV;
+	dmab.dev.dev = snd_dma_pci_data(emu->pci);
 	for (page = first_page; page <= last_page; page++) {
 		if (emu->page_ptr_table[page] == NULL)
 			continue;
 		dmab.area = emu->page_ptr_table[page];
 		dmab.addr = emu->page_addr_table[page];
 		dmab.bytes = PAGE_SIZE;
-		snd_dma_free_pages(&emu->dma_dev, &dmab);
+		snd_dma_free_pages(&dmab);
 		emu->page_addr_table[page] = 0;
 		emu->page_ptr_table[page] = NULL;
 	}
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 43e23d10c..ef32537a1 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -40,8 +40,6 @@
 #include <sound/initval.h>
 #include <sound/asoundef.h>
 
-#define chip_t ensoniq_t
-
 #ifndef CHIP1371
 #undef CHIP1370
 #define CHIP1370
@@ -56,15 +54,14 @@
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Thomas Sailer <sailer@ife.ee.ethz.ch>");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 #ifdef CHIP1370
 MODULE_DESCRIPTION("Ensoniq AudioPCI ES1370");
-MODULE_DEVICES("{{Ensoniq,AudioPCI-97 ES1370},"
+MODULE_SUPPORTED_DEVICE("{{Ensoniq,AudioPCI-97 ES1370},"
 	        "{Creative Labs,SB PCI64/128 (ES1370)}}");
 #endif
 #ifdef CHIP1371
 MODULE_DESCRIPTION("Ensoniq/Creative AudioPCI ES1371+");
-MODULE_DEVICES("{{Ensoniq,AudioPCI ES1371/73},"
+MODULE_SUPPORTED_DEVICE("{{Ensoniq,AudioPCI ES1371/73},"
 		"{Ensoniq,AudioPCI ES1373},"
 		"{Creative Labs,Ectiva EV1938},"
 		"{Creative Labs,SB PCI64/128 (ES1371/73)},"
@@ -90,22 +87,17 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Ensoniq AudioPCI soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Ensoniq AudioPCI soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Ensoniq AudioPCI soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 #ifdef SUPPORT_JOYSTICK
 #ifdef CHIP1371
 module_param_array(joystick_port, int, boot_devs, 0444);
 MODULE_PARM_DESC(joystick_port, "Joystick port address.");
-MODULE_PARM_SYNTAX(joystick_port, SNDRV_ENABLED ",allows:{{0},{1},{0x200},{0x208},{0x210},{0x218}},dialog:list");
 #else
 module_param_array(joystick, bool, boot_devs, 0444);
 MODULE_PARM_DESC(joystick, "Enable joystick.");
-MODULE_PARM_SYNTAX(joystick, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 #endif
 #endif /* SUPPORT_JOYSTICK */
 
@@ -388,7 +380,6 @@ struct _snd_ensoniq {
 	unsigned long capture3size;
 
 	unsigned long port;
-	struct resource *res_port;
 	unsigned int mode;
 	unsigned int uartm;	/* UART mode */
 
@@ -435,7 +426,6 @@ struct _snd_ensoniq {
 	unsigned int spdif_stream;
 
 #ifdef CHIP1370
-	struct snd_dma_device dma_dev;
 	struct snd_dma_buffer dma_bug;
 #endif
 
@@ -581,7 +571,7 @@ static void snd_es1371_src_write(ensoniq_t * ensoniq,
 static void snd_es1370_codec_write(ak4531_t *ak4531,
 				   unsigned short reg, unsigned short val)
 {
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, ak4531->private_data, return);
+	ensoniq_t *ensoniq = ak4531->private_data;
 	unsigned long flags;
 	unsigned long end_time = jiffies + HZ / 10;
 
@@ -611,7 +601,7 @@ static void snd_es1370_codec_write(ak4531_t *ak4531,
 static void snd_es1371_codec_write(ac97_t *ac97,
 				   unsigned short reg, unsigned short val)
 {
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, ac97->private_data, return);
+	ensoniq_t *ensoniq = ac97->private_data;
 	unsigned long flags;
 	unsigned int t, x;
 
@@ -649,7 +639,7 @@ static void snd_es1371_codec_write(ac97_t *ac97,
 static unsigned short snd_es1371_codec_read(ac97_t *ac97,
 					    unsigned short reg)
 {
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, ac97->private_data, return -ENXIO);
+	ensoniq_t *ensoniq = ac97->private_data;
 	unsigned long flags;
 	unsigned int t, x, fail = 0;
 
@@ -844,7 +834,6 @@ static int snd_ensoniq_hw_free(snd_pcm_substream_t * substream)
 
 static int snd_ensoniq_playback1_prepare(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
 	ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	unsigned int mode = 0;
@@ -855,7 +844,7 @@ static int snd_ensoniq_playback1_prepare(snd_pcm_substream_t * substream)
 		mode |= 0x02;
 	if (runtime->channels > 1)
 		mode |= 0x01;
-	spin_lock_irqsave(&ensoniq->reg_lock, flags);
+	spin_lock_irq(&ensoniq->reg_lock);
 	ensoniq->ctrl &= ~ES_DAC1_EN;
 	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
 	outl(ES_MEM_PAGEO(ES_PAGE_DAC), ES_REG(ensoniq, MEM_PAGE));
@@ -878,13 +867,12 @@ static int snd_ensoniq_playback1_prepare(snd_pcm_substream_t * substream)
 	snd_es1371_dac1_rate(ensoniq, runtime->rate);
 #endif
 	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
-	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+	spin_unlock_irq(&ensoniq->reg_lock);
 	return 0;
 }
 
 static int snd_ensoniq_playback2_prepare(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
 	ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	unsigned int mode = 0;
@@ -895,7 +883,7 @@ static int snd_ensoniq_playback2_prepare(snd_pcm_substream_t * substream)
 		mode |= 0x02;
 	if (runtime->channels > 1)
 		mode |= 0x01;
-	spin_lock_irqsave(&ensoniq->reg_lock, flags);
+	spin_lock_irq(&ensoniq->reg_lock);
 	ensoniq->ctrl &= ~ES_DAC2_EN;
 	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
 	outl(ES_MEM_PAGEO(ES_PAGE_DAC), ES_REG(ensoniq, MEM_PAGE));
@@ -917,13 +905,12 @@ static int snd_ensoniq_playback2_prepare(snd_pcm_substream_t * substream)
 	snd_es1371_dac2_rate(ensoniq, runtime->rate);
 #endif
 	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
-	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+	spin_unlock_irq(&ensoniq->reg_lock);
 	return 0;
 }
 
 static int snd_ensoniq_capture_prepare(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
 	ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	unsigned int mode = 0;
@@ -934,7 +921,7 @@ static int snd_ensoniq_capture_prepare(snd_pcm_substream_t * substream)
 		mode |= 0x02;
 	if (runtime->channels > 1)
 		mode |= 0x01;
-	spin_lock_irqsave(&ensoniq->reg_lock, flags);
+	spin_lock_irq(&ensoniq->reg_lock);
 	ensoniq->ctrl &= ~ES_ADC_EN;
 	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
 	outl(ES_MEM_PAGEO(ES_PAGE_ADC), ES_REG(ensoniq, MEM_PAGE));
@@ -954,7 +941,7 @@ static int snd_ensoniq_capture_prepare(snd_pcm_substream_t * substream)
 	snd_es1371_adc_rate(ensoniq, runtime->rate);
 #endif
 	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
-	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+	spin_unlock_irq(&ensoniq->reg_lock);
 	return 0;
 }
 
@@ -1151,31 +1138,29 @@ static int snd_ensoniq_playback1_close(snd_pcm_substream_t * substream)
 
 static int snd_ensoniq_playback2_close(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
 	ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
 
 	ensoniq->playback2_substream = NULL;
-	spin_lock_irqsave(&ensoniq->reg_lock, flags);
+	spin_lock_irq(&ensoniq->reg_lock);
 #ifdef CHIP1370
 	ensoniq->u.es1370.pclkdiv_lock &= ~ES_MODE_PLAY2;
 #endif
 	ensoniq->mode &= ~ES_MODE_PLAY2;
-	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+	spin_unlock_irq(&ensoniq->reg_lock);
 	return 0;
 }
 
 static int snd_ensoniq_capture_close(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
 	ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
 
 	ensoniq->capture_substream = NULL;
-	spin_lock_irqsave(&ensoniq->reg_lock, flags);
+	spin_lock_irq(&ensoniq->reg_lock);
 #ifdef CHIP1370
 	ensoniq->u.es1370.pclkdiv_lock &= ~ES_MODE_CAPTURE;
 #endif
 	ensoniq->mode &= ~ES_MODE_CAPTURE;
-	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+	spin_unlock_irq(&ensoniq->reg_lock);
 	return 0;
 }
 
@@ -1214,7 +1199,7 @@ static snd_pcm_ops_t snd_ensoniq_capture_ops = {
 
 static void snd_ensoniq_pcm_free(snd_pcm_t *pcm)
 {
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, pcm->private_data, return);
+	ensoniq_t *ensoniq = pcm->private_data;
 	ensoniq->pcm1 = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1261,7 +1246,7 @@ static int __devinit snd_ensoniq_pcm(ensoniq_t * ensoniq, int device, snd_pcm_t
 
 static void snd_ensoniq_pcm_free2(snd_pcm_t *pcm)
 {
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, pcm->private_data, return);
+	ensoniq_t *ensoniq = pcm->private_data;
 	ensoniq->pcm2 = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1565,7 +1550,7 @@ static snd_kcontrol_new_t snd_ens1373_line __devinitdata =
 
 static void snd_ensoniq_mixer_free_ac97(ac97_t *ac97)
 {
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, ac97->private_data, return);
+	ensoniq_t *ensoniq = ac97->private_data;
 	ensoniq->u.es1371.ac97 = NULL;
 }
 
@@ -1585,14 +1570,15 @@ static struct {
 static int snd_ensoniq_1371_mixer(ensoniq_t * ensoniq)
 {
 	snd_card_t *card = ensoniq->card;
-	ac97_bus_t bus, *pbus;
-	ac97_t ac97;
+	ac97_bus_t *pbus;
+	ac97_template_t ac97;
 	int err, idx;
+	static ac97_bus_ops_t ops = {
+		.write = snd_es1371_codec_write,
+		.read = snd_es1371_codec_read,
+	};
 
-	memset(&bus, 0, sizeof(bus));
-	bus.write = snd_es1371_codec_write;
-	bus.read = snd_es1371_codec_read;
-	if ((err = snd_ac97_bus(card, &bus, &pbus)) < 0)
+	if ((err = snd_ac97_bus(card, 0, &ops, NULL, &pbus)) < 0)
 		return err;
 
 	memset(&ac97, 0, sizeof(ac97));
@@ -1663,30 +1649,28 @@ static int snd_ensoniq_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_
 static int snd_ensoniq_control_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int mask = kcontrol->private_value;
 	
-	spin_lock_irqsave(&ensoniq->reg_lock, flags);
+	spin_lock_irq(&ensoniq->reg_lock);
 	ucontrol->value.integer.value[0] = ensoniq->ctrl & mask ? 1 : 0;
-	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+	spin_unlock_irq(&ensoniq->reg_lock);
 	return 0;
 }
 
 static int snd_ensoniq_control_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int mask = kcontrol->private_value;
 	unsigned int nval;
 	int change;
 	
 	nval = ucontrol->value.integer.value[0] ? mask : 0;
-	spin_lock_irqsave(&ensoniq->reg_lock, flags);
+	spin_lock_irq(&ensoniq->reg_lock);
 	change = (ensoniq->ctrl & mask) != nval;
 	ensoniq->ctrl &= ~mask;
 	ensoniq->ctrl |= nval;
 	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
-	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+	spin_unlock_irq(&ensoniq->reg_lock);
 	return change;
 }
 
@@ -1703,7 +1687,7 @@ ENSONIQ_CONTROL("Mic +5V bias", ES_1370_XCTL1)
 
 static void snd_ensoniq_mixer_free_ak4531(ak4531_t *ak4531)
 {
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, ak4531->private_data, return);
+	ensoniq_t *ensoniq = ak4531->private_data;
 	ensoniq->u.es1370.ak4531 = NULL;
 }
 
@@ -1785,7 +1769,7 @@ static void snd_ensoniq_joystick_free(ensoniq_t *ensoniq)
 static void snd_ensoniq_proc_read(snd_info_entry_t *entry, 
 				  snd_info_buffer_t * buffer)
 {
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, entry->private_data, return);
+	ensoniq_t *ensoniq = entry->private_data;
 
 #ifdef CHIP1370
 	snd_iprintf(buffer, "Ensoniq AudioPCI ES1370\n\n");
@@ -1833,21 +1817,18 @@ static int snd_ensoniq_free(ensoniq_t *ensoniq)
       __hw_end:
 #ifdef CHIP1370
 	if (ensoniq->dma_bug.area)
-		snd_dma_free_pages(&ensoniq->dma_dev, &ensoniq->dma_bug);
+		snd_dma_free_pages(&ensoniq->dma_bug);
 #endif
-	if (ensoniq->res_port) {
-		release_resource(ensoniq->res_port);
-		kfree_nocheck(ensoniq->res_port);
-	}
 	if (ensoniq->irq >= 0)
 		free_irq(ensoniq->irq, (void *)ensoniq);
-	snd_magic_kfree(ensoniq);
+	pci_release_regions(ensoniq->pci);
+	kfree(ensoniq);
 	return 0;
 }
 
 static int snd_ensoniq_dev_free(snd_device_t *device)
 {
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, device->device_data, return -ENXIO);
+	ensoniq_t *ensoniq = device->device_data;
 	return snd_ensoniq_free(ensoniq);
 }
 
@@ -1894,19 +1875,18 @@ static int __devinit snd_ensoniq_create(snd_card_t * card,
 	*rensoniq = NULL;
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
-	ensoniq = snd_magic_kcalloc(ensoniq_t, 0, GFP_KERNEL);
+	ensoniq = kcalloc(1, sizeof(*ensoniq), GFP_KERNEL);
 	if (ensoniq == NULL)
 		return -ENOMEM;
 	spin_lock_init(&ensoniq->reg_lock);
 	ensoniq->card = card;
 	ensoniq->pci = pci;
 	ensoniq->irq = -1;
-	ensoniq->port = pci_resource_start(pci, 0);
-	if ((ensoniq->res_port = request_region(ensoniq->port, 0x40, "Ensoniq AudioPCI")) == NULL) {
-		snd_printk("unable to grab ports 0x%lx-0x%lx\n", ensoniq->port, ensoniq->port + 0x40 - 1);
-		snd_ensoniq_free(ensoniq);
-		return -EBUSY;
+	if ((err = pci_request_regions(pci, "Ensoniq AudioPCI")) < 0) {
+		kfree(ensoniq);
+		return err;
 	}
+	ensoniq->port = pci_resource_start(pci, 0);
 	if (request_irq(pci->irq, snd_audiopci_interrupt, SA_INTERRUPT|SA_SHIRQ, "Ensoniq AudioPCI", (void *)ensoniq)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
 		snd_ensoniq_free(ensoniq);
@@ -1914,10 +1894,8 @@ static int __devinit snd_ensoniq_create(snd_card_t * card,
 	}
 	ensoniq->irq = pci->irq;
 #ifdef CHIP1370
-	memset(&ensoniq->dma_dev, 0, sizeof(ensoniq->dma_dev));
-	ensoniq->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	ensoniq->dma_dev.dev = snd_dma_pci_data(pci);
-	if (snd_dma_alloc_pages(&ensoniq->dma_dev, 16, &ensoniq->dma_bug) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				16, &ensoniq->dma_bug) < 0) {
 		snd_printk("unable to allocate space for phantom area - dma_bug\n");
 		snd_ensoniq_free(ensoniq);
 		return -EBUSY;
@@ -2074,10 +2052,9 @@ static void snd_ensoniq_midi_interrupt(ensoniq_t * ensoniq)
 
 static int snd_ensoniq_midi_input_open(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, substream->rmidi->private_data, return -ENXIO);
+	ensoniq_t *ensoniq = substream->rmidi->private_data;
 
-	spin_lock_irqsave(&ensoniq->reg_lock, flags);
+	spin_lock_irq(&ensoniq->reg_lock);
 	ensoniq->uartm |= ES_MODE_INPUT;
 	ensoniq->midi_input = substream;
 	if (!(ensoniq->uartm & ES_MODE_OUTPUT)) {
@@ -2085,16 +2062,15 @@ static int snd_ensoniq_midi_input_open(snd_rawmidi_substream_t * substream)
 		outb(ensoniq->uartc = 0, ES_REG(ensoniq, UART_CONTROL));
 		outl(ensoniq->ctrl |= ES_UART_EN, ES_REG(ensoniq, CONTROL));
 	}
-	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+	spin_unlock_irq(&ensoniq->reg_lock);
 	return 0;
 }
 
 static int snd_ensoniq_midi_input_close(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, substream->rmidi->private_data, return -ENXIO);
+	ensoniq_t *ensoniq = substream->rmidi->private_data;
 
-	spin_lock_irqsave(&ensoniq->reg_lock, flags);
+	spin_lock_irq(&ensoniq->reg_lock);
 	if (!(ensoniq->uartm & ES_MODE_OUTPUT)) {
 		outb(ensoniq->uartc = 0, ES_REG(ensoniq, UART_CONTROL));
 		outl(ensoniq->ctrl &= ~ES_UART_EN, ES_REG(ensoniq, CONTROL));
@@ -2103,16 +2079,15 @@ static int snd_ensoniq_midi_input_close(snd_rawmidi_substream_t * substream)
 	}
 	ensoniq->midi_input = NULL;
 	ensoniq->uartm &= ~ES_MODE_INPUT;
-	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+	spin_unlock_irq(&ensoniq->reg_lock);
 	return 0;
 }
 
 static int snd_ensoniq_midi_output_open(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, substream->rmidi->private_data, return -ENXIO);
+	ensoniq_t *ensoniq = substream->rmidi->private_data;
 
-	spin_lock_irqsave(&ensoniq->reg_lock, flags);
+	spin_lock_irq(&ensoniq->reg_lock);
 	ensoniq->uartm |= ES_MODE_OUTPUT;
 	ensoniq->midi_output = substream;
 	if (!(ensoniq->uartm & ES_MODE_INPUT)) {
@@ -2120,16 +2095,15 @@ static int snd_ensoniq_midi_output_open(snd_rawmidi_substream_t * substream)
 		outb(ensoniq->uartc = 0, ES_REG(ensoniq, UART_CONTROL));
 		outl(ensoniq->ctrl |= ES_UART_EN, ES_REG(ensoniq, CONTROL));
 	}
-	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+	spin_unlock_irq(&ensoniq->reg_lock);
 	return 0;
 }
 
 static int snd_ensoniq_midi_output_close(snd_rawmidi_substream_t * substream)
 {
-	unsigned long flags;
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, substream->rmidi->private_data, return -ENXIO);
+	ensoniq_t *ensoniq = substream->rmidi->private_data;
 
-	spin_lock_irqsave(&ensoniq->reg_lock, flags);
+	spin_lock_irq(&ensoniq->reg_lock);
 	if (!(ensoniq->uartm & ES_MODE_INPUT)) {
 		outb(ensoniq->uartc = 0, ES_REG(ensoniq, UART_CONTROL));
 		outl(ensoniq->ctrl &= ~ES_UART_EN, ES_REG(ensoniq, CONTROL));
@@ -2138,14 +2112,14 @@ static int snd_ensoniq_midi_output_close(snd_rawmidi_substream_t * substream)
 	}
 	ensoniq->midi_output = NULL;
 	ensoniq->uartm &= ~ES_MODE_OUTPUT;
-	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
+	spin_unlock_irq(&ensoniq->reg_lock);
 	return 0;
 }
 
 static void snd_ensoniq_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
 {
 	unsigned long flags;
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, substream->rmidi->private_data, return);
+	ensoniq_t *ensoniq = substream->rmidi->private_data;
 	int idx;
 
 	spin_lock_irqsave(&ensoniq->reg_lock, flags);
@@ -2169,7 +2143,7 @@ static void snd_ensoniq_midi_input_trigger(snd_rawmidi_substream_t * substream,
 static void snd_ensoniq_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
 {
 	unsigned long flags;
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, substream->rmidi->private_data, return);
+	ensoniq_t *ensoniq = substream->rmidi->private_data;
 	unsigned char byte;
 
 	spin_lock_irqsave(&ensoniq->reg_lock, flags);
@@ -2240,7 +2214,7 @@ static int __devinit snd_ensoniq_midi(ensoniq_t * ensoniq, int device, snd_rawmi
 
 static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	ensoniq_t *ensoniq = snd_magic_cast(ensoniq_t, dev_id, return IRQ_NONE);
+	ensoniq_t *ensoniq = dev_id;
 	unsigned int status, sctrl;
 
 	if (ensoniq == NULL)
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 87afa49a0..3d7f98ca9 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -54,6 +54,7 @@
 #include <linux/slab.h>
 #include <linux/gameport.h>
 #include <linux/moduleparam.h>
+#include <linux/delay.h>
 #include <sound/core.h>
 #include <sound/control.h>
 #include <sound/pcm.h>
@@ -63,13 +64,10 @@
 
 #include <asm/io.h>
 
-#define chip_t es1938_t
-
 MODULE_AUTHOR("Jaromir Koutek <miri@punknet.cz>");
 MODULE_DESCRIPTION("ESS Solo-1");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ESS,ES1938},"
+MODULE_SUPPORTED_DEVICE("{{ESS,ES1938},"
                 "{ESS,ES1946},"
                 "{ESS,ES1969},"
 		"{TerraTec,128i PCI}}");
@@ -88,13 +86,10 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for ESS Solo-1 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for ESS Solo-1 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable ESS Solo-1 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 
 #define SLIO_REG(chip, x) ((chip)->io_port + ESSIO_REG_##x)
 
@@ -202,19 +197,16 @@ MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 
 typedef struct _snd_es1938 es1938_t;
 
+#define SAVED_REG_SIZE	32 /* max. number of registers to save */
+
 struct _snd_es1938 {
 	int irq;
 
 	unsigned long io_port;
-	struct resource *res_io_port;
 	unsigned long sb_port;
-	struct resource *res_sb_port;
 	unsigned long vc_port;
-	struct resource *res_vc_port;
 	unsigned long mpu_port;
-	struct resource *res_mpu_port;
 	unsigned long game_port;
-	struct resource *res_game_port;
 	unsigned long ddma_port;
 
 	unsigned char irqmask;
@@ -227,6 +219,7 @@ struct _snd_es1938 {
 
 	struct pci_dev *pci;
 	snd_card_t *card;
+	snd_pcm_t *pcm;
 	snd_pcm_substream_t *capture_substream;
 	snd_pcm_substream_t *playback1_substream;
 	snd_pcm_substream_t *playback2_substream;
@@ -248,6 +241,9 @@ struct _snd_es1938 {
 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
 	struct gameport gameport;
 #endif
+#ifdef CONFIG_PM
+	unsigned char saved_regs[SAVED_REG_SIZE];
+#endif
 };
 
 static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id, struct pt_regs *regs);
@@ -573,7 +569,12 @@ static int snd_es1938_playback1_trigger(snd_pcm_substream_t * substream,
 	case SNDRV_PCM_TRIGGER_START:
 		/* According to the documentation this should be:
 		   0x13 but that value may randomly swap stereo channels */
+                snd_es1938_mixer_write(chip, ESSSB_IREG_AUDIO2CONTROL1, 0x92);
+                udelay(10);
 		snd_es1938_mixer_write(chip, ESSSB_IREG_AUDIO2CONTROL1, 0x93);
+                /* This two stage init gives the FIFO -> DAC connection time to
+                 * settle before first data from DMA flows in.  This should ensure
+                 * no swapping of stereo channels.  Report a bug if otherwise :-) */
 		outb(0x0a, SLIO_REG(chip, AUDIO2MODE));
 		chip->active |= DAC2;
 		break;
@@ -690,6 +691,8 @@ static int snd_es1938_playback1_prepare(snd_pcm_substream_t * substream)
 
 	chip->dma2_shift = 2 - mono - is8;
 
+        snd_es1938_reset_fifo(chip);
+
 	/* set clock and counters */
         snd_es1938_rate_set(chip, substream, DAC2);
 
@@ -874,9 +877,9 @@ static snd_pcm_hardware_t snd_es1938_capture =
 	.rate_max =		48000,
 	.channels_min =		1,
 	.channels_max =		2,
-	.buffer_bytes_max =	65536,
+        .buffer_bytes_max =	0x8000,       /* DMA controller screws on higher values */
 	.period_bytes_min =	64,
-	.period_bytes_max =	65536,
+	.period_bytes_max =	0x8000,
 	.periods_min =		1,
 	.periods_max =		1024,
 	.fifo_size =		256,
@@ -896,9 +899,9 @@ static snd_pcm_hardware_t snd_es1938_playback =
 	.rate_max =		48000,
 	.channels_min =		1,
 	.channels_max =		2,
-	.buffer_bytes_max =	65536,
+        .buffer_bytes_max =	0x8000,       /* DMA controller screws on higher values */
 	.period_bytes_min =	64,
-	.period_bytes_max =	65536,
+	.period_bytes_max =	0x8000,
 	.periods_min =		1,
 	.periods_max =		1024,
 	.fifo_size =		256,
@@ -998,13 +1001,11 @@ static void snd_es1938_free_pcm(snd_pcm_t *pcm)
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
-static int __devinit snd_es1938_new_pcm(es1938_t *chip, int device, snd_pcm_t ** rpcm)
+static int __devinit snd_es1938_new_pcm(es1938_t *chip, int device)
 {
 	snd_pcm_t *pcm;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
 	if ((err = snd_pcm_new(chip->card, "es-1938-1946", device, 2, 1, &pcm)) < 0)
 		return err;
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_es1938_playback_ops);
@@ -1018,8 +1019,7 @@ static int __devinit snd_es1938_new_pcm(es1938_t *chip, int device, snd_pcm_t **
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 					      snd_dma_pci_data(chip->pci), 64*1024, 64*1024);
 
-	if (rpcm)
-		*rpcm = pcm;
+	chip->pcm = pcm;
 	return 0;
 }
 
@@ -1129,7 +1129,7 @@ static int snd_es1938_get_hw_switch(snd_kcontrol_t * kcontrol, snd_ctl_elem_valu
 
 static void snd_es1938_hwv_free(snd_kcontrol_t *kcontrol)
 {
-	es1938_t *chip = snd_magic_cast(es1938_t, _snd_kcontrol_chip(kcontrol), return);
+	es1938_t *chip = snd_kcontrol_chip(kcontrol);
 	chip->master_volume = NULL;
 	chip->master_switch = NULL;
 	chip->hw_volume = NULL;
@@ -1340,43 +1340,106 @@ ES1938_SINGLE("Mic Boost (+26dB)", 0, 0x7d, 3, 1, 0)
 /* ---------------------------------------------------------------------------- */
 /* ---------------------------------------------------------------------------- */
 
+/*
+ * initialize the chip - used by resume callback, too
+ */
+static void snd_es1938_chip_init(es1938_t *chip)
+{
+	/* reset chip */
+	snd_es1938_reset(chip);
+
+	/* configure native mode */
+
+	/* enable bus master */
+	pci_set_master(chip->pci);
+
+	/* disable legacy audio */
+	pci_write_config_word(chip->pci, SL_PCI_LEGACYCONTROL, 0x805f);
+
+	/* set DDMA base */
+	pci_write_config_word(chip->pci, SL_PCI_DDMACONTROL, chip->ddma_port | 1);
+
+	/* set DMA/IRQ policy */
+	pci_write_config_dword(chip->pci, SL_PCI_CONFIG, 0);
+
+	/* enable Audio 1, Audio 2, MPU401 IRQ and HW volume IRQ*/
+	outb(0xf0, SLIO_REG(chip, IRQCONTROL));
+
+	/* reset DMA */
+	outb(0, SLDM_REG(chip, DMACLEAR));
+}
+
+#ifdef CONFIG_PM
+/*
+ * PM support
+ */
+
+static unsigned char saved_regs[SAVED_REG_SIZE+1] = {
+	0x14, 0x1a, 0x1c, 0x3a, 0x3c, 0x3e, 0x36, 0x38,
+	0x50, 0x52, 0x60, 0x61, 0x62, 0x63, 0x64, 0x68,
+	0x69, 0x6a, 0x6b, 0x6d, 0x6e, 0x6f, 0x7c, 0x7d,
+	0xa8, 0xb4,
+};
+
+
+static int es1938_suspend(snd_card_t *card, unsigned int state)
+{
+	es1938_t *chip = card->pm_private_data;
+	unsigned char *s, *d;
+
+	snd_pcm_suspend_all(chip->pcm);
+
+	/* save mixer-related registers */
+	for (s = saved_regs, d = chip->saved_regs; *s; s++, d++)
+		*d = snd_es1938_reg_read(chip, *s);
+
+	outb(0x00, SLIO_REG(chip, IRQCONTROL)); /* disable irqs */
+
+	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+	return 0;
+}
+
+static int es1938_resume(snd_card_t *card, unsigned int state)
+{
+	es1938_t *chip = card->pm_private_data;
+	unsigned char *s, *d;
+
+	pci_enable_device(chip->pci);
+	snd_es1938_chip_init(chip);
+
+	/* restore mixer-related registers */
+	for (s = saved_regs, d = chip->saved_regs; *s; s++, d++) {
+		if (*s < 0xa0)
+			snd_es1938_mixer_write(chip, *s, *d);
+		else
+			snd_es1938_write(chip, *s, *d);
+	}
+
+	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+	return 0;
+}
+#endif /* CONFIG_PM */
+
 static int snd_es1938_free(es1938_t *chip)
 {
+	/* disable irqs */
+	outb(0x00, SLIO_REG(chip, IRQCONTROL));
 	/*if (chip->rmidi)
 	  snd_es1938_mixer_bits(chip, ESSSB_IREG_MPU401CONTROL, 0x40, 0);*/
 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
 	if (chip->gameport.io)
 		gameport_unregister_port(&chip->gameport);
 #endif
-	if (chip->res_io_port) {
-		release_resource(chip->res_io_port);
-		kfree_nocheck(chip->res_io_port);
-	}
-	if (chip->res_sb_port) {
-		release_resource(chip->res_sb_port);
-		kfree_nocheck(chip->res_sb_port);
-	}
-	if (chip->res_vc_port) {
-		release_resource(chip->res_vc_port);
-		kfree_nocheck(chip->res_vc_port);
-	}
-	if (chip->res_mpu_port) {
-		release_resource(chip->res_mpu_port);
-		kfree_nocheck(chip->res_mpu_port);
-	}
-	if (chip->res_game_port) {
-		release_resource(chip->res_game_port);
-		kfree_nocheck(chip->res_game_port);
-	}
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void *)chip);
-	snd_magic_kfree(chip);
+	pci_release_regions(chip->pci);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_es1938_dev_free(snd_device_t *device)
 {
-	es1938_t *chip = snd_magic_cast(es1938_t, device->device_data, return -ENXIO);
+	es1938_t *chip = device->device_data;
 	return snd_es1938_free(chip);
 }
 
@@ -1402,43 +1465,22 @@ static int __devinit snd_es1938_create(snd_card_t * card,
                 return -ENXIO;
         }
 
-	chip = snd_magic_kcalloc(es1938_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
 	spin_lock_init(&chip->mixer_lock);
 	chip->card = card;
 	chip->pci = pci;
-	chip->io_port = pci_resource_start(pci, 0);
-	if ((chip->res_io_port = request_region(chip->io_port, 8, "ESS Solo-1")) == NULL) {
-		snd_printk("unable to grab region 0x%lx-0x%lx\n", chip->io_port, chip->io_port + 8 - 1);
-		snd_es1938_free(chip);
-		return -EBUSY;
+	if ((err = pci_request_regions(pci, "ESS Solo-1")) < 0) {
+		kfree(chip);
+		return err;
 	}
+	chip->io_port = pci_resource_start(pci, 0);
 	chip->sb_port = pci_resource_start(pci, 1);
-	if ((chip->res_sb_port = request_region(chip->sb_port, 0x10, "ESS Solo-1 SB")) == NULL) {
-		snd_printk("unable to grab SB region 0x%lx-0x%lx\n", chip->sb_port, chip->sb_port + 0x10 - 1);
-		snd_es1938_free(chip);
-		return -EBUSY;
-	}
 	chip->vc_port = pci_resource_start(pci, 2);
-	if ((chip->res_vc_port = request_region(chip->vc_port, 0x10, "ESS Solo-1 VC (DMA)")) == NULL) {
-		snd_printk("unable to grab VC (DMA) region 0x%lx-0x%lx\n", chip->vc_port, chip->vc_port + 0x10 - 1);
-		snd_es1938_free(chip);
-		return -EBUSY;
-	}
 	chip->mpu_port = pci_resource_start(pci, 3);
-	if ((chip->res_mpu_port = request_region(chip->mpu_port, 4, "ESS Solo-1 MIDI")) == NULL) {
-		snd_printk("unable to grab MIDI region 0x%lx-0x%lx\n", chip->mpu_port, chip->mpu_port + 4 - 1);
-		snd_es1938_free(chip);
-		return -EBUSY;
-	}
 	chip->game_port = pci_resource_start(pci, 4);
-	if ((chip->res_game_port = request_region(chip->game_port, 4, "ESS Solo-1 GAME")) == NULL) {
-		snd_printk("unable to grab GAME region 0x%lx-0x%lx\n", chip->game_port, chip->game_port + 4 - 1);
-		snd_es1938_free(chip);
-		return -EBUSY;
-	}
 	if (request_irq(pci->irq, snd_es1938_interrupt, SA_INTERRUPT|SA_SHIRQ, "ES1938", (void *)chip)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
 		snd_es1938_free(chip);
@@ -1449,32 +1491,12 @@ static int __devinit snd_es1938_create(snd_card_t * card,
 	snd_printk("create: io: 0x%lx, sb: 0x%lx, vc: 0x%lx, mpu: 0x%lx, game: 0x%lx\n",
 		   chip->io_port, chip->sb_port, chip->vc_port, chip->mpu_port, chip->game_port);
 #endif
-	/* reset chip */
-	snd_es1938_reset(chip);
-
-	/* configure native mode */
-
-	/* enable bus master */
-	pci_set_master(pci);
-
-	/* disable legacy audio */
-	pci_write_config_word(pci, SL_PCI_LEGACYCONTROL, 0x805f);
 
-	/* set DDMA base */
 	chip->ddma_port = chip->vc_port + 0x00;		/* fix from Thomas Sailer */
-	pci_write_config_word(pci, SL_PCI_DDMACONTROL, chip->ddma_port | 1);
 
-	/* set DMA/IRQ policy */
-	pci_write_config_dword(pci, SL_PCI_CONFIG, 0);
+	snd_es1938_chip_init(chip);
 
-	/* enable Audio 1, Audio 2, MPU401 IRQ and HW volume IRQ*/
-	outb(0xf0, SLIO_REG(chip, IRQCONTROL));
-
-	/* reset DMA */
-	outb(0, SLDM_REG(chip, DMACLEAR));
-
-	/* enable bus mastering */
-	pci_set_master(pci);
+	snd_card_set_pm_callback(card, es1938_suspend, es1938_resume, chip);
 
 	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
 		snd_es1938_free(chip);
@@ -1492,7 +1514,7 @@ static int __devinit snd_es1938_create(snd_card_t * card,
  * -------------------------------------------------------------------- */
 static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	es1938_t *chip = snd_magic_cast(es1938_t, dev_id, return IRQ_NONE);
+	es1938_t *chip = dev_id;
 	unsigned char status, audiostatus;
 	int handled = 0;
 
@@ -1560,19 +1582,15 @@ static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id, struct pt_regs *r
 
 #define ES1938_DMA_SIZE 64
 
-static int __devinit snd_es1938_mixer(snd_pcm_t *pcm)
+static int __devinit snd_es1938_mixer(es1938_t *chip)
 {
 	snd_card_t *card;
-	es1938_t *chip;
 	unsigned int idx;
 	int err;
 
-	snd_assert(pcm != NULL && pcm->card != NULL, return -EINVAL);
+	card = chip->card;
 
-	card = pcm->card;
-	chip = snd_pcm_chip(pcm);
-
-	strcpy(card->mixername, pcm->name);
+	strcpy(card->mixername, "ESS Solo-1");
 
 	for (idx = 0; idx < ARRAY_SIZE(snd_es1938_controls); idx++) {
 		snd_kcontrol_t *kctl;
@@ -1608,7 +1626,6 @@ static int __devinit snd_es1938_probe(struct pci_dev *pci,
 	static int dev;
 	snd_card_t *card;
 	es1938_t *chip;
-	snd_pcm_t *pcm;
 	opl3_t *opl3;
 	int idx, err;
 
@@ -1641,11 +1658,11 @@ static int __devinit snd_es1938_probe(struct pci_dev *pci,
 		chip->revision,
 		chip->irq);
 
-	if ((err = snd_es1938_new_pcm(chip, 0, &pcm)) < 0) {
+	if ((err = snd_es1938_new_pcm(chip, 0)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
-	if ((err = snd_es1938_mixer(pcm)) < 0) {
+	if ((err = snd_es1938_mixer(chip)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
@@ -1697,6 +1714,7 @@ static struct pci_driver driver = {
 	.id_table = snd_es1938_ids,
 	.probe = snd_es1938_probe,
 	.remove = __devexit_p(snd_es1938_remove),
+	SND_PCI_PM_CALLBACKS
 };
 
 static int __init alsa_card_es1938_init(void)
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 437d13b42..e97a7e8d7 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -109,15 +109,12 @@
 #include <sound/ac97_codec.h>
 #include <sound/initval.h>
 
-#define chip_t es1968_t
-
 #define CARD_NAME "ESS Maestro1/2"
 #define DRIVER_NAME "ES1968"
 
 MODULE_DESCRIPTION("ESS Maestro");
-MODULE_CLASSES("{sound}");
 MODULE_LICENSE("GPL");
-MODULE_DEVICES("{{ESS,Maestro 2e},"
+MODULE_SUPPORTED_DEVICE("{{ESS,Maestro 2e},"
 		"{ESS,Maestro 2},"
 		"{ESS,Maestro 1},"
 		"{TerraTec,DMX}}");
@@ -142,35 +139,25 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(total_bufsize, int, boot_devs, 0444);
 MODULE_PARM_DESC(total_bufsize, "Total buffer size in kB.");
-MODULE_PARM_SYNTAX(total_bufsize, SNDRV_ENABLED ",allows:{{1,4096}},skill:advanced");
 module_param_array(pcm_substreams_p, int, boot_devs, 0444);
 MODULE_PARM_DESC(pcm_substreams_p, "PCM Playback substreams for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(pcm_substreams_p, SNDRV_ENABLED ",allows:{{1,8}}");
 module_param_array(pcm_substreams_c, int, boot_devs, 0444);
 MODULE_PARM_DESC(pcm_substreams_c, "PCM Capture substreams for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(pcm_substreams_c, SNDRV_ENABLED ",allows:{{0,8}}");
 module_param_array(clock, int, boot_devs, 0444);
 MODULE_PARM_DESC(clock, "Clock on " CARD_NAME " soundcard.  (0 = auto-detect)");
-MODULE_PARM_SYNTAX(clock, SNDRV_ENABLED);
 module_param_array(use_pm, int, boot_devs, 0444);
 MODULE_PARM_DESC(use_pm, "Toggle power-management.  (0 = off, 1 = on, 2 = auto)");
-MODULE_PARM_SYNTAX(use_pm, SNDRV_ENABLED ",allows:{{0,1,2}},default:2,skill:advanced");
 module_param_array(enable_mpu, int, boot_devs, 0444);
 MODULE_PARM_DESC(enable_mpu, "Enable MPU401.  (0 = off, 1 = on, 2 = auto)");
-MODULE_PARM_SYNTAX(enable_mpu, SNDRV_ENABLED ",allows:{{0,2}},default:2");
 #ifdef SUPPORT_JOYSTICK
 module_param_array(joystick, bool, boot_devs, 0444);
 MODULE_PARM_DESC(joystick, "Enable joystick.");
-MODULE_PARM_SYNTAX(joystick, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 #endif
 
 
@@ -522,9 +509,7 @@ enum {
 
 /* DMA Hack! */
 struct snd_esm_memory {
-	char *buf;
-	unsigned long addr;
-	int size;
+	struct snd_dma_buffer buf;
 	int empty;	/* status */
 	struct list_head list;
 };
@@ -573,13 +558,11 @@ struct snd_es1968 {
 	unsigned int clock;		/* clock */
 
 	/* buffer */
-	struct snd_dma_device dma_dev;
 	struct snd_dma_buffer dma;
 
 	/* Resources... */
 	int irq;
 	unsigned long io_port;
-	struct resource *res_io_port;
 	int type;
 	struct pci_dev *pci;
 	snd_card_t *card;
@@ -696,7 +679,7 @@ static int snd_es1968_ac97_wait(es1968_t *chip)
 
 static void snd_es1968_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
 {
-	es1968_t *chip = snd_magic_cast(es1968_t, ac97->private_data, return);
+	es1968_t *chip = ac97->private_data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&chip->reg_lock, flags);
@@ -715,7 +698,7 @@ static void snd_es1968_ac97_write(ac97_t *ac97, unsigned short reg, unsigned sho
 static unsigned short snd_es1968_ac97_read(ac97_t *ac97, unsigned short reg)
 {
 	u16 data = 0;
-	es1968_t *chip = snd_magic_cast(es1968_t, ac97->private_data, return 0);
+	es1968_t *chip = ac97->private_data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&chip->reg_lock, flags);
@@ -1078,10 +1061,10 @@ static void snd_es1968_playback_setup(es1968_t *chip, esschan_t *es,
 	for (channel = 0; channel <= high_apu; channel++) {
 		apu = es->apu[channel];
 
-		snd_es1968_program_wavecache(chip, es, channel, es->memory->addr, 0);
+		snd_es1968_program_wavecache(chip, es, channel, es->memory->buf.addr, 0);
 
 		/* Offset to PCMBAR */
-		pa = es->memory->addr;
+		pa = es->memory->buf.addr;
 		pa -= chip->dma.addr;
 		pa >>= 1;	/* words */
 
@@ -1230,20 +1213,20 @@ static void snd_es1968_capture_setup(es1968_t *chip, esschan_t *es,
 	/* input mixer (left/mono) */
 	/* parallel in crap, see maestro reg 0xC [8-11] */
 	init_capture_apu(chip, es, 2,
-			 es->mixbuf->addr, ESM_MIXBUF_SIZE/4, /* in words */
+			 es->mixbuf->buf.addr, ESM_MIXBUF_SIZE/4, /* in words */
 			 ESM_APU_INPUTMIXER, 0x14);
 	/* SRC (left/mono); get input from inputing apu */
-	init_capture_apu(chip, es, 0, es->memory->addr, size,
+	init_capture_apu(chip, es, 0, es->memory->buf.addr, size,
 			 ESM_APU_SRCONVERTOR, es->apu[2]);
 	if (es->fmt & ESS_FMT_STEREO) {
 		/* input mixer (right) */
 		init_capture_apu(chip, es, 3,
-				 es->mixbuf->addr + ESM_MIXBUF_SIZE/2,
+				 es->mixbuf->buf.addr + ESM_MIXBUF_SIZE/2,
 				 ESM_MIXBUF_SIZE/4, /* in words */
 				 ESM_APU_INPUTMIXER, 0x15);
 		/* SRC (right) */
 		init_capture_apu(chip, es, 1,
-				 es->memory->addr + size*2, size,
+				 es->memory->buf.addr + size*2, size,
 				 ESM_APU_SRCONVERTOR, es->apu[3]);
 	}
 
@@ -1281,7 +1264,7 @@ static int snd_es1968_pcm_prepare(snd_pcm_substream_t *substream)
 {
 	es1968_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	esschan_t *es = snd_magic_cast(esschan_t, runtime->private_data, return -ENXIO);
+	esschan_t *es = runtime->private_data;
 
 	es->dma_size = snd_pcm_lib_buffer_bytes(substream);
 	es->frag_size = snd_pcm_lib_period_bytes(substream);
@@ -1312,10 +1295,9 @@ static int snd_es1968_pcm_prepare(snd_pcm_substream_t *substream)
 static int snd_es1968_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
 {
 	es1968_t *chip = snd_pcm_substream_chip(substream);
-	esschan_t *es = snd_magic_cast(esschan_t, substream->runtime->private_data, return -ENXIO);
-	unsigned long flags;
+	esschan_t *es = substream->runtime->private_data;
 
-	spin_lock_irqsave(&chip->substream_lock, flags);
+	spin_lock(&chip->substream_lock);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
@@ -1336,14 +1318,14 @@ static int snd_es1968_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
 		snd_es1968_bob_dec(chip);
 		break;
 	}
-	spin_unlock_irqrestore(&chip->substream_lock, flags);
+	spin_unlock(&chip->substream_lock);
 	return 0;
 }
 
 static snd_pcm_uframes_t snd_es1968_pcm_pointer(snd_pcm_substream_t *substream)
 {
 	es1968_t *chip = snd_pcm_substream_chip(substream);
-	esschan_t *es = snd_magic_cast(esschan_t, substream->runtime->private_data, return -ENXIO);
+	esschan_t *es = substream->runtime->private_data;
 	unsigned int ptr;
 
 	ptr = snd_es1968_get_dma_ptr(chip, es) << es->wav_shift;
@@ -1408,8 +1390,8 @@ static int calc_available_memory_size(es1968_t *chip)
 	down(&chip->memory_mutex);
 	list_for_each(p, &chip->buf_list) {
 		esm_memory_t *buf = list_entry(p, esm_memory_t, list);
-		if (buf->empty && buf->size > max_size)
-			max_size = buf->size;
+		if (buf->empty && buf->buf.bytes > max_size)
+			max_size = buf->buf.bytes;
 	}
 	up(&chip->memory_mutex);
 	if (max_size >= 128*1024)
@@ -1427,24 +1409,25 @@ static esm_memory_t *snd_es1968_new_memory(es1968_t *chip, int size)
 	down(&chip->memory_mutex);
 	list_for_each(p, &chip->buf_list) {
 		buf = list_entry(p, esm_memory_t, list);
-		if (buf->empty && buf->size >= size)
+		if (buf->empty && buf->buf.bytes >= size)
 			goto __found;
 	}
 	up(&chip->memory_mutex);
 	return NULL;
 
 __found:
-	if (buf->size > size) {
+	if (buf->buf.bytes > size) {
 		esm_memory_t *chunk = kmalloc(sizeof(*chunk), GFP_KERNEL);
 		if (chunk == NULL) {
 			up(&chip->memory_mutex);
 			return NULL;
 		}
-		chunk->size = buf->size - size;
-		chunk->buf = buf->buf + size;
-		chunk->addr = buf->addr + size;
+		chunk->buf = buf->buf;
+		chunk->buf.bytes -= size;
+		chunk->buf.area += size;
+		chunk->buf.addr += size;
 		chunk->empty = 1;
-		buf->size = size;
+		buf->buf.bytes = size;
 		list_add(&chunk->list, &buf->list);
 	}
 	buf->empty = 0;
@@ -1462,7 +1445,7 @@ static void snd_es1968_free_memory(es1968_t *chip, esm_memory_t *buf)
 	if (buf->list.prev != &chip->buf_list) {
 		chunk = list_entry(buf->list.prev, esm_memory_t, list);
 		if (chunk->empty) {
-			chunk->size += buf->size;
+			chunk->buf.bytes += buf->buf.bytes;
 			list_del(&buf->list);
 			kfree(buf);
 			buf = chunk;
@@ -1471,7 +1454,7 @@ static void snd_es1968_free_memory(es1968_t *chip, esm_memory_t *buf)
 	if (buf->list.next != &chip->buf_list) {
 		chunk = list_entry(buf->list.next, esm_memory_t, list);
 		if (chunk->empty) {
-			buf->size += chunk->size;
+			buf->buf.bytes += chunk->buf.bytes;
 			list_del(&chunk->list);
 			kfree(chunk);
 		}
@@ -1485,7 +1468,7 @@ static void snd_es1968_free_dmabuf(es1968_t *chip)
 
 	if (! chip->dma.area)
 		return;
-	snd_dma_free_reserved(&chip->dma_dev);
+	snd_dma_reserve_buf(&chip->dma, snd_dma_pci_buf_id(chip->pci));
 	while ((p = chip->buf_list.next) != &chip->buf_list) {
 		esm_memory_t *chunk = list_entry(p, esm_memory_t, list);
 		list_del(p);
@@ -1499,22 +1482,22 @@ snd_es1968_init_dmabuf(es1968_t *chip)
 	int err;
 	esm_memory_t *chunk;
 
-	chip->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	chip->dma_dev.dev = snd_dma_pci_data(chip->pci);
-	chip->dma_dev.id = 0;
-	if (! snd_dma_get_reserved(&chip->dma_dev, &chip->dma)) {
-		err = snd_dma_alloc_pages_fallback(&chip->dma_dev, chip->total_bufsize, &chip->dma);
+	chip->dma.dev.type = SNDRV_DMA_TYPE_DEV;
+	chip->dma.dev.dev = snd_dma_pci_data(chip->pci);
+	if (! snd_dma_get_reserved_buf(&chip->dma, snd_dma_pci_buf_id(chip->pci))) {
+		err = snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV,
+						   snd_dma_pci_data(chip->pci),
+						   chip->total_bufsize, &chip->dma);
 		if (err < 0 || ! chip->dma.area) {
 			snd_printk("es1968: can't allocate dma pages for size %d\n",
 				   chip->total_bufsize);
 			return -ENOMEM;
 		}
 		if ((chip->dma.addr + chip->dma.bytes - 1) & ~((1 << 28) - 1)) {
-			snd_dma_free_pages(&chip->dma_dev, &chip->dma);
+			snd_dma_free_pages(&chip->dma);
 			snd_printk("es1968: DMA buffer beyond 256MB.\n");
 			return -ENOMEM;
 		}
-		snd_dma_set_reserved(&chip->dma_dev, &chip->dma);
 	}
 
 	INIT_LIST_HEAD(&chip->buf_list);
@@ -1525,9 +1508,10 @@ snd_es1968_init_dmabuf(es1968_t *chip)
 		return -ENOMEM;
 	}
 	memset(chip->dma.area, 0, ESM_MEM_ALIGN);
-	chunk->buf = chip->dma.area + ESM_MEM_ALIGN;
-	chunk->addr = chip->dma.addr + ESM_MEM_ALIGN;
-	chunk->size = chip->dma.bytes - ESM_MEM_ALIGN;
+	chunk->buf = chip->dma;
+	chunk->buf.area += ESM_MEM_ALIGN;
+	chunk->buf.addr += ESM_MEM_ALIGN;
+	chunk->buf.bytes -= ESM_MEM_ALIGN;
 	chunk->empty = 1;
 	list_add(&chunk->list, &chip->buf_list);
 
@@ -1541,11 +1525,11 @@ static int snd_es1968_hw_params(snd_pcm_substream_t *substream,
 {
 	es1968_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	esschan_t *chan = snd_magic_cast(esschan_t, runtime->private_data, return -ENXIO);
+	esschan_t *chan = runtime->private_data;
 	int size = params_buffer_bytes(hw_params);
 
 	if (chan->memory) {
-		if (chan->memory->size >= size) {
+		if (chan->memory->buf.bytes >= size) {
 			runtime->dma_bytes = size;
 			return 0;
 		}
@@ -1556,9 +1540,7 @@ static int snd_es1968_hw_params(snd_pcm_substream_t *substream,
 		// snd_printd("cannot allocate dma buffer: size = %d\n", size);
 		return -ENOMEM;
 	}
-	runtime->dma_bytes = size;
-	runtime->dma_area = chan->memory->buf;
-	runtime->dma_addr = chan->memory->addr;
+	snd_pcm_set_runtime_buffer(substream, &chan->memory->buf);
 	return 1; /* area was changed */
 }
 
@@ -1571,7 +1553,7 @@ static int snd_es1968_hw_free(snd_pcm_substream_t * substream)
 	
 	if (runtime->private_data == NULL)
 		return 0;
-	chan = snd_magic_cast(esschan_t, runtime->private_data, return -ENXIO);
+	chan = runtime->private_data;
 	if (chan->memory) {
 		snd_es1968_free_memory(chip, chan->memory);
 		chan->memory = NULL;
@@ -1616,14 +1598,13 @@ static int snd_es1968_playback_open(snd_pcm_substream_t *substream)
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	esschan_t *es;
 	int apu1;
-	unsigned long flags;
 
 	/* search 2 APUs */
 	apu1 = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_PLAY);
 	if (apu1 < 0)
 		return apu1;
 
-	es = snd_magic_kcalloc(esschan_t, 0, GFP_KERNEL);
+	es = kcalloc(1, sizeof(*es), GFP_KERNEL);
 	if (!es) {
 		snd_es1968_free_apu_pair(chip, apu1);
 		return -ENOMEM;
@@ -1645,9 +1626,9 @@ static int snd_es1968_playback_open(snd_pcm_substream_t *substream)
 	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
 				   1024);
 #endif
-	spin_lock_irqsave(&chip->substream_lock, flags);
+	spin_lock_irq(&chip->substream_lock);
 	list_add(&es->list, &chip->substream_list);
-	spin_unlock_irqrestore(&chip->substream_lock, flags);
+	spin_unlock_irq(&chip->substream_lock);
 
 	return 0;
 }
@@ -1658,7 +1639,6 @@ static int snd_es1968_capture_open(snd_pcm_substream_t *substream)
 	es1968_t *chip = snd_pcm_substream_chip(substream);
 	esschan_t *es;
 	int apu1, apu2;
-	unsigned long flags;
 
 	apu1 = snd_es1968_alloc_apu_pair(chip, ESM_APU_PCM_CAPTURE);
 	if (apu1 < 0)
@@ -1669,7 +1649,7 @@ static int snd_es1968_capture_open(snd_pcm_substream_t *substream)
 		return apu2;
 	}
 	
-	es = snd_magic_kcalloc(esschan_t, 0, GFP_KERNEL);
+	es = kcalloc(1, sizeof(*es), GFP_KERNEL);
 	if (!es) {
 		snd_es1968_free_apu_pair(chip, apu1);
 		snd_es1968_free_apu_pair(chip, apu2);
@@ -1692,10 +1672,10 @@ static int snd_es1968_capture_open(snd_pcm_substream_t *substream)
 	if ((es->mixbuf = snd_es1968_new_memory(chip, ESM_MIXBUF_SIZE)) == NULL) {
 		snd_es1968_free_apu_pair(chip, apu1);
 		snd_es1968_free_apu_pair(chip, apu2);
-		snd_magic_kfree(es);
+		kfree(es);
                 return -ENOMEM;
         }
-	memset(es->mixbuf->buf, 0, ESM_MIXBUF_SIZE);
+	memset(es->mixbuf->buf.area, 0, ESM_MIXBUF_SIZE);
 
 	runtime->private_data = es;
 	runtime->hw = snd_es1968_capture;
@@ -1705,9 +1685,9 @@ static int snd_es1968_capture_open(snd_pcm_substream_t *substream)
 	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
 				   1024);
 #endif
-	spin_lock_irqsave(&chip->substream_lock, flags);
+	spin_lock_irq(&chip->substream_lock);
 	list_add(&es->list, &chip->substream_list);
-	spin_unlock_irqrestore(&chip->substream_lock, flags);
+	spin_unlock_irq(&chip->substream_lock);
 
 	return 0;
 }
@@ -1716,16 +1696,15 @@ static int snd_es1968_playback_close(snd_pcm_substream_t * substream)
 {
 	es1968_t *chip = snd_pcm_substream_chip(substream);
 	esschan_t *es;
-	unsigned long flags;
 
 	if (substream->runtime->private_data == NULL)
 		return 0;
-	es = snd_magic_cast(esschan_t, substream->runtime->private_data, return -ENXIO);
-	spin_lock_irqsave(&chip->substream_lock, flags);
+	es = substream->runtime->private_data;
+	spin_lock_irq(&chip->substream_lock);
 	list_del(&es->list);
-	spin_unlock_irqrestore(&chip->substream_lock, flags);
+	spin_unlock_irq(&chip->substream_lock);
 	snd_es1968_free_apu_pair(chip, es->apu[0]);
-	snd_magic_kfree(es);
+	kfree(es);
 
 	return 0;
 }
@@ -1734,18 +1713,17 @@ static int snd_es1968_capture_close(snd_pcm_substream_t * substream)
 {
 	es1968_t *chip = snd_pcm_substream_chip(substream);
 	esschan_t *es;
-	unsigned long flags;
 
 	if (substream->runtime->private_data == NULL)
 		return 0;
-	es = snd_magic_cast(esschan_t, substream->runtime->private_data, return -ENXIO);
-	spin_lock_irqsave(&chip->substream_lock, flags);
+	es = substream->runtime->private_data;
+	spin_lock_irq(&chip->substream_lock);
 	list_del(&es->list);
-	spin_unlock_irqrestore(&chip->substream_lock, flags);
+	spin_unlock_irq(&chip->substream_lock);
 	snd_es1968_free_memory(chip, es->mixbuf);
 	snd_es1968_free_apu_pair(chip, es->apu[0]);
 	snd_es1968_free_apu_pair(chip, es->apu[2]);
-	snd_magic_kfree(es);
+	kfree(es);
 
 	return 0;
 }
@@ -1783,7 +1761,6 @@ static void __devinit es1968_measure_clock(es1968_t *chip)
 	int i, apu;
 	unsigned int pa, offset, t;
 	esm_memory_t *memory;
-	unsigned long flags;
 	struct timeval start_time, stop_time;
 
 	if (chip->clock == 0)
@@ -1800,11 +1777,11 @@ static void __devinit es1968_measure_clock(es1968_t *chip)
 		return;
 	}
 
-	memset(memory->buf, 0, CLOCK_MEASURE_BUFSIZE);
+	memset(memory->buf.area, 0, CLOCK_MEASURE_BUFSIZE);
 
-	wave_set_register(chip, apu << 3, (memory->addr - 0x10) & 0xfff8);
+	wave_set_register(chip, apu << 3, (memory->buf.addr - 0x10) & 0xfff8);
 
-	pa = (unsigned int)((memory->addr - chip->dma.addr) >> 1);
+	pa = (unsigned int)((memory->buf.addr - chip->dma.addr) >> 1);
 	pa |= 0x00400000;	/* System RAM (Bit 22) */
 
 	/* initialize apu */
@@ -1820,18 +1797,18 @@ static void __devinit es1968_measure_clock(es1968_t *chip)
 	apu_set_register(chip, apu, 9, 0xD000);
 	apu_set_register(chip, apu, 10, 0x8F08);
 	apu_set_register(chip, apu, 11, 0x0000);
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	outw(1, chip->io_port + 0x04); /* clear WP interrupts */
 	outw(inw(chip->io_port + ESM_PORT_HOST_IRQ) | ESM_HIRQ_DSIE, chip->io_port + ESM_PORT_HOST_IRQ); /* enable WP ints */
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 
 	snd_es1968_apu_set_freq(chip, apu, ((unsigned int)48000 << 16) / chip->clock); /* 48000 Hz */
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	__apu_set_register(chip, apu, 5, pa & 0xffff);
 	snd_es1968_trigger_apu(chip, apu, ESM_APU_16BITLINEAR);
 	do_gettimeofday(&start_time);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 #if 0
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout(HZ / 20); /* 50 msec */
@@ -1842,11 +1819,11 @@ static void __devinit es1968_measure_clock(es1968_t *chip)
 	 */
 	mdelay(50);
 #endif
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	offset = __apu_get_register(chip, apu, 5);
 	do_gettimeofday(&stop_time);
 	snd_es1968_trigger_apu(chip, apu, 0); /* stop */
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 
 	/* check the current position */
 	offset -= (pa & 0xffff);
@@ -1879,7 +1856,7 @@ static void __devinit es1968_measure_clock(es1968_t *chip)
 
 static void snd_es1968_pcm_free(snd_pcm_t *pcm)
 {
-	es1968_t *esm = snd_magic_cast(es1968_t, pcm->private_data, return);
+	es1968_t *esm = pcm->private_data;
 	snd_es1968_free_dmabuf(esm);
 	esm->pcm = NULL;
 }
@@ -1952,7 +1929,7 @@ static void snd_es1968_update_pcm(es1968_t *chip, esschan_t *es)
  */
 static void es1968_update_hw_volume(unsigned long private_data)
 {
-	es1968_t *chip = snd_magic_cast(es1968_t, (void*)private_data, return);
+	es1968_t *chip = (es1968_t *) private_data;
 	int x, val;
 
 	/* Figure out which volume control button was pushed,
@@ -1990,8 +1967,6 @@ static void es1968_update_hw_volume(unsigned long private_data)
 			if ((val & 0xff00) < 0x1f00)
 				val += 0x0100;
 		}
-		if (val == 0x1f1f)
-			val |= 0x8000;
 		snd_ac97_write_cache(chip->ac97, AC97_MASTER, val);
 		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
 			       &chip->master_volume->id);
@@ -2003,7 +1978,7 @@ static void es1968_update_hw_volume(unsigned long private_data)
  */
 static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	es1968_t *chip = snd_magic_cast(es1968_t, dev_id, return IRQ_NONE);
+	es1968_t *chip = dev_id;
 	u32 event;
 
 	if (!(event = inb(chip->io_port + 0x1A)))
@@ -2042,15 +2017,16 @@ static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id, struct pt_regs *r
 static int __devinit
 snd_es1968_mixer(es1968_t *chip)
 {
-	ac97_bus_t bus, *pbus;
-	ac97_t ac97;
+	ac97_bus_t *pbus;
+	ac97_template_t ac97;
 	snd_ctl_elem_id_t id;
 	int err;
+	static ac97_bus_ops_t ops = {
+		.write = snd_es1968_ac97_write,
+		.read = snd_es1968_ac97_read,
+	};
 
-	memset(&bus, 0, sizeof(bus));
-	bus.write = snd_es1968_ac97_write;
-	bus.read = snd_es1968_ac97_read;
-	if ((err = snd_ac97_bus(chip->card, &bus, &pbus)) < 0)
+	if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0)
 		return err;
 
 	memset(&ac97, 0, sizeof(ac97));
@@ -2420,7 +2396,7 @@ static void snd_es1968_start_irq(es1968_t *chip)
  */
 static int es1968_suspend(snd_card_t *card, unsigned int state)
 {
-	es1968_t *chip = snd_magic_cast(es1968_t, card->pm_private_data, return -EINVAL);
+	es1968_t *chip = card->pm_private_data;
 
 	if (! chip->do_pm)
 		return 0;
@@ -2435,7 +2411,7 @@ static int es1968_suspend(snd_card_t *card, unsigned int state)
 
 static int es1968_resume(snd_card_t *card, unsigned int state)
 {
-	es1968_t *chip = snd_magic_cast(es1968_t, card->pm_private_data, return -EINVAL);
+	es1968_t *chip = card->pm_private_data;
 
 	if (! chip->do_pm)
 		return 0;
@@ -2466,12 +2442,14 @@ static int es1968_resume(snd_card_t *card, unsigned int state)
 
 static int snd_es1968_free(es1968_t *chip)
 {
-	if (chip->res_io_port) {
+	if (chip->io_port) {
 		synchronize_irq(chip->irq);
 		outw(1, chip->io_port + 0x04); /* clear WP interrupts */
 		outw(0, chip->io_port + ESM_PORT_HOST_IRQ); /* disable IRQ */
 	}
 
+	if (chip->irq >= 0)
+		free_irq(chip->irq, (void *)chip);
 #ifdef SUPPORT_JOYSTICK
 	if (chip->res_joystick) {
 		gameport_unregister_port(&chip->gameport);
@@ -2482,19 +2460,14 @@ static int snd_es1968_free(es1968_t *chip)
 	snd_es1968_set_acpi(chip, ACPI_D3);
 	chip->master_switch = NULL;
 	chip->master_volume = NULL;
-	if (chip->res_io_port) {
-		release_resource(chip->res_io_port);
-		kfree_nocheck(chip->res_io_port);
-	}
-	if (chip->irq >= 0)
-		free_irq(chip->irq, (void *)chip);
-	snd_magic_kfree(chip);
+	pci_release_regions(chip->pci);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_es1968_dev_free(snd_device_t *device)
 {
-	es1968_t *chip = snd_magic_cast(es1968_t, device->device_data, return -ENXIO);
+	es1968_t *chip = device->device_data;
 	return snd_es1968_free(chip);
 }
 
@@ -2542,7 +2515,7 @@ static int __devinit snd_es1968_create(snd_card_t * card,
 		return -ENXIO;
 	}
 
-	chip = (es1968_t *) snd_magic_kcalloc(es1968_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (! chip)
 		return -ENOMEM;
 
@@ -2561,12 +2534,11 @@ static int __devinit snd_es1968_create(snd_card_t * card,
 	chip->playback_streams = play_streams;
 	chip->capture_streams = capt_streams;
 
-	chip->io_port = pci_resource_start(pci, 0);
-	if ((chip->res_io_port = request_region(chip->io_port, 0x100, "ESS Maestro")) == NULL) {
-		snd_printk("unable to grab region 0x%lx-0x%lx\n", chip->io_port, chip->io_port + 0x100 - 1);
-		snd_es1968_free(chip);
-		return -EBUSY;
+	if ((err = pci_request_regions(pci, "ESS Maestro")) < 0) {
+		kfree(chip);
+		return err;
 	}
+	chip->io_port = pci_resource_start(pci, 0);
 	if (request_irq(pci->irq, snd_es1968_interrupt, SA_INTERRUPT|SA_SHIRQ,
 			"ESS Maestro", (void*)chip)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index f21a17dda..9a0e1580b 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -40,13 +40,10 @@
 #define TEA575X_RADIO 1
 #endif
 
-#define chip_t fm801_t
-
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("ForteMedia FM801");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ForteMedia,FM801},"
+MODULE_SUPPORTED_DEVICE("{{ForteMedia,FM801},"
 		"{Genius,SoundMaker Live 5.1}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
@@ -64,16 +61,12 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for the FM801 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for the FM801 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable FM801 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(tea575x_tuner, bool, boot_devs, 0444);
 MODULE_PARM_DESC(tea575x_tuner, "Enable TEA575x tuner.");
-MODULE_PARM_SYNTAX(tea575x_tuner, SNDRV_ENABLE_DESC);
 
 /*
  *  Direct registers
@@ -161,7 +154,6 @@ struct _snd_fm801 {
 	int irq;
 
 	unsigned long port;	/* I/O port number */
-	struct resource *res_port;
 	unsigned int multichannel: 1,	/* multichannel support */
 		     secondary: 1;	/* secondary codec */
 	unsigned char secondary_addr;	/* address of the secondary codec */
@@ -233,7 +225,7 @@ static void snd_fm801_codec_write(ac97_t *ac97,
 				  unsigned short reg,
 				  unsigned short val)
 {
-	fm801_t *chip = snd_magic_cast(fm801_t, ac97->private_data, return);
+	fm801_t *chip = ac97->private_data;
 	int idx;
 
 	/*
@@ -264,7 +256,7 @@ static void snd_fm801_codec_write(ac97_t *ac97,
 
 static unsigned short snd_fm801_codec_read(ac97_t *ac97, unsigned short reg)
 {
-	fm801_t *chip = snd_magic_cast(fm801_t, ac97->private_data, return -ENXIO);
+	fm801_t *chip = ac97->private_data;
 	int idx;
 
 	/*
@@ -308,10 +300,8 @@ static unsigned int rates[] = {
   38400, 44100, 48000
 };
 
-#define RATES sizeof(rates) / sizeof(rates[0])
-
 static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
-	.count = RATES,
+	.count = ARRAY_SIZE(rates),
 	.list = rates,
 	.mask = 0,
 };
@@ -336,11 +326,11 @@ static unsigned short snd_fm801_rate_bits(unsigned int rate)
 {
 	unsigned int idx;
 
-	for (idx = 0; idx < 11; idx++)
+	for (idx = 0; idx < ARRAY_SIZE(rates); idx++)
 		if (rates[idx] == rate)
 			return idx;
 	snd_BUG();
-	return RATES - 1;
+	return ARRAY_SIZE(rates) - 1;
 }
 
 /*
@@ -487,42 +477,40 @@ static int snd_fm801_capture_prepare(snd_pcm_substream_t * substream)
 static snd_pcm_uframes_t snd_fm801_playback_pointer(snd_pcm_substream_t * substream)
 {
 	fm801_t *chip = snd_pcm_substream_chip(substream);
-	unsigned long flags;
 	size_t ptr;
 
 	if (!(chip->ply_ctrl & FM801_START))
 		return 0;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
 	ptr = chip->ply_pos + (chip->ply_count - 1) - inw(FM801_REG(chip, PLY_COUNT));
 	if (inw(FM801_REG(chip, IRQ_STATUS)) & FM801_IRQ_PLAYBACK) {
 		ptr += chip->ply_count;
 		ptr %= chip->ply_size;
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return bytes_to_frames(substream->runtime, ptr);
 }
 
 static snd_pcm_uframes_t snd_fm801_capture_pointer(snd_pcm_substream_t * substream)
 {
 	fm801_t *chip = snd_pcm_substream_chip(substream);
-	unsigned long flags;
 	size_t ptr;
 
 	if (!(chip->cap_ctrl & FM801_START))
 		return 0;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
 	ptr = chip->cap_pos + (chip->cap_count - 1) - inw(FM801_REG(chip, CAP_COUNT));
 	if (inw(FM801_REG(chip, IRQ_STATUS)) & FM801_IRQ_CAPTURE) {
 		ptr += chip->cap_count;
 		ptr %= chip->cap_size;
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return bytes_to_frames(substream->runtime, ptr);
 }
 
 static irqreturn_t snd_fm801_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	fm801_t *chip = snd_magic_cast(fm801_t, dev_id, return IRQ_NONE);
+	fm801_t *chip = dev_id;
 	unsigned short status;
 	unsigned int tmp;
 
@@ -680,7 +668,7 @@ static snd_pcm_ops_t snd_fm801_capture_ops = {
 
 static void snd_fm801_pcm_free(snd_pcm_t *pcm)
 {
-	fm801_t *chip = snd_magic_cast(fm801_t, pcm->private_data, return);
+	fm801_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1076,10 +1064,10 @@ static int snd_fm801_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 	int mask = (kcontrol->private_value >> 16) & 0xff;
 	int invert = (kcontrol->private_value >> 24) & 0xff;
 
-	spin_lock(&chip->reg_lock);
+	spin_lock_irq(&chip->reg_lock);
 	ucontrol->value.integer.value[0] = (inw(chip->port + reg) >> shift_left) & mask;
 	ucontrol->value.integer.value[1] = (inw(chip->port + reg) >> shift_right) & mask;
-	spin_unlock(&chip->reg_lock);
+	spin_unlock_irq(&chip->reg_lock);
 	if (invert) {
 		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
 		ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
@@ -1176,13 +1164,13 @@ FM801_SINGLE("IEC958 Playback Switch", FM801_GEN_CTRL, 2, 1, 0),
 
 static void snd_fm801_mixer_free_ac97_bus(ac97_bus_t *bus)
 {
-	fm801_t *chip = snd_magic_cast(fm801_t, bus->private_data, return);
+	fm801_t *chip = bus->private_data;
 	chip->ac97_bus = NULL;
 }
 
 static void snd_fm801_mixer_free_ac97(ac97_t *ac97)
 {
-	fm801_t *chip = snd_magic_cast(fm801_t, ac97->private_data, return);
+	fm801_t *chip = ac97->private_data;
 	if (ac97->num == 0) {
 		chip->ac97 = NULL;
 	} else {
@@ -1192,18 +1180,17 @@ static void snd_fm801_mixer_free_ac97(ac97_t *ac97)
 
 static int __devinit snd_fm801_mixer(fm801_t *chip)
 {
-	ac97_bus_t bus;
-	ac97_t ac97;
+	ac97_template_t ac97;
 	unsigned int i;
 	int err;
+	static ac97_bus_ops_t ops = {
+		.write = snd_fm801_codec_write,
+		.read = snd_fm801_codec_read,
+	};
 
-	memset(&bus, 0, sizeof(bus));
-	bus.write = snd_fm801_codec_write;
-	bus.read = snd_fm801_codec_read;
-	bus.private_data = chip;
-	bus.private_free = snd_fm801_mixer_free_ac97_bus;
-	if ((err = snd_ac97_bus(chip->card, &bus, &chip->ac97_bus)) < 0)
+	if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0)
 		return err;
+	chip->ac97_bus->private_free = snd_fm801_mixer_free_ac97_bus;
 
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = chip;
@@ -1245,20 +1232,17 @@ static int snd_fm801_free(fm801_t *chip)
 #ifdef TEA575X_RADIO
 	snd_tea575x_exit(&chip->tea);
 #endif
-	if (chip->res_port) {
-		release_resource(chip->res_port);
-		kfree_nocheck(chip->res_port);
-	}
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void *)chip);
+	pci_release_regions(chip->pci);
 
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_fm801_dev_free(snd_device_t *device)
 {
-	fm801_t *chip = snd_magic_cast(fm801_t, device->device_data, return -ENXIO);
+	fm801_t *chip = device->device_data;
 	return snd_fm801_free(chip);
 }
 
@@ -1279,19 +1263,18 @@ static int __devinit snd_fm801_create(snd_card_t * card,
 	*rchip = NULL;
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
-	chip = snd_magic_kcalloc(fm801_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
 	chip->card = card;
 	chip->pci = pci;
 	chip->irq = -1;
-	chip->port = pci_resource_start(pci, 0);
-	if ((chip->res_port = request_region(chip->port, 0x80, "FM801")) == NULL) {
-		snd_printk("unable to grab region 0x%lx-0x%lx\n", chip->port, chip->port + 0x80 - 1);
-		snd_fm801_free(chip);
-		return -EBUSY;
+	if ((err = pci_request_regions(pci, "FM801")) < 0) {
+		kfree(chip);
+		return err;
 	}
+	chip->port = pci_resource_start(pci, 0);
 	if (request_irq(pci->irq, snd_fm801_interrupt, SA_INTERRUPT|SA_SHIRQ, "FM801", (void *)chip)) {
 		snd_printk("unable to grab IRQ %d\n", chip->irq);
 		snd_fm801_free(chip);
diff --git a/sound/pci/ice1712/Makefile b/sound/pci/ice1712/Makefile
index f1e417ca0..d98d17797 100644
--- a/sound/pci/ice1712/Makefile
+++ b/sound/pci/ice1712/Makefile
@@ -5,7 +5,7 @@
 
 snd-ice17xx-ak4xxx-objs := ak4xxx.o
 snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o
-snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o
+snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o
diff --git a/sound/pci/ice1712/ak4xxx.c b/sound/pci/ice1712/ak4xxx.c
index 4a318a6ec..e601381e2 100644
--- a/sound/pci/ice1712/ak4xxx.c
+++ b/sound/pci/ice1712/ak4xxx.c
@@ -33,7 +33,6 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("ICEnsemble ICE17xx <-> AK4xxx AD/DA chip interface");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
 
 static void snd_ice1712_akm4xxx_lock(akm4xxx_t *ak, int chip)
 {
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
index a182b8b27..e9a3b055f 100644
--- a/sound/pci/ice1712/aureon.c
+++ b/sound/pci/ice1712/aureon.c
@@ -75,7 +75,7 @@
 #define WM_DAC_ATTEN		0x00	/* DAC1-8 analog attenuation */
 #define WM_DAC_MASTER_ATTEN	0x08	/* DAC master analog attenuation */
 #define WM_DAC_DIG_ATTEN	0x09	/* DAC1-8 digital attenuation */
-#define WM_DAC_DIG_MATER_ATTEN	0x11	/* DAC master digital attenuation */
+#define WM_DAC_DIG_MASTER_ATTEN	0x11	/* DAC master digital attenuation */
 #define WM_PHASE_SWAP		0x12	/* DAC phase */
 #define WM_DAC_CTRL1		0x13	/* DAC control bits */
 #define WM_MUTE			0x14	/* mute controls */
@@ -148,21 +148,28 @@ static unsigned short wm_get(ice1712_t *ice, int reg)
 		ice->akm[0].images[reg + 1];
 }
 
+/*
+ * set the register value of WM codec
+ */
+static void wm_put_nocache(ice1712_t *ice, int reg, unsigned short val)
+{
+	aureon_spi_write(ice, AUREON_WM_CS, (reg << 9) | (val & 0x1ff), 16);
+}
+
 /*
  * set the register value of WM codec and remember it
  */
 static void wm_put(ice1712_t *ice, int reg, unsigned short val)
 {
-	aureon_spi_write(ice, AUREON_WM_CS, (reg << 9) | (val & 0x1ff), 16);
+	wm_put_nocache(ice, reg, val);
 	reg <<= 1;
 	ice->akm[0].images[reg] = val >> 8;
 	ice->akm[0].images[reg + 1] = val;
 }
 
 /*
- * DAC mute control
  */
-static int wm_dac_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int aureon_mono_bool_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 	uinfo->count = 1;
@@ -171,6 +178,11 @@ static int wm_dac_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinf
 	return 0;
 }
 
+/*
+ * DAC mute control
+ */
+#define wm_dac_mute_info	aureon_mono_bool_info
+
 static int wm_dac_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
@@ -205,9 +217,10 @@ static int wm_dac_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * uco
  */
 static int wm_dac_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
 {
+	int voices = kcontrol->private_value >> 8;
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-	uinfo->count = 1;
-	uinfo->value.integer.min = 0;		/* mute */
+	uinfo->count = voices;
+	uinfo->value.integer.min = 0;		/* mute (-101dB) */
 	uinfo->value.integer.max = 101;		/* 0dB */
 	return 0;
 }
@@ -215,19 +228,20 @@ static int wm_dac_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
 static int wm_dac_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
-	int idx;
+	int i, idx, ofs, voices;
 	unsigned short vol;
 
+	voices = kcontrol->private_value >> 8;
+	ofs = kcontrol->private_value & 0xff;
 	down(&ice->gpio_mutex);
-	if (kcontrol->private_value)
-		idx = WM_DAC_MASTER_ATTEN;
-	else
-		idx  = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + WM_DAC_ATTEN;
-	vol = wm_get(ice, idx) & 0x7f;
-	if (vol <= 0x1a)
-		ucontrol->value.integer.value[0] = 0;
-	else
-		ucontrol->value.integer.value[0] = vol - 0x1a;
+	for (i = 0; i < voices; i++) {
+		idx  = WM_DAC_ATTEN + ofs + i;
+		vol = wm_get(ice, idx) & 0x7f;
+		if (vol <= 0x1a)
+			ucontrol->value.integer.value[i] = 0;
+		else
+			ucontrol->value.integer.value[i] = vol - 0x1a;
+	}
 	up(&ice->gpio_mutex);
 	return 0;
 }
@@ -235,23 +249,69 @@ static int wm_dac_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontr
 static int wm_dac_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
-	int idx;
+	int i, idx, ofs, voices;
 	unsigned short ovol, nvol;
-	int change;
+	int change = 0;
 
+	voices = kcontrol->private_value >> 8;
+	ofs = kcontrol->private_value & 0xff;
 	snd_ice1712_save_gpio_status(ice);
-	if (kcontrol->private_value)
-		idx = WM_DAC_MASTER_ATTEN;
-	else
-		idx  = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + WM_DAC_ATTEN;
-	nvol = ucontrol->value.integer.value[0] + 0x1a;
-	ovol = wm_get(ice, idx) & 0x7f;
-	change = (ovol != nvol);
-	if (change) {
-		if (nvol <= 0x1a && ovol <= 0x1a)
-			change = 0;
-		else
-			wm_put(ice, idx, nvol | 0x180); /* update on zero detect */
+	for (i = 0; i < voices; i++) {
+		idx  = WM_DAC_ATTEN + ofs + i;
+		nvol = ucontrol->value.integer.value[i] + 0x1a;
+		ovol = wm_get(ice, idx) & 0x7f;
+		if (ovol != nvol) {
+			if (nvol <= 0x1a && ovol <= 0x1a)
+				continue;
+			wm_put(ice, idx, nvol | 0x80); /* zero-detect, prelatch */
+			wm_put_nocache(ice, idx, nvol | 0x180); /* update */
+			change = 1;
+		}
+	}
+	snd_ice1712_restore_gpio_status(ice);
+	return change;
+}
+
+/* digital master volume */
+#define MASTER_0dB 0xff
+#define MASTER_RES 128	/* -64dB */
+#define MASTER_MIN (MASTER_0dB - MASTER_RES)
+static int wm_master_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;		/* mute (-64dB) */
+	uinfo->value.integer.max = MASTER_RES;	/* 0dB */
+	return 0;
+}
+
+static int wm_master_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned short val;
+
+	down(&ice->gpio_mutex);
+	val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
+	val = val > MASTER_MIN ? (val - MASTER_MIN) : 0;
+	ucontrol->value.integer.value[0] = val;
+	up(&ice->gpio_mutex);
+	return 0;
+}
+
+static int wm_master_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned short ovol, nvol;
+	int change = 0;
+
+	snd_ice1712_save_gpio_status(ice);
+	nvol = ucontrol->value.integer.value[0];
+	nvol = (nvol ? (nvol + MASTER_MIN) : 0) & 0xff;
+	ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
+	if (ovol != nvol) {
+		wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
+		wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
+		change = 1;
 	}
 	snd_ice1712_restore_gpio_status(ice);
 	return change;
@@ -260,10 +320,10 @@ static int wm_dac_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontr
 /*
  * ADC mute control
  */
-static int wm_adc_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int wm_adc_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-	uinfo->count = 1;
+	uinfo->count = 2;
 	uinfo->value.integer.min = 0;
 	uinfo->value.integer.max = 1;
 	return 0;
@@ -273,10 +333,13 @@ static int wm_adc_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucont
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
 	unsigned short val;
+	int i;
 
 	down(&ice->gpio_mutex);
-	val = wm_get(ice, snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)+WM_ADC_GAIN);
-	ucontrol->value.integer.value[0] = ~val>>5 & 0x1;
+	for (i = 0; i < 2; i++) {
+		val = wm_get(ice, WM_ADC_GAIN + i);
+		ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
+	}
 	up(&ice->gpio_mutex);
 	return 0;
 }
@@ -285,14 +348,17 @@ static int wm_adc_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * uco
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
 	unsigned short new, old;
-	int change;
+	int i, change = 0;
 
 	snd_ice1712_save_gpio_status(ice);
-	old = wm_get(ice, snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)+WM_ADC_GAIN);
-	new = (~ucontrol->value.integer.value[0]<<5&0x20) | (old&~0x20);
-	change = (new != old);
-	if (change)
-		wm_put(ice, snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)+WM_ADC_GAIN, new);
+	for (i = 0; i < 2; i++) {
+		old = wm_get(ice, WM_ADC_GAIN + i);
+		new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
+		if (new != old) {
+			wm_put(ice, snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)+WM_ADC_GAIN, new);
+			change = 1;
+		}
+	}
 	snd_ice1712_restore_gpio_status(ice);
 
 	return change;
@@ -304,7 +370,7 @@ static int wm_adc_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * uco
 static int wm_adc_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-	uinfo->count = 1;
+	uinfo->count = 2;
 	uinfo->value.integer.min = 0;		/* -12dB */
 	uinfo->value.integer.max = 0x1f;	/* 19dB */
 	return 0;
@@ -313,13 +379,15 @@ static int wm_adc_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
 static int wm_adc_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
-	int idx;
+	int i, idx;
 	unsigned short vol;
 
 	down(&ice->gpio_mutex);
-	idx  = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + WM_ADC_GAIN;
-	vol = wm_get(ice, idx) & 0x1f;
-	ucontrol->value.integer.value[0] = vol;
+	for (i = 0; i < 2; i++) {
+		idx = WM_ADC_GAIN + i;
+		vol = wm_get(ice, idx) & 0x1f;
+		ucontrol->value.integer.value[i] = vol;
+	}
 	up(&ice->gpio_mutex);
 	return 0;
 }
@@ -327,17 +395,20 @@ static int wm_adc_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontr
 static int wm_adc_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
-	int idx;
+	int i, idx;
 	unsigned short ovol, nvol;
-	int change;
+	int change = 0;
 
 	snd_ice1712_save_gpio_status(ice);
-	idx  = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + WM_ADC_GAIN;
-	nvol = ucontrol->value.integer.value[0];
-	ovol = wm_get(ice, idx);
-	change = ((ovol & 0x1f)  != nvol);
-	if (change)
-		wm_put(ice, idx, nvol | (ovol & ~0x1f));
+	for (i = 0; i < 2; i++) {
+		idx  = WM_ADC_GAIN + i;
+		nvol = ucontrol->value.integer.value[i];
+		ovol = wm_get(ice, idx);
+		if ((ovol & 0x1f) != nvol) {
+			wm_put(ice, idx, nvol | (ovol & ~0x1f));
+			change = 1;
+		}
+	}
 	snd_ice1712_restore_gpio_status(ice);
 	return change;
 }
@@ -355,7 +426,7 @@ static int wm_adc_mux_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
 		"AC97"		//AIN5
 	};
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
+	uinfo->count = 2;
 	uinfo->value.enumerated.items = 5;
 	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
 		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
@@ -420,14 +491,7 @@ static int aureon_get_headphone_amp(ice1712_t *ice)
 	return ( tmp & AUREON_HP_SEL )!= 0;
 }
 
-static int aureon_bool_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
-{
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-	uinfo->count = 1;
-	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = 1;
-	return 0;
-}
+#define aureon_hpamp_info	aureon_mono_bool_info
 
 static int aureon_hpamp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
@@ -448,6 +512,9 @@ static int aureon_hpamp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
 /*
  * Deemphasis
  */
+
+#define aureon_deemp_info	aureon_mono_bool_info
+
 static int aureon_deemp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
@@ -519,44 +586,67 @@ static int aureon_oversampling_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
  * mixers
  */
 
-static snd_kcontrol_new_t aureon51_dac_control __devinitdata = {
-	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name = "DAC Volume",
-	.count = 6,
-	.info = wm_dac_vol_info,
-	.get = wm_dac_vol_get,
-	.put = wm_dac_vol_put,
-};
-
-static snd_kcontrol_new_t aureon71_dac_control __devinitdata = {
-	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name = "DAC Volume",
-	.count = 8,
-	.info = wm_dac_vol_info,
-	.get = wm_dac_vol_get,
-	.put = wm_dac_vol_put,
-};
-
-static snd_kcontrol_new_t wm_controls[] __devinitdata = {
+static snd_kcontrol_new_t aureon_dac_controls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.info = wm_dac_mute_info,
-		.get = wm_dac_mute_get,
-		.put = wm_dac_mute_put,
+		.name = "Front Playback Volume",
+		.info = wm_dac_vol_info,
+		.get = wm_dac_vol_get,
+		.put = wm_dac_vol_put,
+		.private_value = (2 << 8) | 0
 	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Volume",
+		.name = "Rear Playback Volume",
 		.info = wm_dac_vol_info,
 		.get = wm_dac_vol_get,
 		.put = wm_dac_vol_put,
-		.private_value = 1,
+		.private_value = (2 << 8) | 2
 	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "ADC Switch",
-		.count = 2,
+		.name = "Center Playback Volume",
+		.info = wm_dac_vol_info,
+		.get = wm_dac_vol_get,
+		.put = wm_dac_vol_put,
+		.private_value = (1 << 8) | 4
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "LFE Playback Volume",
+		.info = wm_dac_vol_info,
+		.get = wm_dac_vol_get,
+		.put = wm_dac_vol_put,
+		.private_value = (1 << 8) | 5
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Side Playback Volume",
+		.info = wm_dac_vol_info,
+		.get = wm_dac_vol_get,
+		.put = wm_dac_vol_put,
+		.private_value = (2 << 8) | 6
+	}
+};
+
+static snd_kcontrol_new_t wm_controls[] __devinitdata = {
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.info = wm_dac_mute_info,
+		.get = wm_dac_mute_get,
+		.put = wm_dac_mute_put,
+ 	},
+ 	{
+ 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Volume",
+		.info = wm_master_vol_info,
+		.get = wm_master_vol_get,
+		.put = wm_master_vol_put,
+ 	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Capture Switch",
 		.info = wm_adc_mute_info,
 		.get = wm_adc_mute_get,
 		.put = wm_adc_mute_put,
@@ -564,15 +654,14 @@ static snd_kcontrol_new_t wm_controls[] __devinitdata = {
 	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "ADC Volume",
-		.count = 2,
+		.name = "Capture Volume",
 		.info = wm_adc_vol_info,
 		.get = wm_adc_vol_get,
 		.put = wm_adc_vol_put,
 	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Capture Route",
+		.name = "Capture Source",
 		.info = wm_adc_mux_info,
 		.get = wm_adc_mux_get,
 		.put = wm_adc_mux_put,
@@ -580,14 +669,14 @@ static snd_kcontrol_new_t wm_controls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Headphone Amplifier Switch",
-		.info = aureon_bool_info,
+		.info = aureon_hpamp_info,
 		.get = aureon_hpamp_get,
 		.put = aureon_hpamp_put
 	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "DAC Deemphasis Switch",
-		.info = aureon_bool_info,
+		.info = aureon_deemp_info,
 		.get = aureon_deemp_get,
 		.put = aureon_deemp_put
 	},
@@ -603,15 +692,17 @@ static snd_kcontrol_new_t wm_controls[] __devinitdata = {
 
 static int __devinit aureon_add_controls(ice1712_t *ice)
 {
-	unsigned int i;
+	unsigned int i, counts;
 	int err;
 
+	counts = ARRAY_SIZE(aureon_dac_controls);
 	if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
-		err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon51_dac_control, ice));
-	else
-		err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon71_dac_control, ice));
-	if (err < 0)
-		return err;
+		counts--; /* no side */
+	for (i = 0; i < counts; i++) {
+		err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
+		if (err < 0)
+			return err;
+	}
 
 	for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
 		err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
@@ -718,15 +809,15 @@ static int __devinit aureon_init(ice1712_t *ice)
 
 	if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
 		ice->num_total_dacs = 6;
-		ice->num_total_adcs = 6;
+		ice->num_total_adcs = 2;
 	} else {
 		/* aureon 7.1 and prodigy 7.1 */
 		ice->num_total_dacs = 8;
-		ice->num_total_adcs = 8;
+		ice->num_total_adcs = 2;
 	}
 
 	/* to remeber the register values */
-	ice->akm = snd_kcalloc(sizeof(akm4xxx_t), GFP_KERNEL);
+	ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
 	if (! ice->akm)
 		return -ENOMEM;
 	ice->akm_codecs = 1;
@@ -780,7 +871,7 @@ static int __devinit aureon_init(ice1712_t *ice)
  */
 
 static unsigned char aureon51_eeprom[] __devinitdata = {
-	0x2a,	/* SYSCONF: clock 512, mpu401, spdif-in/ADC, 3DACs */
+	0x0a,	/* SYSCONF: clock 512, spdif-in/ADC, 3DACs */
 	0x80,	/* ACLINK: I2S */
 	0xf8,	/* I2S: vol, 96k, 24bit, 192k */
 	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
@@ -796,7 +887,7 @@ static unsigned char aureon51_eeprom[] __devinitdata = {
 };
 
 static unsigned char aureon71_eeprom[] __devinitdata = {
-	0x2b,	/* SYSCONF: clock 512, mpu401, spdif-in/ADC, 4DACs */
+	0x0b,	/* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
 	0x80,	/* ACLINK: I2S */
 	0xf8,	/* I2S: vol, 96k, 24bit, 192k */
 	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
@@ -812,7 +903,7 @@ static unsigned char aureon71_eeprom[] __devinitdata = {
 };
 
 static unsigned char prodigy71_eeprom[] __devinitdata = {
-	0x2b,	/* SYSCONF: clock 512, mpu401, spdif-in/ADC, 4DACs */
+	0x0b,	/* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
 	0x80,	/* ACLINK: I2S */
 	0xf8,	/* I2S: vol, 96k, 24bit, 192k */
 	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
@@ -837,6 +928,7 @@ struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
 		.build_controls = aureon_add_controls,
 		.eeprom_size = sizeof(aureon51_eeprom),
 		.eeprom_data = aureon51_eeprom,
+		.driver = "Aureon51",
 	},
 	{
 		.subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
@@ -846,6 +938,7 @@ struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
 		.build_controls = aureon_add_controls,
 		.eeprom_size = sizeof(aureon71_eeprom),
 		.eeprom_data = aureon71_eeprom,
+		.driver = "Aureon71",
 	},
  	{
  		.subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
@@ -855,6 +948,7 @@ struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
  		.build_controls = aureon_add_controls,
  		.eeprom_size = sizeof(aureon71_eeprom),
  		.eeprom_data = aureon71_eeprom,
+		.driver = "Aureon71",
 	},
 	{
 		.subvendor = VT1724_SUBDEVICE_PRODIGY71,
@@ -864,6 +958,7 @@ struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
 		.build_controls = aureon_add_controls,
 		.eeprom_size = sizeof(prodigy71_eeprom),
 		.eeprom_data = prodigy71_eeprom,
+		.driver = "Prodigy71", /* should be identical with Aureon71 */
 	},
 	{ } /* terminator */
 };
diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c
index 85fc5e4f6..9eb245bb3 100644
--- a/sound/pci/ice1712/delta.c
+++ b/sound/pci/ice1712/delta.c
@@ -126,7 +126,7 @@ static void ap_cs8427_codec_deassert(ice1712_t *ice, unsigned char tmp)
 /* sequential write */
 static int ap_cs8427_sendbytes(snd_i2c_device_t *device, unsigned char *bytes, int count)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, device->bus->private_data, return -EIO);
+	ice1712_t *ice = device->bus->private_data;
 	int res = count;
 	unsigned char tmp;
 
@@ -143,7 +143,7 @@ static int ap_cs8427_sendbytes(snd_i2c_device_t *device, unsigned char *bytes, i
 /* sequential read */
 static int ap_cs8427_readbytes(snd_i2c_device_t *device, unsigned char *bytes, int count)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, device->bus->private_data, return -EIO);
+	ice1712_t *ice = device->bus->private_data;
 	int res = count;
 	unsigned char tmp;
 	
diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c
index 9509e4840..02593f98c 100644
--- a/sound/pci/ice1712/ews.c
+++ b/sound/pci/ice1712/ews.c
@@ -45,7 +45,7 @@
 /* send SDA and SCL */
 static void ewx_i2c_setlines(snd_i2c_bus_t *bus, int clk, int data)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, bus->private_data, return);
+	ice1712_t *ice = bus->private_data;
 	unsigned char tmp = 0;
 	if (clk)
 		tmp |= ICE1712_EWX2496_SERIAL_CLOCK;
@@ -57,13 +57,13 @@ static void ewx_i2c_setlines(snd_i2c_bus_t *bus, int clk, int data)
 
 static int ewx_i2c_getclock(snd_i2c_bus_t *bus)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, bus->private_data, return -EIO);
+	ice1712_t *ice = bus->private_data;
 	return snd_ice1712_read(ice, ICE1712_IREG_GPIO_DATA) & ICE1712_EWX2496_SERIAL_CLOCK ? 1 : 0;
 }
 
 static int ewx_i2c_getdata(snd_i2c_bus_t *bus, int ack)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, bus->private_data, return -EIO);
+	ice1712_t *ice = bus->private_data;
 	int bit;
 	/* set RW pin to low */
 	snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ~ICE1712_EWX2496_RW);
@@ -80,7 +80,7 @@ static int ewx_i2c_getdata(snd_i2c_bus_t *bus, int ack)
 
 static void ewx_i2c_start(snd_i2c_bus_t *bus)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, bus->private_data, return);
+	ice1712_t *ice = bus->private_data;
 	unsigned char mask;
 
 	snd_ice1712_save_gpio_status(ice);
@@ -99,13 +99,13 @@ static void ewx_i2c_start(snd_i2c_bus_t *bus)
 
 static void ewx_i2c_stop(snd_i2c_bus_t *bus)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, bus->private_data, return);
+	ice1712_t *ice = bus->private_data;
 	snd_ice1712_restore_gpio_status(ice);
 }
 
 static void ewx_i2c_direction(snd_i2c_bus_t *bus, int clock, int data)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, bus->private_data, return);
+	ice1712_t *ice = bus->private_data;
 	unsigned char mask = 0;
 
 	if (clock)
@@ -223,6 +223,7 @@ static void snd_ice1712_ews_cs8404_spdif_write(ice1712_t *ice, unsigned char bit
 	switch (ice->eeprom.subvendor) {
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
+	case ICE1712_SUBDEVICE_PHASE88:
 		snd_runtime_check(snd_i2c_sendbytes(ice->cs8404, &bits, 1) == 1, goto _error);
 		break;
 	case ICE1712_SUBDEVICE_EWS88D:
@@ -410,6 +411,7 @@ static int __devinit snd_ice1712_ews_init(ice1712_t *ice)
 		break;	
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
+	case ICE1712_SUBDEVICE_PHASE88:
 		ice->num_total_dacs = 8;
 		ice->num_total_adcs = 8;
 		break;
@@ -440,6 +442,7 @@ static int __devinit snd_ice1712_ews_init(ice1712_t *ice)
 		break;
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
+	case ICE1712_SUBDEVICE_PHASE88:
 		if ((err = snd_i2c_device_create(ice->i2c, "CS8404", ICE1712_EWS88MT_CS8404_ADDR, &ice->cs8404)) < 0)
 			return err;
 		if ((err = snd_i2c_device_create(ice->i2c, "PCF8574 (1st)", ICE1712_EWS88MT_INPUT_ADDR, &ice->i2cdevs[0])) < 0)
@@ -470,6 +473,7 @@ static int __devinit snd_ice1712_ews_init(ice1712_t *ice)
 		break;
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
+	case ICE1712_SUBDEVICE_PHASE88:
 	case ICE1712_SUBDEVICE_EWS88D:
 		/* set up CS8404 */
 		ice->spdif.ops.open = ews88_open_spdif;
@@ -498,6 +502,7 @@ static int __devinit snd_ice1712_ews_init(ice1712_t *ice)
 	switch (ice->eeprom.subvendor) {
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
+	case ICE1712_SUBDEVICE_PHASE88:
 		err = snd_ice1712_akm4xxx_init(ak, &akm_ews88mt, &akm_ews88mt_priv, ice);
 		break;
 	case ICE1712_SUBDEVICE_EWX2496:
@@ -924,6 +929,7 @@ static int __devinit snd_ice1712_ews_add_controls(ice1712_t *ice)
 	case ICE1712_SUBDEVICE_EWX2496:
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
+	case ICE1712_SUBDEVICE_PHASE88:
 	case ICE1712_SUBDEVICE_DMX6FIRE:
 		err = snd_ice1712_akm4xxx_build_controls(ice);
 		if (err < 0)
@@ -942,6 +948,7 @@ static int __devinit snd_ice1712_ews_add_controls(ice1712_t *ice)
 		break;
 	case ICE1712_SUBDEVICE_EWS88MT:
 	case ICE1712_SUBDEVICE_EWS88MT_NEW:
+	case ICE1712_SUBDEVICE_PHASE88:
 		err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_ice1712_ews88mt_input_sense, ice));
 		if (err < 0)
 			return err;
@@ -991,6 +998,13 @@ struct snd_ice1712_card_info snd_ice1712_ews_cards[] __devinitdata = {
 		.chip_init = snd_ice1712_ews_init,
 		.build_controls = snd_ice1712_ews_add_controls,
 	},
+	{
+		.subvendor = ICE1712_SUBDEVICE_PHASE88,
+		.name = "TerraTec Phase88",
+		.model = "phase88",
+		.chip_init = snd_ice1712_ews_init,
+		.build_controls = snd_ice1712_ews_add_controls,
+	},
 	{
 		.subvendor = ICE1712_SUBDEVICE_EWS88D,
 		.name = "TerraTec EWS88D",
diff --git a/sound/pci/ice1712/ews.h b/sound/pci/ice1712/ews.h
index c5670a148..a12a0b053 100644
--- a/sound/pci/ice1712/ews.h
+++ b/sound/pci/ice1712/ews.h
@@ -29,13 +29,15 @@
 		"{TerraTec,EWX 24/96},"\
 		"{TerraTec,EWS 88MT},"\
 		"{TerraTec,EWS 88D},"\
-		"{TerraTec,DMX 6Fire},"
+		"{TerraTec,DMX 6Fire},"\
+		"{TerraTec,Phase 88},"
 
 #define ICE1712_SUBDEVICE_EWX2496	0x3b153011
 #define ICE1712_SUBDEVICE_EWS88MT	0x3b151511
 #define ICE1712_SUBDEVICE_EWS88MT_NEW	0x3b152511
 #define ICE1712_SUBDEVICE_EWS88D	0x3b152b11
 #define ICE1712_SUBDEVICE_DMX6FIRE	0x3b153811
+#define ICE1712_SUBDEVICE_PHASE88	0x3b155111
 
 /* entry point */
 extern struct snd_ice1712_card_info snd_ice1712_ews_cards[];
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index d1f1ec28a..194dc5431 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -73,8 +73,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("ICEnsemble ICE1712 (Envy24)");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{"
+MODULE_SUPPORTED_DEVICE("{"
 	       HOONTECH_DEVICE_DESC
 	       DELTA_DEVICE_DESC
 	       EWS_DEVICE_DESC
@@ -91,19 +90,14 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for ICE1712 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for ICE1712 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable ICE1712 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(omni, bool, boot_devs, 0444);
 MODULE_PARM_DESC(omni, "Enable Midiman M-Audio Delta Omni I/O support.");
-MODULE_PARM_SYNTAX(omni, SNDRV_ENABLED "," SNDRV_ENABLE_DESC);
 module_param_array(cs8427_timeout, int, boot_devs, 0444);
 MODULE_PARM_DESC(cs8427_timeout, "Define reset timeout for cs8427 chip in msec resolution.");
-MODULE_PARM_SYNTAX(cs8427_timeout, SNDRV_ENABLED ", allows:{{1,1000}},default=500,skill:advanced");
 module_param_array(model, charp, boot_devs, 0444);
 MODULE_PARM_DESC(model, "Use the given board model.");
 
@@ -416,7 +410,7 @@ int __devinit snd_ice1712_init_cs8427(ice1712_t *ice, int addr)
 
 static irqreturn_t snd_ice1712_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, dev_id, return IRQ_NONE);
+	ice1712_t *ice = dev_id;
 	unsigned char status;
 	int handled = 0;
 
@@ -590,7 +584,7 @@ static int snd_ice1712_playback_prepare(snd_pcm_substream_t * substream)
 	rate = (runtime->rate * 8192) / 375;
 	if (rate > 0x000fffff)
 		rate = 0x000fffff;
-	spin_lock(&ice->reg_lock);
+	spin_lock_irq(&ice->reg_lock);
 	outb(0, ice->ddma_port + 15);
 	outb(ICE1712_DMA_MODE_WRITE | ICE1712_DMA_AUTOINIT, ice->ddma_port + 0x0b);
 	outl(runtime->dma_addr, ice->ddma_port + 0);
@@ -603,7 +597,7 @@ static int snd_ice1712_playback_prepare(snd_pcm_substream_t * substream)
 	snd_ice1712_write(ice, ICE1712_IREG_PBK_COUNT_HI, period_size >> 8);
 	snd_ice1712_write(ice, ICE1712_IREG_PBK_LEFT, 0);
 	snd_ice1712_write(ice, ICE1712_IREG_PBK_RIGHT, 0);
-	spin_unlock(&ice->reg_lock);
+	spin_unlock_irq(&ice->reg_lock);
 	return 0;
 }
 
@@ -626,7 +620,7 @@ static int snd_ice1712_playback_ds_prepare(snd_pcm_substream_t * substream)
 	ice->playback_con_active_buf[substream->number] = 0;
 	ice->playback_con_virt_addr[substream->number] = runtime->dma_addr;
 	chn = substream->number * 2;
-	spin_lock(&ice->reg_lock);
+	spin_lock_irq(&ice->reg_lock);
 	snd_ice1712_ds_write(ice, chn, ICE1712_DSC_ADDR0, runtime->dma_addr);
 	snd_ice1712_ds_write(ice, chn, ICE1712_DSC_COUNT0, period_size);
 	snd_ice1712_ds_write(ice, chn, ICE1712_DSC_ADDR1, runtime->dma_addr + (runtime->periods > 1 ? period_size + 1 : 0));
@@ -638,7 +632,7 @@ static int snd_ice1712_playback_ds_prepare(snd_pcm_substream_t * substream)
 		snd_ice1712_ds_write(ice, chn + 1, ICE1712_DSC_RATE, rate);
 		snd_ice1712_ds_write(ice, chn + 1, ICE1712_DSC_VOLUME, 0);
 	}
-	spin_unlock(&ice->reg_lock);
+	spin_unlock_irq(&ice->reg_lock);
 	return 0;
 }
 
@@ -656,13 +650,13 @@ static int snd_ice1712_capture_prepare(snd_pcm_substream_t * substream)
 		tmp &= ~0x04;
 	if (runtime->channels == 2)
 		tmp &= ~0x02;
-	spin_lock(&ice->reg_lock);
+	spin_lock_irq(&ice->reg_lock);
 	outl(ice->capture_con_virt_addr = runtime->dma_addr, ICEREG(ice, CONCAP_ADDR));
 	outw(buf_size, ICEREG(ice, CONCAP_COUNT));
 	snd_ice1712_write(ice, ICE1712_IREG_CAP_COUNT_HI, period_size >> 8);
 	snd_ice1712_write(ice, ICE1712_IREG_CAP_COUNT_LO, period_size & 0xff);
 	snd_ice1712_write(ice, ICE1712_IREG_CAP_CTRL, tmp);
-	spin_unlock(&ice->reg_lock);
+	spin_unlock_irq(&ice->reg_lock);
 	snd_ac97_set_rate(ice->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);
 	return 0;
 }
@@ -874,7 +868,7 @@ static snd_pcm_ops_t snd_ice1712_capture_ops = {
 
 static void snd_ice1712_pcm_free(snd_pcm_t *pcm)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, pcm->private_data, return);
+	ice1712_t *ice = pcm->private_data;
 	ice->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -912,7 +906,7 @@ static int __devinit snd_ice1712_pcm(ice1712_t * ice, int device, snd_pcm_t ** r
 
 static void snd_ice1712_pcm_free_ds(snd_pcm_t *pcm)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, pcm->private_data, return);
+	ice1712_t *ice = pcm->private_data;
 	ice->pcm_ds = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -952,10 +946,8 @@ static int __devinit snd_ice1712_pcm_ds(ice1712_t * ice, int device, snd_pcm_t *
 static unsigned int rates[] = { 8000, 9600, 11025, 12000, 16000, 22050, 24000,
 				32000, 44100, 48000, 64000, 88200, 96000 };
 
-#define RATES sizeof(rates) / sizeof(rates[0])
-
 static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
-	.count = RATES,
+	.count = ARRAY_SIZE(rates),
 	.list = rates,
 	.mask = 0,
 };
@@ -1077,11 +1069,11 @@ static int snd_ice1712_playback_pro_prepare(snd_pcm_substream_t * substream)
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
 
 	ice->playback_pro_size = snd_pcm_lib_buffer_bytes(substream);
-	spin_lock(&ice->reg_lock);
+	spin_lock_irq(&ice->reg_lock);
 	outl(substream->runtime->dma_addr, ICEMT(ice, PLAYBACK_ADDR));
 	outw((ice->playback_pro_size >> 2) - 1, ICEMT(ice, PLAYBACK_SIZE));
 	outw((snd_pcm_lib_period_bytes(substream) >> 2) - 1, ICEMT(ice, PLAYBACK_COUNT));
-	spin_unlock(&ice->reg_lock);
+	spin_unlock_irq(&ice->reg_lock);
 
 	return 0;
 }
@@ -1100,11 +1092,11 @@ static int snd_ice1712_capture_pro_prepare(snd_pcm_substream_t * substream)
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
 
 	ice->capture_pro_size = snd_pcm_lib_buffer_bytes(substream);
-	spin_lock(&ice->reg_lock);
+	spin_lock_irq(&ice->reg_lock);
 	outl(substream->runtime->dma_addr, ICEMT(ice, CAPTURE_ADDR));
 	outw((ice->capture_pro_size >> 2) - 1, ICEMT(ice, CAPTURE_SIZE));
 	outw((snd_pcm_lib_period_bytes(substream) >> 2) - 1, ICEMT(ice, CAPTURE_COUNT));
-	spin_unlock(&ice->reg_lock);
+	spin_unlock_irq(&ice->reg_lock);
 	return 0;
 }
 
@@ -1238,7 +1230,7 @@ static int snd_ice1712_capture_pro_close(snd_pcm_substream_t * substream)
 
 static void snd_ice1712_pcm_profi_free(snd_pcm_t *pcm)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, pcm->private_data, return);
+	ice1712_t *ice = pcm->private_data;
 	ice->pcm_pro = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1511,21 +1503,26 @@ static int __devinit snd_ice1712_build_pro_mixer(ice1712_t *ice)
 
 static void snd_ice1712_mixer_free_ac97(ac97_t *ac97)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, ac97->private_data, return);
+	ice1712_t *ice = ac97->private_data;
 	ice->ac97 = NULL;
 }
 
 static int __devinit snd_ice1712_ac97_mixer(ice1712_t * ice)
 {
-	int err;
-	ac97_t ac97;
-	ac97_bus_t bus, *pbus;
+	int err, bus_num = 0;
+	ac97_template_t ac97;
+	ac97_bus_t *pbus;
+	static ac97_bus_ops_t con_ops = {
+		.write = snd_ice1712_ac97_write,
+		.read = snd_ice1712_ac97_read,
+	};
+	static ac97_bus_ops_t pro_ops = {
+		.write = snd_ice1712_pro_ac97_write,
+		.read = snd_ice1712_pro_ac97_read,
+	};
 
 	if (ice_has_con_ac97(ice)) {
-		memset(&bus, 0, sizeof(bus));
-		bus.write = snd_ice1712_ac97_write;
-		bus.read = snd_ice1712_ac97_read;
-		if ((err = snd_ac97_bus(ice->card, &bus, &pbus)) < 0)
+		if ((err = snd_ac97_bus(ice->card, bus_num++, &con_ops, NULL, &pbus)) < 0)
 			return err;
 		memset(&ac97, 0, sizeof(ac97));
 		ac97.private_data = ice;
@@ -1540,10 +1537,7 @@ static int __devinit snd_ice1712_ac97_mixer(ice1712_t * ice)
 	}
 
 	if (! (ice->eeprom.data[ICE_EEP1_ACLINK] & ICE1712_CFG_PRO_I2S)) {
-		memset(&bus, 0, sizeof(bus));
-		bus.write = snd_ice1712_pro_ac97_write;
-		bus.read = snd_ice1712_pro_ac97_read;
-		if ((err = snd_ac97_bus(ice->card, &bus, &pbus)) < 0)
+		if ((err = snd_ac97_bus(ice->card, bus_num, &pro_ops, NULL, &pbus)) < 0)
 			return err;
 		memset(&ac97, 0, sizeof(ac97));
 		ac97.private_data = ice;
@@ -1570,7 +1564,7 @@ static inline unsigned int eeprom_double(ice1712_t *ice, int idx)
 static void snd_ice1712_proc_read(snd_info_entry_t *entry, 
 				  snd_info_buffer_t * buffer)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, entry->private_data, return);
+	ice1712_t *ice = entry->private_data;
 	unsigned int idx;
 
 	snd_iprintf(buffer, "%s\n\n", ice->card->longname);
@@ -2468,7 +2462,7 @@ static int __devinit snd_ice1712_build_controls(ice1712_t *ice)
 
 static int snd_ice1712_free(ice1712_t *ice)
 {
-	if (ice->res_port == NULL)
+	if (! ice->port)
 		goto __hw_end;
 	/* mask all interrupts */
 	outb(0xc0, ICEMT(ice, IRQ));
@@ -2479,30 +2473,16 @@ static int snd_ice1712_free(ice1712_t *ice)
 		synchronize_irq(ice->irq);
 		free_irq(ice->irq, (void *) ice);
 	}
-	if (ice->res_port) {
-		release_resource(ice->res_port);
-		kfree_nocheck(ice->res_port);
-	}
-	if (ice->res_ddma_port) {
-		release_resource(ice->res_ddma_port);
-		kfree_nocheck(ice->res_ddma_port);
-	}
-	if (ice->res_dmapath_port) {
-		release_resource(ice->res_dmapath_port);
-		kfree_nocheck(ice->res_dmapath_port);
-	}
-	if (ice->res_profi_port) {
-		release_resource(ice->res_profi_port);
-		kfree_nocheck(ice->res_profi_port);
-	}
+	if (ice->port)
+		pci_release_regions(ice->pci);
 	snd_ice1712_akm4xxx_free(ice);
-	snd_magic_kfree(ice);
+	kfree(ice);
 	return 0;
 }
 
 static int snd_ice1712_dev_free(snd_device_t *device)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, device->device_data, return -ENXIO);
+	ice1712_t *ice = device->device_data;
 	return snd_ice1712_free(ice);
 }
 
@@ -2531,7 +2511,7 @@ static int __devinit snd_ice1712_create(snd_card_t * card,
 		return -ENXIO;
 	}
 
-	ice = snd_magic_kcalloc(ice1712_t, 0, GFP_KERNEL);
+	ice = kcalloc(1, sizeof(*ice), GFP_KERNEL);
 	if (ice == NULL)
 		return -ENOMEM;
 	ice->omni = omni ? 1 : 0;
@@ -2555,36 +2535,21 @@ static int __devinit snd_ice1712_create(snd_card_t * card,
 	ice->card = card;
 	ice->pci = pci;
 	ice->irq = -1;
-	ice->port = pci_resource_start(pci, 0);
-	ice->ddma_port = pci_resource_start(pci, 1);
-	ice->dmapath_port = pci_resource_start(pci, 2);
-	ice->profi_port = pci_resource_start(pci, 3);
 	pci_set_master(pci);
 	pci_write_config_word(ice->pci, 0x40, 0x807f);
 	pci_write_config_word(ice->pci, 0x42, 0x0006);
 	snd_ice1712_proc_init(ice);
 	synchronize_irq(pci->irq);
 
-	if ((ice->res_port = request_region(ice->port, 32, "ICE1712 - Controller")) == NULL) {
-		snd_printk("unable to grab ports 0x%lx-0x%lx\n", ice->port, ice->port + 32 - 1);
-		snd_ice1712_free(ice);
-		return -EIO;
-	}
-	if ((ice->res_ddma_port = request_region(ice->ddma_port, 16, "ICE1712 - DDMA")) == NULL) {
-		snd_printk("unable to grab ports 0x%lx-0x%lx\n", ice->ddma_port, ice->ddma_port + 16 - 1);
-		snd_ice1712_free(ice);
-		return -EIO;
-	}
-	if ((ice->res_dmapath_port = request_region(ice->dmapath_port, 16, "ICE1712 - DMA path")) == NULL) {
-		snd_printk("unable to grab ports 0x%lx-0x%lx\n", ice->dmapath_port, ice->dmapath_port + 16 - 1);
-		snd_ice1712_free(ice);
-		return -EIO;
-	}
-	if ((ice->res_profi_port = request_region(ice->profi_port, 64, "ICE1712 - Professional")) == NULL) {
-		snd_printk("unable to grab ports 0x%lx-0x%lx\n", ice->profi_port, ice->profi_port + 16 - 1);
-		snd_ice1712_free(ice);
-		return -EIO;
+	if ((err = pci_request_regions(pci, "ICE1712")) < 0) {
+		kfree(ice);
+		return err;
 	}
+	ice->port = pci_resource_start(pci, 0);
+	ice->ddma_port = pci_resource_start(pci, 1);
+	ice->dmapath_port = pci_resource_start(pci, 2);
+	ice->profi_port = pci_resource_start(pci, 3);
+
 	if (request_irq(pci->irq, snd_ice1712_interrupt, SA_INTERRUPT|SA_SHIRQ, "ICE1712", (void *) ice)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
 		snd_ice1712_free(ice);
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index f8233bfdc..1d8998f7f 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -294,13 +294,9 @@ struct _snd_ice1712 {
 	int irq;
 
 	unsigned long port;
-	struct resource *res_port;
 	unsigned long ddma_port;
-	struct resource *res_ddma_port;
 	unsigned long dmapath_port;
-	struct resource *res_dmapath_port;
 	unsigned long profi_port;
-	struct resource *res_profi_port;
 
 	struct pci_dev *pci;
 	snd_card_t *card;
@@ -368,8 +364,6 @@ struct _snd_ice1712 {
 	struct semaphore gpio_mutex;
 };
 
-#define chip_t ice1712_t
-
 
 /*
  * gpio access functions
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 60fb18980..b3b632194 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -44,16 +44,19 @@
 #include "amp.h"
 #include "revo.h"
 #include "aureon.h"
+#include "vt1720_mobo.h"
+#include "pontis.h"
 
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{"
+MODULE_SUPPORTED_DEVICE("{"
 	       REVO_DEVICE_DESC
 	       AMP_AUDIO2000_DEVICE_DESC
 	       AUREON_DEVICE_DESC
+	       VT1720_MOBO_DEVICE_DESC
+	       PONTIS_DEVICE_DESC
 		"{VIA,VT1720},"
 		"{VIA,VT1724},"
 		"{ICEnsemble,Generic ICE1724},"
@@ -68,13 +71,10 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for ICE1724 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for ICE1724 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable ICE1724 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(model, charp, boot_devs, 0444);
 MODULE_PARM_DESC(model, "Use the given board model.");
 
@@ -190,21 +190,26 @@ static void snd_vt1724_set_gpio_dir(ice1712_t *ice, unsigned int data)
 static void snd_vt1724_set_gpio_mask(ice1712_t *ice, unsigned int data)
 {
 	outw(data, ICEREG1724(ice, GPIO_WRITE_MASK));
-	outb((data >> 16) & 0xff, ICEREG1724(ice, GPIO_WRITE_MASK_22));
+	if (! ice->vt1720) /* VT1720 supports only 16 GPIO bits */
+		outb((data >> 16) & 0xff, ICEREG1724(ice, GPIO_WRITE_MASK_22));
 	inw(ICEREG1724(ice, GPIO_WRITE_MASK)); /* dummy read for pci-posting */
 }
 
 static void snd_vt1724_set_gpio_data(ice1712_t *ice, unsigned int data)
 {
 	outw(data, ICEREG1724(ice, GPIO_DATA));
-	outb(data >> 16, ICEREG1724(ice, GPIO_DATA_22));
+	if (! ice->vt1720)
+		outb(data >> 16, ICEREG1724(ice, GPIO_DATA_22));
 	inw(ICEREG1724(ice, GPIO_DATA)); /* dummy read for pci-posting */
 }
 
 static unsigned int snd_vt1724_get_gpio_data(ice1712_t *ice)
 {
 	unsigned int data;
-	data = (unsigned int)inb(ICEREG1724(ice, GPIO_DATA_22));
+	if (! ice->vt1720)
+		data = (unsigned int)inb(ICEREG1724(ice, GPIO_DATA_22));
+	else
+		data = 0;
 	data = (data << 16) | inw(ICEREG1724(ice, GPIO_DATA));
 	return data;
 }
@@ -215,7 +220,7 @@ static unsigned int snd_vt1724_get_gpio_data(ice1712_t *ice)
 
 static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, dev_id, return IRQ_NONE);
+	ice1712_t *ice = dev_id;
 	unsigned char status;
 	int handled = 0;
 
@@ -230,7 +235,7 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id, struct pt_regs *r
 		if ((status & VT1724_IRQ_MPU_RX)||(status & VT1724_IRQ_MPU_TX)) {
 			if (ice->rmidi[0])
 				snd_mpu401_uart_interrupt(irq, ice->rmidi[0]->private_data, regs);
-			outb(VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX, ICEREG1724(ice, IRQSTAT));
+			outb(status & (VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX), ICEREG1724(ice, IRQSTAT));
 			status &= ~(VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX);
 		}
 		if (status & VT1724_IRQ_MTPCM) {
@@ -317,6 +322,13 @@ static snd_pcm_hw_constraint_list_t hw_constraints_rates_192 = {
 	.mask = 0,
 };
 
+struct vt1724_pcm_reg {
+	unsigned int addr;	/* ADDR register offset */
+	unsigned int size;	/* SIZE register offset */
+	unsigned int count;	/* COUNT register offset */
+	unsigned int start;	/* start & pause bit */
+};
+
 static int snd_vt1724_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
 {
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
@@ -327,8 +339,10 @@ static int snd_vt1724_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
 
 	what = 0;
 	snd_pcm_group_for_each(pos, substream) {
+		struct vt1724_pcm_reg *reg;
 		s = snd_pcm_group_substream_entry(pos);
-		what |= (unsigned long)(s->runtime->private_data);
+		reg = s->runtime->private_data;
+		what |= reg->start;
 		snd_pcm_trigger_done(s, substream);
 	}
 
@@ -371,12 +385,26 @@ static int snd_vt1724_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
 #define DMA_PAUSES	(VT1724_RDMA0_PAUSE|VT1724_PDMA0_PAUSE|VT1724_RDMA1_PAUSE|\
 	VT1724_PDMA1_PAUSE|VT1724_PDMA2_PAUSE|VT1724_PDMA3_PAUSE|VT1724_PDMA4_PAUSE)
 
+static int get_max_rate(ice1712_t *ice)
+{
+	if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
+		if ((ice->eeprom.data[ICE_EEP2_I2S] & 0x08) && !ice->vt1720)
+			return 192000;
+		else
+			return 96000;
+	} else
+		return 48000;
+}
+
 static void snd_vt1724_set_pro_rate(ice1712_t *ice, unsigned int rate, int force)
 {
 	unsigned long flags;
 	unsigned char val, old;
 	unsigned int i;
 
+	if (rate > get_max_rate(ice))
+		return;
+
 	spin_lock_irqsave(&ice->reg_lock, flags);
 	if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) || 
 	    (inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) {
@@ -410,8 +438,10 @@ static void snd_vt1724_set_pro_rate(ice1712_t *ice, unsigned int rate, int force
 		val = 0;
 		break;
 	}
-	outb(val, ICEMT1724(ice, RATE));
-	if (rate == ice->cur_rate) {
+	old = inb(ICEMT1724(ice, RATE));
+	if (old != val)
+		outb(val, ICEMT1724(ice, RATE));
+	else if (rate == ice->cur_rate) {
 		spin_unlock_irqrestore(&ice->reg_lock, flags);
 		return;
 	}
@@ -419,7 +449,7 @@ static void snd_vt1724_set_pro_rate(ice1712_t *ice, unsigned int rate, int force
 	ice->cur_rate = rate;
 
 	/* check MT02 */
-	if (ice->eeprom.data[ICE_EEP2_ACLINK] & 0x80) {
+	if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
 		val = old = inb(ICEMT1724(ice, I2S_FORMAT));
 		if (rate > 96000)
 			val |= VT1724_MT_I2S_MCLK_128X; /* 128x MCLK */
@@ -446,15 +476,6 @@ static void snd_vt1724_set_pro_rate(ice1712_t *ice, unsigned int rate, int force
 		if (ice->akm[i].ops.set_rate_val)
 			ice->akm[i].ops.set_rate_val(&ice->akm[i], rate);
 	}
-
-	/* set up AC97 registers if needed */
-	if (! (ice->eeprom.data[ICE_EEP2_ACLINK] & 0x80) && ice->ac97) {
-		snd_ac97_set_rate(ice->ac97, AC97_PCM_FRONT_DAC_RATE, rate);
-		snd_ac97_set_rate(ice->ac97, AC97_PCM_SURR_DAC_RATE, rate);
-		snd_ac97_set_rate(ice->ac97, AC97_PCM_LFE_DAC_RATE, rate);
-		snd_ac97_set_rate(ice->ac97, AC97_SPDIF, rate);
-		snd_ac97_set_rate(ice->ac97, AC97_PCM_LR_ADC_RATE, rate);
-	}
 }
 
 static int snd_vt1724_pcm_hw_params(snd_pcm_substream_t * substream,
@@ -518,7 +539,7 @@ static int snd_vt1724_playback_pro_prepare(snd_pcm_substream_t * substream)
 	unsigned char val;
 	unsigned int size;
 
-	spin_lock(&ice->reg_lock);
+	spin_lock_irq(&ice->reg_lock);
 	val = (8 - substream->runtime->channels) >> 1;
 	outb(val, ICEMT1724(ice, BURST));
 
@@ -533,7 +554,7 @@ static int snd_vt1724_playback_pro_prepare(snd_pcm_substream_t * substream)
 	outw(size, ICEMT1724(ice, PLAYBACK_COUNT));
 	outb(size >> 16, ICEMT1724(ice, PLAYBACK_COUNT) + 2);
 
-	spin_unlock(&ice->reg_lock);
+	spin_unlock_irq(&ice->reg_lock);
 
 	// printk("pro prepare: ch = %d, addr = 0x%x, buffer = 0x%x, period = 0x%x\n", substream->runtime->channels, (unsigned int)substream->runtime->dma_addr, snd_pcm_lib_buffer_bytes(substream), snd_pcm_lib_period_bytes(substream));
 	return 0;
@@ -562,7 +583,9 @@ static snd_pcm_uframes_t snd_vt1724_playback_pro_pointer(snd_pcm_substream_t * s
 	ptr = inl(ICEMT1724(ice, PLAYBACK_SIZE)) & 0xffffff;
 	ptr = (ptr + 1) << 2;
 	ptr = bytes_to_frames(substream->runtime, ptr);
-	if (ptr <= substream->runtime->buffer_size)
+	if (! ptr)
+		;
+	else if (ptr <= substream->runtime->buffer_size)
 		ptr = substream->runtime->buffer_size - ptr;
 	else {
 		snd_printd("ice1724: invalid ptr %d (size=%d)\n", (int)ptr, (int)substream->runtime->buffer_size);
@@ -572,29 +595,23 @@ static snd_pcm_uframes_t snd_vt1724_playback_pro_pointer(snd_pcm_substream_t * s
 	return ptr;
 }
 
-struct vt1724_pcm_reg {
-	unsigned int addr;	/* ADDR register offset */
-	unsigned int size;	/* SIZE register offset */
-	unsigned int count;	/* COUNT register offset */
-	unsigned int start;	/* start bit */
-	unsigned int pause;	/* pause bit */
-};
-
-static int snd_vt1724_pcm_prepare(snd_pcm_substream_t *substream, const struct vt1724_pcm_reg *reg)
+static int snd_vt1724_pcm_prepare(snd_pcm_substream_t *substream)
 {
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
+	struct vt1724_pcm_reg *reg = substream->runtime->private_data;
 
-	spin_lock(&ice->reg_lock);
+	spin_lock_irq(&ice->reg_lock);
 	outl(substream->runtime->dma_addr, ice->profi_port + reg->addr);
 	outw((snd_pcm_lib_buffer_bytes(substream) >> 2) - 1, ice->profi_port + reg->size);
 	outw((snd_pcm_lib_period_bytes(substream) >> 2) - 1, ice->profi_port + reg->count);
-	spin_unlock(&ice->reg_lock);
+	spin_unlock_irq(&ice->reg_lock);
 	return 0;
 }
 
-static snd_pcm_uframes_t snd_vt1724_pcm_pointer(snd_pcm_substream_t *substream, const struct vt1724_pcm_reg *reg)
+static snd_pcm_uframes_t snd_vt1724_pcm_pointer(snd_pcm_substream_t *substream)
 {
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
+	struct vt1724_pcm_reg *reg = substream->runtime->private_data;
 	size_t ptr;
 
 	if (!(inl(ICEMT1724(ice, DMA_CONTROL)) & reg->start))
@@ -607,7 +624,9 @@ static snd_pcm_uframes_t snd_vt1724_pcm_pointer(snd_pcm_substream_t *substream,
 	ptr = inw(ice->profi_port + reg->size);
 	ptr = (ptr + 1) << 2;
 	ptr = bytes_to_frames(substream->runtime, ptr);
-	if (ptr <= substream->runtime->buffer_size)
+	if (! ptr)
+		;
+	else if (ptr <= substream->runtime->buffer_size)
 		ptr = substream->runtime->buffer_size - ptr;
 	else {
 		snd_printd("ice1724: invalid ptr %d (size=%d)\n", (int)ptr, (int)substream->runtime->buffer_size);
@@ -617,24 +636,20 @@ static snd_pcm_uframes_t snd_vt1724_pcm_pointer(snd_pcm_substream_t *substream,
 #endif
 }
 
-const static struct vt1724_pcm_reg vt1724_capture_pro_reg = {
+static struct vt1724_pcm_reg vt1724_playback_pro_reg = {
+	.addr = VT1724_MT_PLAYBACK_ADDR,
+	.size = VT1724_MT_PLAYBACK_SIZE,
+	.count = VT1724_MT_PLAYBACK_COUNT,
+	.start = VT1724_PDMA0_START,
+};
+
+static struct vt1724_pcm_reg vt1724_capture_pro_reg = {
 	.addr = VT1724_MT_CAPTURE_ADDR,
 	.size = VT1724_MT_CAPTURE_SIZE,
 	.count = VT1724_MT_CAPTURE_COUNT,
 	.start = VT1724_RDMA0_START,
-	.pause = VT1724_RDMA0_PAUSE,
 };
 
-static int snd_vt1724_capture_pro_prepare(snd_pcm_substream_t * substream)
-{
-	return snd_vt1724_pcm_prepare(substream, &vt1724_capture_pro_reg);
-}
-
-static snd_pcm_uframes_t snd_vt1724_capture_pro_pointer(snd_pcm_substream_t * substream)
-{
-	return snd_vt1724_pcm_pointer(substream, &vt1724_capture_pro_reg);
-}
-
 static snd_pcm_hardware_t snd_vt1724_playback_pro =
 {
 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
@@ -698,9 +713,10 @@ static snd_pcm_hardware_t snd_vt1724_2ch_stereo =
 static int set_rate_constraints(ice1712_t *ice, snd_pcm_substream_t *substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	if (ice->eeprom.data[ICE_EEP2_ACLINK] & 0x80) {
+	if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
 		/* I2S */
-		if (ice->eeprom.data[ICE_EEP2_I2S] & 0x08)
+		/* VT1720 doesn't support more than 96kHz */
+		if ((ice->eeprom.data[ICE_EEP2_I2S] & 0x08) && !ice->vt1720)
 			return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates_192);
 		else {
 			runtime->hw.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_96000;
@@ -709,25 +725,14 @@ static int set_rate_constraints(ice1712_t *ice, snd_pcm_substream_t *substream)
 		}
 	} else if (ice->ac97) {
 		/* ACLINK */
-		int ratec;
-		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-			ratec = AC97_RATES_FRONT_DAC;
-		else
-			ratec = AC97_RATES_ADC;
-		runtime->hw.rates = ice->ac97->rates[ratec];
 		runtime->hw.rate_max = 48000;
-		if (runtime->hw.rates == SNDRV_PCM_RATE_48000) {
-			runtime->hw.rate_min = 48000;
-			return 0;
-		} else {
-			runtime->hw.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000;
-			return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates_48);
-		}
+		runtime->hw.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000;
+		return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates_48);
 	}
 	return 0;
 }
 
-/* multi-channel playback needs alignment 8x32bit regarless of the channels
+/* multi-channel playback needs alignment 8x32bit regardless of the channels
  * actually used
  */
 #define VT1724_BUFFER_ALIGN	0x20
@@ -738,7 +743,7 @@ static int snd_vt1724_playback_pro_open(snd_pcm_substream_t * substream)
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
 	int chs;
 
-	runtime->private_data = (void*)VT1724_PDMA0_START; /* irq/status/trigger bit */
+	runtime->private_data = &vt1724_playback_pro_reg;
 	ice->playback_pro_substream = substream;
 	runtime->hw = snd_vt1724_playback_pro;
 	snd_pcm_set_sync(substream);
@@ -767,12 +772,16 @@ static int snd_vt1724_capture_pro_open(snd_pcm_substream_t * substream)
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
-	runtime->private_data = (void*)VT1724_RDMA0_START; /* irq/status/trigger bit */
+	runtime->private_data = &vt1724_capture_pro_reg;
 	ice->capture_pro_substream = substream;
 	runtime->hw = snd_vt1724_2ch_stereo;
 	snd_pcm_set_sync(substream);
 	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
 	set_rate_constraints(ice, substream);
+	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+				   VT1724_BUFFER_ALIGN);
+	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+				   VT1724_BUFFER_ALIGN);
 	return 0;
 }
 
@@ -814,9 +823,9 @@ static snd_pcm_ops_t snd_vt1724_capture_pro_ops = {
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_vt1724_pcm_hw_params,
 	.hw_free =	snd_vt1724_pcm_hw_free,
-	.prepare =	snd_vt1724_capture_pro_prepare,
+	.prepare =	snd_vt1724_pcm_prepare,
 	.trigger =	snd_vt1724_pcm_trigger,
-	.pointer =	snd_vt1724_capture_pro_pointer,
+	.pointer =	snd_vt1724_pcm_pointer,
 };
 
 static int __devinit snd_vt1724_pcm_profi(ice1712_t * ice, int device)
@@ -848,40 +857,60 @@ static int __devinit snd_vt1724_pcm_profi(ice1712_t * ice, int device)
  * SPDIF PCM
  */
 
-const static struct vt1724_pcm_reg vt1724_playback_spdif_reg = {
+static struct vt1724_pcm_reg vt1724_playback_spdif_reg = {
 	.addr = VT1724_MT_PDMA4_ADDR,
 	.size = VT1724_MT_PDMA4_SIZE,
 	.count = VT1724_MT_PDMA4_COUNT,
 	.start = VT1724_PDMA4_START,
-	.pause = VT1724_PDMA4_PAUSE,
 };
 
-const static struct vt1724_pcm_reg vt1724_capture_spdif_reg = {
+static struct vt1724_pcm_reg vt1724_capture_spdif_reg = {
 	.addr = VT1724_MT_RDMA1_ADDR,
 	.size = VT1724_MT_RDMA1_SIZE,
 	.count = VT1724_MT_RDMA1_COUNT,
 	.start = VT1724_RDMA1_START,
-	.pause = VT1724_RDMA1_PAUSE,
 };
 
-static int snd_vt1724_playback_spdif_prepare(snd_pcm_substream_t * substream)
+/* update spdif control bits; call with reg_lock */
+static void update_spdif_bits(ice1712_t *ice, unsigned int val)
 {
-	return snd_vt1724_pcm_prepare(substream, &vt1724_playback_spdif_reg);
-}
+	unsigned char cbit, disabled;
 
-static snd_pcm_uframes_t snd_vt1724_playback_spdif_pointer(snd_pcm_substream_t * substream)
-{
-	return snd_vt1724_pcm_pointer(substream, &vt1724_playback_spdif_reg);
+	cbit = inb(ICEREG1724(ice, SPDIF_CFG));
+	disabled = cbit & ~VT1724_CFG_SPDIF_OUT_EN;
+	if (cbit != disabled)
+		outb(disabled, ICEREG1724(ice, SPDIF_CFG));
+	outw(val, ICEMT1724(ice, SPDIF_CTRL));
+	if (cbit != disabled)
+		outb(cbit, ICEREG1724(ice, SPDIF_CFG));
+	outw(val, ICEMT1724(ice, SPDIF_CTRL));
 }
 
-static int snd_vt1724_capture_spdif_prepare(snd_pcm_substream_t * substream)
+/* update SPDIF control bits according to the given rate */
+static void update_spdif_rate(ice1712_t *ice, unsigned int rate)
 {
-	return snd_vt1724_pcm_prepare(substream, &vt1724_capture_spdif_reg);
+	unsigned int val, nval;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ice->reg_lock, flags);
+	nval = val = inw(ICEMT1724(ice, SPDIF_CTRL));
+	nval &= ~(7 << 12);
+	switch (rate) {
+	case 44100: break;
+	case 48000: nval |= 2 << 12; break;
+	case 32000: nval |= 3 << 12; break;
+	}
+	if (val != nval)
+		update_spdif_bits(ice, nval);
+	spin_unlock_irqrestore(&ice->reg_lock, flags);
 }
 
-static snd_pcm_uframes_t snd_vt1724_capture_spdif_pointer(snd_pcm_substream_t * substream)
+static int snd_vt1724_playback_spdif_prepare(snd_pcm_substream_t * substream)
 {
-	return snd_vt1724_pcm_pointer(substream, &vt1724_capture_spdif_reg);
+	ice1712_t *ice = snd_pcm_substream_chip(substream);
+	if (! ice->force_pdma4)
+		update_spdif_rate(ice, substream->runtime->rate);
+	return snd_vt1724_pcm_prepare(substream);
 }
 
 static int snd_vt1724_playback_spdif_open(snd_pcm_substream_t *substream)
@@ -889,7 +918,7 @@ static int snd_vt1724_playback_spdif_open(snd_pcm_substream_t *substream)
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
-	runtime->private_data = (void*)VT1724_PDMA4_START; /* irq/status/trigger bit */
+	runtime->private_data = &vt1724_playback_spdif_reg;
 	ice->playback_con_substream = substream;
 	if (ice->force_pdma4) {
 		runtime->hw = snd_vt1724_2ch_stereo;
@@ -898,6 +927,10 @@ static int snd_vt1724_playback_spdif_open(snd_pcm_substream_t *substream)
 		runtime->hw = snd_vt1724_spdif;
 	snd_pcm_set_sync(substream);
 	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
+	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+				   VT1724_BUFFER_ALIGN);
+	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+				   VT1724_BUFFER_ALIGN);
 	return 0;
 }
 
@@ -917,7 +950,7 @@ static int snd_vt1724_capture_spdif_open(snd_pcm_substream_t *substream)
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
-	runtime->private_data = (void*)VT1724_RDMA1_START; /* irq/status/trigger bit */
+	runtime->private_data = &vt1724_capture_spdif_reg;
 	ice->capture_con_substream = substream;
 	if (ice->force_rdma1) {
 		runtime->hw = snd_vt1724_2ch_stereo;
@@ -926,6 +959,10 @@ static int snd_vt1724_capture_spdif_open(snd_pcm_substream_t *substream)
 		runtime->hw = snd_vt1724_spdif;
 	snd_pcm_set_sync(substream);
 	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
+	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+				   VT1724_BUFFER_ALIGN);
+	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+				   VT1724_BUFFER_ALIGN);
 	return 0;
 }
 
@@ -948,7 +985,7 @@ static snd_pcm_ops_t snd_vt1724_playback_spdif_ops = {
 	.hw_free =	snd_vt1724_pcm_hw_free,
 	.prepare =	snd_vt1724_playback_spdif_prepare,
 	.trigger =	snd_vt1724_pcm_trigger,
-	.pointer =	snd_vt1724_playback_spdif_pointer,
+	.pointer =	snd_vt1724_pcm_pointer,
 };
 
 static snd_pcm_ops_t snd_vt1724_capture_spdif_ops = {
@@ -957,9 +994,9 @@ static snd_pcm_ops_t snd_vt1724_capture_spdif_ops = {
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_vt1724_pcm_hw_params,
 	.hw_free =	snd_vt1724_pcm_hw_free,
-	.prepare =	snd_vt1724_capture_spdif_prepare,
+	.prepare =	snd_vt1724_pcm_prepare,
 	.trigger =	snd_vt1724_pcm_trigger,
-	.pointer =	snd_vt1724_capture_spdif_pointer,
+	.pointer =	snd_vt1724_pcm_pointer,
 };
 
 
@@ -1017,27 +1054,24 @@ static int __devinit snd_vt1724_pcm_spdif(ice1712_t * ice, int device)
  * independent surround PCMs
  */
 
-const static struct vt1724_pcm_reg vt1724_playback_dma_regs[3] = {
+static struct vt1724_pcm_reg vt1724_playback_dma_regs[3] = {
 	{
 		.addr = VT1724_MT_PDMA1_ADDR,
 		.size = VT1724_MT_PDMA1_SIZE,
 		.count = VT1724_MT_PDMA1_COUNT,
 		.start = VT1724_PDMA1_START,
-		.pause = VT1724_PDMA1_PAUSE,
 	},
 	{
 		.addr = VT1724_MT_PDMA2_ADDR,
 		.size = VT1724_MT_PDMA2_SIZE,
 		.count = VT1724_MT_PDMA2_COUNT,
 		.start = VT1724_PDMA2_START,
-		.pause = VT1724_PDMA2_PAUSE,
 	},
 	{
 		.addr = VT1724_MT_PDMA3_ADDR,
 		.size = VT1724_MT_PDMA3_SIZE,
 		.count = VT1724_MT_PDMA3_COUNT,
 		.start = VT1724_PDMA3_START,
-		.pause = VT1724_PDMA3_PAUSE,
 	},
 };
 
@@ -1046,17 +1080,12 @@ static int snd_vt1724_playback_indep_prepare(snd_pcm_substream_t * substream)
 	ice1712_t *ice = snd_pcm_substream_chip(substream);
 	unsigned char val;
 
-	spin_lock(&ice->reg_lock);
+	spin_lock_irq(&ice->reg_lock);
 	val = 3 - substream->number;
 	if (inb(ICEMT1724(ice, BURST)) < val)
 		outb(val, ICEMT1724(ice, BURST));
-	spin_unlock(&ice->reg_lock);
-	return snd_vt1724_pcm_prepare(substream, &vt1724_playback_dma_regs[substream->number]);
-}
-
-static snd_pcm_uframes_t snd_vt1724_playback_indep_pointer(snd_pcm_substream_t * substream)
-{
-	return snd_vt1724_pcm_pointer(substream, &vt1724_playback_dma_regs[substream->number]);
+	spin_unlock_irq(&ice->reg_lock);
+	return snd_vt1724_pcm_prepare(substream);
 }
 
 static int snd_vt1724_playback_indep_open(snd_pcm_substream_t *substream)
@@ -1071,7 +1100,7 @@ static int snd_vt1724_playback_indep_open(snd_pcm_substream_t *substream)
 		return -EBUSY; /* FIXME: should handle blocking mode properly */
 	}
 	up(&ice->open_mutex);
-	runtime->private_data = (void*)(1UL << (substream->number + 4));
+	runtime->private_data = &vt1724_playback_dma_regs[substream->number];
 	ice->playback_con_substream_ds[substream->number] = substream;
 	runtime->hw = snd_vt1724_2ch_stereo;
 	snd_pcm_set_sync(substream);
@@ -1100,7 +1129,7 @@ static snd_pcm_ops_t snd_vt1724_playback_indep_ops = {
 	.hw_free =	snd_vt1724_pcm_hw_free,
 	.prepare =	snd_vt1724_playback_indep_prepare,
 	.trigger =	snd_vt1724_pcm_trigger,
-	.pointer =	snd_vt1724_playback_indep_pointer,
+	.pointer =	snd_vt1724_pcm_pointer,
 };
 
 
@@ -1143,17 +1172,19 @@ static int __devinit snd_vt1724_ac97_mixer(ice1712_t * ice)
 	int err;
 
 	if (! (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S)) {
-		ac97_bus_t bus, *pbus;
-		ac97_t ac97;
+		ac97_bus_t *pbus;
+		ac97_template_t ac97;
+		static ac97_bus_ops_t ops = {
+			.write = snd_vt1724_ac97_write,
+			.read = snd_vt1724_ac97_read,
+		};
+
 		/* cold reset */
 		outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD));
 		mdelay(5); /* FIXME */
 		outb(inb(ICEMT1724(ice, AC97_CMD)) & ~0x80, ICEMT1724(ice, AC97_CMD));
 
-		memset(&bus, 0, sizeof(bus));
-		bus.write = snd_vt1724_ac97_write;
-		bus.read = snd_vt1724_ac97_read;
-		if ((err = snd_ac97_bus(ice->card, &bus, &pbus)) < 0)
+		if ((err = snd_ac97_bus(ice->card, 0, &ops, NULL, &pbus)) < 0)
 			return err;
 		memset(&ac97, 0, sizeof(ac97));
 		ac97.private_data = ice;
@@ -1181,7 +1212,7 @@ static inline unsigned int eeprom_triple(ice1712_t *ice, int idx)
 static void snd_vt1724_proc_read(snd_info_entry_t *entry, 
 				 snd_info_buffer_t * buffer)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, entry->private_data, return);
+	ice1712_t *ice = entry->private_data;
 	unsigned int idx;
 
 	snd_iprintf(buffer, "%s\n\n", ice->card->longname);
@@ -1274,7 +1305,7 @@ static unsigned int encode_spdif_bits(snd_aes_iec958_t *diga)
 		}
 	} else {
 		/* consumer */
-		val |= diga->status[0] & 0x04; /* copyright */
+		val |= diga->status[1] & 0x04; /* copyright */
 		if ((diga->status[0] & IEC958_AES0_CON_EMPHASIS)== IEC958_AES0_CON_EMPHASIS_5015)
 			val |= 1U << 3;
 		val |= (unsigned int)(diga->status[1] & 0x3f) << 4; /* category */
@@ -1326,22 +1357,13 @@ static int snd_vt1724_spdif_default_put(snd_kcontrol_t * kcontrol,
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
 	unsigned int val, old;
-	unsigned long flags;
 
 	val = encode_spdif_bits(&ucontrol->value.iec958);
-	spin_lock_irqsave(&ice->reg_lock, flags);
+	spin_lock_irq(&ice->reg_lock);
 	old = inw(ICEMT1724(ice, SPDIF_CTRL));
-	if (val != old) {
-		unsigned char cbit, disabled;
-		cbit = inb(ICEREG1724(ice, SPDIF_CFG));
-		disabled = cbit & ~VT1724_CFG_SPDIF_OUT_EN;
-		if (cbit != disabled)
-			outb(disabled, ICEREG1724(ice, SPDIF_CFG));
-		outw(val, ICEMT1724(ice, SPDIF_CTRL));
-		if (cbit != disabled)
-			outb(cbit, ICEREG1724(ice, SPDIF_CFG));
-	}
-	spin_unlock_irqrestore(&ice->reg_lock, flags);
+	if (val != old)
+		update_spdif_bits(ice, val);
+	spin_unlock_irq(&ice->reg_lock);
 	return (val != old);
 }
 
@@ -1415,15 +1437,15 @@ static int snd_vt1724_spdif_sw_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
 	unsigned char old, val;
-	unsigned long flags;
-	spin_lock_irqsave(&ice->reg_lock, flags);
+
+	spin_lock_irq(&ice->reg_lock);
 	old = val = inb(ICEREG1724(ice, SPDIF_CFG));
 	val &= ~VT1724_CFG_SPDIF_OUT_EN;
 	if (ucontrol->value.integer.value[0])
 		val |= VT1724_CFG_SPDIF_OUT_EN;
 	if (old != val)
 		outb(val, ICEREG1724(ice, SPDIF_CFG));
-	spin_unlock_irqrestore(&ice->reg_lock, flags);
+	spin_unlock_irq(&ice->reg_lock);
 	return old != val;
 }
 
@@ -1490,7 +1512,7 @@ int snd_ice1712_gpio_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucont
  */
 static int snd_vt1724_pro_internal_clock_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
-	static char *texts[] = {
+	static char *texts_1724[] = {
 		"8000",		/* 0: 6 */
 		"9600",		/* 1: 3 */
 		"11025",	/* 2: 10 */
@@ -1508,12 +1530,32 @@ static int snd_vt1724_pro_internal_clock_info(snd_kcontrol_t *kcontrol, snd_ctl_
 		"192000",	/* 14: 14 */
 		"IEC958 Input",	/* 15: -- */
 	};
+	static char *texts_1720[] = {
+		"8000",		/* 0: 6 */
+		"9600",		/* 1: 3 */
+		"11025",	/* 2: 10 */
+		"12000",	/* 3: 2 */
+		"16000",	/* 4: 5 */
+		"22050",	/* 5: 9 */
+		"24000",	/* 6: 1 */
+		"32000",	/* 7: 4 */
+		"44100",	/* 8: 8 */
+		"48000",	/* 9: 0 */
+		"64000",	/* 10: 15 */
+		"88200",	/* 11: 11 */
+		"96000",	/* 12: 7 */
+		"IEC958 Input",	/* 13: -- */
+	};
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
-	uinfo->value.enumerated.items = 16;
+	uinfo->value.enumerated.items = ice->vt1720 ? 14 : 16;
 	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
 		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
-	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+	strcpy(uinfo->value.enumerated.name,
+	       ice->vt1720 ? texts_1720[uinfo->value.enumerated.item] :
+	       texts_1724[uinfo->value.enumerated.item]);
 	return 0;
 }
 
@@ -1527,7 +1569,7 @@ static int snd_vt1724_pro_internal_clock_get(snd_kcontrol_t * kcontrol, snd_ctl_
 	
 	spin_lock_irq(&ice->reg_lock);
 	if (is_spdif_master(ice)) {
-		ucontrol->value.enumerated.item[0] = 15;
+		ucontrol->value.enumerated.item[0] = ice->vt1720 ? 13 : 15;
 	} else {
 		val = xlate[inb(ICEMT1724(ice, RATE)) & 15];
 		if (val == 255) {
@@ -1544,17 +1586,22 @@ static int snd_vt1724_pro_internal_clock_put(snd_kcontrol_t * kcontrol, snd_ctl_
 {
 	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
 	unsigned char oval;
+	int rate;
 	int change = 0;
+	int spdif = ice->vt1720 ? 13 : 15;
 
 	spin_lock_irq(&ice->reg_lock);
 	oval = inb(ICEMT1724(ice, RATE));
-	if (ucontrol->value.enumerated.item[0] == 15) {
+	if (ucontrol->value.enumerated.item[0] == spdif) {
 		outb(oval | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
 	} else {
-		PRO_RATE_DEFAULT = rates[ucontrol->value.integer.value[0] % 15];
-		spin_unlock_irq(&ice->reg_lock);
-		snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 1);
-		spin_lock_irq(&ice->reg_lock);
+		rate = rates[ucontrol->value.integer.value[0] % 15];
+		if (rate <= get_max_rate(ice)) {
+			PRO_RATE_DEFAULT = rate;
+			spin_unlock_irq(&ice->reg_lock);
+			snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 1);
+			spin_lock_irq(&ice->reg_lock);
+		}
 	}
 	change = inb(ICEMT1724(ice, RATE)) != oval;
 	spin_unlock_irq(&ice->reg_lock);
@@ -1815,6 +1862,8 @@ static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
 	snd_vt1724_revo_cards,
 	snd_vt1724_amp_cards, 
 	snd_vt1724_aureon_cards,
+	snd_vt1720_mobo_cards,
+	snd_vt1720_pontis_cards,
 	NULL,
 };
 
@@ -1822,24 +1871,28 @@ static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
 /*
  */
 
-unsigned char snd_vt1724_read_i2c(ice1712_t *ice, unsigned char dev, unsigned char addr)
+static void wait_i2c_busy(ice1712_t *ice)
 {
-	long t = 0x10000;
+	int t = 0x10000;
+	while ((inb(ICEREG1724(ice, I2C_CTRL)) & VT1724_I2C_BUSY) && t--)
+		;
+}
 
+unsigned char snd_vt1724_read_i2c(ice1712_t *ice, unsigned char dev, unsigned char addr)
+{
 	outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR));
 	outb(dev & ~VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR));
-	while (t-- > 0 && (inb(ICEREG1724(ice, I2C_CTRL)) & VT1724_I2C_BUSY)) ;
+	wait_i2c_busy(ice);
 	return inb(ICEREG1724(ice, I2C_DATA));
 }
 
 void snd_vt1724_write_i2c(ice1712_t *ice, unsigned char dev, unsigned char addr, unsigned char data)
 {
-	long t = 0x10000;
-
+	wait_i2c_busy(ice);
 	outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR));
 	outb(data, ICEREG1724(ice, I2C_DATA));
 	outb(dev | VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR));
-	while (t-- > 0 && (inb(ICEREG1724(ice, I2C_CTRL)) & VT1724_I2C_BUSY)) ;
+	wait_i2c_busy(ice);
 }
 
 static int __devinit snd_vt1724_read_eeprom(ice1712_t *ice, const char *modelname)
@@ -1930,9 +1983,6 @@ static int __devinit snd_vt1724_chip_init(ice1712_t *ice)
 
 	outb(0, ICEREG1724(ice, POWERDOWN));
 
-	/* read back to check the availability of SPDIF out */
-	ice->eeprom.data[ICE_EEP2_SPDIF] = inb(ICEREG1724(ice, SPDIF_CFG));
-
 	return 0;
 }
 
@@ -1994,10 +2044,9 @@ static int __devinit snd_vt1724_build_controls(ice1712_t *ice)
 
 	if (ice->num_total_dacs > 0) {
 		snd_kcontrol_new_t tmp = snd_vt1724_mixer_pro_analog_route;
-		if (ice->vt1720)
+		tmp.count = ice->num_total_dacs;
+		if (ice->vt1720 && tmp.count > 2)
 			tmp.count = 2;
-		else
-			tmp.count = ice->num_total_dacs;
 		err = snd_ctl_add(ice->card, snd_ctl_new1(&tmp, ice));
 		if (err < 0)
 			return err;
@@ -2012,7 +2061,7 @@ static int __devinit snd_vt1724_build_controls(ice1712_t *ice)
 
 static int snd_vt1724_free(ice1712_t *ice)
 {
-	if (ice->res_port == NULL)
+	if (! ice->port)
 		goto __hw_end;
 	/* mask all interrupts */
 	outb(0xff, ICEMT1724(ice, DMA_INT_MASK));
@@ -2023,22 +2072,15 @@ static int snd_vt1724_free(ice1712_t *ice)
 		synchronize_irq(ice->irq);
 		free_irq(ice->irq, (void *) ice);
 	}
-	if (ice->res_port) {
-		release_resource(ice->res_port);
-		kfree_nocheck(ice->res_port);
-	}
-	if (ice->res_profi_port) {
-		release_resource(ice->res_profi_port);
-		kfree_nocheck(ice->res_profi_port);
-	}
+	pci_release_regions(ice->pci);
 	snd_ice1712_akm4xxx_free(ice);
-	snd_magic_kfree(ice);
+	kfree(ice);
 	return 0;
 }
 
 static int snd_vt1724_dev_free(snd_device_t *device)
 {
-	ice1712_t *ice = snd_magic_cast(ice1712_t, device->device_data, return -ENXIO);
+	ice1712_t *ice = device->device_data;
 	return snd_vt1724_free(ice);
 }
 
@@ -2060,7 +2102,7 @@ static int __devinit snd_vt1724_create(snd_card_t * card,
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	ice = snd_magic_kcalloc(ice1712_t, 0, GFP_KERNEL);
+	ice = kcalloc(1, sizeof(*ice), GFP_KERNEL);
 	if (ice == NULL)
 		return -ENOMEM;
 	ice->vt1724 = 1;
@@ -2074,24 +2116,17 @@ static int __devinit snd_vt1724_create(snd_card_t * card,
 	ice->card = card;
 	ice->pci = pci;
 	ice->irq = -1;
-	ice->port = pci_resource_start(pci, 0);
-	ice->profi_port = pci_resource_start(pci, 1);
 	pci_set_master(pci);
 	snd_vt1724_proc_init(ice);
 	synchronize_irq(pci->irq);
 
-	if ((ice->res_port = request_region(ice->port, 32, "ICE1724 - Controller")) == NULL) {
-		snd_printk("unable to grab ports 0x%lx-0x%lx\n", ice->port, ice->port + 32 - 1);
-		snd_vt1724_free(ice);
-		return -EIO;
+	if ((err = pci_request_regions(pci, "ICE1724")) < 0) {
+		kfree(ice);
+		return err;
 	}
+	ice->port = pci_resource_start(pci, 0);
+	ice->profi_port = pci_resource_start(pci, 1);
 
-	if ((ice->res_profi_port = request_region(ice->profi_port, 128, "ICE1724 - Professional")) == NULL) {
-		snd_printk("unable to grab ports 0x%lx-0x%lx\n", ice->profi_port, ice->profi_port + 16 - 1);
-		snd_vt1724_free(ice);
-		return -EIO;
-	}
-		
 	if (request_irq(pci->irq, snd_vt1724_interrupt, SA_INTERRUPT|SA_SHIRQ, "ICE1724", (void *) ice)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
 		snd_vt1724_free(ice);
diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c
index 805631270..82db619b2 100644
--- a/sound/pci/ice1712/revo.c
+++ b/sound/pci/ice1712/revo.c
@@ -128,7 +128,7 @@ static int __devinit revo_init(ice1712_t *ice)
 	switch (ice->eeprom.subvendor) {
 	case VT1724_SUBDEVICE_REVOLUTION71:
 		ice->num_total_dacs = 8;
-		ice->num_total_adcs = 4;
+		ice->num_total_adcs = 2;
 		break;
 	default:
 		snd_BUG();
@@ -136,7 +136,7 @@ static int __devinit revo_init(ice1712_t *ice)
 	}
 
 	/* second stage of initialization, analog parts and others */
-	ak = ice->akm = snd_kcalloc(sizeof(akm4xxx_t) * 2, GFP_KERNEL);
+	ak = ice->akm = kcalloc(2, sizeof(akm4xxx_t), GFP_KERNEL);
 	if (! ak)
 		return -ENOMEM;
 	ice->akm_codecs = 2;
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 5493667dd..0fa7e8a03 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -48,8 +48,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Intel,82801AA-ICH},"
+MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH},"
 		"{Intel,82901AB-ICH0},"
 		"{Intel,82801BA-ICH2},"
 		"{Intel,82801CA-ICH3},"
@@ -75,6 +74,7 @@ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
 static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
 static int ac97_quirk[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = AC97_TUNE_DEFAULT};
+static int buggy_irq[SNDRV_CARDS];
 #ifdef SUPPORT_JOYSTICK
 static int joystick[SNDRV_CARDS];
 #endif
@@ -85,28 +85,23 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Intel i8x0 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Intel i8x0 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(ac97_clock, int, boot_devs, 0444);
 MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect).");
-MODULE_PARM_SYNTAX(ac97_clock, SNDRV_ENABLED ",default:0");
 module_param_array(ac97_quirk, int, boot_devs, 0444);
 MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
-MODULE_PARM_SYNTAX(ac97_quirk, SNDRV_ENABLED ",allows:{{-1,4}},dialog:list,default:-1");
+module_param_array(buggy_irq, bool, boot_devs, 0444);
+MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards.");
 #ifdef SUPPORT_JOYSTICK
 module_param_array(joystick, bool, boot_devs, 0444);
 MODULE_PARM_DESC(joystick, "Enable joystick for Intel i8x0 soundcard.");
-MODULE_PARM_SYNTAX(joystick, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 #endif
 #ifdef SUPPORT_MIDI
 module_param_array(mpu_port, int, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU401 port # for Intel i8x0 driver.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_ENABLED ",allows:{{0},{0x330},{0x300}},dialog:list");
 #endif
 
 /*
@@ -146,9 +141,15 @@ MODULE_PARM_SYNTAX(mpu_port, SNDRV_ENABLED ",allows:{{0},{0x330},{0x300}},dialog
 #ifndef PCI_DEVICE_ID_NVIDIA_MCP_AUDIO
 #define PCI_DEVICE_ID_NVIDIA_MCP_AUDIO	0x01b1
 #endif
+#ifndef PCI_DEVICE_ID_NVIDIA_CK804_AUDIO
+#define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO 0x0059
+#endif
 #ifndef PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO
 #define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO	0x006a
 #endif
+#ifndef PCI_DEVICE_ID_NVIDIA_CK8_AUDIO
+#define PCI_DEVICE_ID_NVIDIA_CK8_AUDIO	0x008a
+#endif
 #ifndef PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO
 #define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO	0x00da
 #endif
@@ -397,25 +398,18 @@ typedef struct {
 } ichdev_t;
 
 typedef struct _snd_intel8x0 intel8x0_t;
-#define chip_t intel8x0_t
 
 struct _snd_intel8x0 {
 	unsigned int device_type;
-	char ac97_name[32];
-	char ctrl_name[32];
 
 	int irq;
 
 	unsigned int mmio;
 	unsigned long addr;
-	unsigned long remap_addr;
-	struct resource *res;
+	void __iomem * remap_addr;
 	unsigned int bm_mmio;
 	unsigned long bmaddr;
-	unsigned long remap_bmaddr;
-	struct resource *res_bm;
-
-	struct snd_dma_device dma_dev;
+	void __iomem * remap_bmaddr;
 
 	struct pci_dev *pci;
 	snd_card_t *card;
@@ -424,12 +418,13 @@ struct _snd_intel8x0 {
 	snd_pcm_t *pcm[6];
 	ichdev_t ichd[6];
 
-	int multi4: 1,
-	    multi6: 1,
-	    smp20bit: 1;
-	int in_ac97_init: 1,
-	    in_sdin_init: 1;
-	int fix_nocache: 1; /* workaround for 440MX */
+	unsigned multi4: 1,
+		 multi6: 1,
+		 smp20bit: 1;
+	unsigned in_ac97_init: 1,
+		 in_sdin_init: 1;
+	unsigned fix_nocache: 1; /* workaround for 440MX */
+	unsigned buggy_irq: 1; /* workaround for buggy mobos */
 
 	ac97_bus_t *ac97_bus;
 	ac97_t *ac97[3];
@@ -444,10 +439,6 @@ struct _snd_intel8x0 {
 	struct snd_dma_buffer bdbars;
 	u32 int_sta_reg;		/* interrupt status register */
 	u32 int_sta_mask;		/* interrupt status mask */
-
-#ifdef CONFIG_PM
-	u32 pci_state[64 / sizeof(u32)];
-#endif
 };
 
 static struct pci_device_id snd_intel8x0_ids[] = {
@@ -462,7 +453,10 @@ static struct pci_device_id snd_intel8x0_ids[] = {
 	{ 0x8086, 0x7195, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* 440MX */
 	{ 0x1039, 0x7012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_SIS },	/* SI7012 */
 	{ 0x10de, 0x01b1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* NFORCE */
+	{ 0x10de, 0x003a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* MCP04 */
 	{ 0x10de, 0x006a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* NFORCE2 */
+	{ 0x10de, 0x0059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* CK804 */
+	{ 0x10de, 0x008a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* CK8 */
 	{ 0x10de, 0x00da, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* NFORCE3 */
 	{ 0x10de, 0x00ea, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* CK8S */
 	{ 0x1022, 0x746d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* AMD8111 */
@@ -605,7 +599,7 @@ static void snd_intel8x0_codec_write(ac97_t *ac97,
 				     unsigned short reg,
 				     unsigned short val)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, ac97->private_data, return);
+	intel8x0_t *chip = ac97->private_data;
 	
 	spin_lock(&chip->ac97_lock);
 	if (snd_intel8x0_codec_semaphore(chip, ac97->num) < 0) {
@@ -619,7 +613,7 @@ static void snd_intel8x0_codec_write(ac97_t *ac97,
 static unsigned short snd_intel8x0_codec_read(ac97_t *ac97,
 					      unsigned short reg)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, ac97->private_data, return ~0);
+	intel8x0_t *chip = ac97->private_data;
 	unsigned short res;
 	unsigned int tmp;
 
@@ -642,6 +636,21 @@ static unsigned short snd_intel8x0_codec_read(ac97_t *ac97,
 	return res;
 }
 
+static void snd_intel8x0_codec_read_test(intel8x0_t *chip, unsigned int codec)
+{
+	unsigned int tmp;
+
+	spin_lock(&chip->ac97_lock);
+	if (snd_intel8x0_codec_semaphore(chip, codec) >= 0) {
+		iagetword(chip, codec * 0x80);
+		if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) {
+			/* reset RCS and preserve other R/WC bits */
+			iputdword(chip, ICHREG(GLOB_STA), tmp & ~(ICH_SRI|ICH_PRI|ICH_TRI|ICH_GSCI));
+		}
+	}
+	spin_unlock(&chip->ac97_lock);
+}
+
 /*
  * access to AC97 for Ali5455
  */
@@ -669,7 +678,7 @@ static int snd_intel8x0_ali_codec_semaphore(intel8x0_t *chip)
 
 static unsigned short snd_intel8x0_ali_codec_read(ac97_t *ac97, unsigned short reg)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, ac97->private_data, return ~0);
+	intel8x0_t *chip = ac97->private_data;
 	unsigned short data = 0xffff;
 
 	spin_lock(&chip->ac97_lock);
@@ -689,7 +698,7 @@ static unsigned short snd_intel8x0_ali_codec_read(ac97_t *ac97, unsigned short r
 
 static void snd_intel8x0_ali_codec_write(ac97_t *ac97, unsigned short reg, unsigned short val)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, ac97->private_data, return);
+	intel8x0_t *chip = ac97->private_data;
 
 	spin_lock(&chip->ac97_lock);
 	if (snd_intel8x0_ali_codec_semaphore(chip)) {
@@ -778,6 +787,7 @@ static inline void snd_intel8x0_update(intel8x0_t *chip, ichdev_t *ichdev)
 	int status, civ, i, step;
 	int ack = 0;
 
+	spin_lock(&chip->reg_lock);
 	status = igetbyte(chip, port + ichdev->roff_sr);
 	civ = igetbyte(chip, port + ICH_REG_OFF_CIV);
 	if (!(status & ICH_BCIS)) {
@@ -811,10 +821,9 @@ static inline void snd_intel8x0_update(intel8x0_t *chip, ichdev_t *ichdev)
 			ack = 1;
 		}
 	}
+	spin_unlock(&chip->reg_lock);
 	if (ack && ichdev->substream) {
-		spin_unlock(&chip->reg_lock);
 		snd_pcm_period_elapsed(ichdev->substream);
-		spin_lock(&chip->reg_lock);
 	}
 	iputbyte(chip, port + ichdev->roff_sr,
 		 status & (ICH_FIFOE | ICH_BCIS | ICH_LVBCI));
@@ -822,24 +831,22 @@ static inline void snd_intel8x0_update(intel8x0_t *chip, ichdev_t *ichdev)
 
 static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, dev_id, return IRQ_NONE);
+	intel8x0_t *chip = dev_id;
 	ichdev_t *ichdev;
 	unsigned int status;
 	unsigned int i;
 
-	spin_lock(&chip->reg_lock);
 	status = igetdword(chip, chip->int_sta_reg);
+	if (status == 0xffffffff)	/* we are not yet resumed */
+		return IRQ_NONE;
+
 	if ((status & chip->int_sta_mask) == 0) {
 		if (status) {
 			/* ack */
 			iputdword(chip, chip->int_sta_reg, status);
-			/* some Nforce[2] boards have problems when
-			   IRQ_NONE is returned here.
-			*/
-			if (chip->device_type != DEVICE_NFORCE)
+			if (! chip->buggy_irq)
 				status = 0;
 		}
-		spin_unlock(&chip->reg_lock);
 		return IRQ_RETVAL(status);
 	}
 
@@ -851,7 +858,6 @@ static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id, struct pt_regs
 
 	/* ack them */
 	iputdword(chip, chip->int_sta_reg, status & chip->int_sta_mask);
-	spin_unlock(&chip->reg_lock);
 	
 	return IRQ_HANDLED;
 }
@@ -1021,8 +1027,10 @@ static void snd_intel8x0_setup_pcm_out(intel8x0_t *chip,
 			/* reset to 2ch once to keep the 6 channel data in alignment,
 			 * to start from Front Left always
 			 */
-			iputdword(chip, ICHREG(GLOB_CNT), (cnt & 0xcfffff));
-			mdelay(50); /* grrr... */
+			if (cnt & ICH_PCM_246_MASK) {
+				iputdword(chip, ICHREG(GLOB_CNT), cnt & ~ICH_PCM_246_MASK);
+				msleep(50); /* grrr... */
+			}
 		} else if (chip->device_type == DEVICE_INTEL_ICH4) {
 			if (sample_bits > 16)
 				cnt |= ICH_PCM_20BIT;
@@ -1041,16 +1049,16 @@ static int snd_intel8x0_pcm_prepare(snd_pcm_substream_t * substream)
 	ichdev->physbuf = runtime->dma_addr;
 	ichdev->size = snd_pcm_lib_buffer_bytes(substream);
 	ichdev->fragsize = snd_pcm_lib_period_bytes(substream);
+	spin_lock_irq(&chip->reg_lock);
 	if (ichdev->ichd == ICHD_PCMOUT) {
-		spin_lock(&chip->reg_lock);
 		snd_intel8x0_setup_pcm_out(chip, runtime->channels,
 					   runtime->sample_bits);
-		spin_unlock(&chip->reg_lock);
 		if (chip->device_type == DEVICE_INTEL_ICH4) {
 			ichdev->pos_shift = (runtime->sample_bits > 16) ? 2 : 1;
 		}
 	}
 	snd_intel8x0_setup_periods(chip, ichdev);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -1058,17 +1066,25 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(snd_pcm_substream_t * substrea
 {
 	intel8x0_t *chip = snd_pcm_substream_chip(substream);
 	ichdev_t *ichdev = get_ichdev(substream);
-	unsigned long flags;
 	size_t ptr1, ptr;
+	int civ, timeout = 10;
+	unsigned int position;
 
-	ptr1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb) << ichdev->pos_shift;
-	if (ptr1 != 0)
-		ptr = ichdev->fragsize1 - ptr1;
-	else
-		ptr = 0;
-	spin_lock_irqsave(&chip->reg_lock, flags);
-	ptr += ichdev->position;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
+	do {
+		civ = igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV);
+		ptr1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb);
+		position = ichdev->position;
+		if (ptr1 == 0)
+			udelay(1);
+		if (civ == igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV) &&
+		    ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb))
+			break;
+	} while (timeout--);
+	ptr1 <<= ichdev->pos_shift;
+	ptr = ichdev->fragsize1 - ptr1;
+	ptr += position;
+	spin_unlock(&chip->reg_lock);
 	if (ptr >= ichdev->size)
 		return 0;
 	return bytes_to_frames(substream->runtime, ptr);
@@ -1099,10 +1115,8 @@ static unsigned int channels4[] = {
 	2, 4,
 };
 
-#define CHANNELS4 sizeof(channels4) / sizeof(channels4[0])
-
 static snd_pcm_hw_constraint_list_t hw_constraints_channels4 = {
-	.count = CHANNELS4,
+	.count = ARRAY_SIZE(channels4),
 	.list = channels4,
 	.mask = 0,
 };
@@ -1111,10 +1125,8 @@ static unsigned int channels6[] = {
 	2, 4, 6,
 };
 
-#define CHANNELS6 sizeof(channels6) / sizeof(channels6[0])
-
 static snd_pcm_hw_constraint_list_t hw_constraints_channels6 = {
-	.count = CHANNELS6,
+	.count = ARRAY_SIZE(channels6),
 	.list = channels6,
 	.mask = 0,
 };
@@ -1156,8 +1168,10 @@ static int snd_intel8x0_playback_open(snd_pcm_substream_t * substream)
 		runtime->hw.channels_max = 4;
 		snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels4);
 	}
-	if (chip->smp20bit)
+	if (chip->smp20bit) {
 		runtime->hw.formats |= SNDRV_PCM_FMTBIT_S32_LE;
+		snd_pcm_hw_constraint_msbits(runtime, 0, 32, 20);
+	}
 	return 0;
 }
 
@@ -1249,14 +1263,14 @@ static int snd_intel8x0_spdif_close(snd_pcm_substream_t * substream)
 static int snd_intel8x0_ali_ac97spdifout_open(snd_pcm_substream_t * substream)
 {
 	intel8x0_t *chip = snd_pcm_substream_chip(substream);
-	unsigned long flags;
 	unsigned int val;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	val = igetdword(chip, ICHREG(ALI_INTERFACECR));
 	val |= ICH_ALI_IF_AC97SP;
+	iputdword(chip, ICHREG(ALI_INTERFACECR), val);
 	/* also needs to set ALI_SC_CODEC_SPDF correctly */
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 
 	return snd_intel8x0_pcm_open(substream, &chip->ichd[ALID_AC97SPDIFOUT]);
 }
@@ -1264,14 +1278,14 @@ static int snd_intel8x0_ali_ac97spdifout_open(snd_pcm_substream_t * substream)
 static int snd_intel8x0_ali_ac97spdifout_close(snd_pcm_substream_t * substream)
 {
 	intel8x0_t *chip = snd_pcm_substream_chip(substream);
-	unsigned long flags;
 	unsigned int val;
 
 	chip->ichd[ALID_AC97SPDIFOUT].substream = NULL;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	val = igetdword(chip, ICHREG(ALI_INTERFACECR));
 	val &= ~ICH_ALI_IF_AC97SP;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	iputdword(chip, ICHREG(ALI_INTERFACECR), val);
+	spin_unlock_irq(&chip->reg_lock);
 
 	return 0;
 }
@@ -1627,13 +1641,13 @@ static int __devinit snd_intel8x0_pcm(intel8x0_t *chip)
 
 static void snd_intel8x0_mixer_free_ac97_bus(ac97_bus_t *bus)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, bus->private_data, return);
+	intel8x0_t *chip = bus->private_data;
 	chip->ac97_bus = NULL;
 }
 
 static void snd_intel8x0_mixer_free_ac97(ac97_t *ac97)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, ac97->private_data, return);
+	intel8x0_t *chip = ac97->private_data;
 	chip->ac97[ac97->num] = NULL;
 }
 
@@ -1726,12 +1740,30 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
 		.name = "Dell Optiplex GX260",	/* AD1981A */
 		.type = AC97_TUNE_HP_ONLY
 	},
+	{
+		.vendor = 0x1028,
+		.device = 0x012d,
+		.name = "Dell Precision 450",	/* AD1981B*/
+		.type = AC97_TUNE_HP_ONLY
+	},
 	{	/* FIXME: which codec? */
 		.vendor = 0x103c,
 		.device = 0x00c3,
 		.name = "Hewlett-Packard onboard",
 		.type = AC97_TUNE_HP_ONLY
 	},
+	{
+		.vendor = 0x103c,
+		.device = 0x12f1,
+		.name = "HP xw8200",	/* AD1981B*/
+		.type = AC97_TUNE_HP_ONLY
+	},
+	{
+		.vendor = 0x103c,
+		.device = 0x3008,
+		.name = "HP xw4200",	/* AD1981B*/
+		.type = AC97_TUNE_HP_ONLY
+	},
  	{
 		.vendor = 0x1043,
 		.device = 0x80f3,
@@ -1800,6 +1832,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
 		.name = "Intel D850EMV2",	/* AD1885 */
 		.type = AC97_TUNE_HP_ONLY
 	},
+	{
+		.vendor = 0x8086,
+		.device = 0x4d56,
+		.name = "Intel ICH/AD1885",
+		.type = AC97_TUNE_HP_ONLY
+	},
 	{
 		.vendor = 0x8086,
 		.device = 0x6000,
@@ -1828,12 +1866,21 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
 
 static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock, int ac97_quirk)
 {
-	ac97_bus_t bus, *pbus;
-	ac97_t ac97, *x97;
+	ac97_bus_t *pbus;
+	ac97_template_t ac97;
 	int err;
 	unsigned int i, codecs;
 	unsigned int glob_sta = 0;
 	int spdif_idx = -1; /* disabled */
+	ac97_bus_ops_t *ops;
+	static ac97_bus_ops_t standard_bus_ops = {
+		.write = snd_intel8x0_codec_write,
+		.read = snd_intel8x0_codec_read,
+	};
+	static ac97_bus_ops_t ali_bus_ops = {
+		.write = snd_intel8x0_ali_codec_write,
+		.read = snd_intel8x0_ali_codec_read,
+	};
 
 	switch (chip->device_type) {
 	case DEVICE_NFORCE:
@@ -1849,13 +1896,6 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock, int ac
 	};
 
 	chip->in_ac97_init = 1;
-	memset(&bus, 0, sizeof(bus));
-	bus.private_data = chip;
-	bus.private_free = snd_intel8x0_mixer_free_ac97_bus;
-	if (ac97_clock >= 8000 && ac97_clock <= 48000)
-		bus.clock = ac97_clock;
-	else
-		bus.clock = 48000;
 	
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = chip;
@@ -1863,8 +1903,7 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock, int ac
 	ac97.scaps = AC97_SCAP_SKIP_MODEM;
 	if (chip->device_type != DEVICE_ALI) {
 		glob_sta = igetdword(chip, ICHREG(GLOB_STA));
-		bus.write = snd_intel8x0_codec_write;
-		bus.read = snd_intel8x0_codec_read;
+		ops = &standard_bus_ops;
 		if (chip->device_type == DEVICE_INTEL_ICH4) {
 			codecs = 0;
 			if (glob_sta & ICH_PCR)
@@ -1875,19 +1914,15 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock, int ac
 				codecs++;
 			chip->in_sdin_init = 1;
 			for (i = 0; i < codecs; i++) {
-				ac97.num = i;
-				snd_intel8x0_codec_read(&ac97, 0);
+				snd_intel8x0_codec_read_test(chip, i);
 				chip->ac97_sdin[i] = igetbyte(chip, ICHREG(SDM)) & ICH_LDI_MASK;
 			}
-			ac97.num = 0;
 			chip->in_sdin_init = 0;
 		} else {
 			codecs = glob_sta & ICH_SCR ? 2 : 1;
 		}
-		bus.vra = 1;
 	} else {
-		bus.write = snd_intel8x0_ali_codec_write;
-		bus.read = snd_intel8x0_ali_codec_read;
+		ops = &ali_bus_ops;
 		codecs = 1;
 		/* detect the secondary codec */
 		for (i = 0; i < 100; i++) {
@@ -1899,23 +1934,28 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock, int ac
 			iputdword(chip, ICHREG(ALI_RTSR), reg | 0x40);
 			udelay(1);
 		}
-		/* FIXME: my test board doens't work well with VRA... */
-		bus.vra = 0;
 	}
-	if ((err = snd_ac97_bus(chip->card, &bus, &pbus)) < 0)
+	if ((err = snd_ac97_bus(chip->card, 0, ops, chip, &pbus)) < 0)
 		goto __err;
+	pbus->private_free = snd_intel8x0_mixer_free_ac97_bus;
+	pbus->shared_type = AC97_SHARED_TYPE_ICH;	/* shared with modem driver */
+	if (ac97_clock >= 8000 && ac97_clock <= 48000)
+		pbus->clock = ac97_clock;
+	/* FIXME: my test board doesn't work well with VRA... */
+	if (chip->device_type == DEVICE_ALI)
+		pbus->no_vra = 1;
 	chip->ac97_bus = pbus;
+
 	ac97.pci = chip->pci;
 	for (i = 0; i < codecs; i++) {
 		ac97.num = i;
-		if ((err = snd_ac97_mixer(pbus, &ac97, &x97)) < 0) {
+		if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) {
 			if (err != -EACCES)
 				snd_printk(KERN_ERR "Unable to initialize codec #%d\n", i);
 			if (i == 0)
 				goto __err;
 			continue;
 		}
-		chip->ac97[i] = x97;
 	}
 	/* tune up the primary codec */
 	snd_ac97_tune_hardware(chip->ac97[0], ac97_quirks, ac97_quirk);
@@ -2179,26 +2219,19 @@ static int snd_intel8x0_free(intel8x0_t *chip)
 	/* --- */
 	synchronize_irq(chip->irq);
       __hw_end:
+	if (chip->irq >= 0)
+		free_irq(chip->irq, (void *)chip);
 	if (chip->bdbars.area) {
 		if (chip->fix_nocache)
 			fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 0);
-		snd_dma_free_pages(&chip->dma_dev, &chip->bdbars);
+		snd_dma_free_pages(&chip->bdbars);
 	}
 	if (chip->remap_addr)
-		iounmap((void *) chip->remap_addr);
+		iounmap(chip->remap_addr);
 	if (chip->remap_bmaddr)
-		iounmap((void *) chip->remap_bmaddr);
-	if (chip->res) {
-		release_resource(chip->res);
-		kfree_nocheck(chip->res);
-	}
-	if (chip->res_bm) {
-		release_resource(chip->res_bm);
-		kfree_nocheck(chip->res_bm);
-	}
-	if (chip->irq >= 0)
-		free_irq(chip->irq, (void *)chip);
-	snd_magic_kfree(chip);
+		iounmap(chip->remap_bmaddr);
+	pci_release_regions(chip->pci);
+	kfree(chip);
 	return 0;
 }
 
@@ -2208,7 +2241,7 @@ static int snd_intel8x0_free(intel8x0_t *chip)
  */
 static int intel8x0_suspend(snd_card_t *card, unsigned int state)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, card->pm_private_data, return -EINVAL);
+	intel8x0_t *chip = card->pm_private_data;
 	int i;
 
 	for (i = 0; i < chip->pcm_devs; i++)
@@ -2216,17 +2249,15 @@ static int intel8x0_suspend(snd_card_t *card, unsigned int state)
 	for (i = 0; i < 3; i++)
 		if (chip->ac97[i])
 			snd_ac97_suspend(chip->ac97[i]);
-	pci_save_state(chip->pci, chip->pci_state);
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
 	return 0;
 }
 
 static int intel8x0_resume(snd_card_t *card, unsigned int state)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, card->pm_private_data, return -EINVAL);
+	intel8x0_t *chip = card->pm_private_data;
 	int i;
 
-	pci_restore_state(chip->pci, chip->pci_state);
 	pci_enable_device(chip->pci);
 	pci_set_master(chip->pci);
 	snd_intel8x0_chip_init(chip, 0);
@@ -2264,7 +2295,6 @@ static void __devinit intel8x0_measure_ac97_clock(intel8x0_t *chip)
 	ichdev_t *ichdev;
 	unsigned long port;
 	unsigned long pos, t;
-	unsigned long flags;
 	struct timeval start_time, stop_time;
 
 	if (chip->ac97_bus->clock != 48000)
@@ -2287,7 +2317,7 @@ static void __devinit intel8x0_measure_ac97_clock(intel8x0_t *chip)
 	}
 	snd_intel8x0_setup_periods(chip, ichdev);
 	port = ichdev->reg_offset;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	/* trigger */
 	if (chip->device_type != DEVICE_ALI)
 		iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE | ICH_STARTBM);
@@ -2296,7 +2326,7 @@ static void __devinit intel8x0_measure_ac97_clock(intel8x0_t *chip)
 		iputdword(chip, ICHREG(ALI_DMACR), 1 << ichdev->ali_slot);
 	}
 	do_gettimeofday(&start_time);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 #if 0
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	schedule_timeout(HZ / 20);
@@ -2304,7 +2334,7 @@ static void __devinit intel8x0_measure_ac97_clock(intel8x0_t *chip)
 	/* FIXME: schedule() can take too long time and overlap the boundary.. */
 	mdelay(50);
 #endif
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	/* check the position */
 	pos = ichdev->fragsize1;
 	pos -= igetword(chip, ichdev->reg_offset + ichdev->roff_picb) << ichdev->pos_shift;
@@ -2322,7 +2352,7 @@ static void __devinit intel8x0_measure_ac97_clock(intel8x0_t *chip)
 			;
 	}
 	iputbyte(chip, port + ICH_REG_OFF_CR, ICH_RESETREGS);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 
 	t = stop_time.tv_sec - start_time.tv_sec;
 	t *= 1000000;
@@ -2346,7 +2376,7 @@ static void __devinit intel8x0_measure_ac97_clock(intel8x0_t *chip)
 static void snd_intel8x0_proc_read(snd_info_entry_t * entry,
 				   snd_info_buffer_t * buffer)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, entry->private_data, return);
+	intel8x0_t *chip = entry->private_data;
 	unsigned int tmp;
 
 	snd_iprintf(buffer, "Intel8x0\n\n");
@@ -2379,7 +2409,7 @@ static void __devinit snd_intel8x0_proc_init(intel8x0_t * chip)
 
 static int snd_intel8x0_dev_free(snd_device_t *device)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, device->device_data, return -ENXIO);
+	intel8x0_t *chip = device->device_data;
 	return snd_intel8x0_free(chip);
 }
 
@@ -2438,7 +2468,7 @@ static int __devinit snd_intel8x0_create(snd_card_t * card,
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	chip = snd_magic_kcalloc(intel8x0_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
@@ -2447,66 +2477,51 @@ static int __devinit snd_intel8x0_create(snd_card_t * card,
 	chip->card = card;
 	chip->pci = pci;
 	chip->irq = -1;
-	snd_intel8x0_proc_init(chip);
-	sprintf(chip->ac97_name, "%s - AC'97", card->shortname);
-	sprintf(chip->ctrl_name, "%s - Controller", card->shortname);
+
 	if (pci->vendor == PCI_VENDOR_ID_INTEL &&
 	    pci->device == PCI_DEVICE_ID_INTEL_440MX)
 		chip->fix_nocache = 1; /* enable workaround */
+
+	/* some Nforce[2] and ICH boards have problems with IRQ handling.
+	 * Needs to return IRQ_HANDLED for unknown irqs.
+	 */
+	if (device_type == DEVICE_NFORCE)
+		chip->buggy_irq = 1;
+
+	if ((err = pci_request_regions(pci, card->shortname)) < 0) {
+		kfree(chip);
+		return err;
+	}
+
 	if (device_type == DEVICE_ALI) {
 		/* ALI5455 has no ac97 region */
 		chip->bmaddr = pci_resource_start(pci, 0);
-		if ((chip->res_bm = request_region(chip->bmaddr, 256, chip->ctrl_name)) == NULL) {
-			snd_printk("unable to grab ports 0x%lx-0x%lx\n", chip->bmaddr, chip->bmaddr + 64 - 1);
-			snd_intel8x0_free(chip);
-			return -EBUSY;
-		}
 		goto port_inited;
 	}
 
 	if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) {	/* ICH4 and Nforce */
 		chip->mmio = 1;
 		chip->addr = pci_resource_start(pci, 2);
-		if ((chip->res = request_mem_region(chip->addr, 512, chip->ac97_name)) == NULL) {
-			snd_printk("unable to grab I/O memory 0x%lx-0x%lx\n", chip->addr, chip->addr + 512 - 1);
-			snd_intel8x0_free(chip);
-			return -EBUSY;
-		}
-		chip->remap_addr = (unsigned long) ioremap_nocache(chip->addr, 512);
-		if (chip->remap_addr == 0) {
+		chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci, 2));
+		if (!chip->remap_addr) {
 			snd_printk("AC'97 space ioremap problem\n");
 			snd_intel8x0_free(chip);
 			return -EIO;
 		}
 	} else {
 		chip->addr = pci_resource_start(pci, 0);
-		if ((chip->res = request_region(chip->addr, 256, chip->ac97_name)) == NULL) {
-			snd_printk("unable to grab ports 0x%lx-0x%lx\n", chip->addr, chip->addr + 256 - 1);
-			snd_intel8x0_free(chip);
-			return -EBUSY;
-		}
 	}
 	if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) {	/* ICH4 */
 		chip->bm_mmio = 1;
 		chip->bmaddr = pci_resource_start(pci, 3);
-		if ((chip->res_bm = request_mem_region(chip->bmaddr, 256, chip->ctrl_name)) == NULL) {
-			snd_printk("unable to grab I/O memory 0x%lx-0x%lx\n", chip->bmaddr, chip->bmaddr + 512 - 1);
-			snd_intel8x0_free(chip);
-			return -EBUSY;
-		}
-		chip->remap_bmaddr = (unsigned long) ioremap_nocache(chip->bmaddr, 256);
-		if (chip->remap_bmaddr == 0) {
+		chip->remap_bmaddr = ioremap_nocache(chip->bmaddr, pci_resource_len(pci, 3));
+		if (!chip->remap_bmaddr) {
 			snd_printk("Controller space ioremap problem\n");
 			snd_intel8x0_free(chip);
 			return -EIO;
 		}
 	} else {
 		chip->bmaddr = pci_resource_start(pci, 1);
-		if ((chip->res_bm = request_region(chip->bmaddr, 64, chip->ctrl_name)) == NULL) {
-			snd_printk("unable to grab ports 0x%lx-0x%lx\n", chip->bmaddr, chip->bmaddr + 64 - 1);
-			snd_intel8x0_free(chip);
-			return -EBUSY;
-		}
 	}
 
  port_inited:
@@ -2552,13 +2567,11 @@ static int __devinit snd_intel8x0_create(snd_card_t * card,
 		ichdev->pos_shift = (device_type == DEVICE_SIS) ? 0 : 1;
 	}
 
-	memset(&chip->dma_dev, 0, sizeof(chip->dma_dev));
-	chip->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	chip->dma_dev.dev = snd_dma_pci_data(pci);
-
 	/* allocate buffer descriptor lists */
 	/* the start of each lists must be aligned to 8 bytes */
-	if (snd_dma_alloc_pages(&chip->dma_dev, chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2, &chip->bdbars) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2,
+				&chip->bdbars) < 0) {
 		snd_intel8x0_free(chip);
 		snd_printk(KERN_ERR "intel8x0: cannot allocate buffer descriptors\n");
 		return -ENOMEM;
@@ -2614,6 +2627,9 @@ static struct shortname_table {
 	{ PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO, "NVidia nForce2" },
 	{ PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO, "NVidia nForce3" },
 	{ PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO, "NVidia CK8S" },
+	{ PCI_DEVICE_ID_NVIDIA_CK804_AUDIO, "NVidia CK804" },
+	{ PCI_DEVICE_ID_NVIDIA_CK8_AUDIO, "NVidia CK8" },
+	{ 0x003a, "NVidia MCP04" },
 	{ 0x746d, "AMD AMD8111" },
 	{ 0x7445, "AMD AMD768" },
 	{ 0x5455, "ALi M5455" },
@@ -2661,6 +2677,8 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
 		snd_card_free(card);
 		return err;
 	}
+	if (buggy_irq[dev])
+		chip->buggy_irq = 1;
 
 	if ((err = snd_intel8x0_mixer(chip, ac97_clock[dev], ac97_quirk[dev])) < 0) {
 		snd_card_free(card);
@@ -2681,6 +2699,8 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
 	} else
 		mpu_port[dev] = 0;
 
+	snd_intel8x0_proc_init(chip);
+
 	sprintf(card->longname, "%s at 0x%lx, irq %i",
 		card->shortname, chip->addr, chip->irq);
 
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index b09b6f7f8..a9b317547 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -40,10 +40,9 @@
 #include <sound/initval.h>
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
-MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440 modem");
+MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7013; NVidia MCP/2/2S/3 modems");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Intel,82801AA-ICH},"
+MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH},"
 		"{Intel,82901AB-ICH0},"
 		"{Intel,82801BA-ICH2},"
 		"{Intel,82801CA-ICH3},"
@@ -60,16 +59,12 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Intel i8x0 modemcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Intel i8x0 modemcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Intel i8x0 modemcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(ac97_clock, int, boot_devs, 0444);
 MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect).");
-MODULE_PARM_SYNTAX(ac97_clock, SNDRV_ENABLED ",default:0");
 
 /*
  *  Direct registers
@@ -99,18 +94,20 @@ MODULE_PARM_SYNTAX(ac97_clock, SNDRV_ENABLED ",default:0");
 #ifndef PCI_DEVICE_ID_SI_7013
 #define PCI_DEVICE_ID_SI_7013		0x7013
 #endif
-#if 0
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP_AUDIO	0x01b1
+#ifndef PCI_DEVICE_ID_NVIDIA_MCP_MODEM
+#define PCI_DEVICE_ID_NVIDIA_MCP_MODEM	0x01c1
 #endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO	0x006a
+#ifndef PCI_DEVICE_ID_NVIDIA_MCP2_MODEM
+#define PCI_DEVICE_ID_NVIDIA_MCP2_MODEM	0x0069
 #endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO	0x00da
+#ifndef PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM
+#define PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM 0x0089
 #endif
+#ifndef PCI_DEVICE_ID_NVIDIA_MCP3_MODEM
+#define PCI_DEVICE_ID_NVIDIA_MCP3_MODEM	0x00d9
 #endif
 
+
 enum { DEVICE_INTEL, DEVICE_SIS, DEVICE_ALI, DEVICE_NFORCE };
 
 #define ICHREG(x) ICH_REG_##x
@@ -228,23 +225,18 @@ typedef struct {
 } ichdev_t;
 
 typedef struct _snd_intel8x0m intel8x0_t;
-#define chip_t intel8x0_t
 
 struct _snd_intel8x0m {
 	unsigned int device_type;
-	char ac97_name[64];
-	char ctrl_name[64];
 
 	int irq;
 
 	unsigned int mmio;
 	unsigned long addr;
 	unsigned long remap_addr;
-	struct resource *res;
 	unsigned int bm_mmio;
 	unsigned long bmaddr;
 	unsigned long remap_bmaddr;
-	struct resource *res_bm;
 
 	struct pci_dev *pci;
 	snd_card_t *card;
@@ -261,7 +253,6 @@ struct _snd_intel8x0m {
 	spinlock_t reg_lock;
 	spinlock_t ac97_lock;
 	
-	struct snd_dma_device dma_dev;
 	struct snd_dma_buffer bdbars;
 	u32 bdbars_count;
 	u32 int_sta_reg;		/* interrupt status register */
@@ -278,12 +269,12 @@ static struct pci_device_id snd_intel8x0m_ids[] = {
 	{ 0x8086, 0x24d6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH5 */
 	{ 0x8086, 0x7196, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* 440MX */
 	{ 0x1022, 0x7446, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* AMD768 */
-#if 0
-	/* TODO: support needed */
 	{ 0x1039, 0x7013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_SIS },	/* SI7013 */
-	{ 0x10de, 0x01b1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* NFORCE */
-	{ 0x10de, 0x006a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* NFORCE2 */
-	{ 0x10de, 0x00da, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },	/* NFORCE3 */
+	{ 0x10de, 0x01c1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE */
+	{ 0x10de, 0x0069, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE2 */
+	{ 0x10de, 0x0089, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE2s */
+	{ 0x10de, 0x00d9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE3 */
+#if 0
 	{ 0x1022, 0x746d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* AMD8111 */
 	{ 0x10b9, 0x5455, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALI },   /* Ali5455 */
 #endif
@@ -328,6 +319,14 @@ static void iputbyte(intel8x0_t *chip, u32 offset, u8 val)
 		outb(val, chip->bmaddr + offset);
 }
 
+static void iputword(intel8x0_t *chip, u32 offset, u16 val)
+{
+	if (chip->bm_mmio)
+		writew(val, chip->remap_bmaddr + offset);
+	else
+		outw(val, chip->bmaddr + offset);
+}
+
 static void iputdword(intel8x0_t *chip, u32 offset, u32 val)
 {
 	if (chip->bm_mmio)
@@ -408,7 +407,7 @@ static void snd_intel8x0_codec_write(ac97_t *ac97,
 				     unsigned short reg,
 				     unsigned short val)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, ac97->private_data, return);
+	intel8x0_t *chip = ac97->private_data;
 	
 	spin_lock(&chip->ac97_lock);
 	if (snd_intel8x0m_codec_semaphore(chip, ac97->num) < 0) {
@@ -422,7 +421,7 @@ static void snd_intel8x0_codec_write(ac97_t *ac97,
 static unsigned short snd_intel8x0_codec_read(ac97_t *ac97,
 					      unsigned short reg)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, ac97->private_data, return ~0);
+	intel8x0_t *chip = ac97->private_data;
 	unsigned short res;
 	unsigned int tmp;
 
@@ -542,13 +541,17 @@ static inline void snd_intel8x0_update(intel8x0_t *chip, ichdev_t *ichdev)
 
 static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, dev_id, return IRQ_NONE);
+	intel8x0_t *chip = dev_id;
 	ichdev_t *ichdev;
 	unsigned int status;
 	unsigned int i;
 
 	spin_lock(&chip->reg_lock);
 	status = igetdword(chip, chip->int_sta_reg);
+	if (status == 0xffffffff) { /* we are not yet resumed */
+		spin_unlock(&chip->reg_lock);
+		return IRQ_NONE;
+	}
 	if ((status & chip->int_sta_mask) == 0) {
 		if (status)
 			iputdword(chip, chip->int_sta_reg, status);
@@ -684,9 +687,9 @@ static snd_pcm_hardware_t snd_intel8x0m_stream =
 	.rate_max =		16000,
 	.channels_min =		1,
 	.channels_max =		1,
-	.buffer_bytes_max =	32 * 1024,
+	.buffer_bytes_max =	64 * 1024,
 	.period_bytes_min =	32,
-	.period_bytes_max =	32 * 1024,
+	.period_bytes_max =	64 * 1024,
 	.periods_min =		1,
 	.periods_max =		1024,
 	.fifo_size =		0,
@@ -818,8 +821,8 @@ static struct ich_pcm_table intel_pcms[] __devinitdata = {
 		.suffix = "Modem",
 		.playback_ops = &snd_intel8x0m_playback_ops,
 		.capture_ops = &snd_intel8x0m_capture_ops,
-		.prealloc_size = 4 * 1024,
-		.prealloc_max_size = 16 * 1024,
+		.prealloc_size = 32 * 1024,
+		.prealloc_max_size = 64 * 1024,
 	},
 };
 
@@ -872,32 +875,30 @@ static int __devinit snd_intel8x0_pcm(intel8x0_t *chip)
 
 static void snd_intel8x0_mixer_free_ac97_bus(ac97_bus_t *bus)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, bus->private_data, return);
+	intel8x0_t *chip = bus->private_data;
 	chip->ac97_bus = NULL;
 }
 
 static void snd_intel8x0_mixer_free_ac97(ac97_t *ac97)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, ac97->private_data, return);
+	intel8x0_t *chip = ac97->private_data;
 	chip->ac97 = NULL;
 }
 
 
 static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
 {
-	ac97_bus_t bus, *pbus;
-	ac97_t ac97, *x97;
+	ac97_bus_t *pbus;
+	ac97_template_t ac97;
+	ac97_t *x97;
 	int err;
 	unsigned int glob_sta = 0;
+	static ac97_bus_ops_t ops = {
+		.write = snd_intel8x0_codec_write,
+		.read = snd_intel8x0_codec_read,
+	};
 
 	chip->in_ac97_init = 1;
-	memset(&bus, 0, sizeof(bus));
-	bus.private_data = chip;
-	bus.private_free = snd_intel8x0_mixer_free_ac97_bus;
-	if (ac97_clock >= 8000 && ac97_clock <= 48000)
-		bus.clock = ac97_clock;
-	else
-		bus.clock = 48000;
 	
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = chip;
@@ -905,13 +906,15 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
 	ac97.scaps = AC97_SCAP_SKIP_AUDIO;
 
 	glob_sta = igetdword(chip, ICHREG(GLOB_STA));
-	bus.write = snd_intel8x0_codec_write;
-	bus.read = snd_intel8x0_codec_read;
-	bus.vra = 1;
 
-	if ((err = snd_ac97_bus(chip->card, &bus, &pbus)) < 0)
+	if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0)
 		goto __err;
+	pbus->private_free = snd_intel8x0_mixer_free_ac97_bus;
+	pbus->shared_type = AC97_SHARED_TYPE_ICH;	/* shared with audio driver */
+	if (ac97_clock >= 8000 && ac97_clock <= 48000)
+		pbus->clock = ac97_clock;
 	chip->ac97_bus = pbus;
+
 	ac97.pci = chip->pci;
 	ac97.num = glob_sta & ICH_SCR ? 1 : 0;
 	if ((err = snd_ac97_mixer(pbus, &ac97, &x97)) < 0) {
@@ -1016,6 +1019,11 @@ static int snd_intel8x0m_ich_chip_init(intel8x0_t *chip, int probing)
 		} while (time_after_eq(end_time, jiffies));
 	}
 
+	if (chip->device_type == DEVICE_SIS) {
+		/* unmute the output on SIS7012 */
+		iputword(chip, 0x4c, igetword(chip, 0x4c) | 1);
+	}
+
       	return 0;
 }
 
@@ -1056,22 +1064,15 @@ static int snd_intel8x0_free(intel8x0_t *chip)
 	synchronize_irq(chip->irq);
       __hw_end:
 	if (chip->bdbars.area)
-		snd_dma_free_pages(&chip->dma_dev, &chip->bdbars);
+		snd_dma_free_pages(&chip->bdbars);
 	if (chip->remap_addr)
 		iounmap((void *) chip->remap_addr);
 	if (chip->remap_bmaddr)
 		iounmap((void *) chip->remap_bmaddr);
-	if (chip->res) {
-		release_resource(chip->res);
-		kfree_nocheck(chip->res);
-	}
-	if (chip->res_bm) {
-		release_resource(chip->res_bm);
-		kfree_nocheck(chip->res_bm);
-	}
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void *)chip);
-	snd_magic_kfree(chip);
+	pci_release_regions(chip->pci);
+	kfree(chip);
 	return 0;
 }
 
@@ -1081,7 +1082,7 @@ static int snd_intel8x0_free(intel8x0_t *chip)
  */
 static int intel8x0m_suspend(snd_card_t *card, unsigned int state)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, card->pm_private_data, return -EINVAL);
+	intel8x0_t *chip = card->pm_private_data;
 	int i;
 
 	for (i = 0; i < chip->pcm_devs; i++)
@@ -1094,7 +1095,7 @@ static int intel8x0m_suspend(snd_card_t *card, unsigned int state)
 
 static int intel8x0m_resume(snd_card_t *card, unsigned int state)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, card->pm_private_data, return -EINVAL);
+	intel8x0_t *chip = card->pm_private_data;
 	pci_enable_device(chip->pci);
 	pci_set_master(chip->pci);
 	snd_intel8x0_chip_init(chip, 0);
@@ -1109,7 +1110,7 @@ static int intel8x0m_resume(snd_card_t *card, unsigned int state)
 static void snd_intel8x0m_proc_read(snd_info_entry_t * entry,
 				   snd_info_buffer_t * buffer)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, entry->private_data, return);
+	intel8x0_t *chip = entry->private_data;
 	unsigned int tmp;
 
 	snd_iprintf(buffer, "Intel8x0m\n\n");
@@ -1135,7 +1136,7 @@ static void __devinit snd_intel8x0m_proc_init(intel8x0_t * chip)
 
 static int snd_intel8x0_dev_free(snd_device_t *device)
 {
-	intel8x0_t *chip = snd_magic_cast(intel8x0_t, device->device_data, return -ENXIO);
+	intel8x0_t *chip = device->device_data;
 	return snd_intel8x0_free(chip);
 }
 
@@ -1168,7 +1169,7 @@ static int __devinit snd_intel8x0m_create(snd_card_t * card,
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	chip = snd_magic_kcalloc(intel8x0_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	spin_lock_init(&chip->reg_lock);
@@ -1177,29 +1178,23 @@ static int __devinit snd_intel8x0m_create(snd_card_t * card,
 	chip->card = card;
 	chip->pci = pci;
 	chip->irq = -1;
-	snd_intel8x0m_proc_init(chip);
-	sprintf(chip->ac97_name, "%s - AC'97", card->shortname);
-	sprintf(chip->ctrl_name, "%s - Controller", card->shortname);
+
+	if ((err = pci_request_regions(pci, card->shortname)) < 0) {
+		kfree(chip);
+		return err;
+	}
+
 	if (device_type == DEVICE_ALI) {
 		/* ALI5455 has no ac97 region */
 		chip->bmaddr = pci_resource_start(pci, 0);
-		if ((chip->res_bm = request_region(chip->bmaddr, 256, chip->ctrl_name)) == NULL) {
-			snd_printk("unable to grab ports 0x%lx-0x%lx\n", chip->bmaddr, chip->bmaddr + 256 - 1);
-			snd_intel8x0_free(chip);
-			return -EBUSY;
-		}
 		goto port_inited;
 	}
 
 	if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) {	/* ICH4 and Nforce */
 		chip->mmio = 1;
 		chip->addr = pci_resource_start(pci, 2);
-		if ((chip->res = request_mem_region(chip->addr, 512, chip->ac97_name)) == NULL) {
-			snd_printk("unable to grab I/O memory 0x%lx-0x%lx\n", chip->addr, chip->addr + 512 - 1);
-			snd_intel8x0_free(chip);
-			return -EBUSY;
-		}
-		chip->remap_addr = (unsigned long) ioremap_nocache(chip->addr, 512);
+		chip->remap_addr = (unsigned long) ioremap_nocache(chip->addr,
+								   pci_resource_len(pci, 2));
 		if (chip->remap_addr == 0) {
 			snd_printk("AC'97 space ioremap problem\n");
 			snd_intel8x0_free(chip);
@@ -1207,21 +1202,12 @@ static int __devinit snd_intel8x0m_create(snd_card_t * card,
 		}
 	} else {
 		chip->addr = pci_resource_start(pci, 0);
-		if ((chip->res = request_region(chip->addr, 256, chip->ac97_name)) == NULL) {
-			snd_printk("unable to grab ports 0x%lx-0x%lx\n", chip->addr, chip->addr + 256 - 1);
-			snd_intel8x0_free(chip);
-			return -EBUSY;
-		}
 	}
 	if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) {	/* ICH4 */
 		chip->bm_mmio = 1;
 		chip->bmaddr = pci_resource_start(pci, 3);
-		if ((chip->res_bm = request_mem_region(chip->bmaddr, 256, chip->ctrl_name)) == NULL) {
-			snd_printk("unable to grab I/O memory 0x%lx-0x%lx\n", chip->bmaddr, chip->bmaddr + 512 - 1);
-			snd_intel8x0_free(chip);
-			return -EBUSY;
-		}
-		chip->remap_bmaddr = (unsigned long) ioremap_nocache(chip->bmaddr, 256);
+		chip->remap_bmaddr = (unsigned long) ioremap_nocache(chip->bmaddr,
+								     pci_resource_len(pci, 3));
 		if (chip->remap_bmaddr == 0) {
 			snd_printk("Controller space ioremap problem\n");
 			snd_intel8x0_free(chip);
@@ -1229,11 +1215,6 @@ static int __devinit snd_intel8x0m_create(snd_card_t * card,
 		}
 	} else {
 		chip->bmaddr = pci_resource_start(pci, 1);
-		if ((chip->res_bm = request_region(chip->bmaddr, 128, chip->ctrl_name)) == NULL) {
-			snd_printk("unable to grab ports 0x%lx-0x%lx\n", chip->bmaddr, chip->bmaddr + 128 - 1);
-			snd_intel8x0_free(chip);
-			return -EBUSY;
-		}
 	}
 
  port_inited:
@@ -1271,10 +1252,9 @@ static int __devinit snd_intel8x0m_create(snd_card_t * card,
 
 	/* allocate buffer descriptor lists */
 	/* the start of each lists must be aligned to 8 bytes */
-	memset(&chip->dma_dev, 0, sizeof(chip->dma_dev));
-	chip->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	chip->dma_dev.dev = snd_dma_pci_data(pci);
-	if (snd_dma_alloc_pages(&chip->dma_dev, chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2, &chip->bdbars) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2,
+				&chip->bdbars) < 0) {
 		snd_intel8x0_free(chip);
 		return -ENOMEM;
 	}
@@ -1320,11 +1300,12 @@ static struct shortname_table {
 	{ PCI_DEVICE_ID_INTEL_ICH4_6, "Intel 82801DB-ICH4" },
 	{ PCI_DEVICE_ID_INTEL_ICH5_6, "Intel ICH5" },
 	{ 0x7446, "AMD AMD768" },
-#if 0
 	{ PCI_DEVICE_ID_SI_7013, "SiS SI7013" },
-	{ PCI_DEVICE_ID_NVIDIA_MCP_AUDIO, "NVidia nForce" },
-	{ PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO, "NVidia nForce2" },
-	{ PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO, "NVidia nForce3" },
+	{ PCI_DEVICE_ID_NVIDIA_MCP_MODEM, "NVidia nForce" },
+	{ PCI_DEVICE_ID_NVIDIA_MCP2_MODEM, "NVidia nForce2" },
+	{ PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM, "NVidia nForce2s" },
+	{ PCI_DEVICE_ID_NVIDIA_MCP3_MODEM, "NVidia nForce3" },
+#if 0
 	{ 0x5455, "ALi M5455" },
 	{ 0x746d, "AMD AMD8111" },
 #endif
@@ -1353,10 +1334,10 @@ static int __devinit snd_intel8x0m_probe(struct pci_dev *pci,
 
 	switch (pci_id->driver_data) {
 	case DEVICE_NFORCE:
-		strcpy(card->driver, "NFORCE");
+		strcpy(card->driver, "NFORCE-MODEM");
 		break;
 	default:
-		strcpy(card->driver, "ICH");
+		strcpy(card->driver, "ICH-MODEM");
 		break;
 	}
 
@@ -1383,6 +1364,8 @@ static int __devinit snd_intel8x0m_probe(struct pci_dev *pci,
 		return err;
 	}
 	
+	snd_intel8x0m_proc_init(chip);
+
 	sprintf(card->longname, "%s at 0x%lx, irq %i",
 		card->shortname, chip->addr, chip->irq);
 
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index edd226021..c04462fd1 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -343,12 +343,6 @@ struct _snd_korg1212 {
         unsigned long inIRQ;
         unsigned long iobase;
 
-	struct resource *res_iomem;
-	struct resource *res_ioport;
-	struct resource *res_iomem2;
-
-	struct snd_dma_device dma_dev;
-
 	struct snd_dma_buffer dma_dsp;
         struct snd_dma_buffer dma_play;
         struct snd_dma_buffer dma_rec;
@@ -411,8 +405,7 @@ struct _snd_korg1212 {
 
 MODULE_DESCRIPTION("korg1212");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{KORG,korg1212}}");
+MODULE_SUPPORTED_DEVICE("{{KORG,korg1212}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	   /* ID for this card */
@@ -421,13 +414,10 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Korg 1212 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Korg 1212 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Korg 1212 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 MODULE_AUTHOR("Haroldo Gamal <gamal@alternex.com.br>");
 
 static struct pci_device_id snd_korg1212_ids[] = {
@@ -637,7 +627,7 @@ static void snd_korg1212_SendStopAndWait(korg1212_t *korg1212)
 /* timer callback for checking the ack of stop request */
 static void snd_korg1212_timer_func(unsigned long data)
 {
-        korg1212_t *korg1212 = snd_magic_cast(korg1212_t, (void*)data, return);
+        korg1212_t *korg1212 = (korg1212_t *) data;
 	
 	spin_lock(&korg1212->lock);
 	if (readl(&korg1212->sharedBufferPtr->cardCommand) == 0) {
@@ -1143,7 +1133,7 @@ static void snd_korg1212_OnDSPDownloadComplete(korg1212_t *korg1212)
 static irqreturn_t snd_korg1212_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
         u32 doorbellValue;
-        korg1212_t *korg1212 = snd_magic_cast(korg1212_t, dev_id, return IRQ_NONE);
+        korg1212_t *korg1212 = dev_id;
 
 	if(irq != korg1212->irq)
 		return IRQ_NONE;
@@ -1407,7 +1397,7 @@ static void snd_korg1212_free_pcm(snd_pcm_t *pcm)
 static int snd_korg1212_playback_open(snd_pcm_substream_t *substream)
 {
         unsigned long flags;
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
         snd_pcm_runtime_t *runtime = substream->runtime;
 
 #if K1212_DEBUG_LEVEL > 0
@@ -1419,8 +1409,7 @@ static int snd_korg1212_playback_open(snd_pcm_substream_t *substream)
 	snd_korg1212_OpenCard(korg1212);
 
         runtime->hw = snd_korg1212_playback_info;
-	runtime->dma_area = (char *) korg1212->playDataBufsPtr;
-	runtime->dma_bytes = K1212_BUF_SIZE;
+	snd_pcm_set_runtime_buffer(substream, &korg1212->dma_play);
 
         spin_lock_irqsave(&korg1212->lock, flags);
 
@@ -1438,7 +1427,7 @@ static int snd_korg1212_playback_open(snd_pcm_substream_t *substream)
 static int snd_korg1212_capture_open(snd_pcm_substream_t *substream)
 {
         unsigned long flags;
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
         snd_pcm_runtime_t *runtime = substream->runtime;
 
 #if K1212_DEBUG_LEVEL > 0
@@ -1450,8 +1439,7 @@ static int snd_korg1212_capture_open(snd_pcm_substream_t *substream)
 	snd_korg1212_OpenCard(korg1212);
 
         runtime->hw = snd_korg1212_capture_info;
-	runtime->dma_area = (char *) korg1212->recordDataBufsPtr;
-	runtime->dma_bytes = K1212_BUF_SIZE;
+	snd_pcm_set_runtime_buffer(substream, &korg1212->dma_rec);
 
         spin_lock_irqsave(&korg1212->lock, flags);
 
@@ -1468,7 +1456,7 @@ static int snd_korg1212_capture_open(snd_pcm_substream_t *substream)
 static int snd_korg1212_playback_close(snd_pcm_substream_t *substream)
 {
         unsigned long flags;
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
 
 #if K1212_DEBUG_LEVEL > 0
 		K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_close [%s]\n", stateName[korg1212->cardState]);
@@ -1490,7 +1478,7 @@ static int snd_korg1212_playback_close(snd_pcm_substream_t *substream)
 static int snd_korg1212_capture_close(snd_pcm_substream_t *substream)
 {
         unsigned long flags;
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
 
 #if K1212_DEBUG_LEVEL > 0
 		K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_close [%s]\n", stateName[korg1212->cardState]);
@@ -1532,7 +1520,7 @@ static int snd_korg1212_hw_params(snd_pcm_substream_t *substream,
                              snd_pcm_hw_params_t *params)
 {
         unsigned long flags;
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
         int err;
 
 #if K1212_DEBUG_LEVEL > 0
@@ -1560,21 +1548,21 @@ static int snd_korg1212_hw_params(snd_pcm_substream_t *substream,
 
 static int snd_korg1212_prepare(snd_pcm_substream_t *substream)
 {
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
 	int rc;
 
 #if K1212_DEBUG_LEVEL > 0
 		K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_prepare [%s]\n", stateName[korg1212->cardState]);
 #endif
 
-        spin_lock(&korg1212->lock);
+	spin_lock_irq(&korg1212->lock);
 
 	/* FIXME: we should wait for ack! */
 	if (korg1212->stop_pending_cnt > 0) {
 #if K1212_DEBUG_LEVEL > 0
 		K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_prepare - Stop is pending... [%s]\n", stateName[korg1212->cardState]);
 #endif
-        	spin_unlock(&korg1212->lock);
+        	spin_unlock_irq(&korg1212->lock);
 		return -EAGAIN;
 		/*
 		writel(0, &korg1212->sharedBufferPtr->cardCommand);
@@ -1587,7 +1575,7 @@ static int snd_korg1212_prepare(snd_pcm_substream_t *substream)
 
         korg1212->currentBuffer = 0;
 
-        spin_unlock(&korg1212->lock);
+        spin_unlock_irq(&korg1212->lock);
 
 	return rc ? -EINVAL : 0;
 }
@@ -1595,7 +1583,7 @@ static int snd_korg1212_prepare(snd_pcm_substream_t *substream)
 static int snd_korg1212_trigger(snd_pcm_substream_t *substream,
                            int cmd)
 {
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
 	int rc;
 
 #if K1212_DEBUG_LEVEL > 0
@@ -1640,7 +1628,7 @@ static int snd_korg1212_trigger(snd_pcm_substream_t *substream,
 
 static snd_pcm_uframes_t snd_korg1212_playback_pointer(snd_pcm_substream_t *substream)
 {
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
         snd_pcm_uframes_t pos;
 
 	pos = korg1212->currentBuffer * kPlayBufferFrames;
@@ -1655,7 +1643,7 @@ static snd_pcm_uframes_t snd_korg1212_playback_pointer(snd_pcm_substream_t *subs
 
 static snd_pcm_uframes_t snd_korg1212_capture_pointer(snd_pcm_substream_t *substream)
 {
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
         snd_pcm_uframes_t pos;
 
 	pos = korg1212->currentBuffer * kPlayBufferFrames;
@@ -1674,7 +1662,7 @@ static int snd_korg1212_playback_copy(snd_pcm_substream_t *substream,
                         void __user *src,
                         snd_pcm_uframes_t count)
 {
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
 
 #if K1212_DEBUG_LEVEL > 2
 		K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_copy [%s] %ld %ld\n", stateName[korg1212->cardState], pos, count);
@@ -1689,7 +1677,7 @@ static int snd_korg1212_playback_silence(snd_pcm_substream_t *substream,
                            snd_pcm_uframes_t pos,
                            snd_pcm_uframes_t count)
 {
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
 
 #if K1212_DEBUG_LEVEL > 0
 		K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_silence [%s]\n", stateName[korg1212->cardState]);
@@ -1704,7 +1692,7 @@ static int snd_korg1212_capture_copy(snd_pcm_substream_t *substream,
                         void __user *dst,
                         snd_pcm_uframes_t count)
 {
-        korg1212_t *korg1212 = _snd_pcm_substream_chip(substream);
+        korg1212_t *korg1212 = snd_pcm_substream_chip(substream);
 
 #if K1212_DEBUG_LEVEL > 2
 		K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_copy [%s] %ld %ld\n", stateName[korg1212->cardState], pos, count);
@@ -1749,30 +1737,28 @@ static int snd_korg1212_control_phase_info(snd_kcontrol_t *kcontrol, snd_ctl_ele
 
 static int snd_korg1212_control_phase_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
 {
-	korg1212_t *korg1212 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
 	int i = kcontrol->private_value;
 
-	spin_lock_irqsave(&korg1212->lock, flags);
+	spin_lock_irq(&korg1212->lock);
 
         u->value.integer.value[0] = korg1212->volumePhase[i];
 
 	if (i >= 8)
         	u->value.integer.value[1] = korg1212->volumePhase[i+1];
 
-        spin_unlock_irqrestore(&korg1212->lock, flags);
+	spin_unlock_irq(&korg1212->lock);
 
         return 0;
 }
 
 static int snd_korg1212_control_phase_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
 {
-	korg1212_t *korg1212 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
         int change = 0;
         int i, val;
 
-	spin_lock_irqsave(&korg1212->lock, flags);
+	spin_lock_irq(&korg1212->lock);
 
 	i = kcontrol->private_value;
 
@@ -1798,7 +1784,7 @@ static int snd_korg1212_control_phase_put(snd_kcontrol_t *kcontrol, snd_ctl_elem
 		}
 	}
 
-	spin_unlock_irqrestore(&korg1212->lock, flags);
+	spin_unlock_irq(&korg1212->lock);
 
         return change;
 }
@@ -1814,11 +1800,10 @@ static int snd_korg1212_control_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_el
 
 static int snd_korg1212_control_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
 {
-	korg1212_t *korg1212 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
         int i;
 
-	spin_lock_irqsave(&korg1212->lock, flags);
+	spin_lock_irq(&korg1212->lock);
 
 	i = kcontrol->private_value;
         u->value.integer.value[0] = abs(korg1212->sharedBufferPtr->volumeData[i]);
@@ -1826,20 +1811,19 @@ static int snd_korg1212_control_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_ele
 	if (i >= 8) 
                 u->value.integer.value[1] = abs(korg1212->sharedBufferPtr->volumeData[i+1]);
 
-        spin_unlock_irqrestore(&korg1212->lock, flags);
+        spin_unlock_irq(&korg1212->lock);
 
         return 0;
 }
 
 static int snd_korg1212_control_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
 {
-	korg1212_t *korg1212 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
         int change = 0;
         int i;
 	int val;
 
-	spin_lock_irqsave(&korg1212->lock, flags);
+	spin_lock_irq(&korg1212->lock);
 
 	i = kcontrol->private_value;
 
@@ -1859,7 +1843,7 @@ static int snd_korg1212_control_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_ele
 		}
 	}
 
-	spin_unlock_irqrestore(&korg1212->lock, flags);
+	spin_unlock_irq(&korg1212->lock);
 
         return change;
 }
@@ -1878,11 +1862,10 @@ static int snd_korg1212_control_route_info(snd_kcontrol_t *kcontrol, snd_ctl_ele
 
 static int snd_korg1212_control_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
 {
-	korg1212_t *korg1212 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
         int i;
 
-	spin_lock_irqsave(&korg1212->lock, flags);
+	spin_lock_irq(&korg1212->lock);
 
 	i = kcontrol->private_value;
 	u->value.enumerated.item[0] = korg1212->sharedBufferPtr->routeData[i];
@@ -1890,18 +1873,17 @@ static int snd_korg1212_control_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem
 	if (i >= 8) 
 		u->value.enumerated.item[1] = korg1212->sharedBufferPtr->routeData[i+1];
 
-        spin_unlock_irqrestore(&korg1212->lock, flags);
+        spin_unlock_irq(&korg1212->lock);
 
         return 0;
 }
 
 static int snd_korg1212_control_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
 {
-	korg1212_t *korg1212 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
         int change = 0, i;
 
-	spin_lock_irqsave(&korg1212->lock, flags);
+	spin_lock_irq(&korg1212->lock);
 
 	i = kcontrol->private_value;
 
@@ -1917,7 +1899,7 @@ static int snd_korg1212_control_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem
 		}
 	}
 
-	spin_unlock_irqrestore(&korg1212->lock, flags);
+	spin_unlock_irq(&korg1212->lock);
 
         return change;
 }
@@ -1933,26 +1915,24 @@ static int snd_korg1212_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info
 
 static int snd_korg1212_control_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
 {
-	korg1212_t *korg1212 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
 
-	spin_lock_irqsave(&korg1212->lock, flags);
+	spin_lock_irq(&korg1212->lock);
 
         u->value.integer.value[0] = korg1212->leftADCInSens;
         u->value.integer.value[1] = korg1212->rightADCInSens;
 
-        spin_unlock_irqrestore(&korg1212->lock, flags);
+	spin_unlock_irq(&korg1212->lock);
 
         return 0;
 }
 
 static int snd_korg1212_control_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
 {
-	korg1212_t *korg1212 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
         int change = 0;
 
-	spin_lock_irqsave(&korg1212->lock, flags);
+	spin_lock_irq(&korg1212->lock);
 
         if (u->value.integer.value[0] != korg1212->leftADCInSens) {
                 korg1212->leftADCInSens = u->value.integer.value[0];
@@ -1963,7 +1943,7 @@ static int snd_korg1212_control_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value
                 change = 1;
         }
 
-	spin_unlock_irqrestore(&korg1212->lock, flags);
+	spin_unlock_irq(&korg1212->lock);
 
         if (change)
                 snd_korg1212_WriteADCSensitivity(korg1212);
@@ -1985,29 +1965,27 @@ static int snd_korg1212_control_sync_info(snd_kcontrol_t *kcontrol, snd_ctl_elem
 
 static int snd_korg1212_control_sync_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	korg1212_t *korg1212 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
 
-	spin_lock_irqsave(&korg1212->lock, flags);
+	spin_lock_irq(&korg1212->lock);
 
 	ucontrol->value.enumerated.item[0] = korg1212->clkSource;
 
-	spin_unlock_irqrestore(&korg1212->lock, flags);
+	spin_unlock_irq(&korg1212->lock);
 	return 0;
 }
 
 static int snd_korg1212_control_sync_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	korg1212_t *korg1212 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	korg1212_t *korg1212 = snd_kcontrol_chip(kcontrol);
 	unsigned int val;
 	int change;
 
 	val = ucontrol->value.enumerated.item[0] % 3;
-	spin_lock_irqsave(&korg1212->lock, flags);
+	spin_lock_irq(&korg1212->lock);
 	change = val != korg1212->clkSource;
         snd_korg1212_SetClockSource(korg1212, val);
-	spin_unlock_irqrestore(&korg1212->lock, flags);
+	spin_unlock_irq(&korg1212->lock);
 	return change;
 }
 
@@ -2063,8 +2041,6 @@ static snd_kcontrol_new_t snd_korg1212_controls[] = {
         }
 };
 
-#define K1212_CONTROL_ELEMENTS (sizeof(snd_korg1212_controls) / sizeof(snd_korg1212_controls[0]))
-
 /*
  * proc interface
  */
@@ -2120,29 +2096,13 @@ snd_korg1212_free(korg1212_t *korg1212)
                 korg1212->iobase = 0;
         }
         
-        if (korg1212->res_iomem != NULL) {
-                release_resource(korg1212->res_iomem);
-                kfree_nocheck(korg1212->res_iomem);
-                korg1212->res_iomem = NULL;
-        }
-        
-        if (korg1212->res_ioport != NULL) {
-                release_resource(korg1212->res_ioport);
-                kfree_nocheck(korg1212->res_ioport);
-                korg1212->res_ioport = NULL;
-        }
-        
-        if (korg1212->res_iomem2 != NULL) {
-                release_resource(korg1212->res_iomem2);
-                kfree_nocheck(korg1212->res_iomem2);
-                korg1212->res_iomem2 = NULL;
-        }
+	pci_release_regions(korg1212->pci);
 
         // ----------------------------------------------------
         // free up memory resources used for the DSP download.
         // ----------------------------------------------------
         if (korg1212->dma_dsp.area) {
-        	snd_dma_free_pages(&korg1212->dma_dev, &korg1212->dma_dsp);
+        	snd_dma_free_pages(&korg1212->dma_dsp);
         	korg1212->dma_dsp.area = NULL;
         }
 
@@ -2152,12 +2112,12 @@ snd_korg1212_free(korg1212_t *korg1212)
         // free up memory resources used for the Play/Rec Buffers
         // ------------------------------------------------------
 	if (korg1212->dma_play.area) {
-		snd_dma_free_pages(&korg1212->dma_dev, &korg1212->dma_play);
+		snd_dma_free_pages(&korg1212->dma_play);
 		korg1212->dma_play.area = NULL;
         }
 
 	if (korg1212->dma_rec.area) {
-		snd_dma_free_pages(&korg1212->dma_dev, &korg1212->dma_rec);
+		snd_dma_free_pages(&korg1212->dma_rec);
 		korg1212->dma_rec.area = NULL;
         }
 
@@ -2167,17 +2127,17 @@ snd_korg1212_free(korg1212_t *korg1212)
         // free up memory resources used for the Shared Buffers
         // ----------------------------------------------------
 	if (korg1212->dma_shared.area) {
-		snd_dma_free_pages(&korg1212->dma_dev, &korg1212->dma_shared);
+		snd_dma_free_pages(&korg1212->dma_shared);
 		korg1212->dma_shared.area = NULL;
         }
         
-        snd_magic_kfree(korg1212);
+        kfree(korg1212);
         return 0;
 }
 
 static int snd_korg1212_dev_free(snd_device_t *device)
 {
-        korg1212_t *korg1212 = snd_magic_cast(korg1212_t, device->device_data, return -ENXIO);
+        korg1212_t *korg1212 = device->device_data;
 #if K1212_DEBUG_LEVEL > 0
         K1212_DEBUG_PRINTK("K1212_DEBUG: Freeing device\n");
 #endif
@@ -2201,7 +2161,7 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
         if ((err = pci_enable_device(pci)) < 0)
                 return err;
 
-        korg1212 = snd_magic_kcalloc(korg1212_t, 0, GFP_KERNEL);
+        korg1212 = kcalloc(1, sizeof(*korg1212), GFP_KERNEL);
         if (korg1212 == NULL)
                 return -ENOMEM;
 
@@ -2232,6 +2192,11 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
         for (i=0; i<kAudioChannels; i++)
                 korg1212->volumePhase[i] = 0;
 
+	if ((err = pci_request_regions(pci, "korg1212")) < 0) {
+		kfree(korg1212);
+		return err;
+	}
+
         korg1212->iomem = pci_resource_start(korg1212->pci, 0);
         korg1212->ioport = pci_resource_start(korg1212->pci, 1);
         korg1212->iomem2 = pci_resource_start(korg1212->pci, 2);
@@ -2252,27 +2217,6 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
 		   stateName[korg1212->cardState]);
 #endif
 
-        korg1212->res_iomem = request_mem_region(korg1212->iomem, iomem_size, "korg1212");
-        if (korg1212->res_iomem == NULL) {
-		snd_printk(KERN_ERR "unable to grab region 0x%lx-0x%lx\n",
-                           korg1212->iomem, korg1212->iomem + iomem_size - 1);
-                return -EBUSY;
-        }
-
-        korg1212->res_ioport = request_region(korg1212->ioport, ioport_size, "korg1212");
-        if (korg1212->res_ioport == NULL) {
-		snd_printk(KERN_ERR "unable to grab region 0x%lx-0x%lx\n",
-                           korg1212->ioport, korg1212->ioport + ioport_size - 1);
-                return -EBUSY;
-        }
-
-        korg1212->res_iomem2 = request_mem_region(korg1212->iomem2, iomem2_size, "korg1212");
-        if (korg1212->res_iomem2 == NULL) {
-		snd_printk(KERN_ERR "unable to grab region 0x%lx-0x%lx\n",
-                           korg1212->iomem2, korg1212->iomem2 + iomem2_size - 1);
-                return -EBUSY;
-        }
-
         if ((korg1212->iobase = (unsigned long) ioremap(korg1212->iomem, iomem_size)) == 0) {
 		snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", korg1212->iobase,
                            korg1212->iobase + iomem_size - 1);
@@ -2329,11 +2273,8 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
 		   stateName[korg1212->cardState]);
 #endif
 
-	memset(&korg1212->dma_dev, 0, sizeof(korg1212->dma_dev));
-	korg1212->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	korg1212->dma_dev.dev = snd_dma_pci_data(korg1212->pci);
-
-	if (snd_dma_alloc_pages(&korg1212->dma_dev, sizeof(KorgSharedBuffer), &korg1212->dma_shared) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				sizeof(KorgSharedBuffer), &korg1212->dma_shared) < 0) {
 		snd_printk(KERN_ERR "can not allocate shared buffer memory (%Zd bytes)\n", sizeof(KorgSharedBuffer));
                 return -ENOMEM;
         }
@@ -2348,7 +2289,8 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
 
         korg1212->DataBufsSize = sizeof(KorgAudioBuffer) * kNumBuffers;
 
-	if (snd_dma_alloc_pages(&korg1212->dma_dev, korg1212->DataBufsSize, &korg1212->dma_play) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				korg1212->DataBufsSize, &korg1212->dma_play) < 0) {
 		snd_printk(KERN_ERR "can not allocate play data buffer memory (%d bytes)\n", korg1212->DataBufsSize);
                 return -ENOMEM;
         }
@@ -2360,7 +2302,8 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
 		korg1212->playDataBufsPtr, korg1212->PlayDataPhy, korg1212->DataBufsSize);
 #endif
 
-	if (snd_dma_alloc_pages(&korg1212->dma_dev, korg1212->DataBufsSize, &korg1212->dma_rec) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				korg1212->DataBufsSize, &korg1212->dma_rec) < 0) {
 		snd_printk(KERN_ERR "can not allocate record data buffer memory (%d bytes)\n", korg1212->DataBufsSize);
                 return -ENOMEM;
         }
@@ -2390,7 +2333,8 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
         korg1212->AdatTimeCodePhy = korg1212->sharedBufferPhy +
 		offsetof(KorgSharedBuffer, AdatTimeCode);
 
-	if (snd_dma_alloc_pages(&korg1212->dma_dev, korg1212->dspCodeSize, &korg1212->dma_dsp) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				korg1212->dspCodeSize, &korg1212->dma_dsp) < 0) {
 		snd_printk(KERN_ERR "can not allocate dsp code memory (%d bytes)\n", korg1212->dspCodeSize);
                 return -ENOMEM;
         }
@@ -2420,7 +2364,7 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
                "VolumeTablePhy  = %08x L[%08x]\n"
                "RoutingTablePhy = %08x L[%08x]\n"
                "AdatTimeCodePhy = %08x L[%08x]\n",
-	       korg1212->dma_dsp.addr,    UpperWordSwap(korg1212->dma_dsp.addr),
+	       (int)korg1212->dma_dsp.addr,    UpperWordSwap(korg1212->dma_dsp.addr),
                korg1212->PlayDataPhy,     LowerWordSwap(korg1212->PlayDataPhy),
                korg1212->RecDataPhy,      LowerWordSwap(korg1212->RecDataPhy),
                korg1212->VolumeTablePhy,  LowerWordSwap(korg1212->VolumeTablePhy),
@@ -2443,7 +2387,7 @@ static int __devinit snd_korg1212_create(snd_card_t * card, struct pci_dev *pci,
 	//snd_pcm_lib_preallocate_pages_for_all(korg1212->pcm,
 	//			K1212_MAX_BUF_SIZE, K1212_MAX_BUF_SIZE, GFP_KERNEL);
 
-        for (i = 0; i < K1212_CONTROL_ELEMENTS; i++) {
+        for (i = 0; i < ARRAY_SIZE(snd_korg1212_controls); i++) {
                 err = snd_ctl_add(korg1212->card, snd_ctl_new1(&snd_korg1212_controls[i], korg1212));
                 if (err < 0)
                         return err;
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index eabfcd30d..8cf0e185d 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -51,8 +51,7 @@
 MODULE_AUTHOR("Zach Brown <zab@zabbo.net>, Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("ESS Maestro3 PCI");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{ESS,Maestro3 PCI},"
+MODULE_SUPPORTED_DEVICE("{{ESS,Maestro3 PCI},"
 		"{ESS,ES1988},"
 		"{ESS,Allegro PCI},"
 		"{ESS,Allegro-1 PCI},"
@@ -67,19 +66,14 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable this soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(external_amp, bool, boot_devs, 0444);
 MODULE_PARM_DESC(external_amp, "Enable external amp for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(external_amp, SNDRV_ENABLED "," SNDRV_BOOLEAN_TRUE_DESC);
 module_param_array(amp_gpio, int, boot_devs, 0444);
 MODULE_PARM_DESC(amp_gpio, "GPIO pin number for external amp. (default = -1)");
-MODULE_PARM_SYNTAX(amp_gpio, SNDRV_ENABLED);
 
 #define MAX_PLAYBACKS	2
 #define MAX_CAPTURES	1
@@ -776,8 +770,6 @@ MODULE_PARM_SYNTAX(amp_gpio, SNDRV_ENABLED);
 
 typedef struct snd_m3_dma m3_dma_t;
 typedef struct snd_m3 m3_t;
-#define chip_t m3_t
-
 
 /* quirk lists */
 struct m3_quirk {
@@ -827,7 +819,6 @@ struct snd_m3 {
 	snd_card_t *card;
 
 	unsigned long iobase;
-	struct resource *iobase_res;
 
 	int irq;
 	int allegro_flag : 1;
@@ -1165,12 +1156,11 @@ snd_m3_pcm_trigger(snd_pcm_substream_t *subs, int cmd)
 {
 	m3_t *chip = snd_pcm_substream_chip(subs);
 	m3_dma_t *s = (m3_dma_t*)subs->runtime->private_data;
-	unsigned long flags;
 	int err = -EINVAL;
 
 	snd_assert(s != NULL, return -ENXIO);
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
@@ -1191,7 +1181,7 @@ snd_m3_pcm_trigger(snd_pcm_substream_t *subs, int cmd)
 		}
 		break;
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return err;
 }
 
@@ -1477,7 +1467,6 @@ snd_m3_pcm_prepare(snd_pcm_substream_t *subs)
 	m3_t *chip = snd_pcm_substream_chip(subs);
 	snd_pcm_runtime_t *runtime = subs->runtime;
 	m3_dma_t *s = (m3_dma_t*)runtime->private_data;
-	unsigned long flags;
 
 	snd_assert(s != NULL, return -ENXIO);
 
@@ -1488,7 +1477,7 @@ snd_m3_pcm_prepare(snd_pcm_substream_t *subs)
 	    runtime->rate < 8000)
 		return -EINVAL;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 
 	snd_m3_pcm_setup1(chip, s, subs);
 
@@ -1499,7 +1488,7 @@ snd_m3_pcm_prepare(snd_pcm_substream_t *subs)
 
 	snd_m3_pcm_setup2(chip, s, runtime);
 
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 
 	return 0;
 }
@@ -1573,7 +1562,7 @@ static void snd_m3_update_ptr(m3_t *chip, m3_dma_t *s)
 static irqreturn_t
 snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	m3_t *chip = snd_magic_cast(m3_t, dev_id, );
+	m3_t *chip = dev_id;
 	u8 status;
 	int i;
 
@@ -1670,20 +1659,19 @@ snd_m3_substream_open(m3_t *chip, snd_pcm_substream_t *subs)
 {
 	int i;
 	m3_dma_t *s;
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	for (i = 0; i < chip->num_substreams; i++) {
 		s = &chip->substreams[i];
 		if (! s->opened)
 			goto __found;
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return -ENOMEM;
 __found:
 	s->opened = 1;
 	s->running = 0;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 
 	subs->runtime->private_data = s;
 	s->substream = subs;
@@ -1703,12 +1691,11 @@ static void
 snd_m3_substream_close(m3_t *chip, snd_pcm_substream_t *subs)
 {
 	m3_dma_t *s = (m3_dma_t*) subs->runtime->private_data;
-	unsigned long flags;
 
 	if (s == NULL)
 		return; /* not opened properly */
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	if (s->substream && s->running)
 		snd_m3_pcm_stop(chip, s, s->substream); /* does this happen? */
 	if (s->in_lists) {
@@ -1719,7 +1706,7 @@ snd_m3_substream_close(m3_t *chip, snd_pcm_substream_t *subs)
 	}
 	s->running = 0;
 	s->opened = 0;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 }
 
 static int
@@ -1848,7 +1835,7 @@ static int snd_m3_ac97_wait(m3_t *chip)
 static unsigned short
 snd_m3_ac97_read(ac97_t *ac97, unsigned short reg)
 {
-	m3_t *chip = snd_magic_cast(m3_t, ac97->private_data, return -ENXIO);
+	m3_t *chip = ac97->private_data;
 	unsigned short ret = 0;
 	unsigned long flags;
 
@@ -1867,7 +1854,7 @@ __error:
 static void
 snd_m3_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
 {
-	m3_t *chip = snd_magic_cast(m3_t, ac97->private_data, return);
+	m3_t *chip = ac97->private_data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&chip->reg_lock, flags);
@@ -1983,14 +1970,15 @@ static void snd_m3_ac97_reset(m3_t *chip)
 
 static int __devinit snd_m3_mixer(m3_t *chip)
 {
-	ac97_bus_t bus, *pbus;
-	ac97_t ac97;
+	ac97_bus_t *pbus;
+	ac97_template_t ac97;
 	int err;
+	static ac97_bus_ops_t ops = {
+		.write = snd_m3_ac97_write,
+		.read = snd_m3_ac97_read,
+	};
 
-	memset(&bus, 0, sizeof(bus));
-	bus.write = snd_m3_ac97_write;
-	bus.read = snd_m3_ac97_read;
-	if ((err = snd_ac97_bus(chip->card, &bus, &pbus)) < 0)
+	if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0)
 		return err;
 	
 	memset(&ac97, 0, sizeof(ac97));
@@ -2167,7 +2155,7 @@ static void __devinit snd_m3_assp_init(m3_t *chip)
 			  KDATA_DMA_XFER0);
 
 	/* write kernel into code memory.. */
-	for (i = 0 ; i < sizeof(assp_kernel_image) / 2; i++) {
+	for (i = 0 ; i < ARRAY_SIZE(assp_kernel_image); i++) {
 		snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, 
 				  REV_B_CODE_MEMORY_BEGIN + i, 
 				  assp_kernel_image[i]);
@@ -2179,7 +2167,7 @@ static void __devinit snd_m3_assp_init(m3_t *chip)
 	 * drop it there.  It seems that the minisrc doesn't
 	 * need vectors, so we won't bother with them..
 	 */
-	for (i = 0; i < sizeof(assp_minisrc_image) / 2; i++) {
+	for (i = 0; i < ARRAY_SIZE(assp_minisrc_image); i++) {
 		snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, 
 				  0x400 + i, 
 				  assp_minisrc_image[i]);
@@ -2368,22 +2356,21 @@ snd_m3_enable_ints(m3_t *chip)
 
 static int snd_m3_free(m3_t *chip)
 {
-	unsigned long flags;
 	m3_dma_t *s;
 	int i;
 
 	if (chip->substreams) {
-		spin_lock_irqsave(&chip->reg_lock, flags);
+		spin_lock_irq(&chip->reg_lock);
 		for (i = 0; i < chip->num_substreams; i++) {
 			s = &chip->substreams[i];
 			/* check surviving pcms; this should not happen though.. */
 			if (s->substream && s->running)
 				snd_m3_pcm_stop(chip, s, s->substream);
 		}
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		spin_unlock_irq(&chip->reg_lock);
 		kfree(chip->substreams);
 	}
-	if (chip->iobase_res) {
+	if (chip->iobase) {
 		snd_m3_outw(chip, HOST_INT_CTRL, 0); /* disable ints */
 	}
 
@@ -2392,17 +2379,15 @@ static int snd_m3_free(m3_t *chip)
 		vfree(chip->suspend_mem);
 #endif
 
-	if (chip->irq >= 0)
+	if (chip->irq >= 0) {
 		synchronize_irq(chip->irq);
-
-	if (chip->iobase_res) {
-		release_resource(chip->iobase_res);
-		kfree_nocheck(chip->iobase_res);
-	}
-	if (chip->irq >= 0)
 		free_irq(chip->irq, (void *)chip);
+	}
+
+	if (chip->iobase)
+		pci_release_regions(chip->pci);
 
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
@@ -2413,7 +2398,7 @@ static int snd_m3_free(m3_t *chip)
 #ifdef CONFIG_PM
 static int m3_suspend(snd_card_t *card, unsigned int state)
 {
-	m3_t *chip = snd_magic_cast(m3_t, card->pm_private_data, return -EINVAL);
+	m3_t *chip = card->pm_private_data;
 	int i, index;
 
 	if (chip->suspend_mem == NULL)
@@ -2444,12 +2429,14 @@ static int m3_suspend(snd_card_t *card, unsigned int state)
 
 static int m3_resume(snd_card_t *card, unsigned int state)
 {
-	m3_t *chip = snd_magic_cast(m3_t, card->pm_private_data, return -EINVAL);
+	m3_t *chip = card->pm_private_data;
 	int i, index;
 
 	if (chip->suspend_mem == NULL)
 		return 0;
 
+	pci_set_master(chip->pci);
+
 	/* first lets just bring everything back. .*/
 	snd_m3_outw(chip, 0, 0x54);
 	snd_m3_outw(chip, 0, 0x56);
@@ -2489,7 +2476,7 @@ static int m3_resume(snd_card_t *card, unsigned int state)
 
 static int snd_m3_dev_free(snd_device_t *device)
 {
-	m3_t *chip = snd_magic_cast(m3_t, device->device_data, return -ENXIO);
+	m3_t *chip = device->device_data;
 	return snd_m3_free(chip);
 }
 
@@ -2519,7 +2506,7 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
 		return -ENXIO;
 	}
 
-	chip = snd_magic_kcalloc(m3_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 
@@ -2562,18 +2549,16 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
 	chip->num_substreams = NR_DSPS;
 	chip->substreams = kmalloc(sizeof(m3_dma_t) * chip->num_substreams, GFP_KERNEL);
 	if (chip->substreams == NULL) {
-		snd_magic_kfree(chip);
+		kfree(chip);
 		return -ENOMEM;
 	}
 	memset(chip->substreams, 0, sizeof(m3_dma_t) * chip->num_substreams);
 
-	chip->iobase = pci_resource_start(pci, 0);
-	if ((chip->iobase_res = request_region(chip->iobase, 256,
-					       card->driver)) == NULL) {
-		snd_printk("unable to grab i/o ports %ld\n", chip->iobase);
+	if ((err = pci_request_regions(pci, card->driver)) < 0) {
 		snd_m3_free(chip);
-		return -EBUSY;
+		return err;
 	}
+	chip->iobase = pci_resource_start(pci, 0);
 	
 	/* just to be sure */
 	pci_set_master(pci);
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index 7e312df0c..9dff42a19 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -42,25 +42,19 @@
 MODULE_AUTHOR("Digigram <alsa@digigram.com>");
 MODULE_DESCRIPTION("Digigram " CARD_NAME);
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Digigram," CARD_NAME "}}");
+MODULE_SUPPORTED_DEVICE("{{Digigram," CARD_NAME "}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;             /* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;              /* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;     /* Enable this card */
 static int boot_devs;
 
-#define chip_t mixart_t
-
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Digigram " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Digigram " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Digigram " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 
 /*
  */
@@ -247,21 +241,27 @@ mixart_pipe_t* snd_mixart_add_ref_pipe( mixart_t *chip, int pcm_number, int capt
 	/* pipe is not yet defined */
 	if( pipe->status == PIPE_UNDEFINED ) {
 		int err, i;
-		mixart_streaming_group_t streaming_group_resp;
-		mixart_streaming_group_req_t streaming_group_req;
+		struct {
+			mixart_streaming_group_req_t sgroup_req;
+			mixart_streaming_group_t sgroup_resp;
+		} *buf;
 
 		snd_printdd("add_ref_pipe audio chip(%d) pcm(%d)\n", chip->chip_idx, pcm_number);
 
+		buf = kmalloc(sizeof(*buf), GFP_KERNEL);
+		if (!buf)
+			return NULL;
+
 		request.uid = (mixart_uid_t){0,0};      /* should be StreamManagerUID, but zero is OK if there is only one ! */
-		request.data = &streaming_group_req;
-		request.size = sizeof(streaming_group_req);
+		request.data = &buf->sgroup_req;
+		request.size = sizeof(buf->sgroup_req);
 
-		memset(&streaming_group_req, 0, sizeof(streaming_group_req));
+		memset(&buf->sgroup_req, 0, sizeof(buf->sgroup_req));
 
-		streaming_group_req.stream_count = stream_count;
-		streaming_group_req.channel_count = 2;
-		streaming_group_req.latency = 256;
-		streaming_group_req.connector = pipe->uid_left_connector;  /* the left connector */
+		buf->sgroup_req.stream_count = stream_count;
+		buf->sgroup_req.channel_count = 2;
+		buf->sgroup_req.latency = 256;
+		buf->sgroup_req.connector = pipe->uid_left_connector;  /* the left connector */
 
 		for (i=0; i<stream_count; i++) {
 			int j;
@@ -269,15 +269,15 @@ mixart_pipe_t* snd_mixart_add_ref_pipe( mixart_t *chip, int pcm_number, int capt
 			struct mixart_bufferinfo *bufferinfo;
 			
 			/* we don't yet know the format, so config 16 bit pcm audio for instance */
-			streaming_group_req.stream_info[i].size_max_byte_frame = 1024;
-			streaming_group_req.stream_info[i].size_max_sample_frame = 256;
-			streaming_group_req.stream_info[i].nb_bytes_max_per_sample = MIXART_FLOAT_P__4_0_TO_HEX; /* is 4.0f */
+			buf->sgroup_req.stream_info[i].size_max_byte_frame = 1024;
+			buf->sgroup_req.stream_info[i].size_max_sample_frame = 256;
+			buf->sgroup_req.stream_info[i].nb_bytes_max_per_sample = MIXART_FLOAT_P__4_0_TO_HEX; /* is 4.0f */
 
 			/* find the right bufferinfo_array */
 			j = (chip->chip_idx * MIXART_MAX_STREAM_PER_CARD) + (pcm_number * (MIXART_PLAYBACK_STREAMS + MIXART_CAPTURE_STREAMS)) + i;
 			if(capture) j += MIXART_PLAYBACK_STREAMS; /* in the array capture is behind playback */
 
-			streaming_group_req.flow_entry[i] = j;
+			buf->sgroup_req.flow_entry[i] = j;
 
 			flowinfo = (struct mixart_flowinfo *)chip->mgr->flowinfo.area;
 			flowinfo[j].bufferinfo_array_phy_address = (u32)chip->mgr->bufferinfo.addr + (j * sizeof(mixart_bufferinfo_t));
@@ -294,17 +294,19 @@ mixart_pipe_t* snd_mixart_add_ref_pipe( mixart_t *chip, int pcm_number, int capt
 			}
 		}
 
-		err = snd_mixart_send_msg(chip->mgr, &request, sizeof(streaming_group_resp), &streaming_group_resp);
-		if((err < 0) || (streaming_group_resp.status != 0)) {
-			snd_printk(KERN_ERR "error MSG_STREAM_ADD_**PUT_GROUP err=%x stat=%x !\n", err, streaming_group_resp.status);
+		err = snd_mixart_send_msg(chip->mgr, &request, sizeof(buf->sgroup_resp), &buf->sgroup_resp);
+		if((err < 0) || (buf->sgroup_resp.status != 0)) {
+			snd_printk(KERN_ERR "error MSG_STREAM_ADD_**PUT_GROUP err=%x stat=%x !\n", err, buf->sgroup_resp.status);
+			kfree(buf);
 			return NULL;
 		}
 
-		pipe->group_uid = streaming_group_resp.group;     /* id of the pipe, as returned by embedded */
-		pipe->stream_count = streaming_group_resp.stream_count;
-		/* pipe->stream_uid[i] = streaming_group_resp.stream[i].stream_uid; */
+		pipe->group_uid = buf->sgroup_resp.group;     /* id of the pipe, as returned by embedded */
+		pipe->stream_count = buf->sgroup_resp.stream_count;
+		/* pipe->stream_uid[i] = buf->sgroup_resp.stream[i].stream_uid; */
 
 		pipe->status = PIPE_STOPPED;
+		kfree(buf);
 	}
 
 	if(monitoring)	pipe->monitoring = 1;
@@ -458,8 +460,6 @@ static int mixart_sync_nonblock_events(mixart_mgr_t *mgr)
 
 /*
  *  prepare callback for all pcms
- *
- *  NOTE: this callback is non-atomic (pcm->info_flags |= SNDRV_PCM_INFO_NONATOMIC_OPS)
  */
 static int snd_mixart_prepare(snd_pcm_substream_t *subs)
 {
@@ -620,7 +620,10 @@ static int snd_mixart_hw_params(snd_pcm_substream_t *subs,
 		bufferinfo[i].available_length = subs->runtime->dma_bytes;
 		/* bufferinfo[i].buffer_id  is already defined */
 
-		snd_printdd("snd_mixart_hw_params(pcm %d) : dma_addr(%x) dma_bytes(%x) subs-number(%d)\n", i, subs->runtime->dma_addr, subs->runtime->dma_bytes, subs->number);
+		snd_printdd("snd_mixart_hw_params(pcm %d) : dma_addr(%x) dma_bytes(%x) subs-number(%d)\n", i,
+				bufferinfo[i].buffer_address,
+				bufferinfo[i].available_length,
+				subs->number);
 	}
 	up(&mgr->setup_mutex);
 
@@ -901,6 +904,7 @@ static snd_pcm_ops_t snd_mixart_capture_ops = {
 
 static void preallocate_buffers(mixart_t *chip, snd_pcm_t *pcm)
 {
+#if 0
 	snd_pcm_substream_t *subs;
 	int stream;
 
@@ -912,6 +916,7 @@ static void preallocate_buffers(mixart_t *chip, snd_pcm_t *pcm)
 				subs->stream << 8 | (subs->number + 1) |
 				(chip->chip_idx + 1) << 24;
 	}
+#endif
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 					      snd_dma_pci_data(chip->mgr->pci), 32*1024, 32*1024);
 }
@@ -937,7 +942,7 @@ static int snd_mixart_pcm_analog(mixart_t *chip)
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_mixart_playback_ops);
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);
 
-	pcm->info_flags = SNDRV_PCM_INFO_NONATOMIC_OPS;
+	pcm->info_flags = 0;
 	strcpy(pcm->name, name);
 
 	preallocate_buffers(chip, pcm);
@@ -968,7 +973,7 @@ static int snd_mixart_pcm_digital(mixart_t *chip)
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_mixart_playback_ops);
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);
 
-	pcm->info_flags = SNDRV_PCM_INFO_NONATOMIC_OPS;
+	pcm->info_flags = 0;
 	strcpy(pcm->name, name);
 
 	preallocate_buffers(chip, pcm);
@@ -979,13 +984,13 @@ static int snd_mixart_pcm_digital(mixart_t *chip)
 
 static int snd_mixart_chip_free(mixart_t *chip)
 {
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_mixart_chip_dev_free(snd_device_t *device)
 {
-	mixart_t *chip = snd_magic_cast(mixart_t, device->device_data, return -ENXIO);
+	mixart_t *chip = device->device_data;
 	return snd_mixart_chip_free(chip);
 }
 
@@ -1000,7 +1005,7 @@ static int __devinit snd_mixart_create(mixart_mgr_t *mgr, snd_card_t *card, int
 		.dev_free = snd_mixart_chip_dev_free,
 	};
 
-	mgr->chip[idx] = chip = snd_magic_kcalloc(mixart_t, 0, GFP_KERNEL);
+	mgr->chip[idx] = chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (! chip) {
 		snd_printk(KERN_ERR "cannot allocate chip\n");
 		return -ENOMEM;
@@ -1074,24 +1079,21 @@ static int snd_mixart_free(mixart_mgr_t *mgr)
 	for (i = 0; i < 2; i++) {
 		if (mgr->mem[i].virt)
 			iounmap((void *)mgr->mem[i].virt);
-		if (mgr->mem[i].res) {
-			release_resource(mgr->mem[i].res);
-			kfree_nocheck(mgr->mem[i].res);
-		}
 	}
+	pci_release_regions(mgr->pci);
 
 	/* free flowarray */
 	if(mgr->flowinfo.area) {
-		snd_dma_free_pages(&mgr->dma_dev, &mgr->flowinfo);
+		snd_dma_free_pages(&mgr->flowinfo);
 		mgr->flowinfo.area = NULL;
 	}
 	/* free bufferarray */
 	if(mgr->bufferinfo.area) {
-		snd_dma_free_pages(&mgr->dma_dev, &mgr->bufferinfo);
+		snd_dma_free_pages(&mgr->bufferinfo);
 		mgr->bufferinfo.area = NULL;
 	}
 
-	snd_magic_kfree(mgr);
+	kfree(mgr);
 	return 0;
 }
 
@@ -1157,7 +1159,7 @@ static long snd_mixart_BA0_read(snd_info_entry_t *entry, void *file_private_data
 				struct file *file, char __user *buf,
 				unsigned long count, unsigned long pos)
 {
-	mixart_mgr_t *mgr = snd_magic_cast(mixart_mgr_t, entry->private_data, return -ENXIO);
+	mixart_mgr_t *mgr = entry->private_data;
 
 	count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
 	if(count <= 0)
@@ -1176,7 +1178,7 @@ static long snd_mixart_BA1_read(snd_info_entry_t *entry, void *file_private_data
 				struct file *file, char __user *buf,
 				unsigned long count, unsigned long pos)
 {
-	mixart_mgr_t *mgr = snd_magic_cast(mixart_mgr_t, entry->private_data, return -ENXIO);
+	mixart_mgr_t *mgr = entry->private_data;
 
 	count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
 	if(count <= 0)
@@ -1202,7 +1204,7 @@ static struct snd_info_entry_ops snd_mixart_proc_ops_BA1 = {
 static void snd_mixart_proc_read(snd_info_entry_t *entry, 
                                  snd_info_buffer_t * buffer)
 {
-	mixart_t *chip = snd_magic_cast(mixart_t, entry->private_data, return);        
+	mixart_t *chip = entry->private_data;        
 	u32 ref; 
 
 	snd_iprintf(buffer, "Digigram miXart (alsa card %d)\n\n", chip->chip_idx);
@@ -1289,15 +1291,14 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci,
 	pci_set_master(pci);
 
 	/* check if we can restrict PCI DMA transfers to 32 bits */
-	if (!pci_dma_supported(pci, 0xffffffff)) {
+	if (pci_set_dma_mask(pci, 0xffffffff) < 0) {
 		snd_printk(KERN_ERR "architecture does not support 32bit PCI busmaster DMA\n");
 		return -ENXIO;
 	}
-	pci_set_dma_mask(pci, 0xffffffff);
 
 	/*
 	 */
-	mgr = snd_magic_kcalloc(mixart_mgr_t, 0, GFP_KERNEL);
+	mgr = kcalloc(1, sizeof(*mgr), GFP_KERNEL);
 	if (! mgr)
 		return -ENOMEM;
 
@@ -1305,19 +1306,14 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci,
 	mgr->irq = -1;
 
 	/* resource assignment */
+	if ((err = pci_request_regions(pci, CARD_NAME)) < 0) {
+		kfree(mgr);
+		return err;
+	}
 	for (i = 0; i < 2; i++) {
-		static int memory_sizes[2] = {
-			MIXART_BA0_SIZE, /* 16M */	  
-			MIXART_BA1_SIZE  /* 4 k */
-		};
 		mgr->mem[i].phys = pci_resource_start(pci, i);
-		mgr->mem[i].res = request_mem_region(mgr->mem[i].phys, memory_sizes[i], CARD_NAME);
-		if (! mgr->mem[i].res) {
-			snd_printk(KERN_ERR "unable to grab memory 0x%lx\n", mgr->mem[i].phys);
-			snd_mixart_free(mgr);
-			return -EBUSY;
-		}
-		mgr->mem[i].virt = (unsigned long)ioremap_nocache(mgr->mem[i].phys, memory_sizes[i]);
+		mgr->mem[i].virt = (unsigned long)ioremap_nocache(mgr->mem[i].phys,
+								  pci_resource_len(pci, i));
 	}
 
 	if (request_irq(pci->irq, snd_mixart_interrupt, SA_INTERRUPT|SA_SHIRQ, CARD_NAME, (void *)mgr)) {
@@ -1331,13 +1327,13 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci,
 	sprintf(mgr->longname, "%s at 0x%lx & 0x%lx, irq %i", mgr->shortname, mgr->mem[0].phys, mgr->mem[1].phys, mgr->irq);
 
 	/* ISR spinlock  */
-	mgr->lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&mgr->lock);
 
 	/* init mailbox  */
 	mgr->msg_fifo_readptr = 0;
 	mgr->msg_fifo_writeptr = 0;
 
-	mgr->msg_lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&mgr->msg_lock);
 	init_MUTEX(&mgr->msg_mutex);
 	init_waitqueue_head(&mgr->msg_sleep);
 	atomic_set(&mgr->msg_processed, 0);
@@ -1391,13 +1387,10 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci,
 	/* init firmware status (mgr->hwdep->dsp_loaded reset in hwdep_new) */
 	mgr->board_type = MIXART_DAUGHTER_TYPE_NONE;
 
-	memset(&mgr->dma_dev, 0, sizeof(mgr->dma_dev));
-	mgr->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	mgr->dma_dev.dev = snd_dma_pci_data(mgr->pci);
-
 	/* create array of streaminfo */
 	size = PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS * sizeof(mixart_flowinfo_t)) );
-	if (snd_dma_alloc_pages(&mgr->dma_dev, size, &mgr->flowinfo) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				size, &mgr->flowinfo) < 0) {
 		snd_mixart_free(mgr);
 		return -ENOMEM;
 	}
@@ -1406,7 +1399,8 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci,
 
 	/* create array of bufferinfo */
 	size = PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS * sizeof(mixart_bufferinfo_t)) );
-	if (snd_dma_alloc_pages(&mgr->dma_dev, size, &mgr->bufferinfo) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				size, &mgr->bufferinfo) < 0) {
 		snd_mixart_free(mgr);
 		return -ENOMEM;
 	}
diff --git a/sound/pci/mixart/mixart.h b/sound/pci/mixart/mixart.h
index 573cdc015..2c2df37ab 100644
--- a/sound/pci/mixart/mixart.h
+++ b/sound/pci/mixart/mixart.h
@@ -115,7 +115,6 @@ struct snd_mixart_mgr {
 	snd_hwdep_t *hwdep;
 	unsigned int board_type;      /* read from embedded once elf file is loaded, 250 = miXart8, 251 = with AES, 252 = with Cobranet */
 
-	struct snd_dma_device dma_dev;
 	struct snd_dma_buffer flowinfo;
 	struct snd_dma_buffer bufferinfo;
 
diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c
index fab32117a..1f588eeb8 100644
--- a/sound/pci/mixart/mixart_core.c
+++ b/sound/pci/mixart/mixart_core.c
@@ -379,7 +379,7 @@ void snd_mixart_msg_tasklet( unsigned long arg)
 					snd_printk(KERN_ERR "tasklet : error MSG_STREAM_ST***_***PUT_STAGE_PACKET status=%x\n", mixart_msg_data[0]);
 				break;
 			default:
-				snd_printdd("tasklet received mf(%x) : msg_id(%x) uid(%x, %x) size(%d)\n",
+				snd_printdd("tasklet received mf(%x) : msg_id(%x) uid(%x, %x) size(%zd)\n",
 					   msg, resp.message_id, resp.uid.object_id, resp.uid.desc, resp.size);
 				break;
 			}
@@ -403,7 +403,7 @@ void snd_mixart_msg_tasklet( unsigned long arg)
 
 irqreturn_t snd_mixart_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	mixart_mgr_t *mgr = snd_magic_cast(mixart_mgr_t, dev_id, return IRQ_NONE);
+	mixart_mgr_t *mgr = dev_id;
 	int err;
 	mixart_msg_t resp;
 
diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c
index 0c0215d56..b6724c799 100644
--- a/sound/pci/mixart/mixart_hwdep.c
+++ b/sound/pci/mixart/mixart_hwdep.c
@@ -146,7 +146,7 @@ static int mixart_load_elf(mixart_mgr_t *mgr, snd_hwdep_dsp_image_t *dsp )
 
 static int mixart_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t *info)
 {
-	mixart_mgr_t *mgr = snd_magic_cast(mixart_mgr_t, hw->private_data, return -ENXIO);
+	mixart_mgr_t *mgr = hw->private_data;
 
 	strcpy(info->id, "miXart");
         info->num_dsps = MIXART_HARDW_FILES_MAX_INDEX;
@@ -346,7 +346,7 @@ static int mixart_first_init(mixart_mgr_t *mgr)
 
 static int mixart_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp)
 {
-	mixart_mgr_t* mgr = snd_magic_cast(mixart_mgr_t, hw->private_data, return -ENXIO);
+	mixart_mgr_t* mgr = hw->private_data;
 	int           err, card_index;
 	u32           status_xilinx, status_elf, status_daught;
 	u32           val;
diff --git a/sound/pci/mixart/mixart_mixer.c b/sound/pci/mixart/mixart_mixer.c
index 592b979e9..39c15416f 100644
--- a/sound/pci/mixart/mixart_mixer.c
+++ b/sound/pci/mixart/mixart_mixer.c
@@ -31,8 +31,6 @@
 #include <sound/control.h>
 #include "mixart_mixer.h"
 
-#define chip_t mixart_t
-
 static u32 mixart_analog_level[256] = {
 	0xc2c00000,		/* [000] -96.0 dB */
 	0xc2bf0000,		/* [001] -95.5 dB */
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 5637e0b79..e65e7de31 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -45,8 +45,7 @@
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("NeoMagic NM256AV/ZX");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{NeoMagic,NM256AV},"
+MODULE_SUPPORTED_DEVICE("{{NeoMagic,NM256AV},"
 		"{NeoMagic,NM256ZX}}");
 
 /*
@@ -66,31 +65,22 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable this soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(playback_bufsize, int, boot_devs, 0444);
 MODULE_PARM_DESC(playback_bufsize, "DAC frame size in kB for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(playback_bufsize, SNDRV_ENABLED);
 module_param_array(capture_bufsize, int, boot_devs, 0444);
 MODULE_PARM_DESC(capture_bufsize, "ADC frame size in kB for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(capture_bufsize, SNDRV_ENABLED);
 module_param_array(force_ac97, bool, boot_devs, 0444);
 MODULE_PARM_DESC(force_ac97, "Force to use AC97 codec for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(force_ac97, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 module_param_array(buffer_top, int, boot_devs, 0444);
 MODULE_PARM_DESC(buffer_top, "Set the top address of audio buffer for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(buffer_top, SNDRV_ENABLED);
 module_param_array(use_cache, bool, boot_devs, 0444);
 MODULE_PARM_DESC(use_cache, "Enable the cache for coefficient table access.");
-MODULE_PARM_SYNTAX(use_cache, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 module_param_array(vaio_hack, bool, boot_devs, 0444);
 MODULE_PARM_DESC(vaio_hack, "Enable workaround for Sony VAIO notebooks.");
-MODULE_PARM_SYNTAX(vaio_hack, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 
 /*
  * hw definitions
@@ -191,7 +181,6 @@ MODULE_PARM_SYNTAX(vaio_hack, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 
 typedef struct snd_nm256 nm256_t;
 typedef struct snd_nm256_stream nm256_stream_t;
-#define chip_t nm256_t
 
 struct snd_nm256_stream {
 
@@ -414,9 +403,8 @@ snd_nm256_load_coefficient(nm256_t *chip, int stream, int number)
 static unsigned int samplerates[8] = {
 	8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000,
 };
-#define NUM_SAMPLERATES (sizeof(samplerates) / sizeof(samplerates[0]))
 static snd_pcm_hw_constraint_list_t constraints_rates = {
-	.count = NUM_SAMPLERATES, 
+	.count = ARRAY_SIZE(samplerates), 
 	.list = samplerates,
 	.mask = 0,
 };
@@ -428,7 +416,7 @@ static int
 snd_nm256_fixed_rate(unsigned int rate)
 {
 	unsigned int i;
-	for (i = 0; i < NUM_SAMPLERATES; i++) {
+	for (i = 0; i < ARRAY_SIZE(samplerates); i++) {
 		if (rate == samplerates[i])
 			return i;
 	}
@@ -542,12 +530,11 @@ snd_nm256_playback_trigger(snd_pcm_substream_t *substream, int cmd)
 {
 	nm256_t *chip = snd_pcm_substream_chip(substream);
 	nm256_stream_t *s = (nm256_stream_t*)substream->runtime->private_data;
-	unsigned long flags;
 	int err = 0;
 
 	snd_assert(s != NULL, return -ENXIO);
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
@@ -567,7 +554,7 @@ snd_nm256_playback_trigger(snd_pcm_substream_t *substream, int cmd)
 		err = -EINVAL;
 		break;
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return err;
 }
 
@@ -576,12 +563,11 @@ snd_nm256_capture_trigger(snd_pcm_substream_t *substream, int cmd)
 {
 	nm256_t *chip = snd_pcm_substream_chip(substream);
 	nm256_stream_t *s = (nm256_stream_t*)substream->runtime->private_data;
-	unsigned long flags;
 	int err = 0;
 
 	snd_assert(s != NULL, return -ENXIO);
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
@@ -601,7 +587,7 @@ snd_nm256_capture_trigger(snd_pcm_substream_t *substream, int cmd)
 		err = -EINVAL;
 		break;
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 	return err;
 }
 
@@ -614,7 +600,6 @@ static int snd_nm256_pcm_prepare(snd_pcm_substream_t *substream)
 	nm256_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	nm256_stream_t *s = (nm256_stream_t*)runtime->private_data;
-	unsigned long flags;
 
 	snd_assert(s, return -ENXIO);
 	s->dma_size = frames_to_bytes(runtime, substream->runtime->buffer_size);
@@ -622,10 +607,10 @@ static int snd_nm256_pcm_prepare(snd_pcm_substream_t *substream)
 	s->periods = substream->runtime->periods;
 	s->cur_period = 0;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	s->running = 0;
 	snd_nm256_set_format(chip, s, substream);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 
 	return 0;
 }
@@ -660,9 +645,9 @@ snd_nm256_capture_pointer(snd_pcm_substream_t * substream)
 	return bytes_to_frames(substream->runtime, curp);
 }
 
+/* Remapped I/O space can be accessible as pointer on i386 */
+/* This might be changed in the future */
 #ifndef __i386__
-/* FIXME: I/O space is not accessible via pointers on all architectures */
-
 /*
  * silence / copy for playback
  */
@@ -757,10 +742,7 @@ snd_nm256_capture_update(nm256_t *chip)
  */
 static snd_pcm_hardware_t snd_nm256_playback =
 {
-	.info =
-#ifdef __i386__
-				SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID|
-#endif
+	.info =			SNDRV_PCM_INFO_MMAP_IOMEM |SNDRV_PCM_INFO_MMAP_VALID |
 				SNDRV_PCM_INFO_INTERLEAVED |
 				/*SNDRV_PCM_INFO_PAUSE |*/
 				SNDRV_PCM_INFO_RESUME,
@@ -779,10 +761,7 @@ static snd_pcm_hardware_t snd_nm256_playback =
 
 static snd_pcm_hardware_t snd_nm256_capture =
 {
-	.info =
-#ifdef __i386__
-				SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID|
-#endif
+	.info =			SNDRV_PCM_INFO_MMAP_IOMEM | SNDRV_PCM_INFO_MMAP_VALID |
 				SNDRV_PCM_INFO_INTERLEAVED |
 				/*SNDRV_PCM_INFO_PAUSE |*/
 				SNDRV_PCM_INFO_RESUME,
@@ -883,6 +862,7 @@ static snd_pcm_ops_t snd_nm256_playback_ops = {
 	.copy =		snd_nm256_playback_copy,
 	.silence =	snd_nm256_playback_silence,
 #endif
+	.mmap =		snd_pcm_lib_mmap_iomem,
 };
 
 static snd_pcm_ops_t snd_nm256_capture_ops = {
@@ -896,6 +876,7 @@ static snd_pcm_ops_t snd_nm256_capture_ops = {
 #ifndef __i386__
 	.copy =		snd_nm256_capture_copy,
 #endif
+	.mmap =		snd_pcm_lib_mmap_iomem,
 };
 
 static int __devinit
@@ -932,16 +913,14 @@ snd_nm256_pcm(nm256_t *chip, int device)
 static void
 snd_nm256_init_chip(nm256_t *chip)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	/* Reset everything. */
 	snd_nm256_writeb(chip, 0x0, 0x11);
 	snd_nm256_writew(chip, 0x214, 0);
 	/* stop sounds.. */
 	//snd_nm256_playback_stop(chip);
 	//snd_nm256_capture_stop(chip);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 }
 
 
@@ -981,7 +960,7 @@ snd_nm256_intr_check(nm256_t *chip)
 static irqreturn_t
 snd_nm256_interrupt(int irq, void *dev_id, struct pt_regs *dummy)
 {
-	nm256_t *chip = snd_magic_cast(nm256_t, dev_id, return IRQ_NONE);
+	nm256_t *chip = dev_id;
 	u16 status;
 	u8 cbyte;
 
@@ -1048,7 +1027,7 @@ snd_nm256_interrupt(int irq, void *dev_id, struct pt_regs *dummy)
 static irqreturn_t
 snd_nm256_interrupt_zx(int irq, void *dev_id, struct pt_regs *dummy)
 {
-	nm256_t *chip = snd_magic_cast(nm256_t, dev_id, return IRQ_NONE);
+	nm256_t *chip = dev_id;
 	u32 status;
 	u8 cbyte;
 
@@ -1139,7 +1118,7 @@ snd_nm256_ac97_ready(nm256_t *chip)
 static unsigned short
 snd_nm256_ac97_read(ac97_t *ac97, unsigned short reg)
 {
-	nm256_t *chip = snd_magic_cast(nm256_t, ac97->private_data, return -ENXIO);
+	nm256_t *chip = ac97->private_data;
 	int res;
 
 	if (reg >= 128)
@@ -1159,7 +1138,7 @@ static void
 snd_nm256_ac97_write(ac97_t *ac97,
 		     unsigned short reg, unsigned short val)
 {
-	nm256_t *chip = snd_magic_cast(nm256_t, ac97->private_data, return);
+	nm256_t *chip = ac97->private_data;
 	int tries = 2;
 	u32 base;
 
@@ -1181,10 +1160,9 @@ snd_nm256_ac97_write(ac97_t *ac97,
 static void
 snd_nm256_ac97_reset(ac97_t *ac97)
 {
-	nm256_t *chip = snd_magic_cast(nm256_t, ac97->private_data, return);
-	unsigned long flags;
+	nm256_t *chip = ac97->private_data;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock(&chip->reg_lock);
 	/* Reset the mixer.  'Tis magic!  */
 	snd_nm256_writeb(chip, 0x6c0, 1);
 	if (chip->latitude_workaround) {
@@ -1193,20 +1171,25 @@ snd_nm256_ac97_reset(ac97_t *ac97)
 	}
 	snd_nm256_writeb(chip, 0x6cc, 0x80);
 	snd_nm256_writeb(chip, 0x6cc, 0x0);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock(&chip->reg_lock);
 }
 
 /* create an ac97 mixer interface */
 static int __devinit
 snd_nm256_mixer(nm256_t *chip)
 {
-	ac97_bus_t bus, *pbus;
-	ac97_t ac97;
+	ac97_bus_t *pbus;
+	ac97_template_t ac97;
 	int i, err;
+	static ac97_bus_ops_t ops = {
+		.reset = snd_nm256_ac97_reset,
+		.write = snd_nm256_ac97_write,
+		.read = snd_nm256_ac97_read,
+	};
 	/* looks like nm256 hangs up when unexpected registers are touched... */
 	static int mixer_regs[] = {
 		AC97_MASTER, AC97_HEADPHONE, AC97_MASTER_MONO,
-		AC97_PC_BEEP, AC97_PHONE, AC97_MIC, AC97_LINE,
+		AC97_PC_BEEP, AC97_PHONE, AC97_MIC, AC97_LINE, AC97_CD,
 		AC97_VIDEO, AC97_AUX, AC97_PCM, AC97_REC_SEL,
 		AC97_REC_GAIN, AC97_GENERAL_PURPOSE, AC97_3D_CONTROL,
 		AC97_EXTENDED_ID,
@@ -1214,11 +1197,7 @@ snd_nm256_mixer(nm256_t *chip)
 		-1
 	};
 
-	memset(&bus, 0, sizeof(bus));
-	bus.reset = snd_nm256_ac97_reset;
-	bus.write = snd_nm256_ac97_write;
-	bus.read = snd_nm256_ac97_read;
-	if ((err = snd_ac97_bus(chip->card, &bus, &pbus)) < 0)
+	if ((err = snd_ac97_bus(chip->card, 0, &ops, NULL, &pbus)) < 0)
 		return err;
 
 	memset(&ac97, 0, sizeof(ac97));
@@ -1290,7 +1269,7 @@ snd_nm256_peek_for_sig(nm256_t *chip)
  */
 static int nm256_suspend(snd_card_t *card, unsigned int state)
 {
-	nm256_t *chip = snd_magic_cast(nm256_t, card->pm_private_data, return -EINVAL);
+	nm256_t *chip = card->pm_private_data;
 
 	snd_pcm_suspend_all(chip->pcm);
 	snd_ac97_suspend(chip->ac97);
@@ -1301,7 +1280,7 @@ static int nm256_suspend(snd_card_t *card, unsigned int state)
 
 static int nm256_resume(snd_card_t *card, unsigned int state)
 {
-	nm256_t *chip = snd_magic_cast(nm256_t, card->pm_private_data, return -EINVAL);
+	nm256_t *chip = card->pm_private_data;
 
 	/* Perform a full reset on the hardware */
 	pci_enable_device(chip->pci);
@@ -1340,13 +1319,13 @@ static int snd_nm256_free(nm256_t *chip)
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void*)chip);
 
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_nm256_dev_free(snd_device_t *device)
 {
-	nm256_t *chip = snd_magic_cast(nm256_t, device->device_data, return -ENXIO);
+	nm256_t *chip = device->device_data;
 	return snd_nm256_free(chip);
 }
 
@@ -1368,7 +1347,7 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci,
 
 	*chip_ret = NULL;
 
-	chip = snd_magic_kcalloc(nm256_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index 2f209664d..ddc8695cb 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -1,7 +1,8 @@
 /*
  *   ALSA driver for RME Digi32, Digi32/8 and Digi32 PRO audio interfaces
  *
- *	Copyright (c) 2002, 2003 Martin Langer <martin-langer@gmx.de>
+ *      Copyright (c) 2002-2004 Martin Langer <martin-langer@gmx.de>,
+ *                              Pilo Chambert <pilo.c@wanadoo.fr>
  *
  *      Thanks to :        Anders Torger <torger@ludd.luth.se>,
  *                         Henk Hesselink <henk@anda.nl>
@@ -52,6 +53,19 @@
  * patch would be welcome!
  * 
  * ****************************************************************************
+ *
+ * "The story after the long seeking" -- tiwai
+ *
+ * Ok, the situation regarding the full duplex is now improved a bit.
+ * In the fullduplex mode (given by the module parameter), the hardware buffer
+ * is split to halves for read and write directions at the DMA pointer.
+ * That is, the half above the current DMA pointer is used for write, and
+ * the half below is used for read.  To mangle this strange behavior, an
+ * software intermediate buffer is introduced.  This is, of course, not good
+ * from the viewpoint of the data transfer efficiency.  However, this allows
+ * you to use arbitrary buffer sizes, instead of the fixed I/O buffer size.
+ *
+ * ****************************************************************************
  */
 
 
@@ -68,6 +82,7 @@
 #include <sound/control.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
+#include <sound/pcm-indirect.h>
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 
@@ -76,22 +91,21 @@
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
+static int fullduplex[SNDRV_CARDS]; // = {[0 ... (SNDRV_CARDS - 1)] = 1};
 static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for RME Digi32 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for RME Digi32 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable RME Digi32 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
-MODULE_AUTHOR("Martin Langer <martin-langer@gmx.de>");
+module_param_array(fullduplex, bool, boot_devs, 0444);
+MODULE_PARM_DESC(fullduplex, "Support full-duplex mode.");
+MODULE_AUTHOR("Martin Langer <martin-langer@gmx.de>, Pilo Chambert <pilo.c@wanadoo.fr>");
 MODULE_DESCRIPTION("RME Digi32, Digi32/8, Digi32 PRO");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{RME,Digi32}," "{RME,Digi32/8}," "{RME,Digi32 PRO}}");
+MODULE_SUPPORTED_DEVICE("{{RME,Digi32}," "{RME,Digi32/8}," "{RME,Digi32 PRO}}");
 
 /* Defines for RME Digi32 series */
 #define RME32_SPDIF_NCHANNELS 2
@@ -140,7 +154,7 @@ MODULE_DEVICES("{{RME,Digi32}," "{RME,Digi32/8}," "{RME,Digi32 PRO}}");
 #define RME32_WCR_BITPOS_INP_1 7
 
 /* Read control register bits */
-#define RME32_RCR_AUDIO_ADDR_MASK 0x10001
+#define RME32_RCR_AUDIO_ADDR_MASK 0x1ffff
 #define RME32_RCR_LOCK      (1 << 23)   /* 1=locked, 0=not locked */
 #define RME32_RCR_ERF       (1 << 26)   /* 1=Error, 0=no Error */
 #define RME32_RCR_FREQ_0    (1 << 27)   /* CS841x frequency (record) */
@@ -168,6 +182,9 @@ MODULE_DEVICES("{{RME,Digi32}," "{RME,Digi32/8}," "{RME,Digi32 PRO}}");
 /* Block sizes in bytes */
 #define RME32_BLOCK_SIZE 8192
 
+/* Software intermediate buffer (max) size */
+#define RME32_MID_BUFFER_SIZE (1024*1024)
+
 /* Hardware revisions */
 #define RME32_32_REVISION 192
 #define RME32_328_REVISION_OLD 100
@@ -194,7 +211,6 @@ typedef struct snd_rme32 {
 	spinlock_t lock;
 	int irq;
 	unsigned long port;
-	struct resource *res_port;
 	unsigned long iobase;
 
 	u32 wcreg;		/* cached write control register value */
@@ -213,9 +229,11 @@ typedef struct snd_rme32 {
 	size_t playback_periodsize;	/* in bytes, zero if not used */
 	size_t capture_periodsize;	/* in bytes, zero if not used */
 
-	snd_pcm_uframes_t playback_last_appl_ptr;
-	size_t playback_ptr;
-	size_t capture_ptr;
+	unsigned int fullduplex_mode;
+	int running;
+
+	snd_pcm_indirect_t playback_pcm;
+	snd_pcm_indirect_t capture_pcm;
 
 	snd_card_t *card;
 	snd_pcm_t *spdif_pcm;
@@ -243,33 +261,16 @@ static int snd_rme32_playback_prepare(snd_pcm_substream_t * substream);
 
 static int snd_rme32_capture_prepare(snd_pcm_substream_t * substream);
 
-static int
-snd_rme32_playback_trigger(snd_pcm_substream_t * substream, int cmd);
-
-static int
-snd_rme32_capture_trigger(snd_pcm_substream_t * substream, int cmd);
-
-static snd_pcm_uframes_t
-snd_rme32_playback_pointer(snd_pcm_substream_t * substream);
-
-static snd_pcm_uframes_t
-snd_rme32_capture_pointer(snd_pcm_substream_t * substream);
+static int snd_rme32_pcm_trigger(snd_pcm_substream_t * substream, int cmd);
 
 static void snd_rme32_proc_init(rme32_t * rme32);
 
 static int snd_rme32_create_switches(snd_card_t * card, rme32_t * rme32);
 
-static inline unsigned int snd_rme32_playback_ptr(rme32_t * rme32)
-{
-
-	return (readl(rme32->iobase + RME32_IO_GET_POS)
-		& RME32_RCR_AUDIO_ADDR_MASK) >> rme32->playback_frlog;
-}
-
-static inline unsigned int snd_rme32_capture_ptr(rme32_t * rme32)
+static inline unsigned int snd_rme32_pcm_byteptr(rme32_t * rme32)
 {
 	return (readl(rme32->iobase + RME32_IO_GET_POS)
-		& RME32_RCR_AUDIO_ADDR_MASK) >> rme32->capture_frlog;
+		& RME32_RCR_AUDIO_ADDR_MASK);
 }
 
 static int snd_rme32_ratecode(int rate)
@@ -285,22 +286,24 @@ static int snd_rme32_ratecode(int rate)
 	return 0;
 }
 
+/* silence callback for halfduplex mode */
 static int snd_rme32_playback_silence(snd_pcm_substream_t * substream, int channel,	/* not used (interleaved data) */
 				      snd_pcm_uframes_t pos,
 				      snd_pcm_uframes_t count)
 {
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 	count <<= rme32->playback_frlog;
 	pos <<= rme32->playback_frlog;
 	memset_io(rme32->iobase + RME32_IO_DATA_BUFFER + pos, 0, count);
 	return 0;
 }
 
+/* copy callback for halfduplex mode */
 static int snd_rme32_playback_copy(snd_pcm_substream_t * substream, int channel,	/* not used (interleaved data) */
 				   snd_pcm_uframes_t pos,
 				   void __user *src, snd_pcm_uframes_t count)
 {
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 	count <<= rme32->playback_frlog;
 	pos <<= rme32->playback_frlog;
 	if (copy_from_user_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos,
@@ -309,11 +312,12 @@ static int snd_rme32_playback_copy(snd_pcm_substream_t * substream, int channel,
 	return 0;
 }
 
+/* copy callback for halfduplex mode */
 static int snd_rme32_capture_copy(snd_pcm_substream_t * substream, int channel,	/* not used (interleaved data) */
 				  snd_pcm_uframes_t pos,
 				  void __user *dst, snd_pcm_uframes_t count)
 {
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 	count <<= rme32->capture_frlog;
 	pos <<= rme32->capture_frlog;
 	if (copy_to_user_fromio(dst,
@@ -324,13 +328,14 @@ static int snd_rme32_capture_copy(snd_pcm_substream_t * substream, int channel,
 }
 
 /*
- * Digital output capabilites (S/PDIF)
+ * SPDIF I/O capabilites (half-duplex mode)
  */
-static snd_pcm_hardware_t snd_rme32_playback_spdif_info = {
-	.info =		(SNDRV_PCM_INFO_MMAP |
+static snd_pcm_hardware_t snd_rme32_spdif_info = {
+	.info =		(SNDRV_PCM_INFO_MMAP_IOMEM |
 			 SNDRV_PCM_INFO_MMAP_VALID |
 			 SNDRV_PCM_INFO_INTERLEAVED | 
-			 SNDRV_PCM_INFO_PAUSE),
+			 SNDRV_PCM_INFO_PAUSE |
+			 SNDRV_PCM_INFO_SYNC_START),
 	.formats =	(SNDRV_PCM_FMTBIT_S16_LE | 
 			 SNDRV_PCM_FMTBIT_S32_LE),
 	.rates =	(SNDRV_PCM_RATE_32000 |
@@ -349,13 +354,39 @@ static snd_pcm_hardware_t snd_rme32_playback_spdif_info = {
 };
 
 /*
- * Digital input capabilites (S/PDIF)
+ * ADAT I/O capabilites (half-duplex mode)
+ */
+static snd_pcm_hardware_t snd_rme32_adat_info =
+{
+	.info =		     (SNDRV_PCM_INFO_MMAP_IOMEM |
+			      SNDRV_PCM_INFO_MMAP_VALID |
+			      SNDRV_PCM_INFO_INTERLEAVED |
+			      SNDRV_PCM_INFO_PAUSE |
+			      SNDRV_PCM_INFO_SYNC_START),
+	.formats=            SNDRV_PCM_FMTBIT_S16_LE,
+	.rates =             (SNDRV_PCM_RATE_44100 | 
+			      SNDRV_PCM_RATE_48000),
+	.rate_min =          44100,
+	.rate_max =          48000,
+	.channels_min =      8,
+	.channels_max =	     8,
+	.buffer_bytes_max =  RME32_BUFFER_SIZE,
+	.period_bytes_min =  RME32_BLOCK_SIZE,
+	.period_bytes_max =  RME32_BLOCK_SIZE,
+	.periods_min =	    RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
+	.periods_max =	    RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
+	.fifo_size =	    0,
+};
+
+/*
+ * SPDIF I/O capabilites (full-duplex mode)
  */
-static snd_pcm_hardware_t snd_rme32_capture_spdif_info = {
+static snd_pcm_hardware_t snd_rme32_spdif_fd_info = {
 	.info =		(SNDRV_PCM_INFO_MMAP |
 			 SNDRV_PCM_INFO_MMAP_VALID |
 			 SNDRV_PCM_INFO_INTERLEAVED | 
-			 SNDRV_PCM_INFO_PAUSE),
+			 SNDRV_PCM_INFO_PAUSE |
+			 SNDRV_PCM_INFO_SYNC_START),
 	.formats =	(SNDRV_PCM_FMTBIT_S16_LE | 
 			 SNDRV_PCM_FMTBIT_S32_LE),
 	.rates =	(SNDRV_PCM_RATE_32000 |
@@ -365,23 +396,24 @@ static snd_pcm_hardware_t snd_rme32_capture_spdif_info = {
 	.rate_max =	48000,
 	.channels_min =	2,
 	.channels_max =	2,
-	.buffer_bytes_max = RME32_BUFFER_SIZE,
+	.buffer_bytes_max = RME32_MID_BUFFER_SIZE,
 	.period_bytes_min = RME32_BLOCK_SIZE,
 	.period_bytes_max = RME32_BLOCK_SIZE,
-	.periods_min =	RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
-	.periods_max =	RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
+	.periods_min =	2,
+	.periods_max =	RME32_MID_BUFFER_SIZE / RME32_BLOCK_SIZE,
 	.fifo_size =	0,
 };
 
 /*
- * Digital output capabilites (ADAT)
+ * ADAT I/O capabilites (full-duplex mode)
  */
-static snd_pcm_hardware_t snd_rme32_playback_adat_info =
+static snd_pcm_hardware_t snd_rme32_adat_fd_info =
 {
 	.info =		     (SNDRV_PCM_INFO_MMAP |
 			      SNDRV_PCM_INFO_MMAP_VALID |
 			      SNDRV_PCM_INFO_INTERLEAVED |
-			      SNDRV_PCM_INFO_PAUSE),
+			      SNDRV_PCM_INFO_PAUSE |
+			      SNDRV_PCM_INFO_SYNC_START),
 	.formats=            SNDRV_PCM_FMTBIT_S16_LE,
 	.rates =             (SNDRV_PCM_RATE_44100 | 
 			      SNDRV_PCM_RATE_48000),
@@ -389,38 +421,14 @@ static snd_pcm_hardware_t snd_rme32_playback_adat_info =
 	.rate_max =          48000,
 	.channels_min =      8,
 	.channels_max =	     8,
-	.buffer_bytes_max =  RME32_BUFFER_SIZE,
+	.buffer_bytes_max =  RME32_MID_BUFFER_SIZE,
 	.period_bytes_min =  RME32_BLOCK_SIZE,
 	.period_bytes_max =  RME32_BLOCK_SIZE,
-	.periods_min =	    RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
-	.periods_max =	    RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
+	.periods_min =	    2,
+	.periods_max =	    RME32_MID_BUFFER_SIZE / RME32_BLOCK_SIZE,
 	.fifo_size =	    0,
 };
 
-/*
- * Digital input capabilites (ADAT)
- */
-static snd_pcm_hardware_t snd_rme32_capture_adat_info =
-{
-	.info =		     (SNDRV_PCM_INFO_MMAP |
-			      SNDRV_PCM_INFO_MMAP_VALID |
-			      SNDRV_PCM_INFO_INTERLEAVED |
-			      SNDRV_PCM_INFO_PAUSE),
-	.formats =           SNDRV_PCM_FMTBIT_S16_LE,
-	.rates =             (SNDRV_PCM_RATE_44100 | 
-			      SNDRV_PCM_RATE_48000),
-	.rate_min =          44100,
-	.rate_max =          48000,
-	.channels_min =	     8,
-	.channels_max =	     8,
-	.buffer_bytes_max =  RME32_BUFFER_SIZE,
-	.period_bytes_min =  RME32_BLOCK_SIZE,
-	.period_bytes_max =  RME32_BLOCK_SIZE,
-	.periods_min =	     RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
-	.periods_max =	     RME32_BUFFER_SIZE / RME32_BLOCK_SIZE,
-	.fifo_size =         0,
-};
-
 static void snd_rme32_reset_dac(rme32_t *rme32)
 {
         writel(rme32->wcreg | RME32_WCR_PD,
@@ -677,11 +685,19 @@ snd_rme32_playback_hw_params(snd_pcm_substream_t * substream,
 			     snd_pcm_hw_params_t * params)
 {
 	int err, rate, dummy;
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+
+	if (rme32->fullduplex_mode) {
+		err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+		if (err < 0)
+			return err;
+	} else {
+		runtime->dma_area = (void *)(rme32->iobase + RME32_IO_DATA_BUFFER);
+		runtime->dma_addr = rme32->port + RME32_IO_DATA_BUFFER;
+		runtime->dma_bytes = RME32_BUFFER_SIZE;
+	}
 
-	if ((err = snd_pcm_lib_malloc_pages(substream,
-				      params_buffer_bytes(params))) < 0)
-		return err;
 	spin_lock_irq(&rme32->lock);
 	if ((rme32->rcreg & RME32_RCR_KMODE) &&
 	    (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) {
@@ -719,45 +735,45 @@ snd_rme32_playback_hw_params(snd_pcm_substream_t * substream,
 	return 0;
 }
 
-static int snd_rme32_playback_hw_free(snd_pcm_substream_t * substream)
-{
-	snd_pcm_lib_free_pages(substream);
-	return 0;
-}
-
 static int
 snd_rme32_capture_hw_params(snd_pcm_substream_t * substream,
 			    snd_pcm_hw_params_t * params)
 {
-	unsigned long flags;
 	int err, isadat, rate;
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
-	if ((err = snd_pcm_lib_malloc_pages(substream,
-				      params_buffer_bytes(params))) < 0)
-		return err;
-	spin_lock_irqsave(&rme32->lock, flags);
+	if (rme32->fullduplex_mode) {
+		err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+		if (err < 0)
+			return err;
+	} else {
+		runtime->dma_area = (void *)rme32->iobase + RME32_IO_DATA_BUFFER;
+		runtime->dma_addr = rme32->port + RME32_IO_DATA_BUFFER;
+		runtime->dma_bytes = RME32_BUFFER_SIZE;
+	}
+
+	spin_lock_irq(&rme32->lock);
 	/* enable AutoSync for record-preparing */
 	rme32->wcreg |= RME32_WCR_AUTOSYNC;
 	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
 
 	if ((err = snd_rme32_setformat(rme32, params_format(params))) < 0) {
-		spin_unlock_irqrestore(&rme32->lock, flags);
+		spin_unlock_irq(&rme32->lock);
 		return err;
 	}
 	if ((err = snd_rme32_playback_setrate(rme32, params_rate(params))) < 0) {
-		spin_unlock_irqrestore(&rme32->lock, flags);
+		spin_unlock_irq(&rme32->lock);
 		return err;
 	}
 	if ((rate = snd_rme32_capture_getrate(rme32, &isadat)) > 0) {
                 if ((int)params_rate(params) != rate) {
-                        spin_unlock_irqrestore(&rme32->lock, flags);
+			spin_unlock_irq(&rme32->lock);
                         return -EIO;                    
                 }
                 if ((isadat && runtime->hw.channels_min == 2) ||
                     (!isadat && runtime->hw.channels_min == 8)) {
-                        spin_unlock_irqrestore(&rme32->lock, flags);
+			spin_unlock_irq(&rme32->lock);
                         return -EIO;
                 }
 	}
@@ -769,36 +785,26 @@ snd_rme32_capture_hw_params(snd_pcm_substream_t * substream,
 	if (rme32->playback_periodsize != 0) {
 		if (params_period_size(params) << rme32->capture_frlog !=
 		    rme32->playback_periodsize) {
-			spin_unlock_irqrestore(&rme32->lock, flags);
+			spin_unlock_irq(&rme32->lock);
 			return -EBUSY;
 		}
 	}
 	rme32->capture_periodsize =
 	    params_period_size(params) << rme32->capture_frlog;
-	spin_unlock_irqrestore(&rme32->lock, flags);
-
-	return 0;
-}
+	spin_unlock_irq(&rme32->lock);
 
-static int snd_rme32_capture_hw_free(snd_pcm_substream_t * substream)
-{
-	snd_pcm_lib_free_pages(substream);
 	return 0;
 }
 
-static void snd_rme32_playback_start(rme32_t * rme32, int from_pause)
+static int snd_rme32_pcm_hw_free(snd_pcm_substream_t * substream)
 {
-	if (!from_pause) {
-		writel(0, rme32->iobase + RME32_IO_RESET_POS);
-		rme32->playback_last_appl_ptr = 0;
-		rme32->playback_ptr = 0;
-	}
-
-	rme32->wcreg |= RME32_WCR_START;
-	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
+	if (! rme32->fullduplex_mode)
+		return 0;
+	return snd_pcm_lib_free_pages(substream);
 }
 
-static void snd_rme32_capture_start(rme32_t * rme32, int from_pause)
+static void snd_rme32_pcm_start(rme32_t * rme32, int from_pause)
 {
 	if (!from_pause) {
 		writel(0, rme32->iobase + RME32_IO_RESET_POS);
@@ -808,7 +814,7 @@ static void snd_rme32_capture_start(rme32_t * rme32, int from_pause)
 	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
 }
 
-static void snd_rme32_playback_stop(rme32_t * rme32)
+static void snd_rme32_pcm_stop(rme32_t * rme32, int to_pause)
 {
 	/*
 	 * Check if there is an unconfirmed IRQ, if so confirm it, or else
@@ -822,16 +828,8 @@ static void snd_rme32_playback_stop(rme32_t * rme32)
 	if (rme32->wcreg & RME32_WCR_SEL)
 		rme32->wcreg |= RME32_WCR_MUTE;
 	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
-}
-
-static void snd_rme32_capture_stop(rme32_t * rme32)
-{
-	rme32->rcreg = readl(rme32->iobase + RME32_IO_CONTROL_REGISTER);
-	if (rme32->rcreg & RME32_RCR_IRQ) {
-		writel(0, rme32->iobase + RME32_IO_CONFIRM_ACTION_IRQ);
-	}
-	rme32->wcreg &= ~RME32_WCR_START;
-	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
+	if (! to_pause)
+		writel(0, rme32->iobase + RME32_IO_RESET_POS);
 }
 
 static irqreturn_t
@@ -857,36 +855,46 @@ snd_rme32_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 static unsigned int period_bytes[] = { RME32_BLOCK_SIZE };
 
 
-#define PERIOD_BYTES sizeof(period_bytes) / sizeof(period_bytes[0])
-
 static snd_pcm_hw_constraint_list_t hw_constraints_period_bytes = {
-	.count = PERIOD_BYTES,
+	.count = ARRAY_SIZE(period_bytes),
 	.list = period_bytes,
 	.mask = 0
 };
 
+static void snd_rme32_set_buffer_constraint(rme32_t *rme32, snd_pcm_runtime_t *runtime)
+{
+	if (! rme32->fullduplex_mode) {
+		snd_pcm_hw_constraint_minmax(runtime,
+					     SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+					     RME32_BUFFER_SIZE, RME32_BUFFER_SIZE);
+		snd_pcm_hw_constraint_list(runtime, 0,
+					   SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+					   &hw_constraints_period_bytes);
+	}
+}
+
 static int snd_rme32_playback_spdif_open(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
 	int rate, dummy;
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
 	snd_pcm_set_sync(substream);
 
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
 	if (rme32->playback_substream != NULL) {
-		spin_unlock_irqrestore(&rme32->lock, flags);
+		spin_unlock_irq(&rme32->lock);
 		return -EBUSY;
 	}
 	rme32->wcreg &= ~RME32_WCR_ADAT;
 	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
 	rme32->playback_substream = substream;
-	rme32->playback_last_appl_ptr = 0;
-	rme32->playback_ptr = 0;
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 
-	runtime->hw = snd_rme32_playback_spdif_info;
+	if (rme32->fullduplex_mode)
+		runtime->hw = snd_rme32_spdif_fd_info;
+	else
+		runtime->hw = snd_rme32_spdif_info;
 	if (rme32->pci->device == PCI_DEVICE_ID_DIGI32_PRO) {
 		runtime->hw.rates |= SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000;
 		runtime->hw.rate_max = 96000;
@@ -898,12 +906,8 @@ static int snd_rme32_playback_spdif_open(snd_pcm_substream_t * substream)
 		runtime->hw.rate_min = rate;
 		runtime->hw.rate_max = rate;
 	}       
-	snd_pcm_hw_constraint_minmax(runtime,
-				     SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
-				     RME32_BUFFER_SIZE, RME32_BUFFER_SIZE);
-	snd_pcm_hw_constraint_list(runtime, 0,
-				   SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
-				   &hw_constraints_period_bytes);
+
+	snd_rme32_set_buffer_constraint(rme32, runtime);
 
 	rme32->wcreg_spdif_stream = rme32->wcreg_spdif;
 	rme32->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
@@ -914,23 +918,24 @@ static int snd_rme32_playback_spdif_open(snd_pcm_substream_t * substream)
 
 static int snd_rme32_capture_spdif_open(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
 	int isadat, rate;
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
 	snd_pcm_set_sync(substream);
 
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
         if (rme32->capture_substream != NULL) {
-	        spin_unlock_irqrestore(&rme32->lock, flags);
+		spin_unlock_irq(&rme32->lock);
                 return -EBUSY;
         }
 	rme32->capture_substream = substream;
-	rme32->capture_ptr = 0;
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 
-	runtime->hw = snd_rme32_capture_spdif_info;
+	if (rme32->fullduplex_mode)
+		runtime->hw = snd_rme32_spdif_fd_info;
+	else
+		runtime->hw = snd_rme32_spdif_info;
 	if (RME32_PRO_WITH_8414(rme32)) {
 		runtime->hw.rates |= SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000;
 		runtime->hw.rate_max = 96000;
@@ -944,12 +949,7 @@ static int snd_rme32_capture_spdif_open(snd_pcm_substream_t * substream)
 		runtime->hw.rate_max = rate;
 	}
 
-	snd_pcm_hw_constraint_minmax(runtime,
-				     SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
-				     RME32_BUFFER_SIZE, RME32_BUFFER_SIZE);
-	snd_pcm_hw_constraint_list(runtime, 0,
-				   SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
-				   &hw_constraints_period_bytes);
+	snd_rme32_set_buffer_constraint(rme32, runtime);
 
 	return 0;
 }
@@ -957,26 +957,26 @@ static int snd_rme32_capture_spdif_open(snd_pcm_substream_t * substream)
 static int
 snd_rme32_playback_adat_open(snd_pcm_substream_t *substream)
 {
-	unsigned long flags;
 	int rate, dummy;
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	
 	snd_pcm_set_sync(substream);
 
-	spin_lock_irqsave(&rme32->lock, flags);	
+	spin_lock_irq(&rme32->lock);	
         if (rme32->playback_substream != NULL) {
-	        spin_unlock_irqrestore(&rme32->lock, flags);
+		spin_unlock_irq(&rme32->lock);
                 return -EBUSY;
         }
 	rme32->wcreg |= RME32_WCR_ADAT;
 	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
 	rme32->playback_substream = substream;
-	rme32->playback_last_appl_ptr = 0;
-	rme32->playback_ptr = 0;
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	
-	runtime->hw = snd_rme32_playback_adat_info;
+	if (rme32->fullduplex_mode)
+		runtime->hw = snd_rme32_adat_fd_info;
+	else
+		runtime->hw = snd_rme32_adat_info;
 	if ((rme32->rcreg & RME32_RCR_KMODE) &&
 	    (rate = snd_rme32_capture_getrate(rme32, &dummy)) > 0) {
                 /* AutoSync */
@@ -984,22 +984,22 @@ snd_rme32_playback_adat_open(snd_pcm_substream_t *substream)
                 runtime->hw.rate_min = rate;
                 runtime->hw.rate_max = rate;
 	}        
-	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
-				     RME32_BUFFER_SIZE, RME32_BUFFER_SIZE);
-	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
-				   &hw_constraints_period_bytes);
+
+	snd_rme32_set_buffer_constraint(rme32, runtime);
 	return 0;
 }
 
 static int
 snd_rme32_capture_adat_open(snd_pcm_substream_t *substream)
 {
-	unsigned long flags;
 	int isadat, rate;
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
-	runtime->hw = snd_rme32_capture_adat_info;
+	if (rme32->fullduplex_mode)
+		runtime->hw = snd_rme32_adat_fd_info;
+	else
+		runtime->hw = snd_rme32_adat_info;
 	if ((rate = snd_rme32_capture_getrate(rme32, &isadat)) > 0) {
 		if (!isadat) {
 			return -EIO;
@@ -1011,33 +1011,28 @@ snd_rme32_capture_adat_open(snd_pcm_substream_t *substream)
 
 	snd_pcm_set_sync(substream);
         
-	spin_lock_irqsave(&rme32->lock, flags);	
+	spin_lock_irq(&rme32->lock);	
 	if (rme32->capture_substream != NULL) {
-		spin_unlock_irqrestore(&rme32->lock, flags);
+		spin_unlock_irq(&rme32->lock);
 		return -EBUSY;
         }
 	rme32->capture_substream = substream;
-	rme32->capture_ptr = 0;
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 
-	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
-				     RME32_BUFFER_SIZE, RME32_BUFFER_SIZE);
-	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
-				   &hw_constraints_period_bytes);
+	snd_rme32_set_buffer_constraint(rme32, runtime);
 	return 0;
 }
 
 static int snd_rme32_playback_close(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 	int spdif = 0;
 
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
 	rme32->playback_substream = NULL;
 	rme32->playback_periodsize = 0;
 	spdif = (rme32->wcreg & RME32_WCR_ADAT) == 0;
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	if (spdif) {
 		rme32->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 		snd_ctl_notify(rme32->card, SNDRV_CTL_EVENT_MASK_VALUE |
@@ -1049,210 +1044,207 @@ static int snd_rme32_playback_close(snd_pcm_substream_t * substream)
 
 static int snd_rme32_capture_close(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
 	rme32->capture_substream = NULL;
 	rme32->capture_periodsize = 0;
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock(&rme32->lock);
 	return 0;
 }
 
 static int snd_rme32_playback_prepare(snd_pcm_substream_t * substream)
 {
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 
-	spin_lock_irqsave(&rme32->lock, flags);
-	if (RME32_ISWORKING(rme32)) {
-		snd_rme32_playback_stop(rme32);
+	spin_lock_irq(&rme32->lock);
+	if (rme32->fullduplex_mode) {
+		memset(&rme32->playback_pcm, 0, sizeof(rme32->playback_pcm));
+		rme32->playback_pcm.hw_buffer_size = RME32_BUFFER_SIZE;
+		rme32->playback_pcm.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+	} else {
+		writel(0, rme32->iobase + RME32_IO_RESET_POS);
 	}
-	writel(0, rme32->iobase + RME32_IO_RESET_POS);
 	if (rme32->wcreg & RME32_WCR_SEL)
 		rme32->wcreg &= ~RME32_WCR_MUTE;
 	writel(rme32->wcreg, rme32->iobase + RME32_IO_CONTROL_REGISTER);
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	return 0;
 }
 
 static int snd_rme32_capture_prepare(snd_pcm_substream_t * substream)
 {
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
 
-	spin_lock_irqsave(&rme32->lock, flags);
-	if (RME32_ISWORKING(rme32)) {
-		snd_rme32_capture_stop(rme32);
+	spin_lock_irq(&rme32->lock);
+	if (rme32->fullduplex_mode) {
+		memset(&rme32->capture_pcm, 0, sizeof(rme32->capture_pcm));
+		rme32->capture_pcm.hw_buffer_size = RME32_BUFFER_SIZE;
+		rme32->capture_pcm.hw_queue_size = RME32_BUFFER_SIZE / 2;
+		rme32->capture_pcm.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+	} else {
+		writel(0, rme32->iobase + RME32_IO_RESET_POS);
 	}
-	writel(0, rme32->iobase + RME32_IO_RESET_POS);
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	return 0;
 }
 
 static int
-snd_rme32_playback_trigger(snd_pcm_substream_t * substream, int cmd)
-{
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		if (!RME32_ISWORKING(rme32)) {
-			if (substream != rme32->playback_substream) {
-				return -EBUSY;
+snd_rme32_pcm_trigger(snd_pcm_substream_t * substream, int cmd)
+{
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
+	struct list_head *pos;
+	snd_pcm_substream_t *s;
+
+	spin_lock(&rme32->lock);
+	snd_pcm_group_for_each(pos, substream) {
+		s = snd_pcm_group_substream_entry(pos);
+		if (s != rme32->playback_substream &&
+		    s != rme32->capture_substream)
+			continue;
+		switch (cmd) {
+		case SNDRV_PCM_TRIGGER_START:
+			rme32->running |= (1 << s->stream);
+			if (rme32->fullduplex_mode) {
+				/* remember the current DMA position */
+				if (s == rme32->playback_substream) {
+					rme32->playback_pcm.hw_io =
+					rme32->playback_pcm.hw_data = snd_rme32_pcm_byteptr(rme32);
+				} else {
+					rme32->capture_pcm.hw_io =
+					rme32->capture_pcm.hw_data = snd_rme32_pcm_byteptr(rme32);
+				}
 			}
-			snd_rme32_playback_start(rme32, 0);
+			break;
+		case SNDRV_PCM_TRIGGER_STOP:
+			rme32->running &= ~(1 << s->stream);
+			break;
 		}
-		break;
-
-	case SNDRV_PCM_TRIGGER_STOP:
-		if (RME32_ISWORKING(rme32)) {
-			if (substream != rme32->playback_substream) {
-				return -EBUSY;
+		snd_pcm_trigger_done(s, substream);
+	}
+	
+	/* prefill playback buffer */
+	if (cmd == SNDRV_PCM_TRIGGER_START) {
+		snd_pcm_group_for_each(pos, substream) {
+			s = snd_pcm_group_substream_entry(pos);
+			if (s == rme32->playback_substream) {
+				s->ops->ack(s);
+				break;
 			}
-			snd_rme32_playback_stop(rme32);
 		}
-		break;
+	}
 
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		if (rme32->running && ! RME32_ISWORKING(rme32))
+			snd_rme32_pcm_start(rme32, 0);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		if (! rme32->running && RME32_ISWORKING(rme32))
+			snd_rme32_pcm_stop(rme32, 0);
+		break;
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		if (RME32_ISWORKING(rme32)) {
-			snd_rme32_playback_stop(rme32);
-		}
+		if (rme32->running && RME32_ISWORKING(rme32))
+			snd_rme32_pcm_stop(rme32, 1);
 		break;
-
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		if (!RME32_ISWORKING(rme32)) {
-			snd_rme32_playback_start(rme32, 1);
-		}
+		if (rme32->running && ! RME32_ISWORKING(rme32))
+			snd_rme32_pcm_start(rme32, 1);
 		break;
-
-	default:
-		return -EINVAL;
 	}
+	spin_unlock(&rme32->lock);
 	return 0;
 }
 
-static int
-snd_rme32_capture_trigger(snd_pcm_substream_t * substream, int cmd)
+/* pointer callback for halfduplex mode */
+static snd_pcm_uframes_t
+snd_rme32_playback_pointer(snd_pcm_substream_t * substream)
 {
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		if (!RME32_ISWORKING(rme32)) {
-			if (substream != rme32->capture_substream) {
-				return -EBUSY;
-			}
-			snd_rme32_capture_start(rme32, 0);
-		}
-		break;
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
+	return snd_rme32_pcm_byteptr(rme32) >> rme32->playback_frlog;
+}
 
-	case SNDRV_PCM_TRIGGER_STOP:
-		if (RME32_ISWORKING(rme32)) {
-			if (substream != rme32->capture_substream) {
-				return -EBUSY;
-			}
-			snd_rme32_capture_stop(rme32);
-		}
-		break;
+static snd_pcm_uframes_t
+snd_rme32_capture_pointer(snd_pcm_substream_t * substream)
+{
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
+	return snd_rme32_pcm_byteptr(rme32) >> rme32->capture_frlog;
+}
 
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		if (RME32_ISWORKING(rme32)) {
-			snd_rme32_capture_stop(rme32);
-		}
-		break;
 
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		if (!RME32_ISWORKING(rme32)) {
-			snd_rme32_capture_start(rme32, 1);
-		}
-		break;
+/* ack and pointer callbacks for fullduplex mode */
+static void snd_rme32_pb_trans_copy(snd_pcm_substream_t *substream,
+				    snd_pcm_indirect_t *rec, size_t bytes)
+{
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
+	memcpy_toio(rme32->iobase + RME32_IO_DATA_BUFFER + rec->hw_data,
+		    substream->runtime->dma_area + rec->sw_data, bytes);
+}
 
-	default:
-		return -EINVAL;
-	}
+static int snd_rme32_playback_fd_ack(snd_pcm_substream_t *substream)
+{
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
+	snd_pcm_indirect_t *rec, *cprec;
+	unsigned long flags;
 
+	rec = &rme32->playback_pcm;
+	cprec = &rme32->capture_pcm;
+	spin_lock_irqsave(&rme32->lock, flags);
+	rec->hw_queue_size = RME32_BUFFER_SIZE;
+	if (rme32->running & (1 << SNDRV_PCM_STREAM_CAPTURE))
+		rec->hw_queue_size -= cprec->hw_ready;
+	spin_unlock_irqrestore(&rme32->lock, flags);
+	snd_pcm_indirect_playback_transfer(substream, rec,
+					   snd_rme32_pb_trans_copy);
 	return 0;
 }
 
-static snd_pcm_uframes_t
-snd_rme32_playback_pointer(snd_pcm_substream_t * substream)
+static void snd_rme32_cp_trans_copy(snd_pcm_substream_t *substream,
+				    snd_pcm_indirect_t *rec, size_t bytes)
 {
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_pcm_sframes_t diff;
-	size_t bytes;
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
+	memcpy_fromio(substream->runtime->dma_area + rec->sw_data,
+		      rme32->iobase + RME32_IO_DATA_BUFFER + rec->hw_data,
+		      bytes);
+}
 
+static int snd_rme32_capture_fd_ack(snd_pcm_substream_t *substream)
+{
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
+	snd_pcm_indirect_capture_transfer(substream, &rme32->capture_pcm,
+					  snd_rme32_cp_trans_copy);
+	return 0;
+}
 
-	if (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
-		diff = runtime->control->appl_ptr -
-		       rme32->playback_last_appl_ptr;
-		rme32->playback_last_appl_ptr = runtime->control->appl_ptr;
-		if (diff != 0 && diff < -(snd_pcm_sframes_t) (runtime->boundary >> 1)) {
-			diff += runtime->boundary;
-		}
-		bytes = diff << rme32->playback_frlog;
-		if (bytes > RME32_BUFFER_SIZE - rme32->playback_ptr) {
-			memcpy_toio((void *)(rme32->iobase + RME32_IO_DATA_BUFFER + rme32->playback_ptr),
-				    runtime->dma_area + rme32->playback_ptr,
-				    RME32_BUFFER_SIZE - rme32->playback_ptr);
-			bytes -= RME32_BUFFER_SIZE - rme32->playback_ptr;
-			if (bytes > RME32_BUFFER_SIZE) {
-				bytes = RME32_BUFFER_SIZE;
-			}
-			memcpy_toio((void *)(rme32->iobase + RME32_IO_DATA_BUFFER),
-				    runtime->dma_area, bytes);
-			rme32->playback_ptr = bytes;
-		} else if (bytes != 0) {
-			memcpy_toio((void *)(rme32->iobase + RME32_IO_DATA_BUFFER + rme32->playback_ptr),
-				    runtime->dma_area + rme32->playback_ptr, bytes);
-			rme32->playback_ptr += bytes;
-		}
-	}
-	return snd_rme32_playback_ptr(rme32);
+static snd_pcm_uframes_t
+snd_rme32_playback_fd_pointer(snd_pcm_substream_t * substream)
+{
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
+	return snd_pcm_indirect_playback_pointer(substream, &rme32->playback_pcm,
+						 snd_rme32_pcm_byteptr(rme32));
 }
 
 static snd_pcm_uframes_t
-snd_rme32_capture_pointer(snd_pcm_substream_t * substream)
+snd_rme32_capture_fd_pointer(snd_pcm_substream_t * substream)
 {
-	rme32_t *rme32 = _snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_pcm_uframes_t frameptr;
-	size_t ptr;
-
-	frameptr = snd_rme32_capture_ptr(rme32);
-	if (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
-		ptr = frameptr << rme32->capture_frlog;
-		if (ptr > rme32->capture_ptr) {
-			memcpy_fromio(runtime->dma_area + rme32->capture_ptr,
-				      (void *)(rme32->iobase + RME32_IO_DATA_BUFFER +
-					       rme32->capture_ptr),
-				      ptr - rme32->capture_ptr);
-			rme32->capture_ptr += ptr - rme32->capture_ptr;
-		} else if (ptr < rme32->capture_ptr) {
-			memcpy_fromio(runtime->dma_area + rme32->capture_ptr,
-				      (void *)(rme32->iobase + RME32_IO_DATA_BUFFER +
-					       rme32->capture_ptr),
-				      RME32_BUFFER_SIZE - rme32->capture_ptr);
-			memcpy_fromio(runtime->dma_area,
-				      (void *)(rme32->iobase + RME32_IO_DATA_BUFFER),
-				      ptr);
-			rme32->capture_ptr = ptr;
-		}
-	}
-	return frameptr;
+	rme32_t *rme32 = snd_pcm_substream_chip(substream);
+	return snd_pcm_indirect_capture_pointer(substream, &rme32->capture_pcm,
+						snd_rme32_pcm_byteptr(rme32));
 }
 
+/* for halfduplex mode */
 static snd_pcm_ops_t snd_rme32_playback_spdif_ops = {
 	.open =		snd_rme32_playback_spdif_open,
 	.close =	snd_rme32_playback_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme32_playback_hw_params,
-	.hw_free =	snd_rme32_playback_hw_free,
+	.hw_free =	snd_rme32_pcm_hw_free,
 	.prepare =	snd_rme32_playback_prepare,
-	.trigger =	snd_rme32_playback_trigger,
+	.trigger =	snd_rme32_pcm_trigger,
 	.pointer =	snd_rme32_playback_pointer,
 	.copy =		snd_rme32_playback_copy,
 	.silence =	snd_rme32_playback_silence,
+	.mmap =		snd_pcm_lib_mmap_iomem,
 };
 
 static snd_pcm_ops_t snd_rme32_capture_spdif_ops = {
@@ -1260,11 +1252,12 @@ static snd_pcm_ops_t snd_rme32_capture_spdif_ops = {
 	.close =	snd_rme32_capture_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme32_capture_hw_params,
-	.hw_free =	snd_rme32_capture_hw_free,
+	.hw_free =	snd_rme32_pcm_hw_free,
 	.prepare =	snd_rme32_capture_prepare,
-	.trigger =	snd_rme32_capture_trigger,
+	.trigger =	snd_rme32_pcm_trigger,
 	.pointer =	snd_rme32_capture_pointer,
 	.copy =		snd_rme32_capture_copy,
+	.mmap =		snd_pcm_lib_mmap_iomem,
 };
 
 static snd_pcm_ops_t snd_rme32_playback_adat_ops = {
@@ -1272,12 +1265,12 @@ static snd_pcm_ops_t snd_rme32_playback_adat_ops = {
 	.close =	snd_rme32_playback_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme32_playback_hw_params,
-	.hw_free =	snd_rme32_playback_hw_free,
 	.prepare =	snd_rme32_playback_prepare,
-	.trigger =	snd_rme32_playback_trigger,
+	.trigger =	snd_rme32_pcm_trigger,
 	.pointer =	snd_rme32_playback_pointer,
 	.copy =		snd_rme32_playback_copy,
 	.silence =	snd_rme32_playback_silence,
+	.mmap =		snd_pcm_lib_mmap_iomem,
 };
 
 static snd_pcm_ops_t snd_rme32_capture_adat_ops = {
@@ -1285,11 +1278,58 @@ static snd_pcm_ops_t snd_rme32_capture_adat_ops = {
 	.close =	snd_rme32_capture_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme32_capture_hw_params,
-	.hw_free =	snd_rme32_capture_hw_free,
 	.prepare =	snd_rme32_capture_prepare,
-	.trigger =	snd_rme32_capture_trigger,
+	.trigger =	snd_rme32_pcm_trigger,
 	.pointer =	snd_rme32_capture_pointer,
 	.copy =		snd_rme32_capture_copy,
+	.mmap =		snd_pcm_lib_mmap_iomem,
+};
+
+/* for fullduplex mode */
+static snd_pcm_ops_t snd_rme32_playback_spdif_fd_ops = {
+	.open =		snd_rme32_playback_spdif_open,
+	.close =	snd_rme32_playback_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	snd_rme32_playback_hw_params,
+	.hw_free =	snd_rme32_pcm_hw_free,
+	.prepare =	snd_rme32_playback_prepare,
+	.trigger =	snd_rme32_pcm_trigger,
+	.pointer =	snd_rme32_playback_fd_pointer,
+	.ack =		snd_rme32_playback_fd_ack,
+};
+
+static snd_pcm_ops_t snd_rme32_capture_spdif_fd_ops = {
+	.open =		snd_rme32_capture_spdif_open,
+	.close =	snd_rme32_capture_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	snd_rme32_capture_hw_params,
+	.hw_free =	snd_rme32_pcm_hw_free,
+	.prepare =	snd_rme32_capture_prepare,
+	.trigger =	snd_rme32_pcm_trigger,
+	.pointer =	snd_rme32_capture_fd_pointer,
+	.ack =		snd_rme32_capture_fd_ack,
+};
+
+static snd_pcm_ops_t snd_rme32_playback_adat_fd_ops = {
+	.open =		snd_rme32_playback_adat_open,
+	.close =	snd_rme32_playback_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	snd_rme32_playback_hw_params,
+	.prepare =	snd_rme32_playback_prepare,
+	.trigger =	snd_rme32_pcm_trigger,
+	.pointer =	snd_rme32_playback_fd_pointer,
+	.ack =		snd_rme32_playback_fd_ack,
+};
+
+static snd_pcm_ops_t snd_rme32_capture_adat_fd_ops = {
+	.open =		snd_rme32_capture_adat_open,
+	.close =	snd_rme32_capture_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	snd_rme32_capture_hw_params,
+	.prepare =	snd_rme32_capture_prepare,
+	.trigger =	snd_rme32_pcm_trigger,
+	.pointer =	snd_rme32_capture_fd_pointer,
+	.ack =		snd_rme32_capture_fd_ack,
 };
 
 static void snd_rme32_free(void *private_data)
@@ -1300,8 +1340,7 @@ static void snd_rme32_free(void *private_data)
 		return;
 	}
 	if (rme32->irq >= 0) {
-		snd_rme32_playback_stop(rme32);
-		snd_rme32_capture_stop(rme32);
+		snd_rme32_pcm_stop(rme32, 0);
 		free_irq(rme32->irq, (void *) rme32);
 		rme32->irq = -1;
 	}
@@ -1309,9 +1348,9 @@ static void snd_rme32_free(void *private_data)
 		iounmap((void *) rme32->iobase);
 		rme32->iobase = 0;
 	}
-	if (rme32->res_port != NULL) {
-		release_resource(rme32->res_port);
-		rme32->res_port = NULL;
+	if (rme32->port) {
+		pci_release_regions(rme32->pci);
+		rme32->port = 0;
 	}
 }
 
@@ -1319,7 +1358,6 @@ static void snd_rme32_free_spdif_pcm(snd_pcm_t * pcm)
 {
 	rme32_t *rme32 = (rme32_t *) pcm->private_data;
 	rme32->spdif_pcm = NULL;
-	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
 static void
@@ -1327,7 +1365,6 @@ snd_rme32_free_adat_pcm(snd_pcm_t *pcm)
 {
 	rme32_t *rme32 = (rme32_t *) pcm->private_data;
 	rme32->adat_pcm = NULL;
-	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
 static int __devinit snd_rme32_create(rme32_t * rme32)
@@ -1336,25 +1373,21 @@ static int __devinit snd_rme32_create(rme32_t * rme32)
 	int err;
 
 	rme32->irq = -1;
+	spin_lock_init(&rme32->lock);
 
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
+	if ((err = pci_request_regions(pci, "RME32")) < 0)
+		return err;
 	rme32->port = pci_resource_start(rme32->pci, 0);
 
-	if ((rme32->res_port = request_mem_region(rme32->port, RME32_IO_SIZE, "RME32")) == NULL) {
-		snd_printk("unable to grab memory region 0x%lx-0x%lx\n",
-			   rme32->port, rme32->port + RME32_IO_SIZE - 1);
-		return -EBUSY;
-	}
-
 	if (request_irq(pci->irq, snd_rme32_interrupt, SA_INTERRUPT | SA_SHIRQ, "RME32", (void *) rme32)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
 		return -EBUSY;
 	}
 	rme32->irq = pci->irq;
 
-	spin_lock_init(&rme32->lock);
 	if ((rme32->iobase = (unsigned long) ioremap_nocache(rme32->port, RME32_IO_SIZE)) == 0) {
 		snd_printk("unable to remap memory region 0x%lx-0x%lx\n",
 			   rme32->port, rme32->port + RME32_IO_SIZE - 1);
@@ -1371,18 +1404,22 @@ static int __devinit snd_rme32_create(rme32_t * rme32)
 	rme32->spdif_pcm->private_data = rme32;
 	rme32->spdif_pcm->private_free = snd_rme32_free_spdif_pcm;
 	strcpy(rme32->spdif_pcm->name, "Digi32 IEC958");
-	snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_PLAYBACK,
-			&snd_rme32_playback_spdif_ops);
-	snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_CAPTURE,
-			&snd_rme32_capture_spdif_ops);
-
-	rme32->spdif_pcm->info_flags = 0;
-
-	snd_pcm_lib_preallocate_pages_for_all(rme32->spdif_pcm,
-					      SNDRV_DMA_TYPE_CONTINUOUS,
-					      snd_dma_continuous_data(GFP_KERNEL),
-					      RME32_BUFFER_SIZE,
-					      RME32_BUFFER_SIZE);
+	if (rme32->fullduplex_mode) {
+		snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_PLAYBACK,
+				&snd_rme32_playback_spdif_fd_ops);
+		snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_CAPTURE,
+				&snd_rme32_capture_spdif_fd_ops);
+		snd_pcm_lib_preallocate_pages_for_all(rme32->spdif_pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+						      snd_dma_continuous_data(GFP_KERNEL),
+						      0, RME32_MID_BUFFER_SIZE);
+		rme32->spdif_pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
+	} else {
+		snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_PLAYBACK,
+				&snd_rme32_playback_spdif_ops);
+		snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_CAPTURE,
+				&snd_rme32_capture_spdif_ops);
+		rme32->spdif_pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
+	}
 
 	/* set up ALSA pcm device for ADAT */
 	if ((pci->device == PCI_DEVICE_ID_DIGI32) ||
@@ -1399,18 +1436,22 @@ static int __devinit snd_rme32_create(rme32_t * rme32)
 		rme32->adat_pcm->private_data = rme32;
 		rme32->adat_pcm->private_free = snd_rme32_free_adat_pcm;
 		strcpy(rme32->adat_pcm->name, "Digi32 ADAT");
-		snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_PLAYBACK, 
-				&snd_rme32_playback_adat_ops);
-		snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_CAPTURE, 
-				&snd_rme32_capture_adat_ops);
-		
-		rme32->adat_pcm->info_flags = 0;
-
-		snd_pcm_lib_preallocate_pages_for_all(rme32->adat_pcm, 
-						      SNDRV_DMA_TYPE_CONTINUOUS,
-						      snd_dma_continuous_data(GFP_KERNEL),
-						      RME32_BUFFER_SIZE, 
-						      RME32_BUFFER_SIZE);
+		if (rme32->fullduplex_mode) {
+			snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_PLAYBACK, 
+					&snd_rme32_playback_adat_fd_ops);
+			snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_CAPTURE, 
+					&snd_rme32_capture_adat_fd_ops);
+			snd_pcm_lib_preallocate_pages_for_all(rme32->adat_pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+							      snd_dma_continuous_data(GFP_KERNEL),
+							      0, RME32_MID_BUFFER_SIZE);
+			rme32->adat_pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
+		} else {
+			snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_PLAYBACK, 
+					&snd_rme32_playback_adat_ops);
+			snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_CAPTURE, 
+					&snd_rme32_capture_adat_ops);
+			rme32->adat_pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
+		}
 	}
 
 
@@ -1418,8 +1459,7 @@ static int __devinit snd_rme32_create(rme32_t * rme32)
 	rme32->capture_periodsize = 0;
 
 	/* make sure playback/capture is stopped, if by some reason active */
-	snd_rme32_playback_stop(rme32);
-	snd_rme32_capture_stop(rme32);
+	snd_rme32_pcm_stop(rme32, 0);
 
         /* reset DAC */
         snd_rme32_reset_dac(rme32);
@@ -1464,6 +1504,10 @@ snd_rme32_proc_read(snd_info_entry_t * entry, snd_info_buffer_t * buffer)
 	snd_iprintf(buffer, " (index #%d)\n", rme32->card->number + 1);
 
 	snd_iprintf(buffer, "\nGeneral settings\n");
+	if (rme32->fullduplex_mode)
+		snd_iprintf(buffer, "  Full-duplex mode\n");
+	else
+		snd_iprintf(buffer, "  Half-duplex mode\n");
 	if (RME32_PRO_WITH_8414(rme32)) {
 		snd_iprintf(buffer, "  receiver: CS8414\n");
 	} else {
@@ -1569,26 +1613,24 @@ static int
 snd_rme32_get_loopback_control(snd_kcontrol_t * kcontrol,
 			       snd_ctl_elem_value_t * ucontrol)
 {
-	rme32_t *rme32 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
 
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
 	ucontrol->value.integer.value[0] =
 	    rme32->wcreg & RME32_WCR_SEL ? 0 : 1;
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	return 0;
 }
 static int
 snd_rme32_put_loopback_control(snd_kcontrol_t * kcontrol,
 			       snd_ctl_elem_value_t * ucontrol)
 {
-	rme32_t *rme32 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
 	unsigned int val;
 	int change;
 
 	val = ucontrol->value.integer.value[0] ? 0 : RME32_WCR_SEL;
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
 	val = (rme32->wcreg & ~RME32_WCR_SEL) | val;
 	change = val != rme32->wcreg;
 	if (ucontrol->value.integer.value[0])
@@ -1597,7 +1639,7 @@ snd_rme32_put_loopback_control(snd_kcontrol_t * kcontrol,
 		val |= RME32_WCR_MUTE;
 	writel(rme32->wcreg =
 	       val, rme32->iobase + RME32_IO_CONTROL_REGISTER);
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	return change;
 }
 
@@ -1605,7 +1647,7 @@ static int
 snd_rme32_info_inputtype_control(snd_kcontrol_t * kcontrol,
 				 snd_ctl_elem_info_t * uinfo)
 {
-	rme32_t *rme32 = _snd_kcontrol_chip(kcontrol);
+	rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
 	static char *texts[4] = { "Optical", "Coaxial", "Internal", "XLR" };
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -1635,11 +1677,10 @@ static int
 snd_rme32_get_inputtype_control(snd_kcontrol_t * kcontrol,
 				snd_ctl_elem_value_t * ucontrol)
 {
-	rme32_t *rme32 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
 	unsigned int items = 3;
 
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
 	ucontrol->value.enumerated.item[0] = snd_rme32_getinputtype(rme32);
 
 	switch (rme32->pci->device) {
@@ -1658,15 +1699,14 @@ snd_rme32_get_inputtype_control(snd_kcontrol_t * kcontrol,
 		ucontrol->value.enumerated.item[0] = items - 1;
 	}
 
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	return 0;
 }
 static int
 snd_rme32_put_inputtype_control(snd_kcontrol_t * kcontrol,
 				snd_ctl_elem_value_t * ucontrol)
 {
-	rme32_t *rme32 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
 	unsigned int val;
 	int change, items = 3;
 
@@ -1684,10 +1724,10 @@ snd_rme32_put_inputtype_control(snd_kcontrol_t * kcontrol,
 	}
 	val = ucontrol->value.enumerated.item[0] % items;
 
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
 	change = val != (unsigned int)snd_rme32_getinputtype(rme32);
 	snd_rme32_setinputtype(rme32, val);
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	return change;
 }
 
@@ -1714,28 +1754,26 @@ static int
 snd_rme32_get_clockmode_control(snd_kcontrol_t * kcontrol,
 				snd_ctl_elem_value_t * ucontrol)
 {
-	rme32_t *rme32 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
 
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
 	ucontrol->value.enumerated.item[0] = snd_rme32_getclockmode(rme32);
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	return 0;
 }
 static int
 snd_rme32_put_clockmode_control(snd_kcontrol_t * kcontrol,
 				snd_ctl_elem_value_t * ucontrol)
 {
-	rme32_t *rme32 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
 	unsigned int val;
 	int change;
 
 	val = ucontrol->value.enumerated.item[0] % 3;
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
 	change = val != (unsigned int)snd_rme32_getclockmode(rme32);
 	snd_rme32_setclockmode(rme32, val);
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	return change;
 }
 
@@ -1770,7 +1808,7 @@ static int snd_rme32_control_spdif_info(snd_kcontrol_t * kcontrol,
 static int snd_rme32_control_spdif_get(snd_kcontrol_t * kcontrol,
 				       snd_ctl_elem_value_t * ucontrol)
 {
-	rme32_t *rme32 = _snd_kcontrol_chip(kcontrol);
+	rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
 
 	snd_rme32_convert_to_aes(&ucontrol->value.iec958,
 				 rme32->wcreg_spdif);
@@ -1780,16 +1818,15 @@ static int snd_rme32_control_spdif_get(snd_kcontrol_t * kcontrol,
 static int snd_rme32_control_spdif_put(snd_kcontrol_t * kcontrol,
 				       snd_ctl_elem_value_t * ucontrol)
 {
-	rme32_t *rme32 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
 	int change;
 	u32 val;
 
 	val = snd_rme32_convert_from_aes(&ucontrol->value.iec958);
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
 	change = val != rme32->wcreg_spdif;
 	rme32->wcreg_spdif = val;
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	return change;
 }
 
@@ -1805,7 +1842,7 @@ static int snd_rme32_control_spdif_stream_get(snd_kcontrol_t * kcontrol,
 					      snd_ctl_elem_value_t *
 					      ucontrol)
 {
-	rme32_t *rme32 = _snd_kcontrol_chip(kcontrol);
+	rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
 
 	snd_rme32_convert_to_aes(&ucontrol->value.iec958,
 				 rme32->wcreg_spdif_stream);
@@ -1816,18 +1853,17 @@ static int snd_rme32_control_spdif_stream_put(snd_kcontrol_t * kcontrol,
 					      snd_ctl_elem_value_t *
 					      ucontrol)
 {
-	rme32_t *rme32 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme32_t *rme32 = snd_kcontrol_chip(kcontrol);
 	int change;
 	u32 val;
 
 	val = snd_rme32_convert_from_aes(&ucontrol->value.iec958);
-	spin_lock_irqsave(&rme32->lock, flags);
+	spin_lock_irq(&rme32->lock);
 	change = val != rme32->wcreg_spdif_stream;
 	rme32->wcreg_spdif_stream = val;
 	rme32->wcreg &= ~(RME32_WCR_PRO | RME32_WCR_EMP);
 	writel(rme32->wcreg |= val, rme32->iobase + RME32_IO_CONTROL_REGISTER);
-	spin_unlock_irqrestore(&rme32->lock, flags);
+	spin_unlock_irq(&rme32->lock);
 	return change;
 }
 
@@ -1907,7 +1943,7 @@ static int snd_rme32_create_switches(snd_card_t * card, rme32_t * rme32)
 	int idx, err;
 	snd_kcontrol_t *kctl;
 
-	for (idx = 0; idx < 7; idx++) {
+	for (idx = 0; idx < (int)ARRAY_SIZE(snd_rme32_controls); idx++) {
 		if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_rme32_controls[idx], rme32))) < 0)
 			return err;
 		if (idx == 1)	/* IEC958 (S/PDIF) Stream */
@@ -1952,6 +1988,8 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 	rme32->card = card;
 	rme32->pci = pci;
 	snd_card_set_dev(card, &pci->dev);
+        if (fullduplex[dev])
+		rme32->fullduplex_mode = 1;
 	if ((err = snd_rme32_create(rme32)) < 0) {
 		snd_card_free(card);
 		return err;
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 0e04ae457..a282795c3 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -47,8 +47,7 @@ MODULE_AUTHOR("Anders Torger <torger@ludd.luth.se>");
 MODULE_DESCRIPTION("RME Digi96, Digi96/8, Digi96/8 PRO, Digi96/8 PST, "
 		   "Digi96/8 PAD");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{RME,Digi96},"
+MODULE_SUPPORTED_DEVICE("{{RME,Digi96},"
 		"{RME,Digi96/8},"
 		"{RME,Digi96/8 PRO},"
 		"{RME,Digi96/8 PST},"
@@ -61,13 +60,10 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for RME Digi96 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for RME Digi96 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable RME Digi96 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 
 /*
  * Defines for RME Digi96 series, from internal RME reference documents
@@ -229,7 +225,6 @@ typedef struct snd_rme96 {
 	spinlock_t    lock;
 	int irq;
 	unsigned long port;
-	struct resource *res_port;
 	unsigned long iobase;
 	
 	u32 wcreg;    /* cached write control register value */
@@ -250,10 +245,6 @@ typedef struct snd_rme96 {
         size_t playback_periodsize; /* in bytes, zero if not used */
 	size_t capture_periodsize; /* in bytes, zero if not used */
 
-        snd_pcm_uframes_t playback_last_appl_ptr;
-	size_t playback_ptr;
-	size_t capture_ptr;
-
 	snd_card_t         *card;
 	snd_pcm_t          *spdif_pcm;
 	snd_pcm_t          *adat_pcm; 
@@ -349,7 +340,7 @@ snd_rme96_playback_silence(snd_pcm_substream_t *substream,
 			   snd_pcm_uframes_t pos,
 			   snd_pcm_uframes_t count)
 {
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	count <<= rme96->playback_frlog;
 	pos <<= rme96->playback_frlog;
 	memset_io(rme96->iobase + RME96_IO_PLAY_BUFFER + pos,
@@ -364,7 +355,7 @@ snd_rme96_playback_copy(snd_pcm_substream_t *substream,
 			void __user *src,
 			snd_pcm_uframes_t count)
 {
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	count <<= rme96->playback_frlog;
 	pos <<= rme96->playback_frlog;
 	copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, src,
@@ -379,7 +370,7 @@ snd_rme96_capture_copy(snd_pcm_substream_t *substream,
 		       void __user *dst,
 		       snd_pcm_uframes_t count)
 {
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	count <<= rme96->capture_frlog;
 	pos <<= rme96->capture_frlog;
 	copy_to_user_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + pos,
@@ -392,7 +383,7 @@ snd_rme96_capture_copy(snd_pcm_substream_t *substream,
  */
 static snd_pcm_hardware_t snd_rme96_playback_spdif_info =
 {
-	.info =		     (SNDRV_PCM_INFO_MMAP |
+	.info =		     (SNDRV_PCM_INFO_MMAP_IOMEM |
 			      SNDRV_PCM_INFO_MMAP_VALID |
 			      SNDRV_PCM_INFO_INTERLEAVED |
 			      SNDRV_PCM_INFO_PAUSE),
@@ -421,7 +412,7 @@ static snd_pcm_hardware_t snd_rme96_playback_spdif_info =
  */
 static snd_pcm_hardware_t snd_rme96_capture_spdif_info =
 {
-	.info =		     (SNDRV_PCM_INFO_MMAP |
+	.info =		     (SNDRV_PCM_INFO_MMAP_IOMEM |
 			      SNDRV_PCM_INFO_MMAP_VALID |
 			      SNDRV_PCM_INFO_INTERLEAVED |
 			      SNDRV_PCM_INFO_PAUSE),
@@ -450,7 +441,7 @@ static snd_pcm_hardware_t snd_rme96_capture_spdif_info =
  */
 static snd_pcm_hardware_t snd_rme96_playback_adat_info =
 {
-	.info =		     (SNDRV_PCM_INFO_MMAP |
+	.info =		     (SNDRV_PCM_INFO_MMAP_IOMEM |
 			      SNDRV_PCM_INFO_MMAP_VALID |
 			      SNDRV_PCM_INFO_INTERLEAVED |
 			      SNDRV_PCM_INFO_PAUSE),
@@ -475,7 +466,7 @@ static snd_pcm_hardware_t snd_rme96_playback_adat_info =
  */
 static snd_pcm_hardware_t snd_rme96_capture_adat_info =
 {
-	.info =		     (SNDRV_PCM_INFO_MMAP |
+	.info =		     (SNDRV_PCM_INFO_MMAP_IOMEM |
 			      SNDRV_PCM_INFO_MMAP_VALID |
 			      SNDRV_PCM_INFO_INTERLEAVED |
 			      SNDRV_PCM_INFO_PAUSE),
@@ -991,28 +982,30 @@ static int
 snd_rme96_playback_hw_params(snd_pcm_substream_t *substream,
 			     snd_pcm_hw_params_t *params)
 {
-	unsigned long flags;        
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
 	int err, rate, dummy;
 
-	if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params))) < 0)
-		return err;
-	spin_lock_irqsave(&rme96->lock, flags);
+	runtime->dma_area = (void *)(rme96->iobase + RME96_IO_PLAY_BUFFER);
+	runtime->dma_addr = rme96->port + RME96_IO_PLAY_BUFFER;
+	runtime->dma_bytes = RME96_BUFFER_SIZE;
+
+	spin_lock_irq(&rme96->lock);
 	if (!(rme96->wcreg & RME96_WCR_MASTER) &&
             snd_rme96_getinputtype(rme96) != RME96_INPUT_ANALOG &&
 	    (rate = snd_rme96_capture_getrate(rme96, &dummy)) > 0)
 	{
                 /* slave clock */
                 if ((int)params_rate(params) != rate) {
-		        spin_unlock_irqrestore(&rme96->lock, flags);
+			spin_unlock_irq(&rme96->lock);
 			return -EIO;                    
                 }
 	} else if ((err = snd_rme96_playback_setrate(rme96, params_rate(params))) < 0) {
-		spin_unlock_irqrestore(&rme96->lock, flags);
+		spin_unlock_irq(&rme96->lock);
 		return err;
 	}
 	if ((err = snd_rme96_playback_setformat(rme96, params_format(params))) < 0) {
-		spin_unlock_irqrestore(&rme96->lock, flags);
+		spin_unlock_irq(&rme96->lock);
 		return err;
 	}
 	snd_rme96_setframelog(rme96, params_channels(params), 1);
@@ -1020,7 +1013,7 @@ snd_rme96_playback_hw_params(snd_pcm_substream_t *substream,
 		if (params_period_size(params) << rme96->playback_frlog !=
 		    rme96->capture_periodsize)
 		{
-			spin_unlock_irqrestore(&rme96->lock, flags);
+			spin_unlock_irq(&rme96->lock);
 			return -EBUSY;
 		}
 	}
@@ -1032,50 +1025,44 @@ snd_rme96_playback_hw_params(snd_pcm_substream_t *substream,
 		rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | RME96_WCR_EMP);
 		writel(rme96->wcreg |= rme96->wcreg_spdif_stream, rme96->iobase + RME96_IO_CONTROL_REGISTER);
 	}
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 		
 	return 0;
 }
 
-static int
-snd_rme96_playback_hw_free(snd_pcm_substream_t *substream)
-{
-	snd_pcm_lib_free_pages(substream);
-	return 0;
-}
-
 static int
 snd_rme96_capture_hw_params(snd_pcm_substream_t *substream,
 			    snd_pcm_hw_params_t *params)
 {
-	unsigned long flags;
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int err, isadat, rate;
 	
-	if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params))) < 0)
-		return err;
-	spin_lock_irqsave(&rme96->lock, flags);
+	runtime->dma_area = (void *)(rme96->iobase + RME96_IO_REC_BUFFER);
+	runtime->dma_addr = rme96->port + RME96_IO_REC_BUFFER;
+	runtime->dma_bytes = RME96_BUFFER_SIZE;
+
+	spin_lock_irq(&rme96->lock);
 	if ((err = snd_rme96_capture_setformat(rme96, params_format(params))) < 0) {
-		spin_unlock_irqrestore(&rme96->lock, flags);
+		spin_unlock_irq(&rme96->lock);
 		return err;
 	}
 	if (snd_rme96_getinputtype(rme96) == RME96_INPUT_ANALOG) {
 		if ((err = snd_rme96_capture_analog_setrate(rme96,
 							    params_rate(params))) < 0)
 		{
-			spin_unlock_irqrestore(&rme96->lock, flags);
+			spin_unlock_irq(&rme96->lock);
 			return err;
 		}
 	} else if ((rate = snd_rme96_capture_getrate(rme96, &isadat)) > 0) {
                 if ((int)params_rate(params) != rate) {
-			spin_unlock_irqrestore(&rme96->lock, flags);
+			spin_unlock_irq(&rme96->lock);
 			return -EIO;                    
                 }
                 if ((isadat && runtime->hw.channels_min == 2) ||
                     (!isadat && runtime->hw.channels_min == 8))
                 {
-			spin_unlock_irqrestore(&rme96->lock, flags);
+			spin_unlock_irq(&rme96->lock);
 			return -EIO;
                 }
         }
@@ -1084,33 +1071,24 @@ snd_rme96_capture_hw_params(snd_pcm_substream_t *substream,
 		if (params_period_size(params) << rme96->capture_frlog !=
 		    rme96->playback_periodsize)
 		{
-			spin_unlock_irqrestore(&rme96->lock, flags);
+			spin_unlock_irq(&rme96->lock);
 			return -EBUSY;
 		}
 	}
 	rme96->capture_periodsize =
 		params_period_size(params) << rme96->capture_frlog;
 	snd_rme96_set_period_properties(rme96, rme96->capture_periodsize);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 
 	return 0;
 }
 
-static int
-snd_rme96_capture_hw_free(snd_pcm_substream_t *substream)
-{
-	snd_pcm_lib_free_pages(substream);
-	return 0;
-}
-
 static void
 snd_rme96_playback_start(rme96_t *rme96,
 			 int from_pause)
 {
 	if (!from_pause) {
 		writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS);
-		rme96->playback_last_appl_ptr = 0;
-		rme96->playback_ptr = 0;
 	}
 
 	rme96->wcreg |= RME96_WCR_START;
@@ -1123,7 +1101,6 @@ snd_rme96_capture_start(rme96_t *rme96,
 {
 	if (!from_pause) {
 		writel(0, rme96->iobase + RME96_IO_RESET_REC_POS);
-		rme96->capture_ptr = 0;
 	}
 
 	rme96->wcreg |= RME96_WCR_START_2;
@@ -1186,10 +1163,8 @@ snd_rme96_interrupt(int irq,
 
 static unsigned int period_bytes[] = { RME96_SMALL_BLOCK_SIZE, RME96_LARGE_BLOCK_SIZE };
 
-#define PERIOD_BYTES sizeof(period_bytes) / sizeof(period_bytes[0])
-
 static snd_pcm_hw_constraint_list_t hw_constraints_period_bytes = {
-	.count = PERIOD_BYTES,
+	.count = ARRAY_SIZE(period_bytes),
 	.list = period_bytes,
 	.mask = 0
 };
@@ -1197,24 +1172,21 @@ static snd_pcm_hw_constraint_list_t hw_constraints_period_bytes = {
 static int
 snd_rme96_playback_spdif_open(snd_pcm_substream_t *substream)
 {
-	unsigned long flags;
         int rate, dummy;
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
 	snd_pcm_set_sync(substream);
 
-	spin_lock_irqsave(&rme96->lock, flags);	
+	spin_lock_irq(&rme96->lock);	
         if (rme96->playback_substream != NULL) {
-	        spin_unlock_irqrestore(&rme96->lock, flags);
+		spin_unlock_irq(&rme96->lock);
                 return -EBUSY;
         }
 	rme96->wcreg &= ~RME96_WCR_ADAT;
 	writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);
 	rme96->playback_substream = substream;
-	rme96->playback_last_appl_ptr = 0;
-	rme96->playback_ptr = 0;
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 
 	runtime->hw = snd_rme96_playback_spdif_info;
 	if (!(rme96->wcreg & RME96_WCR_MASTER) &&
@@ -1239,9 +1211,8 @@ snd_rme96_playback_spdif_open(snd_pcm_substream_t *substream)
 static int
 snd_rme96_capture_spdif_open(snd_pcm_substream_t *substream)
 {
-	unsigned long flags;
         int isadat, rate;
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
 	snd_pcm_set_sync(substream);
@@ -1258,14 +1229,13 @@ snd_rme96_capture_spdif_open(snd_pcm_substream_t *substream)
                 runtime->hw.rate_max = rate;
         }
         
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
         if (rme96->capture_substream != NULL) {
-	        spin_unlock_irqrestore(&rme96->lock, flags);
+		spin_unlock_irq(&rme96->lock);
                 return -EBUSY;
         }
 	rme96->capture_substream = substream;
-	rme96->capture_ptr = 0;
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	
 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE);
 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes);
@@ -1276,24 +1246,21 @@ snd_rme96_capture_spdif_open(snd_pcm_substream_t *substream)
 static int
 snd_rme96_playback_adat_open(snd_pcm_substream_t *substream)
 {
-	unsigned long flags;
         int rate, dummy;
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;        
 	
 	snd_pcm_set_sync(substream);
 
-	spin_lock_irqsave(&rme96->lock, flags);	
+	spin_lock_irq(&rme96->lock);	
         if (rme96->playback_substream != NULL) {
-	        spin_unlock_irqrestore(&rme96->lock, flags);
+		spin_unlock_irq(&rme96->lock);
                 return -EBUSY;
         }
 	rme96->wcreg |= RME96_WCR_ADAT;
 	writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);
 	rme96->playback_substream = substream;
-	rme96->playback_last_appl_ptr = 0;
-	rme96->playback_ptr = 0;
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	
 	runtime->hw = snd_rme96_playback_adat_info;
 	if (!(rme96->wcreg & RME96_WCR_MASTER) &&
@@ -1313,9 +1280,8 @@ snd_rme96_playback_adat_open(snd_pcm_substream_t *substream)
 static int
 snd_rme96_capture_adat_open(snd_pcm_substream_t *substream)
 {
-	unsigned long flags;
         int isadat, rate;
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
 	snd_pcm_set_sync(substream);
@@ -1335,14 +1301,13 @@ snd_rme96_capture_adat_open(snd_pcm_substream_t *substream)
                 runtime->hw.rate_max = rate;
         }
         
-	spin_lock_irqsave(&rme96->lock, flags);	
+	spin_lock_irq(&rme96->lock);	
         if (rme96->capture_substream != NULL) {
-	        spin_unlock_irqrestore(&rme96->lock, flags);
+		spin_unlock_irq(&rme96->lock);
                 return -EBUSY;
         }
 	rme96->capture_substream = substream;
-	rme96->capture_ptr = 0;
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 
 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE);
 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes);
@@ -1352,18 +1317,17 @@ snd_rme96_capture_adat_open(snd_pcm_substream_t *substream)
 static int
 snd_rme96_playback_close(snd_pcm_substream_t *substream)
 {
-	unsigned long flags;
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	int spdif = 0;
 
-	spin_lock_irqsave(&rme96->lock, flags);	
+	spin_lock_irq(&rme96->lock);	
 	if (RME96_ISPLAYING(rme96)) {
 		snd_rme96_playback_stop(rme96);
 	}
 	rme96->playback_substream = NULL;
 	rme96->playback_periodsize = 0;
 	spdif = (rme96->wcreg & RME96_WCR_ADAT) == 0;
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	if (spdif) {
 		rme96->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 		snd_ctl_notify(rme96->card, SNDRV_CTL_EVENT_MASK_VALUE |
@@ -1375,46 +1339,43 @@ snd_rme96_playback_close(snd_pcm_substream_t *substream)
 static int
 snd_rme96_capture_close(snd_pcm_substream_t *substream)
 {
-	unsigned long flags;
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	
-	spin_lock_irqsave(&rme96->lock, flags);	
+	spin_lock_irq(&rme96->lock);	
 	if (RME96_ISRECORDING(rme96)) {
 		snd_rme96_capture_stop(rme96);
 	}
 	rme96->capture_substream = NULL;
 	rme96->capture_periodsize = 0;
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return 0;
 }
 
 static int
 snd_rme96_playback_prepare(snd_pcm_substream_t *substream)
 {
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	
-	spin_lock_irqsave(&rme96->lock, flags);	
+	spin_lock_irq(&rme96->lock);	
 	if (RME96_ISPLAYING(rme96)) {
 		snd_rme96_playback_stop(rme96);
 	}
 	writel(0, rme96->iobase + RME96_IO_RESET_PLAY_POS);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return 0;
 }
 
 static int
 snd_rme96_capture_prepare(snd_pcm_substream_t *substream)
 {
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	
-	spin_lock_irqsave(&rme96->lock, flags);	
+	spin_lock_irq(&rme96->lock);	
 	if (RME96_ISRECORDING(rme96)) {
 		snd_rme96_capture_stop(rme96);
 	}
 	writel(0, rme96->iobase + RME96_IO_RESET_REC_POS);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return 0;
 }
 
@@ -1422,7 +1383,7 @@ static int
 snd_rme96_playback_trigger(snd_pcm_substream_t *substream, 
 			   int cmd)
 {
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
@@ -1465,7 +1426,7 @@ static int
 snd_rme96_capture_trigger(snd_pcm_substream_t *substream, 
 			  int cmd)
 {
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
@@ -1508,75 +1469,15 @@ snd_rme96_capture_trigger(snd_pcm_substream_t *substream,
 static snd_pcm_uframes_t
 snd_rme96_playback_pointer(snd_pcm_substream_t *substream)
 {
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_pcm_sframes_t diff;
-	size_t bytes;
-	
-	if (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
-		diff = runtime->control->appl_ptr -
-		    rme96->playback_last_appl_ptr;
- 	        rme96->playback_last_appl_ptr = runtime->control->appl_ptr;
-	        if (diff != 0 &&
-		    diff < -(snd_pcm_sframes_t)(runtime->boundary >> 1))
-		{
-		        diff += runtime->boundary;
-		}
-		bytes = diff << rme96->playback_frlog;
-		
-		if (bytes > RME96_BUFFER_SIZE - rme96->playback_ptr) {
-			memcpy_toio((void *)(rme96->iobase + RME96_IO_PLAY_BUFFER +
-					     rme96->playback_ptr),
-				    runtime->dma_area + rme96->playback_ptr,
-				    RME96_BUFFER_SIZE - rme96->playback_ptr);
-		        bytes -= RME96_BUFFER_SIZE - rme96->playback_ptr;
-			if (bytes > RME96_BUFFER_SIZE) {
-			        bytes = RME96_BUFFER_SIZE;
-			}
-			memcpy_toio((void *)(rme96->iobase + RME96_IO_PLAY_BUFFER),
-				    runtime->dma_area,
-				    bytes);
-			rme96->playback_ptr = bytes;
-		} else if (bytes != 0) {
-			memcpy_toio((void *)(rme96->iobase + RME96_IO_PLAY_BUFFER +
-					     rme96->playback_ptr),
-				    runtime->dma_area + rme96->playback_ptr,
-				    bytes);
-			rme96->playback_ptr += bytes;
-		}
-	}
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
 	return snd_rme96_playback_ptr(rme96);
 }
 
 static snd_pcm_uframes_t
 snd_rme96_capture_pointer(snd_pcm_substream_t *substream)
 {
-	rme96_t *rme96 = _snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_pcm_uframes_t frameptr;
-	size_t ptr;
-
-	frameptr = snd_rme96_capture_ptr(rme96);
-	if (runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
-		ptr = frameptr << rme96->capture_frlog;
-		if (ptr > rme96->capture_ptr) {
-			memcpy_fromio(runtime->dma_area + rme96->capture_ptr,
-				      (void *)(rme96->iobase + RME96_IO_REC_BUFFER +
-					       rme96->capture_ptr),
-				      ptr - rme96->capture_ptr);
-			rme96->capture_ptr += ptr - rme96->capture_ptr;
-		} else if (ptr < rme96->capture_ptr) {
-			memcpy_fromio(runtime->dma_area + rme96->capture_ptr,
-				      (void *)(rme96->iobase + RME96_IO_REC_BUFFER +
-					       rme96->capture_ptr),
-				      RME96_BUFFER_SIZE - rme96->capture_ptr);
-			memcpy_fromio(runtime->dma_area,
-				      (void *)(rme96->iobase + RME96_IO_REC_BUFFER),
-				      ptr);
-			rme96->capture_ptr = ptr;
-		}
-	}
-	return frameptr;
+	rme96_t *rme96 = snd_pcm_substream_chip(substream);
+	return snd_rme96_capture_ptr(rme96);
 }
 
 static snd_pcm_ops_t snd_rme96_playback_spdif_ops = {
@@ -1584,12 +1485,12 @@ static snd_pcm_ops_t snd_rme96_playback_spdif_ops = {
 	.close =	snd_rme96_playback_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme96_playback_hw_params,
-	.hw_free =	snd_rme96_playback_hw_free,
 	.prepare =	snd_rme96_playback_prepare,
 	.trigger =	snd_rme96_playback_trigger,
 	.pointer =	snd_rme96_playback_pointer,
 	.copy =		snd_rme96_playback_copy,
 	.silence =	snd_rme96_playback_silence,
+	.mmap =		snd_pcm_lib_mmap_iomem,
 };
 
 static snd_pcm_ops_t snd_rme96_capture_spdif_ops = {
@@ -1597,11 +1498,11 @@ static snd_pcm_ops_t snd_rme96_capture_spdif_ops = {
 	.close =	snd_rme96_capture_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme96_capture_hw_params,
-	.hw_free =	snd_rme96_capture_hw_free,
 	.prepare =	snd_rme96_capture_prepare,
 	.trigger =	snd_rme96_capture_trigger,
 	.pointer =	snd_rme96_capture_pointer,
 	.copy =		snd_rme96_capture_copy,
+	.mmap =		snd_pcm_lib_mmap_iomem,
 };
 
 static snd_pcm_ops_t snd_rme96_playback_adat_ops = {
@@ -1609,12 +1510,12 @@ static snd_pcm_ops_t snd_rme96_playback_adat_ops = {
 	.close =	snd_rme96_playback_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme96_playback_hw_params,
-	.hw_free =	snd_rme96_playback_hw_free,
 	.prepare =	snd_rme96_playback_prepare,
 	.trigger =	snd_rme96_playback_trigger,
 	.pointer =	snd_rme96_playback_pointer,
 	.copy =		snd_rme96_playback_copy,
 	.silence =	snd_rme96_playback_silence,
+	.mmap =		snd_pcm_lib_mmap_iomem,
 };
 
 static snd_pcm_ops_t snd_rme96_capture_adat_ops = {
@@ -1622,11 +1523,11 @@ static snd_pcm_ops_t snd_rme96_capture_adat_ops = {
 	.close =	snd_rme96_capture_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_rme96_capture_hw_params,
-	.hw_free =	snd_rme96_capture_hw_free,
 	.prepare =	snd_rme96_capture_prepare,
 	.trigger =	snd_rme96_capture_trigger,
 	.pointer =	snd_rme96_capture_pointer,
 	.copy =		snd_rme96_capture_copy,
+	.mmap =		snd_pcm_lib_mmap_iomem,
 };
 
 static void
@@ -1649,10 +1550,9 @@ snd_rme96_free(void *private_data)
 		iounmap((void *)rme96->iobase);
 		rme96->iobase = 0;
 	}
-	if (rme96->res_port != NULL) {
-		release_resource(rme96->res_port);
-		kfree_nocheck(rme96->res_port);
-		rme96->res_port = NULL;
+	if (rme96->port) {
+		pci_release_regions(rme96->pci);
+		rme96->port = 0;
 	}
 }
 
@@ -1661,7 +1561,6 @@ snd_rme96_free_spdif_pcm(snd_pcm_t *pcm)
 {
 	rme96_t *rme96 = (rme96_t *) pcm->private_data;
 	rme96->spdif_pcm = NULL;
-	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
 static void
@@ -1669,7 +1568,6 @@ snd_rme96_free_adat_pcm(snd_pcm_t *pcm)
 {
 	rme96_t *rme96 = (rme96_t *) pcm->private_data;
 	rme96->adat_pcm = NULL;
-	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
 static int __devinit
@@ -1679,24 +1577,21 @@ snd_rme96_create(rme96_t *rme96)
 	int err;
 
 	rme96->irq = -1;
+	spin_lock_init(&rme96->lock);
 
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
+	if ((err = pci_request_regions(pci, "RME96")) < 0)
+		return err;
 	rme96->port = pci_resource_start(rme96->pci, 0);
 
-	if ((rme96->res_port = request_mem_region(rme96->port, RME96_IO_SIZE, "RME96")) == NULL) {
-		snd_printk("unable to grab memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1);
-		return -EBUSY;
-	}
-
 	if (request_irq(pci->irq, snd_rme96_interrupt, SA_INTERRUPT|SA_SHIRQ, "RME96", (void *)rme96)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
 		return -EBUSY;
 	}
 	rme96->irq = pci->irq;
 
-	spin_lock_init(&rme96->lock);
 	if ((rme96->iobase = (unsigned long) ioremap_nocache(rme96->port, RME96_IO_SIZE)) == 0) {
 		snd_printk("unable to remap memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1);
 		return -ENOMEM;
@@ -1719,12 +1614,6 @@ snd_rme96_create(rme96_t *rme96)
 
 	rme96->spdif_pcm->info_flags = 0;
 
-	snd_pcm_lib_preallocate_pages_for_all(rme96->spdif_pcm,
-					      SNDRV_DMA_TYPE_CONTINUOUS,
-					      snd_dma_continuous_data(GFP_KERNEL),
-					      RME96_BUFFER_SIZE,
-					      RME96_BUFFER_SIZE);
-
 	/* set up ALSA pcm device for ADAT */
 	if (pci->device == PCI_DEVICE_ID_DIGI96) {
 		/* ADAT is not available on the base model */
@@ -1742,12 +1631,6 @@ snd_rme96_create(rme96_t *rme96)
 		snd_pcm_set_ops(rme96->adat_pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_rme96_capture_adat_ops);
 		
 		rme96->adat_pcm->info_flags = 0;
-
-		snd_pcm_lib_preallocate_pages_for_all(rme96->adat_pcm,
-						      SNDRV_DMA_TYPE_CONTINUOUS,
-						      snd_dma_continuous_data(GFP_KERNEL),
-						      RME96_BUFFER_SIZE,
-						      RME96_BUFFER_SIZE);
 	}
 
 	rme96->playback_periodsize = 0;
@@ -1958,28 +1841,26 @@ snd_rme96_info_loopback_control(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
 static int
 snd_rme96_get_loopback_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 	ucontrol->value.integer.value[0] = rme96->wcreg & RME96_WCR_SEL ? 0 : 1;
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return 0;
 }
 static int
 snd_rme96_put_loopback_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	unsigned int val;
 	int change;
 	
 	val = ucontrol->value.integer.value[0] ? 0 : RME96_WCR_SEL;
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 	val = (rme96->wcreg & ~RME96_WCR_SEL) | val;
 	change = val != rme96->wcreg;
 	writel(rme96->wcreg = val, rme96->iobase + RME96_IO_CONTROL_REGISTER);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return change;
 }
 
@@ -1987,7 +1868,7 @@ static int
 snd_rme96_info_inputtype_control(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
 	static char *_texts[5] = { "Optical", "Coaxial", "Internal", "XLR", "Analog" };
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	char *texts[5] = { _texts[0], _texts[1], _texts[2], _texts[3], _texts[4] };
 	
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -2023,11 +1904,10 @@ snd_rme96_info_inputtype_control(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
 static int
 snd_rme96_get_inputtype_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	unsigned int items = 3;
 	
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 	ucontrol->value.enumerated.item[0] = snd_rme96_getinputtype(rme96);
 	
 	switch (rme96->pci->device) {
@@ -2057,14 +1937,13 @@ snd_rme96_get_inputtype_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 		ucontrol->value.enumerated.item[0] = items - 1;
 	}
 	
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return 0;
 }
 static int
 snd_rme96_put_inputtype_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	unsigned int val;
 	int change, items = 3;
 	
@@ -2096,10 +1975,10 @@ snd_rme96_put_inputtype_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 		}
 	}
 	
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 	change = (int)val != snd_rme96_getinputtype(rme96);
 	snd_rme96_setinputtype(rme96, val);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return change;
 }
 
@@ -2120,27 +1999,25 @@ snd_rme96_info_clockmode_control(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
 static int
 snd_rme96_get_clockmode_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 	ucontrol->value.enumerated.item[0] = snd_rme96_getclockmode(rme96);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return 0;
 }
 static int
 snd_rme96_put_clockmode_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	unsigned int val;
 	int change;
 	
 	val = ucontrol->value.enumerated.item[0] % 3;
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 	change = (int)val != snd_rme96_getclockmode(rme96);
 	snd_rme96_setclockmode(rme96, val);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return change;
 }
 
@@ -2161,28 +2038,26 @@ snd_rme96_info_attenuation_control(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
 static int
 snd_rme96_get_attenuation_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 	ucontrol->value.enumerated.item[0] = snd_rme96_getattenuation(rme96);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return 0;
 }
 static int
 snd_rme96_put_attenuation_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	unsigned int val;
 	int change;
 	
 	val = ucontrol->value.enumerated.item[0] % 4;
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 
 	change = (int)val != snd_rme96_getattenuation(rme96);
 	snd_rme96_setattenuation(rme96, val);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return change;
 }
 
@@ -2203,27 +2078,25 @@ snd_rme96_info_montracks_control(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
 static int
 snd_rme96_get_montracks_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 	ucontrol->value.enumerated.item[0] = snd_rme96_getmontracks(rme96);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return 0;
 }
 static int
 snd_rme96_put_montracks_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	unsigned int val;
 	int change;
 	
 	val = ucontrol->value.enumerated.item[0] % 4;
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 	change = (int)val != snd_rme96_getmontracks(rme96);
 	snd_rme96_setmontracks(rme96, val);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return change;
 }
 
@@ -2258,7 +2131,7 @@ static int snd_rme96_control_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_i
 
 static int snd_rme96_control_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	
 	snd_rme96_convert_to_aes(&ucontrol->value.iec958, rme96->wcreg_spdif);
 	return 0;
@@ -2266,16 +2139,15 @@ static int snd_rme96_control_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_v
 
 static int snd_rme96_control_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	int change;
 	u32 val;
 	
 	val = snd_rme96_convert_from_aes(&ucontrol->value.iec958);
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 	change = val != rme96->wcreg_spdif;
 	rme96->wcreg_spdif = val;
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return change;
 }
 
@@ -2288,7 +2160,7 @@ static int snd_rme96_control_spdif_stream_info(snd_kcontrol_t *kcontrol, snd_ctl
 
 static int snd_rme96_control_spdif_stream_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	
 	snd_rme96_convert_to_aes(&ucontrol->value.iec958, rme96->wcreg_spdif_stream);
 	return 0;
@@ -2296,18 +2168,17 @@ static int snd_rme96_control_spdif_stream_get(snd_kcontrol_t * kcontrol, snd_ctl
 
 static int snd_rme96_control_spdif_stream_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	int change;
 	u32 val;
 	
 	val = snd_rme96_convert_from_aes(&ucontrol->value.iec958);
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
 	change = val != rme96->wcreg_spdif_stream;
 	rme96->wcreg_spdif_stream = val;
 	rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | RME96_WCR_EMP);
 	writel(rme96->wcreg |= val, rme96->iobase + RME96_IO_CONTROL_REGISTER);
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 	return change;
 }
 
@@ -2327,7 +2198,7 @@ static int snd_rme96_control_spdif_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_e
 static int
 snd_rme96_dac_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 	
         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
         uinfo->count = 2;
@@ -2339,13 +2210,12 @@ snd_rme96_dac_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 static int
 snd_rme96_dac_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
 
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
         u->value.integer.value[0] = rme96->vol[0];
         u->value.integer.value[1] = rme96->vol[1];
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 
         return 0;
 }
@@ -2353,14 +2223,13 @@ snd_rme96_dac_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
 static int
 snd_rme96_dac_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
 {
-	rme96_t *rme96 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme96_t *rme96 = snd_kcontrol_chip(kcontrol);
         int change = 0;
 
 	if (!RME96_HAS_ANALOG_OUT(rme96)) {
 		return -EINVAL;
 	}
-	spin_lock_irqsave(&rme96->lock, flags);
+	spin_lock_irq(&rme96->lock);
         if (u->value.integer.value[0] != rme96->vol[0]) {
 		rme96->vol[0] = u->value.integer.value[0];
                 change = 1;
@@ -2372,7 +2241,7 @@ snd_rme96_dac_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u)
 	if (change) {
 		snd_rme96_apply_dac_volume(rme96);
 	}
-	spin_unlock_irqrestore(&rme96->lock, flags);
+	spin_unlock_irq(&rme96->lock);
 
         return change;
 }
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 628516c8b..a2c59b948 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -52,24 +52,18 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for RME Hammerfall DSP interface.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for RME Hammerfall DSP interface.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable/disable specific Hammerfall DSP soundcards.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(precise_ptr, bool, boot_devs, 0444);
 MODULE_PARM_DESC(precise_ptr, "Enable precise pointer (doesn't work reliably).");
-MODULE_PARM_SYNTAX(precise_ptr, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 module_param_array(line_outs_monitor, bool, boot_devs, 0444);
 MODULE_PARM_DESC(line_outs_monitor, "Send all input and playback streams to line outs by default.");
-MODULE_PARM_SYNTAX(line_outs_monitor, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 MODULE_AUTHOR("Paul Davis <paul@linuxaudiosystems.com>, Marcus Andersson, Thomas Charbonnel <thomas@undata.org>");
 MODULE_DESCRIPTION("RME Hammerfall DSP");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{RME Hammerfall-DSP},"
+MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP},"
 	        "{RME HDSP-9652},"
 		"{RME HDSP-9632}}");
 
@@ -462,12 +456,12 @@ struct _hdsp {
 	unsigned char	      qs_out_channels;	    
 	unsigned char         ds_out_channels;
 	unsigned char         ss_out_channels;
-	void                 *capture_buffer_unaligned;	 /* original buffer addresses */
-	void                 *playback_buffer_unaligned; /* original buffer addresses */
+
+	struct snd_dma_buffer capture_dma_buf;
+	struct snd_dma_buffer playback_dma_buf;
 	unsigned char        *capture_buffer;	    /* suitably aligned address */
 	unsigned char        *playback_buffer;	    /* suitably aligned address */
-	dma_addr_t            capture_buffer_addr;
-	dma_addr_t            playback_buffer_addr;
+
 	pid_t                 capture_pid;
 	pid_t                 playback_pid;
 	int                   running;
@@ -477,7 +471,6 @@ struct _hdsp {
 	int                   dev;
 	int                   irq;
 	unsigned long         port;
-	struct resource      *res_port;
         unsigned long         iobase;
 	snd_card_t           *card;
 	snd_pcm_t            *pcm;
@@ -561,50 +554,24 @@ static char channel_map_H9632_qs[HDSP_MAX_CHANNELS] = {
 	-1, -1
 };
 
-#define HDSP_PREALLOCATE_MEMORY	/* via module snd-hdsp_mem */
-
-#ifdef HDSP_PREALLOCATE_MEMORY
-static void *snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size, dma_addr_t *addrp, int capture)
+static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer *dmab, size_t size)
 {
-	struct snd_dma_device pdev;
-	struct snd_dma_buffer dmbuf;
-
-	memset(&pdev, 0, sizeof(pdev));
-	pdev.type = SNDRV_DMA_TYPE_DEV;
-	pdev.dev = snd_dma_pci_data(pci);
-	pdev.id = capture;
-	dmbuf.bytes = 0;
-	if (! snd_dma_get_reserved(&pdev, &dmbuf)) {
-		if (snd_dma_alloc_pages(&pdev, size, &dmbuf) < 0)
-			return NULL;
-		snd_dma_set_reserved(&pdev, &dmbuf);
+	dmab->dev.type = SNDRV_DMA_TYPE_DEV;
+	dmab->dev.dev = snd_dma_pci_data(pci);
+	if (! snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
+		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+					size, dmab) < 0)
+			return -ENOMEM;
 	}
-	*addrp = dmbuf.addr;
-	return dmbuf.area;
+	return 0;
 }
 
-static void snd_hammerfall_free_buffer(struct pci_dev *pci, size_t size, void *ptr, dma_addr_t addr, int capture)
+static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
 {
-	struct snd_dma_device pdev;
-
-	memset(&pdev, 0, sizeof(pdev));
-	pdev.type = SNDRV_DMA_TYPE_DEV;
-	pdev.dev = snd_dma_pci_data(pci);
-	pdev.id = capture;
-	snd_dma_free_reserved(&pdev);
+	if (dmab->area)
+		snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));
 }
 
-#else
-static void *snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size, dma_addr_t *addrp, int capture)
-{
-	return snd_malloc_pci_pages(pci, size, addrp);
-}
-
-static void snd_hammerfall_free_buffer(struct pci_dev *pci, size_t size, void *ptr, dma_addr_t addr, int capture)
-{
-	snd_free_pci_pages(pci, size, ptr, addr);
-}
-#endif
 
 static struct pci_device_id snd_hdsp_ids[] = {
 	{
@@ -621,15 +588,15 @@ MODULE_DEVICE_TABLE(pci, snd_hdsp_ids);
 /* prototypes */
 static int __devinit snd_hdsp_create_alsa_devices(snd_card_t *card, hdsp_t *hdsp);
 static int __devinit snd_hdsp_create_pcm(snd_card_t *card, hdsp_t *hdsp);
-static inline int snd_hdsp_enable_io (hdsp_t *hdsp);
-static inline void snd_hdsp_initialize_midi_flush (hdsp_t *hdsp);
-static inline void snd_hdsp_initialize_channels (hdsp_t *hdsp);
-static inline int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout);
+static int snd_hdsp_enable_io (hdsp_t *hdsp);
+static void snd_hdsp_initialize_midi_flush (hdsp_t *hdsp);
+static void snd_hdsp_initialize_channels (hdsp_t *hdsp);
+static int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout);
 static int hdsp_autosync_ref(hdsp_t *hdsp);
 static int snd_hdsp_set_defaults(hdsp_t *hdsp);
-static inline void snd_hdsp_9652_enable_mixer (hdsp_t *hdsp);
+static void snd_hdsp_9652_enable_mixer (hdsp_t *hdsp);
 
-static inline int hdsp_playback_to_output_key (hdsp_t *hdsp, int in, int out)
+static int hdsp_playback_to_output_key (hdsp_t *hdsp, int in, int out)
 {
 	switch (hdsp->firmware_rev) {
 	case 0xa:
@@ -642,7 +609,7 @@ static inline int hdsp_playback_to_output_key (hdsp_t *hdsp, int in, int out)
 	}
 }
 
-static inline int hdsp_input_to_output_key (hdsp_t *hdsp, int in, int out)
+static int hdsp_input_to_output_key (hdsp_t *hdsp, int in, int out)
 {
 	switch (hdsp->firmware_rev) {
 	case 0xa:
@@ -655,17 +622,17 @@ static inline int hdsp_input_to_output_key (hdsp_t *hdsp, int in, int out)
 	}
 }
 
-static inline void hdsp_write(hdsp_t *hdsp, int reg, int val)
+static void hdsp_write(hdsp_t *hdsp, int reg, int val)
 {
 	writel(val, hdsp->iobase + reg);
 }
 
-static inline unsigned int hdsp_read(hdsp_t *hdsp, int reg)
+static unsigned int hdsp_read(hdsp_t *hdsp, int reg)
 {
 	return readl (hdsp->iobase + reg);
 }
 
-static inline int hdsp_check_for_iobox (hdsp_t *hdsp)
+static int hdsp_check_for_iobox (hdsp_t *hdsp)
 {
 
 	if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;
@@ -738,7 +705,7 @@ static int snd_hdsp_load_firmware_from_cache(hdsp_t *hdsp) {
 	return 0;
 }
 
-static inline int hdsp_get_iobox_version (hdsp_t *hdsp)
+static int hdsp_get_iobox_version (hdsp_t *hdsp)
 {
 	int err;
 	
@@ -781,7 +748,7 @@ static inline int hdsp_get_iobox_version (hdsp_t *hdsp)
 }
 
 
-static inline int hdsp_check_for_firmware (hdsp_t *hdsp)
+static int hdsp_check_for_firmware (hdsp_t *hdsp)
 {
 	if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;
 	if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
@@ -793,7 +760,7 @@ static inline int hdsp_check_for_firmware (hdsp_t *hdsp)
 }
 
 
-static inline int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout)
+static int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout)
 {    
 	int i;
 
@@ -818,7 +785,7 @@ static inline int hdsp_fifo_wait(hdsp_t *hdsp, int count, int timeout)
 	return -1;
 }
 
-static inline int hdsp_read_gain (hdsp_t *hdsp, unsigned int addr)
+static int hdsp_read_gain (hdsp_t *hdsp, unsigned int addr)
 {
 	if (addr >= HDSP_MATRIX_MIXER_SIZE) {
 		return 0;
@@ -826,7 +793,7 @@ static inline int hdsp_read_gain (hdsp_t *hdsp, unsigned int addr)
 	return hdsp->mixer_matrix[addr];
 }
 
-static inline int hdsp_write_gain(hdsp_t *hdsp, unsigned int addr, unsigned short data)
+static int hdsp_write_gain(hdsp_t *hdsp, unsigned int addr, unsigned short data)
 {
 	unsigned int ad;
 
@@ -835,7 +802,7 @@ static inline int hdsp_write_gain(hdsp_t *hdsp, unsigned int addr, unsigned shor
 	
 	if (hdsp->io_type == H9652 || hdsp->io_type == H9632) {
 
-		/* from martin björnsen:
+		/* from martin björnsen:
 		   
 		   "You can only write dwords to the
 		   mixer memory which contain two
@@ -889,7 +856,7 @@ static inline int hdsp_write_gain(hdsp_t *hdsp, unsigned int addr, unsigned shor
 	return 0;
 }
 
-static inline int snd_hdsp_use_is_exclusive(hdsp_t *hdsp)
+static int snd_hdsp_use_is_exclusive(hdsp_t *hdsp)
 {
 	unsigned long flags;
 	int ret = 1;
@@ -903,7 +870,7 @@ static inline int snd_hdsp_use_is_exclusive(hdsp_t *hdsp)
 	return ret;
 }
 
-static inline int hdsp_external_sample_rate (hdsp_t *hdsp)
+static int hdsp_external_sample_rate (hdsp_t *hdsp)
 {
 	unsigned int status2 = hdsp_read(hdsp, HDSP_status2Register);
 	unsigned int rate_bits = status2 & HDSP_systemFrequencyMask;
@@ -920,7 +887,7 @@ static inline int hdsp_external_sample_rate (hdsp_t *hdsp)
 	}
 }
 
-static inline int hdsp_spdif_sample_rate(hdsp_t *hdsp)
+static int hdsp_spdif_sample_rate(hdsp_t *hdsp)
 {
 	unsigned int status = hdsp_read(hdsp, HDSP_statusRegister);
 	unsigned int rate_bits = (status & HDSP_spdifFrequencyMask);
@@ -952,7 +919,7 @@ static inline int hdsp_spdif_sample_rate(hdsp_t *hdsp)
 	return 0;
 }
 
-static inline void hdsp_compute_period_size(hdsp_t *hdsp)
+static void hdsp_compute_period_size(hdsp_t *hdsp)
 {
 	hdsp->period_bytes = 1 << ((hdsp_decode_latency(hdsp->control_register) + 8));
 }
@@ -974,24 +941,24 @@ static snd_pcm_uframes_t hdsp_hw_pointer(hdsp_t *hdsp)
 	return position;
 }
 
-static inline void hdsp_reset_hw_pointer(hdsp_t *hdsp)
+static void hdsp_reset_hw_pointer(hdsp_t *hdsp)
 {
 	hdsp_write (hdsp, HDSP_resetPointer, 0);
 }
 
-static inline void hdsp_start_audio(hdsp_t *s)
+static void hdsp_start_audio(hdsp_t *s)
 {
 	s->control_register |= (HDSP_AudioInterruptEnable | HDSP_Start);
 	hdsp_write(s, HDSP_controlRegister, s->control_register);
 }
 
-static inline void hdsp_stop_audio(hdsp_t *s)
+static void hdsp_stop_audio(hdsp_t *s)
 {
 	s->control_register &= ~(HDSP_Start | HDSP_AudioInterruptEnable);
 	hdsp_write(s, HDSP_controlRegister, s->control_register);
 }
 
-static inline void hdsp_silence_playback(hdsp_t *hdsp)
+static void hdsp_silence_playback(hdsp_t *hdsp)
 {
 	memset(hdsp->playback_buffer, 0, HDSP_DMA_AREA_BYTES);
 }
@@ -1236,7 +1203,7 @@ static int hdsp_set_passthru(hdsp_t *hdsp, int onoff)
    MIDI
   ----------------------------------------------------------------------------*/
 
-static inline unsigned char snd_hdsp_midi_read_byte (hdsp_t *hdsp, int id)
+static unsigned char snd_hdsp_midi_read_byte (hdsp_t *hdsp, int id)
 {
 	/* the hardware already does the relevant bit-mask with 0xff */
 	if (id) {
@@ -1246,7 +1213,7 @@ static inline unsigned char snd_hdsp_midi_read_byte (hdsp_t *hdsp, int id)
 	}
 }
 
-static inline void snd_hdsp_midi_write_byte (hdsp_t *hdsp, int id, int val)
+static void snd_hdsp_midi_write_byte (hdsp_t *hdsp, int id, int val)
 {
 	/* the hardware already does the relevant bit-mask with 0xff */
 	if (id) {
@@ -1256,7 +1223,7 @@ static inline void snd_hdsp_midi_write_byte (hdsp_t *hdsp, int id, int val)
 	}
 }
 
-static inline int snd_hdsp_midi_input_available (hdsp_t *hdsp, int id)
+static int snd_hdsp_midi_input_available (hdsp_t *hdsp, int id)
 {
 	if (id) {
 		return (hdsp_read(hdsp, HDSP_midiStatusIn1) & 0xff);
@@ -1265,7 +1232,7 @@ static inline int snd_hdsp_midi_input_available (hdsp_t *hdsp, int id)
 	}
 }
 
-static inline int snd_hdsp_midi_output_possible (hdsp_t *hdsp, int id)
+static int snd_hdsp_midi_output_possible (hdsp_t *hdsp, int id)
 {
 	int fifo_bytes_used;
 
@@ -1282,7 +1249,7 @@ static inline int snd_hdsp_midi_output_possible (hdsp_t *hdsp, int id)
 	}
 }
 
-static inline void snd_hdsp_flush_midi_input (hdsp_t *hdsp, int id)
+static void snd_hdsp_flush_midi_input (hdsp_t *hdsp, int id)
 {
 	while (snd_hdsp_midi_input_available (hdsp, id)) {
 		snd_hdsp_midi_read_byte (hdsp, id);
@@ -1429,13 +1396,12 @@ static void snd_hdsp_midi_output_trigger(snd_rawmidi_substream_t * substream, in
 static int snd_hdsp_midi_input_open(snd_rawmidi_substream_t * substream)
 {
 	hdsp_midi_t *hmidi;
-	unsigned long flags;
 
 	hmidi = (hdsp_midi_t *) substream->rmidi->private_data;
-	spin_lock_irqsave (&hmidi->lock, flags);
+	spin_lock_irq (&hmidi->lock);
 	snd_hdsp_flush_midi_input (hmidi->hdsp, hmidi->id);
 	hmidi->input = substream;
-	spin_unlock_irqrestore (&hmidi->lock, flags);
+	spin_unlock_irq (&hmidi->lock);
 
 	return 0;
 }
@@ -1443,12 +1409,11 @@ static int snd_hdsp_midi_input_open(snd_rawmidi_substream_t * substream)
 static int snd_hdsp_midi_output_open(snd_rawmidi_substream_t * substream)
 {
 	hdsp_midi_t *hmidi;
-	unsigned long flags;
 
 	hmidi = (hdsp_midi_t *) substream->rmidi->private_data;
-	spin_lock_irqsave (&hmidi->lock, flags);
+	spin_lock_irq (&hmidi->lock);
 	hmidi->output = substream;
-	spin_unlock_irqrestore (&hmidi->lock, flags);
+	spin_unlock_irq (&hmidi->lock);
 
 	return 0;
 }
@@ -1456,14 +1421,13 @@ static int snd_hdsp_midi_output_open(snd_rawmidi_substream_t * substream)
 static int snd_hdsp_midi_input_close(snd_rawmidi_substream_t * substream)
 {
 	hdsp_midi_t *hmidi;
-	unsigned long flags;
 
 	snd_hdsp_midi_input_trigger (substream, 0);
 
 	hmidi = (hdsp_midi_t *) substream->rmidi->private_data;
-	spin_lock_irqsave (&hmidi->lock, flags);
+	spin_lock_irq (&hmidi->lock);
 	hmidi->input = NULL;
-	spin_unlock_irqrestore (&hmidi->lock, flags);
+	spin_unlock_irq (&hmidi->lock);
 
 	return 0;
 }
@@ -1471,14 +1435,13 @@ static int snd_hdsp_midi_input_close(snd_rawmidi_substream_t * substream)
 static int snd_hdsp_midi_output_close(snd_rawmidi_substream_t * substream)
 {
 	hdsp_midi_t *hmidi;
-	unsigned long flags;
 
 	snd_hdsp_midi_output_trigger (substream, 0);
 
 	hmidi = (hdsp_midi_t *) substream->rmidi->private_data;
-	spin_lock_irqsave (&hmidi->lock, flags);
+	spin_lock_irq (&hmidi->lock);
 	hmidi->output = NULL;
-	spin_unlock_irqrestore (&hmidi->lock, flags);
+	spin_unlock_irq (&hmidi->lock);
 
 	return 0;
 }
@@ -1563,7 +1526,7 @@ static int snd_hdsp_control_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_in
 
 static int snd_hdsp_control_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif);
 	return 0;
@@ -1571,16 +1534,15 @@ static int snd_hdsp_control_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_va
 
 static int snd_hdsp_control_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	u32 val;
 	
 	val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958);
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = val != hdsp->creg_spdif;
 	hdsp->creg_spdif = val;
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -1593,7 +1555,7 @@ static int snd_hdsp_control_spdif_stream_info(snd_kcontrol_t *kcontrol, snd_ctl_
 
 static int snd_hdsp_control_spdif_stream_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	snd_hdsp_convert_to_aes(&ucontrol->value.iec958, hdsp->creg_spdif_stream);
 	return 0;
@@ -1601,18 +1563,17 @@ static int snd_hdsp_control_spdif_stream_get(snd_kcontrol_t * kcontrol, snd_ctl_
 
 static int snd_hdsp_control_spdif_stream_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	u32 val;
 	
 	val = snd_hdsp_convert_from_aes(&ucontrol->value.iec958);
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = val != hdsp->creg_spdif_stream;
 	hdsp->creg_spdif_stream = val;
 	hdsp->control_register &= ~(HDSP_SPDIFProfessional | HDSP_SPDIFNonAudio | HDSP_SPDIFEmphasis);
 	hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register |= val);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -1653,7 +1614,7 @@ static int hdsp_set_spdif_input(hdsp_t *hdsp, int in)
 static int snd_hdsp_info_spdif_in(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
 	static char *texts[4] = {"Optical", "Coaxial", "Internal", "AES"};
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
@@ -1666,7 +1627,7 @@ static int snd_hdsp_info_spdif_in(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
 
 static int snd_hdsp_get_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.enumerated.item[0] = hdsp_spdif_in(hdsp);
 	return 0;
@@ -1674,19 +1635,18 @@ static int snd_hdsp_get_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 
 static int snd_hdsp_put_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.enumerated.item[0] % ((hdsp->io_type == H9632) ? 4 : 3);
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = val != hdsp_spdif_in(hdsp);
 	if (change)
 		hdsp_set_spdif_input(hdsp, val);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -1722,7 +1682,7 @@ static int snd_hdsp_info_spdif_bits(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_
 
 static int snd_hdsp_get_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.integer.value[0] = hdsp_spdif_out(hdsp);
 	return 0;
@@ -1730,18 +1690,17 @@ static int snd_hdsp_get_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
 
 static int snd_hdsp_put_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = (int)val != hdsp_spdif_out(hdsp);
 	hdsp_set_spdif_output(hdsp, val);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -1768,7 +1727,7 @@ static int hdsp_set_spdif_professional(hdsp_t *hdsp, int val)
 
 static int snd_hdsp_get_spdif_professional(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.integer.value[0] = hdsp_spdif_professional(hdsp);
 	return 0;
@@ -1776,18 +1735,17 @@ static int snd_hdsp_get_spdif_professional(snd_kcontrol_t * kcontrol, snd_ctl_el
 
 static int snd_hdsp_put_spdif_professional(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = (int)val != hdsp_spdif_professional(hdsp);
 	hdsp_set_spdif_professional(hdsp, val);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -1814,7 +1772,7 @@ static int hdsp_set_spdif_emphasis(hdsp_t *hdsp, int val)
 
 static int snd_hdsp_get_spdif_emphasis(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.integer.value[0] = hdsp_spdif_emphasis(hdsp);
 	return 0;
@@ -1822,18 +1780,17 @@ static int snd_hdsp_get_spdif_emphasis(snd_kcontrol_t * kcontrol, snd_ctl_elem_v
 
 static int snd_hdsp_put_spdif_emphasis(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = (int)val != hdsp_spdif_emphasis(hdsp);
 	hdsp_set_spdif_emphasis(hdsp, val);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -1860,7 +1817,7 @@ static int hdsp_set_spdif_nonaudio(hdsp_t *hdsp, int val)
 
 static int snd_hdsp_get_spdif_nonaudio(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.integer.value[0] = hdsp_spdif_nonaudio(hdsp);
 	return 0;
@@ -1868,18 +1825,17 @@ static int snd_hdsp_get_spdif_nonaudio(snd_kcontrol_t * kcontrol, snd_ctl_elem_v
 
 static int snd_hdsp_put_spdif_nonaudio(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = (int)val != hdsp_spdif_nonaudio(hdsp);
 	hdsp_set_spdif_nonaudio(hdsp, val);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -1895,7 +1851,7 @@ static int snd_hdsp_put_spdif_nonaudio(snd_kcontrol_t * kcontrol, snd_ctl_elem_v
 static int snd_hdsp_info_spdif_sample_rate(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
 	static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"};
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
@@ -1908,7 +1864,7 @@ static int snd_hdsp_info_spdif_sample_rate(snd_kcontrol_t *kcontrol, snd_ctl_ele
 
 static int snd_hdsp_get_spdif_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	switch (hdsp_spdif_sample_rate(hdsp)) {
 	case 32000:
@@ -1962,7 +1918,7 @@ static int snd_hdsp_info_system_sample_rate(snd_kcontrol_t *kcontrol, snd_ctl_el
 
 static int snd_hdsp_get_system_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.enumerated.item[0] = hdsp->system_sample_rate;
 	return 0;
@@ -1979,7 +1935,7 @@ static int snd_hdsp_get_system_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_el
 
 static int snd_hdsp_info_autosync_sample_rate(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	static char *texts[] = {"32000", "44100", "48000", "64000", "88200", "96000", "None", "128000", "176400", "192000"};	
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
@@ -1992,7 +1948,7 @@ static int snd_hdsp_info_autosync_sample_rate(snd_kcontrol_t *kcontrol, snd_ctl_
 
 static int snd_hdsp_get_autosync_sample_rate(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	switch (hdsp_external_sample_rate(hdsp)) {
 	case 32000:
@@ -2062,7 +2018,7 @@ static int snd_hdsp_info_system_clock_mode(snd_kcontrol_t *kcontrol, snd_ctl_ele
 
 static int snd_hdsp_get_system_clock_mode(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.enumerated.item[0] = hdsp_system_clock_mode(hdsp);
 	return 0;
@@ -2159,7 +2115,7 @@ static int hdsp_set_clock_source(hdsp_t *hdsp, int mode)
 static int snd_hdsp_info_clock_source(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
 	static char *texts[] = {"AutoSync", "Internal 32.0 kHz", "Internal 44.1 kHz", "Internal 48.0 kHz", "Internal 64.0 kHz", "Internal 88.2 kHz", "Internal 96.0 kHz", "Internal 128 kHz", "Internal 176.4 kHz", "Internal 192.0 KHz" };
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
@@ -2175,7 +2131,7 @@ static int snd_hdsp_info_clock_source(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
 
 static int snd_hdsp_get_clock_source(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.enumerated.item[0] = hdsp_clock_source(hdsp);
 	return 0;
@@ -2183,8 +2139,7 @@ static int snd_hdsp_get_clock_source(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
 
 static int snd_hdsp_put_clock_source(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	int val;
 	
@@ -2197,13 +2152,13 @@ static int snd_hdsp_put_clock_source(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
 	} else {
 	    if (val > 6) val = 6;
 	}
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	if (val != hdsp_clock_source(hdsp)) {
 		change = (hdsp_set_clock_source(hdsp, val) == 0) ? 1 : 0;
 	} else {
 		change = 0;
 	}
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -2266,7 +2221,7 @@ static int snd_hdsp_info_da_gain(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
 
 static int snd_hdsp_get_da_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.enumerated.item[0] = hdsp_da_gain(hdsp);
 	return 0;
@@ -2274,8 +2229,7 @@ static int snd_hdsp_get_da_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 
 static int snd_hdsp_put_da_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	int val;
 	
@@ -2284,13 +2238,13 @@ static int snd_hdsp_put_da_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 	val = ucontrol->value.enumerated.item[0];
 	if (val < 0) val = 0;
 	if (val > 2) val = 2;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	if (val != hdsp_da_gain(hdsp)) {
 		change = (hdsp_set_da_gain(hdsp, val) == 0) ? 1 : 0;
 	} else {
 		change = 0;
 	}
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -2353,7 +2307,7 @@ static int snd_hdsp_info_ad_gain(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
 
 static int snd_hdsp_get_ad_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.enumerated.item[0] = hdsp_ad_gain(hdsp);
 	return 0;
@@ -2361,8 +2315,7 @@ static int snd_hdsp_get_ad_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 
 static int snd_hdsp_put_ad_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	int val;
 	
@@ -2371,13 +2324,13 @@ static int snd_hdsp_put_ad_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 	val = ucontrol->value.enumerated.item[0];
 	if (val < 0) val = 0;
 	if (val > 2) val = 2;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	if (val != hdsp_ad_gain(hdsp)) {
 		change = (hdsp_set_ad_gain(hdsp, val) == 0) ? 1 : 0;
 	} else {
 		change = 0;
 	}
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -2440,7 +2393,7 @@ static int snd_hdsp_info_phone_gain(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_
 
 static int snd_hdsp_get_phone_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.enumerated.item[0] = hdsp_phone_gain(hdsp);
 	return 0;
@@ -2448,8 +2401,7 @@ static int snd_hdsp_get_phone_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
 
 static int snd_hdsp_put_phone_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	int val;
 	
@@ -2458,13 +2410,13 @@ static int snd_hdsp_put_phone_gain(snd_kcontrol_t * kcontrol, snd_ctl_elem_value
 	val = ucontrol->value.enumerated.item[0];
 	if (val < 0) val = 0;
 	if (val > 2) val = 2;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	if (val != hdsp_phone_gain(hdsp)) {
 		change = (hdsp_set_phone_gain(hdsp, val) == 0) ? 1 : 0;
 	} else {
 		change = 0;
 	}
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -2507,7 +2459,7 @@ static int snd_hdsp_info_xlr_breakout_cable(snd_kcontrol_t *kcontrol, snd_ctl_el
 
 static int snd_hdsp_get_xlr_breakout_cable(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.enumerated.item[0] = hdsp_xlr_breakout_cable(hdsp);
 	return 0;
@@ -2515,18 +2467,17 @@ static int snd_hdsp_get_xlr_breakout_cable(snd_kcontrol_t * kcontrol, snd_ctl_el
 
 static int snd_hdsp_put_xlr_breakout_cable(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	int val;
 	
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = (int)val != hdsp_xlr_breakout_cable(hdsp);
 	hdsp_set_xlr_breakout_cable(hdsp, val);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -2573,7 +2524,7 @@ static int snd_hdsp_info_aeb(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uin
 
 static int snd_hdsp_get_aeb(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.enumerated.item[0] = hdsp_aeb(hdsp);
 	return 0;
@@ -2581,18 +2532,17 @@ static int snd_hdsp_get_aeb(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * uc
 
 static int snd_hdsp_put_aeb(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	int val;
 	
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = (int)val != hdsp_aeb(hdsp);
 	hdsp_set_aeb(hdsp, val);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -2662,7 +2612,7 @@ static int hdsp_set_pref_sync_ref(hdsp_t *hdsp, int pref)
 static int snd_hdsp_info_pref_sync_ref(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
 	static char *texts[] = {"Word", "IEC958", "ADAT1", "ADAT Sync", "ADAT2", "ADAT3" };
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
@@ -2691,7 +2641,7 @@ static int snd_hdsp_info_pref_sync_ref(snd_kcontrol_t *kcontrol, snd_ctl_elem_in
 
 static int snd_hdsp_get_pref_sync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.enumerated.item[0] = hdsp_pref_sync_ref(hdsp);
 	return 0;
@@ -2699,8 +2649,7 @@ static int snd_hdsp_get_pref_sync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_va
 
 static int snd_hdsp_put_pref_sync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change, max;
 	unsigned int val;
 	
@@ -2723,10 +2672,10 @@ static int snd_hdsp_put_pref_sync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_va
 	}
 
 	val = ucontrol->value.enumerated.item[0] % max;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = (int)val != hdsp_pref_sync_ref(hdsp);
 	hdsp_set_pref_sync_ref(hdsp, val);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -2780,7 +2729,7 @@ static int snd_hdsp_info_autosync_ref(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
 
 static int snd_hdsp_get_autosync_ref(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.enumerated.item[0] = hdsp_pref_sync_ref(hdsp);
 	return 0;
@@ -2806,19 +2755,17 @@ static int snd_hdsp_info_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t
 
 static int snd_hdsp_get_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	ucontrol->value.integer.value[0] = hdsp->passthru;
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return 0;
 }
 
 static int snd_hdsp_put_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	int err = 0;
@@ -2827,11 +2774,11 @@ static int snd_hdsp_put_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 		return -EBUSY;
 
 	val = ucontrol->value.integer.value[0] & 1;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = (ucontrol->value.integer.value[0] != hdsp->passthru);
 	if (change)
 		err = hdsp_set_passthru(hdsp, val);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return err ? err : change;
 }
 
@@ -2871,29 +2818,27 @@ static int snd_hdsp_info_line_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
 
 static int snd_hdsp_get_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	ucontrol->value.integer.value[0] = hdsp_line_out(hdsp);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return 0;
 }
 
 static int snd_hdsp_put_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = (int)val != hdsp_line_out(hdsp);
 	hdsp_set_line_output(hdsp, val);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -2920,8 +2865,7 @@ static int snd_hdsp_info_mixer(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * u
 
 static int snd_hdsp_get_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int source;
 	int destination;
 	int addr;
@@ -2935,16 +2879,15 @@ static int snd_hdsp_get_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
 		addr = hdsp_input_to_output_key(hdsp,source, destination);
 	}
 	
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	ucontrol->value.integer.value[2] = hdsp_read_gain (hdsp, addr);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return 0;
 }
 
 static int snd_hdsp_put_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	int source;
 	int destination;
@@ -2965,11 +2908,11 @@ static int snd_hdsp_put_mixer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
 
 	gain = ucontrol->value.integer.value[2];
 
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 	change = gain != hdsp_read_gain(hdsp, addr);
 	if (change)
 		hdsp_write_gain(hdsp, addr, gain);
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
 
@@ -3011,7 +2954,7 @@ static int hdsp_wc_sync_check(hdsp_t *hdsp)
 
 static int snd_hdsp_get_wc_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 
 	ucontrol->value.enumerated.item[0] = hdsp_wc_sync_check(hdsp);
 	return 0;
@@ -3043,7 +2986,7 @@ static int hdsp_spdif_sync_check(hdsp_t *hdsp)
 
 static int snd_hdsp_get_spdif_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 
 	ucontrol->value.enumerated.item[0] = hdsp_spdif_sync_check(hdsp);
 	return 0;
@@ -3074,7 +3017,7 @@ static int hdsp_adatsync_sync_check(hdsp_t *hdsp)
 
 static int snd_hdsp_get_adatsync_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 
 	ucontrol->value.enumerated.item[0] = hdsp_adatsync_sync_check(hdsp);
 	return 0;
@@ -3105,7 +3048,7 @@ static int hdsp_adat_sync_check(hdsp_t *hdsp, int idx)
 static int snd_hdsp_get_adat_sync_check(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	int offset;
-	hdsp_t *hdsp = _snd_kcontrol_chip(kcontrol);
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 
 	offset = ucontrol->id.index - 1;
 	snd_assert(offset >= 0);
@@ -3194,10 +3137,6 @@ HDSP_PASSTHRU("Passthru", 0),
 HDSP_LINE_OUT("Line Out", 0),
 };
 
-#define HDSP_CONTROLS (sizeof(snd_hdsp_controls)/sizeof(snd_kcontrol_new_t))
-
-#define HDSP_9632_CONTROLS (sizeof(snd_hdsp_9632_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_hdsp_96xx_aeb = HDSP_AEB("Analog Extension Board", 0);
 static snd_kcontrol_new_t snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK;
 
@@ -3207,7 +3146,7 @@ int snd_hdsp_create_controls(snd_card_t *card, hdsp_t *hdsp)
 	int err;
 	snd_kcontrol_t *kctl;
 
-	for (idx = 0; idx < HDSP_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_controls); idx++) {
 		if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_controls[idx], hdsp))) < 0) {
 			return err;
 		}
@@ -3232,7 +3171,7 @@ int snd_hdsp_create_controls(snd_card_t *card, hdsp_t *hdsp)
 	
 	/* DA, AD and Phone gain and XLR breakout cable controls for H9632 cards */
 	if (hdsp->io_type == H9632) {
-		for (idx = 0; idx < HDSP_9632_CONTROLS; idx++) {
+		for (idx = 0; idx < ARRAY_SIZE(snd_hdsp_9632_controls); idx++) {
 			if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_9632_controls[idx], hdsp))) < 0) {
 				return err;
 			}
@@ -3583,59 +3522,34 @@ static void __devinit snd_hdsp_proc_init(hdsp_t *hdsp)
 
 static void snd_hdsp_free_buffers(hdsp_t *hdsp)
 {
-	if (hdsp->capture_buffer_unaligned) {
-		snd_hammerfall_free_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES,
-					   hdsp->capture_buffer_unaligned,
-					   hdsp->capture_buffer_addr, 1);
-	}
-
-	if (hdsp->playback_buffer_unaligned) {
-		snd_hammerfall_free_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES,
-					   hdsp->playback_buffer_unaligned,
-					   hdsp->playback_buffer_addr, 0);
-	}
+	snd_hammerfall_free_buffer(&hdsp->capture_dma_buf, hdsp->pci);
+	snd_hammerfall_free_buffer(&hdsp->playback_dma_buf, hdsp->pci);
 }
 
 static int __devinit snd_hdsp_initialize_memory(hdsp_t *hdsp)
 {
-	void *pb, *cb;
-	dma_addr_t pb_addr, cb_addr;
 	unsigned long pb_bus, cb_bus;
 
-	cb = snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES, &cb_addr, 1);
-	pb = snd_hammerfall_get_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES, &pb_addr, 0);
-
-	if (cb == 0 || pb == 0) {
-		if (cb) {
-			snd_hammerfall_free_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES, cb, cb_addr, 1);
-		}
-		if (pb) {
-			snd_hammerfall_free_buffer(hdsp->pci, HDSP_DMA_AREA_BYTES, pb, pb_addr, 0);
-		}
-
+	if (snd_hammerfall_get_buffer(hdsp->pci, &hdsp->capture_dma_buf, HDSP_DMA_AREA_BYTES) < 0 ||
+	    snd_hammerfall_get_buffer(hdsp->pci, &hdsp->playback_dma_buf, HDSP_DMA_AREA_BYTES) < 0) {
+		if (hdsp->capture_dma_buf.area)
+			snd_dma_free_pages(&hdsp->capture_dma_buf);
 		printk(KERN_ERR "%s: no buffers available\n", hdsp->card_name);
 		return -ENOMEM;
 	}
 
-	/* save raw addresses for use when freeing memory later */
-
-	hdsp->capture_buffer_unaligned = cb;
-	hdsp->playback_buffer_unaligned = pb;
-	hdsp->capture_buffer_addr = cb_addr;
-	hdsp->playback_buffer_addr = pb_addr;
-
 	/* Align to bus-space 64K boundary */
 
-	cb_bus = (cb_addr + 0xFFFF) & ~0xFFFFl;
-	pb_bus = (pb_addr + 0xFFFF) & ~0xFFFFl;
+	cb_bus = (hdsp->capture_dma_buf.addr + 0xFFFF) & ~0xFFFFl;
+	pb_bus = (hdsp->playback_dma_buf.addr + 0xFFFF) & ~0xFFFFl;
 
 	/* Tell the card where it is */
 
 	hdsp_write(hdsp, HDSP_inputBufferAddress, cb_bus);
 	hdsp_write(hdsp, HDSP_outputBufferAddress, pb_bus);
 
-	hdsp->capture_buffer = cb + (cb_bus - cb_addr);
-	hdsp->playback_buffer = pb + (pb_bus - pb_addr);
+	hdsp->capture_buffer = hdsp->capture_dma_buf.area + (cb_bus - hdsp->capture_dma_buf.addr);
+	hdsp->playback_buffer = hdsp->playback_dma_buf.area + (pb_bus - hdsp->playback_dma_buf.addr);
 
 	return 0;
 }
@@ -3809,7 +3723,7 @@ static irqreturn_t snd_hdsp_interrupt(int irq, void *dev_id, struct pt_regs *reg
 
 static snd_pcm_uframes_t snd_hdsp_hw_pointer(snd_pcm_substream_t *substream)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	return hdsp_hw_pointer(hdsp);
 }
 
@@ -3836,7 +3750,7 @@ static char *hdsp_channel_buffer_location(hdsp_t *hdsp,
 static int snd_hdsp_playback_copy(snd_pcm_substream_t *substream, int channel,
 				  snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	char *channel_buf;
 
 	snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
@@ -3851,7 +3765,7 @@ static int snd_hdsp_playback_copy(snd_pcm_substream_t *substream, int channel,
 static int snd_hdsp_capture_copy(snd_pcm_substream_t *substream, int channel,
 				 snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	char *channel_buf;
 
 	snd_assert(pos + count <= HDSP_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
@@ -3866,7 +3780,7 @@ static int snd_hdsp_capture_copy(snd_pcm_substream_t *substream, int channel,
 static int snd_hdsp_hw_silence(snd_pcm_substream_t *substream, int channel,
 				  snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	char *channel_buf;
 
 	channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
@@ -3878,7 +3792,7 @@ static int snd_hdsp_hw_silence(snd_pcm_substream_t *substream, int channel,
 static int snd_hdsp_reset(snd_pcm_substream_t *substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	snd_pcm_substream_t *other;
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		other = hdsp->capture_substream;
@@ -3906,7 +3820,7 @@ static int snd_hdsp_reset(snd_pcm_substream_t *substream)
 static int snd_hdsp_hw_params(snd_pcm_substream_t *substream,
 				 snd_pcm_hw_params_t *params)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	int err;
 	pid_t this_pid;
 	pid_t other_pid;
@@ -3989,7 +3903,7 @@ static int snd_hdsp_hw_params(snd_pcm_substream_t *substream,
 static int snd_hdsp_channel_info(snd_pcm_substream_t *substream,
 				    snd_pcm_channel_info_t *info)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	int mapped_channel;
 
 	snd_assert(info->channel < hdsp->max_channels, return -EINVAL);
@@ -4026,7 +3940,7 @@ static int snd_hdsp_ioctl(snd_pcm_substream_t *substream,
 
 static int snd_hdsp_trigger(snd_pcm_substream_t *substream, int cmd)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	snd_pcm_substream_t *other;
 	int running;
 	
@@ -4105,7 +4019,7 @@ static int snd_hdsp_trigger(snd_pcm_substream_t *substream, int cmd)
 
 static int snd_hdsp_prepare(snd_pcm_substream_t *substream)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	int result = 0;
 
 	if (hdsp_check_for_iobox (hdsp)) {
@@ -4123,10 +4037,10 @@ static int snd_hdsp_prepare(snd_pcm_substream_t *substream)
 		return -EIO;
 	}
 
-	spin_lock(&hdsp->lock);
+	spin_lock_irq(&hdsp->lock);
 	if (!hdsp->running)
 		hdsp_reset_hw_pointer(hdsp);
-	spin_unlock(&hdsp->lock);
+	spin_unlock_irq(&hdsp->lock);
 	return result;
 }
 
@@ -4183,20 +4097,16 @@ static snd_pcm_hardware_t snd_hdsp_capture_subinfo =
 
 static unsigned int hdsp_period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
 
-#define HDSP_PERIOD_SIZES sizeof(hdsp_period_sizes) / sizeof(hdsp_period_sizes[0])
-
 static snd_pcm_hw_constraint_list_t hdsp_hw_constraints_period_sizes = {
-	.count = HDSP_PERIOD_SIZES,
+	.count = ARRAY_SIZE(hdsp_period_sizes),
 	.list = hdsp_period_sizes,
 	.mask = 0
 };
 
 static unsigned int hdsp_9632_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 };
 
-#define HDSP_9632_SAMPLE_RATES sizeof(hdsp_9632_sample_rates) / sizeof(hdsp_9632_sample_rates[0])
-
 static snd_pcm_hw_constraint_list_t hdsp_hw_constraints_9632_sample_rates = {
-	.count = HDSP_9632_SAMPLE_RATES,
+	.count = ARRAY_SIZE(hdsp_9632_sample_rates),
 	.list = hdsp_9632_sample_rates,
 	.mask = 0
 };
@@ -4364,8 +4274,7 @@ static int snd_hdsp_hw_rule_rate_in_channels(snd_pcm_hw_params_t *params,
 
 static int snd_hdsp_playback_open(snd_pcm_substream_t *substream)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
 	if (hdsp_check_for_iobox (hdsp)) {
@@ -4383,7 +4292,7 @@ static int snd_hdsp_playback_open(snd_pcm_substream_t *substream)
 		return -EIO;
 	}
 
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 
 	snd_pcm_set_sync(substream);
 
@@ -4399,7 +4308,7 @@ static int snd_hdsp_playback_open(snd_pcm_substream_t *substream)
 	hdsp->playback_pid = current->pid;
 	hdsp->playback_substream = substream;
 
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 
 	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes);
@@ -4430,15 +4339,14 @@ static int snd_hdsp_playback_open(snd_pcm_substream_t *substream)
 
 static int snd_hdsp_playback_release(snd_pcm_substream_t *substream)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 
 	hdsp->playback_pid = -1;
 	hdsp->playback_substream = NULL;
 
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 
 	hdsp->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 	snd_ctl_notify(hdsp->card, SNDRV_CTL_EVENT_MASK_VALUE |
@@ -4449,8 +4357,7 @@ static int snd_hdsp_playback_release(snd_pcm_substream_t *substream)
 
 static int snd_hdsp_capture_open(snd_pcm_substream_t *substream)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
 	if (hdsp_check_for_iobox (hdsp)) {
@@ -4468,7 +4375,7 @@ static int snd_hdsp_capture_open(snd_pcm_substream_t *substream)
 		return -EIO;
 	}
 
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 
 	snd_pcm_set_sync(substream);
 
@@ -4484,7 +4391,7 @@ static int snd_hdsp_capture_open(snd_pcm_substream_t *substream)
 	hdsp->capture_pid = current->pid;
 	hdsp->capture_substream = substream;
 
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 
 	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hdsp_hw_constraints_period_sizes);
@@ -4509,15 +4416,14 @@ static int snd_hdsp_capture_open(snd_pcm_substream_t *substream)
 
 static int snd_hdsp_capture_release(snd_pcm_substream_t *substream)
 {
-	hdsp_t *hdsp = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 
-	spin_lock_irqsave(&hdsp->lock, flags);
+	spin_lock_irq(&hdsp->lock);
 
 	hdsp->capture_pid = -1;
 	hdsp->capture_substream = NULL;
 
-	spin_unlock_irqrestore(&hdsp->lock, flags);
+	spin_unlock_irq(&hdsp->lock);
 	return 0;
 }
 
@@ -4830,19 +4736,13 @@ static int __devinit snd_hdsp_create_pcm(snd_card_t *card,
 	return 0;
 }
 
-static inline void snd_hdsp_9652_enable_mixer (hdsp_t *hdsp)
+static void snd_hdsp_9652_enable_mixer (hdsp_t *hdsp)
 {
         hdsp->control2_register |= HDSP_9652_ENABLE_MIXER;
 	hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
 }
 
-static inline void snd_hdsp_9652_disable_mixer (hdsp_t *hdsp)
-{
-        hdsp->control2_register &= ~HDSP_9652_ENABLE_MIXER;
-	hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
-}
-
-static inline int snd_hdsp_enable_io (hdsp_t *hdsp)
+static int snd_hdsp_enable_io (hdsp_t *hdsp)
 {
 	int i;
 	
@@ -4858,7 +4758,7 @@ static inline int snd_hdsp_enable_io (hdsp_t *hdsp)
 	return 0;
 }
 
-static inline void snd_hdsp_initialize_channels(hdsp_t *hdsp)
+static void snd_hdsp_initialize_channels(hdsp_t *hdsp)
 {
 	int status, aebi_channels, aebo_channels;
 	
@@ -4901,7 +4801,7 @@ static inline void snd_hdsp_initialize_channels(hdsp_t *hdsp)
 	}
 }
 
-static inline void snd_hdsp_initialize_midi_flush (hdsp_t *hdsp)
+static void snd_hdsp_initialize_midi_flush (hdsp_t *hdsp)
 {
 	snd_hdsp_flush_midi_input (hdsp, 0);
 	snd_hdsp_flush_midi_input (hdsp, 1);
@@ -4980,7 +4880,6 @@ static int __devinit snd_hdsp_create(snd_card_t *card,
 	spin_lock_init(&hdsp->midi[0].lock);
 	spin_lock_init(&hdsp->midi[1].lock);
 	hdsp->iobase = 0;
-	hdsp->res_port = NULL;
 	hdsp->control_register = 0;
 	hdsp->control2_register = 0;
 	hdsp->io_type = Undefined;
@@ -5035,13 +4934,9 @@ static int __devinit snd_hdsp_create(snd_card_t *card,
 
 	pci_set_master(hdsp->pci);
 
+	if ((err = pci_request_regions(pci, "hdsp")) < 0)
+		return err;
 	hdsp->port = pci_resource_start(pci, 0);
-
-	if ((hdsp->res_port = request_mem_region(hdsp->port, HDSP_IO_EXTENT, "hdsp")) == NULL) {
-		snd_printk("unable to grab memory region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1);
-		return -EBUSY;
-	}
-
 	if ((hdsp->iobase = (unsigned long) ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == 0) {
 		snd_printk("unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1);
 		return -EBUSY;
@@ -5114,7 +5009,7 @@ static int __devinit snd_hdsp_create(snd_card_t *card,
 
 static int snd_hdsp_free(hdsp_t *hdsp)
 {
-	if (hdsp->res_port) {
+	if (hdsp->port) {
 		/* stop the audio, and cancel all interrupts */
 		hdsp->control_register &= ~(HDSP_Start|HDSP_AudioInterruptEnable|HDSP_Midi0InterruptEnable|HDSP_Midi1InterruptEnable);
 		hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register);
@@ -5128,10 +5023,8 @@ static int snd_hdsp_free(hdsp_t *hdsp)
 	if (hdsp->iobase)
 		iounmap((void *) hdsp->iobase);
 
-	if (hdsp->res_port) {
-		release_resource(hdsp->res_port);
-		kfree_nocheck(hdsp->res_port);
-	}
+	if (hdsp->port)
+		pci_release_regions(hdsp->pci);
 		
 	return 0;
 }
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index e1abd9813..c6cbccce4 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -46,21 +46,16 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for RME Digi9652 (Hammerfall) soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for RME Digi9652 (Hammerfall) soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable/disable specific RME96{52,36} soundcards.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(precise_ptr, bool, boot_devs, 0444);
 MODULE_PARM_DESC(precise_ptr, "Enable precise pointer (doesn't work reliably).");
-MODULE_PARM_SYNTAX(precise_ptr, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 MODULE_AUTHOR("Paul Davis <pbd@op.net>, Winfried Ritsch");
 MODULE_DESCRIPTION("RME Digi9652/Digi9636");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{RME,Hammerfall},"
+MODULE_SUPPORTED_DEVICE("{{RME,Hammerfall},"
 		"{RME,Hammerfall-Light}}");
 
 /* The Hammerfall has two sets of 24 ADAT + 2 S/PDIF channels, one for
@@ -217,7 +212,6 @@ typedef struct snd_rme9652 {
 	spinlock_t lock;
 	int irq;
 	unsigned long port;
-	struct resource *res_port;
 	unsigned long iobase;
 	
 	int precise_ptr;
@@ -239,12 +233,11 @@ typedef struct snd_rme9652 {
 	unsigned char ds_channels;
 	unsigned char ss_channels;	/* different for hammerfall/hammerfall-light */
 
-	void *capture_buffer_unaligned;	/* original buffer addresses */
-	void *playback_buffer_unaligned;	/* original buffer addresses */
+	struct snd_dma_buffer playback_dma_buf;
+	struct snd_dma_buffer capture_dma_buf;
+
 	unsigned char *capture_buffer;	/* suitably aligned address */
 	unsigned char *playback_buffer;	/* suitably aligned address */
-	dma_addr_t capture_buffer_addr;
-	dma_addr_t playback_buffer_addr;
 
 	pid_t capture_pid;
 	pid_t playback_pid;
@@ -307,50 +300,24 @@ static char channel_map_9636_ds[26] = {
 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
 };
 
-#define RME9652_PREALLOCATE_MEMORY	/* via module snd-hammerfall-mem */
-
-#ifdef RME9652_PREALLOCATE_MEMORY
-static void *snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size, dma_addr_t *addrp, int capture)
+static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer *dmab, size_t size)
 {
-	struct snd_dma_device pdev;
-	struct snd_dma_buffer dmbuf;
-
-	memset(&pdev, 0, sizeof(pdev));
-	pdev.type = SNDRV_DMA_TYPE_DEV;
-	pdev.dev = snd_dma_pci_data(pci);
-	pdev.id = capture;
-	dmbuf.bytes = 0;
-	if (! snd_dma_get_reserved(&pdev, &dmbuf)) {
-		if (snd_dma_alloc_pages(&pdev, size, &dmbuf) < 0)
-			return NULL;
-		snd_dma_set_reserved(&pdev, &dmbuf);
+	dmab->dev.type = SNDRV_DMA_TYPE_DEV;
+	dmab->dev.dev = snd_dma_pci_data(pci);
+	if (! snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
+		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+					size, dmab) < 0)
+			return -ENOMEM;
 	}
-	*addrp = dmbuf.addr;
-	return dmbuf.area;
-}
-
-static void snd_hammerfall_free_buffer(struct pci_dev *pci, size_t size, void *ptr, dma_addr_t addr, int capture)
-{
-	struct snd_dma_device pdev;
-
-	memset(&pdev, 0, sizeof(pdev));
-	pdev.type = SNDRV_DMA_TYPE_DEV;
-	pdev.dev = snd_dma_pci_data(pci);
-	pdev.id = capture;
-	snd_dma_free_reserved(&pdev);
+	return 0;
 }
 
-#else
-static void *snd_hammerfall_get_buffer(struct pci_dev *pci, size_t size, dma_addr_t *addrp, int capture)
+static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
 {
-	return snd_malloc_pci_pages(pci, size, addrp);
+	if (dmab->area)
+		snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));
 }
 
-static void snd_hammerfall_free_buffer(struct pci_dev *pci, size_t size, void *ptr, dma_addr_t addr, int capture)
-{
-	snd_free_pci_pages(pci, size, ptr, addr);
-}
-#endif
 
 static struct pci_device_id snd_rme9652_ids[] = {
 	{
@@ -858,7 +825,7 @@ static int snd_rme9652_control_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem
 
 static int snd_rme9652_control_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	
 	snd_rme9652_convert_to_aes(&ucontrol->value.iec958, rme9652->creg_spdif);
 	return 0;
@@ -866,16 +833,15 @@ static int snd_rme9652_control_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem
 
 static int snd_rme9652_control_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	int change;
 	u32 val;
 	
 	val = snd_rme9652_convert_from_aes(&ucontrol->value.iec958);
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	change = val != rme9652->creg_spdif;
 	rme9652->creg_spdif = val;
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return change;
 }
 
@@ -888,7 +854,7 @@ static int snd_rme9652_control_spdif_stream_info(snd_kcontrol_t *kcontrol, snd_c
 
 static int snd_rme9652_control_spdif_stream_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	
 	snd_rme9652_convert_to_aes(&ucontrol->value.iec958, rme9652->creg_spdif_stream);
 	return 0;
@@ -896,18 +862,17 @@ static int snd_rme9652_control_spdif_stream_get(snd_kcontrol_t * kcontrol, snd_c
 
 static int snd_rme9652_control_spdif_stream_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	int change;
 	u32 val;
 	
 	val = snd_rme9652_convert_from_aes(&ucontrol->value.iec958);
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	change = val != rme9652->creg_spdif_stream;
 	rme9652->creg_spdif_stream = val;
 	rme9652->control_register &= ~(RME9652_PRO | RME9652_Dolby | RME9652_EMP);
 	rme9652_write(rme9652, RME9652_control_register, rme9652->control_register |= val);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return change;
 }
 
@@ -977,30 +942,28 @@ static int snd_rme9652_info_adat1_in(snd_kcontrol_t *kcontrol, snd_ctl_elem_info
 
 static int snd_rme9652_get_adat1_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	ucontrol->value.enumerated.item[0] = rme9652_adat1_in(rme9652);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return 0;
 }
 
 static int snd_rme9652_put_adat1_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	
 	if (!snd_rme9652_use_is_exclusive(rme9652))
 		return -EBUSY;
 	val = ucontrol->value.enumerated.item[0] % 2;
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	change = val != rme9652_adat1_in(rme9652);
 	if (change)
 		rme9652_set_adat1_input(rme9652, val);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return change;
 }
 
@@ -1050,30 +1013,28 @@ static int snd_rme9652_info_spdif_in(snd_kcontrol_t *kcontrol, snd_ctl_elem_info
 
 static int snd_rme9652_get_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	ucontrol->value.enumerated.item[0] = rme9652_spdif_in(rme9652);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return 0;
 }
 
 static int snd_rme9652_put_spdif_in(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	
 	if (!snd_rme9652_use_is_exclusive(rme9652))
 		return -EBUSY;
 	val = ucontrol->value.enumerated.item[0] % 3;
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	change = val != rme9652_spdif_in(rme9652);
 	if (change)
 		rme9652_set_spdif_input(rme9652, val);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return change;
 }
 
@@ -1121,29 +1082,27 @@ static int snd_rme9652_info_spdif_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
 
 static int snd_rme9652_get_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	ucontrol->value.integer.value[0] = rme9652_spdif_out(rme9652);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return 0;
 }
 
 static int snd_rme9652_put_spdif_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	
 	if (!snd_rme9652_use_is_exclusive(rme9652))
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	change = (int)val != rme9652_spdif_out(rme9652);
 	rme9652_set_spdif_output(rme9652, val);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return change;
 }
 
@@ -1210,27 +1169,25 @@ static int snd_rme9652_info_sync_mode(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
 
 static int snd_rme9652_get_sync_mode(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	ucontrol->value.enumerated.item[0] = rme9652_sync_mode(rme9652);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return 0;
 }
 
 static int snd_rme9652_put_sync_mode(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	
 	val = ucontrol->value.enumerated.item[0] % 3;
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	change = (int)val != rme9652_sync_mode(rme9652);
 	rme9652_set_sync_mode(rme9652, val);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return change;
 }
 
@@ -1291,7 +1248,7 @@ static int rme9652_set_sync_pref(rme9652_t *rme9652, int pref)
 static int snd_rme9652_info_sync_pref(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
 	static char *texts[4] = {"IEC958 In", "ADAT1 In", "ADAT2 In", "ADAT3 In"};
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
@@ -1304,19 +1261,17 @@ static int snd_rme9652_info_sync_pref(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
 
 static int snd_rme9652_get_sync_pref(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	ucontrol->value.enumerated.item[0] = rme9652_sync_pref(rme9652);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return 0;
 }
 
 static int snd_rme9652_put_sync_pref(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	int change, max;
 	unsigned int val;
 	
@@ -1324,16 +1279,16 @@ static int snd_rme9652_put_sync_pref(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
 		return -EBUSY;
 	max = rme9652->ss_channels == RME9652_NCHANNELS ? 4 : 3;
 	val = ucontrol->value.enumerated.item[0] % max;
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	change = (int)val != rme9652_sync_pref(rme9652);
 	rme9652_set_sync_pref(rme9652, val);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return change;
 }
 
 static int snd_rme9652_info_thru(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 	uinfo->count = rme9652->ss_channels;
 	uinfo->value.integer.min = 0;
@@ -1343,7 +1298,7 @@ static int snd_rme9652_info_thru(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
 
 static int snd_rme9652_get_thru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	unsigned int k;
 	u32 thru_bits = rme9652->thru_bits;
 
@@ -1355,8 +1310,7 @@ static int snd_rme9652_get_thru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 
 static int snd_rme9652_put_thru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int chn;
 	u32 thru_bits = 0;
@@ -1369,7 +1323,7 @@ static int snd_rme9652_put_thru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 			thru_bits |= 1 << chn;
 	}
 	
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	change = thru_bits ^ rme9652->thru_bits;
 	if (change) {
 		for (chn = 0; chn < rme9652->ss_channels; ++chn) {
@@ -1378,7 +1332,7 @@ static int snd_rme9652_put_thru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 			rme9652_set_thru(rme9652,chn,thru_bits&(1<<chn));
 		}
 	}
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return !!change;
 }
 
@@ -1399,19 +1353,17 @@ static int snd_rme9652_info_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_inf
 
 static int snd_rme9652_get_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	ucontrol->value.integer.value[0] = rme9652->passthru;
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return 0;
 }
 
 static int snd_rme9652_put_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
 	int err = 0;
@@ -1420,11 +1372,11 @@ static int snd_rme9652_put_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_valu
 		return -EBUSY;
 
 	val = ucontrol->value.integer.value[0] & 1;
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	change = (ucontrol->value.integer.value[0] != rme9652->passthru);
 	if (change)
 		err = rme9652_set_passthru(rme9652, val);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return err ? err : change;
 }
 
@@ -1447,12 +1399,11 @@ static int snd_rme9652_info_spdif_rate(snd_kcontrol_t *kcontrol, snd_ctl_elem_in
 
 static int snd_rme9652_get_spdif_rate(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 	ucontrol->value.integer.value[0] = rme9652_spdif_sample_rate(rme9652);
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return 0;
 }
 
@@ -1477,7 +1428,7 @@ static int snd_rme9652_info_adat_sync(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
 
 static int snd_rme9652_get_adat_sync(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	unsigned int mask1, mask2, val;
 	
 	switch (kcontrol->private_value) {
@@ -1509,7 +1460,7 @@ static int snd_rme9652_info_tc_valid(snd_kcontrol_t *kcontrol, snd_ctl_elem_info
 
 static int snd_rme9652_get_tc_valid(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
-	rme9652_t *rme9652 = _snd_kcontrol_chip(kcontrol);
+	rme9652_t *rme9652 = snd_kcontrol_chip(kcontrol);
 	
 	ucontrol->value.integer.value[0] = 
 		(rme9652_read(rme9652, RME9652_status_register) & RME9652_tc_valid) ? 1 : 0;
@@ -1573,8 +1524,6 @@ static int snd_rme9652_get_tc_value(void *private_data,
 
 #endif				/* ALSA_HAS_STANDARD_WAY_OF_RETURNING_TIMECODE */
 
-#define RME9652_CONTROLS (sizeof(snd_rme9652_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_rme9652_controls[] = {
 {
 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1642,7 +1591,7 @@ int snd_rme9652_create_controls(snd_card_t *card, rme9652_t *rme9652)
 	int err;
 	snd_kcontrol_t *kctl;
 
-	for (idx = 0; idx < RME9652_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_rme9652_controls); idx++) {
 		if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_rme9652_controls[idx], rme9652))) < 0)
 			return err;
 		if (idx == 1)	/* IEC958 (S/PDIF) Stream */
@@ -1847,17 +1796,8 @@ static void __devinit snd_rme9652_proc_init(rme9652_t *rme9652)
 
 static void snd_rme9652_free_buffers(rme9652_t *rme9652)
 {
-	if (rme9652->capture_buffer_unaligned) {
-		snd_hammerfall_free_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES,
-					   rme9652->capture_buffer_unaligned,
-					   rme9652->capture_buffer_addr, 1);
-	}
-
-	if (rme9652->playback_buffer_unaligned) {
-		snd_hammerfall_free_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES,
-					   rme9652->playback_buffer_unaligned,
-					   rme9652->playback_buffer_addr, 0);
-	}
+	snd_hammerfall_free_buffer(&rme9652->capture_dma_buf, rme9652->pci);
+	snd_hammerfall_free_buffer(&rme9652->playback_dma_buf, rme9652->pci);
 }
 
 static int snd_rme9652_free(rme9652_t *rme9652)
@@ -1866,57 +1806,40 @@ static int snd_rme9652_free(rme9652_t *rme9652)
 		rme9652_stop(rme9652);
 	snd_rme9652_free_buffers(rme9652);
 
-	if (rme9652->iobase)
-		iounmap((void *) rme9652->iobase);
-	if (rme9652->res_port) {
-		release_resource(rme9652->res_port);
-		kfree_nocheck(rme9652->res_port);
-	}
 	if (rme9652->irq >= 0)
 		free_irq(rme9652->irq, (void *)rme9652);
+	if (rme9652->iobase)
+		iounmap((void *) rme9652->iobase);
+	if (rme9652->port)
+		pci_release_regions(rme9652->pci);
+
 	return 0;
 }
 
 static int __devinit snd_rme9652_initialize_memory(rme9652_t *rme9652)
 {
-	void *pb, *cb;
-	dma_addr_t pb_addr, cb_addr;
 	unsigned long pb_bus, cb_bus;
 
-	cb = snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES, &cb_addr, 1);
-	pb = snd_hammerfall_get_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES, &pb_addr, 0);
-
-	if (cb == 0 || pb == 0) {
-		if (cb) {
-			snd_hammerfall_free_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES, cb, cb_addr, 1);
-		}
-		if (pb) {
-			snd_hammerfall_free_buffer(rme9652->pci, RME9652_DMA_AREA_BYTES, pb, pb_addr, 0);
-		}
-
+	if (snd_hammerfall_get_buffer(rme9652->pci, &rme9652->capture_dma_buf, RME9652_DMA_AREA_BYTES) < 0 ||
+	    snd_hammerfall_get_buffer(rme9652->pci, &rme9652->playback_dma_buf, RME9652_DMA_AREA_BYTES) < 0) {
+		if (rme9652->capture_dma_buf.area)
+			snd_dma_free_pages(&rme9652->capture_dma_buf);
 		printk(KERN_ERR "%s: no buffers available\n", rme9652->card_name);
 		return -ENOMEM;
 	}
 
-	/* save raw addresses for use when freeing memory later */
-
-	rme9652->capture_buffer_unaligned = cb;
-	rme9652->playback_buffer_unaligned = pb;
-	rme9652->capture_buffer_addr = cb_addr;
-	rme9652->playback_buffer_addr = pb_addr;
-
 	/* Align to bus-space 64K boundary */
 
-	cb_bus = (cb_addr + 0xFFFF) & ~0xFFFFl;
-	pb_bus = (pb_addr + 0xFFFF) & ~0xFFFFl;
+	cb_bus = (rme9652->capture_dma_buf.addr + 0xFFFF) & ~0xFFFFl;
+	pb_bus = (rme9652->playback_dma_buf.addr + 0xFFFF) & ~0xFFFFl;
 
 	/* Tell the card where it is */
 
 	rme9652_write(rme9652, RME9652_rec_buffer, cb_bus);
 	rme9652_write(rme9652, RME9652_play_buffer, pb_bus);
 
-	rme9652->capture_buffer = cb + (cb_bus - cb_addr);
-	rme9652->playback_buffer = pb + (pb_bus - pb_addr);
+	rme9652->capture_buffer = rme9652->capture_dma_buf.area + (cb_bus - rme9652->capture_dma_buf.addr);
+	rme9652->playback_buffer = rme9652->playback_dma_buf.area + (pb_bus - rme9652->playback_dma_buf.addr);
 
 	return 0;
 }
@@ -1984,7 +1907,7 @@ static irqreturn_t snd_rme9652_interrupt(int irq, void *dev_id, struct pt_regs *
 
 static snd_pcm_uframes_t snd_rme9652_hw_pointer(snd_pcm_substream_t *substream)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 	return rme9652_hw_pointer(rme9652);
 }
 
@@ -2013,7 +1936,7 @@ static char *rme9652_channel_buffer_location(rme9652_t *rme9652,
 static int snd_rme9652_playback_copy(snd_pcm_substream_t *substream, int channel,
 				     snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 	char *channel_buf;
 
 	snd_assert(pos + count <= RME9652_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
@@ -2030,7 +1953,7 @@ static int snd_rme9652_playback_copy(snd_pcm_substream_t *substream, int channel
 static int snd_rme9652_capture_copy(snd_pcm_substream_t *substream, int channel,
 				    snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 	char *channel_buf;
 
 	snd_assert(pos + count <= RME9652_CHANNEL_BUFFER_BYTES / 4, return -EINVAL);
@@ -2047,7 +1970,7 @@ static int snd_rme9652_capture_copy(snd_pcm_substream_t *substream, int channel,
 static int snd_rme9652_hw_silence(snd_pcm_substream_t *substream, int channel,
 				  snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 	char *channel_buf;
 
 	channel_buf = rme9652_channel_buffer_location (rme9652,
@@ -2061,7 +1984,7 @@ static int snd_rme9652_hw_silence(snd_pcm_substream_t *substream, int channel,
 static int snd_rme9652_reset(snd_pcm_substream_t *substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 	snd_pcm_substream_t *other;
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 		other = rme9652->capture_substream;
@@ -2089,7 +2012,7 @@ static int snd_rme9652_reset(snd_pcm_substream_t *substream)
 static int snd_rme9652_hw_params(snd_pcm_substream_t *substream,
 				 snd_pcm_hw_params_t *params)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 	int err;
 	pid_t this_pid;
 	pid_t other_pid;
@@ -2154,7 +2077,7 @@ static int snd_rme9652_hw_params(snd_pcm_substream_t *substream,
 static int snd_rme9652_channel_info(snd_pcm_substream_t *substream,
 				    snd_pcm_channel_info_t *info)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 	int chn;
 
 	snd_assert(info->channel < RME9652_NCHANNELS, return -EINVAL);
@@ -2197,7 +2120,7 @@ static void rme9652_silence_playback(rme9652_t *rme9652)
 static int snd_rme9652_trigger(snd_pcm_substream_t *substream,
 			       int cmd)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 	snd_pcm_substream_t *other;
 	int running;
 	spin_lock(&rme9652->lock);
@@ -2260,13 +2183,14 @@ static int snd_rme9652_trigger(snd_pcm_substream_t *substream,
 
 static int snd_rme9652_prepare(snd_pcm_substream_t *substream)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
+	unsigned long flags;
 	int result = 0;
 
-	spin_lock(&rme9652->lock);
+	spin_lock_irqsave(&rme9652->lock, flags);
 	if (!rme9652->running)
 		rme9652_reset_hw_pointer(rme9652);
-	spin_unlock(&rme9652->lock);
+	spin_unlock_irqrestore(&rme9652->lock, flags);
 	return result;
 }
 
@@ -2319,10 +2243,8 @@ static snd_pcm_hardware_t snd_rme9652_capture_subinfo =
 
 static unsigned int period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
 
-#define PERIOD_SIZES sizeof(period_sizes) / sizeof(period_sizes[0])
-
 static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = {
-	.count = PERIOD_SIZES,
+	.count = ARRAY_SIZE(period_sizes),
 	.list = period_sizes,
 	.mask = 0
 };
@@ -2386,11 +2308,10 @@ static int snd_rme9652_hw_rule_rate_channels(snd_pcm_hw_params_t *params,
 
 static int snd_rme9652_playback_open(snd_pcm_substream_t *substream)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 
 	snd_pcm_set_sync(substream);
 
@@ -2406,7 +2327,7 @@ static int snd_rme9652_playback_open(snd_pcm_substream_t *substream)
 	rme9652->playback_pid = current->pid;
 	rme9652->playback_substream = substream;
 
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 
 	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_period_sizes);
@@ -2429,15 +2350,14 @@ static int snd_rme9652_playback_open(snd_pcm_substream_t *substream)
 
 static int snd_rme9652_playback_release(snd_pcm_substream_t *substream)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 
 	rme9652->playback_pid = -1;
 	rme9652->playback_substream = NULL;
 
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 
 	rme9652->spdif_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 	snd_ctl_notify(rme9652->card, SNDRV_CTL_EVENT_MASK_VALUE |
@@ -2448,11 +2368,10 @@ static int snd_rme9652_playback_release(snd_pcm_substream_t *substream)
 
 static int snd_rme9652_capture_open(snd_pcm_substream_t *substream)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 
 	snd_pcm_set_sync(substream);
 
@@ -2468,7 +2387,7 @@ static int snd_rme9652_capture_open(snd_pcm_substream_t *substream)
 	rme9652->capture_pid = current->pid;
 	rme9652->capture_substream = substream;
 
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 
 	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
 	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, &hw_constraints_period_sizes);
@@ -2486,15 +2405,14 @@ static int snd_rme9652_capture_open(snd_pcm_substream_t *substream)
 
 static int snd_rme9652_capture_release(snd_pcm_substream_t *substream)
 {
-	rme9652_t *rme9652 = _snd_pcm_substream_chip(substream);
-	unsigned long flags;
+	rme9652_t *rme9652 = snd_pcm_substream_chip(substream);
 
-	spin_lock_irqsave(&rme9652->lock, flags);
+	spin_lock_irq(&rme9652->lock);
 
 	rme9652->capture_pid = -1;
 	rme9652->capture_substream = NULL;
 
-	spin_unlock_irqrestore(&rme9652->lock, flags);
+	spin_unlock_irq(&rme9652->lock);
 	return 0;
 }
 
@@ -2576,12 +2494,9 @@ static int __devinit snd_rme9652_create(snd_card_t *card,
 
 	spin_lock_init(&rme9652->lock);
 
+	if ((err = pci_request_regions(pci, "rme9652")) < 0)
+		return err;
 	rme9652->port = pci_resource_start(pci, 0);
-	if ((rme9652->res_port = request_mem_region(rme9652->port, RME9652_IO_EXTENT, "rme9652")) == NULL) {
-		snd_printk("unable to grab memory region 0x%lx-0x%lx\n", rme9652->port, rme9652->port + RME9652_IO_EXTENT - 1);
-		return -EBUSY;
-	}
-
 	rme9652->iobase = (unsigned long) ioremap_nocache(rme9652->port, RME9652_IO_EXTENT);
 	if (rme9652->iobase == 0) {
 		snd_printk("unable to remap region 0x%lx-0x%lx\n", rme9652->port, rme9652->port + RME9652_IO_EXTENT - 1);
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index af77bd803..bb6802714 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -44,8 +44,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("S3 SonicVibes PCI");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{S3,SonicVibes PCI}}");
+MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}");
 
 #ifndef PCI_VENDOR_ID_S3
 #define PCI_VENDOR_ID_S3             0x5333
@@ -64,22 +63,16 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for S3 SonicVibes soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for S3 SonicVibes soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable S3 SonicVibes soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(reverb, bool, boot_devs, 0444);
 MODULE_PARM_DESC(reverb, "Enable reverb (SRAM is present) for S3 SonicVibes soundcard.");
-MODULE_PARM_SYNTAX(reverb, SNDRV_ENABLED "," SNDRV_ENABLE_DESC);
 module_param_array(mge, bool, boot_devs, 0444);
 MODULE_PARM_DESC(mge, "MIC Gain Enable for S3 SonicVibes soundcard.");
-MODULE_PARM_SYNTAX(mge, SNDRV_ENABLED "," SNDRV_ENABLE_DESC);
 module_param(dmaio, uint, 0444);
 MODULE_PARM_DESC(dmaio, "DDMA i/o base address for S3 SonicVibes soundcard.");
-MODULE_PARM_SYNTAX(dmaio, "global," SNDRV_PORT_DESC);
 
 /*
  * Enhanced port direct registers
@@ -207,7 +200,6 @@ MODULE_PARM_SYNTAX(dmaio, "global," SNDRV_PORT_DESC);
  */
 
 typedef struct _snd_sonicvibes sonicvibes_t;
-#define chip_t sonicvibes_t
 
 struct _snd_sonicvibes {
 	unsigned long dma1size;
@@ -215,13 +207,9 @@ struct _snd_sonicvibes {
 	int irq;
 
 	unsigned long sb_port;
-	struct resource *res_sb_port;
 	unsigned long enh_port;
-	struct resource *res_enh_port;
 	unsigned long synth_port;
-	struct resource *res_synth_port;
 	unsigned long midi_port;
-	struct resource *res_midi_port;
 	unsigned long game_port;
 	unsigned int dmaa_port;
 	struct resource *res_dmaa;
@@ -599,7 +587,7 @@ static int snd_sonicvibes_trigger(sonicvibes_t * sonic, int what, int cmd)
 
 static irqreturn_t snd_sonicvibes_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	sonicvibes_t *sonic = snd_magic_cast(sonicvibes_t, dev_id, return IRQ_NONE);
+	sonicvibes_t *sonic = dev_id;
 	unsigned char status;
 
 	status = inb(SV_REG(sonic, STATUS));
@@ -689,7 +677,6 @@ static int snd_sonicvibes_hw_free(snd_pcm_substream_t * substream)
 
 static int snd_sonicvibes_playback_prepare(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
 	sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	unsigned char fmt = 0;
@@ -704,17 +691,16 @@ static int snd_sonicvibes_playback_prepare(snd_pcm_substream_t * substream)
 		fmt |= 2;
 	snd_sonicvibes_setfmt(sonic, ~3, fmt);
 	snd_sonicvibes_set_dac_rate(sonic, runtime->rate);
-	spin_lock_irqsave(&sonic->reg_lock, flags);
+	spin_lock_irq(&sonic->reg_lock);
 	snd_sonicvibes_setdmaa(sonic, runtime->dma_addr, size);
 	snd_sonicvibes_out1(sonic, SV_IREG_DMA_A_UPPER, count >> 8);
 	snd_sonicvibes_out1(sonic, SV_IREG_DMA_A_LOWER, count);
-	spin_unlock_irqrestore(&sonic->reg_lock, flags);
+	spin_unlock_irq(&sonic->reg_lock);
 	return 0;
 }
 
 static int snd_sonicvibes_capture_prepare(snd_pcm_substream_t * substream)
 {
-	unsigned long flags;
 	sonicvibes_t *sonic = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	unsigned char fmt = 0;
@@ -730,11 +716,11 @@ static int snd_sonicvibes_capture_prepare(snd_pcm_substream_t * substream)
 		fmt |= 0x20;
 	snd_sonicvibes_setfmt(sonic, ~0x30, fmt);
 	snd_sonicvibes_set_adc_rate(sonic, runtime->rate);
-	spin_lock_irqsave(&sonic->reg_lock, flags);
+	spin_lock_irq(&sonic->reg_lock);
 	snd_sonicvibes_setdmac(sonic, runtime->dma_addr, size);
 	snd_sonicvibes_out1(sonic, SV_IREG_DMA_C_UPPER, count >> 8);
 	snd_sonicvibes_out1(sonic, SV_IREG_DMA_C_LOWER, count);
-	spin_unlock_irqrestore(&sonic->reg_lock, flags);
+	spin_unlock_irq(&sonic->reg_lock);
 	return 0;
 }
 
@@ -864,7 +850,7 @@ static snd_pcm_ops_t snd_sonicvibes_capture_ops = {
 
 static void snd_sonicvibes_pcm_free(snd_pcm_t *pcm)
 {
-	sonicvibes_t *sonic = snd_magic_cast(sonicvibes_t, pcm->private_data, return);
+	sonicvibes_t *sonic = pcm->private_data;
 	sonic->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -922,19 +908,17 @@ static int snd_sonicvibes_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
 static int snd_sonicvibes_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	
-	spin_lock_irqsave(&sonic->reg_lock, flags);
+	spin_lock_irq(&sonic->reg_lock);
 	ucontrol->value.enumerated.item[0] = ((snd_sonicvibes_in1(sonic, SV_IREG_LEFT_ADC) & SV_RECSRC_OUT) >> 5) - 1;
 	ucontrol->value.enumerated.item[1] = ((snd_sonicvibes_in1(sonic, SV_IREG_RIGHT_ADC) & SV_RECSRC_OUT) >> 5) - 1;
-	spin_unlock_irqrestore(&sonic->reg_lock, flags);
+	spin_unlock_irq(&sonic->reg_lock);
 	return 0;
 }
 
 static int snd_sonicvibes_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned short left, right, oval1, oval2;
 	int change;
 	
@@ -943,7 +927,7 @@ static int snd_sonicvibes_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
 		return -EINVAL;
 	left = (ucontrol->value.enumerated.item[0] + 1) << 5;
 	right = (ucontrol->value.enumerated.item[1] + 1) << 5;
-	spin_lock_irqsave(&sonic->reg_lock, flags);
+	spin_lock_irq(&sonic->reg_lock);
 	oval1 = snd_sonicvibes_in1(sonic, SV_IREG_LEFT_ADC);
 	oval2 = snd_sonicvibes_in1(sonic, SV_IREG_RIGHT_ADC);
 	left = (oval1 & ~SV_RECSRC_OUT) | left;
@@ -951,7 +935,7 @@ static int snd_sonicvibes_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
 	change = left != oval1 || right != oval2;
 	snd_sonicvibes_out1(sonic, SV_IREG_LEFT_ADC, left);
 	snd_sonicvibes_out1(sonic, SV_IREG_RIGHT_ADC, right);
-	spin_unlock_irqrestore(&sonic->reg_lock, flags);
+	spin_unlock_irq(&sonic->reg_lock);
 	return change;
 }
 
@@ -975,15 +959,14 @@ static int snd_sonicvibes_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
 static int snd_sonicvibes_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int reg = kcontrol->private_value & 0xff;
 	int shift = (kcontrol->private_value >> 8) & 0xff;
 	int mask = (kcontrol->private_value >> 16) & 0xff;
 	int invert = (kcontrol->private_value >> 24) & 0xff;
 	
-	spin_lock_irqsave(&sonic->reg_lock, flags);
+	spin_lock_irq(&sonic->reg_lock);
 	ucontrol->value.integer.value[0] = (snd_sonicvibes_in1(sonic, reg)>> shift) & mask;
-	spin_unlock_irqrestore(&sonic->reg_lock, flags);
+	spin_unlock_irq(&sonic->reg_lock);
 	if (invert)
 		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
 	return 0;
@@ -992,7 +975,6 @@ static int snd_sonicvibes_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
 static int snd_sonicvibes_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int reg = kcontrol->private_value & 0xff;
 	int shift = (kcontrol->private_value >> 8) & 0xff;
 	int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -1004,12 +986,12 @@ static int snd_sonicvibes_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
 	if (invert)
 		val = mask - val;
 	val <<= shift;
-	spin_lock_irqsave(&sonic->reg_lock, flags);
+	spin_lock_irq(&sonic->reg_lock);
 	oval = snd_sonicvibes_in1(sonic, reg);
 	val = (oval & ~(mask << shift)) | val;
 	change = val != oval;
 	snd_sonicvibes_out1(sonic, reg, val);
-	spin_unlock_irqrestore(&sonic->reg_lock, flags);
+	spin_unlock_irq(&sonic->reg_lock);
 	return change;
 }
 
@@ -1033,7 +1015,6 @@ static int snd_sonicvibes_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_inf
 static int snd_sonicvibes_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int left_reg = kcontrol->private_value & 0xff;
 	int right_reg = (kcontrol->private_value >> 8) & 0xff;
 	int shift_left = (kcontrol->private_value >> 16) & 0x07;
@@ -1041,10 +1022,10 @@ static int snd_sonicvibes_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
 	int mask = (kcontrol->private_value >> 24) & 0xff;
 	int invert = (kcontrol->private_value >> 22) & 1;
 	
-	spin_lock_irqsave(&sonic->reg_lock, flags);
+	spin_lock_irq(&sonic->reg_lock);
 	ucontrol->value.integer.value[0] = (snd_sonicvibes_in1(sonic, left_reg) >> shift_left) & mask;
 	ucontrol->value.integer.value[1] = (snd_sonicvibes_in1(sonic, right_reg) >> shift_right) & mask;
-	spin_unlock_irqrestore(&sonic->reg_lock, flags);
+	spin_unlock_irq(&sonic->reg_lock);
 	if (invert) {
 		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
 		ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
@@ -1055,7 +1036,6 @@ static int snd_sonicvibes_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
 static int snd_sonicvibes_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int left_reg = kcontrol->private_value & 0xff;
 	int right_reg = (kcontrol->private_value >> 8) & 0xff;
 	int shift_left = (kcontrol->private_value >> 16) & 0x07;
@@ -1073,7 +1053,7 @@ static int snd_sonicvibes_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
 	}
 	val1 <<= shift_left;
 	val2 <<= shift_right;
-	spin_lock_irqsave(&sonic->reg_lock, flags);
+	spin_lock_irq(&sonic->reg_lock);
 	oval1 = snd_sonicvibes_in1(sonic, left_reg);
 	oval2 = snd_sonicvibes_in1(sonic, right_reg);
 	val1 = (oval1 & ~(mask << shift_left)) | val1;
@@ -1081,12 +1061,10 @@ static int snd_sonicvibes_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_val
 	change = val1 != oval1 || val2 != oval2;
 	snd_sonicvibes_out1(sonic, left_reg, val1);
 	snd_sonicvibes_out1(sonic, right_reg, val2);
-	spin_unlock_irqrestore(&sonic->reg_lock, flags);
+	spin_unlock_irq(&sonic->reg_lock);
 	return change;
 }
 
-#define SONICVIBES_CONTROLS (sizeof(snd_sonicvibes_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_sonicvibes_controls[] __devinitdata = {
 SONICVIBES_DOUBLE("Capture Volume", 0, SV_IREG_LEFT_ADC, SV_IREG_RIGHT_ADC, 0, 0, 15, 0),
 SONICVIBES_DOUBLE("Aux Playback Switch", 0, SV_IREG_LEFT_AUX1, SV_IREG_RIGHT_AUX1, 7, 7, 1, 1),
@@ -1113,7 +1091,7 @@ SONICVIBES_MUX("Capture Source", 0)
 
 static void snd_sonicvibes_master_free(snd_kcontrol_t *kcontrol)
 {
-	sonicvibes_t *sonic = snd_magic_cast(sonicvibes_t, _snd_kcontrol_chip(kcontrol), return);
+	sonicvibes_t *sonic = snd_kcontrol_chip(kcontrol);
 	sonic->master_mute = NULL;
 	sonic->master_volume = NULL;
 }
@@ -1129,7 +1107,7 @@ static int __devinit snd_sonicvibes_mixer(sonicvibes_t * sonic)
 	card = sonic->card;
 	strcpy(card->mixername, "S3 SonicVibes");
 
-	for (idx = 0; idx < SONICVIBES_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_sonicvibes_controls); idx++) {
 		if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_sonicvibes_controls[idx], sonic))) < 0)
 			return err;
 		switch (idx) {
@@ -1147,7 +1125,7 @@ static int __devinit snd_sonicvibes_mixer(sonicvibes_t * sonic)
 static void snd_sonicvibes_proc_read(snd_info_entry_t *entry, 
 				     snd_info_buffer_t * buffer)
 {
-	sonicvibes_t *sonic = snd_magic_cast(sonicvibes_t, entry->private_data, return);
+	sonicvibes_t *sonic = entry->private_data;
 	unsigned char tmp;
 
 	tmp = sonic->srs_space & 0x0f;
@@ -1197,22 +1175,8 @@ static int snd_sonicvibes_free(sonicvibes_t *sonic)
 #endif
 	pci_write_config_dword(sonic->pci, 0x40, sonic->dmaa_port);
 	pci_write_config_dword(sonic->pci, 0x48, sonic->dmac_port);
-	if (sonic->res_sb_port) {
-		release_resource(sonic->res_sb_port);
-		kfree_nocheck(sonic->res_sb_port);
-	}
-	if (sonic->res_enh_port) {
-		release_resource(sonic->res_enh_port);
-		kfree_nocheck(sonic->res_enh_port);
-	}
-	if (sonic->res_synth_port) {
-		release_resource(sonic->res_synth_port);
-		kfree_nocheck(sonic->res_synth_port);
-	}
-	if (sonic->res_midi_port) {
-		release_resource(sonic->res_midi_port);
-		kfree_nocheck(sonic->res_midi_port);
-	}
+	if (sonic->irq >= 0)
+		free_irq(sonic->irq, (void *)sonic);
 	if (sonic->res_dmaa) {
 		release_resource(sonic->res_dmaa);
 		kfree_nocheck(sonic->res_dmaa);
@@ -1221,15 +1185,14 @@ static int snd_sonicvibes_free(sonicvibes_t *sonic)
 		release_resource(sonic->res_dmac);
 		kfree_nocheck(sonic->res_dmac);
 	}
-	if (sonic->irq >= 0)
-		free_irq(sonic->irq, (void *)sonic);
-	snd_magic_kfree(sonic);
+	pci_release_regions(sonic->pci);
+	kfree(sonic);
 	return 0;
 }
 
 static int snd_sonicvibes_dev_free(snd_device_t *device)
 {
-	sonicvibes_t *sonic = snd_magic_cast(sonicvibes_t, device->device_data, return -ENXIO);
+	sonicvibes_t *sonic = device->device_data;
 	return snd_sonicvibes_free(sonic);
 }
 
@@ -1257,38 +1220,25 @@ static int __devinit snd_sonicvibes_create(snd_card_t * card,
                 return -ENXIO;
         }
 
-	sonic = snd_magic_kcalloc(sonicvibes_t, 0, GFP_KERNEL);
+	sonic = kcalloc(1, sizeof(*sonic), GFP_KERNEL);
 	if (sonic == NULL)
 		return -ENOMEM;
 	spin_lock_init(&sonic->reg_lock);
 	sonic->card = card;
 	sonic->pci = pci;
 	sonic->irq = -1;
-	sonic->sb_port = pci_resource_start(pci, 0);
-	if ((sonic->res_sb_port = request_region(sonic->sb_port, 0x10, "S3 SonicVibes SB")) == NULL) {
-		snd_printk("unable to grab SB port at 0x%lx-0x%lx\n", sonic->sb_port, sonic->sb_port + 0x10 - 1);
-		snd_sonicvibes_free(sonic);
-		return -EBUSY;
+
+	if ((err = pci_request_regions(pci, "S3 SonicVibes")) < 0) {
+		kfree(sonic);
+		return err;
 	}
+
+	sonic->sb_port = pci_resource_start(pci, 0);
 	sonic->enh_port = pci_resource_start(pci, 1);
-	if ((sonic->res_enh_port = request_region(sonic->enh_port, 0x10, "S3 SonicVibes Enhanced")) == NULL) {
-		snd_printk("unable to grab PCM port at 0x%lx-0x%lx\n", sonic->enh_port, sonic->enh_port + 0x10 - 1);
-		snd_sonicvibes_free(sonic);
-		return -EBUSY;
-	}
 	sonic->synth_port = pci_resource_start(pci, 2);
-	if ((sonic->res_synth_port = request_region(sonic->synth_port, 4, "S3 SonicVibes Synth")) == NULL) {
-		snd_printk("unable to grab synth port at 0x%lx-0x%lx\n", sonic->synth_port, sonic->synth_port + 4 - 1);
-		snd_sonicvibes_free(sonic);
-		return -EBUSY;
-	}
 	sonic->midi_port = pci_resource_start(pci, 3);
-	if ((sonic->res_midi_port = request_region(sonic->midi_port, 4, "S3 SonicVibes Midi")) == NULL) {
-		snd_printk("unable to grab MIDI port at 0x%lx-0x%lx\n", sonic->midi_port, sonic->midi_port + 4 - 1);
-		snd_sonicvibes_free(sonic);
-		return -EBUSY;
-	}
 	sonic->game_port = pci_resource_start(pci, 4);
+
 	if (request_irq(pci->irq, snd_sonicvibes_interrupt, SA_INTERRUPT|SA_SHIRQ, "S3 SonicVibes", (void *)sonic)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
 		snd_sonicvibes_free(sonic);
@@ -1396,8 +1346,6 @@ static int __devinit snd_sonicvibes_create(snd_card_t * card,
  *  MIDI section
  */
 
-#define SONICVIBES_MIDI_CONTROLS (sizeof(snd_sonicvibes_midi_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_sonicvibes_midi_controls[] __devinitdata = {
 SONICVIBES_SINGLE("SonicVibes Wave Source RAM", 0, SV_IREG_WAVE_SOURCE, 0, 1, 0),
 SONICVIBES_SINGLE("SonicVibes Wave Source RAM+ROM", 0, SV_IREG_WAVE_SOURCE, 1, 1, 0),
@@ -1408,20 +1356,20 @@ SONICVIBES_SINGLE("SonicVibes External Tx", 0, SV_IREG_MPU401, 2, 1, 0)
 
 static int snd_sonicvibes_midi_input_open(mpu401_t * mpu)
 {
-	sonicvibes_t *sonic = snd_magic_cast(sonicvibes_t, mpu->private_data, return -EIO);
+	sonicvibes_t *sonic = mpu->private_data;
 	outb(sonic->irqmask &= ~SV_MIDI_MASK, SV_REG(sonic, IRQMASK));
 	return 0;
 }
 
 static void snd_sonicvibes_midi_input_close(mpu401_t * mpu)
 {
-	sonicvibes_t *sonic = snd_magic_cast(sonicvibes_t, mpu->private_data, return);
+	sonicvibes_t *sonic = mpu->private_data;
 	outb(sonic->irqmask |= SV_MIDI_MASK, SV_REG(sonic, IRQMASK));
 }
 
 static int __devinit snd_sonicvibes_midi(sonicvibes_t * sonic, snd_rawmidi_t * rmidi)
 {
-	mpu401_t * mpu = snd_magic_cast(mpu401_t, rmidi->private_data, return -ENXIO);
+	mpu401_t * mpu = rmidi->private_data;
 	snd_card_t *card = sonic->card;
 	snd_rawmidi_str_t *dir;
 	unsigned int idx;
@@ -1431,7 +1379,7 @@ static int __devinit snd_sonicvibes_midi(sonicvibes_t * sonic, snd_rawmidi_t * r
 	mpu->open_input = snd_sonicvibes_midi_input_open;
 	mpu->close_input = snd_sonicvibes_midi_input_close;
 	dir = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
-	for (idx = 0; idx < SONICVIBES_MIDI_CONTROLS; idx++)
+	for (idx = 0; idx < ARRAY_SIZE(snd_sonicvibes_midi_controls); idx++)
 		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_sonicvibes_midi_controls[idx], sonic))) < 0)
 			return err;
 	return 0;
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index eb3a882dd..f68d3a372 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -33,8 +33,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, <audio@tridentmicro.com>");
 MODULE_DESCRIPTION("Trident 4D-WaveDX/NX & SiS SI7018");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Trident,4DWave DX},"
+MODULE_SUPPORTED_DEVICE("{{Trident,4DWave DX},"
 		"{Trident,4DWave NX},"
 		"{SiS,SI7018 PCI Audio},"
 		"{Best Union,Miss Melody 4DWave PCI},"
@@ -56,19 +55,14 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Trident 4DWave PCI soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Trident 4DWave PCI soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Trident 4DWave PCI soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(pcm_channels, int, boot_devs, 0444);
 MODULE_PARM_DESC(pcm_channels, "Number of hardware channels assigned for PCM.");
-MODULE_PARM_SYNTAX(pcm_channels, SNDRV_ENABLED ",default:32,allows:{{1,32}}");
 module_param_array(wavetable_size, int, boot_devs, 0444);
 MODULE_PARM_DESC(wavetable_size, "Maximum memory size in kB for wavetable synth.");
-MODULE_PARM_SYNTAX(wavetable_size, SNDRV_ENABLED ",default:8192,skill:advanced");
 
 static struct pci_device_id snd_trident_ids[] = {
 	{ 0x1023, 0x2000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },	/* Trident 4DWave DX PCI Audio */
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index a72dee775..46d050d2b 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -44,8 +44,6 @@
 
 #include <asm/io.h>
 
-#define chip_t trident_t
-
 static int snd_trident_pcm_mixer_build(trident_t *trident, snd_trident_voice_t * voice, snd_pcm_substream_t *substream);
 static int snd_trident_pcm_mixer_free(trident_t *trident, snd_trident_voice_t * voice, snd_pcm_substream_t *substream);
 static irqreturn_t snd_trident_interrupt(int irq, void *dev_id, struct pt_regs *regs);
@@ -119,7 +117,7 @@ static unsigned short snd_trident_codec_read(ac97_t *ac97, unsigned short reg)
 	unsigned int data = 0, treg;
 	unsigned short count = 0xffff;
 	unsigned long flags;
-	trident_t *trident = snd_magic_cast(trident_t, ac97->private_data, return -ENXIO);
+	trident_t *trident = ac97->private_data;
 
 	spin_lock_irqsave(&trident->reg_lock, flags);
 	if (trident->device == TRIDENT_DEVICE_ID_DX) {
@@ -178,7 +176,7 @@ static void snd_trident_codec_write(ac97_t *ac97, unsigned short reg, unsigned s
 	unsigned int address, data;
 	unsigned short count = 0xffff;
 	unsigned long flags;
-	trident_t *trident = snd_magic_cast(trident_t, ac97->private_data, return);
+	trident_t *trident = ac97->private_data;
 
 	data = ((unsigned long) wdata) << 16;
 
@@ -908,7 +906,7 @@ static int snd_trident_playback_prepare(snd_pcm_substream_t * substream)
 	snd_trident_voice_t *evoice = voice->extra;
 	snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[substream->number];
 
-	spin_lock(&trident->reg_lock);	
+	spin_lock_irq(&trident->reg_lock);	
 
 	/* set delta (rate) value */
 	voice->Delta = snd_trident_convert_rate(runtime->rate);
@@ -969,7 +967,7 @@ static int snd_trident_playback_prepare(snd_pcm_substream_t * substream)
 		evoice->ESO = (runtime->period_size * 2) - 1;
 	}
 
-	spin_unlock(&trident->reg_lock);
+	spin_unlock_irq(&trident->reg_lock);
 
 	return 0;
 }
@@ -1010,7 +1008,7 @@ static int snd_trident_capture_prepare(snd_pcm_substream_t * substream)
 	snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
 	unsigned int val, ESO_bytes;
 
-	spin_lock(&trident->reg_lock);
+	spin_lock_irq(&trident->reg_lock);
 
 	// Initilize the channel and set channel Mode
 	outb(0, TRID_REG(trident, LEGACY_DMAR15));
@@ -1079,7 +1077,7 @@ static int snd_trident_capture_prepare(snd_pcm_substream_t * substream)
 
 	snd_trident_write_voice_regs(trident, voice);
 
-	spin_unlock(&trident->reg_lock);
+	spin_unlock_irq(&trident->reg_lock);
 	return 0;
 }
 
@@ -1150,7 +1148,7 @@ static int snd_trident_si7018_capture_prepare(snd_pcm_substream_t * substream)
 	snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
 	snd_trident_voice_t *evoice = voice->extra;
 
-	spin_lock(&trident->reg_lock);
+	spin_lock_irq(&trident->reg_lock);
 
 	voice->LBA = runtime->dma_addr;
 	voice->Delta = snd_trident_convert_adc_rate(runtime->rate);
@@ -1199,7 +1197,7 @@ static int snd_trident_si7018_capture_prepare(snd_pcm_substream_t * substream)
 		evoice->ESO = (runtime->period_size * 2) - 1;
 	}
 	
-	spin_unlock(&trident->reg_lock);
+	spin_unlock_irq(&trident->reg_lock);
 	return 0;
 }
 
@@ -1221,7 +1219,7 @@ static int snd_trident_foldback_prepare(snd_pcm_substream_t * substream)
 	snd_trident_voice_t *voice = (snd_trident_voice_t *) runtime->private_data;
 	snd_trident_voice_t *evoice = voice->extra;
 
-	spin_lock(&trident->reg_lock);
+	spin_lock_irq(&trident->reg_lock);
 
 	/* Set channel buffer Address */
 	if (voice->memblk)
@@ -1276,7 +1274,7 @@ static int snd_trident_foldback_prepare(snd_pcm_substream_t * substream)
 		evoice->ESO = (runtime->period_size * 2) - 1;
 	}
 
-	spin_unlock(&trident->reg_lock);
+	spin_unlock_irq(&trident->reg_lock);
 	return 0;
 }
 
@@ -1367,7 +1365,7 @@ static int snd_trident_spdif_prepare(snd_pcm_substream_t * substream)
 	unsigned int RESO, LBAO;
 	unsigned int temp;
 
-	spin_lock(&trident->reg_lock);
+	spin_lock_irq(&trident->reg_lock);
 
 	if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
 
@@ -1479,7 +1477,7 @@ static int snd_trident_spdif_prepare(snd_pcm_substream_t * substream)
 		outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
 	}
 
-	spin_unlock(&trident->reg_lock);
+	spin_unlock_irq(&trident->reg_lock);
 
 	return 0;
 }
@@ -1526,7 +1524,7 @@ static int snd_trident_trigger(snd_pcm_substream_t *substream,
 	val = inl(TRID_REG(trident, T4D_STIMER)) & 0x00ffffff;
 	snd_pcm_group_for_each(pos, substream) {
 		s = snd_pcm_group_substream_entry(pos);
-		if ((trident_t *) _snd_pcm_chip(s->pcm) == trident) {
+		if ((trident_t *) snd_pcm_substream_chip(s) == trident) {
 			voice = (snd_trident_voice_t *) s->runtime->private_data;
 			evoice = voice->extra;
 			what |= 1 << (voice->number & 0x1f);
@@ -2127,21 +2125,21 @@ static snd_pcm_ops_t snd_trident_spdif_7018_ops = {
   ---------------------------------------------------------------------------*/
 static void snd_trident_pcm_free(snd_pcm_t *pcm)
 {
-	trident_t *trident = snd_magic_cast(trident_t, pcm->private_data, return);
+	trident_t *trident = pcm->private_data;
 	trident->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
 static void snd_trident_foldback_pcm_free(snd_pcm_t *pcm)
 {
-	trident_t *trident = snd_magic_cast(trident_t, pcm->private_data, return);
+	trident_t *trident = pcm->private_data;
 	trident->foldback = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
 
 static void snd_trident_spdif_pcm_free(snd_pcm_t *pcm)
 {
-	trident_t *trident = snd_magic_cast(trident_t, pcm->private_data, return);
+	trident_t *trident = pcm->private_data;
 	trident->spdif = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -2324,13 +2322,12 @@ static int snd_trident_spdif_control_get(snd_kcontrol_t * kcontrol,
 					 snd_ctl_elem_value_t * ucontrol)
 {
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned char val;
 
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	val = trident->spdif_ctrl;
 	ucontrol->value.integer.value[0] = val == kcontrol->private_value;
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return 0;
 }
 
@@ -2338,12 +2335,11 @@ static int snd_trident_spdif_control_put(snd_kcontrol_t * kcontrol,
 					 snd_ctl_elem_value_t * ucontrol)
 {
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned char val;
 	int change;
 
 	val = ucontrol->value.integer.value[0] ? (unsigned char) kcontrol->private_value : 0x00;
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	/* S/PDIF C Channel bits 0-31 : 48khz, SCMS disabled */
 	change = trident->spdif_ctrl != val;
 	trident->spdif_ctrl = val;
@@ -2362,7 +2358,7 @@ static int snd_trident_spdif_control_put(snd_kcontrol_t * kcontrol,
 			outl(temp, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
 		}
 	}
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return change;
 }
 
@@ -2393,14 +2389,13 @@ static int snd_trident_spdif_default_get(snd_kcontrol_t * kcontrol,
 					 snd_ctl_elem_value_t * ucontrol)
 {
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	ucontrol->value.iec958.status[0] = (trident->spdif_bits >> 0) & 0xff;
 	ucontrol->value.iec958.status[1] = (trident->spdif_bits >> 8) & 0xff;
 	ucontrol->value.iec958.status[2] = (trident->spdif_bits >> 16) & 0xff;
 	ucontrol->value.iec958.status[3] = (trident->spdif_bits >> 24) & 0xff;
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return 0;
 }
 
@@ -2408,7 +2403,6 @@ static int snd_trident_spdif_default_put(snd_kcontrol_t * kcontrol,
 					 snd_ctl_elem_value_t * ucontrol)
 {
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned int val;
 	int change;
 
@@ -2416,7 +2410,7 @@ static int snd_trident_spdif_default_put(snd_kcontrol_t * kcontrol,
 	      (ucontrol->value.iec958.status[1] << 8) |
 	      (ucontrol->value.iec958.status[2] << 16) |
 	      (ucontrol->value.iec958.status[3] << 24);
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	change = trident->spdif_bits != val;
 	trident->spdif_bits = val;
 	if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
@@ -2426,7 +2420,7 @@ static int snd_trident_spdif_default_put(snd_kcontrol_t * kcontrol,
 		if (trident->spdif == NULL)
 			outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
 	}
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return change;
 }
 
@@ -2488,14 +2482,13 @@ static int snd_trident_spdif_stream_get(snd_kcontrol_t * kcontrol,
 					snd_ctl_elem_value_t * ucontrol)
 {
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	ucontrol->value.iec958.status[0] = (trident->spdif_pcm_bits >> 0) & 0xff;
 	ucontrol->value.iec958.status[1] = (trident->spdif_pcm_bits >> 8) & 0xff;
 	ucontrol->value.iec958.status[2] = (trident->spdif_pcm_bits >> 16) & 0xff;
 	ucontrol->value.iec958.status[3] = (trident->spdif_pcm_bits >> 24) & 0xff;
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return 0;
 }
 
@@ -2503,7 +2496,6 @@ static int snd_trident_spdif_stream_put(snd_kcontrol_t * kcontrol,
 					snd_ctl_elem_value_t * ucontrol)
 {
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned int val;
 	int change;
 
@@ -2511,7 +2503,7 @@ static int snd_trident_spdif_stream_put(snd_kcontrol_t * kcontrol,
 	      (ucontrol->value.iec958.status[1] << 8) |
 	      (ucontrol->value.iec958.status[2] << 16) |
 	      (ucontrol->value.iec958.status[3] << 24);
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	change = trident->spdif_pcm_bits != val;
 	trident->spdif_pcm_bits = val;
 	if (trident->spdif != NULL) {
@@ -2521,7 +2513,7 @@ static int snd_trident_spdif_stream_put(snd_kcontrol_t * kcontrol,
 			outl(trident->spdif_bits, TRID_REG(trident, SI_SPDIF_CS));
 		}
 	}
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return change;
 }
 
@@ -2554,13 +2546,12 @@ static int snd_trident_ac97_control_get(snd_kcontrol_t * kcontrol,
 					snd_ctl_elem_value_t * ucontrol)
 {
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned char val;
 
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	val = trident->ac97_ctrl = inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
 	ucontrol->value.integer.value[0] = (val & (1 << kcontrol->private_value)) ? 1 : 0;
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return 0;
 }
 
@@ -2568,11 +2559,10 @@ static int snd_trident_ac97_control_put(snd_kcontrol_t * kcontrol,
 					snd_ctl_elem_value_t * ucontrol)
 {
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned char val;
 	int change = 0;
 
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	val = trident->ac97_ctrl = inl(TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
 	val &= ~(1 << kcontrol->private_value);
 	if (ucontrol->value.integer.value[0])
@@ -2580,7 +2570,7 @@ static int snd_trident_ac97_control_put(snd_kcontrol_t * kcontrol,
 	change = val != trident->ac97_ctrl;
 	trident->ac97_ctrl = val;
 	outl(trident->ac97_ctrl = val, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return change;
 }
 
@@ -2624,19 +2614,18 @@ static int snd_trident_vol_control_get(snd_kcontrol_t * kcontrol,
 static int snd_trident_vol_control_put(snd_kcontrol_t * kcontrol,
 				       snd_ctl_elem_value_t * ucontrol)
 {
-	unsigned long flags;
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
 	unsigned int val;
 	int change = 0;
 
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	val = trident->musicvol_wavevol;
 	val &= ~(0xffff << kcontrol->private_value);
 	val |= ((255 - (ucontrol->value.integer.value[0] & 0xff)) |
 	        ((255 - (ucontrol->value.integer.value[1] & 0xff)) << 8)) << kcontrol->private_value;
 	change = val != trident->musicvol_wavevol;
 	outl(trident->musicvol_wavevol = val, TRID_REG(trident, T4D_MUSICVOL_WAVEVOL));
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return change;
 }
 
@@ -2696,7 +2685,6 @@ static int snd_trident_pcm_vol_control_get(snd_kcontrol_t * kcontrol,
 static int snd_trident_pcm_vol_control_put(snd_kcontrol_t * kcontrol,
 					   snd_ctl_elem_value_t * ucontrol)
 {
-	unsigned long flags;
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
 	snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
 	unsigned int val;
@@ -2707,12 +2695,12 @@ static int snd_trident_pcm_vol_control_put(snd_kcontrol_t * kcontrol,
 	} else {
 		val = (255 - (ucontrol->value.integer.value[0] & 255)) << 2;
 	}
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	change = val != mix->vol;
 	mix->vol = val;
 	if (mix->voice != NULL)
 		snd_trident_write_vol_reg(trident, mix->voice, val);
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return change;
 }
 
@@ -2760,7 +2748,6 @@ static int snd_trident_pcm_pan_control_get(snd_kcontrol_t * kcontrol,
 static int snd_trident_pcm_pan_control_put(snd_kcontrol_t * kcontrol,
 					   snd_ctl_elem_value_t * ucontrol)
 {
-	unsigned long flags;
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
 	snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
 	unsigned char val;
@@ -2770,12 +2757,12 @@ static int snd_trident_pcm_pan_control_put(snd_kcontrol_t * kcontrol,
 		val = ucontrol->value.integer.value[0] & 0x3f;
 	else
 		val = (0x3f - (ucontrol->value.integer.value[0] & 0x3f)) | 0x40;
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	change = val != mix->pan;
 	mix->pan = val;
 	if (mix->voice != NULL)
 		snd_trident_write_pan_reg(trident, mix->voice, val);
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return change;
 }
 
@@ -2818,19 +2805,18 @@ static int snd_trident_pcm_rvol_control_get(snd_kcontrol_t * kcontrol,
 static int snd_trident_pcm_rvol_control_put(snd_kcontrol_t * kcontrol,
 					    snd_ctl_elem_value_t * ucontrol)
 {
-	unsigned long flags;
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
 	snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
 	unsigned short val;
 	int change = 0;
 
 	val = 0x7f - (ucontrol->value.integer.value[0] & 0x7f);
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	change = val != mix->rvol;
 	mix->rvol = val;
 	if (mix->voice != NULL)
 		snd_trident_write_rvol_reg(trident, mix->voice, val);
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return change;
 }
 
@@ -2873,19 +2859,18 @@ static int snd_trident_pcm_cvol_control_get(snd_kcontrol_t * kcontrol,
 static int snd_trident_pcm_cvol_control_put(snd_kcontrol_t * kcontrol,
 					    snd_ctl_elem_value_t * ucontrol)
 {
-	unsigned long flags;
 	trident_t *trident = snd_kcontrol_chip(kcontrol);
 	snd_trident_pcm_mixer_t *mix = &trident->pcm_mixer[snd_ctl_get_ioffnum(kcontrol, &ucontrol->id)];
 	unsigned short val;
 	int change = 0;
 
 	val = 0x7f - (ucontrol->value.integer.value[0] & 0x7f);
-	spin_lock_irqsave(&trident->reg_lock, flags);
+	spin_lock_irq(&trident->reg_lock);
 	change = val != mix->cvol;
 	mix->cvol = val;
 	if (mix->voice != NULL)
 		snd_trident_write_cvol_reg(trident, mix->voice, val);
-	spin_unlock_irqrestore(&trident->reg_lock, flags);
+	spin_unlock_irq(&trident->reg_lock);
 	return change;
 }
 
@@ -2961,21 +2946,21 @@ static int snd_trident_pcm_mixer_free(trident_t *trident, snd_trident_voice_t *v
 
 static int __devinit snd_trident_mixer(trident_t * trident, int pcm_spdif_device)
 {
-	ac97_bus_t _bus;
-	ac97_t _ac97;
+	ac97_template_t _ac97;
 	snd_card_t * card = trident->card;
 	snd_kcontrol_t *kctl;
 	snd_ctl_elem_value_t *uctl;
 	int idx, err, retries = 2;
+	static ac97_bus_ops_t ops = {
+		.write = snd_trident_codec_write,
+		.read = snd_trident_codec_read,
+	};
 
-	uctl = (snd_ctl_elem_value_t *)snd_kcalloc(sizeof(*uctl), GFP_KERNEL);
+	uctl = kcalloc(1, sizeof(*uctl), GFP_KERNEL);
 	if (!uctl)
 		return -ENOMEM;
 
-	memset(&_bus, 0, sizeof(_bus));
-	_bus.write = snd_trident_codec_write;
-	_bus.read = snd_trident_codec_read;
-	if ((err = snd_ac97_bus(trident->card, &_bus, &trident->ac97_bus)) < 0)
+	if ((err = snd_ac97_bus(trident->card, 0, &ops, NULL, &trident->ac97_bus)) < 0)
 		goto __out;
 
 	memset(&_ac97, 0, sizeof(_ac97));
@@ -3132,7 +3117,7 @@ static unsigned char snd_trident_gameport_read(struct gameport *gameport)
 	trident_gameport_t *gp = (trident_gameport_t *)gameport;
 	trident_t *chip;
 	snd_assert(gp, return 0);
-	chip = snd_magic_cast(trident_t, gp->chip, return 0);
+	chip = gp->chip;
 	return inb(TRID_REG(chip, GAMEPORT_LEGACY));
 }
 
@@ -3141,7 +3126,7 @@ static void snd_trident_gameport_trigger(struct gameport *gameport)
 	trident_gameport_t *gp = (trident_gameport_t *)gameport;
 	trident_t *chip;
 	snd_assert(gp, return);
-	chip = snd_magic_cast(trident_t, gp->chip, return);
+	chip = gp->chip;
 	outb(0xff, TRID_REG(chip, GAMEPORT_LEGACY));
 }
 
@@ -3152,7 +3137,7 @@ static int snd_trident_gameport_cooked_read(struct gameport *gameport, int *axes
 	int i;
 
 	snd_assert(gp, return 0);
-	chip = snd_magic_cast(trident_t, gp->chip, return 0);
+	chip = gp->chip;
 
 	*buttons = (~inb(TRID_REG(chip, GAMEPORT_LEGACY)) >> 4) & 0xf;
 
@@ -3169,7 +3154,7 @@ static int snd_trident_gameport_open(struct gameport *gameport, int mode)
 	trident_gameport_t *gp = (trident_gameport_t *)gameport;
 	trident_t *chip;
 	snd_assert(gp, return -1);
-	chip = snd_magic_cast(trident_t, gp->chip, return -1);
+	chip = gp->chip;
 
 	switch (mode) {
 		case GAMEPORT_MODE_COOKED:
@@ -3280,7 +3265,7 @@ static int snd_trident_sis_reset(trident_t *trident)
 static void snd_trident_proc_read(snd_info_entry_t *entry, 
 				  snd_info_buffer_t * buffer)
 {
-	trident_t *trident = snd_magic_cast(trident_t, entry->private_data, return);
+	trident_t *trident = entry->private_data;
 	char *s;
 
 	switch (trident->device) {
@@ -3331,7 +3316,7 @@ static void __devinit snd_trident_proc_init(trident_t * trident)
 
 static int snd_trident_dev_free(snd_device_t *device)
 {
-	trident_t *trident = snd_magic_cast(trident_t, device->device_data, return -ENXIO);
+	trident_t *trident = device->device_data;
 	return snd_trident_free(trident);
 }
 
@@ -3354,7 +3339,8 @@ static int __devinit snd_trident_tlb_alloc(trident_t *trident)
 	/* TLB array must be aligned to 16kB !!! so we allocate
 	   32kB region and correct offset when necessary */
 
-	if (snd_dma_alloc_pages(&trident->dma_dev, 2 * SNDRV_TRIDENT_MAX_PAGES * 4, &trident->tlb.buffer) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci),
+				2 * SNDRV_TRIDENT_MAX_PAGES * 4, &trident->tlb.buffer) < 0) {
 		snd_printk(KERN_ERR "trident: unable to allocate TLB buffer\n");
 		return -ENOMEM;
 	}
@@ -3367,7 +3353,8 @@ static int __devinit snd_trident_tlb_alloc(trident_t *trident)
 		return -ENOMEM;
 	}
 	/* allocate and setup silent page and initialise TLB entries */
-	if (snd_dma_alloc_pages(&trident->dma_dev, SNDRV_TRIDENT_PAGE_SIZE, &trident->tlb.silent_page) < 0) {
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci),
+				SNDRV_TRIDENT_PAGE_SIZE, &trident->tlb.silent_page) < 0) {
 		snd_printk(KERN_ERR "trident: unable to allocate silent page\n");
 		return -ENOMEM;
 	}
@@ -3553,7 +3540,7 @@ int __devinit snd_trident_create(snd_card_t * card,
 		return -ENXIO;
 	}
 	
-	trident = snd_magic_kcalloc(trident_t, 0, GFP_KERNEL);
+	trident = kcalloc(1, sizeof(*trident), GFP_KERNEL);
 	if (trident == NULL)
 		return -ENOMEM;
 	trident->device = (pci->vendor << 16) | pci->device;
@@ -3570,18 +3557,17 @@ int __devinit snd_trident_create(snd_card_t * card,
 	if (max_wavetable_size < 0 )
 		max_wavetable_size = 0;
 	trident->synth.max_size = max_wavetable_size * 1024;
-	trident->port = pci_resource_start(pci, 0);
 	trident->irq = -1;
 
 	trident->midi_port = TRID_REG(trident, T4D_MPU401_BASE);
 	pci_set_master(pci);
-	trident->port = pci_resource_start(pci, 0);
 
-	if ((trident->res_port = request_region(trident->port, 0x100, "Trident Audio")) == NULL) {
-		snd_printk("unable to grab I/O region 0x%lx-0x%lx\n", trident->port, trident->port + 0x100 - 1);
-		snd_trident_free(trident);
-		return -EBUSY;
+	if ((err = pci_request_regions(pci, "Trident Audio")) < 0) {
+		kfree(trident);
+		return err;
 	}
+	trident->port = pci_resource_start(pci, 0);
+
 	if (request_irq(pci->irq, snd_trident_interrupt, SA_INTERRUPT|SA_SHIRQ, "Trident Audio", (void *) trident)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
 		snd_trident_free(trident);
@@ -3589,10 +3575,6 @@ int __devinit snd_trident_create(snd_card_t * card,
 	}
 	trident->irq = pci->irq;
 
-	memset(&trident->dma_dev, 0, sizeof(trident->dma_dev));
-	trident->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	trident->dma_dev.dev = snd_dma_pci_data(pci);
-
 	/* allocate 16k-aligned TLB for NX cards */
 	trident->tlb.entries = NULL;
 	trident->tlb.buffer.area = NULL;
@@ -3692,18 +3674,15 @@ int snd_trident_free(trident_t *trident)
 		if (trident->tlb.memhdr)
 			snd_util_memhdr_free(trident->tlb.memhdr);
 		if (trident->tlb.silent_page.area)
-			snd_dma_free_pages(&trident->dma_dev, &trident->tlb.silent_page);
+			snd_dma_free_pages(&trident->tlb.silent_page);
 		if (trident->tlb.shadow_entries)
 			vfree(trident->tlb.shadow_entries);
-		snd_dma_free_pages(&trident->dma_dev, &trident->tlb.buffer);
+		snd_dma_free_pages(&trident->tlb.buffer);
 	}
 	if (trident->irq >= 0)
 		free_irq(trident->irq, (void *)trident);
-	if (trident->res_port) {
-		release_resource(trident->res_port);
-		kfree_nocheck(trident->res_port);
-	}
-	snd_magic_kfree(trident);
+	pci_release_regions(trident->pci);
+	kfree(trident);
 	return 0;
 }
 
@@ -3727,7 +3706,7 @@ int snd_trident_free(trident_t *trident)
 
 static irqreturn_t snd_trident_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	trident_t *trident = snd_magic_cast(trident_t, dev_id, return IRQ_NONE);
+	trident_t *trident = dev_id;
 	unsigned int audio_int, chn_int, stimer, channel, mask, tmp;
 	int delta;
 	snd_trident_voice_t *voice;
@@ -3950,7 +3929,7 @@ void snd_trident_clear_voices(trident_t * trident, unsigned short v_min, unsigne
 #ifdef CONFIG_PM
 static int snd_trident_suspend(snd_card_t *card, unsigned int state)
 {
-	trident_t *trident = snd_magic_cast(trident_t, card->pm_private_data, return -EINVAL);
+	trident_t *trident = card->pm_private_data;
 
 	trident->in_suspend = 1;
 	snd_pcm_suspend_all(trident->pcm);
@@ -3976,7 +3955,7 @@ static int snd_trident_suspend(snd_card_t *card, unsigned int state)
 
 static int snd_trident_resume(snd_card_t *card, unsigned int state)
 {
-	trident_t *trident = snd_magic_cast(trident_t, card->pm_private_data, return -EINVAL);
+	trident_t *trident = card->pm_private_data;
 
 	pci_enable_device(trident->pci);
 	if (pci_set_dma_mask(trident->pci, 0x3fffffff) < 0 ||
diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c
index 3c79110b5..6fd58f180 100644
--- a/sound/pci/trident/trident_memory.c
+++ b/sound/pci/trident/trident_memory.c
@@ -25,6 +25,7 @@
 
 #include <sound/driver.h>
 #include <asm/io.h>
+#include <linux/pci.h>
 #include <linux/time.h>
 #include <sound/core.h>
 #include <sound/trident.h>
@@ -189,7 +190,7 @@ snd_trident_alloc_sg_pages(trident_t *trident, snd_pcm_substream_t *substream)
 	snd_util_memblk_t *blk;
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int idx, page;
-	struct snd_sg_buf *sgbuf = runtime->dma_private;
+	struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
 
 	snd_assert(runtime->dma_bytes > 0 && runtime->dma_bytes <= SNDRV_TRIDENT_MAX_PAGES * SNDRV_TRIDENT_PAGE_SIZE, return NULL);
 	hdr = trident->tlb.memhdr;
@@ -274,7 +275,7 @@ snd_trident_alloc_pages(trident_t *trident, snd_pcm_substream_t *substream)
 {
 	snd_assert(trident != NULL, return NULL);
 	snd_assert(substream != NULL, return NULL);
-	if (substream->dma_device.type == SNDRV_DMA_TYPE_DEV_SG)
+	if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV_SG)
 		return snd_trident_alloc_sg_pages(trident, substream);
 	else
 		return snd_trident_alloc_cont_pages(trident, substream);
@@ -367,10 +368,12 @@ static void clear_tlb(trident_t *trident, int page)
 	set_silent_tlb(trident, page);
 	if (ptr) {
 		struct snd_dma_buffer dmab;
+		dmab.dev.type = SNDRV_DMA_TYPE_DEV;
+		dmab.dev.dev = snd_dma_pci_data(trident->pci);
 		dmab.area = ptr;
 		dmab.addr = addr;
 		dmab.bytes = ALIGN_PAGE_SIZE;
-		snd_dma_free_pages(&trident->dma_dev, &dmab);
+		snd_dma_free_pages(&dmab);
 	}
 }
 
@@ -412,10 +415,11 @@ static int synth_alloc_pages(trident_t *hw, snd_util_memblk_t *blk)
 	 * fortunately Trident page size and kernel PAGE_SIZE is identical!
 	 */
 	for (page = first_page; page <= last_page; page++) {
-		if (snd_dma_alloc_pages(&hw->dma_dev, ALIGN_PAGE_SIZE, &dmab) < 0)
+		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(hw->pci),
+					ALIGN_PAGE_SIZE, &dmab) < 0)
 			goto __fail;
 		if (! is_valid_page(dmab.addr)) {
-			snd_dma_free_pages(&hw->dma_dev, &dmab);
+			snd_dma_free_pages(&dmab);
 			goto __fail;
 		}
 		set_tlb_bus(hw, page, (unsigned long)dmab.area, dmab.addr);
diff --git a/sound/pci/trident/trident_synth.c b/sound/pci/trident/trident_synth.c
index 8f9797d79..72d36b11b 100644
--- a/sound/pci/trident/trident_synth.c
+++ b/sound/pci/trident/trident_synth.c
@@ -23,6 +23,7 @@
 #include <asm/io.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/pci.h>
 #include <sound/core.h>
 #include <sound/trident.h>
 #include <sound/seq_device.h>
@@ -506,7 +507,7 @@ static void sample_private1(trident_t * trident, snd_trident_voice_t * voice, un
 static int snd_trident_simple_put_sample(void *private_data, simple_instrument_t * instr,
 					 char __user *data, long len, int atomic)
 {
-	trident_t *trident = snd_magic_cast(trident_t, private_data, return -ENXIO);
+	trident_t *trident = private_data;
 	int size = instr->size;
 	int shift = 0;
 
@@ -540,12 +541,12 @@ static int snd_trident_simple_put_sample(void *private_data, simple_instrument_t
 		instr->address.memory = memblk->offset;
 	} else {
 		struct snd_dma_buffer dmab;
-
-		if (snd_dma_alloc_pages(&trident->dma_dev, size, &dmab) < 0)
+		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci),
+					size, &dmab) < 0)
 			return -ENOMEM;
 
 		if (copy_from_user(dmab.area, data, size)) {
-			snd_dma_free_pages(&trident->dma_dev, &dmab);
+			snd_dma_free_pages(&dmab);
 			return -EFAULT;
 		}
 		instr->address.ptr = dmab.area;
@@ -559,7 +560,7 @@ static int snd_trident_simple_put_sample(void *private_data, simple_instrument_t
 static int snd_trident_simple_get_sample(void *private_data, simple_instrument_t * instr,
 					 char __user *data, long len, int atomic)
 {
-	//trident_t *trident = snd_magic_cast(trident_t, private_data, return -ENXIO);
+	//trident_t *trident = private_data;
 	int size = instr->size;
 	int shift = 0;
 
@@ -580,9 +581,14 @@ static int snd_trident_simple_get_sample(void *private_data, simple_instrument_t
 static int snd_trident_simple_remove_sample(void *private_data, simple_instrument_t * instr,
 					    int atomic)
 {
-	trident_t *trident = snd_magic_cast(trident_t, private_data, return -ENXIO);
+	trident_t *trident = private_data;
 	int size = instr->size;
 
+	if (instr->format & SIMPLE_WAVE_16BIT)
+		size <<= 1;
+	if (instr->format & SIMPLE_WAVE_STEREO)
+		size <<= 1;
+
 	if (trident->tlb.entries) {
 		snd_util_memblk_t *memblk = (snd_util_memblk_t*)instr->address.ptr;
 		if (memblk)
@@ -590,14 +596,15 @@ static int snd_trident_simple_remove_sample(void *private_data, simple_instrumen
 		else
 			return -EFAULT;
 	} else {
-		kfree(instr->address.ptr);
+		struct snd_dma_buffer dmab;
+		dmab.dev.type = SNDRV_DMA_TYPE_DEV;
+		dmab.dev.dev = snd_dma_pci_data(trident->pci);
+		dmab.area = instr->address.ptr;
+		dmab.addr = instr->address.memory;
+		dmab.bytes = size;
+		snd_dma_free_pages(&dmab);
 	}
 
-	if (instr->format & SIMPLE_WAVE_16BIT)
-		size <<= 1;
-	if (instr->format & SIMPLE_WAVE_STEREO)
-		size <<= 1;
-
 	trident->synth.current_size -= size;
 	if (trident->synth.current_size < 0)	/* shouldn't need this check... */
 		trident->synth.current_size = 0;
@@ -838,7 +845,7 @@ static void snd_trident_synth_instr_notify(void *private_data,
 					   int what)
 {
 	int idx;
-	trident_t *trident = snd_magic_cast(trident_t, private_data, return);
+	trident_t *trident = private_data;
 	snd_trident_voice_t *pvoice;
 	unsigned long flags;
 
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 67e5edd5b..fb549ea9e 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -67,8 +67,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("VIA VT82xx audio");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{VIA,VT82C686A/B/C,pci},{VIA,VT8233A/C,8235}}");
+MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C,pci},{VIA,VT8233A/C,8235}}");
 
 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
 #define SUPPORT_JOYSTICK 1
@@ -88,30 +87,22 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for VIA 82xx bridge.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for VIA 82xx bridge.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable audio part of VIA 82xx bridge.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port. (VT82C686x only)");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT_DESC);
 #ifdef SUPPORT_JOYSTICK
 module_param_array(joystick, bool, boot_devs, 0444);
 MODULE_PARM_DESC(joystick, "Enable joystick. (VT82C686x only)");
-MODULE_PARM_SYNTAX(joystick, SNDRV_ENABLE_DESC "," SNDRV_BOOLEAN_FALSE_DESC);
 #endif
 module_param_array(ac97_clock, int, boot_devs, 0444);
 MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz).");
-MODULE_PARM_SYNTAX(ac97_clock, SNDRV_ENABLED ",default:48000");
 module_param_array(ac97_quirk, int, boot_devs, 0444);
 MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
-MODULE_PARM_SYNTAX(ac97_quirk, SNDRV_ENABLED ",allows:{{-1,4}},dialog:list,default:-1");
 module_param_array(dxs_support, int, boot_devs, 0444);
 MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA)");
-MODULE_PARM_SYNTAX(dxs_support, SNDRV_ENABLED ",allows:{{0,4}},dialog:list");
 
 
 /* pci ids */
@@ -318,7 +309,6 @@ DEFINE_VIA_REGSET(CAPTURE_8233, 0x60);
 
 typedef struct _snd_via82xx via82xx_t;
 typedef struct via_dev viadev_t;
-#define chip_t via82xx_t
 
 /*
  * pcm stream
@@ -362,7 +352,6 @@ struct _snd_via82xx {
 	int irq;
 
 	unsigned long port;
-	struct resource *res_port;
 	struct resource *mpu_res;
 	int chip_type;
 	unsigned char revision;
@@ -375,7 +364,6 @@ struct _snd_via82xx {
 	unsigned char spdif_ctrl_saved;
 	unsigned char capture_src_saved[2];
 	unsigned int mpu_port_saved;
-	u32 pci_state[16];
 #endif
 
 	unsigned char playback_volume[4][2]; /* for VIA8233/C/8235; default = 0 */
@@ -405,8 +393,6 @@ struct _snd_via82xx {
 	spinlock_t ac97_lock;
 	snd_info_entry_t *proc_entry;
 
-	struct snd_dma_device dma_dev;
-
 #ifdef SUPPORT_JOYSTICK
 	struct gameport gameport;
 	struct resource *res_joystick;
@@ -441,7 +427,9 @@ static int build_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
 		/* the start of each lists must be aligned to 8 bytes,
 		 * but the kernel pages are much bigger, so we don't care
 		 */
-		if (snd_dma_alloc_pages(&chip->dma_dev, PAGE_ALIGN(VIA_TABLE_SIZE * 2 * 8), &dev->table) < 0)
+		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+					PAGE_ALIGN(VIA_TABLE_SIZE * 2 * 8),
+					&dev->table) < 0)
 			return -ENOMEM;
 	}
 	if (! dev->idx_table) {
@@ -497,9 +485,8 @@ static int build_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
 static int clean_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
 			   struct pci_dev *pci)
 {
-	via82xx_t *chip = snd_pcm_substream_chip(substream);
 	if (dev->table.area) {
-		snd_dma_free_pages(&chip->dma_dev, &dev->table);
+		snd_dma_free_pages(&dev->table);
 		dev->table.area = NULL;
 	}
 	if (dev->idx_table) {
@@ -556,7 +543,7 @@ static int snd_via82xx_codec_valid(via82xx_t *chip, int secondary)
  
 static void snd_via82xx_codec_wait(ac97_t *ac97)
 {
-	via82xx_t *chip = snd_magic_cast(via82xx_t, ac97->private_data, return);
+	via82xx_t *chip = ac97->private_data;
 	int err;
 	err = snd_via82xx_codec_ready(chip, ac97->num);
 	/* here we need to wait fairly for long time.. */
@@ -568,7 +555,7 @@ static void snd_via82xx_codec_write(ac97_t *ac97,
 				    unsigned short reg,
 				    unsigned short val)
 {
-	via82xx_t *chip = snd_magic_cast(via82xx_t, ac97->private_data, return);
+	via82xx_t *chip = ac97->private_data;
 	unsigned int xval;
 	
 	xval = !ac97->num ? VIA_REG_AC97_CODEC_ID_PRIMARY : VIA_REG_AC97_CODEC_ID_SECONDARY;
@@ -583,7 +570,7 @@ static void snd_via82xx_codec_write(ac97_t *ac97,
 
 static unsigned short snd_via82xx_codec_read(ac97_t *ac97, unsigned short reg)
 {
-	via82xx_t *chip = snd_magic_cast(via82xx_t, ac97->private_data, return ~0);
+	via82xx_t *chip = ac97->private_data;
 	unsigned int xval, val = 0xffff;
 	int again = 0;
 
@@ -632,11 +619,10 @@ static void snd_via82xx_channel_reset(via82xx_t *chip, viadev_t *viadev)
 
 static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	via82xx_t *chip = snd_magic_cast(via82xx_t, dev_id, return IRQ_NONE);
+	via82xx_t *chip = dev_id;
 	unsigned int status;
 	unsigned int i;
 
-	spin_lock(&chip->reg_lock);
 #if 0
 	/* FIXME: does it work on via823x? */
 	if (chip->chip_type != TYPE_VIA686)
@@ -644,7 +630,6 @@ static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id, struct pt_regs *
 #endif
 	status = inl(VIAREG(chip, SGD_SHADOW));
 	if (! (status & chip->intr_mask)) {
-		spin_unlock(&chip->reg_lock);
 		if (chip->rmidi)
 			/* check mpu401 interrupt */
 			return snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);
@@ -653,6 +638,7 @@ static irqreturn_t snd_via82xx_interrupt(int irq, void *dev_id, struct pt_regs *
 // _skip_sgd:
 
 	/* check status for each stream */
+	spin_lock(&chip->reg_lock);
 	for (i = 0; i < chip->num_devs; i++) {
 		viadev_t *viadev = &chip->devs[i];
 		unsigned char c_status = inb(VIADEV_REG(viadev, OFFSET_STATUS));
@@ -720,6 +706,10 @@ static int snd_via82xx_pcm_trigger(snd_pcm_substream_t * substream, int cmd)
 /*
  * calculate the linear position at the given sg-buffer index and the rest count
  */
+
+#define check_invalid_pos(viadev,pos) \
+	((pos) < viadev->lastpos && ((pos) >= viadev->bufsize2 || viadev->lastpos < viadev->bufsize2))
+
 static inline unsigned int calc_linear_pos(viadev_t *viadev, unsigned int idx, unsigned int count)
 {
 	unsigned int size, res;
@@ -728,17 +718,24 @@ static inline unsigned int calc_linear_pos(viadev_t *viadev, unsigned int idx, u
 	res = viadev->idx_table[idx].offset + size - count;
 
 	/* check the validity of the calculated position */
-	if (size < count || (res < viadev->lastpos && (res >= viadev->bufsize2 || viadev->lastpos < viadev->bufsize2))) {
+	if (size < count) {
+		snd_printd(KERN_ERR "invalid via82xx_cur_ptr (size = %d, count = %d)\n", (int)size, (int)count);
+		res = viadev->lastpos;
+	} else if (check_invalid_pos(viadev, res)) {
 #ifdef POINTER_DEBUG
 		printk("fail: idx = %i/%i, lastpos = 0x%x, bufsize2 = 0x%x, offsize = 0x%x, size = 0x%x, count = 0x%x\n", idx, viadev->tbl_entries, viadev->lastpos, viadev->bufsize2, viadev->idx_table[idx].offset, viadev->idx_table[idx].size, count);
 #endif
-		/* count register returns full size when end of buffer is reached */
-		if (size != count) {
+		if (count && size < count) {
 			snd_printd(KERN_ERR "invalid via82xx_cur_ptr, using last valid pointer\n");
 			res = viadev->lastpos;
 		} else {
-			res = viadev->idx_table[idx].offset + size;
-			if (res < viadev->lastpos && (res >= viadev->bufsize2 || viadev->lastpos < viadev->bufsize2)) {
+			if (! count)
+				/* bogus count 0 on the DMA boundary? */
+				res = viadev->idx_table[idx].offset;
+			else
+				/* count register returns full size when end of buffer is reached */
+				res = viadev->idx_table[idx].offset + size;
+			if (check_invalid_pos(viadev, res)) {
 				snd_printd(KERN_ERR "invalid via82xx_cur_ptr (2), using last valid pointer\n");
 				res = viadev->lastpos;
 			}
@@ -904,7 +901,7 @@ static int via_lock_rate(struct via_rate_lock *rec, int rate)
 {
 	int changed = 0;
 
-	spin_lock(&rec->lock);
+	spin_lock_irq(&rec->lock);
 	if (rec->rate != rate) {
 		if (rec->rate && rec->used > 1) /* already set */
 			changed = -EINVAL;
@@ -913,7 +910,7 @@ static int via_lock_rate(struct via_rate_lock *rec, int rate)
 			changed = 1;
 		}
 	}
-	spin_unlock(&rec->lock);
+	spin_unlock_irq(&rec->lock);
 	return changed;
 }
 
@@ -1035,6 +1032,7 @@ static snd_pcm_hardware_t snd_via82xx_hw =
 	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
 				 SNDRV_PCM_INFO_MMAP_VALID |
+				 SNDRV_PCM_INFO_RESUME |
 				 SNDRV_PCM_INFO_PAUSE),
 	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
 	.rates =		SNDRV_PCM_RATE_48000,
@@ -1058,32 +1056,18 @@ static int snd_via82xx_pcm_open(via82xx_t *chip, viadev_t *viadev, snd_pcm_subst
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int err;
-	unsigned long flags;
 	struct via_rate_lock *ratep;
-	struct ratetbl {
-		int rate;
-		unsigned int bit;
-	} ratebits[] = {
-		{8000, SNDRV_PCM_RATE_8000},
-		{11025, SNDRV_PCM_RATE_11025},
-		{16000, SNDRV_PCM_RATE_16000},
-		{22050, SNDRV_PCM_RATE_22050},
-		{32000, SNDRV_PCM_RATE_32000},
-		{44100, SNDRV_PCM_RATE_44100},
-		{48000, SNDRV_PCM_RATE_48000},
-	};
-	int i;
 
 	runtime->hw = snd_via82xx_hw;
 	
 	/* set the hw rate condition */
 	ratep = &chip->rates[viadev->direction];
-	spin_lock_irqsave(&ratep->lock, flags);
+	spin_lock_irq(&ratep->lock);
 	ratep->used++;
-	if (chip->spdif_on) {
-		runtime->hw.rates = SNDRV_PCM_RATE_32000|SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000;
-		runtime->hw.rate_min = 32000;
-		runtime->hw.rate_max = 48000;
+	if (chip->spdif_on && viadev->reg_offset == 0x30) {
+		/* DXS#3 and spdif is on */
+		runtime->hw.rates = chip->ac97->rates[AC97_RATES_SPDIF];
+		snd_pcm_limit_hw_rates(runtime);
 	} else if (chip->dxs_fixed && viadev->reg_offset < 0x40) {
 		/* fixed DXS playback rate */
 		runtime->hw.rates = SNDRV_PCM_RATE_48000;
@@ -1091,30 +1075,13 @@ static int snd_via82xx_pcm_open(via82xx_t *chip, viadev_t *viadev, snd_pcm_subst
 	} else if (! ratep->rate) {
 		int idx = viadev->direction ? AC97_RATES_ADC : AC97_RATES_FRONT_DAC;
 		runtime->hw.rates = chip->ac97->rates[idx];
-		for (i = 0; i < (int)ARRAY_SIZE(ratebits); i++) {
-			if (runtime->hw.rates & ratebits[i].bit) {
-				runtime->hw.rate_min = ratebits[i].rate;
-				break;
-			}
-		}
-		for (i = ARRAY_SIZE(ratebits) - 1; i >= 0; i--) {
-			if (runtime->hw.rates & ratebits[i].bit) {
-				runtime->hw.rate_max = ratebits[i].rate;
-				break;
-			}
-		}
+		snd_pcm_limit_hw_rates(runtime);
 	} else {
 		/* a fixed rate */
 		runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
-		for (i = 0; i < (int)ARRAY_SIZE(ratebits); i++) {
-			if (ratep->rate == ratebits[i].rate) {
-				runtime->hw.rates = ratebits[i].bit;
-				break;
-			}
-		}
 		runtime->hw.rate_max = runtime->hw.rate_min = ratep->rate;
 	}
-	spin_unlock_irqrestore(&ratep->lock, flags);
+	spin_unlock_irq(&ratep->lock);
 
 	/* we may remove following constaint when we modify table entries
 	   in interrupt */
@@ -1188,16 +1155,15 @@ static int snd_via82xx_pcm_close(snd_pcm_substream_t * substream)
 {
 	via82xx_t *chip = snd_pcm_substream_chip(substream);
 	viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
-	unsigned long flags;
 	struct via_rate_lock *ratep;
 
 	/* release the rate lock */
 	ratep = &chip->rates[viadev->direction];
-	spin_lock_irqsave(&ratep->lock, flags);
+	spin_lock_irq(&ratep->lock);
 	ratep->used--;
 	if (! ratep->used)
 		ratep->rate = 0;
-	spin_unlock_irqrestore(&ratep->lock, flags);
+	spin_unlock_irq(&ratep->lock);
 
 	viadev->substream = NULL;
 	return 0;
@@ -1363,6 +1329,10 @@ static int __devinit snd_via8233a_pcm_new(via82xx_t *chip)
 							 snd_dma_pci_data(chip->pci), 64*1024, 128*1024)) < 0)
 		return err;
 
+	/* SPDIF supported? */
+	if (! ac97_can_spdif(chip->ac97))
+		return 0;
+
 	/* PCM #1:  DXS3 playback (for spdif) */
 	err = snd_pcm_new(chip->card, chip->card->shortname, 1, 1, 0, &pcm);
 	if (err < 0)
@@ -1446,17 +1416,16 @@ static int snd_via8233_capture_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem
 {
 	via82xx_t *chip = snd_kcontrol_chip(kcontrol);
 	unsigned long port = chip->port + (kcontrol->id.index ? (VIA_REG_CAPTURE_CHANNEL + 0x10) : VIA_REG_CAPTURE_CHANNEL);
-	unsigned long flags;
 	u8 val, oval;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	oval = inb(port);
 	val = oval & ~VIA_REG_CAPTURE_CHANNEL_MIC;
 	if (ucontrol->value.enumerated.item[0])
 		val |= VIA_REG_CAPTURE_CHANNEL_MIC;
 	if (val != oval)
 		outb(val, port);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return val != oval;
 }
 
@@ -1567,13 +1536,13 @@ static snd_kcontrol_new_t snd_via8233_dxs_volume_control __devinitdata = {
 
 static void snd_via82xx_mixer_free_ac97_bus(ac97_bus_t *bus)
 {
-	via82xx_t *chip = snd_magic_cast(via82xx_t, bus->private_data, return);
+	via82xx_t *chip = bus->private_data;
 	chip->ac97_bus = NULL;
 }
 
 static void snd_via82xx_mixer_free_ac97(ac97_t *ac97)
 {
-	via82xx_t *chip = snd_magic_cast(via82xx_t, ac97->private_data, return);
+	via82xx_t *chip = ac97->private_data;
 	chip->ac97 = NULL;
 }
 
@@ -1584,6 +1553,18 @@ static struct ac97_quirk ac97_quirks[] = {
 		.name = "ASRock K7VT2",
 		.type = AC97_TUNE_HP_ONLY
 	},
+	{
+		.vendor = 0x1019,
+		.device = 0x0a81,
+		.name = "ECS K7VTA3",
+		.type = AC97_TUNE_HP_ONLY
+	},
+	{
+		.vendor = 0x1019,
+		.device = 0x0a85,
+		.name = "ECS L7VMM2",
+		.type = AC97_TUNE_HP_ONLY
+	},
 	{
 		.vendor = 0x1849,
 		.device = 0x3059,
@@ -1613,19 +1594,18 @@ static struct ac97_quirk ac97_quirks[] = {
 
 static int __devinit snd_via82xx_mixer_new(via82xx_t *chip, int ac97_quirk)
 {
-	ac97_bus_t bus;
-	ac97_t ac97;
+	ac97_template_t ac97;
 	int err;
+	static ac97_bus_ops_t ops = {
+		.write = snd_via82xx_codec_write,
+		.read = snd_via82xx_codec_read,
+		.wait = snd_via82xx_codec_wait,
+	};
 
-	memset(&bus, 0, sizeof(bus));
-	bus.write = snd_via82xx_codec_write;
-	bus.read = snd_via82xx_codec_read;
-	bus.wait = snd_via82xx_codec_wait;
-	bus.private_data = chip;
-	bus.private_free = snd_via82xx_mixer_free_ac97_bus;
-	bus.clock = chip->ac97_clock;
-	if ((err = snd_ac97_bus(chip->card, &bus, &chip->ac97_bus)) < 0)
+	if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0)
 		return err;
+	chip->ac97_bus->private_free = snd_via82xx_mixer_free_ac97_bus;
+	chip->ac97_bus->clock = chip->ac97_clock;
 
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = chip;
@@ -1653,6 +1633,8 @@ static int snd_via8233_init_misc(via82xx_t *chip, int dev)
 	int i, err, caps;
 	unsigned char val;
 
+	pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE,
+			      chip->old_legacy & ~(VIA_FUNC_ENABLE_SB|VIA_FUNC_ENABLE_FM));
 	caps = chip->chip_type == TYPE_VIA8233A ? 1 : 2;
 	for (i = 0; i < caps; i++) {
 		snd_via8233_capture_source.index = i;
@@ -1660,9 +1642,11 @@ static int snd_via8233_init_misc(via82xx_t *chip, int dev)
 		if (err < 0)
 			return err;
 	}
-	err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs3_spdif_control, chip));
-	if (err < 0)
-		return err;
+	if (ac97_can_spdif(chip->ac97)) {
+		err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs3_spdif_control, chip));
+		if (err < 0)
+			return err;
+	}
 	if (chip->chip_type != TYPE_VIA8233A) {
 		err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs_volume_control, chip));
 		if (err < 0)
@@ -1672,6 +1656,7 @@ static int snd_via8233_init_misc(via82xx_t *chip, int dev)
 	/* select spdif data slot 10/11 */
 	pci_read_config_byte(chip->pci, VIA8233_SPDIF_CTRL, &val);
 	val = (val & ~VIA8233_SPDIF_SLOT_MASK) | VIA8233_SPDIF_SLOT_1011;
+	val &= ~VIA8233_SPDIF_DX3; /* SPDIF off as default */
 	pci_write_config_byte(chip->pci, VIA8233_SPDIF_CTRL, val);
 
 	return 0;
@@ -1686,6 +1671,7 @@ static int snd_via686_init_misc(via82xx_t *chip, int dev)
 	legacy_cfg = chip->old_legacy_cfg;
 	legacy |= VIA_FUNC_MIDI_IRQMASK;	/* FIXME: correct? (disable MIDI) */
 	legacy &= ~VIA_FUNC_ENABLE_GAME;	/* disable joystick */
+	legacy &= ~(VIA_FUNC_ENABLE_SB|VIA_FUNC_ENABLE_FM);	/* diable SB & FM */
 	if (chip->revision >= VIA_REV_686_H) {
 		rev_h = 1;
 		if (mpu_port[dev] >= 0x200) {	/* force MIDI */
@@ -1766,7 +1752,7 @@ static int snd_via686_init_misc(via82xx_t *chip, int dev)
  */
 static void snd_via82xx_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
 {
-	via82xx_t *chip = snd_magic_cast(via82xx_t, entry->private_data, return);
+	via82xx_t *chip = entry->private_data;
 	int i;
 	
 	snd_iprintf(buffer, "%s\n\n", chip->card->longname);
@@ -1903,7 +1889,7 @@ static int __devinit snd_via82xx_chip_init(via82xx_t *chip)
  */
 static int snd_via82xx_suspend(snd_card_t *card, unsigned int state)
 {
-	via82xx_t *chip = snd_magic_cast(via82xx_t, card->pm_private_data, return -EINVAL);
+	via82xx_t *chip = card->pm_private_data;
 	int i;
 
 	for (i = 0; i < 2; i++)
@@ -1921,7 +1907,6 @@ static int snd_via82xx_suspend(snd_card_t *card, unsigned int state)
 		chip->capture_src_saved[1] = inb(chip->port + VIA_REG_CAPTURE_CHANNEL + 0x10);
 	}
 
-	pci_save_state(chip->pci, chip->pci_state);
 	pci_set_power_state(chip->pci, 3);
 	pci_disable_device(chip->pci);
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
@@ -1930,11 +1915,10 @@ static int snd_via82xx_suspend(snd_card_t *card, unsigned int state)
 
 static int snd_via82xx_resume(snd_card_t *card, unsigned int state)
 {
-	via82xx_t *chip = snd_magic_cast(via82xx_t, card->pm_private_data, return -EINVAL);
+	via82xx_t *chip = card->pm_private_data;
 	int idx, i;
 
 	pci_enable_device(chip->pci);
-	pci_restore_state(chip->pci, chip->pci_state);
 	pci_set_power_state(chip->pci, 0);
 
 	snd_via82xx_chip_init(chip);
@@ -1976,16 +1960,13 @@ static int snd_via82xx_free(via82xx_t *chip)
 		snd_via82xx_channel_reset(chip, &chip->devs[i]);
 	synchronize_irq(chip->irq);
       __end_hw:
+	if (chip->irq >= 0)
+		free_irq(chip->irq, (void *)chip);
 	if (chip->mpu_res) {
 		release_resource(chip->mpu_res);
 		kfree_nocheck(chip->mpu_res);
 	}
-	if (chip->res_port) {
-		release_resource(chip->res_port);
-		kfree_nocheck(chip->res_port);
-	}
-	if (chip->irq >= 0)
-		free_irq(chip->irq, (void *)chip);
+	pci_release_regions(chip->pci);
 	if (chip->chip_type == TYPE_VIA686) {
 #ifdef SUPPORT_JOYSTICK
 		if (chip->res_joystick) {
@@ -1997,13 +1978,13 @@ static int snd_via82xx_free(via82xx_t *chip)
 		pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, chip->old_legacy);
 		pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, chip->old_legacy_cfg);
 	}
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_via82xx_dev_free(snd_device_t *device)
 {
-	via82xx_t *chip = snd_magic_cast(via82xx_t, device->device_data, return -ENXIO);
+	via82xx_t *chip = device->device_data;
 	return snd_via82xx_free(chip);
 }
 
@@ -2023,7 +2004,7 @@ static int __devinit snd_via82xx_create(snd_card_t * card,
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	if ((chip = snd_magic_kcalloc(via82xx_t, 0, GFP_KERNEL)) == NULL)
+	if ((chip = kcalloc(1, sizeof(*chip), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 
 	chip->chip_type = chip_type;
@@ -2037,19 +2018,14 @@ static int __devinit snd_via82xx_create(snd_card_t * card,
 	chip->pci = pci;
 	chip->irq = -1;
 
-	memset(&chip->dma_dev, 0, sizeof(chip->dma_dev));
-	chip->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	chip->dma_dev.dev = snd_dma_pci_data(pci);
-
 	pci_read_config_byte(pci, VIA_FUNC_ENABLE, &chip->old_legacy);
 	pci_read_config_byte(pci, VIA_PNP_CONTROL, &chip->old_legacy_cfg);
 
-	chip->port = pci_resource_start(pci, 0);
-	if ((chip->res_port = request_region(chip->port, 256, card->driver)) == NULL) {
-		snd_printk("unable to grab ports 0x%lx-0x%lx\n", chip->port, chip->port + 256 - 1);
-		snd_via82xx_free(chip);
-		return -EBUSY;
+	if ((err = pci_request_regions(pci, card->driver)) < 0) {
+		kfree(chip);
+		return err;
 	}
+	chip->port = pci_resource_start(pci, 0);
 	if (request_irq(pci->irq, snd_via82xx_interrupt, SA_INTERRUPT|SA_SHIRQ,
 			card->driver, (void *)chip)) {
 		snd_printk("unable to grab IRQ %d\n", pci->irq);
@@ -2111,9 +2087,12 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
 		{ .vendor = 0x1005, .device = 0x4710, .action = VIA_DXS_ENABLE }, /* Avance Logic Mobo */
 		{ .vendor = 0x1019, .device = 0x0996, .action = VIA_DXS_48K },
 		{ .vendor = 0x1019, .device = 0x0a81, .action = VIA_DXS_NO_VRA }, /* ECS K7VTA3 v8.0 */
+		{ .vendor = 0x1019, .device = 0x0a85, .action = VIA_DXS_NO_VRA }, /* ECS L7VMM2 */
+		{ .vendor = 0x1025, .device = 0x0033, .action = VIA_DXS_NO_VRA }, /* Acer Inspire 1353LM */
 		{ .vendor = 0x1043, .device = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/
 		{ .vendor = 0x1043, .device = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */
 		{ .vendor = 0x1043, .device = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/ 
+		{ .vendor = 0x1071, .device = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */
 		{ .vendor = 0x10cf, .device = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */
 		{ .vendor = 0x1106, .device = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */
 		{ .vendor = 0x1106, .device = 0xaa01, .action = VIA_DXS_NO_VRA }, /* EPIA MII */
@@ -2126,6 +2105,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
 		{ .vendor = 0x1462, .device = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */
 		{ .vendor = 0x1462, .device = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */
 		{ .vendor = 0x1584, .device = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */
+		{ .vendor = 0x1584, .device = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */
 		{ .vendor = 0x161f, .device = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */
 		{ .vendor = 0x161f, .device = 0x2032, .action = VIA_DXS_48K }, /* m680x machines */
 		{ .vendor = 0x1631, .device = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index 9f4ef46f7..4dd658d42 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -28,15 +28,12 @@
 #include <sound/initval.h>
 #include "vx222.h"
 
-#define chip_t vx_core_t
-
 #define CARD_NAME "VX222"
 
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("Digigram VX222 V2/Mic");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Digigram," CARD_NAME "}}");
+MODULE_SUPPORTED_DEVICE("{{Digigram," CARD_NAME "}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -47,19 +44,14 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Digigram " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Digigram " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Digigram " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(mic, bool, boot_devs, 0444);
 MODULE_PARM_DESC(mic, "Enable Microphone.");
-MODULE_PARM_SYNTAX(mic, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 module_param_array(ibl, int, boot_devs, 0444);
 MODULE_PARM_DESC(ibl, "Capture IBL size.");
-MODULE_PARM_SYNTAX(ibl, SNDRV_ENABLED);
 
 /*
  */
@@ -119,24 +111,19 @@ static struct snd_vx_hardware vx222_mic_hw = {
  */
 static int snd_vx222_free(vx_core_t *chip)
 {
-	int i;
 	struct snd_vx222 *vx = (struct snd_vx222 *)chip;
 
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void*)chip);
-	for (i = 0; i < 2; i++) {
-		if (vx->port_res[i]) {
-			release_resource(vx->port_res[i]);
-			kfree_nocheck(vx->port_res[i]);
-		}
-	}
-	snd_magic_kfree(chip);
+	if (vx->port[0])
+		pci_release_regions(vx->pci);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_vx222_dev_free(snd_device_t *device)
 {
-	vx_core_t *chip = snd_magic_cast(vx_core_t, device->device_data, return -ENXIO);
+	vx_core_t *chip = device->device_data;
 	return snd_vx222_free(chip);
 }
 
@@ -164,21 +151,14 @@ static int __devinit snd_vx222_create(snd_card_t *card, struct pci_dev *pci,
 	if (! chip)
 		return -ENOMEM;
 	vx = (struct snd_vx222 *)chip;
+	vx->pci = pci;
 
-	for (i = 0; i < 2; i++) {
-		if (!(pci_resource_flags(pci, i + 1) & IORESOURCE_IO)) {
-			snd_printk(KERN_ERR "invalid i/o resource %d\n", i + 1);
-			snd_vx222_free(chip);
-			return -ENOMEM;
-		}
-		vx->port[i] = pci_resource_start(pci, i + 1);
-		if ((vx->port_res[i] = request_region(vx->port[i], 0x60,
-						      CARD_NAME)) == NULL) {
-			snd_printk(KERN_ERR "unable to grab port 0x%lx\n", vx->port[i]);
-			snd_vx222_free(chip);
-			return -EBUSY;
-		}
+	if ((err = pci_request_regions(pci, CARD_NAME)) < 0) {
+		snd_vx222_free(chip);
+		return err;
 	}
+	for (i = 0; i < 2; i++)
+		vx->port[i] = pci_resource_start(pci, i + 1);
 
 	if (request_irq(pci->irq, snd_vx_irq_handler, SA_INTERRUPT|SA_SHIRQ,
 			CARD_NAME, (void *) chip)) {
diff --git a/sound/pci/vx222/vx222.h b/sound/pci/vx222/vx222.h
index b30c9d306..18478ae12 100644
--- a/sound/pci/vx222/vx222.h
+++ b/sound/pci/vx222/vx222.h
@@ -28,8 +28,8 @@ struct snd_vx222 {
 	vx_core_t core;
 
 	/* h/w config; for PLX and for DSP */
+	struct pci_dev *pci;
 	unsigned long port[2];
-	struct resource *port_res[2];
 
 	unsigned int regCDSP;	/* current CDSP register */
 	unsigned int regCFG;	/* current CFG register */
diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c
index c9dfb2bc1..4c669cf19 100644
--- a/sound/pci/vx222/vx222_ops.c
+++ b/sound/pci/vx222/vx222_ops.c
@@ -27,8 +27,6 @@
 #include <asm/io.h>
 #include "vx222.h"
 
-#define chip_t vx_core_t
-
 
 static int vx2_reg_offset[VX_REG_MAX] = {
 	[VX_ICR]    = 0x00,
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index 8fbfc24b4..4440e1df6 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -33,8 +33,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Yamaha DS-XG PCI");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Yamaha,YMF724},"
+MODULE_SUPPORTED_DEVICE("{{Yamaha,YMF724},"
 		"{Yamaha,YMF724F},"
 		"{Yamaha,YMF740},"
 		"{Yamaha,YMF740C},"
@@ -54,27 +53,20 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for the Yamaha DS-XG PCI soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for the Yamaha DS-XG PCI soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Yamaha DS-XG soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(mpu_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 Port.");
-MODULE_PARM_SYNTAX(mpu_port, SNDRV_ENABLED);
 module_param_array(fm_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(fm_port, "FM OPL-3 Port.");
-MODULE_PARM_SYNTAX(fm_port, SNDRV_ENABLED);
 #ifdef SUPPORT_JOYSTICK
 module_param_array(joystick_port, long, boot_devs, 0444);
 MODULE_PARM_DESC(joystick_port, "Joystick port address");
-MODULE_PARM_SYNTAX(joystick_port, SNDRV_ENABLED);
 #endif
 module_param_array(rear_switch, bool, boot_devs, 0444);
 MODULE_PARM_DESC(rear_switch, "Enable shared rear/line-in switch");
-MODULE_PARM_SYNTAX(rear_switch, SNDRV_ENABLED "," SNDRV_BOOLEAN_FALSE_DESC);
 
 static struct pci_device_id snd_ymfpci_ids[] = {
         { 0x1073, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },   /* YMF724 */
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 9d0aa2624..160316951 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -42,8 +42,6 @@
 
 #include <asm/io.h>
 
-#define chip_t ymfpci_t
-
 /*
  *  constants
  */
@@ -102,7 +100,7 @@ static int snd_ymfpci_codec_ready(ymfpci_t *chip, int secondary)
 
 static void snd_ymfpci_codec_write(ac97_t *ac97, u16 reg, u16 val)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, ac97->private_data, return);
+	ymfpci_t *chip = ac97->private_data;
 	u32 cmd;
 	
 	snd_ymfpci_codec_ready(chip, 0);
@@ -112,7 +110,7 @@ static void snd_ymfpci_codec_write(ac97_t *ac97, u16 reg, u16 val)
 
 static u16 snd_ymfpci_codec_read(ac97_t *ac97, u16 reg)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, ac97->private_data, return -ENXIO);
+	ymfpci_t *chip = ac97->private_data;
 
 	if (snd_ymfpci_codec_ready(chip, 0))
 		return ~0;
@@ -330,7 +328,7 @@ static void snd_ymfpci_pcm_interrupt(ymfpci_t *chip, ymfpci_voice_t *voice)
 static void snd_ymfpci_pcm_capture_interrupt(snd_pcm_substream_t *substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return);
+	ymfpci_pcm_t *ypcm = runtime->private_data;
 	ymfpci_t *chip = ypcm->chip;
 	u32 pos, delta;
 	
@@ -358,7 +356,7 @@ static int snd_ymfpci_playback_trigger(snd_pcm_substream_t * substream,
 				       int cmd)
 {
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
-	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, substream->runtime->private_data, return -ENXIO);
+	ymfpci_pcm_t *ypcm = substream->runtime->private_data;
 	int result = 0;
 
 	spin_lock(&chip->reg_lock);
@@ -395,7 +393,7 @@ static int snd_ymfpci_capture_trigger(snd_pcm_substream_t * substream,
 				      int cmd)
 {
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
-	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, substream->runtime->private_data, return -ENXIO);
+	ymfpci_pcm_t *ypcm = substream->runtime->private_data;
 	int result = 0;
 	u32 tmp;
 
@@ -541,7 +539,8 @@ static void snd_ymfpci_pcm_init_voice(ymfpci_voice_t *voice, int stereo,
 
 static int __devinit snd_ymfpci_ac3_init(ymfpci_t *chip)
 {
-	if (snd_dma_alloc_pages(&chip->dma_dev, 4096, &chip->ac3_tmp_base) < 0)
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+				4096, &chip->ac3_tmp_base) < 0)
 		return -ENOMEM;
 
 	chip->bank_effect[3][0]->base =
@@ -568,7 +567,7 @@ static int snd_ymfpci_ac3_done(ymfpci_t *chip)
 	spin_unlock_irq(&chip->reg_lock);
 	// snd_ymfpci_irq_wait(chip);
 	if (chip->ac3_tmp_base.area) {
-		snd_dma_free_pages(&chip->dma_dev, &chip->ac3_tmp_base);
+		snd_dma_free_pages(&chip->ac3_tmp_base);
 		chip->ac3_tmp_base.area = NULL;
 	}
 	return 0;
@@ -578,7 +577,7 @@ static int snd_ymfpci_playback_hw_params(snd_pcm_substream_t * substream,
 					 snd_pcm_hw_params_t * hw_params)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return -ENXIO);
+	ymfpci_pcm_t *ypcm = runtime->private_data;
 	int err;
 
 	if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
@@ -596,7 +595,7 @@ static int snd_ymfpci_playback_hw_free(snd_pcm_substream_t * substream)
 	
 	if (runtime->private_data == NULL)
 		return 0;
-	ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return -ENXIO);
+	ypcm = runtime->private_data;
 
 	/* wait, until the PCI operations are not finished */
 	snd_ymfpci_irq_wait(chip);
@@ -616,7 +615,7 @@ static int snd_ymfpci_playback_prepare(snd_pcm_substream_t * substream)
 {
 	// ymfpci_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return -ENXIO);
+	ymfpci_pcm_t *ypcm = runtime->private_data;
 	unsigned int nvoice;
 
 	ypcm->period_size = runtime->period_size;
@@ -654,7 +653,7 @@ static int snd_ymfpci_capture_prepare(snd_pcm_substream_t * substream)
 {
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return -ENXIO);
+	ymfpci_pcm_t *ypcm = runtime->private_data;
 	snd_ymfpci_capture_bank_t * bank;
 	int nbank;
 	u32 rate, format;
@@ -698,7 +697,7 @@ static snd_pcm_uframes_t snd_ymfpci_playback_pointer(snd_pcm_substream_t * subst
 {
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return -ENXIO);
+	ymfpci_pcm_t *ypcm = runtime->private_data;
 	ymfpci_voice_t *voice = ypcm->voices[0];
 
 	if (!(ypcm->running && voice))
@@ -710,7 +709,7 @@ static snd_pcm_uframes_t snd_ymfpci_capture_pointer(snd_pcm_substream_t * substr
 {
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return -ENXIO);
+	ymfpci_pcm_t *ypcm = runtime->private_data;
 
 	if (!ypcm->running)
 		return 0;
@@ -736,7 +735,7 @@ static void snd_ymfpci_irq_wait(ymfpci_t *chip)
 
 static irqreturn_t snd_ymfpci_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, dev_id, return IRQ_NONE);
+	ymfpci_t *chip = dev_id;
 	u32 status, nvoice, mode;
 	ymfpci_voice_t *voice;
 
@@ -830,10 +829,10 @@ static snd_pcm_hardware_t snd_ymfpci_capture =
 
 static void snd_ymfpci_pcm_free_substream(snd_pcm_runtime_t *runtime)
 {
-	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return);
+	ymfpci_pcm_t *ypcm = runtime->private_data;
 	
 	if (ypcm)
-		snd_magic_kfree(ypcm);
+		kfree(ypcm);
 }
 
 static int snd_ymfpci_playback_open_1(snd_pcm_substream_t * substream)
@@ -842,7 +841,7 @@ static int snd_ymfpci_playback_open_1(snd_pcm_substream_t * substream)
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	ymfpci_pcm_t *ypcm;
 
-	ypcm = snd_magic_kcalloc(ymfpci_pcm_t, 0, GFP_KERNEL);
+	ypcm = kcalloc(1, sizeof(*ypcm), GFP_KERNEL);
 	if (ypcm == NULL)
 		return -ENOMEM;
 	ypcm->chip = chip;
@@ -886,20 +885,19 @@ static int snd_ymfpci_playback_open(snd_pcm_substream_t * substream)
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	ymfpci_pcm_t *ypcm;
-	unsigned long flags;
 	int err;
 	
 	if ((err = snd_ymfpci_playback_open_1(substream)) < 0)
 		return err;
-	ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return 0);
+	ypcm = runtime->private_data;
 	ypcm->output_front = 1;
 	ypcm->output_rear = chip->mode_dup4ch ? 1 : 0;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	if (ypcm->output_rear) {
 		ymfpci_open_extension(chip);
 		chip->rear_opened++;
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -908,22 +906,21 @@ static int snd_ymfpci_playback_spdif_open(snd_pcm_substream_t * substream)
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	ymfpci_pcm_t *ypcm;
-	unsigned long flags;
 	int err;
 	
 	if ((err = snd_ymfpci_playback_open_1(substream)) < 0)
 		return err;
-	ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return 0);
+	ypcm = runtime->private_data;
 	ypcm->output_front = 0;
 	ypcm->output_rear = 1;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTCTRL,
 			  snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) | 2);
 	ymfpci_open_extension(chip);
 	chip->spdif_pcm_bits = chip->spdif_bits;
 	snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_pcm_bits);
 	chip->spdif_opened++;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 
 	chip->spdif_pcm_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 	snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE |
@@ -936,18 +933,17 @@ static int snd_ymfpci_playback_4ch_open(snd_pcm_substream_t * substream)
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	ymfpci_pcm_t *ypcm;
-	unsigned long flags;
 	int err;
 	
 	if ((err = snd_ymfpci_playback_open_1(substream)) < 0)
 		return err;
-	ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return 0);
+	ypcm = runtime->private_data;
 	ypcm->output_front = 0;
 	ypcm->output_rear = 1;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	ymfpci_open_extension(chip);
 	chip->rear_opened++;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -958,7 +954,7 @@ static int snd_ymfpci_capture_open(snd_pcm_substream_t * substream,
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	ymfpci_pcm_t *ypcm;
 
-	ypcm = snd_magic_kcalloc(ymfpci_pcm_t, 0, GFP_KERNEL);
+	ypcm = kcalloc(1, sizeof(*ypcm), GFP_KERNEL);
 	if (ypcm == NULL)
 		return -ENOMEM;
 	ypcm->chip = chip;
@@ -993,30 +989,28 @@ static int snd_ymfpci_playback_close_1(snd_pcm_substream_t * substream)
 static int snd_ymfpci_playback_close(snd_pcm_substream_t * substream)
 {
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
-	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, substream->runtime->private_data, return -ENXIO);
-	unsigned long flags;
+	ymfpci_pcm_t *ypcm = substream->runtime->private_data;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	if (ypcm->output_rear && chip->rear_opened > 0) {
 		chip->rear_opened--;
 		ymfpci_close_extension(chip);
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return snd_ymfpci_playback_close_1(substream);
 }
 
 static int snd_ymfpci_playback_spdif_close(snd_pcm_substream_t * substream)
 {
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	chip->spdif_opened = 0;
 	ymfpci_close_extension(chip);
 	snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTCTRL,
 			  snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) & ~2);
 	snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_bits);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	chip->spdif_pcm_ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 	snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE |
 		       SNDRV_CTL_EVENT_MASK_INFO, &chip->spdif_pcm_ctl->id);
@@ -1026,14 +1020,13 @@ static int snd_ymfpci_playback_spdif_close(snd_pcm_substream_t * substream)
 static int snd_ymfpci_playback_4ch_close(snd_pcm_substream_t * substream)
 {
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	if (chip->rear_opened > 0) {
 		chip->rear_opened--;
 		ymfpci_close_extension(chip);
 	}
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return snd_ymfpci_playback_close_1(substream);
 }
 
@@ -1041,7 +1034,7 @@ static int snd_ymfpci_capture_close(snd_pcm_substream_t * substream)
 {
 	ymfpci_t *chip = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, return -ENXIO);
+	ymfpci_pcm_t *ypcm = runtime->private_data;
 
 	if (ypcm != NULL) {
 		chip->capture_substream[ypcm->capture_bank_number] = NULL;
@@ -1074,7 +1067,7 @@ static snd_pcm_ops_t snd_ymfpci_capture_rec_ops = {
 
 static void snd_ymfpci_pcm_free(snd_pcm_t *pcm)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, pcm->private_data, return);
+	ymfpci_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1120,7 +1113,7 @@ static snd_pcm_ops_t snd_ymfpci_capture_ac97_ops = {
 
 static void snd_ymfpci_pcm2_free(snd_pcm_t *pcm)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, pcm->private_data, return);
+	ymfpci_t *chip = pcm->private_data;
 	chip->pcm2 = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1166,7 +1159,7 @@ static snd_pcm_ops_t snd_ymfpci_playback_spdif_ops = {
 
 static void snd_ymfpci_pcm_spdif_free(snd_pcm_t *pcm)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, pcm->private_data, return);
+	ymfpci_t *chip = pcm->private_data;
 	chip->pcm_spdif = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1211,7 +1204,7 @@ static snd_pcm_ops_t snd_ymfpci_playback_4ch_ops = {
 
 static void snd_ymfpci_pcm_4ch_free(snd_pcm_t *pcm)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, pcm->private_data, return);
+	ymfpci_t *chip = pcm->private_data;
 	chip->pcm_4ch = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1254,12 +1247,11 @@ static int snd_ymfpci_spdif_default_get(snd_kcontrol_t * kcontrol,
 					snd_ctl_elem_value_t * ucontrol)
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	ucontrol->value.iec958.status[0] = (chip->spdif_bits >> 0) & 0xff;
 	ucontrol->value.iec958.status[1] = (chip->spdif_bits >> 8) & 0xff;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -1267,18 +1259,17 @@ static int snd_ymfpci_spdif_default_put(snd_kcontrol_t * kcontrol,
 					 snd_ctl_elem_value_t * ucontrol)
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned int val;
 	int change;
 
 	val = ((ucontrol->value.iec958.status[0] & 0x3e) << 0) |
 	      (ucontrol->value.iec958.status[1] << 8);
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	change = chip->spdif_bits != val;
 	chip->spdif_bits = val;
 	if ((snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) & 1) && chip->pcm_spdif == NULL)
 		snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_bits);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return change;
 }
 
@@ -1302,12 +1293,11 @@ static int snd_ymfpci_spdif_mask_get(snd_kcontrol_t * kcontrol,
 				      snd_ctl_elem_value_t * ucontrol)
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	ucontrol->value.iec958.status[0] = 0x3e;
 	ucontrol->value.iec958.status[1] = 0xff;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -1331,12 +1321,11 @@ static int snd_ymfpci_spdif_stream_get(snd_kcontrol_t * kcontrol,
 					snd_ctl_elem_value_t * ucontrol)
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	ucontrol->value.iec958.status[0] = (chip->spdif_pcm_bits >> 0) & 0xff;
 	ucontrol->value.iec958.status[1] = (chip->spdif_pcm_bits >> 8) & 0xff;
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return 0;
 }
 
@@ -1344,18 +1333,17 @@ static int snd_ymfpci_spdif_stream_put(snd_kcontrol_t * kcontrol,
 					snd_ctl_elem_value_t * ucontrol)
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned int val;
 	int change;
 
 	val = ((ucontrol->value.iec958.status[0] & 0x3e) << 0) |
 	      (ucontrol->value.iec958.status[1] << 8);
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	change = chip->spdif_pcm_bits != val;
 	chip->spdif_pcm_bits = val;
 	if ((snd_ymfpci_readw(chip, YDSXGR_SPDIFOUTCTRL) & 2))
 		snd_ymfpci_writew(chip, YDSXGR_SPDIFOUTSTATUS, chip->spdif_pcm_bits);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return change;
 }
 
@@ -1385,12 +1373,11 @@ static int snd_ymfpci_drec_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_in
 static int snd_ymfpci_drec_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	u16 reg;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	reg = snd_ymfpci_readw(chip, YDSXGR_GLOBALCTRL);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	if (!(reg & 0x100))
 		value->value.enumerated.item[0] = 0;
 	else
@@ -1401,17 +1388,16 @@ static int snd_ymfpci_drec_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
 static int snd_ymfpci_drec_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *value)
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	u16 reg, old_reg;
 
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	old_reg = snd_ymfpci_readw(chip, YDSXGR_GLOBALCTRL);
 	if (value->value.enumerated.item[0] == 0)
 		reg = old_reg & ~0x100;
 	else
 		reg = (old_reg & ~0x300) | 0x100 | ((value->value.enumerated.item[0] == 2) << 9);
 	snd_ymfpci_writew(chip, YDSXGR_GLOBALCTRL, reg);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return reg != old_reg;
 }
 
@@ -1470,7 +1456,6 @@ static int snd_ymfpci_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 static int snd_ymfpci_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	int reg = kcontrol->private_value;
 	unsigned int shift = 0, mask = 1, invert = 0;
 	int change;
@@ -1485,12 +1470,12 @@ static int snd_ymfpci_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 	if (invert)
 		val = mask - val;
 	val <<= shift;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	oval = snd_ymfpci_readl(chip, reg);
 	val = (oval & ~(mask << shift)) | val;
 	change = val != oval;
 	snd_ymfpci_writel(chip, reg, val);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return change;
 }
 
@@ -1517,16 +1502,15 @@ static int snd_ymfpci_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
 static int snd_ymfpci_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned int reg = kcontrol->private_value;
 	unsigned int shift_left = 0, shift_right = 16, mask = 16383, invert = 0;
 	unsigned int val;
 	
 	if (reg < 0x80 || reg >= 0xc0)
 		return -EINVAL;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	val = snd_ymfpci_readl(chip, reg);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	ucontrol->value.integer.value[0] = (val >> shift_left) & mask;
 	ucontrol->value.integer.value[1] = (val >> shift_right) & mask;
 	if (invert) {
@@ -1539,7 +1523,6 @@ static int snd_ymfpci_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 static int snd_ymfpci_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
 	unsigned int reg = kcontrol->private_value;
 	unsigned int shift_left = 0, shift_right = 16, mask = 16383, invert = 0;
 	int change;
@@ -1555,12 +1538,12 @@ static int snd_ymfpci_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 	}
 	val1 <<= shift_left;
 	val2 <<= shift_right;
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	oval = snd_ymfpci_readl(chip, reg);
 	val1 = (oval & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2;
 	change = val1 != oval;
 	snd_ymfpci_writel(chip, reg, val1);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 	return change;
 }
 
@@ -1594,8 +1577,6 @@ static int snd_ymfpci_put_dup4ch(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
 }
 
 
-#define YMFPCI_CONTROLS (sizeof(snd_ymfpci_controls)/sizeof(snd_kcontrol_new_t))
-
 static snd_kcontrol_new_t snd_ymfpci_controls[] __devinitdata = {
 YMFPCI_DOUBLE("Wave Playback Volume", 0, YDSXGR_NATIVEDACOUTVOL),
 YMFPCI_DOUBLE("Wave Capture Volume", 0, YDSXGR_NATIVEDACLOOPVOL),
@@ -1709,31 +1690,30 @@ static snd_kcontrol_new_t snd_ymfpci_rear_shared __devinitdata = {
 
 static void snd_ymfpci_mixer_free_ac97_bus(ac97_bus_t *bus)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, bus->private_data, return);
+	ymfpci_t *chip = bus->private_data;
 	chip->ac97_bus = NULL;
 }
 
 static void snd_ymfpci_mixer_free_ac97(ac97_t *ac97)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, ac97->private_data, return);
+	ymfpci_t *chip = ac97->private_data;
 	chip->ac97 = NULL;
 }
 
 int __devinit snd_ymfpci_mixer(ymfpci_t *chip, int rear_switch)
 {
-	ac97_bus_t bus;
-	ac97_t ac97;
+	ac97_template_t ac97;
 	snd_kcontrol_t *kctl;
 	unsigned int idx;
 	int err;
+	static ac97_bus_ops_t ops = {
+		.write = snd_ymfpci_codec_write,
+		.read = snd_ymfpci_codec_read,
+	};
 
-	memset(&bus, 0, sizeof(bus));
-	bus.write = snd_ymfpci_codec_write;
-	bus.read = snd_ymfpci_codec_read;
-	bus.private_data = chip;
-	bus.private_free = snd_ymfpci_mixer_free_ac97_bus;
-	if ((err = snd_ac97_bus(chip->card, &bus, &chip->ac97_bus)) < 0)
+	if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0)
 		return err;
+	chip->ac97_bus->private_free = snd_ymfpci_mixer_free_ac97_bus;
 
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = chip;
@@ -1741,7 +1721,7 @@ int __devinit snd_ymfpci_mixer(ymfpci_t *chip, int rear_switch)
 	if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0)
 		return err;
 
-	for (idx = 0; idx < YMFPCI_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_ymfpci_controls); idx++) {
 		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_ymfpci_controls[idx], chip))) < 0)
 			return err;
 	}
@@ -1854,7 +1834,7 @@ int __devinit snd_ymfpci_timer(ymfpci_t *chip, int device)
 static void snd_ymfpci_proc_read(snd_info_entry_t *entry, 
 				 snd_info_buffer_t * buffer)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, entry->private_data, return);
+	ymfpci_t *chip = entry->private_data;
 	int i;
 	
 	snd_iprintf(buffer, "YMFPCI\n\n");
@@ -1975,7 +1955,8 @@ static int __devinit snd_ymfpci_memalloc(ymfpci_t *chip)
 	       chip->work_size;
 	/* work_ptr must be aligned to 256 bytes, but it's already
 	   covered with the kernel page allocation mechanism */
-	if (snd_dma_alloc_pages(&chip->dma_dev, size, &chip->work_ptr) < 0) 
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+				size, &chip->work_ptr) < 0) 
 		return -ENOMEM;
 	ptr = chip->work_ptr.area;
 	ptr_addr = chip->work_ptr.addr;
@@ -2106,7 +2087,7 @@ static int snd_ymfpci_free(ymfpci_t *chip)
 	if (chip->reg_area_virt)
 		iounmap((void *)chip->reg_area_virt);
 	if (chip->work_ptr.area)
-		snd_dma_free_pages(&chip->dma_dev, &chip->work_ptr);
+		snd_dma_free_pages(&chip->work_ptr);
 	
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void *)chip);
@@ -2117,13 +2098,13 @@ static int snd_ymfpci_free(ymfpci_t *chip)
 
 	pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl);
 	
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_ymfpci_dev_free(snd_device_t *device)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, device->device_data, return -ENXIO);
+	ymfpci_t *chip = device->device_data;
 	return snd_ymfpci_free(chip);
 }
 
@@ -2159,7 +2140,7 @@ static int saved_regs_index[] = {
 
 static int snd_ymfpci_suspend(snd_card_t *card, unsigned int state)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, card->pm_private_data, return -EINVAL);
+	ymfpci_t *chip = card->pm_private_data;
 	unsigned int i;
 	
 	snd_pcm_suspend_all(chip->pcm);
@@ -2178,7 +2159,7 @@ static int snd_ymfpci_suspend(snd_card_t *card, unsigned int state)
 
 static int snd_ymfpci_resume(snd_card_t *card, unsigned int state)
 {
-	ymfpci_t *chip = snd_magic_cast(ymfpci_t, card->pm_private_data, return -EINVAL);
+	ymfpci_t *chip = card->pm_private_data;
 	unsigned int i;
 
 	pci_enable_device(chip->pci);
@@ -2195,11 +2176,10 @@ static int snd_ymfpci_resume(snd_card_t *card, unsigned int state)
 
 	/* start hw again */
 	if (chip->start_count > 0) {
-		unsigned long flags;
-		spin_lock_irqsave(&chip->reg_lock, flags);
+		spin_lock_irq(&chip->reg_lock);
 		snd_ymfpci_writel(chip, YDSXGR_MODE, chip->saved_ydsxgr_mode);
 		chip->active_bank = snd_ymfpci_readl(chip, YDSXGR_CTRLSELECT);
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		spin_unlock_irq(&chip->reg_lock);
 	}
 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
 	return 0;
@@ -2223,7 +2203,7 @@ int __devinit snd_ymfpci_create(snd_card_t * card,
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 
-	chip = snd_magic_kcalloc(ymfpci_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	chip->old_legacy_ctrl = old_legacy_ctrl;
@@ -2252,10 +2232,6 @@ int __devinit snd_ymfpci_create(snd_card_t * card,
 	}
 	chip->irq = pci->irq;
 
-	memset(&chip->dma_dev, 0, sizeof(chip->dma_dev));
-	chip->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	chip->dma_dev.dev = snd_dma_pci_data(pci);
-
 	snd_ymfpci_aclink_reset(pci);
 	if (snd_ymfpci_codec_ready(chip, 0) < 0) {
 		snd_ymfpci_free(chip);
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index 7b3db54a2..1eb9e54fe 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -37,8 +37,7 @@
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Sound Core " CARD_NAME);
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Sound Core," CARD_NAME "}}");
+MODULE_SUPPORTED_DEVICE("{{Sound Core," CARD_NAME "}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -49,13 +48,10 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param(irq_mask, int, 0444);
 MODULE_PARM_DESC(irq_mask, "IRQ bitmask for " CARD_NAME " soundcard.");
 module_param_array(irq_list, int, boot_devs, 0444);
@@ -103,13 +99,13 @@ static int snd_pdacf_free(pdacf_t *pdacf)
 	card_list[pdacf->index] = NULL;
 	pdacf->card = NULL;
 
-	snd_magic_kfree(pdacf);
+	kfree(pdacf);
 	return 0;
 }
 
 static int snd_pdacf_dev_free(snd_device_t *device)
 {
-	pdacf_t *chip = snd_magic_cast(pdacf_t, device->device_data, return -ENXIO);
+	pdacf_t *chip = device->device_data;
 	return snd_pdacf_free(chip);
 }
 
@@ -152,7 +148,7 @@ static dev_link_t *snd_pdacf_attach(void)
 		return NULL;
 
 	if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, pdacf, &ops) < 0) {
-		snd_magic_kfree(pdacf);
+		kfree(pdacf);
 		snd_card_free(card);
 		return NULL;
 	}
@@ -258,7 +254,7 @@ static int snd_pdacf_assign_resources(pdacf_t *pdacf, int port, int irq)
  */
 static void snd_pdacf_detach(dev_link_t *link)
 {
-	pdacf_t *chip = snd_magic_cast(pdacf_t, link->priv, return);
+	pdacf_t *chip = link->priv;
 
 	snd_printdd(KERN_DEBUG "pdacf_detach called\n");
 	/* Remove the interface data from the linked list */
@@ -297,7 +293,7 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 static void pdacf_config(dev_link_t *link)
 {
 	client_handle_t handle = link->handle;
-	pdacf_t *pdacf = snd_magic_cast(pdacf_t, link->priv, return);
+	pdacf_t *pdacf = link->priv;
 	tuple_t tuple;
 	cisparse_t parse;
 	config_info_t conf;
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
index 7b615fd16..9e194fb07 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
@@ -30,7 +30,7 @@
  */
 unsigned char pdacf_ak4117_read(void *private_data, unsigned char reg)
 {
-	pdacf_t *chip = snd_magic_cast(pdacf_t, private_data, return 0);
+	pdacf_t *chip = private_data;
 	unsigned long timeout;
 	unsigned long flags;
 	unsigned char res;
@@ -62,7 +62,7 @@ unsigned char pdacf_ak4117_read(void *private_data, unsigned char reg)
 
 void pdacf_ak4117_write(void *private_data, unsigned char reg, unsigned char val)
 {
-	pdacf_t *chip = snd_magic_cast(pdacf_t, private_data, return);
+	pdacf_t *chip = private_data;
 	unsigned long timeout;
 	unsigned long flags;
 
@@ -130,7 +130,7 @@ void pdacf_reinit(pdacf_t *chip, int resume)
 static void pdacf_proc_read(snd_info_entry_t * entry,
                             snd_info_buffer_t * buffer)
 {
-	pdacf_t *chip = snd_magic_cast(pdacf_t, entry->private_data, return);
+	pdacf_t *chip = entry->private_data;
 	u16 tmp;
 
 	snd_iprintf(buffer, "PDAudioCF\n\n");
@@ -151,7 +151,7 @@ pdacf_t *snd_pdacf_create(snd_card_t *card)
 {
 	pdacf_t *chip;
 
-	chip = snd_magic_kcalloc(pdacf_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return NULL;
 	chip->card = card;
@@ -257,7 +257,7 @@ void snd_pdacf_powerdown(pdacf_t *chip)
 
 int snd_pdacf_suspend(snd_card_t *card, unsigned int state)
 {
-	pdacf_t *chip = snd_magic_cast(pdacf_t, card->pm_private_data, return -EINVAL);
+	pdacf_t *chip = card->pm_private_data;
 	u16 val;
 	
 	snd_pcm_suspend_all(chip->pcm);
@@ -278,7 +278,7 @@ static inline int check_signal(pdacf_t *chip)
 
 int snd_pdacf_resume(snd_card_t *card, unsigned int state)
 {
-	pdacf_t *chip = snd_magic_cast(pdacf_t, card->pm_private_data, return -EINVAL);
+	pdacf_t *chip = card->pm_private_data;
 	int timeout = 40;
 
 	pdacf_reinit(chip, 1);
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
index 14443f07d..255b63444 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_irq.c
@@ -28,7 +28,7 @@
  */
 irqreturn_t pdacf_interrupt(int irq, void *dev, struct pt_regs *regs)
 {
-	pdacf_t *chip = snd_magic_cast(pdacf_t, dev, return IRQ_NONE);
+	pdacf_t *chip = dev;
 	unsigned short stat;
 
 	if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|
@@ -258,7 +258,7 @@ static void pdacf_transfer(pdacf_t *chip, unsigned int size, unsigned int off)
 
 void pdacf_tasklet(unsigned long private_data)
 {
-	pdacf_t *chip = snd_magic_cast(pdacf_t, (void *)private_data, return);
+	pdacf_t *chip = (pdacf_t *) private_data;
 	int size, off, cont, rdp, wdp;
 
 	if ((chip->chip_status & (PDAUDIOCF_STAT_IS_STALE|PDAUDIOCF_STAT_IS_CONFIGURED)) != PDAUDIOCF_STAT_IS_CONFIGURED)
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
index 2aa90423a..0a954dc11 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
@@ -28,8 +28,6 @@
 #include <sound/asoundef.h>
 #include "pdaudiocf.h"
 
-#define chip_t	pdacf_t
-
 
 /*
  * we use a vmalloc'ed (sg-)buffer
@@ -331,7 +329,7 @@ static snd_pcm_ops_t pdacf_pcm_capture_ops = {
  */
 static void snd_pdacf_pcm_free(snd_pcm_t *pcm)
 {
-	pdacf_t *chip = snd_magic_cast(pdacf_t, pcm->private_data, return);
+	pdacf_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 }
 
diff --git a/sound/pcmcia/vx/vx_entry.c b/sound/pcmcia/vx/vx_entry.c
index e0158008e..f697a101a 100644
--- a/sound/pcmcia/vx/vx_entry.c
+++ b/sound/pcmcia/vx/vx_entry.c
@@ -69,13 +69,13 @@ static int snd_vxpocket_free(vx_core_t *chip)
 		hw->card_list[vxp->index] = NULL;
 	chip->card = NULL;
 
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_vxpocket_dev_free(snd_device_t *device)
 {
-	vx_core_t *chip = snd_magic_cast(vx_core_t, device->device_data, return -ENXIO);
+	vx_core_t *chip = device->device_data;
 	return snd_vxpocket_free(chip);
 }
 
@@ -121,7 +121,7 @@ dev_link_t *snd_vxpocket_attach(struct snd_vxp_entry *hw)
 		return NULL;
 
 	if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops) < 0) {
-		snd_magic_kfree(chip);
+		kfree(chip);
 		snd_card_free(card);
 		return NULL;
 	}
@@ -226,7 +226,7 @@ static int snd_vxpocket_assign_resources(vx_core_t *chip, int port, int irq)
  */
 void snd_vxpocket_detach(struct snd_vxp_entry *hw, dev_link_t *link)
 {
-	vx_core_t *chip = snd_magic_cast(vx_core_t, link->priv, return);
+	vx_core_t *chip = link->priv;
 
 	snd_printdd(KERN_DEBUG "vxpocket_detach called\n");
 	/* Remove the interface data from the linked list */
@@ -263,7 +263,7 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 static void vxpocket_config(dev_link_t *link)
 {
 	client_handle_t handle = link->handle;
-	vx_core_t *chip = snd_magic_cast(vx_core_t, link->priv, return);
+	vx_core_t *chip = link->priv;
 	struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
 	tuple_t tuple;
 	cisparse_t parse;
diff --git a/sound/pcmcia/vx/vxp_mixer.c b/sound/pcmcia/vx/vxp_mixer.c
index d46b2b7e8..aeaef3d81 100644
--- a/sound/pcmcia/vx/vxp_mixer.c
+++ b/sound/pcmcia/vx/vxp_mixer.c
@@ -25,8 +25,6 @@
 #include <sound/control.h>
 #include "vxpocket.h"
 
-#define chip_t vx_core_t
-
 #define MIC_LEVEL_MIN	0
 #define MIC_LEVEL_MAX	8
 
diff --git a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c
index c0e1fd0a8..2d6f0e1e6 100644
--- a/sound/pcmcia/vx/vxp_ops.c
+++ b/sound/pcmcia/vx/vxp_ops.c
@@ -26,8 +26,6 @@
 #include <asm/io.h>
 #include "vxpocket.h"
 
-#define chip_t vx_core_t
-
 
 static int vxp_reg_offset[VX_REG_MAX] = {
 	[VX_ICR]	= 0x00,		// ICR
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index 0a9085840..27608e4c6 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -50,8 +50,7 @@
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("Digigram " CARD_NAME);
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Digigram," CARD_NAME "}}");
+MODULE_SUPPORTED_DEVICE("{{Digigram," CARD_NAME "}}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -63,20 +62,16 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param(irq_mask, int, 0444);
 MODULE_PARM_DESC(irq_mask, "IRQ bitmask for " CARD_NAME " soundcard.");
 module_param_array(irq_list, int, boot_devs, 0444);
 MODULE_PARM_DESC(irq_list, "List of Available interrupts for " CARD_NAME " soundcard.");
 module_param_array(ibl, int, boot_devs, 0444);
 MODULE_PARM_DESC(ibl, "Capture IBL size for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(ibl, SNDRV_ENABLED);
  
 
 /*
diff --git a/sound/ppc/Kconfig b/sound/ppc/Kconfig
index 1860cb95d..ef6a65594 100644
--- a/sound/ppc/Kconfig
+++ b/sound/ppc/Kconfig
@@ -6,9 +6,12 @@ menu "ALSA PowerMac devices"
 comment "ALSA PowerMac requires I2C"
 	depends on SND && I2C=n
 
+comment "ALSA PowerMac requires INPUT"
+	depends on SND && INPUT=n
+
 config SND_POWERMAC
 	tristate "PowerMac (AWACS, DACA, Burgundy, Tumbler, Keywest)"
-	depends on SND && I2C
+	depends on SND && I2C && INPUT
 	select SND_PCM
 
 endmenu
diff --git a/sound/ppc/Makefile b/sound/ppc/Makefile
index a0a4c2084..4d95c652c 100644
--- a/sound/ppc/Makefile
+++ b/sound/ppc/Makefile
@@ -3,7 +3,7 @@
 # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
 #
 
-snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o
+snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o
diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c
index 5dd5a4892..e052bd071 100644
--- a/sound/ppc/awacs.c
+++ b/sound/ppc/awacs.c
@@ -29,8 +29,6 @@
 #include <sound/core.h>
 #include "pmac.h"
 
-#define chip_t pmac_t
-
 
 #ifdef CONFIG_ADB_CUDA
 #define PMAC_AMP_AVAIL
@@ -574,11 +572,22 @@ static snd_kcontrol_new_t snd_pmac_awacs_mixers[] __initdata = {
 	AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
 	AWACS_SWITCH("Master Capture Switch", 1, SHIFT_LOOPTHRU, 0),
 	AWACS_VOLUME("Capture Volume", 0, 4, 0),
-	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_LINE, 0),
 	AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
+};
+
+/* FIXME: is this correct order?
+ * screamer (powerbook G3 pismo) seems to have different bits...
+ */
+static snd_kcontrol_new_t snd_pmac_awacs_mixers2[] __initdata = {
+	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_LINE, 0),
 	AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_MIC, 0),
 };
 
+static snd_kcontrol_new_t snd_pmac_screamer_mixers2[] __initdata = {
+	AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
+	AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_LINE, 0),
+};
+
 static snd_kcontrol_new_t snd_pmac_awacs_master_sw __initdata =
 AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1);
 
@@ -602,8 +611,6 @@ static snd_kcontrol_new_t snd_pmac_awacs_speaker_sw __initdata =
 AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1);
 
 
-#define num_controls(ary) (sizeof(ary) / sizeof(snd_kcontrol_new_t))
-
 /*
  * add new mixer elements to the card
  */
@@ -818,9 +825,17 @@ snd_pmac_awacs_init(pmac_t *chip)
 	 */
 	strcpy(chip->card->mixername, "PowerMac AWACS");
 
-	if ((err = build_mixers(chip, num_controls(snd_pmac_awacs_mixers),
+	if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers),
 				snd_pmac_awacs_mixers)) < 0)
 		return err;
+	if (chip->model == PMAC_SCREAMER)
+		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mixers2),
+				   snd_pmac_screamer_mixers2);
+	else
+		err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers2),
+				   snd_pmac_awacs_mixers2);
+	if (err < 0)
+		return err;
 	chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_master_sw, chip);
 	if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0)
 		return err;
@@ -832,7 +847,7 @@ snd_pmac_awacs_init(pmac_t *chip)
 		 * screamer registers.
 		 * in this case, it seems the route C is not used.
 		 */
-		if ((err = build_mixers(chip, num_controls(snd_pmac_awacs_amp_vol),
+		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_amp_vol),
 					snd_pmac_awacs_amp_vol)) < 0)
 			return err;
 		/* overwrite */
@@ -846,7 +861,7 @@ snd_pmac_awacs_init(pmac_t *chip)
 #endif /* PMAC_AMP_AVAIL */
 	{
 		/* route A = headphone, route C = speaker */
-		if ((err = build_mixers(chip, num_controls(snd_pmac_awacs_speaker_vol),
+		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_speaker_vol),
 					snd_pmac_awacs_speaker_vol)) < 0)
 			return err;
 		chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_speaker_sw, chip);
@@ -855,11 +870,11 @@ snd_pmac_awacs_init(pmac_t *chip)
 	}
 
 	if (chip->model == PMAC_SCREAMER) {
-		if ((err = build_mixers(chip, num_controls(snd_pmac_screamer_mic_boost),
+		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mic_boost),
 					snd_pmac_screamer_mic_boost)) < 0)
 			return err;
 	} else {
-		if ((err = build_mixers(chip, num_controls(snd_pmac_awacs_mic_boost),
+		if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mic_boost),
 					snd_pmac_awacs_mic_boost)) < 0)
 			return err;
 	}
diff --git a/sound/ppc/burgundy.c b/sound/ppc/burgundy.c
index dc54946e1..3f837d9f3 100644
--- a/sound/ppc/burgundy.c
+++ b/sound/ppc/burgundy.c
@@ -28,8 +28,6 @@
 #include "pmac.h"
 #include "burgundy.h"
 
-#define chip_t pmac_t
-
 
 /* Waits for busy flag to clear */
 inline static void
@@ -324,8 +322,6 @@ BURGUNDY_OUTPUT_SWITCH("Headphone Playback Switch", 0, BURGUNDY_OUTPUT_LEFT, BUR
 static snd_kcontrol_new_t snd_pmac_burgundy_speaker_sw __initdata = 
 BURGUNDY_OUTPUT_SWITCH("PC Speaker Playback Switch", 0, BURGUNDY_OUTPUT_INTERN, 0, 0);
 
-#define num_controls(ary) (sizeof(ary) / sizeof(snd_kcontrol_new_t))
-
 
 #ifdef PMAC_SUPPORT_AUTOMUTE
 /*
@@ -420,7 +416,7 @@ int __init snd_pmac_burgundy_init(pmac_t *chip)
 	 */
 	strcpy(chip->card->mixername, "PowerMac Burgundy");
 
-	for (i = 0; i < num_controls(snd_pmac_burgundy_mixers); i++) {
+	for (i = 0; i < ARRAY_SIZE(snd_pmac_burgundy_mixers); i++) {
 		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip))) < 0)
 			return err;
 	}
diff --git a/sound/ppc/daca.c b/sound/ppc/daca.c
index 0b48286c9..6629b6bde 100644
--- a/sound/ppc/daca.c
+++ b/sound/ppc/daca.c
@@ -28,8 +28,6 @@
 #include <sound/core.h>
 #include "pmac.h"
 
-#define chip_t pmac_t
-
 /* i2c address */
 #define DACA_I2C_ADDR	0x4d
 
@@ -217,8 +215,6 @@ static snd_kcontrol_new_t daca_mixers[] = {
 	},
 };
 
-#define num_controls(ary) (sizeof(ary) / sizeof(snd_kcontrol_new_t))
-
 
 #ifdef CONFIG_PMAC_PBOOK
 static void daca_resume(pmac_t *chip)
@@ -272,7 +268,7 @@ int __init snd_pmac_daca_init(pmac_t *chip)
 	 */
 	strcpy(chip->card->mixername, "PowerMac DACA");
 
-	for (i = 0; i < num_controls(daca_mixers); i++) {
+	for (i = 0; i < ARRAY_SIZE(daca_mixers); i++) {
 		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&daca_mixers[i], chip))) < 0)
 			return err;
 	}
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index 6b307b064..3e44a6a7d 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -36,8 +36,6 @@
 #include <asm/feature.h>
 #endif
 
-#define chip_t pmac_t
-
 
 #if defined(CONFIG_PM) && defined(CONFIG_PMAC_PBOOK)
 static int snd_pmac_register_sleep_notifier(pmac_t *chip);
@@ -52,8 +50,8 @@ static int awacs_freqs[8] = {
 	44100, 29400, 22050, 17640, 14700, 11025, 8820, 7350
 };
 /* fixed frequency table for tumbler */
-static int tumbler_freqs[2] = {
-	48000, 44100
+static int tumbler_freqs[1] = {
+	44100
 };
 
 /*
@@ -86,7 +84,7 @@ static void snd_pmac_dbdma_free(pmac_dbdma_t *rec)
  * look up frequency table
  */
 
-static unsigned int snd_pmac_rate_index(pmac_t *chip, pmac_stream_t *rec, unsigned int rate)
+unsigned int snd_pmac_rate_index(pmac_t *chip, pmac_stream_t *rec, unsigned int rate)
 {
 	int i, ok, found;
 
@@ -203,7 +201,6 @@ static int snd_pmac_pcm_prepare(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substr
 {
 	int i;
 	volatile struct dbdma_cmd *cp;
-	unsigned long flags;
 	snd_pcm_runtime_t *runtime = subs->runtime;
 	int rate_index;
 	long offset;
@@ -226,15 +223,17 @@ static int snd_pmac_pcm_prepare(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substr
 	/* We really want to execute a DMA stop command, after the AWACS
 	 * is initialized.
 	 * For reasons I don't understand, it stops the hissing noise
-	 * common to many PowerBook G3 systems (like mine :-).
+	 * common to many PowerBook G3 systems and random noise otherwise
+	 * captured on iBook2's about every third time. -ReneR
 	 */
-	spin_lock_irqsave(&chip->reg_lock, flags);
+	spin_lock_irq(&chip->reg_lock);
 	snd_pmac_dma_stop(rec);
-	if (rec->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		st_le16(&chip->extra_dma.cmds->command, DBDMA_STOP);
-		snd_pmac_dma_set_command(rec, &chip->extra_dma);
-		snd_pmac_dma_run(rec, RUN);
-	}
+	st_le16(&chip->extra_dma.cmds->command, DBDMA_STOP);
+	snd_pmac_dma_set_command(rec, &chip->extra_dma);
+	snd_pmac_dma_run(rec, RUN);
+	spin_unlock_irq(&chip->reg_lock);
+	mdelay(5);
+	spin_lock_irq(&chip->reg_lock);
 	/* continuous DMA memory type doesn't provide the physical address,
 	 * so we need to resolve the address here...
 	 */
@@ -252,7 +251,7 @@ static int snd_pmac_pcm_prepare(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substr
 
 	snd_pmac_dma_stop(rec);
 	snd_pmac_dma_set_command(rec, &rec->cmd);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	spin_unlock_irq(&chip->reg_lock);
 
 	return 0;
 }
@@ -264,7 +263,6 @@ static int snd_pmac_pcm_prepare(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substr
 static int snd_pmac_pcm_trigger(pmac_t *chip, pmac_stream_t *rec,
 				snd_pcm_substream_t *subs, int cmd)
 {
-	unsigned long flags;
 	volatile struct dbdma_cmd *cp;
 	int i, command;
 
@@ -275,7 +273,7 @@ static int snd_pmac_pcm_trigger(pmac_t *chip, pmac_stream_t *rec,
 			return -EBUSY;
 		command = (subs->stream == SNDRV_PCM_STREAM_PLAYBACK ?
 			   OUTPUT_MORE : INPUT_MORE) + INTR_ALWAYS;
-		spin_lock_irqsave(&chip->reg_lock, flags);
+		spin_lock(&chip->reg_lock);
 		snd_pmac_beep_stop(chip);
 		snd_pmac_pcm_set_format(chip);
 		for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++)
@@ -284,18 +282,18 @@ static int snd_pmac_pcm_trigger(pmac_t *chip, pmac_stream_t *rec,
 		(void)in_le32(&rec->dma->status);
 		snd_pmac_dma_run(rec, RUN|WAKE);
 		rec->running = 1;
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		spin_unlock(&chip->reg_lock);
 		break;
 
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
-		spin_lock_irqsave(&chip->reg_lock, flags);
+		spin_lock(&chip->reg_lock);
 		rec->running = 0;
 		/*printk("stopped!!\n");*/
 		snd_pmac_dma_stop(rec);
 		for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++)
 			out_le16(&cp->command, DBDMA_STOP);
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
+		spin_unlock(&chip->reg_lock);
 		break;
 
 	default:
@@ -490,14 +488,12 @@ static int snd_pmac_pcm_open(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substream
 	snd_pcm_runtime_t *runtime = subs->runtime;
 	int i, j, fflags;
 	static int typical_freqs[] = {
-		48000,
 		44100,
 		22050,
 		11025,
 		0,
 	};
 	static int typical_freq_flags[] = {
-		SNDRV_PCM_RATE_48000,
 		SNDRV_PCM_RATE_44100,
 		SNDRV_PCM_RATE_22050,
 		SNDRV_PCM_RATE_11025,
@@ -651,7 +647,7 @@ int __init snd_pmac_pcm_new(pmac_t *chip)
 
 	pcm->private_data = chip;
 	pcm->private_free = pmac_pcm_free;
-	pcm->info_flags = 0;
+	pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
 	strcpy(pcm->name, chip->card->shortname);
 	chip->pcm = pcm;
 
@@ -682,13 +678,42 @@ static void snd_pmac_dbdma_reset(pmac_t *chip)
 }
 
 
+/*
+ * handling beep
+ */
+void snd_pmac_beep_dma_start(pmac_t *chip, int bytes, unsigned long addr, int speed)
+{
+	pmac_stream_t *rec = &chip->playback;
+
+	snd_pmac_dma_stop(rec);
+	st_le16(&chip->extra_dma.cmds->req_count, bytes);
+	st_le16(&chip->extra_dma.cmds->xfer_status, 0);
+	st_le32(&chip->extra_dma.cmds->cmd_dep, chip->extra_dma.addr);
+	st_le32(&chip->extra_dma.cmds->phy_addr, addr);
+	st_le16(&chip->extra_dma.cmds->command, OUTPUT_MORE + BR_ALWAYS);
+	out_le32(&chip->awacs->control,
+		 (in_le32(&chip->awacs->control) & ~0x1f00)
+		 | (speed << 8));
+	out_le32(&chip->awacs->byteswap, 0);
+	snd_pmac_dma_set_command(rec, &chip->extra_dma);
+	snd_pmac_dma_run(rec, RUN);
+}
+
+void snd_pmac_beep_dma_stop(pmac_t *chip)
+{
+	snd_pmac_dma_stop(&chip->playback);
+	st_le16(&chip->extra_dma.cmds->command, DBDMA_STOP);
+	snd_pmac_pcm_set_format(chip); /* reset format */
+}
+
+
 /*
  * interrupt handlers
  */
 static irqreturn_t
 snd_pmac_tx_intr(int irq, void *devid, struct pt_regs *regs)
 {
-	pmac_t *chip = snd_magic_cast(pmac_t, devid, return IRQ_NONE);
+	pmac_t *chip = devid;
 	snd_pmac_pcm_update(chip, &chip->playback);
 	return IRQ_HANDLED;
 }
@@ -697,7 +722,7 @@ snd_pmac_tx_intr(int irq, void *devid, struct pt_regs *regs)
 static irqreturn_t
 snd_pmac_rx_intr(int irq, void *devid, struct pt_regs *regs)
 {
-	pmac_t *chip = snd_magic_cast(pmac_t, devid, return IRQ_NONE);
+	pmac_t *chip = devid;
 	snd_pmac_pcm_update(chip, &chip->capture);
 	return IRQ_HANDLED;
 }
@@ -706,7 +731,7 @@ snd_pmac_rx_intr(int irq, void *devid, struct pt_regs *regs)
 static irqreturn_t
 snd_pmac_ctrl_intr(int irq, void *devid, struct pt_regs *regs)
 {
-	pmac_t *chip = snd_magic_cast(pmac_t, devid, return IRQ_NONE);
+	pmac_t *chip = devid;
 	int ctrl = in_le32(&chip->awacs->control);
 
 	/*printk("pmac: control interrupt.. 0x%x\n", ctrl);*/
@@ -776,6 +801,8 @@ static int snd_pmac_free(pmac_t *chip)
 	if (chip->mixer_free)
 		chip->mixer_free(chip);
 
+	snd_pmac_detach_beep(chip);
+
 	/* release resources */
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void*)chip);
@@ -802,7 +829,7 @@ static int snd_pmac_free(pmac_t *chip)
 				release_OF_resource(chip->node, i);
 		}
 	}
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
@@ -812,7 +839,7 @@ static int snd_pmac_free(pmac_t *chip)
  */
 static int snd_pmac_dev_free(snd_device_t *device)
 {
-	pmac_t *chip = snd_magic_cast(pmac_t, device->device_data, return -ENXIO);
+	pmac_t *chip = device->device_data;
 	return snd_pmac_free(chip);
 }
 
@@ -862,7 +889,7 @@ static int __init snd_pmac_detect(pmac_t *chip)
 	chip->can_byte_swap = 1;
 	chip->can_duplex = 1;
 	chip->can_capture = 1;
-	chip->num_freqs = 8;
+	chip->num_freqs = ARRAY_SIZE(awacs_freqs);
 	chip->freq_table = awacs_freqs;
 
 	chip->control_mask = MASK_IEPC | MASK_IEE | 0x11; /* default */
@@ -920,14 +947,14 @@ static int __init snd_pmac_detect(pmac_t *chip)
 		chip->can_capture = 0;  /* no capture */
 		chip->can_duplex = 0;
 		// chip->can_byte_swap = 0; /* FIXME: check this */
-		chip->num_freqs = 2;
+		chip->num_freqs = ARRAY_SIZE(tumbler_freqs);
 		chip->freq_table = tumbler_freqs;
 		chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */
 	}
 	if (device_is_compatible(sound, "snapper")) {
 		chip->model = PMAC_SNAPPER;
 		// chip->can_byte_swap = 0; /* FIXME: check this */
-		chip->num_freqs = 2;
+		chip->num_freqs = ARRAY_SIZE(tumbler_freqs);
 		chip->freq_table = tumbler_freqs;
 		chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */
 	}
@@ -1069,7 +1096,7 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return)
 	snd_runtime_check(chip_return, return -EINVAL);
 	*chip_return = NULL;
 
-	chip = snd_magic_kcalloc(pmac_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 	chip->card = card;
@@ -1206,7 +1233,7 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return)
 
 static int snd_pmac_suspend(snd_card_t *card, unsigned int state)
 {
-	pmac_t *chip = snd_magic_cast(pmac_t, card->pm_private_data, return -EINVAL);
+	pmac_t *chip = card->pm_private_data;
 	unsigned long flags;
 
 	if (chip->suspend)
@@ -1228,7 +1255,7 @@ static int snd_pmac_suspend(snd_card_t *card, unsigned int state)
 
 static int snd_pmac_resume(snd_card_t *card, unsigned int state)
 {
-	pmac_t *chip = snd_magic_cast(pmac_t, card->pm_private_data, return -EINVAL);
+	pmac_t *chip = card->pm_private_data;
 
 	snd_pmac_sound_feature(chip, 1);
 	if (chip->resume)
diff --git a/sound/ppc/pmac.h b/sound/ppc/pmac.h
index 252ea0311..9521a4106 100644
--- a/sound/ppc/pmac.h
+++ b/sound/ppc/pmac.h
@@ -84,7 +84,7 @@ struct snd_pmac_stream {
 
 	snd_pcm_substream_t *substream;
 
-	unsigned int cur_freqs;		/* currently available frequences */
+	unsigned int cur_freqs;		/* currently available frequencies */
 	unsigned int cur_formats;	/* currently available formats */
 };
 
@@ -155,6 +155,7 @@ struct snd_pmac {
 	void (*mixer_free)(pmac_t *);
 	snd_kcontrol_t *master_sw_ctl;
 	snd_kcontrol_t *speaker_sw_ctl;
+	snd_kcontrol_t *drc_sw_ctl;	/* only used for tumbler -ReneR */
 	snd_kcontrol_t *hp_detect_ctl;
 
 	/* lowlevel callbacks */
@@ -173,6 +174,12 @@ struct snd_pmac {
 int snd_pmac_new(snd_card_t *card, pmac_t **chip_return);
 int snd_pmac_pcm_new(pmac_t *chip);
 int snd_pmac_attach_beep(pmac_t *chip);
+void snd_pmac_detach_beep(pmac_t *chip);
+void snd_pmac_beep_stop(pmac_t *chip);
+unsigned int snd_pmac_rate_index(pmac_t *chip, pmac_stream_t *rec, unsigned int rate);
+
+void snd_pmac_beep_dma_start(pmac_t *chip, int bytes, unsigned long addr, int speed);
+void snd_pmac_beep_dma_stop(pmac_t *chip);
 
 /* initialize mixer */
 int snd_pmac_awacs_init(pmac_t *chip);
@@ -206,9 +213,4 @@ int snd_pmac_add_automute(pmac_t *chip);
 	schedule_timeout(((msec) * HZ + 999) / 1000);\
 } while (0)
 
-#ifndef PMAC_SUPPORT_PCM_BEEP
-#define snd_pmac_attach_beep(chip) 0
-#define snd_pmac_beep_stop(chip)  /**/
-#endif
-
 #endif /* __PMAC_H */
diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c
index 3c4550ae6..8f1953a8e 100644
--- a/sound/ppc/powermac.c
+++ b/sound/ppc/powermac.c
@@ -30,31 +30,19 @@
 #define CHIP_NAME "PMac"
 
 MODULE_DESCRIPTION("PowerMac");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Apple,PowerMac}}");
+MODULE_SUPPORTED_DEVICE("{{Apple,PowerMac}}");
 MODULE_LICENSE("GPL");
 
 static int index = SNDRV_DEFAULT_IDX1;		/* Index 0-MAX */
 static char *id = SNDRV_DEFAULT_STR1;		/* ID for this card */
-/* static int enable = 1; */
-#ifdef PMAC_SUPPORT_PCM_BEEP
 static int enable_beep = 1;
-#endif
 
 module_param(index, int, 0444);
 MODULE_PARM_DESC(index, "Index value for " CHIP_NAME " soundchip.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param(id, charp, 0444);
 MODULE_PARM_DESC(id, "ID string for " CHIP_NAME " soundchip.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
-/* module_param(enable, bool, 0444);
-   MODULE_PARM_DESC(enable, "Enable this soundchip.");
-   MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC); */
-#ifdef PMAC_SUPPORT_PCM_BEEP
 module_param(enable_beep, bool, 0444);
 MODULE_PARM_DESC(enable_beep, "Enable beep using PCM.");
-MODULE_PARM_SYNTAX(enable_beep, SNDRV_ENABLED "," SNDRV_BOOLEAN_TRUE_DESC);
-#endif
 
 
 /*
@@ -133,10 +121,8 @@ static int __init snd_pmac_probe(void)
 		goto __error;
 
 	chip->initialized = 1;
-#ifdef PMAC_SUPPORT_PCM_BEEP
 	if (enable_beep)
 		snd_pmac_attach_beep(chip);
-#endif
 
 	if ((err = snd_card_register(card)) < 0)
 		goto __error;
@@ -151,18 +137,14 @@ __error:
 
 
 /*
- * MODULE sutff
+ * MODULE stuff
  */
 
 static int __init alsa_card_pmac_init(void)
 {
 	int err;
-	if ((err = snd_pmac_probe()) < 0) {
-#ifdef MODULE
-		printk(KERN_ERR "no PMac soundchip found\n");
-#endif
+	if ((err = snd_pmac_probe()) < 0)
 		return err;
-	}
 	return 0;
 
 }
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index 42b55b600..3fa41ffe2 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -16,6 +16,11 @@
  *   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
+ *
+ *   Rene Rebe <rene.rebe@gmx.net>:
+ *     * update from shadow registers on wakeup and headphone plug
+ *     * automatically toggle DRC on headphone plug
+ *	
  */
 
 
@@ -36,8 +41,6 @@
 #include "pmac.h"
 #include "tumbler_volume.h"
 
-#define chip_t pmac_t
-
 /* i2c address for tumbler */
 #define TAS_I2C_ADDR	0x34
 
@@ -758,12 +761,6 @@ static snd_kcontrol_new_t tumbler_mixers[] __initdata = {
 	DEFINE_MONO("Tone Control - Bass", bass),
 	DEFINE_MONO("Tone Control - Treble", treble),
 	DEFINE_MONO("PCM Playback Volume", pcm),
-	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	  .name = "DRC Switch",
-	  .info = snd_pmac_boolean_mono_info,
-	  .get = tumbler_get_drc_switch,
-	  .put = tumbler_put_drc_switch
-	},
 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	  .name = "DRC Range",
 	  .info = tumbler_info_drc_value,
@@ -790,12 +787,6 @@ static snd_kcontrol_new_t snapper_mixers[] __initdata = {
 	DEFINE_SNAPPER_MIX("Monitor Mix Volume", 0, VOL_IDX_ADC),
 	DEFINE_SNAPPER_MONO("Tone Control - Bass", bass),
 	DEFINE_SNAPPER_MONO("Tone Control - Treble", treble),
-	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	  .name = "DRC Switch",
-	  .info = snd_pmac_boolean_mono_info,
-	  .get = tumbler_get_drc_switch,
-	  .put = tumbler_put_drc_switch
-	},
 	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	  .name = "DRC Range",
 	  .info = tumbler_info_drc_value,
@@ -826,6 +817,14 @@ static snd_kcontrol_new_t tumbler_speaker_sw __initdata = {
 	.put = tumbler_put_mute_switch,
 	.private_value = TUMBLER_MUTE_AMP,
 };
+static snd_kcontrol_new_t tumbler_drc_sw __initdata = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "DRC Switch",
+	.info = snd_pmac_boolean_mono_info,
+	.get = tumbler_get_drc_switch,
+	.put = tumbler_put_drc_switch
+};
+
 
 #ifdef PMAC_SUPPORT_AUTOMUTE
 /*
@@ -847,6 +846,29 @@ static void check_mute(pmac_t *chip, pmac_gpio_t *gp, int val, int do_notify, sn
 	}
 }
 
+static struct work_struct device_change;
+
+static void
+device_change_handler(void *self)
+{
+	pmac_t *chip = (pmac_t*) self;
+	pmac_tumbler_t *mix;
+
+	if (!chip)
+		return;
+
+	mix = chip->mixer_data;
+
+	/* first set the DRC so the speaker do not explode -ReneR */
+	if (chip->model == PMAC_TUMBLER)
+		tumbler_set_drc(mix);
+	else
+		snapper_set_drc(mix);
+
+	/* reset the master volume so the correct amplification is applied */
+	tumbler_set_master_volume(mix);
+}
+
 static void tumbler_update_automute(pmac_t *chip, int do_notify)
 {
 	if (chip->auto_mute) {
@@ -856,14 +878,25 @@ static void tumbler_update_automute(pmac_t *chip, int do_notify)
 			/* mute speaker */
 			check_mute(chip, &mix->amp_mute, 1, do_notify, chip->speaker_sw_ctl);
 			check_mute(chip, &mix->hp_mute, 0, do_notify, chip->master_sw_ctl);
+			mix->drc_enable = 0;
+
 		} else {
 			/* unmute speaker */
 			check_mute(chip, &mix->amp_mute, 0, do_notify, chip->speaker_sw_ctl);
 			check_mute(chip, &mix->hp_mute, 1, do_notify, chip->master_sw_ctl);
+			mix->drc_enable = 1;
 		}
-		if (do_notify)
+		if (do_notify) {
 			snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
 				       &chip->hp_detect_ctl->id);
+			snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+			               &chip->drc_sw_ctl->id);
+		}
+
+		/* finally we need to schedule an update of the mixer values
+		   (master and DRC are enough for now) -ReneR */
+		schedule_work(&device_change);
+
 	}
 }
 #endif /* PMAC_SUPPORT_AUTOMUTE */
@@ -872,7 +905,7 @@ static void tumbler_update_automute(pmac_t *chip, int do_notify)
 /* interrupt - headphone plug changed */
 static irqreturn_t headphone_intr(int irq, void *devid, struct pt_regs *regs)
 {
-	pmac_t *chip = snd_magic_cast(pmac_t, devid, return IRQ_NONE);
+	pmac_t *chip = devid;
 	if (chip->update_automute && chip->initialized) {
 		chip->update_automute(chip, 1);
 		return IRQ_HANDLED;
@@ -1114,11 +1147,17 @@ int __init snd_pmac_tumbler_init(pmac_t *chip)
 	chip->speaker_sw_ctl = snd_ctl_new1(&tumbler_speaker_sw, chip);
 	if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0)
 		return err;
+	chip->drc_sw_ctl = snd_ctl_new1(&tumbler_drc_sw, chip);
+	if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0)
+		return err;
+
 
 #ifdef CONFIG_PMAC_PBOOK
 	chip->resume = tumbler_resume;
 #endif
 
+	INIT_WORK(&device_change, device_change_handler, (void *)chip);
+
 #ifdef PMAC_SUPPORT_AUTOMUTE
 	if (mix->headphone_irq >=0 && (err = snd_pmac_add_automute(chip)) < 0)
 		return err;
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c
index 993d0fb7a..aa14c340d 100644
--- a/sound/sparc/amd7930.c
+++ b/sound/sparc/amd7930.c
@@ -54,18 +54,14 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Sun AMD7930 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Sun AMD7930 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Sun AMD7930 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 MODULE_AUTHOR("Thomas K. Dyas and David S. Miller");
 MODULE_DESCRIPTION("Sun AMD7930");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Sun,AMD7930}}");
+MODULE_SUPPORTED_DEVICE("{{Sun,AMD7930}}");
 
 /* Device register layout.  */
 
@@ -318,7 +314,7 @@ struct amd7930_map {
 
 typedef struct snd_amd7930 {
 	spinlock_t		lock;
-	unsigned long		regs;
+	void __iomem		*regs;
 	u32			flags;
 #define AMD7930_FLAG_PLAYBACK	0x00000001
 #define AMD7930_FLAG_CAPTURE	0x00000002
@@ -345,7 +341,6 @@ typedef struct snd_amd7930 {
 	unsigned int		regs_size;
 	struct snd_amd7930	*next;
 } amd7930_t;
-#define chip_t amd7930_t
 
 static amd7930_t *amd7930_list;
 
@@ -475,7 +470,6 @@ static __const__ __u16 ger_coeff[] = {
 	0x000b, /* 16.9 dB */
 	0x000f  /* 18. dB */
 };
-#define NR_GER_COEFFS (sizeof(ger_coeff) / sizeof(ger_coeff[0]))
 
 /* Update amd7930_map settings and program them into the hardware.
  * The amd->lock is held and local interrupts are disabled.
@@ -487,7 +481,7 @@ static void __amd7930_update_map(amd7930_t *amd)
 
 	map->gx = gx_coeff[amd->rgain];
 	map->stgr = gx_coeff[amd->mgain];
-	level = (amd->pgain * (256 + NR_GER_COEFFS)) >> 8;
+	level = (amd->pgain * (256 + ARRAY_SIZE(ger_coeff))) >> 8;
 	if (level >= 256) {
 		map->ger = ger_coeff[level - 256];
 		map->gr = gx_coeff[255];
@@ -764,7 +758,7 @@ static snd_pcm_ops_t snd_amd7930_capture_ops = {
 
 static void snd_amd7930_pcm_free(snd_pcm_t *pcm)
 {
-	amd7930_t *amd = snd_magic_cast(amd7930_t, pcm->private_data, return);
+	amd7930_t *amd = pcm->private_data;
 
 	amd->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
@@ -916,8 +910,6 @@ static snd_kcontrol_new_t amd7930_controls[] __initdata = {
 	},
 };
 
-#define NUM_AMD7930_CONTROLS (sizeof(amd7930_controls)/sizeof(snd_kcontrol_new_t))
-
 static int __init snd_amd7930_mixer(amd7930_t *amd)
 {
 	snd_card_t *card;
@@ -928,7 +920,7 @@ static int __init snd_amd7930_mixer(amd7930_t *amd)
 	card = amd->card;
 	strcpy(card->mixername, card->shortname);
 
-	for (idx = 0; idx < NUM_AMD7930_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(amd7930_controls); idx++) {
 		if ((err = snd_ctl_add(card,
 				       snd_ctl_new1(&amd7930_controls[idx], amd))) < 0)
 			return err;
@@ -947,14 +939,14 @@ static int snd_amd7930_free(amd7930_t *amd)
 	if (amd->regs)
 		sbus_iounmap(amd->regs, amd->regs_size);
 
-	snd_magic_kfree(amd);
+	kfree(amd);
 
 	return 0;
 }
 
 static int snd_amd7930_dev_free(snd_device_t *device)
 {
-	amd7930_t *amd = snd_magic_cast(amd7930_t, device->device_data, return -ENXIO);
+	amd7930_t *amd = device->device_data;
 
 	return snd_amd7930_free(amd);
 }
@@ -976,7 +968,7 @@ static int __init snd_amd7930_create(snd_card_t *card,
 	int err;
 
 	*ramd = NULL;
-	amd = snd_magic_kcalloc(amd7930_t, 0, GFP_KERNEL);
+	amd = kcalloc(1, sizeof(*amd), GFP_KERNEL);
 	if (amd == NULL)
 		return -ENOMEM;
 
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c
index 00a845e28..f084dc121 100644
--- a/sound/sparc/cs4231.c
+++ b/sound/sparc/cs4231.c
@@ -53,22 +53,18 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for Sun CS4231 soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for Sun CS4231 soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable Sun CS4231 soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 MODULE_AUTHOR("Jaroslav Kysela, Derrick J. Brashear and David S. Miller");
 MODULE_DESCRIPTION("Sun CS4231");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Sun,CS4231}}");
+MODULE_SUPPORTED_DEVICE("{{Sun,CS4231}}");
 
 typedef struct snd_cs4231 {
 	spinlock_t		lock;
-	unsigned long		port;
+	void __iomem		*port;
 #ifdef EBUS_SUPPORT
 	struct ebus_dma_info	eb2c;
 	struct ebus_dma_info	eb2p;
@@ -112,7 +108,6 @@ typedef struct snd_cs4231 {
 	unsigned int		regs_size;
 	struct snd_cs4231	*next;
 } cs4231_t;
-#define chip_t cs4231_t
 
 static cs4231_t *cs4231_list;
 
@@ -362,7 +357,7 @@ static unsigned char snd_cs4231_original_image[32] =
 	0x00,			/* 1f/31 - cbrl */
 };
 
-static u8 __cs4231_readb(cs4231_t *cp, unsigned long reg_addr)
+static u8 __cs4231_readb(cs4231_t *cp, void __iomem *reg_addr)
 {
 #ifdef EBUS_SUPPORT
 	if (cp->flags & CS4231_FLAG_EBUS) {
@@ -377,7 +372,7 @@ static u8 __cs4231_readb(cs4231_t *cp, unsigned long reg_addr)
 #endif
 }
 
-static void __cs4231_writeb(cs4231_t *cp, u8 val, unsigned long reg_addr)
+static void __cs4231_writeb(cs4231_t *cp, u8 val, void __iomem *reg_addr)
 {
 #ifdef EBUS_SUPPORT
 	if (cp->flags & CS4231_FLAG_EBUS) {
@@ -556,7 +551,7 @@ static void snd_cs4231_mce_up(cs4231_t *chip)
 	chip->mce_bit |= CS4231_MCE;
 	timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL));
 	if (timeout == 0x80)
-		snd_printk("mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port);
+		snd_printk("mce_up [%p]: serious init problem - codec still busy\n", chip->port);
 	if (!(timeout & CS4231_MCE))
 		__cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));
 	spin_unlock_irqrestore(&chip->lock, flags);
@@ -581,7 +576,7 @@ static void snd_cs4231_mce_down(cs4231_t *chip)
 	timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL));
 	__cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));
 	if (timeout == 0x80)
-		snd_printk("mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port);
+		snd_printk("mce_down [%p]: serious init problem - codec still busy\n", chip->port);
 	if ((timeout & CS4231_MCE) == 0) {
 		spin_unlock_irqrestore(&chip->lock, flags);
 		return;
@@ -1232,7 +1227,7 @@ static void snd_cs4231_generic_interrupt(cs4231_t *chip)
 #ifdef SBUS_SUPPORT
 static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	cs4231_t *chip = snd_magic_cast(cs4231_t, dev_id, return);
+	cs4231_t *chip = dev_id;
 	u32 csr;
 
 	csr = sbus_readl(chip->port + APCCSR);
@@ -1256,7 +1251,7 @@ static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_re
 #ifdef EBUS_SUPPORT
 static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event, void *cookie)
 {
-	cs4231_t *chip = snd_magic_cast(cs4231_t, cookie, return);
+	cs4231_t *chip = cookie;
 
 	if (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE) {
 		snd_pcm_period_elapsed(chip->playback_substream);
@@ -1267,7 +1262,7 @@ static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event, vo
 
 static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event, void *cookie)
 {
-	cs4231_t *chip = snd_magic_cast(cs4231_t, cookie, return);
+	cs4231_t *chip = cookie;
 
 	if (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) {
 		snd_pcm_period_elapsed(chip->capture_substream);
@@ -1547,7 +1542,7 @@ static snd_pcm_ops_t snd_cs4231_capture_ops = {
 
 static void snd_cs4231_pcm_free(snd_pcm_t *pcm)
 {
-	cs4231_t *chip = snd_magic_cast(cs4231_t, pcm->private_data, return);
+	cs4231_t *chip = pcm->private_data;
 	chip->pcm = NULL;
 	snd_pcm_lib_preallocate_free_for_all(pcm);
 }
@@ -1592,7 +1587,7 @@ int snd_cs4231_pcm(cs4231_t *chip)
 
 static void snd_cs4231_timer_free(snd_timer_t *timer)
 {
-	cs4231_t *chip = snd_magic_cast(cs4231_t, timer->private_data, return);
+	cs4231_t *chip = timer->private_data;
 	chip->timer = NULL;
 }
 
@@ -1821,8 +1816,6 @@ int snd_cs4231_put_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontr
 	return change;
 }
 
-#define CS4231_CONTROLS (sizeof(snd_cs4231_controls)/sizeof(snd_kcontrol_new_t))
-
 #define CS4231_SINGLE(xname, xindex, reg, shift, mask, invert) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
   .info = snd_cs4231_info_single, \
@@ -1875,7 +1868,7 @@ int snd_cs4231_mixer(cs4231_t *chip)
 
 	strcpy(card->mixername, chip->pcm->name);
 
-	for (idx = 0; idx < CS4231_CONTROLS; idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(snd_cs4231_controls); idx++) {
 		if ((err = snd_ctl_add(card,
 				       snd_ctl_new1(&snd_cs4231_controls[idx],
 						    chip))) < 0)
@@ -1950,14 +1943,14 @@ static int snd_cs4231_sbus_free(cs4231_t *chip)
 	if (chip->timer)
 		snd_device_free(chip->card, chip->timer);
 
-	snd_magic_kfree(chip);
+	kfree(chip);
 
 	return 0;
 }
 
 static int snd_cs4231_sbus_dev_free(snd_device_t *device)
 {
-	cs4231_t *cp = snd_magic_cast(cs4231_t, device->device_data, return -ENXIO);
+	cs4231_t *cp = device->device_data;
 
 	return snd_cs4231_sbus_free(cp);
 }
@@ -1975,7 +1968,7 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card,
 	int err;
 
 	*rchip = NULL;
-	chip = snd_magic_kcalloc(cs4231_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 
@@ -2064,14 +2057,14 @@ static int snd_cs4231_ebus_free(cs4231_t *chip)
 	if (chip->timer)
 		snd_device_free(chip->card, chip->timer);
 
-	snd_magic_kfree(chip);
+	kfree(chip);
 
 	return 0;
 }
 
 static int snd_cs4231_ebus_dev_free(snd_device_t *device)
 {
-	cs4231_t *cp = snd_magic_cast(cs4231_t, device->device_data, return -ENXIO);
+	cs4231_t *cp = device->device_data;
 
 	return snd_cs4231_ebus_free(cp);
 }
@@ -2089,7 +2082,7 @@ static int __init snd_cs4231_ebus_create(snd_card_t *card,
 	int err;
 
 	*rchip = NULL;
-	chip = snd_magic_kcalloc(cs4231_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (chip == NULL)
 		return -ENOMEM;
 
@@ -2114,9 +2107,9 @@ static int __init snd_cs4231_ebus_create(snd_card_t *card,
 	chip->eb2p.client_cookie = chip;
 	chip->eb2p.irq = edev->irqs[1];
 
-	chip->port = (unsigned long) ioremap(edev->resource[0].start, 0x10);
-	chip->eb2p.regs = (unsigned long) ioremap(edev->resource[1].start, 0x10);
-	chip->eb2c.regs = (unsigned long) ioremap(edev->resource[2].start, 0x10);
+	chip->port = ioremap(edev->resource[0].start, 0x10);
+	chip->eb2p.regs = ioremap(edev->resource[1].start, 0x10);
+	chip->eb2c.regs = ioremap(edev->resource[2].start, 0x10);
 	if (!chip->port || !chip->eb2p.regs || !chip->eb2c.regs) {
 		snd_cs4231_ebus_free(chip);
 		snd_printk("cs4231-%d: Unable to map chip registers.\n", dev);
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c
index 155df152c..0476d0655 100644
--- a/sound/synth/emux/emux.c
+++ b/sound/synth/emux/emux.c
@@ -39,7 +39,7 @@ int snd_emux_new(snd_emux_t **remu)
 	snd_emux_t *emu;
 
 	*remu = NULL;
-	emu = snd_magic_kcalloc(snd_emux_t, 0, GFP_KERNEL);
+	emu = kcalloc(1, sizeof(*emu), GFP_KERNEL);
 	if (emu == NULL)
 		return -ENOMEM;
 
@@ -77,7 +77,7 @@ int snd_emux_register(snd_emux_t *emu, snd_card_t *card, int index, char *name)
 
 	emu->card = card;
 	emu->name = snd_kmalloc_strdup(name, GFP_KERNEL);
-	emu->voices = snd_kcalloc(sizeof(snd_emux_voice_t) * emu->max_voices, GFP_KERNEL);
+	emu->voices = kcalloc(emu->max_voices, sizeof(snd_emux_voice_t), GFP_KERNEL);
 	if (emu->voices == NULL)
 		return -ENOMEM;
 
@@ -143,7 +143,7 @@ int snd_emux_free(snd_emux_t *emu)
 	if (emu->name)
 		kfree(emu->name);
 
-	snd_magic_kfree(emu);
+	kfree(emu);
 	return 0;
 }
 
diff --git a/sound/synth/emux/emux_effect.c b/sound/synth/emux/emux_effect.c
index f1a2af177..ec3fc1ba7 100644
--- a/sound/synth/emux/emux_effect.c
+++ b/sound/synth/emux/emux_effect.c
@@ -278,7 +278,7 @@ void
 snd_emux_create_effect(snd_emux_port_t *p)
 {
 	int i;
-	p->effect = snd_kcalloc(sizeof(snd_emux_effect_table_t) * p->chset.max_channels, GFP_KERNEL);
+	p->effect = kcalloc(p->chset.max_channels, sizeof(snd_emux_effect_table_t), GFP_KERNEL);
 	if (p->effect) {
 		for (i = 0; i < p->chset.max_channels; i++)
 			p->chset.channels[i].private = p->effect + i;
diff --git a/sound/synth/emux/emux_hwdep.c b/sound/synth/emux/emux_hwdep.c
index e1451484a..4182b44eb 100644
--- a/sound/synth/emux/emux_hwdep.c
+++ b/sound/synth/emux/emux_hwdep.c
@@ -104,7 +104,7 @@ snd_emux_hwdep_misc_mode(snd_emux_t *emu, void __user *arg)
 static int
 snd_emux_hwdep_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cmd, unsigned long arg)
 {
-	snd_emux_t *emu = snd_magic_cast(snd_emux_t, hw->private_data, return -ENXIO);
+	snd_emux_t *emu = hw->private_data;
 
 	switch (cmd) {
 	case SNDRV_EMUX_IOCTL_VERSION:
diff --git a/sound/synth/emux/emux_nrpn.c b/sound/synth/emux/emux_nrpn.c
index c49cf56b8..25edff9e1 100644
--- a/sound/synth/emux/emux_nrpn.c
+++ b/sound/synth/emux/emux_nrpn.c
@@ -22,8 +22,6 @@
 #include "emux_voice.h"
 #include <sound/asoundef.h>
 
-#define NELEM(arr) (sizeof(arr)/sizeof((arr)[0]))
-
 /*
  * conversion from NRPN/control parameters to Emu8000 raw parameters
  */
@@ -214,8 +212,6 @@ static nrpn_conv_table awe_effects[] =
 	{26, EMUX_FX_REVERB,		fx_reverb},
 };
 
-static int num_awe_effects = NELEM(awe_effects);
-
 
 /*
  * GS(SC88) NRPN effects; still experimental
@@ -281,8 +277,6 @@ static nrpn_conv_table gs_effects[] =
 	{10, EMUX_FX_LFO1_DELAY, gs_vib_delay},
 };
 
-static int num_gs_effects = NELEM(gs_effects);
-
 
 /*
  * NRPN events
@@ -292,7 +286,7 @@ snd_emux_nrpn(void *p, snd_midi_channel_t *chan, snd_midi_channel_set_t *chset)
 {
 	snd_emux_port_t *port;
 
-	port = snd_magic_cast(snd_emux_port_t, p, return);
+	port = p;
 	snd_assert(port != NULL, return);
 	snd_assert(chan != NULL, return);
 
@@ -305,7 +299,7 @@ snd_emux_nrpn(void *p, snd_midi_channel_t *chan, snd_midi_channel_set_t *chset)
 			chan->control[MIDI_CTL_LSB_DATA_ENTRY]; 
 		val -= 8192;
 		send_converted_effect
-			(awe_effects, num_awe_effects,
+			(awe_effects, ARRAY_SIZE(awe_effects),
 			 port, chan, chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB],
 			 val, EMUX_FX_FLAG_SET);
 		return;
@@ -318,7 +312,7 @@ snd_emux_nrpn(void *p, snd_midi_channel_t *chan, snd_midi_channel_set_t *chset)
 		/* only MSB is valid */
 		val = chan->control[MIDI_CTL_MSB_DATA_ENTRY];
 		send_converted_effect
-			(gs_effects, num_gs_effects,
+			(gs_effects, ARRAY_SIZE(gs_effects),
 			 port, chan, chan->control[MIDI_CTL_NONREG_PARM_NUM_LSB],
 			 val, EMUX_FX_FLAG_ADD);
 		return;
@@ -362,12 +356,10 @@ static nrpn_conv_table xg_effects[] =
 	{73, EMUX_FX_ENV2_ATTACK, xg_attack},
 };
 
-static int num_xg_effects = NELEM(xg_effects);
-
 int
 snd_emux_xg_control(snd_emux_port_t *port, snd_midi_channel_t *chan, int param)
 {
-	return send_converted_effect(xg_effects, num_xg_effects,
+	return send_converted_effect(xg_effects, ARRAY_SIZE(xg_effects),
 				     port, chan, param,
 				     chan->control[param],
 				     EMUX_FX_FLAG_ADD);
@@ -382,7 +374,7 @@ snd_emux_sysex(void *p, unsigned char *buf, int len, int parsed, snd_midi_channe
 	snd_emux_port_t *port;
 	snd_emux_t *emu;
 
-	port = snd_magic_cast(snd_emux_port_t, p, return);
+	port = p;
 	snd_assert(port != NULL, return);
 	snd_assert(chset != NULL, return);
 	emu = port->emu;
diff --git a/sound/synth/emux/emux_oss.c b/sound/synth/emux/emux_oss.c
index 979252146..5272f4ac8 100644
--- a/sound/synth/emux/emux_oss.c
+++ b/sound/synth/emux/emux_oss.c
@@ -108,7 +108,7 @@ snd_emux_open_seq_oss(snd_seq_oss_arg_t *arg, void *closure)
 	snd_seq_port_callback_t callback;
 	char tmpname[64];
 
-	emu = snd_magic_cast(snd_emux_t, closure, return -EINVAL);
+	emu = closure;
 	snd_assert(arg != NULL && emu != NULL, return -ENXIO);
 
 	down(&emu->register_mutex);
@@ -179,7 +179,7 @@ snd_emux_close_seq_oss(snd_seq_oss_arg_t *arg)
 	snd_emux_port_t *p;
 
 	snd_assert(arg != NULL, return -ENXIO);
-	p = snd_magic_cast(snd_emux_port_t, arg->private_data, return -EINVAL);
+	p = arg->private_data;
 	snd_assert(p != NULL, return -ENXIO);
 
 	emu = p->emu;
@@ -208,7 +208,7 @@ snd_emux_load_patch_seq_oss(snd_seq_oss_arg_t *arg, int format,
 	int rc;
 
 	snd_assert(arg != NULL, return -ENXIO);
-	p = snd_magic_cast(snd_emux_port_t, arg->private_data, return -EINVAL);
+	p = arg->private_data;
 	snd_assert(p != NULL, return -ENXIO);
 
 	emu = p->emu;
@@ -248,7 +248,7 @@ snd_emux_ioctl_seq_oss(snd_seq_oss_arg_t *arg, unsigned int cmd, unsigned long i
 	snd_emux_t *emu;
 
 	snd_assert(arg != NULL, return -ENXIO);
-	p = snd_magic_cast(snd_emux_port_t, arg->private_data, return -EINVAL);
+	p = arg->private_data;
 	snd_assert(p != NULL, return -ENXIO);
 
 	emu = p->emu;
@@ -278,7 +278,7 @@ snd_emux_reset_seq_oss(snd_seq_oss_arg_t *arg)
 	snd_emux_port_t *p;
 
 	snd_assert(arg != NULL, return -ENXIO);
-	p = snd_magic_cast(snd_emux_port_t, arg->private_data, return -EINVAL);
+	p = arg->private_data;
 	snd_assert(p != NULL, return -ENXIO);
 	snd_emux_reset_port(p);
 	return 0;
@@ -296,7 +296,7 @@ snd_emux_event_oss_input(snd_seq_event_t *ev, int direct, void *private_data,
 	snd_emux_port_t *p;
 	unsigned char cmd, *data;
 
-	p = snd_magic_cast(snd_emux_port_t, private_data, return -EINVAL);
+	p = private_data;
 	snd_assert(p != NULL, return -EINVAL);
 	emu = p->emu;
 	snd_assert(emu != NULL, return -EINVAL);
@@ -339,9 +339,11 @@ emuspec_control(snd_emux_t *emu, snd_emux_port_t *port, int cmd,
 	p2 = *(short *) &event[6];
 
 	switch (cmd) {
+#if 0 /* don't do this atomically */
 	case _EMUX_OSS_REMOVE_LAST_SAMPLES:
 		snd_soundfont_remove_unlocked(emu->sflist);
 		break;
+#endif
 	case _EMUX_OSS_SEND_EFFECT:
 		if (chan)
 			snd_emux_send_effect_oss(port, chan, p1, p2);
diff --git a/sound/synth/emux/emux_proc.c b/sound/synth/emux/emux_proc.c
index b67bb3986..0f155d68d 100644
--- a/sound/synth/emux/emux_proc.c
+++ b/sound/synth/emux/emux_proc.c
@@ -36,7 +36,7 @@ snd_emux_proc_info_read(snd_info_entry_t *entry,
 	snd_emux_t *emu;
 	int i;
 
-	emu = snd_magic_cast(snd_emux_t, entry->private_data, return);
+	emu = entry->private_data;
 	down(&emu->register_mutex);
 	if (emu->name)
 		snd_iprintf(buf, "Device: %s\n", emu->name);
diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c
index 973b4d60f..4b9172200 100644
--- a/sound/synth/emux/emux_seq.c
+++ b/sound/synth/emux/emux_seq.c
@@ -146,14 +146,14 @@ snd_emux_create_port(snd_emux_t *emu, char *name,
 	int i, type, cap;
 
 	/* Allocate structures for this channel */
-	if ((p = snd_magic_kcalloc(snd_emux_port_t, 0, GFP_KERNEL)) == NULL) {
+	if ((p = kcalloc(1, sizeof(*p), GFP_KERNEL)) == NULL) {
 		snd_printk("no memory\n");
 		return NULL;
 	}
-	p->chset.channels = snd_kcalloc(max_channels * sizeof(snd_midi_channel_t), GFP_KERNEL);
+	p->chset.channels = kcalloc(max_channels, sizeof(snd_midi_channel_t), GFP_KERNEL);
 	if (p->chset.channels == NULL) {
 		snd_printk("no memory\n");
-		snd_magic_kfree(p);
+		kfree(p);
 		return NULL;
 	}
 	for (i = 0; i < max_channels; i++)
@@ -192,14 +192,14 @@ free_port(void *private_data)
 {
 	snd_emux_port_t *p;
 
-	p = snd_magic_cast(snd_emux_port_t, private_data, return);
+	p = private_data;
 	if (p) {
 #ifdef SNDRV_EMUX_USE_RAW_EFFECT
 		snd_emux_delete_effect(p);
 #endif
 		if (p->chset.channels)
 			kfree(p->chset.channels);
-		snd_magic_kfree(p);
+		kfree(p);
 	}
 }
 
@@ -257,7 +257,7 @@ snd_emux_event_input(snd_seq_event_t *ev, int direct, void *private_data,
 {
 	snd_emux_port_t *port;
 
-	port = snd_magic_cast(snd_emux_port_t, private_data, return -EINVAL);
+	port = private_data;
 	snd_assert(port != NULL && ev != NULL, return -EINVAL);
 
 	snd_midi_process_event(&emux_ops, ev, &port->chset);
@@ -308,7 +308,7 @@ snd_emux_use(void *private_data, snd_seq_port_subscribe_t *info)
 	snd_emux_port_t *p;
 	snd_emux_t *emu;
 
-	p = snd_magic_cast(snd_emux_port_t, private_data, return -EINVAL);
+	p = private_data;
 	snd_assert(p != NULL, return -EINVAL);
 	emu = p->emu;
 	snd_assert(emu != NULL, return -EINVAL);
@@ -329,7 +329,7 @@ snd_emux_unuse(void *private_data, snd_seq_port_subscribe_t *info)
 	snd_emux_port_t *p;
 	snd_emux_t *emu;
 
-	p = snd_magic_cast(snd_emux_port_t, private_data, return -EINVAL);
+	p = private_data;
 	snd_assert(p != NULL, return -EINVAL);
 	emu = p->emu;
 	snd_assert(emu != NULL, return -EINVAL);
@@ -383,7 +383,7 @@ int snd_emux_init_virmidi(snd_emux_t *emu, snd_card_t *card)
 	if (emu->midi_ports <= 0)
 		return 0;
 
-	emu->vmidi = snd_kcalloc(sizeof(snd_rawmidi_t*) * emu->midi_ports, GFP_KERNEL);
+	emu->vmidi = kcalloc(emu->midi_ports, sizeof(snd_rawmidi_t*), GFP_KERNEL);
 	if (emu->vmidi == NULL)
 		return -ENOMEM;
 
@@ -392,7 +392,7 @@ int snd_emux_init_virmidi(snd_emux_t *emu, snd_card_t *card)
 		snd_virmidi_dev_t *rdev;
 		if (snd_virmidi_new(card, emu->midi_devidx + i, &rmidi) < 0)
 			goto __error;
-		rdev = snd_magic_cast(snd_virmidi_dev_t, rmidi->private_data, continue);
+		rdev = rmidi->private_data;
 		sprintf(rmidi->name, "%s Synth MIDI", emu->name);
 		rdev->seq_mode = SNDRV_VIRMIDI_SEQ_ATTACH;
 		rdev->client = emu->client;
diff --git a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c
index 15c7f2d7f..0fe8cac75 100644
--- a/sound/synth/emux/emux_synth.c
+++ b/sound/synth/emux/emux_synth.c
@@ -61,7 +61,7 @@ snd_emux_note_on(void *p, int note, int vel, snd_midi_channel_t *chan)
 	unsigned long flags;
 	snd_emux_port_t *port;
 
-	port = snd_magic_cast(snd_emux_port_t, p, return);
+	port = p;
 	snd_assert(port != NULL && chan != NULL, return);
 
 	emu = port->emu;
@@ -160,7 +160,7 @@ snd_emux_note_off(void *p, int note, int vel, snd_midi_channel_t *chan)
 	unsigned long flags;
 	snd_emux_port_t *port;
 
-	port = snd_magic_cast(snd_emux_port_t, p, return);
+	port = p;
 	snd_assert(port != NULL && chan != NULL, return);
 
 	emu = port->emu;
@@ -201,7 +201,7 @@ snd_emux_note_off(void *p, int note, int vel, snd_midi_channel_t *chan)
  */
 void snd_emux_timer_callback(unsigned long data)
 {
-	snd_emux_t *emu = snd_magic_cast(snd_emux_t, (void*)data, return);
+	snd_emux_t *emu = (snd_emux_t*) data;
 	snd_emux_voice_t *vp;
 	int ch, do_again = 0;
 
@@ -238,7 +238,7 @@ snd_emux_key_press(void *p, int note, int vel, snd_midi_channel_t *chan)
 	unsigned long flags;
 	snd_emux_port_t *port;
 
-	port = snd_magic_cast(snd_emux_port_t, p, return);
+	port = p;
 	snd_assert(port != NULL && chan != NULL, return);
 
 	emu = port->emu;
@@ -322,7 +322,7 @@ snd_emux_control(void *p, int type, snd_midi_channel_t *chan)
 {
 	snd_emux_port_t *port;
 
-	port = snd_magic_cast(snd_emux_port_t, p, return);
+	port = p;
 	snd_assert(port != NULL && chan != NULL, return);
 
 	switch (type) {
@@ -402,7 +402,7 @@ snd_emux_terminate_note(void *p, int note, snd_midi_channel_t *chan)
 	snd_emux_t *emu;
 	snd_emux_port_t *port;
 
-	port = snd_magic_cast(snd_emux_port_t, p, return);
+	port = p;
 	snd_assert(port != NULL && chan != NULL, return);
 
 	emu = port->emu;
diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c
index 8db2e2db5..161620230 100644
--- a/sound/synth/emux/soundfont.c
+++ b/sound/synth/emux/soundfont.c
@@ -64,15 +64,14 @@ static void snd_sf_clear(snd_sf_list_t *sflist);
 /*
  * lock access to sflist
  */
-static int
-lock_preset(snd_sf_list_t *sflist, int nonblock)
+static void
+lock_preset(snd_sf_list_t *sflist)
 {
-	if (nonblock) {
-		if (down_trylock(&sflist->presets_mutex))
-			return -EBUSY;
-	} else 
-		down(&sflist->presets_mutex);
-	return 0;
+	unsigned long flags;
+	down(&sflist->presets_mutex);
+	spin_lock_irqsave(&sflist->lock, flags);
+	sflist->presets_locked = 1;
+	spin_unlock_irqrestore(&sflist->lock, flags);
 }
 
 
@@ -82,6 +81,10 @@ lock_preset(snd_sf_list_t *sflist, int nonblock)
 static void
 unlock_preset(snd_sf_list_t *sflist)
 {
+	unsigned long flags;
+	spin_lock_irqsave(&sflist->lock, flags);
+	sflist->presets_locked = 0;
+	spin_unlock_irqrestore(&sflist->lock, flags);
 	up(&sflist->presets_mutex);
 }
 
@@ -143,7 +146,7 @@ snd_soundfont_load(snd_sf_list_t *sflist, const void __user *data, long count, i
 
 	if (patch.type == SNDRV_SFNT_OPEN_PATCH) {
 		/* grab sflist to open */
-		lock_preset(sflist, 0);
+		lock_preset(sflist);
 		rc = open_patch(sflist, data, count, client);
 		unlock_preset(sflist);
 		return rc;
@@ -157,7 +160,7 @@ snd_soundfont_load(snd_sf_list_t *sflist, const void __user *data, long count, i
 	}
 	spin_unlock_irqrestore(&sflist->lock, flags);
 
-	lock_preset(sflist, 0);
+	lock_preset(sflist);
 	rc = -EINVAL;
 	switch (patch.type) {
 	case SNDRV_SFNT_LOAD_INFO:
@@ -237,8 +240,10 @@ open_patch(snd_sf_list_t *sflist, const char __user *data, int count, int client
 		return -ENOMEM;
 	}
 
+	spin_lock_irqsave(&sflist->lock, flags);
 	sflist->open_client = client;
 	sflist->currsf = sf;
+	spin_unlock_irqrestore(&sflist->lock, flags);
 
 	return 0;
 }
@@ -261,7 +266,7 @@ newsf(snd_sf_list_t *sflist, int type, char *name)
 	}
 
 	/* not found -- create a new one */
-	sf = (snd_soundfont_t*)snd_kcalloc(sizeof(*sf), GFP_KERNEL);
+	sf = kcalloc(1, sizeof(*sf), GFP_KERNEL);
 	if (sf == NULL)
 		return NULL;
 	sf->id = sflist->fonts_size;
@@ -296,8 +301,12 @@ is_identical_font(snd_soundfont_t *sf, int type, unsigned char *name)
 static int
 close_patch(snd_sf_list_t *sflist)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&sflist->lock, flags);
 	sflist->currsf = NULL;
 	sflist->open_client = -1;
+	spin_unlock_irqrestore(&sflist->lock, flags);
 
 	rebuild_presets(sflist);
 
@@ -337,7 +346,7 @@ sf_zone_new(snd_sf_list_t *sflist, snd_soundfont_t *sf)
 {
 	snd_sf_zone_t *zp;
 
-	if ((zp = snd_kcalloc(sizeof(*zp), GFP_KERNEL)) == NULL)
+	if ((zp = kcalloc(1, sizeof(*zp), GFP_KERNEL)) == NULL)
 		return NULL;
 	zp->next = sf->zones;
 	sf->zones = zp;
@@ -368,7 +377,7 @@ sf_sample_new(snd_sf_list_t *sflist, snd_soundfont_t *sf)
 {
 	snd_sf_sample_t *sp;
 
-	if ((sp = snd_kcalloc(sizeof(*sp), GFP_KERNEL)) == NULL)
+	if ((sp = kcalloc(1, sizeof(*sp), GFP_KERNEL)) == NULL)
 		return NULL;
 
 	sp->next = sf->samples;
@@ -1090,7 +1099,7 @@ snd_soundfont_load_guspatch(snd_sf_list_t *sflist, const char __user *data,
 			    long count, int client)
 {
 	int rc;
-	lock_preset(sflist, 0);
+	lock_preset(sflist);
 	rc = load_guspatch(sflist, data, count, client);
 	unlock_preset(sflist);
 	return rc;
@@ -1197,17 +1206,23 @@ snd_soundfont_search_zone(snd_sf_list_t *sflist, int *notep, int vel,
 			  snd_sf_zone_t **table, int max_layers)
 {
 	int nvoices;
+	unsigned long flags;
 
-	if (lock_preset(sflist, 1))
+	/* this function is supposed to be called atomically,
+	 * so we check the lock.  if it's busy, just returns 0 to
+	 * tell the caller the busy state
+	 */
+	spin_lock_irqsave(&sflist->lock, flags);
+	if (sflist->presets_locked) {
+		spin_unlock_irqrestore(&sflist->lock, flags);
 		return 0;
-
+	}
 	nvoices = search_zones(sflist, notep, vel, preset, bank, table, max_layers, 0);
 	if (! nvoices) {
 		if (preset != def_preset || bank != def_bank)
 			nvoices = search_zones(sflist, notep, vel, def_preset, def_bank, table, max_layers, 0);
 	}
-	unlock_preset(sflist);
-
+	spin_unlock_irqrestore(&sflist->lock, flags);
 	return nvoices;
 }
 
@@ -1347,7 +1362,7 @@ snd_sf_new(snd_sf_callback_t *callback, snd_util_memhdr_t *hdr)
 {
 	snd_sf_list_t *sflist;
 
-	if ((sflist = snd_kcalloc(sizeof(snd_sf_list_t), GFP_KERNEL)) == NULL)
+	if ((sflist = kcalloc(1, sizeof(*sflist), GFP_KERNEL)) == NULL)
 		return NULL;
 
 	init_MUTEX(&sflist->presets_mutex);
@@ -1371,7 +1386,7 @@ snd_sf_free(snd_sf_list_t *sflist)
 	if (sflist == NULL)
 		return;
 	
-	lock_preset(sflist, 0);
+	lock_preset(sflist);
 	if (sflist->callback.sample_reset)
 		sflist->callback.sample_reset(sflist->callback.private_data);
 	snd_sf_clear(sflist);
@@ -1387,7 +1402,7 @@ snd_sf_free(snd_sf_list_t *sflist)
 int
 snd_soundfont_remove_samples(snd_sf_list_t *sflist)
 {
-	lock_preset(sflist, 0);
+	lock_preset(sflist);
 	if (sflist->callback.sample_reset)
 		sflist->callback.sample_reset(sflist->callback.private_data);
 	snd_sf_clear(sflist);
@@ -1407,8 +1422,7 @@ snd_soundfont_remove_unlocked(snd_sf_list_t *sflist)
 	snd_sf_zone_t *zp, *nextzp;
 	snd_sf_sample_t *sp, *nextsp;
 
-	if (lock_preset(sflist, 1))
-		return -EBUSY;
+	lock_preset(sflist);
 
 	if (sflist->callback.sample_reset)
 		sflist->callback.sample_reset(sflist->callback.private_data);
diff --git a/sound/synth/util_mem.c b/sound/synth/util_mem.c
index 00679af00..8b131a11e 100644
--- a/sound/synth/util_mem.c
+++ b/sound/synth/util_mem.c
@@ -38,7 +38,7 @@ snd_util_memhdr_new(int memsize)
 {
 	snd_util_memhdr_t *hdr;
 
-	hdr = snd_kcalloc(sizeof(*hdr), GFP_KERNEL);
+	hdr = kcalloc(1, sizeof(*hdr), GFP_KERNEL);
 	if (hdr == NULL)
 		return NULL;
 	hdr->size = memsize;
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index b697649bc..934ead068 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -11,5 +11,15 @@ config SND_USB_AUDIO
 	help
 	  Say 'Y' or 'M' to include support for USB audio and USB MIDI devices.
 
+config SND_USB_USX2Y
+	tristate "Tascam US-122, US-224 and US-428 USB driver"
+	depends on SND && USB
+	select SND_HWDEP
+	select SND_RAWMIDI
+	select SND_PCM
+	help
+	  Say 'Y' or 'M' to include support for Tascam USB Audio/MIDI 
+	  interfaces or controllers US-122, US-224 and US-428.
+
 endmenu
 
diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index 6579582d2..2c1dc11a7 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -2,7 +2,11 @@
 # Makefile for ALSA
 #
 
-snd-usb-audio-objs := usbaudio.o usbmixer.o usbmidi.o
+snd-usb-audio-objs := usbaudio.o usbmixer.o
+snd-usb-lib-objs := usbmidi.o
 
 # Toplevel Module Dependency
-obj-$(CONFIG_SND_USB_AUDIO) += snd-usb-audio.o
+obj-$(CONFIG_SND_USB_AUDIO) += snd-usb-audio.o snd-usb-lib.o
+obj-$(CONFIG_SND_USB_USX2Y) += snd-usb-lib.o
+
+obj-$(CONFIG_SND) += usx2y/
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 6d5197c93..1f3548c5d 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -5,7 +5,7 @@
  *
  *   Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
  *
- *   Many codes borrowed from audio.c by 
+ *   Many codes borrowed from audio.c by
  *	    Alan Cox (alan@lxorguk.ukuu.org.uk)
  *	    Thomas Sailer (sailer@ife.ee.ethz.ch)
  *
@@ -58,8 +58,7 @@
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("USB Audio");
 MODULE_LICENSE("GPL");
-MODULE_CLASSES("{sound}");
-MODULE_DEVICES("{{Generic,USB Audio}}");
+MODULE_SUPPORTED_DEVICE("{{Generic,USB Audio}}");
 
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
@@ -73,25 +72,18 @@ static int boot_devs;
 
 module_param_array(index, int, boot_devs, 0444);
 MODULE_PARM_DESC(index, "Index value for the USB audio adapter.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
 module_param_array(id, charp, boot_devs, 0444);
 MODULE_PARM_DESC(id, "ID string for the USB audio adapter.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
 module_param_array(enable, bool, boot_devs, 0444);
 MODULE_PARM_DESC(enable, "Enable USB audio adapter.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
 module_param_array(vid, int, boot_devs, 0444);
 MODULE_PARM_DESC(vid, "Vendor ID for the USB audio device.");
-MODULE_PARM_SYNTAX(vid, SNDRV_ENABLED ",allows:{{-1,0xffff}},base:16");
 module_param_array(pid, int, boot_devs, 0444);
 MODULE_PARM_DESC(pid, "Product ID for the USB audio device.");
-MODULE_PARM_SYNTAX(pid, SNDRV_ENABLED ",allows:{{-1,0xffff}},base:16");
 module_param(nrpacks, int, 0444);
 MODULE_PARM_DESC(nrpacks, "Max. number of packets per URB.");
-MODULE_PARM_SYNTAX(nrpacks, SNDRV_ENABLED ",allows:{{1,10}}");
 module_param(async_unlink, bool, 0444);
 MODULE_PARM_DESC(async_unlink, "Use async unlink mode.");
-MODULE_PARM_SYNTAX(async_unlink, SNDRV_BOOLEAN_TRUE_DESC);
 
 
 /*
@@ -104,7 +96,7 @@ MODULE_PARM_SYNTAX(async_unlink, SNDRV_BOOLEAN_TRUE_DESC);
  *
  */
 
-#define MAX_PACKS	10	
+#define MAX_PACKS	10
 #define MAX_PACKS_HS	(MAX_PACKS * 8)	/* in high speed mode */
 #define MAX_URBS	5	/* max. 20ms long packets */
 #define SYNC_URBS	2	/* always two urbs for sync */
@@ -207,8 +199,6 @@ struct snd_usb_stream {
 	struct list_head list;
 };
 
-#define chip_t snd_usb_stream_t
-
 
 /*
  * we keep the snd_usb_audio_t instances by ourselves for merging
@@ -354,7 +344,7 @@ static int prepare_capture_urb(snd_usb_substream_t *subs,
 	if (! urb->bandwidth) {
 		int bustime;
 		bustime = usb_check_bandwidth(urb->dev, urb);
-		if (bustime < 0) 
+		if (bustime < 0)
 			return bustime;
 		printk("urb %d: bandwidth = %d (packets = %d)\n", ctx->index, bustime, urb->number_of_packets);
 		usb_claim_bandwidth(urb->dev, urb, bustime, 1);
@@ -826,7 +816,7 @@ static int start_urbs(snd_usb_substream_t *subs, snd_pcm_runtime_t *runtime)
 }
 
 
-/* 
+/*
  *  wait until all urbs are processed.
  */
 static int wait_clear_urbs(snd_usb_substream_t *subs)
@@ -1148,7 +1138,7 @@ static int init_usb_pitch(struct usb_device *dev, int iface,
 	if (fmt->attributes & EP_CS_ATTR_PITCH_CONTROL) {
 		data[0] = 1;
 		if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR,
-					   USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
+					   USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
 					   PITCH_CONTROL << 8, ep, data, 1, HZ)) < 0) {
 			snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH\n",
 				   dev->devnum, iface, ep);
@@ -1174,7 +1164,7 @@ static int init_usb_sample_rate(struct usb_device *dev, int iface,
 		data[1] = rate >> 8;
 		data[2] = rate >> 16;
 		if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR,
-					   USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
+					   USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
 					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
 			snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep 0x%x\n",
 				   dev->devnum, iface, fmt->altsetting, rate, ep);
@@ -1183,9 +1173,9 @@ static int init_usb_sample_rate(struct usb_device *dev, int iface,
 		if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR,
 					   USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
 					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
-			snd_printk(KERN_ERR "%d:%d:%d: cannot get freq at ep 0x%x\n",
+			snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep 0x%x\n",
 				   dev->devnum, iface, fmt->altsetting, ep);
-			return err;
+			return 0; /* some devices don't support reading */
 		}
 		crate = data[0] | (data[1] << 8) | (data[2] << 16);
 		if (crate != rate) {
@@ -1323,7 +1313,7 @@ static int snd_usb_hw_params(snd_pcm_substream_t *substream,
 	ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
 	if (ret < 0)
 		return ret;
-	
+
 	format = params_format(hw_params);
 	rate = params_rate(hw_params);
 	channels = params_channels(hw_params);
@@ -1482,7 +1472,7 @@ static int hw_rule_rate(snd_pcm_hw_params_t *params,
 	snd_interval_t *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
 	unsigned int rmin, rmax;
 	int changed;
-	
+
 	hwc_debug("hw_rule_rate: (%d,%d)\n", it->min, it->max);
 	changed = 0;
 	rmin = rmax = 0;
@@ -1536,7 +1526,7 @@ static int hw_rule_channels(snd_pcm_hw_params_t *params,
 	snd_interval_t *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
 	unsigned int rmin, rmax;
 	int changed;
-	
+
 	hwc_debug("hw_rule_channels: (%d,%d)\n", it->min, it->max);
 	changed = 0;
 	rmin = rmax = 0;
@@ -1590,7 +1580,7 @@ static int hw_rule_format(snd_pcm_hw_params_t *params,
 	u64 fbits;
 	u32 oldbits[2];
 	int changed;
-	
+
 	hwc_debug("hw_rule_format: %x:%x\n", fmt->bits[0], fmt->bits[1]);
 	fbits = 0;
 	list_for_each(p, &subs->fmt_list) {
@@ -1734,13 +1724,13 @@ static int setup_hw_info(snd_pcm_runtime_t *runtime, snd_usb_substream_t *subs)
 
 	if (check_hw_params_convention(subs)) {
 		hwc_debug("setting extra hw constraints...\n");
-		if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 
+		if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
 					       hw_rule_rate, subs,
 					       SNDRV_PCM_HW_PARAM_FORMAT,
 					       SNDRV_PCM_HW_PARAM_CHANNELS,
 					       -1)) < 0)
 			return err;
-		if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 
+		if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
 					       hw_rule_channels, subs,
 					       SNDRV_PCM_HW_PARAM_FORMAT,
 					       SNDRV_PCM_HW_PARAM_RATE,
@@ -2001,8 +1991,8 @@ static void proc_dump_substream_status(snd_usb_substream_t *subs, snd_info_buffe
 
 static void proc_pcm_format_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
 {
-	snd_usb_stream_t *stream = snd_magic_cast(snd_usb_stream_t, entry->private_data, return);
-	
+	snd_usb_stream_t *stream = entry->private_data;
+
 	snd_iprintf(buffer, "%s : %s\n", stream->chip->card->longname, stream->pcm->name);
 
 	if (stream->substream[SNDRV_PCM_STREAM_PLAYBACK].num_formats) {
@@ -2089,7 +2079,7 @@ static void snd_usb_audio_stream_free(snd_usb_stream_t *stream)
 	free_substream(&stream->substream[0]);
 	free_substream(&stream->substream[1]);
 	list_del(&stream->list);
-	snd_magic_kfree(stream);
+	kfree(stream);
 }
 
 static void snd_usb_audio_pcm_free(snd_pcm_t *pcm)
@@ -2146,7 +2136,7 @@ static int add_audio_endpoint(snd_usb_audio_t *chip, int stream, struct audiofor
 	}
 
 	/* create a new pcm */
-	as = snd_magic_kmalloc(snd_usb_stream_t, 0, GFP_KERNEL);
+	as = kmalloc(sizeof(*as), GFP_KERNEL);
 	if (! as)
 		return -ENOMEM;
 	memset(as, 0, sizeof(*as));
@@ -2158,13 +2148,13 @@ static int add_audio_endpoint(snd_usb_audio_t *chip, int stream, struct audiofor
 			  stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1,
 			  &pcm);
 	if (err < 0) {
-		snd_magic_kfree(as);
+		kfree(as);
 		return err;
 	}
 	as->pcm = pcm;
 	pcm->private_data = as;
 	pcm->private_free = snd_usb_audio_pcm_free;
-	pcm->info_flags = SNDRV_PCM_INFO_NONATOMIC_OPS;
+	pcm->info_flags = 0;
 	if (chip->pcm_devs > 0)
 		sprintf(pcm->name, "USB Audio #%d", chip->pcm_devs);
 	else
@@ -2181,6 +2171,24 @@ static int add_audio_endpoint(snd_usb_audio_t *chip, int stream, struct audiofor
 }
 
 
+/*
+ * check if the device uses big-endian samples
+ */
+static int is_big_endian_format(struct usb_device *dev, struct audioformat *fp)
+{
+	/* M-Audio */
+	if (dev->descriptor.idVendor == 0x0763) {
+		/* Quattro: captured data only */
+		if (dev->descriptor.idProduct == 0x2001 &&
+		    fp->endpoint & USB_DIR_IN)
+			return 1;
+		/* Audiophile USB */
+		if (dev->descriptor.idProduct == 0x2003)
+			return 1;
+	}
+	return 0;
+}
+
 /*
  * parse the audio format type I descriptor
  * and returns the corresponding pcm format
@@ -2217,17 +2225,13 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat
 			pcm_format = SNDRV_PCM_FORMAT_S8;
 			break;
 		case 2:
-			/* M-Audio audiophile USB workaround */
-			if (dev->descriptor.idVendor == 0x0763 &&
-			    dev->descriptor.idProduct == 0x2003)
+			if (is_big_endian_format(dev, fp))
 				pcm_format = SNDRV_PCM_FORMAT_S16_BE; /* grrr, big endian!! */
 			else
 				pcm_format = SNDRV_PCM_FORMAT_S16_LE;
 			break;
 		case 3:
-			/* M-Audio audiophile USB workaround */
-			if (dev->descriptor.idVendor == 0x0763 &&
-			    dev->descriptor.idProduct == 0x2003)
+			if (is_big_endian_format(dev, fp))
 				pcm_format = SNDRV_PCM_FORMAT_S24_3BE; /* grrr, big endian!! */
 			else
 				pcm_format = SNDRV_PCM_FORMAT_S24_3LE;
@@ -2281,7 +2285,7 @@ static int parse_audio_format_rates(struct usb_device *dev, struct audioformat *
 {
 	int nr_rates = fmt[offset];
 	if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) {
-		snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n", 
+		snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n",
 				   dev->devnum, fp->iface, fp->altsetting);
 		return -1;
 	}
@@ -2419,7 +2423,7 @@ static int parse_audio_format(struct usb_device *dev, struct audioformat *fp,
 	}
 #endif
 	return 0;
-}	
+}
 
 static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no)
 {
@@ -2465,22 +2469,22 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no)
 		}
 
 		if (fmt[0] < 7) {
-			snd_printk(KERN_ERR "%d:%u:%d : invalid AS_GENERAL desc\n", 
+			snd_printk(KERN_ERR "%d:%u:%d : invalid AS_GENERAL desc\n",
 				   dev->devnum, iface_no, altno);
 			continue;
 		}
 
 		format = (fmt[6] << 8) | fmt[5]; /* remember the format value */
-			
+
 		/* get format type */
 		fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, FORMAT_TYPE);
 		if (!fmt) {
-			snd_printk(KERN_ERR "%d:%u:%d : no FORMAT_TYPE desc\n", 
+			snd_printk(KERN_ERR "%d:%u:%d : no FORMAT_TYPE desc\n",
 				   dev->devnum, iface_no, altno);
 			continue;
 		}
 		if (fmt[0] < 8) {
-			snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n", 
+			snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n",
 				   dev->devnum, iface_no, altno);
 			continue;
 		}
@@ -2490,7 +2494,7 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no)
 		if (!csep && altsd->bNumEndpoints >= 2)
 			csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT);
 		if (!csep || csep[0] < 7 || csep[2] != EP_GENERAL) {
-			snd_printk(KERN_ERR "%d:%u:%d : no or invalid class specific endpoint descriptor\n", 
+			snd_printk(KERN_ERR "%d:%u:%d : no or invalid class specific endpoint descriptor\n",
 				   dev->devnum, iface_no, altno);
 			continue;
 		}
@@ -2920,14 +2924,14 @@ static int snd_usb_create_quirk(snd_usb_audio_t *chip,
  */
 static void proc_audio_usbbus_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
 {
-	snd_usb_audio_t *chip = snd_magic_cast(snd_usb_audio_t, entry->private_data, return);
+	snd_usb_audio_t *chip = entry->private_data;
 	if (! chip->shutdown)
 		snd_iprintf(buffer, "%03d/%03d\n", chip->dev->bus->busnum, chip->dev->devnum);
 }
 
 static void proc_audio_usbid_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
 {
-	snd_usb_audio_t *chip = snd_magic_cast(snd_usb_audio_t, entry->private_data, return);
+	snd_usb_audio_t *chip = entry->private_data;
 	if (! chip->shutdown)
 		snd_iprintf(buffer, "%04x:%04x\n", chip->dev->descriptor.idVendor, chip->dev->descriptor.idProduct);
 }
@@ -2950,13 +2954,13 @@ static void snd_usb_audio_create_proc(snd_usb_audio_t *chip)
 
 static int snd_usb_audio_free(snd_usb_audio_t *chip)
 {
-	snd_magic_kfree(chip);
+	kfree(chip);
 	return 0;
 }
 
 static int snd_usb_audio_dev_free(snd_device_t *device)
 {
-	snd_usb_audio_t *chip = snd_magic_cast(snd_usb_audio_t, device->device_data, return -ENXIO);
+	snd_usb_audio_t *chip = device->device_data;
 	return snd_usb_audio_free(chip);
 }
 
@@ -2975,7 +2979,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
 	static snd_device_ops_t ops = {
 		.dev_free =	snd_usb_audio_dev_free,
 	};
-	
+
 	*rchip = NULL;
 
 	if (snd_usb_get_speed(dev) != USB_SPEED_FULL &&
@@ -2990,7 +2994,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
 		return -ENOMEM;
 	}
 
-	chip = snd_magic_kcalloc(snd_usb_audio_t, 0, GFP_KERNEL);
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
 	if (! chip) {
 		snd_card_free(card);
 		return -ENOMEM;
@@ -3171,7 +3175,7 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
 
 /*
  * we need to take care of counter, since disconnection can be called also
- * many times as well as usb_audio_probe(). 
+ * many times as well as usb_audio_probe().
  */
 static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr)
 {
@@ -3182,7 +3186,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr)
 	if (ptr == (void *)-1L)
 		return;
 
-	chip = snd_magic_cast(snd_usb_audio_t, ptr, return);
+	chip = ptr;
 	card = chip->card;
 	down(&register_mutex);
 	chip->shutdown = 1;
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 2fe29989e..627a40235 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -124,7 +124,6 @@
 typedef struct snd_usb_audio snd_usb_audio_t;
 
 struct snd_usb_audio {
-	
 	int index;
 	struct usb_device *dev;
 	snd_card_t *card;
@@ -138,15 +137,17 @@ struct snd_usb_audio {
 	int next_midi_device;
 
 	unsigned int ignore_ctl_error;	/* for mixer */
-};  
+};
 
 /*
  * Information about devices with broken descriptors
  */
 
+/* special values for .ifnum */
 #define QUIRK_NO_INTERFACE		-2
 #define QUIRK_ANY_INTERFACE		-1
 
+/* quirk type */
 #define QUIRK_MIDI_FIXED_ENDPOINT	0
 #define QUIRK_MIDI_YAMAHA		1
 #define QUIRK_MIDI_MIDIMAN		2
@@ -205,6 +206,8 @@ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u
 int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif);
 
 int snd_usb_create_midi_interface(snd_usb_audio_t *chip, struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk);
+void snd_usbmidi_input_stop(struct list_head* p);
+void snd_usbmidi_input_start(struct list_head* p);
 void snd_usbmidi_disconnect(struct list_head *p, struct usb_driver *driver);
 
 /*
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index a2f1b5621..96fd06e33 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -49,6 +49,11 @@
 #include <sound/rawmidi.h>
 #include "usbaudio.h"
 
+MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
+MODULE_DESCRIPTION("USB Audio/MIDI helper module");
+MODULE_LICENSE("Dual BSD/GPL");
+
+
 struct usb_ms_header_descriptor {
 	__u8  bLength;
 	__u8  bDescriptorType;
@@ -175,7 +180,7 @@ static void snd_usbmidi_input_packet(snd_usb_midi_in_endpoint_t* ep,
  */
 static void snd_usbmidi_in_urb_complete(struct urb* urb, struct pt_regs *regs)
 {
-	snd_usb_midi_in_endpoint_t* ep = snd_magic_cast(snd_usb_midi_in_endpoint_t, urb->context, return);
+	snd_usb_midi_in_endpoint_t* ep = urb->context;
 
 	if (urb->status == 0) {
 		uint8_t* buffer = (uint8_t*)ep->urb->transfer_buffer;
@@ -229,7 +234,7 @@ static void snd_usbmidi_in_midiman_complete(struct urb* urb, struct pt_regs *reg
 
 static void snd_usbmidi_out_urb_complete(struct urb* urb, struct pt_regs *regs)
 {
-	snd_usb_midi_out_endpoint_t* ep = snd_magic_cast(snd_usb_midi_out_endpoint_t, urb->context, return);
+	snd_usb_midi_out_endpoint_t* ep = urb->context;
 
 	if (urb->status < 0) {
 		if (snd_usbmidi_urb_error(urb->status) < 0)
@@ -393,7 +398,7 @@ static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep)
 	int p;
 	struct urb* urb = ep->urb;
 	unsigned long flags;
-	
+
 	spin_lock_irqsave(&ep->buffer_lock, flags);
 	if (urb->status == -EINPROGRESS || ep->umidi->chip->shutdown) {
 		spin_unlock_irqrestore(&ep->buffer_lock, flags);
@@ -417,14 +422,14 @@ static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep)
 
 static void snd_usbmidi_out_tasklet(unsigned long data)
 {
-	snd_usb_midi_out_endpoint_t* ep = snd_magic_cast(snd_usb_midi_out_endpoint_t, (void*)data, return);
-	
+	snd_usb_midi_out_endpoint_t* ep = (snd_usb_midi_out_endpoint_t *) data;
+
 	snd_usbmidi_do_output(ep);
 }
 
 static int snd_usbmidi_output_open(snd_rawmidi_substream_t* substream)
 {
-	snd_usb_midi_t* umidi = snd_magic_cast(snd_usb_midi_t, substream->rmidi->private_data, return -ENXIO);
+	snd_usb_midi_t* umidi = substream->rmidi->private_data;
 	usbmidi_out_port_t* port = NULL;
 	int i, j;
 
@@ -503,7 +508,7 @@ static void snd_usbmidi_in_endpoint_delete(snd_usb_midi_in_endpoint_t* ep)
 			kfree(ep->urb->transfer_buffer);
 		usb_free_urb(ep->urb);
 	}
-	snd_magic_kfree(ep);
+	kfree(ep);
 }
 
 /*
@@ -571,7 +576,7 @@ static int snd_usbmidi_in_endpoint_create(snd_usb_midi_t* umidi,
 	int length;
 
 	rep->in = NULL;
-	ep = snd_magic_kcalloc(snd_usb_midi_in_endpoint_t, 0, GFP_KERNEL);
+	ep = kcalloc(1, sizeof(*ep), GFP_KERNEL);
 	if (!ep)
 		return -ENOMEM;
 	ep->umidi = umidi;
@@ -631,7 +636,7 @@ static void snd_usbmidi_out_endpoint_delete(snd_usb_midi_out_endpoint_t* ep)
 			kfree(ep->urb->transfer_buffer);
 		usb_free_urb(ep->urb);
 	}
-	snd_magic_kfree(ep);
+	kfree(ep);
 }
 
 /*
@@ -647,7 +652,7 @@ static int snd_usbmidi_out_endpoint_create(snd_usb_midi_t* umidi,
 	void* buffer;
 
 	rep->out = NULL;
-	ep = snd_magic_kcalloc(snd_usb_midi_out_endpoint_t, 0, GFP_KERNEL);
+	ep = kcalloc(1, sizeof(*ep), GFP_KERNEL);
 	if (!ep)
 		return -ENOMEM;
 	ep->umidi = umidi;
@@ -695,7 +700,7 @@ static void snd_usbmidi_free(snd_usb_midi_t* umidi)
 		if (ep->in)
 			snd_usbmidi_in_endpoint_delete(ep->in);
 	}
-	snd_magic_kfree(umidi);
+	kfree(umidi);
 }
 
 /*
@@ -718,7 +723,7 @@ void snd_usbmidi_disconnect(struct list_head* p, struct usb_driver *driver)
 
 static void snd_usbmidi_rawmidi_free(snd_rawmidi_t* rmidi)
 {
-	snd_usb_midi_t* umidi = snd_magic_cast(snd_usb_midi_t, rmidi->private_data, return);
+	snd_usb_midi_t* umidi = rmidi->private_data;
 	snd_usbmidi_free(umidi);
 }
 
@@ -964,7 +969,7 @@ static int snd_usbmidi_get_ms_info(snd_usb_midi_t* umidi,
  * If the endpoints aren't specified, use the first bulk endpoints in the
  * first alternate setting of the interface.
  */
-static int snd_usbmidi_detect_endpoint(snd_usb_midi_t* umidi, 
+static int snd_usbmidi_detect_endpoint(snd_usb_midi_t* umidi,
 				       snd_usb_midi_endpoint_info_t* endpoint)
 {
 	struct usb_interface* intf;
@@ -998,7 +1003,7 @@ static int snd_usbmidi_detect_endpoint(snd_usb_midi_t* umidi,
 /*
  * Detects the endpoints and ports of Yamaha devices.
  */
-static int snd_usbmidi_detect_yamaha(snd_usb_midi_t* umidi, 
+static int snd_usbmidi_detect_yamaha(snd_usb_midi_t* umidi,
 				     snd_usb_midi_endpoint_info_t* endpoint)
 {
 	struct usb_interface* intf;
@@ -1144,6 +1149,44 @@ static int snd_usbmidi_create_rawmidi(snd_usb_midi_t* umidi,
 	return 0;
 }
 
+/*
+ * Temporarily stop input.
+ */
+void snd_usbmidi_input_stop(struct list_head* p)
+{
+	snd_usb_midi_t* umidi;
+	int i;
+
+	umidi = list_entry(p, snd_usb_midi_t, list);
+	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
+		snd_usb_midi_endpoint_t* ep = &umidi->endpoints[i];
+		if (ep->in)
+			usb_unlink_urb(ep->in->urb);
+	}
+}
+
+static void snd_usbmidi_input_start_ep(snd_usb_midi_in_endpoint_t* ep)
+{
+	if (ep) {
+		struct urb* urb = ep->urb;
+		urb->dev = ep->umidi->chip->dev;
+		snd_usbmidi_submit_urb(urb, GFP_KERNEL);
+	}
+}
+
+/*
+ * Resume input after a call to snd_usbmidi_input_stop().
+ */
+void snd_usbmidi_input_start(struct list_head* p)
+{
+	snd_usb_midi_t* umidi;
+	int i;
+
+	umidi = list_entry(p, snd_usb_midi_t, list);
+	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
+		snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
+}
+
 /*
  * Creates and registers everything needed for a MIDI streaming interface.
  */
@@ -1156,7 +1199,7 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
 	int out_ports, in_ports;
 	int i, err;
 
-	umidi = snd_magic_kcalloc(snd_usb_midi_t, 0, GFP_KERNEL);
+	umidi = kcalloc(1, sizeof(*umidi), GFP_KERNEL);
 	if (!umidi)
 		return -ENOMEM;
 	umidi->chip = chip;
@@ -1189,7 +1232,7 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
 		}
 	}
 	if (err < 0) {
-		snd_magic_kfree(umidi);
+		kfree(umidi);
 		return err;
 	}
 
@@ -1202,7 +1245,7 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
 	}
 	err = snd_usbmidi_create_rawmidi(umidi, out_ports, in_ports);
 	if (err < 0) {
-		snd_magic_kfree(umidi);
+		kfree(umidi);
 		return err;
 	}
 
@@ -1219,8 +1262,11 @@ int snd_usb_create_midi_interface(snd_usb_audio_t* chip,
 	list_add(&umidi->list, &umidi->chip->midi_list);
 
 	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
-		if (umidi->endpoints[i].in)
-			snd_usbmidi_submit_urb(umidi->endpoints[i].in->urb,
-					       GFP_KERNEL);
+		snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
 	return 0;
 }
+
+EXPORT_SYMBOL(snd_usb_create_midi_interface);
+EXPORT_SYMBOL(snd_usbmidi_input_stop);
+EXPORT_SYMBOL(snd_usbmidi_input_start);
+EXPORT_SYMBOL(snd_usbmidi_disconnect);
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index 13921f1f1..1d0aa0332 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -5,7 +5,7 @@
  *
  *   Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
  *
- *   Many codes borrowed from audio.c by 
+ *   Many codes borrowed from audio.c by
  *	    Alan Cox (alan@lxorguk.ukuu.org.uk)
  *	    Thomas Sailer (sailer@ife.ee.ethz.ch)
  *
@@ -77,7 +77,7 @@ struct usb_mixer_elem_info {
 	unsigned int ctrlif;
 	unsigned int id;
 	unsigned int control;	/* CS or ICN (high byte) */
-	unsigned int cmask; /* channel mask bitmap: 0 = master */ 
+	unsigned int cmask; /* channel mask bitmap: 0 = master */
 	int channels;
 	int val_type;
 	int min, max, res;
@@ -299,7 +299,7 @@ static int get_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i
 	unsigned char buf[2];
 	int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
 	int timeout = 10;
- 
+
 	while (timeout-- > 0) {
 		if (snd_usb_ctl_msg(cval->chip->dev, usb_rcvctrlpipe(cval->chip->dev, 0),
 				    request,
@@ -334,7 +334,7 @@ static int set_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i
 	unsigned char buf[2];
 	int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
 	int timeout = 10;
- 
+
 	value_set = convert_bytes_value(cval, value_set);
 	buf[0] = value_set & 0xff;
 	buf[1] = (value_set >> 8) & 0xff;
@@ -361,7 +361,7 @@ inline static int set_cur_mix_value(usb_mixer_elem_info_t *cval, int channel, in
 
 
 /*
- * parser routines begin here... 
+ * parser routines begin here...
  */
 
 static int parse_audio_unit(mixer_build_t *state, int unitid);
@@ -443,7 +443,7 @@ static struct iterm_name_combo {
 	{ 0x0712, "Multi-Track Recorder" },
 	{ 0x0713, "Synthesizer" },
 	{ 0 },
-};	
+};
 
 static int get_term_name(mixer_build_t *state, usb_audio_term_t *iterm,
 			 unsigned char *name, int maxlen, int term_only)
@@ -573,7 +573,7 @@ static struct usb_feature_control_info audio_feature_info[] = {
 static void usb_mixer_elem_free(snd_kcontrol_t *kctl)
 {
 	if (kctl->private_data) {
-		snd_magic_kfree((void *)kctl->private_data);
+		kfree((void *)kctl->private_data);
 		kctl->private_data = NULL;
 	}
 }
@@ -615,7 +615,7 @@ static int get_min_max(usb_mixer_elem_info_t *cval, int default_min)
 			cval->res = 1;
 		} else {
 			int last_valid_res = cval->res;
-		
+
 			while (cval->res > 1) {
 				if (set_ctl_value(cval, SET_RES, (cval->control << 8) | minchn, cval->res / 2) < 0)
 					break;
@@ -634,8 +634,8 @@ static int get_min_max(usb_mixer_elem_info_t *cval, int default_min)
 
 /* get a feature/mixer unit info */
 static int mixer_ctl_feature_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
-{	
-	usb_mixer_elem_info_t *cval = snd_magic_cast(usb_mixer_elem_info_t, kcontrol->private_data, return -EINVAL);
+{
+	usb_mixer_elem_info_t *cval = kcontrol->private_data;
 
 	if (cval->val_type == USB_MIXER_BOOLEAN ||
 	    cval->val_type == USB_MIXER_INV_BOOLEAN)
@@ -659,7 +659,7 @@ static int mixer_ctl_feature_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
 /* get the current value from feature/mixer unit */
 static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	usb_mixer_elem_info_t *cval = snd_magic_cast(usb_mixer_elem_info_t, kcontrol->private_data, return -EINVAL);
+	usb_mixer_elem_info_t *cval = kcontrol->private_data;
 	int c, cnt, val, err;
 
 	if (cval->cmask) {
@@ -700,7 +700,7 @@ static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
 /* put the current value to feature/mixer unit */
 static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	usb_mixer_elem_info_t *cval = snd_magic_cast(usb_mixer_elem_info_t, kcontrol->private_data, return -EINVAL);
+	usb_mixer_elem_info_t *cval = kcontrol->private_data;
 	int c, cnt, val, oval, err;
 	int changed = 0;
 
@@ -774,7 +774,7 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc,
 	if (check_ignored_ctl(state, unitid, control))
 		return;
 
-	cval = snd_magic_kcalloc(usb_mixer_elem_info_t, 0, GFP_KERNEL);
+	cval = kcalloc(1, sizeof(*cval), GFP_KERNEL);
 	if (! cval) {
 		snd_printk(KERN_ERR "cannot malloc kcontrol\n");
 		return;
@@ -801,7 +801,7 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc,
 	kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval);
 	if (! kctl) {
 		snd_printk(KERN_ERR "cannot malloc kcontrol\n");
-		snd_magic_kfree(cval);
+		kfree(cval);
 		return;
 	}
 	kctl->private_free = usb_mixer_elem_free;
@@ -914,7 +914,7 @@ static int parse_audio_feature_unit(mixer_build_t *state, int unitid, unsigned c
 		if (master_bits & (1 << i))
 			build_feature_ctl(state, ftr, 0, i, &iterm, unitid);
 	}
-	
+
 	return 0;
 }
 
@@ -943,7 +943,7 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc,
 	if (check_ignored_ctl(state, unitid, 0))
 		return;
 
-	cval = snd_magic_kcalloc(usb_mixer_elem_info_t, 0, GFP_KERNEL);
+	cval = kcalloc(1, sizeof(*cval), GFP_KERNEL);
 	if (! cval)
 		return;
 
@@ -968,7 +968,7 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc,
 	kctl = snd_ctl_new1(&usb_feature_unit_ctl, cval);
 	if (! kctl) {
 		snd_printk(KERN_ERR "cannot malloc kcontrol\n");
-		snd_magic_kfree(cval);
+		kfree(cval);
 		return;
 	}
 	kctl->private_free = usb_mixer_elem_free;
@@ -1014,7 +1014,7 @@ static int parse_audio_mixer_unit(mixer_build_t *state, int unitid, unsigned cha
 /* get callback for processing/extension unit */
 static int mixer_ctl_procunit_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	usb_mixer_elem_info_t *cval = snd_magic_cast(usb_mixer_elem_info_t, kcontrol->private_data, return -EINVAL);
+	usb_mixer_elem_info_t *cval = kcontrol->private_data;
 	int err, val;
 
 	err = get_cur_ctl_value(cval, cval->control << 8, &val);
@@ -1032,7 +1032,7 @@ static int mixer_ctl_procunit_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
 /* put callback for processing/extension unit */
 static int mixer_ctl_procunit_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	usb_mixer_elem_info_t *cval = snd_magic_cast(usb_mixer_elem_info_t, kcontrol->private_data, return -EINVAL);
+	usb_mixer_elem_info_t *cval = kcontrol->private_data;
 	int val, oval, err;
 
 	err = get_cur_ctl_value(cval, cval->control << 8, &oval);
@@ -1170,7 +1170,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char
 			continue;
 		if (check_ignored_ctl(state, unitid, valinfo->control))
 			continue;
-		cval = snd_magic_kcalloc(usb_mixer_elem_info_t, 0, GFP_KERNEL);
+		cval = kcalloc(1, sizeof(*cval), GFP_KERNEL);
 		if (! cval) {
 			snd_printk(KERN_ERR "cannot malloc kcontrol\n");
 			return -ENOMEM;
@@ -1195,7 +1195,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char
 		kctl = snd_ctl_new1(&mixer_procunit_ctl, cval);
 		if (! kctl) {
 			snd_printk(KERN_ERR "cannot malloc kcontrol\n");
-			snd_magic_kfree(cval);
+			kfree(cval);
 			return -ENOMEM;
 		}
 		kctl->private_free = usb_mixer_elem_free;
@@ -1243,8 +1243,8 @@ static int parse_audio_extension_unit(mixer_build_t *state, int unitid, unsigned
  * use an enumerator type for routing
  */
 static int mixer_ctl_selector_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
-{	
-	usb_mixer_elem_info_t *cval = snd_magic_cast(usb_mixer_elem_info_t, kcontrol->private_data, return -EINVAL);
+{
+	usb_mixer_elem_info_t *cval = kcontrol->private_data;
 	char **itemlist = (char **)kcontrol->private_value;
 
 	snd_assert(itemlist, return -EINVAL);
@@ -1260,7 +1260,7 @@ static int mixer_ctl_selector_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
 /* get callback for selector unit */
 static int mixer_ctl_selector_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	usb_mixer_elem_info_t *cval = snd_magic_cast(usb_mixer_elem_info_t, kcontrol->private_data, return -EINVAL);
+	usb_mixer_elem_info_t *cval = kcontrol->private_data;
 	int val, err;
 
 	err = get_cur_ctl_value(cval, 0, &val);
@@ -1279,7 +1279,7 @@ static int mixer_ctl_selector_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
 /* put callback for selector unit */
 static int mixer_ctl_selector_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
-	usb_mixer_elem_info_t *cval = snd_magic_cast(usb_mixer_elem_info_t, kcontrol->private_data, return -EINVAL);
+	usb_mixer_elem_info_t *cval = kcontrol->private_data;
 	int val, oval, err;
 
 	err = get_cur_ctl_value(cval, 0, &oval);
@@ -1315,9 +1315,9 @@ static void usb_mixer_selector_elem_free(snd_kcontrol_t *kctl)
 	int i, num_ins = 0;
 
 	if (kctl->private_data) {
-		usb_mixer_elem_info_t *cval = snd_magic_cast(usb_mixer_elem_info_t, kctl->private_data,);
+		usb_mixer_elem_info_t *cval = kctl->private_data;
 		num_ins = cval->max;
-		snd_magic_kfree(cval);
+		kfree(cval);
 		kctl->private_data = NULL;
 	}
 	if (kctl->private_value) {
@@ -1357,7 +1357,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
 	if (check_ignored_ctl(state, unitid, 0))
 		return 0;
 
-	cval = snd_magic_kcalloc(usb_mixer_elem_info_t, 0, GFP_KERNEL);
+	cval = kcalloc(1, sizeof(*cval), GFP_KERNEL);
 	if (! cval) {
 		snd_printk(KERN_ERR "cannot malloc kcontrol\n");
 		return -ENOMEM;
@@ -1375,7 +1375,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
 	namelist = kmalloc(sizeof(char *) * num_ins, GFP_KERNEL);
 	if (! namelist) {
 		snd_printk(KERN_ERR "cannot malloc\n");
-		snd_magic_kfree(cval);
+		kfree(cval);
 		return -ENOMEM;
 	}
 #define MAX_ITEM_NAME_LEN	64
@@ -1388,7 +1388,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
 			while (--i > 0)
 				kfree(namelist[i]);
 			kfree(namelist);
-			snd_magic_kfree(cval);
+			kfree(cval);
 			return -ENOMEM;
 		}
 		if (check_input_term(state, desc[5 + i], &iterm) >= 0)
@@ -1400,7 +1400,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
 	kctl = snd_ctl_new1(&mixer_selectunit_ctl, cval);
 	if (! kctl) {
 		snd_printk(KERN_ERR "cannot malloc kcontrol\n");
-		snd_magic_kfree(cval);
+		kfree(cval);
 		return -ENOMEM;
 	}
 	kctl->private_value = (unsigned long)namelist;
diff --git a/sound/usb/usbmixer_maps.c b/sound/usb/usbmixer_maps.c
index 05c9756bc..f01947cf0 100644
--- a/sound/usb/usbmixer_maps.c
+++ b/sound/usb/usbmixer_maps.c
@@ -32,7 +32,7 @@ struct usbmix_ctl_map {
 	const struct usbmix_name_map *map;
 	int ignore_ctl_error;
 };
-	
+
 /*
  * USB control mappers for SB Exitigy
  */
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index 889798b2b..9cb6824b0 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -91,6 +91,31 @@ YAMAHA_DEVICE(0x1020, "EZ-250i"),
 YAMAHA_DEVICE(0x1021, "MOTIF ES 6"),
 YAMAHA_DEVICE(0x1022, "MOTIF ES 7"),
 YAMAHA_DEVICE(0x1023, "MOTIF ES 8"),
+YAMAHA_DEVICE(0x1024, "CVP-301"),
+YAMAHA_DEVICE(0x1025, "CVP-303"),
+YAMAHA_DEVICE(0x1026, "CVP-305"),
+YAMAHA_DEVICE(0x1027, "CVP-307"),
+YAMAHA_DEVICE(0x1028, "CVP-309"),
+YAMAHA_DEVICE(0x1029, "CVP-309GP"),
+YAMAHA_DEVICE(0x102a, "PSR-1500"),
+YAMAHA_DEVICE(0x102b, "PSR-3000"),
+YAMAHA_DEVICE(0x102e, "ELS-01/01C"),
+YAMAHA_DEVICE(0x1030, "PSR-295/293"),
+YAMAHA_DEVICE(0x1031, "DGX-205/203"),
+YAMAHA_DEVICE(0x1032, "DGX-305"),
+YAMAHA_DEVICE(0x1033, "DGX-505"),
+YAMAHA_DEVICE(0x1034, NULL),
+YAMAHA_DEVICE(0x1035, NULL),
+YAMAHA_DEVICE(0x1036, NULL),
+YAMAHA_DEVICE(0x1037, NULL),
+YAMAHA_DEVICE(0x1038, NULL),
+YAMAHA_DEVICE(0x1039, NULL),
+YAMAHA_DEVICE(0x103a, NULL),
+YAMAHA_DEVICE(0x103b, NULL),
+YAMAHA_DEVICE(0x103c, NULL),
+YAMAHA_DEVICE(0x2000, "DGP-7"),
+YAMAHA_DEVICE(0x2001, "DGP-5"),
+YAMAHA_DEVICE(0x2002, NULL),
 YAMAHA_DEVICE(0x5000, "CS1D"),
 YAMAHA_DEVICE(0x5001, "DSP1D"),
 YAMAHA_DEVICE(0x5002, "DME32"),
@@ -100,6 +125,11 @@ YAMAHA_DEVICE(0x5005, "ACU16-C"),
 YAMAHA_DEVICE(0x5006, "NHB32-C"),
 YAMAHA_DEVICE(0x5007, "DM1000"),
 YAMAHA_DEVICE(0x5008, "01V96"),
+YAMAHA_DEVICE(0x500a, "PM5D"),
+YAMAHA_DEVICE(0x500b, "DME64N"),
+YAMAHA_DEVICE(0x500c, "DME24N"),
+YAMAHA_DEVICE(0x7000, "DTX"),
+YAMAHA_DEVICE(0x7010, "UB99"),
 #undef YAMAHA_DEVICE
 #undef YAMAHA_INTERFACE
 
@@ -267,7 +297,8 @@ YAMAHA_DEVICE(0x5008, "01V96"),
 	}
 },
 {
-	/* thanks to Emiliano Grilli <emillo@libero.it> for helping researching this data */
+	/* thanks to Emiliano Grilli <emillo@libero.it>
+	 * for helping researching this data */
 	USB_DEVICE(0x0582, 0x000c),
 	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
 		.vendor_name = "Roland",
@@ -830,11 +861,42 @@ YAMAHA_DEVICE(0x5008, "01V96"),
 	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
 		.vendor_name = "M-Audio",
 		.product_name = "Quattro",
-		.ifnum = 9,
-		.type = QUIRK_MIDI_MIDIMAN,
-		.data = & (const snd_usb_midi_endpoint_info_t) {
-			.out_cables = 0x0001,
-			.in_cables  = 0x0001
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = & (const snd_usb_audio_quirk_t[]) {
+			/*
+			 * Interfaces 0-2 are "Windows-compatible", 16-bit only,
+			 * and share endpoints with the other interfaces.
+			 * Ignore them.  The other interfaces can do 24 bits,
+			 * but captured samples are big-endian (see usbaudio.c).
+			 */
+			{
+				.ifnum = 4,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 5,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 7,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 8,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 9,
+				.type = QUIRK_MIDI_MIDIMAN,
+				.data = & (const snd_usb_midi_endpoint_info_t) {
+					.out_cables = 0x0001,
+					.in_cables  = 0x0001
+				}
+			},
+			{
+				.ifnum = -1
+			}
 		}
 	}
 },
@@ -915,4 +977,19 @@ YAMAHA_DEVICE(0x5008, "01V96"),
 	}
 },
 
+{
+	/*
+	 * Some USB MIDI devices don't have an audio control interface,
+	 * so we have to grab MIDI streaming interfaces here.
+	 */
+	.match_flags = USB_DEVICE_ID_MATCH_INT_CLASS |
+		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+	.bInterfaceClass = USB_CLASS_AUDIO,
+	.bInterfaceSubClass = USB_SUBCLASS_MIDI_STREAMING,
+	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_MIDI_STANDARD_INTERFACE
+	}
+},
+
 #undef USB_DEVICE_VENDOR_SPEC
diff --git a/usr/Makefile b/usr/Makefile
index fe62659ff..965759fc1 100644
--- a/usr/Makefile
+++ b/usr/Makefile
@@ -1,7 +1,7 @@
 
 obj-y := initramfs_data.o
 
-host-progs  := gen_init_cpio
+hostprogs-y  := gen_init_cpio
 
 clean-files := initramfs_data.cpio.gz
 
-- 
2.47.0